summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 12:19:50 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 12:19:50 +0000
commit2e00214b3efbdfeefaa0fe9e8b8fd519de7adc35 (patch)
treed325add32978dbdc1db975a438b3a77d571b1ab8
parentReleasing progress-linux version 1.68.2+dfsg1-1~progress7.99u1. (diff)
downloadrustc-2e00214b3efbdfeefaa0fe9e8b8fd519de7adc35.tar.xz
rustc-2e00214b3efbdfeefaa0fe9e8b8fd519de7adc35.zip
Merging upstream version 1.69.0+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
-rw-r--r--Cargo.lock418
-rw-r--r--README.md2
-rw-r--r--RELEASES.md110
-rw-r--r--compiler/rustc/Cargo.toml7
-rw-r--r--compiler/rustc_abi/src/layout.rs146
-rw-r--r--compiler/rustc_abi/src/lib.rs138
-rw-r--r--compiler/rustc_ast/Cargo.toml3
-rw-r--r--compiler/rustc_ast/src/ast.rs106
-rw-r--r--compiler/rustc_ast/src/attr/mod.rs622
-rw-r--r--compiler/rustc_ast/src/format.rs (renamed from compiler/rustc_builtin_macros/src/format/ast.rs)68
-rw-r--r--compiler/rustc_ast/src/lib.rs3
-rw-r--r--compiler/rustc_ast/src/mut_visit.rs58
-rw-r--r--compiler/rustc_ast/src/tokenstream.rs42
-rw-r--r--compiler/rustc_ast/src/util/comments.rs33
-rw-r--r--compiler/rustc_ast/src/util/parser.rs6
-rw-r--r--compiler/rustc_ast/src/util/unicode.rs2
-rw-r--r--compiler/rustc_ast/src/visit.rs13
-rw-r--r--compiler/rustc_ast_lowering/Cargo.toml4
-rw-r--r--compiler/rustc_ast_lowering/locales/en-US.ftl (renamed from compiler/rustc_error_messages/locales/en-US/ast_lowering.ftl)4
-rw-r--r--compiler/rustc_ast_lowering/src/errors.rs9
-rw-r--r--compiler/rustc_ast_lowering/src/expr.rs125
-rw-r--r--compiler/rustc_ast_lowering/src/format.rs411
-rw-r--r--compiler/rustc_ast_lowering/src/index.rs13
-rw-r--r--compiler/rustc_ast_lowering/src/item.rs90
-rw-r--r--compiler/rustc_ast_lowering/src/lib.rs238
-rw-r--r--compiler/rustc_ast_lowering/src/pat.rs4
-rw-r--r--compiler/rustc_ast_passes/Cargo.toml5
-rw-r--r--compiler/rustc_ast_passes/locales/en-US.ftl236
-rw-r--r--compiler/rustc_ast_passes/src/ast_validation.rs637
-rw-r--r--compiler/rustc_ast_passes/src/errors.rs489
-rw-r--r--compiler/rustc_ast_passes/src/feature_gate.rs111
-rw-r--r--compiler/rustc_ast_passes/src/lib.rs8
-rw-r--r--compiler/rustc_ast_passes/src/show_span.rs8
-rw-r--r--compiler/rustc_ast_pretty/Cargo.toml3
-rw-r--r--compiler/rustc_ast_pretty/src/pprust/state.rs25
-rw-r--r--compiler/rustc_ast_pretty/src/pprust/state/expr.rs104
-rw-r--r--compiler/rustc_ast_pretty/src/pprust/tests.rs7
-rw-r--r--compiler/rustc_attr/locales/en-US.ftl (renamed from compiler/rustc_error_messages/locales/en-US/attr.ftl)0
-rw-r--r--compiler/rustc_attr/src/builtin.rs2
-rw-r--r--compiler/rustc_attr/src/lib.rs5
-rw-r--r--compiler/rustc_attr/src/session_diagnostics.rs19
-rw-r--r--compiler/rustc_baked_icu_data/Cargo.toml11
-rw-r--r--compiler/rustc_baked_icu_data/src/data/any.rs42
-rw-r--r--compiler/rustc_baked_icu_data/src/data/fallback/likelysubtags_v1.rs733
-rw-r--r--compiler/rustc_baked_icu_data/src/data/fallback/likelysubtags_v1/mod.rs6
-rw-r--r--compiler/rustc_baked_icu_data/src/data/fallback/likelysubtags_v1/und.rs.data728
-rw-r--r--compiler/rustc_baked_icu_data/src/data/fallback/parents_v1.rs207
-rw-r--r--compiler/rustc_baked_icu_data/src/data/fallback/parents_v1/mod.rs6
-rw-r--r--compiler/rustc_baked_icu_data/src/data/fallback/parents_v1/und.rs.data216
-rw-r--r--compiler/rustc_baked_icu_data/src/data/fallback/supplement/co_v1.rs41
-rw-r--r--compiler/rustc_baked_icu_data/src/data/fallback/supplement/co_v1/mod.rs6
-rw-r--r--compiler/rustc_baked_icu_data/src/data/fallback/supplement/co_v1/und.rs.data36
-rw-r--r--compiler/rustc_baked_icu_data/src/data/list/and_v1.rs1161
-rw-r--r--compiler/rustc_baked_icu_data/src/data/list/and_v1/en.rs.data74
-rw-r--r--compiler/rustc_baked_icu_data/src/data/list/and_v1/es.rs.data836
-rw-r--r--compiler/rustc_baked_icu_data/src/data/list/and_v1/fr.rs.data74
-rw-r--r--compiler/rustc_baked_icu_data/src/data/list/and_v1/it.rs.data74
-rw-r--r--compiler/rustc_baked_icu_data/src/data/list/and_v1/ja.rs.data74
-rw-r--r--compiler/rustc_baked_icu_data/src/data/list/and_v1/mod.rs22
-rw-r--r--compiler/rustc_baked_icu_data/src/data/list/and_v1/pt.rs.data74
-rw-r--r--compiler/rustc_baked_icu_data/src/data/list/and_v1/ru.rs.data74
-rw-r--r--compiler/rustc_baked_icu_data/src/data/list/and_v1/tr.rs.data74
-rw-r--r--compiler/rustc_baked_icu_data/src/data/list/and_v1/und.rs.data74
-rw-r--r--compiler/rustc_baked_icu_data/src/data/list/and_v1/zh-Hant.rs.data74
-rw-r--r--compiler/rustc_baked_icu_data/src/data/list/and_v1/zh.rs.data74
-rw-r--r--compiler/rustc_baked_icu_data/src/data/mod.rs187
-rw-r--r--compiler/rustc_borrowck/locales/en-US.ftl (renamed from compiler/rustc_error_messages/locales/en-US/borrowck.ftl)13
-rw-r--r--compiler/rustc_borrowck/src/borrowck_errors.rs6
-rw-r--r--compiler/rustc_borrowck/src/constraint_generation.rs4
-rw-r--r--compiler/rustc_borrowck/src/constraints/mod.rs2
-rw-r--r--compiler/rustc_borrowck/src/dataflow.rs1
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs16
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs45
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs33
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/mod.rs52
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/move_errors.rs4
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs72
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/region_errors.rs104
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/region_name.rs40
-rw-r--r--compiler/rustc_borrowck/src/invalidation.rs3
-rw-r--r--compiler/rustc_borrowck/src/lib.rs118
-rw-r--r--compiler/rustc_borrowck/src/nll.rs46
-rw-r--r--compiler/rustc_borrowck/src/region_infer/mod.rs262
-rw-r--r--compiler/rustc_borrowck/src/region_infer/opaque_types.rs67
-rw-r--r--compiler/rustc_borrowck/src/region_infer/values.rs5
-rw-r--r--compiler/rustc_borrowck/src/renumber.rs71
-rw-r--r--compiler/rustc_borrowck/src/session_diagnostics.rs18
-rw-r--r--compiler/rustc_borrowck/src/type_check/canonical.rs11
-rw-r--r--compiler/rustc_borrowck/src/type_check/constraint_conversion.rs20
-rw-r--r--compiler/rustc_borrowck/src/type_check/free_region_relations.rs181
-rw-r--r--compiler/rustc_borrowck/src/type_check/input_output.rs8
-rw-r--r--compiler/rustc_borrowck/src/type_check/liveness/mod.rs8
-rw-r--r--compiler/rustc_borrowck/src/type_check/liveness/trace.rs6
-rw-r--r--compiler/rustc_borrowck/src/type_check/mod.rs100
-rw-r--r--compiler/rustc_borrowck/src/type_check/relate_tys.rs63
-rw-r--r--compiler/rustc_borrowck/src/universal_regions.rs189
-rw-r--r--compiler/rustc_builtin_macros/Cargo.toml2
-rw-r--r--compiler/rustc_builtin_macros/locales/en-US.ftl (renamed from compiler/rustc_error_messages/locales/en-US/builtin_macros.ftl)0
-rw-r--r--compiler/rustc_builtin_macros/src/alloc_error_handler.rs17
-rw-r--r--compiler/rustc_builtin_macros/src/asm.rs2
-rw-r--r--compiler/rustc_builtin_macros/src/assert.rs3
-rw-r--r--compiler/rustc_builtin_macros/src/assert/context.rs21
-rw-r--r--compiler/rustc_builtin_macros/src/deriving/bounds.rs1
-rw-r--r--compiler/rustc_builtin_macros/src/deriving/clone.rs9
-rw-r--r--compiler/rustc_builtin_macros/src/deriving/cmp/eq.rs5
-rw-r--r--compiler/rustc_builtin_macros/src/deriving/cmp/ord.rs5
-rw-r--r--compiler/rustc_builtin_macros/src/deriving/cmp/partial_eq.rs25
-rw-r--r--compiler/rustc_builtin_macros/src/deriving/cmp/partial_ord.rs85
-rw-r--r--compiler/rustc_builtin_macros/src/deriving/debug.rs62
-rw-r--r--compiler/rustc_builtin_macros/src/deriving/decodable.rs17
-rw-r--r--compiler/rustc_builtin_macros/src/deriving/default.rs5
-rw-r--r--compiler/rustc_builtin_macros/src/deriving/encodable.rs33
-rw-r--r--compiler/rustc_builtin_macros/src/deriving/generic/mod.rs221
-rw-r--r--compiler/rustc_builtin_macros/src/deriving/generic/ty.rs11
-rw-r--r--compiler/rustc_builtin_macros/src/deriving/hash.rs7
-rw-r--r--compiler/rustc_builtin_macros/src/deriving/mod.rs11
-rw-r--r--compiler/rustc_builtin_macros/src/env.rs44
-rw-r--r--compiler/rustc_builtin_macros/src/format.rs33
-rw-r--r--compiler/rustc_builtin_macros/src/format/expand.rs353
-rw-r--r--compiler/rustc_builtin_macros/src/global_allocator.rs14
-rw-r--r--compiler/rustc_builtin_macros/src/lib.rs4
-rw-r--r--compiler/rustc_builtin_macros/src/proc_macro_harness.rs14
-rw-r--r--compiler/rustc_builtin_macros/src/standard_library_imports.rs2
-rw-r--r--compiler/rustc_builtin_macros/src/test.rs22
-rw-r--r--compiler/rustc_builtin_macros/src/test_harness.rs13
-rw-r--r--compiler/rustc_codegen_cranelift/.cirrus.yml9
-rw-r--r--compiler/rustc_codegen_cranelift/.github/workflows/main.yml250
-rw-r--r--compiler/rustc_codegen_cranelift/.github/workflows/nightly-cranelift.yml59
-rw-r--r--compiler/rustc_codegen_cranelift/.github/workflows/rustc.yml64
-rw-r--r--compiler/rustc_codegen_cranelift/.vscode/settings.json4
-rw-r--r--compiler/rustc_codegen_cranelift/Cargo.lock107
-rw-r--r--compiler/rustc_codegen_cranelift/Cargo.toml14
-rw-r--r--compiler/rustc_codegen_cranelift/Readme.md14
-rw-r--r--compiler/rustc_codegen_cranelift/build_sysroot/Cargo.lock12
-rw-r--r--compiler/rustc_codegen_cranelift/build_system/abi_cafe.rs23
-rw-r--r--compiler/rustc_codegen_cranelift/build_system/bench.rs103
-rw-r--r--compiler/rustc_codegen_cranelift/build_system/build_backend.rs14
-rw-r--r--compiler/rustc_codegen_cranelift/build_system/build_sysroot.rs308
-rw-r--r--compiler/rustc_codegen_cranelift/build_system/mod.rs109
-rw-r--r--compiler/rustc_codegen_cranelift/build_system/path.rs7
-rw-r--r--compiler/rustc_codegen_cranelift/build_system/prepare.rs129
-rw-r--r--compiler/rustc_codegen_cranelift/build_system/rustc_info.rs27
-rw-r--r--compiler/rustc_codegen_cranelift/build_system/tests.rs573
-rw-r--r--compiler/rustc_codegen_cranelift/build_system/usage.txt35
-rw-r--r--compiler/rustc_codegen_cranelift/build_system/utils.rs116
-rwxr-xr-xcompiler/rustc_codegen_cranelift/clean_all.sh5
-rw-r--r--compiler/rustc_codegen_cranelift/config.txt3
-rw-r--r--compiler/rustc_codegen_cranelift/patches/0001-portable-simd-Disable-unsupported-tests.patch35
-rw-r--r--compiler/rustc_codegen_cranelift/patches/0022-sysroot-Disable-not-compiling-tests.patch5
-rw-r--r--compiler/rustc_codegen_cranelift/rust-toolchain2
-rw-r--r--compiler/rustc_codegen_cranelift/scripts/cargo-clif.rs2
-rw-r--r--compiler/rustc_codegen_cranelift/scripts/rustc-clif.rs2
-rw-r--r--compiler/rustc_codegen_cranelift/scripts/rustdoc-clif.rs2
-rwxr-xr-xcompiler/rustc_codegen_cranelift/scripts/rustup.sh4
-rw-r--r--compiler/rustc_codegen_cranelift/scripts/setup_rust_fork.sh8
-rwxr-xr-xcompiler/rustc_codegen_cranelift/scripts/test_rustc_tests.sh42
-rw-r--r--compiler/rustc_codegen_cranelift/src/abi/comments.rs4
-rw-r--r--compiler/rustc_codegen_cranelift/src/abi/mod.rs43
-rw-r--r--compiler/rustc_codegen_cranelift/src/allocator.rs75
-rw-r--r--compiler/rustc_codegen_cranelift/src/base.rs153
-rw-r--r--compiler/rustc_codegen_cranelift/src/codegen_i128.rs4
-rw-r--r--compiler/rustc_codegen_cranelift/src/common.rs52
-rw-r--r--compiler/rustc_codegen_cranelift/src/compiler_builtins.rs38
-rw-r--r--compiler/rustc_codegen_cranelift/src/config.rs8
-rw-r--r--compiler/rustc_codegen_cranelift/src/constant.rs1
-rw-r--r--compiler/rustc_codegen_cranelift/src/cranelift_native.rs248
-rw-r--r--compiler/rustc_codegen_cranelift/src/debuginfo/mod.rs14
-rw-r--r--compiler/rustc_codegen_cranelift/src/driver/aot.rs166
-rw-r--r--compiler/rustc_codegen_cranelift/src/driver/jit.rs46
-rw-r--r--compiler/rustc_codegen_cranelift/src/driver/mod.rs15
-rw-r--r--compiler/rustc_codegen_cranelift/src/global_asm.rs43
-rw-r--r--compiler/rustc_codegen_cranelift/src/inline_asm.rs189
-rw-r--r--compiler/rustc_codegen_cranelift/src/intrinsics/llvm_x86.rs6
-rw-r--r--compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs122
-rw-r--r--compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs126
-rw-r--r--compiler/rustc_codegen_cranelift/src/lib.rs15
-rw-r--r--compiler/rustc_codegen_cranelift/src/main_shim.rs21
-rw-r--r--compiler/rustc_codegen_cranelift/src/num.rs2
-rw-r--r--compiler/rustc_codegen_cranelift/src/optimize/peephole.rs4
-rw-r--r--compiler/rustc_codegen_cranelift/src/unsize.rs2
-rw-r--r--compiler/rustc_codegen_cranelift/src/value_and_place.rs19
-rwxr-xr-xcompiler/rustc_codegen_cranelift/y.rs2
-rw-r--r--compiler/rustc_codegen_gcc/locales/en-US.ftl (renamed from compiler/rustc_error_messages/locales/en-US/codegen_gcc.ftl)2
-rw-r--r--compiler/rustc_codegen_gcc/src/builder.rs2
-rw-r--r--compiler/rustc_codegen_gcc/src/callee.rs2
-rw-r--r--compiler/rustc_codegen_gcc/src/common.rs2
-rw-r--r--compiler/rustc_codegen_gcc/src/consts.rs7
-rw-r--r--compiler/rustc_codegen_gcc/src/context.rs2
-rw-r--r--compiler/rustc_codegen_gcc/src/intrinsic/simd.rs407
-rw-r--r--compiler/rustc_codegen_gcc/src/lib.rs10
-rw-r--r--compiler/rustc_codegen_gcc/src/mono_item.rs2
-rw-r--r--compiler/rustc_codegen_gcc/src/type_of.rs6
-rw-r--r--compiler/rustc_codegen_llvm/Cargo.toml3
-rw-r--r--compiler/rustc_codegen_llvm/locales/en-US.ftl89
-rw-r--r--compiler/rustc_codegen_llvm/src/asm.rs13
-rw-r--r--compiler/rustc_codegen_llvm/src/attributes.rs42
-rw-r--r--compiler/rustc_codegen_llvm/src/back/archive.rs8
-rw-r--r--compiler/rustc_codegen_llvm/src/back/lto.rs65
-rw-r--r--compiler/rustc_codegen_llvm/src/back/write.rs104
-rw-r--r--compiler/rustc_codegen_llvm/src/builder.rs2
-rw-r--r--compiler/rustc_codegen_llvm/src/callee.rs2
-rw-r--r--compiler/rustc_codegen_llvm/src/common.rs14
-rw-r--r--compiler/rustc_codegen_llvm/src/consts.rs28
-rw-r--r--compiler/rustc_codegen_llvm/src/context.rs42
-rw-r--r--compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs50
-rw-r--r--compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs4
-rw-r--r--compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs7
-rw-r--r--compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs3
-rw-r--r--compiler/rustc_codegen_llvm/src/debuginfo/mod.rs4
-rw-r--r--compiler/rustc_codegen_llvm/src/errors.rs134
-rw-r--r--compiler/rustc_codegen_llvm/src/intrinsic.rs19
-rw-r--r--compiler/rustc_codegen_llvm/src/lib.rs20
-rw-r--r--compiler/rustc_codegen_llvm/src/llvm/ffi.rs6
-rw-r--r--compiler/rustc_codegen_llvm/src/llvm_util.rs28
-rw-r--r--compiler/rustc_codegen_llvm/src/mono_item.rs2
-rw-r--r--compiler/rustc_codegen_llvm/src/type_of.rs33
-rw-r--r--compiler/rustc_codegen_ssa/Cargo.toml1
-rw-r--r--compiler/rustc_codegen_ssa/locales/en-US.ftl (renamed from compiler/rustc_error_messages/locales/en-US/codegen_ssa.ftl)6
-rw-r--r--compiler/rustc_codegen_ssa/src/back/archive.rs2
-rw-r--r--compiler/rustc_codegen_ssa/src/back/link.rs146
-rw-r--r--compiler/rustc_codegen_ssa/src/back/linker.rs16
-rw-r--r--compiler/rustc_codegen_ssa/src/back/metadata.rs1
-rw-r--r--compiler/rustc_codegen_ssa/src/back/symbol_export.rs69
-rw-r--r--compiler/rustc_codegen_ssa/src/back/write.rs8
-rw-r--r--compiler/rustc_codegen_ssa/src/base.rs32
-rw-r--r--compiler/rustc_codegen_ssa/src/codegen_attrs.rs147
-rw-r--r--compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs17
-rw-r--r--compiler/rustc_codegen_ssa/src/errors.rs5
-rw-r--r--compiler/rustc_codegen_ssa/src/lib.rs7
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/analyze.rs33
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/block.rs289
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/debuginfo.rs7
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/intrinsic.rs25
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/mod.rs10
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/place.rs17
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/rvalue.rs41
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/statement.rs1
-rw-r--r--compiler/rustc_codegen_ssa/src/target_features.rs17
-rw-r--r--compiler/rustc_codegen_ssa/src/traits/backend.rs4
-rw-r--r--compiler/rustc_codegen_ssa/src/traits/write.rs1
-rw-r--r--compiler/rustc_const_eval/Cargo.toml1
-rw-r--r--compiler/rustc_const_eval/locales/en-US.ftl (renamed from compiler/rustc_error_messages/locales/en-US/const_eval.ftl)0
-rw-r--r--compiler/rustc_const_eval/src/const_eval/eval_queries.rs6
-rw-r--r--compiler/rustc_const_eval/src/const_eval/fn_queries.rs5
-rw-r--r--compiler/rustc_const_eval/src/const_eval/machine.rs23
-rw-r--r--compiler/rustc_const_eval/src/const_eval/mod.rs4
-rw-r--r--compiler/rustc_const_eval/src/const_eval/valtrees.rs13
-rw-r--r--compiler/rustc_const_eval/src/errors.rs18
-rw-r--r--compiler/rustc_const_eval/src/interpret/cast.rs22
-rw-r--r--compiler/rustc_const_eval/src/interpret/discriminant.rs238
-rw-r--r--compiler/rustc_const_eval/src/interpret/eval_context.rs10
-rw-r--r--compiler/rustc_const_eval/src/interpret/intern.rs26
-rw-r--r--compiler/rustc_const_eval/src/interpret/intrinsics.rs118
-rw-r--r--compiler/rustc_const_eval/src/interpret/intrinsics/caller_location.rs11
-rw-r--r--compiler/rustc_const_eval/src/interpret/machine.rs40
-rw-r--r--compiler/rustc_const_eval/src/interpret/memory.rs70
-rw-r--r--compiler/rustc_const_eval/src/interpret/mod.rs1
-rw-r--r--compiler/rustc_const_eval/src/interpret/operand.rs198
-rw-r--r--compiler/rustc_const_eval/src/interpret/operator.rs10
-rw-r--r--compiler/rustc_const_eval/src/interpret/place.rs191
-rw-r--r--compiler/rustc_const_eval/src/interpret/projection.rs6
-rw-r--r--compiler/rustc_const_eval/src/interpret/step.rs20
-rw-r--r--compiler/rustc_const_eval/src/interpret/terminator.rs118
-rw-r--r--compiler/rustc_const_eval/src/interpret/util.rs8
-rw-r--r--compiler/rustc_const_eval/src/interpret/validity.rs32
-rw-r--r--compiler/rustc_const_eval/src/interpret/visitor.rs16
-rw-r--r--compiler/rustc_const_eval/src/lib.rs11
-rw-r--r--compiler/rustc_const_eval/src/transform/check_consts/check.rs14
-rw-r--r--compiler/rustc_const_eval/src/transform/check_consts/mod.rs4
-rw-r--r--compiler/rustc_const_eval/src/transform/check_consts/ops.rs73
-rw-r--r--compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs4
-rw-r--r--compiler/rustc_const_eval/src/transform/promote_consts.rs42
-rw-r--r--compiler/rustc_const_eval/src/transform/validate.rs65
-rw-r--r--compiler/rustc_const_eval/src/util/aggregate.rs77
-rw-r--r--compiler/rustc_const_eval/src/util/call_kind.rs3
-rw-r--r--compiler/rustc_const_eval/src/util/check_validity_requirement.rs (renamed from compiler/rustc_const_eval/src/util/might_permit_raw_init.rs)65
-rw-r--r--compiler/rustc_const_eval/src/util/mod.rs6
-rw-r--r--compiler/rustc_const_eval/src/util/type_name.rs1
-rw-r--r--compiler/rustc_data_structures/Cargo.toml5
-rw-r--r--compiler/rustc_data_structures/src/functor.rs51
-rw-r--r--compiler/rustc_data_structures/src/graph/dominators/mod.rs51
-rw-r--r--compiler/rustc_data_structures/src/graph/scc/mod.rs18
-rw-r--r--compiler/rustc_data_structures/src/lib.rs2
-rw-r--r--compiler/rustc_data_structures/src/obligation_forest/mod.rs10
-rw-r--r--compiler/rustc_data_structures/src/profiling.rs50
-rw-r--r--compiler/rustc_data_structures/src/sorted_map/index_map.rs5
-rw-r--r--compiler/rustc_data_structures/src/sorted_map/tests.rs4
-rw-r--r--compiler/rustc_data_structures/src/stable_hasher.rs8
-rw-r--r--compiler/rustc_data_structures/src/stable_hasher/tests.rs2
-rw-r--r--compiler/rustc_data_structures/src/sync.rs8
-rw-r--r--compiler/rustc_data_structures/src/sync/vec.rs41
-rw-r--r--compiler/rustc_driver/Cargo.toml37
-rw-r--r--compiler/rustc_driver/src/lib.rs1360
-rw-r--r--compiler/rustc_driver/src/session_diagnostics.rs40
-rw-r--r--compiler/rustc_driver_impl/Cargo.toml64
-rw-r--r--compiler/rustc_driver_impl/README.md (renamed from compiler/rustc_driver/README.md)0
-rw-r--r--compiler/rustc_driver_impl/locales/en-US.ftl19
-rw-r--r--compiler/rustc_driver_impl/src/args.rs (renamed from compiler/rustc_driver/src/args.rs)0
-rw-r--r--compiler/rustc_driver_impl/src/lib.rs1364
-rw-r--r--compiler/rustc_driver_impl/src/pretty.rs (renamed from compiler/rustc_driver/src/pretty.rs)21
-rw-r--r--compiler/rustc_driver_impl/src/session_diagnostics.rs67
-rw-r--r--compiler/rustc_error_codes/src/error_codes.rs20
-rw-r--r--compiler/rustc_error_codes/src/error_codes/E0464.md15
-rw-r--r--compiler/rustc_error_codes/src/error_codes/E0476.md21
-rw-r--r--compiler/rustc_error_codes/src/error_codes/E0523.md25
-rw-r--r--compiler/rustc_error_codes/src/error_codes/E0587.md2
-rw-r--r--compiler/rustc_error_codes/src/error_codes/E0789.md30
-rw-r--r--compiler/rustc_error_codes/src/error_codes/E0793.md64
-rw-r--r--compiler/rustc_error_codes/src/lib.rs7
-rw-r--r--compiler/rustc_error_messages/Cargo.toml7
-rw-r--r--compiler/rustc_error_messages/locales/en-US.ftl1
-rw-r--r--compiler/rustc_error_messages/locales/en-US/ast_passes.ftl92
-rw-r--r--compiler/rustc_error_messages/locales/en-US/codegen_llvm.ftl46
-rw-r--r--compiler/rustc_error_messages/locales/en-US/driver.ftl13
-rw-r--r--compiler/rustc_error_messages/locales/en-US/errors.ftl13
-rw-r--r--compiler/rustc_error_messages/locales/en-US/save_analysis.ftl1
-rw-r--r--compiler/rustc_error_messages/src/lib.rs66
-rw-r--r--compiler/rustc_errors/locales/en-US.ftl19
-rw-r--r--compiler/rustc_errors/src/diagnostic.rs86
-rw-r--r--compiler/rustc_errors/src/diagnostic_builder.rs54
-rw-r--r--compiler/rustc_errors/src/diagnostic_impls.rs38
-rw-r--r--compiler/rustc_errors/src/emitter.rs191
-rw-r--r--compiler/rustc_errors/src/json.rs11
-rw-r--r--compiler/rustc_errors/src/json/tests.rs5
-rw-r--r--compiler/rustc_errors/src/lib.rs112
-rw-r--r--compiler/rustc_errors/src/registry.rs12
-rw-r--r--compiler/rustc_errors/src/styled_buffer.rs2
-rw-r--r--compiler/rustc_errors/src/translation.rs30
-rw-r--r--compiler/rustc_expand/Cargo.toml2
-rw-r--r--compiler/rustc_expand/locales/en-US.ftl (renamed from compiler/rustc_error_messages/locales/en-US/expand.ftl)9
-rw-r--r--compiler/rustc_expand/src/base.rs62
-rw-r--r--compiler/rustc_expand/src/build.rs74
-rw-r--r--compiler/rustc_expand/src/config.rs13
-rw-r--r--compiler/rustc_expand/src/errors.rs43
-rw-r--r--compiler/rustc_expand/src/lib.rs5
-rw-r--r--compiler/rustc_expand/src/mbe/macro_parser.rs2
-rw-r--r--compiler/rustc_expand/src/mbe/macro_rules.rs30
-rw-r--r--compiler/rustc_expand/src/mbe/metavar_expr.rs12
-rw-r--r--compiler/rustc_expand/src/mbe/transcribe.rs2
-rw-r--r--compiler/rustc_expand/src/module.rs4
-rw-r--r--compiler/rustc_expand/src/parse/tests.rs5
-rw-r--r--compiler/rustc_expand/src/proc_macro.rs14
-rw-r--r--compiler/rustc_expand/src/tests.rs20
-rw-r--r--compiler/rustc_feature/src/accepted.rs2
-rw-r--r--compiler/rustc_feature/src/active.rs9
-rw-r--r--compiler/rustc_feature/src/builtin_attrs.rs15
-rw-r--r--compiler/rustc_feature/src/lib.rs3
-rw-r--r--compiler/rustc_feature/src/removed.rs2
-rw-r--r--compiler/rustc_hir/src/def.rs37
-rw-r--r--compiler/rustc_hir/src/definitions.rs8
-rw-r--r--compiler/rustc_hir/src/hir.rs424
-rw-r--r--compiler/rustc_hir/src/intravisit.rs52
-rw-r--r--compiler/rustc_hir/src/lang_items.rs12
-rw-r--r--compiler/rustc_hir/src/stable_hash_impls.rs9
-rw-r--r--compiler/rustc_hir/src/target.rs2
-rw-r--r--compiler/rustc_hir_analysis/Cargo.toml6
-rw-r--r--compiler/rustc_hir_analysis/locales/en-US.ftl (renamed from compiler/rustc_error_messages/locales/en-US/hir_analysis.ftl)83
-rw-r--r--compiler/rustc_hir_analysis/src/astconv/errors.rs229
-rw-r--r--compiler/rustc_hir_analysis/src/astconv/generics.rs25
-rw-r--r--compiler/rustc_hir_analysis/src/astconv/mod.rs558
-rw-r--r--compiler/rustc_hir_analysis/src/autoderef.rs10
-rw-r--r--compiler/rustc_hir_analysis/src/check/check.rs329
-rw-r--r--compiler/rustc_hir_analysis/src/check/compare_impl_item.rs332
-rw-r--r--compiler/rustc_hir_analysis/src/check/dropck.rs6
-rw-r--r--compiler/rustc_hir_analysis/src/check/intrinsic.rs61
-rw-r--r--compiler/rustc_hir_analysis/src/check/intrinsicck.rs13
-rw-r--r--compiler/rustc_hir_analysis/src/check/mod.rs35
-rw-r--r--compiler/rustc_hir_analysis/src/check/wfcheck.rs250
-rw-r--r--compiler/rustc_hir_analysis/src/check_unused.rs135
-rw-r--r--compiler/rustc_hir_analysis/src/coherence/builtin.rs31
-rw-r--r--compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs94
-rw-r--r--compiler/rustc_hir_analysis/src/coherence/inherent_impls_overlap.rs14
-rw-r--r--compiler/rustc_hir_analysis/src/coherence/mod.rs4
-rw-r--r--compiler/rustc_hir_analysis/src/coherence/orphan.rs271
-rw-r--r--compiler/rustc_hir_analysis/src/coherence/unsafety.rs4
-rw-r--r--compiler/rustc_hir_analysis/src/collect.rs91
-rw-r--r--compiler/rustc_hir_analysis/src/collect/generics_of.rs16
-rw-r--r--compiler/rustc_hir_analysis/src/collect/item_bounds.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/collect/predicates_of.rs65
-rw-r--r--compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs (renamed from compiler/rustc_hir_analysis/src/collect/lifetimes.rs)719
-rw-r--r--compiler/rustc_hir_analysis/src/collect/type_of.rs115
-rw-r--r--compiler/rustc_hir_analysis/src/constrained_generic_params.rs4
-rw-r--r--compiler/rustc_hir_analysis/src/errors.rs159
-rw-r--r--compiler/rustc_hir_analysis/src/hir_wf_check.rs13
-rw-r--r--compiler/rustc_hir_analysis/src/impl_wf_check.rs8
-rw-r--r--compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs29
-rw-r--r--compiler/rustc_hir_analysis/src/lib.rs141
-rw-r--r--compiler/rustc_hir_analysis/src/outlives/explicit.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/outlives/implicit_infer.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/outlives/utils.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/structured_errors/missing_cast_for_variadic_arg.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/structured_errors/sized_unsized_cast.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/structured_errors/wrong_number_of_generic_args.rs8
-rw-r--r--compiler/rustc_hir_analysis/src/variance/constraints.rs32
-rw-r--r--compiler/rustc_hir_analysis/src/variance/mod.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/variance/solve.rs2
-rw-r--r--compiler/rustc_hir_pretty/src/lib.rs10
-rw-r--r--compiler/rustc_hir_typeck/locales/en-US.ftl (renamed from compiler/rustc_error_messages/locales/en-US/hir_typeck.ftl)50
-rw-r--r--compiler/rustc_hir_typeck/src/_match.rs9
-rw-r--r--compiler/rustc_hir_typeck/src/callee.rs28
-rw-r--r--compiler/rustc_hir_typeck/src/cast.rs3
-rw-r--r--compiler/rustc_hir_typeck/src/check.rs29
-rw-r--r--compiler/rustc_hir_typeck/src/closure.rs92
-rw-r--r--compiler/rustc_hir_typeck/src/coercion.rs34
-rw-r--r--compiler/rustc_hir_typeck/src/demand.rs333
-rw-r--r--compiler/rustc_hir_typeck/src/errors.rs47
-rw-r--r--compiler/rustc_hir_typeck/src/expr.rs167
-rw-r--r--compiler/rustc_hir_typeck/src/expr_use_visitor.rs2
-rw-r--r--compiler/rustc_hir_typeck/src/fallback.rs18
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs167
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs864
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs608
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs17
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs127
-rw-r--r--compiler/rustc_hir_typeck/src/gather_locals.rs3
-rw-r--r--compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/cfg_build.rs6
-rw-r--r--compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/record_consumed_borrow.rs2
-rw-r--r--compiler/rustc_hir_typeck/src/generator_interior/mod.rs23
-rw-r--r--compiler/rustc_hir_typeck/src/inherited.rs54
-rw-r--r--compiler/rustc_hir_typeck/src/intrinsicck.rs5
-rw-r--r--compiler/rustc_hir_typeck/src/lib.rs38
-rw-r--r--compiler/rustc_hir_typeck/src/mem_categorization.rs13
-rw-r--r--compiler/rustc_hir_typeck/src/method/confirm.rs28
-rw-r--r--compiler/rustc_hir_typeck/src/method/mod.rs17
-rw-r--r--compiler/rustc_hir_typeck/src/method/probe.rs282
-rw-r--r--compiler/rustc_hir_typeck/src/method/suggest.rs126
-rw-r--r--compiler/rustc_hir_typeck/src/op.rs38
-rw-r--r--compiler/rustc_hir_typeck/src/pat.rs281
-rw-r--r--compiler/rustc_hir_typeck/src/place_op.rs12
-rw-r--r--compiler/rustc_hir_typeck/src/upvar.rs26
-rw-r--r--compiler/rustc_hir_typeck/src/writeback.rs28
-rw-r--r--compiler/rustc_incremental/Cargo.toml17
-rw-r--r--compiler/rustc_incremental/locales/en-US.ftl118
-rw-r--r--compiler/rustc_incremental/src/assert_dep_graph.rs56
-rw-r--r--compiler/rustc_incremental/src/assert_module_sources.rs55
-rw-r--r--compiler/rustc_incremental/src/errors.rs364
-rw-r--r--compiler/rustc_incremental/src/lib.rs9
-rw-r--r--compiler/rustc_incremental/src/persist/dirty_clean.rs71
-rw-r--r--compiler/rustc_incremental/src/persist/file_format.rs21
-rw-r--r--compiler/rustc_incremental/src/persist/fs.rs111
-rw-r--r--compiler/rustc_incremental/src/persist/load.rs54
-rw-r--r--compiler/rustc_incremental/src/persist/save.rs24
-rw-r--r--compiler/rustc_incremental/src/persist/work_product.rs18
-rw-r--r--compiler/rustc_index/src/bit_set.rs2
-rw-r--r--compiler/rustc_infer/Cargo.toml1
-rw-r--r--compiler/rustc_infer/locales/en-US.ftl (renamed from compiler/rustc_error_messages/locales/en-US/infer.ftl)78
-rw-r--r--compiler/rustc_infer/src/errors/mod.rs260
-rw-r--r--compiler/rustc_infer/src/errors/note_and_explain.rs51
-rw-r--r--compiler/rustc_infer/src/infer/at.rs30
-rw-r--r--compiler/rustc_infer/src/infer/canonical/canonicalizer.rs58
-rw-r--r--compiler/rustc_infer/src/infer/canonical/mod.rs29
-rw-r--r--compiler/rustc_infer/src/infer/canonical/query_response.rs127
-rw-r--r--compiler/rustc_infer/src/infer/canonical/substitute.rs21
-rw-r--r--compiler/rustc_infer/src/infer/combine.rs233
-rw-r--r--compiler/rustc_infer/src/infer/equate.rs18
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/mod.rs304
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs29
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/nice_region_error/find_anon_type.rs32
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/nice_region_error/mismatched_static_lifetime.rs2
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs12
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_relation.rs66
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs7
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/nice_region_error/trait_impl_difference.rs2
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/nice_region_error/util.rs16
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/note.rs201
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs700
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/suggest.rs287
-rw-r--r--compiler/rustc_infer/src/infer/freshen.rs150
-rw-r--r--compiler/rustc_infer/src/infer/fudge.rs6
-rw-r--r--compiler/rustc_infer/src/infer/glb.rs24
-rw-r--r--compiler/rustc_infer/src/infer/higher_ranked/mod.rs20
-rw-r--r--compiler/rustc_infer/src/infer/lattice.rs11
-rw-r--r--compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs22
-rw-r--r--compiler/rustc_infer/src/infer/lub.rs30
-rw-r--r--compiler/rustc_infer/src/infer/mod.rs199
-rw-r--r--compiler/rustc_infer/src/infer/nll_relate/mod.rs111
-rw-r--r--compiler/rustc_infer/src/infer/opaque_types.rs59
-rw-r--r--compiler/rustc_infer/src/infer/outlives/components.rs4
-rw-r--r--compiler/rustc_infer/src/infer/outlives/mod.rs2
-rw-r--r--compiler/rustc_infer/src/infer/outlives/obligations.rs2
-rw-r--r--compiler/rustc_infer/src/infer/outlives/test_type_match.rs5
-rw-r--r--compiler/rustc_infer/src/infer/outlives/verify.rs1
-rw-r--r--compiler/rustc_infer/src/infer/projection.rs34
-rw-r--r--compiler/rustc_infer/src/infer/region_constraints/leak_check.rs10
-rw-r--r--compiler/rustc_infer/src/infer/region_constraints/mod.rs16
-rw-r--r--compiler/rustc_infer/src/infer/resolve.rs35
-rw-r--r--compiler/rustc_infer/src/infer/sub.rs24
-rw-r--r--compiler/rustc_infer/src/lib.rs6
-rw-r--r--compiler/rustc_infer/src/traits/engine.rs24
-rw-r--r--compiler/rustc_infer/src/traits/mod.rs3
-rw-r--r--compiler/rustc_infer/src/traits/structural_impls.rs17
-rw-r--r--compiler/rustc_infer/src/traits/util.rs87
-rw-r--r--compiler/rustc_interface/Cargo.toml5
-rw-r--r--compiler/rustc_interface/locales/en-US.ftl (renamed from compiler/rustc_error_messages/locales/en-US/interface.ftl)16
-rw-r--r--compiler/rustc_interface/src/callbacks.rs2
-rw-r--r--compiler/rustc_interface/src/errors.rs25
-rw-r--r--compiler/rustc_interface/src/interface.rs3
-rw-r--r--compiler/rustc_interface/src/lib.rs5
-rw-r--r--compiler/rustc_interface/src/passes.rs308
-rw-r--r--compiler/rustc_interface/src/queries.rs87
-rw-r--r--compiler/rustc_interface/src/tests.rs9
-rw-r--r--compiler/rustc_interface/src/util.rs34
-rw-r--r--compiler/rustc_lexer/src/lib.rs12
-rw-r--r--compiler/rustc_lint/locales/en-US.ftl (renamed from compiler/rustc_error_messages/locales/en-US/lint.ftl)10
-rw-r--r--compiler/rustc_lint/src/array_into_iter.rs6
-rw-r--r--compiler/rustc_lint/src/builtin.rs187
-rw-r--r--compiler/rustc_lint/src/context.rs42
-rw-r--r--compiler/rustc_lint/src/deref_into_dyn_supertrait.rs2
-rw-r--r--compiler/rustc_lint/src/enum_intrinsics_non_enums.rs2
-rw-r--r--compiler/rustc_lint/src/errors.rs6
-rw-r--r--compiler/rustc_lint/src/for_loops_over_fallibles.rs10
-rw-r--r--compiler/rustc_lint/src/internal.rs2
-rw-r--r--compiler/rustc_lint/src/late.rs15
-rw-r--r--compiler/rustc_lint/src/levels.rs17
-rw-r--r--compiler/rustc_lint/src/lib.rs24
-rw-r--r--compiler/rustc_lint/src/lints.rs172
-rw-r--r--compiler/rustc_lint/src/map_unit_fn.rs120
-rw-r--r--compiler/rustc_lint/src/multiple_supertrait_upcastable.rs60
-rw-r--r--compiler/rustc_lint/src/non_fmt_panic.rs20
-rw-r--r--compiler/rustc_lint/src/nonstandard_style.rs18
-rw-r--r--compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs2
-rw-r--r--compiler/rustc_lint/src/pass_by_value.rs2
-rw-r--r--compiler/rustc_lint/src/passes.rs3
-rw-r--r--compiler/rustc_lint/src/types.rs47
-rw-r--r--compiler/rustc_lint/src/unused.rs28
-rw-r--r--compiler/rustc_lint_defs/src/builtin.rs122
-rw-r--r--compiler/rustc_lint_defs/src/lib.rs8
-rw-r--r--compiler/rustc_llvm/llvm-wrapper/LLVMWrapper.h8
-rw-r--r--compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp128
-rw-r--r--compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp27
-rw-r--r--compiler/rustc_log/src/lib.rs33
-rw-r--r--compiler/rustc_macros/src/diagnostics/diagnostic.rs4
-rw-r--r--compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs27
-rw-r--r--compiler/rustc_macros/src/diagnostics/fluent.rs433
-rw-r--r--compiler/rustc_macros/src/diagnostics/subdiagnostic.rs25
-rw-r--r--compiler/rustc_macros/src/diagnostics/utils.rs67
-rw-r--r--compiler/rustc_macros/src/lib.rs31
-rw-r--r--compiler/rustc_macros/src/serialize.rs47
-rw-r--r--compiler/rustc_macros/src/type_foldable.rs33
-rw-r--r--compiler/rustc_macros/src/type_visitable.rs23
-rw-r--r--compiler/rustc_metadata/Cargo.toml1
-rw-r--r--compiler/rustc_metadata/locales/en-US.ftl (renamed from compiler/rustc_error_messages/locales/en-US/metadata.ftl)0
-rw-r--r--compiler/rustc_metadata/src/creader.rs138
-rw-r--r--compiler/rustc_metadata/src/dependency_format.rs61
-rw-r--r--compiler/rustc_metadata/src/errors.rs31
-rw-r--r--compiler/rustc_metadata/src/lib.rs4
-rw-r--r--compiler/rustc_metadata/src/locator.rs52
-rw-r--r--compiler/rustc_metadata/src/native_libs.rs142
-rw-r--r--compiler/rustc_metadata/src/rmeta/decoder.rs92
-rw-r--r--compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs78
-rw-r--r--compiler/rustc_metadata/src/rmeta/encoder.rs459
-rw-r--r--compiler/rustc_metadata/src/rmeta/mod.rs78
-rw-r--r--compiler/rustc_metadata/src/rmeta/table.rs231
-rw-r--r--compiler/rustc_middle/Cargo.toml2
-rw-r--r--compiler/rustc_middle/locales/en-US.ftl (renamed from compiler/rustc_error_messages/locales/en-US/middle.ftl)0
-rw-r--r--compiler/rustc_middle/src/arena.rs9
-rw-r--r--compiler/rustc_middle/src/dep_graph/mod.rs6
-rw-r--r--compiler/rustc_middle/src/hir/map/mod.rs102
-rw-r--r--compiler/rustc_middle/src/hir/mod.rs23
-rw-r--r--compiler/rustc_middle/src/infer/canonical.rs162
-rw-r--r--compiler/rustc_middle/src/infer/mod.rs3
-rw-r--r--compiler/rustc_middle/src/lib.rs10
-rw-r--r--compiler/rustc_middle/src/macros.rs154
-rw-r--r--compiler/rustc_middle/src/middle/codegen_fn_attrs.rs3
-rw-r--r--compiler/rustc_middle/src/middle/mod.rs2
-rw-r--r--compiler/rustc_middle/src/middle/privacy.rs25
-rw-r--r--compiler/rustc_middle/src/middle/resolve_bound_vars.rs (renamed from compiler/rustc_middle/src/middle/resolve_lifetime.rs)16
-rw-r--r--compiler/rustc_middle/src/middle/stability.rs4
-rw-r--r--compiler/rustc_middle/src/mir/basic_blocks.rs99
-rw-r--r--compiler/rustc_middle/src/mir/coverage.rs5
-rw-r--r--compiler/rustc_middle/src/mir/graph_cyclic_cache.rs63
-rw-r--r--compiler/rustc_middle/src/mir/graphviz.rs2
-rw-r--r--compiler/rustc_middle/src/mir/interpret/allocation.rs82
-rw-r--r--compiler/rustc_middle/src/mir/interpret/error.rs9
-rw-r--r--compiler/rustc_middle/src/mir/interpret/mod.rs17
-rw-r--r--compiler/rustc_middle/src/mir/interpret/pointer.rs22
-rw-r--r--compiler/rustc_middle/src/mir/interpret/queries.rs2
-rw-r--r--compiler/rustc_middle/src/mir/interpret/value.rs18
-rw-r--r--compiler/rustc_middle/src/mir/mod.rs100
-rw-r--r--compiler/rustc_middle/src/mir/mono.rs9
-rw-r--r--compiler/rustc_middle/src/mir/predecessors.rs78
-rw-r--r--compiler/rustc_middle/src/mir/pretty.rs24
-rw-r--r--compiler/rustc_middle/src/mir/query.rs73
-rw-r--r--compiler/rustc_middle/src/mir/spanview.rs5
-rw-r--r--compiler/rustc_middle/src/mir/switch_sources.rs78
-rw-r--r--compiler/rustc_middle/src/mir/syntax.rs22
-rw-r--r--compiler/rustc_middle/src/mir/tcx.rs18
-rw-r--r--compiler/rustc_middle/src/mir/traversal.rs50
-rw-r--r--compiler/rustc_middle/src/mir/type_foldable.rs29
-rw-r--r--compiler/rustc_middle/src/mir/type_visitable.rs9
-rw-r--r--compiler/rustc_middle/src/mir/visit.rs11
-rw-r--r--compiler/rustc_middle/src/query/keys.rs28
-rw-r--r--compiler/rustc_middle/src/query/mod.rs259
-rw-r--r--compiler/rustc_middle/src/thir.rs32
-rw-r--r--compiler/rustc_middle/src/traits/mod.rs48
-rw-r--r--compiler/rustc_middle/src/traits/query.rs4
-rw-r--r--compiler/rustc_middle/src/traits/solve.rs66
-rw-r--r--compiler/rustc_middle/src/traits/specialization_graph.rs12
-rw-r--r--compiler/rustc_middle/src/ty/_match.rs4
-rw-r--r--compiler/rustc_middle/src/ty/abstract_const.rs8
-rw-r--r--compiler/rustc_middle/src/ty/adt.rs5
-rw-r--r--compiler/rustc_middle/src/ty/assoc.rs16
-rw-r--r--compiler/rustc_middle/src/ty/closure.rs60
-rw-r--r--compiler/rustc_middle/src/ty/codec.rs65
-rw-r--r--compiler/rustc_middle/src/ty/consts.rs55
-rw-r--r--compiler/rustc_middle/src/ty/consts/int.rs2
-rw-r--r--compiler/rustc_middle/src/ty/consts/kind.rs16
-rw-r--r--compiler/rustc_middle/src/ty/consts/valtree.rs4
-rw-r--r--compiler/rustc_middle/src/ty/context.rs934
-rw-r--r--compiler/rustc_middle/src/ty/context/tls.rs186
-rw-r--r--compiler/rustc_middle/src/ty/diagnostics.rs124
-rw-r--r--compiler/rustc_middle/src/ty/erase_regions.rs11
-rw-r--r--compiler/rustc_middle/src/ty/error.rs864
-rw-r--r--compiler/rustc_middle/src/ty/fast_reject.rs12
-rw-r--r--compiler/rustc_middle/src/ty/flags.rs30
-rw-r--r--compiler/rustc_middle/src/ty/fold.rs281
-rw-r--r--compiler/rustc_middle/src/ty/generics.rs8
-rw-r--r--compiler/rustc_middle/src/ty/impls_ty.rs2
-rw-r--r--compiler/rustc_middle/src/ty/inhabitedness/inhabited_predicate.rs4
-rw-r--r--compiler/rustc_middle/src/ty/inhabitedness/mod.rs6
-rw-r--r--compiler/rustc_middle/src/ty/instance.rs24
-rw-r--r--compiler/rustc_middle/src/ty/layout.rs119
-rw-r--r--compiler/rustc_middle/src/ty/mod.rs183
-rw-r--r--compiler/rustc_middle/src/ty/normalize_erasing_regions.rs31
-rw-r--r--compiler/rustc_middle/src/ty/opaque_types.rs112
-rw-r--r--compiler/rustc_middle/src/ty/parameterized.rs5
-rw-r--r--compiler/rustc_middle/src/ty/print/mod.rs3
-rw-r--r--compiler/rustc_middle/src/ty/print/pretty.rs147
-rw-r--r--compiler/rustc_middle/src/ty/query.rs182
-rw-r--r--compiler/rustc_middle/src/ty/relate.rs102
-rw-r--r--compiler/rustc_middle/src/ty/structural_impls.rs446
-rw-r--r--compiler/rustc_middle/src/ty/sty.rs128
-rw-r--r--compiler/rustc_middle/src/ty/subst.rs100
-rw-r--r--compiler/rustc_middle/src/ty/trait_def.rs35
-rw-r--r--compiler/rustc_middle/src/ty/typeck_results.rs14
-rw-r--r--compiler/rustc_middle/src/ty/util.rs193
-rw-r--r--compiler/rustc_middle/src/ty/visit.rs135
-rw-r--r--compiler/rustc_middle/src/ty/vtable.rs2
-rw-r--r--compiler/rustc_middle/src/ty/walk.rs1
-rw-r--r--compiler/rustc_middle/src/values.rs9
-rw-r--r--compiler/rustc_mir_build/Cargo.toml1
-rw-r--r--compiler/rustc_mir_build/locales/en-US.ftl (renamed from compiler/rustc_error_messages/locales/en-US/mir_build.ftl)22
-rw-r--r--compiler/rustc_mir_build/src/build/custom/parse/instruction.rs20
-rw-r--r--compiler/rustc_mir_build/src/build/expr/as_constant.rs6
-rw-r--r--compiler/rustc_mir_build/src/build/expr/as_operand.rs2
-rw-r--r--compiler/rustc_mir_build/src/build/expr/as_place.rs15
-rw-r--r--compiler/rustc_mir_build/src/build/expr/as_rvalue.rs12
-rw-r--r--compiler/rustc_mir_build/src/build/expr/as_temp.rs2
-rw-r--r--compiler/rustc_mir_build/src/build/expr/into.rs2
-rw-r--r--compiler/rustc_mir_build/src/build/matches/mod.rs10
-rw-r--r--compiler/rustc_mir_build/src/build/matches/test.rs11
-rw-r--r--compiler/rustc_mir_build/src/build/matches/util.rs4
-rw-r--r--compiler/rustc_mir_build/src/build/mod.rs196
-rw-r--r--compiler/rustc_mir_build/src/errors.rs108
-rw-r--r--compiler/rustc_mir_build/src/lib.rs8
-rw-r--r--compiler/rustc_mir_build/src/thir/cx/expr.rs47
-rw-r--r--compiler/rustc_mir_build/src/thir/cx/mod.rs41
-rw-r--r--compiler/rustc_mir_build/src/thir/mod.rs4
-rw-r--r--compiler/rustc_mir_build/src/thir/pattern/check_match.rs83
-rw-r--r--compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs2
-rw-r--r--compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs16
-rw-r--r--compiler/rustc_mir_build/src/thir/pattern/mod.rs8
-rw-r--r--compiler/rustc_mir_build/src/thir/print.rs892
-rw-r--r--compiler/rustc_mir_dataflow/Cargo.toml1
-rw-r--r--compiler/rustc_mir_dataflow/locales/en-US.ftl (renamed from compiler/rustc_error_messages/locales/en-US/mir_dataflow.ftl)0
-rw-r--r--compiler/rustc_mir_dataflow/src/drop_flag_effects.rs13
-rw-r--r--compiler/rustc_mir_dataflow/src/elaborate_drops.rs2
-rw-r--r--compiler/rustc_mir_dataflow/src/framework/direction.rs31
-rw-r--r--compiler/rustc_mir_dataflow/src/framework/engine.rs32
-rw-r--r--compiler/rustc_mir_dataflow/src/impls/borrowed_locals.rs4
-rw-r--r--compiler/rustc_mir_dataflow/src/impls/liveness.rs9
-rw-r--r--compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs1
-rw-r--r--compiler/rustc_mir_dataflow/src/lib.rs5
-rw-r--r--compiler/rustc_mir_dataflow/src/move_paths/builder.rs18
-rw-r--r--compiler/rustc_mir_dataflow/src/value_analysis.rs286
-rw-r--r--compiler/rustc_mir_transform/src/abort_unwinding_calls.rs2
-rw-r--r--compiler/rustc_mir_transform/src/check_const_item_mutation.rs2
-rw-r--r--compiler/rustc_mir_transform/src/check_packed_ref.rs88
-rw-r--r--compiler/rustc_mir_transform/src/check_unsafety.rs4
-rw-r--r--compiler/rustc_mir_transform/src/const_goto.rs9
-rw-r--r--compiler/rustc_mir_transform/src/const_prop.rs351
-rw-r--r--compiler/rustc_mir_transform/src/const_prop_lint.rs18
-rw-r--r--compiler/rustc_mir_transform/src/copy_prop.rs182
-rw-r--r--compiler/rustc_mir_transform/src/coverage/counters.rs6
-rw-r--r--compiler/rustc_mir_transform/src/coverage/debug.rs5
-rw-r--r--compiler/rustc_mir_transform/src/coverage/graph.rs14
-rw-r--r--compiler/rustc_mir_transform/src/coverage/mod.rs3
-rw-r--r--compiler/rustc_mir_transform/src/coverage/spans.rs18
-rw-r--r--compiler/rustc_mir_transform/src/ctfe_limit.rs58
-rw-r--r--compiler/rustc_mir_transform/src/dataflow_const_prop.rs150
-rw-r--r--compiler/rustc_mir_transform/src/dead_store_elimination.rs1
-rw-r--r--compiler/rustc_mir_transform/src/deaggregator.rs45
-rw-r--r--compiler/rustc_mir_transform/src/deduce_param_attrs.rs2
-rw-r--r--compiler/rustc_mir_transform/src/dest_prop.rs12
-rw-r--r--compiler/rustc_mir_transform/src/elaborate_box_derefs.rs10
-rw-r--r--compiler/rustc_mir_transform/src/elaborate_drops.rs86
-rw-r--r--compiler/rustc_mir_transform/src/ffi_unwind_calls.rs2
-rw-r--r--compiler/rustc_mir_transform/src/function_item_references.rs13
-rw-r--r--compiler/rustc_mir_transform/src/generator.rs389
-rw-r--r--compiler/rustc_mir_transform/src/inline.rs12
-rw-r--r--compiler/rustc_mir_transform/src/inline/cycle.rs2
-rw-r--r--compiler/rustc_mir_transform/src/instcombine.rs86
-rw-r--r--compiler/rustc_mir_transform/src/large_enums.rs294
-rw-r--r--compiler/rustc_mir_transform/src/lib.rs32
-rw-r--r--compiler/rustc_mir_transform/src/lower_intrinsics.rs26
-rw-r--r--compiler/rustc_mir_transform/src/lower_slice_len.rs5
-rw-r--r--compiler/rustc_mir_transform/src/normalize_array_len.rs322
-rw-r--r--compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs1
-rw-r--r--compiler/rustc_mir_transform/src/remove_zsts.rs2
-rw-r--r--compiler/rustc_mir_transform/src/separate_const_switch.rs2
-rw-r--r--compiler/rustc_mir_transform/src/shim.rs49
-rw-r--r--compiler/rustc_mir_transform/src/simplify.rs20
-rw-r--r--compiler/rustc_mir_transform/src/simplify_try.rs822
-rw-r--r--compiler/rustc_mir_transform/src/sroa.rs439
-rw-r--r--compiler/rustc_mir_transform/src/ssa.rs257
-rw-r--r--compiler/rustc_monomorphize/locales/en-US.ftl (renamed from compiler/rustc_error_messages/locales/en-US/monomorphize.ftl)6
-rw-r--r--compiler/rustc_monomorphize/src/collector.rs135
-rw-r--r--compiler/rustc_monomorphize/src/errors.rs17
-rw-r--r--compiler/rustc_monomorphize/src/lib.rs4
-rw-r--r--compiler/rustc_monomorphize/src/partitioning/default.rs4
-rw-r--r--compiler/rustc_monomorphize/src/partitioning/mod.rs22
-rw-r--r--compiler/rustc_monomorphize/src/polymorphize.rs6
-rw-r--r--compiler/rustc_parse/Cargo.toml2
-rw-r--r--compiler/rustc_parse/locales/en-US.ftl (renamed from compiler/rustc_error_messages/locales/en-US/parse.ftl)356
-rw-r--r--compiler/rustc_parse/src/errors.rs1136
-rw-r--r--compiler/rustc_parse/src/lexer/diagnostics.rs119
-rw-r--r--compiler/rustc_parse/src/lexer/mod.rs189
-rw-r--r--compiler/rustc_parse/src/lexer/tokentrees.rs150
-rw-r--r--compiler/rustc_parse/src/lexer/unescape_error_reporting.rs248
-rw-r--r--compiler/rustc_parse/src/lexer/unicode_chars.rs60
-rw-r--r--compiler/rustc_parse/src/lib.rs36
-rw-r--r--compiler/rustc_parse/src/parser/attr.rs26
-rw-r--r--compiler/rustc_parse/src/parser/attr_wrapper.rs6
-rw-r--r--compiler/rustc_parse/src/parser/diagnostics.rs173
-rw-r--r--compiler/rustc_parse/src/parser/expr.rs543
-rw-r--r--compiler/rustc_parse/src/parser/generics.rs61
-rw-r--r--compiler/rustc_parse/src/parser/item.rs429
-rw-r--r--compiler/rustc_parse/src/parser/mod.rs203
-rw-r--r--compiler/rustc_parse/src/parser/nonterminal.rs22
-rw-r--r--compiler/rustc_parse/src/parser/pat.rs382
-rw-r--r--compiler/rustc_parse/src/parser/path.rs58
-rw-r--r--compiler/rustc_parse/src/parser/stmt.rs96
-rw-r--r--compiler/rustc_parse/src/parser/ty.rs182
-rw-r--r--compiler/rustc_parse_format/src/lib.rs94
-rw-r--r--compiler/rustc_parse_format/src/tests.rs75
-rw-r--r--compiler/rustc_passes/locales/en-US.ftl (renamed from compiler/rustc_error_messages/locales/en-US/passes.ftl)44
-rw-r--r--compiler/rustc_passes/src/check_attr.rs352
-rw-r--r--compiler/rustc_passes/src/check_const.rs6
-rw-r--r--compiler/rustc_passes/src/dead.rs83
-rw-r--r--compiler/rustc_passes/src/diagnostic_items.rs66
-rw-r--r--compiler/rustc_passes/src/errors.rs205
-rw-r--r--compiler/rustc_passes/src/hir_id_validator.rs39
-rw-r--r--compiler/rustc_passes/src/hir_stats.rs7
-rw-r--r--compiler/rustc_passes/src/lang_items.rs27
-rw-r--r--compiler/rustc_passes/src/layout_test.rs2
-rw-r--r--compiler/rustc_passes/src/lib.rs4
-rw-r--r--compiler/rustc_passes/src/lib_features.rs5
-rw-r--r--compiler/rustc_passes/src/liveness.rs8
-rw-r--r--compiler/rustc_passes/src/liveness/rwu_table.rs2
-rw-r--r--compiler/rustc_passes/src/naked_functions.rs2
-rw-r--r--compiler/rustc_passes/src/reachable.rs31
-rw-r--r--compiler/rustc_passes/src/stability.rs63
-rw-r--r--compiler/rustc_plugin_impl/locales/en-US.ftl (renamed from compiler/rustc_error_messages/locales/en-US/plugin_impl.ftl)0
-rw-r--r--compiler/rustc_plugin_impl/src/lib.rs4
-rw-r--r--compiler/rustc_privacy/Cargo.toml1
-rw-r--r--compiler/rustc_privacy/locales/en-US.ftl (renamed from compiler/rustc_error_messages/locales/en-US/privacy.ftl)0
-rw-r--r--compiler/rustc_privacy/src/errors.rs4
-rw-r--r--compiler/rustc_privacy/src/lib.rs76
-rw-r--r--compiler/rustc_query_impl/Cargo.toml3
-rw-r--r--compiler/rustc_query_impl/src/lib.rs4
-rw-r--r--compiler/rustc_query_impl/src/on_disk_cache.rs2
-rw-r--r--compiler/rustc_query_impl/src/plumbing.rs91
-rw-r--r--compiler/rustc_query_system/Cargo.toml2
-rw-r--r--compiler/rustc_query_system/locales/en-US.ftl (renamed from compiler/rustc_error_messages/locales/en-US/query_system.ftl)0
-rw-r--r--compiler/rustc_query_system/src/dep_graph/graph.rs63
-rw-r--r--compiler/rustc_query_system/src/dep_graph/mod.rs6
-rw-r--r--compiler/rustc_query_system/src/dep_graph/serialized.rs3
-rw-r--r--compiler/rustc_query_system/src/ich/hcx.rs4
-rw-r--r--compiler/rustc_query_system/src/lib.rs6
-rw-r--r--compiler/rustc_query_system/src/query/caches.rs267
-rw-r--r--compiler/rustc_query_system/src/query/config.rs13
-rw-r--r--compiler/rustc_query_system/src/query/mod.rs19
-rw-r--r--compiler/rustc_query_system/src/query/plumbing.rs201
-rw-r--r--compiler/rustc_resolve/Cargo.toml3
-rw-r--r--compiler/rustc_resolve/locales/en-US.ftl (renamed from compiler/rustc_error_messages/locales/en-US/resolve.ftl)0
-rw-r--r--compiler/rustc_resolve/src/build_reduced_graph.rs126
-rw-r--r--compiler/rustc_resolve/src/check_unused.rs145
-rw-r--r--compiler/rustc_resolve/src/def_collector.rs10
-rw-r--r--compiler/rustc_resolve/src/diagnostics.rs226
-rw-r--r--compiler/rustc_resolve/src/effective_visibilities.rs42
-rw-r--r--compiler/rustc_resolve/src/errors.rs14
-rw-r--r--compiler/rustc_resolve/src/ident.rs23
-rw-r--r--compiler/rustc_resolve/src/imports.rs163
-rw-r--r--compiler/rustc_resolve/src/late.rs265
-rw-r--r--compiler/rustc_resolve/src/late/diagnostics.rs142
-rw-r--r--compiler/rustc_resolve/src/lib.rs309
-rw-r--r--compiler/rustc_resolve/src/macros.rs69
-rw-r--r--compiler/rustc_resolve/src/rustdoc.rs388
-rw-r--r--compiler/rustc_save_analysis/Cargo.toml21
-rw-r--r--compiler/rustc_save_analysis/src/dump_visitor.rs1471
-rw-r--r--compiler/rustc_save_analysis/src/dumper.rs91
-rw-r--r--compiler/rustc_save_analysis/src/errors.rs10
-rw-r--r--compiler/rustc_save_analysis/src/lib.rs1072
-rw-r--r--compiler/rustc_save_analysis/src/sig.rs923
-rw-r--r--compiler/rustc_save_analysis/src/span_utils.rs96
-rw-r--r--compiler/rustc_serialize/Cargo.toml2
-rw-r--r--compiler/rustc_serialize/src/serialize.rs17
-rw-r--r--compiler/rustc_session/locales/en-US.ftl (renamed from compiler/rustc_error_messages/locales/en-US/session.ftl)6
-rw-r--r--compiler/rustc_session/src/code_stats.rs32
-rw-r--r--compiler/rustc_session/src/config.rs92
-rw-r--r--compiler/rustc_session/src/cstore.rs14
-rw-r--r--compiler/rustc_session/src/errors.rs40
-rw-r--r--compiler/rustc_session/src/filesearch.rs14
-rw-r--r--compiler/rustc_session/src/lib.rs5
-rw-r--r--compiler/rustc_session/src/options.rs124
-rw-r--r--compiler/rustc_session/src/parse.rs12
-rw-r--r--compiler/rustc_session/src/session.rs128
-rw-r--r--compiler/rustc_span/src/def_id.rs12
-rw-r--r--compiler/rustc_span/src/edit_distance.rs229
-rw-r--r--compiler/rustc_span/src/edit_distance/tests.rs80
-rw-r--r--compiler/rustc_span/src/edition.rs29
-rw-r--r--compiler/rustc_span/src/lev_distance.rs177
-rw-r--r--compiler/rustc_span/src/lev_distance/tests.rs71
-rw-r--r--compiler/rustc_span/src/lib.rs27
-rw-r--r--compiler/rustc_span/src/span_encoding.rs7
-rw-r--r--compiler/rustc_span/src/symbol.rs16
-rw-r--r--compiler/rustc_symbol_mangling/locales/en-US.ftl (renamed from compiler/rustc_error_messages/locales/en-US/symbol_mangling.ftl)0
-rw-r--r--compiler/rustc_symbol_mangling/src/legacy.rs4
-rw-r--r--compiler/rustc_symbol_mangling/src/lib.rs7
-rw-r--r--compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs37
-rw-r--r--compiler/rustc_symbol_mangling/src/v0.rs9
-rw-r--r--compiler/rustc_target/src/abi/call/loongarch.rs2
-rw-r--r--compiler/rustc_target/src/abi/call/mod.rs2
-rw-r--r--compiler/rustc_target/src/abi/call/riscv.rs2
-rw-r--r--compiler/rustc_target/src/abi/call/sparc64.rs6
-rw-r--r--compiler/rustc_target/src/abi/call/x86_64.rs2
-rw-r--r--compiler/rustc_target/src/abi/mod.rs50
-rw-r--r--compiler/rustc_target/src/spec/aarch64_apple_ios.rs7
-rw-r--r--compiler/rustc_target/src/spec/aarch64_apple_ios_macabi.rs4
-rw-r--r--compiler/rustc_target/src/spec/aarch64_apple_ios_sim.rs7
-rw-r--r--compiler/rustc_target/src/spec/aarch64_be_unknown_linux_gnu.rs2
-rw-r--r--compiler/rustc_target/src/spec/aarch64_be_unknown_linux_gnu_ilp32.rs2
-rw-r--r--compiler/rustc_target/src/spec/aarch64_kmc_solid_asp3.rs2
-rw-r--r--compiler/rustc_target/src/spec/aarch64_linux_android.rs3
-rw-r--r--compiler/rustc_target/src/spec/aarch64_nintendo_switch_freestanding.rs1
-rw-r--r--compiler/rustc_target/src/spec/aarch64_pc_windows_gnullvm.rs2
-rw-r--r--compiler/rustc_target/src/spec/aarch64_pc_windows_msvc.rs2
-rw-r--r--compiler/rustc_target/src/spec/aarch64_unknown_freebsd.rs1
-rw-r--r--compiler/rustc_target/src/spec/aarch64_unknown_fuchsia.rs1
-rw-r--r--compiler/rustc_target/src/spec/aarch64_unknown_hermit.rs2
-rw-r--r--compiler/rustc_target/src/spec/aarch64_unknown_linux_gnu.rs3
-rw-r--r--compiler/rustc_target/src/spec/aarch64_unknown_linux_gnu_ilp32.rs2
-rw-r--r--compiler/rustc_target/src/spec/aarch64_unknown_linux_musl.rs2
-rw-r--r--compiler/rustc_target/src/spec/aarch64_unknown_netbsd.rs1
-rw-r--r--compiler/rustc_target/src/spec/aarch64_unknown_none.rs4
-rw-r--r--compiler/rustc_target/src/spec/aarch64_unknown_none_softfloat.rs2
-rw-r--r--compiler/rustc_target/src/spec/aarch64_unknown_nto_qnx_710.rs1
-rw-r--r--compiler/rustc_target/src/spec/aarch64_unknown_openbsd.rs6
-rw-r--r--compiler/rustc_target/src/spec/aarch64_unknown_redox.rs1
-rw-r--r--compiler/rustc_target/src/spec/aarch64_unknown_uefi.rs1
-rw-r--r--compiler/rustc_target/src/spec/aarch64_uwp_windows_msvc.rs1
-rw-r--r--compiler/rustc_target/src/spec/aarch64_wrs_vxworks.rs6
-rw-r--r--compiler/rustc_target/src/spec/arm64_32_apple_watchos.rs2
-rw-r--r--compiler/rustc_target/src/spec/armebv7r_none_eabi.rs2
-rw-r--r--compiler/rustc_target/src/spec/armebv7r_none_eabihf.rs2
-rw-r--r--compiler/rustc_target/src/spec/armv4t_none_eabi.rs2
-rw-r--r--compiler/rustc_target/src/spec/armv6k_nintendo_3ds.rs3
-rw-r--r--compiler/rustc_target/src/spec/armv7a_none_eabi.rs2
-rw-r--r--compiler/rustc_target/src/spec/armv7a_none_eabihf.rs2
-rw-r--r--compiler/rustc_target/src/spec/armv7r_none_eabi.rs2
-rw-r--r--compiler/rustc_target/src/spec/armv7r_none_eabihf.rs2
-rw-r--r--compiler/rustc_target/src/spec/bpf_base.rs2
-rw-r--r--compiler/rustc_target/src/spec/hexagon_unknown_linux_musl.rs2
-rw-r--r--compiler/rustc_target/src/spec/mod.rs40
-rw-r--r--compiler/rustc_target/src/spec/riscv64gc_unknown_none_elf.rs3
-rw-r--r--compiler/rustc_target/src/spec/riscv64imac_unknown_none_elf.rs3
-rw-r--r--compiler/rustc_target/src/spec/s390x_unknown_linux_gnu.rs4
-rw-r--r--compiler/rustc_target/src/spec/s390x_unknown_linux_musl.rs4
-rw-r--r--compiler/rustc_target/src/spec/thumb_base.rs2
-rw-r--r--compiler/rustc_target/src/spec/thumbv4t_none_eabi.rs2
-rw-r--r--compiler/rustc_target/src/spec/x86_64_apple_ios.rs7
-rw-r--r--compiler/rustc_target/src/spec/x86_64_apple_ios_macabi.rs2
-rw-r--r--compiler/rustc_target/src/spec/x86_64_linux_android.rs1
-rw-r--r--compiler/rustc_target/src/spec/x86_64_unknown_freebsd.rs1
-rw-r--r--compiler/rustc_target/src/spec/x86_64_unknown_linux_gnu.rs1
-rw-r--r--compiler/rustc_target/src/spec/x86_64_unknown_linux_musl.rs1
-rw-r--r--compiler/rustc_target/src/spec/x86_64_unknown_netbsd.rs1
-rw-r--r--compiler/rustc_target/src/spec/x86_64_unknown_none.rs2
-rw-r--r--compiler/rustc_target/src/spec/x86_64_unknown_openbsd.rs1
-rw-r--r--compiler/rustc_trait_selection/Cargo.toml2
-rw-r--r--compiler/rustc_trait_selection/locales/en-US.ftl (renamed from compiler/rustc_error_messages/locales/en-US/trait_selection.ftl)0
-rw-r--r--compiler/rustc_trait_selection/src/errors.rs11
-rw-r--r--compiler/rustc_trait_selection/src/infer.rs16
-rw-r--r--compiler/rustc_trait_selection/src/lib.rs5
-rw-r--r--compiler/rustc_trait_selection/src/solve/assembly.rs229
-rw-r--r--compiler/rustc_trait_selection/src/solve/canonical/canonicalize.rs390
-rw-r--r--compiler/rustc_trait_selection/src/solve/canonical/mod.rs240
-rw-r--r--compiler/rustc_trait_selection/src/solve/eval_ctxt.rs184
-rw-r--r--compiler/rustc_trait_selection/src/solve/fulfill.rs89
-rw-r--r--compiler/rustc_trait_selection/src/solve/infcx_ext.rs78
-rw-r--r--compiler/rustc_trait_selection/src/solve/mod.rs532
-rw-r--r--compiler/rustc_trait_selection/src/solve/project_goals.rs533
-rw-r--r--compiler/rustc_trait_selection/src/solve/search_graph/cache.rs2
-rw-r--r--compiler/rustc_trait_selection/src/solve/search_graph/mod.rs133
-rw-r--r--compiler/rustc_trait_selection/src/solve/search_graph/overflow.rs58
-rw-r--r--compiler/rustc_trait_selection/src/solve/trait_goals.rs468
-rw-r--r--compiler/rustc_trait_selection/src/solve/trait_goals/structural_traits.rs200
-rw-r--r--compiler/rustc_trait_selection/src/traits/auto_trait.rs14
-rw-r--r--compiler/rustc_trait_selection/src/traits/chalk_fulfill.rs35
-rw-r--r--compiler/rustc_trait_selection/src/traits/coherence.rs24
-rw-r--r--compiler/rustc_trait_selection/src/traits/const_evaluatable.rs6
-rw-r--r--compiler/rustc_trait_selection/src/traits/engine.rs11
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/ambiguity.rs8
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/method_chain.rs15
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs131
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs30
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs287
-rw-r--r--compiler/rustc_trait_selection/src/traits/fulfill.rs161
-rw-r--r--compiler/rustc_trait_selection/src/traits/misc.rs23
-rw-r--r--compiler/rustc_trait_selection/src/traits/mod.rs46
-rw-r--r--compiler/rustc_trait_selection/src/traits/object_safety.rs162
-rw-r--r--compiler/rustc_trait_selection/src/traits/outlives_bounds.rs13
-rw-r--r--compiler/rustc_trait_selection/src/traits/project.rs160
-rw-r--r--compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs1
-rw-r--r--compiler/rustc_trait_selection/src/traits/query/evaluate_obligation.rs43
-rw-r--r--compiler/rustc_trait_selection/src/traits/query/normalize.rs38
-rw-r--r--compiler/rustc_trait_selection/src/traits/query/type_op/mod.rs4
-rw-r--r--compiler/rustc_trait_selection/src/traits/query/type_op/normalize.rs4
-rw-r--r--compiler/rustc_trait_selection/src/traits/query/type_op/outlives.rs6
-rw-r--r--compiler/rustc_trait_selection/src/traits/relationships.rs48
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs27
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/confirmation.rs110
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/mod.rs247
-rw-r--r--compiler/rustc_trait_selection/src/traits/specialize/mod.rs8
-rw-r--r--compiler/rustc_trait_selection/src/traits/specialize/specialization_graph.rs6
-rw-r--r--compiler/rustc_trait_selection/src/traits/structural_match.rs6
-rw-r--r--compiler/rustc_trait_selection/src/traits/util.rs6
-rw-r--r--compiler/rustc_trait_selection/src/traits/vtable.rs6
-rw-r--r--compiler/rustc_trait_selection/src/traits/wf.rs54
-rw-r--r--compiler/rustc_traits/Cargo.toml1
-rw-r--r--compiler/rustc_traits/src/chalk/db.rs36
-rw-r--r--compiler/rustc_traits/src/chalk/lowering.rs124
-rw-r--r--compiler/rustc_traits/src/chalk/mod.rs59
-rw-r--r--compiler/rustc_traits/src/codegen.rs2
-rw-r--r--compiler/rustc_traits/src/dropck_outlives.rs5
-rw-r--r--compiler/rustc_traits/src/implied_outlives_bounds.rs102
-rw-r--r--compiler/rustc_traits/src/lib.rs1
-rw-r--r--compiler/rustc_traits/src/normalize_erasing_regions.rs6
-rw-r--r--compiler/rustc_traits/src/type_op.rs11
-rw-r--r--compiler/rustc_transmute/src/layout/tree.rs5
-rw-r--r--compiler/rustc_transmute/src/lib.rs2
-rw-r--r--compiler/rustc_ty_utils/locales/en-US.ftl (renamed from compiler/rustc_error_messages/locales/en-US/ty_utils.ftl)0
-rw-r--r--compiler/rustc_ty_utils/src/abi.rs73
-rw-r--r--compiler/rustc_ty_utils/src/assoc.rs270
-rw-r--r--compiler/rustc_ty_utils/src/consts.rs4
-rw-r--r--compiler/rustc_ty_utils/src/errors.rs2
-rw-r--r--compiler/rustc_ty_utils/src/implied_bounds.rs12
-rw-r--r--compiler/rustc_ty_utils/src/instance.rs5
-rw-r--r--compiler/rustc_ty_utils/src/layout.rs108
-rw-r--r--compiler/rustc_ty_utils/src/lib.rs4
-rw-r--r--compiler/rustc_ty_utils/src/needs_drop.rs25
-rw-r--r--compiler/rustc_ty_utils/src/representability.rs4
-rw-r--r--compiler/rustc_ty_utils/src/ty.rs151
-rw-r--r--compiler/rustc_type_ir/src/fold.rs239
-rw-r--r--compiler/rustc_type_ir/src/lib.rs142
-rw-r--r--compiler/rustc_type_ir/src/macros.rs176
-rw-r--r--compiler/rustc_type_ir/src/structural_impls.rs175
-rw-r--r--compiler/rustc_type_ir/src/sty.rs156
-rw-r--r--compiler/rustc_type_ir/src/visit.rs115
-rw-r--r--config.toml.example32
-rw-r--r--git-commit-hash2
-rw-r--r--git-commit-info6
-rw-r--r--library/alloc/benches/vec_deque.rs146
-rw-r--r--library/alloc/src/boxed.rs9
-rw-r--r--library/alloc/src/boxed/thin.rs8
-rw-r--r--library/alloc/src/collections/binary_heap/mod.rs24
-rw-r--r--library/alloc/src/collections/binary_heap/tests.rs19
-rw-r--r--library/alloc/src/collections/btree/borrow.rs22
-rw-r--r--library/alloc/src/collections/btree/map.rs730
-rw-r--r--library/alloc/src/collections/btree/map/entry.rs40
-rw-r--r--library/alloc/src/collections/btree/map/tests.rs49
-rw-r--r--library/alloc/src/collections/btree/navigate.rs55
-rw-r--r--library/alloc/src/collections/btree/node.rs102
-rw-r--r--library/alloc/src/collections/vec_deque/into_iter.rs185
-rw-r--r--library/alloc/src/ffi/c_str.rs8
-rw-r--r--library/alloc/src/fmt.rs2
-rw-r--r--library/alloc/src/lib.rs3
-rw-r--r--library/alloc/src/macros.rs2
-rw-r--r--library/alloc/src/raw_vec.rs17
-rw-r--r--library/alloc/src/rc.rs4
-rw-r--r--library/alloc/src/slice.rs43
-rw-r--r--library/alloc/src/string.rs16
-rw-r--r--library/alloc/src/sync.rs149
-rw-r--r--library/alloc/src/sync/tests.rs32
-rw-r--r--library/alloc/src/vec/mod.rs40
-rw-r--r--library/core/benches/array.rs19
-rw-r--r--library/core/benches/char/methods.rs40
-rw-r--r--library/core/benches/lib.rs1
-rw-r--r--library/core/benches/num/flt2dec/strategy/dragon.rs18
-rw-r--r--library/core/benches/num/flt2dec/strategy/grisu.rs18
-rw-r--r--library/core/src/alloc/global.rs9
-rw-r--r--library/core/src/any.rs2
-rw-r--r--library/core/src/array/drain.rs76
-rw-r--r--library/core/src/array/equality.rs73
-rw-r--r--library/core/src/array/mod.rs273
-rw-r--r--library/core/src/cell.rs35
-rw-r--r--library/core/src/cell/once.rs4
-rw-r--r--library/core/src/char/convert.rs28
-rw-r--r--library/core/src/char/decode.rs6
-rw-r--r--library/core/src/char/methods.rs24
-rw-r--r--library/core/src/char/mod.rs2
-rw-r--r--library/core/src/cmp.rs81
-rw-r--r--library/core/src/cmp/bytewise.rs83
-rw-r--r--library/core/src/const_closure.rs78
-rw-r--r--library/core/src/convert/mod.rs2
-rw-r--r--library/core/src/error.rs19
-rw-r--r--library/core/src/ffi/c_str.rs27
-rw-r--r--library/core/src/ffi/mod.rs1
-rw-r--r--library/core/src/fmt/mod.rs87
-rw-r--r--library/core/src/fmt/rt/v1.rs18
-rw-r--r--library/core/src/future/mod.rs45
-rw-r--r--library/core/src/hint.rs3
-rw-r--r--library/core/src/intrinsics.rs6
-rw-r--r--library/core/src/intrinsics/mir.rs18
-rw-r--r--library/core/src/iter/adapters/array_chunks.rs20
-rw-r--r--library/core/src/iter/adapters/by_ref_sized.rs19
-rw-r--r--library/core/src/iter/adapters/cloned.rs15
-rw-r--r--library/core/src/iter/adapters/filter_map.rs2
-rw-r--r--library/core/src/iter/adapters/flatten.rs4
-rw-r--r--library/core/src/iter/adapters/map.rs15
-rw-r--r--library/core/src/iter/adapters/zip.rs9
-rw-r--r--library/core/src/iter/mod.rs8
-rw-r--r--library/core/src/iter/range.rs1
-rw-r--r--library/core/src/iter/traits/double_ended.rs2
-rw-r--r--library/core/src/iter/traits/exact_size.rs10
-rw-r--r--library/core/src/iter/traits/iterator.rs121
-rw-r--r--library/core/src/iter/traits/marker.rs11
-rw-r--r--library/core/src/iter/traits/mod.rs3
-rw-r--r--library/core/src/iter/traits/unchecked_iterator.rs36
-rw-r--r--library/core/src/lib.rs15
-rw-r--r--library/core/src/marker.rs73
-rw-r--r--library/core/src/mem/mod.rs1
-rw-r--r--library/core/src/net/display_buffer.rs (renamed from library/std/src/net/display_buffer.rs)0
-rw-r--r--library/core/src/net/ip_addr.rs2070
-rw-r--r--library/core/src/net/mod.rs24
-rw-r--r--library/core/src/net/parser.rs (renamed from library/std/src/net/parser.rs)4
-rw-r--r--library/core/src/net/socket_addr.rs664
-rw-r--r--library/core/src/num/dec2flt/mod.rs17
-rw-r--r--library/core/src/num/error.rs57
-rw-r--r--library/core/src/num/int_log10.rs8
-rw-r--r--library/core/src/num/int_macros.rs80
-rw-r--r--library/core/src/num/mod.rs396
-rw-r--r--library/core/src/num/shells/i128.rs4
-rw-r--r--library/core/src/num/shells/i16.rs4
-rw-r--r--library/core/src/num/shells/i32.rs4
-rw-r--r--library/core/src/num/shells/i64.rs4
-rw-r--r--library/core/src/num/shells/i8.rs4
-rw-r--r--library/core/src/num/shells/isize.rs4
-rw-r--r--library/core/src/num/shells/u128.rs4
-rw-r--r--library/core/src/num/shells/u16.rs4
-rw-r--r--library/core/src/num/shells/u32.rs4
-rw-r--r--library/core/src/num/shells/u64.rs4
-rw-r--r--library/core/src/num/shells/u8.rs4
-rw-r--r--library/core/src/num/shells/usize.rs4
-rw-r--r--library/core/src/num/uint_macros.rs63
-rw-r--r--library/core/src/ops/arith.rs22
-rw-r--r--library/core/src/ops/control_flow.rs43
-rw-r--r--library/core/src/ops/range.rs98
-rw-r--r--library/core/src/ops/try_trait.rs26
-rw-r--r--library/core/src/option.rs141
-rw-r--r--library/core/src/panicking.rs5
-rw-r--r--library/core/src/primitive_docs.rs6
-rw-r--r--library/core/src/ptr/alignment.rs2
-rw-r--r--library/core/src/ptr/const_ptr.rs22
-rw-r--r--library/core/src/ptr/mut_ptr.rs24
-rw-r--r--library/core/src/result.rs48
-rw-r--r--library/core/src/slice/cmp.rs27
-rw-r--r--library/core/src/slice/iter.rs4
-rw-r--r--library/core/src/slice/iter/macros.rs9
-rw-r--r--library/core/src/slice/memchr.rs15
-rw-r--r--library/core/src/slice/mod.rs70
-rw-r--r--library/core/src/slice/sort.rs526
-rw-r--r--library/core/src/str/iter.rs10
-rw-r--r--library/core/src/str/traits.rs4
-rw-r--r--library/core/src/sync/atomic.rs196
-rw-r--r--library/core/src/task/poll.rs5
-rw-r--r--library/core/src/task/wake.rs2
-rw-r--r--library/core/tests/array.rs25
-rw-r--r--library/core/tests/iter/adapters/mod.rs2
-rw-r--r--library/core/tests/iter/range.rs1
-rw-r--r--library/core/tests/iter/traits/iterator.rs3
-rw-r--r--library/core/tests/lib.rs6
-rw-r--r--library/core/tests/net/ip_addr.rs1035
-rw-r--r--library/core/tests/net/mod.rs13
-rw-r--r--library/core/tests/net/parser.rs (renamed from library/std/src/net/parser/tests.rs)4
-rw-r--r--library/core/tests/net/socket_addr.rs233
-rw-r--r--library/core/tests/num/dec2flt/mod.rs2
-rw-r--r--library/core/tests/ptr.rs6
-rw-r--r--library/portable-simd/crates/core_simd/examples/spectral_norm.rs2
-rw-r--r--library/portable-simd/crates/core_simd/src/vector.rs2
-rw-r--r--library/proc_macro/src/bridge/rpc.rs1
-rw-r--r--library/proc_macro/src/lib.rs3
-rw-r--r--library/std/Cargo.toml6
-rw-r--r--library/std/build.rs1
-rw-r--r--library/std/src/collections/hash/map.rs2
-rw-r--r--library/std/src/f32.rs4
-rw-r--r--library/std/src/f64.rs4
-rw-r--r--library/std/src/fs.rs20
-rw-r--r--library/std/src/fs/tests.rs20
-rw-r--r--library/std/src/io/error.rs19
-rw-r--r--library/std/src/io/error/repr_bitpacked.rs9
-rw-r--r--library/std/src/io/error/repr_unpacked.rs4
-rw-r--r--library/std/src/io/error/tests.rs4
-rw-r--r--library/std/src/io/mod.rs2
-rw-r--r--library/std/src/keyword_docs.rs2
-rw-r--r--library/std/src/lib.rs10
-rw-r--r--library/std/src/net/ip_addr.rs2075
-rw-r--r--library/std/src/net/ip_addr/tests.rs1035
-rw-r--r--library/std/src/net/mod.rs6
-rw-r--r--library/std/src/net/socket_addr.rs689
-rw-r--r--library/std/src/net/socket_addr/tests.rs8
-rw-r--r--library/std/src/net/tcp.rs2
-rw-r--r--library/std/src/net/tcp/tests.rs5
-rw-r--r--library/std/src/net/udp/tests.rs5
-rw-r--r--library/std/src/os/fd/owned.rs17
-rw-r--r--library/std/src/os/fd/raw.rs18
-rw-r--r--library/std/src/os/fuchsia/raw.rs7
-rw-r--r--library/std/src/os/hermit/io/mod.rs13
-rw-r--r--library/std/src/os/hermit/io/net.rs46
-rw-r--r--library/std/src/os/hermit/mod.rs5
-rw-r--r--library/std/src/os/l4re/raw.rs1
-rw-r--r--library/std/src/os/linux/raw.rs1
-rw-r--r--library/std/src/os/mod.rs14
-rw-r--r--library/std/src/os/net/mod.rs9
-rw-r--r--library/std/src/os/nto/fs.rs92
-rw-r--r--library/std/src/os/nto/mod.rs4
-rw-r--r--library/std/src/os/nto/raw.rs40
-rw-r--r--library/std/src/os/unix/fs.rs30
-rw-r--r--library/std/src/os/unix/fs/tests.rs57
-rw-r--r--library/std/src/os/unix/mod.rs5
-rw-r--r--library/std/src/os/unix/net/datagram.rs6
-rw-r--r--library/std/src/os/unix/net/tests.rs1
-rw-r--r--library/std/src/os/unix/process.rs26
-rw-r--r--library/std/src/os/unix/ucred.rs3
-rw-r--r--library/std/src/panicking.rs16
-rw-r--r--library/std/src/path.rs4
-rw-r--r--library/std/src/personality/emcc.rs2
-rw-r--r--library/std/src/personality/gcc.rs3
-rw-r--r--library/std/src/primitive_docs.rs6
-rw-r--r--library/std/src/process.rs2
-rw-r--r--library/std/src/sync/lazy_lock.rs86
-rw-r--r--library/std/src/sync/mod.rs2
-rw-r--r--library/std/src/sync/mpmc/array.rs18
-rw-r--r--library/std/src/sync/mpmc/utils.rs12
-rw-r--r--library/std/src/sync/once.rs16
-rw-r--r--library/std/src/sys/common/alloc.rs1
-rw-r--r--library/std/src/sys/hermit/args.rs2
-rw-r--r--library/std/src/sys/hermit/fd.rs77
-rw-r--r--library/std/src/sys/hermit/fs.rs57
-rw-r--r--library/std/src/sys/hermit/mod.rs92
-rw-r--r--library/std/src/sys/hermit/net.rs639
-rw-r--r--library/std/src/sys/hermit/os.rs2
-rw-r--r--library/std/src/sys/hermit/thread.rs4
-rw-r--r--library/std/src/sys/hermit/thread_local_dtor.rs23
-rw-r--r--library/std/src/sys/hermit/time.rs98
-rw-r--r--library/std/src/sys/itron/thread.rs2
-rw-r--r--library/std/src/sys/itron/thread_parking.rs37
-rw-r--r--library/std/src/sys/itron/wait_flag.rs72
-rw-r--r--library/std/src/sys/solid/mod.rs4
-rw-r--r--library/std/src/sys/solid/thread_local_dtor.rs32
-rw-r--r--library/std/src/sys/unix/args.rs31
-rw-r--r--library/std/src/sys/unix/env.rs11
-rw-r--r--library/std/src/sys/unix/fd.rs203
-rw-r--r--library/std/src/sys/unix/fs.rs92
-rw-r--r--library/std/src/sys/unix/locks/pthread_condvar.rs11
-rw-r--r--library/std/src/sys/unix/mod.rs2
-rw-r--r--library/std/src/sys/unix/net.rs2
-rw-r--r--library/std/src/sys/unix/os.rs12
-rw-r--r--library/std/src/sys/unix/process/process_unix.rs74
-rw-r--r--library/std/src/sys/unix/thread.rs17
-rw-r--r--library/std/src/sys/unix/thread_local_dtor.rs36
-rw-r--r--library/std/src/sys/unix/thread_parking/pthread.rs9
-rw-r--r--library/std/src/sys/unix/time.rs22
-rw-r--r--library/std/src/sys/unsupported/once.rs11
-rw-r--r--library/std/src/sys/wasi/os.rs8
-rw-r--r--library/std/src/sys/windows/args.rs11
-rw-r--r--library/std/src/sys/windows/c.rs40
-rw-r--r--library/std/src/sys/windows/fs.rs9
-rw-r--r--library/std/src/sys/windows/io.rs32
-rw-r--r--library/std/src/sys/windows/stdio.rs75
-rw-r--r--library/std/src/sys/windows/thread.rs2
-rw-r--r--library/std/src/sys/windows/thread_parking.rs2
-rw-r--r--library/std/src/sys_common/backtrace.rs13
-rw-r--r--library/std/src/sys_common/mod.rs1
-rw-r--r--library/std/src/sys_common/net.rs15
-rw-r--r--library/std/src/sys_common/net/tests.rs2
-rw-r--r--library/std/src/sys_common/once/futex.rs11
-rw-r--r--library/std/src/sys_common/once/queue.rs11
-rw-r--r--library/std/src/sys_common/thread_local_dtor.rs2
-rw-r--r--library/std/src/sys_common/thread_local_key.rs10
-rw-r--r--library/std/src/sys_common/thread_parking/id.rs6
-rw-r--r--library/std/src/sys_common/thread_parking/mod.rs4
-rw-r--r--library/std/src/sys_common/thread_parking/wait_flag.rs102
-rw-r--r--library/std/src/sys_common/wtf8.rs8
-rw-r--r--library/std/src/thread/local.rs3
-rw-r--r--library/std/src/thread/mod.rs6
-rw-r--r--library/std/src/time.rs8
-rw-r--r--library/std/tests/common/mod.rs58
-rw-r--r--library/std/tests/create_dir_all_bare.rs39
-rw-r--r--library/std/tests/env.rs14
-rw-r--r--library/std/tests/run-time-detect.rs6
-rw-r--r--library/stdarch/.github/workflows/main.yml12
-rw-r--r--library/stdarch/ci/android-install-ndk.sh38
-rw-r--r--library/stdarch/ci/android-install-sdk.sh60
-rw-r--r--library/stdarch/ci/android-sysimage.sh56
-rw-r--r--library/stdarch/ci/docker/aarch64-linux-android/Dockerfile46
-rw-r--r--library/stdarch/ci/docker/arm-linux-androideabi/Dockerfile46
-rw-r--r--library/stdarch/ci/docker/x86_64-linux-android/Dockerfile29
-rw-r--r--library/stdarch/ci/runtest-android.rs45
-rw-r--r--library/stdarch/crates/assert-instr-macro/Cargo.toml2
-rw-r--r--library/stdarch/crates/assert-instr-macro/src/lib.rs8
-rw-r--r--library/stdarch/crates/core_arch/Cargo.toml2
-rw-r--r--library/stdarch/crates/core_arch/src/aarch64/neon/mod.rs174
-rw-r--r--library/stdarch/crates/core_arch/src/arm_shared/neon/generated.rs3090
-rw-r--r--library/stdarch/crates/core_arch/src/arm_shared/neon/mod.rs257
-rw-r--r--library/stdarch/crates/core_arch/src/mips/msa.rs4
-rw-r--r--library/stdarch/crates/core_arch/src/mod.rs2
-rw-r--r--library/stdarch/crates/core_arch/src/x86/avx.rs2
-rw-r--r--library/stdarch/crates/core_arch/src/x86/avx2.rs76
-rw-r--r--library/stdarch/crates/core_arch/src/x86/avx512bf16.rs2
-rw-r--r--library/stdarch/crates/core_arch/src/x86/avx512bitalg.rs12
-rw-r--r--library/stdarch/crates/core_arch/src/x86/avx512bw.rs28
-rw-r--r--library/stdarch/crates/core_arch/src/x86/avx512f.rs2
-rw-r--r--library/stdarch/crates/core_arch/src/x86/gfni.rs (renamed from library/stdarch/crates/core_arch/src/x86/avx512gfni.rs)114
-rw-r--r--library/stdarch/crates/core_arch/src/x86/mod.rs12
-rw-r--r--library/stdarch/crates/core_arch/src/x86/sse.rs5
-rw-r--r--library/stdarch/crates/core_arch/src/x86/sse2.rs32
-rw-r--r--library/stdarch/crates/core_arch/src/x86/sse41.rs48
-rw-r--r--library/stdarch/crates/core_arch/src/x86/sse42.rs8
-rw-r--r--library/stdarch/crates/core_arch/src/x86/vaes.rs (renamed from library/stdarch/crates/core_arch/src/x86/avx512vaes.rs)52
-rw-r--r--library/stdarch/crates/core_arch/src/x86/vpclmulqdq.rs (renamed from library/stdarch/crates/core_arch/src/x86/avx512vpclmulqdq.rs)12
-rw-r--r--library/stdarch/crates/core_arch/tests/cpu-detection.rs21
-rw-r--r--library/stdarch/crates/intrinsic-test/Cargo.toml4
-rw-r--r--library/stdarch/crates/intrinsic-test/missing_arm.txt11
-rw-r--r--library/stdarch/crates/intrinsic-test/src/acle_csv_parser.rs6
-rw-r--r--library/stdarch/crates/intrinsic-test/src/intrinsic.rs2
-rw-r--r--library/stdarch/crates/intrinsic-test/src/main.rs22
-rw-r--r--library/stdarch/crates/intrinsic-test/src/types.rs14
-rw-r--r--library/stdarch/crates/intrinsic-test/src/values.rs2
-rw-r--r--library/stdarch/crates/simd-test-macro/Cargo.toml2
-rw-r--r--library/stdarch/crates/simd-test-macro/src/lib.rs4
-rw-r--r--library/stdarch/crates/std_detect/Cargo.toml2
-rw-r--r--library/stdarch/crates/std_detect/src/detect/arch/x86.rs15
-rw-r--r--library/stdarch/crates/std_detect/src/detect/cache.rs2
-rw-r--r--library/stdarch/crates/std_detect/src/detect/macros.rs12
-rw-r--r--library/stdarch/crates/std_detect/src/detect/mod.rs2
-rw-r--r--library/stdarch/crates/std_detect/src/detect/os/linux/aarch64.rs6
-rw-r--r--library/stdarch/crates/std_detect/src/detect/os/linux/auxvec.rs8
-rw-r--r--library/stdarch/crates/std_detect/src/detect/os/linux/riscv.rs146
-rw-r--r--library/stdarch/crates/std_detect/src/detect/os/x86.rs6
-rw-r--r--library/stdarch/crates/std_detect/tests/cpu-detection.rs11
-rw-r--r--library/stdarch/crates/std_detect/tests/x86-specific.rs9
-rw-r--r--library/stdarch/crates/stdarch-gen/Cargo.toml2
-rw-r--r--library/stdarch/crates/stdarch-gen/src/main.rs322
-rw-r--r--library/stdarch/crates/stdarch-test/Cargo.toml2
-rw-r--r--library/stdarch/crates/stdarch-test/src/disassembly.rs8
-rw-r--r--library/stdarch/crates/stdarch-test/src/lib.rs10
-rw-r--r--library/stdarch/crates/stdarch-verify/Cargo.toml2
-rw-r--r--library/stdarch/crates/stdarch-verify/src/lib.rs14
-rw-r--r--library/stdarch/crates/stdarch-verify/tests/arm.rs6
-rw-r--r--library/stdarch/crates/stdarch-verify/tests/mips.rs8
-rw-r--r--library/stdarch/crates/stdarch-verify/tests/x86-intel.rs20
-rw-r--r--library/stdarch/examples/Cargo.toml2
-rw-r--r--library/stdarch/examples/connect5.rs2
-rw-r--r--library/stdarch/examples/hex.rs2
-rw-r--r--library/stdarch/triagebot.toml3
-rw-r--r--library/test/Cargo.toml2
-rw-r--r--library/test/src/cli.rs3
-rw-r--r--library/test/src/console.rs7
-rw-r--r--library/test/src/formatters/terse.rs9
-rw-r--r--library/test/src/lib.rs2
-rw-r--r--library/test/src/tests.rs1
-rw-r--r--library/unwind/src/lib.rs4
-rw-r--r--library/unwind/src/libunwind.rs2
-rw-r--r--src/bootstrap/Cargo.lock4
-rw-r--r--src/bootstrap/Cargo.toml5
-rw-r--r--src/bootstrap/README.md199
-rw-r--r--src/bootstrap/bin/main.rs36
-rw-r--r--src/bootstrap/bootstrap.py252
-rw-r--r--src/bootstrap/builder.rs20
-rw-r--r--src/bootstrap/builder/tests.rs2
-rw-r--r--src/bootstrap/check.rs95
-rw-r--r--src/bootstrap/clean.rs1
-rw-r--r--src/bootstrap/compile.rs130
-rw-r--r--src/bootstrap/config.rs28
-rw-r--r--src/bootstrap/config/tests.rs12
-rwxr-xr-xsrc/bootstrap/configure.py28
-rw-r--r--src/bootstrap/defaults/config.compiler.toml2
-rw-r--r--src/bootstrap/defaults/config.library.toml2
-rw-r--r--src/bootstrap/dist.rs33
-rw-r--r--src/bootstrap/doc.rs38
-rw-r--r--src/bootstrap/download.rs168
-rw-r--r--src/bootstrap/flags.rs34
-rw-r--r--src/bootstrap/format.rs60
-rw-r--r--src/bootstrap/install.rs12
-rw-r--r--src/bootstrap/lib.rs143
-rw-r--r--src/bootstrap/metadata.rs2
-rw-r--r--src/bootstrap/metrics.rs2
-rw-r--r--src/bootstrap/native.rs117
-rw-r--r--src/bootstrap/run.rs1
-rw-r--r--src/bootstrap/setup.rs268
-rw-r--r--src/bootstrap/setup/tests.rs14
-rw-r--r--src/bootstrap/test.rs25
-rw-r--r--src/bootstrap/tool.rs72
-rw-r--r--src/bootstrap/toolstate.rs2
-rw-r--r--src/ci/docker/host-x86_64/dist-s390x-linux/Dockerfile2
-rw-r--r--src/ci/docker/host-x86_64/dist-x86_64-linux/Dockerfile2
-rw-r--r--src/ci/docker/host-x86_64/mingw-check/Dockerfile4
-rwxr-xr-xsrc/ci/docker/host-x86_64/mingw-check/validate-toolstate.sh6
-rw-r--r--src/ci/docker/host-x86_64/x86_64-gnu-llvm-13-stage1/Dockerfile49
-rw-r--r--src/ci/docker/host-x86_64/x86_64-gnu-llvm-14-stage1/Dockerfile49
-rw-r--r--src/ci/docker/host-x86_64/x86_64-gnu-llvm-14/Dockerfile (renamed from src/ci/docker/host-x86_64/x86_64-gnu-llvm-13/Dockerfile)22
-rw-r--r--src/ci/docker/host-x86_64/x86_64-gnu-llvm-15/Dockerfile67
-rw-r--r--src/ci/docker/host-x86_64/x86_64-gnu-tools/browser-ui-test.version2
-rwxr-xr-xsrc/ci/docker/scripts/fuchsia-test-runner.py172
-rw-r--r--src/ci/github-actions/ci.yml34
-rwxr-xr-xsrc/ci/pgo.sh230
-rwxr-xr-xsrc/ci/run.sh10
-rwxr-xr-xsrc/ci/scripts/install-mingw.sh23
-rwxr-xr-xsrc/ci/scripts/should-skip-this.sh37
-rw-r--r--src/ci/stage-build.py842
-rw-r--r--src/doc/book/.github/workflows/main.yml4
-rw-r--r--src/doc/book/CONTRIBUTING.md4
-rw-r--r--src/doc/book/README.md4
-rw-r--r--src/doc/book/ci/dictionary.txt1
-rw-r--r--src/doc/book/listings/ch02-guessing-game-tutorial/listing-02-04/output.txt1
-rw-r--r--src/doc/book/listings/ch02-guessing-game-tutorial/no-listing-02-without-expect/output.txt4
-rw-r--r--src/doc/book/listings/ch03-common-programming-concepts/no-listing-23-statements-dont-return-values/output.txt2
-rw-r--r--src/doc/book/listings/ch04-understanding-ownership/no-listing-04-cant-use-after-move/output.txt4
-rw-r--r--src/doc/book/listings/ch06-enums-and-pattern-matching/no-listing-07-cant-use-option-directly/output.txt11
-rw-r--r--src/doc/book/listings/ch06-enums-and-pattern-matching/no-listing-10-non-exhaustive-match/output.txt4
-rw-r--r--src/doc/book/listings/ch07-managing-growing-projects/listing-07-12/output.txt12
-rw-r--r--src/doc/book/listings/ch08-common-collections/listing-08-19/output.txt1
-rw-r--r--src/doc/book/listings/ch11-writing-automated-tests/listing-11-03/output.txt2
-rw-r--r--src/doc/book/listings/ch11-writing-automated-tests/listing-11-10/output.txt2
-rw-r--r--src/doc/book/listings/ch11-writing-automated-tests/no-listing-03-introducing-a-bug/output.txt2
-rw-r--r--src/doc/book/listings/ch11-writing-automated-tests/no-listing-04-bug-in-add-two/output.txt2
-rw-r--r--src/doc/book/listings/ch11-writing-automated-tests/no-listing-06-greeter-with-bug/output.txt2
-rw-r--r--src/doc/book/listings/ch11-writing-automated-tests/no-listing-07-custom-failure-message/output.txt2
-rw-r--r--src/doc/book/listings/ch11-writing-automated-tests/no-listing-09-guess-with-panic-msg-bug/output.txt2
-rw-r--r--src/doc/book/listings/ch11-writing-automated-tests/output-only-01-show-output/output.txt2
-rw-r--r--src/doc/book/listings/ch12-an-io-project/listing-12-12/output.txt4
-rw-r--r--src/doc/book/listings/ch12-an-io-project/listing-12-16/output.txt2
-rw-r--r--src/doc/book/listings/ch13-functional-features/listing-13-14/output.txt4
-rw-r--r--src/doc/book/listings/ch15-smart-pointers/listing-15-03/output.txt4
-rw-r--r--src/doc/book/listings/ch15-smart-pointers/listing-15-23/output.txt2
-rw-r--r--src/doc/book/listings/ch16-fearless-concurrency/listing-16-14/output.txt3
-rw-r--r--src/doc/book/listings/ch18-patterns-and-matching/listing-18-08/output.txt8
-rw-r--r--src/doc/book/listings/ch18-patterns-and-matching/listing-18-10/output.txt2
-rw-r--r--src/doc/book/listings/ch19-advanced-features/listing-19-20/output.txt4
-rw-r--r--src/doc/book/listings/ch20-web-server/listing-20-22/output.txt1
-rw-r--r--src/doc/book/listings/ch20-web-server/no-listing-04-update-worker-definition/output.txt1
-rw-r--r--src/doc/book/rust-toolchain2
-rw-r--r--src/doc/book/src/ch00-00-introduction.md2
-rw-r--r--src/doc/book/src/ch03-01-variables-and-mutability.md2
-rw-r--r--src/doc/book/src/ch10-01-syntax.md8
-rw-r--r--src/doc/book/src/title-page.md4
-rw-r--r--src/doc/embedded-book/src/assets/verify.jpegbin155671 -> 100961 bytes
-rw-r--r--src/doc/embedded-book/src/collections/index.md9
-rw-r--r--src/doc/embedded-book/src/interoperability/c-with-rust.md2
-rw-r--r--src/doc/embedded-book/src/intro/install/macos.md20
-rw-r--r--src/doc/embedded-book/src/intro/install/verify.md2
-rw-r--r--src/doc/embedded-book/src/peripherals/singletons.md3
-rw-r--r--src/doc/embedded-book/src/start/registers.md2
-rw-r--r--src/doc/index.md228
-rw-r--r--src/doc/nomicon/src/dropck.md2
-rw-r--r--src/doc/nomicon/src/ffi.md21
-rw-r--r--src/doc/nomicon/src/send-and-sync.md5
-rw-r--r--src/doc/nomicon/src/subtyping.md2
-rw-r--r--src/doc/reference/src/behavior-considered-undefined.md2
-rw-r--r--src/doc/reference/src/destructors.md2
-rw-r--r--src/doc/reference/src/expressions/if-expr.md2
-rw-r--r--src/doc/reference/src/expressions/operator-expr.md2
-rw-r--r--src/doc/reference/src/items/external-blocks.md2
-rw-r--r--src/doc/reference/src/linkage.md2
-rw-r--r--src/doc/reference/src/patterns.md47
-rw-r--r--src/doc/reference/src/trait-bounds.md2
-rw-r--r--src/doc/rust-by-example/src/error/option_unwrap/and_then.md5
-rw-r--r--src/doc/rust-by-example/src/error/result/result_map.md2
-rw-r--r--src/doc/rust-by-example/src/generics/bounds.md4
-rw-r--r--src/doc/rust-by-example/src/hello/comment.md2
-rw-r--r--src/doc/rust-by-example/src/index.md2
-rw-r--r--src/doc/rust-by-example/src/primitives/tuples.md2
-rw-r--r--src/doc/rust-by-example/src/std_misc/file/create.md2
-rw-r--r--src/doc/rustc-dev-guide/.github/workflows/ci.yml5
-rw-r--r--src/doc/rustc-dev-guide/CITATION.cff9
-rw-r--r--src/doc/rustc-dev-guide/README.md2
-rw-r--r--src/doc/rustc-dev-guide/book.toml12
-rw-r--r--src/doc/rustc-dev-guide/ci/date-check/src/main.rs2
-rw-r--r--src/doc/rustc-dev-guide/examples/README11
-rw-r--r--src/doc/rustc-dev-guide/examples/rustc-driver-example.rs19
-rw-r--r--src/doc/rustc-dev-guide/examples/rustc-driver-getting-diagnostics.rs9
-rw-r--r--src/doc/rustc-dev-guide/examples/rustc-driver-interacting-with-the-ast.rs14
-rw-r--r--src/doc/rustc-dev-guide/src/SUMMARY.md16
-rw-r--r--src/doc/rustc-dev-guide/src/appendix/glossary.md4
-rw-r--r--src/doc/rustc-dev-guide/src/asm.md2
-rw-r--r--src/doc/rustc-dev-guide/src/ast-validation.md36
-rw-r--r--src/doc/rustc-dev-guide/src/backend/backend-agnostic.md23
-rw-r--r--src/doc/rustc-dev-guide/src/backend/monomorph.md2
-rw-r--r--src/doc/rustc-dev-guide/src/backend/updating-llvm.md17
-rw-r--r--src/doc/rustc-dev-guide/src/borrow_check/region_inference/lifetime_parameters.md4
-rw-r--r--src/doc/rustc-dev-guide/src/building/bootstrapping.md124
-rw-r--r--src/doc/rustc-dev-guide/src/building/how-to-build-and-run.md15
-rw-r--r--src/doc/rustc-dev-guide/src/building/prerequisites.md2
-rw-r--r--src/doc/rustc-dev-guide/src/building/suggested.md96
-rw-r--r--src/doc/rustc-dev-guide/src/closure.md2
-rw-r--r--src/doc/rustc-dev-guide/src/compiler-debugging.md37
-rw-r--r--src/doc/rustc-dev-guide/src/compiler-src.md4
-rw-r--r--src/doc/rustc-dev-guide/src/constants.md2
-rw-r--r--src/doc/rustc-dev-guide/src/contributing.md10
-rw-r--r--src/doc/rustc-dev-guide/src/crates-io.md7
-rw-r--r--src/doc/rustc-dev-guide/src/diagnostics.md17
-rw-r--r--src/doc/rustc-dev-guide/src/diagnostics/diagnostic-items.md2
-rw-r--r--src/doc/rustc-dev-guide/src/diagnostics/diagnostic-structs.md4
-rw-r--r--src/doc/rustc-dev-guide/src/diagnostics/translation.md2
-rw-r--r--src/doc/rustc-dev-guide/src/getting-started.md6
-rw-r--r--src/doc/rustc-dev-guide/src/git.md18
-rw-r--r--src/doc/rustc-dev-guide/src/hir.md4
-rw-r--r--src/doc/rustc-dev-guide/src/identifiers.md2
-rw-r--r--src/doc/rustc-dev-guide/src/implementing_new_features.md2
-rw-r--r--src/doc/rustc-dev-guide/src/llvm-coverage-instrumentation.md17
-rw-r--r--src/doc/rustc-dev-guide/src/mir/debugging.md4
-rw-r--r--src/doc/rustc-dev-guide/src/mir/visitor.md6
-rw-r--r--src/doc/rustc-dev-guide/src/overview.md2
-rw-r--r--src/doc/rustc-dev-guide/src/profiling/with_perf.md11
-rw-r--r--src/doc/rustc-dev-guide/src/rustc-driver-getting-diagnostics.md30
-rw-r--r--src/doc/rustc-dev-guide/src/rustc-driver-interacting-with-the-ast.md41
-rw-r--r--src/doc/rustc-dev-guide/src/rustc-driver.md2
-rw-r--r--src/doc/rustc-dev-guide/src/solve/canonicalization.md84
-rw-r--r--src/doc/rustc-dev-guide/src/solve/coinduction.md250
-rw-r--r--src/doc/rustc-dev-guide/src/solve/the-solver.md17
-rw-r--r--src/doc/rustc-dev-guide/src/solve/trait-solving.md114
-rw-r--r--src/doc/rustc-dev-guide/src/tests/compiletest.md5
-rw-r--r--src/doc/rustc-dev-guide/src/tests/running.md21
-rw-r--r--src/doc/rustc-dev-guide/src/traits/resolution.md4
-rw-r--r--src/doc/rustc-dev-guide/src/ty.md80
-rw-r--r--src/doc/rustc-dev-guide/src/type-checking.md10
-rw-r--r--src/doc/rustc-dev-guide/src/type-inference.md12
-rw-r--r--src/doc/rustc/book.toml1
-rw-r--r--src/doc/rustc/src/codegen-options/index.md66
-rw-r--r--src/doc/rustc/src/json.md1
-rw-r--r--src/doc/rustc/src/platform-support.md6
-rw-r--r--src/doc/rustc/src/platform-support/fuchsia.md98
-rw-r--r--src/doc/rustc/src/platform-support/nto-qnx.md175
-rw-r--r--src/doc/rustdoc/src/how-to-read-rustdoc.md3
-rw-r--r--src/doc/style-guide/src/cargo.md3
-rw-r--r--src/doc/style-guide/src/statements.md78
-rw-r--r--src/doc/unstable-book/src/compiler-flags/export-executable-symbols.md43
-rw-r--r--src/doc/unstable-book/src/compiler-flags/instrument-xray.md39
-rw-r--r--src/doc/unstable-book/src/compiler-flags/sanitizer.md20
-rw-r--r--src/doc/unstable-book/src/compiler-flags/tiny-const-eval-limit.md6
-rw-r--r--src/doc/unstable-book/src/library-features/char-error-internals.md5
-rw-r--r--src/doc/unstable-book/src/library-features/int-error-internals.md5
-rwxr-xr-xsrc/etc/pre-push.sh2
-rw-r--r--src/etc/vscode_settings.json28
-rw-r--r--src/librustdoc/Cargo.toml2
-rw-r--r--src/librustdoc/clean/auto_trait.rs6
-rw-r--r--src/librustdoc/clean/blanket_impl.rs2
-rw-r--r--src/librustdoc/clean/cfg.rs8
-rw-r--r--src/librustdoc/clean/cfg/tests.rs5
-rw-r--r--src/librustdoc/clean/inline.rs64
-rw-r--r--src/librustdoc/clean/mod.rs476
-rw-r--r--src/librustdoc/clean/render_macro_matchers.rs3
-rw-r--r--src/librustdoc/clean/types.rs248
-rw-r--r--src/librustdoc/clean/types/tests.rs1
-rw-r--r--src/librustdoc/clean/utils.rs23
-rw-r--r--src/librustdoc/config.rs2
-rw-r--r--src/librustdoc/core.rs80
-rw-r--r--src/librustdoc/doctest.rs117
-rw-r--r--src/librustdoc/formats/cache.rs41
-rw-r--r--src/librustdoc/formats/item_type.rs3
-rw-r--r--src/librustdoc/html/format.rs98
-rw-r--r--src/librustdoc/html/highlight.rs30
-rw-r--r--src/librustdoc/html/layout.rs1
-rw-r--r--src/librustdoc/html/length_limit.rs4
-rw-r--r--src/librustdoc/html/length_limit/tests.rs2
-rw-r--r--src/librustdoc/html/markdown.rs209
-rw-r--r--src/librustdoc/html/markdown/tests.rs2
-rw-r--r--src/librustdoc/html/render/context.rs43
-rw-r--r--src/librustdoc/html/render/mod.rs166
-rw-r--r--src/librustdoc/html/render/print_item.rs672
-rw-r--r--src/librustdoc/html/render/search_index.rs11
-rw-r--r--src/librustdoc/html/render/write_shared.rs5
-rw-r--r--src/librustdoc/html/sources.rs3
-rw-r--r--src/librustdoc/html/static/.eslintrc.js1
-rw-r--r--src/librustdoc/html/static/css/rustdoc.css148
-rw-r--r--src/librustdoc/html/static/css/settings.css30
-rw-r--r--src/librustdoc/html/static/css/themes/ayu.css77
-rw-r--r--src/librustdoc/html/static/css/themes/dark.css26
-rw-r--r--src/librustdoc/html/static/css/themes/light.css26
-rw-r--r--src/librustdoc/html/static/fonts/SourceSerif4-Bold.ttf.woff2bin81320 -> 81540 bytes
-rw-r--r--src/librustdoc/html/static/fonts/SourceSerif4-It.ttf.woff2bin59860 -> 59716 bytes
-rw-r--r--src/librustdoc/html/static/fonts/SourceSerif4-LICENSE.md2
-rw-r--r--src/librustdoc/html/static/fonts/SourceSerif4-Regular.ttf.woff2bin76180 -> 76260 bytes
-rw-r--r--src/librustdoc/html/static/images/down-arrow.svg1
-rw-r--r--src/librustdoc/html/static/images/toggle-minus.svg1
-rw-r--r--src/librustdoc/html/static/images/toggle-plus.svg1
-rw-r--r--src/librustdoc/html/static/images/wheel.svg2
-rw-r--r--src/librustdoc/html/static/js/main.js125
-rw-r--r--src/librustdoc/html/static/js/search.js355
-rw-r--r--src/librustdoc/html/static/js/settings.js55
-rw-r--r--src/librustdoc/html/static/js/source-script.js3
-rw-r--r--src/librustdoc/html/static/js/storage.js113
-rw-r--r--src/librustdoc/html/static_files.rs3
-rw-r--r--src/librustdoc/html/templates/page.html3
-rw-r--r--src/librustdoc/html/templates/print_item.html2
-rw-r--r--src/librustdoc/json/conversions.rs99
-rw-r--r--src/librustdoc/json/import_finder.rs10
-rw-r--r--src/librustdoc/json/mod.rs34
-rw-r--r--src/librustdoc/lib.rs40
-rw-r--r--src/librustdoc/lint.rs6
-rw-r--r--src/librustdoc/markdown.rs9
-rw-r--r--src/librustdoc/passes/calculate_doc_coverage.rs8
-rw-r--r--src/librustdoc/passes/check_doc_test_visibility.rs38
-rw-r--r--src/librustdoc/passes/collect_intra_doc_links.rs313
-rw-r--r--src/librustdoc/passes/collect_intra_doc_links/early.rs407
-rw-r--r--src/librustdoc/passes/collect_trait_impls.rs91
-rw-r--r--src/librustdoc/passes/lint/check_code_block_syntax.rs11
-rw-r--r--src/librustdoc/passes/lint/html_tags.rs10
-rw-r--r--src/librustdoc/passes/mod.rs3
-rw-r--r--src/librustdoc/passes/propagate_doc_cfg.rs17
-rw-r--r--src/librustdoc/passes/strip_hidden.rs117
-rw-r--r--src/librustdoc/passes/stripper.rs32
-rw-r--r--src/librustdoc/scrape_examples.rs2
-rw-r--r--src/librustdoc/visit_ast.rs275
-rw-r--r--src/librustdoc/visit_lib.rs9
-rw-r--r--src/stage0.json580
-rw-r--r--src/tools/build_helper/src/git.rs72
-rw-r--r--src/tools/bump-stage0/src/main.rs2
-rw-r--r--src/tools/clippy/.github/workflows/clippy_bors.yml5
-rw-r--r--src/tools/clippy/CHANGELOG.md207
-rw-r--r--src/tools/clippy/Cargo.toml3
-rw-r--r--src/tools/clippy/README.md57
-rw-r--r--src/tools/clippy/book/src/README.md2
-rw-r--r--src/tools/clippy/book/src/SUMMARY.md1
-rw-r--r--src/tools/clippy/book/src/configuration.md16
-rw-r--r--src/tools/clippy/book/src/development/adding_lints.md7
-rw-r--r--src/tools/clippy/book/src/development/infrastructure/backport.md1
-rw-r--r--src/tools/clippy/book/src/development/infrastructure/book.md14
-rw-r--r--src/tools/clippy/book/src/development/infrastructure/changelog_update.md16
-rw-r--r--src/tools/clippy/book/src/development/infrastructure/sync.md3
-rw-r--r--src/tools/clippy/book/src/lint_configuration.md553
-rw-r--r--src/tools/clippy/clippy_dev/Cargo.toml2
-rw-r--r--src/tools/clippy/clippy_dev/src/main.rs127
-rw-r--r--src/tools/clippy/clippy_dev/src/new_lint.rs9
-rw-r--r--src/tools/clippy/clippy_dev/src/update_lints.rs6
-rw-r--r--src/tools/clippy/clippy_lints/Cargo.toml4
-rw-r--r--src/tools/clippy/clippy_lints/src/bool_assert_comparison.rs90
-rw-r--r--src/tools/clippy/clippy_lints/src/booleans.rs5
-rw-r--r--src/tools/clippy/clippy_lints/src/box_default.rs3
-rw-r--r--src/tools/clippy/clippy_lints/src/casts/as_ptr_cast_mut.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/casts/cast_possible_truncation.rs32
-rw-r--r--src/tools/clippy/clippy_lints/src/casts/cast_ptr_alignment.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/casts/mod.rs20
-rw-r--r--src/tools/clippy/clippy_lints/src/cognitive_complexity.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/copy_iterator.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/declared_lints.rs9
-rw-r--r--src/tools/clippy/clippy_lints/src/default.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/default_numeric_fallback.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/dereference.rs105
-rw-r--r--src/tools/clippy/clippy_lints/src/derivable_impls.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/derive.rs11
-rw-r--r--src/tools/clippy/clippy_lints/src/doc.rs45
-rw-r--r--src/tools/clippy/clippy_lints/src/empty_enum.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/entry.rs12
-rw-r--r--src/tools/clippy/clippy_lints/src/enum_clike.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/enum_variants.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/escape.rs12
-rw-r--r--src/tools/clippy/clippy_lints/src/eta_reduction.rs8
-rw-r--r--src/tools/clippy/clippy_lints/src/excessive_bools.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/exhaustive_items.rs3
-rw-r--r--src/tools/clippy/clippy_lints/src/extra_unused_type_parameters.rs229
-rw-r--r--src/tools/clippy/clippy_lints/src/format_args.rs11
-rw-r--r--src/tools/clippy/clippy_lints/src/from_raw_with_void_ptr.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/functions/impl_trait_in_params.rs50
-rw-r--r--src/tools/clippy/clippy_lints/src/functions/misnamed_getters.rs11
-rw-r--r--src/tools/clippy/clippy_lints/src/functions/mod.rs37
-rw-r--r--src/tools/clippy/clippy_lints/src/functions/must_use.rs22
-rw-r--r--src/tools/clippy/clippy_lints/src/functions/not_unsafe_ptr_arg_deref.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/functions/result.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/future_not_send.rs9
-rw-r--r--src/tools/clippy/clippy_lints/src/implicit_return.rs3
-rw-r--r--src/tools/clippy/clippy_lints/src/implicit_saturating_sub.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/inconsistent_struct_constructor.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/indexing_slicing.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/inherent_impl.rs3
-rw-r--r--src/tools/clippy/clippy_lints/src/inherent_to_string.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/instant_subtraction.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/iter_not_returning_iterator.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/large_const_arrays.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/large_enum_variant.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/large_stack_arrays.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/len_zero.rs23
-rw-r--r--src/tools/clippy/clippy_lints/src/let_underscore.rs54
-rw-r--r--src/tools/clippy/clippy_lints/src/lib.rs20
-rw-r--r--src/tools/clippy/clippy_lints/src/lifetimes.rs268
-rw-r--r--src/tools/clippy/clippy_lints/src/literal_representation.rs12
-rw-r--r--src/tools/clippy/clippy_lints/src/loops/explicit_iter_loop.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/loops/mod.rs3
-rw-r--r--src/tools/clippy/clippy_lints/src/loops/needless_range_loop.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/loops/never_loop.rs61
-rw-r--r--src/tools/clippy/clippy_lints/src/manual_assert.rs97
-rw-r--r--src/tools/clippy/clippy_lints/src/manual_async_fn.rs5
-rw-r--r--src/tools/clippy/clippy_lints/src/manual_is_ascii_check.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/manual_let_else.rs153
-rw-r--r--src/tools/clippy/clippy_lints/src/manual_non_exhaustive.rs5
-rw-r--r--src/tools/clippy/clippy_lints/src/map_unit_fn.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/matches/match_wild_enum.rs13
-rw-r--r--src/tools/clippy/clippy_lints/src/matches/rest_pat_in_fully_bound_struct.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/matches/significant_drop_in_scrutinee.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/bytes_count_to_len.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/bytes_nth.rs42
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/case_sensitive_file_extension_comparisons.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/collapsible_str_replace.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/expect_fun_call.rs8
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/expect_used.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/get_first.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/implicit_clone.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/manual_ok_or.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/map_clone.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/map_err_ignore.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/mod.rs44
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/mut_mutex_lock.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/needless_collect.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/open_options.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/path_buf_push_overwrite.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/search_is_some.rs3
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/single_char_pattern.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/stable_sort_primitive.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/string_extend_chars.rs3
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/suspicious_command_arg_space.rs39
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/suspicious_map.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/suspicious_splitn.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/suspicious_to_owned.rs22
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/unnecessary_sort_by.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs13
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/unwrap_used.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/utils.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/vec_resize_to_zero.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/misc.rs7
-rw-r--r--src/tools/clippy/clippy_lints/src/missing_const_for_fn.rs9
-rw-r--r--src/tools/clippy/clippy_lints/src/missing_doc.rs32
-rw-r--r--src/tools/clippy/clippy_lints/src/missing_trait_methods.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/module_style.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/multiple_unsafe_ops_per_block.rs186
-rw-r--r--src/tools/clippy/clippy_lints/src/mut_key.rs17
-rw-r--r--src/tools/clippy/clippy_lints/src/mut_reference.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs13
-rw-r--r--src/tools/clippy/clippy_lints/src/new_without_default.rs14
-rw-r--r--src/tools/clippy/clippy_lints/src/no_mangle_with_rust_abi.rs65
-rw-r--r--src/tools/clippy/clippy_lints/src/non_copy_const.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/only_used_in_recursion.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/operators/arithmetic_side_effects.rs36
-rw-r--r--src/tools/clippy/clippy_lints/src/operators/cmp_owned.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/operators/numeric_arithmetic.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/option_if_let_else.rs10
-rw-r--r--src/tools/clippy/clippy_lints/src/panic_in_result_fn.rs9
-rw-r--r--src/tools/clippy/clippy_lints/src/pass_by_ref_or_value.rs9
-rw-r--r--src/tools/clippy/clippy_lints/src/pattern_type_mismatch.rs7
-rw-r--r--src/tools/clippy/clippy_lints/src/ptr.rs13
-rw-r--r--src/tools/clippy/clippy_lints/src/question_mark_used.rs52
-rw-r--r--src/tools/clippy/clippy_lints/src/redundant_clone.rs9
-rw-r--r--src/tools/clippy/clippy_lints/src/redundant_slicing.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/regex.rs89
-rw-r--r--src/tools/clippy/clippy_lints/src/return_self_not_must_use.rs18
-rw-r--r--src/tools/clippy/clippy_lints/src/returns.rs142
-rw-r--r--src/tools/clippy/clippy_lints/src/same_name_method.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/self_named_constructors.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/semicolon_block.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/significant_drop_tightening.rs423
-rw-r--r--src/tools/clippy/clippy_lints/src/strings.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/suspicious_xor_used_as_pow.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/swap.rs107
-rw-r--r--src/tools/clippy/clippy_lints/src/trailing_empty_array.rs5
-rw-r--r--src/tools/clippy/clippy_lints/src/transmute/mod.rs35
-rw-r--r--src/tools/clippy/clippy_lints/src/transmute/transmute_int_to_non_zero.rs61
-rw-r--r--src/tools/clippy/clippy_lints/src/transmute/transmute_ptr_to_ref.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/transmute/transmute_ref_to_ref.rs3
-rw-r--r--src/tools/clippy/clippy_lints/src/transmute/transmute_undefined_repr.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/transmute/transmutes_expressible_as_ptr_casts.rs58
-rw-r--r--src/tools/clippy/clippy_lints/src/transmute/useless_transmute.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/transmute/utils.rs26
-rw-r--r--src/tools/clippy/clippy_lints/src/types/mod.rs35
-rw-r--r--src/tools/clippy/clippy_lints/src/types/redundant_allocation.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/types/vec_box.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/undocumented_unsafe_blocks.rs12
-rw-r--r--src/tools/clippy/clippy_lints/src/unit_return_expecting_ord.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/unit_types/let_unit_value.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/unnecessary_owned_empty_strings.rs3
-rw-r--r--src/tools/clippy/clippy_lints/src/unnecessary_wraps.rs26
-rw-r--r--src/tools/clippy/clippy_lints/src/unnested_or_patterns.rs50
-rw-r--r--src/tools/clippy/clippy_lints/src/unused_async.rs7
-rw-r--r--src/tools/clippy/clippy_lints/src/unused_io_amount.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/unwrap.rs3
-rw-r--r--src/tools/clippy/clippy_lints/src/unwrap_in_result.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/use_self.rs8
-rw-r--r--src/tools/clippy/clippy_lints/src/useless_conversion.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/utils/author.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/utils/conf.rs26
-rw-r--r--src/tools/clippy/clippy_lints/src/utils/dump_hir.rs13
-rw-r--r--src/tools/clippy/clippy_lints/src/utils/internal_lints/interning_defined_symbol.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/utils/internal_lints/lint_without_lint_pass.rs15
-rw-r--r--src/tools/clippy/clippy_lints/src/utils/internal_lints/metadata_collector.rs79
-rw-r--r--src/tools/clippy/clippy_lints/src/utils/internal_lints/msrv_attr_impl.rs1
-rw-r--r--src/tools/clippy/clippy_lints/src/utils/internal_lints/unnecessary_def_path.rs8
-rw-r--r--src/tools/clippy/clippy_lints/src/zero_sized_map_values.rs2
-rw-r--r--src/tools/clippy/clippy_utils/Cargo.toml2
-rw-r--r--src/tools/clippy/clippy_utils/src/ast_utils.rs3
-rw-r--r--src/tools/clippy/clippy_utils/src/consts.rs10
-rw-r--r--src/tools/clippy/clippy_utils/src/eager_or_lazy.rs8
-rw-r--r--src/tools/clippy/clippy_utils/src/higher.rs13
-rw-r--r--src/tools/clippy/clippy_utils/src/hir_utils.rs4
-rw-r--r--src/tools/clippy/clippy_utils/src/lib.rs30
-rw-r--r--src/tools/clippy/clippy_utils/src/macros.rs76
-rw-r--r--src/tools/clippy/clippy_utils/src/mir/possible_borrower.rs6
-rw-r--r--src/tools/clippy/clippy_utils/src/numeric_literal.rs2
-rw-r--r--src/tools/clippy/clippy_utils/src/paths.rs1
-rw-r--r--src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs7
-rw-r--r--src/tools/clippy/clippy_utils/src/sugg.rs22
-rw-r--r--src/tools/clippy/clippy_utils/src/ty.rs56
-rw-r--r--src/tools/clippy/clippy_utils/src/visitors.rs10
-rw-r--r--src/tools/clippy/declare_clippy_lint/Cargo.toml2
-rw-r--r--src/tools/clippy/lintcheck/Cargo.toml4
-rw-r--r--src/tools/clippy/lintcheck/src/config.rs2
-rw-r--r--src/tools/clippy/lintcheck/src/main.rs12
-rw-r--r--src/tools/clippy/rust-toolchain2
-rw-r--r--src/tools/clippy/src/driver.rs3
-rw-r--r--src/tools/clippy/src/main.rs2
-rw-r--r--src/tools/clippy/tests/ui-internal/custom_ice_message.rs3
-rw-r--r--src/tools/clippy/tests/ui-internal/custom_ice_message.stderr4
-rw-r--r--src/tools/clippy/tests/ui-toml/expect_used/expect_used.rs12
-rw-r--r--src/tools/clippy/tests/ui-toml/pub_crate_missing_docs/clippy.toml1
-rw-r--r--src/tools/clippy/tests/ui-toml/pub_crate_missing_docs/pub_crate_missing_doc.rs59
-rw-r--r--src/tools/clippy/tests/ui-toml/pub_crate_missing_docs/pub_crate_missing_doc.stderr52
-rw-r--r--src/tools/clippy/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr1
-rw-r--r--src/tools/clippy/tests/ui-toml/unwrap_used/unwrap_used.rs6
-rw-r--r--src/tools/clippy/tests/ui-toml/unwrap_used/unwrap_used.stderr10
-rw-r--r--src/tools/clippy/tests/ui/arithmetic_side_effects.rs27
-rw-r--r--src/tools/clippy/tests/ui/arithmetic_side_effects.stderr198
-rw-r--r--src/tools/clippy/tests/ui/auxiliary/macro_rules.rs19
-rw-r--r--src/tools/clippy/tests/ui/bool_assert_comparison.fixed171
-rw-r--r--src/tools/clippy/tests/ui/bool_assert_comparison.rs53
-rw-r--r--src/tools/clippy/tests/ui/bool_assert_comparison.stderr353
-rw-r--r--src/tools/clippy/tests/ui/box_default.fixed18
-rw-r--r--src/tools/clippy/tests/ui/box_default.rs18
-rw-r--r--src/tools/clippy/tests/ui/box_default.stderr14
-rw-r--r--src/tools/clippy/tests/ui/bytes_nth.fixed6
-rw-r--r--src/tools/clippy/tests/ui/bytes_nth.rs2
-rw-r--r--src/tools/clippy/tests/ui/bytes_nth.stderr10
-rw-r--r--src/tools/clippy/tests/ui/cast.rs1
-rw-r--r--src/tools/clippy/tests/ui/cast.stderr163
-rw-r--r--src/tools/clippy/tests/ui/cast_size.stderr53
-rw-r--r--src/tools/clippy/tests/ui/crashes/ice-2774.stderr5
-rw-r--r--src/tools/clippy/tests/ui/crashes/ice-rust-107877.rs17
-rw-r--r--src/tools/clippy/tests/ui/crashes/needless_lifetimes_impl_trait.stderr5
-rw-r--r--src/tools/clippy/tests/ui/crashes/needless_pass_by_value-w-late-bound.rs9
-rw-r--r--src/tools/clippy/tests/ui/crashes/needless_pass_by_value-w-late-bound.stderr15
-rw-r--r--src/tools/clippy/tests/ui/doc/doc-fixable.fixed2
-rw-r--r--src/tools/clippy/tests/ui/doc/doc-fixable.rs4
-rw-r--r--src/tools/clippy/tests/ui/doc/doc-fixable.stderr24
-rw-r--r--src/tools/clippy/tests/ui/entry.fixed14
-rw-r--r--src/tools/clippy/tests/ui/entry.rs14
-rw-r--r--src/tools/clippy/tests/ui/explicit_auto_deref.fixed14
-rw-r--r--src/tools/clippy/tests/ui/explicit_auto_deref.rs14
-rw-r--r--src/tools/clippy/tests/ui/extra_unused_type_parameters.rs110
-rw-r--r--src/tools/clippy/tests/ui/extra_unused_type_parameters.stderr75
-rw-r--r--src/tools/clippy/tests/ui/format.fixed6
-rw-r--r--src/tools/clippy/tests/ui/format.rs6
-rw-r--r--src/tools/clippy/tests/ui/format.stderr30
-rw-r--r--src/tools/clippy/tests/ui/impl_trait_in_params.rs17
-rw-r--r--src/tools/clippy/tests/ui/impl_trait_in_params.stderr25
-rw-r--r--src/tools/clippy/tests/ui/large_digit_groups.fixed4
-rw-r--r--src/tools/clippy/tests/ui/large_digit_groups.stderr20
-rw-r--r--src/tools/clippy/tests/ui/len_without_is_empty.rs46
-rw-r--r--src/tools/clippy/tests/ui/let_underscore_untyped.rs54
-rw-r--r--src/tools/clippy/tests/ui/let_underscore_untyped.stderr51
-rw-r--r--src/tools/clippy/tests/ui/literals.stderr10
-rw-r--r--src/tools/clippy/tests/ui/manual_assert.edition2018.fixed35
-rw-r--r--src/tools/clippy/tests/ui/manual_assert.edition2018.stderr67
-rw-r--r--src/tools/clippy/tests/ui/manual_let_else.rs11
-rw-r--r--src/tools/clippy/tests/ui/manual_let_else_match.rs29
-rw-r--r--src/tools/clippy/tests/ui/manual_let_else_match.stderr15
-rw-r--r--src/tools/clippy/tests/ui/map_flatten_fixable.fixed1
-rw-r--r--src/tools/clippy/tests/ui/map_flatten_fixable.rs1
-rw-r--r--src/tools/clippy/tests/ui/map_flatten_fixable.stderr18
-rw-r--r--src/tools/clippy/tests/ui/match_wildcard_for_single_variants.fixed2
-rw-r--r--src/tools/clippy/tests/ui/match_wildcard_for_single_variants.stderr8
-rw-r--r--src/tools/clippy/tests/ui/methods.rs1
-rw-r--r--src/tools/clippy/tests/ui/methods.stderr4
-rw-r--r--src/tools/clippy/tests/ui/missing_doc_impl.stderr4
-rw-r--r--src/tools/clippy/tests/ui/module_name_repetitions.stderr20
-rw-r--r--src/tools/clippy/tests/ui/multiple_unsafe_ops_per_block.rs119
-rw-r--r--src/tools/clippy/tests/ui/multiple_unsafe_ops_per_block.stderr129
-rw-r--r--src/tools/clippy/tests/ui/must_use_candidates.fixed2
-rw-r--r--src/tools/clippy/tests/ui/must_use_candidates.rs2
-rw-r--r--src/tools/clippy/tests/ui/needless_lifetimes.fixed548
-rw-r--r--src/tools/clippy/tests/ui/needless_lifetimes.rs52
-rw-r--r--src/tools/clippy/tests/ui/needless_lifetimes.stderr391
-rw-r--r--src/tools/clippy/tests/ui/needless_range_loop.stderr8
-rw-r--r--src/tools/clippy/tests/ui/needless_return.fixed20
-rw-r--r--src/tools/clippy/tests/ui/needless_return.rs20
-rw-r--r--src/tools/clippy/tests/ui/needless_return.stderr126
-rw-r--r--src/tools/clippy/tests/ui/never_loop.rs45
-rw-r--r--src/tools/clippy/tests/ui/never_loop.stderr15
-rw-r--r--src/tools/clippy/tests/ui/new_without_default.rs7
-rw-r--r--src/tools/clippy/tests/ui/new_without_default.stderr14
-rw-r--r--src/tools/clippy/tests/ui/no_mangle_with_rust_abi.fixed48
-rw-r--r--src/tools/clippy/tests/ui/no_mangle_with_rust_abi.rs48
-rw-r--r--src/tools/clippy/tests/ui/no_mangle_with_rust_abi.stderr45
-rw-r--r--src/tools/clippy/tests/ui/question_mark_used.rs15
-rw-r--r--src/tools/clippy/tests/ui/question_mark_used.stderr11
-rw-r--r--src/tools/clippy/tests/ui/redundant_field_names.fixed2
-rw-r--r--src/tools/clippy/tests/ui/redundant_field_names.rs2
-rw-r--r--src/tools/clippy/tests/ui/regex.rs4
-rw-r--r--src/tools/clippy/tests/ui/regex.stderr66
-rw-r--r--src/tools/clippy/tests/ui/seek_to_start_instead_of_rewind.fixed4
-rw-r--r--src/tools/clippy/tests/ui/seek_to_start_instead_of_rewind.rs4
-rw-r--r--src/tools/clippy/tests/ui/significant_drop_tightening.fixed84
-rw-r--r--src/tools/clippy/tests/ui/significant_drop_tightening.rs80
-rw-r--r--src/tools/clippy/tests/ui/significant_drop_tightening.stderr94
-rw-r--r--src/tools/clippy/tests/ui/suspicious_command_arg_space.rs10
-rw-r--r--src/tools/clippy/tests/ui/suspicious_command_arg_space.stderr25
-rw-r--r--src/tools/clippy/tests/ui/suspicious_to_owned.stderr43
-rw-r--r--src/tools/clippy/tests/ui/swap.fixed24
-rw-r--r--src/tools/clippy/tests/ui/swap.rs29
-rw-r--r--src/tools/clippy/tests/ui/swap.stderr65
-rw-r--r--src/tools/clippy/tests/ui/track-diagnostics.stderr2
-rw-r--r--src/tools/clippy/tests/ui/transmute_int_to_non_zero.rs41
-rw-r--r--src/tools/clippy/tests/ui/transmute_int_to_non_zero.stderr64
-rw-r--r--src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.fixed2
-rw-r--r--src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.rs2
-rw-r--r--src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.stderr10
-rw-r--r--src/tools/clippy/tests/ui/type_repetition_in_bounds.rs1
-rw-r--r--src/tools/clippy/tests/ui/type_repetition_in_bounds.stderr8
-rw-r--r--src/tools/clippy/tests/ui/uninlined_format_args.fixed4
-rw-r--r--src/tools/clippy/tests/ui/uninlined_format_args.rs4
-rw-r--r--src/tools/clippy/tests/ui/unnecessary_safety_comment.rs17
-rw-r--r--src/tools/clippy/tests/ui/unreadable_literal.fixed2
-rw-r--r--src/tools/clippy/tests/ui/unreadable_literal.stderr10
-rw-r--r--src/tools/clippy/tests/ui/unused_io_amount.rs8
-rw-r--r--src/tools/clippy/tests/ui/unused_io_amount.stderr44
-rw-r--r--src/tools/clippy/tests/ui/wildcard_enum_match_arm.fixed2
-rw-r--r--src/tools/clippy/tests/ui/wildcard_enum_match_arm.stderr4
-rw-r--r--src/tools/compiletest/Cargo.toml5
-rw-r--r--src/tools/compiletest/src/common.rs6
-rw-r--r--src/tools/compiletest/src/errors.rs8
-rw-r--r--src/tools/compiletest/src/header.rs87
-rw-r--r--src/tools/compiletest/src/main.rs57
-rw-r--r--src/tools/compiletest/src/runtest.rs87
-rw-r--r--src/tools/compiletest/src/util.rs37
-rw-r--r--src/tools/error_index_generator/Cargo.toml1
-rw-r--r--src/tools/error_index_generator/main.rs58
-rw-r--r--src/tools/expand-yaml-anchors/src/main.rs2
-rw-r--r--src/tools/jsondoclint/src/validator.rs28
-rwxr-xr-xsrc/tools/publish_toolstate.py61
-rw-r--r--src/tools/rust-analyzer/Cargo.lock430
-rw-r--r--src/tools/rust-analyzer/Cargo.toml44
-rw-r--r--src/tools/rust-analyzer/crates/base-db/Cargo.toml23
-rw-r--r--src/tools/rust-analyzer/crates/base-db/src/fixture.rs86
-rw-r--r--src/tools/rust-analyzer/crates/base-db/src/input.rs36
-rw-r--r--src/tools/rust-analyzer/crates/base-db/src/lib.rs1
-rw-r--r--src/tools/rust-analyzer/crates/cfg/Cargo.toml21
-rw-r--r--src/tools/rust-analyzer/crates/cfg/src/cfg_expr.rs4
-rw-r--r--src/tools/rust-analyzer/crates/flycheck/Cargo.toml17
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/Cargo.toml37
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/adt.rs9
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/attr.rs360
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/body.rs148
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/body/lower.rs12
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/body/pretty.rs4
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/body/tests.rs13
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/child_by_source.rs2
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/data.rs4
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/db.rs8
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/expr.rs2
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/find_path.rs8
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/generics.rs2
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/item_scope.rs6
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/item_tree.rs20
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/item_tree/lower.rs33
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/item_tree/pretty.rs1
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/keys.rs3
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/lang_item.rs298
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/layout.rs1
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/lib.rs49
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests.rs12
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/mbe.rs37
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/mbe/regression.rs21
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/proc_macros.rs7
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/nameres/attr_resolution.rs3
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs52
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/nameres/diagnostics.rs11
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/nameres/mod_resolution.rs2
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/nameres/proc_macro.rs2
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/nameres/tests.rs8
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/nameres/tests/macros.rs6
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/path.rs64
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/path/lower.rs87
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/pretty.rs4
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/resolver.rs2
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/type_ref.rs10
-rw-r--r--src/tools/rust-analyzer/crates/hir-expand/Cargo.toml28
-rw-r--r--src/tools/rust-analyzer/crates/hir-expand/src/attrs.rs349
-rw-r--r--src/tools/rust-analyzer/crates/hir-expand/src/builtin_attr_macro.rs6
-rw-r--r--src/tools/rust-analyzer/crates/hir-expand/src/builtin_derive_macro.rs10
-rw-r--r--src/tools/rust-analyzer/crates/hir-expand/src/builtin_fn_macro.rs66
-rw-r--r--src/tools/rust-analyzer/crates/hir-expand/src/db.rs25
-rw-r--r--src/tools/rust-analyzer/crates/hir-expand/src/eager.rs6
-rw-r--r--src/tools/rust-analyzer/crates/hir-expand/src/fixup.rs18
-rw-r--r--src/tools/rust-analyzer/crates/hir-expand/src/hygiene.rs4
-rw-r--r--src/tools/rust-analyzer/crates/hir-expand/src/lib.rs42
-rw-r--r--src/tools/rust-analyzer/crates/hir-expand/src/name.rs18
-rw-r--r--src/tools/rust-analyzer/crates/hir-expand/src/proc_macro.rs24
-rw-r--r--src/tools/rust-analyzer/crates/hir-expand/src/quote.rs112
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/Cargo.toml33
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/autoderef.rs9
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/builder.rs17
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/chalk_db.rs83
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/chalk_ext.rs36
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/db.rs2
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/decl_check/case_conv.rs2
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/expr.rs41
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/display.rs236
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/infer.rs122
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/infer/closure.rs4
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/infer/coerce.rs15
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/infer/expr.rs378
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/infer/path.rs2
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/infer/unify.rs25
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/interner.rs7
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/lang_items.rs11
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/layout.rs53
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/layout/adt.rs4
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/layout/target.rs40
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/layout/tests.rs115
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/lib.rs81
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/lower.rs145
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/method_resolution.rs112
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/tests/method_resolution.rs16
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/tests/simple.rs83
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/tests/traits.rs337
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/traits.rs18
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/utils.rs185
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/walk.rs147
-rw-r--r--src/tools/rust-analyzer/crates/hir/Cargo.toml31
-rw-r--r--src/tools/rust-analyzer/crates/hir/src/display.rs7
-rw-r--r--src/tools/rust-analyzer/crates/hir/src/lib.rs186
-rw-r--r--src/tools/rust-analyzer/crates/hir/src/semantics.rs16
-rw-r--r--src/tools/rust-analyzer/crates/hir/src/semantics/source_to_def.rs3
-rw-r--r--src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs48
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/Cargo.toml29
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_braces.rs155
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_missing_impl_members.rs92
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_missing_match_arms.rs201
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_comment_block.rs4
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_match_to_let_else.rs87
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_named_struct_to_tuple_struct.rs5
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_tuple_struct_to_named_struct.rs5
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/handlers/desugar_doc_comment.rs312
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_type_alias.rs38
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_default_from_new.rs6
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_delegate_methods.rs2
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_function.rs901
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_getter.rs107
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/handlers/inline_macro.rs26
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/handlers/merge_imports.rs2
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/handlers/move_const_to_impl.rs44
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/handlers/raw_string.rs23
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/handlers/reorder_fields.rs5
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_arith_op.rs2
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_derive_with_manual_impl.rs2
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_if_let_with_match.rs183
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/handlers/unmerge_match_arm.rs3
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/handlers/unwrap_block.rs162
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/lib.rs4
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/tests.rs42
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/tests/generated.rs40
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/utils.rs38
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/utils/gen_trait_fn_body.rs36
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/Cargo.toml30
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/completions/item_list/trait_impl.rs2
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/completions/keyword.rs3
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/completions/postfix.rs163
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/config.rs1
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/context.rs37
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/context/analysis.rs175
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/item.rs104
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/lib.rs18
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/render.rs29
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/render/literal.rs2
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/render/union_literal.rs2
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/tests.rs46
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/tests/expression.rs252
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/tests/flyimport.rs6
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/tests/item_list.rs51
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/tests/proc_macros.rs114
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/tests/special.rs89
-rw-r--r--src/tools/rust-analyzer/crates/ide-db/Cargo.toml38
-rw-r--r--src/tools/rust-analyzer/crates/ide-db/src/active_parameter.rs80
-rw-r--r--src/tools/rust-analyzer/crates/ide-db/src/defs.rs2
-rw-r--r--src/tools/rust-analyzer/crates/ide-db/src/line_index.rs199
-rw-r--r--src/tools/rust-analyzer/crates/ide-db/src/path_transform.rs24
-rw-r--r--src/tools/rust-analyzer/crates/ide-db/src/rename.rs76
-rw-r--r--src/tools/rust-analyzer/crates/ide-db/src/search.rs183
-rw-r--r--src/tools/rust-analyzer/crates/ide-db/src/symbol_index.rs8
-rw-r--r--src/tools/rust-analyzer/crates/ide-diagnostics/Cargo.toml28
-rw-r--r--src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/json_is_not_rust.rs122
-rw-r--r--src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/private_assoc_item.rs5
-rw-r--r--src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unlinked_file.rs230
-rw-r--r--src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unresolved_proc_macro.rs5
-rw-r--r--src/tools/rust-analyzer/crates/ide-ssr/Cargo.toml25
-rw-r--r--src/tools/rust-analyzer/crates/ide/Cargo.toml39
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/file_structure.rs29
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/goto_declaration.rs1
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/goto_definition.rs64
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/highlight_related.rs2
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/hover.rs181
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/hover/render.rs163
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/hover/tests.rs248
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/inlay_hints.rs191
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/inlay_hints/adjustment.rs135
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/inlay_hints/bind_pat.rs137
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/inlay_hints/binding_mode.rs55
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/inlay_hints/chaining.rs323
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/inlay_hints/closing_brace.rs14
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/inlay_hints/closure_ret.rs7
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/inlay_hints/discriminant.rs108
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/inlay_hints/fn_lifetime_fn.rs11
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/inlay_hints/implicit_static.rs5
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/inlay_hints/param_name.rs11
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/join_lines.rs6
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/lib.rs7
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/markdown_remove.rs140
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/references.rs395
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/rename.rs202
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/shuffle_crate_graph.rs22
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/signature_help.rs299
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/static_index.rs7
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/syntax_highlighting.rs9
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/tests.rs2
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/typing.rs57
-rw-r--r--src/tools/rust-analyzer/crates/intern/Cargo.toml20
-rw-r--r--src/tools/rust-analyzer/crates/intern/src/lib.rs (renamed from src/tools/rust-analyzer/crates/hir-def/src/intern.rs)19
-rw-r--r--src/tools/rust-analyzer/crates/limit/Cargo.toml8
-rw-r--r--src/tools/rust-analyzer/crates/mbe/Cargo.toml21
-rw-r--r--src/tools/rust-analyzer/crates/mbe/src/benchmark.rs30
-rw-r--r--src/tools/rust-analyzer/crates/mbe/src/expander.rs7
-rw-r--r--src/tools/rust-analyzer/crates/mbe/src/expander/matcher.rs41
-rw-r--r--src/tools/rust-analyzer/crates/mbe/src/expander/transcriber.rs74
-rw-r--r--src/tools/rust-analyzer/crates/mbe/src/lib.rs55
-rw-r--r--src/tools/rust-analyzer/crates/mbe/src/parser.rs22
-rw-r--r--src/tools/rust-analyzer/crates/mbe/src/syntax_bridge.rs166
-rw-r--r--src/tools/rust-analyzer/crates/mbe/src/syntax_bridge/tests.rs4
-rw-r--r--src/tools/rust-analyzer/crates/mbe/src/to_parser_input.rs36
-rw-r--r--src/tools/rust-analyzer/crates/mbe/src/tt_iter.rs27
-rw-r--r--src/tools/rust-analyzer/crates/parser/Cargo.toml17
-rw-r--r--src/tools/rust-analyzer/crates/parser/src/event.rs13
-rw-r--r--src/tools/rust-analyzer/crates/parser/src/grammar.rs30
-rw-r--r--src/tools/rust-analyzer/crates/parser/src/grammar/attributes.rs2
-rw-r--r--src/tools/rust-analyzer/crates/parser/src/grammar/expressions.rs137
-rw-r--r--src/tools/rust-analyzer/crates/parser/src/grammar/expressions/atom.rs38
-rw-r--r--src/tools/rust-analyzer/crates/parser/src/grammar/generic_args.rs32
-rw-r--r--src/tools/rust-analyzer/crates/parser/src/grammar/generic_params.rs29
-rw-r--r--src/tools/rust-analyzer/crates/parser/src/grammar/items/adt.rs25
-rw-r--r--src/tools/rust-analyzer/crates/parser/src/grammar/params.rs14
-rw-r--r--src/tools/rust-analyzer/crates/parser/src/grammar/paths.rs11
-rw-r--r--src/tools/rust-analyzer/crates/parser/src/grammar/types.rs3
-rw-r--r--src/tools/rust-analyzer/crates/parser/src/lexed_str.rs5
-rw-r--r--src/tools/rust-analyzer/crates/parser/src/lib.rs4
-rw-r--r--src/tools/rust-analyzer/crates/parser/src/output.rs61
-rw-r--r--src/tools/rust-analyzer/crates/parser/src/parser.rs29
-rw-r--r--src/tools/rust-analyzer/crates/parser/src/shortcuts.rs53
-rw-r--r--src/tools/rust-analyzer/crates/parser/src/tests.rs6
-rw-r--r--src/tools/rust-analyzer/crates/parser/src/tests/prefix_entries.rs4
-rw-r--r--src/tools/rust-analyzer/crates/parser/src/tests/top_entries.rs2
-rw-r--r--src/tools/rust-analyzer/crates/parser/test_data/parser/err/0009_broken_struct_type_parameter.rast3
-rw-r--r--src/tools/rust-analyzer/crates/parser/test_data/parser/err/0013_invalid_type.rast38
-rw-r--r--src/tools/rust-analyzer/crates/parser/test_data/parser/err/0022_bad_exprs.rast18
-rw-r--r--src/tools/rust-analyzer/crates/parser/test_data/parser/err/0024_many_type_parens.rast211
-rw-r--r--src/tools/rust-analyzer/crates/parser/test_data/parser/err/0025_nope.rast7
-rw-r--r--src/tools/rust-analyzer/crates/parser/test_data/parser/err/0042_weird_blocks.rast2
-rw-r--r--src/tools/rust-analyzer/crates/parser/test_data/parser/err/0048_double_fish.rast19
-rw-r--r--src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0002_misplaced_label_err.rast2
-rw-r--r--src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0015_arg_list_recovery.rast77
-rw-r--r--src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0015_arg_list_recovery.rs5
-rw-r--r--src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0015_missing_fn_param_type.rast2
-rw-r--r--src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0011_field_expr.rast33
-rw-r--r--src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0011_field_expr.rs2
-rw-r--r--src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0107_method_call_expr.rast43
-rw-r--r--src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0107_method_call_expr.rs2
-rw-r--r--src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0137_await_expr.rast35
-rw-r--r--src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0137_await_expr.rs2
-rw-r--r--src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0205_const_closure.rast42
-rw-r--r--src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0205_const_closure.rs1
-rw-r--r--src/tools/rust-analyzer/crates/paths/Cargo.toml8
-rw-r--r--src/tools/rust-analyzer/crates/proc-macro-api/Cargo.toml23
-rw-r--r--src/tools/rust-analyzer/crates/proc-macro-api/src/lib.rs17
-rw-r--r--src/tools/rust-analyzer/crates/proc-macro-api/src/msg.rs23
-rw-r--r--src/tools/rust-analyzer/crates/proc-macro-api/src/msg/flat.rs43
-rw-r--r--src/tools/rust-analyzer/crates/proc-macro-api/src/process.rs54
-rw-r--r--src/tools/rust-analyzer/crates/proc-macro-api/src/version.rs13
-rw-r--r--src/tools/rust-analyzer/crates/proc-macro-srv-cli/Cargo.toml10
-rw-r--r--src/tools/rust-analyzer/crates/proc-macro-srv/Cargo.toml20
-rw-r--r--src/tools/rust-analyzer/crates/proc-macro-srv/src/abis/abi_1_58/mod.rs104
-rw-r--r--src/tools/rust-analyzer/crates/proc-macro-srv/src/abis/abi_1_58/proc_macro/bridge/buffer.rs143
-rw-r--r--src/tools/rust-analyzer/crates/proc-macro-srv/src/abis/abi_1_58/proc_macro/bridge/client.rs485
-rw-r--r--src/tools/rust-analyzer/crates/proc-macro-srv/src/abis/abi_1_58/proc_macro/bridge/closure.rs24
-rw-r--r--src/tools/rust-analyzer/crates/proc-macro-srv/src/abis/abi_1_58/proc_macro/bridge/handle.rs70
-rw-r--r--src/tools/rust-analyzer/crates/proc-macro-srv/src/abis/abi_1_58/proc_macro/bridge/mod.rs429
-rw-r--r--src/tools/rust-analyzer/crates/proc-macro-srv/src/abis/abi_1_58/proc_macro/bridge/rpc.rs305
-rw-r--r--src/tools/rust-analyzer/crates/proc-macro-srv/src/abis/abi_1_58/proc_macro/bridge/scoped_cell.rs81
-rw-r--r--src/tools/rust-analyzer/crates/proc-macro-srv/src/abis/abi_1_58/proc_macro/bridge/server.rs352
-rw-r--r--src/tools/rust-analyzer/crates/proc-macro-srv/src/abis/abi_1_58/proc_macro/diagnostic.rs166
-rw-r--r--src/tools/rust-analyzer/crates/proc-macro-srv/src/abis/abi_1_58/proc_macro/mod.rs1056
-rw-r--r--src/tools/rust-analyzer/crates/proc-macro-srv/src/abis/abi_1_58/proc_macro/quote.rs140
-rw-r--r--src/tools/rust-analyzer/crates/proc-macro-srv/src/abis/abi_1_58/ra_server.rs822
-rw-r--r--src/tools/rust-analyzer/crates/proc-macro-srv/src/abis/abi_1_63/mod.rs1
-rw-r--r--src/tools/rust-analyzer/crates/proc-macro-srv/src/abis/abi_1_63/proc_macro/mod.rs24
-rw-r--r--src/tools/rust-analyzer/crates/proc-macro-srv/src/abis/abi_1_63/ra_server.rs119
-rw-r--r--src/tools/rust-analyzer/crates/proc-macro-srv/src/abis/abi_sysroot/mod.rs2
-rw-r--r--src/tools/rust-analyzer/crates/proc-macro-srv/src/abis/abi_sysroot/ra_server.rs65
-rw-r--r--src/tools/rust-analyzer/crates/proc-macro-srv/src/abis/abi_sysroot/ra_server/token_stream.rs28
-rw-r--r--src/tools/rust-analyzer/crates/proc-macro-srv/src/abis/mod.rs11
-rw-r--r--src/tools/rust-analyzer/crates/proc-macro-srv/src/cli.rs3
-rw-r--r--src/tools/rust-analyzer/crates/proc-macro-srv/src/dylib.rs2
-rw-r--r--src/tools/rust-analyzer/crates/proc-macro-srv/src/lib.rs2
-rw-r--r--src/tools/rust-analyzer/crates/proc-macro-srv/src/tests/mod.rs26
-rw-r--r--src/tools/rust-analyzer/crates/proc-macro-test/Cargo.toml15
-rw-r--r--src/tools/rust-analyzer/crates/proc-macro-test/imp/Cargo.toml1
-rw-r--r--src/tools/rust-analyzer/crates/profile/Cargo.toml10
-rw-r--r--src/tools/rust-analyzer/crates/profile/src/lib.rs2
-rw-r--r--src/tools/rust-analyzer/crates/project-model/Cargo.toml21
-rw-r--r--src/tools/rust-analyzer/crates/project-model/src/cargo_workspace.rs1
-rw-r--r--src/tools/rust-analyzer/crates/project-model/src/lib.rs2
-rw-r--r--src/tools/rust-analyzer/crates/project-model/src/project_json.rs44
-rw-r--r--src/tools/rust-analyzer/crates/project-model/src/sysroot.rs34
-rw-r--r--src/tools/rust-analyzer/crates/project-model/src/target_data_layout.rs13
-rw-r--r--src/tools/rust-analyzer/crates/project-model/src/tests.rs128
-rw-r--r--src/tools/rust-analyzer/crates/project-model/src/workspace.rs230
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/Cargo.toml58
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/bin/main.rs37
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/caps.rs25
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/cli/analysis_stats.rs22
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/cli/diagnostics.rs4
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/cli/load_cargo.rs33
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/cli/lsif.rs8
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/cli/scip.rs7
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/cli/ssr.rs6
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs70
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/config/patch_old_style.rs42
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/diagnostics/to_proto.rs6
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/from_proto.rs13
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/global_state.rs82
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/handlers.rs66
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/integrated_benchmarks.rs8
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/line_index.rs5
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/lsp_ext.rs41
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/lsp_utils.rs88
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/main_loop.rs61
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/reload.rs46
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/to_proto.rs277
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/tests/slow-tests/main.rs4
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/tests/slow-tests/support.rs2
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/tests/slow-tests/tidy.rs27
-rw-r--r--src/tools/rust-analyzer/crates/sourcegen/Cargo.toml8
-rw-r--r--src/tools/rust-analyzer/crates/stdx/Cargo.toml8
-rw-r--r--src/tools/rust-analyzer/crates/stdx/src/lib.rs15
-rw-r--r--src/tools/rust-analyzer/crates/stdx/src/macros.rs9
-rw-r--r--src/tools/rust-analyzer/crates/stdx/src/rand.rs21
-rw-r--r--src/tools/rust-analyzer/crates/syntax/Cargo.toml26
-rw-r--r--src/tools/rust-analyzer/crates/syntax/fuzz/Cargo.toml7
-rw-r--r--src/tools/rust-analyzer/crates/syntax/rust.ungram2
-rw-r--r--src/tools/rust-analyzer/crates/syntax/src/ast.rs30
-rw-r--r--src/tools/rust-analyzer/crates/syntax/src/ast/generated/nodes.rs1
-rw-r--r--src/tools/rust-analyzer/crates/syntax/src/ast/make.rs21
-rw-r--r--src/tools/rust-analyzer/crates/syntax/src/lib.rs2
-rw-r--r--src/tools/rust-analyzer/crates/syntax/src/syntax_node.rs1
-rw-r--r--src/tools/rust-analyzer/crates/syntax/src/utils.rs7
-rw-r--r--src/tools/rust-analyzer/crates/test-utils/Cargo.toml12
-rw-r--r--src/tools/rust-analyzer/crates/test-utils/src/minicore.rs44
-rw-r--r--src/tools/rust-analyzer/crates/text-edit/Cargo.toml8
-rw-r--r--src/tools/rust-analyzer/crates/toolchain/Cargo.toml8
-rw-r--r--src/tools/rust-analyzer/crates/tt/Cargo.toml10
-rw-r--r--src/tools/rust-analyzer/crates/tt/src/buffer.rs105
-rw-r--r--src/tools/rust-analyzer/crates/tt/src/lib.rs228
-rw-r--r--src/tools/rust-analyzer/crates/vfs-notify/Cargo.toml12
-rw-r--r--src/tools/rust-analyzer/crates/vfs/Cargo.toml12
-rw-r--r--src/tools/rust-analyzer/crates/vfs/src/lib.rs3
-rw-r--r--src/tools/rust-analyzer/crates/vfs/src/vfs_path.rs17
-rw-r--r--src/tools/rust-analyzer/docs/dev/architecture.md2
-rw-r--r--src/tools/rust-analyzer/docs/dev/lsp-extensions.md2
-rw-r--r--src/tools/rust-analyzer/docs/user/generated_config.adoc18
-rw-r--r--src/tools/rust-analyzer/docs/user/manual.adoc119
-rw-r--r--src/tools/rust-analyzer/lib/lsp-server/Cargo.toml2
-rw-r--r--src/tools/rust-analyzer/lib/lsp-server/src/stdio.rs5
-rw-r--r--src/tools/rust-analyzer/xtask/Cargo.toml1
-rw-r--r--src/tools/rust-analyzer/xtask/src/dist.rs9
-rw-r--r--src/tools/rust-analyzer/xtask/src/publish.rs2
-rw-r--r--src/tools/rust-analyzer/xtask/src/release/changelog.rs4
-rw-r--r--src/tools/rust-installer/src/generator.rs16
-rw-r--r--src/tools/rustdoc-js/tester.js14
-rw-r--r--src/tools/rustfmt/.github/workflows/check_diff.yml33
-rw-r--r--src/tools/rustfmt/.github/workflows/integration.yml4
-rw-r--r--src/tools/rustfmt/CHANGELOG.md28
-rw-r--r--src/tools/rustfmt/Cargo.lock4
-rw-r--r--src/tools/rustfmt/Cargo.toml4
-rw-r--r--src/tools/rustfmt/Configurations.md185
-rw-r--r--src/tools/rustfmt/Processes.md2
-rwxr-xr-xsrc/tools/rustfmt/ci/build_and_test.bat1
-rwxr-xr-xsrc/tools/rustfmt/ci/build_and_test.sh1
-rwxr-xr-xsrc/tools/rustfmt/ci/check_diff.sh199
-rwxr-xr-xsrc/tools/rustfmt/ci/integration.sh18
-rw-r--r--src/tools/rustfmt/config_proc_macro/Cargo.lock2
-rw-r--r--src/tools/rustfmt/config_proc_macro/Cargo.toml2
-rw-r--r--src/tools/rustfmt/config_proc_macro/src/attrs.rs27
-rw-r--r--src/tools/rustfmt/config_proc_macro/src/item_enum.rs40
-rw-r--r--src/tools/rustfmt/config_proc_macro/src/lib.rs13
-rw-r--r--src/tools/rustfmt/config_proc_macro/tests/smoke.rs1
-rw-r--r--src/tools/rustfmt/rust-toolchain4
-rw-r--r--src/tools/rustfmt/src/attr.rs4
-rw-r--r--src/tools/rustfmt/src/bin/main.rs2
-rw-r--r--src/tools/rustfmt/src/cargo-fmt/main.rs12
-rw-r--r--src/tools/rustfmt/src/cargo-fmt/test/mod.rs4
-rw-r--r--src/tools/rustfmt/src/chains.rs124
-rw-r--r--src/tools/rustfmt/src/closures.rs3
-rw-r--r--src/tools/rustfmt/src/config/config_type.rs122
-rw-r--r--src/tools/rustfmt/src/config/macro_names.rs118
-rw-r--r--src/tools/rustfmt/src/config/mod.rs149
-rw-r--r--src/tools/rustfmt/src/expr.rs14
-rw-r--r--src/tools/rustfmt/src/imports.rs4
-rw-r--r--src/tools/rustfmt/src/items.rs10
-rw-r--r--src/tools/rustfmt/src/lib.rs1
-rw-r--r--src/tools/rustfmt/src/lists.rs16
-rw-r--r--src/tools/rustfmt/src/macros.rs26
-rw-r--r--src/tools/rustfmt/src/modules.rs13
-rw-r--r--src/tools/rustfmt/src/parse/parser.rs3
-rw-r--r--src/tools/rustfmt/src/parse/session.rs9
-rw-r--r--src/tools/rustfmt/src/skip.rs79
-rw-r--r--src/tools/rustfmt/src/test/configuration_snippet.rs7
-rw-r--r--src/tools/rustfmt/src/test/mod.rs6
-rw-r--r--src/tools/rustfmt/src/types.rs44
-rw-r--r--src/tools/rustfmt/src/utils.rs6
-rw-r--r--src/tools/rustfmt/src/visitor.rs13
-rw-r--r--src/tools/rustfmt/tests/cargo-fmt/main.rs29
-rw-r--r--src/tools/rustfmt/tests/cargo-fmt/source/issue_3164/Cargo.toml8
-rw-r--r--src/tools/rustfmt/tests/cargo-fmt/source/issue_3164/src/main.rs13
-rw-r--r--src/tools/rustfmt/tests/config/small_tabs.toml2
-rw-r--r--src/tools/rustfmt/tests/mod-resolver/issue-5198/lib/c/d/explanation.txt2
-rw-r--r--src/tools/rustfmt/tests/mod-resolver/issue-5198/lib/explanation.txt2
-rw-r--r--src/tools/rustfmt/tests/rustfmt/main.rs21
-rw-r--r--src/tools/rustfmt/tests/source/cfg_if/detect/arch/x86.rs2
-rw-r--r--src/tools/rustfmt/tests/source/comments_unicode.rs140
-rw-r--r--src/tools/rustfmt/tests/source/configs/fn_params_layout/compressed.rs (renamed from src/tools/rustfmt/tests/source/configs/fn_args_layout/compressed.rs)2
-rw-r--r--src/tools/rustfmt/tests/source/configs/fn_params_layout/tall.rs (renamed from src/tools/rustfmt/tests/source/configs/fn_args_layout/tall.rs)2
-rw-r--r--src/tools/rustfmt/tests/source/configs/fn_params_layout/vertical.rs (renamed from src/tools/rustfmt/tests/source/configs/fn_args_layout/vertical.rs)2
-rw-r--r--src/tools/rustfmt/tests/source/enum.rs2
-rw-r--r--src/tools/rustfmt/tests/source/fn-custom-7.rs2
-rw-r--r--src/tools/rustfmt/tests/source/fn-custom.rs2
-rw-r--r--src/tools/rustfmt/tests/source/fn_args_layout-vertical.rs2
-rw-r--r--src/tools/rustfmt/tests/source/issue-3987/format_macro_bodies_true.rs26
-rw-r--r--src/tools/rustfmt/tests/source/issue-4643.rs23
-rw-r--r--src/tools/rustfmt/tests/source/issue-4689/one.rs149
-rw-r--r--src/tools/rustfmt/tests/source/issue-4689/two.rs149
-rw-r--r--src/tools/rustfmt/tests/source/issue_1306.rs29
-rw-r--r--src/tools/rustfmt/tests/source/issue_3245.rs4
-rw-r--r--src/tools/rustfmt/tests/source/issue_3561.rs6
-rw-r--r--src/tools/rustfmt/tests/source/skip_macro_invocations/all.rs11
-rw-r--r--src/tools/rustfmt/tests/source/skip_macro_invocations/all_and_name.rs11
-rw-r--r--src/tools/rustfmt/tests/source/skip_macro_invocations/empty.rs11
-rw-r--r--src/tools/rustfmt/tests/source/skip_macro_invocations/name.rs11
-rw-r--r--src/tools/rustfmt/tests/source/skip_macro_invocations/name_unknown.rs6
-rw-r--r--src/tools/rustfmt/tests/source/skip_macro_invocations/names.rs16
-rw-r--r--src/tools/rustfmt/tests/source/skip_macro_invocations/path_qualified_invocation_mismatch.rs6
-rw-r--r--src/tools/rustfmt/tests/source/skip_macro_invocations/path_qualified_match.rs6
-rw-r--r--src/tools/rustfmt/tests/source/skip_macro_invocations/path_qualified_name_mismatch.rs6
-rw-r--r--src/tools/rustfmt/tests/source/skip_macro_invocations/use_alias_examples.rs32
-rw-r--r--src/tools/rustfmt/tests/source/tuple.rs2
-rw-r--r--src/tools/rustfmt/tests/source/wrap_comments_should_not_imply_format_doc_comments.rs2
-rw-r--r--src/tools/rustfmt/tests/target/cfg_if/detect/arch/x86.rs2
-rw-r--r--src/tools/rustfmt/tests/target/comments_unicode.rs140
-rw-r--r--src/tools/rustfmt/tests/target/configs/fn_params_layout/compressed.rs (renamed from src/tools/rustfmt/tests/target/configs/fn_args_layout/compressed.rs)2
-rw-r--r--src/tools/rustfmt/tests/target/configs/fn_params_layout/tall.rs (renamed from src/tools/rustfmt/tests/target/configs/fn_args_layout/tall.rs)2
-rw-r--r--src/tools/rustfmt/tests/target/configs/fn_params_layout/vertical.rs (renamed from src/tools/rustfmt/tests/target/configs/fn_args_layout/vertical.rs)2
-rw-r--r--src/tools/rustfmt/tests/target/enum.rs2
-rw-r--r--src/tools/rustfmt/tests/target/fn-custom-7.rs2
-rw-r--r--src/tools/rustfmt/tests/target/fn-custom.rs2
-rw-r--r--src/tools/rustfmt/tests/target/fn_args_layout-vertical.rs2
-rw-r--r--src/tools/rustfmt/tests/target/issue-2534/format_macro_matchers_false.rs6
-rw-r--r--src/tools/rustfmt/tests/target/issue-2534/format_macro_matchers_true.rs6
-rw-r--r--src/tools/rustfmt/tests/target/issue-3987/format_macro_bodies_false.rs26
-rw-r--r--src/tools/rustfmt/tests/target/issue-3987/format_macro_bodies_true.rs21
-rw-r--r--src/tools/rustfmt/tests/target/issue-4643.rs19
-rw-r--r--src/tools/rustfmt/tests/target/issue-4689/one.rs150
-rw-r--r--src/tools/rustfmt/tests/target/issue-4689/two.rs152
-rw-r--r--src/tools/rustfmt/tests/target/issue-4791/issue_4928.rs2
-rw-r--r--src/tools/rustfmt/tests/target/issue-5358.rs4
-rw-r--r--src/tools/rustfmt/tests/target/issue_1306.rs33
-rw-r--r--src/tools/rustfmt/tests/target/issue_3033.rs2
-rw-r--r--src/tools/rustfmt/tests/target/issue_3245.rs4
-rw-r--r--src/tools/rustfmt/tests/target/issue_3561.rs7
-rw-r--r--src/tools/rustfmt/tests/target/issue_4350.rs13
-rw-r--r--src/tools/rustfmt/tests/target/issue_5668.rs8
-rw-r--r--src/tools/rustfmt/tests/target/skip_macro_invocations/all.rs11
-rw-r--r--src/tools/rustfmt/tests/target/skip_macro_invocations/all_and_name.rs11
-rw-r--r--src/tools/rustfmt/tests/target/skip_macro_invocations/empty.rs11
-rw-r--r--src/tools/rustfmt/tests/target/skip_macro_invocations/name.rs11
-rw-r--r--src/tools/rustfmt/tests/target/skip_macro_invocations/name_unknown.rs6
-rw-r--r--src/tools/rustfmt/tests/target/skip_macro_invocations/names.rs16
-rw-r--r--src/tools/rustfmt/tests/target/skip_macro_invocations/path_qualified_invocation_mismatch.rs6
-rw-r--r--src/tools/rustfmt/tests/target/skip_macro_invocations/path_qualified_match.rs6
-rw-r--r--src/tools/rustfmt/tests/target/skip_macro_invocations/path_qualified_name_mismatch.rs6
-rw-r--r--src/tools/rustfmt/tests/target/skip_macro_invocations/use_alias_examples.rs32
-rw-r--r--src/tools/rustfmt/tests/target/tuple.rs2
-rw-r--r--src/tools/rustfmt/tests/target/wrap_comments_should_not_imply_format_doc_comments.rs2
-rw-r--r--src/tools/tidy/src/deps.rs9
-rw-r--r--src/tools/tidy/src/error_codes.rs26
-rw-r--r--src/tools/tidy/src/ui_tests.rs4
-rw-r--r--src/tools/x/Cargo.toml2
-rw-r--r--src/tools/x/src/main.rs74
-rw-r--r--src/version2
-rw-r--r--tests/assembly/align_offset.rs1
-rw-r--r--tests/codegen/array-equality.rs30
-rw-r--r--tests/codegen/array-map.rs49
-rw-r--r--tests/codegen/autovectorize-f32x4.rs13
-rw-r--r--tests/codegen/avr/avr-func-addrspace.rs25
-rw-r--r--tests/codegen/consts.rs5
-rw-r--r--tests/codegen/debug-vtable.rs8
-rw-r--r--tests/codegen/function-arguments-noopt.rs6
-rw-r--r--tests/codegen/function-arguments.rs35
-rw-r--r--tests/codegen/inherit_overflow.rs14
-rw-r--r--tests/codegen/instrument-xray/basic.rs9
-rw-r--r--tests/codegen/instrument-xray/options-combine.rs12
-rw-r--r--tests/codegen/instrument-xray/options-override.rs11
-rw-r--r--tests/codegen/issue-75659.rs2
-rw-r--r--tests/codegen/merge-functions.rs1
-rw-r--r--tests/codegen/move-operands.rs2
-rw-r--r--tests/codegen/option-as-slice.rs28
-rw-r--r--tests/codegen/option-nonzero-eq.rs10
-rw-r--r--tests/codegen/remap_path_prefix/main.rs2
-rw-r--r--tests/codegen/sanitizer-kasan-emits-instrumentation.rs47
-rw-r--r--tests/codegen/simd-intrinsic/simd-intrinsic-generic-arithmetic-saturating.rs166
-rw-r--r--tests/codegen/simd-intrinsic/simd-intrinsic-generic-bitmask.rs10
-rw-r--r--tests/codegen/simd-intrinsic/simd-intrinsic-generic-extract-insert.rs8
-rw-r--r--tests/codegen/simd-intrinsic/simd-intrinsic-transmute-array.rs3
-rw-r--r--tests/codegen/simd_arith_offset.rs2
-rw-r--r--tests/codegen/slice-ref-equality.rs56
-rw-r--r--tests/codegen/sse42-implies-crc32.rs1
-rw-r--r--tests/codegen/thread-local.rs1
-rw-r--r--tests/codegen/uninit-consts.rs1
-rw-r--r--tests/codegen/vec-in-place.rs1
-rw-r--r--tests/debuginfo/captured-fields-1.rs3
-rw-r--r--tests/debuginfo/captured-fields-2.rs8
-rw-r--r--tests/debuginfo/embedded-visualizer.rs1
-rw-r--r--tests/debuginfo/numeric-types.rs1
-rw-r--r--tests/debuginfo/vec-slices.rs1
-rw-r--r--tests/mir-opt/76803_regression.encode.SimplifyBranchSame.diff29
-rw-r--r--tests/mir-opt/76803_regression.rs19
-rw-r--r--tests/mir-opt/building/async_await.a-{closure#0}.generator_resume.0.mir4
-rw-r--r--tests/mir-opt/building/async_await.b-{closure#0}.generator_resume.0.mir28
-rw-r--r--tests/mir-opt/building/custom/arrays.arrays.built.after.mir14
-rw-r--r--tests/mir-opt/building/custom/arrays.rs19
-rw-r--r--tests/mir-opt/building/custom/enums.rs1
-rw-r--r--tests/mir-opt/building/custom/enums.set_discr.built.after.mir5
-rw-r--r--tests/mir-opt/building/custom/operators.f.built.after.mir30
-rw-r--r--tests/mir-opt/building/custom/operators.rs31
-rw-r--r--tests/mir-opt/casts.redundant.InstCombine.diff25
-rw-r--r--tests/mir-opt/casts.redundant.PreCodegen.after.mir14
-rw-r--r--tests/mir-opt/casts.roundtrip.PreCodegen.after.mir15
-rw-r--r--tests/mir-opt/casts.rs17
-rw-r--r--tests/mir-opt/combine_clone_of_primitives.{impl#0}-clone.InstCombine.diff5
-rw-r--r--tests/mir-opt/const_allocation.main.ConstProp.after.32bit.mir16
-rw-r--r--tests/mir-opt/const_allocation.main.ConstProp.after.64bit.mir16
-rw-r--r--tests/mir-opt/const_debuginfo.main.ConstDebugInfo.diff34
-rw-r--r--tests/mir-opt/const_goto_storage.match_nested_if.ConstGoto.diff2
-rw-r--r--tests/mir-opt/const_prop/aggregate.foo.ConstProp.diff55
-rw-r--r--tests/mir-opt/const_prop/aggregate.foo.PreCodegen.after.mir49
-rw-r--r--tests/mir-opt/const_prop/aggregate.main.ConstProp.diff40
-rw-r--r--tests/mir-opt/const_prop/aggregate.main.PreCodegen.after.mir35
-rw-r--r--tests/mir-opt/const_prop/aggregate.rs9
-rw-r--r--tests/mir-opt/const_prop/bad_op_div_by_zero.main.ConstProp.diff3
-rw-r--r--tests/mir-opt/const_prop/bad_op_mod_by_zero.main.ConstProp.diff18
-rw-r--r--tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.ConstProp.32bit.diff11
-rw-r--r--tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.ConstProp.64bit.diff11
-rw-r--r--tests/mir-opt/const_prop/boolean_identities.test.ConstProp.diff12
-rw-r--r--tests/mir-opt/const_prop/discriminant.main.ConstProp.32bit.diff11
-rw-r--r--tests/mir-opt/const_prop/discriminant.main.ConstProp.64bit.diff11
-rw-r--r--tests/mir-opt/const_prop/inherit_overflow.main.ConstProp.diff39
-rw-r--r--tests/mir-opt/const_prop/inherit_overflow.rs9
-rw-r--r--tests/mir-opt/const_prop/invalid_constant.main.ConstProp.diff6
-rw-r--r--tests/mir-opt/const_prop/issue_66971.main.ConstProp.diff7
-rw-r--r--tests/mir-opt/const_prop/issue_67019.main.ConstProp.diff9
-rw-r--r--tests/mir-opt/const_prop/mult_by_zero.test.ConstProp.diff5
-rw-r--r--tests/mir-opt/const_prop/mutable_variable_aggregate.main.ConstProp.diff25
-rw-r--r--tests/mir-opt/const_prop/mutable_variable_aggregate_mut_ref.main.ConstProp.diff14
-rw-r--r--tests/mir-opt/const_prop/mutable_variable_unprop_assign.main.ConstProp.diff10
-rw-r--r--tests/mir-opt/const_prop/optimizes_into_variable.main.ConstProp.32bit.diff9
-rw-r--r--tests/mir-opt/const_prop/optimizes_into_variable.main.ConstProp.64bit.diff9
-rw-r--r--tests/mir-opt/const_prop/optimizes_into_variable.main.PreCodegen.after.32bit.mir4
-rw-r--r--tests/mir-opt/const_prop/optimizes_into_variable.main.PreCodegen.after.64bit.mir4
-rw-r--r--tests/mir-opt/const_prop/optimizes_into_variable.main.ScalarReplacementOfAggregates.32bit.diff9
-rw-r--r--tests/mir-opt/const_prop/optimizes_into_variable.main.ScalarReplacementOfAggregates.64bit.diff9
-rw-r--r--tests/mir-opt/const_prop/optimizes_into_variable.main.SimplifyLocals-final.after.32bit.mir4
-rw-r--r--tests/mir-opt/const_prop/optimizes_into_variable.main.SimplifyLocals-final.after.64bit.mir4
-rw-r--r--tests/mir-opt/const_prop/ref_deref.main.ConstProp.diff9
-rw-r--r--tests/mir-opt/const_prop/ref_deref.main.PromoteTemps.diff30
-rw-r--r--tests/mir-opt/const_prop/ref_deref.rs3
-rw-r--r--tests/mir-opt/const_prop/ref_deref_project.main.ConstProp.diff4
-rw-r--r--tests/mir-opt/const_prop/ref_deref_project.main.PromoteTemps.diff30
-rw-r--r--tests/mir-opt/const_prop/ref_deref_project.rs3
-rw-r--r--tests/mir-opt/const_prop/scalar_literal_propagation.main.ConstProp.diff8
-rw-r--r--tests/mir-opt/const_prop/slice_len.main.ConstProp.32bit.diff6
-rw-r--r--tests/mir-opt/const_prop/slice_len.main.ConstProp.64bit.diff6
-rw-r--r--tests/mir-opt/const_prop/slice_len.rs3
-rw-r--r--tests/mir-opt/const_prop/tuple_literal_propagation.main.ConstProp.diff13
-rw-r--r--tests/mir-opt/const_prop_miscompile.bar.ConstProp.diff37
-rw-r--r--tests/mir-opt/const_prop_miscompile.foo.ConstProp.diff5
-rw-r--r--tests/mir-opt/const_prop_miscompile.rs1
-rw-r--r--tests/mir-opt/copy-prop/borrowed_local.f.CopyProp.diff34
-rw-r--r--tests/mir-opt/copy-prop/borrowed_local.rs39
-rw-r--r--tests/mir-opt/copy-prop/branch.foo.CopyProp.diff65
-rw-r--r--tests/mir-opt/copy-prop/branch.rs27
-rw-r--r--tests/mir-opt/copy-prop/copy_propagation_arg.arg_src.CopyProp.diff21
-rw-r--r--tests/mir-opt/copy-prop/copy_propagation_arg.bar.CopyProp.diff28
-rw-r--r--tests/mir-opt/copy-prop/copy_propagation_arg.baz.CopyProp.diff18
-rw-r--r--tests/mir-opt/copy-prop/copy_propagation_arg.foo.CopyProp.diff28
-rw-r--r--tests/mir-opt/copy-prop/copy_propagation_arg.rs40
-rw-r--r--tests/mir-opt/copy-prop/custom_move_arg.f.CopyProp.diff31
-rw-r--r--tests/mir-opt/copy-prop/custom_move_arg.rs32
-rw-r--r--tests/mir-opt/copy-prop/cycle.main.CopyProp.diff60
-rw-r--r--tests/mir-opt/copy-prop/cycle.rs15
-rw-r--r--tests/mir-opt/copy-prop/dead_stores_79191.f.CopyProp.after.mir29
-rw-r--r--tests/mir-opt/copy-prop/dead_stores_79191.rs17
-rw-r--r--tests/mir-opt/copy-prop/dead_stores_better.f.CopyProp.after.mir29
-rw-r--r--tests/mir-opt/copy-prop/dead_stores_better.rs21
-rw-r--r--tests/mir-opt/copy-prop/issue_107511.main.CopyProp.diff138
-rw-r--r--tests/mir-opt/copy-prop/issue_107511.rs13
-rw-r--r--tests/mir-opt/copy-prop/move_arg.f.CopyProp.diff40
-rw-r--r--tests/mir-opt/copy-prop/move_arg.rs15
-rw-r--r--tests/mir-opt/copy-prop/move_projection.f.CopyProp.diff31
-rw-r--r--tests/mir-opt/copy-prop/move_projection.rs34
-rw-r--r--tests/mir-opt/copy-prop/mutate_through_pointer.f.CopyProp.diff19
-rw-r--r--tests/mir-opt/copy-prop/mutate_through_pointer.rs32
-rw-r--r--tests/mir-opt/copy-prop/non_dominate.f.CopyProp.diff29
-rw-r--r--tests/mir-opt/copy-prop/non_dominate.rs26
-rw-r--r--tests/mir-opt/dataflow-const-prop/checked.main.DataflowConstProp.diff2
-rw-r--r--tests/mir-opt/dataflow-const-prop/enum.multiple.DataflowConstProp.diff82
-rw-r--r--tests/mir-opt/dataflow-const-prop/enum.mutate_discriminant.DataflowConstProp.diff26
-rw-r--r--tests/mir-opt/dataflow-const-prop/enum.rs61
-rw-r--r--tests/mir-opt/dataflow-const-prop/enum.simple.DataflowConstProp.diff (renamed from tests/mir-opt/dataflow-const-prop/enum.main.DataflowConstProp.diff)26
-rw-r--r--tests/mir-opt/dataflow-const-prop/inherit_overflow.main.DataflowConstProp.diff34
-rw-r--r--tests/mir-opt/dataflow-const-prop/inherit_overflow.rs7
-rw-r--r--tests/mir-opt/dataflow-const-prop/repr_transparent.main.DataflowConstProp.diff8
-rw-r--r--tests/mir-opt/dataflow-const-prop/sibling_ptr.main.DataflowConstProp.diff6
-rw-r--r--tests/mir-opt/dataflow-const-prop/sibling_ptr.rs9
-rw-r--r--tests/mir-opt/dataflow-const-prop/struct.main.DataflowConstProp.diff3
-rw-r--r--tests/mir-opt/dataflow-const-prop/tuple.main.DataflowConstProp.diff8
-rw-r--r--tests/mir-opt/deaggregator_test.bar.Deaggregator.diff21
-rw-r--r--tests/mir-opt/deaggregator_test.rs17
-rw-r--r--tests/mir-opt/deaggregator_test_enum.bar.Deaggregator.diff20
-rw-r--r--tests/mir-opt/deaggregator_test_enum.rs19
-rw-r--r--tests/mir-opt/deaggregator_test_enum_2.rs21
-rw-r--r--tests/mir-opt/deaggregator_test_enum_2.test1.Deaggregator.diff45
-rw-r--r--tests/mir-opt/deaggregator_test_multiple.rs17
-rw-r--r--tests/mir-opt/deaggregator_test_multiple.test.Deaggregator.diff35
-rw-r--r--tests/mir-opt/div_overflow.const_dividend.PreCodegen.after.mir2
-rw-r--r--tests/mir-opt/div_overflow.const_divisor.PreCodegen.after.mir2
-rw-r--r--tests/mir-opt/dont_yeet_assert.generic.InstCombine.diff23
-rw-r--r--tests/mir-opt/dont_yeet_assert.rs11
-rw-r--r--tests/mir-opt/early_otherwise_branch.opt1.EarlyOtherwiseBranch.diff4
-rw-r--r--tests/mir-opt/early_otherwise_branch.opt2.EarlyOtherwiseBranch.diff4
-rw-r--r--tests/mir-opt/early_otherwise_branch.opt3.EarlyOtherwiseBranch.diff4
-rw-r--r--tests/mir-opt/early_otherwise_branch_3_element_tuple.opt1.EarlyOtherwiseBranch.diff5
-rw-r--r--tests/mir-opt/early_otherwise_branch_68867.try_sum.EarlyOtherwiseBranch.diff30
-rw-r--r--tests/mir-opt/early_otherwise_branch_noopt.noopt1.EarlyOtherwiseBranch.diff4
-rw-r--r--tests/mir-opt/enum_opt.cand.EnumSizeOpt.32bit.diff68
-rw-r--r--tests/mir-opt/enum_opt.cand.EnumSizeOpt.64bit.diff68
-rw-r--r--tests/mir-opt/enum_opt.invalid.EnumSizeOpt.32bit.diff28
-rw-r--r--tests/mir-opt/enum_opt.invalid.EnumSizeOpt.64bit.diff28
-rw-r--r--tests/mir-opt/enum_opt.rs86
-rw-r--r--tests/mir-opt/enum_opt.trunc.EnumSizeOpt.32bit.diff37
-rw-r--r--tests/mir-opt/enum_opt.trunc.EnumSizeOpt.64bit.diff37
-rw-r--r--tests/mir-opt/enum_opt.unin.EnumSizeOpt.32bit.diff68
-rw-r--r--tests/mir-opt/enum_opt.unin.EnumSizeOpt.64bit.diff68
-rw-r--r--tests/mir-opt/funky_arms.float_to_exponential_common.ConstProp.diff43
-rw-r--r--tests/mir-opt/generator_drop_cleanup.main-{closure#0}.generator_drop.0.mir9
-rw-r--r--tests/mir-opt/generator_tiny.main-{closure#0}.generator_resume.0.mir13
-rw-r--r--tests/mir-opt/inline/cycle.f.Inline.diff2
-rw-r--r--tests/mir-opt/inline/dyn_trait.get_query.Inline.diff4
-rw-r--r--tests/mir-opt/inline/dyn_trait.try_execute_query.Inline.diff2
-rw-r--r--tests/mir-opt/inline/inline_any_operand.bar.Inline.after.mir2
-rw-r--r--tests/mir-opt/inline/inline_closure.foo.Inline.after.mir14
-rw-r--r--tests/mir-opt/inline/inline_closure_borrows_arg.foo.Inline.after.mir14
-rw-r--r--tests/mir-opt/inline/inline_closure_captures.foo.Inline.after.mir19
-rw-r--r--tests/mir-opt/inline/inline_diverging.h.Inline.diff4
-rw-r--r--tests/mir-opt/inline/inline_generator.main.Inline.diff78
-rw-r--r--tests/mir-opt/inline/inline_into_box_place.main.Inline.diff4
-rw-r--r--tests/mir-opt/inline/inline_trait_method_2.test2.Inline.after.mir2
-rw-r--r--tests/mir-opt/inline/issue_58867_inline_as_ref_as_mut.a.Inline.after.mir6
-rw-r--r--tests/mir-opt/inline/issue_58867_inline_as_ref_as_mut.b.Inline.after.mir18
-rw-r--r--tests/mir-opt/inline/issue_76997_inline_scopes_parenting.main.Inline.after.mir14
-rw-r--r--tests/mir-opt/inline/issue_78442.bar.Inline.diff2
-rw-r--r--tests/mir-opt/inline/issue_78442.bar.RevealAll.diff2
-rw-r--r--tests/mir-opt/intrinsic_asserts.generic.InstCombine.diff42
-rw-r--r--tests/mir-opt/intrinsic_asserts.panics.InstCombine.diff47
-rw-r--r--tests/mir-opt/intrinsic_asserts.removable.InstCombine.diff45
-rw-r--r--tests/mir-opt/intrinsic_asserts.rs28
-rw-r--r--tests/mir-opt/issue_101973.inner.ConstProp.diff22
-rw-r--r--tests/mir-opt/issue_41110.main.ElaborateDrops.after.mir70
-rw-r--r--tests/mir-opt/issue_41110.main.ElaborateDrops.diff75
-rw-r--r--tests/mir-opt/issue_41110.rs4
-rw-r--r--tests/mir-opt/issue_41110.test.ElaborateDrops.after.mir101
-rw-r--r--tests/mir-opt/issue_41110.test.ElaborateDrops.diff109
-rw-r--r--tests/mir-opt/issue_41888.main.ElaborateDrops.after.mir152
-rw-r--r--tests/mir-opt/issue_41888.main.ElaborateDrops.diff158
-rw-r--r--tests/mir-opt/issue_41888.rs2
-rw-r--r--tests/mir-opt/issue_73223.main.SimplifyArmIdentity.diff156
-rw-r--r--tests/mir-opt/issue_73223.rs12
-rw-r--r--tests/mir-opt/issue_76432.rs1
-rw-r--r--tests/mir-opt/issue_76432.test.SimplifyComparisonIntegral.diff18
-rw-r--r--tests/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.mir14
-rw-r--r--tests/mir-opt/issues/issue_75439.foo.MatchBranchSimplification.diff7
-rw-r--r--tests/mir-opt/lower_array_len.array_bound.NormalizeArrayLen.diff6
-rw-r--r--tests/mir-opt/lower_array_len.array_bound_mut.NormalizeArrayLen.diff6
-rw-r--r--tests/mir-opt/lower_array_len.array_len.NormalizeArrayLen.diff6
-rw-r--r--tests/mir-opt/lower_array_len.array_len_by_value.NormalizeArrayLen.diff6
-rw-r--r--tests/mir-opt/lower_array_len.array_len_raw.NormalizeArrayLen.diff50
-rw-r--r--tests/mir-opt/lower_array_len.array_len_reborrow.NormalizeArrayLen.diff44
-rw-r--r--tests/mir-opt/lower_array_len.rs16
-rw-r--r--tests/mir-opt/lower_array_len_e2e.array_bound.PreCodegen.after.mir45
-rw-r--r--tests/mir-opt/lower_array_len_e2e.array_bound_mut.PreCodegen.after.mir58
-rw-r--r--tests/mir-opt/lower_array_len_e2e.array_len.PreCodegen.after.mir11
-rw-r--r--tests/mir-opt/lower_array_len_e2e.array_len_by_value.PreCodegen.after.mir11
-rw-r--r--tests/mir-opt/lower_array_len_e2e.rs39
-rw-r--r--tests/mir-opt/lower_intrinsics.f_copy_nonoverlapping.LowerIntrinsics.diff4
-rw-r--r--tests/mir-opt/lower_intrinsics.rs7
-rw-r--r--tests/mir-opt/lower_intrinsics.with_overflow.LowerIntrinsics.diff83
-rw-r--r--tests/mir-opt/matches_reduce_branches.bar.MatchBranchSimplification.diff10
-rw-r--r--tests/mir-opt/matches_reduce_branches.foo.MatchBranchSimplification.diff2
-rw-r--r--tests/mir-opt/matches_reduce_branches.match_nested_if.MatchBranchSimplification.diff2
-rw-r--r--tests/mir-opt/packed_struct_drop_aligned.main.SimplifyCfg-elaborate-drops.after.mir15
-rw-r--r--tests/mir-opt/remove_storage_markers.main.RemoveStorageMarkers.diff4
-rw-r--r--tests/mir-opt/remove_zsts.get_union.PreCodegen.after.mir5
-rw-r--r--tests/mir-opt/remove_zsts.get_union.RemoveZsts.diff6
-rw-r--r--tests/mir-opt/retag.array_casts.SimplifyCfg-elaborate-drops.after.mir10
-rw-r--r--tests/mir-opt/retag.main.SimplifyCfg-elaborate-drops.after.mir15
-rw-r--r--tests/mir-opt/separate_const_switch.identity.SeparateConstSwitch.diff116
-rw-r--r--tests/mir-opt/separate_const_switch.too_complex.SeparateConstSwitch.diff48
-rw-r--r--tests/mir-opt/simple_option_map_e2e.ezmap.PreCodegen.after.mir21
-rw-r--r--tests/mir-opt/simplify_locals.d1.SimplifyLocals-before-const-prop.diff3
-rw-r--r--tests/mir-opt/simplify_locals.d2.SimplifyLocals-before-const-prop.diff10
-rw-r--r--tests/mir-opt/simplify_locals_fixedpoint.foo.SimplifyLocals-final.diff17
-rw-r--r--tests/mir-opt/simplify_locals_removes_unused_consts.main.SimplifyLocals-before-const-prop.diff30
-rw-r--r--tests/mir-opt/simplify_locals_removes_unused_discriminant_reads.map.SimplifyLocals-before-const-prop.diff7
-rw-r--r--tests/mir-opt/simplify_match.main.ConstProp.diff8
-rw-r--r--tests/mir-opt/slice_filter.rs18
-rw-r--r--tests/mir-opt/slice_filter.variant_a-{closure#0}.CopyProp.diff279
-rw-r--r--tests/mir-opt/slice_filter.variant_a-{closure#0}.DestinationPropagation.diff237
-rw-r--r--tests/mir-opt/slice_filter.variant_b-{closure#0}.CopyProp.diff139
-rw-r--r--tests/mir-opt/slice_filter.variant_b-{closure#0}.DestinationPropagation.diff109
-rw-r--r--tests/mir-opt/sroa.constant.ScalarReplacementOfAggregates.diff46
-rw-r--r--tests/mir-opt/sroa.copies.ScalarReplacementOfAggregates.diff91
-rw-r--r--tests/mir-opt/sroa.dropping.ScalarReplacementOfAggregates.diff14
-rw-r--r--tests/mir-opt/sroa.enums.ScalarReplacementOfAggregates.diff4
-rw-r--r--tests/mir-opt/sroa.escaping.ScalarReplacementOfAggregates.diff47
-rw-r--r--tests/mir-opt/sroa.flat.ScalarReplacementOfAggregates.diff21
-rw-r--r--tests/mir-opt/sroa.ref_copies.ScalarReplacementOfAggregates.diff56
-rw-r--r--tests/mir-opt/sroa.rs48
-rw-r--r--tests/mir-opt/sroa.structs.ScalarReplacementOfAggregates.diff9
-rw-r--r--tests/mir-opt/sroa.unions.ScalarReplacementOfAggregates.diff3
-rw-r--r--tests/mir-opt/try_identity_e2e.new.PreCodegen.after.mir39
-rw-r--r--tests/mir-opt/try_identity_e2e.old.PreCodegen.after.mir10
-rw-r--r--tests/mir-opt/uninhabited_enum_branching.main.SimplifyCfg-after-uninhabited-enum-branching.after.mir6
-rw-r--r--tests/mir-opt/uninhabited_enum_branching.main.UninhabitedEnumBranching.diff6
-rw-r--r--tests/mir-opt/uninhabited_enum_branching2.main.SimplifyCfg-after-uninhabited-enum-branching.after.mir7
-rw-r--r--tests/mir-opt/uninhabited_enum_branching2.main.UninhabitedEnumBranching.diff7
-rw-r--r--tests/mir-opt/unusual_item_types.Test-X-{constructor#0}.built.after.mir4
-rw-r--r--tests/mir-opt/while_let_loops.change_loop_body.ConstProp.diff3
-rw-r--r--tests/mir-opt/while_storage.while_loop.PreCodegen.after.mir22
-rw-r--r--tests/pretty/dollar-crate.pp4
-rw-r--r--tests/pretty/issue-4264.pp9
-rw-r--r--tests/run-make-fulldeps/hotplug_codegen_backend/the_backend.rs2
-rw-r--r--tests/run-make-fulldeps/issue-19371/foo.rs1
-rw-r--r--tests/run-make-fulldeps/issues-41478-43796/Makefile8
-rw-r--r--tests/run-make-fulldeps/issues-41478-43796/a.rs9
-rw-r--r--tests/run-make-fulldeps/save-analysis-fail/Makefile6
-rw-r--r--tests/run-make-fulldeps/save-analysis-fail/SameDir.rs5
-rw-r--r--tests/run-make-fulldeps/save-analysis-fail/SameDir3.rs3
-rw-r--r--tests/run-make-fulldeps/save-analysis-fail/SubDir/mod.rs27
-rw-r--r--tests/run-make-fulldeps/save-analysis-fail/foo.rs463
-rw-r--r--tests/run-make-fulldeps/save-analysis-fail/krate2.rs8
-rw-r--r--tests/run-make-fulldeps/save-analysis-rfc2126/Makefile8
-rw-r--r--tests/run-make-fulldeps/save-analysis-rfc2126/extern_absolute_paths.rs6
-rw-r--r--tests/run-make-fulldeps/save-analysis-rfc2126/krate2.rs5
-rw-r--r--tests/run-make-fulldeps/save-analysis-rfc2126/validate_json.py7
-rw-r--r--tests/run-make-fulldeps/save-analysis/Makefile6
-rw-r--r--tests/run-make-fulldeps/save-analysis/SameDir.rs5
-rw-r--r--tests/run-make-fulldeps/save-analysis/SameDir3.rs3
-rw-r--r--tests/run-make-fulldeps/save-analysis/SubDir/mod.rs27
-rw-r--r--tests/run-make-fulldeps/save-analysis/extra-docs.md1
-rw-r--r--tests/run-make-fulldeps/save-analysis/foo.rs465
-rw-r--r--tests/run-make-fulldeps/save-analysis/krate2.rs8
-rw-r--r--tests/run-make-fulldeps/split-debuginfo/Makefile4
-rw-r--r--tests/run-make-fulldeps/type-mismatch-same-crate-name/Makefile2
-rw-r--r--tests/run-make/incremental-session-fail/Makefile2
-rw-r--r--tests/run-make/native-link-modifier-bundle/Makefile5
-rw-r--r--tests/run-make/no-input-file/Makefile4
-rw-r--r--tests/run-make/no-input-file/no-input-file.stderr2
-rw-r--r--tests/run-make/overwrite-input/Makefile13
-rw-r--r--tests/run-make/overwrite-input/file.stderr6
-rw-r--r--tests/run-make/overwrite-input/folder.stderr6
-rw-r--r--tests/run-make/overwrite-input/main.rs1
-rw-r--r--tests/run-make/overwrite-input/main.stderr6
-rw-r--r--tests/run-make/raw-dylib-inline-cross-dylib/Makefile10
-rw-r--r--tests/run-make/rlib-format-packed-bundled-libs-2/Makefile5
-rw-r--r--tests/run-make/rlib-format-packed-bundled-libs-3/Makefile35
-rw-r--r--tests/run-make/rlib-format-packed-bundled-libs-3/main.rs5
-rw-r--r--tests/run-make/rlib-format-packed-bundled-libs-3/native_dep_1.c1
-rw-r--r--tests/run-make/rlib-format-packed-bundled-libs-3/native_dep_2.c1
-rw-r--r--tests/run-make/rlib-format-packed-bundled-libs-3/native_dep_3.c1
-rw-r--r--tests/run-make/rlib-format-packed-bundled-libs-3/native_dep_4.c1
-rw-r--r--tests/run-make/rlib-format-packed-bundled-libs-3/rust_dep.rs16
-rw-r--r--tests/run-make/rlib-format-packed-bundled-libs-3/rust_dep_cfg.rs10
-rw-r--r--tests/run-make/rlib-format-packed-bundled-libs/Makefile5
-rw-r--r--tests/run-make/translation/Makefile18
-rw-r--r--tests/rustdoc-gui/code-tags.goml10
-rw-r--r--tests/rustdoc-gui/codeblock-tooltip.goml94
-rw-r--r--tests/rustdoc-gui/font-weight.goml9
-rw-r--r--tests/rustdoc-gui/help-page.goml3
-rw-r--r--tests/rustdoc-gui/huge-collection-of-constants.goml4
-rw-r--r--tests/rustdoc-gui/item-summary-table.goml4
-rw-r--r--tests/rustdoc-gui/label-next-to-symbol.goml36
-rw-r--r--tests/rustdoc-gui/list_code_block.goml2
-rw-r--r--tests/rustdoc-gui/mobile.goml6
-rw-r--r--tests/rustdoc-gui/module-items-font.goml26
-rw-r--r--tests/rustdoc-gui/notable-trait.goml128
-rw-r--r--tests/rustdoc-gui/scrape-examples-color.goml36
-rw-r--r--tests/rustdoc-gui/scrape-examples-layout.goml8
-rw-r--r--tests/rustdoc-gui/search-error.goml39
-rw-r--r--tests/rustdoc-gui/search-result-display.goml4
-rw-r--r--tests/rustdoc-gui/settings.goml42
-rw-r--r--tests/rustdoc-gui/sidebar-mobile-scroll.goml6
-rw-r--r--tests/rustdoc-gui/sidebar-mobile.goml2
-rw-r--r--tests/rustdoc-gui/sidebar.goml10
-rw-r--r--tests/rustdoc-gui/src-font-size.goml10
-rw-r--r--tests/rustdoc-gui/src/test_docs/lib.rs16
-rw-r--r--tests/rustdoc-gui/theme-change.goml8
-rw-r--r--tests/rustdoc-gui/type-declation-overflow.goml18
-rw-r--r--tests/rustdoc-gui/unsafe-fn.goml6
-rw-r--r--tests/rustdoc-js-std/parser-errors.js34
-rw-r--r--tests/rustdoc-js-std/parser-filter.js47
-rw-r--r--tests/rustdoc-js-std/parser-ident.js40
-rw-r--r--tests/rustdoc-js-std/reference-shrink.js8
-rw-r--r--tests/rustdoc-js-std/regex.js10
-rw-r--r--tests/rustdoc-js-std/typed-query.js4
-rw-r--r--tests/rustdoc-js/doc-alias.js2
-rw-r--r--tests/rustdoc-js/macro-search.js10
-rw-r--r--tests/rustdoc-js/macro-search.rs10
-rw-r--r--tests/rustdoc-js/module-substring.js1
-rw-r--r--tests/rustdoc-json/reexport/same_name_different_types.rs25
-rw-r--r--tests/rustdoc-ui/auxiliary/panic-handler.rs9
-rw-r--r--tests/rustdoc-ui/bounded-hr-lifetime.stderr4
-rw-r--r--tests/rustdoc-ui/check-fail.rs1
-rw-r--r--tests/rustdoc-ui/check-fail.stderr18
-rw-r--r--tests/rustdoc-ui/check.rs1
-rw-r--r--tests/rustdoc-ui/check.stderr12
-rw-r--r--tests/rustdoc-ui/feature-gate-doc_cfg_hide.stderr4
-rw-r--r--tests/rustdoc-ui/feature-gate-rustdoc_missing_doc_code_examples.rs4
-rw-r--r--tests/rustdoc-ui/feature-gate-rustdoc_missing_doc_code_examples.stderr14
-rw-r--r--tests/rustdoc-ui/impl-fn-nesting.stderr4
-rw-r--r--tests/rustdoc-ui/infinite-recursive-type-impl-trait-return.rs4
-rw-r--r--tests/rustdoc-ui/infinite-recursive-type-impl-trait-return.stderr16
-rw-r--r--tests/rustdoc-ui/infinite-recursive-type-impl-trait.rs5
-rw-r--r--tests/rustdoc-ui/infinite-recursive-type-impl-trait.stderr16
-rw-r--r--tests/rustdoc-ui/intra-doc/errors.rs16
-rw-r--r--tests/rustdoc-ui/intra-doc/errors.stderr14
-rw-r--r--tests/rustdoc-ui/intra-doc/import-inline-merge.rs16
-rw-r--r--tests/rustdoc-ui/intra-doc/proc-macro-doc.rs27
-rw-r--r--tests/rustdoc-ui/intra-doc/unknown-disambiguator.stderr32
-rw-r--r--tests/rustdoc-ui/intra-doc/unresolved-import-recovery.stderr4
-rw-r--r--tests/rustdoc-ui/issue-105742.rs21
-rw-r--r--tests/rustdoc-ui/issue-105742.stderr362
-rw-r--r--tests/rustdoc-ui/issue-107918.rs12
-rw-r--r--tests/rustdoc-ui/issue-61732.stderr4
-rw-r--r--tests/rustdoc-ui/lint-group.rs1
-rw-r--r--tests/rustdoc-ui/lint-group.stderr20
-rw-r--r--tests/rustdoc-ui/proc_macro_bug.rs12
-rw-r--r--tests/rustdoc-ui/proc_macro_bug.stderr8
-rw-r--r--tests/rustdoc-ui/rustdoc-all-only-stable-lints.rs6
-rw-r--r--tests/rustdoc-ui/track-diagnostics.stderr2
-rw-r--r--tests/rustdoc-ui/unable-fulfill-trait.stderr2
-rw-r--r--tests/rustdoc-ui/unknown-renamed-lints.stderr4
-rw-r--r--tests/rustdoc-ui/z-help.stdout361
-rw-r--r--tests/rustdoc/anchors.no_const_anchor.html2
-rw-r--r--tests/rustdoc/anchors.no_const_anchor2.html2
-rw-r--r--tests/rustdoc/anchors.no_method_anchor.html2
-rw-r--r--tests/rustdoc/anchors.no_trait_method_anchor.html2
-rw-r--r--tests/rustdoc/anchors.no_tymethod_anchor.html2
-rw-r--r--tests/rustdoc/anchors.no_type_anchor.html2
-rw-r--r--tests/rustdoc/anchors.no_type_anchor2.html2
-rw-r--r--tests/rustdoc/array-links.rs8
-rw-r--r--tests/rustdoc/assoc-consts.rs2
-rw-r--r--tests/rustdoc/assoc-item-cast.rs2
-rw-r--r--tests/rustdoc/assoc-types.rs12
-rw-r--r--tests/rustdoc/async-fn-opaque-item.rs15
-rw-r--r--tests/rustdoc/async-fn.rs36
-rw-r--r--tests/rustdoc/attribute-rendering.rs2
-rw-r--r--tests/rustdoc/attributes.rs6
-rw-r--r--tests/rustdoc/auxiliary/inline-default-methods.rs12
-rw-r--r--tests/rustdoc/auxiliary/issue-85454.rs2
-rw-r--r--tests/rustdoc/cfg_doc_reexport.rs4
-rw-r--r--tests/rustdoc/codeblock-title.rs2
-rw-r--r--tests/rustdoc/const-fn.rs4
-rw-r--r--tests/rustdoc/const-generics/add-impl.rs2
-rw-r--r--tests/rustdoc/const-generics/const-generic-defaults.rs2
-rw-r--r--tests/rustdoc/const-generics/const-generic-slice.rs2
-rw-r--r--tests/rustdoc/const-generics/const-generics-docs.rs44
-rw-r--r--tests/rustdoc/const-generics/const-impl.rs12
-rw-r--r--tests/rustdoc/const-generics/generic_const_exprs.rs2
-rw-r--r--tests/rustdoc/const-generics/type-alias.rs2
-rw-r--r--tests/rustdoc/const-intrinsic.rs6
-rw-r--r--tests/rustdoc/const-value-display.rs4
-rw-r--r--tests/rustdoc/decl-trailing-whitespace.declaration.html24
-rw-r--r--tests/rustdoc/decl-trailing-whitespace.rs2
-rw-r--r--tests/rustdoc/deprecated.rs6
-rw-r--r--tests/rustdoc/description.rs6
-rw-r--r--tests/rustdoc/doc-assoc-item.rs2
-rw-r--r--tests/rustdoc/doc-cfg.rs6
-rw-r--r--tests/rustdoc/doc-notable_trait.rs6
-rw-r--r--tests/rustdoc/doc-notable_trait.some-struct-new.html2
-rw-r--r--tests/rustdoc/doc-notable_trait.wrap-me.html2
-rw-r--r--tests/rustdoc/document-item-with-associated-const-in-where-clause.rs17
-rw-r--r--tests/rustdoc/double-quote-escape.rs2
-rw-r--r--tests/rustdoc/duplicate-cfg.rs4
-rw-r--r--tests/rustdoc/duplicate_impls/issue-33054.rs4
-rw-r--r--tests/rustdoc/duplicated_impl.rs2
-rw-r--r--tests/rustdoc/empty-impl-block-private-with-doc.rs2
-rw-r--r--tests/rustdoc/empty-impl-block-private.rs2
-rw-r--r--tests/rustdoc/empty-impl-block.rs2
-rw-r--r--tests/rustdoc/fn-pointer-arg-name.rs2
-rw-r--r--tests/rustdoc/generic-associated-types/gats.rs4
-rw-r--r--tests/rustdoc/glob-shadowing-const.rs4
-rw-r--r--tests/rustdoc/glob-shadowing.rs18
-rw-r--r--tests/rustdoc/hidden-private.rs50
-rw-r--r--tests/rustdoc/hide-complex-unevaluated-const-arguments.rs2
-rw-r--r--tests/rustdoc/impl-in-const-block.rs43
-rw-r--r--tests/rustdoc/impl-parts.rs2
-rw-r--r--tests/rustdoc/inline-default-methods.rs16
-rw-r--r--tests/rustdoc/inline_cross/dyn_trait.rs12
-rw-r--r--tests/rustdoc/inline_cross/impl_trait.rs32
-rw-r--r--tests/rustdoc/inline_cross/issue-24183.rs4
-rw-r--r--tests/rustdoc/inline_cross/issue-31948-1.rs4
-rw-r--r--tests/rustdoc/inline_cross/issue-31948-2.rs6
-rw-r--r--tests/rustdoc/inline_cross/issue-31948.rs6
-rw-r--r--tests/rustdoc/inline_cross/macros.rs4
-rw-r--r--tests/rustdoc/internal.rs6
-rw-r--r--tests/rustdoc/intra-doc/basic.rs29
-rw-r--r--tests/rustdoc/issue-107995.rs28
-rw-r--r--tests/rustdoc/issue-108231.rs23
-rw-r--r--tests/rustdoc/issue-108281.rs25
-rw-r--r--tests/rustdoc/issue-20646.rs4
-rw-r--r--tests/rustdoc/issue-20727-2.rs12
-rw-r--r--tests/rustdoc/issue-20727-3.rs12
-rw-r--r--tests/rustdoc/issue-20727-4.rs20
-rw-r--r--tests/rustdoc/issue-20727.rs12
-rw-r--r--tests/rustdoc/issue-21474.rs2
-rw-r--r--tests/rustdoc/issue-22038.rs8
-rw-r--r--tests/rustdoc/issue-32374.rs6
-rw-r--r--tests/rustdoc/issue-33302.rs12
-rw-r--r--tests/rustdoc/issue-34928.rs2
-rw-r--r--tests/rustdoc/issue-45584.rs8
-rw-r--r--tests/rustdoc/issue-46377.rs2
-rw-r--r--tests/rustdoc/issue-50159.rs2
-rw-r--r--tests/rustdoc/issue-51236.rs2
-rw-r--r--tests/rustdoc/issue-53812.rs10
-rw-r--r--tests/rustdoc/issue-54705.rs4
-rw-r--r--tests/rustdoc/issue-55321.rs8
-rw-r--r--tests/rustdoc/issue-55364.rs8
-rw-r--r--tests/rustdoc/issue-56822.rs2
-rw-r--r--tests/rustdoc/issue-60726.rs4
-rw-r--r--tests/rustdoc/issue-76501.rs2
-rw-r--r--tests/rustdoc/issue-78673.rs8
-rw-r--r--tests/rustdoc/issue-83375-multiple-mods-w-same-name-doc-inline-last-item.rs2
-rw-r--r--tests/rustdoc/issue-83375-multiple-mods-w-same-name-doc-inline.rs2
-rw-r--r--tests/rustdoc/issue-85454.rs4
-rw-r--r--tests/rustdoc/issue-95873.rs2
-rw-r--r--tests/rustdoc/issue-98697.rs4
-rw-r--r--tests/rustdoc/issue-99221-multiple-structs-w-same-name.rs2
-rw-r--r--tests/rustdoc/issue-99734-multiple-foreigns-w-same-name.rs2
-rw-r--r--tests/rustdoc/issue-99734-multiple-mods-w-same-name.rs2
-rw-r--r--tests/rustdoc/item-desc-list-at-start.item-table.html1
-rw-r--r--tests/rustdoc/item-desc-list-at-start.rs9
-rw-r--r--tests/rustdoc/legacy-const-generic.rs4
-rw-r--r--tests/rustdoc/lifetime-name.rs2
-rw-r--r--tests/rustdoc/macro-higher-kinded-function.rs4
-rw-r--r--tests/rustdoc/markdown-summaries.rs27
-rw-r--r--tests/rustdoc/mut-params.rs6
-rw-r--r--tests/rustdoc/negative-impl.rs4
-rw-r--r--tests/rustdoc/normalize-assoc-item.rs16
-rw-r--r--tests/rustdoc/playground-arg.rs2
-rw-r--r--tests/rustdoc/playground.rs6
-rw-r--r--tests/rustdoc/primitive-reference.rs2
-rw-r--r--tests/rustdoc/primitive-tuple-variadic.rs4
-rw-r--r--tests/rustdoc/pub-method.rs6
-rw-r--r--tests/rustdoc/range-arg-pattern.rs2
-rw-r--r--tests/rustdoc/redirect.rs3
-rw-r--r--tests/rustdoc/reexport-attr-merge.rs33
-rw-r--r--tests/rustdoc/reexport-check.rs8
-rw-r--r--tests/rustdoc/reexport-dep-foreign-fn.rs2
-rw-r--r--tests/rustdoc/reexport-hidden-macro.rs22
-rw-r--r--tests/rustdoc/reexport-macro.rs23
-rw-r--r--tests/rustdoc/reexports-of-same-name.rs26
-rw-r--r--tests/rustdoc/reexports-priv.rs48
-rw-r--r--tests/rustdoc/reexports.rs24
-rw-r--r--tests/rustdoc/rfc-2632-const-trait-impl.rs16
-rw-r--r--tests/rustdoc/safe-intrinsic.rs6
-rw-r--r--tests/rustdoc/short-docblock-codeblock.rs2
-rw-r--r--tests/rustdoc/short-docblock.rs10
-rw-r--r--tests/rustdoc/sidebar-links-to-foreign-impl.rs4
-rw-r--r--tests/rustdoc/slice-links.rs8
-rw-r--r--tests/rustdoc/spotlight-from-dependency.rs2
-rw-r--r--tests/rustdoc/struct-arg-pattern.rs2
-rw-r--r--tests/rustdoc/synthetic_auto/basic.rs4
-rw-r--r--tests/rustdoc/synthetic_auto/complex.rs2
-rw-r--r--tests/rustdoc/synthetic_auto/lifetimes.rs4
-rw-r--r--tests/rustdoc/synthetic_auto/manual.rs8
-rw-r--r--tests/rustdoc/synthetic_auto/negative.rs4
-rw-r--r--tests/rustdoc/synthetic_auto/nested.rs4
-rw-r--r--tests/rustdoc/synthetic_auto/no-redundancy.rs2
-rw-r--r--tests/rustdoc/synthetic_auto/project.rs4
-rw-r--r--tests/rustdoc/synthetic_auto/self-referential.rs2
-rw-r--r--tests/rustdoc/synthetic_auto/static-region.rs2
-rw-r--r--tests/rustdoc/test-parens.rs2
-rw-r--r--tests/rustdoc/toggle-item-contents.rs6
-rw-r--r--tests/rustdoc/trait_alias.rs6
-rw-r--r--tests/rustdoc/tuple-struct-fields-doc.rs2
-rw-r--r--tests/rustdoc/tuples.rs12
-rw-r--r--tests/rustdoc/typedef.rs4
-rw-r--r--tests/rustdoc/unit-return.rs8
-rw-r--r--tests/rustdoc/where-clause-order.rs2
-rw-r--r--tests/rustdoc/where-sized.rs4
-rw-r--r--tests/rustdoc/where.SWhere_Simd_item-decl.html4
-rw-r--r--tests/rustdoc/where.SWhere_TraitWhere_item-decl.html19
-rw-r--r--tests/rustdoc/where.rs20
-rw-r--r--tests/rustdoc/whitespace-after-where-clause.enum.html7
-rw-r--r--tests/rustdoc/whitespace-after-where-clause.enum2.html6
-rw-r--r--tests/rustdoc/whitespace-after-where-clause.rs16
-rw-r--r--tests/rustdoc/whitespace-after-where-clause.struct.html7
-rw-r--r--tests/rustdoc/whitespace-after-where-clause.struct2.html6
-rw-r--r--tests/rustdoc/whitespace-after-where-clause.trait.html6
-rw-r--r--tests/rustdoc/whitespace-after-where-clause.trait2.html5
-rw-r--r--tests/rustdoc/whitespace-after-where-clause.union.html5
-rw-r--r--tests/rustdoc/whitespace-after-where-clause.union2.html4
-rw-r--r--tests/rustdoc/wrapping.rs4
-rw-r--r--tests/ui-fulldeps/auxiliary/issue-40001-plugin.rs4
-rw-r--r--tests/ui-fulldeps/create-dir-all-bare.rs11
-rw-r--r--tests/ui-fulldeps/dropck-tarena-cycle-checked.stderr2
-rw-r--r--tests/ui-fulldeps/dropck-tarena-unsound-drop.stderr2
-rw-r--r--tests/ui-fulldeps/fluent-messages/duplicate.ftl3
-rw-r--r--tests/ui-fulldeps/fluent-messages/label-with-hyphens.ftl2
-rw-r--r--tests/ui-fulldeps/fluent-messages/missing-crate-name.ftl2
-rw-r--r--tests/ui-fulldeps/fluent-messages/missing-message-ref.ftl1
-rw-r--r--tests/ui-fulldeps/fluent-messages/missing-message.ftl2
-rw-r--r--tests/ui-fulldeps/fluent-messages/slug-with-hyphens.ftl2
-rw-r--r--tests/ui-fulldeps/fluent-messages/test.rs68
-rw-r--r--tests/ui-fulldeps/fluent-messages/test.stderr95
-rw-r--r--tests/ui-fulldeps/fluent-messages/valid.ftl2
-rw-r--r--tests/ui-fulldeps/internal-lints/diagnostics.ftl (renamed from compiler/rustc_error_messages/locales/en-US/compiletest.ftl)2
-rw-r--r--tests/ui-fulldeps/internal-lints/diagnostics.rs16
-rw-r--r--tests/ui-fulldeps/internal-lints/diagnostics.stderr12
-rw-r--r--tests/ui-fulldeps/internal-lints/ty_tykind_usage.rs1
-rw-r--r--tests/ui-fulldeps/internal-lints/ty_tykind_usage.stderr32
-rw-r--r--tests/ui-fulldeps/mod_dir_path_canonicalized.rs5
-rw-r--r--tests/ui-fulldeps/pprust-expr-roundtrip.rs16
-rw-r--r--tests/ui-fulldeps/rename-directory.rs30
-rw-r--r--tests/ui-fulldeps/session-diagnostic/diagnostic-derive.rs302
-rw-r--r--tests/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr344
-rw-r--r--tests/ui-fulldeps/session-diagnostic/example.ftl5
-rw-r--r--tests/ui-fulldeps/session-diagnostic/subdiagnostic-derive.rs160
-rw-r--r--tests/ui-fulldeps/session-diagnostic/subdiagnostic-derive.stderr281
-rw-r--r--tests/ui-fulldeps/std/issue-15149.rs (renamed from tests/ui-fulldeps/issue-15149.rs)0
-rw-r--r--tests/ui-fulldeps/std/issue-81357-unsound-file-methods.rs (renamed from tests/ui-fulldeps/issue-81357-unsound-file-methods.rs)0
-rw-r--r--tests/ui-fulldeps/std/stdio-from.rs (renamed from tests/ui-fulldeps/stdio-from.rs)0
-rw-r--r--tests/ui-fulldeps/std/switch-stdout.rs (renamed from tests/ui-fulldeps/switch-stdout.rs)0
-rw-r--r--tests/ui/abi/stack-probes-lto.rs1
-rw-r--r--tests/ui/abi/stack-probes.rs1
-rw-r--r--tests/ui/alloc-error/alloc-error-handler-bad-signature-1.stderr2
-rw-r--r--tests/ui/alloc-error/alloc-error-handler-bad-signature-2.stderr8
-rw-r--r--tests/ui/alloc-error/alloc-error-handler-bad-signature-3.stderr6
-rw-r--r--tests/ui/argument-suggestions/basic.stderr9
-rw-r--r--tests/ui/argument-suggestions/exotic-calls.stderr36
-rw-r--r--tests/ui/argument-suggestions/extra_arguments.rs8
-rw-r--r--tests/ui/argument-suggestions/extra_arguments.stderr214
-rw-r--r--tests/ui/argument-suggestions/formal-and-expected-differ.stderr4
-rw-r--r--tests/ui/argument-suggestions/invalid_arguments.stderr48
-rw-r--r--tests/ui/argument-suggestions/issue-100154.stderr2
-rw-r--r--tests/ui/argument-suggestions/issue-100478.stderr2
-rw-r--r--tests/ui/argument-suggestions/issue-101097.stderr8
-rw-r--r--tests/ui/argument-suggestions/issue-97484.stderr13
-rw-r--r--tests/ui/argument-suggestions/mixed_cases.stderr17
-rw-r--r--tests/ui/argument-suggestions/too-long.stderr2
-rw-r--r--tests/ui/argument-suggestions/two-mismatch-notes.stderr5
-rw-r--r--tests/ui/array-slice-vec/array-not-vector.rs4
-rw-r--r--tests/ui/array-slice-vec/array-not-vector.stderr4
-rw-r--r--tests/ui/array-slice-vec/slice-to-vec-comparison.stderr2
-rw-r--r--tests/ui/asm/issue-72570.rs2
-rw-r--r--tests/ui/asm/issue-72570.stderr2
-rw-r--r--tests/ui/asm/type-check-4.stderr6
-rw-r--r--tests/ui/associated-consts/associated-const-generic-obligations.stderr2
-rw-r--r--tests/ui/associated-consts/issue-105330.stderr2
-rw-r--r--tests/ui/associated-inherent-types/ambiguity.rs16
-rw-r--r--tests/ui/associated-inherent-types/ambiguity.stderr20
-rw-r--r--tests/ui/associated-inherent-types/bugs/ice-substitution.rs23
-rw-r--r--tests/ui/associated-inherent-types/bugs/ice-substitution.stderr6
-rw-r--r--tests/ui/associated-inherent-types/bugs/inference-fail.rs15
-rw-r--r--tests/ui/associated-inherent-types/bugs/inference-fail.stderr9
-rw-r--r--tests/ui/associated-inherent-types/bugs/lack-of-regionck.rs19
-rw-r--r--tests/ui/associated-inherent-types/dispatch-on-self-type-0.rs41
-rw-r--r--tests/ui/associated-inherent-types/dispatch-on-self-type-1.rs39
-rw-r--r--tests/ui/associated-inherent-types/dispatch-on-self-type-2.rs17
-rw-r--r--tests/ui/associated-inherent-types/dispatch-on-self-type-2.stderr19
-rw-r--r--tests/ui/associated-inherent-types/not-found-self-type-differs-shadowing-trait-item.rs31
-rw-r--r--tests/ui/associated-inherent-types/not-found-self-type-differs-shadowing-trait-item.shadowed.stderr15
-rw-r--r--tests/ui/associated-inherent-types/not-found-self-type-differs-shadowing-trait-item.uncovered.stderr9
-rw-r--r--tests/ui/associated-inherent-types/not-found-self-type-differs.alias.stderr16
-rw-r--r--tests/ui/associated-inherent-types/not-found-self-type-differs.local.stderr16
-rw-r--r--tests/ui/associated-inherent-types/not-found-self-type-differs.rs22
-rw-r--r--tests/ui/associated-inherent-types/not-found-unsatisfied-bounds-0.rs21
-rw-r--r--tests/ui/associated-inherent-types/not-found-unsatisfied-bounds-0.stderr27
-rw-r--r--tests/ui/associated-inherent-types/not-found-unsatisfied-bounds-1.rs18
-rw-r--r--tests/ui/associated-inherent-types/not-found-unsatisfied-bounds-1.stderr14
-rw-r--r--tests/ui/associated-inherent-types/not-found-unsatisfied-bounds-in-multiple-impls.rs20
-rw-r--r--tests/ui/associated-inherent-types/not-found-unsatisfied-bounds-in-multiple-impls.stderr20
-rw-r--r--tests/ui/associated-inherent-types/substitute-params-bad.rs23
-rw-r--r--tests/ui/associated-inherent-types/substitute-params-bad.stderr20
-rw-r--r--tests/ui/associated-inherent-types/substitute-params.rs (renamed from tests/ui/associated-inherent-types/struct-generics.rs)8
-rw-r--r--tests/ui/associated-type-bounds/bad-universal-in-dyn-in-where-clause.rs14
-rw-r--r--tests/ui/associated-type-bounds/bad-universal-in-dyn-in-where-clause.stderr8
-rw-r--r--tests/ui/associated-type-bounds/bad-universal-in-impl-sig.rs13
-rw-r--r--tests/ui/associated-type-bounds/bad-universal-in-impl-sig.stderr8
-rw-r--r--tests/ui/associated-type-bounds/elision.stderr6
-rw-r--r--tests/ui/associated-type-bounds/inside-adt.rs22
-rw-r--r--tests/ui/associated-type-bounds/inside-adt.stderr105
-rw-r--r--tests/ui/associated-type-bounds/issue-71443-1.stderr2
-rw-r--r--tests/ui/associated-types/associated-type-projection-from-supertrait.stderr12
-rw-r--r--tests/ui/associated-types/associated-types-eq-3.rs2
-rw-r--r--tests/ui/associated-types/associated-types-eq-3.stderr2
-rw-r--r--tests/ui/associated-types/associated-types-eq-hr.stderr12
-rw-r--r--tests/ui/associated-types/associated-types-outlives.stderr3
-rw-r--r--tests/ui/associated-types/defaults-in-other-trait-items.rs14
-rw-r--r--tests/ui/associated-types/defaults-in-other-trait-items.stderr17
-rw-r--r--tests/ui/associated-types/defaults-suitability.stderr6
-rw-r--r--tests/ui/associated-types/hr-associated-type-bound-1.stderr2
-rw-r--r--tests/ui/associated-types/hr-associated-type-bound-object.stderr2
-rw-r--r--tests/ui/associated-types/hr-associated-type-bound-param-1.stderr2
-rw-r--r--tests/ui/associated-types/hr-associated-type-bound-param-2.stderr6
-rw-r--r--tests/ui/associated-types/hr-associated-type-bound-param-3.stderr2
-rw-r--r--tests/ui/associated-types/hr-associated-type-bound-param-4.stderr2
-rw-r--r--tests/ui/associated-types/hr-associated-type-bound-param-5.stderr4
-rw-r--r--tests/ui/associated-types/hr-associated-type-projection-1.stderr6
-rw-r--r--tests/ui/associated-types/issue-26681.stderr4
-rw-r--r--tests/ui/associated-types/issue-38821.rs (renamed from tests/ui/issues/issue-38821.rs)0
-rw-r--r--tests/ui/associated-types/issue-38821.stderr (renamed from tests/ui/issues/issue-38821.stderr)0
-rw-r--r--tests/ui/associated-types/issue-43924.stderr2
-rw-r--r--tests/ui/associated-types/issue-87261.rs6
-rw-r--r--tests/ui/associated-types/issue-87261.stderr6
-rw-r--r--tests/ui/associated-types/point-at-type-on-obligation-failure-2.stderr4
-rw-r--r--tests/ui/async-await/async-await-let-else.drop_tracking.stderr106
-rw-r--r--tests/ui/async-await/async-await-let-else.drop_tracking_mir.stderr100
-rw-r--r--tests/ui/async-await/async-await-let-else.no_drop_tracking.stderr90
-rw-r--r--tests/ui/async-await/async-await-let-else.rs6
-rw-r--r--tests/ui/async-await/async-block-control-flow-static-semantics.stderr4
-rw-r--r--tests/ui/async-await/async-error-span.drop_tracking.stderr (renamed from tests/ui/async-await/async-error-span.stderr)6
-rw-r--r--tests/ui/async-await/async-error-span.drop_tracking_mir.stderr24
-rw-r--r--tests/ui/async-await/async-error-span.no_drop_tracking.stderr25
-rw-r--r--tests/ui/async-await/async-error-span.rs7
-rw-r--r--tests/ui/async-await/async-fn-nonsend.drop_tracking.stderr49
-rw-r--r--tests/ui/async-await/async-fn-nonsend.drop_tracking_mir.stderr43
-rw-r--r--tests/ui/async-await/async-fn-nonsend.no_drop_tracking.stderr120
-rw-r--r--tests/ui/async-await/async-fn-nonsend.rs8
-rw-r--r--tests/ui/async-await/async-fn-nonsend.stderr12
-rw-r--r--tests/ui/async-await/async-fn-path-elision.stderr1
-rw-r--r--tests/ui/async-await/default-struct-update.rs4
-rw-r--r--tests/ui/async-await/dont-suggest-missing-await.stderr12
-rw-r--r--tests/ui/async-await/drop-and-assign.rs4
-rw-r--r--tests/ui/async-await/drop-track-field-assign-nonsend.drop_tracking.stderr (renamed from tests/ui/async-await/drop-track-field-assign-nonsend.stderr)6
-rw-r--r--tests/ui/async-await/drop-track-field-assign-nonsend.drop_tracking_mir.stderr23
-rw-r--r--tests/ui/async-await/drop-track-field-assign-nonsend.no_drop_tracking.stderr25
-rw-r--r--tests/ui/async-await/drop-track-field-assign-nonsend.rs4
-rw-r--r--tests/ui/async-await/drop-track-field-assign.rs4
-rw-r--r--tests/ui/async-await/field-assign-nonsend.drop_tracking.stderr25
-rw-r--r--tests/ui/async-await/field-assign-nonsend.drop_tracking_mir.stderr23
-rw-r--r--tests/ui/async-await/field-assign-nonsend.no_drop_tracking.stderr25
-rw-r--r--tests/ui/async-await/field-assign-nonsend.rs47
-rw-r--r--tests/ui/async-await/field-assign.rs46
-rw-r--r--tests/ui/async-await/future-sizes/async-awaiting-fut.rs24
-rw-r--r--tests/ui/async-await/future-sizes/async-awaiting-fut.stdout72
-rw-r--r--tests/ui/async-await/future-sizes/future-as-arg.rs16
-rw-r--r--tests/ui/async-await/future-sizes/large-arg.rs18
-rw-r--r--tests/ui/async-await/future-sizes/large-arg.stdout60
-rw-r--r--tests/ui/async-await/generator-desc.stderr14
-rw-r--r--tests/ui/async-await/in-trait/async-default-fn-overridden.rs66
-rw-r--r--tests/ui/async-await/in-trait/async-default-fn-overridden.stderr11
-rw-r--r--tests/ui/async-await/in-trait/async-example-desugared-boxed-in-trait.stderr2
-rw-r--r--tests/ui/async-await/in-trait/dont-project-to-specializable-projection.rs71
-rw-r--r--tests/ui/async-await/in-trait/dont-project-to-specializable-projection.stderr19
-rw-r--r--tests/ui/async-await/in-trait/fn-not-async-err2.rs2
-rw-r--r--tests/ui/async-await/in-trait/fn-not-async-err2.stderr2
-rw-r--r--tests/ui/async-await/in-trait/return-type-suggestion.stderr2
-rw-r--r--tests/ui/async-await/issue-61076.rs5
-rw-r--r--tests/ui/async-await/issue-61076.stderr17
-rw-r--r--tests/ui/async-await/issue-64130-1-sync.drop_tracking.stderr25
-rw-r--r--tests/ui/async-await/issue-64130-1-sync.drop_tracking_mir.stderr22
-rw-r--r--tests/ui/async-await/issue-64130-1-sync.no_drop_tracking.stderr25
-rw-r--r--tests/ui/async-await/issue-64130-1-sync.rs4
-rw-r--r--tests/ui/async-await/issue-64130-1-sync.stderr6
-rw-r--r--tests/ui/async-await/issue-64130-2-send.drop_tracking.stderr28
-rw-r--r--tests/ui/async-await/issue-64130-2-send.drop_tracking_mir.stderr26
-rw-r--r--tests/ui/async-await/issue-64130-2-send.no_drop_tracking.stderr28
-rw-r--r--tests/ui/async-await/issue-64130-2-send.rs5
-rw-r--r--tests/ui/async-await/issue-64130-2-send.stderr6
-rw-r--r--tests/ui/async-await/issue-64130-3-other.drop_tracking.stderr27
-rw-r--r--tests/ui/async-await/issue-64130-3-other.drop_tracking_mir.stderr25
-rw-r--r--tests/ui/async-await/issue-64130-3-other.no_drop_tracking.stderr27
-rw-r--r--tests/ui/async-await/issue-64130-3-other.rs5
-rw-r--r--tests/ui/async-await/issue-64130-3-other.stderr6
-rw-r--r--tests/ui/async-await/issue-64130-4-async-move.drop-tracking.stderr6
-rw-r--r--tests/ui/async-await/issue-64130-4-async-move.no_drop_tracking.stderr6
-rw-r--r--tests/ui/async-await/issue-64130-4-async-move.rs8
-rw-r--r--tests/ui/async-await/issue-67252-unnamed-future.drop_tracking.stderr30
-rw-r--r--tests/ui/async-await/issue-67252-unnamed-future.drop_tracking_mir.stderr22
-rw-r--r--tests/ui/async-await/issue-67252-unnamed-future.no_drop_tracking.stderr30
-rw-r--r--tests/ui/async-await/issue-67252-unnamed-future.rs6
-rw-r--r--tests/ui/async-await/issue-67252-unnamed-future.stderr28
-rw-r--r--tests/ui/async-await/issue-68112.drop_tracking.stderr3
-rw-r--r--tests/ui/async-await/issue-68112.drop_tracking_mir.stderr80
-rw-r--r--tests/ui/async-await/issue-68112.no_drop_tracking.stderr3
-rw-r--r--tests/ui/async-await/issue-68112.rs8
-rw-r--r--tests/ui/async-await/issue-70818.drop_tracking.stderr18
-rw-r--r--tests/ui/async-await/issue-70818.drop_tracking_mir.stderr18
-rw-r--r--tests/ui/async-await/issue-70818.no_drop_tracking.stderr18
-rw-r--r--tests/ui/async-await/issue-70818.rs3
-rw-r--r--tests/ui/async-await/issue-70818.stderr4
-rw-r--r--tests/ui/async-await/issue-70935-complex-spans.drop_tracking_mir.stderr34
-rw-r--r--tests/ui/async-await/issue-70935-complex-spans.rs8
-rw-r--r--tests/ui/async-await/issue-73741-type-err-drop-tracking.drop_tracking.stderr11
-rw-r--r--tests/ui/async-await/issue-73741-type-err-drop-tracking.drop_tracking_mir.stderr11
-rw-r--r--tests/ui/async-await/issue-73741-type-err-drop-tracking.no_drop_tracking.stderr11
-rw-r--r--tests/ui/async-await/issue-73741-type-err-drop-tracking.rs5
-rw-r--r--tests/ui/async-await/issue-73741-type-err-drop-tracking.stderr2
-rw-r--r--tests/ui/async-await/issue-74072-lifetime-name-annotations.stderr16
-rw-r--r--tests/ui/async-await/issue-75785-confusing-named-region.stderr4
-rw-r--r--tests/ui/async-await/issue-86507.drop_tracking.stderr (renamed from tests/ui/async-await/issue-86507.stderr)6
-rw-r--r--tests/ui/async-await/issue-86507.drop_tracking_mir.stderr23
-rw-r--r--tests/ui/async-await/issue-86507.no_drop_tracking.stderr23
-rw-r--r--tests/ui/async-await/issue-86507.rs3
-rw-r--r--tests/ui/async-await/issue-93648.rs4
-rw-r--r--tests/ui/async-await/issue-98634.rs6
-rw-r--r--tests/ui/async-await/issue-98634.stderr33
-rw-r--r--tests/ui/async-await/issues/auxiliary/issue_67893.rs3
-rw-r--r--tests/ui/async-await/issues/issue-102206.stderr9
-rw-r--r--tests/ui/async-await/issues/issue-107280.rs15
-rw-r--r--tests/ui/async-await/issues/issue-107280.stderr82
-rw-r--r--tests/ui/async-await/issues/issue-62097.rs2
-rw-r--r--tests/ui/async-await/issues/issue-62097.stderr6
-rw-r--r--tests/ui/async-await/issues/issue-65159.rs2
-rw-r--r--tests/ui/async-await/issues/issue-65159.stderr2
-rw-r--r--tests/ui/async-await/issues/issue-65436-raw-ptr-not-send.no_drop_tracking.stderr10
-rw-r--r--tests/ui/async-await/issues/issue-65436-raw-ptr-not-send.rs7
-rw-r--r--tests/ui/async-await/issues/issue-67611-static-mut-refs.rs4
-rw-r--r--tests/ui/async-await/issues/issue-67893.stderr2
-rw-r--r--tests/ui/async-await/issues/issue-72312.stderr6
-rw-r--r--tests/ui/async-await/multiple-lifetimes/member-constraints-min-choice-issue-63033.rs10
-rw-r--r--tests/ui/async-await/multiple-lifetimes/ret-impl-trait-one.stderr5
-rw-r--r--tests/ui/async-await/multiple-lifetimes/ret-ref.stderr12
-rw-r--r--tests/ui/async-await/mutually-recursive-async-impl-trait-type.drop_tracking.stderr21
-rw-r--r--tests/ui/async-await/mutually-recursive-async-impl-trait-type.drop_tracking_mir.stderr21
-rw-r--r--tests/ui/async-await/mutually-recursive-async-impl-trait-type.no_drop_tracking.stderr21
-rw-r--r--tests/ui/async-await/mutually-recursive-async-impl-trait-type.rs4
-rw-r--r--tests/ui/async-await/mutually-recursive-async-impl-trait-type.stderr4
-rw-r--r--tests/ui/async-await/no-const-async.stderr4
-rw-r--r--tests/ui/async-await/non-trivial-drop.rs4
-rw-r--r--tests/ui/async-await/proper-span-for-type-error.stderr2
-rw-r--r--tests/ui/async-await/recursive-async-impl-trait-type.drop_tracking.stderr12
-rw-r--r--tests/ui/async-await/recursive-async-impl-trait-type.drop_tracking_mir.stderr12
-rw-r--r--tests/ui/async-await/recursive-async-impl-trait-type.no_drop_tracking.stderr12
-rw-r--r--tests/ui/async-await/recursive-async-impl-trait-type.rs3
-rw-r--r--tests/ui/async-await/recursive-async-impl-trait-type.stderr2
-rw-r--r--tests/ui/async-await/send-bound-async-closure.rs37
-rw-r--r--tests/ui/async-await/suggest-missing-await-closure.stderr12
-rw-r--r--tests/ui/async-await/suggest-missing-await.stderr59
-rw-r--r--tests/ui/async-await/unresolved_type_param.drop_tracking.stderr39
-rw-r--r--tests/ui/async-await/unresolved_type_param.drop_tracking_mir.stderr14
-rw-r--r--tests/ui/async-await/unresolved_type_param.no_drop_tracking.stderr63
-rw-r--r--tests/ui/async-await/unresolved_type_param.rs38
-rw-r--r--tests/ui/async-await/unresolved_type_param.stderr12
-rw-r--r--tests/ui/attributes/invalid_macro_export_argument.rs26
-rw-r--r--tests/ui/attributes/invalid_macro_export_argument.stderr16
-rw-r--r--tests/ui/attributes/key-value-expansion.stderr7
-rw-r--r--tests/ui/attributes/log-backtrace.rs4
-rw-r--r--tests/ui/attributes/rustc-box.rs18
-rw-r--r--tests/ui/attributes/rustc-box.stderr34
-rw-r--r--tests/ui/augmented-assignments.rs2
-rw-r--r--tests/ui/augmented-assignments.stderr2
-rw-r--r--tests/ui/auto-traits/auto-trait-validation.stderr6
-rw-r--r--tests/ui/auto-traits/issue-23080-2.stderr2
-rw-r--r--tests/ui/auto-traits/issue-23080.stderr2
-rw-r--r--tests/ui/auto-traits/issue-84075.stderr2
-rw-r--r--tests/ui/auto-traits/str-contains-slice-conceptually.rs13
-rw-r--r--tests/ui/auto-traits/str-contains-slice-conceptually.stderr16
-rw-r--r--tests/ui/auto-traits/typeck-auto-trait-no-supertraits-2.stderr4
-rw-r--r--tests/ui/auto-traits/typeck-auto-trait-no-supertraits.stderr2
-rw-r--r--tests/ui/autoref-autoderef/issue-38940.stderr2
-rw-r--r--tests/ui/binding/issue-53114-safety-checks.rs4
-rw-r--r--tests/ui/binding/issue-53114-safety-checks.stderr92
-rw-r--r--tests/ui/binop/binary-op-on-double-ref.fixed2
-rw-r--r--tests/ui/binop/binary-op-on-double-ref.rs2
-rw-r--r--tests/ui/binop/binary-op-on-double-ref.stderr2
-rw-r--r--tests/ui/binop/binop-move-semantics.stderr5
-rw-r--r--tests/ui/binop/issue-28837.rs2
-rw-r--r--tests/ui/binop/issue-28837.stderr2
-rw-r--r--tests/ui/blind/blind-item-block-middle.stderr2
-rw-r--r--tests/ui/block-result/consider-removing-last-semi.stderr4
-rw-r--r--tests/ui/block-result/issue-13428.stderr4
-rw-r--r--tests/ui/block-result/issue-13624.rs4
-rw-r--r--tests/ui/block-result/issue-13624.stderr4
-rw-r--r--tests/ui/block-result/issue-22645.stderr2
-rw-r--r--tests/ui/block-result/issue-5500.rs2
-rw-r--r--tests/ui/block-result/issue-5500.stderr2
-rw-r--r--tests/ui/borrowck/bindings-after-at-or-patterns-slice-patterns-box-patterns.stderr8
-rw-r--r--tests/ui/borrowck/borrow-tuple-fields.stderr4
-rw-r--r--tests/ui/borrowck/borrowck-anon-fields-variant.stderr4
-rw-r--r--tests/ui/borrowck/borrowck-assign-comp.stderr12
-rw-r--r--tests/ui/borrowck/borrowck-assign-to-andmut-in-borrowed-loc.stderr6
-rw-r--r--tests/ui/borrowck/borrowck-bad-nested-calls-move.stderr5
-rw-r--r--tests/ui/borrowck/borrowck-borrow-mut-base-ptr-in-aliasable-loc.stderr8
-rw-r--r--tests/ui/borrowck/borrowck-closures-mut-and-imm.stderr16
-rw-r--r--tests/ui/borrowck/borrowck-describe-lvalue.stderr42
-rw-r--r--tests/ui/borrowck/borrowck-field-sensitivity.stderr4
-rw-r--r--tests/ui/borrowck/borrowck-imm-ref-to-mut-rec-field-issue-3162-c.stderr4
-rw-r--r--tests/ui/borrowck/borrowck-issue-14498.stderr32
-rw-r--r--tests/ui/borrowck/borrowck-lend-flow-match.stderr4
-rw-r--r--tests/ui/borrowck/borrowck-loan-blocks-move-cc.stderr4
-rw-r--r--tests/ui/borrowck/borrowck-loan-blocks-move.stderr2
-rw-r--r--tests/ui/borrowck/borrowck-loan-of-static-data-issue-27616.stderr4
-rw-r--r--tests/ui/borrowck/borrowck-loan-rcvr-overloaded-op.stderr2
-rw-r--r--tests/ui/borrowck/borrowck-local-borrow-with-panic-outlives-fn.stderr2
-rw-r--r--tests/ui/borrowck/borrowck-match-already-borrowed.stderr8
-rw-r--r--tests/ui/borrowck/borrowck-move-by-capture.stderr2
-rw-r--r--tests/ui/borrowck/borrowck-move-from-subpath-of-borrowed-path.stderr2
-rw-r--r--tests/ui/borrowck/borrowck-move-mut-base-ptr.stderr2
-rw-r--r--tests/ui/borrowck/borrowck-move-subcomponent.stderr2
-rw-r--r--tests/ui/borrowck/borrowck-multiple-captures.stderr6
-rw-r--r--tests/ui/borrowck/borrowck-overloaded-index-and-overloaded-deref.stderr4
-rw-r--r--tests/ui/borrowck/borrowck-overloaded-index-autoderef.stderr16
-rw-r--r--tests/ui/borrowck/borrowck-overloaded-index-move-index.stderr4
-rw-r--r--tests/ui/borrowck/borrowck-pat-reassign-binding.stderr4
-rw-r--r--tests/ui/borrowck/borrowck-unary-move.stderr2
-rw-r--r--tests/ui/borrowck/borrowck-union-borrow-nested.stderr2
-rw-r--r--tests/ui/borrowck/borrowck-union-borrow.stderr20
-rw-r--r--tests/ui/borrowck/borrowck-use-mut-borrow.stderr18
-rw-r--r--tests/ui/borrowck/borrowck-vec-pattern-move-tail.stderr4
-rw-r--r--tests/ui/borrowck/borrowck-vec-pattern-nesting.rs8
-rw-r--r--tests/ui/borrowck/borrowck-vec-pattern-nesting.stderr8
-rw-r--r--tests/ui/borrowck/issue-103624.rs2
-rw-r--r--tests/ui/borrowck/issue-103624.stderr6
-rw-r--r--tests/ui/borrowck/issue-25793.stderr2
-rw-r--r--tests/ui/borrowck/issue-52713-bug.stderr4
-rw-r--r--tests/ui/borrowck/issue-58776-borrowck-scans-children.stderr4
-rw-r--r--tests/ui/borrowck/issue-81365-1.stderr4
-rw-r--r--tests/ui/borrowck/issue-81365-10.stderr4
-rw-r--r--tests/ui/borrowck/issue-81365-11.stderr4
-rw-r--r--tests/ui/borrowck/issue-81365-2.stderr4
-rw-r--r--tests/ui/borrowck/issue-81365-3.stderr4
-rw-r--r--tests/ui/borrowck/issue-81365-4.stderr4
-rw-r--r--tests/ui/borrowck/issue-81365-5.stderr4
-rw-r--r--tests/ui/borrowck/issue-81365-6.stderr4
-rw-r--r--tests/ui/borrowck/issue-81365-7.stderr4
-rw-r--r--tests/ui/borrowck/issue-81365-8.stderr4
-rw-r--r--tests/ui/borrowck/issue-81365-9.stderr4
-rw-r--r--tests/ui/borrowck/issue-82126-mismatched-subst-and-hir.rs4
-rw-r--r--tests/ui/borrowck/issue-82126-mismatched-subst-and-hir.stderr4
-rw-r--r--tests/ui/borrowck/issue-83924.fixed (renamed from tests/ui/issues/issue-83924.fixed)0
-rw-r--r--tests/ui/borrowck/issue-83924.rs (renamed from tests/ui/issues/issue-83924.rs)0
-rw-r--r--tests/ui/borrowck/issue-83924.stderr (renamed from tests/ui/issues/issue-83924.stderr)0
-rw-r--r--tests/ui/borrowck/issue-85765.rs6
-rw-r--r--tests/ui/borrowck/issue-85765.stderr24
-rw-r--r--tests/ui/borrowck/issue-91206.rs2
-rw-r--r--tests/ui/borrowck/issue-91206.stderr8
-rw-r--r--tests/ui/borrowck/issue-92015.stderr7
-rw-r--r--tests/ui/borrowck/issue-95079-missing-move-in-nested-closure.fixed26
-rw-r--r--tests/ui/borrowck/issue-95079-missing-move-in-nested-closure.rs12
-rw-r--r--tests/ui/borrowck/issue-95079-missing-move-in-nested-closure.stderr31
-rw-r--r--tests/ui/borrowck/two-phase-allow-access-during-reservation.nll_target.stderr4
-rw-r--r--tests/ui/borrowck/two-phase-surprise-no-conflict.stderr2
-rw-r--r--tests/ui/bounds-lifetime.stderr11
-rw-r--r--tests/ui/box/issue-82446.stderr2
-rw-r--r--tests/ui/box/leak-alloc.stderr2
-rw-r--r--tests/ui/btreemap/btreemap_dropck.stderr2
-rw-r--r--tests/ui/c-variadic/variadic-ffi-1.stderr2
-rw-r--r--tests/ui/c-variadic/variadic-ffi-4.stderr4
-rw-r--r--tests/ui/check-cfg/invalid-cfg-value.stderr4
-rw-r--r--tests/ui/closure-expected-type/expect-infer-var-appearing-twice.stderr2
-rw-r--r--tests/ui/closures/2229_closure_analysis/diagnostics/arrays.stderr14
-rw-r--r--tests/ui/closures/2229_closure_analysis/diagnostics/box.stderr8
-rw-r--r--tests/ui/closures/2229_closure_analysis/diagnostics/repr_packed.rs1
-rw-r--r--tests/ui/closures/2229_closure_analysis/diagnostics/repr_packed.stderr20
-rw-r--r--tests/ui/closures/2229_closure_analysis/diagnostics/union.rs4
-rw-r--r--tests/ui/closures/2229_closure_analysis/diagnostics/union.stderr4
-rw-r--r--tests/ui/closures/2229_closure_analysis/issue_88118.rs5
-rw-r--r--tests/ui/closures/2229_closure_analysis/migrations/auto_traits.fixed4
-rw-r--r--tests/ui/closures/2229_closure_analysis/migrations/auto_traits.rs4
-rw-r--r--tests/ui/closures/2229_closure_analysis/migrations/auto_traits.stderr4
-rw-r--r--tests/ui/closures/2229_closure_analysis/migrations/multi_diagnostics.fixed2
-rw-r--r--tests/ui/closures/2229_closure_analysis/migrations/multi_diagnostics.rs2
-rw-r--r--tests/ui/closures/2229_closure_analysis/migrations/multi_diagnostics.stderr2
-rw-r--r--tests/ui/closures/binder/const-bound.rs7
-rw-r--r--tests/ui/closures/binder/const-bound.stderr17
-rw-r--r--tests/ui/closures/binder/disallow-const.stderr6
-rw-r--r--tests/ui/closures/binder/disallow-ty.stderr6
-rw-r--r--tests/ui/closures/binder/type-bound-2.rs7
-rw-r--r--tests/ui/closures/binder/type-bound-2.stderr17
-rw-r--r--tests/ui/closures/binder/type-bound.rs7
-rw-r--r--tests/ui/closures/binder/type-bound.stderr17
-rw-r--r--tests/ui/closures/issue-78720.stderr2
-rw-r--r--tests/ui/coercion/coerce-block-tail-26978.stderr2
-rw-r--r--tests/ui/coercion/coerce-block-tail-57749.stderr2
-rw-r--r--tests/ui/coercion/coerce-block-tail-83783.stderr2
-rw-r--r--tests/ui/coercion/coerce-block-tail-83850.stderr2
-rw-r--r--tests/ui/coercion/coerce-block-tail.stderr2
-rw-r--r--tests/ui/coercion/coerce-expect-unsized-ascribed.stderr28
-rw-r--r--tests/ui/coercion/coerce-overloaded-autoderef-fail.stderr4
-rw-r--r--tests/ui/coercion/coerce-to-bang.stderr2
-rw-r--r--tests/ui/coercion/coercion-missing-tail-expected-type.stderr2
-rw-r--r--tests/ui/coercion/coercion-slice.rs2
-rw-r--r--tests/ui/coercion/coercion-slice.stderr2
-rw-r--r--tests/ui/coherence/coherence-impl-trait-for-marker-trait-negative.rs23
-rw-r--r--tests/ui/coherence/coherence-impl-trait-for-marker-trait-negative.stderr42
-rw-r--r--tests/ui/coherence/coherence-impl-trait-for-marker-trait-positive.rs23
-rw-r--r--tests/ui/coherence/coherence-impl-trait-for-marker-trait-positive.stderr42
-rw-r--r--tests/ui/coherence/issue-85026.stderr8
-rw-r--r--tests/ui/coinduction/canonicalization-rerun.rs54
-rw-r--r--tests/ui/command/command-setgroups.rs1
-rw-r--r--tests/ui/compare-method/bad-self-type.stderr6
-rw-r--r--tests/ui/conditional-compilation/cfg-generic-params.stderr46
-rw-r--r--tests/ui/confuse-field-and-method/issue-33784.stderr4
-rw-r--r--tests/ui/const-generics/bad-const-generic-exprs.rs34
-rw-r--r--tests/ui/const-generics/bad-const-generic-exprs.stderr106
-rw-r--r--tests/ui/const-generics/const-argument-non-static-lifetime.min.stderr2
-rw-r--r--tests/ui/const-generics/const-argument-non-static-lifetime.rs1
-rw-r--r--tests/ui/const-generics/const-param-elided-lifetime.min.stderr10
-rw-r--r--tests/ui/const-generics/const-param-elided-lifetime.rs10
-rw-r--r--tests/ui/const-generics/const-param-type-depends-on-type-param-ungated.rs3
-rw-r--r--tests/ui/const-generics/const-param-type-depends-on-type-param-ungated.stderr2
-rw-r--r--tests/ui/const-generics/defaults/mismatch.stderr10
-rw-r--r--tests/ui/const-generics/defaults/wfness.stderr2
-rw-r--r--tests/ui/const-generics/early/invalid-const-arguments.stderr9
-rw-r--r--tests/ui/const-generics/ensure_is_evaluatable.stderr2
-rw-r--r--tests/ui/const-generics/fn_with_two_const_inputs.stderr2
-rw-r--r--tests/ui/const-generics/generic_const_exprs/const_kind_expr/relate_binop_arg_tys.rs18
-rw-r--r--tests/ui/const-generics/generic_const_exprs/const_kind_expr/relate_binop_arg_tys.stderr20
-rw-r--r--tests/ui/const-generics/generic_const_exprs/const_kind_expr/relate_cast_arg_ty.rs12
-rw-r--r--tests/ui/const-generics/generic_const_exprs/const_kind_expr/relate_cast_arg_ty.stderr20
-rw-r--r--tests/ui/const-generics/generic_const_exprs/const_kind_expr/relate_ty_with_infer_1.rs30
-rw-r--r--tests/ui/const-generics/generic_const_exprs/const_kind_expr/relate_ty_with_infer_2.rs151
-rw-r--r--tests/ui/const-generics/generic_const_exprs/issue-102768.rs4
-rw-r--r--tests/ui/const-generics/generic_const_exprs/issue-102768.stderr4
-rw-r--r--tests/ui/const-generics/generic_const_exprs/issue-105608.stderr2
-rw-r--r--tests/ui/const-generics/generic_const_exprs/issue-72819-generic-in-const-eval.full.stderr4
-rw-r--r--tests/ui/const-generics/generic_const_exprs/issue-76595.stderr2
-rw-r--r--tests/ui/const-generics/generic_const_exprs/issue-79518-default_trait_method_normalization.stderr2
-rw-r--r--tests/ui/const-generics/generic_const_exprs/obligation-cause.stderr2
-rw-r--r--tests/ui/const-generics/generic_const_exprs/single-satisfied-ConstEvaluatable-in-probe.rs39
-rw-r--r--tests/ui/const-generics/incorrect-number-of-const-args.stderr4
-rw-r--r--tests/ui/const-generics/infer/method-chain.stderr2
-rw-r--r--tests/ui/const-generics/infer/uninferred-consts.stderr2
-rw-r--r--tests/ui/const-generics/invalid-const-arg-for-type-param.rs4
-rw-r--r--tests/ui/const-generics/invalid-const-arg-for-type-param.stderr4
-rw-r--r--tests/ui/const-generics/invalid-constant-in-args.rs2
-rw-r--r--tests/ui/const-generics/invalid-constant-in-args.stderr2
-rw-r--r--tests/ui/const-generics/issues/issue-105821.rs23
-rw-r--r--tests/ui/const-generics/issues/issue-56445-1.min.stderr2
-rw-r--r--tests/ui/const-generics/issues/issue-56445-1.rs2
-rw-r--r--tests/ui/const-generics/issues/issue-67185-2.stderr8
-rw-r--r--tests/ui/const-generics/issues/issue-67945-1.full.stderr2
-rw-r--r--tests/ui/const-generics/issues/issue-73260.rs1
-rw-r--r--tests/ui/const-generics/issues/issue-73260.stderr12
-rw-r--r--tests/ui/const-generics/issues/issue-79674.stderr2
-rw-r--r--tests/ui/const-generics/issues/issue-86530.stderr2
-rw-r--r--tests/ui/const-generics/issues/issue-87493.rs2
-rw-r--r--tests/ui/const-generics/issues/issue-87493.stderr2
-rw-r--r--tests/ui/const-generics/min_const_generics/macro-fail.stderr23
-rw-r--r--tests/ui/const-generics/nested-type.min.stderr11
-rw-r--r--tests/ui/const-generics/nested-type.rs2
-rw-r--r--tests/ui/const-generics/occurs-check/unused-substs-1.stderr2
-rw-r--r--tests/ui/const-generics/parser-error-recovery/issue-89013-no-kw.rs2
-rw-r--r--tests/ui/const-generics/parser-error-recovery/issue-89013-no-kw.stderr2
-rw-r--r--tests/ui/const-generics/parser-error-recovery/issue-89013.rs2
-rw-r--r--tests/ui/const-generics/parser-error-recovery/issue-89013.stderr2
-rw-r--r--tests/ui/const-generics/type_mismatch.stderr2
-rw-r--r--tests/ui/const-generics/type_not_in_scope.stderr2
-rw-r--r--tests/ui/const-generics/types-mismatch-const-args.full.stderr4
-rw-r--r--tests/ui/const-generics/types-mismatch-const-args.min.stderr4
-rw-r--r--tests/ui/const-generics/unify_with_nested_expr.stderr2
-rw-r--r--tests/ui/const-generics/wrong-normalization.rs19
-rw-r--r--tests/ui/const-generics/wrong-normalization.stderr11
-rw-r--r--tests/ui/constructor-lifetime-args.rs8
-rw-r--r--tests/ui/constructor-lifetime-args.stderr8
-rw-r--r--tests/ui/consts/array-literal-len-mismatch.rs4
-rw-r--r--tests/ui/consts/array-literal-len-mismatch.stderr11
-rw-r--r--tests/ui/consts/const-array-oob-arith.stderr8
-rw-r--r--tests/ui/consts/const-err-late.stderr12
-rw-r--r--tests/ui/consts/const-eval/const-eval-query-stack.rs3
-rw-r--r--tests/ui/consts/const-eval/const-eval-query-stack.stderr2
-rw-r--r--tests/ui/consts/const-eval/const-eval-span.rs2
-rw-r--r--tests/ui/consts/const-eval/const-eval-span.stderr2
-rw-r--r--tests/ui/consts/const-eval/infinite_loop.stderr9
-rw-r--r--tests/ui/consts/const-eval/issue-52475.rs4
-rw-r--r--tests/ui/consts/const-eval/issue-52475.stderr9
-rw-r--r--tests/ui/consts/const-eval/issue-91827-extern-types.rs5
-rw-r--r--tests/ui/consts/const-eval/raw-bytes.32bit.stderr4
-rw-r--r--tests/ui/consts/const-eval/raw-bytes.64bit.stderr4
-rw-r--r--tests/ui/consts/const-eval/stable-metric/ctfe-fn-call.rs36
-rw-r--r--tests/ui/consts/const-eval/stable-metric/ctfe-fn-call.stderr20
-rw-r--r--tests/ui/consts/const-eval/stable-metric/ctfe-labelled-loop.rs19
-rw-r--r--tests/ui/consts/const-eval/stable-metric/ctfe-labelled-loop.stderr30
-rw-r--r--tests/ui/consts/const-eval/stable-metric/ctfe-recursion.rs16
-rw-r--r--tests/ui/consts/const-eval/stable-metric/ctfe-recursion.stderr25
-rw-r--r--tests/ui/consts/const-eval/stable-metric/ctfe-simple-loop.rs15
-rw-r--r--tests/ui/consts/const-eval/stable-metric/ctfe-simple-loop.stderr24
-rw-r--r--tests/ui/consts/const-eval/stable-metric/dominators-edge-case.rs19
-rw-r--r--tests/ui/consts/const-eval/ub-ref-ptr.stderr4
-rw-r--r--tests/ui/consts/const-eval/validate_uninhabited_zsts.32bit.stderr10
-rw-r--r--tests/ui/consts/const-eval/validate_uninhabited_zsts.64bit.stderr10
-rw-r--r--tests/ui/consts/const-tup-index-span.rs2
-rw-r--r--tests/ui/consts/const-tup-index-span.stderr2
-rw-r--r--tests/ui/consts/const_limit/const_eval_limit_reached.stderr9
-rw-r--r--tests/ui/consts/ct-var-in-collect_all_mismatches.stderr2
-rw-r--r--tests/ui/consts/gate-do-not-const-check.rs5
-rw-r--r--tests/ui/consts/gate-do-not-const-check.stderr11
-rw-r--r--tests/ui/consts/issue-33903.rs (renamed from tests/ui/issues/issue-33903.rs)0
-rw-r--r--tests/ui/consts/issue-54582.rs (renamed from tests/ui/issues/issue-54582.rs)0
-rw-r--r--tests/ui/consts/nested_erroneous_ctfe.stderr2
-rw-r--r--tests/ui/consts/promote_const_let.stderr1
-rw-r--r--tests/ui/cross/cross-borrow-trait.stderr2
-rw-r--r--tests/ui/deprecation/deprecation-lint.rs96
-rw-r--r--tests/ui/deprecation/deprecation-lint.stderr140
-rw-r--r--tests/ui/deprecation/issue-84637-deprecated-associated-function.fixed4
-rw-r--r--tests/ui/deprecation/issue-84637-deprecated-associated-function.rs4
-rw-r--r--tests/ui/deprecation/issue-84637-deprecated-associated-function.stderr8
-rw-r--r--tests/ui/deprecation/suggestion.stderr4
-rw-r--r--tests/ui/deref-patterns/gate.stderr2
-rw-r--r--tests/ui/derives/deriving-copyclone.stderr24
-rw-r--r--tests/ui/derives/deriving-with-repr-packed-2.rs20
-rw-r--r--tests/ui/derives/deriving-with-repr-packed-2.stderr33
-rw-r--r--tests/ui/derives/deriving-with-repr-packed.rs53
-rw-r--r--tests/ui/derives/deriving-with-repr-packed.stderr138
-rw-r--r--tests/ui/deriving/deriving-all-codegen.rs85
-rw-r--r--tests/ui/deriving/deriving-all-codegen.stderr63
-rw-r--r--tests/ui/deriving/deriving-all-codegen.stdout570
-rw-r--r--tests/ui/destructure-trait-ref.stderr6
-rw-r--r--tests/ui/destructuring-assignment/default-match-bindings-forbidden.stderr2
-rw-r--r--tests/ui/diagnostic-flags/terminal_urls.rs4
-rw-r--r--tests/ui/diagnostic-flags/terminal_urls.stderr11
-rw-r--r--tests/ui/diagnostic-width/long-E0308.stderr8
-rw-r--r--tests/ui/did_you_mean/brackets-to-braces-single-element.stderr6
-rw-r--r--tests/ui/did_you_mean/compatible-variants-in-pat.stderr6
-rw-r--r--tests/ui/did_you_mean/compatible-variants.stderr26
-rw-r--r--tests/ui/did_you_mean/issue-42764.stderr4
-rw-r--r--tests/ui/did_you_mean/issue-46718-struct-pattern-dotdotdot.stderr7
-rw-r--r--tests/ui/did_you_mean/println-typo.rs6
-rw-r--r--tests/ui/did_you_mean/println-typo.stderr11
-rw-r--r--tests/ui/did_you_mean/recursion_limit_deref.stderr2
-rw-r--r--tests/ui/disambiguate-identical-names.stderr2
-rw-r--r--tests/ui/diverging-fn-tail-35849.stderr2
-rw-r--r--tests/ui/drop/issue-2735-2.rs (renamed from tests/ui/issues/issue-2735-2.rs)0
-rw-r--r--tests/ui/drop/issue-2735-3.rs (renamed from tests/ui/issues/issue-2735-3.rs)0
-rw-r--r--tests/ui/drop/issue-2735.rs (renamed from tests/ui/issues/issue-2735.rs)0
-rw-r--r--tests/ui/dropck/drop-with-active-borrows-1.stderr2
-rw-r--r--tests/ui/dropck/dropck-eyepatch-extern-crate.stderr6
-rw-r--r--tests/ui/dropck/dropck-eyepatch-reorder.stderr6
-rw-r--r--tests/ui/dropck/dropck-eyepatch.stderr6
-rw-r--r--tests/ui/dropck/dropck-union.stderr2
-rw-r--r--tests/ui/dropck/dropck_trait_cycle_checked.stderr12
-rw-r--r--tests/ui/dst/dst-bad-assign-3.rs2
-rw-r--r--tests/ui/dst/dst-bad-assign-3.stderr2
-rw-r--r--tests/ui/dst/dst-bad-assign.rs2
-rw-r--r--tests/ui/dst/dst-bad-assign.stderr2
-rw-r--r--tests/ui/dst/dst-bad-coerce1.stderr4
-rw-r--r--tests/ui/dst/dst-bad-coerce3.stderr10
-rw-r--r--tests/ui/dst/dst-bad-coerce4.rs4
-rw-r--r--tests/ui/dst/dst-bad-coerce4.stderr4
-rw-r--r--tests/ui/dyn-star/align.over_aligned.stderr6
-rw-r--r--tests/ui/dyn-star/align.rs2
-rw-r--r--tests/ui/dyn-star/check-size-at-cast-polymorphic-bad.rs2
-rw-r--r--tests/ui/dyn-star/check-size-at-cast-polymorphic-bad.stderr10
-rw-r--r--tests/ui/dyn-star/check-size-at-cast.rs2
-rw-r--r--tests/ui/dyn-star/check-size-at-cast.stderr6
-rw-r--r--tests/ui/dyn-star/dyn-star-to-dyn.rs14
-rw-r--r--tests/ui/dyn-star/llvm-old-style-ptrs.rs23
-rw-r--r--tests/ui/dyn-star/no-implicit-dyn-star.stderr2
-rw-r--r--tests/ui/dyn-star/upcast.stderr6
-rw-r--r--tests/ui/empty/empty-struct-braces-expr.stderr4
-rw-r--r--tests/ui/empty/issue-37026.stderr4
-rw-r--r--tests/ui/error-codes/E0057.stderr9
-rw-r--r--tests/ui/error-codes/E0071.rs2
-rw-r--r--tests/ui/error-codes/E0071.stderr2
-rw-r--r--tests/ui/error-codes/E0107.rs20
-rw-r--r--tests/ui/error-codes/E0107.stderr20
-rw-r--r--tests/ui/error-codes/E0116.stderr2
-rw-r--r--tests/ui/error-codes/E0118.stderr4
-rw-r--r--tests/ui/error-codes/E0208.rs2
-rw-r--r--tests/ui/error-codes/E0208.stderr2
-rw-r--r--tests/ui/error-codes/E0390.stderr8
-rw-r--r--tests/ui/error-codes/E0476.rs13
-rw-r--r--tests/ui/error-codes/E0476.stderr31
-rw-r--r--tests/ui/error-codes/E0503.stderr2
-rw-r--r--tests/ui/error-codes/E0504.stderr2
-rw-r--r--tests/ui/error-codes/E0505.stderr3
-rw-r--r--tests/ui/error-codes/E0506.stderr4
-rw-r--r--tests/ui/error-codes/E0520.stderr2
-rw-r--r--tests/ui/error-codes/E0523.rs14
-rw-r--r--tests/ui/error-codes/E0523.stderr13
-rw-r--r--tests/ui/error-codes/E0597.stderr2
-rw-r--r--tests/ui/error-codes/E0624.rs2
-rw-r--r--tests/ui/error-codes/E0624.stderr6
-rw-r--r--tests/ui/error-codes/E0789.rs12
-rw-r--r--tests/ui/error-codes/E0789.stderr15
-rw-r--r--tests/ui/errors/trait-bound-error-spans/blame-trait-error.rs102
-rw-r--r--tests/ui/errors/trait-bound-error-spans/blame-trait-error.stderr402
-rw-r--r--tests/ui/errors/traits/blame-trait-error-spans-on-exprs.rs137
-rw-r--r--tests/ui/errors/traits/blame-trait-error-spans-on-exprs.stderr412
-rw-r--r--tests/ui/explore-issue-38412.stderr36
-rw-r--r--tests/ui/expr/malformed_closure/missing_braces_around_block.fixed9
-rw-r--r--tests/ui/expr/malformed_closure/missing_braces_around_block.rs9
-rw-r--r--tests/ui/expr/malformed_closure/missing_braces_around_block.stderr33
-rw-r--r--tests/ui/extenv/extenv-not-defined-default.rs4
-rw-r--r--tests/ui/extenv/extenv-not-defined-default.stderr7
-rw-r--r--tests/ui/extenv/issue-55897.stderr3
-rw-r--r--tests/ui/extern/extern-types-distinct-types.stderr2
-rw-r--r--tests/ui/feature-gates/feature-gate-associated_type_bounds.rs3
-rw-r--r--tests/ui/feature-gates/feature-gate-associated_type_bounds.stderr40
-rw-r--r--tests/ui/feature-gates/feature-gate-dispatch-from-dyn-cell.rs9
-rw-r--r--tests/ui/feature-gates/feature-gate-dispatch-from-dyn-cell.stderr12
-rw-r--r--tests/ui/feature-gates/feature-gate-dispatch-from-dyn-missing-impl.rs35
-rw-r--r--tests/ui/feature-gates/feature-gate-dispatch-from-dyn-missing-impl.stderr45
-rw-r--r--tests/ui/feature-gates/feature-gate-impl_trait_in_fn_trait_return.stderr4
-rw-r--r--tests/ui/feature-gates/feature-gate-multiple_supertrait_upcastable.rs12
-rw-r--r--tests/ui/feature-gates/feature-gate-multiple_supertrait_upcastable.stderr57
-rw-r--r--tests/ui/feature-gates/feature-gate-non_lifetime_binders.rs4
-rw-r--r--tests/ui/feature-gates/feature-gate-non_lifetime_binders.stderr12
-rw-r--r--tests/ui/feature-gates/feature-gate-return_position_impl_trait_in_trait.stderr6
-rw-r--r--tests/ui/feature-gates/feature-gate-trivial_bounds.stderr2
-rw-r--r--tests/ui/ffi_const.rs10
-rw-r--r--tests/ui/ffi_const.stderr14
-rw-r--r--tests/ui/ffi_pure.rs10
-rw-r--r--tests/ui/ffi_pure.stderr14
-rw-r--r--tests/ui/ffi_returns_twice.rs10
-rw-r--r--tests/ui/ffi_returns_twice.stderr14
-rw-r--r--tests/ui/fmt/format-string-wrong-order.rs15
-rw-r--r--tests/ui/fmt/format-string-wrong-order.stderr54
-rw-r--r--tests/ui/fmt/ifmt-bad-arg.stderr4
-rw-r--r--tests/ui/fmt/ifmt-unimpl.stderr2
-rw-r--r--tests/ui/fmt/issue-75307.rs (renamed from tests/ui/issues/issue-75307.rs)0
-rw-r--r--tests/ui/fmt/issue-75307.stderr (renamed from tests/ui/issues/issue-75307.stderr)0
-rw-r--r--tests/ui/fmt/respanned-literal-issue-106191.rs2
-rw-r--r--tests/ui/fmt/send-sync.stderr4
-rw-r--r--tests/ui/fn/fn-compare-mismatch.stderr2
-rw-r--r--tests/ui/fn/fn-item-type.rs38
-rw-r--r--tests/ui/fn/fn-item-type.stderr53
-rw-r--r--tests/ui/fn/fn-pointer-mismatch.rs56
-rw-r--r--tests/ui/fn/fn-pointer-mismatch.stderr91
-rw-r--r--tests/ui/fn/fn-trait-formatting.stderr6
-rw-r--r--tests/ui/fn/implied-bounds-unnorm-associated-type-4.stderr2
-rw-r--r--tests/ui/fn/implied-bounds-unnorm-associated-type.stderr2
-rw-r--r--tests/ui/fn/issue-3044.stderr2
-rw-r--r--tests/ui/fn/signature-error-reporting-under-verbose.rs3
-rw-r--r--tests/ui/fn/signature-error-reporting-under-verbose.stderr3
-rw-r--r--tests/ui/for/for-else-err.rs8
-rw-r--r--tests/ui/for/for-else-err.stderr17
-rw-r--r--tests/ui/for/for-else-let-else-err.rs8
-rw-r--r--tests/ui/for/for-else-let-else-err.stderr17
-rw-r--r--tests/ui/fully-qualified-type/fully-qualified-type-name1.rs2
-rw-r--r--tests/ui/fully-qualified-type/fully-qualified-type-name1.stderr2
-rw-r--r--tests/ui/fully-qualified-type/fully-qualified-type-name2.rs2
-rw-r--r--tests/ui/fully-qualified-type/fully-qualified-type-name2.stderr8
-rw-r--r--tests/ui/fully-qualified-type/fully-qualified-type-name4.rs2
-rw-r--r--tests/ui/fully-qualified-type/fully-qualified-type-name4.stderr2
-rw-r--r--tests/ui/function-pointer/unsized-ret.stderr2
-rw-r--r--tests/ui/functions-closures/fn-help-with-err.stderr2
-rw-r--r--tests/ui/generator/addassign-yield.rs3
-rw-r--r--tests/ui/generator/auto-trait-regions.drop_tracking.stderr47
-rw-r--r--tests/ui/generator/auto-trait-regions.drop_tracking_mir.stderr47
-rw-r--r--tests/ui/generator/auto-trait-regions.no_drop_tracking.stderr47
-rw-r--r--tests/ui/generator/auto-trait-regions.rs3
-rw-r--r--tests/ui/generator/auto-trait-regions.stderr8
-rw-r--r--tests/ui/generator/borrowing.drop_tracking.stderr31
-rw-r--r--tests/ui/generator/borrowing.drop_tracking_mir.stderr39
-rw-r--r--tests/ui/generator/borrowing.no_drop_tracking.stderr31
-rw-r--r--tests/ui/generator/borrowing.rs4
-rw-r--r--tests/ui/generator/borrowing.stderr4
-rw-r--r--tests/ui/generator/drop-tracking-parent-expression.drop_tracking.stderr (renamed from tests/ui/generator/drop-tracking-parent-expression.stderr)24
-rw-r--r--tests/ui/generator/drop-tracking-parent-expression.drop_tracking_mir.stderr122
-rw-r--r--tests/ui/generator/drop-tracking-parent-expression.no_drop_tracking.stderr334
-rw-r--r--tests/ui/generator/drop-tracking-parent-expression.rs12
-rw-r--r--tests/ui/generator/drop-tracking-yielding-in-match-guards.rs4
-rw-r--r--tests/ui/generator/dropck.stderr3
-rw-r--r--tests/ui/generator/generator-yielding-or-returning-itself.stderr4
-rw-r--r--tests/ui/generator/issue-102645.stderr2
-rw-r--r--tests/ui/generator/issue-105084.drop_tracking_mir.stderr51
-rw-r--r--tests/ui/generator/issue-105084.rs49
-rw-r--r--tests/ui/generator/issue-57017.no_drop_tracking.stderr248
-rw-r--r--tests/ui/generator/issue-57017.rs14
-rw-r--r--tests/ui/generator/issue-57478.no_drop_tracking.stderr31
-rw-r--r--tests/ui/generator/issue-57478.rs8
-rw-r--r--tests/ui/generator/issue-68112.drop_tracking.stderr (renamed from tests/ui/generator/issue-68112.stderr)20
-rw-r--r--tests/ui/generator/issue-68112.drop_tracking_mir.stderr61
-rw-r--r--tests/ui/generator/issue-68112.no_drop_tracking.stderr66
-rw-r--r--tests/ui/generator/issue-68112.rs11
-rw-r--r--tests/ui/generator/issue-93161.rs4
-rw-r--r--tests/ui/generator/not-send-sync.drop_tracking.stderr60
-rw-r--r--tests/ui/generator/not-send-sync.drop_tracking_mir.stderr42
-rw-r--r--tests/ui/generator/not-send-sync.no_drop_tracking.stderr60
-rw-r--r--tests/ui/generator/not-send-sync.rs19
-rw-r--r--tests/ui/generator/not-send-sync.stderr56
-rw-r--r--tests/ui/generator/parent-expression.drop_tracking.stderr128
-rw-r--r--tests/ui/generator/parent-expression.drop_tracking_mir.stderr122
-rw-r--r--tests/ui/generator/parent-expression.no_drop_tracking.stderr334
-rw-r--r--tests/ui/generator/parent-expression.rs77
-rw-r--r--tests/ui/generator/partial-drop.drop_tracking.stderr (renamed from tests/ui/generator/partial-drop.stderr)51
-rw-r--r--tests/ui/generator/partial-drop.no_drop_tracking.stderr61
-rw-r--r--tests/ui/generator/partial-drop.rs21
-rw-r--r--tests/ui/generator/print/generator-print-verbose-1.drop_tracking.stderr (renamed from tests/ui/generator/print/generator-print-verbose-1.stderr)20
-rw-r--r--tests/ui/generator/print/generator-print-verbose-1.drop_tracking_mir.stderr60
-rw-r--r--tests/ui/generator/print/generator-print-verbose-1.no_drop_tracking.stderr64
-rw-r--r--tests/ui/generator/print/generator-print-verbose-1.rs5
-rw-r--r--tests/ui/generator/print/generator-print-verbose-2.drop_tracking.stderr60
-rw-r--r--tests/ui/generator/print/generator-print-verbose-2.drop_tracking_mir.stderr42
-rw-r--r--tests/ui/generator/print/generator-print-verbose-2.no_drop_tracking.stderr60
-rw-r--r--tests/ui/generator/print/generator-print-verbose-2.rs19
-rw-r--r--tests/ui/generator/print/generator-print-verbose-2.stderr56
-rw-r--r--tests/ui/generator/retain-resume-ref.drop_tracking.stderr13
-rw-r--r--tests/ui/generator/retain-resume-ref.drop_tracking_mir.stderr14
-rw-r--r--tests/ui/generator/retain-resume-ref.no_drop_tracking.stderr13
-rw-r--r--tests/ui/generator/retain-resume-ref.rs4
-rw-r--r--tests/ui/generator/retain-resume-ref.stderr2
-rw-r--r--tests/ui/generator/static-mut-reference-across-yield.rs4
-rw-r--r--tests/ui/generator/type-mismatch-signature-deduction.stderr4
-rw-r--r--tests/ui/generic-associated-types/bugs/issue-88460.stderr2
-rw-r--r--tests/ui/generic-associated-types/collections-project-default.stderr3
-rw-r--r--tests/ui/generic-associated-types/constraint-assoc-type-suggestion.stderr2
-rw-r--r--tests/ui/generic-associated-types/gat-trait-path-parenthesised-args.rs6
-rw-r--r--tests/ui/generic-associated-types/gat-trait-path-parenthesised-args.stderr6
-rw-r--r--tests/ui/generic-associated-types/issue-101020.stderr2
-rw-r--r--tests/ui/generic-associated-types/issue-68656-unsized-values.stderr4
-rw-r--r--tests/ui/generic-associated-types/issue-74684-1.stderr1
-rw-r--r--tests/ui/generic-associated-types/issue-79422.extended.stderr4
-rw-r--r--tests/ui/generic-associated-types/issue-88360.fixed20
-rw-r--r--tests/ui/generic-associated-types/issue-88360.rs2
-rw-r--r--tests/ui/generic-associated-types/issue-88360.stderr12
-rw-r--r--tests/ui/generic-associated-types/method-unsatisfied-assoc-type-predicate.rs (renamed from tests/ui/generic-associated-types/method-unsatified-assoc-type-predicate.rs)0
-rw-r--r--tests/ui/generic-associated-types/method-unsatisfied-assoc-type-predicate.stderr (renamed from tests/ui/generic-associated-types/method-unsatified-assoc-type-predicate.stderr)4
-rw-r--r--tests/ui/generic-associated-types/missing-bounds.fixed6
-rw-r--r--tests/ui/generic-associated-types/missing-bounds.stderr12
-rw-r--r--tests/ui/generic-associated-types/missing_lifetime_args.rs4
-rw-r--r--tests/ui/generic-associated-types/missing_lifetime_args.stderr4
-rw-r--r--tests/ui/generic-associated-types/missing_lifetime_const.rs2
-rw-r--r--tests/ui/generic-associated-types/missing_lifetime_const.stderr2
-rw-r--r--tests/ui/generic-associated-types/parameter_number_and_kind.rs6
-rw-r--r--tests/ui/generic-associated-types/parameter_number_and_kind.stderr6
-rw-r--r--tests/ui/generic-associated-types/parse/trait-path-type-error-once-implemented.rs4
-rw-r--r--tests/ui/generic-associated-types/parse/trait-path-type-error-once-implemented.stderr4
-rw-r--r--tests/ui/generic-associated-types/unsatisfied-item-lifetime-bound.rs (renamed from tests/ui/generic-associated-types/unsatified-item-lifetime-bound.rs)2
-rw-r--r--tests/ui/generic-associated-types/unsatisfied-item-lifetime-bound.stderr (renamed from tests/ui/generic-associated-types/unsatified-item-lifetime-bound.stderr)19
-rw-r--r--tests/ui/generics/bad-mid-path-type-params.rs10
-rw-r--r--tests/ui/generics/bad-mid-path-type-params.stderr10
-rw-r--r--tests/ui/generics/generic-arg-mismatch-recover.rs6
-rw-r--r--tests/ui/generics/generic-arg-mismatch-recover.stderr6
-rw-r--r--tests/ui/generics/generic-impl-less-params-with-defaults.rs2
-rw-r--r--tests/ui/generics/generic-impl-less-params-with-defaults.stderr2
-rw-r--r--tests/ui/generics/generic-impl-more-params-with-defaults.rs2
-rw-r--r--tests/ui/generics/generic-impl-more-params-with-defaults.stderr2
-rw-r--r--tests/ui/generics/generic-type-more-params-with-defaults.rs2
-rw-r--r--tests/ui/generics/generic-type-more-params-with-defaults.stderr2
-rw-r--r--tests/ui/generics/generic-type-params-name-repr.rs12
-rw-r--r--tests/ui/generics/generic-type-params-name-repr.stderr12
-rw-r--r--tests/ui/generics/issue-65285-incorrect-explicit-lifetime-name-needed.rs1
-rw-r--r--tests/ui/generics/issue-65285-incorrect-explicit-lifetime-name-needed.stderr18
-rw-r--r--tests/ui/generics/wrong-number-of-args.rs106
-rw-r--r--tests/ui/generics/wrong-number-of-args.stderr106
-rw-r--r--tests/ui/half-open-range-patterns/exclusive_range_pattern_syntax_collision.stderr2
-rw-r--r--tests/ui/half-open-range-patterns/exclusive_range_pattern_syntax_collision2.stderr2
-rw-r--r--tests/ui/half-open-range-patterns/exclusive_range_pattern_syntax_collision3.stderr6
-rw-r--r--tests/ui/half-open-range-patterns/half-open-range-pats-inclusive-match-arrow.rs9
-rw-r--r--tests/ui/half-open-range-patterns/half-open-range-pats-inclusive-match-arrow.stderr15
-rw-r--r--tests/ui/half-open-range-patterns/pat-tuple-5.stderr2
-rw-r--r--tests/ui/higher-rank-trait-bounds/hang-on-deeply-nested-dyn.stderr4
-rw-r--r--tests/ui/higher-rank-trait-bounds/hrtb-higher-ranker-supertraits-transitive.stderr2
-rw-r--r--tests/ui/higher-rank-trait-bounds/hrtb-higher-ranker-supertraits.stderr4
-rw-r--r--tests/ui/higher-rank-trait-bounds/hrtb-identity-fn-borrows.stderr4
-rw-r--r--tests/ui/higher-rank-trait-bounds/hrtb-wrong-kind.stderr11
-rw-r--r--tests/ui/higher-rank-trait-bounds/issue-30786.rs2
-rw-r--r--tests/ui/higher-rank-trait-bounds/issue-30786.stderr27
-rw-r--r--tests/ui/higher-rank-trait-bounds/issue-39292.rs (renamed from tests/ui/issues/issue-39292.rs)0
-rw-r--r--tests/ui/higher-rank-trait-bounds/issue-62203-hrtb-ice.stderr10
-rw-r--r--tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-89118.stderr6
-rw-r--r--tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-90950.stderr2
-rw-r--r--tests/ui/higher-rank-trait-bounds/normalize-under-binder/norm-before-method-resolution.stderr2
-rw-r--r--tests/ui/hygiene/panic-location.run.stderr2
-rw-r--r--tests/ui/impl-header-lifetime-elision/path-elided.stderr1
-rw-r--r--tests/ui/impl-header-lifetime-elision/trait-elided.stderr1
-rw-r--r--tests/ui/impl-trait/auto-trait-leak.stderr4
-rw-r--r--tests/ui/impl-trait/bound-normalization-pass.rs2
-rw-r--r--tests/ui/impl-trait/dyn-trait-return-should-be-impl-trait.stderr26
-rw-r--r--tests/ui/impl-trait/equal-hidden-lifetimes.rs1
-rw-r--r--tests/ui/impl-trait/equal-hidden-lifetimes.stderr10
-rw-r--r--tests/ui/impl-trait/equality2.stderr2
-rw-r--r--tests/ui/impl-trait/explicit-generic-args-with-impl-trait/explicit-generic-args-for-impl.stderr2
-rw-r--r--tests/ui/impl-trait/explicit-generic-args-with-impl-trait/not-enough-args.stderr2
-rw-r--r--tests/ui/impl-trait/feature-self-return-type.stderr3
-rw-r--r--tests/ui/impl-trait/hidden-lifetimes.stderr8
-rw-r--r--tests/ui/impl-trait/impl-fn-hrtb-bounds-2.stderr2
-rw-r--r--tests/ui/impl-trait/in-trait/deep-match.stderr2
-rw-r--r--tests/ui/impl-trait/in-trait/default-body-type-err-2.stderr2
-rw-r--r--tests/ui/impl-trait/in-trait/default-body-type-err.stderr2
-rw-r--r--tests/ui/impl-trait/in-trait/default-method-constraint.rs17
-rw-r--r--tests/ui/impl-trait/in-trait/default-method-constraint.stderr11
-rw-r--r--tests/ui/impl-trait/in-trait/method-signature-matches.stderr10
-rw-r--r--tests/ui/impl-trait/in-trait/new-lowering-strategy/simple-trait.rs11
-rw-r--r--tests/ui/impl-trait/in-trait/signature-mismatch.stderr4
-rw-r--r--tests/ui/impl-trait/in-trait/specialization-broken.rs1
-rw-r--r--tests/ui/impl-trait/in-trait/specialization-broken.stderr10
-rw-r--r--tests/ui/impl-trait/issue-102605.stderr12
-rw-r--r--tests/ui/impl-trait/issue-55872-2.drop_tracking.stderr8
-rw-r--r--tests/ui/impl-trait/issue-55872-2.drop_tracking_mir.stderr14
-rw-r--r--tests/ui/impl-trait/issue-55872-2.no_drop_tracking.stderr8
-rw-r--r--tests/ui/impl-trait/issue-55872-2.rs4
-rw-r--r--tests/ui/impl-trait/issue-55872-2.stderr2
-rw-r--r--tests/ui/impl-trait/issue-99914.stderr9
-rw-r--r--tests/ui/impl-trait/issues/infinite-impl-trait-issue-38064.stderr4
-rw-r--r--tests/ui/impl-trait/issues/issue-54600.stderr2
-rw-r--r--tests/ui/impl-trait/issues/issue-54840.stderr2
-rw-r--r--tests/ui/impl-trait/issues/issue-58504.stderr2
-rw-r--r--tests/ui/impl-trait/issues/issue-58956.stderr4
-rw-r--r--tests/ui/impl-trait/issues/issue-70971.stderr2
-rw-r--r--tests/ui/impl-trait/issues/issue-74282.stderr4
-rw-r--r--tests/ui/impl-trait/issues/issue-79099.stderr2
-rw-r--r--tests/ui/impl-trait/issues/issue-83929-impl-trait-in-generic-default.stderr4
-rw-r--r--tests/ui/impl-trait/issues/issue-84919.stderr2
-rw-r--r--tests/ui/impl-trait/issues/issue-86642.stderr2
-rw-r--r--tests/ui/impl-trait/issues/issue-86800.stderr4
-rw-r--r--tests/ui/impl-trait/issues/issue-87295.stderr2
-rw-r--r--tests/ui/impl-trait/multiple-lifetimes/error-handling-2.stderr3
-rw-r--r--tests/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unrelated.stderr4
-rw-r--r--tests/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unsuited.stderr4
-rw-r--r--tests/ui/impl-trait/must_outlive_least_region_or_bound.stderr14
-rw-r--r--tests/ui/impl-trait/nested-return-type2.rs3
-rw-r--r--tests/ui/impl-trait/nested-return-type2.stderr2
-rw-r--r--tests/ui/impl-trait/nested-return-type4.stderr4
-rw-r--r--tests/ui/impl-trait/nested_impl_trait.stderr2
-rw-r--r--tests/ui/impl-trait/no-method-suggested-traits.stderr16
-rw-r--r--tests/ui/impl-trait/normalize-tait-in-const.rs1
-rw-r--r--tests/ui/impl-trait/normalize-tait-in-const.stderr2
-rw-r--r--tests/ui/impl-trait/object-unsafe-trait-in-return-position-impl-trait.stderr4
-rw-r--r--tests/ui/impl-trait/recursive-impl-trait-type-indirect.drop_tracking.stderr (renamed from tests/ui/impl-trait/recursive-impl-trait-type-indirect.stderr)40
-rw-r--r--tests/ui/impl-trait/recursive-impl-trait-type-indirect.drop_tracking_mir.stderr144
-rw-r--r--tests/ui/impl-trait/recursive-impl-trait-type-indirect.no_drop_tracking.stderr152
-rw-r--r--tests/ui/impl-trait/recursive-impl-trait-type-indirect.rs4
-rw-r--r--tests/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle.stderr4
-rw-r--r--tests/ui/impl-trait/region-escape-via-bound.stderr4
-rw-r--r--tests/ui/impl-trait/static-return-lifetime-infered.stderr8
-rw-r--r--tests/ui/impl-trait/universal-mismatched-type.stderr2
-rw-r--r--tests/ui/impl-trait/where-allowed.stderr82
-rw-r--r--tests/ui/implied-bounds/assoc-ty-wf-used-to-get-assoc-ty.stderr2
-rw-r--r--tests/ui/implied-bounds/issue-100690.stderr2
-rw-r--r--tests/ui/imports/import-prefix-macro-1.stderr2
-rw-r--r--tests/ui/include-macros/mismatched-types.stderr4
-rw-r--r--tests/ui/incoherent-inherent-impls/needs-has-incoherent-impls.stderr78
-rw-r--r--tests/ui/incoherent-inherent-impls/no-attr-empty-impl.stderr12
-rw-r--r--tests/ui/inference/array-len-mismatch.rs12
-rw-r--r--tests/ui/inference/array-len-mismatch.stderr21
-rw-r--r--tests/ui/inference/deref-suggestion.stderr6
-rw-r--r--tests/ui/inference/inference_unstable.rs8
-rw-r--r--tests/ui/inference/inference_unstable.stderr8
-rw-r--r--tests/ui/inference/inference_unstable_featured.stderr4
-rw-r--r--tests/ui/inference/issue-107090.rs25
-rw-r--r--tests/ui/inference/issue-107090.stderr84
-rw-r--r--tests/ui/inference/issue-71732.stderr2
-rw-r--r--tests/ui/inference/need_type_info/issue-107745-avoid-expr-from-macro-expansion.rs19
-rw-r--r--tests/ui/inference/need_type_info/issue-107745-avoid-expr-from-macro-expansion.stderr11
-rw-r--r--tests/ui/inference/question-mark-type-infer.stderr2
-rw-r--r--tests/ui/infinite/auxiliary/alias.rs2
-rw-r--r--tests/ui/infinite/infinite-alias.rs9
-rw-r--r--tests/ui/infinite/infinite-alias.stderr14
-rw-r--r--tests/ui/inline-const/const-expr-lifetime-err.stderr1
-rw-r--r--tests/ui/instrument-xray/flags-always-never-1.rs7
-rw-r--r--tests/ui/instrument-xray/flags-always-never-1.stderr2
-rw-r--r--tests/ui/instrument-xray/flags-always-never-2.rs9
-rw-r--r--tests/ui/instrument-xray/flags-basic.rs9
-rw-r--r--tests/ui/instrument-xray/flags-dupe-always.rs7
-rw-r--r--tests/ui/instrument-xray/flags-dupe-always.stderr2
-rw-r--r--tests/ui/instrument-xray/flags-dupe-ignore-loops.rs7
-rw-r--r--tests/ui/instrument-xray/flags-dupe-ignore-loops.stderr2
-rw-r--r--tests/ui/instrument-xray/target-not-supported.rs9
-rw-r--r--tests/ui/instrument-xray/target-not-supported.stderr4
-rw-r--r--tests/ui/intrinsics/const-eval-select-bad.rs2
-rw-r--r--tests/ui/intrinsics/const-eval-select-bad.stderr2
-rw-r--r--tests/ui/intrinsics/intrinsic-alignment.rs4
-rw-r--r--tests/ui/io-checks/inaccessbile-temp-dir.rs39
-rw-r--r--tests/ui/io-checks/inaccessbile-temp-dir.stderr4
-rw-r--r--tests/ui/io-checks/non-ice-error-on-worker-io-fail.rs (renamed from tests/ui/non-ice-error-on-worker-io-fail.rs)0
-rw-r--r--tests/ui/io-checks/non-ice-error-on-worker-io-fail.stderr (renamed from tests/ui/non-ice-error-on-worker-io-fail.stderr)0
-rw-r--r--tests/ui/issues/issue-100605.stderr4
-rw-r--r--tests/ui/issues/issue-102964.stderr2
-rw-r--r--tests/ui/issues/issue-10412.stderr1
-rw-r--r--tests/ui/issues/issue-106755.rs19
-rw-r--r--tests/ui/issues/issue-106755.stderr22
-rw-r--r--tests/ui/issues/issue-10764.stderr1
-rw-r--r--tests/ui/issues/issue-11374.stderr4
-rw-r--r--tests/ui/issues/issue-11844.stderr2
-rw-r--r--tests/ui/issues/issue-13446.stderr2
-rw-r--r--tests/ui/issues/issue-13466.rs4
-rw-r--r--tests/ui/issues/issue-13466.stderr4
-rw-r--r--tests/ui/issues/issue-14541.rs2
-rw-r--r--tests/ui/issues/issue-14541.stderr2
-rw-r--r--tests/ui/issues/issue-15783.rs2
-rw-r--r--tests/ui/issues/issue-15783.stderr2
-rw-r--r--tests/ui/issues/issue-15896.stderr2
-rw-r--r--tests/ui/issues/issue-16338.stderr2
-rw-r--r--tests/ui/issues/issue-16401.rs2
-rw-r--r--tests/ui/issues/issue-16401.stderr2
-rw-r--r--tests/ui/issues/issue-16939.stderr9
-rw-r--r--tests/ui/issues/issue-16966.stderr6
-rw-r--r--tests/ui/issues/issue-17337.stderr2
-rw-r--r--tests/ui/issues/issue-18423.rs2
-rw-r--r--tests/ui/issues/issue-18423.stderr2
-rw-r--r--tests/ui/issues/issue-18446.stderr2
-rw-r--r--tests/ui/issues/issue-18819.stderr2
-rw-r--r--tests/ui/issues/issue-19521.stderr2
-rw-r--r--tests/ui/issues/issue-20225.stderr6
-rw-r--r--tests/ui/issues/issue-21202.rs2
-rw-r--r--tests/ui/issues/issue-21202.stderr6
-rw-r--r--tests/ui/issues/issue-21332.rs2
-rw-r--r--tests/ui/issues/issue-21332.stderr2
-rw-r--r--tests/ui/issues/issue-23041.stderr2
-rw-r--r--tests/ui/issues/issue-24322.stderr2
-rw-r--r--tests/ui/issues/issue-24819.rs2
-rw-r--r--tests/ui/issues/issue-24819.stderr2
-rw-r--r--tests/ui/issues/issue-26094.rs7
-rw-r--r--tests/ui/issues/issue-26094.stderr6
-rw-r--r--tests/ui/issues/issue-27008.rs2
-rw-r--r--tests/ui/issues/issue-27008.stderr2
-rw-r--r--tests/ui/issues/issue-30123.stderr2
-rw-r--r--tests/ui/issues/issue-30438-c.rs1
-rw-r--r--tests/ui/issues/issue-30438-c.stderr12
-rw-r--r--tests/ui/issues/issue-32122-1.stderr2
-rw-r--r--tests/ui/issues/issue-32122-2.stderr2
-rw-r--r--tests/ui/issues/issue-3214.rs2
-rw-r--r--tests/ui/issues/issue-3214.stderr2
-rw-r--r--tests/ui/issues/issue-33504.stderr2
-rw-r--r--tests/ui/issues/issue-33941.stderr6
-rw-r--r--tests/ui/issues/issue-35241.stderr2
-rw-r--r--tests/ui/issues/issue-3680.rs2
-rw-r--r--tests/ui/issues/issue-3680.stderr2
-rw-r--r--tests/ui/issues/issue-3702-2.stderr4
-rw-r--r--tests/ui/issues/issue-3763.rs7
-rw-r--r--tests/ui/issues/issue-3763.stderr22
-rw-r--r--tests/ui/issues/issue-39970.rs2
-rw-r--r--tests/ui/issues/issue-39970.stderr4
-rw-r--r--tests/ui/issues/issue-40288.stderr4
-rw-r--r--tests/ui/issues/issue-40749.stderr2
-rw-r--r--tests/ui/issues/issue-43420-no-over-suggest.stderr2
-rw-r--r--tests/ui/issues/issue-4517.rs2
-rw-r--r--tests/ui/issues/issue-4517.stderr2
-rw-r--r--tests/ui/issues/issue-45697-1.stderr6
-rw-r--r--tests/ui/issues/issue-45697.stderr6
-rw-r--r--tests/ui/issues/issue-46471-1.stderr7
-rw-r--r--tests/ui/issues/issue-47715.stderr8
-rw-r--r--tests/ui/issues/issue-48364.stderr4
-rw-r--r--tests/ui/issues/issue-4935.stderr9
-rw-r--r--tests/ui/issues/issue-4968.rs2
-rw-r--r--tests/ui/issues/issue-4968.stderr2
-rw-r--r--tests/ui/issues/issue-5100.rs4
-rw-r--r--tests/ui/issues/issue-5100.stderr6
-rw-r--r--tests/ui/issues/issue-51515.rs1
-rw-r--r--tests/ui/issues/issue-51515.stderr9
-rw-r--r--tests/ui/issues/issue-51632-try-desugar-incompatible-types.stderr2
-rw-r--r--tests/ui/issues/issue-52126-assign-op-invariance.stderr2
-rw-r--r--tests/ui/issues/issue-53251.rs4
-rw-r--r--tests/ui/issues/issue-53251.stderr4
-rw-r--r--tests/ui/issues/issue-53348.rs2
-rw-r--r--tests/ui/issues/issue-53348.stderr2
-rw-r--r--tests/ui/issues/issue-5358-1.rs2
-rw-r--r--tests/ui/issues/issue-5358-1.stderr2
-rw-r--r--tests/ui/issues/issue-56943.stderr2
-rw-r--r--tests/ui/issues/issue-57362-2.stderr4
-rw-r--r--tests/ui/issues/issue-57741-1.stderr4
-rw-r--r--tests/ui/issues/issue-57741.stderr8
-rw-r--r--tests/ui/issues/issue-59488.stderr4
-rw-r--r--tests/ui/issues/issue-60218.stderr2
-rw-r--r--tests/ui/issues/issue-60622.rs2
-rw-r--r--tests/ui/issues/issue-60622.stderr4
-rw-r--r--tests/ui/issues/issue-61106.stderr2
-rw-r--r--tests/ui/issues/issue-6458-4.stderr2
-rw-r--r--tests/ui/issues/issue-65634-raw-ident-suggestion.edition2015.stderr4
-rw-r--r--tests/ui/issues/issue-65634-raw-ident-suggestion.edition2018.stderr4
-rw-r--r--tests/ui/issues/issue-67039-unsound-pin-partialeq.stderr2
-rw-r--r--tests/ui/issues/issue-69306.stderr6
-rw-r--r--tests/ui/issues/issue-69455.stderr4
-rw-r--r--tests/ui/issues/issue-69683.stderr2
-rw-r--r--tests/ui/issues/issue-70093/issue-70093-link-directives.rs10
-rw-r--r--tests/ui/issues/issue-70093/issue-70093.rs (renamed from tests/ui/issues/issue-70093.rs)0
-rw-r--r--tests/ui/issues/issue-7061.stderr2
-rw-r--r--tests/ui/issues/issue-7092.rs2
-rw-r--r--tests/ui/issues/issue-7092.stderr2
-rw-r--r--tests/ui/issues/issue-71676-1.stderr6
-rw-r--r--tests/ui/issues/issue-7364.stderr1
-rw-r--r--tests/ui/issues/issue-74236/main.stderr2
-rw-r--r--tests/ui/issues/issue-76191.stderr4
-rw-r--r--tests/ui/issues/issue-7867.rs2
-rw-r--r--tests/ui/issues/issue-7867.stderr2
-rw-r--r--tests/ui/issues/issue-92741.fixed13
-rw-r--r--tests/ui/issues/issue-92741.rs17
-rw-r--r--tests/ui/issues/issue-92741.stderr49
-rw-r--r--tests/ui/json/json-bom-plus-crlf-multifile.stderr8
-rw-r--r--tests/ui/json/json-bom-plus-crlf.stderr8
-rw-r--r--tests/ui/kindck/kindck-send-object1.stderr2
-rw-r--r--tests/ui/kinds-of-primitive-impl.stderr16
-rw-r--r--tests/ui/lang-items/bad-add-impl.rs18
-rw-r--r--tests/ui/lang-items/bad-add-impl.stderr11
-rw-r--r--tests/ui/lang-items/fn-fn_mut-call-ill-formed.bad_item.stderr18
-rw-r--r--tests/ui/lang-items/fn-fn_mut-call-ill-formed.bad_sig.stderr18
-rw-r--r--tests/ui/lang-items/fn-fn_mut-call-ill-formed.fn_bad_item.stderr18
-rw-r--r--tests/ui/lang-items/fn-fn_mut-call-ill-formed.fn_bad_sig.stderr18
-rw-r--r--tests/ui/lang-items/fn-fn_mut-call-ill-formed.fn_mut_bad_item.stderr18
-rw-r--r--tests/ui/lang-items/fn-fn_mut-call-ill-formed.fn_mut_bad_sig.stderr18
-rw-r--r--tests/ui/lang-items/fn-fn_mut-call-ill-formed.fn_once_bad_item.stderr18
-rw-r--r--tests/ui/lang-items/fn-fn_mut-call-ill-formed.fn_once_bad_sig.stderr18
-rw-r--r--tests/ui/lang-items/fn-fn_mut-call-ill-formed.rs34
-rw-r--r--tests/ui/lang-items/fn-fn_mut-call-ill-formed.stderr14
-rw-r--r--tests/ui/lang-items/issue-86238.stderr2
-rw-r--r--tests/ui/lang-items/lang-item-missing-generator.rs21
-rw-r--r--tests/ui/lang-items/lang-item-missing-generator.stderr15
-rw-r--r--tests/ui/late-bound-lifetimes/mismatched_arg_count.rs2
-rw-r--r--tests/ui/late-bound-lifetimes/mismatched_arg_count.stderr2
-rw-r--r--tests/ui/layout/valid_range_oob.stderr2
-rw-r--r--tests/ui/let-else/accidental-if.rs6
-rw-r--r--tests/ui/let-else/accidental-if.stderr19
-rw-r--r--tests/ui/let-else/issue-94176.stderr2
-rw-r--r--tests/ui/let-else/let-else-brace-before-else.fixed4
-rw-r--r--tests/ui/let-else/let-else-brace-before-else.rs4
-rw-r--r--tests/ui/let-else/let-else-brace-before-else.stderr17
-rw-r--r--tests/ui/let-else/let-else-deref-coercion.stderr4
-rw-r--r--tests/ui/let-else/let-else-non-diverging.stderr6
-rw-r--r--tests/ui/let-else/let-else-ref-bindings.stderr16
-rw-r--r--tests/ui/lifetimes/issue-103582-hint-for-missing-lifetime-bound-on-trait-object-using-type-alias.fixed45
-rw-r--r--tests/ui/lifetimes/issue-103582-hint-for-missing-lifetime-bound-on-trait-object-using-type-alias.rs45
-rw-r--r--tests/ui/lifetimes/issue-103582-hint-for-missing-lifetime-bound-on-trait-object-using-type-alias.stderr15
-rw-r--r--tests/ui/lifetimes/issue-104432-unused-lifetimes-in-expansion.rs12
-rw-r--r--tests/ui/lifetimes/issue-105227.stderr13
-rw-r--r--tests/ui/lifetimes/issue-107492-default-value-for-lifetime.rs6
-rw-r--r--tests/ui/lifetimes/issue-107492-default-value-for-lifetime.stderr8
-rw-r--r--tests/ui/lifetimes/issue-107988.rs13
-rw-r--r--tests/ui/lifetimes/issue-107988.stderr27
-rw-r--r--tests/ui/lifetimes/issue-17728.stderr2
-rw-r--r--tests/ui/lifetimes/issue-26638.stderr8
-rw-r--r--tests/ui/lifetimes/issue-69314.fixed22
-rw-r--r--tests/ui/lifetimes/issue-69314.rs22
-rw-r--r--tests/ui/lifetimes/issue-69314.stderr26
-rw-r--r--tests/ui/lifetimes/issue-90600-expected-return-static-indirect.stderr2
-rw-r--r--tests/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-return-type-is-anon.stderr2
-rw-r--r--tests/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-self-is-anon.stderr2
-rw-r--r--tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-return-type-is-anon.stderr2
-rw-r--r--tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-self-is-anon.stderr2
-rw-r--r--tests/ui/lifetimes/unusual-rib-combinations.rs2
-rw-r--r--tests/ui/lifetimes/unusual-rib-combinations.stderr2
-rw-r--r--tests/ui/lint/dead-code/in-closure.rs16
-rw-r--r--tests/ui/lint/dead-code/in-closure.stderr20
-rw-r--r--tests/ui/lint/dead-code/issue-85255.rs12
-rw-r--r--tests/ui/lint/dead-code/issue-85255.stderr12
-rw-r--r--tests/ui/lint/dead-code/lint-dead-code-3.rs2
-rw-r--r--tests/ui/lint/dead-code/lint-dead-code-3.stderr2
-rw-r--r--tests/ui/lint/invalid_value-polymorphic.rs8
-rw-r--r--tests/ui/lint/invalid_value.stderr40
-rw-r--r--tests/ui/lint/issue-104897.rs1
-rw-r--r--tests/ui/lint/issue-104897.stderr35
-rw-r--r--tests/ui/lint/issue-106991.rs13
-rw-r--r--tests/ui/lint/issue-106991.stderr11
-rw-r--r--tests/ui/lint/lint-missing-doc.rs6
-rw-r--r--tests/ui/lint/lint-missing-doc.stderr46
-rw-r--r--tests/ui/lint/lint-stability-deprecated.rs144
-rw-r--r--tests/ui/lint/lint-stability-deprecated.stderr224
-rw-r--r--tests/ui/lint/lint_map_unit_fn.rs20
-rw-r--r--tests/ui/lint/lint_map_unit_fn.stderr66
-rw-r--r--tests/ui/lint/must_not_suspend/dedup.drop_tracking.stderr21
-rw-r--r--tests/ui/lint/must_not_suspend/dedup.drop_tracking_mir.stderr21
-rw-r--r--tests/ui/lint/must_not_suspend/dedup.no_drop_tracking.stderr33
-rw-r--r--tests/ui/lint/must_not_suspend/dedup.rs7
-rw-r--r--tests/ui/lint/must_not_suspend/dedup.stderr6
-rw-r--r--tests/ui/lint/must_not_suspend/ref.drop_tracking.stderr8
-rw-r--r--tests/ui/lint/must_not_suspend/ref.drop_tracking_mir.stderr27
-rw-r--r--tests/ui/lint/must_not_suspend/ref.no_drop_tracking.stderr8
-rw-r--r--tests/ui/lint/must_not_suspend/ref.rs8
-rw-r--r--tests/ui/lint/must_not_suspend/trait.drop_tracking.stderr37
-rw-r--r--tests/ui/lint/must_not_suspend/trait.drop_tracking_mir.stderr37
-rw-r--r--tests/ui/lint/must_not_suspend/trait.no_drop_tracking.stderr37
-rw-r--r--tests/ui/lint/must_not_suspend/trait.rs6
-rw-r--r--tests/ui/lint/must_not_suspend/trait.stderr10
-rw-r--r--tests/ui/lint/must_not_suspend/tuple-mismatch.stderr2
-rw-r--r--tests/ui/lint/must_not_suspend/unit.drop_tracking.stderr26
-rw-r--r--tests/ui/lint/must_not_suspend/unit.drop_tracking_mir.stderr26
-rw-r--r--tests/ui/lint/must_not_suspend/unit.no_drop_tracking.stderr26
-rw-r--r--tests/ui/lint/must_not_suspend/unit.rs5
-rw-r--r--tests/ui/lint/must_not_suspend/unit.stderr8
-rw-r--r--tests/ui/lint/must_not_suspend/warn.drop_tracking.stderr26
-rw-r--r--tests/ui/lint/must_not_suspend/warn.drop_tracking_mir.stderr26
-rw-r--r--tests/ui/lint/must_not_suspend/warn.no_drop_tracking.stderr26
-rw-r--r--tests/ui/lint/must_not_suspend/warn.rs4
-rw-r--r--tests/ui/lint/must_not_suspend/warn.stderr8
-rw-r--r--tests/ui/lint/reasons-forbidden.rs2
-rw-r--r--tests/ui/lint/unaligned_references.rs42
-rw-r--r--tests/ui/lint/unaligned_references.stderr214
-rw-r--r--tests/ui/lint/unaligned_references_external_macro.rs1
-rw-r--r--tests/ui/lint/unaligned_references_external_macro.stderr47
-rw-r--r--tests/ui/lint/unused/issue-103320-must-use-ops.rs27
-rw-r--r--tests/ui/lint/unused/issue-103320-must-use-ops.stderr67
-rw-r--r--tests/ui/lint/unused/issue-96606.rs8
-rw-r--r--tests/ui/lint/unused/issue-96606.stderr33
-rw-r--r--tests/ui/lint/unused_parens_multibyte_recovery.rs1
-rw-r--r--tests/ui/lint/unused_parens_multibyte_recovery.stderr35
-rw-r--r--tests/ui/loops/issue-50576.rs (renamed from tests/ui/issues/issue-50576.rs)0
-rw-r--r--tests/ui/loops/issue-50576.stderr (renamed from tests/ui/issues/issue-50576.stderr)0
-rw-r--r--tests/ui/loops/loop-break-value.stderr2
-rw-r--r--tests/ui/loops/loop-else-break-with-value.rs10
-rw-r--r--tests/ui/loops/loop-else-break-with-value.stderr18
-rw-r--r--tests/ui/loops/loop-else-err.rs8
-rw-r--r--tests/ui/loops/loop-else-err.stderr17
-rw-r--r--tests/ui/loops/loop-else-let-else-err.rs8
-rw-r--r--tests/ui/loops/loop-else-let-else-err.stderr17
-rw-r--r--tests/ui/macros/format-args-temporaries-in-write.stderr4
-rw-r--r--tests/ui/macros/issue-102878.rs4
-rw-r--r--tests/ui/macros/issue-102878.stderr51
-rw-r--r--tests/ui/macros/macros-nonfatal-errors.stderr9
-rw-r--r--tests/ui/macros/rfc-2011-nicer-assert-messages/non-consuming-methods-have-optimized-codegen.stdout36
-rw-r--r--tests/ui/macros/stringify.rs6
-rw-r--r--tests/ui/malformed/issue-107423-unused-delim-only-one-no-pair.rs7
-rw-r--r--tests/ui/malformed/issue-107423-unused-delim-only-one-no-pair.stderr12
-rw-r--r--tests/ui/match/issue-12552.stderr4
-rw-r--r--tests/ui/match/issue-74050-end-span.stderr1
-rw-r--r--tests/ui/match/issue-91058.stderr2
-rw-r--r--tests/ui/match/match-ref-mut-invariance.stderr2
-rw-r--r--tests/ui/match/match-ref-mut-let-invariance.stderr2
-rw-r--r--tests/ui/match/match-struct.rs2
-rw-r--r--tests/ui/match/match-struct.stderr2
-rw-r--r--tests/ui/match/match-tag-nullary.stderr2
-rw-r--r--tests/ui/match/match-tag-unary.stderr2
-rw-r--r--tests/ui/methods/assign-to-method.rs3
-rw-r--r--tests/ui/methods/assign-to-method.stderr4
-rw-r--r--tests/ui/methods/issues/issue-105732.stderr2
-rw-r--r--tests/ui/methods/issues/issue-61525.stderr4
-rw-r--r--tests/ui/methods/issues/issue-90315.stderr10
-rw-r--r--tests/ui/methods/method-ambig-two-traits-cross-crate.stderr4
-rw-r--r--tests/ui/methods/method-ambig-two-traits-from-bounds.stderr4
-rw-r--r--tests/ui/methods/method-ambig-two-traits-from-impls.stderr4
-rw-r--r--tests/ui/methods/method-ambig-two-traits-with-default-method.stderr4
-rw-r--r--tests/ui/methods/method-call-err-msg.stderr34
-rw-r--r--tests/ui/methods/method-call-lifetime-args-fail.rs8
-rw-r--r--tests/ui/methods/method-call-lifetime-args-fail.stderr16
-rw-r--r--tests/ui/methods/method-deref-to-same-trait-object-with-separate-params.stderr6
-rw-r--r--tests/ui/methods/method-not-found-but-doc-alias.rs11
-rw-r--r--tests/ui/methods/method-not-found-but-doc-alias.stderr12
-rw-r--r--tests/ui/methods/method-self-arg-1.rs4
-rw-r--r--tests/ui/methods/method-self-arg-1.stderr8
-rw-r--r--tests/ui/mir/field-projection-invariant.rs24
-rw-r--r--tests/ui/mir/field-projection-mutating-context.rs19
-rw-r--r--tests/ui/mir/field-projection-mutating-context.stderr12
-rw-r--r--tests/ui/mir/field-projection-mutating-context2.rs17
-rw-r--r--tests/ui/mir/field-projection-mutating-context2.stderr10
-rw-r--r--tests/ui/mir/field-ty-ascription-enums.rs15
-rw-r--r--tests/ui/mir/field-ty-ascription.rs37
-rw-r--r--tests/ui/mir/issue-107678-projection-with-lifetime.rs20
-rw-r--r--tests/ui/mir/issue-107691.rs42
-rw-r--r--tests/ui/mir/issue-109743.rs51
-rw-r--r--tests/ui/mir/mir_codegen_ssa.rs19
-rw-r--r--tests/ui/mir/validate/storage-live.rs30
-rw-r--r--tests/ui/mir/validate/storage-live.stderr13
-rw-r--r--tests/ui/mismatched_types/abridged.stderr16
-rw-r--r--tests/ui/mismatched_types/do-not-suggest-boxed-trait-objects-instead-of-impl-trait.stderr4
-rw-r--r--tests/ui/mismatched_types/issue-106182.stderr2
-rw-r--r--tests/ui/mismatched_types/issue-38371-unfixable.stderr2
-rw-r--r--tests/ui/mismatched_types/issue-38371.stderr4
-rw-r--r--tests/ui/mismatched_types/issue-47706.stderr2
-rw-r--r--tests/ui/mismatched_types/issue-74918-missing-lifetime.stderr4
-rw-r--r--tests/ui/mismatched_types/non_zero_assigned_something.stderr4
-rw-r--r--tests/ui/mismatched_types/normalize-fn-sig.stderr3
-rw-r--r--tests/ui/mismatched_types/overloaded-calls-bad.stderr7
-rw-r--r--tests/ui/mismatched_types/ref-pat-suggestions.stderr18
-rw-r--r--tests/ui/mismatched_types/show_module.stderr8
-rw-r--r--tests/ui/mismatched_types/similar_paths.stderr8
-rw-r--r--tests/ui/mismatched_types/similar_paths_primitive.stderr6
-rw-r--r--tests/ui/mismatched_types/suggest-boxed-trait-objects-instead-of-impl-trait.stderr4
-rw-r--r--tests/ui/mismatched_types/suggest-removing-tuple-struct-field.stderr4
-rw-r--r--tests/ui/mismatched_types/wrap-suggestion-privacy.stderr6
-rw-r--r--tests/ui/modules/issue-107649.rs106
-rw-r--r--tests/ui/modules/issue-107649.stderr18
-rw-r--r--tests/ui/moves/issue-22536-copy-mustnt-zero.rs (renamed from tests/ui/issues/issue-22536-copy-mustnt-zero.rs)0
-rw-r--r--tests/ui/moves/move-fn-self-receiver.stderr2
-rw-r--r--tests/ui/moves/pin-mut-reborrow-infer-var-issue-107419.fixed11
-rw-r--r--tests/ui/moves/pin-mut-reborrow-infer-var-issue-107419.rs11
-rw-r--r--tests/ui/moves/pin-mut-reborrow-infer-var-issue-107419.stderr20
-rw-r--r--tests/ui/mut/mut-cross-borrowing.stderr2
-rw-r--r--tests/ui/mut/mut-pattern-internal-mutability.stderr4
-rw-r--r--tests/ui/native-library-link-flags/mix-bundle-and-whole-archive-link-attr.rs13
-rw-r--r--tests/ui/native-library-link-flags/mix-bundle-and-whole-archive-link-attr.stderr6
-rw-r--r--tests/ui/native-library-link-flags/mix-bundle-and-whole-archive.rs9
-rw-r--r--tests/ui/native-library-link-flags/mix-bundle-and-whole-archive.stderr6
-rw-r--r--tests/ui/never_type/diverging-tuple-parts-39485.stderr4
-rw-r--r--tests/ui/never_type/issue-10176.rs2
-rw-r--r--tests/ui/never_type/issue-10176.stderr2
-rw-r--r--tests/ui/never_type/issue-52443.stderr2
-rw-r--r--tests/ui/never_type/issue-96335.stderr2
-rw-r--r--tests/ui/nll/borrowed-local-error.stderr1
-rw-r--r--tests/ui/nll/borrowed-match-issue-45045.stderr2
-rw-r--r--tests/ui/nll/capture-ref-in-struct.stderr3
-rw-r--r--tests/ui/nll/closure-access-spans.stderr4
-rw-r--r--tests/ui/nll/closure-borrow-spans.stderr14
-rw-r--r--tests/ui/nll/closure-requirements/escape-argument.stderr3
-rw-r--r--tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-comparing-against-free.stderr2
-rw-r--r--tests/ui/nll/closure-requirements/type-test-subject-non-trivial-region.rs19
-rw-r--r--tests/ui/nll/closure-requirements/type-test-subject-opaque-1.rs18
-rw-r--r--tests/ui/nll/closure-requirements/type-test-subject-opaque-2.rs17
-rw-r--r--tests/ui/nll/closure-requirements/type-test-subject-unnamed-region.rs24
-rw-r--r--tests/ui/nll/closure-use-spans.stderr12
-rw-r--r--tests/ui/nll/do-not-ignore-lifetime-bounds-in-copy-proj.stderr2
-rw-r--r--tests/ui/nll/do-not-ignore-lifetime-bounds-in-copy.stderr2
-rw-r--r--tests/ui/nll/dont-print-desugared.stderr1
-rw-r--r--tests/ui/nll/drop-no-may-dangle.stderr8
-rw-r--r--tests/ui/nll/guarantor-issue-46974.stderr4
-rw-r--r--tests/ui/nll/issue-27282-move-ref-mut-into-guard.stderr4
-rw-r--r--tests/ui/nll/issue-27282-mutation-in-guard.stderr4
-rw-r--r--tests/ui/nll/issue-27583.rs (renamed from tests/ui/issues/issue-27583.rs)0
-rw-r--r--tests/ui/nll/issue-27868.stderr4
-rw-r--r--tests/ui/nll/issue-46036.stderr2
-rw-r--r--tests/ui/nll/issue-48179.rs (renamed from tests/ui/issues/issue-48179.rs)0
-rw-r--r--tests/ui/nll/issue-48803.stderr4
-rw-r--r--tests/ui/nll/issue-52057.rs4
-rw-r--r--tests/ui/nll/issue-52534-2.stderr2
-rw-r--r--tests/ui/nll/issue-52663-trait-object.stderr2
-rw-r--r--tests/ui/nll/issue-54382-use-span-of-tail-of-block.stderr3
-rw-r--r--tests/ui/nll/issue-54556-niconii.stderr3
-rw-r--r--tests/ui/nll/issue-54556-stephaneyfx.stderr2
-rw-r--r--tests/ui/nll/issue-54556-temps-in-tail-diagnostic.stderr3
-rw-r--r--tests/ui/nll/issue-54556-used-vs-unused-tails.stderr103
-rw-r--r--tests/ui/nll/issue-54556-wrap-it-up.stderr4
-rw-r--r--tests/ui/nll/issue-55511.stderr2
-rw-r--r--tests/ui/nll/issue-57642-higher-ranked-subtype.stderr6
-rw-r--r--tests/ui/nll/issue-57989.stderr4
-rw-r--r--tests/ui/nll/issue-68550.stderr4
-rw-r--r--tests/ui/nll/issue-69114-static-mut-ty.stderr6
-rw-r--r--tests/ui/nll/issue-69114-static-ty.stderr2
-rw-r--r--tests/ui/nll/issue-73159-rpit-static.stderr1
-rw-r--r--tests/ui/nll/issue-75777.rs (renamed from tests/ui/issues/issue-75777.rs)0
-rw-r--r--tests/ui/nll/issue-75777.stderr (renamed from tests/ui/issues/issue-75777.stderr)0
-rw-r--r--tests/ui/nll/loan_ends_mid_block_pair.stderr4
-rw-r--r--tests/ui/nll/local-outlives-static-via-hrtb.stderr5
-rw-r--r--tests/ui/nll/match-cfg-fake-edges2.stderr2
-rw-r--r--tests/ui/nll/match-guards-always-borrow.stderr4
-rw-r--r--tests/ui/nll/match-guards-partially-borrow.stderr8
-rw-r--r--tests/ui/nll/match-on-borrowed.stderr6
-rw-r--r--tests/ui/nll/maybe-initialized-drop-implicit-fragment-drop.stderr4
-rw-r--r--tests/ui/nll/maybe-initialized-drop-with-fragment.stderr4
-rw-r--r--tests/ui/nll/maybe-initialized-drop-with-uninitialized-fragments.stderr4
-rw-r--r--tests/ui/nll/maybe-initialized-drop.stderr4
-rw-r--r--tests/ui/nll/member-constraints/min-choice-reject-ambiguous.rs43
-rw-r--r--tests/ui/nll/member-constraints/min-choice-reject-ambiguous.stderr42
-rw-r--r--tests/ui/nll/member-constraints/min-choice.rs34
-rw-r--r--tests/ui/nll/member-constraints/nested-impl-trait-fail.rs33
-rw-r--r--tests/ui/nll/member-constraints/nested-impl-trait-fail.stderr83
-rw-r--r--tests/ui/nll/member-constraints/nested-impl-trait-pass.rs29
-rw-r--r--tests/ui/nll/outlives-suggestion-simple.stderr4
-rw-r--r--tests/ui/nll/polonius/polonius-smoke-test.stderr8
-rw-r--r--tests/ui/nll/promoted-bounds.stderr1
-rw-r--r--tests/ui/nll/reference-carried-through-struct-field.stderr2
-rw-r--r--tests/ui/nll/relate_tys/var-appears-twice.stderr3
-rw-r--r--tests/ui/nll/ty-outlives/impl-trait-captures.stderr4
-rw-r--r--tests/ui/nll/ty-outlives/projection-one-region-closure.stderr2
-rw-r--r--tests/ui/nll/ty-outlives/projection-one-region-trait-bound-closure.stderr2
-rw-r--r--tests/ui/nll/ty-outlives/projection-two-region-trait-bound-closure.stderr28
-rw-r--r--tests/ui/nll/user-annotations/adt-brace-enums.stderr3
-rw-r--r--tests/ui/nll/user-annotations/adt-brace-structs.stderr3
-rw-r--r--tests/ui/nll/user-annotations/adt-nullary-enums.stderr6
-rw-r--r--tests/ui/nll/user-annotations/adt-tuple-enums.stderr3
-rw-r--r--tests/ui/nll/user-annotations/adt-tuple-struct-calls.stderr7
-rw-r--r--tests/ui/nll/user-annotations/adt-tuple-struct.stderr3
-rw-r--r--tests/ui/nll/user-annotations/cast_static_lifetime.stderr2
-rw-r--r--tests/ui/nll/user-annotations/constant-in-expr-inherent-2.stderr11
-rw-r--r--tests/ui/nll/user-annotations/fns.stderr3
-rw-r--r--tests/ui/nll/user-annotations/method-call.stderr4
-rw-r--r--tests/ui/nll/user-annotations/method-ufcs-1.stderr5
-rw-r--r--tests/ui/nll/user-annotations/method-ufcs-2.stderr8
-rw-r--r--tests/ui/nll/user-annotations/method-ufcs-3.stderr4
-rw-r--r--tests/ui/nll/user-annotations/method-ufcs-inherent-1.stderr1
-rw-r--r--tests/ui/nll/user-annotations/method-ufcs-inherent-2.stderr2
-rw-r--r--tests/ui/nll/user-annotations/method-ufcs-inherent-3.stderr1
-rw-r--r--tests/ui/nll/user-annotations/method-ufcs-inherent-4.stderr2
-rw-r--r--tests/ui/nll/user-annotations/normalization.stderr4
-rw-r--r--tests/ui/nll/user-annotations/pattern_substs_on_brace_enum_variant.stderr4
-rw-r--r--tests/ui/nll/user-annotations/pattern_substs_on_brace_struct.stderr4
-rw-r--r--tests/ui/nll/user-annotations/pattern_substs_on_tuple_enum_variant.stderr4
-rw-r--r--tests/ui/nll/user-annotations/pattern_substs_on_tuple_struct.stderr4
-rw-r--r--tests/ui/nll/user-annotations/patterns.stderr24
-rw-r--r--tests/ui/nll/user-annotations/promoted-annotation.stderr1
-rw-r--r--tests/ui/nll/user-annotations/type_ascription_static_lifetime.stderr2
-rw-r--r--tests/ui/noexporttypeexe.rs2
-rw-r--r--tests/ui/noexporttypeexe.stderr2
-rw-r--r--tests/ui/numbers-arithmetic/issue-105626.rs17
-rw-r--r--tests/ui/numbers-arithmetic/next-power-of-two-overflow-debug.rs2
-rw-r--r--tests/ui/object-pointer-types.stderr2
-rw-r--r--tests/ui/object-safety/object-safety-supertrait-mentions-GAT.stderr5
-rw-r--r--tests/ui/optimization-remark.rs1
-rw-r--r--tests/ui/or-patterns/already-bound-name.stderr2
-rw-r--r--tests/ui/or-patterns/nested-undelimited-precedence.stderr8
-rw-r--r--tests/ui/packed/issue-27060-rpass.rs23
-rw-r--r--tests/ui/packed/issue-27060-rpass.stderr68
-rw-r--r--tests/ui/packed/issue-27060.rs4
-rw-r--r--tests/ui/packed/issue-27060.stderr76
-rw-r--r--tests/ui/packed/packed-struct-borrow-element-64bit.rs5
-rw-r--r--tests/ui/packed/packed-struct-borrow-element-64bit.stderr31
-rw-r--r--tests/ui/packed/packed-struct-borrow-element.rs8
-rw-r--r--tests/ui/packed/packed-struct-borrow-element.stderr54
-rw-r--r--tests/ui/panics/default-backtrace-ice.stderr5
-rw-r--r--tests/ui/parser/anon-enums-are-ambiguous.rs26
-rw-r--r--tests/ui/parser/bastion-of-the-turbofish.rs2
-rw-r--r--tests/ui/parser/deli-ident-issue-1.rs22
-rw-r--r--tests/ui/parser/deli-ident-issue-1.stderr17
-rw-r--r--tests/ui/parser/deli-ident-issue-2.rs7
-rw-r--r--tests/ui/parser/deli-ident-issue-2.stderr19
-rw-r--r--tests/ui/parser/do-not-suggest-semicolon-before-array.rs2
-rw-r--r--tests/ui/parser/do-not-suggest-semicolon-before-array.stderr4
-rw-r--r--tests/ui/parser/fn-header-semantic-fail.stderr12
-rw-r--r--tests/ui/parser/issue-102806.stderr7
-rw-r--r--tests/ui/parser/issue-103451.rs1
-rw-r--r--tests/ui/parser/issue-103451.stderr24
-rw-r--r--tests/ui/parser/issue-107705.rs3
-rw-r--r--tests/ui/parser/issue-107705.stderr10
-rw-r--r--tests/ui/parser/issue-108495-dec.rs39
-rw-r--r--tests/ui/parser/issue-108495-dec.stderr69
-rw-r--r--tests/ui/parser/issue-68987-unmatch-issue-1.rs12
-rw-r--r--tests/ui/parser/issue-68987-unmatch-issue-1.stderr16
-rw-r--r--tests/ui/parser/issue-68987-unmatch-issue-2.rs14
-rw-r--r--tests/ui/parser/issue-68987-unmatch-issue-2.stderr19
-rw-r--r--tests/ui/parser/issue-68987-unmatch-issue-3.rs8
-rw-r--r--tests/ui/parser/issue-68987-unmatch-issue-3.stderr19
-rw-r--r--tests/ui/parser/issue-68987-unmatch-issue.rs12
-rw-r--r--tests/ui/parser/issue-68987-unmatch-issue.stderr16
-rw-r--r--tests/ui/parser/issue-81804.rs3
-rw-r--r--tests/ui/parser/issue-81804.stderr36
-rw-r--r--tests/ui/parser/issue-81827.rs1
-rw-r--r--tests/ui/parser/issue-81827.stderr32
-rw-r--r--tests/ui/parser/issues/issue-104367.rs6
-rw-r--r--tests/ui/parser/issues/issue-104367.stderr26
-rw-r--r--tests/ui/parser/issues/issue-105209.rs3
-rw-r--r--tests/ui/parser/issues/issue-105209.stderr22
-rw-r--r--tests/ui/parser/issues/issue-10636-2.rs4
-rw-r--r--tests/ui/parser/issues/issue-10636-2.stderr19
-rw-r--r--tests/ui/parser/issues/issue-44406.stderr4
-rw-r--r--tests/ui/parser/issues/issue-58094-missing-right-square-bracket.rs3
-rw-r--r--tests/ui/parser/issues/issue-58094-missing-right-square-bracket.stderr10
-rw-r--r--tests/ui/parser/issues/issue-58856-1.rs5
-rw-r--r--tests/ui/parser/issues/issue-58856-1.stderr29
-rw-r--r--tests/ui/parser/issues/issue-58856-2.rs5
-rw-r--r--tests/ui/parser/issues/issue-58856-2.stderr33
-rw-r--r--tests/ui/parser/issues/issue-60075.rs5
-rw-r--r--tests/ui/parser/issues/issue-60075.stderr20
-rw-r--r--tests/ui/parser/issues/issue-62524.rs2
-rw-r--r--tests/ui/parser/issues/issue-62524.stderr25
-rw-r--r--tests/ui/parser/issues/issue-62546.rs4
-rw-r--r--tests/ui/parser/issues/issue-62546.stderr15
-rw-r--r--tests/ui/parser/issues/issue-62554.rs1
-rw-r--r--tests/ui/parser/issues/issue-62554.stderr64
-rw-r--r--tests/ui/parser/issues/issue-62881.rs5
-rw-r--r--tests/ui/parser/issues/issue-62881.stderr24
-rw-r--r--tests/ui/parser/issues/issue-62894.rs1
-rw-r--r--tests/ui/parser/issues/issue-62894.stderr40
-rw-r--r--tests/ui/parser/issues/issue-62895.rs14
-rw-r--r--tests/ui/parser/issues/issue-62895.stderr51
-rw-r--r--tests/ui/parser/issues/issue-62973.rs2
-rw-r--r--tests/ui/parser/issues/issue-62973.stderr80
-rw-r--r--tests/ui/parser/issues/issue-63116.rs2
-rw-r--r--tests/ui/parser/issues/issue-63116.stderr25
-rw-r--r--tests/ui/parser/issues/issue-63135.rs4
-rw-r--r--tests/ui/parser/issues/issue-63135.stderr34
-rw-r--r--tests/ui/parser/issues/issue-66357-unexpected-unreachable.rs4
-rw-r--r--tests/ui/parser/issues/issue-66357-unexpected-unreachable.stderr17
-rw-r--r--tests/ui/parser/issues/issue-67377-invalid-syntax-in-enum-discriminant.rs14
-rw-r--r--tests/ui/parser/issues/issue-67377-invalid-syntax-in-enum-discriminant.stderr113
-rw-r--r--tests/ui/parser/issues/issue-68629.rsbin336 -> 129 bytes
-rw-r--r--tests/ui/parser/issues/issue-68629.stderrbin1637 -> 944 bytes
-rw-r--r--tests/ui/parser/issues/issue-69259.rs3
-rw-r--r--tests/ui/parser/issues/issue-69259.stderr8
-rw-r--r--tests/ui/parser/issues/issue-70583-block-is-empty-1.stderr4
-rw-r--r--tests/ui/parser/issues/issue-70583-block-is-empty-2.stderr6
-rw-r--r--tests/ui/parser/issues/issue-84104.rs1
-rw-r--r--tests/ui/parser/issues/issue-84104.stderr10
-rw-r--r--tests/ui/parser/issues/issue-84148-2.rs1
-rw-r--r--tests/ui/parser/issues/issue-84148-2.stderr21
-rw-r--r--tests/ui/parser/issues/issue-87086-colon-path-sep.rs1
-rw-r--r--tests/ui/parser/issues/issue-87086-colon-path-sep.stderr81
-rw-r--r--tests/ui/parser/issues/issue-87812-path.stderr2
-rw-r--r--tests/ui/parser/issues/issue-88770.rs3
-rw-r--r--tests/ui/parser/issues/issue-88770.stderr50
-rw-r--r--tests/ui/parser/macro-mismatched-delim-paren-brace.stderr22
-rw-r--r--tests/ui/parser/match-arm-without-braces.stderr10
-rw-r--r--tests/ui/parser/mbe_missing_right_paren.rs2
-rw-r--r--tests/ui/parser/mbe_missing_right_paren.stderr23
-rw-r--r--tests/ui/parser/mismatched-braces/missing-close-brace-in-impl-trait.rs6
-rw-r--r--tests/ui/parser/mismatched-braces/missing-close-brace-in-impl-trait.stderr25
-rw-r--r--tests/ui/parser/mismatched-braces/missing-close-brace-in-struct.rs2
-rw-r--r--tests/ui/parser/mismatched-braces/missing-close-brace-in-struct.stderr11
-rw-r--r--tests/ui/parser/mismatched-braces/missing-close-brace-in-trait.rs3
-rw-r--r--tests/ui/parser/mismatched-braces/missing-close-brace-in-trait.stderr20
-rw-r--r--tests/ui/parser/missing-closing-angle-bracket-eq-constraint.rs2
-rw-r--r--tests/ui/parser/missing-closing-angle-bracket-eq-constraint.stderr12
-rw-r--r--tests/ui/parser/missing-expression-in-for-loop.rs5
-rw-r--r--tests/ui/parser/missing-expression-in-for-loop.stderr13
-rw-r--r--tests/ui/parser/missing_right_paren.rs3
-rw-r--r--tests/ui/parser/missing_right_paren.stderr25
-rw-r--r--tests/ui/parser/parser-recovery-1.rs3
-rw-r--r--tests/ui/parser/parser-recovery-1.stderr25
-rw-r--r--tests/ui/parser/parser-recovery-2.rs5
-rw-r--r--tests/ui/parser/parser-recovery-2.stderr21
-rw-r--r--tests/ui/parser/raw/too-many-hash.rs6
-rw-r--r--tests/ui/parser/raw/too-many-hash.stderr8
-rw-r--r--tests/ui/parser/recover-fn-ptr-with-generics.stderr12
-rw-r--r--tests/ui/parser/recover-quantified-closure.rs2
-rw-r--r--tests/ui/parser/recover-quantified-closure.stderr4
-rw-r--r--tests/ui/parser/recover-range-pats.stderr6
-rw-r--r--tests/ui/parser/suggest_misplaced_generics/enum.fixed9
-rw-r--r--tests/ui/parser/suggest_misplaced_generics/enum.rs9
-rw-r--r--tests/ui/parser/suggest_misplaced_generics/enum.stderr14
-rw-r--r--tests/ui/parser/suggest_misplaced_generics/existing_generics.rs9
-rw-r--r--tests/ui/parser/suggest_misplaced_generics/existing_generics.stderr10
-rw-r--r--tests/ui/parser/suggest_misplaced_generics/fn-complex-generics.fixed9
-rw-r--r--tests/ui/parser/suggest_misplaced_generics/fn-complex-generics.rs9
-rw-r--r--tests/ui/parser/suggest_misplaced_generics/fn-complex-generics.stderr14
-rw-r--r--tests/ui/parser/suggest_misplaced_generics/fn-invalid-generics.rs8
-rw-r--r--tests/ui/parser/suggest_misplaced_generics/fn-invalid-generics.stderr8
-rw-r--r--tests/ui/parser/suggest_misplaced_generics/fn-simple.fixed9
-rw-r--r--tests/ui/parser/suggest_misplaced_generics/fn-simple.rs9
-rw-r--r--tests/ui/parser/suggest_misplaced_generics/fn-simple.stderr14
-rw-r--r--tests/ui/parser/suggest_misplaced_generics/struct.fixed9
-rw-r--r--tests/ui/parser/suggest_misplaced_generics/struct.rs9
-rw-r--r--tests/ui/parser/suggest_misplaced_generics/struct.stderr14
-rw-r--r--tests/ui/parser/suggest_misplaced_generics/trait.fixed11
-rw-r--r--tests/ui/parser/suggest_misplaced_generics/trait.rs11
-rw-r--r--tests/ui/parser/suggest_misplaced_generics/trait.stderr14
-rw-r--r--tests/ui/parser/suggest_misplaced_generics/type.fixed9
-rw-r--r--tests/ui/parser/suggest_misplaced_generics/type.rs9
-rw-r--r--tests/ui/parser/suggest_misplaced_generics/type.stderr14
-rw-r--r--tests/ui/parser/trait-object-delimiters.rs2
-rw-r--r--tests/ui/parser/trait-object-delimiters.stderr28
-rw-r--r--tests/ui/parser/type-ascription-in-pattern.rs16
-rw-r--r--tests/ui/parser/type-ascription-in-pattern.stderr54
-rw-r--r--tests/ui/parser/unclosed-delimiter-in-dep.rs1
-rw-r--r--tests/ui/parser/unclosed-delimiter-in-dep.stderr14
-rw-r--r--tests/ui/parser/use-unclosed-brace.rs2
-rw-r--r--tests/ui/parser/use-unclosed-brace.stderr20
-rw-r--r--tests/ui/pattern/bindings-after-at/bind-by-move-neither-can-live-while-the-other-survives-1.stderr8
-rw-r--r--tests/ui/pattern/bindings-after-at/borrowck-pat-at-and-box.stderr32
-rw-r--r--tests/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref.stderr120
-rw-r--r--tests/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-and-ref.stderr144
-rw-r--r--tests/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-twice.stderr96
-rw-r--r--tests/ui/pattern/bindings-after-at/default-binding-modes-both-sides-independent.stderr16
-rw-r--r--tests/ui/pattern/for-loop-bad-item.stderr2
-rw-r--r--tests/ui/pattern/issue-67037-pat-tup-scrut-ty-diff-less-fields.stderr2
-rw-r--r--tests/ui/pattern/move-ref-patterns/borrowck-move-ref-pattern.stderr2
-rw-r--r--tests/ui/pattern/pat-struct-field-expr-has-type.stderr2
-rw-r--r--tests/ui/pattern/pat-type-err-formal-param.stderr2
-rw-r--r--tests/ui/pattern/pat-type-err-let-stmt.stderr8
-rw-r--r--tests/ui/pattern/pattern-error-continue.rs2
-rw-r--r--tests/ui/pattern/pattern-error-continue.stderr2
-rw-r--r--tests/ui/pattern/pattern-ident-path-generics.stderr2
-rw-r--r--tests/ui/pattern/pattern-tyvar.stderr2
-rw-r--r--tests/ui/point-to-type-err-cause-on-impl-trait-return-2.stderr2
-rw-r--r--tests/ui/print_type_sizes/async.stdout14
-rw-r--r--tests/ui/print_type_sizes/generator.stdout10
-rw-r--r--tests/ui/print_type_sizes/generator_discr_placement.stdout6
-rw-r--r--tests/ui/privacy/privacy1.rs2
-rw-r--r--tests/ui/privacy/privacy1.stderr6
-rw-r--r--tests/ui/privacy/private-impl-method.rs2
-rw-r--r--tests/ui/privacy/private-impl-method.stderr6
-rw-r--r--tests/ui/privacy/private-in-public-ill-formed.stderr8
-rw-r--r--tests/ui/privacy/private-method-cross-crate.rs2
-rw-r--r--tests/ui/privacy/private-method-cross-crate.stderr6
-rw-r--r--tests/ui/privacy/private-method-inherited.rs2
-rw-r--r--tests/ui/privacy/private-method-inherited.stderr6
-rw-r--r--tests/ui/privacy/private-method.rs2
-rw-r--r--tests/ui/privacy/private-method.stderr6
-rw-r--r--tests/ui/privacy/restricted/test.stderr18
-rw-r--r--tests/ui/proc-macro/allowed-signatures.rs26
-rw-r--r--tests/ui/proc-macro/break-token-spans.stderr2
-rw-r--r--tests/ui/proc-macro/crt-static.rs3
-rw-r--r--tests/ui/proc-macro/issue-37788.stderr2
-rw-r--r--tests/ui/proc-macro/proc-macro-abi.rs31
-rw-r--r--tests/ui/proc-macro/proc-macro-abi.stderr20
-rw-r--r--tests/ui/proc-macro/resolved-located-at.stderr2
-rw-r--r--tests/ui/proc-macro/signature-proc-macro-attribute.rs32
-rw-r--r--tests/ui/proc-macro/signature-proc-macro-attribute.stderr42
-rw-r--r--tests/ui/proc-macro/signature-proc-macro-derive.rs31
-rw-r--r--tests/ui/proc-macro/signature-proc-macro-derive.stderr40
-rw-r--r--tests/ui/proc-macro/signature-proc-macro.rs31
-rw-r--r--tests/ui/proc-macro/signature-proc-macro.stderr40
-rw-r--r--tests/ui/proc-macro/signature.rs6
-rw-r--r--tests/ui/proc-macro/signature.stderr46
-rw-r--r--tests/ui/process/process-sigpipe.rs1
-rw-r--r--tests/ui/pub/pub-ident-fn-3.rs8
-rw-r--r--tests/ui/pub/pub-ident-fn-3.stderr8
-rw-r--r--tests/ui/pub/pub-ident-fn-or-struct-2.rs4
-rw-r--r--tests/ui/pub/pub-ident-fn-or-struct-2.stderr8
-rw-r--r--tests/ui/pub/pub-ident-struct-2.rs8
-rw-r--r--tests/ui/pub/pub-ident-struct-2.stderr13
-rw-r--r--tests/ui/pub/pub-ident-struct-3.rs4
-rw-r--r--tests/ui/pub/pub-ident-struct-3.stderr13
-rw-r--r--tests/ui/pub/pub-ident-struct-4.fixed6
-rw-r--r--tests/ui/pub/pub-ident-struct-4.rs6
-rw-r--r--tests/ui/pub/pub-ident-struct-4.stderr13
-rw-r--r--tests/ui/query-system/no-query-in-printing-during-query-descr.rs6
-rw-r--r--tests/ui/query-system/no-query-in-printing-during-query-descr.stderr9
-rw-r--r--tests/ui/range/issue-54505-no-literals.stderr24
-rw-r--r--tests/ui/range/issue-54505-no-std.stderr12
-rw-r--r--tests/ui/range/issue-54505.stderr12
-rw-r--r--tests/ui/range/issue-73553-misinterp-range-literal.stderr4
-rw-r--r--tests/ui/recursion/issue-83150.stderr4
-rw-r--r--tests/ui/recursion_limit/issue-105700.rs9
-rw-r--r--tests/ui/recursion_limit/issue-105700.stderr10
-rw-r--r--tests/ui/recursion_limit/issue-40003.rs (renamed from tests/ui/issues/issue-40003.rs)0
-rw-r--r--tests/ui/regions/do-not-suggest-adding-bound-to-opaque-type.stderr2
-rw-r--r--tests/ui/regions/higher-ranked-implied.rs14
-rw-r--r--tests/ui/regions/higher-ranked-implied.stderr21
-rw-r--r--tests/ui/regions/issue-102374.stderr2
-rw-r--r--tests/ui/regions/region-lifetime-bounds-on-fns-where-clause.stderr1
-rw-r--r--tests/ui/regions/region-multiple-lifetime-bounds-on-fns-where-clause.stderr1
-rw-r--r--tests/ui/regions/regions-addr-of-arg.stderr2
-rw-r--r--tests/ui/regions/regions-early-bound-error-method.stderr2
-rw-r--r--tests/ui/regions/regions-fn-subtyping-return-static-fail.stderr1
-rw-r--r--tests/ui/regions/regions-free-region-ordering-caller1.stderr2
-rw-r--r--tests/ui/regions/regions-free-region-ordering-incorrect.stderr2
-rw-r--r--tests/ui/regions/regions-free-region-outlives-static-outlives-free-region.rs2
-rw-r--r--tests/ui/regions/regions-free-region-outlives-static-outlives-free-region.stderr7
-rw-r--r--tests/ui/regions/regions-infer-proc-static-upvar.stderr2
-rw-r--r--tests/ui/regions/regions-lifetime-bounds-on-fns.stderr1
-rw-r--r--tests/ui/regions/regions-mock-codegen.rs8
-rw-r--r--tests/ui/regions/regions-nested-fns.stderr2
-rw-r--r--tests/ui/regions/regions-pattern-typing-issue-19552.stderr2
-rw-r--r--tests/ui/regions/regions-pattern-typing-issue-19997.stderr4
-rw-r--r--tests/ui/regions/regions-static-bound-rpass.rs2
-rw-r--r--tests/ui/regions/regions-static-bound-rpass.stderr11
-rw-r--r--tests/ui/regions/regions-static-bound.rs8
-rw-r--r--tests/ui/regions/regions-static-bound.stderr30
-rw-r--r--tests/ui/regions/resolve-re-error-ice.rs22
-rw-r--r--tests/ui/regions/resolve-re-error-ice.stderr15
-rw-r--r--tests/ui/reify-intrinsic.stderr5
-rw-r--r--tests/ui/repeat-expr/repeat_count.rs2
-rw-r--r--tests/ui/repeat-expr/repeat_count.stderr2
-rw-r--r--tests/ui/repr/16-bit-repr-c-enum.rs52
-rw-r--r--tests/ui/resolve/issue-108529.rs8
-rw-r--r--tests/ui/resolve/issue-108529.stderr9
-rw-r--r--tests/ui/resolve/name-clash-nullary.stderr2
-rw-r--r--tests/ui/resolve/privacy-enum-ctor.stderr6
-rw-r--r--tests/ui/resolve/resolve-inconsistent-names.stderr2
-rw-r--r--tests/ui/resolve/resolve-primitive-fallback.stderr9
-rw-r--r--tests/ui/resolve/token-error-correct-2.rs1
-rw-r--r--tests/ui/resolve/token-error-correct-2.stderr10
-rw-r--r--tests/ui/resolve/token-error-correct-3.rs5
-rw-r--r--tests/ui/resolve/token-error-correct-3.stderr26
-rw-r--r--tests/ui/resolve/token-error-correct-4.fixed10
-rw-r--r--tests/ui/resolve/token-error-correct-4.rs5
-rw-r--r--tests/ui/resolve/token-error-correct-4.stderr18
-rw-r--r--tests/ui/resolve/token-error-correct.rs1
-rw-r--r--tests/ui/resolve/token-error-correct.stderr10
-rw-r--r--tests/ui/return/return-type.stderr2
-rw-r--r--tests/ui/return/tail-expr-as-potential-return.stderr4
-rw-r--r--tests/ui/rfc-2005-default-binding-mode/const.stderr2
-rw-r--r--tests/ui/rfc-2005-default-binding-mode/lit.stderr4
-rw-r--r--tests/ui/rfc-2008-non-exhaustive/borrowck-non-exhaustive.stderr2
-rw-r--r--tests/ui/rfc-2008-non-exhaustive/uninhabited/coercions.stderr8
-rw-r--r--tests/ui/rfc-2008-non-exhaustive/uninhabited/coercions_same_crate.stderr8
-rw-r--r--tests/ui/rfc-2091-track-caller/call-chain.rs2
-rw-r--r--tests/ui/rfc-2091-track-caller/error-with-main.stderr2
-rw-r--r--tests/ui/rfc-2294-if-let-guard/typeck.stderr4
-rw-r--r--tests/ui/rfc-2457/mod_file_nonascii_forbidden.stderr2
-rw-r--r--tests/ui/rfc-2497-if-let-chains/disallowed-positions.stderr46
-rw-r--r--tests/ui/rfc-2497-if-let-chains/ensure-that-let-else-does-not-interact-with-let-chains.stderr13
-rw-r--r--tests/ui/rfc-2632-const-trait-impl/const-closure-parse-not-item.rs10
-rw-r--r--tests/ui/rfc-2632-const-trait-impl/const_derives/derive-const-with-params.rs13
-rw-r--r--tests/ui/rfc-2632-const-trait-impl/do-not-const-check-override.rs19
-rw-r--r--tests/ui/rfc-2632-const-trait-impl/do-not-const-check.rs18
-rw-r--r--tests/ui/rfc-2632-const-trait-impl/function-pointer-does-not-require-const.rs8
-rw-r--r--tests/ui/rfcs/rfc-2396-target_feature-11/fn-ptr.mir.stderr6
-rw-r--r--tests/ui/rfcs/rfc-2396-target_feature-11/fn-ptr.thir.stderr6
-rw-r--r--tests/ui/rfcs/rfc-2528-type-changing-struct-update/feature-gate.stderr2
-rw-r--r--tests/ui/rfcs/rfc-2528-type-changing-struct-update/issue-92010-trait-bound-not-satisfied.stderr2
-rw-r--r--tests/ui/rfcs/rfc-2528-type-changing-struct-update/lifetime-update.stderr3
-rw-r--r--tests/ui/rfcs/rfc-2528-type-changing-struct-update/type-generic-update.stderr4
-rw-r--r--tests/ui/runtime/out-of-stack.rs1
-rw-r--r--tests/ui/runtime/signal-alternate-stack-cleanup.rs1
-rw-r--r--tests/ui/rust-2018/edition-lint-infer-outlives-multispan.rs20
-rw-r--r--tests/ui/rust-2018/edition-lint-infer-outlives-multispan.stderr58
-rw-r--r--tests/ui/rust-2018/edition-lint-infer-outlives.fixed9
-rw-r--r--tests/ui/rust-2018/edition-lint-infer-outlives.rs9
-rw-r--r--tests/ui/rust-2018/edition-lint-infer-outlives.stderr14
-rw-r--r--tests/ui/rust-2018/remove-extern-crate.fixed10
-rw-r--r--tests/ui/rust-2018/remove-extern-crate.rs10
-rw-r--r--tests/ui/rust-2018/remove-extern-crate.stderr22
-rw-r--r--tests/ui/sanitize/cfg-kasan.rs28
-rw-r--r--tests/ui/sanitize/memory-eager.rs1
-rw-r--r--tests/ui/save-analysis/emit-notifications.polonius.stderr2
-rw-r--r--tests/ui/save-analysis/emit-notifications.rs7
-rw-r--r--tests/ui/save-analysis/emit-notifications.stderr2
-rw-r--r--tests/ui/save-analysis/issue-26459.rs8
-rw-r--r--tests/ui/save-analysis/issue-26459.stderr9
-rw-r--r--tests/ui/save-analysis/issue-37323.rs20
-rw-r--r--tests/ui/save-analysis/issue-59134-0.rs12
-rw-r--r--tests/ui/save-analysis/issue-59134-0.stderr9
-rw-r--r--tests/ui/save-analysis/issue-59134-1.rs12
-rw-r--r--tests/ui/save-analysis/issue-59134-1.stderr9
-rw-r--r--tests/ui/save-analysis/issue-63663.rs28
-rw-r--r--tests/ui/save-analysis/issue-64659.rs10
-rw-r--r--tests/ui/save-analysis/issue-65411.rs15
-rw-r--r--tests/ui/save-analysis/issue-65590.rs21
-rw-r--r--tests/ui/save-analysis/issue-68621.rs17
-rw-r--r--tests/ui/save-analysis/issue-68621.stderr10
-rw-r--r--tests/ui/save-analysis/issue-72267.rs7
-rw-r--r--tests/ui/save-analysis/issue-72267.stderr15
-rw-r--r--tests/ui/save-analysis/issue-73020.rs5
-rw-r--r--tests/ui/save-analysis/issue-73020.stderr9
-rw-r--r--tests/ui/save-analysis/issue-73022.rs13
-rw-r--r--tests/ui/save-analysis/issue-89066.rs28
-rw-r--r--tests/ui/save-analysis/issue-89066.stderr39
-rw-r--r--tests/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.stderr5
-rw-r--r--tests/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.stderr5
-rw-r--r--tests/ui/self/arbitrary_self_types_pin_lifetime_mismatch-async.stderr6
-rw-r--r--tests/ui/self/arbitrary_self_types_pin_lifetime_mismatch.stderr6
-rw-r--r--tests/ui/self/arbitrary_self_types_pointers_and_wrappers.rs22
-rw-r--r--tests/ui/self/elision/lt-ref-self-async.stderr12
-rw-r--r--tests/ui/self/elision/lt-ref-self.stderr12
-rw-r--r--tests/ui/self/elision/ref-mut-self-async.stderr12
-rw-r--r--tests/ui/self/elision/ref-mut-self.stderr12
-rw-r--r--tests/ui/self/elision/ref-mut-struct-async.stderr10
-rw-r--r--tests/ui/self/elision/ref-mut-struct.stderr10
-rw-r--r--tests/ui/self/elision/ref-self-async.stderr14
-rw-r--r--tests/ui/self/elision/ref-self.stderr14
-rw-r--r--tests/ui/self/elision/ref-struct-async.stderr10
-rw-r--r--tests/ui/self/elision/ref-struct.stderr10
-rw-r--r--tests/ui/self/issue-61882-2.stderr2
-rw-r--r--tests/ui/self/issue-61882.stderr2
-rw-r--r--tests/ui/seq-args.rs4
-rw-r--r--tests/ui/seq-args.stderr4
-rw-r--r--tests/ui/simd/intrinsic/generic-cast-pass.rs146
-rw-r--r--tests/ui/simd/intrinsic/generic-gather-pass.rs24
-rw-r--r--tests/ui/simd/issue-89193.rs11
-rw-r--r--tests/ui/single-use-lifetime/issue-107998.rs9
-rw-r--r--tests/ui/single-use-lifetime/issue-107998.stderr30
-rw-r--r--tests/ui/slightly-nice-generic-literal-messages.rs2
-rw-r--r--tests/ui/slightly-nice-generic-literal-messages.stderr2
-rw-r--r--tests/ui/span/borrowck-call-is-borrow-issue-12224.stderr3
-rw-r--r--tests/ui/span/borrowck-let-suggestion-suffixes.rs1
-rw-r--r--tests/ui/span/borrowck-let-suggestion-suffixes.stderr11
-rw-r--r--tests/ui/span/coerce-suggestions.stderr6
-rw-r--r--tests/ui/span/destructor-restrictions.stderr2
-rw-r--r--tests/ui/span/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.rs12
-rw-r--r--tests/ui/span/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.stderr93
-rw-r--r--tests/ui/span/dropck-object-cycle.stderr2
-rw-r--r--tests/ui/span/dropck_arr_cycle_checked.stderr9
-rw-r--r--tests/ui/span/dropck_direct_cycle_with_drop.stderr5
-rw-r--r--tests/ui/span/dropck_misc_variants.stderr6
-rw-r--r--tests/ui/span/dropck_vec_cycle_checked.stderr9
-rw-r--r--tests/ui/span/issue-107353.rs9
-rw-r--r--tests/ui/span/issue-23338-locals-die-before-temps-of-body.stderr4
-rw-r--r--tests/ui/span/issue-24805-dropck-child-has-items-via-parent.stderr3
-rw-r--r--tests/ui/span/issue-24805-dropck-trait-has-items.stderr9
-rw-r--r--tests/ui/span/issue-24895-copy-clone-dropck.stderr3
-rw-r--r--tests/ui/span/issue-25199.stderr2
-rw-r--r--tests/ui/span/issue-26656.stderr3
-rw-r--r--tests/ui/span/issue-29106.stderr6
-rw-r--r--tests/ui/span/issue-33884.stderr2
-rw-r--r--tests/ui/span/issue-34264.stderr18
-rw-r--r--tests/ui/span/issue-36537.stderr2
-rw-r--r--tests/ui/span/issue-37767.stderr12
-rw-r--r--tests/ui/span/issue-39018.stderr2
-rw-r--r--tests/ui/span/issue-40157.stderr9
-rw-r--r--tests/ui/span/issue-42234-unknown-receiver-type.full.stderr2
-rw-r--r--tests/ui/span/issue-42234-unknown-receiver-type.generic_arg.stderr2
-rw-r--r--tests/ui/span/issue28498-reject-lifetime-param.stderr3
-rw-r--r--tests/ui/span/issue28498-reject-passed-to-fn.stderr3
-rw-r--r--tests/ui/span/issue28498-reject-trait-bound.stderr3
-rw-r--r--tests/ui/span/missing-unit-argument.stderr4
-rw-r--r--tests/ui/span/mut-ptr-cant-outlive-ref.stderr2
-rw-r--r--tests/ui/span/range-2.stderr8
-rw-r--r--tests/ui/span/regionck-unboxed-closure-lifetimes.stderr2
-rw-r--r--tests/ui/span/regions-close-over-type-parameter-2.stderr2
-rw-r--r--tests/ui/span/regions-escape-loop-via-variable.stderr4
-rw-r--r--tests/ui/span/regions-escape-loop-via-vec.stderr13
-rw-r--r--tests/ui/span/regions-infer-borrow-scope-within-loop.stderr3
-rw-r--r--tests/ui/span/send-is-not-static-ensures-scoping.stderr1
-rw-r--r--tests/ui/span/send-is-not-static-std-sync-2.stderr6
-rw-r--r--tests/ui/span/send-is-not-static-std-sync.stderr15
-rw-r--r--tests/ui/span/type-annotations-needed-expr.stderr2
-rw-r--r--tests/ui/span/vec-must-not-hide-type-from-dropck.stderr6
-rw-r--r--tests/ui/span/vec_refs_data_with_early_death.stderr6
-rw-r--r--tests/ui/span/wf-method-late-bound-regions.stderr1
-rw-r--r--tests/ui/specialization/defaultimpl/specialization-no-default.stderr10
-rw-r--r--tests/ui/specialization/issue-50452-fail.stderr2
-rw-r--r--tests/ui/specialization/non-defaulted-item-fail.stderr12
-rw-r--r--tests/ui/specialization/specialization-default-types.stderr4
-rw-r--r--tests/ui/specialization/specialization-no-default.stderr10
-rw-r--r--tests/ui/stability-attribute/unresolved_stability_lint.rs8
-rw-r--r--tests/ui/stability-attribute/unresolved_stability_lint.stderr9
-rw-r--r--tests/ui/static/bad-const-type.rs2
-rw-r--r--tests/ui/static/bad-const-type.stderr2
-rw-r--r--tests/ui/static/issue-5216.stderr4
-rw-r--r--tests/ui/static/static-lifetime-bound.rs2
-rw-r--r--tests/ui/static/static-lifetime-bound.stderr12
-rw-r--r--tests/ui/static/static-reference-to-fn-1.stderr8
-rw-r--r--tests/ui/statics/uninhabited-static.stderr10
-rw-r--r--tests/ui/stats/hir-stats.rs6
-rw-r--r--tests/ui/stats/hir-stats.stderr208
-rw-r--r--tests/ui/stdlib-unit-tests/not-sync.stderr2
-rw-r--r--tests/ui/str/str-lit-type-mismatch.stderr6
-rw-r--r--tests/ui/structs-enums/rec-align-u64.rs4
-rw-r--r--tests/ui/structs-enums/struct-enum-ignoring-field-with-underscore.rs3
-rw-r--r--tests/ui/structs-enums/struct-enum-ignoring-field-with-underscore.stderr23
-rw-r--r--tests/ui/structs/struct-base-wrong-type.stderr8
-rw-r--r--tests/ui/structs/struct-path-associated-type.rs4
-rw-r--r--tests/ui/structs/struct-path-associated-type.stderr4
-rw-r--r--tests/ui/structs/struct-path-self-type-mismatch.stderr2
-rw-r--r--tests/ui/structs/struct-record-suggestion.stderr2
-rw-r--r--tests/ui/structs/structure-constructor-type-mismatch.rs4
-rw-r--r--tests/ui/structs/structure-constructor-type-mismatch.stderr10
-rw-r--r--tests/ui/suggest-null-ptr.fixed31
-rw-r--r--tests/ui/suggest-null-ptr.rs31
-rw-r--r--tests/ui/suggest-null-ptr.stderr83
-rw-r--r--tests/ui/suggestions/args-instead-of-tuple-errors.stderr22
-rw-r--r--tests/ui/suggestions/args-instead-of-tuple.stderr4
-rw-r--r--tests/ui/suggestions/as-ref.stderr22
-rw-r--r--tests/ui/suggestions/assoc-const-without-self.rs11
-rw-r--r--tests/ui/suggestions/assoc-const-without-self.stderr14
-rw-r--r--tests/ui/suggestions/assoc-ct-for-assoc-method.stderr2
-rw-r--r--tests/ui/suggestions/borrow-for-loop-head.stderr2
-rw-r--r--tests/ui/suggestions/boxed-variant-field.stderr2
-rw-r--r--tests/ui/suggestions/call-boxed.stderr2
-rw-r--r--tests/ui/suggestions/chain-method-call-mutation-in-place.stderr2
-rw-r--r--tests/ui/suggestions/clone-on-unconstrained-borrowed-type-param.stderr2
-rw-r--r--tests/ui/suggestions/const-in-struct-pat.stderr2
-rw-r--r--tests/ui/suggestions/constrain-suggest-ice.rs10
-rw-r--r--tests/ui/suggestions/constrain-suggest-ice.stderr61
-rw-r--r--tests/ui/suggestions/copied-and-cloned.stderr8
-rw-r--r--tests/ui/suggestions/dont-suggest-deref-inside-macro-issue-58298.stderr2
-rw-r--r--tests/ui/suggestions/dont-suggest-doc-hidden-variant-for-enum/hidden-child.stderr2
-rw-r--r--tests/ui/suggestions/dont-suggest-doc-hidden-variant-for-enum/hidden-parent.stderr2
-rw-r--r--tests/ui/suggestions/expected-boxed-future-isnt-pinned.stderr8
-rw-r--r--tests/ui/suggestions/field-access.stderr8
-rw-r--r--tests/ui/suggestions/fn-or-tuple-struct-without-args.stderr14
-rw-r--r--tests/ui/suggestions/format-borrow.stderr8
-rw-r--r--tests/ui/suggestions/if-then-neeing-semi.rs26
-rw-r--r--tests/ui/suggestions/if-then-neeing-semi.stderr46
-rw-r--r--tests/ui/suggestions/imm-ref-trait-object-literal-bound-regions.stderr2
-rw-r--r--tests/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.stderr8
-rw-r--r--tests/ui/suggestions/into-convert.stderr6
-rw-r--r--tests/ui/suggestions/issue-101065.stderr2
-rw-r--r--tests/ui/suggestions/issue-101421.rs2
-rw-r--r--tests/ui/suggestions/issue-101421.stderr4
-rw-r--r--tests/ui/suggestions/issue-101465.stderr2
-rw-r--r--tests/ui/suggestions/issue-101984.stderr2
-rw-r--r--tests/ui/suggestions/issue-102892.stderr6
-rw-r--r--tests/ui/suggestions/issue-104287.rs2
-rw-r--r--tests/ui/suggestions/issue-104287.stderr4
-rw-r--r--tests/ui/suggestions/issue-104961.fixed16
-rw-r--r--tests/ui/suggestions/issue-104961.rs16
-rw-r--r--tests/ui/suggestions/issue-104961.stderr37
-rw-r--r--tests/ui/suggestions/issue-105494.stderr8
-rw-r--r--tests/ui/suggestions/issue-106443-sugg-clone-for-arg.stderr4
-rw-r--r--tests/ui/suggestions/issue-52820.stderr4
-rw-r--r--tests/ui/suggestions/issue-53692.stderr4
-rw-r--r--tests/ui/suggestions/issue-59819.stderr4
-rw-r--r--tests/ui/suggestions/issue-81839.stderr10
-rw-r--r--tests/ui/suggestions/issue-83943.stderr2
-rw-r--r--tests/ui/suggestions/issue-84973.stderr2
-rw-r--r--tests/ui/suggestions/issue-85347.rs2
-rw-r--r--tests/ui/suggestions/issue-85347.stderr2
-rw-r--r--tests/ui/suggestions/issue-86100-tuple-paren-comma.stderr6
-rw-r--r--tests/ui/suggestions/issue-89064.stderr8
-rw-r--r--tests/ui/suggestions/issue-90213-expected-boxfuture-self-ice.stderr2
-rw-r--r--tests/ui/suggestions/late-bound-in-borrow-closure-sugg.rs28
-rw-r--r--tests/ui/suggestions/late-bound-in-borrow-closure-sugg.stderr26
-rw-r--r--tests/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr4
-rw-r--r--tests/ui/suggestions/match-ergonomics.stderr6
-rw-r--r--tests/ui/suggestions/match-prev-arm-needing-semi.rs26
-rw-r--r--tests/ui/suggestions/match-prev-arm-needing-semi.stderr46
-rw-r--r--tests/ui/suggestions/match-with-different-arm-types-as-stmt-instead-of-expr.stderr4
-rw-r--r--tests/ui/suggestions/method-access-to-range-literal-typo.stderr4
-rw-r--r--tests/ui/suggestions/missing-lifetime-specifier.rs20
-rw-r--r--tests/ui/suggestions/missing-lifetime-specifier.stderr20
-rw-r--r--tests/ui/suggestions/missing-type-param-used-in-param.stderr2
-rw-r--r--tests/ui/suggestions/move-generic-to-trait-in-method-with-params.rs2
-rw-r--r--tests/ui/suggestions/move-generic-to-trait-in-method-with-params.stderr4
-rw-r--r--tests/ui/suggestions/mut-ref-reassignment.stderr8
-rw-r--r--tests/ui/suggestions/opaque-type-error.stderr8
-rw-r--r--tests/ui/suggestions/option-content-move2.stderr2
-rw-r--r--tests/ui/suggestions/option-to-bool.stderr2
-rw-r--r--tests/ui/suggestions/recover-from-semicolon-trailing-item.stderr4
-rw-r--r--tests/ui/suggestions/recover-invalid-float-invalid.rs24
-rw-r--r--tests/ui/suggestions/recover-invalid-float-invalid.stderr26
-rw-r--r--tests/ui/suggestions/ref-pattern-binding.stderr8
-rw-r--r--tests/ui/suggestions/restrict-existing-type-bounds.rs30
-rw-r--r--tests/ui/suggestions/restrict-existing-type-bounds.stderr57
-rw-r--r--tests/ui/suggestions/return-bindings.stderr12
-rw-r--r--tests/ui/suggestions/shadowed-lplace-method-2.stderr2
-rw-r--r--tests/ui/suggestions/shadowed-lplace-method.stderr2
-rw-r--r--tests/ui/suggestions/sugg-else-for-closure.stderr2
-rw-r--r--tests/ui/suggestions/suggest-box.stderr2
-rw-r--r--tests/ui/suggestions/suggest-call-on-pat-mismatch.rs16
-rw-r--r--tests/ui/suggestions/suggest-call-on-pat-mismatch.stderr33
-rw-r--r--tests/ui/suggestions/suggest-fn-ptr-for-fn-item-in-fn-ret.fixed12
-rw-r--r--tests/ui/suggestions/suggest-fn-ptr-for-fn-item-in-fn-ret.rs12
-rw-r--r--tests/ui/suggestions/suggest-fn-ptr-for-fn-item-in-fn-ret.stderr12
-rw-r--r--tests/ui/suggestions/suggest-full-enum-variant-for-local-module.stderr2
-rw-r--r--tests/ui/suggestions/suggest-remove-deref.fixed28
-rw-r--r--tests/ui/suggestions/suggest-remove-deref.rs28
-rw-r--r--tests/ui/suggestions/suggest-remove-deref.stderr43
-rw-r--r--tests/ui/suggestions/suggest-trait-in-ufcs-in-hrtb.rs8
-rw-r--r--tests/ui/suggestions/suggest-trait-in-ufcs-in-hrtb.stderr9
-rw-r--r--tests/ui/suggestions/suggest-using-chars.stderr4
-rw-r--r--tests/ui/suggestions/trait-hidden-method.rs11
-rw-r--r--tests/ui/suggestions/trait-hidden-method.stderr24
-rw-r--r--tests/ui/suggestions/trait-with-missing-associated-type-restriction.stderr2
-rw-r--r--tests/ui/suggestions/type-ascription-instead-of-path-in-type.stderr2
-rw-r--r--tests/ui/suggestions/type-mismatch-byte-literal.rs12
-rw-r--r--tests/ui/suggestions/type-mismatch-byte-literal.stderr45
-rw-r--r--tests/ui/suggestions/unnecessary_dot_for_floating_point_literal.stderr8
-rw-r--r--tests/ui/suggestions/use-type-argument-instead-of-assoc-type.rs2
-rw-r--r--tests/ui/suggestions/use-type-argument-instead-of-assoc-type.stderr2
-rw-r--r--tests/ui/suppressed-error.rs2
-rw-r--r--tests/ui/suppressed-error.stderr2
-rw-r--r--tests/ui/switched-expectations.stderr2
-rw-r--r--tests/ui/symbol-names/basic.legacy.stderr4
-rw-r--r--tests/ui/symbol-names/issue-60925.legacy.stderr4
-rw-r--r--tests/ui/sync/mutexguard-sync.rs (renamed from tests/ui/mutexguard-sync.rs)0
-rw-r--r--tests/ui/sync/mutexguard-sync.stderr (renamed from tests/ui/mutexguard-sync.stderr)1
-rw-r--r--tests/ui/sync/suggest-cell.rs31
-rw-r--r--tests/ui/sync/suggest-cell.stderr59
-rw-r--r--tests/ui/sync/suggest-once-cell.rs12
-rw-r--r--tests/ui/sync/suggest-once-cell.stderr17
-rw-r--r--tests/ui/sync/suggest-ref-cell.rs12
-rw-r--r--tests/ui/sync/suggest-ref-cell.stderr17
-rw-r--r--tests/ui/tag-that-dare-not-speak-its-name.rs2
-rw-r--r--tests/ui/tag-that-dare-not-speak-its-name.stderr2
-rw-r--r--tests/ui/terr-in-field.rs2
-rw-r--r--tests/ui/terr-in-field.stderr2
-rw-r--r--tests/ui/terr-sorts.stderr2
-rw-r--r--tests/ui/thir-print/thir-flat.rs4
-rw-r--r--tests/ui/thir-print/thir-flat.stdout (renamed from tests/ui/thir-tree.stdout)31
-rw-r--r--tests/ui/thir-print/thir-tree-match.rs23
-rw-r--r--tests/ui/thir-print/thir-tree-match.stdout342
-rw-r--r--tests/ui/thir-print/thir-tree.rs (renamed from tests/ui/thir-tree.rs)0
-rw-r--r--tests/ui/thir-print/thir-tree.stdout43
-rw-r--r--tests/ui/thread-local/tls.rs1
-rw-r--r--tests/ui/tool-attributes/auxiliary/p1.rs3
-rw-r--r--tests/ui/tool-attributes/auxiliary/p2.rs3
-rw-r--r--tests/ui/tool-attributes/duplicate-diagnostic.rs13
-rw-r--r--tests/ui/tool-attributes/duplicate-diagnostic.stderr14
-rw-r--r--tests/ui/track-diagnostics/track4.stderr2
-rw-r--r--tests/ui/traits/alias/ambiguous.stderr4
-rw-r--r--tests/ui/traits/alias/issue-107747-do-not-assemble-supertraits.rs21
-rw-r--r--tests/ui/traits/alias/issue-108072-unmet-trait-alias-bound.rs11
-rw-r--r--tests/ui/traits/alias/issue-108072-unmet-trait-alias-bound.stderr19
-rw-r--r--tests/ui/traits/alias/issue-108132-unmet-trait-alias-bound-on-generic-impl.rs15
-rw-r--r--tests/ui/traits/alias/issue-108132-unmet-trait-alias-bound-on-generic-impl.stderr25
-rw-r--r--tests/ui/traits/alias/issue-60755.rs12
-rw-r--r--tests/ui/traits/alias/self-in-generics.rs4
-rw-r--r--tests/ui/traits/alias/self-in-generics.stderr2
-rw-r--r--tests/ui/traits/associated_type_bound/check-trait-object-bounds-3.stderr2
-rw-r--r--tests/ui/traits/coercion-generic-regions.stderr2
-rw-r--r--tests/ui/traits/inductive-overflow/supertrait-auto-trait.stderr2
-rw-r--r--tests/ui/traits/issue-103563.rs75
-rw-r--r--tests/ui/traits/issue-52893.stderr4
-rw-r--r--tests/ui/traits/issue-68295.stderr2
-rw-r--r--tests/ui/traits/issue-77982.stderr6
-rw-r--r--tests/ui/traits/item-privacy.rs4
-rw-r--r--tests/ui/traits/item-privacy.stderr12
-rw-r--r--tests/ui/traits/method-private.stderr6
-rw-r--r--tests/ui/traits/multidispatch-convert-ambig-dest.stderr2
-rw-r--r--tests/ui/traits/negative-impls/negated-auto-traits-error.stderr4
-rw-r--r--tests/ui/traits/negative-impls/no-items.stderr2
-rw-r--r--tests/ui/traits/new-solver/alias_eq_cant_be_furthur_normalized.rs29
-rw-r--r--tests/ui/traits/new-solver/alias_eq_dont_use_normalizes_to_if_substs_eq.rs45
-rw-r--r--tests/ui/traits/new-solver/alias_eq_dont_use_normalizes_to_if_substs_eq.stderr9
-rw-r--r--tests/ui/traits/new-solver/alias_eq_simple.rs22
-rw-r--r--tests/ui/traits/new-solver/alias_eq_substs_eq_not_intercrate.rs20
-rw-r--r--tests/ui/traits/new-solver/alias_eq_substs_eq_not_intercrate.stderr9
-rw-r--r--tests/ui/traits/new-solver/async.fail.stderr17
-rw-r--r--tests/ui/traits/new-solver/async.rs19
-rw-r--r--tests/ui/traits/new-solver/builtin-fn-must-return-sized.rs17
-rw-r--r--tests/ui/traits/new-solver/builtin-fn-must-return-sized.stderr18
-rw-r--r--tests/ui/traits/new-solver/elaborate-item-bounds.rs12
-rw-r--r--tests/ui/traits/new-solver/fn-trait-closure.rs9
-rw-r--r--tests/ui/traits/new-solver/generator.fail.stderr64
-rw-r--r--tests/ui/traits/new-solver/generator.rs32
-rw-r--r--tests/ui/traits/new-solver/higher-ranked-dyn-bounds.rs17
-rw-r--r--tests/ui/traits/new-solver/more-object-bound.rs27
-rw-r--r--tests/ui/traits/new-solver/more-object-bound.stderr19
-rw-r--r--tests/ui/traits/new-solver/normalizes_to_ignores_unnormalizable_candidate.rs40
-rw-r--r--tests/ui/traits/new-solver/normalizes_to_ignores_unnormalizable_candidate.self_infer.stderr14
-rw-r--r--tests/ui/traits/new-solver/object-unsafety.rs20
-rw-r--r--tests/ui/traits/new-solver/object-unsafety.stderr19
-rw-r--r--tests/ui/traits/new-solver/param-candidate-doesnt-shadow-project.rs25
-rw-r--r--tests/ui/traits/new-solver/pointee.rs23
-rw-r--r--tests/ui/traits/new-solver/pointer-like.rs14
-rw-r--r--tests/ui/traits/new-solver/pointer-like.stderr24
-rw-r--r--tests/ui/traits/new-solver/pointer-sized.rs12
-rw-r--r--tests/ui/traits/new-solver/pointer-sized.stderr24
-rw-r--r--tests/ui/traits/new-solver/provisional-result-done.rs33
-rw-r--r--tests/ui/traits/new-solver/temporary-ambiguity.rs22
-rw-r--r--tests/ui/traits/new-solver/try-example.rs28
-rw-r--r--tests/ui/traits/new-solver/two-projection-param-candidates-are-ambiguous.rs30
-rw-r--r--tests/ui/traits/new-solver/two-projection-param-candidates-are-ambiguous.stderr16
-rw-r--r--tests/ui/traits/new-solver/unsafe-auto-trait-impl.rs8
-rw-r--r--tests/ui/traits/new-solver/unsize-good.rs25
-rw-r--r--tests/ui/traits/new-solver/upcast-right-substs.rs14
-rw-r--r--tests/ui/traits/new-solver/upcast-wrong-substs.rs13
-rw-r--r--tests/ui/traits/new-solver/upcast-wrong-substs.stderr14
-rw-r--r--tests/ui/traits/non_lifetime_binders/bad-sized-cond.rs23
-rw-r--r--tests/ui/traits/non_lifetime_binders/bad-sized-cond.stderr62
-rw-r--r--tests/ui/traits/non_lifetime_binders/basic.rs19
-rw-r--r--tests/ui/traits/non_lifetime_binders/basic.stderr11
-rw-r--r--tests/ui/traits/non_lifetime_binders/fail.rs23
-rw-r--r--tests/ui/traits/non_lifetime_binders/fail.stderr43
-rw-r--r--tests/ui/traits/non_lifetime_binders/late-bound-in-anon-ct.rs11
-rw-r--r--tests/ui/traits/non_lifetime_binders/late-bound-in-anon-ct.stderr27
-rw-r--r--tests/ui/traits/non_lifetime_binders/object-lifetime-default-for-late.rs7
-rw-r--r--tests/ui/traits/non_lifetime_binders/object-lifetime-default-for-late.stderr11
-rw-r--r--tests/ui/traits/non_lifetime_binders/on-dyn.rs13
-rw-r--r--tests/ui/traits/non_lifetime_binders/on-dyn.stderr17
-rw-r--r--tests/ui/traits/non_lifetime_binders/on-ptr.rs13
-rw-r--r--tests/ui/traits/non_lifetime_binders/on-ptr.stderr17
-rw-r--r--tests/ui/traits/non_lifetime_binders/type-match-with-late-bound.rs14
-rw-r--r--tests/ui/traits/non_lifetime_binders/type-match-with-late-bound.stderr11
-rw-r--r--tests/ui/traits/object/enforce-supertrait-projection.stderr2
-rw-r--r--tests/ui/traits/object/vs-lifetime.rs4
-rw-r--r--tests/ui/traits/object/vs-lifetime.stderr4
-rw-r--r--tests/ui/traits/suggest-deferences/issue-39029.stderr4
-rw-r--r--tests/ui/traits/test-2.rs4
-rw-r--r--tests/ui/traits/test-2.stderr8
-rw-r--r--tests/ui/traits/trait-or-new-type-instead.stderr7
-rw-r--r--tests/ui/traits/trait-upcasting/multiple_supertrait_upcastable.rs10
-rw-r--r--tests/ui/traits/trait-upcasting/multiple_supertrait_upcastable.stderr14
-rw-r--r--tests/ui/traits/unsend-future.rs21
-rw-r--r--tests/ui/traits/unsend-future.stderr24
-rw-r--r--tests/ui/traits/vtable/issue-97381.stderr3
-rw-r--r--tests/ui/transmutability/arrays/should_require_well_defined_layout.stderr12
-rw-r--r--tests/ui/transmutability/enums/repr/primitive_reprs_should_have_correct_length.stderr40
-rw-r--r--tests/ui/transmutability/enums/repr/should_require_well_defined_layout.stderr12
-rw-r--r--tests/ui/transmutability/enums/should_pad_variants.stderr2
-rw-r--r--tests/ui/transmutability/enums/should_respect_endianness.stderr2
-rw-r--r--tests/ui/transmutability/issue-101739-1.stderr2
-rw-r--r--tests/ui/transmutability/issue-101739-2.rs2
-rw-r--r--tests/ui/transmutability/issue-101739-2.stderr2
-rw-r--r--tests/ui/transmutability/primitives/bool.stderr2
-rw-r--r--tests/ui/transmutability/primitives/numbers.stderr114
-rw-r--r--tests/ui/transmutability/primitives/unit.stderr2
-rw-r--r--tests/ui/transmutability/references.stderr2
-rw-r--r--tests/ui/transmutability/structs/repr/should_require_well_defined_layout.stderr24
-rw-r--r--tests/ui/transmutability/unions/repr/should_require_well_defined_layout.stderr4
-rw-r--r--tests/ui/transmutability/unions/should_pad_variants.stderr2
-rw-r--r--tests/ui/transmutability/unions/should_reject_contraction.stderr2
-rw-r--r--tests/ui/transmutability/unions/should_reject_disjoint.stderr4
-rw-r--r--tests/ui/transmutability/unions/should_reject_intersecting.stderr4
-rw-r--r--tests/ui/transmutability/visibility/should_reject_if_dst_has_private_field.stderr2
-rw-r--r--tests/ui/transmutability/visibility/should_reject_if_dst_has_private_variant.stderr2
-rw-r--r--tests/ui/transmutability/visibility/should_reject_if_dst_has_unreachable_field.stderr2
-rw-r--r--tests/ui/transmutability/visibility/should_reject_if_dst_has_unreachable_ty.stderr2
-rw-r--r--tests/ui/transmute/transmute-padding-ice.stderr2
-rw-r--r--tests/ui/treat-err-as-bug/delay_span_bug.stderr2
-rw-r--r--tests/ui/treat-err-as-bug/err.stderr2
-rw-r--r--tests/ui/try-block/try-block-bad-lifetime.stderr9
-rw-r--r--tests/ui/try-block/try-block-maybe-bad-lifetime.stderr8
-rw-r--r--tests/ui/tuple/add-tuple-within-arguments.stderr2
-rw-r--r--tests/ui/tuple/wrong_argument_ice-3.stderr11
-rw-r--r--tests/ui/tuple/wrong_argument_ice-4.stderr9
-rw-r--r--tests/ui/tuple/wrong_argument_ice.stderr2
-rw-r--r--tests/ui/type-alias-enum-variants/enum-variant-generic-args.rs12
-rw-r--r--tests/ui/type-alias-enum-variants/enum-variant-generic-args.stderr12
-rw-r--r--tests/ui/type-alias-enum-variants/enum-variant-priority-higher-than-other-inherent.stderr2
-rw-r--r--tests/ui/type-alias-impl-trait/bounds-are-checked.rs3
-rw-r--r--tests/ui/type-alias-impl-trait/bounds-are-checked.stderr15
-rw-r--r--tests/ui/type-alias-impl-trait/generic_nondefining_use.rs2
-rw-r--r--tests/ui/type-alias-impl-trait/generic_nondefining_use.stderr2
-rw-r--r--tests/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.rs2
-rw-r--r--tests/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.stderr2
-rw-r--r--tests/ui/type-alias-impl-trait/implied_lifetime_wf_check3.rs3
-rw-r--r--tests/ui/type-alias-impl-trait/implied_lifetime_wf_check3.stderr34
-rw-r--r--tests/ui/type-alias-impl-trait/imply_bounds_from_bounds_param.stderr4
-rw-r--r--tests/ui/type-alias-impl-trait/issue-63279.rs2
-rw-r--r--tests/ui/type-alias-impl-trait/issue-63279.stderr12
-rw-r--r--tests/ui/type-alias-impl-trait/issue-65679-inst-opaque-ty-from-val-twice.rs1
-rw-r--r--tests/ui/type-alias-impl-trait/issue-98604.rs2
-rw-r--r--tests/ui/type-alias-impl-trait/issue-98604.stderr11
-rw-r--r--tests/ui/type-alias-impl-trait/issue-98608.rs2
-rw-r--r--tests/ui/type-alias-impl-trait/issue-98608.stderr4
-rw-r--r--tests/ui/type-alias-impl-trait/match-unification.rs14
-rw-r--r--tests/ui/type-alias-impl-trait/missing_lifetime_bound.stderr2
-rw-r--r--tests/ui/type-alias-impl-trait/type-alias-impl-trait-fn-type.stderr2
-rw-r--r--tests/ui/type-alias-impl-trait/unnameable_type.stderr2
-rw-r--r--tests/ui/type-inference/issue-30225.stderr2
-rw-r--r--tests/ui/type-inference/sort_by_key.stderr2
-rw-r--r--tests/ui/type/issue-91268.rs4
-rw-r--r--tests/ui/type/issue-91268.stderr55
-rw-r--r--tests/ui/type/type-ascription-instead-of-initializer.stderr9
-rw-r--r--tests/ui/type/type-ascription-precedence.stderr12
-rw-r--r--tests/ui/type/type-ascription-soundness.stderr8
-rw-r--r--tests/ui/type/type-check/assignment-in-if.stderr9
-rw-r--r--tests/ui/type/type-check/cannot_infer_local_or_vec.stderr6
-rw-r--r--tests/ui/type/type-check/cannot_infer_local_or_vec_in_tuples.stderr6
-rw-r--r--tests/ui/type/type-check/coerce-result-return-value-2.rs24
-rw-r--r--tests/ui/type/type-check/coerce-result-return-value-2.stderr47
-rw-r--r--tests/ui/type/type-check/coerce-result-return-value.fixed24
-rw-r--r--tests/ui/type/type-check/coerce-result-return-value.rs24
-rw-r--r--tests/ui/type/type-check/coerce-result-return-value.stderr65
-rw-r--r--tests/ui/type/type-check/point-at-inference-2.stderr11
-rw-r--r--tests/ui/type/type-check/point-at-inference-3.fixed3
-rw-r--r--tests/ui/type/type-check/point-at-inference-3.rs3
-rw-r--r--tests/ui/type/type-check/point-at-inference-3.stderr7
-rw-r--r--tests/ui/type/type-check/point-at-inference-4.rs21
-rw-r--r--tests/ui/type/type-check/point-at-inference-4.stderr31
-rw-r--r--tests/ui/type/type-check/point-at-inference.fixed13
-rw-r--r--tests/ui/type/type-check/point-at-inference.rs1
-rw-r--r--tests/ui/type/type-check/point-at-inference.stderr13
-rw-r--r--tests/ui/type/type-mismatch-same-crate-name.rs2
-rw-r--r--tests/ui/type/type-mismatch-same-crate-name.stderr8
-rw-r--r--tests/ui/type/type-mismatch.stderr94
-rw-r--r--tests/ui/type/wrong-call-return-type-due-to-generic-arg.stderr2
-rw-r--r--tests/ui/typeck/assign-non-lval-derefmut.stderr2
-rw-r--r--tests/ui/typeck/bad-type-in-vec-contains.rs7
-rw-r--r--tests/ui/typeck/bad-type-in-vec-contains.stderr19
-rw-r--r--tests/ui/typeck/bad-type-in-vec-push.rs20
-rw-r--r--tests/ui/typeck/bad-type-in-vec-push.stderr29
-rw-r--r--tests/ui/typeck/conversion-methods.stderr8
-rw-r--r--tests/ui/typeck/deref-multi.stderr2
-rw-r--r--tests/ui/typeck/explain_clone_autoref.rs2
-rw-r--r--tests/ui/typeck/explain_clone_autoref.stderr2
-rw-r--r--tests/ui/typeck/issue-100246.stderr2
-rw-r--r--tests/ui/typeck/issue-104513-ice.stderr2
-rw-r--r--tests/ui/typeck/issue-107087.rs18
-rw-r--r--tests/ui/typeck/issue-107087.stderr9
-rw-r--r--tests/ui/typeck/issue-107775.rs40
-rw-r--r--tests/ui/typeck/issue-107775.stderr16
-rw-r--r--tests/ui/typeck/issue-13853.stderr4
-rw-r--r--tests/ui/typeck/issue-31173.stderr15
-rw-r--r--tests/ui/typeck/issue-46112.stderr2
-rw-r--r--tests/ui/typeck/issue-50687-ice-on-borrow.stderr2
-rw-r--r--tests/ui/typeck/issue-53712.rs (renamed from tests/ui/issues/issue-53712.rs)0
-rw-r--r--tests/ui/typeck/issue-53712.stderr (renamed from tests/ui/issues/issue-53712.stderr)0
-rw-r--r--tests/ui/typeck/issue-57673-ice-on-deref-of-boxed-trait.stderr2
-rw-r--r--tests/ui/typeck/issue-67971.stderr2
-rw-r--r--tests/ui/typeck/issue-75883.rs4
-rw-r--r--tests/ui/typeck/issue-75883.stderr4
-rw-r--r--tests/ui/typeck/issue-7813.rs (renamed from tests/ui/issues/issue-7813.rs)0
-rw-r--r--tests/ui/typeck/issue-7813.stderr (renamed from tests/ui/issues/issue-7813.stderr)0
-rw-r--r--tests/ui/typeck/issue-84160.stderr2
-rw-r--r--tests/ui/typeck/issue-84768.stderr4
-rw-r--r--tests/ui/typeck/issue-89856.fixed18
-rw-r--r--tests/ui/typeck/issue-89856.rs14
-rw-r--r--tests/ui/typeck/issue-89856.stderr54
-rw-r--r--tests/ui/typeck/issue-90027-async-fn-return-suggestion.rs21
-rw-r--r--tests/ui/typeck/issue-90027-async-fn-return-suggestion.stderr39
-rw-r--r--tests/ui/typeck/issue-91334.rs3
-rw-r--r--tests/ui/typeck/issue-91334.stderr47
-rw-r--r--tests/ui/typeck/issue-91450-inner-ty-error.stderr2
-rw-r--r--tests/ui/typeck/issue-92481.rs9
-rw-r--r--tests/ui/typeck/issue-92481.stderr61
-rw-r--r--tests/ui/typeck/issue-96530.stderr2
-rw-r--r--tests/ui/typeck/lazy-norm/cast-checks-handling-projections.rs6
-rw-r--r--tests/ui/typeck/lazy-norm/cast-checks-handling-projections.stderr9
-rw-r--r--tests/ui/typeck/lazy-norm/equating-projection-cyclically.rs24
-rw-r--r--tests/ui/typeck/lazy-norm/equating-projection-cyclically.stderr14
-rw-r--r--tests/ui/typeck/remove-extra-argument.stderr9
-rw-r--r--tests/ui/typeck/return_type_containing_closure.rs2
-rw-r--r--tests/ui/typeck/return_type_containing_closure.stderr2
-rw-r--r--tests/ui/typeck/struct-enum-wrong-args.stderr36
-rw-r--r--tests/ui/typeck/typeck-builtin-bound-type-parameters.rs12
-rw-r--r--tests/ui/typeck/typeck-builtin-bound-type-parameters.stderr12
-rw-r--r--tests/ui/typeck/typeck_type_placeholder_item.rs4
-rw-r--r--tests/ui/typeck/typeck_type_placeholder_item.stderr34
-rw-r--r--tests/ui/typeck/typeck_type_placeholder_lifetime_1.rs2
-rw-r--r--tests/ui/typeck/typeck_type_placeholder_lifetime_1.stderr2
-rw-r--r--tests/ui/typeck/typeck_type_placeholder_lifetime_2.rs2
-rw-r--r--tests/ui/typeck/typeck_type_placeholder_lifetime_2.stderr2
-rw-r--r--tests/ui/typeck/typeck_type_placeholder_mismatch.rs4
-rw-r--r--tests/ui/typeck/typeck_type_placeholder_mismatch.stderr4
-rw-r--r--tests/ui/ufcs/ufcs-qpath-missing-params.rs2
-rw-r--r--tests/ui/ufcs/ufcs-qpath-missing-params.stderr4
-rw-r--r--tests/ui/ufcs/ufcs-qpath-self-mismatch.stderr4
-rw-r--r--tests/ui/unboxed-closures/unboxed-closure-sugar-region.rs2
-rw-r--r--tests/ui/unboxed-closures/unboxed-closure-sugar-region.stderr2
-rw-r--r--tests/ui/unboxed-closures/unboxed-closure-sugar-used-on-struct-1.rs2
-rw-r--r--tests/ui/unboxed-closures/unboxed-closure-sugar-used-on-struct-1.stderr2
-rw-r--r--tests/ui/unboxed-closures/unboxed-closure-sugar-used-on-struct.rs2
-rw-r--r--tests/ui/unboxed-closures/unboxed-closure-sugar-used-on-struct.stderr2
-rw-r--r--tests/ui/unboxed-closures/unboxed-closure-sugar-wrong-number-number-type-parameters-3.rs2
-rw-r--r--tests/ui/unboxed-closures/unboxed-closure-sugar-wrong-number-number-type-parameters-3.stderr2
-rw-r--r--tests/ui/unboxed-closures/unboxed-closure-sugar-wrong-number-number-type-parameters.rs10
-rw-r--r--tests/ui/unboxed-closures/unboxed-closure-sugar-wrong-number-number-type-parameters.stderr10
-rw-r--r--tests/ui/unboxed-closures/unboxed-closure-sugar-wrong-trait.rs2
-rw-r--r--tests/ui/unboxed-closures/unboxed-closure-sugar-wrong-trait.stderr2
-rw-r--r--tests/ui/unboxed-closures/unboxed-closures-borrow-conflict.stderr2
-rw-r--r--tests/ui/unboxed-closures/unboxed-closures-failed-recursive-fn-1.stderr8
-rw-r--r--tests/ui/unboxed-closures/unboxed-closures-infer-fn-once-move-from-projection.stderr2
-rw-r--r--tests/ui/unboxed-closures/unboxed-closures-static-call-wrong-trait.stderr2
-rw-r--r--tests/ui/uninhabited/issue-107505.rs18
-rw-r--r--tests/ui/union/projection-as-union-type-error-2.rs20
-rw-r--r--tests/ui/union/projection-as-union-type-error-2.stderr17
-rw-r--r--tests/ui/union/projection-as-union-type-error.rs15
-rw-r--r--tests/ui/union/projection-as-union-type-error.stderr9
-rw-r--r--tests/ui/union/projection-as-union-type.rs19
-rw-r--r--tests/ui/unop-move-semantics.stderr5
-rw-r--r--tests/ui/unpretty/ast-const-trait-bound.rs4
-rw-r--r--tests/ui/unpretty/ast-const-trait-bound.stdout4
-rw-r--r--tests/ui/unsized-locals/suggest-borrow.stderr4
-rw-r--r--tests/ui/unsized/box-instead-of-dyn-fn.stderr2
-rw-r--r--tests/ui/unsized/issue-71659.stderr2
-rw-r--r--tests/ui/unsized/param-mentioned-by-different-field.stderr2
-rw-r--r--tests/ui/unsized/unsized3-rpass.rs4
-rw-r--r--tests/ui/variance/variance-associated-types.rs2
-rw-r--r--tests/ui/variance/variance-associated-types.stderr2
-rw-r--r--tests/ui/variance/variance-issue-20533.stderr6
-rw-r--r--tests/ui/variance/variance-regions-direct.rs12
-rw-r--r--tests/ui/variance/variance-regions-direct.stderr12
-rw-r--r--tests/ui/variance/variance-regions-indirect.rs8
-rw-r--r--tests/ui/variance/variance-regions-indirect.stderr8
-rw-r--r--tests/ui/variance/variance-trait-object-bound.rs2
-rw-r--r--tests/ui/variance/variance-trait-object-bound.stderr2
-rw-r--r--tests/ui/variance/variance-types.rs2
-rw-r--r--tests/ui/variance/variance-types.stderr2
-rw-r--r--tests/ui/wait-forked-but-failed-child.rs1
-rw-r--r--tests/ui/wf/wf-in-foreign-fn-decls-issue-80468.rs2
-rw-r--r--tests/ui/wf/wf-in-foreign-fn-decls-issue-80468.stderr25
-rw-r--r--tests/ui/wf/wf-unsafe-trait-obj-match.stderr2
-rw-r--r--tests/ui/where-clauses/higher-ranked-fn-type.quiet.stderr2
-rw-r--r--tests/ui/where-clauses/higher-ranked-fn-type.verbose.stderr2
-rw-r--r--tests/ui/where-clauses/self-in-where-clause-allowed.rs23
-rw-r--r--tests/ui/where-clauses/self-in-where-clause-allowed.stderr15
-rw-r--r--tests/ui/while/while-else-err.rs8
-rw-r--r--tests/ui/while/while-else-err.stderr17
-rw-r--r--tests/ui/while/while-else-let-else-err.rs8
-rw-r--r--tests/ui/while/while-else-let-else-err.stderr17
-rw-r--r--tests/ui/wrong-mul-method-signature.stderr6
-rw-r--r--tests/ui/xc-private-method2.rs4
-rw-r--r--tests/ui/xc-private-method2.stderr12
-rw-r--r--vendor/addr2line-0.17.0/.cargo-checksum.json1
-rw-r--r--vendor/addr2line-0.17.0/CHANGELOG.md260
-rw-r--r--vendor/addr2line-0.17.0/Cargo.lock430
-rw-r--r--vendor/addr2line-0.17.0/Cargo.toml120
-rw-r--r--vendor/addr2line-0.17.0/LICENSE-APACHE (renamed from vendor/parking_lot_core-0.8.5/LICENSE-APACHE)0
-rw-r--r--vendor/addr2line-0.17.0/LICENSE-MIT25
-rw-r--r--vendor/addr2line-0.17.0/README.md48
-rw-r--r--vendor/addr2line-0.17.0/bench.plot.r23
-rwxr-xr-xvendor/addr2line-0.17.0/benchmark.sh112
-rw-r--r--vendor/addr2line-0.17.0/coverage.sh5
-rw-r--r--vendor/addr2line-0.17.0/examples/addr2line.rs299
-rw-r--r--vendor/addr2line-0.17.0/rustfmt.toml1
-rw-r--r--vendor/addr2line-0.17.0/src/function.rs520
-rw-r--r--vendor/addr2line-0.17.0/src/lazy.rs29
-rw-r--r--vendor/addr2line-0.17.0/src/lib.rs1192
-rw-r--r--vendor/addr2line-0.17.0/tests/correctness.rs91
-rw-r--r--vendor/addr2line-0.17.0/tests/output_equivalence.rs145
-rw-r--r--vendor/addr2line-0.17.0/tests/parse.rs118
-rw-r--r--vendor/addr2line/.cargo-checksum.json2
-rw-r--r--vendor/addr2line/CHANGELOG.md27
-rw-r--r--vendor/addr2line/Cargo.lock180
-rw-r--r--vendor/addr2line/Cargo.toml72
-rw-r--r--vendor/addr2line/examples/addr2line.rs212
-rw-r--r--vendor/addr2line/src/function.rs30
-rw-r--r--vendor/addr2line/src/lazy.rs24
-rw-r--r--vendor/addr2line/src/lib.rs246
-rw-r--r--vendor/addr2line/tests/correctness.rs11
-rw-r--r--vendor/addr2line/tests/output_equivalence.rs1
-rw-r--r--vendor/addr2line/tests/parse.rs4
-rw-r--r--vendor/ansi_term/.cargo-checksum.json1
-rw-r--r--vendor/ansi_term/Cargo.lock168
-rw-r--r--vendor/ansi_term/Cargo.toml43
-rw-r--r--vendor/ansi_term/examples/basic_colours.rs18
-rw-r--r--vendor/ansi_term/examples/rgb_colours.rs23
-rw-r--r--vendor/ansi_term/src/style.rs521
-rw-r--r--vendor/anyhow/.cargo-checksum.json2
-rw-r--r--vendor/anyhow/Cargo.toml7
-rw-r--r--vendor/anyhow/README.md4
-rw-r--r--vendor/anyhow/src/context.rs19
-rw-r--r--vendor/anyhow/src/lib.rs2
-rw-r--r--vendor/anyhow/tests/test_ensure.rs1
-rw-r--r--vendor/anyhow/tests/ui/empty-ensure.stderr5
-rw-r--r--vendor/anyhow/tests/ui/no-impl.stderr2
-rw-r--r--vendor/anyhow/tests/ui/temporary-value.stderr2
-rw-r--r--vendor/backtrace/.cargo-checksum.json2
-rw-r--r--vendor/backtrace/Cargo.lock58
-rw-r--r--vendor/backtrace/Cargo.toml18
-rw-r--r--vendor/backtrace/src/backtrace/miri.rs6
-rw-r--r--vendor/backtrace/src/print.rs2
-rw-r--r--vendor/backtrace/src/symbolize/gimli.rs2
-rw-r--r--vendor/backtrace/src/symbolize/gimli/libs_dl_iterate_phdr.rs20
-rw-r--r--vendor/backtrace/src/symbolize/gimli/libs_macos.rs4
-rw-r--r--vendor/backtrace/src/symbolize/gimli/macho.rs4
-rw-r--r--vendor/backtrace/src/symbolize/gimli/parse_running_mmaps_unix.rs242
-rw-r--r--vendor/backtrace/src/windows.rs6
-rw-r--r--vendor/backtrace/tests/common/mod.rs14
-rw-r--r--vendor/backtrace/tests/concurrent-panics.rs14
-rw-r--r--vendor/backtrace/tests/current-exe-mismatch.rs137
-rw-r--r--vendor/backtrace/tests/skip_inner_frames.rs2
-rw-r--r--vendor/camino/.cargo-checksum.json2
-rw-r--r--vendor/camino/CHANGELOG.md8
-rw-r--r--vendor/camino/Cargo.toml2
-rw-r--r--vendor/camino/release.toml8
-rw-r--r--vendor/camino/src/lib.rs42
-rw-r--r--vendor/camino/src/proptest_impls.rs3
-rw-r--r--vendor/camino/tests/integration_tests.rs2
-rw-r--r--vendor/cargo_metadata/.cargo-checksum.json2
-rw-r--r--vendor/cargo_metadata/CHANGELOG.md38
-rw-r--r--vendor/cargo_metadata/Cargo.toml5
-rw-r--r--vendor/cargo_metadata/src/errors.rs82
-rw-r--r--vendor/cargo_metadata/src/lib.rs154
-rw-r--r--vendor/cargo_metadata/src/messages.rs3
-rw-r--r--vendor/cargo_metadata/tests/test_samples.rs27
-rw-r--r--vendor/cc/.cargo-checksum.json2
-rw-r--r--vendor/cc/Cargo.lock6
-rw-r--r--vendor/cc/Cargo.toml2
-rw-r--r--vendor/cc/src/lib.rs95
-rw-r--r--vendor/compiler_builtins/.cargo-checksum.json2
-rw-r--r--vendor/compiler_builtins/Cargo.lock2
-rw-r--r--vendor/compiler_builtins/Cargo.toml2
-rw-r--r--vendor/compiler_builtins/src/float/conv.rs20
-rw-r--r--vendor/compiler_builtins/src/int/shift.rs9
-rw-r--r--vendor/dissimilar/.cargo-checksum.json2
-rw-r--r--vendor/dissimilar/Cargo.toml10
-rw-r--r--vendor/dissimilar/LICENSE-APACHE25
-rw-r--r--vendor/dissimilar/README.md6
-rw-r--r--vendor/dissimilar/src/find.rs14
-rw-r--r--vendor/dissimilar/src/lib.rs169
-rw-r--r--vendor/dissimilar/src/range.rs49
-rw-r--r--vendor/dissimilar/src/tests.rs131
-rw-r--r--vendor/dissimilar/tests/test.rs16
-rw-r--r--vendor/elsa/.cargo-checksum.json1
-rw-r--r--vendor/elsa/Cargo.lock39
-rw-r--r--vendor/elsa/Cargo.toml47
-rw-r--r--vendor/elsa/LICENSE-APACHE (renamed from vendor/toml/LICENSE-APACHE)0
-rw-r--r--vendor/elsa/LICENSE-MIT27
-rw-r--r--vendor/elsa/README.md19
-rw-r--r--vendor/elsa/examples/arena.rs56
-rw-r--r--vendor/elsa/examples/fluentresource.rs50
-rw-r--r--vendor/elsa/examples/mutable_arena.rs79
-rw-r--r--vendor/elsa/examples/string_interner.rs61
-rw-r--r--vendor/elsa/examples/sync.rs26
-rw-r--r--vendor/elsa/src/index_map.rs215
-rw-r--r--vendor/elsa/src/index_set.rs180
-rw-r--r--vendor/elsa/src/lib.rs29
-rw-r--r--vendor/elsa/src/map.rs451
-rw-r--r--vendor/elsa/src/sync.rs624
-rw-r--r--vendor/elsa/src/vec.rs347
-rw-r--r--vendor/ena/.cargo-checksum.json2
-rw-r--r--vendor/ena/Cargo.toml23
-rw-r--r--vendor/ena/README.md2
-rw-r--r--vendor/ena/src/unify/mod.rs24
-rw-r--r--vendor/filetime/.cargo-checksum.json2
-rw-r--r--vendor/filetime/Cargo.toml2
-rw-r--r--vendor/filetime/src/unix/linux.rs33
-rw-r--r--vendor/filetime/src/unix/mod.rs15
-rw-r--r--vendor/flate2/.cargo-checksum.json2
-rw-r--r--vendor/flate2/Cargo.lock38
-rw-r--r--vendor/flate2/Cargo.toml8
-rw-r--r--vendor/gimli-0.26.2/.cargo-checksum.json1
-rw-r--r--vendor/gimli-0.26.2/CHANGELOG.md873
-rw-r--r--vendor/gimli-0.26.2/CONTRIBUTING.md137
-rw-r--r--vendor/gimli-0.26.2/Cargo.lock358
-rw-r--r--vendor/gimli-0.26.2/Cargo.toml146
-rw-r--r--vendor/gimli-0.26.2/LICENSE-APACHE201
-rw-r--r--vendor/gimli-0.26.2/LICENSE-MIT25
-rw-r--r--vendor/gimli-0.26.2/README.md78
-rw-r--r--vendor/gimli-0.26.2/benches/bench.rs807
-rw-r--r--vendor/gimli-0.26.2/examples/dwarf-validate.rs267
-rw-r--r--vendor/gimli-0.26.2/examples/dwarfdump.rs2417
-rw-r--r--vendor/gimli-0.26.2/examples/simple.rs67
-rw-r--r--vendor/gimli-0.26.2/examples/simple_line.rs106
-rw-r--r--vendor/gimli-0.26.2/fixtures/self/README.md147
-rw-r--r--vendor/gimli-0.26.2/fixtures/self/debug_abbrevbin0 -> 1865 bytes
-rw-r--r--vendor/gimli-0.26.2/fixtures/self/debug_arangesbin0 -> 16304 bytes
-rw-r--r--vendor/gimli-0.26.2/fixtures/self/debug_infobin0 -> 392832 bytes
-rw-r--r--vendor/gimli-0.26.2/fixtures/self/debug_inlinedbin0 -> 25062 bytes
-rw-r--r--vendor/gimli-0.26.2/fixtures/self/debug_linebin0 -> 109251 bytes
-rw-r--r--vendor/gimli-0.26.2/fixtures/self/debug_locbin0 -> 283588 bytes
-rw-r--r--vendor/gimli-0.26.2/fixtures/self/debug_pubnamesbin0 -> 138556 bytes
-rw-r--r--vendor/gimli-0.26.2/fixtures/self/debug_pubtypesbin0 -> 52984 bytes
-rw-r--r--vendor/gimli-0.26.2/fixtures/self/debug_rangesbin0 -> 186016 bytes
-rw-r--r--vendor/gimli-0.26.2/fixtures/self/debug_strbin0 -> 145794 bytes
-rw-r--r--vendor/gimli-0.26.2/fixtures/self/eh_framebin0 -> 147656 bytes
-rw-r--r--vendor/gimli-0.26.2/fixtures/self/eh_frame_hdrbin0 -> 108732 bytes
-rw-r--r--vendor/gimli-0.26.2/rustfmt.toml0
-rw-r--r--vendor/gimli-0.26.2/src/arch.rs603
-rw-r--r--vendor/gimli-0.26.2/src/common.rs363
-rw-r--r--vendor/gimli-0.26.2/src/constants.rs1425
-rw-r--r--vendor/gimli-0.26.2/src/endianity.rs256
-rw-r--r--vendor/gimli-0.26.2/src/leb128.rs612
-rw-r--r--vendor/gimli-0.26.2/src/lib.rs76
-rw-r--r--vendor/gimli-0.26.2/src/read/abbrev.rs996
-rw-r--r--vendor/gimli-0.26.2/src/read/addr.rs128
-rw-r--r--vendor/gimli-0.26.2/src/read/aranges.rs660
-rw-r--r--vendor/gimli-0.26.2/src/read/cfi.rs7585
-rw-r--r--vendor/gimli-0.26.2/src/read/dwarf.rs1143
-rw-r--r--vendor/gimli-0.26.2/src/read/endian_reader.rs639
-rw-r--r--vendor/gimli-0.26.2/src/read/endian_slice.rs350
-rw-r--r--vendor/gimli-0.26.2/src/read/index.rs535
-rw-r--r--vendor/gimli-0.26.2/src/read/line.rs3030
-rw-r--r--vendor/gimli-0.26.2/src/read/lists.rs68
-rw-r--r--vendor/gimli-0.26.2/src/read/loclists.rs1514
-rw-r--r--vendor/gimli-0.26.2/src/read/lookup.rs202
-rw-r--r--vendor/gimli-0.26.2/src/read/mod.rs821
-rw-r--r--vendor/gimli-0.26.2/src/read/op.rs4114
-rw-r--r--vendor/gimli-0.26.2/src/read/pubnames.rs141
-rw-r--r--vendor/gimli-0.26.2/src/read/pubtypes.rs141
-rw-r--r--vendor/gimli-0.26.2/src/read/reader.rs502
-rw-r--r--vendor/gimli-0.26.2/src/read/rnglists.rs1354
-rw-r--r--vendor/gimli-0.26.2/src/read/str.rs321
-rw-r--r--vendor/gimli-0.26.2/src/read/unit.rs6146
-rw-r--r--vendor/gimli-0.26.2/src/read/util.rs250
-rw-r--r--vendor/gimli-0.26.2/src/read/value.rs1621
-rw-r--r--vendor/gimli-0.26.2/src/test_util.rs53
-rw-r--r--vendor/gimli-0.26.2/src/write/abbrev.rs188
-rw-r--r--vendor/gimli-0.26.2/src/write/cfi.rs1025
-rw-r--r--vendor/gimli-0.26.2/src/write/dwarf.rs138
-rw-r--r--vendor/gimli-0.26.2/src/write/endian_vec.rs117
-rw-r--r--vendor/gimli-0.26.2/src/write/line.rs1960
-rw-r--r--vendor/gimli-0.26.2/src/write/loc.rs549
-rw-r--r--vendor/gimli-0.26.2/src/write/mod.rs425
-rw-r--r--vendor/gimli-0.26.2/src/write/op.rs1621
-rw-r--r--vendor/gimli-0.26.2/src/write/range.rs415
-rw-r--r--vendor/gimli-0.26.2/src/write/section.rs172
-rw-r--r--vendor/gimli-0.26.2/src/write/str.rs172
-rw-r--r--vendor/gimli-0.26.2/src/write/unit.rs3157
-rw-r--r--vendor/gimli-0.26.2/src/write/writer.rs497
-rw-r--r--vendor/gimli-0.26.2/tests/convert_self.rs158
-rwxr-xr-xvendor/gimli-0.26.2/tests/parse_self.rs431
-rw-r--r--vendor/gimli/.cargo-checksum.json2
-rw-r--r--vendor/gimli/CHANGELOG.md21
-rw-r--r--vendor/gimli/Cargo.lock120
-rw-r--r--vendor/gimli/Cargo.toml4
-rw-r--r--vendor/gimli/README.md4
-rw-r--r--vendor/gimli/clippy.toml1
-rw-r--r--vendor/gimli/examples/dwarfdump.rs164
-rw-r--r--vendor/gimli/src/arch.rs148
-rw-r--r--vendor/gimli/src/lib.rs15
-rw-r--r--vendor/gimli/src/read/abbrev.rs129
-rw-r--r--vendor/gimli/src/read/cfi.rs23
-rw-r--r--vendor/gimli/src/read/dwarf.rs26
-rw-r--r--vendor/gimli/src/read/endian_slice.rs6
-rw-r--r--vendor/gimli/src/read/lazy.rs116
-rw-r--r--vendor/gimli/src/read/line.rs2
-rw-r--r--vendor/gimli/src/read/loclists.rs241
-rw-r--r--vendor/gimli/src/read/mod.rs3
-rw-r--r--vendor/gimli/src/read/op.rs7
-rw-r--r--vendor/gimli/src/read/rnglists.rs206
-rw-r--r--vendor/gimli/src/read/unit.rs13
-rw-r--r--vendor/gimli/src/read/util.rs5
-rw-r--r--vendor/gimli/src/write/line.rs5
-rw-r--r--vendor/gimli/src/write/loc.rs3
-rw-r--r--vendor/gimli/src/write/op.rs15
-rw-r--r--vendor/gimli/src/write/range.rs3
-rw-r--r--vendor/gimli/src/write/section.rs2
-rw-r--r--vendor/gimli/src/write/unit.rs17
-rw-r--r--vendor/gimli/src/write/writer.rs5
-rw-r--r--vendor/hermit-abi/.cargo-checksum.json2
-rw-r--r--vendor/hermit-abi/Cargo.toml13
-rw-r--r--vendor/hermit-abi/src/net.rs232
-rw-r--r--vendor/hermit-abi/src/net_old.rs302
-rw-r--r--vendor/icu_list/.cargo-checksum.json2
-rw-r--r--vendor/icu_list/Cargo.lock761
-rw-r--r--vendor/icu_list/Cargo.toml43
-rw-r--r--vendor/icu_list/examples/and_list.rs4
-rw-r--r--vendor/icu_list/src/lazy_automaton.rs79
-rw-r--r--vendor/icu_list/src/lib.rs3
-rw-r--r--vendor/icu_list/src/list_formatter.rs43
-rw-r--r--vendor/icu_list/src/patterns.rs283
-rw-r--r--vendor/icu_list/src/provider.rs465
-rw-r--r--vendor/icu_list/src/provider/mod.rs261
-rw-r--r--vendor/icu_list/src/provider/serde_dfa.rs244
-rw-r--r--vendor/icu_list/src/string_matcher.rs213
-rw-r--r--vendor/icu_locid/.cargo-checksum.json2
-rw-r--r--vendor/icu_locid/Cargo.lock132
-rw-r--r--vendor/icu_locid/Cargo.toml30
-rw-r--r--vendor/icu_locid/README.md31
-rw-r--r--vendor/icu_locid/benches/iai_langid.rs8
-rw-r--r--vendor/icu_locid/examples/filter_langids.rs5
-rw-r--r--vendor/icu_locid/src/extensions/mod.rs29
-rw-r--r--vendor/icu_locid/src/extensions/other/mod.rs61
-rw-r--r--vendor/icu_locid/src/extensions/other/subtag.rs6
-rw-r--r--vendor/icu_locid/src/extensions/private/mod.rs26
-rw-r--r--vendor/icu_locid/src/extensions/transform/fields.rs30
-rw-r--r--vendor/icu_locid/src/extensions/transform/mod.rs6
-rw-r--r--vendor/icu_locid/src/extensions/transform/value.rs35
-rw-r--r--vendor/icu_locid/src/extensions/unicode/attributes.rs15
-rw-r--r--vendor/icu_locid/src/extensions/unicode/keywords.rs65
-rw-r--r--vendor/icu_locid/src/extensions/unicode/mod.rs46
-rw-r--r--vendor/icu_locid/src/extensions/unicode/value.rs33
-rw-r--r--vendor/icu_locid/src/helpers.rs46
-rw-r--r--vendor/icu_locid/src/langid.rs109
-rw-r--r--vendor/icu_locid/src/lib.rs32
-rw-r--r--vendor/icu_locid/src/locale.rs106
-rw-r--r--vendor/icu_locid/src/parser/errors.rs16
-rw-r--r--vendor/icu_locid/src/parser/langid.rs47
-rw-r--r--vendor/icu_locid/src/parser/locale.rs6
-rw-r--r--vendor/icu_locid/src/parser/mod.rs231
-rw-r--r--vendor/icu_locid/src/subtags/language.rs11
-rw-r--r--vendor/icu_locid/src/subtags/variants.rs28
-rw-r--r--vendor/icu_locid/tests/fixtures/invalid-extensions.json40
-rw-r--r--vendor/icu_locid/tests/fixtures/invalid.json49
-rw-r--r--vendor/icu_locid/tests/fixtures/mod.rs1
-rw-r--r--vendor/icu_locid/tests/langid.rs15
-rw-r--r--vendor/icu_locid/tests/locale.rs16
-rw-r--r--vendor/icu_provider/.cargo-checksum.json2
-rw-r--r--vendor/icu_provider/Cargo.toml49
-rw-r--r--vendor/icu_provider/README.md2
-rw-r--r--vendor/icu_provider/src/any.rs60
-rw-r--r--vendor/icu_provider/src/buf.rs6
-rw-r--r--vendor/icu_provider/src/constructors.rs6
-rw-r--r--vendor/icu_provider/src/datagen/mod.rs2
-rw-r--r--vendor/icu_provider/src/error.rs12
-rw-r--r--vendor/icu_provider/src/hello_world.rs2
-rw-r--r--vendor/icu_provider/src/key.rs6
-rw-r--r--vendor/icu_provider/src/lib.rs2
-rw-r--r--vendor/icu_provider/src/request.rs40
-rw-r--r--vendor/icu_provider/src/response.rs10
-rw-r--r--vendor/icu_provider/src/serde/mod.rs18
-rw-r--r--vendor/icu_provider_adapters/.cargo-checksum.json2
-rw-r--r--vendor/icu_provider_adapters/Cargo.toml28
-rw-r--r--vendor/icu_provider_adapters/src/empty.rs23
-rw-r--r--vendor/icu_provider_adapters/src/fallback/adapter.rs12
-rw-r--r--vendor/icu_provider_adapters/src/fallback/algorithms.rs26
-rw-r--r--vendor/icu_provider_adapters/src/fallback/mod.rs94
-rw-r--r--vendor/icu_provider_adapters/src/fork/by_error.rs39
-rw-r--r--vendor/icu_provider_macros/.cargo-checksum.json2
-rw-r--r--vendor/icu_provider_macros/Cargo.toml2
-rw-r--r--vendor/icu_provider_macros/src/lib.rs2
-rw-r--r--vendor/icu_provider_macros/src/tests.rs2
-rw-r--r--vendor/itoa/.cargo-checksum.json2
-rw-r--r--vendor/itoa/Cargo.toml2
-rw-r--r--vendor/itoa/README.md2
-rw-r--r--vendor/itoa/src/lib.rs2
-rw-r--r--vendor/jobserver/.cargo-checksum.json2
-rw-r--r--vendor/jobserver/Cargo.toml22
-rw-r--r--vendor/jobserver/src/lib.rs54
-rw-r--r--vendor/jobserver/src/unix.rs122
-rw-r--r--vendor/jobserver/src/wasm.rs5
-rw-r--r--vendor/jobserver/src/windows.rs20
-rw-r--r--vendor/jobserver/tests/client.rs3
-rw-r--r--vendor/jobserver/tests/make-as-a-client.rs3
-rw-r--r--vendor/jobserver/tests/server.rs29
-rw-r--r--vendor/libc/.cargo-checksum.json2
-rw-r--r--vendor/libc/Cargo.toml2
-rw-r--r--vendor/libc/src/fuchsia/mod.rs6
-rw-r--r--vendor/libc/src/unix/bsd/mod.rs1
-rw-r--r--vendor/libc/src/unix/haiku/mod.rs1
-rw-r--r--vendor/libc/src/unix/hermit/mod.rs1
-rw-r--r--vendor/libc/src/unix/linux_like/android/b32/arm.rs3
-rw-r--r--vendor/libc/src/unix/linux_like/android/b32/x86/mod.rs3
-rw-r--r--vendor/libc/src/unix/linux_like/android/b64/aarch64/mod.rs3
-rw-r--r--vendor/libc/src/unix/linux_like/android/b64/x86_64/mod.rs3
-rw-r--r--vendor/libc/src/unix/linux_like/android/mod.rs27
-rw-r--r--vendor/libc/src/unix/linux_like/emscripten/mod.rs1
-rw-r--r--vendor/libc/src/unix/linux_like/linux/mod.rs11
-rw-r--r--vendor/libc/src/unix/linux_like/mod.rs8
-rw-r--r--vendor/libc/src/unix/mod.rs151
-rw-r--r--vendor/libc/src/unix/newlib/mod.rs1
-rw-r--r--vendor/libc/src/unix/nto/aarch64.rs36
-rw-r--r--vendor/libc/src/unix/nto/mod.rs3286
-rw-r--r--vendor/libc/src/unix/nto/neutrino.rs1288
-rw-r--r--vendor/libc/src/unix/nto/x86_64.rs132
-rw-r--r--vendor/libc/src/unix/solarish/mod.rs1
-rw-r--r--vendor/libc/src/vxworks/mod.rs5
-rw-r--r--vendor/libc/src/wasi.rs6
-rw-r--r--vendor/libc/src/windows/mod.rs6
-rw-r--r--vendor/litemap/.cargo-checksum.json2
-rw-r--r--vendor/litemap/Cargo.lock322
-rw-r--r--vendor/litemap/Cargo.toml18
-rw-r--r--vendor/litemap/benches/litemap.rs17
-rw-r--r--vendor/litemap/src/map.rs4
-rw-r--r--vendor/litemap/src/store/mod.rs2
-rw-r--r--vendor/litemap/tests/rkyv.rs15
-rw-r--r--vendor/lsp-types/.cargo-checksum.json2
-rw-r--r--vendor/lsp-types/CHANGELOG.md584
-rw-r--r--vendor/lsp-types/Cargo.toml3
-rw-r--r--vendor/lsp-types/LICENSE44
-rw-r--r--vendor/lsp-types/README.md28
-rw-r--r--[-rwxr-xr-x]vendor/lsp-types/release.sh30
-rw-r--r--vendor/lsp-types/release.toml3
-rw-r--r--vendor/lsp-types/src/call_hierarchy.rs254
-rw-r--r--vendor/lsp-types/src/code_action.rs755
-rw-r--r--vendor/lsp-types/src/code_lens.rs132
-rw-r--r--vendor/lsp-types/src/color.rs244
-rw-r--r--vendor/lsp-types/src/completion.rs1216
-rw-r--r--vendor/lsp-types/src/document_highlight.rs102
-rw-r--r--vendor/lsp-types/src/document_link.rs134
-rw-r--r--vendor/lsp-types/src/document_symbols.rs264
-rw-r--r--vendor/lsp-types/src/error_codes.rs73
-rw-r--r--vendor/lsp-types/src/file_operations.rs426
-rw-r--r--vendor/lsp-types/src/folding_range.rs246
-rw-r--r--vendor/lsp-types/src/formatting.rs306
-rw-r--r--vendor/lsp-types/src/hover.rs172
-rw-r--r--vendor/lsp-types/src/inlay_hint.rs560
-rw-r--r--vendor/lsp-types/src/inline_value.rs217
-rw-r--r--vendor/lsp-types/src/lib.rs5490
-rw-r--r--vendor/lsp-types/src/linked_editing.rs122
-rw-r--r--vendor/lsp-types/src/lsif.rs676
-rw-r--r--vendor/lsp-types/src/moniker.rs184
-rw-r--r--vendor/lsp-types/src/notification.rs722
-rw-r--r--vendor/lsp-types/src/progress.rs268
-rw-r--r--vendor/lsp-types/src/references.rs60
-rw-r--r--vendor/lsp-types/src/rename.rs176
-rw-r--r--vendor/lsp-types/src/request.rs1890
-rw-r--r--vendor/lsp-types/src/selection_range.rs172
-rw-r--r--vendor/lsp-types/src/semantic_tokens.rs1472
-rw-r--r--vendor/lsp-types/src/signature_help.rs414
-rw-r--r--vendor/lsp-types/src/trace.rs164
-rw-r--r--vendor/lsp-types/src/type_hierarchy.rs90
-rw-r--r--vendor/lsp-types/src/window.rs352
-rw-r--r--vendor/lsp-types/src/workspace_folders.rs98
-rw-r--r--vendor/lsp-types/src/workspace_symbols.rs148
-rw-r--r--vendor/lsp-types/tests/lsif.rs32
-rw-r--r--vendor/lsp-types/tests/tsc-unix.lsif270
-rw-r--r--vendor/memmap2/.cargo-checksum.json2
-rw-r--r--vendor/memmap2/CHANGELOG.md9
-rw-r--r--vendor/memmap2/Cargo.lock2
-rw-r--r--vendor/memmap2/Cargo.toml4
-rw-r--r--vendor/memmap2/src/lib.rs34
-rw-r--r--vendor/miniz_oxide-0.5.3/.cargo-checksum.json1
-rw-r--r--vendor/miniz_oxide-0.5.3/Cargo.toml55
-rw-r--r--vendor/miniz_oxide-0.5.3/LICENSE (renamed from vendor/time-macros/LICENSE-MIT)4
-rw-r--r--vendor/miniz_oxide-0.5.3/LICENSE-APACHE.md (renamed from vendor/time-macros/LICENSE-Apache)25
-rw-r--r--vendor/miniz_oxide-0.5.3/LICENSE-MIT.md21
-rw-r--r--vendor/miniz_oxide-0.5.3/LICENSE-ZLIB.md11
-rw-r--r--vendor/miniz_oxide-0.5.3/Readme.md35
-rw-r--r--vendor/miniz_oxide-0.5.3/src/deflate/buffer.rs58
-rw-r--r--vendor/miniz_oxide-0.5.3/src/deflate/core.rs2463
-rw-r--r--vendor/miniz_oxide-0.5.3/src/deflate/mod.rs227
-rw-r--r--vendor/miniz_oxide-0.5.3/src/deflate/stream.rs121
-rw-r--r--vendor/miniz_oxide-0.5.3/src/inflate/core.rs1931
-rw-r--r--vendor/miniz_oxide-0.5.3/src/inflate/mod.rs279
-rw-r--r--vendor/miniz_oxide-0.5.3/src/inflate/output_buffer.rs60
-rw-r--r--vendor/miniz_oxide-0.5.3/src/inflate/stream.rs415
-rw-r--r--vendor/miniz_oxide-0.5.3/src/lib.rs208
-rw-r--r--vendor/miniz_oxide-0.5.3/src/shared.rs25
-rw-r--r--vendor/miniz_oxide/.cargo-checksum.json2
-rw-r--r--vendor/miniz_oxide/Cargo.toml6
-rw-r--r--vendor/miniz_oxide/Readme.md19
-rw-r--r--vendor/miniz_oxide/src/inflate/core.rs5
-rw-r--r--vendor/miniz_oxide/src/inflate/mod.rs102
-rw-r--r--vendor/miniz_oxide/src/inflate/stream.rs3
-rw-r--r--vendor/miniz_oxide/src/lib.rs10
-rw-r--r--vendor/nu-ansi-term/.cargo-checksum.json1
-rw-r--r--vendor/nu-ansi-term/Cargo.lock159
-rw-r--r--vendor/nu-ansi-term/Cargo.toml57
-rw-r--r--vendor/nu-ansi-term/LICENCE (renamed from vendor/ansi_term/LICENCE)1
-rw-r--r--vendor/nu-ansi-term/README.md (renamed from vendor/ansi_term/README.md)107
-rw-r--r--vendor/nu-ansi-term/examples/256_colors.rs (renamed from vendor/ansi_term/examples/256_colours.rs)33
-rw-r--r--vendor/nu-ansi-term/examples/basic_colors.rs18
-rw-r--r--vendor/nu-ansi-term/examples/gradient_colors.rs37
-rw-r--r--vendor/nu-ansi-term/examples/rgb_colors.rs23
-rw-r--r--vendor/nu-ansi-term/src/ansi.rs (renamed from vendor/ansi_term/src/ansi.rs)229
-rw-r--r--vendor/nu-ansi-term/src/debug.rs (renamed from vendor/ansi_term/src/debug.rs)84
-rw-r--r--vendor/nu-ansi-term/src/difference.rs (renamed from vendor/ansi_term/src/difference.rs)25
-rw-r--r--vendor/nu-ansi-term/src/display.rs (renamed from vendor/ansi_term/src/display.rs)220
-rw-r--r--vendor/nu-ansi-term/src/gradient.rs105
-rw-r--r--vendor/nu-ansi-term/src/lib.rs (renamed from vendor/ansi_term/src/lib.rs)145
-rw-r--r--vendor/nu-ansi-term/src/rgb.rs173
-rw-r--r--vendor/nu-ansi-term/src/style.rs629
-rw-r--r--vendor/nu-ansi-term/src/util.rs (renamed from vendor/ansi_term/src/util.rs)40
-rw-r--r--vendor/nu-ansi-term/src/windows.rs (renamed from vendor/ansi_term/src/windows.rs)17
-rw-r--r--vendor/nu-ansi-term/src/write.rs (renamed from vendor/ansi_term/src/write.rs)19
-rw-r--r--vendor/num_cpus/.cargo-checksum.json2
-rw-r--r--vendor/num_cpus/CHANGELOG.md13
-rw-r--r--vendor/num_cpus/Cargo.lock6
-rw-r--r--vendor/num_cpus/Cargo.toml12
-rw-r--r--vendor/num_cpus/fixtures/cgroups2/cgroups/ceil/cpu.max1
-rw-r--r--vendor/num_cpus/fixtures/cgroups2/cgroups/good/cpu.max1
-rw-r--r--vendor/num_cpus/fixtures/cgroups2/cgroups/zero-period/cpu.max1
-rw-r--r--vendor/num_cpus/fixtures/cgroups2/proc/cgroups/cgroup2
-rw-r--r--vendor/num_cpus/fixtures/cgroups2/proc/cgroups/cgroup_multi3
-rw-r--r--vendor/num_cpus/fixtures/cgroups2/proc/cgroups/mountinfo5
-rw-r--r--vendor/num_cpus/src/linux.rs407
-rw-r--r--vendor/object/.cargo-checksum.json2
-rw-r--r--vendor/object/CHANGELOG.md11
-rw-r--r--vendor/object/Cargo.toml2
-rw-r--r--vendor/object/src/elf.rs116
-rw-r--r--vendor/once_cell/.cargo-checksum.json2
-rw-r--r--vendor/once_cell/CHANGELOG.md4
-rw-r--r--vendor/once_cell/Cargo.lock2
-rw-r--r--vendor/once_cell/Cargo.toml2
-rw-r--r--vendor/once_cell/README.md2
-rw-r--r--vendor/once_cell/src/lib.rs14
-rw-r--r--vendor/once_cell/src/race.rs92
-rw-r--r--vendor/overload/.cargo-checksum.json1
-rw-r--r--vendor/overload/Cargo.toml (renamed from vendor/rls-data/Cargo.toml)24
-rw-r--r--vendor/overload/LICENSE21
-rw-r--r--vendor/overload/README.md64
-rw-r--r--vendor/overload/logo.pngbin0 -> 19188 bytes
-rw-r--r--vendor/overload/src/assignment.rs27
-rw-r--r--vendor/overload/src/binary.rs28
-rw-r--r--vendor/overload/src/lib.rs257
-rw-r--r--vendor/overload/src/unary.rs20
-rw-r--r--vendor/overload/tests/assignment.rs89
-rw-r--r--vendor/overload/tests/binary.rs72
-rw-r--r--vendor/overload/tests/unary.rs21
-rw-r--r--vendor/parking_lot_core-0.8.6/.cargo-checksum.json (renamed from vendor/parking_lot_core-0.8.5/.cargo-checksum.json)2
-rw-r--r--vendor/parking_lot_core-0.8.6/Cargo.toml (renamed from vendor/parking_lot_core-0.8.5/Cargo.toml)30
-rw-r--r--vendor/parking_lot_core-0.8.6/LICENSE-APACHE201
-rw-r--r--vendor/parking_lot_core-0.8.6/LICENSE-MIT (renamed from vendor/parking_lot_core-0.8.5/LICENSE-MIT)0
-rw-r--r--vendor/parking_lot_core-0.8.6/build.rs (renamed from vendor/parking_lot_core-0.8.5/build.rs)0
-rw-r--r--vendor/parking_lot_core-0.8.6/src/lib.rs (renamed from vendor/parking_lot_core-0.8.5/src/lib.rs)0
-rw-r--r--vendor/parking_lot_core-0.8.6/src/parking_lot.rs (renamed from vendor/parking_lot_core-0.8.5/src/parking_lot.rs)0
-rw-r--r--vendor/parking_lot_core-0.8.6/src/spinwait.rs (renamed from vendor/parking_lot_core-0.8.5/src/spinwait.rs)0
-rw-r--r--vendor/parking_lot_core-0.8.6/src/thread_parker/generic.rs (renamed from vendor/parking_lot_core-0.8.5/src/thread_parker/generic.rs)0
-rw-r--r--vendor/parking_lot_core-0.8.6/src/thread_parker/linux.rs (renamed from vendor/parking_lot_core-0.8.5/src/thread_parker/linux.rs)8
-rw-r--r--vendor/parking_lot_core-0.8.6/src/thread_parker/mod.rs (renamed from vendor/parking_lot_core-0.8.5/src/thread_parker/mod.rs)0
-rw-r--r--vendor/parking_lot_core-0.8.6/src/thread_parker/redox.rs (renamed from vendor/parking_lot_core-0.8.5/src/thread_parker/redox.rs)0
-rw-r--r--vendor/parking_lot_core-0.8.6/src/thread_parker/sgx.rs (renamed from vendor/parking_lot_core-0.8.5/src/thread_parker/sgx.rs)0
-rw-r--r--vendor/parking_lot_core-0.8.6/src/thread_parker/unix.rs (renamed from vendor/parking_lot_core-0.8.5/src/thread_parker/unix.rs)0
-rw-r--r--vendor/parking_lot_core-0.8.6/src/thread_parker/wasm.rs (renamed from vendor/parking_lot_core-0.8.5/src/thread_parker/wasm.rs)0
-rw-r--r--vendor/parking_lot_core-0.8.6/src/thread_parker/wasm_atomic.rs (renamed from vendor/parking_lot_core-0.8.5/src/thread_parker/wasm_atomic.rs)0
-rw-r--r--vendor/parking_lot_core-0.8.6/src/thread_parker/windows/keyed_event.rs (renamed from vendor/parking_lot_core-0.8.5/src/thread_parker/windows/keyed_event.rs)0
-rw-r--r--vendor/parking_lot_core-0.8.6/src/thread_parker/windows/mod.rs (renamed from vendor/parking_lot_core-0.8.5/src/thread_parker/windows/mod.rs)0
-rw-r--r--vendor/parking_lot_core-0.8.6/src/thread_parker/windows/waitaddress.rs (renamed from vendor/parking_lot_core-0.8.5/src/thread_parker/windows/waitaddress.rs)0
-rw-r--r--vendor/parking_lot_core-0.8.6/src/util.rs (renamed from vendor/parking_lot_core-0.8.5/src/util.rs)0
-rw-r--r--vendor/parking_lot_core-0.8.6/src/word_lock.rs (renamed from vendor/parking_lot_core-0.8.5/src/word_lock.rs)0
-rw-r--r--vendor/parking_lot_core/.cargo-checksum.json2
-rw-r--r--vendor/parking_lot_core/Cargo.toml2
-rw-r--r--vendor/parking_lot_core/src/thread_parker/linux.rs8
-rw-r--r--vendor/parking_lot_core/src/thread_parker/unix.rs8
-rw-r--r--vendor/proc-macro2/.cargo-checksum.json2
-rw-r--r--vendor/proc-macro2/Cargo.toml5
-rw-r--r--vendor/proc-macro2/LICENSE-APACHE25
-rw-r--r--vendor/proc-macro2/LICENSE-MIT2
-rw-r--r--vendor/proc-macro2/README.md2
-rw-r--r--vendor/proc-macro2/src/fallback.rs8
-rw-r--r--vendor/proc-macro2/src/lib.rs45
-rw-r--r--vendor/proc-macro2/src/location.rs29
-rw-r--r--vendor/proc-macro2/src/wrapper.rs22
-rw-r--r--vendor/quote/.cargo-checksum.json2
-rw-r--r--vendor/quote/Cargo.toml7
-rw-r--r--vendor/quote/LICENSE-MIT2
-rw-r--r--vendor/quote/README.md2
-rw-r--r--vendor/quote/src/lib.rs2
-rw-r--r--vendor/quote/tests/test.rs3
-rw-r--r--vendor/quote/tests/ui/not-quotable.rs2
-rw-r--r--vendor/quote/tests/ui/not-quotable.stderr9
-rw-r--r--vendor/quote/tests/ui/not-repeatable.rs2
-rw-r--r--vendor/quote/tests/ui/not-repeatable.stderr66
-rw-r--r--vendor/rayon/.cargo-checksum.json2
-rw-r--r--vendor/rayon/Cargo.toml5
-rw-r--r--vendor/rayon/RELEASES.md12
-rw-r--r--vendor/rayon/src/iter/par_bridge.rs159
-rw-r--r--vendor/rayon/tests/par_bridge_recursion.rs30
-rw-r--r--vendor/regex-syntax/.cargo-checksum.json2
-rw-r--r--vendor/regex-syntax/Cargo.toml2
-rw-r--r--vendor/regex-syntax/src/unicode.rs1
-rw-r--r--vendor/regex-syntax/src/unicode_tables/age.rs42
-rw-r--r--vendor/regex-syntax/src/unicode_tables/case_folding_simple.rs6
-rw-r--r--vendor/regex-syntax/src/unicode_tables/general_category.rs250
-rw-r--r--vendor/regex-syntax/src/unicode_tables/grapheme_cluster_break.rs26
-rw-r--r--vendor/regex-syntax/src/unicode_tables/perl_decimal.rs8
-rw-r--r--vendor/regex-syntax/src/unicode_tables/perl_space.rs6
-rw-r--r--vendor/regex-syntax/src/unicode_tables/perl_word.rs30
-rw-r--r--vendor/regex-syntax/src/unicode_tables/property_bool.rs266
-rw-r--r--vendor/regex-syntax/src/unicode_tables/property_names.rs6
-rw-r--r--vendor/regex-syntax/src/unicode_tables/property_values.rs14
-rw-r--r--vendor/regex-syntax/src/unicode_tables/script.rs63
-rw-r--r--vendor/regex-syntax/src/unicode_tables/script_extension.rs54
-rw-r--r--vendor/regex-syntax/src/unicode_tables/sentence_break.rs47
-rw-r--r--vendor/regex-syntax/src/unicode_tables/word_break.rs34
-rw-r--r--vendor/regex/.cargo-checksum.json2
-rw-r--r--vendor/regex/CHANGELOG.md26
-rw-r--r--vendor/regex/Cargo.lock22
-rw-r--r--vendor/regex/Cargo.toml2
-rw-r--r--vendor/regex/README.md8
-rw-r--r--vendor/regex/src/lib.rs3
-rw-r--r--vendor/regex/src/re_bytes.rs12
-rw-r--r--vendor/regex/src/re_unicode.rs12
-rw-r--r--vendor/regex/tests/replace.rs18
-rw-r--r--vendor/rls-data/.cargo-checksum.json1
-rw-r--r--vendor/rls-data/README.md11
-rw-r--r--vendor/rls-data/src/config.rs24
-rw-r--r--vendor/rls-data/src/lib.rs272
-rw-r--r--vendor/rls-span/.cargo-checksum.json1
-rw-r--r--vendor/rls-span/Cargo.toml33
-rw-r--r--vendor/rls-span/src/compiler.rs78
-rw-r--r--vendor/rls-span/src/lib.rs383
-rw-r--r--vendor/rustc-ap-rustc_lexer/.cargo-checksum.json2
-rw-r--r--vendor/rustc-ap-rustc_lexer/Cargo.toml4
-rw-r--r--vendor/rustc-ap-rustc_lexer/src/lib.rs22
-rw-r--r--vendor/ryu/.cargo-checksum.json2
-rw-r--r--vendor/ryu/Cargo.lock30
-rw-r--r--vendor/ryu/Cargo.toml2
-rw-r--r--vendor/ryu/README.md2
-rw-r--r--vendor/ryu/src/lib.rs2
-rw-r--r--vendor/ryu/src/pretty/mantissa.rs6
-rw-r--r--vendor/ryu/src/pretty/mod.rs3
-rw-r--r--vendor/ryu/src/s2f.rs2
-rw-r--r--vendor/scoped-tls/.cargo-checksum.json2
-rw-r--r--vendor/scoped-tls/Cargo.toml18
-rw-r--r--vendor/scoped-tls/README.md2
-rw-r--r--vendor/scoped-tls/appveyor.yml17
-rw-r--r--vendor/scoped-tls/src/lib.rs22
-rw-r--r--vendor/semver/.cargo-checksum.json2
-rw-r--r--vendor/semver/Cargo.toml7
-rw-r--r--vendor/semver/README.md2
-rw-r--r--vendor/semver/build.rs2
-rw-r--r--vendor/semver/src/backport.rs39
-rw-r--r--vendor/semver/src/identifier.rs20
-rw-r--r--vendor/semver/src/lib.rs12
-rw-r--r--vendor/serde/.cargo-checksum.json2
-rw-r--r--vendor/serde/Cargo.toml9
-rw-r--r--vendor/serde/README.md4
-rw-r--r--vendor/serde/build.rs38
-rw-r--r--vendor/serde/crates-io.md2
-rw-r--r--vendor/serde/src/de/format.rs2
-rw-r--r--vendor/serde/src/de/impls.rs44
-rw-r--r--vendor/serde/src/de/mod.rs5
-rw-r--r--vendor/serde/src/lib.rs37
-rw-r--r--vendor/serde/src/private/de.rs14
-rw-r--r--vendor/serde/src/private/ser.rs2
-rw-r--r--vendor/serde/src/ser/impls.rs70
-rw-r--r--vendor/serde/src/ser/mod.rs10
-rw-r--r--vendor/serde_derive/.cargo-checksum.json2
-rw-r--r--vendor/serde_derive/Cargo.toml4
-rw-r--r--vendor/serde_derive/README.md4
-rw-r--r--vendor/serde_derive/build.rs2
-rw-r--r--vendor/serde_derive/crates-io.md2
-rw-r--r--vendor/serde_derive/src/de.rs186
-rw-r--r--vendor/serde_derive/src/internals/check.rs23
-rw-r--r--vendor/serde_derive/src/lib.rs4
-rw-r--r--vendor/serde_derive/src/ser.rs62
-rw-r--r--vendor/serde_derive/src/this.rs32
-rw-r--r--vendor/serde_json/.cargo-checksum.json2
-rw-r--r--vendor/serde_json/Cargo.toml5
-rw-r--r--vendor/serde_json/README.md10
-rw-r--r--vendor/serde_json/build.rs2
-rw-r--r--vendor/serde_json/src/de.rs154
-rw-r--r--vendor/serde_json/src/lib.rs6
-rw-r--r--vendor/serde_json/src/map.rs10
-rw-r--r--vendor/serde_json/src/number.rs37
-rw-r--r--vendor/serde_json/src/ser.rs382
-rw-r--r--vendor/serde_json/src/value/de.rs27
-rw-r--r--vendor/serde_json/src/value/from.rs9
-rw-r--r--vendor/serde_json/src/value/ser.rs15
-rw-r--r--vendor/serde_json/tests/regression/issue953.rs9
-rw-r--r--vendor/serde_json/tests/test.rs3
-rw-r--r--vendor/serde_json/tests/ui/missing_colon.stderr5
-rw-r--r--vendor/serde_json/tests/ui/missing_comma.stderr6
-rw-r--r--vendor/serde_json/tests/ui/missing_value.stderr5
-rw-r--r--vendor/serde_json/tests/ui/parse_expr.stderr6
-rw-r--r--vendor/serde_json/tests/ui/unexpected_after_array_element.stderr2
-rw-r--r--vendor/serde_json/tests/ui/unexpected_after_map_entry.stderr2
-rw-r--r--vendor/serde_json/tests/ui/unexpected_colon.stderr2
-rw-r--r--vendor/serde_json/tests/ui/unexpected_comma.stderr2
-rw-r--r--vendor/serde_repr/.cargo-checksum.json2
-rw-r--r--vendor/serde_repr/Cargo.toml2
-rw-r--r--vendor/serde_repr/README.md2
-rw-r--r--vendor/snap/.cargo-checksum.json2
-rw-r--r--vendor/snap/Cargo.lock8
-rw-r--r--vendor/snap/Cargo.toml26
-rw-r--r--vendor/snap/src/error.rs7
-rw-r--r--vendor/snap/src/read.rs5
-rw-r--r--vendor/syn/.cargo-checksum.json2
-rw-r--r--vendor/syn/Cargo.toml5
-rw-r--r--vendor/syn/README.md2
-rw-r--r--vendor/syn/src/buffer.rs50
-rw-r--r--vendor/syn/src/drops.rs58
-rw-r--r--vendor/syn/src/error.rs54
-rw-r--r--vendor/syn/src/generics.rs25
-rw-r--r--vendor/syn/src/lib.rs6
-rw-r--r--vendor/syn/src/path.rs5
-rw-r--r--vendor/syn/src/punctuated.rs43
-rw-r--r--vendor/syn/src/ty.rs92
-rw-r--r--vendor/syn/src/verbatim.rs20
-rw-r--r--vendor/syn/tests/common/eq.rs95
-rw-r--r--vendor/syn/tests/regression.rs2
-rw-r--r--vendor/syn/tests/regression/issue1235.rs32
-rw-r--r--vendor/syn/tests/repo/mod.rs2
-rw-r--r--vendor/syn/tests/test_expr.rs70
-rw-r--r--vendor/syn/tests/test_iterators.rs19
-rw-r--r--vendor/syn/tests/test_round_trip.rs8
-rw-r--r--vendor/syn/tests/test_size.rs4
-rw-r--r--vendor/thin-vec/.cargo-checksum.json2
-rw-r--r--vendor/thin-vec/Cargo.toml2
-rw-r--r--vendor/thin-vec/src/lib.rs1458
-rw-r--r--vendor/time-macros/.cargo-checksum.json1
-rw-r--r--vendor/time-macros/Cargo.toml45
-rw-r--r--vendor/time-macros/src/date.rs137
-rw-r--r--vendor/time-macros/src/datetime.rs57
-rw-r--r--vendor/time-macros/src/error.rs136
-rw-r--r--vendor/time-macros/src/format_description/component.rs168
-rw-r--r--vendor/time-macros/src/format_description/error.rs29
-rw-r--r--vendor/time-macros/src/format_description/mod.rs40
-rw-r--r--vendor/time-macros/src/format_description/modifier.rs417
-rw-r--r--vendor/time-macros/src/format_description/parse.rs84
-rw-r--r--vendor/time-macros/src/helpers/mod.rs129
-rw-r--r--vendor/time-macros/src/helpers/string.rs188
-rw-r--r--vendor/time-macros/src/lib.rs167
-rw-r--r--vendor/time-macros/src/offset.rs95
-rw-r--r--vendor/time-macros/src/quote.rs134
-rw-r--r--vendor/time-macros/src/serde_format_description.rs163
-rw-r--r--vendor/time-macros/src/time.rs118
-rw-r--r--vendor/time-macros/src/to_tokens.rs68
-rw-r--r--vendor/tinystr/.cargo-checksum.json2
-rw-r--r--vendor/tinystr/Cargo.toml14
-rw-r--r--vendor/tinystr/README.md6
-rw-r--r--vendor/tinystr/src/ascii.rs17
-rw-r--r--vendor/tinystr/src/error.rs3
-rw-r--r--vendor/tinystr/src/lib.rs8
-rw-r--r--vendor/toml-0.5.9/.cargo-checksum.json (renamed from vendor/toml/.cargo-checksum.json)0
-rw-r--r--vendor/toml-0.5.9/Cargo.lock (renamed from vendor/toml/Cargo.lock)0
-rw-r--r--vendor/toml-0.5.9/Cargo.toml (renamed from vendor/toml/Cargo.toml)0
-rw-r--r--vendor/toml-0.5.9/LICENSE-APACHE201
-rw-r--r--vendor/toml-0.5.9/LICENSE-MIT (renamed from vendor/toml/LICENSE-MIT)0
-rw-r--r--vendor/toml-0.5.9/README.md (renamed from vendor/toml/README.md)0
-rw-r--r--vendor/toml-0.5.9/examples/decode.rs (renamed from vendor/toml/examples/decode.rs)0
-rw-r--r--vendor/toml-0.5.9/examples/enum_external.rs (renamed from vendor/toml/examples/enum_external.rs)0
-rw-r--r--vendor/toml-0.5.9/examples/toml2json.rs (renamed from vendor/toml/examples/toml2json.rs)0
-rw-r--r--vendor/toml-0.5.9/src/datetime.rs (renamed from vendor/toml/src/datetime.rs)0
-rw-r--r--vendor/toml-0.5.9/src/de.rs (renamed from vendor/toml/src/de.rs)0
-rw-r--r--vendor/toml-0.5.9/src/lib.rs (renamed from vendor/toml/src/lib.rs)0
-rw-r--r--vendor/toml-0.5.9/src/macros.rs (renamed from vendor/toml/src/macros.rs)0
-rw-r--r--vendor/toml-0.5.9/src/map.rs (renamed from vendor/toml/src/map.rs)0
-rw-r--r--vendor/toml-0.5.9/src/ser.rs (renamed from vendor/toml/src/ser.rs)0
-rw-r--r--vendor/toml-0.5.9/src/spanned.rs (renamed from vendor/toml/src/spanned.rs)0
-rw-r--r--vendor/toml-0.5.9/src/tokens.rs (renamed from vendor/toml/src/tokens.rs)0
-rw-r--r--vendor/toml-0.5.9/src/value.rs (renamed from vendor/toml/src/value.rs)0
-rw-r--r--vendor/toml-0.5.9/tests/enum_external_deserialize.rs (renamed from vendor/toml/tests/enum_external_deserialize.rs)0
-rw-r--r--vendor/tracing-subscriber-0.3.3/.cargo-checksum.json1
-rw-r--r--vendor/tracing-subscriber-0.3.3/src/fmt/format/pretty.rs415
-rw-r--r--vendor/tracing-subscriber-0.3.3/src/fmt/time/time_crate.rs276
-rw-r--r--vendor/tracing-subscriber-0.3.3/src/reload.rs237
-rw-r--r--vendor/tracing-subscriber-0.3.3/tests/filter.rs187
-rw-r--r--vendor/tracing-subscriber-0.3.3/tests/reload.rs81
-rw-r--r--vendor/tracing-subscriber/.cargo-checksum.json1
-rw-r--r--vendor/tracing-subscriber/CHANGELOG.md (renamed from vendor/tracing-subscriber-0.3.3/CHANGELOG.md)392
-rw-r--r--vendor/tracing-subscriber/Cargo.toml (renamed from vendor/tracing-subscriber-0.3.3/Cargo.toml)168
-rw-r--r--vendor/tracing-subscriber/LICENSE (renamed from vendor/tracing-subscriber-0.3.3/LICENSE)0
-rw-r--r--vendor/tracing-subscriber/README.md (renamed from vendor/tracing-subscriber-0.3.3/README.md)6
-rw-r--r--vendor/tracing-subscriber/benches/enter.rs (renamed from vendor/tracing-subscriber-0.3.3/benches/enter.rs)0
-rw-r--r--vendor/tracing-subscriber/benches/filter.rs (renamed from vendor/tracing-subscriber-0.3.3/benches/filter.rs)0
-rw-r--r--vendor/tracing-subscriber/benches/filter_log.rs (renamed from vendor/tracing-subscriber-0.3.3/benches/filter_log.rs)0
-rw-r--r--vendor/tracing-subscriber/benches/fmt.rs (renamed from vendor/tracing-subscriber-0.3.3/benches/fmt.rs)0
-rw-r--r--vendor/tracing-subscriber/benches/support/mod.rs (renamed from vendor/tracing-subscriber-0.3.3/benches/support/mod.rs)0
-rw-r--r--vendor/tracing-subscriber/src/field/debug.rs (renamed from vendor/tracing-subscriber-0.3.3/src/field/debug.rs)0
-rw-r--r--vendor/tracing-subscriber/src/field/delimited.rs (renamed from vendor/tracing-subscriber-0.3.3/src/field/delimited.rs)4
-rw-r--r--vendor/tracing-subscriber/src/field/display.rs (renamed from vendor/tracing-subscriber-0.3.3/src/field/display.rs)2
-rw-r--r--vendor/tracing-subscriber/src/field/mod.rs (renamed from vendor/tracing-subscriber-0.3.3/src/field/mod.rs)14
-rw-r--r--vendor/tracing-subscriber/src/filter/directive.rs (renamed from vendor/tracing-subscriber-0.3.3/src/filter/directive.rs)34
-rw-r--r--vendor/tracing-subscriber/src/filter/env/builder.rs325
-rw-r--r--vendor/tracing-subscriber/src/filter/env/directive.rs (renamed from vendor/tracing-subscriber-0.3.3/src/filter/env/directive.rs)160
-rw-r--r--vendor/tracing-subscriber/src/filter/env/field.rs (renamed from vendor/tracing-subscriber-0.3.3/src/filter/env/field.rs)250
-rw-r--r--vendor/tracing-subscriber/src/filter/env/mod.rs (renamed from vendor/tracing-subscriber-0.3.3/src/filter/env/mod.rs)677
-rw-r--r--vendor/tracing-subscriber/src/filter/filter_fn.rs (renamed from vendor/tracing-subscriber-0.3.3/src/filter/filter_fn.rs)0
-rw-r--r--vendor/tracing-subscriber/src/filter/layer_filters/combinator.rs542
-rw-r--r--vendor/tracing-subscriber/src/filter/layer_filters/mod.rs (renamed from vendor/tracing-subscriber-0.3.3/src/filter/layer_filters.rs)454
-rw-r--r--vendor/tracing-subscriber/src/filter/level.rs (renamed from vendor/tracing-subscriber-0.3.3/src/filter/level.rs)0
-rw-r--r--vendor/tracing-subscriber/src/filter/mod.rs (renamed from vendor/tracing-subscriber-0.3.3/src/filter/mod.rs)0
-rw-r--r--vendor/tracing-subscriber/src/filter/targets.rs (renamed from vendor/tracing-subscriber-0.3.3/src/filter/targets.rs)104
-rw-r--r--vendor/tracing-subscriber/src/fmt/fmt_layer.rs (renamed from vendor/tracing-subscriber-0.3.3/src/fmt/fmt_layer.rs)321
-rw-r--r--vendor/tracing-subscriber/src/fmt/format/json.rs (renamed from vendor/tracing-subscriber-0.3.3/src/fmt/format/json.rs)175
-rw-r--r--vendor/tracing-subscriber/src/fmt/format/mod.rs (renamed from vendor/tracing-subscriber-0.3.3/src/fmt/format/mod.rs)459
-rw-r--r--vendor/tracing-subscriber/src/fmt/format/pretty.rs511
-rw-r--r--vendor/tracing-subscriber/src/fmt/mod.rs (renamed from vendor/tracing-subscriber-0.3.3/src/fmt/mod.rs)392
-rw-r--r--vendor/tracing-subscriber/src/fmt/time/datetime.rs (renamed from vendor/tracing-subscriber-0.3.3/src/fmt/time/datetime.rs)0
-rw-r--r--vendor/tracing-subscriber/src/fmt/time/mod.rs (renamed from vendor/tracing-subscriber-0.3.3/src/fmt/time/mod.rs)8
-rw-r--r--vendor/tracing-subscriber/src/fmt/time/time_crate.rs470
-rw-r--r--vendor/tracing-subscriber/src/fmt/writer.rs (renamed from vendor/tracing-subscriber-0.3.3/src/fmt/writer.rs)30
-rw-r--r--vendor/tracing-subscriber/src/layer/context.rs (renamed from vendor/tracing-subscriber-0.3.3/src/layer/context.rs)22
-rw-r--r--vendor/tracing-subscriber/src/layer/layered.rs (renamed from vendor/tracing-subscriber-0.3.3/src/layer/layered.rs)107
-rw-r--r--vendor/tracing-subscriber/src/layer/mod.rs (renamed from vendor/tracing-subscriber-0.3.3/src/layer/mod.rs)820
-rw-r--r--vendor/tracing-subscriber/src/layer/tests.rs (renamed from vendor/tracing-subscriber-0.3.3/src/layer/tests.rs)0
-rw-r--r--vendor/tracing-subscriber/src/lib.rs (renamed from vendor/tracing-subscriber-0.3.3/src/lib.rs)54
-rw-r--r--vendor/tracing-subscriber/src/macros.rs (renamed from vendor/tracing-subscriber-0.3.3/src/macros.rs)0
-rw-r--r--vendor/tracing-subscriber/src/prelude.rs (renamed from vendor/tracing-subscriber-0.3.3/src/prelude.rs)0
-rw-r--r--vendor/tracing-subscriber/src/registry/extensions.rs (renamed from vendor/tracing-subscriber-0.3.3/src/registry/extensions.rs)2
-rw-r--r--vendor/tracing-subscriber/src/registry/mod.rs (renamed from vendor/tracing-subscriber-0.3.3/src/registry/mod.rs)20
-rw-r--r--vendor/tracing-subscriber/src/registry/sharded.rs (renamed from vendor/tracing-subscriber-0.3.3/src/registry/sharded.rs)34
-rw-r--r--vendor/tracing-subscriber/src/registry/stack.rs (renamed from vendor/tracing-subscriber-0.3.3/src/registry/stack.rs)0
-rw-r--r--vendor/tracing-subscriber/src/reload.rs384
-rw-r--r--vendor/tracing-subscriber/src/sync.rs (renamed from vendor/tracing-subscriber-0.3.3/src/sync.rs)0
-rw-r--r--vendor/tracing-subscriber/src/util.rs (renamed from vendor/tracing-subscriber-0.3.3/src/util.rs)0
-rw-r--r--vendor/tracing-subscriber/tests/cached_layer_filters_dont_break_other_layers.rs (renamed from vendor/tracing-subscriber-0.3.3/tests/cached_layer_filters_dont_break_other_layers.rs)0
-rw-r--r--vendor/tracing-subscriber/tests/duplicate_spans.rs (renamed from vendor/tracing-subscriber-0.3.3/tests/duplicate_spans.rs)1
-rw-r--r--vendor/tracing-subscriber/tests/env_filter/main.rs547
-rw-r--r--vendor/tracing-subscriber/tests/env_filter/per_layer.rs305
-rw-r--r--vendor/tracing-subscriber/tests/event_enabling.rs81
-rw-r--r--vendor/tracing-subscriber/tests/field_filter.rs (renamed from vendor/tracing-subscriber-0.3.3/tests/field_filter.rs)4
-rw-r--r--vendor/tracing-subscriber/tests/filter_log.rs (renamed from vendor/tracing-subscriber-0.3.3/tests/filter_log.rs)4
-rw-r--r--vendor/tracing-subscriber/tests/fmt_max_level_hint.rs (renamed from vendor/tracing-subscriber-0.3.3/tests/fmt_max_level_hint.rs)0
-rw-r--r--vendor/tracing-subscriber/tests/hinted_layer_filters_dont_break_other_layers.rs (renamed from vendor/tracing-subscriber-0.3.3/tests/hinted_layer_filters_dont_break_other_layers.rs)0
-rw-r--r--vendor/tracing-subscriber/tests/layer_filter_interests_are_cached.rs (renamed from vendor/tracing-subscriber-0.3.3/tests/layer_filter_interests_are_cached.rs)0
-rw-r--r--vendor/tracing-subscriber/tests/layer_filters/boxed.rs (renamed from vendor/tracing-subscriber-0.3.3/tests/layer_filters/boxed.rs)0
-rw-r--r--vendor/tracing-subscriber/tests/layer_filters/combinators.rs42
-rw-r--r--vendor/tracing-subscriber/tests/layer_filters/downcast_raw.rs (renamed from vendor/tracing-subscriber-0.3.3/tests/layer_filters/downcast_raw.rs)0
-rw-r--r--vendor/tracing-subscriber/tests/layer_filters/filter_scopes.rs (renamed from vendor/tracing-subscriber-0.3.3/tests/layer_filters/filter_scopes.rs)0
-rw-r--r--vendor/tracing-subscriber/tests/layer_filters/main.rs (renamed from vendor/tracing-subscriber-0.3.3/tests/layer_filters/main.rs)4
-rw-r--r--vendor/tracing-subscriber/tests/layer_filters/per_event.rs61
-rw-r--r--vendor/tracing-subscriber/tests/layer_filters/targets.rs (renamed from vendor/tracing-subscriber-0.3.3/tests/layer_filters/targets.rs)0
-rw-r--r--vendor/tracing-subscriber/tests/layer_filters/trees.rs (renamed from vendor/tracing-subscriber-0.3.3/tests/layer_filters/trees.rs)0
-rw-r--r--vendor/tracing-subscriber/tests/layer_filters/vec.rs120
-rw-r--r--vendor/tracing-subscriber/tests/multiple_layer_filter_interests_cached.rs (renamed from vendor/tracing-subscriber-0.3.3/tests/multiple_layer_filter_interests_cached.rs)0
-rw-r--r--vendor/tracing-subscriber/tests/option.rs262
-rw-r--r--vendor/tracing-subscriber/tests/registry_max_level_hint.rs (renamed from vendor/tracing-subscriber-0.3.3/tests/registry_max_level_hint.rs)0
-rw-r--r--vendor/tracing-subscriber/tests/registry_with_subscriber.rs (renamed from vendor/tracing-subscriber-0.3.3/tests/registry_with_subscriber.rs)2
-rw-r--r--vendor/tracing-subscriber/tests/reload.rs155
-rw-r--r--vendor/tracing-subscriber/tests/same_len_filters.rs (renamed from vendor/tracing-subscriber-0.3.3/tests/same_len_filters.rs)4
-rw-r--r--vendor/tracing-subscriber/tests/support.rs (renamed from vendor/tracing-subscriber-0.3.3/tests/support.rs)19
-rw-r--r--vendor/tracing-subscriber/tests/unhinted_layer_filters_dont_break_other_layers.rs (renamed from vendor/tracing-subscriber-0.3.3/tests/unhinted_layer_filters_dont_break_other_layers.rs)0
-rw-r--r--vendor/tracing-subscriber/tests/utils.rs (renamed from vendor/tracing-subscriber-0.3.3/tests/utils.rs)4
-rw-r--r--vendor/tracing-subscriber/tests/vec.rs19
-rw-r--r--vendor/tracing-subscriber/tests/vec_subscriber_filter_interests_cached.rs117
-rw-r--r--vendor/tracing-tree/.cargo-checksum.json2
-rw-r--r--vendor/tracing-tree/Cargo.lock29
-rw-r--r--vendor/tracing-tree/Cargo.toml8
-rw-r--r--vendor/tracing-tree/src/format.rs4
-rw-r--r--vendor/tracing-tree/src/lib.rs2
-rw-r--r--vendor/unicode-bidi/.cargo-checksum.json2
-rw-r--r--vendor/unicode-bidi/Cargo.toml7
-rw-r--r--vendor/unicode-bidi/src/char_data/mod.rs18
-rw-r--r--vendor/unicode-bidi/src/char_data/tables.rs311
-rw-r--r--vendor/unicode-bidi/src/data_source.rs30
-rw-r--r--vendor/unicode-bidi/src/explicit.rs44
-rw-r--r--vendor/unicode-bidi/src/implicit.rs521
-rw-r--r--vendor/unicode-bidi/src/lib.rs93
-rw-r--r--vendor/unicode-bidi/src/prepare.rs102
-rw-r--r--vendor/unicode-ident/.cargo-checksum.json2
-rw-r--r--vendor/unicode-ident/Cargo.toml2
-rw-r--r--vendor/unicode-ident/README.md2
-rw-r--r--vendor/unicode-ident/src/tables.rs2
-rw-r--r--vendor/unicode-ident/tests/static_size.rs9
-rw-r--r--vendor/unicode-ident/tests/tables/mod.rs7
-rw-r--r--vendor/unicode-ident/tests/tables/tables.rs347
-rw-r--r--vendor/writeable/.cargo-checksum.json2
-rw-r--r--vendor/writeable/Cargo.lock110
-rw-r--r--vendor/writeable/Cargo.toml12
-rw-r--r--vendor/writeable/src/impls.rs104
-rw-r--r--vendor/writeable/src/lib.rs60
-rw-r--r--vendor/writeable/src/ops.rs5
-rw-r--r--vendor/xflags-macros/.cargo-checksum.json2
-rw-r--r--vendor/xflags-macros/Cargo.toml2
-rw-r--r--vendor/xflags-macros/tests/it/main.rs70
-rw-r--r--vendor/xflags/.cargo-checksum.json2
-rw-r--r--vendor/xflags/Cargo.lock6
-rw-r--r--vendor/xflags/Cargo.toml4
-rw-r--r--vendor/xflags/src/rt.rs58
-rw-r--r--vendor/xshell-macros/.cargo-checksum.json2
-rw-r--r--vendor/xshell-macros/Cargo.toml2
-rw-r--r--vendor/xshell/.cargo-checksum.json2
-rw-r--r--vendor/xshell/CHANGELOG.md4
-rw-r--r--vendor/xshell/Cargo.lock10
-rw-r--r--vendor/xshell/Cargo.toml4
-rw-r--r--vendor/xshell/src/lib.rs5
-rw-r--r--vendor/yoke-derive/.cargo-checksum.json2
-rw-r--r--vendor/yoke-derive/Cargo.lock87
-rw-r--r--vendor/yoke-derive/Cargo.toml13
-rw-r--r--vendor/yoke-derive/src/lib.rs55
-rw-r--r--vendor/yoke/.cargo-checksum.json2
-rw-r--r--vendor/yoke/Cargo.toml13
-rw-r--r--vendor/yoke/src/erased.rs8
-rw-r--r--vendor/yoke/src/is_covariant.rs142
-rw-r--r--vendor/yoke/src/lib.rs2
-rw-r--r--vendor/yoke/src/macro_impls.rs3
-rw-r--r--vendor/yoke/src/yoke.rs228
-rw-r--r--vendor/yoke/src/zero_from.rs5
-rw-r--r--vendor/zerovec-derive/.cargo-checksum.json2
-rw-r--r--vendor/zerovec-derive/Cargo.lock45
-rw-r--r--vendor/zerovec-derive/Cargo.toml8
-rw-r--r--vendor/zerovec-derive/src/make_varule.rs16
-rw-r--r--vendor/zerovec/.cargo-checksum.json2
-rw-r--r--vendor/zerovec/Cargo.lock327
-rw-r--r--vendor/zerovec/Cargo.toml29
-rw-r--r--vendor/zerovec/README.md2
-rw-r--r--vendor/zerovec/benches/vzv.rs8
-rw-r--r--vendor/zerovec/benches/zeromap.rs20
-rw-r--r--vendor/zerovec/src/flexzerovec/serde.rs8
-rw-r--r--vendor/zerovec/src/flexzerovec/slice.rs8
-rw-r--r--vendor/zerovec/src/lib.rs9
-rw-r--r--vendor/zerovec/src/map/borrowed.rs14
-rw-r--r--vendor/zerovec/src/map/map.rs4
-rw-r--r--vendor/zerovec/src/map/serde.rs8
-rw-r--r--vendor/zerovec/src/map2d/borrowed.rs9
-rw-r--r--vendor/zerovec/src/map2d/cursor.rs70
-rw-r--r--vendor/zerovec/src/map2d/map.rs12
-rw-r--r--vendor/zerovec/src/map2d/serde.rs8
-rw-r--r--vendor/zerovec/src/ule/mod.rs6
-rw-r--r--vendor/zerovec/src/ule/option.rs2
-rw-r--r--vendor/zerovec/src/ule/plain.rs19
-rw-r--r--vendor/zerovec/src/ule/unvalidated.rs10
-rw-r--r--vendor/zerovec/src/varzerovec/serde.rs8
-rw-r--r--vendor/zerovec/src/varzerovec/slice.rs28
-rw-r--r--vendor/zerovec/src/varzerovec/vec.rs16
-rw-r--r--vendor/zerovec/src/yoke_impls.rs14
-rw-r--r--vendor/zerovec/src/zerovec/mod.rs7
-rw-r--r--vendor/zerovec/src/zerovec/serde.rs10
-rw-r--r--vendor/zerovec/src/zerovec/slice.rs30
-rw-r--r--vendor/zip/.cargo-checksum.json2
-rw-r--r--vendor/zip/CHANGELOG.md9
-rw-r--r--vendor/zip/Cargo.lock134
-rw-r--r--vendor/zip/Cargo.toml18
-rw-r--r--vendor/zip/README.md4
-rw-r--r--vendor/zip/benches/read_metadata.rs5
-rw-r--r--vendor/zip/examples/extract.rs6
-rw-r--r--vendor/zip/examples/extract_lorem.rs4
-rw-r--r--vendor/zip/examples/file_info.rs4
-rw-r--r--vendor/zip/examples/stdin_info.rs4
-rw-r--r--vendor/zip/examples/write_dir.rs12
-rw-r--r--vendor/zip/examples/write_sample.rs6
-rw-r--r--vendor/zip/src/compression.rs6
-rw-r--r--vendor/zip/src/read.rs20
-rw-r--r--vendor/zip/src/result.rs21
-rw-r--r--vendor/zip/src/spec.rs16
-rw-r--r--vendor/zip/src/types.rs91
-rw-r--r--vendor/zip/src/write.rs56
-rw-r--r--vendor/zip/tests/end_to_end.rs2
-rw-r--r--vendor/zip/tests/zip64_large.rs2
-rw-r--r--version2
-rwxr-xr-xx.py3
5841 files changed, 213108 insertions, 91006 deletions
diff --git a/Cargo.lock b/Cargo.lock
index c4bb084d9..ece96826a 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -90,15 +90,6 @@ dependencies = [
[[package]]
name = "ansi_term"
-version = "0.11.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b"
-dependencies = [
- "winapi",
-]
-
-[[package]]
-name = "ansi_term"
version = "0.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2"
@@ -129,6 +120,12 @@ checksum = "8f8cb5d814eb646a863c4f24978cff2880c4be96ad8cde2c0f0678732902e271"
[[package]]
name = "arrayvec"
+version = "0.5.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b"
+
+[[package]]
+name = "arrayvec"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5a2f58b0bb10c380af2b26e57212856b8c9a59e0925b4c20f4a174a49734eaf7"
@@ -173,7 +170,7 @@ dependencies = [
"quote",
"serde",
"syn",
- "toml",
+ "toml 0.5.7",
]
[[package]]
@@ -285,7 +282,7 @@ dependencies = [
"serde_json",
"sha2",
"tar",
- "toml",
+ "toml 0.5.7",
]
[[package]]
@@ -301,7 +298,7 @@ dependencies = [
"indexmap",
"serde",
"serde_json",
- "toml",
+ "toml 0.5.7",
]
[[package]]
@@ -342,7 +339,7 @@ dependencies = [
[[package]]
name = "cargo"
-version = "0.69.1"
+version = "0.70.0"
dependencies = [
"anyhow",
"base64",
@@ -384,7 +381,6 @@ dependencies = [
"os_info",
"pasetors",
"pathdiff",
- "percent-encoding",
"pretty_env_logger",
"rustc-workspace-hack",
"rustfix",
@@ -402,12 +398,13 @@ dependencies = [
"tempfile",
"termcolor",
"time 0.3.17",
+ "toml 0.7.2",
"toml_edit",
"unicode-width",
"unicode-xid",
"url",
"walkdir",
- "winapi",
+ "windows-sys 0.45.0",
]
[[package]]
@@ -436,18 +433,18 @@ name = "cargo-credential-wincred"
version = "0.2.0"
dependencies = [
"cargo-credential",
- "winapi",
+ "windows-sys 0.45.0",
]
[[package]]
name = "cargo-miri"
version = "0.1.0"
dependencies = [
- "cargo_metadata 0.15.0",
+ "cargo_metadata 0.15.3",
"directories",
"rustc-build-sysroot",
"rustc-workspace-hack",
- "rustc_tools_util 0.2.1",
+ "rustc_tools_util",
"rustc_version",
"serde",
"serde_json",
@@ -494,9 +491,9 @@ dependencies = [
"tar",
"termcolor",
"time 0.3.17",
- "toml_edit",
+ "toml 0.7.2",
"url",
- "winapi",
+ "windows-sys 0.45.0",
]
[[package]]
@@ -516,7 +513,7 @@ dependencies = [
"shell-escape",
"tempfile",
"walkdir",
- "winapi",
+ "windows-sys 0.45.0",
]
[[package]]
@@ -534,15 +531,16 @@ dependencies = [
[[package]]
name = "cargo_metadata"
-version = "0.15.0"
+version = "0.15.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3abb7553d5b9b8421c6de7cb02606ff15e0c6eea7d8eadd75ef013fd636bec36"
+checksum = "08a1ec454bc3eead8719cb56e15dbbfecdbc14e4b3a3ae4936cc6e31f5fc0d07"
dependencies = [
"camino",
"cargo-platform 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"semver",
"serde",
"serde_json",
+ "thiserror",
]
[[package]]
@@ -724,8 +722,9 @@ dependencies = [
[[package]]
name = "clippy"
-version = "0.1.68"
+version = "0.1.69"
dependencies = [
+ "clap 4.1.4",
"clippy_lints",
"clippy_utils",
"compiletest_rs",
@@ -739,7 +738,7 @@ dependencies = [
"regex",
"rustc-semver",
"rustc-workspace-hack",
- "rustc_tools_util 0.3.0",
+ "rustc_tools_util",
"semver",
"serde",
"syn",
@@ -747,7 +746,7 @@ dependencies = [
"termize",
"tester",
"tokio",
- "toml",
+ "toml 0.5.7",
"walkdir",
]
@@ -756,7 +755,7 @@ name = "clippy_dev"
version = "0.0.1"
dependencies = [
"aho-corasick",
- "clap 3.2.20",
+ "clap 4.1.4",
"indoc",
"itertools",
"opener",
@@ -766,14 +765,14 @@ dependencies = [
[[package]]
name = "clippy_lints"
-version = "0.1.68"
+version = "0.1.69"
dependencies = [
- "cargo_metadata 0.14.0",
+ "cargo_metadata 0.15.3",
"clippy_utils",
"declare_clippy_lint",
"if_chain",
"itertools",
- "pulldown-cmark 0.9.2",
+ "pulldown-cmark",
"quine-mc_cluskey",
"regex-syntax",
"rustc-semver",
@@ -781,7 +780,7 @@ dependencies = [
"serde",
"serde_json",
"tempfile",
- "toml",
+ "toml 0.5.7",
"unicode-normalization",
"unicode-script",
"url",
@@ -789,9 +788,9 @@ dependencies = [
[[package]]
name = "clippy_utils"
-version = "0.1.68"
+version = "0.1.69"
dependencies = [
- "arrayvec",
+ "arrayvec 0.7.0",
"if_chain",
"itertools",
"rustc-semver",
@@ -846,16 +845,6 @@ dependencies = [
]
[[package]]
-name = "combine"
-version = "4.6.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "35ed6e9d84f0b51a7f52daf1c7d71dd136fd7a3f41a8462b8cdb8c78d920fad4"
-dependencies = [
- "bytes",
- "memchr",
-]
-
-[[package]]
name = "commoncrypto"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -875,9 +864,9 @@ dependencies = [
[[package]]
name = "compiler_builtins"
-version = "0.1.85"
+version = "0.1.87"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "13e81c6cd7ab79f51a0c927d22858d61ad12bd0b3865f0b13ece02a4486aeabb"
+checksum = "f867ce54c09855ccd135ad4a50c777182a0c7af5ff20a8f537617bd648b10d50"
dependencies = [
"cc",
"rustc-std-workspace-core",
@@ -887,15 +876,16 @@ dependencies = [
name = "compiletest"
version = "0.0.0"
dependencies = [
+ "build_helper",
"colored",
"diff",
"getopts",
"glob",
- "lazy_static",
"lazycell",
"libc",
- "miow 0.3.7",
+ "miow 0.5.0",
"miropt-test-tools",
+ "once_cell",
"regex",
"rustfix",
"serde",
@@ -1007,7 +997,7 @@ dependencies = [
[[package]]
name = "crates-io"
-version = "0.35.1"
+version = "0.36.0"
dependencies = [
"anyhow",
"curl",
@@ -1168,7 +1158,7 @@ checksum = "a0afaad2b26fa326569eb264b1363e8ae3357618c43982b3f285f0774ce76b69"
[[package]]
name = "declare_clippy_lint"
-version = "0.1.68"
+version = "0.1.69"
dependencies = [
"itertools",
"quote",
@@ -1217,12 +1207,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "56254986775e3233ffa9c4d7d3faaf6d36a2c09d30b20687e9f88bc8bafc16c8"
[[package]]
-name = "difference"
-version = "2.0.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "524cbf6897b527295dff137cec09ecf3a05f4fddffd7dfcd1585403449e74198"
-
-[[package]]
name = "digest"
version = "0.10.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1379,10 +1363,19 @@ dependencies = [
]
[[package]]
+name = "elsa"
+version = "1.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f74077c3c3aedb99a2683919698285596662518ea13e5eedcf8bdd43b0d0453b"
+dependencies = [
+ "stable_deref_trait",
+]
+
+[[package]]
name = "ena"
-version = "0.14.0"
+version = "0.14.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d7402b94a93c24e742487327a7cd839dc9d36fec9de9fb25b09f2dae459f36c3"
+checksum = "b2e5d13ca2353ab7d0230988629def93914a8c4015f621f9b13ed2955614731d"
dependencies = [
"log",
]
@@ -1452,6 +1445,7 @@ name = "error_index_generator"
version = "0.0.0"
dependencies = [
"mdbook",
+ "rustc_error_codes",
]
[[package]]
@@ -1930,23 +1924,16 @@ dependencies = [
[[package]]
name = "hermit-abi"
-version = "0.2.6"
+version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ee512640fe35acbfb4bb779db6f0d80704c2cacfa2e39b601ef3e3f47d1ae4c7"
+checksum = "856b5cb0902c2b6d65d5fd97dfa30f9b70c7538e770b98eab5ed52d8db923e01"
dependencies = [
"compiler_builtins",
- "libc",
"rustc-std-workspace-alloc",
"rustc-std-workspace-core",
]
[[package]]
-name = "hermit-abi"
-version = "0.3.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fed44880c466736ef9a5c5b5facefb5ed0785676d0c02d612db14e54f0d84286"
-
-[[package]]
name = "hex"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2033,23 +2020,21 @@ checksum = "3c1ad908cc71012b7bea4d0c53ba96a8cba9962f048fa68d143376143d863b7a"
[[package]]
name = "icu_list"
-version = "1.0.0"
+version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c40218275f081c4493f190357c5395647b06734c2dc3dcb41cc099a0f60168b1"
+checksum = "01a65ff0cab77c33c7e165c858eaa6e84a09f1e485dd495d9d0ae61083c6f786"
dependencies = [
"displaydoc",
- "icu_locid",
"icu_provider",
"regex-automata 0.2.0",
"writeable",
- "zerovec",
]
[[package]]
name = "icu_locid"
-version = "1.0.0"
+version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "34b3de5d99a0e275fe6193b9586dbf37364daebc0d39c89b5cf8376a53b789e8"
+checksum = "71d7a98ecb812760b5f077e55a4763edeefa7ccc30d6eb5680a70841ede81928"
dependencies = [
"displaydoc",
"litemap",
@@ -2060,9 +2045,9 @@ dependencies = [
[[package]]
name = "icu_provider"
-version = "1.0.1"
+version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2f911086e3c521a8a824d4f8bfd87769645ced2f07ff913b521c0d793be07100"
+checksum = "a86816c97bc4e613086497f9479f63e120315e056763e8c4435604f98d21d82d"
dependencies = [
"displaydoc",
"icu_locid",
@@ -2076,9 +2061,9 @@ dependencies = [
[[package]]
name = "icu_provider_adapters"
-version = "1.0.0"
+version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "980c71d8a91b246ebbb97847178a4b816eea39d1d550c70ee566384555bb6545"
+checksum = "8e89bf33962b24bb48a4a21330c20c9ff17949338ea376360dd9eda2c209dca1"
dependencies = [
"icu_locid",
"icu_provider",
@@ -2089,9 +2074,9 @@ dependencies = [
[[package]]
name = "icu_provider_macros"
-version = "1.0.0"
+version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "38cf6f5b65cf81f0b4298da647101acbfe6ae0e25263f92bd7a22597e9d6d606"
+checksum = "9ddb07844c2ffc4c28840e799e9e54ff054393cf090740decf25624e9d94b93a"
dependencies = [
"proc-macro2",
"quote",
@@ -2232,7 +2217,7 @@ version = "0.4.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "21b6b32576413a8e69b90e952e4a026476040d81017b80445deda5f2d3921857"
dependencies = [
- "hermit-abi 0.3.1",
+ "hermit-abi 0.3.0",
"io-lifetimes",
"rustix",
"windows-sys 0.45.0",
@@ -2266,9 +2251,9 @@ dependencies = [
[[package]]
name = "jobserver"
-version = "0.1.24"
+version = "0.1.26"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "af25a77299a7f711a01975c35a6a424eb6862092cc2d6c72c4ed6cbc56dfc1fa"
+checksum = "936cfd212a0155903bcbc060e316fb6cc7cbf2e1907329391ebadc1fe0ce77c2"
dependencies = [
"libc",
]
@@ -2321,15 +2306,6 @@ dependencies = [
]
[[package]]
-name = "kstring"
-version = "2.0.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ec3066350882a1cd6d950d055997f379ac37fd39f81cd4d8ed186032eb3c5747"
-dependencies = [
- "static_assertions",
-]
-
-[[package]]
name = "lazy_static"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2343,9 +2319,9 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55"
[[package]]
name = "libc"
-version = "0.2.138"
+version = "0.2.139"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "db6d7e329c562c5dfab7a46a2afabc8b987ab9a4834c9d1ca04dc54c1546cef8"
+checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79"
dependencies = [
"rustc-std-workspace-core",
]
@@ -2466,9 +2442,9 @@ checksum = "f051f77a7c8e6957c0696eac88f26b0117e54f52d3fc682ab19397a8812846a4"
[[package]]
name = "litemap"
-version = "0.6.0"
+version = "0.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f34a3f4798fac63fb48cf277eefa38f94d3443baff555bb98e4f56bc9092368e"
+checksum = "575d8a551c59104b4df91269921e5eab561aa1b77c618dac0414b5d44a4617de"
[[package]]
name = "lld-wrapper"
@@ -2572,13 +2548,13 @@ dependencies = [
"memchr",
"once_cell",
"opener",
- "pulldown-cmark 0.9.2",
+ "pulldown-cmark",
"regex",
"serde",
"serde_json",
"shlex",
"tempfile",
- "toml",
+ "toml 0.5.7",
"topological-sort",
]
@@ -2589,7 +2565,7 @@ dependencies = [
"anyhow",
"handlebars 3.5.5",
"pretty_assertions",
- "pulldown-cmark 0.7.2",
+ "pulldown-cmark",
"same-file",
"serde_json",
"url",
@@ -2725,6 +2701,15 @@ dependencies = [
]
[[package]]
+name = "nom8"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ae01545c9c7fc4486ab7debaf2aad7003ac19431791868fb2e8066df97fad2f8"
+dependencies = [
+ "memchr",
+]
+
+[[package]]
name = "normalize-line-endings"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -3192,14 +3177,14 @@ checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c"
[[package]]
name = "pretty_assertions"
-version = "0.6.1"
+version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3f81e1644e1b54f5a68959a29aa86cde704219254669da328ecfdf6a1f09d427"
+checksum = "a25e9bcb20aa780fd0bb16b72403a9064d6b3f22f026946029acb941a50af755"
dependencies = [
- "ansi_term 0.11.0",
"ctor",
- "difference",
+ "diff",
"output_vt100",
+ "yansi",
]
[[package]]
@@ -3279,17 +3264,6 @@ dependencies = [
[[package]]
name = "pulldown-cmark"
-version = "0.7.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ca36dea94d187597e104a5c8e4b07576a8a45aa5db48a65e12940d3eb7461f55"
-dependencies = [
- "bitflags",
- "memchr",
- "unicase",
-]
-
-[[package]]
-name = "pulldown-cmark"
version = "0.9.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2d9cc634bc78768157b5cbfe988ffcd1dcba95cd2b2f03a88316c08c6d00ed63"
@@ -3504,25 +3478,6 @@ dependencies = [
]
[[package]]
-name = "rls-data"
-version = "0.19.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a58135eb039f3a3279a33779192f0ee78b56f57ae636e25cec83530e41debb99"
-dependencies = [
- "rls-span",
- "serde",
-]
-
-[[package]]
-name = "rls-span"
-version = "0.5.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f0eea58478fc06e15f71b03236612173a1b81e9770314edecfa664375e3e4c86"
-dependencies = [
- "serde",
-]
-
-[[package]]
name = "rust-demangler"
version = "0.0.1"
dependencies = [
@@ -3573,6 +3528,7 @@ dependencies = [
"jemalloc-sys",
"rustc_codegen_ssa",
"rustc_driver",
+ "rustc_driver_impl",
"rustc_smir",
]
@@ -3678,6 +3634,7 @@ name = "rustc_ast"
version = "0.0.0"
dependencies = [
"bitflags",
+ "memchr",
"rustc_data_structures",
"rustc_index",
"rustc_lexer",
@@ -3693,7 +3650,6 @@ dependencies = [
name = "rustc_ast_lowering"
version = "0.0.0"
dependencies = [
- "rustc_arena",
"rustc_ast",
"rustc_ast_pretty",
"rustc_data_structures",
@@ -3702,7 +3658,6 @@ dependencies = [
"rustc_index",
"rustc_macros",
"rustc_middle",
- "rustc_query_system",
"rustc_session",
"rustc_span",
"rustc_target",
@@ -3727,6 +3682,7 @@ dependencies = [
"rustc_session",
"rustc_span",
"rustc_target",
+ "thin-vec",
"tracing",
]
@@ -3736,6 +3692,7 @@ version = "0.0.0"
dependencies = [
"rustc_ast",
"rustc_span",
+ "thin-vec",
]
[[package]]
@@ -3762,7 +3719,6 @@ dependencies = [
"icu_locid",
"icu_provider",
"icu_provider_adapters",
- "litemap",
"zerovec",
]
@@ -3841,11 +3797,12 @@ dependencies = [
"rustc_metadata",
"rustc_middle",
"rustc_query_system",
- "rustc_serialize",
"rustc_session",
"rustc_span",
"rustc_symbol_mangling",
"rustc_target",
+ "serde",
+ "serde_json",
"smallvec",
"tempfile",
"tracing",
@@ -3867,7 +3824,6 @@ dependencies = [
"rustc_arena",
"rustc_ast",
"rustc_attr",
- "rustc_const_eval",
"rustc_data_structures",
"rustc_errors",
"rustc_fs_util",
@@ -3908,7 +3864,6 @@ dependencies = [
"rustc_macros",
"rustc_middle",
"rustc_mir_dataflow",
- "rustc_query_system",
"rustc_session",
"rustc_span",
"rustc_target",
@@ -3921,9 +3876,10 @@ dependencies = [
name = "rustc_data_structures"
version = "0.0.0"
dependencies = [
- "arrayvec",
+ "arrayvec 0.7.0",
"bitflags",
"cfg-if",
+ "elsa",
"ena",
"indexmap",
"jobserver",
@@ -3951,29 +3907,56 @@ dependencies = [
name = "rustc_driver"
version = "0.0.0"
dependencies = [
+ "rustc_driver_impl",
+]
+
+[[package]]
+name = "rustc_driver_impl"
+version = "0.0.0"
+dependencies = [
"libc",
"rustc_ast",
+ "rustc_ast_lowering",
+ "rustc_ast_passes",
"rustc_ast_pretty",
+ "rustc_attr",
+ "rustc_borrowck",
+ "rustc_builtin_macros",
"rustc_codegen_ssa",
+ "rustc_const_eval",
"rustc_data_structures",
"rustc_error_codes",
+ "rustc_error_messages",
"rustc_errors",
+ "rustc_expand",
"rustc_feature",
"rustc_hir",
"rustc_hir_analysis",
"rustc_hir_pretty",
+ "rustc_hir_typeck",
+ "rustc_incremental",
+ "rustc_infer",
"rustc_interface",
"rustc_lint",
"rustc_log",
"rustc_macros",
"rustc_metadata",
"rustc_middle",
+ "rustc_mir_build",
+ "rustc_mir_dataflow",
+ "rustc_monomorphize",
"rustc_parse",
+ "rustc_passes",
"rustc_plugin_impl",
- "rustc_save_analysis",
+ "rustc_privacy",
+ "rustc_query_system",
+ "rustc_resolve",
"rustc_session",
"rustc_span",
+ "rustc_symbol_mangling",
"rustc_target",
+ "rustc_trait_selection",
+ "rustc_ty_utils",
"serde_json",
"tracing",
"winapi",
@@ -4000,7 +3983,6 @@ dependencies = [
"rustc_span",
"tracing",
"unic-langid",
- "writeable",
]
[[package]]
@@ -4096,21 +4078,19 @@ dependencies = [
"rustc_data_structures",
"rustc_errors",
"rustc_feature",
- "rustc_graphviz",
"rustc_hir",
- "rustc_hir_pretty",
"rustc_index",
"rustc_infer",
"rustc_lint",
"rustc_macros",
"rustc_middle",
- "rustc_serialize",
"rustc_session",
"rustc_span",
"rustc_target",
"rustc_trait_selection",
"rustc_type_ir",
"smallvec",
+ "thin-vec",
"tracing",
]
@@ -4167,6 +4147,7 @@ dependencies = [
"rustc_serialize",
"rustc_session",
"rustc_span",
+ "thin-vec",
"tracing",
]
@@ -4174,7 +4155,7 @@ dependencies = [
name = "rustc_index"
version = "0.0.0"
dependencies = [
- "arrayvec",
+ "arrayvec 0.7.0",
"rustc_macros",
"rustc_serialize",
"smallvec",
@@ -4191,7 +4172,6 @@ dependencies = [
"rustc_macros",
"rustc_middle",
"rustc_serialize",
- "rustc_session",
"rustc_span",
"rustc_target",
"smallvec",
@@ -4221,6 +4201,7 @@ dependencies = [
"rustc_hir_analysis",
"rustc_hir_typeck",
"rustc_incremental",
+ "rustc_index",
"rustc_lint",
"rustc_macros",
"rustc_metadata",
@@ -4234,7 +4215,6 @@ dependencies = [
"rustc_privacy",
"rustc_query_impl",
"rustc_resolve",
- "rustc_serialize",
"rustc_session",
"rustc_span",
"rustc_symbol_mangling",
@@ -4332,6 +4312,7 @@ dependencies = [
name = "rustc_metadata"
version = "0.0.0"
dependencies = [
+ "bitflags",
"libloading",
"odht",
"rustc_ast",
@@ -4399,7 +4380,6 @@ dependencies = [
"rustc_apfloat",
"rustc_arena",
"rustc_ast",
- "rustc_attr",
"rustc_data_structures",
"rustc_errors",
"rustc_hir",
@@ -4431,7 +4411,6 @@ dependencies = [
"rustc_macros",
"rustc_middle",
"rustc_serialize",
- "rustc_session",
"rustc_span",
"rustc_target",
"smallvec",
@@ -4562,7 +4541,6 @@ dependencies = [
"rustc_middle",
"rustc_session",
"rustc_span",
- "rustc_trait_selection",
"tracing",
]
@@ -4583,7 +4561,6 @@ dependencies = [
"rustc_serialize",
"rustc_session",
"rustc_span",
- "rustc_target",
"thin-vec",
"tracing",
]
@@ -4617,6 +4594,7 @@ name = "rustc_resolve"
version = "0.0.0"
dependencies = [
"bitflags",
+ "pulldown-cmark",
"rustc_arena",
"rustc_ast",
"rustc_ast_pretty",
@@ -4639,27 +4617,6 @@ dependencies = [
]
[[package]]
-name = "rustc_save_analysis"
-version = "0.0.0"
-dependencies = [
- "rls-data",
- "rls-span",
- "rustc_ast",
- "rustc_ast_pretty",
- "rustc_data_structures",
- "rustc_errors",
- "rustc_hir",
- "rustc_hir_pretty",
- "rustc_lexer",
- "rustc_macros",
- "rustc_middle",
- "rustc_session",
- "rustc_span",
- "serde_json",
- "tracing",
-]
-
-[[package]]
name = "rustc_serialize"
version = "0.0.0"
dependencies = [
@@ -4763,12 +4720,6 @@ dependencies = [
[[package]]
name = "rustc_tools_util"
-version = "0.2.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "598f48ce2a421542b3e64828aa742b687cc1b91d2f96591cfdb7ac5988cd6366"
-
-[[package]]
-name = "rustc_tools_util"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8ba09476327c4b70ccefb6180f046ef588c26a24cf5d269a9feba316eb4f029f"
@@ -4777,6 +4728,7 @@ checksum = "8ba09476327c4b70ccefb6180f046ef588c26a24cf5d269a9feba316eb4f029f"
name = "rustc_trait_selection"
version = "0.0.0"
dependencies = [
+ "itertools",
"rustc_ast",
"rustc_attr",
"rustc_data_structures",
@@ -4784,7 +4736,6 @@ dependencies = [
"rustc_hir",
"rustc_index",
"rustc_infer",
- "rustc_lint_defs",
"rustc_macros",
"rustc_middle",
"rustc_parse_format",
@@ -4806,7 +4757,6 @@ dependencies = [
"chalk-ir",
"chalk-solve",
"rustc_ast",
- "rustc_attr",
"rustc_data_structures",
"rustc_hir",
"rustc_index",
@@ -4878,13 +4828,12 @@ dependencies = [
name = "rustdoc"
version = "0.0.0"
dependencies = [
- "arrayvec",
+ "arrayvec 0.7.0",
"askama",
"expect-test",
"itertools",
"minifier",
"once_cell",
- "pulldown-cmark 0.9.2",
"rayon",
"regex",
"rustdoc-json-types",
@@ -4892,7 +4841,6 @@ dependencies = [
"serde_json",
"smallvec",
"tempfile",
- "thin-vec",
"tracing",
"tracing-subscriber",
"tracing-tree",
@@ -4931,7 +4879,7 @@ dependencies = [
[[package]]
name = "rustfmt-config_proc_macro"
-version = "0.2.0"
+version = "0.3.0"
dependencies = [
"proc-macro2",
"quote",
@@ -4941,7 +4889,7 @@ dependencies = [
[[package]]
name = "rustfmt-nightly"
-version = "1.5.1"
+version = "1.5.2"
dependencies = [
"annotate-snippets",
"anyhow",
@@ -4964,7 +4912,7 @@ dependencies = [
"serde_json",
"term",
"thiserror",
- "toml",
+ "toml 0.5.7",
"unicode-segmentation",
"unicode-width",
"unicode_categories",
@@ -5131,6 +5079,15 @@ dependencies = [
]
[[package]]
+name = "serde_spanned"
+version = "0.6.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0efd8caf556a6cebd3b285caf480045fcc1ac04f6bd786b09a6f11af30c4fcf4"
+dependencies = [
+ "serde",
+]
+
+[[package]]
name = "sha1"
version = "0.10.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -5219,9 +5176,9 @@ checksum = "cc88c725d61fc6c3132893370cac4a0200e3fedf5da8331c570664b1987f5ca2"
[[package]]
name = "snap"
-version = "1.0.1"
+version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "da73c8f77aebc0e40c300b93f0a5f1bece7a248a36eee287d4e095f35c7b7d6e"
+checksum = "5e9f0ab6ef7eb7353d9119c170a436d1bf248eea575ac42d19d12f4e34130831"
[[package]]
name = "snapbox"
@@ -5333,7 +5290,7 @@ dependencies = [
"dlmalloc",
"fortanix-sgx-abi",
"hashbrown 0.12.3",
- "hermit-abi 0.2.6",
+ "hermit-abi 0.3.0",
"libc",
"miniz_oxide",
"object 0.29.0",
@@ -5387,9 +5344,9 @@ dependencies = [
[[package]]
name = "strip-ansi-escapes"
-version = "0.1.0"
+version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9d63676e2abafa709460982ddc02a3bb586b6d15a49b75c212e06edd3933acee"
+checksum = "011cbb39cf7c1f62871aea3cc46e5817b0937b49e9447370c93cacbe93a766d8"
dependencies = [
"vte",
]
@@ -5528,10 +5485,8 @@ dependencies = [
name = "test"
version = "0.0.0"
dependencies = [
- "cfg-if",
"core",
"getopts",
- "libc",
"panic_abort",
"panic_unwind",
"proc_macro",
@@ -5559,9 +5514,9 @@ checksum = "b1141d4d61095b28419e22cb0bbf02755f5e54e0526f97f1e3d1d160e60885fb"
[[package]]
name = "thin-vec"
-version = "0.2.9"
+version = "0.2.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ceb05e71730d396f960f8f3901cdb41be2d339b303e9d7d3a07c5ff0536e671b"
+checksum = "aac81b6fd6beb5884b0cf3321b8117e6e5d47ecb6fc89f414cfdcca8b2fe2dd8"
[[package]]
name = "thiserror"
@@ -5662,9 +5617,9 @@ dependencies = [
[[package]]
name = "tinystr"
-version = "0.7.0"
+version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f8aeafdfd935e4a7fe16a91ab711fa52d54df84f9c8f7ca5837a9d1d902ef4c2"
+checksum = "7ac3f5b6856e931e15e07b478e98c8045239829a65f9156d4fa7e7788197a5ef"
dependencies = [
"displaydoc",
"zerovec",
@@ -5707,25 +5662,36 @@ dependencies = [
]
[[package]]
+name = "toml"
+version = "0.7.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f7afcae9e3f0fe2c370fd4657108972cbb2fa9db1b9f84849cefd80741b01cb6"
+dependencies = [
+ "serde",
+ "serde_spanned",
+ "toml_datetime",
+ "toml_edit",
+]
+
+[[package]]
name = "toml_datetime"
-version = "0.5.0"
+version = "0.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "808b51e57d0ef8f71115d8f3a01e7d3750d01c79cac4b3eda910f4389fdf92fd"
+checksum = "3ab8ed2edee10b50132aed5f331333428b011c99402b5a534154ed15746f9622"
dependencies = [
"serde",
]
[[package]]
name = "toml_edit"
-version = "0.15.0"
+version = "0.19.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b1541ba70885967e662f69d31ab3aeca7b1aaecfcd58679590b893e9239c3646"
+checksum = "5e6a7712b49e1775fb9a7b998de6635b299237f48b404dde71704f2e0e7f37e5"
dependencies = [
- "combine",
"indexmap",
- "itertools",
- "kstring",
+ "nom8",
"serde",
+ "serde_spanned",
"toml_datetime",
]
@@ -5795,7 +5761,7 @@ version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "245da694cc7fc4729f3f418b304cb57789f1bed2a78c575407ab8a23f53cb4d3"
dependencies = [
- "ansi_term 0.12.1",
+ "ansi_term",
"lazy_static",
"matchers",
"parking_lot 0.11.2",
@@ -5814,7 +5780,7 @@ version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3ce989c9962c7f61fe084dd4a230eec784649dfc2392467c790007c3a6e134e7"
dependencies = [
- "ansi_term 0.12.1",
+ "ansi_term",
"atty",
"tracing-core",
"tracing-log",
@@ -5870,7 +5836,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "54ddb6f31025943e2f9d59237f433711c461a43d9415974c3eb3a4902edc1c1f"
dependencies = [
"bstr 1.0.1",
- "cargo_metadata 0.15.0",
+ "cargo_metadata 0.15.3",
"color-eyre",
"colored",
"crossbeam-channel",
@@ -6101,9 +6067,9 @@ checksum = "05e42f7c18b8f902290b009cde6d651262f956c98bc51bca4cd1d511c9cd85c7"
[[package]]
name = "utf8parse"
-version = "0.1.1"
+version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8772a4ccbb4e89959023bc5b7cb8623a795caa7092d99f3aa9501b9484d4557d"
+checksum = "936e4b492acfd135421d8dca4b1aa80a7bfc26e702ef3af710e0752684df5372"
[[package]]
name = "uuid"
@@ -6134,11 +6100,23 @@ checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
[[package]]
name = "vte"
-version = "0.3.3"
+version = "0.10.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4f42f536e22f7fcbb407639765c8fd78707a33109301f834a594758bedd6e8cf"
+checksum = "6cbce692ab4ca2f1f3047fcf732430249c0e971bfdd2b234cf2c47ad93af5983"
dependencies = [
+ "arrayvec 0.5.2",
"utf8parse",
+ "vte_generate_state_changes",
+]
+
+[[package]]
+name = "vte_generate_state_changes"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d257817081c7dffcdbab24b9e62d2def62e2ff7d00b1c20062551e6cccc145ff"
+dependencies = [
+ "proc-macro2",
+ "quote",
]
[[package]]
@@ -6331,9 +6309,9 @@ checksum = "447660ad36a13288b1db4d4248e857b510e8c3a225c822ba4fb748c0aafecffd"
[[package]]
name = "writeable"
-version = "0.5.0"
+version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f8e6ab4f5da1b24daf2c590cfac801bacb27b15b4f050e84eb60149ea726f06b"
+checksum = "92d74a687e3b9a7a129db0a8c82b4d464eb9c36f5a66ca68572a7e5f1cfdb5bc"
[[package]]
name = "xattr"
@@ -6390,9 +6368,9 @@ dependencies = [
[[package]]
name = "yoke"
-version = "0.6.2"
+version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1fe1d55ca72c32d573bfbd5cb2f0ca65a497854c44762957a6d3da96041a5184"
+checksum = "222180af14a6b54ef2c33493c1eff77ae95a3687a21b243e752624006fb8f26e"
dependencies = [
"serde",
"stable_deref_trait",
@@ -6402,9 +6380,9 @@ dependencies = [
[[package]]
name = "yoke-derive"
-version = "0.6.1"
+version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1346e4cd025ae818b88566eac7eb65ab33a994ea55f355c86889af2e7e56b14e"
+checksum = "ca800d73d6b7a7ee54f2608205c98b549fca71c9500c1abcb3abdc7708b4a8cb"
dependencies = [
"proc-macro2",
"quote",
@@ -6441,9 +6419,9 @@ checksum = "c394b5bd0c6f669e7275d9c20aa90ae064cb22e75a1cad54e1b34088034b149f"
[[package]]
name = "zerovec"
-version = "0.9.0"
+version = "0.9.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b9d919a74c17749ccb17beaf6405562e413cd94e98ba52ca1e64bbe7eefbd8b8"
+checksum = "154df60c74c4a844bc04a53cef4fc18a909d3ea07e19f5225eaba86209da3aa6"
dependencies = [
"yoke",
"zerofrom",
@@ -6452,9 +6430,9 @@ dependencies = [
[[package]]
name = "zerovec-derive"
-version = "0.9.0"
+version = "0.9.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "490e5f878c2856225e884c35927e7ea6db3c24cdb7229b72542c7526ad7ed49e"
+checksum = "2154cb6e2a748163354165e22c6a555effb09ca2d16334767bf66bb404f2206e"
dependencies = [
"proc-macro2",
"quote",
diff --git a/README.md b/README.md
index 0eb7c4b26..c424bd12f 100644
--- a/README.md
+++ b/README.md
@@ -1,5 +1,7 @@
# The Rust Programming Language
+[![Rust Community](https://img.shields.io/badge/Rust_Community%20-Join_us-brightgreen?style=plastic&logo=rust)](https://www.rust-lang.org/community)
+
This is the main source code repository for [Rust]. It contains the compiler,
standard library, and documentation.
diff --git a/RELEASES.md b/RELEASES.md
index e2b43690d..b89178a6f 100644
--- a/RELEASES.md
+++ b/RELEASES.md
@@ -1,3 +1,105 @@
+Version 1.69.0 (2023-04-20)
+==========================
+
+<a id="1.69.0-Language"></a>
+
+Language
+--------
+
+- [Deriving built-in traits on packed structs works with `Copy` fields.](https://github.com/rust-lang/rust/pull/104429/)
+- [Stabilize the `cmpxchg16b` target feature on x86 and x86_64.](https://github.com/rust-lang/rust/pull/106774/)
+- [Improve analysis of trait bounds for associated types.](https://github.com/rust-lang/rust/pull/103695/)
+- [Allow associated types to be used as union fields.](https://github.com/rust-lang/rust/pull/106938/)
+- [Allow `Self: Autotrait` bounds on dyn-safe trait methods.](https://github.com/rust-lang/rust/pull/107082/)
+- [Treat `str` as containing `[u8]` for auto trait purposes.](https://github.com/rust-lang/rust/pull/107941/)
+
+<a id="1.69.0-Compiler"></a>
+
+Compiler
+--------
+
+- [Upgrade `*-pc-windows-gnu` on CI to mingw-w64 v10 and GCC 12.2.](https://github.com/rust-lang/rust/pull/100178/)
+- [Rework min_choice algorithm of member constraints.](https://github.com/rust-lang/rust/pull/105300/)
+- [Support `true` and `false` as boolean flags in compiler arguments.](https://github.com/rust-lang/rust/pull/107043/)
+- [Default `repr(C)` enums to `c_int` size.](https://github.com/rust-lang/rust/pull/107592/)
+
+<a id="1.69.0-Libraries"></a>
+
+Libraries
+---------
+
+- [Implement the unstable `DispatchFromDyn` for cell types, allowing downstream experimentation with custom method receivers.](https://github.com/rust-lang/rust/pull/97373/)
+- [Document that `fmt::Arguments::as_str()` may return `Some(_)` in more cases after optimization, subject to change.](https://github.com/rust-lang/rust/pull/106823/)
+- [Implement `AsFd` and `AsRawFd` for `Rc`.](https://github.com/rust-lang/rust/pull/107317/)
+
+<a id="1.69.0-Stabilized-APIs"></a>
+
+Stabilized APIs
+---------------
+
+- [`CStr::from_bytes_until_nul`](https://doc.rust-lang.org/stable/core/ffi/struct.CStr.html#method.from_bytes_until_nul)
+- [`core::ffi::FromBytesUntilNulError`](https://doc.rust-lang.org/stable/core/ffi/struct.FromBytesUntilNulError.html)
+
+These APIs are now stable in const contexts:
+
+- [`SocketAddr::new`](https://doc.rust-lang.org/stable/std/net/enum.SocketAddr.html#method.new)
+- [`SocketAddr::ip`](https://doc.rust-lang.org/stable/std/net/enum.SocketAddr.html#method.ip)
+- [`SocketAddr::port`](https://doc.rust-lang.org/stable/std/net/enum.SocketAddr.html#method.port)
+- [`SocketAddr::is_ipv4`](https://doc.rust-lang.org/stable/std/net/enum.SocketAddr.html#method.is_ipv4)
+- [`SocketAddr::is_ipv6`](https://doc.rust-lang.org/stable/std/net/enum.SocketAddr.html#method.is_ipv6)
+- [`SocketAddrV4::new`](https://doc.rust-lang.org/stable/std/net/struct.SocketAddrV4.html#method.new)
+- [`SocketAddrV4::ip`](https://doc.rust-lang.org/stable/std/net/struct.SocketAddrV4.html#method.ip)
+- [`SocketAddrV4::port`](https://doc.rust-lang.org/stable/std/net/struct.SocketAddrV4.html#method.port)
+- [`SocketAddrV6::new`](https://doc.rust-lang.org/stable/std/net/struct.SocketAddrV6.html#method.new)
+- [`SocketAddrV6::ip`](https://doc.rust-lang.org/stable/std/net/struct.SocketAddrV6.html#method.ip)
+- [`SocketAddrV6::port`](https://doc.rust-lang.org/stable/std/net/struct.SocketAddrV6.html#method.port)
+- [`SocketAddrV6::flowinfo`](https://doc.rust-lang.org/stable/std/net/struct.SocketAddrV6.html#method.flowinfo)
+- [`SocketAddrV6::scope_id`](https://doc.rust-lang.org/stable/std/net/struct.SocketAddrV6.html#method.scope_id)
+
+<a id="1.69.0-Cargo"></a>
+
+Cargo
+-----
+
+- [Cargo now suggests `cargo fix` or `cargo clippy --fix` when compilation warnings are auto-fixable.](https://github.com/rust-lang/cargo/pull/11558/)
+- [Cargo now suggests `cargo add` if you try to install a library crate.](https://github.com/rust-lang/cargo/pull/11410/)
+- [Cargo now sets the `CARGO_BIN_NAME` environment variable also for binary examples.](https://github.com/rust-lang/cargo/pull/11705/)
+
+<a id="1.69.0-Rustdoc"></a>
+
+Rustdoc
+-----
+
+- [Vertically compact trait bound formatting.](https://github.com/rust-lang/rust/pull/102842/)
+- [Only include stable lints in `rustdoc::all` group.](https://github.com/rust-lang/rust/pull/106316/)
+- [Compute maximum Levenshtein distance based on the query.](https://github.com/rust-lang/rust/pull/107141/)
+- [Remove inconsistently-present sidebar tooltips.](https://github.com/rust-lang/rust/pull/107490/)
+- [Search by macro when query ends with `!`.](https://github.com/rust-lang/rust/pull/108143/)
+
+<a id="1.69.0-Compatibility-Notes"></a>
+
+Compatibility Notes
+-------------------
+
+- [The `rust-analysis` component from `rustup` now only contains a warning placeholder.](https://github.com/rust-lang/rust/pull/101841/) This was primarily intended for RLS, and the corresponding `-Zsave-analysis` flag has been removed from the compiler as well.
+- [Unaligned references to packed fields are now a hard error.](https://github.com/rust-lang/rust/pull/102513/) This has been a warning since 1.53, and denied by default with a future-compatibility warning since 1.62.
+- [Update the minimum external LLVM to 14.](https://github.com/rust-lang/rust/pull/107573/)
+- [Cargo now emits errors on invalid characters in a registry token.](https://github.com/rust-lang/cargo/pull/11600/)
+- [When `default-features` is set to false of a workspace dependency, and an inherited dependency of a member has `default-features = true`, Cargo will enable default features of that dependency.](https://github.com/rust-lang/cargo/pull/11409/)
+- [Cargo denies `CARGO_HOME` in the `[env]` configuration table. Cargo itself doesn't pick up this value, but recursive calls to cargo would, which was not intended.](https://github.com/rust-lang/cargo/pull/11644/)
+- [Debuginfo for build dependencies is now off if not explicitly set. This is expected to improve the overall build time.](https://github.com/rust-lang/cargo/pull/11252/)
+
+<a id="1.69.0-Internal-Changes"></a>
+
+Internal Changes
+----------------
+
+These changes do not affect any public interfaces of Rust, but they represent
+significant improvements to the performance or internals of rustc and related
+tools.
+
+- [Move `format_args!()` into AST (and expand it during AST lowering)](https://github.com/rust-lang/rust/pull/106745/)
+
Version 1.68.2 (2023-03-28)
===========================
@@ -94,6 +196,7 @@ Misc
Compatibility Notes
-------------------
+- [Only support Android NDK 25 or newer](https://blog.rust-lang.org/2023/01/09/android-ndk-update-r25.html)
- [Add `SEMICOLON_IN_EXPRESSIONS_FROM_MACROS` to future-incompat report](https://github.com/rust-lang/rust/pull/103418/)
- [Only specify `--target` by default for `-Zgcc-ld=lld` on wasm](https://github.com/rust-lang/rust/pull/101792/)
- [Bump `IMPLIED_BOUNDS_ENTAILMENT` to Deny + ReportNow](https://github.com/rust-lang/rust/pull/106465/)
@@ -148,12 +251,13 @@ Compiler
- [Optimize field ordering by grouping m\*2^n-sized fields with equivalently aligned ones.](https://github.com/rust-lang/rust/pull/102750/)
- [Stabilize native library modifier `verbatim`.](https://github.com/rust-lang/rust/pull/104360/)
-Added and removed targets:
+Added, updated, and removed targets:
- [Add a tier 3 target for PowerPC on AIX](https://github.com/rust-lang/rust/pull/102293/), `powerpc64-ibm-aix`.
- [Add a tier 3 target for the Sony PlayStation 1](https://github.com/rust-lang/rust/pull/102689/), `mipsel-sony-psx`.
- [Add tier 3 `no_std` targets for the QNX Neutrino RTOS](https://github.com/rust-lang/rust/pull/102701/),
`aarch64-unknown-nto-qnx710` and `x86_64-pc-nto-qnx710`.
+- [Promote UEFI targets to tier 2](https://github.com/rust-lang/rust/pull/103933/), `aarch64-unknown-uefi`, `i686-unknown-uefi`, and `x86_64-unknown-uefi`.
- [Remove tier 3 `linuxkernel` targets](https://github.com/rust-lang/rust/pull/104015/) (not used by the actual kernel).
Refer to Rust's [platform support page][platform-support-doc]
@@ -3884,6 +3988,8 @@ Version 1.41.1 (2020-02-27)
* [Always check types of static items][69145]
* [Always check lifetime bounds of `Copy` impls][69145]
* [Fix miscompilation in callers of `Layout::repeat`][69225]
+* [Rust 1.41.0 was announced as the last Rust release with tier 1 or tier 2 support for 32-bit Apple targets][apple-32bit-drop].
+ That announcement did not expect a patch release. 1.41.1 also includes release binaries for these targets.
[69225]: https://github.com/rust-lang/rust/issues/69225
[69145]: https://github.com/rust-lang/rust/pull/69145
@@ -3976,7 +4082,7 @@ Misc
Compatibility Notes
-------------------
-- [As previously announced 1.41.0 will be the last tier 1 release for 32-bit
+- [As previously announced 1.41 will be the last tier 1 release for 32-bit
Apple targets.][apple-32bit-drop] This means that the source code is still
available to build, but the targets are no longer being tested and release
binaries for those platforms will no longer be distributed by the Rust project.
diff --git a/compiler/rustc/Cargo.toml b/compiler/rustc/Cargo.toml
index 27ee3dd2a..41003ad83 100644
--- a/compiler/rustc/Cargo.toml
+++ b/compiler/rustc/Cargo.toml
@@ -5,6 +5,7 @@ edition = "2021"
[dependencies]
rustc_driver = { path = "../rustc_driver" }
+rustc_driver_impl = { path = "../rustc_driver_impl" }
# Make sure rustc_codegen_ssa ends up in the sysroot, because this
# crate is intended to be used by codegen backends, which may not be in-tree.
@@ -20,6 +21,6 @@ features = ['unprefixed_malloc_on_supported_platforms']
[features]
jemalloc = ['jemalloc-sys']
-llvm = ['rustc_driver/llvm']
-max_level_info = ['rustc_driver/max_level_info']
-rustc_use_parallel_compiler = ['rustc_driver/rustc_use_parallel_compiler']
+llvm = ['rustc_driver_impl/llvm']
+max_level_info = ['rustc_driver_impl/max_level_info']
+rustc_use_parallel_compiler = ['rustc_driver_impl/rustc_use_parallel_compiler']
diff --git a/compiler/rustc_abi/src/layout.rs b/compiler/rustc_abi/src/layout.rs
index 9c2cf58ef..54858b520 100644
--- a/compiler/rustc_abi/src/layout.rs
+++ b/compiler/rustc_abi/src/layout.rs
@@ -1,11 +1,5 @@
use super::*;
-use std::{
- borrow::Borrow,
- cmp,
- fmt::Debug,
- iter,
- ops::{Bound, Deref},
-};
+use std::{borrow::Borrow, cmp, iter, ops::Bound};
#[cfg(feature = "randomize")]
use rand::{seq::SliceRandom, SeedableRng};
@@ -33,7 +27,7 @@ pub trait LayoutCalculator {
fn delay_bug(&self, txt: &str);
fn current_data_layout(&self) -> Self::TargetDataLayoutRef;
- fn scalar_pair<V: Idx>(&self, a: Scalar, b: Scalar) -> LayoutS<V> {
+ fn scalar_pair(&self, a: Scalar, b: Scalar) -> LayoutS {
let dl = self.current_data_layout();
let dl = dl.borrow();
let b_align = b.align(dl);
@@ -49,7 +43,7 @@ pub trait LayoutCalculator {
.max_by_key(|niche| niche.available(dl));
LayoutS {
- variants: Variants::Single { index: V::new(0) },
+ variants: Variants::Single { index: VariantIdx::new(0) },
fields: FieldsShape::Arbitrary {
offsets: vec![Size::ZERO, b_offset],
memory_index: vec![0, 1],
@@ -61,13 +55,13 @@ pub trait LayoutCalculator {
}
}
- fn univariant<'a, V: Idx, F: Deref<Target = &'a LayoutS<V>> + Debug>(
+ fn univariant(
&self,
dl: &TargetDataLayout,
- fields: &[F],
+ fields: &[Layout<'_>],
repr: &ReprOptions,
kind: StructKind,
- ) -> Option<LayoutS<V>> {
+ ) -> Option<LayoutS> {
let pack = repr.pack;
let mut align = if pack.is_some() { dl.i8_align } else { dl.aggregate_align };
let mut inverse_memory_index: Vec<u32> = (0..fields.len() as u32).collect();
@@ -76,17 +70,17 @@ pub trait LayoutCalculator {
let end =
if let StructKind::MaybeUnsized = kind { fields.len() - 1 } else { fields.len() };
let optimizing = &mut inverse_memory_index[..end];
- let effective_field_align = |f: &F| {
+ let effective_field_align = |layout: Layout<'_>| {
if let Some(pack) = pack {
// return the packed alignment in bytes
- f.align.abi.min(pack).bytes()
+ layout.align().abi.min(pack).bytes()
} else {
// returns log2(effective-align).
// This is ok since `pack` applies to all fields equally.
// The calculation assumes that size is an integer multiple of align, except for ZSTs.
//
// group [u8; 4] with align-4 or [u8; 6] with align-2 fields
- f.align.abi.bytes().max(f.size.bytes()).trailing_zeros() as u64
+ layout.align().abi.bytes().max(layout.size().bytes()).trailing_zeros() as u64
}
};
@@ -111,9 +105,9 @@ pub trait LayoutCalculator {
// Place ZSTs first to avoid "interesting offsets",
// especially with only one or two non-ZST fields.
// Then place largest alignments first, largest niches within an alignment group last
- let f = &fields[x as usize];
- let niche_size = f.largest_niche.map_or(0, |n| n.available(dl));
- (!f.is_zst(), cmp::Reverse(effective_field_align(f)), niche_size)
+ let f = fields[x as usize];
+ let niche_size = f.largest_niche().map_or(0, |n| n.available(dl));
+ (!f.0.is_zst(), cmp::Reverse(effective_field_align(f)), niche_size)
});
}
@@ -123,8 +117,8 @@ pub trait LayoutCalculator {
// And put the largest niche in an alignment group at the end
// so it can be used as discriminant in jagged enums
optimizing.sort_by_key(|&x| {
- let f = &fields[x as usize];
- let niche_size = f.largest_niche.map_or(0, |n| n.available(dl));
+ let f = fields[x as usize];
+ let niche_size = f.largest_niche().map_or(0, |n| n.available(dl));
(effective_field_align(f), niche_size)
});
}
@@ -160,15 +154,15 @@ pub trait LayoutCalculator {
));
}
- if field.is_unsized() {
+ if field.0.is_unsized() {
sized = false;
}
// Invariant: offset < dl.obj_size_bound() <= 1<<61
let field_align = if let Some(pack) = pack {
- field.align.min(AbiAndPrefAlign::new(pack))
+ field.align().min(AbiAndPrefAlign::new(pack))
} else {
- field.align
+ field.align()
};
offset = offset.align_to(field_align.abi);
align = align.max(field_align);
@@ -176,7 +170,7 @@ pub trait LayoutCalculator {
debug!("univariant offset: {:?} field: {:#?}", offset, field);
offsets[i as usize] = offset;
- if let Some(mut niche) = field.largest_niche {
+ if let Some(mut niche) = field.largest_niche() {
let available = niche.available(dl);
if available > largest_niche_available {
largest_niche_available = available;
@@ -185,7 +179,7 @@ pub trait LayoutCalculator {
}
}
- offset = offset.checked_add(field.size, dl)?;
+ offset = offset.checked_add(field.size(), dl)?;
}
if let Some(repr_align) = repr.align {
align = align.max(AbiAndPrefAlign::new(repr_align));
@@ -205,24 +199,26 @@ pub trait LayoutCalculator {
// Unpack newtype ABIs and find scalar pairs.
if sized && size.bytes() > 0 {
// All other fields must be ZSTs.
- let mut non_zst_fields = fields.iter().enumerate().filter(|&(_, f)| !f.is_zst());
+ let mut non_zst_fields = fields.iter().enumerate().filter(|&(_, f)| !f.0.is_zst());
match (non_zst_fields.next(), non_zst_fields.next(), non_zst_fields.next()) {
// We have exactly one non-ZST field.
(Some((i, field)), None, None) => {
// Field fills the struct and it has a scalar or scalar pair ABI.
- if offsets[i].bytes() == 0 && align.abi == field.align.abi && size == field.size
+ if offsets[i].bytes() == 0
+ && align.abi == field.align().abi
+ && size == field.size()
{
- match field.abi {
+ match field.abi() {
// 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;
+ abi = field.abi();
}
// But scalar pairs are Rust-specific and get
// treated as aggregates by C ABIs anyway.
Abi::ScalarPair(..) => {
- abi = field.abi;
+ abi = field.abi();
}
_ => {}
}
@@ -231,7 +227,7 @@ pub trait LayoutCalculator {
// Two non-ZST fields, and they're both scalars.
(Some((i, a)), Some((j, b)), None) => {
- match (a.abi, b.abi) {
+ match (a.abi(), b.abi()) {
(Abi::Scalar(a), Abi::Scalar(b)) => {
// Order by the memory placement, not source order.
let ((i, a), (j, b)) = if offsets[i] < offsets[j] {
@@ -239,7 +235,7 @@ pub trait LayoutCalculator {
} else {
((j, b), (i, a))
};
- let pair = self.scalar_pair::<V>(a, b);
+ 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]);
@@ -264,11 +260,11 @@ pub trait LayoutCalculator {
_ => {}
}
}
- if fields.iter().any(|f| f.abi.is_uninhabited()) {
+ if fields.iter().any(|f| f.abi().is_uninhabited()) {
abi = Abi::Uninhabited;
}
Some(LayoutS {
- variants: Variants::Single { index: V::new(0) },
+ variants: Variants::Single { index: VariantIdx::new(0) },
fields: FieldsShape::Arbitrary { offsets, memory_index },
abi,
largest_niche,
@@ -277,11 +273,11 @@ pub trait LayoutCalculator {
})
}
- fn layout_of_never_type<V: Idx>(&self) -> LayoutS<V> {
+ fn layout_of_never_type(&self) -> LayoutS {
let dl = self.current_data_layout();
let dl = dl.borrow();
LayoutS {
- variants: Variants::Single { index: V::new(0) },
+ variants: Variants::Single { index: VariantIdx::new(0) },
fields: FieldsShape::Primitive,
abi: Abi::Uninhabited,
largest_niche: None,
@@ -290,18 +286,18 @@ pub trait LayoutCalculator {
}
}
- fn layout_of_struct_or_enum<'a, V: Idx, F: Deref<Target = &'a LayoutS<V>> + Debug>(
+ fn layout_of_struct_or_enum(
&self,
repr: &ReprOptions,
- variants: &IndexVec<V, Vec<F>>,
+ variants: &IndexVec<VariantIdx, Vec<Layout<'_>>>,
is_enum: bool,
is_unsafe_cell: bool,
scalar_valid_range: (Bound<u128>, Bound<u128>),
discr_range_of_repr: impl Fn(i128, i128) -> (Integer, bool),
- discriminants: impl Iterator<Item = (V, i128)>,
+ discriminants: impl Iterator<Item = (VariantIdx, i128)>,
niche_optimize_enum: bool,
always_sized: bool,
- ) -> Option<LayoutS<V>> {
+ ) -> Option<LayoutS> {
let dl = self.current_data_layout();
let dl = dl.borrow();
@@ -316,9 +312,9 @@ pub trait LayoutCalculator {
// but *not* an encoding of the discriminant (e.g., a tag value).
// See issue #49298 for more details on the need to leave space
// for non-ZST uninhabited data (mostly partial initialization).
- let absent = |fields: &[F]| {
- let uninhabited = fields.iter().any(|f| f.abi.is_uninhabited());
- let is_zst = fields.iter().all(|f| f.is_zst());
+ let absent = |fields: &[Layout<'_>]| {
+ let uninhabited = fields.iter().any(|f| f.abi().is_uninhabited());
+ let is_zst = fields.iter().all(|f| f.0.is_zst());
uninhabited && is_zst
};
let (present_first, present_second) = {
@@ -335,7 +331,7 @@ pub trait LayoutCalculator {
}
// If it's a struct, still compute a layout so that we can still compute the
// field offsets.
- None => V::new(0),
+ None => VariantIdx::new(0),
};
let is_struct = !is_enum ||
@@ -439,12 +435,12 @@ pub trait LayoutCalculator {
// variant layouts, so we can't store them in the
// overall LayoutS. Store the overall LayoutS
// and the variant LayoutSs here until then.
- struct TmpLayout<V: Idx> {
- layout: LayoutS<V>,
- variants: IndexVec<V, LayoutS<V>>,
+ struct TmpLayout {
+ layout: LayoutS,
+ variants: IndexVec<VariantIdx, LayoutS>,
}
- let calculate_niche_filling_layout = || -> Option<TmpLayout<V>> {
+ let calculate_niche_filling_layout = || -> Option<TmpLayout> {
if niche_optimize_enum {
return None;
}
@@ -464,15 +460,16 @@ pub trait LayoutCalculator {
Some(st)
})
- .collect::<Option<IndexVec<V, _>>>()?;
+ .collect::<Option<IndexVec<VariantIdx, _>>>()?;
let largest_variant_index = variant_layouts
.iter_enumerated()
.max_by_key(|(_i, layout)| layout.size.bytes())
.map(|(i, _layout)| i)?;
- let all_indices = (0..=variants.len() - 1).map(V::new);
- let needs_disc = |index: V| index != largest_variant_index && !absent(&variants[index]);
+ let all_indices = (0..=variants.len() - 1).map(VariantIdx::new);
+ let needs_disc =
+ |index: VariantIdx| index != largest_variant_index && !absent(&variants[index]);
let niche_variants = all_indices.clone().find(|v| needs_disc(*v)).unwrap().index()
..=all_indices.rev().find(|v| needs_disc(*v)).unwrap().index();
@@ -482,7 +479,7 @@ pub trait LayoutCalculator {
let (field_index, niche, (niche_start, niche_scalar)) = variants[largest_variant_index]
.iter()
.enumerate()
- .filter_map(|(j, field)| Some((j, field.largest_niche?)))
+ .filter_map(|(j, field)| Some((j, field.largest_niche()?)))
.max_by_key(|(_, niche)| niche.available(dl))
.and_then(|(j, niche)| Some((j, niche, niche.reserve(dl, count)?)))?;
let niche_offset =
@@ -514,7 +511,7 @@ pub trait LayoutCalculator {
match layout.fields {
FieldsShape::Arbitrary { ref mut offsets, .. } => {
for (j, offset) in offsets.iter_mut().enumerate() {
- if !variants[i][j].is_zst() {
+ if !variants[i][j].0.is_zst() {
*offset += this_offset;
}
}
@@ -572,8 +569,8 @@ pub trait LayoutCalculator {
tag: niche_scalar,
tag_encoding: TagEncoding::Niche {
untagged_variant: largest_variant_index,
- niche_variants: (V::new(*niche_variants.start())
- ..=V::new(*niche_variants.end())),
+ niche_variants: (VariantIdx::new(*niche_variants.start())
+ ..=VariantIdx::new(*niche_variants.end())),
niche_start,
},
tag_field: 0,
@@ -598,7 +595,7 @@ pub trait LayoutCalculator {
let discr_type = repr.discr_type();
let bits = Integer::from_attr(dl, discr_type).size().bits();
for (i, mut val) in discriminants {
- if variants[i].iter().any(|f| f.abi.is_uninhabited()) {
+ if variants[i].iter().any(|f| f.abi().is_uninhabited()) {
continue;
}
if discr_type.is_signed() {
@@ -636,7 +633,7 @@ pub trait LayoutCalculator {
if repr.c() {
for fields in variants {
for field in fields {
- prefix_align = prefix_align.max(field.align.abi);
+ prefix_align = prefix_align.max(field.align().abi);
}
}
}
@@ -655,8 +652,8 @@ pub trait LayoutCalculator {
// Find the first field we can't move later
// to make room for a larger discriminant.
for field in st.fields.index_by_increasing_offset().map(|j| &field_layouts[j]) {
- if !field.is_zst() || field.align.abi.bytes() != 1 {
- start_align = start_align.min(field.align.abi);
+ if !field.0.is_zst() || field.align().abi.bytes() != 1 {
+ start_align = start_align.min(field.align().abi);
break;
}
}
@@ -664,7 +661,7 @@ pub trait LayoutCalculator {
align = align.max(st.align);
Some(st)
})
- .collect::<Option<IndexVec<V, _>>>()?;
+ .collect::<Option<IndexVec<VariantIdx, _>>>()?;
// Align the maximum variant size to the largest alignment.
size = size.align_to(align.abi);
@@ -759,7 +756,7 @@ pub trait LayoutCalculator {
let FieldsShape::Arbitrary { ref offsets, .. } = layout_variant.fields else {
panic!();
};
- let mut fields = iter::zip(field_layouts, offsets).filter(|p| !p.0.is_zst());
+ let mut fields = iter::zip(field_layouts, offsets).filter(|p| !p.0.0.is_zst());
let (field, offset) = match (fields.next(), fields.next()) {
(None, None) => {
common_prim_initialized_in_all_variants = false;
@@ -771,7 +768,7 @@ pub trait LayoutCalculator {
break;
}
};
- let prim = match field.abi {
+ let prim = match field.abi() {
Abi::Scalar(scalar) => {
common_prim_initialized_in_all_variants &=
matches!(scalar, Scalar::Initialized { .. });
@@ -802,7 +799,7 @@ pub trait LayoutCalculator {
// Common prim might be uninit.
Scalar::Union { value: prim }
};
- let pair = self.scalar_pair::<V>(tag, prim_scalar);
+ let pair = self.scalar_pair(tag, prim_scalar);
let pair_offsets = match pair.fields {
FieldsShape::Arbitrary { ref offsets, ref memory_index } => {
assert_eq!(memory_index, &[0, 1]);
@@ -862,9 +859,8 @@ pub trait LayoutCalculator {
// pick the layout with the larger niche; otherwise,
// pick tagged as it has simpler codegen.
use cmp::Ordering::*;
- let niche_size = |tmp_l: &TmpLayout<V>| {
- tmp_l.layout.largest_niche.map_or(0, |n| n.available(dl))
- };
+ let niche_size =
+ |tmp_l: &TmpLayout| tmp_l.layout.largest_niche.map_or(0, |n| n.available(dl));
match (tl.layout.size.cmp(&nl.layout.size), niche_size(&tl).cmp(&niche_size(&nl))) {
(Greater, _) => nl,
(Equal, Less) => nl,
@@ -884,11 +880,11 @@ pub trait LayoutCalculator {
Some(best_layout.layout)
}
- fn layout_of_union<'a, V: Idx, F: Deref<Target = &'a LayoutS<V>> + Debug>(
+ fn layout_of_union(
&self,
repr: &ReprOptions,
- variants: &IndexVec<V, Vec<F>>,
- ) -> Option<LayoutS<V>> {
+ variants: &IndexVec<VariantIdx, Vec<Layout<'_>>>,
+ ) -> Option<LayoutS> {
let dl = self.current_data_layout();
let dl = dl.borrow();
let mut align = if repr.pack.is_some() { dl.i8_align } else { dl.aggregate_align };
@@ -900,15 +896,15 @@ pub trait LayoutCalculator {
let optimize = !repr.inhibit_union_abi_opt();
let mut size = Size::ZERO;
let mut abi = Abi::Aggregate { sized: true };
- let index = V::new(0);
+ let index = VariantIdx::new(0);
for field in &variants[index] {
- assert!(field.is_sized());
- align = align.max(field.align);
+ assert!(field.0.is_sized());
+ align = align.max(field.align());
// If all non-ZST fields have the same ABI, forward this ABI
- if optimize && !field.is_zst() {
+ if optimize && !field.0.is_zst() {
// Discard valid range information and allow undef
- let field_abi = match field.abi {
+ let field_abi = match field.abi() {
Abi::Scalar(x) => Abi::Scalar(x.to_union()),
Abi::ScalarPair(x, y) => Abi::ScalarPair(x.to_union(), y.to_union()),
Abi::Vector { element: x, count } => {
@@ -926,7 +922,7 @@ pub trait LayoutCalculator {
}
}
- size = cmp::max(size, field.size);
+ size = cmp::max(size, field.size());
}
if let Some(pack) = repr.pack {
diff --git a/compiler/rustc_abi/src/lib.rs b/compiler/rustc_abi/src/lib.rs
index f4cb459f3..39574ca55 100644
--- a/compiler/rustc_abi/src/lib.rs
+++ b/compiler/rustc_abi/src/lib.rs
@@ -8,6 +8,7 @@ use std::ops::{Add, AddAssign, Mul, RangeInclusive, Sub};
use std::str::FromStr;
use bitflags::bitflags;
+use rustc_data_structures::intern::Interned;
#[cfg(feature = "nightly")]
use rustc_data_structures::stable_hasher::StableOrd;
use rustc_index::vec::{Idx, IndexVec};
@@ -170,7 +171,9 @@ pub struct TargetDataLayout {
pub instruction_address_space: AddressSpace,
- /// Minimum size of #[repr(C)] enums (default I32 bits)
+ /// Minimum size of #[repr(C)] enums (default c_int::BITS, usually 32)
+ /// Note: This isn't in LLVM's data layout string, it is `short_enum`
+ /// so the only valid spec for LLVM is c_int::BITS or 8
pub c_enum_min_size: Integer,
}
@@ -267,6 +270,9 @@ impl TargetDataLayout {
["a", ref a @ ..] => dl.aggregate_align = align(a, "a")?,
["f32", ref a @ ..] => dl.f32_align = align(a, "f32")?,
["f64", ref a @ ..] => dl.f64_align = align(a, "f64")?,
+ // FIXME(erikdesjardins): we should be parsing nonzero address spaces
+ // this will require replacing TargetDataLayout::{pointer_size,pointer_align}
+ // with e.g. `fn pointer_size_in(AddressSpace)`
[p @ "p", s, ref a @ ..] | [p @ "p0", s, ref a @ ..] => {
dl.pointer_size = size(s, p)?;
dl.pointer_align = align(a, p)?;
@@ -861,7 +867,7 @@ pub enum Primitive {
Int(Integer, bool),
F32,
F64,
- Pointer,
+ Pointer(AddressSpace),
}
impl Primitive {
@@ -872,7 +878,10 @@ impl Primitive {
Int(i, _) => i.size(),
F32 => Size::from_bits(32),
F64 => Size::from_bits(64),
- Pointer => dl.pointer_size,
+ // FIXME(erikdesjardins): ignoring address space is technically wrong, pointers in
+ // different address spaces can have different sizes
+ // (but TargetDataLayout doesn't currently parse that part of the DL string)
+ Pointer(_) => dl.pointer_size,
}
}
@@ -883,26 +892,12 @@ impl Primitive {
Int(i, _) => i.align(dl),
F32 => dl.f32_align,
F64 => dl.f64_align,
- Pointer => dl.pointer_align,
+ // FIXME(erikdesjardins): ignoring address space is technically wrong, pointers in
+ // different address spaces can have different alignments
+ // (but TargetDataLayout doesn't currently parse that part of the DL string)
+ Pointer(_) => dl.pointer_align,
}
}
-
- // FIXME(eddyb) remove, it's trivial thanks to `matches!`.
- #[inline]
- pub fn is_float(self) -> bool {
- matches!(self, F32 | F64)
- }
-
- // FIXME(eddyb) remove, it's completely unused.
- #[inline]
- pub fn is_int(self) -> bool {
- matches!(self, Int(..))
- }
-
- #[inline]
- pub fn is_ptr(self) -> bool {
- matches!(self, Pointer)
- }
}
/// Inclusive wrap-around range of valid values, that is, if
@@ -1188,7 +1183,8 @@ impl FieldsShape {
/// An identifier that specifies the address space that some operation
/// should operate on. Special address spaces have an effect on code generation,
/// depending on the target and the address spaces it implements.
-#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
+#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
+#[cfg_attr(feature = "nightly", derive(HashStable_Generic))]
pub struct AddressSpace(pub u32);
impl AddressSpace {
@@ -1257,9 +1253,9 @@ impl Abi {
#[derive(PartialEq, Eq, Hash, Clone, Debug)]
#[cfg_attr(feature = "nightly", derive(HashStable_Generic))]
-pub enum Variants<V: Idx> {
+pub enum Variants {
/// Single enum variants, structs/tuples, unions, and all non-ADTs.
- Single { index: V },
+ Single { index: VariantIdx },
/// Enum-likes with more than one inhabited variant: each variant comes with
/// a *discriminant* (usually the same as the variant index but the user can
@@ -1269,15 +1265,15 @@ pub enum Variants<V: Idx> {
/// For enums, the tag is the sole field of the layout.
Multiple {
tag: Scalar,
- tag_encoding: TagEncoding<V>,
+ tag_encoding: TagEncoding,
tag_field: usize,
- variants: IndexVec<V, LayoutS<V>>,
+ variants: IndexVec<VariantIdx, LayoutS>,
},
}
#[derive(PartialEq, Eq, Hash, Clone, Debug)]
#[cfg_attr(feature = "nightly", derive(HashStable_Generic))]
-pub enum TagEncoding<V: Idx> {
+pub enum TagEncoding {
/// The tag directly stores the discriminant, but possibly with a smaller layout
/// (so converting the tag to the discriminant can require sign extension).
Direct,
@@ -1292,7 +1288,11 @@ pub enum TagEncoding<V: Idx> {
/// For example, `Option<(usize, &T)>` is represented such that
/// `None` has a null pointer for the second tuple field, and
/// `Some` is the identity function (with a non-null reference).
- Niche { untagged_variant: V, niche_variants: RangeInclusive<V>, niche_start: u128 },
+ Niche {
+ untagged_variant: VariantIdx,
+ niche_variants: RangeInclusive<VariantIdx>,
+ niche_start: u128,
+ },
}
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
@@ -1379,9 +1379,14 @@ impl Niche {
}
}
+rustc_index::newtype_index! {
+ #[derive(HashStable_Generic)]
+ pub struct VariantIdx {}
+}
+
#[derive(PartialEq, Eq, Hash, Clone)]
#[cfg_attr(feature = "nightly", derive(HashStable_Generic))]
-pub struct LayoutS<V: Idx> {
+pub struct LayoutS {
/// Says where the fields are located within the layout.
pub fields: FieldsShape,
@@ -1392,7 +1397,7 @@ pub struct LayoutS<V: Idx> {
///
/// To access all fields of this layout, both `fields` and the fields of the active variant
/// must be taken into account.
- pub variants: Variants<V>,
+ pub variants: Variants,
/// The `abi` defines how this data is passed between functions, and it defines
/// value restrictions via `valid_range`.
@@ -1411,13 +1416,13 @@ pub struct LayoutS<V: Idx> {
pub size: Size,
}
-impl<V: Idx> LayoutS<V> {
+impl LayoutS {
pub fn scalar<C: HasDataLayout>(cx: &C, scalar: Scalar) -> Self {
let largest_niche = Niche::from_scalar(cx, Size::ZERO, scalar);
let size = scalar.size(cx);
let align = scalar.align(cx);
LayoutS {
- variants: Variants::Single { index: V::new(0) },
+ variants: Variants::Single { index: VariantIdx::new(0) },
fields: FieldsShape::Primitive,
abi: Abi::Scalar(scalar),
largest_niche,
@@ -1427,7 +1432,7 @@ impl<V: Idx> LayoutS<V> {
}
}
-impl<V: Idx> fmt::Debug for LayoutS<V> {
+impl fmt::Debug for LayoutS {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
// This is how `Layout` used to print before it become
// `Interned<LayoutS>`. We print it like this to avoid having to update
@@ -1444,42 +1449,63 @@ impl<V: Idx> fmt::Debug for LayoutS<V> {
}
}
-#[derive(Copy, Clone, PartialEq, Eq, Debug)]
-pub enum PointerKind {
- /// Most general case, we know no restrictions to tell LLVM.
- SharedMutable,
+#[derive(Copy, Clone, PartialEq, Eq, Hash, HashStable_Generic)]
+#[rustc_pass_by_value]
+pub struct Layout<'a>(pub Interned<'a, LayoutS>);
+
+impl<'a> fmt::Debug for Layout<'a> {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ // See comment on `<LayoutS as Debug>::fmt` above.
+ self.0.0.fmt(f)
+ }
+}
- /// `&T` where `T` contains no `UnsafeCell`, is `dereferenceable`, `noalias` and `readonly`.
- Frozen,
+impl<'a> Layout<'a> {
+ pub fn fields(self) -> &'a FieldsShape {
+ &self.0.0.fields
+ }
- /// `&mut T` which is `dereferenceable` and `noalias` but not `readonly`.
- UniqueBorrowed,
+ pub fn variants(self) -> &'a Variants {
+ &self.0.0.variants
+ }
- /// `&mut !Unpin`, which is `dereferenceable` but neither `noalias` nor `readonly`.
- UniqueBorrowedPinned,
+ pub fn abi(self) -> Abi {
+ self.0.0.abi
+ }
+
+ pub fn largest_niche(self) -> Option<Niche> {
+ self.0.0.largest_niche
+ }
+
+ pub fn align(self) -> AbiAndPrefAlign {
+ self.0.0.align
+ }
- /// `Box<T>`, which is `noalias` (even on return types, unlike the above) but neither `readonly`
- /// nor `dereferenceable`.
- UniqueOwned,
+ pub fn size(self) -> Size {
+ self.0.0.size
+ }
+}
+
+#[derive(Copy, Clone, PartialEq, Eq, Debug)]
+pub enum PointerKind {
+ /// Shared reference. `frozen` indicates the absence of any `UnsafeCell`.
+ SharedRef { frozen: bool },
+ /// Mutable reference. `unpin` indicates the absence of any pinned data.
+ MutableRef { unpin: bool },
+ /// Box. `unpin` indicates the absence of any pinned data.
+ Box { unpin: bool },
}
+/// Note that this information is advisory only, and backends are free to ignore it.
+/// It can only be used to encode potential optimizations, but no critical information.
#[derive(Copy, Clone, Debug)]
pub struct PointeeInfo {
pub size: Size,
pub align: Align,
pub safe: Option<PointerKind>,
- pub address_space: AddressSpace,
-}
-
-/// Used in `might_permit_raw_init` to indicate the kind of initialisation
-/// that is checked to be valid
-#[derive(Copy, Clone, Debug, PartialEq, Eq)]
-pub enum InitKind {
- Zero,
- UninitMitigated0x01Fill,
}
-impl<V: Idx> LayoutS<V> {
+impl LayoutS {
/// Returns `true` if the layout corresponds to an unsized type.
pub fn is_unsized(&self) -> bool {
self.abi.is_unsized()
diff --git a/compiler/rustc_ast/Cargo.toml b/compiler/rustc_ast/Cargo.toml
index 9253b7e68..f0632ac92 100644
--- a/compiler/rustc_ast/Cargo.toml
+++ b/compiler/rustc_ast/Cargo.toml
@@ -7,6 +7,7 @@ edition = "2021"
[dependencies]
bitflags = "1.2.1"
+memchr = "2.5.0"
rustc_data_structures = { path = "../rustc_data_structures" }
rustc_index = { path = "../rustc_index" }
rustc_lexer = { path = "../rustc_lexer" }
@@ -14,5 +15,5 @@ rustc_macros = { path = "../rustc_macros" }
rustc_serialize = { path = "../rustc_serialize" }
rustc_span = { path = "../rustc_span" }
smallvec = { version = "1.8.1", features = ["union", "may_dangle"] }
-thin-vec = "0.2.9"
+thin-vec = "0.2.12"
tracing = "0.1"
diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs
index 9317579f7..03c375c46 100644
--- a/compiler/rustc_ast/src/ast.rs
+++ b/compiler/rustc_ast/src/ast.rs
@@ -18,6 +18,7 @@
//! - [`Attribute`]: Metadata associated with item.
//! - [`UnOp`], [`BinOp`], and [`BinOpKind`]: Unary and binary operators.
+pub use crate::format::*;
pub use crate::util::parser::ExprPrecedence;
pub use GenericArgs::*;
pub use UnsafeSource::*;
@@ -208,7 +209,7 @@ pub struct AngleBracketedArgs {
/// The overall span.
pub span: Span,
/// The comma separated parts in the `<...>`.
- pub args: Vec<AngleBracketedArg>,
+ pub args: ThinVec<AngleBracketedArg>,
}
/// Either an argument for a parameter e.g., `'a`, `Vec<u8>`, `0`,
@@ -252,7 +253,7 @@ pub struct ParenthesizedArgs {
pub span: Span,
/// `(A, B)`
- pub inputs: Vec<P<Ty>>,
+ pub inputs: ThinVec<P<Ty>>,
/// ```text
/// Foo(A, B) -> C
@@ -383,7 +384,7 @@ impl GenericParam {
/// a function, enum, trait, etc.
#[derive(Clone, Encodable, Decodable, Debug)]
pub struct Generics {
- pub params: Vec<GenericParam>,
+ pub params: ThinVec<GenericParam>,
pub where_clause: WhereClause,
pub span: Span,
}
@@ -391,7 +392,7 @@ pub struct Generics {
impl Default for Generics {
/// Creates an instance of `Generics`.
fn default() -> Generics {
- Generics { params: Vec::new(), where_clause: Default::default(), span: DUMMY_SP }
+ Generics { params: ThinVec::new(), where_clause: Default::default(), span: DUMMY_SP }
}
}
@@ -402,13 +403,13 @@ pub struct WhereClause {
/// if we parsed no predicates (e.g. `struct Foo where {}`).
/// This allows us to pretty-print accurately.
pub has_where_token: bool,
- pub predicates: Vec<WherePredicate>,
+ pub predicates: ThinVec<WherePredicate>,
pub span: Span,
}
impl Default for WhereClause {
fn default() -> WhereClause {
- WhereClause { has_where_token: false, predicates: Vec::new(), span: DUMMY_SP }
+ WhereClause { has_where_token: false, predicates: ThinVec::new(), span: DUMMY_SP }
}
}
@@ -440,7 +441,7 @@ impl WherePredicate {
pub struct WhereBoundPredicate {
pub span: Span,
/// Any generics from a `for` binding.
- pub bound_generic_params: Vec<GenericParam>,
+ pub bound_generic_params: ThinVec<GenericParam>,
/// The type being bounded.
pub bounded_ty: P<Ty>,
/// Trait and lifetime bounds (`Clone + Send + 'static`).
@@ -470,7 +471,7 @@ pub struct WhereEqPredicate {
#[derive(Clone, Encodable, Decodable, Debug)]
pub struct Crate {
pub attrs: AttrVec,
- pub items: Vec<P<Item>>,
+ pub items: ThinVec<P<Item>>,
pub spans: ModSpans,
/// Must be equal to `CRATE_NODE_ID` after the crate root is expanded, but may hold
/// expansion placeholders or an unassigned value (`DUMMY_NODE_ID`) before that.
@@ -502,7 +503,7 @@ pub enum MetaItemKind {
/// List meta item.
///
/// E.g., `#[derive(..)]`, where the field represents the `..`.
- List(Vec<NestedMetaItem>),
+ List(ThinVec<NestedMetaItem>),
/// Name value meta item.
///
@@ -530,7 +531,7 @@ pub enum NestedMetaItem {
#[derive(Clone, Encodable, Decodable, Debug)]
pub struct Block {
/// The statements in the block.
- pub stmts: Vec<Stmt>,
+ pub stmts: ThinVec<Stmt>,
pub id: NodeId,
/// Distinguishes between `unsafe { ... }` and `{ ... }`.
pub rules: BlockCheckMode,
@@ -580,7 +581,7 @@ impl Pat {
// A tuple pattern `(P0, .., Pn)` can be reparsed as `(T0, .., Tn)`
// assuming `T0` to `Tn` are all syntactically valid as types.
PatKind::Tuple(pats) => {
- let mut tys = Vec::with_capacity(pats.len());
+ let mut tys = ThinVec::with_capacity(pats.len());
// FIXME(#48994) - could just be collected into an Option<Vec>
for pat in pats {
tys.push(pat.to_ty()?);
@@ -721,14 +722,14 @@ pub enum PatKind {
/// A struct or struct variant pattern (e.g., `Variant {x, y, ..}`).
/// The `bool` is `true` in the presence of a `..`.
- Struct(Option<P<QSelf>>, Path, Vec<PatField>, /* recovered */ bool),
+ Struct(Option<P<QSelf>>, Path, ThinVec<PatField>, /* recovered */ bool),
/// A tuple struct/variant pattern (`Variant(x, y, .., z)`).
- TupleStruct(Option<P<QSelf>>, Path, Vec<P<Pat>>),
+ TupleStruct(Option<P<QSelf>>, Path, ThinVec<P<Pat>>),
/// An or-pattern `A | B | C`.
/// Invariant: `pats.len() >= 2`.
- Or(Vec<P<Pat>>),
+ Or(ThinVec<P<Pat>>),
/// A possibly qualified path pattern.
/// Unqualified path patterns `A::B::C` can legally refer to variants, structs, constants
@@ -737,7 +738,7 @@ pub enum PatKind {
Path(Option<P<QSelf>>, Path),
/// A tuple pattern (`(a, b)`).
- Tuple(Vec<P<Pat>>),
+ Tuple(ThinVec<P<Pat>>),
/// A `box` pattern.
Box(P<Pat>),
@@ -752,7 +753,7 @@ pub enum PatKind {
Range(Option<P<Expr>>, Option<P<Expr>>, Spanned<RangeEnd>),
/// A slice pattern `[a, b, c]`.
- Slice(Vec<P<Pat>>),
+ Slice(ThinVec<P<Pat>>),
/// A rest pattern `..`.
///
@@ -1168,7 +1169,7 @@ impl Expr {
pub fn to_bound(&self) -> Option<GenericBound> {
match &self.kind {
ExprKind::Path(None, path) => Some(GenericBound::Trait(
- PolyTraitRef::new(Vec::new(), path.clone(), self.span),
+ PolyTraitRef::new(ThinVec::new(), path.clone(), self.span),
TraitBoundModifier::None,
)),
_ => None,
@@ -1203,7 +1204,7 @@ impl Expr {
ExprKind::Array(exprs) if exprs.len() == 1 => exprs[0].to_ty().map(TyKind::Slice)?,
ExprKind::Tup(exprs) => {
- let tys = exprs.iter().map(|expr| expr.to_ty()).collect::<Option<Vec<_>>>()?;
+ let tys = exprs.iter().map(|expr| expr.to_ty()).collect::<Option<ThinVec<_>>>()?;
TyKind::Tup(tys)
}
@@ -1269,6 +1270,7 @@ impl Expr {
ExprKind::Try(..) => ExprPrecedence::Try,
ExprKind::Yield(..) => ExprPrecedence::Yield,
ExprKind::Yeet(..) => ExprPrecedence::Yeet,
+ ExprKind::FormatArgs(..) => ExprPrecedence::FormatArgs,
ExprKind::Err => ExprPrecedence::Err,
}
}
@@ -1335,7 +1337,7 @@ pub struct MethodCall {
/// The receiver, e.g. `x`.
pub receiver: P<Expr>,
/// The arguments, e.g. `a, b, c`.
- pub args: Vec<P<Expr>>,
+ pub args: ThinVec<P<Expr>>,
/// The span of the function, without the dot and receiver e.g. `foo::<Bar,
/// Baz>(a, b, c)`.
pub span: Span,
@@ -1355,7 +1357,7 @@ pub enum StructRest {
pub struct StructExpr {
pub qself: Option<P<QSelf>>,
pub path: Path,
- pub fields: Vec<ExprField>,
+ pub fields: ThinVec<ExprField>,
pub rest: StructRest,
}
@@ -1364,7 +1366,7 @@ pub enum ExprKind {
/// A `box x` expression.
Box(P<Expr>),
/// An array (`[a, b, c, d]`)
- Array(Vec<P<Expr>>),
+ Array(ThinVec<P<Expr>>),
/// Allow anonymous constants from an inline `const` block
ConstBlock(AnonConst),
/// A function call
@@ -1373,11 +1375,11 @@ pub enum ExprKind {
/// and the second field is the list of arguments.
/// This also represents calling the constructor of
/// tuple-like ADTs such as tuple structs and enum variants.
- Call(P<Expr>, Vec<P<Expr>>),
+ Call(P<Expr>, ThinVec<P<Expr>>),
/// A method call (e.g. `x.foo::<Bar, Baz>(a, b, c)`).
MethodCall(Box<MethodCall>),
/// A tuple (e.g., `(a, b, c, d)`).
- Tup(Vec<P<Expr>>),
+ Tup(ThinVec<P<Expr>>),
/// A binary operation (e.g., `a + b`, `a * b`).
Binary(BinOp, P<Expr>, P<Expr>),
/// A unary operation (e.g., `!x`, `*x`).
@@ -1412,7 +1414,7 @@ pub enum ExprKind {
/// `'label: loop { block }`
Loop(P<Block>, Option<Label>, Span),
/// A `match` block.
- Match(P<Expr>, Vec<Arm>),
+ Match(P<Expr>, ThinVec<Arm>),
/// A closure (e.g., `move |a, b, c| a + b + c`).
Closure(Box<Closure>),
/// A block (`'label: { ... }`).
@@ -1499,6 +1501,9 @@ pub enum ExprKind {
/// with a `ByteStr` literal.
IncludedBytes(Lrc<[u8]>),
+ /// A `format_args!()` expression.
+ FormatArgs(P<FormatArgs>),
+
/// Placeholder for an expression that wasn't syntactically well formed in some way.
Err,
}
@@ -1569,7 +1574,7 @@ pub enum ClosureBinder {
/// for<'a, 'b> |_: &'a (), _: &'b ()| { ... }
/// ^^^^^^ -- this
/// ```
- generic_params: P<[GenericParam]>,
+ generic_params: ThinVec<GenericParam>,
},
}
@@ -1821,6 +1826,13 @@ pub enum LitKind {
}
impl LitKind {
+ pub fn str(&self) -> Option<Symbol> {
+ match *self {
+ LitKind::Str(s, _) => Some(s),
+ _ => None,
+ }
+ }
+
/// Returns `true` if this literal is a string.
pub fn is_str(&self) -> bool {
matches!(self, LitKind::Str(..))
@@ -2044,7 +2056,7 @@ impl Ty {
pub struct BareFnTy {
pub unsafety: Unsafe,
pub ext: Extern,
- pub generic_params: Vec<GenericParam>,
+ pub generic_params: ThinVec<GenericParam>,
pub decl: P<FnDecl>,
/// Span of the `fn(...) -> ...` part.
pub decl_span: Span,
@@ -2066,7 +2078,7 @@ pub enum TyKind {
/// The never type (`!`).
Never,
/// A tuple (`(A, B, C, D,...)`).
- Tup(Vec<P<Ty>>),
+ Tup(ThinVec<P<Ty>>),
/// A path (`module::module::...::Type`), optionally
/// "qualified", e.g., `<Vec<T> as SomeTrait>::SomeType`.
///
@@ -2351,7 +2363,7 @@ impl Param {
/// which contains metadata about function safety, asyncness, constness and ABI.
#[derive(Clone, Encodable, Decodable, Debug)]
pub struct FnDecl {
- pub inputs: Vec<Param>,
+ pub inputs: ThinVec<Param>,
pub output: FnRetTy,
}
@@ -2463,7 +2475,7 @@ pub enum ModKind {
/// or with definition outlined to a separate file `mod foo;` and already loaded from it.
/// The inner span is from the first token past `{` to the last token until `}`,
/// or from the first to the last token in the loaded file.
- Loaded(Vec<P<Item>>, Inline, ModSpans),
+ Loaded(ThinVec<P<Item>>, Inline, ModSpans),
/// Module with definition outlined to a separate file `mod foo;` but not yet loaded from it.
Unloaded,
}
@@ -2485,12 +2497,12 @@ pub struct ForeignMod {
/// semantically by Rust.
pub unsafety: Unsafe,
pub abi: Option<StrLit>,
- pub items: Vec<P<ForeignItem>>,
+ pub items: ThinVec<P<ForeignItem>>,
}
#[derive(Clone, Encodable, Decodable, Debug)]
pub struct EnumDef {
- pub variants: Vec<Variant>,
+ pub variants: ThinVec<Variant>,
}
/// Enum variant.
#[derive(Clone, Encodable, Decodable, Debug)]
@@ -2520,7 +2532,7 @@ pub enum UseTreeKind {
/// `use prefix` or `use prefix as rename`
Simple(Option<Ident>),
/// `use prefix::{...}`
- Nested(Vec<(UseTree, NodeId)>),
+ Nested(ThinVec<(UseTree, NodeId)>),
/// `use prefix::*`
Glob,
}
@@ -2624,7 +2636,7 @@ pub struct TraitRef {
#[derive(Clone, Encodable, Decodable, Debug)]
pub struct PolyTraitRef {
/// The `'a` in `for<'a> Foo<&'a T>`.
- pub bound_generic_params: Vec<GenericParam>,
+ pub bound_generic_params: ThinVec<GenericParam>,
/// The `Foo<&'a T>` in `<'a> Foo<&'a T>`.
pub trait_ref: TraitRef,
@@ -2633,7 +2645,7 @@ pub struct PolyTraitRef {
}
impl PolyTraitRef {
- pub fn new(generic_params: Vec<GenericParam>, path: Path, span: Span) -> Self {
+ pub fn new(generic_params: ThinVec<GenericParam>, path: Path, span: Span) -> Self {
PolyTraitRef {
bound_generic_params: generic_params,
trait_ref: TraitRef { path, ref_id: DUMMY_NODE_ID },
@@ -2683,11 +2695,11 @@ pub enum VariantData {
/// Struct variant.
///
/// E.g., `Bar { .. }` as in `enum Foo { Bar { .. } }`.
- Struct(Vec<FieldDef>, bool),
+ Struct(ThinVec<FieldDef>, bool),
/// Tuple variant.
///
/// E.g., `Bar(..)` as in `enum Foo { Bar(..) }`.
- Tuple(Vec<FieldDef>, NodeId),
+ Tuple(ThinVec<FieldDef>, NodeId),
/// Unit variant.
///
/// E.g., `Bar = ..` as in `enum Foo { Bar = .. }`.
@@ -2814,7 +2826,7 @@ pub struct Trait {
pub is_auto: IsAuto,
pub generics: Generics,
pub bounds: GenericBounds,
- pub items: Vec<P<AssocItem>>,
+ pub items: ThinVec<P<AssocItem>>,
}
/// The location of a where clause on a `TyAlias` (`Span`) and whether there was
@@ -2862,7 +2874,7 @@ pub struct Impl {
/// The trait being implemented, if any.
pub of_trait: Option<TraitRef>,
pub self_ty: P<Ty>,
- pub items: Vec<P<AssocItem>>,
+ pub items: ThinVec<P<AssocItem>>,
}
#[derive(Clone, Encodable, Decodable, Debug)]
@@ -3100,26 +3112,26 @@ mod size_asserts {
static_assert_size!(AssocItem, 104);
static_assert_size!(AssocItemKind, 32);
static_assert_size!(Attribute, 32);
- static_assert_size!(Block, 48);
+ static_assert_size!(Block, 32);
static_assert_size!(Expr, 72);
static_assert_size!(ExprKind, 40);
- static_assert_size!(Fn, 184);
+ static_assert_size!(Fn, 152);
static_assert_size!(ForeignItem, 96);
static_assert_size!(ForeignItemKind, 24);
static_assert_size!(GenericArg, 24);
- static_assert_size!(GenericBound, 72);
- static_assert_size!(Generics, 72);
- static_assert_size!(Impl, 184);
- static_assert_size!(Item, 184);
- static_assert_size!(ItemKind, 112);
+ static_assert_size!(GenericBound, 56);
+ static_assert_size!(Generics, 40);
+ static_assert_size!(Impl, 136);
+ static_assert_size!(Item, 136);
+ static_assert_size!(ItemKind, 64);
static_assert_size!(LitKind, 24);
static_assert_size!(Local, 72);
static_assert_size!(MetaItemLit, 40);
static_assert_size!(Param, 40);
- static_assert_size!(Pat, 88);
+ static_assert_size!(Pat, 72);
static_assert_size!(Path, 24);
static_assert_size!(PathSegment, 24);
- static_assert_size!(PatKind, 64);
+ static_assert_size!(PatKind, 48);
static_assert_size!(Stmt, 32);
static_assert_size!(StmtKind, 16);
static_assert_size!(Ty, 64);
diff --git a/compiler/rustc_ast/src/attr/mod.rs b/compiler/rustc_ast/src/attr/mod.rs
index c6b6207b3..2e83b3e62 100644
--- a/compiler/rustc_ast/src/attr/mod.rs
+++ b/compiler/rustc_ast/src/attr/mod.rs
@@ -20,7 +20,7 @@ use std::iter;
use std::ops::BitXor;
#[cfg(debug_assertions)]
use std::sync::atomic::{AtomicU32, Ordering};
-use thin_vec::thin_vec;
+use thin_vec::{thin_vec, ThinVec};
pub struct MarkedAttrs(GrowableBitSet<AttrId>);
@@ -40,84 +40,65 @@ impl MarkedAttrs {
}
}
-impl NestedMetaItem {
- /// Returns the `MetaItem` if `self` is a `NestedMetaItem::MetaItem`.
- pub fn meta_item(&self) -> Option<&MetaItem> {
- match self {
- NestedMetaItem::MetaItem(item) => Some(item),
- _ => None,
- }
- }
+pub struct AttrIdGenerator(WorkerLocal<Cell<u32>>);
- /// Returns the `MetaItemLit` if `self` is a `NestedMetaItem::Literal`s.
- pub fn lit(&self) -> Option<&MetaItemLit> {
- match self {
- NestedMetaItem::Lit(lit) => Some(lit),
- _ => None,
- }
- }
+#[cfg(debug_assertions)]
+static MAX_ATTR_ID: AtomicU32 = AtomicU32::new(u32::MAX);
- /// Returns `true` if this list item is a MetaItem with a name of `name`.
- pub fn has_name(&self, name: Symbol) -> bool {
- self.meta_item().map_or(false, |meta_item| meta_item.has_name(name))
- }
+impl AttrIdGenerator {
+ pub fn new() -> Self {
+ // We use `(index as u32).reverse_bits()` to initialize the
+ // starting value of AttrId in each worker thread.
+ // The `index` is the index of the worker thread.
+ // This ensures that the AttrId generated in each thread is unique.
+ AttrIdGenerator(WorkerLocal::new(|index| {
+ let index: u32 = index.try_into().unwrap();
- /// For a single-segment meta item, returns its name; otherwise, returns `None`.
- pub fn ident(&self) -> Option<Ident> {
- self.meta_item().and_then(|meta_item| meta_item.ident())
- }
- pub fn name_or_empty(&self) -> Symbol {
- self.ident().unwrap_or_else(Ident::empty).name
- }
+ #[cfg(debug_assertions)]
+ {
+ let max_id = ((index + 1).next_power_of_two() - 1).bitxor(u32::MAX).reverse_bits();
+ MAX_ATTR_ID.fetch_min(max_id, Ordering::Release);
+ }
- /// Gets the string value if `self` is a `MetaItem` and the `MetaItem` is a
- /// `MetaItemKind::NameValue` variant containing a string, otherwise `None`.
- pub fn value_str(&self) -> Option<Symbol> {
- self.meta_item().and_then(|meta_item| meta_item.value_str())
+ Cell::new(index.reverse_bits())
+ }))
}
- /// Returns a name and single literal value tuple of the `MetaItem`.
- pub fn name_value_literal(&self) -> Option<(Symbol, &MetaItemLit)> {
- self.meta_item().and_then(|meta_item| {
- meta_item.meta_item_list().and_then(|meta_item_list| {
- if meta_item_list.len() == 1
- && let Some(ident) = meta_item.ident()
- && let Some(lit) = meta_item_list[0].lit()
- {
- return Some((ident.name, lit));
- }
- None
- })
- })
- }
+ pub fn mk_attr_id(&self) -> AttrId {
+ let id = self.0.get();
- /// Gets a list of inner meta items from a list `MetaItem` type.
- pub fn meta_item_list(&self) -> Option<&[NestedMetaItem]> {
- self.meta_item().and_then(|meta_item| meta_item.meta_item_list())
- }
+ // Ensure the assigned attr_id does not overlap the bits
+ // representing the number of threads.
+ #[cfg(debug_assertions)]
+ assert!(id <= MAX_ATTR_ID.load(Ordering::Acquire));
- /// Returns `true` if the variant is `MetaItem`.
- pub fn is_meta_item(&self) -> bool {
- self.meta_item().is_some()
+ self.0.set(id + 1);
+ AttrId::from_u32(id)
}
+}
- /// Returns `true` if `self` is a `MetaItem` and the meta item is a word.
- pub fn is_word(&self) -> bool {
- self.meta_item().map_or(false, |meta_item| meta_item.is_word())
+impl Attribute {
+ pub fn get_normal_item(&self) -> &AttrItem {
+ match &self.kind {
+ AttrKind::Normal(normal) => &normal.item,
+ AttrKind::DocComment(..) => panic!("unexpected doc comment"),
+ }
}
- /// See [`MetaItem::name_value_literal_span`].
- pub fn name_value_literal_span(&self) -> Option<Span> {
- self.meta_item()?.name_value_literal_span()
+ pub fn unwrap_normal_item(self) -> AttrItem {
+ match self.kind {
+ AttrKind::Normal(normal) => normal.into_inner().item,
+ AttrKind::DocComment(..) => panic!("unexpected doc comment"),
+ }
}
-}
-impl Attribute {
- #[inline]
- pub fn has_name(&self, name: Symbol) -> bool {
- match &self.kind {
- AttrKind::Normal(normal) => normal.item.path == name,
- AttrKind::DocComment(..) => false,
+ /// Returns `true` if it is a sugared doc comment (`///` or `//!` for example).
+ /// So `#[doc = "doc"]` (which is a doc comment) and `#[doc(...)]` (which is not
+ /// a doc comment) will return `false`.
+ pub fn is_doc_comment(&self) -> bool {
+ match self.kind {
+ AttrKind::Normal(..) => false,
+ AttrKind::DocComment(..) => true,
}
}
@@ -138,20 +119,11 @@ impl Attribute {
self.ident().unwrap_or_else(Ident::empty).name
}
- pub fn value_str(&self) -> Option<Symbol> {
- match &self.kind {
- AttrKind::Normal(normal) => normal.item.meta_kind().and_then(|kind| kind.value_str()),
- AttrKind::DocComment(..) => None,
- }
- }
-
- pub fn meta_item_list(&self) -> Option<Vec<NestedMetaItem>> {
+ #[inline]
+ pub fn has_name(&self, name: Symbol) -> bool {
match &self.kind {
- AttrKind::Normal(normal) => match normal.item.meta_kind() {
- Some(MetaItemKind::List(list)) => Some(list),
- _ => None,
- },
- AttrKind::DocComment(..) => None,
+ AttrKind::Normal(normal) => normal.item.path == name,
+ AttrKind::DocComment(..) => false,
}
}
@@ -162,82 +134,18 @@ impl Attribute {
false
}
}
-}
-
-impl MetaItem {
- /// For a single-segment meta item, returns its name; otherwise, returns `None`.
- pub fn ident(&self) -> Option<Ident> {
- if self.path.segments.len() == 1 { Some(self.path.segments[0].ident) } else { None }
- }
- pub fn name_or_empty(&self) -> Symbol {
- self.ident().unwrap_or_else(Ident::empty).name
- }
- /// ```text
- /// Example:
- /// #[attribute(name = "value")]
- /// ^^^^^^^^^^^^^^
- /// ```
- pub fn name_value_literal(&self) -> Option<&MetaItemLit> {
+ pub fn meta_item_list(&self) -> Option<ThinVec<NestedMetaItem>> {
match &self.kind {
- MetaItemKind::NameValue(v) => Some(v),
- _ => None,
+ AttrKind::Normal(normal) => normal.item.meta_item_list(),
+ AttrKind::DocComment(..) => None,
}
}
pub fn value_str(&self) -> Option<Symbol> {
- self.kind.value_str()
- }
-
- pub fn meta_item_list(&self) -> Option<&[NestedMetaItem]> {
match &self.kind {
- MetaItemKind::List(l) => Some(&**l),
- _ => None,
- }
- }
-
- pub fn is_word(&self) -> bool {
- matches!(self.kind, MetaItemKind::Word)
- }
-
- pub fn has_name(&self, name: Symbol) -> bool {
- self.path == name
- }
-
- /// This is used in case you want the value span instead of the whole attribute. Example:
- ///
- /// ```text
- /// #[doc(alias = "foo")]
- /// ```
- ///
- /// In here, it'll return a span for `"foo"`.
- pub fn name_value_literal_span(&self) -> Option<Span> {
- Some(self.name_value_literal()?.span)
- }
-}
-
-impl AttrItem {
- pub fn span(&self) -> Span {
- self.args.span().map_or(self.path.span, |args_span| self.path.span.to(args_span))
- }
-
- pub fn meta(&self, span: Span) -> Option<MetaItem> {
- Some(MetaItem { path: self.path.clone(), kind: self.meta_kind()?, span })
- }
-
- pub fn meta_kind(&self) -> Option<MetaItemKind> {
- MetaItemKind::from_attr_args(&self.args)
- }
-}
-
-impl Attribute {
- /// Returns `true` if it is a sugared doc comment (`///` or `//!` for example).
- /// So `#[doc = "doc"]` (which is a doc comment) and `#[doc(...)]` (which is not
- /// a doc comment) will return `false`.
- pub fn is_doc_comment(&self) -> bool {
- match self.kind {
- AttrKind::Normal(..) => false,
- AttrKind::DocComment(..) => true,
+ AttrKind::Normal(normal) => normal.item.value_str(),
+ AttrKind::DocComment(..) => None,
}
}
@@ -247,13 +155,11 @@ impl Attribute {
/// * `#[doc = "doc"]` returns `Some(("doc", CommentKind::Line))`.
/// * `#[doc(...)]` returns `None`.
pub fn doc_str_and_comment_kind(&self) -> Option<(Symbol, CommentKind)> {
- match self.kind {
- AttrKind::DocComment(kind, data) => Some((data, kind)),
- AttrKind::Normal(ref normal) if normal.item.path == sym::doc => normal
- .item
- .meta_kind()
- .and_then(|kind| kind.value_str())
- .map(|data| (data, CommentKind::Line)),
+ match &self.kind {
+ AttrKind::DocComment(kind, data) => Some((*data, *kind)),
+ AttrKind::Normal(normal) if normal.item.path == sym::doc => {
+ normal.item.value_str().map(|s| (s, CommentKind::Line))
+ }
_ => None,
}
}
@@ -265,9 +171,7 @@ impl Attribute {
pub fn doc_str(&self) -> Option<Symbol> {
match &self.kind {
AttrKind::DocComment(.., data) => Some(*data),
- AttrKind::Normal(normal) if normal.item.path == sym::doc => {
- normal.item.meta_kind().and_then(|kind| kind.value_str())
- }
+ AttrKind::Normal(normal) if normal.item.path == sym::doc => normal.item.value_str(),
_ => None,
}
}
@@ -276,20 +180,6 @@ impl Attribute {
self.doc_str().map_or(false, |s| comments::may_have_doc_links(s.as_str()))
}
- pub fn get_normal_item(&self) -> &AttrItem {
- match &self.kind {
- AttrKind::Normal(normal) => &normal.item,
- AttrKind::DocComment(..) => panic!("unexpected doc comment"),
- }
- }
-
- pub fn unwrap_normal_item(self) -> AttrItem {
- match self.kind {
- AttrKind::Normal(normal) => normal.into_inner().item,
- AttrKind::DocComment(..) => panic!("unexpected doc comment"),
- }
- }
-
/// Extracts the MetaItem from inside this Attribute.
pub fn meta(&self) -> Option<MetaItem> {
match &self.kind {
@@ -321,130 +211,102 @@ impl Attribute {
}
}
-pub struct AttrIdGenerator(WorkerLocal<Cell<u32>>);
-
-#[cfg(debug_assertions)]
-static MAX_ATTR_ID: AtomicU32 = AtomicU32::new(u32::MAX);
-
-impl AttrIdGenerator {
- pub fn new() -> Self {
- // We use `(index as u32).reverse_bits()` to initialize the
- // starting value of AttrId in each worker thread.
- // The `index` is the index of the worker thread.
- // This ensures that the AttrId generated in each thread is unique.
- AttrIdGenerator(WorkerLocal::new(|index| {
- let index: u32 = index.try_into().unwrap();
+impl AttrItem {
+ pub fn span(&self) -> Span {
+ self.args.span().map_or(self.path.span, |args_span| self.path.span.to(args_span))
+ }
- #[cfg(debug_assertions)]
- {
- let max_id = ((index + 1).next_power_of_two() - 1).bitxor(u32::MAX).reverse_bits();
- MAX_ATTR_ID.fetch_min(max_id, Ordering::Release);
+ fn meta_item_list(&self) -> Option<ThinVec<NestedMetaItem>> {
+ match &self.args {
+ AttrArgs::Delimited(args) if args.delim == MacDelimiter::Parenthesis => {
+ MetaItemKind::list_from_tokens(args.tokens.clone())
}
-
- Cell::new(index.reverse_bits())
- }))
+ AttrArgs::Delimited(_) | AttrArgs::Eq(..) | AttrArgs::Empty => None,
+ }
}
- pub fn mk_attr_id(&self) -> AttrId {
- let id = self.0.get();
+ fn value_str(&self) -> Option<Symbol> {
+ match &self.args {
+ AttrArgs::Eq(_, args) => args.value_str(),
+ AttrArgs::Delimited(_) | AttrArgs::Empty => None,
+ }
+ }
- // Ensure the assigned attr_id does not overlap the bits
- // representing the number of threads.
- #[cfg(debug_assertions)]
- assert!(id <= MAX_ATTR_ID.load(Ordering::Acquire));
+ pub fn meta(&self, span: Span) -> Option<MetaItem> {
+ Some(MetaItem { path: self.path.clone(), kind: self.meta_kind()?, span })
+ }
- self.0.set(id + 1);
- AttrId::from_u32(id)
+ pub fn meta_kind(&self) -> Option<MetaItemKind> {
+ MetaItemKind::from_attr_args(&self.args)
}
}
-pub fn mk_attr(
- g: &AttrIdGenerator,
- style: AttrStyle,
- path: Path,
- args: AttrArgs,
- span: Span,
-) -> Attribute {
- mk_attr_from_item(g, AttrItem { path, args, tokens: None }, None, style, span)
+impl AttrArgsEq {
+ fn value_str(&self) -> Option<Symbol> {
+ match self {
+ AttrArgsEq::Ast(expr) => match expr.kind {
+ ExprKind::Lit(token_lit) => {
+ LitKind::from_token_lit(token_lit).ok().and_then(|lit| lit.str())
+ }
+ _ => None,
+ },
+ AttrArgsEq::Hir(lit) => lit.kind.str(),
+ }
+ }
}
-pub fn mk_attr_from_item(
- g: &AttrIdGenerator,
- item: AttrItem,
- tokens: Option<LazyAttrTokenStream>,
- style: AttrStyle,
- span: Span,
-) -> Attribute {
- Attribute {
- kind: AttrKind::Normal(P(NormalAttr { item, tokens })),
- id: g.mk_attr_id(),
- style,
- span,
+impl MetaItem {
+ /// For a single-segment meta item, returns its name; otherwise, returns `None`.
+ pub fn ident(&self) -> Option<Ident> {
+ if self.path.segments.len() == 1 { Some(self.path.segments[0].ident) } else { None }
}
-}
-pub fn mk_attr_word(g: &AttrIdGenerator, style: AttrStyle, name: Symbol, span: Span) -> Attribute {
- let path = Path::from_ident(Ident::new(name, span));
- let args = AttrArgs::Empty;
- mk_attr(g, style, path, args, span)
-}
+ pub fn name_or_empty(&self) -> Symbol {
+ self.ident().unwrap_or_else(Ident::empty).name
+ }
-pub fn mk_attr_name_value_str(
- g: &AttrIdGenerator,
- style: AttrStyle,
- name: Symbol,
- val: Symbol,
- span: Span,
-) -> Attribute {
- let lit = token::Lit::new(token::Str, escape_string_symbol(val), None);
- let expr = P(Expr {
- id: DUMMY_NODE_ID,
- kind: ExprKind::Lit(lit),
- span,
- attrs: AttrVec::new(),
- tokens: None,
- });
- let path = Path::from_ident(Ident::new(name, span));
- let args = AttrArgs::Eq(span, AttrArgsEq::Ast(expr));
- mk_attr(g, style, path, args, span)
-}
+ pub fn has_name(&self, name: Symbol) -> bool {
+ self.path == name
+ }
-pub fn mk_attr_nested_word(
- g: &AttrIdGenerator,
- style: AttrStyle,
- outer: Symbol,
- inner: Symbol,
- span: Span,
-) -> Attribute {
- let inner_tokens = TokenStream::new(vec![TokenTree::Token(
- Token::from_ast_ident(Ident::new(inner, span)),
- Spacing::Alone,
- )]);
- let outer_ident = Ident::new(outer, span);
- let path = Path::from_ident(outer_ident);
- let attr_args = AttrArgs::Delimited(DelimArgs {
- dspan: DelimSpan::from_single(span),
- delim: MacDelimiter::Parenthesis,
- tokens: inner_tokens,
- });
- mk_attr(g, style, path, attr_args, span)
-}
+ pub fn is_word(&self) -> bool {
+ matches!(self.kind, MetaItemKind::Word)
+ }
-pub fn mk_doc_comment(
- g: &AttrIdGenerator,
- comment_kind: CommentKind,
- style: AttrStyle,
- data: Symbol,
- span: Span,
-) -> Attribute {
- Attribute { kind: AttrKind::DocComment(comment_kind, data), id: g.mk_attr_id(), style, span }
-}
+ pub fn meta_item_list(&self) -> Option<&[NestedMetaItem]> {
+ match &self.kind {
+ MetaItemKind::List(l) => Some(&**l),
+ _ => None,
+ }
+ }
-pub fn list_contains_name(items: &[NestedMetaItem], name: Symbol) -> bool {
- items.iter().any(|item| item.has_name(name))
-}
+ /// ```text
+ /// Example:
+ /// #[attribute(name = "value")]
+ /// ^^^^^^^^^^^^^^
+ /// ```
+ pub fn name_value_literal(&self) -> Option<&MetaItemLit> {
+ match &self.kind {
+ MetaItemKind::NameValue(v) => Some(v),
+ _ => None,
+ }
+ }
+
+ /// This is used in case you want the value span instead of the whole attribute. Example:
+ ///
+ /// ```text
+ /// #[doc(alias = "foo")]
+ /// ```
+ ///
+ /// In here, it'll return a span for `"foo"`.
+ pub fn name_value_literal_span(&self) -> Option<Span> {
+ Some(self.name_value_literal()?.span)
+ }
+
+ pub fn value_str(&self) -> Option<Symbol> {
+ self.kind.value_str()
+ }
-impl MetaItem {
fn from_tokens<I>(tokens: &mut iter::Peekable<I>) -> Option<MetaItem>
where
I: Iterator<Item = TokenTree>,
@@ -508,17 +370,14 @@ impl MetaItem {
impl MetaItemKind {
pub fn value_str(&self) -> Option<Symbol> {
match self {
- MetaItemKind::NameValue(v) => match v.kind {
- LitKind::Str(s, _) => Some(s),
- _ => None,
- },
+ MetaItemKind::NameValue(v) => v.kind.str(),
_ => None,
}
}
- fn list_from_tokens(tokens: TokenStream) -> Option<MetaItemKind> {
+ fn list_from_tokens(tokens: TokenStream) -> Option<ThinVec<NestedMetaItem>> {
let mut tokens = tokens.into_trees().peekable();
- let mut result = Vec::new();
+ let mut result = ThinVec::new();
while tokens.peek().is_some() {
let item = NestedMetaItem::from_tokens(&mut tokens)?;
result.push(item);
@@ -527,7 +386,7 @@ impl MetaItemKind {
_ => return None,
}
}
- Some(MetaItemKind::List(result))
+ Some(result)
}
fn name_value_from_tokens(
@@ -544,6 +403,24 @@ impl MetaItemKind {
}
}
+ fn from_tokens(
+ tokens: &mut iter::Peekable<impl Iterator<Item = TokenTree>>,
+ ) -> Option<MetaItemKind> {
+ match tokens.peek() {
+ Some(TokenTree::Delimited(_, Delimiter::Parenthesis, inner_tokens)) => {
+ let inner_tokens = inner_tokens.clone();
+ tokens.next();
+ MetaItemKind::list_from_tokens(inner_tokens).map(MetaItemKind::List)
+ }
+ Some(TokenTree::Delimited(..)) => None,
+ Some(TokenTree::Token(Token { kind: token::Eq, .. }, _)) => {
+ tokens.next();
+ MetaItemKind::name_value_from_tokens(tokens)
+ }
+ _ => Some(MetaItemKind::Word),
+ }
+ }
+
fn from_attr_args(args: &AttrArgs) -> Option<MetaItemKind> {
match args {
AttrArgs::Empty => Some(MetaItemKind::Word),
@@ -551,7 +428,7 @@ impl MetaItemKind {
dspan: _,
delim: MacDelimiter::Parenthesis,
tokens,
- }) => MetaItemKind::list_from_tokens(tokens.clone()),
+ }) => MetaItemKind::list_from_tokens(tokens.clone()).map(MetaItemKind::List),
AttrArgs::Delimited(..) => None,
AttrArgs::Eq(_, AttrArgsEq::Ast(expr)) => match expr.kind {
ExprKind::Lit(token_lit) => {
@@ -565,24 +442,6 @@ impl MetaItemKind {
AttrArgs::Eq(_, AttrArgsEq::Hir(lit)) => Some(MetaItemKind::NameValue(lit.clone())),
}
}
-
- fn from_tokens(
- tokens: &mut iter::Peekable<impl Iterator<Item = TokenTree>>,
- ) -> Option<MetaItemKind> {
- match tokens.peek() {
- Some(TokenTree::Delimited(_, Delimiter::Parenthesis, inner_tokens)) => {
- let inner_tokens = inner_tokens.clone();
- tokens.next();
- MetaItemKind::list_from_tokens(inner_tokens)
- }
- Some(TokenTree::Delimited(..)) => None,
- Some(TokenTree::Token(Token { kind: token::Eq, .. }, _)) => {
- tokens.next();
- MetaItemKind::name_value_from_tokens(tokens)
- }
- _ => Some(MetaItemKind::Word),
- }
- }
}
impl NestedMetaItem {
@@ -593,6 +452,77 @@ impl NestedMetaItem {
}
}
+ /// For a single-segment meta item, returns its name; otherwise, returns `None`.
+ pub fn ident(&self) -> Option<Ident> {
+ self.meta_item().and_then(|meta_item| meta_item.ident())
+ }
+
+ pub fn name_or_empty(&self) -> Symbol {
+ self.ident().unwrap_or_else(Ident::empty).name
+ }
+
+ /// Returns `true` if this list item is a MetaItem with a name of `name`.
+ pub fn has_name(&self, name: Symbol) -> bool {
+ self.meta_item().map_or(false, |meta_item| meta_item.has_name(name))
+ }
+
+ /// Returns `true` if `self` is a `MetaItem` and the meta item is a word.
+ pub fn is_word(&self) -> bool {
+ self.meta_item().map_or(false, |meta_item| meta_item.is_word())
+ }
+
+ /// Gets a list of inner meta items from a list `MetaItem` type.
+ pub fn meta_item_list(&self) -> Option<&[NestedMetaItem]> {
+ self.meta_item().and_then(|meta_item| meta_item.meta_item_list())
+ }
+
+ /// Returns a name and single literal value tuple of the `MetaItem`.
+ pub fn name_value_literal(&self) -> Option<(Symbol, &MetaItemLit)> {
+ self.meta_item().and_then(|meta_item| {
+ meta_item.meta_item_list().and_then(|meta_item_list| {
+ if meta_item_list.len() == 1
+ && let Some(ident) = meta_item.ident()
+ && let Some(lit) = meta_item_list[0].lit()
+ {
+ return Some((ident.name, lit));
+ }
+ None
+ })
+ })
+ }
+
+ /// See [`MetaItem::name_value_literal_span`].
+ pub fn name_value_literal_span(&self) -> Option<Span> {
+ self.meta_item()?.name_value_literal_span()
+ }
+
+ /// Gets the string value if `self` is a `MetaItem` and the `MetaItem` is a
+ /// `MetaItemKind::NameValue` variant containing a string, otherwise `None`.
+ pub fn value_str(&self) -> Option<Symbol> {
+ self.meta_item().and_then(|meta_item| meta_item.value_str())
+ }
+
+ /// Returns the `MetaItemLit` if `self` is a `NestedMetaItem::Literal`s.
+ pub fn lit(&self) -> Option<&MetaItemLit> {
+ match self {
+ NestedMetaItem::Lit(lit) => Some(lit),
+ _ => None,
+ }
+ }
+
+ /// Returns the `MetaItem` if `self` is a `NestedMetaItem::MetaItem`.
+ pub fn meta_item(&self) -> Option<&MetaItem> {
+ match self {
+ NestedMetaItem::MetaItem(item) => Some(item),
+ _ => None,
+ }
+ }
+
+ /// Returns `true` if the variant is `MetaItem`.
+ pub fn is_meta_item(&self) -> bool {
+ self.meta_item().is_some()
+ }
+
fn from_tokens<I>(tokens: &mut iter::Peekable<I>) -> Option<NestedMetaItem>
where
I: Iterator<Item = TokenTree>,
@@ -614,3 +544,89 @@ impl NestedMetaItem {
MetaItem::from_tokens(tokens).map(NestedMetaItem::MetaItem)
}
}
+
+pub fn mk_doc_comment(
+ g: &AttrIdGenerator,
+ comment_kind: CommentKind,
+ style: AttrStyle,
+ data: Symbol,
+ span: Span,
+) -> Attribute {
+ Attribute { kind: AttrKind::DocComment(comment_kind, data), id: g.mk_attr_id(), style, span }
+}
+
+pub fn mk_attr(
+ g: &AttrIdGenerator,
+ style: AttrStyle,
+ path: Path,
+ args: AttrArgs,
+ span: Span,
+) -> Attribute {
+ mk_attr_from_item(g, AttrItem { path, args, tokens: None }, None, style, span)
+}
+
+pub fn mk_attr_from_item(
+ g: &AttrIdGenerator,
+ item: AttrItem,
+ tokens: Option<LazyAttrTokenStream>,
+ style: AttrStyle,
+ span: Span,
+) -> Attribute {
+ Attribute {
+ kind: AttrKind::Normal(P(NormalAttr { item, tokens })),
+ id: g.mk_attr_id(),
+ style,
+ span,
+ }
+}
+
+pub fn mk_attr_word(g: &AttrIdGenerator, style: AttrStyle, name: Symbol, span: Span) -> Attribute {
+ let path = Path::from_ident(Ident::new(name, span));
+ let args = AttrArgs::Empty;
+ mk_attr(g, style, path, args, span)
+}
+
+pub fn mk_attr_nested_word(
+ g: &AttrIdGenerator,
+ style: AttrStyle,
+ outer: Symbol,
+ inner: Symbol,
+ span: Span,
+) -> Attribute {
+ let inner_tokens = TokenStream::new(vec![TokenTree::Token(
+ Token::from_ast_ident(Ident::new(inner, span)),
+ Spacing::Alone,
+ )]);
+ let outer_ident = Ident::new(outer, span);
+ let path = Path::from_ident(outer_ident);
+ let attr_args = AttrArgs::Delimited(DelimArgs {
+ dspan: DelimSpan::from_single(span),
+ delim: MacDelimiter::Parenthesis,
+ tokens: inner_tokens,
+ });
+ mk_attr(g, style, path, attr_args, span)
+}
+
+pub fn mk_attr_name_value_str(
+ g: &AttrIdGenerator,
+ style: AttrStyle,
+ name: Symbol,
+ val: Symbol,
+ span: Span,
+) -> Attribute {
+ let lit = token::Lit::new(token::Str, escape_string_symbol(val), None);
+ let expr = P(Expr {
+ id: DUMMY_NODE_ID,
+ kind: ExprKind::Lit(lit),
+ span,
+ attrs: AttrVec::new(),
+ tokens: None,
+ });
+ let path = Path::from_ident(Ident::new(name, span));
+ let args = AttrArgs::Eq(span, AttrArgsEq::Ast(expr));
+ mk_attr(g, style, path, args, span)
+}
+
+pub fn list_contains_name(items: &[NestedMetaItem], name: Symbol) -> bool {
+ items.iter().any(|item| item.has_name(name))
+}
diff --git a/compiler/rustc_builtin_macros/src/format/ast.rs b/compiler/rustc_ast/src/format.rs
index 01dbffa21..d021bea5e 100644
--- a/compiler/rustc_builtin_macros/src/format/ast.rs
+++ b/compiler/rustc_ast/src/format.rs
@@ -1,5 +1,5 @@
-use rustc_ast::ptr::P;
-use rustc_ast::Expr;
+use crate::ptr::P;
+use crate::Expr;
use rustc_data_structures::fx::FxHashMap;
use rustc_span::symbol::{Ident, Symbol};
use rustc_span::Span;
@@ -39,7 +39,7 @@ use rustc_span::Span;
/// Basically the "AST" for a complete `format_args!()`.
///
/// E.g., `format_args!("hello {name}");`.
-#[derive(Clone, Debug)]
+#[derive(Clone, Encodable, Decodable, Debug)]
pub struct FormatArgs {
pub span: Span,
pub template: Vec<FormatArgsPiece>,
@@ -49,7 +49,7 @@ pub struct FormatArgs {
/// A piece of a format template string.
///
/// E.g. "hello" or "{name}".
-#[derive(Clone, Debug)]
+#[derive(Clone, Encodable, Decodable, Debug)]
pub enum FormatArgsPiece {
Literal(Symbol),
Placeholder(FormatPlaceholder),
@@ -59,7 +59,7 @@ pub enum FormatArgsPiece {
///
/// E.g. `1, 2, name="ferris", n=3`,
/// but also implicit captured arguments like `x` in `format_args!("{x}")`.
-#[derive(Clone, Debug)]
+#[derive(Clone, Encodable, Decodable, Debug)]
pub struct FormatArguments {
arguments: Vec<FormatArgument>,
num_unnamed_args: usize,
@@ -67,6 +67,12 @@ pub struct FormatArguments {
names: FxHashMap<Symbol, usize>,
}
+// FIXME: Rustdoc has trouble proving Send/Sync for this. See #106930.
+#[cfg(parallel_compiler)]
+unsafe impl Sync for FormatArguments {}
+#[cfg(parallel_compiler)]
+unsafe impl Send for FormatArguments {}
+
impl FormatArguments {
pub fn new() -> Self {
Self {
@@ -121,18 +127,22 @@ impl FormatArguments {
&self.arguments[..self.num_explicit_args]
}
- pub fn into_vec(self) -> Vec<FormatArgument> {
- self.arguments
+ pub fn all_args(&self) -> &[FormatArgument] {
+ &self.arguments[..]
+ }
+
+ pub fn all_args_mut(&mut self) -> &mut [FormatArgument] {
+ &mut self.arguments[..]
}
}
-#[derive(Clone, Debug)]
+#[derive(Clone, Encodable, Decodable, Debug)]
pub struct FormatArgument {
pub kind: FormatArgumentKind,
pub expr: P<Expr>,
}
-#[derive(Clone, Debug)]
+#[derive(Clone, Encodable, Decodable, Debug)]
pub enum FormatArgumentKind {
/// `format_args(…, arg)`
Normal,
@@ -152,7 +162,7 @@ impl FormatArgumentKind {
}
}
-#[derive(Clone, Debug, PartialEq, Eq)]
+#[derive(Clone, Encodable, Decodable, Debug, PartialEq, Eq)]
pub struct FormatPlaceholder {
/// Index into [`FormatArgs::arguments`].
pub argument: FormatArgPosition,
@@ -164,7 +174,7 @@ pub struct FormatPlaceholder {
pub format_options: FormatOptions,
}
-#[derive(Clone, Debug, PartialEq, Eq)]
+#[derive(Clone, Encodable, Decodable, Debug, PartialEq, Eq)]
pub struct FormatArgPosition {
/// Which argument this position refers to (Ok),
/// or would've referred to if it existed (Err).
@@ -175,7 +185,7 @@ pub struct FormatArgPosition {
pub span: Option<Span>,
}
-#[derive(Copy, Clone, Debug, PartialEq, Eq)]
+#[derive(Copy, Clone, Encodable, Decodable, Debug, PartialEq, Eq)]
pub enum FormatArgPositionKind {
/// `{}` or `{:.*}`
Implicit,
@@ -185,7 +195,7 @@ pub enum FormatArgPositionKind {
Named,
}
-#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
+#[derive(Copy, Clone, Encodable, Decodable, Debug, PartialEq, Eq, Hash)]
pub enum FormatTrait {
/// `{}`
Display,
@@ -207,7 +217,7 @@ pub enum FormatTrait {
UpperHex,
}
-#[derive(Clone, Debug, Default, PartialEq, Eq)]
+#[derive(Clone, Encodable, Decodable, Default, Debug, PartialEq, Eq)]
pub struct FormatOptions {
/// The width. E.g. `{:5}` or `{:width$}`.
pub width: Option<FormatCount>,
@@ -217,11 +227,33 @@ pub struct FormatOptions {
pub alignment: Option<FormatAlignment>,
/// The fill character. E.g. the `.` in `{:.>10}`.
pub fill: Option<char>,
- /// The `+`, `-`, `0`, `#`, `x?` and `X?` flags.
- pub flags: u32,
+ /// The `+` or `-` flag.
+ pub sign: Option<FormatSign>,
+ /// The `#` flag.
+ pub alternate: bool,
+ /// The `0` flag. E.g. the `0` in `{:02x}`.
+ pub zero_pad: bool,
+ /// The `x` or `X` flag (for `Debug` only). E.g. the `x` in `{:x?}`.
+ pub debug_hex: Option<FormatDebugHex>,
+}
+
+#[derive(Copy, Clone, Encodable, Decodable, Debug, PartialEq, Eq)]
+pub enum FormatSign {
+ /// The `+` flag.
+ Plus,
+ /// The `-` flag.
+ Minus,
+}
+
+#[derive(Copy, Clone, Encodable, Decodable, Debug, PartialEq, Eq)]
+pub enum FormatDebugHex {
+ /// The `x` flag in `{:x?}`.
+ Lower,
+ /// The `X` flag in `{:X?}`.
+ Upper,
}
-#[derive(Clone, Debug, PartialEq, Eq)]
+#[derive(Copy, Clone, Encodable, Decodable, Debug, PartialEq, Eq)]
pub enum FormatAlignment {
/// `{:<}`
Left,
@@ -231,7 +263,7 @@ pub enum FormatAlignment {
Center,
}
-#[derive(Clone, Debug, PartialEq, Eq)]
+#[derive(Clone, Encodable, Decodable, Debug, PartialEq, Eq)]
pub enum FormatCount {
/// `{:5}` or `{:.5}`
Literal(usize),
diff --git a/compiler/rustc_ast/src/lib.rs b/compiler/rustc_ast/src/lib.rs
index 9c1dfeb1a..23c32fa96 100644
--- a/compiler/rustc_ast/src/lib.rs
+++ b/compiler/rustc_ast/src/lib.rs
@@ -16,7 +16,6 @@
#![feature(let_chains)]
#![feature(min_specialization)]
#![feature(negative_impls)]
-#![feature(slice_internals)]
#![feature(stmt_expr_attributes)]
#![recursion_limit = "256"]
#![deny(rustc::untranslatable_diagnostic)]
@@ -42,6 +41,7 @@ pub mod ast_traits;
pub mod attr;
pub mod entry;
pub mod expand;
+pub mod format;
pub mod mut_visit;
pub mod node_id;
pub mod ptr;
@@ -51,6 +51,7 @@ pub mod visit;
pub use self::ast::*;
pub use self::ast_traits::{AstDeref, AstNodeWrapper, HasAttrs, HasNodeId, HasSpan, HasTokens};
+pub use self::format::*;
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs
index 77f342d1e..7dcb03b4c 100644
--- a/compiler/rustc_ast/src/mut_visit.rs
+++ b/compiler/rustc_ast/src/mut_visit.rs
@@ -17,10 +17,10 @@ use rustc_data_structures::sync::Lrc;
use rustc_span::source_map::Spanned;
use rustc_span::symbol::Ident;
use rustc_span::Span;
-
use smallvec::{smallvec, Array, SmallVec};
use std::ops::DerefMut;
use std::{panic, ptr};
+use thin_vec::ThinVec;
pub trait ExpectOne<A: Array> {
fn expect_one(self, err: &'static str) -> A::Item;
@@ -297,6 +297,10 @@ pub trait MutVisitor: Sized {
fn visit_inline_asm_sym(&mut self, sym: &mut InlineAsmSym) {
noop_visit_inline_asm_sym(sym, self)
}
+
+ fn visit_format_args(&mut self, fmt: &mut FormatArgs) {
+ noop_visit_format_args(fmt, self)
+ }
}
/// Use a map-style function (`FnOnce(T) -> T`) to overwrite a `&mut T`. Useful
@@ -333,6 +337,17 @@ where
// No `noop_` prefix because there isn't a corresponding method in `MutVisitor`.
#[inline]
+pub fn visit_thin_vec<T, F>(elems: &mut ThinVec<T>, mut visit_elem: F)
+where
+ F: FnMut(&mut T),
+{
+ for elem in elems {
+ visit_elem(elem);
+ }
+}
+
+// No `noop_` prefix because there isn't a corresponding method in `MutVisitor`.
+#[inline]
pub fn visit_opt<T, F>(opt: &mut Option<T>, mut visit_elem: F)
where
F: FnMut(&mut T),
@@ -355,6 +370,11 @@ pub fn visit_exprs<T: MutVisitor>(exprs: &mut Vec<P<Expr>>, vis: &mut T) {
}
// No `noop_` prefix because there isn't a corresponding method in `MutVisitor`.
+pub fn visit_thin_exprs<T: MutVisitor>(exprs: &mut ThinVec<P<Expr>>, vis: &mut T) {
+ exprs.flat_map_in_place(|expr| vis.filter_map_expr(expr))
+}
+
+// No `noop_` prefix because there isn't a corresponding method in `MutVisitor`.
pub fn visit_bounds<T: MutVisitor>(bounds: &mut GenericBounds, vis: &mut T) {
visit_vec(bounds, |bound| vis.visit_param_bound(bound));
}
@@ -470,7 +490,7 @@ pub fn noop_visit_ty<T: MutVisitor>(ty: &mut P<Ty>, vis: &mut T) {
vis.visit_fn_decl(decl);
vis.visit_span(decl_span);
}
- TyKind::Tup(tys) => visit_vec(tys, |ty| vis.visit_ty(ty)),
+ TyKind::Tup(tys) => visit_thin_vec(tys, |ty| vis.visit_ty(ty)),
TyKind::Paren(ty) => vis.visit_ty(ty),
TyKind::Path(qself, path) => {
vis.visit_qself(qself);
@@ -557,7 +577,7 @@ pub fn noop_visit_angle_bracketed_parameter_data<T: MutVisitor>(
vis: &mut T,
) {
let AngleBracketedArgs { args, span } = data;
- visit_vec(args, |arg| match arg {
+ visit_thin_vec(args, |arg| match arg {
AngleBracketedArg::Arg(arg) => vis.visit_generic_arg(arg),
AngleBracketedArg::Constraint(constraint) => vis.visit_constraint(constraint),
});
@@ -569,7 +589,7 @@ pub fn noop_visit_parenthesized_parameter_data<T: MutVisitor>(
vis: &mut T,
) {
let ParenthesizedArgs { inputs, output, span, .. } = args;
- visit_vec(inputs, |input| vis.visit_ty(input));
+ visit_thin_vec(inputs, |input| vis.visit_ty(input));
noop_visit_fn_ret_ty(output, vis);
vis.visit_span(span);
}
@@ -632,7 +652,7 @@ pub fn noop_visit_meta_item<T: MutVisitor>(mi: &mut MetaItem, vis: &mut T) {
let MetaItem { path: _, kind, span } = mi;
match kind {
MetaItemKind::Word => {}
- MetaItemKind::List(mis) => visit_vec(mis, |mi| vis.visit_meta_list_item(mi)),
+ MetaItemKind::List(mis) => visit_thin_vec(mis, |mi| vis.visit_meta_list_item(mi)),
MetaItemKind::NameValue(_s) => {}
}
vis.visit_span(span);
@@ -835,9 +855,7 @@ pub fn noop_visit_closure_binder<T: MutVisitor>(binder: &mut ClosureBinder, vis:
match binder {
ClosureBinder::NotPresent => {}
ClosureBinder::For { span: _, generic_params } => {
- let mut vec = std::mem::take(generic_params).into_vec();
- vec.flat_map_in_place(|param| vis.flat_map_generic_param(param));
- *generic_params = P::from_vec(vec);
+ generic_params.flat_map_in_place(|param| vis.flat_map_generic_param(param));
}
}
}
@@ -915,7 +933,7 @@ pub fn noop_visit_generics<T: MutVisitor>(generics: &mut Generics, vis: &mut T)
pub fn noop_visit_where_clause<T: MutVisitor>(wc: &mut WhereClause, vis: &mut T) {
let WhereClause { has_where_token: _, predicates, span } = wc;
- visit_vec(predicates, |predicate| vis.visit_where_predicate(predicate));
+ visit_thin_vec(predicates, |predicate| vis.visit_where_predicate(predicate));
vis.visit_span(span);
}
@@ -1223,7 +1241,7 @@ pub fn noop_visit_pat<T: MutVisitor>(pat: &mut P<Pat>, vis: &mut T) {
PatKind::TupleStruct(qself, path, elems) => {
vis.visit_qself(qself);
vis.visit_path(path);
- visit_vec(elems, |elem| vis.visit_pat(elem));
+ visit_thin_vec(elems, |elem| vis.visit_pat(elem));
}
PatKind::Path(qself, path) => {
vis.visit_qself(qself);
@@ -1242,7 +1260,7 @@ pub fn noop_visit_pat<T: MutVisitor>(pat: &mut P<Pat>, vis: &mut T) {
vis.visit_span(span);
}
PatKind::Tuple(elems) | PatKind::Slice(elems) | PatKind::Or(elems) => {
- visit_vec(elems, |elem| vis.visit_pat(elem))
+ visit_thin_vec(elems, |elem| vis.visit_pat(elem))
}
PatKind::Paren(inner) => vis.visit_pat(inner),
PatKind::MacCall(mac) => vis.visit_mac_call(mac),
@@ -1284,13 +1302,22 @@ pub fn noop_visit_inline_asm_sym<T: MutVisitor>(
vis.visit_path(path);
}
+pub fn noop_visit_format_args<T: MutVisitor>(fmt: &mut FormatArgs, vis: &mut T) {
+ for arg in fmt.arguments.all_args_mut() {
+ if let FormatArgumentKind::Named(name) = &mut arg.kind {
+ vis.visit_ident(name);
+ }
+ vis.visit_expr(&mut arg.expr);
+ }
+}
+
pub fn noop_visit_expr<T: MutVisitor>(
Expr { kind, id, span, attrs, tokens }: &mut Expr,
vis: &mut T,
) {
match kind {
ExprKind::Box(expr) => vis.visit_expr(expr),
- ExprKind::Array(exprs) => visit_exprs(exprs, vis),
+ ExprKind::Array(exprs) => visit_thin_exprs(exprs, vis),
ExprKind::ConstBlock(anon_const) => {
vis.visit_anon_const(anon_const);
}
@@ -1298,10 +1325,10 @@ pub fn noop_visit_expr<T: MutVisitor>(
vis.visit_expr(expr);
vis.visit_anon_const(count);
}
- ExprKind::Tup(exprs) => visit_exprs(exprs, vis),
+ ExprKind::Tup(exprs) => visit_thin_exprs(exprs, vis),
ExprKind::Call(f, args) => {
vis.visit_expr(f);
- visit_exprs(args, vis);
+ visit_thin_exprs(args, vis);
}
ExprKind::MethodCall(box MethodCall {
seg: PathSegment { ident, id, args: seg_args },
@@ -1313,7 +1340,7 @@ pub fn noop_visit_expr<T: MutVisitor>(
vis.visit_id(id);
visit_opt(seg_args, |args| vis.visit_generic_args(args));
vis.visit_method_receiver_expr(receiver);
- visit_exprs(call_args, vis);
+ visit_thin_exprs(call_args, vis);
vis.visit_span(span);
}
ExprKind::Binary(_binop, lhs, rhs) => {
@@ -1425,6 +1452,7 @@ pub fn noop_visit_expr<T: MutVisitor>(
visit_opt(expr, |expr| vis.visit_expr(expr));
}
ExprKind::InlineAsm(asm) => vis.visit_inline_asm(asm),
+ ExprKind::FormatArgs(fmt) => vis.visit_format_args(fmt),
ExprKind::MacCall(mac) => vis.visit_mac_call(mac),
ExprKind::Struct(se) => {
let StructExpr { qself, path, fields, rest } = se.deref_mut();
diff --git a/compiler/rustc_ast/src/tokenstream.rs b/compiler/rustc_ast/src/tokenstream.rs
index fabd43a16..f0a6a5e07 100644
--- a/compiler/rustc_ast/src/tokenstream.rs
+++ b/compiler/rustc_ast/src/tokenstream.rs
@@ -41,7 +41,8 @@ use std::{fmt, iter};
/// Nothing special happens to misnamed or misplaced `SubstNt`s.
#[derive(Debug, Clone, PartialEq, Encodable, Decodable, HashStable_Generic)]
pub enum TokenTree {
- /// A single token.
+ /// A single token. Should never be `OpenDelim` or `CloseDelim`, because
+ /// delimiters are implicitly represented by `Delimited`.
Token(Token, Spacing),
/// A delimited sequence of token trees.
Delimited(DelimSpan, Delimiter, TokenStream),
@@ -388,12 +389,12 @@ impl TokenStream {
self.0.len()
}
- pub fn trees(&self) -> CursorRef<'_> {
- CursorRef::new(self)
+ pub fn trees(&self) -> RefTokenTreeCursor<'_> {
+ RefTokenTreeCursor::new(self)
}
- pub fn into_trees(self) -> Cursor {
- Cursor::new(self)
+ pub fn into_trees(self) -> TokenTreeCursor {
+ TokenTreeCursor::new(self)
}
/// Compares two `TokenStream`s, checking equality without regarding span information.
@@ -551,16 +552,17 @@ impl TokenStream {
}
}
-/// By-reference iterator over a [`TokenStream`].
+/// By-reference iterator over a [`TokenStream`], that produces `&TokenTree`
+/// items.
#[derive(Clone)]
-pub struct CursorRef<'t> {
+pub struct RefTokenTreeCursor<'t> {
stream: &'t TokenStream,
index: usize,
}
-impl<'t> CursorRef<'t> {
+impl<'t> RefTokenTreeCursor<'t> {
fn new(stream: &'t TokenStream) -> Self {
- CursorRef { stream, index: 0 }
+ RefTokenTreeCursor { stream, index: 0 }
}
pub fn look_ahead(&self, n: usize) -> Option<&TokenTree> {
@@ -568,7 +570,7 @@ impl<'t> CursorRef<'t> {
}
}
-impl<'t> Iterator for CursorRef<'t> {
+impl<'t> Iterator for RefTokenTreeCursor<'t> {
type Item = &'t TokenTree;
fn next(&mut self) -> Option<&'t TokenTree> {
@@ -579,15 +581,16 @@ impl<'t> Iterator for CursorRef<'t> {
}
}
-/// Owning by-value iterator over a [`TokenStream`].
+/// Owning by-value iterator over a [`TokenStream`], that produces `TokenTree`
+/// items.
// FIXME: Many uses of this can be replaced with by-reference iterator to avoid clones.
#[derive(Clone)]
-pub struct Cursor {
+pub struct TokenTreeCursor {
pub stream: TokenStream,
index: usize,
}
-impl Iterator for Cursor {
+impl Iterator for TokenTreeCursor {
type Item = TokenTree;
fn next(&mut self) -> Option<TokenTree> {
@@ -598,9 +601,9 @@ impl Iterator for Cursor {
}
}
-impl Cursor {
+impl TokenTreeCursor {
fn new(stream: TokenStream) -> Self {
- Cursor { stream, index: 0 }
+ TokenTreeCursor { stream, index: 0 }
}
#[inline]
@@ -614,6 +617,15 @@ impl Cursor {
pub fn look_ahead(&self, n: usize) -> Option<&TokenTree> {
self.stream.0.get(self.index + n)
}
+
+ // Replace the previously obtained token tree with `tts`, and rewind to
+ // just before them.
+ pub fn replace_prev_and_rewind(&mut self, tts: Vec<TokenTree>) {
+ assert!(self.index > 0);
+ self.index -= 1;
+ let stream = Lrc::make_mut(&mut self.stream.0);
+ stream.splice(self.index..self.index + 1, tts);
+ }
}
#[derive(Debug, Copy, Clone, PartialEq, Encodable, Decodable, HashStable_Generic)]
diff --git a/compiler/rustc_ast/src/util/comments.rs b/compiler/rustc_ast/src/util/comments.rs
index 275ed02c2..eece99a3e 100644
--- a/compiler/rustc_ast/src/util/comments.rs
+++ b/compiler/rustc_ast/src/util/comments.rs
@@ -58,23 +58,24 @@ pub fn beautify_doc_string(data: Symbol, kind: CommentKind) -> Symbol {
// In case we have doc comments like `/**` or `/*!`, we want to remove stars if they are
// present. However, we first need to strip the empty lines so they don't get in the middle
// when we try to compute the "horizontal trim".
- let lines = if kind == CommentKind::Block {
- // Whatever happens, we skip the first line.
- let mut i = lines
- .get(0)
- .map(|l| if l.trim_start().starts_with('*') { 0 } else { 1 })
- .unwrap_or(0);
- let mut j = lines.len();
-
- while i < j && lines[i].trim().is_empty() {
- i += 1;
- }
- while j > i && lines[j - 1].trim().is_empty() {
- j -= 1;
+ let lines = match kind {
+ CommentKind::Block => {
+ // Whatever happens, we skip the first line.
+ let mut i = lines
+ .get(0)
+ .map(|l| if l.trim_start().starts_with('*') { 0 } else { 1 })
+ .unwrap_or(0);
+ let mut j = lines.len();
+
+ while i < j && lines[i].trim().is_empty() {
+ i += 1;
+ }
+ while j > i && lines[j - 1].trim().is_empty() {
+ j -= 1;
+ }
+ &lines[i..j]
}
- &lines[i..j]
- } else {
- lines
+ CommentKind::Line => lines,
};
for line in lines {
diff --git a/compiler/rustc_ast/src/util/parser.rs b/compiler/rustc_ast/src/util/parser.rs
index 4f7099c7b..3a0af04f9 100644
--- a/compiler/rustc_ast/src/util/parser.rs
+++ b/compiler/rustc_ast/src/util/parser.rs
@@ -225,7 +225,7 @@ impl AssocOp {
AssignOp(_) | // `{ 42 } +=`
As | // `{ 42 } as usize`
// Equal | // `{ 42 } == { 42 }` Accepting these here would regress incorrect
- // NotEqual | // `{ 42 } != { 42 } struct literals parser recovery.
+ // NotEqual | // `{ 42 } != { 42 }` struct literals parser recovery.
Colon, // `{ 42 }: usize`
)
}
@@ -271,6 +271,7 @@ pub enum ExprPrecedence {
Try,
InlineAsm,
Mac,
+ FormatArgs,
Array,
Repeat,
@@ -335,7 +336,8 @@ impl ExprPrecedence {
| ExprPrecedence::Index
| ExprPrecedence::Try
| ExprPrecedence::InlineAsm
- | ExprPrecedence::Mac => PREC_POSTFIX,
+ | ExprPrecedence::Mac
+ | ExprPrecedence::FormatArgs => PREC_POSTFIX,
// Never need parens
ExprPrecedence::Array
diff --git a/compiler/rustc_ast/src/util/unicode.rs b/compiler/rustc_ast/src/util/unicode.rs
index 0eae791b2..6f57d66b2 100644
--- a/compiler/rustc_ast/src/util/unicode.rs
+++ b/compiler/rustc_ast/src/util/unicode.rs
@@ -17,7 +17,7 @@ pub fn contains_text_flow_control_chars(s: &str) -> bool {
// U+2069 - E2 81 A9
let mut bytes = s.as_bytes();
loop {
- match core::slice::memchr::memchr(0xE2, bytes) {
+ match memchr::memchr(0xE2, bytes) {
Some(idx) => {
// bytes are valid UTF-8 -> E2 must be followed by two bytes
let ch = &bytes[idx..idx + 3];
diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs
index e8823eff8..bdb1879ec 100644
--- a/compiler/rustc_ast/src/visit.rs
+++ b/compiler/rustc_ast/src/visit.rs
@@ -242,6 +242,9 @@ pub trait Visitor<'ast>: Sized {
fn visit_inline_asm(&mut self, asm: &'ast InlineAsm) {
walk_inline_asm(self, asm)
}
+ fn visit_format_args(&mut self, fmt: &'ast FormatArgs) {
+ walk_format_args(self, fmt)
+ }
fn visit_inline_asm_sym(&mut self, sym: &'ast InlineAsmSym) {
walk_inline_asm_sym(self, sym)
}
@@ -756,6 +759,15 @@ pub fn walk_inline_asm_sym<'a, V: Visitor<'a>>(visitor: &mut V, sym: &'a InlineA
visitor.visit_path(&sym.path, sym.id);
}
+pub fn walk_format_args<'a, V: Visitor<'a>>(visitor: &mut V, fmt: &'a FormatArgs) {
+ for arg in fmt.arguments.all_args() {
+ if let FormatArgumentKind::Named(name) = arg.kind {
+ visitor.visit_ident(name);
+ }
+ visitor.visit_expr(&arg.expr);
+ }
+}
+
pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) {
walk_list!(visitor, visit_attribute, expression.attrs.iter());
@@ -896,6 +908,7 @@ pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) {
ExprKind::MacCall(mac) => visitor.visit_mac_call(mac),
ExprKind::Paren(subexpression) => visitor.visit_expr(subexpression),
ExprKind::InlineAsm(asm) => visitor.visit_inline_asm(asm),
+ ExprKind::FormatArgs(f) => visitor.visit_format_args(f),
ExprKind::Yield(optional_expression) => {
walk_list!(visitor, visit_expr, optional_expression);
}
diff --git a/compiler/rustc_ast_lowering/Cargo.toml b/compiler/rustc_ast_lowering/Cargo.toml
index 6a59b9e61..eb2e82d79 100644
--- a/compiler/rustc_ast_lowering/Cargo.toml
+++ b/compiler/rustc_ast_lowering/Cargo.toml
@@ -7,7 +7,6 @@ edition = "2021"
doctest = false
[dependencies]
-rustc_arena = { path = "../rustc_arena" }
rustc_ast = { path = "../rustc_ast" }
rustc_ast_pretty = { path = "../rustc_ast_pretty" }
rustc_data_structures = { path = "../rustc_data_structures" }
@@ -16,10 +15,9 @@ rustc_hir = { path = "../rustc_hir" }
rustc_index = { path = "../rustc_index" }
rustc_middle = { path = "../rustc_middle" }
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" }
smallvec = { version = "1.8.1", features = ["union", "may_dangle"] }
-thin-vec = "0.2.9"
+thin-vec = "0.2.12"
tracing = "0.1"
diff --git a/compiler/rustc_error_messages/locales/en-US/ast_lowering.ftl b/compiler/rustc_ast_lowering/locales/en-US.ftl
index 03c88c6c0..3ccd84398 100644
--- a/compiler/rustc_error_messages/locales/en-US/ast_lowering.ftl
+++ b/compiler/rustc_ast_lowering/locales/en-US.ftl
@@ -19,8 +19,8 @@ ast_lowering_remove_parentheses = remove these parentheses
ast_lowering_misplaced_impl_trait =
`impl Trait` only allowed in function and inherent method return types, not in {$position}
-ast_lowering_rustc_box_attribute_error =
- #[rustc_box] requires precisely one argument and no other attributes are allowed
+ast_lowering_misplaced_assoc_ty_binding =
+ associated type bounds are only allowed in where clauses and function signatures, not in {$position}
ast_lowering_underscore_expr_lhs_assign =
in expressions, `_` can only be used on the left-hand side of an assignment
diff --git a/compiler/rustc_ast_lowering/src/errors.rs b/compiler/rustc_ast_lowering/src/errors.rs
index 21c6a2d26..5e6b6050b 100644
--- a/compiler/rustc_ast_lowering/src/errors.rs
+++ b/compiler/rustc_ast_lowering/src/errors.rs
@@ -79,11 +79,12 @@ pub struct MisplacedImplTrait<'a> {
pub position: DiagnosticArgFromDisplay<'a>,
}
-#[derive(Diagnostic, Clone, Copy)]
-#[diag(ast_lowering_rustc_box_attribute_error)]
-pub struct RustcBoxAttributeError {
+#[derive(Diagnostic)]
+#[diag(ast_lowering_misplaced_assoc_ty_binding)]
+pub struct MisplacedAssocTyBinding<'a> {
#[primary_span]
pub span: Span,
+ pub position: DiagnosticArgFromDisplay<'a>,
}
#[derive(Diagnostic, Clone, Copy)]
@@ -339,7 +340,7 @@ pub struct InclusiveRangeWithNoEnd {
#[derive(Diagnostic, Clone, Copy)]
#[diag(ast_lowering_trait_fn_async, code = "E0706")]
#[note]
-#[note(note2)]
+#[note(ast_lowering_note2)]
pub struct TraitFnAsync {
#[primary_span]
pub fn_span: Span,
diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs
index c3611b2f5..ffb30b1b3 100644
--- a/compiler/rustc_ast_lowering/src/expr.rs
+++ b/compiler/rustc_ast_lowering/src/expr.rs
@@ -2,7 +2,7 @@ use super::errors::{
AsyncGeneratorsNotSupported, AsyncNonMoveClosureNotSupported, AwaitOnlyInAsyncFnAndBlocks,
BaseExpressionDoubleDot, ClosureCannotBeStatic, FunctionalRecordUpdateDestructuringAssignemnt,
GeneratorTooManyParameters, InclusiveRangeWithNoEnd, NotSupportedForLifetimeBinderAsyncClosure,
- RustcBoxAttributeError, UnderscoreExprLhsAssign,
+ UnderscoreExprLhsAssign,
};
use super::ResolverAstLoweringExt;
use super::{ImplTraitContext, LoweringContext, ParamMode, ParenthesizedGenericArgs};
@@ -16,9 +16,9 @@ use rustc_hir::def::Res;
use rustc_hir::definitions::DefPathData;
use rustc_session::errors::report_lit_error;
use rustc_span::source_map::{respan, DesugaringKind, Span, Spanned};
-use rustc_span::symbol::{sym, Ident};
+use rustc_span::symbol::{sym, Ident, Symbol};
use rustc_span::DUMMY_SP;
-use thin_vec::thin_vec;
+use thin_vec::{thin_vec, ThinVec};
impl<'hir> LoweringContext<'_, 'hir> {
fn lower_exprs(&mut self, exprs: &[AstP<Expr>]) -> &'hir [hir::Expr<'hir>] {
@@ -83,15 +83,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
}
ExprKind::Tup(elts) => hir::ExprKind::Tup(self.lower_exprs(elts)),
ExprKind::Call(f, args) => {
- if e.attrs.get(0).map_or(false, |a| a.has_name(sym::rustc_box)) {
- if let [inner] = &args[..] && e.attrs.len() == 1 {
- let kind = hir::ExprKind::Box(self.lower_expr(&inner));
- return hir::Expr { hir_id, kind, span: self.lower_span(e.span) };
- } else {
- self.tcx.sess.emit_err(RustcBoxAttributeError { span: e.span });
- hir::ExprKind::Err
- }
- } else if let Some(legacy_args) = self.resolver.legacy_const_generic_args(f) {
+ if let Some(legacy_args) = self.resolver.legacy_const_generic_args(f) {
self.lower_legacy_const_generics((**f).clone(), args.clone(), &legacy_args)
} else {
let f = self.lower_expr(f);
@@ -139,13 +131,13 @@ impl<'hir> LoweringContext<'_, 'hir> {
ExprKind::Cast(expr, ty) => {
let expr = self.lower_expr(expr);
let ty =
- self.lower_ty(ty, &ImplTraitContext::Disallowed(ImplTraitPosition::Type));
+ self.lower_ty(ty, &ImplTraitContext::Disallowed(ImplTraitPosition::Cast));
hir::ExprKind::Cast(expr, ty)
}
ExprKind::Type(expr, ty) => {
let expr = self.lower_expr(expr);
let ty =
- self.lower_ty(ty, &ImplTraitContext::Disallowed(ImplTraitPosition::Type));
+ self.lower_ty(ty, &ImplTraitContext::Disallowed(ImplTraitPosition::Cast));
hir::ExprKind::Type(expr, ty)
}
ExprKind::AddrOf(k, m, ohs) => {
@@ -266,8 +258,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
self.lower_expr_range(e.span, e1.as_deref(), e2.as_deref(), *lims)
}
ExprKind::Underscore => {
- self.tcx.sess.emit_err(UnderscoreExprLhsAssign { span: e.span });
- hir::ExprKind::Err
+ let guar = self.tcx.sess.emit_err(UnderscoreExprLhsAssign { span: e.span });
+ hir::ExprKind::Err(guar)
}
ExprKind::Path(qself, path) => {
let qpath = self.lower_qpath(
@@ -294,12 +286,14 @@ impl<'hir> LoweringContext<'_, 'hir> {
ExprKind::InlineAsm(asm) => {
hir::ExprKind::InlineAsm(self.lower_inline_asm(e.span, asm))
}
+ ExprKind::FormatArgs(fmt) => self.lower_format_args(e.span, fmt),
ExprKind::Struct(se) => {
let rest = match &se.rest {
StructRest::Base(e) => Some(self.lower_expr(e)),
StructRest::Rest(sp) => {
- self.tcx.sess.emit_err(BaseExpressionDoubleDot { span: *sp });
- Some(&*self.arena.alloc(self.expr_err(*sp)))
+ let guar =
+ self.tcx.sess.emit_err(BaseExpressionDoubleDot { span: *sp });
+ Some(&*self.arena.alloc(self.expr_err(*sp, guar)))
}
StructRest::None => None,
};
@@ -317,7 +311,9 @@ impl<'hir> LoweringContext<'_, 'hir> {
)
}
ExprKind::Yield(opt_expr) => self.lower_expr_yield(e.span, opt_expr.as_deref()),
- ExprKind::Err => hir::ExprKind::Err,
+ ExprKind::Err => hir::ExprKind::Err(
+ self.tcx.sess.delay_span_bug(e.span, "lowered ExprKind::Err"),
+ ),
ExprKind::Try(sub_expr) => self.lower_expr_try(e.span, sub_expr),
ExprKind::Paren(_) | ExprKind::ForLoop(..) => unreachable!("already handled"),
@@ -366,7 +362,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
fn lower_legacy_const_generics(
&mut self,
mut f: Expr,
- args: Vec<AstP<Expr>>,
+ args: ThinVec<AstP<Expr>>,
legacy_args_idx: &[usize],
) -> hir::ExprKind<'hir> {
let ExprKind::Path(None, path) = &mut f.kind else {
@@ -375,7 +371,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
// Split the arguments into const generics and normal arguments
let mut real_args = vec![];
- let mut generic_args = vec![];
+ let mut generic_args = ThinVec::new();
for (idx, arg) in args.into_iter().enumerate() {
if legacy_args_idx.contains(&idx) {
let parent_def_id = self.current_hir_id_owner;
@@ -760,7 +756,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
self.expr_ident_mut(span, task_context_ident, task_context_hid)
} else {
// Use of `await` outside of an async context, we cannot use `task_context` here.
- self.expr_err(span)
+ self.expr_err(span, self.tcx.sess.delay_span_bug(span, "no task_context hir id"))
};
let new_unchecked = self.expr_call_lang_item_fn_mut(
span,
@@ -1735,7 +1731,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
self.expr(span, hir::ExprKind::DropTemps(expr))
}
- fn expr_match(
+ pub(super) fn expr_match(
&mut self,
span: Span,
arg: &'hir hir::Expr<'hir>,
@@ -1763,7 +1759,44 @@ impl<'hir> LoweringContext<'_, 'hir> {
self.arena.alloc(self.expr(sp, hir::ExprKind::Tup(&[])))
}
- fn expr_call_mut(
+ pub(super) fn expr_usize(&mut self, sp: Span, value: usize) -> hir::Expr<'hir> {
+ self.expr(
+ sp,
+ hir::ExprKind::Lit(hir::Lit {
+ span: sp,
+ node: ast::LitKind::Int(
+ value as u128,
+ ast::LitIntType::Unsigned(ast::UintTy::Usize),
+ ),
+ }),
+ )
+ }
+
+ pub(super) fn expr_u32(&mut self, sp: Span, value: u32) -> hir::Expr<'hir> {
+ self.expr(
+ sp,
+ hir::ExprKind::Lit(hir::Lit {
+ span: sp,
+ node: ast::LitKind::Int(value.into(), ast::LitIntType::Unsigned(ast::UintTy::U32)),
+ }),
+ )
+ }
+
+ pub(super) fn expr_char(&mut self, sp: Span, value: char) -> hir::Expr<'hir> {
+ self.expr(sp, hir::ExprKind::Lit(hir::Lit { span: sp, node: ast::LitKind::Char(value) }))
+ }
+
+ pub(super) fn expr_str(&mut self, sp: Span, value: Symbol) -> hir::Expr<'hir> {
+ self.expr(
+ sp,
+ hir::ExprKind::Lit(hir::Lit {
+ span: sp,
+ node: ast::LitKind::Str(value, ast::StrStyle::Cooked),
+ }),
+ )
+ }
+
+ pub(super) fn expr_call_mut(
&mut self,
span: Span,
e: &'hir hir::Expr<'hir>,
@@ -1772,7 +1805,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
self.expr(span, hir::ExprKind::Call(e, args))
}
- fn expr_call(
+ pub(super) fn expr_call(
&mut self,
span: Span,
e: &'hir hir::Expr<'hir>,
@@ -1814,6 +1847,27 @@ impl<'hir> LoweringContext<'_, 'hir> {
)
}
+ /// `<LangItem>::name`
+ pub(super) fn expr_lang_item_type_relative(
+ &mut self,
+ span: Span,
+ lang_item: hir::LangItem,
+ name: Symbol,
+ ) -> hir::Expr<'hir> {
+ let path = hir::ExprKind::Path(hir::QPath::TypeRelative(
+ self.arena.alloc(self.ty(
+ span,
+ hir::TyKind::Path(hir::QPath::LangItem(lang_item, self.lower_span(span), None)),
+ )),
+ self.arena.alloc(hir::PathSegment::new(
+ Ident::new(name, span),
+ self.next_id(),
+ Res::Err,
+ )),
+ ));
+ self.expr(span, path)
+ }
+
pub(super) fn expr_ident(
&mut self,
sp: Span,
@@ -1872,12 +1926,25 @@ impl<'hir> LoweringContext<'_, 'hir> {
self.expr(b.span, hir::ExprKind::Block(b, None))
}
+ pub(super) fn expr_array_ref(
+ &mut self,
+ span: Span,
+ elements: &'hir [hir::Expr<'hir>],
+ ) -> hir::Expr<'hir> {
+ let addrof = hir::ExprKind::AddrOf(
+ hir::BorrowKind::Ref,
+ hir::Mutability::Not,
+ self.arena.alloc(self.expr(span, hir::ExprKind::Array(elements))),
+ );
+ self.expr(span, addrof)
+ }
+
pub(super) fn expr(&mut self, span: Span, kind: hir::ExprKind<'hir>) -> hir::Expr<'hir> {
let hir_id = self.next_id();
hir::Expr { hir_id, kind, span: self.lower_span(span) }
}
- fn expr_field(
+ pub(super) fn expr_field(
&mut self,
ident: Ident,
expr: &'hir hir::Expr<'hir>,
@@ -1892,7 +1959,11 @@ impl<'hir> LoweringContext<'_, 'hir> {
}
}
- fn arm(&mut self, pat: &'hir hir::Pat<'hir>, expr: &'hir hir::Expr<'hir>) -> hir::Arm<'hir> {
+ pub(super) fn arm(
+ &mut self,
+ pat: &'hir hir::Pat<'hir>,
+ expr: &'hir hir::Expr<'hir>,
+ ) -> hir::Arm<'hir> {
hir::Arm {
hir_id: self.next_id(),
pat,
diff --git a/compiler/rustc_ast_lowering/src/format.rs b/compiler/rustc_ast_lowering/src/format.rs
new file mode 100644
index 000000000..4095e225a
--- /dev/null
+++ b/compiler/rustc_ast_lowering/src/format.rs
@@ -0,0 +1,411 @@
+use super::LoweringContext;
+use rustc_ast as ast;
+use rustc_ast::visit::{self, Visitor};
+use rustc_ast::*;
+use rustc_data_structures::fx::FxIndexSet;
+use rustc_hir as hir;
+use rustc_span::{
+ sym,
+ symbol::{kw, Ident},
+ Span,
+};
+
+impl<'hir> LoweringContext<'_, 'hir> {
+ pub(crate) fn lower_format_args(&mut self, sp: Span, fmt: &FormatArgs) -> hir::ExprKind<'hir> {
+ expand_format_args(self, sp, fmt)
+ }
+}
+
+#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
+enum ArgumentType {
+ Format(FormatTrait),
+ Usize,
+}
+
+/// Generate a hir expression representing an argument to a format_args invocation.
+///
+/// Generates:
+///
+/// ```text
+/// <core::fmt::ArgumentV1>::new_…(arg)
+/// ```
+fn make_argument<'hir>(
+ ctx: &mut LoweringContext<'_, 'hir>,
+ sp: Span,
+ arg: &'hir hir::Expr<'hir>,
+ ty: ArgumentType,
+) -> hir::Expr<'hir> {
+ use ArgumentType::*;
+ use FormatTrait::*;
+ let new_fn = ctx.arena.alloc(ctx.expr_lang_item_type_relative(
+ sp,
+ hir::LangItem::FormatArgument,
+ match ty {
+ Format(Display) => sym::new_display,
+ Format(Debug) => sym::new_debug,
+ Format(LowerExp) => sym::new_lower_exp,
+ Format(UpperExp) => sym::new_upper_exp,
+ Format(Octal) => sym::new_octal,
+ Format(Pointer) => sym::new_pointer,
+ Format(Binary) => sym::new_binary,
+ Format(LowerHex) => sym::new_lower_hex,
+ Format(UpperHex) => sym::new_upper_hex,
+ Usize => sym::from_usize,
+ },
+ ));
+ ctx.expr_call_mut(sp, new_fn, std::slice::from_ref(arg))
+}
+
+/// Generate a hir expression for a format_args Count.
+///
+/// Generates:
+///
+/// ```text
+/// <core::fmt::rt::v1::Count>::Is(…)
+/// ```
+///
+/// or
+///
+/// ```text
+/// <core::fmt::rt::v1::Count>::Param(…)
+/// ```
+///
+/// or
+///
+/// ```text
+/// <core::fmt::rt::v1::Count>::Implied
+/// ```
+fn make_count<'hir>(
+ ctx: &mut LoweringContext<'_, 'hir>,
+ sp: Span,
+ count: &Option<FormatCount>,
+ argmap: &mut FxIndexSet<(usize, ArgumentType)>,
+) -> hir::Expr<'hir> {
+ match count {
+ Some(FormatCount::Literal(n)) => {
+ let count_is = ctx.arena.alloc(ctx.expr_lang_item_type_relative(
+ sp,
+ hir::LangItem::FormatCount,
+ sym::Is,
+ ));
+ let value = ctx.arena.alloc_from_iter([ctx.expr_usize(sp, *n)]);
+ ctx.expr_call_mut(sp, count_is, value)
+ }
+ Some(FormatCount::Argument(arg)) => {
+ if let Ok(arg_index) = arg.index {
+ let (i, _) = argmap.insert_full((arg_index, ArgumentType::Usize));
+ let count_param = ctx.arena.alloc(ctx.expr_lang_item_type_relative(
+ sp,
+ hir::LangItem::FormatCount,
+ sym::Param,
+ ));
+ let value = ctx.arena.alloc_from_iter([ctx.expr_usize(sp, i)]);
+ ctx.expr_call_mut(sp, count_param, value)
+ } else {
+ ctx.expr(
+ sp,
+ hir::ExprKind::Err(
+ ctx.tcx.sess.delay_span_bug(sp, "lowered bad format_args count"),
+ ),
+ )
+ }
+ }
+ None => ctx.expr_lang_item_type_relative(sp, hir::LangItem::FormatCount, sym::Implied),
+ }
+}
+
+/// Generate a hir expression for a format_args placeholder specification.
+///
+/// Generates
+///
+/// ```text
+/// <core::fmt::rt::v1::Argument::new(
+/// …usize, // position
+/// '…', // fill
+/// <core::fmt::rt::v1::Alignment>::…, // alignment
+/// …u32, // flags
+/// <core::fmt::rt::v1::Count::…>, // width
+/// <core::fmt::rt::v1::Count::…>, // precision
+/// )
+/// ```
+fn make_format_spec<'hir>(
+ ctx: &mut LoweringContext<'_, 'hir>,
+ sp: Span,
+ placeholder: &FormatPlaceholder,
+ argmap: &mut FxIndexSet<(usize, ArgumentType)>,
+) -> hir::Expr<'hir> {
+ let position = match placeholder.argument.index {
+ Ok(arg_index) => {
+ let (i, _) =
+ argmap.insert_full((arg_index, ArgumentType::Format(placeholder.format_trait)));
+ ctx.expr_usize(sp, i)
+ }
+ Err(_) => ctx.expr(
+ sp,
+ hir::ExprKind::Err(ctx.tcx.sess.delay_span_bug(sp, "lowered bad format_args count")),
+ ),
+ };
+ let &FormatOptions {
+ ref width,
+ ref precision,
+ alignment,
+ fill,
+ sign,
+ alternate,
+ zero_pad,
+ debug_hex,
+ } = &placeholder.format_options;
+ let fill = ctx.expr_char(sp, fill.unwrap_or(' '));
+ let align = ctx.expr_lang_item_type_relative(
+ sp,
+ hir::LangItem::FormatAlignment,
+ match alignment {
+ Some(FormatAlignment::Left) => sym::Left,
+ Some(FormatAlignment::Right) => sym::Right,
+ Some(FormatAlignment::Center) => sym::Center,
+ None => sym::Unknown,
+ },
+ );
+ // This needs to match `FlagV1` in library/core/src/fmt/mod.rs.
+ let flags: u32 = ((sign == Some(FormatSign::Plus)) as u32)
+ | ((sign == Some(FormatSign::Minus)) as u32) << 1
+ | (alternate as u32) << 2
+ | (zero_pad as u32) << 3
+ | ((debug_hex == Some(FormatDebugHex::Lower)) as u32) << 4
+ | ((debug_hex == Some(FormatDebugHex::Upper)) as u32) << 5;
+ let flags = ctx.expr_u32(sp, flags);
+ let precision = make_count(ctx, sp, &precision, argmap);
+ let width = make_count(ctx, sp, &width, argmap);
+ let format_placeholder_new = ctx.arena.alloc(ctx.expr_lang_item_type_relative(
+ sp,
+ hir::LangItem::FormatPlaceholder,
+ sym::new,
+ ));
+ let args = ctx.arena.alloc_from_iter([position, fill, align, flags, precision, width]);
+ ctx.expr_call_mut(sp, format_placeholder_new, args)
+}
+
+fn expand_format_args<'hir>(
+ ctx: &mut LoweringContext<'_, 'hir>,
+ macsp: Span,
+ fmt: &FormatArgs,
+) -> hir::ExprKind<'hir> {
+ let lit_pieces =
+ ctx.arena.alloc_from_iter(fmt.template.iter().enumerate().filter_map(|(i, piece)| {
+ match piece {
+ &FormatArgsPiece::Literal(s) => Some(ctx.expr_str(fmt.span, s)),
+ &FormatArgsPiece::Placeholder(_) => {
+ // Inject empty string before placeholders when not already preceded by a literal piece.
+ if i == 0 || matches!(fmt.template[i - 1], FormatArgsPiece::Placeholder(_)) {
+ Some(ctx.expr_str(fmt.span, kw::Empty))
+ } else {
+ None
+ }
+ }
+ }
+ }));
+ let lit_pieces = ctx.expr_array_ref(fmt.span, lit_pieces);
+
+ // Whether we'll use the `Arguments::new_v1_formatted` form (true),
+ // or the `Arguments::new_v1` form (false).
+ let mut use_format_options = false;
+
+ // Create a list of all _unique_ (argument, format trait) combinations.
+ // E.g. "{0} {0:x} {0} {1}" -> [(0, Display), (0, LowerHex), (1, Display)]
+ let mut argmap = FxIndexSet::default();
+ for piece in &fmt.template {
+ let FormatArgsPiece::Placeholder(placeholder) = piece else { continue };
+ if placeholder.format_options != Default::default() {
+ // Can't use basic form if there's any formatting options.
+ use_format_options = true;
+ }
+ if let Ok(index) = placeholder.argument.index {
+ if !argmap.insert((index, ArgumentType::Format(placeholder.format_trait))) {
+ // Duplicate (argument, format trait) combination,
+ // which we'll only put once in the args array.
+ use_format_options = true;
+ }
+ }
+ }
+
+ let format_options = use_format_options.then(|| {
+ // Generate:
+ // &[format_spec_0, format_spec_1, format_spec_2]
+ let elements: Vec<_> = fmt
+ .template
+ .iter()
+ .filter_map(|piece| {
+ let FormatArgsPiece::Placeholder(placeholder) = piece else { return None };
+ Some(make_format_spec(ctx, macsp, placeholder, &mut argmap))
+ })
+ .collect();
+ ctx.expr_array_ref(macsp, ctx.arena.alloc_from_iter(elements))
+ });
+
+ let arguments = fmt.arguments.all_args();
+
+ // If the args array contains exactly all the original arguments once,
+ // in order, we can use a simple array instead of a `match` construction.
+ // However, if there's a yield point in any argument except the first one,
+ // we don't do this, because an ArgumentV1 cannot be kept across yield points.
+ //
+ // This is an optimization, speeding up compilation about 1-2% in some cases.
+ // See https://github.com/rust-lang/rust/pull/106770#issuecomment-1380790609
+ let use_simple_array = argmap.len() == arguments.len()
+ && argmap.iter().enumerate().all(|(i, &(j, _))| i == j)
+ && arguments.iter().skip(1).all(|arg| !may_contain_yield_point(&arg.expr));
+
+ let args = if use_simple_array {
+ // Generate:
+ // &[
+ // <core::fmt::ArgumentV1>::new_display(&arg0),
+ // <core::fmt::ArgumentV1>::new_lower_hex(&arg1),
+ // <core::fmt::ArgumentV1>::new_debug(&arg2),
+ // …
+ // ]
+ let elements: Vec<_> = arguments
+ .iter()
+ .zip(argmap)
+ .map(|(arg, (_, ty))| {
+ let sp = arg.expr.span.with_ctxt(macsp.ctxt());
+ let arg = ctx.lower_expr(&arg.expr);
+ let ref_arg = ctx.arena.alloc(ctx.expr(
+ sp,
+ hir::ExprKind::AddrOf(hir::BorrowKind::Ref, hir::Mutability::Not, arg),
+ ));
+ make_argument(ctx, sp, ref_arg, ty)
+ })
+ .collect();
+ ctx.expr_array_ref(macsp, ctx.arena.alloc_from_iter(elements))
+ } else {
+ // Generate:
+ // &match (&arg0, &arg1, &…) {
+ // args => [
+ // <core::fmt::ArgumentV1>::new_display(args.0),
+ // <core::fmt::ArgumentV1>::new_lower_hex(args.1),
+ // <core::fmt::ArgumentV1>::new_debug(args.0),
+ // …
+ // ]
+ // }
+ let args_ident = Ident::new(sym::args, macsp);
+ let (args_pat, args_hir_id) = ctx.pat_ident(macsp, args_ident);
+ let args = ctx.arena.alloc_from_iter(argmap.iter().map(|&(arg_index, ty)| {
+ if let Some(arg) = arguments.get(arg_index) {
+ let sp = arg.expr.span.with_ctxt(macsp.ctxt());
+ let args_ident_expr = ctx.expr_ident(macsp, args_ident, args_hir_id);
+ let arg = ctx.arena.alloc(ctx.expr(
+ sp,
+ hir::ExprKind::Field(
+ args_ident_expr,
+ Ident::new(sym::integer(arg_index), macsp),
+ ),
+ ));
+ make_argument(ctx, sp, arg, ty)
+ } else {
+ ctx.expr(
+ macsp,
+ hir::ExprKind::Err(
+ ctx.tcx.sess.delay_span_bug(macsp, format!("no arg at {arg_index}")),
+ ),
+ )
+ }
+ }));
+ let elements: Vec<_> = arguments
+ .iter()
+ .map(|arg| {
+ let arg_expr = ctx.lower_expr(&arg.expr);
+ ctx.expr(
+ arg.expr.span.with_ctxt(macsp.ctxt()),
+ hir::ExprKind::AddrOf(hir::BorrowKind::Ref, hir::Mutability::Not, arg_expr),
+ )
+ })
+ .collect();
+ let args_tuple = ctx
+ .arena
+ .alloc(ctx.expr(macsp, hir::ExprKind::Tup(ctx.arena.alloc_from_iter(elements))));
+ let array = ctx.arena.alloc(ctx.expr(macsp, hir::ExprKind::Array(args)));
+ let match_arms = ctx.arena.alloc_from_iter([ctx.arm(args_pat, array)]);
+ let match_expr = ctx.arena.alloc(ctx.expr_match(
+ macsp,
+ args_tuple,
+ match_arms,
+ hir::MatchSource::FormatArgs,
+ ));
+ ctx.expr(
+ macsp,
+ hir::ExprKind::AddrOf(hir::BorrowKind::Ref, hir::Mutability::Not, match_expr),
+ )
+ };
+
+ if let Some(format_options) = format_options {
+ // Generate:
+ // <core::fmt::Arguments>::new_v1_formatted(
+ // lit_pieces,
+ // args,
+ // format_options,
+ // unsafe { ::core::fmt::UnsafeArg::new() }
+ // )
+ let new_v1_formatted = ctx.arena.alloc(ctx.expr_lang_item_type_relative(
+ macsp,
+ hir::LangItem::FormatArguments,
+ sym::new_v1_formatted,
+ ));
+ let unsafe_arg_new = ctx.arena.alloc(ctx.expr_lang_item_type_relative(
+ macsp,
+ hir::LangItem::FormatUnsafeArg,
+ sym::new,
+ ));
+ let unsafe_arg_new_call = ctx.expr_call(macsp, unsafe_arg_new, &[]);
+ let hir_id = ctx.next_id();
+ let unsafe_arg = ctx.expr_block(ctx.arena.alloc(hir::Block {
+ stmts: &[],
+ expr: Some(unsafe_arg_new_call),
+ hir_id,
+ rules: hir::BlockCheckMode::UnsafeBlock(hir::UnsafeSource::CompilerGenerated),
+ span: macsp,
+ targeted_by_break: false,
+ }));
+ let args = ctx.arena.alloc_from_iter([lit_pieces, args, format_options, unsafe_arg]);
+ hir::ExprKind::Call(new_v1_formatted, args)
+ } else {
+ // Generate:
+ // <core::fmt::Arguments>::new_v1(
+ // lit_pieces,
+ // args,
+ // )
+ let new_v1 = ctx.arena.alloc(ctx.expr_lang_item_type_relative(
+ macsp,
+ hir::LangItem::FormatArguments,
+ sym::new_v1,
+ ));
+ let new_args = ctx.arena.alloc_from_iter([lit_pieces, args]);
+ hir::ExprKind::Call(new_v1, new_args)
+ }
+}
+
+fn may_contain_yield_point(e: &ast::Expr) -> bool {
+ struct MayContainYieldPoint(bool);
+
+ impl Visitor<'_> for MayContainYieldPoint {
+ fn visit_expr(&mut self, e: &ast::Expr) {
+ if let ast::ExprKind::Await(_) | ast::ExprKind::Yield(_) = e.kind {
+ self.0 = true;
+ } else {
+ visit::walk_expr(self, e);
+ }
+ }
+
+ fn visit_mac_call(&mut self, _: &ast::MacCall) {
+ // Macros should be expanded at this point.
+ unreachable!("unexpanded macro in ast lowering");
+ }
+
+ fn visit_item(&mut self, _: &ast::Item) {
+ // Do not recurse into nested items.
+ }
+ }
+
+ let mut visitor = MayContainYieldPoint(false);
+ visitor.visit_expr(e);
+ visitor.0
+}
diff --git a/compiler/rustc_ast_lowering/src/index.rs b/compiler/rustc_ast_lowering/src/index.rs
index 63033085b..f7fe0d771 100644
--- a/compiler/rustc_ast_lowering/src/index.rs
+++ b/compiler/rustc_ast_lowering/src/index.rs
@@ -275,19 +275,6 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> {
});
}
- fn visit_fn(
- &mut self,
- fk: intravisit::FnKind<'hir>,
- fd: &'hir FnDecl<'hir>,
- b: BodyId,
- _: Span,
- id: HirId,
- ) {
- assert_eq!(self.owner, id.owner);
- assert_eq!(self.parent_node, id.local_id);
- intravisit::walk_fn(self, fk, fd, b, id);
- }
-
fn visit_block(&mut self, block: &'hir Block<'hir>) {
self.insert(block.span, block.hir_id, Node::Block(block));
self.with_parent(block.hir_id, |this| {
diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs
index 5d2589cb2..41295f2b7 100644
--- a/compiler/rustc_ast_lowering/src/item.rs
+++ b/compiler/rustc_ast_lowering/src/item.rs
@@ -7,13 +7,14 @@ use rustc_ast::ptr::P;
use rustc_ast::visit::AssocCtxt;
use rustc_ast::*;
use rustc_data_structures::sorted_map::SortedMap;
+use rustc_errors::ErrorGuaranteed;
use rustc_hir as hir;
use rustc_hir::def::{DefKind, Res};
use rustc_hir::def_id::{LocalDefId, CRATE_DEF_ID};
use rustc_hir::PredicateOrigin;
use rustc_index::vec::{Idx, IndexVec};
use rustc_middle::ty::{DefIdTree, ResolverAstLowering, TyCtxt};
-use rustc_span::lev_distance::find_best_match_for_name;
+use rustc_span::edit_distance::find_best_match_for_name;
use rustc_span::source_map::DesugaringKind;
use rustc_span::symbol::{kw, sym, Ident};
use rustc_span::{Span, Symbol};
@@ -67,7 +68,6 @@ impl<'a, 'hir> ItemLowerer<'a, 'hir> {
current_hir_id_owner: hir::CRATE_OWNER_ID,
item_local_id_counter: hir::ItemLocalId::new(0),
node_id_to_local_id: Default::default(),
- local_id_to_def_id: SortedMap::new(),
trait_map: Default::default(),
// Lowering state.
@@ -285,7 +285,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
.alloc_from_iter(fm.items.iter().map(|x| self.lower_foreign_item_ref(x))),
},
ItemKind::GlobalAsm(asm) => hir::ItemKind::GlobalAsm(self.lower_inline_asm(span, asm)),
- ItemKind::TyAlias(box TyAlias { generics, where_clauses, ty: Some(ty), .. }) => {
+ ItemKind::TyAlias(box TyAlias { generics, where_clauses, ty, .. }) => {
// We lower
//
// type Foo = impl Trait
@@ -300,18 +300,16 @@ impl<'hir> LoweringContext<'_, 'hir> {
&generics,
id,
&ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
- |this| this.lower_ty(ty, &ImplTraitContext::TypeAliasesOpaqueTy),
- );
- hir::ItemKind::TyAlias(ty, generics)
- }
- ItemKind::TyAlias(box TyAlias { generics, where_clauses, ty: None, .. }) => {
- let mut generics = generics.clone();
- add_ty_alias_where_clause(&mut generics, *where_clauses, true);
- let (generics, ty) = self.lower_generics(
- &generics,
- id,
- &ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
- |this| this.arena.alloc(this.ty(span, hir::TyKind::Err)),
+ |this| match ty {
+ None => {
+ let guar = this.tcx.sess.delay_span_bug(
+ span,
+ "expected to lower type alias type, but it was missing",
+ );
+ this.arena.alloc(this.ty(span, hir::TyKind::Err(guar)))
+ }
+ Some(ty) => this.lower_ty(ty, &ImplTraitContext::TypeAliasesOpaqueTy),
+ },
);
hir::ItemKind::TyAlias(ty, generics)
}
@@ -379,8 +377,10 @@ impl<'hir> LoweringContext<'_, 'hir> {
)
});
- let lowered_ty = this
- .lower_ty(ty, &ImplTraitContext::Disallowed(ImplTraitPosition::Type));
+ let lowered_ty = this.lower_ty(
+ ty,
+ &ImplTraitContext::Disallowed(ImplTraitPosition::ImplSelf),
+ );
(trait_ref, lowered_ty)
});
@@ -459,7 +459,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
span: Span,
body: Option<&Expr>,
) -> (&'hir hir::Ty<'hir>, hir::BodyId) {
- let ty = self.lower_ty(ty, &ImplTraitContext::Disallowed(ImplTraitPosition::Type));
+ let ty = self.lower_ty(ty, &ImplTraitContext::Disallowed(ImplTraitPosition::ConstTy));
(ty, self.lower_const_body(span, body))
}
@@ -609,8 +609,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
hir::ForeignItemKind::Fn(fn_dec, fn_args, generics)
}
ForeignItemKind::Static(t, m, _) => {
- let ty =
- self.lower_ty(t, &ImplTraitContext::Disallowed(ImplTraitPosition::Type));
+ let ty = self
+ .lower_ty(t, &ImplTraitContext::Disallowed(ImplTraitPosition::StaticTy));
hir::ForeignItemKind::Static(ty, *m)
}
ForeignItemKind::TyAlias(..) => hir::ForeignItemKind::Type,
@@ -680,11 +680,11 @@ impl<'hir> LoweringContext<'_, 'hir> {
qself,
path,
ParamMode::ExplicitNamed, // no `'_` in declarations (Issue #61124)
- &ImplTraitContext::Disallowed(ImplTraitPosition::Path),
+ &ImplTraitContext::Disallowed(ImplTraitPosition::FieldTy),
);
self.arena.alloc(t)
} else {
- self.lower_ty(&f.ty, &ImplTraitContext::Disallowed(ImplTraitPosition::Type))
+ self.lower_ty(&f.ty, &ImplTraitContext::Disallowed(ImplTraitPosition::FieldTy))
};
let hir_id = self.lower_node_id(f.id);
self.lower_attrs(hir_id, &f.attrs);
@@ -709,7 +709,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
let (generics, kind, has_default) = match &i.kind {
AssocItemKind::Const(_, ty, default) => {
- let ty = self.lower_ty(ty, &ImplTraitContext::Disallowed(ImplTraitPosition::Type));
+ let ty =
+ self.lower_ty(ty, &ImplTraitContext::Disallowed(ImplTraitPosition::ConstTy));
let body = default.as_ref().map(|x| self.lower_const_body(i.span, Some(x)));
(hir::Generics::empty(), hir::TraitItemKind::Const(ty, body), body.is_some())
}
@@ -747,7 +748,10 @@ impl<'hir> LoweringContext<'_, 'hir> {
&ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
|this| {
let ty = ty.as_ref().map(|x| {
- this.lower_ty(x, &ImplTraitContext::Disallowed(ImplTraitPosition::Type))
+ this.lower_ty(
+ x,
+ &ImplTraitContext::Disallowed(ImplTraitPosition::AssocTy),
+ )
});
hir::TraitItemKind::Type(
this.lower_param_bounds(
@@ -793,8 +797,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
}
/// Construct `ExprKind::Err` for the given `span`.
- pub(crate) fn expr_err(&mut self, span: Span) -> hir::Expr<'hir> {
- self.expr(span, hir::ExprKind::Err)
+ pub(crate) fn expr_err(&mut self, span: Span, guar: ErrorGuaranteed) -> hir::Expr<'hir> {
+ self.expr(span, hir::ExprKind::Err(guar))
}
fn lower_impl_item(&mut self, i: &AssocItem) -> &'hir hir::ImplItem<'hir> {
@@ -806,7 +810,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
let (generics, kind) = match &i.kind {
AssocItemKind::Const(_, ty, expr) => {
- let ty = self.lower_ty(ty, &ImplTraitContext::Disallowed(ImplTraitPosition::Type));
+ let ty =
+ self.lower_ty(ty, &ImplTraitContext::Disallowed(ImplTraitPosition::ConstTy));
(
hir::Generics::empty(),
hir::ImplItemKind::Const(ty, self.lower_const_body(i.span, expr.as_deref())),
@@ -841,7 +846,11 @@ impl<'hir> LoweringContext<'_, 'hir> {
&ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
|this| match ty {
None => {
- let ty = this.arena.alloc(this.ty(i.span, hir::TyKind::Err));
+ let guar = this.tcx.sess.delay_span_bug(
+ i.span,
+ "expected to lower associated type, but it was missing",
+ );
+ let ty = this.arena.alloc(this.ty(i.span, hir::TyKind::Err(guar)));
hir::ImplItemKind::Type(ty)
}
Some(ty) => {
@@ -967,7 +976,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
fn lower_block_expr_opt(&mut self, span: Span, block: Option<&Block>) -> hir::Expr<'hir> {
match block {
Some(block) => self.lower_block_expr(block),
- None => self.expr_err(span),
+ None => self.expr_err(span, self.tcx.sess.delay_span_bug(span, "no block")),
}
}
@@ -977,7 +986,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
&[],
match expr {
Some(expr) => this.lower_expr_mut(expr),
- None => this.expr_err(span),
+ None => this.expr_err(span, this.tcx.sess.delay_span_bug(span, "no block")),
},
)
})
@@ -1330,13 +1339,19 @@ impl<'hir> LoweringContext<'_, 'hir> {
.map(|predicate| self.lower_where_predicate(predicate)),
);
- let mut params: SmallVec<[hir::GenericParam<'hir>; 4]> =
- self.lower_generic_params_mut(&generics.params).collect();
+ let mut params: SmallVec<[hir::GenericParam<'hir>; 4]> = self
+ .lower_generic_params_mut(&generics.params, hir::GenericParamSource::Generics)
+ .collect();
// Introduce extra lifetimes if late resolution tells us to.
let extra_lifetimes = self.resolver.take_extra_lifetime_params(parent_node_id);
params.extend(extra_lifetimes.into_iter().filter_map(|(ident, node_id, res)| {
- self.lifetime_res_to_generic_param(ident, node_id, res)
+ self.lifetime_res_to_generic_param(
+ ident,
+ node_id,
+ res,
+ hir::GenericParamSource::Generics,
+ )
}));
let has_where_clause_predicates = !generics.where_clause.predicates.is_empty();
@@ -1440,9 +1455,10 @@ impl<'hir> LoweringContext<'_, 'hir> {
span,
}) => hir::WherePredicate::BoundPredicate(hir::WhereBoundPredicate {
hir_id: self.next_id(),
- bound_generic_params: self.lower_generic_params(bound_generic_params),
+ bound_generic_params: self
+ .lower_generic_params(bound_generic_params, hir::GenericParamSource::Binder),
bounded_ty: self
- .lower_ty(bounded_ty, &ImplTraitContext::Disallowed(ImplTraitPosition::Type)),
+ .lower_ty(bounded_ty, &ImplTraitContext::Disallowed(ImplTraitPosition::Bound)),
bounds: self.arena.alloc_from_iter(bounds.iter().map(|bound| {
self.lower_param_bound(
bound,
@@ -1466,9 +1482,9 @@ impl<'hir> LoweringContext<'_, 'hir> {
WherePredicate::EqPredicate(WhereEqPredicate { lhs_ty, rhs_ty, span }) => {
hir::WherePredicate::EqPredicate(hir::WhereEqPredicate {
lhs_ty: self
- .lower_ty(lhs_ty, &ImplTraitContext::Disallowed(ImplTraitPosition::Type)),
+ .lower_ty(lhs_ty, &ImplTraitContext::Disallowed(ImplTraitPosition::Bound)),
rhs_ty: self
- .lower_ty(rhs_ty, &ImplTraitContext::Disallowed(ImplTraitPosition::Type)),
+ .lower_ty(rhs_ty, &ImplTraitContext::Disallowed(ImplTraitPosition::Bound)),
span: self.lower_span(*span),
})
}
diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs
index bc6d2cf12..b20157f2c 100644
--- a/compiler/rustc_ast_lowering/src/lib.rs
+++ b/compiler/rustc_ast_lowering/src/lib.rs
@@ -52,23 +52,28 @@ use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::sorted_map::SortedMap;
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
use rustc_data_structures::sync::Lrc;
-use rustc_errors::{DiagnosticArgFromDisplay, Handler, StashKey};
+use rustc_errors::{
+ DiagnosticArgFromDisplay, DiagnosticMessage, Handler, StashKey, SubdiagnosticMessage,
+};
use rustc_hir as hir;
use rustc_hir::def::{DefKind, LifetimeRes, Namespace, PartialRes, PerNS, Res};
use rustc_hir::def_id::{LocalDefId, CRATE_DEF_ID};
use rustc_hir::definitions::DefPathData;
use rustc_hir::{ConstArg, GenericArg, ItemLocalId, ParamName, TraitCandidate};
use rustc_index::vec::{Idx, IndexVec};
-use rustc_middle::span_bug;
-use rustc_middle::ty::{ResolverAstLowering, TyCtxt};
+use rustc_macros::fluent_messages;
+use rustc_middle::{
+ span_bug,
+ ty::{ResolverAstLowering, TyCtxt},
+};
use rustc_session::parse::feature_err;
use rustc_span::hygiene::MacroKind;
use rustc_span::source_map::DesugaringKind;
use rustc_span::symbol::{kw, sym, Ident, Symbol};
use rustc_span::{Span, DUMMY_SP};
-
use smallvec::SmallVec;
use std::collections::hash_map::Entry;
+use thin_vec::ThinVec;
macro_rules! arena_vec {
($this:expr; $($x:expr),*) => (
@@ -80,12 +85,15 @@ mod asm;
mod block;
mod errors;
mod expr;
+mod format;
mod index;
mod item;
mod lifetime_collector;
mod pat;
mod path;
+fluent_messages! { "../locales/en-US.ftl" }
+
struct LoweringContext<'a, 'hir> {
tcx: TyCtxt<'hir>,
resolver: &'a mut ResolverAstLowering,
@@ -118,7 +126,6 @@ struct LoweringContext<'a, 'hir> {
current_hir_id_owner: hir::OwnerId,
item_local_id_counter: hir::ItemLocalId,
- local_id_to_def_id: SortedMap<ItemLocalId, LocalDefId>,
trait_map: FxHashMap<ItemLocalId, Box<[TraitCandidate]>>,
impl_trait_defs: Vec<hir::GenericParam<'hir>>,
@@ -253,7 +260,6 @@ enum ImplTraitContext {
enum ImplTraitPosition {
Path,
Variable,
- Type,
Trait,
AsyncBlock,
Bound,
@@ -270,30 +276,43 @@ enum ImplTraitPosition {
FnTraitReturn,
TraitReturn,
ImplReturn,
+ GenericDefault,
+ ConstTy,
+ StaticTy,
+ AssocTy,
+ FieldTy,
+ Cast,
+ ImplSelf,
}
impl std::fmt::Display for ImplTraitPosition {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let name = match self {
- ImplTraitPosition::Path => "path",
- ImplTraitPosition::Variable => "variable binding",
- ImplTraitPosition::Type => "type",
- ImplTraitPosition::Trait => "trait",
- ImplTraitPosition::AsyncBlock => "async block",
- ImplTraitPosition::Bound => "bound",
- ImplTraitPosition::Generic => "generic",
- ImplTraitPosition::ExternFnParam => "`extern fn` param",
- ImplTraitPosition::ClosureParam => "closure param",
- ImplTraitPosition::PointerParam => "`fn` pointer param",
- ImplTraitPosition::FnTraitParam => "`Fn` trait param",
- ImplTraitPosition::TraitParam => "trait method param",
- ImplTraitPosition::ImplParam => "`impl` method param",
- ImplTraitPosition::ExternFnReturn => "`extern fn` return",
- ImplTraitPosition::ClosureReturn => "closure return",
- ImplTraitPosition::PointerReturn => "`fn` pointer return",
- ImplTraitPosition::FnTraitReturn => "`Fn` trait return",
- ImplTraitPosition::TraitReturn => "trait method return",
- ImplTraitPosition::ImplReturn => "`impl` method return",
+ ImplTraitPosition::Path => "paths",
+ ImplTraitPosition::Variable => "variable bindings",
+ ImplTraitPosition::Trait => "traits",
+ ImplTraitPosition::AsyncBlock => "async blocks",
+ ImplTraitPosition::Bound => "bounds",
+ ImplTraitPosition::Generic => "generics",
+ ImplTraitPosition::ExternFnParam => "`extern fn` params",
+ ImplTraitPosition::ClosureParam => "closure params",
+ ImplTraitPosition::PointerParam => "`fn` pointer params",
+ ImplTraitPosition::FnTraitParam => "`Fn` trait params",
+ ImplTraitPosition::TraitParam => "trait method params",
+ ImplTraitPosition::ImplParam => "`impl` method params",
+ ImplTraitPosition::ExternFnReturn => "`extern fn` return types",
+ ImplTraitPosition::ClosureReturn => "closure return types",
+ ImplTraitPosition::PointerReturn => "`fn` pointer return types",
+ ImplTraitPosition::FnTraitReturn => "`Fn` trait return types",
+ ImplTraitPosition::TraitReturn => "trait method return types",
+ ImplTraitPosition::ImplReturn => "`impl` method return types",
+ ImplTraitPosition::GenericDefault => "generic parameter defaults",
+ ImplTraitPosition::ConstTy => "const types",
+ ImplTraitPosition::StaticTy => "static types",
+ ImplTraitPosition::AssocTy => "associated types",
+ ImplTraitPosition::FieldTy => "field types",
+ ImplTraitPosition::Cast => "cast types",
+ ImplTraitPosition::ImplSelf => "impl headers",
};
write!(f, "{name}")
@@ -416,6 +435,7 @@ fn compute_hir_hash(
pub fn lower_to_hir(tcx: TyCtxt<'_>, (): ()) -> hir::Crate<'_> {
let sess = tcx.sess;
+ tcx.ensure().output_filenames(());
let (mut resolver, krate) = tcx.resolver_for_lowering(()).steal();
let ast_index = index_crate(&resolver.node_id_to_def_id, &krate);
@@ -565,7 +585,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
let current_attrs = std::mem::take(&mut self.attrs);
let current_bodies = std::mem::take(&mut self.bodies);
let current_node_ids = std::mem::take(&mut self.node_id_to_local_id);
- let current_id_to_def_id = std::mem::take(&mut self.local_id_to_def_id);
let current_trait_map = std::mem::take(&mut self.trait_map);
let current_owner =
std::mem::replace(&mut self.current_hir_id_owner, hir::OwnerId { def_id });
@@ -592,7 +611,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
self.attrs = current_attrs;
self.bodies = current_bodies;
self.node_id_to_local_id = current_node_ids;
- self.local_id_to_def_id = current_id_to_def_id;
self.trait_map = current_trait_map;
self.current_hir_id_owner = current_owner;
self.item_local_id_counter = current_local_counter;
@@ -627,7 +645,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
fn make_owner_info(&mut self, node: hir::OwnerNode<'hir>) -> &'hir hir::OwnerInfo<'hir> {
let attrs = std::mem::take(&mut self.attrs);
let mut bodies = std::mem::take(&mut self.bodies);
- let local_id_to_def_id = std::mem::take(&mut self.local_id_to_def_id);
let trait_map = std::mem::take(&mut self.trait_map);
#[cfg(debug_assertions)]
@@ -643,13 +660,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
let (hash_including_bodies, hash_without_bodies) = self.hash_owner(node, &bodies);
let (nodes, parenting) =
index::index_hir(self.tcx.sess, &*self.tcx.definitions_untracked(), node, &bodies);
- let nodes = hir::OwnerNodes {
- hash_including_bodies,
- hash_without_bodies,
- nodes,
- bodies,
- local_id_to_def_id,
- };
+ let nodes = hir::OwnerNodes { hash_including_bodies, hash_without_bodies, nodes, bodies };
let attrs = {
let hash = self.tcx.with_stable_hashing_context(|mut hcx| {
let mut stable_hasher = StableHasher::new();
@@ -708,7 +719,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
assert_ne!(local_id, hir::ItemLocalId::new(0));
if let Some(def_id) = self.opt_local_def_id(ast_node_id) {
self.children.push((def_id, hir::MaybeOwner::NonOwner(hir_id)));
- self.local_id_to_def_id.insert(local_id, def_id);
}
if let Some(traits) = self.resolver.trait_map.remove(&ast_node_id) {
@@ -794,6 +804,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
ident: Ident,
node_id: NodeId,
res: LifetimeRes,
+ source: hir::GenericParamSource,
) -> Option<hir::GenericParam<'hir>> {
let (name, kind) = match res {
LifetimeRes::Param { .. } => {
@@ -827,6 +838,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
pure_wrt_drop: false,
kind: hir::GenericParamKind::Lifetime { kind },
colon_span: None,
+ source,
})
}
@@ -842,11 +854,13 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
binder: NodeId,
generic_params: &[GenericParam],
) -> &'hir [hir::GenericParam<'hir>] {
- let mut generic_params: Vec<_> = self.lower_generic_params_mut(generic_params).collect();
+ let mut generic_params: Vec<_> = self
+ .lower_generic_params_mut(generic_params, hir::GenericParamSource::Binder)
+ .collect();
let extra_lifetimes = self.resolver.take_extra_lifetime_params(binder);
debug!(?extra_lifetimes);
generic_params.extend(extra_lifetimes.into_iter().filter_map(|(ident, node_id, res)| {
- self.lifetime_res_to_generic_param(ident, node_id, res)
+ self.lifetime_res_to_generic_param(ident, node_id, res, hir::GenericParamSource::Binder)
}));
let generic_params = self.arena.alloc_from_iter(generic_params);
debug!(?generic_params);
@@ -992,8 +1006,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
} else {
self.arena.alloc(hir::GenericArgs::none())
};
- let itctx_tait = &ImplTraitContext::TypeAliasesOpaqueTy;
-
let kind = match &constraint.kind {
AssocConstraintKind::Equality { term } => {
let term = match term {
@@ -1003,8 +1015,14 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
hir::TypeBindingKind::Equality { term }
}
AssocConstraintKind::Bound { bounds } => {
+ enum DesugarKind<'a> {
+ ImplTrait,
+ Error(&'a ImplTraitPosition),
+ Bound,
+ }
+
// Piggy-back on the `impl Trait` context to figure out the correct behavior.
- let (desugar_to_impl_trait, itctx) = match itctx {
+ let desugar_kind = match itctx {
// We are in the return position:
//
// fn foo() -> impl Iterator<Item: Debug>
@@ -1013,7 +1031,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
//
// fn foo() -> impl Iterator<Item = impl Debug>
ImplTraitContext::ReturnPositionOpaqueTy { .. }
- | ImplTraitContext::TypeAliasesOpaqueTy { .. } => (true, itctx),
+ | ImplTraitContext::TypeAliasesOpaqueTy { .. } => DesugarKind::ImplTrait,
// We are in the argument position, but within a dyn type:
//
@@ -1022,15 +1040,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
// so desugar to
//
// fn foo(x: dyn Iterator<Item = impl Debug>)
- ImplTraitContext::Universal if self.is_in_dyn_type => (true, itctx),
+ ImplTraitContext::Universal if self.is_in_dyn_type => DesugarKind::ImplTrait,
- // In `type Foo = dyn Iterator<Item: Debug>` we desugar to
- // `type Foo = dyn Iterator<Item = impl Debug>` but we have to override the
- // "impl trait context" to permit `impl Debug` in this position (it desugars
- // then to an opaque type).
- //
- // FIXME: this is only needed until `impl Trait` is allowed in type aliases.
- ImplTraitContext::Disallowed(_) if self.is_in_dyn_type => (true, itctx_tait),
+ ImplTraitContext::Disallowed(position) if self.is_in_dyn_type => {
+ DesugarKind::Error(position)
+ }
// We are in the parameter position, but not within a dyn type:
//
@@ -1039,35 +1053,47 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
// so we leave it as is and this gets expanded in astconv to a bound like
// `<T as Iterator>::Item: Debug` where `T` is the type parameter for the
// `impl Iterator`.
- _ => (false, itctx),
+ _ => DesugarKind::Bound,
};
- if desugar_to_impl_trait {
- // Desugar `AssocTy: Bounds` into `AssocTy = impl Bounds`. We do this by
- // constructing the HIR for `impl bounds...` and then lowering that.
-
- let impl_trait_node_id = self.next_node_id();
-
- self.with_dyn_type_scope(false, |this| {
- let node_id = this.next_node_id();
- let ty = this.lower_ty(
- &Ty {
- id: node_id,
- kind: TyKind::ImplTrait(impl_trait_node_id, bounds.clone()),
- span: this.lower_span(constraint.span),
- tokens: None,
- },
- itctx,
- );
+ match desugar_kind {
+ DesugarKind::ImplTrait => {
+ // Desugar `AssocTy: Bounds` into `AssocTy = impl Bounds`. We do this by
+ // constructing the HIR for `impl bounds...` and then lowering that.
- hir::TypeBindingKind::Equality { term: ty.into() }
- })
- } else {
- // Desugar `AssocTy: Bounds` into a type binding where the
- // later desugars into a trait predicate.
- let bounds = self.lower_param_bounds(bounds, itctx);
+ let impl_trait_node_id = self.next_node_id();
+
+ self.with_dyn_type_scope(false, |this| {
+ let node_id = this.next_node_id();
+ let ty = this.lower_ty(
+ &Ty {
+ id: node_id,
+ kind: TyKind::ImplTrait(impl_trait_node_id, bounds.clone()),
+ span: this.lower_span(constraint.span),
+ tokens: None,
+ },
+ itctx,
+ );
+
+ hir::TypeBindingKind::Equality { term: ty.into() }
+ })
+ }
+ DesugarKind::Bound => {
+ // Desugar `AssocTy: Bounds` into a type binding where the
+ // later desugars into a trait predicate.
+ let bounds = self.lower_param_bounds(bounds, itctx);
- hir::TypeBindingKind::Constraint { bounds }
+ hir::TypeBindingKind::Constraint { bounds }
+ }
+ DesugarKind::Error(position) => {
+ let guar = self.tcx.sess.emit_err(errors::MisplacedAssocTyBinding {
+ span: constraint.span,
+ position: DiagnosticArgFromDisplay(position),
+ });
+ let err_ty =
+ &*self.arena.alloc(self.ty(constraint.span, hir::TyKind::Err(guar)));
+ hir::TypeBindingKind::Equality { term: err_ty.into() }
+ }
}
}
};
@@ -1204,7 +1230,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
let (bounds, lifetime_bound) = self.with_dyn_type_scope(true, |this| {
let bound = this.lower_poly_trait_ref(
&PolyTraitRef {
- bound_generic_params: vec![],
+ bound_generic_params: ThinVec::new(),
trait_ref: TraitRef { path: path.clone(), ref_id: t.id },
span: t.span
},
@@ -1234,7 +1260,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
fn lower_ty_direct(&mut self, t: &Ty, itctx: &ImplTraitContext) -> hir::Ty<'hir> {
let kind = match &t.kind {
TyKind::Infer => hir::TyKind::Infer,
- TyKind::Err => hir::TyKind::Err,
+ TyKind::Err => {
+ hir::TyKind::Err(self.tcx.sess.delay_span_bug(t.span, "TyKind::Err lowered"))
+ }
TyKind::Slice(ty) => hir::TyKind::Slice(self.lower_ty(ty, itctx)),
TyKind::Ptr(mt) => hir::TyKind::Ptr(self.lower_mt(mt, itctx)),
TyKind::Ref(region, mt) => {
@@ -1351,8 +1379,12 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
span,
);
let ident = Ident::from_str_and_span(&pprust::ty_to_string(t), span);
- let (param, bounds, path) =
- self.lower_generic_and_bounds(*def_node_id, span, ident, bounds);
+ let (param, bounds, path) = self.lower_universal_param_and_bounds(
+ *def_node_id,
+ span,
+ ident,
+ bounds,
+ );
self.impl_trait_defs.push(param);
if let Some(bounds) = bounds {
self.impl_trait_bounds.push(bounds);
@@ -1360,7 +1392,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
path
}
ImplTraitContext::FeatureGated(position, feature) => {
- self.tcx
+ let guar = self
+ .tcx
.sess
.create_feature_err(
MisplacedImplTrait {
@@ -1370,24 +1403,24 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
*feature,
)
.emit();
- hir::TyKind::Err
+ hir::TyKind::Err(guar)
}
ImplTraitContext::Disallowed(position) => {
- self.tcx.sess.emit_err(MisplacedImplTrait {
+ let guar = self.tcx.sess.emit_err(MisplacedImplTrait {
span: t.span,
position: DiagnosticArgFromDisplay(position),
});
- hir::TyKind::Err
+ hir::TyKind::Err(guar)
}
}
}
TyKind::MacCall(_) => panic!("`TyKind::MacCall` should have been expanded by now"),
TyKind::CVarArgs => {
- self.tcx.sess.delay_span_bug(
+ let guar = self.tcx.sess.delay_span_bug(
t.span,
"`TyKind::CVarArgs` should have been handled elsewhere",
);
- hir::TyKind::Err
+ hir::TyKind::Err(guar)
}
};
@@ -1505,6 +1538,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
pure_wrt_drop: false,
kind: hir::GenericParamKind::Lifetime { kind },
colon_span: None,
+ source: hir::GenericParamSource::Generics,
}
},
));
@@ -1573,7 +1607,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
hir::OwnerNode::Item(self.arena.alloc(opaque_ty_item))
}
- /// Given a `parent_def_id`, a list of `lifetimes_in_bounds and a `remapping` hash to be
+ /// Given a `parent_def_id`, a list of `lifetimes_in_bounds` and a `remapping` hash to be
/// filled, this function creates new definitions for `Param` and `Fresh` lifetimes, inserts the
/// new definition, adds it to the remapping with the definition of the given lifetime and
/// returns a list of lifetimes to be lowered afterwards.
@@ -1962,6 +1996,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
pure_wrt_drop: false,
kind: hir::GenericParamKind::Lifetime { kind },
colon_span: None,
+ source: hir::GenericParamSource::Generics,
}
},
));
@@ -2127,16 +2162,25 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
fn lower_generic_params_mut<'s>(
&'s mut self,
params: &'s [GenericParam],
+ source: hir::GenericParamSource,
) -> impl Iterator<Item = hir::GenericParam<'hir>> + Captures<'a> + Captures<'s> {
- params.iter().map(move |param| self.lower_generic_param(param))
+ params.iter().map(move |param| self.lower_generic_param(param, source))
}
- fn lower_generic_params(&mut self, params: &[GenericParam]) -> &'hir [hir::GenericParam<'hir>] {
- self.arena.alloc_from_iter(self.lower_generic_params_mut(params))
+ fn lower_generic_params(
+ &mut self,
+ params: &[GenericParam],
+ source: hir::GenericParamSource,
+ ) -> &'hir [hir::GenericParam<'hir>] {
+ self.arena.alloc_from_iter(self.lower_generic_params_mut(params, source))
}
#[instrument(level = "trace", skip(self))]
- fn lower_generic_param(&mut self, param: &GenericParam) -> hir::GenericParam<'hir> {
+ fn lower_generic_param(
+ &mut self,
+ param: &GenericParam,
+ source: hir::GenericParamSource,
+ ) -> hir::GenericParam<'hir> {
let (name, kind) = self.lower_generic_param_kind(param);
let hir_id = self.lower_node_id(param.id);
@@ -2149,6 +2193,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
pure_wrt_drop: self.tcx.sess.contains_name(&param.attrs, sym::may_dangle),
kind,
colon_span: param.colon_span.map(|s| self.lower_span(s)),
+ source,
}
}
@@ -2175,7 +2220,10 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
GenericParamKind::Type { default, .. } => {
let kind = hir::GenericParamKind::Type {
default: default.as_ref().map(|x| {
- self.lower_ty(x, &ImplTraitContext::Disallowed(ImplTraitPosition::Type))
+ self.lower_ty(
+ x,
+ &ImplTraitContext::Disallowed(ImplTraitPosition::GenericDefault),
+ )
}),
synthetic: false,
};
@@ -2183,7 +2231,10 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
(hir::ParamName::Plain(self.lower_ident(param.ident)), kind)
}
GenericParamKind::Const { ty, kw_span: _, default } => {
- let ty = self.lower_ty(&ty, &ImplTraitContext::Disallowed(ImplTraitPosition::Type));
+ let ty = self.lower_ty(
+ &ty,
+ &ImplTraitContext::Disallowed(ImplTraitPosition::GenericDefault),
+ );
let default = default.as_ref().map(|def| self.lower_anon_const(def));
(
hir::ParamName::Plain(self.lower_ident(param.ident)),
@@ -2235,7 +2286,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
}
#[instrument(level = "debug", skip(self), ret)]
- fn lower_generic_and_bounds(
+ fn lower_universal_param_and_bounds(
&mut self,
node_id: NodeId,
span: Span,
@@ -2255,6 +2306,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
span,
kind: hir::GenericParamKind::Type { default: None, synthetic: true },
colon_span: None,
+ source: hir::GenericParamSource::Generics,
};
let preds = self.lower_generic_bound_predicate(
diff --git a/compiler/rustc_ast_lowering/src/pat.rs b/compiler/rustc_ast_lowering/src/pat.rs
index 06d885a45..2509b7056 100644
--- a/compiler/rustc_ast_lowering/src/pat.rs
+++ b/compiler/rustc_ast_lowering/src/pat.rs
@@ -330,8 +330,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
ExprKind::Path(..) if allow_paths => {}
ExprKind::Unary(UnOp::Neg, inner) if matches!(inner.kind, ExprKind::Lit(_)) => {}
_ => {
- self.tcx.sess.emit_err(ArbitraryExpressionInPattern { span: expr.span });
- return self.arena.alloc(self.expr_err(expr.span));
+ let guar = self.tcx.sess.emit_err(ArbitraryExpressionInPattern { span: expr.span });
+ return self.arena.alloc(self.expr_err(expr.span, guar));
}
}
self.lower_expr(expr)
diff --git a/compiler/rustc_ast_passes/Cargo.toml b/compiler/rustc_ast_passes/Cargo.toml
index 37eff9207..8bd212073 100644
--- a/compiler/rustc_ast_passes/Cargo.toml
+++ b/compiler/rustc_ast_passes/Cargo.toml
@@ -5,7 +5,7 @@ edition = "2021"
[dependencies]
itertools = "0.10.1"
-tracing = "0.1"
+rustc_ast = { path = "../rustc_ast" }
rustc_ast_pretty = { path = "../rustc_ast_pretty" }
rustc_attr = { path = "../rustc_attr" }
rustc_data_structures = { path = "../rustc_data_structures" }
@@ -16,4 +16,5 @@ rustc_parse = { path = "../rustc_parse" }
rustc_session = { path = "../rustc_session" }
rustc_span = { path = "../rustc_span" }
rustc_target = { path = "../rustc_target" }
-rustc_ast = { path = "../rustc_ast" }
+thin-vec = "0.2.12"
+tracing = "0.1"
diff --git a/compiler/rustc_ast_passes/locales/en-US.ftl b/compiler/rustc_ast_passes/locales/en-US.ftl
new file mode 100644
index 000000000..747bd52b2
--- /dev/null
+++ b/compiler/rustc_ast_passes/locales/en-US.ftl
@@ -0,0 +1,236 @@
+ast_passes_forbidden_let =
+ `let` expressions are not supported here
+ .note = only supported directly in conditions of `if` and `while` expressions
+ .not_supported_or = `||` operators are not supported in let chain expressions
+ .not_supported_parentheses = `let`s wrapped in parentheses are not supported in a context with let chains
+
+ast_passes_forbidden_let_stable =
+ expected expression, found statement (`let`)
+ .note = variable declaration using `let` is a statement
+
+ast_passes_deprecated_where_clause_location =
+ where clause not allowed here
+
+ast_passes_keyword_lifetime =
+ lifetimes cannot use keyword names
+
+ast_passes_invalid_label =
+ invalid label name `{$name}`
+
+ast_passes_invalid_visibility =
+ unnecessary visibility qualifier
+ .implied = `pub` not permitted here because it's implied
+ .individual_impl_items = place qualifiers on individual impl items instead
+ .individual_foreign_items = place qualifiers on individual foreign items instead
+
+ast_passes_trait_fn_const =
+ functions in traits cannot be declared const
+ .label = functions in traits cannot be const
+
+ast_passes_forbidden_lifetime_bound =
+ lifetime bounds cannot be used in this context
+
+ast_passes_forbidden_non_lifetime_param =
+ only lifetime parameters can be used in this context
+
+ast_passes_fn_param_too_many =
+ function can not have more than {$max_num_args} arguments
+
+ast_passes_fn_param_c_var_args_only =
+ C-variadic function must be declared with at least one named argument
+
+ast_passes_fn_param_c_var_args_not_last =
+ `...` must be the last argument of a C-variadic function
+
+ast_passes_fn_param_doc_comment =
+ documentation comments cannot be applied to function parameters
+ .label = doc comments are not allowed here
+
+ast_passes_fn_param_forbidden_attr =
+ allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters
+
+ast_passes_fn_param_forbidden_self =
+ `self` parameter is only allowed in associated functions
+ .label = not semantically valid as function parameter
+ .note = associated functions are those in `impl` or `trait` definitions
+
+ast_passes_forbidden_default =
+ `default` is only allowed on items in trait impls
+ .label = `default` because of this
+
+ast_passes_assoc_const_without_body =
+ associated constant in `impl` without body
+ .suggestion = provide a definition for the constant
+
+ast_passes_assoc_fn_without_body =
+ associated function in `impl` without body
+ .suggestion = provide a definition for the function
+
+ast_passes_assoc_type_without_body =
+ associated type in `impl` without body
+ .suggestion = provide a definition for the type
+
+ast_passes_const_without_body =
+ free constant item without body
+ .suggestion = provide a definition for the constant
+
+ast_passes_static_without_body =
+ free static item without body
+ .suggestion = provide a definition for the static
+
+ast_passes_ty_alias_without_body =
+ free type alias without body
+ .suggestion = provide a definition for the type
+
+ast_passes_fn_without_body =
+ free function without a body
+ .suggestion = provide a definition for the function
+
+ast_passes_extern_block_suggestion = if you meant to declare an externally defined function, use an `extern` block
+
+ast_passes_bound_in_context = bounds on `type`s in {$ctx} have no effect
+
+ast_passes_extern_types_cannot = `type`s inside `extern` blocks cannot have {$descr}
+ .suggestion = remove the {$remove_descr}
+ .label = `extern` block begins here
+
+ast_passes_extern_keyword_link = for more information, visit https://doc.rust-lang.org/std/keyword.extern.html
+
+ast_passes_body_in_extern = incorrect `{$kind}` inside `extern` block
+ .cannot_have = cannot have a body
+ .invalid = the invalid body
+ .existing = `extern` blocks define existing foreign {$kind}s and {$kind}s inside of them cannot have a body
+
+ast_passes_fn_body_extern = incorrect function inside `extern` block
+ .cannot_have = cannot have a body
+ .suggestion = remove the invalid body
+ .help = you might have meant to write a function accessible through FFI, which can be done by writing `extern fn` outside of the `extern` block
+ .label = `extern` blocks define existing foreign functions and functions inside of them cannot have a body
+
+ast_passes_extern_fn_qualifiers = functions in `extern` blocks cannot have qualifiers
+ .label = in this `extern` block
+ .suggestion = remove the qualifiers
+
+ast_passes_extern_item_ascii = items in `extern` blocks cannot use non-ascii identifiers
+ .label = in this `extern` block
+ .note = this limitation may be lifted in the future; see issue #83942 <https://github.com/rust-lang/rust/issues/83942> for more information
+
+ast_passes_bad_c_variadic = only foreign or `unsafe extern "C"` functions may be C-variadic
+
+ast_passes_item_underscore = `{$kind}` items in this context need a name
+ .label = `_` is not a valid name for this `{$kind}` item
+
+ast_passes_nomangle_ascii = `#[no_mangle]` requires ASCII identifier
+
+ast_passes_module_nonascii = trying to load file for module `{$name}` with non-ascii identifier name
+ .help = consider using the `#[path]` attribute to specify filesystem path
+
+ast_passes_auto_generic = auto traits cannot have generic parameters
+ .label = auto trait cannot have generic parameters
+ .suggestion = remove the parameters
+
+ast_passes_auto_super_lifetime = auto traits cannot have super traits or lifetime bounds
+ .label = {ast_passes_auto_super_lifetime}
+ .suggestion = remove the super traits or lifetime bounds
+
+ast_passes_auto_items = auto traits cannot have associated items
+ .label = {ast_passes_auto_items}
+ .suggestion = remove these associated items
+
+ast_passes_generic_before_constraints = generic arguments must come before the first constraint
+ .constraints = {$constraint_len ->
+ [one] constraint
+ *[other] constraints
+ }
+ .args = generic {$args_len ->
+ [one] argument
+ *[other] arguments
+ }
+ .empty_string = {""},
+ .suggestion = move the {$constraint_len ->
+ [one] constraint
+ *[other] constraints
+ } after the generic {$args_len ->
+ [one] argument
+ *[other] arguments
+ }
+
+ast_passes_pattern_in_fn_pointer = patterns aren't allowed in function pointer types
+
+ast_passes_trait_object_single_bound = only a single explicit lifetime bound is permitted
+
+ast_passes_impl_trait_path = `impl Trait` is not allowed in path parameters
+
+ast_passes_nested_impl_trait = nested `impl Trait` is not allowed
+ .outer = outer `impl Trait`
+ .inner = nested `impl Trait` here
+
+ast_passes_at_least_one_trait = at least one trait must be specified
+
+ast_passes_extern_without_abi = extern declarations without an explicit ABI are deprecated
+
+ast_passes_out_of_order_params = {$param_ord} parameters must be declared prior to {$max_param} parameters
+ .suggestion = reorder the parameters: lifetimes, then consts and types
+
+ast_passes_obsolete_auto = `impl Trait for .. {"{}"}` is an obsolete syntax
+ .help = use `auto trait Trait {"{}"}` instead
+
+ast_passes_unsafe_negative_impl = negative impls cannot be unsafe
+ .negative = negative because of this
+ .unsafe = unsafe because of this
+
+ast_passes_inherent_cannot_be = inherent impls cannot be {$annotation}
+ .because = {$annotation} because of this
+ .type = inherent impl for this type
+ .only_trait = only trait implementations may be annotated with {$annotation}
+
+ast_passes_unsafe_item = {$kind} cannot be declared unsafe
+
+ast_passes_fieldless_union = unions cannot have zero fields
+
+ast_passes_where_after_type_alias = where clauses are not allowed after the type for type aliases
+ .note = see issue #89122 <https://github.com/rust-lang/rust/issues/89122> for more information
+
+ast_passes_generic_default_trailing = generic parameters with a default must be trailing
+
+ast_passes_nested_lifetimes = nested quantification of lifetimes
+
+ast_passes_optional_trait_supertrait = `?Trait` is not permitted in supertraits
+ .note = traits are `?{$path_str}` by default
+
+ast_passes_optional_trait_object = `?Trait` is not permitted in trait object types
+
+ast_passes_tilde_const_disallowed = `~const` is not allowed here
+ .trait = trait objects cannot have `~const` trait bounds
+ .closure = closures cannot have `~const` trait bounds
+ .function = this function is not `const`, so it cannot have `~const` trait bounds
+
+ast_passes_optional_const_exclusive = `~const` and `?` are mutually exclusive
+
+ast_passes_const_and_async = functions cannot be both `const` and `async`
+ .const = `const` because of this
+ .async = `async` because of this
+ .label = {""}
+
+ast_passes_pattern_in_foreign = patterns aren't allowed in foreign function declarations
+ .label = pattern not allowed in foreign function
+
+ast_passes_pattern_in_bodiless = patterns aren't allowed in functions without bodies
+ .label = pattern not allowed in function without body
+
+ast_passes_equality_in_where = equality constraints are not yet supported in `where` clauses
+ .label = not supported
+ .suggestion = if `{$ident}` is an associated type you're trying to set, use the associated type binding syntax
+ .suggestion_path = if `{$trait_segment}::{$potential_assoc}` is an associated type you're trying to set, use the associated type binding syntax
+ .note = see issue #20041 <https://github.com/rust-lang/rust/issues/20041> for more information
+
+ast_passes_stability_outside_std = stability attributes may not be used outside of the standard library
+
+ast_passes_feature_on_non_nightly = `#![feature]` may not be used on the {$channel} release channel
+ .suggestion = remove the attribute
+ .stable_since = the feature `{$name}` has been stable since `{$since}` and no longer requires an attribute to enable
+
+ast_passes_incompatbile_features = `{$f1}` and `{$f2}` are incompatible, using them at the same time is not allowed
+ .help = remove one of these features
+
+ast_passes_show_span = {$msg}
diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs
index 902b4b1a1..2cc009410 100644
--- a/compiler/rustc_ast_passes/src/ast_validation.rs
+++ b/compiler/rustc_ast_passes/src/ast_validation.rs
@@ -13,7 +13,6 @@ use rustc_ast::walk_list;
use rustc_ast::*;
use rustc_ast_pretty::pprust::{self, State};
use rustc_data_structures::fx::FxHashMap;
-use rustc_errors::{error_code, fluent, pluralize, struct_span_err, Applicability};
use rustc_macros::Subdiagnostic;
use rustc_parse::validate_attr;
use rustc_session::lint::builtin::{
@@ -27,11 +26,10 @@ use rustc_span::Span;
use rustc_target::spec::abi;
use std::mem;
use std::ops::{Deref, DerefMut};
+use thin_vec::thin_vec;
-use crate::errors::*;
-
-const MORE_EXTERN: &str =
- "for more information, visit https://doc.rust-lang.org/std/keyword.extern.html";
+use crate::errors;
+use crate::fluent_generated as fluent;
/// Is `self` allowed semantically as the first parameter in an `FnDecl`?
enum SelfSemantic {
@@ -69,10 +67,6 @@ struct AstValidator<'a> {
/// or `Foo::Bar<impl Trait>`
is_impl_trait_banned: bool,
- /// Used to ban associated type bounds (i.e., `Type<AssocType: Bounds>`) in
- /// certain positions.
- is_assoc_ty_bound_banned: bool,
-
/// See [ForbiddenLetReason]
forbidden_let_reason: Option<ForbiddenLetReason>,
@@ -136,9 +130,9 @@ impl<'a> AstValidator<'a> {
fn ban_let_expr(&self, expr: &'a Expr, forbidden_let_reason: ForbiddenLetReason) {
let sess = &self.session;
if sess.opts.unstable_features.is_nightly_build() {
- sess.emit_err(ForbiddenLet { span: expr.span, reason: forbidden_let_reason });
+ sess.emit_err(errors::ForbiddenLet { span: expr.span, reason: forbidden_let_reason });
} else {
- sess.emit_err(ForbiddenLetStable { span: expr.span });
+ sess.emit_err(errors::ForbiddenLetStable { span: expr.span });
}
}
@@ -178,30 +172,12 @@ impl<'a> AstValidator<'a> {
}
}
- fn with_banned_assoc_ty_bound(&mut self, f: impl FnOnce(&mut Self)) {
- let old = mem::replace(&mut self.is_assoc_ty_bound_banned, true);
- f(self);
- self.is_assoc_ty_bound_banned = old;
- }
-
fn with_impl_trait(&mut self, outer: Option<Span>, f: impl FnOnce(&mut Self)) {
let old = mem::replace(&mut self.outer_impl_trait, outer);
f(self);
self.outer_impl_trait = old;
}
- fn visit_assoc_constraint_from_generic_args(&mut self, constraint: &'a AssocConstraint) {
- match constraint.kind {
- AssocConstraintKind::Equality { .. } => {}
- AssocConstraintKind::Bound { .. } => {
- if self.is_assoc_ty_bound_banned {
- self.session.emit_err(ForbiddenAssocConstraint { span: constraint.span });
- }
- }
- }
- self.visit_assoc_constraint(constraint);
- }
-
// Mirrors `visit::walk_ty`, but tracks relevant state.
fn walk_ty(&mut self, t: &'a Ty) {
match &t.kind {
@@ -216,7 +192,7 @@ impl<'a> AstValidator<'a> {
// We allow these:
// - `Option<impl Trait>`
// - `option::Option<impl Trait>`
- // - `option::Option<T>::Foo<impl Trait>
+ // - `option::Option<T>::Foo<impl Trait>`
//
// But not these:
// - `<impl Trait>::Foo`
@@ -254,24 +230,24 @@ impl<'a> AstValidator<'a> {
fn check_lifetime(&self, ident: Ident) {
let valid_names = [kw::UnderscoreLifetime, kw::StaticLifetime, kw::Empty];
if !valid_names.contains(&ident.name) && ident.without_first_quote().is_reserved() {
- self.session.emit_err(KeywordLifetime { span: ident.span });
+ self.session.emit_err(errors::KeywordLifetime { span: ident.span });
}
}
fn check_label(&self, ident: Ident) {
if ident.without_first_quote().is_reserved() {
- self.session.emit_err(InvalidLabel { span: ident.span, name: ident.name });
+ self.session.emit_err(errors::InvalidLabel { span: ident.span, name: ident.name });
}
}
- fn invalid_visibility(&self, vis: &Visibility, note: Option<InvalidVisibilityNote>) {
+ fn invalid_visibility(&self, vis: &Visibility, note: Option<errors::InvalidVisibilityNote>) {
if let VisibilityKind::Inherited = vis.kind {
return;
}
- self.session.emit_err(InvalidVisibility {
+ self.session.emit_err(errors::InvalidVisibility {
span: vis.span,
- implied: if vis.kind.is_pub() { Some(vis.span) } else { None },
+ implied: vis.kind.is_pub().then_some(vis.span),
note,
});
}
@@ -290,28 +266,7 @@ impl<'a> AstValidator<'a> {
fn check_trait_fn_not_const(&self, constness: Const) {
if let Const::Yes(span) = constness {
- self.session.emit_err(TraitFnConst { span });
- }
- }
-
- fn check_late_bound_lifetime_defs(&self, params: &[GenericParam]) {
- // Check only lifetime parameters are present and that the lifetime
- // parameters that are present have no bounds.
- let non_lt_param_spans: Vec<_> = params
- .iter()
- .filter_map(|param| match param.kind {
- GenericParamKind::Lifetime { .. } => {
- if !param.bounds.is_empty() {
- let spans: Vec<_> = param.bounds.iter().map(|b| b.span()).collect();
- self.session.emit_err(ForbiddenLifetimeBound { spans });
- }
- None
- }
- _ => Some(param.ident.span),
- })
- .collect();
- if !non_lt_param_spans.is_empty() {
- self.session.emit_err(ForbiddenNonLifetimeParam { spans: non_lt_param_spans });
+ self.session.emit_err(errors::TraitFnConst { span });
}
}
@@ -328,7 +283,7 @@ impl<'a> AstValidator<'a> {
let max_num_args: usize = u16::MAX.into();
if fn_decl.inputs.len() > max_num_args {
let Param { span, .. } = fn_decl.inputs[0];
- self.session.emit_fatal(FnParamTooMany { span, max_num_args });
+ self.session.emit_fatal(errors::FnParamTooMany { span, max_num_args });
}
}
@@ -336,13 +291,13 @@ impl<'a> AstValidator<'a> {
match &*fn_decl.inputs {
[Param { ty, span, .. }] => {
if let TyKind::CVarArgs = ty.kind {
- self.session.emit_err(FnParamCVarArgsOnly { span: *span });
+ self.session.emit_err(errors::FnParamCVarArgsOnly { span: *span });
}
}
[ps @ .., _] => {
for Param { ty, span, .. } in ps {
if let TyKind::CVarArgs = ty.kind {
- self.session.emit_err(FnParamCVarArgsNotLast { span: *span });
+ self.session.emit_err(errors::FnParamCVarArgsNotLast { span: *span });
}
}
}
@@ -369,9 +324,9 @@ impl<'a> AstValidator<'a> {
})
.for_each(|attr| {
if attr.is_doc_comment() {
- self.session.emit_err(FnParamDocComment { span: attr.span });
+ self.session.emit_err(errors::FnParamDocComment { span: attr.span });
} else {
- self.session.emit_err(FnParamForbiddenAttr { span: attr.span });
+ self.session.emit_err(errors::FnParamForbiddenAttr { span: attr.span });
}
});
}
@@ -379,7 +334,7 @@ impl<'a> AstValidator<'a> {
fn check_decl_self_param(&self, fn_decl: &FnDecl, self_semantic: SelfSemantic) {
if let (SelfSemantic::No, [param, ..]) = (self_semantic, &*fn_decl.inputs) {
if param.is_self() {
- self.session.emit_err(FnParamForbiddenSelf { span: param.span });
+ self.session.emit_err(errors::FnParamForbiddenSelf { span: param.span });
}
}
}
@@ -387,7 +342,7 @@ impl<'a> AstValidator<'a> {
fn check_defaultness(&self, span: Span, defaultness: Defaultness) {
if let Defaultness::Default(def_span) = defaultness {
let span = self.session.source_map().guess_head_span(span);
- self.session.emit_err(ForbiddenDefault { span, def_span });
+ self.session.emit_err(errors::ForbiddenDefault { span, def_span });
}
}
@@ -410,27 +365,17 @@ impl<'a> AstValidator<'a> {
[b0] => b0.span(),
[b0, .., bl] => b0.span().to(bl.span()),
};
- self.err_handler()
- .struct_span_err(span, &format!("bounds on `type`s in {} have no effect", ctx))
- .emit();
+ self.err_handler().emit_err(errors::BoundInContext { span, ctx });
}
fn check_foreign_ty_genericless(&self, generics: &Generics, where_span: Span) {
let cannot_have = |span, descr, remove_descr| {
- self.err_handler()
- .struct_span_err(
- span,
- &format!("`type`s inside `extern` blocks cannot have {}", descr),
- )
- .span_suggestion(
- span,
- &format!("remove the {}", remove_descr),
- "",
- Applicability::MaybeIncorrect,
- )
- .span_label(self.current_extern_span(), "`extern` block begins here")
- .note(MORE_EXTERN)
- .emit();
+ self.err_handler().emit_err(errors::ExternTypesCannotHave {
+ span,
+ descr,
+ remove_descr,
+ block_span: self.current_extern_span(),
+ });
};
if !generics.params.is_empty() {
@@ -446,20 +391,12 @@ impl<'a> AstValidator<'a> {
let Some(body) = body else {
return;
};
- self.err_handler()
- .struct_span_err(ident.span, &format!("incorrect `{}` inside `extern` block", kind))
- .span_label(ident.span, "cannot have a body")
- .span_label(body, "the invalid body")
- .span_label(
- self.current_extern_span(),
- format!(
- "`extern` blocks define existing foreign {0}s and {0}s \
- inside of them cannot have a body",
- kind
- ),
- )
- .note(MORE_EXTERN)
- .emit();
+ self.err_handler().emit_err(errors::BodyInExtern {
+ span: ident.span,
+ body,
+ block: self.current_extern_span(),
+ kind,
+ });
}
/// An `fn` in `extern { ... }` cannot have a body `{ ... }`.
@@ -467,26 +404,11 @@ impl<'a> AstValidator<'a> {
let Some(body) = body else {
return;
};
- self.err_handler()
- .struct_span_err(ident.span, "incorrect function inside `extern` block")
- .span_label(ident.span, "cannot have a body")
- .span_suggestion(
- body.span,
- "remove the invalid body",
- ";",
- Applicability::MaybeIncorrect,
- )
- .help(
- "you might have meant to write a function accessible through FFI, \
- which can be done by writing `extern fn` outside of the `extern` block",
- )
- .span_label(
- self.current_extern_span(),
- "`extern` blocks define existing foreign functions and functions \
- inside of them cannot have a body",
- )
- .note(MORE_EXTERN)
- .emit();
+ self.err_handler().emit_err(errors::FnBodyInExtern {
+ span: ident.span,
+ body: body.span,
+ block: self.current_extern_span(),
+ });
}
fn current_extern_span(&self) -> Span {
@@ -496,34 +418,21 @@ impl<'a> AstValidator<'a> {
/// An `fn` in `extern { ... }` cannot have qualifiers, e.g. `async fn`.
fn check_foreign_fn_headerless(&self, ident: Ident, span: Span, header: FnHeader) {
if header.has_qualifiers() {
- self.err_handler()
- .struct_span_err(ident.span, "functions in `extern` blocks cannot have qualifiers")
- .span_label(self.current_extern_span(), "in this `extern` block")
- .span_suggestion_verbose(
- span.until(ident.span.shrink_to_lo()),
- "remove the qualifiers",
- "fn ",
- Applicability::MaybeIncorrect,
- )
- .emit();
+ self.err_handler().emit_err(errors::FnQualifierInExtern {
+ span: ident.span,
+ block: self.current_extern_span(),
+ sugg_span: span.until(ident.span.shrink_to_lo()),
+ });
}
}
/// An item in `extern { ... }` cannot use non-ascii identifier.
fn check_foreign_item_ascii_only(&self, ident: Ident) {
if !ident.as_str().is_ascii() {
- let n = 83942;
- self.err_handler()
- .struct_span_err(
- ident.span,
- "items in `extern` blocks cannot use non-ascii identifiers",
- )
- .span_label(self.current_extern_span(), "in this `extern` block")
- .note(&format!(
- "this limitation may be lifted in the future; see issue #{} <https://github.com/rust-lang/rust/issues/{}> for more information",
- n, n,
- ))
- .emit();
+ self.err_handler().emit_err(errors::ExternItemAscii {
+ span: ident.span,
+ block: self.current_extern_span(),
+ });
}
}
@@ -546,12 +455,7 @@ impl<'a> AstValidator<'a> {
for Param { ty, span, .. } in &fk.decl().inputs {
if let TyKind::CVarArgs = ty.kind {
- self.err_handler()
- .struct_span_err(
- *span,
- "only foreign or `unsafe extern \"C\"` functions may be C-variadic",
- )
- .emit();
+ self.err_handler().emit_err(errors::BadCVariadic { span: *span });
}
}
}
@@ -560,75 +464,32 @@ impl<'a> AstValidator<'a> {
if ident.name != kw::Underscore {
return;
}
- self.err_handler()
- .struct_span_err(ident.span, &format!("`{}` items in this context need a name", kind))
- .span_label(ident.span, format!("`_` is not a valid name for this `{}` item", kind))
- .emit();
+ self.err_handler().emit_err(errors::ItemUnderscore { span: ident.span, kind });
}
fn check_nomangle_item_asciionly(&self, ident: Ident, item_span: Span) {
if ident.name.as_str().is_ascii() {
return;
}
- let head_span = self.session.source_map().guess_head_span(item_span);
- struct_span_err!(
- self.session,
- head_span,
- E0754,
- "`#[no_mangle]` requires ASCII identifier"
- )
- .emit();
+ let span = self.session.source_map().guess_head_span(item_span);
+ self.session.emit_err(errors::NoMangleAscii { span });
}
fn check_mod_file_item_asciionly(&self, ident: Ident) {
if ident.name.as_str().is_ascii() {
return;
}
- struct_span_err!(
- self.session,
- ident.span,
- E0754,
- "trying to load file for module `{}` with non-ascii identifier name",
- ident.name
- )
- .help("consider using `#[path]` attribute to specify filesystem path")
- .emit();
+ self.session.emit_err(errors::ModuleNonAscii { span: ident.span, name: ident.name });
}
- fn deny_generic_params(&self, generics: &Generics, ident_span: Span) {
+ fn deny_generic_params(&self, generics: &Generics, ident: Span) {
if !generics.params.is_empty() {
- struct_span_err!(
- self.session,
- generics.span,
- E0567,
- "auto traits cannot have generic parameters"
- )
- .span_label(ident_span, "auto trait cannot have generic parameters")
- .span_suggestion(
- generics.span,
- "remove the parameters",
- "",
- Applicability::MachineApplicable,
- )
- .emit();
+ self.session.emit_err(errors::AutoTraitGeneric { span: generics.span, ident });
}
}
- 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",
- "",
- Applicability::MachineApplicable,
- )
- .emit();
+ fn emit_e0568(&self, span: Span, ident: Span) {
+ self.session.emit_err(errors::AutoTraitBounds { span, ident });
}
fn deny_super_traits(&self, bounds: &GenericBounds, ident_span: Span) {
@@ -644,24 +505,11 @@ impl<'a> AstValidator<'a> {
}
}
- fn deny_items(&self, trait_items: &[P<AssocItem>], ident_span: Span) {
+ fn deny_items(&self, trait_items: &[P<AssocItem>], ident: 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 associated items"
- )
- .span_suggestion(
- total_span,
- "remove these associated items",
- "",
- Applicability::MachineApplicable,
- )
- .span_label(ident_span, "auto trait cannot have associated items")
- .emit();
+ let total = trait_items.first().unwrap().span.to(trait_items.last().unwrap().span);
+ self.session.emit_err(errors::AutoTraitItems { spans, total, ident });
}
}
@@ -707,29 +555,17 @@ impl<'a> AstValidator<'a> {
let args_len = arg_spans.len();
let constraint_len = constraint_spans.len();
// ...and then error:
- self.err_handler()
- .struct_span_err(
- arg_spans.clone(),
- "generic arguments must come before the first constraint",
- )
- .span_label(constraint_spans[0], &format!("constraint{}", pluralize!(constraint_len)))
- .span_label(
- *arg_spans.iter().last().unwrap(),
- &format!("generic argument{}", pluralize!(args_len)),
- )
- .span_labels(constraint_spans, "")
- .span_labels(arg_spans, "")
- .span_suggestion_verbose(
- data.span,
- &format!(
- "move the constraint{} after the generic argument{}",
- pluralize!(constraint_len),
- pluralize!(args_len)
- ),
- self.correct_generic_order_suggestion(&data),
- Applicability::MachineApplicable,
- )
- .emit();
+ self.err_handler().emit_err(errors::ArgsBeforeConstraint {
+ arg_spans: arg_spans.clone(),
+ constraints: constraint_spans[0],
+ args: *arg_spans.iter().last().unwrap(),
+ data: data.span,
+ constraint_spans: errors::EmptyLabelManySpans(constraint_spans),
+ arg_spans2: errors::EmptyLabelManySpans(arg_spans),
+ suggestion: self.correct_generic_order_suggestion(&data),
+ constraint_len,
+ args_len,
+ });
}
fn visit_ty_common(&mut self, ty: &'a Ty) {
@@ -737,15 +573,8 @@ impl<'a> AstValidator<'a> {
TyKind::BareFn(bfty) => {
self.check_fn_decl(&bfty.decl, SelfSemantic::No);
Self::check_decl_no_pat(&bfty.decl, |span, _, _| {
- struct_span_err!(
- self.session,
- span,
- E0561,
- "patterns aren't allowed in function pointer types"
- )
- .emit();
+ self.session.emit_err(errors::PatternFnPointer { span });
});
- self.check_late_bound_lifetime_defs(&bfty.generic_params);
if let Extern::Implicit(_) = bfty.ext {
let sig_span = self.session.source_map().next_point(ty.span.shrink_to_lo());
self.maybe_lint_missing_abi(sig_span, ty.id);
@@ -756,13 +585,8 @@ impl<'a> AstValidator<'a> {
for bound in bounds {
if let GenericBound::Outlives(lifetime) = bound {
if any_lifetime_bounds {
- struct_span_err!(
- self.session,
- lifetime.ident.span,
- E0226,
- "only a single explicit lifetime bound is permitted"
- )
- .emit();
+ self.session
+ .emit_err(errors::TraitObjectBound { span: lifetime.ident.span });
break;
}
any_lifetime_bounds = true;
@@ -771,29 +595,19 @@ impl<'a> AstValidator<'a> {
}
TyKind::ImplTrait(_, bounds) => {
if self.is_impl_trait_banned {
- struct_span_err!(
- self.session,
- ty.span,
- E0667,
- "`impl Trait` is not allowed in path parameters"
- )
- .emit();
+ self.session.emit_err(errors::ImplTraitPath { span: ty.span });
}
if let Some(outer_impl_trait_sp) = self.outer_impl_trait {
- struct_span_err!(
- self.session,
- ty.span,
- E0666,
- "nested `impl Trait` is not allowed"
- )
- .span_label(outer_impl_trait_sp, "outer `impl Trait`")
- .span_label(ty.span, "nested `impl Trait` here")
- .emit();
+ self.session.emit_err(errors::NestedImplTrait {
+ span: ty.span,
+ outer: outer_impl_trait_sp,
+ inner: ty.span,
+ });
}
if !bounds.iter().any(|b| matches!(b, GenericBound::Trait(..))) {
- self.err_handler().span_err(ty.span, "at least one trait must be specified");
+ self.err_handler().emit_err(errors::AtLeastOneTrait { span: ty.span });
}
}
_ => {}
@@ -814,7 +628,7 @@ impl<'a> AstValidator<'a> {
MISSING_ABI,
id,
span,
- "extern declarations without an explicit ABI are deprecated",
+ fluent::ast_passes_extern_without_abi,
BuiltinLintDiagnostics::MissingAbi(span, abi::Abi::FALLBACK),
)
}
@@ -887,20 +701,13 @@ fn validate_generic_param_order(
ordered_params += ">";
for (param_ord, (max_param, spans)) in &out_of_order {
- let mut err = handler.struct_span_err(
- spans.clone(),
- &format!(
- "{} parameters must be declared prior to {} parameters",
- param_ord, max_param,
- ),
- );
- err.span_suggestion(
- span,
- "reorder the parameters: lifetimes, then consts and types",
- &ordered_params,
- Applicability::MachineApplicable,
- );
- err.emit();
+ handler.emit_err(errors::OutOfOrderParams {
+ spans: spans.clone(),
+ sugg_span: span,
+ param_ord,
+ max_param,
+ ordered_params: &ordered_params,
+ });
}
}
}
@@ -1014,25 +821,15 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
self.with_in_trait_impl(true, Some(*constness), |this| {
this.invalid_visibility(&item.vis, None);
if let TyKind::Err = self_ty.kind {
- this.err_handler()
- .struct_span_err(
- item.span,
- "`impl Trait for .. {}` is an obsolete syntax",
- )
- .help("use `auto trait Trait {}` instead")
- .emit();
+ this.err_handler().emit_err(errors::ObsoleteAuto { span: item.span });
}
if let (&Unsafe::Yes(span), &ImplPolarity::Negative(sp)) = (unsafety, polarity)
{
- struct_span_err!(
- this.session,
- sp.to(t.path.span),
- E0198,
- "negative impls cannot be unsafe"
- )
- .span_label(sp, "negative because of this")
- .span_label(span, "unsafe because of this")
- .emit();
+ this.session.emit_err(errors::UnsafeNegativeImpl {
+ span: sp.to(t.path.span),
+ negative: sp,
+ r#unsafe: span,
+ });
}
this.visit_vis(&item.vis);
@@ -1060,52 +857,54 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
self_ty,
items: _,
}) => {
- let error = |annotation_span, annotation| {
- let mut err = self.err_handler().struct_span_err(
- self_ty.span,
- &format!("inherent impls cannot be {}", annotation),
- );
- err.span_label(annotation_span, &format!("{} because of this", annotation));
- err.span_label(self_ty.span, "inherent impl for this type");
- err
- };
+ let error =
+ |annotation_span, annotation, only_trait: bool| errors::InherentImplCannot {
+ span: self_ty.span,
+ annotation_span,
+ annotation,
+ self_ty: self_ty.span,
+ only_trait: only_trait.then_some(()),
+ };
self.invalid_visibility(
&item.vis,
- Some(InvalidVisibilityNote::IndividualImplItems),
+ Some(errors::InvalidVisibilityNote::IndividualImplItems),
);
if let &Unsafe::Yes(span) = unsafety {
- error(span, "unsafe").code(error_code!(E0197)).emit();
+ self.err_handler().emit_err(errors::InherentImplCannotUnsafe {
+ span: self_ty.span,
+ annotation_span: span,
+ annotation: "unsafe",
+ self_ty: self_ty.span,
+ });
}
if let &ImplPolarity::Negative(span) = polarity {
- error(span, "negative").emit();
+ self.err_handler().emit_err(error(span, "negative", false));
}
if let &Defaultness::Default(def_span) = defaultness {
- error(def_span, "`default`")
- .note("only trait implementations may be annotated with `default`")
- .emit();
+ self.err_handler().emit_err(error(def_span, "`default`", true));
}
if let &Const::Yes(span) = constness {
- error(span, "`const`")
- .note("only trait implementations may be annotated with `const`")
- .emit();
+ self.err_handler().emit_err(error(span, "`const`", true));
}
}
ItemKind::Fn(box Fn { defaultness, sig, generics, body }) => {
self.check_defaultness(item.span, *defaultness);
if body.is_none() {
- self.session.emit_err(FnWithoutBody {
+ self.session.emit_err(errors::FnWithoutBody {
span: item.span,
replace_span: self.ending_semi_or_hi(item.span),
extern_block_suggestion: match sig.header.ext {
Extern::None => None,
- Extern::Implicit(start_span) => Some(ExternBlockSuggestion::Implicit {
- start_span,
- end_span: item.span.shrink_to_hi(),
- }),
+ Extern::Implicit(start_span) => {
+ Some(errors::ExternBlockSuggestion::Implicit {
+ start_span,
+ end_span: item.span.shrink_to_hi(),
+ })
+ }
Extern::Explicit(abi, start_span) => {
- Some(ExternBlockSuggestion::Explicit {
+ Some(errors::ExternBlockSuggestion::Explicit {
start_span,
end_span: item.span.shrink_to_hi(),
abi: abi.symbol_unescaped,
@@ -1127,10 +926,10 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
let old_item = mem::replace(&mut self.extern_mod, Some(item));
self.invalid_visibility(
&item.vis,
- Some(InvalidVisibilityNote::IndividualForeignItems),
+ Some(errors::InvalidVisibilityNote::IndividualForeignItems),
);
if let &Unsafe::Yes(span) = unsafety {
- self.err_handler().span_err(span, "extern block cannot be declared unsafe");
+ self.err_handler().emit_err(errors::UnsafeItem { span, kind: "extern block" });
}
if abi.is_none() {
self.maybe_lint_missing_abi(item.span, item.id);
@@ -1170,7 +969,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
}
ItemKind::Mod(unsafety, mod_kind) => {
if let &Unsafe::Yes(span) = unsafety {
- self.err_handler().span_err(span, "module cannot be declared unsafe");
+ self.err_handler().emit_err(errors::UnsafeItem { span, kind: "module" });
}
// Ensure that `path` attributes on modules are recorded as used (cf. issue #35584).
if !matches!(mod_kind, ModKind::Loaded(_, Inline::Yes, _))
@@ -1181,18 +980,18 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
}
ItemKind::Union(vdata, ..) => {
if vdata.fields().is_empty() {
- self.err_handler().span_err(item.span, "unions cannot have zero fields");
+ self.err_handler().emit_err(errors::FieldlessUnion { span: item.span });
}
}
ItemKind::Const(def, .., None) => {
self.check_defaultness(item.span, *def);
- self.session.emit_err(ConstWithoutBody {
+ self.session.emit_err(errors::ConstWithoutBody {
span: item.span,
replace_span: self.ending_semi_or_hi(item.span),
});
}
ItemKind::Static(.., None) => {
- self.session.emit_err(StaticWithoutBody {
+ self.session.emit_err(errors::StaticWithoutBody {
span: item.span,
replace_span: self.ending_semi_or_hi(item.span),
});
@@ -1200,21 +999,15 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
ItemKind::TyAlias(box TyAlias { defaultness, where_clauses, bounds, ty, .. }) => {
self.check_defaultness(item.span, *defaultness);
if ty.is_none() {
- self.session.emit_err(TyAliasWithoutBody {
+ self.session.emit_err(errors::TyAliasWithoutBody {
span: item.span,
replace_span: self.ending_semi_or_hi(item.span),
});
}
self.check_type_no_bounds(bounds, "this context");
if where_clauses.1.0 {
- let mut err = self.err_handler().struct_span_err(
- where_clauses.1.1,
- "where clauses are not allowed after the type for type aliases",
- );
- err.note(
- "see issue #89122 <https://github.com/rust-lang/rust/issues/89122> for more information",
- );
- err.emit();
+ self.err_handler()
+ .emit_err(errors::WhereAfterTypeAlias { span: where_clauses.1.1 });
}
}
_ => {}
@@ -1268,7 +1061,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
// are allowed to contain nested `impl Trait`.
AngleBracketedArg::Constraint(constraint) => {
self.with_impl_trait(None, |this| {
- this.visit_assoc_constraint_from_generic_args(constraint);
+ this.visit_assoc_constraint(constraint);
});
}
}
@@ -1296,11 +1089,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
}
GenericParamKind::Type { .. } | GenericParamKind::Const { .. } => {
if let Some(span) = prev_param_default {
- let mut err = self.err_handler().struct_span_err(
- span,
- "generic parameters with a default must be trailing",
- );
- err.emit();
+ self.err_handler().emit_err(errors::GenericDefaultTrailing { span });
break;
}
}
@@ -1318,9 +1107,6 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
for predicate in &generics.where_clause.predicates {
match predicate {
WherePredicate::BoundPredicate(bound_pred) => {
- // A type binding, eg `for<'c> Foo: Send+Clone+'c`
- self.check_late_bound_lifetime_defs(&bound_pred.bound_generic_params);
-
// This is slightly complicated. Our representation for poly-trait-refs contains a single
// binder and thus we only allow a single level of quantification. However,
// the syntax of Rust permits quantification in two places in where clauses,
@@ -1331,13 +1117,8 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
match bound {
GenericBound::Trait(t, _) => {
if !t.bound_generic_params.is_empty() {
- struct_span_err!(
- self.err_handler(),
- t.span,
- E0316,
- "nested quantification of lifetimes"
- )
- .emit();
+ self.err_handler()
+ .emit_err(errors::NestedLifetimes { span: t.span });
}
}
GenericBound::Outlives(_) => {}
@@ -1362,32 +1143,27 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
if let GenericBound::Trait(poly, modify) = bound {
match (ctxt, modify) {
(BoundKind::SuperTraits, TraitBoundModifier::Maybe) => {
- let mut err = self
- .err_handler()
- .struct_span_err(poly.span, "`?Trait` is not permitted in supertraits");
- let path_str = pprust::path_to_string(&poly.trait_ref.path);
- err.note(&format!("traits are `?{}` by default", path_str));
- err.emit();
+ self.err_handler().emit_err(errors::OptionalTraitSupertrait {
+ span: poly.span,
+ path_str: pprust::path_to_string(&poly.trait_ref.path)
+ });
}
(BoundKind::TraitObject, TraitBoundModifier::Maybe) => {
- let mut err = self.err_handler().struct_span_err(
- poly.span,
- "`?Trait` is not permitted in trait object types",
- );
- err.emit();
+ self.err_handler().emit_err(errors::OptionalTraitObject {span: poly.span});
}
(_, TraitBoundModifier::MaybeConst) if let Some(reason) = &self.disallow_tilde_const => {
- let mut err = self.err_handler().struct_span_err(bound.span(), "`~const` is not allowed here");
- match reason {
- DisallowTildeConstContext::TraitObject => err.note("trait objects cannot have `~const` trait bounds"),
- DisallowTildeConstContext::Fn(FnKind::Closure(..)) => err.note("closures cannot have `~const` trait bounds"),
- DisallowTildeConstContext::Fn(FnKind::Fn(_, ident, ..)) => err.span_note(ident.span, "this function is not `const`, so it cannot have `~const` trait bounds"),
+ let reason = match reason {
+ DisallowTildeConstContext::TraitObject => errors::TildeConstReason::TraitObject,
+ DisallowTildeConstContext::Fn(FnKind::Closure(..)) => errors::TildeConstReason::Closure,
+ DisallowTildeConstContext::Fn(FnKind::Fn(_, ident, ..)) => errors::TildeConstReason::Function { ident: ident.span },
};
- err.emit();
+ self.err_handler().emit_err(errors::TildeConstDisallowed {
+ span: bound.span(),
+ reason
+ });
}
(_, TraitBoundModifier::MaybeConstMaybe) => {
- self.err_handler()
- .span_err(bound.span(), "`~const` and `?` are mutually exclusive");
+ self.err_handler().emit_err(errors::OptionalConstExclusive {span: bound.span()});
}
_ => {}
}
@@ -1396,19 +1172,6 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
visit::walk_param_bound(self, bound)
}
- fn visit_poly_trait_ref(&mut self, t: &'a PolyTraitRef) {
- self.check_late_bound_lifetime_defs(&t.bound_generic_params);
- visit::walk_poly_trait_ref(self, t);
- }
-
- fn visit_variant_data(&mut self, s: &'a VariantData) {
- self.with_banned_assoc_ty_bound(|this| visit::walk_struct_def(this, s))
- }
-
- fn visit_enum_def(&mut self, enum_definition: &'a EnumDef) {
- self.with_banned_assoc_ty_bound(|this| visit::walk_enum_def(this, enum_definition))
- }
-
fn visit_fn(&mut self, fk: FnKind<'a>, span: Span, id: NodeId) {
// Only associated `fn`s can have `self` parameters.
let self_semantic = match fk.ctxt() {
@@ -1420,25 +1183,18 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
self.check_c_variadic_type(fk);
// Functions cannot both be `const async`
- if let Some(FnHeader {
+ if let Some(&FnHeader {
constness: Const::Yes(cspan),
asyncness: Async::Yes { span: aspan, .. },
..
}) = fk.header()
{
- self.err_handler()
- .struct_span_err(
- vec![*cspan, *aspan],
- "functions cannot be both `const` and `async`",
- )
- .span_label(*cspan, "`const` because of this")
- .span_label(*aspan, "`async` because of this")
- .span_label(span, "") // Point at the fn header.
- .emit();
- }
-
- if let FnKind::Closure(ClosureBinder::For { generic_params, .. }, ..) = fk {
- self.check_late_bound_lifetime_defs(generic_params);
+ self.err_handler().emit_err(errors::ConstAndAsync {
+ spans: vec![cspan, aspan],
+ cspan,
+ aspan,
+ span,
+ });
}
if let FnKind::Fn(
@@ -1456,20 +1212,12 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
// Functions without bodies cannot have patterns.
if let FnKind::Fn(ctxt, _, sig, _, _, None) = fk {
Self::check_decl_no_pat(&sig.decl, |span, ident, mut_ident| {
- let (code, msg, label) = match ctxt {
- FnCtxt::Foreign => (
- error_code!(E0130),
- "patterns aren't allowed in foreign function declarations",
- "pattern not allowed in foreign function",
- ),
- _ => (
- error_code!(E0642),
- "patterns aren't allowed in functions without bodies",
- "pattern not allowed in function without body",
- ),
- };
if mut_ident && matches!(ctxt, FnCtxt::Assoc(_)) {
if let Some(ident) = ident {
+ let msg = match ctxt {
+ FnCtxt::Foreign => fluent::ast_passes_pattern_in_foreign,
+ _ => fluent::ast_passes_pattern_in_bodiless,
+ };
let diag = BuiltinLintDiagnostics::PatternsInFnsWithoutBody(span, ident);
self.lint_buffer.buffer_lint_with_diagnostic(
PATTERNS_IN_FNS_WITHOUT_BODY,
@@ -1480,11 +1228,12 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
)
}
} else {
- self.err_handler()
- .struct_span_err(span, msg)
- .span_label(span, label)
- .code(code)
- .emit();
+ match ctxt {
+ FnCtxt::Foreign => {
+ self.err_handler().emit_err(errors::PatternInForeign { span })
+ }
+ _ => self.err_handler().emit_err(errors::PatternInBodiless { span }),
+ };
}
});
}
@@ -1511,7 +1260,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
match &item.kind {
AssocItemKind::Const(_, _, body) => {
if body.is_none() {
- self.session.emit_err(AssocConstWithoutBody {
+ self.session.emit_err(errors::AssocConstWithoutBody {
span: item.span,
replace_span: self.ending_semi_or_hi(item.span),
});
@@ -1519,7 +1268,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
}
AssocItemKind::Fn(box Fn { body, .. }) => {
if body.is_none() {
- self.session.emit_err(AssocFnWithoutBody {
+ self.session.emit_err(errors::AssocFnWithoutBody {
span: item.span,
replace_span: self.ending_semi_or_hi(item.span),
});
@@ -1534,7 +1283,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
..
}) => {
if ty.is_none() {
- self.session.emit_err(AssocTypeWithoutBody {
+ self.session.emit_err(errors::AssocTypeWithoutBody {
span: item.span,
replace_span: self.ending_semi_or_hi(item.span),
});
@@ -1606,11 +1355,7 @@ fn deny_equality_constraints(
predicate: &WhereEqPredicate,
generics: &Generics,
) {
- let mut err = this.err_handler().struct_span_err(
- predicate.span,
- "equality constraints are not yet supported in `where` clauses",
- );
- err.span_label(predicate.span, "not supported");
+ let mut err = errors::EqualityInWhere { span: predicate.span, assoc: None, assoc2: None };
// Given `<A as Foo>::Bar = RhsTy`, suggest `A: Foo<Bar = RhsTy>`.
if let TyKind::Path(Some(qself), full_path) = &predicate.lhs_ty.kind {
@@ -1649,25 +1394,17 @@ fn deny_equality_constraints(
empty_args => {
*empty_args = AngleBracketedArgs {
span: ident.span,
- args: vec![arg],
+ args: thin_vec![arg],
}
.into();
}
}
- err.span_suggestion_verbose(
- predicate.span,
- &format!(
- "if `{}` is an associated type you're trying to set, \
- use the associated type binding syntax",
- ident
- ),
- format!(
- "{}: {}",
- param,
- pprust::path_to_string(&assoc_path)
- ),
- Applicability::MaybeIncorrect,
- );
+ err.assoc = Some(errors::AssociatedSuggestion {
+ span: predicate.span,
+ ident: *ident,
+ param: *param,
+ path: pprust::path_to_string(&assoc_path),
+ })
}
_ => {}
};
@@ -1709,15 +1446,13 @@ fn deny_equality_constraints(
trait_segment.span().shrink_to_hi(),
),
};
- err.multipart_suggestion(
- &format!(
- "if `{}::{}` is an associated type you're trying to set, \
- use the associated type binding syntax",
- trait_segment.ident, potential_assoc.ident,
- ),
- vec![(span, args), (predicate.span, String::new())],
- Applicability::MaybeIncorrect,
- );
+ err.assoc2 = Some(errors::AssociatedSuggestion2 {
+ span,
+ args,
+ predicate: predicate.span,
+ trait_segment: trait_segment.ident,
+ potential_assoc: potential_assoc.ident,
+ });
}
}
}
@@ -1725,10 +1460,7 @@ fn deny_equality_constraints(
}
}
}
- err.note(
- "see issue #20041 <https://github.com/rust-lang/rust/issues/20041> for more information",
- );
- err.emit();
+ this.err_handler().emit_err(err);
}
pub fn check_crate(session: &Session, krate: &Crate, lints: &mut LintBuffer) -> bool {
@@ -1741,7 +1473,6 @@ pub fn check_crate(session: &Session, krate: &Crate, lints: &mut LintBuffer) ->
outer_impl_trait: None,
disallow_tilde_const: None,
is_impl_trait_banned: false,
- is_assoc_ty_bound_banned: false,
forbidden_let_reason: Some(ForbiddenLetReason::GenericForbidden),
lint_buffer: lints,
};
@@ -1756,12 +1487,12 @@ pub(crate) enum ForbiddenLetReason {
/// `let` is not valid and the source environment is not important
GenericForbidden,
/// A let chain with the `||` operator
- #[note(not_supported_or)]
+ #[note(ast_passes_not_supported_or)]
NotSupportedOr(#[primary_span] Span),
/// A let chain with invalid parentheses
///
/// For example, `let 1 = 1 && (expr && expr)` is allowed
/// but `(let 1 = 1 && (let 1 = 1 && (let 1 = 1))) && let a = 1` is not
- #[note(not_supported_parentheses)]
+ #[note(ast_passes_not_supported_parentheses)]
NotSupportedParentheses(#[primary_span] Span),
}
diff --git a/compiler/rustc_ast_passes/src/errors.rs b/compiler/rustc_ast_passes/src/errors.rs
index 09e262452..d007097d9 100644
--- a/compiler/rustc_ast_passes/src/errors.rs
+++ b/compiler/rustc_ast_passes/src/errors.rs
@@ -1,9 +1,12 @@
//! Errors emitted by ast_passes.
+use rustc_ast::ParamKindOrd;
+use rustc_errors::AddToDiagnostic;
use rustc_macros::{Diagnostic, Subdiagnostic};
-use rustc_span::{Span, Symbol};
+use rustc_span::{symbol::Ident, Span, Symbol};
use crate::ast_validation::ForbiddenLetReason;
+use crate::fluent_generated as fluent;
#[derive(Diagnostic)]
#[diag(ast_passes_forbidden_let)]
@@ -24,13 +27,6 @@ pub struct ForbiddenLetStable {
}
#[derive(Diagnostic)]
-#[diag(ast_passes_forbidden_assoc_constraint)]
-pub struct ForbiddenAssocConstraint {
- #[primary_span]
- pub span: Span,
-}
-
-#[derive(Diagnostic)]
#[diag(ast_passes_keyword_lifetime)]
pub struct KeywordLifetime {
#[primary_span]
@@ -50,7 +46,7 @@ pub struct InvalidLabel {
pub struct InvalidVisibility {
#[primary_span]
pub span: Span,
- #[label(implied)]
+ #[label(ast_passes_implied)]
pub implied: Option<Span>,
#[subdiagnostic]
pub note: Option<InvalidVisibilityNote>,
@@ -58,9 +54,9 @@ pub struct InvalidVisibility {
#[derive(Subdiagnostic)]
pub enum InvalidVisibilityNote {
- #[note(individual_impl_items)]
+ #[note(ast_passes_individual_impl_items)]
IndividualImplItems,
- #[note(individual_foreign_items)]
+ #[note(ast_passes_individual_foreign_items)]
IndividualForeignItems,
}
@@ -224,3 +220,474 @@ pub enum ExternBlockSuggestion {
abi: Symbol,
},
}
+
+#[derive(Diagnostic)]
+#[diag(ast_passes_bound_in_context)]
+pub struct BoundInContext<'a> {
+ #[primary_span]
+ pub span: Span,
+ pub ctx: &'a str,
+}
+
+#[derive(Diagnostic)]
+#[diag(ast_passes_extern_types_cannot)]
+#[note(ast_passes_extern_keyword_link)]
+pub struct ExternTypesCannotHave<'a> {
+ #[primary_span]
+ #[suggestion(code = "", applicability = "maybe-incorrect")]
+ pub span: Span,
+ pub descr: &'a str,
+ pub remove_descr: &'a str,
+ #[label]
+ pub block_span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(ast_passes_body_in_extern)]
+#[note(ast_passes_extern_keyword_link)]
+pub struct BodyInExtern<'a> {
+ #[primary_span]
+ #[label(ast_passes_cannot_have)]
+ pub span: Span,
+ #[label(ast_passes_invalid)]
+ pub body: Span,
+ #[label(ast_passes_existing)]
+ pub block: Span,
+ pub kind: &'a str,
+}
+
+#[derive(Diagnostic)]
+#[diag(ast_passes_fn_body_extern)]
+#[help]
+#[note(ast_passes_extern_keyword_link)]
+pub struct FnBodyInExtern {
+ #[primary_span]
+ #[label(ast_passes_cannot_have)]
+ pub span: Span,
+ #[suggestion(code = ";", applicability = "maybe-incorrect")]
+ pub body: Span,
+ #[label]
+ pub block: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(ast_passes_extern_fn_qualifiers)]
+pub struct FnQualifierInExtern {
+ #[primary_span]
+ pub span: Span,
+ #[label]
+ pub block: Span,
+ #[suggestion(code = "fn ", applicability = "maybe-incorrect", style = "verbose")]
+ pub sugg_span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(ast_passes_extern_item_ascii)]
+#[note]
+pub struct ExternItemAscii {
+ #[primary_span]
+ pub span: Span,
+ #[label]
+ pub block: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(ast_passes_bad_c_variadic)]
+pub struct BadCVariadic {
+ #[primary_span]
+ pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(ast_passes_item_underscore)]
+pub struct ItemUnderscore<'a> {
+ #[primary_span]
+ #[label]
+ pub span: Span,
+ pub kind: &'a str,
+}
+
+#[derive(Diagnostic)]
+#[diag(ast_passes_nomangle_ascii, code = "E0754")]
+pub struct NoMangleAscii {
+ #[primary_span]
+ pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(ast_passes_module_nonascii, code = "E0754")]
+#[help]
+pub struct ModuleNonAscii {
+ #[primary_span]
+ pub span: Span,
+ pub name: Symbol,
+}
+
+#[derive(Diagnostic)]
+#[diag(ast_passes_auto_generic, code = "E0567")]
+pub struct AutoTraitGeneric {
+ #[primary_span]
+ #[suggestion(code = "", applicability = "machine-applicable")]
+ pub span: Span,
+ #[label]
+ pub ident: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(ast_passes_auto_super_lifetime, code = "E0568")]
+pub struct AutoTraitBounds {
+ #[primary_span]
+ #[suggestion(code = "", applicability = "machine-applicable")]
+ pub span: Span,
+ #[label]
+ pub ident: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(ast_passes_auto_items, code = "E0380")]
+pub struct AutoTraitItems {
+ #[primary_span]
+ pub spans: Vec<Span>,
+ #[suggestion(code = "", applicability = "machine-applicable")]
+ pub total: Span,
+ #[label]
+ pub ident: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(ast_passes_generic_before_constraints)]
+pub struct ArgsBeforeConstraint {
+ #[primary_span]
+ pub arg_spans: Vec<Span>,
+ #[label(ast_passes_constraints)]
+ pub constraints: Span,
+ #[label(ast_passes_args)]
+ pub args: Span,
+ #[suggestion(code = "{suggestion}", applicability = "machine-applicable", style = "verbose")]
+ pub data: Span,
+ pub suggestion: String,
+ pub constraint_len: usize,
+ pub args_len: usize,
+ #[subdiagnostic]
+ pub constraint_spans: EmptyLabelManySpans,
+ #[subdiagnostic]
+ pub arg_spans2: EmptyLabelManySpans,
+}
+
+pub struct EmptyLabelManySpans(pub Vec<Span>);
+
+// The derive for `Vec<Span>` does multiple calls to `span_label`, adding commas between each
+impl AddToDiagnostic for EmptyLabelManySpans {
+ fn add_to_diagnostic_with<F>(self, diag: &mut rustc_errors::Diagnostic, _: F)
+ where
+ F: Fn(
+ &mut rustc_errors::Diagnostic,
+ rustc_errors::SubdiagnosticMessage,
+ ) -> rustc_errors::SubdiagnosticMessage,
+ {
+ diag.span_labels(self.0, "");
+ }
+}
+
+#[derive(Diagnostic)]
+#[diag(ast_passes_pattern_in_fn_pointer, code = "E0561")]
+pub struct PatternFnPointer {
+ #[primary_span]
+ pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(ast_passes_trait_object_single_bound, code = "E0226")]
+pub struct TraitObjectBound {
+ #[primary_span]
+ pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(ast_passes_impl_trait_path, code = "E0667")]
+pub struct ImplTraitPath {
+ #[primary_span]
+ pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(ast_passes_nested_impl_trait, code = "E0666")]
+pub struct NestedImplTrait {
+ #[primary_span]
+ pub span: Span,
+ #[label(ast_passes_outer)]
+ pub outer: Span,
+ #[label(ast_passes_inner)]
+ pub inner: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(ast_passes_at_least_one_trait)]
+pub struct AtLeastOneTrait {
+ #[primary_span]
+ pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(ast_passes_out_of_order_params)]
+pub struct OutOfOrderParams<'a> {
+ #[primary_span]
+ pub spans: Vec<Span>,
+ #[suggestion(code = "{ordered_params}", applicability = "machine-applicable")]
+ pub sugg_span: Span,
+ pub param_ord: &'a ParamKindOrd,
+ pub max_param: &'a ParamKindOrd,
+ pub ordered_params: &'a str,
+}
+
+#[derive(Diagnostic)]
+#[diag(ast_passes_obsolete_auto)]
+#[help]
+pub struct ObsoleteAuto {
+ #[primary_span]
+ pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(ast_passes_unsafe_negative_impl, code = "E0198")]
+pub struct UnsafeNegativeImpl {
+ #[primary_span]
+ pub span: Span,
+ #[label(ast_passes_negative)]
+ pub negative: Span,
+ #[label(ast_passes_unsafe)]
+ pub r#unsafe: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(ast_passes_inherent_cannot_be)]
+pub struct InherentImplCannot<'a> {
+ #[primary_span]
+ pub span: Span,
+ #[label(ast_passes_because)]
+ pub annotation_span: Span,
+ pub annotation: &'a str,
+ #[label(ast_passes_type)]
+ pub self_ty: Span,
+ #[note(ast_passes_only_trait)]
+ pub only_trait: Option<()>,
+}
+
+#[derive(Diagnostic)]
+#[diag(ast_passes_inherent_cannot_be, code = "E0197")]
+pub struct InherentImplCannotUnsafe<'a> {
+ #[primary_span]
+ pub span: Span,
+ #[label(ast_passes_because)]
+ pub annotation_span: Span,
+ pub annotation: &'a str,
+ #[label(ast_passes_type)]
+ pub self_ty: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(ast_passes_unsafe_item)]
+pub struct UnsafeItem {
+ #[primary_span]
+ pub span: Span,
+ pub kind: &'static str,
+}
+
+#[derive(Diagnostic)]
+#[diag(ast_passes_fieldless_union)]
+pub struct FieldlessUnion {
+ #[primary_span]
+ pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(ast_passes_where_after_type_alias)]
+#[note]
+pub struct WhereAfterTypeAlias {
+ #[primary_span]
+ pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(ast_passes_generic_default_trailing)]
+pub struct GenericDefaultTrailing {
+ #[primary_span]
+ pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(ast_passes_nested_lifetimes, code = "E0316")]
+pub struct NestedLifetimes {
+ #[primary_span]
+ pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(ast_passes_optional_trait_supertrait)]
+#[note]
+pub struct OptionalTraitSupertrait {
+ #[primary_span]
+ pub span: Span,
+ pub path_str: String,
+}
+
+#[derive(Diagnostic)]
+#[diag(ast_passes_optional_trait_object)]
+pub struct OptionalTraitObject {
+ #[primary_span]
+ pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(ast_passes_tilde_const_disallowed)]
+pub struct TildeConstDisallowed {
+ #[primary_span]
+ pub span: Span,
+ #[subdiagnostic]
+ pub reason: TildeConstReason,
+}
+
+#[derive(Subdiagnostic)]
+pub enum TildeConstReason {
+ #[note(ast_passes_trait)]
+ TraitObject,
+ #[note(ast_passes_closure)]
+ Closure,
+ #[note(ast_passes_function)]
+ Function {
+ #[primary_span]
+ ident: Span,
+ },
+}
+
+#[derive(Diagnostic)]
+#[diag(ast_passes_optional_const_exclusive)]
+pub struct OptionalConstExclusive {
+ #[primary_span]
+ pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(ast_passes_const_and_async)]
+pub struct ConstAndAsync {
+ #[primary_span]
+ pub spans: Vec<Span>,
+ #[label(ast_passes_const)]
+ pub cspan: Span,
+ #[label(ast_passes_async)]
+ pub aspan: Span,
+ #[label]
+ pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(ast_passes_pattern_in_foreign, code = "E0130")]
+pub struct PatternInForeign {
+ #[primary_span]
+ #[label]
+ pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(ast_passes_pattern_in_bodiless, code = "E0642")]
+pub struct PatternInBodiless {
+ #[primary_span]
+ #[label]
+ pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(ast_passes_equality_in_where)]
+#[note]
+pub struct EqualityInWhere {
+ #[primary_span]
+ #[label]
+ pub span: Span,
+ #[subdiagnostic]
+ pub assoc: Option<AssociatedSuggestion>,
+ #[subdiagnostic]
+ pub assoc2: Option<AssociatedSuggestion2>,
+}
+
+#[derive(Subdiagnostic)]
+#[suggestion(
+ ast_passes_suggestion,
+ code = "{param}: {path}",
+ style = "verbose",
+ applicability = "maybe-incorrect"
+)]
+pub struct AssociatedSuggestion {
+ #[primary_span]
+ pub span: Span,
+ pub ident: Ident,
+ pub param: Ident,
+ pub path: String,
+}
+
+#[derive(Subdiagnostic)]
+#[multipart_suggestion(ast_passes_suggestion_path, applicability = "maybe-incorrect")]
+pub struct AssociatedSuggestion2 {
+ #[suggestion_part(code = "{args}")]
+ pub span: Span,
+ pub args: String,
+ #[suggestion_part(code = "")]
+ pub predicate: Span,
+ pub trait_segment: Ident,
+ pub potential_assoc: Ident,
+}
+
+#[derive(Diagnostic)]
+#[diag(ast_passes_stability_outside_std, code = "E0734")]
+pub struct StabilityOutsideStd {
+ #[primary_span]
+ pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(ast_passes_feature_on_non_nightly, code = "E0554")]
+pub struct FeatureOnNonNightly {
+ #[primary_span]
+ pub span: Span,
+ pub channel: &'static str,
+ #[subdiagnostic]
+ pub stable_features: Vec<StableFeature>,
+ #[suggestion(code = "", applicability = "machine-applicable")]
+ pub sugg: Option<Span>,
+}
+
+pub struct StableFeature {
+ pub name: Symbol,
+ pub since: Symbol,
+}
+
+impl AddToDiagnostic for StableFeature {
+ fn add_to_diagnostic_with<F>(self, diag: &mut rustc_errors::Diagnostic, _: F)
+ where
+ F: Fn(
+ &mut rustc_errors::Diagnostic,
+ rustc_errors::SubdiagnosticMessage,
+ ) -> rustc_errors::SubdiagnosticMessage,
+ {
+ diag.set_arg("name", self.name);
+ diag.set_arg("since", self.since);
+ diag.help(fluent::ast_passes_stable_since);
+ }
+}
+
+#[derive(Diagnostic)]
+#[diag(ast_passes_incompatbile_features)]
+#[help]
+pub struct IncompatibleFeatures {
+ #[primary_span]
+ pub spans: Vec<Span>,
+ pub f1: Symbol,
+ pub f2: Symbol,
+}
+
+#[derive(Diagnostic)]
+#[diag(ast_passes_show_span)]
+pub struct ShowSpan {
+ #[primary_span]
+ pub span: Span,
+ pub msg: &'static str,
+}
diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs
index 89ba6f936..96042ea30 100644
--- a/compiler/rustc_ast_passes/src/feature_gate.rs
+++ b/compiler/rustc_ast_passes/src/feature_gate.rs
@@ -2,7 +2,7 @@ use rustc_ast as ast;
use rustc_ast::visit::{self, AssocCtxt, FnCtxt, FnKind, Visitor};
use rustc_ast::{AssocConstraint, AssocConstraintKind, NodeId};
use rustc_ast::{PatKind, RangeEnd};
-use rustc_errors::{struct_span_err, Applicability, StashKey};
+use rustc_errors::{Applicability, StashKey};
use rustc_feature::{AttributeGate, BuiltinAttribute, Features, GateIssue, BUILTIN_ATTRIBUTE_MAP};
use rustc_session::parse::{feature_err, feature_err_issue, feature_warn};
use rustc_session::Session;
@@ -10,6 +10,10 @@ use rustc_span::source_map::Spanned;
use rustc_span::symbol::sym;
use rustc_span::Span;
use rustc_target::spec::abi;
+use thin_vec::ThinVec;
+use tracing::debug;
+
+use crate::errors;
macro_rules! gate_feature_fn {
($visitor: expr, $has_feature: expr, $span: expr, $name: expr, $explain: expr, $help: expr) => {{
@@ -136,6 +140,34 @@ impl<'a> PostExpansionVisitor<'a> {
}
ImplTraitVisitor { vis: self }.visit_ty(ty);
}
+
+ fn check_late_bound_lifetime_defs(&self, params: &[ast::GenericParam]) {
+ // Check only lifetime parameters are present and that the lifetime
+ // parameters that are present have no bounds.
+ let non_lt_param_spans: Vec<_> = params
+ .iter()
+ .filter_map(|param| match param.kind {
+ ast::GenericParamKind::Lifetime { .. } => None,
+ _ => Some(param.ident.span),
+ })
+ .collect();
+ // FIXME: gate_feature_post doesn't really handle multispans...
+ if !non_lt_param_spans.is_empty() && !self.features.non_lifetime_binders {
+ feature_err(
+ &self.sess.parse_sess,
+ sym::non_lifetime_binders,
+ non_lt_param_spans,
+ crate::fluent_generated::ast_passes_forbidden_non_lifetime_param,
+ )
+ .emit();
+ }
+ for param in params {
+ if !param.bounds.is_empty() {
+ let spans: Vec<_> = param.bounds.iter().map(|b| b.span()).collect();
+ self.sess.emit_err(errors::ForbiddenLifetimeBound { spans });
+ }
+ }
+ }
}
impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
@@ -147,7 +179,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
..
}) = attr_info
{
- gate_feature_fn!(self, has_feature, attr.span, *name, descr);
+ gate_feature_fn!(self, has_feature, attr.span, *name, *descr);
}
// Check unstable flavors of the `#[doc]` attribute.
if attr.has_name(sym::doc) {
@@ -186,13 +218,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
|| attr.has_name(sym::rustc_const_stable)
|| attr.has_name(sym::rustc_default_body_unstable)
{
- struct_span_err!(
- self.sess,
- attr.span,
- E0734,
- "stability attributes may not be used outside of the standard library",
- )
- .emit();
+ self.sess.emit_err(errors::StabilityOutsideStd { span: attr.span });
}
}
}
@@ -220,7 +246,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
ast::ItemKind::Struct(..) => {
for attr in self.sess.filter_by_name(&i.attrs, sym::repr) {
- for item in attr.meta_item_list().unwrap_or_else(Vec::new) {
+ for item in attr.meta_item_list().unwrap_or_else(ThinVec::new) {
if item.has_name(sym::simd) {
gate_feature_post!(
&self,
@@ -306,6 +332,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
ast::TyKind::BareFn(bare_fn_ty) => {
// Function pointers cannot be `const`
self.check_extern(bare_fn_ty.ext, ast::Const::No);
+ self.check_late_bound_lifetime_defs(&bare_fn_ty.generic_params);
}
ast::TyKind::Never => {
gate_feature_post!(&self, never_type, ty.span, "the `!` type is experimental");
@@ -318,6 +345,19 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
visit::walk_ty(self, ty)
}
+ fn visit_generics(&mut self, g: &'a ast::Generics) {
+ for predicate in &g.where_clause.predicates {
+ match predicate {
+ ast::WherePredicate::BoundPredicate(bound_pred) => {
+ // A type binding, eg `for<'c> Foo: Send+Clone+'c`
+ self.check_late_bound_lifetime_defs(&bound_pred.bound_generic_params);
+ }
+ _ => {}
+ }
+ }
+ visit::walk_generics(self, g);
+ }
+
fn visit_fn_ret_ty(&mut self, ret_ty: &'a ast::FnRetTy) {
if let ast::FnRetTy::Ty(output_ty) = ret_ty {
if let ast::TyKind::Never = output_ty.kind {
@@ -346,7 +386,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
).span_suggestion_verbose(
lhs.span.shrink_to_lo(),
"you might have meant to introduce a new binding",
- "let ".to_string(),
+ "let ",
Applicability::MachineApplicable,
).emit();
}
@@ -437,12 +477,21 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
visit::walk_pat(self, pattern)
}
+ fn visit_poly_trait_ref(&mut self, t: &'a ast::PolyTraitRef) {
+ self.check_late_bound_lifetime_defs(&t.bound_generic_params);
+ visit::walk_poly_trait_ref(self, t);
+ }
+
fn visit_fn(&mut self, fn_kind: FnKind<'a>, span: Span, _: NodeId) {
if let Some(header) = fn_kind.header() {
// Stability of const fn methods are covered in `visit_assoc_item` below.
self.check_extern(header.ext, header.constness);
}
+ if let FnKind::Closure(ast::ClosureBinder::For { generic_params, .. }, ..) = fn_kind {
+ self.check_late_bound_lifetime_defs(generic_params);
+ }
+
if fn_kind.ctxt() != Some(FnCtxt::Foreign) && fn_kind.decl().c_variadic() {
gate_feature_post!(&self, c_variadic, span, "C-variadic functions are unstable");
}
@@ -580,13 +629,13 @@ fn maybe_stage_features(sess: &Session, krate: &ast::Crate) {
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,
- attr.span,
- E0554,
- "`#![feature]` may not be used on the {} release channel",
- option_env!("CFG_RELEASE_CHANNEL").unwrap_or("(unknown)")
- );
+ let mut err = errors::FeatureOnNonNightly {
+ span: attr.span,
+ channel: option_env!("CFG_RELEASE_CHANNEL").unwrap_or("(unknown)"),
+ stable_features: vec![],
+ sugg: None,
+ };
+
let mut all_stable = true;
for ident in
attr.meta_item_list().into_iter().flatten().flat_map(|nested| nested.ident())
@@ -597,24 +646,15 @@ fn maybe_stage_features(sess: &Session, krate: &ast::Crate) {
.flat_map(|&(feature, _, since)| if feature == name { since } else { None })
.next();
if let Some(since) = stable_since {
- err.help(&format!(
- "the feature `{}` has been stable since {} and no longer requires \
- an attribute to enable",
- name, since
- ));
+ err.stable_features.push(errors::StableFeature { name, since });
} else {
all_stable = false;
}
}
if all_stable {
- err.span_suggestion(
- attr.span,
- "remove the attribute",
- "",
- Applicability::MachineApplicable,
- );
+ err.sugg = Some(attr.span);
}
- err.emit();
+ sess.parse_sess.span_diagnostic.emit_err(err);
}
}
}
@@ -637,16 +677,7 @@ fn check_incompatible_features(sess: &Session) {
if let Some((f2_name, f2_span)) = declared_features.clone().find(|(name, _)| name == f2)
{
let spans = vec![f1_span, f2_span];
- sess.struct_span_err(
- spans,
- &format!(
- "features `{}` and `{}` are incompatible, using them at the same time \
- is not allowed",
- f1_name, f2_name
- ),
- )
- .help("remove one of these features")
- .emit();
+ sess.emit_err(errors::IncompatibleFeatures { spans, f1: f1_name, f2: f2_name });
}
}
}
diff --git a/compiler/rustc_ast_passes/src/lib.rs b/compiler/rustc_ast_passes/src/lib.rs
index f58fffc91..b9dcaee23 100644
--- a/compiler/rustc_ast_passes/src/lib.rs
+++ b/compiler/rustc_ast_passes/src/lib.rs
@@ -10,12 +10,16 @@
#![feature(iter_is_partitioned)]
#![feature(let_chains)]
#![recursion_limit = "256"]
+#![deny(rustc::untranslatable_diagnostic)]
+#![deny(rustc::diagnostic_outside_of_impl)]
-#[macro_use]
-extern crate tracing;
+use rustc_errors::{DiagnosticMessage, SubdiagnosticMessage};
+use rustc_macros::fluent_messages;
pub mod ast_validation;
mod errors;
pub mod feature_gate;
pub mod node_count;
pub mod show_span;
+
+fluent_messages! { "../locales/en-US.ftl" }
diff --git a/compiler/rustc_ast_passes/src/show_span.rs b/compiler/rustc_ast_passes/src/show_span.rs
index 27637e311..280cf3284 100644
--- a/compiler/rustc_ast_passes/src/show_span.rs
+++ b/compiler/rustc_ast_passes/src/show_span.rs
@@ -9,6 +9,8 @@ use rustc_ast as ast;
use rustc_ast::visit;
use rustc_ast::visit::Visitor;
+use crate::errors;
+
enum Mode {
Expression,
Pattern,
@@ -36,21 +38,21 @@ struct ShowSpanVisitor<'a> {
impl<'a> Visitor<'a> for ShowSpanVisitor<'a> {
fn visit_expr(&mut self, e: &'a ast::Expr) {
if let Mode::Expression = self.mode {
- self.span_diagnostic.span_warn(e.span, "expression");
+ self.span_diagnostic.emit_warning(errors::ShowSpan { span: e.span, msg: "expression" });
}
visit::walk_expr(self, e);
}
fn visit_pat(&mut self, p: &'a ast::Pat) {
if let Mode::Pattern = self.mode {
- self.span_diagnostic.span_warn(p.span, "pattern");
+ self.span_diagnostic.emit_warning(errors::ShowSpan { span: p.span, msg: "pattern" });
}
visit::walk_pat(self, p);
}
fn visit_ty(&mut self, t: &'a ast::Ty) {
if let Mode::Type = self.mode {
- self.span_diagnostic.span_warn(t.span, "type");
+ self.span_diagnostic.emit_warning(errors::ShowSpan { span: t.span, msg: "type" });
}
visit::walk_ty(self, t);
}
diff --git a/compiler/rustc_ast_pretty/Cargo.toml b/compiler/rustc_ast_pretty/Cargo.toml
index a3e3e823b..980a8fa93 100644
--- a/compiler/rustc_ast_pretty/Cargo.toml
+++ b/compiler/rustc_ast_pretty/Cargo.toml
@@ -6,5 +6,6 @@ edition = "2021"
[lib]
[dependencies]
-rustc_span = { path = "../rustc_span" }
rustc_ast = { path = "../rustc_ast" }
+rustc_span = { path = "../rustc_span" }
+thin-vec = "0.2.12"
diff --git a/compiler/rustc_ast_pretty/src/pprust/state.rs b/compiler/rustc_ast_pretty/src/pprust/state.rs
index 6a8064b0e..694d688bf 100644
--- a/compiler/rustc_ast_pretty/src/pprust/state.rs
+++ b/compiler/rustc_ast_pretty/src/pprust/state.rs
@@ -4,7 +4,7 @@ mod item;
use crate::pp::Breaks::{Consistent, Inconsistent};
use crate::pp::{self, Breaks};
-
+use rustc_ast::attr::AttrIdGenerator;
use rustc_ast::ptr::P;
use rustc_ast::token::{self, BinOpToken, CommentKind, Delimiter, Nonterminal, Token, TokenKind};
use rustc_ast::tokenstream::{TokenStream, TokenTree};
@@ -20,9 +20,8 @@ use rustc_span::edition::Edition;
use rustc_span::source_map::{SourceMap, Spanned};
use rustc_span::symbol::{kw, sym, Ident, IdentPrinter, Symbol};
use rustc_span::{BytePos, FileName, Span, DUMMY_SP};
-
-use rustc_ast::attr::AttrIdGenerator;
use std::borrow::Cow;
+use thin_vec::ThinVec;
pub use self::delimited::IterDelimited;
@@ -131,7 +130,7 @@ pub fn print_crate<'a>(
// Currently, in Rust 2018 we don't have `extern crate std;` at the crate
// root, so this is not needed, and actually breaks things.
- if edition == Edition::Edition2015 {
+ if edition.is_rust_2015() {
// `#![no_std]`
let fake_attr = attr::mk_attr_word(g, ast::AttrStyle::Inner, sym::no_std, DUMMY_SP);
s.print_attribute(&fake_attr);
@@ -1567,8 +1566,18 @@ impl<'a> State<'a> {
match bound {
GenericBound::Trait(tref, modifier) => {
- if modifier == &TraitBoundModifier::Maybe {
- self.word("?");
+ match modifier {
+ TraitBoundModifier::None => {}
+ TraitBoundModifier::Maybe => {
+ self.word("?");
+ }
+ TraitBoundModifier::MaybeConst => {
+ self.word_space("~const");
+ }
+ TraitBoundModifier::MaybeConstMaybe => {
+ self.word_space("~const");
+ self.word("?");
+ }
}
self.print_poly_trait_ref(tref);
}
@@ -1712,10 +1721,10 @@ impl<'a> State<'a> {
self.ibox(INDENT_UNIT);
self.print_formal_generic_params(generic_params);
let generics = ast::Generics {
- params: Vec::new(),
+ params: ThinVec::new(),
where_clause: ast::WhereClause {
has_where_token: false,
- predicates: Vec::new(),
+ predicates: ThinVec::new(),
span: DUMMY_SP,
},
span: DUMMY_SP,
diff --git a/compiler/rustc_ast_pretty/src/pprust/state/expr.rs b/compiler/rustc_ast_pretty/src/pprust/state/expr.rs
index 2a18e5164..cacfe9eb2 100644
--- a/compiler/rustc_ast_pretty/src/pprust/state/expr.rs
+++ b/compiler/rustc_ast_pretty/src/pprust/state/expr.rs
@@ -6,6 +6,11 @@ use rustc_ast::token;
use rustc_ast::util::literal::escape_byte_str_symbol;
use rustc_ast::util::parser::{self, AssocOp, Fixity};
use rustc_ast::{self as ast, BlockCheckMode};
+use rustc_ast::{
+ FormatAlignment, FormatArgPosition, FormatArgsPiece, FormatCount, FormatDebugHex, FormatSign,
+ FormatTrait,
+};
+use std::fmt::Write;
impl<'a> State<'a> {
fn print_else(&mut self, els: Option<&ast::Expr>) {
@@ -527,9 +532,23 @@ impl<'a> State<'a> {
}
}
ast::ExprKind::InlineAsm(a) => {
+ // FIXME: This should have its own syntax, distinct from a macro invocation.
self.word("asm!");
self.print_inline_asm(a);
}
+ ast::ExprKind::FormatArgs(fmt) => {
+ // FIXME: This should have its own syntax, distinct from a macro invocation.
+ self.word("format_args!");
+ self.popen();
+ self.rbox(0, Inconsistent);
+ self.word(reconstruct_format_args_template_string(&fmt.template));
+ for arg in fmt.arguments.all_args() {
+ self.word_space(",");
+ self.print_expr(&arg.expr);
+ }
+ self.end();
+ self.pclose();
+ }
ast::ExprKind::MacCall(m) => self.print_mac(m),
ast::ExprKind::Paren(e) => {
self.popen();
@@ -629,3 +648,88 @@ impl<'a> State<'a> {
}
}
}
+
+pub fn reconstruct_format_args_template_string(pieces: &[FormatArgsPiece]) -> String {
+ let mut template = "\"".to_string();
+ for piece in pieces {
+ match piece {
+ FormatArgsPiece::Literal(s) => {
+ for c in s.as_str().escape_debug() {
+ template.push(c);
+ if let '{' | '}' = c {
+ template.push(c);
+ }
+ }
+ }
+ FormatArgsPiece::Placeholder(p) => {
+ template.push('{');
+ let (Ok(n) | Err(n)) = p.argument.index;
+ write!(template, "{n}").unwrap();
+ if p.format_options != Default::default() || p.format_trait != FormatTrait::Display
+ {
+ template.push_str(":");
+ }
+ if let Some(fill) = p.format_options.fill {
+ template.push(fill);
+ }
+ match p.format_options.alignment {
+ Some(FormatAlignment::Left) => template.push_str("<"),
+ Some(FormatAlignment::Right) => template.push_str(">"),
+ Some(FormatAlignment::Center) => template.push_str("^"),
+ None => {}
+ }
+ match p.format_options.sign {
+ Some(FormatSign::Plus) => template.push('+'),
+ Some(FormatSign::Minus) => template.push('-'),
+ None => {}
+ }
+ if p.format_options.alternate {
+ template.push('#');
+ }
+ if p.format_options.zero_pad {
+ template.push('0');
+ }
+ if let Some(width) = &p.format_options.width {
+ match width {
+ FormatCount::Literal(n) => write!(template, "{n}").unwrap(),
+ FormatCount::Argument(FormatArgPosition {
+ index: Ok(n) | Err(n), ..
+ }) => {
+ write!(template, "{n}$").unwrap();
+ }
+ }
+ }
+ if let Some(precision) = &p.format_options.precision {
+ template.push('.');
+ match precision {
+ FormatCount::Literal(n) => write!(template, "{n}").unwrap(),
+ FormatCount::Argument(FormatArgPosition {
+ index: Ok(n) | Err(n), ..
+ }) => {
+ write!(template, "{n}$").unwrap();
+ }
+ }
+ }
+ match p.format_options.debug_hex {
+ Some(FormatDebugHex::Lower) => template.push('x'),
+ Some(FormatDebugHex::Upper) => template.push('X'),
+ None => {}
+ }
+ template.push_str(match p.format_trait {
+ FormatTrait::Display => "",
+ FormatTrait::Debug => "?",
+ FormatTrait::LowerExp => "e",
+ FormatTrait::UpperExp => "E",
+ FormatTrait::Octal => "o",
+ FormatTrait::Pointer => "p",
+ FormatTrait::Binary => "b",
+ FormatTrait::LowerHex => "x",
+ FormatTrait::UpperHex => "X",
+ });
+ template.push('}');
+ }
+ }
+ }
+ template.push('"');
+ template
+}
diff --git a/compiler/rustc_ast_pretty/src/pprust/tests.rs b/compiler/rustc_ast_pretty/src/pprust/tests.rs
index 6c8d42f33..3b2b60a86 100644
--- a/compiler/rustc_ast_pretty/src/pprust/tests.rs
+++ b/compiler/rustc_ast_pretty/src/pprust/tests.rs
@@ -3,6 +3,7 @@ use super::*;
use rustc_ast as ast;
use rustc_span::create_default_session_globals_then;
use rustc_span::symbol::Ident;
+use thin_vec::ThinVec;
fn fun_to_string(
decl: &ast::FnDecl,
@@ -27,8 +28,10 @@ fn test_fun_to_string() {
create_default_session_globals_then(|| {
let abba_ident = Ident::from_str("abba");
- let decl =
- ast::FnDecl { inputs: Vec::new(), output: ast::FnRetTy::Default(rustc_span::DUMMY_SP) };
+ let decl = ast::FnDecl {
+ inputs: ThinVec::new(),
+ output: ast::FnRetTy::Default(rustc_span::DUMMY_SP),
+ };
let generics = ast::Generics::default();
assert_eq!(
fun_to_string(&decl, ast::FnHeader::default(), abba_ident, &generics),
diff --git a/compiler/rustc_error_messages/locales/en-US/attr.ftl b/compiler/rustc_attr/locales/en-US.ftl
index a7f8c993d..a7f8c993d 100644
--- a/compiler/rustc_error_messages/locales/en-US/attr.ftl
+++ b/compiler/rustc_attr/locales/en-US.ftl
diff --git a/compiler/rustc_attr/src/builtin.rs b/compiler/rustc_attr/src/builtin.rs
index 40531c1c1..3d240108b 100644
--- a/compiler/rustc_attr/src/builtin.rs
+++ b/compiler/rustc_attr/src/builtin.rs
@@ -731,7 +731,7 @@ pub fn eval_condition(
sess,
sym::cfg_target_compact,
cfg.span,
- &"compact `cfg(target(..))` is experimental and subject to change"
+ "compact `cfg(target(..))` is experimental and subject to change"
).emit();
}
diff --git a/compiler/rustc_attr/src/lib.rs b/compiler/rustc_attr/src/lib.rs
index 4580ffcc6..5fede0a58 100644
--- a/compiler/rustc_attr/src/lib.rs
+++ b/compiler/rustc_attr/src/lib.rs
@@ -11,6 +11,9 @@
#[macro_use]
extern crate rustc_macros;
+use rustc_errors::{DiagnosticMessage, SubdiagnosticMessage};
+use rustc_macros::fluent_messages;
+
mod builtin;
mod session_diagnostics;
@@ -22,3 +25,5 @@ pub use StabilityLevel::*;
pub use rustc_ast::attr::*;
pub(crate) use rustc_ast::HashStableContext;
+
+fluent_messages! { "../locales/en-US.ftl" }
diff --git a/compiler/rustc_attr/src/session_diagnostics.rs b/compiler/rustc_attr/src/session_diagnostics.rs
index 3ba7a3c53..ee79545e3 100644
--- a/compiler/rustc_attr/src/session_diagnostics.rs
+++ b/compiler/rustc_attr/src/session_diagnostics.rs
@@ -2,11 +2,12 @@ use std::num::IntErrorKind;
use rustc_ast as ast;
use rustc_errors::{
- error_code, fluent, Applicability, DiagnosticBuilder, ErrorGuaranteed, Handler, IntoDiagnostic,
+ error_code, Applicability, DiagnosticBuilder, ErrorGuaranteed, Handler, IntoDiagnostic,
};
use rustc_macros::Diagnostic;
use rustc_span::{Span, Symbol};
+use crate::fluent_generated as fluent;
use crate::UnsupportedLiteralReason;
#[derive(Diagnostic)]
@@ -59,7 +60,7 @@ impl<'a> IntoDiagnostic<'a> for UnknownMetaItem<'_> {
);
diag.set_arg("item", self.item);
diag.set_arg("expected", expected.join(", "));
- diag.span_label(self.span, fluent::label);
+ diag.span_label(self.span, fluent::attr_label);
diag
}
}
@@ -99,31 +100,31 @@ pub(crate) struct InvalidIssueString {
// translatable.
#[derive(Subdiagnostic)]
pub(crate) enum InvalidIssueStringCause {
- #[label(must_not_be_zero)]
+ #[label(attr_must_not_be_zero)]
MustNotBeZero {
#[primary_span]
span: Span,
},
- #[label(empty)]
+ #[label(attr_empty)]
Empty {
#[primary_span]
span: Span,
},
- #[label(invalid_digit)]
+ #[label(attr_invalid_digit)]
InvalidDigit {
#[primary_span]
span: Span,
},
- #[label(pos_overflow)]
+ #[label(attr_pos_overflow)]
PosOverflow {
#[primary_span]
span: Span,
},
- #[label(neg_overflow)]
+ #[label(attr_neg_overflow)]
NegOverflow {
#[primary_span]
span: Span,
@@ -275,7 +276,7 @@ pub(crate) struct IncorrectReprFormatGeneric<'a> {
#[derive(Subdiagnostic)]
pub(crate) enum IncorrectReprFormatGenericCause<'a> {
- #[suggestion(suggestion, code = "{name}({int})", applicability = "machine-applicable")]
+ #[suggestion(attr_suggestion, code = "{name}({int})", applicability = "machine-applicable")]
Int {
#[primary_span]
span: Span,
@@ -287,7 +288,7 @@ pub(crate) enum IncorrectReprFormatGenericCause<'a> {
int: u128,
},
- #[suggestion(suggestion, code = "{name}({symbol})", applicability = "machine-applicable")]
+ #[suggestion(attr_suggestion, code = "{name}({symbol})", applicability = "machine-applicable")]
Symbol {
#[primary_span]
span: Span,
diff --git a/compiler/rustc_baked_icu_data/Cargo.toml b/compiler/rustc_baked_icu_data/Cargo.toml
index 3477306db..184fea868 100644
--- a/compiler/rustc_baked_icu_data/Cargo.toml
+++ b/compiler/rustc_baked_icu_data/Cargo.toml
@@ -4,12 +4,11 @@ version = "0.0.0"
edition = "2021"
[dependencies]
-icu_list = "1.0.0"
-icu_locid = "1.0.0"
-icu_provider = "1.0.1"
-icu_provider_adapters = "1.0.0"
-litemap = "0.6.0"
-zerovec = "0.9.0"
+icu_list = "1.1.0"
+icu_locid = "1.1.0"
+icu_provider = "1.1.0"
+icu_provider_adapters = "1.1.0"
+zerovec = "0.9.2"
[features]
rustc_use_parallel_compiler = ['icu_provider/sync']
diff --git a/compiler/rustc_baked_icu_data/src/data/any.rs b/compiler/rustc_baked_icu_data/src/data/any.rs
index e8e99be93..230288766 100644
--- a/compiler/rustc_baked_icu_data/src/data/any.rs
+++ b/compiler/rustc_baked_icu_data/src/data/any.rs
@@ -1,42 +1,2 @@
// @generated
-impl AnyProvider for BakedDataProvider {
- fn load_any(&self, key: DataKey, req: DataRequest) -> Result<AnyResponse, DataError> {
- const ANDLISTV1MARKER: ::icu_provider::DataKeyHash =
- ::icu_list::provider::AndListV1Marker::KEY.hashed();
- const COLLATIONFALLBACKSUPPLEMENTV1MARKER: ::icu_provider::DataKeyHash =
- ::icu_provider_adapters::fallback::provider::CollationFallbackSupplementV1Marker::KEY
- .hashed();
- const LOCALEFALLBACKLIKELYSUBTAGSV1MARKER: ::icu_provider::DataKeyHash =
- ::icu_provider_adapters::fallback::provider::LocaleFallbackLikelySubtagsV1Marker::KEY
- .hashed();
- const LOCALEFALLBACKPARENTSV1MARKER: ::icu_provider::DataKeyHash =
- ::icu_provider_adapters::fallback::provider::LocaleFallbackParentsV1Marker::KEY
- .hashed();
- #[allow(clippy::match_single_binding)]
- match key.hashed() {
- ANDLISTV1MARKER => list::and_v1::DATA
- .get_by(|k| req.locale.strict_cmp(k.as_bytes()).reverse())
- .copied()
- .map(AnyPayload::from_static_ref)
- .ok_or(DataErrorKind::MissingLocale),
- COLLATIONFALLBACKSUPPLEMENTV1MARKER => fallback::supplement::co_v1::DATA
- .get_by(|k| req.locale.strict_cmp(k.as_bytes()).reverse())
- .copied()
- .map(AnyPayload::from_static_ref)
- .ok_or(DataErrorKind::MissingLocale),
- LOCALEFALLBACKLIKELYSUBTAGSV1MARKER => fallback::likelysubtags_v1::DATA
- .get_by(|k| req.locale.strict_cmp(k.as_bytes()).reverse())
- .copied()
- .map(AnyPayload::from_static_ref)
- .ok_or(DataErrorKind::MissingLocale),
- LOCALEFALLBACKPARENTSV1MARKER => fallback::parents_v1::DATA
- .get_by(|k| req.locale.strict_cmp(k.as_bytes()).reverse())
- .copied()
- .map(AnyPayload::from_static_ref)
- .ok_or(DataErrorKind::MissingLocale),
- _ => Err(DataErrorKind::MissingDataKey),
- }
- .map_err(|e| e.with_req(key, req))
- .map(|payload| AnyResponse { payload: Some(payload), metadata: Default::default() })
- }
-}
+impl_any_provider!(BakedDataProvider);
diff --git a/compiler/rustc_baked_icu_data/src/data/fallback/likelysubtags_v1.rs b/compiler/rustc_baked_icu_data/src/data/fallback/likelysubtags_v1.rs
deleted file mode 100644
index 0a90c832e..000000000
--- a/compiler/rustc_baked_icu_data/src/data/fallback/likelysubtags_v1.rs
+++ /dev/null
@@ -1,733 +0,0 @@
-// @generated
-type DataStruct = < :: icu_provider_adapters :: fallback :: provider :: LocaleFallbackLikelySubtagsV1Marker as :: icu_provider :: DataMarker > :: Yokeable ;
-pub static DATA: litemap::LiteMap<&str, &DataStruct, &[(&str, &DataStruct)]> =
- litemap::LiteMap::from_sorted_store_unchecked(&[("und", UND)]);
-static UND: &DataStruct =
- &::icu_provider_adapters::fallback::provider::LocaleFallbackLikelySubtagsV1 {
- l2s: unsafe {
- #[allow(unused_unsafe)]
- ::zerovec::ZeroMap::from_parts_unchecked(
- unsafe {
- ::zerovec::ZeroVec::from_bytes_unchecked(&[
- 97u8, 98u8, 0u8, 97u8, 98u8, 113u8, 97u8, 100u8, 112u8, 97u8, 100u8, 121u8,
- 97u8, 101u8, 0u8, 97u8, 101u8, 98u8, 97u8, 104u8, 111u8, 97u8, 106u8,
- 116u8, 97u8, 107u8, 107u8, 97u8, 108u8, 116u8, 97u8, 109u8, 0u8, 97u8,
- 112u8, 99u8, 97u8, 112u8, 100u8, 97u8, 114u8, 0u8, 97u8, 114u8, 99u8, 97u8,
- 114u8, 113u8, 97u8, 114u8, 115u8, 97u8, 114u8, 121u8, 97u8, 114u8, 122u8,
- 97u8, 115u8, 0u8, 97u8, 115u8, 101u8, 97u8, 118u8, 0u8, 97u8, 118u8, 108u8,
- 97u8, 119u8, 97u8, 98u8, 97u8, 0u8, 98u8, 97u8, 108u8, 98u8, 97u8, 112u8,
- 98u8, 97u8, 120u8, 98u8, 99u8, 113u8, 98u8, 101u8, 0u8, 98u8, 101u8, 106u8,
- 98u8, 102u8, 113u8, 98u8, 102u8, 116u8, 98u8, 102u8, 121u8, 98u8, 103u8,
- 0u8, 98u8, 103u8, 99u8, 98u8, 103u8, 110u8, 98u8, 103u8, 120u8, 98u8,
- 104u8, 98u8, 98u8, 104u8, 105u8, 98u8, 104u8, 111u8, 98u8, 106u8, 105u8,
- 98u8, 106u8, 106u8, 98u8, 108u8, 116u8, 98u8, 110u8, 0u8, 98u8, 111u8, 0u8,
- 98u8, 112u8, 121u8, 98u8, 113u8, 105u8, 98u8, 114u8, 97u8, 98u8, 114u8,
- 104u8, 98u8, 114u8, 120u8, 98u8, 115u8, 113u8, 98u8, 115u8, 116u8, 98u8,
- 116u8, 118u8, 98u8, 117u8, 97u8, 98u8, 121u8, 110u8, 99u8, 99u8, 112u8,
- 99u8, 101u8, 0u8, 99u8, 104u8, 109u8, 99u8, 104u8, 114u8, 99u8, 106u8,
- 97u8, 99u8, 106u8, 109u8, 99u8, 107u8, 98u8, 99u8, 109u8, 103u8, 99u8,
- 111u8, 112u8, 99u8, 114u8, 0u8, 99u8, 114u8, 104u8, 99u8, 114u8, 107u8,
- 99u8, 114u8, 108u8, 99u8, 115u8, 119u8, 99u8, 116u8, 100u8, 99u8, 117u8,
- 0u8, 99u8, 118u8, 0u8, 100u8, 97u8, 114u8, 100u8, 99u8, 99u8, 100u8, 103u8,
- 108u8, 100u8, 109u8, 102u8, 100u8, 111u8, 105u8, 100u8, 114u8, 104u8,
- 100u8, 114u8, 115u8, 100u8, 116u8, 121u8, 100u8, 118u8, 0u8, 100u8, 122u8,
- 0u8, 101u8, 103u8, 121u8, 101u8, 107u8, 121u8, 101u8, 108u8, 0u8, 101u8,
- 115u8, 103u8, 101u8, 116u8, 116u8, 102u8, 97u8, 0u8, 102u8, 105u8, 97u8,
- 102u8, 117u8, 98u8, 103u8, 97u8, 110u8, 103u8, 98u8, 109u8, 103u8, 98u8,
- 122u8, 103u8, 101u8, 122u8, 103u8, 103u8, 110u8, 103u8, 106u8, 107u8,
- 103u8, 106u8, 117u8, 103u8, 108u8, 107u8, 103u8, 109u8, 118u8, 103u8,
- 111u8, 102u8, 103u8, 111u8, 109u8, 103u8, 111u8, 110u8, 103u8, 111u8,
- 116u8, 103u8, 114u8, 99u8, 103u8, 114u8, 116u8, 103u8, 117u8, 0u8, 103u8,
- 118u8, 114u8, 103u8, 119u8, 99u8, 103u8, 119u8, 116u8, 104u8, 97u8, 107u8,
- 104u8, 97u8, 122u8, 104u8, 100u8, 121u8, 104u8, 101u8, 0u8, 104u8, 105u8,
- 0u8, 104u8, 108u8, 117u8, 104u8, 109u8, 100u8, 104u8, 110u8, 100u8, 104u8,
- 110u8, 101u8, 104u8, 110u8, 106u8, 104u8, 110u8, 111u8, 104u8, 111u8, 99u8,
- 104u8, 111u8, 106u8, 104u8, 115u8, 110u8, 104u8, 121u8, 0u8, 105u8, 105u8,
- 0u8, 105u8, 110u8, 104u8, 105u8, 117u8, 0u8, 105u8, 119u8, 0u8, 106u8,
- 97u8, 0u8, 106u8, 105u8, 0u8, 106u8, 109u8, 108u8, 107u8, 97u8, 0u8, 107u8,
- 97u8, 97u8, 107u8, 97u8, 119u8, 107u8, 98u8, 100u8, 107u8, 98u8, 121u8,
- 107u8, 100u8, 116u8, 107u8, 102u8, 114u8, 107u8, 102u8, 121u8, 107u8,
- 104u8, 98u8, 107u8, 104u8, 110u8, 107u8, 104u8, 116u8, 107u8, 104u8, 119u8,
- 107u8, 106u8, 103u8, 107u8, 107u8, 0u8, 107u8, 109u8, 0u8, 107u8, 110u8,
- 0u8, 107u8, 111u8, 0u8, 107u8, 111u8, 105u8, 107u8, 111u8, 107u8, 107u8,
- 113u8, 121u8, 107u8, 114u8, 99u8, 107u8, 114u8, 117u8, 107u8, 115u8, 0u8,
- 107u8, 116u8, 98u8, 107u8, 117u8, 109u8, 107u8, 118u8, 0u8, 107u8, 118u8,
- 120u8, 107u8, 120u8, 99u8, 107u8, 120u8, 108u8, 107u8, 120u8, 109u8, 107u8,
- 120u8, 112u8, 107u8, 121u8, 0u8, 107u8, 122u8, 104u8, 108u8, 97u8, 98u8,
- 108u8, 97u8, 100u8, 108u8, 97u8, 104u8, 108u8, 98u8, 101u8, 108u8, 99u8,
- 112u8, 108u8, 101u8, 112u8, 108u8, 101u8, 122u8, 108u8, 105u8, 102u8,
- 108u8, 105u8, 115u8, 108u8, 107u8, 105u8, 108u8, 109u8, 110u8, 108u8,
- 111u8, 0u8, 108u8, 114u8, 99u8, 108u8, 117u8, 122u8, 108u8, 119u8, 108u8,
- 108u8, 122u8, 104u8, 109u8, 97u8, 103u8, 109u8, 97u8, 105u8, 109u8, 100u8,
- 101u8, 109u8, 100u8, 102u8, 109u8, 100u8, 120u8, 109u8, 102u8, 97u8, 109u8,
- 103u8, 112u8, 109u8, 107u8, 0u8, 109u8, 107u8, 105u8, 109u8, 108u8, 0u8,
- 109u8, 110u8, 0u8, 109u8, 110u8, 105u8, 109u8, 110u8, 119u8, 109u8, 114u8,
- 0u8, 109u8, 114u8, 100u8, 109u8, 114u8, 106u8, 109u8, 114u8, 111u8, 109u8,
- 116u8, 114u8, 109u8, 118u8, 121u8, 109u8, 119u8, 114u8, 109u8, 119u8,
- 119u8, 109u8, 121u8, 0u8, 109u8, 121u8, 109u8, 109u8, 121u8, 118u8, 109u8,
- 121u8, 122u8, 109u8, 122u8, 110u8, 110u8, 97u8, 110u8, 110u8, 101u8, 0u8,
- 110u8, 101u8, 119u8, 110u8, 110u8, 112u8, 110u8, 111u8, 100u8, 110u8,
- 111u8, 101u8, 110u8, 111u8, 110u8, 110u8, 113u8, 111u8, 110u8, 115u8,
- 107u8, 110u8, 115u8, 116u8, 111u8, 106u8, 0u8, 111u8, 106u8, 115u8, 111u8,
- 114u8, 0u8, 111u8, 114u8, 117u8, 111u8, 115u8, 0u8, 111u8, 115u8, 97u8,
- 111u8, 116u8, 97u8, 111u8, 116u8, 107u8, 111u8, 117u8, 105u8, 112u8, 97u8,
- 0u8, 112u8, 97u8, 108u8, 112u8, 101u8, 111u8, 112u8, 104u8, 108u8, 112u8,
- 104u8, 110u8, 112u8, 107u8, 97u8, 112u8, 110u8, 116u8, 112u8, 112u8, 97u8,
- 112u8, 114u8, 97u8, 112u8, 114u8, 100u8, 112u8, 115u8, 0u8, 114u8, 97u8,
- 106u8, 114u8, 104u8, 103u8, 114u8, 105u8, 102u8, 114u8, 106u8, 115u8,
- 114u8, 107u8, 116u8, 114u8, 109u8, 116u8, 114u8, 117u8, 0u8, 114u8, 117u8,
- 101u8, 114u8, 121u8, 117u8, 115u8, 97u8, 0u8, 115u8, 97u8, 104u8, 115u8,
- 97u8, 116u8, 115u8, 97u8, 122u8, 115u8, 99u8, 107u8, 115u8, 99u8, 108u8,
- 115u8, 100u8, 0u8, 115u8, 100u8, 104u8, 115u8, 103u8, 97u8, 115u8, 103u8,
- 119u8, 115u8, 104u8, 105u8, 115u8, 104u8, 110u8, 115u8, 104u8, 117u8,
- 115u8, 105u8, 0u8, 115u8, 107u8, 114u8, 115u8, 109u8, 112u8, 115u8, 111u8,
- 103u8, 115u8, 111u8, 117u8, 115u8, 114u8, 0u8, 115u8, 114u8, 98u8, 115u8,
- 114u8, 120u8, 115u8, 119u8, 98u8, 115u8, 119u8, 118u8, 115u8, 121u8, 108u8,
- 115u8, 121u8, 114u8, 116u8, 97u8, 0u8, 116u8, 97u8, 106u8, 116u8, 99u8,
- 121u8, 116u8, 100u8, 100u8, 116u8, 100u8, 103u8, 116u8, 100u8, 104u8,
- 116u8, 101u8, 0u8, 116u8, 103u8, 0u8, 116u8, 104u8, 0u8, 116u8, 104u8,
- 108u8, 116u8, 104u8, 113u8, 116u8, 104u8, 114u8, 116u8, 105u8, 0u8, 116u8,
- 105u8, 103u8, 116u8, 107u8, 116u8, 116u8, 114u8, 119u8, 116u8, 115u8,
- 100u8, 116u8, 115u8, 102u8, 116u8, 115u8, 106u8, 116u8, 116u8, 0u8, 116u8,
- 116u8, 115u8, 116u8, 120u8, 103u8, 116u8, 120u8, 111u8, 116u8, 121u8,
- 118u8, 117u8, 100u8, 105u8, 117u8, 100u8, 109u8, 117u8, 103u8, 0u8, 117u8,
- 103u8, 97u8, 117u8, 107u8, 0u8, 117u8, 110u8, 114u8, 117u8, 110u8, 120u8,
- 117u8, 114u8, 0u8, 118u8, 97u8, 105u8, 119u8, 97u8, 108u8, 119u8, 98u8,
- 113u8, 119u8, 98u8, 114u8, 119u8, 110u8, 105u8, 119u8, 115u8, 103u8, 119u8,
- 116u8, 109u8, 119u8, 117u8, 117u8, 120u8, 99u8, 111u8, 120u8, 99u8, 114u8,
- 120u8, 108u8, 99u8, 120u8, 108u8, 100u8, 120u8, 109u8, 102u8, 120u8, 109u8,
- 110u8, 120u8, 109u8, 114u8, 120u8, 110u8, 97u8, 120u8, 110u8, 114u8, 120u8,
- 112u8, 114u8, 120u8, 115u8, 97u8, 120u8, 115u8, 114u8, 121u8, 105u8, 0u8,
- 121u8, 117u8, 101u8, 122u8, 100u8, 106u8, 122u8, 103u8, 104u8, 122u8,
- 104u8, 0u8, 122u8, 104u8, 120u8, 122u8, 107u8, 116u8,
- ])
- },
- unsafe {
- ::zerovec::ZeroVec::from_bytes_unchecked(&[
- 67u8, 121u8, 114u8, 108u8, 67u8, 121u8, 114u8, 108u8, 84u8, 105u8, 98u8,
- 116u8, 67u8, 121u8, 114u8, 108u8, 65u8, 118u8, 115u8, 116u8, 65u8, 114u8,
- 97u8, 98u8, 65u8, 104u8, 111u8, 109u8, 65u8, 114u8, 97u8, 98u8, 88u8,
- 115u8, 117u8, 120u8, 67u8, 121u8, 114u8, 108u8, 69u8, 116u8, 104u8, 105u8,
- 65u8, 114u8, 97u8, 98u8, 65u8, 114u8, 97u8, 98u8, 65u8, 114u8, 97u8, 98u8,
- 65u8, 114u8, 109u8, 105u8, 65u8, 114u8, 97u8, 98u8, 65u8, 114u8, 97u8,
- 98u8, 65u8, 114u8, 97u8, 98u8, 65u8, 114u8, 97u8, 98u8, 66u8, 101u8, 110u8,
- 103u8, 83u8, 103u8, 110u8, 119u8, 67u8, 121u8, 114u8, 108u8, 65u8, 114u8,
- 97u8, 98u8, 68u8, 101u8, 118u8, 97u8, 67u8, 121u8, 114u8, 108u8, 65u8,
- 114u8, 97u8, 98u8, 68u8, 101u8, 118u8, 97u8, 66u8, 97u8, 109u8, 117u8,
- 69u8, 116u8, 104u8, 105u8, 67u8, 121u8, 114u8, 108u8, 65u8, 114u8, 97u8,
- 98u8, 84u8, 97u8, 109u8, 108u8, 65u8, 114u8, 97u8, 98u8, 68u8, 101u8,
- 118u8, 97u8, 67u8, 121u8, 114u8, 108u8, 68u8, 101u8, 118u8, 97u8, 65u8,
- 114u8, 97u8, 98u8, 71u8, 114u8, 101u8, 107u8, 68u8, 101u8, 118u8, 97u8,
- 68u8, 101u8, 118u8, 97u8, 68u8, 101u8, 118u8, 97u8, 69u8, 116u8, 104u8,
- 105u8, 68u8, 101u8, 118u8, 97u8, 84u8, 97u8, 118u8, 116u8, 66u8, 101u8,
- 110u8, 103u8, 84u8, 105u8, 98u8, 116u8, 66u8, 101u8, 110u8, 103u8, 65u8,
- 114u8, 97u8, 98u8, 68u8, 101u8, 118u8, 97u8, 65u8, 114u8, 97u8, 98u8, 68u8,
- 101u8, 118u8, 97u8, 66u8, 97u8, 115u8, 115u8, 69u8, 116u8, 104u8, 105u8,
- 68u8, 101u8, 118u8, 97u8, 67u8, 121u8, 114u8, 108u8, 69u8, 116u8, 104u8,
- 105u8, 67u8, 97u8, 107u8, 109u8, 67u8, 121u8, 114u8, 108u8, 67u8, 121u8,
- 114u8, 108u8, 67u8, 104u8, 101u8, 114u8, 65u8, 114u8, 97u8, 98u8, 67u8,
- 104u8, 97u8, 109u8, 65u8, 114u8, 97u8, 98u8, 83u8, 111u8, 121u8, 111u8,
- 67u8, 111u8, 112u8, 116u8, 67u8, 97u8, 110u8, 115u8, 67u8, 121u8, 114u8,
- 108u8, 67u8, 97u8, 110u8, 115u8, 67u8, 97u8, 110u8, 115u8, 67u8, 97u8,
- 110u8, 115u8, 80u8, 97u8, 117u8, 99u8, 67u8, 121u8, 114u8, 108u8, 67u8,
- 121u8, 114u8, 108u8, 67u8, 121u8, 114u8, 108u8, 65u8, 114u8, 97u8, 98u8,
- 65u8, 114u8, 97u8, 98u8, 77u8, 101u8, 100u8, 102u8, 68u8, 101u8, 118u8,
- 97u8, 77u8, 111u8, 110u8, 103u8, 69u8, 116u8, 104u8, 105u8, 68u8, 101u8,
- 118u8, 97u8, 84u8, 104u8, 97u8, 97u8, 84u8, 105u8, 98u8, 116u8, 69u8,
- 103u8, 121u8, 112u8, 75u8, 97u8, 108u8, 105u8, 71u8, 114u8, 101u8, 107u8,
- 71u8, 111u8, 110u8, 109u8, 73u8, 116u8, 97u8, 108u8, 65u8, 114u8, 97u8,
- 98u8, 65u8, 114u8, 97u8, 98u8, 65u8, 114u8, 97u8, 98u8, 72u8, 97u8, 110u8,
- 115u8, 68u8, 101u8, 118u8, 97u8, 65u8, 114u8, 97u8, 98u8, 69u8, 116u8,
- 104u8, 105u8, 68u8, 101u8, 118u8, 97u8, 65u8, 114u8, 97u8, 98u8, 65u8,
- 114u8, 97u8, 98u8, 65u8, 114u8, 97u8, 98u8, 69u8, 116u8, 104u8, 105u8,
- 69u8, 116u8, 104u8, 105u8, 68u8, 101u8, 118u8, 97u8, 84u8, 101u8, 108u8,
- 117u8, 71u8, 111u8, 116u8, 104u8, 67u8, 112u8, 114u8, 116u8, 66u8, 101u8,
- 110u8, 103u8, 71u8, 117u8, 106u8, 114u8, 68u8, 101u8, 118u8, 97u8, 65u8,
- 114u8, 97u8, 98u8, 65u8, 114u8, 97u8, 98u8, 72u8, 97u8, 110u8, 115u8, 65u8,
- 114u8, 97u8, 98u8, 69u8, 116u8, 104u8, 105u8, 72u8, 101u8, 98u8, 114u8,
- 68u8, 101u8, 118u8, 97u8, 72u8, 108u8, 117u8, 119u8, 80u8, 108u8, 114u8,
- 100u8, 65u8, 114u8, 97u8, 98u8, 68u8, 101u8, 118u8, 97u8, 72u8, 109u8,
- 110u8, 112u8, 65u8, 114u8, 97u8, 98u8, 68u8, 101u8, 118u8, 97u8, 68u8,
- 101u8, 118u8, 97u8, 72u8, 97u8, 110u8, 115u8, 65u8, 114u8, 109u8, 110u8,
- 89u8, 105u8, 105u8, 105u8, 67u8, 121u8, 114u8, 108u8, 67u8, 97u8, 110u8,
- 115u8, 72u8, 101u8, 98u8, 114u8, 74u8, 112u8, 97u8, 110u8, 72u8, 101u8,
- 98u8, 114u8, 68u8, 101u8, 118u8, 97u8, 71u8, 101u8, 111u8, 114u8, 67u8,
- 121u8, 114u8, 108u8, 75u8, 97u8, 119u8, 105u8, 67u8, 121u8, 114u8, 108u8,
- 65u8, 114u8, 97u8, 98u8, 84u8, 104u8, 97u8, 105u8, 68u8, 101u8, 118u8,
- 97u8, 68u8, 101u8, 118u8, 97u8, 84u8, 97u8, 108u8, 117u8, 68u8, 101u8,
- 118u8, 97u8, 77u8, 121u8, 109u8, 114u8, 65u8, 114u8, 97u8, 98u8, 76u8,
- 97u8, 111u8, 111u8, 67u8, 121u8, 114u8, 108u8, 75u8, 104u8, 109u8, 114u8,
- 75u8, 110u8, 100u8, 97u8, 75u8, 111u8, 114u8, 101u8, 67u8, 121u8, 114u8,
- 108u8, 68u8, 101u8, 118u8, 97u8, 69u8, 116u8, 104u8, 105u8, 67u8, 121u8,
- 114u8, 108u8, 68u8, 101u8, 118u8, 97u8, 65u8, 114u8, 97u8, 98u8, 69u8,
- 116u8, 104u8, 105u8, 67u8, 121u8, 114u8, 108u8, 67u8, 121u8, 114u8, 108u8,
- 65u8, 114u8, 97u8, 98u8, 69u8, 116u8, 104u8, 105u8, 68u8, 101u8, 118u8,
- 97u8, 84u8, 104u8, 97u8, 105u8, 65u8, 114u8, 97u8, 98u8, 67u8, 121u8,
- 114u8, 108u8, 65u8, 114u8, 97u8, 98u8, 76u8, 105u8, 110u8, 97u8, 72u8,
- 101u8, 98u8, 114u8, 65u8, 114u8, 97u8, 98u8, 67u8, 121u8, 114u8, 108u8,
- 84u8, 104u8, 97u8, 105u8, 76u8, 101u8, 112u8, 99u8, 67u8, 121u8, 114u8,
- 108u8, 68u8, 101u8, 118u8, 97u8, 76u8, 105u8, 115u8, 117u8, 65u8, 114u8,
- 97u8, 98u8, 84u8, 101u8, 108u8, 117u8, 76u8, 97u8, 111u8, 111u8, 65u8,
- 114u8, 97u8, 98u8, 65u8, 114u8, 97u8, 98u8, 84u8, 104u8, 97u8, 105u8, 72u8,
- 97u8, 110u8, 115u8, 68u8, 101u8, 118u8, 97u8, 68u8, 101u8, 118u8, 97u8,
- 65u8, 114u8, 97u8, 98u8, 67u8, 121u8, 114u8, 108u8, 69u8, 116u8, 104u8,
- 105u8, 65u8, 114u8, 97u8, 98u8, 68u8, 101u8, 118u8, 97u8, 67u8, 121u8,
- 114u8, 108u8, 65u8, 114u8, 97u8, 98u8, 77u8, 108u8, 121u8, 109u8, 67u8,
- 121u8, 114u8, 108u8, 66u8, 101u8, 110u8, 103u8, 77u8, 121u8, 109u8, 114u8,
- 68u8, 101u8, 118u8, 97u8, 68u8, 101u8, 118u8, 97u8, 67u8, 121u8, 114u8,
- 108u8, 77u8, 114u8, 111u8, 111u8, 68u8, 101u8, 118u8, 97u8, 65u8, 114u8,
- 97u8, 98u8, 68u8, 101u8, 118u8, 97u8, 72u8, 109u8, 110u8, 112u8, 77u8,
- 121u8, 109u8, 114u8, 69u8, 116u8, 104u8, 105u8, 67u8, 121u8, 114u8, 108u8,
- 77u8, 97u8, 110u8, 100u8, 65u8, 114u8, 97u8, 98u8, 72u8, 97u8, 110u8,
- 115u8, 68u8, 101u8, 118u8, 97u8, 68u8, 101u8, 118u8, 97u8, 87u8, 99u8,
- 104u8, 111u8, 76u8, 97u8, 110u8, 97u8, 68u8, 101u8, 118u8, 97u8, 82u8,
- 117u8, 110u8, 114u8, 78u8, 107u8, 111u8, 111u8, 67u8, 97u8, 110u8, 115u8,
- 84u8, 110u8, 115u8, 97u8, 67u8, 97u8, 110u8, 115u8, 67u8, 97u8, 110u8,
- 115u8, 79u8, 114u8, 121u8, 97u8, 65u8, 114u8, 97u8, 98u8, 67u8, 121u8,
- 114u8, 108u8, 79u8, 115u8, 103u8, 101u8, 65u8, 114u8, 97u8, 98u8, 79u8,
- 114u8, 107u8, 104u8, 79u8, 117u8, 103u8, 114u8, 71u8, 117u8, 114u8, 117u8,
- 80u8, 104u8, 108u8, 105u8, 88u8, 112u8, 101u8, 111u8, 65u8, 114u8, 97u8,
- 98u8, 80u8, 104u8, 110u8, 120u8, 66u8, 114u8, 97u8, 104u8, 71u8, 114u8,
- 101u8, 107u8, 68u8, 101u8, 118u8, 97u8, 75u8, 104u8, 97u8, 114u8, 65u8,
- 114u8, 97u8, 98u8, 65u8, 114u8, 97u8, 98u8, 68u8, 101u8, 118u8, 97u8, 82u8,
- 111u8, 104u8, 103u8, 84u8, 102u8, 110u8, 103u8, 68u8, 101u8, 118u8, 97u8,
- 66u8, 101u8, 110u8, 103u8, 65u8, 114u8, 97u8, 98u8, 67u8, 121u8, 114u8,
- 108u8, 67u8, 121u8, 114u8, 108u8, 75u8, 97u8, 110u8, 97u8, 68u8, 101u8,
- 118u8, 97u8, 67u8, 121u8, 114u8, 108u8, 79u8, 108u8, 99u8, 107u8, 83u8,
- 97u8, 117u8, 114u8, 68u8, 101u8, 118u8, 97u8, 65u8, 114u8, 97u8, 98u8,
- 65u8, 114u8, 97u8, 98u8, 65u8, 114u8, 97u8, 98u8, 79u8, 103u8, 97u8, 109u8,
- 69u8, 116u8, 104u8, 105u8, 84u8, 102u8, 110u8, 103u8, 77u8, 121u8, 109u8,
- 114u8, 65u8, 114u8, 97u8, 98u8, 83u8, 105u8, 110u8, 104u8, 65u8, 114u8,
- 97u8, 98u8, 83u8, 97u8, 109u8, 114u8, 83u8, 111u8, 103u8, 100u8, 84u8,
- 104u8, 97u8, 105u8, 67u8, 121u8, 114u8, 108u8, 83u8, 111u8, 114u8, 97u8,
- 68u8, 101u8, 118u8, 97u8, 65u8, 114u8, 97u8, 98u8, 68u8, 101u8, 118u8,
- 97u8, 66u8, 101u8, 110u8, 103u8, 83u8, 121u8, 114u8, 99u8, 84u8, 97u8,
- 109u8, 108u8, 68u8, 101u8, 118u8, 97u8, 75u8, 110u8, 100u8, 97u8, 84u8,
- 97u8, 108u8, 101u8, 68u8, 101u8, 118u8, 97u8, 68u8, 101u8, 118u8, 97u8,
- 84u8, 101u8, 108u8, 117u8, 67u8, 121u8, 114u8, 108u8, 84u8, 104u8, 97u8,
- 105u8, 68u8, 101u8, 118u8, 97u8, 68u8, 101u8, 118u8, 97u8, 68u8, 101u8,
- 118u8, 97u8, 69u8, 116u8, 104u8, 105u8, 69u8, 116u8, 104u8, 105u8, 68u8,
- 101u8, 118u8, 97u8, 65u8, 114u8, 97u8, 98u8, 71u8, 114u8, 101u8, 107u8,
- 68u8, 101u8, 118u8, 97u8, 84u8, 105u8, 98u8, 116u8, 67u8, 121u8, 114u8,
- 108u8, 84u8, 104u8, 97u8, 105u8, 84u8, 97u8, 110u8, 103u8, 84u8, 111u8,
- 116u8, 111u8, 67u8, 121u8, 114u8, 108u8, 65u8, 103u8, 104u8, 98u8, 67u8,
- 121u8, 114u8, 108u8, 65u8, 114u8, 97u8, 98u8, 85u8, 103u8, 97u8, 114u8,
- 67u8, 121u8, 114u8, 108u8, 66u8, 101u8, 110u8, 103u8, 66u8, 101u8, 110u8,
- 103u8, 65u8, 114u8, 97u8, 98u8, 86u8, 97u8, 105u8, 105u8, 69u8, 116u8,
- 104u8, 105u8, 84u8, 101u8, 108u8, 117u8, 68u8, 101u8, 118u8, 97u8, 65u8,
- 114u8, 97u8, 98u8, 71u8, 111u8, 110u8, 103u8, 68u8, 101u8, 118u8, 97u8,
- 72u8, 97u8, 110u8, 115u8, 67u8, 104u8, 114u8, 115u8, 67u8, 97u8, 114u8,
- 105u8, 76u8, 121u8, 99u8, 105u8, 76u8, 121u8, 100u8, 105u8, 71u8, 101u8,
- 111u8, 114u8, 77u8, 97u8, 110u8, 105u8, 77u8, 101u8, 114u8, 99u8, 78u8,
- 97u8, 114u8, 98u8, 68u8, 101u8, 118u8, 97u8, 80u8, 114u8, 116u8, 105u8,
- 83u8, 97u8, 114u8, 98u8, 68u8, 101u8, 118u8, 97u8, 72u8, 101u8, 98u8,
- 114u8, 72u8, 97u8, 110u8, 116u8, 65u8, 114u8, 97u8, 98u8, 84u8, 102u8,
- 110u8, 103u8, 72u8, 97u8, 110u8, 115u8, 78u8, 115u8, 104u8, 117u8, 75u8,
- 105u8, 116u8, 115u8,
- ])
- },
- )
- },
- lr2s: unsafe {
- #[allow(unused_unsafe)]
- ::zerovec::ZeroMap2d::from_parts_unchecked(
- unsafe {
- ::zerovec::ZeroVec::from_bytes_unchecked(&[
- 97u8, 122u8, 0u8, 104u8, 97u8, 0u8, 107u8, 107u8, 0u8, 107u8, 117u8, 0u8,
- 107u8, 121u8, 0u8, 109u8, 97u8, 110u8, 109u8, 110u8, 0u8, 109u8, 115u8,
- 0u8, 112u8, 97u8, 0u8, 114u8, 105u8, 102u8, 115u8, 100u8, 0u8, 115u8,
- 114u8, 0u8, 116u8, 103u8, 0u8, 117u8, 103u8, 0u8, 117u8, 110u8, 114u8,
- 117u8, 122u8, 0u8, 121u8, 117u8, 101u8, 122u8, 104u8, 0u8,
- ])
- },
- unsafe {
- ::zerovec::ZeroVec::from_bytes_unchecked(&[
- 3u8, 0u8, 0u8, 0u8, 5u8, 0u8, 0u8, 0u8, 9u8, 0u8, 0u8, 0u8, 10u8, 0u8, 0u8,
- 0u8, 12u8, 0u8, 0u8, 0u8, 13u8, 0u8, 0u8, 0u8, 14u8, 0u8, 0u8, 0u8, 15u8,
- 0u8, 0u8, 0u8, 16u8, 0u8, 0u8, 0u8, 17u8, 0u8, 0u8, 0u8, 18u8, 0u8, 0u8,
- 0u8, 22u8, 0u8, 0u8, 0u8, 23u8, 0u8, 0u8, 0u8, 25u8, 0u8, 0u8, 0u8, 26u8,
- 0u8, 0u8, 0u8, 28u8, 0u8, 0u8, 0u8, 29u8, 0u8, 0u8, 0u8, 44u8, 0u8, 0u8,
- 0u8,
- ])
- },
- unsafe {
- ::zerovec::ZeroVec::from_bytes_unchecked(&[
- 73u8, 81u8, 0u8, 73u8, 82u8, 0u8, 82u8, 85u8, 0u8, 67u8, 77u8, 0u8, 83u8,
- 68u8, 0u8, 65u8, 70u8, 0u8, 67u8, 78u8, 0u8, 73u8, 82u8, 0u8, 77u8, 78u8,
- 0u8, 76u8, 66u8, 0u8, 67u8, 78u8, 0u8, 84u8, 82u8, 0u8, 71u8, 78u8, 0u8,
- 67u8, 78u8, 0u8, 67u8, 67u8, 0u8, 80u8, 75u8, 0u8, 78u8, 76u8, 0u8, 73u8,
- 78u8, 0u8, 77u8, 69u8, 0u8, 82u8, 79u8, 0u8, 82u8, 85u8, 0u8, 84u8, 82u8,
- 0u8, 80u8, 75u8, 0u8, 75u8, 90u8, 0u8, 77u8, 78u8, 0u8, 78u8, 80u8, 0u8,
- 65u8, 70u8, 0u8, 67u8, 78u8, 0u8, 67u8, 78u8, 0u8, 65u8, 85u8, 0u8, 66u8,
- 78u8, 0u8, 71u8, 66u8, 0u8, 71u8, 70u8, 0u8, 72u8, 75u8, 0u8, 73u8, 68u8,
- 0u8, 77u8, 79u8, 0u8, 80u8, 65u8, 0u8, 80u8, 70u8, 0u8, 80u8, 72u8, 0u8,
- 83u8, 82u8, 0u8, 84u8, 72u8, 0u8, 84u8, 87u8, 0u8, 85u8, 83u8, 0u8, 86u8,
- 78u8, 0u8,
- ])
- },
- unsafe {
- ::zerovec::ZeroVec::from_bytes_unchecked(&[
- 65u8, 114u8, 97u8, 98u8, 65u8, 114u8, 97u8, 98u8, 67u8, 121u8, 114u8,
- 108u8, 65u8, 114u8, 97u8, 98u8, 65u8, 114u8, 97u8, 98u8, 65u8, 114u8, 97u8,
- 98u8, 65u8, 114u8, 97u8, 98u8, 65u8, 114u8, 97u8, 98u8, 65u8, 114u8, 97u8,
- 98u8, 65u8, 114u8, 97u8, 98u8, 65u8, 114u8, 97u8, 98u8, 76u8, 97u8, 116u8,
- 110u8, 78u8, 107u8, 111u8, 111u8, 77u8, 111u8, 110u8, 103u8, 65u8, 114u8,
- 97u8, 98u8, 65u8, 114u8, 97u8, 98u8, 76u8, 97u8, 116u8, 110u8, 68u8, 101u8,
- 118u8, 97u8, 76u8, 97u8, 116u8, 110u8, 76u8, 97u8, 116u8, 110u8, 76u8,
- 97u8, 116u8, 110u8, 76u8, 97u8, 116u8, 110u8, 65u8, 114u8, 97u8, 98u8,
- 67u8, 121u8, 114u8, 108u8, 67u8, 121u8, 114u8, 108u8, 68u8, 101u8, 118u8,
- 97u8, 65u8, 114u8, 97u8, 98u8, 67u8, 121u8, 114u8, 108u8, 72u8, 97u8,
- 110u8, 115u8, 72u8, 97u8, 110u8, 116u8, 72u8, 97u8, 110u8, 116u8, 72u8,
- 97u8, 110u8, 116u8, 72u8, 97u8, 110u8, 116u8, 72u8, 97u8, 110u8, 116u8,
- 72u8, 97u8, 110u8, 116u8, 72u8, 97u8, 110u8, 116u8, 72u8, 97u8, 110u8,
- 116u8, 72u8, 97u8, 110u8, 116u8, 72u8, 97u8, 110u8, 116u8, 72u8, 97u8,
- 110u8, 116u8, 72u8, 97u8, 110u8, 116u8, 72u8, 97u8, 110u8, 116u8, 72u8,
- 97u8, 110u8, 116u8, 72u8, 97u8, 110u8, 116u8,
- ])
- },
- )
- },
- l2r: unsafe {
- #[allow(unused_unsafe)]
- ::zerovec::ZeroMap::from_parts_unchecked(
- unsafe {
- ::zerovec::ZeroVec::from_bytes_unchecked(&[
- 97u8, 97u8, 0u8, 97u8, 98u8, 0u8, 97u8, 98u8, 114u8, 97u8, 99u8, 101u8,
- 97u8, 99u8, 104u8, 97u8, 100u8, 97u8, 97u8, 100u8, 112u8, 97u8, 100u8,
- 121u8, 97u8, 101u8, 0u8, 97u8, 101u8, 98u8, 97u8, 102u8, 0u8, 97u8, 103u8,
- 113u8, 97u8, 104u8, 111u8, 97u8, 106u8, 116u8, 97u8, 107u8, 0u8, 97u8,
- 107u8, 107u8, 97u8, 108u8, 110u8, 97u8, 108u8, 116u8, 97u8, 109u8, 0u8,
- 97u8, 109u8, 111u8, 97u8, 110u8, 0u8, 97u8, 110u8, 110u8, 97u8, 111u8,
- 122u8, 97u8, 112u8, 100u8, 97u8, 114u8, 0u8, 97u8, 114u8, 99u8, 97u8,
- 114u8, 110u8, 97u8, 114u8, 111u8, 97u8, 114u8, 113u8, 97u8, 114u8, 115u8,
- 97u8, 114u8, 121u8, 97u8, 114u8, 122u8, 97u8, 115u8, 0u8, 97u8, 115u8,
- 97u8, 97u8, 115u8, 101u8, 97u8, 115u8, 116u8, 97u8, 116u8, 106u8, 97u8,
- 118u8, 0u8, 97u8, 119u8, 97u8, 97u8, 121u8, 0u8, 97u8, 122u8, 0u8, 98u8,
- 97u8, 0u8, 98u8, 97u8, 108u8, 98u8, 97u8, 110u8, 98u8, 97u8, 112u8, 98u8,
- 97u8, 114u8, 98u8, 97u8, 115u8, 98u8, 97u8, 120u8, 98u8, 98u8, 99u8, 98u8,
- 98u8, 106u8, 98u8, 99u8, 105u8, 98u8, 101u8, 0u8, 98u8, 101u8, 106u8, 98u8,
- 101u8, 109u8, 98u8, 101u8, 119u8, 98u8, 101u8, 122u8, 98u8, 102u8, 100u8,
- 98u8, 102u8, 113u8, 98u8, 102u8, 116u8, 98u8, 102u8, 121u8, 98u8, 103u8,
- 0u8, 98u8, 103u8, 99u8, 98u8, 103u8, 110u8, 98u8, 103u8, 120u8, 98u8,
- 104u8, 98u8, 98u8, 104u8, 105u8, 98u8, 104u8, 111u8, 98u8, 105u8, 0u8,
- 98u8, 105u8, 107u8, 98u8, 105u8, 110u8, 98u8, 106u8, 106u8, 98u8, 106u8,
- 110u8, 98u8, 106u8, 116u8, 98u8, 107u8, 109u8, 98u8, 107u8, 117u8, 98u8,
- 108u8, 97u8, 98u8, 108u8, 103u8, 98u8, 108u8, 116u8, 98u8, 109u8, 0u8,
- 98u8, 109u8, 113u8, 98u8, 110u8, 0u8, 98u8, 111u8, 0u8, 98u8, 112u8, 121u8,
- 98u8, 113u8, 105u8, 98u8, 113u8, 118u8, 98u8, 114u8, 0u8, 98u8, 114u8,
- 97u8, 98u8, 114u8, 104u8, 98u8, 114u8, 120u8, 98u8, 115u8, 0u8, 98u8,
- 115u8, 113u8, 98u8, 115u8, 115u8, 98u8, 116u8, 111u8, 98u8, 116u8, 118u8,
- 98u8, 117u8, 97u8, 98u8, 117u8, 99u8, 98u8, 117u8, 103u8, 98u8, 117u8,
- 109u8, 98u8, 118u8, 98u8, 98u8, 121u8, 110u8, 98u8, 121u8, 118u8, 98u8,
- 122u8, 101u8, 99u8, 97u8, 0u8, 99u8, 97u8, 100u8, 99u8, 99u8, 104u8, 99u8,
- 99u8, 112u8, 99u8, 101u8, 0u8, 99u8, 101u8, 98u8, 99u8, 103u8, 103u8, 99u8,
- 104u8, 0u8, 99u8, 104u8, 107u8, 99u8, 104u8, 109u8, 99u8, 104u8, 111u8,
- 99u8, 104u8, 112u8, 99u8, 104u8, 114u8, 99u8, 105u8, 99u8, 99u8, 106u8,
- 97u8, 99u8, 106u8, 109u8, 99u8, 107u8, 98u8, 99u8, 108u8, 99u8, 99u8,
- 109u8, 103u8, 99u8, 111u8, 0u8, 99u8, 111u8, 112u8, 99u8, 112u8, 115u8,
- 99u8, 114u8, 0u8, 99u8, 114u8, 103u8, 99u8, 114u8, 104u8, 99u8, 114u8,
- 107u8, 99u8, 114u8, 108u8, 99u8, 114u8, 115u8, 99u8, 115u8, 0u8, 99u8,
- 115u8, 98u8, 99u8, 115u8, 119u8, 99u8, 116u8, 100u8, 99u8, 117u8, 0u8,
- 99u8, 118u8, 0u8, 99u8, 121u8, 0u8, 100u8, 97u8, 0u8, 100u8, 97u8, 102u8,
- 100u8, 97u8, 107u8, 100u8, 97u8, 114u8, 100u8, 97u8, 118u8, 100u8, 99u8,
- 99u8, 100u8, 101u8, 0u8, 100u8, 101u8, 110u8, 100u8, 103u8, 114u8, 100u8,
- 106u8, 101u8, 100u8, 109u8, 102u8, 100u8, 110u8, 106u8, 100u8, 111u8,
- 105u8, 100u8, 114u8, 104u8, 100u8, 115u8, 98u8, 100u8, 116u8, 109u8, 100u8,
- 116u8, 112u8, 100u8, 116u8, 121u8, 100u8, 117u8, 97u8, 100u8, 118u8, 0u8,
- 100u8, 121u8, 111u8, 100u8, 121u8, 117u8, 100u8, 122u8, 0u8, 101u8, 98u8,
- 117u8, 101u8, 101u8, 0u8, 101u8, 102u8, 105u8, 101u8, 103u8, 108u8, 101u8,
- 103u8, 121u8, 101u8, 107u8, 121u8, 101u8, 108u8, 0u8, 101u8, 110u8, 0u8,
- 101u8, 111u8, 0u8, 101u8, 115u8, 0u8, 101u8, 115u8, 103u8, 101u8, 115u8,
- 117u8, 101u8, 116u8, 0u8, 101u8, 116u8, 116u8, 101u8, 117u8, 0u8, 101u8,
- 119u8, 111u8, 101u8, 120u8, 116u8, 102u8, 97u8, 0u8, 102u8, 97u8, 110u8,
- 102u8, 102u8, 0u8, 102u8, 102u8, 109u8, 102u8, 105u8, 0u8, 102u8, 105u8,
- 97u8, 102u8, 105u8, 108u8, 102u8, 105u8, 116u8, 102u8, 106u8, 0u8, 102u8,
- 111u8, 0u8, 102u8, 111u8, 110u8, 102u8, 114u8, 0u8, 102u8, 114u8, 99u8,
- 102u8, 114u8, 112u8, 102u8, 114u8, 114u8, 102u8, 114u8, 115u8, 102u8,
- 117u8, 98u8, 102u8, 117u8, 100u8, 102u8, 117u8, 102u8, 102u8, 117u8, 113u8,
- 102u8, 117u8, 114u8, 102u8, 117u8, 118u8, 102u8, 118u8, 114u8, 102u8,
- 121u8, 0u8, 103u8, 97u8, 0u8, 103u8, 97u8, 97u8, 103u8, 97u8, 103u8, 103u8,
- 97u8, 110u8, 103u8, 97u8, 121u8, 103u8, 98u8, 109u8, 103u8, 98u8, 122u8,
- 103u8, 99u8, 114u8, 103u8, 100u8, 0u8, 103u8, 101u8, 122u8, 103u8, 103u8,
- 110u8, 103u8, 105u8, 108u8, 103u8, 106u8, 107u8, 103u8, 106u8, 117u8,
- 103u8, 108u8, 0u8, 103u8, 108u8, 107u8, 103u8, 110u8, 0u8, 103u8, 111u8,
- 109u8, 103u8, 111u8, 110u8, 103u8, 111u8, 114u8, 103u8, 111u8, 115u8,
- 103u8, 111u8, 116u8, 103u8, 114u8, 99u8, 103u8, 114u8, 116u8, 103u8, 115u8,
- 119u8, 103u8, 117u8, 0u8, 103u8, 117u8, 98u8, 103u8, 117u8, 99u8, 103u8,
- 117u8, 114u8, 103u8, 117u8, 122u8, 103u8, 118u8, 0u8, 103u8, 118u8, 114u8,
- 103u8, 119u8, 105u8, 104u8, 97u8, 0u8, 104u8, 97u8, 107u8, 104u8, 97u8,
- 119u8, 104u8, 97u8, 122u8, 104u8, 101u8, 0u8, 104u8, 105u8, 0u8, 104u8,
- 105u8, 102u8, 104u8, 105u8, 108u8, 104u8, 108u8, 117u8, 104u8, 109u8,
- 100u8, 104u8, 110u8, 100u8, 104u8, 110u8, 101u8, 104u8, 110u8, 106u8,
- 104u8, 110u8, 110u8, 104u8, 110u8, 111u8, 104u8, 111u8, 0u8, 104u8, 111u8,
- 99u8, 104u8, 111u8, 106u8, 104u8, 114u8, 0u8, 104u8, 115u8, 98u8, 104u8,
- 115u8, 110u8, 104u8, 116u8, 0u8, 104u8, 117u8, 0u8, 104u8, 117u8, 114u8,
- 104u8, 121u8, 0u8, 104u8, 122u8, 0u8, 105u8, 97u8, 0u8, 105u8, 98u8, 97u8,
- 105u8, 98u8, 98u8, 105u8, 100u8, 0u8, 105u8, 102u8, 101u8, 105u8, 103u8,
- 0u8, 105u8, 105u8, 0u8, 105u8, 107u8, 0u8, 105u8, 108u8, 111u8, 105u8,
- 110u8, 0u8, 105u8, 110u8, 104u8, 105u8, 111u8, 0u8, 105u8, 115u8, 0u8,
- 105u8, 116u8, 0u8, 105u8, 117u8, 0u8, 105u8, 119u8, 0u8, 105u8, 122u8,
- 104u8, 106u8, 97u8, 0u8, 106u8, 97u8, 109u8, 106u8, 98u8, 111u8, 106u8,
- 103u8, 111u8, 106u8, 105u8, 0u8, 106u8, 109u8, 99u8, 106u8, 109u8, 108u8,
- 106u8, 117u8, 116u8, 106u8, 118u8, 0u8, 106u8, 119u8, 0u8, 107u8, 97u8,
- 0u8, 107u8, 97u8, 97u8, 107u8, 97u8, 98u8, 107u8, 97u8, 99u8, 107u8, 97u8,
- 106u8, 107u8, 97u8, 109u8, 107u8, 97u8, 111u8, 107u8, 97u8, 119u8, 107u8,
- 98u8, 100u8, 107u8, 98u8, 121u8, 107u8, 99u8, 103u8, 107u8, 99u8, 107u8,
- 107u8, 100u8, 101u8, 107u8, 100u8, 104u8, 107u8, 100u8, 116u8, 107u8,
- 101u8, 97u8, 107u8, 101u8, 110u8, 107u8, 102u8, 111u8, 107u8, 102u8, 114u8,
- 107u8, 102u8, 121u8, 107u8, 103u8, 0u8, 107u8, 103u8, 101u8, 107u8, 103u8,
- 112u8, 107u8, 104u8, 97u8, 107u8, 104u8, 98u8, 107u8, 104u8, 110u8, 107u8,
- 104u8, 113u8, 107u8, 104u8, 116u8, 107u8, 104u8, 119u8, 107u8, 105u8, 0u8,
- 107u8, 105u8, 117u8, 107u8, 106u8, 0u8, 107u8, 106u8, 103u8, 107u8, 107u8,
- 0u8, 107u8, 107u8, 106u8, 107u8, 108u8, 0u8, 107u8, 108u8, 110u8, 107u8,
- 109u8, 0u8, 107u8, 109u8, 98u8, 107u8, 110u8, 0u8, 107u8, 110u8, 102u8,
- 107u8, 111u8, 0u8, 107u8, 111u8, 105u8, 107u8, 111u8, 107u8, 107u8, 111u8,
- 115u8, 107u8, 112u8, 101u8, 107u8, 114u8, 99u8, 107u8, 114u8, 105u8, 107u8,
- 114u8, 106u8, 107u8, 114u8, 108u8, 107u8, 114u8, 117u8, 107u8, 115u8, 0u8,
- 107u8, 115u8, 98u8, 107u8, 115u8, 102u8, 107u8, 115u8, 104u8, 107u8, 116u8,
- 114u8, 107u8, 117u8, 0u8, 107u8, 117u8, 109u8, 107u8, 118u8, 0u8, 107u8,
- 118u8, 114u8, 107u8, 118u8, 120u8, 107u8, 119u8, 0u8, 107u8, 119u8, 107u8,
- 107u8, 120u8, 108u8, 107u8, 120u8, 109u8, 107u8, 120u8, 112u8, 107u8,
- 121u8, 0u8, 107u8, 122u8, 106u8, 107u8, 122u8, 116u8, 108u8, 97u8, 0u8,
- 108u8, 97u8, 98u8, 108u8, 97u8, 100u8, 108u8, 97u8, 103u8, 108u8, 97u8,
- 104u8, 108u8, 97u8, 106u8, 108u8, 98u8, 0u8, 108u8, 98u8, 101u8, 108u8,
- 98u8, 119u8, 108u8, 99u8, 112u8, 108u8, 101u8, 112u8, 108u8, 101u8, 122u8,
- 108u8, 103u8, 0u8, 108u8, 105u8, 0u8, 108u8, 105u8, 102u8, 108u8, 105u8,
- 106u8, 108u8, 105u8, 108u8, 108u8, 105u8, 115u8, 108u8, 106u8, 112u8,
- 108u8, 107u8, 105u8, 108u8, 107u8, 116u8, 108u8, 109u8, 110u8, 108u8,
- 109u8, 111u8, 108u8, 110u8, 0u8, 108u8, 111u8, 0u8, 108u8, 111u8, 108u8,
- 108u8, 111u8, 122u8, 108u8, 114u8, 99u8, 108u8, 116u8, 0u8, 108u8, 116u8,
- 103u8, 108u8, 117u8, 0u8, 108u8, 117u8, 97u8, 108u8, 117u8, 111u8, 108u8,
- 117u8, 121u8, 108u8, 117u8, 122u8, 108u8, 118u8, 0u8, 108u8, 119u8, 108u8,
- 108u8, 122u8, 104u8, 108u8, 122u8, 122u8, 109u8, 97u8, 100u8, 109u8, 97u8,
- 102u8, 109u8, 97u8, 103u8, 109u8, 97u8, 105u8, 109u8, 97u8, 107u8, 109u8,
- 97u8, 110u8, 109u8, 97u8, 115u8, 109u8, 97u8, 122u8, 109u8, 100u8, 102u8,
- 109u8, 100u8, 104u8, 109u8, 100u8, 114u8, 109u8, 101u8, 110u8, 109u8,
- 101u8, 114u8, 109u8, 102u8, 97u8, 109u8, 102u8, 101u8, 109u8, 103u8, 0u8,
- 109u8, 103u8, 104u8, 109u8, 103u8, 111u8, 109u8, 103u8, 112u8, 109u8,
- 103u8, 121u8, 109u8, 104u8, 0u8, 109u8, 105u8, 0u8, 109u8, 105u8, 99u8,
- 109u8, 105u8, 110u8, 109u8, 107u8, 0u8, 109u8, 108u8, 0u8, 109u8, 108u8,
- 115u8, 109u8, 110u8, 0u8, 109u8, 110u8, 105u8, 109u8, 110u8, 119u8, 109u8,
- 111u8, 0u8, 109u8, 111u8, 101u8, 109u8, 111u8, 104u8, 109u8, 111u8, 115u8,
- 109u8, 114u8, 0u8, 109u8, 114u8, 100u8, 109u8, 114u8, 106u8, 109u8, 114u8,
- 111u8, 109u8, 115u8, 0u8, 109u8, 116u8, 0u8, 109u8, 116u8, 114u8, 109u8,
- 117u8, 97u8, 109u8, 117u8, 115u8, 109u8, 118u8, 121u8, 109u8, 119u8, 107u8,
- 109u8, 119u8, 114u8, 109u8, 119u8, 118u8, 109u8, 119u8, 119u8, 109u8,
- 120u8, 99u8, 109u8, 121u8, 0u8, 109u8, 121u8, 118u8, 109u8, 121u8, 120u8,
- 109u8, 121u8, 122u8, 109u8, 122u8, 110u8, 110u8, 97u8, 0u8, 110u8, 97u8,
- 110u8, 110u8, 97u8, 112u8, 110u8, 97u8, 113u8, 110u8, 98u8, 0u8, 110u8,
- 99u8, 104u8, 110u8, 100u8, 0u8, 110u8, 100u8, 99u8, 110u8, 100u8, 115u8,
- 110u8, 101u8, 0u8, 110u8, 101u8, 119u8, 110u8, 103u8, 0u8, 110u8, 103u8,
- 108u8, 110u8, 104u8, 101u8, 110u8, 104u8, 119u8, 110u8, 105u8, 106u8,
- 110u8, 105u8, 117u8, 110u8, 106u8, 111u8, 110u8, 108u8, 0u8, 110u8, 109u8,
- 103u8, 110u8, 110u8, 0u8, 110u8, 110u8, 104u8, 110u8, 110u8, 112u8, 110u8,
- 111u8, 0u8, 110u8, 111u8, 100u8, 110u8, 111u8, 101u8, 110u8, 111u8, 110u8,
- 110u8, 113u8, 111u8, 110u8, 114u8, 0u8, 110u8, 115u8, 107u8, 110u8, 115u8,
- 111u8, 110u8, 115u8, 116u8, 110u8, 117u8, 115u8, 110u8, 118u8, 0u8, 110u8,
- 120u8, 113u8, 110u8, 121u8, 0u8, 110u8, 121u8, 109u8, 110u8, 121u8, 110u8,
- 110u8, 122u8, 105u8, 111u8, 99u8, 0u8, 111u8, 106u8, 0u8, 111u8, 106u8,
- 115u8, 111u8, 107u8, 97u8, 111u8, 109u8, 0u8, 111u8, 114u8, 0u8, 111u8,
- 115u8, 0u8, 111u8, 115u8, 97u8, 111u8, 116u8, 107u8, 111u8, 117u8, 105u8,
- 112u8, 97u8, 0u8, 112u8, 97u8, 103u8, 112u8, 97u8, 108u8, 112u8, 97u8,
- 109u8, 112u8, 97u8, 112u8, 112u8, 97u8, 117u8, 112u8, 99u8, 100u8, 112u8,
- 99u8, 109u8, 112u8, 100u8, 99u8, 112u8, 100u8, 116u8, 112u8, 101u8, 111u8,
- 112u8, 102u8, 108u8, 112u8, 104u8, 110u8, 112u8, 105u8, 115u8, 112u8,
- 107u8, 97u8, 112u8, 107u8, 111u8, 112u8, 108u8, 0u8, 112u8, 109u8, 115u8,
- 112u8, 110u8, 116u8, 112u8, 111u8, 110u8, 112u8, 112u8, 97u8, 112u8, 113u8,
- 109u8, 112u8, 114u8, 97u8, 112u8, 114u8, 100u8, 112u8, 114u8, 103u8, 112u8,
- 115u8, 0u8, 112u8, 116u8, 0u8, 112u8, 117u8, 117u8, 113u8, 117u8, 0u8,
- 113u8, 117u8, 99u8, 113u8, 117u8, 103u8, 114u8, 97u8, 106u8, 114u8, 99u8,
- 102u8, 114u8, 101u8, 106u8, 114u8, 103u8, 110u8, 114u8, 104u8, 103u8,
- 114u8, 105u8, 97u8, 114u8, 105u8, 102u8, 114u8, 106u8, 115u8, 114u8, 107u8,
- 116u8, 114u8, 109u8, 0u8, 114u8, 109u8, 102u8, 114u8, 109u8, 111u8, 114u8,
- 109u8, 116u8, 114u8, 109u8, 117u8, 114u8, 110u8, 0u8, 114u8, 110u8, 103u8,
- 114u8, 111u8, 0u8, 114u8, 111u8, 98u8, 114u8, 111u8, 102u8, 114u8, 116u8,
- 109u8, 114u8, 117u8, 0u8, 114u8, 117u8, 101u8, 114u8, 117u8, 103u8, 114u8,
- 119u8, 0u8, 114u8, 119u8, 107u8, 114u8, 121u8, 117u8, 115u8, 97u8, 0u8,
- 115u8, 97u8, 102u8, 115u8, 97u8, 104u8, 115u8, 97u8, 113u8, 115u8, 97u8,
- 115u8, 115u8, 97u8, 116u8, 115u8, 97u8, 118u8, 115u8, 97u8, 122u8, 115u8,
- 98u8, 112u8, 115u8, 99u8, 0u8, 115u8, 99u8, 107u8, 115u8, 99u8, 110u8,
- 115u8, 99u8, 111u8, 115u8, 100u8, 0u8, 115u8, 100u8, 99u8, 115u8, 100u8,
- 104u8, 115u8, 101u8, 0u8, 115u8, 101u8, 102u8, 115u8, 101u8, 104u8, 115u8,
- 101u8, 105u8, 115u8, 101u8, 115u8, 115u8, 103u8, 0u8, 115u8, 103u8, 97u8,
- 115u8, 103u8, 115u8, 115u8, 104u8, 105u8, 115u8, 104u8, 110u8, 115u8,
- 105u8, 0u8, 115u8, 105u8, 100u8, 115u8, 107u8, 0u8, 115u8, 107u8, 114u8,
- 115u8, 108u8, 0u8, 115u8, 108u8, 105u8, 115u8, 108u8, 121u8, 115u8, 109u8,
- 0u8, 115u8, 109u8, 97u8, 115u8, 109u8, 100u8, 115u8, 109u8, 106u8, 115u8,
- 109u8, 110u8, 115u8, 109u8, 112u8, 115u8, 109u8, 115u8, 115u8, 110u8, 0u8,
- 115u8, 110u8, 98u8, 115u8, 110u8, 107u8, 115u8, 111u8, 0u8, 115u8, 111u8,
- 103u8, 115u8, 111u8, 117u8, 115u8, 113u8, 0u8, 115u8, 114u8, 0u8, 115u8,
- 114u8, 98u8, 115u8, 114u8, 110u8, 115u8, 114u8, 114u8, 115u8, 114u8, 120u8,
- 115u8, 115u8, 0u8, 115u8, 115u8, 121u8, 115u8, 116u8, 0u8, 115u8, 116u8,
- 113u8, 115u8, 117u8, 0u8, 115u8, 117u8, 107u8, 115u8, 117u8, 115u8, 115u8,
- 118u8, 0u8, 115u8, 119u8, 0u8, 115u8, 119u8, 98u8, 115u8, 119u8, 99u8,
- 115u8, 119u8, 103u8, 115u8, 119u8, 118u8, 115u8, 120u8, 110u8, 115u8,
- 121u8, 108u8, 115u8, 121u8, 114u8, 115u8, 122u8, 108u8, 116u8, 97u8, 0u8,
- 116u8, 97u8, 106u8, 116u8, 98u8, 119u8, 116u8, 99u8, 121u8, 116u8, 100u8,
- 100u8, 116u8, 100u8, 103u8, 116u8, 100u8, 104u8, 116u8, 100u8, 117u8,
- 116u8, 101u8, 0u8, 116u8, 101u8, 109u8, 116u8, 101u8, 111u8, 116u8, 101u8,
- 116u8, 116u8, 103u8, 0u8, 116u8, 104u8, 0u8, 116u8, 104u8, 108u8, 116u8,
- 104u8, 113u8, 116u8, 104u8, 114u8, 116u8, 105u8, 0u8, 116u8, 105u8, 103u8,
- 116u8, 105u8, 118u8, 116u8, 107u8, 0u8, 116u8, 107u8, 108u8, 116u8, 107u8,
- 114u8, 116u8, 107u8, 116u8, 116u8, 108u8, 0u8, 116u8, 108u8, 121u8, 116u8,
- 109u8, 104u8, 116u8, 110u8, 0u8, 116u8, 111u8, 0u8, 116u8, 111u8, 103u8,
- 116u8, 111u8, 107u8, 116u8, 112u8, 105u8, 116u8, 114u8, 0u8, 116u8, 114u8,
- 117u8, 116u8, 114u8, 118u8, 116u8, 114u8, 119u8, 116u8, 115u8, 0u8, 116u8,
- 115u8, 100u8, 116u8, 115u8, 102u8, 116u8, 115u8, 103u8, 116u8, 115u8,
- 106u8, 116u8, 116u8, 0u8, 116u8, 116u8, 106u8, 116u8, 116u8, 115u8, 116u8,
- 116u8, 116u8, 116u8, 117u8, 109u8, 116u8, 118u8, 108u8, 116u8, 119u8,
- 113u8, 116u8, 120u8, 103u8, 116u8, 120u8, 111u8, 116u8, 121u8, 0u8, 116u8,
- 121u8, 118u8, 116u8, 122u8, 109u8, 117u8, 100u8, 105u8, 117u8, 100u8,
- 109u8, 117u8, 103u8, 0u8, 117u8, 103u8, 97u8, 117u8, 107u8, 0u8, 117u8,
- 108u8, 105u8, 117u8, 109u8, 98u8, 117u8, 110u8, 114u8, 117u8, 110u8, 120u8,
- 117u8, 114u8, 0u8, 117u8, 122u8, 0u8, 118u8, 97u8, 105u8, 118u8, 101u8,
- 0u8, 118u8, 101u8, 99u8, 118u8, 101u8, 112u8, 118u8, 105u8, 0u8, 118u8,
- 105u8, 99u8, 118u8, 108u8, 115u8, 118u8, 109u8, 102u8, 118u8, 109u8, 119u8,
- 118u8, 111u8, 0u8, 118u8, 111u8, 116u8, 118u8, 114u8, 111u8, 118u8, 117u8,
- 110u8, 119u8, 97u8, 0u8, 119u8, 97u8, 101u8, 119u8, 97u8, 108u8, 119u8,
- 97u8, 114u8, 119u8, 98u8, 112u8, 119u8, 98u8, 113u8, 119u8, 98u8, 114u8,
- 119u8, 108u8, 115u8, 119u8, 110u8, 105u8, 119u8, 111u8, 0u8, 119u8, 115u8,
- 103u8, 119u8, 116u8, 109u8, 119u8, 117u8, 117u8, 120u8, 97u8, 118u8, 120u8,
- 99u8, 111u8, 120u8, 99u8, 114u8, 120u8, 104u8, 0u8, 120u8, 108u8, 99u8,
- 120u8, 108u8, 100u8, 120u8, 109u8, 102u8, 120u8, 109u8, 110u8, 120u8,
- 109u8, 114u8, 120u8, 110u8, 97u8, 120u8, 110u8, 114u8, 120u8, 111u8, 103u8,
- 120u8, 112u8, 114u8, 120u8, 115u8, 97u8, 120u8, 115u8, 114u8, 121u8, 97u8,
- 111u8, 121u8, 97u8, 112u8, 121u8, 97u8, 118u8, 121u8, 98u8, 98u8, 121u8,
- 105u8, 0u8, 121u8, 111u8, 0u8, 121u8, 114u8, 108u8, 121u8, 117u8, 97u8,
- 121u8, 117u8, 101u8, 122u8, 97u8, 0u8, 122u8, 97u8, 103u8, 122u8, 100u8,
- 106u8, 122u8, 101u8, 97u8, 122u8, 103u8, 104u8, 122u8, 104u8, 0u8, 122u8,
- 104u8, 120u8, 122u8, 107u8, 116u8, 122u8, 108u8, 109u8, 122u8, 109u8,
- 105u8, 122u8, 117u8, 0u8, 122u8, 122u8, 97u8,
- ])
- },
- unsafe {
- ::zerovec::ZeroVec::from_bytes_unchecked(&[
- 69u8, 84u8, 0u8, 71u8, 69u8, 0u8, 71u8, 72u8, 0u8, 73u8, 68u8, 0u8, 85u8,
- 71u8, 0u8, 71u8, 72u8, 0u8, 66u8, 84u8, 0u8, 82u8, 85u8, 0u8, 73u8, 82u8,
- 0u8, 84u8, 78u8, 0u8, 90u8, 65u8, 0u8, 67u8, 77u8, 0u8, 73u8, 78u8, 0u8,
- 84u8, 78u8, 0u8, 71u8, 72u8, 0u8, 73u8, 81u8, 0u8, 88u8, 75u8, 0u8, 82u8,
- 85u8, 0u8, 69u8, 84u8, 0u8, 78u8, 71u8, 0u8, 69u8, 83u8, 0u8, 78u8, 71u8,
- 0u8, 73u8, 68u8, 0u8, 84u8, 71u8, 0u8, 69u8, 71u8, 0u8, 73u8, 82u8, 0u8,
- 67u8, 76u8, 0u8, 66u8, 79u8, 0u8, 68u8, 90u8, 0u8, 83u8, 65u8, 0u8, 77u8,
- 65u8, 0u8, 69u8, 71u8, 0u8, 73u8, 78u8, 0u8, 84u8, 90u8, 0u8, 85u8, 83u8,
- 0u8, 69u8, 83u8, 0u8, 67u8, 65u8, 0u8, 82u8, 85u8, 0u8, 73u8, 78u8, 0u8,
- 66u8, 79u8, 0u8, 65u8, 90u8, 0u8, 82u8, 85u8, 0u8, 80u8, 75u8, 0u8, 73u8,
- 68u8, 0u8, 78u8, 80u8, 0u8, 65u8, 84u8, 0u8, 67u8, 77u8, 0u8, 67u8, 77u8,
- 0u8, 73u8, 68u8, 0u8, 67u8, 77u8, 0u8, 67u8, 73u8, 0u8, 66u8, 89u8, 0u8,
- 83u8, 68u8, 0u8, 90u8, 77u8, 0u8, 73u8, 68u8, 0u8, 84u8, 90u8, 0u8, 67u8,
- 77u8, 0u8, 73u8, 78u8, 0u8, 80u8, 75u8, 0u8, 73u8, 78u8, 0u8, 66u8, 71u8,
- 0u8, 73u8, 78u8, 0u8, 80u8, 75u8, 0u8, 84u8, 82u8, 0u8, 73u8, 78u8, 0u8,
- 73u8, 78u8, 0u8, 73u8, 78u8, 0u8, 86u8, 85u8, 0u8, 80u8, 72u8, 0u8, 78u8,
- 71u8, 0u8, 73u8, 78u8, 0u8, 73u8, 68u8, 0u8, 83u8, 78u8, 0u8, 67u8, 77u8,
- 0u8, 80u8, 72u8, 0u8, 67u8, 65u8, 0u8, 77u8, 89u8, 0u8, 86u8, 78u8, 0u8,
- 77u8, 76u8, 0u8, 77u8, 76u8, 0u8, 66u8, 68u8, 0u8, 67u8, 78u8, 0u8, 73u8,
- 78u8, 0u8, 73u8, 82u8, 0u8, 67u8, 73u8, 0u8, 70u8, 82u8, 0u8, 73u8, 78u8,
- 0u8, 80u8, 75u8, 0u8, 73u8, 78u8, 0u8, 66u8, 65u8, 0u8, 76u8, 82u8, 0u8,
- 67u8, 77u8, 0u8, 80u8, 72u8, 0u8, 80u8, 75u8, 0u8, 82u8, 85u8, 0u8, 89u8,
- 84u8, 0u8, 73u8, 68u8, 0u8, 67u8, 77u8, 0u8, 71u8, 81u8, 0u8, 69u8, 82u8,
- 0u8, 67u8, 77u8, 0u8, 77u8, 76u8, 0u8, 69u8, 83u8, 0u8, 85u8, 83u8, 0u8,
- 78u8, 71u8, 0u8, 66u8, 68u8, 0u8, 82u8, 85u8, 0u8, 80u8, 72u8, 0u8, 85u8,
- 71u8, 0u8, 71u8, 85u8, 0u8, 70u8, 77u8, 0u8, 82u8, 85u8, 0u8, 85u8, 83u8,
- 0u8, 67u8, 65u8, 0u8, 85u8, 83u8, 0u8, 85u8, 83u8, 0u8, 75u8, 72u8, 0u8,
- 86u8, 78u8, 0u8, 73u8, 81u8, 0u8, 67u8, 65u8, 0u8, 77u8, 78u8, 0u8, 70u8,
- 82u8, 0u8, 69u8, 71u8, 0u8, 80u8, 72u8, 0u8, 67u8, 65u8, 0u8, 67u8, 65u8,
- 0u8, 85u8, 65u8, 0u8, 67u8, 65u8, 0u8, 67u8, 65u8, 0u8, 83u8, 67u8, 0u8,
- 67u8, 90u8, 0u8, 80u8, 76u8, 0u8, 67u8, 65u8, 0u8, 77u8, 77u8, 0u8, 82u8,
- 85u8, 0u8, 82u8, 85u8, 0u8, 71u8, 66u8, 0u8, 68u8, 75u8, 0u8, 67u8, 73u8,
- 0u8, 85u8, 83u8, 0u8, 82u8, 85u8, 0u8, 75u8, 69u8, 0u8, 73u8, 78u8, 0u8,
- 68u8, 69u8, 0u8, 67u8, 65u8, 0u8, 67u8, 65u8, 0u8, 78u8, 69u8, 0u8, 78u8,
- 71u8, 0u8, 67u8, 73u8, 0u8, 73u8, 78u8, 0u8, 67u8, 78u8, 0u8, 68u8, 69u8,
- 0u8, 77u8, 76u8, 0u8, 77u8, 89u8, 0u8, 78u8, 80u8, 0u8, 67u8, 77u8, 0u8,
- 77u8, 86u8, 0u8, 83u8, 78u8, 0u8, 66u8, 70u8, 0u8, 66u8, 84u8, 0u8, 75u8,
- 69u8, 0u8, 71u8, 72u8, 0u8, 78u8, 71u8, 0u8, 73u8, 84u8, 0u8, 69u8, 71u8,
- 0u8, 77u8, 77u8, 0u8, 71u8, 82u8, 0u8, 85u8, 83u8, 0u8, 48u8, 48u8, 49u8,
- 69u8, 83u8, 0u8, 73u8, 78u8, 0u8, 85u8, 83u8, 0u8, 69u8, 69u8, 0u8, 73u8,
- 84u8, 0u8, 69u8, 83u8, 0u8, 67u8, 77u8, 0u8, 69u8, 83u8, 0u8, 73u8, 82u8,
- 0u8, 71u8, 81u8, 0u8, 83u8, 78u8, 0u8, 77u8, 76u8, 0u8, 70u8, 73u8, 0u8,
- 83u8, 68u8, 0u8, 80u8, 72u8, 0u8, 83u8, 69u8, 0u8, 70u8, 74u8, 0u8, 70u8,
- 79u8, 0u8, 66u8, 74u8, 0u8, 70u8, 82u8, 0u8, 85u8, 83u8, 0u8, 70u8, 82u8,
- 0u8, 68u8, 69u8, 0u8, 68u8, 69u8, 0u8, 67u8, 77u8, 0u8, 87u8, 70u8, 0u8,
- 71u8, 78u8, 0u8, 78u8, 69u8, 0u8, 73u8, 84u8, 0u8, 78u8, 71u8, 0u8, 83u8,
- 68u8, 0u8, 78u8, 76u8, 0u8, 73u8, 69u8, 0u8, 71u8, 72u8, 0u8, 77u8, 68u8,
- 0u8, 67u8, 78u8, 0u8, 73u8, 68u8, 0u8, 73u8, 78u8, 0u8, 73u8, 82u8, 0u8,
- 71u8, 70u8, 0u8, 71u8, 66u8, 0u8, 69u8, 84u8, 0u8, 78u8, 80u8, 0u8, 75u8,
- 73u8, 0u8, 80u8, 75u8, 0u8, 80u8, 75u8, 0u8, 69u8, 83u8, 0u8, 73u8, 82u8,
- 0u8, 80u8, 89u8, 0u8, 73u8, 78u8, 0u8, 73u8, 78u8, 0u8, 73u8, 68u8, 0u8,
- 78u8, 76u8, 0u8, 85u8, 65u8, 0u8, 67u8, 89u8, 0u8, 73u8, 78u8, 0u8, 67u8,
- 72u8, 0u8, 73u8, 78u8, 0u8, 66u8, 82u8, 0u8, 67u8, 79u8, 0u8, 71u8, 72u8,
- 0u8, 75u8, 69u8, 0u8, 73u8, 77u8, 0u8, 78u8, 80u8, 0u8, 67u8, 65u8, 0u8,
- 78u8, 71u8, 0u8, 67u8, 78u8, 0u8, 85u8, 83u8, 0u8, 65u8, 70u8, 0u8, 73u8,
- 76u8, 0u8, 73u8, 78u8, 0u8, 70u8, 74u8, 0u8, 80u8, 72u8, 0u8, 84u8, 82u8,
- 0u8, 67u8, 78u8, 0u8, 80u8, 75u8, 0u8, 73u8, 78u8, 0u8, 85u8, 83u8, 0u8,
- 80u8, 72u8, 0u8, 80u8, 75u8, 0u8, 80u8, 71u8, 0u8, 73u8, 78u8, 0u8, 73u8,
- 78u8, 0u8, 72u8, 82u8, 0u8, 68u8, 69u8, 0u8, 67u8, 78u8, 0u8, 72u8, 84u8,
- 0u8, 72u8, 85u8, 0u8, 67u8, 65u8, 0u8, 65u8, 77u8, 0u8, 78u8, 65u8, 0u8,
- 48u8, 48u8, 49u8, 77u8, 89u8, 0u8, 78u8, 71u8, 0u8, 73u8, 68u8, 0u8, 84u8,
- 71u8, 0u8, 78u8, 71u8, 0u8, 67u8, 78u8, 0u8, 85u8, 83u8, 0u8, 80u8, 72u8,
- 0u8, 73u8, 68u8, 0u8, 82u8, 85u8, 0u8, 48u8, 48u8, 49u8, 73u8, 83u8, 0u8,
- 73u8, 84u8, 0u8, 67u8, 65u8, 0u8, 73u8, 76u8, 0u8, 82u8, 85u8, 0u8, 74u8,
- 80u8, 0u8, 74u8, 77u8, 0u8, 48u8, 48u8, 49u8, 67u8, 77u8, 0u8, 85u8, 65u8,
- 0u8, 84u8, 90u8, 0u8, 78u8, 80u8, 0u8, 68u8, 75u8, 0u8, 73u8, 68u8, 0u8,
- 73u8, 68u8, 0u8, 71u8, 69u8, 0u8, 85u8, 90u8, 0u8, 68u8, 90u8, 0u8, 77u8,
- 77u8, 0u8, 78u8, 71u8, 0u8, 75u8, 69u8, 0u8, 77u8, 76u8, 0u8, 73u8, 68u8,
- 0u8, 82u8, 85u8, 0u8, 78u8, 69u8, 0u8, 78u8, 71u8, 0u8, 90u8, 87u8, 0u8,
- 84u8, 90u8, 0u8, 84u8, 71u8, 0u8, 84u8, 72u8, 0u8, 67u8, 86u8, 0u8, 67u8,
- 77u8, 0u8, 67u8, 73u8, 0u8, 73u8, 78u8, 0u8, 73u8, 78u8, 0u8, 67u8, 68u8,
- 0u8, 73u8, 68u8, 0u8, 66u8, 82u8, 0u8, 73u8, 78u8, 0u8, 67u8, 78u8, 0u8,
- 73u8, 78u8, 0u8, 77u8, 76u8, 0u8, 73u8, 78u8, 0u8, 80u8, 75u8, 0u8, 75u8,
- 69u8, 0u8, 84u8, 82u8, 0u8, 78u8, 65u8, 0u8, 76u8, 65u8, 0u8, 75u8, 90u8,
- 0u8, 67u8, 77u8, 0u8, 71u8, 76u8, 0u8, 75u8, 69u8, 0u8, 75u8, 72u8, 0u8,
- 65u8, 79u8, 0u8, 73u8, 78u8, 0u8, 71u8, 87u8, 0u8, 75u8, 82u8, 0u8, 82u8,
- 85u8, 0u8, 73u8, 78u8, 0u8, 70u8, 77u8, 0u8, 76u8, 82u8, 0u8, 82u8, 85u8,
- 0u8, 83u8, 76u8, 0u8, 80u8, 72u8, 0u8, 82u8, 85u8, 0u8, 73u8, 78u8, 0u8,
- 73u8, 78u8, 0u8, 84u8, 90u8, 0u8, 67u8, 77u8, 0u8, 68u8, 69u8, 0u8, 77u8,
- 89u8, 0u8, 84u8, 82u8, 0u8, 82u8, 85u8, 0u8, 82u8, 85u8, 0u8, 73u8, 68u8,
- 0u8, 80u8, 75u8, 0u8, 71u8, 66u8, 0u8, 67u8, 65u8, 0u8, 73u8, 78u8, 0u8,
- 84u8, 72u8, 0u8, 80u8, 75u8, 0u8, 75u8, 71u8, 0u8, 77u8, 89u8, 0u8, 77u8,
- 89u8, 0u8, 86u8, 65u8, 0u8, 71u8, 82u8, 0u8, 73u8, 76u8, 0u8, 84u8, 90u8,
- 0u8, 80u8, 75u8, 0u8, 85u8, 71u8, 0u8, 76u8, 85u8, 0u8, 82u8, 85u8, 0u8,
- 73u8, 68u8, 0u8, 67u8, 78u8, 0u8, 73u8, 78u8, 0u8, 82u8, 85u8, 0u8, 85u8,
- 71u8, 0u8, 78u8, 76u8, 0u8, 78u8, 80u8, 0u8, 73u8, 84u8, 0u8, 67u8, 65u8,
- 0u8, 67u8, 78u8, 0u8, 73u8, 68u8, 0u8, 73u8, 82u8, 0u8, 85u8, 83u8, 0u8,
- 73u8, 78u8, 0u8, 73u8, 84u8, 0u8, 67u8, 68u8, 0u8, 76u8, 65u8, 0u8, 67u8,
- 68u8, 0u8, 90u8, 77u8, 0u8, 73u8, 82u8, 0u8, 76u8, 84u8, 0u8, 76u8, 86u8,
- 0u8, 67u8, 68u8, 0u8, 67u8, 68u8, 0u8, 75u8, 69u8, 0u8, 75u8, 69u8, 0u8,
- 73u8, 82u8, 0u8, 76u8, 86u8, 0u8, 84u8, 72u8, 0u8, 67u8, 78u8, 0u8, 84u8,
- 82u8, 0u8, 73u8, 68u8, 0u8, 67u8, 77u8, 0u8, 73u8, 78u8, 0u8, 73u8, 78u8,
- 0u8, 73u8, 68u8, 0u8, 71u8, 77u8, 0u8, 75u8, 69u8, 0u8, 77u8, 88u8, 0u8,
- 82u8, 85u8, 0u8, 80u8, 72u8, 0u8, 73u8, 68u8, 0u8, 83u8, 76u8, 0u8, 75u8,
- 69u8, 0u8, 84u8, 72u8, 0u8, 77u8, 85u8, 0u8, 77u8, 71u8, 0u8, 77u8, 90u8,
- 0u8, 67u8, 77u8, 0u8, 78u8, 80u8, 0u8, 84u8, 90u8, 0u8, 77u8, 72u8, 0u8,
- 78u8, 90u8, 0u8, 67u8, 65u8, 0u8, 73u8, 68u8, 0u8, 77u8, 75u8, 0u8, 73u8,
- 78u8, 0u8, 83u8, 68u8, 0u8, 77u8, 78u8, 0u8, 73u8, 78u8, 0u8, 77u8, 77u8,
- 0u8, 82u8, 79u8, 0u8, 67u8, 65u8, 0u8, 67u8, 65u8, 0u8, 66u8, 70u8, 0u8,
- 73u8, 78u8, 0u8, 78u8, 80u8, 0u8, 82u8, 85u8, 0u8, 66u8, 68u8, 0u8, 77u8,
- 89u8, 0u8, 77u8, 84u8, 0u8, 73u8, 78u8, 0u8, 67u8, 77u8, 0u8, 85u8, 83u8,
- 0u8, 80u8, 75u8, 0u8, 77u8, 76u8, 0u8, 73u8, 78u8, 0u8, 73u8, 68u8, 0u8,
- 85u8, 83u8, 0u8, 90u8, 87u8, 0u8, 77u8, 77u8, 0u8, 82u8, 85u8, 0u8, 85u8,
- 71u8, 0u8, 73u8, 82u8, 0u8, 73u8, 82u8, 0u8, 78u8, 82u8, 0u8, 67u8, 78u8,
- 0u8, 73u8, 84u8, 0u8, 78u8, 65u8, 0u8, 78u8, 79u8, 0u8, 77u8, 88u8, 0u8,
- 90u8, 87u8, 0u8, 77u8, 90u8, 0u8, 68u8, 69u8, 0u8, 78u8, 80u8, 0u8, 78u8,
- 80u8, 0u8, 78u8, 65u8, 0u8, 77u8, 90u8, 0u8, 77u8, 88u8, 0u8, 77u8, 88u8,
- 0u8, 73u8, 68u8, 0u8, 78u8, 85u8, 0u8, 73u8, 78u8, 0u8, 78u8, 76u8, 0u8,
- 67u8, 77u8, 0u8, 78u8, 79u8, 0u8, 67u8, 77u8, 0u8, 73u8, 78u8, 0u8, 78u8,
- 79u8, 0u8, 84u8, 72u8, 0u8, 73u8, 78u8, 0u8, 83u8, 69u8, 0u8, 71u8, 78u8,
- 0u8, 90u8, 65u8, 0u8, 67u8, 65u8, 0u8, 90u8, 65u8, 0u8, 73u8, 78u8, 0u8,
- 83u8, 83u8, 0u8, 85u8, 83u8, 0u8, 67u8, 78u8, 0u8, 77u8, 87u8, 0u8, 84u8,
- 90u8, 0u8, 85u8, 71u8, 0u8, 71u8, 72u8, 0u8, 70u8, 82u8, 0u8, 67u8, 65u8,
- 0u8, 67u8, 65u8, 0u8, 67u8, 65u8, 0u8, 69u8, 84u8, 0u8, 73u8, 78u8, 0u8,
- 71u8, 69u8, 0u8, 85u8, 83u8, 0u8, 77u8, 78u8, 0u8, 49u8, 52u8, 51u8, 73u8,
- 78u8, 0u8, 80u8, 72u8, 0u8, 73u8, 82u8, 0u8, 80u8, 72u8, 0u8, 65u8, 87u8,
- 0u8, 80u8, 87u8, 0u8, 70u8, 82u8, 0u8, 78u8, 71u8, 0u8, 85u8, 83u8, 0u8,
- 67u8, 65u8, 0u8, 73u8, 82u8, 0u8, 68u8, 69u8, 0u8, 76u8, 66u8, 0u8, 83u8,
- 66u8, 0u8, 73u8, 78u8, 0u8, 75u8, 69u8, 0u8, 80u8, 76u8, 0u8, 73u8, 84u8,
- 0u8, 71u8, 82u8, 0u8, 70u8, 77u8, 0u8, 73u8, 78u8, 0u8, 67u8, 65u8, 0u8,
- 80u8, 75u8, 0u8, 73u8, 82u8, 0u8, 48u8, 48u8, 49u8, 65u8, 70u8, 0u8, 66u8,
- 82u8, 0u8, 71u8, 65u8, 0u8, 80u8, 69u8, 0u8, 71u8, 84u8, 0u8, 69u8, 67u8,
- 0u8, 73u8, 78u8, 0u8, 82u8, 69u8, 0u8, 73u8, 68u8, 0u8, 73u8, 84u8, 0u8,
- 77u8, 77u8, 0u8, 73u8, 78u8, 0u8, 77u8, 65u8, 0u8, 78u8, 80u8, 0u8, 66u8,
- 68u8, 0u8, 67u8, 72u8, 0u8, 70u8, 73u8, 0u8, 67u8, 72u8, 0u8, 73u8, 82u8,
- 0u8, 83u8, 69u8, 0u8, 66u8, 73u8, 0u8, 77u8, 90u8, 0u8, 82u8, 79u8, 0u8,
- 73u8, 68u8, 0u8, 84u8, 90u8, 0u8, 70u8, 74u8, 0u8, 82u8, 85u8, 0u8, 85u8,
- 65u8, 0u8, 83u8, 66u8, 0u8, 82u8, 87u8, 0u8, 84u8, 90u8, 0u8, 74u8, 80u8,
- 0u8, 73u8, 78u8, 0u8, 71u8, 72u8, 0u8, 82u8, 85u8, 0u8, 75u8, 69u8, 0u8,
- 73u8, 68u8, 0u8, 73u8, 78u8, 0u8, 83u8, 78u8, 0u8, 73u8, 78u8, 0u8, 84u8,
- 90u8, 0u8, 73u8, 84u8, 0u8, 73u8, 78u8, 0u8, 73u8, 84u8, 0u8, 71u8, 66u8,
- 0u8, 80u8, 75u8, 0u8, 73u8, 84u8, 0u8, 73u8, 82u8, 0u8, 78u8, 79u8, 0u8,
- 67u8, 73u8, 0u8, 77u8, 90u8, 0u8, 77u8, 88u8, 0u8, 77u8, 76u8, 0u8, 67u8,
- 70u8, 0u8, 73u8, 69u8, 0u8, 76u8, 84u8, 0u8, 77u8, 65u8, 0u8, 77u8, 77u8,
- 0u8, 76u8, 75u8, 0u8, 69u8, 84u8, 0u8, 83u8, 75u8, 0u8, 80u8, 75u8, 0u8,
- 83u8, 73u8, 0u8, 80u8, 76u8, 0u8, 73u8, 68u8, 0u8, 87u8, 83u8, 0u8, 83u8,
- 69u8, 0u8, 65u8, 79u8, 0u8, 83u8, 69u8, 0u8, 70u8, 73u8, 0u8, 73u8, 76u8,
- 0u8, 70u8, 73u8, 0u8, 90u8, 87u8, 0u8, 77u8, 89u8, 0u8, 77u8, 76u8, 0u8,
- 83u8, 79u8, 0u8, 85u8, 90u8, 0u8, 84u8, 72u8, 0u8, 65u8, 76u8, 0u8, 82u8,
- 83u8, 0u8, 73u8, 78u8, 0u8, 83u8, 82u8, 0u8, 83u8, 78u8, 0u8, 73u8, 78u8,
- 0u8, 90u8, 65u8, 0u8, 69u8, 82u8, 0u8, 90u8, 65u8, 0u8, 68u8, 69u8, 0u8,
- 73u8, 68u8, 0u8, 84u8, 90u8, 0u8, 71u8, 78u8, 0u8, 83u8, 69u8, 0u8, 84u8,
- 90u8, 0u8, 89u8, 84u8, 0u8, 67u8, 68u8, 0u8, 68u8, 69u8, 0u8, 73u8, 78u8,
- 0u8, 73u8, 68u8, 0u8, 66u8, 68u8, 0u8, 73u8, 81u8, 0u8, 80u8, 76u8, 0u8,
- 73u8, 78u8, 0u8, 78u8, 80u8, 0u8, 80u8, 72u8, 0u8, 73u8, 78u8, 0u8, 67u8,
- 78u8, 0u8, 78u8, 80u8, 0u8, 78u8, 80u8, 0u8, 77u8, 89u8, 0u8, 73u8, 78u8,
- 0u8, 83u8, 76u8, 0u8, 85u8, 71u8, 0u8, 84u8, 76u8, 0u8, 84u8, 74u8, 0u8,
- 84u8, 72u8, 0u8, 78u8, 80u8, 0u8, 78u8, 80u8, 0u8, 78u8, 80u8, 0u8, 69u8,
- 84u8, 0u8, 69u8, 82u8, 0u8, 78u8, 71u8, 0u8, 84u8, 77u8, 0u8, 84u8, 75u8,
- 0u8, 65u8, 90u8, 0u8, 78u8, 80u8, 0u8, 80u8, 72u8, 0u8, 65u8, 90u8, 0u8,
- 78u8, 69u8, 0u8, 90u8, 65u8, 0u8, 84u8, 79u8, 0u8, 77u8, 87u8, 0u8, 48u8,
- 48u8, 49u8, 80u8, 71u8, 0u8, 84u8, 82u8, 0u8, 84u8, 82u8, 0u8, 84u8, 87u8,
- 0u8, 80u8, 75u8, 0u8, 90u8, 65u8, 0u8, 71u8, 82u8, 0u8, 78u8, 80u8, 0u8,
- 80u8, 72u8, 0u8, 66u8, 84u8, 0u8, 82u8, 85u8, 0u8, 85u8, 71u8, 0u8, 84u8,
- 72u8, 0u8, 65u8, 90u8, 0u8, 77u8, 87u8, 0u8, 84u8, 86u8, 0u8, 78u8, 69u8,
- 0u8, 67u8, 78u8, 0u8, 73u8, 78u8, 0u8, 80u8, 70u8, 0u8, 82u8, 85u8, 0u8,
- 77u8, 65u8, 0u8, 82u8, 85u8, 0u8, 82u8, 85u8, 0u8, 67u8, 78u8, 0u8, 83u8,
- 89u8, 0u8, 85u8, 65u8, 0u8, 70u8, 77u8, 0u8, 65u8, 79u8, 0u8, 73u8, 78u8,
- 0u8, 73u8, 78u8, 0u8, 80u8, 75u8, 0u8, 85u8, 90u8, 0u8, 76u8, 82u8, 0u8,
- 90u8, 65u8, 0u8, 73u8, 84u8, 0u8, 82u8, 85u8, 0u8, 86u8, 78u8, 0u8, 83u8,
- 88u8, 0u8, 66u8, 69u8, 0u8, 68u8, 69u8, 0u8, 77u8, 90u8, 0u8, 48u8, 48u8,
- 49u8, 82u8, 85u8, 0u8, 69u8, 69u8, 0u8, 84u8, 90u8, 0u8, 66u8, 69u8, 0u8,
- 67u8, 72u8, 0u8, 69u8, 84u8, 0u8, 80u8, 72u8, 0u8, 65u8, 85u8, 0u8, 73u8,
- 78u8, 0u8, 73u8, 78u8, 0u8, 87u8, 70u8, 0u8, 75u8, 77u8, 0u8, 83u8, 78u8,
- 0u8, 73u8, 78u8, 0u8, 73u8, 78u8, 0u8, 67u8, 78u8, 0u8, 66u8, 82u8, 0u8,
- 85u8, 90u8, 0u8, 84u8, 82u8, 0u8, 90u8, 65u8, 0u8, 84u8, 82u8, 0u8, 84u8,
- 82u8, 0u8, 71u8, 69u8, 0u8, 67u8, 78u8, 0u8, 83u8, 68u8, 0u8, 83u8, 65u8,
- 0u8, 73u8, 78u8, 0u8, 85u8, 71u8, 0u8, 73u8, 82u8, 0u8, 89u8, 69u8, 0u8,
- 78u8, 80u8, 0u8, 77u8, 90u8, 0u8, 70u8, 77u8, 0u8, 67u8, 77u8, 0u8, 67u8,
- 77u8, 0u8, 48u8, 48u8, 49u8, 78u8, 71u8, 0u8, 66u8, 82u8, 0u8, 77u8, 88u8,
- 0u8, 72u8, 75u8, 0u8, 67u8, 78u8, 0u8, 83u8, 68u8, 0u8, 75u8, 77u8, 0u8,
- 78u8, 76u8, 0u8, 77u8, 65u8, 0u8, 67u8, 78u8, 0u8, 67u8, 78u8, 0u8, 67u8,
- 78u8, 0u8, 84u8, 71u8, 0u8, 77u8, 89u8, 0u8, 90u8, 65u8, 0u8, 84u8, 82u8,
- 0u8,
- ])
- },
- )
- },
- ls2r: unsafe {
- #[allow(unused_unsafe)]
- ::zerovec::ZeroMap2d::from_parts_unchecked(
- unsafe {
- ::zerovec::ZeroVec::from_bytes_unchecked(&[
- 97u8, 114u8, 99u8, 97u8, 122u8, 0u8, 99u8, 117u8, 0u8, 101u8, 110u8, 0u8,
- 102u8, 102u8, 0u8, 103u8, 114u8, 99u8, 107u8, 107u8, 0u8, 107u8, 117u8,
- 0u8, 107u8, 121u8, 0u8, 108u8, 105u8, 102u8, 109u8, 97u8, 110u8, 109u8,
- 110u8, 0u8, 112u8, 97u8, 0u8, 112u8, 97u8, 108u8, 115u8, 100u8, 0u8, 116u8,
- 103u8, 0u8, 117u8, 103u8, 0u8, 117u8, 110u8, 114u8, 117u8, 122u8, 0u8,
- 121u8, 117u8, 101u8, 122u8, 104u8, 0u8,
- ])
- },
- unsafe {
- ::zerovec::ZeroVec::from_bytes_unchecked(&[
- 2u8, 0u8, 0u8, 0u8, 3u8, 0u8, 0u8, 0u8, 4u8, 0u8, 0u8, 0u8, 5u8, 0u8, 0u8,
- 0u8, 6u8, 0u8, 0u8, 0u8, 7u8, 0u8, 0u8, 0u8, 8u8, 0u8, 0u8, 0u8, 10u8, 0u8,
- 0u8, 0u8, 12u8, 0u8, 0u8, 0u8, 13u8, 0u8, 0u8, 0u8, 14u8, 0u8, 0u8, 0u8,
- 15u8, 0u8, 0u8, 0u8, 16u8, 0u8, 0u8, 0u8, 17u8, 0u8, 0u8, 0u8, 20u8, 0u8,
- 0u8, 0u8, 21u8, 0u8, 0u8, 0u8, 22u8, 0u8, 0u8, 0u8, 23u8, 0u8, 0u8, 0u8,
- 24u8, 0u8, 0u8, 0u8, 25u8, 0u8, 0u8, 0u8, 28u8, 0u8, 0u8, 0u8,
- ])
- },
- unsafe {
- ::zerovec::ZeroVec::from_bytes_unchecked(&[
- 78u8, 98u8, 97u8, 116u8, 80u8, 97u8, 108u8, 109u8, 65u8, 114u8, 97u8, 98u8,
- 71u8, 108u8, 97u8, 103u8, 83u8, 104u8, 97u8, 119u8, 65u8, 100u8, 108u8,
- 109u8, 76u8, 105u8, 110u8, 98u8, 65u8, 114u8, 97u8, 98u8, 65u8, 114u8,
- 97u8, 98u8, 89u8, 101u8, 122u8, 105u8, 65u8, 114u8, 97u8, 98u8, 76u8, 97u8,
- 116u8, 110u8, 76u8, 105u8, 109u8, 98u8, 78u8, 107u8, 111u8, 111u8, 77u8,
- 111u8, 110u8, 103u8, 65u8, 114u8, 97u8, 98u8, 80u8, 104u8, 108u8, 112u8,
- 68u8, 101u8, 118u8, 97u8, 75u8, 104u8, 111u8, 106u8, 83u8, 105u8, 110u8,
- 100u8, 65u8, 114u8, 97u8, 98u8, 67u8, 121u8, 114u8, 108u8, 68u8, 101u8,
- 118u8, 97u8, 65u8, 114u8, 97u8, 98u8, 72u8, 97u8, 110u8, 115u8, 66u8,
- 111u8, 112u8, 111u8, 72u8, 97u8, 110u8, 98u8, 72u8, 97u8, 110u8, 116u8,
- ])
- },
- unsafe {
- ::zerovec::ZeroVec::from_bytes_unchecked(&[
- 74u8, 79u8, 0u8, 83u8, 89u8, 0u8, 73u8, 82u8, 0u8, 66u8, 71u8, 0u8, 71u8,
- 66u8, 0u8, 71u8, 78u8, 0u8, 71u8, 82u8, 0u8, 67u8, 78u8, 0u8, 73u8, 81u8,
- 0u8, 71u8, 69u8, 0u8, 67u8, 78u8, 0u8, 84u8, 82u8, 0u8, 73u8, 78u8, 0u8,
- 71u8, 78u8, 0u8, 67u8, 78u8, 0u8, 80u8, 75u8, 0u8, 67u8, 78u8, 0u8, 73u8,
- 78u8, 0u8, 73u8, 78u8, 0u8, 73u8, 78u8, 0u8, 80u8, 75u8, 0u8, 75u8, 90u8,
- 0u8, 78u8, 80u8, 0u8, 65u8, 70u8, 0u8, 67u8, 78u8, 0u8, 84u8, 87u8, 0u8,
- 84u8, 87u8, 0u8, 84u8, 87u8, 0u8,
- ])
- },
- )
- },
- };
diff --git a/compiler/rustc_baked_icu_data/src/data/fallback/likelysubtags_v1/mod.rs b/compiler/rustc_baked_icu_data/src/data/fallback/likelysubtags_v1/mod.rs
new file mode 100644
index 000000000..57f7496dc
--- /dev/null
+++ b/compiler/rustc_baked_icu_data/src/data/fallback/likelysubtags_v1/mod.rs
@@ -0,0 +1,6 @@
+// @generated
+type DataStruct = < :: icu_provider_adapters :: fallback :: provider :: LocaleFallbackLikelySubtagsV1Marker as :: icu_provider :: DataMarker > :: Yokeable ;
+pub fn lookup(locale: &icu_provider::DataLocale) -> Option<&'static DataStruct> {
+ locale.is_empty().then(|| &UND)
+}
+static UND: DataStruct = include!("und.rs.data");
diff --git a/compiler/rustc_baked_icu_data/src/data/fallback/likelysubtags_v1/und.rs.data b/compiler/rustc_baked_icu_data/src/data/fallback/likelysubtags_v1/und.rs.data
new file mode 100644
index 000000000..4fd177834
--- /dev/null
+++ b/compiler/rustc_baked_icu_data/src/data/fallback/likelysubtags_v1/und.rs.data
@@ -0,0 +1,728 @@
+::icu_provider_adapters::fallback::provider::LocaleFallbackLikelySubtagsV1 {
+ l2s: unsafe {
+ #[allow(unused_unsafe)]
+ ::zerovec::ZeroMap::from_parts_unchecked(
+ unsafe {
+ ::zerovec::ZeroVec::from_bytes_unchecked(&[
+ 97u8, 98u8, 0u8, 97u8, 98u8, 113u8, 97u8, 100u8, 112u8, 97u8, 100u8, 121u8,
+ 97u8, 101u8, 0u8, 97u8, 101u8, 98u8, 97u8, 104u8, 111u8, 97u8, 106u8,
+ 116u8, 97u8, 107u8, 107u8, 97u8, 108u8, 116u8, 97u8, 109u8, 0u8, 97u8,
+ 112u8, 99u8, 97u8, 112u8, 100u8, 97u8, 114u8, 0u8, 97u8, 114u8, 99u8, 97u8,
+ 114u8, 113u8, 97u8, 114u8, 115u8, 97u8, 114u8, 121u8, 97u8, 114u8, 122u8,
+ 97u8, 115u8, 0u8, 97u8, 115u8, 101u8, 97u8, 118u8, 0u8, 97u8, 118u8, 108u8,
+ 97u8, 119u8, 97u8, 98u8, 97u8, 0u8, 98u8, 97u8, 108u8, 98u8, 97u8, 112u8,
+ 98u8, 97u8, 120u8, 98u8, 99u8, 113u8, 98u8, 101u8, 0u8, 98u8, 101u8, 106u8,
+ 98u8, 102u8, 113u8, 98u8, 102u8, 116u8, 98u8, 102u8, 121u8, 98u8, 103u8,
+ 0u8, 98u8, 103u8, 99u8, 98u8, 103u8, 110u8, 98u8, 103u8, 120u8, 98u8,
+ 104u8, 98u8, 98u8, 104u8, 105u8, 98u8, 104u8, 111u8, 98u8, 106u8, 105u8,
+ 98u8, 106u8, 106u8, 98u8, 108u8, 116u8, 98u8, 110u8, 0u8, 98u8, 111u8, 0u8,
+ 98u8, 112u8, 121u8, 98u8, 113u8, 105u8, 98u8, 114u8, 97u8, 98u8, 114u8,
+ 104u8, 98u8, 114u8, 120u8, 98u8, 115u8, 113u8, 98u8, 115u8, 116u8, 98u8,
+ 116u8, 118u8, 98u8, 117u8, 97u8, 98u8, 121u8, 110u8, 99u8, 99u8, 112u8,
+ 99u8, 101u8, 0u8, 99u8, 104u8, 109u8, 99u8, 104u8, 114u8, 99u8, 106u8,
+ 97u8, 99u8, 106u8, 109u8, 99u8, 107u8, 98u8, 99u8, 109u8, 103u8, 99u8,
+ 111u8, 112u8, 99u8, 114u8, 0u8, 99u8, 114u8, 104u8, 99u8, 114u8, 107u8,
+ 99u8, 114u8, 108u8, 99u8, 115u8, 119u8, 99u8, 116u8, 100u8, 99u8, 117u8,
+ 0u8, 99u8, 118u8, 0u8, 100u8, 97u8, 114u8, 100u8, 99u8, 99u8, 100u8, 103u8,
+ 108u8, 100u8, 109u8, 102u8, 100u8, 111u8, 105u8, 100u8, 114u8, 104u8,
+ 100u8, 114u8, 115u8, 100u8, 116u8, 121u8, 100u8, 118u8, 0u8, 100u8, 122u8,
+ 0u8, 101u8, 103u8, 121u8, 101u8, 107u8, 121u8, 101u8, 108u8, 0u8, 101u8,
+ 115u8, 103u8, 101u8, 116u8, 116u8, 102u8, 97u8, 0u8, 102u8, 105u8, 97u8,
+ 102u8, 117u8, 98u8, 103u8, 97u8, 110u8, 103u8, 98u8, 109u8, 103u8, 98u8,
+ 122u8, 103u8, 101u8, 122u8, 103u8, 103u8, 110u8, 103u8, 106u8, 107u8,
+ 103u8, 106u8, 117u8, 103u8, 108u8, 107u8, 103u8, 109u8, 118u8, 103u8,
+ 111u8, 102u8, 103u8, 111u8, 109u8, 103u8, 111u8, 110u8, 103u8, 111u8,
+ 116u8, 103u8, 114u8, 99u8, 103u8, 114u8, 116u8, 103u8, 117u8, 0u8, 103u8,
+ 118u8, 114u8, 103u8, 119u8, 99u8, 103u8, 119u8, 116u8, 104u8, 97u8, 107u8,
+ 104u8, 97u8, 122u8, 104u8, 100u8, 121u8, 104u8, 101u8, 0u8, 104u8, 105u8,
+ 0u8, 104u8, 108u8, 117u8, 104u8, 109u8, 100u8, 104u8, 110u8, 100u8, 104u8,
+ 110u8, 101u8, 104u8, 110u8, 106u8, 104u8, 110u8, 111u8, 104u8, 111u8, 99u8,
+ 104u8, 111u8, 106u8, 104u8, 115u8, 110u8, 104u8, 121u8, 0u8, 105u8, 105u8,
+ 0u8, 105u8, 110u8, 104u8, 105u8, 117u8, 0u8, 105u8, 119u8, 0u8, 106u8,
+ 97u8, 0u8, 106u8, 105u8, 0u8, 106u8, 109u8, 108u8, 107u8, 97u8, 0u8, 107u8,
+ 97u8, 97u8, 107u8, 97u8, 119u8, 107u8, 98u8, 100u8, 107u8, 98u8, 121u8,
+ 107u8, 100u8, 116u8, 107u8, 102u8, 114u8, 107u8, 102u8, 121u8, 107u8,
+ 104u8, 98u8, 107u8, 104u8, 110u8, 107u8, 104u8, 116u8, 107u8, 104u8, 119u8,
+ 107u8, 106u8, 103u8, 107u8, 107u8, 0u8, 107u8, 109u8, 0u8, 107u8, 110u8,
+ 0u8, 107u8, 111u8, 0u8, 107u8, 111u8, 105u8, 107u8, 111u8, 107u8, 107u8,
+ 113u8, 121u8, 107u8, 114u8, 99u8, 107u8, 114u8, 117u8, 107u8, 115u8, 0u8,
+ 107u8, 116u8, 98u8, 107u8, 117u8, 109u8, 107u8, 118u8, 0u8, 107u8, 118u8,
+ 120u8, 107u8, 120u8, 99u8, 107u8, 120u8, 108u8, 107u8, 120u8, 109u8, 107u8,
+ 120u8, 112u8, 107u8, 121u8, 0u8, 107u8, 122u8, 104u8, 108u8, 97u8, 98u8,
+ 108u8, 97u8, 100u8, 108u8, 97u8, 104u8, 108u8, 98u8, 101u8, 108u8, 99u8,
+ 112u8, 108u8, 101u8, 112u8, 108u8, 101u8, 122u8, 108u8, 105u8, 102u8,
+ 108u8, 105u8, 115u8, 108u8, 107u8, 105u8, 108u8, 109u8, 110u8, 108u8,
+ 111u8, 0u8, 108u8, 114u8, 99u8, 108u8, 117u8, 122u8, 108u8, 119u8, 108u8,
+ 108u8, 122u8, 104u8, 109u8, 97u8, 103u8, 109u8, 97u8, 105u8, 109u8, 100u8,
+ 101u8, 109u8, 100u8, 102u8, 109u8, 100u8, 120u8, 109u8, 102u8, 97u8, 109u8,
+ 103u8, 112u8, 109u8, 107u8, 0u8, 109u8, 107u8, 105u8, 109u8, 108u8, 0u8,
+ 109u8, 110u8, 0u8, 109u8, 110u8, 105u8, 109u8, 110u8, 119u8, 109u8, 114u8,
+ 0u8, 109u8, 114u8, 100u8, 109u8, 114u8, 106u8, 109u8, 114u8, 111u8, 109u8,
+ 116u8, 114u8, 109u8, 118u8, 121u8, 109u8, 119u8, 114u8, 109u8, 119u8,
+ 119u8, 109u8, 121u8, 0u8, 109u8, 121u8, 109u8, 109u8, 121u8, 118u8, 109u8,
+ 121u8, 122u8, 109u8, 122u8, 110u8, 110u8, 97u8, 110u8, 110u8, 101u8, 0u8,
+ 110u8, 101u8, 119u8, 110u8, 110u8, 112u8, 110u8, 111u8, 100u8, 110u8,
+ 111u8, 101u8, 110u8, 111u8, 110u8, 110u8, 113u8, 111u8, 110u8, 115u8,
+ 107u8, 110u8, 115u8, 116u8, 111u8, 106u8, 0u8, 111u8, 106u8, 115u8, 111u8,
+ 114u8, 0u8, 111u8, 114u8, 117u8, 111u8, 115u8, 0u8, 111u8, 115u8, 97u8,
+ 111u8, 116u8, 97u8, 111u8, 116u8, 107u8, 111u8, 117u8, 105u8, 112u8, 97u8,
+ 0u8, 112u8, 97u8, 108u8, 112u8, 101u8, 111u8, 112u8, 104u8, 108u8, 112u8,
+ 104u8, 110u8, 112u8, 107u8, 97u8, 112u8, 110u8, 116u8, 112u8, 112u8, 97u8,
+ 112u8, 114u8, 97u8, 112u8, 114u8, 100u8, 112u8, 115u8, 0u8, 114u8, 97u8,
+ 106u8, 114u8, 104u8, 103u8, 114u8, 105u8, 102u8, 114u8, 106u8, 115u8,
+ 114u8, 107u8, 116u8, 114u8, 109u8, 116u8, 114u8, 117u8, 0u8, 114u8, 117u8,
+ 101u8, 114u8, 121u8, 117u8, 115u8, 97u8, 0u8, 115u8, 97u8, 104u8, 115u8,
+ 97u8, 116u8, 115u8, 97u8, 122u8, 115u8, 99u8, 107u8, 115u8, 99u8, 108u8,
+ 115u8, 100u8, 0u8, 115u8, 100u8, 104u8, 115u8, 103u8, 97u8, 115u8, 103u8,
+ 119u8, 115u8, 104u8, 105u8, 115u8, 104u8, 110u8, 115u8, 104u8, 117u8,
+ 115u8, 105u8, 0u8, 115u8, 107u8, 114u8, 115u8, 109u8, 112u8, 115u8, 111u8,
+ 103u8, 115u8, 111u8, 117u8, 115u8, 114u8, 0u8, 115u8, 114u8, 98u8, 115u8,
+ 114u8, 120u8, 115u8, 119u8, 98u8, 115u8, 119u8, 118u8, 115u8, 121u8, 108u8,
+ 115u8, 121u8, 114u8, 116u8, 97u8, 0u8, 116u8, 97u8, 106u8, 116u8, 99u8,
+ 121u8, 116u8, 100u8, 100u8, 116u8, 100u8, 103u8, 116u8, 100u8, 104u8,
+ 116u8, 101u8, 0u8, 116u8, 103u8, 0u8, 116u8, 104u8, 0u8, 116u8, 104u8,
+ 108u8, 116u8, 104u8, 113u8, 116u8, 104u8, 114u8, 116u8, 105u8, 0u8, 116u8,
+ 105u8, 103u8, 116u8, 107u8, 116u8, 116u8, 114u8, 119u8, 116u8, 115u8,
+ 100u8, 116u8, 115u8, 102u8, 116u8, 115u8, 106u8, 116u8, 116u8, 0u8, 116u8,
+ 116u8, 115u8, 116u8, 120u8, 103u8, 116u8, 120u8, 111u8, 116u8, 121u8,
+ 118u8, 117u8, 100u8, 105u8, 117u8, 100u8, 109u8, 117u8, 103u8, 0u8, 117u8,
+ 103u8, 97u8, 117u8, 107u8, 0u8, 117u8, 110u8, 114u8, 117u8, 110u8, 120u8,
+ 117u8, 114u8, 0u8, 118u8, 97u8, 105u8, 119u8, 97u8, 108u8, 119u8, 98u8,
+ 113u8, 119u8, 98u8, 114u8, 119u8, 110u8, 105u8, 119u8, 115u8, 103u8, 119u8,
+ 116u8, 109u8, 119u8, 117u8, 117u8, 120u8, 99u8, 111u8, 120u8, 99u8, 114u8,
+ 120u8, 108u8, 99u8, 120u8, 108u8, 100u8, 120u8, 109u8, 102u8, 120u8, 109u8,
+ 110u8, 120u8, 109u8, 114u8, 120u8, 110u8, 97u8, 120u8, 110u8, 114u8, 120u8,
+ 112u8, 114u8, 120u8, 115u8, 97u8, 120u8, 115u8, 114u8, 121u8, 105u8, 0u8,
+ 121u8, 117u8, 101u8, 122u8, 100u8, 106u8, 122u8, 103u8, 104u8, 122u8,
+ 104u8, 0u8, 122u8, 104u8, 120u8, 122u8, 107u8, 116u8,
+ ])
+ },
+ unsafe {
+ ::zerovec::ZeroVec::from_bytes_unchecked(&[
+ 67u8, 121u8, 114u8, 108u8, 67u8, 121u8, 114u8, 108u8, 84u8, 105u8, 98u8,
+ 116u8, 67u8, 121u8, 114u8, 108u8, 65u8, 118u8, 115u8, 116u8, 65u8, 114u8,
+ 97u8, 98u8, 65u8, 104u8, 111u8, 109u8, 65u8, 114u8, 97u8, 98u8, 88u8,
+ 115u8, 117u8, 120u8, 67u8, 121u8, 114u8, 108u8, 69u8, 116u8, 104u8, 105u8,
+ 65u8, 114u8, 97u8, 98u8, 65u8, 114u8, 97u8, 98u8, 65u8, 114u8, 97u8, 98u8,
+ 65u8, 114u8, 109u8, 105u8, 65u8, 114u8, 97u8, 98u8, 65u8, 114u8, 97u8,
+ 98u8, 65u8, 114u8, 97u8, 98u8, 65u8, 114u8, 97u8, 98u8, 66u8, 101u8, 110u8,
+ 103u8, 83u8, 103u8, 110u8, 119u8, 67u8, 121u8, 114u8, 108u8, 65u8, 114u8,
+ 97u8, 98u8, 68u8, 101u8, 118u8, 97u8, 67u8, 121u8, 114u8, 108u8, 65u8,
+ 114u8, 97u8, 98u8, 68u8, 101u8, 118u8, 97u8, 66u8, 97u8, 109u8, 117u8,
+ 69u8, 116u8, 104u8, 105u8, 67u8, 121u8, 114u8, 108u8, 65u8, 114u8, 97u8,
+ 98u8, 84u8, 97u8, 109u8, 108u8, 65u8, 114u8, 97u8, 98u8, 68u8, 101u8,
+ 118u8, 97u8, 67u8, 121u8, 114u8, 108u8, 68u8, 101u8, 118u8, 97u8, 65u8,
+ 114u8, 97u8, 98u8, 71u8, 114u8, 101u8, 107u8, 68u8, 101u8, 118u8, 97u8,
+ 68u8, 101u8, 118u8, 97u8, 68u8, 101u8, 118u8, 97u8, 69u8, 116u8, 104u8,
+ 105u8, 68u8, 101u8, 118u8, 97u8, 84u8, 97u8, 118u8, 116u8, 66u8, 101u8,
+ 110u8, 103u8, 84u8, 105u8, 98u8, 116u8, 66u8, 101u8, 110u8, 103u8, 65u8,
+ 114u8, 97u8, 98u8, 68u8, 101u8, 118u8, 97u8, 65u8, 114u8, 97u8, 98u8, 68u8,
+ 101u8, 118u8, 97u8, 66u8, 97u8, 115u8, 115u8, 69u8, 116u8, 104u8, 105u8,
+ 68u8, 101u8, 118u8, 97u8, 67u8, 121u8, 114u8, 108u8, 69u8, 116u8, 104u8,
+ 105u8, 67u8, 97u8, 107u8, 109u8, 67u8, 121u8, 114u8, 108u8, 67u8, 121u8,
+ 114u8, 108u8, 67u8, 104u8, 101u8, 114u8, 65u8, 114u8, 97u8, 98u8, 67u8,
+ 104u8, 97u8, 109u8, 65u8, 114u8, 97u8, 98u8, 83u8, 111u8, 121u8, 111u8,
+ 67u8, 111u8, 112u8, 116u8, 67u8, 97u8, 110u8, 115u8, 67u8, 121u8, 114u8,
+ 108u8, 67u8, 97u8, 110u8, 115u8, 67u8, 97u8, 110u8, 115u8, 67u8, 97u8,
+ 110u8, 115u8, 80u8, 97u8, 117u8, 99u8, 67u8, 121u8, 114u8, 108u8, 67u8,
+ 121u8, 114u8, 108u8, 67u8, 121u8, 114u8, 108u8, 65u8, 114u8, 97u8, 98u8,
+ 65u8, 114u8, 97u8, 98u8, 77u8, 101u8, 100u8, 102u8, 68u8, 101u8, 118u8,
+ 97u8, 77u8, 111u8, 110u8, 103u8, 69u8, 116u8, 104u8, 105u8, 68u8, 101u8,
+ 118u8, 97u8, 84u8, 104u8, 97u8, 97u8, 84u8, 105u8, 98u8, 116u8, 69u8,
+ 103u8, 121u8, 112u8, 75u8, 97u8, 108u8, 105u8, 71u8, 114u8, 101u8, 107u8,
+ 71u8, 111u8, 110u8, 109u8, 73u8, 116u8, 97u8, 108u8, 65u8, 114u8, 97u8,
+ 98u8, 65u8, 114u8, 97u8, 98u8, 65u8, 114u8, 97u8, 98u8, 72u8, 97u8, 110u8,
+ 115u8, 68u8, 101u8, 118u8, 97u8, 65u8, 114u8, 97u8, 98u8, 69u8, 116u8,
+ 104u8, 105u8, 68u8, 101u8, 118u8, 97u8, 65u8, 114u8, 97u8, 98u8, 65u8,
+ 114u8, 97u8, 98u8, 65u8, 114u8, 97u8, 98u8, 69u8, 116u8, 104u8, 105u8,
+ 69u8, 116u8, 104u8, 105u8, 68u8, 101u8, 118u8, 97u8, 84u8, 101u8, 108u8,
+ 117u8, 71u8, 111u8, 116u8, 104u8, 67u8, 112u8, 114u8, 116u8, 66u8, 101u8,
+ 110u8, 103u8, 71u8, 117u8, 106u8, 114u8, 68u8, 101u8, 118u8, 97u8, 65u8,
+ 114u8, 97u8, 98u8, 65u8, 114u8, 97u8, 98u8, 72u8, 97u8, 110u8, 115u8, 65u8,
+ 114u8, 97u8, 98u8, 69u8, 116u8, 104u8, 105u8, 72u8, 101u8, 98u8, 114u8,
+ 68u8, 101u8, 118u8, 97u8, 72u8, 108u8, 117u8, 119u8, 80u8, 108u8, 114u8,
+ 100u8, 65u8, 114u8, 97u8, 98u8, 68u8, 101u8, 118u8, 97u8, 72u8, 109u8,
+ 110u8, 112u8, 65u8, 114u8, 97u8, 98u8, 68u8, 101u8, 118u8, 97u8, 68u8,
+ 101u8, 118u8, 97u8, 72u8, 97u8, 110u8, 115u8, 65u8, 114u8, 109u8, 110u8,
+ 89u8, 105u8, 105u8, 105u8, 67u8, 121u8, 114u8, 108u8, 67u8, 97u8, 110u8,
+ 115u8, 72u8, 101u8, 98u8, 114u8, 74u8, 112u8, 97u8, 110u8, 72u8, 101u8,
+ 98u8, 114u8, 68u8, 101u8, 118u8, 97u8, 71u8, 101u8, 111u8, 114u8, 67u8,
+ 121u8, 114u8, 108u8, 75u8, 97u8, 119u8, 105u8, 67u8, 121u8, 114u8, 108u8,
+ 65u8, 114u8, 97u8, 98u8, 84u8, 104u8, 97u8, 105u8, 68u8, 101u8, 118u8,
+ 97u8, 68u8, 101u8, 118u8, 97u8, 84u8, 97u8, 108u8, 117u8, 68u8, 101u8,
+ 118u8, 97u8, 77u8, 121u8, 109u8, 114u8, 65u8, 114u8, 97u8, 98u8, 76u8,
+ 97u8, 111u8, 111u8, 67u8, 121u8, 114u8, 108u8, 75u8, 104u8, 109u8, 114u8,
+ 75u8, 110u8, 100u8, 97u8, 75u8, 111u8, 114u8, 101u8, 67u8, 121u8, 114u8,
+ 108u8, 68u8, 101u8, 118u8, 97u8, 69u8, 116u8, 104u8, 105u8, 67u8, 121u8,
+ 114u8, 108u8, 68u8, 101u8, 118u8, 97u8, 65u8, 114u8, 97u8, 98u8, 69u8,
+ 116u8, 104u8, 105u8, 67u8, 121u8, 114u8, 108u8, 67u8, 121u8, 114u8, 108u8,
+ 65u8, 114u8, 97u8, 98u8, 69u8, 116u8, 104u8, 105u8, 68u8, 101u8, 118u8,
+ 97u8, 84u8, 104u8, 97u8, 105u8, 65u8, 114u8, 97u8, 98u8, 67u8, 121u8,
+ 114u8, 108u8, 65u8, 114u8, 97u8, 98u8, 76u8, 105u8, 110u8, 97u8, 72u8,
+ 101u8, 98u8, 114u8, 65u8, 114u8, 97u8, 98u8, 67u8, 121u8, 114u8, 108u8,
+ 84u8, 104u8, 97u8, 105u8, 76u8, 101u8, 112u8, 99u8, 67u8, 121u8, 114u8,
+ 108u8, 68u8, 101u8, 118u8, 97u8, 76u8, 105u8, 115u8, 117u8, 65u8, 114u8,
+ 97u8, 98u8, 84u8, 101u8, 108u8, 117u8, 76u8, 97u8, 111u8, 111u8, 65u8,
+ 114u8, 97u8, 98u8, 65u8, 114u8, 97u8, 98u8, 84u8, 104u8, 97u8, 105u8, 72u8,
+ 97u8, 110u8, 115u8, 68u8, 101u8, 118u8, 97u8, 68u8, 101u8, 118u8, 97u8,
+ 65u8, 114u8, 97u8, 98u8, 67u8, 121u8, 114u8, 108u8, 69u8, 116u8, 104u8,
+ 105u8, 65u8, 114u8, 97u8, 98u8, 68u8, 101u8, 118u8, 97u8, 67u8, 121u8,
+ 114u8, 108u8, 65u8, 114u8, 97u8, 98u8, 77u8, 108u8, 121u8, 109u8, 67u8,
+ 121u8, 114u8, 108u8, 66u8, 101u8, 110u8, 103u8, 77u8, 121u8, 109u8, 114u8,
+ 68u8, 101u8, 118u8, 97u8, 68u8, 101u8, 118u8, 97u8, 67u8, 121u8, 114u8,
+ 108u8, 77u8, 114u8, 111u8, 111u8, 68u8, 101u8, 118u8, 97u8, 65u8, 114u8,
+ 97u8, 98u8, 68u8, 101u8, 118u8, 97u8, 72u8, 109u8, 110u8, 112u8, 77u8,
+ 121u8, 109u8, 114u8, 69u8, 116u8, 104u8, 105u8, 67u8, 121u8, 114u8, 108u8,
+ 77u8, 97u8, 110u8, 100u8, 65u8, 114u8, 97u8, 98u8, 72u8, 97u8, 110u8,
+ 115u8, 68u8, 101u8, 118u8, 97u8, 68u8, 101u8, 118u8, 97u8, 87u8, 99u8,
+ 104u8, 111u8, 76u8, 97u8, 110u8, 97u8, 68u8, 101u8, 118u8, 97u8, 82u8,
+ 117u8, 110u8, 114u8, 78u8, 107u8, 111u8, 111u8, 67u8, 97u8, 110u8, 115u8,
+ 84u8, 110u8, 115u8, 97u8, 67u8, 97u8, 110u8, 115u8, 67u8, 97u8, 110u8,
+ 115u8, 79u8, 114u8, 121u8, 97u8, 65u8, 114u8, 97u8, 98u8, 67u8, 121u8,
+ 114u8, 108u8, 79u8, 115u8, 103u8, 101u8, 65u8, 114u8, 97u8, 98u8, 79u8,
+ 114u8, 107u8, 104u8, 79u8, 117u8, 103u8, 114u8, 71u8, 117u8, 114u8, 117u8,
+ 80u8, 104u8, 108u8, 105u8, 88u8, 112u8, 101u8, 111u8, 65u8, 114u8, 97u8,
+ 98u8, 80u8, 104u8, 110u8, 120u8, 66u8, 114u8, 97u8, 104u8, 71u8, 114u8,
+ 101u8, 107u8, 68u8, 101u8, 118u8, 97u8, 75u8, 104u8, 97u8, 114u8, 65u8,
+ 114u8, 97u8, 98u8, 65u8, 114u8, 97u8, 98u8, 68u8, 101u8, 118u8, 97u8, 82u8,
+ 111u8, 104u8, 103u8, 84u8, 102u8, 110u8, 103u8, 68u8, 101u8, 118u8, 97u8,
+ 66u8, 101u8, 110u8, 103u8, 65u8, 114u8, 97u8, 98u8, 67u8, 121u8, 114u8,
+ 108u8, 67u8, 121u8, 114u8, 108u8, 75u8, 97u8, 110u8, 97u8, 68u8, 101u8,
+ 118u8, 97u8, 67u8, 121u8, 114u8, 108u8, 79u8, 108u8, 99u8, 107u8, 83u8,
+ 97u8, 117u8, 114u8, 68u8, 101u8, 118u8, 97u8, 65u8, 114u8, 97u8, 98u8,
+ 65u8, 114u8, 97u8, 98u8, 65u8, 114u8, 97u8, 98u8, 79u8, 103u8, 97u8, 109u8,
+ 69u8, 116u8, 104u8, 105u8, 84u8, 102u8, 110u8, 103u8, 77u8, 121u8, 109u8,
+ 114u8, 65u8, 114u8, 97u8, 98u8, 83u8, 105u8, 110u8, 104u8, 65u8, 114u8,
+ 97u8, 98u8, 83u8, 97u8, 109u8, 114u8, 83u8, 111u8, 103u8, 100u8, 84u8,
+ 104u8, 97u8, 105u8, 67u8, 121u8, 114u8, 108u8, 83u8, 111u8, 114u8, 97u8,
+ 68u8, 101u8, 118u8, 97u8, 65u8, 114u8, 97u8, 98u8, 68u8, 101u8, 118u8,
+ 97u8, 66u8, 101u8, 110u8, 103u8, 83u8, 121u8, 114u8, 99u8, 84u8, 97u8,
+ 109u8, 108u8, 68u8, 101u8, 118u8, 97u8, 75u8, 110u8, 100u8, 97u8, 84u8,
+ 97u8, 108u8, 101u8, 68u8, 101u8, 118u8, 97u8, 68u8, 101u8, 118u8, 97u8,
+ 84u8, 101u8, 108u8, 117u8, 67u8, 121u8, 114u8, 108u8, 84u8, 104u8, 97u8,
+ 105u8, 68u8, 101u8, 118u8, 97u8, 68u8, 101u8, 118u8, 97u8, 68u8, 101u8,
+ 118u8, 97u8, 69u8, 116u8, 104u8, 105u8, 69u8, 116u8, 104u8, 105u8, 68u8,
+ 101u8, 118u8, 97u8, 65u8, 114u8, 97u8, 98u8, 71u8, 114u8, 101u8, 107u8,
+ 68u8, 101u8, 118u8, 97u8, 84u8, 105u8, 98u8, 116u8, 67u8, 121u8, 114u8,
+ 108u8, 84u8, 104u8, 97u8, 105u8, 84u8, 97u8, 110u8, 103u8, 84u8, 111u8,
+ 116u8, 111u8, 67u8, 121u8, 114u8, 108u8, 65u8, 103u8, 104u8, 98u8, 67u8,
+ 121u8, 114u8, 108u8, 65u8, 114u8, 97u8, 98u8, 85u8, 103u8, 97u8, 114u8,
+ 67u8, 121u8, 114u8, 108u8, 66u8, 101u8, 110u8, 103u8, 66u8, 101u8, 110u8,
+ 103u8, 65u8, 114u8, 97u8, 98u8, 86u8, 97u8, 105u8, 105u8, 69u8, 116u8,
+ 104u8, 105u8, 84u8, 101u8, 108u8, 117u8, 68u8, 101u8, 118u8, 97u8, 65u8,
+ 114u8, 97u8, 98u8, 71u8, 111u8, 110u8, 103u8, 68u8, 101u8, 118u8, 97u8,
+ 72u8, 97u8, 110u8, 115u8, 67u8, 104u8, 114u8, 115u8, 67u8, 97u8, 114u8,
+ 105u8, 76u8, 121u8, 99u8, 105u8, 76u8, 121u8, 100u8, 105u8, 71u8, 101u8,
+ 111u8, 114u8, 77u8, 97u8, 110u8, 105u8, 77u8, 101u8, 114u8, 99u8, 78u8,
+ 97u8, 114u8, 98u8, 68u8, 101u8, 118u8, 97u8, 80u8, 114u8, 116u8, 105u8,
+ 83u8, 97u8, 114u8, 98u8, 68u8, 101u8, 118u8, 97u8, 72u8, 101u8, 98u8,
+ 114u8, 72u8, 97u8, 110u8, 116u8, 65u8, 114u8, 97u8, 98u8, 84u8, 102u8,
+ 110u8, 103u8, 72u8, 97u8, 110u8, 115u8, 78u8, 115u8, 104u8, 117u8, 75u8,
+ 105u8, 116u8, 115u8,
+ ])
+ },
+ )
+ },
+ lr2s: unsafe {
+ #[allow(unused_unsafe)]
+ ::zerovec::ZeroMap2d::from_parts_unchecked(
+ unsafe {
+ ::zerovec::ZeroVec::from_bytes_unchecked(&[
+ 97u8, 122u8, 0u8, 104u8, 97u8, 0u8, 107u8, 107u8, 0u8, 107u8, 117u8, 0u8,
+ 107u8, 121u8, 0u8, 109u8, 97u8, 110u8, 109u8, 110u8, 0u8, 109u8, 115u8,
+ 0u8, 112u8, 97u8, 0u8, 114u8, 105u8, 102u8, 115u8, 100u8, 0u8, 115u8,
+ 114u8, 0u8, 116u8, 103u8, 0u8, 117u8, 103u8, 0u8, 117u8, 110u8, 114u8,
+ 117u8, 122u8, 0u8, 121u8, 117u8, 101u8, 122u8, 104u8, 0u8,
+ ])
+ },
+ unsafe {
+ ::zerovec::ZeroVec::from_bytes_unchecked(&[
+ 3u8, 0u8, 0u8, 0u8, 5u8, 0u8, 0u8, 0u8, 9u8, 0u8, 0u8, 0u8, 10u8, 0u8, 0u8,
+ 0u8, 12u8, 0u8, 0u8, 0u8, 13u8, 0u8, 0u8, 0u8, 14u8, 0u8, 0u8, 0u8, 15u8,
+ 0u8, 0u8, 0u8, 16u8, 0u8, 0u8, 0u8, 17u8, 0u8, 0u8, 0u8, 18u8, 0u8, 0u8,
+ 0u8, 22u8, 0u8, 0u8, 0u8, 23u8, 0u8, 0u8, 0u8, 25u8, 0u8, 0u8, 0u8, 26u8,
+ 0u8, 0u8, 0u8, 28u8, 0u8, 0u8, 0u8, 29u8, 0u8, 0u8, 0u8, 44u8, 0u8, 0u8,
+ 0u8,
+ ])
+ },
+ unsafe {
+ ::zerovec::ZeroVec::from_bytes_unchecked(&[
+ 73u8, 81u8, 0u8, 73u8, 82u8, 0u8, 82u8, 85u8, 0u8, 67u8, 77u8, 0u8, 83u8,
+ 68u8, 0u8, 65u8, 70u8, 0u8, 67u8, 78u8, 0u8, 73u8, 82u8, 0u8, 77u8, 78u8,
+ 0u8, 76u8, 66u8, 0u8, 67u8, 78u8, 0u8, 84u8, 82u8, 0u8, 71u8, 78u8, 0u8,
+ 67u8, 78u8, 0u8, 67u8, 67u8, 0u8, 80u8, 75u8, 0u8, 78u8, 76u8, 0u8, 73u8,
+ 78u8, 0u8, 77u8, 69u8, 0u8, 82u8, 79u8, 0u8, 82u8, 85u8, 0u8, 84u8, 82u8,
+ 0u8, 80u8, 75u8, 0u8, 75u8, 90u8, 0u8, 77u8, 78u8, 0u8, 78u8, 80u8, 0u8,
+ 65u8, 70u8, 0u8, 67u8, 78u8, 0u8, 67u8, 78u8, 0u8, 65u8, 85u8, 0u8, 66u8,
+ 78u8, 0u8, 71u8, 66u8, 0u8, 71u8, 70u8, 0u8, 72u8, 75u8, 0u8, 73u8, 68u8,
+ 0u8, 77u8, 79u8, 0u8, 80u8, 65u8, 0u8, 80u8, 70u8, 0u8, 80u8, 72u8, 0u8,
+ 83u8, 82u8, 0u8, 84u8, 72u8, 0u8, 84u8, 87u8, 0u8, 85u8, 83u8, 0u8, 86u8,
+ 78u8, 0u8,
+ ])
+ },
+ unsafe {
+ ::zerovec::ZeroVec::from_bytes_unchecked(&[
+ 65u8, 114u8, 97u8, 98u8, 65u8, 114u8, 97u8, 98u8, 67u8, 121u8, 114u8,
+ 108u8, 65u8, 114u8, 97u8, 98u8, 65u8, 114u8, 97u8, 98u8, 65u8, 114u8, 97u8,
+ 98u8, 65u8, 114u8, 97u8, 98u8, 65u8, 114u8, 97u8, 98u8, 65u8, 114u8, 97u8,
+ 98u8, 65u8, 114u8, 97u8, 98u8, 65u8, 114u8, 97u8, 98u8, 76u8, 97u8, 116u8,
+ 110u8, 78u8, 107u8, 111u8, 111u8, 77u8, 111u8, 110u8, 103u8, 65u8, 114u8,
+ 97u8, 98u8, 65u8, 114u8, 97u8, 98u8, 76u8, 97u8, 116u8, 110u8, 68u8, 101u8,
+ 118u8, 97u8, 76u8, 97u8, 116u8, 110u8, 76u8, 97u8, 116u8, 110u8, 76u8,
+ 97u8, 116u8, 110u8, 76u8, 97u8, 116u8, 110u8, 65u8, 114u8, 97u8, 98u8,
+ 67u8, 121u8, 114u8, 108u8, 67u8, 121u8, 114u8, 108u8, 68u8, 101u8, 118u8,
+ 97u8, 65u8, 114u8, 97u8, 98u8, 67u8, 121u8, 114u8, 108u8, 72u8, 97u8,
+ 110u8, 115u8, 72u8, 97u8, 110u8, 116u8, 72u8, 97u8, 110u8, 116u8, 72u8,
+ 97u8, 110u8, 116u8, 72u8, 97u8, 110u8, 116u8, 72u8, 97u8, 110u8, 116u8,
+ 72u8, 97u8, 110u8, 116u8, 72u8, 97u8, 110u8, 116u8, 72u8, 97u8, 110u8,
+ 116u8, 72u8, 97u8, 110u8, 116u8, 72u8, 97u8, 110u8, 116u8, 72u8, 97u8,
+ 110u8, 116u8, 72u8, 97u8, 110u8, 116u8, 72u8, 97u8, 110u8, 116u8, 72u8,
+ 97u8, 110u8, 116u8, 72u8, 97u8, 110u8, 116u8,
+ ])
+ },
+ )
+ },
+ l2r: unsafe {
+ #[allow(unused_unsafe)]
+ ::zerovec::ZeroMap::from_parts_unchecked(
+ unsafe {
+ ::zerovec::ZeroVec::from_bytes_unchecked(&[
+ 97u8, 97u8, 0u8, 97u8, 98u8, 0u8, 97u8, 98u8, 114u8, 97u8, 99u8, 101u8,
+ 97u8, 99u8, 104u8, 97u8, 100u8, 97u8, 97u8, 100u8, 112u8, 97u8, 100u8,
+ 121u8, 97u8, 101u8, 0u8, 97u8, 101u8, 98u8, 97u8, 102u8, 0u8, 97u8, 103u8,
+ 113u8, 97u8, 104u8, 111u8, 97u8, 106u8, 116u8, 97u8, 107u8, 0u8, 97u8,
+ 107u8, 107u8, 97u8, 108u8, 110u8, 97u8, 108u8, 116u8, 97u8, 109u8, 0u8,
+ 97u8, 109u8, 111u8, 97u8, 110u8, 0u8, 97u8, 110u8, 110u8, 97u8, 111u8,
+ 122u8, 97u8, 112u8, 100u8, 97u8, 114u8, 0u8, 97u8, 114u8, 99u8, 97u8,
+ 114u8, 110u8, 97u8, 114u8, 111u8, 97u8, 114u8, 113u8, 97u8, 114u8, 115u8,
+ 97u8, 114u8, 121u8, 97u8, 114u8, 122u8, 97u8, 115u8, 0u8, 97u8, 115u8,
+ 97u8, 97u8, 115u8, 101u8, 97u8, 115u8, 116u8, 97u8, 116u8, 106u8, 97u8,
+ 118u8, 0u8, 97u8, 119u8, 97u8, 97u8, 121u8, 0u8, 97u8, 122u8, 0u8, 98u8,
+ 97u8, 0u8, 98u8, 97u8, 108u8, 98u8, 97u8, 110u8, 98u8, 97u8, 112u8, 98u8,
+ 97u8, 114u8, 98u8, 97u8, 115u8, 98u8, 97u8, 120u8, 98u8, 98u8, 99u8, 98u8,
+ 98u8, 106u8, 98u8, 99u8, 105u8, 98u8, 101u8, 0u8, 98u8, 101u8, 106u8, 98u8,
+ 101u8, 109u8, 98u8, 101u8, 119u8, 98u8, 101u8, 122u8, 98u8, 102u8, 100u8,
+ 98u8, 102u8, 113u8, 98u8, 102u8, 116u8, 98u8, 102u8, 121u8, 98u8, 103u8,
+ 0u8, 98u8, 103u8, 99u8, 98u8, 103u8, 110u8, 98u8, 103u8, 120u8, 98u8,
+ 104u8, 98u8, 98u8, 104u8, 105u8, 98u8, 104u8, 111u8, 98u8, 105u8, 0u8,
+ 98u8, 105u8, 107u8, 98u8, 105u8, 110u8, 98u8, 106u8, 106u8, 98u8, 106u8,
+ 110u8, 98u8, 106u8, 116u8, 98u8, 107u8, 109u8, 98u8, 107u8, 117u8, 98u8,
+ 108u8, 97u8, 98u8, 108u8, 103u8, 98u8, 108u8, 116u8, 98u8, 109u8, 0u8,
+ 98u8, 109u8, 113u8, 98u8, 110u8, 0u8, 98u8, 111u8, 0u8, 98u8, 112u8, 121u8,
+ 98u8, 113u8, 105u8, 98u8, 113u8, 118u8, 98u8, 114u8, 0u8, 98u8, 114u8,
+ 97u8, 98u8, 114u8, 104u8, 98u8, 114u8, 120u8, 98u8, 115u8, 0u8, 98u8,
+ 115u8, 113u8, 98u8, 115u8, 115u8, 98u8, 116u8, 111u8, 98u8, 116u8, 118u8,
+ 98u8, 117u8, 97u8, 98u8, 117u8, 99u8, 98u8, 117u8, 103u8, 98u8, 117u8,
+ 109u8, 98u8, 118u8, 98u8, 98u8, 121u8, 110u8, 98u8, 121u8, 118u8, 98u8,
+ 122u8, 101u8, 99u8, 97u8, 0u8, 99u8, 97u8, 100u8, 99u8, 99u8, 104u8, 99u8,
+ 99u8, 112u8, 99u8, 101u8, 0u8, 99u8, 101u8, 98u8, 99u8, 103u8, 103u8, 99u8,
+ 104u8, 0u8, 99u8, 104u8, 107u8, 99u8, 104u8, 109u8, 99u8, 104u8, 111u8,
+ 99u8, 104u8, 112u8, 99u8, 104u8, 114u8, 99u8, 105u8, 99u8, 99u8, 106u8,
+ 97u8, 99u8, 106u8, 109u8, 99u8, 107u8, 98u8, 99u8, 108u8, 99u8, 99u8,
+ 109u8, 103u8, 99u8, 111u8, 0u8, 99u8, 111u8, 112u8, 99u8, 112u8, 115u8,
+ 99u8, 114u8, 0u8, 99u8, 114u8, 103u8, 99u8, 114u8, 104u8, 99u8, 114u8,
+ 107u8, 99u8, 114u8, 108u8, 99u8, 114u8, 115u8, 99u8, 115u8, 0u8, 99u8,
+ 115u8, 98u8, 99u8, 115u8, 119u8, 99u8, 116u8, 100u8, 99u8, 117u8, 0u8,
+ 99u8, 118u8, 0u8, 99u8, 121u8, 0u8, 100u8, 97u8, 0u8, 100u8, 97u8, 102u8,
+ 100u8, 97u8, 107u8, 100u8, 97u8, 114u8, 100u8, 97u8, 118u8, 100u8, 99u8,
+ 99u8, 100u8, 101u8, 0u8, 100u8, 101u8, 110u8, 100u8, 103u8, 114u8, 100u8,
+ 106u8, 101u8, 100u8, 109u8, 102u8, 100u8, 110u8, 106u8, 100u8, 111u8,
+ 105u8, 100u8, 114u8, 104u8, 100u8, 115u8, 98u8, 100u8, 116u8, 109u8, 100u8,
+ 116u8, 112u8, 100u8, 116u8, 121u8, 100u8, 117u8, 97u8, 100u8, 118u8, 0u8,
+ 100u8, 121u8, 111u8, 100u8, 121u8, 117u8, 100u8, 122u8, 0u8, 101u8, 98u8,
+ 117u8, 101u8, 101u8, 0u8, 101u8, 102u8, 105u8, 101u8, 103u8, 108u8, 101u8,
+ 103u8, 121u8, 101u8, 107u8, 121u8, 101u8, 108u8, 0u8, 101u8, 110u8, 0u8,
+ 101u8, 111u8, 0u8, 101u8, 115u8, 0u8, 101u8, 115u8, 103u8, 101u8, 115u8,
+ 117u8, 101u8, 116u8, 0u8, 101u8, 116u8, 116u8, 101u8, 117u8, 0u8, 101u8,
+ 119u8, 111u8, 101u8, 120u8, 116u8, 102u8, 97u8, 0u8, 102u8, 97u8, 110u8,
+ 102u8, 102u8, 0u8, 102u8, 102u8, 109u8, 102u8, 105u8, 0u8, 102u8, 105u8,
+ 97u8, 102u8, 105u8, 108u8, 102u8, 105u8, 116u8, 102u8, 106u8, 0u8, 102u8,
+ 111u8, 0u8, 102u8, 111u8, 110u8, 102u8, 114u8, 0u8, 102u8, 114u8, 99u8,
+ 102u8, 114u8, 112u8, 102u8, 114u8, 114u8, 102u8, 114u8, 115u8, 102u8,
+ 117u8, 98u8, 102u8, 117u8, 100u8, 102u8, 117u8, 102u8, 102u8, 117u8, 113u8,
+ 102u8, 117u8, 114u8, 102u8, 117u8, 118u8, 102u8, 118u8, 114u8, 102u8,
+ 121u8, 0u8, 103u8, 97u8, 0u8, 103u8, 97u8, 97u8, 103u8, 97u8, 103u8, 103u8,
+ 97u8, 110u8, 103u8, 97u8, 121u8, 103u8, 98u8, 109u8, 103u8, 98u8, 122u8,
+ 103u8, 99u8, 114u8, 103u8, 100u8, 0u8, 103u8, 101u8, 122u8, 103u8, 103u8,
+ 110u8, 103u8, 105u8, 108u8, 103u8, 106u8, 107u8, 103u8, 106u8, 117u8,
+ 103u8, 108u8, 0u8, 103u8, 108u8, 107u8, 103u8, 110u8, 0u8, 103u8, 111u8,
+ 109u8, 103u8, 111u8, 110u8, 103u8, 111u8, 114u8, 103u8, 111u8, 115u8,
+ 103u8, 111u8, 116u8, 103u8, 114u8, 99u8, 103u8, 114u8, 116u8, 103u8, 115u8,
+ 119u8, 103u8, 117u8, 0u8, 103u8, 117u8, 98u8, 103u8, 117u8, 99u8, 103u8,
+ 117u8, 114u8, 103u8, 117u8, 122u8, 103u8, 118u8, 0u8, 103u8, 118u8, 114u8,
+ 103u8, 119u8, 105u8, 104u8, 97u8, 0u8, 104u8, 97u8, 107u8, 104u8, 97u8,
+ 119u8, 104u8, 97u8, 122u8, 104u8, 101u8, 0u8, 104u8, 105u8, 0u8, 104u8,
+ 105u8, 102u8, 104u8, 105u8, 108u8, 104u8, 108u8, 117u8, 104u8, 109u8,
+ 100u8, 104u8, 110u8, 100u8, 104u8, 110u8, 101u8, 104u8, 110u8, 106u8,
+ 104u8, 110u8, 110u8, 104u8, 110u8, 111u8, 104u8, 111u8, 0u8, 104u8, 111u8,
+ 99u8, 104u8, 111u8, 106u8, 104u8, 114u8, 0u8, 104u8, 115u8, 98u8, 104u8,
+ 115u8, 110u8, 104u8, 116u8, 0u8, 104u8, 117u8, 0u8, 104u8, 117u8, 114u8,
+ 104u8, 121u8, 0u8, 104u8, 122u8, 0u8, 105u8, 97u8, 0u8, 105u8, 98u8, 97u8,
+ 105u8, 98u8, 98u8, 105u8, 100u8, 0u8, 105u8, 102u8, 101u8, 105u8, 103u8,
+ 0u8, 105u8, 105u8, 0u8, 105u8, 107u8, 0u8, 105u8, 108u8, 111u8, 105u8,
+ 110u8, 0u8, 105u8, 110u8, 104u8, 105u8, 111u8, 0u8, 105u8, 115u8, 0u8,
+ 105u8, 116u8, 0u8, 105u8, 117u8, 0u8, 105u8, 119u8, 0u8, 105u8, 122u8,
+ 104u8, 106u8, 97u8, 0u8, 106u8, 97u8, 109u8, 106u8, 98u8, 111u8, 106u8,
+ 103u8, 111u8, 106u8, 105u8, 0u8, 106u8, 109u8, 99u8, 106u8, 109u8, 108u8,
+ 106u8, 117u8, 116u8, 106u8, 118u8, 0u8, 106u8, 119u8, 0u8, 107u8, 97u8,
+ 0u8, 107u8, 97u8, 97u8, 107u8, 97u8, 98u8, 107u8, 97u8, 99u8, 107u8, 97u8,
+ 106u8, 107u8, 97u8, 109u8, 107u8, 97u8, 111u8, 107u8, 97u8, 119u8, 107u8,
+ 98u8, 100u8, 107u8, 98u8, 121u8, 107u8, 99u8, 103u8, 107u8, 99u8, 107u8,
+ 107u8, 100u8, 101u8, 107u8, 100u8, 104u8, 107u8, 100u8, 116u8, 107u8,
+ 101u8, 97u8, 107u8, 101u8, 110u8, 107u8, 102u8, 111u8, 107u8, 102u8, 114u8,
+ 107u8, 102u8, 121u8, 107u8, 103u8, 0u8, 107u8, 103u8, 101u8, 107u8, 103u8,
+ 112u8, 107u8, 104u8, 97u8, 107u8, 104u8, 98u8, 107u8, 104u8, 110u8, 107u8,
+ 104u8, 113u8, 107u8, 104u8, 116u8, 107u8, 104u8, 119u8, 107u8, 105u8, 0u8,
+ 107u8, 105u8, 117u8, 107u8, 106u8, 0u8, 107u8, 106u8, 103u8, 107u8, 107u8,
+ 0u8, 107u8, 107u8, 106u8, 107u8, 108u8, 0u8, 107u8, 108u8, 110u8, 107u8,
+ 109u8, 0u8, 107u8, 109u8, 98u8, 107u8, 110u8, 0u8, 107u8, 110u8, 102u8,
+ 107u8, 111u8, 0u8, 107u8, 111u8, 105u8, 107u8, 111u8, 107u8, 107u8, 111u8,
+ 115u8, 107u8, 112u8, 101u8, 107u8, 114u8, 99u8, 107u8, 114u8, 105u8, 107u8,
+ 114u8, 106u8, 107u8, 114u8, 108u8, 107u8, 114u8, 117u8, 107u8, 115u8, 0u8,
+ 107u8, 115u8, 98u8, 107u8, 115u8, 102u8, 107u8, 115u8, 104u8, 107u8, 116u8,
+ 114u8, 107u8, 117u8, 0u8, 107u8, 117u8, 109u8, 107u8, 118u8, 0u8, 107u8,
+ 118u8, 114u8, 107u8, 118u8, 120u8, 107u8, 119u8, 0u8, 107u8, 119u8, 107u8,
+ 107u8, 120u8, 108u8, 107u8, 120u8, 109u8, 107u8, 120u8, 112u8, 107u8,
+ 121u8, 0u8, 107u8, 122u8, 106u8, 107u8, 122u8, 116u8, 108u8, 97u8, 0u8,
+ 108u8, 97u8, 98u8, 108u8, 97u8, 100u8, 108u8, 97u8, 103u8, 108u8, 97u8,
+ 104u8, 108u8, 97u8, 106u8, 108u8, 98u8, 0u8, 108u8, 98u8, 101u8, 108u8,
+ 98u8, 119u8, 108u8, 99u8, 112u8, 108u8, 101u8, 112u8, 108u8, 101u8, 122u8,
+ 108u8, 103u8, 0u8, 108u8, 105u8, 0u8, 108u8, 105u8, 102u8, 108u8, 105u8,
+ 106u8, 108u8, 105u8, 108u8, 108u8, 105u8, 115u8, 108u8, 106u8, 112u8,
+ 108u8, 107u8, 105u8, 108u8, 107u8, 116u8, 108u8, 109u8, 110u8, 108u8,
+ 109u8, 111u8, 108u8, 110u8, 0u8, 108u8, 111u8, 0u8, 108u8, 111u8, 108u8,
+ 108u8, 111u8, 122u8, 108u8, 114u8, 99u8, 108u8, 116u8, 0u8, 108u8, 116u8,
+ 103u8, 108u8, 117u8, 0u8, 108u8, 117u8, 97u8, 108u8, 117u8, 111u8, 108u8,
+ 117u8, 121u8, 108u8, 117u8, 122u8, 108u8, 118u8, 0u8, 108u8, 119u8, 108u8,
+ 108u8, 122u8, 104u8, 108u8, 122u8, 122u8, 109u8, 97u8, 100u8, 109u8, 97u8,
+ 102u8, 109u8, 97u8, 103u8, 109u8, 97u8, 105u8, 109u8, 97u8, 107u8, 109u8,
+ 97u8, 110u8, 109u8, 97u8, 115u8, 109u8, 97u8, 122u8, 109u8, 100u8, 102u8,
+ 109u8, 100u8, 104u8, 109u8, 100u8, 114u8, 109u8, 101u8, 110u8, 109u8,
+ 101u8, 114u8, 109u8, 102u8, 97u8, 109u8, 102u8, 101u8, 109u8, 103u8, 0u8,
+ 109u8, 103u8, 104u8, 109u8, 103u8, 111u8, 109u8, 103u8, 112u8, 109u8,
+ 103u8, 121u8, 109u8, 104u8, 0u8, 109u8, 105u8, 0u8, 109u8, 105u8, 99u8,
+ 109u8, 105u8, 110u8, 109u8, 107u8, 0u8, 109u8, 108u8, 0u8, 109u8, 108u8,
+ 115u8, 109u8, 110u8, 0u8, 109u8, 110u8, 105u8, 109u8, 110u8, 119u8, 109u8,
+ 111u8, 0u8, 109u8, 111u8, 101u8, 109u8, 111u8, 104u8, 109u8, 111u8, 115u8,
+ 109u8, 114u8, 0u8, 109u8, 114u8, 100u8, 109u8, 114u8, 106u8, 109u8, 114u8,
+ 111u8, 109u8, 115u8, 0u8, 109u8, 116u8, 0u8, 109u8, 116u8, 114u8, 109u8,
+ 117u8, 97u8, 109u8, 117u8, 115u8, 109u8, 118u8, 121u8, 109u8, 119u8, 107u8,
+ 109u8, 119u8, 114u8, 109u8, 119u8, 118u8, 109u8, 119u8, 119u8, 109u8,
+ 120u8, 99u8, 109u8, 121u8, 0u8, 109u8, 121u8, 118u8, 109u8, 121u8, 120u8,
+ 109u8, 121u8, 122u8, 109u8, 122u8, 110u8, 110u8, 97u8, 0u8, 110u8, 97u8,
+ 110u8, 110u8, 97u8, 112u8, 110u8, 97u8, 113u8, 110u8, 98u8, 0u8, 110u8,
+ 99u8, 104u8, 110u8, 100u8, 0u8, 110u8, 100u8, 99u8, 110u8, 100u8, 115u8,
+ 110u8, 101u8, 0u8, 110u8, 101u8, 119u8, 110u8, 103u8, 0u8, 110u8, 103u8,
+ 108u8, 110u8, 104u8, 101u8, 110u8, 104u8, 119u8, 110u8, 105u8, 106u8,
+ 110u8, 105u8, 117u8, 110u8, 106u8, 111u8, 110u8, 108u8, 0u8, 110u8, 109u8,
+ 103u8, 110u8, 110u8, 0u8, 110u8, 110u8, 104u8, 110u8, 110u8, 112u8, 110u8,
+ 111u8, 0u8, 110u8, 111u8, 100u8, 110u8, 111u8, 101u8, 110u8, 111u8, 110u8,
+ 110u8, 113u8, 111u8, 110u8, 114u8, 0u8, 110u8, 115u8, 107u8, 110u8, 115u8,
+ 111u8, 110u8, 115u8, 116u8, 110u8, 117u8, 115u8, 110u8, 118u8, 0u8, 110u8,
+ 120u8, 113u8, 110u8, 121u8, 0u8, 110u8, 121u8, 109u8, 110u8, 121u8, 110u8,
+ 110u8, 122u8, 105u8, 111u8, 99u8, 0u8, 111u8, 106u8, 0u8, 111u8, 106u8,
+ 115u8, 111u8, 107u8, 97u8, 111u8, 109u8, 0u8, 111u8, 114u8, 0u8, 111u8,
+ 115u8, 0u8, 111u8, 115u8, 97u8, 111u8, 116u8, 107u8, 111u8, 117u8, 105u8,
+ 112u8, 97u8, 0u8, 112u8, 97u8, 103u8, 112u8, 97u8, 108u8, 112u8, 97u8,
+ 109u8, 112u8, 97u8, 112u8, 112u8, 97u8, 117u8, 112u8, 99u8, 100u8, 112u8,
+ 99u8, 109u8, 112u8, 100u8, 99u8, 112u8, 100u8, 116u8, 112u8, 101u8, 111u8,
+ 112u8, 102u8, 108u8, 112u8, 104u8, 110u8, 112u8, 105u8, 115u8, 112u8,
+ 107u8, 97u8, 112u8, 107u8, 111u8, 112u8, 108u8, 0u8, 112u8, 109u8, 115u8,
+ 112u8, 110u8, 116u8, 112u8, 111u8, 110u8, 112u8, 112u8, 97u8, 112u8, 113u8,
+ 109u8, 112u8, 114u8, 97u8, 112u8, 114u8, 100u8, 112u8, 114u8, 103u8, 112u8,
+ 115u8, 0u8, 112u8, 116u8, 0u8, 112u8, 117u8, 117u8, 113u8, 117u8, 0u8,
+ 113u8, 117u8, 99u8, 113u8, 117u8, 103u8, 114u8, 97u8, 106u8, 114u8, 99u8,
+ 102u8, 114u8, 101u8, 106u8, 114u8, 103u8, 110u8, 114u8, 104u8, 103u8,
+ 114u8, 105u8, 97u8, 114u8, 105u8, 102u8, 114u8, 106u8, 115u8, 114u8, 107u8,
+ 116u8, 114u8, 109u8, 0u8, 114u8, 109u8, 102u8, 114u8, 109u8, 111u8, 114u8,
+ 109u8, 116u8, 114u8, 109u8, 117u8, 114u8, 110u8, 0u8, 114u8, 110u8, 103u8,
+ 114u8, 111u8, 0u8, 114u8, 111u8, 98u8, 114u8, 111u8, 102u8, 114u8, 116u8,
+ 109u8, 114u8, 117u8, 0u8, 114u8, 117u8, 101u8, 114u8, 117u8, 103u8, 114u8,
+ 119u8, 0u8, 114u8, 119u8, 107u8, 114u8, 121u8, 117u8, 115u8, 97u8, 0u8,
+ 115u8, 97u8, 102u8, 115u8, 97u8, 104u8, 115u8, 97u8, 113u8, 115u8, 97u8,
+ 115u8, 115u8, 97u8, 116u8, 115u8, 97u8, 118u8, 115u8, 97u8, 122u8, 115u8,
+ 98u8, 112u8, 115u8, 99u8, 0u8, 115u8, 99u8, 107u8, 115u8, 99u8, 110u8,
+ 115u8, 99u8, 111u8, 115u8, 100u8, 0u8, 115u8, 100u8, 99u8, 115u8, 100u8,
+ 104u8, 115u8, 101u8, 0u8, 115u8, 101u8, 102u8, 115u8, 101u8, 104u8, 115u8,
+ 101u8, 105u8, 115u8, 101u8, 115u8, 115u8, 103u8, 0u8, 115u8, 103u8, 97u8,
+ 115u8, 103u8, 115u8, 115u8, 104u8, 105u8, 115u8, 104u8, 110u8, 115u8,
+ 105u8, 0u8, 115u8, 105u8, 100u8, 115u8, 107u8, 0u8, 115u8, 107u8, 114u8,
+ 115u8, 108u8, 0u8, 115u8, 108u8, 105u8, 115u8, 108u8, 121u8, 115u8, 109u8,
+ 0u8, 115u8, 109u8, 97u8, 115u8, 109u8, 100u8, 115u8, 109u8, 106u8, 115u8,
+ 109u8, 110u8, 115u8, 109u8, 112u8, 115u8, 109u8, 115u8, 115u8, 110u8, 0u8,
+ 115u8, 110u8, 98u8, 115u8, 110u8, 107u8, 115u8, 111u8, 0u8, 115u8, 111u8,
+ 103u8, 115u8, 111u8, 117u8, 115u8, 113u8, 0u8, 115u8, 114u8, 0u8, 115u8,
+ 114u8, 98u8, 115u8, 114u8, 110u8, 115u8, 114u8, 114u8, 115u8, 114u8, 120u8,
+ 115u8, 115u8, 0u8, 115u8, 115u8, 121u8, 115u8, 116u8, 0u8, 115u8, 116u8,
+ 113u8, 115u8, 117u8, 0u8, 115u8, 117u8, 107u8, 115u8, 117u8, 115u8, 115u8,
+ 118u8, 0u8, 115u8, 119u8, 0u8, 115u8, 119u8, 98u8, 115u8, 119u8, 99u8,
+ 115u8, 119u8, 103u8, 115u8, 119u8, 118u8, 115u8, 120u8, 110u8, 115u8,
+ 121u8, 108u8, 115u8, 121u8, 114u8, 115u8, 122u8, 108u8, 116u8, 97u8, 0u8,
+ 116u8, 97u8, 106u8, 116u8, 98u8, 119u8, 116u8, 99u8, 121u8, 116u8, 100u8,
+ 100u8, 116u8, 100u8, 103u8, 116u8, 100u8, 104u8, 116u8, 100u8, 117u8,
+ 116u8, 101u8, 0u8, 116u8, 101u8, 109u8, 116u8, 101u8, 111u8, 116u8, 101u8,
+ 116u8, 116u8, 103u8, 0u8, 116u8, 104u8, 0u8, 116u8, 104u8, 108u8, 116u8,
+ 104u8, 113u8, 116u8, 104u8, 114u8, 116u8, 105u8, 0u8, 116u8, 105u8, 103u8,
+ 116u8, 105u8, 118u8, 116u8, 107u8, 0u8, 116u8, 107u8, 108u8, 116u8, 107u8,
+ 114u8, 116u8, 107u8, 116u8, 116u8, 108u8, 0u8, 116u8, 108u8, 121u8, 116u8,
+ 109u8, 104u8, 116u8, 110u8, 0u8, 116u8, 111u8, 0u8, 116u8, 111u8, 103u8,
+ 116u8, 111u8, 107u8, 116u8, 112u8, 105u8, 116u8, 114u8, 0u8, 116u8, 114u8,
+ 117u8, 116u8, 114u8, 118u8, 116u8, 114u8, 119u8, 116u8, 115u8, 0u8, 116u8,
+ 115u8, 100u8, 116u8, 115u8, 102u8, 116u8, 115u8, 103u8, 116u8, 115u8,
+ 106u8, 116u8, 116u8, 0u8, 116u8, 116u8, 106u8, 116u8, 116u8, 115u8, 116u8,
+ 116u8, 116u8, 116u8, 117u8, 109u8, 116u8, 118u8, 108u8, 116u8, 119u8,
+ 113u8, 116u8, 120u8, 103u8, 116u8, 120u8, 111u8, 116u8, 121u8, 0u8, 116u8,
+ 121u8, 118u8, 116u8, 122u8, 109u8, 117u8, 100u8, 105u8, 117u8, 100u8,
+ 109u8, 117u8, 103u8, 0u8, 117u8, 103u8, 97u8, 117u8, 107u8, 0u8, 117u8,
+ 108u8, 105u8, 117u8, 109u8, 98u8, 117u8, 110u8, 114u8, 117u8, 110u8, 120u8,
+ 117u8, 114u8, 0u8, 117u8, 122u8, 0u8, 118u8, 97u8, 105u8, 118u8, 101u8,
+ 0u8, 118u8, 101u8, 99u8, 118u8, 101u8, 112u8, 118u8, 105u8, 0u8, 118u8,
+ 105u8, 99u8, 118u8, 108u8, 115u8, 118u8, 109u8, 102u8, 118u8, 109u8, 119u8,
+ 118u8, 111u8, 0u8, 118u8, 111u8, 116u8, 118u8, 114u8, 111u8, 118u8, 117u8,
+ 110u8, 119u8, 97u8, 0u8, 119u8, 97u8, 101u8, 119u8, 97u8, 108u8, 119u8,
+ 97u8, 114u8, 119u8, 98u8, 112u8, 119u8, 98u8, 113u8, 119u8, 98u8, 114u8,
+ 119u8, 108u8, 115u8, 119u8, 110u8, 105u8, 119u8, 111u8, 0u8, 119u8, 115u8,
+ 103u8, 119u8, 116u8, 109u8, 119u8, 117u8, 117u8, 120u8, 97u8, 118u8, 120u8,
+ 99u8, 111u8, 120u8, 99u8, 114u8, 120u8, 104u8, 0u8, 120u8, 108u8, 99u8,
+ 120u8, 108u8, 100u8, 120u8, 109u8, 102u8, 120u8, 109u8, 110u8, 120u8,
+ 109u8, 114u8, 120u8, 110u8, 97u8, 120u8, 110u8, 114u8, 120u8, 111u8, 103u8,
+ 120u8, 112u8, 114u8, 120u8, 115u8, 97u8, 120u8, 115u8, 114u8, 121u8, 97u8,
+ 111u8, 121u8, 97u8, 112u8, 121u8, 97u8, 118u8, 121u8, 98u8, 98u8, 121u8,
+ 105u8, 0u8, 121u8, 111u8, 0u8, 121u8, 114u8, 108u8, 121u8, 117u8, 97u8,
+ 121u8, 117u8, 101u8, 122u8, 97u8, 0u8, 122u8, 97u8, 103u8, 122u8, 100u8,
+ 106u8, 122u8, 101u8, 97u8, 122u8, 103u8, 104u8, 122u8, 104u8, 0u8, 122u8,
+ 104u8, 120u8, 122u8, 107u8, 116u8, 122u8, 108u8, 109u8, 122u8, 109u8,
+ 105u8, 122u8, 117u8, 0u8, 122u8, 122u8, 97u8,
+ ])
+ },
+ unsafe {
+ ::zerovec::ZeroVec::from_bytes_unchecked(&[
+ 69u8, 84u8, 0u8, 71u8, 69u8, 0u8, 71u8, 72u8, 0u8, 73u8, 68u8, 0u8, 85u8,
+ 71u8, 0u8, 71u8, 72u8, 0u8, 66u8, 84u8, 0u8, 82u8, 85u8, 0u8, 73u8, 82u8,
+ 0u8, 84u8, 78u8, 0u8, 90u8, 65u8, 0u8, 67u8, 77u8, 0u8, 73u8, 78u8, 0u8,
+ 84u8, 78u8, 0u8, 71u8, 72u8, 0u8, 73u8, 81u8, 0u8, 88u8, 75u8, 0u8, 82u8,
+ 85u8, 0u8, 69u8, 84u8, 0u8, 78u8, 71u8, 0u8, 69u8, 83u8, 0u8, 78u8, 71u8,
+ 0u8, 73u8, 68u8, 0u8, 84u8, 71u8, 0u8, 69u8, 71u8, 0u8, 73u8, 82u8, 0u8,
+ 67u8, 76u8, 0u8, 66u8, 79u8, 0u8, 68u8, 90u8, 0u8, 83u8, 65u8, 0u8, 77u8,
+ 65u8, 0u8, 69u8, 71u8, 0u8, 73u8, 78u8, 0u8, 84u8, 90u8, 0u8, 85u8, 83u8,
+ 0u8, 69u8, 83u8, 0u8, 67u8, 65u8, 0u8, 82u8, 85u8, 0u8, 73u8, 78u8, 0u8,
+ 66u8, 79u8, 0u8, 65u8, 90u8, 0u8, 82u8, 85u8, 0u8, 80u8, 75u8, 0u8, 73u8,
+ 68u8, 0u8, 78u8, 80u8, 0u8, 65u8, 84u8, 0u8, 67u8, 77u8, 0u8, 67u8, 77u8,
+ 0u8, 73u8, 68u8, 0u8, 67u8, 77u8, 0u8, 67u8, 73u8, 0u8, 66u8, 89u8, 0u8,
+ 83u8, 68u8, 0u8, 90u8, 77u8, 0u8, 73u8, 68u8, 0u8, 84u8, 90u8, 0u8, 67u8,
+ 77u8, 0u8, 73u8, 78u8, 0u8, 80u8, 75u8, 0u8, 73u8, 78u8, 0u8, 66u8, 71u8,
+ 0u8, 73u8, 78u8, 0u8, 80u8, 75u8, 0u8, 84u8, 82u8, 0u8, 73u8, 78u8, 0u8,
+ 73u8, 78u8, 0u8, 73u8, 78u8, 0u8, 86u8, 85u8, 0u8, 80u8, 72u8, 0u8, 78u8,
+ 71u8, 0u8, 73u8, 78u8, 0u8, 73u8, 68u8, 0u8, 83u8, 78u8, 0u8, 67u8, 77u8,
+ 0u8, 80u8, 72u8, 0u8, 67u8, 65u8, 0u8, 77u8, 89u8, 0u8, 86u8, 78u8, 0u8,
+ 77u8, 76u8, 0u8, 77u8, 76u8, 0u8, 66u8, 68u8, 0u8, 67u8, 78u8, 0u8, 73u8,
+ 78u8, 0u8, 73u8, 82u8, 0u8, 67u8, 73u8, 0u8, 70u8, 82u8, 0u8, 73u8, 78u8,
+ 0u8, 80u8, 75u8, 0u8, 73u8, 78u8, 0u8, 66u8, 65u8, 0u8, 76u8, 82u8, 0u8,
+ 67u8, 77u8, 0u8, 80u8, 72u8, 0u8, 80u8, 75u8, 0u8, 82u8, 85u8, 0u8, 89u8,
+ 84u8, 0u8, 73u8, 68u8, 0u8, 67u8, 77u8, 0u8, 71u8, 81u8, 0u8, 69u8, 82u8,
+ 0u8, 67u8, 77u8, 0u8, 77u8, 76u8, 0u8, 69u8, 83u8, 0u8, 85u8, 83u8, 0u8,
+ 78u8, 71u8, 0u8, 66u8, 68u8, 0u8, 82u8, 85u8, 0u8, 80u8, 72u8, 0u8, 85u8,
+ 71u8, 0u8, 71u8, 85u8, 0u8, 70u8, 77u8, 0u8, 82u8, 85u8, 0u8, 85u8, 83u8,
+ 0u8, 67u8, 65u8, 0u8, 85u8, 83u8, 0u8, 85u8, 83u8, 0u8, 75u8, 72u8, 0u8,
+ 86u8, 78u8, 0u8, 73u8, 81u8, 0u8, 67u8, 65u8, 0u8, 77u8, 78u8, 0u8, 70u8,
+ 82u8, 0u8, 69u8, 71u8, 0u8, 80u8, 72u8, 0u8, 67u8, 65u8, 0u8, 67u8, 65u8,
+ 0u8, 85u8, 65u8, 0u8, 67u8, 65u8, 0u8, 67u8, 65u8, 0u8, 83u8, 67u8, 0u8,
+ 67u8, 90u8, 0u8, 80u8, 76u8, 0u8, 67u8, 65u8, 0u8, 77u8, 77u8, 0u8, 82u8,
+ 85u8, 0u8, 82u8, 85u8, 0u8, 71u8, 66u8, 0u8, 68u8, 75u8, 0u8, 67u8, 73u8,
+ 0u8, 85u8, 83u8, 0u8, 82u8, 85u8, 0u8, 75u8, 69u8, 0u8, 73u8, 78u8, 0u8,
+ 68u8, 69u8, 0u8, 67u8, 65u8, 0u8, 67u8, 65u8, 0u8, 78u8, 69u8, 0u8, 78u8,
+ 71u8, 0u8, 67u8, 73u8, 0u8, 73u8, 78u8, 0u8, 67u8, 78u8, 0u8, 68u8, 69u8,
+ 0u8, 77u8, 76u8, 0u8, 77u8, 89u8, 0u8, 78u8, 80u8, 0u8, 67u8, 77u8, 0u8,
+ 77u8, 86u8, 0u8, 83u8, 78u8, 0u8, 66u8, 70u8, 0u8, 66u8, 84u8, 0u8, 75u8,
+ 69u8, 0u8, 71u8, 72u8, 0u8, 78u8, 71u8, 0u8, 73u8, 84u8, 0u8, 69u8, 71u8,
+ 0u8, 77u8, 77u8, 0u8, 71u8, 82u8, 0u8, 85u8, 83u8, 0u8, 48u8, 48u8, 49u8,
+ 69u8, 83u8, 0u8, 73u8, 78u8, 0u8, 85u8, 83u8, 0u8, 69u8, 69u8, 0u8, 73u8,
+ 84u8, 0u8, 69u8, 83u8, 0u8, 67u8, 77u8, 0u8, 69u8, 83u8, 0u8, 73u8, 82u8,
+ 0u8, 71u8, 81u8, 0u8, 83u8, 78u8, 0u8, 77u8, 76u8, 0u8, 70u8, 73u8, 0u8,
+ 83u8, 68u8, 0u8, 80u8, 72u8, 0u8, 83u8, 69u8, 0u8, 70u8, 74u8, 0u8, 70u8,
+ 79u8, 0u8, 66u8, 74u8, 0u8, 70u8, 82u8, 0u8, 85u8, 83u8, 0u8, 70u8, 82u8,
+ 0u8, 68u8, 69u8, 0u8, 68u8, 69u8, 0u8, 67u8, 77u8, 0u8, 87u8, 70u8, 0u8,
+ 71u8, 78u8, 0u8, 78u8, 69u8, 0u8, 73u8, 84u8, 0u8, 78u8, 71u8, 0u8, 83u8,
+ 68u8, 0u8, 78u8, 76u8, 0u8, 73u8, 69u8, 0u8, 71u8, 72u8, 0u8, 77u8, 68u8,
+ 0u8, 67u8, 78u8, 0u8, 73u8, 68u8, 0u8, 73u8, 78u8, 0u8, 73u8, 82u8, 0u8,
+ 71u8, 70u8, 0u8, 71u8, 66u8, 0u8, 69u8, 84u8, 0u8, 78u8, 80u8, 0u8, 75u8,
+ 73u8, 0u8, 80u8, 75u8, 0u8, 80u8, 75u8, 0u8, 69u8, 83u8, 0u8, 73u8, 82u8,
+ 0u8, 80u8, 89u8, 0u8, 73u8, 78u8, 0u8, 73u8, 78u8, 0u8, 73u8, 68u8, 0u8,
+ 78u8, 76u8, 0u8, 85u8, 65u8, 0u8, 67u8, 89u8, 0u8, 73u8, 78u8, 0u8, 67u8,
+ 72u8, 0u8, 73u8, 78u8, 0u8, 66u8, 82u8, 0u8, 67u8, 79u8, 0u8, 71u8, 72u8,
+ 0u8, 75u8, 69u8, 0u8, 73u8, 77u8, 0u8, 78u8, 80u8, 0u8, 67u8, 65u8, 0u8,
+ 78u8, 71u8, 0u8, 67u8, 78u8, 0u8, 85u8, 83u8, 0u8, 65u8, 70u8, 0u8, 73u8,
+ 76u8, 0u8, 73u8, 78u8, 0u8, 70u8, 74u8, 0u8, 80u8, 72u8, 0u8, 84u8, 82u8,
+ 0u8, 67u8, 78u8, 0u8, 80u8, 75u8, 0u8, 73u8, 78u8, 0u8, 85u8, 83u8, 0u8,
+ 80u8, 72u8, 0u8, 80u8, 75u8, 0u8, 80u8, 71u8, 0u8, 73u8, 78u8, 0u8, 73u8,
+ 78u8, 0u8, 72u8, 82u8, 0u8, 68u8, 69u8, 0u8, 67u8, 78u8, 0u8, 72u8, 84u8,
+ 0u8, 72u8, 85u8, 0u8, 67u8, 65u8, 0u8, 65u8, 77u8, 0u8, 78u8, 65u8, 0u8,
+ 48u8, 48u8, 49u8, 77u8, 89u8, 0u8, 78u8, 71u8, 0u8, 73u8, 68u8, 0u8, 84u8,
+ 71u8, 0u8, 78u8, 71u8, 0u8, 67u8, 78u8, 0u8, 85u8, 83u8, 0u8, 80u8, 72u8,
+ 0u8, 73u8, 68u8, 0u8, 82u8, 85u8, 0u8, 48u8, 48u8, 49u8, 73u8, 83u8, 0u8,
+ 73u8, 84u8, 0u8, 67u8, 65u8, 0u8, 73u8, 76u8, 0u8, 82u8, 85u8, 0u8, 74u8,
+ 80u8, 0u8, 74u8, 77u8, 0u8, 48u8, 48u8, 49u8, 67u8, 77u8, 0u8, 85u8, 65u8,
+ 0u8, 84u8, 90u8, 0u8, 78u8, 80u8, 0u8, 68u8, 75u8, 0u8, 73u8, 68u8, 0u8,
+ 73u8, 68u8, 0u8, 71u8, 69u8, 0u8, 85u8, 90u8, 0u8, 68u8, 90u8, 0u8, 77u8,
+ 77u8, 0u8, 78u8, 71u8, 0u8, 75u8, 69u8, 0u8, 77u8, 76u8, 0u8, 73u8, 68u8,
+ 0u8, 82u8, 85u8, 0u8, 78u8, 69u8, 0u8, 78u8, 71u8, 0u8, 90u8, 87u8, 0u8,
+ 84u8, 90u8, 0u8, 84u8, 71u8, 0u8, 84u8, 72u8, 0u8, 67u8, 86u8, 0u8, 67u8,
+ 77u8, 0u8, 67u8, 73u8, 0u8, 73u8, 78u8, 0u8, 73u8, 78u8, 0u8, 67u8, 68u8,
+ 0u8, 73u8, 68u8, 0u8, 66u8, 82u8, 0u8, 73u8, 78u8, 0u8, 67u8, 78u8, 0u8,
+ 73u8, 78u8, 0u8, 77u8, 76u8, 0u8, 73u8, 78u8, 0u8, 80u8, 75u8, 0u8, 75u8,
+ 69u8, 0u8, 84u8, 82u8, 0u8, 78u8, 65u8, 0u8, 76u8, 65u8, 0u8, 75u8, 90u8,
+ 0u8, 67u8, 77u8, 0u8, 71u8, 76u8, 0u8, 75u8, 69u8, 0u8, 75u8, 72u8, 0u8,
+ 65u8, 79u8, 0u8, 73u8, 78u8, 0u8, 71u8, 87u8, 0u8, 75u8, 82u8, 0u8, 82u8,
+ 85u8, 0u8, 73u8, 78u8, 0u8, 70u8, 77u8, 0u8, 76u8, 82u8, 0u8, 82u8, 85u8,
+ 0u8, 83u8, 76u8, 0u8, 80u8, 72u8, 0u8, 82u8, 85u8, 0u8, 73u8, 78u8, 0u8,
+ 73u8, 78u8, 0u8, 84u8, 90u8, 0u8, 67u8, 77u8, 0u8, 68u8, 69u8, 0u8, 77u8,
+ 89u8, 0u8, 84u8, 82u8, 0u8, 82u8, 85u8, 0u8, 82u8, 85u8, 0u8, 73u8, 68u8,
+ 0u8, 80u8, 75u8, 0u8, 71u8, 66u8, 0u8, 67u8, 65u8, 0u8, 73u8, 78u8, 0u8,
+ 84u8, 72u8, 0u8, 80u8, 75u8, 0u8, 75u8, 71u8, 0u8, 77u8, 89u8, 0u8, 77u8,
+ 89u8, 0u8, 86u8, 65u8, 0u8, 71u8, 82u8, 0u8, 73u8, 76u8, 0u8, 84u8, 90u8,
+ 0u8, 80u8, 75u8, 0u8, 85u8, 71u8, 0u8, 76u8, 85u8, 0u8, 82u8, 85u8, 0u8,
+ 73u8, 68u8, 0u8, 67u8, 78u8, 0u8, 73u8, 78u8, 0u8, 82u8, 85u8, 0u8, 85u8,
+ 71u8, 0u8, 78u8, 76u8, 0u8, 78u8, 80u8, 0u8, 73u8, 84u8, 0u8, 67u8, 65u8,
+ 0u8, 67u8, 78u8, 0u8, 73u8, 68u8, 0u8, 73u8, 82u8, 0u8, 85u8, 83u8, 0u8,
+ 73u8, 78u8, 0u8, 73u8, 84u8, 0u8, 67u8, 68u8, 0u8, 76u8, 65u8, 0u8, 67u8,
+ 68u8, 0u8, 90u8, 77u8, 0u8, 73u8, 82u8, 0u8, 76u8, 84u8, 0u8, 76u8, 86u8,
+ 0u8, 67u8, 68u8, 0u8, 67u8, 68u8, 0u8, 75u8, 69u8, 0u8, 75u8, 69u8, 0u8,
+ 73u8, 82u8, 0u8, 76u8, 86u8, 0u8, 84u8, 72u8, 0u8, 67u8, 78u8, 0u8, 84u8,
+ 82u8, 0u8, 73u8, 68u8, 0u8, 67u8, 77u8, 0u8, 73u8, 78u8, 0u8, 73u8, 78u8,
+ 0u8, 73u8, 68u8, 0u8, 71u8, 77u8, 0u8, 75u8, 69u8, 0u8, 77u8, 88u8, 0u8,
+ 82u8, 85u8, 0u8, 80u8, 72u8, 0u8, 73u8, 68u8, 0u8, 83u8, 76u8, 0u8, 75u8,
+ 69u8, 0u8, 84u8, 72u8, 0u8, 77u8, 85u8, 0u8, 77u8, 71u8, 0u8, 77u8, 90u8,
+ 0u8, 67u8, 77u8, 0u8, 78u8, 80u8, 0u8, 84u8, 90u8, 0u8, 77u8, 72u8, 0u8,
+ 78u8, 90u8, 0u8, 67u8, 65u8, 0u8, 73u8, 68u8, 0u8, 77u8, 75u8, 0u8, 73u8,
+ 78u8, 0u8, 83u8, 68u8, 0u8, 77u8, 78u8, 0u8, 73u8, 78u8, 0u8, 77u8, 77u8,
+ 0u8, 82u8, 79u8, 0u8, 67u8, 65u8, 0u8, 67u8, 65u8, 0u8, 66u8, 70u8, 0u8,
+ 73u8, 78u8, 0u8, 78u8, 80u8, 0u8, 82u8, 85u8, 0u8, 66u8, 68u8, 0u8, 77u8,
+ 89u8, 0u8, 77u8, 84u8, 0u8, 73u8, 78u8, 0u8, 67u8, 77u8, 0u8, 85u8, 83u8,
+ 0u8, 80u8, 75u8, 0u8, 77u8, 76u8, 0u8, 73u8, 78u8, 0u8, 73u8, 68u8, 0u8,
+ 85u8, 83u8, 0u8, 90u8, 87u8, 0u8, 77u8, 77u8, 0u8, 82u8, 85u8, 0u8, 85u8,
+ 71u8, 0u8, 73u8, 82u8, 0u8, 73u8, 82u8, 0u8, 78u8, 82u8, 0u8, 67u8, 78u8,
+ 0u8, 73u8, 84u8, 0u8, 78u8, 65u8, 0u8, 78u8, 79u8, 0u8, 77u8, 88u8, 0u8,
+ 90u8, 87u8, 0u8, 77u8, 90u8, 0u8, 68u8, 69u8, 0u8, 78u8, 80u8, 0u8, 78u8,
+ 80u8, 0u8, 78u8, 65u8, 0u8, 77u8, 90u8, 0u8, 77u8, 88u8, 0u8, 77u8, 88u8,
+ 0u8, 73u8, 68u8, 0u8, 78u8, 85u8, 0u8, 73u8, 78u8, 0u8, 78u8, 76u8, 0u8,
+ 67u8, 77u8, 0u8, 78u8, 79u8, 0u8, 67u8, 77u8, 0u8, 73u8, 78u8, 0u8, 78u8,
+ 79u8, 0u8, 84u8, 72u8, 0u8, 73u8, 78u8, 0u8, 83u8, 69u8, 0u8, 71u8, 78u8,
+ 0u8, 90u8, 65u8, 0u8, 67u8, 65u8, 0u8, 90u8, 65u8, 0u8, 73u8, 78u8, 0u8,
+ 83u8, 83u8, 0u8, 85u8, 83u8, 0u8, 67u8, 78u8, 0u8, 77u8, 87u8, 0u8, 84u8,
+ 90u8, 0u8, 85u8, 71u8, 0u8, 71u8, 72u8, 0u8, 70u8, 82u8, 0u8, 67u8, 65u8,
+ 0u8, 67u8, 65u8, 0u8, 67u8, 65u8, 0u8, 69u8, 84u8, 0u8, 73u8, 78u8, 0u8,
+ 71u8, 69u8, 0u8, 85u8, 83u8, 0u8, 77u8, 78u8, 0u8, 49u8, 52u8, 51u8, 73u8,
+ 78u8, 0u8, 80u8, 72u8, 0u8, 73u8, 82u8, 0u8, 80u8, 72u8, 0u8, 65u8, 87u8,
+ 0u8, 80u8, 87u8, 0u8, 70u8, 82u8, 0u8, 78u8, 71u8, 0u8, 85u8, 83u8, 0u8,
+ 67u8, 65u8, 0u8, 73u8, 82u8, 0u8, 68u8, 69u8, 0u8, 76u8, 66u8, 0u8, 83u8,
+ 66u8, 0u8, 73u8, 78u8, 0u8, 75u8, 69u8, 0u8, 80u8, 76u8, 0u8, 73u8, 84u8,
+ 0u8, 71u8, 82u8, 0u8, 70u8, 77u8, 0u8, 73u8, 78u8, 0u8, 67u8, 65u8, 0u8,
+ 80u8, 75u8, 0u8, 73u8, 82u8, 0u8, 48u8, 48u8, 49u8, 65u8, 70u8, 0u8, 66u8,
+ 82u8, 0u8, 71u8, 65u8, 0u8, 80u8, 69u8, 0u8, 71u8, 84u8, 0u8, 69u8, 67u8,
+ 0u8, 73u8, 78u8, 0u8, 82u8, 69u8, 0u8, 73u8, 68u8, 0u8, 73u8, 84u8, 0u8,
+ 77u8, 77u8, 0u8, 73u8, 78u8, 0u8, 77u8, 65u8, 0u8, 78u8, 80u8, 0u8, 66u8,
+ 68u8, 0u8, 67u8, 72u8, 0u8, 70u8, 73u8, 0u8, 67u8, 72u8, 0u8, 73u8, 82u8,
+ 0u8, 83u8, 69u8, 0u8, 66u8, 73u8, 0u8, 77u8, 90u8, 0u8, 82u8, 79u8, 0u8,
+ 73u8, 68u8, 0u8, 84u8, 90u8, 0u8, 70u8, 74u8, 0u8, 82u8, 85u8, 0u8, 85u8,
+ 65u8, 0u8, 83u8, 66u8, 0u8, 82u8, 87u8, 0u8, 84u8, 90u8, 0u8, 74u8, 80u8,
+ 0u8, 73u8, 78u8, 0u8, 71u8, 72u8, 0u8, 82u8, 85u8, 0u8, 75u8, 69u8, 0u8,
+ 73u8, 68u8, 0u8, 73u8, 78u8, 0u8, 83u8, 78u8, 0u8, 73u8, 78u8, 0u8, 84u8,
+ 90u8, 0u8, 73u8, 84u8, 0u8, 73u8, 78u8, 0u8, 73u8, 84u8, 0u8, 71u8, 66u8,
+ 0u8, 80u8, 75u8, 0u8, 73u8, 84u8, 0u8, 73u8, 82u8, 0u8, 78u8, 79u8, 0u8,
+ 67u8, 73u8, 0u8, 77u8, 90u8, 0u8, 77u8, 88u8, 0u8, 77u8, 76u8, 0u8, 67u8,
+ 70u8, 0u8, 73u8, 69u8, 0u8, 76u8, 84u8, 0u8, 77u8, 65u8, 0u8, 77u8, 77u8,
+ 0u8, 76u8, 75u8, 0u8, 69u8, 84u8, 0u8, 83u8, 75u8, 0u8, 80u8, 75u8, 0u8,
+ 83u8, 73u8, 0u8, 80u8, 76u8, 0u8, 73u8, 68u8, 0u8, 87u8, 83u8, 0u8, 83u8,
+ 69u8, 0u8, 65u8, 79u8, 0u8, 83u8, 69u8, 0u8, 70u8, 73u8, 0u8, 73u8, 76u8,
+ 0u8, 70u8, 73u8, 0u8, 90u8, 87u8, 0u8, 77u8, 89u8, 0u8, 77u8, 76u8, 0u8,
+ 83u8, 79u8, 0u8, 85u8, 90u8, 0u8, 84u8, 72u8, 0u8, 65u8, 76u8, 0u8, 82u8,
+ 83u8, 0u8, 73u8, 78u8, 0u8, 83u8, 82u8, 0u8, 83u8, 78u8, 0u8, 73u8, 78u8,
+ 0u8, 90u8, 65u8, 0u8, 69u8, 82u8, 0u8, 90u8, 65u8, 0u8, 68u8, 69u8, 0u8,
+ 73u8, 68u8, 0u8, 84u8, 90u8, 0u8, 71u8, 78u8, 0u8, 83u8, 69u8, 0u8, 84u8,
+ 90u8, 0u8, 89u8, 84u8, 0u8, 67u8, 68u8, 0u8, 68u8, 69u8, 0u8, 73u8, 78u8,
+ 0u8, 73u8, 68u8, 0u8, 66u8, 68u8, 0u8, 73u8, 81u8, 0u8, 80u8, 76u8, 0u8,
+ 73u8, 78u8, 0u8, 78u8, 80u8, 0u8, 80u8, 72u8, 0u8, 73u8, 78u8, 0u8, 67u8,
+ 78u8, 0u8, 78u8, 80u8, 0u8, 78u8, 80u8, 0u8, 77u8, 89u8, 0u8, 73u8, 78u8,
+ 0u8, 83u8, 76u8, 0u8, 85u8, 71u8, 0u8, 84u8, 76u8, 0u8, 84u8, 74u8, 0u8,
+ 84u8, 72u8, 0u8, 78u8, 80u8, 0u8, 78u8, 80u8, 0u8, 78u8, 80u8, 0u8, 69u8,
+ 84u8, 0u8, 69u8, 82u8, 0u8, 78u8, 71u8, 0u8, 84u8, 77u8, 0u8, 84u8, 75u8,
+ 0u8, 65u8, 90u8, 0u8, 78u8, 80u8, 0u8, 80u8, 72u8, 0u8, 65u8, 90u8, 0u8,
+ 78u8, 69u8, 0u8, 90u8, 65u8, 0u8, 84u8, 79u8, 0u8, 77u8, 87u8, 0u8, 48u8,
+ 48u8, 49u8, 80u8, 71u8, 0u8, 84u8, 82u8, 0u8, 84u8, 82u8, 0u8, 84u8, 87u8,
+ 0u8, 80u8, 75u8, 0u8, 90u8, 65u8, 0u8, 71u8, 82u8, 0u8, 78u8, 80u8, 0u8,
+ 80u8, 72u8, 0u8, 66u8, 84u8, 0u8, 82u8, 85u8, 0u8, 85u8, 71u8, 0u8, 84u8,
+ 72u8, 0u8, 65u8, 90u8, 0u8, 77u8, 87u8, 0u8, 84u8, 86u8, 0u8, 78u8, 69u8,
+ 0u8, 67u8, 78u8, 0u8, 73u8, 78u8, 0u8, 80u8, 70u8, 0u8, 82u8, 85u8, 0u8,
+ 77u8, 65u8, 0u8, 82u8, 85u8, 0u8, 82u8, 85u8, 0u8, 67u8, 78u8, 0u8, 83u8,
+ 89u8, 0u8, 85u8, 65u8, 0u8, 70u8, 77u8, 0u8, 65u8, 79u8, 0u8, 73u8, 78u8,
+ 0u8, 73u8, 78u8, 0u8, 80u8, 75u8, 0u8, 85u8, 90u8, 0u8, 76u8, 82u8, 0u8,
+ 90u8, 65u8, 0u8, 73u8, 84u8, 0u8, 82u8, 85u8, 0u8, 86u8, 78u8, 0u8, 83u8,
+ 88u8, 0u8, 66u8, 69u8, 0u8, 68u8, 69u8, 0u8, 77u8, 90u8, 0u8, 48u8, 48u8,
+ 49u8, 82u8, 85u8, 0u8, 69u8, 69u8, 0u8, 84u8, 90u8, 0u8, 66u8, 69u8, 0u8,
+ 67u8, 72u8, 0u8, 69u8, 84u8, 0u8, 80u8, 72u8, 0u8, 65u8, 85u8, 0u8, 73u8,
+ 78u8, 0u8, 73u8, 78u8, 0u8, 87u8, 70u8, 0u8, 75u8, 77u8, 0u8, 83u8, 78u8,
+ 0u8, 73u8, 78u8, 0u8, 73u8, 78u8, 0u8, 67u8, 78u8, 0u8, 66u8, 82u8, 0u8,
+ 85u8, 90u8, 0u8, 84u8, 82u8, 0u8, 90u8, 65u8, 0u8, 84u8, 82u8, 0u8, 84u8,
+ 82u8, 0u8, 71u8, 69u8, 0u8, 67u8, 78u8, 0u8, 83u8, 68u8, 0u8, 83u8, 65u8,
+ 0u8, 73u8, 78u8, 0u8, 85u8, 71u8, 0u8, 73u8, 82u8, 0u8, 89u8, 69u8, 0u8,
+ 78u8, 80u8, 0u8, 77u8, 90u8, 0u8, 70u8, 77u8, 0u8, 67u8, 77u8, 0u8, 67u8,
+ 77u8, 0u8, 48u8, 48u8, 49u8, 78u8, 71u8, 0u8, 66u8, 82u8, 0u8, 77u8, 88u8,
+ 0u8, 72u8, 75u8, 0u8, 67u8, 78u8, 0u8, 83u8, 68u8, 0u8, 75u8, 77u8, 0u8,
+ 78u8, 76u8, 0u8, 77u8, 65u8, 0u8, 67u8, 78u8, 0u8, 67u8, 78u8, 0u8, 67u8,
+ 78u8, 0u8, 84u8, 71u8, 0u8, 77u8, 89u8, 0u8, 90u8, 65u8, 0u8, 84u8, 82u8,
+ 0u8,
+ ])
+ },
+ )
+ },
+ ls2r: unsafe {
+ #[allow(unused_unsafe)]
+ ::zerovec::ZeroMap2d::from_parts_unchecked(
+ unsafe {
+ ::zerovec::ZeroVec::from_bytes_unchecked(&[
+ 97u8, 114u8, 99u8, 97u8, 122u8, 0u8, 99u8, 117u8, 0u8, 101u8, 110u8, 0u8,
+ 102u8, 102u8, 0u8, 103u8, 114u8, 99u8, 107u8, 107u8, 0u8, 107u8, 117u8,
+ 0u8, 107u8, 121u8, 0u8, 108u8, 105u8, 102u8, 109u8, 97u8, 110u8, 109u8,
+ 110u8, 0u8, 112u8, 97u8, 0u8, 112u8, 97u8, 108u8, 115u8, 100u8, 0u8, 116u8,
+ 103u8, 0u8, 117u8, 103u8, 0u8, 117u8, 110u8, 114u8, 117u8, 122u8, 0u8,
+ 121u8, 117u8, 101u8, 122u8, 104u8, 0u8,
+ ])
+ },
+ unsafe {
+ ::zerovec::ZeroVec::from_bytes_unchecked(&[
+ 2u8, 0u8, 0u8, 0u8, 3u8, 0u8, 0u8, 0u8, 4u8, 0u8, 0u8, 0u8, 5u8, 0u8, 0u8,
+ 0u8, 6u8, 0u8, 0u8, 0u8, 7u8, 0u8, 0u8, 0u8, 8u8, 0u8, 0u8, 0u8, 10u8, 0u8,
+ 0u8, 0u8, 12u8, 0u8, 0u8, 0u8, 13u8, 0u8, 0u8, 0u8, 14u8, 0u8, 0u8, 0u8,
+ 15u8, 0u8, 0u8, 0u8, 16u8, 0u8, 0u8, 0u8, 17u8, 0u8, 0u8, 0u8, 20u8, 0u8,
+ 0u8, 0u8, 21u8, 0u8, 0u8, 0u8, 22u8, 0u8, 0u8, 0u8, 23u8, 0u8, 0u8, 0u8,
+ 24u8, 0u8, 0u8, 0u8, 25u8, 0u8, 0u8, 0u8, 28u8, 0u8, 0u8, 0u8,
+ ])
+ },
+ unsafe {
+ ::zerovec::ZeroVec::from_bytes_unchecked(&[
+ 78u8, 98u8, 97u8, 116u8, 80u8, 97u8, 108u8, 109u8, 65u8, 114u8, 97u8, 98u8,
+ 71u8, 108u8, 97u8, 103u8, 83u8, 104u8, 97u8, 119u8, 65u8, 100u8, 108u8,
+ 109u8, 76u8, 105u8, 110u8, 98u8, 65u8, 114u8, 97u8, 98u8, 65u8, 114u8,
+ 97u8, 98u8, 89u8, 101u8, 122u8, 105u8, 65u8, 114u8, 97u8, 98u8, 76u8, 97u8,
+ 116u8, 110u8, 76u8, 105u8, 109u8, 98u8, 78u8, 107u8, 111u8, 111u8, 77u8,
+ 111u8, 110u8, 103u8, 65u8, 114u8, 97u8, 98u8, 80u8, 104u8, 108u8, 112u8,
+ 68u8, 101u8, 118u8, 97u8, 75u8, 104u8, 111u8, 106u8, 83u8, 105u8, 110u8,
+ 100u8, 65u8, 114u8, 97u8, 98u8, 67u8, 121u8, 114u8, 108u8, 68u8, 101u8,
+ 118u8, 97u8, 65u8, 114u8, 97u8, 98u8, 72u8, 97u8, 110u8, 115u8, 66u8,
+ 111u8, 112u8, 111u8, 72u8, 97u8, 110u8, 98u8, 72u8, 97u8, 110u8, 116u8,
+ ])
+ },
+ unsafe {
+ ::zerovec::ZeroVec::from_bytes_unchecked(&[
+ 74u8, 79u8, 0u8, 83u8, 89u8, 0u8, 73u8, 82u8, 0u8, 66u8, 71u8, 0u8, 71u8,
+ 66u8, 0u8, 71u8, 78u8, 0u8, 71u8, 82u8, 0u8, 67u8, 78u8, 0u8, 73u8, 81u8,
+ 0u8, 71u8, 69u8, 0u8, 67u8, 78u8, 0u8, 84u8, 82u8, 0u8, 73u8, 78u8, 0u8,
+ 71u8, 78u8, 0u8, 67u8, 78u8, 0u8, 80u8, 75u8, 0u8, 67u8, 78u8, 0u8, 73u8,
+ 78u8, 0u8, 73u8, 78u8, 0u8, 73u8, 78u8, 0u8, 80u8, 75u8, 0u8, 75u8, 90u8,
+ 0u8, 78u8, 80u8, 0u8, 65u8, 70u8, 0u8, 67u8, 78u8, 0u8, 84u8, 87u8, 0u8,
+ 84u8, 87u8, 0u8, 84u8, 87u8, 0u8,
+ ])
+ },
+ )
+ },
+}
diff --git a/compiler/rustc_baked_icu_data/src/data/fallback/parents_v1.rs b/compiler/rustc_baked_icu_data/src/data/fallback/parents_v1.rs
deleted file mode 100644
index f07b4b806..000000000
--- a/compiler/rustc_baked_icu_data/src/data/fallback/parents_v1.rs
+++ /dev/null
@@ -1,207 +0,0 @@
-// @generated
-type DataStruct = < :: icu_provider_adapters :: fallback :: provider :: LocaleFallbackParentsV1Marker as :: icu_provider :: DataMarker > :: Yokeable ;
-pub static DATA: litemap::LiteMap<&str, &DataStruct, &[(&str, &DataStruct)]> =
- litemap::LiteMap::from_sorted_store_unchecked(&[("und", UND)]);
-static UND: &DataStruct = &::icu_provider_adapters::fallback::provider::LocaleFallbackParentsV1 {
- parents: unsafe {
- #[allow(unused_unsafe)]
- ::zerovec::ZeroMap::from_parts_unchecked(
- unsafe {
- ::zerovec::VarZeroVec::from_bytes_unchecked(&[
- 131u8, 0u8, 0u8, 0u8, 0u8, 0u8, 6u8, 0u8, 11u8, 0u8, 16u8, 0u8, 21u8, 0u8,
- 26u8, 0u8, 31u8, 0u8, 36u8, 0u8, 41u8, 0u8, 46u8, 0u8, 51u8, 0u8, 56u8, 0u8,
- 61u8, 0u8, 66u8, 0u8, 71u8, 0u8, 76u8, 0u8, 81u8, 0u8, 86u8, 0u8, 91u8, 0u8,
- 96u8, 0u8, 101u8, 0u8, 106u8, 0u8, 111u8, 0u8, 116u8, 0u8, 121u8, 0u8, 126u8,
- 0u8, 131u8, 0u8, 136u8, 0u8, 141u8, 0u8, 146u8, 0u8, 151u8, 0u8, 156u8, 0u8,
- 161u8, 0u8, 166u8, 0u8, 171u8, 0u8, 176u8, 0u8, 181u8, 0u8, 186u8, 0u8, 191u8,
- 0u8, 196u8, 0u8, 201u8, 0u8, 206u8, 0u8, 211u8, 0u8, 216u8, 0u8, 221u8, 0u8,
- 226u8, 0u8, 231u8, 0u8, 236u8, 0u8, 241u8, 0u8, 246u8, 0u8, 251u8, 0u8, 0u8,
- 1u8, 5u8, 1u8, 10u8, 1u8, 15u8, 1u8, 20u8, 1u8, 25u8, 1u8, 30u8, 1u8, 35u8,
- 1u8, 40u8, 1u8, 45u8, 1u8, 50u8, 1u8, 55u8, 1u8, 60u8, 1u8, 65u8, 1u8, 70u8,
- 1u8, 75u8, 1u8, 80u8, 1u8, 85u8, 1u8, 90u8, 1u8, 95u8, 1u8, 100u8, 1u8, 105u8,
- 1u8, 110u8, 1u8, 115u8, 1u8, 120u8, 1u8, 125u8, 1u8, 130u8, 1u8, 135u8, 1u8,
- 140u8, 1u8, 145u8, 1u8, 150u8, 1u8, 155u8, 1u8, 160u8, 1u8, 165u8, 1u8, 170u8,
- 1u8, 175u8, 1u8, 180u8, 1u8, 185u8, 1u8, 190u8, 1u8, 195u8, 1u8, 200u8, 1u8,
- 205u8, 1u8, 210u8, 1u8, 215u8, 1u8, 220u8, 1u8, 225u8, 1u8, 230u8, 1u8, 235u8,
- 1u8, 240u8, 1u8, 245u8, 1u8, 250u8, 1u8, 255u8, 1u8, 4u8, 2u8, 9u8, 2u8, 14u8,
- 2u8, 19u8, 2u8, 24u8, 2u8, 29u8, 2u8, 34u8, 2u8, 39u8, 2u8, 44u8, 2u8, 49u8,
- 2u8, 54u8, 2u8, 59u8, 2u8, 64u8, 2u8, 71u8, 2u8, 73u8, 2u8, 75u8, 2u8, 77u8,
- 2u8, 82u8, 2u8, 87u8, 2u8, 92u8, 2u8, 97u8, 2u8, 102u8, 2u8, 107u8, 2u8, 112u8,
- 2u8, 117u8, 2u8, 122u8, 2u8, 127u8, 2u8, 132u8, 2u8, 101u8, 110u8, 45u8, 49u8,
- 53u8, 48u8, 101u8, 110u8, 45u8, 65u8, 71u8, 101u8, 110u8, 45u8, 65u8, 73u8,
- 101u8, 110u8, 45u8, 65u8, 84u8, 101u8, 110u8, 45u8, 65u8, 85u8, 101u8, 110u8,
- 45u8, 66u8, 66u8, 101u8, 110u8, 45u8, 66u8, 69u8, 101u8, 110u8, 45u8, 66u8,
- 77u8, 101u8, 110u8, 45u8, 66u8, 83u8, 101u8, 110u8, 45u8, 66u8, 87u8, 101u8,
- 110u8, 45u8, 66u8, 90u8, 101u8, 110u8, 45u8, 67u8, 67u8, 101u8, 110u8, 45u8,
- 67u8, 72u8, 101u8, 110u8, 45u8, 67u8, 75u8, 101u8, 110u8, 45u8, 67u8, 77u8,
- 101u8, 110u8, 45u8, 67u8, 88u8, 101u8, 110u8, 45u8, 67u8, 89u8, 101u8, 110u8,
- 45u8, 68u8, 69u8, 101u8, 110u8, 45u8, 68u8, 71u8, 101u8, 110u8, 45u8, 68u8,
- 75u8, 101u8, 110u8, 45u8, 68u8, 77u8, 101u8, 110u8, 45u8, 69u8, 82u8, 101u8,
- 110u8, 45u8, 70u8, 73u8, 101u8, 110u8, 45u8, 70u8, 74u8, 101u8, 110u8, 45u8,
- 70u8, 75u8, 101u8, 110u8, 45u8, 70u8, 77u8, 101u8, 110u8, 45u8, 71u8, 66u8,
- 101u8, 110u8, 45u8, 71u8, 68u8, 101u8, 110u8, 45u8, 71u8, 71u8, 101u8, 110u8,
- 45u8, 71u8, 72u8, 101u8, 110u8, 45u8, 71u8, 73u8, 101u8, 110u8, 45u8, 71u8,
- 77u8, 101u8, 110u8, 45u8, 71u8, 89u8, 101u8, 110u8, 45u8, 72u8, 75u8, 101u8,
- 110u8, 45u8, 73u8, 69u8, 101u8, 110u8, 45u8, 73u8, 76u8, 101u8, 110u8, 45u8,
- 73u8, 77u8, 101u8, 110u8, 45u8, 73u8, 78u8, 101u8, 110u8, 45u8, 73u8, 79u8,
- 101u8, 110u8, 45u8, 74u8, 69u8, 101u8, 110u8, 45u8, 74u8, 77u8, 101u8, 110u8,
- 45u8, 75u8, 69u8, 101u8, 110u8, 45u8, 75u8, 73u8, 101u8, 110u8, 45u8, 75u8,
- 78u8, 101u8, 110u8, 45u8, 75u8, 89u8, 101u8, 110u8, 45u8, 76u8, 67u8, 101u8,
- 110u8, 45u8, 76u8, 82u8, 101u8, 110u8, 45u8, 76u8, 83u8, 101u8, 110u8, 45u8,
- 77u8, 71u8, 101u8, 110u8, 45u8, 77u8, 79u8, 101u8, 110u8, 45u8, 77u8, 83u8,
- 101u8, 110u8, 45u8, 77u8, 84u8, 101u8, 110u8, 45u8, 77u8, 85u8, 101u8, 110u8,
- 45u8, 77u8, 86u8, 101u8, 110u8, 45u8, 77u8, 87u8, 101u8, 110u8, 45u8, 77u8,
- 89u8, 101u8, 110u8, 45u8, 78u8, 65u8, 101u8, 110u8, 45u8, 78u8, 70u8, 101u8,
- 110u8, 45u8, 78u8, 71u8, 101u8, 110u8, 45u8, 78u8, 76u8, 101u8, 110u8, 45u8,
- 78u8, 82u8, 101u8, 110u8, 45u8, 78u8, 85u8, 101u8, 110u8, 45u8, 78u8, 90u8,
- 101u8, 110u8, 45u8, 80u8, 71u8, 101u8, 110u8, 45u8, 80u8, 75u8, 101u8, 110u8,
- 45u8, 80u8, 78u8, 101u8, 110u8, 45u8, 80u8, 87u8, 101u8, 110u8, 45u8, 82u8,
- 87u8, 101u8, 110u8, 45u8, 83u8, 66u8, 101u8, 110u8, 45u8, 83u8, 67u8, 101u8,
- 110u8, 45u8, 83u8, 68u8, 101u8, 110u8, 45u8, 83u8, 69u8, 101u8, 110u8, 45u8,
- 83u8, 71u8, 101u8, 110u8, 45u8, 83u8, 72u8, 101u8, 110u8, 45u8, 83u8, 73u8,
- 101u8, 110u8, 45u8, 83u8, 76u8, 101u8, 110u8, 45u8, 83u8, 83u8, 101u8, 110u8,
- 45u8, 83u8, 88u8, 101u8, 110u8, 45u8, 83u8, 90u8, 101u8, 110u8, 45u8, 84u8,
- 67u8, 101u8, 110u8, 45u8, 84u8, 75u8, 101u8, 110u8, 45u8, 84u8, 79u8, 101u8,
- 110u8, 45u8, 84u8, 84u8, 101u8, 110u8, 45u8, 84u8, 86u8, 101u8, 110u8, 45u8,
- 84u8, 90u8, 101u8, 110u8, 45u8, 85u8, 71u8, 101u8, 110u8, 45u8, 86u8, 67u8,
- 101u8, 110u8, 45u8, 86u8, 71u8, 101u8, 110u8, 45u8, 86u8, 85u8, 101u8, 110u8,
- 45u8, 87u8, 83u8, 101u8, 110u8, 45u8, 90u8, 65u8, 101u8, 110u8, 45u8, 90u8,
- 77u8, 101u8, 110u8, 45u8, 90u8, 87u8, 101u8, 115u8, 45u8, 65u8, 82u8, 101u8,
- 115u8, 45u8, 66u8, 79u8, 101u8, 115u8, 45u8, 66u8, 82u8, 101u8, 115u8, 45u8,
- 66u8, 90u8, 101u8, 115u8, 45u8, 67u8, 76u8, 101u8, 115u8, 45u8, 67u8, 79u8,
- 101u8, 115u8, 45u8, 67u8, 82u8, 101u8, 115u8, 45u8, 67u8, 85u8, 101u8, 115u8,
- 45u8, 68u8, 79u8, 101u8, 115u8, 45u8, 69u8, 67u8, 101u8, 115u8, 45u8, 71u8,
- 84u8, 101u8, 115u8, 45u8, 72u8, 78u8, 101u8, 115u8, 45u8, 77u8, 88u8, 101u8,
- 115u8, 45u8, 78u8, 73u8, 101u8, 115u8, 45u8, 80u8, 65u8, 101u8, 115u8, 45u8,
- 80u8, 69u8, 101u8, 115u8, 45u8, 80u8, 82u8, 101u8, 115u8, 45u8, 80u8, 89u8,
- 101u8, 115u8, 45u8, 83u8, 86u8, 101u8, 115u8, 45u8, 85u8, 83u8, 101u8, 115u8,
- 45u8, 85u8, 89u8, 101u8, 115u8, 45u8, 86u8, 69u8, 104u8, 105u8, 45u8, 76u8,
- 97u8, 116u8, 110u8, 104u8, 116u8, 110u8, 98u8, 110u8, 110u8, 112u8, 116u8,
- 45u8, 65u8, 79u8, 112u8, 116u8, 45u8, 67u8, 72u8, 112u8, 116u8, 45u8, 67u8,
- 86u8, 112u8, 116u8, 45u8, 70u8, 82u8, 112u8, 116u8, 45u8, 71u8, 81u8, 112u8,
- 116u8, 45u8, 71u8, 87u8, 112u8, 116u8, 45u8, 76u8, 85u8, 112u8, 116u8, 45u8,
- 77u8, 79u8, 112u8, 116u8, 45u8, 77u8, 90u8, 112u8, 116u8, 45u8, 83u8, 84u8,
- 112u8, 116u8, 45u8, 84u8, 76u8, 122u8, 104u8, 45u8, 72u8, 97u8, 110u8, 116u8,
- 45u8, 77u8, 79u8,
- ])
- },
- unsafe {
- ::zerovec::ZeroVec::from_bytes_unchecked(&[
- 101u8, 110u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 48u8, 48u8, 49u8, 101u8,
- 110u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 48u8, 48u8, 49u8, 101u8, 110u8, 0u8,
- 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 48u8, 48u8, 49u8, 101u8, 110u8, 0u8, 0u8, 0u8,
- 0u8, 0u8, 0u8, 1u8, 49u8, 53u8, 48u8, 101u8, 110u8, 0u8, 0u8, 0u8, 0u8, 0u8,
- 0u8, 1u8, 48u8, 48u8, 49u8, 101u8, 110u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8,
- 48u8, 48u8, 49u8, 101u8, 110u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 49u8, 53u8,
- 48u8, 101u8, 110u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 48u8, 48u8, 49u8, 101u8,
- 110u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 48u8, 48u8, 49u8, 101u8, 110u8, 0u8,
- 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 48u8, 48u8, 49u8, 101u8, 110u8, 0u8, 0u8, 0u8,
- 0u8, 0u8, 0u8, 1u8, 48u8, 48u8, 49u8, 101u8, 110u8, 0u8, 0u8, 0u8, 0u8, 0u8,
- 0u8, 1u8, 48u8, 48u8, 49u8, 101u8, 110u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8,
- 49u8, 53u8, 48u8, 101u8, 110u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 48u8, 48u8,
- 49u8, 101u8, 110u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 48u8, 48u8, 49u8, 101u8,
- 110u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 48u8, 48u8, 49u8, 101u8, 110u8, 0u8,
- 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 48u8, 48u8, 49u8, 101u8, 110u8, 0u8, 0u8, 0u8,
- 0u8, 0u8, 0u8, 1u8, 49u8, 53u8, 48u8, 101u8, 110u8, 0u8, 0u8, 0u8, 0u8, 0u8,
- 0u8, 1u8, 48u8, 48u8, 49u8, 101u8, 110u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8,
- 49u8, 53u8, 48u8, 101u8, 110u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 48u8, 48u8,
- 49u8, 101u8, 110u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 48u8, 48u8, 49u8, 101u8,
- 110u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 49u8, 53u8, 48u8, 101u8, 110u8, 0u8,
- 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 48u8, 48u8, 49u8, 101u8, 110u8, 0u8, 0u8, 0u8,
- 0u8, 0u8, 0u8, 1u8, 48u8, 48u8, 49u8, 101u8, 110u8, 0u8, 0u8, 0u8, 0u8, 0u8,
- 0u8, 1u8, 48u8, 48u8, 49u8, 101u8, 110u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8,
- 48u8, 48u8, 49u8, 101u8, 110u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 48u8, 48u8,
- 49u8, 101u8, 110u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 48u8, 48u8, 49u8, 101u8,
- 110u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 48u8, 48u8, 49u8, 101u8, 110u8, 0u8,
- 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 48u8, 48u8, 49u8, 101u8, 110u8, 0u8, 0u8, 0u8,
- 0u8, 0u8, 0u8, 1u8, 48u8, 48u8, 49u8, 101u8, 110u8, 0u8, 0u8, 0u8, 0u8, 0u8,
- 0u8, 1u8, 48u8, 48u8, 49u8, 101u8, 110u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8,
- 48u8, 48u8, 49u8, 101u8, 110u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 48u8, 48u8,
- 49u8, 101u8, 110u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 48u8, 48u8, 49u8, 101u8,
- 110u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 48u8, 48u8, 49u8, 101u8, 110u8, 0u8,
- 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 48u8, 48u8, 49u8, 101u8, 110u8, 0u8, 0u8, 0u8,
- 0u8, 0u8, 0u8, 1u8, 48u8, 48u8, 49u8, 101u8, 110u8, 0u8, 0u8, 0u8, 0u8, 0u8,
- 0u8, 1u8, 48u8, 48u8, 49u8, 101u8, 110u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8,
- 48u8, 48u8, 49u8, 101u8, 110u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 48u8, 48u8,
- 49u8, 101u8, 110u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 48u8, 48u8, 49u8, 101u8,
- 110u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 48u8, 48u8, 49u8, 101u8, 110u8, 0u8,
- 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 48u8, 48u8, 49u8, 101u8, 110u8, 0u8, 0u8, 0u8,
- 0u8, 0u8, 0u8, 1u8, 48u8, 48u8, 49u8, 101u8, 110u8, 0u8, 0u8, 0u8, 0u8, 0u8,
- 0u8, 1u8, 48u8, 48u8, 49u8, 101u8, 110u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8,
- 48u8, 48u8, 49u8, 101u8, 110u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 48u8, 48u8,
- 49u8, 101u8, 110u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 48u8, 48u8, 49u8, 101u8,
- 110u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 48u8, 48u8, 49u8, 101u8, 110u8, 0u8,
- 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 48u8, 48u8, 49u8, 101u8, 110u8, 0u8, 0u8, 0u8,
- 0u8, 0u8, 0u8, 1u8, 48u8, 48u8, 49u8, 101u8, 110u8, 0u8, 0u8, 0u8, 0u8, 0u8,
- 0u8, 1u8, 48u8, 48u8, 49u8, 101u8, 110u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8,
- 48u8, 48u8, 49u8, 101u8, 110u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 48u8, 48u8,
- 49u8, 101u8, 110u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 48u8, 48u8, 49u8, 101u8,
- 110u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 48u8, 48u8, 49u8, 101u8, 110u8, 0u8,
- 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 48u8, 48u8, 49u8, 101u8, 110u8, 0u8, 0u8, 0u8,
- 0u8, 0u8, 0u8, 1u8, 49u8, 53u8, 48u8, 101u8, 110u8, 0u8, 0u8, 0u8, 0u8, 0u8,
- 0u8, 1u8, 48u8, 48u8, 49u8, 101u8, 110u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8,
- 48u8, 48u8, 49u8, 101u8, 110u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 48u8, 48u8,
- 49u8, 101u8, 110u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 48u8, 48u8, 49u8, 101u8,
- 110u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 48u8, 48u8, 49u8, 101u8, 110u8, 0u8,
- 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 48u8, 48u8, 49u8, 101u8, 110u8, 0u8, 0u8, 0u8,
- 0u8, 0u8, 0u8, 1u8, 48u8, 48u8, 49u8, 101u8, 110u8, 0u8, 0u8, 0u8, 0u8, 0u8,
- 0u8, 1u8, 48u8, 48u8, 49u8, 101u8, 110u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8,
- 48u8, 48u8, 49u8, 101u8, 110u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 48u8, 48u8,
- 49u8, 101u8, 110u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 48u8, 48u8, 49u8, 101u8,
- 110u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 49u8, 53u8, 48u8, 101u8, 110u8, 0u8,
- 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 48u8, 48u8, 49u8, 101u8, 110u8, 0u8, 0u8, 0u8,
- 0u8, 0u8, 0u8, 1u8, 48u8, 48u8, 49u8, 101u8, 110u8, 0u8, 0u8, 0u8, 0u8, 0u8,
- 0u8, 1u8, 49u8, 53u8, 48u8, 101u8, 110u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8,
- 48u8, 48u8, 49u8, 101u8, 110u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 48u8, 48u8,
- 49u8, 101u8, 110u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 48u8, 48u8, 49u8, 101u8,
- 110u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 48u8, 48u8, 49u8, 101u8, 110u8, 0u8,
- 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 48u8, 48u8, 49u8, 101u8, 110u8, 0u8, 0u8, 0u8,
- 0u8, 0u8, 0u8, 1u8, 48u8, 48u8, 49u8, 101u8, 110u8, 0u8, 0u8, 0u8, 0u8, 0u8,
- 0u8, 1u8, 48u8, 48u8, 49u8, 101u8, 110u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8,
- 48u8, 48u8, 49u8, 101u8, 110u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 48u8, 48u8,
- 49u8, 101u8, 110u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 48u8, 48u8, 49u8, 101u8,
- 110u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 48u8, 48u8, 49u8, 101u8, 110u8, 0u8,
- 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 48u8, 48u8, 49u8, 101u8, 110u8, 0u8, 0u8, 0u8,
- 0u8, 0u8, 0u8, 1u8, 48u8, 48u8, 49u8, 101u8, 110u8, 0u8, 0u8, 0u8, 0u8, 0u8,
- 0u8, 1u8, 48u8, 48u8, 49u8, 101u8, 110u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8,
- 48u8, 48u8, 49u8, 101u8, 110u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 48u8, 48u8,
- 49u8, 101u8, 110u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 48u8, 48u8, 49u8, 101u8,
- 110u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 48u8, 48u8, 49u8, 101u8, 115u8, 0u8,
- 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 52u8, 49u8, 57u8, 101u8, 115u8, 0u8, 0u8, 0u8,
- 0u8, 0u8, 0u8, 1u8, 52u8, 49u8, 57u8, 101u8, 115u8, 0u8, 0u8, 0u8, 0u8, 0u8,
- 0u8, 1u8, 52u8, 49u8, 57u8, 101u8, 115u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8,
- 52u8, 49u8, 57u8, 101u8, 115u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 52u8, 49u8,
- 57u8, 101u8, 115u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 52u8, 49u8, 57u8, 101u8,
- 115u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 52u8, 49u8, 57u8, 101u8, 115u8, 0u8,
- 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 52u8, 49u8, 57u8, 101u8, 115u8, 0u8, 0u8, 0u8,
- 0u8, 0u8, 0u8, 1u8, 52u8, 49u8, 57u8, 101u8, 115u8, 0u8, 0u8, 0u8, 0u8, 0u8,
- 0u8, 1u8, 52u8, 49u8, 57u8, 101u8, 115u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8,
- 52u8, 49u8, 57u8, 101u8, 115u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 52u8, 49u8,
- 57u8, 101u8, 115u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 52u8, 49u8, 57u8, 101u8,
- 115u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 52u8, 49u8, 57u8, 101u8, 115u8, 0u8,
- 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 52u8, 49u8, 57u8, 101u8, 115u8, 0u8, 0u8, 0u8,
- 0u8, 0u8, 0u8, 1u8, 52u8, 49u8, 57u8, 101u8, 115u8, 0u8, 0u8, 0u8, 0u8, 0u8,
- 0u8, 1u8, 52u8, 49u8, 57u8, 101u8, 115u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8,
- 52u8, 49u8, 57u8, 101u8, 115u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 52u8, 49u8,
- 57u8, 101u8, 115u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 52u8, 49u8, 57u8, 101u8,
- 115u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 52u8, 49u8, 57u8, 101u8, 115u8, 0u8,
- 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 52u8, 49u8, 57u8, 101u8, 110u8, 0u8, 0u8, 0u8,
- 0u8, 0u8, 0u8, 1u8, 73u8, 78u8, 0u8, 102u8, 114u8, 0u8, 0u8, 0u8, 0u8, 0u8,
- 0u8, 1u8, 72u8, 84u8, 0u8, 110u8, 111u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
- 0u8, 0u8, 0u8, 110u8, 111u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
- 112u8, 116u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 80u8, 84u8, 0u8, 112u8, 116u8,
- 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 80u8, 84u8, 0u8, 112u8, 116u8, 0u8, 0u8,
- 0u8, 0u8, 0u8, 0u8, 1u8, 80u8, 84u8, 0u8, 112u8, 116u8, 0u8, 0u8, 0u8, 0u8,
- 0u8, 0u8, 1u8, 80u8, 84u8, 0u8, 112u8, 116u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
- 1u8, 80u8, 84u8, 0u8, 112u8, 116u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 80u8,
- 84u8, 0u8, 112u8, 116u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 80u8, 84u8, 0u8,
- 112u8, 116u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 80u8, 84u8, 0u8, 112u8, 116u8,
- 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 80u8, 84u8, 0u8, 112u8, 116u8, 0u8, 0u8,
- 0u8, 0u8, 0u8, 0u8, 1u8, 80u8, 84u8, 0u8, 112u8, 116u8, 0u8, 0u8, 0u8, 0u8,
- 0u8, 0u8, 1u8, 80u8, 84u8, 0u8, 122u8, 104u8, 0u8, 1u8, 72u8, 97u8, 110u8,
- 116u8, 1u8, 72u8, 75u8, 0u8,
- ])
- },
- )
- },
-};
diff --git a/compiler/rustc_baked_icu_data/src/data/fallback/parents_v1/mod.rs b/compiler/rustc_baked_icu_data/src/data/fallback/parents_v1/mod.rs
new file mode 100644
index 000000000..ce04af868
--- /dev/null
+++ b/compiler/rustc_baked_icu_data/src/data/fallback/parents_v1/mod.rs
@@ -0,0 +1,6 @@
+// @generated
+type DataStruct = < :: icu_provider_adapters :: fallback :: provider :: LocaleFallbackParentsV1Marker as :: icu_provider :: DataMarker > :: Yokeable ;
+pub fn lookup(locale: &icu_provider::DataLocale) -> Option<&'static DataStruct> {
+ locale.is_empty().then(|| &UND)
+}
+static UND: DataStruct = include!("und.rs.data");
diff --git a/compiler/rustc_baked_icu_data/src/data/fallback/parents_v1/und.rs.data b/compiler/rustc_baked_icu_data/src/data/fallback/parents_v1/und.rs.data
new file mode 100644
index 000000000..5ead95908
--- /dev/null
+++ b/compiler/rustc_baked_icu_data/src/data/fallback/parents_v1/und.rs.data
@@ -0,0 +1,216 @@
+::icu_provider_adapters::fallback::provider::LocaleFallbackParentsV1 {
+ parents: unsafe {
+ #[allow(unused_unsafe)]
+ ::zerovec::ZeroMap::from_parts_unchecked(
+ unsafe {
+ ::zerovec::VarZeroVec::from_bytes_unchecked(&[
+ 131u8, 0u8, 0u8, 0u8, 0u8, 0u8, 6u8, 0u8, 11u8, 0u8, 16u8, 0u8, 21u8, 0u8,
+ 26u8, 0u8, 31u8, 0u8, 36u8, 0u8, 41u8, 0u8, 46u8, 0u8, 51u8, 0u8, 56u8,
+ 0u8, 61u8, 0u8, 66u8, 0u8, 71u8, 0u8, 76u8, 0u8, 81u8, 0u8, 86u8, 0u8,
+ 91u8, 0u8, 96u8, 0u8, 101u8, 0u8, 106u8, 0u8, 111u8, 0u8, 116u8, 0u8,
+ 121u8, 0u8, 126u8, 0u8, 131u8, 0u8, 136u8, 0u8, 141u8, 0u8, 146u8, 0u8,
+ 151u8, 0u8, 156u8, 0u8, 161u8, 0u8, 166u8, 0u8, 171u8, 0u8, 176u8, 0u8,
+ 181u8, 0u8, 186u8, 0u8, 191u8, 0u8, 196u8, 0u8, 201u8, 0u8, 206u8, 0u8,
+ 211u8, 0u8, 216u8, 0u8, 221u8, 0u8, 226u8, 0u8, 231u8, 0u8, 236u8, 0u8,
+ 241u8, 0u8, 246u8, 0u8, 251u8, 0u8, 0u8, 1u8, 5u8, 1u8, 10u8, 1u8, 15u8,
+ 1u8, 20u8, 1u8, 25u8, 1u8, 30u8, 1u8, 35u8, 1u8, 40u8, 1u8, 45u8, 1u8,
+ 50u8, 1u8, 55u8, 1u8, 60u8, 1u8, 65u8, 1u8, 70u8, 1u8, 75u8, 1u8, 80u8,
+ 1u8, 85u8, 1u8, 90u8, 1u8, 95u8, 1u8, 100u8, 1u8, 105u8, 1u8, 110u8, 1u8,
+ 115u8, 1u8, 120u8, 1u8, 125u8, 1u8, 130u8, 1u8, 135u8, 1u8, 140u8, 1u8,
+ 145u8, 1u8, 150u8, 1u8, 155u8, 1u8, 160u8, 1u8, 165u8, 1u8, 170u8, 1u8,
+ 175u8, 1u8, 180u8, 1u8, 185u8, 1u8, 190u8, 1u8, 195u8, 1u8, 200u8, 1u8,
+ 205u8, 1u8, 210u8, 1u8, 215u8, 1u8, 220u8, 1u8, 225u8, 1u8, 230u8, 1u8,
+ 235u8, 1u8, 240u8, 1u8, 245u8, 1u8, 250u8, 1u8, 255u8, 1u8, 4u8, 2u8, 9u8,
+ 2u8, 14u8, 2u8, 19u8, 2u8, 24u8, 2u8, 29u8, 2u8, 34u8, 2u8, 39u8, 2u8,
+ 44u8, 2u8, 49u8, 2u8, 54u8, 2u8, 59u8, 2u8, 64u8, 2u8, 71u8, 2u8, 73u8,
+ 2u8, 75u8, 2u8, 77u8, 2u8, 82u8, 2u8, 87u8, 2u8, 92u8, 2u8, 97u8, 2u8,
+ 102u8, 2u8, 107u8, 2u8, 112u8, 2u8, 117u8, 2u8, 122u8, 2u8, 127u8, 2u8,
+ 132u8, 2u8, 101u8, 110u8, 45u8, 49u8, 53u8, 48u8, 101u8, 110u8, 45u8, 65u8,
+ 71u8, 101u8, 110u8, 45u8, 65u8, 73u8, 101u8, 110u8, 45u8, 65u8, 84u8,
+ 101u8, 110u8, 45u8, 65u8, 85u8, 101u8, 110u8, 45u8, 66u8, 66u8, 101u8,
+ 110u8, 45u8, 66u8, 69u8, 101u8, 110u8, 45u8, 66u8, 77u8, 101u8, 110u8,
+ 45u8, 66u8, 83u8, 101u8, 110u8, 45u8, 66u8, 87u8, 101u8, 110u8, 45u8, 66u8,
+ 90u8, 101u8, 110u8, 45u8, 67u8, 67u8, 101u8, 110u8, 45u8, 67u8, 72u8,
+ 101u8, 110u8, 45u8, 67u8, 75u8, 101u8, 110u8, 45u8, 67u8, 77u8, 101u8,
+ 110u8, 45u8, 67u8, 88u8, 101u8, 110u8, 45u8, 67u8, 89u8, 101u8, 110u8,
+ 45u8, 68u8, 69u8, 101u8, 110u8, 45u8, 68u8, 71u8, 101u8, 110u8, 45u8, 68u8,
+ 75u8, 101u8, 110u8, 45u8, 68u8, 77u8, 101u8, 110u8, 45u8, 69u8, 82u8,
+ 101u8, 110u8, 45u8, 70u8, 73u8, 101u8, 110u8, 45u8, 70u8, 74u8, 101u8,
+ 110u8, 45u8, 70u8, 75u8, 101u8, 110u8, 45u8, 70u8, 77u8, 101u8, 110u8,
+ 45u8, 71u8, 66u8, 101u8, 110u8, 45u8, 71u8, 68u8, 101u8, 110u8, 45u8, 71u8,
+ 71u8, 101u8, 110u8, 45u8, 71u8, 72u8, 101u8, 110u8, 45u8, 71u8, 73u8,
+ 101u8, 110u8, 45u8, 71u8, 77u8, 101u8, 110u8, 45u8, 71u8, 89u8, 101u8,
+ 110u8, 45u8, 72u8, 75u8, 101u8, 110u8, 45u8, 73u8, 69u8, 101u8, 110u8,
+ 45u8, 73u8, 76u8, 101u8, 110u8, 45u8, 73u8, 77u8, 101u8, 110u8, 45u8, 73u8,
+ 78u8, 101u8, 110u8, 45u8, 73u8, 79u8, 101u8, 110u8, 45u8, 74u8, 69u8,
+ 101u8, 110u8, 45u8, 74u8, 77u8, 101u8, 110u8, 45u8, 75u8, 69u8, 101u8,
+ 110u8, 45u8, 75u8, 73u8, 101u8, 110u8, 45u8, 75u8, 78u8, 101u8, 110u8,
+ 45u8, 75u8, 89u8, 101u8, 110u8, 45u8, 76u8, 67u8, 101u8, 110u8, 45u8, 76u8,
+ 82u8, 101u8, 110u8, 45u8, 76u8, 83u8, 101u8, 110u8, 45u8, 77u8, 71u8,
+ 101u8, 110u8, 45u8, 77u8, 79u8, 101u8, 110u8, 45u8, 77u8, 83u8, 101u8,
+ 110u8, 45u8, 77u8, 84u8, 101u8, 110u8, 45u8, 77u8, 85u8, 101u8, 110u8,
+ 45u8, 77u8, 86u8, 101u8, 110u8, 45u8, 77u8, 87u8, 101u8, 110u8, 45u8, 77u8,
+ 89u8, 101u8, 110u8, 45u8, 78u8, 65u8, 101u8, 110u8, 45u8, 78u8, 70u8,
+ 101u8, 110u8, 45u8, 78u8, 71u8, 101u8, 110u8, 45u8, 78u8, 76u8, 101u8,
+ 110u8, 45u8, 78u8, 82u8, 101u8, 110u8, 45u8, 78u8, 85u8, 101u8, 110u8,
+ 45u8, 78u8, 90u8, 101u8, 110u8, 45u8, 80u8, 71u8, 101u8, 110u8, 45u8, 80u8,
+ 75u8, 101u8, 110u8, 45u8, 80u8, 78u8, 101u8, 110u8, 45u8, 80u8, 87u8,
+ 101u8, 110u8, 45u8, 82u8, 87u8, 101u8, 110u8, 45u8, 83u8, 66u8, 101u8,
+ 110u8, 45u8, 83u8, 67u8, 101u8, 110u8, 45u8, 83u8, 68u8, 101u8, 110u8,
+ 45u8, 83u8, 69u8, 101u8, 110u8, 45u8, 83u8, 71u8, 101u8, 110u8, 45u8, 83u8,
+ 72u8, 101u8, 110u8, 45u8, 83u8, 73u8, 101u8, 110u8, 45u8, 83u8, 76u8,
+ 101u8, 110u8, 45u8, 83u8, 83u8, 101u8, 110u8, 45u8, 83u8, 88u8, 101u8,
+ 110u8, 45u8, 83u8, 90u8, 101u8, 110u8, 45u8, 84u8, 67u8, 101u8, 110u8,
+ 45u8, 84u8, 75u8, 101u8, 110u8, 45u8, 84u8, 79u8, 101u8, 110u8, 45u8, 84u8,
+ 84u8, 101u8, 110u8, 45u8, 84u8, 86u8, 101u8, 110u8, 45u8, 84u8, 90u8,
+ 101u8, 110u8, 45u8, 85u8, 71u8, 101u8, 110u8, 45u8, 86u8, 67u8, 101u8,
+ 110u8, 45u8, 86u8, 71u8, 101u8, 110u8, 45u8, 86u8, 85u8, 101u8, 110u8,
+ 45u8, 87u8, 83u8, 101u8, 110u8, 45u8, 90u8, 65u8, 101u8, 110u8, 45u8, 90u8,
+ 77u8, 101u8, 110u8, 45u8, 90u8, 87u8, 101u8, 115u8, 45u8, 65u8, 82u8,
+ 101u8, 115u8, 45u8, 66u8, 79u8, 101u8, 115u8, 45u8, 66u8, 82u8, 101u8,
+ 115u8, 45u8, 66u8, 90u8, 101u8, 115u8, 45u8, 67u8, 76u8, 101u8, 115u8,
+ 45u8, 67u8, 79u8, 101u8, 115u8, 45u8, 67u8, 82u8, 101u8, 115u8, 45u8, 67u8,
+ 85u8, 101u8, 115u8, 45u8, 68u8, 79u8, 101u8, 115u8, 45u8, 69u8, 67u8,
+ 101u8, 115u8, 45u8, 71u8, 84u8, 101u8, 115u8, 45u8, 72u8, 78u8, 101u8,
+ 115u8, 45u8, 77u8, 88u8, 101u8, 115u8, 45u8, 78u8, 73u8, 101u8, 115u8,
+ 45u8, 80u8, 65u8, 101u8, 115u8, 45u8, 80u8, 69u8, 101u8, 115u8, 45u8, 80u8,
+ 82u8, 101u8, 115u8, 45u8, 80u8, 89u8, 101u8, 115u8, 45u8, 83u8, 86u8,
+ 101u8, 115u8, 45u8, 85u8, 83u8, 101u8, 115u8, 45u8, 85u8, 89u8, 101u8,
+ 115u8, 45u8, 86u8, 69u8, 104u8, 105u8, 45u8, 76u8, 97u8, 116u8, 110u8,
+ 104u8, 116u8, 110u8, 98u8, 110u8, 110u8, 112u8, 116u8, 45u8, 65u8, 79u8,
+ 112u8, 116u8, 45u8, 67u8, 72u8, 112u8, 116u8, 45u8, 67u8, 86u8, 112u8,
+ 116u8, 45u8, 70u8, 82u8, 112u8, 116u8, 45u8, 71u8, 81u8, 112u8, 116u8,
+ 45u8, 71u8, 87u8, 112u8, 116u8, 45u8, 76u8, 85u8, 112u8, 116u8, 45u8, 77u8,
+ 79u8, 112u8, 116u8, 45u8, 77u8, 90u8, 112u8, 116u8, 45u8, 83u8, 84u8,
+ 112u8, 116u8, 45u8, 84u8, 76u8, 122u8, 104u8, 45u8, 72u8, 97u8, 110u8,
+ 116u8, 45u8, 77u8, 79u8,
+ ])
+ },
+ unsafe {
+ ::zerovec::ZeroVec::from_bytes_unchecked(&[
+ 101u8, 110u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 48u8, 48u8, 49u8, 101u8,
+ 110u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 48u8, 48u8, 49u8, 101u8, 110u8,
+ 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 48u8, 48u8, 49u8, 101u8, 110u8, 0u8,
+ 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 49u8, 53u8, 48u8, 101u8, 110u8, 0u8, 0u8,
+ 0u8, 0u8, 0u8, 0u8, 1u8, 48u8, 48u8, 49u8, 101u8, 110u8, 0u8, 0u8, 0u8,
+ 0u8, 0u8, 0u8, 1u8, 48u8, 48u8, 49u8, 101u8, 110u8, 0u8, 0u8, 0u8, 0u8,
+ 0u8, 0u8, 1u8, 49u8, 53u8, 48u8, 101u8, 110u8, 0u8, 0u8, 0u8, 0u8, 0u8,
+ 0u8, 1u8, 48u8, 48u8, 49u8, 101u8, 110u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
+ 1u8, 48u8, 48u8, 49u8, 101u8, 110u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8,
+ 48u8, 48u8, 49u8, 101u8, 110u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 48u8,
+ 48u8, 49u8, 101u8, 110u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 48u8, 48u8,
+ 49u8, 101u8, 110u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 49u8, 53u8, 48u8,
+ 101u8, 110u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 48u8, 48u8, 49u8, 101u8,
+ 110u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 48u8, 48u8, 49u8, 101u8, 110u8,
+ 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 48u8, 48u8, 49u8, 101u8, 110u8, 0u8,
+ 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 48u8, 48u8, 49u8, 101u8, 110u8, 0u8, 0u8,
+ 0u8, 0u8, 0u8, 0u8, 1u8, 49u8, 53u8, 48u8, 101u8, 110u8, 0u8, 0u8, 0u8,
+ 0u8, 0u8, 0u8, 1u8, 48u8, 48u8, 49u8, 101u8, 110u8, 0u8, 0u8, 0u8, 0u8,
+ 0u8, 0u8, 1u8, 49u8, 53u8, 48u8, 101u8, 110u8, 0u8, 0u8, 0u8, 0u8, 0u8,
+ 0u8, 1u8, 48u8, 48u8, 49u8, 101u8, 110u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
+ 1u8, 48u8, 48u8, 49u8, 101u8, 110u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8,
+ 49u8, 53u8, 48u8, 101u8, 110u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 48u8,
+ 48u8, 49u8, 101u8, 110u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 48u8, 48u8,
+ 49u8, 101u8, 110u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 48u8, 48u8, 49u8,
+ 101u8, 110u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 48u8, 48u8, 49u8, 101u8,
+ 110u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 48u8, 48u8, 49u8, 101u8, 110u8,
+ 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 48u8, 48u8, 49u8, 101u8, 110u8, 0u8,
+ 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 48u8, 48u8, 49u8, 101u8, 110u8, 0u8, 0u8,
+ 0u8, 0u8, 0u8, 0u8, 1u8, 48u8, 48u8, 49u8, 101u8, 110u8, 0u8, 0u8, 0u8,
+ 0u8, 0u8, 0u8, 1u8, 48u8, 48u8, 49u8, 101u8, 110u8, 0u8, 0u8, 0u8, 0u8,
+ 0u8, 0u8, 1u8, 48u8, 48u8, 49u8, 101u8, 110u8, 0u8, 0u8, 0u8, 0u8, 0u8,
+ 0u8, 1u8, 48u8, 48u8, 49u8, 101u8, 110u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
+ 1u8, 48u8, 48u8, 49u8, 101u8, 110u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8,
+ 48u8, 48u8, 49u8, 101u8, 110u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 48u8,
+ 48u8, 49u8, 101u8, 110u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 48u8, 48u8,
+ 49u8, 101u8, 110u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 48u8, 48u8, 49u8,
+ 101u8, 110u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 48u8, 48u8, 49u8, 101u8,
+ 110u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 48u8, 48u8, 49u8, 101u8, 110u8,
+ 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 48u8, 48u8, 49u8, 101u8, 110u8, 0u8,
+ 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 48u8, 48u8, 49u8, 101u8, 110u8, 0u8, 0u8,
+ 0u8, 0u8, 0u8, 0u8, 1u8, 48u8, 48u8, 49u8, 101u8, 110u8, 0u8, 0u8, 0u8,
+ 0u8, 0u8, 0u8, 1u8, 48u8, 48u8, 49u8, 101u8, 110u8, 0u8, 0u8, 0u8, 0u8,
+ 0u8, 0u8, 1u8, 48u8, 48u8, 49u8, 101u8, 110u8, 0u8, 0u8, 0u8, 0u8, 0u8,
+ 0u8, 1u8, 48u8, 48u8, 49u8, 101u8, 110u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
+ 1u8, 48u8, 48u8, 49u8, 101u8, 110u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8,
+ 48u8, 48u8, 49u8, 101u8, 110u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 48u8,
+ 48u8, 49u8, 101u8, 110u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 48u8, 48u8,
+ 49u8, 101u8, 110u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 48u8, 48u8, 49u8,
+ 101u8, 110u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 48u8, 48u8, 49u8, 101u8,
+ 110u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 48u8, 48u8, 49u8, 101u8, 110u8,
+ 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 48u8, 48u8, 49u8, 101u8, 110u8, 0u8,
+ 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 48u8, 48u8, 49u8, 101u8, 110u8, 0u8, 0u8,
+ 0u8, 0u8, 0u8, 0u8, 1u8, 48u8, 48u8, 49u8, 101u8, 110u8, 0u8, 0u8, 0u8,
+ 0u8, 0u8, 0u8, 1u8, 48u8, 48u8, 49u8, 101u8, 110u8, 0u8, 0u8, 0u8, 0u8,
+ 0u8, 0u8, 1u8, 48u8, 48u8, 49u8, 101u8, 110u8, 0u8, 0u8, 0u8, 0u8, 0u8,
+ 0u8, 1u8, 49u8, 53u8, 48u8, 101u8, 110u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
+ 1u8, 48u8, 48u8, 49u8, 101u8, 110u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8,
+ 48u8, 48u8, 49u8, 101u8, 110u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 48u8,
+ 48u8, 49u8, 101u8, 110u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 48u8, 48u8,
+ 49u8, 101u8, 110u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 48u8, 48u8, 49u8,
+ 101u8, 110u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 48u8, 48u8, 49u8, 101u8,
+ 110u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 48u8, 48u8, 49u8, 101u8, 110u8,
+ 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 48u8, 48u8, 49u8, 101u8, 110u8, 0u8,
+ 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 48u8, 48u8, 49u8, 101u8, 110u8, 0u8, 0u8,
+ 0u8, 0u8, 0u8, 0u8, 1u8, 48u8, 48u8, 49u8, 101u8, 110u8, 0u8, 0u8, 0u8,
+ 0u8, 0u8, 0u8, 1u8, 48u8, 48u8, 49u8, 101u8, 110u8, 0u8, 0u8, 0u8, 0u8,
+ 0u8, 0u8, 1u8, 49u8, 53u8, 48u8, 101u8, 110u8, 0u8, 0u8, 0u8, 0u8, 0u8,
+ 0u8, 1u8, 48u8, 48u8, 49u8, 101u8, 110u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
+ 1u8, 48u8, 48u8, 49u8, 101u8, 110u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8,
+ 49u8, 53u8, 48u8, 101u8, 110u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 48u8,
+ 48u8, 49u8, 101u8, 110u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 48u8, 48u8,
+ 49u8, 101u8, 110u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 48u8, 48u8, 49u8,
+ 101u8, 110u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 48u8, 48u8, 49u8, 101u8,
+ 110u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 48u8, 48u8, 49u8, 101u8, 110u8,
+ 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 48u8, 48u8, 49u8, 101u8, 110u8, 0u8,
+ 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 48u8, 48u8, 49u8, 101u8, 110u8, 0u8, 0u8,
+ 0u8, 0u8, 0u8, 0u8, 1u8, 48u8, 48u8, 49u8, 101u8, 110u8, 0u8, 0u8, 0u8,
+ 0u8, 0u8, 0u8, 1u8, 48u8, 48u8, 49u8, 101u8, 110u8, 0u8, 0u8, 0u8, 0u8,
+ 0u8, 0u8, 1u8, 48u8, 48u8, 49u8, 101u8, 110u8, 0u8, 0u8, 0u8, 0u8, 0u8,
+ 0u8, 1u8, 48u8, 48u8, 49u8, 101u8, 110u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
+ 1u8, 48u8, 48u8, 49u8, 101u8, 110u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8,
+ 48u8, 48u8, 49u8, 101u8, 110u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 48u8,
+ 48u8, 49u8, 101u8, 110u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 48u8, 48u8,
+ 49u8, 101u8, 110u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 48u8, 48u8, 49u8,
+ 101u8, 110u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 48u8, 48u8, 49u8, 101u8,
+ 110u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 48u8, 48u8, 49u8, 101u8, 115u8,
+ 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 52u8, 49u8, 57u8, 101u8, 115u8, 0u8,
+ 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 52u8, 49u8, 57u8, 101u8, 115u8, 0u8, 0u8,
+ 0u8, 0u8, 0u8, 0u8, 1u8, 52u8, 49u8, 57u8, 101u8, 115u8, 0u8, 0u8, 0u8,
+ 0u8, 0u8, 0u8, 1u8, 52u8, 49u8, 57u8, 101u8, 115u8, 0u8, 0u8, 0u8, 0u8,
+ 0u8, 0u8, 1u8, 52u8, 49u8, 57u8, 101u8, 115u8, 0u8, 0u8, 0u8, 0u8, 0u8,
+ 0u8, 1u8, 52u8, 49u8, 57u8, 101u8, 115u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
+ 1u8, 52u8, 49u8, 57u8, 101u8, 115u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8,
+ 52u8, 49u8, 57u8, 101u8, 115u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 52u8,
+ 49u8, 57u8, 101u8, 115u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 52u8, 49u8,
+ 57u8, 101u8, 115u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 52u8, 49u8, 57u8,
+ 101u8, 115u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 52u8, 49u8, 57u8, 101u8,
+ 115u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 52u8, 49u8, 57u8, 101u8, 115u8,
+ 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 52u8, 49u8, 57u8, 101u8, 115u8, 0u8,
+ 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 52u8, 49u8, 57u8, 101u8, 115u8, 0u8, 0u8,
+ 0u8, 0u8, 0u8, 0u8, 1u8, 52u8, 49u8, 57u8, 101u8, 115u8, 0u8, 0u8, 0u8,
+ 0u8, 0u8, 0u8, 1u8, 52u8, 49u8, 57u8, 101u8, 115u8, 0u8, 0u8, 0u8, 0u8,
+ 0u8, 0u8, 1u8, 52u8, 49u8, 57u8, 101u8, 115u8, 0u8, 0u8, 0u8, 0u8, 0u8,
+ 0u8, 1u8, 52u8, 49u8, 57u8, 101u8, 115u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
+ 1u8, 52u8, 49u8, 57u8, 101u8, 115u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8,
+ 52u8, 49u8, 57u8, 101u8, 115u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 52u8,
+ 49u8, 57u8, 101u8, 110u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 73u8, 78u8,
+ 0u8, 102u8, 114u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 72u8, 84u8, 0u8,
+ 110u8, 111u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 110u8,
+ 111u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 112u8, 116u8, 0u8,
+ 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 80u8, 84u8, 0u8, 112u8, 116u8, 0u8, 0u8, 0u8,
+ 0u8, 0u8, 0u8, 1u8, 80u8, 84u8, 0u8, 112u8, 116u8, 0u8, 0u8, 0u8, 0u8, 0u8,
+ 0u8, 1u8, 80u8, 84u8, 0u8, 112u8, 116u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8,
+ 80u8, 84u8, 0u8, 112u8, 116u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 80u8,
+ 84u8, 0u8, 112u8, 116u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 80u8, 84u8,
+ 0u8, 112u8, 116u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 80u8, 84u8, 0u8,
+ 112u8, 116u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 80u8, 84u8, 0u8, 112u8,
+ 116u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 80u8, 84u8, 0u8, 112u8, 116u8,
+ 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 80u8, 84u8, 0u8, 112u8, 116u8, 0u8, 0u8,
+ 0u8, 0u8, 0u8, 0u8, 1u8, 80u8, 84u8, 0u8, 122u8, 104u8, 0u8, 1u8, 72u8,
+ 97u8, 110u8, 116u8, 1u8, 72u8, 75u8, 0u8,
+ ])
+ },
+ )
+ },
+}
diff --git a/compiler/rustc_baked_icu_data/src/data/fallback/supplement/co_v1.rs b/compiler/rustc_baked_icu_data/src/data/fallback/supplement/co_v1.rs
deleted file mode 100644
index 7df33c12e..000000000
--- a/compiler/rustc_baked_icu_data/src/data/fallback/supplement/co_v1.rs
+++ /dev/null
@@ -1,41 +0,0 @@
-// @generated
-type DataStruct = < :: icu_provider_adapters :: fallback :: provider :: CollationFallbackSupplementV1Marker as :: icu_provider :: DataMarker > :: Yokeable ;
-pub static DATA: litemap::LiteMap<&str, &DataStruct, &[(&str, &DataStruct)]> =
- litemap::LiteMap::from_sorted_store_unchecked(&[("und", UND)]);
-static UND: &DataStruct =
- &::icu_provider_adapters::fallback::provider::LocaleFallbackSupplementV1 {
- parents: unsafe {
- #[allow(unused_unsafe)]
- ::zerovec::ZeroMap::from_parts_unchecked(
- unsafe {
- ::zerovec::VarZeroVec::from_bytes_unchecked(&[
- 1u8, 0u8, 0u8, 0u8, 0u8, 0u8, 121u8, 117u8, 101u8,
- ])
- },
- unsafe {
- ::zerovec::ZeroVec::from_bytes_unchecked(&[
- 122u8, 104u8, 0u8, 1u8, 72u8, 97u8, 110u8, 116u8, 0u8, 0u8, 0u8, 0u8,
- ])
- },
- )
- },
- unicode_extension_defaults: unsafe {
- #[allow(unused_unsafe)]
- ::zerovec::ZeroMap2d::from_parts_unchecked(
- unsafe { ::zerovec::ZeroVec::from_bytes_unchecked(&[99u8, 111u8]) },
- unsafe { ::zerovec::ZeroVec::from_bytes_unchecked(&[2u8, 0u8, 0u8, 0u8]) },
- unsafe {
- ::zerovec::VarZeroVec::from_bytes_unchecked(&[
- 2u8, 0u8, 0u8, 0u8, 0u8, 0u8, 2u8, 0u8, 122u8, 104u8, 122u8, 104u8, 45u8,
- 72u8, 97u8, 110u8, 116u8,
- ])
- },
- unsafe {
- ::zerovec::VarZeroVec::from_bytes_unchecked(&[
- 2u8, 0u8, 0u8, 0u8, 0u8, 0u8, 6u8, 0u8, 112u8, 105u8, 110u8, 121u8, 105u8,
- 110u8, 115u8, 116u8, 114u8, 111u8, 107u8, 101u8,
- ])
- },
- )
- },
- };
diff --git a/compiler/rustc_baked_icu_data/src/data/fallback/supplement/co_v1/mod.rs b/compiler/rustc_baked_icu_data/src/data/fallback/supplement/co_v1/mod.rs
new file mode 100644
index 000000000..902364713
--- /dev/null
+++ b/compiler/rustc_baked_icu_data/src/data/fallback/supplement/co_v1/mod.rs
@@ -0,0 +1,6 @@
+// @generated
+type DataStruct = < :: icu_provider_adapters :: fallback :: provider :: CollationFallbackSupplementV1Marker as :: icu_provider :: DataMarker > :: Yokeable ;
+pub fn lookup(locale: &icu_provider::DataLocale) -> Option<&'static DataStruct> {
+ locale.is_empty().then(|| &UND)
+}
+static UND: DataStruct = include!("und.rs.data");
diff --git a/compiler/rustc_baked_icu_data/src/data/fallback/supplement/co_v1/und.rs.data b/compiler/rustc_baked_icu_data/src/data/fallback/supplement/co_v1/und.rs.data
new file mode 100644
index 000000000..7d70e78c3
--- /dev/null
+++ b/compiler/rustc_baked_icu_data/src/data/fallback/supplement/co_v1/und.rs.data
@@ -0,0 +1,36 @@
+::icu_provider_adapters::fallback::provider::LocaleFallbackSupplementV1 {
+ parents: unsafe {
+ #[allow(unused_unsafe)]
+ ::zerovec::ZeroMap::from_parts_unchecked(
+ unsafe {
+ ::zerovec::VarZeroVec::from_bytes_unchecked(&[
+ 1u8, 0u8, 0u8, 0u8, 0u8, 0u8, 121u8, 117u8, 101u8,
+ ])
+ },
+ unsafe {
+ ::zerovec::ZeroVec::from_bytes_unchecked(&[
+ 122u8, 104u8, 0u8, 1u8, 72u8, 97u8, 110u8, 116u8, 0u8, 0u8, 0u8, 0u8,
+ ])
+ },
+ )
+ },
+ unicode_extension_defaults: unsafe {
+ #[allow(unused_unsafe)]
+ ::zerovec::ZeroMap2d::from_parts_unchecked(
+ unsafe { ::zerovec::ZeroVec::from_bytes_unchecked(&[99u8, 111u8]) },
+ unsafe { ::zerovec::ZeroVec::from_bytes_unchecked(&[2u8, 0u8, 0u8, 0u8]) },
+ unsafe {
+ ::zerovec::VarZeroVec::from_bytes_unchecked(&[
+ 2u8, 0u8, 0u8, 0u8, 0u8, 0u8, 2u8, 0u8, 122u8, 104u8, 122u8, 104u8, 45u8,
+ 72u8, 97u8, 110u8, 116u8,
+ ])
+ },
+ unsafe {
+ ::zerovec::VarZeroVec::from_bytes_unchecked(&[
+ 2u8, 0u8, 0u8, 0u8, 0u8, 0u8, 6u8, 0u8, 112u8, 105u8, 110u8, 121u8, 105u8,
+ 110u8, 115u8, 116u8, 114u8, 111u8, 107u8, 101u8,
+ ])
+ },
+ )
+ },
+}
diff --git a/compiler/rustc_baked_icu_data/src/data/list/and_v1.rs b/compiler/rustc_baked_icu_data/src/data/list/and_v1.rs
deleted file mode 100644
index 9cae549e1..000000000
--- a/compiler/rustc_baked_icu_data/src/data/list/and_v1.rs
+++ /dev/null
@@ -1,1161 +0,0 @@
-// @generated
-type DataStruct = <::icu_list::provider::AndListV1Marker as ::icu_provider::DataMarker>::Yokeable;
-pub static DATA: litemap::LiteMap<&str, &DataStruct, &[(&str, &DataStruct)]> =
- litemap::LiteMap::from_sorted_store_unchecked(&[
- ("en", EN),
- ("es", ES),
- ("fr", FR),
- ("it", IT),
- ("ja", JA),
- ("pt", PT),
- ("ru", RU),
- ("tr", TR),
- ("und", UND),
- ("zh", ZH_ZH_HANS),
- ("zh-Hans", ZH_ZH_HANS),
- ("zh-Hant", ZH_HANT),
- ]);
-static EN: &DataStruct = &::icu_list::provider::ListFormatterPatternsV1([
- ::icu_list::provider::ConditionalListJoinerPattern {
- default: unsafe {
- ::icu_list::provider::ListJoinerPattern::from_parts_unchecked(", ", 2u8)
- },
- special_case: None,
- },
- ::icu_list::provider::ConditionalListJoinerPattern {
- default: unsafe {
- ::icu_list::provider::ListJoinerPattern::from_parts_unchecked(", ", 2u8)
- },
- special_case: None,
- },
- ::icu_list::provider::ConditionalListJoinerPattern {
- default: unsafe {
- ::icu_list::provider::ListJoinerPattern::from_parts_unchecked(", and ", 6u8)
- },
- special_case: None,
- },
- ::icu_list::provider::ConditionalListJoinerPattern {
- default: unsafe {
- ::icu_list::provider::ListJoinerPattern::from_parts_unchecked(" and ", 5u8)
- },
- special_case: None,
- },
- ::icu_list::provider::ConditionalListJoinerPattern {
- default: unsafe {
- ::icu_list::provider::ListJoinerPattern::from_parts_unchecked(", ", 2u8)
- },
- special_case: None,
- },
- ::icu_list::provider::ConditionalListJoinerPattern {
- default: unsafe {
- ::icu_list::provider::ListJoinerPattern::from_parts_unchecked(", ", 2u8)
- },
- special_case: None,
- },
- ::icu_list::provider::ConditionalListJoinerPattern {
- default: unsafe {
- ::icu_list::provider::ListJoinerPattern::from_parts_unchecked(", & ", 4u8)
- },
- special_case: None,
- },
- ::icu_list::provider::ConditionalListJoinerPattern {
- default: unsafe {
- ::icu_list::provider::ListJoinerPattern::from_parts_unchecked(" & ", 3u8)
- },
- special_case: None,
- },
- ::icu_list::provider::ConditionalListJoinerPattern {
- default: unsafe {
- ::icu_list::provider::ListJoinerPattern::from_parts_unchecked(", ", 2u8)
- },
- special_case: None,
- },
- ::icu_list::provider::ConditionalListJoinerPattern {
- default: unsafe {
- ::icu_list::provider::ListJoinerPattern::from_parts_unchecked(", ", 2u8)
- },
- special_case: None,
- },
- ::icu_list::provider::ConditionalListJoinerPattern {
- default: unsafe {
- ::icu_list::provider::ListJoinerPattern::from_parts_unchecked(", ", 2u8)
- },
- special_case: None,
- },
- ::icu_list::provider::ConditionalListJoinerPattern {
- default: unsafe {
- ::icu_list::provider::ListJoinerPattern::from_parts_unchecked(", ", 2u8)
- },
- special_case: None,
- },
-]);
-static ES: &DataStruct = &::icu_list::provider::ListFormatterPatternsV1([
- ::icu_list::provider::ConditionalListJoinerPattern {
- default: unsafe {
- ::icu_list::provider::ListJoinerPattern::from_parts_unchecked(", ", 2u8)
- },
- special_case: None,
- },
- ::icu_list::provider::ConditionalListJoinerPattern {
- default: unsafe {
- ::icu_list::provider::ListJoinerPattern::from_parts_unchecked(", ", 2u8)
- },
- special_case: None,
- },
- ::icu_list::provider::ConditionalListJoinerPattern {
- default: unsafe {
- ::icu_list::provider::ListJoinerPattern::from_parts_unchecked(" y ", 3u8)
- },
- special_case: Some(::icu_list::provider::SpecialCasePattern {
- condition: unsafe {
- ::icu_list::provider::StringMatcher::from_dfa_bytes_unchecked(&[
- 114u8, 117u8, 115u8, 116u8, 45u8, 114u8, 101u8, 103u8, 101u8, 120u8, 45u8,
- 97u8, 117u8, 116u8, 111u8, 109u8, 97u8, 116u8, 97u8, 45u8, 100u8, 102u8, 97u8,
- 45u8, 115u8, 112u8, 97u8, 114u8, 115u8, 101u8, 0u8, 0u8, 255u8, 254u8, 0u8,
- 0u8, 2u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 14u8, 0u8, 0u8, 0u8, 1u8, 0u8,
- 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
- 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
- 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
- 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
- 0u8, 0u8, 0u8, 1u8, 2u8, 2u8, 2u8, 3u8, 4u8, 4u8, 5u8, 6u8, 7u8, 7u8, 7u8, 7u8,
- 7u8, 7u8, 7u8, 7u8, 7u8, 7u8, 7u8, 7u8, 7u8, 7u8, 7u8, 7u8, 7u8, 7u8, 7u8, 7u8,
- 7u8, 7u8, 7u8, 8u8, 9u8, 9u8, 9u8, 10u8, 11u8, 11u8, 12u8, 13u8, 14u8, 14u8,
- 14u8, 14u8, 14u8, 14u8, 14u8, 14u8, 14u8, 14u8, 14u8, 14u8, 14u8, 14u8, 14u8,
- 14u8, 14u8, 14u8, 14u8, 14u8, 14u8, 14u8, 15u8, 15u8, 15u8, 15u8, 15u8, 15u8,
- 15u8, 15u8, 15u8, 15u8, 15u8, 15u8, 15u8, 15u8, 15u8, 15u8, 16u8, 16u8, 16u8,
- 16u8, 16u8, 16u8, 16u8, 16u8, 16u8, 16u8, 16u8, 16u8, 16u8, 16u8, 16u8, 16u8,
- 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8,
- 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8,
- 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 18u8, 18u8, 19u8, 19u8, 19u8, 19u8, 19u8,
- 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8,
- 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 20u8,
- 21u8, 21u8, 21u8, 21u8, 21u8, 21u8, 21u8, 21u8, 21u8, 21u8, 21u8, 21u8, 22u8,
- 23u8, 23u8, 24u8, 25u8, 25u8, 25u8, 26u8, 27u8, 27u8, 27u8, 27u8, 27u8, 27u8,
- 27u8, 27u8, 27u8, 27u8, 27u8, 40u8, 1u8, 0u8, 0u8, 1u8, 0u8, 0u8, 0u8, 0u8,
- 0u8, 0u8, 0u8, 0u8, 1u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 128u8,
- 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 5u8,
- 0u8, 5u8, 5u8, 6u8, 6u8, 12u8, 12u8, 13u8, 13u8, 0u8, 0u8, 83u8, 0u8, 0u8, 0u8,
- 68u8, 0u8, 0u8, 0u8, 83u8, 0u8, 0u8, 0u8, 68u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
- 0u8, 0u8, 2u8, 0u8, 0u8, 27u8, 0u8, 0u8, 18u8, 0u8, 0u8, 0u8, 18u8, 0u8, 0u8,
- 0u8, 0u8, 3u8, 0u8, 6u8, 6u8, 13u8, 13u8, 0u8, 0u8, 104u8, 0u8, 0u8, 0u8,
- 104u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 14u8, 0u8, 0u8, 0u8, 2u8, 2u8,
- 4u8, 7u8, 9u8, 9u8, 11u8, 14u8, 19u8, 19u8, 20u8, 20u8, 21u8, 21u8, 22u8, 22u8,
- 23u8, 23u8, 24u8, 24u8, 25u8, 25u8, 26u8, 26u8, 0u8, 0u8, 68u8, 0u8, 0u8, 0u8,
- 68u8, 0u8, 0u8, 0u8, 68u8, 0u8, 0u8, 0u8, 68u8, 0u8, 0u8, 0u8, 68u8, 0u8, 0u8,
- 0u8, 191u8, 0u8, 0u8, 0u8, 206u8, 0u8, 0u8, 0u8, 221u8, 0u8, 0u8, 0u8, 236u8,
- 0u8, 0u8, 0u8, 221u8, 0u8, 0u8, 0u8, 251u8, 0u8, 0u8, 0u8, 10u8, 1u8, 0u8, 0u8,
- 25u8, 1u8, 0u8, 0u8, 18u8, 0u8, 0u8, 0u8, 0u8, 2u8, 0u8, 15u8, 17u8, 0u8, 0u8,
- 68u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 2u8, 0u8, 17u8, 17u8, 0u8, 0u8,
- 191u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 2u8, 0u8, 15u8, 17u8, 0u8, 0u8,
- 191u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 2u8, 0u8, 15u8, 16u8, 0u8, 0u8,
- 191u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 2u8, 0u8, 16u8, 17u8, 0u8, 0u8,
- 221u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 2u8, 0u8, 15u8, 17u8, 0u8, 0u8,
- 221u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 2u8, 0u8, 15u8, 15u8, 0u8, 0u8,
- 221u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 4u8, 0u8, 0u8, 0u8, 0u8, 0u8,
- 0u8, 0u8, 35u8, 0u8, 0u8, 0u8, 35u8, 0u8, 0u8, 0u8, 35u8, 0u8, 0u8, 0u8, 35u8,
- 0u8, 0u8, 0u8, 35u8, 0u8, 0u8, 0u8, 9u8, 0u8, 0u8, 0u8, 18u8, 0u8, 0u8, 0u8,
- 18u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 35u8, 0u8, 0u8,
- 0u8, 35u8, 0u8, 0u8, 0u8,
- ])
- },
- pattern: unsafe {
- ::icu_list::provider::ListJoinerPattern::from_parts_unchecked(" e ", 3u8)
- },
- }),
- },
- ::icu_list::provider::ConditionalListJoinerPattern {
- default: unsafe {
- ::icu_list::provider::ListJoinerPattern::from_parts_unchecked(" y ", 3u8)
- },
- special_case: Some(::icu_list::provider::SpecialCasePattern {
- condition: unsafe {
- ::icu_list::provider::StringMatcher::from_dfa_bytes_unchecked(&[
- 114u8, 117u8, 115u8, 116u8, 45u8, 114u8, 101u8, 103u8, 101u8, 120u8, 45u8,
- 97u8, 117u8, 116u8, 111u8, 109u8, 97u8, 116u8, 97u8, 45u8, 100u8, 102u8, 97u8,
- 45u8, 115u8, 112u8, 97u8, 114u8, 115u8, 101u8, 0u8, 0u8, 255u8, 254u8, 0u8,
- 0u8, 2u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 14u8, 0u8, 0u8, 0u8, 1u8, 0u8,
- 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
- 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
- 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
- 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
- 0u8, 0u8, 0u8, 1u8, 2u8, 2u8, 2u8, 3u8, 4u8, 4u8, 5u8, 6u8, 7u8, 7u8, 7u8, 7u8,
- 7u8, 7u8, 7u8, 7u8, 7u8, 7u8, 7u8, 7u8, 7u8, 7u8, 7u8, 7u8, 7u8, 7u8, 7u8, 7u8,
- 7u8, 7u8, 7u8, 8u8, 9u8, 9u8, 9u8, 10u8, 11u8, 11u8, 12u8, 13u8, 14u8, 14u8,
- 14u8, 14u8, 14u8, 14u8, 14u8, 14u8, 14u8, 14u8, 14u8, 14u8, 14u8, 14u8, 14u8,
- 14u8, 14u8, 14u8, 14u8, 14u8, 14u8, 14u8, 15u8, 15u8, 15u8, 15u8, 15u8, 15u8,
- 15u8, 15u8, 15u8, 15u8, 15u8, 15u8, 15u8, 15u8, 15u8, 15u8, 16u8, 16u8, 16u8,
- 16u8, 16u8, 16u8, 16u8, 16u8, 16u8, 16u8, 16u8, 16u8, 16u8, 16u8, 16u8, 16u8,
- 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8,
- 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8,
- 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 18u8, 18u8, 19u8, 19u8, 19u8, 19u8, 19u8,
- 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8,
- 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 20u8,
- 21u8, 21u8, 21u8, 21u8, 21u8, 21u8, 21u8, 21u8, 21u8, 21u8, 21u8, 21u8, 22u8,
- 23u8, 23u8, 24u8, 25u8, 25u8, 25u8, 26u8, 27u8, 27u8, 27u8, 27u8, 27u8, 27u8,
- 27u8, 27u8, 27u8, 27u8, 27u8, 40u8, 1u8, 0u8, 0u8, 1u8, 0u8, 0u8, 0u8, 0u8,
- 0u8, 0u8, 0u8, 0u8, 1u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 128u8,
- 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 5u8,
- 0u8, 5u8, 5u8, 6u8, 6u8, 12u8, 12u8, 13u8, 13u8, 0u8, 0u8, 83u8, 0u8, 0u8, 0u8,
- 68u8, 0u8, 0u8, 0u8, 83u8, 0u8, 0u8, 0u8, 68u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
- 0u8, 0u8, 2u8, 0u8, 0u8, 27u8, 0u8, 0u8, 18u8, 0u8, 0u8, 0u8, 18u8, 0u8, 0u8,
- 0u8, 0u8, 3u8, 0u8, 6u8, 6u8, 13u8, 13u8, 0u8, 0u8, 104u8, 0u8, 0u8, 0u8,
- 104u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 14u8, 0u8, 0u8, 0u8, 2u8, 2u8,
- 4u8, 7u8, 9u8, 9u8, 11u8, 14u8, 19u8, 19u8, 20u8, 20u8, 21u8, 21u8, 22u8, 22u8,
- 23u8, 23u8, 24u8, 24u8, 25u8, 25u8, 26u8, 26u8, 0u8, 0u8, 68u8, 0u8, 0u8, 0u8,
- 68u8, 0u8, 0u8, 0u8, 68u8, 0u8, 0u8, 0u8, 68u8, 0u8, 0u8, 0u8, 68u8, 0u8, 0u8,
- 0u8, 191u8, 0u8, 0u8, 0u8, 206u8, 0u8, 0u8, 0u8, 221u8, 0u8, 0u8, 0u8, 236u8,
- 0u8, 0u8, 0u8, 221u8, 0u8, 0u8, 0u8, 251u8, 0u8, 0u8, 0u8, 10u8, 1u8, 0u8, 0u8,
- 25u8, 1u8, 0u8, 0u8, 18u8, 0u8, 0u8, 0u8, 0u8, 2u8, 0u8, 15u8, 17u8, 0u8, 0u8,
- 68u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 2u8, 0u8, 17u8, 17u8, 0u8, 0u8,
- 191u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 2u8, 0u8, 15u8, 17u8, 0u8, 0u8,
- 191u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 2u8, 0u8, 15u8, 16u8, 0u8, 0u8,
- 191u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 2u8, 0u8, 16u8, 17u8, 0u8, 0u8,
- 221u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 2u8, 0u8, 15u8, 17u8, 0u8, 0u8,
- 221u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 2u8, 0u8, 15u8, 15u8, 0u8, 0u8,
- 221u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 4u8, 0u8, 0u8, 0u8, 0u8, 0u8,
- 0u8, 0u8, 35u8, 0u8, 0u8, 0u8, 35u8, 0u8, 0u8, 0u8, 35u8, 0u8, 0u8, 0u8, 35u8,
- 0u8, 0u8, 0u8, 35u8, 0u8, 0u8, 0u8, 9u8, 0u8, 0u8, 0u8, 18u8, 0u8, 0u8, 0u8,
- 18u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 35u8, 0u8, 0u8,
- 0u8, 35u8, 0u8, 0u8, 0u8,
- ])
- },
- pattern: unsafe {
- ::icu_list::provider::ListJoinerPattern::from_parts_unchecked(" e ", 3u8)
- },
- }),
- },
- ::icu_list::provider::ConditionalListJoinerPattern {
- default: unsafe {
- ::icu_list::provider::ListJoinerPattern::from_parts_unchecked(", ", 2u8)
- },
- special_case: None,
- },
- ::icu_list::provider::ConditionalListJoinerPattern {
- default: unsafe {
- ::icu_list::provider::ListJoinerPattern::from_parts_unchecked(", ", 2u8)
- },
- special_case: None,
- },
- ::icu_list::provider::ConditionalListJoinerPattern {
- default: unsafe {
- ::icu_list::provider::ListJoinerPattern::from_parts_unchecked(" y ", 3u8)
- },
- special_case: Some(::icu_list::provider::SpecialCasePattern {
- condition: unsafe {
- ::icu_list::provider::StringMatcher::from_dfa_bytes_unchecked(&[
- 114u8, 117u8, 115u8, 116u8, 45u8, 114u8, 101u8, 103u8, 101u8, 120u8, 45u8,
- 97u8, 117u8, 116u8, 111u8, 109u8, 97u8, 116u8, 97u8, 45u8, 100u8, 102u8, 97u8,
- 45u8, 115u8, 112u8, 97u8, 114u8, 115u8, 101u8, 0u8, 0u8, 255u8, 254u8, 0u8,
- 0u8, 2u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 14u8, 0u8, 0u8, 0u8, 1u8, 0u8,
- 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
- 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
- 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
- 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
- 0u8, 0u8, 0u8, 1u8, 2u8, 2u8, 2u8, 3u8, 4u8, 4u8, 5u8, 6u8, 7u8, 7u8, 7u8, 7u8,
- 7u8, 7u8, 7u8, 7u8, 7u8, 7u8, 7u8, 7u8, 7u8, 7u8, 7u8, 7u8, 7u8, 7u8, 7u8, 7u8,
- 7u8, 7u8, 7u8, 8u8, 9u8, 9u8, 9u8, 10u8, 11u8, 11u8, 12u8, 13u8, 14u8, 14u8,
- 14u8, 14u8, 14u8, 14u8, 14u8, 14u8, 14u8, 14u8, 14u8, 14u8, 14u8, 14u8, 14u8,
- 14u8, 14u8, 14u8, 14u8, 14u8, 14u8, 14u8, 15u8, 15u8, 15u8, 15u8, 15u8, 15u8,
- 15u8, 15u8, 15u8, 15u8, 15u8, 15u8, 15u8, 15u8, 15u8, 15u8, 16u8, 16u8, 16u8,
- 16u8, 16u8, 16u8, 16u8, 16u8, 16u8, 16u8, 16u8, 16u8, 16u8, 16u8, 16u8, 16u8,
- 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8,
- 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8,
- 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 18u8, 18u8, 19u8, 19u8, 19u8, 19u8, 19u8,
- 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8,
- 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 20u8,
- 21u8, 21u8, 21u8, 21u8, 21u8, 21u8, 21u8, 21u8, 21u8, 21u8, 21u8, 21u8, 22u8,
- 23u8, 23u8, 24u8, 25u8, 25u8, 25u8, 26u8, 27u8, 27u8, 27u8, 27u8, 27u8, 27u8,
- 27u8, 27u8, 27u8, 27u8, 27u8, 40u8, 1u8, 0u8, 0u8, 1u8, 0u8, 0u8, 0u8, 0u8,
- 0u8, 0u8, 0u8, 0u8, 1u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 128u8,
- 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 5u8,
- 0u8, 5u8, 5u8, 6u8, 6u8, 12u8, 12u8, 13u8, 13u8, 0u8, 0u8, 83u8, 0u8, 0u8, 0u8,
- 68u8, 0u8, 0u8, 0u8, 83u8, 0u8, 0u8, 0u8, 68u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
- 0u8, 0u8, 2u8, 0u8, 0u8, 27u8, 0u8, 0u8, 18u8, 0u8, 0u8, 0u8, 18u8, 0u8, 0u8,
- 0u8, 0u8, 3u8, 0u8, 6u8, 6u8, 13u8, 13u8, 0u8, 0u8, 104u8, 0u8, 0u8, 0u8,
- 104u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 14u8, 0u8, 0u8, 0u8, 2u8, 2u8,
- 4u8, 7u8, 9u8, 9u8, 11u8, 14u8, 19u8, 19u8, 20u8, 20u8, 21u8, 21u8, 22u8, 22u8,
- 23u8, 23u8, 24u8, 24u8, 25u8, 25u8, 26u8, 26u8, 0u8, 0u8, 68u8, 0u8, 0u8, 0u8,
- 68u8, 0u8, 0u8, 0u8, 68u8, 0u8, 0u8, 0u8, 68u8, 0u8, 0u8, 0u8, 68u8, 0u8, 0u8,
- 0u8, 191u8, 0u8, 0u8, 0u8, 206u8, 0u8, 0u8, 0u8, 221u8, 0u8, 0u8, 0u8, 236u8,
- 0u8, 0u8, 0u8, 221u8, 0u8, 0u8, 0u8, 251u8, 0u8, 0u8, 0u8, 10u8, 1u8, 0u8, 0u8,
- 25u8, 1u8, 0u8, 0u8, 18u8, 0u8, 0u8, 0u8, 0u8, 2u8, 0u8, 15u8, 17u8, 0u8, 0u8,
- 68u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 2u8, 0u8, 17u8, 17u8, 0u8, 0u8,
- 191u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 2u8, 0u8, 15u8, 17u8, 0u8, 0u8,
- 191u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 2u8, 0u8, 15u8, 16u8, 0u8, 0u8,
- 191u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 2u8, 0u8, 16u8, 17u8, 0u8, 0u8,
- 221u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 2u8, 0u8, 15u8, 17u8, 0u8, 0u8,
- 221u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 2u8, 0u8, 15u8, 15u8, 0u8, 0u8,
- 221u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 4u8, 0u8, 0u8, 0u8, 0u8, 0u8,
- 0u8, 0u8, 35u8, 0u8, 0u8, 0u8, 35u8, 0u8, 0u8, 0u8, 35u8, 0u8, 0u8, 0u8, 35u8,
- 0u8, 0u8, 0u8, 35u8, 0u8, 0u8, 0u8, 9u8, 0u8, 0u8, 0u8, 18u8, 0u8, 0u8, 0u8,
- 18u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 35u8, 0u8, 0u8,
- 0u8, 35u8, 0u8, 0u8, 0u8,
- ])
- },
- pattern: unsafe {
- ::icu_list::provider::ListJoinerPattern::from_parts_unchecked(" e ", 3u8)
- },
- }),
- },
- ::icu_list::provider::ConditionalListJoinerPattern {
- default: unsafe {
- ::icu_list::provider::ListJoinerPattern::from_parts_unchecked(" y ", 3u8)
- },
- special_case: Some(::icu_list::provider::SpecialCasePattern {
- condition: unsafe {
- ::icu_list::provider::StringMatcher::from_dfa_bytes_unchecked(&[
- 114u8, 117u8, 115u8, 116u8, 45u8, 114u8, 101u8, 103u8, 101u8, 120u8, 45u8,
- 97u8, 117u8, 116u8, 111u8, 109u8, 97u8, 116u8, 97u8, 45u8, 100u8, 102u8, 97u8,
- 45u8, 115u8, 112u8, 97u8, 114u8, 115u8, 101u8, 0u8, 0u8, 255u8, 254u8, 0u8,
- 0u8, 2u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 14u8, 0u8, 0u8, 0u8, 1u8, 0u8,
- 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
- 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
- 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
- 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
- 0u8, 0u8, 0u8, 1u8, 2u8, 2u8, 2u8, 3u8, 4u8, 4u8, 5u8, 6u8, 7u8, 7u8, 7u8, 7u8,
- 7u8, 7u8, 7u8, 7u8, 7u8, 7u8, 7u8, 7u8, 7u8, 7u8, 7u8, 7u8, 7u8, 7u8, 7u8, 7u8,
- 7u8, 7u8, 7u8, 8u8, 9u8, 9u8, 9u8, 10u8, 11u8, 11u8, 12u8, 13u8, 14u8, 14u8,
- 14u8, 14u8, 14u8, 14u8, 14u8, 14u8, 14u8, 14u8, 14u8, 14u8, 14u8, 14u8, 14u8,
- 14u8, 14u8, 14u8, 14u8, 14u8, 14u8, 14u8, 15u8, 15u8, 15u8, 15u8, 15u8, 15u8,
- 15u8, 15u8, 15u8, 15u8, 15u8, 15u8, 15u8, 15u8, 15u8, 15u8, 16u8, 16u8, 16u8,
- 16u8, 16u8, 16u8, 16u8, 16u8, 16u8, 16u8, 16u8, 16u8, 16u8, 16u8, 16u8, 16u8,
- 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8,
- 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8,
- 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 18u8, 18u8, 19u8, 19u8, 19u8, 19u8, 19u8,
- 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8,
- 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 20u8,
- 21u8, 21u8, 21u8, 21u8, 21u8, 21u8, 21u8, 21u8, 21u8, 21u8, 21u8, 21u8, 22u8,
- 23u8, 23u8, 24u8, 25u8, 25u8, 25u8, 26u8, 27u8, 27u8, 27u8, 27u8, 27u8, 27u8,
- 27u8, 27u8, 27u8, 27u8, 27u8, 40u8, 1u8, 0u8, 0u8, 1u8, 0u8, 0u8, 0u8, 0u8,
- 0u8, 0u8, 0u8, 0u8, 1u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 128u8,
- 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 5u8,
- 0u8, 5u8, 5u8, 6u8, 6u8, 12u8, 12u8, 13u8, 13u8, 0u8, 0u8, 83u8, 0u8, 0u8, 0u8,
- 68u8, 0u8, 0u8, 0u8, 83u8, 0u8, 0u8, 0u8, 68u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
- 0u8, 0u8, 2u8, 0u8, 0u8, 27u8, 0u8, 0u8, 18u8, 0u8, 0u8, 0u8, 18u8, 0u8, 0u8,
- 0u8, 0u8, 3u8, 0u8, 6u8, 6u8, 13u8, 13u8, 0u8, 0u8, 104u8, 0u8, 0u8, 0u8,
- 104u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 14u8, 0u8, 0u8, 0u8, 2u8, 2u8,
- 4u8, 7u8, 9u8, 9u8, 11u8, 14u8, 19u8, 19u8, 20u8, 20u8, 21u8, 21u8, 22u8, 22u8,
- 23u8, 23u8, 24u8, 24u8, 25u8, 25u8, 26u8, 26u8, 0u8, 0u8, 68u8, 0u8, 0u8, 0u8,
- 68u8, 0u8, 0u8, 0u8, 68u8, 0u8, 0u8, 0u8, 68u8, 0u8, 0u8, 0u8, 68u8, 0u8, 0u8,
- 0u8, 191u8, 0u8, 0u8, 0u8, 206u8, 0u8, 0u8, 0u8, 221u8, 0u8, 0u8, 0u8, 236u8,
- 0u8, 0u8, 0u8, 221u8, 0u8, 0u8, 0u8, 251u8, 0u8, 0u8, 0u8, 10u8, 1u8, 0u8, 0u8,
- 25u8, 1u8, 0u8, 0u8, 18u8, 0u8, 0u8, 0u8, 0u8, 2u8, 0u8, 15u8, 17u8, 0u8, 0u8,
- 68u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 2u8, 0u8, 17u8, 17u8, 0u8, 0u8,
- 191u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 2u8, 0u8, 15u8, 17u8, 0u8, 0u8,
- 191u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 2u8, 0u8, 15u8, 16u8, 0u8, 0u8,
- 191u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 2u8, 0u8, 16u8, 17u8, 0u8, 0u8,
- 221u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 2u8, 0u8, 15u8, 17u8, 0u8, 0u8,
- 221u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 2u8, 0u8, 15u8, 15u8, 0u8, 0u8,
- 221u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 4u8, 0u8, 0u8, 0u8, 0u8, 0u8,
- 0u8, 0u8, 35u8, 0u8, 0u8, 0u8, 35u8, 0u8, 0u8, 0u8, 35u8, 0u8, 0u8, 0u8, 35u8,
- 0u8, 0u8, 0u8, 35u8, 0u8, 0u8, 0u8, 9u8, 0u8, 0u8, 0u8, 18u8, 0u8, 0u8, 0u8,
- 18u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 35u8, 0u8, 0u8,
- 0u8, 35u8, 0u8, 0u8, 0u8,
- ])
- },
- pattern: unsafe {
- ::icu_list::provider::ListJoinerPattern::from_parts_unchecked(" e ", 3u8)
- },
- }),
- },
- ::icu_list::provider::ConditionalListJoinerPattern {
- default: unsafe {
- ::icu_list::provider::ListJoinerPattern::from_parts_unchecked(", ", 2u8)
- },
- special_case: None,
- },
- ::icu_list::provider::ConditionalListJoinerPattern {
- default: unsafe {
- ::icu_list::provider::ListJoinerPattern::from_parts_unchecked(", ", 2u8)
- },
- special_case: None,
- },
- ::icu_list::provider::ConditionalListJoinerPattern {
- default: unsafe {
- ::icu_list::provider::ListJoinerPattern::from_parts_unchecked(" y ", 3u8)
- },
- special_case: Some(::icu_list::provider::SpecialCasePattern {
- condition: unsafe {
- ::icu_list::provider::StringMatcher::from_dfa_bytes_unchecked(&[
- 114u8, 117u8, 115u8, 116u8, 45u8, 114u8, 101u8, 103u8, 101u8, 120u8, 45u8,
- 97u8, 117u8, 116u8, 111u8, 109u8, 97u8, 116u8, 97u8, 45u8, 100u8, 102u8, 97u8,
- 45u8, 115u8, 112u8, 97u8, 114u8, 115u8, 101u8, 0u8, 0u8, 255u8, 254u8, 0u8,
- 0u8, 2u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 14u8, 0u8, 0u8, 0u8, 1u8, 0u8,
- 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
- 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
- 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
- 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
- 0u8, 0u8, 0u8, 1u8, 2u8, 2u8, 2u8, 3u8, 4u8, 4u8, 5u8, 6u8, 7u8, 7u8, 7u8, 7u8,
- 7u8, 7u8, 7u8, 7u8, 7u8, 7u8, 7u8, 7u8, 7u8, 7u8, 7u8, 7u8, 7u8, 7u8, 7u8, 7u8,
- 7u8, 7u8, 7u8, 8u8, 9u8, 9u8, 9u8, 10u8, 11u8, 11u8, 12u8, 13u8, 14u8, 14u8,
- 14u8, 14u8, 14u8, 14u8, 14u8, 14u8, 14u8, 14u8, 14u8, 14u8, 14u8, 14u8, 14u8,
- 14u8, 14u8, 14u8, 14u8, 14u8, 14u8, 14u8, 15u8, 15u8, 15u8, 15u8, 15u8, 15u8,
- 15u8, 15u8, 15u8, 15u8, 15u8, 15u8, 15u8, 15u8, 15u8, 15u8, 16u8, 16u8, 16u8,
- 16u8, 16u8, 16u8, 16u8, 16u8, 16u8, 16u8, 16u8, 16u8, 16u8, 16u8, 16u8, 16u8,
- 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8,
- 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8,
- 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 18u8, 18u8, 19u8, 19u8, 19u8, 19u8, 19u8,
- 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8,
- 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 20u8,
- 21u8, 21u8, 21u8, 21u8, 21u8, 21u8, 21u8, 21u8, 21u8, 21u8, 21u8, 21u8, 22u8,
- 23u8, 23u8, 24u8, 25u8, 25u8, 25u8, 26u8, 27u8, 27u8, 27u8, 27u8, 27u8, 27u8,
- 27u8, 27u8, 27u8, 27u8, 27u8, 40u8, 1u8, 0u8, 0u8, 1u8, 0u8, 0u8, 0u8, 0u8,
- 0u8, 0u8, 0u8, 0u8, 1u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 128u8,
- 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 5u8,
- 0u8, 5u8, 5u8, 6u8, 6u8, 12u8, 12u8, 13u8, 13u8, 0u8, 0u8, 83u8, 0u8, 0u8, 0u8,
- 68u8, 0u8, 0u8, 0u8, 83u8, 0u8, 0u8, 0u8, 68u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
- 0u8, 0u8, 2u8, 0u8, 0u8, 27u8, 0u8, 0u8, 18u8, 0u8, 0u8, 0u8, 18u8, 0u8, 0u8,
- 0u8, 0u8, 3u8, 0u8, 6u8, 6u8, 13u8, 13u8, 0u8, 0u8, 104u8, 0u8, 0u8, 0u8,
- 104u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 14u8, 0u8, 0u8, 0u8, 2u8, 2u8,
- 4u8, 7u8, 9u8, 9u8, 11u8, 14u8, 19u8, 19u8, 20u8, 20u8, 21u8, 21u8, 22u8, 22u8,
- 23u8, 23u8, 24u8, 24u8, 25u8, 25u8, 26u8, 26u8, 0u8, 0u8, 68u8, 0u8, 0u8, 0u8,
- 68u8, 0u8, 0u8, 0u8, 68u8, 0u8, 0u8, 0u8, 68u8, 0u8, 0u8, 0u8, 68u8, 0u8, 0u8,
- 0u8, 191u8, 0u8, 0u8, 0u8, 206u8, 0u8, 0u8, 0u8, 221u8, 0u8, 0u8, 0u8, 236u8,
- 0u8, 0u8, 0u8, 221u8, 0u8, 0u8, 0u8, 251u8, 0u8, 0u8, 0u8, 10u8, 1u8, 0u8, 0u8,
- 25u8, 1u8, 0u8, 0u8, 18u8, 0u8, 0u8, 0u8, 0u8, 2u8, 0u8, 15u8, 17u8, 0u8, 0u8,
- 68u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 2u8, 0u8, 17u8, 17u8, 0u8, 0u8,
- 191u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 2u8, 0u8, 15u8, 17u8, 0u8, 0u8,
- 191u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 2u8, 0u8, 15u8, 16u8, 0u8, 0u8,
- 191u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 2u8, 0u8, 16u8, 17u8, 0u8, 0u8,
- 221u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 2u8, 0u8, 15u8, 17u8, 0u8, 0u8,
- 221u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 2u8, 0u8, 15u8, 15u8, 0u8, 0u8,
- 221u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 4u8, 0u8, 0u8, 0u8, 0u8, 0u8,
- 0u8, 0u8, 35u8, 0u8, 0u8, 0u8, 35u8, 0u8, 0u8, 0u8, 35u8, 0u8, 0u8, 0u8, 35u8,
- 0u8, 0u8, 0u8, 35u8, 0u8, 0u8, 0u8, 9u8, 0u8, 0u8, 0u8, 18u8, 0u8, 0u8, 0u8,
- 18u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 35u8, 0u8, 0u8,
- 0u8, 35u8, 0u8, 0u8, 0u8,
- ])
- },
- pattern: unsafe {
- ::icu_list::provider::ListJoinerPattern::from_parts_unchecked(" e ", 3u8)
- },
- }),
- },
- ::icu_list::provider::ConditionalListJoinerPattern {
- default: unsafe {
- ::icu_list::provider::ListJoinerPattern::from_parts_unchecked(" y ", 3u8)
- },
- special_case: Some(::icu_list::provider::SpecialCasePattern {
- condition: unsafe {
- ::icu_list::provider::StringMatcher::from_dfa_bytes_unchecked(&[
- 114u8, 117u8, 115u8, 116u8, 45u8, 114u8, 101u8, 103u8, 101u8, 120u8, 45u8,
- 97u8, 117u8, 116u8, 111u8, 109u8, 97u8, 116u8, 97u8, 45u8, 100u8, 102u8, 97u8,
- 45u8, 115u8, 112u8, 97u8, 114u8, 115u8, 101u8, 0u8, 0u8, 255u8, 254u8, 0u8,
- 0u8, 2u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 14u8, 0u8, 0u8, 0u8, 1u8, 0u8,
- 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
- 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
- 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
- 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
- 0u8, 0u8, 0u8, 1u8, 2u8, 2u8, 2u8, 3u8, 4u8, 4u8, 5u8, 6u8, 7u8, 7u8, 7u8, 7u8,
- 7u8, 7u8, 7u8, 7u8, 7u8, 7u8, 7u8, 7u8, 7u8, 7u8, 7u8, 7u8, 7u8, 7u8, 7u8, 7u8,
- 7u8, 7u8, 7u8, 8u8, 9u8, 9u8, 9u8, 10u8, 11u8, 11u8, 12u8, 13u8, 14u8, 14u8,
- 14u8, 14u8, 14u8, 14u8, 14u8, 14u8, 14u8, 14u8, 14u8, 14u8, 14u8, 14u8, 14u8,
- 14u8, 14u8, 14u8, 14u8, 14u8, 14u8, 14u8, 15u8, 15u8, 15u8, 15u8, 15u8, 15u8,
- 15u8, 15u8, 15u8, 15u8, 15u8, 15u8, 15u8, 15u8, 15u8, 15u8, 16u8, 16u8, 16u8,
- 16u8, 16u8, 16u8, 16u8, 16u8, 16u8, 16u8, 16u8, 16u8, 16u8, 16u8, 16u8, 16u8,
- 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8,
- 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8,
- 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 18u8, 18u8, 19u8, 19u8, 19u8, 19u8, 19u8,
- 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8,
- 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 20u8,
- 21u8, 21u8, 21u8, 21u8, 21u8, 21u8, 21u8, 21u8, 21u8, 21u8, 21u8, 21u8, 22u8,
- 23u8, 23u8, 24u8, 25u8, 25u8, 25u8, 26u8, 27u8, 27u8, 27u8, 27u8, 27u8, 27u8,
- 27u8, 27u8, 27u8, 27u8, 27u8, 40u8, 1u8, 0u8, 0u8, 1u8, 0u8, 0u8, 0u8, 0u8,
- 0u8, 0u8, 0u8, 0u8, 1u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 128u8,
- 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 5u8,
- 0u8, 5u8, 5u8, 6u8, 6u8, 12u8, 12u8, 13u8, 13u8, 0u8, 0u8, 83u8, 0u8, 0u8, 0u8,
- 68u8, 0u8, 0u8, 0u8, 83u8, 0u8, 0u8, 0u8, 68u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
- 0u8, 0u8, 2u8, 0u8, 0u8, 27u8, 0u8, 0u8, 18u8, 0u8, 0u8, 0u8, 18u8, 0u8, 0u8,
- 0u8, 0u8, 3u8, 0u8, 6u8, 6u8, 13u8, 13u8, 0u8, 0u8, 104u8, 0u8, 0u8, 0u8,
- 104u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 14u8, 0u8, 0u8, 0u8, 2u8, 2u8,
- 4u8, 7u8, 9u8, 9u8, 11u8, 14u8, 19u8, 19u8, 20u8, 20u8, 21u8, 21u8, 22u8, 22u8,
- 23u8, 23u8, 24u8, 24u8, 25u8, 25u8, 26u8, 26u8, 0u8, 0u8, 68u8, 0u8, 0u8, 0u8,
- 68u8, 0u8, 0u8, 0u8, 68u8, 0u8, 0u8, 0u8, 68u8, 0u8, 0u8, 0u8, 68u8, 0u8, 0u8,
- 0u8, 191u8, 0u8, 0u8, 0u8, 206u8, 0u8, 0u8, 0u8, 221u8, 0u8, 0u8, 0u8, 236u8,
- 0u8, 0u8, 0u8, 221u8, 0u8, 0u8, 0u8, 251u8, 0u8, 0u8, 0u8, 10u8, 1u8, 0u8, 0u8,
- 25u8, 1u8, 0u8, 0u8, 18u8, 0u8, 0u8, 0u8, 0u8, 2u8, 0u8, 15u8, 17u8, 0u8, 0u8,
- 68u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 2u8, 0u8, 17u8, 17u8, 0u8, 0u8,
- 191u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 2u8, 0u8, 15u8, 17u8, 0u8, 0u8,
- 191u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 2u8, 0u8, 15u8, 16u8, 0u8, 0u8,
- 191u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 2u8, 0u8, 16u8, 17u8, 0u8, 0u8,
- 221u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 2u8, 0u8, 15u8, 17u8, 0u8, 0u8,
- 221u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 2u8, 0u8, 15u8, 15u8, 0u8, 0u8,
- 221u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 4u8, 0u8, 0u8, 0u8, 0u8, 0u8,
- 0u8, 0u8, 35u8, 0u8, 0u8, 0u8, 35u8, 0u8, 0u8, 0u8, 35u8, 0u8, 0u8, 0u8, 35u8,
- 0u8, 0u8, 0u8, 35u8, 0u8, 0u8, 0u8, 9u8, 0u8, 0u8, 0u8, 18u8, 0u8, 0u8, 0u8,
- 18u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 35u8, 0u8, 0u8,
- 0u8, 35u8, 0u8, 0u8, 0u8,
- ])
- },
- pattern: unsafe {
- ::icu_list::provider::ListJoinerPattern::from_parts_unchecked(" e ", 3u8)
- },
- }),
- },
-]);
-static FR: &DataStruct = &::icu_list::provider::ListFormatterPatternsV1([
- ::icu_list::provider::ConditionalListJoinerPattern {
- default: unsafe {
- ::icu_list::provider::ListJoinerPattern::from_parts_unchecked(", ", 2u8)
- },
- special_case: None,
- },
- ::icu_list::provider::ConditionalListJoinerPattern {
- default: unsafe {
- ::icu_list::provider::ListJoinerPattern::from_parts_unchecked(", ", 2u8)
- },
- special_case: None,
- },
- ::icu_list::provider::ConditionalListJoinerPattern {
- default: unsafe {
- ::icu_list::provider::ListJoinerPattern::from_parts_unchecked(" et ", 4u8)
- },
- special_case: None,
- },
- ::icu_list::provider::ConditionalListJoinerPattern {
- default: unsafe {
- ::icu_list::provider::ListJoinerPattern::from_parts_unchecked(" et ", 4u8)
- },
- special_case: None,
- },
- ::icu_list::provider::ConditionalListJoinerPattern {
- default: unsafe {
- ::icu_list::provider::ListJoinerPattern::from_parts_unchecked(", ", 2u8)
- },
- special_case: None,
- },
- ::icu_list::provider::ConditionalListJoinerPattern {
- default: unsafe {
- ::icu_list::provider::ListJoinerPattern::from_parts_unchecked(", ", 2u8)
- },
- special_case: None,
- },
- ::icu_list::provider::ConditionalListJoinerPattern {
- default: unsafe {
- ::icu_list::provider::ListJoinerPattern::from_parts_unchecked(" et ", 4u8)
- },
- special_case: None,
- },
- ::icu_list::provider::ConditionalListJoinerPattern {
- default: unsafe {
- ::icu_list::provider::ListJoinerPattern::from_parts_unchecked(" et ", 4u8)
- },
- special_case: None,
- },
- ::icu_list::provider::ConditionalListJoinerPattern {
- default: unsafe {
- ::icu_list::provider::ListJoinerPattern::from_parts_unchecked(", ", 2u8)
- },
- special_case: None,
- },
- ::icu_list::provider::ConditionalListJoinerPattern {
- default: unsafe {
- ::icu_list::provider::ListJoinerPattern::from_parts_unchecked(", ", 2u8)
- },
- special_case: None,
- },
- ::icu_list::provider::ConditionalListJoinerPattern {
- default: unsafe {
- ::icu_list::provider::ListJoinerPattern::from_parts_unchecked(", ", 2u8)
- },
- special_case: None,
- },
- ::icu_list::provider::ConditionalListJoinerPattern {
- default: unsafe {
- ::icu_list::provider::ListJoinerPattern::from_parts_unchecked(", ", 2u8)
- },
- special_case: None,
- },
-]);
-static IT: &DataStruct = &::icu_list::provider::ListFormatterPatternsV1([
- ::icu_list::provider::ConditionalListJoinerPattern {
- default: unsafe {
- ::icu_list::provider::ListJoinerPattern::from_parts_unchecked(", ", 2u8)
- },
- special_case: None,
- },
- ::icu_list::provider::ConditionalListJoinerPattern {
- default: unsafe {
- ::icu_list::provider::ListJoinerPattern::from_parts_unchecked(", ", 2u8)
- },
- special_case: None,
- },
- ::icu_list::provider::ConditionalListJoinerPattern {
- default: unsafe {
- ::icu_list::provider::ListJoinerPattern::from_parts_unchecked(" e ", 3u8)
- },
- special_case: None,
- },
- ::icu_list::provider::ConditionalListJoinerPattern {
- default: unsafe {
- ::icu_list::provider::ListJoinerPattern::from_parts_unchecked(" e ", 3u8)
- },
- special_case: None,
- },
- ::icu_list::provider::ConditionalListJoinerPattern {
- default: unsafe {
- ::icu_list::provider::ListJoinerPattern::from_parts_unchecked(", ", 2u8)
- },
- special_case: None,
- },
- ::icu_list::provider::ConditionalListJoinerPattern {
- default: unsafe {
- ::icu_list::provider::ListJoinerPattern::from_parts_unchecked(", ", 2u8)
- },
- special_case: None,
- },
- ::icu_list::provider::ConditionalListJoinerPattern {
- default: unsafe {
- ::icu_list::provider::ListJoinerPattern::from_parts_unchecked(" e ", 3u8)
- },
- special_case: None,
- },
- ::icu_list::provider::ConditionalListJoinerPattern {
- default: unsafe {
- ::icu_list::provider::ListJoinerPattern::from_parts_unchecked(" e ", 3u8)
- },
- special_case: None,
- },
- ::icu_list::provider::ConditionalListJoinerPattern {
- default: unsafe {
- ::icu_list::provider::ListJoinerPattern::from_parts_unchecked(", ", 2u8)
- },
- special_case: None,
- },
- ::icu_list::provider::ConditionalListJoinerPattern {
- default: unsafe {
- ::icu_list::provider::ListJoinerPattern::from_parts_unchecked(", ", 2u8)
- },
- special_case: None,
- },
- ::icu_list::provider::ConditionalListJoinerPattern {
- default: unsafe {
- ::icu_list::provider::ListJoinerPattern::from_parts_unchecked(" e ", 3u8)
- },
- special_case: None,
- },
- ::icu_list::provider::ConditionalListJoinerPattern {
- default: unsafe {
- ::icu_list::provider::ListJoinerPattern::from_parts_unchecked(" e ", 3u8)
- },
- special_case: None,
- },
-]);
-static JA: &DataStruct = &::icu_list::provider::ListFormatterPatternsV1([
- ::icu_list::provider::ConditionalListJoinerPattern {
- default: unsafe {
- ::icu_list::provider::ListJoinerPattern::from_parts_unchecked("、", 3u8)
- },
- special_case: None,
- },
- ::icu_list::provider::ConditionalListJoinerPattern {
- default: unsafe {
- ::icu_list::provider::ListJoinerPattern::from_parts_unchecked("、", 3u8)
- },
- special_case: None,
- },
- ::icu_list::provider::ConditionalListJoinerPattern {
- default: unsafe {
- ::icu_list::provider::ListJoinerPattern::from_parts_unchecked("、", 3u8)
- },
- special_case: None,
- },
- ::icu_list::provider::ConditionalListJoinerPattern {
- default: unsafe {
- ::icu_list::provider::ListJoinerPattern::from_parts_unchecked("、", 3u8)
- },
- special_case: None,
- },
- ::icu_list::provider::ConditionalListJoinerPattern {
- default: unsafe {
- ::icu_list::provider::ListJoinerPattern::from_parts_unchecked("、", 3u8)
- },
- special_case: None,
- },
- ::icu_list::provider::ConditionalListJoinerPattern {
- default: unsafe {
- ::icu_list::provider::ListJoinerPattern::from_parts_unchecked("、", 3u8)
- },
- special_case: None,
- },
- ::icu_list::provider::ConditionalListJoinerPattern {
- default: unsafe {
- ::icu_list::provider::ListJoinerPattern::from_parts_unchecked("、", 3u8)
- },
- special_case: None,
- },
- ::icu_list::provider::ConditionalListJoinerPattern {
- default: unsafe {
- ::icu_list::provider::ListJoinerPattern::from_parts_unchecked("、", 3u8)
- },
- special_case: None,
- },
- ::icu_list::provider::ConditionalListJoinerPattern {
- default: unsafe {
- ::icu_list::provider::ListJoinerPattern::from_parts_unchecked("、", 3u8)
- },
- special_case: None,
- },
- ::icu_list::provider::ConditionalListJoinerPattern {
- default: unsafe {
- ::icu_list::provider::ListJoinerPattern::from_parts_unchecked("、", 3u8)
- },
- special_case: None,
- },
- ::icu_list::provider::ConditionalListJoinerPattern {
- default: unsafe {
- ::icu_list::provider::ListJoinerPattern::from_parts_unchecked("、", 3u8)
- },
- special_case: None,
- },
- ::icu_list::provider::ConditionalListJoinerPattern {
- default: unsafe {
- ::icu_list::provider::ListJoinerPattern::from_parts_unchecked("、", 3u8)
- },
- special_case: None,
- },
-]);
-static PT: &DataStruct = &::icu_list::provider::ListFormatterPatternsV1([
- ::icu_list::provider::ConditionalListJoinerPattern {
- default: unsafe {
- ::icu_list::provider::ListJoinerPattern::from_parts_unchecked(", ", 2u8)
- },
- special_case: None,
- },
- ::icu_list::provider::ConditionalListJoinerPattern {
- default: unsafe {
- ::icu_list::provider::ListJoinerPattern::from_parts_unchecked(", ", 2u8)
- },
- special_case: None,
- },
- ::icu_list::provider::ConditionalListJoinerPattern {
- default: unsafe {
- ::icu_list::provider::ListJoinerPattern::from_parts_unchecked(" e ", 3u8)
- },
- special_case: None,
- },
- ::icu_list::provider::ConditionalListJoinerPattern {
- default: unsafe {
- ::icu_list::provider::ListJoinerPattern::from_parts_unchecked(" e ", 3u8)
- },
- special_case: None,
- },
- ::icu_list::provider::ConditionalListJoinerPattern {
- default: unsafe {
- ::icu_list::provider::ListJoinerPattern::from_parts_unchecked(", ", 2u8)
- },
- special_case: None,
- },
- ::icu_list::provider::ConditionalListJoinerPattern {
- default: unsafe {
- ::icu_list::provider::ListJoinerPattern::from_parts_unchecked(", ", 2u8)
- },
- special_case: None,
- },
- ::icu_list::provider::ConditionalListJoinerPattern {
- default: unsafe {
- ::icu_list::provider::ListJoinerPattern::from_parts_unchecked(" e ", 3u8)
- },
- special_case: None,
- },
- ::icu_list::provider::ConditionalListJoinerPattern {
- default: unsafe {
- ::icu_list::provider::ListJoinerPattern::from_parts_unchecked(" e ", 3u8)
- },
- special_case: None,
- },
- ::icu_list::provider::ConditionalListJoinerPattern {
- default: unsafe {
- ::icu_list::provider::ListJoinerPattern::from_parts_unchecked(", ", 2u8)
- },
- special_case: None,
- },
- ::icu_list::provider::ConditionalListJoinerPattern {
- default: unsafe {
- ::icu_list::provider::ListJoinerPattern::from_parts_unchecked(", ", 2u8)
- },
- special_case: None,
- },
- ::icu_list::provider::ConditionalListJoinerPattern {
- default: unsafe {
- ::icu_list::provider::ListJoinerPattern::from_parts_unchecked(", ", 2u8)
- },
- special_case: None,
- },
- ::icu_list::provider::ConditionalListJoinerPattern {
- default: unsafe {
- ::icu_list::provider::ListJoinerPattern::from_parts_unchecked(", ", 2u8)
- },
- special_case: None,
- },
-]);
-static RU: &DataStruct = &::icu_list::provider::ListFormatterPatternsV1([
- ::icu_list::provider::ConditionalListJoinerPattern {
- default: unsafe {
- ::icu_list::provider::ListJoinerPattern::from_parts_unchecked(", ", 2u8)
- },
- special_case: None,
- },
- ::icu_list::provider::ConditionalListJoinerPattern {
- default: unsafe {
- ::icu_list::provider::ListJoinerPattern::from_parts_unchecked(", ", 2u8)
- },
- special_case: None,
- },
- ::icu_list::provider::ConditionalListJoinerPattern {
- default: unsafe {
- ::icu_list::provider::ListJoinerPattern::from_parts_unchecked(" и ", 4u8)
- },
- special_case: None,
- },
- ::icu_list::provider::ConditionalListJoinerPattern {
- default: unsafe {
- ::icu_list::provider::ListJoinerPattern::from_parts_unchecked(" и ", 4u8)
- },
- special_case: None,
- },
- ::icu_list::provider::ConditionalListJoinerPattern {
- default: unsafe {
- ::icu_list::provider::ListJoinerPattern::from_parts_unchecked(", ", 2u8)
- },
- special_case: None,
- },
- ::icu_list::provider::ConditionalListJoinerPattern {
- default: unsafe {
- ::icu_list::provider::ListJoinerPattern::from_parts_unchecked(", ", 2u8)
- },
- special_case: None,
- },
- ::icu_list::provider::ConditionalListJoinerPattern {
- default: unsafe {
- ::icu_list::provider::ListJoinerPattern::from_parts_unchecked(" и ", 4u8)
- },
- special_case: None,
- },
- ::icu_list::provider::ConditionalListJoinerPattern {
- default: unsafe {
- ::icu_list::provider::ListJoinerPattern::from_parts_unchecked(" и ", 4u8)
- },
- special_case: None,
- },
- ::icu_list::provider::ConditionalListJoinerPattern {
- default: unsafe {
- ::icu_list::provider::ListJoinerPattern::from_parts_unchecked(", ", 2u8)
- },
- special_case: None,
- },
- ::icu_list::provider::ConditionalListJoinerPattern {
- default: unsafe {
- ::icu_list::provider::ListJoinerPattern::from_parts_unchecked(", ", 2u8)
- },
- special_case: None,
- },
- ::icu_list::provider::ConditionalListJoinerPattern {
- default: unsafe {
- ::icu_list::provider::ListJoinerPattern::from_parts_unchecked(", ", 2u8)
- },
- special_case: None,
- },
- ::icu_list::provider::ConditionalListJoinerPattern {
- default: unsafe {
- ::icu_list::provider::ListJoinerPattern::from_parts_unchecked(", ", 2u8)
- },
- special_case: None,
- },
-]);
-static TR: &DataStruct = &::icu_list::provider::ListFormatterPatternsV1([
- ::icu_list::provider::ConditionalListJoinerPattern {
- default: unsafe {
- ::icu_list::provider::ListJoinerPattern::from_parts_unchecked(", ", 2u8)
- },
- special_case: None,
- },
- ::icu_list::provider::ConditionalListJoinerPattern {
- default: unsafe {
- ::icu_list::provider::ListJoinerPattern::from_parts_unchecked(", ", 2u8)
- },
- special_case: None,
- },
- ::icu_list::provider::ConditionalListJoinerPattern {
- default: unsafe {
- ::icu_list::provider::ListJoinerPattern::from_parts_unchecked(" ve ", 4u8)
- },
- special_case: None,
- },
- ::icu_list::provider::ConditionalListJoinerPattern {
- default: unsafe {
- ::icu_list::provider::ListJoinerPattern::from_parts_unchecked(" ve ", 4u8)
- },
- special_case: None,
- },
- ::icu_list::provider::ConditionalListJoinerPattern {
- default: unsafe {
- ::icu_list::provider::ListJoinerPattern::from_parts_unchecked(", ", 2u8)
- },
- special_case: None,
- },
- ::icu_list::provider::ConditionalListJoinerPattern {
- default: unsafe {
- ::icu_list::provider::ListJoinerPattern::from_parts_unchecked(", ", 2u8)
- },
- special_case: None,
- },
- ::icu_list::provider::ConditionalListJoinerPattern {
- default: unsafe {
- ::icu_list::provider::ListJoinerPattern::from_parts_unchecked(" ve ", 4u8)
- },
- special_case: None,
- },
- ::icu_list::provider::ConditionalListJoinerPattern {
- default: unsafe {
- ::icu_list::provider::ListJoinerPattern::from_parts_unchecked(" ve ", 4u8)
- },
- special_case: None,
- },
- ::icu_list::provider::ConditionalListJoinerPattern {
- default: unsafe {
- ::icu_list::provider::ListJoinerPattern::from_parts_unchecked(", ", 2u8)
- },
- special_case: None,
- },
- ::icu_list::provider::ConditionalListJoinerPattern {
- default: unsafe {
- ::icu_list::provider::ListJoinerPattern::from_parts_unchecked(", ", 2u8)
- },
- special_case: None,
- },
- ::icu_list::provider::ConditionalListJoinerPattern {
- default: unsafe {
- ::icu_list::provider::ListJoinerPattern::from_parts_unchecked(", ", 2u8)
- },
- special_case: None,
- },
- ::icu_list::provider::ConditionalListJoinerPattern {
- default: unsafe {
- ::icu_list::provider::ListJoinerPattern::from_parts_unchecked(", ", 2u8)
- },
- special_case: None,
- },
-]);
-static UND: &DataStruct = &::icu_list::provider::ListFormatterPatternsV1([
- ::icu_list::provider::ConditionalListJoinerPattern {
- default: unsafe {
- ::icu_list::provider::ListJoinerPattern::from_parts_unchecked(", ", 2u8)
- },
- special_case: None,
- },
- ::icu_list::provider::ConditionalListJoinerPattern {
- default: unsafe {
- ::icu_list::provider::ListJoinerPattern::from_parts_unchecked(", ", 2u8)
- },
- special_case: None,
- },
- ::icu_list::provider::ConditionalListJoinerPattern {
- default: unsafe {
- ::icu_list::provider::ListJoinerPattern::from_parts_unchecked(", ", 2u8)
- },
- special_case: None,
- },
- ::icu_list::provider::ConditionalListJoinerPattern {
- default: unsafe {
- ::icu_list::provider::ListJoinerPattern::from_parts_unchecked(", ", 2u8)
- },
- special_case: None,
- },
- ::icu_list::provider::ConditionalListJoinerPattern {
- default: unsafe {
- ::icu_list::provider::ListJoinerPattern::from_parts_unchecked(", ", 2u8)
- },
- special_case: None,
- },
- ::icu_list::provider::ConditionalListJoinerPattern {
- default: unsafe {
- ::icu_list::provider::ListJoinerPattern::from_parts_unchecked(", ", 2u8)
- },
- special_case: None,
- },
- ::icu_list::provider::ConditionalListJoinerPattern {
- default: unsafe {
- ::icu_list::provider::ListJoinerPattern::from_parts_unchecked(", ", 2u8)
- },
- special_case: None,
- },
- ::icu_list::provider::ConditionalListJoinerPattern {
- default: unsafe {
- ::icu_list::provider::ListJoinerPattern::from_parts_unchecked(", ", 2u8)
- },
- special_case: None,
- },
- ::icu_list::provider::ConditionalListJoinerPattern {
- default: unsafe {
- ::icu_list::provider::ListJoinerPattern::from_parts_unchecked(", ", 2u8)
- },
- special_case: None,
- },
- ::icu_list::provider::ConditionalListJoinerPattern {
- default: unsafe {
- ::icu_list::provider::ListJoinerPattern::from_parts_unchecked(", ", 2u8)
- },
- special_case: None,
- },
- ::icu_list::provider::ConditionalListJoinerPattern {
- default: unsafe {
- ::icu_list::provider::ListJoinerPattern::from_parts_unchecked(", ", 2u8)
- },
- special_case: None,
- },
- ::icu_list::provider::ConditionalListJoinerPattern {
- default: unsafe {
- ::icu_list::provider::ListJoinerPattern::from_parts_unchecked(", ", 2u8)
- },
- special_case: None,
- },
-]);
-static ZH_HANT: &DataStruct = &::icu_list::provider::ListFormatterPatternsV1([
- ::icu_list::provider::ConditionalListJoinerPattern {
- default: unsafe {
- ::icu_list::provider::ListJoinerPattern::from_parts_unchecked("、", 3u8)
- },
- special_case: None,
- },
- ::icu_list::provider::ConditionalListJoinerPattern {
- default: unsafe {
- ::icu_list::provider::ListJoinerPattern::from_parts_unchecked("、", 3u8)
- },
- special_case: None,
- },
- ::icu_list::provider::ConditionalListJoinerPattern {
- default: unsafe {
- ::icu_list::provider::ListJoinerPattern::from_parts_unchecked("和", 3u8)
- },
- special_case: None,
- },
- ::icu_list::provider::ConditionalListJoinerPattern {
- default: unsafe {
- ::icu_list::provider::ListJoinerPattern::from_parts_unchecked("和", 3u8)
- },
- special_case: None,
- },
- ::icu_list::provider::ConditionalListJoinerPattern {
- default: unsafe {
- ::icu_list::provider::ListJoinerPattern::from_parts_unchecked("、", 3u8)
- },
- special_case: None,
- },
- ::icu_list::provider::ConditionalListJoinerPattern {
- default: unsafe {
- ::icu_list::provider::ListJoinerPattern::from_parts_unchecked("、", 3u8)
- },
- special_case: None,
- },
- ::icu_list::provider::ConditionalListJoinerPattern {
- default: unsafe {
- ::icu_list::provider::ListJoinerPattern::from_parts_unchecked("和", 3u8)
- },
- special_case: None,
- },
- ::icu_list::provider::ConditionalListJoinerPattern {
- default: unsafe {
- ::icu_list::provider::ListJoinerPattern::from_parts_unchecked("和", 3u8)
- },
- special_case: None,
- },
- ::icu_list::provider::ConditionalListJoinerPattern {
- default: unsafe {
- ::icu_list::provider::ListJoinerPattern::from_parts_unchecked("、", 3u8)
- },
- special_case: None,
- },
- ::icu_list::provider::ConditionalListJoinerPattern {
- default: unsafe {
- ::icu_list::provider::ListJoinerPattern::from_parts_unchecked("、", 3u8)
- },
- special_case: None,
- },
- ::icu_list::provider::ConditionalListJoinerPattern {
- default: unsafe {
- ::icu_list::provider::ListJoinerPattern::from_parts_unchecked("和", 3u8)
- },
- special_case: None,
- },
- ::icu_list::provider::ConditionalListJoinerPattern {
- default: unsafe {
- ::icu_list::provider::ListJoinerPattern::from_parts_unchecked("和", 3u8)
- },
- special_case: None,
- },
-]);
-static ZH_ZH_HANS: &DataStruct = &::icu_list::provider::ListFormatterPatternsV1([
- ::icu_list::provider::ConditionalListJoinerPattern {
- default: unsafe {
- ::icu_list::provider::ListJoinerPattern::from_parts_unchecked("、", 3u8)
- },
- special_case: None,
- },
- ::icu_list::provider::ConditionalListJoinerPattern {
- default: unsafe {
- ::icu_list::provider::ListJoinerPattern::from_parts_unchecked("、", 3u8)
- },
- special_case: None,
- },
- ::icu_list::provider::ConditionalListJoinerPattern {
- default: unsafe {
- ::icu_list::provider::ListJoinerPattern::from_parts_unchecked("和", 3u8)
- },
- special_case: None,
- },
- ::icu_list::provider::ConditionalListJoinerPattern {
- default: unsafe {
- ::icu_list::provider::ListJoinerPattern::from_parts_unchecked("和", 3u8)
- },
- special_case: None,
- },
- ::icu_list::provider::ConditionalListJoinerPattern {
- default: unsafe {
- ::icu_list::provider::ListJoinerPattern::from_parts_unchecked("、", 3u8)
- },
- special_case: None,
- },
- ::icu_list::provider::ConditionalListJoinerPattern {
- default: unsafe {
- ::icu_list::provider::ListJoinerPattern::from_parts_unchecked("、", 3u8)
- },
- special_case: None,
- },
- ::icu_list::provider::ConditionalListJoinerPattern {
- default: unsafe {
- ::icu_list::provider::ListJoinerPattern::from_parts_unchecked("和", 3u8)
- },
- special_case: None,
- },
- ::icu_list::provider::ConditionalListJoinerPattern {
- default: unsafe {
- ::icu_list::provider::ListJoinerPattern::from_parts_unchecked("和", 3u8)
- },
- special_case: None,
- },
- ::icu_list::provider::ConditionalListJoinerPattern {
- default: unsafe {
- ::icu_list::provider::ListJoinerPattern::from_parts_unchecked("、", 3u8)
- },
- special_case: None,
- },
- ::icu_list::provider::ConditionalListJoinerPattern {
- default: unsafe {
- ::icu_list::provider::ListJoinerPattern::from_parts_unchecked("、", 3u8)
- },
- special_case: None,
- },
- ::icu_list::provider::ConditionalListJoinerPattern {
- default: unsafe {
- ::icu_list::provider::ListJoinerPattern::from_parts_unchecked("、", 3u8)
- },
- special_case: None,
- },
- ::icu_list::provider::ConditionalListJoinerPattern {
- default: unsafe {
- ::icu_list::provider::ListJoinerPattern::from_parts_unchecked("、", 3u8)
- },
- special_case: None,
- },
-]);
diff --git a/compiler/rustc_baked_icu_data/src/data/list/and_v1/en.rs.data b/compiler/rustc_baked_icu_data/src/data/list/and_v1/en.rs.data
new file mode 100644
index 000000000..cb5cbfa87
--- /dev/null
+++ b/compiler/rustc_baked_icu_data/src/data/list/and_v1/en.rs.data
@@ -0,0 +1,74 @@
+::icu_list::provider::ListFormatterPatternsV1([
+ ::icu_list::provider::ConditionalListJoinerPattern {
+ default: unsafe {
+ ::icu_list::provider::ListJoinerPattern::from_parts_unchecked(", ", 2u8)
+ },
+ special_case: None,
+ },
+ ::icu_list::provider::ConditionalListJoinerPattern {
+ default: unsafe {
+ ::icu_list::provider::ListJoinerPattern::from_parts_unchecked(", ", 2u8)
+ },
+ special_case: None,
+ },
+ ::icu_list::provider::ConditionalListJoinerPattern {
+ default: unsafe {
+ ::icu_list::provider::ListJoinerPattern::from_parts_unchecked(", and ", 6u8)
+ },
+ special_case: None,
+ },
+ ::icu_list::provider::ConditionalListJoinerPattern {
+ default: unsafe {
+ ::icu_list::provider::ListJoinerPattern::from_parts_unchecked(" and ", 5u8)
+ },
+ special_case: None,
+ },
+ ::icu_list::provider::ConditionalListJoinerPattern {
+ default: unsafe {
+ ::icu_list::provider::ListJoinerPattern::from_parts_unchecked(", ", 2u8)
+ },
+ special_case: None,
+ },
+ ::icu_list::provider::ConditionalListJoinerPattern {
+ default: unsafe {
+ ::icu_list::provider::ListJoinerPattern::from_parts_unchecked(", ", 2u8)
+ },
+ special_case: None,
+ },
+ ::icu_list::provider::ConditionalListJoinerPattern {
+ default: unsafe {
+ ::icu_list::provider::ListJoinerPattern::from_parts_unchecked(", & ", 4u8)
+ },
+ special_case: None,
+ },
+ ::icu_list::provider::ConditionalListJoinerPattern {
+ default: unsafe {
+ ::icu_list::provider::ListJoinerPattern::from_parts_unchecked(" & ", 3u8)
+ },
+ special_case: None,
+ },
+ ::icu_list::provider::ConditionalListJoinerPattern {
+ default: unsafe {
+ ::icu_list::provider::ListJoinerPattern::from_parts_unchecked(", ", 2u8)
+ },
+ special_case: None,
+ },
+ ::icu_list::provider::ConditionalListJoinerPattern {
+ default: unsafe {
+ ::icu_list::provider::ListJoinerPattern::from_parts_unchecked(", ", 2u8)
+ },
+ special_case: None,
+ },
+ ::icu_list::provider::ConditionalListJoinerPattern {
+ default: unsafe {
+ ::icu_list::provider::ListJoinerPattern::from_parts_unchecked(", ", 2u8)
+ },
+ special_case: None,
+ },
+ ::icu_list::provider::ConditionalListJoinerPattern {
+ default: unsafe {
+ ::icu_list::provider::ListJoinerPattern::from_parts_unchecked(", ", 2u8)
+ },
+ special_case: None,
+ },
+])
diff --git a/compiler/rustc_baked_icu_data/src/data/list/and_v1/es.rs.data b/compiler/rustc_baked_icu_data/src/data/list/and_v1/es.rs.data
new file mode 100644
index 000000000..51f910975
--- /dev/null
+++ b/compiler/rustc_baked_icu_data/src/data/list/and_v1/es.rs.data
@@ -0,0 +1,836 @@
+::icu_list::provider::ListFormatterPatternsV1([
+ ::icu_list::provider::ConditionalListJoinerPattern {
+ default: unsafe {
+ ::icu_list::provider::ListJoinerPattern::from_parts_unchecked(", ", 2u8)
+ },
+ special_case: None,
+ },
+ ::icu_list::provider::ConditionalListJoinerPattern {
+ default: unsafe {
+ ::icu_list::provider::ListJoinerPattern::from_parts_unchecked(", ", 2u8)
+ },
+ special_case: None,
+ },
+ ::icu_list::provider::ConditionalListJoinerPattern {
+ default: unsafe {
+ ::icu_list::provider::ListJoinerPattern::from_parts_unchecked(" y ", 3u8)
+ },
+ special_case: Some(::icu_list::provider::SpecialCasePattern {
+ condition: unsafe {
+ ::icu_list::provider::SerdeDFA::from_dfa_bytes_unchecked(
+ if cfg!(target_endian = "little") {
+ &[
+ 114u8, 117u8, 115u8, 116u8, 45u8, 114u8, 101u8, 103u8, 101u8,
+ 120u8, 45u8, 97u8, 117u8, 116u8, 111u8, 109u8, 97u8, 116u8, 97u8,
+ 45u8, 100u8, 102u8, 97u8, 45u8, 115u8, 112u8, 97u8, 114u8, 115u8,
+ 101u8, 0u8, 0u8, 255u8, 254u8, 0u8, 0u8, 2u8, 0u8, 0u8, 0u8, 0u8,
+ 0u8, 0u8, 0u8, 14u8, 0u8, 0u8, 0u8, 1u8, 0u8, 0u8, 0u8, 0u8, 0u8,
+ 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
+ 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
+ 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
+ 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
+ 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 2u8,
+ 2u8, 2u8, 3u8, 4u8, 4u8, 5u8, 6u8, 7u8, 7u8, 7u8, 7u8, 7u8, 7u8,
+ 7u8, 7u8, 7u8, 7u8, 7u8, 7u8, 7u8, 7u8, 7u8, 7u8, 7u8, 7u8, 7u8,
+ 7u8, 7u8, 7u8, 7u8, 8u8, 9u8, 9u8, 9u8, 10u8, 11u8, 11u8, 12u8,
+ 13u8, 14u8, 14u8, 14u8, 14u8, 14u8, 14u8, 14u8, 14u8, 14u8, 14u8,
+ 14u8, 14u8, 14u8, 14u8, 14u8, 14u8, 14u8, 14u8, 14u8, 14u8, 14u8,
+ 14u8, 15u8, 15u8, 15u8, 15u8, 15u8, 15u8, 15u8, 15u8, 15u8, 15u8,
+ 15u8, 15u8, 15u8, 15u8, 15u8, 15u8, 16u8, 16u8, 16u8, 16u8, 16u8,
+ 16u8, 16u8, 16u8, 16u8, 16u8, 16u8, 16u8, 16u8, 16u8, 16u8, 16u8,
+ 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8,
+ 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8,
+ 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 18u8,
+ 18u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8,
+ 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8,
+ 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 20u8, 21u8,
+ 21u8, 21u8, 21u8, 21u8, 21u8, 21u8, 21u8, 21u8, 21u8, 21u8, 21u8,
+ 22u8, 23u8, 23u8, 24u8, 25u8, 25u8, 25u8, 26u8, 27u8, 27u8, 27u8,
+ 27u8, 27u8, 27u8, 27u8, 27u8, 27u8, 27u8, 27u8, 40u8, 1u8, 0u8,
+ 0u8, 1u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 0u8, 0u8,
+ 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 128u8, 0u8, 0u8, 0u8, 0u8, 0u8,
+ 0u8, 1u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 5u8, 0u8, 5u8,
+ 5u8, 6u8, 6u8, 12u8, 12u8, 13u8, 13u8, 0u8, 0u8, 83u8, 0u8, 0u8,
+ 0u8, 68u8, 0u8, 0u8, 0u8, 83u8, 0u8, 0u8, 0u8, 68u8, 0u8, 0u8, 0u8,
+ 0u8, 0u8, 0u8, 0u8, 0u8, 2u8, 0u8, 0u8, 27u8, 0u8, 0u8, 18u8, 0u8,
+ 0u8, 0u8, 18u8, 0u8, 0u8, 0u8, 0u8, 3u8, 0u8, 6u8, 6u8, 13u8, 13u8,
+ 0u8, 0u8, 104u8, 0u8, 0u8, 0u8, 104u8, 0u8, 0u8, 0u8, 0u8, 0u8,
+ 0u8, 0u8, 0u8, 14u8, 0u8, 0u8, 0u8, 2u8, 2u8, 4u8, 7u8, 9u8, 9u8,
+ 11u8, 14u8, 19u8, 19u8, 20u8, 20u8, 21u8, 21u8, 22u8, 22u8, 23u8,
+ 23u8, 24u8, 24u8, 25u8, 25u8, 26u8, 26u8, 0u8, 0u8, 68u8, 0u8, 0u8,
+ 0u8, 68u8, 0u8, 0u8, 0u8, 68u8, 0u8, 0u8, 0u8, 68u8, 0u8, 0u8, 0u8,
+ 68u8, 0u8, 0u8, 0u8, 191u8, 0u8, 0u8, 0u8, 206u8, 0u8, 0u8, 0u8,
+ 221u8, 0u8, 0u8, 0u8, 236u8, 0u8, 0u8, 0u8, 221u8, 0u8, 0u8, 0u8,
+ 251u8, 0u8, 0u8, 0u8, 10u8, 1u8, 0u8, 0u8, 25u8, 1u8, 0u8, 0u8,
+ 18u8, 0u8, 0u8, 0u8, 0u8, 2u8, 0u8, 15u8, 17u8, 0u8, 0u8, 68u8,
+ 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 2u8, 0u8, 17u8, 17u8, 0u8,
+ 0u8, 191u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 2u8, 0u8, 15u8,
+ 17u8, 0u8, 0u8, 191u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 2u8,
+ 0u8, 15u8, 16u8, 0u8, 0u8, 191u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
+ 0u8, 0u8, 2u8, 0u8, 16u8, 17u8, 0u8, 0u8, 221u8, 0u8, 0u8, 0u8,
+ 0u8, 0u8, 0u8, 0u8, 0u8, 2u8, 0u8, 15u8, 17u8, 0u8, 0u8, 221u8,
+ 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 2u8, 0u8, 15u8, 15u8, 0u8,
+ 0u8, 221u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 4u8, 0u8, 0u8,
+ 0u8, 0u8, 0u8, 0u8, 0u8, 35u8, 0u8, 0u8, 0u8, 35u8, 0u8, 0u8, 0u8,
+ 35u8, 0u8, 0u8, 0u8, 35u8, 0u8, 0u8, 0u8, 35u8, 0u8, 0u8, 0u8, 9u8,
+ 0u8, 0u8, 0u8, 18u8, 0u8, 0u8, 0u8, 18u8, 0u8, 0u8, 0u8, 0u8, 0u8,
+ 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 35u8, 0u8, 0u8, 0u8, 35u8, 0u8, 0u8,
+ 0u8,
+ ]
+ } else {
+ &[
+ 114u8, 117u8, 115u8, 116u8, 45u8, 114u8, 101u8, 103u8, 101u8,
+ 120u8, 45u8, 97u8, 117u8, 116u8, 111u8, 109u8, 97u8, 116u8, 97u8,
+ 45u8, 100u8, 102u8, 97u8, 45u8, 115u8, 112u8, 97u8, 114u8, 115u8,
+ 101u8, 0u8, 0u8, 0u8, 0u8, 254u8, 255u8, 0u8, 0u8, 0u8, 2u8, 0u8,
+ 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 14u8, 0u8, 0u8, 0u8, 1u8, 0u8, 0u8,
+ 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
+ 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
+ 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
+ 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
+ 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 2u8,
+ 2u8, 2u8, 3u8, 4u8, 4u8, 5u8, 6u8, 7u8, 7u8, 7u8, 7u8, 7u8, 7u8,
+ 7u8, 7u8, 7u8, 7u8, 7u8, 7u8, 7u8, 7u8, 7u8, 7u8, 7u8, 7u8, 7u8,
+ 7u8, 7u8, 7u8, 7u8, 8u8, 9u8, 9u8, 9u8, 10u8, 11u8, 11u8, 12u8,
+ 13u8, 14u8, 14u8, 14u8, 14u8, 14u8, 14u8, 14u8, 14u8, 14u8, 14u8,
+ 14u8, 14u8, 14u8, 14u8, 14u8, 14u8, 14u8, 14u8, 14u8, 14u8, 14u8,
+ 14u8, 15u8, 15u8, 15u8, 15u8, 15u8, 15u8, 15u8, 15u8, 15u8, 15u8,
+ 15u8, 15u8, 15u8, 15u8, 15u8, 15u8, 16u8, 16u8, 16u8, 16u8, 16u8,
+ 16u8, 16u8, 16u8, 16u8, 16u8, 16u8, 16u8, 16u8, 16u8, 16u8, 16u8,
+ 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8,
+ 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8,
+ 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 18u8,
+ 18u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8,
+ 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8,
+ 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 20u8, 21u8,
+ 21u8, 21u8, 21u8, 21u8, 21u8, 21u8, 21u8, 21u8, 21u8, 21u8, 21u8,
+ 22u8, 23u8, 23u8, 24u8, 25u8, 25u8, 25u8, 26u8, 27u8, 27u8, 27u8,
+ 27u8, 27u8, 27u8, 27u8, 27u8, 27u8, 27u8, 27u8, 0u8, 0u8, 1u8,
+ 40u8, 1u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 0u8, 0u8,
+ 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 128u8, 0u8, 0u8, 0u8, 0u8, 0u8,
+ 0u8, 1u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 5u8, 0u8, 5u8,
+ 5u8, 6u8, 6u8, 12u8, 12u8, 13u8, 13u8, 0u8, 0u8, 83u8, 0u8, 0u8,
+ 0u8, 68u8, 0u8, 0u8, 0u8, 83u8, 0u8, 0u8, 0u8, 68u8, 0u8, 0u8, 0u8,
+ 0u8, 0u8, 0u8, 0u8, 0u8, 2u8, 0u8, 0u8, 27u8, 0u8, 0u8, 18u8, 0u8,
+ 0u8, 0u8, 18u8, 0u8, 0u8, 0u8, 0u8, 3u8, 0u8, 6u8, 6u8, 13u8, 13u8,
+ 0u8, 0u8, 104u8, 0u8, 0u8, 0u8, 104u8, 0u8, 0u8, 0u8, 0u8, 0u8,
+ 0u8, 0u8, 0u8, 14u8, 0u8, 0u8, 0u8, 2u8, 2u8, 4u8, 7u8, 9u8, 9u8,
+ 11u8, 14u8, 19u8, 19u8, 20u8, 20u8, 21u8, 21u8, 22u8, 22u8, 23u8,
+ 23u8, 24u8, 24u8, 25u8, 25u8, 26u8, 26u8, 0u8, 0u8, 68u8, 0u8, 0u8,
+ 0u8, 68u8, 0u8, 0u8, 0u8, 68u8, 0u8, 0u8, 0u8, 68u8, 0u8, 0u8, 0u8,
+ 68u8, 0u8, 0u8, 0u8, 191u8, 0u8, 0u8, 0u8, 206u8, 0u8, 0u8, 0u8,
+ 221u8, 0u8, 0u8, 0u8, 236u8, 0u8, 0u8, 0u8, 221u8, 0u8, 0u8, 0u8,
+ 251u8, 0u8, 0u8, 0u8, 10u8, 1u8, 0u8, 0u8, 25u8, 1u8, 0u8, 0u8,
+ 18u8, 0u8, 0u8, 0u8, 0u8, 2u8, 0u8, 15u8, 17u8, 0u8, 0u8, 68u8,
+ 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 2u8, 0u8, 17u8, 17u8, 0u8,
+ 0u8, 191u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 2u8, 0u8, 15u8,
+ 17u8, 0u8, 0u8, 191u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 2u8,
+ 0u8, 15u8, 16u8, 0u8, 0u8, 191u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
+ 0u8, 0u8, 2u8, 0u8, 16u8, 17u8, 0u8, 0u8, 221u8, 0u8, 0u8, 0u8,
+ 0u8, 0u8, 0u8, 0u8, 0u8, 2u8, 0u8, 15u8, 17u8, 0u8, 0u8, 221u8,
+ 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 2u8, 0u8, 15u8, 15u8, 0u8,
+ 0u8, 221u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
+ 4u8, 0u8, 0u8, 0u8, 0u8, 35u8, 0u8, 0u8, 0u8, 35u8, 0u8, 0u8, 0u8,
+ 35u8, 0u8, 0u8, 0u8, 35u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 35u8, 0u8,
+ 0u8, 0u8, 9u8, 0u8, 0u8, 0u8, 18u8, 0u8, 0u8, 0u8, 18u8, 0u8, 0u8,
+ 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 35u8, 0u8, 0u8, 0u8,
+ 35u8,
+ ]
+ },
+ )
+ },
+ pattern: unsafe {
+ ::icu_list::provider::ListJoinerPattern::from_parts_unchecked(" e ", 3u8)
+ },
+ }),
+ },
+ ::icu_list::provider::ConditionalListJoinerPattern {
+ default: unsafe {
+ ::icu_list::provider::ListJoinerPattern::from_parts_unchecked(" y ", 3u8)
+ },
+ special_case: Some(::icu_list::provider::SpecialCasePattern {
+ condition: unsafe {
+ ::icu_list::provider::SerdeDFA::from_dfa_bytes_unchecked(
+ if cfg!(target_endian = "little") {
+ &[
+ 114u8, 117u8, 115u8, 116u8, 45u8, 114u8, 101u8, 103u8, 101u8,
+ 120u8, 45u8, 97u8, 117u8, 116u8, 111u8, 109u8, 97u8, 116u8, 97u8,
+ 45u8, 100u8, 102u8, 97u8, 45u8, 115u8, 112u8, 97u8, 114u8, 115u8,
+ 101u8, 0u8, 0u8, 255u8, 254u8, 0u8, 0u8, 2u8, 0u8, 0u8, 0u8, 0u8,
+ 0u8, 0u8, 0u8, 14u8, 0u8, 0u8, 0u8, 1u8, 0u8, 0u8, 0u8, 0u8, 0u8,
+ 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
+ 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
+ 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
+ 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
+ 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 2u8,
+ 2u8, 2u8, 3u8, 4u8, 4u8, 5u8, 6u8, 7u8, 7u8, 7u8, 7u8, 7u8, 7u8,
+ 7u8, 7u8, 7u8, 7u8, 7u8, 7u8, 7u8, 7u8, 7u8, 7u8, 7u8, 7u8, 7u8,
+ 7u8, 7u8, 7u8, 7u8, 8u8, 9u8, 9u8, 9u8, 10u8, 11u8, 11u8, 12u8,
+ 13u8, 14u8, 14u8, 14u8, 14u8, 14u8, 14u8, 14u8, 14u8, 14u8, 14u8,
+ 14u8, 14u8, 14u8, 14u8, 14u8, 14u8, 14u8, 14u8, 14u8, 14u8, 14u8,
+ 14u8, 15u8, 15u8, 15u8, 15u8, 15u8, 15u8, 15u8, 15u8, 15u8, 15u8,
+ 15u8, 15u8, 15u8, 15u8, 15u8, 15u8, 16u8, 16u8, 16u8, 16u8, 16u8,
+ 16u8, 16u8, 16u8, 16u8, 16u8, 16u8, 16u8, 16u8, 16u8, 16u8, 16u8,
+ 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8,
+ 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8,
+ 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 18u8,
+ 18u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8,
+ 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8,
+ 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 20u8, 21u8,
+ 21u8, 21u8, 21u8, 21u8, 21u8, 21u8, 21u8, 21u8, 21u8, 21u8, 21u8,
+ 22u8, 23u8, 23u8, 24u8, 25u8, 25u8, 25u8, 26u8, 27u8, 27u8, 27u8,
+ 27u8, 27u8, 27u8, 27u8, 27u8, 27u8, 27u8, 27u8, 40u8, 1u8, 0u8,
+ 0u8, 1u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 0u8, 0u8,
+ 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 128u8, 0u8, 0u8, 0u8, 0u8, 0u8,
+ 0u8, 1u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 5u8, 0u8, 5u8,
+ 5u8, 6u8, 6u8, 12u8, 12u8, 13u8, 13u8, 0u8, 0u8, 83u8, 0u8, 0u8,
+ 0u8, 68u8, 0u8, 0u8, 0u8, 83u8, 0u8, 0u8, 0u8, 68u8, 0u8, 0u8, 0u8,
+ 0u8, 0u8, 0u8, 0u8, 0u8, 2u8, 0u8, 0u8, 27u8, 0u8, 0u8, 18u8, 0u8,
+ 0u8, 0u8, 18u8, 0u8, 0u8, 0u8, 0u8, 3u8, 0u8, 6u8, 6u8, 13u8, 13u8,
+ 0u8, 0u8, 104u8, 0u8, 0u8, 0u8, 104u8, 0u8, 0u8, 0u8, 0u8, 0u8,
+ 0u8, 0u8, 0u8, 14u8, 0u8, 0u8, 0u8, 2u8, 2u8, 4u8, 7u8, 9u8, 9u8,
+ 11u8, 14u8, 19u8, 19u8, 20u8, 20u8, 21u8, 21u8, 22u8, 22u8, 23u8,
+ 23u8, 24u8, 24u8, 25u8, 25u8, 26u8, 26u8, 0u8, 0u8, 68u8, 0u8, 0u8,
+ 0u8, 68u8, 0u8, 0u8, 0u8, 68u8, 0u8, 0u8, 0u8, 68u8, 0u8, 0u8, 0u8,
+ 68u8, 0u8, 0u8, 0u8, 191u8, 0u8, 0u8, 0u8, 206u8, 0u8, 0u8, 0u8,
+ 221u8, 0u8, 0u8, 0u8, 236u8, 0u8, 0u8, 0u8, 221u8, 0u8, 0u8, 0u8,
+ 251u8, 0u8, 0u8, 0u8, 10u8, 1u8, 0u8, 0u8, 25u8, 1u8, 0u8, 0u8,
+ 18u8, 0u8, 0u8, 0u8, 0u8, 2u8, 0u8, 15u8, 17u8, 0u8, 0u8, 68u8,
+ 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 2u8, 0u8, 17u8, 17u8, 0u8,
+ 0u8, 191u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 2u8, 0u8, 15u8,
+ 17u8, 0u8, 0u8, 191u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 2u8,
+ 0u8, 15u8, 16u8, 0u8, 0u8, 191u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
+ 0u8, 0u8, 2u8, 0u8, 16u8, 17u8, 0u8, 0u8, 221u8, 0u8, 0u8, 0u8,
+ 0u8, 0u8, 0u8, 0u8, 0u8, 2u8, 0u8, 15u8, 17u8, 0u8, 0u8, 221u8,
+ 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 2u8, 0u8, 15u8, 15u8, 0u8,
+ 0u8, 221u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 4u8, 0u8, 0u8,
+ 0u8, 0u8, 0u8, 0u8, 0u8, 35u8, 0u8, 0u8, 0u8, 35u8, 0u8, 0u8, 0u8,
+ 35u8, 0u8, 0u8, 0u8, 35u8, 0u8, 0u8, 0u8, 35u8, 0u8, 0u8, 0u8, 9u8,
+ 0u8, 0u8, 0u8, 18u8, 0u8, 0u8, 0u8, 18u8, 0u8, 0u8, 0u8, 0u8, 0u8,
+ 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 35u8, 0u8, 0u8, 0u8, 35u8, 0u8, 0u8,
+ 0u8,
+ ]
+ } else {
+ &[
+ 114u8, 117u8, 115u8, 116u8, 45u8, 114u8, 101u8, 103u8, 101u8,
+ 120u8, 45u8, 97u8, 117u8, 116u8, 111u8, 109u8, 97u8, 116u8, 97u8,
+ 45u8, 100u8, 102u8, 97u8, 45u8, 115u8, 112u8, 97u8, 114u8, 115u8,
+ 101u8, 0u8, 0u8, 0u8, 0u8, 254u8, 255u8, 0u8, 0u8, 0u8, 2u8, 0u8,
+ 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 14u8, 0u8, 0u8, 0u8, 1u8, 0u8, 0u8,
+ 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
+ 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
+ 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
+ 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
+ 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 2u8,
+ 2u8, 2u8, 3u8, 4u8, 4u8, 5u8, 6u8, 7u8, 7u8, 7u8, 7u8, 7u8, 7u8,
+ 7u8, 7u8, 7u8, 7u8, 7u8, 7u8, 7u8, 7u8, 7u8, 7u8, 7u8, 7u8, 7u8,
+ 7u8, 7u8, 7u8, 7u8, 8u8, 9u8, 9u8, 9u8, 10u8, 11u8, 11u8, 12u8,
+ 13u8, 14u8, 14u8, 14u8, 14u8, 14u8, 14u8, 14u8, 14u8, 14u8, 14u8,
+ 14u8, 14u8, 14u8, 14u8, 14u8, 14u8, 14u8, 14u8, 14u8, 14u8, 14u8,
+ 14u8, 15u8, 15u8, 15u8, 15u8, 15u8, 15u8, 15u8, 15u8, 15u8, 15u8,
+ 15u8, 15u8, 15u8, 15u8, 15u8, 15u8, 16u8, 16u8, 16u8, 16u8, 16u8,
+ 16u8, 16u8, 16u8, 16u8, 16u8, 16u8, 16u8, 16u8, 16u8, 16u8, 16u8,
+ 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8,
+ 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8,
+ 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 18u8,
+ 18u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8,
+ 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8,
+ 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 20u8, 21u8,
+ 21u8, 21u8, 21u8, 21u8, 21u8, 21u8, 21u8, 21u8, 21u8, 21u8, 21u8,
+ 22u8, 23u8, 23u8, 24u8, 25u8, 25u8, 25u8, 26u8, 27u8, 27u8, 27u8,
+ 27u8, 27u8, 27u8, 27u8, 27u8, 27u8, 27u8, 27u8, 0u8, 0u8, 1u8,
+ 40u8, 1u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 0u8, 0u8,
+ 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 128u8, 0u8, 0u8, 0u8, 0u8, 0u8,
+ 0u8, 1u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 5u8, 0u8, 5u8,
+ 5u8, 6u8, 6u8, 12u8, 12u8, 13u8, 13u8, 0u8, 0u8, 83u8, 0u8, 0u8,
+ 0u8, 68u8, 0u8, 0u8, 0u8, 83u8, 0u8, 0u8, 0u8, 68u8, 0u8, 0u8, 0u8,
+ 0u8, 0u8, 0u8, 0u8, 0u8, 2u8, 0u8, 0u8, 27u8, 0u8, 0u8, 18u8, 0u8,
+ 0u8, 0u8, 18u8, 0u8, 0u8, 0u8, 0u8, 3u8, 0u8, 6u8, 6u8, 13u8, 13u8,
+ 0u8, 0u8, 104u8, 0u8, 0u8, 0u8, 104u8, 0u8, 0u8, 0u8, 0u8, 0u8,
+ 0u8, 0u8, 0u8, 14u8, 0u8, 0u8, 0u8, 2u8, 2u8, 4u8, 7u8, 9u8, 9u8,
+ 11u8, 14u8, 19u8, 19u8, 20u8, 20u8, 21u8, 21u8, 22u8, 22u8, 23u8,
+ 23u8, 24u8, 24u8, 25u8, 25u8, 26u8, 26u8, 0u8, 0u8, 68u8, 0u8, 0u8,
+ 0u8, 68u8, 0u8, 0u8, 0u8, 68u8, 0u8, 0u8, 0u8, 68u8, 0u8, 0u8, 0u8,
+ 68u8, 0u8, 0u8, 0u8, 191u8, 0u8, 0u8, 0u8, 206u8, 0u8, 0u8, 0u8,
+ 221u8, 0u8, 0u8, 0u8, 236u8, 0u8, 0u8, 0u8, 221u8, 0u8, 0u8, 0u8,
+ 251u8, 0u8, 0u8, 0u8, 10u8, 1u8, 0u8, 0u8, 25u8, 1u8, 0u8, 0u8,
+ 18u8, 0u8, 0u8, 0u8, 0u8, 2u8, 0u8, 15u8, 17u8, 0u8, 0u8, 68u8,
+ 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 2u8, 0u8, 17u8, 17u8, 0u8,
+ 0u8, 191u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 2u8, 0u8, 15u8,
+ 17u8, 0u8, 0u8, 191u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 2u8,
+ 0u8, 15u8, 16u8, 0u8, 0u8, 191u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
+ 0u8, 0u8, 2u8, 0u8, 16u8, 17u8, 0u8, 0u8, 221u8, 0u8, 0u8, 0u8,
+ 0u8, 0u8, 0u8, 0u8, 0u8, 2u8, 0u8, 15u8, 17u8, 0u8, 0u8, 221u8,
+ 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 2u8, 0u8, 15u8, 15u8, 0u8,
+ 0u8, 221u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
+ 4u8, 0u8, 0u8, 0u8, 0u8, 35u8, 0u8, 0u8, 0u8, 35u8, 0u8, 0u8, 0u8,
+ 35u8, 0u8, 0u8, 0u8, 35u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 35u8, 0u8,
+ 0u8, 0u8, 9u8, 0u8, 0u8, 0u8, 18u8, 0u8, 0u8, 0u8, 18u8, 0u8, 0u8,
+ 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 35u8, 0u8, 0u8, 0u8,
+ 35u8,
+ ]
+ },
+ )
+ },
+ pattern: unsafe {
+ ::icu_list::provider::ListJoinerPattern::from_parts_unchecked(" e ", 3u8)
+ },
+ }),
+ },
+ ::icu_list::provider::ConditionalListJoinerPattern {
+ default: unsafe {
+ ::icu_list::provider::ListJoinerPattern::from_parts_unchecked(", ", 2u8)
+ },
+ special_case: None,
+ },
+ ::icu_list::provider::ConditionalListJoinerPattern {
+ default: unsafe {
+ ::icu_list::provider::ListJoinerPattern::from_parts_unchecked(", ", 2u8)
+ },
+ special_case: None,
+ },
+ ::icu_list::provider::ConditionalListJoinerPattern {
+ default: unsafe {
+ ::icu_list::provider::ListJoinerPattern::from_parts_unchecked(" y ", 3u8)
+ },
+ special_case: Some(::icu_list::provider::SpecialCasePattern {
+ condition: unsafe {
+ ::icu_list::provider::SerdeDFA::from_dfa_bytes_unchecked(
+ if cfg!(target_endian = "little") {
+ &[
+ 114u8, 117u8, 115u8, 116u8, 45u8, 114u8, 101u8, 103u8, 101u8,
+ 120u8, 45u8, 97u8, 117u8, 116u8, 111u8, 109u8, 97u8, 116u8, 97u8,
+ 45u8, 100u8, 102u8, 97u8, 45u8, 115u8, 112u8, 97u8, 114u8, 115u8,
+ 101u8, 0u8, 0u8, 255u8, 254u8, 0u8, 0u8, 2u8, 0u8, 0u8, 0u8, 0u8,
+ 0u8, 0u8, 0u8, 14u8, 0u8, 0u8, 0u8, 1u8, 0u8, 0u8, 0u8, 0u8, 0u8,
+ 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
+ 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
+ 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
+ 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
+ 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 2u8,
+ 2u8, 2u8, 3u8, 4u8, 4u8, 5u8, 6u8, 7u8, 7u8, 7u8, 7u8, 7u8, 7u8,
+ 7u8, 7u8, 7u8, 7u8, 7u8, 7u8, 7u8, 7u8, 7u8, 7u8, 7u8, 7u8, 7u8,
+ 7u8, 7u8, 7u8, 7u8, 8u8, 9u8, 9u8, 9u8, 10u8, 11u8, 11u8, 12u8,
+ 13u8, 14u8, 14u8, 14u8, 14u8, 14u8, 14u8, 14u8, 14u8, 14u8, 14u8,
+ 14u8, 14u8, 14u8, 14u8, 14u8, 14u8, 14u8, 14u8, 14u8, 14u8, 14u8,
+ 14u8, 15u8, 15u8, 15u8, 15u8, 15u8, 15u8, 15u8, 15u8, 15u8, 15u8,
+ 15u8, 15u8, 15u8, 15u8, 15u8, 15u8, 16u8, 16u8, 16u8, 16u8, 16u8,
+ 16u8, 16u8, 16u8, 16u8, 16u8, 16u8, 16u8, 16u8, 16u8, 16u8, 16u8,
+ 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8,
+ 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8,
+ 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 18u8,
+ 18u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8,
+ 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8,
+ 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 20u8, 21u8,
+ 21u8, 21u8, 21u8, 21u8, 21u8, 21u8, 21u8, 21u8, 21u8, 21u8, 21u8,
+ 22u8, 23u8, 23u8, 24u8, 25u8, 25u8, 25u8, 26u8, 27u8, 27u8, 27u8,
+ 27u8, 27u8, 27u8, 27u8, 27u8, 27u8, 27u8, 27u8, 40u8, 1u8, 0u8,
+ 0u8, 1u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 0u8, 0u8,
+ 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 128u8, 0u8, 0u8, 0u8, 0u8, 0u8,
+ 0u8, 1u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 5u8, 0u8, 5u8,
+ 5u8, 6u8, 6u8, 12u8, 12u8, 13u8, 13u8, 0u8, 0u8, 83u8, 0u8, 0u8,
+ 0u8, 68u8, 0u8, 0u8, 0u8, 83u8, 0u8, 0u8, 0u8, 68u8, 0u8, 0u8, 0u8,
+ 0u8, 0u8, 0u8, 0u8, 0u8, 2u8, 0u8, 0u8, 27u8, 0u8, 0u8, 18u8, 0u8,
+ 0u8, 0u8, 18u8, 0u8, 0u8, 0u8, 0u8, 3u8, 0u8, 6u8, 6u8, 13u8, 13u8,
+ 0u8, 0u8, 104u8, 0u8, 0u8, 0u8, 104u8, 0u8, 0u8, 0u8, 0u8, 0u8,
+ 0u8, 0u8, 0u8, 14u8, 0u8, 0u8, 0u8, 2u8, 2u8, 4u8, 7u8, 9u8, 9u8,
+ 11u8, 14u8, 19u8, 19u8, 20u8, 20u8, 21u8, 21u8, 22u8, 22u8, 23u8,
+ 23u8, 24u8, 24u8, 25u8, 25u8, 26u8, 26u8, 0u8, 0u8, 68u8, 0u8, 0u8,
+ 0u8, 68u8, 0u8, 0u8, 0u8, 68u8, 0u8, 0u8, 0u8, 68u8, 0u8, 0u8, 0u8,
+ 68u8, 0u8, 0u8, 0u8, 191u8, 0u8, 0u8, 0u8, 206u8, 0u8, 0u8, 0u8,
+ 221u8, 0u8, 0u8, 0u8, 236u8, 0u8, 0u8, 0u8, 221u8, 0u8, 0u8, 0u8,
+ 251u8, 0u8, 0u8, 0u8, 10u8, 1u8, 0u8, 0u8, 25u8, 1u8, 0u8, 0u8,
+ 18u8, 0u8, 0u8, 0u8, 0u8, 2u8, 0u8, 15u8, 17u8, 0u8, 0u8, 68u8,
+ 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 2u8, 0u8, 17u8, 17u8, 0u8,
+ 0u8, 191u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 2u8, 0u8, 15u8,
+ 17u8, 0u8, 0u8, 191u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 2u8,
+ 0u8, 15u8, 16u8, 0u8, 0u8, 191u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
+ 0u8, 0u8, 2u8, 0u8, 16u8, 17u8, 0u8, 0u8, 221u8, 0u8, 0u8, 0u8,
+ 0u8, 0u8, 0u8, 0u8, 0u8, 2u8, 0u8, 15u8, 17u8, 0u8, 0u8, 221u8,
+ 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 2u8, 0u8, 15u8, 15u8, 0u8,
+ 0u8, 221u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 4u8, 0u8, 0u8,
+ 0u8, 0u8, 0u8, 0u8, 0u8, 35u8, 0u8, 0u8, 0u8, 35u8, 0u8, 0u8, 0u8,
+ 35u8, 0u8, 0u8, 0u8, 35u8, 0u8, 0u8, 0u8, 35u8, 0u8, 0u8, 0u8, 9u8,
+ 0u8, 0u8, 0u8, 18u8, 0u8, 0u8, 0u8, 18u8, 0u8, 0u8, 0u8, 0u8, 0u8,
+ 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 35u8, 0u8, 0u8, 0u8, 35u8, 0u8, 0u8,
+ 0u8,
+ ]
+ } else {
+ &[
+ 114u8, 117u8, 115u8, 116u8, 45u8, 114u8, 101u8, 103u8, 101u8,
+ 120u8, 45u8, 97u8, 117u8, 116u8, 111u8, 109u8, 97u8, 116u8, 97u8,
+ 45u8, 100u8, 102u8, 97u8, 45u8, 115u8, 112u8, 97u8, 114u8, 115u8,
+ 101u8, 0u8, 0u8, 0u8, 0u8, 254u8, 255u8, 0u8, 0u8, 0u8, 2u8, 0u8,
+ 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 14u8, 0u8, 0u8, 0u8, 1u8, 0u8, 0u8,
+ 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
+ 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
+ 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
+ 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
+ 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 2u8,
+ 2u8, 2u8, 3u8, 4u8, 4u8, 5u8, 6u8, 7u8, 7u8, 7u8, 7u8, 7u8, 7u8,
+ 7u8, 7u8, 7u8, 7u8, 7u8, 7u8, 7u8, 7u8, 7u8, 7u8, 7u8, 7u8, 7u8,
+ 7u8, 7u8, 7u8, 7u8, 8u8, 9u8, 9u8, 9u8, 10u8, 11u8, 11u8, 12u8,
+ 13u8, 14u8, 14u8, 14u8, 14u8, 14u8, 14u8, 14u8, 14u8, 14u8, 14u8,
+ 14u8, 14u8, 14u8, 14u8, 14u8, 14u8, 14u8, 14u8, 14u8, 14u8, 14u8,
+ 14u8, 15u8, 15u8, 15u8, 15u8, 15u8, 15u8, 15u8, 15u8, 15u8, 15u8,
+ 15u8, 15u8, 15u8, 15u8, 15u8, 15u8, 16u8, 16u8, 16u8, 16u8, 16u8,
+ 16u8, 16u8, 16u8, 16u8, 16u8, 16u8, 16u8, 16u8, 16u8, 16u8, 16u8,
+ 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8,
+ 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8,
+ 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 18u8,
+ 18u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8,
+ 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8,
+ 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 20u8, 21u8,
+ 21u8, 21u8, 21u8, 21u8, 21u8, 21u8, 21u8, 21u8, 21u8, 21u8, 21u8,
+ 22u8, 23u8, 23u8, 24u8, 25u8, 25u8, 25u8, 26u8, 27u8, 27u8, 27u8,
+ 27u8, 27u8, 27u8, 27u8, 27u8, 27u8, 27u8, 27u8, 0u8, 0u8, 1u8,
+ 40u8, 1u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 0u8, 0u8,
+ 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 128u8, 0u8, 0u8, 0u8, 0u8, 0u8,
+ 0u8, 1u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 5u8, 0u8, 5u8,
+ 5u8, 6u8, 6u8, 12u8, 12u8, 13u8, 13u8, 0u8, 0u8, 83u8, 0u8, 0u8,
+ 0u8, 68u8, 0u8, 0u8, 0u8, 83u8, 0u8, 0u8, 0u8, 68u8, 0u8, 0u8, 0u8,
+ 0u8, 0u8, 0u8, 0u8, 0u8, 2u8, 0u8, 0u8, 27u8, 0u8, 0u8, 18u8, 0u8,
+ 0u8, 0u8, 18u8, 0u8, 0u8, 0u8, 0u8, 3u8, 0u8, 6u8, 6u8, 13u8, 13u8,
+ 0u8, 0u8, 104u8, 0u8, 0u8, 0u8, 104u8, 0u8, 0u8, 0u8, 0u8, 0u8,
+ 0u8, 0u8, 0u8, 14u8, 0u8, 0u8, 0u8, 2u8, 2u8, 4u8, 7u8, 9u8, 9u8,
+ 11u8, 14u8, 19u8, 19u8, 20u8, 20u8, 21u8, 21u8, 22u8, 22u8, 23u8,
+ 23u8, 24u8, 24u8, 25u8, 25u8, 26u8, 26u8, 0u8, 0u8, 68u8, 0u8, 0u8,
+ 0u8, 68u8, 0u8, 0u8, 0u8, 68u8, 0u8, 0u8, 0u8, 68u8, 0u8, 0u8, 0u8,
+ 68u8, 0u8, 0u8, 0u8, 191u8, 0u8, 0u8, 0u8, 206u8, 0u8, 0u8, 0u8,
+ 221u8, 0u8, 0u8, 0u8, 236u8, 0u8, 0u8, 0u8, 221u8, 0u8, 0u8, 0u8,
+ 251u8, 0u8, 0u8, 0u8, 10u8, 1u8, 0u8, 0u8, 25u8, 1u8, 0u8, 0u8,
+ 18u8, 0u8, 0u8, 0u8, 0u8, 2u8, 0u8, 15u8, 17u8, 0u8, 0u8, 68u8,
+ 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 2u8, 0u8, 17u8, 17u8, 0u8,
+ 0u8, 191u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 2u8, 0u8, 15u8,
+ 17u8, 0u8, 0u8, 191u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 2u8,
+ 0u8, 15u8, 16u8, 0u8, 0u8, 191u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
+ 0u8, 0u8, 2u8, 0u8, 16u8, 17u8, 0u8, 0u8, 221u8, 0u8, 0u8, 0u8,
+ 0u8, 0u8, 0u8, 0u8, 0u8, 2u8, 0u8, 15u8, 17u8, 0u8, 0u8, 221u8,
+ 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 2u8, 0u8, 15u8, 15u8, 0u8,
+ 0u8, 221u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
+ 4u8, 0u8, 0u8, 0u8, 0u8, 35u8, 0u8, 0u8, 0u8, 35u8, 0u8, 0u8, 0u8,
+ 35u8, 0u8, 0u8, 0u8, 35u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 35u8, 0u8,
+ 0u8, 0u8, 9u8, 0u8, 0u8, 0u8, 18u8, 0u8, 0u8, 0u8, 18u8, 0u8, 0u8,
+ 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 35u8, 0u8, 0u8, 0u8,
+ 35u8,
+ ]
+ },
+ )
+ },
+ pattern: unsafe {
+ ::icu_list::provider::ListJoinerPattern::from_parts_unchecked(" e ", 3u8)
+ },
+ }),
+ },
+ ::icu_list::provider::ConditionalListJoinerPattern {
+ default: unsafe {
+ ::icu_list::provider::ListJoinerPattern::from_parts_unchecked(" y ", 3u8)
+ },
+ special_case: Some(::icu_list::provider::SpecialCasePattern {
+ condition: unsafe {
+ ::icu_list::provider::SerdeDFA::from_dfa_bytes_unchecked(
+ if cfg!(target_endian = "little") {
+ &[
+ 114u8, 117u8, 115u8, 116u8, 45u8, 114u8, 101u8, 103u8, 101u8,
+ 120u8, 45u8, 97u8, 117u8, 116u8, 111u8, 109u8, 97u8, 116u8, 97u8,
+ 45u8, 100u8, 102u8, 97u8, 45u8, 115u8, 112u8, 97u8, 114u8, 115u8,
+ 101u8, 0u8, 0u8, 255u8, 254u8, 0u8, 0u8, 2u8, 0u8, 0u8, 0u8, 0u8,
+ 0u8, 0u8, 0u8, 14u8, 0u8, 0u8, 0u8, 1u8, 0u8, 0u8, 0u8, 0u8, 0u8,
+ 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
+ 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
+ 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
+ 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
+ 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 2u8,
+ 2u8, 2u8, 3u8, 4u8, 4u8, 5u8, 6u8, 7u8, 7u8, 7u8, 7u8, 7u8, 7u8,
+ 7u8, 7u8, 7u8, 7u8, 7u8, 7u8, 7u8, 7u8, 7u8, 7u8, 7u8, 7u8, 7u8,
+ 7u8, 7u8, 7u8, 7u8, 8u8, 9u8, 9u8, 9u8, 10u8, 11u8, 11u8, 12u8,
+ 13u8, 14u8, 14u8, 14u8, 14u8, 14u8, 14u8, 14u8, 14u8, 14u8, 14u8,
+ 14u8, 14u8, 14u8, 14u8, 14u8, 14u8, 14u8, 14u8, 14u8, 14u8, 14u8,
+ 14u8, 15u8, 15u8, 15u8, 15u8, 15u8, 15u8, 15u8, 15u8, 15u8, 15u8,
+ 15u8, 15u8, 15u8, 15u8, 15u8, 15u8, 16u8, 16u8, 16u8, 16u8, 16u8,
+ 16u8, 16u8, 16u8, 16u8, 16u8, 16u8, 16u8, 16u8, 16u8, 16u8, 16u8,
+ 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8,
+ 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8,
+ 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 18u8,
+ 18u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8,
+ 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8,
+ 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 20u8, 21u8,
+ 21u8, 21u8, 21u8, 21u8, 21u8, 21u8, 21u8, 21u8, 21u8, 21u8, 21u8,
+ 22u8, 23u8, 23u8, 24u8, 25u8, 25u8, 25u8, 26u8, 27u8, 27u8, 27u8,
+ 27u8, 27u8, 27u8, 27u8, 27u8, 27u8, 27u8, 27u8, 40u8, 1u8, 0u8,
+ 0u8, 1u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 0u8, 0u8,
+ 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 128u8, 0u8, 0u8, 0u8, 0u8, 0u8,
+ 0u8, 1u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 5u8, 0u8, 5u8,
+ 5u8, 6u8, 6u8, 12u8, 12u8, 13u8, 13u8, 0u8, 0u8, 83u8, 0u8, 0u8,
+ 0u8, 68u8, 0u8, 0u8, 0u8, 83u8, 0u8, 0u8, 0u8, 68u8, 0u8, 0u8, 0u8,
+ 0u8, 0u8, 0u8, 0u8, 0u8, 2u8, 0u8, 0u8, 27u8, 0u8, 0u8, 18u8, 0u8,
+ 0u8, 0u8, 18u8, 0u8, 0u8, 0u8, 0u8, 3u8, 0u8, 6u8, 6u8, 13u8, 13u8,
+ 0u8, 0u8, 104u8, 0u8, 0u8, 0u8, 104u8, 0u8, 0u8, 0u8, 0u8, 0u8,
+ 0u8, 0u8, 0u8, 14u8, 0u8, 0u8, 0u8, 2u8, 2u8, 4u8, 7u8, 9u8, 9u8,
+ 11u8, 14u8, 19u8, 19u8, 20u8, 20u8, 21u8, 21u8, 22u8, 22u8, 23u8,
+ 23u8, 24u8, 24u8, 25u8, 25u8, 26u8, 26u8, 0u8, 0u8, 68u8, 0u8, 0u8,
+ 0u8, 68u8, 0u8, 0u8, 0u8, 68u8, 0u8, 0u8, 0u8, 68u8, 0u8, 0u8, 0u8,
+ 68u8, 0u8, 0u8, 0u8, 191u8, 0u8, 0u8, 0u8, 206u8, 0u8, 0u8, 0u8,
+ 221u8, 0u8, 0u8, 0u8, 236u8, 0u8, 0u8, 0u8, 221u8, 0u8, 0u8, 0u8,
+ 251u8, 0u8, 0u8, 0u8, 10u8, 1u8, 0u8, 0u8, 25u8, 1u8, 0u8, 0u8,
+ 18u8, 0u8, 0u8, 0u8, 0u8, 2u8, 0u8, 15u8, 17u8, 0u8, 0u8, 68u8,
+ 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 2u8, 0u8, 17u8, 17u8, 0u8,
+ 0u8, 191u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 2u8, 0u8, 15u8,
+ 17u8, 0u8, 0u8, 191u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 2u8,
+ 0u8, 15u8, 16u8, 0u8, 0u8, 191u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
+ 0u8, 0u8, 2u8, 0u8, 16u8, 17u8, 0u8, 0u8, 221u8, 0u8, 0u8, 0u8,
+ 0u8, 0u8, 0u8, 0u8, 0u8, 2u8, 0u8, 15u8, 17u8, 0u8, 0u8, 221u8,
+ 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 2u8, 0u8, 15u8, 15u8, 0u8,
+ 0u8, 221u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 4u8, 0u8, 0u8,
+ 0u8, 0u8, 0u8, 0u8, 0u8, 35u8, 0u8, 0u8, 0u8, 35u8, 0u8, 0u8, 0u8,
+ 35u8, 0u8, 0u8, 0u8, 35u8, 0u8, 0u8, 0u8, 35u8, 0u8, 0u8, 0u8, 9u8,
+ 0u8, 0u8, 0u8, 18u8, 0u8, 0u8, 0u8, 18u8, 0u8, 0u8, 0u8, 0u8, 0u8,
+ 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 35u8, 0u8, 0u8, 0u8, 35u8, 0u8, 0u8,
+ 0u8,
+ ]
+ } else {
+ &[
+ 114u8, 117u8, 115u8, 116u8, 45u8, 114u8, 101u8, 103u8, 101u8,
+ 120u8, 45u8, 97u8, 117u8, 116u8, 111u8, 109u8, 97u8, 116u8, 97u8,
+ 45u8, 100u8, 102u8, 97u8, 45u8, 115u8, 112u8, 97u8, 114u8, 115u8,
+ 101u8, 0u8, 0u8, 0u8, 0u8, 254u8, 255u8, 0u8, 0u8, 0u8, 2u8, 0u8,
+ 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 14u8, 0u8, 0u8, 0u8, 1u8, 0u8, 0u8,
+ 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
+ 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
+ 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
+ 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
+ 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 2u8,
+ 2u8, 2u8, 3u8, 4u8, 4u8, 5u8, 6u8, 7u8, 7u8, 7u8, 7u8, 7u8, 7u8,
+ 7u8, 7u8, 7u8, 7u8, 7u8, 7u8, 7u8, 7u8, 7u8, 7u8, 7u8, 7u8, 7u8,
+ 7u8, 7u8, 7u8, 7u8, 8u8, 9u8, 9u8, 9u8, 10u8, 11u8, 11u8, 12u8,
+ 13u8, 14u8, 14u8, 14u8, 14u8, 14u8, 14u8, 14u8, 14u8, 14u8, 14u8,
+ 14u8, 14u8, 14u8, 14u8, 14u8, 14u8, 14u8, 14u8, 14u8, 14u8, 14u8,
+ 14u8, 15u8, 15u8, 15u8, 15u8, 15u8, 15u8, 15u8, 15u8, 15u8, 15u8,
+ 15u8, 15u8, 15u8, 15u8, 15u8, 15u8, 16u8, 16u8, 16u8, 16u8, 16u8,
+ 16u8, 16u8, 16u8, 16u8, 16u8, 16u8, 16u8, 16u8, 16u8, 16u8, 16u8,
+ 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8,
+ 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8,
+ 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 18u8,
+ 18u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8,
+ 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8,
+ 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 20u8, 21u8,
+ 21u8, 21u8, 21u8, 21u8, 21u8, 21u8, 21u8, 21u8, 21u8, 21u8, 21u8,
+ 22u8, 23u8, 23u8, 24u8, 25u8, 25u8, 25u8, 26u8, 27u8, 27u8, 27u8,
+ 27u8, 27u8, 27u8, 27u8, 27u8, 27u8, 27u8, 27u8, 0u8, 0u8, 1u8,
+ 40u8, 1u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 0u8, 0u8,
+ 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 128u8, 0u8, 0u8, 0u8, 0u8, 0u8,
+ 0u8, 1u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 5u8, 0u8, 5u8,
+ 5u8, 6u8, 6u8, 12u8, 12u8, 13u8, 13u8, 0u8, 0u8, 83u8, 0u8, 0u8,
+ 0u8, 68u8, 0u8, 0u8, 0u8, 83u8, 0u8, 0u8, 0u8, 68u8, 0u8, 0u8, 0u8,
+ 0u8, 0u8, 0u8, 0u8, 0u8, 2u8, 0u8, 0u8, 27u8, 0u8, 0u8, 18u8, 0u8,
+ 0u8, 0u8, 18u8, 0u8, 0u8, 0u8, 0u8, 3u8, 0u8, 6u8, 6u8, 13u8, 13u8,
+ 0u8, 0u8, 104u8, 0u8, 0u8, 0u8, 104u8, 0u8, 0u8, 0u8, 0u8, 0u8,
+ 0u8, 0u8, 0u8, 14u8, 0u8, 0u8, 0u8, 2u8, 2u8, 4u8, 7u8, 9u8, 9u8,
+ 11u8, 14u8, 19u8, 19u8, 20u8, 20u8, 21u8, 21u8, 22u8, 22u8, 23u8,
+ 23u8, 24u8, 24u8, 25u8, 25u8, 26u8, 26u8, 0u8, 0u8, 68u8, 0u8, 0u8,
+ 0u8, 68u8, 0u8, 0u8, 0u8, 68u8, 0u8, 0u8, 0u8, 68u8, 0u8, 0u8, 0u8,
+ 68u8, 0u8, 0u8, 0u8, 191u8, 0u8, 0u8, 0u8, 206u8, 0u8, 0u8, 0u8,
+ 221u8, 0u8, 0u8, 0u8, 236u8, 0u8, 0u8, 0u8, 221u8, 0u8, 0u8, 0u8,
+ 251u8, 0u8, 0u8, 0u8, 10u8, 1u8, 0u8, 0u8, 25u8, 1u8, 0u8, 0u8,
+ 18u8, 0u8, 0u8, 0u8, 0u8, 2u8, 0u8, 15u8, 17u8, 0u8, 0u8, 68u8,
+ 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 2u8, 0u8, 17u8, 17u8, 0u8,
+ 0u8, 191u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 2u8, 0u8, 15u8,
+ 17u8, 0u8, 0u8, 191u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 2u8,
+ 0u8, 15u8, 16u8, 0u8, 0u8, 191u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
+ 0u8, 0u8, 2u8, 0u8, 16u8, 17u8, 0u8, 0u8, 221u8, 0u8, 0u8, 0u8,
+ 0u8, 0u8, 0u8, 0u8, 0u8, 2u8, 0u8, 15u8, 17u8, 0u8, 0u8, 221u8,
+ 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 2u8, 0u8, 15u8, 15u8, 0u8,
+ 0u8, 221u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
+ 4u8, 0u8, 0u8, 0u8, 0u8, 35u8, 0u8, 0u8, 0u8, 35u8, 0u8, 0u8, 0u8,
+ 35u8, 0u8, 0u8, 0u8, 35u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 35u8, 0u8,
+ 0u8, 0u8, 9u8, 0u8, 0u8, 0u8, 18u8, 0u8, 0u8, 0u8, 18u8, 0u8, 0u8,
+ 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 35u8, 0u8, 0u8, 0u8,
+ 35u8,
+ ]
+ },
+ )
+ },
+ pattern: unsafe {
+ ::icu_list::provider::ListJoinerPattern::from_parts_unchecked(" e ", 3u8)
+ },
+ }),
+ },
+ ::icu_list::provider::ConditionalListJoinerPattern {
+ default: unsafe {
+ ::icu_list::provider::ListJoinerPattern::from_parts_unchecked(", ", 2u8)
+ },
+ special_case: None,
+ },
+ ::icu_list::provider::ConditionalListJoinerPattern {
+ default: unsafe {
+ ::icu_list::provider::ListJoinerPattern::from_parts_unchecked(", ", 2u8)
+ },
+ special_case: None,
+ },
+ ::icu_list::provider::ConditionalListJoinerPattern {
+ default: unsafe {
+ ::icu_list::provider::ListJoinerPattern::from_parts_unchecked(" y ", 3u8)
+ },
+ special_case: Some(::icu_list::provider::SpecialCasePattern {
+ condition: unsafe {
+ ::icu_list::provider::SerdeDFA::from_dfa_bytes_unchecked(
+ if cfg!(target_endian = "little") {
+ &[
+ 114u8, 117u8, 115u8, 116u8, 45u8, 114u8, 101u8, 103u8, 101u8,
+ 120u8, 45u8, 97u8, 117u8, 116u8, 111u8, 109u8, 97u8, 116u8, 97u8,
+ 45u8, 100u8, 102u8, 97u8, 45u8, 115u8, 112u8, 97u8, 114u8, 115u8,
+ 101u8, 0u8, 0u8, 255u8, 254u8, 0u8, 0u8, 2u8, 0u8, 0u8, 0u8, 0u8,
+ 0u8, 0u8, 0u8, 14u8, 0u8, 0u8, 0u8, 1u8, 0u8, 0u8, 0u8, 0u8, 0u8,
+ 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
+ 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
+ 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
+ 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
+ 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 2u8,
+ 2u8, 2u8, 3u8, 4u8, 4u8, 5u8, 6u8, 7u8, 7u8, 7u8, 7u8, 7u8, 7u8,
+ 7u8, 7u8, 7u8, 7u8, 7u8, 7u8, 7u8, 7u8, 7u8, 7u8, 7u8, 7u8, 7u8,
+ 7u8, 7u8, 7u8, 7u8, 8u8, 9u8, 9u8, 9u8, 10u8, 11u8, 11u8, 12u8,
+ 13u8, 14u8, 14u8, 14u8, 14u8, 14u8, 14u8, 14u8, 14u8, 14u8, 14u8,
+ 14u8, 14u8, 14u8, 14u8, 14u8, 14u8, 14u8, 14u8, 14u8, 14u8, 14u8,
+ 14u8, 15u8, 15u8, 15u8, 15u8, 15u8, 15u8, 15u8, 15u8, 15u8, 15u8,
+ 15u8, 15u8, 15u8, 15u8, 15u8, 15u8, 16u8, 16u8, 16u8, 16u8, 16u8,
+ 16u8, 16u8, 16u8, 16u8, 16u8, 16u8, 16u8, 16u8, 16u8, 16u8, 16u8,
+ 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8,
+ 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8,
+ 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 18u8,
+ 18u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8,
+ 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8,
+ 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 20u8, 21u8,
+ 21u8, 21u8, 21u8, 21u8, 21u8, 21u8, 21u8, 21u8, 21u8, 21u8, 21u8,
+ 22u8, 23u8, 23u8, 24u8, 25u8, 25u8, 25u8, 26u8, 27u8, 27u8, 27u8,
+ 27u8, 27u8, 27u8, 27u8, 27u8, 27u8, 27u8, 27u8, 40u8, 1u8, 0u8,
+ 0u8, 1u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 0u8, 0u8,
+ 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 128u8, 0u8, 0u8, 0u8, 0u8, 0u8,
+ 0u8, 1u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 5u8, 0u8, 5u8,
+ 5u8, 6u8, 6u8, 12u8, 12u8, 13u8, 13u8, 0u8, 0u8, 83u8, 0u8, 0u8,
+ 0u8, 68u8, 0u8, 0u8, 0u8, 83u8, 0u8, 0u8, 0u8, 68u8, 0u8, 0u8, 0u8,
+ 0u8, 0u8, 0u8, 0u8, 0u8, 2u8, 0u8, 0u8, 27u8, 0u8, 0u8, 18u8, 0u8,
+ 0u8, 0u8, 18u8, 0u8, 0u8, 0u8, 0u8, 3u8, 0u8, 6u8, 6u8, 13u8, 13u8,
+ 0u8, 0u8, 104u8, 0u8, 0u8, 0u8, 104u8, 0u8, 0u8, 0u8, 0u8, 0u8,
+ 0u8, 0u8, 0u8, 14u8, 0u8, 0u8, 0u8, 2u8, 2u8, 4u8, 7u8, 9u8, 9u8,
+ 11u8, 14u8, 19u8, 19u8, 20u8, 20u8, 21u8, 21u8, 22u8, 22u8, 23u8,
+ 23u8, 24u8, 24u8, 25u8, 25u8, 26u8, 26u8, 0u8, 0u8, 68u8, 0u8, 0u8,
+ 0u8, 68u8, 0u8, 0u8, 0u8, 68u8, 0u8, 0u8, 0u8, 68u8, 0u8, 0u8, 0u8,
+ 68u8, 0u8, 0u8, 0u8, 191u8, 0u8, 0u8, 0u8, 206u8, 0u8, 0u8, 0u8,
+ 221u8, 0u8, 0u8, 0u8, 236u8, 0u8, 0u8, 0u8, 221u8, 0u8, 0u8, 0u8,
+ 251u8, 0u8, 0u8, 0u8, 10u8, 1u8, 0u8, 0u8, 25u8, 1u8, 0u8, 0u8,
+ 18u8, 0u8, 0u8, 0u8, 0u8, 2u8, 0u8, 15u8, 17u8, 0u8, 0u8, 68u8,
+ 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 2u8, 0u8, 17u8, 17u8, 0u8,
+ 0u8, 191u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 2u8, 0u8, 15u8,
+ 17u8, 0u8, 0u8, 191u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 2u8,
+ 0u8, 15u8, 16u8, 0u8, 0u8, 191u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
+ 0u8, 0u8, 2u8, 0u8, 16u8, 17u8, 0u8, 0u8, 221u8, 0u8, 0u8, 0u8,
+ 0u8, 0u8, 0u8, 0u8, 0u8, 2u8, 0u8, 15u8, 17u8, 0u8, 0u8, 221u8,
+ 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 2u8, 0u8, 15u8, 15u8, 0u8,
+ 0u8, 221u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 4u8, 0u8, 0u8,
+ 0u8, 0u8, 0u8, 0u8, 0u8, 35u8, 0u8, 0u8, 0u8, 35u8, 0u8, 0u8, 0u8,
+ 35u8, 0u8, 0u8, 0u8, 35u8, 0u8, 0u8, 0u8, 35u8, 0u8, 0u8, 0u8, 9u8,
+ 0u8, 0u8, 0u8, 18u8, 0u8, 0u8, 0u8, 18u8, 0u8, 0u8, 0u8, 0u8, 0u8,
+ 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 35u8, 0u8, 0u8, 0u8, 35u8, 0u8, 0u8,
+ 0u8,
+ ]
+ } else {
+ &[
+ 114u8, 117u8, 115u8, 116u8, 45u8, 114u8, 101u8, 103u8, 101u8,
+ 120u8, 45u8, 97u8, 117u8, 116u8, 111u8, 109u8, 97u8, 116u8, 97u8,
+ 45u8, 100u8, 102u8, 97u8, 45u8, 115u8, 112u8, 97u8, 114u8, 115u8,
+ 101u8, 0u8, 0u8, 0u8, 0u8, 254u8, 255u8, 0u8, 0u8, 0u8, 2u8, 0u8,
+ 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 14u8, 0u8, 0u8, 0u8, 1u8, 0u8, 0u8,
+ 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
+ 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
+ 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
+ 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
+ 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 2u8,
+ 2u8, 2u8, 3u8, 4u8, 4u8, 5u8, 6u8, 7u8, 7u8, 7u8, 7u8, 7u8, 7u8,
+ 7u8, 7u8, 7u8, 7u8, 7u8, 7u8, 7u8, 7u8, 7u8, 7u8, 7u8, 7u8, 7u8,
+ 7u8, 7u8, 7u8, 7u8, 8u8, 9u8, 9u8, 9u8, 10u8, 11u8, 11u8, 12u8,
+ 13u8, 14u8, 14u8, 14u8, 14u8, 14u8, 14u8, 14u8, 14u8, 14u8, 14u8,
+ 14u8, 14u8, 14u8, 14u8, 14u8, 14u8, 14u8, 14u8, 14u8, 14u8, 14u8,
+ 14u8, 15u8, 15u8, 15u8, 15u8, 15u8, 15u8, 15u8, 15u8, 15u8, 15u8,
+ 15u8, 15u8, 15u8, 15u8, 15u8, 15u8, 16u8, 16u8, 16u8, 16u8, 16u8,
+ 16u8, 16u8, 16u8, 16u8, 16u8, 16u8, 16u8, 16u8, 16u8, 16u8, 16u8,
+ 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8,
+ 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8,
+ 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 18u8,
+ 18u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8,
+ 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8,
+ 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 20u8, 21u8,
+ 21u8, 21u8, 21u8, 21u8, 21u8, 21u8, 21u8, 21u8, 21u8, 21u8, 21u8,
+ 22u8, 23u8, 23u8, 24u8, 25u8, 25u8, 25u8, 26u8, 27u8, 27u8, 27u8,
+ 27u8, 27u8, 27u8, 27u8, 27u8, 27u8, 27u8, 27u8, 0u8, 0u8, 1u8,
+ 40u8, 1u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 0u8, 0u8,
+ 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 128u8, 0u8, 0u8, 0u8, 0u8, 0u8,
+ 0u8, 1u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 5u8, 0u8, 5u8,
+ 5u8, 6u8, 6u8, 12u8, 12u8, 13u8, 13u8, 0u8, 0u8, 83u8, 0u8, 0u8,
+ 0u8, 68u8, 0u8, 0u8, 0u8, 83u8, 0u8, 0u8, 0u8, 68u8, 0u8, 0u8, 0u8,
+ 0u8, 0u8, 0u8, 0u8, 0u8, 2u8, 0u8, 0u8, 27u8, 0u8, 0u8, 18u8, 0u8,
+ 0u8, 0u8, 18u8, 0u8, 0u8, 0u8, 0u8, 3u8, 0u8, 6u8, 6u8, 13u8, 13u8,
+ 0u8, 0u8, 104u8, 0u8, 0u8, 0u8, 104u8, 0u8, 0u8, 0u8, 0u8, 0u8,
+ 0u8, 0u8, 0u8, 14u8, 0u8, 0u8, 0u8, 2u8, 2u8, 4u8, 7u8, 9u8, 9u8,
+ 11u8, 14u8, 19u8, 19u8, 20u8, 20u8, 21u8, 21u8, 22u8, 22u8, 23u8,
+ 23u8, 24u8, 24u8, 25u8, 25u8, 26u8, 26u8, 0u8, 0u8, 68u8, 0u8, 0u8,
+ 0u8, 68u8, 0u8, 0u8, 0u8, 68u8, 0u8, 0u8, 0u8, 68u8, 0u8, 0u8, 0u8,
+ 68u8, 0u8, 0u8, 0u8, 191u8, 0u8, 0u8, 0u8, 206u8, 0u8, 0u8, 0u8,
+ 221u8, 0u8, 0u8, 0u8, 236u8, 0u8, 0u8, 0u8, 221u8, 0u8, 0u8, 0u8,
+ 251u8, 0u8, 0u8, 0u8, 10u8, 1u8, 0u8, 0u8, 25u8, 1u8, 0u8, 0u8,
+ 18u8, 0u8, 0u8, 0u8, 0u8, 2u8, 0u8, 15u8, 17u8, 0u8, 0u8, 68u8,
+ 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 2u8, 0u8, 17u8, 17u8, 0u8,
+ 0u8, 191u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 2u8, 0u8, 15u8,
+ 17u8, 0u8, 0u8, 191u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 2u8,
+ 0u8, 15u8, 16u8, 0u8, 0u8, 191u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
+ 0u8, 0u8, 2u8, 0u8, 16u8, 17u8, 0u8, 0u8, 221u8, 0u8, 0u8, 0u8,
+ 0u8, 0u8, 0u8, 0u8, 0u8, 2u8, 0u8, 15u8, 17u8, 0u8, 0u8, 221u8,
+ 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 2u8, 0u8, 15u8, 15u8, 0u8,
+ 0u8, 221u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
+ 4u8, 0u8, 0u8, 0u8, 0u8, 35u8, 0u8, 0u8, 0u8, 35u8, 0u8, 0u8, 0u8,
+ 35u8, 0u8, 0u8, 0u8, 35u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 35u8, 0u8,
+ 0u8, 0u8, 9u8, 0u8, 0u8, 0u8, 18u8, 0u8, 0u8, 0u8, 18u8, 0u8, 0u8,
+ 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 35u8, 0u8, 0u8, 0u8,
+ 35u8,
+ ]
+ },
+ )
+ },
+ pattern: unsafe {
+ ::icu_list::provider::ListJoinerPattern::from_parts_unchecked(" e ", 3u8)
+ },
+ }),
+ },
+ ::icu_list::provider::ConditionalListJoinerPattern {
+ default: unsafe {
+ ::icu_list::provider::ListJoinerPattern::from_parts_unchecked(" y ", 3u8)
+ },
+ special_case: Some(::icu_list::provider::SpecialCasePattern {
+ condition: unsafe {
+ ::icu_list::provider::SerdeDFA::from_dfa_bytes_unchecked(
+ if cfg!(target_endian = "little") {
+ &[
+ 114u8, 117u8, 115u8, 116u8, 45u8, 114u8, 101u8, 103u8, 101u8,
+ 120u8, 45u8, 97u8, 117u8, 116u8, 111u8, 109u8, 97u8, 116u8, 97u8,
+ 45u8, 100u8, 102u8, 97u8, 45u8, 115u8, 112u8, 97u8, 114u8, 115u8,
+ 101u8, 0u8, 0u8, 255u8, 254u8, 0u8, 0u8, 2u8, 0u8, 0u8, 0u8, 0u8,
+ 0u8, 0u8, 0u8, 14u8, 0u8, 0u8, 0u8, 1u8, 0u8, 0u8, 0u8, 0u8, 0u8,
+ 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
+ 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
+ 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
+ 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
+ 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 2u8,
+ 2u8, 2u8, 3u8, 4u8, 4u8, 5u8, 6u8, 7u8, 7u8, 7u8, 7u8, 7u8, 7u8,
+ 7u8, 7u8, 7u8, 7u8, 7u8, 7u8, 7u8, 7u8, 7u8, 7u8, 7u8, 7u8, 7u8,
+ 7u8, 7u8, 7u8, 7u8, 8u8, 9u8, 9u8, 9u8, 10u8, 11u8, 11u8, 12u8,
+ 13u8, 14u8, 14u8, 14u8, 14u8, 14u8, 14u8, 14u8, 14u8, 14u8, 14u8,
+ 14u8, 14u8, 14u8, 14u8, 14u8, 14u8, 14u8, 14u8, 14u8, 14u8, 14u8,
+ 14u8, 15u8, 15u8, 15u8, 15u8, 15u8, 15u8, 15u8, 15u8, 15u8, 15u8,
+ 15u8, 15u8, 15u8, 15u8, 15u8, 15u8, 16u8, 16u8, 16u8, 16u8, 16u8,
+ 16u8, 16u8, 16u8, 16u8, 16u8, 16u8, 16u8, 16u8, 16u8, 16u8, 16u8,
+ 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8,
+ 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8,
+ 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 18u8,
+ 18u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8,
+ 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8,
+ 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 20u8, 21u8,
+ 21u8, 21u8, 21u8, 21u8, 21u8, 21u8, 21u8, 21u8, 21u8, 21u8, 21u8,
+ 22u8, 23u8, 23u8, 24u8, 25u8, 25u8, 25u8, 26u8, 27u8, 27u8, 27u8,
+ 27u8, 27u8, 27u8, 27u8, 27u8, 27u8, 27u8, 27u8, 40u8, 1u8, 0u8,
+ 0u8, 1u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 0u8, 0u8,
+ 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 128u8, 0u8, 0u8, 0u8, 0u8, 0u8,
+ 0u8, 1u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 5u8, 0u8, 5u8,
+ 5u8, 6u8, 6u8, 12u8, 12u8, 13u8, 13u8, 0u8, 0u8, 83u8, 0u8, 0u8,
+ 0u8, 68u8, 0u8, 0u8, 0u8, 83u8, 0u8, 0u8, 0u8, 68u8, 0u8, 0u8, 0u8,
+ 0u8, 0u8, 0u8, 0u8, 0u8, 2u8, 0u8, 0u8, 27u8, 0u8, 0u8, 18u8, 0u8,
+ 0u8, 0u8, 18u8, 0u8, 0u8, 0u8, 0u8, 3u8, 0u8, 6u8, 6u8, 13u8, 13u8,
+ 0u8, 0u8, 104u8, 0u8, 0u8, 0u8, 104u8, 0u8, 0u8, 0u8, 0u8, 0u8,
+ 0u8, 0u8, 0u8, 14u8, 0u8, 0u8, 0u8, 2u8, 2u8, 4u8, 7u8, 9u8, 9u8,
+ 11u8, 14u8, 19u8, 19u8, 20u8, 20u8, 21u8, 21u8, 22u8, 22u8, 23u8,
+ 23u8, 24u8, 24u8, 25u8, 25u8, 26u8, 26u8, 0u8, 0u8, 68u8, 0u8, 0u8,
+ 0u8, 68u8, 0u8, 0u8, 0u8, 68u8, 0u8, 0u8, 0u8, 68u8, 0u8, 0u8, 0u8,
+ 68u8, 0u8, 0u8, 0u8, 191u8, 0u8, 0u8, 0u8, 206u8, 0u8, 0u8, 0u8,
+ 221u8, 0u8, 0u8, 0u8, 236u8, 0u8, 0u8, 0u8, 221u8, 0u8, 0u8, 0u8,
+ 251u8, 0u8, 0u8, 0u8, 10u8, 1u8, 0u8, 0u8, 25u8, 1u8, 0u8, 0u8,
+ 18u8, 0u8, 0u8, 0u8, 0u8, 2u8, 0u8, 15u8, 17u8, 0u8, 0u8, 68u8,
+ 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 2u8, 0u8, 17u8, 17u8, 0u8,
+ 0u8, 191u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 2u8, 0u8, 15u8,
+ 17u8, 0u8, 0u8, 191u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 2u8,
+ 0u8, 15u8, 16u8, 0u8, 0u8, 191u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
+ 0u8, 0u8, 2u8, 0u8, 16u8, 17u8, 0u8, 0u8, 221u8, 0u8, 0u8, 0u8,
+ 0u8, 0u8, 0u8, 0u8, 0u8, 2u8, 0u8, 15u8, 17u8, 0u8, 0u8, 221u8,
+ 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 2u8, 0u8, 15u8, 15u8, 0u8,
+ 0u8, 221u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 4u8, 0u8, 0u8,
+ 0u8, 0u8, 0u8, 0u8, 0u8, 35u8, 0u8, 0u8, 0u8, 35u8, 0u8, 0u8, 0u8,
+ 35u8, 0u8, 0u8, 0u8, 35u8, 0u8, 0u8, 0u8, 35u8, 0u8, 0u8, 0u8, 9u8,
+ 0u8, 0u8, 0u8, 18u8, 0u8, 0u8, 0u8, 18u8, 0u8, 0u8, 0u8, 0u8, 0u8,
+ 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 35u8, 0u8, 0u8, 0u8, 35u8, 0u8, 0u8,
+ 0u8,
+ ]
+ } else {
+ &[
+ 114u8, 117u8, 115u8, 116u8, 45u8, 114u8, 101u8, 103u8, 101u8,
+ 120u8, 45u8, 97u8, 117u8, 116u8, 111u8, 109u8, 97u8, 116u8, 97u8,
+ 45u8, 100u8, 102u8, 97u8, 45u8, 115u8, 112u8, 97u8, 114u8, 115u8,
+ 101u8, 0u8, 0u8, 0u8, 0u8, 254u8, 255u8, 0u8, 0u8, 0u8, 2u8, 0u8,
+ 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 14u8, 0u8, 0u8, 0u8, 1u8, 0u8, 0u8,
+ 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
+ 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
+ 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
+ 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
+ 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 2u8,
+ 2u8, 2u8, 3u8, 4u8, 4u8, 5u8, 6u8, 7u8, 7u8, 7u8, 7u8, 7u8, 7u8,
+ 7u8, 7u8, 7u8, 7u8, 7u8, 7u8, 7u8, 7u8, 7u8, 7u8, 7u8, 7u8, 7u8,
+ 7u8, 7u8, 7u8, 7u8, 8u8, 9u8, 9u8, 9u8, 10u8, 11u8, 11u8, 12u8,
+ 13u8, 14u8, 14u8, 14u8, 14u8, 14u8, 14u8, 14u8, 14u8, 14u8, 14u8,
+ 14u8, 14u8, 14u8, 14u8, 14u8, 14u8, 14u8, 14u8, 14u8, 14u8, 14u8,
+ 14u8, 15u8, 15u8, 15u8, 15u8, 15u8, 15u8, 15u8, 15u8, 15u8, 15u8,
+ 15u8, 15u8, 15u8, 15u8, 15u8, 15u8, 16u8, 16u8, 16u8, 16u8, 16u8,
+ 16u8, 16u8, 16u8, 16u8, 16u8, 16u8, 16u8, 16u8, 16u8, 16u8, 16u8,
+ 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8,
+ 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8,
+ 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 17u8, 18u8,
+ 18u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8,
+ 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8,
+ 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 19u8, 20u8, 21u8,
+ 21u8, 21u8, 21u8, 21u8, 21u8, 21u8, 21u8, 21u8, 21u8, 21u8, 21u8,
+ 22u8, 23u8, 23u8, 24u8, 25u8, 25u8, 25u8, 26u8, 27u8, 27u8, 27u8,
+ 27u8, 27u8, 27u8, 27u8, 27u8, 27u8, 27u8, 27u8, 0u8, 0u8, 1u8,
+ 40u8, 1u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 0u8, 0u8,
+ 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 128u8, 0u8, 0u8, 0u8, 0u8, 0u8,
+ 0u8, 1u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 5u8, 0u8, 5u8,
+ 5u8, 6u8, 6u8, 12u8, 12u8, 13u8, 13u8, 0u8, 0u8, 83u8, 0u8, 0u8,
+ 0u8, 68u8, 0u8, 0u8, 0u8, 83u8, 0u8, 0u8, 0u8, 68u8, 0u8, 0u8, 0u8,
+ 0u8, 0u8, 0u8, 0u8, 0u8, 2u8, 0u8, 0u8, 27u8, 0u8, 0u8, 18u8, 0u8,
+ 0u8, 0u8, 18u8, 0u8, 0u8, 0u8, 0u8, 3u8, 0u8, 6u8, 6u8, 13u8, 13u8,
+ 0u8, 0u8, 104u8, 0u8, 0u8, 0u8, 104u8, 0u8, 0u8, 0u8, 0u8, 0u8,
+ 0u8, 0u8, 0u8, 14u8, 0u8, 0u8, 0u8, 2u8, 2u8, 4u8, 7u8, 9u8, 9u8,
+ 11u8, 14u8, 19u8, 19u8, 20u8, 20u8, 21u8, 21u8, 22u8, 22u8, 23u8,
+ 23u8, 24u8, 24u8, 25u8, 25u8, 26u8, 26u8, 0u8, 0u8, 68u8, 0u8, 0u8,
+ 0u8, 68u8, 0u8, 0u8, 0u8, 68u8, 0u8, 0u8, 0u8, 68u8, 0u8, 0u8, 0u8,
+ 68u8, 0u8, 0u8, 0u8, 191u8, 0u8, 0u8, 0u8, 206u8, 0u8, 0u8, 0u8,
+ 221u8, 0u8, 0u8, 0u8, 236u8, 0u8, 0u8, 0u8, 221u8, 0u8, 0u8, 0u8,
+ 251u8, 0u8, 0u8, 0u8, 10u8, 1u8, 0u8, 0u8, 25u8, 1u8, 0u8, 0u8,
+ 18u8, 0u8, 0u8, 0u8, 0u8, 2u8, 0u8, 15u8, 17u8, 0u8, 0u8, 68u8,
+ 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 2u8, 0u8, 17u8, 17u8, 0u8,
+ 0u8, 191u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 2u8, 0u8, 15u8,
+ 17u8, 0u8, 0u8, 191u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 2u8,
+ 0u8, 15u8, 16u8, 0u8, 0u8, 191u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
+ 0u8, 0u8, 2u8, 0u8, 16u8, 17u8, 0u8, 0u8, 221u8, 0u8, 0u8, 0u8,
+ 0u8, 0u8, 0u8, 0u8, 0u8, 2u8, 0u8, 15u8, 17u8, 0u8, 0u8, 221u8,
+ 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 2u8, 0u8, 15u8, 15u8, 0u8,
+ 0u8, 221u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
+ 4u8, 0u8, 0u8, 0u8, 0u8, 35u8, 0u8, 0u8, 0u8, 35u8, 0u8, 0u8, 0u8,
+ 35u8, 0u8, 0u8, 0u8, 35u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 35u8, 0u8,
+ 0u8, 0u8, 9u8, 0u8, 0u8, 0u8, 18u8, 0u8, 0u8, 0u8, 18u8, 0u8, 0u8,
+ 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 35u8, 0u8, 0u8, 0u8,
+ 35u8,
+ ]
+ },
+ )
+ },
+ pattern: unsafe {
+ ::icu_list::provider::ListJoinerPattern::from_parts_unchecked(" e ", 3u8)
+ },
+ }),
+ },
+])
diff --git a/compiler/rustc_baked_icu_data/src/data/list/and_v1/fr.rs.data b/compiler/rustc_baked_icu_data/src/data/list/and_v1/fr.rs.data
new file mode 100644
index 000000000..66ec8f600
--- /dev/null
+++ b/compiler/rustc_baked_icu_data/src/data/list/and_v1/fr.rs.data
@@ -0,0 +1,74 @@
+::icu_list::provider::ListFormatterPatternsV1([
+ ::icu_list::provider::ConditionalListJoinerPattern {
+ default: unsafe {
+ ::icu_list::provider::ListJoinerPattern::from_parts_unchecked(", ", 2u8)
+ },
+ special_case: None,
+ },
+ ::icu_list::provider::ConditionalListJoinerPattern {
+ default: unsafe {
+ ::icu_list::provider::ListJoinerPattern::from_parts_unchecked(", ", 2u8)
+ },
+ special_case: None,
+ },
+ ::icu_list::provider::ConditionalListJoinerPattern {
+ default: unsafe {
+ ::icu_list::provider::ListJoinerPattern::from_parts_unchecked(" et ", 4u8)
+ },
+ special_case: None,
+ },
+ ::icu_list::provider::ConditionalListJoinerPattern {
+ default: unsafe {
+ ::icu_list::provider::ListJoinerPattern::from_parts_unchecked(" et ", 4u8)
+ },
+ special_case: None,
+ },
+ ::icu_list::provider::ConditionalListJoinerPattern {
+ default: unsafe {
+ ::icu_list::provider::ListJoinerPattern::from_parts_unchecked(", ", 2u8)
+ },
+ special_case: None,
+ },
+ ::icu_list::provider::ConditionalListJoinerPattern {
+ default: unsafe {
+ ::icu_list::provider::ListJoinerPattern::from_parts_unchecked(", ", 2u8)
+ },
+ special_case: None,
+ },
+ ::icu_list::provider::ConditionalListJoinerPattern {
+ default: unsafe {
+ ::icu_list::provider::ListJoinerPattern::from_parts_unchecked(" et ", 4u8)
+ },
+ special_case: None,
+ },
+ ::icu_list::provider::ConditionalListJoinerPattern {
+ default: unsafe {
+ ::icu_list::provider::ListJoinerPattern::from_parts_unchecked(" et ", 4u8)
+ },
+ special_case: None,
+ },
+ ::icu_list::provider::ConditionalListJoinerPattern {
+ default: unsafe {
+ ::icu_list::provider::ListJoinerPattern::from_parts_unchecked(", ", 2u8)
+ },
+ special_case: None,
+ },
+ ::icu_list::provider::ConditionalListJoinerPattern {
+ default: unsafe {
+ ::icu_list::provider::ListJoinerPattern::from_parts_unchecked(", ", 2u8)
+ },
+ special_case: None,
+ },
+ ::icu_list::provider::ConditionalListJoinerPattern {
+ default: unsafe {
+ ::icu_list::provider::ListJoinerPattern::from_parts_unchecked(", ", 2u8)
+ },
+ special_case: None,
+ },
+ ::icu_list::provider::ConditionalListJoinerPattern {
+ default: unsafe {
+ ::icu_list::provider::ListJoinerPattern::from_parts_unchecked(", ", 2u8)
+ },
+ special_case: None,
+ },
+])
diff --git a/compiler/rustc_baked_icu_data/src/data/list/and_v1/it.rs.data b/compiler/rustc_baked_icu_data/src/data/list/and_v1/it.rs.data
new file mode 100644
index 000000000..cbccf1120
--- /dev/null
+++ b/compiler/rustc_baked_icu_data/src/data/list/and_v1/it.rs.data
@@ -0,0 +1,74 @@
+::icu_list::provider::ListFormatterPatternsV1([
+ ::icu_list::provider::ConditionalListJoinerPattern {
+ default: unsafe {
+ ::icu_list::provider::ListJoinerPattern::from_parts_unchecked(", ", 2u8)
+ },
+ special_case: None,
+ },
+ ::icu_list::provider::ConditionalListJoinerPattern {
+ default: unsafe {
+ ::icu_list::provider::ListJoinerPattern::from_parts_unchecked(", ", 2u8)
+ },
+ special_case: None,
+ },
+ ::icu_list::provider::ConditionalListJoinerPattern {
+ default: unsafe {
+ ::icu_list::provider::ListJoinerPattern::from_parts_unchecked(" e ", 3u8)
+ },
+ special_case: None,
+ },
+ ::icu_list::provider::ConditionalListJoinerPattern {
+ default: unsafe {
+ ::icu_list::provider::ListJoinerPattern::from_parts_unchecked(" e ", 3u8)
+ },
+ special_case: None,
+ },
+ ::icu_list::provider::ConditionalListJoinerPattern {
+ default: unsafe {
+ ::icu_list::provider::ListJoinerPattern::from_parts_unchecked(", ", 2u8)
+ },
+ special_case: None,
+ },
+ ::icu_list::provider::ConditionalListJoinerPattern {
+ default: unsafe {
+ ::icu_list::provider::ListJoinerPattern::from_parts_unchecked(", ", 2u8)
+ },
+ special_case: None,
+ },
+ ::icu_list::provider::ConditionalListJoinerPattern {
+ default: unsafe {
+ ::icu_list::provider::ListJoinerPattern::from_parts_unchecked(" e ", 3u8)
+ },
+ special_case: None,
+ },
+ ::icu_list::provider::ConditionalListJoinerPattern {
+ default: unsafe {
+ ::icu_list::provider::ListJoinerPattern::from_parts_unchecked(" e ", 3u8)
+ },
+ special_case: None,
+ },
+ ::icu_list::provider::ConditionalListJoinerPattern {
+ default: unsafe {
+ ::icu_list::provider::ListJoinerPattern::from_parts_unchecked(", ", 2u8)
+ },
+ special_case: None,
+ },
+ ::icu_list::provider::ConditionalListJoinerPattern {
+ default: unsafe {
+ ::icu_list::provider::ListJoinerPattern::from_parts_unchecked(", ", 2u8)
+ },
+ special_case: None,
+ },
+ ::icu_list::provider::ConditionalListJoinerPattern {
+ default: unsafe {
+ ::icu_list::provider::ListJoinerPattern::from_parts_unchecked(" e ", 3u8)
+ },
+ special_case: None,
+ },
+ ::icu_list::provider::ConditionalListJoinerPattern {
+ default: unsafe {
+ ::icu_list::provider::ListJoinerPattern::from_parts_unchecked(" e ", 3u8)
+ },
+ special_case: None,
+ },
+])
diff --git a/compiler/rustc_baked_icu_data/src/data/list/and_v1/ja.rs.data b/compiler/rustc_baked_icu_data/src/data/list/and_v1/ja.rs.data
new file mode 100644
index 000000000..9fd168375
--- /dev/null
+++ b/compiler/rustc_baked_icu_data/src/data/list/and_v1/ja.rs.data
@@ -0,0 +1,74 @@
+::icu_list::provider::ListFormatterPatternsV1([
+ ::icu_list::provider::ConditionalListJoinerPattern {
+ default: unsafe {
+ ::icu_list::provider::ListJoinerPattern::from_parts_unchecked("、", 3u8)
+ },
+ special_case: None,
+ },
+ ::icu_list::provider::ConditionalListJoinerPattern {
+ default: unsafe {
+ ::icu_list::provider::ListJoinerPattern::from_parts_unchecked("、", 3u8)
+ },
+ special_case: None,
+ },
+ ::icu_list::provider::ConditionalListJoinerPattern {
+ default: unsafe {
+ ::icu_list::provider::ListJoinerPattern::from_parts_unchecked("、", 3u8)
+ },
+ special_case: None,
+ },
+ ::icu_list::provider::ConditionalListJoinerPattern {
+ default: unsafe {
+ ::icu_list::provider::ListJoinerPattern::from_parts_unchecked("、", 3u8)
+ },
+ special_case: None,
+ },
+ ::icu_list::provider::ConditionalListJoinerPattern {
+ default: unsafe {
+ ::icu_list::provider::ListJoinerPattern::from_parts_unchecked("、", 3u8)
+ },
+ special_case: None,
+ },
+ ::icu_list::provider::ConditionalListJoinerPattern {
+ default: unsafe {
+ ::icu_list::provider::ListJoinerPattern::from_parts_unchecked("、", 3u8)
+ },
+ special_case: None,
+ },
+ ::icu_list::provider::ConditionalListJoinerPattern {
+ default: unsafe {
+ ::icu_list::provider::ListJoinerPattern::from_parts_unchecked("、", 3u8)
+ },
+ special_case: None,
+ },
+ ::icu_list::provider::ConditionalListJoinerPattern {
+ default: unsafe {
+ ::icu_list::provider::ListJoinerPattern::from_parts_unchecked("、", 3u8)
+ },
+ special_case: None,
+ },
+ ::icu_list::provider::ConditionalListJoinerPattern {
+ default: unsafe {
+ ::icu_list::provider::ListJoinerPattern::from_parts_unchecked("、", 3u8)
+ },
+ special_case: None,
+ },
+ ::icu_list::provider::ConditionalListJoinerPattern {
+ default: unsafe {
+ ::icu_list::provider::ListJoinerPattern::from_parts_unchecked("、", 3u8)
+ },
+ special_case: None,
+ },
+ ::icu_list::provider::ConditionalListJoinerPattern {
+ default: unsafe {
+ ::icu_list::provider::ListJoinerPattern::from_parts_unchecked("、", 3u8)
+ },
+ special_case: None,
+ },
+ ::icu_list::provider::ConditionalListJoinerPattern {
+ default: unsafe {
+ ::icu_list::provider::ListJoinerPattern::from_parts_unchecked("、", 3u8)
+ },
+ special_case: None,
+ },
+])
diff --git a/compiler/rustc_baked_icu_data/src/data/list/and_v1/mod.rs b/compiler/rustc_baked_icu_data/src/data/list/and_v1/mod.rs
new file mode 100644
index 000000000..e20941f0c
--- /dev/null
+++ b/compiler/rustc_baked_icu_data/src/data/list/and_v1/mod.rs
@@ -0,0 +1,22 @@
+// @generated
+type DataStruct = <::icu_list::provider::AndListV1Marker as ::icu_provider::DataMarker>::Yokeable;
+pub fn lookup(locale: &icu_provider::DataLocale) -> Option<&'static DataStruct> {
+ static KEYS: [&str; 12usize] =
+ ["en", "es", "fr", "it", "ja", "pt", "ru", "tr", "und", "zh", "zh-Hans", "zh-Hant"];
+ static DATA: [&DataStruct; 12usize] =
+ [&EN, &ES, &FR, &IT, &JA, &PT, &RU, &TR, &UND, &ZH, &ZH, &ZH_HANT];
+ KEYS.binary_search_by(|k| locale.strict_cmp(k.as_bytes()).reverse())
+ .ok()
+ .map(|i| unsafe { *DATA.get_unchecked(i) })
+}
+static EN: DataStruct = include!("en.rs.data");
+static ES: DataStruct = include!("es.rs.data");
+static FR: DataStruct = include!("fr.rs.data");
+static IT: DataStruct = include!("it.rs.data");
+static JA: DataStruct = include!("ja.rs.data");
+static PT: DataStruct = include!("pt.rs.data");
+static RU: DataStruct = include!("ru.rs.data");
+static TR: DataStruct = include!("tr.rs.data");
+static UND: DataStruct = include!("und.rs.data");
+static ZH_HANT: DataStruct = include!("zh-Hant.rs.data");
+static ZH: DataStruct = include!("zh.rs.data");
diff --git a/compiler/rustc_baked_icu_data/src/data/list/and_v1/pt.rs.data b/compiler/rustc_baked_icu_data/src/data/list/and_v1/pt.rs.data
new file mode 100644
index 000000000..403975213
--- /dev/null
+++ b/compiler/rustc_baked_icu_data/src/data/list/and_v1/pt.rs.data
@@ -0,0 +1,74 @@
+::icu_list::provider::ListFormatterPatternsV1([
+ ::icu_list::provider::ConditionalListJoinerPattern {
+ default: unsafe {
+ ::icu_list::provider::ListJoinerPattern::from_parts_unchecked(", ", 2u8)
+ },
+ special_case: None,
+ },
+ ::icu_list::provider::ConditionalListJoinerPattern {
+ default: unsafe {
+ ::icu_list::provider::ListJoinerPattern::from_parts_unchecked(", ", 2u8)
+ },
+ special_case: None,
+ },
+ ::icu_list::provider::ConditionalListJoinerPattern {
+ default: unsafe {
+ ::icu_list::provider::ListJoinerPattern::from_parts_unchecked(" e ", 3u8)
+ },
+ special_case: None,
+ },
+ ::icu_list::provider::ConditionalListJoinerPattern {
+ default: unsafe {
+ ::icu_list::provider::ListJoinerPattern::from_parts_unchecked(" e ", 3u8)
+ },
+ special_case: None,
+ },
+ ::icu_list::provider::ConditionalListJoinerPattern {
+ default: unsafe {
+ ::icu_list::provider::ListJoinerPattern::from_parts_unchecked(", ", 2u8)
+ },
+ special_case: None,
+ },
+ ::icu_list::provider::ConditionalListJoinerPattern {
+ default: unsafe {
+ ::icu_list::provider::ListJoinerPattern::from_parts_unchecked(", ", 2u8)
+ },
+ special_case: None,
+ },
+ ::icu_list::provider::ConditionalListJoinerPattern {
+ default: unsafe {
+ ::icu_list::provider::ListJoinerPattern::from_parts_unchecked(" e ", 3u8)
+ },
+ special_case: None,
+ },
+ ::icu_list::provider::ConditionalListJoinerPattern {
+ default: unsafe {
+ ::icu_list::provider::ListJoinerPattern::from_parts_unchecked(" e ", 3u8)
+ },
+ special_case: None,
+ },
+ ::icu_list::provider::ConditionalListJoinerPattern {
+ default: unsafe {
+ ::icu_list::provider::ListJoinerPattern::from_parts_unchecked(", ", 2u8)
+ },
+ special_case: None,
+ },
+ ::icu_list::provider::ConditionalListJoinerPattern {
+ default: unsafe {
+ ::icu_list::provider::ListJoinerPattern::from_parts_unchecked(", ", 2u8)
+ },
+ special_case: None,
+ },
+ ::icu_list::provider::ConditionalListJoinerPattern {
+ default: unsafe {
+ ::icu_list::provider::ListJoinerPattern::from_parts_unchecked(", ", 2u8)
+ },
+ special_case: None,
+ },
+ ::icu_list::provider::ConditionalListJoinerPattern {
+ default: unsafe {
+ ::icu_list::provider::ListJoinerPattern::from_parts_unchecked(", ", 2u8)
+ },
+ special_case: None,
+ },
+])
diff --git a/compiler/rustc_baked_icu_data/src/data/list/and_v1/ru.rs.data b/compiler/rustc_baked_icu_data/src/data/list/and_v1/ru.rs.data
new file mode 100644
index 000000000..933cb85c8
--- /dev/null
+++ b/compiler/rustc_baked_icu_data/src/data/list/and_v1/ru.rs.data
@@ -0,0 +1,74 @@
+::icu_list::provider::ListFormatterPatternsV1([
+ ::icu_list::provider::ConditionalListJoinerPattern {
+ default: unsafe {
+ ::icu_list::provider::ListJoinerPattern::from_parts_unchecked(", ", 2u8)
+ },
+ special_case: None,
+ },
+ ::icu_list::provider::ConditionalListJoinerPattern {
+ default: unsafe {
+ ::icu_list::provider::ListJoinerPattern::from_parts_unchecked(", ", 2u8)
+ },
+ special_case: None,
+ },
+ ::icu_list::provider::ConditionalListJoinerPattern {
+ default: unsafe {
+ ::icu_list::provider::ListJoinerPattern::from_parts_unchecked(" и ", 4u8)
+ },
+ special_case: None,
+ },
+ ::icu_list::provider::ConditionalListJoinerPattern {
+ default: unsafe {
+ ::icu_list::provider::ListJoinerPattern::from_parts_unchecked(" и ", 4u8)
+ },
+ special_case: None,
+ },
+ ::icu_list::provider::ConditionalListJoinerPattern {
+ default: unsafe {
+ ::icu_list::provider::ListJoinerPattern::from_parts_unchecked(", ", 2u8)
+ },
+ special_case: None,
+ },
+ ::icu_list::provider::ConditionalListJoinerPattern {
+ default: unsafe {
+ ::icu_list::provider::ListJoinerPattern::from_parts_unchecked(", ", 2u8)
+ },
+ special_case: None,
+ },
+ ::icu_list::provider::ConditionalListJoinerPattern {
+ default: unsafe {
+ ::icu_list::provider::ListJoinerPattern::from_parts_unchecked(" и ", 4u8)
+ },
+ special_case: None,
+ },
+ ::icu_list::provider::ConditionalListJoinerPattern {
+ default: unsafe {
+ ::icu_list::provider::ListJoinerPattern::from_parts_unchecked(" и ", 4u8)
+ },
+ special_case: None,
+ },
+ ::icu_list::provider::ConditionalListJoinerPattern {
+ default: unsafe {
+ ::icu_list::provider::ListJoinerPattern::from_parts_unchecked(", ", 2u8)
+ },
+ special_case: None,
+ },
+ ::icu_list::provider::ConditionalListJoinerPattern {
+ default: unsafe {
+ ::icu_list::provider::ListJoinerPattern::from_parts_unchecked(", ", 2u8)
+ },
+ special_case: None,
+ },
+ ::icu_list::provider::ConditionalListJoinerPattern {
+ default: unsafe {
+ ::icu_list::provider::ListJoinerPattern::from_parts_unchecked(", ", 2u8)
+ },
+ special_case: None,
+ },
+ ::icu_list::provider::ConditionalListJoinerPattern {
+ default: unsafe {
+ ::icu_list::provider::ListJoinerPattern::from_parts_unchecked(", ", 2u8)
+ },
+ special_case: None,
+ },
+])
diff --git a/compiler/rustc_baked_icu_data/src/data/list/and_v1/tr.rs.data b/compiler/rustc_baked_icu_data/src/data/list/and_v1/tr.rs.data
new file mode 100644
index 000000000..286eaf69f
--- /dev/null
+++ b/compiler/rustc_baked_icu_data/src/data/list/and_v1/tr.rs.data
@@ -0,0 +1,74 @@
+::icu_list::provider::ListFormatterPatternsV1([
+ ::icu_list::provider::ConditionalListJoinerPattern {
+ default: unsafe {
+ ::icu_list::provider::ListJoinerPattern::from_parts_unchecked(", ", 2u8)
+ },
+ special_case: None,
+ },
+ ::icu_list::provider::ConditionalListJoinerPattern {
+ default: unsafe {
+ ::icu_list::provider::ListJoinerPattern::from_parts_unchecked(", ", 2u8)
+ },
+ special_case: None,
+ },
+ ::icu_list::provider::ConditionalListJoinerPattern {
+ default: unsafe {
+ ::icu_list::provider::ListJoinerPattern::from_parts_unchecked(" ve ", 4u8)
+ },
+ special_case: None,
+ },
+ ::icu_list::provider::ConditionalListJoinerPattern {
+ default: unsafe {
+ ::icu_list::provider::ListJoinerPattern::from_parts_unchecked(" ve ", 4u8)
+ },
+ special_case: None,
+ },
+ ::icu_list::provider::ConditionalListJoinerPattern {
+ default: unsafe {
+ ::icu_list::provider::ListJoinerPattern::from_parts_unchecked(", ", 2u8)
+ },
+ special_case: None,
+ },
+ ::icu_list::provider::ConditionalListJoinerPattern {
+ default: unsafe {
+ ::icu_list::provider::ListJoinerPattern::from_parts_unchecked(", ", 2u8)
+ },
+ special_case: None,
+ },
+ ::icu_list::provider::ConditionalListJoinerPattern {
+ default: unsafe {
+ ::icu_list::provider::ListJoinerPattern::from_parts_unchecked(" ve ", 4u8)
+ },
+ special_case: None,
+ },
+ ::icu_list::provider::ConditionalListJoinerPattern {
+ default: unsafe {
+ ::icu_list::provider::ListJoinerPattern::from_parts_unchecked(" ve ", 4u8)
+ },
+ special_case: None,
+ },
+ ::icu_list::provider::ConditionalListJoinerPattern {
+ default: unsafe {
+ ::icu_list::provider::ListJoinerPattern::from_parts_unchecked(", ", 2u8)
+ },
+ special_case: None,
+ },
+ ::icu_list::provider::ConditionalListJoinerPattern {
+ default: unsafe {
+ ::icu_list::provider::ListJoinerPattern::from_parts_unchecked(", ", 2u8)
+ },
+ special_case: None,
+ },
+ ::icu_list::provider::ConditionalListJoinerPattern {
+ default: unsafe {
+ ::icu_list::provider::ListJoinerPattern::from_parts_unchecked(", ", 2u8)
+ },
+ special_case: None,
+ },
+ ::icu_list::provider::ConditionalListJoinerPattern {
+ default: unsafe {
+ ::icu_list::provider::ListJoinerPattern::from_parts_unchecked(", ", 2u8)
+ },
+ special_case: None,
+ },
+])
diff --git a/compiler/rustc_baked_icu_data/src/data/list/and_v1/und.rs.data b/compiler/rustc_baked_icu_data/src/data/list/and_v1/und.rs.data
new file mode 100644
index 000000000..2d2c9bcec
--- /dev/null
+++ b/compiler/rustc_baked_icu_data/src/data/list/and_v1/und.rs.data
@@ -0,0 +1,74 @@
+::icu_list::provider::ListFormatterPatternsV1([
+ ::icu_list::provider::ConditionalListJoinerPattern {
+ default: unsafe {
+ ::icu_list::provider::ListJoinerPattern::from_parts_unchecked(", ", 2u8)
+ },
+ special_case: None,
+ },
+ ::icu_list::provider::ConditionalListJoinerPattern {
+ default: unsafe {
+ ::icu_list::provider::ListJoinerPattern::from_parts_unchecked(", ", 2u8)
+ },
+ special_case: None,
+ },
+ ::icu_list::provider::ConditionalListJoinerPattern {
+ default: unsafe {
+ ::icu_list::provider::ListJoinerPattern::from_parts_unchecked(", ", 2u8)
+ },
+ special_case: None,
+ },
+ ::icu_list::provider::ConditionalListJoinerPattern {
+ default: unsafe {
+ ::icu_list::provider::ListJoinerPattern::from_parts_unchecked(", ", 2u8)
+ },
+ special_case: None,
+ },
+ ::icu_list::provider::ConditionalListJoinerPattern {
+ default: unsafe {
+ ::icu_list::provider::ListJoinerPattern::from_parts_unchecked(", ", 2u8)
+ },
+ special_case: None,
+ },
+ ::icu_list::provider::ConditionalListJoinerPattern {
+ default: unsafe {
+ ::icu_list::provider::ListJoinerPattern::from_parts_unchecked(", ", 2u8)
+ },
+ special_case: None,
+ },
+ ::icu_list::provider::ConditionalListJoinerPattern {
+ default: unsafe {
+ ::icu_list::provider::ListJoinerPattern::from_parts_unchecked(", ", 2u8)
+ },
+ special_case: None,
+ },
+ ::icu_list::provider::ConditionalListJoinerPattern {
+ default: unsafe {
+ ::icu_list::provider::ListJoinerPattern::from_parts_unchecked(", ", 2u8)
+ },
+ special_case: None,
+ },
+ ::icu_list::provider::ConditionalListJoinerPattern {
+ default: unsafe {
+ ::icu_list::provider::ListJoinerPattern::from_parts_unchecked(", ", 2u8)
+ },
+ special_case: None,
+ },
+ ::icu_list::provider::ConditionalListJoinerPattern {
+ default: unsafe {
+ ::icu_list::provider::ListJoinerPattern::from_parts_unchecked(", ", 2u8)
+ },
+ special_case: None,
+ },
+ ::icu_list::provider::ConditionalListJoinerPattern {
+ default: unsafe {
+ ::icu_list::provider::ListJoinerPattern::from_parts_unchecked(", ", 2u8)
+ },
+ special_case: None,
+ },
+ ::icu_list::provider::ConditionalListJoinerPattern {
+ default: unsafe {
+ ::icu_list::provider::ListJoinerPattern::from_parts_unchecked(", ", 2u8)
+ },
+ special_case: None,
+ },
+])
diff --git a/compiler/rustc_baked_icu_data/src/data/list/and_v1/zh-Hant.rs.data b/compiler/rustc_baked_icu_data/src/data/list/and_v1/zh-Hant.rs.data
new file mode 100644
index 000000000..5d96cc85e
--- /dev/null
+++ b/compiler/rustc_baked_icu_data/src/data/list/and_v1/zh-Hant.rs.data
@@ -0,0 +1,74 @@
+::icu_list::provider::ListFormatterPatternsV1([
+ ::icu_list::provider::ConditionalListJoinerPattern {
+ default: unsafe {
+ ::icu_list::provider::ListJoinerPattern::from_parts_unchecked("、", 3u8)
+ },
+ special_case: None,
+ },
+ ::icu_list::provider::ConditionalListJoinerPattern {
+ default: unsafe {
+ ::icu_list::provider::ListJoinerPattern::from_parts_unchecked("、", 3u8)
+ },
+ special_case: None,
+ },
+ ::icu_list::provider::ConditionalListJoinerPattern {
+ default: unsafe {
+ ::icu_list::provider::ListJoinerPattern::from_parts_unchecked("和", 3u8)
+ },
+ special_case: None,
+ },
+ ::icu_list::provider::ConditionalListJoinerPattern {
+ default: unsafe {
+ ::icu_list::provider::ListJoinerPattern::from_parts_unchecked("和", 3u8)
+ },
+ special_case: None,
+ },
+ ::icu_list::provider::ConditionalListJoinerPattern {
+ default: unsafe {
+ ::icu_list::provider::ListJoinerPattern::from_parts_unchecked("、", 3u8)
+ },
+ special_case: None,
+ },
+ ::icu_list::provider::ConditionalListJoinerPattern {
+ default: unsafe {
+ ::icu_list::provider::ListJoinerPattern::from_parts_unchecked("、", 3u8)
+ },
+ special_case: None,
+ },
+ ::icu_list::provider::ConditionalListJoinerPattern {
+ default: unsafe {
+ ::icu_list::provider::ListJoinerPattern::from_parts_unchecked("和", 3u8)
+ },
+ special_case: None,
+ },
+ ::icu_list::provider::ConditionalListJoinerPattern {
+ default: unsafe {
+ ::icu_list::provider::ListJoinerPattern::from_parts_unchecked("和", 3u8)
+ },
+ special_case: None,
+ },
+ ::icu_list::provider::ConditionalListJoinerPattern {
+ default: unsafe {
+ ::icu_list::provider::ListJoinerPattern::from_parts_unchecked("、", 3u8)
+ },
+ special_case: None,
+ },
+ ::icu_list::provider::ConditionalListJoinerPattern {
+ default: unsafe {
+ ::icu_list::provider::ListJoinerPattern::from_parts_unchecked("、", 3u8)
+ },
+ special_case: None,
+ },
+ ::icu_list::provider::ConditionalListJoinerPattern {
+ default: unsafe {
+ ::icu_list::provider::ListJoinerPattern::from_parts_unchecked("和", 3u8)
+ },
+ special_case: None,
+ },
+ ::icu_list::provider::ConditionalListJoinerPattern {
+ default: unsafe {
+ ::icu_list::provider::ListJoinerPattern::from_parts_unchecked("和", 3u8)
+ },
+ special_case: None,
+ },
+])
diff --git a/compiler/rustc_baked_icu_data/src/data/list/and_v1/zh.rs.data b/compiler/rustc_baked_icu_data/src/data/list/and_v1/zh.rs.data
new file mode 100644
index 000000000..4a38374ca
--- /dev/null
+++ b/compiler/rustc_baked_icu_data/src/data/list/and_v1/zh.rs.data
@@ -0,0 +1,74 @@
+::icu_list::provider::ListFormatterPatternsV1([
+ ::icu_list::provider::ConditionalListJoinerPattern {
+ default: unsafe {
+ ::icu_list::provider::ListJoinerPattern::from_parts_unchecked("、", 3u8)
+ },
+ special_case: None,
+ },
+ ::icu_list::provider::ConditionalListJoinerPattern {
+ default: unsafe {
+ ::icu_list::provider::ListJoinerPattern::from_parts_unchecked("、", 3u8)
+ },
+ special_case: None,
+ },
+ ::icu_list::provider::ConditionalListJoinerPattern {
+ default: unsafe {
+ ::icu_list::provider::ListJoinerPattern::from_parts_unchecked("和", 3u8)
+ },
+ special_case: None,
+ },
+ ::icu_list::provider::ConditionalListJoinerPattern {
+ default: unsafe {
+ ::icu_list::provider::ListJoinerPattern::from_parts_unchecked("和", 3u8)
+ },
+ special_case: None,
+ },
+ ::icu_list::provider::ConditionalListJoinerPattern {
+ default: unsafe {
+ ::icu_list::provider::ListJoinerPattern::from_parts_unchecked("、", 3u8)
+ },
+ special_case: None,
+ },
+ ::icu_list::provider::ConditionalListJoinerPattern {
+ default: unsafe {
+ ::icu_list::provider::ListJoinerPattern::from_parts_unchecked("、", 3u8)
+ },
+ special_case: None,
+ },
+ ::icu_list::provider::ConditionalListJoinerPattern {
+ default: unsafe {
+ ::icu_list::provider::ListJoinerPattern::from_parts_unchecked("和", 3u8)
+ },
+ special_case: None,
+ },
+ ::icu_list::provider::ConditionalListJoinerPattern {
+ default: unsafe {
+ ::icu_list::provider::ListJoinerPattern::from_parts_unchecked("和", 3u8)
+ },
+ special_case: None,
+ },
+ ::icu_list::provider::ConditionalListJoinerPattern {
+ default: unsafe {
+ ::icu_list::provider::ListJoinerPattern::from_parts_unchecked("、", 3u8)
+ },
+ special_case: None,
+ },
+ ::icu_list::provider::ConditionalListJoinerPattern {
+ default: unsafe {
+ ::icu_list::provider::ListJoinerPattern::from_parts_unchecked("、", 3u8)
+ },
+ special_case: None,
+ },
+ ::icu_list::provider::ConditionalListJoinerPattern {
+ default: unsafe {
+ ::icu_list::provider::ListJoinerPattern::from_parts_unchecked("、", 3u8)
+ },
+ special_case: None,
+ },
+ ::icu_list::provider::ConditionalListJoinerPattern {
+ default: unsafe {
+ ::icu_list::provider::ListJoinerPattern::from_parts_unchecked("、", 3u8)
+ },
+ special_case: None,
+ },
+])
diff --git a/compiler/rustc_baked_icu_data/src/data/mod.rs b/compiler/rustc_baked_icu_data/src/data/mod.rs
index a6a71c79c..ce33339ad 100644
--- a/compiler/rustc_baked_icu_data/src/data/mod.rs
+++ b/compiler/rustc_baked_icu_data/src/data/mod.rs
@@ -1,90 +1,113 @@
// @generated
mod fallback;
mod list;
-/// This data provider was programmatically generated by [`icu_datagen`](
-/// https://unicode-org.github.io/icu4x-docs/doc/icu_datagen/enum.Out.html#variant.Module).
-#[non_exhaustive]
-pub struct BakedDataProvider;
use ::icu_provider::prelude::*;
-impl DataProvider<::icu_list::provider::AndListV1Marker> for BakedDataProvider {
- fn load(
- &self,
- req: DataRequest,
- ) -> Result<DataResponse<::icu_list::provider::AndListV1Marker>, DataError> {
- Ok(DataResponse {
- metadata: Default::default(),
- payload: Some(DataPayload::from_owned(zerofrom::ZeroFrom::zero_from(
- *list::and_v1::DATA
- .get_by(|k| req.locale.strict_cmp(k.as_bytes()).reverse())
+/// Implement [`DataProvider<M>`] on the given struct using the data
+/// hardcoded in this module. This allows the struct to be used with
+/// `icu`'s `_unstable` constructors.
+///
+/// This macro can only be called from its definition-site, i.e. right
+/// after `include!`-ing the generated module.
+///
+/// ```compile_fail
+/// struct MyDataProvider;
+/// include!("/path/to/generated/mod.rs");
+/// impl_data_provider(MyDataProvider);
+/// ```
+#[allow(unused_macros)]
+macro_rules! impl_data_provider {
+ ($ provider : path) => {
+ impl DataProvider<::icu_list::provider::AndListV1Marker> for $provider {
+ fn load(&self, req: DataRequest) -> Result<DataResponse<::icu_list::provider::AndListV1Marker>, DataError> {
+ list::and_v1::lookup(&req.locale)
+ .map(zerofrom::ZeroFrom::zero_from)
+ .map(DataPayload::from_owned)
+ .map(|payload| DataResponse { metadata: Default::default(), payload: Some(payload) })
+ .ok_or_else(|| DataErrorKind::MissingLocale.with_req(::icu_list::provider::AndListV1Marker::KEY, req))
+ }
+ }
+ impl DataProvider<::icu_provider_adapters::fallback::provider::CollationFallbackSupplementV1Marker> for $provider {
+ fn load(
+ &self,
+ req: DataRequest,
+ ) -> Result<DataResponse<::icu_provider_adapters::fallback::provider::CollationFallbackSupplementV1Marker>, DataError> {
+ fallback::supplement::co_v1::lookup(&req.locale)
+ .map(zerofrom::ZeroFrom::zero_from)
+ .map(DataPayload::from_owned)
+ .map(|payload| DataResponse { metadata: Default::default(), payload: Some(payload) })
.ok_or_else(|| {
DataErrorKind::MissingLocale
- .with_req(::icu_list::provider::AndListV1Marker::KEY, req)
- })?,
- ))),
- })
- }
-}
-impl DataProvider<::icu_provider_adapters::fallback::provider::CollationFallbackSupplementV1Marker>
- for BakedDataProvider
-{
- fn load(
- &self,
- req: DataRequest,
- ) -> Result<
- DataResponse<
- ::icu_provider_adapters::fallback::provider::CollationFallbackSupplementV1Marker,
- >,
- DataError,
- > {
- Ok(DataResponse {
- metadata: Default::default(),
- payload: Some(DataPayload::from_owned(zerofrom::ZeroFrom::zero_from(
- *fallback::supplement::co_v1::DATA.get_by(|k| req.locale.strict_cmp(k.as_bytes()).reverse()).ok_or_else(|| {
- DataErrorKind::MissingLocale.with_req(::icu_provider_adapters::fallback::provider::CollationFallbackSupplementV1Marker::KEY, req)
- })?,
- ))),
- })
- }
-}
-impl DataProvider<::icu_provider_adapters::fallback::provider::LocaleFallbackLikelySubtagsV1Marker>
- for BakedDataProvider
-{
- fn load(
- &self,
- req: DataRequest,
- ) -> Result<
- DataResponse<
- ::icu_provider_adapters::fallback::provider::LocaleFallbackLikelySubtagsV1Marker,
- >,
- DataError,
- > {
- Ok(DataResponse {
- metadata: Default::default(),
- payload: Some(DataPayload::from_owned(zerofrom::ZeroFrom::zero_from(
- *fallback::likelysubtags_v1::DATA.get_by(|k| req.locale.strict_cmp(k.as_bytes()).reverse()).ok_or_else(|| {
- DataErrorKind::MissingLocale.with_req(::icu_provider_adapters::fallback::provider::LocaleFallbackLikelySubtagsV1Marker::KEY, req)
- })?,
- ))),
- })
- }
+ .with_req(::icu_provider_adapters::fallback::provider::CollationFallbackSupplementV1Marker::KEY, req)
+ })
+ }
+ }
+ impl DataProvider<::icu_provider_adapters::fallback::provider::LocaleFallbackLikelySubtagsV1Marker> for $provider {
+ fn load(
+ &self,
+ req: DataRequest,
+ ) -> Result<DataResponse<::icu_provider_adapters::fallback::provider::LocaleFallbackLikelySubtagsV1Marker>, DataError> {
+ fallback::likelysubtags_v1::lookup(&req.locale)
+ .map(zerofrom::ZeroFrom::zero_from)
+ .map(DataPayload::from_owned)
+ .map(|payload| DataResponse { metadata: Default::default(), payload: Some(payload) })
+ .ok_or_else(|| {
+ DataErrorKind::MissingLocale
+ .with_req(::icu_provider_adapters::fallback::provider::LocaleFallbackLikelySubtagsV1Marker::KEY, req)
+ })
+ }
+ }
+ impl DataProvider<::icu_provider_adapters::fallback::provider::LocaleFallbackParentsV1Marker> for $provider {
+ fn load(
+ &self,
+ req: DataRequest,
+ ) -> Result<DataResponse<::icu_provider_adapters::fallback::provider::LocaleFallbackParentsV1Marker>, DataError> {
+ fallback::parents_v1::lookup(&req.locale)
+ .map(zerofrom::ZeroFrom::zero_from)
+ .map(DataPayload::from_owned)
+ .map(|payload| DataResponse { metadata: Default::default(), payload: Some(payload) })
+ .ok_or_else(|| {
+ DataErrorKind::MissingLocale.with_req(::icu_provider_adapters::fallback::provider::LocaleFallbackParentsV1Marker::KEY, req)
+ })
+ }
+ }
+ };
}
-impl DataProvider<::icu_provider_adapters::fallback::provider::LocaleFallbackParentsV1Marker>
- for BakedDataProvider
-{
- fn load(
- &self,
- req: DataRequest,
- ) -> Result<
- DataResponse<::icu_provider_adapters::fallback::provider::LocaleFallbackParentsV1Marker>,
- DataError,
- > {
- Ok(DataResponse {
- metadata: Default::default(),
- payload: Some(DataPayload::from_owned(zerofrom::ZeroFrom::zero_from(
- *fallback::parents_v1::DATA.get_by(|k| req.locale.strict_cmp(k.as_bytes()).reverse()).ok_or_else(|| {
- DataErrorKind::MissingLocale.with_req(::icu_provider_adapters::fallback::provider::LocaleFallbackParentsV1Marker::KEY, req)
- })?,
- ))),
- })
- }
+/// Implement [`AnyProvider`] on the given struct using the data
+/// hardcoded in this module. This allows the struct to be used with
+/// `icu`'s `_any` constructors.
+///
+/// This macro can only be called from its definition-site, i.e. right
+/// after `include!`-ing the generated module.
+///
+/// ```compile_fail
+/// struct MyAnyProvider;
+/// include!("/path/to/generated/mod.rs");
+/// impl_any_provider(MyAnyProvider);
+/// ```
+#[allow(unused_macros)]
+macro_rules! impl_any_provider {
+ ($ provider : path) => {
+ impl AnyProvider for $provider {
+ fn load_any(&self, key: DataKey, req: DataRequest) -> Result<AnyResponse, DataError> {
+ const ANDLISTV1MARKER: ::icu_provider::DataKeyHash = ::icu_list::provider::AndListV1Marker::KEY.hashed();
+ const COLLATIONFALLBACKSUPPLEMENTV1MARKER: ::icu_provider::DataKeyHash =
+ ::icu_provider_adapters::fallback::provider::CollationFallbackSupplementV1Marker::KEY.hashed();
+ const LOCALEFALLBACKLIKELYSUBTAGSV1MARKER: ::icu_provider::DataKeyHash =
+ ::icu_provider_adapters::fallback::provider::LocaleFallbackLikelySubtagsV1Marker::KEY.hashed();
+ const LOCALEFALLBACKPARENTSV1MARKER: ::icu_provider::DataKeyHash =
+ ::icu_provider_adapters::fallback::provider::LocaleFallbackParentsV1Marker::KEY.hashed();
+ match key.hashed() {
+ ANDLISTV1MARKER => list::and_v1::lookup(&req.locale).map(AnyPayload::from_static_ref),
+ COLLATIONFALLBACKSUPPLEMENTV1MARKER => fallback::supplement::co_v1::lookup(&req.locale).map(AnyPayload::from_static_ref),
+ LOCALEFALLBACKLIKELYSUBTAGSV1MARKER => fallback::likelysubtags_v1::lookup(&req.locale).map(AnyPayload::from_static_ref),
+ LOCALEFALLBACKPARENTSV1MARKER => fallback::parents_v1::lookup(&req.locale).map(AnyPayload::from_static_ref),
+ _ => return Err(DataErrorKind::MissingDataKey.with_req(key, req)),
+ }
+ .map(|payload| AnyResponse { payload: Some(payload), metadata: Default::default() })
+ .ok_or_else(|| DataErrorKind::MissingLocale.with_req(key, req))
+ }
+ }
+ };
}
+pub struct BakedDataProvider;
+impl_data_provider!(BakedDataProvider);
diff --git a/compiler/rustc_error_messages/locales/en-US/borrowck.ftl b/compiler/rustc_borrowck/locales/en-US.ftl
index 9e4332c42..a3b6b5e81 100644
--- a/compiler/rustc_error_messages/locales/en-US/borrowck.ftl
+++ b/compiler/rustc_borrowck/locales/en-US.ftl
@@ -18,7 +18,7 @@ borrowck_generic_does_not_live_long_enough =
`{$kind}` does not live long enough
borrowck_move_borrowed =
- cannot move out of `{$desc}` beacause it is borrowed
+ cannot move out of `{$desc}` because it is borrowed
borrowck_var_does_not_need_mut =
variable does not need to be mutable
@@ -33,7 +33,7 @@ borrowck_var_here_defined = variable defined here
borrowck_var_here_captured = variable captured here
-borrowck_closure_inferred_mut = inferred to be a `FnMut` closure
+borrowck_closure_inferred_mut = inferred to be a `FnMut` closure
borrowck_returned_closure_escaped =
returns a closure that contains a reference to a captured variable, which then escapes the closure body
@@ -87,10 +87,10 @@ borrowck_use_due_to_use_closure =
use occurs due to use in closure
borrowck_assign_due_to_use_closure =
- assign occurs due to use in closure
+ assignment occurs due to use in closure
borrowck_assign_part_due_to_use_closure =
- assign to part occurs due to use in closure
+ assignment to part occurs due to use in closure
borrowck_capture_immute =
capture is immutable because of use here
@@ -123,4 +123,7 @@ borrowck_cannot_move_when_borrowed =
borrowck_opaque_type_non_generic_param =
expected generic {$kind} parameter, found `{$ty}`
- .label = this generic parameter must be used with a generic {$kind} parameter
+ .label = {STREQ($ty, "'static") ->
+ [true] cannot use static lifetime; use a bound lifetime instead or remove the lifetime parameter from the opaque type
+ *[other] this generic parameter must be used with a generic {$kind} parameter
+ }
diff --git a/compiler/rustc_borrowck/src/borrowck_errors.rs b/compiler/rustc_borrowck/src/borrowck_errors.rs
index a4943d112..2bbb9618d 100644
--- a/compiler/rustc_borrowck/src/borrowck_errors.rs
+++ b/compiler/rustc_borrowck/src/borrowck_errors.rs
@@ -37,7 +37,7 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> {
desc,
);
- err.span_label(borrow_span, format!("borrow of {} occurs here", borrow_desc));
+ err.span_label(borrow_span, format!("{} is borrowed here", borrow_desc));
err.span_label(span, format!("use of borrowed {}", borrow_desc));
err
}
@@ -250,8 +250,8 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> {
desc,
);
- err.span_label(borrow_span, format!("borrow of {} occurs here", desc));
- err.span_label(span, format!("assignment to borrowed {} occurs here", desc));
+ err.span_label(borrow_span, format!("{} is borrowed here", desc));
+ err.span_label(span, format!("{} is assigned to here but it was already borrowed", desc));
err
}
diff --git a/compiler/rustc_borrowck/src/constraint_generation.rs b/compiler/rustc_borrowck/src/constraint_generation.rs
index 11b31c3f1..1427f5cb3 100644
--- a/compiler/rustc_borrowck/src/constraint_generation.rs
+++ b/compiler/rustc_borrowck/src/constraint_generation.rs
@@ -9,7 +9,7 @@ use rustc_middle::mir::{
};
use rustc_middle::ty::subst::SubstsRef;
use rustc_middle::ty::visit::TypeVisitable;
-use rustc_middle::ty::{self, RegionVid, Ty};
+use rustc_middle::ty::{self, RegionVid, Ty, TyCtxt};
use crate::{
borrow_set::BorrowSet, facts::AllFacts, location::LocationTable, nll::ToRegionVid,
@@ -165,7 +165,7 @@ impl<'cx, 'tcx> ConstraintGeneration<'cx, 'tcx> {
/// `location`.
fn add_regular_live_constraint<T>(&mut self, live_ty: T, location: Location)
where
- T: TypeVisitable<'tcx>,
+ T: TypeVisitable<TyCtxt<'tcx>>,
{
debug!("add_regular_live_constraint(live_ty={:?}, location={:?})", live_ty, location);
diff --git a/compiler/rustc_borrowck/src/constraints/mod.rs b/compiler/rustc_borrowck/src/constraints/mod.rs
index 1f0b8adea..f370c0216 100644
--- a/compiler/rustc_borrowck/src/constraints/mod.rs
+++ b/compiler/rustc_borrowck/src/constraints/mod.rs
@@ -17,7 +17,7 @@ pub(crate) mod graph;
/// constraints of the form `R1: R2`. Each constraint is identified by
/// a unique `OutlivesConstraintIndex` and you can index into the set
/// (`constraint_set[i]`) to access the constraint details.
-#[derive(Clone, Default)]
+#[derive(Clone, Debug, Default)]
pub(crate) struct OutlivesConstraintSet<'tcx> {
outlives: IndexVec<OutlivesConstraintIndex, OutlivesConstraint<'tcx>>,
}
diff --git a/compiler/rustc_borrowck/src/dataflow.rs b/compiler/rustc_borrowck/src/dataflow.rs
index 8c4885770..2821677c5 100644
--- a/compiler/rustc_borrowck/src/dataflow.rs
+++ b/compiler/rustc_borrowck/src/dataflow.rs
@@ -393,6 +393,7 @@ impl<'tcx> rustc_mir_dataflow::GenKillAnalysis<'tcx> for Borrows<'_, 'tcx> {
| mir::StatementKind::AscribeUserType(..)
| mir::StatementKind::Coverage(..)
| mir::StatementKind::Intrinsic(..)
+ | mir::StatementKind::ConstEvalCounter
| mir::StatementKind::Nop => {}
}
}
diff --git a/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs
index 1550958ab..68205fa45 100644
--- a/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs
@@ -106,7 +106,7 @@ impl<'tcx> ToUniverseInfo<'tcx>
}
}
-impl<'tcx, T: Copy + fmt::Display + TypeFoldable<'tcx> + 'tcx> ToUniverseInfo<'tcx>
+impl<'tcx, T: Copy + fmt::Display + TypeFoldable<TyCtxt<'tcx>> + 'tcx> ToUniverseInfo<'tcx>
for Canonical<'tcx, ty::ParamEnvAnd<'tcx, type_op::Normalize<T>>>
{
fn to_universe_info(self, base_universe: ty::UniverseIndex) -> UniverseInfo<'tcx> {
@@ -180,20 +180,20 @@ trait TypeOpInfo<'tcx> {
return;
};
- let placeholder_region = tcx.mk_region(ty::RePlaceholder(ty::Placeholder {
+ let placeholder_region = tcx.mk_re_placeholder(ty::Placeholder {
name: placeholder.name,
universe: adjusted_universe.into(),
- }));
+ });
let error_region =
if let RegionElement::PlaceholderRegion(error_placeholder) = error_element {
let adjusted_universe =
error_placeholder.universe.as_u32().checked_sub(base_universe.as_u32());
adjusted_universe.map(|adjusted| {
- tcx.mk_region(ty::RePlaceholder(ty::Placeholder {
+ tcx.mk_re_placeholder(ty::Placeholder {
name: error_placeholder.name,
universe: adjusted.into(),
- }))
+ })
})
} else {
None
@@ -258,7 +258,7 @@ struct NormalizeQuery<'tcx, T> {
impl<'tcx, T> TypeOpInfo<'tcx> for NormalizeQuery<'tcx, T>
where
- T: Copy + fmt::Display + TypeFoldable<'tcx> + 'tcx,
+ T: Copy + fmt::Display + TypeFoldable<TyCtxt<'tcx>> + 'tcx,
{
fn fallback_error(
&self,
@@ -390,7 +390,7 @@ fn try_extract_error_from_fulfill_cx<'tcx>(
error_region,
&region_constraints,
|vid| ocx.infcx.region_var_origin(vid),
- |vid| ocx.infcx.universe_of_region(ocx.infcx.tcx.mk_region(ty::ReVar(vid))),
+ |vid| ocx.infcx.universe_of_region(ocx.infcx.tcx.mk_re_var(vid)),
)
}
@@ -411,7 +411,7 @@ fn try_extract_error_from_region_constraints<'tcx>(
}
// FIXME: Should this check the universe of the var?
Constraint::VarSubReg(vid, sup) if sup == placeholder_region => {
- Some((infcx.tcx.mk_region(ty::ReVar(vid)), cause.clone()))
+ Some((infcx.tcx.mk_re_var(vid), cause.clone()))
}
_ => None,
}
diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
index e5a36259f..cb97699d7 100644
--- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
@@ -6,7 +6,7 @@ use rustc_errors::{
struct_span_err, Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed, MultiSpan,
};
use rustc_hir as hir;
-use rustc_hir::def::Res;
+use rustc_hir::def::{DefKind, Res};
use rustc_hir::intravisit::{walk_block, walk_expr, Visitor};
use rustc_hir::{AsyncGeneratorKind, GeneratorKind, LangItem};
use rustc_infer::infer::TyCtxtInferExt;
@@ -236,10 +236,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
let ty = used_place.ty(self.body, self.infcx.tcx).ty;
let needs_note = match ty.kind() {
ty::Closure(id, _) => {
- let tables = self.infcx.tcx.typeck(id.expect_local());
- let hir_id = self.infcx.tcx.hir().local_def_id_to_hir_id(id.expect_local());
-
- tables.closure_kind_origins().get(hir_id).is_none()
+ self.infcx.tcx.closure_kind_origin(id.expect_local()).is_none()
}
_ => true,
};
@@ -766,7 +763,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
let copy_did = infcx.tcx.require_lang_item(LangItem::Copy, Some(span));
let cause = ObligationCause::new(
span,
- self.mir_hir_id(),
+ self.mir_def_id(),
rustc_infer::traits::ObligationCauseCode::MiscObligation,
);
let errors = rustc_trait_selection::traits::fully_solve_bound(
@@ -803,6 +800,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
predicates
.iter()
.map(|(param, constraint)| (param.name.as_str(), &**constraint, None)),
+ None,
);
}
}
@@ -1185,11 +1183,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
return None;
};
debug!("checking call args for uses of inner_param: {:?}", args);
- if args.contains(&Operand::Move(inner_param)) {
- Some((loc, term))
- } else {
- None
- }
+ args.contains(&Operand::Move(inner_param)).then_some((loc, term))
}) else {
debug!("no uses of inner_param found as a by-move call arg");
return;
@@ -1497,7 +1491,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
assert!(root_place.projection.is_empty());
let proper_span = self.body.local_decls[root_place.local].source_info.span;
- let root_place_projection = self.infcx.tcx.intern_place_elems(root_place.projection);
+ let root_place_projection = self.infcx.tcx.mk_place_elems(root_place.projection);
if self.access_place_error_reported.contains(&(
Place { local: root_place.local, projection: root_place_projection },
@@ -1673,7 +1667,6 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
format!("`{}` would have to be valid for `{}`...", name, region_name),
);
- let fn_hir_id = self.mir_hir_id();
err.span_label(
drop_span,
format!(
@@ -1681,19 +1674,12 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
name,
self.infcx
.tcx
- .hir()
- .opt_name(fn_hir_id)
+ .opt_item_name(self.mir_def_id().to_def_id())
.map(|name| format!("function `{}`", name))
.unwrap_or_else(|| {
- match &self
- .infcx
- .tcx
- .typeck(self.mir_def_id())
- .node_type(fn_hir_id)
- .kind()
- {
- ty::Closure(..) => "enclosing closure",
- ty::Generator(..) => "enclosing generator",
+ match &self.infcx.tcx.def_kind(self.mir_def_id()) {
+ DefKind::Closure => "enclosing closure",
+ DefKind::Generator => "enclosing generator",
kind => bug!("expected closure or generator, found {:?}", kind),
}
.to_string()
@@ -1736,7 +1722,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
&self.local_names,
&mut err,
"",
- None,
+ Some(borrow_span),
None,
);
}
@@ -2138,7 +2124,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
) -> DiagnosticBuilder<'cx, ErrorGuaranteed> {
let tcx = self.infcx.tcx;
- let (_, escapes_from) = tcx.article_and_description(self.mir_def_id().to_def_id());
+ let escapes_from = tcx.def_descr(self.mir_def_id().to_def_id());
let mut err =
borrowck_errors::borrowed_data_escapes_closure(tcx, escape_span, escapes_from);
@@ -2595,11 +2581,11 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
if is_closure {
None
} else {
- let ty = self.infcx.tcx.type_of(self.mir_def_id());
+ let ty = self.infcx.tcx.type_of(self.mir_def_id()).subst_identity();
match ty.kind() {
ty::FnDef(_, _) | ty::FnPtr(_) => self.annotate_fn_sig(
self.mir_def_id(),
- self.infcx.tcx.fn_sig(self.mir_def_id()),
+ self.infcx.tcx.fn_sig(self.mir_def_id()).subst_identity(),
),
_ => None,
}
@@ -2645,6 +2631,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
operands,
) = rvalue
{
+ let def_id = def_id.expect_local();
for operand in operands {
let (Operand::Copy(assigned_from) | Operand::Move(assigned_from)) = operand else {
continue;
@@ -2667,7 +2654,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
// into a place then we should annotate the closure in
// case it ends up being assigned into the return place.
annotated_closure =
- self.annotate_fn_sig(*def_id, substs.as_closure().sig());
+ self.annotate_fn_sig(def_id, substs.as_closure().sig());
debug!(
"annotate_argument_and_return_for_borrow: \
annotated_closure={:?} assigned_from_local={:?} \
diff --git a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs
index 209574709..19855075c 100644
--- a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs
@@ -1,6 +1,8 @@
//! Print diagnostics to explain why values are borrowed.
use rustc_errors::{Applicability, Diagnostic};
+use rustc_hir as hir;
+use rustc_hir::intravisit::Visitor;
use rustc_index::vec::IndexVec;
use rustc_infer::infer::NllRegionVariableOrigin;
use rustc_middle::mir::{
@@ -11,6 +13,7 @@ use rustc_middle::ty::adjustment::PointerCast;
use rustc_middle::ty::{self, RegionVid, TyCtxt};
use rustc_span::symbol::{kw, Symbol};
use rustc_span::{sym, DesugaringKind, Span};
+use rustc_trait_selection::traits::error_reporting::FindExprBySpan;
use crate::region_infer::{BlameConstraint, ExtraConstraintInfo};
use crate::{
@@ -63,6 +66,36 @@ impl<'tcx> BorrowExplanation<'tcx> {
borrow_span: Option<Span>,
multiple_borrow_span: Option<(Span, Span)>,
) {
+ if let Some(span) = borrow_span {
+ let def_id = body.source.def_id();
+ if let Some(node) = tcx.hir().get_if_local(def_id)
+ && let Some(body_id) = node.body_id()
+ {
+ let body = tcx.hir().body(body_id);
+ let mut expr_finder = FindExprBySpan::new(span);
+ expr_finder.visit_expr(body.value);
+ if let Some(mut expr) = expr_finder.result {
+ while let hir::ExprKind::AddrOf(_, _, inner)
+ | hir::ExprKind::Unary(hir::UnOp::Deref, inner)
+ | hir::ExprKind::Field(inner, _)
+ | hir::ExprKind::MethodCall(_, inner, _, _)
+ | hir::ExprKind::Index(inner, _) = &expr.kind
+ {
+ expr = inner;
+ }
+ if let hir::ExprKind::Path(hir::QPath::Resolved(None, p)) = expr.kind
+ && let [hir::PathSegment { ident, args: None, .. }] = p.segments
+ && let hir::def::Res::Local(hir_id) = p.res
+ && let Some(hir::Node::Pat(pat)) = tcx.hir().find(hir_id)
+ {
+ err.span_label(
+ pat.span,
+ &format!("binding `{ident}` declared here"),
+ );
+ }
+ }
+ }
+ }
match *self {
BorrowExplanation::UsedLater(later_use_kind, var_or_use_span, path_span) => {
let message = match later_use_kind {
diff --git a/compiler/rustc_borrowck/src/diagnostics/mod.rs b/compiler/rustc_borrowck/src/diagnostics/mod.rs
index 1b40b7143..a99fd594a 100644
--- a/compiler/rustc_borrowck/src/diagnostics/mod.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/mod.rs
@@ -115,11 +115,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
debug!("add_moved_or_invoked_closure_note: closure={:?}", closure);
if let ty::Closure(did, _) = self.body.local_decls[closure].ty.kind() {
let did = did.expect_local();
- let hir_id = self.infcx.tcx.hir().local_def_id_to_hir_id(did);
-
- if let Some((span, hir_place)) =
- self.infcx.tcx.typeck(did).closure_kind_origins().get(hir_id)
- {
+ if let Some((span, hir_place)) = self.infcx.tcx.closure_kind_origin(did) {
diag.span_note(
*span,
&format!(
@@ -139,11 +135,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
if let Some(target) = target {
if let ty::Closure(did, _) = self.body.local_decls[target].ty.kind() {
let did = did.expect_local();
- let hir_id = self.infcx.tcx.hir().local_def_id_to_hir_id(did);
-
- if let Some((span, hir_place)) =
- self.infcx.tcx.typeck(did).closure_kind_origins().get(hir_id)
- {
+ if let Some((span, hir_place)) = self.infcx.tcx.closure_kind_origin(did) {
diag.span_note(
*span,
&format!(
@@ -373,14 +365,8 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
//
// We know the field exists so it's safe to call operator[] and `unwrap` here.
let def_id = def_id.expect_local();
- let var_id = self
- .infcx
- .tcx
- .typeck(def_id)
- .closure_min_captures_flattened(def_id)
- .nth(field.index())
- .unwrap()
- .get_root_variable();
+ let var_id =
+ self.infcx.tcx.closure_captures(def_id)[field.index()].get_root_variable();
Some(self.infcx.tcx.hir().name(var_id).to_string())
}
@@ -817,6 +803,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
&& let AggregateKind::Closure(def_id, _) | AggregateKind::Generator(def_id, _, _) = **kind
{
debug!("move_spans: def_id={:?} places={:?}", def_id, places);
+ let def_id = def_id.expect_local();
if let Some((args_span, generator_kind, capture_kind_span, path_span)) =
self.closure_span(def_id, moved_place, places)
{
@@ -945,6 +932,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
box AggregateKind::Generator(def_id, _, _) => (def_id, true),
_ => continue,
};
+ let def_id = def_id.expect_local();
debug!(
"borrow_spans: def_id={:?} is_generator={:?} places={:?}",
@@ -985,7 +973,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
debug!("closure_span: hir_id={:?} expr={:?}", hir_id, expr);
if let hir::ExprKind::Closure(&hir::Closure { body, fn_decl_span, .. }) = expr {
for (captured_place, place) in
- self.infcx.tcx.typeck(def_id).closure_min_captures_flattened(def_id).zip(places)
+ self.infcx.tcx.closure_captures(def_id).iter().zip(places)
{
match place {
Operand::Copy(place) | Operand::Move(place)
@@ -1064,7 +1052,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
);
}
}
- CallKind::Normal { self_arg, desugaring, method_did } => {
+ CallKind::Normal { self_arg, desugaring, method_did, method_substs } => {
let self_arg = self_arg.unwrap();
let tcx = self.infcx.tcx;
if let Some((CallDesugaringKind::ForLoopIntoIter, _)) = desugaring {
@@ -1128,17 +1116,21 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
"{place_name} {partially_str}moved due to this method call{loop_message}",
),
);
+
let infcx = tcx.infer_ctxt().build();
+ // Erase and shadow everything that could be passed to the new infcx.
let ty = tcx.erase_regions(moved_place.ty(self.body, tcx).ty);
+ let method_substs = tcx.erase_regions(method_substs);
+
if let ty::Adt(def, substs) = ty.kind()
&& Some(def.did()) == tcx.lang_items().pin_type()
&& let ty::Ref(_, _, hir::Mutability::Mut) = substs.type_at(0).kind()
- && let self_ty = infcx.replace_bound_vars_with_fresh_vars(
+ && let self_ty = infcx.instantiate_binder_with_fresh_vars(
fn_call_span,
LateBoundRegionConversionTime::FnCall,
- tcx.fn_sig(method_did).input(0),
+ tcx.fn_sig(method_did).subst(tcx, method_substs).input(0),
)
- && infcx.can_eq(self.param_env, ty, self_ty).is_ok()
+ && infcx.can_eq(self.param_env, ty, self_ty)
{
err.span_suggestion_verbose(
fn_call_span.shrink_to_lo(),
@@ -1176,13 +1168,13 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
);
}
let parent_did = tcx.parent(method_did);
- let parent_self_ty = (tcx.def_kind(parent_did)
- == rustc_hir::def::DefKind::Impl)
- .then_some(parent_did)
- .and_then(|did| match tcx.type_of(did).kind() {
- ty::Adt(def, ..) => Some(def.did()),
- _ => None,
- });
+ let parent_self_ty =
+ matches!(tcx.def_kind(parent_did), rustc_hir::def::DefKind::Impl { .. })
+ .then_some(parent_did)
+ .and_then(|did| match tcx.type_of(did).subst_identity().kind() {
+ ty::Adt(def, ..) => Some(def.did()),
+ _ => None,
+ });
let is_option_or_result = parent_self_ty.map_or(false, |def_id| {
matches!(tcx.get_diagnostic_name(def_id), Some(sym::Option | sym::Result))
});
diff --git a/compiler/rustc_borrowck/src/diagnostics/move_errors.rs b/compiler/rustc_borrowck/src/diagnostics/move_errors.rs
index 6db3c858a..5e4c7292e 100644
--- a/compiler/rustc_borrowck/src/diagnostics/move_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/move_errors.rs
@@ -448,7 +448,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
};
self.note_type_does_not_implement_copy(err, &place_desc, place_ty, Some(span), "");
- use_spans.args_span_label(err, format!("move out of {place_desc} occurs here"));
+ use_spans.args_span_label(err, format!("{place_desc} is moved here"));
}
}
}
@@ -467,7 +467,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
err.span_suggestion_verbose(
span.shrink_to_lo(),
"consider borrowing here",
- "&".to_string(),
+ '&',
Applicability::MaybeIncorrect,
);
}
diff --git a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs
index 45b15c2c5..328ac880d 100644
--- a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs
@@ -344,7 +344,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
} else {
err.span_help(source_info.span, "try removing `&mut` here");
}
- } else if decl.mutability == Mutability::Not {
+ } else if decl.mutability.is_not() {
if matches!(
decl.local_info,
Some(box LocalInfo::User(ClearCrossCrate::Set(BindingForm::ImplicitSelf(
@@ -385,7 +385,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
err.span_suggestion_verbose(
local_decl.source_info.span.shrink_to_lo(),
"consider changing this to be mutable",
- "mut ".to_string(),
+ "mut ",
Applicability::MachineApplicable,
);
let tcx = self.infcx.tcx;
@@ -606,12 +606,63 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
}
}
Some((false, err_label_span, message)) => {
- err.span_label(
- err_label_span,
- &format!(
- "consider changing this binding's type to be: `{message}`"
- ),
- );
+ struct BindingFinder {
+ span: Span,
+ hir_id: Option<hir::HirId>,
+ }
+
+ impl<'tcx> Visitor<'tcx> for BindingFinder {
+ fn visit_stmt(&mut self, s: &'tcx hir::Stmt<'tcx>) {
+ if let hir::StmtKind::Local(local) = s.kind {
+ if local.pat.span == self.span {
+ self.hir_id = Some(local.hir_id);
+ }
+ }
+ hir::intravisit::walk_stmt(self, s);
+ }
+ }
+ let hir_map = self.infcx.tcx.hir();
+ let def_id = self.body.source.def_id();
+ let hir_id = hir_map.local_def_id_to_hir_id(def_id.expect_local());
+ let node = hir_map.find(hir_id);
+ let hir_id = if let Some(hir::Node::Item(item)) = node
+ && let hir::ItemKind::Fn(.., body_id) = item.kind
+ {
+ let body = hir_map.body(body_id);
+ let mut v = BindingFinder {
+ span: err_label_span,
+ hir_id: None,
+ };
+ v.visit_body(body);
+ v.hir_id
+ } else {
+ None
+ };
+ if let Some(hir_id) = hir_id
+ && let Some(hir::Node::Local(local)) = hir_map.find(hir_id)
+ {
+ let (changing, span, sugg) = match local.ty {
+ Some(ty) => ("changing", ty.span, message),
+ None => (
+ "specifying",
+ local.pat.span.shrink_to_hi(),
+ format!(": {message}"),
+ ),
+ };
+ err.span_suggestion_verbose(
+ span,
+ &format!("consider {changing} this binding's type"),
+ sugg,
+ Applicability::HasPlaceholders,
+ );
+ } else {
+ err.span_label(
+ err_label_span,
+ &format!(
+ "consider changing this binding's type to be: `{message}`"
+ ),
+ );
+ }
}
None => {}
}
@@ -850,10 +901,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
err: &mut Diagnostic,
) {
let tables = tcx.typeck(closure_local_def_id);
- let closure_hir_id = tcx.hir().local_def_id_to_hir_id(closure_local_def_id);
- if let Some((span, closure_kind_origin)) =
- &tables.closure_kind_origins().get(closure_hir_id)
- {
+ if let Some((span, closure_kind_origin)) = tcx.closure_kind_origin(closure_local_def_id) {
let reason = if let PlaceBase::Upvar(upvar_id) = closure_kind_origin.base {
let upvar = ty::place_to_string_for_capture(tcx, closure_kind_origin);
let root_hir_id = upvar_id.var_path.hir_id;
diff --git a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs
index 187861ba1..ffe82b46c 100644
--- a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs
@@ -415,7 +415,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
/// fn foo<'a, 'b>(x: &'a u32) -> &'b u32 { x }
/// ```
///
- /// Here we would be invoked with `fr = 'a` and `outlived_fr = `'b`.
+ /// Here we would be invoked with `fr = 'a` and `outlived_fr = 'b`.
pub(crate) fn report_region_error(
&mut self,
fr: RegionVid,
@@ -575,7 +575,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
let mut output_ty = self.regioncx.universal_regions().unnormalized_output_ty;
if let ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }) = *output_ty.kind() {
- output_ty = self.infcx.tcx.type_of(def_id)
+ output_ty = self.infcx.tcx.type_of(def_id).subst_identity()
};
debug!("report_fnmut_error: output_ty={:?}", output_ty);
@@ -583,10 +583,12 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
let err = FnMutError {
span: *span,
ty_err: match output_ty.kind() {
- ty::Closure(_, _) => FnMutReturnTypeErr::ReturnClosure { span: *span },
ty::Generator(def, ..) if self.infcx.tcx.generator_is_async(*def) => {
FnMutReturnTypeErr::ReturnAsyncBlock { span: *span }
}
+ _ if output_ty.contains_closure() => {
+ FnMutReturnTypeErr::ReturnClosure { span: *span }
+ }
_ => FnMutReturnTypeErr::ReturnRef { span: *span },
},
};
@@ -658,10 +660,8 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
errci.outlived_fr,
);
- let (_, escapes_from) = self
- .infcx
- .tcx
- .article_and_description(self.regioncx.universal_regions().defining_ty.def_id());
+ let escapes_from =
+ self.infcx.tcx.def_descr(self.regioncx.universal_regions().defining_ty.def_id());
// Revert to the normal error in these cases.
// Assignments aren't "escapes" in function items.
@@ -755,8 +755,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
..
} = errci;
- let (_, mir_def_name) =
- self.infcx.tcx.article_and_description(self.mir_def_id().to_def_id());
+ let mir_def_name = self.infcx.tcx.def_descr(self.mir_def_id().to_def_id());
let err = LifetimeOutliveErr { span: *span };
let mut diag = self.infcx.tcx.sess.create_err(err);
@@ -813,17 +812,10 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
if *outlived_f != ty::ReStatic {
return;
}
+ let suitable_region = self.infcx.tcx.is_suitable_region(f);
+ let Some(suitable_region) = suitable_region else { return; };
- let fn_returns = self
- .infcx
- .tcx
- .is_suitable_region(f)
- .map(|r| self.infcx.tcx.return_type_impl_or_dyn_traits(r.def_id))
- .unwrap_or_default();
-
- if fn_returns.is_empty() {
- return;
- }
+ let fn_returns = self.infcx.tcx.return_type_impl_or_dyn_traits(suitable_region.def_id);
let param = if let Some(param) = find_param_with_region(self.infcx.tcx, f, outlived_f) {
param
@@ -839,15 +831,43 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
};
let captures = format!("captures data from {arg}");
- return nice_region_error::suggest_new_region_bound(
- self.infcx.tcx,
- diag,
- fn_returns,
- lifetime.to_string(),
- Some(arg),
- captures,
- Some((param.param_ty_span, param.param_ty.to_string())),
- self.infcx.tcx.is_suitable_region(f).map(|r| r.def_id),
+ if !fn_returns.is_empty() {
+ nice_region_error::suggest_new_region_bound(
+ self.infcx.tcx,
+ diag,
+ fn_returns,
+ lifetime.to_string(),
+ Some(arg),
+ captures,
+ Some((param.param_ty_span, param.param_ty.to_string())),
+ Some(suitable_region.def_id),
+ );
+ return;
+ }
+
+ let Some((alias_tys, alias_span)) = self
+ .infcx
+ .tcx
+ .return_type_impl_or_dyn_traits_with_type_alias(suitable_region.def_id) else { return; };
+
+ // in case the return type of the method is a type alias
+ let mut spans_suggs: Vec<_> = Vec::new();
+ for alias_ty in alias_tys {
+ if alias_ty.span.desugaring_kind().is_some() {
+ // Skip `async` desugaring `impl Future`.
+ ()
+ }
+ if let TyKind::TraitObject(_, lt, _) = alias_ty.kind {
+ spans_suggs.push((lt.ident.span.shrink_to_hi(), " + 'a".to_string()));
+ }
+ }
+ spans_suggs.push((alias_span.shrink_to_hi(), "<'a>".to_string()));
+ diag.multipart_suggestion_verbose(
+ &format!(
+ "to declare that the trait object {captures}, you can add a lifetime parameter `'a` in the type alias"
+ ),
+ spans_suggs,
+ Applicability::MaybeIncorrect,
);
}
}
@@ -873,7 +893,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
debug!(?fn_did, ?substs);
// Only suggest this on function calls, not closures
- let ty = tcx.type_of(fn_did);
+ let ty = tcx.type_of(fn_did).subst_identity();
debug!("ty: {:?}, ty.kind: {:?}", ty, ty.kind());
if let ty::Closure(_, _) = ty.kind() {
return;
@@ -929,7 +949,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
.push_span_label(*span, "this has an implicit `'static` lifetime requirement");
multi_span.push_span_label(
ident.span,
- "calling this method introduces the `impl`'s 'static` requirement",
+ "calling this method introduces the `impl`'s `'static` requirement",
);
err.subdiagnostic(RequireStaticErr::UsedImpl { multi_span });
err.span_suggestion_verbose(
@@ -976,7 +996,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
fn suggest_move_on_borrowing_closure(&self, diag: &mut Diagnostic) {
let map = self.infcx.tcx.hir();
let body_id = map.body_owned_by(self.mir_def_id());
- let expr = &map.body(body_id).value;
+ let expr = &map.body(body_id).value.peel_blocks();
let mut closure_span = None::<rustc_span::Span>;
match expr.kind {
hir::ExprKind::MethodCall(.., args, _) => {
@@ -991,20 +1011,14 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
}
}
}
- hir::ExprKind::Block(blk, _) => {
- if let Some(expr) = blk.expr {
- // only when the block is a closure
- if let hir::ExprKind::Closure(hir::Closure {
- capture_clause: hir::CaptureBy::Ref,
- body,
- ..
- }) = expr.kind
- {
- let body = map.body(*body);
- if !matches!(body.generator_kind, Some(hir::GeneratorKind::Async(..))) {
- closure_span = Some(expr.span.shrink_to_lo());
- }
- }
+ hir::ExprKind::Closure(hir::Closure {
+ capture_clause: hir::CaptureBy::Ref,
+ body,
+ ..
+ }) => {
+ let body = map.body(*body);
+ if !matches!(body.generator_kind, Some(hir::GeneratorKind::Async(..))) {
+ closure_span = Some(expr.span.shrink_to_lo());
}
}
_ => {}
diff --git a/compiler/rustc_borrowck/src/diagnostics/region_name.rs b/compiler/rustc_borrowck/src/diagnostics/region_name.rs
index 9233287cf..f6881a2e5 100644
--- a/compiler/rustc_borrowck/src/diagnostics/region_name.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/region_name.rs
@@ -187,6 +187,12 @@ impl Display for RegionName {
}
}
+impl rustc_errors::IntoDiagnosticArg for RegionName {
+ fn into_diagnostic_arg(self) -> rustc_errors::DiagnosticArgValue<'static> {
+ self.to_string().into_diagnostic_arg()
+ }
+}
+
impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
pub(crate) fn mir_def_id(&self) -> hir::def_id::LocalDefId {
self.body.source.def_id().expect_local()
@@ -274,17 +280,10 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
debug!("give_region_a_name: error_region = {:?}", error_region);
match *error_region {
- ty::ReEarlyBound(ebr) => {
- if ebr.has_name() {
- let span = tcx.hir().span_if_local(ebr.def_id).unwrap_or(DUMMY_SP);
- Some(RegionName {
- name: ebr.name,
- source: RegionNameSource::NamedEarlyBoundRegion(span),
- })
- } else {
- None
- }
- }
+ ty::ReEarlyBound(ebr) => ebr.has_name().then(|| {
+ let span = tcx.hir().span_if_local(ebr.def_id).unwrap_or(DUMMY_SP);
+ RegionName { name: ebr.name, source: RegionNameSource::NamedEarlyBoundRegion(span) }
+ }),
ty::ReStatic => {
Some(RegionName { name: kw::StaticLifetime, source: RegionNameSource::Static })
@@ -337,11 +336,11 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
let note = match closure_kind_ty.to_opt_closure_kind() {
Some(ty::ClosureKind::Fn) => {
"closure implements `Fn`, so references to captured variables \
- can't escape the closure"
+ can't escape the closure"
}
Some(ty::ClosureKind::FnMut) => {
"closure implements `FnMut`, so references to captured variables \
- can't escape the closure"
+ can't escape the closure"
}
Some(ty::ClosureKind::FnOnce) => {
bug!("BrEnv in a `FnOnce` closure");
@@ -358,7 +357,11 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
ty::BoundRegionKind::BrAnon(..) => None,
},
- ty::ReLateBound(..) | ty::ReVar(..) | ty::RePlaceholder(..) | ty::ReErased => None,
+ ty::ReLateBound(..)
+ | ty::ReVar(..)
+ | ty::RePlaceholder(..)
+ | ty::ReErased
+ | ty::ReError(_) => None,
}
}
@@ -842,12 +845,13 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
let tcx = self.infcx.tcx;
let region_parent = tcx.parent(region.def_id);
- if tcx.def_kind(region_parent) != DefKind::Impl {
+ let DefKind::Impl { .. } = tcx.def_kind(region_parent) else {
return None;
- }
+ };
- let found = tcx
- .any_free_region_meets(&tcx.type_of(region_parent), |r| *r == ty::ReEarlyBound(region));
+ let found = tcx.any_free_region_meets(&tcx.type_of(region_parent).subst_identity(), |r| {
+ *r == ty::ReEarlyBound(region)
+ });
Some(RegionName {
name: self.synthesize_region_name(),
diff --git a/compiler/rustc_borrowck/src/invalidation.rs b/compiler/rustc_borrowck/src/invalidation.rs
index 6fd929005..6217676d5 100644
--- a/compiler/rustc_borrowck/src/invalidation.rs
+++ b/compiler/rustc_borrowck/src/invalidation.rs
@@ -91,7 +91,8 @@ impl<'cx, 'tcx> Visitor<'tcx> for InvalidationGenerator<'cx, 'tcx> {
LocalMutationIsAllowed::Yes,
);
}
- StatementKind::Nop
+ StatementKind::ConstEvalCounter
+ | StatementKind::Nop
| StatementKind::Retag { .. }
| StatementKind::Deinit(..)
| StatementKind::SetDiscriminant { .. } => {
diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs
index 73ea7314b..0f591460e 100644
--- a/compiler/rustc_borrowck/src/lib.rs
+++ b/compiler/rustc_borrowck/src/lib.rs
@@ -1,6 +1,7 @@
//! This query borrow-checks the MIR to (further) ensure it is not broken.
#![allow(rustc::potential_query_instability)]
+#![feature(associated_type_bounds)]
#![feature(box_patterns)]
#![feature(let_chains)]
#![feature(min_specialization)]
@@ -20,12 +21,15 @@ extern crate tracing;
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_data_structures::graph::dominators::Dominators;
use rustc_data_structures::vec_map::VecMap;
-use rustc_errors::{Diagnostic, DiagnosticBuilder};
+use rustc_errors::{Diagnostic, DiagnosticBuilder, DiagnosticMessage, SubdiagnosticMessage};
use rustc_hir as hir;
use rustc_hir::def_id::LocalDefId;
use rustc_index::bit_set::ChunkedBitSet;
use rustc_index::vec::IndexVec;
-use rustc_infer::infer::{DefiningAnchor, InferCtxt, TyCtxtInferExt};
+use rustc_infer::infer::{
+ DefiningAnchor, InferCtxt, NllRegionVariableOrigin, RegionVariableOrigin, TyCtxtInferExt,
+};
+use rustc_macros::fluent_messages;
use rustc_middle::mir::{
traversal, Body, ClearCrossCrate, Local, Location, Mutability, NonDivergingIntrinsic, Operand,
Place, PlaceElem, PlaceRef, VarDebugInfoContents,
@@ -43,6 +47,7 @@ use smallvec::SmallVec;
use std::cell::OnceCell;
use std::cell::RefCell;
use std::collections::BTreeMap;
+use std::ops::Deref;
use std::rc::Rc;
use rustc_mir_dataflow::impls::{
@@ -94,6 +99,9 @@ use nll::{PoloniusOutput, ToRegionVid};
use place_ext::PlaceExt;
use places_conflict::{places_conflict, PlaceConflictBias};
use region_infer::RegionInferenceContext;
+use renumber::RegionCtxt;
+
+fluent_messages! { "../locales/en-US.ftl" }
// FIXME(eddyb) perhaps move this somewhere more centrally.
#[derive(Debug)]
@@ -167,10 +175,10 @@ fn do_mir_borrowck<'tcx>(
return_body_with_facts: bool,
) -> (BorrowCheckResult<'tcx>, Option<Box<BodyWithBorrowckFacts<'tcx>>>) {
let def = input_body.source.with_opt_param().as_local().unwrap();
-
debug!(?def);
let tcx = infcx.tcx;
+ let infcx = BorrowckInferCtxt::new(infcx);
let param_env = tcx.param_env(def.did);
let mut local_names = IndexVec::from_elem(None, &input_body.local_decls);
@@ -194,14 +202,14 @@ fn do_mir_borrowck<'tcx>(
let mut errors = error::BorrowckErrors::new(infcx.tcx);
// Gather the upvars of a closure, if any.
- let tables = tcx.typeck_opt_const_arg(def);
- if let Some(e) = tables.tainted_by_errors {
+ if let Some(e) = input_body.tainted_by_errors {
infcx.set_tainted_by_errors(e);
errors.set_tainted_by_errors(e);
}
- let upvars: Vec<_> = tables
- .closure_min_captures_flattened(def.did)
- .map(|captured_place| {
+ let upvars: Vec<_> = tcx
+ .closure_captures(def.did)
+ .iter()
+ .map(|&captured_place| {
let capture = captured_place.info.capture_kind;
let by_ref = match capture {
ty::UpvarCapture::ByValue => false,
@@ -218,7 +226,7 @@ fn do_mir_borrowck<'tcx>(
let mut body_owned = input_body.clone();
let mut promoted = input_promoted.clone();
let free_regions =
- nll::replace_regions_in_mir(infcx, param_env, &mut body_owned, &mut promoted);
+ nll::replace_regions_in_mir(&infcx, param_env, &mut body_owned, &mut promoted);
let body = &body_owned; // no further changes
let location_table_owned = LocationTable::new(body);
@@ -256,7 +264,7 @@ fn do_mir_borrowck<'tcx>(
opt_closure_req,
nll_errors,
} = nll::compute_regions(
- infcx,
+ &infcx,
free_regions,
body,
&promoted,
@@ -271,12 +279,12 @@ fn do_mir_borrowck<'tcx>(
// Dump MIR results into a file, if that is enabled. This let us
// write unit-tests, as well as helping with debugging.
- nll::dump_mir_results(infcx, &body, &regioncx, &opt_closure_req);
+ nll::dump_mir_results(&infcx, &body, &regioncx, &opt_closure_req);
// We also have a `#[rustc_regions]` annotation that causes us to dump
// information.
nll::dump_annotation(
- infcx,
+ &infcx,
&body,
&regioncx,
&opt_closure_req,
@@ -320,7 +328,7 @@ fn do_mir_borrowck<'tcx>(
if let Err((move_data, move_errors)) = move_data_results {
let mut promoted_mbcx = MirBorrowckCtxt {
- infcx,
+ infcx: &infcx,
param_env,
body: promoted_body,
move_data: &move_data,
@@ -349,7 +357,7 @@ fn do_mir_borrowck<'tcx>(
}
let mut mbcx = MirBorrowckCtxt {
- infcx,
+ infcx: &infcx,
param_env,
body,
move_data: &mdpe.move_data,
@@ -481,8 +489,84 @@ pub struct BodyWithBorrowckFacts<'tcx> {
pub location_table: LocationTable,
}
+pub struct BorrowckInferCtxt<'cx, 'tcx> {
+ pub(crate) infcx: &'cx InferCtxt<'tcx>,
+ pub(crate) reg_var_to_origin: RefCell<FxHashMap<ty::RegionVid, RegionCtxt>>,
+}
+
+impl<'cx, 'tcx> BorrowckInferCtxt<'cx, 'tcx> {
+ pub(crate) fn new(infcx: &'cx InferCtxt<'tcx>) -> Self {
+ BorrowckInferCtxt { infcx, reg_var_to_origin: RefCell::new(Default::default()) }
+ }
+
+ pub(crate) fn next_region_var<F>(
+ &self,
+ origin: RegionVariableOrigin,
+ get_ctxt_fn: F,
+ ) -> ty::Region<'tcx>
+ where
+ F: Fn() -> RegionCtxt,
+ {
+ let next_region = self.infcx.next_region_var(origin);
+ let vid = next_region
+ .as_var()
+ .unwrap_or_else(|| bug!("expected RegionKind::RegionVar on {:?}", next_region));
+
+ if cfg!(debug_assertions) {
+ debug!("inserting vid {:?} with origin {:?} into var_to_origin", vid, origin);
+ let ctxt = get_ctxt_fn();
+ let mut var_to_origin = self.reg_var_to_origin.borrow_mut();
+ let prev = var_to_origin.insert(vid, ctxt);
+
+ // This only makes sense if not called in a canonicalization context. If this
+ // ever changes we either want to get rid of `BorrowckInferContext::reg_var_to_origin`
+ // or modify how we track nll region vars for that map.
+ assert!(matches!(prev, None));
+ }
+
+ next_region
+ }
+
+ #[instrument(skip(self, get_ctxt_fn), level = "debug")]
+ pub(crate) fn next_nll_region_var<F>(
+ &self,
+ origin: NllRegionVariableOrigin,
+ get_ctxt_fn: F,
+ ) -> ty::Region<'tcx>
+ where
+ F: Fn() -> RegionCtxt,
+ {
+ let next_region = self.infcx.next_nll_region_var(origin.clone());
+ let vid = next_region
+ .as_var()
+ .unwrap_or_else(|| bug!("expected RegionKind::RegionVar on {:?}", next_region));
+
+ if cfg!(debug_assertions) {
+ debug!("inserting vid {:?} with origin {:?} into var_to_origin", vid, origin);
+ let ctxt = get_ctxt_fn();
+ let mut var_to_origin = self.reg_var_to_origin.borrow_mut();
+ let prev = var_to_origin.insert(vid, ctxt);
+
+ // This only makes sense if not called in a canonicalization context. If this
+ // ever changes we either want to get rid of `BorrowckInferContext::reg_var_to_origin`
+ // or modify how we track nll region vars for that map.
+ assert!(matches!(prev, None));
+ }
+
+ next_region
+ }
+}
+
+impl<'cx, 'tcx> Deref for BorrowckInferCtxt<'cx, 'tcx> {
+ type Target = InferCtxt<'tcx>;
+
+ fn deref(&self) -> &'cx Self::Target {
+ self.infcx
+ }
+}
+
struct MirBorrowckCtxt<'cx, 'tcx> {
- infcx: &'cx InferCtxt<'tcx>,
+ infcx: &'cx BorrowckInferCtxt<'cx, 'tcx>,
param_env: ParamEnv<'tcx>,
body: &'cx Body<'tcx>,
move_data: &'cx MoveData<'tcx>,
@@ -609,7 +693,8 @@ impl<'cx, 'tcx> rustc_mir_dataflow::ResultsVisitor<'cx, 'tcx> for MirBorrowckCtx
StatementKind::AscribeUserType(..)
// Doesn't have any language semantics
| StatementKind::Coverage(..)
- // Does not actually affect borrowck
+ // These do not actually affect borrowck
+ | StatementKind::ConstEvalCounter
| StatementKind::StorageLive(..) => {}
StatementKind::StorageDead(local) => {
self.access_place(
@@ -1277,6 +1362,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
// in order to populate our used_mut set.
match **aggregate_kind {
AggregateKind::Closure(def_id, _) | AggregateKind::Generator(def_id, _, _) => {
+ let def_id = def_id.expect_local();
let BorrowCheckResult { used_mut_upvars, .. } =
self.infcx.tcx.mir_borrowck(def_id);
debug!("{:?} used_mut_upvars={:?}", def_id, used_mut_upvars);
diff --git a/compiler/rustc_borrowck/src/nll.rs b/compiler/rustc_borrowck/src/nll.rs
index b2d92d0db..96228338a 100644
--- a/compiler/rustc_borrowck/src/nll.rs
+++ b/compiler/rustc_borrowck/src/nll.rs
@@ -5,16 +5,14 @@
use rustc_data_structures::vec_map::VecMap;
use rustc_hir::def_id::LocalDefId;
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,
};
-use rustc_middle::ty::{self, OpaqueHiddenType, Region, RegionVid};
+use rustc_middle::ty::{self, OpaqueHiddenType, Region, RegionVid, TyCtxt};
use rustc_span::symbol::sym;
use std::env;
-use std::fmt::Debug;
use std::io;
use std::path::PathBuf;
use std::rc::Rc;
@@ -37,7 +35,7 @@ use crate::{
renumber,
type_check::{self, MirTypeckRegionConstraints, MirTypeckResults},
universal_regions::UniversalRegions,
- Upvar,
+ BorrowckInferCtxt, Upvar,
};
pub type PoloniusOutput = Output<RustcFacts>;
@@ -58,7 +56,7 @@ pub(crate) struct NllOutput<'tcx> {
/// `compute_regions`.
#[instrument(skip(infcx, param_env, body, promoted), level = "debug")]
pub(crate) fn replace_regions_in_mir<'tcx>(
- infcx: &InferCtxt<'tcx>,
+ infcx: &BorrowckInferCtxt<'_, 'tcx>,
param_env: ty::ParamEnv<'tcx>,
body: &mut Body<'tcx>,
promoted: &mut IndexVec<Promoted, Body<'tcx>>,
@@ -157,7 +155,7 @@ fn populate_polonius_move_facts(
///
/// This may result in errors being reported.
pub(crate) fn compute_regions<'cx, 'tcx>(
- infcx: &InferCtxt<'tcx>,
+ infcx: &BorrowckInferCtxt<'_, 'tcx>,
universal_regions: UniversalRegions<'tcx>,
body: &Body<'tcx>,
promoted: &IndexVec<Promoted, Body<'tcx>>,
@@ -259,6 +257,7 @@ pub(crate) fn compute_regions<'cx, 'tcx>(
);
let mut regioncx = RegionInferenceContext::new(
+ infcx,
var_origins,
universal_regions,
placeholder_indices,
@@ -322,10 +321,10 @@ pub(crate) fn compute_regions<'cx, 'tcx>(
}
pub(super) fn dump_mir_results<'tcx>(
- infcx: &InferCtxt<'tcx>,
+ infcx: &BorrowckInferCtxt<'_, 'tcx>,
body: &Body<'tcx>,
regioncx: &RegionInferenceContext<'tcx>,
- closure_region_requirements: &Option<ClosureRegionRequirements<'_>>,
+ closure_region_requirements: &Option<ClosureRegionRequirements<'tcx>>,
) {
if !dump_enabled(infcx.tcx, "nll", body.source.def_id()) {
return;
@@ -340,9 +339,11 @@ pub(super) fn dump_mir_results<'tcx>(
if let Some(closure_region_requirements) = closure_region_requirements {
writeln!(out, "| Free Region Constraints")?;
- for_each_region_constraint(closure_region_requirements, &mut |msg| {
- writeln!(out, "| {}", msg)
- })?;
+ for_each_region_constraint(
+ infcx.tcx,
+ closure_region_requirements,
+ &mut |msg| writeln!(out, "| {}", msg),
+ )?;
writeln!(out, "|")?;
}
}
@@ -369,11 +370,13 @@ pub(super) fn dump_mir_results<'tcx>(
};
}
+#[allow(rustc::diagnostic_outside_of_impl)]
+#[allow(rustc::untranslatable_diagnostic)]
pub(super) fn dump_annotation<'tcx>(
- infcx: &InferCtxt<'tcx>,
+ infcx: &BorrowckInferCtxt<'_, 'tcx>,
body: &Body<'tcx>,
regioncx: &RegionInferenceContext<'tcx>,
- closure_region_requirements: &Option<ClosureRegionRequirements<'_>>,
+ closure_region_requirements: &Option<ClosureRegionRequirements<'tcx>>,
opaque_type_values: &VecMap<LocalDefId, OpaqueHiddenType<'tcx>>,
errors: &mut crate::error::BorrowckErrors<'tcx>,
) {
@@ -403,7 +406,7 @@ pub(super) fn dump_annotation<'tcx>(
// Dump the region constraints we are imposing *between* those
// newly created variables.
- for_each_region_constraint(closure_region_requirements, &mut |msg| {
+ for_each_region_constraint(tcx, closure_region_requirements, &mut |msg| {
err.note(msg);
Ok(())
})
@@ -424,16 +427,19 @@ pub(super) fn dump_annotation<'tcx>(
errors.buffer_non_error_diag(err);
}
-fn for_each_region_constraint(
- closure_region_requirements: &ClosureRegionRequirements<'_>,
+fn for_each_region_constraint<'tcx>(
+ tcx: TyCtxt<'tcx>,
+ closure_region_requirements: &ClosureRegionRequirements<'tcx>,
with_msg: &mut dyn FnMut(&str) -> io::Result<()>,
) -> io::Result<()> {
for req in &closure_region_requirements.outlives_requirements {
- let subject: &dyn Debug = match &req.subject {
- ClosureOutlivesSubject::Region(subject) => subject,
- ClosureOutlivesSubject::Ty(ty) => ty,
+ let subject = match req.subject {
+ ClosureOutlivesSubject::Region(subject) => format!("{:?}", subject),
+ ClosureOutlivesSubject::Ty(ty) => {
+ format!("{:?}", ty.instantiate(tcx, |vid| tcx.mk_re_var(vid)))
+ }
};
- with_msg(&format!("where {:?}: {:?}", subject, req.outlived_free_region,))?;
+ with_msg(&format!("where {}: {:?}", subject, req.outlived_free_region,))?;
}
Ok(())
}
diff --git a/compiler/rustc_borrowck/src/region_infer/mod.rs b/compiler/rustc_borrowck/src/region_infer/mod.rs
index 238172ea3..e6195de40 100644
--- a/compiler/rustc_borrowck/src/region_infer/mod.rs
+++ b/compiler/rustc_borrowck/src/region_infer/mod.rs
@@ -7,18 +7,18 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_data_structures::graph::scc::Sccs;
use rustc_errors::Diagnostic;
use rustc_hir::def_id::CRATE_DEF_ID;
-use rustc_hir::CRATE_HIR_ID;
use rustc_index::vec::IndexVec;
use rustc_infer::infer::outlives::test_type_match;
use rustc_infer::infer::region_constraints::{GenericKind, VarInfos, VerifyBound, VerifyIfEq};
use rustc_infer::infer::{InferCtxt, NllRegionVariableOrigin, RegionVariableOrigin};
use rustc_middle::mir::{
- Body, ClosureOutlivesRequirement, ClosureOutlivesSubject, ClosureRegionRequirements,
- ConstraintCategory, Local, Location, ReturnConstraint, TerminatorKind,
+ Body, ClosureOutlivesRequirement, ClosureOutlivesSubject, ClosureOutlivesSubjectTy,
+ ClosureRegionRequirements, ConstraintCategory, Local, Location, ReturnConstraint,
+ TerminatorKind,
};
use rustc_middle::traits::ObligationCause;
use rustc_middle::traits::ObligationCauseCode;
-use rustc_middle::ty::{self, RegionVid, Ty, TyCtxt, TypeFoldable, TypeVisitable};
+use rustc_middle::ty::{self, RegionVid, Ty, TyCtxt, TypeFoldable, TypeVisitableExt};
use rustc_span::Span;
use crate::{
@@ -35,6 +35,7 @@ use crate::{
},
type_check::{free_region_relations::UniversalRegionRelations, Locations},
universal_regions::UniversalRegions,
+ BorrowckInferCtxt,
};
mod dump_mir;
@@ -244,6 +245,70 @@ pub enum ExtraConstraintInfo {
PlaceholderFromPredicate(Span),
}
+#[instrument(skip(infcx, sccs), level = "debug")]
+fn sccs_info<'cx, 'tcx>(
+ infcx: &'cx BorrowckInferCtxt<'cx, 'tcx>,
+ sccs: Rc<Sccs<RegionVid, ConstraintSccIndex>>,
+) {
+ use crate::renumber::RegionCtxt;
+
+ let var_to_origin = infcx.reg_var_to_origin.borrow();
+
+ let mut var_to_origin_sorted = var_to_origin.clone().into_iter().collect::<Vec<_>>();
+ var_to_origin_sorted.sort_by(|a, b| a.0.cmp(&b.0));
+ let mut debug_str = "region variables to origins:\n".to_string();
+ for (reg_var, origin) in var_to_origin_sorted.into_iter() {
+ debug_str.push_str(&format!("{:?}: {:?}\n", reg_var, origin));
+ }
+ debug!(debug_str);
+
+ let num_components = sccs.scc_data().ranges().len();
+ let mut components = vec![FxHashSet::default(); num_components];
+
+ for (reg_var_idx, scc_idx) in sccs.scc_indices().iter().enumerate() {
+ let reg_var = ty::RegionVid::from_usize(reg_var_idx);
+ let origin = var_to_origin.get(&reg_var).unwrap_or_else(|| &RegionCtxt::Unknown);
+ components[scc_idx.as_usize()].insert((reg_var, *origin));
+ }
+
+ let mut components_str = "strongly connected components:".to_string();
+ for (scc_idx, reg_vars_origins) in components.iter().enumerate() {
+ let regions_info = reg_vars_origins.clone().into_iter().collect::<Vec<_>>();
+ components_str.push_str(&format!(
+ "{:?}: {:?})",
+ ConstraintSccIndex::from_usize(scc_idx),
+ regions_info,
+ ))
+ }
+ debug!(components_str);
+
+ // calculate the best representative for each component
+ let components_representatives = components
+ .into_iter()
+ .enumerate()
+ .map(|(scc_idx, region_ctxts)| {
+ let repr = region_ctxts
+ .into_iter()
+ .map(|reg_var_origin| reg_var_origin.1)
+ .max_by(|x, y| x.preference_value().cmp(&y.preference_value()))
+ .unwrap();
+
+ (ConstraintSccIndex::from_usize(scc_idx), repr)
+ })
+ .collect::<FxHashMap<_, _>>();
+
+ let mut scc_node_to_edges = FxHashMap::default();
+ for (scc_idx, repr) in components_representatives.iter() {
+ let edges_range = sccs.scc_data().ranges()[*scc_idx].clone();
+ let edges = &sccs.scc_data().all_successors()[edges_range];
+ let edge_representatives =
+ edges.iter().map(|scc_idx| components_representatives[scc_idx]).collect::<Vec<_>>();
+ scc_node_to_edges.insert((scc_idx, repr), edge_representatives);
+ }
+
+ debug!("SCC edges {:#?}", scc_node_to_edges);
+}
+
impl<'tcx> RegionInferenceContext<'tcx> {
/// Creates a new region inference context with a total of
/// `num_region_variables` valid inference variables; the first N
@@ -252,7 +317,8 @@ impl<'tcx> RegionInferenceContext<'tcx> {
///
/// The `outlives_constraints` and `type_tests` are an initial set
/// of constraints produced by the MIR type check.
- pub(crate) fn new(
+ pub(crate) fn new<'cx>(
+ _infcx: &BorrowckInferCtxt<'cx, 'tcx>,
var_infos: VarInfos,
universal_regions: Rc<UniversalRegions<'tcx>>,
placeholder_indices: Rc<PlaceholderIndices>,
@@ -264,6 +330,11 @@ impl<'tcx> RegionInferenceContext<'tcx> {
liveness_constraints: LivenessValues<RegionVid>,
elements: &Rc<RegionValueElements>,
) -> Self {
+ debug!("universal_regions: {:#?}", universal_regions);
+ debug!("outlives constraints: {:#?}", outlives_constraints);
+ debug!("placeholder_indices: {:#?}", placeholder_indices);
+ debug!("type tests: {:#?}", type_tests);
+
// Create a RegionDefinition for each inference variable.
let definitions: IndexVec<_, _> = var_infos
.iter()
@@ -275,6 +346,10 @@ impl<'tcx> RegionInferenceContext<'tcx> {
let fr_static = universal_regions.fr_static;
let constraint_sccs = Rc::new(constraints.compute_sccs(&constraint_graph, fr_static));
+ if cfg!(debug_assertions) {
+ sccs_info(_infcx, constraint_sccs.clone());
+ }
+
let mut scc_values =
RegionValues::new(elements, universal_regions.len(), &placeholder_indices);
@@ -747,20 +822,33 @@ impl<'tcx> RegionInferenceContext<'tcx> {
}
debug!(?choice_regions, "after ub");
- // If we ruled everything out, we're done.
- if choice_regions.is_empty() {
- return false;
- }
-
- // Otherwise, we need to find the minimum remaining choice, if
- // any, and take that.
- debug!("choice_regions remaining are {:#?}", choice_regions);
- let Some(&min_choice) = choice_regions.iter().find(|&r1| {
+ // At this point we can pick any member of `choice_regions`, but to avoid potential
+ // non-determinism we will pick the *unique minimum* choice.
+ //
+ // Because universal regions are only partially ordered (i.e, not every two regions are
+ // comparable), we will ignore any region that doesn't compare to all others when picking
+ // the minimum choice.
+ // For example, consider `choice_regions = ['static, 'a, 'b, 'c, 'd, 'e]`, where
+ // `'static: 'a, 'static: 'b, 'a: 'c, 'b: 'c, 'c: 'd, 'c: 'e`.
+ // `['d, 'e]` are ignored because they do not compare - the same goes for `['a, 'b]`.
+ let totally_ordered_subset = choice_regions.iter().copied().filter(|&r1| {
choice_regions.iter().all(|&r2| {
- self.universal_region_relations.outlives(r2, *r1)
+ self.universal_region_relations.outlives(r1, r2)
+ || self.universal_region_relations.outlives(r2, r1)
})
+ });
+ // Now we're left with `['static, 'c]`. Pick `'c` as the minimum!
+ let Some(min_choice) = totally_ordered_subset.reduce(|r1, r2| {
+ let r1_outlives_r2 = self.universal_region_relations.outlives(r1, r2);
+ let r2_outlives_r1 = self.universal_region_relations.outlives(r2, r1);
+ match (r1_outlives_r2, r2_outlives_r1) {
+ (true, true) => r1.min(r2),
+ (true, false) => r2,
+ (false, true) => r1,
+ (false, false) => bug!("incomparable regions in total order"),
+ }
}) else {
- debug!("no choice region outlived by all others");
+ debug!("no unique minimum choice");
return false;
};
@@ -802,7 +890,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
/// from a universe it can't name; at present, the only way for
/// this to be true is if `scc` outlives `'static`. This is
/// actually stricter than necessary: ideally, we'd support bounds
- /// like `for<'a: 'b`>` that might then allow us to approximate
+ /// like `for<'a: 'b>` that might then allow us to approximate
/// `'a` with `'b` and not `'static`. But it will have to do for
/// now.
fn add_incompatible_universe(&mut self, scc: ConstraintSccIndex) {
@@ -997,18 +1085,10 @@ impl<'tcx> RegionInferenceContext<'tcx> {
true
}
- /// When we promote a type test `T: 'r`, we have to convert the
- /// type `T` into something we can store in a query result (so
- /// something allocated for `'tcx`). This is problematic if `ty`
- /// contains regions. During the course of NLL region checking, we
- /// will have replaced all of those regions with fresh inference
- /// variables. To create a test subject, we want to replace those
- /// inference variables with some region from the closure
- /// signature -- this is not always possible, so this is a
- /// fallible process. Presuming we do find a suitable region, we
- /// will use it's *external name*, which will be a `RegionKind`
- /// variant that can be used in query responses such as
- /// `ReEarlyBound`.
+ /// When we promote a type test `T: 'r`, we have to replace all region
+ /// variables in the type `T` with an equal universal region from the
+ /// closure signature.
+ /// This is not always possible, so this is a fallible process.
#[instrument(level = "debug", skip(self, infcx))]
fn try_promote_type_test_subject(
&self,
@@ -1017,91 +1097,63 @@ impl<'tcx> RegionInferenceContext<'tcx> {
) -> Option<ClosureOutlivesSubject<'tcx>> {
let tcx = infcx.tcx;
+ // Opaque types' substs may include useless lifetimes.
+ // We will replace them with ReStatic.
+ struct OpaqueFolder<'tcx> {
+ tcx: TyCtxt<'tcx>,
+ }
+ impl<'tcx> ty::TypeFolder<TyCtxt<'tcx>> for OpaqueFolder<'tcx> {
+ fn interner(&self) -> TyCtxt<'tcx> {
+ self.tcx
+ }
+ fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
+ use ty::TypeSuperFoldable as _;
+ let tcx = self.tcx;
+ let &ty::Alias(ty::Opaque, ty::AliasTy { substs, def_id, .. }) = t.kind() else {
+ return t.super_fold_with(self);
+ };
+ let substs =
+ std::iter::zip(substs, tcx.variances_of(def_id)).map(|(arg, v)| {
+ match (arg.unpack(), v) {
+ (ty::GenericArgKind::Lifetime(_), ty::Bivariant) => {
+ tcx.lifetimes.re_static.into()
+ }
+ _ => arg.fold_with(self),
+ }
+ });
+ tcx.mk_opaque(def_id, tcx.mk_substs_from_iter(substs))
+ }
+ }
+
+ let ty = ty.fold_with(&mut OpaqueFolder { tcx });
+
let ty = tcx.fold_regions(ty, |r, _depth| {
- let region_vid = self.to_region_vid(r);
+ let r_vid = self.to_region_vid(r);
+ let r_scc = self.constraint_sccs.scc(r_vid);
// The challenge if this. We have some region variable `r`
// whose value is a set of CFG points and universal
// regions. We want to find if that set is *equivalent* to
// any of the named regions found in the closure.
- //
- // To do so, we compute the
- // `non_local_universal_upper_bound`. This will be a
- // non-local, universal region that is greater than `r`.
- // However, it might not be *contained* within `r`, so
- // then we further check whether this bound is contained
- // in `r`. If so, we can say that `r` is equivalent to the
- // bound.
- //
- // Let's work through a few examples. For these, imagine
- // that we have 3 non-local regions (I'll denote them as
- // `'static`, `'a`, and `'b`, though of course in the code
- // they would be represented with indices) where:
- //
- // - `'static: 'a`
- // - `'static: 'b`
- //
- // First, let's assume that `r` is some existential
- // variable with an inferred value `{'a, 'static}` (plus
- // some CFG nodes). In this case, the non-local upper
- // bound is `'static`, since that outlives `'a`. `'static`
- // is also a member of `r` and hence we consider `r`
- // equivalent to `'static` (and replace it with
- // `'static`).
- //
- // Now let's consider the inferred value `{'a, 'b}`. This
- // means `r` is effectively `'a | 'b`. I'm not sure if
- // this can come about, actually, but assuming it did, we
- // would get a non-local upper bound of `'static`. Since
- // `'static` is not contained in `r`, we would fail to
- // find an equivalent.
- let upper_bound = self.non_local_universal_upper_bound(region_vid);
- if self.region_contains(region_vid, upper_bound) {
- self.definitions[upper_bound].external_name.unwrap_or(r)
- } else {
- // In the case of a failure, use a `ReVar` result. This will
- // cause the `needs_infer` later on to return `None`.
- r
- }
+ // To do so, we simply check every candidate `u_r` for equality.
+ self.scc_values
+ .universal_regions_outlived_by(r_scc)
+ .filter(|&u_r| !self.universal_regions.is_local_free_region(u_r))
+ .find(|&u_r| self.eval_equal(u_r, r_vid))
+ .map(|u_r| tcx.mk_re_var(u_r))
+ // In the case of a failure, use `ReErased`. We will eventually
+ // return `None` in this case.
+ .unwrap_or(tcx.lifetimes.re_erased)
});
debug!("try_promote_type_test_subject: folded ty = {:?}", ty);
- // `needs_infer` will only be true if we failed to promote some region.
- if ty.needs_infer() {
+ // This will be true if we failed to promote some region.
+ if ty.has_erased_regions() {
return None;
}
- Some(ClosureOutlivesSubject::Ty(ty))
- }
-
- /// Given some universal or existential region `r`, finds a
- /// non-local, universal region `r+` that outlives `r` at entry to (and
- /// exit from) the closure. In the worst case, this will be
- /// `'static`.
- ///
- /// This is used for two purposes. First, if we are propagated
- /// some requirement `T: r`, we can use this method to enlarge `r`
- /// to something we can encode for our creator (which only knows
- /// about non-local, universal regions). It is also used when
- /// encoding `T` as part of `try_promote_type_test_subject` (see
- /// that fn for details).
- ///
- /// This is based on the result `'y` of `universal_upper_bound`,
- /// except that it converts further takes the non-local upper
- /// bound of `'y`, so that the final result is non-local.
- fn non_local_universal_upper_bound(&self, r: RegionVid) -> RegionVid {
- debug!("non_local_universal_upper_bound(r={:?}={})", r, self.region_value_str(r));
-
- let lub = self.universal_upper_bound(r);
-
- // Grow further to get smallest universal region known to
- // creator.
- let non_local_lub = self.universal_region_relations.non_local_upper_bound(lub);
-
- debug!("non_local_universal_upper_bound: non_local_lub={:?}", non_local_lub);
-
- non_local_lub
+ Some(ClosureOutlivesSubject::Ty(ClosureOutlivesSubjectTy::bind(tcx, ty)))
}
/// Returns a universally quantified region that outlives the
@@ -1279,13 +1331,13 @@ impl<'tcx> RegionInferenceContext<'tcx> {
/// we use this kind of hacky solution.
fn normalize_to_scc_representatives<T>(&self, tcx: TyCtxt<'tcx>, value: T) -> T
where
- T: TypeFoldable<'tcx>,
+ T: TypeFoldable<TyCtxt<'tcx>>,
{
tcx.fold_regions(value, |r, _db| {
let vid = self.to_region_vid(r);
let scc = self.constraint_sccs.scc(vid);
let repr = self.scc_representatives[scc];
- tcx.mk_region(ty::ReVar(repr))
+ tcx.mk_re_var(repr)
})
}
@@ -1707,7 +1759,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
}
// If not, report an error.
- let member_region = infcx.tcx.mk_region(ty::ReVar(member_region_vid));
+ let member_region = infcx.tcx.mk_re_var(member_region_vid);
errors_buffer.push(RegionErrorKind::UnexpectedHiddenRegion {
span: m_c.definition_span,
hidden_ty: m_c.hidden_ty,
@@ -2022,7 +2074,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
.map(|constraint| BlameConstraint {
category: constraint.category,
from_closure: constraint.from_closure,
- cause: ObligationCause::new(constraint.span, CRATE_HIR_ID, cause_code.clone()),
+ cause: ObligationCause::new(constraint.span, CRATE_DEF_ID, cause_code.clone()),
variance_info: constraint.variance_info,
outlives_constraint: *constraint,
})
diff --git a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs
index db5a67a8b..c550e37c6 100644
--- a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs
+++ b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs
@@ -1,12 +1,13 @@
use rustc_data_structures::fx::{FxHashMap, FxIndexSet};
use rustc_data_structures::vec_map::VecMap;
+use rustc_errors::ErrorGuaranteed;
use rustc_hir::def_id::LocalDefId;
use rustc_hir::OpaqueTyOrigin;
use rustc_infer::infer::TyCtxtInferExt as _;
use rustc_infer::infer::{DefiningAnchor, InferCtxt};
use rustc_infer::traits::{Obligation, ObligationCause};
use rustc_middle::ty::subst::{GenericArgKind, InternalSubsts};
-use rustc_middle::ty::visit::TypeVisitable;
+use rustc_middle::ty::visit::TypeVisitableExt;
use rustc_middle::ty::{self, OpaqueHiddenType, OpaqueTypeKey, Ty, TyCtxt, TypeFoldable};
use rustc_span::Span;
use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt as _;
@@ -91,11 +92,10 @@ impl<'tcx> RegionInferenceContext<'tcx> {
}
None => {
subst_regions.push(vid);
- infcx.tcx.sess.delay_span_bug(
+ infcx.tcx.mk_re_error_with_message(
concrete_type.span,
"opaque type with non-universal region substs",
- );
- infcx.tcx.lifetimes.re_static
+ )
}
}
};
@@ -150,13 +150,13 @@ impl<'tcx> RegionInferenceContext<'tcx> {
// once we convert the generic parameters to those of the opaque type.
if let Some(prev) = result.get_mut(&opaque_type_key.def_id) {
if prev.ty != ty {
- if !ty.references_error() {
+ let guar = ty.error_reported().err().unwrap_or_else(|| {
prev.report_mismatch(
&OpaqueHiddenType { ty, span: concrete_type.span },
infcx.tcx,
- );
- }
- prev.ty = infcx.tcx.ty_error();
+ )
+ });
+ prev.ty = infcx.tcx.ty_error(guar);
}
// Pick a better span if there is one.
// FIXME(oli-obk): collect multiple spans for better diagnostics down the road.
@@ -179,7 +179,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
/// region names in error messages.
pub(crate) fn name_regions<T>(&self, tcx: TyCtxt<'tcx>, ty: T) -> T
where
- T: TypeFoldable<'tcx>,
+ T: TypeFoldable<TyCtxt<'tcx>>,
{
tcx.fold_regions(ty, |region, _| match *region {
ty::ReVar(vid) => {
@@ -248,20 +248,20 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> {
origin: OpaqueTyOrigin,
) -> Ty<'tcx> {
if let Some(e) = self.tainted_by_errors() {
- return self.tcx.ty_error_with_guaranteed(e);
+ return self.tcx.ty_error(e);
}
let definition_ty = instantiated_ty
.remap_generic_params_to_declaration_params(opaque_type_key, self.tcx, false)
.ty;
- if !check_opaque_type_parameter_valid(
+ if let Err(guar) = check_opaque_type_parameter_valid(
self.tcx,
opaque_type_key,
origin,
instantiated_ty.span,
) {
- return self.tcx.ty_error();
+ return self.tcx.ty_error(guar);
}
// Only check this for TAIT. RPIT already supports `tests/ui/impl-trait/nested-return-type2.rs`
@@ -273,9 +273,9 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> {
// This logic duplicates most of `check_opaque_meets_bounds`.
// FIXME(oli-obk): Also do region checks here and then consider removing `check_opaque_meets_bounds` entirely.
let param_env = self.tcx.param_env(def_id);
- let body_id = self.tcx.local_def_id_to_hir_id(def_id);
// HACK This bubble is required for this tests to pass:
- // type-alias-impl-trait/issue-67844-nested-opaque.rs
+ // nested-return-type2-tait2.rs
+ // nested-return-type2-tait3.rs
let infcx =
self.tcx.infer_ctxt().with_opaque_type_inference(DefiningAnchor::Bubble).build();
let ocx = ObligationCtxt::new(&infcx);
@@ -290,7 +290,7 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> {
// the bounds that the function supplies.
let opaque_ty = self.tcx.mk_opaque(def_id.to_def_id(), id_substs);
if let Err(err) = ocx.eq(
- &ObligationCause::misc(instantiated_ty.span, body_id),
+ &ObligationCause::misc(instantiated_ty.span, def_id),
param_env,
opaque_ty,
definition_ty,
@@ -298,7 +298,7 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> {
infcx
.err_ctxt()
.report_mismatched_types(
- &ObligationCause::misc(instantiated_ty.span, body_id),
+ &ObligationCause::misc(instantiated_ty.span, def_id),
opaque_ty,
definition_ty,
err,
@@ -309,7 +309,7 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> {
ocx.register_obligation(Obligation::misc(
infcx.tcx,
instantiated_ty.span,
- body_id,
+ def_id,
param_env,
predicate,
));
@@ -326,7 +326,7 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> {
definition_ty
} else {
let reported = infcx.err_ctxt().report_fulfillment_errors(&errors, None);
- self.tcx.ty_error_with_guaranteed(reported)
+ self.tcx.ty_error(reported)
}
}
}
@@ -336,7 +336,7 @@ fn check_opaque_type_parameter_valid(
opaque_type_key: OpaqueTypeKey<'_>,
origin: OpaqueTyOrigin,
span: Span,
-) -> bool {
+) -> Result<(), ErrorGuaranteed> {
match origin {
// No need to check return position impl trait (RPIT)
// because for type and const parameters they are correct
@@ -359,7 +359,7 @@ fn check_opaque_type_parameter_valid(
// fn foo<l0..'ln>() -> foo::<'static..'static>::Foo<'l0..'lm>.
//
// which would error here on all of the `'static` args.
- OpaqueTyOrigin::FnReturn(..) | OpaqueTyOrigin::AsyncFn(..) => return true,
+ OpaqueTyOrigin::FnReturn(..) | OpaqueTyOrigin::AsyncFn(..) => return Ok(()),
// Check these
OpaqueTyOrigin::TyAlias => {}
}
@@ -368,18 +368,6 @@ fn check_opaque_type_parameter_valid(
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) if lt.is_static() => {
- 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(_))
}
@@ -392,13 +380,13 @@ fn check_opaque_type_parameter_valid(
// Prevent `fn foo() -> Foo<u32>` from being defining.
let opaque_param = opaque_generics.param_at(i, tcx);
let kind = opaque_param.kind.descr();
- tcx.sess.emit_err(NonGenericOpaqueTypeParam {
+
+ return Err(tcx.sess.emit_err(NonGenericOpaqueTypeParam {
ty: arg,
kind,
span,
param_span: tcx.def_span(opaque_param.def_id),
- });
- return false;
+ }));
}
}
@@ -409,12 +397,13 @@ fn check_opaque_type_parameter_valid(
.into_iter()
.map(|i| tcx.def_span(opaque_generics.param_at(i, tcx).def_id))
.collect();
- tcx.sess
+ return Err(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;
+ .emit());
}
}
- true
+
+ Ok(())
}
diff --git a/compiler/rustc_borrowck/src/region_infer/values.rs b/compiler/rustc_borrowck/src/region_infer/values.rs
index c3dfeedc2..8132800f1 100644
--- a/compiler/rustc_borrowck/src/region_infer/values.rs
+++ b/compiler/rustc_borrowck/src/region_infer/values.rs
@@ -181,12 +181,13 @@ impl<N: Idx> LivenessValues<N> {
/// Maps from `ty::PlaceholderRegion` values that are used in the rest of
/// rustc to the internal `PlaceholderIndex` values that are used in
/// NLL.
-#[derive(Default)]
+#[derive(Debug, Default)]
pub(crate) struct PlaceholderIndices {
indices: FxIndexSet<ty::PlaceholderRegion>,
}
impl PlaceholderIndices {
+ /// Returns the `PlaceholderIndex` for the inserted `PlaceholderRegion`
pub(crate) fn insert(&mut self, placeholder: ty::PlaceholderRegion) -> PlaceholderIndex {
let (index, _) = self.indices.insert_full(placeholder);
index.into()
@@ -234,7 +235,7 @@ pub(crate) struct RegionValues<N: Idx> {
free_regions: SparseBitMatrix<N, RegionVid>,
/// Placeholders represent bound regions -- so something like `'a`
- /// in for<'a> fn(&'a u32)`.
+ /// in `for<'a> fn(&'a u32)`.
placeholders: SparseBitMatrix<N, PlaceholderIndex>,
}
diff --git a/compiler/rustc_borrowck/src/renumber.rs b/compiler/rustc_borrowck/src/renumber.rs
index 084754830..016f6f78d 100644
--- a/compiler/rustc_borrowck/src/renumber.rs
+++ b/compiler/rustc_borrowck/src/renumber.rs
@@ -1,18 +1,20 @@
#![deny(rustc::untranslatable_diagnostic)]
#![deny(rustc::diagnostic_outside_of_impl)]
+use crate::BorrowckInferCtxt;
use rustc_index::vec::IndexVec;
-use rustc_infer::infer::{InferCtxt, NllRegionVariableOrigin};
+use rustc_infer::infer::NllRegionVariableOrigin;
use rustc_middle::mir::visit::{MutVisitor, TyContext};
use rustc_middle::mir::Constant;
use rustc_middle::mir::{Body, Location, Promoted};
use rustc_middle::ty::subst::SubstsRef;
use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable};
+use rustc_span::{Span, Symbol};
/// 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>,
+ infcx: &BorrowckInferCtxt<'_, 'tcx>,
body: &mut Body<'tcx>,
promoted: &mut IndexVec<Promoted, Body<'tcx>>,
) {
@@ -29,27 +31,68 @@ 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
+#[instrument(skip(infcx, get_ctxt_fn), level = "debug")]
+pub(crate) fn renumber_regions<'tcx, T, F>(
+ infcx: &BorrowckInferCtxt<'_, 'tcx>,
+ value: T,
+ get_ctxt_fn: F,
+) -> T
where
- T: TypeFoldable<'tcx>,
+ T: TypeFoldable<TyCtxt<'tcx>>,
+ F: Fn() -> RegionCtxt,
{
infcx.tcx.fold_regions(value, |_region, _depth| {
let origin = NllRegionVariableOrigin::Existential { from_forall: false };
- infcx.next_nll_region_var(origin)
+ infcx.next_nll_region_var(origin, || get_ctxt_fn())
})
}
+#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
+pub(crate) enum BoundRegionInfo {
+ Name(Symbol),
+ Span(Span),
+}
+
+#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
+pub(crate) enum RegionCtxt {
+ Location(Location),
+ TyContext(TyContext),
+ Free(Symbol),
+ Bound(BoundRegionInfo),
+ LateBound(BoundRegionInfo),
+ Existential(Option<Symbol>),
+ Placeholder(BoundRegionInfo),
+ Unknown,
+}
+
+impl RegionCtxt {
+ /// Used to determine the representative of a component in the strongly connected
+ /// constraint graph
+ pub(crate) fn preference_value(self) -> usize {
+ let _anon = Symbol::intern("anon");
+
+ match self {
+ RegionCtxt::Unknown => 1,
+ RegionCtxt::Existential(None) => 2,
+ RegionCtxt::Existential(Some(_anon)) | RegionCtxt::Free(_anon) => 2,
+ RegionCtxt::Location(_) => 3,
+ RegionCtxt::TyContext(_) => 4,
+ _ => 5,
+ }
+ }
+}
+
struct NllVisitor<'a, 'tcx> {
- infcx: &'a InferCtxt<'tcx>,
+ infcx: &'a BorrowckInferCtxt<'a, 'tcx>,
}
impl<'a, 'tcx> NllVisitor<'a, 'tcx> {
- fn renumber_regions<T>(&mut self, value: T) -> T
+ fn renumber_regions<T, F>(&mut self, value: T, region_ctxt_fn: F) -> T
where
- T: TypeFoldable<'tcx>,
+ T: TypeFoldable<TyCtxt<'tcx>>,
+ F: Fn() -> RegionCtxt,
{
- renumber_regions(self.infcx, value)
+ renumber_regions(self.infcx, value, region_ctxt_fn)
}
}
@@ -60,14 +103,14 @@ impl<'a, 'tcx> MutVisitor<'tcx> for NllVisitor<'a, 'tcx> {
#[instrument(skip(self), level = "debug")]
fn visit_ty(&mut self, ty: &mut Ty<'tcx>, ty_context: TyContext) {
- *ty = self.renumber_regions(*ty);
+ *ty = self.renumber_regions(*ty, || RegionCtxt::TyContext(ty_context));
debug!(?ty);
}
#[instrument(skip(self), level = "debug")]
fn visit_substs(&mut self, substs: &mut SubstsRef<'tcx>, location: Location) {
- *substs = self.renumber_regions(*substs);
+ *substs = self.renumber_regions(*substs, || RegionCtxt::Location(location));
debug!(?substs);
}
@@ -75,7 +118,7 @@ impl<'a, 'tcx> MutVisitor<'tcx> for NllVisitor<'a, 'tcx> {
#[instrument(skip(self), level = "debug")]
fn visit_region(&mut self, region: &mut ty::Region<'tcx>, location: Location) {
let old_region = *region;
- *region = self.renumber_regions(old_region);
+ *region = self.renumber_regions(old_region, || RegionCtxt::Location(location));
debug!(?region);
}
@@ -83,7 +126,7 @@ impl<'a, 'tcx> MutVisitor<'tcx> for NllVisitor<'a, 'tcx> {
#[instrument(skip(self), level = "debug")]
fn visit_constant(&mut self, constant: &mut Constant<'tcx>, _location: Location) {
let literal = constant.literal;
- constant.literal = self.renumber_regions(literal);
+ constant.literal = self.renumber_regions(literal, || RegionCtxt::Location(_location));
debug!("constant: {:#?}", constant);
}
}
diff --git a/compiler/rustc_borrowck/src/session_diagnostics.rs b/compiler/rustc_borrowck/src/session_diagnostics.rs
index 23acf1592..a36789290 100644
--- a/compiler/rustc_borrowck/src/session_diagnostics.rs
+++ b/compiler/rustc_borrowck/src/session_diagnostics.rs
@@ -1,4 +1,4 @@
-use rustc_errors::{IntoDiagnosticArg, MultiSpan};
+use rustc_errors::MultiSpan;
use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic};
use rustc_middle::ty::{GenericArg, Ty};
use rustc_span::Span;
@@ -55,7 +55,7 @@ pub(crate) struct VarNeedNotMut {
#[derive(Diagnostic)]
#[diag(borrowck_var_cannot_escape_closure)]
#[note]
-#[note(cannot_escape)]
+#[note(borrowck_cannot_escape)]
pub(crate) struct FnMutError {
#[primary_span]
pub span: Span,
@@ -128,18 +128,6 @@ pub(crate) enum LifetimeReturnCategoryErr<'a> {
},
}
-impl IntoDiagnosticArg for &RegionName {
- fn into_diagnostic_arg(self) -> rustc_errors::DiagnosticArgValue<'static> {
- format!("{}", self).into_diagnostic_arg()
- }
-}
-
-impl IntoDiagnosticArg for RegionName {
- fn into_diagnostic_arg(self) -> rustc_errors::DiagnosticArgValue<'static> {
- format!("{}", self).into_diagnostic_arg()
- }
-}
-
#[derive(Subdiagnostic)]
pub(crate) enum RequireStaticErr {
#[note(borrowck_used_impl_require_static)]
@@ -235,7 +223,7 @@ pub(crate) struct MoveBorrow<'a> {
pub borrow_place: &'a str,
pub value_place: &'a str,
#[primary_span]
- #[label(move_label)]
+ #[label(borrowck_move_label)]
pub span: Span,
#[label]
pub borrow_span: Span,
diff --git a/compiler/rustc_borrowck/src/type_check/canonical.rs b/compiler/rustc_borrowck/src/type_check/canonical.rs
index 11729e2c8..b27d5d205 100644
--- a/compiler/rustc_borrowck/src/type_check/canonical.rs
+++ b/compiler/rustc_borrowck/src/type_check/canonical.rs
@@ -2,7 +2,7 @@ use std::fmt;
use rustc_infer::infer::{canonical::Canonical, InferOk};
use rustc_middle::mir::ConstraintCategory;
-use rustc_middle::ty::{self, ToPredicate, Ty, TypeFoldable};
+use rustc_middle::ty::{self, ToPredicate, Ty, TyCtxt, TypeFoldable};
use rustc_span::def_id::DefId;
use rustc_span::Span;
use rustc_trait_selection::traits::query::type_op::{self, TypeOpOutput};
@@ -66,7 +66,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
canonical: &Canonical<'tcx, T>,
) -> T
where
- T: TypeFoldable<'tcx>,
+ T: TypeFoldable<TyCtxt<'tcx>>,
{
let old_universe = self.infcx.universe();
@@ -117,7 +117,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
pub(super) fn prove_predicates(
&mut self,
- predicates: impl IntoIterator<Item = impl ToPredicate<'tcx> + std::fmt::Debug>,
+ predicates: impl IntoIterator<Item: ToPredicate<'tcx> + std::fmt::Debug>,
locations: Locations,
category: ConstraintCategory<'tcx>,
) {
@@ -181,9 +181,6 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
user_ty: ty::UserType<'tcx>,
span: Span,
) {
- // FIXME: Ideally MIR types are normalized, but this is not always true.
- let mir_ty = self.normalize(mir_ty, Locations::All(span));
-
self.fully_perform_op(
Locations::All(span),
ConstraintCategory::Boring,
@@ -217,7 +214,9 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
return;
}
+ // FIXME: Ideally MIR types are normalized, but this is not always true.
let mir_ty = self.normalize(mir_ty, Locations::All(span));
+
let cause = ObligationCause::dummy_with_span(span);
let param_env = self.param_env;
let op = |infcx: &'_ _| {
diff --git a/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs b/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs
index e15d1b99a..a93561350 100644
--- a/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs
+++ b/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs
@@ -6,8 +6,8 @@ use rustc_infer::infer::region_constraints::{GenericKind, VerifyBound};
use rustc_infer::infer::{self, InferCtxt, SubregionOrigin};
use rustc_middle::mir::{ClosureOutlivesSubject, ClosureRegionRequirements, ConstraintCategory};
use rustc_middle::ty::subst::GenericArgKind;
-use rustc_middle::ty::TypeFoldable;
use rustc_middle::ty::{self, TyCtxt};
+use rustc_middle::ty::{TypeFoldable, TypeVisitableExt};
use rustc_span::{Span, DUMMY_SP};
use crate::{
@@ -83,16 +83,8 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> {
}
self.constraints.member_constraints = tmp;
- for (predicate, constraint_category) in outlives {
- // At the moment, we never generate any "higher-ranked"
- // region constraints like `for<'a> 'a: 'b`. At some point
- // when we move to universes, we will, and this assertion
- // will start to fail.
- let predicate = predicate.no_bound_vars().unwrap_or_else(|| {
- bug!("query_constraint {:?} contained bound vars", predicate,);
- });
-
- self.convert(predicate, *constraint_category);
+ for &(predicate, constraint_category) in outlives {
+ self.convert(predicate, constraint_category);
}
}
@@ -124,7 +116,9 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> {
let outlived_region = closure_mapping[outlives_requirement.outlived_free_region];
let subject = match outlives_requirement.subject {
ClosureOutlivesSubject::Region(re) => closure_mapping[re].into(),
- ClosureOutlivesSubject::Ty(ty) => ty.into(),
+ ClosureOutlivesSubject::Ty(subject_ty) => {
+ subject_ty.instantiate(self.tcx, |vid| closure_mapping[vid]).into()
+ }
};
self.category = outlives_requirement.category;
@@ -179,7 +173,7 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> {
///
/// FIXME: This should get removed once higher ranked region obligations
/// are dealt with during trait solving.
- fn replace_placeholders_with_nll<T: TypeFoldable<'tcx>>(&mut self, value: T) -> T {
+ fn replace_placeholders_with_nll<T: TypeFoldable<TyCtxt<'tcx>>>(&mut self, value: T) -> T {
if value.has_placeholders() {
self.tcx.fold_regions(value, |r, _| match *r {
ty::RePlaceholder(placeholder) => {
diff --git a/compiler/rustc_borrowck/src/type_check/free_region_relations.rs b/compiler/rustc_borrowck/src/type_check/free_region_relations.rs
index 82ff86247..4004966c4 100644
--- a/compiler/rustc_borrowck/src/type_check/free_region_relations.rs
+++ b/compiler/rustc_borrowck/src/type_check/free_region_relations.rs
@@ -8,6 +8,7 @@ use rustc_infer::infer::InferCtxt;
use rustc_middle::mir::ConstraintCategory;
use rustc_middle::traits::query::OutlivesBound;
use rustc_middle::ty::{self, RegionVid, Ty};
+use rustc_span::Span;
use rustc_trait_selection::traits::query::type_op::{self, TypeOp};
use std::rc::Rc;
use type_op::TypeOpOutput;
@@ -92,31 +93,6 @@ impl UniversalRegionRelations<'_> {
res
}
- /// Returns the "postdominating" bound of the set of
- /// `non_local_upper_bounds` for the given region.
- pub(crate) fn non_local_upper_bound(&self, fr: RegionVid) -> RegionVid {
- let upper_bounds = self.non_local_upper_bounds(fr);
-
- // In case we find more than one, reduce to one for
- // convenience. This is to prevent us from generating more
- // complex constraints, but it will cause spurious errors.
- let post_dom = self.inverse_outlives.mutual_immediate_postdominator(upper_bounds);
-
- debug!("non_local_bound: post_dom={:?}", post_dom);
-
- post_dom
- .and_then(|post_dom| {
- // If the mutual immediate postdom is not local, then
- // there is no non-local result we can return.
- if !self.universal_regions.is_local_free_region(post_dom) {
- Some(post_dom)
- } else {
- None
- }
- })
- .unwrap_or(self.universal_regions.fr_static)
- }
-
/// Finds a "lower bound" for `fr` that is not local. In other
/// words, returns the largest (*) known region `fr1` that (a) is
/// outlived by `fr` and (b) is not local.
@@ -217,8 +193,27 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> {
self.inverse_outlives.add(fr_b, fr_a);
}
+ #[instrument(level = "debug", skip(self))]
pub(crate) fn create(mut self) -> CreateResult<'tcx> {
let span = self.infcx.tcx.def_span(self.universal_regions.defining_ty.def_id());
+
+ // Insert the facts we know from the predicates. Why? Why not.
+ let param_env = self.param_env;
+ self.add_outlives_bounds(outlives::explicit_outlives_bounds(param_env));
+
+ // - outlives is reflexive, so `'r: 'r` for every region `'r`
+ // - `'static: 'r` for every region `'r`
+ // - `'r: 'fn_body` for every (other) universally quantified
+ // region `'r`, all of which are provided by our caller
+ let fr_static = self.universal_regions.fr_static;
+ let fr_fn_body = self.universal_regions.fr_fn_body;
+ for fr in self.universal_regions.universal_regions() {
+ debug!("build: relating free region {:?} to itself and to 'static", fr);
+ self.relate_universal_regions(fr, fr);
+ self.relate_universal_regions(fr_static, fr);
+ self.relate_universal_regions(fr, fr_fn_body);
+ }
+
let unnormalized_input_output_tys = self
.universal_regions
.unnormalized_input_tys
@@ -236,78 +231,59 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> {
// the `relations` is built.
let mut normalized_inputs_and_output =
Vec::with_capacity(self.universal_regions.unnormalized_input_tys.len() + 1);
- let constraint_sets: Vec<_> = unnormalized_input_output_tys
- .flat_map(|ty| {
- debug!("build: input_or_output={:?}", ty);
- // We add implied bounds from both the unnormalized and normalized ty.
- // See issue #87748
- let constraints_implied1 = self.add_implied_bounds(ty);
- let TypeOpOutput { output: norm_ty, constraints: constraints1, .. } = self
- .param_env
- .and(type_op::normalize::Normalize::new(ty))
- .fully_perform(self.infcx)
- .unwrap_or_else(|_| {
- let reported = self
- .infcx
- .tcx
- .sess
- .delay_span_bug(span, &format!("failed to normalize {:?}", ty));
- TypeOpOutput {
- output: self.infcx.tcx.ty_error_with_guaranteed(reported),
- constraints: None,
- error_info: None,
- }
- });
- // Note: we need this in examples like
- // ```
- // trait Foo {
- // type Bar;
- // fn foo(&self) -> &Self::Bar;
- // }
- // impl Foo for () {
- // type Bar = ();
- // fn foo(&self) -> &() {}
- // }
- // ```
- // Both &Self::Bar and &() are WF
- let constraints_implied2 =
- if ty != norm_ty { self.add_implied_bounds(norm_ty) } else { None };
- normalized_inputs_and_output.push(norm_ty);
- constraints1.into_iter().chain(constraints_implied1).chain(constraints_implied2)
- })
- .collect();
+ let mut constraints = vec![];
+ for ty in unnormalized_input_output_tys {
+ debug!("build: input_or_output={:?}", ty);
+ // We add implied bounds from both the unnormalized and normalized ty.
+ // See issue #87748
+ let constraints_unnorm = self.add_implied_bounds(ty);
+ if let Some(c) = constraints_unnorm {
+ constraints.push(c)
+ }
+ let TypeOpOutput { output: norm_ty, constraints: constraints_normalize, .. } = self
+ .param_env
+ .and(type_op::normalize::Normalize::new(ty))
+ .fully_perform(self.infcx)
+ .unwrap_or_else(|_| {
+ let guar = self
+ .infcx
+ .tcx
+ .sess
+ .delay_span_bug(span, &format!("failed to normalize {:?}", ty));
+ TypeOpOutput {
+ output: self.infcx.tcx.ty_error(guar),
+ constraints: None,
+ error_info: None,
+ }
+ });
+ if let Some(c) = constraints_normalize {
+ constraints.push(c)
+ }
- // Insert the facts we know from the predicates. Why? Why not.
- let param_env = self.param_env;
- self.add_outlives_bounds(outlives::explicit_outlives_bounds(param_env));
+ // Note: we need this in examples like
+ // ```
+ // trait Foo {
+ // type Bar;
+ // fn foo(&self) -> &Self::Bar;
+ // }
+ // impl Foo for () {
+ // type Bar = ();
+ // fn foo(&self) ->&() {}
+ // }
+ // ```
+ // Both &Self::Bar and &() are WF
+ if ty != norm_ty {
+ let constraints_norm = self.add_implied_bounds(norm_ty);
+ if let Some(c) = constraints_norm {
+ constraints.push(c)
+ }
+ }
- // Finally:
- // - outlives is reflexive, so `'r: 'r` for every region `'r`
- // - `'static: 'r` for every region `'r`
- // - `'r: 'fn_body` for every (other) universally quantified
- // region `'r`, all of which are provided by our caller
- let fr_static = self.universal_regions.fr_static;
- let fr_fn_body = self.universal_regions.fr_fn_body;
- for fr in self.universal_regions.universal_regions() {
- debug!("build: relating free region {:?} to itself and to 'static", fr);
- self.relate_universal_regions(fr, fr);
- self.relate_universal_regions(fr_static, fr);
- self.relate_universal_regions(fr, fr_fn_body);
+ normalized_inputs_and_output.push(norm_ty);
}
- for data in &constraint_sets {
- constraint_conversion::ConstraintConversion::new(
- self.infcx,
- &self.universal_regions,
- &self.region_bound_pairs,
- self.implicit_region_bound,
- self.param_env,
- Locations::All(span),
- span,
- ConstraintCategory::Internal,
- &mut self.constraints,
- )
- .convert_all(data);
+ for c in constraints {
+ self.push_region_constraints(c, span);
}
CreateResult {
@@ -321,6 +297,24 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> {
}
}
+ #[instrument(skip(self, data), level = "debug")]
+ fn push_region_constraints(&mut self, data: &QueryRegionConstraints<'tcx>, span: Span) {
+ debug!("constraints generated: {:#?}", data);
+
+ constraint_conversion::ConstraintConversion::new(
+ self.infcx,
+ &self.universal_regions,
+ &self.region_bound_pairs,
+ self.implicit_region_bound,
+ self.param_env,
+ Locations::All(span),
+ span,
+ ConstraintCategory::Internal,
+ &mut self.constraints,
+ )
+ .convert_all(data);
+ }
+
/// Update the type of a single local, which should represent
/// either the return type of the MIR or one of its arguments. At
/// the same time, compute and add any implied bounds that come
@@ -332,6 +326,7 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> {
.and(type_op::implied_outlives_bounds::ImpliedOutlivesBounds { ty })
.fully_perform(self.infcx)
.unwrap_or_else(|_| bug!("failed to compute implied bounds {:?}", ty));
+ debug!(?bounds, ?constraints);
self.add_outlives_bounds(bounds);
constraints
}
diff --git a/compiler/rustc_borrowck/src/type_check/input_output.rs b/compiler/rustc_borrowck/src/type_check/input_output.rs
index fa9ea769a..717020ea5 100644
--- a/compiler/rustc_borrowck/src/type_check/input_output.rs
+++ b/compiler/rustc_borrowck/src/type_check/input_output.rs
@@ -26,11 +26,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
if !self.tcx().is_closure(mir_def_id.to_def_id()) {
return;
}
- let Some(user_provided_poly_sig) =
- self.tcx().typeck(mir_def_id).user_provided_sigs.get(&mir_def_id)
- else {
- return;
- };
+ let user_provided_poly_sig = self.tcx().closure_user_provided_sig(mir_def_id);
// Instantiate the canonicalized variables from user-provided signature
// (e.g., the `_` in the code above) with fresh variables.
@@ -38,7 +34,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
// so that they represent the view from "inside" the closure.
let user_provided_sig = self
.instantiate_canonical_with_fresh_inference_vars(body.span, &user_provided_poly_sig);
- let user_provided_sig = self.infcx.replace_bound_vars_with_fresh_vars(
+ let user_provided_sig = self.infcx.instantiate_binder_with_fresh_vars(
body.span,
LateBoundRegionConversionTime::FnCall,
user_provided_sig,
diff --git a/compiler/rustc_borrowck/src/type_check/liveness/mod.rs b/compiler/rustc_borrowck/src/type_check/liveness/mod.rs
index d5c401ae1..a411aec51 100644
--- a/compiler/rustc_borrowck/src/type_check/liveness/mod.rs
+++ b/compiler/rustc_borrowck/src/type_check/liveness/mod.rs
@@ -50,13 +50,11 @@ pub(super) fn generate<'mir, 'tcx>(
compute_relevant_live_locals(typeck.tcx(), &free_regions, &body);
let facts_enabled = use_polonius || AllFacts::enabled(typeck.tcx());
- let polonius_drop_used = if facts_enabled {
+ let polonius_drop_used = facts_enabled.then(|| {
let mut drop_used = Vec::new();
polonius::populate_access_facts(typeck, body, location_table, move_data, &mut drop_used);
- Some(drop_used)
- } else {
- None
- };
+ drop_used
+ });
trace::trace(
typeck,
diff --git a/compiler/rustc_borrowck/src/type_check/liveness/trace.rs b/compiler/rustc_borrowck/src/type_check/liveness/trace.rs
index 3ff5d188a..473c05963 100644
--- a/compiler/rustc_borrowck/src/type_check/liveness/trace.rs
+++ b/compiler/rustc_borrowck/src/type_check/liveness/trace.rs
@@ -3,7 +3,7 @@ use rustc_index::bit_set::HybridBitSet;
use rustc_index::interval::IntervalSet;
use rustc_infer::infer::canonical::QueryRegionConstraints;
use rustc_middle::mir::{BasicBlock, Body, ConstraintCategory, Local, Location};
-use rustc_middle::ty::{Ty, TypeVisitable};
+use rustc_middle::ty::{Ty, TyCtxt, TypeVisitable, TypeVisitableExt};
use rustc_trait_selection::traits::query::dropck_outlives::DropckOutlivesResult;
use rustc_trait_selection::traits::query::type_op::outlives::DropckOutlives;
use rustc_trait_selection::traits::query::type_op::{TypeOp, TypeOpOutput};
@@ -477,7 +477,7 @@ impl<'tcx> LivenessContext<'_, '_, '_, 'tcx> {
/// points `live_at`.
fn add_use_live_facts_for(
&mut self,
- value: impl TypeVisitable<'tcx>,
+ value: impl TypeVisitable<TyCtxt<'tcx>>,
live_at: &IntervalSet<PointIndex>,
) {
debug!("add_use_live_facts_for(value={:?})", value);
@@ -542,7 +542,7 @@ impl<'tcx> LivenessContext<'_, '_, '_, 'tcx> {
fn make_all_regions_live(
elements: &RegionValueElements,
typeck: &mut TypeChecker<'_, 'tcx>,
- value: impl TypeVisitable<'tcx>,
+ value: impl TypeVisitable<TyCtxt<'tcx>>,
live_at: &IntervalSet<PointIndex>,
) {
debug!("make_all_regions_live(value={:?})", value);
diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs
index 81bd4c2a7..a49da3da6 100644
--- a/compiler/rustc_borrowck/src/type_check/mod.rs
+++ b/compiler/rustc_borrowck/src/type_check/mod.rs
@@ -30,7 +30,7 @@ use rustc_middle::mir::*;
use rustc_middle::ty::adjustment::PointerCast;
use rustc_middle::ty::cast::CastTy;
use rustc_middle::ty::subst::{SubstsRef, UserSubsts};
-use rustc_middle::ty::visit::TypeVisitable;
+use rustc_middle::ty::visit::TypeVisitableExt;
use rustc_middle::ty::{
self, Binder, CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations, Dynamic,
OpaqueHiddenType, OpaqueTypeKey, RegionVid, Ty, TyCtxt, UserType, UserTypeAnnotationIndex,
@@ -64,7 +64,7 @@ use crate::{
region_infer::TypeTest,
type_check::free_region_relations::{CreateResult, UniversalRegionRelations},
universal_regions::{DefiningTy, UniversalRegions},
- Upvar,
+ BorrowckInferCtxt, Upvar,
};
macro_rules! span_mirbug {
@@ -123,7 +123,7 @@ mod relate_tys;
/// - `move_data` -- move-data constructed when performing the maybe-init dataflow analysis
/// - `elements` -- MIR region map
pub(crate) fn type_check<'mir, 'tcx>(
- infcx: &InferCtxt<'tcx>,
+ infcx: &BorrowckInferCtxt<'_, 'tcx>,
param_env: ty::ParamEnv<'tcx>,
body: &Body<'tcx>,
promoted: &IndexVec<Promoted, Body<'tcx>>,
@@ -137,7 +137,7 @@ pub(crate) fn type_check<'mir, 'tcx>(
upvars: &[Upvar<'tcx>],
use_polonius: bool,
) -> MirTypeckResults<'tcx> {
- let implicit_region_bound = infcx.tcx.mk_region(ty::ReVar(universal_regions.fr_fn_body));
+ let implicit_region_bound = infcx.tcx.mk_re_var(universal_regions.fr_fn_body);
let mut constraints = MirTypeckRegionConstraints {
placeholder_indices: PlaceholderIndices::default(),
placeholder_index_to_region: IndexVec::default(),
@@ -239,7 +239,7 @@ pub(crate) fn type_check<'mir, 'tcx>(
decl.hidden_type.span,
&format!("could not resolve {:#?}", hidden_type.ty.kind()),
);
- hidden_type.ty = infcx.tcx.ty_error_with_guaranteed(reported);
+ hidden_type.ty = infcx.tcx.ty_error(reported);
}
(opaque_type_key, (hidden_type, decl.origin))
@@ -402,7 +402,7 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> {
);
}
} else if let Some(static_def_id) = constant.check_static_ptr(tcx) {
- let unnormalized_ty = tcx.type_of(static_def_id);
+ let unnormalized_ty = tcx.type_of(static_def_id).subst_identity();
let normalized_ty = self.cx.normalize(unnormalized_ty, locations);
let literal_ty = constant.literal.ty().builtin_deref(true).unwrap().ty;
@@ -529,12 +529,12 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
for elem in place.projection.iter() {
if place_ty.variant_index.is_none() {
- if place_ty.ty.references_error() {
+ if let Err(guar) = place_ty.ty.error_reported() {
assert!(self.errors_reported);
- return PlaceTy::from_ty(self.tcx().ty_error());
+ return PlaceTy::from_ty(self.tcx().ty_error(guar));
}
}
- place_ty = self.sanitize_projection(place_ty, elem, place, location);
+ place_ty = self.sanitize_projection(place_ty, elem, place, location, context);
}
if let PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy) = context {
@@ -630,12 +630,14 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
}
}
+ #[instrument(skip(self), level = "debug")]
fn sanitize_projection(
&mut self,
base: PlaceTy<'tcx>,
pi: PlaceElem<'tcx>,
place: &Place<'tcx>,
location: Location,
+ context: PlaceContext,
) -> PlaceTy<'tcx> {
debug!("sanitize_projection: {:?} {:?} {:?}", base, pi, place);
let tcx = self.tcx();
@@ -713,8 +715,11 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
match self.field_ty(place, base, field, location) {
Ok(ty) => {
let ty = self.cx.normalize(ty, location);
- if let Err(terr) = self.cx.eq_types(
+ debug!(?fty, ?ty);
+
+ if let Err(terr) = self.cx.relate_types(
ty,
+ self.get_ambient_variance(context),
fty,
location.to_locations(),
ConstraintCategory::Boring,
@@ -743,9 +748,10 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
let ty = self.sanitize_type(place, ty);
let ty = self.cx.normalize(ty, location);
self.cx
- .eq_types(
- base.ty,
+ .relate_types(
ty,
+ self.get_ambient_variance(context),
+ base.ty,
location.to_locations(),
ConstraintCategory::TypeAnnotation,
)
@@ -757,7 +763,22 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
fn error(&mut self) -> Ty<'tcx> {
self.errors_reported = true;
- self.tcx().ty_error()
+ self.tcx().ty_error_misc()
+ }
+
+ fn get_ambient_variance(&self, context: PlaceContext) -> ty::Variance {
+ use rustc_middle::mir::visit::NonMutatingUseContext::*;
+ use rustc_middle::mir::visit::NonUseContext::*;
+
+ match context {
+ PlaceContext::MutatingUse(_) => ty::Invariant,
+ PlaceContext::NonUse(StorageDead | StorageLive | VarDebugInfo) => ty::Invariant,
+ PlaceContext::NonMutatingUse(
+ Inspect | Copy | Move | SharedBorrow | ShallowBorrow | UniqueBorrow | AddressOf
+ | Projection,
+ ) => ty::Covariant,
+ PlaceContext::NonUse(AscribeUserTy) => ty::Covariant,
+ }
}
fn field_ty(
@@ -845,7 +866,7 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
/// way, it accrues region constraints -- these can later be used by
/// NLL region checking.
struct TypeChecker<'a, 'tcx> {
- infcx: &'a InferCtxt<'tcx>,
+ infcx: &'a BorrowckInferCtxt<'a, 'tcx>,
param_env: ty::ParamEnv<'tcx>,
last_span: Span,
body: &'a Body<'tcx>,
@@ -910,6 +931,8 @@ pub(crate) struct MirTypeckRegionConstraints<'tcx> {
}
impl<'tcx> MirTypeckRegionConstraints<'tcx> {
+ /// Creates a `Region` for a given `PlaceholderRegion`, or returns the
+ /// region that corresponds to a previously created one.
fn placeholder_region(
&mut self,
infcx: &InferCtxt<'tcx>,
@@ -996,7 +1019,7 @@ impl Locations {
impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
fn new(
- infcx: &'a InferCtxt<'tcx>,
+ infcx: &'a BorrowckInferCtxt<'a, 'tcx>,
body: &'a Body<'tcx>,
param_env: ty::ParamEnv<'tcx>,
region_bound_pairs: &'a RegionBoundPairs<'tcx>,
@@ -1258,6 +1281,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
| StatementKind::StorageDead(..)
| StatementKind::Retag { .. }
| StatementKind::Coverage(..)
+ | StatementKind::ConstEvalCounter
| StatementKind::Nop => {}
StatementKind::Deinit(..) | StatementKind::SetDiscriminant { .. } => {
bug!("Statement not allowed in this MIR phase")
@@ -1332,11 +1356,34 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
}
};
let (sig, map) = tcx.replace_late_bound_regions(sig, |br| {
- self.infcx.next_region_var(LateBoundRegion(
- term.source_info.span,
- br.kind,
- LateBoundRegionConversionTime::FnCall,
- ))
+ use crate::renumber::{BoundRegionInfo, RegionCtxt};
+ use rustc_span::Symbol;
+
+ let region_ctxt_fn = || {
+ let reg_info = match br.kind {
+ ty::BoundRegionKind::BrAnon(_, Some(span)) => {
+ BoundRegionInfo::Span(span)
+ }
+ ty::BoundRegionKind::BrAnon(..) => {
+ BoundRegionInfo::Name(Symbol::intern("anon"))
+ }
+ ty::BoundRegionKind::BrNamed(_, name) => BoundRegionInfo::Name(name),
+ ty::BoundRegionKind::BrEnv => {
+ BoundRegionInfo::Name(Symbol::intern("env"))
+ }
+ };
+
+ RegionCtxt::LateBound(reg_info)
+ };
+
+ self.infcx.next_region_var(
+ LateBoundRegion(
+ term.source_info.span,
+ br.kind,
+ LateBoundRegionConversionTime::FnCall,
+ ),
+ region_ctxt_fn,
+ )
});
debug!(?sig);
// IMPORTANT: We have to prove well formed for the function signature before
@@ -1483,7 +1530,10 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
}
}
None => {
- if !sig.output().is_privately_uninhabited(self.tcx(), self.param_env) {
+ // The signature in this call can reference region variables,
+ // so erase them before calling a query.
+ let output_ty = self.tcx().erase_regions(sig.output());
+ if !output_ty.is_privately_uninhabited(self.tcx(), self.param_env) {
span_mirbug!(self, term, "call to converging function {:?} w/o dest", sig);
}
}
@@ -1776,7 +1826,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
// than 1.
// If the length is larger than 1, the repeat expression will need to copy the
// element, so we require the `Copy` trait.
- if len.try_eval_usize(tcx, self.param_env).map_or(true, |len| len > 1) {
+ if len.try_eval_target_usize(tcx, self.param_env).map_or(true, |len| len > 1) {
match operand {
Operand::Copy(..) | Operand::Constant(..) => {
// These are always okay: direct use of a const, or a value that can evidently be copied.
@@ -2027,7 +2077,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
}
};
- if ty_to_mut == Mutability::Mut && ty_mut == Mutability::Not {
+ if ty_to_mut.is_mut() && ty_mut.is_not() {
span_mirbug!(
self,
rvalue,
@@ -2532,7 +2582,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
// clauses on the struct.
AggregateKind::Closure(def_id, substs)
| AggregateKind::Generator(def_id, substs, _) => {
- (def_id.to_def_id(), self.prove_closure_bounds(tcx, def_id, substs, location))
+ (def_id, self.prove_closure_bounds(tcx, def_id.expect_local(), substs, location))
}
AggregateKind::Array(_) | AggregateKind::Tuple => {
@@ -2583,7 +2633,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
DefKind::InlineConst => substs.as_inline_const().parent_substs(),
other => bug!("unexpected item {:?}", other),
};
- let parent_substs = tcx.mk_substs(parent_substs.iter());
+ let parent_substs = tcx.mk_substs(parent_substs);
assert_eq!(typeck_root_substs.len(), parent_substs.len());
if let Err(_) = self.eq_substs(
diff --git a/compiler/rustc_borrowck/src/type_check/relate_tys.rs b/compiler/rustc_borrowck/src/type_check/relate_tys.rs
index b2702eafd..d96372fb9 100644
--- a/compiler/rustc_borrowck/src/type_check/relate_tys.rs
+++ b/compiler/rustc_borrowck/src/type_check/relate_tys.rs
@@ -1,14 +1,15 @@
-use rustc_infer::infer::nll_relate::{NormalizationStrategy, TypeRelating, TypeRelatingDelegate};
+use rustc_infer::infer::nll_relate::{TypeRelating, TypeRelatingDelegate};
use rustc_infer::infer::NllRegionVariableOrigin;
use rustc_infer::traits::PredicateObligations;
use rustc_middle::mir::ConstraintCategory;
use rustc_middle::ty::relate::TypeRelation;
use rustc_middle::ty::{self, Ty};
-use rustc_span::Span;
+use rustc_span::{Span, Symbol};
use rustc_trait_selection::traits::query::Fallible;
use crate::constraints::OutlivesConstraint;
use crate::diagnostics::UniverseInfo;
+use crate::renumber::{BoundRegionInfo, RegionCtxt};
use crate::type_check::{InstantiateOpaqueType, Locations, TypeChecker};
impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
@@ -100,23 +101,65 @@ impl<'tcx> TypeRelatingDelegate<'tcx> for NllTypeRelatingDelegate<'_, '_, 'tcx>
universe
}
- fn next_existential_region_var(&mut self, from_forall: bool) -> ty::Region<'tcx> {
+ #[instrument(skip(self), level = "debug")]
+ fn next_existential_region_var(
+ &mut self,
+ from_forall: bool,
+ _name: Option<Symbol>,
+ ) -> ty::Region<'tcx> {
let origin = NllRegionVariableOrigin::Existential { from_forall };
- self.type_checker.infcx.next_nll_region_var(origin)
+
+ let reg_var =
+ self.type_checker.infcx.next_nll_region_var(origin, || RegionCtxt::Existential(_name));
+
+ reg_var
}
+ #[instrument(skip(self), level = "debug")]
fn next_placeholder_region(&mut self, placeholder: ty::PlaceholderRegion) -> ty::Region<'tcx> {
- self.type_checker
+ let reg = self
+ .type_checker
.borrowck_context
.constraints
- .placeholder_region(self.type_checker.infcx, placeholder)
+ .placeholder_region(self.type_checker.infcx, placeholder);
+
+ let reg_info = match placeholder.name {
+ ty::BoundRegionKind::BrAnon(_, Some(span)) => BoundRegionInfo::Span(span),
+ ty::BoundRegionKind::BrAnon(..) => BoundRegionInfo::Name(Symbol::intern("anon")),
+ ty::BoundRegionKind::BrNamed(_, name) => BoundRegionInfo::Name(name),
+ ty::BoundRegionKind::BrEnv => BoundRegionInfo::Name(Symbol::intern("env")),
+ };
+
+ let reg_var =
+ reg.as_var().unwrap_or_else(|| bug!("expected region {:?} to be of kind ReVar", reg));
+ let mut var_to_origin = self.type_checker.infcx.reg_var_to_origin.borrow_mut();
+ let prev = var_to_origin.insert(reg_var, RegionCtxt::Placeholder(reg_info));
+ assert!(matches!(prev, None));
+
+ reg
}
+ #[instrument(skip(self), level = "debug")]
fn generalize_existential(&mut self, universe: ty::UniverseIndex) -> ty::Region<'tcx> {
- self.type_checker.infcx.next_nll_region_var_in_universe(
+ let reg = self.type_checker.infcx.next_nll_region_var_in_universe(
NllRegionVariableOrigin::Existential { from_forall: false },
universe,
- )
+ );
+
+ let reg_var =
+ reg.as_var().unwrap_or_else(|| bug!("expected region {:?} to be of kind ReVar", reg));
+
+ if cfg!(debug_assertions) {
+ let mut var_to_origin = self.type_checker.infcx.reg_var_to_origin.borrow_mut();
+ let prev = var_to_origin.insert(reg_var, RegionCtxt::Existential(None));
+
+ // It only makes sense to track region vars in non-canonicalization contexts. If this
+ // ever changes we either want to get rid of `BorrowckInferContext::reg_var_to_origin`
+ // or modify how we track nll region vars for that map.
+ assert!(matches!(prev, None));
+ }
+
+ reg
}
fn push_outlives(
@@ -140,10 +183,6 @@ impl<'tcx> TypeRelatingDelegate<'tcx> for NllTypeRelatingDelegate<'_, '_, 'tcx>
);
}
- fn normalization() -> NormalizationStrategy {
- NormalizationStrategy::Eager
- }
-
fn forbid_inference_vars() -> bool {
true
}
diff --git a/compiler/rustc_borrowck/src/universal_regions.rs b/compiler/rustc_borrowck/src/universal_regions.rs
index 5b4d99682..15d7613a8 100644
--- a/compiler/rustc_borrowck/src/universal_regions.rs
+++ b/compiler/rustc_borrowck/src/universal_regions.rs
@@ -18,17 +18,20 @@ use rustc_errors::Diagnostic;
use rustc_hir as hir;
use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_hir::lang_items::LangItem;
-use rustc_hir::{BodyOwnerKind, HirId};
+use rustc_hir::BodyOwnerKind;
use rustc_index::vec::{Idx, IndexVec};
-use rustc_infer::infer::{InferCtxt, NllRegionVariableOrigin};
+use rustc_infer::infer::NllRegionVariableOrigin;
use rustc_middle::ty::fold::TypeFoldable;
use rustc_middle::ty::{
self, DefIdTree, InlineConstSubsts, InlineConstSubstsParts, RegionVid, Ty, TyCtxt,
};
use rustc_middle::ty::{InternalSubsts, SubstsRef};
+use rustc_span::Symbol;
use std::iter;
use crate::nll::ToRegionVid;
+use crate::renumber::{BoundRegionInfo, RegionCtxt};
+use crate::BorrowckInferCtxt;
#[derive(Debug)]
pub struct UniversalRegions<'tcx> {
@@ -162,11 +165,14 @@ struct UniversalRegionIndices<'tcx> {
/// `ty::Region` to the internal `RegionVid` we are using. This is
/// used because trait matching and type-checking will feed us
/// region constraints that reference those regions and we need to
- /// be able to map them our internal `RegionVid`. This is
+ /// be able to map them to our internal `RegionVid`. This is
/// basically equivalent to an `InternalSubsts`, except that it also
/// contains an entry for `ReStatic` -- it might be nice to just
/// use a substs, and then handle `ReStatic` another way.
indices: FxHashMap<ty::Region<'tcx>, RegionVid>,
+
+ /// The vid assigned to `'static`. Used only for diagnostics.
+ pub fr_static: RegionVid,
}
#[derive(Debug, PartialEq)]
@@ -221,13 +227,11 @@ impl<'tcx> UniversalRegions<'tcx> {
/// signature. This will also compute the relationships that are
/// known between those regions.
pub fn new(
- infcx: &InferCtxt<'tcx>,
+ infcx: &BorrowckInferCtxt<'_, 'tcx>,
mir_def: ty::WithOptConstParam<LocalDefId>,
param_env: ty::ParamEnv<'tcx>,
) -> Self {
- let tcx = infcx.tcx;
- let mir_hir_id = tcx.hir().local_def_id_to_hir_id(mir_def.did);
- UniversalRegionsBuilder { infcx, mir_def, mir_hir_id, param_env }.build()
+ UniversalRegionsBuilder { infcx, mir_def, param_env }.build()
}
/// Given a reference to a closure type, extracts all the values
@@ -382,9 +386,8 @@ impl<'tcx> UniversalRegions<'tcx> {
}
struct UniversalRegionsBuilder<'cx, 'tcx> {
- infcx: &'cx InferCtxt<'tcx>,
+ infcx: &'cx BorrowckInferCtxt<'cx, 'tcx>,
mir_def: ty::WithOptConstParam<LocalDefId>,
- mir_hir_id: HirId,
param_env: ty::ParamEnv<'tcx>,
}
@@ -400,7 +403,10 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> {
assert_eq!(FIRST_GLOBAL_INDEX, self.infcx.num_region_vars());
// Create the "global" region that is always free in all contexts: 'static.
- let fr_static = self.infcx.next_nll_region_var(FR).to_region_vid();
+ let fr_static = self
+ .infcx
+ .next_nll_region_var(FR, || RegionCtxt::Free(Symbol::intern("static")))
+ .to_region_vid();
// We've now added all the global regions. The next ones we
// add will be external.
@@ -432,7 +438,17 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> {
|r| {
debug!(?r);
if !indices.indices.contains_key(&r) {
- let region_vid = self.infcx.next_nll_region_var(FR);
+ let region_vid = {
+ let name = match r.get_name() {
+ Some(name) => name,
+ _ => Symbol::intern("anon"),
+ };
+
+ self.infcx.next_nll_region_var(FR, || {
+ RegionCtxt::LateBound(BoundRegionInfo::Name(name))
+ })
+ };
+
debug!(?region_vid);
indices.insert_late_bound_region(r, region_vid.to_region_vid());
}
@@ -460,7 +476,17 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> {
for_each_late_bound_region_in_item(self.infcx.tcx, self.mir_def.did, |r| {
debug!(?r);
if !indices.indices.contains_key(&r) {
- let region_vid = self.infcx.next_nll_region_var(FR);
+ let region_vid = {
+ let name = match r.get_name() {
+ Some(name) => name,
+ _ => Symbol::intern("anon"),
+ };
+
+ self.infcx.next_nll_region_var(FR, || {
+ RegionCtxt::LateBound(BoundRegionInfo::Name(name))
+ })
+ };
+
debug!(?region_vid);
indices.insert_late_bound_region(r, region_vid.to_region_vid());
}
@@ -472,28 +498,32 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> {
// C-variadic fns also have a `VaList` input that's not listed in the signature
// (as it's created inside the body itself, not passed in from outside).
if let DefiningTy::FnDef(def_id, _) = defining_ty {
- if self.infcx.tcx.fn_sig(def_id).c_variadic() {
+ if self.infcx.tcx.fn_sig(def_id).skip_binder().c_variadic() {
let va_list_did = self.infcx.tcx.require_lang_item(
LangItem::VaList,
Some(self.infcx.tcx.def_span(self.mir_def.did)),
);
- let region = self
- .infcx
- .tcx
- .mk_region(ty::ReVar(self.infcx.next_nll_region_var(FR).to_region_vid()));
- let va_list_ty = self
+
+ let reg_vid = self
.infcx
- .tcx
- .bound_type_of(va_list_did)
- .subst(self.infcx.tcx, &[region.into()]);
+ .next_nll_region_var(FR, || RegionCtxt::Free(Symbol::intern("c-variadic")))
+ .to_region_vid();
+
+ let region = self.infcx.tcx.mk_re_var(reg_vid);
+ let va_list_ty =
+ self.infcx.tcx.type_of(va_list_did).subst(self.infcx.tcx, &[region.into()]);
- unnormalized_input_tys = self.infcx.tcx.mk_type_list(
+ unnormalized_input_tys = self.infcx.tcx.mk_type_list_from_iter(
unnormalized_input_tys.iter().copied().chain(iter::once(va_list_ty)),
);
}
}
- let fr_fn_body = self.infcx.next_nll_region_var(FR).to_region_vid();
+ let fr_fn_body = self
+ .infcx
+ .next_nll_region_var(FR, || RegionCtxt::Free(Symbol::intern("fn_body")))
+ .to_region_vid();
+
let num_universals = self.infcx.num_region_vars();
debug!("build: global regions = {}..{}", FIRST_GLOBAL_INDEX, first_extern_index);
@@ -527,12 +557,7 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> {
match tcx.hir().body_owner_kind(self.mir_def.did) {
BodyOwnerKind::Closure | BodyOwnerKind::Fn => {
- let defining_ty = if self.mir_def.did.to_def_id() == typeck_root_def_id {
- tcx.type_of(typeck_root_def_id)
- } else {
- let tables = tcx.typeck(self.mir_def.did);
- tables.node_type(self.mir_hir_id)
- };
+ let defining_ty = tcx.type_of(self.mir_def.def_id_for_type_of()).subst_identity();
debug!("defining_ty (pre-replacement): {:?}", defining_ty);
@@ -561,7 +586,18 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> {
self.infcx.replace_free_regions_with_nll_infer_vars(FR, identity_substs);
DefiningTy::Const(self.mir_def.did.to_def_id(), substs)
} else {
- let ty = tcx.typeck(self.mir_def.did).node_type(self.mir_hir_id);
+ // FIXME this line creates a dependency between borrowck and typeck.
+ //
+ // This is required for `AscribeUserType` canonical query, which will call
+ // `type_of(inline_const_def_id)`. That `type_of` would inject erased lifetimes
+ // into borrowck, which is ICE #78174.
+ //
+ // As a workaround, inline consts have an additional generic param (`ty`
+ // below), so that `type_of(inline_const_def_id).substs(substs)` uses the
+ // proper type with NLL infer vars.
+ let ty = tcx
+ .typeck(self.mir_def.did)
+ .node_type(tcx.local_def_id_to_hir_id(self.mir_def.did));
let substs = InlineConstSubsts::new(
tcx,
InlineConstSubstsParts { parent_substs: identity_substs, ty },
@@ -609,7 +645,7 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> {
let subst_mapping =
iter::zip(identity_substs.regions(), fr_substs.regions().map(|r| r.to_region_vid()));
- UniversalRegionIndices { indices: global_mapping.chain(subst_mapping).collect() }
+ UniversalRegionIndices { indices: global_mapping.chain(subst_mapping).collect(), fr_static }
}
fn compute_inputs_and_output(
@@ -623,7 +659,7 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> {
assert_eq!(self.mir_def.did.to_def_id(), def_id);
let closure_sig = substs.as_closure().sig();
let inputs_and_output = closure_sig.inputs_and_output();
- let bound_vars = tcx.mk_bound_variable_kinds(
+ let bound_vars = tcx.mk_bound_variable_kinds_from_iter(
inputs_and_output
.bound_vars()
.iter()
@@ -633,7 +669,7 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> {
var: ty::BoundVar::from_usize(bound_vars.len() - 1),
kind: ty::BrEnv,
};
- let env_region = ty::ReLateBound(ty::INNERMOST, br);
+ let env_region = tcx.mk_re_late_bound(ty::INNERMOST, br);
let closure_ty = tcx.closure_env_ty(def_id, substs, env_region).unwrap();
// The "inputs" of the closure in the
@@ -647,7 +683,7 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> {
};
ty::Binder::bind_with_vars(
- tcx.mk_type_list(
+ tcx.mk_type_list_from_iter(
iter::once(closure_ty).chain(inputs).chain(iter::once(output)),
),
bound_vars,
@@ -660,12 +696,12 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> {
let output = substs.as_generator().return_ty();
let generator_ty = tcx.mk_generator(def_id, substs, movability);
let inputs_and_output =
- self.infcx.tcx.intern_type_list(&[generator_ty, resume_ty, output]);
+ self.infcx.tcx.mk_type_list(&[generator_ty, resume_ty, output]);
ty::Binder::dummy(inputs_and_output)
}
DefiningTy::FnDef(def_id, _) => {
- let sig = tcx.fn_sig(def_id);
+ let sig = tcx.fn_sig(def_id).subst_identity();
let sig = indices.fold_to_region_vids(tcx, sig);
sig.inputs_and_output()
}
@@ -674,15 +710,15 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> {
// For a constant body, there are no inputs, and one
// "output" (the type of the constant).
assert_eq!(self.mir_def.did.to_def_id(), def_id);
- let ty = tcx.type_of(self.mir_def.def_id_for_type_of());
+ let ty = tcx.type_of(self.mir_def.def_id_for_type_of()).subst_identity();
let ty = indices.fold_to_region_vids(tcx, ty);
- ty::Binder::dummy(tcx.intern_type_list(&[ty]))
+ ty::Binder::dummy(tcx.mk_type_list(&[ty]))
}
DefiningTy::InlineConst(def_id, substs) => {
assert_eq!(self.mir_def.did.to_def_id(), def_id);
let ty = substs.as_inline_const().ty();
- ty::Binder::dummy(tcx.intern_type_list(&[ty]))
+ ty::Binder::dummy(tcx.mk_type_list(&[ty]))
}
}
}
@@ -695,7 +731,7 @@ trait InferCtxtExt<'tcx> {
value: T,
) -> T
where
- T: TypeFoldable<'tcx>;
+ T: TypeFoldable<TyCtxt<'tcx>>;
fn replace_bound_regions_with_nll_infer_vars<T>(
&self,
@@ -705,7 +741,7 @@ trait InferCtxtExt<'tcx> {
indices: &mut UniversalRegionIndices<'tcx>,
) -> T
where
- T: TypeFoldable<'tcx>;
+ T: TypeFoldable<TyCtxt<'tcx>>;
fn replace_late_bound_regions_with_nll_infer_vars_in_recursive_scope(
&self,
@@ -720,16 +756,27 @@ trait InferCtxtExt<'tcx> {
);
}
-impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> {
+impl<'cx, 'tcx> InferCtxtExt<'tcx> for BorrowckInferCtxt<'cx, 'tcx> {
+ #[instrument(skip(self), level = "debug")]
fn replace_free_regions_with_nll_infer_vars<T>(
&self,
origin: NllRegionVariableOrigin,
value: T,
) -> T
where
- T: TypeFoldable<'tcx>,
+ T: TypeFoldable<TyCtxt<'tcx>>,
{
- self.tcx.fold_regions(value, |_region, _depth| self.next_nll_region_var(origin))
+ self.infcx.tcx.fold_regions(value, |region, _depth| {
+ let name = match region.get_name() {
+ Some(name) => name,
+ _ => Symbol::intern("anon"),
+ };
+ debug!(?region, ?name);
+
+ let reg_var = self.next_nll_region_var(origin, || RegionCtxt::Free(name));
+
+ reg_var
+ })
}
#[instrument(level = "debug", skip(self, indices))]
@@ -741,15 +788,20 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> {
indices: &mut UniversalRegionIndices<'tcx>,
) -> T
where
- T: TypeFoldable<'tcx>,
+ T: TypeFoldable<TyCtxt<'tcx>>,
{
let (value, _map) = self.tcx.replace_late_bound_regions(value, |br| {
debug!(?br);
- let liberated_region = self.tcx.mk_region(ty::ReFree(ty::FreeRegion {
- scope: all_outlive_scope.to_def_id(),
- bound_region: br.kind,
- }));
- let region_vid = self.next_nll_region_var(origin);
+ let liberated_region = self.tcx.mk_re_free(all_outlive_scope.to_def_id(), br.kind);
+ let region_vid = {
+ let name = match br.kind.get_name() {
+ Some(name) => name,
+ _ => Symbol::intern("anon"),
+ };
+
+ self.next_nll_region_var(origin, || RegionCtxt::Bound(BoundRegionInfo::Name(name)))
+ };
+
indices.insert_late_bound_region(liberated_region, region_vid.to_region_vid());
debug!(?liberated_region, ?region_vid);
region_vid
@@ -775,7 +827,17 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> {
for_each_late_bound_region_in_recursive_scope(self.tcx, mir_def_id, |r| {
debug!(?r);
if !indices.indices.contains_key(&r) {
- let region_vid = self.next_nll_region_var(FR);
+ let region_vid = {
+ let name = match r.get_name() {
+ Some(name) => name,
+ _ => Symbol::intern("anon"),
+ };
+
+ self.next_nll_region_var(FR, || {
+ RegionCtxt::LateBound(BoundRegionInfo::Name(name))
+ })
+ };
+
debug!(?region_vid);
indices.insert_late_bound_region(r, region_vid.to_region_vid());
}
@@ -791,8 +853,17 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> {
for_each_late_bound_region_in_item(self.tcx, mir_def_id, |r| {
debug!(?r);
if !indices.indices.contains_key(&r) {
- let region_vid = self.next_nll_region_var(FR);
- debug!(?region_vid);
+ let region_vid = {
+ let name = match r.get_name() {
+ Some(name) => name,
+ _ => Symbol::intern("anon"),
+ };
+
+ self.next_nll_region_var(FR, || {
+ RegionCtxt::LateBound(BoundRegionInfo::Name(name))
+ })
+ };
+
indices.insert_late_bound_region(r, region_vid.to_region_vid());
}
});
@@ -821,6 +892,11 @@ impl<'tcx> UniversalRegionIndices<'tcx> {
pub fn to_region_vid(&self, r: ty::Region<'tcx>) -> RegionVid {
if let ty::ReVar(..) = *r {
r.to_region_vid()
+ } else if r.is_error() {
+ // We use the `'static` `RegionVid` because `ReError` doesn't actually exist in the
+ // `UniversalRegionIndices`. This is fine because 1) it is a fallback only used if
+ // errors are being emitted and 2) it leaves the happy path unaffected.
+ self.fr_static
} else {
*self
.indices
@@ -833,9 +909,9 @@ impl<'tcx> UniversalRegionIndices<'tcx> {
/// returned by `to_region_vid`.
pub fn fold_to_region_vids<T>(&self, tcx: TyCtxt<'tcx>, value: T) -> T
where
- T: TypeFoldable<'tcx>,
+ T: TypeFoldable<TyCtxt<'tcx>>,
{
- tcx.fold_regions(value, |region, _| tcx.mk_region(ty::ReVar(self.to_region_vid(region))))
+ tcx.fold_regions(value, |region, _| tcx.mk_re_var(self.to_region_vid(region)))
}
}
@@ -875,8 +951,7 @@ fn for_each_late_bound_region_in_item<'tcx>(
for bound_var in tcx.late_bound_vars(tcx.hir().local_def_id_to_hir_id(mir_def_id)) {
let ty::BoundVariableKind::Region(bound_region) = bound_var else { continue; };
- let liberated_region = tcx
- .mk_region(ty::ReFree(ty::FreeRegion { scope: mir_def_id.to_def_id(), bound_region }));
+ let liberated_region = tcx.mk_re_free(mir_def_id.to_def_id(), bound_region);
f(liberated_region);
}
}
diff --git a/compiler/rustc_builtin_macros/Cargo.toml b/compiler/rustc_builtin_macros/Cargo.toml
index 467fa932a..336e14ef9 100644
--- a/compiler/rustc_builtin_macros/Cargo.toml
+++ b/compiler/rustc_builtin_macros/Cargo.toml
@@ -23,5 +23,5 @@ rustc_session = { path = "../rustc_session" }
rustc_span = { path = "../rustc_span" }
rustc_target = { path = "../rustc_target" }
smallvec = { version = "1.8.1", features = ["union", "may_dangle"] }
-thin-vec = "0.2.9"
+thin-vec = "0.2.12"
tracing = "0.1"
diff --git a/compiler/rustc_error_messages/locales/en-US/builtin_macros.ftl b/compiler/rustc_builtin_macros/locales/en-US.ftl
index 4d088e27b..4d088e27b 100644
--- a/compiler/rustc_error_messages/locales/en-US/builtin_macros.ftl
+++ b/compiler/rustc_builtin_macros/locales/en-US.ftl
diff --git a/compiler/rustc_builtin_macros/src/alloc_error_handler.rs b/compiler/rustc_builtin_macros/src/alloc_error_handler.rs
index dcf500ddb..ac6697232 100644
--- a/compiler/rustc_builtin_macros/src/alloc_error_handler.rs
+++ b/compiler/rustc_builtin_macros/src/alloc_error_handler.rs
@@ -6,7 +6,7 @@ use rustc_ast::{Fn, ItemKind, Stmt, TyKind, Unsafe};
use rustc_expand::base::{Annotatable, ExtCtxt};
use rustc_span::symbol::{kw, sym, Ident};
use rustc_span::Span;
-use thin_vec::thin_vec;
+use thin_vec::{thin_vec, ThinVec};
pub fn expand(
ecx: &mut ExtCtxt<'_>,
@@ -39,10 +39,10 @@ pub fn expand(
let span = ecx.with_def_site_ctxt(item.span);
// Generate item statements for the allocator methods.
- let stmts = vec![generate_handler(ecx, item.ident, span, sig_span)];
+ let stmts = thin_vec![generate_handler(ecx, item.ident, span, sig_span)];
// Generate anonymous constant serving as container for the allocator methods.
- let const_ty = ecx.ty(sig_span, TyKind::Tup(Vec::new()));
+ let const_ty = ecx.ty(sig_span, TyKind::Tup(ThinVec::new()));
let const_body = ecx.expr_block(ecx.block(span, stmts));
let const_item = ecx.item_const(span, Ident::new(kw::Underscore, span), const_ty, const_body);
let const_item = if is_stmt {
@@ -67,13 +67,16 @@ fn generate_handler(cx: &ExtCtxt<'_>, handler: Ident, span: Span, sig_span: Span
let layout_new = cx.std_path(&[sym::alloc, sym::Layout, sym::from_size_align_unchecked]);
let layout_new = cx.expr_path(cx.path(span, layout_new));
- let layout =
- cx.expr_call(span, layout_new, vec![cx.expr_ident(span, size), cx.expr_ident(span, align)]);
+ let layout = cx.expr_call(
+ span,
+ layout_new,
+ thin_vec![cx.expr_ident(span, size), cx.expr_ident(span, align)],
+ );
- let call = cx.expr_call_ident(sig_span, handler, vec![layout]);
+ let call = cx.expr_call_ident(sig_span, handler, thin_vec![layout]);
let never = ast::FnRetTy::Ty(cx.ty(span, TyKind::Never));
- let params = vec![cx.param(span, size, ty_usize.clone()), cx.param(span, align, ty_usize)];
+ let params = thin_vec![cx.param(span, size, ty_usize.clone()), cx.param(span, align, ty_usize)];
let decl = cx.fn_decl(params, never);
let header = FnHeader { unsafety: Unsafe::Yes(span), ..FnHeader::default() };
let sig = FnSig { decl, header, span: span };
diff --git a/compiler/rustc_builtin_macros/src/asm.rs b/compiler/rustc_builtin_macros/src/asm.rs
index 925392b50..3fdbc9715 100644
--- a/compiler/rustc_builtin_macros/src/asm.rs
+++ b/compiler/rustc_builtin_macros/src/asm.rs
@@ -152,7 +152,7 @@ pub fn parse_asm_args<'a>(
ast::InlineAsmOperand::InOut { reg, expr, late: true }
}
} else if p.eat_keyword(kw::Const) {
- let anon_const = p.parse_anon_const_expr()?;
+ let anon_const = p.parse_expr_anon_const()?;
ast::InlineAsmOperand::Const { anon_const }
} else if p.eat_keyword(sym::sym) {
let expr = p.parse_expr()?;
diff --git a/compiler/rustc_builtin_macros/src/assert.rs b/compiler/rustc_builtin_macros/src/assert.rs
index 8555c3593..75af5e2b1 100644
--- a/compiler/rustc_builtin_macros/src/assert.rs
+++ b/compiler/rustc_builtin_macros/src/assert.rs
@@ -11,6 +11,7 @@ use rustc_expand::base::{DummyResult, ExtCtxt, MacEager, MacResult};
use rustc_parse::parser::Parser;
use rustc_span::symbol::{sym, Ident, Symbol};
use rustc_span::{Span, DUMMY_SP};
+use thin_vec::thin_vec;
pub fn expand_assert<'cx>(
cx: &'cx mut ExtCtxt<'_>,
@@ -79,7 +80,7 @@ pub fn expand_assert<'cx>(
let then = cx.expr_call_global(
call_site_span,
cx.std_path(&[sym::panicking, sym::panic]),
- vec![cx.expr_str(
+ thin_vec![cx.expr_str(
DUMMY_SP,
Symbol::intern(&format!(
"assertion failed: {}",
diff --git a/compiler/rustc_builtin_macros/src/assert/context.rs b/compiler/rustc_builtin_macros/src/assert/context.rs
index 93b07801e..b0b4dda16 100644
--- a/compiler/rustc_builtin_macros/src/assert/context.rs
+++ b/compiler/rustc_builtin_macros/src/assert/context.rs
@@ -12,7 +12,7 @@ use rustc_span::{
symbol::{sym, Ident, Symbol},
Span,
};
-use thin_vec::thin_vec;
+use thin_vec::{thin_vec, ThinVec};
pub(super) struct Context<'cx, 'a> {
// An optimization.
@@ -83,12 +83,12 @@ impl<'cx, 'a> Context<'cx, 'a> {
let Self { best_case_captures, capture_decls, cx, local_bind_decls, span, .. } = self;
- let mut assert_then_stmts = Vec::with_capacity(2);
+ let mut assert_then_stmts = ThinVec::with_capacity(2);
assert_then_stmts.extend(best_case_captures);
assert_then_stmts.push(self.cx.stmt_expr(panic));
let assert_then = self.cx.block(span, assert_then_stmts);
- let mut stmts = Vec::with_capacity(4);
+ let mut stmts = ThinVec::with_capacity(4);
stmts.push(initial_imports);
stmts.extend(capture_decls.into_iter().map(|c| c.decl));
stmts.extend(local_bind_decls);
@@ -120,7 +120,7 @@ impl<'cx, 'a> Context<'cx, 'a> {
thin_vec![self.cx.attr_nested_word(sym::allow, sym::unused_imports, self.span)],
ItemKind::Use(UseTree {
prefix: self.cx.path(self.span, self.cx.std_path(&[sym::asserting])),
- kind: UseTreeKind::Nested(vec![
+ kind: UseTreeKind::Nested(thin_vec![
nested_tree(self, sym::TryCaptureGeneric),
nested_tree(self, sym::TryCapturePrintable),
]),
@@ -136,7 +136,7 @@ impl<'cx, 'a> Context<'cx, 'a> {
self.cx.expr_call(
self.span,
self.cx.expr_path(self.cx.path(self.span, unlikely_path)),
- vec![self.cx.expr(self.span, ExprKind::Unary(UnOp::Not, cond_expr))],
+ thin_vec![self.cx.expr(self.span, ExprKind::Unary(UnOp::Not, cond_expr))],
)
}
@@ -297,6 +297,7 @@ impl<'cx, 'a> Context<'cx, 'a> {
| ExprKind::Continue(_)
| ExprKind::Err
| ExprKind::Field(_, _)
+ | ExprKind::FormatArgs(_)
| ExprKind::ForLoop(_, _, _, _)
| ExprKind::If(_, _, _)
| ExprKind::IncludedBytes(..)
@@ -338,7 +339,7 @@ impl<'cx, 'a> Context<'cx, 'a> {
let init = self.cx.expr_call(
self.span,
self.cx.expr_path(self.cx.path(self.span, init_std_path)),
- vec![],
+ ThinVec::new(),
);
let capture = Capture { decl: self.cx.stmt_let(self.span, true, ident, init), ident };
self.capture_decls.push(capture);
@@ -365,7 +366,7 @@ impl<'cx, 'a> Context<'cx, 'a> {
self.cx.expr_path(
self.cx.path(self.span, self.cx.std_path(&[sym::asserting, sym::Wrapper])),
),
- vec![self.cx.expr_path(Path::from_ident(local_bind))],
+ thin_vec![self.cx.expr_path(Path::from_ident(local_bind))],
);
let try_capture_call = self
.cx
@@ -377,7 +378,7 @@ impl<'cx, 'a> Context<'cx, 'a> {
ident: Ident::new(sym::try_capture, self.span),
},
expr_paren(self.cx, self.span, self.cx.expr_addr_of(self.span, wrapper)),
- vec![expr_addr_of_mut(
+ thin_vec![expr_addr_of_mut(
self.cx,
self.span,
self.cx.expr_path(Path::from_ident(capture)),
@@ -388,7 +389,7 @@ impl<'cx, 'a> Context<'cx, 'a> {
let local_bind_path = self.cx.expr_path(Path::from_ident(local_bind));
let rslt = if self.is_consumed {
let ret = self.cx.stmt_expr(local_bind_path);
- self.cx.expr_block(self.cx.block(self.span, vec![try_capture_call, ret]))
+ self.cx.expr_block(self.cx.block(self.span, thin_vec![try_capture_call, ret]))
} else {
self.best_case_captures.push(try_capture_call);
local_bind_path
@@ -440,7 +441,7 @@ fn expr_method_call(
cx: &ExtCtxt<'_>,
seg: PathSegment,
receiver: P<Expr>,
- args: Vec<P<Expr>>,
+ args: ThinVec<P<Expr>>,
span: Span,
) -> P<Expr> {
cx.expr(span, ExprKind::MethodCall(Box::new(MethodCall { seg, receiver, args, span })))
diff --git a/compiler/rustc_builtin_macros/src/deriving/bounds.rs b/compiler/rustc_builtin_macros/src/deriving/bounds.rs
index 240167146..0481a1189 100644
--- a/compiler/rustc_builtin_macros/src/deriving/bounds.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/bounds.rs
@@ -17,6 +17,7 @@ pub fn expand_deriving_copy(
span,
path: path_std!(marker::Copy),
skip_path_as_bound: false,
+ needs_copy_as_bound_if_packed: false,
additional_bounds: Vec::new(),
supports_unions: true,
methods: Vec::new(),
diff --git a/compiler/rustc_builtin_macros/src/deriving/clone.rs b/compiler/rustc_builtin_macros/src/deriving/clone.rs
index ef5a75f42..dfee2d3ce 100644
--- a/compiler/rustc_builtin_macros/src/deriving/clone.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/clone.rs
@@ -6,7 +6,7 @@ use rustc_data_structures::fx::FxHashSet;
use rustc_expand::base::{Annotatable, ExtCtxt};
use rustc_span::symbol::{kw, sym, Ident};
use rustc_span::Span;
-use thin_vec::thin_vec;
+use thin_vec::{thin_vec, ThinVec};
pub fn expand_deriving_clone(
cx: &mut ExtCtxt<'_>,
@@ -73,6 +73,7 @@ pub fn expand_deriving_clone(
span,
path: path_std!(clone::Clone),
skip_path_as_bound: false,
+ needs_copy_as_bound_if_packed: true,
additional_bounds: bounds,
supports_unions: true,
methods: vec![MethodDef {
@@ -99,7 +100,7 @@ fn cs_clone_simple(
substr: &Substructure<'_>,
is_union: bool,
) -> BlockOrExpr {
- let mut stmts = Vec::new();
+ let mut stmts = ThinVec::new();
let mut seen_type_names = FxHashSet::default();
let mut process_variant = |variant: &VariantData| {
for field in variant.fields() {
@@ -161,7 +162,7 @@ fn cs_clone(
let all_fields;
let fn_path = cx.std_path(&[sym::clone, sym::Clone, sym::clone]);
let subcall = |cx: &mut ExtCtxt<'_>, field: &FieldInfo| {
- let args = vec![field.self_expr.clone()];
+ let args = thin_vec![field.self_expr.clone()];
cx.expr_call_global(field.span, fn_path.clone(), args)
};
@@ -199,7 +200,7 @@ fn cs_clone(
let call = subcall(cx, field);
cx.field_imm(field.span, ident, call)
})
- .collect::<Vec<_>>();
+ .collect::<ThinVec<_>>();
cx.expr_struct(trait_span, ctor_path, fields)
}
diff --git a/compiler/rustc_builtin_macros/src/deriving/cmp/eq.rs b/compiler/rustc_builtin_macros/src/deriving/cmp/eq.rs
index 3e994f037..af9719586 100644
--- a/compiler/rustc_builtin_macros/src/deriving/cmp/eq.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/cmp/eq.rs
@@ -7,7 +7,7 @@ use rustc_data_structures::fx::FxHashSet;
use rustc_expand::base::{Annotatable, ExtCtxt};
use rustc_span::symbol::sym;
use rustc_span::Span;
-use thin_vec::thin_vec;
+use thin_vec::{thin_vec, ThinVec};
pub fn expand_deriving_eq(
cx: &mut ExtCtxt<'_>,
@@ -27,6 +27,7 @@ pub fn expand_deriving_eq(
span,
path: path_std!(cmp::Eq),
skip_path_as_bound: false,
+ needs_copy_as_bound_if_packed: true,
additional_bounds: Vec::new(),
supports_unions: true,
methods: vec![MethodDef {
@@ -55,7 +56,7 @@ fn cs_total_eq_assert(
trait_span: Span,
substr: &Substructure<'_>,
) -> BlockOrExpr {
- let mut stmts = Vec::new();
+ let mut stmts = ThinVec::new();
let mut seen_type_names = FxHashSet::default();
let mut process_variant = |variant: &ast::VariantData| {
for field in variant.fields() {
diff --git a/compiler/rustc_builtin_macros/src/deriving/cmp/ord.rs b/compiler/rustc_builtin_macros/src/deriving/cmp/ord.rs
index a926fca4e..cfd36f030 100644
--- a/compiler/rustc_builtin_macros/src/deriving/cmp/ord.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/cmp/ord.rs
@@ -20,6 +20,7 @@ pub fn expand_deriving_ord(
span,
path: path_std!(cmp::Ord),
skip_path_as_bound: false,
+ needs_copy_as_bound_if_packed: true,
additional_bounds: Vec::new(),
supports_unions: false,
methods: vec![MethodDef {
@@ -63,14 +64,14 @@ pub fn cs_cmp(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_>) -> Bl
let [other_expr] = &field.other_selflike_exprs[..] else {
cx.span_bug(field.span, "not exactly 2 arguments in `derive(Ord)`");
};
- let args = vec![field.self_expr.clone(), other_expr.clone()];
+ let args = thin_vec![field.self_expr.clone(), other_expr.clone()];
cx.expr_call_global(field.span, cmp_path.clone(), args)
}
CsFold::Combine(span, expr1, expr2) => {
let eq_arm = cx.arm(span, cx.pat_path(span, equal_path.clone()), expr1);
let neq_arm =
cx.arm(span, cx.pat_ident(span, test_id), cx.expr_ident(span, test_id));
- cx.expr_match(span, expr2, vec![eq_arm, neq_arm])
+ cx.expr_match(span, expr2, thin_vec![eq_arm, neq_arm])
}
CsFold::Fieldless => cx.expr_path(equal_path.clone()),
},
diff --git a/compiler/rustc_builtin_macros/src/deriving/cmp/partial_eq.rs b/compiler/rustc_builtin_macros/src/deriving/cmp/partial_eq.rs
index 9051fe0b2..bad47db0d 100644
--- a/compiler/rustc_builtin_macros/src/deriving/cmp/partial_eq.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/cmp/partial_eq.rs
@@ -29,16 +29,30 @@ pub fn expand_deriving_partial_eq(
cx.span_bug(field.span, "not exactly 2 arguments in `derive(PartialEq)`");
};
- // We received `&T` arguments. Convert them to `T` by
- // stripping `&` or adding `*`. This isn't necessary for
- // type checking, but it results in much better error
- // messages if something goes wrong.
+ // We received arguments of type `&T`. Convert them to type `T` by stripping
+ // any leading `&` or adding `*`. This isn't necessary for type checking, but
+ // it results in better error messages if something goes wrong.
+ //
+ // Note: for arguments that look like `&{ x }`, which occur with packed
+ // structs, this would cause expressions like `{ self.x } == { other.x }`,
+ // which isn't valid Rust syntax. This wouldn't break compilation because these
+ // AST nodes are constructed within the compiler. But it would mean that code
+ // printed by `-Zunpretty=expanded` (or `cargo expand`) would have invalid
+ // syntax, which would be suboptimal. So we wrap these in parens, giving
+ // `({ self.x }) == ({ other.x })`, which is valid syntax.
let convert = |expr: &P<Expr>| {
if let ExprKind::AddrOf(BorrowKind::Ref, Mutability::Not, inner) =
&expr.kind
{
- inner.clone()
+ if let ExprKind::Block(..) = &inner.kind {
+ // `&{ x }` form: remove the `&`, add parens.
+ cx.expr_paren(field.span, inner.clone())
+ } else {
+ // `&x` form: remove the `&`.
+ inner.clone()
+ }
} else {
+ // No leading `&`: add a leading `*`.
cx.expr_deref(field.span, expr.clone())
}
};
@@ -84,6 +98,7 @@ pub fn expand_deriving_partial_eq(
span,
path: path_std!(cmp::PartialEq),
skip_path_as_bound: false,
+ needs_copy_as_bound_if_packed: true,
additional_bounds: Vec::new(),
supports_unions: false,
methods,
diff --git a/compiler/rustc_builtin_macros/src/deriving/cmp/partial_ord.rs b/compiler/rustc_builtin_macros/src/deriving/cmp/partial_ord.rs
index c9dc89212..9f4624790 100644
--- a/compiler/rustc_builtin_macros/src/deriving/cmp/partial_ord.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/cmp/partial_ord.rs
@@ -1,7 +1,7 @@
use crate::deriving::generic::ty::*;
use crate::deriving::generic::*;
use crate::deriving::{path_std, pathvec_std};
-use rustc_ast::MetaItem;
+use rustc_ast::{ExprKind, ItemKind, MetaItem, PatKind};
use rustc_expand::base::{Annotatable, ExtCtxt};
use rustc_span::symbol::{sym, Ident};
use rustc_span::Span;
@@ -21,6 +21,27 @@ pub fn expand_deriving_partial_ord(
let attrs = thin_vec![cx.attr_word(sym::inline, span)];
+ // Order in which to perform matching
+ let tag_then_data = if let Annotatable::Item(item) = item
+ && let ItemKind::Enum(def, _) = &item.kind {
+ let dataful: Vec<bool> = def.variants.iter().map(|v| !v.data.fields().is_empty()).collect();
+ match dataful.iter().filter(|&&b| b).count() {
+ // No data, placing the tag check first makes codegen simpler
+ 0 => true,
+ 1..=2 => false,
+ _ => {
+ (0..dataful.len()-1).any(|i| {
+ if dataful[i] && let Some(idx) = dataful[i+1..].iter().position(|v| *v) {
+ idx >= 2
+ } else {
+ false
+ }
+ })
+ }
+ }
+ } else {
+ true
+ };
let partial_cmp_def = MethodDef {
name: sym::partial_cmp,
generics: Bounds::empty(),
@@ -30,7 +51,7 @@ pub fn expand_deriving_partial_ord(
attributes: attrs,
fieldless_variants_strategy: FieldlessVariantsStrategy::Unify,
combine_substructure: combine_substructure(Box::new(|cx, span, substr| {
- cs_partial_cmp(cx, span, substr)
+ cs_partial_cmp(cx, span, substr, tag_then_data)
})),
};
@@ -38,6 +59,7 @@ pub fn expand_deriving_partial_ord(
span,
path: path_std!(cmp::PartialOrd),
skip_path_as_bound: false,
+ needs_copy_as_bound_if_packed: true,
additional_bounds: vec![],
supports_unions: false,
methods: vec![partial_cmp_def],
@@ -47,7 +69,12 @@ pub fn expand_deriving_partial_ord(
trait_def.expand(cx, mitem, item, push)
}
-pub fn cs_partial_cmp(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_>) -> BlockOrExpr {
+fn cs_partial_cmp(
+ cx: &mut ExtCtxt<'_>,
+ span: Span,
+ substr: &Substructure<'_>,
+ tag_then_data: bool,
+) -> BlockOrExpr {
let test_id = Ident::new(sym::cmp, span);
let equal_path = cx.path_global(span, cx.std_path(&[sym::cmp, sym::Ordering, sym::Equal]));
let partial_cmp_path = cx.std_path(&[sym::cmp, sym::PartialOrd, sym::partial_cmp]);
@@ -71,15 +98,53 @@ pub fn cs_partial_cmp(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_
let [other_expr] = &field.other_selflike_exprs[..] else {
cx.span_bug(field.span, "not exactly 2 arguments in `derive(Ord)`");
};
- let args = vec![field.self_expr.clone(), other_expr.clone()];
+ let args = thin_vec![field.self_expr.clone(), other_expr.clone()];
cx.expr_call_global(field.span, partial_cmp_path.clone(), args)
}
- CsFold::Combine(span, expr1, expr2) => {
- let eq_arm =
- cx.arm(span, cx.pat_some(span, cx.pat_path(span, equal_path.clone())), expr1);
- let neq_arm =
- cx.arm(span, cx.pat_ident(span, test_id), cx.expr_ident(span, test_id));
- cx.expr_match(span, expr2, vec![eq_arm, neq_arm])
+ CsFold::Combine(span, mut expr1, expr2) => {
+ // When the item is an enum, this expands to
+ // ```
+ // match (expr2) {
+ // Some(Ordering::Equal) => expr1,
+ // cmp => cmp
+ // }
+ // ```
+ // where `expr2` is `partial_cmp(self_tag, other_tag)`, and `expr1` is a `match`
+ // against the enum variants. This means that we begin by comparing the enum tags,
+ // before either inspecting their contents (if they match), or returning
+ // the `cmp::Ordering` of comparing the enum tags.
+ // ```
+ // match partial_cmp(self_tag, other_tag) {
+ // Some(Ordering::Equal) => match (self, other) {
+ // (Self::A(self_0), Self::A(other_0)) => partial_cmp(self_0, other_0),
+ // (Self::B(self_0), Self::B(other_0)) => partial_cmp(self_0, other_0),
+ // _ => Some(Ordering::Equal)
+ // }
+ // cmp => cmp
+ // }
+ // ```
+ // If we have any certain enum layouts, flipping this results in better codegen
+ // ```
+ // match (self, other) {
+ // (Self::A(self_0), Self::A(other_0)) => partial_cmp(self_0, other_0),
+ // _ => partial_cmp(self_tag, other_tag)
+ // }
+ // ```
+ // Reference: https://github.com/rust-lang/rust/pull/103659#issuecomment-1328126354
+
+ if !tag_then_data
+ && let ExprKind::Match(_, arms) = &mut expr1.kind
+ && let Some(last) = arms.last_mut()
+ && let PatKind::Wild = last.pat.kind {
+ last.body = expr2;
+ expr1
+ } else {
+ let eq_arm =
+ cx.arm(span, cx.pat_some(span, cx.pat_path(span, equal_path.clone())), expr1);
+ let neq_arm =
+ cx.arm(span, cx.pat_ident(span, test_id), cx.expr_ident(span, test_id));
+ cx.expr_match(span, expr2, thin_vec![eq_arm, neq_arm])
+ }
}
CsFold::Fieldless => cx.expr_some(span, cx.expr_path(equal_path.clone())),
},
diff --git a/compiler/rustc_builtin_macros/src/deriving/debug.rs b/compiler/rustc_builtin_macros/src/deriving/debug.rs
index e0f487e86..809f9838d 100644
--- a/compiler/rustc_builtin_macros/src/deriving/debug.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/debug.rs
@@ -7,6 +7,7 @@ use rustc_ast::{self as ast, MetaItem};
use rustc_expand::base::{Annotatable, ExtCtxt};
use rustc_span::symbol::{sym, Ident, Symbol};
use rustc_span::Span;
+use thin_vec::{thin_vec, ThinVec};
pub fn expand_deriving_debug(
cx: &mut ExtCtxt<'_>,
@@ -23,6 +24,7 @@ pub fn expand_deriving_debug(
span,
path: path_std!(fmt::Debug),
skip_path_as_bound: false,
+ needs_copy_as_bound_if_packed: true,
additional_bounds: Vec::new(),
supports_unions: false,
methods: vec![MethodDef {
@@ -75,10 +77,25 @@ fn show_substructure(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_>
// The number of fields that can be handled without an array.
const CUTOFF: usize = 5;
+ fn expr_for_field(
+ cx: &ExtCtxt<'_>,
+ field: &FieldInfo,
+ index: usize,
+ len: usize,
+ ) -> ast::ptr::P<ast::Expr> {
+ if index < len - 1 {
+ field.self_expr.clone()
+ } else {
+ // Unsized types need an extra indirection, but only the last field
+ // may be unsized.
+ cx.expr_addr_of(field.span, field.self_expr.clone())
+ }
+ }
+
if fields.is_empty() {
// Special case for no fields.
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 expr = cx.expr_call_global(span, fn_path_write_str, thin_vec![fmt, name]);
BlockOrExpr::new_expr(expr)
} else if fields.len() <= CUTOFF {
// Few enough fields that we can use a specific-length method.
@@ -89,7 +106,7 @@ fn show_substructure(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_>
};
let fn_path_debug = cx.std_path(&[sym::fmt, sym::Formatter, Symbol::intern(&debug)]);
- let mut args = Vec::with_capacity(2 + fields.len() * args_per_field);
+ let mut args = ThinVec::with_capacity(2 + fields.len() * args_per_field);
args.extend([fmt, name]);
for i in 0..fields.len() {
let field = &fields[i];
@@ -97,47 +114,48 @@ fn show_substructure(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_>
let name = cx.expr_str(field.span, field.name.unwrap().name);
args.push(name);
}
- // Use an extra indirection to make sure this works for unsized types.
- let field = cx.expr_addr_of(field.span, field.self_expr.clone());
+
+ let field = expr_for_field(cx, field, i, fields.len());
args.push(field);
}
let expr = cx.expr_call_global(span, fn_path_debug, args);
BlockOrExpr::new_expr(expr)
} else {
// Enough fields that we must use the any-length method.
- let mut name_exprs = Vec::with_capacity(fields.len());
- let mut value_exprs = Vec::with_capacity(fields.len());
+ let mut name_exprs = ThinVec::with_capacity(fields.len());
+ let mut value_exprs = ThinVec::with_capacity(fields.len());
- for field in fields {
+ for i in 0..fields.len() {
+ let field = &fields[i];
if is_struct {
name_exprs.push(cx.expr_str(field.span, field.name.unwrap().name));
}
- // Use an extra indirection to make sure this works for unsized types.
- let field = cx.expr_addr_of(field.span, field.self_expr.clone());
+ let field = expr_for_field(cx, field, i, fields.len());
value_exprs.push(field);
}
// `let names: &'static _ = &["field1", "field2"];`
- let names_let = if is_struct {
+ let names_let = is_struct.then(|| {
let lt_static = Some(cx.lifetime_static(span));
let ty_static_ref = cx.ty_ref(span, cx.ty_infer(span), lt_static, ast::Mutability::Not);
- Some(cx.stmt_let_ty(
+ cx.stmt_let_ty(
span,
false,
Ident::new(sym::names, span),
Some(ty_static_ref),
cx.expr_array_ref(span, name_exprs),
- ))
- } else {
- None
- };
+ )
+ });
// `let values: &[&dyn Debug] = &[&&self.field1, &&self.field2];`
let path_debug = cx.path_global(span, cx.std_path(&[sym::fmt, sym::Debug]));
let ty_dyn_debug = cx.ty(
span,
- ast::TyKind::TraitObject(vec![cx.trait_bound(path_debug)], ast::TraitObjectSyntax::Dyn),
+ ast::TyKind::TraitObject(
+ vec![cx.trait_bound(path_debug, false)],
+ ast::TraitObjectSyntax::Dyn,
+ ),
);
let ty_slice = cx.ty(
span,
@@ -160,7 +178,7 @@ fn show_substructure(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_>
};
let fn_path_debug_internal = cx.std_path(&[sym::fmt, sym::Formatter, sym_debug]);
- let mut args = Vec::with_capacity(4);
+ let mut args = ThinVec::with_capacity(4);
args.push(fmt);
args.push(name);
if is_struct {
@@ -169,7 +187,7 @@ fn show_substructure(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_>
args.push(cx.expr_ident(span, Ident::new(sym::values, span)));
let expr = cx.expr_call_global(span, fn_path_debug_internal, args);
- let mut stmts = Vec::with_capacity(3);
+ let mut stmts = ThinVec::with_capacity(2);
if is_struct {
stmts.push(names_let.unwrap());
}
@@ -206,18 +224,18 @@ fn show_fieldless_enum(
let pat = match &v.data {
ast::VariantData::Tuple(fields, _) => {
debug_assert!(fields.is_empty());
- cx.pat_tuple_struct(span, variant_path, vec![])
+ cx.pat_tuple_struct(span, variant_path, ThinVec::new())
}
ast::VariantData::Struct(fields, _) => {
debug_assert!(fields.is_empty());
- cx.pat_struct(span, variant_path, vec![])
+ cx.pat_struct(span, variant_path, ThinVec::new())
}
ast::VariantData::Unit(_) => cx.pat_path(span, variant_path),
};
cx.arm(span, pat, cx.expr_str(span, v.ident.name))
})
- .collect::<Vec<_>>();
+ .collect::<ThinVec<_>>();
let name = cx.expr_match(span, cx.expr_self(span), arms);
let fn_path_write_str = cx.std_path(&[sym::fmt, sym::Formatter, sym::write_str]);
- BlockOrExpr::new_expr(cx.expr_call_global(span, fn_path_write_str, vec![fmt, name]))
+ BlockOrExpr::new_expr(cx.expr_call_global(span, fn_path_write_str, thin_vec![fmt, name]))
}
diff --git a/compiler/rustc_builtin_macros/src/deriving/decodable.rs b/compiler/rustc_builtin_macros/src/deriving/decodable.rs
index 5f9519dad..3921533c8 100644
--- a/compiler/rustc_builtin_macros/src/deriving/decodable.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/decodable.rs
@@ -3,12 +3,12 @@
use crate::deriving::generic::ty::*;
use crate::deriving::generic::*;
use crate::deriving::pathvec_std;
-
use rustc_ast::ptr::P;
use rustc_ast::{self as ast, Expr, MetaItem, Mutability};
use rustc_expand::base::{Annotatable, ExtCtxt};
use rustc_span::symbol::{sym, Ident, Symbol};
use rustc_span::Span;
+use thin_vec::{thin_vec, ThinVec};
pub fn expand_deriving_rustc_decodable(
cx: &mut ExtCtxt<'_>,
@@ -25,6 +25,7 @@ pub fn expand_deriving_rustc_decodable(
span,
path: Path::new_(vec![krate, sym::Decodable], vec![], PathKind::Global),
skip_path_as_bound: false,
+ needs_copy_as_bound_if_packed: true,
additional_bounds: Vec::new(),
supports_unions: false,
methods: vec![MethodDef {
@@ -95,7 +96,7 @@ fn decodable_substructure(
cx.expr_call_global(
span,
fn_read_struct_field_path.clone(),
- vec![
+ thin_vec![
blkdecoder.clone(),
cx.expr_str(span, name),
cx.expr_usize(span, field),
@@ -111,7 +112,7 @@ fn decodable_substructure(
cx.expr_call_global(
trait_span,
fn_read_struct_path,
- vec![
+ thin_vec![
decoder,
cx.expr_str(trait_span, substr.type_ident.name),
cx.expr_usize(trait_span, nfields),
@@ -122,8 +123,8 @@ fn decodable_substructure(
StaticEnum(_, fields) => {
let variant = Ident::new(sym::i, trait_span);
- let mut arms = Vec::with_capacity(fields.len() + 1);
- let mut variants = Vec::with_capacity(fields.len());
+ let mut arms = ThinVec::with_capacity(fields.len() + 1);
+ let mut variants = ThinVec::with_capacity(fields.len());
let fn_read_enum_variant_arg_path: Vec<_> =
cx.def_site_path(&[sym::rustc_serialize, sym::Decoder, sym::read_enum_variant_arg]);
@@ -140,7 +141,7 @@ fn decodable_substructure(
cx.expr_call_global(
span,
fn_read_enum_variant_arg_path.clone(),
- vec![blkdecoder.clone(), idx, exprdecode.clone()],
+ thin_vec![blkdecoder.clone(), idx, exprdecode.clone()],
),
)
});
@@ -161,7 +162,7 @@ fn decodable_substructure(
let result = cx.expr_call_global(
trait_span,
fn_read_enum_variant_path,
- vec![blkdecoder, variant_array_ref, lambda],
+ thin_vec![blkdecoder, variant_array_ref, lambda],
);
let fn_read_enum_path: Vec<_> =
cx.def_site_path(&[sym::rustc_serialize, sym::Decoder, sym::read_enum]);
@@ -169,7 +170,7 @@ fn decodable_substructure(
cx.expr_call_global(
trait_span,
fn_read_enum_path,
- vec![
+ thin_vec![
decoder,
cx.expr_str(trait_span, substr.type_ident.name),
cx.lambda1(trait_span, result, blkarg),
diff --git a/compiler/rustc_builtin_macros/src/deriving/default.rs b/compiler/rustc_builtin_macros/src/deriving/default.rs
index 182707472..4d753a2ed 100644
--- a/compiler/rustc_builtin_macros/src/deriving/default.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/default.rs
@@ -8,7 +8,7 @@ use rustc_span::symbol::Ident;
use rustc_span::symbol::{kw, sym};
use rustc_span::Span;
use smallvec::SmallVec;
-use thin_vec::thin_vec;
+use thin_vec::{thin_vec, ThinVec};
pub fn expand_deriving_default(
cx: &mut ExtCtxt<'_>,
@@ -25,6 +25,7 @@ pub fn expand_deriving_default(
span,
path: Path::new(vec![kw::Default, sym::Default]),
skip_path_as_bound: has_a_default_variant(item),
+ needs_copy_as_bound_if_packed: false,
additional_bounds: Vec::new(),
supports_unions: false,
methods: vec![MethodDef {
@@ -59,7 +60,7 @@ fn default_struct_substructure(
) -> BlockOrExpr {
// Note that `kw::Default` is "default" and `sym::Default` is "Default"!
let default_ident = cx.std_path(&[kw::Default, sym::Default, kw::Default]);
- let default_call = |span| cx.expr_call_global(span, default_ident.clone(), Vec::new());
+ let default_call = |span| cx.expr_call_global(span, default_ident.clone(), ThinVec::new());
let expr = match summary {
Unnamed(_, false) => cx.expr_ident(trait_span, substr.type_ident),
diff --git a/compiler/rustc_builtin_macros/src/deriving/encodable.rs b/compiler/rustc_builtin_macros/src/deriving/encodable.rs
index 2afeed927..a3b11309d 100644
--- a/compiler/rustc_builtin_macros/src/deriving/encodable.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/encodable.rs
@@ -88,11 +88,11 @@
use crate::deriving::generic::ty::*;
use crate::deriving::generic::*;
use crate::deriving::pathvec_std;
-
use rustc_ast::{AttrVec, ExprKind, MetaItem, Mutability};
use rustc_expand::base::{Annotatable, ExtCtxt};
use rustc_span::symbol::{sym, Ident, Symbol};
use rustc_span::Span;
+use thin_vec::{thin_vec, ThinVec};
pub fn expand_deriving_rustc_encodable(
cx: &mut ExtCtxt<'_>,
@@ -109,6 +109,7 @@ pub fn expand_deriving_rustc_encodable(
span,
path: Path::new_(vec![krate, sym::Encodable], vec![], PathKind::Global),
skip_path_as_bound: false,
+ needs_copy_as_bound_if_packed: true,
additional_bounds: Vec::new(),
supports_unions: false,
methods: vec![MethodDef {
@@ -168,19 +169,20 @@ fn encodable_substructure(
Struct(_, fields) => {
let fn_emit_struct_field_path =
cx.def_site_path(&[sym::rustc_serialize, sym::Encoder, sym::emit_struct_field]);
- let mut stmts = Vec::new();
+ let mut stmts = ThinVec::new();
for (i, &FieldInfo { name, ref self_expr, span, .. }) in fields.iter().enumerate() {
let name = match name {
Some(id) => id.name,
None => Symbol::intern(&format!("_field{}", i)),
};
let self_ref = cx.expr_addr_of(span, self_expr.clone());
- let enc = cx.expr_call(span, fn_path.clone(), vec![self_ref, blkencoder.clone()]);
+ let enc =
+ cx.expr_call(span, fn_path.clone(), thin_vec![self_ref, blkencoder.clone()]);
let lambda = cx.lambda1(span, enc, blkarg);
let call = cx.expr_call_global(
span,
fn_emit_struct_field_path.clone(),
- vec![
+ thin_vec![
blkencoder.clone(),
cx.expr_str(span, name),
cx.expr_usize(span, i),
@@ -202,7 +204,7 @@ fn encodable_substructure(
// unit structs have no fields and need to return Ok()
let blk = if stmts.is_empty() {
- let ok = cx.expr_ok(trait_span, cx.expr_tuple(trait_span, vec![]));
+ let ok = cx.expr_ok(trait_span, cx.expr_tuple(trait_span, ThinVec::new()));
cx.lambda1(trait_span, ok, blkarg)
} else {
cx.lambda_stmts_1(trait_span, stmts, blkarg)
@@ -214,7 +216,7 @@ fn encodable_substructure(
let expr = cx.expr_call_global(
trait_span,
fn_emit_struct_path,
- vec![
+ thin_vec![
encoder,
cx.expr_str(trait_span, substr.type_ident.name),
cx.expr_usize(trait_span, fields.len()),
@@ -235,19 +237,22 @@ fn encodable_substructure(
let fn_emit_enum_variant_arg_path: Vec<_> =
cx.def_site_path(&[sym::rustc_serialize, sym::Encoder, sym::emit_enum_variant_arg]);
- let mut stmts = Vec::new();
+ let mut stmts = ThinVec::new();
if !fields.is_empty() {
let last = fields.len() - 1;
for (i, &FieldInfo { ref self_expr, span, .. }) in fields.iter().enumerate() {
let self_ref = cx.expr_addr_of(span, self_expr.clone());
- let enc =
- cx.expr_call(span, fn_path.clone(), vec![self_ref, blkencoder.clone()]);
+ let enc = cx.expr_call(
+ span,
+ fn_path.clone(),
+ thin_vec![self_ref, blkencoder.clone()],
+ );
let lambda = cx.lambda1(span, enc, blkarg);
let call = cx.expr_call_global(
span,
fn_emit_enum_variant_arg_path.clone(),
- vec![blkencoder.clone(), cx.expr_usize(span, i), lambda],
+ thin_vec![blkencoder.clone(), cx.expr_usize(span, i), lambda],
);
let call = if i != last {
cx.expr_try(span, call)
@@ -257,7 +262,7 @@ fn encodable_substructure(
stmts.push(cx.stmt_expr(call));
}
} else {
- let ok = cx.expr_ok(trait_span, cx.expr_tuple(trait_span, vec![]));
+ let ok = cx.expr_ok(trait_span, cx.expr_tuple(trait_span, ThinVec::new()));
let ret_ok = cx.expr(trait_span, ExprKind::Ret(Some(ok)));
stmts.push(cx.stmt_expr(ret_ok));
}
@@ -271,7 +276,7 @@ fn encodable_substructure(
let call = cx.expr_call_global(
trait_span,
fn_emit_enum_variant_path,
- vec![
+ thin_vec![
blkencoder,
name,
cx.expr_usize(trait_span, *idx),
@@ -286,9 +291,9 @@ fn encodable_substructure(
let expr = cx.expr_call_global(
trait_span,
fn_emit_enum_path,
- vec![encoder, cx.expr_str(trait_span, substr.type_ident.name), blk],
+ thin_vec![encoder, cx.expr_str(trait_span, substr.type_ident.name), blk],
);
- BlockOrExpr::new_mixed(vec![me], Some(expr))
+ BlockOrExpr::new_mixed(thin_vec![me], Some(expr))
}
_ => cx.bug("expected Struct or EnumMatching in derive(Encodable)"),
diff --git a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs
index 17b7ac0eb..1f819beeb 100644
--- a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs
@@ -165,18 +165,19 @@ pub use SubstructureFields::*;
use crate::deriving;
use rustc_ast::ptr::P;
use rustc_ast::{
- self as ast, BindingAnnotation, ByRef, EnumDef, Expr, Generics, Mutability, PatKind,
+ self as ast, BindingAnnotation, ByRef, EnumDef, Expr, GenericArg, GenericParamKind, Generics,
+ Mutability, PatKind, TyKind, VariantData,
};
-use rustc_ast::{GenericArg, GenericParamKind, VariantData};
use rustc_attr as attr;
use rustc_expand::base::{Annotatable, ExtCtxt};
+use rustc_session::lint::builtin::BYTE_SLICE_IN_PACKED_STRUCT_WITH_DERIVE;
use rustc_span::symbol::{kw, sym, Ident, Symbol};
use rustc_span::{Span, DUMMY_SP};
use std::cell::RefCell;
use std::iter;
use std::ops::Not;
use std::vec;
-use thin_vec::thin_vec;
+use thin_vec::{thin_vec, ThinVec};
use ty::{Bounds, Path, Ref, Self_, Ty};
pub mod ty;
@@ -191,6 +192,9 @@ pub struct TraitDef<'a> {
/// Whether to skip adding the current trait as a bound to the type parameters of the type.
pub skip_path_as_bound: bool,
+ /// Whether `Copy` is needed as an additional bound on type parameters in a packed struct.
+ pub needs_copy_as_bound_if_packed: bool,
+
/// Additional bounds required of any type parameters of the type,
/// other than the current trait
pub additional_bounds: Vec<Ty>,
@@ -314,7 +318,7 @@ pub fn combine_substructure(
}
struct TypeParameter {
- bound_generic_params: Vec<ast::GenericParam>,
+ bound_generic_params: ThinVec<ast::GenericParam>,
ty: P<ast::Ty>,
}
@@ -324,18 +328,18 @@ struct TypeParameter {
/// avoiding the insertion of any unnecessary blocks.
///
/// The statements come before the expression.
-pub struct BlockOrExpr(Vec<ast::Stmt>, Option<P<Expr>>);
+pub struct BlockOrExpr(ThinVec<ast::Stmt>, Option<P<Expr>>);
impl BlockOrExpr {
- pub fn new_stmts(stmts: Vec<ast::Stmt>) -> BlockOrExpr {
+ pub fn new_stmts(stmts: ThinVec<ast::Stmt>) -> BlockOrExpr {
BlockOrExpr(stmts, None)
}
pub fn new_expr(expr: P<Expr>) -> BlockOrExpr {
- BlockOrExpr(vec![], Some(expr))
+ BlockOrExpr(ThinVec::new(), Some(expr))
}
- pub fn new_mixed(stmts: Vec<ast::Stmt>, expr: Option<P<Expr>>) -> BlockOrExpr {
+ pub fn new_mixed(stmts: ThinVec<ast::Stmt>, expr: Option<P<Expr>>) -> BlockOrExpr {
BlockOrExpr(stmts, expr)
}
@@ -351,7 +355,7 @@ impl BlockOrExpr {
fn into_expr(self, cx: &ExtCtxt<'_>, span: Span) -> P<Expr> {
if self.0.is_empty() {
match self.1 {
- None => cx.expr_block(cx.block(span, vec![])),
+ None => cx.expr_block(cx.block(span, ThinVec::new())),
Some(expr) => expr,
}
} else if self.0.len() == 1
@@ -381,7 +385,7 @@ fn find_type_parameters(
struct Visitor<'a, 'b> {
cx: &'a ExtCtxt<'b>,
ty_param_names: &'a [Symbol],
- bound_generic_params_stack: Vec<ast::GenericParam>,
+ bound_generic_params_stack: ThinVec<ast::GenericParam>,
type_params: Vec<TypeParameter>,
}
@@ -418,7 +422,7 @@ fn find_type_parameters(
let mut visitor = Visitor {
cx,
ty_param_names,
- bound_generic_params_stack: Vec::new(),
+ bound_generic_params_stack: ThinVec::new(),
type_params: Vec::new(),
};
visit::Visitor::visit_ty(&mut visitor, ty);
@@ -455,18 +459,6 @@ impl<'a> TraitDef<'a> {
}
false
});
- let has_no_type_params = match &item.kind {
- ast::ItemKind::Struct(_, generics)
- | ast::ItemKind::Enum(_, generics)
- | ast::ItemKind::Union(_, generics) => !generics
- .params
- .iter()
- .any(|param| matches!(param.kind, ast::GenericParamKind::Type { .. })),
- _ => unreachable!(),
- };
- let container_id = cx.current_expansion.id.expn_data().parent.expect_local();
- let copy_fields =
- is_packed && has_no_type_params && cx.resolver.has_derive_copy(container_id);
let newitem = match &item.kind {
ast::ItemKind::Struct(struct_def, generics) => self.expand_struct_def(
@@ -475,7 +467,7 @@ impl<'a> TraitDef<'a> {
item.ident,
generics,
from_scratch,
- copy_fields,
+ is_packed,
),
ast::ItemKind::Enum(enum_def, generics) => {
// We ignore `is_packed` here, because `repr(packed)`
@@ -493,7 +485,7 @@ impl<'a> TraitDef<'a> {
item.ident,
generics,
from_scratch,
- copy_fields,
+ is_packed,
)
} else {
cx.span_err(mitem.span, "this trait cannot be derived for unions");
@@ -565,6 +557,7 @@ impl<'a> TraitDef<'a> {
generics: &Generics,
field_tys: Vec<P<ast::Ty>>,
methods: Vec<P<ast::AssocItem>>,
+ is_packed: bool,
) -> P<ast::Item> {
let trait_path = self.path.to_path(cx, self.span, type_ident, generics);
@@ -601,26 +594,46 @@ impl<'a> TraitDef<'a> {
let span = generics.span.with_ctxt(ctxt);
// Create the generic parameters
- let params: Vec<_> = generics
+ let params: ThinVec<_> = generics
.params
.iter()
.map(|param| match &param.kind {
GenericParamKind::Lifetime { .. } => param.clone(),
GenericParamKind::Type { .. } => {
- // I don't think this can be moved out of the loop, since
- // a GenericBound requires an ast id
- let bounds: Vec<_> =
- // extra restrictions on the generics parameters to the
- // type being derived upon
- self.additional_bounds.iter().map(|p| {
- cx.trait_bound(p.to_path(cx, self.span, type_ident, generics))
- }).chain(
- // require the current trait
- self.skip_path_as_bound.not().then(|| cx.trait_bound(trait_path.clone()))
- ).chain(
- // also add in any bounds from the declaration
- param.bounds.iter().cloned()
- ).collect();
+ // Extra restrictions on the generics parameters to the
+ // type being derived upon.
+ let bounds: Vec<_> = self
+ .additional_bounds
+ .iter()
+ .map(|p| {
+ cx.trait_bound(
+ p.to_path(cx, self.span, type_ident, generics),
+ self.is_const,
+ )
+ })
+ .chain(
+ // Add a bound for the current trait.
+ self.skip_path_as_bound
+ .not()
+ .then(|| cx.trait_bound(trait_path.clone(), self.is_const)),
+ )
+ .chain({
+ // Add a `Copy` bound if required.
+ if is_packed && self.needs_copy_as_bound_if_packed {
+ let p = deriving::path_std!(marker::Copy);
+ Some(cx.trait_bound(
+ p.to_path(cx, self.span, type_ident, generics),
+ self.is_const,
+ ))
+ } else {
+ None
+ }
+ })
+ .chain(
+ // Also add in any bounds from the declaration.
+ param.bounds.iter().cloned(),
+ )
+ .collect();
cx.typaram(param.ident.span.with_ctxt(ctxt), param.ident, bounds, None)
}
@@ -689,11 +702,25 @@ impl<'a> TraitDef<'a> {
let mut bounds: Vec<_> = self
.additional_bounds
.iter()
- .map(|p| cx.trait_bound(p.to_path(cx, self.span, type_ident, generics)))
+ .map(|p| {
+ cx.trait_bound(
+ p.to_path(cx, self.span, type_ident, generics),
+ self.is_const,
+ )
+ })
.collect();
- // require the current trait
- bounds.push(cx.trait_bound(trait_path.clone()));
+ // Require the current trait.
+ bounds.push(cx.trait_bound(trait_path.clone(), self.is_const));
+
+ // Add a `Copy` bound if required.
+ if is_packed && self.needs_copy_as_bound_if_packed {
+ let p = deriving::path_std!(marker::Copy);
+ bounds.push(cx.trait_bound(
+ p.to_path(cx, self.span, type_ident, generics),
+ self.is_const,
+ ));
+ }
let predicate = ast::WhereBoundPredicate {
span: self.span,
@@ -734,8 +761,7 @@ impl<'a> TraitDef<'a> {
let path = cx.path_all(self.span, false, vec![type_ident], self_params);
let self_type = cx.ty_path(path);
- let attr = cx.attr_word(sym::automatically_derived, self.span);
- let attrs = thin_vec![attr];
+ let attrs = thin_vec![cx.attr_word(sym::automatically_derived, self.span),];
let opt_trait_ref = Some(trait_ref);
cx.item(
@@ -762,7 +788,7 @@ impl<'a> TraitDef<'a> {
type_ident: Ident,
generics: &Generics,
from_scratch: bool,
- copy_fields: bool,
+ is_packed: bool,
) -> P<ast::Item> {
let field_tys: Vec<P<ast::Ty>> =
struct_def.fields().iter().map(|field| field.ty.clone()).collect();
@@ -790,7 +816,7 @@ impl<'a> TraitDef<'a> {
type_ident,
&selflike_args,
&nonselflike_args,
- copy_fields,
+ is_packed,
)
};
@@ -806,7 +832,7 @@ impl<'a> TraitDef<'a> {
})
.collect();
- self.create_derived_impl(cx, type_ident, generics, field_tys, methods)
+ self.create_derived_impl(cx, type_ident, generics, field_tys, methods, is_packed)
}
fn expand_enum_def(
@@ -861,7 +887,8 @@ impl<'a> TraitDef<'a> {
})
.collect();
- self.create_derived_impl(cx, type_ident, generics, field_tys, methods)
+ let is_packed = false; // enums are never packed
+ self.create_derived_impl(cx, type_ident, generics, field_tys, methods, is_packed)
}
}
@@ -908,19 +935,17 @@ impl<'a> MethodDef<'a> {
trait_: &TraitDef<'_>,
type_ident: Ident,
generics: &Generics,
- ) -> (Option<ast::ExplicitSelf>, Vec<P<Expr>>, Vec<P<Expr>>, Vec<(Ident, P<ast::Ty>)>) {
- let mut selflike_args = Vec::new();
+ ) -> (Option<ast::ExplicitSelf>, ThinVec<P<Expr>>, Vec<P<Expr>>, Vec<(Ident, P<ast::Ty>)>) {
+ let mut selflike_args = ThinVec::new();
let mut nonselflike_args = Vec::new();
let mut nonself_arg_tys = Vec::new();
let span = trait_.span;
- let explicit_self = if self.explicit_self {
+ let explicit_self = self.explicit_self.then(|| {
let (self_expr, explicit_self) = ty::get_explicit_self(cx, span);
selflike_args.push(self_expr);
- Some(explicit_self)
- } else {
- None
- };
+ explicit_self
+ });
for (ty, name) in self.nonself_args.iter() {
let ast_ty = ty.to_ty(cx, span, type_ident, generics);
@@ -1011,8 +1036,8 @@ impl<'a> MethodDef<'a> {
/// ```
/// But if the struct is `repr(packed)`, we can't use something like
/// `&self.x` because that might cause an unaligned ref. So for any trait
- /// method that takes a reference, if the struct impls `Copy` then we use a
- /// local block to force a copy:
+ /// method that takes a reference, we use a local block to force a copy.
+ /// This requires that the field impl `Copy`.
/// ```
/// # struct A { x: u8, y: u8 }
/// impl PartialEq for A {
@@ -1027,10 +1052,6 @@ impl<'a> MethodDef<'a> {
/// ::core::hash::Hash::hash(&{ self.y }, state)
/// }
/// }
- /// ```
- /// If the struct doesn't impl `Copy`, we use the normal `&self.x`. This
- /// only works if the fields match the alignment required by the
- /// `packed(N)` attribute. (We'll get errors later on if not.)
fn expand_struct_method_body<'b>(
&self,
cx: &mut ExtCtxt<'_>,
@@ -1039,12 +1060,12 @@ impl<'a> MethodDef<'a> {
type_ident: Ident,
selflike_args: &[P<Expr>],
nonselflike_args: &[P<Expr>],
- copy_fields: bool,
+ is_packed: bool,
) -> BlockOrExpr {
assert!(selflike_args.len() == 1 || selflike_args.len() == 2);
let selflike_fields =
- trait_.create_struct_field_access_fields(cx, selflike_args, struct_def, copy_fields);
+ trait_.create_struct_field_access_fields(cx, selflike_args, struct_def, is_packed);
self.call_substructure_method(
cx,
trait_,
@@ -1112,7 +1133,7 @@ impl<'a> MethodDef<'a> {
trait_: &TraitDef<'b>,
enum_def: &'b EnumDef,
type_ident: Ident,
- selflike_args: Vec<P<Expr>>,
+ selflike_args: ThinVec<P<Expr>>,
nonselflike_args: &[P<Expr>],
) -> BlockOrExpr {
let span = trait_.span;
@@ -1125,7 +1146,7 @@ impl<'a> MethodDef<'a> {
// There is no sensible code to be generated for *any* deriving on a
// zero-variant enum. So we just generate a failing expression.
if variants.is_empty() {
- return BlockOrExpr(vec![], Some(deriving::call_unreachable(cx, span)));
+ return BlockOrExpr(ThinVec::new(), Some(deriving::call_unreachable(cx, span)));
}
let prefixes = iter::once("__self".to_string())
@@ -1161,13 +1182,13 @@ impl<'a> MethodDef<'a> {
let other_selflike_exprs = tag_exprs;
let tag_field = FieldInfo { span, name: None, self_expr, other_selflike_exprs };
- let tag_let_stmts: Vec<_> = iter::zip(&tag_idents, &selflike_args)
+ let tag_let_stmts: ThinVec<_> = iter::zip(&tag_idents, &selflike_args)
.map(|(&ident, selflike_arg)| {
let variant_value = deriving::call_intrinsic(
cx,
span,
sym::discriminant_value,
- vec![selflike_arg.clone()],
+ thin_vec![selflike_arg.clone()],
);
cx.stmt_let(span, false, ident, variant_value)
})
@@ -1226,7 +1247,7 @@ impl<'a> MethodDef<'a> {
// (Variant2, Variant2, ...) => Body2
// ...
// where each tuple has length = selflike_args.len()
- let mut match_arms: Vec<ast::Arm> = variants
+ let mut match_arms: ThinVec<ast::Arm> = variants
.iter()
.enumerate()
.filter(|&(_, v)| !(unify_fieldless_variants && v.data.fields().is_empty()))
@@ -1239,7 +1260,7 @@ impl<'a> MethodDef<'a> {
let sp = variant.span.with_ctxt(trait_.span.ctxt());
let variant_path = cx.path(sp, vec![type_ident, variant.ident]);
let by_ref = ByRef::No; // because enums can't be repr(packed)
- let mut subpats: Vec<_> = trait_.create_struct_patterns(
+ let mut subpats = trait_.create_struct_patterns(
cx,
variant_path,
&variant.data,
@@ -1315,7 +1336,7 @@ impl<'a> MethodDef<'a> {
// ...
// _ => ::core::intrinsics::unreachable()
// }
- let get_match_expr = |mut selflike_args: Vec<P<Expr>>| {
+ let get_match_expr = |mut selflike_args: ThinVec<P<Expr>>| {
let match_arg = if selflike_args.len() == 1 {
selflike_args.pop().unwrap()
} else {
@@ -1341,7 +1362,7 @@ impl<'a> MethodDef<'a> {
tag_let_stmts.append(&mut tag_check_plus_match.0);
BlockOrExpr(tag_let_stmts, tag_check_plus_match.1)
} else {
- BlockOrExpr(vec![], Some(get_match_expr(selflike_args)))
+ BlockOrExpr(ThinVec::new(), Some(get_match_expr(selflike_args)))
}
}
@@ -1406,7 +1427,7 @@ impl<'a> TraitDef<'a> {
struct_def: &'a VariantData,
prefixes: &[String],
by_ref: ByRef,
- ) -> Vec<P<ast::Pat>> {
+ ) -> ThinVec<P<ast::Pat>> {
prefixes
.iter()
.map(|prefix| {
@@ -1514,7 +1535,7 @@ impl<'a> TraitDef<'a> {
cx: &mut ExtCtxt<'_>,
selflike_args: &[P<Expr>],
struct_def: &'a VariantData,
- copy_fields: bool,
+ is_packed: bool,
) -> Vec<FieldInfo> {
self.create_fields(struct_def, |i, struct_field, sp| {
selflike_args
@@ -1533,10 +1554,54 @@ impl<'a> TraitDef<'a> {
}),
),
);
- if copy_fields {
- field_expr = cx.expr_block(
- cx.block(struct_field.span, vec![cx.stmt_expr(field_expr)]),
- );
+ if is_packed {
+ // In general, fields in packed structs are copied via a
+ // block, e.g. `&{self.0}`. The two exceptions are `[u8]`
+ // and `str` fields, which cannot be copied and also never
+ // cause unaligned references. These exceptions are allowed
+ // to handle the `FlexZeroSlice` type in the `zerovec`
+ // crate within `icu4x-0.9.0`.
+ //
+ // Once use of `icu4x-0.9.0` has dropped sufficiently, this
+ // exception should be removed.
+ let is_simple_path = |ty: &P<ast::Ty>, sym| {
+ if let TyKind::Path(None, ast::Path { segments, .. }) = &ty.kind &&
+ let [seg] = segments.as_slice() &&
+ seg.ident.name == sym && seg.args.is_none()
+ {
+ true
+ } else {
+ false
+ }
+ };
+
+ let exception = if let TyKind::Slice(ty) = &struct_field.ty.kind &&
+ is_simple_path(ty, sym::u8)
+ {
+ Some("byte")
+ } else if is_simple_path(&struct_field.ty, sym::str) {
+ Some("string")
+ } else {
+ None
+ };
+
+ if let Some(ty) = exception {
+ cx.sess.parse_sess.buffer_lint_with_diagnostic(
+ BYTE_SLICE_IN_PACKED_STRUCT_WITH_DERIVE,
+ sp,
+ ast::CRATE_NODE_ID,
+ &format!(
+ "{} slice in a packed struct that derives a built-in trait",
+ ty
+ ),
+ rustc_lint_defs::BuiltinLintDiagnostics::ByteSliceInPackedStructWithDerive
+ );
+ } else {
+ // Wrap the expression in `{...}`, causing a copy.
+ field_expr = cx.expr_block(
+ cx.block(struct_field.span, thin_vec![cx.stmt_expr(field_expr)]),
+ );
+ }
}
cx.expr_addr_of(sp, field_expr)
})
diff --git a/compiler/rustc_builtin_macros/src/deriving/generic/ty.rs b/compiler/rustc_builtin_macros/src/deriving/generic/ty.rs
index c6f5f5d08..26f91b714 100644
--- a/compiler/rustc_builtin_macros/src/deriving/generic/ty.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/generic/ty.rs
@@ -9,6 +9,7 @@ use rustc_expand::base::ExtCtxt;
use rustc_span::source_map::{respan, DUMMY_SP};
use rustc_span::symbol::{kw, Ident, Symbol};
use rustc_span::Span;
+use thin_vec::ThinVec;
/// A path, e.g., `::std::option::Option::<i32>` (global). Has support
/// for type parameters.
@@ -102,7 +103,7 @@ impl Ty {
Path(p) => p.to_ty(cx, span, self_ty, self_generics),
Self_ => cx.ty_path(self.to_path(cx, span, self_ty, self_generics)),
Unit => {
- let ty = ast::TyKind::Tup(vec![]);
+ let ty = ast::TyKind::Tup(ThinVec::new());
cx.ty(span, ty)
}
}
@@ -154,7 +155,7 @@ fn mk_ty_param(
.iter()
.map(|b| {
let path = b.to_path(cx, span, self_ident, self_generics);
- cx.trait_bound(path)
+ cx.trait_bound(path, false)
})
.collect();
cx.typaram(span, Ident::new(name, span), bounds, None)
@@ -185,7 +186,11 @@ impl Bounds {
Generics {
params,
- where_clause: ast::WhereClause { has_where_token: false, predicates: Vec::new(), span },
+ where_clause: ast::WhereClause {
+ has_where_token: false,
+ predicates: ThinVec::new(),
+ span,
+ },
span,
}
}
diff --git a/compiler/rustc_builtin_macros/src/deriving/hash.rs b/compiler/rustc_builtin_macros/src/deriving/hash.rs
index f8570d8f8..4eee573db 100644
--- a/compiler/rustc_builtin_macros/src/deriving/hash.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/hash.rs
@@ -1,11 +1,11 @@
use crate::deriving::generic::ty::*;
use crate::deriving::generic::*;
use crate::deriving::{path_std, pathvec_std};
-
use rustc_ast::{AttrVec, MetaItem, Mutability};
use rustc_expand::base::{Annotatable, ExtCtxt};
use rustc_span::symbol::sym;
use rustc_span::Span;
+use thin_vec::thin_vec;
pub fn expand_deriving_hash(
cx: &mut ExtCtxt<'_>,
@@ -24,6 +24,7 @@ pub fn expand_deriving_hash(
span,
path,
skip_path_as_bound: false,
+ needs_copy_as_bound_if_packed: true,
additional_bounds: Vec::new(),
supports_unions: false,
methods: vec![MethodDef {
@@ -59,7 +60,7 @@ fn hash_substructure(
cx.expr_path(cx.path_global(span, strs))
};
- let expr = cx.expr_call(span, hash_path, vec![expr, state_expr.clone()]);
+ let expr = cx.expr_call(span, hash_path, thin_vec![expr, state_expr.clone()]);
cx.stmt_expr(expr)
};
@@ -71,7 +72,7 @@ fn hash_substructure(
}
EnumTag(tag_field, match_expr) => {
assert!(tag_field.other_selflike_exprs.is_empty());
- let stmts = vec![call_hash(tag_field.span, tag_field.self_expr.clone())];
+ let stmts = thin_vec![call_hash(tag_field.span, tag_field.self_expr.clone())];
(stmts, match_expr.clone())
}
_ => cx.span_bug(trait_span, "impossible substructure in `derive(Hash)`"),
diff --git a/compiler/rustc_builtin_macros/src/deriving/mod.rs b/compiler/rustc_builtin_macros/src/deriving/mod.rs
index de657e4e6..d34336e76 100644
--- a/compiler/rustc_builtin_macros/src/deriving/mod.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/mod.rs
@@ -6,6 +6,7 @@ use rustc_ast::{GenericArg, Impl, ItemKind, MetaItem};
use rustc_expand::base::{Annotatable, ExpandResult, ExtCtxt, MultiItemModifier};
use rustc_span::symbol::{sym, Ident, Symbol};
use rustc_span::Span;
+use thin_vec::{thin_vec, ThinVec};
macro path_local($x:ident) {
generic::ty::Path::new_local(sym::$x)
@@ -92,7 +93,7 @@ fn call_intrinsic(
cx: &ExtCtxt<'_>,
span: Span,
intrinsic: Symbol,
- args: Vec<P<ast::Expr>>,
+ args: ThinVec<P<ast::Expr>>,
) -> P<ast::Expr> {
let span = cx.with_def_site_ctxt(span);
let path = cx.std_path(&[sym::intrinsics, intrinsic]);
@@ -103,10 +104,10 @@ fn call_intrinsic(
fn call_unreachable(cx: &ExtCtxt<'_>, span: Span) -> P<ast::Expr> {
let span = cx.with_def_site_ctxt(span);
let path = cx.std_path(&[sym::intrinsics, sym::unreachable]);
- let call = cx.expr_call_global(span, path, vec![]);
+ let call = cx.expr_call_global(span, path, ThinVec::new());
cx.expr_block(P(ast::Block {
- stmts: vec![cx.stmt_expr(call)],
+ stmts: thin_vec![cx.stmt_expr(call)],
id: ast::DUMMY_NODE_ID,
rules: ast::BlockCheckMode::Unsafe(ast::CompilerGenerated),
span,
@@ -202,7 +203,7 @@ fn inject_impl_of_structural_trait(
generics,
of_trait: Some(trait_ref),
self_ty: self_type,
- items: Vec::new(),
+ items: ThinVec::new(),
})),
);
@@ -211,7 +212,7 @@ fn inject_impl_of_structural_trait(
fn assert_ty_bounds(
cx: &mut ExtCtxt<'_>,
- stmts: &mut Vec<ast::Stmt>,
+ stmts: &mut ThinVec<ast::Stmt>,
ty: P<ast::Ty>,
span: Span,
assert_path: &[Symbol],
diff --git a/compiler/rustc_builtin_macros/src/env.rs b/compiler/rustc_builtin_macros/src/env.rs
index e5a5e6069..f011cb754 100644
--- a/compiler/rustc_builtin_macros/src/env.rs
+++ b/compiler/rustc_builtin_macros/src/env.rs
@@ -8,8 +8,8 @@ use rustc_ast::{self as ast, GenericArg};
use rustc_expand::base::{self, *};
use rustc_span::symbol::{kw, sym, Ident, Symbol};
use rustc_span::Span;
-
use std::env;
+use thin_vec::thin_vec;
pub fn expand_option_env<'cx>(
cx: &'cx mut ExtCtxt<'_>,
@@ -41,7 +41,7 @@ pub fn expand_option_env<'cx>(
Some(value) => cx.expr_call_global(
sp,
cx.std_path(&[sym::option, sym::Option, sym::Some]),
- vec![cx.expr_str(sp, value)],
+ thin_vec![cx.expr_str(sp, value)],
),
};
MacEager::expr(e)
@@ -53,7 +53,7 @@ pub fn expand_env<'cx>(
tts: TokenStream,
) -> Box<dyn base::MacResult + 'cx> {
let mut exprs = match get_exprs_from_tts(cx, tts) {
- Some(exprs) if exprs.is_empty() => {
+ Some(exprs) if exprs.is_empty() || exprs.len() > 2 => {
cx.span_err(sp, "env! takes 1 or 2 arguments");
return DummyResult::any(sp);
}
@@ -64,28 +64,48 @@ pub fn expand_env<'cx>(
let Some((var, _style)) = expr_to_string(cx, exprs.next().unwrap(), "expected string literal") else {
return DummyResult::any(sp);
};
- let msg = match exprs.next() {
- None => Symbol::intern(&format!("environment variable `{}` not defined", var)),
+
+ let custom_msg = match exprs.next() {
+ None => None,
Some(second) => match expr_to_string(cx, second, "expected string literal") {
None => return DummyResult::any(sp),
- Some((s, _style)) => s,
+ Some((s, _style)) => Some(s),
},
};
- if exprs.next().is_some() {
- cx.span_err(sp, "env! takes 1 or 2 arguments");
- return DummyResult::any(sp);
- }
-
let sp = cx.with_def_site_ctxt(sp);
let value = env::var(var.as_str()).ok().as_deref().map(Symbol::intern);
cx.sess.parse_sess.env_depinfo.borrow_mut().insert((var, value));
let e = match value {
None => {
- cx.span_err(sp, msg.as_str());
+ let (msg, help) = match custom_msg {
+ None => (
+ format!("environment variable `{var}` not defined at compile time"),
+ Some(help_for_missing_env_var(var.as_str())),
+ ),
+ Some(s) => (s.to_string(), None),
+ };
+ let mut diag = cx.struct_span_err(sp, &msg);
+ if let Some(help) = help {
+ diag.help(help);
+ }
+ diag.emit();
return DummyResult::any(sp);
}
Some(value) => cx.expr_str(sp, value),
};
MacEager::expr(e)
}
+
+fn help_for_missing_env_var(var: &str) -> String {
+ if var.starts_with("CARGO_")
+ || var.starts_with("DEP_")
+ || matches!(var, "OUT_DIR" | "OPT_LEVEL" | "PROFILE" | "HOST" | "TARGET")
+ {
+ format!(
+ "Cargo sets build script variables at run time. Use `std::env::var(\"{var}\")` instead"
+ )
+ } else {
+ format!("Use `std::env::var(\"{var}\")` to read the variable at run time")
+ }
+}
diff --git a/compiler/rustc_builtin_macros/src/format.rs b/compiler/rustc_builtin_macros/src/format.rs
index 9f4bbbc62..e93a23394 100644
--- a/compiler/rustc_builtin_macros/src/format.rs
+++ b/compiler/rustc_builtin_macros/src/format.rs
@@ -1,7 +1,11 @@
use rustc_ast::ptr::P;
use rustc_ast::token;
use rustc_ast::tokenstream::TokenStream;
-use rustc_ast::Expr;
+use rustc_ast::{
+ Expr, ExprKind, FormatAlignment, FormatArgPosition, FormatArgPositionKind, FormatArgs,
+ FormatArgsPiece, FormatArgument, FormatArgumentKind, FormatArguments, FormatCount,
+ FormatDebugHex, FormatOptions, FormatPlaceholder, FormatSign, FormatTrait,
+};
use rustc_data_structures::fx::FxHashSet;
use rustc_errors::{pluralize, Applicability, MultiSpan, PResult};
use rustc_expand::base::{self, *};
@@ -12,21 +16,15 @@ use rustc_span::{BytePos, InnerSpan, Span};
use rustc_lint_defs::builtin::NAMED_ARGUMENTS_USED_POSITIONALLY;
use rustc_lint_defs::{BufferedEarlyLint, BuiltinLintDiagnostics, LintId};
-mod ast;
-use ast::*;
-
-mod expand;
-use expand::expand_parsed_format_args;
-
// The format_args!() macro is expanded in three steps:
// 1. First, `parse_args` will parse the `(literal, arg, arg, name=arg, name=arg)` syntax,
// but doesn't parse the template (the literal) itself.
// 2. Second, `make_format_args` will parse the template, the format options, resolve argument references,
-// produce diagnostics, and turn the whole thing into a `FormatArgs` structure.
-// 3. Finally, `expand_parsed_format_args` will turn that `FormatArgs` structure
-// into the expression that the macro expands to.
+// produce diagnostics, and turn the whole thing into a `FormatArgs` AST node.
+// 3. Much later, in AST lowering (rustc_ast_lowering), that `FormatArgs` structure will be turned
+// into the expression of type `core::fmt::Arguments`.
-// See format/ast.rs for the FormatArgs structure and glossary.
+// See rustc_ast/src/format.rs for the FormatArgs structure and glossary.
// Only used in parse_args and report_invalid_references,
// to indicate how a referred argument was used.
@@ -437,7 +435,16 @@ pub fn make_format_args(
format_options: FormatOptions {
fill: format.fill,
alignment,
- flags: format.flags,
+ sign: format.sign.map(|s| match s {
+ parse::Sign::Plus => FormatSign::Plus,
+ parse::Sign::Minus => FormatSign::Minus,
+ }),
+ alternate: format.alternate,
+ zero_pad: format.zero_pad,
+ debug_hex: format.debug_hex.map(|s| match s {
+ parse::DebugHex::Lower => FormatDebugHex::Lower,
+ parse::DebugHex::Upper => FormatDebugHex::Upper,
+ }),
precision,
width,
},
@@ -850,7 +857,7 @@ fn expand_format_args_impl<'cx>(
match parse_args(ecx, sp, tts) {
Ok((efmt, args)) => {
if let Ok(format_args) = make_format_args(ecx, efmt, args, nl) {
- MacEager::expr(expand_parsed_format_args(ecx, format_args))
+ MacEager::expr(ecx.expr(sp, ExprKind::FormatArgs(P(format_args))))
} else {
MacEager::expr(DummyResult::raw_expr(sp, true))
}
diff --git a/compiler/rustc_builtin_macros/src/format/expand.rs b/compiler/rustc_builtin_macros/src/format/expand.rs
deleted file mode 100644
index 9dde5efcb..000000000
--- a/compiler/rustc_builtin_macros/src/format/expand.rs
+++ /dev/null
@@ -1,353 +0,0 @@
-use super::*;
-use rustc_ast as ast;
-use rustc_ast::visit::{self, Visitor};
-use rustc_ast::{BlockCheckMode, UnsafeSource};
-use rustc_data_structures::fx::FxIndexSet;
-use rustc_span::{sym, symbol::kw};
-
-#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
-enum ArgumentType {
- Format(FormatTrait),
- Usize,
-}
-
-fn make_argument(ecx: &ExtCtxt<'_>, sp: Span, arg: P<ast::Expr>, ty: ArgumentType) -> P<ast::Expr> {
- // Generate:
- // ::core::fmt::ArgumentV1::new_…(arg)
- use ArgumentType::*;
- use FormatTrait::*;
- ecx.expr_call_global(
- sp,
- ecx.std_path(&[
- sym::fmt,
- sym::ArgumentV1,
- match ty {
- Format(Display) => sym::new_display,
- Format(Debug) => sym::new_debug,
- Format(LowerExp) => sym::new_lower_exp,
- Format(UpperExp) => sym::new_upper_exp,
- Format(Octal) => sym::new_octal,
- Format(Pointer) => sym::new_pointer,
- Format(Binary) => sym::new_binary,
- Format(LowerHex) => sym::new_lower_hex,
- Format(UpperHex) => sym::new_upper_hex,
- Usize => sym::from_usize,
- },
- ]),
- vec![arg],
- )
-}
-
-fn make_count(
- ecx: &ExtCtxt<'_>,
- sp: Span,
- count: &Option<FormatCount>,
- argmap: &mut FxIndexSet<(usize, ArgumentType)>,
-) -> P<ast::Expr> {
- // Generate:
- // ::core::fmt::rt::v1::Count::…(…)
- match count {
- Some(FormatCount::Literal(n)) => ecx.expr_call_global(
- sp,
- ecx.std_path(&[sym::fmt, sym::rt, sym::v1, sym::Count, sym::Is]),
- vec![ecx.expr_usize(sp, *n)],
- ),
- Some(FormatCount::Argument(arg)) => {
- if let Ok(arg_index) = arg.index {
- let (i, _) = argmap.insert_full((arg_index, ArgumentType::Usize));
- ecx.expr_call_global(
- sp,
- ecx.std_path(&[sym::fmt, sym::rt, sym::v1, sym::Count, sym::Param]),
- vec![ecx.expr_usize(sp, i)],
- )
- } else {
- DummyResult::raw_expr(sp, true)
- }
- }
- None => ecx.expr_path(ecx.path_global(
- sp,
- ecx.std_path(&[sym::fmt, sym::rt, sym::v1, sym::Count, sym::Implied]),
- )),
- }
-}
-
-fn make_format_spec(
- ecx: &ExtCtxt<'_>,
- sp: Span,
- placeholder: &FormatPlaceholder,
- argmap: &mut FxIndexSet<(usize, ArgumentType)>,
-) -> P<ast::Expr> {
- // Generate:
- // ::core::fmt::rt::v1::Argument {
- // position: 0usize,
- // format: ::core::fmt::rt::v1::FormatSpec {
- // fill: ' ',
- // align: ::core::fmt::rt::v1::Alignment::Unknown,
- // flags: 0u32,
- // precision: ::core::fmt::rt::v1::Count::Implied,
- // width: ::core::fmt::rt::v1::Count::Implied,
- // },
- // }
- let position = match placeholder.argument.index {
- Ok(arg_index) => {
- let (i, _) =
- argmap.insert_full((arg_index, ArgumentType::Format(placeholder.format_trait)));
- ecx.expr_usize(sp, i)
- }
- Err(_) => DummyResult::raw_expr(sp, true),
- };
- let fill = ecx.expr_char(sp, placeholder.format_options.fill.unwrap_or(' '));
- let align = ecx.expr_path(ecx.path_global(
- sp,
- ecx.std_path(&[
- sym::fmt,
- sym::rt,
- sym::v1,
- sym::Alignment,
- match placeholder.format_options.alignment {
- Some(FormatAlignment::Left) => sym::Left,
- Some(FormatAlignment::Right) => sym::Right,
- Some(FormatAlignment::Center) => sym::Center,
- None => sym::Unknown,
- },
- ]),
- ));
- let flags = ecx.expr_u32(sp, placeholder.format_options.flags);
- let prec = make_count(ecx, sp, &placeholder.format_options.precision, argmap);
- let width = make_count(ecx, sp, &placeholder.format_options.width, argmap);
- ecx.expr_struct(
- sp,
- ecx.path_global(sp, ecx.std_path(&[sym::fmt, sym::rt, sym::v1, sym::Argument])),
- vec![
- ecx.field_imm(sp, Ident::new(sym::position, sp), position),
- ecx.field_imm(
- sp,
- Ident::new(sym::format, sp),
- ecx.expr_struct(
- sp,
- ecx.path_global(
- sp,
- ecx.std_path(&[sym::fmt, sym::rt, sym::v1, sym::FormatSpec]),
- ),
- vec![
- ecx.field_imm(sp, Ident::new(sym::fill, sp), fill),
- ecx.field_imm(sp, Ident::new(sym::align, sp), align),
- ecx.field_imm(sp, Ident::new(sym::flags, sp), flags),
- ecx.field_imm(sp, Ident::new(sym::precision, sp), prec),
- ecx.field_imm(sp, Ident::new(sym::width, sp), width),
- ],
- ),
- ),
- ],
- )
-}
-
-pub fn expand_parsed_format_args(ecx: &mut ExtCtxt<'_>, fmt: FormatArgs) -> P<ast::Expr> {
- let macsp = ecx.with_def_site_ctxt(ecx.call_site());
-
- let lit_pieces = ecx.expr_array_ref(
- fmt.span,
- fmt.template
- .iter()
- .enumerate()
- .filter_map(|(i, piece)| match piece {
- &FormatArgsPiece::Literal(s) => Some(ecx.expr_str(fmt.span, s)),
- &FormatArgsPiece::Placeholder(_) => {
- // Inject empty string before placeholders when not already preceded by a literal piece.
- if i == 0 || matches!(fmt.template[i - 1], FormatArgsPiece::Placeholder(_)) {
- Some(ecx.expr_str(fmt.span, kw::Empty))
- } else {
- None
- }
- }
- })
- .collect(),
- );
-
- // Whether we'll use the `Arguments::new_v1_formatted` form (true),
- // or the `Arguments::new_v1` form (false).
- let mut use_format_options = false;
-
- // Create a list of all _unique_ (argument, format trait) combinations.
- // E.g. "{0} {0:x} {0} {1}" -> [(0, Display), (0, LowerHex), (1, Display)]
- let mut argmap = FxIndexSet::default();
- for piece in &fmt.template {
- let FormatArgsPiece::Placeholder(placeholder) = piece else { continue };
- if placeholder.format_options != Default::default() {
- // Can't use basic form if there's any formatting options.
- use_format_options = true;
- }
- if let Ok(index) = placeholder.argument.index {
- if !argmap.insert((index, ArgumentType::Format(placeholder.format_trait))) {
- // Duplicate (argument, format trait) combination,
- // which we'll only put once in the args array.
- use_format_options = true;
- }
- }
- }
-
- let format_options = use_format_options.then(|| {
- // Generate:
- // &[format_spec_0, format_spec_1, format_spec_2]
- ecx.expr_array_ref(
- macsp,
- fmt.template
- .iter()
- .filter_map(|piece| {
- let FormatArgsPiece::Placeholder(placeholder) = piece else { return None };
- Some(make_format_spec(ecx, macsp, placeholder, &mut argmap))
- })
- .collect(),
- )
- });
-
- let arguments = fmt.arguments.into_vec();
-
- // If the args array contains exactly all the original arguments once,
- // in order, we can use a simple array instead of a `match` construction.
- // However, if there's a yield point in any argument except the first one,
- // we don't do this, because an ArgumentV1 cannot be kept across yield points.
- let use_simple_array = argmap.len() == arguments.len()
- && argmap.iter().enumerate().all(|(i, &(j, _))| i == j)
- && arguments.iter().skip(1).all(|arg| !may_contain_yield_point(&arg.expr));
-
- let args = if use_simple_array {
- // Generate:
- // &[
- // ::core::fmt::ArgumentV1::new_display(&arg0),
- // ::core::fmt::ArgumentV1::new_lower_hex(&arg1),
- // ::core::fmt::ArgumentV1::new_debug(&arg2),
- // ]
- ecx.expr_array_ref(
- macsp,
- arguments
- .into_iter()
- .zip(argmap)
- .map(|(arg, (_, ty))| {
- let sp = arg.expr.span.with_ctxt(macsp.ctxt());
- make_argument(ecx, sp, ecx.expr_addr_of(sp, arg.expr), ty)
- })
- .collect(),
- )
- } else {
- // Generate:
- // match (&arg0, &arg1, &arg2) {
- // args => &[
- // ::core::fmt::ArgumentV1::new_display(args.0),
- // ::core::fmt::ArgumentV1::new_lower_hex(args.1),
- // ::core::fmt::ArgumentV1::new_debug(args.0),
- // ]
- // }
- let args_ident = Ident::new(sym::args, macsp);
- let args = argmap
- .iter()
- .map(|&(arg_index, ty)| {
- if let Some(arg) = arguments.get(arg_index) {
- let sp = arg.expr.span.with_ctxt(macsp.ctxt());
- make_argument(
- ecx,
- sp,
- ecx.expr_field(
- sp,
- ecx.expr_ident(macsp, args_ident),
- Ident::new(sym::integer(arg_index), macsp),
- ),
- ty,
- )
- } else {
- DummyResult::raw_expr(macsp, true)
- }
- })
- .collect();
- ecx.expr_addr_of(
- macsp,
- ecx.expr_match(
- macsp,
- ecx.expr_tuple(
- macsp,
- arguments
- .into_iter()
- .map(|arg| {
- ecx.expr_addr_of(arg.expr.span.with_ctxt(macsp.ctxt()), arg.expr)
- })
- .collect(),
- ),
- vec![ecx.arm(macsp, ecx.pat_ident(macsp, args_ident), ecx.expr_array(macsp, args))],
- ),
- )
- };
-
- if let Some(format_options) = format_options {
- // Generate:
- // ::core::fmt::Arguments::new_v1_formatted(
- // lit_pieces,
- // args,
- // format_options,
- // unsafe { ::core::fmt::UnsafeArg::new() }
- // )
- ecx.expr_call_global(
- macsp,
- ecx.std_path(&[sym::fmt, sym::Arguments, sym::new_v1_formatted]),
- vec![
- lit_pieces,
- args,
- format_options,
- ecx.expr_block(P(ast::Block {
- stmts: vec![ecx.stmt_expr(ecx.expr_call_global(
- macsp,
- ecx.std_path(&[sym::fmt, sym::UnsafeArg, sym::new]),
- Vec::new(),
- ))],
- id: ast::DUMMY_NODE_ID,
- rules: BlockCheckMode::Unsafe(UnsafeSource::CompilerGenerated),
- span: macsp,
- tokens: None,
- could_be_bare_literal: false,
- })),
- ],
- )
- } else {
- // Generate:
- // ::core::fmt::Arguments::new_v1(
- // lit_pieces,
- // args,
- // )
- ecx.expr_call_global(
- macsp,
- ecx.std_path(&[sym::fmt, sym::Arguments, sym::new_v1]),
- vec![lit_pieces, args],
- )
- }
-}
-
-fn may_contain_yield_point(e: &ast::Expr) -> bool {
- struct MayContainYieldPoint(bool);
-
- impl Visitor<'_> for MayContainYieldPoint {
- fn visit_expr(&mut self, e: &ast::Expr) {
- if let ast::ExprKind::Await(_) | ast::ExprKind::Yield(_) = e.kind {
- self.0 = true;
- } else {
- visit::walk_expr(self, e);
- }
- }
-
- fn visit_mac_call(&mut self, _: &ast::MacCall) {
- self.0 = true;
- }
-
- fn visit_attribute(&mut self, _: &ast::Attribute) {
- // Conservatively assume this may be a proc macro attribute in
- // expression position.
- self.0 = true;
- }
-
- fn visit_item(&mut self, _: &ast::Item) {
- // Do not recurse into nested items.
- }
- }
-
- let mut visitor = MayContainYieldPoint(false);
- visitor.visit_expr(e);
- visitor.0
-}
diff --git a/compiler/rustc_builtin_macros/src/global_allocator.rs b/compiler/rustc_builtin_macros/src/global_allocator.rs
index f8761653b..41b51bae7 100644
--- a/compiler/rustc_builtin_macros/src/global_allocator.rs
+++ b/compiler/rustc_builtin_macros/src/global_allocator.rs
@@ -9,7 +9,7 @@ use rustc_ast::{Fn, ItemKind, Mutability, Stmt, Ty, TyKind, Unsafe};
use rustc_expand::base::{Annotatable, ExtCtxt};
use rustc_span::symbol::{kw, sym, Ident, Symbol};
use rustc_span::Span;
-use thin_vec::thin_vec;
+use thin_vec::{thin_vec, ThinVec};
pub fn expand(
ecx: &mut ExtCtxt<'_>,
@@ -47,7 +47,7 @@ pub fn expand(
let stmts = ALLOCATOR_METHODS.iter().map(|method| f.allocator_fn(method)).collect();
// Generate anonymous constant serving as container for the allocator methods.
- let const_ty = ecx.ty(ty_span, TyKind::Tup(Vec::new()));
+ let const_ty = ecx.ty(ty_span, TyKind::Tup(ThinVec::new()));
let const_body = ecx.expr_block(ecx.block(span, stmts));
let const_item = ecx.item_const(span, Ident::new(kw::Underscore, span), const_ty, const_body);
let const_item = if is_stmt {
@@ -70,7 +70,7 @@ struct AllocFnFactory<'a, 'b> {
impl AllocFnFactory<'_, '_> {
fn allocator_fn(&self, method: &AllocatorMethod) -> Stmt {
- let mut abi_args = Vec::new();
+ let mut abi_args = ThinVec::new();
let mut i = 0;
let mut mk = || {
let name = Ident::from_str_and_span(&format!("arg{}", i), self.span);
@@ -99,7 +99,7 @@ impl AllocFnFactory<'_, '_> {
self.cx.stmt_item(self.ty_span, item)
}
- fn call_allocator(&self, method: Symbol, mut args: Vec<P<Expr>>) -> P<Expr> {
+ fn call_allocator(&self, method: Symbol, mut args: ThinVec<P<Expr>>) -> P<Expr> {
let method = self.cx.std_path(&[sym::alloc, sym::GlobalAlloc, method]);
let method = self.cx.expr_path(self.cx.path(self.ty_span, method));
let allocator = self.cx.path_ident(self.ty_span, self.global);
@@ -117,7 +117,7 @@ impl AllocFnFactory<'_, '_> {
fn arg_ty(
&self,
ty: &AllocatorTy,
- args: &mut Vec<Param>,
+ args: &mut ThinVec<Param>,
ident: &mut dyn FnMut() -> Ident,
) -> P<Expr> {
match *ty {
@@ -134,7 +134,7 @@ impl AllocFnFactory<'_, '_> {
let layout_new = self.cx.expr_path(self.cx.path(self.span, layout_new));
let size = self.cx.expr_ident(self.span, size);
let align = self.cx.expr_ident(self.span, align);
- let layout = self.cx.expr_call(self.span, layout_new, vec![size, align]);
+ let layout = self.cx.expr_call(self.span, layout_new, thin_vec![size, align]);
layout
}
@@ -168,7 +168,7 @@ impl AllocFnFactory<'_, '_> {
(self.ptr_u8(), expr)
}
- AllocatorTy::Unit => (self.cx.ty(self.span, TyKind::Tup(Vec::new())), expr),
+ AllocatorTy::Unit => (self.cx.ty(self.span, TyKind::Tup(ThinVec::new())), expr),
AllocatorTy::Layout | AllocatorTy::Usize | AllocatorTy::Ptr => {
panic!("can't convert `AllocatorTy` to an output")
diff --git a/compiler/rustc_builtin_macros/src/lib.rs b/compiler/rustc_builtin_macros/src/lib.rs
index 75cfac723..8afb6e560 100644
--- a/compiler/rustc_builtin_macros/src/lib.rs
+++ b/compiler/rustc_builtin_macros/src/lib.rs
@@ -21,8 +21,10 @@ extern crate tracing;
use crate::deriving::*;
+use rustc_errors::{DiagnosticMessage, SubdiagnosticMessage};
use rustc_expand::base::{MacroExpanderFn, ResolverExpand, SyntaxExtensionKind};
use rustc_expand::proc_macro::BangProcMacro;
+use rustc_macros::fluent_messages;
use rustc_span::symbol::sym;
mod alloc_error_handler;
@@ -54,6 +56,8 @@ pub mod proc_macro_harness;
pub mod standard_library_imports;
pub mod test_harness;
+fluent_messages! { "../locales/en-US.ftl" }
+
pub fn register_builtin_macros(resolver: &mut dyn ResolverExpand) {
let mut register = |name, kind| resolver.register_builtin_macro(name, kind);
macro register_bang($($name:ident: $f:expr,)*) {
diff --git a/compiler/rustc_builtin_macros/src/proc_macro_harness.rs b/compiler/rustc_builtin_macros/src/proc_macro_harness.rs
index 21c8caa65..bc513607d 100644
--- a/compiler/rustc_builtin_macros/src/proc_macro_harness.rs
+++ b/compiler/rustc_builtin_macros/src/proc_macro_harness.rs
@@ -11,6 +11,7 @@ use rustc_span::symbol::{kw, sym, Ident, Symbol};
use rustc_span::{Span, DUMMY_SP};
use smallvec::smallvec;
use std::mem;
+use thin_vec::{thin_vec, ThinVec};
struct ProcMacroDerive {
id: NodeId,
@@ -314,11 +315,14 @@ fn mk_decls(cx: &mut ExtCtxt<'_>, macros: &[ProcMacro]) -> P<ast::Item> {
cx.expr_call(
span,
proc_macro_ty_method_path(cx, custom_derive),
- vec![
+ thin_vec![
cx.expr_str(span, cd.trait_name),
cx.expr_array_ref(
span,
- cd.attrs.iter().map(|&s| cx.expr_str(span, s)).collect::<Vec<_>>(),
+ cd.attrs
+ .iter()
+ .map(|&s| cx.expr_str(span, s))
+ .collect::<ThinVec<_>>(),
),
local_path(cx, cd.function_name),
],
@@ -335,7 +339,7 @@ fn mk_decls(cx: &mut ExtCtxt<'_>, macros: &[ProcMacro]) -> P<ast::Item> {
cx.expr_call(
span,
proc_macro_ty_method_path(cx, ident),
- vec![
+ thin_vec![
cx.expr_str(span, ca.function_name.name),
local_path(cx, ca.function_name),
],
@@ -371,13 +375,13 @@ fn mk_decls(cx: &mut ExtCtxt<'_>, macros: &[ProcMacro]) -> P<ast::Item> {
});
let block = cx.expr_block(
- cx.block(span, vec![cx.stmt_item(span, krate), cx.stmt_item(span, decls_static)]),
+ cx.block(span, thin_vec![cx.stmt_item(span, krate), cx.stmt_item(span, decls_static)]),
);
let anon_constant = cx.item_const(
span,
Ident::new(kw::Underscore, span),
- cx.ty(span, ast::TyKind::Tup(Vec::new())),
+ cx.ty(span, ast::TyKind::Tup(ThinVec::new())),
block,
);
diff --git a/compiler/rustc_builtin_macros/src/standard_library_imports.rs b/compiler/rustc_builtin_macros/src/standard_library_imports.rs
index f73f20c84..e67c0dba6 100644
--- a/compiler/rustc_builtin_macros/src/standard_library_imports.rs
+++ b/compiler/rustc_builtin_macros/src/standard_library_imports.rs
@@ -62,7 +62,7 @@ pub fn inject(
// the one with the prelude.
let name = names[0];
- let root = (edition == Edition2015).then(|| kw::PathRoot);
+ let root = (edition == Edition2015).then_some(kw::PathRoot);
let import_path = root
.iter()
diff --git a/compiler/rustc_builtin_macros/src/test.rs b/compiler/rustc_builtin_macros/src/test.rs
index 729ae4071..e02c7e6c0 100644
--- a/compiler/rustc_builtin_macros/src/test.rs
+++ b/compiler/rustc_builtin_macros/src/test.rs
@@ -10,7 +10,7 @@ use rustc_session::Session;
use rustc_span::symbol::{sym, Ident, Symbol};
use rustc_span::Span;
use std::iter;
-use thin_vec::thin_vec;
+use thin_vec::{thin_vec, ThinVec};
/// #[test_case] is used by custom test authors to mark tests
/// When building for test, it needs to make the item public and gensym the name
@@ -179,19 +179,19 @@ pub fn expand_test_or_bench(
cx.expr_call(
sp,
cx.expr_path(test_path("StaticBenchFn")),
- vec![
+ thin_vec![
// |b| self::test::assert_test_result(
cx.lambda1(
sp,
cx.expr_call(
sp,
cx.expr_path(test_path("assert_test_result")),
- vec![
+ thin_vec![
// super::$test_fn(b)
cx.expr_call(
ret_ty_sp,
cx.expr_path(cx.path(sp, vec![item.ident])),
- vec![cx.expr_ident(sp, b)],
+ thin_vec![cx.expr_ident(sp, b)],
),
],
),
@@ -203,7 +203,7 @@ pub fn expand_test_or_bench(
cx.expr_call(
sp,
cx.expr_path(test_path("StaticTestFn")),
- vec![
+ thin_vec![
// || {
cx.lambda0(
sp,
@@ -211,12 +211,12 @@ pub fn expand_test_or_bench(
cx.expr_call(
sp,
cx.expr_path(test_path("assert_test_result")),
- vec![
+ thin_vec![
// $test_fn()
cx.expr_call(
ret_ty_sp,
cx.expr_path(cx.path(sp, vec![item.ident])),
- vec![],
+ ThinVec::new(),
), // )
],
), // }
@@ -249,21 +249,21 @@ pub fn expand_test_or_bench(
cx.expr_struct(
sp,
test_path("TestDescAndFn"),
- vec![
+ thin_vec![
// desc: test::TestDesc {
field(
"desc",
cx.expr_struct(
sp,
test_path("TestDesc"),
- vec![
+ thin_vec![
// name: "path::to::test"
field(
"name",
cx.expr_call(
sp,
cx.expr_path(test_path("StaticTestName")),
- vec![cx.expr_str(sp, test_path_symbol)],
+ thin_vec![cx.expr_str(sp, test_path_symbol)],
),
),
// ignore: true | false
@@ -300,7 +300,7 @@ pub fn expand_test_or_bench(
ShouldPanic::Yes(Some(sym)) => cx.expr_call(
sp,
cx.expr_path(should_panic_path("YesWithMessage")),
- vec![cx.expr_str(sp, sym)],
+ thin_vec![cx.expr_str(sp, sym)],
),
},
),
diff --git a/compiler/rustc_builtin_macros/src/test_harness.rs b/compiler/rustc_builtin_macros/src/test_harness.rs
index ad8871080..d8e3db9e8 100644
--- a/compiler/rustc_builtin_macros/src/test_harness.rs
+++ b/compiler/rustc_builtin_macros/src/test_harness.rs
@@ -14,7 +14,8 @@ use rustc_span::symbol::{sym, Ident, Symbol};
use rustc_span::{Span, DUMMY_SP};
use rustc_target::spec::PanicStrategy;
use smallvec::{smallvec, SmallVec};
-use thin_vec::thin_vec;
+use thin_vec::{thin_vec, ThinVec};
+use tracing::debug;
use std::{iter, mem};
@@ -299,7 +300,7 @@ fn mk_main(cx: &mut TestCtxt<'_>) -> P<ast::Item> {
test_runner.span = sp;
let test_main_path_expr = ecx.expr_path(test_runner);
- let call_test_main = ecx.expr_call(sp, test_main_path_expr, vec![mk_tests_slice(cx, sp)]);
+ let call_test_main = ecx.expr_call(sp, test_main_path_expr, thin_vec![mk_tests_slice(cx, sp)]);
let call_test_main = ecx.stmt_expr(call_test_main);
// extern crate test
@@ -312,16 +313,16 @@ fn mk_main(cx: &mut TestCtxt<'_>) -> P<ast::Item> {
let main_attr = ecx.attr_word(sym::rustc_main, sp);
// pub fn main() { ... }
- let main_ret_ty = ecx.ty(sp, ast::TyKind::Tup(vec![]));
+ let main_ret_ty = ecx.ty(sp, ast::TyKind::Tup(ThinVec::new()));
// If no test runner is provided we need to import the test crate
let main_body = if cx.test_runner.is_none() {
- ecx.block(sp, vec![test_extern_stmt, call_test_main])
+ ecx.block(sp, thin_vec![test_extern_stmt, call_test_main])
} else {
- ecx.block(sp, vec![call_test_main])
+ ecx.block(sp, thin_vec![call_test_main])
};
- let decl = ecx.fn_decl(vec![], ast::FnRetTy::Ty(main_ret_ty));
+ let decl = ecx.fn_decl(ThinVec::new(), ast::FnRetTy::Ty(main_ret_ty));
let sig = ast::FnSig { decl, header: ast::FnHeader::default(), span: sp };
let defaultness = ast::Defaultness::Final;
let main = ast::ItemKind::Fn(Box::new(ast::Fn {
diff --git a/compiler/rustc_codegen_cranelift/.cirrus.yml b/compiler/rustc_codegen_cranelift/.cirrus.yml
index d627c2ee0..7886cae42 100644
--- a/compiler/rustc_codegen_cranelift/.cirrus.yml
+++ b/compiler/rustc_codegen_cranelift/.cirrus.yml
@@ -1,13 +1,11 @@
task:
name: freebsd
freebsd_instance:
- image: freebsd-12-1-release-amd64
+ image: freebsd-13-1-release-amd64
setup_rust_script:
- pkg install -y curl git bash
- curl https://sh.rustup.rs -sSf --output rustup.sh
- sh rustup.sh --default-toolchain none -y --profile=minimal
- cargo_bin_cache:
- folder: ~/.cargo/bin
target_cache:
folder: target
prepare_script:
@@ -15,9 +13,4 @@ task:
- ./y.rs prepare
test_script:
- . $HOME/.cargo/env
- - # 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
- ./y.rs test
diff --git a/compiler/rustc_codegen_cranelift/.github/workflows/main.yml b/compiler/rustc_codegen_cranelift/.github/workflows/main.yml
index a6bb12a66..9d3ed3ac5 100644
--- a/compiler/rustc_codegen_cranelift/.github/workflows/main.yml
+++ b/compiler/rustc_codegen_cranelift/.github/workflows/main.yml
@@ -21,15 +21,20 @@ jobs:
cargo fmt --check
rustfmt --check build_system/mod.rs
+
build:
runs-on: ${{ matrix.os }}
timeout-minutes: 60
+ defaults:
+ run:
+ shell: bash
+
strategy:
fail-fast: false
matrix:
include:
- - os: ubuntu-20.04 # FIXME switch to ubuntu-22.04 once #1303 is fixed
+ - os: ubuntu-latest
env:
TARGET_TRIPLE: x86_64-unknown-linux-gnu
- os: macos-latest
@@ -46,36 +51,31 @@ jobs:
- os: ubuntu-latest
env:
TARGET_TRIPLE: s390x-unknown-linux-gnu
+ - os: windows-latest
+ env:
+ TARGET_TRIPLE: x86_64-pc-windows-msvc
+ - os: windows-latest
+ env:
+ TARGET_TRIPLE: x86_64-pc-windows-gnu
steps:
- uses: actions/checkout@v3
- - name: Cache cargo installed crates
- uses: actions/cache@v3
- with:
- path: ~/.cargo/bin
- key: ${{ runner.os }}-cargo-installed-crates
-
- - name: Cache cargo registry and index
- uses: actions/cache@v3
- with:
- path: |
- ~/.cargo/registry
- ~/.cargo/git
- key: ${{ runner.os }}-cargo-registry-and-index-${{ hashFiles('**/Cargo.lock') }}
-
- name: Cache cargo target dir
uses: actions/cache@v3
with:
path: build/cg_clif
- key: ${{ runner.os }}-cargo-build-target-${{ hashFiles('rust-toolchain', '**/Cargo.lock') }}
+ key: ${{ runner.os }}-${{ matrix.env.TARGET_TRIPLE }}-cargo-build-target-${{ hashFiles('rust-toolchain', '**/Cargo.lock') }}
+
+ - name: Set MinGW as the default toolchain
+ if: matrix.os == 'windows-latest' && matrix.env.TARGET_TRIPLE == 'x86_64-pc-windows-gnu'
+ run: rustup set default-host x86_64-pc-windows-gnu
- name: Install MinGW toolchain and wine
if: matrix.os == 'ubuntu-latest' && matrix.env.TARGET_TRIPLE == 'x86_64-pc-windows-gnu'
run: |
sudo apt-get update
sudo apt-get install -y gcc-mingw-w64-x86-64 wine-stable
- rustup target add x86_64-pc-windows-gnu
- name: Install AArch64 toolchain and qemu
if: matrix.os == 'ubuntu-latest' && matrix.env.TARGET_TRIPLE == 'aarch64-unknown-linux-gnu'
@@ -89,6 +89,13 @@ jobs:
sudo apt-get update
sudo apt-get install -y gcc-s390x-linux-gnu qemu-user
+ - name: Use sparse cargo registry
+ run: |
+ cat >> ~/.cargo/config.toml <<EOF
+ [unstable]
+ sparse-registry = true
+ EOF
+
- name: Prepare dependencies
run: ./y.rs prepare
@@ -104,49 +111,30 @@ jobs:
- name: Test
env:
TARGET_TRIPLE: ${{ matrix.env.TARGET_TRIPLE }}
- run: |
- # Enable backtraces for easier debugging
- export RUST_BACKTRACE=1
-
- # Reduce amount of benchmark runs as they are slow
- export COMPILE_RUNS=2
- export RUN_RUNS=2
-
- # Enable extra checks
- export CG_CLIF_ENABLE_VERIFIER=1
-
- ./y.rs test
-
- - name: Package prebuilt cg_clif
- run: tar cvfJ cg_clif.tar.xz dist
+ run: ./y.rs test
- - name: Upload prebuilt cg_clif
- if: matrix.env.TARGET_TRIPLE != 'x86_64-pc-windows-gnu'
- uses: actions/upload-artifact@v2
- with:
- name: cg_clif-${{ matrix.env.TARGET_TRIPLE }}
- path: cg_clif.tar.xz
- - name: Upload prebuilt cg_clif (cross compile)
- if: matrix.env.TARGET_TRIPLE == 'x86_64-pc-windows-gnu'
- uses: actions/upload-artifact@v3
- with:
- name: cg_clif-${{ runner.os }}-cross-x86_64-mingw
- path: cg_clif.tar.xz
-
- windows:
+ abi_cafe:
runs-on: ${{ matrix.os }}
timeout-minutes: 60
+ defaults:
+ run:
+ shell: bash
+
strategy:
- fail-fast: false
+ fail-fast: true
matrix:
include:
- # Native Windows build with MSVC
+ - os: ubuntu-latest
+ env:
+ TARGET_TRIPLE: x86_64-unknown-linux-gnu
+ - os: macos-latest
+ env:
+ TARGET_TRIPLE: x86_64-apple-darwin
- os: windows-latest
env:
TARGET_TRIPLE: x86_64-pc-windows-msvc
- # cross-compile from Windows to Windows MinGW
- os: windows-latest
env:
TARGET_TRIPLE: x86_64-pc-windows-gnu
@@ -154,20 +142,6 @@ jobs:
steps:
- uses: actions/checkout@v3
- - name: Cache cargo installed crates
- uses: actions/cache@v3
- with:
- path: ~/.cargo/bin
- key: ${{ runner.os }}-${{ matrix.env.TARGET_TRIPLE }}-cargo-installed-crates
-
- - name: Cache cargo registry and index
- uses: actions/cache@v3
- with:
- path: |
- ~/.cargo/registry
- ~/.cargo/git
- key: ${{ runner.os }}-${{ matrix.env.TARGET_TRIPLE }}-cargo-registry-and-index-${{ hashFiles('**/Cargo.lock') }}
-
- name: Cache cargo target dir
uses: actions/cache@v3
with:
@@ -178,50 +152,146 @@ jobs:
if: matrix.env.TARGET_TRIPLE == 'x86_64-pc-windows-gnu'
run: rustup set default-host x86_64-pc-windows-gnu
- - name: Prepare dependencies
+ - name: Use sparse cargo registry
run: |
- git config --global core.autocrlf false
- rustc y.rs -o y.exe -g
- ./y.exe prepare
+ cat >> ~/.cargo/config.toml <<EOF
+ [unstable]
+ sparse-registry = true
+ EOF
- - name: Build without unstable features
- env:
- TARGET_TRIPLE: ${{ matrix.env.TARGET_TRIPLE }}
- # This is the config rust-lang/rust uses for builds
- run: ./y.rs build --no-unstable-features
+ - name: Prepare dependencies
+ run: ./y.rs prepare
- name: Build
run: ./y.rs build --sysroot none
- - name: Test
+ - name: Test abi-cafe
+ env:
+ TARGET_TRIPLE: ${{ matrix.env.TARGET_TRIPLE }}
+ run: ./y.rs abi-cafe
+
+
+ bench:
+ runs-on: ubuntu-latest
+ timeout-minutes: 60
+
+ defaults:
+ run:
+ shell: bash
+
+ steps:
+ - uses: actions/checkout@v3
+
+ - name: Cache cargo target dir
+ uses: actions/cache@v3
+ with:
+ path: build/cg_clif
+ key: ${{ runner.os }}-x86_64-unknown-linux-gnu-cargo-build-target-${{ hashFiles('rust-toolchain', '**/Cargo.lock') }}
+
+ - name: Cache cargo bin dir
+ uses: actions/cache@v3
+ with:
+ path: ~/.cargo/bin
+ key: ${{ runner.os }}-${{ matrix.env.TARGET_TRIPLE }}-cargo-bin-dir-${{ hashFiles('rust-toolchain', '**/Cargo.lock') }}
+
+ - name: Use sparse cargo registry
run: |
- # Enable backtraces for easier debugging
- $Env:RUST_BACKTRACE=1
+ cat >> ~/.cargo/config.toml <<EOF
+ [unstable]
+ sparse-registry = true
+ EOF
- # Reduce amount of benchmark runs as they are slow
- $Env:COMPILE_RUNS=2
- $Env:RUN_RUNS=2
+ - name: Install hyperfine
+ run: cargo install hyperfine || true
- # Enable extra checks
- $Env:CG_CLIF_ENABLE_VERIFIER=1
+ - name: Prepare dependencies
+ run: ./y.rs prepare
+
+ - name: Build
+ run: CI_OPT=1 ./y.rs build --sysroot none
- # WIP Disable some tests
+ - name: Benchmark
+ run: CI_OPT=1 ./y.rs bench
- # This fails due to some weird argument handling by hyperfine, not an actual regression
- # more of a build system issue
- (Get-Content config.txt) -replace '(bench.simple-raytracer)', '# $1' | Out-File config.txt
- # This fails with a different output than expected
- (Get-Content config.txt) -replace '(test.regex-shootout-regex-dna)', '# $1' | Out-File config.txt
+ dist:
+ runs-on: ${{ matrix.os }}
+ timeout-minutes: 60
- ./y.exe test
+ defaults:
+ run:
+ shell: bash
+
+ strategy:
+ fail-fast: false
+ matrix:
+ include:
+ # FIXME update at some point in the future once most distros use a newer glibc
+ - os: ubuntu-20.04
+ env:
+ TARGET_TRIPLE: x86_64-unknown-linux-gnu
+ - os: macos-latest
+ env:
+ TARGET_TRIPLE: x86_64-apple-darwin
+ # cross-compile from Linux to Windows using mingw
+ - os: ubuntu-latest
+ env:
+ TARGET_TRIPLE: x86_64-pc-windows-gnu
+ - os: windows-latest
+ env:
+ TARGET_TRIPLE: x86_64-pc-windows-msvc
+ - os: windows-latest
+ env:
+ TARGET_TRIPLE: x86_64-pc-windows-gnu
+
+ steps:
+ - uses: actions/checkout@v3
+
+ - name: Cache cargo target dir
+ uses: actions/cache@v3
+ with:
+ path: build/cg_clif
+ key: ${{ runner.os }}-${{ matrix.env.TARGET_TRIPLE }}-dist-cargo-build-target-${{ hashFiles('rust-toolchain', '**/Cargo.lock') }}
+
+ - name: Set MinGW as the default toolchain
+ if: matrix.os == 'windows-latest' && matrix.env.TARGET_TRIPLE == 'x86_64-pc-windows-gnu'
+ run: rustup set default-host x86_64-pc-windows-gnu
+
+ - name: Install MinGW toolchain and wine
+ if: matrix.os == 'ubuntu-latest' && matrix.env.TARGET_TRIPLE == 'x86_64-pc-windows-gnu'
+ run: |
+ sudo apt-get update
+ sudo apt-get install -y gcc-mingw-w64-x86-64 wine-stable
+
+ - name: Use sparse cargo registry
+ run: |
+ cat >> ~/.cargo/config.toml <<EOF
+ [unstable]
+ sparse-registry = true
+ EOF
+
+ - name: Prepare dependencies
+ run: ./y.rs prepare
+
+ - name: Build backend
+ run: CI_OPT=1 ./y.rs build --sysroot none
+
+ - name: Build sysroot
+ run: CI_OPT=1 ./y.rs build
- name: Package prebuilt cg_clif
- # don't use compression as xzip isn't supported by tar on windows and bzip2 hangs
- run: tar cvf cg_clif.tar dist
+ run: tar cvfJ cg_clif.tar.xz dist
- name: Upload prebuilt cg_clif
+ if: matrix.os == 'windows-latest' || matrix.env.TARGET_TRIPLE != 'x86_64-pc-windows-gnu'
uses: actions/upload-artifact@v3
with:
name: cg_clif-${{ matrix.env.TARGET_TRIPLE }}
- path: cg_clif.tar
+ path: cg_clif.tar.xz
+
+ - name: Upload prebuilt cg_clif (cross compile)
+ if: matrix.os != 'windows-latest' && matrix.env.TARGET_TRIPLE == 'x86_64-pc-windows-gnu'
+ uses: actions/upload-artifact@v3
+ with:
+ name: cg_clif-${{ runner.os }}-cross-x86_64-mingw
+ path: cg_clif.tar.xz
diff --git a/compiler/rustc_codegen_cranelift/.github/workflows/nightly-cranelift.yml b/compiler/rustc_codegen_cranelift/.github/workflows/nightly-cranelift.yml
deleted file mode 100644
index d0d58d2a7..000000000
--- a/compiler/rustc_codegen_cranelift/.github/workflows/nightly-cranelift.yml
+++ /dev/null
@@ -1,59 +0,0 @@
-name: Test nightly Cranelift
-
-on:
- push:
- schedule:
- - cron: '17 1 * * *' # At 01:17 UTC every day.
-
-jobs:
- build:
- runs-on: ubuntu-latest
- timeout-minutes: 60
-
- steps:
- - uses: actions/checkout@v3
-
- - name: Cache cargo installed crates
- uses: actions/cache@v3
- with:
- path: ~/.cargo/bin
- key: ubuntu-latest-cargo-installed-crates
-
- - name: Prepare dependencies
- run: |
- git config --global user.email "user@example.com"
- git config --global user.name "User"
- ./y.rs prepare
-
- - name: Patch Cranelift
- run: |
- sed -i 's/cranelift-codegen = { version = "\w*.\w*.\w*", features = \["unwind", "all-arch"\] }/cranelift-codegen = { git = "https:\/\/github.com\/bytecodealliance\/wasmtime.git", features = ["unwind", "all-arch"] }/' Cargo.toml
- sed -i 's/cranelift-frontend = "\w*.\w*.\w*"/cranelift-frontend = { git = "https:\/\/github.com\/bytecodealliance\/wasmtime.git" }/' Cargo.toml
- sed -i 's/cranelift-module = "\w*.\w*.\w*"/cranelift-module = { git = "https:\/\/github.com\/bytecodealliance\/wasmtime.git" }/' Cargo.toml
- sed -i 's/cranelift-native = "\w*.\w*.\w*"/cranelift-native = { git = "https:\/\/github.com\/bytecodealliance\/wasmtime.git" }/' Cargo.toml
- sed -i 's/cranelift-jit = { version = "\w*.\w*.\w*", optional = true }/cranelift-jit = { git = "https:\/\/github.com\/bytecodealliance\/wasmtime.git", optional = true }/' Cargo.toml
- sed -i 's/cranelift-object = "\w*.\w*.\w*"/cranelift-object = { git = "https:\/\/github.com\/bytecodealliance\/wasmtime.git" }/' Cargo.toml
-
- sed -i 's/object = { version = "0.27.0"/object = { version = "0.28.0"/' Cargo.toml
-
- cat Cargo.toml
-
- - name: Build without unstable features
- # This is the config rust-lang/rust uses for builds
- run: ./y.rs build --no-unstable-features
-
- - name: Build
- run: ./y.rs build --sysroot none
- - name: Test
- run: |
- # Enable backtraces for easier debugging
- export RUST_BACKTRACE=1
-
- # Reduce amount of benchmark runs as they are slow
- export COMPILE_RUNS=2
- export RUN_RUNS=2
-
- # Enable extra checks
- export CG_CLIF_ENABLE_VERIFIER=1
-
- ./test.sh
diff --git a/compiler/rustc_codegen_cranelift/.github/workflows/rustc.yml b/compiler/rustc_codegen_cranelift/.github/workflows/rustc.yml
index bef806318..5faa8f054 100644
--- a/compiler/rustc_codegen_cranelift/.github/workflows/rustc.yml
+++ b/compiler/rustc_codegen_cranelift/.github/workflows/rustc.yml
@@ -10,73 +10,45 @@ jobs:
steps:
- uses: actions/checkout@v3
- - name: Cache cargo installed crates
- uses: actions/cache@v3
- with:
- path: ~/.cargo/bin
- key: ${{ runner.os }}-cargo-installed-crates
-
- - name: Cache cargo registry and index
- uses: actions/cache@v3
- with:
- path: |
- ~/.cargo/registry
- ~/.cargo/git
- key: ${{ runner.os }}-cargo-registry-and-index-${{ hashFiles('**/Cargo.lock') }}
-
- name: Cache cargo target dir
uses: actions/cache@v3
with:
path: build/cg_clif
key: ${{ runner.os }}-cargo-build-target-${{ hashFiles('rust-toolchain', '**/Cargo.lock') }}
- - name: Prepare dependencies
+ - name: Use sparse cargo registry
run: |
- git config --global user.email "user@example.com"
- git config --global user.name "User"
- ./y.rs prepare
+ cat >> ~/.cargo/config.toml <<EOF
+ [unstable]
+ sparse-registry = true
+ EOF
- - name: Test
- run: |
- # Enable backtraces for easier debugging
- export RUST_BACKTRACE=1
+ - name: Prepare dependencies
+ run: ./y.rs prepare
- ./scripts/test_bootstrap.sh
+ - name: Test
+ run: ./scripts/test_bootstrap.sh
rustc_test_suite:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- - name: Cache cargo installed crates
- uses: actions/cache@v3
- with:
- path: ~/.cargo/bin
- key: ${{ runner.os }}-cargo-installed-crates
-
- - name: Cache cargo registry and index
- uses: actions/cache@v3
- with:
- path: |
- ~/.cargo/registry
- ~/.cargo/git
- key: ${{ runner.os }}-cargo-registry-and-index-${{ hashFiles('**/Cargo.lock') }}
-
- name: Cache cargo target dir
uses: actions/cache@v3
with:
path: build/cg_clif
key: ${{ runner.os }}-cargo-build-target-${{ hashFiles('rust-toolchain', '**/Cargo.lock') }}
- - name: Prepare dependencies
+ - name: Use sparse cargo registry
run: |
- git config --global user.email "user@example.com"
- git config --global user.name "User"
- ./y.rs prepare
+ cat >> ~/.cargo/config.toml <<EOF
+ [unstable]
+ sparse-registry = true
+ EOF
- - name: Test
- run: |
- # Enable backtraces for easier debugging
- export RUST_BACKTRACE=1
+ - name: Prepare dependencies
+ run: ./y.rs prepare
- ./scripts/test_rustc_tests.sh
+ - name: Test
+ run: ./scripts/test_rustc_tests.sh
diff --git a/compiler/rustc_codegen_cranelift/.vscode/settings.json b/compiler/rustc_codegen_cranelift/.vscode/settings.json
index bc914e37d..7c8703cba 100644
--- a/compiler/rustc_codegen_cranelift/.vscode/settings.json
+++ b/compiler/rustc_codegen_cranelift/.vscode/settings.json
@@ -1,4 +1,6 @@
{
+ "editor.formatOnSave": true,
+
// source for rustc_* is not included in the rust-src component; disable the errors about this
"rust-analyzer.diagnostics.disabled": ["unresolved-extern-crate", "unresolved-macro-call"],
"rust-analyzer.imports.granularity.enforce": true,
@@ -30,7 +32,7 @@
]
},
{
- "sysroot_src": "./build_sysroot/sysroot_src/library",
+ "sysroot_src": "./download/sysroot/sysroot_src/library",
"crates": [
{
"root_module": "./example/std_example.rs",
diff --git a/compiler/rustc_codegen_cranelift/Cargo.lock b/compiler/rustc_codegen_cranelift/Cargo.lock
index e4d3e9ca5..50249ea1b 100644
--- a/compiler/rustc_codegen_cranelift/Cargo.lock
+++ b/compiler/rustc_codegen_cranelift/Cargo.lock
@@ -57,28 +57,28 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "cranelift-bforest"
-version = "0.90.1"
+version = "0.92.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b62c772976416112fa4484cbd688cb6fb35fd430005c1c586224fc014018abad"
+checksum = "2f3d54eab028f5805ae3b26fd60eca3f3a9cfb76b989d9bab173be3f61356cc3"
dependencies = [
"cranelift-entity",
]
[[package]]
name = "cranelift-codegen"
-version = "0.90.1"
+version = "0.92.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9b40ed2dd13c2ac7e24f88a3090c68ad3414eb1d066a95f8f1f7b3b819cb4e46"
+checksum = "2be1d5f2c3cca1efb691844bc1988b89c77291f13f778499a3f3c0cf49c0ed61"
dependencies = [
"arrayvec",
"bumpalo",
"cranelift-bforest",
"cranelift-codegen-meta",
"cranelift-codegen-shared",
- "cranelift-egraph",
"cranelift-entity",
"cranelift-isle",
"gimli",
+ "hashbrown",
"log",
"regalloc2",
"smallvec",
@@ -87,44 +87,30 @@ dependencies = [
[[package]]
name = "cranelift-codegen-meta"
-version = "0.90.1"
+version = "0.92.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bb927a8f1c27c34ee3759b6b0ffa528d2330405d5cc4511f0cab33fe2279f4b5"
+checksum = "3f9b1b1089750ce4005893af7ee00bb08a2cf1c9779999c0f7164cbc8ad2e0d2"
dependencies = [
"cranelift-codegen-shared",
]
[[package]]
name = "cranelift-codegen-shared"
-version = "0.90.1"
+version = "0.92.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "43dfa417b884a9ab488d95fd6b93b25e959321fe7bfd7a0a960ba5d7fb7ab927"
-
-[[package]]
-name = "cranelift-egraph"
-version = "0.90.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e0a66b39785efd8513d2cca967ede56d6cc57c8d7986a595c7c47d0c78de8dce"
-dependencies = [
- "cranelift-entity",
- "fxhash",
- "hashbrown",
- "indexmap",
- "log",
- "smallvec",
-]
+checksum = "cc5fbaec51de47297fd7304986fd53c8c0030abbe69728a60d72e1c63559318d"
[[package]]
name = "cranelift-entity"
-version = "0.90.1"
+version = "0.92.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0637ffde963cb5d759bc4d454cfa364b6509e6c74cdaa21298add0ed9276f346"
+checksum = "dab984c94593f876090fae92e984bdcc74d9b1acf740ab5f79036001c65cba13"
[[package]]
name = "cranelift-frontend"
-version = "0.90.1"
+version = "0.92.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fb72b8342685e850cb037350418f62cc4fc55d6c2eb9c7ca01b82f9f1a6f3d56"
+checksum = "6e0cb3102d21a2fe5f3210af608748ddd0cd09825ac12d42dc56ed5ed8725fe0"
dependencies = [
"cranelift-codegen",
"log",
@@ -134,15 +120,15 @@ dependencies = [
[[package]]
name = "cranelift-isle"
-version = "0.90.1"
+version = "0.92.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "850579cb9e4b448f7c301f1e6e6cbad99abe3f1f1d878a4994cb66e33c6db8cd"
+checksum = "72101dd1f441d629735143c41e00b3428f9267738176983ef588ff43382af0a0"
[[package]]
name = "cranelift-jit"
-version = "0.90.1"
+version = "0.92.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9add822ad66dcbe152b5ab57de10240a2df4505099f2f6c27159acb711890bd4"
+checksum = "6557f8ce44d498777f2495aa58d9692a4a37d6f84aa445750d666cef770b6a5c"
dependencies = [
"anyhow",
"cranelift-codegen",
@@ -159,9 +145,9 @@ dependencies = [
[[package]]
name = "cranelift-module"
-version = "0.90.1"
+version = "0.92.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "406b772626fc2664864cf947f3895a23b619895c7fff635f3622e2d857f4492f"
+checksum = "88807e1c0c47ec02fe433333ccbe56b480425418b1470e333205e11650697d72"
dependencies = [
"anyhow",
"cranelift-codegen",
@@ -169,9 +155,9 @@ dependencies = [
[[package]]
name = "cranelift-native"
-version = "0.90.1"
+version = "0.92.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2d0a279e5bcba3e0466c734d8d8eb6bfc1ad29e95c37f3e4955b492b5616335e"
+checksum = "c22b0d9fcbe3fc5a1af9e7021b44ce42b930bcefac446ce22e02e8f9a0d67120"
dependencies = [
"cranelift-codegen",
"libc",
@@ -180,9 +166,9 @@ dependencies = [
[[package]]
name = "cranelift-object"
-version = "0.90.1"
+version = "0.92.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "39793c550f0c1d7db96c2fc1324583670c8143befe6edbfbaf1c68aba53be983"
+checksum = "341375758d7c3fedc0b5315f552e6f0feac46baf87c450a15e9455ef47c2b261"
dependencies = [
"anyhow",
"cranelift-codegen",
@@ -317,9 +303,9 @@ checksum = "86f0b0d4bf799edbc74508c1e8bf170ff5f41238e5f8225603ca7caaae2b7860"
[[package]]
name = "regalloc2"
-version = "0.4.2"
+version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "91b2eab54204ea0117fe9a060537e0b07a4e72f7c7d182361ecc346cab2240e5"
+checksum = "300d4fbfb40c1c66a78ba3ddd41c1110247cf52f97b87d0f2fc9209bd49b030c"
dependencies = [
"fxhash",
"log",
@@ -347,7 +333,6 @@ dependencies = [
"cranelift-frontend",
"cranelift-jit",
"cranelift-module",
- "cranelift-native",
"cranelift-object",
"gimli",
"indexmap",
@@ -396,9 +381,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
[[package]]
name = "wasmtime-jit-icache-coherence"
-version = "2.0.1"
+version = "5.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e6bbabb309c06cc238ee91b1455b748c45f0bdcab0dda2c2db85b0a1e69fcb66"
+checksum = "08fcba5ebd96da2a9f0747ab6337fe9788adfb3f63fa2c180520d665562d257e"
dependencies = [
"cfg-if",
"libc",
@@ -429,43 +414,57 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
[[package]]
name = "windows-sys"
-version = "0.36.1"
+version = "0.42.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ea04155a16a59f9eab786fe12a4a450e75cdb175f9e0d80da1e17db09f55b8d2"
+checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7"
dependencies = [
+ "windows_aarch64_gnullvm",
"windows_aarch64_msvc",
"windows_i686_gnu",
"windows_i686_msvc",
"windows_x86_64_gnu",
+ "windows_x86_64_gnullvm",
"windows_x86_64_msvc",
]
[[package]]
+name = "windows_aarch64_gnullvm"
+version = "0.42.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "41d2aa71f6f0cbe00ae5167d90ef3cfe66527d6f613ca78ac8024c3ccab9a19e"
+
+[[package]]
name = "windows_aarch64_msvc"
-version = "0.36.1"
+version = "0.42.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9bb8c3fd39ade2d67e9874ac4f3db21f0d710bee00fe7cab16949ec184eeaa47"
+checksum = "dd0f252f5a35cac83d6311b2e795981f5ee6e67eb1f9a7f64eb4500fbc4dcdb4"
[[package]]
name = "windows_i686_gnu"
-version = "0.36.1"
+version = "0.42.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "180e6ccf01daf4c426b846dfc66db1fc518f074baa793aa7d9b9aaeffad6a3b6"
+checksum = "fbeae19f6716841636c28d695375df17562ca208b2b7d0dc47635a50ae6c5de7"
[[package]]
name = "windows_i686_msvc"
-version = "0.36.1"
+version = "0.42.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e2e7917148b2812d1eeafaeb22a97e4813dfa60a3f8f78ebe204bcc88f12f024"
+checksum = "84c12f65daa39dd2babe6e442988fc329d6243fdce47d7d2d155b8d874862246"
[[package]]
name = "windows_x86_64_gnu"
-version = "0.36.1"
+version = "0.42.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bf7b1b21b5362cbc318f686150e5bcea75ecedc74dd157d874d754a2ca44b0ed"
+
+[[package]]
+name = "windows_x86_64_gnullvm"
+version = "0.42.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4dcd171b8776c41b97521e5da127a2d86ad280114807d0b2ab1e462bc764d9e1"
+checksum = "09d525d2ba30eeb3297665bd434a54297e4170c7f1a44cad4ef58095b4cd2028"
[[package]]
name = "windows_x86_64_msvc"
-version = "0.36.1"
+version = "0.42.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c811ca4a8c853ef420abd8592ba53ddbbac90410fab6903b3e79972a631f7680"
+checksum = "f40009d85759725a34da6d89a94e63d7bdc50a862acf0dbc7c8e488f1edcb6f5"
diff --git a/compiler/rustc_codegen_cranelift/Cargo.toml b/compiler/rustc_codegen_cranelift/Cargo.toml
index 2b216ca07..34117c288 100644
--- a/compiler/rustc_codegen_cranelift/Cargo.toml
+++ b/compiler/rustc_codegen_cranelift/Cargo.toml
@@ -15,12 +15,14 @@ crate-type = ["dylib"]
[dependencies]
# These have to be in sync with each other
-cranelift-codegen = { version = "0.90.1", features = ["unwind", "all-arch"] }
-cranelift-frontend = "0.90.1"
-cranelift-module = "0.90.1"
-cranelift-native = "0.90.1"
-cranelift-jit = { version = "0.90.1", optional = true }
-cranelift-object = "0.90.1"
+cranelift-codegen = { version = "0.92", features = ["unwind", "all-arch"] }
+cranelift-frontend = { version = "0.92" }
+cranelift-module = { version = "0.92" }
+# NOTE vendored as src/cranelift_native.rs
+# FIXME revert back to the external crate with Cranelift 0.93
+#cranelift-native = { version = "0.92" }
+cranelift-jit = { version = "0.92", optional = true }
+cranelift-object = { version = "0.92" }
target-lexicon = "0.12.0"
gimli = { version = "0.26.0", default-features = false, features = ["write"]}
object = { version = "0.29.0", default-features = false, features = ["std", "read_core", "write", "archive", "coff", "elf", "macho", "pe"] }
diff --git a/compiler/rustc_codegen_cranelift/Readme.md b/compiler/rustc_codegen_cranelift/Readme.md
index 0e9c77244..b87a9dc51 100644
--- a/compiler/rustc_codegen_cranelift/Readme.md
+++ b/compiler/rustc_codegen_cranelift/Readme.md
@@ -8,9 +8,9 @@ If not please open an issue.
## Building and testing
```bash
-$ git clone https://github.com/bjorn3/rustc_codegen_cranelift.git
+$ git clone https://github.com/bjorn3/rustc_codegen_cranelift
$ cd rustc_codegen_cranelift
-$ ./y.rs prepare # download and patch sysroot src and install hyperfine for benchmarking
+$ ./y.rs prepare
$ ./y.rs build
```
@@ -20,13 +20,12 @@ To run the test suite replace the last command with:
$ ./test.sh
```
-This will implicitly build cg_clif too. Both `y.rs build` and `test.sh` accept a `--debug` argument to
-build in debug mode.
+For more docs on how to build and test see [build_system/usage.txt](build_system/usage.txt) or the help message of `./y.rs`.
-Alternatively you can download a pre built version from [GHA]. It is listed in the artifacts section
+Alternatively you can download a pre built version from [Github Actions]. It is listed in the artifacts section
of workflow runs. Unfortunately due to GHA restrictions you need to be logged in to access it.
-[GHA]: https://github.com/bjorn3/rustc_codegen_cranelift/actions?query=branch%3Amaster+event%3Apush+is%3Asuccess
+[Github Actions]: https://github.com/bjorn3/rustc_codegen_cranelift/actions?query=branch%3Amaster+event%3Apush+is%3Asuccess
## Usage
@@ -53,7 +52,8 @@ configuration options.
* Inline assembly ([no cranelift support](https://github.com/bytecodealliance/wasmtime/issues/1041))
* On UNIX there is support for invoking an external assembler for `global_asm!` and `asm!`.
-* SIMD ([tracked here](https://github.com/bjorn3/rustc_codegen_cranelift/issues/171), some basic things work)
+* SIMD ([tracked here](https://github.com/bjorn3/rustc_codegen_cranelift/issues/171), `std::simd` fully works, `std::arch` is partially supported)
+* Unwinding on panics ([no cranelift support](https://github.com/bytecodealliance/wasmtime/issues/1677), `-Cpanic=abort` is enabled by default)
## License
diff --git a/compiler/rustc_codegen_cranelift/build_sysroot/Cargo.lock b/compiler/rustc_codegen_cranelift/build_sysroot/Cargo.lock
index bba321053..b7e0b68a2 100644
--- a/compiler/rustc_codegen_cranelift/build_sysroot/Cargo.lock
+++ b/compiler/rustc_codegen_cranelift/build_sysroot/Cargo.lock
@@ -34,9 +34,9 @@ dependencies = [
[[package]]
name = "cc"
-version = "1.0.77"
+version = "1.0.79"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e9f73505338f7d905b19d18738976aae232eb46b8efc15554ffc56deb5d9ebe4"
+checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f"
[[package]]
name = "cfg-if"
@@ -50,9 +50,9 @@ dependencies = [
[[package]]
name = "compiler_builtins"
-version = "0.1.85"
+version = "0.1.86"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "13e81c6cd7ab79f51a0c927d22858d61ad12bd0b3865f0b13ece02a4486aeabb"
+checksum = "5dae98c88e576098d7ab13ebcb40cc43e5114b2beafe61a87cda9200649ff205"
dependencies = [
"rustc-std-workspace-core",
]
@@ -129,9 +129,9 @@ dependencies = [
[[package]]
name = "libc"
-version = "0.2.138"
+version = "0.2.139"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "db6d7e329c562c5dfab7a46a2afabc8b987ab9a4834c9d1ca04dc54c1546cef8"
+checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79"
dependencies = [
"rustc-std-workspace-core",
]
diff --git a/compiler/rustc_codegen_cranelift/build_system/abi_cafe.rs b/compiler/rustc_codegen_cranelift/build_system/abi_cafe.rs
index a081fdaa1..0da27f529 100644
--- a/compiler/rustc_codegen_cranelift/build_system/abi_cafe.rs
+++ b/compiler/rustc_codegen_cranelift/build_system/abi_cafe.rs
@@ -1,13 +1,12 @@
use std::path::Path;
use super::build_sysroot;
-use super::config;
use super::path::Dirs;
use super::prepare::GitRepo;
use super::utils::{spawn_and_wait, CargoProject, Compiler};
use super::SysrootKind;
-pub(crate) static ABI_CAFE_REPO: GitRepo =
+static ABI_CAFE_REPO: GitRepo =
GitRepo::github("Gankra", "abi-cafe", "4c6dc8c9c687e2b3a760ff2176ce236872b37212", "abi-cafe");
static ABI_CAFE: CargoProject = CargoProject::new(&ABI_CAFE_REPO.source_dir(), "abi_cafe");
@@ -17,18 +16,10 @@ pub(crate) fn run(
sysroot_kind: SysrootKind,
dirs: &Dirs,
cg_clif_dylib: &Path,
- host_triple: &str,
- target_triple: &str,
+ bootstrap_host_compiler: &Compiler,
) {
- if !config::get_bool("testsuite.abi-cafe") {
- eprintln!("[SKIP] abi-cafe");
- return;
- }
-
- if host_triple != target_triple {
- eprintln!("[SKIP] abi-cafe (cross-compilation not supported)");
- return;
- }
+ ABI_CAFE_REPO.fetch(dirs);
+ spawn_and_wait(ABI_CAFE.fetch("cargo", &bootstrap_host_compiler.rustc, dirs));
eprintln!("Building sysroot for abi-cafe");
build_sysroot::build_sysroot(
@@ -36,15 +27,15 @@ pub(crate) fn run(
channel,
sysroot_kind,
cg_clif_dylib,
- host_triple,
- target_triple,
+ bootstrap_host_compiler,
+ bootstrap_host_compiler.triple.clone(),
);
eprintln!("Running abi-cafe");
let pairs = ["rustc_calls_cgclif", "cgclif_calls_rustc", "cgclif_calls_cc", "cc_calls_cgclif"];
- let mut cmd = ABI_CAFE.run(&Compiler::host(), dirs);
+ let mut cmd = ABI_CAFE.run(bootstrap_host_compiler, dirs);
cmd.arg("--");
cmd.arg("--pairs");
cmd.args(pairs);
diff --git a/compiler/rustc_codegen_cranelift/build_system/bench.rs b/compiler/rustc_codegen_cranelift/build_system/bench.rs
new file mode 100644
index 000000000..a9a851d0a
--- /dev/null
+++ b/compiler/rustc_codegen_cranelift/build_system/bench.rs
@@ -0,0 +1,103 @@
+use std::env;
+use std::fs;
+use std::path::Path;
+
+use super::path::{Dirs, RelPath};
+use super::prepare::GitRepo;
+use super::rustc_info::get_file_name;
+use super::utils::{hyperfine_command, spawn_and_wait, CargoProject, Compiler};
+
+static SIMPLE_RAYTRACER_REPO: GitRepo = GitRepo::github(
+ "ebobby",
+ "simple-raytracer",
+ "804a7a21b9e673a482797aa289a18ed480e4d813",
+ "<none>",
+);
+
+// Use a separate target dir for the initial LLVM build to reduce unnecessary recompiles
+static SIMPLE_RAYTRACER_LLVM: CargoProject =
+ CargoProject::new(&SIMPLE_RAYTRACER_REPO.source_dir(), "simple_raytracer_llvm");
+
+static SIMPLE_RAYTRACER: CargoProject =
+ CargoProject::new(&SIMPLE_RAYTRACER_REPO.source_dir(), "simple_raytracer");
+
+pub(crate) fn benchmark(dirs: &Dirs, bootstrap_host_compiler: &Compiler) {
+ benchmark_simple_raytracer(dirs, bootstrap_host_compiler);
+}
+
+fn benchmark_simple_raytracer(dirs: &Dirs, bootstrap_host_compiler: &Compiler) {
+ if std::process::Command::new("hyperfine").output().is_err() {
+ eprintln!("Hyperfine not installed");
+ eprintln!("Hint: Try `cargo install hyperfine` to install hyperfine");
+ std::process::exit(1);
+ }
+
+ if !SIMPLE_RAYTRACER_REPO.source_dir().to_path(dirs).exists() {
+ SIMPLE_RAYTRACER_REPO.fetch(dirs);
+ spawn_and_wait(SIMPLE_RAYTRACER.fetch(
+ &bootstrap_host_compiler.cargo,
+ &bootstrap_host_compiler.rustc,
+ dirs,
+ ));
+ }
+
+ eprintln!("[LLVM BUILD] simple-raytracer");
+ let build_cmd = SIMPLE_RAYTRACER_LLVM.build(bootstrap_host_compiler, dirs);
+ spawn_and_wait(build_cmd);
+ fs::copy(
+ SIMPLE_RAYTRACER_LLVM
+ .target_dir(dirs)
+ .join(&bootstrap_host_compiler.triple)
+ .join("debug")
+ .join(get_file_name("main", "bin")),
+ RelPath::BUILD.to_path(dirs).join(get_file_name("raytracer_cg_llvm", "bin")),
+ )
+ .unwrap();
+
+ let bench_runs = env::var("BENCH_RUNS").unwrap_or_else(|_| "10".to_string()).parse().unwrap();
+
+ eprintln!("[BENCH COMPILE] ebobby/simple-raytracer");
+ let cargo_clif =
+ RelPath::DIST.to_path(dirs).join(get_file_name("cargo_clif", "bin").replace('_', "-"));
+ let manifest_path = SIMPLE_RAYTRACER.manifest_path(dirs);
+ let target_dir = SIMPLE_RAYTRACER.target_dir(dirs);
+
+ let clean_cmd = format!(
+ "RUSTC=rustc cargo clean --manifest-path {manifest_path} --target-dir {target_dir}",
+ manifest_path = manifest_path.display(),
+ target_dir = target_dir.display(),
+ );
+ let llvm_build_cmd = format!(
+ "RUSTC=rustc cargo build --manifest-path {manifest_path} --target-dir {target_dir}",
+ manifest_path = manifest_path.display(),
+ target_dir = target_dir.display(),
+ );
+ let clif_build_cmd = format!(
+ "RUSTC=rustc {cargo_clif} build --manifest-path {manifest_path} --target-dir {target_dir}",
+ cargo_clif = cargo_clif.display(),
+ manifest_path = manifest_path.display(),
+ target_dir = target_dir.display(),
+ );
+
+ let bench_compile =
+ hyperfine_command(1, bench_runs, Some(&clean_cmd), &llvm_build_cmd, &clif_build_cmd);
+
+ spawn_and_wait(bench_compile);
+
+ eprintln!("[BENCH RUN] ebobby/simple-raytracer");
+ fs::copy(
+ target_dir.join("debug").join(get_file_name("main", "bin")),
+ RelPath::BUILD.to_path(dirs).join(get_file_name("raytracer_cg_clif", "bin")),
+ )
+ .unwrap();
+
+ let mut bench_run = hyperfine_command(
+ 0,
+ bench_runs,
+ None,
+ Path::new(".").join(get_file_name("raytracer_cg_llvm", "bin")).to_str().unwrap(),
+ Path::new(".").join(get_file_name("raytracer_cg_clif", "bin")).to_str().unwrap(),
+ );
+ bench_run.current_dir(RelPath::BUILD.to_path(dirs));
+ spawn_and_wait(bench_run);
+}
diff --git a/compiler/rustc_codegen_cranelift/build_system/build_backend.rs b/compiler/rustc_codegen_cranelift/build_system/build_backend.rs
index fde8ef424..4b740fa2d 100644
--- a/compiler/rustc_codegen_cranelift/build_system/build_backend.rs
+++ b/compiler/rustc_codegen_cranelift/build_system/build_backend.rs
@@ -3,17 +3,17 @@ use std::path::PathBuf;
use super::path::{Dirs, RelPath};
use super::rustc_info::get_file_name;
-use super::utils::{is_ci, CargoProject, Compiler};
+use super::utils::{is_ci, is_ci_opt, CargoProject, Compiler};
-static CG_CLIF: CargoProject = CargoProject::new(&RelPath::SOURCE, "cg_clif");
+pub(crate) static CG_CLIF: CargoProject = CargoProject::new(&RelPath::SOURCE, "cg_clif");
pub(crate) fn build_backend(
dirs: &Dirs,
channel: &str,
- host_triple: &str,
+ bootstrap_host_compiler: &Compiler,
use_unstable_features: bool,
) -> PathBuf {
- let mut cmd = CG_CLIF.build(&Compiler::host(), dirs);
+ let mut cmd = CG_CLIF.build(&bootstrap_host_compiler, dirs);
cmd.env("CARGO_BUILD_INCREMENTAL", "true"); // Force incr comp even in release mode
@@ -25,6 +25,10 @@ pub(crate) fn build_backend(
// Disabling incr comp reduces cache size and incr comp doesn't save as much on CI anyway
cmd.env("CARGO_BUILD_INCREMENTAL", "false");
+
+ if !is_ci_opt() {
+ cmd.env("CARGO_PROFILE_RELEASE_DEBUG_ASSERTIONS", "true");
+ }
}
if use_unstable_features {
@@ -46,7 +50,7 @@ pub(crate) fn build_backend(
CG_CLIF
.target_dir(dirs)
- .join(host_triple)
+ .join(&bootstrap_host_compiler.triple)
.join(channel)
.join(get_file_name("rustc_codegen_cranelift", "dylib"))
}
diff --git a/compiler/rustc_codegen_cranelift/build_system/build_sysroot.rs b/compiler/rustc_codegen_cranelift/build_system/build_sysroot.rs
index cbbf09b9b..2e04f2c68 100644
--- a/compiler/rustc_codegen_cranelift/build_system/build_sysroot.rs
+++ b/compiler/rustc_codegen_cranelift/build_system/build_sysroot.rs
@@ -1,31 +1,32 @@
use std::fs;
-use std::path::Path;
+use std::path::{Path, PathBuf};
use std::process::{self, Command};
use super::path::{Dirs, RelPath};
-use super::rustc_info::{get_file_name, get_rustc_version, get_wrapper_file_name};
-use super::utils::{spawn_and_wait, try_hard_link, CargoProject, Compiler};
+use super::rustc_info::{get_file_name, get_rustc_version, get_toolchain_name};
+use super::utils::{remove_dir_if_exists, spawn_and_wait, try_hard_link, CargoProject, Compiler};
use super::SysrootKind;
static DIST_DIR: RelPath = RelPath::DIST;
static BIN_DIR: RelPath = RelPath::DIST.join("bin");
static LIB_DIR: RelPath = RelPath::DIST.join("lib");
-static RUSTLIB_DIR: RelPath = LIB_DIR.join("rustlib");
pub(crate) fn build_sysroot(
dirs: &Dirs,
channel: &str,
sysroot_kind: SysrootKind,
cg_clif_dylib_src: &Path,
- host_triple: &str,
- target_triple: &str,
-) {
+ bootstrap_host_compiler: &Compiler,
+ target_triple: String,
+) -> Compiler {
eprintln!("[BUILD] sysroot {:?}", sysroot_kind);
DIST_DIR.ensure_fresh(dirs);
BIN_DIR.ensure_exists(dirs);
LIB_DIR.ensure_exists(dirs);
+ let is_native = bootstrap_host_compiler.triple == target_triple;
+
// Copy the backend
let cg_clif_dylib_path = if cfg!(windows) {
// Windows doesn't have rpath support, so the cg_clif dylib needs to be next to the
@@ -35,129 +36,169 @@ pub(crate) fn build_sysroot(
LIB_DIR
}
.to_path(dirs)
- .join(get_file_name("rustc_codegen_cranelift", "dylib"));
+ .join(cg_clif_dylib_src.file_name().unwrap());
try_hard_link(cg_clif_dylib_src, &cg_clif_dylib_path);
// Build and copy rustc and cargo wrappers
+ let wrapper_base_name = get_file_name("____", "bin");
+ let toolchain_name = get_toolchain_name();
for wrapper in ["rustc-clif", "rustdoc-clif", "cargo-clif"] {
- let wrapper_name = get_wrapper_file_name(wrapper, "bin");
+ let wrapper_name = wrapper_base_name.replace("____", wrapper);
- let mut build_cargo_wrapper_cmd = Command::new("rustc");
+ let mut build_cargo_wrapper_cmd = Command::new(&bootstrap_host_compiler.rustc);
build_cargo_wrapper_cmd
+ .env("TOOLCHAIN_NAME", toolchain_name.clone())
.arg(RelPath::SCRIPTS.to_path(dirs).join(&format!("{wrapper}.rs")))
.arg("-o")
.arg(DIST_DIR.to_path(dirs).join(wrapper_name))
- .arg("-g");
+ .arg("-Cstrip=debuginfo");
spawn_and_wait(build_cargo_wrapper_cmd);
}
- let default_sysroot = super::rustc_info::get_default_sysroot();
+ let host = build_sysroot_for_triple(
+ dirs,
+ channel,
+ bootstrap_host_compiler.clone(),
+ &cg_clif_dylib_path,
+ sysroot_kind,
+ );
+ host.install_into_sysroot(&DIST_DIR.to_path(dirs));
- let host_rustlib_lib = RUSTLIB_DIR.to_path(dirs).join(host_triple).join("lib");
- let target_rustlib_lib = RUSTLIB_DIR.to_path(dirs).join(target_triple).join("lib");
- fs::create_dir_all(&host_rustlib_lib).unwrap();
- fs::create_dir_all(&target_rustlib_lib).unwrap();
+ if !is_native {
+ build_sysroot_for_triple(
+ dirs,
+ channel,
+ {
+ let mut bootstrap_target_compiler = bootstrap_host_compiler.clone();
+ bootstrap_target_compiler.triple = target_triple.clone();
+ bootstrap_target_compiler.set_cross_linker_and_runner();
+ bootstrap_target_compiler
+ },
+ &cg_clif_dylib_path,
+ sysroot_kind,
+ )
+ .install_into_sysroot(&DIST_DIR.to_path(dirs));
+ }
- if target_triple == "x86_64-pc-windows-gnu" {
- if !default_sysroot.join("lib").join("rustlib").join(target_triple).join("lib").exists() {
- eprintln!(
- "The x86_64-pc-windows-gnu target needs to be installed first before it is possible \
- to compile a sysroot for it.",
- );
- process::exit(1);
+ // Copy std for the host to the lib dir. This is necessary for the jit mode to find
+ // libstd.
+ for lib in host.libs {
+ let filename = lib.file_name().unwrap().to_str().unwrap();
+ if filename.contains("std-") && !filename.contains(".rlib") {
+ try_hard_link(&lib, LIB_DIR.to_path(dirs).join(lib.file_name().unwrap()));
}
- for file in fs::read_dir(
- default_sysroot.join("lib").join("rustlib").join(target_triple).join("lib"),
- )
- .unwrap()
- {
- let file = file.unwrap().path();
- if file.extension().map_or(true, |ext| ext.to_str().unwrap() != "o") {
- continue; // only copy object files
- }
- try_hard_link(&file, target_rustlib_lib.join(file.file_name().unwrap()));
+ }
+
+ let mut target_compiler = {
+ let dirs: &Dirs = &dirs;
+ let rustc_clif =
+ RelPath::DIST.to_path(&dirs).join(wrapper_base_name.replace("____", "rustc-clif"));
+ let rustdoc_clif =
+ RelPath::DIST.to_path(&dirs).join(wrapper_base_name.replace("____", "rustdoc-clif"));
+
+ Compiler {
+ cargo: bootstrap_host_compiler.cargo.clone(),
+ rustc: rustc_clif.clone(),
+ rustdoc: rustdoc_clif.clone(),
+ rustflags: String::new(),
+ rustdocflags: String::new(),
+ triple: target_triple,
+ runner: vec![],
}
+ };
+ if !is_native {
+ target_compiler.set_cross_linker_and_runner();
}
+ target_compiler
+}
- match sysroot_kind {
- SysrootKind::None => {} // Nothing to do
- SysrootKind::Llvm => {
- for file in fs::read_dir(
- default_sysroot.join("lib").join("rustlib").join(host_triple).join("lib"),
- )
- .unwrap()
- {
- let file = file.unwrap().path();
- let file_name_str = file.file_name().unwrap().to_str().unwrap();
- if (file_name_str.contains("rustc_")
- && !file_name_str.contains("rustc_std_workspace_")
- && !file_name_str.contains("rustc_demangle"))
- || file_name_str.contains("chalk")
- || file_name_str.contains("tracing")
- || file_name_str.contains("regex")
- {
- // These are large crates that are part of the rustc-dev component and are not
- // necessary to run regular programs.
- continue;
- }
- try_hard_link(&file, host_rustlib_lib.join(file.file_name().unwrap()));
- }
+struct SysrootTarget {
+ triple: String,
+ libs: Vec<PathBuf>,
+}
- if target_triple != host_triple {
- for file in fs::read_dir(
- default_sysroot.join("lib").join("rustlib").join(target_triple).join("lib"),
- )
- .unwrap()
- {
- let file = file.unwrap().path();
- try_hard_link(&file, target_rustlib_lib.join(file.file_name().unwrap()));
- }
- }
+impl SysrootTarget {
+ fn install_into_sysroot(&self, sysroot: &Path) {
+ if self.libs.is_empty() {
+ return;
}
- SysrootKind::Clif => {
- build_clif_sysroot_for_triple(dirs, channel, host_triple, &cg_clif_dylib_path, None);
-
- if host_triple != target_triple {
- // When cross-compiling it is often necessary to manually pick the right linker
- let linker = match target_triple {
- "aarch64-unknown-linux-gnu" => Some("aarch64-linux-gnu-gcc"),
- "s390x-unknown-linux-gnu" => Some("s390x-linux-gnu-gcc"),
- _ => None,
- };
- build_clif_sysroot_for_triple(
- dirs,
- channel,
- target_triple,
- &cg_clif_dylib_path,
- linker,
- );
- }
- // Copy std for the host to the lib dir. This is necessary for the jit mode to find
- // libstd.
- for file in fs::read_dir(host_rustlib_lib).unwrap() {
- let file = file.unwrap().path();
- let filename = file.file_name().unwrap().to_str().unwrap();
- if filename.contains("std-") && !filename.contains(".rlib") {
- try_hard_link(&file, LIB_DIR.to_path(dirs).join(file.file_name().unwrap()));
- }
- }
+ let target_rustlib_lib = sysroot.join("lib").join("rustlib").join(&self.triple).join("lib");
+ fs::create_dir_all(&target_rustlib_lib).unwrap();
+
+ for lib in &self.libs {
+ try_hard_link(lib, target_rustlib_lib.join(lib.file_name().unwrap()));
+ }
+ }
+}
+
+pub(crate) static ORIG_BUILD_SYSROOT: RelPath = RelPath::SOURCE.join("build_sysroot");
+pub(crate) static BUILD_SYSROOT: RelPath = RelPath::DOWNLOAD.join("sysroot");
+pub(crate) static SYSROOT_RUSTC_VERSION: RelPath = BUILD_SYSROOT.join("rustc_version");
+pub(crate) static SYSROOT_SRC: RelPath = BUILD_SYSROOT.join("sysroot_src");
+pub(crate) static STANDARD_LIBRARY: CargoProject =
+ CargoProject::new(&BUILD_SYSROOT, "build_sysroot");
+pub(crate) static RTSTARTUP_SYSROOT: RelPath = RelPath::BUILD.join("rtstartup");
+
+#[must_use]
+fn build_sysroot_for_triple(
+ dirs: &Dirs,
+ channel: &str,
+ compiler: Compiler,
+ cg_clif_dylib_path: &Path,
+ sysroot_kind: SysrootKind,
+) -> SysrootTarget {
+ match sysroot_kind {
+ SysrootKind::None => build_rtstartup(dirs, &compiler)
+ .unwrap_or(SysrootTarget { triple: compiler.triple, libs: vec![] }),
+ SysrootKind::Llvm => build_llvm_sysroot_for_triple(compiler),
+ SysrootKind::Clif => {
+ build_clif_sysroot_for_triple(dirs, channel, compiler, &cg_clif_dylib_path)
}
}
}
-// FIXME move to download/ or dist/
-pub(crate) static SYSROOT_RUSTC_VERSION: RelPath = RelPath::BUILD_SYSROOT.join("rustc_version");
-pub(crate) static SYSROOT_SRC: RelPath = RelPath::BUILD_SYSROOT.join("sysroot_src");
-static STANDARD_LIBRARY: CargoProject = CargoProject::new(&RelPath::BUILD_SYSROOT, "build_sysroot");
+#[must_use]
+fn build_llvm_sysroot_for_triple(compiler: Compiler) -> SysrootTarget {
+ let default_sysroot = super::rustc_info::get_default_sysroot(&compiler.rustc);
+ let mut target_libs = SysrootTarget { triple: compiler.triple, libs: vec![] };
+
+ for entry in fs::read_dir(
+ default_sysroot.join("lib").join("rustlib").join(&target_libs.triple).join("lib"),
+ )
+ .unwrap()
+ {
+ let entry = entry.unwrap();
+ if entry.file_type().unwrap().is_dir() {
+ continue;
+ }
+ let file = entry.path();
+ let file_name_str = file.file_name().unwrap().to_str().unwrap();
+ if (file_name_str.contains("rustc_")
+ && !file_name_str.contains("rustc_std_workspace_")
+ && !file_name_str.contains("rustc_demangle"))
+ || file_name_str.contains("chalk")
+ || file_name_str.contains("tracing")
+ || file_name_str.contains("regex")
+ {
+ // These are large crates that are part of the rustc-dev component and are not
+ // necessary to run regular programs.
+ continue;
+ }
+ target_libs.libs.push(file);
+ }
+
+ target_libs
+}
+
+#[must_use]
fn build_clif_sysroot_for_triple(
dirs: &Dirs,
channel: &str,
- triple: &str,
+ mut compiler: Compiler,
cg_clif_dylib_path: &Path,
- linker: Option<&str>,
-) {
+) -> SysrootTarget {
match fs::read_to_string(SYSROOT_RUSTC_VERSION.to_path(dirs)) {
Err(e) => {
eprintln!("Failed to get rustc version for patched sysroot source: {}", e);
@@ -165,7 +206,7 @@ fn build_clif_sysroot_for_triple(
process::exit(1);
}
Ok(source_version) => {
- let rustc_version = get_rustc_version();
+ let rustc_version = get_rustc_version(&compiler.rustc);
if source_version != rustc_version {
eprintln!("The patched sysroot source is outdated");
eprintln!("Source version: {}", source_version.trim());
@@ -176,37 +217,42 @@ fn build_clif_sysroot_for_triple(
}
}
- let build_dir = STANDARD_LIBRARY.target_dir(dirs).join(triple).join(channel);
+ let mut target_libs = SysrootTarget { triple: compiler.triple.clone(), libs: vec![] };
+
+ if let Some(rtstartup_target_libs) = build_rtstartup(dirs, &compiler) {
+ rtstartup_target_libs.install_into_sysroot(&RTSTARTUP_SYSROOT.to_path(dirs));
+
+ target_libs.libs.extend(rtstartup_target_libs.libs);
+ }
+
+ let build_dir = STANDARD_LIBRARY.target_dir(dirs).join(&compiler.triple).join(channel);
if !super::config::get_bool("keep_sysroot") {
// Cleanup the deps dir, but keep build scripts and the incremental cache for faster
// recompilation as they are not affected by changes in cg_clif.
- if build_dir.join("deps").exists() {
- fs::remove_dir_all(build_dir.join("deps")).unwrap();
- }
+ remove_dir_if_exists(&build_dir.join("deps"));
}
// Build sysroot
- let mut rustflags = "-Zforce-unstable-if-unmarked -Cpanic=abort".to_string();
+ let mut rustflags = " -Zforce-unstable-if-unmarked -Cpanic=abort".to_string();
rustflags.push_str(&format!(" -Zcodegen-backend={}", cg_clif_dylib_path.to_str().unwrap()));
- rustflags.push_str(&format!(" --sysroot={}", DIST_DIR.to_path(dirs).to_str().unwrap()));
+ // Necessary for MinGW to find rsbegin.o and rsend.o
+ rustflags
+ .push_str(&format!(" --sysroot={}", RTSTARTUP_SYSROOT.to_path(dirs).to_str().unwrap()));
if channel == "release" {
rustflags.push_str(" -Zmir-opt-level=3");
}
- if let Some(linker) = linker {
- use std::fmt::Write;
- write!(rustflags, " -Clinker={}", linker).unwrap();
- }
- let mut compiler = Compiler::with_triple(triple.to_owned());
- compiler.rustflags = rustflags;
+ compiler.rustflags += &rustflags;
let mut build_cmd = STANDARD_LIBRARY.build(&compiler, dirs);
if channel == "release" {
build_cmd.arg("--release");
}
build_cmd.env("__CARGO_DEFAULT_LIB_METADATA", "cg_clif");
+ if compiler.triple.contains("apple") {
+ build_cmd.env("CARGO_PROFILE_RELEASE_SPLIT_DEBUGINFO", "packed");
+ }
spawn_and_wait(build_cmd);
- // Copy all relevant files to the sysroot
for entry in fs::read_dir(build_dir.join("deps")).unwrap() {
let entry = entry.unwrap();
if let Some(ext) = entry.path().extension() {
@@ -216,9 +262,35 @@ fn build_clif_sysroot_for_triple(
} else {
continue;
};
- try_hard_link(
- entry.path(),
- RUSTLIB_DIR.to_path(dirs).join(triple).join("lib").join(entry.file_name()),
- );
+ target_libs.libs.push(entry.path());
}
+
+ target_libs
+}
+
+fn build_rtstartup(dirs: &Dirs, compiler: &Compiler) -> Option<SysrootTarget> {
+ if !compiler.triple.ends_with("windows-gnu") {
+ return None;
+ }
+
+ RTSTARTUP_SYSROOT.ensure_fresh(dirs);
+
+ let rtstartup_src = SYSROOT_SRC.to_path(dirs).join("library").join("rtstartup");
+ let mut target_libs = SysrootTarget { triple: compiler.triple.clone(), libs: vec![] };
+
+ for file in ["rsbegin", "rsend"] {
+ let obj = RTSTARTUP_SYSROOT.to_path(dirs).join(format!("{file}.o"));
+ let mut build_rtstartup_cmd = Command::new(&compiler.rustc);
+ build_rtstartup_cmd
+ .arg("--target")
+ .arg(&compiler.triple)
+ .arg("--emit=obj")
+ .arg("-o")
+ .arg(&obj)
+ .arg(rtstartup_src.join(format!("{file}.rs")));
+ spawn_and_wait(build_rtstartup_cmd);
+ target_libs.libs.push(obj.clone());
+ }
+
+ Some(target_libs)
}
diff --git a/compiler/rustc_codegen_cranelift/build_system/mod.rs b/compiler/rustc_codegen_cranelift/build_system/mod.rs
index 1afc9a55c..8a53acdf7 100644
--- a/compiler/rustc_codegen_cranelift/build_system/mod.rs
+++ b/compiler/rustc_codegen_cranelift/build_system/mod.rs
@@ -2,9 +2,10 @@ use std::env;
use std::path::PathBuf;
use std::process;
-use self::utils::is_ci;
+use self::utils::{is_ci, is_ci_opt, Compiler};
mod abi_cafe;
+mod bench;
mod build_backend;
mod build_sysroot;
mod config;
@@ -14,31 +15,8 @@ mod rustc_info;
mod tests;
mod utils;
-const USAGE: &str = r#"The build system of cg_clif.
-
-USAGE:
- ./y.rs prepare [--out-dir DIR]
- ./y.rs build [--debug] [--sysroot none|clif|llvm] [--out-dir DIR] [--no-unstable-features]
- ./y.rs test [--debug] [--sysroot none|clif|llvm] [--out-dir DIR] [--no-unstable-features]
-
-OPTIONS:
- --sysroot none|clif|llvm
- Which sysroot libraries to use:
- `none` will not include any standard library in the sysroot.
- `clif` will build the standard library using Cranelift.
- `llvm` will use the pre-compiled standard library of rustc which is compiled with LLVM.
-
- --out-dir DIR
- Specify the directory in which the download, build and dist directories are stored.
- By default this is the working directory.
-
- --no-unstable-features
- fSome features are not yet ready for production usage. This option will disable these
- features. This includes the JIT mode and inline assembly support.
-"#;
-
fn usage() {
- eprintln!("{USAGE}");
+ eprintln!("{}", include_str!("usage.txt"));
}
macro_rules! arg_error {
@@ -54,6 +32,8 @@ enum Command {
Prepare,
Build,
Test,
+ AbiCafe,
+ Bench,
}
#[derive(Copy, Clone, Debug)]
@@ -64,12 +44,19 @@ pub(crate) enum SysrootKind {
}
pub fn main() {
- env::set_var("CG_CLIF_DISPLAY_CG_TIME", "1");
+ if env::var("RUST_BACKTRACE").is_err() {
+ env::set_var("RUST_BACKTRACE", "1");
+ }
env::set_var("CG_CLIF_DISABLE_INCR_CACHE", "1");
if is_ci() {
// Disabling incr comp reduces cache size and incr comp doesn't save as much on CI anyway
env::set_var("CARGO_BUILD_INCREMENTAL", "false");
+
+ if !is_ci_opt() {
+ // Enable the Cranelift verifier
+ env::set_var("CG_CLIF_ENABLE_VERIFIER", "1");
+ }
}
let mut args = env::args().skip(1);
@@ -77,6 +64,8 @@ pub fn main() {
Some("prepare") => Command::Prepare,
Some("build") => Command::Build,
Some("test") => Command::Test,
+ Some("abi-cafe") => Command::AbiCafe,
+ Some("bench") => Command::Bench,
Some(flag) if flag.starts_with('-') => arg_error!("Expected command found flag {}", flag),
Some(command) => arg_error!("Unknown command {}", command),
None => {
@@ -112,24 +101,16 @@ pub fn main() {
}
}
- let host_triple = if let Ok(host_triple) = std::env::var("HOST_TRIPLE") {
- host_triple
- } else if let Some(host_triple) = config::get_value("host") {
- host_triple
- } else {
- rustc_info::get_host_triple()
- };
- let target_triple = if let Ok(target_triple) = std::env::var("TARGET_TRIPLE") {
- if target_triple != "" {
- target_triple
- } else {
- host_triple.clone() // Empty target triple can happen on GHA
- }
- } else if let Some(target_triple) = config::get_value("target") {
- target_triple
- } else {
- host_triple.clone()
- };
+ let bootstrap_host_compiler = Compiler::bootstrap_with_triple(
+ std::env::var("HOST_TRIPLE")
+ .ok()
+ .or_else(|| config::get_value("host"))
+ .unwrap_or_else(|| rustc_info::get_host_triple()),
+ );
+ let target_triple = std::env::var("TARGET_TRIPLE")
+ .ok()
+ .or_else(|| config::get_value("target"))
+ .unwrap_or_else(|| bootstrap_host_compiler.triple.clone());
// FIXME allow changing the location of these dirs using cli arguments
let current_dir = std::env::current_dir().unwrap();
@@ -157,8 +138,15 @@ pub fn main() {
process::exit(0);
}
- let cg_clif_dylib =
- build_backend::build_backend(&dirs, channel, &host_triple, use_unstable_features);
+ env::set_var("RUSTC", "rustc_should_be_set_explicitly");
+ env::set_var("RUSTDOC", "rustdoc_should_be_set_explicitly");
+
+ let cg_clif_dylib = build_backend::build_backend(
+ &dirs,
+ channel,
+ &bootstrap_host_compiler,
+ use_unstable_features,
+ );
match command {
Command::Prepare => {
// Handled above
@@ -169,28 +157,37 @@ pub fn main() {
channel,
sysroot_kind,
&cg_clif_dylib,
- &host_triple,
- &target_triple,
+ &bootstrap_host_compiler,
+ target_triple.clone(),
);
-
- abi_cafe::run(
+ }
+ Command::AbiCafe => {
+ if bootstrap_host_compiler.triple != target_triple {
+ eprintln!("Abi-cafe doesn't support cross-compilation");
+ process::exit(1);
+ }
+ abi_cafe::run(channel, sysroot_kind, &dirs, &cg_clif_dylib, &bootstrap_host_compiler);
+ }
+ Command::Build => {
+ build_sysroot::build_sysroot(
+ &dirs,
channel,
sysroot_kind,
- &dirs,
&cg_clif_dylib,
- &host_triple,
- &target_triple,
+ &bootstrap_host_compiler,
+ target_triple,
);
}
- Command::Build => {
+ Command::Bench => {
build_sysroot::build_sysroot(
&dirs,
channel,
sysroot_kind,
&cg_clif_dylib,
- &host_triple,
- &target_triple,
+ &bootstrap_host_compiler,
+ target_triple,
);
+ bench::benchmark(&dirs, &bootstrap_host_compiler);
}
}
}
diff --git a/compiler/rustc_codegen_cranelift/build_system/path.rs b/compiler/rustc_codegen_cranelift/build_system/path.rs
index e93981f1d..329072300 100644
--- a/compiler/rustc_codegen_cranelift/build_system/path.rs
+++ b/compiler/rustc_codegen_cranelift/build_system/path.rs
@@ -1,6 +1,8 @@
use std::fs;
use std::path::PathBuf;
+use super::utils::remove_dir_if_exists;
+
#[derive(Debug, Clone)]
pub(crate) struct Dirs {
pub(crate) source_dir: PathBuf,
@@ -42,7 +44,6 @@ impl RelPath {
pub(crate) const DIST: RelPath = RelPath::Base(PathBase::Dist);
pub(crate) const SCRIPTS: RelPath = RelPath::SOURCE.join("scripts");
- pub(crate) const BUILD_SYSROOT: RelPath = RelPath::SOURCE.join("build_sysroot");
pub(crate) const PATCHES: RelPath = RelPath::SOURCE.join("patches");
pub(crate) const fn join(&'static self, suffix: &'static str) -> RelPath {
@@ -62,9 +63,7 @@ impl RelPath {
pub(crate) fn ensure_fresh(&self, dirs: &Dirs) {
let path = self.to_path(dirs);
- if path.exists() {
- fs::remove_dir_all(&path).unwrap();
- }
+ remove_dir_if_exists(&path);
fs::create_dir_all(path).unwrap();
}
}
diff --git a/compiler/rustc_codegen_cranelift/build_system/prepare.rs b/compiler/rustc_codegen_cranelift/build_system/prepare.rs
index 8ac67e8f9..50b1b7836 100644
--- a/compiler/rustc_codegen_cranelift/build_system/prepare.rs
+++ b/compiler/rustc_codegen_cranelift/build_system/prepare.rs
@@ -3,73 +3,51 @@ use std::fs;
use std::path::{Path, PathBuf};
use std::process::Command;
-use super::build_sysroot::{SYSROOT_RUSTC_VERSION, SYSROOT_SRC};
+use super::build_sysroot::{BUILD_SYSROOT, ORIG_BUILD_SYSROOT, SYSROOT_RUSTC_VERSION, SYSROOT_SRC};
use super::path::{Dirs, RelPath};
-use super::rustc_info::{get_file_name, get_rustc_path, get_rustc_version};
-use super::utils::{copy_dir_recursively, spawn_and_wait, Compiler};
+use super::rustc_info::{get_default_sysroot, get_rustc_version};
+use super::utils::{copy_dir_recursively, git_command, retry_spawn_and_wait, spawn_and_wait};
pub(crate) fn prepare(dirs: &Dirs) {
- if RelPath::DOWNLOAD.to_path(dirs).exists() {
- std::fs::remove_dir_all(RelPath::DOWNLOAD.to_path(dirs)).unwrap();
- }
- std::fs::create_dir_all(RelPath::DOWNLOAD.to_path(dirs)).unwrap();
+ RelPath::DOWNLOAD.ensure_fresh(dirs);
- prepare_sysroot(dirs);
+ spawn_and_wait(super::build_backend::CG_CLIF.fetch("cargo", "rustc", dirs));
- // FIXME maybe install this only locally?
- eprintln!("[INSTALL] hyperfine");
- Command::new("cargo")
- .arg("install")
- .arg("hyperfine")
- .env_remove("CARGO_TARGET_DIR")
- .spawn()
- .unwrap()
- .wait()
- .unwrap();
+ prepare_sysroot(dirs);
+ spawn_and_wait(super::build_sysroot::STANDARD_LIBRARY.fetch("cargo", "rustc", dirs));
+ spawn_and_wait(super::tests::LIBCORE_TESTS.fetch("cargo", "rustc", dirs));
- super::abi_cafe::ABI_CAFE_REPO.fetch(dirs);
super::tests::RAND_REPO.fetch(dirs);
+ spawn_and_wait(super::tests::RAND.fetch("cargo", "rustc", dirs));
super::tests::REGEX_REPO.fetch(dirs);
+ spawn_and_wait(super::tests::REGEX.fetch("cargo", "rustc", dirs));
super::tests::PORTABLE_SIMD_REPO.fetch(dirs);
- super::tests::SIMPLE_RAYTRACER_REPO.fetch(dirs);
-
- eprintln!("[LLVM BUILD] simple-raytracer");
- let host_compiler = Compiler::host();
- let build_cmd = super::tests::SIMPLE_RAYTRACER.build(&host_compiler, dirs);
- spawn_and_wait(build_cmd);
- fs::copy(
- super::tests::SIMPLE_RAYTRACER
- .target_dir(dirs)
- .join(&host_compiler.triple)
- .join("debug")
- .join(get_file_name("main", "bin")),
- RelPath::BUILD.to_path(dirs).join(get_file_name("raytracer_cg_llvm", "bin")),
- )
- .unwrap();
+ spawn_and_wait(super::tests::PORTABLE_SIMD.fetch("cargo", "rustc", dirs));
}
fn prepare_sysroot(dirs: &Dirs) {
- let rustc_path = get_rustc_path();
- let sysroot_src_orig = rustc_path.parent().unwrap().join("../lib/rustlib/src/rust");
- let sysroot_src = SYSROOT_SRC;
-
+ let sysroot_src_orig = get_default_sysroot(Path::new("rustc")).join("lib/rustlib/src/rust");
assert!(sysroot_src_orig.exists());
- sysroot_src.ensure_fresh(dirs);
- fs::create_dir_all(sysroot_src.to_path(dirs).join("library")).unwrap();
eprintln!("[COPY] sysroot src");
+
+ // FIXME ensure builds error out or update the copy if any of the files copied here change
+ BUILD_SYSROOT.ensure_fresh(dirs);
+ copy_dir_recursively(&ORIG_BUILD_SYSROOT.to_path(dirs), &BUILD_SYSROOT.to_path(dirs));
+
+ fs::create_dir_all(SYSROOT_SRC.to_path(dirs).join("library")).unwrap();
copy_dir_recursively(
&sysroot_src_orig.join("library"),
- &sysroot_src.to_path(dirs).join("library"),
+ &SYSROOT_SRC.to_path(dirs).join("library"),
);
- let rustc_version = get_rustc_version();
+ let rustc_version = get_rustc_version(Path::new("rustc"));
fs::write(SYSROOT_RUSTC_VERSION.to_path(dirs), &rustc_version).unwrap();
eprintln!("[GIT] init");
- init_git_repo(&sysroot_src.to_path(dirs));
+ init_git_repo(&SYSROOT_SRC.to_path(dirs));
- apply_patches(dirs, "sysroot", &sysroot_src.to_path(dirs));
+ apply_patches(dirs, "sysroot", &SYSROOT_SRC.to_path(dirs));
}
pub(crate) struct GitRepo {
@@ -98,7 +76,7 @@ impl GitRepo {
}
}
- fn fetch(&self, dirs: &Dirs) {
+ pub(crate) fn fetch(&self, dirs: &Dirs) {
match self.url {
GitRepoUrl::Github { user, repo } => {
clone_repo_shallow_github(
@@ -118,14 +96,14 @@ impl GitRepo {
fn clone_repo(download_dir: &Path, repo: &str, rev: &str) {
eprintln!("[CLONE] {}", repo);
// Ignore exit code as the repo may already have been checked out
- Command::new("git").arg("clone").arg(repo).arg(&download_dir).spawn().unwrap().wait().unwrap();
+ git_command(None, "clone").arg(repo).arg(download_dir).spawn().unwrap().wait().unwrap();
- let mut clean_cmd = Command::new("git");
- clean_cmd.arg("checkout").arg("--").arg(".").current_dir(&download_dir);
+ let mut clean_cmd = git_command(download_dir, "checkout");
+ clean_cmd.arg("--").arg(".");
spawn_and_wait(clean_cmd);
- let mut checkout_cmd = Command::new("git");
- checkout_cmd.arg("checkout").arg("-q").arg(rev).current_dir(download_dir);
+ let mut checkout_cmd = git_command(download_dir, "checkout");
+ checkout_cmd.arg("-q").arg(rev);
spawn_and_wait(checkout_cmd);
}
@@ -149,8 +127,22 @@ fn clone_repo_shallow_github(dirs: &Dirs, download_dir: &Path, user: &str, repo:
// Download zip archive
let mut download_cmd = Command::new("curl");
- download_cmd.arg("--location").arg("--output").arg(&archive_file).arg(archive_url);
- spawn_and_wait(download_cmd);
+ download_cmd
+ .arg("--max-time")
+ .arg("600")
+ .arg("-y")
+ .arg("30")
+ .arg("-Y")
+ .arg("10")
+ .arg("--connect-timeout")
+ .arg("30")
+ .arg("--continue-at")
+ .arg("-")
+ .arg("--location")
+ .arg("--output")
+ .arg(&archive_file)
+ .arg(archive_url);
+ retry_spawn_and_wait(5, download_cmd);
// Unpack tar archive
let mut unpack_cmd = Command::new("tar");
@@ -167,25 +159,16 @@ fn clone_repo_shallow_github(dirs: &Dirs, download_dir: &Path, user: &str, repo:
}
fn init_git_repo(repo_dir: &Path) {
- let mut git_init_cmd = Command::new("git");
- git_init_cmd.arg("init").arg("-q").current_dir(repo_dir);
+ let mut git_init_cmd = git_command(repo_dir, "init");
+ git_init_cmd.arg("-q");
spawn_and_wait(git_init_cmd);
- let mut git_add_cmd = Command::new("git");
- git_add_cmd.arg("add").arg(".").current_dir(repo_dir);
+ let mut git_add_cmd = git_command(repo_dir, "add");
+ git_add_cmd.arg(".");
spawn_and_wait(git_add_cmd);
- let mut git_commit_cmd = Command::new("git");
- git_commit_cmd
- .arg("-c")
- .arg("user.name=Dummy")
- .arg("-c")
- .arg("user.email=dummy@example.com")
- .arg("commit")
- .arg("-m")
- .arg("Initial commit")
- .arg("-q")
- .current_dir(repo_dir);
+ let mut git_commit_cmd = git_command(repo_dir, "commit");
+ git_commit_cmd.arg("-m").arg("Initial commit").arg("-q");
spawn_and_wait(git_commit_cmd);
}
@@ -220,16 +203,8 @@ fn apply_patches(dirs: &Dirs, crate_name: &str, target_dir: &Path) {
target_dir.file_name().unwrap(),
patch.file_name().unwrap()
);
- let mut apply_patch_cmd = Command::new("git");
- apply_patch_cmd
- .arg("-c")
- .arg("user.name=Dummy")
- .arg("-c")
- .arg("user.email=dummy@example.com")
- .arg("am")
- .arg(patch)
- .arg("-q")
- .current_dir(target_dir);
+ let mut apply_patch_cmd = git_command(target_dir, "am");
+ apply_patch_cmd.arg(patch).arg("-q");
spawn_and_wait(apply_patch_cmd);
}
}
diff --git a/compiler/rustc_codegen_cranelift/build_system/rustc_info.rs b/compiler/rustc_codegen_cranelift/build_system/rustc_info.rs
index 8e5ab688e..a70453b44 100644
--- a/compiler/rustc_codegen_cranelift/build_system/rustc_info.rs
+++ b/compiler/rustc_codegen_cranelift/build_system/rustc_info.rs
@@ -1,9 +1,9 @@
use std::path::{Path, PathBuf};
use std::process::{Command, Stdio};
-pub(crate) fn get_rustc_version() -> String {
+pub(crate) fn get_rustc_version(rustc: &Path) -> String {
let version_info =
- Command::new("rustc").stderr(Stdio::inherit()).args(&["-V"]).output().unwrap().stdout;
+ Command::new(rustc).stderr(Stdio::inherit()).args(&["-V"]).output().unwrap().stdout;
String::from_utf8(version_info).unwrap()
}
@@ -23,6 +23,16 @@ pub(crate) fn get_host_triple() -> String {
.to_owned()
}
+pub(crate) fn get_toolchain_name() -> String {
+ let active_toolchain = Command::new("rustup")
+ .stderr(Stdio::inherit())
+ .args(&["show", "active-toolchain"])
+ .output()
+ .unwrap()
+ .stdout;
+ String::from_utf8(active_toolchain).unwrap().trim().split_once(' ').unwrap().0.to_owned()
+}
+
pub(crate) fn get_cargo_path() -> PathBuf {
let cargo_path = Command::new("rustup")
.stderr(Stdio::inherit())
@@ -53,8 +63,8 @@ pub(crate) fn get_rustdoc_path() -> PathBuf {
Path::new(String::from_utf8(rustc_path).unwrap().trim()).to_owned()
}
-pub(crate) fn get_default_sysroot() -> PathBuf {
- let default_sysroot = Command::new("rustc")
+pub(crate) fn get_default_sysroot(rustc: &Path) -> PathBuf {
+ let default_sysroot = Command::new(rustc)
.stderr(Stdio::inherit())
.args(&["--print", "sysroot"])
.output()
@@ -83,12 +93,3 @@ pub(crate) fn get_file_name(crate_name: &str, crate_type: &str) -> String {
assert!(file_name.contains(crate_name));
file_name
}
-
-/// Similar to `get_file_name`, but converts any dashes (`-`) in the `crate_name` to
-/// underscores (`_`). This is specially made for the rustc and cargo wrappers
-/// which have a dash in the name, and that is not allowed in a crate name.
-pub(crate) fn get_wrapper_file_name(crate_name: &str, crate_type: &str) -> String {
- let crate_name = crate_name.replace('-', "_");
- let wrapper_name = get_file_name(&crate_name, crate_type);
- wrapper_name.replace('_', "-")
-}
diff --git a/compiler/rustc_codegen_cranelift/build_system/tests.rs b/compiler/rustc_codegen_cranelift/build_system/tests.rs
index 1c372736e..e9486888f 100644
--- a/compiler/rustc_codegen_cranelift/build_system/tests.rs
+++ b/compiler/rustc_codegen_cranelift/build_system/tests.rs
@@ -1,11 +1,9 @@
-use super::build_sysroot;
+use super::build_sysroot::{self, SYSROOT_SRC};
use super::config;
use super::path::{Dirs, RelPath};
use super::prepare::GitRepo;
-use super::rustc_info::{get_cargo_path, get_wrapper_file_name};
-use super::utils::{
- hyperfine_command, spawn_and_wait, spawn_and_wait_with_input, CargoProject, Compiler,
-};
+use super::rustc_info::get_host_triple;
+use super::utils::{spawn_and_wait, spawn_and_wait_with_input, CargoProject, Compiler};
use super::SysrootKind;
use std::env;
use std::ffi::OsStr;
@@ -17,256 +15,111 @@ static BUILD_EXAMPLE_OUT_DIR: RelPath = RelPath::BUILD.join("example");
struct TestCase {
config: &'static str,
- func: &'static dyn Fn(&TestRunner),
+ cmd: TestCaseCmd,
+}
+
+enum TestCaseCmd {
+ Custom { func: &'static dyn Fn(&TestRunner) },
+ BuildLib { source: &'static str, crate_types: &'static str },
+ BuildBinAndRun { source: &'static str, args: &'static [&'static str] },
+ JitBin { source: &'static str, args: &'static str },
}
impl TestCase {
- const fn new(config: &'static str, func: &'static dyn Fn(&TestRunner)) -> Self {
- Self { config, func }
+ // FIXME reduce usage of custom test case commands
+ const fn custom(config: &'static str, func: &'static dyn Fn(&TestRunner)) -> Self {
+ Self { config, cmd: TestCaseCmd::Custom { func } }
+ }
+
+ const fn build_lib(
+ config: &'static str,
+ source: &'static str,
+ crate_types: &'static str,
+ ) -> Self {
+ Self { config, cmd: TestCaseCmd::BuildLib { source, crate_types } }
+ }
+
+ const fn build_bin_and_run(
+ config: &'static str,
+ source: &'static str,
+ args: &'static [&'static str],
+ ) -> Self {
+ Self { config, cmd: TestCaseCmd::BuildBinAndRun { source, args } }
+ }
+
+ const fn jit_bin(config: &'static str, source: &'static str, args: &'static str) -> Self {
+ Self { config, cmd: TestCaseCmd::JitBin { source, args } }
}
}
const NO_SYSROOT_SUITE: &[TestCase] = &[
- TestCase::new("build.mini_core", &|runner| {
- runner.run_rustc([
- "example/mini_core.rs",
- "--crate-name",
- "mini_core",
- "--crate-type",
- "lib,dylib",
- "--target",
- &runner.target_compiler.triple,
- ]);
- }),
- TestCase::new("build.example", &|runner| {
- runner.run_rustc([
- "example/example.rs",
- "--crate-type",
- "lib",
- "--target",
- &runner.target_compiler.triple,
- ]);
- }),
- TestCase::new("jit.mini_core_hello_world", &|runner| {
- let mut jit_cmd = runner.rustc_command([
- "-Zunstable-options",
- "-Cllvm-args=mode=jit",
- "-Cprefer-dynamic",
- "example/mini_core_hello_world.rs",
- "--cfg",
- "jit",
- "--target",
- &runner.target_compiler.triple,
- ]);
- jit_cmd.env("CG_CLIF_JIT_ARGS", "abc bcd");
- spawn_and_wait(jit_cmd);
-
- eprintln!("[JIT-lazy] mini_core_hello_world");
- let mut jit_cmd = runner.rustc_command([
- "-Zunstable-options",
- "-Cllvm-args=mode=jit-lazy",
- "-Cprefer-dynamic",
- "example/mini_core_hello_world.rs",
- "--cfg",
- "jit",
- "--target",
- &runner.target_compiler.triple,
- ]);
- jit_cmd.env("CG_CLIF_JIT_ARGS", "abc bcd");
- spawn_and_wait(jit_cmd);
- }),
- TestCase::new("aot.mini_core_hello_world", &|runner| {
- runner.run_rustc([
- "example/mini_core_hello_world.rs",
- "--crate-name",
- "mini_core_hello_world",
- "--crate-type",
- "bin",
- "-g",
- "--target",
- &runner.target_compiler.triple,
- ]);
- runner.run_out_command("mini_core_hello_world", ["abc", "bcd"]);
- }),
+ TestCase::build_lib("build.mini_core", "example/mini_core.rs", "lib,dylib"),
+ TestCase::build_lib("build.example", "example/example.rs", "lib"),
+ TestCase::jit_bin("jit.mini_core_hello_world", "example/mini_core_hello_world.rs", "abc bcd"),
+ TestCase::build_bin_and_run(
+ "aot.mini_core_hello_world",
+ "example/mini_core_hello_world.rs",
+ &["abc", "bcd"],
+ ),
];
const BASE_SYSROOT_SUITE: &[TestCase] = &[
- TestCase::new("aot.arbitrary_self_types_pointers_and_wrappers", &|runner| {
- runner.run_rustc([
- "example/arbitrary_self_types_pointers_and_wrappers.rs",
- "--crate-name",
- "arbitrary_self_types_pointers_and_wrappers",
- "--crate-type",
- "bin",
- "--target",
- &runner.target_compiler.triple,
- ]);
- runner.run_out_command("arbitrary_self_types_pointers_and_wrappers", []);
- }),
- TestCase::new("aot.issue_91827_extern_types", &|runner| {
- runner.run_rustc([
- "example/issue-91827-extern-types.rs",
- "--crate-name",
- "issue_91827_extern_types",
- "--crate-type",
- "bin",
- "--target",
- &runner.target_compiler.triple,
- ]);
- runner.run_out_command("issue_91827_extern_types", []);
- }),
- TestCase::new("build.alloc_system", &|runner| {
- runner.run_rustc([
- "example/alloc_system.rs",
- "--crate-type",
- "lib",
- "--target",
- &runner.target_compiler.triple,
- ]);
- }),
- TestCase::new("aot.alloc_example", &|runner| {
- runner.run_rustc([
- "example/alloc_example.rs",
- "--crate-type",
- "bin",
- "--target",
- &runner.target_compiler.triple,
- ]);
- runner.run_out_command("alloc_example", []);
- }),
- TestCase::new("jit.std_example", &|runner| {
- runner.run_rustc([
- "-Zunstable-options",
- "-Cllvm-args=mode=jit",
- "-Cprefer-dynamic",
- "example/std_example.rs",
- "--target",
- &runner.target_compiler.triple,
- ]);
-
- eprintln!("[JIT-lazy] std_example");
- runner.run_rustc([
- "-Zunstable-options",
- "-Cllvm-args=mode=jit-lazy",
- "-Cprefer-dynamic",
- "example/std_example.rs",
- "--target",
- &runner.target_compiler.triple,
- ]);
- }),
- TestCase::new("aot.std_example", &|runner| {
- runner.run_rustc([
- "example/std_example.rs",
- "--crate-type",
- "bin",
- "--target",
- &runner.target_compiler.triple,
- ]);
- runner.run_out_command("std_example", ["arg"]);
- }),
- TestCase::new("aot.dst_field_align", &|runner| {
- runner.run_rustc([
- "example/dst-field-align.rs",
- "--crate-name",
- "dst_field_align",
- "--crate-type",
- "bin",
- "--target",
- &runner.target_compiler.triple,
- ]);
- runner.run_out_command("dst_field_align", []);
- }),
- TestCase::new("aot.subslice-patterns-const-eval", &|runner| {
- runner.run_rustc([
- "example/subslice-patterns-const-eval.rs",
- "--crate-type",
- "bin",
- "-Cpanic=abort",
- "--target",
- &runner.target_compiler.triple,
- ]);
- runner.run_out_command("subslice-patterns-const-eval", []);
- }),
- TestCase::new("aot.track-caller-attribute", &|runner| {
- runner.run_rustc([
- "example/track-caller-attribute.rs",
- "--crate-type",
- "bin",
- "-Cpanic=abort",
- "--target",
- &runner.target_compiler.triple,
- ]);
- runner.run_out_command("track-caller-attribute", []);
- }),
- TestCase::new("aot.float-minmax-pass", &|runner| {
- runner.run_rustc([
- "example/float-minmax-pass.rs",
- "--crate-type",
- "bin",
- "-Cpanic=abort",
- "--target",
- &runner.target_compiler.triple,
- ]);
- runner.run_out_command("float-minmax-pass", []);
- }),
- TestCase::new("aot.mod_bench", &|runner| {
- runner.run_rustc([
- "example/mod_bench.rs",
- "--crate-type",
- "bin",
- "--target",
- &runner.target_compiler.triple,
- ]);
- runner.run_out_command("mod_bench", []);
- }),
- TestCase::new("aot.issue-72793", &|runner| {
- runner.run_rustc([
- "example/issue-72793.rs",
- "--crate-type",
- "bin",
- "--target",
- &runner.target_compiler.triple,
- ]);
- runner.run_out_command("issue-72793", []);
- }),
+ TestCase::build_bin_and_run(
+ "aot.arbitrary_self_types_pointers_and_wrappers",
+ "example/arbitrary_self_types_pointers_and_wrappers.rs",
+ &[],
+ ),
+ TestCase::build_bin_and_run(
+ "aot.issue_91827_extern_types",
+ "example/issue-91827-extern-types.rs",
+ &[],
+ ),
+ TestCase::build_lib("build.alloc_system", "example/alloc_system.rs", "lib"),
+ TestCase::build_bin_and_run("aot.alloc_example", "example/alloc_example.rs", &[]),
+ TestCase::jit_bin("jit.std_example", "example/std_example.rs", ""),
+ TestCase::build_bin_and_run("aot.std_example", "example/std_example.rs", &["arg"]),
+ TestCase::build_bin_and_run("aot.dst_field_align", "example/dst-field-align.rs", &[]),
+ TestCase::build_bin_and_run(
+ "aot.subslice-patterns-const-eval",
+ "example/subslice-patterns-const-eval.rs",
+ &[],
+ ),
+ TestCase::build_bin_and_run(
+ "aot.track-caller-attribute",
+ "example/track-caller-attribute.rs",
+ &[],
+ ),
+ TestCase::build_bin_and_run("aot.float-minmax-pass", "example/float-minmax-pass.rs", &[]),
+ TestCase::build_bin_and_run("aot.mod_bench", "example/mod_bench.rs", &[]),
+ TestCase::build_bin_and_run("aot.issue-72793", "example/issue-72793.rs", &[]),
];
pub(crate) static RAND_REPO: GitRepo =
GitRepo::github("rust-random", "rand", "0f933f9c7176e53b2a3c7952ded484e1783f0bf1", "rand");
-static RAND: CargoProject = CargoProject::new(&RAND_REPO.source_dir(), "rand");
+pub(crate) static RAND: CargoProject = CargoProject::new(&RAND_REPO.source_dir(), "rand");
pub(crate) static REGEX_REPO: GitRepo =
GitRepo::github("rust-lang", "regex", "341f207c1071f7290e3f228c710817c280c8dca1", "regex");
-static REGEX: CargoProject = CargoProject::new(&REGEX_REPO.source_dir(), "regex");
+pub(crate) static REGEX: CargoProject = CargoProject::new(&REGEX_REPO.source_dir(), "regex");
pub(crate) static PORTABLE_SIMD_REPO: GitRepo = GitRepo::github(
"rust-lang",
"portable-simd",
- "d5cd4a8112d958bd3a252327e0d069a6363249bd",
+ "582239ac3b32007613df04d7ffa78dc30f4c5645",
"portable-simd",
);
-static PORTABLE_SIMD: CargoProject =
+pub(crate) static PORTABLE_SIMD: CargoProject =
CargoProject::new(&PORTABLE_SIMD_REPO.source_dir(), "portable_simd");
-pub(crate) static SIMPLE_RAYTRACER_REPO: GitRepo = GitRepo::github(
- "ebobby",
- "simple-raytracer",
- "804a7a21b9e673a482797aa289a18ed480e4d813",
- "<none>",
-);
-
-pub(crate) static SIMPLE_RAYTRACER: CargoProject =
- CargoProject::new(&SIMPLE_RAYTRACER_REPO.source_dir(), "simple_raytracer");
-
-static LIBCORE_TESTS: CargoProject =
- CargoProject::new(&RelPath::BUILD_SYSROOT.join("sysroot_src/library/core/tests"), "core_tests");
+pub(crate) static LIBCORE_TESTS: CargoProject =
+ CargoProject::new(&SYSROOT_SRC.join("library/core/tests"), "core_tests");
const EXTENDED_SYSROOT_SUITE: &[TestCase] = &[
- TestCase::new("test.rust-random/rand", &|runner| {
- spawn_and_wait(RAND.clean(&runner.target_compiler.cargo, &runner.dirs));
+ TestCase::custom("test.rust-random/rand", &|runner| {
+ RAND.clean(&runner.dirs);
if runner.is_native {
eprintln!("[TEST] rust-random/rand");
@@ -280,60 +133,8 @@ const EXTENDED_SYSROOT_SUITE: &[TestCase] = &[
spawn_and_wait(build_cmd);
}
}),
- TestCase::new("bench.simple-raytracer", &|runner| {
- let run_runs = env::var("RUN_RUNS").unwrap_or("10".to_string()).parse().unwrap();
-
- if runner.is_native {
- eprintln!("[BENCH COMPILE] ebobby/simple-raytracer");
- let cargo_clif = RelPath::DIST
- .to_path(&runner.dirs)
- .join(get_wrapper_file_name("cargo-clif", "bin"));
- let manifest_path = SIMPLE_RAYTRACER.manifest_path(&runner.dirs);
- let target_dir = SIMPLE_RAYTRACER.target_dir(&runner.dirs);
-
- let clean_cmd = format!(
- "cargo clean --manifest-path {manifest_path} --target-dir {target_dir}",
- manifest_path = manifest_path.display(),
- target_dir = target_dir.display(),
- );
- let llvm_build_cmd = format!(
- "cargo build --manifest-path {manifest_path} --target-dir {target_dir}",
- manifest_path = manifest_path.display(),
- target_dir = target_dir.display(),
- );
- let clif_build_cmd = format!(
- "{cargo_clif} build --manifest-path {manifest_path} --target-dir {target_dir}",
- cargo_clif = cargo_clif.display(),
- manifest_path = manifest_path.display(),
- target_dir = target_dir.display(),
- );
-
- let bench_compile =
- hyperfine_command(1, run_runs, Some(&clean_cmd), &llvm_build_cmd, &clif_build_cmd);
-
- spawn_and_wait(bench_compile);
-
- eprintln!("[BENCH RUN] ebobby/simple-raytracer");
- fs::copy(
- target_dir.join("debug").join("main"),
- RelPath::BUILD.to_path(&runner.dirs).join("raytracer_cg_clif"),
- )
- .unwrap();
-
- let mut bench_run =
- hyperfine_command(0, run_runs, None, "./raytracer_cg_llvm", "./raytracer_cg_clif");
- bench_run.current_dir(RelPath::BUILD.to_path(&runner.dirs));
- spawn_and_wait(bench_run);
- } else {
- spawn_and_wait(SIMPLE_RAYTRACER.clean(&runner.target_compiler.cargo, &runner.dirs));
- eprintln!("[BENCH COMPILE] ebobby/simple-raytracer (skipped)");
- eprintln!("[COMPILE] ebobby/simple-raytracer");
- spawn_and_wait(SIMPLE_RAYTRACER.build(&runner.target_compiler, &runner.dirs));
- eprintln!("[BENCH RUN] ebobby/simple-raytracer (skipped)");
- }
- }),
- TestCase::new("test.libcore", &|runner| {
- spawn_and_wait(LIBCORE_TESTS.clean(&runner.host_compiler.cargo, &runner.dirs));
+ TestCase::custom("test.libcore", &|runner| {
+ LIBCORE_TESTS.clean(&runner.dirs);
if runner.is_native {
spawn_and_wait(LIBCORE_TESTS.test(&runner.target_compiler, &runner.dirs));
@@ -344,8 +145,8 @@ const EXTENDED_SYSROOT_SUITE: &[TestCase] = &[
spawn_and_wait(build_cmd);
}
}),
- TestCase::new("test.regex-shootout-regex-dna", &|runner| {
- spawn_and_wait(REGEX.clean(&runner.target_compiler.cargo, &runner.dirs));
+ TestCase::custom("test.regex-shootout-regex-dna", &|runner| {
+ REGEX.clean(&runner.dirs);
// newer aho_corasick versions throw a deprecation warning
let lint_rust_flags = format!("{} --cap-lints warn", runner.target_compiler.rustflags);
@@ -364,9 +165,10 @@ const EXTENDED_SYSROOT_SUITE: &[TestCase] = &[
REGEX.source_dir(&runner.dirs).join("examples").join("regexdna-input.txt"),
)
.unwrap();
- let expected_path =
- REGEX.source_dir(&runner.dirs).join("examples").join("regexdna-output.txt");
- let expected = fs::read_to_string(&expected_path).unwrap();
+ let expected = fs::read_to_string(
+ REGEX.source_dir(&runner.dirs).join("examples").join("regexdna-output.txt"),
+ )
+ .unwrap();
let output = spawn_and_wait_with_input(run_cmd, input);
// Make sure `[codegen mono items] start` doesn't poison the diff
@@ -379,27 +181,16 @@ const EXTENDED_SYSROOT_SUITE: &[TestCase] = &[
let output_matches = expected.lines().eq(output.lines());
if !output_matches {
- let res_path = REGEX.source_dir(&runner.dirs).join("res.txt");
- fs::write(&res_path, &output).unwrap();
-
- if cfg!(windows) {
- println!("Output files don't match!");
- println!("Expected Output:\n{}", expected);
- println!("Actual Output:\n{}", output);
- } else {
- let mut diff = Command::new("diff");
- diff.arg("-u");
- diff.arg(res_path);
- diff.arg(expected_path);
- spawn_and_wait(diff);
- }
+ println!("Output files don't match!");
+ println!("Expected Output:\n{}", expected);
+ println!("Actual Output:\n{}", output);
std::process::exit(1);
}
}
}),
- TestCase::new("test.regex", &|runner| {
- spawn_and_wait(REGEX.clean(&runner.host_compiler.cargo, &runner.dirs));
+ TestCase::custom("test.regex", &|runner| {
+ REGEX.clean(&runner.dirs);
// newer aho_corasick versions throw a deprecation warning
let lint_rust_flags = format!("{} --cap-lints warn", runner.target_compiler.rustflags);
@@ -425,8 +216,8 @@ const EXTENDED_SYSROOT_SUITE: &[TestCase] = &[
spawn_and_wait(build_cmd);
}
}),
- TestCase::new("test.portable-simd", &|runner| {
- spawn_and_wait(PORTABLE_SIMD.clean(&runner.host_compiler.cargo, &runner.dirs));
+ TestCase::custom("test.portable-simd", &|runner| {
+ PORTABLE_SIMD.clean(&runner.dirs);
let mut build_cmd = PORTABLE_SIMD.build(&runner.target_compiler, &runner.dirs);
build_cmd.arg("--all-targets");
@@ -445,21 +236,22 @@ pub(crate) fn run_tests(
channel: &str,
sysroot_kind: SysrootKind,
cg_clif_dylib: &Path,
- host_triple: &str,
- target_triple: &str,
+ bootstrap_host_compiler: &Compiler,
+ target_triple: String,
) {
- let runner = TestRunner::new(dirs.clone(), host_triple.to_string(), target_triple.to_string());
-
if config::get_bool("testsuite.no_sysroot") {
- build_sysroot::build_sysroot(
+ let target_compiler = build_sysroot::build_sysroot(
dirs,
channel,
SysrootKind::None,
cg_clif_dylib,
- &host_triple,
- &target_triple,
+ bootstrap_host_compiler,
+ target_triple.clone(),
);
+ let runner =
+ TestRunner::new(dirs.clone(), target_compiler, get_host_triple() == target_triple);
+
BUILD_EXAMPLE_OUT_DIR.ensure_fresh(dirs);
runner.run_testsuite(NO_SYSROOT_SUITE);
} else {
@@ -470,26 +262,29 @@ pub(crate) fn run_tests(
let run_extended_sysroot = config::get_bool("testsuite.extended_sysroot");
if run_base_sysroot || run_extended_sysroot {
- build_sysroot::build_sysroot(
+ let target_compiler = build_sysroot::build_sysroot(
dirs,
channel,
sysroot_kind,
cg_clif_dylib,
- &host_triple,
- &target_triple,
+ bootstrap_host_compiler,
+ target_triple.clone(),
);
- }
- if run_base_sysroot {
- runner.run_testsuite(BASE_SYSROOT_SUITE);
- } else {
- eprintln!("[SKIP] base_sysroot tests");
- }
+ let runner =
+ TestRunner::new(dirs.clone(), target_compiler, get_host_triple() == target_triple);
- if run_extended_sysroot {
- runner.run_testsuite(EXTENDED_SYSROOT_SUITE);
- } else {
- eprintln!("[SKIP] extended_sysroot tests");
+ if run_base_sysroot {
+ runner.run_testsuite(BASE_SYSROOT_SUITE);
+ } else {
+ eprintln!("[SKIP] base_sysroot tests");
+ }
+
+ if run_extended_sysroot {
+ runner.run_testsuite(EXTENDED_SYSROOT_SUITE);
+ } else {
+ eprintln!("[SKIP] extended_sysroot tests");
+ }
}
}
@@ -497,84 +292,34 @@ struct TestRunner {
is_native: bool,
jit_supported: bool,
dirs: Dirs,
- host_compiler: Compiler,
target_compiler: Compiler,
}
impl TestRunner {
- pub fn new(dirs: Dirs, host_triple: String, target_triple: String) -> Self {
- let is_native = host_triple == target_triple;
- let jit_supported =
- target_triple.contains("x86_64") && is_native && !host_triple.contains("windows");
-
- let rustc_clif =
- RelPath::DIST.to_path(&dirs).join(get_wrapper_file_name("rustc-clif", "bin"));
- let rustdoc_clif =
- RelPath::DIST.to_path(&dirs).join(get_wrapper_file_name("rustdoc-clif", "bin"));
-
- let mut rustflags = env::var("RUSTFLAGS").ok().unwrap_or("".to_string());
- let mut runner = vec![];
-
- if !is_native {
- match target_triple.as_str() {
- "aarch64-unknown-linux-gnu" => {
- // We are cross-compiling for aarch64. Use the correct linker and run tests in qemu.
- rustflags = format!("-Clinker=aarch64-linux-gnu-gcc{}", rustflags);
- runner = vec![
- "qemu-aarch64".to_owned(),
- "-L".to_owned(),
- "/usr/aarch64-linux-gnu".to_owned(),
- ];
- }
- "s390x-unknown-linux-gnu" => {
- // We are cross-compiling for s390x. Use the correct linker and run tests in qemu.
- rustflags = format!("-Clinker=s390x-linux-gnu-gcc{}", rustflags);
- runner = vec![
- "qemu-s390x".to_owned(),
- "-L".to_owned(),
- "/usr/s390x-linux-gnu".to_owned(),
- ];
- }
- "x86_64-pc-windows-gnu" => {
- // We are cross-compiling for Windows. Run tests in wine.
- runner = vec!["wine".to_owned()];
- }
- _ => {
- println!("Unknown non-native platform");
- }
- }
+ pub fn new(dirs: Dirs, mut target_compiler: Compiler, is_native: bool) -> Self {
+ if let Ok(rustflags) = env::var("RUSTFLAGS") {
+ target_compiler.rustflags.push(' ');
+ target_compiler.rustflags.push_str(&rustflags);
+ }
+ if let Ok(rustdocflags) = env::var("RUSTDOCFLAGS") {
+ target_compiler.rustdocflags.push(' ');
+ target_compiler.rustdocflags.push_str(&rustdocflags);
}
// FIXME fix `#[linkage = "extern_weak"]` without this
- if target_triple.contains("darwin") {
- rustflags = format!("{} -Clink-arg=-undefined -Clink-arg=dynamic_lookup", rustflags);
+ if target_compiler.triple.contains("darwin") {
+ target_compiler.rustflags.push_str(" -Clink-arg=-undefined -Clink-arg=dynamic_lookup");
}
- let host_compiler = Compiler {
- cargo: get_cargo_path(),
- rustc: rustc_clif.clone(),
- rustdoc: rustdoc_clif.clone(),
- rustflags: String::new(),
- rustdocflags: String::new(),
- triple: host_triple,
- runner: vec![],
- };
-
- let target_compiler = Compiler {
- cargo: get_cargo_path(),
- rustc: rustc_clif,
- rustdoc: rustdoc_clif,
- rustflags: rustflags.clone(),
- rustdocflags: rustflags,
- triple: target_triple,
- runner,
- };
-
- Self { is_native, jit_supported, dirs, host_compiler, target_compiler }
+ let jit_supported = is_native
+ && target_compiler.triple.contains("x86_64")
+ && !target_compiler.triple.contains("windows");
+
+ Self { is_native, jit_supported, dirs, target_compiler }
}
pub fn run_testsuite(&self, tests: &[TestCase]) {
- for &TestCase { config, func } in tests {
+ for TestCase { config, cmd } in tests {
let (tag, testname) = config.split_once('.').unwrap();
let tag = tag.to_uppercase();
let is_jit_test = tag == "JIT";
@@ -586,7 +331,47 @@ impl TestRunner {
eprintln!("[{tag}] {testname}");
}
- func(self);
+ match *cmd {
+ TestCaseCmd::Custom { func } => func(self),
+ TestCaseCmd::BuildLib { source, crate_types } => {
+ self.run_rustc([source, "--crate-type", crate_types]);
+ }
+ TestCaseCmd::BuildBinAndRun { source, args } => {
+ self.run_rustc([source]);
+ self.run_out_command(
+ source.split('/').last().unwrap().split('.').next().unwrap(),
+ args,
+ );
+ }
+ TestCaseCmd::JitBin { source, args } => {
+ let mut jit_cmd = self.rustc_command([
+ "-Zunstable-options",
+ "-Cllvm-args=mode=jit",
+ "-Cprefer-dynamic",
+ source,
+ "--cfg",
+ "jit",
+ ]);
+ if !args.is_empty() {
+ jit_cmd.env("CG_CLIF_JIT_ARGS", args);
+ }
+ spawn_and_wait(jit_cmd);
+
+ eprintln!("[JIT-lazy] {testname}");
+ let mut jit_cmd = self.rustc_command([
+ "-Zunstable-options",
+ "-Cllvm-args=mode=jit-lazy",
+ "-Cprefer-dynamic",
+ source,
+ "--cfg",
+ "jit",
+ ]);
+ if !args.is_empty() {
+ jit_cmd.env("CG_CLIF_JIT_ARGS", args);
+ }
+ spawn_and_wait(jit_cmd);
+ }
+ }
}
}
@@ -603,6 +388,9 @@ impl TestRunner {
cmd.arg("--out-dir");
cmd.arg(format!("{}", BUILD_EXAMPLE_OUT_DIR.to_path(&self.dirs).display()));
cmd.arg("-Cdebuginfo=2");
+ cmd.arg("--target");
+ cmd.arg(&self.target_compiler.triple);
+ cmd.arg("-Cpanic=abort");
cmd.args(args);
cmd
}
@@ -615,10 +403,7 @@ impl TestRunner {
spawn_and_wait(self.rustc_command(args));
}
- fn run_out_command<'a, I>(&self, name: &str, args: I)
- where
- I: IntoIterator<Item = &'a str>,
- {
+ fn run_out_command<'a>(&self, name: &str, args: &[&str]) {
let mut full_cmd = vec![];
// Prepend the RUN_WRAPPER's
@@ -630,7 +415,7 @@ impl TestRunner {
BUILD_EXAMPLE_OUT_DIR.to_path(&self.dirs).join(name).to_str().unwrap().to_string(),
);
- for arg in args.into_iter() {
+ for arg in args {
full_cmd.push(arg.to_string());
}
diff --git a/compiler/rustc_codegen_cranelift/build_system/usage.txt b/compiler/rustc_codegen_cranelift/build_system/usage.txt
new file mode 100644
index 000000000..ab98ccc35
--- /dev/null
+++ b/compiler/rustc_codegen_cranelift/build_system/usage.txt
@@ -0,0 +1,35 @@
+The build system of cg_clif.
+
+USAGE:
+ ./y.rs prepare [--out-dir DIR]
+ ./y.rs build [--debug] [--sysroot none|clif|llvm] [--out-dir DIR] [--no-unstable-features]
+ ./y.rs test [--debug] [--sysroot none|clif|llvm] [--out-dir DIR] [--no-unstable-features]
+ ./y.rs abi-cafe [--debug] [--sysroot none|clif|llvm] [--out-dir DIR] [--no-unstable-features]
+ ./y.rs bench [--debug] [--sysroot none|clif|llvm] [--out-dir DIR] [--no-unstable-features]
+
+OPTIONS:
+ --debug
+ Build cg_clif and the standard library in debug mode rather than release mode.
+ Warning: An unoptimized cg_clif is very slow.
+
+ --sysroot none|clif|llvm
+ Which sysroot libraries to use:
+ `none` will not include any standard library in the sysroot.
+ `clif` will build the standard library using Cranelift.
+ `llvm` will use the pre-compiled standard library of rustc which is compiled with LLVM.
+
+ --out-dir DIR
+ Specify the directory in which the download, build and dist directories are stored.
+ By default this is the working directory.
+
+ --no-unstable-features
+ Some features are not yet ready for production usage. This option will disable these
+ features. This includes the JIT mode and inline assembly support.
+
+REQUIREMENTS:
+ * Rustup: The build system has a hard coded dependency on rustup to install the right nightly
+ version and make sure it is used where necessary.
+ * Git: `./y.rs prepare` uses git for applying patches and on Windows for downloading test repos.
+ * Curl and tar (non-Windows only): Used by `./y.rs prepare` to download a single commit for
+ repos. Git will be used to clone the whole repo when using Windows.
+ * [Hyperfine](https://github.com/sharkdp/hyperfine/): Used for benchmarking with `./y.rs bench`.
diff --git a/compiler/rustc_codegen_cranelift/build_system/utils.rs b/compiler/rustc_codegen_cranelift/build_system/utils.rs
index 2be70e8e4..abc5bab49 100644
--- a/compiler/rustc_codegen_cranelift/build_system/utils.rs
+++ b/compiler/rustc_codegen_cranelift/build_system/utils.rs
@@ -1,12 +1,13 @@
use std::env;
use std::fs;
-use std::io::Write;
+use std::io::{self, Write};
use std::path::{Path, PathBuf};
use std::process::{self, Command, Stdio};
use super::path::{Dirs, RelPath};
-use super::rustc_info::{get_cargo_path, get_host_triple, get_rustc_path, get_rustdoc_path};
+use super::rustc_info::{get_cargo_path, get_rustc_path, get_rustdoc_path};
+#[derive(Clone, Debug)]
pub(crate) struct Compiler {
pub(crate) cargo: PathBuf,
pub(crate) rustc: PathBuf,
@@ -18,27 +19,47 @@ pub(crate) struct Compiler {
}
impl Compiler {
- pub(crate) fn host() -> Compiler {
+ pub(crate) fn bootstrap_with_triple(triple: String) -> Compiler {
Compiler {
cargo: get_cargo_path(),
rustc: get_rustc_path(),
rustdoc: get_rustdoc_path(),
rustflags: String::new(),
rustdocflags: String::new(),
- triple: get_host_triple(),
+ triple,
runner: vec![],
}
}
- pub(crate) fn with_triple(triple: String) -> Compiler {
- Compiler {
- cargo: get_cargo_path(),
- rustc: get_rustc_path(),
- rustdoc: get_rustdoc_path(),
- rustflags: String::new(),
- rustdocflags: String::new(),
- triple,
- runner: vec![],
+ pub(crate) fn set_cross_linker_and_runner(&mut self) {
+ match self.triple.as_str() {
+ "aarch64-unknown-linux-gnu" => {
+ // We are cross-compiling for aarch64. Use the correct linker and run tests in qemu.
+ self.rustflags += " -Clinker=aarch64-linux-gnu-gcc";
+ self.rustdocflags += " -Clinker=aarch64-linux-gnu-gcc";
+ self.runner = vec![
+ "qemu-aarch64".to_owned(),
+ "-L".to_owned(),
+ "/usr/aarch64-linux-gnu".to_owned(),
+ ];
+ }
+ "s390x-unknown-linux-gnu" => {
+ // We are cross-compiling for s390x. Use the correct linker and run tests in qemu.
+ self.rustflags += " -Clinker=s390x-linux-gnu-gcc";
+ self.rustdocflags += " -Clinker=s390x-linux-gnu-gcc";
+ self.runner = vec![
+ "qemu-s390x".to_owned(),
+ "-L".to_owned(),
+ "/usr/s390x-linux-gnu".to_owned(),
+ ];
+ }
+ "x86_64-pc-windows-gnu" => {
+ // We are cross-compiling for Windows. Run tests in wine.
+ self.runner = vec!["wine".to_owned()];
+ }
+ _ => {
+ println!("Unknown non-native platform");
+ }
}
}
}
@@ -65,6 +86,7 @@ impl CargoProject {
RelPath::BUILD.join(self.target).to_path(dirs)
}
+ #[must_use]
fn base_cmd(&self, command: &str, cargo: &Path, dirs: &Dirs) -> Command {
let mut cmd = Command::new(cargo);
@@ -72,11 +94,13 @@ impl CargoProject {
.arg("--manifest-path")
.arg(self.manifest_path(dirs))
.arg("--target-dir")
- .arg(self.target_dir(dirs));
+ .arg(self.target_dir(dirs))
+ .arg("--frozen");
cmd
}
+ #[must_use]
fn build_cmd(&self, command: &str, compiler: &Compiler, dirs: &Dirs) -> Command {
let mut cmd = self.base_cmd(command, &compiler.cargo, dirs);
@@ -97,17 +121,24 @@ impl CargoProject {
}
#[must_use]
- pub(crate) fn fetch(&self, cargo: impl AsRef<Path>, dirs: &Dirs) -> Command {
+ pub(crate) fn fetch(
+ &self,
+ cargo: impl AsRef<Path>,
+ rustc: impl AsRef<Path>,
+ dirs: &Dirs,
+ ) -> Command {
let mut cmd = Command::new(cargo.as_ref());
- cmd.arg("fetch").arg("--manifest-path").arg(self.manifest_path(dirs));
+ cmd.env("RUSTC", rustc.as_ref())
+ .arg("fetch")
+ .arg("--manifest-path")
+ .arg(self.manifest_path(dirs));
cmd
}
- #[must_use]
- pub(crate) fn clean(&self, cargo: &Path, dirs: &Dirs) -> Command {
- self.base_cmd("clean", cargo, dirs)
+ pub(crate) fn clean(&self, dirs: &Dirs) {
+ let _ = fs::remove_dir_all(self.target_dir(dirs));
}
#[must_use]
@@ -153,6 +184,23 @@ pub(crate) fn hyperfine_command(
bench
}
+#[must_use]
+pub(crate) fn git_command<'a>(repo_dir: impl Into<Option<&'a Path>>, cmd: &str) -> Command {
+ let mut git_cmd = Command::new("git");
+ git_cmd
+ .arg("-c")
+ .arg("user.name=Dummy")
+ .arg("-c")
+ .arg("user.email=dummy@example.com")
+ .arg("-c")
+ .arg("core.autocrlf=false")
+ .arg(cmd);
+ if let Some(repo_dir) = repo_dir.into() {
+ git_cmd.current_dir(repo_dir);
+ }
+ git_cmd
+}
+
#[track_caller]
pub(crate) fn try_hard_link(src: impl AsRef<Path>, dst: impl AsRef<Path>) {
let src = src.as_ref();
@@ -169,6 +217,22 @@ pub(crate) fn spawn_and_wait(mut cmd: Command) {
}
}
+// Based on the retry function in rust's src/ci/shared.sh
+#[track_caller]
+pub(crate) fn retry_spawn_and_wait(tries: u64, mut cmd: Command) {
+ for i in 1..tries + 1 {
+ if i != 1 {
+ println!("Command failed. Attempt {i}/{tries}:");
+ }
+ if cmd.spawn().unwrap().wait().unwrap().success() {
+ return;
+ }
+ std::thread::sleep(std::time::Duration::from_secs(i * 5));
+ }
+ println!("The command has failed after {tries} attempts.");
+ process::exit(1);
+}
+
#[track_caller]
pub(crate) fn spawn_and_wait_with_input(mut cmd: Command, input: String) -> String {
let mut child = cmd
@@ -190,6 +254,14 @@ pub(crate) fn spawn_and_wait_with_input(mut cmd: Command, input: String) -> Stri
String::from_utf8(output.stdout).unwrap()
}
+pub(crate) fn remove_dir_if_exists(path: &Path) {
+ match fs::remove_dir_all(&path) {
+ Ok(()) => {}
+ Err(err) if err.kind() == io::ErrorKind::NotFound => {}
+ Err(err) => panic!("Failed to remove {path}: {err}", path = path.display()),
+ }
+}
+
pub(crate) fn copy_dir_recursively(from: &Path, to: &Path) {
for entry in fs::read_dir(from).unwrap() {
let entry = entry.unwrap();
@@ -207,5 +279,9 @@ pub(crate) fn copy_dir_recursively(from: &Path, to: &Path) {
}
pub(crate) fn is_ci() -> bool {
- env::var("CI").as_deref() == Ok("true")
+ env::var("CI").is_ok()
+}
+
+pub(crate) fn is_ci_opt() -> bool {
+ env::var("CI_OPT").is_ok()
}
diff --git a/compiler/rustc_codegen_cranelift/clean_all.sh b/compiler/rustc_codegen_cranelift/clean_all.sh
index 1760e5836..cdfc2e143 100755
--- a/compiler/rustc_codegen_cranelift/clean_all.sh
+++ b/compiler/rustc_codegen_cranelift/clean_all.sh
@@ -1,10 +1,9 @@
#!/usr/bin/env bash
set -e
-rm -rf build_sysroot/{sysroot_src/,target/,compiler-builtins/,rustc_version}
-rm -rf target/ build/ dist/ perf.data{,.old} y.bin
-rm -rf download/
+rm -rf target/ download/ build/ dist/ y.bin y.bin.dSYM y.exe y.pdb
# Kept for now in case someone updates their checkout of cg_clif before running clean_all.sh
# FIXME remove at some point in the future
rm -rf rand/ regex/ simple-raytracer/ portable-simd/ abi-checker/ abi-cafe/
+rm -rf build_sysroot/{sysroot_src/,target/,compiler-builtins/,rustc_version}
diff --git a/compiler/rustc_codegen_cranelift/config.txt b/compiler/rustc_codegen_cranelift/config.txt
index 258b67e93..d6e3924a2 100644
--- a/compiler/rustc_codegen_cranelift/config.txt
+++ b/compiler/rustc_codegen_cranelift/config.txt
@@ -44,10 +44,7 @@ aot.issue-72793
testsuite.extended_sysroot
test.rust-random/rand
-bench.simple-raytracer
test.libcore
test.regex-shootout-regex-dna
test.regex
test.portable-simd
-
-testsuite.abi-cafe
diff --git a/compiler/rustc_codegen_cranelift/patches/0001-portable-simd-Disable-unsupported-tests.patch b/compiler/rustc_codegen_cranelift/patches/0001-portable-simd-Disable-unsupported-tests.patch
deleted file mode 100644
index 89e2b61c1..000000000
--- a/compiler/rustc_codegen_cranelift/patches/0001-portable-simd-Disable-unsupported-tests.patch
+++ /dev/null
@@ -1,35 +0,0 @@
-From b742f03694b920cc14400727d54424e8e1b60928 Mon Sep 17 00:00:00 2001
-From: bjorn3 <bjorn3@users.noreply.github.com>
-Date: Thu, 18 Nov 2021 19:28:40 +0100
-Subject: [PATCH] Disable unsupported tests
-
----
- crates/core_simd/src/elements/int.rs | 8 ++++++++
- crates/core_simd/src/elements/uint.rs | 4 ++++
- crates/core_simd/src/masks/full_masks.rs | 6 ++++++
- crates/core_simd/src/vector.rs | 2 ++
- crates/core_simd/tests/masks.rs | 3 ---
- 5 files changed, 20 insertions(+), 3 deletions(-)
-
-diff --git a/crates/core_simd/src/vector.rs b/crates/core_simd/src/vector.rs
-index e8e8f68..7173c24 100644
---- a/crates/core_simd/src/vector.rs
-+++ b/crates/core_simd/src/vector.rs
-@@ -250,6 +250,7 @@ where
- unsafe { intrinsics::simd_cast(self) }
- }
-
-+ /*
- /// Reads from potentially discontiguous indices in `slice` to construct a SIMD vector.
- /// If an index is out-of-bounds, the lane is instead selected from the `or` vector.
- ///
-@@ -473,6 +474,7 @@ where
- // Cleared ☢️ *mut T Zone
- }
- }
-+ */
- }
-
- impl<T, const LANES: usize> Copy for Simd<T, LANES>
---
-2.25.1
diff --git a/compiler/rustc_codegen_cranelift/patches/0022-sysroot-Disable-not-compiling-tests.patch b/compiler/rustc_codegen_cranelift/patches/0022-sysroot-Disable-not-compiling-tests.patch
index 8d9ee3f25..865aa833a 100644
--- a/compiler/rustc_codegen_cranelift/patches/0022-sysroot-Disable-not-compiling-tests.patch
+++ b/compiler/rustc_codegen_cranelift/patches/0022-sysroot-Disable-not-compiling-tests.patch
@@ -18,7 +18,7 @@ new file mode 100644
index 0000000..46fd999
--- /dev/null
+++ b/library/core/tests/Cargo.toml
-@@ -0,0 +1,11 @@
+@@ -0,0 +1,12 @@
+[package]
+name = "core"
+version = "0.0.0"
@@ -29,6 +29,7 @@ index 0000000..46fd999
+path = "lib.rs"
+
+[dependencies]
-+rand = "0.7"
++rand = { version = "0.8.5", default-features = false }
++rand_xorshift = { version = "0.3.0", default-features = false }
--
2.21.0 (Apple Git-122)
diff --git a/compiler/rustc_codegen_cranelift/rust-toolchain b/compiler/rustc_codegen_cranelift/rust-toolchain
index d8f28dbcc..40fb54b91 100644
--- a/compiler/rustc_codegen_cranelift/rust-toolchain
+++ b/compiler/rustc_codegen_cranelift/rust-toolchain
@@ -1,3 +1,3 @@
[toolchain]
-channel = "nightly-2022-12-13"
+channel = "nightly-2023-02-06"
components = ["rust-src", "rustc-dev", "llvm-tools-preview"]
diff --git a/compiler/rustc_codegen_cranelift/scripts/cargo-clif.rs b/compiler/rustc_codegen_cranelift/scripts/cargo-clif.rs
index 9362b47fa..c993430b8 100644
--- a/compiler/rustc_codegen_cranelift/scripts/cargo-clif.rs
+++ b/compiler/rustc_codegen_cranelift/scripts/cargo-clif.rs
@@ -26,7 +26,7 @@ fn main() {
env::set_var("RUSTDOCFLAGS", env::var("RUSTDOCFLAGS").unwrap_or(String::new()) + &rustflags);
// Ensure that the right toolchain is used
- env::set_var("RUSTUP_TOOLCHAIN", env!("RUSTUP_TOOLCHAIN"));
+ env::set_var("RUSTUP_TOOLCHAIN", env!("TOOLCHAIN_NAME"));
let args: Vec<_> = match env::args().nth(1).as_deref() {
Some("jit") => {
diff --git a/compiler/rustc_codegen_cranelift/scripts/rustc-clif.rs b/compiler/rustc_codegen_cranelift/scripts/rustc-clif.rs
index 3abfcd8dd..c187f54a6 100644
--- a/compiler/rustc_codegen_cranelift/scripts/rustc-clif.rs
+++ b/compiler/rustc_codegen_cranelift/scripts/rustc-clif.rs
@@ -24,7 +24,7 @@ fn main() {
}
// Ensure that the right toolchain is used
- env::set_var("RUSTUP_TOOLCHAIN", env!("RUSTUP_TOOLCHAIN"));
+ env::set_var("RUSTUP_TOOLCHAIN", env!("TOOLCHAIN_NAME"));
#[cfg(unix)]
Command::new("rustc").args(args).exec();
diff --git a/compiler/rustc_codegen_cranelift/scripts/rustdoc-clif.rs b/compiler/rustc_codegen_cranelift/scripts/rustdoc-clif.rs
index a19d72acf..a6528ac41 100644
--- a/compiler/rustc_codegen_cranelift/scripts/rustdoc-clif.rs
+++ b/compiler/rustc_codegen_cranelift/scripts/rustdoc-clif.rs
@@ -24,7 +24,7 @@ fn main() {
}
// Ensure that the right toolchain is used
- env::set_var("RUSTUP_TOOLCHAIN", env!("RUSTUP_TOOLCHAIN"));
+ env::set_var("RUSTUP_TOOLCHAIN", env!("TOOLCHAIN_NAME"));
#[cfg(unix)]
Command::new("rustdoc").args(args).exec();
diff --git a/compiler/rustc_codegen_cranelift/scripts/rustup.sh b/compiler/rustc_codegen_cranelift/scripts/rustup.sh
index bc4c06ed7..34e3981b5 100755
--- a/compiler/rustc_codegen_cranelift/scripts/rustup.sh
+++ b/compiler/rustc_codegen_cranelift/scripts/rustup.sh
@@ -17,10 +17,10 @@ case $1 in
done
./clean_all.sh
- ./y.rs prepare
- (cd build_sysroot && cargo update)
+ ./y.rs prepare
+ (cd download/sysroot && cargo update && cargo fetch && cp Cargo.lock ../../build_sysroot/)
;;
"commit")
git add rust-toolchain build_sysroot/Cargo.lock
diff --git a/compiler/rustc_codegen_cranelift/scripts/setup_rust_fork.sh b/compiler/rustc_codegen_cranelift/scripts/setup_rust_fork.sh
index 6c64b7de7..a08e80dd1 100644
--- a/compiler/rustc_codegen_cranelift/scripts/setup_rust_fork.sh
+++ b/compiler/rustc_codegen_cranelift/scripts/setup_rust_fork.sh
@@ -10,7 +10,7 @@ git fetch
git checkout -- .
git checkout "$(rustc -V | cut -d' ' -f3 | tr -d '(')"
-git am ../patches/*-sysroot-*.patch
+git -c user.name=Dummy -c user.email=dummy@example.com am ../patches/*-sysroot-*.patch
git apply - <<EOF
diff --git a/library/alloc/Cargo.toml b/library/alloc/Cargo.toml
@@ -25,8 +25,8 @@ index d95b5b7f17f..00b6f0e3635 100644
+compiler_builtins = { version = "0.1.66", features = ['rustc-dep-of-std', 'no-asm'] }
[dev-dependencies]
- rand = "0.7"
- rand_xorshift = "0.2"
+ rand = { version = "0.8.5", default-features = false, features = ["alloc"] }
+ rand_xorshift = "0.3.0"
EOF
cat > config.toml <<EOF
@@ -51,7 +51,7 @@ popd
# FIXME remove once inline asm is fully supported
export RUSTFLAGS="$RUSTFLAGS --cfg=rustix_use_libc"
-export CFG_VIRTUAL_RUST_SOURCE_BASE_DIR="$(cd build_sysroot/sysroot_src; pwd)"
+export CFG_VIRTUAL_RUST_SOURCE_BASE_DIR="$(cd download/sysroot/sysroot_src; pwd)"
# Allow the testsuite to use llvm tools
host_triple=$(rustc -vV | grep host | cut -d: -f2 | tr -d " ")
diff --git a/compiler/rustc_codegen_cranelift/scripts/test_rustc_tests.sh b/compiler/rustc_codegen_cranelift/scripts/test_rustc_tests.sh
index 12ecb8cf4..e14a129db 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
command -v rg >/dev/null 2>&1 || cargo install ripgrep
rm -r tests/ui/{extern/,unsized-locals/,lto/,linkage*} || true
-for test in $(rg --files-with-matches "lto|// needs-asm-support|// needs-unwind" tests/{ui,incremental}); do
+for test in $(rg --files-with-matches "lto|// needs-asm-support|// needs-unwind" tests/{codegen-units,ui,incremental}); do
rm $test
done
@@ -32,20 +32,13 @@ rm tests/incremental/issue-80691-bad-eval-cache.rs # -Cpanic=abort causes abort
# requires compiling with -Cpanic=unwind
rm -r tests/ui/macros/rfc-2011-nicer-assert-messages/
rm -r tests/run-make/test-benches
+rm tests/ui/test-attrs/test-type.rs
# vendor intrinsics
rm tests/ui/sse2.rs # cpuid not supported, so sse2 not detected
rm tests/ui/intrinsics/const-eval-select-x86_64.rs # requires x86_64 vendor intrinsics
rm tests/ui/simd/array-type.rs # "Index argument for `simd_insert` is not a constant"
-rm tests/ui/simd/intrinsic/generic-bitmask-pass.rs # simd_bitmask unimplemented
-rm tests/ui/simd/intrinsic/generic-as.rs # simd_as unimplemented
-rm tests/ui/simd/intrinsic/generic-arithmetic-saturating-pass.rs # simd_saturating_add unimplemented
rm tests/ui/simd/intrinsic/float-math-pass.rs # simd_fcos unimplemented
-rm tests/ui/simd/intrinsic/generic-gather-pass.rs # simd_gather unimplemented
-rm tests/ui/simd/intrinsic/generic-select-pass.rs # simd_select_bitmask unimplemented
-rm tests/ui/simd/issue-85915-simd-ptrs.rs # simd_gather unimplemented
-rm tests/ui/simd/issue-89193.rs # simd_gather unimplemented
-rm tests/ui/simd/simd-bitmask.rs # simd_bitmask unimplemented
# exotic linkages
rm tests/ui/issues/issue-33992.rs # unsupported linkages
@@ -64,10 +57,7 @@ rm tests/ui/intrinsics/intrinsic-nearby.rs # unimplemented nearbyintf32 and near
rm tests/ui/target-feature/missing-plusminus.rs # error not implemented
rm tests/ui/fn/dyn-fn-alignment.rs # wants a 256 byte alignment
rm -r tests/run-make/emit-named-files # requires full --emit support
-rm tests/ui/abi/stack-probes.rs # stack probes not yet implemented
-rm tests/ui/simd/intrinsic/ptr-cast.rs # simd_expose_addr intrinsic unimplemented
rm -r tests/run-make/repr128-dwarf # debuginfo test
-rm tests/codegen-units/item-collection/asm-sym.rs # requires support for sym in asm!()
# optimization tests
# ==================
@@ -88,6 +78,21 @@ rm tests/ui/mir/mir_raw_fat_ptr.rs # same
rm tests/ui/consts/issue-33537.rs # same
rm tests/ui/layout/valid_range_oob.rs # different ICE message
+rm tests/ui/consts/issue-miri-1910.rs # different error message
+rm tests/ui/consts/offset_ub.rs # same
+rm tests/ui/intrinsics/panic-uninitialized-zeroed.rs # same
+rm tests/ui/lint/lint-const-item-mutation.rs # same
+rm tests/ui/pattern/usefulness/doc-hidden-non-exhaustive.rs # same
+rm tests/ui/suggestions/derive-trait-for-method-call.rs # same
+rm tests/ui/typeck/issue-46112.rs # same
+
+rm tests/ui/proc-macro/crt-static.rs # extra warning about -Cpanic=abort for proc macros
+rm tests/ui/proc-macro/proc-macro-deprecated-attr.rs # same
+rm tests/ui/proc-macro/quote-debug.rs # same
+rm tests/ui/proc-macro/no-missing-docs.rs # same
+rm tests/ui/rust-2018/proc-macro-crate-in-paths.rs # same
+rm tests/ui/proc-macro/allowed-signatures.rs # same
+
# doesn't work due to the way the rustc test suite is invoked.
# should work when using ./x.py test the way it is intended
# ============================================================
@@ -102,23 +107,20 @@ rm -r tests/ui/consts/missing_span_in_backtrace.rs # expects sysroot source to b
# ============
rm tests/incremental/spike-neg1.rs # errors out for some reason
rm tests/incremental/spike-neg2.rs # same
-rm tests/ui/issues/issue-74564-if-expr-stack-overflow.rs # gives a stackoverflow before the backend runs
-rm tests/ui/mir/ssa-analysis-regression-50041.rs # produces ICE
-rm tests/ui/type-alias-impl-trait/assoc-projection-ice.rs # produces ICE
rm tests/ui/simd/intrinsic/generic-reduction-pass.rs # simd_reduce_add_unordered doesn't accept an accumulator for integer vectors
-rm tests/ui/runtime/out-of-stack.rs # SIGSEGV instead of SIGABRT for some reason (#1301)
+rm tests/ui/simd/intrinsic/generic-as.rs # crash when accessing vector type filed (#1318)
+rm tests/ui/simd/simd-bitmask.rs # crash
+
+rm tests/ui/dyn-star/dyn-star-to-dyn.rs
+rm tests/ui/dyn-star/dispatch-on-pin-mut.rs
# bugs in the test suite
# ======================
rm tests/ui/backtrace.rs # TODO warning
rm tests/ui/simple_global_asm.rs # TODO add needs-asm-support
-rm tests/ui/test-attrs/test-type.rs # TODO panic message on stderr. correct stdout
-# not sure if this is actually a bug in the test suite, but the symbol list shows the function without leading _ for some reason
-rm -r tests/run-make/native-link-modifier-bundle
rm tests/ui/process/nofile-limit.rs # TODO some AArch64 linking issue
-rm tests/ui/dyn-star/dispatch-on-pin-mut.rs # TODO failed assertion in vtable::get_ptr_and_method_ref
rm tests/ui/stdio-is-blocking.rs # really slow with unoptimized libstd
diff --git a/compiler/rustc_codegen_cranelift/src/abi/comments.rs b/compiler/rustc_codegen_cranelift/src/abi/comments.rs
index 7f4619b5c..abf63e33c 100644
--- a/compiler/rustc_codegen_cranelift/src/abi/comments.rs
+++ b/compiler/rustc_codegen_cranelift/src/abi/comments.rs
@@ -98,12 +98,12 @@ pub(super) fn add_local_place_comments<'tcx>(
}
CPlaceInner::VarPair(place_local, var1, var2) => {
assert_eq!(local, place_local);
- ("ssa", Cow::Owned(format!(",var=({}, {})", var1.index(), var2.index())))
+ ("ssa", Cow::Owned(format!("var=({}, {})", var1.index(), var2.index())))
}
CPlaceInner::VarLane(_local, _var, _lane) => unreachable!(),
CPlaceInner::Addr(ptr, meta) => {
let meta = if let Some(meta) = meta {
- Cow::Owned(format!(",meta={}", meta))
+ Cow::Owned(format!("meta={}", meta))
} else {
Cow::Borrowed("")
};
diff --git a/compiler/rustc_codegen_cranelift/src/abi/mod.rs b/compiler/rustc_codegen_cranelift/src/abi/mod.rs
index 65cc6b437..74396a66f 100644
--- a/compiler/rustc_codegen_cranelift/src/abi/mod.rs
+++ b/compiler/rustc_codegen_cranelift/src/abi/mod.rs
@@ -7,6 +7,7 @@ mod returning;
use cranelift_module::ModuleError;
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
use rustc_middle::ty::layout::FnAbiOf;
+use rustc_session::Session;
use rustc_target::abi::call::{Conv, FnAbi};
use rustc_target::spec::abi::Abi;
@@ -22,7 +23,7 @@ fn clif_sig_from_fn_abi<'tcx>(
default_call_conv: CallConv,
fn_abi: &FnAbi<'tcx, Ty<'tcx>>,
) -> Signature {
- let call_conv = conv_to_call_conv(fn_abi.conv, default_call_conv);
+ let call_conv = conv_to_call_conv(tcx.sess, fn_abi.conv, default_call_conv);
let inputs = fn_abi.args.iter().map(|arg_abi| arg_abi.get_abi_param(tcx).into_iter()).flatten();
@@ -33,24 +34,32 @@ fn clif_sig_from_fn_abi<'tcx>(
Signature { params, returns, call_conv }
}
-pub(crate) fn conv_to_call_conv(c: Conv, default_call_conv: CallConv) -> CallConv {
+pub(crate) fn conv_to_call_conv(sess: &Session, c: Conv, default_call_conv: CallConv) -> CallConv {
match c {
Conv::Rust | Conv::C => default_call_conv,
Conv::RustCold => CallConv::Cold,
Conv::X86_64SysV => CallConv::SystemV,
Conv::X86_64Win64 => CallConv::WindowsFastcall,
- Conv::ArmAapcs
- | Conv::CCmseNonSecureCall
- | Conv::Msp430Intr
+
+ // Should already get a back compat warning
+ Conv::X86Fastcall | Conv::X86Stdcall | Conv::X86ThisCall | Conv::X86VectorCall => {
+ default_call_conv
+ }
+
+ Conv::X86Intr => sess.fatal("x86-interrupt call conv not yet implemented"),
+
+ Conv::ArmAapcs => sess.fatal("aapcs call conv not yet implemented"),
+ Conv::CCmseNonSecureCall => {
+ sess.fatal("C-cmse-nonsecure-call call conv is not yet implemented");
+ }
+
+ Conv::Msp430Intr
| Conv::PtxKernel
- | Conv::X86Fastcall
- | Conv::X86Intr
- | Conv::X86Stdcall
- | Conv::X86ThisCall
- | Conv::X86VectorCall
| Conv::AmdGpuKernel
| Conv::AvrInterrupt
- | Conv::AvrNonBlockingInterrupt => todo!("{:?}", c),
+ | Conv::AvrNonBlockingInterrupt => {
+ unreachable!("tried to use {c:?} call conv which only exists on an unsupported target");
+ }
}
}
@@ -161,6 +170,12 @@ fn make_local_place<'tcx>(
layout: TyAndLayout<'tcx>,
is_ssa: bool,
) -> CPlace<'tcx> {
+ if layout.is_unsized() {
+ fx.tcx.sess.span_fatal(
+ fx.mir.local_decls[local].source_info.span,
+ "unsized locals are not yet supported",
+ );
+ }
let place = if is_ssa {
if let rustc_target::abi::Abi::ScalarPair(_, _) = layout.abi {
CPlace::new_var_pair(fx, local, layout)
@@ -390,9 +405,9 @@ pub(crate) fn codegen_terminator_call<'tcx>(
};
let extra_args = &args[fn_sig.inputs().skip_binder().len()..];
- let extra_args = fx
- .tcx
- .mk_type_list(extra_args.iter().map(|op_arg| fx.monomorphize(op_arg.ty(fx.mir, fx.tcx))));
+ let extra_args = fx.tcx.mk_type_list_from_iter(
+ extra_args.iter().map(|op_arg| fx.monomorphize(op_arg.ty(fx.mir, fx.tcx))),
+ );
let fn_abi = if let Some(instance) = instance {
RevealAllLayoutCx(fx.tcx).fn_abi_of_instance(instance, extra_args)
} else {
diff --git a/compiler/rustc_codegen_cranelift/src/allocator.rs b/compiler/rustc_codegen_cranelift/src/allocator.rs
index 850822717..1c73957ca 100644
--- a/compiler/rustc_codegen_cranelift/src/allocator.rs
+++ b/compiler/rustc_codegen_cranelift/src/allocator.rs
@@ -70,37 +70,13 @@ fn codegen_inner(
params: arg_tys.iter().cloned().map(AbiParam::new).collect(),
returns: output.into_iter().map(AbiParam::new).collect(),
};
-
- let caller_name = format!("__rust_{}", method.name);
- let callee_name = kind.fn_name(method.name);
-
- let func_id = module.declare_function(&caller_name, Linkage::Export, &sig).unwrap();
-
- let callee_func_id = module.declare_function(&callee_name, Linkage::Import, &sig).unwrap();
-
- let mut ctx = Context::new();
- ctx.func.signature = sig.clone();
- {
- let mut func_ctx = FunctionBuilderContext::new();
- let mut bcx = FunctionBuilder::new(&mut ctx.func, &mut func_ctx);
-
- let block = bcx.create_block();
- bcx.switch_to_block(block);
- let args = arg_tys
- .into_iter()
- .map(|ty| bcx.append_block_param(block, ty))
- .collect::<Vec<Value>>();
-
- let callee_func_ref = module.declare_func_in_func(callee_func_id, &mut bcx.func);
- let call_inst = bcx.ins().call(callee_func_ref, &args);
- let results = bcx.inst_results(call_inst).to_vec(); // Clone to prevent borrow error
-
- bcx.ins().return_(&results);
- bcx.seal_all_blocks();
- bcx.finalize();
- }
- module.define_function(func_id, &mut ctx).unwrap();
- unwind_context.add_function(func_id, &ctx, module.isa());
+ crate::common::create_wrapper_function(
+ module,
+ unwind_context,
+ sig,
+ &format!("__rust_{}", method.name),
+ &kind.fn_name(method.name),
+ );
}
let sig = Signature {
@@ -108,36 +84,13 @@ fn codegen_inner(
params: vec![AbiParam::new(usize_ty), AbiParam::new(usize_ty)],
returns: vec![],
};
-
- let callee_name = alloc_error_handler_kind.fn_name(sym::oom);
-
- let func_id =
- module.declare_function("__rust_alloc_error_handler", Linkage::Export, &sig).unwrap();
-
- let callee_func_id = module.declare_function(&callee_name, Linkage::Import, &sig).unwrap();
-
- let mut ctx = Context::new();
- ctx.func.signature = sig;
- {
- let mut func_ctx = FunctionBuilderContext::new();
- let mut bcx = FunctionBuilder::new(&mut ctx.func, &mut func_ctx);
-
- let block = bcx.create_block();
- bcx.switch_to_block(block);
- let args = (&[usize_ty, usize_ty])
- .iter()
- .map(|&ty| bcx.append_block_param(block, ty))
- .collect::<Vec<Value>>();
-
- let callee_func_ref = module.declare_func_in_func(callee_func_id, &mut bcx.func);
- bcx.ins().call(callee_func_ref, &args);
-
- bcx.ins().trap(TrapCode::UnreachableCodeReached);
- bcx.seal_all_blocks();
- bcx.finalize();
- }
- module.define_function(func_id, &mut ctx).unwrap();
- unwind_context.add_function(func_id, &ctx, module.isa());
+ crate::common::create_wrapper_function(
+ module,
+ unwind_context,
+ sig,
+ "__rust_alloc_error_handler",
+ &alloc_error_handler_kind.fn_name(sym::oom),
+ );
let data_id = module.declare_data(OomStrategy::SYMBOL, Linkage::Export, false, false).unwrap();
let mut data_ctx = DataContext::new();
diff --git a/compiler/rustc_codegen_cranelift/src/base.rs b/compiler/rustc_codegen_cranelift/src/base.rs
index 89d955e8b..7f857528c 100644
--- a/compiler/rustc_codegen_cranelift/src/base.rs
+++ b/compiler/rustc_codegen_cranelift/src/base.rs
@@ -21,23 +21,6 @@ pub(crate) struct CodegenedFunction {
func_debug_cx: Option<FunctionDebugContext>,
}
-#[cfg_attr(not(feature = "jit"), allow(dead_code))]
-pub(crate) fn codegen_and_compile_fn<'tcx>(
- tcx: TyCtxt<'tcx>,
- cx: &mut crate::CodegenCx,
- cached_context: &mut Context,
- module: &mut dyn Module,
- instance: Instance<'tcx>,
-) {
- let _inst_guard =
- crate::PrintOnPanic(|| format!("{:?} {}", instance, tcx.symbol_name(instance).name));
-
- let cached_func = std::mem::replace(&mut cached_context.func, Function::new());
- let codegened_func = codegen_fn(tcx, cx, cached_func, module, instance);
-
- compile_fn(cx, cached_context, module, codegened_func);
-}
-
pub(crate) fn codegen_fn<'tcx>(
tcx: TyCtxt<'tcx>,
cx: &mut crate::CodegenCx,
@@ -47,6 +30,9 @@ pub(crate) fn codegen_fn<'tcx>(
) -> CodegenedFunction {
debug_assert!(!instance.substs.needs_infer());
+ let symbol_name = tcx.symbol_name(instance).name.to_string();
+ let _timer = tcx.prof.generic_activity_with_arg("codegen fn", &*symbol_name);
+
let mir = tcx.instance_mir(instance.def);
let _mir_guard = crate::PrintOnPanic(|| {
let mut buf = Vec::new();
@@ -58,7 +44,6 @@ pub(crate) fn codegen_fn<'tcx>(
});
// Declare function
- let symbol_name = tcx.symbol_name(instance).name.to_string();
let sig = get_function_sig(tcx, module.target_config().default_call_conv, instance);
let func_id = module.declare_function(&symbol_name, Linkage::Local, &sig).unwrap();
@@ -112,7 +97,9 @@ pub(crate) fn codegen_fn<'tcx>(
next_ssa_var: 0,
};
- tcx.sess.time("codegen clif ir", || codegen_fn_body(&mut fx, start_block));
+ tcx.prof.generic_activity("codegen clif ir").run(|| codegen_fn_body(&mut fx, start_block));
+ fx.bcx.seal_all_blocks();
+ fx.bcx.finalize();
// Recover all necessary data from fx, before accessing func will prevent future access to it.
let symbol_name = fx.symbol_name;
@@ -144,6 +131,9 @@ pub(crate) fn compile_fn(
module: &mut dyn Module,
codegened_func: CodegenedFunction,
) {
+ let _timer =
+ cx.profiler.generic_activity_with_arg("compile function", &*codegened_func.symbol_name);
+
let clif_comments = codegened_func.clif_comments;
// Store function in context
@@ -189,9 +179,30 @@ pub(crate) fn compile_fn(
};
// Define function
- cx.profiler.verbose_generic_activity("define function").run(|| {
+ cx.profiler.generic_activity("define function").run(|| {
context.want_disasm = cx.should_write_ir;
module.define_function(codegened_func.func_id, context).unwrap();
+
+ if cx.profiler.enabled() {
+ let mut recording_args = false;
+ cx.profiler
+ .generic_activity_with_arg_recorder(
+ "define function (clif pass timings)",
+ |recorder| {
+ let pass_times = cranelift_codegen::timing::take_current();
+ // Replace newlines with | as measureme doesn't allow control characters like
+ // newlines inside strings.
+ recorder.record_arg(format!("{}", pass_times).replace("\n", " | "));
+ recording_args = true;
+ },
+ )
+ .run(|| {
+ if recording_args {
+ // Wait a tiny bit to ensure chrome's profiler doesn't hide the event
+ std::thread::sleep(std::time::Duration::from_nanos(2))
+ }
+ });
+ }
});
if cx.should_write_ir {
@@ -218,7 +229,7 @@ pub(crate) fn compile_fn(
let isa = module.isa();
let debug_context = &mut cx.debug_context;
let unwind_context = &mut cx.unwind_context;
- cx.profiler.verbose_generic_activity("generate debug info").run(|| {
+ cx.profiler.generic_activity("generate debug info").run(|| {
if let Some(debug_context) = debug_context {
codegened_func.func_debug_cx.unwrap().finalize(
debug_context,
@@ -235,7 +246,7 @@ pub(crate) fn verify_func(
writer: &crate::pretty_clif::CommentWriter,
func: &Function,
) {
- tcx.sess.time("verify clif ir", || {
+ tcx.prof.generic_activity("verify clif ir").run(|| {
let flags = cranelift_codegen::settings::Flags::new(cranelift_codegen::settings::builder());
match cranelift_codegen::verify_function(&func, &flags) {
Ok(_) => {}
@@ -271,7 +282,10 @@ fn codegen_fn_body(fx: &mut FunctionCx<'_, '_, '_>, start_block: Block) {
fx.bcx.ins().trap(TrapCode::UnreachableCodeReached);
return;
}
- fx.tcx.sess.time("codegen prelude", || crate::abi::codegen_fn_prelude(fx, start_block));
+ fx.tcx
+ .prof
+ .generic_activity("codegen prelude")
+ .run(|| crate::abi::codegen_fn_prelude(fx, start_block));
for (bb, bb_data) in fx.mir.basic_blocks.iter_enumerated() {
let block = fx.get_block(bb);
@@ -303,6 +317,9 @@ fn codegen_fn_body(fx: &mut FunctionCx<'_, '_, '_>, start_block: Block) {
let source_info = bb_data.terminator().source_info;
fx.set_debug_loc(source_info);
+ let _print_guard =
+ crate::PrintOnPanic(|| format!("terminator {:?}", bb_data.terminator().kind));
+
match &bb_data.terminator().kind {
TerminatorKind::Goto { target } => {
if let TerminatorKind::Return = fx.mir[*target].terminator().kind {
@@ -330,7 +347,12 @@ fn codegen_fn_body(fx: &mut FunctionCx<'_, '_, '_>, start_block: Block) {
}
TerminatorKind::Assert { cond, expected, msg, target, cleanup: _ } => {
if !fx.tcx.sess.overflow_checks() {
- if let mir::AssertKind::OverflowNeg(_) = *msg {
+ let overflow_not_to_check = match msg {
+ AssertKind::OverflowNeg(..) => true,
+ AssertKind::Overflow(op, ..) => op.is_checkable(),
+ _ => false,
+ };
+ if overflow_not_to_check {
let target = fx.get_block(*target);
fx.bcx.ins().jump(target, &[]);
continue;
@@ -429,7 +451,7 @@ fn codegen_fn_body(fx: &mut FunctionCx<'_, '_, '_>, start_block: Block) {
cleanup: _,
from_hir_call: _,
} => {
- fx.tcx.sess.time("codegen call", || {
+ fx.tcx.prof.generic_activity("codegen call").run(|| {
crate::abi::codegen_terminator_call(
fx,
mir::SourceInfo { span: *fn_span, ..source_info },
@@ -464,7 +486,10 @@ fn codegen_fn_body(fx: &mut FunctionCx<'_, '_, '_>, start_block: Block) {
*destination,
);
}
- TerminatorKind::Resume | TerminatorKind::Abort => {
+ TerminatorKind::Abort => {
+ codegen_panic_cannot_unwind(fx, source_info);
+ }
+ TerminatorKind::Resume => {
// FIXME implement unwinding
fx.bcx.ins().trap(TrapCode::UnreachableCodeReached);
}
@@ -487,9 +512,6 @@ fn codegen_fn_body(fx: &mut FunctionCx<'_, '_, '_>, start_block: Block) {
}
};
}
-
- fx.bcx.seal_all_blocks();
- fx.bcx.finalize();
}
fn codegen_stmt<'tcx>(
@@ -550,15 +572,7 @@ fn codegen_stmt<'tcx>(
let lhs = codegen_operand(fx, &lhs_rhs.0);
let rhs = codegen_operand(fx, &lhs_rhs.1);
- let res = if !fx.tcx.sess.overflow_checks() {
- let val =
- crate::num::codegen_int_binop(fx, bin_op, lhs, rhs).load_scalar(fx);
- let is_overflow = fx.bcx.ins().iconst(types::I8, 0);
- CValue::by_val_pair(val, is_overflow, lval.layout())
- } else {
- crate::num::codegen_checked_int_binop(fx, bin_op, lhs, rhs)
- };
-
+ let res = crate::num::codegen_checked_int_binop(fx, bin_op, lhs, rhs);
lval.write_cvalue(fx, res);
}
Rvalue::UnaryOp(un_op, ref operand) => {
@@ -773,22 +787,36 @@ fn codegen_stmt<'tcx>(
let val = 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() {
- AggregateKind::Array(_ty) => {
- for (i, operand) in operands.iter().enumerate() {
- let operand = codegen_operand(fx, operand);
- let index = fx.bcx.ins().iconst(fx.pointer_type, i as i64);
- let to = lval.place_index(fx, index);
- to.write_cvalue(fx, operand);
+ Rvalue::Aggregate(ref kind, ref operands) => {
+ let (variant_index, variant_dest, active_field_index) = match **kind {
+ mir::AggregateKind::Adt(_, variant_index, _, _, active_field_index) => {
+ let variant_dest = lval.downcast_variant(fx, variant_index);
+ (variant_index, variant_dest, active_field_index)
}
+ _ => (VariantIdx::from_u32(0), lval, None),
+ };
+ if active_field_index.is_some() {
+ assert_eq!(operands.len(), 1);
}
- _ => unreachable!("shouldn't exist at codegen {:?}", to_place_and_rval.1),
- },
+ for (i, operand) in operands.iter().enumerate() {
+ let operand = codegen_operand(fx, operand);
+ let field_index = active_field_index.unwrap_or(i);
+ let to = if let mir::AggregateKind::Array(_) = **kind {
+ let index = fx.bcx.ins().iconst(fx.pointer_type, field_index as i64);
+ variant_dest.place_index(fx, index)
+ } else {
+ variant_dest.place_field(fx, mir::Field::new(field_index))
+ };
+ to.write_cvalue(fx, operand);
+ }
+ crate::discriminant::codegen_set_discriminant(fx, lval, variant_index);
+ }
}
}
StatementKind::StorageLive(_)
| StatementKind::StorageDead(_)
| StatementKind::Deinit(_)
+ | StatementKind::ConstEvalCounter
| StatementKind::Nop
| StatementKind::FakeRead(..)
| StatementKind::Retag { .. }
@@ -826,7 +854,7 @@ fn codegen_stmt<'tcx>(
fn codegen_array_len<'tcx>(fx: &mut FunctionCx<'_, '_, 'tcx>, place: CPlace<'tcx>) -> Value {
match *place.layout().ty.kind() {
ty::Array(_elem_ty, len) => {
- let len = fx.monomorphize(len).eval_usize(fx.tcx, ParamEnv::reveal_all()) as i64;
+ let len = fx.monomorphize(len).eval_target_usize(fx.tcx, ParamEnv::reveal_all()) as i64;
fx.bcx.ins().iconst(fx.pointer_type, len)
}
ty::Slice(_elem_ty) => {
@@ -932,7 +960,28 @@ pub(crate) fn codegen_panic<'tcx>(
codegen_panic_inner(fx, rustc_hir::LangItem::Panic, &args, source_info.span);
}
-pub(crate) fn codegen_panic_inner<'tcx>(
+pub(crate) fn codegen_panic_nounwind<'tcx>(
+ fx: &mut FunctionCx<'_, '_, 'tcx>,
+ msg_str: &str,
+ source_info: mir::SourceInfo,
+) {
+ let msg_ptr = fx.anonymous_str(msg_str);
+ let msg_len = fx.bcx.ins().iconst(fx.pointer_type, i64::try_from(msg_str.len()).unwrap());
+ let args = [msg_ptr, msg_len];
+
+ codegen_panic_inner(fx, rustc_hir::LangItem::PanicNounwind, &args, source_info.span);
+}
+
+pub(crate) fn codegen_panic_cannot_unwind<'tcx>(
+ fx: &mut FunctionCx<'_, '_, 'tcx>,
+ source_info: mir::SourceInfo,
+) {
+ let args = [];
+
+ codegen_panic_inner(fx, rustc_hir::LangItem::PanicCannotUnwind, &args, source_info.span);
+}
+
+fn codegen_panic_inner<'tcx>(
fx: &mut FunctionCx<'_, '_, 'tcx>,
lang_item: rustc_hir::LangItem,
args: &[Value],
@@ -949,11 +998,7 @@ pub(crate) fn codegen_panic_inner<'tcx>(
fx.lib_call(
&*symbol_name,
- vec![
- AbiParam::new(fx.pointer_type),
- AbiParam::new(fx.pointer_type),
- AbiParam::new(fx.pointer_type),
- ],
+ args.iter().map(|&arg| AbiParam::new(fx.bcx.func.dfg.value_type(arg))).collect(),
vec![],
args,
);
diff --git a/compiler/rustc_codegen_cranelift/src/codegen_i128.rs b/compiler/rustc_codegen_cranelift/src/codegen_i128.rs
index 638b2d573..40bfe7077 100644
--- a/compiler/rustc_codegen_cranelift/src/codegen_i128.rs
+++ b/compiler/rustc_codegen_cranelift/src/codegen_i128.rs
@@ -56,7 +56,7 @@ pub(crate) fn maybe_codegen<'tcx>(
Some(fx.easy_call("__multi3", &[lhs, rhs], val_ty))
}
} else {
- let out_ty = fx.tcx.mk_tup([lhs.layout().ty, fx.tcx.types.bool].iter());
+ let out_ty = fx.tcx.mk_tup(&[lhs.layout().ty, fx.tcx.types.bool]);
let oflow = CPlace::new_stack_slot(fx, fx.layout_of(fx.tcx.types.i32));
let lhs = lhs.load_scalar(fx);
let rhs = rhs.load_scalar(fx);
@@ -78,7 +78,7 @@ pub(crate) fn maybe_codegen<'tcx>(
}
BinOp::Add | BinOp::Sub | BinOp::Mul => {
assert!(checked);
- let out_ty = fx.tcx.mk_tup([lhs.layout().ty, fx.tcx.types.bool].iter());
+ let out_ty = fx.tcx.mk_tup(&[lhs.layout().ty, fx.tcx.types.bool]);
let out_place = CPlace::new_stack_slot(fx, fx.layout_of(out_ty));
let (param_types, args) = if fx.tcx.sess.target.is_like_windows {
let (lhs_ptr, lhs_extra) = lhs.force_stack(fx);
diff --git a/compiler/rustc_codegen_cranelift/src/common.rs b/compiler/rustc_codegen_cranelift/src/common.rs
index 2dcd42fbd..722e2754e 100644
--- a/compiler/rustc_codegen_cranelift/src/common.rs
+++ b/compiler/rustc_codegen_cranelift/src/common.rs
@@ -35,7 +35,8 @@ pub(crate) fn scalar_to_clif_type(tcx: TyCtxt<'_>, scalar: Scalar) -> Type {
},
Primitive::F32 => types::F32,
Primitive::F64 => types::F64,
- Primitive::Pointer => pointer_ty(tcx),
+ // FIXME(erikdesjardins): handle non-default addrspace ptr sizes
+ Primitive::Pointer(_) => pointer_ty(tcx),
}
}
@@ -167,6 +168,15 @@ pub(crate) fn codegen_icmp_imm(
}
}
+pub(crate) fn codegen_bitcast(fx: &mut FunctionCx<'_, '_, '_>, dst_ty: Type, val: Value) -> Value {
+ let mut flags = MemFlags::new();
+ flags.set_endianness(match fx.tcx.data_layout.endian {
+ rustc_target::abi::Endian::Big => cranelift_codegen::ir::Endianness::Big,
+ rustc_target::abi::Endian::Little => cranelift_codegen::ir::Endianness::Little,
+ });
+ fx.bcx.ins().bitcast(dst_ty, flags, val)
+}
+
pub(crate) fn type_zero_value(bcx: &mut FunctionBuilder<'_>, ty: Type) -> Value {
if ty == types::I128 {
let zero = bcx.ins().iconst(types::I64, 0);
@@ -244,6 +254,44 @@ pub(crate) fn type_sign(ty: Ty<'_>) -> bool {
}
}
+pub(crate) fn create_wrapper_function(
+ module: &mut dyn Module,
+ unwind_context: &mut UnwindContext,
+ sig: Signature,
+ wrapper_name: &str,
+ callee_name: &str,
+) {
+ let wrapper_func_id = module.declare_function(wrapper_name, Linkage::Export, &sig).unwrap();
+ let callee_func_id = module.declare_function(callee_name, Linkage::Import, &sig).unwrap();
+
+ let mut ctx = Context::new();
+ ctx.func.signature = sig;
+ {
+ let mut func_ctx = FunctionBuilderContext::new();
+ let mut bcx = FunctionBuilder::new(&mut ctx.func, &mut func_ctx);
+
+ let block = bcx.create_block();
+ bcx.switch_to_block(block);
+ let func = &mut bcx.func.stencil;
+ let args = func
+ .signature
+ .params
+ .iter()
+ .map(|param| func.dfg.append_block_param(block, param.value_type))
+ .collect::<Vec<Value>>();
+
+ let callee_func_ref = module.declare_func_in_func(callee_func_id, &mut bcx.func);
+ let call_inst = bcx.ins().call(callee_func_ref, &args);
+ let results = bcx.inst_results(call_inst).to_vec(); // Clone to prevent borrow error
+
+ bcx.ins().return_(&results);
+ bcx.seal_all_blocks();
+ bcx.finalize();
+ }
+ module.define_function(wrapper_func_id, &mut ctx).unwrap();
+ unwind_context.add_function(wrapper_func_id, &ctx, module.isa());
+}
+
pub(crate) struct FunctionCx<'m, 'clif, 'tcx: 'm> {
pub(crate) cx: &'clif mut crate::CodegenCx,
pub(crate) module: &'m mut dyn Module,
@@ -326,7 +374,7 @@ impl<'tcx> HasTargetSpec for FunctionCx<'_, '_, 'tcx> {
impl<'tcx> FunctionCx<'_, '_, 'tcx> {
pub(crate) fn monomorphize<T>(&self, value: T) -> T
where
- T: TypeFoldable<'tcx> + Copy,
+ T: TypeFoldable<TyCtxt<'tcx>> + Copy,
{
self.instance.subst_mir_and_normalize_erasing_regions(
self.tcx,
diff --git a/compiler/rustc_codegen_cranelift/src/compiler_builtins.rs b/compiler/rustc_codegen_cranelift/src/compiler_builtins.rs
index c6a247cf5..8a53baa76 100644
--- a/compiler/rustc_codegen_cranelift/src/compiler_builtins.rs
+++ b/compiler/rustc_codegen_cranelift/src/compiler_builtins.rs
@@ -1,14 +1,33 @@
+#[cfg(all(unix, feature = "jit"))]
+use std::ffi::c_int;
+#[cfg(feature = "jit")]
+use std::ffi::c_void;
+
+// FIXME replace with core::ffi::c_size_t once stablized
+#[allow(non_camel_case_types)]
+#[cfg(feature = "jit")]
+type size_t = usize;
+
macro_rules! builtin_functions {
- ($register:ident; $(fn $name:ident($($arg_name:ident: $arg_ty:ty),*) -> $ret_ty:ty;)*) => {
+ (
+ $register:ident;
+ $(
+ $(#[$attr:meta])?
+ fn $name:ident($($arg_name:ident: $arg_ty:ty),*) -> $ret_ty:ty;
+ )*
+ ) => {
#[cfg(feature = "jit")]
#[allow(improper_ctypes)]
extern "C" {
- $(fn $name($($arg_name: $arg_ty),*) -> $ret_ty;)*
+ $(
+ $(#[$attr])?
+ fn $name($($arg_name: $arg_ty),*) -> $ret_ty;
+ )*
}
#[cfg(feature = "jit")]
pub(crate) fn $register(builder: &mut cranelift_jit::JITBuilder) {
- for (name, val) in [$((stringify!($name), $name as *const u8)),*] {
+ for (name, val) in [$($(#[$attr])? (stringify!($name), $name as *const u8)),*] {
builder.symbol(name, val);
}
}
@@ -40,4 +59,17 @@ builtin_functions! {
fn __fixdfti(f: f64) -> i128;
fn __fixunssfti(f: f32) -> u128;
fn __fixunsdfti(f: f64) -> u128;
+
+ // allocator
+ // NOTE: These need to be mentioned here despite not being part of compiler_builtins because
+ // newer glibc resolve dlsym("malloc") to libc.so despite the override in the rustc binary to
+ // use jemalloc. Libraries opened with dlopen still get the jemalloc version, causing multiple
+ // allocators to be mixed, resulting in a crash.
+ fn calloc(nobj: size_t, size: size_t) -> *mut c_void;
+ #[cfg(unix)]
+ fn posix_memalign(memptr: *mut *mut c_void, align: size_t, size: size_t) -> c_int;
+ fn malloc(size: size_t) -> *mut c_void;
+ fn realloc(p: *mut c_void, size: size_t) -> *mut c_void;
+ fn free(p: *mut c_void) -> ();
+
}
diff --git a/compiler/rustc_codegen_cranelift/src/config.rs b/compiler/rustc_codegen_cranelift/src/config.rs
index 45522fb1a..263401e1c 100644
--- a/compiler/rustc_codegen_cranelift/src/config.rs
+++ b/compiler/rustc_codegen_cranelift/src/config.rs
@@ -42,12 +42,6 @@ pub struct BackendConfig {
/// Defaults to the value of `CG_CLIF_JIT_ARGS`.
pub jit_args: Vec<String>,
- /// Display the time it took to perform codegen for a crate.
- ///
- /// Defaults to true when the `CG_CLIF_DISPLAY_CG_TIME` env var is set to 1 or false otherwise.
- /// Can be set using `-Cllvm-args=display_cg_time=...`.
- pub display_cg_time: bool,
-
/// Enable the Cranelift ir verifier for all compilation passes. If not set it will only run
/// once before passing the clif ir to Cranelift for compilation.
///
@@ -73,7 +67,6 @@ impl Default for BackendConfig {
let args = std::env::var("CG_CLIF_JIT_ARGS").unwrap_or_else(|_| String::new());
args.split(' ').map(|arg| arg.to_string()).collect()
},
- display_cg_time: bool_env_var("CG_CLIF_DISPLAY_CG_TIME"),
enable_verifier: cfg!(debug_assertions) || bool_env_var("CG_CLIF_ENABLE_VERIFIER"),
disable_incr_cache: bool_env_var("CG_CLIF_DISABLE_INCR_CACHE"),
}
@@ -92,7 +85,6 @@ impl BackendConfig {
if let Some((name, value)) = opt.split_once('=') {
match name {
"mode" => config.codegen_mode = value.parse()?,
- "display_cg_time" => config.display_cg_time = parse_bool(name, value)?,
"enable_verifier" => config.enable_verifier = parse_bool(name, value)?,
"disable_incr_cache" => config.disable_incr_cache = parse_bool(name, value)?,
_ => return Err(format!("Unknown option `{}`", name)),
diff --git a/compiler/rustc_codegen_cranelift/src/constant.rs b/compiler/rustc_codegen_cranelift/src/constant.rs
index 51450897b..49c4f1aaa 100644
--- a/compiler/rustc_codegen_cranelift/src/constant.rs
+++ b/compiler/rustc_codegen_cranelift/src/constant.rs
@@ -530,6 +530,7 @@ pub(crate) fn mir_operand_get_const_val<'tcx>(
| StatementKind::Retag(_, _)
| StatementKind::AscribeUserType(_, _)
| StatementKind::Coverage(_)
+ | StatementKind::ConstEvalCounter
| StatementKind::Nop => {}
}
}
diff --git a/compiler/rustc_codegen_cranelift/src/cranelift_native.rs b/compiler/rustc_codegen_cranelift/src/cranelift_native.rs
new file mode 100644
index 000000000..6c4efca44
--- /dev/null
+++ b/compiler/rustc_codegen_cranelift/src/cranelift_native.rs
@@ -0,0 +1,248 @@
+// Vendored from https://github.com/bytecodealliance/wasmtime/blob/b58a197d33f044193c3d608010f5e6ec394ac07e/cranelift/native/src/lib.rs
+// which is licensed as
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+// unlike rustc_codegen_cranelift itself. Also applies a small change to remove #![cfg_attr] that
+// rust's CI complains about and to fix formatting to match rustc.
+// FIXME revert back to the external crate with Cranelift 0.93
+#![allow(warnings)]
+
+//! Performs autodetection of the host for the purposes of running
+//! Cranelift to generate code to run on the same machine.
+
+#![deny(missing_docs, trivial_numeric_casts, unused_extern_crates, unstable_features)]
+#![warn(unused_import_braces)]
+
+use cranelift_codegen::isa;
+use target_lexicon::Triple;
+
+/// Return an `isa` builder configured for the current host
+/// machine, or `Err(())` if the host machine is not supported
+/// in the current configuration.
+pub fn builder() -> Result<isa::Builder, &'static str> {
+ builder_with_options(true)
+}
+
+/// Return an `isa` builder configured for the current host
+/// machine, or `Err(())` if the host machine is not supported
+/// in the current configuration.
+///
+/// Selects the given backend variant specifically; this is
+/// useful when more than oen backend exists for a given target
+/// (e.g., on x86-64).
+pub fn builder_with_options(infer_native_flags: bool) -> Result<isa::Builder, &'static str> {
+ let mut isa_builder = isa::lookup(Triple::host()).map_err(|err| match err {
+ isa::LookupError::SupportDisabled => "support for architecture disabled at compile time",
+ isa::LookupError::Unsupported => "unsupported architecture",
+ })?;
+
+ #[cfg(target_arch = "x86_64")]
+ {
+ use cranelift_codegen::settings::Configurable;
+
+ if !std::is_x86_feature_detected!("sse2") {
+ return Err("x86 support requires SSE2");
+ }
+
+ if !infer_native_flags {
+ return Ok(isa_builder);
+ }
+
+ // These are temporarily enabled by default (see #3810 for
+ // more) so that a default-constructed `Flags` can work with
+ // default Wasmtime features. Otherwise, the user must
+ // explicitly use native flags or turn these on when on x86-64
+ // platforms to avoid a configuration panic. In order for the
+ // "enable if detected" logic below to work, we must turn them
+ // *off* (differing from the default) and then re-enable below
+ // if present.
+ isa_builder.set("has_sse3", "false").unwrap();
+ isa_builder.set("has_ssse3", "false").unwrap();
+ isa_builder.set("has_sse41", "false").unwrap();
+ isa_builder.set("has_sse42", "false").unwrap();
+
+ if std::is_x86_feature_detected!("sse3") {
+ isa_builder.enable("has_sse3").unwrap();
+ }
+ if std::is_x86_feature_detected!("ssse3") {
+ isa_builder.enable("has_ssse3").unwrap();
+ }
+ if std::is_x86_feature_detected!("sse4.1") {
+ isa_builder.enable("has_sse41").unwrap();
+ }
+ if std::is_x86_feature_detected!("sse4.2") {
+ isa_builder.enable("has_sse42").unwrap();
+ }
+ if std::is_x86_feature_detected!("popcnt") {
+ isa_builder.enable("has_popcnt").unwrap();
+ }
+ if std::is_x86_feature_detected!("avx") {
+ isa_builder.enable("has_avx").unwrap();
+ }
+ if std::is_x86_feature_detected!("avx2") {
+ isa_builder.enable("has_avx2").unwrap();
+ }
+ if std::is_x86_feature_detected!("fma") {
+ isa_builder.enable("has_fma").unwrap();
+ }
+ if std::is_x86_feature_detected!("bmi1") {
+ isa_builder.enable("has_bmi1").unwrap();
+ }
+ if std::is_x86_feature_detected!("bmi2") {
+ isa_builder.enable("has_bmi2").unwrap();
+ }
+ if std::is_x86_feature_detected!("avx512bitalg") {
+ isa_builder.enable("has_avx512bitalg").unwrap();
+ }
+ if std::is_x86_feature_detected!("avx512dq") {
+ isa_builder.enable("has_avx512dq").unwrap();
+ }
+ if std::is_x86_feature_detected!("avx512f") {
+ isa_builder.enable("has_avx512f").unwrap();
+ }
+ if std::is_x86_feature_detected!("avx512vl") {
+ isa_builder.enable("has_avx512vl").unwrap();
+ }
+ if std::is_x86_feature_detected!("avx512vbmi") {
+ isa_builder.enable("has_avx512vbmi").unwrap();
+ }
+ if std::is_x86_feature_detected!("lzcnt") {
+ isa_builder.enable("has_lzcnt").unwrap();
+ }
+ }
+
+ #[cfg(target_arch = "aarch64")]
+ {
+ use cranelift_codegen::settings::Configurable;
+
+ if !infer_native_flags {
+ return Ok(isa_builder);
+ }
+
+ if std::arch::is_aarch64_feature_detected!("lse") {
+ isa_builder.enable("has_lse").unwrap();
+ }
+
+ if std::arch::is_aarch64_feature_detected!("paca") {
+ isa_builder.enable("has_pauth").unwrap();
+ }
+
+ if cfg!(target_os = "macos") {
+ // Pointer authentication is always available on Apple Silicon.
+ isa_builder.enable("sign_return_address").unwrap();
+ // macOS enforces the use of the B key for return addresses.
+ isa_builder.enable("sign_return_address_with_bkey").unwrap();
+ }
+ }
+
+ // There is no is_s390x_feature_detected macro yet, so for now
+ // we use getauxval from the libc crate directly.
+ #[cfg(all(target_arch = "s390x", target_os = "linux"))]
+ {
+ use cranelift_codegen::settings::Configurable;
+
+ if !infer_native_flags {
+ return Ok(isa_builder);
+ }
+
+ let v = unsafe { libc::getauxval(libc::AT_HWCAP) };
+ const HWCAP_S390X_VXRS_EXT2: libc::c_ulong = 32768;
+ if (v & HWCAP_S390X_VXRS_EXT2) != 0 {
+ isa_builder.enable("has_vxrs_ext2").unwrap();
+ // There is no separate HWCAP bit for mie2, so assume
+ // that any machine with vxrs_ext2 also has mie2.
+ isa_builder.enable("has_mie2").unwrap();
+ }
+ }
+
+ // `is_riscv_feature_detected` is nightly only for now, use
+ // getauxval from the libc crate directly as a temporary measure.
+ #[cfg(all(target_arch = "riscv64", target_os = "linux"))]
+ {
+ use cranelift_codegen::settings::Configurable;
+
+ if !infer_native_flags {
+ return Ok(isa_builder);
+ }
+
+ let v = unsafe { libc::getauxval(libc::AT_HWCAP) };
+
+ const HWCAP_RISCV_EXT_A: libc::c_ulong = 1 << (b'a' - b'a');
+ const HWCAP_RISCV_EXT_C: libc::c_ulong = 1 << (b'c' - b'a');
+ const HWCAP_RISCV_EXT_D: libc::c_ulong = 1 << (b'd' - b'a');
+ const HWCAP_RISCV_EXT_F: libc::c_ulong = 1 << (b'f' - b'a');
+ const HWCAP_RISCV_EXT_M: libc::c_ulong = 1 << (b'm' - b'a');
+ const HWCAP_RISCV_EXT_V: libc::c_ulong = 1 << (b'v' - b'a');
+
+ if (v & HWCAP_RISCV_EXT_A) != 0 {
+ isa_builder.enable("has_a").unwrap();
+ }
+
+ if (v & HWCAP_RISCV_EXT_C) != 0 {
+ isa_builder.enable("has_c").unwrap();
+ }
+
+ if (v & HWCAP_RISCV_EXT_D) != 0 {
+ isa_builder.enable("has_d").unwrap();
+ }
+
+ if (v & HWCAP_RISCV_EXT_F) != 0 {
+ isa_builder.enable("has_f").unwrap();
+
+ // TODO: There doesn't seem to be a bit associated with this extension
+ // rust enables it with the `f` extension:
+ // https://github.com/rust-lang/stdarch/blob/790411f93c4b5eada3c23abb4c9a063fb0b24d99/crates/std_detect/src/detect/os/linux/riscv.rs#L43
+ isa_builder.enable("has_zicsr").unwrap();
+ }
+
+ if (v & HWCAP_RISCV_EXT_M) != 0 {
+ isa_builder.enable("has_m").unwrap();
+ }
+
+ if (v & HWCAP_RISCV_EXT_V) != 0 {
+ isa_builder.enable("has_v").unwrap();
+ }
+
+ // TODO: ZiFencei does not have a bit associated with it
+ // TODO: Zbkb does not have a bit associated with it
+ }
+
+ // squelch warnings about unused mut/variables on some platforms.
+ drop(&mut isa_builder);
+ drop(infer_native_flags);
+
+ Ok(isa_builder)
+}
+
+#[cfg(test)]
+mod tests {
+ use super::builder;
+ use cranelift_codegen::isa::CallConv;
+ use cranelift_codegen::settings;
+
+ #[test]
+ fn test() {
+ if let Ok(isa_builder) = builder() {
+ let flag_builder = settings::builder();
+ let isa = isa_builder.finish(settings::Flags::new(flag_builder)).unwrap();
+
+ if cfg!(all(target_os = "macos", target_arch = "aarch64")) {
+ assert_eq!(isa.default_call_conv(), CallConv::AppleAarch64);
+ } else if cfg!(any(unix, target_os = "nebulet")) {
+ assert_eq!(isa.default_call_conv(), CallConv::SystemV);
+ } else if cfg!(windows) {
+ assert_eq!(isa.default_call_conv(), CallConv::WindowsFastcall);
+ }
+
+ if cfg!(target_pointer_width = "64") {
+ assert_eq!(isa.pointer_bits(), 64);
+ } else if cfg!(target_pointer_width = "32") {
+ assert_eq!(isa.pointer_bits(), 32);
+ } else if cfg!(target_pointer_width = "16") {
+ assert_eq!(isa.pointer_bits(), 16);
+ }
+ }
+ }
+}
+
+/// Version number of this crate.
+pub const VERSION: &str = env!("CARGO_PKG_VERSION");
diff --git a/compiler/rustc_codegen_cranelift/src/debuginfo/mod.rs b/compiler/rustc_codegen_cranelift/src/debuginfo/mod.rs
index 28fbcb15b..3a7421d8b 100644
--- a/compiler/rustc_codegen_cranelift/src/debuginfo/mod.rs
+++ b/compiler/rustc_codegen_cranelift/src/debuginfo/mod.rs
@@ -20,6 +20,14 @@ use indexmap::IndexSet;
pub(crate) use emit::{DebugReloc, DebugRelocName};
pub(crate) use unwind::UnwindContext;
+pub(crate) fn producer() -> String {
+ format!(
+ "cg_clif (rustc {}, cranelift {})",
+ rustc_interface::util::rustc_version_str().unwrap_or("unknown version"),
+ cranelift_codegen::VERSION,
+ )
+}
+
pub(crate) struct DebugContext {
endian: RunTimeEndian,
@@ -57,11 +65,7 @@ impl DebugContext {
let mut dwarf = DwarfUnit::new(encoding);
- let producer = format!(
- "cg_clif (rustc {}, cranelift {})",
- rustc_interface::util::rustc_version_str().unwrap_or("unknown version"),
- cranelift_codegen::VERSION,
- );
+ let producer = producer();
let comp_dir = tcx
.sess
.opts
diff --git a/compiler/rustc_codegen_cranelift/src/driver/aot.rs b/compiler/rustc_codegen_cranelift/src/driver/aot.rs
index f873561c1..7c6fd9f6f 100644
--- a/compiler/rustc_codegen_cranelift/src/driver/aot.rs
+++ b/compiler/rustc_codegen_cranelift/src/driver/aot.rs
@@ -108,6 +108,8 @@ impl OngoingCodegen {
self.concurrency_limiter.finished();
+ sess.abort_if_errors();
+
(
CodegenResults {
modules,
@@ -169,10 +171,22 @@ fn emit_cgu(
fn emit_module(
output_filenames: &OutputFilenames,
prof: &SelfProfilerRef,
- object: cranelift_object::object::write::Object<'_>,
+ mut object: cranelift_object::object::write::Object<'_>,
kind: ModuleKind,
name: String,
) -> Result<CompiledModule, String> {
+ if object.format() == cranelift_object::object::BinaryFormat::Elf {
+ let comment_section = object.add_section(
+ Vec::new(),
+ b".comment".to_vec(),
+ cranelift_object::object::SectionKind::OtherString,
+ );
+ let mut producer = vec![0];
+ producer.extend(crate::debuginfo::producer().as_bytes());
+ producer.push(0);
+ object.set_section_data(comment_section, producer, 1);
+ }
+
let tmp_file = output_filenames.temp_path(OutputType::Object, Some(&name));
let mut file = match File::create(&tmp_file) {
Ok(file) => file,
@@ -234,17 +248,13 @@ fn reuse_workproduct_for_cgu(
dwarf_object: None,
bytecode: None,
},
- module_global_asm: if has_global_asm {
- Some(CompiledModule {
- name: cgu.name().to_string(),
- kind: ModuleKind::Regular,
- object: Some(obj_out_global_asm),
- dwarf_object: None,
- bytecode: None,
- })
- } else {
- None
- },
+ module_global_asm: has_global_asm.then(|| CompiledModule {
+ name: cgu.name().to_string(),
+ kind: ModuleKind::Regular,
+ object: Some(obj_out_global_asm),
+ dwarf_object: None,
+ bytecode: None,
+ }),
existing_work_product: Some((cgu.work_product_id(), work_product)),
})
}
@@ -258,25 +268,25 @@ fn module_codegen(
ConcurrencyLimiterToken,
),
) -> OngoingModuleCodegen {
- let (cgu_name, mut cx, mut module, codegened_functions) = tcx.sess.time("codegen cgu", || {
- let cgu = tcx.codegen_unit(cgu_name);
- let mono_items = cgu.items_in_deterministic_order(tcx);
-
- let mut module = make_module(tcx.sess, &backend_config, cgu_name.as_str().to_string());
-
- let mut cx = crate::CodegenCx::new(
- tcx,
- backend_config.clone(),
- module.isa(),
- tcx.sess.opts.debuginfo != DebugInfo::None,
- cgu_name,
- );
- super::predefine_mono_items(tcx, &mut module, &mono_items);
- let mut codegened_functions = vec![];
- for (mono_item, _) in mono_items {
- match mono_item {
- MonoItem::Fn(inst) => {
- tcx.sess.time("codegen fn", || {
+ let (cgu_name, mut cx, mut module, codegened_functions) =
+ tcx.prof.verbose_generic_activity_with_arg("codegen cgu", cgu_name.as_str()).run(|| {
+ let cgu = tcx.codegen_unit(cgu_name);
+ let mono_items = cgu.items_in_deterministic_order(tcx);
+
+ let mut module = make_module(tcx.sess, &backend_config, cgu_name.as_str().to_string());
+
+ let mut cx = crate::CodegenCx::new(
+ tcx,
+ backend_config.clone(),
+ module.isa(),
+ tcx.sess.opts.debuginfo != DebugInfo::None,
+ cgu_name,
+ );
+ super::predefine_mono_items(tcx, &mut module, &mono_items);
+ let mut codegened_functions = vec![];
+ for (mono_item, _) in mono_items {
+ match mono_item {
+ MonoItem::Fn(inst) => {
let codegened_function = crate::base::codegen_fn(
tcx,
&mut cx,
@@ -285,53 +295,68 @@ fn module_codegen(
inst,
);
codegened_functions.push(codegened_function);
- });
- }
- MonoItem::Static(def_id) => {
- crate::constant::codegen_static(tcx, &mut module, def_id)
- }
- MonoItem::GlobalAsm(item_id) => {
- crate::global_asm::codegen_global_asm_item(tcx, &mut cx.global_asm, item_id);
+ }
+ MonoItem::Static(def_id) => {
+ crate::constant::codegen_static(tcx, &mut module, def_id)
+ }
+ MonoItem::GlobalAsm(item_id) => {
+ crate::global_asm::codegen_global_asm_item(
+ tcx,
+ &mut cx.global_asm,
+ item_id,
+ );
+ }
}
}
- }
- crate::main_shim::maybe_create_entry_wrapper(
- tcx,
- &mut module,
- &mut cx.unwind_context,
- false,
- cgu.is_primary(),
- );
+ crate::main_shim::maybe_create_entry_wrapper(
+ tcx,
+ &mut module,
+ &mut cx.unwind_context,
+ false,
+ cgu.is_primary(),
+ );
- let cgu_name = cgu.name().as_str().to_owned();
+ let cgu_name = cgu.name().as_str().to_owned();
- (cgu_name, cx, module, codegened_functions)
- });
+ (cgu_name, cx, module, codegened_functions)
+ });
OngoingModuleCodegen::Async(std::thread::spawn(move || {
- cx.profiler.clone().verbose_generic_activity("compile functions").run(|| {
- let mut cached_context = Context::new();
- for codegened_func in codegened_functions {
- crate::base::compile_fn(&mut cx, &mut cached_context, &mut module, codegened_func);
- }
- });
+ cx.profiler.clone().verbose_generic_activity_with_arg("compile functions", &*cgu_name).run(
+ || {
+ let mut cached_context = Context::new();
+ for codegened_func in codegened_functions {
+ crate::base::compile_fn(
+ &mut cx,
+ &mut cached_context,
+ &mut module,
+ codegened_func,
+ );
+ }
+ },
+ );
- let global_asm_object_file =
- cx.profiler.verbose_generic_activity("compile assembly").run(|| {
+ let global_asm_object_file = cx
+ .profiler
+ .verbose_generic_activity_with_arg("compile assembly", &*cgu_name)
+ .run(|| {
crate::global_asm::compile_global_asm(&global_asm_config, &cgu_name, &cx.global_asm)
})?;
- let codegen_result = cx.profiler.verbose_generic_activity("write object file").run(|| {
- emit_cgu(
- &global_asm_config.output_filenames,
- &cx.profiler,
- cgu_name,
- module,
- cx.debug_context,
- cx.unwind_context,
- global_asm_object_file,
- )
- });
+ let codegen_result = cx
+ .profiler
+ .verbose_generic_activity_with_arg("write object file", &*cgu_name)
+ .run(|| {
+ emit_cgu(
+ &global_asm_config.output_filenames,
+ &cx.profiler,
+ cgu_name,
+ module,
+ cx.debug_context,
+ cx.unwind_context,
+ global_asm_object_file,
+ )
+ });
std::mem::drop(token);
codegen_result
}))
@@ -361,7 +386,7 @@ pub(crate) fn run_aot(
let mut concurrency_limiter = ConcurrencyLimiter::new(tcx.sess, cgus.len());
- let modules = super::time(tcx, backend_config.display_cg_time, "codegen mono items", || {
+ let modules = tcx.sess.time("codegen mono items", || {
cgus.iter()
.map(|cgu| {
let cgu_reuse = if backend_config.disable_incr_cache {
@@ -399,8 +424,6 @@ pub(crate) fn run_aot(
.collect::<Vec<_>>()
});
- tcx.sess.abort_if_errors();
-
let mut allocator_module = make_module(tcx.sess, &backend_config, "allocator_shim".to_string());
let mut allocator_unwind_context = UnwindContext::new(allocator_module.isa(), true);
let created_alloc_shim =
@@ -425,7 +448,6 @@ pub(crate) fn run_aot(
};
let metadata_module = if need_metadata_module {
- let _timer = tcx.prof.generic_activity("codegen crate metadata");
let (metadata_cgu_name, tmp_file) = tcx.sess.time("write compressed metadata", || {
use rustc_middle::mir::mono::CodegenUnitNameBuilder;
diff --git a/compiler/rustc_codegen_cranelift/src/driver/jit.rs b/compiler/rustc_codegen_cranelift/src/driver/jit.rs
index be1b8c9ea..8b5a2da2c 100644
--- a/compiler/rustc_codegen_cranelift/src/driver/jit.rs
+++ b/compiler/rustc_codegen_cranelift/src/driver/jit.rs
@@ -121,22 +121,20 @@ pub(crate) fn run_jit(tcx: TyCtxt<'_>, backend_config: BackendConfig) -> ! {
.into_iter()
.collect::<Vec<(_, (_, _))>>();
- super::time(tcx, backend_config.display_cg_time, "codegen mono items", || {
+ tcx.sess.time("codegen mono items", || {
super::predefine_mono_items(tcx, &mut jit_module, &mono_items);
for (mono_item, _) in mono_items {
match mono_item {
MonoItem::Fn(inst) => match backend_config.codegen_mode {
CodegenMode::Aot => unreachable!(),
CodegenMode::Jit => {
- tcx.sess.time("codegen fn", || {
- crate::base::codegen_and_compile_fn(
- tcx,
- &mut cx,
- &mut cached_context,
- &mut jit_module,
- inst,
- )
- });
+ codegen_and_compile_fn(
+ tcx,
+ &mut cx,
+ &mut cached_context,
+ &mut jit_module,
+ inst,
+ );
}
CodegenMode::JitLazy => {
codegen_shim(tcx, &mut cx, &mut cached_context, &mut jit_module, inst)
@@ -219,6 +217,24 @@ pub(crate) fn run_jit(tcx: TyCtxt<'_>, backend_config: BackendConfig) -> ! {
}
}
+pub(crate) fn codegen_and_compile_fn<'tcx>(
+ tcx: TyCtxt<'tcx>,
+ cx: &mut crate::CodegenCx,
+ cached_context: &mut Context,
+ module: &mut dyn Module,
+ instance: Instance<'tcx>,
+) {
+ tcx.prof.generic_activity("codegen and compile fn").run(|| {
+ let _inst_guard =
+ crate::PrintOnPanic(|| format!("{:?} {}", instance, tcx.symbol_name(instance).name));
+
+ let cached_func = std::mem::replace(&mut cached_context.func, Function::new());
+ let codegened_func = crate::base::codegen_fn(tcx, cx, cached_func, module, instance);
+
+ crate::base::compile_fn(cx, cached_context, module, codegened_func);
+ });
+}
+
extern "C" fn clif_jit_fn(
instance_ptr: *const Instance<'static>,
trampoline_ptr: *const u8,
@@ -271,15 +287,7 @@ fn jit_fn(instance_ptr: *const Instance<'static>, trampoline_ptr: *const u8) ->
false,
Symbol::intern("dummy_cgu_name"),
);
- tcx.sess.time("codegen fn", || {
- crate::base::codegen_and_compile_fn(
- tcx,
- &mut cx,
- &mut Context::new(),
- jit_module,
- instance,
- )
- });
+ codegen_and_compile_fn(tcx, &mut cx, &mut Context::new(), jit_module, instance);
assert!(cx.global_asm.is_empty());
jit_module.finalize_definitions().unwrap();
diff --git a/compiler/rustc_codegen_cranelift/src/driver/mod.rs b/compiler/rustc_codegen_cranelift/src/driver/mod.rs
index 6e925cea2..d09d3a529 100644
--- a/compiler/rustc_codegen_cranelift/src/driver/mod.rs
+++ b/compiler/rustc_codegen_cranelift/src/driver/mod.rs
@@ -17,7 +17,7 @@ fn predefine_mono_items<'tcx>(
module: &mut dyn Module,
mono_items: &[(MonoItem<'tcx>, (RLinkage, Visibility))],
) {
- tcx.sess.time("predefine functions", || {
+ tcx.prof.generic_activity("predefine functions").run(|| {
let is_compiler_builtins = tcx.is_compiler_builtins(LOCAL_CRATE);
for &(mono_item, (linkage, visibility)) in mono_items {
match mono_item {
@@ -39,16 +39,3 @@ fn predefine_mono_items<'tcx>(
}
});
}
-
-fn time<R>(tcx: TyCtxt<'_>, display: bool, name: &'static str, f: impl FnOnce() -> R) -> R {
- if display {
- println!("[{:<30}: {}] start", tcx.crate_name(LOCAL_CRATE), name);
- let before = std::time::Instant::now();
- let res = tcx.sess.time(name, f);
- let after = std::time::Instant::now();
- println!("[{:<30}: {}] end time: {:?}", tcx.crate_name(LOCAL_CRATE), name, after - before);
- res
- } else {
- tcx.sess.time(name, f)
- }
-}
diff --git a/compiler/rustc_codegen_cranelift/src/global_asm.rs b/compiler/rustc_codegen_cranelift/src/global_asm.rs
index dcbcaba30..46c78ce6a 100644
--- a/compiler/rustc_codegen_cranelift/src/global_asm.rs
+++ b/compiler/rustc_codegen_cranelift/src/global_asm.rs
@@ -7,7 +7,7 @@ use std::process::{Command, Stdio};
use std::sync::Arc;
use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece};
-use rustc_hir::ItemId;
+use rustc_hir::{InlineAsmOperand, ItemId};
use rustc_session::config::{OutputFilenames, OutputType};
use crate::prelude::*;
@@ -23,7 +23,46 @@ pub(crate) fn codegen_global_asm_item(tcx: TyCtxt<'_>, global_asm: &mut String,
for piece in asm.template {
match *piece {
InlineAsmTemplatePiece::String(ref s) => global_asm.push_str(s),
- InlineAsmTemplatePiece::Placeholder { .. } => todo!(),
+ InlineAsmTemplatePiece::Placeholder { operand_idx, modifier: _, span: op_sp } => {
+ match asm.operands[operand_idx].0 {
+ InlineAsmOperand::Const { ref anon_const } => {
+ let const_value =
+ tcx.const_eval_poly(anon_const.def_id.to_def_id()).unwrap_or_else(
+ |_| span_bug!(op_sp, "asm const cannot be resolved"),
+ );
+ let ty = tcx.typeck_body(anon_const.body).node_type(anon_const.hir_id);
+ let string = rustc_codegen_ssa::common::asm_const_to_str(
+ tcx,
+ op_sp,
+ const_value,
+ RevealAllLayoutCx(tcx).layout_of(ty),
+ );
+ global_asm.push_str(&string);
+ }
+ InlineAsmOperand::SymFn { anon_const } => {
+ let ty = tcx.typeck_body(anon_const.body).node_type(anon_const.hir_id);
+ let instance = match ty.kind() {
+ &ty::FnDef(def_id, substs) => Instance::new(def_id, substs),
+ _ => span_bug!(op_sp, "asm sym is not a function"),
+ };
+ let symbol = tcx.symbol_name(instance);
+ // FIXME handle the case where the function was made private to the
+ // current codegen unit
+ global_asm.push_str(symbol.name);
+ }
+ InlineAsmOperand::SymStatic { path: _, def_id } => {
+ let instance = Instance::mono(tcx, def_id).polymorphize(tcx);
+ let symbol = tcx.symbol_name(instance);
+ global_asm.push_str(symbol.name);
+ }
+ InlineAsmOperand::In { .. }
+ | InlineAsmOperand::Out { .. }
+ | InlineAsmOperand::InOut { .. }
+ | InlineAsmOperand::SplitInOut { .. } => {
+ span_bug!(op_sp, "invalid operand type for global_asm!")
+ }
+ }
+ }
}
}
global_asm.push_str("\n.att_syntax\n\n");
diff --git a/compiler/rustc_codegen_cranelift/src/inline_asm.rs b/compiler/rustc_codegen_cranelift/src/inline_asm.rs
index 3fcc84d39..6206fbf7d 100644
--- a/compiler/rustc_codegen_cranelift/src/inline_asm.rs
+++ b/compiler/rustc_codegen_cranelift/src/inline_asm.rs
@@ -9,9 +9,33 @@ use rustc_middle::mir::InlineAsmOperand;
use rustc_span::sym;
use rustc_target::asm::*;
+enum CInlineAsmOperand<'tcx> {
+ In {
+ reg: InlineAsmRegOrRegClass,
+ value: CValue<'tcx>,
+ },
+ Out {
+ reg: InlineAsmRegOrRegClass,
+ late: bool,
+ place: Option<CPlace<'tcx>>,
+ },
+ InOut {
+ reg: InlineAsmRegOrRegClass,
+ _late: bool,
+ in_value: CValue<'tcx>,
+ out_place: Option<CPlace<'tcx>>,
+ },
+ Const {
+ value: String,
+ },
+ Symbol {
+ symbol: String,
+ },
+}
+
pub(crate) fn codegen_inline_asm<'tcx>(
fx: &mut FunctionCx<'_, '_, 'tcx>,
- _span: Span,
+ span: Span,
template: &[InlineAsmTemplatePiece],
operands: &[InlineAsmOperand<'tcx>],
options: InlineAsmOptions,
@@ -198,6 +222,81 @@ pub(crate) fn codegen_inline_asm<'tcx>(
}
}
+ let operands = operands
+ .into_iter()
+ .map(|operand| match *operand {
+ InlineAsmOperand::In { reg, ref value } => {
+ CInlineAsmOperand::In { reg, value: crate::base::codegen_operand(fx, value) }
+ }
+ InlineAsmOperand::Out { reg, late, ref place } => CInlineAsmOperand::Out {
+ reg,
+ late,
+ place: place.map(|place| crate::base::codegen_place(fx, place)),
+ },
+ InlineAsmOperand::InOut { reg, late, ref in_value, ref out_place } => {
+ CInlineAsmOperand::InOut {
+ reg,
+ _late: late,
+ in_value: crate::base::codegen_operand(fx, in_value),
+ out_place: out_place.map(|place| crate::base::codegen_place(fx, place)),
+ }
+ }
+ InlineAsmOperand::Const { ref value } => {
+ let (const_value, ty) = crate::constant::eval_mir_constant(fx, &*value)
+ .unwrap_or_else(|| span_bug!(span, "asm const cannot be resolved"));
+ let value = rustc_codegen_ssa::common::asm_const_to_str(
+ fx.tcx,
+ span,
+ const_value,
+ fx.layout_of(ty),
+ );
+ CInlineAsmOperand::Const { value }
+ }
+ InlineAsmOperand::SymFn { ref value } => {
+ let literal = fx.monomorphize(value.literal);
+ if let ty::FnDef(def_id, substs) = *literal.ty().kind() {
+ let instance = ty::Instance::resolve_for_fn_ptr(
+ fx.tcx,
+ ty::ParamEnv::reveal_all(),
+ def_id,
+ substs,
+ )
+ .unwrap();
+ let symbol = fx.tcx.symbol_name(instance);
+
+ // Pass a wrapper rather than the function itself as the function itself may not
+ // be exported from the main codegen unit and may thus be unreachable from the
+ // object file created by an external assembler.
+ let inline_asm_index = fx.cx.inline_asm_index.get();
+ fx.cx.inline_asm_index.set(inline_asm_index + 1);
+ let wrapper_name = format!(
+ "__inline_asm_{}_wrapper_n{}",
+ fx.cx.cgu_name.as_str().replace('.', "__").replace('-', "_"),
+ inline_asm_index
+ );
+ let sig =
+ get_function_sig(fx.tcx, fx.target_config.default_call_conv, instance);
+ create_wrapper_function(
+ fx.module,
+ &mut fx.cx.unwind_context,
+ sig,
+ &wrapper_name,
+ symbol.name,
+ );
+
+ CInlineAsmOperand::Symbol { symbol: wrapper_name }
+ } else {
+ span_bug!(span, "invalid type for asm sym (fn)");
+ }
+ }
+ InlineAsmOperand::SymStatic { def_id } => {
+ assert!(fx.tcx.is_static(def_id));
+ let instance = Instance::mono(fx.tcx, def_id).polymorphize(fx.tcx);
+ CInlineAsmOperand::Symbol { symbol: fx.tcx.symbol_name(instance).name.to_owned() }
+ }
+ })
+ .collect::<Vec<_>>();
+
let mut inputs = Vec::new();
let mut outputs = Vec::new();
@@ -206,7 +305,7 @@ pub(crate) fn codegen_inline_asm<'tcx>(
arch: fx.tcx.sess.asm_arch.unwrap(),
enclosing_def_id: fx.instance.def_id(),
template,
- operands,
+ operands: &operands,
options,
registers: Vec::new(),
stack_slots_clobber: Vec::new(),
@@ -229,36 +328,22 @@ pub(crate) fn codegen_inline_asm<'tcx>(
fx.cx.global_asm.push_str(&generated_asm);
for (i, operand) in operands.iter().enumerate() {
- match *operand {
- InlineAsmOperand::In { reg: _, ref value } => {
- inputs.push((
- asm_gen.stack_slots_input[i].unwrap(),
- crate::base::codegen_operand(fx, value).load_scalar(fx),
- ));
- }
- InlineAsmOperand::Out { reg: _, late: _, place } => {
+ match operand {
+ CInlineAsmOperand::In { reg: _, value } => {
+ inputs.push((asm_gen.stack_slots_input[i].unwrap(), value.load_scalar(fx)));
+ }
+ CInlineAsmOperand::Out { reg: _, late: _, place } => {
if let Some(place) = place {
- outputs.push((
- asm_gen.stack_slots_output[i].unwrap(),
- crate::base::codegen_place(fx, place),
- ));
+ outputs.push((asm_gen.stack_slots_output[i].unwrap(), place.clone()));
}
}
- InlineAsmOperand::InOut { reg: _, late: _, ref in_value, out_place } => {
- inputs.push((
- asm_gen.stack_slots_input[i].unwrap(),
- crate::base::codegen_operand(fx, in_value).load_scalar(fx),
- ));
+ CInlineAsmOperand::InOut { reg: _, _late: _, in_value, out_place } => {
+ inputs.push((asm_gen.stack_slots_input[i].unwrap(), in_value.load_scalar(fx)));
if let Some(out_place) = out_place {
- outputs.push((
- asm_gen.stack_slots_output[i].unwrap(),
- crate::base::codegen_place(fx, out_place),
- ));
+ outputs.push((asm_gen.stack_slots_output[i].unwrap(), out_place.clone()));
}
}
- InlineAsmOperand::Const { value: _ } => todo!(),
- InlineAsmOperand::SymFn { value: _ } => todo!(),
- InlineAsmOperand::SymStatic { def_id: _ } => todo!(),
+ CInlineAsmOperand::Const { value: _ } | CInlineAsmOperand::Symbol { symbol: _ } => {}
}
}
@@ -280,7 +365,7 @@ struct InlineAssemblyGenerator<'a, 'tcx> {
arch: InlineAsmArch,
enclosing_def_id: DefId,
template: &'a [InlineAsmTemplatePiece],
- operands: &'a [InlineAsmOperand<'tcx>],
+ operands: &'a [CInlineAsmOperand<'tcx>],
options: InlineAsmOptions,
registers: Vec<Option<InlineAsmReg>>,
stack_slots_clobber: Vec<Option<Size>>,
@@ -304,18 +389,20 @@ impl<'tcx> InlineAssemblyGenerator<'_, 'tcx> {
// Add explicit registers to the allocated set.
for (i, operand) in self.operands.iter().enumerate() {
match *operand {
- InlineAsmOperand::In { reg: InlineAsmRegOrRegClass::Reg(reg), .. } => {
+ CInlineAsmOperand::In { reg: InlineAsmRegOrRegClass::Reg(reg), .. } => {
regs[i] = Some(reg);
allocated.entry(reg).or_default().0 = true;
}
- InlineAsmOperand::Out {
- reg: InlineAsmRegOrRegClass::Reg(reg), late: true, ..
+ CInlineAsmOperand::Out {
+ reg: InlineAsmRegOrRegClass::Reg(reg),
+ late: true,
+ ..
} => {
regs[i] = Some(reg);
allocated.entry(reg).or_default().1 = true;
}
- InlineAsmOperand::Out { reg: InlineAsmRegOrRegClass::Reg(reg), .. }
- | InlineAsmOperand::InOut { reg: InlineAsmRegOrRegClass::Reg(reg), .. } => {
+ CInlineAsmOperand::Out { reg: InlineAsmRegOrRegClass::Reg(reg), .. }
+ | CInlineAsmOperand::InOut { reg: InlineAsmRegOrRegClass::Reg(reg), .. } => {
regs[i] = Some(reg);
allocated.insert(reg, (true, true));
}
@@ -326,12 +413,12 @@ impl<'tcx> InlineAssemblyGenerator<'_, 'tcx> {
// Allocate out/inout/inlateout registers first because they are more constrained.
for (i, operand) in self.operands.iter().enumerate() {
match *operand {
- InlineAsmOperand::Out {
+ CInlineAsmOperand::Out {
reg: InlineAsmRegOrRegClass::RegClass(class),
late: false,
..
}
- | InlineAsmOperand::InOut {
+ | CInlineAsmOperand::InOut {
reg: InlineAsmRegOrRegClass::RegClass(class), ..
} => {
let mut alloc_reg = None;
@@ -360,7 +447,7 @@ impl<'tcx> InlineAssemblyGenerator<'_, 'tcx> {
// Allocate in/lateout.
for (i, operand) in self.operands.iter().enumerate() {
match *operand {
- InlineAsmOperand::In { reg: InlineAsmRegOrRegClass::RegClass(class), .. } => {
+ CInlineAsmOperand::In { reg: InlineAsmRegOrRegClass::RegClass(class), .. } => {
let mut alloc_reg = None;
for &reg in &map[&class] {
let mut used = false;
@@ -380,7 +467,7 @@ impl<'tcx> InlineAssemblyGenerator<'_, 'tcx> {
regs[i] = Some(reg);
allocated.entry(reg).or_default().0 = true;
}
- InlineAsmOperand::Out {
+ CInlineAsmOperand::Out {
reg: InlineAsmRegOrRegClass::RegClass(class),
late: true,
..
@@ -455,7 +542,7 @@ impl<'tcx> InlineAssemblyGenerator<'_, 'tcx> {
// Allocate stack slots for inout
for (i, operand) in self.operands.iter().enumerate() {
match *operand {
- InlineAsmOperand::InOut { reg, out_place: Some(_), .. } => {
+ CInlineAsmOperand::InOut { reg, out_place: Some(_), .. } => {
let slot = new_slot(reg.reg_class());
slots_input[i] = Some(slot);
slots_output[i] = Some(slot);
@@ -470,8 +557,8 @@ impl<'tcx> InlineAssemblyGenerator<'_, 'tcx> {
// Allocate stack slots for input
for (i, operand) in self.operands.iter().enumerate() {
match *operand {
- InlineAsmOperand::In { reg, .. }
- | InlineAsmOperand::InOut { reg, out_place: None, .. } => {
+ CInlineAsmOperand::In { reg, .. }
+ | CInlineAsmOperand::InOut { reg, out_place: None, .. } => {
slots_input[i] = Some(new_slot(reg.reg_class()));
}
_ => (),
@@ -487,7 +574,7 @@ impl<'tcx> InlineAssemblyGenerator<'_, 'tcx> {
// Allocate stack slots for output
for (i, operand) in self.operands.iter().enumerate() {
match *operand {
- InlineAsmOperand::Out { reg, place: Some(_), .. } => {
+ CInlineAsmOperand::Out { reg, place: Some(_), .. } => {
slots_output[i] = Some(new_slot(reg.reg_class()));
}
_ => (),
@@ -549,13 +636,23 @@ impl<'tcx> InlineAssemblyGenerator<'_, 'tcx> {
generated_asm.push_str(s);
}
InlineAsmTemplatePiece::Placeholder { operand_idx, modifier, span: _ } => {
- if self.options.contains(InlineAsmOptions::ATT_SYNTAX) {
- generated_asm.push('%');
+ match self.operands[*operand_idx] {
+ CInlineAsmOperand::In { .. }
+ | CInlineAsmOperand::Out { .. }
+ | CInlineAsmOperand::InOut { .. } => {
+ if self.options.contains(InlineAsmOptions::ATT_SYNTAX) {
+ generated_asm.push('%');
+ }
+ self.registers[*operand_idx]
+ .unwrap()
+ .emit(&mut generated_asm, self.arch, *modifier)
+ .unwrap();
+ }
+ CInlineAsmOperand::Const { ref value } => {
+ generated_asm.push_str(value);
+ }
+ CInlineAsmOperand::Symbol { ref symbol } => generated_asm.push_str(symbol),
}
- self.registers[*operand_idx]
- .unwrap()
- .emit(&mut generated_asm, self.arch, *modifier)
- .unwrap();
}
}
}
diff --git a/compiler/rustc_codegen_cranelift/src/intrinsics/llvm_x86.rs b/compiler/rustc_codegen_cranelift/src/intrinsics/llvm_x86.rs
index 7bc161fbe..e5c4b244a 100644
--- a/compiler/rustc_codegen_cranelift/src/intrinsics/llvm_x86.rs
+++ b/compiler/rustc_codegen_cranelift/src/intrinsics/llvm_x86.rs
@@ -33,8 +33,8 @@ pub(crate) fn codegen_x86_llvm_intrinsic_call<'tcx>(
// cast float to int
let a_lane = match lane_ty {
- types::F32 => fx.bcx.ins().bitcast(types::I32, a_lane),
- types::F64 => fx.bcx.ins().bitcast(types::I64, a_lane),
+ types::F32 => codegen_bitcast(fx, types::I32, a_lane),
+ types::F64 => codegen_bitcast(fx, types::I64, a_lane),
_ => a_lane,
};
@@ -191,7 +191,7 @@ fn llvm_add_sub<'tcx>(
// carry0 | carry1 -> carry or borrow respectively
let cb_out = fx.bcx.ins().bor(cb0, cb1);
- let layout = fx.layout_of(fx.tcx.mk_tup([fx.tcx.types.u8, fx.tcx.types.u64].iter()));
+ let layout = fx.layout_of(fx.tcx.mk_tup(&[fx.tcx.types.u8, fx.tcx.types.u64]));
let val = CValue::by_val_pair(cb_out, c, layout);
ret.write_cvalue(fx, val);
}
diff --git a/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs b/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs
index e4ac89a7b..e74aabf2f 100644
--- a/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs
+++ b/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs
@@ -21,6 +21,8 @@ mod simd;
pub(crate) use cpuid::codegen_cpuid_call;
pub(crate) use llvm::codegen_llvm_intrinsic_call;
+use rustc_middle::ty;
+use rustc_middle::ty::layout::{HasParamEnv, ValidityRequirement};
use rustc_middle::ty::print::with_no_trimmed_paths;
use rustc_middle::ty::subst::SubstsRef;
use rustc_span::symbol::{kw, sym, Symbol};
@@ -200,7 +202,7 @@ fn bool_to_zero_or_max_uint<'tcx>(
let mut res = fx.bcx.ins().bmask(int_ty, val);
if ty.is_float() {
- res = fx.bcx.ins().bitcast(ty, res);
+ res = codegen_bitcast(fx, ty, res);
}
res
@@ -217,22 +219,6 @@ pub(crate) fn codegen_intrinsic_call<'tcx>(
let intrinsic = fx.tcx.item_name(instance.def_id());
let substs = instance.substs;
- let target = if let Some(target) = target {
- target
- } else {
- // Insert non returning intrinsics here
- match intrinsic {
- sym::abort => {
- fx.bcx.ins().trap(TrapCode::User(0));
- }
- sym::transmute => {
- crate::base::codegen_panic(fx, "Transmuting to uninhabited type.", source_info);
- }
- _ => unimplemented!("unsupported intrinsic {}", intrinsic),
- }
- return;
- };
-
if intrinsic.as_str().starts_with("simd_") {
self::simd::codegen_simd_intrinsic_call(
fx,
@@ -240,12 +226,11 @@ pub(crate) fn codegen_intrinsic_call<'tcx>(
substs,
args,
destination,
+ target.expect("target for simd intrinsic"),
source_info.span,
);
- let ret_block = fx.get_block(target);
- fx.bcx.ins().jump(ret_block, &[]);
} else if codegen_float_intrinsic_call(fx, intrinsic, args, destination) {
- let ret_block = fx.get_block(target);
+ let ret_block = fx.get_block(target.expect("target for float intrinsic"));
fx.bcx.ins().jump(ret_block, &[]);
} else {
codegen_regular_intrinsic_call(
@@ -255,7 +240,7 @@ pub(crate) fn codegen_intrinsic_call<'tcx>(
substs,
args,
destination,
- Some(target),
+ target,
source_info,
);
}
@@ -382,6 +367,10 @@ fn codegen_regular_intrinsic_call<'tcx>(
let usize_layout = fx.layout_of(fx.tcx.types.usize);
match intrinsic {
+ sym::abort => {
+ fx.bcx.ins().trap(TrapCode::User(0));
+ return;
+ }
sym::likely | sym::unlikely => {
intrinsic_args!(fx, args => (a); intrinsic);
@@ -505,20 +494,6 @@ fn codegen_regular_intrinsic_call<'tcx>(
let res = crate::num::codegen_int_binop(fx, bin_op, x, y);
ret.write_cvalue(fx, res);
}
- sym::add_with_overflow | sym::sub_with_overflow | sym::mul_with_overflow => {
- intrinsic_args!(fx, args => (x, y); intrinsic);
-
- assert_eq!(x.layout().ty, y.layout().ty);
- let bin_op = match intrinsic {
- sym::add_with_overflow => BinOp::Add,
- sym::sub_with_overflow => BinOp::Sub,
- sym::mul_with_overflow => BinOp::Mul,
- _ => unreachable!(),
- };
-
- let res = crate::num::codegen_checked_int_binop(fx, bin_op, x, y);
- ret.write_cvalue(fx, res);
- }
sym::saturating_add | sym::saturating_sub => {
intrinsic_args!(fx, args => (lhs, rhs); intrinsic);
@@ -579,6 +554,11 @@ fn codegen_regular_intrinsic_call<'tcx>(
sym::transmute => {
intrinsic_args!(fx, args => (from); intrinsic);
+ if ret.layout().abi.is_uninhabited() {
+ crate::base::codegen_panic(fx, "Transmuting to uninhabited type.", source_info);
+ return;
+ }
+
ret.write_cvalue_transmute(fx, from);
}
sym::write_bytes | sym::volatile_set_memory => {
@@ -647,46 +627,40 @@ fn codegen_regular_intrinsic_call<'tcx>(
sym::assert_inhabited | sym::assert_zero_valid | sym::assert_mem_uninitialized_valid => {
intrinsic_args!(fx, args => (); intrinsic);
- let layout = fx.layout_of(substs.type_at(0));
- if layout.abi.is_uninhabited() {
- with_no_trimmed_paths!({
- crate::base::codegen_panic(
- fx,
- &format!("attempted to instantiate uninhabited type `{}`", layout.ty),
- source_info,
- )
- });
- return;
- }
-
- if intrinsic == sym::assert_zero_valid && !fx.tcx.permits_zero_init(layout) {
- with_no_trimmed_paths!({
- crate::base::codegen_panic(
- fx,
- &format!(
- "attempted to zero-initialize type `{}`, which is invalid",
- layout.ty
- ),
- source_info,
- );
- });
- return;
- }
+ let ty = substs.type_at(0);
- if intrinsic == sym::assert_mem_uninitialized_valid
- && !fx.tcx.permits_uninit_init(layout)
- {
- with_no_trimmed_paths!({
- crate::base::codegen_panic(
- fx,
- &format!(
- "attempted to leave type `{}` uninitialized, which is invalid",
- layout.ty
- ),
- source_info,
- )
- });
- return;
+ let requirement = ValidityRequirement::from_intrinsic(intrinsic);
+
+ if let Some(requirement) = requirement {
+ let do_panic = !fx
+ .tcx
+ .check_validity_requirement((requirement, fx.param_env().and(ty)))
+ .expect("expect to have layout during codegen");
+
+ if do_panic {
+ let layout = fx.layout_of(ty);
+
+ with_no_trimmed_paths!({
+ crate::base::codegen_panic_nounwind(
+ fx,
+ &if layout.abi.is_uninhabited() {
+ format!("attempted to instantiate uninhabited type `{}`", layout.ty)
+ } else if requirement == ValidityRequirement::Zero {
+ format!(
+ "attempted to zero-initialize type `{}`, which is invalid",
+ layout.ty
+ )
+ } else {
+ format!(
+ "attempted to leave type `{}` uninitialized, which is invalid",
+ layout.ty
+ )
+ },
+ source_info,
+ )
+ });
+ return;
+ }
}
}
diff --git a/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs b/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs
index 14f5e9187..a1d63acfb 100644
--- a/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs
+++ b/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs
@@ -24,6 +24,7 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>(
_substs: SubstsRef<'tcx>,
args: &[mir::Operand<'tcx>],
ret: CPlace<'tcx>,
+ target: BasicBlock,
span: Span,
) {
match intrinsic {
@@ -140,7 +141,7 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>(
let idx_ty = fx.monomorphize(idx.ty(fx.mir, fx.tcx));
match idx_ty.kind() {
ty::Array(ty, len) if matches!(ty.kind(), ty::Uint(ty::UintTy::U32)) => len
- .try_eval_usize(fx.tcx, ty::ParamEnv::reveal_all())
+ .try_eval_target_usize(fx.tcx, ty::ParamEnv::reveal_all())
.unwrap_or_else(|| {
span_bug!(span, "could not evaluate shuffle index array length")
})
@@ -277,16 +278,15 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>(
} else {
fx.tcx.sess.span_warn(span, "Index argument for `simd_extract` is not a constant");
let trap_block = fx.bcx.create_block();
- let dummy_block = fx.bcx.create_block();
let true_ = fx.bcx.ins().iconst(types::I8, 1);
fx.bcx.ins().brnz(true_, trap_block, &[]);
- fx.bcx.ins().jump(dummy_block, &[]);
+ let ret_block = fx.get_block(target);
+ fx.bcx.ins().jump(ret_block, &[]);
fx.bcx.switch_to_block(trap_block);
crate::trap::trap_unimplemented(
fx,
"Index argument for `simd_extract` is not a constant",
);
- fx.bcx.switch_to_block(dummy_block);
return;
};
@@ -735,7 +735,7 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>(
ty::Uint(i) if i.bit_width() == Some(expected_int_bits) => {}
ty::Array(elem, len)
if matches!(elem.kind(), ty::Uint(ty::UintTy::U8))
- && len.try_eval_usize(fx.tcx, ty::ParamEnv::reveal_all())
+ && len.try_eval_target_usize(fx.tcx, ty::ParamEnv::reveal_all())
== Some(expected_bytes) => {}
_ => {
fx.tcx.sess.span_fatal(
@@ -770,11 +770,119 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>(
});
}
- // simd_arith_offset
- // simd_scatter
- // simd_gather
+ sym::simd_expose_addr | sym::simd_from_exposed_addr | sym::simd_cast_ptr => {
+ intrinsic_args!(fx, args => (arg); intrinsic);
+ ret.write_cvalue_transmute(fx, arg);
+ }
+
+ sym::simd_arith_offset => {
+ intrinsic_args!(fx, args => (ptr, offset); intrinsic);
+
+ let (lane_count, ptr_lane_ty) = ptr.layout().ty.simd_size_and_type(fx.tcx);
+ let pointee_ty = ptr_lane_ty.builtin_deref(true).unwrap().ty;
+ let pointee_size = fx.layout_of(pointee_ty).size.bytes();
+ let (ret_lane_count, ret_lane_ty) = ret.layout().ty.simd_size_and_type(fx.tcx);
+ let ret_lane_layout = fx.layout_of(ret_lane_ty);
+ assert_eq!(lane_count, ret_lane_count);
+
+ for lane_idx in 0..lane_count {
+ let ptr_lane = ptr.value_lane(fx, lane_idx).load_scalar(fx);
+ let offset_lane = offset.value_lane(fx, lane_idx).load_scalar(fx);
+
+ let ptr_diff = if pointee_size != 1 {
+ fx.bcx.ins().imul_imm(offset_lane, pointee_size as i64)
+ } else {
+ offset_lane
+ };
+ let res_lane = fx.bcx.ins().iadd(ptr_lane, ptr_diff);
+ let res_lane = CValue::by_val(res_lane, ret_lane_layout);
+
+ ret.place_lane(fx, lane_idx).write_cvalue(fx, res_lane);
+ }
+ }
+
+ sym::simd_gather => {
+ intrinsic_args!(fx, args => (val, ptr, mask); intrinsic);
+
+ let (val_lane_count, val_lane_ty) = val.layout().ty.simd_size_and_type(fx.tcx);
+ let (ptr_lane_count, _ptr_lane_ty) = ptr.layout().ty.simd_size_and_type(fx.tcx);
+ let (mask_lane_count, _mask_lane_ty) = mask.layout().ty.simd_size_and_type(fx.tcx);
+ let (ret_lane_count, ret_lane_ty) = ret.layout().ty.simd_size_and_type(fx.tcx);
+ assert_eq!(val_lane_count, ptr_lane_count);
+ assert_eq!(val_lane_count, mask_lane_count);
+ assert_eq!(val_lane_count, ret_lane_count);
+
+ let lane_clif_ty = fx.clif_type(val_lane_ty).unwrap();
+ let ret_lane_layout = fx.layout_of(ret_lane_ty);
+
+ for lane_idx in 0..ptr_lane_count {
+ let val_lane = val.value_lane(fx, lane_idx).load_scalar(fx);
+ let ptr_lane = ptr.value_lane(fx, lane_idx).load_scalar(fx);
+ let mask_lane = mask.value_lane(fx, lane_idx).load_scalar(fx);
+
+ let if_enabled = fx.bcx.create_block();
+ let if_disabled = fx.bcx.create_block();
+ let next = fx.bcx.create_block();
+ let res_lane = fx.bcx.append_block_param(next, lane_clif_ty);
+
+ fx.bcx.ins().brnz(mask_lane, if_enabled, &[]);
+ fx.bcx.ins().jump(if_disabled, &[]);
+ fx.bcx.seal_block(if_enabled);
+ fx.bcx.seal_block(if_disabled);
+
+ fx.bcx.switch_to_block(if_enabled);
+ let res = fx.bcx.ins().load(lane_clif_ty, MemFlags::trusted(), ptr_lane, 0);
+ fx.bcx.ins().jump(next, &[res]);
+
+ fx.bcx.switch_to_block(if_disabled);
+ fx.bcx.ins().jump(next, &[val_lane]);
+
+ fx.bcx.seal_block(next);
+ fx.bcx.switch_to_block(next);
+
+ fx.bcx.ins().nop();
+
+ ret.place_lane(fx, lane_idx)
+ .write_cvalue(fx, CValue::by_val(res_lane, ret_lane_layout));
+ }
+ }
+
+ sym::simd_scatter => {
+ intrinsic_args!(fx, args => (val, ptr, mask); intrinsic);
+
+ let (val_lane_count, _val_lane_ty) = val.layout().ty.simd_size_and_type(fx.tcx);
+ let (ptr_lane_count, _ptr_lane_ty) = ptr.layout().ty.simd_size_and_type(fx.tcx);
+ let (mask_lane_count, _mask_lane_ty) = mask.layout().ty.simd_size_and_type(fx.tcx);
+ assert_eq!(val_lane_count, ptr_lane_count);
+ assert_eq!(val_lane_count, mask_lane_count);
+
+ for lane_idx in 0..ptr_lane_count {
+ let val_lane = val.value_lane(fx, lane_idx).load_scalar(fx);
+ let ptr_lane = ptr.value_lane(fx, lane_idx).load_scalar(fx);
+ let mask_lane = mask.value_lane(fx, lane_idx).load_scalar(fx);
+
+ let if_enabled = fx.bcx.create_block();
+ let next = fx.bcx.create_block();
+
+ fx.bcx.ins().brnz(mask_lane, if_enabled, &[]);
+ fx.bcx.ins().jump(next, &[]);
+ fx.bcx.seal_block(if_enabled);
+
+ fx.bcx.switch_to_block(if_enabled);
+ fx.bcx.ins().store(MemFlags::trusted(), val_lane, ptr_lane, 0);
+ fx.bcx.ins().jump(next, &[]);
+
+ fx.bcx.seal_block(next);
+ fx.bcx.switch_to_block(next);
+ }
+ }
+
_ => {
- fx.tcx.sess.span_fatal(span, &format!("Unknown SIMD intrinsic {}", intrinsic));
+ fx.tcx.sess.span_err(span, &format!("Unknown SIMD intrinsic {}", intrinsic));
+ // Prevent verifier error
+ fx.bcx.ins().trap(TrapCode::UnreachableCodeReached);
}
}
+ let ret_block = fx.get_block(target);
+ fx.bcx.ins().jump(ret_block, &[]);
}
diff --git a/compiler/rustc_codegen_cranelift/src/lib.rs b/compiler/rustc_codegen_cranelift/src/lib.rs
index 629d79d50..80ce3dc93 100644
--- a/compiler/rustc_codegen_cranelift/src/lib.rs
+++ b/compiler/rustc_codegen_cranelift/src/lib.rs
@@ -57,6 +57,8 @@ mod compiler_builtins;
mod concurrency_limiter;
mod config;
mod constant;
+// FIXME revert back to the external crate with Cranelift 0.93
+mod cranelift_native;
mod debuginfo;
mod discriminant;
mod driver;
@@ -84,7 +86,7 @@ mod prelude {
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, TypeVisitable, UintTy,
+ TypeFoldable, TypeVisitableExt, UintTy,
};
pub(crate) use rustc_target::abi::{Abi, Scalar, Size, VariantIdx};
@@ -170,6 +172,11 @@ pub struct CraneliftCodegenBackend {
}
impl CodegenBackend for CraneliftCodegenBackend {
+ fn locale_resource(&self) -> &'static str {
+ // FIXME(rust-lang/rust#100717) - cranelift codegen backend is not yet translated
+ ""
+ }
+
fn init(&self, sess: &Session) {
use rustc_session::config::Lto;
match sess.lto() {
@@ -278,12 +285,14 @@ fn build_isa(sess: &Session, backend_config: &BackendConfig) -> Box<dyn isa::Tar
}
}
- if target_triple.architecture == target_lexicon::Architecture::X86_64 {
+ if let target_lexicon::Architecture::Aarch64(_) | target_lexicon::Architecture::X86_64 =
+ target_triple.architecture
+ {
// Windows depends on stack probes to grow the committed part of the stack
flags_builder.enable("enable_probestack").unwrap();
flags_builder.set("probestack_strategy", "inline").unwrap();
} else {
- // __cranelift_probestack is not provided and inline stack probes are only supported on x86_64
+ // __cranelift_probestack is not provided and inline stack probes are only supported on AArch64 and x86_64
flags_builder.set("enable_probestack", "false").unwrap();
}
diff --git a/compiler/rustc_codegen_cranelift/src/main_shim.rs b/compiler/rustc_codegen_cranelift/src/main_shim.rs
index c10054e7f..be908df83 100644
--- a/compiler/rustc_codegen_cranelift/src/main_shim.rs
+++ b/compiler/rustc_codegen_cranelift/src/main_shim.rs
@@ -46,7 +46,7 @@ pub(crate) fn maybe_create_entry_wrapper(
is_main_fn: bool,
sigpipe: u8,
) {
- let main_ret_ty = tcx.fn_sig(rust_main_def_id).output();
+ let main_ret_ty = tcx.fn_sig(rust_main_def_id).no_bound_vars().unwrap().output();
// Given that `main()` has no arguments,
// then its return type cannot have
// late-bound regions, since late-bound
@@ -64,13 +64,20 @@ pub(crate) fn maybe_create_entry_wrapper(
],
returns: vec![AbiParam::new(m.target_config().pointer_type() /*isize*/)],
call_conv: crate::conv_to_call_conv(
+ tcx.sess,
tcx.sess.target.options.entry_abi,
m.target_config().default_call_conv,
),
};
let entry_name = tcx.sess.target.options.entry_name.as_ref();
- let cmain_func_id = m.declare_function(entry_name, Linkage::Export, &cmain_sig).unwrap();
+ let cmain_func_id = match m.declare_function(entry_name, Linkage::Export, &cmain_sig) {
+ Ok(func_id) => func_id,
+ Err(err) => {
+ tcx.sess
+ .fatal(&format!("entry symbol `{entry_name}` declared multiple times: {err}"));
+ }
+ };
let instance = Instance::mono(tcx, rust_main_def_id).polymorphize(tcx);
@@ -112,7 +119,7 @@ pub(crate) fn maybe_create_entry_wrapper(
tcx,
ParamEnv::reveal_all(),
report.def_id,
- tcx.mk_substs([GenericArg::from(main_ret_ty)].iter()),
+ tcx.mk_substs(&[GenericArg::from(main_ret_ty)]),
)
.unwrap()
.unwrap()
@@ -139,7 +146,7 @@ pub(crate) fn maybe_create_entry_wrapper(
tcx,
ParamEnv::reveal_all(),
start_def_id,
- tcx.intern_substs(&[main_ret_ty.into()]),
+ tcx.mk_substs(&[main_ret_ty.into()]),
)
.unwrap()
.unwrap()
@@ -162,7 +169,11 @@ pub(crate) fn maybe_create_entry_wrapper(
bcx.seal_all_blocks();
bcx.finalize();
}
- m.define_function(cmain_func_id, &mut ctx).unwrap();
+
+ if let Err(err) = m.define_function(cmain_func_id, &mut ctx) {
+ tcx.sess.fatal(&format!("entry symbol `{entry_name}` defined multiple times: {err}"));
+ }
+
unwind_context.add_function(cmain_func_id, &ctx, m.isa());
}
}
diff --git a/compiler/rustc_codegen_cranelift/src/num.rs b/compiler/rustc_codegen_cranelift/src/num.rs
index afacbec64..c058ece96 100644
--- a/compiler/rustc_codegen_cranelift/src/num.rs
+++ b/compiler/rustc_codegen_cranelift/src/num.rs
@@ -289,7 +289,7 @@ pub(crate) fn codegen_checked_int_binop<'tcx>(
_ => bug!("binop {:?} on checked int/uint lhs: {:?} rhs: {:?}", bin_op, in_lhs, in_rhs),
};
- let out_layout = fx.layout_of(fx.tcx.mk_tup([in_lhs.layout().ty, fx.tcx.types.bool].iter()));
+ let out_layout = fx.layout_of(fx.tcx.mk_tup(&[in_lhs.layout().ty, fx.tcx.types.bool]));
CValue::by_val_pair(res, has_overflow, out_layout)
}
diff --git a/compiler/rustc_codegen_cranelift/src/optimize/peephole.rs b/compiler/rustc_codegen_cranelift/src/optimize/peephole.rs
index 7f45bbd8f..26327dca2 100644
--- a/compiler/rustc_codegen_cranelift/src/optimize/peephole.rs
+++ b/compiler/rustc_codegen_cranelift/src/optimize/peephole.rs
@@ -7,7 +7,7 @@ use cranelift_frontend::FunctionBuilder;
/// otherwise return the given value and false.
pub(crate) fn maybe_unwrap_bool_not(bcx: &mut FunctionBuilder<'_>, arg: Value) -> (Value, bool) {
if let ValueDef::Result(arg_inst, 0) = bcx.func.dfg.value_def(arg) {
- match bcx.func.dfg[arg_inst] {
+ match bcx.func.dfg.insts[arg_inst] {
// This is the lowering of `Rvalue::Not`
InstructionData::IntCompareImm {
opcode: Opcode::IcmpImm,
@@ -34,7 +34,7 @@ pub(crate) fn maybe_known_branch_taken(
return None;
};
- match bcx.func.dfg[arg_inst] {
+ match bcx.func.dfg.insts[arg_inst] {
InstructionData::UnaryImm { opcode: Opcode::Iconst, imm } => {
if test_zero {
Some(imm.bits() == 0)
diff --git a/compiler/rustc_codegen_cranelift/src/unsize.rs b/compiler/rustc_codegen_cranelift/src/unsize.rs
index 9c88f7dbc..a0745582d 100644
--- a/compiler/rustc_codegen_cranelift/src/unsize.rs
+++ b/compiler/rustc_codegen_cranelift/src/unsize.rs
@@ -24,7 +24,7 @@ pub(crate) fn unsized_info<'tcx>(
(&ty::Array(_, len), &ty::Slice(_)) => fx
.bcx
.ins()
- .iconst(fx.pointer_type, len.eval_usize(fx.tcx, ParamEnv::reveal_all()) as i64),
+ .iconst(fx.pointer_type, len.eval_target_usize(fx.tcx, ParamEnv::reveal_all()) as i64),
(
&ty::Dynamic(ref data_a, _, src_dyn_kind),
&ty::Dynamic(ref data_b, _, target_dyn_kind),
diff --git a/compiler/rustc_codegen_cranelift/src/value_and_place.rs b/compiler/rustc_codegen_cranelift/src/value_and_place.rs
index fe8af21ac..cc1edaa97 100644
--- a/compiler/rustc_codegen_cranelift/src/value_and_place.rs
+++ b/compiler/rustc_codegen_cranelift/src/value_and_place.rs
@@ -514,8 +514,8 @@ impl<'tcx> CPlace<'tcx> {
(types::I32, types::F32)
| (types::F32, types::I32)
| (types::I64, types::F64)
- | (types::F64, types::I64) => fx.bcx.ins().bitcast(dst_ty, data),
- _ if src_ty.is_vector() && dst_ty.is_vector() => fx.bcx.ins().bitcast(dst_ty, data),
+ | (types::F64, types::I64) => codegen_bitcast(fx, dst_ty, data),
+ _ if src_ty.is_vector() && dst_ty.is_vector() => codegen_bitcast(fx, dst_ty, data),
_ if src_ty.is_vector() || dst_ty.is_vector() => {
// FIXME do something more efficient for transmutes between vectors and integers.
let stack_slot = fx.bcx.create_sized_stack_slot(StackSlotData {
@@ -564,8 +564,8 @@ impl<'tcx> CPlace<'tcx> {
CPlaceInner::Var(_local, var) => {
if let ty::Array(element, len) = dst_layout.ty.kind() {
// Can only happen for vector types
- let len =
- u32::try_from(len.eval_usize(fx.tcx, ParamEnv::reveal_all())).unwrap();
+ let len = u32::try_from(len.eval_target_usize(fx.tcx, ParamEnv::reveal_all()))
+ .unwrap();
let vector_ty = fx.clif_type(*element).unwrap().by(len).unwrap();
let data = match from.0 {
@@ -588,10 +588,13 @@ impl<'tcx> CPlace<'tcx> {
return;
}
CPlaceInner::VarPair(_local, var1, var2) => {
- let (ptr, meta) = from.force_stack(fx);
- assert!(meta.is_none());
- let (data1, data2) =
- CValue(CValueInner::ByRef(ptr, None), dst_layout).load_scalar_pair(fx);
+ let (data1, data2) = if from.layout().ty == dst_layout.ty {
+ CValue(from.0, dst_layout).load_scalar_pair(fx)
+ } else {
+ let (ptr, meta) = from.force_stack(fx);
+ assert!(meta.is_none());
+ CValue(CValueInner::ByRef(ptr, None), dst_layout).load_scalar_pair(fx)
+ };
let (dst_ty1, dst_ty2) = fx.clif_pair_type(self.layout().ty).unwrap();
transmute_value(fx, var1, data1, dst_ty1);
transmute_value(fx, var2, data2, dst_ty2);
diff --git a/compiler/rustc_codegen_cranelift/y.rs b/compiler/rustc_codegen_cranelift/y.rs
index 02e1e21ad..fd825d02e 100755
--- a/compiler/rustc_codegen_cranelift/y.rs
+++ b/compiler/rustc_codegen_cranelift/y.rs
@@ -3,7 +3,7 @@
# This block is ignored by rustc
set -e
echo "[BUILD] y.rs" 1>&2
-rustc $0 -o ${0/.rs/.bin} -Cdebuginfo=1 --edition 2021
+rustc $0 -o ${0/.rs/.bin} -Cdebuginfo=1 --edition 2021 -Cpanic=abort
exec ${0/.rs/.bin} $@
*/
diff --git a/compiler/rustc_error_messages/locales/en-US/codegen_gcc.ftl b/compiler/rustc_codegen_gcc/locales/en-US.ftl
index 08ce51725..6101b28ab 100644
--- a/compiler/rustc_error_messages/locales/en-US/codegen_gcc.ftl
+++ b/compiler/rustc_codegen_gcc/locales/en-US.ftl
@@ -23,7 +23,7 @@ codegen_gcc_invalid_monomorphization_unsupported_element =
invalid monomorphization of `{$name}` intrinsic: unsupported {$name} from `{$in_ty}` with element `{$elem_ty}` to `{$ret_ty}`
codegen_gcc_invalid_monomorphization_invalid_bitmask =
- invalid monomorphization of `{$name}` intrinsic: invalid bitmask `{ty}`, expected `u{$expected_int_bits}` or `[u8; {$expected_bytes}]`
+ invalid monomorphization of `{$name}` intrinsic: invalid bitmask `{$ty}`, expected `u{$expected_int_bits}` or `[u8; {$expected_bytes}]`
codegen_gcc_invalid_monomorphization_simd_shuffle =
invalid monomorphization of `{$name}` intrinsic: simd_shuffle index must be an array of `u32`, got `{$ty}`
diff --git a/compiler/rustc_codegen_gcc/src/builder.rs b/compiler/rustc_codegen_gcc/src/builder.rs
index a92242b26..e88c12716 100644
--- a/compiler/rustc_codegen_gcc/src/builder.rs
+++ b/compiler/rustc_codegen_gcc/src/builder.rs
@@ -709,7 +709,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
bx.range_metadata(load, vr);
}
}
- abi::Pointer if vr.start < vr.end && !vr.contains(0) => {
+ abi::Pointer(_) if vr.start < vr.end && !vr.contains(0) => {
bx.nonnull_metadata(load);
}
_ => {}
diff --git a/compiler/rustc_codegen_gcc/src/callee.rs b/compiler/rustc_codegen_gcc/src/callee.rs
index c1041125e..9e3a22ee0 100644
--- a/compiler/rustc_codegen_gcc/src/callee.rs
+++ b/compiler/rustc_codegen_gcc/src/callee.rs
@@ -1,6 +1,6 @@
use gccjit::{FunctionType, RValue};
use rustc_codegen_ssa::traits::BaseTypeMethods;
-use rustc_middle::ty::{self, Instance, TypeVisitable};
+use rustc_middle::ty::{self, Instance, TypeVisitableExt};
use rustc_middle::ty::layout::{FnAbiOf, HasTyCtxt};
use crate::abi::FnAbiGccExt;
diff --git a/compiler/rustc_codegen_gcc/src/common.rs b/compiler/rustc_codegen_gcc/src/common.rs
index 0afc56b44..c939da9ce 100644
--- a/compiler/rustc_codegen_gcc/src/common.rs
+++ b/compiler/rustc_codegen_gcc/src/common.rs
@@ -211,7 +211,7 @@ impl<'gcc, 'tcx> ConstMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
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.primitive() != Pointer {
+ if !matches!(layout.primitive(), Pointer(_)) {
self.const_bitcast(ptr.dereference(None).to_rvalue(), ty)
}
else {
diff --git a/compiler/rustc_codegen_gcc/src/consts.rs b/compiler/rustc_codegen_gcc/src/consts.rs
index ea8ab7611..dc41cb761 100644
--- a/compiler/rustc_codegen_gcc/src/consts.rs
+++ b/compiler/rustc_codegen_gcc/src/consts.rs
@@ -322,13 +322,16 @@ pub fn const_alloc_to_gcc<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, alloc: ConstAl
)
.expect("const_alloc_to_llvm: could not read relocation pointer")
as u64;
+
+ let address_space = cx.tcx.global_alloc(alloc_id).address_space(cx);
+
llvals.push(cx.scalar_to_backend(
InterpScalar::from_pointer(
interpret::Pointer::new(alloc_id, Size::from_bytes(ptr_offset)),
&cx.tcx,
),
- abi::Scalar::Initialized { value: Primitive::Pointer, valid_range: WrappingRange::full(dl.pointer_size) },
- cx.type_i8p(),
+ abi::Scalar::Initialized { value: Primitive::Pointer(address_space), valid_range: WrappingRange::full(dl.pointer_size) },
+ cx.type_i8p_ext(address_space),
));
next_offset = offset + pointer_size;
}
diff --git a/compiler/rustc_codegen_gcc/src/context.rs b/compiler/rustc_codegen_gcc/src/context.rs
index 4424b31c0..457006319 100644
--- a/compiler/rustc_codegen_gcc/src/context.rs
+++ b/compiler/rustc_codegen_gcc/src/context.rs
@@ -383,7 +383,7 @@ impl<'gcc, 'tcx> MiscMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
tcx,
ty::ParamEnv::reveal_all(),
def_id,
- tcx.intern_substs(&[]),
+ ty::List::empty(),
)
.unwrap().unwrap(),
),
diff --git a/compiler/rustc_codegen_gcc/src/intrinsic/simd.rs b/compiler/rustc_codegen_gcc/src/intrinsic/simd.rs
index 12e416f62..cb8168b40 100644
--- a/compiler/rustc_codegen_gcc/src/intrinsic/simd.rs
+++ b/compiler/rustc_codegen_gcc/src/intrinsic/simd.rs
@@ -1,6 +1,6 @@
use std::cmp::Ordering;
-use gccjit::{BinaryOp, RValue, Type, ToRValue};
+use gccjit::{BinaryOp, RValue, ToRValue, Type};
use rustc_codegen_ssa::base::compare_simd_types;
use rustc_codegen_ssa::common::TypeKind;
use rustc_codegen_ssa::mir::operand::OperandRef;
@@ -10,52 +10,57 @@ 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 rustc_span::{sym, Span, Symbol};
use rustc_target::abi::Align;
use crate::builder::Builder;
use crate::errors::{
- InvalidMonomorphizationInvalidFloatVector,
- InvalidMonomorphizationNotFloat,
- InvalidMonomorphizationUnrecognized,
- InvalidMonomorphizationExpectedSignedUnsigned,
- InvalidMonomorphizationUnsupportedElement,
- InvalidMonomorphizationInvalidBitmask,
- InvalidMonomorphizationSimdShuffle,
- InvalidMonomorphizationExpectedSimd,
- InvalidMonomorphizationMaskType,
- InvalidMonomorphizationReturnLength,
- InvalidMonomorphizationReturnLengthInputType,
- InvalidMonomorphizationReturnElement,
- InvalidMonomorphizationReturnType,
- InvalidMonomorphizationInsertedType,
- InvalidMonomorphizationReturnIntegerType,
- InvalidMonomorphizationMismatchedLengths,
- InvalidMonomorphizationUnsupportedCast,
- InvalidMonomorphizationUnsupportedOperation
+ InvalidMonomorphizationExpectedSignedUnsigned, InvalidMonomorphizationExpectedSimd,
+ InvalidMonomorphizationInsertedType, InvalidMonomorphizationInvalidBitmask,
+ InvalidMonomorphizationInvalidFloatVector, InvalidMonomorphizationMaskType,
+ InvalidMonomorphizationMismatchedLengths, InvalidMonomorphizationNotFloat,
+ InvalidMonomorphizationReturnElement, InvalidMonomorphizationReturnIntegerType,
+ InvalidMonomorphizationReturnLength, InvalidMonomorphizationReturnLengthInputType,
+ InvalidMonomorphizationReturnType, InvalidMonomorphizationSimdShuffle,
+ InvalidMonomorphizationUnrecognized, InvalidMonomorphizationUnsupportedCast,
+ InvalidMonomorphizationUnsupportedElement, InvalidMonomorphizationUnsupportedOperation,
};
use crate::intrinsic;
-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<RValue<'gcc>, ()> {
+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<RValue<'gcc>, ()> {
// macros for error handling:
macro_rules! return_error {
- ($err:expr) => {
- {
- bx.sess().emit_err($err);
- return Err(());
- }
- }
+ ($err:expr) => {{
+ bx.sess().emit_err($err);
+ return Err(());
+ }};
}
macro_rules! require {
($cond:expr, $err:expr) => {
if !$cond {
return_error!($err);
}
- }
+ };
}
macro_rules! require_simd {
($ty: expr, $position: expr) => {
- require!($ty.is_simd(), InvalidMonomorphizationExpectedSimd { span, name, position: $position, found_ty: $ty })
+ require!(
+ $ty.is_simd(),
+ InvalidMonomorphizationExpectedSimd {
+ span,
+ name,
+ position: $position,
+ found_ty: $ty
+ }
+ )
};
}
@@ -77,7 +82,7 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(bx: &mut Builder<'a, 'gcc, 'tcx>,
ty::Uint(i) if i.bit_width() == Some(expected_int_bits) => args[0].immediate(),
ty::Array(elem, len)
if matches!(elem.kind(), ty::Uint(ty::UintTy::U8))
- && len.try_eval_usize(bx.tcx, ty::ParamEnv::reveal_all())
+ && len.try_eval_target_usize(bx.tcx, ty::ParamEnv::reveal_all())
== Some(expected_bytes) =>
{
let place = PlaceRef::alloca(bx, args[0].layout);
@@ -86,9 +91,13 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(bx: &mut Builder<'a, 'gcc, 'tcx>,
let ptr = bx.pointercast(place.llval, bx.cx.type_ptr_to(int_ty));
bx.load(int_ty, ptr, Align::ONE)
}
- _ => return_error!(
- InvalidMonomorphizationInvalidBitmask { span, name, ty: mask_ty, expected_int_bits, expected_bytes }
- ),
+ _ => return_error!(InvalidMonomorphizationInvalidBitmask {
+ span,
+ name,
+ ty: mask_ty,
+ expected_int_bits,
+ expected_bytes
+ }),
};
let arg1 = args[1].immediate();
@@ -129,11 +138,18 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(bx: &mut Builder<'a, 'gcc, 'tcx>,
let (out_len, out_ty) = ret_ty.simd_size_and_type(bx.tcx());
require!(
in_len == out_len,
- InvalidMonomorphizationReturnLengthInputType { span, name, in_len, in_ty, ret_ty, out_len }
+ InvalidMonomorphizationReturnLengthInputType {
+ span,
+ name,
+ in_len,
+ in_ty,
+ ret_ty,
+ out_len
+ }
);
require!(
bx.type_kind(bx.element_type(llret_ty)) == TypeKind::Integer,
- InvalidMonomorphizationReturnIntegerType {span, name, ret_ty, out_ty}
+ InvalidMonomorphizationReturnIntegerType { span, name, ret_ty, out_ty }
);
return Ok(compare_simd_types(
@@ -147,26 +163,26 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(bx: &mut Builder<'a, 'gcc, 'tcx>,
}
if let Some(stripped) = name.as_str().strip_prefix("simd_shuffle") {
- 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!(
- InvalidMonomorphizationSimdShuffle { span, name, ty: args[2].layout.ty }
- ),
+ 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_target_usize(bx.cx.tcx, ty::ParamEnv::reveal_all()).unwrap_or_else(
+ || span_bug!(span, "could not evaluate shuffle index array length"),
+ )
}
+ _ => return_error!(InvalidMonomorphizationSimdShuffle {
+ span,
+ name,
+ ty: args[2].layout.ty
+ }),
}
- else {
- stripped.parse().unwrap_or_else(|_| {
- span_bug!(span, "bad `simd_shuffle` instruction only caught in codegen?")
- })
- };
+ } else {
+ stripped.parse().unwrap_or_else(|_| {
+ span_bug!(span, "bad `simd_shuffle` instruction only caught in codegen?")
+ })
+ };
require_simd!(ret_ty, "return");
@@ -182,14 +198,10 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(bx: &mut Builder<'a, 'gcc, 'tcx>,
let vector = args[2].immediate();
- return Ok(bx.shuffle_vector(
- args[0].immediate(),
- args[1].immediate(),
- vector,
- ));
+ return Ok(bx.shuffle_vector(args[0].immediate(), args[1].immediate(), vector));
}
- #[cfg(feature="master")]
+ #[cfg(feature = "master")]
if name == sym::simd_insert {
require!(
in_elem == arg_tys[2],
@@ -205,44 +217,44 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(bx: &mut Builder<'a, 'gcc, 'tcx>,
// not be an l-value. So, call a builtin to set the element.
// TODO(antoyo): perhaps we could create a new vector or maybe there's a GIMPLE instruction for that?
// TODO(antoyo): don't use target specific builtins here.
- let func_name =
- match in_len {
- 2 => {
- if element_type == bx.i64_type {
- "__builtin_ia32_vec_set_v2di"
- }
- else {
- unimplemented!();
- }
- },
- 4 => {
- if element_type == bx.i32_type {
- "__builtin_ia32_vec_set_v4si"
- }
- else {
- unimplemented!();
- }
- },
- 8 => {
- if element_type == bx.i16_type {
- "__builtin_ia32_vec_set_v8hi"
- }
- else {
- unimplemented!();
- }
- },
- _ => unimplemented!("Len: {}", in_len),
- };
+ let func_name = match in_len {
+ 2 => {
+ if element_type == bx.i64_type {
+ "__builtin_ia32_vec_set_v2di"
+ } else {
+ unimplemented!();
+ }
+ }
+ 4 => {
+ if element_type == bx.i32_type {
+ "__builtin_ia32_vec_set_v4si"
+ } else {
+ unimplemented!();
+ }
+ }
+ 8 => {
+ if element_type == bx.i16_type {
+ "__builtin_ia32_vec_set_v8hi"
+ } else {
+ unimplemented!();
+ }
+ }
+ _ => unimplemented!("Len: {}", in_len),
+ };
let builtin = bx.context.get_target_builtin_function(func_name);
let param1_type = builtin.get_param(0).to_rvalue().get_type();
// TODO(antoyo): perhaps use __builtin_convertvector for vector casting.
let vector = bx.cx.bitcast_if_needed(vector, param1_type);
- let result = bx.context.new_call(None, builtin, &[vector, value, bx.context.new_cast(None, index, bx.int_type)]);
+ let result = bx.context.new_call(
+ None,
+ builtin,
+ &[vector, value, bx.context.new_cast(None, index, bx.int_type)],
+ );
// TODO(antoyo): perhaps use __builtin_convertvector for vector casting.
return Ok(bx.context.new_bitcast(None, result, vector.get_type()));
}
- #[cfg(feature="master")]
+ #[cfg(feature = "master")]
if name == sym::simd_extract {
require!(
ret_ty == in_elem,
@@ -273,7 +285,14 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(bx: &mut Builder<'a, 'gcc, 'tcx>,
let (out_len, out_elem) = ret_ty.simd_size_and_type(bx.tcx());
require!(
in_len == out_len,
- InvalidMonomorphizationReturnLengthInputType { span, name, in_len, in_ty, ret_ty, out_len }
+ InvalidMonomorphizationReturnLengthInputType {
+ span,
+ name,
+ in_len,
+ in_ty,
+ ret_ty,
+ out_len
+ }
);
// casting cares about nominal type, not just structural type
if in_elem == out_elem {
@@ -322,19 +341,27 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(bx: &mut Builder<'a, 'gcc, 'tcx>,
let cast_vec_element = |index| {
let index = bx.context.new_rvalue_from_int(bx.int_type, index);
- bx.context.new_cast(None, bx.context.new_array_access(None, array, index).to_rvalue(), out_type)
+ bx.context.new_cast(
+ None,
+ bx.context.new_array_access(None, array, index).to_rvalue(),
+ out_type,
+ )
};
- bx.context.new_rvalue_from_vector(None, vector_type, &[
- cast_vec_element(0),
- cast_vec_element(1),
- cast_vec_element(2),
- cast_vec_element(3),
- cast_vec_element(4),
- cast_vec_element(5),
- cast_vec_element(6),
- cast_vec_element(7),
- ])
+ bx.context.new_rvalue_from_vector(
+ None,
+ vector_type,
+ &[
+ cast_vec_element(0),
+ cast_vec_element(1),
+ cast_vec_element(2),
+ cast_vec_element(3),
+ cast_vec_element(4),
+ cast_vec_element(5),
+ cast_vec_element(6),
+ cast_vec_element(7),
+ ],
+ )
};
match (in_style, out_style) {
@@ -385,9 +412,14 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(bx: &mut Builder<'a, 'gcc, 'tcx>,
}
_ => { /* Unsupported. Fallthrough. */ }
}
- return_error!(
- InvalidMonomorphizationUnsupportedCast { span, name, in_ty, in_elem, ret_ty, out_elem }
- );
+ return_error!(InvalidMonomorphizationUnsupportedCast {
+ span,
+ name,
+ in_ty,
+ in_elem,
+ ret_ty,
+ out_elem
+ });
}
macro_rules! arith_binary {
@@ -414,54 +446,60 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(bx: &mut Builder<'a, 'gcc, 'tcx>,
args: &[OperandRef<'tcx, RValue<'gcc>>],
) -> Result<RValue<'gcc>, ()> {
macro_rules! return_error {
- ($err:expr) => {
- {
- bx.sess().emit_err($err);
- return Err(());
- }
- }
+ ($err:expr) => {{
+ bx.sess().emit_err($err);
+ return Err(());
+ }};
}
- let (elem_ty_str, elem_ty) =
- if let ty::Float(f) = in_elem.kind() {
- let elem_ty = bx.cx.type_float_from_ty(*f);
- match f.bit_width() {
- 32 => ("f32", elem_ty),
- 64 => ("f64", elem_ty),
- _ => {
- return_error!(InvalidMonomorphizationInvalidFloatVector { span, name, elem_ty: f.name_str(), vec_ty: in_ty });
- }
+ let (elem_ty_str, elem_ty) = if let ty::Float(f) = in_elem.kind() {
+ let elem_ty = bx.cx.type_float_from_ty(*f);
+ match f.bit_width() {
+ 32 => ("f32", elem_ty),
+ 64 => ("f64", elem_ty),
+ _ => {
+ return_error!(InvalidMonomorphizationInvalidFloatVector {
+ span,
+ name,
+ elem_ty: f.name_str(),
+ vec_ty: in_ty
+ });
}
}
- else {
- return_error!(InvalidMonomorphizationNotFloat { span, name, ty: in_ty });
- };
+ } else {
+ return_error!(InvalidMonomorphizationNotFloat { span, name, ty: in_ty });
+ };
let vec_ty = bx.cx.type_vector(elem_ty, in_len);
- let (intr_name, fn_ty) =
- match name {
- sym::simd_ceil => ("ceil", bx.type_func(&[vec_ty], vec_ty)),
- sym::simd_fabs => ("fabs", bx.type_func(&[vec_ty], vec_ty)), // TODO(antoyo): pand with 170141183420855150465331762880109871103
- sym::simd_fcos => ("cos", bx.type_func(&[vec_ty], vec_ty)),
- sym::simd_fexp2 => ("exp2", bx.type_func(&[vec_ty], vec_ty)),
- sym::simd_fexp => ("exp", bx.type_func(&[vec_ty], vec_ty)),
- sym::simd_flog10 => ("log10", bx.type_func(&[vec_ty], vec_ty)),
- sym::simd_flog2 => ("log2", bx.type_func(&[vec_ty], vec_ty)),
- sym::simd_flog => ("log", bx.type_func(&[vec_ty], vec_ty)),
- sym::simd_floor => ("floor", bx.type_func(&[vec_ty], vec_ty)),
- sym::simd_fma => ("fma", bx.type_func(&[vec_ty, vec_ty, vec_ty], vec_ty)),
- sym::simd_fpowi => ("powi", bx.type_func(&[vec_ty, bx.type_i32()], vec_ty)),
- sym::simd_fpow => ("pow", bx.type_func(&[vec_ty, vec_ty], vec_ty)),
- sym::simd_fsin => ("sin", bx.type_func(&[vec_ty], vec_ty)),
- sym::simd_fsqrt => ("sqrt", bx.type_func(&[vec_ty], vec_ty)),
- sym::simd_round => ("round", bx.type_func(&[vec_ty], vec_ty)),
- sym::simd_trunc => ("trunc", bx.type_func(&[vec_ty], vec_ty)),
- _ => return_error!(InvalidMonomorphizationUnrecognized { span, name })
- };
+ let (intr_name, fn_ty) = match name {
+ sym::simd_ceil => ("ceil", bx.type_func(&[vec_ty], vec_ty)),
+ sym::simd_fabs => ("fabs", bx.type_func(&[vec_ty], vec_ty)), // TODO(antoyo): pand with 170141183420855150465331762880109871103
+ sym::simd_fcos => ("cos", bx.type_func(&[vec_ty], vec_ty)),
+ sym::simd_fexp2 => ("exp2", bx.type_func(&[vec_ty], vec_ty)),
+ sym::simd_fexp => ("exp", bx.type_func(&[vec_ty], vec_ty)),
+ sym::simd_flog10 => ("log10", bx.type_func(&[vec_ty], vec_ty)),
+ sym::simd_flog2 => ("log2", bx.type_func(&[vec_ty], vec_ty)),
+ sym::simd_flog => ("log", bx.type_func(&[vec_ty], vec_ty)),
+ sym::simd_floor => ("floor", bx.type_func(&[vec_ty], vec_ty)),
+ sym::simd_fma => ("fma", bx.type_func(&[vec_ty, vec_ty, vec_ty], vec_ty)),
+ sym::simd_fpowi => ("powi", bx.type_func(&[vec_ty, bx.type_i32()], vec_ty)),
+ sym::simd_fpow => ("pow", bx.type_func(&[vec_ty, vec_ty], vec_ty)),
+ sym::simd_fsin => ("sin", bx.type_func(&[vec_ty], vec_ty)),
+ sym::simd_fsqrt => ("sqrt", bx.type_func(&[vec_ty], vec_ty)),
+ sym::simd_round => ("round", bx.type_func(&[vec_ty], vec_ty)),
+ sym::simd_trunc => ("trunc", bx.type_func(&[vec_ty], vec_ty)),
+ _ => return_error!(InvalidMonomorphizationUnrecognized { span, name }),
+ };
let llvm_name = &format!("llvm.{0}.v{1}{2}", intr_name, in_len, elem_ty_str);
let function = intrinsic::llvm::intrinsic(llvm_name, &bx.cx);
let function: RValue<'gcc> = unsafe { std::mem::transmute(function) };
- let c = bx.call(fn_ty, None, function, &args.iter().map(|arg| arg.immediate()).collect::<Vec<_>>(), None);
+ let c = bx.call(
+ fn_ty,
+ None,
+ function,
+ &args.iter().map(|arg| arg.immediate()).collect::<Vec<_>>(),
+ None,
+ );
Ok(c)
}
@@ -518,7 +556,7 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(bx: &mut Builder<'a, 'gcc, 'tcx>,
simd_neg: Int => neg, Float => fneg;
}
- #[cfg(feature="master")]
+ #[cfg(feature = "master")]
if name == sym::simd_saturating_add || name == sym::simd_saturating_sub {
let lhs = args[0].immediate();
let rhs = args[1].immediate();
@@ -536,18 +574,23 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(bx: &mut Builder<'a, 'gcc, 'tcx>,
});
}
};
- let builtin_name =
- match (signed, is_add, in_len, elem_width) {
- (true, true, 32, 8) => "__builtin_ia32_paddsb256", // TODO(antoyo): cast arguments to unsigned.
- (false, true, 32, 8) => "__builtin_ia32_paddusb256",
- (true, true, 16, 16) => "__builtin_ia32_paddsw256",
- (false, true, 16, 16) => "__builtin_ia32_paddusw256",
- (true, false, 16, 16) => "__builtin_ia32_psubsw256",
- (false, false, 16, 16) => "__builtin_ia32_psubusw256",
- (true, false, 32, 8) => "__builtin_ia32_psubsb256",
- (false, false, 32, 8) => "__builtin_ia32_psubusb256",
- _ => unimplemented!("signed: {}, is_add: {}, in_len: {}, elem_width: {}", signed, is_add, in_len, elem_width),
- };
+ let builtin_name = match (signed, is_add, in_len, elem_width) {
+ (true, true, 32, 8) => "__builtin_ia32_paddsb256", // TODO(antoyo): cast arguments to unsigned.
+ (false, true, 32, 8) => "__builtin_ia32_paddusb256",
+ (true, true, 16, 16) => "__builtin_ia32_paddsw256",
+ (false, true, 16, 16) => "__builtin_ia32_paddusw256",
+ (true, false, 16, 16) => "__builtin_ia32_psubsw256",
+ (false, false, 16, 16) => "__builtin_ia32_psubusw256",
+ (true, false, 32, 8) => "__builtin_ia32_psubsb256",
+ (false, false, 32, 8) => "__builtin_ia32_psubusb256",
+ _ => unimplemented!(
+ "signed: {}, is_add: {}, in_len: {}, elem_width: {}",
+ signed,
+ is_add,
+ in_len,
+ elem_width
+ ),
+ };
let vec_ty = bx.cx.type_vector(elem_ty, in_len as u64);
let func = bx.context.get_target_builtin_function(builtin_name);
@@ -575,8 +618,7 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(bx: &mut Builder<'a, 'gcc, 'tcx>,
// if overflow occurs, the result is the
// mathematical result modulo 2^n:
Ok(bx.$op(args[1].immediate(), r))
- }
- else {
+ } else {
Ok(bx.vector_reduce_op(args[0].immediate(), $vec_op))
}
}
@@ -585,12 +627,17 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(bx: &mut Builder<'a, 'gcc, 'tcx>,
// ordered arithmetic reductions take an accumulator
let acc = args[1].immediate();
Ok(bx.$float_reduce(acc, args[0].immediate()))
- }
- else {
+ } else {
Ok(bx.vector_reduce_op(args[0].immediate(), $vec_op))
}
}
- _ => return_error!(InvalidMonomorphizationUnsupportedElement { span, name, in_ty, elem_ty: in_elem, ret_ty }),
+ _ => return_error!(InvalidMonomorphizationUnsupportedElement {
+ span,
+ name,
+ in_ty,
+ elem_ty: in_elem,
+ ret_ty
+ }),
};
}
};
@@ -603,13 +650,7 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(bx: &mut Builder<'a, 'gcc, 'tcx>,
add,
0.0 // TODO: Use this argument.
);
- arith_red!(
- simd_reduce_mul_unordered: BinaryOp::Mult,
- vector_reduce_fmul_fast,
- false,
- mul,
- 1.0
- );
+ arith_red!(simd_reduce_mul_unordered: BinaryOp::Mult, vector_reduce_fmul_fast, false, mul, 1.0);
macro_rules! minmax_red {
($name:ident: $reduction:ident) => {
@@ -619,8 +660,16 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(bx: &mut Builder<'a, 'gcc, 'tcx>,
InvalidMonomorphizationReturnType { span, name, in_elem, in_ty, ret_ty }
);
return match in_elem.kind() {
- ty::Int(_) | ty::Uint(_) | ty::Float(_) => Ok(bx.$reduction(args[0].immediate())),
- _ => return_error!(InvalidMonomorphizationUnsupportedElement { span, name, in_ty, elem_ty: in_elem, ret_ty }),
+ ty::Int(_) | ty::Uint(_) | ty::Float(_) => {
+ Ok(bx.$reduction(args[0].immediate()))
+ }
+ _ => return_error!(InvalidMonomorphizationUnsupportedElement {
+ span,
+ name,
+ in_ty,
+ elem_ty: in_elem,
+ ret_ty
+ }),
};
}
};
@@ -641,7 +690,13 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(bx: &mut Builder<'a, 'gcc, 'tcx>,
} else {
match in_elem.kind() {
ty::Int(_) | ty::Uint(_) => {}
- _ => return_error!(InvalidMonomorphizationUnsupportedElement { span, name, in_ty, elem_ty: in_elem, ret_ty }),
+ _ => return_error!(InvalidMonomorphizationUnsupportedElement {
+ span,
+ name,
+ in_ty,
+ elem_ty: in_elem,
+ ret_ty
+ }),
}
// boolean reductions operate on vectors of i1s:
@@ -654,9 +709,13 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(bx: &mut Builder<'a, 'gcc, 'tcx>,
let r = bx.vector_reduce_op(input, $op);
Ok(if !$boolean { r } else { bx.zext(r, bx.type_bool()) })
}
- _ => return_error!(
- InvalidMonomorphizationUnsupportedElement { span, name, in_ty, elem_ty: in_elem, ret_ty }
- ),
+ _ => return_error!(InvalidMonomorphizationUnsupportedElement {
+ span,
+ name,
+ in_ty,
+ elem_ty: in_elem,
+ ret_ty
+ }),
};
}
};
diff --git a/compiler/rustc_codegen_gcc/src/lib.rs b/compiler/rustc_codegen_gcc/src/lib.rs
index bf1da3831..44538b415 100644
--- a/compiler/rustc_codegen_gcc/src/lib.rs
+++ b/compiler/rustc_codegen_gcc/src/lib.rs
@@ -73,7 +73,8 @@ use rustc_codegen_ssa::back::lto::{LtoModuleCodegen, SerializedModule, ThinModul
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::{ErrorGuaranteed, Handler};
+use rustc_errors::{DiagnosticMessage, ErrorGuaranteed, Handler, SubdiagnosticMessage};
+use rustc_macros::fluent_messages;
use rustc_metadata::EncodedMetadata;
use rustc_middle::dep_graph::{WorkProduct, WorkProductId};
use rustc_middle::ty::TyCtxt;
@@ -84,6 +85,8 @@ use rustc_span::Symbol;
use rustc_span::fatal_error::FatalError;
use tempfile::TempDir;
+fluent_messages! { "../locales/en-US.ftl" }
+
pub struct PrintOnPanic<F: Fn() -> String>(pub F);
impl<F: Fn() -> String> Drop for PrintOnPanic<F> {
@@ -100,6 +103,10 @@ pub struct GccCodegenBackend {
}
impl CodegenBackend for GccCodegenBackend {
+ fn locale_resource(&self) -> &'static str {
+ crate::DEFAULT_LOCALE_RESOURCE
+ }
+
fn init(&self, sess: &Session) {
if sess.lto() != Lto::No {
sess.emit_warning(LTONotSupported {});
@@ -200,6 +207,7 @@ unsafe impl Sync for GccContext {}
impl WriteBackendMethods for GccCodegenBackend {
type Module = GccContext;
type TargetMachine = ();
+ type TargetMachineError = ();
type ModuleBuffer = ModuleBuffer;
type ThinData = ();
type ThinBuffer = ThinBuffer;
diff --git a/compiler/rustc_codegen_gcc/src/mono_item.rs b/compiler/rustc_codegen_gcc/src/mono_item.rs
index 9468a1ef4..a7c868354 100644
--- a/compiler/rustc_codegen_gcc/src/mono_item.rs
+++ b/compiler/rustc_codegen_gcc/src/mono_item.rs
@@ -1,7 +1,7 @@
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, TypeVisitable};
+use rustc_middle::ty::{self, Instance, TypeVisitableExt};
use rustc_middle::ty::layout::{FnAbiOf, LayoutOf};
use rustc_span::def_id::DefId;
diff --git a/compiler/rustc_codegen_gcc/src/type_of.rs b/compiler/rustc_codegen_gcc/src/type_of.rs
index 524d10fb5..ea2ce7650 100644
--- a/compiler/rustc_codegen_gcc/src/type_of.rs
+++ b/compiler/rustc_codegen_gcc/src/type_of.rs
@@ -3,7 +3,7 @@ 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, TypeVisitable};
+use rustc_middle::ty::{self, Ty, TypeVisitableExt};
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};
@@ -253,7 +253,7 @@ impl<'tcx> LayoutGccExt<'tcx> for TyAndLayout<'tcx> {
Int(i, false) => cx.type_from_unsigned_integer(i),
F32 => cx.type_f32(),
F64 => cx.type_f64(),
- Pointer => {
+ Pointer(address_space) => {
// If we know the alignment, pick something better than i8.
let pointee =
if let Some(pointee) = self.pointee_info_at(cx, offset) {
@@ -262,7 +262,7 @@ impl<'tcx> LayoutGccExt<'tcx> for TyAndLayout<'tcx> {
else {
cx.type_i8()
};
- cx.type_ptr_to(pointee)
+ cx.type_ptr_to_ext(pointee, address_space)
}
}
}
diff --git a/compiler/rustc_codegen_llvm/Cargo.toml b/compiler/rustc_codegen_llvm/Cargo.toml
index 9c1bcd431..a7ba2f8b6 100644
--- a/compiler/rustc_codegen_llvm/Cargo.toml
+++ b/compiler/rustc_codegen_llvm/Cargo.toml
@@ -30,10 +30,11 @@ rustc_macros = { path = "../rustc_macros" }
rustc_metadata = { path = "../rustc_metadata" }
rustc_query_system = { path = "../rustc_query_system" }
rustc_session = { path = "../rustc_session" }
-rustc_serialize = { path = "../rustc_serialize" }
rustc_symbol_mangling = { path = "../rustc_symbol_mangling" }
rustc_target = { path = "../rustc_target" }
smallvec = { version = "1.8.1", features = ["union", "may_dangle"] }
rustc_ast = { path = "../rustc_ast" }
rustc_span = { path = "../rustc_span" }
tempfile = "3.2.0"
+serde = { version = "1", features = [ "derive" ]}
+serde_json = "1"
diff --git a/compiler/rustc_codegen_llvm/locales/en-US.ftl b/compiler/rustc_codegen_llvm/locales/en-US.ftl
new file mode 100644
index 000000000..e5df41737
--- /dev/null
+++ b/compiler/rustc_codegen_llvm/locales/en-US.ftl
@@ -0,0 +1,89 @@
+codegen_llvm_unknown_ctarget_feature =
+ unknown feature specified for `-Ctarget-feature`: `{$feature}`
+ .note = it is still passed through to the codegen backend
+ .possible_feature = you might have meant: `{$rust_feature}`
+ .consider_filing_feature_request = consider filing a feature request
+
+codegen_llvm_unknown_ctarget_feature_prefix =
+ unknown feature specified for `-Ctarget-feature`: `{$feature}`
+ .note = features must begin with a `+` to enable or `-` to disable it
+
+codegen_llvm_error_creating_import_library =
+ Error creating import library for {$lib_name}: {$error}
+
+codegen_llvm_symbol_already_defined =
+ symbol `{$symbol_name}` is already defined
+
+codegen_llvm_invalid_minimum_alignment =
+ invalid minimum global alignment: {$err}
+
+codegen_llvm_sanitizer_memtag_requires_mte =
+ `-Zsanitizer=memtag` requires `-Ctarget-feature=+mte`
+
+codegen_llvm_error_writing_def_file =
+ Error writing .DEF file: {$error}
+
+codegen_llvm_error_calling_dlltool =
+ Error calling dlltool: {$error}
+
+codegen_llvm_dlltool_fail_import_library =
+ Dlltool could not create import library: {$stdout}\n{$stderr}
+
+codegen_llvm_target_feature_disable_or_enable =
+ the target features {$features} must all be either enabled or disabled together
+
+codegen_llvm_missing_features =
+ add the missing features in a `target_feature` attribute
+
+codegen_llvm_dynamic_linking_with_lto =
+ cannot prefer dynamic linking when performing LTO
+ .note = only 'staticlib', 'bin', and 'cdylib' outputs are supported with LTO
+
+codegen_llvm_parse_target_machine_config =
+ failed to parse target machine config to target machine: {$error}
+
+codegen_llvm_lto_disallowed = lto can only be run for executables, cdylibs and static library outputs
+
+codegen_llvm_lto_dylib = lto cannot be used for `dylib` crate type without `-Zdylib-lto`
+
+codegen_llvm_lto_bitcode_from_rlib = failed to get bitcode from object file for LTO ({$llvm_err})
+
+codegen_llvm_write_output = could not write output to {$path}
+codegen_llvm_write_output_with_llvm_err = could not write output to {$path}: {$llvm_err}
+
+codegen_llvm_target_machine = could not create LLVM TargetMachine for triple: {$triple}
+codegen_llvm_target_machine_with_llvm_err = could not create LLVM TargetMachine for triple: {$triple}: {$llvm_err}
+
+codegen_llvm_run_passes = failed to run LLVM passes
+codegen_llvm_run_passes_with_llvm_err = failed to run LLVM passes: {$llvm_err}
+
+codegen_llvm_serialize_module = failed to serialize module {$name}
+codegen_llvm_serialize_module_with_llvm_err = failed to serialize module {$name}: {$llvm_err}
+
+codegen_llvm_write_ir = failed to write LLVM IR to {$path}
+codegen_llvm_write_ir_with_llvm_err = failed to write LLVM IR to {$path}: {$llvm_err}
+
+codegen_llvm_prepare_thin_lto_context = failed to prepare thin LTO context
+codegen_llvm_prepare_thin_lto_context_with_llvm_err = failed to prepare thin LTO context: {$llvm_err}
+
+codegen_llvm_load_bitcode = failed to load bitcode of module "{$name}"
+codegen_llvm_load_bitcode_with_llvm_err = failed to load bitcode of module "{$name}": {$llvm_err}
+
+codegen_llvm_write_thinlto_key = error while writing ThinLTO key data: {$err}
+codegen_llvm_write_thinlto_key_with_llvm_err = error while writing ThinLTO key data: {$err}: {$llvm_err}
+
+codegen_llvm_multiple_source_dicompileunit = multiple source DICompileUnits found
+codegen_llvm_multiple_source_dicompileunit_with_llvm_err = multiple source DICompileUnits found: {$llvm_err}
+
+codegen_llvm_prepare_thin_lto_module = failed to prepare thin LTO module
+codegen_llvm_prepare_thin_lto_module_with_llvm_err = failed to prepare thin LTO module: {$llvm_err}
+
+codegen_llvm_parse_bitcode = failed to parse bitcode for LTO module
+codegen_llvm_parse_bitcode_with_llvm_err = failed to parse bitcode for LTO module: {$llvm_err}
+
+codegen_llvm_from_llvm_optimization_diag = {$filename}:{$line}:{$column} {$pass_name}: {$message}
+codegen_llvm_from_llvm_diag = {$message}
+
+codegen_llvm_write_bytecode = failed to write bytecode to {$path}: {$err}
+
+codegen_llvm_copy_bitcode = failed to copy bitcode to object file: {$err}
diff --git a/compiler/rustc_codegen_llvm/src/asm.rs b/compiler/rustc_codegen_llvm/src/asm.rs
index 52c8b5179..d9f8170a3 100644
--- a/compiler/rustc_codegen_llvm/src/asm.rs
+++ b/compiler/rustc_codegen_llvm/src/asm.rs
@@ -849,6 +849,7 @@ fn dummy_output_type<'ll>(cx: &CodegenCx<'ll, '_>, reg: InlineAsmRegClass) -> &'
/// Helper function to get the LLVM type for a Scalar. Pointers are returned as
/// the equivalent integer type.
fn llvm_asm_scalar_type<'ll>(cx: &CodegenCx<'ll, '_>, scalar: Scalar) -> &'ll Type {
+ let dl = &cx.tcx.data_layout;
match scalar.primitive() {
Primitive::Int(Integer::I8, _) => cx.type_i8(),
Primitive::Int(Integer::I16, _) => cx.type_i16(),
@@ -856,7 +857,8 @@ fn llvm_asm_scalar_type<'ll>(cx: &CodegenCx<'ll, '_>, scalar: Scalar) -> &'ll Ty
Primitive::Int(Integer::I64, _) => cx.type_i64(),
Primitive::F32 => cx.type_f32(),
Primitive::F64 => cx.type_f64(),
- Primitive::Pointer => cx.type_isize(),
+ // FIXME(erikdesjardins): handle non-default addrspace ptr sizes
+ Primitive::Pointer(_) => cx.type_from_integer(dl.ptr_sized_integer()),
_ => unreachable!(),
}
}
@@ -868,6 +870,7 @@ fn llvm_fixup_input<'ll, 'tcx>(
reg: InlineAsmRegClass,
layout: &TyAndLayout<'tcx>,
) -> &'ll Value {
+ let dl = &bx.tcx.data_layout;
match (reg, layout.abi) {
(InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::vreg), Abi::Scalar(s)) => {
if let Primitive::Int(Integer::I8, _) = s.primitive() {
@@ -881,8 +884,10 @@ fn llvm_fixup_input<'ll, 'tcx>(
let elem_ty = llvm_asm_scalar_type(bx.cx, s);
let count = 16 / layout.size.bytes();
let vec_ty = bx.cx.type_vector(elem_ty, count);
- if let Primitive::Pointer = s.primitive() {
- value = bx.ptrtoint(value, bx.cx.type_isize());
+ // FIXME(erikdesjardins): handle non-default addrspace ptr sizes
+ if let Primitive::Pointer(_) = s.primitive() {
+ let t = bx.type_from_integer(dl.ptr_sized_integer());
+ value = bx.ptrtoint(value, t);
}
bx.insert_element(bx.const_undef(vec_ty), value, bx.const_i32(0))
}
@@ -958,7 +963,7 @@ fn llvm_fixup_output<'ll, 'tcx>(
}
(InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::vreg_low16), Abi::Scalar(s)) => {
value = bx.extract_element(value, bx.const_i32(0));
- if let Primitive::Pointer = s.primitive() {
+ if let Primitive::Pointer(_) = s.primitive() {
value = bx.inttoptr(value, layout.llvm_type(bx.cx));
}
value
diff --git a/compiler/rustc_codegen_llvm/src/attributes.rs b/compiler/rustc_codegen_llvm/src/attributes.rs
index 95baa95b0..651d644eb 100644
--- a/compiler/rustc_codegen_llvm/src/attributes.rs
+++ b/compiler/rustc_codegen_llvm/src/attributes.rs
@@ -62,7 +62,7 @@ pub fn sanitize_attrs<'ll>(
) -> SmallVec<[&'ll Attribute; 4]> {
let mut attrs = SmallVec::new();
let enabled = cx.tcx.sess.opts.unstable_opts.sanitizer - no_sanitize;
- if enabled.contains(SanitizerSet::ADDRESS) {
+ if enabled.contains(SanitizerSet::ADDRESS) || enabled.contains(SanitizerSet::KERNELADDRESS) {
attrs.push(llvm::AttributeKind::SanitizeAddress.create_attr(cx.llcx));
}
if enabled.contains(SanitizerSet::MEMORY) {
@@ -118,7 +118,8 @@ pub fn frame_pointer_type_attr<'ll>(cx: &CodegenCx<'ll, '_>) -> Option<&'ll Attr
/// Tell LLVM what instrument function to insert.
#[inline]
-fn instrument_function_attr<'ll>(cx: &CodegenCx<'ll, '_>) -> Option<&'ll Attribute> {
+fn instrument_function_attr<'ll>(cx: &CodegenCx<'ll, '_>) -> SmallVec<[&'ll Attribute; 4]> {
+ let mut attrs = SmallVec::new();
if cx.sess().opts.unstable_opts.instrument_mcount {
// Similar to `clang -pg` behavior. Handled by the
// `post-inline-ee-instrument` LLVM pass.
@@ -127,14 +128,41 @@ fn instrument_function_attr<'ll>(cx: &CodegenCx<'ll, '_>) -> Option<&'ll Attribu
// See test/CodeGen/mcount.c in clang.
let mcount_name = cx.sess().target.mcount.as_ref();
- Some(llvm::CreateAttrStringValue(
+ attrs.push(llvm::CreateAttrStringValue(
cx.llcx,
"instrument-function-entry-inlined",
&mcount_name,
- ))
- } else {
- None
+ ));
+ }
+ if let Some(options) = &cx.sess().opts.unstable_opts.instrument_xray {
+ // XRay instrumentation is similar to __cyg_profile_func_{enter,exit}.
+ // Function prologue and epilogue are instrumented with NOP sleds,
+ // a runtime library later replaces them with detours into tracing code.
+ if options.always {
+ attrs.push(llvm::CreateAttrStringValue(cx.llcx, "function-instrument", "xray-always"));
+ }
+ if options.never {
+ attrs.push(llvm::CreateAttrStringValue(cx.llcx, "function-instrument", "xray-never"));
+ }
+ if options.ignore_loops {
+ attrs.push(llvm::CreateAttrString(cx.llcx, "xray-ignore-loops"));
+ }
+ // LLVM will not choose the default for us, but rather requires specific
+ // threshold in absence of "xray-always". Use the same default as Clang.
+ let threshold = options.instruction_threshold.unwrap_or(200);
+ attrs.push(llvm::CreateAttrStringValue(
+ cx.llcx,
+ "xray-instruction-threshold",
+ &threshold.to_string(),
+ ));
+ if options.skip_entry {
+ attrs.push(llvm::CreateAttrString(cx.llcx, "xray-skip-entry"));
+ }
+ if options.skip_exit {
+ attrs.push(llvm::CreateAttrString(cx.llcx, "xray-skip-exit"));
+ }
}
+ attrs
}
fn nojumptables_attr<'ll>(cx: &CodegenCx<'ll, '_>) -> Option<&'ll Attribute> {
@@ -441,7 +469,7 @@ pub fn from_fn_attrs<'ll, 'tcx>(
// the WebAssembly specification, which has this feature. This won't be
// needed when LLVM enables this `multivalue` feature by default.
if !cx.tcx.is_closure(instance.def_id()) {
- let abi = cx.tcx.fn_sig(instance.def_id()).abi();
+ let abi = cx.tcx.fn_sig(instance.def_id()).skip_binder().abi();
if abi == Abi::Wasm {
function_features.push("+multivalue".to_string());
}
diff --git a/compiler/rustc_codegen_llvm/src/back/archive.rs b/compiler/rustc_codegen_llvm/src/back/archive.rs
index 58ca87524..dd3268d77 100644
--- a/compiler/rustc_codegen_llvm/src/back/archive.rs
+++ b/compiler/rustc_codegen_llvm/src/back/archive.rs
@@ -183,6 +183,12 @@ impl ArchiveBuilderBuilder for LlvmArchiveBuilderBuilder {
// able to control the *exact* spelling of each of the symbols that are being imported:
// hence we don't want `dlltool` adding leading underscores automatically.
let dlltool = find_binutils_dlltool(sess);
+ let temp_prefix = {
+ let mut path = PathBuf::from(&output_path);
+ path.pop();
+ path.push(lib_name);
+ path
+ };
let result = std::process::Command::new(dlltool)
.args([
"-d",
@@ -192,6 +198,8 @@ impl ArchiveBuilderBuilder for LlvmArchiveBuilderBuilder {
"-l",
output_path.to_str().unwrap(),
"--no-leading-underscore",
+ "--temp-prefix",
+ temp_prefix.to_str().unwrap(),
])
.output();
diff --git a/compiler/rustc_codegen_llvm/src/back/lto.rs b/compiler/rustc_codegen_llvm/src/back/lto.rs
index 6c0faf37a..d2e01708a 100644
--- a/compiler/rustc_codegen_llvm/src/back/lto.rs
+++ b/compiler/rustc_codegen_llvm/src/back/lto.rs
@@ -1,5 +1,7 @@
use crate::back::write::{self, save_temp_bitcode, DiagnosticHandlers};
-use crate::errors::DynamicLinkingWithLTO;
+use crate::errors::{
+ DynamicLinkingWithLTO, LlvmError, LtoBitcodeFromRlib, LtoDisallowed, LtoDylib,
+};
use crate::llvm::{self, build_string};
use crate::{LlvmCodegenBackend, ModuleLlvm};
use object::read::archive::ArchiveFile;
@@ -77,15 +79,12 @@ fn prepare_lto(
// Make sure we actually can run LTO
for crate_type in cgcx.crate_types.iter() {
if !crate_type_allows_lto(*crate_type) {
- let e = diag_handler.fatal(
- "lto can only be run for executables, cdylibs and \
- static library outputs",
- );
- return Err(e);
+ diag_handler.emit_err(LtoDisallowed);
+ return Err(FatalError);
} else if *crate_type == CrateType::Dylib {
if !cgcx.opts.unstable_opts.dylib_lto {
- return Err(diag_handler
- .fatal("lto cannot be used for `dylib` crate type without `-Zdylib-lto`"));
+ diag_handler.emit_err(LtoDylib);
+ return Err(FatalError);
}
}
}
@@ -127,7 +126,10 @@ fn prepare_lto(
let module = SerializedModule::FromRlib(data.to_vec());
upstream_modules.push((module, CString::new(name).unwrap()));
}
- Err(msg) => return Err(diag_handler.fatal(&msg)),
+ Err(e) => {
+ diag_handler.emit_err(e);
+ return Err(FatalError);
+ }
}
}
}
@@ -140,7 +142,7 @@ fn prepare_lto(
Ok((symbols_below_threshold, upstream_modules))
}
-fn get_bitcode_slice_from_object_data(obj: &[u8]) -> Result<&[u8], String> {
+fn get_bitcode_slice_from_object_data(obj: &[u8]) -> Result<&[u8], LtoBitcodeFromRlib> {
let mut len = 0;
let data =
unsafe { llvm::LLVMRustGetBitcodeSliceFromObjectData(obj.as_ptr(), obj.len(), &mut len) };
@@ -155,8 +157,9 @@ fn get_bitcode_slice_from_object_data(obj: &[u8]) -> Result<&[u8], String> {
Ok(bc)
} else {
assert!(len == 0);
- let msg = llvm::last_error().unwrap_or_else(|| "unknown LLVM error".to_string());
- Err(format!("failed to get bitcode from object file for LTO ({})", msg))
+ Err(LtoBitcodeFromRlib {
+ llvm_err: llvm::last_error().unwrap_or_else(|| "unknown LLVM error".to_string()),
+ })
}
}
@@ -328,10 +331,9 @@ fn fat_lto(
});
info!("linking {:?}", name);
let data = bc_decoded.data();
- linker.add(data).map_err(|()| {
- let msg = format!("failed to load bitcode of module {:?}", name);
- write::llvm_err(diag_handler, &msg)
- })?;
+ linker
+ .add(data)
+ .map_err(|()| write::llvm_err(diag_handler, LlvmError::LoadBitcode { name }))?;
serialized_bitcode.push(bc_decoded);
}
drop(linker);
@@ -489,7 +491,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, LlvmError::PrepareThinLtoContext))?;
let data = ThinData(data);
@@ -562,8 +564,7 @@ fn thin_lto(
// session, overwriting the previous serialized data (if any).
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, LlvmError::WriteThinLtoKey { err }));
}
}
@@ -689,8 +690,7 @@ pub unsafe fn optimize_thin_module(
let module_name = &thin_module.shared.module_names[thin_module.idx];
let tm_factory_config = TargetMachineFactoryConfig::new(cgcx, module_name.to_str().unwrap());
- let tm =
- (cgcx.tm_factory)(tm_factory_config).map_err(|e| write::llvm_err(&diag_handler, &e))?;
+ let tm = (cgcx.tm_factory)(tm_factory_config).map_err(|e| write::llvm_err(&diag_handler, e))?;
// Right now the implementation we've got only works over serialized
// modules, so we create a fresh new LLVM context and parse the module
@@ -717,8 +717,7 @@ pub unsafe fn optimize_thin_module(
let mut cu2 = ptr::null_mut();
llvm::LLVMRustThinLTOGetDICompileUnit(llmod, &mut cu1, &mut cu2);
if !cu2.is_null() {
- let msg = "multiple source DICompileUnits found";
- return Err(write::llvm_err(&diag_handler, msg));
+ return Err(write::llvm_err(&diag_handler, LlvmError::MultipleSourceDiCompileUnit));
}
// Up next comes the per-module local analyses that we do for Thin LTO.
@@ -733,8 +732,7 @@ pub unsafe fn optimize_thin_module(
let _timer =
cgcx.prof.generic_activity_with_arg("LLVM_thin_lto_rename", thin_module.name());
if !llvm::LLVMRustPrepareThinLTORename(thin_module.shared.data.0, llmod, target) {
- let msg = "failed to prepare thin LTO module";
- return Err(write::llvm_err(&diag_handler, msg));
+ return Err(write::llvm_err(&diag_handler, LlvmError::PrepareThinLtoModule));
}
save_temp_bitcode(cgcx, &module, "thin-lto-after-rename");
}
@@ -744,8 +742,7 @@ pub unsafe fn optimize_thin_module(
.prof
.generic_activity_with_arg("LLVM_thin_lto_resolve_weak", thin_module.name());
if !llvm::LLVMRustPrepareThinLTOResolveWeak(thin_module.shared.data.0, llmod) {
- let msg = "failed to prepare thin LTO module";
- return Err(write::llvm_err(&diag_handler, msg));
+ return Err(write::llvm_err(&diag_handler, LlvmError::PrepareThinLtoModule));
}
save_temp_bitcode(cgcx, &module, "thin-lto-after-resolve");
}
@@ -755,8 +752,7 @@ pub unsafe fn optimize_thin_module(
.prof
.generic_activity_with_arg("LLVM_thin_lto_internalize", thin_module.name());
if !llvm::LLVMRustPrepareThinLTOInternalize(thin_module.shared.data.0, llmod) {
- let msg = "failed to prepare thin LTO module";
- return Err(write::llvm_err(&diag_handler, msg));
+ return Err(write::llvm_err(&diag_handler, LlvmError::PrepareThinLtoModule));
}
save_temp_bitcode(cgcx, &module, "thin-lto-after-internalize");
}
@@ -765,8 +761,7 @@ pub unsafe fn optimize_thin_module(
let _timer =
cgcx.prof.generic_activity_with_arg("LLVM_thin_lto_import", thin_module.name());
if !llvm::LLVMRustPrepareThinLTOImport(thin_module.shared.data.0, llmod, target) {
- let msg = "failed to prepare thin LTO module";
- return Err(write::llvm_err(&diag_handler, msg));
+ return Err(write::llvm_err(&diag_handler, LlvmError::PrepareThinLtoModule));
}
save_temp_bitcode(cgcx, &module, "thin-lto-after-import");
}
@@ -886,11 +881,7 @@ pub fn parse_module<'a>(
diag_handler: &Handler,
) -> Result<&'a llvm::Module, FatalError> {
unsafe {
- 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)
- },
- )
+ llvm::LLVMRustParseBitcodeForLTO(cx, data.as_ptr(), data.len(), name.as_ptr())
+ .ok_or_else(|| write::llvm_err(diag_handler, LlvmError::ParseBitcode))
}
}
diff --git a/compiler/rustc_codegen_llvm/src/back/write.rs b/compiler/rustc_codegen_llvm/src/back/write.rs
index b2af9f31e..a4ae1b01e 100644
--- a/compiler/rustc_codegen_llvm/src/back/write.rs
+++ b/compiler/rustc_codegen_llvm/src/back/write.rs
@@ -5,6 +5,9 @@ use crate::back::profiling::{
use crate::base;
use crate::common;
use crate::consts;
+use crate::errors::{
+ CopyBitcode, FromLlvmDiag, FromLlvmOptimizationDiag, LlvmError, WithLlvmError, WriteBytecode,
+};
use crate::llvm::{self, DiagnosticInfo, PassManager};
use crate::llvm_util;
use crate::type_::Type;
@@ -37,10 +40,10 @@ use std::slice;
use std::str;
use std::sync::Arc;
-pub fn llvm_err(handler: &rustc_errors::Handler, msg: &str) -> FatalError {
+pub fn llvm_err<'a>(handler: &rustc_errors::Handler, err: LlvmError<'a>) -> FatalError {
match llvm::last_error() {
- Some(err) => handler.fatal(&format!("{}: {}", msg, err)),
- None => handler.fatal(msg),
+ Some(llvm_err) => handler.emit_almost_fatal(WithLlvmError(err, llvm_err)),
+ None => handler.emit_almost_fatal(err),
}
}
@@ -85,10 +88,9 @@ pub fn write_output_file<'ll>(
}
}
- result.into_result().map_err(|()| {
- let msg = format!("could not write output to {}", output.display());
- llvm_err(handler, &msg)
- })
+ result
+ .into_result()
+ .map_err(|()| llvm_err(handler, LlvmError::WriteOutput { path: output }))
}
}
@@ -98,7 +100,7 @@ pub fn create_informational_target_machine(sess: &Session) -> &'static mut llvm:
// system/tcx is set up.
let features = llvm_util::global_llvm_features(sess, false);
target_machine_factory(sess, config::OptLevel::No, &features)(config)
- .unwrap_or_else(|err| llvm_err(sess.diagnostic(), &err).raise())
+ .unwrap_or_else(|err| llvm_err(sess.diagnostic(), err).raise())
}
pub fn create_target_machine(tcx: TyCtxt<'_>, mod_name: &str) -> &'static mut llvm::TargetMachine {
@@ -117,7 +119,7 @@ pub fn create_target_machine(tcx: TyCtxt<'_>, mod_name: &str) -> &'static mut ll
tcx.backend_optimization_level(()),
tcx.global_backend_features(()),
)(config)
- .unwrap_or_else(|err| llvm_err(tcx.sess.diagnostic(), &err).raise())
+ .unwrap_or_else(|err| llvm_err(tcx.sess.diagnostic(), err).raise())
}
pub fn to_llvm_opt_settings(
@@ -240,9 +242,7 @@ pub fn target_machine_factory(
)
};
- tm.ok_or_else(|| {
- format!("Could not create LLVM TargetMachine for triple: {}", triple.to_str().unwrap())
- })
+ tm.ok_or_else(|| LlvmError::CreateTargetMachine { triple: triple.clone() })
})
}
@@ -355,25 +355,28 @@ unsafe extern "C" fn diagnostic_handler(info: &DiagnosticInfo, user: *mut c_void
};
if enabled {
- diag_handler.note_without_error(&format!(
- "{}:{}:{}: {}: {}",
- opt.filename, opt.line, opt.column, opt.pass_name, opt.message,
- ));
+ diag_handler.emit_note(FromLlvmOptimizationDiag {
+ filename: &opt.filename,
+ line: opt.line,
+ column: opt.column,
+ pass_name: &opt.pass_name,
+ message: &opt.message,
+ });
}
}
llvm::diagnostic::PGO(diagnostic_ref) | llvm::diagnostic::Linker(diagnostic_ref) => {
- let msg = llvm::build_string(|s| {
+ let message = llvm::build_string(|s| {
llvm::LLVMRustWriteDiagnosticInfoToString(diagnostic_ref, s)
})
.expect("non-UTF8 diagnostic");
- diag_handler.warn(&msg);
+ diag_handler.emit_warning(FromLlvmDiag { message });
}
llvm::diagnostic::Unsupported(diagnostic_ref) => {
- let msg = llvm::build_string(|s| {
+ let message = llvm::build_string(|s| {
llvm::LLVMRustWriteDiagnosticInfoToString(diagnostic_ref, s)
})
.expect("non-UTF8 diagnostic");
- diag_handler.err(&msg);
+ diag_handler.emit_err(FromLlvmDiag { message });
}
llvm::diagnostic::UnknownDiagnostic(..) => {}
}
@@ -409,11 +412,7 @@ fn get_pgo_sample_use_path(config: &ModuleConfig) -> Option<CString> {
}
fn get_instr_profile_output_path(config: &ModuleConfig) -> Option<CString> {
- if config.instrument_coverage {
- Some(CString::new("default_%m_%p.profraw").unwrap())
- } else {
- None
- }
+ config.instrument_coverage.then(|| CString::new("default_%m_%p.profraw").unwrap())
}
pub(crate) unsafe fn llvm_optimize(
@@ -443,16 +442,19 @@ pub(crate) unsafe fn llvm_optimize(
sanitize_thread: config.sanitizer.contains(SanitizerSet::THREAD),
sanitize_hwaddress: config.sanitizer.contains(SanitizerSet::HWADDRESS),
sanitize_hwaddress_recover: config.sanitizer_recover.contains(SanitizerSet::HWADDRESS),
+ sanitize_kernel_address: config.sanitizer.contains(SanitizerSet::KERNELADDRESS),
+ sanitize_kernel_address_recover: config
+ .sanitizer_recover
+ .contains(SanitizerSet::KERNELADDRESS),
})
} else {
None
};
- let mut llvm_profiler = if cgcx.prof.llvm_recording_enabled() {
- Some(LlvmSelfProfiler::new(cgcx.prof.get_self_profiler().unwrap()))
- } else {
- None
- };
+ let mut llvm_profiler = cgcx
+ .prof
+ .llvm_recording_enabled()
+ .then(|| LlvmSelfProfiler::new(cgcx.prof.get_self_profiler().unwrap()));
let llvm_selfprofiler =
llvm_profiler.as_mut().map(|s| s as *mut _ as *mut c_void).unwrap_or(std::ptr::null_mut());
@@ -494,7 +496,7 @@ pub(crate) unsafe fn llvm_optimize(
llvm_plugins.as_ptr().cast(),
llvm_plugins.len(),
);
- result.into_result().map_err(|()| llvm_err(diag_handler, "failed to run LLVM passes"))
+ result.into_result().map_err(|()| llvm_err(diag_handler, LlvmError::RunLlvmPasses))
}
// Unsafe due to LLVM calls.
@@ -547,8 +549,7 @@ pub(crate) fn link(
let _timer = cgcx.prof.generic_activity_with_arg("LLVM_link_module", &*module.name);
let buffer = ModuleBuffer::new(module.module_llvm.llmod());
linker.add(buffer.data()).map_err(|()| {
- let msg = format!("failed to serialize module {:?}", module.name);
- llvm_err(diag_handler, &msg)
+ llvm_err(diag_handler, LlvmError::SerializeModule { name: &module.name })
})?;
}
drop(linker);
@@ -626,9 +627,8 @@ pub(crate) unsafe fn codegen(
let _timer = cgcx
.prof
.generic_activity_with_arg("LLVM_module_codegen_emit_bitcode", &*module.name);
- if let Err(e) = fs::write(&bc_out, data) {
- let msg = format!("failed to write bytecode to {}: {}", bc_out.display(), e);
- diag_handler.err(&msg);
+ if let Err(err) = fs::write(&bc_out, data) {
+ diag_handler.emit_err(WriteBytecode { path: &bc_out, err });
}
}
@@ -678,10 +678,9 @@ pub(crate) unsafe fn codegen(
record_artifact_size(&cgcx.prof, "llvm_ir", &out);
}
- result.into_result().map_err(|()| {
- let msg = format!("failed to write LLVM IR to {}", out.display());
- llvm_err(diag_handler, &msg)
- })?;
+ result
+ .into_result()
+ .map_err(|()| llvm_err(diag_handler, LlvmError::WriteIr { path: &out }))?;
}
if config.emit_asm {
@@ -749,8 +748,8 @@ pub(crate) unsafe fn codegen(
EmitObj::Bitcode => {
debug!("copying bitcode {:?} to obj {:?}", bc_out, obj_out);
- if let Err(e) = link_or_copy(&bc_out, &obj_out) {
- diag_handler.err(&format!("failed to copy bitcode to object file: {}", e));
+ if let Err(err) = link_or_copy(&bc_out, &obj_out) {
+ diag_handler.emit_err(CopyBitcode { err });
}
if !config.emit_bc {
@@ -762,6 +761,7 @@ pub(crate) unsafe fn codegen(
EmitObj::None => {}
}
+ record_llvm_cgu_instructions_stats(&cgcx.prof, llmod);
drop(handlers);
}
@@ -975,3 +975,23 @@ fn record_artifact_size(
self_profiler_ref.artifact_size(artifact_kind, artifact_name.to_string_lossy(), file_size);
}
}
+
+fn record_llvm_cgu_instructions_stats(prof: &SelfProfilerRef, llmod: &llvm::Module) {
+ if !prof.enabled() {
+ return;
+ }
+
+ let raw_stats =
+ llvm::build_string(|s| unsafe { llvm::LLVMRustModuleInstructionStats(&llmod, s) })
+ .expect("cannot get module instruction stats");
+
+ #[derive(serde::Deserialize)]
+ struct InstructionsStats {
+ module: String,
+ total: u64,
+ }
+
+ let InstructionsStats { module, total } =
+ serde_json::from_str(&raw_stats).expect("cannot parse llvm cgu instructions stats");
+ prof.artifact_size("cgu_instructions", module, total);
+}
diff --git a/compiler/rustc_codegen_llvm/src/builder.rs b/compiler/rustc_codegen_llvm/src/builder.rs
index 5e98deae4..0f33b9854 100644
--- a/compiler/rustc_codegen_llvm/src/builder.rs
+++ b/compiler/rustc_codegen_llvm/src/builder.rs
@@ -511,7 +511,7 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
bx.range_metadata(load, scalar.valid_range(bx));
}
}
- abi::Pointer => {
+ abi::Pointer(_) => {
if !scalar.valid_range(bx).contains(0) {
bx.nonnull_metadata(load);
}
diff --git a/compiler/rustc_codegen_llvm/src/callee.rs b/compiler/rustc_codegen_llvm/src/callee.rs
index f1d01a460..6ee2a05ff 100644
--- a/compiler/rustc_codegen_llvm/src/callee.rs
+++ b/compiler/rustc_codegen_llvm/src/callee.rs
@@ -13,7 +13,7 @@ use crate::value::Value;
use rustc_codegen_ssa::traits::*;
use rustc_middle::ty::layout::{FnAbiOf, HasTyCtxt};
-use rustc_middle::ty::{self, Instance, TypeVisitable};
+use rustc_middle::ty::{self, Instance, TypeVisitableExt};
/// Codegens a reference to a fn/method item, monomorphizing and
/// inlining as it goes.
diff --git a/compiler/rustc_codegen_llvm/src/common.rs b/compiler/rustc_codegen_llvm/src/common.rs
index acee9134f..b0a9a30ab 100644
--- a/compiler/rustc_codegen_llvm/src/common.rs
+++ b/compiler/rustc_codegen_llvm/src/common.rs
@@ -10,6 +10,7 @@ use crate::value::Value;
use rustc_ast::Mutability;
use rustc_codegen_ssa::mir::place::PlaceRef;
use rustc_codegen_ssa::traits::*;
+use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
use rustc_hir::def_id::DefId;
use rustc_middle::bug;
use rustc_middle::mir::interpret::{ConstAllocation, GlobalAlloc, Scalar};
@@ -236,7 +237,7 @@ impl<'ll, 'tcx> ConstMethods<'tcx> for CodegenCx<'ll, 'tcx> {
Scalar::Int(int) => {
let data = int.assert_bits(layout.size(self));
let llval = self.const_uint_big(self.type_ix(bitsize), data);
- if layout.primitive() == Pointer {
+ if matches!(layout.primitive(), Pointer(_)) {
unsafe { llvm::LLVMConstIntToPtr(llval, llty) }
} else {
self.const_bitcast(llval, llty)
@@ -252,8 +253,13 @@ impl<'ll, 'tcx> ConstMethods<'tcx> for CodegenCx<'ll, 'tcx> {
Mutability::Mut => self.static_addr_of_mut(init, alloc.align, None),
_ => self.static_addr_of(init, alloc.align, None),
};
- if !self.sess().fewer_names() {
- llvm::set_value_name(value, format!("{:?}", alloc_id).as_bytes());
+ if !self.sess().fewer_names() && llvm::get_value_name(value).is_empty() {
+ let hash = self.tcx.with_stable_hashing_context(|mut hcx| {
+ let mut hasher = StableHasher::new();
+ alloc.hash_stable(&mut hcx, &mut hasher);
+ hasher.finish::<u128>()
+ });
+ llvm::set_value_name(value, format!("alloc_{hash:032x}").as_bytes());
}
(value, AddressSpace::DATA)
}
@@ -284,7 +290,7 @@ impl<'ll, 'tcx> ConstMethods<'tcx> for CodegenCx<'ll, 'tcx> {
1,
)
};
- if layout.primitive() != Pointer {
+ if !matches!(layout.primitive(), Pointer(_)) {
unsafe { llvm::LLVMConstPtrToInt(llval, llty) }
} else {
self.const_bitcast(llval, llty)
diff --git a/compiler/rustc_codegen_llvm/src/consts.rs b/compiler/rustc_codegen_llvm/src/consts.rs
index 16467b614..9116e71be 100644
--- a/compiler/rustc_codegen_llvm/src/consts.rs
+++ b/compiler/rustc_codegen_llvm/src/consts.rs
@@ -3,7 +3,6 @@ use crate::common::{self, CodegenCx};
use crate::debuginfo;
use crate::errors::{InvalidMinimumAlignment, SymbolAlreadyDefined};
use crate::llvm::{self, True};
-use crate::llvm_util;
use crate::type_::Type;
use crate::type_of::LayoutLlvmExt;
use crate::value::Value;
@@ -13,7 +12,7 @@ use rustc_codegen_ssa::traits::*;
use rustc_hir::def_id::DefId;
use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs};
use rustc_middle::mir::interpret::{
- read_target_uint, Allocation, ConstAllocation, ErrorHandled, GlobalAlloc, InitChunk, Pointer,
+ read_target_uint, Allocation, ConstAllocation, ErrorHandled, InitChunk, Pointer,
Scalar as InterpScalar,
};
use rustc_middle::mir::mono::MonoItem;
@@ -21,9 +20,7 @@ use rustc_middle::ty::layout::LayoutOf;
use rustc_middle::ty::{self, Instance, Ty};
use rustc_middle::{bug, span_bug};
use rustc_session::config::Lto;
-use rustc_target::abi::{
- AddressSpace, Align, HasDataLayout, Primitive, Scalar, Size, WrappingRange,
-};
+use rustc_target::abi::{Align, HasDataLayout, Primitive, Scalar, Size, WrappingRange};
use std::ops::Range;
pub fn const_alloc_to_llvm<'ll>(cx: &CodegenCx<'ll, '_>, alloc: ConstAllocation<'_>) -> &'ll Value {
@@ -58,13 +55,7 @@ pub fn const_alloc_to_llvm<'ll>(cx: &CodegenCx<'ll, '_>, alloc: ConstAllocation<
// to avoid the cost of generating large complex const expressions.
// For example, `[(u32, u8); 1024 * 1024]` contains uninit padding in each element,
// and would result in `{ [5 x i8] zeroinitializer, [3 x i8] undef, ...repeat 1M times... }`.
- let max = if llvm_util::get_version() < (14, 0, 0) {
- // Generating partially-uninit consts inhibits optimizations in LLVM < 14.
- // See https://github.com/rust-lang/rust/issues/84565.
- 1
- } else {
- cx.sess().opts.unstable_opts.uninit_const_chunk_threshold
- };
+ let max = cx.sess().opts.unstable_opts.uninit_const_chunk_threshold;
let allow_uninit_chunks = chunks.clone().take(max.saturating_add(1)).count() <= max;
if allow_uninit_chunks {
@@ -98,12 +89,7 @@ pub fn const_alloc_to_llvm<'ll>(cx: &CodegenCx<'ll, '_>, alloc: ConstAllocation<
.expect("const_alloc_to_llvm: could not read relocation pointer")
as u64;
- let address_space = match cx.tcx.global_alloc(alloc_id) {
- GlobalAlloc::Function(..) => cx.data_layout().instruction_address_space,
- GlobalAlloc::Static(..) | GlobalAlloc::Memory(..) | GlobalAlloc::VTable(..) => {
- AddressSpace::DATA
- }
- };
+ let address_space = cx.tcx.global_alloc(alloc_id).address_space(cx);
llvals.push(cx.scalar_to_backend(
InterpScalar::from_pointer(
@@ -111,7 +97,7 @@ pub fn const_alloc_to_llvm<'ll>(cx: &CodegenCx<'ll, '_>, alloc: ConstAllocation<
&cx.tcx,
),
Scalar::Initialized {
- value: Primitive::Pointer,
+ value: Primitive::Pointer(address_space),
valid_range: WrappingRange::full(dl.pointer_size),
},
cx.type_i8p_ext(address_space),
@@ -535,7 +521,7 @@ impl<'ll> StaticMethods for CodegenCx<'ll, '_> {
// The semantics of #[used] in Rust only require the symbol to make it into the
// object file. It is explicitly allowed for the linker to strip the symbol if it
- // is dead, which means we are allowed use `llvm.compiler.used` instead of
+ // is dead, which means we are allowed to use `llvm.compiler.used` instead of
// `llvm.used` here.
//
// Additionally, https://reviews.llvm.org/D97448 in LLVM 13 started emitting unique
@@ -546,7 +532,7 @@ impl<'ll> StaticMethods for CodegenCx<'ll, '_> {
// That said, we only ever emit these when compiling for ELF targets, unless
// `#[used(compiler)]` is explicitly requested. This is to avoid similar breakage
// on other targets, in particular MachO targets have *their* static constructor
- // lists broken if `llvm.compiler.used` is emitted rather than llvm.used. However,
+ // lists broken if `llvm.compiler.used` is emitted rather than `llvm.used`. However,
// that check happens when assigning the `CodegenFnAttrFlags` in `rustc_hir_analysis`,
// so we don't need to take care of it here.
self.add_compiler_used_global(g);
diff --git a/compiler/rustc_codegen_llvm/src/context.rs b/compiler/rustc_codegen_llvm/src/context.rs
index d9ccba07a..3d29968d5 100644
--- a/compiler/rustc_codegen_llvm/src/context.rs
+++ b/compiler/rustc_codegen_llvm/src/context.rs
@@ -143,24 +143,15 @@ pub unsafe fn create_module<'ll>(
let mut target_data_layout = sess.target.data_layout.to_string();
let llvm_version = llvm_util::get_version();
- if llvm_version < (14, 0, 0) {
- if sess.target.llvm_target == "i686-pc-windows-msvc"
- || sess.target.llvm_target == "i586-pc-windows-msvc"
- {
- target_data_layout =
- "e-m:x-p:32:32-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:32-n8:16:32-a:0:32-S32"
- .to_string();
- }
- if sess.target.arch == "wasm32" {
- target_data_layout = target_data_layout.replace("-p10:8:8-p20:8:8", "");
- }
- }
if llvm_version < (16, 0, 0) {
if sess.target.arch == "s390x" {
+ // LLVM 16 data layout changed to always set 64-bit vector alignment,
+ // which is conditional in earlier LLVM versions.
+ // https://reviews.llvm.org/D131158 for the discussion.
target_data_layout = target_data_layout.replace("-v128:64", "");
- }
-
- if sess.target.arch == "riscv64" {
+ } else if sess.target.arch == "riscv64" {
+ // LLVM 16 introduced this change so as to produce more efficient code.
+ // See https://reviews.llvm.org/D116735 for the discussion.
target_data_layout = target_data_layout.replace("-n32:64-", "-n64-");
}
}
@@ -191,7 +182,7 @@ pub unsafe fn create_module<'ll>(
//
// FIXME(#34960)
let cfg_llvm_root = option_env!("CFG_LLVM_ROOT").unwrap_or("");
- let custom_llvm_used = cfg_llvm_root.trim() != "";
+ let custom_llvm_used = !cfg_llvm_root.trim().is_empty();
if !custom_llvm_used && target_data_layout != llvm_data_layout {
bug!(
@@ -416,12 +407,8 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> {
let (llcx, llmod) = (&*llvm_module.llcx, llvm_module.llmod());
- let coverage_cx = if tcx.sess.instrument_coverage() {
- let covctx = coverageinfo::CrateCoverageContext::new();
- Some(covctx)
- } else {
- None
- };
+ let coverage_cx =
+ tcx.sess.instrument_coverage().then(coverageinfo::CrateCoverageContext::new);
let dbg_cx = if tcx.sess.opts.debuginfo != DebugInfo::None {
let dctx = debuginfo::CodegenUnitDebugContext::new(llmod);
@@ -533,14 +520,9 @@ impl<'ll, 'tcx> MiscMethods<'tcx> for CodegenCx<'ll, 'tcx> {
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(),
+ ty::Instance::resolve(tcx, ty::ParamEnv::reveal_all(), def_id, ty::List::empty())
+ .unwrap()
+ .unwrap(),
),
_ => {
let name = if wants_msvc_seh(self.sess()) {
diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs
index 22c61248b..240a9d2f3 100644
--- a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs
+++ b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs
@@ -1,6 +1,5 @@
use crate::common::CodegenCx;
use crate::coverageinfo;
-use crate::errors::InstrumentCoverageRequiresLLVM12;
use crate::llvm;
use llvm::coverageinfo::CounterMappingRegion;
@@ -19,8 +18,8 @@ use std::ffi::CString;
/// Generates and exports the Coverage Map.
///
-/// Rust Coverage Map generation supports LLVM Coverage Mapping Format versions
-/// 5 (LLVM 12, only) and 6 (zero-based encoded as 4 and 5, respectively), as defined at
+/// Rust Coverage Map generation supports LLVM Coverage Mapping Format version
+/// 6 (zero-based encoded as 5), as defined at
/// [LLVM Code Coverage Mapping Format](https://github.com/rust-lang/llvm-project/blob/rustc/13.0-2021-09-30/llvm/docs/CoverageMappingFormat.rst#llvm-code-coverage-mapping-format).
/// These versions are supported by the LLVM coverage tools (`llvm-profdata` and `llvm-cov`)
/// bundled with Rust's fork of LLVM.
@@ -33,13 +32,10 @@ use std::ffi::CString;
pub fn finalize(cx: &CodegenCx<'_, '_>) {
let tcx = cx.tcx;
- // Ensure the installed version of LLVM supports at least Coverage Map
- // Version 5 (encoded as a zero-based value: 4), which was introduced with
- // LLVM 12.
+ // Ensure the installed version of LLVM supports Coverage Map Version 6
+ // (encoded as a zero-based value: 5), which was introduced with LLVM 13.
let version = coverageinfo::mapping_version();
- if version < 4 {
- tcx.sess.emit_fatal(InstrumentCoverageRequiresLLVM12);
- }
+ assert_eq!(version, 5, "The `CoverageMappingVersion` exposed by `llvm-wrapper` is out of sync");
debug!("Generating coverage map for CodegenUnit: `{}`", cx.codegen_unit.name());
@@ -61,7 +57,7 @@ pub fn finalize(cx: &CodegenCx<'_, '_>) {
return;
}
- let mut mapgen = CoverageMapGenerator::new(tcx, version);
+ let mut mapgen = CoverageMapGenerator::new(tcx);
// Encode coverage mappings and generate function records
let mut function_data = Vec::new();
@@ -124,25 +120,18 @@ struct CoverageMapGenerator {
}
impl CoverageMapGenerator {
- fn new(tcx: TyCtxt<'_>, version: u32) -> Self {
+ fn new(tcx: TyCtxt<'_>) -> Self {
let mut filenames = FxIndexSet::default();
- if version >= 5 {
- // LLVM Coverage Mapping Format version 6 (zero-based encoded as 5)
- // requires setting the first filename to the compilation directory.
- // Since rustc generates coverage maps with relative paths, the
- // compilation directory can be combined with the relative paths
- // to get absolute paths, if needed.
- let working_dir = tcx
- .sess
- .opts
- .working_dir
- .remapped_path_if_available()
- .to_string_lossy()
- .to_string();
- let c_filename =
- CString::new(working_dir).expect("null error converting filename to C string");
- filenames.insert(c_filename);
- }
+ // LLVM Coverage Mapping Format version 6 (zero-based encoded as 5)
+ // requires setting the first filename to the compilation directory.
+ // Since rustc generates coverage maps with relative paths, the
+ // compilation directory can be combined with the relative paths
+ // to get absolute paths, if needed.
+ let working_dir =
+ tcx.sess.opts.working_dir.remapped_path_if_available().to_string_lossy().to_string();
+ let c_filename =
+ CString::new(working_dir).expect("null error converting filename to C string");
+ filenames.insert(c_filename);
Self { filenames }
}
@@ -306,9 +295,8 @@ fn add_unused_functions(cx: &CodegenCx<'_, '_>) {
DefKind::Fn | DefKind::AssocFn | DefKind::Closure | DefKind::Generator
) {
return None;
- } else if ignore_unused_generics
- && tcx.generics_of(def_id).requires_monomorphization(tcx)
- {
+ }
+ if ignore_unused_generics && tcx.generics_of(def_id).requires_monomorphization(tcx) {
return None;
}
Some(local_def_id.to_def_id())
diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs
index ace15cfb0..3dc0ac033 100644
--- a/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs
+++ b/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs
@@ -27,8 +27,6 @@ use rustc_middle::ty::Instance;
use std::cell::RefCell;
use std::ffi::CString;
-use std::iter;
-
pub mod mapgen;
const UNUSED_FUNCTION_COUNTER_ID: CounterValueReference = CounterValueReference::START;
@@ -201,7 +199,7 @@ fn declare_unused_fn<'tcx>(cx: &CodegenCx<'_, 'tcx>, def_id: DefId) -> Instance<
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()],
tcx.mk_unit(),
false,
hir::Unsafety::Unsafe,
diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs
index b6eb5ee18..c1b3f34e5 100644
--- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs
+++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs
@@ -132,7 +132,7 @@ fn build_fixed_size_array_di_node<'ll, 'tcx>(
let (size, align) = cx.size_and_align_of(array_type);
- let upper_bound = len.eval_usize(cx.tcx, ty::ParamEnv::reveal_all()) as c_longlong;
+ let upper_bound = len.eval_target_usize(cx.tcx, ty::ParamEnv::reveal_all()) as c_longlong;
let subrange =
unsafe { Some(llvm::LLVMRustDIBuilderGetOrCreateSubrange(DIB(cx), 0, upper_bound)) };
@@ -1499,6 +1499,11 @@ pub fn create_vtable_di_node<'ll, 'tcx>(
return;
}
+ // When full debuginfo is enabled, we want to try and prevent vtables from being
+ // merged. Otherwise debuggers will have a hard time mapping from dyn pointer
+ // to concrete type.
+ llvm::SetUnnamedAddress(vtable, llvm::UnnamedAddr::No);
+
let vtable_name =
compute_debuginfo_vtable_name(cx.tcx, ty, poly_trait_ref, VTableNameKind::GlobalVariable);
let vtable_type_di_node = build_vtable_type_di_node(cx, ty, poly_trait_ref);
diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs
index 564ab351b..54e850f25 100644
--- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs
+++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs
@@ -122,7 +122,8 @@ fn tag_base_type<'ll, 'tcx>(
Primitive::Int(t, _) => t,
Primitive::F32 => Integer::I32,
Primitive::F64 => Integer::I64,
- Primitive::Pointer => {
+ // FIXME(erikdesjardins): handle non-default addrspace ptr sizes
+ Primitive::Pointer(_) => {
// If the niche is the NULL value of a reference, then `discr_enum_ty` will be
// a RawPtr. CodeView doesn't know what to do with enums whose base type is a
// pointer so we fix this up to just be `usize`.
diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs b/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs
index ca7a07d83..5392534cf 100644
--- a/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs
+++ b/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs
@@ -27,7 +27,7 @@ use rustc_index::vec::IndexVec;
use rustc_middle::mir;
use rustc_middle::ty::layout::LayoutOf;
use rustc_middle::ty::subst::{GenericArgKind, SubstsRef};
-use rustc_middle::ty::{self, Instance, ParamEnv, Ty, TypeVisitable};
+use rustc_middle::ty::{self, Instance, ParamEnv, Ty, TypeVisitableExt};
use rustc_session::config::{self, DebugInfo};
use rustc_session::Session;
use rustc_span::symbol::Symbol;
@@ -508,7 +508,7 @@ impl<'ll, 'tcx> DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> {
let impl_self_ty = cx.tcx.subst_and_normalize_erasing_regions(
instance.substs,
ty::ParamEnv::reveal_all(),
- cx.tcx.type_of(impl_def_id),
+ cx.tcx.type_of(impl_def_id).skip_binder(),
);
// Only "class" methods are generally understood by LLVM,
diff --git a/compiler/rustc_codegen_llvm/src/errors.rs b/compiler/rustc_codegen_llvm/src/errors.rs
index b46209972..bae88d942 100644
--- a/compiler/rustc_codegen_llvm/src/errors.rs
+++ b/compiler/rustc_codegen_llvm/src/errors.rs
@@ -1,10 +1,12 @@
use std::borrow::Cow;
-
-use rustc_errors::fluent;
-use rustc_errors::DiagnosticBuilder;
-use rustc_errors::ErrorGuaranteed;
-use rustc_errors::Handler;
-use rustc_errors::IntoDiagnostic;
+use std::ffi::CString;
+use std::path::Path;
+
+use crate::fluent_generated as fluent;
+use rustc_data_structures::small_c_str::SmallCStr;
+use rustc_errors::{
+ DiagnosticBuilder, EmissionGuarantee, ErrorGuaranteed, Handler, IntoDiagnostic,
+};
use rustc_macros::{Diagnostic, Subdiagnostic};
use rustc_span::Span;
@@ -26,9 +28,9 @@ pub(crate) struct UnknownCTargetFeature<'a> {
#[derive(Subdiagnostic)]
pub(crate) enum PossibleFeature<'a> {
- #[help(possible_feature)]
+ #[help(codegen_llvm_possible_feature)]
Some { rust_feature: &'a str },
- #[help(consider_filing_feature_request)]
+ #[help(codegen_llvm_consider_filing_feature_request)]
None,
}
@@ -40,10 +42,6 @@ pub(crate) struct ErrorCreatingImportLibrary<'a> {
}
#[derive(Diagnostic)]
-#[diag(codegen_llvm_instrument_coverage_requires_llvm_12)]
-pub(crate) struct InstrumentCoverageRequiresLLVM12;
-
-#[derive(Diagnostic)]
#[diag(codegen_llvm_symbol_already_defined)]
pub(crate) struct SymbolAlreadyDefined<'a> {
#[primary_span]
@@ -85,10 +83,18 @@ pub(crate) struct DlltoolFailImportLibrary<'a> {
#[note]
pub(crate) struct DynamicLinkingWithLTO;
-#[derive(Diagnostic)]
-#[diag(codegen_llvm_fail_parsing_target_machine_config_to_target_machine)]
-pub(crate) struct FailParsingTargetMachineConfigToTargetMachine {
- pub error: String,
+pub(crate) struct ParseTargetMachineConfig<'a>(pub LlvmError<'a>);
+
+impl<EM: EmissionGuarantee> IntoDiagnostic<'_, EM> for ParseTargetMachineConfig<'_> {
+ fn into_diagnostic(self, sess: &'_ Handler) -> DiagnosticBuilder<'_, EM> {
+ let diag: DiagnosticBuilder<'_, EM> = self.0.into_diagnostic(sess);
+ let (message, _) = diag.styled_message().first().expect("`LlvmError` with no message");
+ let message = sess.eagerly_translate_to_string(message.clone(), diag.args());
+
+ let mut diag = sess.struct_diagnostic(fluent::codegen_llvm_parse_target_machine_config);
+ diag.set_arg("error", message);
+ diag
+ }
}
pub(crate) struct TargetFeatureDisableOrEnable<'a> {
@@ -114,3 +120,99 @@ impl IntoDiagnostic<'_, ErrorGuaranteed> for TargetFeatureDisableOrEnable<'_> {
diag
}
}
+
+#[derive(Diagnostic)]
+#[diag(codegen_llvm_lto_disallowed)]
+pub(crate) struct LtoDisallowed;
+
+#[derive(Diagnostic)]
+#[diag(codegen_llvm_lto_dylib)]
+pub(crate) struct LtoDylib;
+
+#[derive(Diagnostic)]
+#[diag(codegen_llvm_lto_bitcode_from_rlib)]
+pub(crate) struct LtoBitcodeFromRlib {
+ pub llvm_err: String,
+}
+
+#[derive(Diagnostic)]
+pub enum LlvmError<'a> {
+ #[diag(codegen_llvm_write_output)]
+ WriteOutput { path: &'a Path },
+ #[diag(codegen_llvm_target_machine)]
+ CreateTargetMachine { triple: SmallCStr },
+ #[diag(codegen_llvm_run_passes)]
+ RunLlvmPasses,
+ #[diag(codegen_llvm_serialize_module)]
+ SerializeModule { name: &'a str },
+ #[diag(codegen_llvm_write_ir)]
+ WriteIr { path: &'a Path },
+ #[diag(codegen_llvm_prepare_thin_lto_context)]
+ PrepareThinLtoContext,
+ #[diag(codegen_llvm_load_bitcode)]
+ LoadBitcode { name: CString },
+ #[diag(codegen_llvm_write_thinlto_key)]
+ WriteThinLtoKey { err: std::io::Error },
+ #[diag(codegen_llvm_multiple_source_dicompileunit)]
+ MultipleSourceDiCompileUnit,
+ #[diag(codegen_llvm_prepare_thin_lto_module)]
+ PrepareThinLtoModule,
+ #[diag(codegen_llvm_parse_bitcode)]
+ ParseBitcode,
+}
+
+pub(crate) struct WithLlvmError<'a>(pub LlvmError<'a>, pub String);
+
+impl<EM: EmissionGuarantee> IntoDiagnostic<'_, EM> for WithLlvmError<'_> {
+ fn into_diagnostic(self, sess: &'_ Handler) -> DiagnosticBuilder<'_, EM> {
+ use LlvmError::*;
+ let msg_with_llvm_err = match &self.0 {
+ WriteOutput { .. } => fluent::codegen_llvm_write_output_with_llvm_err,
+ CreateTargetMachine { .. } => fluent::codegen_llvm_target_machine_with_llvm_err,
+ RunLlvmPasses => fluent::codegen_llvm_run_passes_with_llvm_err,
+ SerializeModule { .. } => fluent::codegen_llvm_serialize_module_with_llvm_err,
+ WriteIr { .. } => fluent::codegen_llvm_write_ir_with_llvm_err,
+ PrepareThinLtoContext => fluent::codegen_llvm_prepare_thin_lto_context_with_llvm_err,
+ LoadBitcode { .. } => fluent::codegen_llvm_load_bitcode_with_llvm_err,
+ WriteThinLtoKey { .. } => fluent::codegen_llvm_write_thinlto_key_with_llvm_err,
+ MultipleSourceDiCompileUnit => {
+ fluent::codegen_llvm_multiple_source_dicompileunit_with_llvm_err
+ }
+ PrepareThinLtoModule => fluent::codegen_llvm_prepare_thin_lto_module_with_llvm_err,
+ ParseBitcode => fluent::codegen_llvm_parse_bitcode_with_llvm_err,
+ };
+ let mut diag = self.0.into_diagnostic(sess);
+ diag.set_primary_message(msg_with_llvm_err);
+ diag.set_arg("llvm_err", self.1);
+ diag
+ }
+}
+
+#[derive(Diagnostic)]
+#[diag(codegen_llvm_from_llvm_optimization_diag)]
+pub(crate) struct FromLlvmOptimizationDiag<'a> {
+ pub filename: &'a str,
+ pub line: std::ffi::c_uint,
+ pub column: std::ffi::c_uint,
+ pub pass_name: &'a str,
+ pub message: &'a str,
+}
+
+#[derive(Diagnostic)]
+#[diag(codegen_llvm_from_llvm_diag)]
+pub(crate) struct FromLlvmDiag {
+ pub message: String,
+}
+
+#[derive(Diagnostic)]
+#[diag(codegen_llvm_write_bytecode)]
+pub(crate) struct WriteBytecode<'a> {
+ pub path: &'a Path,
+ pub err: std::io::Error,
+}
+
+#[derive(Diagnostic)]
+#[diag(codegen_llvm_copy_bitcode)]
+pub(crate) struct CopyBitcode {
+ pub err: std::io::Error,
+}
diff --git a/compiler/rustc_codegen_llvm/src/intrinsic.rs b/compiler/rustc_codegen_llvm/src/intrinsic.rs
index a6a75eff9..39afb4af6 100644
--- a/compiler/rustc_codegen_llvm/src/intrinsic.rs
+++ b/compiler/rustc_codegen_llvm/src/intrinsic.rs
@@ -22,7 +22,6 @@ use rustc_target::abi::{self, Align, HasDataLayout, Primitive};
use rustc_target::spec::{HasTargetSpec, PanicStrategy};
use std::cmp::Ordering;
-use std::iter;
fn get_simple_intrinsic<'ll>(
cx: &CodegenCx<'ll, '_>,
@@ -149,7 +148,7 @@ impl<'ll, 'tcx> IntrinsicCallMethods<'tcx> for Builder<'_, 'll, 'tcx> {
emit_va_arg(self, args[0], ret_ty)
}
}
- Primitive::F64 | Primitive::Pointer => {
+ Primitive::F64 | Primitive::Pointer(_) => {
emit_va_arg(self, args[0], ret_ty)
}
// `va_arg` should never be used with the return type f32.
@@ -798,7 +797,7 @@ fn get_rust_try_fn<'ll, 'tcx>(
let i8p = tcx.mk_mut_ptr(tcx.types.i8);
// `unsafe fn(*mut i8) -> ()`
let try_fn_ty = tcx.mk_fn_ptr(ty::Binder::dummy(tcx.mk_fn_sig(
- iter::once(i8p),
+ [i8p],
tcx.mk_unit(),
false,
hir::Unsafety::Unsafe,
@@ -806,7 +805,7 @@ fn get_rust_try_fn<'ll, 'tcx>(
)));
// `unsafe fn(*mut i8, *mut i8) -> ()`
let catch_fn_ty = tcx.mk_fn_ptr(ty::Binder::dummy(tcx.mk_fn_sig(
- [i8p, i8p].iter().cloned(),
+ [i8p, i8p],
tcx.mk_unit(),
false,
hir::Unsafety::Unsafe,
@@ -814,7 +813,7 @@ fn get_rust_try_fn<'ll, 'tcx>(
)));
// `unsafe fn(unsafe fn(*mut i8) -> (), *mut i8, unsafe fn(*mut i8, *mut i8) -> ()) -> i32`
let rust_fn_sig = ty::Binder::dummy(cx.tcx.mk_fn_sig(
- [try_fn_ty, i8p, catch_fn_ty].into_iter(),
+ [try_fn_ty, i8p, catch_fn_ty],
tcx.types.i32,
false,
hir::Unsafety::Unsafe,
@@ -877,7 +876,7 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
ty::Uint(i) if i.bit_width() == Some(expected_int_bits) => args[0].immediate(),
ty::Array(elem, len)
if matches!(elem.kind(), ty::Uint(ty::UintTy::U8))
- && len.try_eval_usize(bx.tcx, ty::ParamEnv::reveal_all())
+ && len.try_eval_target_usize(bx.tcx, ty::ParamEnv::reveal_all())
== Some(expected_bytes) =>
{
let place = PlaceRef::alloca(bx, args[0].layout);
@@ -957,9 +956,9 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
// 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")
- })
+ len.try_eval_target_usize(bx.cx.tcx, ty::ParamEnv::reveal_all()).unwrap_or_else(
+ || span_bug!(span, "could not evaluate shuffle index array length"),
+ )
}
_ => return_error!(InvalidMonomorphization::SimdShuffle {
span,
@@ -1123,7 +1122,7 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
}
ty::Array(elem, len)
if matches!(elem.kind(), ty::Uint(ty::UintTy::U8))
- && len.try_eval_usize(bx.tcx, ty::ParamEnv::reveal_all())
+ && len.try_eval_target_usize(bx.tcx, ty::ParamEnv::reveal_all())
== Some(expected_bytes) =>
{
// Zero-extend iN to the array length:
diff --git a/compiler/rustc_codegen_llvm/src/lib.rs b/compiler/rustc_codegen_llvm/src/lib.rs
index 246e82545..c41e74c51 100644
--- a/compiler/rustc_codegen_llvm/src/lib.rs
+++ b/compiler/rustc_codegen_llvm/src/lib.rs
@@ -5,11 +5,12 @@
//! This API is completely unstable and subject to change.
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
+#![feature(extern_types)]
#![feature(hash_raw_entry)]
+#![feature(iter_intersperse)]
#![feature(let_chains)]
-#![feature(extern_types)]
+#![feature(never_type)]
#![feature(once_cell)]
-#![feature(iter_intersperse)]
#![recursion_limit = "256"]
#![allow(rustc::potential_query_instability)]
#![deny(rustc::untranslatable_diagnostic)]
@@ -22,7 +23,7 @@ extern crate tracing;
use back::write::{create_informational_target_machine, create_target_machine};
-use errors::FailParsingTargetMachineConfigToTargetMachine;
+use errors::ParseTargetMachineConfig;
pub use llvm_util::target_features;
use rustc_ast::expand::allocator::AllocatorKind;
use rustc_codegen_ssa::back::lto::{LtoModuleCodegen, SerializedModule, ThinModule};
@@ -33,7 +34,8 @@ use rustc_codegen_ssa::traits::*;
use rustc_codegen_ssa::ModuleCodegen;
use rustc_codegen_ssa::{CodegenResults, CompiledModule};
use rustc_data_structures::fx::FxHashMap;
-use rustc_errors::{ErrorGuaranteed, FatalError, Handler};
+use rustc_errors::{DiagnosticMessage, ErrorGuaranteed, FatalError, Handler, SubdiagnosticMessage};
+use rustc_macros::fluent_messages;
use rustc_metadata::EncodedMetadata;
use rustc_middle::dep_graph::{WorkProduct, WorkProductId};
use rustc_middle::ty::query::Providers;
@@ -82,6 +84,8 @@ mod type_of;
mod va_arg;
mod value;
+fluent_messages! { "../locales/en-US.ftl" }
+
#[derive(Clone)]
pub struct LlvmCodegenBackend(());
@@ -169,6 +173,7 @@ impl WriteBackendMethods for LlvmCodegenBackend {
type Module = ModuleLlvm;
type ModuleBuffer = back::lto::ModuleBuffer;
type TargetMachine = &'static mut llvm::TargetMachine;
+ type TargetMachineError = crate::errors::LlvmError<'static>;
type ThinData = back::lto::ThinData;
type ThinBuffer = back::lto::ThinBuffer;
fn print_pass_timings(&self) {
@@ -244,6 +249,10 @@ impl LlvmCodegenBackend {
}
impl CodegenBackend for LlvmCodegenBackend {
+ fn locale_resource(&self) -> &'static str {
+ crate::DEFAULT_LOCALE_RESOURCE
+ }
+
fn init(&self, sess: &Session) {
llvm_util::init(sess); // Make sure llvm is inited
}
@@ -416,8 +425,7 @@ impl ModuleLlvm {
let tm = match (cgcx.tm_factory)(tm_factory_config) {
Ok(m) => m,
Err(e) => {
- handler.emit_err(FailParsingTargetMachineConfigToTargetMachine { error: e });
- return Err(FatalError);
+ return Err(handler.emit_almost_fatal(ParseTargetMachineConfig(e)));
}
};
diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
index 8b4861962..253c2ca7c 100644
--- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
+++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
@@ -482,6 +482,8 @@ pub struct SanitizerOptions {
pub sanitize_thread: bool,
pub sanitize_hwaddress: bool,
pub sanitize_hwaddress_recover: bool,
+ pub sanitize_kernel_address: bool,
+ pub sanitize_kernel_address_recover: bool,
}
/// LLVMRelocMode
@@ -1812,8 +1814,6 @@ extern "C" {
/// Creates a legacy pass manager -- only used for final codegen.
pub fn LLVMCreatePassManager<'a>() -> &'a mut PassManager<'a>;
- pub fn LLVMInitializePasses();
-
pub fn LLVMTimeTraceProfilerInitialize();
pub fn LLVMTimeTraceProfilerFinishThread();
@@ -2408,6 +2408,8 @@ extern "C" {
pub fn LLVMRustModuleBufferLen(p: &ModuleBuffer) -> usize;
pub fn LLVMRustModuleBufferFree(p: &'static mut ModuleBuffer);
pub fn LLVMRustModuleCost(M: &Module) -> u64;
+ #[allow(improper_ctypes)]
+ pub fn LLVMRustModuleInstructionStats(M: &Module, Str: &RustString);
pub fn LLVMRustThinLTOBufferCreate(M: &Module, is_thin: bool) -> &'static mut ThinLTOBuffer;
pub fn LLVMRustThinLTOBufferFree(M: &'static mut ThinLTOBuffer);
diff --git a/compiler/rustc_codegen_llvm/src/llvm_util.rs b/compiler/rustc_codegen_llvm/src/llvm_util.rs
index 79b243f73..ba58a2e68 100644
--- a/compiler/rustc_codegen_llvm/src/llvm_util.rs
+++ b/compiler/rustc_codegen_llvm/src/llvm_util.rs
@@ -120,8 +120,6 @@ unsafe fn configure_llvm(sess: &Session) {
llvm::LLVMTimeTraceProfilerInitialize();
}
- llvm::LLVMInitializePasses();
-
rustc_llvm::initialize_available_targets();
llvm::LLVMRustSetLLVMOptions(llvm_args.len() as c_int, llvm_args.as_ptr());
@@ -152,13 +150,7 @@ pub fn time_trace_profiler_finish(file_name: &Path) {
pub fn to_llvm_features<'a>(sess: &Session, s: &'a str) -> SmallVec<[&'a str; 2]> {
let arch = if sess.target.arch == "x86_64" { "x86" } else { &*sess.target.arch };
match (arch, s) {
- ("x86", "sse4.2") => {
- if get_version() >= (14, 0, 0) {
- smallvec!["sse4.2", "crc32"]
- } else {
- smallvec!["sse4.2"]
- }
- }
+ ("x86", "sse4.2") => smallvec!["sse4.2", "crc32"],
("x86", "pclmulqdq") => smallvec!["pclmul"],
("x86", "rdrand") => smallvec!["rdrnd"],
("x86", "bmi1") => smallvec!["bmi"],
@@ -217,7 +209,7 @@ pub fn check_tied_features(
/// Must express features in the way Rust understands them
pub fn target_features(sess: &Session, allow_unstable: bool) -> Vec<Symbol> {
let target_machine = create_informational_target_machine(sess);
- let mut features: Vec<Symbol> = supported_target_features(sess)
+ supported_target_features(sess)
.iter()
.filter_map(|&(feature, gate)| {
if sess.is_nightly_build() || allow_unstable || gate.is_none() {
@@ -237,16 +229,7 @@ pub fn target_features(sess: &Session, allow_unstable: bool) -> Vec<Symbol> {
true
})
.map(|feature| Symbol::intern(feature))
- .collect();
-
- // LLVM 14 changed the ABI for i128 arguments to __float/__fix builtins on Win64
- // (see https://reviews.llvm.org/D110413). This unstable target feature is intended for use
- // by compiler-builtins, to export the builtins with the expected, LLVM-version-dependent ABI.
- // The target feature can be dropped once we no longer support older LLVM versions.
- if sess.is_nightly_build() && get_version() >= (14, 0, 0) {
- features.push(Symbol::intern("llvm14-builtins-abi"));
- }
- features
+ .collect()
}
pub fn print_version() {
@@ -494,11 +477,6 @@ pub(crate) fn global_llvm_features(sess: &Session, diagnostics: bool) -> Vec<Str
.flatten();
features.extend(feats);
- // FIXME: Move v8a to target definition list when earliest supported LLVM is 14.
- if get_version() >= (14, 0, 0) && sess.target.arch == "aarch64" {
- features.push("+v8a".into());
- }
-
if diagnostics && let Some(f) = check_tied_features(sess, &featsmap) {
sess.emit_err(TargetFeatureDisableOrEnable {
features: f,
diff --git a/compiler/rustc_codegen_llvm/src/mono_item.rs b/compiler/rustc_codegen_llvm/src/mono_item.rs
index 76f692b20..d0ae36349 100644
--- a/compiler/rustc_codegen_llvm/src/mono_item.rs
+++ b/compiler/rustc_codegen_llvm/src/mono_item.rs
@@ -9,7 +9,7 @@ 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::{FnAbiOf, LayoutOf};
-use rustc_middle::ty::{self, Instance, TypeVisitable};
+use rustc_middle::ty::{self, Instance, TypeVisitableExt};
use rustc_session::config::CrateType;
use rustc_target::spec::RelocModel;
diff --git a/compiler/rustc_codegen_llvm/src/type_of.rs b/compiler/rustc_codegen_llvm/src/type_of.rs
index 75cd5df97..e264ce78f 100644
--- a/compiler/rustc_codegen_llvm/src/type_of.rs
+++ b/compiler/rustc_codegen_llvm/src/type_of.rs
@@ -1,13 +1,12 @@
use crate::common::*;
use crate::context::TypeLowering;
-use crate::llvm_util::get_version;
use crate::type_::Type;
use rustc_codegen_ssa::traits::*;
use rustc_middle::bug;
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, TypeVisitable};
-use rustc_target::abi::{Abi, AddressSpace, Align, FieldsShape};
+use rustc_middle::ty::{self, Ty, TypeVisitableExt};
+use rustc_target::abi::{Abi, Align, FieldsShape};
use rustc_target::abi::{Int, Pointer, F32, F64};
use rustc_target::abi::{PointeeInfo, Scalar, Size, TyAbiInterface, Variants};
use smallvec::{smallvec, SmallVec};
@@ -43,10 +42,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
- // For performance reasons we use names only when emitting LLVM IR. Unless we are on
- // LLVM < 14, where the use of unnamed types resulted in various issues, e.g., #76213,
- // #79564, and #79246.
- if get_version() < (14, 0, 0) || !cx.sess().fewer_names() =>
+ // For performance reasons we use names only when emitting LLVM IR.
+ if !cx.sess().fewer_names() =>
{
let mut name = with_no_visible_paths!(with_no_trimmed_paths!(layout.ty.to_string()));
if let (&ty::Adt(def, _), &Variants::Single { index }) =
@@ -157,7 +154,7 @@ fn struct_llfields<'a, 'tcx>(
} else {
debug!("struct_llfields: offset: {:?} stride: {:?}", offset, layout.size);
}
- let field_remapping = if padding_used { Some(field_remapping) } else { None };
+ let field_remapping = padding_used.then_some(field_remapping);
(result, packed, field_remapping)
}
@@ -312,14 +309,13 @@ impl<'tcx> LayoutLlvmExt<'tcx> for TyAndLayout<'tcx> {
Int(i, _) => cx.type_from_integer(i),
F32 => cx.type_f32(),
F64 => cx.type_f64(),
- Pointer => {
+ Pointer(address_space) => {
// If we know the alignment, pick something better than i8.
- let (pointee, address_space) =
- if let Some(pointee) = self.pointee_info_at(cx, offset) {
- (cx.type_pointee_for_align(pointee.align), pointee.address_space)
- } else {
- (cx.type_i8(), AddressSpace::DATA)
- };
+ 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_ext(pointee, address_space)
}
}
@@ -333,7 +329,7 @@ impl<'tcx> LayoutLlvmExt<'tcx> for TyAndLayout<'tcx> {
) -> &'a Type {
// HACK(eddyb) special-case fat pointers until LLVM removes
// pointee types, to avoid bitcasting every `OperandRef::deref`.
- match self.ty.kind() {
+ match *self.ty.kind() {
ty::Ref(..) | ty::RawPtr(_) => {
return self.field(cx, index).llvm_type(cx);
}
@@ -343,6 +339,11 @@ impl<'tcx> LayoutLlvmExt<'tcx> for TyAndLayout<'tcx> {
let ptr_ty = cx.tcx.mk_mut_ptr(self.ty.boxed_ty());
return cx.layout_of(ptr_ty).scalar_pair_element_llvm_type(cx, index, immediate);
}
+ // `dyn* Trait` has the same ABI as `*mut dyn Trait`
+ ty::Dynamic(bounds, region, ty::DynStar) => {
+ let ptr_ty = cx.tcx.mk_mut_ptr(cx.tcx.mk_dynamic(bounds, region, ty::Dyn));
+ return cx.layout_of(ptr_ty).scalar_pair_element_llvm_type(cx, index, immediate);
+ }
_ => {}
}
diff --git a/compiler/rustc_codegen_ssa/Cargo.toml b/compiler/rustc_codegen_ssa/Cargo.toml
index 0d2d2ec68..c55991e00 100644
--- a/compiler/rustc_codegen_ssa/Cargo.toml
+++ b/compiler/rustc_codegen_ssa/Cargo.toml
@@ -41,7 +41,6 @@ rustc_metadata = { path = "../rustc_metadata" }
rustc_query_system = { path = "../rustc_query_system" }
rustc_target = { path = "../rustc_target" }
rustc_session = { path = "../rustc_session" }
-rustc_const_eval = { path = "../rustc_const_eval" }
[dependencies.object]
version = "0.30.1"
diff --git a/compiler/rustc_error_messages/locales/en-US/codegen_ssa.ftl b/compiler/rustc_codegen_ssa/locales/en-US.ftl
index c8c7afb5f..8fe5f8d50 100644
--- a/compiler/rustc_error_messages/locales/en-US/codegen_ssa.ftl
+++ b/compiler/rustc_codegen_ssa/locales/en-US.ftl
@@ -22,7 +22,7 @@ codegen_ssa_ignoring_output = ignoring -o because multiple .{$extension} files w
codegen_ssa_create_temp_dir = couldn't create a temp dir: {$error}
-codegen_ssa_incompatible_linking_modifiers = the linking modifiers `+bundle` and `+whole-archive` are not compatible with each other when generating rlibs
+codegen_ssa_incompatible_linking_modifiers = link modifiers combination `+bundle,+whole-archive` is unstable when generating rlibs
codegen_ssa_add_native_library = failed to add native library {$library_path}: {$error}
@@ -179,9 +179,9 @@ codegen_ssa_extract_bundled_libs_write_file = failed to write file '{$rlib}': {$
codegen_ssa_unsupported_arch = unsupported arch `{$arch}` for os `{$os}`
-codegen_ssa_apple_sdk_error_sdk_path = failed to get {$sdk_name} SDK path: {error}
+codegen_ssa_apple_sdk_error_sdk_path = failed to get {$sdk_name} SDK path: {$error}
-codegen_ssa_read_file = failed to read file: {message}
+codegen_ssa_read_file = failed to read file: {$message}
codegen_ssa_unsupported_link_self_contained = option `-C link-self-contained` is not supported on this target
diff --git a/compiler/rustc_codegen_ssa/src/back/archive.rs b/compiler/rustc_codegen_ssa/src/back/archive.rs
index d3cd085cf..66ec8f5f5 100644
--- a/compiler/rustc_codegen_ssa/src/back/archive.rs
+++ b/compiler/rustc_codegen_ssa/src/back/archive.rs
@@ -203,7 +203,7 @@ impl<'a> ArchiveBuilder<'a> for ArArchiveBuilder<'a> {
}
}
- self.src_archives.push((archive_path.to_owned(), archive_map));
+ self.src_archives.push((archive_path, archive_map));
Ok(())
}
diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs
index 34e042376..8bb143ed3 100644
--- a/compiler/rustc_codegen_ssa/src/back/link.rs
+++ b/compiler/rustc_codegen_ssa/src/back/link.rs
@@ -270,10 +270,9 @@ pub fn each_linked_rlib(
/// Create an 'rlib'.
///
-/// An rlib in its current incarnation is essentially a renamed .a file. The rlib primarily contains
-/// the object file of the crate, but it also contains all of the object files from native
-/// libraries. This is done by unzipping native libraries and inserting all of the contents into
-/// this archive.
+/// An rlib in its current incarnation is essentially a renamed .a file (with "dummy" object files).
+/// The rlib primarily contains the object file of the crate, but it also some of the object files
+/// from native libraries.
fn link_rlib<'a>(
sess: &'a Session,
archive_builder_builder: &dyn ArchiveBuilderBuilder,
@@ -347,44 +346,23 @@ fn link_rlib<'a>(
// loaded from the libraries found here and then encode that into the
// 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 && sess.opts.unstable_opts.packed_bundled_libs => {}
- 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.emit_err(errors::IncompatibleLinkingModifiers);
- }
- NativeLibKind::Static { bundle: None | Some(true), .. } => {}
- NativeLibKind::Static { bundle: Some(false), .. }
- | NativeLibKind::Dylib { .. }
- | NativeLibKind::Framework { .. }
- | NativeLibKind::RawDylib
- | NativeLibKind::LinkArg
- | NativeLibKind::Unspecified => continue,
- }
- if let Some(name) = lib.name {
- let location =
+ let NativeLibKind::Static { bundle: None | Some(true), whole_archive } = lib.kind else {
+ continue;
+ };
+ if whole_archive == Some(true) && !codegen_results.crate_info.feature_packed_bundled_libs {
+ sess.emit_err(errors::IncompatibleLinkingModifiers);
+ }
+ if flavor == RlibFlavor::Normal && let Some(filename) = lib.filename {
+ let path = find_native_static_library(filename.as_str(), true, &lib_search_paths, sess);
+ let src = read(path).map_err(|e| sess.emit_fatal(errors::ReadFileError {message: e }))?;
+ let (data, _) = create_wrapper_file(sess, b".bundled_lib".to_vec(), &src);
+ let wrapper_file = emit_wrapper_file(sess, &data, tmpdir, filename.as_str());
+ packed_bundled_libs.push(wrapper_file);
+ } else if let Some(name) = lib.name {
+ let path =
find_native_static_library(name.as_str(), lib.verbatim, &lib_search_paths, sess);
- if sess.opts.unstable_opts.packed_bundled_libs && flavor == RlibFlavor::Normal {
- let filename = lib.filename.unwrap();
- let lib_path =
- find_native_static_library(filename.as_str(), true, &lib_search_paths, sess);
- let src = read(lib_path)
- .map_err(|e| sess.emit_fatal(errors::ReadFileError { message: e }))?;
- let (data, _) = create_wrapper_file(sess, b".bundled_lib".to_vec(), &src);
- let wrapper_file = emit_wrapper_file(sess, &data, tmpdir, filename.as_str());
- packed_bundled_libs.push(wrapper_file);
- continue;
- }
- ab.add_archive(&location, Box::new(|_| false)).unwrap_or_else(|error| {
- sess.emit_fatal(errors::AddNativeLibrary { library_path: location, error });
- });
+ ab.add_archive(&path, Box::new(|_| false)).unwrap_or_else(|error| {
+ sess.emit_fatal(errors::AddNativeLibrary { library_path: path, error })});
}
}
@@ -516,36 +494,14 @@ fn link_staticlib<'a>(
&codegen_results.crate_info,
Some(CrateType::Staticlib),
&mut |cnum, path| {
- let name = codegen_results.crate_info.crate_name[&cnum];
- let native_libs = &codegen_results.crate_info.native_libraries[&cnum];
-
- // Here when we include the rlib into our staticlib we need to make a
- // decision whether to include the extra object files along the way.
- // These extra object files come from statically included native
- // libraries, but they may be cfg'd away with #[link(cfg(..))].
- //
- // This unstable feature, though, only needs liblibc to work. The only
- // use case there is where musl is statically included in liblibc.rlib,
- // so if we don't want the included version we just need to skip it. As
- // a result the logic here is that if *any* linked library is cfg'd away
- // we just skip all object files.
- //
- // Clearly this is not sufficient for a general purpose feature, and
- // we'd want to read from the library's metadata to determine which
- // object files come from where and selectively skip them.
- let skip_object_files = native_libs.iter().any(|lib| {
- matches!(lib.kind, NativeLibKind::Static { bundle: None | Some(true), .. })
- && !relevant_lib(sess, lib)
- });
-
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();
+ let native_libs = codegen_results.crate_info.native_libraries[&cnum].iter();
+ let relevant = native_libs.clone().filter(|lib| relevant_lib(sess, &lib));
+ let relevant_libs: FxHashSet<_> = relevant.filter_map(|lib| lib.filename).collect();
+ let bundled_libs: FxHashSet<_> = native_libs.filter_map(|lib| lib.filename).collect();
ab.add_archive(
path,
Box::new(move |fname: &str| {
@@ -559,20 +515,25 @@ fn link_staticlib<'a>(
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"))
- {
+ // Skip objects for bundled libs.
+ if bundled_libs.contains(&Symbol::intern(fname)) {
return true;
}
- // ok, don't skip this
false
}),
)
.unwrap();
+ archive_builder_builder
+ .extract_bundled_libs(path, tempdir.as_ref(), &relevant_libs)
+ .unwrap_or_else(|e| sess.emit_fatal(e));
+ for filename in relevant_libs {
+ let joined = tempdir.as_ref().join(filename.as_str());
+ let path = joined.as_path();
+ ab.add_archive(path, Box::new(|_| false)).unwrap();
+ }
+
all_native_libs
.extend(codegen_results.crate_info.native_libraries[&cnum].iter().cloned());
},
@@ -599,7 +560,8 @@ fn link_dwarf_object<'a>(
cg_results: &CodegenResults,
executable_out_filename: &Path,
) {
- let dwp_out_filename = executable_out_filename.with_extension("dwp");
+ let mut dwp_out_filename = executable_out_filename.to_path_buf().into_os_string();
+ dwp_out_filename.push(".dwp");
debug!(?dwp_out_filename, ?executable_out_filename);
#[derive(Default)]
@@ -1302,12 +1264,6 @@ fn preserve_objects_for_their_debuginfo(sess: &Session) -> (bool, bool) {
return (false, false);
}
- // If we're only producing artifacts that are archives, no need to preserve
- // the objects as they're losslessly contained inside the archives.
- if sess.crate_types().iter().all(|&x| x.is_archive()) {
- return (false, false);
- }
-
match (sess.split_debuginfo(), sess.opts.unstable_opts.split_dwarf_kind) {
// If there is no split debuginfo then do not preserve objects.
(SplitDebuginfo::Off, _) => (false, false),
@@ -2070,7 +2026,7 @@ fn linker_with_args<'a>(
.native_libraries
.iter()
.filter_map(|(cnum, libraries)| {
- (dependency_linkage[cnum.as_usize() - 1] != Linkage::Static).then(|| libraries)
+ (dependency_linkage[cnum.as_usize() - 1] != Linkage::Static).then_some(libraries)
})
.flatten();
for (raw_dylib_name, raw_dylib_imports) in
@@ -2597,18 +2553,8 @@ fn add_static_crate<'a>(
cmd.link_rlib(&fix_windows_verbatim_for_gcc(path));
};
- // See the comment above in `link_staticlib` and `link_rlib` for why if
- // there's a static library that's not relevant we skip all object
- // files.
- let native_libs = &codegen_results.crate_info.native_libraries[&cnum];
- let skip_native = native_libs.iter().any(|lib| {
- matches!(lib.kind, NativeLibKind::Static { bundle: None | Some(true), .. })
- && !relevant_lib(sess, lib)
- });
-
- if (!are_upstream_rust_objects_already_included(sess)
- || ignored_for_lto(sess, &codegen_results.crate_info, cnum))
- && !skip_native
+ if !are_upstream_rust_objects_already_included(sess)
+ || ignored_for_lto(sess, &codegen_results.crate_info, cnum)
{
link_upstream(cratepath);
return;
@@ -2639,17 +2585,13 @@ fn add_static_crate<'a>(
let is_rust_object =
canonical.starts_with(&canonical_name) && looks_like_rust_object_file(&f);
- // If we've been requested to skip all native object files
- // (those not generated by the rust compiler) then we can skip
- // this file. See above for why we may want to do this.
- let skip_because_cfg_say_so = skip_native && !is_rust_object;
-
// If we're performing LTO and this is a rust-generated object
// file, then we don't need the object file as it's part of the
// LTO module. Note that `#![no_builtins]` is excluded from LTO,
// though, so we let that object file slide.
- let skip_because_lto =
- upstream_rust_objects_already_included && is_rust_object && is_builtins;
+ if upstream_rust_objects_already_included && is_rust_object && is_builtins {
+ return true;
+ }
// We skip native libraries because:
// 1. This native libraries won't be used from the generated rlib,
@@ -2660,10 +2602,6 @@ fn add_static_crate<'a>(
return true;
}
- if skip_because_cfg_say_so || skip_because_lto {
- return true;
- }
-
false
}),
) {
diff --git a/compiler/rustc_codegen_ssa/src/back/linker.rs b/compiler/rustc_codegen_ssa/src/back/linker.rs
index eaf1e9817..52c01b423 100644
--- a/compiler/rustc_codegen_ssa/src/back/linker.rs
+++ b/compiler/rustc_codegen_ssa/src/back/linker.rs
@@ -473,13 +473,13 @@ impl<'a> Linker for GccLinker<'a> {
self.cmd.arg(path);
}
fn full_relro(&mut self) {
- self.linker_args(&["-zrelro", "-znow"]);
+ self.linker_args(&["-z", "relro", "-z", "now"]);
}
fn partial_relro(&mut self) {
- self.linker_arg("-zrelro");
+ self.linker_args(&["-z", "relro"]);
}
fn no_relro(&mut self) {
- self.linker_arg("-znorelro");
+ self.linker_args(&["-z", "norelro"]);
}
fn link_rust_dylib(&mut self, lib: &str, _path: &Path) {
@@ -758,7 +758,7 @@ impl<'a> Linker for GccLinker<'a> {
if self.sess.target.is_like_windows {
self.linker_arg("--nxcompat");
} else if self.is_gnu {
- self.linker_arg("-znoexecstack");
+ self.linker_args(&["-z", "noexecstack"]);
}
}
@@ -1364,16 +1364,16 @@ impl<'a> Linker for L4Bender<'a> {
}
fn full_relro(&mut self) {
- self.cmd.arg("-zrelro");
- self.cmd.arg("-znow");
+ self.cmd.arg("-z").arg("relro");
+ self.cmd.arg("-z").arg("now");
}
fn partial_relro(&mut self) {
- self.cmd.arg("-zrelro");
+ self.cmd.arg("-z").arg("relro");
}
fn no_relro(&mut self) {
- self.cmd.arg("-znorelro");
+ self.cmd.arg("-z").arg("norelro");
}
fn cmd(&mut self) -> &mut Command {
diff --git a/compiler/rustc_codegen_ssa/src/back/metadata.rs b/compiler/rustc_codegen_ssa/src/back/metadata.rs
index 7d3c14fec..019ec0758 100644
--- a/compiler/rustc_codegen_ssa/src/back/metadata.rs
+++ b/compiler/rustc_codegen_ssa/src/back/metadata.rs
@@ -33,6 +33,7 @@ use rustc_target::spec::{RelocModel, Target};
/// <dt>dylib</dt>
/// <dd>The metadata can be found in the `.rustc` section of the shared library.</dd>
/// </dl>
+#[derive(Debug)]
pub struct DefaultMetadataLoader;
fn load_metadata_with(
diff --git a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs
index 57a99e74c..067a3e167 100644
--- a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs
+++ b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs
@@ -2,9 +2,8 @@ use std::collections::hash_map::Entry::*;
use rustc_ast::expand::allocator::ALLOCATOR_METHODS;
use rustc_data_structures::fx::FxHashMap;
-use rustc_hir as hir;
+use rustc_hir::def::DefKind;
use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, LocalDefId, LOCAL_CRATE};
-use rustc_hir::Node;
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
use rustc_middle::middle::exported_symbols::{
metadata_symbol_name, ExportedSymbol, SymbolExportInfo, SymbolExportKind, SymbolExportLevel,
@@ -12,7 +11,7 @@ use rustc_middle::middle::exported_symbols::{
use rustc_middle::ty::query::{ExternProviders, Providers};
use rustc_middle::ty::subst::{GenericArgKind, SubstsRef};
use rustc_middle::ty::Instance;
-use rustc_middle::ty::{self, SymbolName, TyCtxt};
+use rustc_middle::ty::{self, DefIdTree, SymbolName, TyCtxt};
use rustc_session::config::{CrateType, OomStrategy};
use rustc_target::spec::SanitizerSet;
@@ -74,32 +73,34 @@ fn reachable_non_generics_provider(tcx: TyCtxt<'_>, cnum: CrateNum) -> DefIdMap<
//
// As a result, if this id is an FFI item (foreign item) then we only
// let it through if it's included statically.
- match tcx.hir().get_by_def_id(def_id) {
- Node::ForeignItem(..) => {
- tcx.native_library(def_id).map_or(false, |library| library.kind.is_statically_included()).then_some(def_id)
- }
+ if let Some(parent_id) = tcx.opt_local_parent(def_id)
+ && let DefKind::ForeignMod = tcx.def_kind(parent_id)
+ {
+ let library = tcx.native_library(def_id)?;
+ return library.kind.is_statically_included().then_some(def_id);
+ }
- // Only consider nodes that actually have exported symbols.
- Node::Item(&hir::Item {
- kind: hir::ItemKind::Static(..) | hir::ItemKind::Fn(..),
- ..
- })
- | Node::ImplItem(&hir::ImplItem { kind: hir::ImplItemKind::Fn(..), .. }) => {
- let generics = tcx.generics_of(def_id);
- if !generics.requires_monomorphization(tcx)
- // Functions marked with #[inline] are codegened with "internal"
- // linkage and are not exported unless marked with an extern
- // indicator
- && (!Instance::mono(tcx, def_id.to_def_id()).def.generates_cgu_internal_copy(tcx)
- || tcx.codegen_fn_attrs(def_id.to_def_id()).contains_extern_indicator())
- {
- Some(def_id)
- } else {
- None
- }
- }
+ // Only consider nodes that actually have exported symbols.
+ match tcx.def_kind(def_id) {
+ DefKind::Fn | DefKind::Static(_) => {}
+ DefKind::AssocFn if tcx.impl_of_method(def_id.to_def_id()).is_some() => {}
+ _ => return None,
+ };
- _ => None,
+ let generics = tcx.generics_of(def_id);
+ if generics.requires_monomorphization(tcx) {
+ return None;
+ }
+
+ // Functions marked with #[inline] are codegened with "internal"
+ // linkage and are not exported unless marked with an extern
+ // indicator
+ if !Instance::mono(tcx, def_id.to_def_id()).def.generates_cgu_internal_copy(tcx)
+ || tcx.codegen_fn_attrs(def_id.to_def_id()).contains_extern_indicator()
+ {
+ Some(def_id)
+ } else {
+ None
}
})
.map(|def_id| {
@@ -118,7 +119,7 @@ fn reachable_non_generics_provider(tcx: TyCtxt<'_>, cnum: CrateNum) -> DefIdMap<
tcx.symbol_name(Instance::mono(tcx, def_id.to_def_id())),
export_level
);
- (def_id.to_def_id(), SymbolExportInfo {
+ let info = SymbolExportInfo {
level: export_level,
kind: if tcx.is_static(def_id.to_def_id()) {
if codegen_attrs.flags.contains(CodegenFnAttrFlags::THREAD_LOCAL) {
@@ -130,8 +131,10 @@ fn reachable_non_generics_provider(tcx: TyCtxt<'_>, cnum: CrateNum) -> DefIdMap<
SymbolExportKind::Text
},
used: codegen_attrs.flags.contains(CodegenFnAttrFlags::USED)
- || codegen_attrs.flags.contains(CodegenFnAttrFlags::USED_LINKER) || used,
- })
+ || codegen_attrs.flags.contains(CodegenFnAttrFlags::USED_LINKER)
+ || used,
+ };
+ (def_id.to_def_id(), info)
})
.collect();
@@ -370,7 +373,7 @@ fn upstream_monomorphizations_provider(
ExportedSymbol::Generic(def_id, substs) => (def_id, substs),
ExportedSymbol::DropGlue(ty) => {
if let Some(drop_in_place_fn_def_id) = drop_in_place_fn_def_id {
- (drop_in_place_fn_def_id, tcx.intern_substs(&[ty.into()]))
+ (drop_in_place_fn_def_id, tcx.mk_substs(&[ty.into()]))
} else {
// `drop_in_place` in place does not exist, don't try
// to use it.
@@ -457,9 +460,7 @@ fn symbol_export_level(tcx: TyCtxt<'_>, sym_def_id: DefId) -> SymbolExportLevel
let target = &tcx.sess.target.llvm_target;
// WebAssembly cannot export data symbols, so reduce their export level
if target.contains("emscripten") {
- if let Some(Node::Item(&hir::Item { kind: hir::ItemKind::Static(..), .. })) =
- tcx.hir().get_if_local(sym_def_id)
- {
+ if let DefKind::Static(_) = tcx.def_kind(sym_def_id) {
return SymbolExportLevel::Rust;
}
}
diff --git a/compiler/rustc_codegen_ssa/src/back/write.rs b/compiler/rustc_codegen_ssa/src/back/write.rs
index 9f1614af7..8508ab875 100644
--- a/compiler/rustc_codegen_ssa/src/back/write.rs
+++ b/compiler/rustc_codegen_ssa/src/back/write.rs
@@ -305,8 +305,12 @@ impl TargetMachineFactoryConfig {
}
pub type TargetMachineFactoryFn<B> = Arc<
- dyn Fn(TargetMachineFactoryConfig) -> Result<<B as WriteBackendMethods>::TargetMachine, String>
- + Send
+ dyn Fn(
+ TargetMachineFactoryConfig,
+ ) -> Result<
+ <B as WriteBackendMethods>::TargetMachine,
+ <B as WriteBackendMethods>::TargetMachineError,
+ > + Send
+ Sync,
>;
diff --git a/compiler/rustc_codegen_ssa/src/base.rs b/compiler/rustc_codegen_ssa/src/base.rs
index 32d3cfe6f..73179249b 100644
--- a/compiler/rustc_codegen_ssa/src/base.rs
+++ b/compiler/rustc_codegen_ssa/src/base.rs
@@ -39,7 +39,7 @@ use rustc_session::Session;
use rustc_span::symbol::sym;
use rustc_span::Symbol;
use rustc_span::{DebuggerVisualizerFile, DebuggerVisualizerType};
-use rustc_target::abi::{Align, Size, VariantIdx};
+use rustc_target::abi::{Align, VariantIdx};
use std::collections::BTreeSet;
use std::time::{Duration, Instant};
@@ -148,7 +148,7 @@ pub fn unsized_info<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
cx.tcx().struct_lockstep_tails_erasing_lifetimes(source, target, bx.param_env());
match (source.kind(), target.kind()) {
(&ty::Array(_, len), &ty::Slice(_)) => {
- cx.const_usize(len.eval_usize(cx.tcx(), ty::ParamEnv::reveal_all()))
+ cx.const_usize(len.eval_target_usize(cx.tcx(), ty::ParamEnv::reveal_all()))
}
(
&ty::Dynamic(ref data_a, _, src_dyn_kind),
@@ -273,12 +273,13 @@ pub fn cast_to_dyn_star<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
matches!(dst_ty.kind(), ty::Dynamic(_, _, ty::DynStar)),
"destination type must be a dyn*"
);
- // FIXME(dyn-star): this is probably not the best way to check if this is
- // a pointer, and really we should ensure that the value is a suitable
- // pointer earlier in the compilation process.
- let src = match src_ty_and_layout.pointee_info_at(bx.cx(), Size::ZERO) {
- Some(_) => bx.ptrtoint(src, bx.cx().type_isize()),
- None => bx.bitcast(src, bx.type_isize()),
+ // FIXME(dyn-star): We can remove this when all supported LLVMs use opaque ptrs only.
+ let unit_ptr = bx.cx().type_ptr_to(bx.cx().type_struct(&[], false));
+ let src = match bx.cx().type_kind(bx.cx().backend_type(src_ty_and_layout)) {
+ TypeKind::Pointer => bx.pointercast(src, unit_ptr),
+ TypeKind::Integer => bx.inttoptr(src, unit_ptr),
+ // FIXME(dyn-star): We probably have to do a bitcast first, then inttoptr.
+ kind => bug!("unexpected TypeKind for left-hand side of `dyn*` cast: {kind:?}"),
};
(src, unsized_info(bx, src_ty_and_layout.ty, dst_ty, old_info))
}
@@ -436,7 +437,7 @@ pub fn maybe_create_entry_wrapper<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
cx.type_func(&[], cx.type_int())
};
- let main_ret_ty = cx.tcx().fn_sig(rust_main_def_id).output();
+ let main_ret_ty = cx.tcx().fn_sig(rust_main_def_id).no_bound_vars().unwrap().output();
// Given that `main()` has no arguments,
// then its return type cannot have
// late-bound regions, since late-bound
@@ -475,7 +476,7 @@ pub fn maybe_create_entry_wrapper<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
cx.tcx(),
ty::ParamEnv::reveal_all(),
start_def_id,
- cx.tcx().intern_substs(&[main_ret_ty.into()]),
+ cx.tcx().mk_substs(&[main_ret_ty.into()]),
)
.unwrap()
.unwrap(),
@@ -579,7 +580,7 @@ pub fn codegen_crate<B: ExtraBackendMethods>(
}
}
- let metadata_module = if need_metadata_module {
+ let metadata_module = need_metadata_module.then(|| {
// Emit compressed metadata object.
let metadata_cgu_name =
cgu_name_builder.build_cgu_name(LOCAL_CRATE, &["crate"], Some("metadata")).to_string();
@@ -594,17 +595,15 @@ pub fn codegen_crate<B: ExtraBackendMethods>(
if let Err(error) = std::fs::write(&file_name, data) {
tcx.sess.emit_fatal(errors::MetadataObjectFileWrite { error });
}
- Some(CompiledModule {
+ CompiledModule {
name: metadata_cgu_name,
kind: ModuleKind::Metadata,
object: Some(file_name),
dwarf_object: None,
bytecode: None,
- })
+ }
})
- } else {
- None
- };
+ });
let ongoing_codegen = start_async_codegen(
backend.clone(),
@@ -858,6 +857,7 @@ impl CrateInfo {
dependency_formats: tcx.dependency_formats(()).clone(),
windows_subsystem,
natvis_debugger_visualizers: Default::default(),
+ feature_packed_bundled_libs: tcx.features().packed_bundled_libs,
};
let crates = tcx.crates(());
diff --git a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs
index 8808ad2dc..7d5c00486 100644
--- a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs
+++ b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs
@@ -85,55 +85,11 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: DefId) -> CodegenFnAttrs {
} else if attr.has_name(sym::rustc_allocator) {
codegen_fn_attrs.flags |= CodegenFnAttrFlags::ALLOCATOR;
} else if attr.has_name(sym::ffi_returns_twice) {
- if tcx.is_foreign_item(did) {
- codegen_fn_attrs.flags |= CodegenFnAttrFlags::FFI_RETURNS_TWICE;
- } else {
- // `#[ffi_returns_twice]` is only allowed `extern fn`s.
- struct_span_err!(
- tcx.sess,
- attr.span,
- E0724,
- "`#[ffi_returns_twice]` may only be used on foreign functions"
- )
- .emit();
- }
+ codegen_fn_attrs.flags |= CodegenFnAttrFlags::FFI_RETURNS_TWICE;
} else if attr.has_name(sym::ffi_pure) {
- if tcx.is_foreign_item(did) {
- if attrs.iter().any(|a| a.has_name(sym::ffi_const)) {
- // `#[ffi_const]` functions cannot be `#[ffi_pure]`
- struct_span_err!(
- tcx.sess,
- attr.span,
- E0757,
- "`#[ffi_const]` function cannot be `#[ffi_pure]`"
- )
- .emit();
- } else {
- codegen_fn_attrs.flags |= CodegenFnAttrFlags::FFI_PURE;
- }
- } else {
- // `#[ffi_pure]` is only allowed on foreign functions
- struct_span_err!(
- tcx.sess,
- attr.span,
- E0755,
- "`#[ffi_pure]` may only be used on foreign functions"
- )
- .emit();
- }
+ codegen_fn_attrs.flags |= CodegenFnAttrFlags::FFI_PURE;
} else if attr.has_name(sym::ffi_const) {
- if tcx.is_foreign_item(did) {
- codegen_fn_attrs.flags |= CodegenFnAttrFlags::FFI_CONST;
- } else {
- // `#[ffi_const]` is only allowed on foreign functions
- struct_span_err!(
- tcx.sess,
- attr.span,
- E0756,
- "`#[ffi_const]` may only be used on foreign functions"
- )
- .emit();
- }
+ codegen_fn_attrs.flags |= CodegenFnAttrFlags::FFI_CONST;
} else if attr.has_name(sym::rustc_nounwind) {
codegen_fn_attrs.flags |= CodegenFnAttrFlags::NEVER_UNWIND;
} else if attr.has_name(sym::rustc_reallocator) {
@@ -214,7 +170,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: DefId) -> CodegenFnAttrs {
}
} else if attr.has_name(sym::cmse_nonsecure_entry) {
if validate_fn_only_attr(attr.span)
- && !matches!(tcx.fn_sig(did).abi(), abi::Abi::C { .. })
+ && !matches!(tcx.fn_sig(did).skip_binder().abi(), abi::Abi::C { .. })
{
struct_span_err!(
tcx.sess,
@@ -234,7 +190,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: DefId) -> CodegenFnAttrs {
} else if attr.has_name(sym::track_caller) {
if !tcx.is_closure(did.to_def_id())
&& validate_fn_only_attr(attr.span)
- && tcx.fn_sig(did).abi() != abi::Abi::Rust
+ && tcx.fn_sig(did).skip_binder().abi() != abi::Abi::Rust
{
struct_span_err!(tcx.sess, attr.span, E0737, "`#[track_caller]` requires Rust ABI")
.emit();
@@ -266,7 +222,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: DefId) -> CodegenFnAttrs {
}
} else if attr.has_name(sym::target_feature) {
if !tcx.is_closure(did.to_def_id())
- && tcx.fn_sig(did).unsafety() == hir::Unsafety::Normal
+ && tcx.fn_sig(did).skip_binder().unsafety() == hir::Unsafety::Normal
{
if tcx.sess.target.is_like_wasm || tcx.sess.opts.actually_rustdoc {
// The `#[target_feature]` attribute is allowed on
@@ -339,7 +295,8 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: DefId) -> CodegenFnAttrs {
if let Some(list) = attr.meta_item_list() {
for item in list.iter() {
if item.has_name(sym::address) {
- codegen_fn_attrs.no_sanitize |= SanitizerSet::ADDRESS;
+ codegen_fn_attrs.no_sanitize |=
+ SanitizerSet::ADDRESS | SanitizerSet::KERNELADDRESS;
} else if item.has_name(sym::cfi) {
codegen_fn_attrs.no_sanitize |= SanitizerSet::CFI;
} else if item.has_name(sym::kcfi) {
@@ -363,74 +320,62 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: DefId) -> CodegenFnAttrs {
}
}
} else if attr.has_name(sym::instruction_set) {
- codegen_fn_attrs.instruction_set = match attr.meta_kind() {
- Some(MetaItemKind::List(ref items)) => match items.as_slice() {
- [NestedMetaItem::MetaItem(set)] => {
- let segments =
- set.path.segments.iter().map(|x| x.ident.name).collect::<Vec<_>>();
- match segments.as_slice() {
- [sym::arm, sym::a32] | [sym::arm, sym::t32] => {
- if !tcx.sess.target.has_thumb_interworking {
- struct_span_err!(
- tcx.sess.diagnostic(),
- attr.span,
- E0779,
- "target does not support `#[instruction_set]`"
- )
- .emit();
- None
- } else if segments[1] == sym::a32 {
- Some(InstructionSetAttr::ArmA32)
- } else if segments[1] == sym::t32 {
- Some(InstructionSetAttr::ArmT32)
- } else {
- unreachable!()
- }
- }
- _ => {
+ codegen_fn_attrs.instruction_set = attr.meta_item_list().and_then(|l| match &l[..] {
+ [NestedMetaItem::MetaItem(set)] => {
+ let segments =
+ set.path.segments.iter().map(|x| x.ident.name).collect::<Vec<_>>();
+ match segments.as_slice() {
+ [sym::arm, sym::a32] | [sym::arm, sym::t32] => {
+ if !tcx.sess.target.has_thumb_interworking {
struct_span_err!(
tcx.sess.diagnostic(),
attr.span,
E0779,
- "invalid instruction set specified",
+ "target does not support `#[instruction_set]`"
)
.emit();
None
+ } else if segments[1] == sym::a32 {
+ Some(InstructionSetAttr::ArmA32)
+ } else if segments[1] == sym::t32 {
+ Some(InstructionSetAttr::ArmT32)
+ } else {
+ unreachable!()
}
}
+ _ => {
+ struct_span_err!(
+ tcx.sess.diagnostic(),
+ attr.span,
+ E0779,
+ "invalid instruction set specified",
+ )
+ .emit();
+ None
+ }
}
- [] => {
- struct_span_err!(
- tcx.sess.diagnostic(),
- attr.span,
- E0778,
- "`#[instruction_set]` requires an argument"
- )
- .emit();
- None
- }
- _ => {
- struct_span_err!(
- tcx.sess.diagnostic(),
- attr.span,
- E0779,
- "cannot specify more than one instruction set"
- )
- .emit();
- None
- }
- },
- _ => {
+ }
+ [] => {
struct_span_err!(
tcx.sess.diagnostic(),
attr.span,
E0778,
- "must specify an instruction set"
+ "`#[instruction_set]` requires an argument"
)
.emit();
None
}
- };
+ _ => {
+ struct_span_err!(
+ tcx.sess.diagnostic(),
+ attr.span,
+ E0779,
+ "cannot specify more than one instruction set"
+ )
+ .emit();
+ None
+ }
+ })
} else if attr.has_name(sym::repr) {
codegen_fn_attrs.alignment = match attr.meta_item_list() {
Some(items) => match items.as_slice() {
diff --git a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs
index 1599ccbb2..f2469fde3 100644
--- a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs
+++ b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs
@@ -181,16 +181,24 @@ fn push_debuginfo_type_name<'tcx>(
push_debuginfo_type_name(tcx, inner_type, true, output, visited);
match len.kind() {
ty::ConstKind::Param(param) => write!(output, ",{}>", param.name).unwrap(),
- _ => write!(output, ",{}>", len.eval_usize(tcx, ty::ParamEnv::reveal_all()))
- .unwrap(),
+ _ => write!(
+ output,
+ ",{}>",
+ len.eval_target_usize(tcx, ty::ParamEnv::reveal_all())
+ )
+ .unwrap(),
}
} else {
output.push('[');
push_debuginfo_type_name(tcx, inner_type, true, output, visited);
match len.kind() {
ty::ConstKind::Param(param) => write!(output, "; {}]", param.name).unwrap(),
- _ => write!(output, "; {}]", len.eval_usize(tcx, ty::ParamEnv::reveal_all()))
- .unwrap(),
+ _ => write!(
+ output,
+ "; {}]",
+ len.eval_target_usize(tcx, ty::ParamEnv::reveal_all())
+ )
+ .unwrap(),
}
}
}
@@ -414,6 +422,7 @@ fn push_debuginfo_type_name<'tcx>(
| ty::Placeholder(..)
| ty::Alias(..)
| ty::Bound(..)
+ | ty::GeneratorWitnessMIR(..)
| ty::GeneratorWitness(..) => {
bug!(
"debuginfo: Trying to create type name for \
diff --git a/compiler/rustc_codegen_ssa/src/errors.rs b/compiler/rustc_codegen_ssa/src/errors.rs
index d81252653..6dea7496f 100644
--- a/compiler/rustc_codegen_ssa/src/errors.rs
+++ b/compiler/rustc_codegen_ssa/src/errors.rs
@@ -1,8 +1,9 @@
//! Errors emitted by codegen_ssa
use crate::back::command::Command;
+use crate::fluent_generated as fluent;
use rustc_errors::{
- fluent, DiagnosticArgValue, DiagnosticBuilder, ErrorGuaranteed, Handler, IntoDiagnostic,
+ DiagnosticArgValue, DiagnosticBuilder, ErrorGuaranteed, Handler, IntoDiagnostic,
IntoDiagnosticArg,
};
use rustc_macros::Diagnostic;
@@ -388,7 +389,7 @@ pub struct LinkerNotFound {
#[derive(Diagnostic)]
#[diag(codegen_ssa_unable_to_exe_linker)]
#[note]
-#[note(command_note)]
+#[note(codegen_ssa_command_note)]
pub struct UnableToExeLinker {
pub linker_path: PathBuf,
pub error: Error,
diff --git a/compiler/rustc_codegen_ssa/src/lib.rs b/compiler/rustc_codegen_ssa/src/lib.rs
index 0e6596d4b..ebe9e50ff 100644
--- a/compiler/rustc_codegen_ssa/src/lib.rs
+++ b/compiler/rustc_codegen_ssa/src/lib.rs
@@ -13,7 +13,7 @@
//! This crate contains codegen code that is used by all codegen backends (LLVM and others).
//! The backend-agnostic functions of this crate use functions defined in various traits that
-//! have to be implemented by each backends.
+//! have to be implemented by each backend.
#[macro_use]
extern crate rustc_macros;
@@ -25,7 +25,9 @@ extern crate rustc_middle;
use rustc_ast as ast;
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_data_structures::sync::Lrc;
+use rustc_errors::{DiagnosticMessage, SubdiagnosticMessage};
use rustc_hir::def_id::CrateNum;
+use rustc_macros::fluent_messages;
use rustc_middle::dep_graph::WorkProduct;
use rustc_middle::middle::dependency_format::Dependencies;
use rustc_middle::middle::exported_symbols::SymbolExportKind;
@@ -54,6 +56,8 @@ pub mod mono_item;
pub mod target_features;
pub mod traits;
+fluent_messages! { "../locales/en-US.ftl" }
+
pub struct ModuleCodegen<M> {
/// The name of the module. When the crate may be saved between
/// compilations, incremental compilation requires that name be
@@ -159,6 +163,7 @@ pub struct CrateInfo {
pub dependency_formats: Lrc<Dependencies>,
pub windows_subsystem: Option<String>,
pub natvis_debugger_visualizers: BTreeSet<DebuggerVisualizerFile>,
+ pub feature_packed_bundled_libs: bool, // unstable feature flag.
}
#[derive(Encodable, Decodable)]
diff --git a/compiler/rustc_codegen_ssa/src/mir/analyze.rs b/compiler/rustc_codegen_ssa/src/mir/analyze.rs
index dd1ac2c74..95aad10fd 100644
--- a/compiler/rustc_codegen_ssa/src/mir/analyze.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/analyze.rs
@@ -36,7 +36,7 @@ pub fn non_ssa_locals<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
// Arguments get assigned to by means of the function being called
for arg in mir.args_iter() {
- analyzer.assign(arg, mir::START_BLOCK.start_location());
+ analyzer.assign(arg, DefLocation::Argument);
}
// If there exists a local definition that dominates all uses of that local,
@@ -64,7 +64,22 @@ enum LocalKind {
/// A scalar or a scalar pair local that is neither defined nor used.
Unused,
/// A scalar or a scalar pair local with a single definition that dominates all uses.
- SSA(mir::Location),
+ SSA(DefLocation),
+}
+
+#[derive(Copy, Clone, PartialEq, Eq)]
+enum DefLocation {
+ Argument,
+ Body(Location),
+}
+
+impl DefLocation {
+ fn dominates(self, location: Location, dominators: &Dominators<mir::BasicBlock>) -> bool {
+ match self {
+ DefLocation::Argument => true,
+ DefLocation::Body(def) => def.successor_within_block().dominates(location, dominators),
+ }
+ }
}
struct LocalAnalyzer<'mir, 'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> {
@@ -74,17 +89,13 @@ struct LocalAnalyzer<'mir, 'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> {
}
impl<'mir, 'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> LocalAnalyzer<'mir, 'a, 'tcx, Bx> {
- fn assign(&mut self, local: mir::Local, location: Location) {
+ fn assign(&mut self, local: mir::Local, location: DefLocation) {
let kind = &mut self.locals[local];
match *kind {
LocalKind::ZST => {}
LocalKind::Memory => {}
- LocalKind::Unused => {
- *kind = LocalKind::SSA(location);
- }
- LocalKind::SSA(_) => {
- *kind = LocalKind::Memory;
- }
+ LocalKind::Unused => *kind = LocalKind::SSA(location),
+ LocalKind::SSA(_) => *kind = LocalKind::Memory,
}
}
@@ -166,7 +177,7 @@ impl<'mir, 'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> Visitor<'tcx>
debug!("visit_assign(place={:?}, rvalue={:?})", place, rvalue);
if let Some(local) = place.as_local() {
- self.assign(local, location);
+ self.assign(local, DefLocation::Body(location));
if self.locals[local] != LocalKind::Memory {
let decl_span = self.fx.mir.local_decls[local].source_info.span;
if !self.fx.rvalue_creates_operand(rvalue, decl_span) {
@@ -189,7 +200,7 @@ impl<'mir, 'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> Visitor<'tcx>
match context {
PlaceContext::MutatingUse(MutatingUseContext::Call)
| PlaceContext::MutatingUse(MutatingUseContext::Yield) => {
- self.assign(local, location);
+ self.assign(local, DefLocation::Body(location));
}
PlaceContext::NonUse(_) | PlaceContext::MutatingUse(MutatingUseContext::Retag) => {}
diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs
index 978aff511..57a19a4ab 100644
--- a/compiler/rustc_codegen_ssa/src/mir/block.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/block.rs
@@ -14,9 +14,9 @@ use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece};
use rustc_hir::lang_items::LangItem;
use rustc_index::vec::Idx;
use rustc_middle::mir::{self, AssertKind, SwitchTargets};
-use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf};
+use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf, ValidityRequirement};
use rustc_middle::ty::print::{with_no_trimmed_paths, with_no_visible_paths};
-use rustc_middle::ty::{self, Instance, Ty, TypeVisitable};
+use rustc_middle::ty::{self, Instance, Ty, TypeVisitableExt};
use rustc_session::config::OptLevel;
use rustc_span::source_map::Span;
use rustc_span::{sym, Symbol};
@@ -39,7 +39,6 @@ enum MergingSucc {
struct TerminatorCodegenHelper<'tcx> {
bb: mir::BasicBlock,
terminator: &'tcx mir::Terminator<'tcx>,
- funclet_bb: Option<mir::BasicBlock>,
}
impl<'a, 'tcx> TerminatorCodegenHelper<'tcx> {
@@ -49,28 +48,24 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'tcx> {
&self,
fx: &'b mut FunctionCx<'a, 'tcx, Bx>,
) -> Option<&'b Bx::Funclet> {
- let funclet_bb = self.funclet_bb?;
- if base::wants_msvc_seh(fx.cx.tcx().sess) {
- // If `landing_pad_for` hasn't been called yet to create the `Funclet`,
- // it has to be now. This may not seem necessary, as RPO should lead
- // to all the unwind edges being visited (and so to `landing_pad_for`
- // getting called for them), before building any of the blocks inside
- // the funclet itself - however, if MIR contains edges that end up not
- // being needed in the LLVM IR after monomorphization, the funclet may
- // be unreachable, and we don't have yet a way to skip building it in
- // such an eventuality (which may be a better solution than this).
- if fx.funclets[funclet_bb].is_none() {
- fx.landing_pad_for(funclet_bb);
- }
-
- Some(
- fx.funclets[funclet_bb]
- .as_ref()
- .expect("landing_pad_for didn't also create funclets entry"),
- )
- } else {
- None
+ let cleanup_kinds = (&fx.cleanup_kinds).as_ref()?;
+ let funclet_bb = cleanup_kinds[self.bb].funclet_bb(self.bb)?;
+ // If `landing_pad_for` hasn't been called yet to create the `Funclet`,
+ // it has to be now. This may not seem necessary, as RPO should lead
+ // to all the unwind edges being visited (and so to `landing_pad_for`
+ // getting called for them), before building any of the blocks inside
+ // the funclet itself - however, if MIR contains edges that end up not
+ // being needed in the LLVM IR after monomorphization, the funclet may
+ // be unreachable, and we don't have yet a way to skip building it in
+ // such an eventuality (which may be a better solution than this).
+ if fx.funclets[funclet_bb].is_none() {
+ fx.landing_pad_for(funclet_bb);
}
+ Some(
+ fx.funclets[funclet_bb]
+ .as_ref()
+ .expect("landing_pad_for didn't also create funclets entry"),
+ )
}
/// Get a basic block (creating it if necessary), possibly with cleanup
@@ -104,23 +99,24 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'tcx> {
fx: &mut FunctionCx<'a, 'tcx, Bx>,
target: mir::BasicBlock,
) -> (bool, bool) {
- let target_funclet = fx.cleanup_kinds[target].funclet_bb(target);
- let (needs_landing_pad, is_cleanupret) = match (self.funclet_bb, target_funclet) {
- (None, None) => (false, false),
- (None, Some(_)) => (true, false),
- (Some(_), None) => {
- let span = self.terminator.source_info.span;
- span_bug!(span, "{:?} - jump out of cleanup?", self.terminator);
- }
- (Some(f), Some(t_f)) => {
- if f == t_f || !base::wants_msvc_seh(fx.cx.tcx().sess) {
- (false, false)
- } else {
- (true, true)
+ if let Some(ref cleanup_kinds) = fx.cleanup_kinds {
+ let funclet_bb = cleanup_kinds[self.bb].funclet_bb(self.bb);
+ let target_funclet = cleanup_kinds[target].funclet_bb(target);
+ let (needs_landing_pad, is_cleanupret) = match (funclet_bb, target_funclet) {
+ (None, None) => (false, false),
+ (None, Some(_)) => (true, false),
+ (Some(f), Some(t_f)) => (f != t_f, f != t_f),
+ (Some(_), None) => {
+ let span = self.terminator.source_info.span;
+ span_bug!(span, "{:?} - jump out of cleanup?", self.terminator);
}
- }
- };
- (needs_landing_pad, is_cleanupret)
+ };
+ (needs_landing_pad, is_cleanupret)
+ } else {
+ let needs_landing_pad = !fx.mir[self.bb].is_cleanup && fx.mir[target].is_cleanup;
+ let is_cleanupret = false;
+ (needs_landing_pad, is_cleanupret)
+ }
}
fn funclet_br<Bx: BuilderMethods<'a, 'tcx>>(
@@ -456,86 +452,84 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
args1 = [place.llval];
&args1[..]
};
- let (drop_fn, fn_abi) = match ty.kind() {
- // FIXME(eddyb) perhaps move some of this logic into
- // `Instance::resolve_drop_in_place`?
- ty::Dynamic(_, _, ty::Dyn) => {
- // IN THIS ARM, WE HAVE:
- // ty = *mut (dyn Trait)
- // which is: exists<T> ( *mut T, Vtable<T: Trait> )
- // args[0] args[1]
- //
- // args = ( Data, Vtable )
- // |
- // v
- // /-------\
- // | ... |
- // \-------/
- //
- let virtual_drop = Instance {
- def: ty::InstanceDef::Virtual(drop_fn.def_id(), 0),
- substs: drop_fn.substs,
- };
- debug!("ty = {:?}", ty);
- debug!("drop_fn = {:?}", drop_fn);
- debug!("args = {:?}", args);
- let fn_abi = bx.fn_abi_of_instance(virtual_drop, ty::List::empty());
- let vtable = args[1];
- // Truncate vtable off of args list
- args = &args[..1];
- (
- meth::VirtualIndex::from_index(ty::COMMON_VTABLE_ENTRIES_DROPINPLACE)
- .get_fn(bx, vtable, ty, &fn_abi),
- fn_abi,
- )
- }
- ty::Dynamic(_, _, ty::DynStar) => {
- // IN THIS ARM, WE HAVE:
- // ty = *mut (dyn* Trait)
- // which is: *mut exists<T: sizeof(T) == sizeof(usize)> (T, Vtable<T: Trait>)
- //
- // args = [ * ]
- // |
- // v
- // ( Data, Vtable )
- // |
- // v
- // /-------\
- // | ... |
- // \-------/
- //
- //
- // WE CAN CONVERT THIS INTO THE ABOVE LOGIC BY DOING
- //
- // data = &(*args[0]).0 // gives a pointer to Data above (really the same pointer)
- // vtable = (*args[0]).1 // loads the vtable out
- // (data, vtable) // an equivalent Rust `*mut dyn Trait`
- //
- // SO THEN WE CAN USE THE ABOVE CODE.
- let virtual_drop = Instance {
- def: ty::InstanceDef::Virtual(drop_fn.def_id(), 0),
- substs: drop_fn.substs,
- };
- debug!("ty = {:?}", ty);
- debug!("drop_fn = {:?}", drop_fn);
- debug!("args = {:?}", args);
- let fn_abi = bx.fn_abi_of_instance(virtual_drop, ty::List::empty());
- let data = args[0];
- let data_ty = bx.cx().backend_type(place.layout);
- let vtable_ptr =
- bx.gep(data_ty, data, &[bx.cx().const_i32(0), bx.cx().const_i32(1)]);
- let vtable = bx.load(bx.type_i8p(), vtable_ptr, abi::Align::ONE);
- // Truncate vtable off of args list
- args = &args[..1];
- debug!("args' = {:?}", args);
- (
- meth::VirtualIndex::from_index(ty::COMMON_VTABLE_ENTRIES_DROPINPLACE)
- .get_fn(bx, vtable, ty, &fn_abi),
- fn_abi,
- )
- }
- _ => (bx.get_fn_addr(drop_fn), bx.fn_abi_of_instance(drop_fn, ty::List::empty())),
- };
+ let (drop_fn, fn_abi) =
+ match ty.kind() {
+ // FIXME(eddyb) perhaps move some of this logic into
+ // `Instance::resolve_drop_in_place`?
+ ty::Dynamic(_, _, ty::Dyn) => {
+ // IN THIS ARM, WE HAVE:
+ // ty = *mut (dyn Trait)
+ // which is: exists<T> ( *mut T, Vtable<T: Trait> )
+ // args[0] args[1]
+ //
+ // args = ( Data, Vtable )
+ // |
+ // v
+ // /-------\
+ // | ... |
+ // \-------/
+ //
+ let virtual_drop = Instance {
+ def: ty::InstanceDef::Virtual(drop_fn.def_id(), 0),
+ substs: drop_fn.substs,
+ };
+ debug!("ty = {:?}", ty);
+ debug!("drop_fn = {:?}", drop_fn);
+ debug!("args = {:?}", args);
+ let fn_abi = bx.fn_abi_of_instance(virtual_drop, ty::List::empty());
+ let vtable = args[1];
+ // Truncate vtable off of args list
+ args = &args[..1];
+ (
+ meth::VirtualIndex::from_index(ty::COMMON_VTABLE_ENTRIES_DROPINPLACE)
+ .get_fn(bx, vtable, ty, &fn_abi),
+ fn_abi,
+ )
+ }
+ ty::Dynamic(_, _, ty::DynStar) => {
+ // IN THIS ARM, WE HAVE:
+ // ty = *mut (dyn* Trait)
+ // which is: *mut exists<T: sizeof(T) == sizeof(usize)> (T, Vtable<T: Trait>)
+ //
+ // args = [ * ]
+ // |
+ // v
+ // ( Data, Vtable )
+ // |
+ // v
+ // /-------\
+ // | ... |
+ // \-------/
+ //
+ //
+ // WE CAN CONVERT THIS INTO THE ABOVE LOGIC BY DOING
+ //
+ // data = &(*args[0]).0 // gives a pointer to Data above (really the same pointer)
+ // vtable = (*args[0]).1 // loads the vtable out
+ // (data, vtable) // an equivalent Rust `*mut dyn Trait`
+ //
+ // SO THEN WE CAN USE THE ABOVE CODE.
+ let virtual_drop = Instance {
+ def: ty::InstanceDef::Virtual(drop_fn.def_id(), 0),
+ substs: drop_fn.substs,
+ };
+ debug!("ty = {:?}", ty);
+ debug!("drop_fn = {:?}", drop_fn);
+ debug!("args = {:?}", args);
+ let fn_abi = bx.fn_abi_of_instance(virtual_drop, ty::List::empty());
+ let meta_ptr = place.project_field(bx, 1);
+ let meta = bx.load_operand(meta_ptr);
+ // Truncate vtable off of args list
+ args = &args[..1];
+ debug!("args' = {:?}", args);
+ (
+ meth::VirtualIndex::from_index(ty::COMMON_VTABLE_ENTRIES_DROPINPLACE)
+ .get_fn(bx, meta.immediate(), ty, &fn_abi),
+ fn_abi,
+ )
+ }
+ _ => (bx.get_fn_addr(drop_fn), bx.fn_abi_of_instance(drop_fn, ty::List::empty())),
+ };
helper.do_call(
self,
bx,
@@ -569,11 +563,13 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
// with #[rustc_inherit_overflow_checks] and inlined from
// another crate (mostly core::num generic/#[inline] fns),
// while the current crate doesn't use overflow checks.
- // NOTE: Unlike binops, negation doesn't have its own
- // checked operation, just a comparison with the minimum
- // value, so we have to check for the assert message.
- if !bx.check_overflow() {
- if let AssertKind::OverflowNeg(_) = *msg {
+ if !bx.cx().check_overflow() {
+ let overflow_not_to_check = match msg {
+ AssertKind::OverflowNeg(..) => true,
+ AssertKind::Overflow(op, ..) => op.is_checkable(),
+ _ => false,
+ };
+ if overflow_not_to_check {
const_cond = Some(expected);
}
}
@@ -659,35 +655,24 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
// Emit a panic or a no-op for `assert_*` intrinsics.
// These are intrinsics that compile to panics so that we can get a message
// which mentions the offending type, even from a const context.
- #[derive(Debug, PartialEq)]
- enum AssertIntrinsic {
- Inhabited,
- ZeroValid,
- MemUninitializedValid,
- }
- let panic_intrinsic = intrinsic.and_then(|i| match i {
- sym::assert_inhabited => Some(AssertIntrinsic::Inhabited),
- sym::assert_zero_valid => Some(AssertIntrinsic::ZeroValid),
- sym::assert_mem_uninitialized_valid => Some(AssertIntrinsic::MemUninitializedValid),
- _ => None,
- });
- if let Some(intrinsic) = panic_intrinsic {
- use AssertIntrinsic::*;
-
+ let panic_intrinsic = intrinsic.and_then(|s| ValidityRequirement::from_intrinsic(s));
+ if let Some(requirement) = panic_intrinsic {
let ty = instance.unwrap().substs.type_at(0);
+
+ let do_panic = !bx
+ .tcx()
+ .check_validity_requirement((requirement, bx.param_env().and(ty)))
+ .expect("expect to have layout during codegen");
+
let layout = bx.layout_of(ty);
- let do_panic = match intrinsic {
- Inhabited => layout.abi.is_uninhabited(),
- ZeroValid => !bx.tcx().permits_zero_init(layout),
- MemUninitializedValid => !bx.tcx().permits_uninit_init(layout),
- };
+
Some(if do_panic {
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 {
+ } else if requirement == ValidityRequirement::Zero {
format!("attempted to zero-initialize type `{}`, which is invalid", ty)
} else {
format!(
@@ -781,7 +766,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
};
let extra_args = &args[sig.inputs().skip_binder().len()..];
- let extra_args = bx.tcx().mk_type_list(extra_args.iter().map(|op_arg| {
+ let extra_args = bx.tcx().mk_type_list_from_iter(extra_args.iter().map(|op_arg| {
let op_ty = op_arg.ty(self.mir, bx.tcx());
self.monomorphize(op_ty)
}));
@@ -1253,9 +1238,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
) -> MergingSucc {
debug!("codegen_terminator: {:?}", terminator);
- // Create the cleanup bundle, if needed.
- let funclet_bb = self.cleanup_kinds[bb].funclet_bb(bb);
- let helper = TerminatorCodegenHelper { bb, terminator, funclet_bb };
+ let helper = TerminatorCodegenHelper { bb, terminator };
let mergeable_succ = || {
// Note: any call to `switch_to_block` will invalidate a `true` value
@@ -1547,7 +1530,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
slot
} else {
let layout = cx.layout_of(
- cx.tcx().intern_tup(&[cx.tcx().mk_mut_ptr(cx.tcx().types.u8), cx.tcx().types.i32]),
+ cx.tcx().mk_tup(&[cx.tcx().mk_mut_ptr(cx.tcx().types.u8), cx.tcx().types.i32]),
);
let slot = PlaceRef::alloca(bx, layout);
self.personality_slot = Some(slot);
@@ -1801,8 +1784,8 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
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.
- let src_is_ptr = src_scalar.primitive() == abi::Pointer;
- let dst_is_ptr = dst_scalar.primitive() == abi::Pointer;
+ let src_is_ptr = matches!(src_scalar.primitive(), abi::Pointer(_));
+ let dst_is_ptr = matches!(dst_scalar.primitive(), abi::Pointer(_));
if src_is_ptr == dst_is_ptr {
assert_eq!(src.layout.size, dst.layout.size);
diff --git a/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs b/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs
index e9bc40c33..708f3bc0c 100644
--- a/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs
@@ -385,10 +385,9 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
calculate_debuginfo_offset(bx, local, &var, base);
// Create a variable which will be a pointer to the actual value
- let ptr_ty = bx.tcx().mk_ty(ty::RawPtr(ty::TypeAndMut {
- mutbl: mir::Mutability::Mut,
- ty: place.layout.ty,
- }));
+ let ptr_ty = bx
+ .tcx()
+ .mk_ptr(ty::TypeAndMut { mutbl: mir::Mutability::Mut, ty: place.layout.ty });
let ptr_layout = bx.layout_of(ptr_ty);
let alloca = PlaceRef::alloca(bx, ptr_layout);
bx.set_var_name(alloca.llval, &(var.name.to_string() + ".dbg.spill"));
diff --git a/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs b/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs
index 766dc74cb..7af7fc92d 100644
--- a/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs
@@ -218,9 +218,6 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
args[1].val.unaligned_volatile_store(bx, dst);
return;
}
- sym::add_with_overflow
- | sym::sub_with_overflow
- | sym::mul_with_overflow
| sym::unchecked_div
| sym::unchecked_rem
| sym::unchecked_shl
@@ -232,28 +229,6 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
let ty = arg_tys[0];
match int_type_width_signed(ty, bx.tcx()) {
Some((_width, signed)) => match name {
- sym::add_with_overflow
- | sym::sub_with_overflow
- | sym::mul_with_overflow => {
- let op = match name {
- sym::add_with_overflow => OverflowOp::Add,
- sym::sub_with_overflow => OverflowOp::Sub,
- sym::mul_with_overflow => OverflowOp::Mul,
- _ => bug!(),
- };
- let (val, overflow) =
- bx.checked_binop(op, ty, args[0].immediate(), args[1].immediate());
- // Convert `i1` to a `bool`, and write it to the out parameter
- let val = bx.from_immediate(val);
- let overflow = bx.from_immediate(overflow);
-
- let dest = result.project_field(bx, 0);
- bx.store(val, dest.llval, dest.align);
- let dest = result.project_field(bx, 1);
- bx.store(overflow, dest.llval, dest.align);
-
- return;
- }
sym::exact_div => {
if signed {
bx.exactsdiv(args[0].immediate(), args[1].immediate())
diff --git a/compiler/rustc_codegen_ssa/src/mir/mod.rs b/compiler/rustc_codegen_ssa/src/mir/mod.rs
index 79c66a955..2ec9fdbf4 100644
--- a/compiler/rustc_codegen_ssa/src/mir/mod.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/mod.rs
@@ -1,8 +1,9 @@
+use crate::base;
use crate::traits::*;
use rustc_middle::mir;
use rustc_middle::mir::interpret::ErrorHandled;
use rustc_middle::ty::layout::{FnAbiOf, HasTyCtxt, TyAndLayout};
-use rustc_middle::ty::{self, Instance, Ty, TypeFoldable, TypeVisitable};
+use rustc_middle::ty::{self, Instance, Ty, TyCtxt, TypeFoldable, TypeVisitableExt};
use rustc_target::abi::call::{FnAbi, PassMode};
use std::iter;
@@ -58,7 +59,7 @@ pub struct FunctionCx<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> {
cached_llbbs: IndexVec<mir::BasicBlock, CachedLlbb<Bx::BasicBlock>>,
/// The funclet status of each basic block
- cleanup_kinds: IndexVec<mir::BasicBlock, analyze::CleanupKind>,
+ cleanup_kinds: Option<IndexVec<mir::BasicBlock, analyze::CleanupKind>>,
/// When targeting MSVC, this stores the cleanup info for each funclet BB.
/// This is initialized at the same time as the `landing_pads` entry for the
@@ -104,7 +105,7 @@ pub struct FunctionCx<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> {
impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
pub fn monomorphize<T>(&self, value: T) -> T
where
- T: Copy + TypeFoldable<'tcx>,
+ T: Copy + TypeFoldable<TyCtxt<'tcx>>,
{
debug!("monomorphize: self.instance={:?}", self.instance);
self.instance.subst_mir_and_normalize_erasing_regions(
@@ -166,7 +167,8 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
start_bx.set_personality_fn(cx.eh_personality());
}
- let cleanup_kinds = analyze::cleanup_kinds(&mir);
+ let cleanup_kinds = base::wants_msvc_seh(cx.tcx().sess).then(|| analyze::cleanup_kinds(&mir));
+
let cached_llbbs: IndexVec<mir::BasicBlock, CachedLlbb<Bx::BasicBlock>> =
mir.basic_blocks
.indices()
diff --git a/compiler/rustc_codegen_ssa/src/mir/place.rs b/compiler/rustc_codegen_ssa/src/mir/place.rs
index fbe30154a..cf02f59f6 100644
--- a/compiler/rustc_codegen_ssa/src/mir/place.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/place.rs
@@ -9,7 +9,7 @@ use rustc_middle::mir;
use rustc_middle::mir::tcx::PlaceTy;
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::{Abi, Align, FieldsShape, Int, Pointer, TagEncoding};
use rustc_target::abi::{VariantIdx, Variants};
#[derive(Copy, Clone, Debug)]
@@ -209,6 +209,7 @@ impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> {
bx: &mut Bx,
cast_to: Ty<'tcx>,
) -> V {
+ let dl = &bx.tcx().data_layout;
let cast_to_layout = bx.cx().layout_of(cast_to);
let cast_to_size = cast_to_layout.layout.size();
let cast_to = bx.cx().immediate_backend_type(cast_to_layout);
@@ -250,12 +251,14 @@ impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> {
TagEncoding::Niche { untagged_variant, ref niche_variants, niche_start } => {
// Cast to an integer so we don't have to treat a pointer as a
// special case.
- let (tag, tag_llty) = if tag_scalar.primitive().is_ptr() {
- let t = bx.type_isize();
- let tag = bx.ptrtoint(tag_imm, t);
- (tag, t)
- } else {
- (tag_imm, bx.cx().immediate_backend_type(tag_op.layout))
+ let (tag, tag_llty) = match tag_scalar.primitive() {
+ // FIXME(erikdesjardins): handle non-default addrspace ptr sizes
+ Pointer(_) => {
+ let t = bx.type_from_integer(dl.ptr_sized_integer());
+ let tag = bx.ptrtoint(tag_imm, t);
+ (tag, t)
+ }
+ _ => (tag_imm, bx.cx().immediate_backend_type(tag_op.layout)),
};
let tag_size = tag_scalar.size(bx.cx());
diff --git a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs
index 23196c8cb..3d856986f 100644
--- a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs
@@ -13,6 +13,7 @@ use rustc_middle::ty::cast::{CastTy, IntTy};
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::VariantIdx;
impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
#[instrument(level = "trace", skip(self, bx))]
@@ -99,24 +100,24 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
}
}
- let count =
- self.monomorphize(count).eval_usize(bx.cx().tcx(), ty::ParamEnv::reveal_all());
+ let count = self
+ .monomorphize(count)
+ .eval_target_usize(bx.cx().tcx(), ty::ParamEnv::reveal_all());
bx.write_operand_repeatedly(cg_elem, count, dest);
}
mir::Rvalue::Aggregate(ref kind, ref operands) => {
- let (dest, active_field_index) = match **kind {
- mir::AggregateKind::Adt(adt_did, variant_index, _, _, active_field_index) => {
- dest.codegen_set_discr(bx, variant_index);
- if bx.tcx().adt_def(adt_did).is_enum() {
- (dest.project_downcast(bx, variant_index), active_field_index)
- } else {
- (dest, active_field_index)
- }
+ let (variant_index, variant_dest, active_field_index) = match **kind {
+ mir::AggregateKind::Adt(_, variant_index, _, _, active_field_index) => {
+ let variant_dest = dest.project_downcast(bx, variant_index);
+ (variant_index, variant_dest, active_field_index)
}
- _ => (dest, None),
+ _ => (VariantIdx::from_u32(0), dest, None),
};
+ if active_field_index.is_some() {
+ assert_eq!(operands.len(), 1);
+ }
for (i, operand) in operands.iter().enumerate() {
let op = self.codegen_operand(bx, operand);
// Do not generate stores and GEPis for zero-sized fields.
@@ -124,13 +125,14 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
let field_index = active_field_index.unwrap_or(i);
let field = if let mir::AggregateKind::Array(_) = **kind {
let llindex = bx.cx().const_usize(field_index as u64);
- dest.project_index(bx, llindex)
+ variant_dest.project_index(bx, llindex)
} else {
- dest.project_field(bx, field_index)
+ variant_dest.project_field(bx, field_index)
};
op.val.store(bx, field);
}
}
+ dest.codegen_set_discr(bx, variant_index);
}
_ => {
@@ -411,7 +413,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
lhs.layout.ty,
);
let val_ty = op.ty(bx.tcx(), lhs.layout.ty, rhs.layout.ty);
- let operand_ty = bx.tcx().intern_tup(&[val_ty, bx.tcx().types.bool]);
+ let operand_ty = bx.tcx().mk_tup(&[val_ty, bx.tcx().types.bool]);
OperandRef { val: result, layout: bx.cx().layout_of(operand_ty) }
}
@@ -491,7 +493,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
if let Some(index) = place.as_local() {
if let LocalRef::Operand(Some(op)) = self.locals[index] {
if let ty::Array(_, n) = op.layout.ty.kind() {
- let n = n.eval_usize(bx.cx().tcx(), ty::ParamEnv::reveal_all());
+ let n = n.eval_target_usize(bx.cx().tcx(), ty::ParamEnv::reveal_all());
return bx.cx().const_usize(n);
}
}
@@ -650,15 +652,6 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
rhs: Bx::Value,
input_ty: Ty<'tcx>,
) -> OperandValue<Bx::Value> {
- // This case can currently arise only from functions marked
- // with #[rustc_inherit_overflow_checks] and inlined from
- // another crate (mostly core::num generic/#[inline] fns),
- // while the current crate doesn't use overflow checks.
- if !bx.cx().check_overflow() {
- let val = self.codegen_scalar_binop(bx, op, lhs, rhs, input_ty);
- return OperandValue::Pair(val, bx.cx().const_bool(false));
- }
-
let (val, of) = match op {
// These are checked using intrinsics
mir::BinOp::Add | mir::BinOp::Sub | mir::BinOp::Mul => {
diff --git a/compiler/rustc_codegen_ssa/src/mir/statement.rs b/compiler/rustc_codegen_ssa/src/mir/statement.rs
index 19452c8cd..60fbceb34 100644
--- a/compiler/rustc_codegen_ssa/src/mir/statement.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/statement.rs
@@ -91,6 +91,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
mir::StatementKind::FakeRead(..)
| mir::StatementKind::Retag { .. }
| mir::StatementKind::AscribeUserType(..)
+ | mir::StatementKind::ConstEvalCounter
| mir::StatementKind::Nop => {}
}
}
diff --git a/compiler/rustc_codegen_ssa/src/target_features.rs b/compiler/rustc_codegen_ssa/src/target_features.rs
index 739963fff..e59fad99a 100644
--- a/compiler/rustc_codegen_ssa/src/target_features.rs
+++ b/compiler/rustc_codegen_ssa/src/target_features.rs
@@ -3,12 +3,12 @@ use rustc_attr::InstructionSetAttr;
use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::fx::FxHashSet;
use rustc_errors::Applicability;
-use rustc_hir as hir;
+use rustc_hir::def::DefKind;
use rustc_hir::def_id::DefId;
use rustc_hir::def_id::LocalDefId;
use rustc_hir::def_id::LOCAL_CRATE;
use rustc_middle::ty::query::Providers;
-use rustc_middle::ty::TyCtxt;
+use rustc_middle::ty::{DefIdTree, TyCtxt};
use rustc_session::parse::feature_err;
use rustc_session::Session;
use rustc_span::symbol::sym;
@@ -185,7 +185,7 @@ const X86_ALLOWED_FEATURES: &[(&str, Option<Symbol>)] = &[
("avx512vpopcntdq", Some(sym::avx512_target_feature)),
("bmi1", None),
("bmi2", None),
- ("cmpxchg16b", Some(sym::cmpxchg16b_target_feature)),
+ ("cmpxchg16b", None),
("ermsb", Some(sym::ermsb_target_feature)),
("f16c", None),
("fma", None),
@@ -286,6 +286,7 @@ const WASM_ALLOWED_FEATURES: &[(&str, Option<Symbol>)] = &[
("mutable-globals", Some(sym::wasm_target_feature)),
("nontrapping-fptoint", Some(sym::wasm_target_feature)),
("reference-types", Some(sym::wasm_target_feature)),
+ ("relaxed-simd", Some(sym::wasm_target_feature)),
("sign-ext", Some(sym::wasm_target_feature)),
("simd128", None),
// tidy-alphabetical-end
@@ -393,7 +394,6 @@ pub fn from_target_feature(
Some(sym::sse4a_target_feature) => rust_features.sse4a_target_feature,
Some(sym::tbm_target_feature) => rust_features.tbm_target_feature,
Some(sym::wasm_target_feature) => rust_features.wasm_target_feature,
- Some(sym::cmpxchg16b_target_feature) => rust_features.cmpxchg16b_target_feature,
Some(sym::movbe_target_feature) => rust_features.movbe_target_feature,
Some(sym::rtm_target_feature) => rust_features.rtm_target_feature,
Some(sym::ermsb_target_feature) => rust_features.ermsb_target_feature,
@@ -440,12 +440,9 @@ fn asm_target_features(tcx: TyCtxt<'_>, did: DefId) -> &FxHashSet<Symbol> {
/// Checks the function annotated with `#[target_feature]` is not a safe
/// trait method implementation, reporting an error if it is.
pub fn check_target_feature_trait_unsafe(tcx: TyCtxt<'_>, id: LocalDefId, attr_span: Span) {
- let hir_id = tcx.hir().local_def_id_to_hir_id(id);
- let node = tcx.hir().get(hir_id);
- if let hir::Node::ImplItem(hir::ImplItem { kind: hir::ImplItemKind::Fn(..), .. }) = node {
- let parent_id = tcx.hir().get_parent_item(hir_id);
- let parent_item = tcx.hir().expect_item(parent_id.def_id);
- if let hir::ItemKind::Impl(hir::Impl { of_trait: Some(_), .. }) = parent_item.kind {
+ if let DefKind::AssocFn = tcx.def_kind(id) {
+ let parent_id = tcx.local_parent(id);
+ if let DefKind::Impl { of_trait: true } = tcx.def_kind(parent_id) {
tcx.sess
.struct_span_err(
attr_span,
diff --git a/compiler/rustc_codegen_ssa/src/traits/backend.rs b/compiler/rustc_codegen_ssa/src/traits/backend.rs
index 5c35070ea..64bebe50d 100644
--- a/compiler/rustc_codegen_ssa/src/traits/backend.rs
+++ b/compiler/rustc_codegen_ssa/src/traits/backend.rs
@@ -57,6 +57,10 @@ impl<'tcx, T> Backend<'tcx> for T where
}
pub trait CodegenBackend {
+ /// Locale resources for diagnostic messages - a string the content of the Fluent resource.
+ /// Called before `init` so that all other functions are able to emit translatable diagnostics.
+ fn locale_resource(&self) -> &'static str;
+
fn init(&self, _sess: &Session) {}
fn print(&self, _req: PrintRequest, _sess: &Session) {}
fn target_features(&self, _sess: &Session, _allow_unstable: bool) -> Vec<Symbol> {
diff --git a/compiler/rustc_codegen_ssa/src/traits/write.rs b/compiler/rustc_codegen_ssa/src/traits/write.rs
index e0e8ffa89..9826256a4 100644
--- a/compiler/rustc_codegen_ssa/src/traits/write.rs
+++ b/compiler/rustc_codegen_ssa/src/traits/write.rs
@@ -8,6 +8,7 @@ use rustc_middle::dep_graph::WorkProduct;
pub trait WriteBackendMethods: 'static + Sized + Clone {
type Module: Send + Sync;
type TargetMachine;
+ type TargetMachineError;
type ModuleBuffer: ModuleBufferMethods;
type ThinData: Send + Sync;
type ThinBuffer: ThinBufferMethods;
diff --git a/compiler/rustc_const_eval/Cargo.toml b/compiler/rustc_const_eval/Cargo.toml
index 51489e293..98ac36c1c 100644
--- a/compiler/rustc_const_eval/Cargo.toml
+++ b/compiler/rustc_const_eval/Cargo.toml
@@ -19,7 +19,6 @@ 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" }
diff --git a/compiler/rustc_error_messages/locales/en-US/const_eval.ftl b/compiler/rustc_const_eval/locales/en-US.ftl
index 33bb116d6..33bb116d6 100644
--- a/compiler/rustc_error_messages/locales/en-US/const_eval.ftl
+++ b/compiler/rustc_const_eval/locales/en-US.ftl
diff --git a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs
index 18e01567c..7564ba17b 100644
--- a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs
+++ b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs
@@ -54,7 +54,7 @@ fn eval_body_using_ecx<'mir, 'tcx>(
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()))),
+ with_no_trimmed_paths!(ecx.tcx.def_path_str(cid.instance.def_id())),
cid.promoted.map_or_else(String::new, |p| format!("::promoted[{:?}]", p))
);
@@ -180,13 +180,13 @@ pub(super) fn op_to_const<'tcx>(
(ecx.tcx.global_alloc(alloc_id).unwrap_memory(), offset.bytes())
}
(None, _offset) => (
- ecx.tcx.intern_const_alloc(Allocation::from_bytes_byte_aligned_immutable(
+ ecx.tcx.mk_const_alloc(Allocation::from_bytes_byte_aligned_immutable(
b"" as &[u8],
)),
0,
),
};
- let len = b.to_machine_usize(ecx).unwrap();
+ let len = b.to_target_usize(ecx).unwrap();
let start = start.try_into().unwrap();
let len: usize = len.try_into().unwrap();
ConstValue::Slice { data, start, end: start + len }
diff --git a/compiler/rustc_const_eval/src/const_eval/fn_queries.rs b/compiler/rustc_const_eval/src/const_eval/fn_queries.rs
index 351c70130..9eaab1f47 100644
--- a/compiler/rustc_const_eval/src/const_eval/fn_queries.rs
+++ b/compiler/rustc_const_eval/src/const_eval/fn_queries.rs
@@ -17,7 +17,8 @@ pub fn is_unstable_const_fn(tcx: TyCtxt<'_>, def_id: DefId) -> Option<Symbol> {
pub fn is_parent_const_impl_raw(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool {
let parent_id = tcx.local_parent(def_id);
- tcx.def_kind(parent_id) == DefKind::Impl && tcx.constness(parent_id) == hir::Constness::Const
+ matches!(tcx.def_kind(parent_id), DefKind::Impl { .. })
+ && tcx.constness(parent_id) == hir::Constness::Const
}
/// Checks whether an item is considered to be `const`. If it is a constructor, it is const. If
@@ -66,7 +67,7 @@ fn is_promotable_const_fn(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
if cfg!(debug_assertions) && stab.promotable {
let sig = tcx.fn_sig(def_id);
assert_eq!(
- sig.unsafety(),
+ sig.skip_binder().unsafety(),
hir::Unsafety::Normal,
"don't mark const unsafe fns as promotable",
// https://github.com/rust-lang/rust/pull/53851#issuecomment-418760682
diff --git a/compiler/rustc_const_eval/src/const_eval/machine.rs b/compiler/rustc_const_eval/src/const_eval/machine.rs
index 4709514c8..a44f70ed0 100644
--- a/compiler/rustc_const_eval/src/const_eval/machine.rs
+++ b/compiler/rustc_const_eval/src/const_eval/machine.rs
@@ -244,7 +244,7 @@ impl<'mir, 'tcx: 'mir> CompileTimeEvalContext<'mir, 'tcx> {
assert_eq!(args.len(), 2);
let ptr = self.read_pointer(&args[0])?;
- let target_align = self.read_scalar(&args[1])?.to_machine_usize(self)?;
+ let target_align = self.read_scalar(&args[1])?.to_target_usize(self)?;
if !target_align.is_power_of_two() {
throw_ub_format!("`align_offset` called with non-power-of-two align: {}", target_align);
@@ -276,7 +276,7 @@ impl<'mir, 'tcx: 'mir> CompileTimeEvalContext<'mir, 'tcx> {
Ok(ControlFlow::Break(()))
} else {
// Not alignable in const, return `usize::MAX`.
- let usize_max = Scalar::from_machine_usize(self.machine_usize_max(), self);
+ let usize_max = Scalar::from_target_usize(self.target_usize_max(), self);
self.write_scalar(usize_max, dest)?;
self.return_to_block(ret)?;
Ok(ControlFlow::Break(()))
@@ -470,8 +470,8 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
ecx.write_scalar(Scalar::from_u8(cmp), dest)?;
}
sym::const_allocate => {
- let size = ecx.read_scalar(&args[0])?.to_machine_usize(ecx)?;
- let align = ecx.read_scalar(&args[1])?.to_machine_usize(ecx)?;
+ let size = ecx.read_scalar(&args[0])?.to_target_usize(ecx)?;
+ let align = ecx.read_scalar(&args[1])?.to_target_usize(ecx)?;
let align = match Align::from_bytes(align) {
Ok(a) => a,
@@ -487,8 +487,8 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
}
sym::const_deallocate => {
let ptr = ecx.read_pointer(&args[0])?;
- let size = ecx.read_scalar(&args[1])?.to_machine_usize(ecx)?;
- let align = ecx.read_scalar(&args[2])?.to_machine_usize(ecx)?;
+ let size = ecx.read_scalar(&args[1])?.to_target_usize(ecx)?;
+ let align = ecx.read_scalar(&args[2])?.to_target_usize(ecx)?;
let size = Size::from_bytes(size);
let align = match Align::from_bytes(align) {
@@ -561,8 +561,8 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
throw_unsup_format!("pointer arithmetic or comparison is not supported at compile-time");
}
- fn before_terminator(ecx: &mut InterpCx<'mir, 'tcx, Self>) -> InterpResult<'tcx> {
- // The step limit has already been hit in a previous call to `before_terminator`.
+ fn increment_const_eval_counter(ecx: &mut InterpCx<'mir, 'tcx, Self>) -> InterpResult<'tcx> {
+ // The step limit has already been hit in a previous call to `increment_const_eval_counter`.
if ecx.machine.steps_remaining == 0 {
return Ok(());
}
@@ -622,10 +622,9 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
let alloc = alloc.inner();
if is_write {
// Write access. These are never allowed, but we give a targeted error message.
- if alloc.mutability == Mutability::Not {
- Err(err_ub!(WriteToReadOnly(alloc_id)).into())
- } else {
- Err(ConstEvalErrKind::ModifiedGlobal.into())
+ match alloc.mutability {
+ Mutability::Not => Err(err_ub!(WriteToReadOnly(alloc_id)).into()),
+ Mutability::Mut => Err(ConstEvalErrKind::ModifiedGlobal.into()),
}
} else {
// Read access. These are usually allowed, with some exceptions.
diff --git a/compiler/rustc_const_eval/src/const_eval/mod.rs b/compiler/rustc_const_eval/src/const_eval/mod.rs
index 01b2b4b5d..3cdf1e6e3 100644
--- a/compiler/rustc_const_eval/src/const_eval/mod.rs
+++ b/compiler/rustc_const_eval/src/const_eval/mod.rs
@@ -107,7 +107,7 @@ pub(crate) fn try_destructure_mir_constant<'tcx>(
// We go to `usize` as we cannot allocate anything bigger anyway.
let (field_count, variant, down) = match val.ty().kind() {
- ty::Array(_, len) => (len.eval_usize(tcx, param_env) as usize, None, op),
+ ty::Array(_, len) => (len.eval_target_usize(tcx, param_env) as usize, None, op),
ty::Adt(def, _) if def.variants().is_empty() => {
throw_ub!(Unreachable)
}
@@ -155,7 +155,7 @@ pub(crate) fn deref_mir_constant<'tcx>(
// In case of unsized types, figure out the real type behind.
MemPlaceMeta::Meta(scalar) => match mplace.layout.ty.kind() {
ty::Str => bug!("there's no sized equivalent of a `str`"),
- ty::Slice(elem_ty) => tcx.mk_array(*elem_ty, scalar.to_machine_usize(&tcx).unwrap()),
+ ty::Slice(elem_ty) => tcx.mk_array(*elem_ty, scalar.to_target_usize(&tcx).unwrap()),
_ => bug!(
"type {} should not have metadata, but had {:?}",
mplace.layout.ty,
diff --git a/compiler/rustc_const_eval/src/const_eval/valtrees.rs b/compiler/rustc_const_eval/src/const_eval/valtrees.rs
index 498c00873..a73f778d4 100644
--- a/compiler/rustc_const_eval/src/const_eval/valtrees.rs
+++ b/compiler/rustc_const_eval/src/const_eval/valtrees.rs
@@ -151,7 +151,7 @@ pub(crate) fn const_to_valtree_inner<'tcx>(
// FIXME(oli-obk): we can probably encode closures just like structs
| ty::Closure(..)
| ty::Generator(..)
- | ty::GeneratorWitness(..) => Err(ValTreeCreationError::NonSupportedType),
+ | ty::GeneratorWitness(..) |ty::GeneratorWitnessMIR(..)=> Err(ValTreeCreationError::NonSupportedType),
}
}
@@ -193,7 +193,7 @@ fn get_info_on_unsized_field<'tcx>(
// Have to adjust type for ty::Str
let unsized_inner_ty = match unsized_inner_ty.kind() {
- ty::Str => tcx.mk_ty(ty::Uint(ty::UintTy::U8)),
+ ty::Str => tcx.types.u8,
_ => unsized_inner_ty,
};
@@ -216,7 +216,7 @@ fn create_pointee_place<'tcx>(
let (unsized_inner_ty, num_elems) = get_info_on_unsized_field(ty, valtree, tcx);
let unsized_inner_ty = match unsized_inner_ty.kind() {
- ty::Str => tcx.mk_ty(ty::Uint(ty::UintTy::U8)),
+ ty::Str => tcx.types.u8,
_ => unsized_inner_ty,
};
let unsized_inner_ty_size =
@@ -239,7 +239,7 @@ fn create_pointee_place<'tcx>(
MPlaceTy::from_aligned_ptr_with_meta(
ptr.into(),
layout,
- MemPlaceMeta::Meta(Scalar::from_machine_usize(num_elems as u64, &tcx)),
+ MemPlaceMeta::Meta(Scalar::from_target_usize(num_elems as u64, &tcx)),
)
} else {
create_mplace_from_layout(ecx, ty)
@@ -314,6 +314,7 @@ pub fn valtree_to_const_value<'tcx>(
| ty::Closure(..)
| ty::Generator(..)
| ty::GeneratorWitness(..)
+ | ty::GeneratorWitnessMIR(..)
| ty::FnPtr(_)
| ty::RawPtr(_)
| ty::Str
@@ -354,7 +355,7 @@ fn valtree_into_mplace<'tcx>(
let imm = match inner_ty.kind() {
ty::Slice(_) | ty::Str => {
let len = valtree.unwrap_branch().len();
- let len_scalar = Scalar::from_machine_usize(len as u64, &tcx);
+ let len_scalar = Scalar::from_target_usize(len as u64, &tcx);
Immediate::ScalarPair(
Scalar::from_maybe_pointer((*pointee_place).ptr, &tcx),
@@ -425,7 +426,7 @@ fn valtree_into_mplace<'tcx>(
place
.offset_with_meta(
offset,
- MemPlaceMeta::Meta(Scalar::from_machine_usize(
+ MemPlaceMeta::Meta(Scalar::from_target_usize(
num_elems as u64,
&tcx,
)),
diff --git a/compiler/rustc_const_eval/src/errors.rs b/compiler/rustc_const_eval/src/errors.rs
index 4b0550767..f8b7cc6d7 100644
--- a/compiler/rustc_const_eval/src/errors.rs
+++ b/compiler/rustc_const_eval/src/errors.rs
@@ -9,12 +9,12 @@ pub(crate) struct UnstableInStable {
#[primary_span]
pub span: Span,
#[suggestion(
- unstable_sugg,
+ const_eval_unstable_sugg,
code = "#[rustc_const_unstable(feature = \"...\", issue = \"...\")]\n",
applicability = "has-placeholders"
)]
#[suggestion(
- bypass_sugg,
+ const_eval_bypass_sugg,
code = "#[rustc_allow_const_fn_unstable({gate})]\n",
applicability = "has-placeholders"
)]
@@ -35,15 +35,15 @@ pub(crate) struct StaticAccessErr {
#[primary_span]
pub span: Span,
pub kind: ConstContext,
- #[note(teach_note)]
- #[help(teach_help)]
+ #[note(const_eval_teach_note)]
+ #[help(const_eval_teach_help)]
pub teach: Option<()>,
}
#[derive(Diagnostic)]
#[diag(const_eval_raw_ptr_to_int)]
#[note]
-#[note(note2)]
+#[note(const_eval_note2)]
pub(crate) struct RawPtrToIntErr {
#[primary_span]
pub span: Span,
@@ -118,7 +118,7 @@ pub(crate) struct UnallowedMutableRefs {
#[primary_span]
pub span: Span,
pub kind: ConstContext,
- #[note(teach_note)]
+ #[note(const_eval_teach_note)]
pub teach: Option<()>,
}
@@ -128,7 +128,7 @@ pub(crate) struct UnallowedMutableRefsRaw {
#[primary_span]
pub span: Span,
pub kind: ConstContext,
- #[note(teach_note)]
+ #[note(const_eval_teach_note)]
pub teach: Option<()>,
}
#[derive(Diagnostic)]
@@ -163,7 +163,7 @@ pub(crate) struct UnallowedHeapAllocations {
#[label]
pub span: Span,
pub kind: ConstContext,
- #[note(teach_note)]
+ #[note(const_eval_teach_note)]
pub teach: Option<()>,
}
@@ -184,7 +184,7 @@ pub(crate) struct InteriorMutableDataRefer {
#[help]
pub opt_help: Option<()>,
pub kind: ConstContext,
- #[note(teach_note)]
+ #[note(const_eval_teach_note)]
pub teach: Option<()>,
}
diff --git a/compiler/rustc_const_eval/src/interpret/cast.rs b/compiler/rustc_const_eval/src/interpret/cast.rs
index b2c847d3f..2be5ed896 100644
--- a/compiler/rustc_const_eval/src/interpret/cast.rs
+++ b/compiler/rustc_const_eval/src/interpret/cast.rs
@@ -126,7 +126,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
let vtable = self.get_vtable_ptr(src.layout.ty, data.principal())?;
let vtable = Scalar::from_maybe_pointer(vtable, self);
let data = self.read_immediate(src)?.to_scalar();
- let _assert_pointer_sized = data.to_pointer(self)?;
+ let _assert_pointer_like = data.to_pointer(self)?;
let val = Immediate::ScalarPair(data, vtable);
self.write_immediate(val, dest)?;
} else {
@@ -231,7 +231,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
// First cast to usize.
let scalar = src.to_scalar();
let addr = self.cast_from_int_like(scalar, src.layout, self.tcx.types.usize)?;
- let addr = addr.to_machine_usize(self)?;
+ let addr = addr.to_target_usize(self)?;
// Then turn address into pointer.
let ptr = M::ptr_from_addr_cast(&self, addr)?;
@@ -312,6 +312,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
}
}
+ /// `src` is a *pointer to* a `source_ty`, and in `dest` we should store a pointer to th same
+ /// data at type `cast_ty`.
fn unsize_into_ptr(
&mut self,
src: &OpTy<'tcx, M::Provenance>,
@@ -328,11 +330,14 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
(&ty::Array(_, length), &ty::Slice(_)) => {
let ptr = self.read_scalar(src)?;
// u64 cast is from usize to u64, which is always good
- let val =
- Immediate::new_slice(ptr, length.eval_usize(*self.tcx, self.param_env), self);
+ let val = Immediate::new_slice(
+ ptr,
+ length.eval_target_usize(*self.tcx, self.param_env),
+ self,
+ );
self.write_immediate(val, dest)
}
- (ty::Dynamic(data_a, ..), ty::Dynamic(data_b, ..)) => {
+ (ty::Dynamic(data_a, _, ty::Dyn), ty::Dynamic(data_b, _, ty::Dyn)) => {
let val = self.read_immediate(src)?;
if data_a.principal() == data_b.principal() {
// A NOP cast that doesn't actually change anything, should be allowed even with mismatching vtables.
@@ -356,7 +361,12 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
}
_ => {
- span_bug!(self.cur_span(), "invalid unsizing {:?} -> {:?}", src.layout.ty, cast_ty)
+ span_bug!(
+ self.cur_span(),
+ "invalid pointer unsizing {:?} -> {:?}",
+ src.layout.ty,
+ cast_ty
+ )
}
}
}
diff --git a/compiler/rustc_const_eval/src/interpret/discriminant.rs b/compiler/rustc_const_eval/src/interpret/discriminant.rs
new file mode 100644
index 000000000..557e72124
--- /dev/null
+++ b/compiler/rustc_const_eval/src/interpret/discriminant.rs
@@ -0,0 +1,238 @@
+//! Functions for reading and writing discriminants of multi-variant layouts (enums and generators).
+
+use rustc_middle::ty::layout::{LayoutOf, PrimitiveExt};
+use rustc_middle::{mir, ty};
+use rustc_target::abi::{self, TagEncoding};
+use rustc_target::abi::{VariantIdx, Variants};
+
+use super::{ImmTy, InterpCx, InterpResult, Machine, OpTy, PlaceTy, Scalar};
+
+impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
+ /// Writes the discriminant of the given variant.
+ #[instrument(skip(self), level = "trace")]
+ pub fn write_discriminant(
+ &mut self,
+ variant_index: VariantIdx,
+ dest: &PlaceTy<'tcx, M::Provenance>,
+ ) -> InterpResult<'tcx> {
+ // 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!(UninhabitedEnumVariantWritten)
+ }
+
+ match dest.layout.variants {
+ abi::Variants::Single { index } => {
+ assert_eq!(index, variant_index);
+ }
+ abi::Variants::Multiple {
+ tag_encoding: TagEncoding::Direct,
+ tag: tag_layout,
+ tag_field,
+ ..
+ } => {
+ // No need to validate that the discriminant here because the
+ // `TyAndLayout::for_variant()` call earlier already checks the variant is valid.
+
+ let discr_val =
+ dest.layout.ty.discriminant_for_variant(*self.tcx, variant_index).unwrap().val;
+
+ // raw discriminants for enums are isize or bigger during
+ // their computation, but the in-memory tag is the smallest possible
+ // representation
+ let size = tag_layout.size(self);
+ let tag_val = size.truncate(discr_val);
+
+ let tag_dest = self.place_field(dest, tag_field)?;
+ self.write_scalar(Scalar::from_uint(tag_val, size), &tag_dest)?;
+ }
+ abi::Variants::Multiple {
+ tag_encoding:
+ TagEncoding::Niche { untagged_variant, ref niche_variants, niche_start },
+ tag: tag_layout,
+ tag_field,
+ ..
+ } => {
+ // No need to validate that the discriminant here because the
+ // `TyAndLayout::for_variant()` call earlier already checks the variant is valid.
+
+ if variant_index != untagged_variant {
+ let variants_start = niche_variants.start().as_u32();
+ let variant_index_relative = variant_index
+ .as_u32()
+ .checked_sub(variants_start)
+ .expect("overflow computing relative variant idx");
+ // We need to use machine arithmetic when taking into account `niche_start`:
+ // tag_val = variant_index_relative + niche_start_val
+ let tag_layout = self.layout_of(tag_layout.primitive().to_int_ty(*self.tcx))?;
+ let niche_start_val = ImmTy::from_uint(niche_start, tag_layout);
+ let variant_index_relative_val =
+ ImmTy::from_uint(variant_index_relative, tag_layout);
+ let tag_val = self.binary_op(
+ mir::BinOp::Add,
+ &variant_index_relative_val,
+ &niche_start_val,
+ )?;
+ // Write result.
+ let niche_dest = self.place_field(dest, tag_field)?;
+ self.write_immediate(*tag_val, &niche_dest)?;
+ }
+ }
+ }
+
+ Ok(())
+ }
+
+ /// 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)!
+ #[instrument(skip(self), level = "trace")]
+ pub fn read_discriminant(
+ &self,
+ op: &OpTy<'tcx, M::Provenance>,
+ ) -> InterpResult<'tcx, (Scalar<M::Provenance>, VariantIdx)> {
+ trace!("read_discriminant_value {:#?}", op.layout);
+ // Get type and layout of the discriminant.
+ let discr_layout = self.layout_of(op.layout.ty.discriminant_ty(*self.tcx))?;
+ trace!("discriminant type: {:?}", discr_layout.ty);
+
+ // We use "discriminant" to refer to the value associated with a particular enum variant.
+ // This is not to be confused with its "variant index", which is just determining its position in the
+ // declared list of variants -- they can differ with explicitly assigned discriminants.
+ // We use "tag" to refer to how the discriminant is encoded in memory, which can be either
+ // straight-forward (`TagEncoding::Direct`) or with a niche (`TagEncoding::Niche`).
+ let (tag_scalar_layout, tag_encoding, tag_field) = match op.layout.variants {
+ Variants::Single { index } => {
+ let discr = match op.layout.ty.discriminant_for_variant(*self.tcx, index) {
+ Some(discr) => {
+ // This type actually has discriminants.
+ assert_eq!(discr.ty, discr_layout.ty);
+ Scalar::from_uint(discr.val, discr_layout.size)
+ }
+ None => {
+ // On a type without actual discriminants, variant is 0.
+ assert_eq!(index.as_u32(), 0);
+ Scalar::from_uint(index.as_u32(), discr_layout.size)
+ }
+ };
+ return Ok((discr, index));
+ }
+ Variants::Multiple { tag, ref tag_encoding, tag_field, .. } => {
+ (tag, tag_encoding, tag_field)
+ }
+ };
+
+ // There are *three* layouts that come into play here:
+ // - The discriminant has a type for typechecking. This is `discr_layout`, and is used for
+ // the `Scalar` we return.
+ // - The tag (encoded discriminant) has layout `tag_layout`. This is always an integer type,
+ // and used to interpret the value we read from the tag field.
+ // For the return value, a cast to `discr_layout` is performed.
+ // - The field storing the tag has a layout, which is very similar to `tag_layout` but
+ // may be a pointer. This is `tag_val.layout`; we just use it for sanity checks.
+
+ // Get layout for tag.
+ let tag_layout = self.layout_of(tag_scalar_layout.primitive().to_int_ty(*self.tcx))?;
+
+ // Read tag and sanity-check `tag_layout`.
+ let tag_val = self.read_immediate(&self.operand_field(op, tag_field)?)?;
+ assert_eq!(tag_layout.size, tag_val.layout.size);
+ assert_eq!(tag_layout.abi.is_signed(), tag_val.layout.abi.is_signed());
+ trace!("tag value: {}", tag_val);
+
+ // Figure out which discriminant and variant this corresponds to.
+ Ok(match *tag_encoding {
+ TagEncoding::Direct => {
+ let scalar = tag_val.to_scalar();
+ // Generate a specific error if `tag_val` is not an integer.
+ // (`tag_bits` itself is only used for error messages below.)
+ let tag_bits = scalar
+ .try_to_int()
+ .map_err(|dbg_val| err_ub!(InvalidTag(dbg_val)))?
+ .assert_bits(tag_layout.size);
+ // Cast bits from tag layout to discriminant layout.
+ // After the checks we did above, this cannot fail, as
+ // discriminants are int-like.
+ let discr_val =
+ self.cast_from_int_like(scalar, tag_val.layout, discr_layout.ty).unwrap();
+ let discr_bits = discr_val.assert_bits(discr_layout.size);
+ // Convert discriminant to variant index, and catch invalid discriminants.
+ let index = match *op.layout.ty.kind() {
+ ty::Adt(adt, _) => {
+ adt.discriminants(*self.tcx).find(|(_, var)| var.val == discr_bits)
+ }
+ ty::Generator(def_id, substs, _) => {
+ let substs = substs.as_generator();
+ substs
+ .discriminants(def_id, *self.tcx)
+ .find(|(_, var)| var.val == discr_bits)
+ }
+ _ => span_bug!(self.cur_span(), "tagged layout for non-adt non-generator"),
+ }
+ .ok_or_else(|| err_ub!(InvalidTag(Scalar::from_uint(tag_bits, tag_layout.size))))?;
+ // Return the cast value, and the index.
+ (discr_val, index.0)
+ }
+ TagEncoding::Niche { untagged_variant, ref niche_variants, niche_start } => {
+ let tag_val = tag_val.to_scalar();
+ // Compute the variant this niche value/"tag" corresponds to. With niche layout,
+ // discriminant (encoded in niche/tag) and variant index are the same.
+ let variants_start = niche_variants.start().as_u32();
+ let variants_end = niche_variants.end().as_u32();
+ let variant = match tag_val.try_to_int() {
+ Err(dbg_val) => {
+ // So this is a pointer then, and casting to an int failed.
+ // Can only happen during CTFE.
+ // The niche must be just 0, and the ptr not null, then we know this is
+ // okay. Everything else, we conservatively reject.
+ let ptr_valid = niche_start == 0
+ && variants_start == variants_end
+ && !self.scalar_may_be_null(tag_val)?;
+ if !ptr_valid {
+ throw_ub!(InvalidTag(dbg_val))
+ }
+ untagged_variant
+ }
+ Ok(tag_bits) => {
+ let tag_bits = tag_bits.assert_bits(tag_layout.size);
+ // We need to use machine arithmetic to get the relative variant idx:
+ // variant_index_relative = tag_val - niche_start_val
+ let tag_val = ImmTy::from_uint(tag_bits, tag_layout);
+ let niche_start_val = ImmTy::from_uint(niche_start, tag_layout);
+ let variant_index_relative_val =
+ self.binary_op(mir::BinOp::Sub, &tag_val, &niche_start_val)?;
+ let variant_index_relative =
+ variant_index_relative_val.to_scalar().assert_bits(tag_val.layout.size);
+ // Check if this is in the range that indicates an actual discriminant.
+ if variant_index_relative <= u128::from(variants_end - variants_start) {
+ let variant_index_relative = u32::try_from(variant_index_relative)
+ .expect("we checked that this fits into a u32");
+ // Then computing the absolute variant idx should not overflow any more.
+ let variant_index = variants_start
+ .checked_add(variant_index_relative)
+ .expect("overflow computing absolute variant idx");
+ let variants_len = op
+ .layout
+ .ty
+ .ty_adt_def()
+ .expect("tagged layout for non adt")
+ .variants()
+ .len();
+ assert!(usize::try_from(variant_index).unwrap() < variants_len);
+ VariantIdx::from_u32(variant_index)
+ } else {
+ untagged_variant
+ }
+ }
+ };
+ // Compute the size of the scalar we need to return.
+ // No need to cast, because the variant index directly serves as discriminant and is
+ // encoded in the tag.
+ (Scalar::from_uint(variant.as_u32(), discr_layout.size), variant)
+ }
+ })
+ }
+}
diff --git a/compiler/rustc_const_eval/src/interpret/eval_context.rs b/compiler/rustc_const_eval/src/interpret/eval_context.rs
index d13fed7a9..3db102e48 100644
--- a/compiler/rustc_const_eval/src/interpret/eval_context.rs
+++ b/compiler/rustc_const_eval/src/interpret/eval_context.rs
@@ -489,7 +489,9 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
/// Call this on things you got out of the MIR (so it is as generic as the current
/// stack frame), to bring it into the proper environment for this interpreter.
- pub(super) fn subst_from_current_frame_and_normalize_erasing_regions<T: TypeFoldable<'tcx>>(
+ pub(super) fn subst_from_current_frame_and_normalize_erasing_regions<
+ T: TypeFoldable<TyCtxt<'tcx>>,
+ >(
&self,
value: T,
) -> Result<T, InterpError<'tcx>> {
@@ -498,7 +500,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
/// Call this on things you got out of the MIR (so it is as generic as the provided
/// stack frame), to bring it into the proper environment for this interpreter.
- pub(super) fn subst_from_frame_and_normalize_erasing_regions<T: TypeFoldable<'tcx>>(
+ pub(super) fn subst_from_frame_and_normalize_erasing_regions<T: TypeFoldable<TyCtxt<'tcx>>>(
&self,
frame: &Frame<'mir, 'tcx, M::Provenance, M::FrameExtra>,
value: T,
@@ -632,14 +634,14 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
}
Ok(Some((size, align)))
}
- ty::Dynamic(..) => {
+ ty::Dynamic(_, _, ty::Dyn) => {
let vtable = metadata.unwrap_meta().to_pointer(self)?;
// Read size and align from vtable (already checks size).
Ok(Some(self.get_vtable_size_and_align(vtable)?))
}
ty::Slice(_) | ty::Str => {
- let len = metadata.unwrap_meta().to_machine_usize(self)?;
+ let len = metadata.unwrap_meta().to_target_usize(self)?;
let elem = layout.field(self, 0);
// Make sure the slice is not too big.
diff --git a/compiler/rustc_const_eval/src/interpret/intern.rs b/compiler/rustc_const_eval/src/interpret/intern.rs
index 54528b1db..b220d21f6 100644
--- a/compiler/rustc_const_eval/src/interpret/intern.rs
+++ b/compiler/rustc_const_eval/src/interpret/intern.rs
@@ -30,15 +30,15 @@ use super::{
use crate::const_eval;
pub trait CompileTimeMachine<'mir, 'tcx, T> = Machine<
- 'mir,
- 'tcx,
- MemoryKind = T,
- Provenance = AllocId,
- ExtraFnVal = !,
- FrameExtra = (),
- AllocExtra = (),
- MemoryMap = FxIndexMap<AllocId, (MemoryKind<T>, Allocation)>,
->;
+ 'mir,
+ 'tcx,
+ MemoryKind = T,
+ Provenance = AllocId,
+ ExtraFnVal = !,
+ FrameExtra = (),
+ AllocExtra = (),
+ MemoryMap = FxIndexMap<AllocId, (MemoryKind<T>, Allocation)>,
+ >;
struct InternVisitor<'rt, 'mir, 'tcx, M: CompileTimeMachine<'mir, 'tcx, const_eval::MemoryKind>> {
/// The ectx from which we intern.
@@ -135,7 +135,7 @@ fn intern_shallow<'rt, 'mir, 'tcx, M: CompileTimeMachine<'mir, 'tcx, const_eval:
};
// link the alloc id to the actual allocation
leftover_allocations.extend(alloc.provenance().ptrs().iter().map(|&(_, alloc_id)| alloc_id));
- let alloc = tcx.intern_const_alloc(alloc);
+ let alloc = tcx.mk_const_alloc(alloc);
tcx.set_alloc_id_memory(alloc_id, alloc);
None
}
@@ -242,7 +242,7 @@ impl<'rt, 'mir, 'tcx: 'mir, M: CompileTimeMachine<'mir, 'tcx, const_eval::Memory
let mplace = self.ecx.ref_to_mplace(&value)?;
assert_eq!(mplace.layout.ty, referenced_ty);
// Handle trait object vtables.
- if let ty::Dynamic(..) =
+ if let ty::Dynamic(_, _, ty::Dyn) =
tcx.struct_tail_erasing_lifetimes(referenced_ty, self.ecx.param_env).kind()
{
let ptr = mplace.meta.unwrap_meta().to_pointer(&tcx)?;
@@ -437,7 +437,7 @@ pub fn intern_const_alloc_recursive<
alloc.mutability = Mutability::Not;
}
}
- let alloc = tcx.intern_const_alloc(alloc);
+ let alloc = tcx.mk_const_alloc(alloc);
tcx.set_alloc_id_memory(alloc_id, alloc);
for &(_, alloc_id) in alloc.inner().provenance().ptrs().iter() {
if leftover_allocations.insert(alloc_id) {
@@ -479,6 +479,6 @@ impl<'mir, 'tcx: 'mir, M: super::intern::CompileTimeMachine<'mir, 'tcx, !>>
f(self, &dest.into())?;
let mut alloc = self.memory.alloc_map.remove(&dest.ptr.provenance.unwrap()).unwrap().1;
alloc.mutability = Mutability::Not;
- Ok(self.tcx.intern_const_alloc(alloc))
+ Ok(self.tcx.mk_const_alloc(alloc))
}
}
diff --git a/compiler/rustc_const_eval/src/interpret/intrinsics.rs b/compiler/rustc_const_eval/src/interpret/intrinsics.rs
index cc7b6c91b..a29cdade0 100644
--- a/compiler/rustc_const_eval/src/interpret/intrinsics.rs
+++ b/compiler/rustc_const_eval/src/interpret/intrinsics.rs
@@ -11,7 +11,7 @@ use rustc_middle::mir::{
BinOp, NonDivergingIntrinsic,
};
use rustc_middle::ty;
-use rustc_middle::ty::layout::LayoutOf as _;
+use rustc_middle::ty::layout::{LayoutOf as _, ValidityRequirement};
use rustc_middle::ty::subst::SubstsRef;
use rustc_middle::ty::{Ty, TyCtxt};
use rustc_span::symbol::{sym, Symbol};
@@ -45,7 +45,7 @@ fn numeric_intrinsic<Prov>(name: Symbol, bits: u128, kind: Primitive) -> Scalar<
pub(crate) fn alloc_type_name<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> ConstAllocation<'tcx> {
let path = crate::util::type_name(tcx, ty);
let alloc = Allocation::from_bytes_byte_aligned_immutable(path.into_bytes());
- tcx.intern_const_alloc(alloc)
+ tcx.mk_const_alloc(alloc)
}
/// The logic for all nullary intrinsics is implemented here. These intrinsics don't get evaluated
@@ -71,7 +71,7 @@ pub(crate) fn eval_nullary_intrinsic<'tcx>(
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)))?;
- ConstValue::from_machine_usize(layout.align.pref.bytes(), &tcx)
+ ConstValue::from_target_usize(layout.align.pref.bytes(), &tcx)
}
sym::type_id => {
ensure_monomorphic_enough(tcx, tp_ty)?;
@@ -79,7 +79,7 @@ pub(crate) fn eval_nullary_intrinsic<'tcx>(
}
sym::variant_count => match tp_ty.kind() {
// Correctly handles non-monomorphic calls, so there is no need for ensure_monomorphic_enough.
- ty::Adt(adt, _) => ConstValue::from_machine_usize(adt.variants().len() as u64, &tcx),
+ ty::Adt(adt, _) => ConstValue::from_target_usize(adt.variants().len() as u64, &tcx),
ty::Alias(..) | ty::Param(_) | ty::Placeholder(_) | ty::Infer(_) => {
throw_inval!(TooGeneric)
}
@@ -101,9 +101,10 @@ pub(crate) fn eval_nullary_intrinsic<'tcx>(
| ty::Closure(_, _)
| ty::Generator(_, _, _)
| ty::GeneratorWitness(_)
+ | ty::GeneratorWitnessMIR(_, _)
| ty::Never
| ty::Tuple(_)
- | ty::Error(_) => ConstValue::from_machine_usize(0u64, &tcx),
+ | ty::Error(_) => ConstValue::from_target_usize(0u64, &tcx),
},
other => bug!("`{}` is not a zero arg intrinsic", other),
})
@@ -155,7 +156,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
_ => bug!(),
};
- self.write_scalar(Scalar::from_machine_usize(result, self), dest)?;
+ self.write_scalar(Scalar::from_target_usize(result, self), dest)?;
}
sym::pref_align_of
@@ -209,19 +210,6 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
let out_val = numeric_intrinsic(intrinsic_name, bits, kind);
self.write_scalar(out_val, dest)?;
}
- sym::add_with_overflow | sym::sub_with_overflow | sym::mul_with_overflow => {
- let lhs = self.read_immediate(&args[0])?;
- let rhs = self.read_immediate(&args[1])?;
- let bin_op = match intrinsic_name {
- sym::add_with_overflow => BinOp::Add,
- sym::sub_with_overflow => BinOp::Sub,
- sym::mul_with_overflow => BinOp::Mul,
- _ => bug!(),
- };
- self.binop_with_overflow(
- bin_op, /*force_overflow_checks*/ true, &lhs, &rhs, dest,
- )?;
- }
sym::saturating_add | sym::saturating_sub => {
let l = self.read_immediate(&args[0])?;
let r = self.read_immediate(&args[1])?;
@@ -301,7 +289,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
}
sym::offset => {
let ptr = self.read_pointer(&args[0])?;
- let offset_count = self.read_machine_isize(&args[1])?;
+ let offset_count = self.read_target_isize(&args[1])?;
let pointee_ty = substs.type_at(0);
let offset_ptr = self.ptr_offset_inbounds(ptr, pointee_ty, offset_count)?;
@@ -309,7 +297,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
}
sym::arith_offset => {
let ptr = self.read_pointer(&args[0])?;
- let offset_count = self.read_machine_isize(&args[1])?;
+ let offset_count = self.read_target_isize(&args[1])?;
let pointee_ty = substs.type_at(0);
let pointee_size = i64::try_from(self.layout_of(pointee_ty)?.size.bytes()).unwrap();
@@ -375,7 +363,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
// The signed form of the intrinsic allows this. If we interpret the
// difference as isize, we'll get the proper signed difference. If that
// seems *positive*, they were more than isize::MAX apart.
- let dist = val.to_machine_isize(self)?;
+ let dist = val.to_target_isize(self)?;
if dist >= 0 {
throw_ub_format!(
"`{}` called when first pointer is too far before second",
@@ -385,7 +373,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
dist
} else {
// b >= a
- let dist = val.to_machine_isize(self)?;
+ let dist = val.to_target_isize(self)?;
// If converting to isize produced a *negative* result, we had an overflow
// because they were more than isize::MAX apart.
if dist < 0 {
@@ -410,10 +398,10 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
// Perform division by size to compute return value.
let ret_layout = if intrinsic_name == sym::ptr_offset_from_unsigned {
- assert!(0 <= dist && dist <= self.machine_isize_max());
+ assert!(0 <= dist && dist <= self.target_isize_max());
usize_layout
} else {
- assert!(self.machine_isize_min() <= dist && dist <= self.machine_isize_max());
+ assert!(self.target_isize_min() <= dist && dist <= self.target_isize_max());
isize_layout
};
let pointee_layout = self.layout_of(substs.type_at(0))?;
@@ -430,48 +418,36 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
| sym::assert_zero_valid
| sym::assert_mem_uninitialized_valid => {
let ty = instance.substs.type_at(0);
- let layout = self.layout_of(ty)?;
-
- // For *all* intrinsics we first check `is_uninhabited` to give a more specific
- // error message.
- if layout.abi.is_uninhabited() {
- // The run-time intrinsic panics just to get a good backtrace; here we abort
- // since there is no problem showing a backtrace even for aborts.
- M::abort(
- self,
- format!(
+ let requirement = ValidityRequirement::from_intrinsic(intrinsic_name).unwrap();
+
+ let should_panic = !self
+ .tcx
+ .check_validity_requirement((requirement, self.param_env.and(ty)))
+ .map_err(|_| err_inval!(TooGeneric))?;
+
+ if should_panic {
+ let layout = self.layout_of(ty)?;
+
+ let msg = match requirement {
+ // For *all* intrinsics we first check `is_uninhabited` to give a more specific
+ // error message.
+ _ if layout.abi.is_uninhabited() => format!(
"aborted execution: attempted to instantiate uninhabited type `{}`",
ty
),
- )?;
- }
-
- if intrinsic_name == sym::assert_zero_valid {
- let should_panic = !self.tcx.permits_zero_init(layout);
-
- if should_panic {
- M::abort(
- self,
- format!(
- "aborted execution: attempted to zero-initialize type `{}`, which is invalid",
- ty
- ),
- )?;
- }
- }
+ ValidityRequirement::Inhabited => bug!("handled earlier"),
+ ValidityRequirement::Zero => format!(
+ "aborted execution: attempted to zero-initialize type `{}`, which is invalid",
+ ty
+ ),
+ ValidityRequirement::UninitMitigated0x01Fill => format!(
+ "aborted execution: attempted to leave type `{}` uninitialized, which is invalid",
+ ty
+ ),
+ ValidityRequirement::Uninit => bug!("assert_uninit_valid doesn't exist"),
+ };
- if intrinsic_name == sym::assert_mem_uninitialized_valid {
- let should_panic = !self.tcx.permits_uninit_init(layout);
-
- if should_panic {
- M::abort(
- self,
- format!(
- "aborted execution: attempted to leave type `{}` uninitialized, which is invalid",
- ty
- ),
- )?;
- }
+ M::abort(self, msg)?;
}
}
sym::simd_insert => {
@@ -482,7 +458,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
assert_eq!(input_len, dest_len, "Return vector length must match input length");
assert!(
index < dest_len,
- "Index `{}` must be in bounds of vector with length {}`",
+ "Index `{}` must be in bounds of vector with length {}",
index,
dest_len
);
@@ -502,7 +478,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
let (input, input_len) = self.operand_to_simd(&args[0])?;
assert!(
index < input_len,
- "index `{}` must be in bounds of vector with length `{}`",
+ "index `{}` must be in bounds of vector with length {}",
index,
input_len
);
@@ -524,12 +500,12 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
sym::vtable_size => {
let ptr = self.read_pointer(&args[0])?;
let (size, _align) = self.get_vtable_size_and_align(ptr)?;
- self.write_scalar(Scalar::from_machine_usize(size.bytes(), self), dest)?;
+ self.write_scalar(Scalar::from_target_usize(size.bytes(), self), dest)?;
}
sym::vtable_align => {
let ptr = self.read_pointer(&args[0])?;
let (_size, align) = self.get_vtable_size_and_align(ptr)?;
- self.write_scalar(Scalar::from_machine_usize(align.bytes(), self), dest)?;
+ self.write_scalar(Scalar::from_target_usize(align.bytes(), self), dest)?;
}
_ => return Ok(false),
@@ -668,10 +644,10 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
count: &OpTy<'tcx, <M as Machine<'mir, 'tcx>>::Provenance>,
nonoverlapping: bool,
) -> InterpResult<'tcx> {
- let count = self.read_machine_usize(&count)?;
+ let count = self.read_target_usize(&count)?;
let layout = self.layout_of(src.layout.ty.builtin_deref(true).unwrap().ty)?;
let (size, align) = (layout.size, layout.align.abi);
- // `checked_mul` enforces a too small bound (the correct one would probably be machine_isize_max),
+ // `checked_mul` enforces a too small bound (the correct one would probably be target_isize_max),
// but no actual allocation can be big enough for the difference to be noticeable.
let size = size.checked_mul(count, self).ok_or_else(|| {
err_ub_format!(
@@ -696,9 +672,9 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
let dst = self.read_pointer(&dst)?;
let byte = self.read_scalar(&byte)?.to_u8()?;
- let count = self.read_machine_usize(&count)?;
+ let count = self.read_target_usize(&count)?;
- // `checked_mul` enforces a too small bound (the correct one would probably be machine_isize_max),
+ // `checked_mul` enforces a too small bound (the correct one would probably be target_isize_max),
// but no actual allocation can be big enough for the difference to be noticeable.
let len = layout
.size
diff --git a/compiler/rustc_const_eval/src/interpret/intrinsics/caller_location.rs b/compiler/rustc_const_eval/src/interpret/intrinsics/caller_location.rs
index 77c7b4bac..cf52299b7 100644
--- a/compiler/rustc_const_eval/src/interpret/intrinsics/caller_location.rs
+++ b/compiler/rustc_const_eval/src/interpret/intrinsics/caller_location.rs
@@ -78,13 +78,16 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
col: u32,
) -> MPlaceTy<'tcx, M::Provenance> {
let loc_details = &self.tcx.sess.opts.unstable_opts.location_detail;
+ // This can fail if rustc runs out of memory right here. Trying to emit an error would be
+ // pointless, since that would require allocating more memory than these short strings.
let file = if loc_details.file {
self.allocate_str(filename.as_str(), MemoryKind::CallerLocation, Mutability::Not)
+ .unwrap()
} else {
// FIXME: This creates a new allocation each time. It might be preferable to
// perform this allocation only once, and re-use the `MPlaceTy`.
// See https://github.com/rust-lang/rust/pull/89920#discussion_r730012398
- self.allocate_str("<redacted>", MemoryKind::CallerLocation, Mutability::Not)
+ self.allocate_str("<redacted>", MemoryKind::CallerLocation, Mutability::Not).unwrap()
};
let line = if loc_details.line { Scalar::from_u32(line) } else { Scalar::from_u32(0) };
let col = if loc_details.column { Scalar::from_u32(col) } else { Scalar::from_u32(0) };
@@ -92,11 +95,9 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
// Allocate memory for `CallerLocation` struct.
let loc_ty = self
.tcx
- .bound_type_of(self.tcx.require_lang_item(LangItem::PanicLocation, None))
- .subst(*self.tcx, self.tcx.mk_substs([self.tcx.lifetimes.re_erased.into()].iter()));
+ .type_of(self.tcx.require_lang_item(LangItem::PanicLocation, None))
+ .subst(*self.tcx, self.tcx.mk_substs(&[self.tcx.lifetimes.re_erased.into()]));
let loc_layout = self.layout_of(loc_ty).unwrap();
- // This can fail if rustc runs out of memory right here. Trying to emit an error would be
- // pointless, since that would require allocating more memory than a Location.
let location = self.allocate(loc_layout, MemoryKind::CallerLocation).unwrap();
// Initialize fields.
diff --git a/compiler/rustc_const_eval/src/interpret/machine.rs b/compiler/rustc_const_eval/src/interpret/machine.rs
index 248953de8..92fa59aec 100644
--- a/compiler/rustc_const_eval/src/interpret/machine.rs
+++ b/compiler/rustc_const_eval/src/interpret/machine.rs
@@ -16,8 +16,8 @@ use rustc_target::spec::abi::Abi as CallAbi;
use crate::const_eval::CheckAlignment;
use super::{
- AllocId, AllocRange, Allocation, ConstAllocation, Frame, ImmTy, InterpCx, InterpResult,
- MemoryKind, OpTy, Operand, PlaceTy, Pointer, Provenance, Scalar, StackPopUnwind,
+ AllocBytes, AllocId, AllocRange, Allocation, ConstAllocation, Frame, ImmTy, InterpCx,
+ InterpResult, MemoryKind, OpTy, Operand, PlaceTy, Pointer, Provenance, Scalar, StackPopUnwind,
};
/// Data returned by Machine::stack_pop,
@@ -105,10 +105,16 @@ pub trait Machine<'mir, 'tcx>: Sized {
/// Extra data stored in every allocation.
type AllocExtra: Debug + Clone + 'static;
+ /// Type for the bytes of the allocation.
+ type Bytes: AllocBytes + 'static;
+
/// Memory's allocation map
type MemoryMap: AllocMap<
AllocId,
- (MemoryKind<Self::MemoryKind>, Allocation<Self::Provenance, Self::AllocExtra>),
+ (
+ MemoryKind<Self::MemoryKind>,
+ Allocation<Self::Provenance, Self::AllocExtra, Self::Bytes>,
+ ),
> + Default
+ Clone;
@@ -147,8 +153,9 @@ pub trait Machine<'mir, 'tcx>: Sized {
true
}
- /// Whether CheckedBinOp MIR statements should actually check for overflow.
- fn checked_binop_checks_overflow(_ecx: &InterpCx<'mir, 'tcx, Self>) -> bool;
+ /// Whether Assert(OverflowNeg) and Assert(Overflow) MIR terminators should actually
+ /// check for overflow.
+ fn ignore_checkable_overflow_assertions(_ecx: &InterpCx<'mir, 'tcx, Self>) -> bool;
/// Entry point for obtaining the MIR of anything that should get evaluated.
/// So not just functions and shims, but also const/static initializers, anonymous
@@ -244,12 +251,18 @@ pub trait Machine<'mir, 'tcx>: Sized {
}
/// Called before a basic block terminator is executed.
- /// You can use this to detect endlessly running programs.
#[inline]
fn before_terminator(_ecx: &mut InterpCx<'mir, 'tcx, Self>) -> InterpResult<'tcx> {
Ok(())
}
+ /// Called when the interpreter encounters a `StatementKind::ConstEvalCounter` instruction.
+ /// You can use this to detect long or endlessly running programs.
+ #[inline]
+ fn increment_const_eval_counter(_ecx: &mut InterpCx<'mir, 'tcx, Self>) -> InterpResult<'tcx> {
+ Ok(())
+ }
+
/// Called before a global allocation is accessed.
/// `def_id` is `Some` if this is the "lazy" allocation of a static.
#[inline]
@@ -285,7 +298,7 @@ pub trait Machine<'mir, 'tcx>: Sized {
fn adjust_alloc_base_pointer(
ecx: &InterpCx<'mir, 'tcx, Self>,
ptr: Pointer,
- ) -> Pointer<Self::Provenance>;
+ ) -> InterpResult<'tcx, Pointer<Self::Provenance>>;
/// "Int-to-pointer cast"
fn ptr_from_addr_cast(
@@ -331,7 +344,7 @@ pub trait Machine<'mir, 'tcx>: Sized {
id: AllocId,
alloc: Cow<'b, Allocation>,
kind: Option<MemoryKind<Self::MemoryKind>>,
- ) -> InterpResult<'tcx, Cow<'b, Allocation<Self::Provenance, Self::AllocExtra>>>;
+ ) -> InterpResult<'tcx, Cow<'b, Allocation<Self::Provenance, Self::AllocExtra, Self::Bytes>>>;
fn eval_inline_asm(
_ecx: &mut InterpCx<'mir, 'tcx, Self>,
@@ -452,6 +465,7 @@ pub macro compile_time_machine(<$mir: lifetime, $tcx: lifetime>) {
type AllocExtra = ();
type FrameExtra = ();
+ type Bytes = Box<[u8]>;
#[inline(always)]
fn use_addr_for_alignment_check(_ecx: &InterpCx<$mir, $tcx, Self>) -> bool {
@@ -460,8 +474,8 @@ pub macro compile_time_machine(<$mir: lifetime, $tcx: lifetime>) {
}
#[inline(always)]
- fn checked_binop_checks_overflow(_ecx: &InterpCx<$mir, $tcx, Self>) -> bool {
- true
+ fn ignore_checkable_overflow_assertions(_ecx: &InterpCx<$mir, $tcx, Self>) -> bool {
+ false
}
#[inline(always)]
@@ -499,8 +513,8 @@ pub macro compile_time_machine(<$mir: lifetime, $tcx: lifetime>) {
fn adjust_alloc_base_pointer(
_ecx: &InterpCx<$mir, $tcx, Self>,
ptr: Pointer<AllocId>,
- ) -> Pointer<AllocId> {
- ptr
+ ) -> InterpResult<$tcx, Pointer<AllocId>> {
+ Ok(ptr)
}
#[inline(always)]
@@ -511,7 +525,7 @@ pub macro compile_time_machine(<$mir: lifetime, $tcx: lifetime>) {
// Allow these casts, but make the pointer not dereferenceable.
// (I.e., they behave like transmutation.)
// This is correct because no pointers can ever be exposed in compile-time evaluation.
- Ok(Pointer::from_addr(addr))
+ Ok(Pointer::from_addr_invalid(addr))
}
#[inline(always)]
diff --git a/compiler/rustc_const_eval/src/interpret/memory.rs b/compiler/rustc_const_eval/src/interpret/memory.rs
index 291bfb2b5..a3764a7d1 100644
--- a/compiler/rustc_const_eval/src/interpret/memory.rs
+++ b/compiler/rustc_const_eval/src/interpret/memory.rs
@@ -21,8 +21,9 @@ use rustc_target::abi::{Align, HasDataLayout, Size};
use crate::const_eval::CheckAlignment;
use super::{
- alloc_range, AllocId, AllocMap, AllocRange, Allocation, CheckInAllocMsg, GlobalAlloc, InterpCx,
- InterpResult, Machine, MayLeak, Pointer, PointerArithmetic, Provenance, Scalar,
+ alloc_range, AllocBytes, AllocId, AllocMap, AllocRange, Allocation, CheckInAllocMsg,
+ GlobalAlloc, InterpCx, InterpResult, Machine, MayLeak, Pointer, PointerArithmetic, Provenance,
+ Scalar,
};
#[derive(Debug, PartialEq, Copy, Clone)]
@@ -114,16 +115,16 @@ pub struct Memory<'mir, 'tcx, M: Machine<'mir, 'tcx>> {
/// A reference to some allocation that was already bounds-checked for the given region
/// and had the on-access machine hooks run.
#[derive(Copy, Clone)]
-pub struct AllocRef<'a, 'tcx, Prov: Provenance, Extra> {
- alloc: &'a Allocation<Prov, Extra>,
+pub struct AllocRef<'a, 'tcx, Prov: Provenance, Extra, Bytes: AllocBytes = Box<[u8]>> {
+ alloc: &'a Allocation<Prov, Extra, Bytes>,
range: AllocRange,
tcx: TyCtxt<'tcx>,
alloc_id: AllocId,
}
/// A reference to some allocation that was already bounds-checked for the given region
/// and had the on-access machine hooks run.
-pub struct AllocRefMut<'a, 'tcx, Prov: Provenance, Extra> {
- alloc: &'a mut Allocation<Prov, Extra>,
+pub struct AllocRefMut<'a, 'tcx, Prov: Provenance, Extra, Bytes: AllocBytes = Box<[u8]>> {
+ alloc: &'a mut Allocation<Prov, Extra, Bytes>,
range: AllocRange,
tcx: TyCtxt<'tcx>,
alloc_id: AllocId,
@@ -171,7 +172,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
_ => {}
}
// And we need to get the provenance.
- Ok(M::adjust_alloc_base_pointer(self, ptr))
+ M::adjust_alloc_base_pointer(self, ptr)
}
pub fn create_fn_alloc_ptr(
@@ -200,8 +201,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
kind: MemoryKind<M::MemoryKind>,
) -> InterpResult<'tcx, Pointer<M::Provenance>> {
let alloc = Allocation::uninit(size, align, M::PANIC_ON_ALLOC_FAIL)?;
- // We can `unwrap` since `alloc` contains no pointers.
- Ok(self.allocate_raw_ptr(alloc, kind).unwrap())
+ self.allocate_raw_ptr(alloc, kind)
}
pub fn allocate_bytes_ptr(
@@ -210,10 +210,9 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
align: Align,
kind: MemoryKind<M::MemoryKind>,
mutability: Mutability,
- ) -> Pointer<M::Provenance> {
+ ) -> InterpResult<'tcx, Pointer<M::Provenance>> {
let alloc = Allocation::from_bytes(bytes, align, mutability);
- // We can `unwrap` since `alloc` contains no pointers.
- self.allocate_raw_ptr(alloc, kind).unwrap()
+ self.allocate_raw_ptr(alloc, kind)
}
/// This can fail only of `alloc` contains provenance.
@@ -230,7 +229,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
);
let alloc = M::adjust_allocation(self, id, Cow::Owned(alloc), Some(kind))?;
self.memory.alloc_map.insert(id, (kind, alloc.into_owned()));
- Ok(M::adjust_alloc_base_pointer(self, Pointer::from(id)))
+ M::adjust_alloc_base_pointer(self, Pointer::from(id))
}
pub fn reallocate_ptr(
@@ -304,7 +303,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
.into());
};
- if alloc.mutability == Mutability::Not {
+ if alloc.mutability.is_not() {
throw_ub_format!("deallocating immutable allocation {alloc_id:?}");
}
if alloc_kind != kind {
@@ -427,7 +426,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
throw_ub!(PointerOutOfBounds {
alloc_id,
alloc_size,
- ptr_offset: self.machine_usize_to_isize(offset.bytes()),
+ ptr_offset: self.target_usize_to_isize(offset.bytes()),
ptr_size: size,
msg,
})
@@ -485,7 +484,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
&self,
id: AllocId,
is_write: bool,
- ) -> InterpResult<'tcx, Cow<'tcx, Allocation<M::Provenance, M::AllocExtra>>> {
+ ) -> InterpResult<'tcx, Cow<'tcx, Allocation<M::Provenance, M::AllocExtra, M::Bytes>>> {
let (alloc, def_id) = match self.tcx.try_get_global_alloc(id) {
Some(GlobalAlloc::Memory(mem)) => {
// Memory of a constant or promoted or anonymous memory referenced by a static.
@@ -528,6 +527,17 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
)
}
+ /// Get the base address for the bytes in an `Allocation` specified by the
+ /// `AllocID` passed in; error if no such allocation exists.
+ ///
+ /// It is up to the caller to take sufficient care when using this address:
+ /// there could be provenance or uninit memory in there, and other memory
+ /// accesses could invalidate the exposed pointer.
+ pub fn alloc_base_addr(&self, id: AllocId) -> InterpResult<'tcx, *const u8> {
+ let alloc = self.get_alloc_raw(id)?;
+ Ok(alloc.base_addr())
+ }
+
/// Gives raw access to the `Allocation`, without bounds or alignment checks.
/// The caller is responsible for calling the access hooks!
///
@@ -535,7 +545,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
fn get_alloc_raw(
&self,
id: AllocId,
- ) -> InterpResult<'tcx, &Allocation<M::Provenance, M::AllocExtra>> {
+ ) -> InterpResult<'tcx, &Allocation<M::Provenance, M::AllocExtra, M::Bytes>> {
// The error type of the inner closure here is somewhat funny. We have two
// ways of "erroring": An actual error, or because we got a reference from
// `get_global_alloc` that we can actually use directly without inserting anything anywhere.
@@ -571,7 +581,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
ptr: Pointer<Option<M::Provenance>>,
size: Size,
align: Align,
- ) -> InterpResult<'tcx, Option<AllocRef<'a, 'tcx, M::Provenance, M::AllocExtra>>> {
+ ) -> InterpResult<'tcx, Option<AllocRef<'a, 'tcx, M::Provenance, M::AllocExtra, M::Bytes>>>
+ {
let ptr_and_alloc = self.check_and_deref_ptr(
ptr,
size,
@@ -614,7 +625,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
fn get_alloc_raw_mut(
&mut self,
id: AllocId,
- ) -> InterpResult<'tcx, (&mut Allocation<M::Provenance, M::AllocExtra>, &mut M)> {
+ ) -> InterpResult<'tcx, (&mut Allocation<M::Provenance, M::AllocExtra, M::Bytes>, &mut M)> {
// We have "NLL problem case #3" here, which cannot be worked around without loss of
// efficiency even for the common case where the key is in the map.
// <https://rust-lang.github.io/rfcs/2094-nll.html#problem-case-3-conditional-control-flow-across-functions>
@@ -631,7 +642,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
}
let (_kind, alloc) = self.memory.alloc_map.get_mut(id).unwrap();
- if alloc.mutability == Mutability::Not {
+ if alloc.mutability.is_not() {
throw_ub!(WriteToReadOnly(id))
}
Ok((alloc, &mut self.machine))
@@ -643,7 +654,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
ptr: Pointer<Option<M::Provenance>>,
size: Size,
align: Align,
- ) -> InterpResult<'tcx, Option<AllocRefMut<'a, 'tcx, M::Provenance, M::AllocExtra>>> {
+ ) -> InterpResult<'tcx, Option<AllocRefMut<'a, 'tcx, M::Provenance, M::AllocExtra, M::Bytes>>>
+ {
let parts = self.get_ptr_access(ptr, size, align)?;
if let Some((alloc_id, offset, prov)) = parts {
let tcx = *self.tcx;
@@ -692,7 +704,11 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
assert!(self.tcx.is_static(def_id));
assert!(!self.tcx.is_thread_local_static(def_id));
// Use size and align of the type.
- let ty = self.tcx.type_of(def_id);
+ let ty = self
+ .tcx
+ .type_of(def_id)
+ .no_bound_vars()
+ .expect("statics should not have generic parameters");
let layout = self.tcx.layout_of(ParamEnv::empty().and(ty)).unwrap();
assert!(layout.is_sized());
(layout.size, layout.align.abi, AllocKind::LiveData)
@@ -838,11 +854,11 @@ pub struct DumpAllocs<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> {
impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> std::fmt::Debug for DumpAllocs<'a, 'mir, 'tcx, M> {
fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
// Cannot be a closure because it is generic in `Prov`, `Extra`.
- fn write_allocation_track_relocs<'tcx, Prov: Provenance, Extra>(
+ fn write_allocation_track_relocs<'tcx, Prov: Provenance, Extra, Bytes: AllocBytes>(
fmt: &mut std::fmt::Formatter<'_>,
tcx: TyCtxt<'tcx>,
allocs_to_print: &mut VecDeque<AllocId>,
- alloc: &Allocation<Prov, Extra>,
+ alloc: &Allocation<Prov, Extra, Bytes>,
) -> std::fmt::Result {
for alloc_id in alloc.provenance().provenances().filter_map(|prov| prov.get_alloc_id())
{
@@ -910,7 +926,9 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> std::fmt::Debug for DumpAllocs<'a,
}
/// Reading and writing.
-impl<'tcx, 'a, Prov: Provenance, Extra> AllocRefMut<'a, 'tcx, Prov, Extra> {
+impl<'tcx, 'a, Prov: Provenance, Extra, Bytes: AllocBytes>
+ AllocRefMut<'a, 'tcx, Prov, Extra, Bytes>
+{
/// `range` is relative to this allocation reference, not the base of the allocation.
pub fn write_scalar(&mut self, range: AllocRange, val: Scalar<Prov>) -> InterpResult<'tcx> {
let range = self.range.subrange(range);
@@ -935,7 +953,7 @@ impl<'tcx, 'a, Prov: Provenance, Extra> AllocRefMut<'a, 'tcx, Prov, Extra> {
}
}
-impl<'tcx, 'a, Prov: Provenance, Extra> AllocRef<'a, 'tcx, Prov, Extra> {
+impl<'tcx, 'a, Prov: Provenance, Extra, Bytes: AllocBytes> AllocRef<'a, 'tcx, Prov, Extra, Bytes> {
/// `range` is relative to this allocation reference, not the base of the allocation.
pub fn read_scalar(
&self,
diff --git a/compiler/rustc_const_eval/src/interpret/mod.rs b/compiler/rustc_const_eval/src/interpret/mod.rs
index 2e356f67b..86de4e4e3 100644
--- a/compiler/rustc_const_eval/src/interpret/mod.rs
+++ b/compiler/rustc_const_eval/src/interpret/mod.rs
@@ -1,6 +1,7 @@
//! An interpreter for MIR used in CTFE and by miri
mod cast;
+mod discriminant;
mod eval_context;
mod intern;
mod intrinsics;
diff --git a/compiler/rustc_const_eval/src/interpret/operand.rs b/compiler/rustc_const_eval/src/interpret/operand.rs
index befc0928f..5310ef0bb 100644
--- a/compiler/rustc_const_eval/src/interpret/operand.rs
+++ b/compiler/rustc_const_eval/src/interpret/operand.rs
@@ -4,13 +4,12 @@
use either::{Either, Left, Right};
use rustc_hir::def::Namespace;
-use rustc_middle::ty::layout::{LayoutOf, PrimitiveExt, TyAndLayout};
+use rustc_middle::ty::layout::{LayoutOf, TyAndLayout};
use rustc_middle::ty::print::{FmtPrinter, PrettyPrinter};
use rustc_middle::ty::{ConstInt, Ty, ValTree};
use rustc_middle::{mir, ty};
use rustc_span::Span;
-use rustc_target::abi::{self, Abi, Align, HasDataLayout, Size, TagEncoding};
-use rustc_target::abi::{VariantIdx, Variants};
+use rustc_target::abi::{self, Abi, Align, HasDataLayout, Size};
use super::{
alloc_range, from_known_layout, mir_assign_valid_types, AllocId, ConstValue, Frame, GlobalId,
@@ -53,7 +52,7 @@ impl<Prov: Provenance> Immediate<Prov> {
}
pub fn new_slice(val: Scalar<Prov>, len: u64, cx: &impl HasDataLayout) -> Self {
- Immediate::ScalarPair(val, Scalar::from_machine_usize(len, cx))
+ Immediate::ScalarPair(val, Scalar::from_target_usize(len, cx))
}
pub fn new_dyn_trait(
@@ -256,7 +255,22 @@ impl<'tcx, Prov: Provenance> OpTy<'tcx, Prov> {
}
}
- pub fn offset_with_meta(
+ /// Replace the layout of this operand. There's basically no sanity check that this makes sense,
+ /// you better know what you are doing! If this is an immediate, applying the wrong layout can
+ /// not just lead to invalid data, it can actually *shift the data around* since the offsets of
+ /// a ScalarPair are entirely determined by the layout, not the data.
+ pub fn transmute(&self, layout: TyAndLayout<'tcx>) -> Self {
+ assert_eq!(
+ self.layout.size, layout.size,
+ "transmuting with a size change, that doesn't seem right"
+ );
+ OpTy { layout, ..*self }
+ }
+
+ /// Offset the operand in memory (if possible) and change its metadata.
+ ///
+ /// This can go wrong very easily if you give the wrong layout for the new place!
+ pub(super) fn offset_with_meta(
&self,
offset: Size,
meta: MemPlaceMeta<Prov>,
@@ -277,6 +291,9 @@ impl<'tcx, Prov: Provenance> OpTy<'tcx, Prov> {
}
}
+ /// Offset the operand in memory (if possible).
+ ///
+ /// This can go wrong very easily if you give the wrong layout for the new place!
pub fn offset(
&self,
offset: Size,
@@ -319,7 +336,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
assert_eq!(size, mplace.layout.size, "abi::Scalar size does not match layout size");
let scalar = alloc.read_scalar(
alloc_range(Size::ZERO, size),
- /*read_provenance*/ s.is_ptr(),
+ /*read_provenance*/ matches!(s, abi::Pointer(_)),
)?;
Some(ImmTy { imm: scalar.into(), layout: mplace.layout })
}
@@ -335,11 +352,11 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
assert!(b_offset.bytes() > 0); // in `operand_field` we use the offset to tell apart the fields
let a_val = alloc.read_scalar(
alloc_range(Size::ZERO, a_size),
- /*read_provenance*/ a.is_ptr(),
+ /*read_provenance*/ matches!(a, abi::Pointer(_)),
)?;
let b_val = alloc.read_scalar(
alloc_range(b_offset, b_size),
- /*read_provenance*/ b.is_ptr(),
+ /*read_provenance*/ matches!(b, abi::Pointer(_)),
)?;
Some(ImmTy { imm: Immediate::ScalarPair(a_val, b_val), layout: mplace.layout })
}
@@ -415,12 +432,12 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
self.read_scalar(op)?.to_pointer(self)
}
/// Read a pointer-sized unsigned integer from a place.
- pub fn read_machine_usize(&self, op: &OpTy<'tcx, M::Provenance>) -> InterpResult<'tcx, u64> {
- self.read_scalar(op)?.to_machine_usize(self)
+ pub fn read_target_usize(&self, op: &OpTy<'tcx, M::Provenance>) -> InterpResult<'tcx, u64> {
+ self.read_scalar(op)?.to_target_usize(self)
}
/// Read a pointer-sized signed integer from a place.
- pub fn read_machine_isize(&self, op: &OpTy<'tcx, M::Provenance>) -> InterpResult<'tcx, i64> {
- self.read_scalar(op)?.to_machine_isize(self)
+ pub fn read_target_isize(&self, op: &OpTy<'tcx, M::Provenance>) -> InterpResult<'tcx, i64> {
+ self.read_scalar(op)?.to_target_isize(self)
}
/// Turn the wide MPlace into a string (must already be dereferenced!)
@@ -595,14 +612,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
span: Option<Span>,
layout: Option<TyAndLayout<'tcx>>,
) -> InterpResult<'tcx, OpTy<'tcx, M::Provenance>> {
- // FIXME(const_prop): normalization needed b/c const prop lint in
- // `mir_drops_elaborated_and_const_checked`, which happens before
- // optimized MIR. Only after optimizing the MIR can we guarantee
- // that the `RevealAll` pass has happened and that the body's consts
- // are normalized, so any call to resolve before that needs to be
- // manually normalized.
- let val = self.tcx.normalize_erasing_regions(self.param_env, *val);
- match val {
+ match *val {
mir::ConstantKind::Ty(ct) => {
let ty = ct.ty();
let valtree = self.eval_ty_constant(ct, span)?;
@@ -657,154 +667,6 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
};
Ok(OpTy { op, layout, align: Some(layout.align.abi) })
}
-
- /// 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::Provenance>,
- ) -> InterpResult<'tcx, (Scalar<M::Provenance>, VariantIdx)> {
- trace!("read_discriminant_value {:#?}", op.layout);
- // Get type and layout of the discriminant.
- let discr_layout = self.layout_of(op.layout.ty.discriminant_ty(*self.tcx))?;
- trace!("discriminant type: {:?}", discr_layout.ty);
-
- // We use "discriminant" to refer to the value associated with a particular enum variant.
- // This is not to be confused with its "variant index", which is just determining its position in the
- // declared list of variants -- they can differ with explicitly assigned discriminants.
- // We use "tag" to refer to how the discriminant is encoded in memory, which can be either
- // straight-forward (`TagEncoding::Direct`) or with a niche (`TagEncoding::Niche`).
- let (tag_scalar_layout, tag_encoding, tag_field) = match op.layout.variants {
- Variants::Single { index } => {
- let discr = match op.layout.ty.discriminant_for_variant(*self.tcx, index) {
- Some(discr) => {
- // This type actually has discriminants.
- assert_eq!(discr.ty, discr_layout.ty);
- Scalar::from_uint(discr.val, discr_layout.size)
- }
- None => {
- // On a type without actual discriminants, variant is 0.
- assert_eq!(index.as_u32(), 0);
- Scalar::from_uint(index.as_u32(), discr_layout.size)
- }
- };
- return Ok((discr, index));
- }
- Variants::Multiple { tag, ref tag_encoding, tag_field, .. } => {
- (tag, tag_encoding, tag_field)
- }
- };
-
- // There are *three* layouts that come into play here:
- // - The discriminant has a type for typechecking. This is `discr_layout`, and is used for
- // the `Scalar` we return.
- // - The tag (encoded discriminant) has layout `tag_layout`. This is always an integer type,
- // and used to interpret the value we read from the tag field.
- // For the return value, a cast to `discr_layout` is performed.
- // - The field storing the tag has a layout, which is very similar to `tag_layout` but
- // may be a pointer. This is `tag_val.layout`; we just use it for sanity checks.
-
- // Get layout for tag.
- let tag_layout = self.layout_of(tag_scalar_layout.primitive().to_int_ty(*self.tcx))?;
-
- // Read tag and sanity-check `tag_layout`.
- let tag_val = self.read_immediate(&self.operand_field(op, tag_field)?)?;
- assert_eq!(tag_layout.size, tag_val.layout.size);
- assert_eq!(tag_layout.abi.is_signed(), tag_val.layout.abi.is_signed());
- trace!("tag value: {}", tag_val);
-
- // Figure out which discriminant and variant this corresponds to.
- Ok(match *tag_encoding {
- TagEncoding::Direct => {
- let scalar = tag_val.to_scalar();
- // Generate a specific error if `tag_val` is not an integer.
- // (`tag_bits` itself is only used for error messages below.)
- let tag_bits = scalar
- .try_to_int()
- .map_err(|dbg_val| err_ub!(InvalidTag(dbg_val)))?
- .assert_bits(tag_layout.size);
- // Cast bits from tag layout to discriminant layout.
- // After the checks we did above, this cannot fail, as
- // discriminants are int-like.
- let discr_val =
- self.cast_from_int_like(scalar, tag_val.layout, discr_layout.ty).unwrap();
- let discr_bits = discr_val.assert_bits(discr_layout.size);
- // Convert discriminant to variant index, and catch invalid discriminants.
- let index = match *op.layout.ty.kind() {
- ty::Adt(adt, _) => {
- adt.discriminants(*self.tcx).find(|(_, var)| var.val == discr_bits)
- }
- ty::Generator(def_id, substs, _) => {
- let substs = substs.as_generator();
- substs
- .discriminants(def_id, *self.tcx)
- .find(|(_, var)| var.val == discr_bits)
- }
- _ => span_bug!(self.cur_span(), "tagged layout for non-adt non-generator"),
- }
- .ok_or_else(|| err_ub!(InvalidTag(Scalar::from_uint(tag_bits, tag_layout.size))))?;
- // Return the cast value, and the index.
- (discr_val, index.0)
- }
- TagEncoding::Niche { untagged_variant, ref niche_variants, niche_start } => {
- let tag_val = tag_val.to_scalar();
- // Compute the variant this niche value/"tag" corresponds to. With niche layout,
- // discriminant (encoded in niche/tag) and variant index are the same.
- let variants_start = niche_variants.start().as_u32();
- let variants_end = niche_variants.end().as_u32();
- let variant = match tag_val.try_to_int() {
- Err(dbg_val) => {
- // So this is a pointer then, and casting to an int failed.
- // Can only happen during CTFE.
- // The niche must be just 0, and the ptr not null, then we know this is
- // okay. Everything else, we conservatively reject.
- let ptr_valid = niche_start == 0
- && variants_start == variants_end
- && !self.scalar_may_be_null(tag_val)?;
- if !ptr_valid {
- throw_ub!(InvalidTag(dbg_val))
- }
- untagged_variant
- }
- Ok(tag_bits) => {
- let tag_bits = tag_bits.assert_bits(tag_layout.size);
- // We need to use machine arithmetic to get the relative variant idx:
- // variant_index_relative = tag_val - niche_start_val
- let tag_val = ImmTy::from_uint(tag_bits, tag_layout);
- let niche_start_val = ImmTy::from_uint(niche_start, tag_layout);
- let variant_index_relative_val =
- self.binary_op(mir::BinOp::Sub, &tag_val, &niche_start_val)?;
- let variant_index_relative =
- variant_index_relative_val.to_scalar().assert_bits(tag_val.layout.size);
- // Check if this is in the range that indicates an actual discriminant.
- if variant_index_relative <= u128::from(variants_end - variants_start) {
- let variant_index_relative = u32::try_from(variant_index_relative)
- .expect("we checked that this fits into a u32");
- // Then computing the absolute variant idx should not overflow any more.
- let variant_index = variants_start
- .checked_add(variant_index_relative)
- .expect("overflow computing absolute variant idx");
- let variants_len = op
- .layout
- .ty
- .ty_adt_def()
- .expect("tagged layout for non adt")
- .variants()
- .len();
- assert!(usize::try_from(variant_index).unwrap() < variants_len);
- VariantIdx::from_u32(variant_index)
- } else {
- untagged_variant
- }
- }
- };
- // Compute the size of the scalar we need to return.
- // No need to cast, because the variant index directly serves as discriminant and is
- // encoded in the tag.
- (Scalar::from_uint(variant.as_u32(), discr_layout.size), variant)
- }
- })
- }
}
// Some nodes are used a lot. Make sure they don't unintentionally get bigger.
diff --git a/compiler/rustc_const_eval/src/interpret/operator.rs b/compiler/rustc_const_eval/src/interpret/operator.rs
index e8ff70e3a..4decfe863 100644
--- a/compiler/rustc_const_eval/src/interpret/operator.rs
+++ b/compiler/rustc_const_eval/src/interpret/operator.rs
@@ -10,28 +10,20 @@ use super::{ImmTy, Immediate, InterpCx, Machine, PlaceTy};
impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
/// Applies the binary operation `op` to the two operands and writes a tuple of the result
/// and a boolean signifying the potential overflow to the destination.
- ///
- /// `force_overflow_checks` indicates whether overflow checks should be done even when
- /// `tcx.sess.overflow_checks()` is `false`.
pub fn binop_with_overflow(
&mut self,
op: mir::BinOp,
- force_overflow_checks: bool,
left: &ImmTy<'tcx, M::Provenance>,
right: &ImmTy<'tcx, M::Provenance>,
dest: &PlaceTy<'tcx, M::Provenance>,
) -> InterpResult<'tcx> {
let (val, overflowed, ty) = self.overflowing_binary_op(op, &left, &right)?;
debug_assert_eq!(
- self.tcx.intern_tup(&[ty, self.tcx.types.bool]),
+ self.tcx.mk_tup(&[ty, self.tcx.types.bool]),
dest.layout.ty,
"type mismatch for result of {:?}",
op,
);
- // As per https://github.com/rust-lang/rust/pull/98738, we always return `false` in the 2nd
- // component when overflow checking is disabled.
- let overflowed =
- overflowed && (force_overflow_checks || M::checked_binop_checks_overflow(self));
// Write the result to `dest`.
if let Abi::ScalarPair(..) = dest.layout.abi {
// We can use the optimized path and avoid `place_field` (which might do
diff --git a/compiler/rustc_const_eval/src/interpret/place.rs b/compiler/rustc_const_eval/src/interpret/place.rs
index 274af61ee..3c463500a 100644
--- a/compiler/rustc_const_eval/src/interpret/place.rs
+++ b/compiler/rustc_const_eval/src/interpret/place.rs
@@ -7,8 +7,8 @@ use either::{Either, Left, Right};
use rustc_ast::Mutability;
use rustc_middle::mir;
use rustc_middle::ty;
-use rustc_middle::ty::layout::{LayoutOf, PrimitiveExt, TyAndLayout};
-use rustc_target::abi::{self, Abi, Align, HasDataLayout, Size, TagEncoding, VariantIdx};
+use rustc_middle::ty::layout::{LayoutOf, TyAndLayout};
+use rustc_target::abi::{self, Abi, Align, HasDataLayout, Size, VariantIdx};
use super::{
alloc_range, mir_assign_valid_types, AllocId, AllocRef, AllocRefMut, CheckInAllocMsg,
@@ -26,6 +26,7 @@ pub enum MemPlaceMeta<Prov: Provenance = AllocId> {
}
impl<Prov: Provenance> MemPlaceMeta<Prov> {
+ #[cfg_attr(debug_assertions, track_caller)] // only in debug builds due to perf (see #98980)
pub fn unwrap_meta(self) -> Scalar<Prov> {
match self {
Self::Meta(s) => s,
@@ -147,12 +148,16 @@ impl<Prov: Provenance> MemPlace<Prov> {
}
#[inline]
- pub fn offset_with_meta<'tcx>(
+ pub(super) fn offset_with_meta<'tcx>(
self,
offset: Size,
meta: MemPlaceMeta<Prov>,
cx: &impl HasDataLayout,
) -> InterpResult<'tcx, Self> {
+ debug_assert!(
+ !meta.has_meta() || self.meta.has_meta(),
+ "cannot use `offset_with_meta` to add metadata to a place"
+ );
Ok(MemPlace { ptr: self.ptr.offset(offset, cx)?, meta })
}
}
@@ -178,12 +183,15 @@ impl<'tcx, Prov: Provenance> MPlaceTy<'tcx, Prov> {
pub fn fake_alloc_zst(layout: TyAndLayout<'tcx>) -> Self {
assert!(layout.is_zst());
let align = layout.align.abi;
- let ptr = Pointer::from_addr(align.bytes()); // no provenance, absolute address
+ let ptr = Pointer::from_addr_invalid(align.bytes()); // no provenance, absolute address
MPlaceTy { mplace: MemPlace { ptr, meta: MemPlaceMeta::None }, layout, align }
}
+ /// Offset the place in memory and change its metadata.
+ ///
+ /// This can go wrong very easily if you give the wrong layout for the new place!
#[inline]
- pub fn offset_with_meta(
+ pub(crate) fn offset_with_meta(
&self,
offset: Size,
meta: MemPlaceMeta<Prov>,
@@ -197,6 +205,9 @@ impl<'tcx, Prov: Provenance> MPlaceTy<'tcx, Prov> {
})
}
+ /// Offset the place in memory.
+ ///
+ /// This can go wrong very easily if you give the wrong layout for the new place!
pub fn offset(
&self,
offset: Size,
@@ -229,7 +240,7 @@ impl<'tcx, Prov: Provenance> MPlaceTy<'tcx, Prov> {
if self.layout.is_unsized() {
// We need to consult `meta` metadata
match self.layout.ty.kind() {
- ty::Slice(..) | ty::Str => self.mplace.meta.unwrap_meta().to_machine_usize(cx),
+ ty::Slice(..) | ty::Str => self.mplace.meta.unwrap_meta().to_target_usize(cx),
_ => bug!("len not supported on unsized type {:?}", self.layout.ty),
}
} else {
@@ -241,14 +252,6 @@ impl<'tcx, Prov: Provenance> MPlaceTy<'tcx, Prov> {
}
}
}
-
- #[inline]
- pub(super) fn vtable(&self) -> Scalar<Prov> {
- match self.layout.ty.kind() {
- ty::Dynamic(..) => self.mplace.meta.unwrap_meta(),
- _ => bug!("vtable not supported on type {:?}", self.layout.ty),
- }
- }
}
// These are defined here because they produce a place.
@@ -266,7 +269,12 @@ impl<'tcx, Prov: Provenance> OpTy<'tcx, Prov> {
#[inline(always)]
#[cfg_attr(debug_assertions, track_caller)] // only in debug builds due to perf (see #98980)
pub fn assert_mem_place(&self) -> MPlaceTy<'tcx, Prov> {
- self.as_mplace_or_imm().left().unwrap()
+ self.as_mplace_or_imm().left().unwrap_or_else(|| {
+ bug!(
+ "OpTy of type {} was immediate when it was expected to be an MPlace",
+ self.layout.ty
+ )
+ })
}
}
@@ -283,7 +291,12 @@ impl<'tcx, Prov: Provenance> PlaceTy<'tcx, Prov> {
#[inline(always)]
#[cfg_attr(debug_assertions, track_caller)] // only in debug builds due to perf (see #98980)
pub fn assert_mem_place(&self) -> MPlaceTy<'tcx, Prov> {
- self.as_mplace_or_local().left().unwrap()
+ self.as_mplace_or_local().left().unwrap_or_else(|| {
+ bug!(
+ "PlaceTy of type {} was a local when it was expected to be an MPlace",
+ self.layout.ty
+ )
+ })
}
}
@@ -340,7 +353,8 @@ where
pub(super) fn get_place_alloc(
&self,
place: &MPlaceTy<'tcx, M::Provenance>,
- ) -> InterpResult<'tcx, Option<AllocRef<'_, 'tcx, M::Provenance, M::AllocExtra>>> {
+ ) -> InterpResult<'tcx, Option<AllocRef<'_, 'tcx, M::Provenance, M::AllocExtra, M::Bytes>>>
+ {
assert!(place.layout.is_sized());
assert!(!place.meta.has_meta());
let size = place.layout.size;
@@ -351,7 +365,8 @@ where
pub(super) fn get_place_alloc_mut(
&mut self,
place: &MPlaceTy<'tcx, M::Provenance>,
- ) -> InterpResult<'tcx, Option<AllocRefMut<'_, 'tcx, M::Provenance, M::AllocExtra>>> {
+ ) -> InterpResult<'tcx, Option<AllocRefMut<'_, 'tcx, M::Provenance, M::AllocExtra, M::Bytes>>>
+ {
assert!(place.layout.is_sized());
assert!(!place.meta.has_meta());
let size = place.layout.size;
@@ -754,9 +769,9 @@ where
str: &str,
kind: MemoryKind<M::MemoryKind>,
mutbl: Mutability,
- ) -> MPlaceTy<'tcx, M::Provenance> {
- let ptr = self.allocate_bytes_ptr(str.as_bytes(), Align::ONE, kind, mutbl);
- let meta = Scalar::from_machine_usize(u64::try_from(str.len()).unwrap(), self);
+ ) -> InterpResult<'tcx, MPlaceTy<'tcx, M::Provenance>> {
+ let ptr = self.allocate_bytes_ptr(str.as_bytes(), Align::ONE, kind, mutbl)?;
+ let meta = Scalar::from_target_usize(u64::try_from(str.len()).unwrap(), self);
let mplace = MemPlace { ptr: ptr.into(), meta: MemPlaceMeta::Meta(meta) };
let ty = self.tcx.mk_ref(
@@ -764,95 +779,35 @@ where
ty::TypeAndMut { ty: self.tcx.types.str_, mutbl },
);
let layout = self.layout_of(ty).unwrap();
- MPlaceTy { mplace, layout, align: layout.align.abi }
+ Ok(MPlaceTy { mplace, layout, align: layout.align.abi })
}
- /// Writes the discriminant of the given variant.
- #[instrument(skip(self), level = "debug")]
- pub fn write_discriminant(
+ /// Writes the aggregate to the destination.
+ #[instrument(skip(self), level = "trace")]
+ pub fn write_aggregate(
&mut self,
- variant_index: VariantIdx,
+ kind: &mir::AggregateKind<'tcx>,
+ operands: &[mir::Operand<'tcx>],
dest: &PlaceTy<'tcx, M::Provenance>,
) -> 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!(UninhabitedEnumVariantWritten)
- }
-
- match dest.layout.variants {
- abi::Variants::Single { index } => {
- assert_eq!(index, variant_index);
- }
- abi::Variants::Multiple {
- tag_encoding: TagEncoding::Direct,
- tag: tag_layout,
- tag_field,
- ..
- } => {
- // No need to validate that the discriminant here because the
- // `TyAndLayout::for_variant()` call earlier already checks the variant is valid.
-
- let discr_val =
- dest.layout.ty.discriminant_for_variant(*self.tcx, variant_index).unwrap().val;
-
- // raw discriminants for enums are isize or bigger during
- // their computation, but the in-memory tag is the smallest possible
- // representation
- let size = tag_layout.size(self);
- let tag_val = size.truncate(discr_val);
-
- let tag_dest = self.place_field(dest, tag_field)?;
- self.write_scalar(Scalar::from_uint(tag_val, size), &tag_dest)?;
- }
- abi::Variants::Multiple {
- tag_encoding:
- TagEncoding::Niche { untagged_variant, ref niche_variants, niche_start },
- tag: tag_layout,
- tag_field,
- ..
- } => {
- // No need to validate that the discriminant here because the
- // `TyAndLayout::for_variant()` call earlier already checks the variant is valid.
-
- if variant_index != untagged_variant {
- let variants_start = niche_variants.start().as_u32();
- let variant_index_relative = variant_index
- .as_u32()
- .checked_sub(variants_start)
- .expect("overflow computing relative variant idx");
- // We need to use machine arithmetic when taking into account `niche_start`:
- // tag_val = variant_index_relative + niche_start_val
- let tag_layout = self.layout_of(tag_layout.primitive().to_int_ty(*self.tcx))?;
- let niche_start_val = ImmTy::from_uint(niche_start, tag_layout);
- let variant_index_relative_val =
- ImmTy::from_uint(variant_index_relative, tag_layout);
- let tag_val = self.binary_op(
- mir::BinOp::Add,
- &variant_index_relative_val,
- &niche_start_val,
- )?;
- // Write result.
- let niche_dest = self.place_field(dest, tag_field)?;
- self.write_immediate(*tag_val, &niche_dest)?;
- }
+ self.write_uninit(&dest)?;
+ let (variant_index, variant_dest, active_field_index) = match *kind {
+ mir::AggregateKind::Adt(_, variant_index, _, _, active_field_index) => {
+ let variant_dest = self.place_downcast(&dest, variant_index)?;
+ (variant_index, variant_dest, active_field_index)
}
+ _ => (VariantIdx::from_u32(0), dest.clone(), None),
+ };
+ if active_field_index.is_some() {
+ assert_eq!(operands.len(), 1);
}
-
- Ok(())
+ for (field_index, operand) in operands.iter().enumerate() {
+ let field_index = active_field_index.unwrap_or(field_index);
+ let field_dest = self.place_field(&variant_dest, field_index)?;
+ let op = self.eval_operand(operand, Some(field_dest.layout))?;
+ self.copy_op(&op, &field_dest, /*allow_transmute*/ false)?;
+ }
+ self.write_discriminant(variant_index, &dest)
}
pub fn raw_const_to_mplace(
@@ -867,11 +822,16 @@ where
}
/// Turn a place with a `dyn Trait` type into a place with the actual dynamic type.
+ /// Aso returns the vtable.
pub(super) fn unpack_dyn_trait(
&self,
mplace: &MPlaceTy<'tcx, M::Provenance>,
- ) -> InterpResult<'tcx, MPlaceTy<'tcx, M::Provenance>> {
- let vtable = mplace.vtable().to_pointer(self)?; // also sanity checks the type
+ ) -> InterpResult<'tcx, (MPlaceTy<'tcx, M::Provenance>, Pointer<Option<M::Provenance>>)> {
+ assert!(
+ matches!(mplace.layout.ty.kind(), ty::Dynamic(_, _, ty::Dyn)),
+ "`unpack_dyn_trait` only makes sense on `dyn*` types"
+ );
+ let vtable = mplace.meta.unwrap_meta().to_pointer(self)?;
let (ty, _) = self.get_ptr_vtable(vtable)?;
let layout = self.layout_of(ty)?;
@@ -880,7 +840,26 @@ where
layout,
align: layout.align.abi,
};
- Ok(mplace)
+ Ok((mplace, vtable))
+ }
+
+ /// Turn an operand with a `dyn* Trait` type into an operand with the actual dynamic type.
+ /// Aso returns the vtable.
+ pub(super) fn unpack_dyn_star(
+ &self,
+ op: &OpTy<'tcx, M::Provenance>,
+ ) -> InterpResult<'tcx, (OpTy<'tcx, M::Provenance>, Pointer<Option<M::Provenance>>)> {
+ assert!(
+ matches!(op.layout.ty.kind(), ty::Dynamic(_, _, ty::DynStar)),
+ "`unpack_dyn_star` only makes sense on `dyn*` types"
+ );
+ let data = self.operand_field(&op, 0)?;
+ let vtable = self.operand_field(&op, 1)?;
+ let vtable = self.read_pointer(&vtable)?;
+ let (ty, _) = self.get_ptr_vtable(vtable)?;
+ let layout = self.layout_of(ty)?;
+ let data = data.transmute(layout);
+ Ok((data, vtable))
}
}
diff --git a/compiler/rustc_const_eval/src/interpret/projection.rs b/compiler/rustc_const_eval/src/interpret/projection.rs
index 291464ab5..91da930db 100644
--- a/compiler/rustc_const_eval/src/interpret/projection.rs
+++ b/compiler/rustc_const_eval/src/interpret/projection.rs
@@ -319,7 +319,7 @@ where
// implement this.
ty::Array(inner, _) => (MemPlaceMeta::None, self.tcx.mk_array(*inner, inner_len)),
ty::Slice(..) => {
- let len = Scalar::from_machine_usize(inner_len, self);
+ let len = Scalar::from_target_usize(inner_len, self);
(MemPlaceMeta::Meta(len), base.layout.ty)
}
_ => {
@@ -363,7 +363,7 @@ where
Index(local) => {
let layout = self.layout_of(self.tcx.types.usize)?;
let n = self.local_to_op(self.frame(), local, Some(layout))?;
- let n = self.read_machine_usize(&n)?;
+ let n = self.read_target_usize(&n)?;
self.place_index(base, n)?
}
ConstantIndex { offset, min_length, from_end } => {
@@ -392,7 +392,7 @@ where
Index(local) => {
let layout = self.layout_of(self.tcx.types.usize)?;
let n = self.local_to_op(self.frame(), local, Some(layout))?;
- let n = self.read_machine_usize(&n)?;
+ let n = self.read_target_usize(&n)?;
self.operand_index(base, n)?
}
ConstantIndex { offset, min_length, from_end } => {
diff --git a/compiler/rustc_const_eval/src/interpret/step.rs b/compiler/rustc_const_eval/src/interpret/step.rs
index fad4cb06c..6863435e5 100644
--- a/compiler/rustc_const_eval/src/interpret/step.rs
+++ b/compiler/rustc_const_eval/src/interpret/step.rs
@@ -129,6 +129,10 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
// FIXME(#73156): Handle source code coverage in const eval
Coverage(..) => {}
+ ConstEvalCounter => {
+ M::increment_const_eval_counter(self)?;
+ }
+
// Defined to do nothing. These are added by optimization passes, to avoid changing the
// size of MIR constantly.
Nop => {}
@@ -181,9 +185,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
let left = self.read_immediate(&self.eval_operand(left, None)?)?;
let layout = binop_right_homogeneous(bin_op).then_some(left.layout);
let right = self.read_immediate(&self.eval_operand(right, layout)?)?;
- self.binop_with_overflow(
- bin_op, /*force_overflow_checks*/ false, &left, &right, &dest,
- )?;
+ self.binop_with_overflow(bin_op, &left, &right, &dest)?;
}
UnaryOp(un_op, ref operand) => {
@@ -195,13 +197,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
}
Aggregate(box ref kind, ref operands) => {
- assert!(matches!(kind, mir::AggregateKind::Array(..)));
-
- for (field_index, operand) in operands.iter().enumerate() {
- let op = self.eval_operand(operand, None)?;
- let field_dest = self.place_field(&dest, field_index)?;
- self.copy_op(&op, &field_dest, /*allow_transmute*/ false)?;
- }
+ self.write_aggregate(kind, operands, &dest)?;
}
Repeat(ref operand, _) => {
@@ -244,7 +240,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
let src = self.eval_place(place)?;
let op = self.place_to_op(&src)?;
let len = op.len(self)?;
- self.write_scalar(Scalar::from_machine_usize(len, self), &dest)?;
+ self.write_scalar(Scalar::from_target_usize(len, self), &dest)?;
}
Ref(_, borrow_kind, place) => {
@@ -299,7 +295,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
mir::NullOp::SizeOf => layout.size.bytes(),
mir::NullOp::AlignOf => layout.align.abi.bytes(),
};
- self.write_scalar(Scalar::from_machine_usize(val, self), &dest)?;
+ self.write_scalar(Scalar::from_target_usize(val, self), &dest)?;
}
ShallowInitBox(ref operand, _) => {
diff --git a/compiler/rustc_const_eval/src/interpret/terminator.rs b/compiler/rustc_const_eval/src/interpret/terminator.rs
index da320cd1c..2aea7c79b 100644
--- a/compiler/rustc_const_eval/src/interpret/terminator.rs
+++ b/compiler/rustc_const_eval/src/interpret/terminator.rs
@@ -73,7 +73,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
let fn_sig =
self.tcx.normalize_erasing_late_bound_regions(self.param_env, fn_sig_binder);
let extra_args = &args[fn_sig.inputs().len()..];
- let extra_args = self.tcx.mk_type_list(extra_args.iter().map(|arg| arg.layout.ty));
+ let extra_args =
+ self.tcx.mk_type_list_from_iter(extra_args.iter().map(|arg| arg.layout.ty));
let (fn_val, fn_abi, with_caller_location) = match *func.layout.ty.kind() {
ty::FnPtr(_sig) => {
@@ -137,8 +138,14 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
}
Assert { ref cond, expected, ref msg, target, cleanup } => {
+ let ignored = M::ignore_checkable_overflow_assertions(self)
+ && match msg {
+ mir::AssertKind::OverflowNeg(..) => true,
+ mir::AssertKind::Overflow(op, ..) => op.is_checkable(),
+ _ => false,
+ };
let cond_val = self.read_scalar(&self.eval_operand(cond, None)?)?.to_bool()?;
- if expected == cond_val {
+ if ignored || expected == cond_val {
self.go_to_block(target);
} else {
M::assert_panic(self, msg, cleanup)?;
@@ -541,7 +548,14 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
let receiver_place = loop {
match receiver.layout.ty.kind() {
ty::Ref(..) | ty::RawPtr(..) => break self.deref_operand(&receiver)?,
- ty::Dynamic(..) => break receiver.assert_mem_place(), // no immediate unsized values
+ ty::Dynamic(.., ty::Dyn) => break receiver.assert_mem_place(), // no immediate unsized values
+ ty::Dynamic(.., ty::DynStar) => {
+ // Not clear how to handle this, so far we assume the receiver is always a pointer.
+ span_bug!(
+ self.cur_span(),
+ "by-value calls on a `dyn*`... are those a thing?"
+ );
+ }
_ => {
// Not there yet, search for the only non-ZST field.
let mut non_zst_field = None;
@@ -567,39 +581,59 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
}
}
};
- // Obtain the underlying trait we are working on.
- let receiver_tail = self
- .tcx
- .struct_tail_erasing_lifetimes(receiver_place.layout.ty, self.param_env);
- let ty::Dynamic(data, ..) = receiver_tail.kind() else {
- span_bug!(self.cur_span(), "dynamic call on non-`dyn` type {}", receiver_tail)
- };
- // Get the required information from the vtable.
- let vptr = receiver_place.meta.unwrap_meta().to_pointer(self)?;
- let (dyn_ty, dyn_trait) = self.get_ptr_vtable(vptr)?;
- if dyn_trait != data.principal() {
- throw_ub_format!(
- "`dyn` call on a pointer whose vtable does not match its type"
- );
- }
+ // Obtain the underlying trait we are working on, and the adjusted receiver argument.
+ let (vptr, dyn_ty, adjusted_receiver) = if let ty::Dynamic(data, _, ty::DynStar) =
+ receiver_place.layout.ty.kind()
+ {
+ let (recv, vptr) = self.unpack_dyn_star(&receiver_place.into())?;
+ let (dyn_ty, dyn_trait) = self.get_ptr_vtable(vptr)?;
+ if dyn_trait != data.principal() {
+ throw_ub_format!(
+ "`dyn*` call on a pointer whose vtable does not match its type"
+ );
+ }
+ let recv = recv.assert_mem_place(); // we passed an MPlaceTy to `unpack_dyn_star` so we definitely still have one
+
+ (vptr, dyn_ty, recv.ptr)
+ } else {
+ // Doesn't have to be a `dyn Trait`, but the unsized tail must be `dyn Trait`.
+ // (For that reason we also cannot use `unpack_dyn_trait`.)
+ let receiver_tail = self
+ .tcx
+ .struct_tail_erasing_lifetimes(receiver_place.layout.ty, self.param_env);
+ let ty::Dynamic(data, _, ty::Dyn) = receiver_tail.kind() else {
+ span_bug!(self.cur_span(), "dynamic call on non-`dyn` type {}", receiver_tail)
+ };
+ assert!(receiver_place.layout.is_unsized());
+
+ // Get the required information from the vtable.
+ let vptr = receiver_place.meta.unwrap_meta().to_pointer(self)?;
+ let (dyn_ty, dyn_trait) = self.get_ptr_vtable(vptr)?;
+ if dyn_trait != data.principal() {
+ throw_ub_format!(
+ "`dyn` call on a pointer whose vtable does not match its type"
+ );
+ }
+
+ // It might be surprising that we use a pointer as the receiver even if this
+ // is a by-val case; this works because by-val passing of an unsized `dyn
+ // Trait` to a function is actually desugared to a pointer.
+ (vptr, dyn_ty, receiver_place.ptr)
+ };
// Now determine the actual method to call. We can do that in two different ways and
// compare them to ensure everything fits.
let Some(ty::VtblEntry::Method(fn_inst)) = self.get_vtable_entries(vptr)?.get(idx).copied() else {
throw_ub_format!("`dyn` call trying to call something that is not a method")
};
+ trace!("Virtual call dispatches to {fn_inst:#?}");
if cfg!(debug_assertions) {
let tcx = *self.tcx;
let trait_def_id = tcx.trait_of_item(def_id).unwrap();
let virtual_trait_ref =
ty::TraitRef::from_method(tcx, trait_def_id, instance.substs);
- assert_eq!(
- receiver_tail,
- virtual_trait_ref.self_ty(),
- "mismatch in underlying dyn trait computation within Miri and MIR building",
- );
let existential_trait_ref =
ty::ExistentialTraitRef::erase_self_ty(tcx, virtual_trait_ref);
let concrete_trait_ref = existential_trait_ref.with_self_ty(tcx, dyn_ty);
@@ -614,17 +648,12 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
assert_eq!(fn_inst, concrete_method);
}
- // `*mut receiver_place.layout.ty` is almost the layout that we
- // want for args[0]: We have to project to field 0 because we want
- // a thin pointer.
- assert!(receiver_place.layout.is_unsized());
- let receiver_ptr_ty = self.tcx.mk_mut_ptr(receiver_place.layout.ty);
- let this_receiver_ptr = self.layout_of(receiver_ptr_ty)?.field(self, 0);
- // Adjust receiver argument.
- args[0] = OpTy::from(ImmTy::from_immediate(
- Scalar::from_maybe_pointer(receiver_place.ptr, self).into(),
- this_receiver_ptr,
- ));
+ // Adjust receiver argument. Layout can be any (thin) ptr.
+ args[0] = ImmTy::from_immediate(
+ Scalar::from_maybe_pointer(adjusted_receiver, self).into(),
+ self.layout_of(self.tcx.mk_mut_ptr(dyn_ty))?,
+ )
+ .into();
trace!("Patched receiver operand to {:#?}", args[0]);
// recurse with concrete function
self.eval_fn_call(
@@ -653,15 +682,24 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
// implementation fail -- a problem shared by rustc.
let place = self.force_allocation(place)?;
- let (instance, place) = match place.layout.ty.kind() {
- ty::Dynamic(..) => {
+ let place = match place.layout.ty.kind() {
+ ty::Dynamic(_, _, ty::Dyn) => {
// Dropping a trait object. Need to find actual drop fn.
- let place = self.unpack_dyn_trait(&place)?;
- let instance = ty::Instance::resolve_drop_in_place(*self.tcx, place.layout.ty);
- (instance, place)
+ self.unpack_dyn_trait(&place)?.0
+ }
+ ty::Dynamic(_, _, ty::DynStar) => {
+ // Dropping a `dyn*`. Need to find actual drop fn.
+ self.unpack_dyn_star(&place.into())?.0.assert_mem_place()
+ }
+ _ => {
+ debug_assert_eq!(
+ instance,
+ ty::Instance::resolve_drop_in_place(*self.tcx, place.layout.ty)
+ );
+ place
}
- _ => (instance, place),
};
+ let instance = ty::Instance::resolve_drop_in_place(*self.tcx, place.layout.ty);
let fn_abi = self.fn_abi_of_instance(instance, ty::List::empty())?;
let arg = ImmTy::from_immediate(
diff --git a/compiler/rustc_const_eval/src/interpret/util.rs b/compiler/rustc_const_eval/src/interpret/util.rs
index cabc65e2c..bf2b4ee69 100644
--- a/compiler/rustc_const_eval/src/interpret/util.rs
+++ b/compiler/rustc_const_eval/src/interpret/util.rs
@@ -1,5 +1,7 @@
use rustc_middle::mir::interpret::InterpResult;
-use rustc_middle::ty::{self, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitor};
+use rustc_middle::ty::{
+ self, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor,
+};
use std::ops::ControlFlow;
/// Checks whether a type contains generic parameters which require substitution.
@@ -9,7 +11,7 @@ use std::ops::ControlFlow;
/// case these parameters are unused.
pub(crate) fn ensure_monomorphic_enough<'tcx, T>(tcx: TyCtxt<'tcx>, ty: T) -> InterpResult<'tcx>
where
- T: TypeVisitable<'tcx>,
+ T: TypeVisitable<TyCtxt<'tcx>>,
{
debug!("ensure_monomorphic_enough: ty={:?}", ty);
if !ty.needs_subst() {
@@ -21,7 +23,7 @@ where
tcx: TyCtxt<'tcx>,
}
- impl<'tcx> TypeVisitor<'tcx> for UsedParamsNeedSubstVisitor<'tcx> {
+ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for UsedParamsNeedSubstVisitor<'tcx> {
type BreakTy = FoundParam;
fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
diff --git a/compiler/rustc_const_eval/src/interpret/validity.rs b/compiler/rustc_const_eval/src/interpret/validity.rs
index 19e359986..f7881c509 100644
--- a/compiler/rustc_const_eval/src/interpret/validity.rs
+++ b/compiler/rustc_const_eval/src/interpret/validity.rs
@@ -23,18 +23,18 @@ use std::hash::Hash;
// for the validation errors
use super::UndefinedBehaviorInfo::*;
use super::{
- CheckInAllocMsg, GlobalAlloc, ImmTy, Immediate, InterpCx, InterpResult, MPlaceTy, Machine,
- MemPlaceMeta, OpTy, Scalar, ValueVisitor,
+ AllocId, CheckInAllocMsg, GlobalAlloc, ImmTy, Immediate, InterpCx, InterpResult, MPlaceTy,
+ Machine, MemPlaceMeta, OpTy, Pointer, Scalar, ValueVisitor,
};
macro_rules! throw_validation_failure {
- ($where:expr, { $( $what_fmt:expr ),+ } $( expected { $( $expected_fmt:expr ),+ } )?) => {{
+ ($where:expr, { $( $what_fmt:tt )* } $( expected { $( $expected_fmt:tt )* } )?) => {{
let mut msg = String::new();
msg.push_str("encountered ");
- write!(&mut msg, $($what_fmt),+).unwrap();
+ write!(&mut msg, $($what_fmt)*).unwrap();
$(
msg.push_str(", but expected ");
- write!(&mut msg, $($expected_fmt),+).unwrap();
+ write!(&mut msg, $($expected_fmt)*).unwrap();
)?
let path = rustc_middle::ty::print::with_no_trimmed_paths!({
let where_ = &$where;
@@ -82,7 +82,7 @@ macro_rules! throw_validation_failure {
///
macro_rules! try_validation {
($e:expr, $where:expr,
- $( $( $p:pat_param )|+ => { $( $what_fmt:expr ),+ } $( expected { $( $expected_fmt:expr ),+ } )? ),+ $(,)?
+ $( $( $p:pat_param )|+ => { $( $what_fmt:tt )* } $( expected { $( $expected_fmt:tt )* } )? ),+ $(,)?
) => {{
match $e {
Ok(x) => x,
@@ -93,7 +93,7 @@ macro_rules! try_validation {
InterpError::UndefinedBehavior($($p)|+) =>
throw_validation_failure!(
$where,
- { $( $what_fmt ),+ } $( expected { $( $expected_fmt ),+ } )?
+ { $( $what_fmt )* } $( expected { $( $expected_fmt )* } )?
)
),+,
#[allow(unreachable_patterns)]
@@ -240,10 +240,8 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, '
// FIXME this should be more descriptive i.e. CapturePlace instead of CapturedVar
// https://github.com/rust-lang/project-rfc-2229/issues/46
if let Some(local_def_id) = def_id.as_local() {
- let tables = self.ecx.tcx.typeck(local_def_id);
- if let Some(captured_place) =
- tables.closure_min_captures_flattened(local_def_id).nth(field)
- {
+ let captures = self.ecx.tcx.closure_captures(local_def_id);
+ if let Some(captured_place) = captures.get(field) {
// Sometimes the index is beyond the number of upvars (seen
// for a generator).
let var_hir_id = captured_place.get_root_variable();
@@ -335,7 +333,7 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, '
) -> InterpResult<'tcx> {
let tail = self.ecx.tcx.struct_tail_erasing_lifetimes(pointee.ty, self.ecx.param_env);
match tail.kind() {
- ty::Dynamic(..) => {
+ ty::Dynamic(_, _, ty::Dyn) => {
let vtable = meta.unwrap_meta().to_pointer(self.ecx)?;
// Make sure it is a genuine vtable pointer.
let (_ty, _trait) = try_validation!(
@@ -348,7 +346,7 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, '
// FIXME: check if the type/trait match what ty::Dynamic says?
}
ty::Slice(..) | ty::Str => {
- let _len = meta.unwrap_meta().to_machine_usize(self.ecx)?;
+ let _len = meta.unwrap_meta().to_target_usize(self.ecx)?;
// We do not check that `len * elem_size <= isize::MAX`:
// that is only required for references, and there it falls out of the
// "dereferenceable" check performed by Stacked Borrows.
@@ -399,12 +397,15 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, '
{
"an unaligned {kind} (required {} byte alignment but found {})",
required.bytes(),
- has.bytes()
+ has.bytes(),
},
DanglingIntPointer(0, _) =>
{ "a null {kind}" },
DanglingIntPointer(i, _) =>
- { "a dangling {kind} (address {i:#x} is unallocated)" },
+ {
+ "a dangling {kind} ({pointer} has no provenance)",
+ pointer = Pointer::<Option<AllocId>>::from_addr_invalid(*i),
+ },
PointerOutOfBounds { .. } =>
{ "a dangling {kind} (going beyond the bounds of its allocation)" },
// This cannot happen during const-eval (because interning already detects
@@ -602,6 +603,7 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, '
| ty::Bound(..)
| ty::Param(..)
| ty::Alias(..)
+ | ty::GeneratorWitnessMIR(..)
| ty::GeneratorWitness(..) => bug!("Encountered invalid type {:?}", ty),
}
}
diff --git a/compiler/rustc_const_eval/src/interpret/visitor.rs b/compiler/rustc_const_eval/src/interpret/visitor.rs
index f9efc2418..7a1445939 100644
--- a/compiler/rustc_const_eval/src/interpret/visitor.rs
+++ b/compiler/rustc_const_eval/src/interpret/visitor.rs
@@ -284,7 +284,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValueMut<'mir, 'tcx, M>
&self,
ecx: &InterpCx<'mir, 'tcx, M>,
) -> InterpResult<'tcx, OpTy<'tcx, M::Provenance>> {
- // We `force_allocation` here so that `from_op` below can work.
+ // No need for `force_allocation` since we are just going to read from this.
ecx.place_to_op(self)
}
@@ -421,15 +421,25 @@ macro_rules! make_value_visitor {
// Special treatment for special types, where the (static) layout is not sufficient.
match *ty.kind() {
// If it is a trait object, switch to the real type that was used to create it.
- ty::Dynamic(..) => {
+ ty::Dynamic(_, _, ty::Dyn) => {
+ // Dyn types. This is unsized, and the actual dynamic type of the data is given by the
+ // vtable stored in the place metadata.
// unsized values are never immediate, so we can assert_mem_place
let op = v.to_op_for_read(self.ecx())?;
let dest = op.assert_mem_place();
- let inner_mplace = self.ecx().unpack_dyn_trait(&dest)?;
+ let inner_mplace = self.ecx().unpack_dyn_trait(&dest)?.0;
trace!("walk_value: dyn object layout: {:#?}", inner_mplace.layout);
// recurse with the inner type
return self.visit_field(&v, 0, &$value_trait::from_op(&inner_mplace.into()));
},
+ ty::Dynamic(_, _, ty::DynStar) => {
+ // DynStar types. Very different from a dyn type (but strangely part of the
+ // same variant in `TyKind`): These are pairs where the 2nd component is the
+ // vtable, and the first component is the data (which must be ptr-sized).
+ let op = v.to_op_for_proj(self.ecx())?;
+ let data = self.ecx().unpack_dyn_star(&op)?.0;
+ return self.visit_field(&v, 0, &$value_trait::from_op(&data));
+ }
// Slices do not need special handling here: they have `Array` field
// placement with length 0, so we enter the `Array` case below which
// indirectly uses the metadata to determine the actual length.
diff --git a/compiler/rustc_const_eval/src/lib.rs b/compiler/rustc_const_eval/src/lib.rs
index 57b91df2d..ed9efe568 100644
--- a/compiler/rustc_const_eval/src/lib.rs
+++ b/compiler/rustc_const_eval/src/lib.rs
@@ -34,9 +34,12 @@ pub mod interpret;
pub mod transform;
pub mod util;
+use rustc_errors::{DiagnosticMessage, SubdiagnosticMessage};
+use rustc_macros::fluent_messages;
use rustc_middle::ty;
use rustc_middle::ty::query::Providers;
-use rustc_target::abi::InitKind;
+
+fluent_messages! { "../locales/en-US.ftl" }
pub fn provide(providers: &mut Providers) {
const_eval::provide(providers);
@@ -58,7 +61,7 @@ pub fn provide(providers: &mut Providers) {
let (param_env, value) = param_env_and_value.into_parts();
const_eval::deref_mir_constant(tcx, param_env, value)
};
- providers.permits_uninit_init =
- |tcx, ty| util::might_permit_raw_init(tcx, ty, InitKind::UninitMitigated0x01Fill);
- providers.permits_zero_init = |tcx, ty| util::might_permit_raw_init(tcx, ty, InitKind::Zero);
+ providers.check_validity_requirement = |tcx, (init_kind, param_env_and_ty)| {
+ util::check_validity_requirement(tcx, init_kind, param_env_and_ty)
+ };
}
diff --git a/compiler/rustc_const_eval/src/transform/check_consts/check.rs b/compiler/rustc_const_eval/src/transform/check_consts/check.rs
index 79f1737e3..aa24d9053 100644
--- a/compiler/rustc_const_eval/src/transform/check_consts/check.rs
+++ b/compiler/rustc_const_eval/src/transform/check_consts/check.rs
@@ -10,7 +10,7 @@ use rustc_middle::mir::visit::{MutatingUseContext, NonMutatingUseContext, PlaceC
use rustc_middle::mir::*;
use rustc_middle::ty::subst::{GenericArgKind, InternalSubsts};
use rustc_middle::ty::{self, adjustment::PointerCast, Instance, InstanceDef, Ty, TyCtxt};
-use rustc_middle::ty::{Binder, TraitRef, TypeVisitable};
+use rustc_middle::ty::{Binder, TraitRef, TypeVisitableExt};
use rustc_mir_dataflow::{self, Analysis};
use rustc_span::{sym, Span, Symbol};
use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt as _;
@@ -332,7 +332,7 @@ impl<'mir, 'tcx> Checker<'mir, 'tcx> {
fn check_static(&mut self, def_id: DefId, span: Span) {
if self.tcx.is_thread_local_static(def_id) {
- self.tcx.sess.delay_span_bug(span, "tls access is checked in `Rvalue::ThreadLocalRef");
+ self.tcx.sess.delay_span_bug(span, "tls access is checked in `Rvalue::ThreadLocalRef`");
}
self.check_op_spanned(ops::StaticAccess, span)
}
@@ -453,7 +453,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
Rvalue::Aggregate(kind, ..) => {
if let AggregateKind::Generator(def_id, ..) = kind.as_ref()
- && let Some(generator_kind @ hir::GeneratorKind::Async(..)) = self.tcx.generator_kind(def_id.to_def_id())
+ && let Some(generator_kind @ hir::GeneratorKind::Async(..)) = self.tcx.generator_kind(def_id)
{
self.check_op(ops::Generator(generator_kind));
}
@@ -473,7 +473,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
// that this is merely a ZST and it is already eligible for promotion.
// This may require an RFC?
/*
- ty::Array(_, len) if len.try_eval_usize(cx.tcx, cx.param_env) == Some(0)
+ ty::Array(_, len) if len.try_eval_target_usize(cx.tcx, cx.param_env) == Some(0)
=> true,
*/
_ => false,
@@ -693,6 +693,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
| StatementKind::AscribeUserType(..)
| StatementKind::Coverage(..)
| StatementKind::Intrinsic(..)
+ | StatementKind::ConstEvalCounter
| StatementKind::Nop => {}
}
}
@@ -754,12 +755,9 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
let ocx = ObligationCtxt::new(&infcx);
let predicates = tcx.predicates_of(callee).instantiate(tcx, substs);
- let hir_id = tcx
- .hir()
- .local_def_id_to_hir_id(self.body.source.def_id().expect_local());
let cause = ObligationCause::new(
terminator.source_info.span,
- hir_id,
+ self.body.source.def_id().expect_local(),
ObligationCauseCode::ItemObligation(callee),
);
let normalized_predicates = ocx.normalize(&cause, param_env, predicates);
diff --git a/compiler/rustc_const_eval/src/transform/check_consts/mod.rs b/compiler/rustc_const_eval/src/transform/check_consts/mod.rs
index 54868e418..0e4501922 100644
--- a/compiler/rustc_const_eval/src/transform/check_consts/mod.rs
+++ b/compiler/rustc_const_eval/src/transform/check_consts/mod.rs
@@ -68,11 +68,11 @@ impl<'mir, 'tcx> ConstCx<'mir, 'tcx> {
pub fn fn_sig(&self) -> PolyFnSig<'tcx> {
let did = self.def_id().to_def_id();
if self.tcx.is_closure(did) {
- let ty = self.tcx.type_of(did);
+ let ty = self.tcx.type_of(did).subst_identity();
let ty::Closure(_, substs) = ty.kind() else { bug!("type_of closure not ty::Closure") };
substs.as_closure().sig()
} else {
- self.tcx.fn_sig(did)
+ self.tcx.fn_sig(did).subst_identity()
}
}
}
diff --git a/compiler/rustc_const_eval/src/transform/check_consts/ops.rs b/compiler/rustc_const_eval/src/transform/check_consts/ops.rs
index 0cb5d2ff8..3e416b89c 100644
--- a/compiler/rustc_const_eval/src/transform/check_consts/ops.rs
+++ b/compiler/rustc_const_eval/src/transform/check_consts/ops.rs
@@ -22,13 +22,7 @@ use rustc_span::{BytePos, Pos, Span, Symbol};
use rustc_trait_selection::traits::SelectionContext;
use super::ConstCx;
-use crate::errors::{
- InteriorMutabilityBorrow, InteriorMutableDataRefer, MutDerefErr, NonConstFmtMacroCall,
- NonConstFnCall, NonConstOpErr, PanicNonStrErr, RawPtrToIntErr, StaticAccessErr,
- TransientMutBorrowErr, TransientMutBorrowErrRaw, UnallowedFnPointerCall,
- UnallowedHeapAllocations, UnallowedInlineAsm, UnallowedMutableRefs, UnallowedMutableRefsRaw,
- UnallowedOpInConstContext, UnstableConstFn,
-};
+use crate::errors;
use crate::util::{call_kind, CallDesugaringKind, CallKind};
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
@@ -99,7 +93,7 @@ impl<'tcx> NonConstOp<'tcx> for FnCallIndirect {
ccx: &ConstCx<'_, 'tcx>,
span: Span,
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
- ccx.tcx.sess.create_err(UnallowedFnPointerCall { span, kind: ccx.const_kind() })
+ ccx.tcx.sess.create_err(errors::UnallowedFnPointerCall { span, kind: ccx.const_kind() })
}
}
@@ -142,6 +136,7 @@ impl<'tcx> NonConstOp<'tcx> for FnCallNonConst<'tcx> {
&param_ty.name.as_str(),
&constraint,
None,
+ None,
);
}
}
@@ -303,10 +298,11 @@ impl<'tcx> NonConstOp<'tcx> for FnCallNonConst<'tcx> {
diag_trait(&mut err, self_ty, tcx.require_lang_item(LangItem::Deref, Some(span)));
err
}
- _ if tcx.opt_parent(callee) == tcx.get_diagnostic_item(sym::ArgumentV1Methods) => {
- ccx.tcx.sess.create_err(NonConstFmtMacroCall { span, kind: ccx.const_kind() })
- }
- _ => ccx.tcx.sess.create_err(NonConstFnCall {
+ _ if tcx.opt_parent(callee) == tcx.get_diagnostic_item(sym::ArgumentV1Methods) => ccx
+ .tcx
+ .sess
+ .create_err(errors::NonConstFmtMacroCall { span, kind: ccx.const_kind() }),
+ _ => ccx.tcx.sess.create_err(errors::NonConstFnCall {
span,
def_path_str: ccx.tcx.def_path_str_with_substs(callee, substs),
kind: ccx.const_kind(),
@@ -351,7 +347,7 @@ impl<'tcx> NonConstOp<'tcx> for FnCallUnstable {
let mut err = ccx
.tcx
.sess
- .create_err(UnstableConstFn { span, def_path: ccx.tcx.def_path_str(def_id) });
+ .create_err(errors::UnstableConstFn { span, def_path: ccx.tcx.def_path_str(def_id) });
if ccx.is_const_stable_const_fn() {
err.help("const-stable functions can only call other const-stable functions");
@@ -387,11 +383,11 @@ impl<'tcx> NonConstOp<'tcx> for Generator {
let msg = format!("{}s are not allowed in {}s", self.0.descr(), ccx.const_kind());
if let hir::GeneratorKind::Async(hir::AsyncGeneratorKind::Block) = self.0 {
ccx.tcx.sess.create_feature_err(
- UnallowedOpInConstContext { span, msg },
+ errors::UnallowedOpInConstContext { span, msg },
sym::const_async_blocks,
)
} else {
- ccx.tcx.sess.create_err(UnallowedOpInConstContext { span, msg })
+ ccx.tcx.sess.create_err(errors::UnallowedOpInConstContext { span, msg })
}
}
}
@@ -404,7 +400,7 @@ impl<'tcx> NonConstOp<'tcx> for HeapAllocation {
ccx: &ConstCx<'_, 'tcx>,
span: Span,
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
- ccx.tcx.sess.create_err(UnallowedHeapAllocations {
+ ccx.tcx.sess.create_err(errors::UnallowedHeapAllocations {
span,
kind: ccx.const_kind(),
teach: ccx.tcx.sess.teach(&error_code!(E0010)).then_some(()),
@@ -420,7 +416,7 @@ impl<'tcx> NonConstOp<'tcx> for InlineAsm {
ccx: &ConstCx<'_, 'tcx>,
span: Span,
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
- ccx.tcx.sess.create_err(UnallowedInlineAsm { span, kind: ccx.const_kind() })
+ ccx.tcx.sess.create_err(errors::UnallowedInlineAsm { span, kind: ccx.const_kind() })
}
}
@@ -471,7 +467,9 @@ impl<'tcx> NonConstOp<'tcx> for TransientCellBorrow {
ccx: &ConstCx<'_, 'tcx>,
span: Span,
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
- ccx.tcx.sess.create_feature_err(InteriorMutabilityBorrow { span }, sym::const_refs_to_cell)
+ ccx.tcx
+ .sess
+ .create_feature_err(errors::InteriorMutabilityBorrow { span }, sym::const_refs_to_cell)
}
}
@@ -488,14 +486,14 @@ impl<'tcx> NonConstOp<'tcx> for CellBorrow {
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
// FIXME: Maybe a more elegant solution to this if else case
if let hir::ConstContext::Static(_) = ccx.const_kind() {
- ccx.tcx.sess.create_err(InteriorMutableDataRefer {
+ ccx.tcx.sess.create_err(errors::InteriorMutableDataRefer {
span,
opt_help: Some(()),
kind: ccx.const_kind(),
teach: ccx.tcx.sess.teach(&error_code!(E0492)).then_some(()),
})
} else {
- ccx.tcx.sess.create_err(InteriorMutableDataRefer {
+ ccx.tcx.sess.create_err(errors::InteriorMutableDataRefer {
span,
opt_help: None,
kind: ccx.const_kind(),
@@ -528,12 +526,12 @@ impl<'tcx> NonConstOp<'tcx> for MutBorrow {
span: Span,
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
match self.0 {
- hir::BorrowKind::Raw => ccx.tcx.sess.create_err(UnallowedMutableRefsRaw {
+ hir::BorrowKind::Raw => ccx.tcx.sess.create_err(errors::UnallowedMutableRefsRaw {
span,
kind: ccx.const_kind(),
teach: ccx.tcx.sess.teach(&error_code!(E0764)).then_some(()),
}),
- hir::BorrowKind::Ref => ccx.tcx.sess.create_err(UnallowedMutableRefs {
+ hir::BorrowKind::Ref => ccx.tcx.sess.create_err(errors::UnallowedMutableRefs {
span,
kind: ccx.const_kind(),
teach: ccx.tcx.sess.teach(&error_code!(E0764)).then_some(()),
@@ -557,14 +555,14 @@ impl<'tcx> NonConstOp<'tcx> for TransientMutBorrow {
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
let kind = ccx.const_kind();
match self.0 {
- hir::BorrowKind::Raw => ccx
- .tcx
- .sess
- .create_feature_err(TransientMutBorrowErrRaw { span, kind }, sym::const_mut_refs),
- hir::BorrowKind::Ref => ccx
- .tcx
- .sess
- .create_feature_err(TransientMutBorrowErr { span, kind }, sym::const_mut_refs),
+ hir::BorrowKind::Raw => ccx.tcx.sess.create_feature_err(
+ errors::TransientMutBorrowErrRaw { span, kind },
+ sym::const_mut_refs,
+ ),
+ hir::BorrowKind::Ref => ccx.tcx.sess.create_feature_err(
+ errors::TransientMutBorrowErr { span, kind },
+ sym::const_mut_refs,
+ ),
}
}
}
@@ -586,9 +584,10 @@ impl<'tcx> NonConstOp<'tcx> for MutDeref {
ccx: &ConstCx<'_, 'tcx>,
span: Span,
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
- ccx.tcx
- .sess
- .create_feature_err(MutDerefErr { span, kind: ccx.const_kind() }, sym::const_mut_refs)
+ ccx.tcx.sess.create_feature_err(
+ errors::MutDerefErr { span, kind: ccx.const_kind() },
+ sym::const_mut_refs,
+ )
}
}
@@ -601,7 +600,7 @@ impl<'tcx> NonConstOp<'tcx> for PanicNonStr {
ccx: &ConstCx<'_, 'tcx>,
span: Span,
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
- ccx.tcx.sess.create_err(PanicNonStrErr { span })
+ ccx.tcx.sess.create_err(errors::PanicNonStrErr { span })
}
}
@@ -652,7 +651,7 @@ impl<'tcx> NonConstOp<'tcx> for RawPtrToIntCast {
ccx: &ConstCx<'_, 'tcx>,
span: Span,
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
- ccx.tcx.sess.create_err(RawPtrToIntErr { span })
+ ccx.tcx.sess.create_err(errors::RawPtrToIntErr { span })
}
}
@@ -673,7 +672,7 @@ impl<'tcx> NonConstOp<'tcx> for StaticAccess {
ccx: &ConstCx<'_, 'tcx>,
span: Span,
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
- ccx.tcx.sess.create_err(StaticAccessErr {
+ ccx.tcx.sess.create_err(errors::StaticAccessErr {
span,
kind: ccx.const_kind(),
teach: ccx.tcx.sess.teach(&error_code!(E0013)).then_some(()),
@@ -690,7 +689,7 @@ impl<'tcx> NonConstOp<'tcx> for ThreadLocalAccess {
ccx: &ConstCx<'_, 'tcx>,
span: Span,
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
- ccx.tcx.sess.create_err(NonConstOpErr { span })
+ ccx.tcx.sess.create_err(errors::NonConstOpErr { span })
}
}
diff --git a/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs b/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs
index 8ca3fdf40..bb4b7ad50 100644
--- a/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs
+++ b/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs
@@ -217,10 +217,10 @@ impl Qualif for CustomEq {
fn in_adt_inherently<'tcx>(
cx: &ConstCx<'_, 'tcx>,
- adt: AdtDef<'tcx>,
+ def: AdtDef<'tcx>,
substs: SubstsRef<'tcx>,
) -> bool {
- let ty = cx.tcx.mk_ty(ty::Adt(adt, substs));
+ let ty = cx.tcx.mk_adt(def, substs);
!ty.is_structural_eq_shallow(cx.tcx)
}
}
diff --git a/compiler/rustc_const_eval/src/transform/promote_consts.rs b/compiler/rustc_const_eval/src/transform/promote_consts.rs
index fae6117f8..3f3b66b06 100644
--- a/compiler/rustc_const_eval/src/transform/promote_consts.rs
+++ b/compiler/rustc_const_eval/src/transform/promote_consts.rs
@@ -18,7 +18,7 @@ use rustc_middle::mir::traversal::ReversePostorderIter;
use rustc_middle::mir::visit::{MutVisitor, MutatingUseContext, PlaceContext, Visitor};
use rustc_middle::mir::*;
use rustc_middle::ty::subst::InternalSubsts;
-use rustc_middle::ty::{self, List, TyCtxt, TypeVisitable};
+use rustc_middle::ty::{self, List, TyCtxt, TypeVisitableExt};
use rustc_span::Span;
use rustc_index::vec::{Idx, IndexVec};
@@ -364,31 +364,33 @@ impl<'tcx> Validator<'_, 'tcx> {
ProjectionElem::Index(local) => {
let mut promotable = false;
// Only accept if we can predict the index and are indexing an array.
- let val =
- if let TempState::Defined { location: loc, .. } = self.temps[local] {
- let block = &self.body[loc.block];
- if loc.statement_index < block.statements.len() {
- let statement = &block.statements[loc.statement_index];
- match &statement.kind {
- StatementKind::Assign(box (
- _,
- Rvalue::Use(Operand::Constant(c)),
- )) => c.literal.try_eval_usize(self.tcx, self.param_env),
- _ => None,
- }
- } else {
- None
+ let val = if let TempState::Defined { location: loc, .. } =
+ self.temps[local]
+ {
+ let block = &self.body[loc.block];
+ if loc.statement_index < block.statements.len() {
+ let statement = &block.statements[loc.statement_index];
+ match &statement.kind {
+ StatementKind::Assign(box (
+ _,
+ Rvalue::Use(Operand::Constant(c)),
+ )) => c.literal.try_eval_target_usize(self.tcx, self.param_env),
+ _ => None,
}
} else {
None
- };
+ }
+ } else {
+ None
+ };
if let Some(idx) = val {
// Determine the type of the thing we are indexing.
let ty = place_base.ty(self.body, self.tcx).ty;
match ty.kind() {
ty::Array(_, len) => {
// It's an array; determine its length.
- if let Some(len) = len.try_eval_usize(self.tcx, self.param_env)
+ if let Some(len) =
+ len.try_eval_target_usize(self.tcx, self.param_env)
{
// If the index is in-bounds, go ahead.
if idx < len {
@@ -470,7 +472,7 @@ impl<'tcx> Validator<'_, 'tcx> {
// mutably without consequences. However, only &mut []
// is allowed right now.
if let ty::Array(_, len) = ty.kind() {
- match len.try_eval_usize(self.tcx, self.param_env) {
+ match len.try_eval_target_usize(self.tcx, self.param_env) {
Some(0) => {}
_ => return Err(Unpromotable),
}
@@ -864,7 +866,7 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> {
let mut projection = vec![PlaceElem::Deref];
projection.extend(place.projection);
- place.projection = tcx.intern_place_elems(&projection);
+ place.projection = tcx.mk_place_elems(&projection);
// Create a temp to hold the promoted reference.
// This is because `*r` requires `r` to be a local,
@@ -896,7 +898,7 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> {
assert_eq!(self.new_block(), START_BLOCK);
self.visit_rvalue(
&mut rvalue,
- Location { block: BasicBlock::new(0), statement_index: usize::MAX },
+ Location { block: START_BLOCK, statement_index: usize::MAX },
);
let span = self.promoted.span;
diff --git a/compiler/rustc_const_eval/src/transform/validate.rs b/compiler/rustc_const_eval/src/transform/validate.rs
index dd168a9ac..fb37eb79a 100644
--- a/compiler/rustc_const_eval/src/transform/validate.rs
+++ b/compiler/rustc_const_eval/src/transform/validate.rs
@@ -8,12 +8,12 @@ use rustc_middle::mir::interpret::Scalar;
use rustc_middle::mir::visit::NonUseContext::VarDebugInfo;
use rustc_middle::mir::visit::{PlaceContext, Visitor};
use rustc_middle::mir::{
- traversal, AggregateKind, BasicBlock, BinOp, Body, BorrowKind, CastKind, CopyNonOverlapping,
- Local, Location, MirPass, MirPhase, NonDivergingIntrinsic, Operand, Place, PlaceElem, PlaceRef,
- ProjectionElem, RetagKind, RuntimePhase, Rvalue, SourceScope, Statement, StatementKind,
- Terminator, TerminatorKind, UnOp, START_BLOCK,
+ traversal, BasicBlock, BinOp, Body, BorrowKind, CastKind, CopyNonOverlapping, Local, Location,
+ MirPass, MirPhase, NonDivergingIntrinsic, Operand, Place, PlaceElem, PlaceRef, ProjectionElem,
+ RetagKind, RuntimePhase, Rvalue, SourceScope, Statement, StatementKind, Terminator,
+ TerminatorKind, UnOp, START_BLOCK,
};
-use rustc_middle::ty::{self, InstanceDef, ParamEnv, Ty, TyCtxt, TypeVisitable};
+use rustc_middle::ty::{self, InstanceDef, ParamEnv, Ty, TyCtxt, TypeVisitableExt};
use rustc_mir_dataflow::impls::MaybeStorageLive;
use rustc_mir_dataflow::storage::always_storage_live_locals;
use rustc_mir_dataflow::{Analysis, ResultsCursor};
@@ -230,8 +230,12 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
// Equal types, all is good.
return true;
}
- // Normalization reveals opaque types, but we may be validating MIR while computing
- // said opaque types, causing cycles.
+
+ // We sometimes have to use `defining_opaque_types` for subtyping
+ // to succeed here and figuring out how exactly that should work
+ // is annoying. It is harmless enough to just not validate anything
+ // in that case. We still check this after analysis as all opque
+ // types have been revealed at this point.
if (src, dest).has_opaque_types() {
return true;
}
@@ -311,7 +315,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
}
}
ProjectionElem::Field(f, ty) => {
- let parent = Place { local, projection: self.tcx.intern_place_elems(proj_base) };
+ let parent = Place { local, projection: self.tcx.mk_place_elems(proj_base) };
let parent_ty = parent.ty(&self.body.local_decls, self.tcx);
let fail_out_of_bounds = |this: &Self, location| {
this.fail(location, format!("Out of bounds field {:?} for {:?}", f, parent_ty));
@@ -330,7 +334,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
let kind = match parent_ty.ty.kind() {
&ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. }) => {
- self.tcx.bound_type_of(def_id).subst(self.tcx, substs).kind()
+ self.tcx.type_of(def_id).subst(self.tcx, substs).kind()
}
kind => kind,
};
@@ -377,12 +381,12 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
return;
};
- let Some(&f_ty) = layout.field_tys.get(local) else {
+ let Some(f_ty) = layout.field_tys.get(local) else {
self.fail(location, format!("Out of bounds local {:?} for {:?}", local, parent_ty));
return;
};
- f_ty
+ f_ty.ty
} else {
let Some(f_ty) = substs.as_generator().prefix_tys().nth(f.index()) else {
fail_out_of_bounds(self, location);
@@ -428,19 +432,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
};
}
match rvalue {
- Rvalue::Use(_) | Rvalue::CopyForDeref(_) => {}
- Rvalue::Aggregate(agg_kind, _) => {
- let disallowed = match **agg_kind {
- AggregateKind::Array(..) => false,
- _ => self.mir_phase >= MirPhase::Runtime(RuntimePhase::PostCleanup),
- };
- if disallowed {
- self.fail(
- location,
- format!("{:?} have been lowered to field assignments", rvalue),
- )
- }
- }
+ Rvalue::Use(_) | Rvalue::CopyForDeref(_) | Rvalue::Aggregate(..) => {}
Rvalue::Ref(_, BorrowKind::Shallow, _) => {
if self.mir_phase >= MirPhase::Runtime(RuntimePhase::Initial) {
self.fail(
@@ -759,13 +751,32 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
// FIXME(JakobDegen) The validator should check that `self.mir_phase <
// DropsLowered`. However, this causes ICEs with generation of drop shims, which
// seem to fail to set their `MirPhase` correctly.
- if *kind == RetagKind::Raw || *kind == RetagKind::TwoPhase {
+ if matches!(kind, RetagKind::Raw | RetagKind::TwoPhase) {
self.fail(location, format!("explicit `{:?}` is forbidden", kind));
}
}
- StatementKind::StorageLive(..)
- | StatementKind::StorageDead(..)
+ StatementKind::StorageLive(local) => {
+ // We check that the local is not live when entering a `StorageLive` for it.
+ // Technically, violating this restriction is only UB and not actually indicative
+ // of not well-formed MIR. This means that an optimization which turns MIR that
+ // already has UB into MIR that fails this check is not necessarily wrong. However,
+ // we have no such optimizations at the moment, and so we include this check anyway
+ // to help us catch bugs. If you happen to write an optimization that might cause
+ // this to incorrectly fire, feel free to remove this check.
+ if self.reachable_blocks.contains(location.block) {
+ self.storage_liveness.seek_before_primary_effect(location);
+ let locals_with_storage = self.storage_liveness.get();
+ if locals_with_storage.contains(*local) {
+ self.fail(
+ location,
+ format!("StorageLive({local:?}) which already has storage here"),
+ );
+ }
+ }
+ }
+ StatementKind::StorageDead(_)
| StatementKind::Coverage(_)
+ | StatementKind::ConstEvalCounter
| StatementKind::Nop => {}
}
diff --git a/compiler/rustc_const_eval/src/util/aggregate.rs b/compiler/rustc_const_eval/src/util/aggregate.rs
deleted file mode 100644
index 10783c5ed..000000000
--- a/compiler/rustc_const_eval/src/util/aggregate.rs
+++ /dev/null
@@ -1,77 +0,0 @@
-use rustc_index::vec::Idx;
-use rustc_middle::mir::*;
-use rustc_middle::ty::{Ty, TyCtxt};
-use rustc_target::abi::VariantIdx;
-
-use std::iter::TrustedLen;
-
-/// Expand `lhs = Rvalue::Aggregate(kind, operands)` into assignments to the fields.
-///
-/// Produces something like
-/// ```ignore (ilustrative)
-/// (lhs as Variant).field0 = arg0; // We only have a downcast if this is an enum
-/// (lhs as Variant).field1 = arg1;
-/// discriminant(lhs) = variant_index; // If lhs is an enum or generator.
-/// ```
-pub fn expand_aggregate<'tcx>(
- orig_lhs: Place<'tcx>,
- operands: impl Iterator<Item = (Operand<'tcx>, Ty<'tcx>)> + TrustedLen,
- kind: AggregateKind<'tcx>,
- source_info: SourceInfo,
- tcx: TyCtxt<'tcx>,
-) -> impl Iterator<Item = Statement<'tcx>> + TrustedLen {
- let mut lhs = orig_lhs;
- let mut set_discriminant = None;
- let active_field_index = match kind {
- AggregateKind::Adt(adt_did, variant_index, _, _, active_field_index) => {
- let adt_def = tcx.adt_def(adt_did);
- if adt_def.is_enum() {
- set_discriminant = Some(Statement {
- kind: StatementKind::SetDiscriminant {
- place: Box::new(orig_lhs),
- variant_index,
- },
- source_info,
- });
- lhs = tcx.mk_place_downcast(orig_lhs, adt_def, variant_index);
- }
- active_field_index
- }
- AggregateKind::Generator(..) => {
- // Right now we only support initializing generators to
- // variant 0 (Unresumed).
- let variant_index = VariantIdx::new(0);
- set_discriminant = Some(Statement {
- kind: StatementKind::SetDiscriminant { place: Box::new(orig_lhs), variant_index },
- source_info,
- });
-
- // Operands are upvars stored on the base place, so no
- // downcast is necessary.
-
- None
- }
- _ => None,
- };
-
- let operands = operands.enumerate().map(move |(i, (op, ty))| {
- let lhs_field = if let AggregateKind::Array(_) = kind {
- let offset = u64::try_from(i).unwrap();
- tcx.mk_place_elem(
- lhs,
- ProjectionElem::ConstantIndex { offset, min_length: offset + 1, from_end: false },
- )
- } else {
- let field = Field::new(active_field_index.unwrap_or(i));
- tcx.mk_place_field(lhs, field, ty)
- };
- Statement {
- source_info,
- kind: StatementKind::Assign(Box::new((lhs_field, Rvalue::Use(op)))),
- }
- });
- [Statement { source_info, kind: StatementKind::Deinit(Box::new(orig_lhs)) }]
- .into_iter()
- .chain(operands)
- .chain(set_discriminant)
-}
diff --git a/compiler/rustc_const_eval/src/util/call_kind.rs b/compiler/rustc_const_eval/src/util/call_kind.rs
index 38d9b0449..995363c0e 100644
--- a/compiler/rustc_const_eval/src/util/call_kind.rs
+++ b/compiler/rustc_const_eval/src/util/call_kind.rs
@@ -40,6 +40,7 @@ pub enum CallKind<'tcx> {
self_arg: Option<Ident>,
desugaring: Option<(CallDesugaringKind, Ty<'tcx>)>,
method_did: DefId,
+ method_substs: SubstsRef<'tcx>,
},
/// A call to `Fn(..)::call(..)`, desugared from `my_closure(a, b, c)`
FnCall { fn_trait_id: DefId, self_ty: Ty<'tcx> },
@@ -131,6 +132,6 @@ pub fn call_kind<'tcx>(
} else {
None
};
- CallKind::Normal { self_arg, desugaring, method_did }
+ CallKind::Normal { self_arg, desugaring, method_did, method_substs }
})
}
diff --git a/compiler/rustc_const_eval/src/util/might_permit_raw_init.rs b/compiler/rustc_const_eval/src/util/check_validity_requirement.rs
index 4ce107ea6..23fcd22c5 100644
--- a/compiler/rustc_const_eval/src/util/might_permit_raw_init.rs
+++ b/compiler/rustc_const_eval/src/util/check_validity_requirement.rs
@@ -1,7 +1,7 @@
-use rustc_middle::ty::layout::{LayoutCx, LayoutOf, TyAndLayout};
-use rustc_middle::ty::{ParamEnv, TyCtxt};
+use rustc_middle::ty::layout::{LayoutCx, LayoutError, LayoutOf, TyAndLayout, ValidityRequirement};
+use rustc_middle::ty::{ParamEnv, ParamEnvAnd, Ty, TyCtxt};
use rustc_session::Limit;
-use rustc_target::abi::{Abi, FieldsShape, InitKind, Scalar, Variants};
+use rustc_target::abi::{Abi, FieldsShape, Scalar, Variants};
use crate::const_eval::{CheckAlignment, CompileTimeInterpreter};
use crate::interpret::{InterpCx, MemoryKind, OpTy};
@@ -18,16 +18,23 @@ use crate::interpret::{InterpCx, MemoryKind, OpTy};
/// Rust UB as long as there is no risk of miscompilations. The `strict_init_checks` can be set to
/// do a full check against Rust UB instead (in which case we will also ignore the 0x01-filling and
/// to the full uninit check).
-pub fn might_permit_raw_init<'tcx>(
+pub fn check_validity_requirement<'tcx>(
tcx: TyCtxt<'tcx>,
- ty: TyAndLayout<'tcx>,
- kind: InitKind,
-) -> bool {
- if tcx.sess.opts.unstable_opts.strict_init_checks {
- might_permit_raw_init_strict(ty, tcx, kind)
+ kind: ValidityRequirement,
+ param_env_and_ty: ParamEnvAnd<'tcx, Ty<'tcx>>,
+) -> Result<bool, LayoutError<'tcx>> {
+ let layout = tcx.layout_of(param_env_and_ty)?;
+
+ // There is nothing strict or lax about inhabitedness.
+ if kind == ValidityRequirement::Inhabited {
+ return Ok(!layout.abi.is_uninhabited());
+ }
+
+ if kind == ValidityRequirement::Uninit || tcx.sess.opts.unstable_opts.strict_init_checks {
+ might_permit_raw_init_strict(layout, tcx, kind)
} else {
- let layout_cx = LayoutCx { tcx, param_env: ParamEnv::reveal_all() };
- might_permit_raw_init_lax(ty, &layout_cx, kind)
+ let layout_cx = LayoutCx { tcx, param_env: param_env_and_ty.param_env };
+ might_permit_raw_init_lax(layout, &layout_cx, kind)
}
}
@@ -36,8 +43,8 @@ pub fn might_permit_raw_init<'tcx>(
fn might_permit_raw_init_strict<'tcx>(
ty: TyAndLayout<'tcx>,
tcx: TyCtxt<'tcx>,
- kind: InitKind,
-) -> bool {
+ kind: ValidityRequirement,
+) -> Result<bool, LayoutError<'tcx>> {
let machine = CompileTimeInterpreter::new(
Limit::new(0),
/*can_access_statics:*/ false,
@@ -50,7 +57,7 @@ fn might_permit_raw_init_strict<'tcx>(
.allocate(ty, MemoryKind::Machine(crate::const_eval::MemoryKind::Heap))
.expect("OOM: failed to allocate for uninit check");
- if kind == InitKind::Zero {
+ if kind == ValidityRequirement::Zero {
cx.write_bytes_ptr(
allocated.ptr,
std::iter::repeat(0_u8).take(ty.layout.size().bytes_usize()),
@@ -64,7 +71,7 @@ fn might_permit_raw_init_strict<'tcx>(
// This does *not* actually check that references are dereferenceable, but since all types that
// require dereferenceability also require non-null, we don't actually get any false negatives
// due to this.
- cx.validate_operand(&ot).is_ok()
+ Ok(cx.validate_operand(&ot).is_ok())
}
/// Implements the 'lax' (default) version of the `might_permit_raw_init` checks; see that function for
@@ -72,15 +79,18 @@ fn might_permit_raw_init_strict<'tcx>(
fn might_permit_raw_init_lax<'tcx>(
this: TyAndLayout<'tcx>,
cx: &LayoutCx<'tcx, TyCtxt<'tcx>>,
- init_kind: InitKind,
-) -> bool {
+ init_kind: ValidityRequirement,
+) -> Result<bool, LayoutError<'tcx>> {
let scalar_allows_raw_init = move |s: Scalar| -> bool {
match init_kind {
- InitKind::Zero => {
+ ValidityRequirement::Inhabited => {
+ bug!("ValidityRequirement::Inhabited should have been handled above")
+ }
+ ValidityRequirement::Zero => {
// The range must contain 0.
s.valid_range(cx).contains(0)
}
- InitKind::UninitMitigated0x01Fill => {
+ ValidityRequirement::UninitMitigated0x01Fill => {
// The range must include an 0x01-filled buffer.
let mut val: u128 = 0x01;
for _ in 1..s.size(cx).bytes() {
@@ -89,6 +99,9 @@ fn might_permit_raw_init_lax<'tcx>(
}
s.valid_range(cx).contains(val)
}
+ ValidityRequirement::Uninit => {
+ bug!("ValidityRequirement::Uninit should have been handled above")
+ }
}
};
@@ -102,20 +115,20 @@ fn might_permit_raw_init_lax<'tcx>(
};
if !valid {
// This is definitely not okay.
- return false;
+ return Ok(false);
}
// Special magic check for references and boxes (i.e., special pointer types).
if let Some(pointee) = this.ty.builtin_deref(false) {
- let pointee = cx.layout_of(pointee.ty).expect("need to be able to compute layouts");
+ let pointee = cx.layout_of(pointee.ty)?;
// We need to ensure that the LLVM attributes `aligned` and `dereferenceable(size)` are satisfied.
if pointee.align.abi.bytes() > 1 {
// 0x01-filling is not aligned.
- return false;
+ return Ok(false);
}
if pointee.size.bytes() > 0 {
// A 'fake' integer pointer is not sufficiently dereferenceable.
- return false;
+ return Ok(false);
}
}
@@ -128,9 +141,9 @@ fn might_permit_raw_init_lax<'tcx>(
}
FieldsShape::Arbitrary { offsets, .. } => {
for idx in 0..offsets.len() {
- if !might_permit_raw_init_lax(this.field(cx, idx), cx, init_kind) {
+ if !might_permit_raw_init_lax(this.field(cx, idx), cx, init_kind)? {
// We found a field that is unhappy with this kind of initialization.
- return false;
+ return Ok(false);
}
}
}
@@ -147,5 +160,5 @@ fn might_permit_raw_init_lax<'tcx>(
}
}
- true
+ Ok(true)
}
diff --git a/compiler/rustc_const_eval/src/util/mod.rs b/compiler/rustc_const_eval/src/util/mod.rs
index 76ea5a24e..c0aabd77c 100644
--- a/compiler/rustc_const_eval/src/util/mod.rs
+++ b/compiler/rustc_const_eval/src/util/mod.rs
@@ -1,16 +1,14 @@
-pub mod aggregate;
mod alignment;
mod call_kind;
+mod check_validity_requirement;
pub mod collect_writes;
mod compare_types;
mod find_self_call;
-mod might_permit_raw_init;
mod type_name;
-pub use self::aggregate::expand_aggregate;
pub use self::alignment::is_disaligned;
pub use self::call_kind::{call_kind, CallDesugaringKind, CallKind};
+pub use self::check_validity_requirement::check_validity_requirement;
pub use self::compare_types::{is_equal_up_to_subtyping, is_subtype};
pub use self::find_self_call::find_self_call;
-pub use self::might_permit_raw_init::might_permit_raw_init;
pub use self::type_name::type_name;
diff --git a/compiler/rustc_const_eval/src/util/type_name.rs b/compiler/rustc_const_eval/src/util/type_name.rs
index c4122f664..4e80a2851 100644
--- a/compiler/rustc_const_eval/src/util/type_name.rs
+++ b/compiler/rustc_const_eval/src/util/type_name.rs
@@ -64,6 +64,7 @@ impl<'tcx> Printer<'tcx> for AbsolutePathPrinter<'tcx> {
ty::Foreign(def_id) => self.print_def_path(def_id, &[]),
ty::GeneratorWitness(_) => bug!("type_name: unexpected `GeneratorWitness`"),
+ ty::GeneratorWitnessMIR(..) => bug!("type_name: unexpected `GeneratorWitnessMIR`"),
}
}
diff --git a/compiler/rustc_data_structures/Cargo.toml b/compiler/rustc_data_structures/Cargo.toml
index 0366fb0a1..29cb2c0a3 100644
--- a/compiler/rustc_data_structures/Cargo.toml
+++ b/compiler/rustc_data_structures/Cargo.toml
@@ -9,7 +9,7 @@ edition = "2021"
arrayvec = { version = "0.7", default-features = false }
bitflags = "1.2.1"
cfg-if = "1.0"
-ena = "0.14"
+ena = "0.14.1"
indexmap = { version = "1.9.1" }
jobserver_crate = { version = "0.1.13", package = "jobserver" }
libc = "0.2"
@@ -29,8 +29,9 @@ smallvec = { version = "1.8.1", features = [
stable_deref_trait = "1.0.0"
stacker = "0.1.15"
tempfile = "3.2"
-thin-vec = "0.2.9"
+thin-vec = "0.2.12"
tracing = "0.1"
+elsa = "1.8"
[dependencies.parking_lot]
version = "0.11"
diff --git a/compiler/rustc_data_structures/src/functor.rs b/compiler/rustc_data_structures/src/functor.rs
index 84cb417dd..28fcf80b3 100644
--- a/compiler/rustc_data_structures/src/functor.rs
+++ b/compiler/rustc_data_structures/src/functor.rs
@@ -1,5 +1,5 @@
use rustc_index::vec::{Idx, IndexVec};
-use std::mem;
+use std::{mem, rc::Rc, sync::Arc};
pub trait IdFunctor: Sized {
type Inner;
@@ -65,3 +65,52 @@ impl<I: Idx, T> IdFunctor for IndexVec<I, T> {
self.raw.try_map_id(f).map(IndexVec::from_raw)
}
}
+
+macro_rules! rc {
+ ($($rc:ident),+) => {$(
+ impl<T: Clone> IdFunctor for $rc<T> {
+ type Inner = T;
+
+ #[inline]
+ fn try_map_id<F, E>(mut self, mut f: F) -> Result<Self, E>
+ where
+ F: FnMut(Self::Inner) -> Result<Self::Inner, E>,
+ {
+ // We merely want to replace the contained `T`, if at all possible,
+ // so that we don't needlessly allocate a new `$rc` or indeed clone
+ // the contained type.
+ unsafe {
+ // First step is to ensure that we have a unique reference to
+ // the contained type, which `$rc::make_mut` will accomplish (by
+ // allocating a new `$rc` and cloning the `T` only if required).
+ // This is done *before* casting to `$rc<ManuallyDrop<T>>` so that
+ // panicking during `make_mut` does not leak the `T`.
+ $rc::make_mut(&mut self);
+
+ // Casting to `$rc<ManuallyDrop<T>>` is safe because `ManuallyDrop`
+ // is `repr(transparent)`.
+ let ptr = $rc::into_raw(self).cast::<mem::ManuallyDrop<T>>();
+ let mut unique = $rc::from_raw(ptr);
+
+ // Call to `$rc::make_mut` above guarantees that `unique` is the
+ // sole reference to the contained value, so we can avoid doing
+ // a checked `get_mut` here.
+ let slot = $rc::get_mut_unchecked(&mut unique);
+
+ // Semantically move the contained type out from `unique`, fold
+ // it, then move the folded value back into `unique`. Should
+ // folding fail, `ManuallyDrop` ensures that the "moved-out"
+ // value is not re-dropped.
+ let owned = mem::ManuallyDrop::take(slot);
+ let folded = f(owned)?;
+ *slot = mem::ManuallyDrop::new(folded);
+
+ // Cast back to `$rc<T>`.
+ Ok($rc::from_raw($rc::into_raw(unique).cast()))
+ }
+ }
+ }
+ )+};
+}
+
+rc! { Rc, Arc }
diff --git a/compiler/rustc_data_structures/src/graph/dominators/mod.rs b/compiler/rustc_data_structures/src/graph/dominators/mod.rs
index 471457f61..0a21a4249 100644
--- a/compiler/rustc_data_structures/src/graph/dominators/mod.rs
+++ b/compiler/rustc_data_structures/src/graph/dominators/mod.rs
@@ -135,7 +135,47 @@ pub fn dominators<G: ControlFlowGraph>(graph: G) -> Dominators<G::Node> {
// This loop computes the semi[w] for w.
semi[w] = w;
for v in graph.predecessors(pre_order_to_real[w]) {
- // Reachable vertices may have unreachable predecessors, so ignore any of them
+ // TL;DR: Reachable vertices may have unreachable predecessors, so ignore any of them.
+ //
+ // Ignore blocks which are not connected to the entry block.
+ //
+ // The algorithm that was used to traverse the graph and build the
+ // `pre_order_to_real` and `real_to_pre_order` vectors does so by
+ // starting from the entry block and following the successors.
+ // Therefore, any blocks not reachable from the entry block will be
+ // set to `None` in the `pre_order_to_real` vector.
+ //
+ // For example, in this graph, A and B should be skipped:
+ //
+ // ┌─────┐
+ // │ │
+ // └──┬──┘
+ // │
+ // ┌──▼──┐ ┌─────┐
+ // │ │ │ A │
+ // └──┬──┘ └──┬──┘
+ // │ │
+ // ┌───────┴───────┐ │
+ // │ │ │
+ // ┌──▼──┐ ┌──▼──┐ ┌──▼──┐
+ // │ │ │ │ │ B │
+ // └──┬──┘ └──┬──┘ └──┬──┘
+ // │ └──────┬─────┘
+ // ┌──▼──┐ │
+ // │ │ │
+ // └──┬──┘ ┌──▼──┐
+ // │ │ │
+ // │ └─────┘
+ // ┌──▼──┐
+ // │ │
+ // └──┬──┘
+ // │
+ // ┌──▼──┐
+ // │ │
+ // └─────┘
+ //
+ // ...this may be the case if a MirPass modifies the CFG to remove
+ // or rearrange certain blocks/edges.
let Some(v) = real_to_pre_order[v] else {
continue
};
@@ -264,13 +304,18 @@ fn compress(
}
}
+/// Tracks the list of dominators for each node.
#[derive(Clone, Debug)]
pub struct Dominators<N: Idx> {
post_order_rank: IndexVec<N, usize>,
+ // Even though we track only the immediate dominator of each node, it's
+ // possible to get its full list of dominators by looking up the dominator
+ // of each dominator. (See the `impl Iterator for Iter` definition).
immediate_dominators: IndexVec<N, Option<N>>,
}
impl<Node: Idx> Dominators<Node> {
+ /// Whether the given Node has an immediate dominator.
pub fn is_reachable(&self, node: Node) -> bool {
self.immediate_dominators[node].is_some()
}
@@ -280,12 +325,14 @@ impl<Node: Idx> Dominators<Node> {
self.immediate_dominators[node].unwrap()
}
+ /// Provides an iterator over each dominator up the CFG, for the given Node.
+ /// See the `impl Iterator for Iter` definition to understand how this works.
pub fn dominators(&self, node: Node) -> Iter<'_, Node> {
assert!(self.is_reachable(node), "node {node:?} is not reachable");
Iter { dominators: self, node: Some(node) }
}
- pub fn is_dominated_by(&self, node: Node, dom: Node) -> bool {
+ pub fn dominates(&self, dom: Node, node: Node) -> bool {
// FIXME -- could be optimized by using post-order-rank
self.dominators(node).any(|n| n == dom)
}
diff --git a/compiler/rustc_data_structures/src/graph/scc/mod.rs b/compiler/rustc_data_structures/src/graph/scc/mod.rs
index c8e66eb67..c4b11951a 100644
--- a/compiler/rustc_data_structures/src/graph/scc/mod.rs
+++ b/compiler/rustc_data_structures/src/graph/scc/mod.rs
@@ -27,7 +27,7 @@ pub struct Sccs<N: Idx, S: Idx> {
scc_data: SccData<S>,
}
-struct SccData<S: Idx> {
+pub struct SccData<S: Idx> {
/// For each SCC, the range of `all_successors` where its
/// successors can be found.
ranges: IndexVec<S, Range<usize>>,
@@ -43,6 +43,14 @@ impl<N: Idx, S: Idx + Ord> Sccs<N, S> {
SccsConstruction::construct(graph)
}
+ pub fn scc_indices(&self) -> &IndexVec<N, S> {
+ &self.scc_indices
+ }
+
+ pub fn scc_data(&self) -> &SccData<S> {
+ &self.scc_data
+ }
+
/// Returns the number of SCCs in the graph.
pub fn num_sccs(&self) -> usize {
self.scc_data.len()
@@ -115,6 +123,14 @@ impl<S: Idx> SccData<S> {
self.ranges.len()
}
+ pub fn ranges(&self) -> &IndexVec<S, Range<usize>> {
+ &self.ranges
+ }
+
+ pub fn all_successors(&self) -> &Vec<S> {
+ &self.all_successors
+ }
+
/// Returns the successors of the given SCC.
fn successors(&self, scc: S) -> &[S] {
// Annoyingly, `range` does not implement `Copy`, so we have
diff --git a/compiler/rustc_data_structures/src/lib.rs b/compiler/rustc_data_structures/src/lib.rs
index 954e84c30..a94e52fdf 100644
--- a/compiler/rustc_data_structures/src/lib.rs
+++ b/compiler/rustc_data_structures/src/lib.rs
@@ -11,6 +11,7 @@
#![feature(associated_type_bounds)]
#![feature(auto_traits)]
#![feature(cell_leak)]
+#![feature(core_intrinsics)]
#![feature(extend_one)]
#![feature(hash_raw_entry)]
#![feature(hasher_prefixfree_extras)]
@@ -25,6 +26,7 @@
#![feature(test)]
#![feature(thread_id_value)]
#![feature(vec_into_raw_parts)]
+#![feature(get_mut_unchecked)]
#![allow(rustc::default_hash_types)]
#![allow(rustc::potential_query_instability)]
#![deny(rustc::untranslatable_diagnostic)]
diff --git a/compiler/rustc_data_structures/src/obligation_forest/mod.rs b/compiler/rustc_data_structures/src/obligation_forest/mod.rs
index 10e673cd9..91abdaada 100644
--- a/compiler/rustc_data_structures/src/obligation_forest/mod.rs
+++ b/compiler/rustc_data_structures/src/obligation_forest/mod.rs
@@ -95,10 +95,7 @@ pub trait ForestObligation: Clone + Debug {
pub trait ObligationProcessor {
type Obligation: ForestObligation;
type Error: Debug;
- type OUT: OutcomeTrait<
- Obligation = Self::Obligation,
- Error = Error<Self::Obligation, Self::Error>,
- >;
+ type OUT: OutcomeTrait<Obligation = Self::Obligation, Error = Error<Self::Obligation, Self::Error>>;
fn needs_process_obligation(&self, obligation: &Self::Obligation) -> bool;
@@ -139,8 +136,7 @@ pub enum ProcessResult<O, E> {
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
struct ObligationTreeId(usize);
-type ObligationTreeIdGenerator =
- std::iter::Map<std::ops::RangeFrom<usize>, fn(usize) -> ObligationTreeId>;
+type ObligationTreeIdGenerator = impl Iterator<Item = ObligationTreeId>;
pub struct ObligationForest<O: ForestObligation> {
/// The list of obligations. In between calls to [Self::process_obligations],
@@ -430,6 +426,7 @@ impl<O: ForestObligation> ObligationForest<O> {
// nodes. Therefore we use a `while` loop.
let mut index = 0;
while let Some(node) = self.nodes.get_mut(index) {
+ // This test is extremely hot.
if node.state.get() != NodeState::Pending
|| !processor.needs_process_obligation(&node.obligation)
{
@@ -443,6 +440,7 @@ impl<O: ForestObligation> ObligationForest<O> {
// out of sync with `nodes`. It's not very common, but it does
// happen, and code in `compress` has to allow for it.
+ // This code is much less hot.
match processor.process_obligation(&mut node.obligation) {
ProcessResult::Unchanged => {
// No change in state.
diff --git a/compiler/rustc_data_structures/src/profiling.rs b/compiler/rustc_data_structures/src/profiling.rs
index 393f17390..443316836 100644
--- a/compiler/rustc_data_structures/src/profiling.rs
+++ b/compiler/rustc_data_structures/src/profiling.rs
@@ -88,6 +88,7 @@ use std::borrow::Borrow;
use std::collections::hash_map::Entry;
use std::error::Error;
use std::fs;
+use std::intrinsics::unlikely;
use std::path::Path;
use std::process;
use std::sync::Arc;
@@ -206,8 +207,7 @@ impl SelfProfilerRef {
/// a measureme event, "verbose" generic activities also print a timing entry to
/// stderr if the compiler is invoked with -Ztime-passes.
pub fn verbose_generic_activity(&self, event_label: &'static str) -> VerboseTimingGuard<'_> {
- let message =
- if self.print_verbose_generic_activities { Some(event_label.to_owned()) } else { None };
+ let message = self.print_verbose_generic_activities.then(|| event_label.to_owned());
VerboseTimingGuard::start(message, self.generic_activity(event_label))
}
@@ -221,11 +221,9 @@ impl SelfProfilerRef {
where
A: Borrow<str> + Into<String>,
{
- let message = if self.print_verbose_generic_activities {
- Some(format!("{}({})", event_label, event_arg.borrow()))
- } else {
- None
- };
+ let message = self
+ .print_verbose_generic_activities
+ .then(|| format!("{}({})", event_label, event_arg.borrow()));
VerboseTimingGuard::start(message, self.generic_activity_with_arg(event_label, event_arg))
}
@@ -395,11 +393,18 @@ impl SelfProfilerRef {
/// Record a query in-memory cache hit.
#[inline(always)]
pub fn query_cache_hit(&self, query_invocation_id: QueryInvocationId) {
- self.instant_query_event(
- |profiler| profiler.query_cache_hit_event_kind,
- query_invocation_id,
- EventFilter::QUERY_CACHE_HITS,
- );
+ #[inline(never)]
+ #[cold]
+ fn cold_call(profiler_ref: &SelfProfilerRef, query_invocation_id: QueryInvocationId) {
+ profiler_ref.instant_query_event(
+ |profiler| profiler.query_cache_hit_event_kind,
+ query_invocation_id,
+ );
+ }
+
+ if unlikely(self.event_filter_mask.contains(EventFilter::QUERY_CACHE_HITS)) {
+ cold_call(self, query_invocation_id);
+ }
}
/// Start profiling a query being blocked on a concurrent execution.
@@ -444,20 +449,15 @@ impl SelfProfilerRef {
&self,
event_kind: fn(&SelfProfiler) -> StringId,
query_invocation_id: QueryInvocationId,
- event_filter: EventFilter,
) {
- drop(self.exec(event_filter, |profiler| {
- let event_id = StringId::new_virtual(query_invocation_id.0);
- let thread_id = get_thread_id();
-
- profiler.profiler.record_instant_event(
- event_kind(profiler),
- EventId::from_virtual(event_id),
- thread_id,
- );
-
- TimingGuard::none()
- }));
+ let event_id = StringId::new_virtual(query_invocation_id.0);
+ let thread_id = get_thread_id();
+ let profiler = self.profiler.as_ref().unwrap();
+ profiler.profiler.record_instant_event(
+ event_kind(profiler),
+ EventId::from_virtual(event_id),
+ thread_id,
+ );
}
pub fn with_profiler(&self, f: impl FnOnce(&SelfProfiler)) {
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 814e7c7fb..7d23ff519 100644
--- a/compiler/rustc_data_structures/src/sorted_map/index_map.rs
+++ b/compiler/rustc_data_structures/src/sorted_map/index_map.rs
@@ -100,6 +100,11 @@ impl<I: Idx, K: Ord, V> SortedIndexMultiMap<I, K, V> {
(k == &key).then_some((i, v))
})
}
+
+ #[inline]
+ pub fn contains_key(&self, key: K) -> bool {
+ self.get_by_key(key).next().is_some()
+ }
}
impl<I: Idx, K: Eq, V: Eq> Eq for SortedIndexMultiMap<I, K, V> {}
diff --git a/compiler/rustc_data_structures/src/sorted_map/tests.rs b/compiler/rustc_data_structures/src/sorted_map/tests.rs
index 3cc250862..def7a7112 100644
--- a/compiler/rustc_data_structures/src/sorted_map/tests.rs
+++ b/compiler/rustc_data_structures/src/sorted_map/tests.rs
@@ -17,6 +17,10 @@ fn test_sorted_index_multi_map() {
assert_eq!(set.get_by_key(3).copied().collect::<Vec<_>>(), vec![0]);
assert!(set.get_by_key(4).next().is_none());
+ // `contains_key` works
+ assert!(set.contains_key(3));
+ assert!(!set.contains_key(4));
+
// `get_by_key` returns items in insertion order.
let twos: Vec<_> = set.get_by_key_enumerated(2).collect();
let idxs: Vec<usize> = twos.iter().map(|(i, _)| *i).collect();
diff --git a/compiler/rustc_data_structures/src/stable_hasher.rs b/compiler/rustc_data_structures/src/stable_hasher.rs
index ae4836645..e0d77cdae 100644
--- a/compiler/rustc_data_structures/src/stable_hasher.rs
+++ b/compiler/rustc_data_structures/src/stable_hasher.rs
@@ -486,6 +486,14 @@ impl<HCX> ToStableHashKey<HCX> for String {
}
}
+impl<HCX, T1: ToStableHashKey<HCX>, T2: ToStableHashKey<HCX>> ToStableHashKey<HCX> for (T1, T2) {
+ type KeyType = (T1::KeyType, T2::KeyType);
+ #[inline]
+ fn to_stable_hash_key(&self, hcx: &HCX) -> Self::KeyType {
+ (self.0.to_stable_hash_key(hcx), self.1.to_stable_hash_key(hcx))
+ }
+}
+
impl<CTX> HashStable<CTX> for bool {
#[inline]
fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) {
diff --git a/compiler/rustc_data_structures/src/stable_hasher/tests.rs b/compiler/rustc_data_structures/src/stable_hasher/tests.rs
index b0d66c32a..724be5888 100644
--- a/compiler/rustc_data_structures/src/stable_hasher/tests.rs
+++ b/compiler/rustc_data_structures/src/stable_hasher/tests.rs
@@ -150,7 +150,7 @@ fn test_isize_compression() {
let hash_b = hash(&(b as isize, a as isize));
assert_ne!(
hash_a, hash_b,
- "The hash stayed the same when permuting values `{a}` and `{b}!",
+ "The hash stayed the same when permuting values `{a}` and `{b}`!",
);
}
diff --git a/compiler/rustc_data_structures/src/sync.rs b/compiler/rustc_data_structures/src/sync.rs
index ed5341c40..31323c21d 100644
--- a/compiler/rustc_data_structures/src/sync.rs
+++ b/compiler/rustc_data_structures/src/sync.rs
@@ -26,13 +26,17 @@ use std::panic::{catch_unwind, resume_unwind, AssertUnwindSafe};
pub use std::sync::atomic::Ordering;
pub use std::sync::atomic::Ordering::SeqCst;
+pub use vec::AppendOnlyVec;
+
+mod vec;
+
cfg_if! {
if #[cfg(not(parallel_compiler))] {
pub auto trait Send {}
pub auto trait Sync {}
- impl<T: ?Sized> Send for T {}
- impl<T: ?Sized> Sync for T {}
+ impl<T> Send for T {}
+ impl<T> Sync for T {}
#[macro_export]
macro_rules! rustc_erase_owner {
diff --git a/compiler/rustc_data_structures/src/sync/vec.rs b/compiler/rustc_data_structures/src/sync/vec.rs
new file mode 100644
index 000000000..cbea4f059
--- /dev/null
+++ b/compiler/rustc_data_structures/src/sync/vec.rs
@@ -0,0 +1,41 @@
+use std::marker::PhantomData;
+
+use rustc_index::vec::Idx;
+
+pub struct AppendOnlyVec<I: Idx, T: Copy> {
+ #[cfg(not(parallel_compiler))]
+ vec: elsa::vec::FrozenVec<T>,
+ #[cfg(parallel_compiler)]
+ vec: elsa::sync::LockFreeFrozenVec<T>,
+ _marker: PhantomData<fn(&I)>,
+}
+
+impl<I: Idx, T: Copy> AppendOnlyVec<I, T> {
+ pub fn new() -> Self {
+ Self {
+ #[cfg(not(parallel_compiler))]
+ vec: elsa::vec::FrozenVec::new(),
+ #[cfg(parallel_compiler)]
+ vec: elsa::sync::LockFreeFrozenVec::new(),
+ _marker: PhantomData,
+ }
+ }
+
+ pub fn push(&self, val: T) -> I {
+ #[cfg(not(parallel_compiler))]
+ let i = self.vec.len();
+ #[cfg(not(parallel_compiler))]
+ self.vec.push(val);
+ #[cfg(parallel_compiler)]
+ let i = self.vec.push(val);
+ I::new(i)
+ }
+
+ pub fn get(&self, i: I) -> Option<T> {
+ let i = i.index();
+ #[cfg(not(parallel_compiler))]
+ return self.vec.get_copy(i);
+ #[cfg(parallel_compiler)]
+ return self.vec.get(i);
+ }
+}
diff --git a/compiler/rustc_driver/Cargo.toml b/compiler/rustc_driver/Cargo.toml
index 59e937777..d7c295418 100644
--- a/compiler/rustc_driver/Cargo.toml
+++ b/compiler/rustc_driver/Cargo.toml
@@ -7,39 +7,4 @@ edition = "2021"
crate-type = ["dylib"]
[dependencies]
-tracing = { version = "0.1.35" }
-serde_json = "1.0.59"
-rustc_log = { path = "../rustc_log" }
-rustc_middle = { path = "../rustc_middle" }
-rustc_ast_pretty = { path = "../rustc_ast_pretty" }
-rustc_target = { path = "../rustc_target" }
-rustc_lint = { path = "../rustc_lint" }
-rustc_data_structures = { path = "../rustc_data_structures" }
-rustc_errors = { path = "../rustc_errors" }
-rustc_feature = { path = "../rustc_feature" }
-rustc_hir = { path = "../rustc_hir" }
-rustc_hir_pretty = { path = "../rustc_hir_pretty" }
-rustc_macros = { path = "../rustc_macros" }
-rustc_metadata = { path = "../rustc_metadata" }
-rustc_parse = { path = "../rustc_parse" }
-rustc_plugin_impl = { path = "../rustc_plugin_impl" }
-rustc_save_analysis = { path = "../rustc_save_analysis" }
-rustc_codegen_ssa = { path = "../rustc_codegen_ssa" }
-rustc_session = { path = "../rustc_session" }
-rustc_error_codes = { path = "../rustc_error_codes" }
-rustc_interface = { path = "../rustc_interface" }
-rustc_ast = { path = "../rustc_ast" }
-rustc_span = { path = "../rustc_span" }
-rustc_hir_analysis = { path = "../rustc_hir_analysis" }
-
-[target.'cfg(unix)'.dependencies]
-libc = "0.2"
-
-[target.'cfg(windows)'.dependencies]
-winapi = { version = "0.3", features = ["consoleapi", "debugapi", "processenv"] }
-
-[features]
-llvm = ['rustc_interface/llvm']
-max_level_info = ['rustc_log/max_level_info']
-rustc_use_parallel_compiler = ['rustc_data_structures/rustc_use_parallel_compiler', 'rustc_interface/rustc_use_parallel_compiler',
- 'rustc_middle/rustc_use_parallel_compiler']
+rustc_driver_impl = { path = "../rustc_driver_impl" }
diff --git a/compiler/rustc_driver/src/lib.rs b/compiler/rustc_driver/src/lib.rs
index f50ad0137..4eabba575 100644
--- a/compiler/rustc_driver/src/lib.rs
+++ b/compiler/rustc_driver/src/lib.rs
@@ -1,1358 +1,4 @@
-//! The Rust compiler.
-//!
-//! # Note
-//!
-//! This API is completely unstable and subject to change.
+// This crate is intentionally empty and a rexport of `rustc_driver_impl` to allow the code in
+// `rustc_driver_impl` to be compiled in parallel with other crates.
-#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
-#![feature(is_terminal)]
-#![feature(once_cell)]
-#![feature(decl_macro)]
-#![recursion_limit = "256"]
-#![allow(rustc::potential_query_instability)]
-#![deny(rustc::untranslatable_diagnostic)]
-#![deny(rustc::diagnostic_outside_of_impl)]
-
-#[macro_use]
-extern crate tracing;
-
-pub extern crate rustc_plugin_impl as plugin;
-
-use rustc_ast as ast;
-use rustc_codegen_ssa::{traits::CodegenBackend, CodegenErrors, CodegenResults};
-use rustc_data_structures::profiling::{get_resident_set_size, print_time_passes_entry};
-use rustc_data_structures::sync::SeqCst;
-use rustc_errors::registry::{InvalidErrorCode, Registry};
-use rustc_errors::{ErrorGuaranteed, PResult};
-use rustc_feature::find_gated_cfg;
-use rustc_hir::def_id::LOCAL_CRATE;
-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_save_analysis as save;
-use rustc_save_analysis::DumpHandler;
-use rustc_session::config::{nightly_options, CG_OPTIONS, Z_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, Session};
-use rustc_session::{early_error, early_error_no_abort, early_warn};
-use rustc_span::source_map::{FileLoader, FileName};
-use rustc_span::symbol::sym;
-use rustc_target::json::ToJson;
-
-use std::borrow::Cow;
-use std::cmp::max;
-use std::env;
-use std::ffi::OsString;
-use std::fs;
-use std::io::{self, IsTerminal, Read, Write};
-use std::panic::{self, catch_unwind};
-use std::path::PathBuf;
-use std::process::{self, Command, Stdio};
-use std::str;
-use std::sync::LazyLock;
-use std::time::Instant;
-
-pub mod args;
-pub mod pretty;
-mod session_diagnostics;
-
-use crate::session_diagnostics::{
- RLinkEmptyVersionNumber, RLinkEncodingVersionMismatch, RLinkRustcVersionMismatch,
- RLinkWrongFileType, RlinkNotAFile, RlinkUnableToRead,
-};
-
-/// Exit status code used for successful compilation and help output.
-pub const EXIT_SUCCESS: i32 = 0;
-
-/// Exit status code used for compilation failures and invalid flags.
-pub const EXIT_FAILURE: i32 = 1;
-
-const BUG_REPORT_URL: &str = "https://github.com/rust-lang/rust/issues/new\
- ?labels=C-bug%2C+I-ICE%2C+T-compiler&template=ice.md";
-
-const ICE_REPORT_COMPILER_FLAGS: &[&str] = &["-Z", "-C", "--crate-type"];
-
-const ICE_REPORT_COMPILER_FLAGS_EXCLUDE: &[&str] = &["metadata", "extra-filename"];
-
-const ICE_REPORT_COMPILER_FLAGS_STRIP_VALUE: &[&str] = &["incremental"];
-
-pub fn abort_on_err<T>(result: Result<T, ErrorGuaranteed>, sess: &Session) -> T {
- match result {
- Err(..) => {
- sess.abort_if_errors();
- panic!("error reported but abort_if_errors didn't abort???");
- }
- Ok(x) => x,
- }
-}
-
-pub trait Callbacks {
- /// Called before creating the compiler instance
- fn config(&mut self, _config: &mut interface::Config) {}
- /// Called after parsing. Return value instructs the compiler whether to
- /// continue the compilation afterwards (defaults to `Compilation::Continue`)
- fn after_parsing<'tcx>(
- &mut self,
- _compiler: &interface::Compiler,
- _queries: &'tcx Queries<'tcx>,
- ) -> Compilation {
- Compilation::Continue
- }
- /// Called after expansion. Return value instructs the compiler whether to
- /// continue the compilation afterwards (defaults to `Compilation::Continue`)
- fn after_expansion<'tcx>(
- &mut self,
- _compiler: &interface::Compiler,
- _queries: &'tcx Queries<'tcx>,
- ) -> Compilation {
- Compilation::Continue
- }
- /// Called after analysis. Return value instructs the compiler whether to
- /// continue the compilation afterwards (defaults to `Compilation::Continue`)
- fn after_analysis<'tcx>(
- &mut self,
- _compiler: &interface::Compiler,
- _queries: &'tcx Queries<'tcx>,
- ) -> Compilation {
- Compilation::Continue
- }
-}
-
-#[derive(Default)]
-pub struct TimePassesCallbacks {
- time_passes: bool,
-}
-
-impl Callbacks for TimePassesCallbacks {
- // JUSTIFICATION: the session doesn't exist at this point.
- #[allow(rustc::bad_opt_access)]
- fn config(&mut self, config: &mut interface::Config) {
- // If a --print=... option has been given, we don't print the "total"
- // time because it will mess up the --print output. See #64339.
- //
- self.time_passes = config.opts.prints.is_empty() && config.opts.unstable_opts.time_passes;
- config.opts.trimmed_def_paths = TrimmedDefPaths::GoodPath;
- }
-}
-
-pub fn diagnostics_registry() -> Registry {
- Registry::new(rustc_error_codes::DIAGNOSTICS)
-}
-
-/// This is the primary entry point for rustc.
-pub struct RunCompiler<'a, 'b> {
- at_args: &'a [String],
- callbacks: &'b mut (dyn Callbacks + Send),
- file_loader: Option<Box<dyn FileLoader + Send + Sync>>,
- make_codegen_backend:
- Option<Box<dyn FnOnce(&config::Options) -> Box<dyn CodegenBackend> + Send>>,
-}
-
-impl<'a, 'b> RunCompiler<'a, 'b> {
- pub fn new(at_args: &'a [String], callbacks: &'b mut (dyn Callbacks + Send)) -> Self {
- Self { at_args, callbacks, file_loader: None, make_codegen_backend: None }
- }
-
- /// Set a custom codegen backend.
- ///
- /// Has no uses within this repository, but is used by bjorn3 for "the
- /// hotswapping branch of cg_clif" for "setting the codegen backend from a
- /// custom driver where the custom codegen backend has arbitrary data."
- /// (See #102759.)
- pub fn set_make_codegen_backend(
- &mut self,
- make_codegen_backend: Option<
- Box<dyn FnOnce(&config::Options) -> Box<dyn CodegenBackend> + Send>,
- >,
- ) -> &mut Self {
- self.make_codegen_backend = make_codegen_backend;
- self
- }
-
- /// Load files from sources other than the file system.
- ///
- /// Has no uses within this repository, but may be used in the future by
- /// bjorn3 for "hooking rust-analyzer's VFS into rustc at some point for
- /// running rustc without having to save". (See #102759.)
- pub fn set_file_loader(
- &mut self,
- file_loader: Option<Box<dyn FileLoader + Send + Sync>>,
- ) -> &mut Self {
- self.file_loader = file_loader;
- self
- }
-
- /// Parse args and run the compiler.
- pub fn run(self) -> interface::Result<()> {
- run_compiler(self.at_args, self.callbacks, self.file_loader, self.make_codegen_backend)
- }
-}
-
-fn run_compiler(
- at_args: &[String],
- callbacks: &mut (dyn Callbacks + Send),
- file_loader: Option<Box<dyn FileLoader + Send + Sync>>,
- make_codegen_backend: Option<
- Box<dyn FnOnce(&config::Options) -> Box<dyn CodegenBackend> + Send>,
- >,
-) -> interface::Result<()> {
- let args = args::arg_expand_all(at_args);
-
- let Some(matches) = handle_options(&args) else { return Ok(()) };
-
- let sopts = config::build_session_options(&matches);
-
- if let Some(ref code) = matches.opt_str("explain") {
- handle_explain(diagnostics_registry(), code, sopts.error_format);
- return Ok(());
- }
-
- let cfg = interface::parse_cfgspecs(matches.opt_strs("cfg"));
- let check_cfg = interface::parse_check_cfg(matches.opt_strs("check-cfg"));
- let (odir, ofile) = make_output(&matches);
- let mut config = interface::Config {
- opts: sopts,
- crate_cfg: cfg,
- crate_check_cfg: check_cfg,
- input: Input::File(PathBuf::new()),
- output_file: ofile,
- output_dir: odir,
- file_loader,
- lint_caps: Default::default(),
- parse_sess_created: None,
- register_lints: None,
- override_queries: None,
- make_codegen_backend,
- registry: diagnostics_registry(),
- };
-
- if !tracing::dispatcher::has_been_set() {
- init_rustc_env_logger_with_backtrace_option(&config.opts.unstable_opts.log_backtrace);
- }
-
- match make_input(config.opts.error_format, &matches.free) {
- Err(reported) => return Err(reported),
- Ok(Some(input)) => {
- config.input = input;
-
- callbacks.config(&mut config);
- }
- Ok(None) => match matches.free.len() {
- 0 => {
- callbacks.config(&mut config);
- interface::run_compiler(config, |compiler| {
- let sopts = &compiler.session().opts;
- if sopts.describe_lints {
- let mut lint_store =
- rustc_lint::new_lint_store(compiler.session().enable_internal_lints());
- let registered_lints =
- if let Some(register_lints) = compiler.register_lints() {
- register_lints(compiler.session(), &mut lint_store);
- true
- } else {
- false
- };
- describe_lints(compiler.session(), &lint_store, registered_lints);
- return;
- }
- let should_stop =
- print_crate_info(&***compiler.codegen_backend(), compiler.session(), false);
-
- if should_stop == Compilation::Stop {
- return;
- }
- early_error(sopts.error_format, "no input filename given")
- });
- return Ok(());
- }
- 1 => panic!("make_input should have provided valid inputs"),
- _ => early_error(
- config.opts.error_format,
- &format!(
- "multiple input filenames provided (first two filenames are `{}` and `{}`)",
- matches.free[0], matches.free[1],
- ),
- ),
- },
- };
-
- interface::run_compiler(config, |compiler| {
- let sess = compiler.session();
- let should_stop = print_crate_info(&***compiler.codegen_backend(), sess, true)
- .and_then(|| list_metadata(sess, &*compiler.codegen_backend().metadata_loader()))
- .and_then(|| try_process_rlink(sess, compiler));
-
- if should_stop == Compilation::Stop {
- return sess.compile_status();
- }
-
- let linker = compiler.enter(|queries| {
- let early_exit = || sess.compile_status().map(|_| None);
- queries.parse()?;
-
- if let Some(ppm) = &sess.opts.pretty {
- if ppm.needs_ast_map() {
- let expanded_crate = queries.expansion()?.borrow().0.clone();
- queries.global_ctxt()?.enter(|tcx| {
- pretty::print_after_hir_lowering(tcx, &*expanded_crate, *ppm);
- Ok(())
- })?;
- } else {
- let krate = queries.parse()?.steal();
- pretty::print_after_parsing(sess, &krate, *ppm);
- }
- trace!("finished pretty-printing");
- return early_exit();
- }
-
- if callbacks.after_parsing(compiler, queries) == Compilation::Stop {
- return early_exit();
- }
-
- if sess.opts.unstable_opts.parse_only || sess.opts.unstable_opts.show_span.is_some() {
- return early_exit();
- }
-
- {
- let plugins = queries.register_plugins()?;
- let (_, lint_store) = &*plugins.borrow();
-
- // Lint plugins are registered; now we can process command line flags.
- if sess.opts.describe_lints {
- describe_lints(sess, lint_store, true);
- return early_exit();
- }
- }
-
- queries.global_ctxt()?;
- if callbacks.after_expansion(compiler, queries) == Compilation::Stop {
- return early_exit();
- }
-
- if sess.opts.output_types.contains_key(&OutputType::DepInfo)
- && sess.opts.output_types.len() == 1
- {
- return early_exit();
- }
-
- if sess.opts.unstable_opts.no_analysis {
- return early_exit();
- }
-
- queries.global_ctxt()?.enter(|tcx| {
- let result = tcx.analysis(());
- if sess.opts.unstable_opts.save_analysis {
- let crate_name = tcx.crate_name(LOCAL_CRATE);
- sess.time("save_analysis", || {
- save::process_crate(
- tcx,
- crate_name,
- &sess.io.input,
- None,
- DumpHandler::new(sess.io.output_dir.as_deref(), crate_name),
- )
- });
- }
- result
- })?;
-
- if callbacks.after_analysis(compiler, queries) == Compilation::Stop {
- return early_exit();
- }
-
- queries.ongoing_codegen()?;
-
- if sess.opts.unstable_opts.print_type_sizes {
- sess.code_stats.print_type_sizes();
- }
-
- let linker = queries.linker()?;
- Ok(Some(linker))
- })?;
-
- if let Some(linker) = linker {
- let _timer = sess.timer("link");
- linker.link()?
- }
-
- if sess.opts.unstable_opts.perf_stats {
- sess.print_perf_stats();
- }
-
- if sess.opts.unstable_opts.print_fuel.is_some() {
- eprintln!(
- "Fuel used by {}: {}",
- sess.opts.unstable_opts.print_fuel.as_ref().unwrap(),
- sess.print_fuel.load(SeqCst)
- );
- }
-
- Ok(())
- })
-}
-
-// Extract output directory and file from matches.
-fn make_output(matches: &getopts::Matches) -> (Option<PathBuf>, Option<PathBuf>) {
- let odir = matches.opt_str("out-dir").map(|o| PathBuf::from(&o));
- let ofile = matches.opt_str("o").map(|o| PathBuf::from(&o));
- (odir, ofile)
-}
-
-// Extract input (string or file and optional path) from matches.
-fn make_input(
- error_format: ErrorOutputType,
- free_matches: &[String],
-) -> Result<Option<Input>, ErrorGuaranteed> {
- if free_matches.len() == 1 {
- let ifile = &free_matches[0];
- if ifile == "-" {
- let mut src = String::new();
- if io::stdin().read_to_string(&mut src).is_err() {
- // Immediately stop compilation if there was an issue reading
- // the input (for example if the input stream is not UTF-8).
- let reported = early_error_no_abort(
- error_format,
- "couldn't read from stdin, as it did not contain valid UTF-8",
- );
- return Err(reported);
- }
- if let Ok(path) = env::var("UNSTABLE_RUSTDOC_TEST_PATH") {
- let line = env::var("UNSTABLE_RUSTDOC_TEST_LINE").expect(
- "when UNSTABLE_RUSTDOC_TEST_PATH is set \
- UNSTABLE_RUSTDOC_TEST_LINE also needs to be set",
- );
- let line = isize::from_str_radix(&line, 10)
- .expect("UNSTABLE_RUSTDOC_TEST_LINE needs to be an number");
- let file_name = FileName::doc_test_source_code(PathBuf::from(path), line);
- Ok(Some(Input::Str { name: file_name, input: src }))
- } else {
- Ok(Some(Input::Str { name: FileName::anon_source_code(&src), input: src }))
- }
- } else {
- Ok(Some(Input::File(PathBuf::from(ifile))))
- }
- } else {
- Ok(None)
- }
-}
-
-/// Whether to stop or continue compilation.
-#[derive(Copy, Clone, Debug, Eq, PartialEq)]
-pub enum Compilation {
- Stop,
- Continue,
-}
-
-impl Compilation {
- pub fn and_then<F: FnOnce() -> Compilation>(self, next: F) -> Compilation {
- match self {
- Compilation::Stop => Compilation::Stop,
- Compilation::Continue => next(),
- }
- }
-}
-
-fn handle_explain(registry: Registry, code: &str, output: ErrorOutputType) {
- let upper_cased_code = code.to_ascii_uppercase();
- let normalised =
- if upper_cased_code.starts_with('E') { upper_cased_code } else { format!("E{code:0>4}") };
- match registry.try_find_description(&normalised) {
- Ok(Some(description)) => {
- let mut is_in_code_block = false;
- let mut text = String::new();
- // Slice off the leading newline and print.
- for line in description.lines() {
- let indent_level =
- line.find(|c: char| !c.is_whitespace()).unwrap_or_else(|| line.len());
- let dedented_line = &line[indent_level..];
- if dedented_line.starts_with("```") {
- is_in_code_block = !is_in_code_block;
- text.push_str(&line[..(indent_level + 3)]);
- } else if is_in_code_block && dedented_line.starts_with("# ") {
- continue;
- } else {
- text.push_str(line);
- }
- text.push('\n');
- }
- if io::stdout().is_terminal() {
- show_content_with_pager(&text);
- } else {
- print!("{text}");
- }
- }
- Ok(None) => {
- early_error(output, &format!("no extended information for {code}"));
- }
- Err(InvalidErrorCode) => {
- early_error(output, &format!("{code} is not a valid error code"));
- }
- }
-}
-
-fn show_content_with_pager(content: &str) {
- let pager_name = env::var_os("PAGER").unwrap_or_else(|| {
- if cfg!(windows) { OsString::from("more.com") } else { OsString::from("less") }
- });
-
- let mut fallback_to_println = false;
-
- match Command::new(pager_name).stdin(Stdio::piped()).spawn() {
- Ok(mut pager) => {
- if let Some(pipe) = pager.stdin.as_mut() {
- if pipe.write_all(content.as_bytes()).is_err() {
- fallback_to_println = true;
- }
- }
-
- if pager.wait().is_err() {
- fallback_to_println = true;
- }
- }
- Err(_) => {
- fallback_to_println = true;
- }
- }
-
- // If pager fails for whatever reason, we should still print the content
- // to standard output
- if fallback_to_println {
- print!("{content}");
- }
-}
-
-pub fn try_process_rlink(sess: &Session, compiler: &interface::Compiler) -> Compilation {
- if sess.opts.unstable_opts.link_only {
- if let Input::File(file) = &sess.io.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 rlink_data = fs::read(file).unwrap_or_else(|err| {
- sess.emit_fatal(RlinkUnableToRead { err });
- });
- let codegen_results = match CodegenResults::deserialize_rlink(rlink_data) {
- Ok(codegen) => codegen,
- Err(err) => {
- match err {
- CodegenErrors::WrongFileType => sess.emit_fatal(RLinkWrongFileType),
- CodegenErrors::EmptyVersionNumber => {
- sess.emit_fatal(RLinkEmptyVersionNumber)
- }
- CodegenErrors::EncodingVersionMismatch { version_array, rlink_version } => {
- sess.emit_fatal(RLinkEncodingVersionMismatch {
- version_array,
- rlink_version,
- })
- }
- CodegenErrors::RustcVersionMismatch { rustc_version, current_version } => {
- sess.emit_fatal(RLinkRustcVersionMismatch {
- rustc_version,
- current_version,
- })
- }
- };
- }
- };
- let result = compiler.codegen_backend().link(sess, codegen_results, &outputs);
- abort_on_err(result, sess);
- } else {
- sess.emit_fatal(RlinkNotAFile {})
- }
- Compilation::Stop
- } else {
- Compilation::Continue
- }
-}
-
-pub fn list_metadata(sess: &Session, metadata_loader: &dyn MetadataLoader) -> Compilation {
- if sess.opts.unstable_opts.ls {
- match sess.io.input {
- Input::File(ref ifile) => {
- let path = &(*ifile);
- let mut v = Vec::new();
- locator::list_file_metadata(&sess.target, path, metadata_loader, &mut v).unwrap();
- println!("{}", String::from_utf8(v).unwrap());
- }
- Input::Str { .. } => {
- early_error(ErrorOutputType::default(), "cannot list metadata for stdin");
- }
- }
- return Compilation::Stop;
- }
-
- Compilation::Continue
-}
-
-fn print_crate_info(
- codegen_backend: &dyn CodegenBackend,
- sess: &Session,
- parse_attrs: bool,
-) -> Compilation {
- use rustc_session::config::PrintRequest::*;
- // NativeStaticLibs and LinkArgs are special - printed during linking
- // (empty iterator returns true)
- if sess.opts.prints.iter().all(|&p| p == NativeStaticLibs || p == LinkArgs) {
- return Compilation::Continue;
- }
-
- let attrs = if parse_attrs {
- let result = parse_crate_attrs(sess);
- match result {
- Ok(attrs) => Some(attrs),
- Err(mut parse_error) => {
- parse_error.emit();
- return Compilation::Stop;
- }
- }
- } else {
- None
- };
- for req in &sess.opts.prints {
- match *req {
- TargetList => {
- let mut targets = rustc_target::spec::TARGETS.to_vec();
- targets.sort_unstable();
- println!("{}", targets.join("\n"));
- }
- Sysroot => println!("{}", sess.sysroot.display()),
- TargetLibdir => println!("{}", sess.target_tlib_path.dir.display()),
- TargetSpec => {
- println!("{}", serde_json::to_string_pretty(&sess.target.to_json()).unwrap());
- }
- FileNames | CrateName => {
- let attrs = attrs.as_ref().unwrap();
- let t_outputs = rustc_interface::util::build_output_filenames(attrs, sess);
- let id = rustc_session::output::find_crate_name(sess, attrs);
- if *req == PrintRequest::CrateName {
- println!("{id}");
- continue;
- }
- let crate_types = collect_crate_types(sess, attrs);
- for &style in &crate_types {
- let fname =
- rustc_session::output::filename_for_input(sess, style, id, &t_outputs);
- println!("{}", fname.file_name().unwrap().to_string_lossy());
- }
- }
- Cfg => {
- let mut cfgs = sess
- .parse_sess
- .config
- .iter()
- .filter_map(|&(name, value)| {
- // Note that crt-static is a specially recognized cfg
- // directive that's printed out here as part of
- // rust-lang/rust#37406, but in general the
- // `target_feature` cfg is gated under
- // rust-lang/rust#29717. For now this is just
- // specifically allowing the crt-static cfg and that's
- // it, this is intended to get into Cargo and then go
- // through to build scripts.
- if (name != sym::target_feature || value != Some(sym::crt_dash_static))
- && !sess.is_nightly_build()
- && find_gated_cfg(|cfg_sym| cfg_sym == name).is_some()
- {
- return None;
- }
-
- if let Some(value) = value {
- Some(format!("{name}=\"{value}\""))
- } else {
- Some(name.to_string())
- }
- })
- .collect::<Vec<String>>();
-
- cfgs.sort();
- for cfg in cfgs {
- println!("{cfg}");
- }
- }
- CallingConventions => {
- let mut calling_conventions = rustc_target::spec::abi::all_names();
- calling_conventions.sort_unstable();
- println!("{}", calling_conventions.join("\n"));
- }
- RelocationModels
- | CodeModels
- | TlsModels
- | TargetCPUs
- | StackProtectorStrategies
- | TargetFeatures => {
- codegen_backend.print(*req, sess);
- }
- // Any output here interferes with Cargo's parsing of other printed output
- NativeStaticLibs => {}
- LinkArgs => {}
- SplitDebuginfo => {
- use rustc_target::spec::SplitDebuginfo::{Off, Packed, Unpacked};
-
- for split in &[Off, Packed, Unpacked] {
- let stable = sess.target.options.supported_split_debuginfo.contains(split);
- let unstable_ok = sess.unstable_options();
- if stable || unstable_ok {
- println!("{split}");
- }
- }
- }
- }
- }
- Compilation::Stop
-}
-
-/// Prints version information
-///
-/// NOTE: this is a macro to support drivers built at a different time than the main `rustc_driver` crate.
-pub macro version($binary: literal, $matches: expr) {
- fn unw(x: Option<&str>) -> &str {
- x.unwrap_or("unknown")
- }
- $crate::version_at_macro_invocation(
- $binary,
- $matches,
- unw(option_env!("CFG_VERSION")),
- unw(option_env!("CFG_VER_HASH")),
- unw(option_env!("CFG_VER_DATE")),
- unw(option_env!("CFG_RELEASE")),
- )
-}
-
-#[doc(hidden)] // use the macro instead
-pub fn version_at_macro_invocation(
- binary: &str,
- matches: &getopts::Matches,
- version: &str,
- commit_hash: &str,
- commit_date: &str,
- release: &str,
-) {
- let verbose = matches.opt_present("verbose");
-
- println!("{binary} {version}");
-
- if verbose {
- println!("binary: {binary}");
- println!("commit-hash: {commit_hash}");
- println!("commit-date: {commit_date}");
- println!("host: {}", config::host_triple());
- println!("release: {release}");
-
- let debug_flags = matches.opt_strs("Z");
- let backend_name = debug_flags.iter().find_map(|x| x.strip_prefix("codegen-backend="));
- get_codegen_backend(&None, backend_name).print_version();
- }
-}
-
-fn usage(verbose: bool, include_unstable_options: bool, nightly_build: bool) {
- let groups = if verbose { config::rustc_optgroups() } else { config::rustc_short_optgroups() };
- let mut options = getopts::Options::new();
- for option in groups.iter().filter(|x| include_unstable_options || x.is_stable()) {
- (option.apply)(&mut options);
- }
- let message = "Usage: rustc [OPTIONS] INPUT";
- let nightly_help = if nightly_build {
- "\n -Z help Print unstable compiler options"
- } else {
- ""
- };
- let verbose_help = if verbose {
- ""
- } else {
- "\n --help -v Print the full set of options rustc accepts"
- };
- let at_path = if verbose {
- " @path Read newline separated options from `path`\n"
- } else {
- ""
- };
- println!(
- "{options}{at_path}\nAdditional help:
- -C help Print codegen options
- -W help \
- Print 'lint' options and default settings{nightly}{verbose}\n",
- options = options.usage(message),
- at_path = at_path,
- nightly = nightly_help,
- verbose = verbose_help
- );
-}
-
-fn print_wall_help() {
- println!(
- "
-The flag `-Wall` does not exist in `rustc`. Most useful lints are enabled by
-default. Use `rustc -W help` to see all available lints. It's more common to put
-warning settings in the crate root using `#![warn(LINT_NAME)]` instead of using
-the command line flag directly.
-"
- );
-}
-
-/// Write to stdout lint command options, together with a list of all available lints
-pub fn describe_lints(sess: &Session, lint_store: &LintStore, loaded_plugins: bool) {
- println!(
- "
-Available lint options:
- -W <foo> Warn about <foo>
- -A <foo> \
- Allow <foo>
- -D <foo> Deny <foo>
- -F <foo> Forbid <foo> \
- (deny <foo> and all attempts to override)
-
-"
- );
-
- fn sort_lints(sess: &Session, mut lints: Vec<&'static Lint>) -> Vec<&'static Lint> {
- // The sort doesn't case-fold but it's doubtful we care.
- lints.sort_by_cached_key(|x: &&Lint| (x.default_level(sess.edition()), x.name));
- lints
- }
-
- fn sort_lint_groups(
- lints: Vec<(&'static str, Vec<LintId>, bool)>,
- ) -> Vec<(&'static str, Vec<LintId>)> {
- let mut lints: Vec<_> = lints.into_iter().map(|(x, y, _)| (x, y)).collect();
- lints.sort_by_key(|l| l.0);
- lints
- }
-
- let (plugin, builtin): (Vec<_>, _) =
- lint_store.get_lints().iter().cloned().partition(|&lint| lint.is_plugin);
- let plugin = sort_lints(sess, plugin);
- let builtin = sort_lints(sess, builtin);
-
- let (plugin_groups, builtin_groups): (Vec<_>, _) =
- lint_store.get_lint_groups().partition(|&(.., p)| p);
- let plugin_groups = sort_lint_groups(plugin_groups);
- let builtin_groups = sort_lint_groups(builtin_groups);
-
- let max_name_len =
- plugin.iter().chain(&builtin).map(|&s| s.name.chars().count()).max().unwrap_or(0);
- let padded = |x: &str| {
- let mut s = " ".repeat(max_name_len - x.chars().count());
- s.push_str(x);
- s
- };
-
- println!("Lint checks provided by rustc:\n");
-
- let print_lints = |lints: Vec<&Lint>| {
- println!(" {} {:7.7} {}", padded("name"), "default", "meaning");
- println!(" {} {:7.7} {}", padded("----"), "-------", "-------");
- for lint in lints {
- let name = lint.name_lower().replace('_', "-");
- println!(
- " {} {:7.7} {}",
- padded(&name),
- lint.default_level(sess.edition()).as_str(),
- lint.desc
- );
- }
- println!("\n");
- };
-
- print_lints(builtin);
-
- let max_name_len = max(
- "warnings".len(),
- plugin_groups
- .iter()
- .chain(&builtin_groups)
- .map(|&(s, _)| s.chars().count())
- .max()
- .unwrap_or(0),
- );
-
- let padded = |x: &str| {
- let mut s = " ".repeat(max_name_len - x.chars().count());
- s.push_str(x);
- s
- };
-
- println!("Lint groups provided by rustc:\n");
-
- let print_lint_groups = |lints: Vec<(&'static str, Vec<LintId>)>, all_warnings| {
- println!(" {} sub-lints", padded("name"));
- println!(" {} ---------", padded("----"));
-
- if all_warnings {
- println!(" {} all lints that are set to issue warnings", padded("warnings"));
- }
-
- for (name, to) in lints {
- let name = name.to_lowercase().replace('_', "-");
- let desc = to
- .into_iter()
- .map(|x| x.to_string().replace('_', "-"))
- .collect::<Vec<String>>()
- .join(", ");
- println!(" {} {}", padded(&name), desc);
- }
- println!("\n");
- };
-
- print_lint_groups(builtin_groups, true);
-
- match (loaded_plugins, plugin.len(), plugin_groups.len()) {
- (false, 0, _) | (false, _, 0) => {
- println!("Lint tools like Clippy can provide additional lints and lint groups.");
- }
- (false, ..) => panic!("didn't load lint plugins but got them anyway!"),
- (true, 0, 0) => println!("This crate does not load any lint plugins or lint groups."),
- (true, l, g) => {
- if l > 0 {
- println!("Lint checks provided by plugins loaded by this crate:\n");
- print_lints(plugin);
- }
- if g > 0 {
- println!("Lint groups provided by plugins loaded by this crate:\n");
- print_lint_groups(plugin_groups, false);
- }
- }
- }
-}
-
-fn describe_debug_flags() {
- println!("\nAvailable options:\n");
- print_flag_list("-Z", config::Z_OPTIONS);
-}
-
-fn describe_codegen_flags() {
- println!("\nAvailable codegen options:\n");
- print_flag_list("-C", config::CG_OPTIONS);
-}
-
-pub fn print_flag_list<T>(
- cmdline_opt: &str,
- flag_list: &[(&'static str, T, &'static str, &'static str)],
-) {
- let max_len = flag_list.iter().map(|&(name, _, _, _)| name.chars().count()).max().unwrap_or(0);
-
- for &(name, _, _, desc) in flag_list {
- println!(
- " {} {:>width$}=val -- {}",
- cmdline_opt,
- name.replace('_', "-"),
- desc,
- width = max_len
- );
- }
-}
-
-/// Process command line options. Emits messages as appropriate. If compilation
-/// should continue, returns a getopts::Matches object parsed from args,
-/// otherwise returns `None`.
-///
-/// The compiler's handling of options is a little complicated as it ties into
-/// our stability story. The current intention of each compiler option is to
-/// have one of two modes:
-///
-/// 1. An option is stable and can be used everywhere.
-/// 2. An option is unstable, and can only be used on nightly.
-///
-/// Like unstable library and language features, however, unstable options have
-/// always required a form of "opt in" to indicate that you're using them. This
-/// provides the easy ability to scan a code base to check to see if anything
-/// unstable is being used. Currently, this "opt in" is the `-Z` "zed" flag.
-///
-/// All options behind `-Z` are considered unstable by default. Other top-level
-/// options can also be considered unstable, and they were unlocked through the
-/// `-Z unstable-options` flag. Note that `-Z` remains to be the root of
-/// instability in both cases, though.
-///
-/// So with all that in mind, the comments below have some more detail about the
-/// contortions done here to get things to work out correctly.
-pub fn handle_options(args: &[String]) -> Option<getopts::Matches> {
- // Throw away the first argument, the name of the binary
- let args = &args[1..];
-
- if args.is_empty() {
- // user did not write `-v` nor `-Z unstable-options`, so do not
- // include that extra information.
- let nightly_build =
- rustc_feature::UnstableFeatures::from_environment(None).is_nightly_build();
- usage(false, false, nightly_build);
- return None;
- }
-
- // Parse with *all* options defined in the compiler, we don't worry about
- // option stability here we just want to parse as much as possible.
- let mut options = getopts::Options::new();
- for option in config::rustc_optgroups() {
- (option.apply)(&mut options);
- }
- let matches = options.parse(args).unwrap_or_else(|e| {
- let msg = match e {
- getopts::Fail::UnrecognizedOption(ref opt) => CG_OPTIONS
- .iter()
- .map(|&(name, ..)| ('C', name))
- .chain(Z_OPTIONS.iter().map(|&(name, ..)| ('Z', name)))
- .find(|&(_, name)| *opt == name.replace('_', "-"))
- .map(|(flag, _)| format!("{e}. Did you mean `-{flag} {opt}`?")),
- _ => None,
- };
- early_error(ErrorOutputType::default(), &msg.unwrap_or_else(|| e.to_string()));
- });
-
- // For all options we just parsed, we check a few aspects:
- //
- // * If the option is stable, we're all good
- // * If the option wasn't passed, we're all good
- // * If `-Z unstable-options` wasn't passed (and we're not a -Z option
- // ourselves), then we require the `-Z unstable-options` flag to unlock
- // this option that was passed.
- // * If we're a nightly compiler, then unstable options are now unlocked, so
- // we're good to go.
- // * Otherwise, if we're an unstable option then we generate an error
- // (unstable option being used on stable)
- nightly_options::check_nightly_options(&matches, &config::rustc_optgroups());
-
- if matches.opt_present("h") || matches.opt_present("help") {
- // Only show unstable options in --help if we accept unstable options.
- let unstable_enabled = nightly_options::is_unstable_enabled(&matches);
- let nightly_build = nightly_options::match_is_nightly_build(&matches);
- usage(matches.opt_present("verbose"), unstable_enabled, nightly_build);
- return None;
- }
-
- // Handle the special case of -Wall.
- let wall = matches.opt_strs("W");
- if wall.iter().any(|x| *x == "all") {
- print_wall_help();
- rustc_errors::FatalError.raise();
- }
-
- // Don't handle -W help here, because we might first load plugins.
- let debug_flags = matches.opt_strs("Z");
- if debug_flags.iter().any(|x| *x == "help") {
- describe_debug_flags();
- return None;
- }
-
- let cg_flags = matches.opt_strs("C");
-
- if cg_flags.iter().any(|x| *x == "help") {
- describe_codegen_flags();
- return None;
- }
-
- if cg_flags.iter().any(|x| *x == "no-stack-check") {
- early_warn(
- ErrorOutputType::default(),
- "the --no-stack-check flag is deprecated and does nothing",
- );
- }
-
- if cg_flags.iter().any(|x| *x == "passes=list") {
- let backend_name = debug_flags.iter().find_map(|x| x.strip_prefix("codegen-backend="));
- get_codegen_backend(&None, backend_name).print_passes();
- return None;
- }
-
- if matches.opt_present("version") {
- version!("rustc", &matches);
- return None;
- }
-
- Some(matches)
-}
-
-fn parse_crate_attrs<'a>(sess: &'a Session) -> PResult<'a, ast::AttrVec> {
- match &sess.io.input {
- Input::File(ifile) => rustc_parse::parse_crate_attrs_from_file(ifile, &sess.parse_sess),
- Input::Str { name, input } => rustc_parse::parse_crate_attrs_from_source_str(
- name.clone(),
- input.clone(),
- &sess.parse_sess,
- ),
- }
-}
-
-/// Gets a list of extra command-line flags provided by the user, as strings.
-///
-/// This function is used during ICEs to show more information useful for
-/// debugging, since some ICEs only happens with non-default compiler flags
-/// (and the users don't always report them).
-fn extra_compiler_flags() -> Option<(Vec<String>, bool)> {
- let mut args = env::args_os().map(|arg| arg.to_string_lossy().to_string()).peekable();
-
- let mut result = Vec::new();
- let mut excluded_cargo_defaults = false;
- while let Some(arg) = args.next() {
- if let Some(a) = ICE_REPORT_COMPILER_FLAGS.iter().find(|a| arg.starts_with(*a)) {
- let content = if arg.len() == a.len() {
- // A space-separated option, like `-C incremental=foo` or `--crate-type rlib`
- match args.next() {
- Some(arg) => arg.to_string(),
- None => continue,
- }
- } else if arg.get(a.len()..a.len() + 1) == Some("=") {
- // An equals option, like `--crate-type=rlib`
- arg[a.len() + 1..].to_string()
- } else {
- // A non-space option, like `-Cincremental=foo`
- arg[a.len()..].to_string()
- };
- let option = content.split_once('=').map(|s| s.0).unwrap_or(&content);
- if ICE_REPORT_COMPILER_FLAGS_EXCLUDE.iter().any(|exc| option == *exc) {
- excluded_cargo_defaults = true;
- } else {
- result.push(a.to_string());
- match ICE_REPORT_COMPILER_FLAGS_STRIP_VALUE.iter().find(|s| option == **s) {
- Some(s) => result.push(format!("{s}=[REDACTED]")),
- None => result.push(content),
- }
- }
- }
- }
-
- if !result.is_empty() { Some((result, excluded_cargo_defaults)) } else { None }
-}
-
-/// Runs a closure and catches unwinds triggered by fatal errors.
-///
-/// The compiler currently unwinds with a special sentinel value to abort
-/// compilation on fatal errors. This function catches that sentinel and turns
-/// the panic into a `Result` instead.
-pub fn catch_fatal_errors<F: FnOnce() -> R, R>(f: F) -> Result<R, ErrorGuaranteed> {
- catch_unwind(panic::AssertUnwindSafe(f)).map_err(|value| {
- if value.is::<rustc_errors::FatalErrorMarker>() {
- ErrorGuaranteed::unchecked_claim_error_was_emitted()
- } else {
- panic::resume_unwind(value);
- }
- })
-}
-
-/// Variant of `catch_fatal_errors` for the `interface::Result` return type
-/// that also computes the exit code.
-pub fn catch_with_exit_code(f: impl FnOnce() -> interface::Result<()>) -> i32 {
- let result = catch_fatal_errors(f).and_then(|result| result);
- match result {
- Ok(()) => EXIT_SUCCESS,
- Err(_) => EXIT_FAILURE,
- }
-}
-
-static DEFAULT_HOOK: LazyLock<Box<dyn Fn(&panic::PanicInfo<'_>) + Sync + Send + 'static>> =
- LazyLock::new(|| {
- let hook = panic::take_hook();
- panic::set_hook(Box::new(|info| {
- // If the error was caused by a broken pipe then this is not a bug.
- // Write the error and return immediately. See #98700.
- #[cfg(windows)]
- if let Some(msg) = info.payload().downcast_ref::<String>() {
- if msg.starts_with("failed printing to stdout: ") && msg.ends_with("(os error 232)")
- {
- early_error_no_abort(ErrorOutputType::default(), &msg);
- return;
- }
- };
-
- // Invoke the default handler, which prints the actual panic message and optionally a backtrace
- // Don't do this for delayed bugs, which already emit their own more useful backtrace.
- if !info.payload().is::<rustc_errors::DelayedBugPanic>() {
- (*DEFAULT_HOOK)(info);
-
- // Separate the output with an empty line
- eprintln!();
- }
-
- // Print the ICE message
- report_ice(info, BUG_REPORT_URL);
- }));
- hook
- });
-
-/// Prints the ICE message, including query stack, but without backtrace.
-///
-/// The message will point the user at `bug_report_url` to report the ICE.
-///
-/// When `install_ice_hook` is called, this function will be called as the panic
-/// hook.
-pub fn report_ice(info: &panic::PanicInfo<'_>, bug_report_url: &str) {
- let fallback_bundle =
- rustc_errors::fallback_fluent_bundle(rustc_errors::DEFAULT_LOCALE_RESOURCES, false);
- let emitter = Box::new(rustc_errors::emitter::EmitterWriter::stderr(
- rustc_errors::ColorConfig::Auto,
- None,
- None,
- fallback_bundle,
- false,
- false,
- None,
- false,
- false,
- ));
- let handler = rustc_errors::Handler::with_emitter(true, None, emitter);
-
- // a .span_bug or .bug call has already printed what
- // it wants to print.
- if !info.payload().is::<rustc_errors::ExplicitBug>()
- && !info.payload().is::<rustc_errors::DelayedBugPanic>()
- {
- let mut d = rustc_errors::Diagnostic::new(rustc_errors::Level::Bug, "unexpected panic");
- handler.emit_diagnostic(&mut d);
- }
-
- let mut xs: Vec<Cow<'static, str>> = vec![
- "the compiler unexpectedly panicked. this is a bug.".into(),
- format!("we would appreciate a bug report: {bug_report_url}").into(),
- format!(
- "rustc {} running on {}",
- util::version_str!().unwrap_or("unknown_version"),
- config::host_triple()
- )
- .into(),
- ];
-
- if let Some((flags, excluded_cargo_defaults)) = extra_compiler_flags() {
- xs.push(format!("compiler flags: {}", flags.join(" ")).into());
-
- if excluded_cargo_defaults {
- xs.push("some of the compiler flags provided by cargo are hidden".into());
- }
- }
-
- for note in &xs {
- handler.note_without_error(note.as_ref());
- }
-
- // If backtraces are enabled, also print the query stack
- let backtrace = env::var_os("RUST_BACKTRACE").map_or(false, |x| &x != "0");
-
- let num_frames = if backtrace { None } else { Some(2) };
-
- interface::try_print_query_stack(&handler, num_frames);
-
- #[cfg(windows)]
- unsafe {
- if env::var("RUSTC_BREAK_ON_ICE").is_ok() {
- // Trigger a debugger if we crashed during bootstrap
- winapi::um::debugapi::DebugBreak();
- }
- }
-}
-
-/// Installs a panic hook that will print the ICE message on unexpected panics.
-///
-/// A custom rustc driver can skip calling this to set up a custom ICE hook.
-pub fn install_ice_hook() {
- // If the user has not explicitly overridden "RUST_BACKTRACE", then produce
- // full backtraces. When a compiler ICE happens, we want to gather
- // as much information as possible to present in the issue opened
- // by the user. Compiler developers and other rustc users can
- // opt in to less-verbose backtraces by manually setting "RUST_BACKTRACE"
- // (e.g. `RUST_BACKTRACE=1`)
- if std::env::var("RUST_BACKTRACE").is_err() {
- std::env::set_var("RUST_BACKTRACE", "full");
- }
- LazyLock::force(&DEFAULT_HOOK);
-}
-
-/// This allows tools to enable rust logging without having to magically match rustc's
-/// tracing crate version.
-pub fn init_rustc_env_logger() {
- init_rustc_env_logger_with_backtrace_option(&None);
-}
-
-/// This allows tools to enable rust logging without having to magically match rustc's
-/// tracing crate version. In contrast to `init_rustc_env_logger` it allows you to
-/// choose a target module you wish to show backtraces along with its logging.
-pub fn init_rustc_env_logger_with_backtrace_option(backtrace_target: &Option<String>) {
- if let Err(error) = rustc_log::init_rustc_env_logger_with_backtrace_option(backtrace_target) {
- early_error(ErrorOutputType::default(), &error.to_string());
- }
-}
-
-/// This allows tools to enable rust logging without having to magically match rustc's
-/// 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) {
- if let Err(error) = rustc_log::init_env_logger(env) {
- early_error(ErrorOutputType::default(), &error.to_string());
- }
-}
-
-#[cfg(all(unix, any(target_env = "gnu", target_os = "macos")))]
-mod signal_handler {
- extern "C" {
- fn backtrace_symbols_fd(
- buffer: *const *mut libc::c_void,
- size: libc::c_int,
- fd: libc::c_int,
- );
- }
-
- extern "C" fn print_stack_trace(_: libc::c_int) {
- const MAX_FRAMES: usize = 256;
- static mut STACK_TRACE: [*mut libc::c_void; MAX_FRAMES] =
- [std::ptr::null_mut(); MAX_FRAMES];
- unsafe {
- let depth = libc::backtrace(STACK_TRACE.as_mut_ptr(), MAX_FRAMES as i32);
- if depth == 0 {
- return;
- }
- backtrace_symbols_fd(STACK_TRACE.as_ptr(), depth, 2);
- }
- }
-
- /// When an error signal (such as SIGABRT or SIGSEGV) is delivered to the
- /// process, print a stack trace and then exit.
- pub(super) fn install() {
- unsafe {
- const ALT_STACK_SIZE: usize = libc::MINSIGSTKSZ + 64 * 1024;
- let mut alt_stack: libc::stack_t = std::mem::zeroed();
- alt_stack.ss_sp =
- std::alloc::alloc(std::alloc::Layout::from_size_align(ALT_STACK_SIZE, 1).unwrap())
- as *mut libc::c_void;
- alt_stack.ss_size = ALT_STACK_SIZE;
- libc::sigaltstack(&alt_stack, std::ptr::null_mut());
-
- let mut sa: libc::sigaction = std::mem::zeroed();
- sa.sa_sigaction = print_stack_trace as libc::sighandler_t;
- sa.sa_flags = libc::SA_NODEFER | libc::SA_RESETHAND | libc::SA_ONSTACK;
- libc::sigemptyset(&mut sa.sa_mask);
- libc::sigaction(libc::SIGSEGV, &sa, std::ptr::null_mut());
- }
- }
-}
-
-#[cfg(not(all(unix, any(target_env = "gnu", target_os = "macos"))))]
-mod signal_handler {
- pub(super) fn install() {}
-}
-
-pub fn main() -> ! {
- let start_time = Instant::now();
- let start_rss = get_resident_set_size();
- signal_handler::install();
- let mut callbacks = TimePassesCallbacks::default();
- install_ice_hook();
- let exit_code = catch_with_exit_code(|| {
- let args = env::args_os()
- .enumerate()
- .map(|(i, arg)| {
- arg.into_string().unwrap_or_else(|arg| {
- early_error(
- ErrorOutputType::default(),
- &format!("argument {i} is not valid Unicode: {arg:?}"),
- )
- })
- })
- .collect::<Vec<_>>();
- RunCompiler::new(&args, &mut callbacks).run()
- });
-
- if callbacks.time_passes {
- let end_rss = get_resident_set_size();
- print_time_passes_entry("total", start_time.elapsed(), start_rss, end_rss);
- }
-
- process::exit(exit_code)
-}
+pub use rustc_driver_impl::*;
diff --git a/compiler/rustc_driver/src/session_diagnostics.rs b/compiler/rustc_driver/src/session_diagnostics.rs
deleted file mode 100644
index c1bc10891..000000000
--- a/compiler/rustc_driver/src/session_diagnostics.rs
+++ /dev/null
@@ -1,40 +0,0 @@
-use rustc_macros::Diagnostic;
-
-#[derive(Diagnostic)]
-#[diag(driver_rlink_unable_to_read)]
-pub(crate) struct RlinkUnableToRead {
- pub err: std::io::Error,
-}
-
-#[derive(Diagnostic)]
-#[diag(driver_rlink_wrong_file_type)]
-pub(crate) struct RLinkWrongFileType;
-
-#[derive(Diagnostic)]
-#[diag(driver_rlink_empty_version_number)]
-pub(crate) struct RLinkEmptyVersionNumber;
-
-#[derive(Diagnostic)]
-#[diag(driver_rlink_encoding_version_mismatch)]
-pub(crate) struct RLinkEncodingVersionMismatch {
- pub version_array: String,
- pub rlink_version: u32,
-}
-
-#[derive(Diagnostic)]
-#[diag(driver_rlink_rustc_version_mismatch)]
-pub(crate) struct RLinkRustcVersionMismatch<'a> {
- pub rustc_version: String,
- pub current_version: &'a str,
-}
-
-#[derive(Diagnostic)]
-#[diag(driver_rlink_no_a_file)]
-pub(crate) struct RlinkNotAFile;
-
-#[derive(Diagnostic)]
-#[diag(driver_unpretty_dump_fail)]
-pub(crate) struct UnprettyDumpFail {
- pub path: String,
- pub err: String,
-}
diff --git a/compiler/rustc_driver_impl/Cargo.toml b/compiler/rustc_driver_impl/Cargo.toml
new file mode 100644
index 000000000..7b59a52cf
--- /dev/null
+++ b/compiler/rustc_driver_impl/Cargo.toml
@@ -0,0 +1,64 @@
+[package]
+name = "rustc_driver_impl"
+version = "0.0.0"
+edition = "2021"
+
+[lib]
+
+[dependencies]
+tracing = { version = "0.1.35" }
+serde_json = "1.0.59"
+rustc_log = { path = "../rustc_log" }
+rustc_ast_lowering = { path = "../rustc_ast_lowering" }
+rustc_ast_passes = { path = "../rustc_ast_passes" }
+rustc_attr = { path = "../rustc_attr" }
+rustc_borrowck = { path = "../rustc_borrowck" }
+rustc_builtin_macros = { path = "../rustc_builtin_macros" }
+rustc_const_eval = { path = "../rustc_const_eval" }
+rustc_error_messages = { path = "../rustc_error_messages" }
+rustc_expand = { path = "../rustc_expand" }
+rustc_hir_typeck = { path = "../rustc_hir_typeck" }
+rustc_incremental = { path = "../rustc_incremental" }
+rustc_infer = { path = "../rustc_infer" }
+rustc_mir_build = { path = "../rustc_mir_build" }
+rustc_mir_dataflow = { path = "../rustc_mir_dataflow" }
+rustc_monomorphize = { path = "../rustc_monomorphize" }
+rustc_passes = { path = "../rustc_passes" }
+rustc_privacy = { path = "../rustc_privacy" }
+rustc_query_system = { path = "../rustc_query_system" }
+rustc_resolve = { path = "../rustc_resolve" }
+rustc_symbol_mangling = { path = "../rustc_symbol_mangling" }
+rustc_trait_selection = { path = "../rustc_trait_selection" }
+rustc_ty_utils = { path = "../rustc_ty_utils" }
+rustc_middle = { path = "../rustc_middle" }
+rustc_ast_pretty = { path = "../rustc_ast_pretty" }
+rustc_target = { path = "../rustc_target" }
+rustc_lint = { path = "../rustc_lint" }
+rustc_data_structures = { path = "../rustc_data_structures" }
+rustc_errors = { path = "../rustc_errors" }
+rustc_feature = { path = "../rustc_feature" }
+rustc_hir = { path = "../rustc_hir" }
+rustc_hir_pretty = { path = "../rustc_hir_pretty" }
+rustc_macros = { path = "../rustc_macros" }
+rustc_metadata = { path = "../rustc_metadata" }
+rustc_parse = { path = "../rustc_parse" }
+rustc_plugin_impl = { path = "../rustc_plugin_impl" }
+rustc_codegen_ssa = { path = "../rustc_codegen_ssa" }
+rustc_session = { path = "../rustc_session" }
+rustc_error_codes = { path = "../rustc_error_codes" }
+rustc_interface = { path = "../rustc_interface" }
+rustc_ast = { path = "../rustc_ast" }
+rustc_span = { path = "../rustc_span" }
+rustc_hir_analysis = { path = "../rustc_hir_analysis" }
+
+[target.'cfg(unix)'.dependencies]
+libc = "0.2"
+
+[target.'cfg(windows)'.dependencies]
+winapi = { version = "0.3", features = ["consoleapi", "debugapi", "processenv"] }
+
+[features]
+llvm = ['rustc_interface/llvm']
+max_level_info = ['rustc_log/max_level_info']
+rustc_use_parallel_compiler = ['rustc_data_structures/rustc_use_parallel_compiler', 'rustc_interface/rustc_use_parallel_compiler',
+ 'rustc_middle/rustc_use_parallel_compiler']
diff --git a/compiler/rustc_driver/README.md b/compiler/rustc_driver_impl/README.md
index 6d7fba36f..6d7fba36f 100644
--- a/compiler/rustc_driver/README.md
+++ b/compiler/rustc_driver_impl/README.md
diff --git a/compiler/rustc_driver_impl/locales/en-US.ftl b/compiler/rustc_driver_impl/locales/en-US.ftl
new file mode 100644
index 000000000..f19b1ff64
--- /dev/null
+++ b/compiler/rustc_driver_impl/locales/en-US.ftl
@@ -0,0 +1,19 @@
+driver_impl_rlink_unable_to_read = failed to read rlink file: `{$err}`
+
+driver_impl_rlink_wrong_file_type = The input does not look like a .rlink file
+
+driver_impl_rlink_empty_version_number = The input does not contain version number
+
+driver_impl_rlink_encoding_version_mismatch = .rlink file was produced with encoding version `{$version_array}`, but the current version is `{$rlink_version}`
+
+driver_impl_rlink_rustc_version_mismatch = .rlink file was produced by rustc version `{$rustc_version}`, but the current version is `{$current_version}`
+
+driver_impl_rlink_no_a_file = rlink must be a file
+
+driver_impl_unpretty_dump_fail = pretty-print failed to write `{$path}` due to error `{$err}`
+
+driver_impl_ice = the compiler unexpectedly panicked. this is a bug.
+driver_impl_ice_bug_report = we would appreciate a bug report: {$bug_report_url}
+driver_impl_ice_version = rustc {$version} running on {$triple}
+driver_impl_ice_flags = compiler flags: {$flags}
+driver_impl_ice_exclude_cargo_defaults = some of the compiler flags provided by cargo are hidden
diff --git a/compiler/rustc_driver/src/args.rs b/compiler/rustc_driver_impl/src/args.rs
index 42c97cc6a..42c97cc6a 100644
--- a/compiler/rustc_driver/src/args.rs
+++ b/compiler/rustc_driver_impl/src/args.rs
diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs
new file mode 100644
index 000000000..464ddae47
--- /dev/null
+++ b/compiler/rustc_driver_impl/src/lib.rs
@@ -0,0 +1,1364 @@
+//! The Rust compiler.
+//!
+//! # Note
+//!
+//! This API is completely unstable and subject to change.
+
+#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
+#![feature(is_terminal)]
+#![feature(once_cell)]
+#![feature(decl_macro)]
+#![recursion_limit = "256"]
+#![allow(rustc::potential_query_instability)]
+#![deny(rustc::untranslatable_diagnostic)]
+#![deny(rustc::diagnostic_outside_of_impl)]
+
+#[macro_use]
+extern crate tracing;
+
+pub extern crate rustc_plugin_impl as plugin;
+
+use rustc_ast as ast;
+use rustc_codegen_ssa::{traits::CodegenBackend, CodegenErrors, CodegenResults};
+use rustc_data_structures::profiling::{get_resident_set_size, print_time_passes_entry};
+use rustc_data_structures::sync::SeqCst;
+use rustc_errors::registry::{InvalidErrorCode, Registry};
+use rustc_errors::{
+ DiagnosticMessage, ErrorGuaranteed, PResult, SubdiagnosticMessage, TerminalUrl,
+};
+use rustc_feature::find_gated_cfg;
+use rustc_interface::util::{self, collect_crate_types, get_codegen_backend};
+use rustc_interface::{interface, Queries};
+use rustc_lint::LintStore;
+use rustc_macros::fluent_messages;
+use rustc_metadata::locator;
+use rustc_session::config::{nightly_options, CG_OPTIONS, Z_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, Session};
+use rustc_session::{early_error, early_error_no_abort, early_warn};
+use rustc_span::source_map::{FileLoader, FileName};
+use rustc_span::symbol::sym;
+use rustc_target::json::ToJson;
+
+use std::cmp::max;
+use std::env;
+use std::ffi::OsString;
+use std::fs;
+use std::io::{self, IsTerminal, Read, Write};
+use std::panic::{self, catch_unwind};
+use std::path::PathBuf;
+use std::process::{self, Command, Stdio};
+use std::str;
+use std::sync::LazyLock;
+use std::time::Instant;
+
+pub mod args;
+pub mod pretty;
+mod session_diagnostics;
+
+use crate::session_diagnostics::{
+ RLinkEmptyVersionNumber, RLinkEncodingVersionMismatch, RLinkRustcVersionMismatch,
+ RLinkWrongFileType, RlinkNotAFile, RlinkUnableToRead,
+};
+
+fluent_messages! { "../locales/en-US.ftl" }
+
+pub static DEFAULT_LOCALE_RESOURCES: &[&str] = &[
+ // tidy-alphabetical-start
+ crate::DEFAULT_LOCALE_RESOURCE,
+ rustc_ast_lowering::DEFAULT_LOCALE_RESOURCE,
+ rustc_ast_passes::DEFAULT_LOCALE_RESOURCE,
+ rustc_attr::DEFAULT_LOCALE_RESOURCE,
+ rustc_borrowck::DEFAULT_LOCALE_RESOURCE,
+ rustc_builtin_macros::DEFAULT_LOCALE_RESOURCE,
+ rustc_codegen_ssa::DEFAULT_LOCALE_RESOURCE,
+ rustc_const_eval::DEFAULT_LOCALE_RESOURCE,
+ rustc_error_messages::DEFAULT_LOCALE_RESOURCE,
+ rustc_expand::DEFAULT_LOCALE_RESOURCE,
+ rustc_hir_analysis::DEFAULT_LOCALE_RESOURCE,
+ rustc_hir_typeck::DEFAULT_LOCALE_RESOURCE,
+ rustc_incremental::DEFAULT_LOCALE_RESOURCE,
+ rustc_infer::DEFAULT_LOCALE_RESOURCE,
+ rustc_interface::DEFAULT_LOCALE_RESOURCE,
+ rustc_lint::DEFAULT_LOCALE_RESOURCE,
+ rustc_metadata::DEFAULT_LOCALE_RESOURCE,
+ rustc_middle::DEFAULT_LOCALE_RESOURCE,
+ rustc_mir_build::DEFAULT_LOCALE_RESOURCE,
+ rustc_mir_dataflow::DEFAULT_LOCALE_RESOURCE,
+ rustc_monomorphize::DEFAULT_LOCALE_RESOURCE,
+ rustc_parse::DEFAULT_LOCALE_RESOURCE,
+ rustc_passes::DEFAULT_LOCALE_RESOURCE,
+ rustc_plugin_impl::DEFAULT_LOCALE_RESOURCE,
+ rustc_privacy::DEFAULT_LOCALE_RESOURCE,
+ rustc_query_system::DEFAULT_LOCALE_RESOURCE,
+ rustc_resolve::DEFAULT_LOCALE_RESOURCE,
+ rustc_session::DEFAULT_LOCALE_RESOURCE,
+ rustc_symbol_mangling::DEFAULT_LOCALE_RESOURCE,
+ rustc_trait_selection::DEFAULT_LOCALE_RESOURCE,
+ rustc_ty_utils::DEFAULT_LOCALE_RESOURCE,
+ // tidy-alphabetical-end
+];
+
+/// Exit status code used for successful compilation and help output.
+pub const EXIT_SUCCESS: i32 = 0;
+
+/// Exit status code used for compilation failures and invalid flags.
+pub const EXIT_FAILURE: i32 = 1;
+
+const BUG_REPORT_URL: &str = "https://github.com/rust-lang/rust/issues/new\
+ ?labels=C-bug%2C+I-ICE%2C+T-compiler&template=ice.md";
+
+const ICE_REPORT_COMPILER_FLAGS: &[&str] = &["-Z", "-C", "--crate-type"];
+
+const ICE_REPORT_COMPILER_FLAGS_EXCLUDE: &[&str] = &["metadata", "extra-filename"];
+
+const ICE_REPORT_COMPILER_FLAGS_STRIP_VALUE: &[&str] = &["incremental"];
+
+pub fn abort_on_err<T>(result: Result<T, ErrorGuaranteed>, sess: &Session) -> T {
+ match result {
+ Err(..) => {
+ sess.abort_if_errors();
+ panic!("error reported but abort_if_errors didn't abort???");
+ }
+ Ok(x) => x,
+ }
+}
+
+pub trait Callbacks {
+ /// Called before creating the compiler instance
+ fn config(&mut self, _config: &mut interface::Config) {}
+ /// Called after parsing. Return value instructs the compiler whether to
+ /// continue the compilation afterwards (defaults to `Compilation::Continue`)
+ fn after_parsing<'tcx>(
+ &mut self,
+ _compiler: &interface::Compiler,
+ _queries: &'tcx Queries<'tcx>,
+ ) -> Compilation {
+ Compilation::Continue
+ }
+ /// Called after expansion. Return value instructs the compiler whether to
+ /// continue the compilation afterwards (defaults to `Compilation::Continue`)
+ fn after_expansion<'tcx>(
+ &mut self,
+ _compiler: &interface::Compiler,
+ _queries: &'tcx Queries<'tcx>,
+ ) -> Compilation {
+ Compilation::Continue
+ }
+ /// Called after analysis. Return value instructs the compiler whether to
+ /// continue the compilation afterwards (defaults to `Compilation::Continue`)
+ fn after_analysis<'tcx>(
+ &mut self,
+ _compiler: &interface::Compiler,
+ _queries: &'tcx Queries<'tcx>,
+ ) -> Compilation {
+ Compilation::Continue
+ }
+}
+
+#[derive(Default)]
+pub struct TimePassesCallbacks {
+ time_passes: bool,
+}
+
+impl Callbacks for TimePassesCallbacks {
+ // JUSTIFICATION: the session doesn't exist at this point.
+ #[allow(rustc::bad_opt_access)]
+ fn config(&mut self, config: &mut interface::Config) {
+ // If a --print=... option has been given, we don't print the "total"
+ // time because it will mess up the --print output. See #64339.
+ //
+ self.time_passes = config.opts.prints.is_empty() && config.opts.unstable_opts.time_passes;
+ config.opts.trimmed_def_paths = TrimmedDefPaths::GoodPath;
+ }
+}
+
+pub fn diagnostics_registry() -> Registry {
+ Registry::new(rustc_error_codes::DIAGNOSTICS)
+}
+
+/// This is the primary entry point for rustc.
+pub struct RunCompiler<'a, 'b> {
+ at_args: &'a [String],
+ callbacks: &'b mut (dyn Callbacks + Send),
+ file_loader: Option<Box<dyn FileLoader + Send + Sync>>,
+ make_codegen_backend:
+ Option<Box<dyn FnOnce(&config::Options) -> Box<dyn CodegenBackend> + Send>>,
+}
+
+impl<'a, 'b> RunCompiler<'a, 'b> {
+ pub fn new(at_args: &'a [String], callbacks: &'b mut (dyn Callbacks + Send)) -> Self {
+ Self { at_args, callbacks, file_loader: None, make_codegen_backend: None }
+ }
+
+ /// Set a custom codegen backend.
+ ///
+ /// Has no uses within this repository, but is used by bjorn3 for "the
+ /// hotswapping branch of cg_clif" for "setting the codegen backend from a
+ /// custom driver where the custom codegen backend has arbitrary data."
+ /// (See #102759.)
+ pub fn set_make_codegen_backend(
+ &mut self,
+ make_codegen_backend: Option<
+ Box<dyn FnOnce(&config::Options) -> Box<dyn CodegenBackend> + Send>,
+ >,
+ ) -> &mut Self {
+ self.make_codegen_backend = make_codegen_backend;
+ self
+ }
+
+ /// Load files from sources other than the file system.
+ ///
+ /// Has no uses within this repository, but may be used in the future by
+ /// bjorn3 for "hooking rust-analyzer's VFS into rustc at some point for
+ /// running rustc without having to save". (See #102759.)
+ pub fn set_file_loader(
+ &mut self,
+ file_loader: Option<Box<dyn FileLoader + Send + Sync>>,
+ ) -> &mut Self {
+ self.file_loader = file_loader;
+ self
+ }
+
+ /// Parse args and run the compiler.
+ pub fn run(self) -> interface::Result<()> {
+ run_compiler(self.at_args, self.callbacks, self.file_loader, self.make_codegen_backend)
+ }
+}
+
+fn run_compiler(
+ at_args: &[String],
+ callbacks: &mut (dyn Callbacks + Send),
+ file_loader: Option<Box<dyn FileLoader + Send + Sync>>,
+ make_codegen_backend: Option<
+ Box<dyn FnOnce(&config::Options) -> Box<dyn CodegenBackend> + Send>,
+ >,
+) -> interface::Result<()> {
+ let args = args::arg_expand_all(at_args);
+
+ let Some(matches) = handle_options(&args) else { return Ok(()) };
+
+ let sopts = config::build_session_options(&matches);
+
+ if let Some(ref code) = matches.opt_str("explain") {
+ handle_explain(diagnostics_registry(), code, sopts.error_format);
+ return Ok(());
+ }
+
+ let cfg = interface::parse_cfgspecs(matches.opt_strs("cfg"));
+ let check_cfg = interface::parse_check_cfg(matches.opt_strs("check-cfg"));
+ let (odir, ofile) = make_output(&matches);
+ let mut config = interface::Config {
+ opts: sopts,
+ crate_cfg: cfg,
+ crate_check_cfg: check_cfg,
+ input: Input::File(PathBuf::new()),
+ output_file: ofile,
+ output_dir: odir,
+ file_loader,
+ locale_resources: DEFAULT_LOCALE_RESOURCES,
+ lint_caps: Default::default(),
+ parse_sess_created: None,
+ register_lints: None,
+ override_queries: None,
+ make_codegen_backend,
+ registry: diagnostics_registry(),
+ };
+
+ match make_input(config.opts.error_format, &matches.free) {
+ Err(reported) => return Err(reported),
+ Ok(Some(input)) => {
+ config.input = input;
+
+ callbacks.config(&mut config);
+ }
+ Ok(None) => match matches.free.len() {
+ 0 => {
+ callbacks.config(&mut config);
+ interface::run_compiler(config, |compiler| {
+ let sopts = &compiler.session().opts;
+ if sopts.describe_lints {
+ let mut lint_store =
+ rustc_lint::new_lint_store(compiler.session().enable_internal_lints());
+ let registered_lints =
+ if let Some(register_lints) = compiler.register_lints() {
+ register_lints(compiler.session(), &mut lint_store);
+ true
+ } else {
+ false
+ };
+ describe_lints(compiler.session(), &lint_store, registered_lints);
+ return;
+ }
+ let should_stop =
+ print_crate_info(&***compiler.codegen_backend(), compiler.session(), false);
+
+ if should_stop == Compilation::Stop {
+ return;
+ }
+ early_error(sopts.error_format, "no input filename given")
+ });
+ return Ok(());
+ }
+ 1 => panic!("make_input should have provided valid inputs"),
+ _ => early_error(
+ config.opts.error_format,
+ &format!(
+ "multiple input filenames provided (first two filenames are `{}` and `{}`)",
+ matches.free[0], matches.free[1],
+ ),
+ ),
+ },
+ };
+
+ interface::run_compiler(config, |compiler| {
+ let sess = compiler.session();
+ let should_stop = print_crate_info(&***compiler.codegen_backend(), sess, true)
+ .and_then(|| list_metadata(sess, &*compiler.codegen_backend().metadata_loader()))
+ .and_then(|| try_process_rlink(sess, compiler));
+
+ if should_stop == Compilation::Stop {
+ return sess.compile_status();
+ }
+
+ let linker = compiler.enter(|queries| {
+ let early_exit = || sess.compile_status().map(|_| None);
+ queries.parse()?;
+
+ if let Some(ppm) = &sess.opts.pretty {
+ if ppm.needs_ast_map() {
+ queries.global_ctxt()?.enter(|tcx| {
+ pretty::print_after_hir_lowering(tcx, *ppm);
+ Ok(())
+ })?;
+ } else {
+ let krate = queries.parse()?.steal();
+ pretty::print_after_parsing(sess, &krate, *ppm);
+ }
+ trace!("finished pretty-printing");
+ return early_exit();
+ }
+
+ if callbacks.after_parsing(compiler, queries) == Compilation::Stop {
+ return early_exit();
+ }
+
+ if sess.opts.unstable_opts.parse_only || sess.opts.unstable_opts.show_span.is_some() {
+ return early_exit();
+ }
+
+ {
+ let plugins = queries.register_plugins()?;
+ let (_, lint_store) = &*plugins.borrow();
+
+ // Lint plugins are registered; now we can process command line flags.
+ if sess.opts.describe_lints {
+ describe_lints(sess, lint_store, true);
+ return early_exit();
+ }
+ }
+
+ // Make sure name resolution and macro expansion is run.
+ queries.global_ctxt()?.enter(|tcx| tcx.resolver_for_lowering(()));
+
+ if callbacks.after_expansion(compiler, queries) == Compilation::Stop {
+ return early_exit();
+ }
+
+ // Make sure the `output_filenames` query is run for its side
+ // effects of writing the dep-info and reporting errors.
+ queries.global_ctxt()?.enter(|tcx| tcx.output_filenames(()));
+
+ if sess.opts.output_types.contains_key(&OutputType::DepInfo)
+ && sess.opts.output_types.len() == 1
+ {
+ return early_exit();
+ }
+
+ if sess.opts.unstable_opts.no_analysis {
+ return early_exit();
+ }
+
+ queries.global_ctxt()?.enter(|tcx| tcx.analysis(()))?;
+
+ if callbacks.after_analysis(compiler, queries) == Compilation::Stop {
+ return early_exit();
+ }
+
+ queries.ongoing_codegen()?;
+
+ if sess.opts.unstable_opts.print_type_sizes {
+ sess.code_stats.print_type_sizes();
+ }
+
+ let linker = queries.linker()?;
+ Ok(Some(linker))
+ })?;
+
+ if let Some(linker) = linker {
+ let _timer = sess.timer("link");
+ linker.link()?
+ }
+
+ if sess.opts.unstable_opts.perf_stats {
+ sess.print_perf_stats();
+ }
+
+ if sess.opts.unstable_opts.print_fuel.is_some() {
+ eprintln!(
+ "Fuel used by {}: {}",
+ sess.opts.unstable_opts.print_fuel.as_ref().unwrap(),
+ sess.print_fuel.load(SeqCst)
+ );
+ }
+
+ Ok(())
+ })
+}
+
+// Extract output directory and file from matches.
+fn make_output(matches: &getopts::Matches) -> (Option<PathBuf>, Option<PathBuf>) {
+ let odir = matches.opt_str("out-dir").map(|o| PathBuf::from(&o));
+ let ofile = matches.opt_str("o").map(|o| PathBuf::from(&o));
+ (odir, ofile)
+}
+
+// Extract input (string or file and optional path) from matches.
+fn make_input(
+ error_format: ErrorOutputType,
+ free_matches: &[String],
+) -> Result<Option<Input>, ErrorGuaranteed> {
+ if free_matches.len() == 1 {
+ let ifile = &free_matches[0];
+ if ifile == "-" {
+ let mut src = String::new();
+ if io::stdin().read_to_string(&mut src).is_err() {
+ // Immediately stop compilation if there was an issue reading
+ // the input (for example if the input stream is not UTF-8).
+ let reported = early_error_no_abort(
+ error_format,
+ "couldn't read from stdin, as it did not contain valid UTF-8",
+ );
+ return Err(reported);
+ }
+ if let Ok(path) = env::var("UNSTABLE_RUSTDOC_TEST_PATH") {
+ let line = env::var("UNSTABLE_RUSTDOC_TEST_LINE").expect(
+ "when UNSTABLE_RUSTDOC_TEST_PATH is set \
+ UNSTABLE_RUSTDOC_TEST_LINE also needs to be set",
+ );
+ let line = isize::from_str_radix(&line, 10)
+ .expect("UNSTABLE_RUSTDOC_TEST_LINE needs to be an number");
+ let file_name = FileName::doc_test_source_code(PathBuf::from(path), line);
+ Ok(Some(Input::Str { name: file_name, input: src }))
+ } else {
+ Ok(Some(Input::Str { name: FileName::anon_source_code(&src), input: src }))
+ }
+ } else {
+ Ok(Some(Input::File(PathBuf::from(ifile))))
+ }
+ } else {
+ Ok(None)
+ }
+}
+
+/// Whether to stop or continue compilation.
+#[derive(Copy, Clone, Debug, Eq, PartialEq)]
+pub enum Compilation {
+ Stop,
+ Continue,
+}
+
+impl Compilation {
+ pub fn and_then<F: FnOnce() -> Compilation>(self, next: F) -> Compilation {
+ match self {
+ Compilation::Stop => Compilation::Stop,
+ Compilation::Continue => next(),
+ }
+ }
+}
+
+fn handle_explain(registry: Registry, code: &str, output: ErrorOutputType) {
+ let upper_cased_code = code.to_ascii_uppercase();
+ let normalised =
+ if upper_cased_code.starts_with('E') { upper_cased_code } else { format!("E{code:0>4}") };
+ match registry.try_find_description(&normalised) {
+ Ok(description) => {
+ let mut is_in_code_block = false;
+ let mut text = String::new();
+ // Slice off the leading newline and print.
+ for line in description.lines() {
+ let indent_level =
+ line.find(|c: char| !c.is_whitespace()).unwrap_or_else(|| line.len());
+ let dedented_line = &line[indent_level..];
+ if dedented_line.starts_with("```") {
+ is_in_code_block = !is_in_code_block;
+ text.push_str(&line[..(indent_level + 3)]);
+ } else if is_in_code_block && dedented_line.starts_with("# ") {
+ continue;
+ } else {
+ text.push_str(line);
+ }
+ text.push('\n');
+ }
+ if io::stdout().is_terminal() {
+ show_content_with_pager(&text);
+ } else {
+ print!("{text}");
+ }
+ }
+ Err(InvalidErrorCode) => {
+ early_error(output, &format!("{code} is not a valid error code"));
+ }
+ }
+}
+
+fn show_content_with_pager(content: &str) {
+ let pager_name = env::var_os("PAGER").unwrap_or_else(|| {
+ if cfg!(windows) { OsString::from("more.com") } else { OsString::from("less") }
+ });
+
+ let mut fallback_to_println = false;
+
+ match Command::new(pager_name).stdin(Stdio::piped()).spawn() {
+ Ok(mut pager) => {
+ if let Some(pipe) = pager.stdin.as_mut() {
+ if pipe.write_all(content.as_bytes()).is_err() {
+ fallback_to_println = true;
+ }
+ }
+
+ if pager.wait().is_err() {
+ fallback_to_println = true;
+ }
+ }
+ Err(_) => {
+ fallback_to_println = true;
+ }
+ }
+
+ // If pager fails for whatever reason, we should still print the content
+ // to standard output
+ if fallback_to_println {
+ print!("{content}");
+ }
+}
+
+pub fn try_process_rlink(sess: &Session, compiler: &interface::Compiler) -> Compilation {
+ if sess.opts.unstable_opts.link_only {
+ if let Input::File(file) = &sess.io.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 rlink_data = fs::read(file).unwrap_or_else(|err| {
+ sess.emit_fatal(RlinkUnableToRead { err });
+ });
+ let codegen_results = match CodegenResults::deserialize_rlink(rlink_data) {
+ Ok(codegen) => codegen,
+ Err(err) => {
+ match err {
+ CodegenErrors::WrongFileType => sess.emit_fatal(RLinkWrongFileType),
+ CodegenErrors::EmptyVersionNumber => {
+ sess.emit_fatal(RLinkEmptyVersionNumber)
+ }
+ CodegenErrors::EncodingVersionMismatch { version_array, rlink_version } => {
+ sess.emit_fatal(RLinkEncodingVersionMismatch {
+ version_array,
+ rlink_version,
+ })
+ }
+ CodegenErrors::RustcVersionMismatch { rustc_version, current_version } => {
+ sess.emit_fatal(RLinkRustcVersionMismatch {
+ rustc_version,
+ current_version,
+ })
+ }
+ };
+ }
+ };
+ let result = compiler.codegen_backend().link(sess, codegen_results, &outputs);
+ abort_on_err(result, sess);
+ } else {
+ sess.emit_fatal(RlinkNotAFile {})
+ }
+ Compilation::Stop
+ } else {
+ Compilation::Continue
+ }
+}
+
+pub fn list_metadata(sess: &Session, metadata_loader: &dyn MetadataLoader) -> Compilation {
+ if sess.opts.unstable_opts.ls {
+ match sess.io.input {
+ Input::File(ref ifile) => {
+ let path = &(*ifile);
+ let mut v = Vec::new();
+ locator::list_file_metadata(&sess.target, path, metadata_loader, &mut v).unwrap();
+ println!("{}", String::from_utf8(v).unwrap());
+ }
+ Input::Str { .. } => {
+ early_error(ErrorOutputType::default(), "cannot list metadata for stdin");
+ }
+ }
+ return Compilation::Stop;
+ }
+
+ Compilation::Continue
+}
+
+fn print_crate_info(
+ codegen_backend: &dyn CodegenBackend,
+ sess: &Session,
+ parse_attrs: bool,
+) -> Compilation {
+ use rustc_session::config::PrintRequest::*;
+ // NativeStaticLibs and LinkArgs are special - printed during linking
+ // (empty iterator returns true)
+ if sess.opts.prints.iter().all(|&p| p == NativeStaticLibs || p == LinkArgs) {
+ return Compilation::Continue;
+ }
+
+ let attrs = if parse_attrs {
+ let result = parse_crate_attrs(sess);
+ match result {
+ Ok(attrs) => Some(attrs),
+ Err(mut parse_error) => {
+ parse_error.emit();
+ return Compilation::Stop;
+ }
+ }
+ } else {
+ None
+ };
+ for req in &sess.opts.prints {
+ match *req {
+ TargetList => {
+ let mut targets = rustc_target::spec::TARGETS.to_vec();
+ targets.sort_unstable();
+ println!("{}", targets.join("\n"));
+ }
+ Sysroot => println!("{}", sess.sysroot.display()),
+ TargetLibdir => println!("{}", sess.target_tlib_path.dir.display()),
+ TargetSpec => {
+ println!("{}", serde_json::to_string_pretty(&sess.target.to_json()).unwrap());
+ }
+ FileNames | CrateName => {
+ let Some(attrs) = attrs.as_ref() else {
+ // no crate attributes, print out an error and exit
+ return Compilation::Continue;
+ };
+ let t_outputs = rustc_interface::util::build_output_filenames(attrs, sess);
+ let id = rustc_session::output::find_crate_name(sess, attrs);
+ if *req == PrintRequest::CrateName {
+ println!("{id}");
+ continue;
+ }
+ let crate_types = collect_crate_types(sess, attrs);
+ for &style in &crate_types {
+ let fname =
+ rustc_session::output::filename_for_input(sess, style, id, &t_outputs);
+ println!("{}", fname.file_name().unwrap().to_string_lossy());
+ }
+ }
+ Cfg => {
+ let mut cfgs = sess
+ .parse_sess
+ .config
+ .iter()
+ .filter_map(|&(name, value)| {
+ // Note that crt-static is a specially recognized cfg
+ // directive that's printed out here as part of
+ // rust-lang/rust#37406, but in general the
+ // `target_feature` cfg is gated under
+ // rust-lang/rust#29717. For now this is just
+ // specifically allowing the crt-static cfg and that's
+ // it, this is intended to get into Cargo and then go
+ // through to build scripts.
+ if (name != sym::target_feature || value != Some(sym::crt_dash_static))
+ && !sess.is_nightly_build()
+ && find_gated_cfg(|cfg_sym| cfg_sym == name).is_some()
+ {
+ return None;
+ }
+
+ if let Some(value) = value {
+ Some(format!("{name}=\"{value}\""))
+ } else {
+ Some(name.to_string())
+ }
+ })
+ .collect::<Vec<String>>();
+
+ cfgs.sort();
+ for cfg in cfgs {
+ println!("{cfg}");
+ }
+ }
+ CallingConventions => {
+ let mut calling_conventions = rustc_target::spec::abi::all_names();
+ calling_conventions.sort_unstable();
+ println!("{}", calling_conventions.join("\n"));
+ }
+ RelocationModels
+ | CodeModels
+ | TlsModels
+ | TargetCPUs
+ | StackProtectorStrategies
+ | TargetFeatures => {
+ codegen_backend.print(*req, sess);
+ }
+ // Any output here interferes with Cargo's parsing of other printed output
+ NativeStaticLibs => {}
+ LinkArgs => {}
+ SplitDebuginfo => {
+ use rustc_target::spec::SplitDebuginfo::{Off, Packed, Unpacked};
+
+ for split in &[Off, Packed, Unpacked] {
+ let stable = sess.target.options.supported_split_debuginfo.contains(split);
+ let unstable_ok = sess.unstable_options();
+ if stable || unstable_ok {
+ println!("{split}");
+ }
+ }
+ }
+ }
+ }
+ Compilation::Stop
+}
+
+/// Prints version information
+///
+/// NOTE: this is a macro to support drivers built at a different time than the main `rustc_driver` crate.
+pub macro version($binary: literal, $matches: expr) {
+ fn unw(x: Option<&str>) -> &str {
+ x.unwrap_or("unknown")
+ }
+ $crate::version_at_macro_invocation(
+ $binary,
+ $matches,
+ unw(option_env!("CFG_VERSION")),
+ unw(option_env!("CFG_VER_HASH")),
+ unw(option_env!("CFG_VER_DATE")),
+ unw(option_env!("CFG_RELEASE")),
+ )
+}
+
+#[doc(hidden)] // use the macro instead
+pub fn version_at_macro_invocation(
+ binary: &str,
+ matches: &getopts::Matches,
+ version: &str,
+ commit_hash: &str,
+ commit_date: &str,
+ release: &str,
+) {
+ let verbose = matches.opt_present("verbose");
+
+ println!("{binary} {version}");
+
+ if verbose {
+ println!("binary: {binary}");
+ println!("commit-hash: {commit_hash}");
+ println!("commit-date: {commit_date}");
+ println!("host: {}", config::host_triple());
+ println!("release: {release}");
+
+ let debug_flags = matches.opt_strs("Z");
+ let backend_name = debug_flags.iter().find_map(|x| x.strip_prefix("codegen-backend="));
+ get_codegen_backend(&None, backend_name).print_version();
+ }
+}
+
+fn usage(verbose: bool, include_unstable_options: bool, nightly_build: bool) {
+ let groups = if verbose { config::rustc_optgroups() } else { config::rustc_short_optgroups() };
+ let mut options = getopts::Options::new();
+ for option in groups.iter().filter(|x| include_unstable_options || x.is_stable()) {
+ (option.apply)(&mut options);
+ }
+ let message = "Usage: rustc [OPTIONS] INPUT";
+ let nightly_help = if nightly_build {
+ "\n -Z help Print unstable compiler options"
+ } else {
+ ""
+ };
+ let verbose_help = if verbose {
+ ""
+ } else {
+ "\n --help -v Print the full set of options rustc accepts"
+ };
+ let at_path = if verbose {
+ " @path Read newline separated options from `path`\n"
+ } else {
+ ""
+ };
+ println!(
+ "{options}{at_path}\nAdditional help:
+ -C help Print codegen options
+ -W help \
+ Print 'lint' options and default settings{nightly}{verbose}\n",
+ options = options.usage(message),
+ at_path = at_path,
+ nightly = nightly_help,
+ verbose = verbose_help
+ );
+}
+
+fn print_wall_help() {
+ println!(
+ "
+The flag `-Wall` does not exist in `rustc`. Most useful lints are enabled by
+default. Use `rustc -W help` to see all available lints. It's more common to put
+warning settings in the crate root using `#![warn(LINT_NAME)]` instead of using
+the command line flag directly.
+"
+ );
+}
+
+/// Write to stdout lint command options, together with a list of all available lints
+pub fn describe_lints(sess: &Session, lint_store: &LintStore, loaded_plugins: bool) {
+ println!(
+ "
+Available lint options:
+ -W <foo> Warn about <foo>
+ -A <foo> \
+ Allow <foo>
+ -D <foo> Deny <foo>
+ -F <foo> Forbid <foo> \
+ (deny <foo> and all attempts to override)
+
+"
+ );
+
+ fn sort_lints(sess: &Session, mut lints: Vec<&'static Lint>) -> Vec<&'static Lint> {
+ // The sort doesn't case-fold but it's doubtful we care.
+ lints.sort_by_cached_key(|x: &&Lint| (x.default_level(sess.edition()), x.name));
+ lints
+ }
+
+ fn sort_lint_groups(
+ lints: Vec<(&'static str, Vec<LintId>, bool)>,
+ ) -> Vec<(&'static str, Vec<LintId>)> {
+ let mut lints: Vec<_> = lints.into_iter().map(|(x, y, _)| (x, y)).collect();
+ lints.sort_by_key(|l| l.0);
+ lints
+ }
+
+ let (plugin, builtin): (Vec<_>, _) =
+ lint_store.get_lints().iter().cloned().partition(|&lint| lint.is_plugin);
+ let plugin = sort_lints(sess, plugin);
+ let builtin = sort_lints(sess, builtin);
+
+ let (plugin_groups, builtin_groups): (Vec<_>, _) =
+ lint_store.get_lint_groups().partition(|&(.., p)| p);
+ let plugin_groups = sort_lint_groups(plugin_groups);
+ let builtin_groups = sort_lint_groups(builtin_groups);
+
+ let max_name_len =
+ plugin.iter().chain(&builtin).map(|&s| s.name.chars().count()).max().unwrap_or(0);
+ let padded = |x: &str| {
+ let mut s = " ".repeat(max_name_len - x.chars().count());
+ s.push_str(x);
+ s
+ };
+
+ println!("Lint checks provided by rustc:\n");
+
+ let print_lints = |lints: Vec<&Lint>| {
+ println!(" {} {:7.7} {}", padded("name"), "default", "meaning");
+ println!(" {} {:7.7} {}", padded("----"), "-------", "-------");
+ for lint in lints {
+ let name = lint.name_lower().replace('_', "-");
+ println!(
+ " {} {:7.7} {}",
+ padded(&name),
+ lint.default_level(sess.edition()).as_str(),
+ lint.desc
+ );
+ }
+ println!("\n");
+ };
+
+ print_lints(builtin);
+
+ let max_name_len = max(
+ "warnings".len(),
+ plugin_groups
+ .iter()
+ .chain(&builtin_groups)
+ .map(|&(s, _)| s.chars().count())
+ .max()
+ .unwrap_or(0),
+ );
+
+ let padded = |x: &str| {
+ let mut s = " ".repeat(max_name_len - x.chars().count());
+ s.push_str(x);
+ s
+ };
+
+ println!("Lint groups provided by rustc:\n");
+
+ let print_lint_groups = |lints: Vec<(&'static str, Vec<LintId>)>, all_warnings| {
+ println!(" {} sub-lints", padded("name"));
+ println!(" {} ---------", padded("----"));
+
+ if all_warnings {
+ println!(" {} all lints that are set to issue warnings", padded("warnings"));
+ }
+
+ for (name, to) in lints {
+ let name = name.to_lowercase().replace('_', "-");
+ let desc = to
+ .into_iter()
+ .map(|x| x.to_string().replace('_', "-"))
+ .collect::<Vec<String>>()
+ .join(", ");
+ println!(" {} {}", padded(&name), desc);
+ }
+ println!("\n");
+ };
+
+ print_lint_groups(builtin_groups, true);
+
+ match (loaded_plugins, plugin.len(), plugin_groups.len()) {
+ (false, 0, _) | (false, _, 0) => {
+ println!("Lint tools like Clippy can provide additional lints and lint groups.");
+ }
+ (false, ..) => panic!("didn't load lint plugins but got them anyway!"),
+ (true, 0, 0) => println!("This crate does not load any lint plugins or lint groups."),
+ (true, l, g) => {
+ if l > 0 {
+ println!("Lint checks provided by plugins loaded by this crate:\n");
+ print_lints(plugin);
+ }
+ if g > 0 {
+ println!("Lint groups provided by plugins loaded by this crate:\n");
+ print_lint_groups(plugin_groups, false);
+ }
+ }
+ }
+}
+
+fn describe_debug_flags() {
+ println!("\nAvailable options:\n");
+ print_flag_list("-Z", config::Z_OPTIONS);
+}
+
+fn describe_codegen_flags() {
+ println!("\nAvailable codegen options:\n");
+ print_flag_list("-C", config::CG_OPTIONS);
+}
+
+pub fn print_flag_list<T>(
+ cmdline_opt: &str,
+ flag_list: &[(&'static str, T, &'static str, &'static str)],
+) {
+ let max_len = flag_list.iter().map(|&(name, _, _, _)| name.chars().count()).max().unwrap_or(0);
+
+ for &(name, _, _, desc) in flag_list {
+ println!(
+ " {} {:>width$}=val -- {}",
+ cmdline_opt,
+ name.replace('_', "-"),
+ desc,
+ width = max_len
+ );
+ }
+}
+
+/// Process command line options. Emits messages as appropriate. If compilation
+/// should continue, returns a getopts::Matches object parsed from args,
+/// otherwise returns `None`.
+///
+/// The compiler's handling of options is a little complicated as it ties into
+/// our stability story. The current intention of each compiler option is to
+/// have one of two modes:
+///
+/// 1. An option is stable and can be used everywhere.
+/// 2. An option is unstable, and can only be used on nightly.
+///
+/// Like unstable library and language features, however, unstable options have
+/// always required a form of "opt in" to indicate that you're using them. This
+/// provides the easy ability to scan a code base to check to see if anything
+/// unstable is being used. Currently, this "opt in" is the `-Z` "zed" flag.
+///
+/// All options behind `-Z` are considered unstable by default. Other top-level
+/// options can also be considered unstable, and they were unlocked through the
+/// `-Z unstable-options` flag. Note that `-Z` remains to be the root of
+/// instability in both cases, though.
+///
+/// So with all that in mind, the comments below have some more detail about the
+/// contortions done here to get things to work out correctly.
+pub fn handle_options(args: &[String]) -> Option<getopts::Matches> {
+ // Throw away the first argument, the name of the binary
+ let args = &args[1..];
+
+ if args.is_empty() {
+ // user did not write `-v` nor `-Z unstable-options`, so do not
+ // include that extra information.
+ let nightly_build =
+ rustc_feature::UnstableFeatures::from_environment(None).is_nightly_build();
+ usage(false, false, nightly_build);
+ return None;
+ }
+
+ // Parse with *all* options defined in the compiler, we don't worry about
+ // option stability here we just want to parse as much as possible.
+ let mut options = getopts::Options::new();
+ for option in config::rustc_optgroups() {
+ (option.apply)(&mut options);
+ }
+ let matches = options.parse(args).unwrap_or_else(|e| {
+ let msg = match e {
+ getopts::Fail::UnrecognizedOption(ref opt) => CG_OPTIONS
+ .iter()
+ .map(|&(name, ..)| ('C', name))
+ .chain(Z_OPTIONS.iter().map(|&(name, ..)| ('Z', name)))
+ .find(|&(_, name)| *opt == name.replace('_', "-"))
+ .map(|(flag, _)| format!("{e}. Did you mean `-{flag} {opt}`?")),
+ _ => None,
+ };
+ early_error(ErrorOutputType::default(), &msg.unwrap_or_else(|| e.to_string()));
+ });
+
+ // For all options we just parsed, we check a few aspects:
+ //
+ // * If the option is stable, we're all good
+ // * If the option wasn't passed, we're all good
+ // * If `-Z unstable-options` wasn't passed (and we're not a -Z option
+ // ourselves), then we require the `-Z unstable-options` flag to unlock
+ // this option that was passed.
+ // * If we're a nightly compiler, then unstable options are now unlocked, so
+ // we're good to go.
+ // * Otherwise, if we're an unstable option then we generate an error
+ // (unstable option being used on stable)
+ nightly_options::check_nightly_options(&matches, &config::rustc_optgroups());
+
+ if matches.opt_present("h") || matches.opt_present("help") {
+ // Only show unstable options in --help if we accept unstable options.
+ let unstable_enabled = nightly_options::is_unstable_enabled(&matches);
+ let nightly_build = nightly_options::match_is_nightly_build(&matches);
+ usage(matches.opt_present("verbose"), unstable_enabled, nightly_build);
+ return None;
+ }
+
+ // Handle the special case of -Wall.
+ let wall = matches.opt_strs("W");
+ if wall.iter().any(|x| *x == "all") {
+ print_wall_help();
+ rustc_errors::FatalError.raise();
+ }
+
+ // Don't handle -W help here, because we might first load plugins.
+ let debug_flags = matches.opt_strs("Z");
+ if debug_flags.iter().any(|x| *x == "help") {
+ describe_debug_flags();
+ return None;
+ }
+
+ let cg_flags = matches.opt_strs("C");
+
+ if cg_flags.iter().any(|x| *x == "help") {
+ describe_codegen_flags();
+ return None;
+ }
+
+ if cg_flags.iter().any(|x| *x == "no-stack-check") {
+ early_warn(
+ ErrorOutputType::default(),
+ "the --no-stack-check flag is deprecated and does nothing",
+ );
+ }
+
+ if cg_flags.iter().any(|x| *x == "passes=list") {
+ let backend_name = debug_flags.iter().find_map(|x| x.strip_prefix("codegen-backend="));
+ get_codegen_backend(&None, backend_name).print_passes();
+ return None;
+ }
+
+ if matches.opt_present("version") {
+ version!("rustc", &matches);
+ return None;
+ }
+
+ Some(matches)
+}
+
+fn parse_crate_attrs<'a>(sess: &'a Session) -> PResult<'a, ast::AttrVec> {
+ match &sess.io.input {
+ Input::File(ifile) => rustc_parse::parse_crate_attrs_from_file(ifile, &sess.parse_sess),
+ Input::Str { name, input } => rustc_parse::parse_crate_attrs_from_source_str(
+ name.clone(),
+ input.clone(),
+ &sess.parse_sess,
+ ),
+ }
+}
+
+/// Gets a list of extra command-line flags provided by the user, as strings.
+///
+/// This function is used during ICEs to show more information useful for
+/// debugging, since some ICEs only happens with non-default compiler flags
+/// (and the users don't always report them).
+fn extra_compiler_flags() -> Option<(Vec<String>, bool)> {
+ let mut args = env::args_os().map(|arg| arg.to_string_lossy().to_string()).peekable();
+
+ let mut result = Vec::new();
+ let mut excluded_cargo_defaults = false;
+ while let Some(arg) = args.next() {
+ if let Some(a) = ICE_REPORT_COMPILER_FLAGS.iter().find(|a| arg.starts_with(*a)) {
+ let content = if arg.len() == a.len() {
+ // A space-separated option, like `-C incremental=foo` or `--crate-type rlib`
+ match args.next() {
+ Some(arg) => arg.to_string(),
+ None => continue,
+ }
+ } else if arg.get(a.len()..a.len() + 1) == Some("=") {
+ // An equals option, like `--crate-type=rlib`
+ arg[a.len() + 1..].to_string()
+ } else {
+ // A non-space option, like `-Cincremental=foo`
+ arg[a.len()..].to_string()
+ };
+ let option = content.split_once('=').map(|s| s.0).unwrap_or(&content);
+ if ICE_REPORT_COMPILER_FLAGS_EXCLUDE.iter().any(|exc| option == *exc) {
+ excluded_cargo_defaults = true;
+ } else {
+ result.push(a.to_string());
+ match ICE_REPORT_COMPILER_FLAGS_STRIP_VALUE.iter().find(|s| option == **s) {
+ Some(s) => result.push(format!("{s}=[REDACTED]")),
+ None => result.push(content),
+ }
+ }
+ }
+ }
+
+ if !result.is_empty() { Some((result, excluded_cargo_defaults)) } else { None }
+}
+
+/// Runs a closure and catches unwinds triggered by fatal errors.
+///
+/// The compiler currently unwinds with a special sentinel value to abort
+/// compilation on fatal errors. This function catches that sentinel and turns
+/// the panic into a `Result` instead.
+pub fn catch_fatal_errors<F: FnOnce() -> R, R>(f: F) -> Result<R, ErrorGuaranteed> {
+ catch_unwind(panic::AssertUnwindSafe(f)).map_err(|value| {
+ if value.is::<rustc_errors::FatalErrorMarker>() {
+ ErrorGuaranteed::unchecked_claim_error_was_emitted()
+ } else {
+ panic::resume_unwind(value);
+ }
+ })
+}
+
+/// Variant of `catch_fatal_errors` for the `interface::Result` return type
+/// that also computes the exit code.
+pub fn catch_with_exit_code(f: impl FnOnce() -> interface::Result<()>) -> i32 {
+ let result = catch_fatal_errors(f).and_then(|result| result);
+ match result {
+ Ok(()) => EXIT_SUCCESS,
+ Err(_) => EXIT_FAILURE,
+ }
+}
+
+static DEFAULT_HOOK: LazyLock<Box<dyn Fn(&panic::PanicInfo<'_>) + Sync + Send + 'static>> =
+ LazyLock::new(|| {
+ let hook = panic::take_hook();
+ panic::set_hook(Box::new(|info| {
+ // If the error was caused by a broken pipe then this is not a bug.
+ // Write the error and return immediately. See #98700.
+ #[cfg(windows)]
+ if let Some(msg) = info.payload().downcast_ref::<String>() {
+ if msg.starts_with("failed printing to stdout: ") && msg.ends_with("(os error 232)")
+ {
+ early_error_no_abort(ErrorOutputType::default(), &msg);
+ return;
+ }
+ };
+
+ // Invoke the default handler, which prints the actual panic message and optionally a backtrace
+ // Don't do this for delayed bugs, which already emit their own more useful backtrace.
+ if !info.payload().is::<rustc_errors::DelayedBugPanic>() {
+ (*DEFAULT_HOOK)(info);
+
+ // Separate the output with an empty line
+ eprintln!();
+ }
+
+ // Print the ICE message
+ report_ice(info, BUG_REPORT_URL);
+ }));
+ hook
+ });
+
+/// Prints the ICE message, including query stack, but without backtrace.
+///
+/// The message will point the user at `bug_report_url` to report the ICE.
+///
+/// When `install_ice_hook` is called, this function will be called as the panic
+/// hook.
+pub fn report_ice(info: &panic::PanicInfo<'_>, bug_report_url: &str) {
+ let fallback_bundle =
+ rustc_errors::fallback_fluent_bundle(crate::DEFAULT_LOCALE_RESOURCES.to_vec(), false);
+ let emitter = Box::new(rustc_errors::emitter::EmitterWriter::stderr(
+ rustc_errors::ColorConfig::Auto,
+ None,
+ None,
+ fallback_bundle,
+ false,
+ false,
+ None,
+ false,
+ false,
+ TerminalUrl::No,
+ ));
+ let handler = rustc_errors::Handler::with_emitter(true, None, emitter);
+
+ // a .span_bug or .bug call has already printed what
+ // it wants to print.
+ if !info.payload().is::<rustc_errors::ExplicitBug>()
+ && !info.payload().is::<rustc_errors::DelayedBugPanic>()
+ {
+ handler.emit_err(session_diagnostics::Ice);
+ }
+
+ handler.emit_note(session_diagnostics::IceBugReport { bug_report_url });
+ handler.emit_note(session_diagnostics::IceVersion {
+ version: util::version_str!().unwrap_or("unknown_version"),
+ triple: config::host_triple(),
+ });
+
+ if let Some((flags, excluded_cargo_defaults)) = extra_compiler_flags() {
+ handler.emit_note(session_diagnostics::IceFlags { flags: flags.join(" ") });
+ if excluded_cargo_defaults {
+ handler.emit_note(session_diagnostics::IceExcludeCargoDefaults);
+ }
+ }
+
+ // If backtraces are enabled, also print the query stack
+ let backtrace = env::var_os("RUST_BACKTRACE").map_or(false, |x| &x != "0");
+
+ let num_frames = if backtrace { None } else { Some(2) };
+
+ interface::try_print_query_stack(&handler, num_frames);
+
+ #[cfg(windows)]
+ unsafe {
+ if env::var("RUSTC_BREAK_ON_ICE").is_ok() {
+ // Trigger a debugger if we crashed during bootstrap
+ winapi::um::debugapi::DebugBreak();
+ }
+ }
+}
+
+/// Installs a panic hook that will print the ICE message on unexpected panics.
+///
+/// A custom rustc driver can skip calling this to set up a custom ICE hook.
+pub fn install_ice_hook() {
+ // If the user has not explicitly overridden "RUST_BACKTRACE", then produce
+ // full backtraces. When a compiler ICE happens, we want to gather
+ // as much information as possible to present in the issue opened
+ // by the user. Compiler developers and other rustc users can
+ // opt in to less-verbose backtraces by manually setting "RUST_BACKTRACE"
+ // (e.g. `RUST_BACKTRACE=1`)
+ if std::env::var("RUST_BACKTRACE").is_err() {
+ std::env::set_var("RUST_BACKTRACE", "full");
+ }
+ LazyLock::force(&DEFAULT_HOOK);
+}
+
+/// This allows tools to enable rust logging without having to magically match rustc's
+/// tracing crate version.
+pub fn init_rustc_env_logger() {
+ init_env_logger("RUSTC_LOG");
+}
+
+/// This allows tools to enable rust logging without having to magically match rustc's
+/// 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) {
+ if let Err(error) = rustc_log::init_env_logger(env) {
+ early_error(ErrorOutputType::default(), &error.to_string());
+ }
+}
+
+#[cfg(all(unix, any(target_env = "gnu", target_os = "macos")))]
+mod signal_handler {
+ extern "C" {
+ fn backtrace_symbols_fd(
+ buffer: *const *mut libc::c_void,
+ size: libc::c_int,
+ fd: libc::c_int,
+ );
+ }
+
+ extern "C" fn print_stack_trace(_: libc::c_int) {
+ const MAX_FRAMES: usize = 256;
+ static mut STACK_TRACE: [*mut libc::c_void; MAX_FRAMES] =
+ [std::ptr::null_mut(); MAX_FRAMES];
+ unsafe {
+ let depth = libc::backtrace(STACK_TRACE.as_mut_ptr(), MAX_FRAMES as i32);
+ if depth == 0 {
+ return;
+ }
+ backtrace_symbols_fd(STACK_TRACE.as_ptr(), depth, 2);
+ }
+ }
+
+ /// When an error signal (such as SIGABRT or SIGSEGV) is delivered to the
+ /// process, print a stack trace and then exit.
+ pub(super) fn install() {
+ unsafe {
+ const ALT_STACK_SIZE: usize = libc::MINSIGSTKSZ + 64 * 1024;
+ let mut alt_stack: libc::stack_t = std::mem::zeroed();
+ alt_stack.ss_sp =
+ std::alloc::alloc(std::alloc::Layout::from_size_align(ALT_STACK_SIZE, 1).unwrap())
+ as *mut libc::c_void;
+ alt_stack.ss_size = ALT_STACK_SIZE;
+ libc::sigaltstack(&alt_stack, std::ptr::null_mut());
+
+ let mut sa: libc::sigaction = std::mem::zeroed();
+ sa.sa_sigaction = print_stack_trace as libc::sighandler_t;
+ sa.sa_flags = libc::SA_NODEFER | libc::SA_RESETHAND | libc::SA_ONSTACK;
+ libc::sigemptyset(&mut sa.sa_mask);
+ libc::sigaction(libc::SIGSEGV, &sa, std::ptr::null_mut());
+ }
+ }
+}
+
+#[cfg(not(all(unix, any(target_env = "gnu", target_os = "macos"))))]
+mod signal_handler {
+ pub(super) fn install() {}
+}
+
+pub fn main() -> ! {
+ let start_time = Instant::now();
+ let start_rss = get_resident_set_size();
+ init_rustc_env_logger();
+ signal_handler::install();
+ let mut callbacks = TimePassesCallbacks::default();
+ install_ice_hook();
+ let exit_code = catch_with_exit_code(|| {
+ let args = env::args_os()
+ .enumerate()
+ .map(|(i, arg)| {
+ arg.into_string().unwrap_or_else(|arg| {
+ early_error(
+ ErrorOutputType::default(),
+ &format!("argument {i} is not valid Unicode: {arg:?}"),
+ )
+ })
+ })
+ .collect::<Vec<_>>();
+ RunCompiler::new(&args, &mut callbacks).run()
+ });
+
+ if callbacks.time_passes {
+ let end_rss = get_resident_set_size();
+ print_time_passes_entry("total", start_time.elapsed(), start_rss, end_rss);
+ }
+
+ process::exit(exit_code)
+}
diff --git a/compiler/rustc_driver/src/pretty.rs b/compiler/rustc_driver_impl/src/pretty.rs
index ae3ac8625..446c6832c 100644
--- a/compiler/rustc_driver/src/pretty.rs
+++ b/compiler/rustc_driver_impl/src/pretty.rs
@@ -403,7 +403,7 @@ pub fn print_after_parsing(sess: &Session, krate: &ast::Crate, ppm: PpMode) {
write_or_print(&out, sess);
}
-pub fn print_after_hir_lowering<'tcx>(tcx: TyCtxt<'tcx>, krate: &ast::Crate, ppm: PpMode) {
+pub fn print_after_hir_lowering<'tcx>(tcx: TyCtxt<'tcx>, ppm: PpMode) {
if ppm.needs_analysis() {
abort_on_err(print_with_analysis(tcx, ppm), tcx.sess);
return;
@@ -420,7 +420,7 @@ pub fn print_after_hir_lowering<'tcx>(tcx: TyCtxt<'tcx>, krate: &ast::Crate, ppm
let parse = &sess.parse_sess;
pprust::print_crate(
sess.source_map(),
- krate,
+ &tcx.resolver_for_lowering(()).borrow().1,
src_name,
src,
annotation.pp_ann(),
@@ -433,7 +433,7 @@ pub fn print_after_hir_lowering<'tcx>(tcx: TyCtxt<'tcx>, krate: &ast::Crate, ppm
AstTree(PpAstTreeMode::Expanded) => {
debug!("pretty-printing expanded AST");
- format!("{krate:#?}")
+ format!("{:#?}", tcx.resolver_for_lowering(()).borrow().1)
}
Hir(s) => call_with_pp_support_hir(&s, tcx, move |annotation, hir_map| {
@@ -498,6 +498,21 @@ fn print_with_analysis(tcx: TyCtxt<'_>, ppm: PpMode) -> Result<(), ErrorGuarante
out
}
+ ThirFlat => {
+ let mut out = String::new();
+ abort_on_err(rustc_hir_analysis::check_crate(tcx), tcx.sess);
+ debug!("pretty printing THIR flat");
+ for did in tcx.hir().body_owners() {
+ let _ = writeln!(
+ out,
+ "{:?}:\n{}\n",
+ did,
+ tcx.thir_flat(ty::WithOptConstParam::unknown(did))
+ );
+ }
+ out
+ }
+
_ => unreachable!(),
};
diff --git a/compiler/rustc_driver_impl/src/session_diagnostics.rs b/compiler/rustc_driver_impl/src/session_diagnostics.rs
new file mode 100644
index 000000000..638b368f7
--- /dev/null
+++ b/compiler/rustc_driver_impl/src/session_diagnostics.rs
@@ -0,0 +1,67 @@
+use rustc_macros::Diagnostic;
+
+#[derive(Diagnostic)]
+#[diag(driver_impl_rlink_unable_to_read)]
+pub(crate) struct RlinkUnableToRead {
+ pub err: std::io::Error,
+}
+
+#[derive(Diagnostic)]
+#[diag(driver_impl_rlink_wrong_file_type)]
+pub(crate) struct RLinkWrongFileType;
+
+#[derive(Diagnostic)]
+#[diag(driver_impl_rlink_empty_version_number)]
+pub(crate) struct RLinkEmptyVersionNumber;
+
+#[derive(Diagnostic)]
+#[diag(driver_impl_rlink_encoding_version_mismatch)]
+pub(crate) struct RLinkEncodingVersionMismatch {
+ pub version_array: String,
+ pub rlink_version: u32,
+}
+
+#[derive(Diagnostic)]
+#[diag(driver_impl_rlink_rustc_version_mismatch)]
+pub(crate) struct RLinkRustcVersionMismatch<'a> {
+ pub rustc_version: String,
+ pub current_version: &'a str,
+}
+
+#[derive(Diagnostic)]
+#[diag(driver_impl_rlink_no_a_file)]
+pub(crate) struct RlinkNotAFile;
+
+#[derive(Diagnostic)]
+#[diag(driver_impl_unpretty_dump_fail)]
+pub(crate) struct UnprettyDumpFail {
+ pub path: String,
+ pub err: String,
+}
+
+#[derive(Diagnostic)]
+#[diag(driver_impl_ice)]
+pub(crate) struct Ice;
+
+#[derive(Diagnostic)]
+#[diag(driver_impl_ice_bug_report)]
+pub(crate) struct IceBugReport<'a> {
+ pub bug_report_url: &'a str,
+}
+
+#[derive(Diagnostic)]
+#[diag(driver_impl_ice_version)]
+pub(crate) struct IceVersion<'a> {
+ pub version: &'a str,
+ pub triple: &'a str,
+}
+
+#[derive(Diagnostic)]
+#[diag(driver_impl_ice_flags)]
+pub(crate) struct IceFlags {
+ pub flags: String,
+}
+
+#[derive(Diagnostic)]
+#[diag(driver_impl_ice_exclude_cargo_defaults)]
+pub(crate) struct IceExcludeCargoDefaults;
diff --git a/compiler/rustc_error_codes/src/error_codes.rs b/compiler/rustc_error_codes/src/error_codes.rs
index 9d5f4ad75..df857be85 100644
--- a/compiler/rustc_error_codes/src/error_codes.rs
+++ b/compiler/rustc_error_codes/src/error_codes.rs
@@ -5,7 +5,7 @@
// /!\ IMPORTANT /!\
//
// Error messages' format must follow the RFC 1567 available here:
-// https://github.com/rust-lang/rfcs/pull/1567
+// https://rust-lang.github.io/rfcs/1567-long-error-codes-explanation-normalization.html
register_diagnostics! {
E0001: include_str!("./error_codes/E0001.md"),
@@ -253,6 +253,7 @@ E0466: include_str!("./error_codes/E0466.md"),
E0468: include_str!("./error_codes/E0468.md"),
E0469: include_str!("./error_codes/E0469.md"),
E0472: include_str!("./error_codes/E0472.md"),
+E0476: include_str!("./error_codes/E0476.md"),
E0477: include_str!("./error_codes/E0477.md"),
E0478: include_str!("./error_codes/E0478.md"),
E0482: include_str!("./error_codes/E0482.md"),
@@ -286,6 +287,7 @@ E0519: include_str!("./error_codes/E0519.md"),
E0520: include_str!("./error_codes/E0520.md"),
E0521: include_str!("./error_codes/E0521.md"),
E0522: include_str!("./error_codes/E0522.md"),
+E0523: include_str!("./error_codes/E0523.md"),
E0524: include_str!("./error_codes/E0524.md"),
E0525: include_str!("./error_codes/E0525.md"),
E0527: include_str!("./error_codes/E0527.md"),
@@ -506,10 +508,14 @@ E0785: include_str!("./error_codes/E0785.md"),
E0786: include_str!("./error_codes/E0786.md"),
E0787: include_str!("./error_codes/E0787.md"),
E0788: include_str!("./error_codes/E0788.md"),
+E0789: include_str!("./error_codes/E0789.md"),
E0790: include_str!("./error_codes/E0790.md"),
E0791: include_str!("./error_codes/E0791.md"),
E0792: include_str!("./error_codes/E0792.md"),
-;
+E0793: include_str!("./error_codes/E0793.md"),
+}
+
+// Undocumented removed error codes. Note that many removed error codes are documented.
// E0006, // merged with E0005
// E0008, // cannot bind by-move into a pattern guard
// E0019, // merged into E0015
@@ -566,7 +572,7 @@ E0792: include_str!("./error_codes/E0792.md"),
// E0246, // invalid recursive type
// E0247,
// E0248, // value used as a type, now reported earlier during resolution
- // as E0412
+// // as E0412
// E0249,
// E0257,
// E0258,
@@ -608,7 +614,6 @@ E0792: include_str!("./error_codes/E0792.md"),
// E0473, // dereference of reference outside its lifetime
// E0474, // captured variable `..` does not outlive the enclosing closure
// E0475, // index of slice outside its lifetime
- E0476, // lifetime of the source pointer does not outlive lifetime bound...
// 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
@@ -620,7 +625,6 @@ E0792: include_str!("./error_codes/E0792.md"),
// E0488, // lifetime of variable does not enclose its declaration
// E0489, // type/lifetime parameter not in scope here
// E0490, // removed: unreachable
- E0523, // two dependencies have same (crate-name, disambiguator) but different SVH
// E0526, // shuffle indices are not constant
// E0540, // multiple rustc_deprecated attributes
// E0548, // replaced with a generic attribute input check
@@ -629,14 +633,14 @@ E0792: include_str!("./error_codes/E0792.md"),
// E0558, // replaced with a generic attribute input check
// E0563, // cannot determine a type for this `impl Trait` removed in 6383de15
// E0564, // only named lifetimes are allowed in `impl Trait`,
- // but `{}` was found in the type `{}`
+// // but `{}` was found in the type `{}`
// E0598, // lifetime of {} is too short to guarantee its contents can be...
// E0611, // merged into E0616
// E0612, // merged into E0609
// E0613, // Removed (merged with E0609)
// E0629, // missing 'feature' (rustc_const_unstable)
// E0630, // rustc_const_unstable attribute must be paired with stable/unstable
- // attribute
+// // attribute
// E0645, // trait aliases not finished
// E0694, // an unknown tool name found in scoped attributes
// E0702, // replaced with a generic attribute input check
@@ -645,5 +649,3 @@ E0792: include_str!("./error_codes/E0792.md"),
// E0721, // `await` keyword
// E0723, // unstable feature in `const` context
// E0738, // Removed; errored on `#[track_caller] fn`s in `extern "Rust" { ... }`.
- E0789, // rustc_allowed_through_unstable_modules without stability attribute
-}
diff --git a/compiler/rustc_error_codes/src/error_codes/E0464.md b/compiler/rustc_error_codes/src/error_codes/E0464.md
index 9108d856c..209cbb00d 100644
--- a/compiler/rustc_error_codes/src/error_codes/E0464.md
+++ b/compiler/rustc_error_codes/src/error_codes/E0464.md
@@ -1,6 +1,21 @@
The compiler found multiple library files with the requested crate name.
+```compile_fail
+// aux-build:crateresolve-1.rs
+// aux-build:crateresolve-2.rs
+// aux-build:crateresolve-3.rs
+
+extern crate crateresolve;
+//~^ ERROR multiple candidates for `rlib` dependency `crateresolve` found
+
+fn main() {}
+```
+
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.
+
+In the above example, there are three different library files, all of which
+define the same crate name. Without providing a full path, there is no way for
+the compiler to know which crate it should use.
diff --git a/compiler/rustc_error_codes/src/error_codes/E0476.md b/compiler/rustc_error_codes/src/error_codes/E0476.md
new file mode 100644
index 000000000..fc141ba77
--- /dev/null
+++ b/compiler/rustc_error_codes/src/error_codes/E0476.md
@@ -0,0 +1,21 @@
+The coerced type does not outlive the value being coerced to.
+
+Example of erroneous code:
+
+```compile_fail,E0476
+#![feature(coerce_unsized)]
+#![feature(unsize)]
+
+use std::marker::Unsize;
+use std::ops::CoerceUnsized;
+
+// error: lifetime of the source pointer does not outlive lifetime bound of the
+// object type
+impl<'a, 'b, T, S> CoerceUnsized<&'a T> for &'b S where S: Unsize<T> {}
+```
+
+During a coercion, the "source pointer" (the coerced type) did not outlive the
+"object type" (value being coerced to). In the above example, `'b` is not a
+subtype of `'a`. This error can currently only be encountered with the unstable
+`CoerceUnsized` trait which allows custom coercions of unsized types behind a
+smart pointer to be implemented.
diff --git a/compiler/rustc_error_codes/src/error_codes/E0523.md b/compiler/rustc_error_codes/src/error_codes/E0523.md
new file mode 100644
index 000000000..0ddf70386
--- /dev/null
+++ b/compiler/rustc_error_codes/src/error_codes/E0523.md
@@ -0,0 +1,25 @@
+#### Note: this error code is no longer emitted by the compiler.
+
+The compiler found multiple library files with the requested crate name.
+
+```compile_fail
+// aux-build:crateresolve-1.rs
+// aux-build:crateresolve-2.rs
+// aux-build:crateresolve-3.rs
+
+extern crate crateresolve;
+//~^ ERROR multiple candidates for `rlib` dependency `crateresolve` found
+
+fn main() {}
+```
+
+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.
+
+In the above example, there are three different library files, all of which
+define the same crate name. Without providing a full path, there is no way for
+the compiler to know which crate it should use.
+
+*Note that E0523 has been merged into E0464.*
diff --git a/compiler/rustc_error_codes/src/error_codes/E0587.md b/compiler/rustc_error_codes/src/error_codes/E0587.md
index ee9031dc3..d7998af85 100644
--- a/compiler/rustc_error_codes/src/error_codes/E0587.md
+++ b/compiler/rustc_error_codes/src/error_codes/E0587.md
@@ -11,6 +11,6 @@ You cannot use `packed` and `align` hints on a same type. If you want to pack a
type to a given size, you should provide a size to packed:
```
-#[repr(packed)] // ok!
+#[repr(packed(8))] // ok!
struct Umbrella(i32);
```
diff --git a/compiler/rustc_error_codes/src/error_codes/E0789.md b/compiler/rustc_error_codes/src/error_codes/E0789.md
new file mode 100644
index 000000000..89b7cd422
--- /dev/null
+++ b/compiler/rustc_error_codes/src/error_codes/E0789.md
@@ -0,0 +1,30 @@
+#### This error code is internal to the compiler and will not be emitted with normal Rust code.
+
+The internal `rustc_allowed_through_unstable_modules` attribute must be used
+on an item with a `stable` attribute.
+
+Erroneous code example:
+
+```compile_fail,E0789
+// NOTE: both of these attributes are perma-unstable and should *never* be
+// used outside of the compiler and standard library.
+#![feature(rustc_attrs)]
+#![feature(staged_api)]
+
+#![unstable(feature = "foo_module", reason = "...", issue = "123")]
+
+#[rustc_allowed_through_unstable_modules]
+// #[stable(feature = "foo", since = "1.0")]
+struct Foo;
+// ^^^ error: `rustc_allowed_through_unstable_modules` attribute must be
+// paired with a `stable` attribute
+```
+
+Typically when an item is marked with a `stable` attribute, the modules that
+enclose the item must also be marked with `stable` attributes, otherwise the
+item becomes *de facto* unstable. `#[rustc_allowed_through_unstable_modules]`
+is a workaround which allows an item to "escape" its unstable parent modules.
+This error occurs when an item is marked with
+`#[rustc_allowed_through_unstable_modules]` but no supplementary `stable`
+attribute exists. See [#99288](https://github.com/rust-lang/rust/pull/99288)
+for an example of `#[rustc_allowed_through_unstable_modules]` in use.
diff --git a/compiler/rustc_error_codes/src/error_codes/E0793.md b/compiler/rustc_error_codes/src/error_codes/E0793.md
new file mode 100644
index 000000000..b2e51e24e
--- /dev/null
+++ b/compiler/rustc_error_codes/src/error_codes/E0793.md
@@ -0,0 +1,64 @@
+An unaligned references to a field of a [packed] struct got created.
+
+Erroneous code example:
+
+```compile_fail,E0793
+#[repr(packed)]
+pub struct Foo {
+ field1: u64,
+ field2: u8,
+}
+
+unsafe {
+ let foo = Foo { field1: 0, field2: 0 };
+ // Accessing the field directly is fine.
+ let val = foo.field1;
+ // A reference to a packed field causes a error.
+ let val = &foo.field1; // ERROR
+ // An implicit `&` is added in format strings, causing the same error.
+ println!("{}", foo.field1); // ERROR
+}
+```
+
+Creating a reference to an insufficiently aligned packed field is
+[undefined behavior] and therefore disallowed. Using an `unsafe` block does not
+change anything about this. Instead, the code should do a copy of the data in
+the packed field or use raw pointers and unaligned accesses.
+
+```
+#[repr(packed)]
+pub struct Foo {
+ field1: u64,
+ field2: u8,
+}
+
+unsafe {
+ let foo = Foo { field1: 0, field2: 0 };
+
+ // Instead of a reference, we can create a raw pointer...
+ let ptr = std::ptr::addr_of!(foo.field1);
+ // ... and then (crucially!) access it in an explicitly unaligned way.
+ let val = unsafe { ptr.read_unaligned() };
+ // This would *NOT* be correct:
+ // let val = unsafe { *ptr }; // Undefined Behavior due to unaligned load!
+
+ // For formatting, we can create a copy to avoid the direct reference.
+ let copy = foo.field1;
+ println!("{}", copy);
+ // Creating a copy can be written in a single line with curly braces.
+ // (This is equivalent to the two lines above.)
+ println!("{}", { foo.field1 });
+}
+```
+
+### Additional information
+
+Note that this error is specifically about *references* to packed fields.
+Direct by-value access of those fields is fine, since then the compiler has
+enough information to generate the correct kind of access.
+
+See [issue #82523] for more information.
+
+[packed]: https://doc.rust-lang.org/reference/type-layout.html#the-alignment-modifiers
+[undefined behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html
+[issue #82523]: https://github.com/rust-lang/rust/issues/82523
diff --git a/compiler/rustc_error_codes/src/lib.rs b/compiler/rustc_error_codes/src/lib.rs
index bd424dd9d..d6b120e4d 100644
--- a/compiler/rustc_error_codes/src/lib.rs
+++ b/compiler/rustc_error_codes/src/lib.rs
@@ -5,10 +5,9 @@
//! the goal being to make their maintenance easier.
macro_rules! register_diagnostics {
- ($($ecode:ident: $message:expr,)* ; $($code:ident,)*) => (
- pub static DIAGNOSTICS: &[(&str, Option<&str>)] = &[
- $( (stringify!($ecode), Some($message)), )*
- $( (stringify!($code), None), )*
+ ($($ecode:ident: $message:expr,)*) => (
+ pub static DIAGNOSTICS: &[(&str, &str)] = &[
+ $( (stringify!($ecode), $message), )*
];
)
}
diff --git a/compiler/rustc_error_messages/Cargo.toml b/compiler/rustc_error_messages/Cargo.toml
index 0c705d2ec..27783d60b 100644
--- a/compiler/rustc_error_messages/Cargo.toml
+++ b/compiler/rustc_error_messages/Cargo.toml
@@ -16,10 +16,9 @@ rustc_span = { path = "../rustc_span" }
rustc_macros = { path = "../rustc_macros" }
tracing = "0.1"
unic-langid = { version = "0.9.0", features = ["macros"] }
-icu_list = "1.0.0"
-writeable = "0.5.0"
-icu_locid = "1.0.0"
-icu_provider_adapters = "1.0.0"
+icu_list = "1.1.0"
+icu_locid = "1.1.0"
+icu_provider_adapters = "1.1.0"
[features]
rustc_use_parallel_compiler = ['rustc_baked_icu_data/rustc_use_parallel_compiler']
diff --git a/compiler/rustc_error_messages/locales/en-US.ftl b/compiler/rustc_error_messages/locales/en-US.ftl
new file mode 100644
index 000000000..e62923744
--- /dev/null
+++ b/compiler/rustc_error_messages/locales/en-US.ftl
@@ -0,0 +1 @@
+# satisfy tidy lint by having a line in this file
diff --git a/compiler/rustc_error_messages/locales/en-US/ast_passes.ftl b/compiler/rustc_error_messages/locales/en-US/ast_passes.ftl
deleted file mode 100644
index 5f28839f1..000000000
--- a/compiler/rustc_error_messages/locales/en-US/ast_passes.ftl
+++ /dev/null
@@ -1,92 +0,0 @@
-ast_passes_forbidden_let =
- `let` expressions are not supported here
- .note = only supported directly in conditions of `if` and `while` expressions
- .not_supported_or = `||` operators are not supported in let chain expressions
- .not_supported_parentheses = `let`s wrapped in parentheses are not supported in a context with let chains
-
-ast_passes_forbidden_let_stable =
- expected expression, found statement (`let`)
- .note = variable declaration using `let` is a statement
-
-ast_passes_deprecated_where_clause_location =
- where clause not allowed here
-
-ast_passes_forbidden_assoc_constraint =
- associated type bounds are not allowed within structs, enums, or unions
-
-ast_passes_keyword_lifetime =
- lifetimes cannot use keyword names
-
-ast_passes_invalid_label =
- invalid label name `{$name}`
-
-ast_passes_invalid_visibility =
- unnecessary visibility qualifier
- .implied = `pub` not permitted here because it's implied
- .individual_impl_items = place qualifiers on individual impl items instead
- .individual_foreign_items = place qualifiers on individual foreign items instead
-
-ast_passes_trait_fn_const =
- functions in traits cannot be declared const
- .label = functions in traits cannot be const
-
-ast_passes_forbidden_lifetime_bound =
- lifetime bounds cannot be used in this context
-
-ast_passes_forbidden_non_lifetime_param =
- only lifetime parameters can be used in this context
-
-ast_passes_fn_param_too_many =
- function can not have more than {$max_num_args} arguments
-
-ast_passes_fn_param_c_var_args_only =
- C-variadic function must be declared with at least one named argument
-
-ast_passes_fn_param_c_var_args_not_last =
- `...` must be the last argument of a C-variadic function
-
-ast_passes_fn_param_doc_comment =
- documentation comments cannot be applied to function parameters
- .label = doc comments are not allowed here
-
-ast_passes_fn_param_forbidden_attr =
- allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters
-
-ast_passes_fn_param_forbidden_self =
- `self` parameter is only allowed in associated functions
- .label = not semantically valid as function parameter
- .note = associated functions are those in `impl` or `trait` definitions
-
-ast_passes_forbidden_default =
- `default` is only allowed on items in trait impls
- .label = `default` because of this
-
-ast_passes_assoc_const_without_body =
- associated constant in `impl` without body
- .suggestion = provide a definition for the constant
-
-ast_passes_assoc_fn_without_body =
- associated function in `impl` without body
- .suggestion = provide a definition for the function
-
-ast_passes_assoc_type_without_body =
- associated type in `impl` without body
- .suggestion = provide a definition for the type
-
-ast_passes_const_without_body =
- free constant item without body
- .suggestion = provide a definition for the constant
-
-ast_passes_static_without_body =
- free static item without body
- .suggestion = provide a definition for the static
-
-ast_passes_ty_alias_without_body =
- free type alias without body
- .suggestion = provide a definition for the type
-
-ast_passes_fn_without_body =
- free function without a body
- .suggestion = provide a definition for the function
-
-ast_passes_extern_block_suggestion = if you meant to declare an externally defined function, use an `extern` block
diff --git a/compiler/rustc_error_messages/locales/en-US/codegen_llvm.ftl b/compiler/rustc_error_messages/locales/en-US/codegen_llvm.ftl
deleted file mode 100644
index 860212b05..000000000
--- a/compiler/rustc_error_messages/locales/en-US/codegen_llvm.ftl
+++ /dev/null
@@ -1,46 +0,0 @@
-codegen_llvm_unknown_ctarget_feature =
- unknown feature specified for `-Ctarget-feature`: `{$feature}`
- .note = it is still passed through to the codegen backend
- .possible_feature = you might have meant: `{$rust_feature}`
- .consider_filing_feature_request = consider filing a feature request
-
-codegen_llvm_unknown_ctarget_feature_prefix =
- unknown feature specified for `-Ctarget-feature`: `{$feature}`
- .note = features must begin with a `+` to enable or `-` to disable it
-
-codegen_llvm_error_creating_import_library =
- Error creating import library for {$lib_name}: {$error}
-
-codegen_llvm_instrument_coverage_requires_llvm_12 =
- rustc option `-C instrument-coverage` requires LLVM 12 or higher.
-
-codegen_llvm_symbol_already_defined =
- symbol `{$symbol_name}` is already defined
-
-codegen_llvm_invalid_minimum_alignment =
- invalid minimum global alignment: {$err}
-
-codegen_llvm_sanitizer_memtag_requires_mte =
- `-Zsanitizer=memtag` requires `-Ctarget-feature=+mte`
-
-codegen_llvm_error_writing_def_file =
- Error writing .DEF file: {$error}
-
-codegen_llvm_error_calling_dlltool =
- Error calling dlltool: {$error}
-
-codegen_llvm_dlltool_fail_import_library =
- Dlltool could not create import library: {$stdout}\n{$stderr}
-
-codegen_llvm_target_feature_disable_or_enable =
- the target features {$features} must all be either enabled or disabled together
-
-codegen_llvm_missing_features =
- add the missing features in a `target_feature` attribute
-
-codegen_llvm_dynamic_linking_with_lto =
- cannot prefer dynamic linking when performing LTO
- .note = only 'staticlib', 'bin', and 'cdylib' outputs are supported with LTO
-
-codegen_llvm_fail_parsing_target_machine_config_to_target_machine =
- failed to parse target machine config to target machine: {$error}
diff --git a/compiler/rustc_error_messages/locales/en-US/driver.ftl b/compiler/rustc_error_messages/locales/en-US/driver.ftl
deleted file mode 100644
index 8ad198c86..000000000
--- a/compiler/rustc_error_messages/locales/en-US/driver.ftl
+++ /dev/null
@@ -1,13 +0,0 @@
-driver_rlink_unable_to_read = failed to read rlink file: `{$err}`
-
-driver_rlink_wrong_file_type = The input does not look like a .rlink file
-
-driver_rlink_empty_version_number = The input does not contain version number
-
-driver_rlink_encoding_version_mismatch = .rlink file was produced with encoding version `{$version_array}`, but the current version is `{$rlink_version}`
-
-driver_rlink_rustc_version_mismatch = .rlink file was produced by rustc version `{$rustc_version}`, but the current version is `{$current_version}`
-
-driver_rlink_no_a_file = rlink must be a file
-
-driver_unpretty_dump_fail = pretty-print failed to write `{$path}` due to error `{$err}`
diff --git a/compiler/rustc_error_messages/locales/en-US/errors.ftl b/compiler/rustc_error_messages/locales/en-US/errors.ftl
deleted file mode 100644
index 429bdd277..000000000
--- a/compiler/rustc_error_messages/locales/en-US/errors.ftl
+++ /dev/null
@@ -1,13 +0,0 @@
-errors_target_invalid_address_space = invalid address space `{$addr_space}` for `{$cause}` in "data-layout": {$err}
-
-errors_target_invalid_bits = invalid {$kind} `{$bit}` for `{$cause}` in "data-layout": {$err}
-
-errors_target_missing_alignment = missing alignment for `{$cause}` in "data-layout"
-
-errors_target_invalid_alignment = invalid alignment for `{$cause}` in "data-layout": {$err}
-
-errors_target_inconsistent_architecture = inconsistent target specification: "data-layout" claims architecture is {$dl}-endian, while "target-endian" is `{$target}`
-
-errors_target_inconsistent_pointer_width = inconsistent target specification: "data-layout" claims pointers are {$pointer_size}-bit, while "target-pointer-width" is `{$target}`
-
-errors_target_invalid_bits_size = {$err}
diff --git a/compiler/rustc_error_messages/locales/en-US/save_analysis.ftl b/compiler/rustc_error_messages/locales/en-US/save_analysis.ftl
deleted file mode 100644
index 36c2ff468..000000000
--- a/compiler/rustc_error_messages/locales/en-US/save_analysis.ftl
+++ /dev/null
@@ -1 +0,0 @@
-save_analysis_could_not_open = Could not open `{$file_name}`: `{$err}`
diff --git a/compiler/rustc_error_messages/src/lib.rs b/compiler/rustc_error_messages/src/lib.rs
index 37a51980a..010e5f060 100644
--- a/compiler/rustc_error_messages/src/lib.rs
+++ b/compiler/rustc_error_messages/src/lib.rs
@@ -34,47 +34,7 @@ use intl_memoizer::IntlLangMemoizer;
pub use fluent_bundle::{self, types::FluentType, FluentArgs, FluentError, FluentValue};
pub use unic_langid::{langid, LanguageIdentifier};
-// Generates `DEFAULT_LOCALE_RESOURCES` static and `fluent_generated` module.
-fluent_messages! {
- // tidy-alphabetical-start
- ast_lowering => "../locales/en-US/ast_lowering.ftl",
- ast_passes => "../locales/en-US/ast_passes.ftl",
- attr => "../locales/en-US/attr.ftl",
- borrowck => "../locales/en-US/borrowck.ftl",
- builtin_macros => "../locales/en-US/builtin_macros.ftl",
- codegen_gcc => "../locales/en-US/codegen_gcc.ftl",
- codegen_llvm => "../locales/en-US/codegen_llvm.ftl",
- codegen_ssa => "../locales/en-US/codegen_ssa.ftl",
- compiletest => "../locales/en-US/compiletest.ftl",
- const_eval => "../locales/en-US/const_eval.ftl",
- driver => "../locales/en-US/driver.ftl",
- errors => "../locales/en-US/errors.ftl",
- expand => "../locales/en-US/expand.ftl",
- hir_analysis => "../locales/en-US/hir_analysis.ftl",
- hir_typeck => "../locales/en-US/hir_typeck.ftl",
- infer => "../locales/en-US/infer.ftl",
- interface => "../locales/en-US/interface.ftl",
- lint => "../locales/en-US/lint.ftl",
- metadata => "../locales/en-US/metadata.ftl",
- middle => "../locales/en-US/middle.ftl",
- mir_build => "../locales/en-US/mir_build.ftl",
- mir_dataflow => "../locales/en-US/mir_dataflow.ftl",
- monomorphize => "../locales/en-US/monomorphize.ftl",
- parse => "../locales/en-US/parse.ftl",
- passes => "../locales/en-US/passes.ftl",
- plugin_impl => "../locales/en-US/plugin_impl.ftl",
- privacy => "../locales/en-US/privacy.ftl",
- query_system => "../locales/en-US/query_system.ftl",
- resolve => "../locales/en-US/resolve.ftl",
- save_analysis => "../locales/en-US/save_analysis.ftl",
- session => "../locales/en-US/session.ftl",
- symbol_mangling => "../locales/en-US/symbol_mangling.ftl",
- trait_selection => "../locales/en-US/trait_selection.ftl",
- ty_utils => "../locales/en-US/ty_utils.ftl",
- // tidy-alphabetical-end
-}
-
-pub use fluent_generated::{self as fluent, DEFAULT_LOCALE_RESOURCES};
+fluent_messages! { "../locales/en-US.ftl" }
pub type FluentBundle = fluent_bundle::bundle::FluentBundle<FluentResource, IntlLangMemoizer>;
@@ -175,13 +135,19 @@ pub fn fluent_bundle(
let fallback_locale = langid!("en-US");
let requested_fallback_locale = requested_locale.as_ref() == Some(&fallback_locale);
-
+ trace!(?requested_fallback_locale);
+ if requested_fallback_locale && additional_ftl_path.is_none() {
+ return Ok(None);
+ }
// If there is only `-Z additional-ftl-path`, assume locale is "en-US", otherwise use user
// provided locale.
let locale = requested_locale.clone().unwrap_or(fallback_locale);
trace!(?locale);
let mut bundle = new_bundle(vec![locale]);
+ // Add convenience functions available to ftl authors.
+ register_functions(&mut bundle);
+
// Fluent diagnostics can insert directionality isolation markers around interpolated variables
// indicating that there may be a shift from right-to-left to left-to-right text (or
// vice-versa). These are disabled because they are sometimes visible in the error output, but
@@ -190,7 +156,7 @@ pub fn fluent_bundle(
bundle.set_use_isolating(with_directionality_markers);
// If the user requests the default locale then don't try to load anything.
- if !requested_fallback_locale && let Some(requested_locale) = requested_locale {
+ if let Some(requested_locale) = requested_locale {
let mut found_resources = false;
for sysroot in user_provided_sysroot.iter_mut().chain(sysroot_candidates.iter_mut()) {
sysroot.push("share");
@@ -244,6 +210,15 @@ pub fn fluent_bundle(
Ok(Some(bundle))
}
+fn register_functions(bundle: &mut FluentBundle) {
+ bundle
+ .add_function("STREQ", |positional, _named| match positional {
+ [FluentValue::String(a), FluentValue::String(b)] => format!("{}", (a == b)).into(),
+ _ => FluentValue::Error,
+ })
+ .expect("Failed to add a function to the bundle.");
+}
+
/// Type alias for the result of `fallback_fluent_bundle` - a reference-counted pointer to a lazily
/// evaluated fluent bundle.
pub type LazyFallbackBundle = Lrc<Lazy<FluentBundle, impl FnOnce() -> FluentBundle>>;
@@ -251,11 +226,14 @@ pub type LazyFallbackBundle = Lrc<Lazy<FluentBundle, impl FnOnce() -> FluentBund
/// Return the default `FluentBundle` with standard "en-US" diagnostic messages.
#[instrument(level = "trace")]
pub fn fallback_fluent_bundle(
- resources: &'static [&'static str],
+ resources: Vec<&'static str>,
with_directionality_markers: bool,
) -> LazyFallbackBundle {
Lrc::new(Lazy::new(move || {
let mut fallback_bundle = new_bundle(vec![langid!("en-US")]);
+
+ register_functions(&mut fallback_bundle);
+
// See comment in `fluent_bundle`.
fallback_bundle.set_use_isolating(with_directionality_markers);
diff --git a/compiler/rustc_errors/locales/en-US.ftl b/compiler/rustc_errors/locales/en-US.ftl
new file mode 100644
index 000000000..dde1d6c0a
--- /dev/null
+++ b/compiler/rustc_errors/locales/en-US.ftl
@@ -0,0 +1,19 @@
+errors_target_invalid_address_space =
+ invalid address space `{$addr_space}` for `{$cause}` in "data-layout": {$err}
+
+errors_target_invalid_bits =
+ invalid {$kind} `{$bit}` for `{$cause}` in "data-layout": {$err}
+
+errors_target_missing_alignment =
+ missing alignment for `{$cause}` in "data-layout"
+
+errors_target_invalid_alignment =
+ invalid alignment for `{$cause}` in "data-layout": {$err}
+
+errors_target_inconsistent_architecture =
+ inconsistent target specification: "data-layout" claims architecture is {$dl}-endian, while "target-endian" is `{$target}`
+
+errors_target_inconsistent_pointer_width =
+ inconsistent target specification: "data-layout" claims pointers are {$pointer_size}-bit, while "target-pointer-width" is `{$target}`
+
+errors_target_invalid_bits_size = {$err}
diff --git a/compiler/rustc_errors/src/diagnostic.rs b/compiler/rustc_errors/src/diagnostic.rs
index 51b2ff6a0..9ed8ab674 100644
--- a/compiler/rustc_errors/src/diagnostic.rs
+++ b/compiler/rustc_errors/src/diagnostic.rs
@@ -7,7 +7,6 @@ use rustc_data_structures::fx::FxHashMap;
use rustc_error_messages::fluent_value_from_str_list_sep_by_and;
use rustc_error_messages::FluentValue;
use rustc_lint_defs::{Applicability, LintExpectationId};
-use rustc_span::edition::LATEST_STABLE_EDITION;
use rustc_span::symbol::Symbol;
use rustc_span::{Span, DUMMY_SP};
use std::borrow::Cow;
@@ -555,18 +554,6 @@ impl Diagnostic {
self
}
- /// Help the user upgrade to the latest edition.
- /// This is factored out to make sure it does the right thing with `Cargo.toml`.
- pub fn help_use_latest_edition(&mut self) -> &mut Self {
- if std::env::var_os("CARGO").is_some() {
- self.help(&format!("set `edition = \"{}\"` in `Cargo.toml`", LATEST_STABLE_EDITION));
- } else {
- self.help(&format!("pass `--edition {}` to `rustc`", LATEST_STABLE_EDITION));
- }
- self.note("for more on editions, read https://doc.rust-lang.org/edition-guide");
- self
- }
-
/// Disallow attaching suggestions this diagnostic.
/// Any suggestions attached e.g. with the `span_suggestion_*` methods
/// (before and after the call to `disable_suggestions`) will be ignored.
@@ -629,19 +616,27 @@ impl Diagnostic {
applicability: Applicability,
style: SuggestionStyle,
) -> &mut Self {
- assert!(!suggestion.is_empty());
- debug_assert!(
- !(suggestion.iter().any(|(sp, text)| sp.is_empty() && text.is_empty())),
- "Span must not be empty and have no suggestion"
+ let mut parts = suggestion
+ .into_iter()
+ .map(|(span, snippet)| SubstitutionPart { snippet, span })
+ .collect::<Vec<_>>();
+
+ parts.sort_unstable_by_key(|part| part.span);
+
+ assert!(!parts.is_empty());
+ debug_assert_eq!(
+ parts.iter().find(|part| part.span.is_empty() && part.snippet.is_empty()),
+ None,
+ "Span must not be empty and have no suggestion",
+ );
+ debug_assert_eq!(
+ parts.array_windows().find(|[a, b]| a.span.overlaps(b.span)),
+ None,
+ "suggestion must not have overlapping parts",
);
self.push_suggestion(CodeSuggestion {
- substitutions: vec![Substitution {
- parts: suggestion
- .into_iter()
- .map(|(span, snippet)| SubstitutionPart { snippet, span })
- .collect(),
- }],
+ substitutions: vec![Substitution { parts }],
msg: self.subdiagnostic_message_to_diagnostic_message(msg),
style,
applicability,
@@ -802,25 +797,34 @@ impl Diagnostic {
suggestions: impl IntoIterator<Item = Vec<(Span, String)>>,
applicability: Applicability,
) -> &mut Self {
- let suggestions: Vec<_> = suggestions.into_iter().collect();
- debug_assert!(
- !(suggestions
- .iter()
- .flatten()
- .any(|(sp, suggestion)| sp.is_empty() && suggestion.is_empty())),
- "Span must not be empty and have no suggestion"
- );
+ let substitutions = suggestions
+ .into_iter()
+ .map(|sugg| {
+ let mut parts = sugg
+ .into_iter()
+ .map(|(span, snippet)| SubstitutionPart { snippet, span })
+ .collect::<Vec<_>>();
+
+ parts.sort_unstable_by_key(|part| part.span);
+
+ assert!(!parts.is_empty());
+ debug_assert_eq!(
+ parts.iter().find(|part| part.span.is_empty() && part.snippet.is_empty()),
+ None,
+ "Span must not be empty and have no suggestion",
+ );
+ debug_assert_eq!(
+ parts.array_windows().find(|[a, b]| a.span.overlaps(b.span)),
+ None,
+ "suggestion must not have overlapping parts",
+ );
+
+ Substitution { parts }
+ })
+ .collect();
self.push_suggestion(CodeSuggestion {
- substitutions: suggestions
- .into_iter()
- .map(|sugg| Substitution {
- parts: sugg
- .into_iter()
- .map(|(span, snippet)| SubstitutionPart { snippet, span })
- .collect(),
- })
- .collect(),
+ substitutions,
msg: self.subdiagnostic_message_to_diagnostic_message(msg),
style: SuggestionStyle::ShowCode,
applicability,
@@ -1034,6 +1038,7 @@ impl Diagnostic {
) -> (
&Level,
&[(DiagnosticMessage, Style)],
+ Vec<(&Cow<'static, str>, &DiagnosticArgValue<'static>)>,
&Option<DiagnosticId>,
&MultiSpan,
&Result<Vec<CodeSuggestion>, SuggestionsDisabled>,
@@ -1042,6 +1047,7 @@ impl Diagnostic {
(
&self.level,
&self.message,
+ self.args().collect(),
&self.code,
&self.span,
&self.suggestions,
diff --git a/compiler/rustc_errors/src/diagnostic_builder.rs b/compiler/rustc_errors/src/diagnostic_builder.rs
index cbfee582d..3064d2bed 100644
--- a/compiler/rustc_errors/src/diagnostic_builder.rs
+++ b/compiler/rustc_errors/src/diagnostic_builder.rs
@@ -408,6 +408,59 @@ impl EmissionGuarantee for ! {
}
}
+impl<'a> DiagnosticBuilder<'a, rustc_span::fatal_error::FatalError> {
+ /// Convenience function for internal use, clients should use one of the
+ /// `struct_*` methods on [`Handler`].
+ #[track_caller]
+ pub(crate) fn new_almost_fatal(
+ handler: &'a Handler,
+ message: impl Into<DiagnosticMessage>,
+ ) -> Self {
+ let diagnostic = Diagnostic::new_with_code(Level::Fatal, None, message);
+ Self::new_diagnostic_almost_fatal(handler, diagnostic)
+ }
+
+ /// Creates a new `DiagnosticBuilder` with an already constructed
+ /// diagnostic.
+ pub(crate) fn new_diagnostic_almost_fatal(
+ handler: &'a Handler,
+ diagnostic: Diagnostic,
+ ) -> Self {
+ debug!("Created new diagnostic");
+ Self {
+ inner: DiagnosticBuilderInner {
+ state: DiagnosticBuilderState::Emittable(handler),
+ diagnostic: Box::new(diagnostic),
+ },
+ _marker: PhantomData,
+ }
+ }
+}
+
+impl EmissionGuarantee for rustc_span::fatal_error::FatalError {
+ fn diagnostic_builder_emit_producing_guarantee(db: &mut DiagnosticBuilder<'_, Self>) -> Self {
+ match db.inner.state {
+ // First `.emit()` call, the `&Handler` is still available.
+ DiagnosticBuilderState::Emittable(handler) => {
+ db.inner.state = DiagnosticBuilderState::AlreadyEmittedOrDuringCancellation;
+
+ handler.emit_diagnostic(&mut db.inner.diagnostic);
+ }
+ // `.emit()` was previously called, disallowed from repeating it.
+ DiagnosticBuilderState::AlreadyEmittedOrDuringCancellation => {}
+ }
+ // Then fatally error..
+ rustc_span::fatal_error::FatalError
+ }
+
+ fn make_diagnostic_builder(
+ handler: &Handler,
+ msg: impl Into<DiagnosticMessage>,
+ ) -> DiagnosticBuilder<'_, Self> {
+ DiagnosticBuilder::new_almost_fatal(handler, msg)
+ }
+}
+
/// In general, the `DiagnosticBuilder` uses deref to allow access to
/// the fields and methods of the embedded `diagnostic` in a
/// transparent way. *However,* many of the methods are intended to
@@ -616,7 +669,6 @@ impl<'a, G: EmissionGuarantee> DiagnosticBuilder<'a, G> {
sp: impl Into<MultiSpan>,
msg: impl Into<SubdiagnosticMessage>,
) -> &mut Self);
- forward!(pub fn help_use_latest_edition(&mut self,) -> &mut Self);
forward!(pub fn set_is_lint(&mut self,) -> &mut Self);
forward!(pub fn disable_suggestions(&mut self,) -> &mut Self);
diff --git a/compiler/rustc_errors/src/diagnostic_impls.rs b/compiler/rustc_errors/src/diagnostic_impls.rs
index dad5e98aa..e82bad67b 100644
--- a/compiler/rustc_errors/src/diagnostic_impls.rs
+++ b/compiler/rustc_errors/src/diagnostic_impls.rs
@@ -1,6 +1,5 @@
-use crate::{
- fluent, DiagnosticArgValue, DiagnosticBuilder, Handler, IntoDiagnostic, IntoDiagnosticArg,
-};
+use crate::fluent_generated as fluent;
+use crate::{DiagnosticArgValue, DiagnosticBuilder, Handler, IntoDiagnostic, IntoDiagnosticArg};
use rustc_ast as ast;
use rustc_ast_pretty::pprust;
use rustc_hir as hir;
@@ -36,6 +35,12 @@ impl<'a, T: fmt::Display> From<&'a T> for DiagnosticArgFromDisplay<'a> {
}
}
+impl<'a, T: Clone + IntoDiagnosticArg> IntoDiagnosticArg for &'a T {
+ fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
+ self.clone().into_diagnostic_arg()
+ }
+}
+
macro_rules! into_diagnostic_arg_using_display {
($( $ty:ty ),+ $(,)?) => {
$(
@@ -49,6 +54,7 @@ macro_rules! into_diagnostic_arg_using_display {
}
into_diagnostic_arg_using_display!(
+ ast::ParamKindOrd,
i8,
u8,
i16,
@@ -153,12 +159,6 @@ impl IntoDiagnosticArg for ast::Path {
}
}
-impl IntoDiagnosticArg for &ast::Path {
- fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
- DiagnosticArgValue::Str(Cow::Owned(pprust::path_to_string(self)))
- }
-}
-
impl IntoDiagnosticArg for ast::token::Token {
fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
DiagnosticArgValue::Str(pprust::token_to_string(&self))
@@ -177,6 +177,26 @@ impl IntoDiagnosticArg for type_ir::FloatTy {
}
}
+impl IntoDiagnosticArg for std::ffi::CString {
+ fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
+ DiagnosticArgValue::Str(Cow::Owned(self.to_string_lossy().into_owned()))
+ }
+}
+
+impl IntoDiagnosticArg for rustc_data_structures::small_c_str::SmallCStr {
+ fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
+ DiagnosticArgValue::Str(Cow::Owned(self.to_string_lossy().into_owned()))
+ }
+}
+
+impl IntoDiagnosticArg for ast::Visibility {
+ fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
+ let s = pprust::vis_to_string(&self);
+ let s = s.trim_end().to_string();
+ DiagnosticArgValue::Str(Cow::Owned(s))
+ }
+}
+
impl IntoDiagnosticArg for Level {
fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
DiagnosticArgValue::Str(Cow::Borrowed(self.to_cmd_flag()))
diff --git a/compiler/rustc_errors/src/emitter.rs b/compiler/rustc_errors/src/emitter.rs
index 628e19999..211bbf4f5 100644
--- a/compiler/rustc_errors/src/emitter.rs
+++ b/compiler/rustc_errors/src/emitter.rs
@@ -18,7 +18,7 @@ use crate::translation::{to_fluent_args, Translate};
use crate::{
diagnostic::DiagnosticLocation, CodeSuggestion, Diagnostic, DiagnosticId, DiagnosticMessage,
FluentBundle, Handler, LazyFallbackBundle, Level, MultiSpan, SubDiagnostic,
- SubstitutionHighlight, SuggestionStyle,
+ SubstitutionHighlight, SuggestionStyle, TerminalUrl,
};
use rustc_lint_defs::pluralize;
@@ -66,6 +66,7 @@ impl HumanReadableErrorType {
diagnostic_width: Option<usize>,
macro_backtrace: bool,
track_diagnostics: bool,
+ terminal_url: TerminalUrl,
) -> EmitterWriter {
let (short, color_config) = self.unzip();
let color = color_config.suggests_using_colors();
@@ -80,6 +81,7 @@ impl HumanReadableErrorType {
diagnostic_width,
macro_backtrace,
track_diagnostics,
+ terminal_url,
)
}
}
@@ -652,6 +654,7 @@ pub struct EmitterWriter {
macro_backtrace: bool,
track_diagnostics: bool,
+ terminal_url: TerminalUrl,
}
#[derive(Debug)]
@@ -672,6 +675,7 @@ impl EmitterWriter {
diagnostic_width: Option<usize>,
macro_backtrace: bool,
track_diagnostics: bool,
+ terminal_url: TerminalUrl,
) -> EmitterWriter {
let dst = Destination::from_stderr(color_config);
EmitterWriter {
@@ -685,6 +689,7 @@ impl EmitterWriter {
diagnostic_width,
macro_backtrace,
track_diagnostics,
+ terminal_url,
}
}
@@ -699,6 +704,7 @@ impl EmitterWriter {
diagnostic_width: Option<usize>,
macro_backtrace: bool,
track_diagnostics: bool,
+ terminal_url: TerminalUrl,
) -> EmitterWriter {
EmitterWriter {
dst: Raw(dst, colored),
@@ -711,6 +717,7 @@ impl EmitterWriter {
diagnostic_width,
macro_backtrace,
track_diagnostics,
+ terminal_url,
}
}
@@ -1378,7 +1385,13 @@ impl EmitterWriter {
// only render error codes, not lint codes
if let Some(DiagnosticId::Error(ref code)) = *code {
buffer.append(0, "[", Style::Level(*level));
- buffer.append(0, code, Style::Level(*level));
+ let code = if let TerminalUrl::Yes = self.terminal_url {
+ let path = "https://doc.rust-lang.org/error_codes";
+ format!("\x1b]8;;{path}/{code}.html\x07{code}\x1b]8;;\x07")
+ } else {
+ code.clone()
+ };
+ buffer.append(0, &code, Style::Level(*level));
buffer.append(0, "]", Style::Level(*level));
label_width += 2 + code.len();
}
@@ -1755,7 +1768,7 @@ impl EmitterWriter {
// Render the replacements for each suggestion
let suggestions = suggestion.splice_lines(sm);
- debug!("emit_suggestion_default: suggestions={:?}", suggestions);
+ debug!(?suggestions);
if suggestions.is_empty() {
// Suggestions coming from macros can have malformed spans. This is a heavy handed
@@ -1784,6 +1797,7 @@ impl EmitterWriter {
for (complete, parts, highlights, only_capitalization) in
suggestions.iter().take(MAX_SUGGESTIONS)
{
+ debug!(?complete, ?parts, ?highlights);
notice_capitalization |= only_capitalization;
let has_deletion = parts.iter().any(|p| p.is_deletion(sm));
@@ -1796,17 +1810,17 @@ impl EmitterWriter {
// telling users to make a change but not clarifying *where*.
let loc = sm.lookup_char_pos(parts[0].span.lo());
if loc.file.name != sm.span_to_filename(span) && loc.file.name.is_real() {
- buffer.puts(row_num - 1, 0, "--> ", Style::LineNumber);
- buffer.append(
- row_num - 1,
- &format!(
- "{}:{}:{}",
- sm.filename_for_diagnostics(&loc.file.name),
- sm.doctest_offset_line(&loc.file.name, loc.line),
- loc.col.0 + 1,
- ),
- Style::LineAndColumn,
- );
+ let arrow = "--> ";
+ buffer.puts(row_num - 1, 0, arrow, Style::LineNumber);
+ let filename = sm.filename_for_diagnostics(&loc.file.name);
+ let offset = sm.doctest_offset_line(&loc.file.name, loc.line);
+ let message = format!("{}:{}:{}", filename, offset, loc.col.0 + 1);
+ if row_num == 2 {
+ let col = usize::max(max_line_num_len + 1, arrow.len());
+ buffer.puts(1, col, &message, Style::LineAndColumn);
+ } else {
+ buffer.append(row_num - 1, &message, Style::LineAndColumn);
+ }
for _ in 0..max_line_num_len {
buffer.prepend(row_num - 1, " ", Style::NoStyle);
}
@@ -1882,9 +1896,8 @@ impl EmitterWriter {
&mut buffer,
&mut row_num,
&Vec::new(),
- p,
+ p + line_start,
l,
- line_start,
show_code_change,
max_line_num_len,
&file_lines,
@@ -1907,9 +1920,8 @@ impl EmitterWriter {
&mut buffer,
&mut row_num,
&Vec::new(),
- p,
+ p + line_start,
l,
- line_start,
show_code_change,
max_line_num_len,
&file_lines,
@@ -1925,9 +1937,8 @@ impl EmitterWriter {
&mut buffer,
&mut row_num,
&Vec::new(),
- p,
+ p + line_start,
l,
- line_start,
show_code_change,
max_line_num_len,
&file_lines,
@@ -1941,9 +1952,8 @@ impl EmitterWriter {
&mut buffer,
&mut row_num,
highlight_parts,
- line_pos,
+ line_pos + line_start,
line,
- line_start,
show_code_change,
max_line_num_len,
&file_lines,
@@ -2113,30 +2123,38 @@ impl EmitterWriter {
}
}
for sugg in suggestions {
- if sugg.style == SuggestionStyle::CompletelyHidden {
- // do not display this suggestion, it is meant only for tools
- } else if sugg.style == SuggestionStyle::HideCodeAlways {
- if let Err(e) = self.emit_message_default(
- &MultiSpan::new(),
- &[(sugg.msg.to_owned(), Style::HeaderMsg)],
- args,
- &None,
- &Level::Help,
- max_line_num_len,
- true,
- None,
- ) {
- panic!("failed to emit error: {}", e);
+ match sugg.style {
+ SuggestionStyle::CompletelyHidden => {
+ // do not display this suggestion, it is meant only for tools
}
- } else if let Err(e) = self.emit_suggestion_default(
- span,
- sugg,
- args,
- &Level::Help,
- max_line_num_len,
- ) {
- panic!("failed to emit error: {}", e);
- };
+ SuggestionStyle::HideCodeAlways => {
+ if let Err(e) = self.emit_message_default(
+ &MultiSpan::new(),
+ &[(sugg.msg.to_owned(), Style::HeaderMsg)],
+ args,
+ &None,
+ &Level::Help,
+ max_line_num_len,
+ true,
+ None,
+ ) {
+ panic!("failed to emit error: {}", e);
+ }
+ }
+ SuggestionStyle::HideCodeInline
+ | SuggestionStyle::ShowCode
+ | SuggestionStyle::ShowAlways => {
+ if let Err(e) = self.emit_suggestion_default(
+ span,
+ sugg,
+ args,
+ &Level::Help,
+ max_line_num_len,
+ ) {
+ panic!("failed to emit error: {}", e);
+ }
+ }
+ }
}
}
}
@@ -2159,40 +2177,63 @@ impl EmitterWriter {
buffer: &mut StyledBuffer,
row_num: &mut usize,
highlight_parts: &Vec<SubstitutionHighlight>,
- line_pos: usize,
- line: &str,
- line_start: usize,
+ line_num: usize,
+ line_to_add: &str,
show_code_change: DisplaySuggestion,
max_line_num_len: usize,
file_lines: &FileLines,
is_multiline: bool,
) {
- // Print the span column to avoid confusion
- buffer.puts(*row_num, 0, &self.maybe_anonymized(line_start + line_pos), Style::LineNumber);
if let DisplaySuggestion::Diff = show_code_change {
- // Add the line number for both addition and removal to drive the point home.
- //
- // N - fn foo<A: T>(bar: A) {
- // N + fn foo(bar: impl T) {
- buffer.puts(
- *row_num - 1,
- 0,
- &self.maybe_anonymized(line_start + line_pos),
- Style::LineNumber,
- );
- buffer.puts(*row_num - 1, max_line_num_len + 1, "- ", Style::Removal);
- buffer.puts(
- *row_num - 1,
- max_line_num_len + 3,
- &normalize_whitespace(
- &file_lines.file.get_line(file_lines.lines[line_pos].line_index).unwrap(),
- ),
- Style::NoStyle,
- );
- buffer.puts(*row_num, max_line_num_len + 1, "+ ", Style::Addition);
+ // We need to print more than one line if the span we need to remove is multiline.
+ // For more info: https://github.com/rust-lang/rust/issues/92741
+ let lines_to_remove = file_lines.lines.iter().take(file_lines.lines.len() - 1);
+ for (index, line_to_remove) in lines_to_remove.enumerate() {
+ buffer.puts(
+ *row_num - 1,
+ 0,
+ &self.maybe_anonymized(line_num + index),
+ Style::LineNumber,
+ );
+ buffer.puts(*row_num - 1, max_line_num_len + 1, "- ", Style::Removal);
+ let line = normalize_whitespace(
+ &file_lines.file.get_line(line_to_remove.line_index).unwrap(),
+ );
+ buffer.puts(*row_num - 1, max_line_num_len + 3, &line, Style::NoStyle);
+ *row_num += 1;
+ }
+ // If the last line is exactly equal to the line we need to add, we can skip both of them.
+ // This allows us to avoid output like the following:
+ // 2 - &
+ // 2 + if true { true } else { false }
+ // 3 - if true { true } else { false }
+ // If those lines aren't equal, we print their diff
+ let last_line_index = file_lines.lines[file_lines.lines.len() - 1].line_index;
+ let last_line = &file_lines.file.get_line(last_line_index).unwrap();
+ if last_line != line_to_add {
+ buffer.puts(
+ *row_num - 1,
+ 0,
+ &self.maybe_anonymized(line_num + file_lines.lines.len() - 1),
+ Style::LineNumber,
+ );
+ buffer.puts(*row_num - 1, max_line_num_len + 1, "- ", Style::Removal);
+ buffer.puts(
+ *row_num - 1,
+ max_line_num_len + 3,
+ &normalize_whitespace(last_line),
+ Style::NoStyle,
+ );
+ buffer.puts(*row_num, 0, &self.maybe_anonymized(line_num), Style::LineNumber);
+ buffer.puts(*row_num, max_line_num_len + 1, "+ ", Style::Addition);
+ buffer.append(*row_num, &normalize_whitespace(line_to_add), Style::NoStyle);
+ } else {
+ *row_num -= 2;
+ }
} else if is_multiline {
+ buffer.puts(*row_num, 0, &self.maybe_anonymized(line_num), Style::LineNumber);
match &highlight_parts[..] {
- [SubstitutionHighlight { start: 0, end }] if *end == line.len() => {
+ [SubstitutionHighlight { start: 0, end }] if *end == line_to_add.len() => {
buffer.puts(*row_num, max_line_num_len + 1, "+ ", Style::Addition);
}
[] => {
@@ -2202,17 +2243,17 @@ impl EmitterWriter {
buffer.puts(*row_num, max_line_num_len + 1, "~ ", Style::Addition);
}
}
+ buffer.append(*row_num, &normalize_whitespace(line_to_add), Style::NoStyle);
} else {
+ buffer.puts(*row_num, 0, &self.maybe_anonymized(line_num), Style::LineNumber);
draw_col_separator(buffer, *row_num, max_line_num_len + 1);
+ buffer.append(*row_num, &normalize_whitespace(line_to_add), Style::NoStyle);
}
- // print the suggestion
- buffer.append(*row_num, &normalize_whitespace(line), Style::NoStyle);
-
// Colorize addition/replacements with green.
for &SubstitutionHighlight { start, end } in highlight_parts {
// Account for tabs when highlighting (#87972).
- let tabs: usize = line
+ let tabs: usize = line_to_add
.chars()
.take(start)
.map(|ch| match ch {
diff --git a/compiler/rustc_errors/src/json.rs b/compiler/rustc_errors/src/json.rs
index dc38b8725..f32d6b96b 100644
--- a/compiler/rustc_errors/src/json.rs
+++ b/compiler/rustc_errors/src/json.rs
@@ -17,6 +17,7 @@ use crate::translation::{to_fluent_args, Translate};
use crate::DiagnosticId;
use crate::{
CodeSuggestion, FluentBundle, LazyFallbackBundle, MultiSpan, SpanLabel, SubDiagnostic,
+ TerminalUrl,
};
use rustc_lint_defs::Applicability;
@@ -47,6 +48,7 @@ pub struct JsonEmitter {
diagnostic_width: Option<usize>,
macro_backtrace: bool,
track_diagnostics: bool,
+ terminal_url: TerminalUrl,
}
impl JsonEmitter {
@@ -60,6 +62,7 @@ impl JsonEmitter {
diagnostic_width: Option<usize>,
macro_backtrace: bool,
track_diagnostics: bool,
+ terminal_url: TerminalUrl,
) -> JsonEmitter {
JsonEmitter {
dst: Box::new(io::BufWriter::new(io::stderr())),
@@ -73,6 +76,7 @@ impl JsonEmitter {
diagnostic_width,
macro_backtrace,
track_diagnostics,
+ terminal_url,
}
}
@@ -84,6 +88,7 @@ impl JsonEmitter {
diagnostic_width: Option<usize>,
macro_backtrace: bool,
track_diagnostics: bool,
+ terminal_url: TerminalUrl,
) -> JsonEmitter {
let file_path_mapping = FilePathMapping::empty();
JsonEmitter::stderr(
@@ -96,6 +101,7 @@ impl JsonEmitter {
diagnostic_width,
macro_backtrace,
track_diagnostics,
+ terminal_url,
)
}
@@ -110,6 +116,7 @@ impl JsonEmitter {
diagnostic_width: Option<usize>,
macro_backtrace: bool,
track_diagnostics: bool,
+ terminal_url: TerminalUrl,
) -> JsonEmitter {
JsonEmitter {
dst,
@@ -123,6 +130,7 @@ impl JsonEmitter {
diagnostic_width,
macro_backtrace,
track_diagnostics,
+ terminal_url,
}
}
@@ -360,6 +368,7 @@ impl Diagnostic {
je.diagnostic_width,
je.macro_backtrace,
je.track_diagnostics,
+ je.terminal_url,
)
.ui_testing(je.ui_testing)
.emit_diagnostic(diag);
@@ -571,7 +580,7 @@ impl DiagnosticCode {
let je_result =
je.registry.as_ref().map(|registry| registry.try_find_description(&s)).unwrap();
- DiagnosticCode { code: s, explanation: je_result.unwrap_or(None) }
+ DiagnosticCode { code: s, explanation: je_result.ok() }
})
}
}
diff --git a/compiler/rustc_errors/src/json/tests.rs b/compiler/rustc_errors/src/json/tests.rs
index f13146897..671dc449e 100644
--- a/compiler/rustc_errors/src/json/tests.rs
+++ b/compiler/rustc_errors/src/json/tests.rs
@@ -4,7 +4,7 @@ use crate::json::JsonEmitter;
use rustc_span::source_map::{FilePathMapping, SourceMap};
use crate::emitter::{ColorConfig, HumanReadableErrorType};
-use crate::Handler;
+use crate::{Handler, TerminalUrl};
use rustc_span::{BytePos, Span};
use std::str;
@@ -46,7 +46,7 @@ fn test_positions(code: &str, span: (u32, u32), expected_output: SpanTestData) {
let sm = Lrc::new(SourceMap::new(FilePathMapping::empty()));
sm.new_source_file(Path::new("test.rs").to_owned().into(), code.to_owned());
let fallback_bundle =
- crate::fallback_fluent_bundle(rustc_error_messages::DEFAULT_LOCALE_RESOURCES, false);
+ crate::fallback_fluent_bundle(vec![crate::DEFAULT_LOCALE_RESOURCE], false);
let output = Arc::new(Mutex::new(Vec::new()));
let je = JsonEmitter::new(
@@ -60,6 +60,7 @@ fn test_positions(code: &str, span: (u32, u32), expected_output: SpanTestData) {
None,
false,
false,
+ TerminalUrl::No,
);
let span = Span::with_root_ctxt(BytePos(span.0), BytePos(span.1));
diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs
index 535812fb0..09bf28ed4 100644
--- a/compiler/rustc_errors/src/lib.rs
+++ b/compiler/rustc_errors/src/lib.rs
@@ -3,6 +3,7 @@
//! This module contains the code for creating and emitting diagnostics.
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
+#![feature(array_windows)]
#![feature(drain_filter)]
#![feature(if_let_guard)]
#![feature(is_terminal)]
@@ -35,13 +36,13 @@ use rustc_data_structures::stable_hasher::StableHasher;
use rustc_data_structures::sync::{self, Lock, Lrc};
use rustc_data_structures::AtomicRef;
pub use rustc_error_messages::{
- fallback_fluent_bundle, fluent, fluent_bundle, DelayDm, DiagnosticMessage, FluentBundle,
+ fallback_fluent_bundle, fluent_bundle, DelayDm, DiagnosticMessage, FluentBundle,
LanguageIdentifier, LazyFallbackBundle, MultiSpan, SpanLabel, SubdiagnosticMessage,
- DEFAULT_LOCALE_RESOURCES,
};
pub use rustc_lint_defs::{pluralize, Applicability};
+use rustc_macros::fluent_messages;
use rustc_span::source_map::SourceMap;
-use rustc_span::HashStableContext;
+pub use rustc_span::ErrorGuaranteed;
use rustc_span::{Loc, Span};
use std::borrow::Cow;
@@ -75,6 +76,8 @@ pub use snippet::Style;
pub type PErr<'a> = DiagnosticBuilder<'a, ErrorGuaranteed>;
pub type PResult<'a, T> = Result<T, PErr<'a>>;
+fluent_messages! { "../locales/en-US.ftl" }
+
// `PResult` is used a lot. Make sure it doesn't unintentionally get bigger.
// (See also the comment on `DiagnosticBuilderInner`'s `diagnostic` field.)
#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
@@ -572,6 +575,7 @@ impl Handler {
None,
flags.macro_backtrace,
flags.track_diagnostics,
+ TerminalUrl::No,
));
Self::with_emitter_and_flags(emitter, flags)
}
@@ -616,22 +620,24 @@ impl Handler {
}
}
- /// Translate `message` eagerly with `args`.
+ /// Translate `message` eagerly with `args` to `SubdiagnosticMessage::Eager`.
pub fn eagerly_translate<'a>(
&self,
message: DiagnosticMessage,
args: impl Iterator<Item = DiagnosticArg<'a, 'static>>,
) -> SubdiagnosticMessage {
+ SubdiagnosticMessage::Eager(self.eagerly_translate_to_string(message, args))
+ }
+
+ /// Translate `message` eagerly with `args` to `String`.
+ pub fn eagerly_translate_to_string<'a>(
+ &self,
+ message: DiagnosticMessage,
+ args: impl Iterator<Item = DiagnosticArg<'a, 'static>>,
+ ) -> String {
let inner = self.inner.borrow();
let args = crate::translation::to_fluent_args(args);
- SubdiagnosticMessage::Eager(
- inner
- .emitter
- .translate_message(&message, &args)
- .map_err(Report::new)
- .unwrap()
- .to_string(),
- )
+ inner.emitter.translate_message(&message, &args).map_err(Report::new).unwrap().to_string()
}
// This is here to not allow mutation of flags;
@@ -1009,6 +1015,7 @@ impl Handler {
}
#[track_caller]
+ #[rustc_lint_diagnostics]
pub fn span_note_without_error(
&self,
span: impl Into<MultiSpan>,
@@ -1018,6 +1025,7 @@ impl Handler {
}
#[track_caller]
+ #[rustc_lint_diagnostics]
pub fn span_note_diag(
&self,
span: Span,
@@ -1029,19 +1037,23 @@ impl Handler {
}
// NOTE: intentionally doesn't raise an error so rustc_codegen_ssa only reports fatal errors in the main thread
+ #[rustc_lint_diagnostics]
pub fn fatal(&self, msg: impl Into<DiagnosticMessage>) -> FatalError {
self.inner.borrow_mut().fatal(msg)
}
+ #[rustc_lint_diagnostics]
pub fn err(&self, msg: impl Into<DiagnosticMessage>) -> ErrorGuaranteed {
self.inner.borrow_mut().err(msg)
}
+ #[rustc_lint_diagnostics]
pub fn warn(&self, msg: impl Into<DiagnosticMessage>) {
let mut db = DiagnosticBuilder::new(self, Warning(None), msg);
db.emit();
}
+ #[rustc_lint_diagnostics]
pub fn note_without_error(&self, msg: impl Into<DiagnosticMessage>) {
DiagnosticBuilder::new(self, Note, msg).emit();
}
@@ -1056,28 +1068,26 @@ impl Handler {
}
pub fn has_errors(&self) -> Option<ErrorGuaranteed> {
- if self.inner.borrow().has_errors() { Some(ErrorGuaranteed(())) } else { None }
+ self.inner.borrow().has_errors().then(ErrorGuaranteed::unchecked_claim_error_was_emitted)
}
+
pub fn has_errors_or_lint_errors(&self) -> Option<ErrorGuaranteed> {
- if self.inner.borrow().has_errors_or_lint_errors() {
- Some(ErrorGuaranteed::unchecked_claim_error_was_emitted())
- } else {
- None
- }
+ self.inner
+ .borrow()
+ .has_errors_or_lint_errors()
+ .then(ErrorGuaranteed::unchecked_claim_error_was_emitted)
}
pub fn has_errors_or_delayed_span_bugs(&self) -> Option<ErrorGuaranteed> {
- if self.inner.borrow().has_errors_or_delayed_span_bugs() {
- Some(ErrorGuaranteed::unchecked_claim_error_was_emitted())
- } else {
- None
- }
+ self.inner
+ .borrow()
+ .has_errors_or_delayed_span_bugs()
+ .then(ErrorGuaranteed::unchecked_claim_error_was_emitted)
}
pub fn is_compilation_going_to_fail(&self) -> Option<ErrorGuaranteed> {
- if self.inner.borrow().is_compilation_going_to_fail() {
- Some(ErrorGuaranteed::unchecked_claim_error_was_emitted())
- } else {
- None
- }
+ self.inner
+ .borrow()
+ .is_compilation_going_to_fail()
+ .then(ErrorGuaranteed::unchecked_claim_error_was_emitted)
}
pub fn print_error_count(&self, registry: &Registry) {
@@ -1131,6 +1141,20 @@ impl Handler {
self.create_warning(warning).emit()
}
+ pub fn create_almost_fatal<'a>(
+ &'a self,
+ fatal: impl IntoDiagnostic<'a, FatalError>,
+ ) -> DiagnosticBuilder<'a, FatalError> {
+ fatal.into_diagnostic(self)
+ }
+
+ pub fn emit_almost_fatal<'a>(
+ &'a self,
+ fatal: impl IntoDiagnostic<'a, FatalError>,
+ ) -> FatalError {
+ self.create_almost_fatal(fatal).emit()
+ }
+
pub fn create_fatal<'a>(
&'a self,
fatal: impl IntoDiagnostic<'a, !>,
@@ -1156,6 +1180,17 @@ impl Handler {
self.create_bug(bug).emit()
}
+ pub fn emit_note<'a>(&'a self, note: impl IntoDiagnostic<'a, Noted>) -> Noted {
+ self.create_note(note).emit()
+ }
+
+ pub fn create_note<'a>(
+ &'a self,
+ note: impl IntoDiagnostic<'a, Noted>,
+ ) -> DiagnosticBuilder<'a, Noted> {
+ note.into_diagnostic(self)
+ }
+
fn emit_diag_at_span(
&self,
mut diag: Diagnostic,
@@ -1440,9 +1475,7 @@ impl HandlerInner {
.emitted_diagnostic_codes
.iter()
.filter_map(|x| match &x {
- DiagnosticId::Error(s)
- if registry.try_find_description(s).map_or(false, |o| o.is_some()) =>
- {
+ DiagnosticId::Error(s) if registry.try_find_description(s).is_ok() => {
Some(s.clone())
}
_ => None,
@@ -1803,16 +1836,9 @@ pub fn add_elided_lifetime_in_path_suggestion(
);
}
-/// Useful type to use with `Result<>` indicate that an error has already
-/// been reported to the user, so no need to continue checking.
-#[derive(Clone, Copy, Debug, Encodable, Decodable, Hash, PartialEq, Eq, PartialOrd, Ord)]
-#[derive(HashStable_Generic)]
-pub struct ErrorGuaranteed(());
-
-impl ErrorGuaranteed {
- /// To be used only if you really know what you are doing... ideally, we would find a way to
- /// eliminate all calls to this method.
- pub fn unchecked_claim_error_was_emitted() -> Self {
- ErrorGuaranteed(())
- }
+#[derive(Clone, Copy, PartialEq, Hash, Debug)]
+pub enum TerminalUrl {
+ No,
+ Yes,
+ Auto,
}
diff --git a/compiler/rustc_errors/src/registry.rs b/compiler/rustc_errors/src/registry.rs
index da764d993..f26d8e7eb 100644
--- a/compiler/rustc_errors/src/registry.rs
+++ b/compiler/rustc_errors/src/registry.rs
@@ -5,21 +5,17 @@ pub struct InvalidErrorCode;
#[derive(Clone)]
pub struct Registry {
- long_descriptions: FxHashMap<&'static str, Option<&'static str>>,
+ long_descriptions: FxHashMap<&'static str, &'static str>,
}
impl Registry {
- pub fn new(long_descriptions: &[(&'static str, Option<&'static str>)]) -> Registry {
+ pub fn new(long_descriptions: &[(&'static str, &'static str)]) -> Registry {
Registry { long_descriptions: long_descriptions.iter().copied().collect() }
}
/// Returns `InvalidErrorCode` if the code requested does not exist in the
- /// registry. Otherwise, returns an `Option` where `None` means the error
- /// code is valid but has no extended information.
- pub fn try_find_description(
- &self,
- code: &str,
- ) -> Result<Option<&'static str>, InvalidErrorCode> {
+ /// registry.
+ pub fn try_find_description(&self, code: &str) -> Result<&'static str, InvalidErrorCode> {
self.long_descriptions.get(code).copied().ok_or(InvalidErrorCode)
}
}
diff --git a/compiler/rustc_errors/src/styled_buffer.rs b/compiler/rustc_errors/src/styled_buffer.rs
index 9abdb5fc9..9aa14e1f2 100644
--- a/compiler/rustc_errors/src/styled_buffer.rs
+++ b/compiler/rustc_errors/src/styled_buffer.rs
@@ -142,7 +142,7 @@ impl StyledBuffer {
pub fn set_style(&mut self, line: usize, col: usize, style: Style, overwrite: bool) {
if let Some(ref mut line) = self.lines.get_mut(line) {
if let Some(StyledChar { style: s, .. }) = line.get_mut(col) {
- if overwrite || *s == Style::NoStyle || *s == Style::Quotation {
+ if overwrite || matches!(s, Style::NoStyle | Style::Quotation) {
*s = style;
}
}
diff --git a/compiler/rustc_errors/src/translation.rs b/compiler/rustc_errors/src/translation.rs
index addfc9726..ed35eb1b6 100644
--- a/compiler/rustc_errors/src/translation.rs
+++ b/compiler/rustc_errors/src/translation.rs
@@ -1,9 +1,10 @@
-use crate::error::TranslateError;
+use crate::error::{TranslateError, TranslateErrorKind};
use crate::snippet::Style;
use crate::{DiagnosticArg, DiagnosticMessage, FluentBundle};
use rustc_data_structures::sync::Lrc;
use rustc_error_messages::FluentArgs;
use std::borrow::Cow;
+use std::env;
use std::error::Report;
/// Convert diagnostic arguments (a rustc internal type that exists to implement
@@ -94,12 +95,29 @@ pub trait Translate {
// The primary bundle was present and translation succeeded
Some(Ok(t)) => t,
- // Always yeet out for errors on debug
- Some(Err(primary)) if cfg!(debug_assertions) => do yeet primary,
-
// If `translate_with_bundle` returns `Err` with the primary bundle, this is likely
- // just that the primary bundle doesn't contain the message being translated or
- // something else went wrong) so proceed to the fallback bundle.
+ // just that the primary bundle doesn't contain the message being translated, so
+ // proceed to the fallback bundle.
+ Some(Err(
+ primary @ TranslateError::One {
+ kind: TranslateErrorKind::MessageMissing, ..
+ },
+ )) => translate_with_bundle(self.fallback_fluent_bundle())
+ .map_err(|fallback| primary.and(fallback))?,
+
+ // Always yeet out for errors on debug (unless
+ // `RUSTC_TRANSLATION_NO_DEBUG_ASSERT` is set in the environment - this allows
+ // local runs of the test suites, of builds with debug assertions, to test the
+ // behaviour in a normal build).
+ Some(Err(primary))
+ if cfg!(debug_assertions)
+ && env::var("RUSTC_TRANSLATION_NO_DEBUG_ASSERT").is_err() =>
+ {
+ do yeet primary
+ }
+
+ // ..otherwise, for end users, an error about this wouldn't be useful or actionable, so
+ // just hide it and try with the fallback bundle.
Some(Err(primary)) => translate_with_bundle(self.fallback_fluent_bundle())
.map_err(|fallback| primary.and(fallback))?,
diff --git a/compiler/rustc_expand/Cargo.toml b/compiler/rustc_expand/Cargo.toml
index 192f54171..c971714e0 100644
--- a/compiler/rustc_expand/Cargo.toml
+++ b/compiler/rustc_expand/Cargo.toml
@@ -24,5 +24,5 @@ rustc_serialize = { path = "../rustc_serialize" }
rustc_session = { path = "../rustc_session" }
rustc_span = { path = "../rustc_span" }
smallvec = { version = "1.8.1", features = ["union", "may_dangle"] }
-thin-vec = "0.2.8"
+thin-vec = "0.2.12"
tracing = "0.1"
diff --git a/compiler/rustc_error_messages/locales/en-US/expand.ftl b/compiler/rustc_expand/locales/en-US.ftl
index df0e8ae5d..cfae781bd 100644
--- a/compiler/rustc_error_messages/locales/en-US/expand.ftl
+++ b/compiler/rustc_expand/locales/en-US.ftl
@@ -127,3 +127,12 @@ expand_module_file_not_found =
expand_module_multiple_candidates =
file for module `{$name}` found at both "{$default_path}" and "{$secondary_path}"
.help = delete or rename one of them to remove the ambiguity
+
+expand_trace_macro = trace_macro
+
+expand_proc_macro_panicked =
+ proc macro panicked
+ .help = message: {$message}
+
+expand_proc_macro_derive_tokens =
+ proc-macro derive produced unparseable tokens
diff --git a/compiler/rustc_expand/src/base.rs b/compiler/rustc_expand/src/base.rs
index 951d59246..22bc90f5c 100644
--- a/compiler/rustc_expand/src/base.rs
+++ b/compiler/rustc_expand/src/base.rs
@@ -1,15 +1,11 @@
#![deny(rustc::untranslatable_diagnostic)]
-use crate::errors::{
- ArgumentNotAttributes, AttrNoArguments, AttributeMetaItem, AttributeSingleWord,
- AttributesWrongForm, CannotBeNameOfMacro, ExpectedCommaInList, HelperAttributeNameInvalid,
- MacroBodyStability, MacroConstStability, NotAMetaItem, OnlyOneArgument, OnlyOneWord,
- ResolveRelativePath, TakesNoArguments,
-};
+use crate::errors;
use crate::expand::{self, AstFragment, Invocation};
use crate::module::DirOwnership;
use rustc_ast::attr::MarkedAttrs;
+use rustc_ast::mut_visit::DummyAstNode;
use rustc_ast::ptr::P;
use rustc_ast::token::{self, Nonterminal};
use rustc_ast::tokenstream::TokenStream;
@@ -33,10 +29,11 @@ use rustc_span::source_map::SourceMap;
use rustc_span::symbol::{kw, sym, Ident, Symbol};
use rustc_span::{BytePos, FileName, Span, DUMMY_SP};
use smallvec::{smallvec, SmallVec};
-
+use std::default::Default;
use std::iter;
use std::path::{Path, PathBuf};
use std::rc::Rc;
+use thin_vec::ThinVec;
pub(crate) use rustc_span::hygiene::MacroKind;
@@ -558,7 +555,7 @@ impl DummyResult {
pub fn raw_expr(sp: Span, is_error: bool) -> P<ast::Expr> {
P(ast::Expr {
id: ast::DUMMY_NODE_ID,
- kind: if is_error { ast::ExprKind::Err } else { ast::ExprKind::Tup(Vec::new()) },
+ kind: if is_error { ast::ExprKind::Err } else { ast::ExprKind::Tup(ThinVec::new()) },
span: sp,
attrs: ast::AttrVec::new(),
tokens: None,
@@ -574,7 +571,7 @@ impl DummyResult {
pub fn raw_ty(sp: Span, is_error: bool) -> P<ast::Ty> {
P(ast::Ty {
id: ast::DUMMY_NODE_ID,
- kind: if is_error { ast::TyKind::Err } else { ast::TyKind::Tup(Vec::new()) },
+ kind: if is_error { ast::TyKind::Err } else { ast::TyKind::Tup(ThinVec::new()) },
span: sp,
tokens: None,
})
@@ -645,6 +642,10 @@ impl MacResult for DummyResult {
fn make_variants(self: Box<DummyResult>) -> Option<SmallVec<[ast::Variant; 1]>> {
Some(SmallVec::new())
}
+
+ fn make_crate(self: Box<DummyResult>) -> Option<ast::Crate> {
+ Some(DummyAstNode::dummy())
+ }
}
/// A syntax extension kind.
@@ -796,13 +797,13 @@ impl SyntaxExtension {
.unwrap_or_else(|| (None, helper_attrs));
let (stability, const_stability, body_stability) = attr::find_stability(&sess, attrs, span);
if let Some((_, sp)) = const_stability {
- sess.emit_err(MacroConstStability {
+ sess.emit_err(errors::MacroConstStability {
span: sp,
head_span: sess.source_map().guess_head_span(span),
});
}
if let Some((_, sp)) = body_stability {
- sess.emit_err(MacroBodyStability {
+ sess.emit_err(errors::MacroBodyStability {
span: sp,
head_span: sess.source_map().guess_head_span(span),
});
@@ -1142,8 +1143,8 @@ impl<'a> ExtCtxt<'a> {
self.sess.parse_sess.span_diagnostic.span_bug(sp, msg);
}
pub fn trace_macros_diag(&mut self) {
- for (sp, notes) in self.expansions.iter() {
- let mut db = self.sess.parse_sess.span_diagnostic.span_note_diag(*sp, "trace_macro");
+ for (span, notes) in self.expansions.iter() {
+ let mut db = self.sess.parse_sess.create_note(errors::TraceMacro { span: *span });
for note in notes {
db.note(note);
}
@@ -1197,7 +1198,7 @@ pub fn resolve_path(
.expect("attempting to resolve a file path in an external file"),
FileName::DocTest(path, _) => path,
other => {
- return Err(ResolveRelativePath {
+ return Err(errors::ResolveRelativePath {
span,
path: parse_sess.source_map().filename_for_diagnostics(&other).to_string(),
}
@@ -1279,7 +1280,7 @@ pub fn expr_to_string(
/// done as rarely as possible).
pub fn check_zero_tts(cx: &ExtCtxt<'_>, span: Span, tts: TokenStream, name: &str) {
if !tts.is_empty() {
- cx.emit_err(TakesNoArguments { span, name });
+ cx.emit_err(errors::TakesNoArguments { span, name });
}
}
@@ -1307,14 +1308,14 @@ pub fn get_single_str_from_tts(
) -> Option<Symbol> {
let mut p = cx.new_parser_from_tts(tts);
if p.token == token::Eof {
- cx.emit_err(OnlyOneArgument { span, name });
+ cx.emit_err(errors::OnlyOneArgument { span, name });
return None;
}
let ret = parse_expr(&mut p)?;
let _ = p.eat(&token::Comma);
if p.token != token::Eof {
- cx.emit_err(OnlyOneArgument { span, name });
+ cx.emit_err(errors::OnlyOneArgument { span, name });
}
expr_to_string(cx, ret, "argument must be a string literal").map(|(s, _)| s)
}
@@ -1336,7 +1337,7 @@ pub fn get_exprs_from_tts(cx: &mut ExtCtxt<'_>, tts: TokenStream) -> Option<Vec<
continue;
}
if p.token != token::Eof {
- cx.emit_err(ExpectedCommaInList { span: p.token.span });
+ cx.emit_err(errors::ExpectedCommaInList { span: p.token.span });
return None;
}
}
@@ -1353,51 +1354,58 @@ pub fn parse_macro_name_and_helper_attrs(
// `#[proc_macro_derive(Foo, attributes(A, ..))]`
let list = attr.meta_item_list()?;
if list.len() != 1 && list.len() != 2 {
- diag.emit_err(AttrNoArguments { span: attr.span });
+ diag.emit_err(errors::AttrNoArguments { span: attr.span });
return None;
}
let Some(trait_attr) = list[0].meta_item() else {
- diag.emit_err(NotAMetaItem {span: list[0].span()});
+ diag.emit_err(errors::NotAMetaItem {span: list[0].span()});
return None;
};
let trait_ident = match trait_attr.ident() {
Some(trait_ident) if trait_attr.is_word() => trait_ident,
_ => {
- diag.emit_err(OnlyOneWord { span: trait_attr.span });
+ diag.emit_err(errors::OnlyOneWord { span: trait_attr.span });
return None;
}
};
if !trait_ident.name.can_be_raw() {
- diag.emit_err(CannotBeNameOfMacro { span: trait_attr.span, trait_ident, macro_type });
+ diag.emit_err(errors::CannotBeNameOfMacro {
+ span: trait_attr.span,
+ trait_ident,
+ macro_type,
+ });
}
let attributes_attr = list.get(1);
let proc_attrs: Vec<_> = if let Some(attr) = attributes_attr {
if !attr.has_name(sym::attributes) {
- diag.emit_err(ArgumentNotAttributes { span: attr.span() });
+ diag.emit_err(errors::ArgumentNotAttributes { span: attr.span() });
}
attr.meta_item_list()
.unwrap_or_else(|| {
- diag.emit_err(AttributesWrongForm { span: attr.span() });
+ diag.emit_err(errors::AttributesWrongForm { span: attr.span() });
&[]
})
.iter()
.filter_map(|attr| {
let Some(attr) = attr.meta_item() else {
- diag.emit_err(AttributeMetaItem { span: attr.span() });
+ diag.emit_err(errors::AttributeMetaItem { span: attr.span() });
return None;
};
let ident = match attr.ident() {
Some(ident) if attr.is_word() => ident,
_ => {
- diag.emit_err(AttributeSingleWord { span: attr.span });
+ diag.emit_err(errors::AttributeSingleWord { span: attr.span });
return None;
}
};
if !ident.name.can_be_raw() {
- diag.emit_err(HelperAttributeNameInvalid { span: attr.span, name: ident });
+ diag.emit_err(errors::HelperAttributeNameInvalid {
+ span: attr.span,
+ name: ident,
+ });
}
Some(ident.name)
diff --git a/compiler/rustc_expand/src/build.rs b/compiler/rustc_expand/src/build.rs
index 9b16e79d4..8a78c3296 100644
--- a/compiler/rustc_expand/src/build.rs
+++ b/compiler/rustc_expand/src/build.rs
@@ -5,7 +5,7 @@ use rustc_ast::{attr, token, util::literal};
use rustc_span::source_map::Spanned;
use rustc_span::symbol::{kw, sym, Ident, Symbol};
use rustc_span::Span;
-use thin_vec::ThinVec;
+use thin_vec::{thin_vec, ThinVec};
impl<'a> ExtCtxt<'a> {
pub fn path(&self, span: Span, strs: Vec<Ident>) -> ast::Path {
@@ -125,16 +125,20 @@ impl<'a> ExtCtxt<'a> {
pub fn poly_trait_ref(&self, span: Span, path: ast::Path) -> ast::PolyTraitRef {
ast::PolyTraitRef {
- bound_generic_params: Vec::new(),
+ bound_generic_params: ThinVec::new(),
trait_ref: self.trait_ref(path),
span,
}
}
- pub fn trait_bound(&self, path: ast::Path) -> ast::GenericBound {
+ pub fn trait_bound(&self, path: ast::Path, is_const: bool) -> ast::GenericBound {
ast::GenericBound::Trait(
self.poly_trait_ref(path.span, path),
- ast::TraitBoundModifier::None,
+ if is_const {
+ ast::TraitBoundModifier::MaybeConst
+ } else {
+ ast::TraitBoundModifier::None
+ },
)
}
@@ -217,14 +221,14 @@ impl<'a> ExtCtxt<'a> {
pub fn block_expr(&self, expr: P<ast::Expr>) -> P<ast::Block> {
self.block(
expr.span,
- vec![ast::Stmt {
+ thin_vec![ast::Stmt {
id: ast::DUMMY_NODE_ID,
span: expr.span,
kind: ast::StmtKind::Expr(expr),
}],
)
}
- pub fn block(&self, span: Span, stmts: Vec<ast::Stmt>) -> P<ast::Block> {
+ pub fn block(&self, span: Span, stmts: ThinVec<ast::Stmt>) -> P<ast::Block> {
P(ast::Block {
stmts,
id: ast::DUMMY_NODE_ID,
@@ -272,22 +276,31 @@ impl<'a> ExtCtxt<'a> {
self.expr(sp, ast::ExprKind::AddrOf(ast::BorrowKind::Ref, ast::Mutability::Not, e))
}
+ pub fn expr_paren(&self, sp: Span, e: P<ast::Expr>) -> P<ast::Expr> {
+ self.expr(sp, ast::ExprKind::Paren(e))
+ }
+
pub fn expr_call(
&self,
span: Span,
expr: P<ast::Expr>,
- args: Vec<P<ast::Expr>>,
+ args: ThinVec<P<ast::Expr>>,
) -> P<ast::Expr> {
self.expr(span, ast::ExprKind::Call(expr, args))
}
- pub fn expr_call_ident(&self, span: Span, id: Ident, args: Vec<P<ast::Expr>>) -> P<ast::Expr> {
+ pub fn expr_call_ident(
+ &self,
+ span: Span,
+ id: Ident,
+ args: ThinVec<P<ast::Expr>>,
+ ) -> P<ast::Expr> {
self.expr(span, ast::ExprKind::Call(self.expr_ident(span, id), args))
}
pub fn expr_call_global(
&self,
sp: Span,
fn_path: Vec<Ident>,
- args: Vec<P<ast::Expr>>,
+ args: ThinVec<P<ast::Expr>>,
) -> P<ast::Expr> {
let pathexpr = self.expr_path(self.path_global(sp, fn_path));
self.expr_call(sp, pathexpr, args)
@@ -310,7 +323,7 @@ impl<'a> ExtCtxt<'a> {
&self,
span: Span,
path: ast::Path,
- fields: Vec<ast::ExprField>,
+ fields: ThinVec<ast::ExprField>,
) -> P<ast::Expr> {
self.expr(
span,
@@ -326,7 +339,7 @@ impl<'a> ExtCtxt<'a> {
&self,
span: Span,
id: Ident,
- fields: Vec<ast::ExprField>,
+ fields: ThinVec<ast::ExprField>,
) -> P<ast::Expr> {
self.expr_struct(span, self.path_ident(span, id), fields)
}
@@ -364,12 +377,12 @@ impl<'a> ExtCtxt<'a> {
}
/// `[expr1, expr2, ...]`
- pub fn expr_array(&self, sp: Span, exprs: Vec<P<ast::Expr>>) -> P<ast::Expr> {
+ pub fn expr_array(&self, sp: Span, exprs: ThinVec<P<ast::Expr>>) -> P<ast::Expr> {
self.expr(sp, ast::ExprKind::Array(exprs))
}
/// `&[expr1, expr2, ...]`
- pub fn expr_array_ref(&self, sp: Span, exprs: Vec<P<ast::Expr>>) -> P<ast::Expr> {
+ pub fn expr_array_ref(&self, sp: Span, exprs: ThinVec<P<ast::Expr>>) -> P<ast::Expr> {
self.expr_addr_of(sp, self.expr_array(sp, exprs))
}
@@ -379,14 +392,14 @@ impl<'a> ExtCtxt<'a> {
pub fn expr_some(&self, sp: Span, expr: P<ast::Expr>) -> P<ast::Expr> {
let some = self.std_path(&[sym::option, sym::Option, sym::Some]);
- self.expr_call_global(sp, some, vec![expr])
+ self.expr_call_global(sp, some, thin_vec![expr])
}
pub fn expr_none(&self, sp: Span) -> P<ast::Expr> {
let none = self.std_path(&[sym::option, sym::Option, sym::None]);
self.expr_path(self.path_global(sp, none))
}
- pub fn expr_tuple(&self, sp: Span, exprs: Vec<P<ast::Expr>>) -> P<ast::Expr> {
+ pub fn expr_tuple(&self, sp: Span, exprs: ThinVec<P<ast::Expr>>) -> P<ast::Expr> {
self.expr(sp, ast::ExprKind::Tup(exprs))
}
@@ -394,7 +407,7 @@ impl<'a> ExtCtxt<'a> {
self.expr_call_global(
span,
[sym::std, sym::rt, sym::begin_panic].iter().map(|s| Ident::new(*s, span)).collect(),
- vec![self.expr_str(span, msg)],
+ thin_vec![self.expr_str(span, msg)],
)
}
@@ -404,7 +417,7 @@ impl<'a> ExtCtxt<'a> {
pub fn expr_ok(&self, sp: Span, expr: P<ast::Expr>) -> P<ast::Expr> {
let ok = self.std_path(&[sym::result, sym::Result, sym::Ok]);
- self.expr_call_global(sp, ok, vec![expr])
+ self.expr_call_global(sp, ok, thin_vec![expr])
}
pub fn expr_try(&self, sp: Span, head: P<ast::Expr>) -> P<ast::Expr> {
@@ -418,12 +431,12 @@ impl<'a> ExtCtxt<'a> {
let binding_expr = self.expr_ident(sp, binding_variable);
// `Ok(__try_var)` pattern
- let ok_pat = self.pat_tuple_struct(sp, ok_path, vec![binding_pat.clone()]);
+ let ok_pat = self.pat_tuple_struct(sp, ok_path, thin_vec![binding_pat.clone()]);
// `Err(__try_var)` (pattern and expression respectively)
- let err_pat = self.pat_tuple_struct(sp, err_path.clone(), vec![binding_pat]);
+ let err_pat = self.pat_tuple_struct(sp, err_path.clone(), thin_vec![binding_pat]);
let err_inner_expr =
- self.expr_call(sp, self.expr_path(err_path), vec![binding_expr.clone()]);
+ self.expr_call(sp, self.expr_path(err_path), thin_vec![binding_expr.clone()]);
// `return Err(__try_var)`
let err_expr = self.expr(sp, ast::ExprKind::Ret(Some(err_inner_expr)));
@@ -433,7 +446,7 @@ impl<'a> ExtCtxt<'a> {
let err_arm = self.arm(sp, err_pat, err_expr);
// `match head { Ok() => ..., Err() => ... }`
- self.expr_match(sp, head, vec![ok_arm, err_arm])
+ self.expr_match(sp, head, thin_vec![ok_arm, err_arm])
}
pub fn pat(&self, span: Span, kind: PatKind) -> P<ast::Pat> {
@@ -465,7 +478,7 @@ impl<'a> ExtCtxt<'a> {
&self,
span: Span,
path: ast::Path,
- subpats: Vec<P<ast::Pat>>,
+ subpats: ThinVec<P<ast::Pat>>,
) -> P<ast::Pat> {
self.pat(span, PatKind::TupleStruct(None, path, subpats))
}
@@ -473,18 +486,18 @@ impl<'a> ExtCtxt<'a> {
&self,
span: Span,
path: ast::Path,
- field_pats: Vec<ast::PatField>,
+ field_pats: ThinVec<ast::PatField>,
) -> P<ast::Pat> {
self.pat(span, PatKind::Struct(None, path, field_pats, false))
}
- pub fn pat_tuple(&self, span: Span, pats: Vec<P<ast::Pat>>) -> P<ast::Pat> {
+ pub fn pat_tuple(&self, span: Span, pats: ThinVec<P<ast::Pat>>) -> P<ast::Pat> {
self.pat(span, PatKind::Tuple(pats))
}
pub fn pat_some(&self, span: Span, pat: P<ast::Pat>) -> P<ast::Pat> {
let some = self.std_path(&[sym::option, sym::Option, sym::Some]);
let path = self.path_global(span, some);
- self.pat_tuple_struct(span, path, vec![pat])
+ self.pat_tuple_struct(span, path, thin_vec![pat])
}
pub fn arm(&self, span: Span, pat: P<ast::Pat>, expr: P<ast::Expr>) -> ast::Arm {
@@ -503,7 +516,7 @@ impl<'a> ExtCtxt<'a> {
self.arm(span, self.pat_wild(span), self.expr_unreachable(span))
}
- pub fn expr_match(&self, span: Span, arg: P<ast::Expr>, arms: Vec<ast::Arm>) -> P<Expr> {
+ pub fn expr_match(&self, span: Span, arg: P<ast::Expr>, arms: ThinVec<ast::Arm>) -> P<Expr> {
self.expr(span, ast::ExprKind::Match(arg, arms))
}
@@ -554,7 +567,12 @@ impl<'a> ExtCtxt<'a> {
self.lambda(span, vec![ident], body)
}
- pub fn lambda_stmts_1(&self, span: Span, stmts: Vec<ast::Stmt>, ident: Ident) -> P<ast::Expr> {
+ pub fn lambda_stmts_1(
+ &self,
+ span: Span,
+ stmts: ThinVec<ast::Stmt>,
+ ident: Ident,
+ ) -> P<ast::Expr> {
self.lambda1(span, self.expr_block(self.block(span, stmts)), ident)
}
@@ -571,7 +589,7 @@ impl<'a> ExtCtxt<'a> {
}
// `self` is unused but keep it as method for the convenience use.
- pub fn fn_decl(&self, inputs: Vec<ast::Param>, output: ast::FnRetTy) -> P<ast::FnDecl> {
+ pub fn fn_decl(&self, inputs: ThinVec<ast::Param>, output: ast::FnRetTy) -> P<ast::FnDecl> {
P(ast::FnDecl { inputs, output })
}
diff --git a/compiler/rustc_expand/src/config.rs b/compiler/rustc_expand/src/config.rs
index 1fcbdfd9b..01500c2c7 100644
--- a/compiler/rustc_expand/src/config.rs
+++ b/compiler/rustc_expand/src/config.rs
@@ -24,6 +24,7 @@ use rustc_session::Session;
use rustc_span::edition::{Edition, ALL_EDITIONS};
use rustc_span::symbol::{sym, Symbol};
use rustc_span::{Span, DUMMY_SP};
+use thin_vec::ThinVec;
/// A folder that strips out items that do not belong in the current configuration.
pub struct StripUnconfigured<'a> {
@@ -206,7 +207,7 @@ pub fn features(
None => {
// The entire crate is unconfigured.
krate.attrs = ast::AttrVec::new();
- krate.items = Vec::new();
+ krate.items = ThinVec::new();
Features::default()
}
Some(attrs) => {
@@ -238,12 +239,10 @@ macro_rules! configure {
impl<'a> StripUnconfigured<'a> {
pub fn configure<T: HasAttrs + HasTokens>(&self, mut node: T) -> Option<T> {
self.process_cfg_attrs(&mut node);
- if self.in_cfg(node.attrs()) {
+ self.in_cfg(node.attrs()).then(|| {
self.try_configure_tokens(&mut node);
- Some(node)
- } else {
- None
- }
+ node
+ })
}
fn try_configure_tokens<T: HasTokens>(&self, node: &mut T) {
@@ -257,7 +256,7 @@ impl<'a> StripUnconfigured<'a> {
fn configure_krate_attrs(&self, mut attrs: ast::AttrVec) -> Option<ast::AttrVec> {
attrs.flat_map_in_place(|attr| self.process_cfg_attr(attr));
- if self.in_cfg(&attrs) { Some(attrs) } else { None }
+ self.in_cfg(&attrs).then_some(attrs)
}
/// Performs cfg-expansion on `stream`, producing a new `AttrTokenStream`.
diff --git a/compiler/rustc_expand/src/errors.rs b/compiler/rustc_expand/src/errors.rs
index afe5169d3..e5102a952 100644
--- a/compiler/rustc_expand/src/errors.rs
+++ b/compiler/rustc_expand/src/errors.rs
@@ -65,7 +65,7 @@ pub(crate) struct MacroConstStability {
#[primary_span]
#[label]
pub span: Span,
- #[label(label2)]
+ #[label(expand_label2)]
pub head_span: Span,
}
@@ -75,7 +75,7 @@ pub(crate) struct MacroBodyStability {
#[primary_span]
#[label]
pub span: Span,
- #[label(label2)]
+ #[label(expand_label2)]
pub head_span: Span,
}
@@ -188,7 +188,7 @@ pub(crate) struct FeatureRemoved<'a> {
}
#[derive(Subdiagnostic)]
-#[note(reason)]
+#[note(expand_reason)]
pub(crate) struct FeatureRemovedReason<'a> {
pub reason: &'a str,
}
@@ -223,12 +223,12 @@ pub(crate) struct MalformedFeatureAttribute {
#[derive(Subdiagnostic)]
pub(crate) enum MalformedFeatureAttributeHelp {
- #[label(expected)]
+ #[label(expand_expected)]
Label {
#[primary_span]
span: Span,
},
- #[suggestion(expected, code = "{suggestion}", applicability = "maybe-incorrect")]
+ #[suggestion(expand_expected, code = "{suggestion}", applicability = "maybe-incorrect")]
Suggestion {
#[primary_span]
span: Span,
@@ -306,7 +306,7 @@ pub(crate) struct IncompleteParse<'a> {
pub kind_name: &'a str,
#[suggestion(
- suggestion_add_semi,
+ expand_suggestion_add_semi,
style = "verbose",
code = ";",
applicability = "maybe-incorrect"
@@ -340,7 +340,7 @@ pub(crate) struct ModuleInBlock {
}
#[derive(Subdiagnostic)]
-#[note(note)]
+#[note(expand_note)]
pub(crate) struct ModuleInBlockName {
#[primary_span]
pub span: Span,
@@ -368,3 +368,32 @@ pub(crate) struct ModuleMultipleCandidates {
pub default_path: String,
pub secondary_path: String,
}
+
+#[derive(Diagnostic)]
+#[diag(expand_trace_macro)]
+pub struct TraceMacro {
+ #[primary_span]
+ pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(expand_proc_macro_panicked)]
+pub(crate) struct ProcMacroPanicked {
+ #[primary_span]
+ pub span: Span,
+ #[subdiagnostic]
+ pub message: Option<ProcMacroPanickedHelp>,
+}
+
+#[derive(Subdiagnostic)]
+#[help(expand_help)]
+pub(crate) struct ProcMacroPanickedHelp {
+ pub message: String,
+}
+
+#[derive(Diagnostic)]
+#[diag(expand_proc_macro_derive_tokens)]
+pub struct ProcMacroDeriveTokens {
+ #[primary_span]
+ pub span: Span,
+}
diff --git a/compiler/rustc_expand/src/lib.rs b/compiler/rustc_expand/src/lib.rs
index 897268566..634e206e5 100644
--- a/compiler/rustc_expand/src/lib.rs
+++ b/compiler/rustc_expand/src/lib.rs
@@ -20,6 +20,9 @@ extern crate tracing;
extern crate proc_macro as pm;
+use rustc_errors::{DiagnosticMessage, SubdiagnosticMessage};
+use rustc_macros::fluent_messages;
+
mod placeholders;
mod proc_macro_server;
@@ -60,3 +63,5 @@ mod tokenstream {
mod mut_visit {
mod tests;
}
+
+fluent_messages! { "../locales/en-US.ftl" }
diff --git a/compiler/rustc_expand/src/mbe/macro_parser.rs b/compiler/rustc_expand/src/mbe/macro_parser.rs
index 2e199541b..283e68a68 100644
--- a/compiler/rustc_expand/src/mbe/macro_parser.rs
+++ b/compiler/rustc_expand/src/mbe/macro_parser.rs
@@ -503,7 +503,7 @@ impl TtParser {
mp.push_match(metavar_idx, seq_depth, MatchedSeq(vec![]));
}
- if op == KleeneOp::ZeroOrMore || op == KleeneOp::ZeroOrOne {
+ if matches!(op, KleeneOp::ZeroOrMore | KleeneOp::ZeroOrOne) {
// Try zero matches of this sequence, by skipping over it.
self.cur_mps.push(MatcherPos {
idx: idx_first_after,
diff --git a/compiler/rustc_expand/src/mbe/macro_rules.rs b/compiler/rustc_expand/src/mbe/macro_rules.rs
index 4ebd75f01..5679cdcbb 100644
--- a/compiler/rustc_expand/src/mbe/macro_rules.rs
+++ b/compiler/rustc_expand/src/mbe/macro_rules.rs
@@ -10,13 +10,12 @@ use crate::mbe::transcribe::transcribe;
use rustc_ast as ast;
use rustc_ast::token::{self, Delimiter, NonterminalKind, Token, TokenKind, TokenKind::*};
-use rustc_ast::tokenstream::{DelimSpan, TokenStream};
+use rustc_ast::tokenstream::{DelimSpan, TokenStream, TokenTree};
use rustc_ast::{NodeId, DUMMY_NODE_ID};
use rustc_ast_pretty::pprust;
use rustc_attr::{self as attr, TransparencyError};
use rustc_data_structures::fx::{FxHashMap, FxIndexMap};
use rustc_errors::{Applicability, ErrorGuaranteed};
-use rustc_feature::Features;
use rustc_lint_defs::builtin::{
RUST_2021_INCOMPATIBLE_OR_PATTERNS, SEMICOLON_IN_EXPRESSIONS_FROM_MACROS,
};
@@ -212,7 +211,6 @@ fn expand_macro<'cx>(
};
let arm_span = rhses[i].span();
- let rhs_spans = rhs.tts.iter().map(|t| t.span()).collect::<Vec<_>>();
// rhs has holes ( `$id` and `$(...)` that need filled)
let mut tts = match transcribe(cx, &named_matches, &rhs, rhs_span, transparency) {
Ok(tts) => tts,
@@ -224,12 +222,25 @@ fn expand_macro<'cx>(
// Replace all the tokens for the corresponding positions in the macro, to maintain
// proper positions in error reporting, while maintaining the macro_backtrace.
- if rhs_spans.len() == tts.len() {
+ if tts.len() == rhs.tts.len() {
tts = tts.map_enumerated(|i, tt| {
let mut tt = tt.clone();
- let mut sp = rhs_spans[i];
- sp = sp.with_ctxt(tt.span().ctxt());
- tt.set_span(sp);
+ let rhs_tt = &rhs.tts[i];
+ let ctxt = tt.span().ctxt();
+ match (&mut tt, rhs_tt) {
+ // preserve the delim spans if able
+ (
+ TokenTree::Delimited(target_sp, ..),
+ mbe::TokenTree::Delimited(source_sp, ..),
+ ) => {
+ target_sp.open = source_sp.open.with_ctxt(ctxt);
+ target_sp.close = source_sp.close.with_ctxt(ctxt);
+ }
+ _ => {
+ let sp = rhs_tt.span().with_ctxt(ctxt);
+ tt.set_span(sp);
+ }
+ }
tt
});
}
@@ -367,7 +378,6 @@ pub(super) fn try_match_macro<'matcher, T: Tracker<'matcher>>(
/// Converts a macro item into a syntax extension.
pub fn compile_declarative_macro(
sess: &Session,
- features: &Features,
def: &ast::Item,
edition: Edition,
) -> (SyntaxExtension, Vec<(usize, Span)>) {
@@ -496,7 +506,7 @@ pub fn compile_declarative_macro(
true,
&sess.parse_sess,
def.id,
- features,
+ sess.features_untracked(),
edition,
)
.pop()
@@ -520,7 +530,7 @@ pub fn compile_declarative_macro(
false,
&sess.parse_sess,
def.id,
- features,
+ sess.features_untracked(),
edition,
)
.pop()
diff --git a/compiler/rustc_expand/src/mbe/metavar_expr.rs b/compiler/rustc_expand/src/mbe/metavar_expr.rs
index 99fe47454..de34df011 100644
--- a/compiler/rustc_expand/src/mbe/metavar_expr.rs
+++ b/compiler/rustc_expand/src/mbe/metavar_expr.rs
@@ -1,5 +1,5 @@
use rustc_ast::token::{self, Delimiter};
-use rustc_ast::tokenstream::{CursorRef, TokenStream, TokenTree};
+use rustc_ast::tokenstream::{RefTokenTreeCursor, TokenStream, TokenTree};
use rustc_ast::{LitIntType, LitKind};
use rustc_ast_pretty::pprust;
use rustc_errors::{Applicability, PResult};
@@ -72,7 +72,7 @@ impl MetaVarExpr {
// Checks if there are any remaining tokens. For example, `${ignore(ident ... a b c ...)}`
fn check_trailing_token<'sess>(
- iter: &mut CursorRef<'_>,
+ iter: &mut RefTokenTreeCursor<'_>,
sess: &'sess ParseSess,
) -> PResult<'sess, ()> {
if let Some(tt) = iter.next() {
@@ -88,7 +88,7 @@ fn check_trailing_token<'sess>(
/// Parse a meta-variable `count` expression: `count(ident[, depth])`
fn parse_count<'sess>(
- iter: &mut CursorRef<'_>,
+ iter: &mut RefTokenTreeCursor<'_>,
sess: &'sess ParseSess,
span: Span,
) -> PResult<'sess, MetaVarExpr> {
@@ -99,7 +99,7 @@ fn parse_count<'sess>(
/// Parses the depth used by index(depth) and length(depth).
fn parse_depth<'sess>(
- iter: &mut CursorRef<'_>,
+ iter: &mut RefTokenTreeCursor<'_>,
sess: &'sess ParseSess,
span: Span,
) -> PResult<'sess, usize> {
@@ -126,7 +126,7 @@ fn parse_depth<'sess>(
/// Parses an generic ident
fn parse_ident<'sess>(
- iter: &mut CursorRef<'_>,
+ iter: &mut RefTokenTreeCursor<'_>,
sess: &'sess ParseSess,
span: Span,
) -> PResult<'sess, Ident> {
@@ -152,7 +152,7 @@ fn parse_ident<'sess>(
/// Tries to move the iterator forward returning `true` if there is a comma. If not, then the
/// iterator is not modified and the result is `false`.
-fn try_eat_comma(iter: &mut CursorRef<'_>) -> bool {
+fn try_eat_comma(iter: &mut RefTokenTreeCursor<'_>) -> bool {
if let Some(TokenTree::Token(token::Token { kind: token::Comma, .. }, _)) = iter.look_ahead(0) {
let _ = iter.next();
return true;
diff --git a/compiler/rustc_expand/src/mbe/transcribe.rs b/compiler/rustc_expand/src/mbe/transcribe.rs
index b79835be7..47a8b4bc4 100644
--- a/compiler/rustc_expand/src/mbe/transcribe.rs
+++ b/compiler/rustc_expand/src/mbe/transcribe.rs
@@ -282,7 +282,7 @@ pub(super) fn transcribe<'a>(
}
// There should be no meta-var declarations in the invocation of a macro.
- mbe::TokenTree::MetaVarDecl(..) => panic!("unexpected `TokenTree::MetaVarDecl"),
+ mbe::TokenTree::MetaVarDecl(..) => panic!("unexpected `TokenTree::MetaVarDecl`"),
}
}
}
diff --git a/compiler/rustc_expand/src/module.rs b/compiler/rustc_expand/src/module.rs
index 07f47a9c3..3779af19e 100644
--- a/compiler/rustc_expand/src/module.rs
+++ b/compiler/rustc_expand/src/module.rs
@@ -12,8 +12,8 @@ use rustc_session::Session;
use rustc_span::symbol::{sym, Ident};
use rustc_span::Span;
use std::iter::once;
-
use std::path::{self, Path, PathBuf};
+use thin_vec::ThinVec;
#[derive(Copy, Clone)]
pub enum DirOwnership {
@@ -31,7 +31,7 @@ pub struct ModulePathSuccess {
}
pub(crate) struct ParsedExternalMod {
- pub items: Vec<P<Item>>,
+ pub items: ThinVec<P<Item>>,
pub spans: ModSpans,
pub file_path: PathBuf,
pub dir_path: PathBuf,
diff --git a/compiler/rustc_expand/src/parse/tests.rs b/compiler/rustc_expand/src/parse/tests.rs
index 0726d922c..8b37728b6 100644
--- a/compiler/rustc_expand/src/parse/tests.rs
+++ b/compiler/rustc_expand/src/parse/tests.rs
@@ -18,7 +18,10 @@ use rustc_span::{BytePos, FileName, Pos, Span};
use std::path::PathBuf;
fn sess() -> ParseSess {
- ParseSess::new(FilePathMapping::empty())
+ ParseSess::new(
+ vec![crate::DEFAULT_LOCALE_RESOURCE, rustc_parse::DEFAULT_LOCALE_RESOURCE],
+ FilePathMapping::empty(),
+ )
}
/// Parses an item.
diff --git a/compiler/rustc_expand/src/proc_macro.rs b/compiler/rustc_expand/src/proc_macro.rs
index e9a691920..ddba14417 100644
--- a/compiler/rustc_expand/src/proc_macro.rs
+++ b/compiler/rustc_expand/src/proc_macro.rs
@@ -1,4 +1,5 @@
use crate::base::{self, *};
+use crate::errors;
use crate::proc_macro_server;
use rustc_ast as ast;
@@ -60,11 +61,12 @@ impl base::BangProcMacro for BangProcMacro {
let strategy = exec_strategy(ecx);
let server = proc_macro_server::Rustc::new(ecx);
self.client.run(&strategy, server, input, proc_macro_backtrace).map_err(|e| {
- let mut err = ecx.struct_span_err(span, "proc macro panicked");
- if let Some(s) = e.as_str() {
- err.help(&format!("message: {}", s));
- }
- err.emit()
+ ecx.sess.emit_err(errors::ProcMacroPanicked {
+ span,
+ message: e
+ .as_str()
+ .map(|message| errors::ProcMacroPanickedHelp { message: message.into() }),
+ })
})
}
}
@@ -174,7 +176,7 @@ impl MultiItemModifier for DeriveProcMacro {
// fail if there have been errors emitted
if ecx.sess.parse_sess.span_diagnostic.err_count() > error_count_before {
- ecx.struct_span_err(span, "proc-macro derive produced unparseable tokens").emit();
+ ecx.sess.emit_err(errors::ProcMacroDeriveTokens { span });
}
ExpandResult::Ready(items)
diff --git a/compiler/rustc_expand/src/tests.rs b/compiler/rustc_expand/src/tests.rs
index 8f3bea29f..480d95b77 100644
--- a/compiler/rustc_expand/src/tests.rs
+++ b/compiler/rustc_expand/src/tests.rs
@@ -8,7 +8,7 @@ use rustc_span::{BytePos, Span};
use rustc_data_structures::sync::Lrc;
use rustc_errors::emitter::EmitterWriter;
-use rustc_errors::{Handler, MultiSpan, PResult};
+use rustc_errors::{Handler, MultiSpan, PResult, TerminalUrl};
use std::io;
use std::io::prelude::*;
@@ -34,18 +34,23 @@ where
/// Maps a string to tts, using a made-up filename.
pub(crate) fn string_to_stream(source_str: String) -> TokenStream {
- let ps = ParseSess::new(FilePathMapping::empty());
+ let ps = ParseSess::new(
+ vec![crate::DEFAULT_LOCALE_RESOURCE, rustc_parse::DEFAULT_LOCALE_RESOURCE],
+ FilePathMapping::empty(),
+ );
source_file_to_stream(
&ps,
ps.source_map().new_source_file(PathBuf::from("bogofile").into(), source_str),
None,
)
- .0
}
/// Parses a string, returns a crate.
pub(crate) fn string_to_crate(source_str: String) -> ast::Crate {
- let ps = ParseSess::new(FilePathMapping::empty());
+ let ps = ParseSess::new(
+ vec![crate::DEFAULT_LOCALE_RESOURCE, rustc_parse::DEFAULT_LOCALE_RESOURCE],
+ FilePathMapping::empty(),
+ );
with_error_checking_parse(source_str, &ps, |p| p.parse_crate_mod())
}
@@ -127,8 +132,10 @@ fn test_harness(file_text: &str, span_labels: Vec<SpanLabel>, expected_output: &
create_default_session_if_not_set_then(|_| {
let output = Arc::new(Mutex::new(Vec::new()));
- let fallback_bundle =
- rustc_errors::fallback_fluent_bundle(rustc_errors::DEFAULT_LOCALE_RESOURCES, false);
+ let fallback_bundle = rustc_errors::fallback_fluent_bundle(
+ vec![crate::DEFAULT_LOCALE_RESOURCE, rustc_parse::DEFAULT_LOCALE_RESOURCE],
+ false,
+ );
let source_map = Lrc::new(SourceMap::new(FilePathMapping::empty()));
source_map.new_source_file(Path::new("test.rs").to_owned().into(), file_text.to_owned());
@@ -152,6 +159,7 @@ fn test_harness(file_text: &str, span_labels: Vec<SpanLabel>, expected_output: &
None,
false,
false,
+ TerminalUrl::No,
);
let handler = Handler::with_emitter(true, None, Box::new(emitter));
#[allow(rustc::untranslatable_diagnostic)]
diff --git a/compiler/rustc_feature/src/accepted.rs b/compiler/rustc_feature/src/accepted.rs
index e064e87a5..d304d38e1 100644
--- a/compiler/rustc_feature/src/accepted.rs
+++ b/compiler/rustc_feature/src/accepted.rs
@@ -90,6 +90,8 @@ declare_features! (
(accepted, clone_closures, "1.26.0", Some(44490), None),
/// Allows coercing non capturing closures to function pointers.
(accepted, closure_to_fn_coercion, "1.19.0", Some(39817), None),
+ /// Allows using `cmpxchg16b` from `core::arch::x86_64`.
+ (accepted, cmpxchg16b_target_feature, "1.69.0", Some(44839), None),
/// Allows usage of the `compile_error!` macro.
(accepted, compile_error, "1.20.0", Some(40872), None),
/// Allows `impl Trait` in function return types.
diff --git a/compiler/rustc_feature/src/active.rs b/compiler/rustc_feature/src/active.rs
index b5256043e..baea5968e 100644
--- a/compiler/rustc_feature/src/active.rs
+++ b/compiler/rustc_feature/src/active.rs
@@ -160,6 +160,8 @@ declare_features! (
(active, intrinsics, "1.0.0", None, None),
/// Allows using `#[lang = ".."]` attribute for linking items to special compiler logic.
(active, lang_items, "1.0.0", None, None),
+ /// Allows the `multiple_supertrait_upcastable` lint.
+ (active, multiple_supertrait_upcastable, "1.69.0", None, None),
/// Allows using `#[omit_gdb_pretty_printer_section]`.
(active, omit_gdb_pretty_printer_section, "1.5.0", None, None),
/// Allows using `#[prelude_import]` on glob `use` items.
@@ -213,6 +215,8 @@ declare_features! (
(active, linkage, "1.0.0", Some(29603), None),
/// Allows declaring with `#![needs_panic_runtime]` that a panic runtime is needed.
(active, needs_panic_runtime, "1.10.0", Some(32837), None),
+ /// Allows using `+bundled,+whole-archive` native libs.
+ (active, packed_bundled_libs, "1.69.0", Some(108081), None),
/// Allows using the `#![panic_runtime]` attribute.
(active, panic_runtime, "1.10.0", Some(32837), None),
/// Allows using `#[rustc_allow_const_fn_unstable]`.
@@ -252,7 +256,6 @@ declare_features! (
(active, arm_target_feature, "1.27.0", Some(44839), None),
(active, avx512_target_feature, "1.27.0", Some(44839), None),
(active, bpf_target_feature, "1.54.0", Some(44839), None),
- (active, cmpxchg16b_target_feature, "1.32.0", Some(44839), None),
(active, ermsb_target_feature, "1.49.0", Some(44839), None),
(active, hexagon_target_feature, "1.27.0", Some(44839), None),
(active, mips_target_feature, "1.27.0", Some(44839), None),
@@ -313,8 +316,6 @@ declare_features! (
(active, c_unwind, "1.52.0", Some(74990), None),
/// Allows using C-variadics.
(active, c_variadic, "1.34.0", Some(44930), None),
- /// Allows capturing disjoint fields in a closure/generator (RFC 2229).
- (incomplete, capture_disjoint_fields, "1.49.0", Some(53488), None),
/// Allows the use of `#[cfg(sanitize = "option")]`; set when -Zsanitizer is used.
(active, cfg_sanitize, "1.41.0", Some(39699), None),
/// Allows `cfg(target_abi = "...")`.
@@ -469,6 +470,8 @@ declare_features! (
(active, no_sanitize, "1.42.0", Some(39699), None),
/// Allows using the `non_exhaustive_omitted_patterns` lint.
(active, non_exhaustive_omitted_patterns_lint, "1.57.0", Some(89554), None),
+ /// Allows `for<T>` binders in where-clauses
+ (incomplete, non_lifetime_binders, "1.69.0", Some(108185), None),
/// Allows making `dyn Trait` well-formed even if `Trait` is not object safe.
/// In that case, `dyn Trait: Trait` does not hold. Moreover, coercions and
/// casts in safe Rust to `dyn Trait` for such a `Trait` is also forbidden.
diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs
index af56a0b24..493a9cd89 100644
--- a/compiler/rustc_feature/src/builtin_attrs.rs
+++ b/compiler/rustc_feature/src/builtin_attrs.rs
@@ -414,7 +414,10 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
),
// Linking:
- gated!(naked, Normal, template!(Word), WarnFollowing, @only_local: true, naked_functions, experimental!(naked)),
+ gated!(
+ naked, Normal, template!(Word), WarnFollowing, @only_local: true,
+ naked_functions, experimental!(naked)
+ ),
// Plugins:
BuiltinAttribute {
@@ -441,7 +444,8 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
),
// RFC #1268
gated!(
- marker, Normal, template!(Word), WarnFollowing, marker_trait_attr, experimental!(marker)
+ marker, Normal, template!(Word), WarnFollowing, @only_local: true,
+ marker_trait_attr, experimental!(marker)
),
gated!(
thread_local, Normal, template!(Word), WarnFollowing,
@@ -682,8 +686,7 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
"language items are subject to change",
),
rustc_attr!(
- rustc_pass_by_value, Normal,
- template!(Word), ErrorFollowing,
+ rustc_pass_by_value, Normal, template!(Word), ErrorFollowing,
"#[rustc_pass_by_value] is used to mark types that must be passed by value instead of reference."
),
rustc_attr!(
@@ -691,6 +694,10 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
"#![rustc_coherence_is_core] allows inherent methods on builtin types, only intended to be used in `core`."
),
rustc_attr!(
+ rustc_coinductive, AttributeType::Normal, template!(Word), WarnFollowing, @only_local: true,
+ "#![rustc_coinductive] changes a trait to be coinductive, allowing cycles in the trait solver."
+ ),
+ rustc_attr!(
rustc_allow_incoherent_impl, AttributeType::Normal, template!(Word), ErrorFollowing, @only_local: true,
"#[rustc_allow_incoherent_impl] has to be added to all impl items of an incoherent inherent impl."
),
diff --git a/compiler/rustc_feature/src/lib.rs b/compiler/rustc_feature/src/lib.rs
index 8e2a13a6c..93d167163 100644
--- a/compiler/rustc_feature/src/lib.rs
+++ b/compiler/rustc_feature/src/lib.rs
@@ -83,7 +83,8 @@ impl UnstableFeatures {
/// Otherwise, only `RUSTC_BOOTSTRAP=1` will work.
pub fn from_environment(krate: Option<&str>) -> Self {
// `true` if this is a feature-staged build, i.e., on the beta or stable channel.
- let disable_unstable_features = option_env!("CFG_DISABLE_UNSTABLE_FEATURES").is_some();
+ let disable_unstable_features =
+ option_env!("CFG_DISABLE_UNSTABLE_FEATURES").map(|s| s != "0").unwrap_or(false);
// Returns whether `krate` should be counted as unstable
let is_unstable_crate = |var: &str| {
krate.map_or(false, |name| var.split(',').any(|new_krate| new_krate == name))
diff --git a/compiler/rustc_feature/src/removed.rs b/compiler/rustc_feature/src/removed.rs
index 79a12801d..04d4f6cb1 100644
--- a/compiler/rustc_feature/src/removed.rs
+++ b/compiler/rustc_feature/src/removed.rs
@@ -52,6 +52,8 @@ declare_features! (
(removed, allow_fail, "1.19.0", Some(46488), None, Some("removed due to no clear use cases")),
(removed, await_macro, "1.38.0", Some(50547), None,
Some("subsumed by `.await` syntax")),
+ /// Allows capturing disjoint fields in a closure/generator (RFC 2229).
+ (removed, capture_disjoint_fields, "1.49.0", Some(53488), None, Some("stabilized in Rust 2021")),
/// Allows comparing raw pointers during const eval.
(removed, const_compare_raw_pointers, "1.46.0", Some(53020), None,
Some("cannot be allowed in const eval in any meaningful way")),
diff --git a/compiler/rustc_hir/src/def.rs b/compiler/rustc_hir/src/def.rs
index cca5ead0f..8c58129c8 100644
--- a/compiler/rustc_hir/src/def.rs
+++ b/compiler/rustc_hir/src/def.rs
@@ -2,6 +2,8 @@ use crate::hir;
use rustc_ast as ast;
use rustc_ast::NodeId;
+use rustc_data_structures::fx::FxHashMap;
+use rustc_data_structures::stable_hasher::ToStableHashKey;
use rustc_macros::HashStable_Generic;
use rustc_span::def_id::{DefId, LocalDefId};
use rustc_span::hygiene::MacroKind;
@@ -114,12 +116,19 @@ pub enum DefKind {
LifetimeParam,
/// A use of `global_asm!`.
GlobalAsm,
- Impl,
+ Impl {
+ of_trait: bool,
+ },
Closure,
Generator,
}
impl DefKind {
+ /// Get an English description for the item's kind.
+ ///
+ /// If you have access to `TyCtxt`, use `TyCtxt::def_descr` or
+ /// `TyCtxt::def_kind_descr` instead, because they give better
+ /// information for generators and associated functions.
pub fn descr(self, def_id: DefId) -> &'static str {
match self {
DefKind::Fn => "function",
@@ -153,7 +162,7 @@ impl DefKind {
DefKind::AnonConst => "constant expression",
DefKind::InlineConst => "inline constant",
DefKind::Field => "field",
- DefKind::Impl => "implementation",
+ DefKind::Impl { .. } => "implementation",
DefKind::Closure => "closure",
DefKind::Generator => "generator",
DefKind::ExternCrate => "extern crate",
@@ -162,6 +171,10 @@ impl DefKind {
}
/// Gets an English article for the definition.
+ ///
+ /// If you have access to `TyCtxt`, use `TyCtxt::def_descr_article` or
+ /// `TyCtxt::def_kind_descr_article` instead, because they give better
+ /// information for generators and associated functions.
pub fn article(&self) -> &'static str {
match *self {
DefKind::AssocTy
@@ -169,7 +182,7 @@ impl DefKind {
| DefKind::AssocFn
| DefKind::Enum
| DefKind::OpaqueTy
- | DefKind::Impl
+ | DefKind::Impl { .. }
| DefKind::Use
| DefKind::InlineConst
| DefKind::ExternCrate => "an",
@@ -214,7 +227,7 @@ impl DefKind {
| DefKind::Use
| DefKind::ForeignMod
| DefKind::GlobalAsm
- | DefKind::Impl
+ | DefKind::Impl { .. }
| DefKind::ImplTraitPlaceholder => None,
}
}
@@ -253,7 +266,7 @@ impl DefKind {
| DefKind::ForeignMod
| DefKind::OpaqueTy
| DefKind::ImplTraitPlaceholder
- | DefKind::Impl
+ | DefKind::Impl { .. }
| DefKind::Field
| DefKind::TyParam
| DefKind::ConstParam
@@ -472,7 +485,8 @@ impl PartialRes {
/// Different kinds of symbols can coexist even if they share the same textual name.
/// Therefore, they each have a separate universe (known as a "namespace").
-#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
+#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Encodable, Decodable)]
+#[derive(HashStable_Generic)]
pub enum Namespace {
/// The type namespace includes `struct`s, `enum`s, `union`s, `trait`s, and `mod`s
/// (and, by extension, crates).
@@ -499,6 +513,15 @@ impl Namespace {
}
}
+impl<CTX: crate::HashStableContext> ToStableHashKey<CTX> for Namespace {
+ type KeyType = Namespace;
+
+ #[inline]
+ fn to_stable_hash_key(&self, _: &CTX) -> Namespace {
+ *self
+ }
+}
+
/// Just a helper ‒ separate structure for each namespace.
#[derive(Copy, Clone, Default, Debug)]
pub struct PerNS<T> {
@@ -760,3 +783,5 @@ pub enum LifetimeRes {
/// HACK: This is used to recover the NodeId of an elided lifetime.
ElidedAnchor { start: NodeId, end: NodeId },
}
+
+pub type DocLinkResMap = FxHashMap<(Symbol, Namespace), Option<Res<NodeId>>>;
diff --git a/compiler/rustc_hir/src/definitions.rs b/compiler/rustc_hir/src/definitions.rs
index 21cf214e4..8ceb17649 100644
--- a/compiler/rustc_hir/src/definitions.rs
+++ b/compiler/rustc_hir/src/definitions.rs
@@ -92,7 +92,7 @@ impl DefPathTable {
/// The definition table containing node definitions.
/// It holds the `DefPathTable` for `LocalDefId`s/`DefPath`s.
/// It also stores mappings to convert `LocalDefId`s to/from `HirId`s.
-#[derive(Clone, Debug)]
+#[derive(Debug)]
pub struct Definitions {
table: DefPathTable,
next_disambiguator: FxHashMap<(LocalDefId, DefPathData), u32>,
@@ -280,6 +280,8 @@ pub enum DefPathData {
AnonConst,
/// An `impl Trait` type node.
ImplTrait,
+ /// `impl Trait` generated associated type node.
+ ImplTraitAssocTy,
}
impl Definitions {
@@ -403,7 +405,7 @@ impl DefPathData {
TypeNs(name) | ValueNs(name) | MacroNs(name) | LifetimeNs(name) => Some(name),
Impl | ForeignMod | CrateRoot | Use | GlobalAsm | ClosureExpr | Ctor | AnonConst
- | ImplTrait => None,
+ | ImplTrait | ImplTraitAssocTy => None,
}
}
@@ -422,7 +424,7 @@ impl DefPathData {
ClosureExpr => DefPathDataName::Anon { namespace: sym::closure },
Ctor => DefPathDataName::Anon { namespace: sym::constructor },
AnonConst => DefPathDataName::Anon { namespace: sym::constant },
- ImplTrait => DefPathDataName::Anon { namespace: sym::opaque },
+ ImplTrait | ImplTraitAssocTy => DefPathDataName::Anon { namespace: sym::opaque },
}
}
}
diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs
index d6566860f..19d3d41c9 100644
--- a/compiler/rustc_hir/src/hir.rs
+++ b/compiler/rustc_hir/src/hir.rs
@@ -369,10 +369,10 @@ impl<'hir> GenericArgs<'hir> {
pub fn has_err(&self) -> bool {
self.args.iter().any(|arg| match arg {
- GenericArg::Type(ty) => matches!(ty.kind, TyKind::Err),
+ GenericArg::Type(ty) => matches!(ty.kind, TyKind::Err(_)),
_ => false,
}) || self.bindings.iter().any(|arg| match arg.kind {
- TypeBindingKind::Equality { term: Term::Ty(ty) } => matches!(ty.kind, TyKind::Err),
+ TypeBindingKind::Equality { term: Term::Ty(ty) } => matches!(ty.kind, TyKind::Err(_)),
_ => false,
})
}
@@ -498,6 +498,7 @@ pub struct GenericParam<'hir> {
pub pure_wrt_drop: bool,
pub kind: GenericParamKind<'hir>,
pub colon_span: Option<Span>,
+ pub source: GenericParamSource,
}
impl<'hir> GenericParam<'hir> {
@@ -516,6 +517,20 @@ impl<'hir> GenericParam<'hir> {
}
}
+/// Records where the generic parameter originated from.
+///
+/// This can either be from an item's generics, in which case it's typically
+/// early-bound (but can be a late-bound lifetime in functions, for example),
+/// or from a `for<...>` binder, in which case it's late-bound (and notably,
+/// does not show up in the parent item's generics).
+#[derive(Debug, HashStable_Generic, PartialEq, Eq, Copy, Clone)]
+pub enum GenericParamSource {
+ // Early or late-bound parameters defined on an item
+ Generics,
+ // Late-bound parameters defined via a `for<...>`
+ Binder,
+}
+
#[derive(Default)]
pub struct GenericParamCount {
pub lifetimes: usize,
@@ -574,14 +589,11 @@ impl<'hir> Generics<'hir> {
/// If there are generic parameters, return where to introduce a new one.
pub fn span_for_param_suggestion(&self) -> Option<Span> {
- if self.params.iter().any(|p| self.span.contains(p.span)) {
+ self.params.iter().any(|p| self.span.contains(p.span)).then(|| {
// `fn foo<A>(t: impl Trait)`
// ^ suggest `, T: Trait` here
- let span = self.span.with_lo(self.span.hi() - BytePos(1)).shrink_to_lo();
- Some(span)
- } else {
- None
- }
+ self.span.with_lo(self.span.hi() - BytePos(1)).shrink_to_lo()
+ })
}
/// `Span` where further predicates would be suggested, accounting for trailing commas, like
@@ -639,7 +651,7 @@ impl<'hir> Generics<'hir> {
// We include bounds that come from a `#[derive(_)]` but point at the user's code,
// as we use this method to get a span appropriate for suggestions.
let bs = bound.span();
- if bs.can_be_used_for_suggestions() { Some(bs.shrink_to_hi()) } else { None }
+ bs.can_be_used_for_suggestions().then(|| bs.shrink_to_hi())
},
)
}
@@ -831,8 +843,6 @@ pub struct OwnerNodes<'tcx> {
pub nodes: IndexVec<ItemLocalId, Option<ParentedNode<'tcx>>>,
/// Content of local bodies.
pub bodies: SortedMap<ItemLocalId, &'tcx Body<'tcx>>,
- /// Non-owning definitions contained in this owner.
- pub local_id_to_def_id: SortedMap<ItemLocalId, LocalDefId>,
}
impl<'tcx> OwnerNodes<'tcx> {
@@ -862,7 +872,6 @@ impl fmt::Debug for OwnerNodes<'_> {
.collect::<Vec<_>>(),
)
.field("bodies", &self.bodies)
- .field("local_id_to_def_id", &self.local_id_to_def_id)
.field("hash_without_bodies", &self.hash_without_bodies)
.field("hash_including_bodies", &self.hash_including_bodies)
.finish()
@@ -993,7 +1002,6 @@ pub struct Pat<'hir> {
}
impl<'hir> Pat<'hir> {
- // FIXME(#19596) this is a workaround, but there should be a better way
fn walk_short_(&self, it: &mut impl FnMut(&Pat<'hir>) -> bool) -> bool {
if !it(self) {
return false;
@@ -1021,7 +1029,6 @@ impl<'hir> Pat<'hir> {
self.walk_short_(&mut it)
}
- // FIXME(#19596) this is a workaround, but there should be a better way
fn walk_(&self, it: &mut impl FnMut(&Pat<'hir>) -> bool) {
if !it(self) {
return;
@@ -1696,7 +1703,7 @@ impl Expr<'_> {
ExprKind::Struct(..) => ExprPrecedence::Struct,
ExprKind::Repeat(..) => ExprPrecedence::Repeat,
ExprKind::Yield(..) => ExprPrecedence::Yield,
- ExprKind::Err => ExprPrecedence::Err,
+ ExprKind::Err(_) => ExprPrecedence::Err,
}
}
@@ -1762,7 +1769,7 @@ impl Expr<'_> {
| ExprKind::Yield(..)
| ExprKind::Cast(..)
| ExprKind::DropTemps(..)
- | ExprKind::Err => false,
+ | ExprKind::Err(_) => false,
}
}
@@ -1848,7 +1855,7 @@ impl Expr<'_> {
| ExprKind::Binary(..)
| ExprKind::Yield(..)
| ExprKind::DropTemps(..)
- | ExprKind::Err => true,
+ | ExprKind::Err(_) => true,
}
}
@@ -2021,7 +2028,7 @@ pub enum ExprKind<'hir> {
Yield(&'hir Expr<'hir>, YieldSource),
/// A placeholder for an expression that wasn't syntactically well formed in some way.
- Err,
+ Err(rustc_span::ErrorGuaranteed),
}
/// Represents an optionally `Self`-qualified value/type path or associated extension.
@@ -2106,8 +2113,8 @@ pub enum LocalSource {
}
/// Hints at the original code for a `match _ { .. }`.
-#[derive(Copy, Clone, PartialEq, Eq, Encodable, Hash, Debug)]
-#[derive(HashStable_Generic)]
+#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
+#[derive(HashStable_Generic, Encodable, Decodable)]
pub enum MatchSource {
/// A `match _ { .. }`.
Normal,
@@ -2117,6 +2124,8 @@ pub enum MatchSource {
TryDesugar,
/// A desugared `<expr>.await`.
AwaitDesugar,
+ /// A desugared `format_args!()`.
+ FormatArgs,
}
impl MatchSource {
@@ -2128,6 +2137,7 @@ impl MatchSource {
ForLoopDesugar => "for",
TryDesugar => "?",
AwaitDesugar => ".await",
+ FormatArgs => "format_args!()",
}
}
}
@@ -2263,7 +2273,7 @@ pub struct TraitItem<'hir> {
pub defaultness: Defaultness,
}
-impl TraitItem<'_> {
+impl<'hir> TraitItem<'hir> {
#[inline]
pub fn hir_id(&self) -> HirId {
// Items are always HIR owners.
@@ -2273,6 +2283,32 @@ impl TraitItem<'_> {
pub fn trait_item_id(&self) -> TraitItemId {
TraitItemId { owner_id: self.owner_id }
}
+
+ /// Expect an [`TraitItemKind::Const`] or panic.
+ #[track_caller]
+ pub fn expect_const(&self) -> (&'hir Ty<'hir>, Option<BodyId>) {
+ let TraitItemKind::Const(ty, body) = self.kind else { self.expect_failed("a constant") };
+ (ty, body)
+ }
+
+ /// Expect an [`TraitItemKind::Fn`] or panic.
+ #[track_caller]
+ pub fn expect_fn(&self) -> (&FnSig<'hir>, &TraitFn<'hir>) {
+ let TraitItemKind::Fn(ty, trfn) = &self.kind else { self.expect_failed("a function") };
+ (ty, trfn)
+ }
+
+ /// Expect an [`TraitItemKind::Type`] or panic.
+ #[track_caller]
+ pub fn expect_type(&self) -> (GenericBounds<'hir>, Option<&'hir Ty<'hir>>) {
+ let TraitItemKind::Type(bounds, ty) = self.kind else { self.expect_failed("a type") };
+ (bounds, ty)
+ }
+
+ #[track_caller]
+ fn expect_failed(&self, expected: &'static str) -> ! {
+ panic!("expected {expected} item, found {self:?}")
+ }
}
/// Represents a trait method's body (or just argument names).
@@ -2325,7 +2361,7 @@ pub struct ImplItem<'hir> {
pub vis_span: Span,
}
-impl ImplItem<'_> {
+impl<'hir> ImplItem<'hir> {
#[inline]
pub fn hir_id(&self) -> HirId {
// Items are always HIR owners.
@@ -2335,6 +2371,32 @@ impl ImplItem<'_> {
pub fn impl_item_id(&self) -> ImplItemId {
ImplItemId { owner_id: self.owner_id }
}
+
+ /// Expect an [`ImplItemKind::Const`] or panic.
+ #[track_caller]
+ pub fn expect_const(&self) -> (&'hir Ty<'hir>, BodyId) {
+ let ImplItemKind::Const(ty, body) = self.kind else { self.expect_failed("a constant") };
+ (ty, body)
+ }
+
+ /// Expect an [`ImplItemKind::Fn`] or panic.
+ #[track_caller]
+ pub fn expect_fn(&self) -> (&FnSig<'hir>, BodyId) {
+ let ImplItemKind::Fn(ty, body) = &self.kind else { self.expect_failed("a function") };
+ (ty, *body)
+ }
+
+ /// Expect an [`ImplItemKind::Type`] or panic.
+ #[track_caller]
+ pub fn expect_type(&self) -> &'hir Ty<'hir> {
+ let ImplItemKind::Type(ty) = self.kind else { self.expect_failed("a type") };
+ ty
+ }
+
+ #[track_caller]
+ fn expect_failed(&self, expected: &'static str) -> ! {
+ panic!("expected {expected} item, found {self:?}")
+ }
}
/// Represents various kinds of content within an `impl`.
@@ -2629,7 +2691,7 @@ pub enum TyKind<'hir> {
/// specified. This can appear anywhere in a type.
Infer,
/// Placeholder for a type that has failed to be defined.
- Err,
+ Err(rustc_span::ErrorGuaranteed),
}
#[derive(Debug, HashStable_Generic)]
@@ -2995,7 +3057,7 @@ pub struct Item<'hir> {
pub vis_span: Span,
}
-impl Item<'_> {
+impl<'hir> Item<'hir> {
#[inline]
pub fn hir_id(&self) -> HirId {
// Items are always HIR owners.
@@ -3005,6 +3067,132 @@ impl Item<'_> {
pub fn item_id(&self) -> ItemId {
ItemId { owner_id: self.owner_id }
}
+
+ /// Expect an [`ItemKind::ExternCrate`] or panic.
+ #[track_caller]
+ pub fn expect_extern_crate(&self) -> Option<Symbol> {
+ let ItemKind::ExternCrate(s) = self.kind else { self.expect_failed("an extern crate") };
+ s
+ }
+
+ /// Expect an [`ItemKind::Use`] or panic.
+ #[track_caller]
+ pub fn expect_use(&self) -> (&'hir UsePath<'hir>, UseKind) {
+ let ItemKind::Use(p, uk) = self.kind else { self.expect_failed("a use") };
+ (p, uk)
+ }
+
+ /// Expect an [`ItemKind::Static`] or panic.
+ #[track_caller]
+ pub fn expect_static(&self) -> (&'hir Ty<'hir>, Mutability, BodyId) {
+ let ItemKind::Static(ty, mutbl, body) = self.kind else { self.expect_failed("a static") };
+ (ty, mutbl, body)
+ }
+ /// Expect an [`ItemKind::Const`] or panic.
+ #[track_caller]
+ pub fn expect_const(&self) -> (&'hir Ty<'hir>, BodyId) {
+ let ItemKind::Const(ty, body) = self.kind else { self.expect_failed("a constant") };
+ (ty, body)
+ }
+ /// Expect an [`ItemKind::Fn`] or panic.
+ #[track_caller]
+ pub fn expect_fn(&self) -> (&FnSig<'hir>, &'hir Generics<'hir>, BodyId) {
+ let ItemKind::Fn(sig, gen, body) = &self.kind else { self.expect_failed("a function") };
+ (sig, gen, *body)
+ }
+
+ /// Expect an [`ItemKind::Macro`] or panic.
+ #[track_caller]
+ pub fn expect_macro(&self) -> (&ast::MacroDef, MacroKind) {
+ let ItemKind::Macro(def, mk) = &self.kind else { self.expect_failed("a macro") };
+ (def, *mk)
+ }
+
+ /// Expect an [`ItemKind::Mod`] or panic.
+ #[track_caller]
+ pub fn expect_mod(&self) -> &'hir Mod<'hir> {
+ let ItemKind::Mod(m) = self.kind else { self.expect_failed("a module") };
+ m
+ }
+
+ /// Expect an [`ItemKind::ForeignMod`] or panic.
+ #[track_caller]
+ pub fn expect_foreign_mod(&self) -> (Abi, &'hir [ForeignItemRef]) {
+ let ItemKind::ForeignMod { abi, items } = self.kind else { self.expect_failed("a foreign module") };
+ (abi, items)
+ }
+
+ /// Expect an [`ItemKind::GlobalAsm`] or panic.
+ #[track_caller]
+ pub fn expect_global_asm(&self) -> &'hir InlineAsm<'hir> {
+ let ItemKind::GlobalAsm(asm) = self.kind else { self.expect_failed("a global asm") };
+ asm
+ }
+
+ /// Expect an [`ItemKind::TyAlias`] or panic.
+ #[track_caller]
+ pub fn expect_ty_alias(&self) -> (&'hir Ty<'hir>, &'hir Generics<'hir>) {
+ let ItemKind::TyAlias(ty, gen) = self.kind else { self.expect_failed("a type alias") };
+ (ty, gen)
+ }
+
+ /// An opaque `impl Trait` type alias, e.g., `type Foo = impl Bar;`.
+ /// Expect an [`ItemKind::OpaqueTy`] or panic.
+ #[track_caller]
+ pub fn expect_opaque_ty(&self) -> &OpaqueTy<'hir> {
+ let ItemKind::OpaqueTy(ty) = &self.kind else { self.expect_failed("an opaque type") };
+ ty
+ }
+
+ /// Expect an [`ItemKind::Enum`] or panic.
+ #[track_caller]
+ pub fn expect_enum(&self) -> (&EnumDef<'hir>, &'hir Generics<'hir>) {
+ let ItemKind::Enum(def, gen) = &self.kind else { self.expect_failed("an enum") };
+ (def, gen)
+ }
+
+ /// Expect an [`ItemKind::Struct`] or panic.
+ #[track_caller]
+ pub fn expect_struct(&self) -> (&VariantData<'hir>, &'hir Generics<'hir>) {
+ let ItemKind::Struct(data, gen) = &self.kind else { self.expect_failed("a struct") };
+ (data, gen)
+ }
+
+ /// A union definition, e.g., `union Foo<A, B> {x: A, y: B}`.
+ /// Expect an [`ItemKind::Union`] or panic.
+ #[track_caller]
+ pub fn expect_union(&self) -> (&VariantData<'hir>, &'hir Generics<'hir>) {
+ let ItemKind::Union(data, gen) = &self.kind else { self.expect_failed("a union") };
+ (data, gen)
+ }
+
+ /// Expect an [`ItemKind::Trait`] or panic.
+ #[track_caller]
+ pub fn expect_trait(
+ self,
+ ) -> (IsAuto, Unsafety, &'hir Generics<'hir>, GenericBounds<'hir>, &'hir [TraitItemRef]) {
+ let ItemKind::Trait(is_auto, unsafety, gen, bounds, items) = self.kind else { self.expect_failed("a trait") };
+ (is_auto, unsafety, gen, bounds, items)
+ }
+
+ /// Expect an [`ItemKind::TraitAlias`] or panic.
+ #[track_caller]
+ pub fn expect_trait_alias(&self) -> (&'hir Generics<'hir>, GenericBounds<'hir>) {
+ let ItemKind::TraitAlias(gen, bounds) = self.kind else { self.expect_failed("a trait alias") };
+ (gen, bounds)
+ }
+
+ /// Expect an [`ItemKind::Impl`] or panic.
+ #[track_caller]
+ pub fn expect_impl(&self) -> &'hir Impl<'hir> {
+ let ItemKind::Impl(imp) = self.kind else { self.expect_failed("an impl") };
+ imp
+ }
+
+ #[track_caller]
+ fn expect_failed(&self, expected: &'static str) -> ! {
+ panic!("expected {expected} item, found {self:?}")
+ }
}
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
@@ -3282,7 +3470,7 @@ pub struct Upvar {
// The TraitCandidate's import_ids is empty if the trait is defined in the same module, and
// has length > 0 if the trait is found through an chain of imports, starting with the
// import/use statement in the scope where the trait is used.
-#[derive(Encodable, Decodable, Clone, Debug, HashStable_Generic)]
+#[derive(Encodable, Decodable, Debug, HashStable_Generic)]
pub struct TraitCandidate {
pub def_id: DefId,
pub import_ids: SmallVec<[LocalDefId; 1]>,
@@ -3524,6 +3712,13 @@ impl<'hir> Node<'hir> {
}
}
+ pub fn alias_ty(self) -> Option<&'hir Ty<'hir>> {
+ match self {
+ Node::Item(Item { kind: ItemKind::TyAlias(ty, ..), .. }) => Some(ty),
+ _ => None,
+ }
+ }
+
pub fn body_id(&self) -> Option<BodyId> {
match self {
Node::TraitItem(TraitItem {
@@ -3590,6 +3785,185 @@ impl<'hir> Node<'hir> {
pub fn tuple_fields(&self) -> Option<&'hir [FieldDef<'hir>]> {
if let Node::Ctor(&VariantData::Tuple(fields, _, _)) = self { Some(fields) } else { None }
}
+
+ /// Expect a [`Node::Param`] or panic.
+ #[track_caller]
+ pub fn expect_param(self) -> &'hir Param<'hir> {
+ let Node::Param(this) = self else { self.expect_failed("a parameter") };
+ this
+ }
+
+ /// Expect a [`Node::Item`] or panic.
+ #[track_caller]
+ pub fn expect_item(self) -> &'hir Item<'hir> {
+ let Node::Item(this) = self else { self.expect_failed("a item") };
+ this
+ }
+
+ /// Expect a [`Node::ForeignItem`] or panic.
+ #[track_caller]
+ pub fn expect_foreign_item(self) -> &'hir ForeignItem<'hir> {
+ let Node::ForeignItem(this) = self else { self.expect_failed("a foreign item") };
+ this
+ }
+
+ /// Expect a [`Node::TraitItem`] or panic.
+ #[track_caller]
+ pub fn expect_trait_item(self) -> &'hir TraitItem<'hir> {
+ let Node::TraitItem(this) = self else { self.expect_failed("a trait item") };
+ this
+ }
+
+ /// Expect a [`Node::ImplItem`] or panic.
+ #[track_caller]
+ pub fn expect_impl_item(self) -> &'hir ImplItem<'hir> {
+ let Node::ImplItem(this) = self else { self.expect_failed("an implementation item") };
+ this
+ }
+
+ /// Expect a [`Node::Variant`] or panic.
+ #[track_caller]
+ pub fn expect_variant(self) -> &'hir Variant<'hir> {
+ let Node::Variant(this) = self else { self.expect_failed("a variant") };
+ this
+ }
+
+ /// Expect a [`Node::Field`] or panic.
+ #[track_caller]
+ pub fn expect_field(self) -> &'hir FieldDef<'hir> {
+ let Node::Field(this) = self else { self.expect_failed("a field definition") };
+ this
+ }
+
+ /// Expect a [`Node::AnonConst`] or panic.
+ #[track_caller]
+ pub fn expect_anon_const(self) -> &'hir AnonConst {
+ let Node::AnonConst(this) = self else { self.expect_failed("an anonymous constant") };
+ this
+ }
+
+ /// Expect a [`Node::Expr`] or panic.
+ #[track_caller]
+ pub fn expect_expr(self) -> &'hir Expr<'hir> {
+ let Node::Expr(this) = self else { self.expect_failed("an expression") };
+ this
+ }
+ /// Expect a [`Node::ExprField`] or panic.
+ #[track_caller]
+ pub fn expect_expr_field(self) -> &'hir ExprField<'hir> {
+ let Node::ExprField(this) = self else { self.expect_failed("an expression field") };
+ this
+ }
+
+ /// Expect a [`Node::Stmt`] or panic.
+ #[track_caller]
+ pub fn expect_stmt(self) -> &'hir Stmt<'hir> {
+ let Node::Stmt(this) = self else { self.expect_failed("a statement") };
+ this
+ }
+
+ /// Expect a [`Node::PathSegment`] or panic.
+ #[track_caller]
+ pub fn expect_path_segment(self) -> &'hir PathSegment<'hir> {
+ let Node::PathSegment(this) = self else { self.expect_failed("a path segment") };
+ this
+ }
+
+ /// Expect a [`Node::Ty`] or panic.
+ #[track_caller]
+ pub fn expect_ty(self) -> &'hir Ty<'hir> {
+ let Node::Ty(this) = self else { self.expect_failed("a type") };
+ this
+ }
+
+ /// Expect a [`Node::TypeBinding`] or panic.
+ #[track_caller]
+ pub fn expect_type_binding(self) -> &'hir TypeBinding<'hir> {
+ let Node::TypeBinding(this) = self else { self.expect_failed("a type binding") };
+ this
+ }
+
+ /// Expect a [`Node::TraitRef`] or panic.
+ #[track_caller]
+ pub fn expect_trait_ref(self) -> &'hir TraitRef<'hir> {
+ let Node::TraitRef(this) = self else { self.expect_failed("a trait reference") };
+ this
+ }
+
+ /// Expect a [`Node::Pat`] or panic.
+ #[track_caller]
+ pub fn expect_pat(self) -> &'hir Pat<'hir> {
+ let Node::Pat(this) = self else { self.expect_failed("a pattern") };
+ this
+ }
+
+ /// Expect a [`Node::PatField`] or panic.
+ #[track_caller]
+ pub fn expect_pat_field(self) -> &'hir PatField<'hir> {
+ let Node::PatField(this) = self else { self.expect_failed("a pattern field") };
+ this
+ }
+
+ /// Expect a [`Node::Arm`] or panic.
+ #[track_caller]
+ pub fn expect_arm(self) -> &'hir Arm<'hir> {
+ let Node::Arm(this) = self else { self.expect_failed("an arm") };
+ this
+ }
+
+ /// Expect a [`Node::Block`] or panic.
+ #[track_caller]
+ pub fn expect_block(self) -> &'hir Block<'hir> {
+ let Node::Block(this) = self else { self.expect_failed("a block") };
+ this
+ }
+
+ /// Expect a [`Node::Local`] or panic.
+ #[track_caller]
+ pub fn expect_local(self) -> &'hir Local<'hir> {
+ let Node::Local(this) = self else { self.expect_failed("a local") };
+ this
+ }
+
+ /// Expect a [`Node::Ctor`] or panic.
+ #[track_caller]
+ pub fn expect_ctor(self) -> &'hir VariantData<'hir> {
+ let Node::Ctor(this) = self else { self.expect_failed("a constructor") };
+ this
+ }
+
+ /// Expect a [`Node::Lifetime`] or panic.
+ #[track_caller]
+ pub fn expect_lifetime(self) -> &'hir Lifetime {
+ let Node::Lifetime(this) = self else { self.expect_failed("a lifetime") };
+ this
+ }
+
+ /// Expect a [`Node::GenericParam`] or panic.
+ #[track_caller]
+ pub fn expect_generic_param(self) -> &'hir GenericParam<'hir> {
+ let Node::GenericParam(this) = self else { self.expect_failed("a generic parameter") };
+ this
+ }
+
+ /// Expect a [`Node::Crate`] or panic.
+ #[track_caller]
+ pub fn expect_crate(self) -> &'hir Mod<'hir> {
+ let Node::Crate(this) = self else { self.expect_failed("a crate") };
+ this
+ }
+
+ /// Expect a [`Node::Infer`] or panic.
+ #[track_caller]
+ pub fn expect_infer(self) -> &'hir InferArg {
+ let Node::Infer(this) = self else { self.expect_failed("an infer") };
+ this
+ }
+
+ #[track_caller]
+ fn expect_failed(&self, expected: &'static str) -> ! {
+ panic!("expected {expected} node, found {self:?}")
+ }
}
// Some nodes are used a lot. Make sure they don't unintentionally get bigger.
diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs
index 02641b7cf..cc0f64017 100644
--- a/compiler/rustc_hir/src/intravisit.rs
+++ b/compiler/rustc_hir/src/intravisit.rs
@@ -67,6 +67,7 @@
use crate::hir::*;
use rustc_ast::walk_list;
use rustc_ast::{Attribute, Label};
+use rustc_span::def_id::LocalDefId;
use rustc_span::symbol::{Ident, Symbol};
use rustc_span::Span;
@@ -364,7 +365,7 @@ pub trait Visitor<'v>: Sized {
fn visit_fn_decl(&mut self, fd: &'v FnDecl<'v>) {
walk_fn_decl(self, fd)
}
- fn visit_fn(&mut self, fk: FnKind<'v>, fd: &'v FnDecl<'v>, b: BodyId, _: Span, id: HirId) {
+ fn visit_fn(&mut self, fk: FnKind<'v>, fd: &'v FnDecl<'v>, b: BodyId, _: Span, id: LocalDefId) {
walk_fn(self, fk, fd, b, id)
}
fn visit_use(&mut self, path: &'v UsePath<'v>, hir_id: HirId) {
@@ -468,13 +469,16 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item<'v>) {
visitor.visit_ty(typ);
visitor.visit_nested_body(body);
}
- ItemKind::Fn(ref sig, ref generics, body_id) => visitor.visit_fn(
- FnKind::ItemFn(item.ident, generics, sig.header),
- sig.decl,
- body_id,
- item.span,
- item.hir_id(),
- ),
+ ItemKind::Fn(ref sig, ref generics, body_id) => {
+ visitor.visit_id(item.hir_id());
+ visitor.visit_fn(
+ FnKind::ItemFn(item.ident, generics, sig.header),
+ sig.decl,
+ body_id,
+ item.span,
+ item.owner_id.def_id,
+ )
+ }
ItemKind::Macro(..) => {
visitor.visit_id(item.hir_id());
}
@@ -733,7 +737,7 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr<'v>)
walk_list!(visitor, visit_arm, arms);
}
ExprKind::Closure(&Closure {
- def_id: _,
+ def_id,
binder: _,
bound_generic_params,
fn_decl,
@@ -745,7 +749,7 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr<'v>)
constness: _,
}) => {
walk_list!(visitor, visit_generic_param, bound_generic_params);
- visitor.visit_fn(FnKind::Closure, fn_decl, body, expression.span, expression.hir_id)
+ visitor.visit_fn(FnKind::Closure, fn_decl, body, expression.span, def_id)
}
ExprKind::Block(ref block, ref opt_label) => {
walk_list!(visitor, visit_label, opt_label);
@@ -786,7 +790,7 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr<'v>)
ExprKind::Yield(ref subexpression, _) => {
visitor.visit_expr(subexpression);
}
- ExprKind::Lit(_) | ExprKind::Err => {}
+ ExprKind::Lit(_) | ExprKind::Err(_) => {}
}
}
@@ -840,7 +844,7 @@ pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty<'v>) {
visitor.visit_lifetime(lifetime);
}
TyKind::Typeof(ref expression) => visitor.visit_anon_const(expression),
- TyKind::Infer | TyKind::Err => {}
+ TyKind::Infer | TyKind::Err(_) => {}
}
}
@@ -923,9 +927,8 @@ pub fn walk_fn<'v, V: Visitor<'v>>(
function_kind: FnKind<'v>,
function_declaration: &'v FnDecl<'v>,
body_id: BodyId,
- id: HirId,
+ _: LocalDefId,
) {
- visitor.visit_id(id);
visitor.visit_fn_decl(function_declaration);
walk_fn_kind(visitor, function_kind);
visitor.visit_nested_body(body_id)
@@ -953,26 +956,30 @@ pub fn walk_trait_item<'v, V: Visitor<'v>>(visitor: &mut V, trait_item: &'v Trai
let TraitItem { ident, generics, ref defaultness, ref kind, span, owner_id: _ } = *trait_item;
let hir_id = trait_item.hir_id();
visitor.visit_ident(ident);
- visitor.visit_generics(generics);
- visitor.visit_defaultness(defaultness);
+ visitor.visit_generics(&generics);
+ visitor.visit_defaultness(&defaultness);
+ visitor.visit_id(hir_id);
match *kind {
TraitItemKind::Const(ref ty, default) => {
- visitor.visit_id(hir_id);
visitor.visit_ty(ty);
walk_list!(visitor, visit_nested_body, default);
}
TraitItemKind::Fn(ref sig, TraitFn::Required(param_names)) => {
- visitor.visit_id(hir_id);
visitor.visit_fn_decl(sig.decl);
for &param_name in param_names {
visitor.visit_ident(param_name);
}
}
TraitItemKind::Fn(ref sig, TraitFn::Provided(body_id)) => {
- visitor.visit_fn(FnKind::Method(ident, sig), sig.decl, body_id, span, hir_id);
+ visitor.visit_fn(
+ FnKind::Method(ident, sig),
+ sig.decl,
+ body_id,
+ span,
+ trait_item.owner_id.def_id,
+ );
}
TraitItemKind::Type(bounds, ref default) => {
- visitor.visit_id(hir_id);
walk_list!(visitor, visit_param_bound, bounds);
walk_list!(visitor, visit_ty, default);
}
@@ -1002,9 +1009,9 @@ pub fn walk_impl_item<'v, V: Visitor<'v>>(visitor: &mut V, impl_item: &'v ImplIt
visitor.visit_ident(ident);
visitor.visit_generics(generics);
visitor.visit_defaultness(defaultness);
+ visitor.visit_id(impl_item.hir_id());
match *kind {
ImplItemKind::Const(ref ty, body) => {
- visitor.visit_id(impl_item.hir_id());
visitor.visit_ty(ty);
visitor.visit_nested_body(body);
}
@@ -1014,11 +1021,10 @@ pub fn walk_impl_item<'v, V: Visitor<'v>>(visitor: &mut V, impl_item: &'v ImplIt
sig.decl,
body_id,
impl_item.span,
- impl_item.hir_id(),
+ impl_item.owner_id.def_id,
);
}
ImplItemKind::Type(ref ty) => {
- visitor.visit_id(impl_item.hir_id());
visitor.visit_ty(ty);
}
}
diff --git a/compiler/rustc_hir/src/lang_items.rs b/compiler/rustc_hir/src/lang_items.rs
index 54fa5702f..60fa5a99e 100644
--- a/compiler/rustc_hir/src/lang_items.rs
+++ b/compiler/rustc_hir/src/lang_items.rs
@@ -244,6 +244,14 @@ language_item_table! {
/// libstd panic entry point. Necessary for const eval to be able to catch it
BeginPanic, sym::begin_panic, begin_panic_fn, Target::Fn, GenericRequirement::None;
+ // Lang items needed for `format_args!()`.
+ FormatAlignment, sym::format_alignment, format_alignment, Target::Enum, GenericRequirement::None;
+ FormatArgument, sym::format_argument, format_argument, Target::Struct, GenericRequirement::None;
+ FormatArguments, sym::format_arguments, format_arguments, Target::Struct, GenericRequirement::None;
+ FormatCount, sym::format_count, format_count, Target::Enum, GenericRequirement::None;
+ FormatPlaceholder, sym::format_placeholder, format_placeholder, Target::Struct, GenericRequirement::None;
+ FormatUnsafeArg, sym::format_unsafe_arg, format_unsafe_arg, Target::Struct, GenericRequirement::None;
+
ExchangeMalloc, sym::exchange_malloc, exchange_malloc_fn, Target::Fn, GenericRequirement::None;
BoxFree, sym::box_free, box_free_fn, Target::Fn, GenericRequirement::Minimum(1);
DropInPlace, sym::drop_in_place, drop_in_place_fn, Target::Fn, GenericRequirement::Minimum(1);
@@ -279,7 +287,7 @@ language_item_table! {
TryTraitBranch, sym::branch, branch_fn, Target::Method(MethodKind::Trait { body: false }), GenericRequirement::None;
TryTraitFromYeet, sym::from_yeet, from_yeet_fn, Target::Fn, GenericRequirement::None;
- PointerSized, sym::pointer_sized, pointer_sized, Target::Trait, GenericRequirement::Exact(0);
+ PointerLike, sym::pointer_like, pointer_like, Target::Trait, GenericRequirement::Exact(0);
Poll, sym::Poll, poll, Target::Enum, GenericRequirement::None;
PollReady, sym::Ready, poll_ready_variant, Target::Variant, GenericRequirement::None;
@@ -294,8 +302,6 @@ language_item_table! {
Context, sym::Context, context, Target::Struct, GenericRequirement::None;
FuturePoll, sym::poll, future_poll_fn, Target::Method(MethodKind::Trait { body: false }), GenericRequirement::None;
- FromFrom, sym::from, from_fn, Target::Method(MethodKind::Trait { body: false }), GenericRequirement::None;
-
OptionSome, sym::Some, option_some_variant, Target::Variant, GenericRequirement::None;
OptionNone, sym::None, option_none_variant, Target::Variant, GenericRequirement::None;
diff --git a/compiler/rustc_hir/src/stable_hash_impls.rs b/compiler/rustc_hir/src/stable_hash_impls.rs
index 23423e8f3..85d0e02d0 100644
--- a/compiler/rustc_hir/src/stable_hash_impls.rs
+++ b/compiler/rustc_hir/src/stable_hash_impls.rs
@@ -100,13 +100,8 @@ impl<'tcx, HirCtx: crate::HashStableContext> HashStable<HirCtx> for OwnerNodes<'
// `local_id_to_def_id` is also ignored because is dependent on the body, then just hashing
// the body satisfies the condition of two nodes being different have different
// `hash_stable` results.
- let OwnerNodes {
- hash_including_bodies,
- hash_without_bodies: _,
- nodes: _,
- bodies: _,
- local_id_to_def_id: _,
- } = *self;
+ let OwnerNodes { hash_including_bodies, hash_without_bodies: _, nodes: _, bodies: _ } =
+ *self;
hash_including_bodies.hash_stable(hcx, hasher);
}
}
diff --git a/compiler/rustc_hir/src/target.rs b/compiler/rustc_hir/src/target.rs
index 5917d5e34..961deac54 100644
--- a/compiler/rustc_hir/src/target.rs
+++ b/compiler/rustc_hir/src/target.rs
@@ -116,7 +116,7 @@ impl Target {
DefKind::Union => Target::Union,
DefKind::Trait => Target::Trait,
DefKind::TraitAlias => Target::TraitAlias,
- DefKind::Impl => Target::Impl,
+ DefKind::Impl { .. } => Target::Impl,
_ => panic!("impossible case reached"),
}
}
diff --git a/compiler/rustc_hir_analysis/Cargo.toml b/compiler/rustc_hir_analysis/Cargo.toml
index 0761d8cdb..fab16b80f 100644
--- a/compiler/rustc_hir_analysis/Cargo.toml
+++ b/compiler/rustc_hir_analysis/Cargo.toml
@@ -9,15 +9,12 @@ doctest = false
[dependencies]
rustc_arena = { path = "../rustc_arena" }
-tracing = "0.1"
rustc_macros = { path = "../rustc_macros" }
rustc_middle = { path = "../rustc_middle" }
rustc_attr = { path = "../rustc_attr" }
rustc_data_structures = { path = "../rustc_data_structures" }
rustc_errors = { path = "../rustc_errors" }
-rustc_graphviz = { path = "../rustc_graphviz" }
rustc_hir = { path = "../rustc_hir" }
-rustc_hir_pretty = { path = "../rustc_hir_pretty" }
rustc_target = { path = "../rustc_target" }
rustc_session = { path = "../rustc_session" }
smallvec = { version = "1.8.1", features = ["union", "may_dangle"] }
@@ -27,6 +24,7 @@ rustc_index = { path = "../rustc_index" }
rustc_infer = { path = "../rustc_infer" }
rustc_trait_selection = { path = "../rustc_trait_selection" }
rustc_lint = { path = "../rustc_lint" }
-rustc_serialize = { path = "../rustc_serialize" }
rustc_type_ir = { path = "../rustc_type_ir" }
rustc_feature = { path = "../rustc_feature" }
+thin-vec = "0.2.12"
+tracing = "0.1"
diff --git a/compiler/rustc_error_messages/locales/en-US/hir_analysis.ftl b/compiler/rustc_hir_analysis/locales/en-US.ftl
index 41f458f6c..1d313945b 100644
--- a/compiler/rustc_error_messages/locales/en-US/hir_analysis.ftl
+++ b/compiler/rustc_hir_analysis/locales/en-US.ftl
@@ -33,20 +33,7 @@ hir_analysis_field_already_declared =
.label = field already declared
.previous_decl_label = `{$field_name}` first declared here
-hir_analysis_copy_impl_on_type_with_dtor =
- the trait `Copy` may not be implemented for this type; the type has a destructor
- .label = `Copy` not allowed on types with destructors
-
-hir_analysis_multiple_relaxed_default_bounds =
- type parameter has more than one relaxed default bound, only one is supported
-
-hir_analysis_copy_impl_on_non_adt =
- the trait `Copy` may not be implemented for this type
- .label = type is not a structure or enumeration
-
-hir_analysis_trait_object_declared_with_no_traits =
- at least one trait is required for an object type
- .alias_span = this alias does not contain a trait
+hir_analysis_expected_used_symbol = expected `used`, `used(compiler)` or `used(linker)`
hir_analysis_ambiguous_lifetime_bound =
ambiguous lifetime bound, explicit lifetime bound required
@@ -68,6 +55,17 @@ hir_analysis_value_of_associated_struct_already_specified =
hir_analysis_unconstrained_opaque_type = unconstrained opaque type
.note = `{$name}` must be used in combination with a concrete type within the same {$what}
+hir_analysis_manual_implementation =
+ manual implementations of `{$trait_name}` are experimental
+ .label = manual implementations of `{$trait_name}` are experimental
+ .help = add `#![feature(unboxed_closures)]` to the crate attributes to enable
+
+hir_analysis_substs_on_overridden_impl = could not resolve substs on overridden impl
+
+hir_analysis_trait_object_declared_with_no_traits =
+ at least one trait is required for an object type
+ .alias_span = this alias does not contain a trait
+
hir_analysis_missing_type_params =
the type {$parameterCount ->
[one] parameter
@@ -90,20 +88,16 @@ hir_analysis_missing_type_params =
} to {$parameters}
.note = because of the default `Self` reference, type parameters must be specified on object types
-hir_analysis_manual_implementation =
- manual implementations of `{$trait_name}` are experimental
- .label = manual implementations of `{$trait_name}` are experimental
- .help = add `#![feature(unboxed_closures)]` to the crate attributes to enable
-
-hir_analysis_substs_on_overridden_impl = could not resolve substs on overridden impl
+hir_analysis_copy_impl_on_type_with_dtor =
+ the trait `Copy` may not be implemented for this type; the type has a destructor
+ .label = `Copy` not allowed on types with destructors
-hir_analysis_unused_extern_crate =
- unused extern crate
- .suggestion = remove it
+hir_analysis_multiple_relaxed_default_bounds =
+ type parameter has more than one relaxed default bound, only one is supported
-hir_analysis_extern_crate_not_idiomatic =
- `extern crate` is not idiomatic in the new edition
- .suggestion = convert it to a `{$msg_code}`
+hir_analysis_copy_impl_on_non_adt =
+ the trait `Copy` may not be implemented for this type
+ .label = type is not a structure or enumeration
hir_analysis_const_impl_for_non_const_trait =
const `impl` for trait `{$trait_name}` which is not marked with `#[const_trait]`
@@ -124,3 +118,40 @@ hir_analysis_linkage_type =
hir_analysis_auto_deref_reached_recursion_limit = reached the recursion limit while auto-dereferencing `{$ty}`
.label = deref recursion limit reached
.help = consider increasing the recursion limit by adding a `#![recursion_limit = "{$suggested_limit}"]` attribute to your crate (`{$crate_name}`)
+
+hir_analysis_where_clause_on_main = `main` function is not allowed to have a `where` clause
+ .label = `main` cannot have a `where` clause
+
+hir_analysis_track_caller_on_main = `main` function is not allowed to be `#[track_caller]`
+ .suggestion = remove this annotation
+
+hir_analysis_start_not_track_caller = `start` is not allowed to be `#[track_caller]`
+ .label = `start` is not allowed to be `#[track_caller]`
+
+hir_analysis_start_not_async = `start` is not allowed to be `async`
+ .label = `start` is not allowed to be `async`
+
+hir_analysis_start_function_where = start function is not allowed to have a `where` clause
+ .label = start function cannot have a `where` clause
+
+hir_analysis_start_function_parameters = start function is not allowed to have type parameters
+ .label = start function cannot have type parameters
+
+hir_analysis_main_function_return_type_generic = `main` function return type is not allowed to have generic parameters
+
+hir_analysis_main_function_async = `main` function is not allowed to be `async`
+ .label = `main` function is not allowed to be `async`
+
+hir_analysis_main_function_generic_parameters = `main` function is not allowed to have generic parameters
+ .label = `main` cannot have generic parameters
+
+hir_analysis_variadic_function_compatible_convention = C-variadic function must have a compatible calling convention, like {$conventions}
+ .label = C-variadic function must have a compatible calling convention
+
+hir_analysis_cannot_capture_late_bound_ty_in_anon_const =
+ cannot capture late-bound type parameter in a constant
+ .label = parameter defined here
+
+hir_analysis_cannot_capture_late_bound_const_in_anon_const =
+ cannot capture late-bound const parameter in a constant
+ .label = parameter defined here
diff --git a/compiler/rustc_hir_analysis/src/astconv/errors.rs b/compiler/rustc_hir_analysis/src/astconv/errors.rs
index 232ef2079..c49e4d9d5 100644
--- a/compiler/rustc_hir_analysis/src/astconv/errors.rs
+++ b/compiler/rustc_hir_analysis/src/astconv/errors.rs
@@ -1,12 +1,13 @@
use crate::astconv::AstConv;
use crate::errors::{ManualImplementation, MissingTypeParams};
use rustc_data_structures::fx::FxHashMap;
-use rustc_errors::{pluralize, struct_span_err, Applicability, ErrorGuaranteed};
+use rustc_errors::{pluralize, struct_span_err, Applicability, Diagnostic, ErrorGuaranteed};
use rustc_hir as hir;
use rustc_hir::def_id::DefId;
-use rustc_middle::ty;
+use rustc_infer::traits::FulfillmentError;
+use rustc_middle::ty::{self, Ty};
use rustc_session::parse::feature_err;
-use rustc_span::lev_distance::find_best_match_for_name;
+use rustc_span::edit_distance::find_best_match_for_name;
use rustc_span::symbol::{sym, Ident};
use rustc_span::{Span, Symbol, DUMMY_SP};
@@ -221,6 +222,228 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
err.emit()
}
+ pub(crate) fn complain_about_ambiguous_inherent_assoc_type(
+ &self,
+ name: Ident,
+ candidates: Vec<DefId>,
+ span: Span,
+ ) -> ErrorGuaranteed {
+ let mut err = struct_span_err!(
+ self.tcx().sess,
+ name.span,
+ E0034,
+ "multiple applicable items in scope"
+ );
+ err.span_label(name.span, format!("multiple `{name}` found"));
+ self.note_ambiguous_inherent_assoc_type(&mut err, candidates, span);
+ err.emit()
+ }
+
+ // FIXME(fmease): Heavily adapted from `rustc_hir_typeck::method::suggest`. Deduplicate.
+ fn note_ambiguous_inherent_assoc_type(
+ &self,
+ err: &mut Diagnostic,
+ candidates: Vec<DefId>,
+ span: Span,
+ ) {
+ let tcx = self.tcx();
+
+ // Dynamic limit to avoid hiding just one candidate, which is silly.
+ let limit = if candidates.len() == 5 { 5 } else { 4 };
+
+ for (index, &item) in candidates.iter().take(limit).enumerate() {
+ let impl_ = tcx.impl_of_method(item).unwrap();
+
+ let note_span = if item.is_local() {
+ Some(tcx.def_span(item))
+ } else if impl_.is_local() {
+ Some(tcx.def_span(impl_))
+ } else {
+ None
+ };
+
+ let title = if candidates.len() > 1 {
+ format!("candidate #{}", index + 1)
+ } else {
+ "the candidate".into()
+ };
+
+ let impl_ty = tcx.at(span).type_of(impl_).subst_identity();
+ let note = format!("{title} is defined in an impl for the type `{impl_ty}`");
+
+ if let Some(span) = note_span {
+ err.span_note(span, &note);
+ } else {
+ err.note(&note);
+ }
+ }
+ if candidates.len() > limit {
+ err.note(&format!("and {} others", candidates.len() - limit));
+ }
+ }
+
+ // FIXME(inherent_associated_types): Find similarly named associated types and suggest them.
+ pub(crate) fn complain_about_inherent_assoc_type_not_found(
+ &self,
+ name: Ident,
+ self_ty: Ty<'tcx>,
+ candidates: Vec<(DefId, (DefId, DefId))>,
+ fulfillment_errors: Vec<FulfillmentError<'tcx>>,
+ span: Span,
+ ) -> ErrorGuaranteed {
+ // FIXME(fmease): This was copied in parts from an old version of `rustc_hir_typeck::method::suggest`.
+ // Either
+ // * update this code by applying changes similar to #106702 or by taking a
+ // Vec<(DefId, (DefId, DefId), Option<Vec<FulfillmentError<'tcx>>>)> or
+ // * deduplicate this code across the two crates.
+
+ let tcx = self.tcx();
+
+ let adt_did = self_ty.ty_adt_def().map(|def| def.did());
+ let add_def_label = |err: &mut Diagnostic| {
+ if let Some(did) = adt_did {
+ err.span_label(
+ tcx.def_span(did),
+ format!("associated item `{name}` not found for this {}", tcx.def_descr(did)),
+ );
+ }
+ };
+
+ if fulfillment_errors.is_empty() {
+ // FIXME(fmease): Copied from `rustc_hir_typeck::method::probe`. Deduplicate.
+
+ let limit = if candidates.len() == 5 { 5 } else { 4 };
+ let type_candidates = candidates
+ .iter()
+ .take(limit)
+ .map(|&(impl_, _)| format!("- `{}`", tcx.at(span).type_of(impl_).subst_identity()))
+ .collect::<Vec<_>>()
+ .join("\n");
+ let additional_types = if candidates.len() > limit {
+ format!("\nand {} more types", candidates.len() - limit)
+ } else {
+ String::new()
+ };
+
+ let mut err = struct_span_err!(
+ tcx.sess,
+ name.span,
+ E0220,
+ "associated type `{name}` not found for `{self_ty}` in the current scope"
+ );
+ err.span_label(name.span, format!("associated item not found in `{self_ty}`"));
+ err.note(&format!(
+ "the associated type was found for\n{type_candidates}{additional_types}",
+ ));
+ add_def_label(&mut err);
+ return err.emit();
+ }
+
+ let mut bound_spans = Vec::new();
+
+ let mut bound_span_label = |self_ty: Ty<'_>, obligation: &str, quiet: &str| {
+ let msg = format!(
+ "doesn't satisfy `{}`",
+ if obligation.len() > 50 { quiet } else { obligation }
+ );
+ match &self_ty.kind() {
+ // Point at the type that couldn't satisfy the bound.
+ ty::Adt(def, _) => bound_spans.push((tcx.def_span(def.did()), msg)),
+ // Point at the trait object that couldn't satisfy the bound.
+ ty::Dynamic(preds, _, _) => {
+ for pred in preds.iter() {
+ match pred.skip_binder() {
+ ty::ExistentialPredicate::Trait(tr) => {
+ bound_spans.push((tcx.def_span(tr.def_id), msg.clone()))
+ }
+ ty::ExistentialPredicate::Projection(_)
+ | ty::ExistentialPredicate::AutoTrait(_) => {}
+ }
+ }
+ }
+ // Point at the closure that couldn't satisfy the bound.
+ ty::Closure(def_id, _) => {
+ bound_spans.push((tcx.def_span(*def_id), format!("doesn't satisfy `{quiet}`")))
+ }
+ _ => {}
+ }
+ };
+
+ let format_pred = |pred: ty::Predicate<'tcx>| {
+ let bound_predicate = pred.kind();
+ match bound_predicate.skip_binder() {
+ ty::PredicateKind::Clause(ty::Clause::Projection(pred)) => {
+ let pred = bound_predicate.rebind(pred);
+ // `<Foo as Iterator>::Item = String`.
+ let projection_ty = pred.skip_binder().projection_ty;
+
+ let substs_with_infer_self = tcx.mk_substs_from_iter(
+ std::iter::once(tcx.mk_ty_var(ty::TyVid::from_u32(0)).into())
+ .chain(projection_ty.substs.iter().skip(1)),
+ );
+
+ let quiet_projection_ty =
+ tcx.mk_alias_ty(projection_ty.def_id, substs_with_infer_self);
+
+ let term = pred.skip_binder().term;
+
+ let obligation = format!("{projection_ty} = {term}");
+ let quiet = format!("{quiet_projection_ty} = {term}");
+
+ bound_span_label(projection_ty.self_ty(), &obligation, &quiet);
+ Some((obligation, projection_ty.self_ty()))
+ }
+ ty::PredicateKind::Clause(ty::Clause::Trait(poly_trait_ref)) => {
+ let p = poly_trait_ref.trait_ref;
+ let self_ty = p.self_ty();
+ let path = p.print_only_trait_path();
+ let obligation = format!("{self_ty}: {path}");
+ let quiet = format!("_: {path}");
+ bound_span_label(self_ty, &obligation, &quiet);
+ Some((obligation, self_ty))
+ }
+ _ => None,
+ }
+ };
+
+ // FIXME(fmease): `rustc_hir_typeck::method::suggest` uses a `skip_list` to filter out some bounds.
+ // I would do the same here if it didn't mean more code duplication.
+ let mut bounds: Vec<_> = fulfillment_errors
+ .into_iter()
+ .map(|error| error.root_obligation.predicate)
+ .filter_map(format_pred)
+ .map(|(p, _)| format!("`{}`", p))
+ .collect();
+ bounds.sort();
+ bounds.dedup();
+
+ let mut err = tcx.sess.struct_span_err(
+ name.span,
+ &format!("the associated type `{name}` exists for `{self_ty}`, but its trait bounds were not satisfied")
+ );
+ if !bounds.is_empty() {
+ err.note(&format!(
+ "the following trait bounds were not satisfied:\n{}",
+ bounds.join("\n")
+ ));
+ }
+ err.span_label(
+ name.span,
+ format!("associated type cannot be referenced on `{self_ty}` due to unsatisfied trait bounds")
+ );
+
+ bound_spans.sort();
+ bound_spans.dedup();
+ for (span, msg) in bound_spans {
+ if !tcx.sess.source_map().is_span_accessible(span) {
+ continue;
+ }
+ err.span_label(span, &msg);
+ }
+ add_def_label(&mut err);
+ err.emit()
+ }
+
/// 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 supertraits), we instead
diff --git a/compiler/rustc_hir_analysis/src/astconv/generics.rs b/compiler/rustc_hir_analysis/src/astconv/generics.rs
index 7a499327d..7f6518ffd 100644
--- a/compiler/rustc_hir_analysis/src/astconv/generics.rs
+++ b/compiler/rustc_hir_analysis/src/astconv/generics.rs
@@ -6,7 +6,7 @@ use crate::astconv::{
use crate::errors::AssocTypeBindingNotAllowed;
use crate::structured_errors::{GenericArgsInfo, StructuredDiagnostic, WrongNumberOfGenericArgs};
use rustc_ast::ast::ParamKindOrd;
-use rustc_errors::{struct_span_err, Applicability, Diagnostic, MultiSpan};
+use rustc_errors::{struct_span_err, Applicability, Diagnostic, ErrorGuaranteed, MultiSpan};
use rustc_hir as hir;
use rustc_hir::def::{DefKind, Res};
use rustc_hir::def_id::DefId;
@@ -26,7 +26,7 @@ fn generic_arg_mismatch_err(
param: &GenericParamDef,
possible_ordering_error: bool,
help: Option<&str>,
-) {
+) -> ErrorGuaranteed {
let sess = tcx.sess;
let mut err = struct_span_err!(
sess,
@@ -70,18 +70,18 @@ fn generic_arg_mismatch_err(
) => match path.res {
Res::Err => {
add_braces_suggestion(arg, &mut err);
- err.set_primary_message("unresolved item provided when a constant was expected")
+ return err
+ .set_primary_message("unresolved item provided when a constant was expected")
.emit();
- return;
}
Res::Def(DefKind::TyParam, src_def_id) => {
if let Some(param_local_id) = param.def_id.as_local() {
let param_name = tcx.hir().ty_param_name(param_local_id);
- let param_type = tcx.type_of(param.def_id);
+ let param_type = tcx.type_of(param.def_id).subst_identity();
if param_type.is_suggestable(tcx, false) {
err.span_suggestion(
tcx.def_span(src_def_id),
- "consider changing this type parameter to be a `const` generic",
+ "consider changing this type parameter to a const parameter",
format!("const {}: {}", param_name, param_type),
Applicability::MaybeIncorrect,
);
@@ -97,7 +97,7 @@ fn generic_arg_mismatch_err(
(
GenericArg::Type(hir::Ty { kind: hir::TyKind::Array(_, len), .. }),
GenericParamDefKind::Const { .. },
- ) if tcx.type_of(param.def_id) == tcx.types.usize => {
+ ) if tcx.type_of(param.def_id).skip_binder() == tcx.types.usize => {
let snippet = sess.source_map().span_to_snippet(tcx.hir().span(len.hir_id()));
if let Ok(snippet) = snippet {
err.span_suggestion(
@@ -137,7 +137,7 @@ fn generic_arg_mismatch_err(
}
}
- err.emit();
+ err.emit()
}
/// Creates the relevant generic argument substitutions
@@ -370,7 +370,7 @@ pub fn create_substs_for_generic_args<'tcx, 'a>(
}
}
- tcx.intern_substs(&substs)
+ tcx.mk_substs(&substs)
}
/// Checks that the correct number of generic arguments have been provided.
@@ -385,10 +385,9 @@ pub fn check_generic_arg_count_for_call(
) -> GenericArgCountResult {
let empty_args = hir::GenericArgs::none();
let gen_args = seg.args.unwrap_or(&empty_args);
- let gen_pos = if is_method_call == IsMethodCall::Yes {
- GenericArgPosition::MethodCall
- } else {
- GenericArgPosition::Value
+ let gen_pos = match is_method_call {
+ IsMethodCall::Yes => GenericArgPosition::MethodCall,
+ IsMethodCall::No => GenericArgPosition::Value,
};
let has_self = generics.parent.is_none() && generics.has_self;
diff --git a/compiler/rustc_hir_analysis/src/astconv/mod.rs b/compiler/rustc_hir_analysis/src/astconv/mod.rs
index 6435b05ce..f5ce02c9e 100644
--- a/compiler/rustc_hir_analysis/src/astconv/mod.rs
+++ b/compiler/rustc_hir_analysis/src/astconv/mod.rs
@@ -14,7 +14,7 @@ use crate::errors::{
AmbiguousLifetimeBound, MultipleRelaxedDefaultBounds, TraitObjectDeclaredWithNoTraits,
TypeofReservedKeywordUsed, ValueOfAssociatedStructAlreadySpecified,
};
-use crate::middle::resolve_lifetime as rl;
+use crate::middle::resolve_bound_vars as rbv;
use crate::require_c_abi_if_c_variadic;
use rustc_ast::TraitObjectSyntax;
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
@@ -27,34 +27,37 @@ use rustc_hir::def::{CtorOf, DefKind, Namespace, Res};
use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_hir::intravisit::{walk_generics, Visitor as _};
use rustc_hir::{GenericArg, GenericArgs, OpaqueTyOrigin};
-use rustc_infer::infer::TyCtxtInferExt;
+use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
+use rustc_infer::infer::{InferCtxt, TyCtxtInferExt};
+use rustc_infer::traits::ObligationCause;
+use rustc_middle::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind};
use rustc_middle::middle::stability::AllowUnstable;
use rustc_middle::ty::subst::{self, GenericArgKind, InternalSubsts, SubstsRef};
+use rustc_middle::ty::DynKind;
use rustc_middle::ty::GenericParamDefKind;
-use rustc_middle::ty::{self, Const, DefIdTree, IsSuggestable, Ty, TyCtxt, TypeVisitable};
-use rustc_middle::ty::{DynKind, EarlyBinder};
+use rustc_middle::ty::{self, Const, DefIdTree, IsSuggestable, Ty, TyCtxt, TypeVisitableExt};
use rustc_session::lint::builtin::{AMBIGUOUS_ASSOCIATED_ITEMS, BARE_TRAIT_OBJECTS};
+use rustc_span::edit_distance::find_best_match_for_name;
use rustc_span::edition::Edition;
-use rustc_span::lev_distance::find_best_match_for_name;
use rustc_span::symbol::{kw, Ident, Symbol};
-use rustc_span::{sym, Span};
+use rustc_span::{sym, Span, DUMMY_SP};
use rustc_target::spec::abi;
-use rustc_trait_selection::traits;
-use rustc_trait_selection::traits::astconv_object_safety_violations;
use rustc_trait_selection::traits::error_reporting::{
report_object_safety_error, suggestions::NextTypeParamName,
};
use rustc_trait_selection::traits::wf::object_region_bounds;
+use rustc_trait_selection::traits::{self, astconv_object_safety_violations, ObligationCtxt};
use smallvec::{smallvec, SmallVec};
use std::collections::BTreeSet;
+use std::fmt::Display;
use std::slice;
#[derive(Debug)]
pub struct PathSeg(pub DefId, pub usize);
pub trait AstConv<'tcx> {
- fn tcx<'a>(&'a self) -> TyCtxt<'tcx>;
+ fn tcx(&self) -> TyCtxt<'tcx>;
fn item_def_id(&self) -> DefId;
@@ -131,6 +134,8 @@ pub trait AstConv<'tcx> {
{
self
}
+
+ fn infcx(&self) -> Option<&InferCtxt<'tcx>>;
}
#[derive(Debug)]
@@ -223,36 +228,37 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
let tcx = self.tcx();
let lifetime_name = |def_id| tcx.hir().name(tcx.hir().local_def_id_to_hir_id(def_id));
- match tcx.named_region(lifetime.hir_id) {
- Some(rl::Region::Static) => tcx.lifetimes.re_static,
+ match tcx.named_bound_var(lifetime.hir_id) {
+ Some(rbv::ResolvedArg::StaticLifetime) => tcx.lifetimes.re_static,
- Some(rl::Region::LateBound(debruijn, index, def_id)) => {
+ Some(rbv::ResolvedArg::LateBound(debruijn, index, def_id)) => {
let name = lifetime_name(def_id.expect_local());
let br = ty::BoundRegion {
var: ty::BoundVar::from_u32(index),
kind: ty::BrNamed(def_id, name),
};
- tcx.mk_region(ty::ReLateBound(debruijn, br))
+ tcx.mk_re_late_bound(debruijn, br)
}
- Some(rl::Region::EarlyBound(def_id)) => {
+ Some(rbv::ResolvedArg::EarlyBound(def_id)) => {
let name = tcx.hir().ty_param_name(def_id.expect_local());
let item_def_id = tcx.hir().ty_param_owner(def_id.expect_local());
let generics = tcx.generics_of(item_def_id);
let index = generics.param_def_id_to_index[&def_id];
- tcx.mk_region(ty::ReEarlyBound(ty::EarlyBoundRegion { def_id, index, name }))
+ tcx.mk_re_early_bound(ty::EarlyBoundRegion { def_id, index, name })
}
- Some(rl::Region::Free(scope, id)) => {
+ Some(rbv::ResolvedArg::Free(scope, id)) => {
let name = lifetime_name(id.expect_local());
- tcx.mk_region(ty::ReFree(ty::FreeRegion {
- scope,
- bound_region: ty::BrNamed(id, name),
- }))
+ tcx.mk_re_free(scope, ty::BrNamed(id, name))
// (*) -- not late-bound, won't change
}
+ Some(rbv::ResolvedArg::Error(_)) => {
+ bug!("only ty/ct should resolve as ResolvedArg::Error")
+ }
+
None => {
self.re_infer(def, lifetime.ident.span).unwrap_or_else(|| {
debug!(?lifetime, "unelided lifetime in signature");
@@ -261,11 +267,10 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
// elision. `resolve_lifetime` should have
// reported an error in this case -- but if
// not, let's error out.
- tcx.sess.delay_span_bug(lifetime.ident.span, "unelided lifetime in signature");
-
- // Supply some dummy value. We don't have an
- // `re_error`, annoyingly, so use `'static`.
- tcx.lifetimes.re_static
+ tcx.mk_re_error_with_message(
+ lifetime.ident.span,
+ "unelided lifetime in signature",
+ )
})
}
}
@@ -377,7 +382,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
// here and so associated type bindings will be handled regardless of whether there are any
// non-`Self` generic parameters.
if generics.params.is_empty() {
- return (tcx.intern_substs(parent_substs), arg_count);
+ return (tcx.mk_substs(parent_substs), arg_count);
}
struct SubstsForAstPathCtxt<'a, 'tcx> {
@@ -425,7 +430,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
}
if let (hir::TyKind::Infer, false) = (&ty.kind, self.astconv.allow_ty_infer()) {
self.inferred_params.push(ty.span);
- tcx.ty_error().into()
+ tcx.ty_error_misc().into()
} else {
self.astconv.ast_ty_to_ty(ty).into()
}
@@ -452,7 +457,11 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
.into()
}
(&GenericParamDefKind::Const { .. }, hir::GenericArg::Infer(inf)) => {
- let ty = tcx.at(self.span).type_of(param.def_id);
+ let ty = tcx
+ .at(self.span)
+ .type_of(param.def_id)
+ .no_bound_vars()
+ .expect("const parameter types cannot be generic");
if self.astconv.allow_ty_infer() {
self.astconv.ct_infer(ty, Some(param), inf.span).into()
} else {
@@ -479,11 +488,10 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
debug!(?param, "unelided lifetime in signature");
// This indicates an illegal lifetime in a non-assoc-trait position
- tcx.sess.delay_span_bug(self.span, "unelided lifetime in signature");
-
- // Supply some dummy value. We don't have an
- // `re_error`, annoyingly, so use `'static`.
- tcx.lifetimes.re_static
+ tcx.mk_re_error_with_message(
+ self.span,
+ "unelided lifetime in signature",
+ )
})
.into(),
GenericParamDefKind::Type { has_default, .. } => {
@@ -495,20 +503,24 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
_ => false,
}) {
// Avoid ICE #86756 when type error recovery goes awry.
- return tcx.ty_error().into();
+ return tcx.ty_error_misc().into();
}
- tcx.at(self.span).bound_type_of(param.def_id).subst(tcx, substs).into()
+ tcx.at(self.span).type_of(param.def_id).subst(tcx, substs).into()
} else if infer_args {
self.astconv.ty_infer(Some(param), self.span).into()
} else {
// We've already errored above about the mismatch.
- tcx.ty_error().into()
+ tcx.ty_error_misc().into()
}
}
GenericParamDefKind::Const { has_default } => {
- let ty = tcx.at(self.span).type_of(param.def_id);
- if ty.references_error() {
- return tcx.const_error(ty).into();
+ let ty = tcx
+ .at(self.span)
+ .type_of(param.def_id)
+ .no_bound_vars()
+ .expect("const parameter types cannot be generic");
+ if let Err(guar) = ty.error_reported() {
+ return tcx.const_error_with_guaranteed(ty, guar).into();
}
if !infer_args && has_default {
tcx.const_param_default(param.def_id).subst(tcx, substs.unwrap()).into()
@@ -1084,11 +1096,11 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
// those that do.
self.one_bound_for_assoc_type(
|| traits::supertraits(tcx, trait_ref),
- || trait_ref.print_only_trait_path().to_string(),
+ trait_ref.print_only_trait_path(),
binding.item_name,
path_span,
- || match binding.kind {
- ConvertedBindingKind::Equality(ty) => Some(ty.to_string()),
+ match binding.kind {
+ ConvertedBindingKind::Equality(term) => Some(term),
_ => None,
},
)?
@@ -1206,7 +1218,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
| (hir::def::DefKind::AssocConst, ty::TermKind::Const(_)) => (),
(_, _) => {
let got = if let Some(_) = term.ty() { "type" } else { "constant" };
- let expected = def_kind.descr(assoc_item_def_id);
+ let expected = tcx.def_descr(assoc_item_def_id);
let mut err = tcx.sess.struct_span_err(
binding.span,
&format!("expected {expected} bound, found {got}"),
@@ -1228,12 +1240,10 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
}
let reported = err.emit();
term = match def_kind {
- hir::def::DefKind::AssocTy => {
- tcx.ty_error_with_guaranteed(reported).into()
- }
+ hir::def::DefKind::AssocTy => tcx.ty_error(reported).into(),
hir::def::DefKind::AssocConst => tcx
.const_error_with_guaranteed(
- tcx.bound_type_of(assoc_item_def_id)
+ tcx.type_of(assoc_item_def_id)
.subst(tcx, projection_ty.skip_binder().substs),
reported,
)
@@ -1256,7 +1266,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::Alias(ty::Projection, projection_ty.skip_binder()));
+ let param_ty = tcx.mk_alias(ty::Projection, projection_ty.skip_binder());
self.add_bounds(param_ty, ast_bounds.iter(), bounds, candidate.bound_vars());
}
}
@@ -1270,7 +1280,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
item_segment: &hir::PathSegment<'_>,
) -> Ty<'tcx> {
let substs = self.ast_path_substs_for_ty(span, did, item_segment);
- self.tcx().at(span).bound_type_of(did).subst(self.tcx(), substs)
+ self.tcx().at(span).type_of(did).subst(self.tcx(), substs)
}
fn conv_object_ty_poly_trait_ref(
@@ -1323,9 +1333,10 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
ty::Clause::TypeOutlives(_) => {
// Do nothing, we deal with regions separately
}
- ty::Clause::RegionOutlives(_) => bug!(),
+ ty::Clause::RegionOutlives(_) | ty::Clause::ConstArgHasType(..) => bug!(),
},
ty::PredicateKind::WellFormed(_)
+ | ty::PredicateKind::AliasEq(..)
| ty::PredicateKind::ObjectSafe(_)
| ty::PredicateKind::ClosureKind(_, _, _)
| ty::PredicateKind::Subtype(_)
@@ -1385,7 +1396,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
.map(|trait_ref| tcx.def_span(trait_ref));
let reported =
tcx.sess.emit_err(TraitObjectDeclaredWithNoTraits { span, trait_alias_span });
- return tcx.ty_error_with_guaranteed(reported);
+ return tcx.ty_error(reported);
}
// Check that there are no gross object safety violations;
@@ -1402,7 +1413,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
&object_safety_violations,
)
.emit();
- return tcx.ty_error_with_guaranteed(reported);
+ return tcx.ty_error(reported);
}
}
@@ -1511,15 +1522,15 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
if arg == dummy_self.into() {
let param = &generics.params[index];
missing_type_params.push(param.name);
- return tcx.ty_error().into();
+ return tcx.ty_error_misc().into();
} else if arg.walk().any(|arg| arg == dummy_self.into()) {
references_self = true;
- return tcx.ty_error().into();
+ return tcx.ty_error_misc().into();
}
arg
})
.collect();
- let substs = tcx.intern_substs(&substs[..]);
+ let substs = tcx.mk_substs(&substs);
let span = i.bottom().1;
let empty_generic_args = hir_trait_bounds.iter().any(|hir_bound| {
@@ -1540,7 +1551,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
i.bottom().1,
E0038,
"the {} `{}` cannot be made into an object",
- tcx.def_kind(def_id).descr(def_id),
+ tcx.def_descr(def_id),
tcx.item_name(def_id),
);
err.note(
@@ -1567,7 +1578,8 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
false
});
if references_self {
- tcx.sess
+ let guar = tcx
+ .sess
.delay_span_bug(span, "trait object projection bounds reference `Self`");
let substs: Vec<_> = b
.projection_ty
@@ -1575,12 +1587,12 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
.iter()
.map(|arg| {
if arg.walk().any(|arg| arg == dummy_self.into()) {
- return tcx.ty_error().into();
+ return tcx.ty_error(guar).into();
}
arg
})
.collect();
- b.projection_ty.substs = tcx.intern_substs(&substs[..]);
+ b.projection_ty.substs = tcx.mk_substs(&substs);
}
ty::ExistentialProjection::erase_self_ty(tcx, b)
@@ -1602,14 +1614,14 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
.collect::<SmallVec<[_; 8]>>();
v.sort_by(|a, b| a.skip_binder().stable_cmp(tcx, &b.skip_binder()));
v.dedup();
- let existential_predicates = tcx.mk_poly_existential_predicates(v.into_iter());
+ let existential_predicates = tcx.mk_poly_existential_predicates(&v);
// Use explicitly-specified region bound.
let region_bound = if !lifetime.is_elided() {
self.ast_region_to_region(lifetime, None)
} else {
self.compute_object_lifetime_bound(span, existential_predicates).unwrap_or_else(|| {
- if tcx.named_region(lifetime.hir_id).is_some() {
+ if tcx.named_bound_var(lifetime.hir_id).is_some() {
self.ast_region_to_region(lifetime, None)
} else {
self.re_infer(None, span).unwrap_or_else(|| {
@@ -1620,14 +1632,14 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
"the lifetime bound for this object type cannot be deduced \
from context; please supply an explicit bound"
);
- if borrowed {
+ let e = if borrowed {
// We will have already emitted an error E0106 complaining about a
// missing named lifetime in `&dyn Trait`, so we elide this one.
- err.delay_as_bug();
+ err.delay_as_bug()
} else {
- err.emit();
- }
- tcx.lifetimes.re_static
+ err.emit()
+ };
+ tcx.mk_re_error(e)
})
}
})
@@ -1778,10 +1790,10 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
assoc_name,
)
},
- || param_name.to_string(),
+ param_name,
assoc_name,
span,
- || None,
+ None,
)
}
@@ -1791,10 +1803,10 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
fn one_bound_for_assoc_type<I>(
&self,
all_candidates: impl Fn() -> I,
- ty_param_name: impl Fn() -> String,
+ ty_param_name: impl Display,
assoc_name: Ident,
span: Span,
- is_equality: impl Fn() -> Option<String>,
+ is_equality: Option<ty::Term<'tcx>>,
) -> Result<ty::PolyTraitRef<'tcx>, ErrorGuaranteed>
where
I: Iterator<Item = ty::PolyTraitRef<'tcx>>,
@@ -1810,7 +1822,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
(None, None) => {
let reported = self.complain_about_assoc_type_not_found(
all_candidates,
- &ty_param_name(),
+ &ty_param_name.to_string(),
assoc_name,
span,
);
@@ -1822,7 +1834,6 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
if let Some(bound2) = next_cand {
debug!(?bound2);
- let is_equality = is_equality();
let bounds = IntoIterator::into_iter([bound, bound2]).chain(matching_candidates);
let mut err = if is_equality.is_some() {
// More specific Error Index entry.
@@ -1832,7 +1843,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
E0222,
"ambiguous associated type `{}` in bounds of `{}`",
assoc_name,
- ty_param_name()
+ ty_param_name
)
} else {
struct_span_err!(
@@ -1841,7 +1852,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
E0221,
"ambiguous associated type `{}` in bounds of `{}`",
assoc_name,
- ty_param_name()
+ ty_param_name
)
};
err.span_label(span, format!("ambiguous associated type `{}`", assoc_name));
@@ -1875,18 +1886,14 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
err.span_suggestion_verbose(
span.with_hi(assoc_name.span.lo()),
"use fully qualified syntax to disambiguate",
- format!(
- "<{} as {}>::",
- ty_param_name(),
- bound.print_only_trait_path(),
- ),
+ format!("<{} as {}>::", ty_param_name, bound.print_only_trait_path()),
Applicability::MaybeIncorrect,
);
}
} else {
err.note(&format!(
"associated type `{}` could derive from `{}`",
- ty_param_name(),
+ ty_param_name,
bound.print_only_trait_path(),
));
}
@@ -1895,7 +1902,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
err.help(&format!(
"consider introducing a new type parameter `T` and adding `where` constraints:\
\n where\n T: {},\n{}",
- ty_param_name(),
+ ty_param_name,
where_bounds.join(",\n"),
));
}
@@ -1934,7 +1941,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
Res::Err
};
- // Check if we have an enum variant.
+ // Check if we have an enum variant or an inherent associated type.
let mut variant_resolution = None;
if let Some(adt_def) = self.probe_adt(span, qself_ty) {
if adt_def.is_enum() {
@@ -1975,7 +1982,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
) = &qself.kind {
// If the path segment already has type params, we want to overwrite
// them.
- match &path.segments[..] {
+ match &path.segments {
// `segment` is the previous to last element on the path,
// which would normally be the `enum` itself, while the last
// `_` `PathSegment` corresponds to the variant.
@@ -2033,23 +2040,15 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
}
}
- // see if we can satisfy using an inherent associated type
- for &impl_ in tcx.inherent_impls(adt_def.did()) {
- let Some(assoc_ty_did) = self.lookup_assoc_ty(assoc_ident, hir_ref_id, span, impl_) else {
- continue;
- };
- let ty::Adt(_, adt_substs) = qself_ty.kind() else {
- // FIXME(inherent_associated_types)
- bug!("unimplemented: non-adt self of inherent assoc ty");
- };
- let item_substs = self.create_substs_for_associated_item(
- span,
- assoc_ty_did,
- assoc_segment,
- adt_substs,
- );
- let ty = tcx.bound_type_of(assoc_ty_did).subst(tcx, item_substs);
- return Ok((ty, DefKind::AssocTy, assoc_ty_did));
+ if let Some((ty, did)) = self.lookup_inherent_assoc_ty(
+ assoc_ident,
+ assoc_segment,
+ adt_def.did(),
+ qself_ty,
+ hir_ref_id,
+ span,
+ )? {
+ return Ok((ty, DefKind::AssocTy, did));
}
}
@@ -2067,10 +2066,10 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
self.one_bound_for_assoc_type(
|| traits::supertraits(tcx, ty::Binder::dummy(trait_ref.subst_identity())),
- || "Self".to_string(),
+ kw::SelfUpper,
assoc_ident,
span,
- || None,
+ None,
)?
}
(
@@ -2132,48 +2131,8 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
)
.emit() // Already reported in an earlier stage.
} else {
- // Find all the `impl`s that `qself_ty` has for any trait that has the
- // associated type, so that we suggest the right one.
- let infcx = tcx.infer_ctxt().build();
- // We create a fresh `ty::ParamEnv` instead of the one for `self.item_def_id()`
- // to avoid a cycle error in `src/test/ui/resolve/issue-102946.rs`.
- let param_env = ty::ParamEnv::empty();
- let traits: Vec<_> = self
- .tcx()
- .all_traits()
- .filter(|trait_def_id| {
- // Consider only traits with the associated type
- tcx.associated_items(*trait_def_id)
- .in_definition_order()
- .any(|i| {
- i.kind.namespace() == Namespace::TypeNS
- && i.ident(tcx).normalize_to_macros_2_0() == assoc_ident
- && matches!(i.kind, ty::AssocKind::Type)
- })
- // Consider only accessible traits
- && tcx.visibility(*trait_def_id)
- .is_accessible_from(self.item_def_id(), tcx)
- && tcx.all_impls(*trait_def_id)
- .any(|impl_def_id| {
- let trait_ref = tcx.impl_trait_ref(impl_def_id);
- trait_ref.map_or(false, |trait_ref| {
- let impl_ = trait_ref.subst(
- tcx,
- infcx.fresh_substs_for_item(span, impl_def_id),
- );
- infcx
- .can_eq(
- param_env,
- tcx.erase_regions(impl_.self_ty()),
- tcx.erase_regions(qself_ty),
- )
- .is_ok()
- })
- && tcx.impl_polarity(impl_def_id) != ty::ImplPolarity::Negative
- })
- })
- .map(|trait_def_id| tcx.def_path_str(trait_def_id))
- .collect();
+ let traits: Vec<_> =
+ self.probe_traits_that_match_assoc_ty(qself_ty, assoc_ident);
// Don't print `TyErr` to the user.
self.report_ambiguous_associated_type(
@@ -2210,7 +2169,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
"`{}` could{} refer to the {} defined here",
assoc_ident,
also,
- kind.descr(def_id)
+ tcx.def_kind_descr(kind, def_id)
);
lint.span_note(tcx.def_span(def_id), &note_msg);
};
@@ -2232,15 +2191,137 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
Ok((ty, DefKind::AssocTy, assoc_ty_did))
}
+ fn lookup_inherent_assoc_ty(
+ &self,
+ name: Ident,
+ segment: &hir::PathSegment<'_>,
+ adt_did: DefId,
+ self_ty: Ty<'tcx>,
+ block: hir::HirId,
+ span: Span,
+ ) -> Result<Option<(Ty<'tcx>, DefId)>, ErrorGuaranteed> {
+ let tcx = self.tcx();
+
+ let candidates: Vec<_> = tcx
+ .inherent_impls(adt_did)
+ .iter()
+ .filter_map(|&impl_| Some((impl_, self.lookup_assoc_ty_unchecked(name, block, impl_)?)))
+ .collect();
+
+ if candidates.is_empty() {
+ return Ok(None);
+ }
+
+ // In contexts that have no inference context, just make a new one.
+ // We do need a local variable to store it, though.
+ let infcx_;
+ let infcx = match self.infcx() {
+ Some(infcx) => infcx,
+ None => {
+ assert!(!self_ty.needs_infer());
+ infcx_ = tcx.infer_ctxt().ignoring_regions().build();
+ &infcx_
+ }
+ };
+
+ let param_env = tcx.param_env(block.owner.to_def_id());
+ let cause = ObligationCause::misc(span, block.owner.def_id);
+ let mut fulfillment_errors = Vec::new();
+ let mut applicable_candidates: Vec<_> = candidates
+ .iter()
+ .filter_map(|&(impl_, (assoc_item, def_scope))| {
+ infcx.probe(|_| {
+ let ocx = ObligationCtxt::new_in_snapshot(&infcx);
+
+ let impl_ty = tcx.type_of(impl_);
+ let impl_substs = infcx.fresh_item_substs(impl_);
+ let impl_ty = impl_ty.subst(tcx, impl_substs);
+ let impl_ty = ocx.normalize(&cause, param_env, impl_ty);
+
+ // Check that the Self-types can be related.
+ // FIXME(fmease): Should we use `eq` here?
+ ocx.sup(&ObligationCause::dummy(), param_env, impl_ty, self_ty).ok()?;
+
+ // Check whether the impl imposes obligations we have to worry about.
+ let impl_bounds = tcx.predicates_of(impl_);
+ let impl_bounds = impl_bounds.instantiate(tcx, impl_substs);
+
+ let impl_bounds = ocx.normalize(&cause, param_env, impl_bounds);
+
+ let impl_obligations = traits::predicates_for_generics(
+ |_, _| cause.clone(),
+ param_env,
+ impl_bounds,
+ );
+
+ ocx.register_obligations(impl_obligations);
+
+ let mut errors = ocx.select_where_possible();
+ if !errors.is_empty() {
+ fulfillment_errors.append(&mut errors);
+ return None;
+ }
+
+ // FIXME(fmease): Unsolved vars can escape this InferCtxt snapshot.
+ Some((assoc_item, def_scope, infcx.resolve_vars_if_possible(impl_substs)))
+ })
+ })
+ .collect();
+
+ if applicable_candidates.len() > 1 {
+ return Err(self.complain_about_ambiguous_inherent_assoc_type(
+ name,
+ applicable_candidates.into_iter().map(|(candidate, ..)| candidate).collect(),
+ span,
+ ));
+ }
+
+ if let Some((assoc_item, def_scope, impl_substs)) = applicable_candidates.pop() {
+ self.check_assoc_ty(assoc_item, name, def_scope, block, span);
+
+ // FIXME(inherent_associated_types): To fully *confirm* the *probed* candidate, we still
+ // need to relate the Self-type with fresh item substs & register region obligations for
+ // regionck to prove/disprove.
+
+ let item_substs =
+ self.create_substs_for_associated_item(span, assoc_item, segment, impl_substs);
+
+ // FIXME(fmease, #106722): Check if the bounds on the parameters of the
+ // associated type hold, if any.
+ let ty = tcx.type_of(assoc_item).subst(tcx, item_substs);
+
+ return Ok(Some((ty, assoc_item)));
+ }
+
+ Err(self.complain_about_inherent_assoc_type_not_found(
+ name,
+ self_ty,
+ candidates,
+ fulfillment_errors,
+ span,
+ ))
+ }
+
fn lookup_assoc_ty(
&self,
- ident: Ident,
+ name: Ident,
block: hir::HirId,
span: Span,
scope: DefId,
) -> Option<DefId> {
+ let (item, def_scope) = self.lookup_assoc_ty_unchecked(name, block, scope)?;
+ self.check_assoc_ty(item, name, def_scope, block, span);
+ Some(item)
+ }
+
+ fn lookup_assoc_ty_unchecked(
+ &self,
+ name: Ident,
+ block: hir::HirId,
+ scope: DefId,
+ ) -> Option<(DefId, DefId)> {
let tcx = self.tcx();
- let (ident, def_scope) = tcx.adjust_ident_and_get_scope(ident, scope, block);
+ let (ident, def_scope) = tcx.adjust_ident_and_get_scope(name, scope, block);
// We have already adjusted the item name above, so compare with `ident.normalize_to_macros_2_0()` instead
// of calling `find_by_name_and_kind`.
@@ -2249,20 +2330,86 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
&& i.ident(tcx).normalize_to_macros_2_0() == ident
})?;
+ Some((item.def_id, def_scope))
+ }
+
+ fn check_assoc_ty(
+ &self,
+ item: DefId,
+ name: Ident,
+ def_scope: DefId,
+ block: hir::HirId,
+ span: Span,
+ ) {
+ let tcx = self.tcx();
let kind = DefKind::AssocTy;
- if !item.visibility(tcx).is_accessible_from(def_scope, tcx) {
- let kind = kind.descr(item.def_id);
- let msg = format!("{kind} `{ident}` is private");
- let def_span = self.tcx().def_span(item.def_id);
+
+ if !tcx.visibility(item).is_accessible_from(def_scope, tcx) {
+ let kind = tcx.def_kind_descr(kind, item);
+ let msg = format!("{kind} `{name}` is private");
+ let def_span = tcx.def_span(item);
tcx.sess
.struct_span_err_with_code(span, &msg, rustc_errors::error_code!(E0624))
.span_label(span, &format!("private {kind}"))
.span_label(def_span, &format!("{kind} defined here"))
.emit();
}
- tcx.check_stability(item.def_id, Some(block), span, None);
+ tcx.check_stability(item, Some(block), span, None);
+ }
+
+ fn probe_traits_that_match_assoc_ty(
+ &self,
+ qself_ty: Ty<'tcx>,
+ assoc_ident: Ident,
+ ) -> Vec<String> {
+ let tcx = self.tcx();
+
+ // In contexts that have no inference context, just make a new one.
+ // We do need a local variable to store it, though.
+ let infcx_;
+ let infcx = if let Some(infcx) = self.infcx() {
+ infcx
+ } else {
+ assert!(!qself_ty.needs_infer());
+ infcx_ = tcx.infer_ctxt().build();
+ &infcx_
+ };
- Some(item.def_id)
+ tcx.all_traits()
+ .filter(|trait_def_id| {
+ // Consider only traits with the associated type
+ tcx.associated_items(*trait_def_id)
+ .in_definition_order()
+ .any(|i| {
+ i.kind.namespace() == Namespace::TypeNS
+ && i.ident(tcx).normalize_to_macros_2_0() == assoc_ident
+ && matches!(i.kind, ty::AssocKind::Type)
+ })
+ // Consider only accessible traits
+ && tcx.visibility(*trait_def_id)
+ .is_accessible_from(self.item_def_id(), tcx)
+ && tcx.all_impls(*trait_def_id)
+ .any(|impl_def_id| {
+ let trait_ref = tcx.impl_trait_ref(impl_def_id);
+ trait_ref.map_or(false, |trait_ref| {
+ let impl_ = trait_ref.subst(
+ tcx,
+ infcx.fresh_substs_for_item(DUMMY_SP, impl_def_id),
+ );
+ infcx
+ .can_eq(
+ ty::ParamEnv::empty(),
+ impl_.self_ty(),
+ // Must fold past escaping bound vars too,
+ // since we have those at this point in astconv.
+ tcx.fold_regions(qself_ty, |_, _| tcx.lifetimes.re_erased),
+ )
+ })
+ && tcx.impl_polarity(impl_def_id) != ty::ImplPolarity::Negative
+ })
+ })
+ .map(|trait_def_id| tcx.def_path_str(trait_def_id))
+ .collect()
}
fn qpath_to_ty(
@@ -2323,7 +2470,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
&[path_str],
item_segment.ident.name,
);
- return tcx.ty_error_with_guaranteed(reported)
+ return tcx.ty_error(reported)
};
debug!("qpath_to_ty: self_type={:?}", self_ty);
@@ -2589,6 +2736,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
&self,
opt_self_ty: Option<Ty<'tcx>>,
path: &hir::Path<'_>,
+ hir_id: hir::HirId,
permit_variants: bool,
) -> Ty<'tcx> {
let tcx = self.tcx();
@@ -2652,17 +2800,32 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
}
});
- let def_id = def_id.expect_local();
- let item_def_id = tcx.hir().ty_param_owner(def_id);
- let generics = tcx.generics_of(item_def_id);
- let index = generics.param_def_id_to_index[&def_id.to_def_id()];
- tcx.mk_ty_param(index, tcx.hir().ty_param_name(def_id))
+ match tcx.named_bound_var(hir_id) {
+ Some(rbv::ResolvedArg::LateBound(debruijn, index, _)) => {
+ let name =
+ tcx.hir().name(tcx.hir().local_def_id_to_hir_id(def_id.expect_local()));
+ let br = ty::BoundTy {
+ var: ty::BoundVar::from_u32(index),
+ kind: ty::BoundTyKind::Param(def_id, name),
+ };
+ tcx.mk_bound(debruijn, br)
+ }
+ Some(rbv::ResolvedArg::EarlyBound(_)) => {
+ let def_id = def_id.expect_local();
+ let item_def_id = tcx.hir().ty_param_owner(def_id);
+ let generics = tcx.generics_of(item_def_id);
+ let index = generics.param_def_id_to_index[&def_id.to_def_id()];
+ tcx.mk_ty_param(index, tcx.hir().ty_param_name(def_id))
+ }
+ Some(rbv::ResolvedArg::Error(guar)) => tcx.ty_error(guar),
+ arg => bug!("unexpected bound var resolution for {hir_id:?}: {arg:?}"),
+ }
}
Res::SelfTyParam { .. } => {
// `Self` in trait or type alias.
assert_eq!(opt_self_ty, None);
self.prohibit_generics(path.segments.iter(), |err| {
- if let [hir::PathSegment { args: Some(args), ident, .. }] = &path.segments[..] {
+ if let [hir::PathSegment { args: Some(args), ident, .. }] = &path.segments {
err.span_suggestion_verbose(
ident.span.shrink_to_hi().to(args.span_ext),
"the `Self` type doesn't accept type parameters",
@@ -2677,7 +2840,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
// `Self` in impl (we know the concrete type).
assert_eq!(opt_self_ty, None);
// Try to evaluate any array length constants.
- let ty = tcx.at(span).type_of(def_id);
+ let ty = tcx.at(span).type_of(def_id).subst_identity();
let span_of_impl = tcx.span_of_impl(def_id);
self.prohibit_generics(path.segments.iter(), |err| {
let def_id = match *ty.kind() {
@@ -2766,7 +2929,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
{
err.span_note(impl_.self_ty.span, "not a concrete type");
}
- tcx.ty_error_with_guaranteed(err.emit())
+ tcx.ty_error(err.emit())
} else {
ty
}
@@ -2819,7 +2982,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
.sess
.delay_span_bug(path.span, "path with `Res::Err` but no error emitted");
self.set_tainted_by_errors(e);
- self.tcx().ty_error_with_guaranteed(e)
+ self.tcx().ty_error(e)
}
_ => span_bug!(span, "unexpected resolution: {:?}", path.res),
}
@@ -2855,7 +3018,9 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
tcx.mk_ref(r, ty::TypeAndMut { ty: t, mutbl: mt.mutbl })
}
hir::TyKind::Never => tcx.types.never,
- hir::TyKind::Tup(fields) => tcx.mk_tup(fields.iter().map(|t| self.ast_ty_to_ty(t))),
+ hir::TyKind::Tup(fields) => {
+ tcx.mk_tup_from_iter(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);
@@ -2874,12 +3039,13 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
TraitObjectSyntax::Dyn | TraitObjectSyntax::None => ty::Dyn,
TraitObjectSyntax::DynStar => ty::DynStar,
};
+
self.conv_object_ty_poly_trait_ref(ast_ty.span, bounds, lifetime, borrowed, repr)
}
hir::TyKind::Path(hir::QPath::Resolved(maybe_qself, path)) => {
debug!(?maybe_qself, ?path);
let opt_self_ty = maybe_qself.as_ref().map(|qself| self.ast_ty_to_ty(qself));
- self.res_to_ty(opt_self_ty, path, false)
+ self.res_to_ty(opt_self_ty, path, ast_ty.hir_id, false)
}
&hir::TyKind::OpaqueDef(item_id, lifetimes, in_trait) => {
let opaque_ty = tcx.hir().item(item_id);
@@ -2897,7 +3063,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
let ty = self.ast_ty_to_ty_inner(qself, false, true);
self.associated_path_to_ty(ast_ty.hir_id, ast_ty.span, ty, qself, segment, false)
.map(|(ty, _, _)| ty)
- .unwrap_or_else(|_| tcx.ty_error())
+ .unwrap_or_else(|guar| tcx.ty_error(guar))
}
&hir::TyKind::Path(hir::QPath::LangItem(lang_item, span, _)) => {
let def_id = tcx.require_lang_item(lang_item, Some(span));
@@ -2911,7 +3077,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
None,
ty::BoundConstness::NotConst,
);
- EarlyBinder(tcx.at(span).type_of(def_id)).subst(tcx, substs)
+ tcx.at(span).type_of(def_id).subst(tcx, substs)
}
hir::TyKind::Array(ty, length) => {
let length = match length {
@@ -2921,20 +3087,20 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
}
};
- tcx.mk_ty(ty::Array(self.ast_ty_to_ty(ty), length))
+ tcx.mk_array_with_const_len(self.ast_ty_to_ty(ty), length)
}
hir::TyKind::Typeof(e) => {
- let ty_erased = tcx.type_of(e.def_id);
+ let ty_erased = tcx.type_of(e.def_id).subst_identity();
let ty = tcx.fold_regions(ty_erased, |r, _| {
if r.is_erased() { tcx.lifetimes.re_static } else { r }
});
let span = ast_ty.span;
- tcx.sess.emit_err(TypeofReservedKeywordUsed {
- span,
- ty,
- opt_sugg: Some((span, Applicability::MachineApplicable))
- .filter(|_| ty.is_suggestable(tcx, false)),
- });
+ let (ty, opt_sugg) = if let Some(ty) = ty.make_suggestable(tcx, false) {
+ (ty, Some((span, Applicability::MachineApplicable)))
+ } else {
+ (ty, None)
+ };
+ tcx.sess.emit_err(TypeofReservedKeywordUsed { span, ty, opt_sugg });
ty
}
@@ -2945,7 +3111,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
// handled specially and will not descend into this routine.
self.ty_infer(None, ast_ty.span)
}
- hir::TyKind::Err => tcx.ty_error(),
+ hir::TyKind::Err(guar) => tcx.ty_error(*guar),
};
self.record_ty(ast_ty.hir_id, result_ty, ast_ty.span);
@@ -3052,7 +3218,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
debug!(?output_ty);
- let fn_ty = tcx.mk_fn_sig(input_tys.into_iter(), output_ty, decl.c_variadic, unsafety, abi);
+ let fn_ty = tcx.mk_fn_sig(input_tys, output_ty, decl.c_variadic, unsafety, abi);
let bare_fn_ty = ty::Binder::bind_with_vars(fn_ty, bound_vars);
if !self.allow_ty_infer() && !(visitor.0.is_empty() && infer_replacements.is_empty()) {
@@ -3124,8 +3290,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
let hir::Node::ImplItem(hir::ImplItem { kind: hir::ImplItemKind::Fn(..), ident, .. }) =
hir.get(fn_hir_id) else { return None };
- let hir::Node::Item(hir::Item { kind: hir::ItemKind::Impl(i), .. }) =
- hir.get_parent(fn_hir_id) else { bug!("ImplItem should have Impl parent") };
+ let i = hir.get_parent(fn_hir_id).expect_item().expect_impl();
let trait_ref = self.instantiate_mono_trait_ref(
i.of_trait.as_ref()?,
@@ -3140,7 +3305,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
trait_ref.def_id,
)?;
- let fn_sig = tcx.bound_fn_sig(assoc.def_id).subst(
+ let fn_sig = tcx.fn_sig(assoc.def_id).subst(
tcx,
trait_ref.substs.extend_to(tcx, assoc.def_id, |param, _| tcx.mk_param_from_def(param)),
);
@@ -3336,3 +3501,36 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
}
}
}
+
+pub trait InferCtxtExt<'tcx> {
+ fn fresh_item_substs(&self, def_id: DefId) -> SubstsRef<'tcx>;
+}
+
+impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> {
+ fn fresh_item_substs(&self, def_id: DefId) -> SubstsRef<'tcx> {
+ InternalSubsts::for_item(self.tcx, def_id, |param, _| match param.kind {
+ GenericParamDefKind::Lifetime => self.tcx.lifetimes.re_erased.into(),
+ GenericParamDefKind::Type { .. } => self
+ .next_ty_var(TypeVariableOrigin {
+ kind: TypeVariableOriginKind::SubstitutionPlaceholder,
+ span: self.tcx.def_span(def_id),
+ })
+ .into(),
+ GenericParamDefKind::Const { .. } => {
+ let span = self.tcx.def_span(def_id);
+ let origin = ConstVariableOrigin {
+ kind: ConstVariableOriginKind::SubstitutionPlaceholder,
+ span,
+ };
+ self.next_const_var(
+ self.tcx
+ .type_of(param.def_id)
+ .no_bound_vars()
+ .expect("const parameter types cannot be generic"),
+ origin,
+ )
+ .into()
+ }
+ })
+ }
+}
diff --git a/compiler/rustc_hir_analysis/src/autoderef.rs b/compiler/rustc_hir_analysis/src/autoderef.rs
index 730560cc6..ba2d4319a 100644
--- a/compiler/rustc_hir_analysis/src/autoderef.rs
+++ b/compiler/rustc_hir_analysis/src/autoderef.rs
@@ -2,11 +2,11 @@ use crate::errors::AutoDerefReachedRecursionLimit;
use crate::traits::query::evaluate_obligation::InferCtxtExt;
use crate::traits::NormalizeExt;
use crate::traits::{self, TraitEngine, TraitEngineExt};
-use rustc_hir as hir;
use rustc_infer::infer::InferCtxt;
-use rustc_middle::ty::TypeVisitable;
+use rustc_middle::ty::TypeVisitableExt;
use rustc_middle::ty::{self, Ty, TyCtxt};
use rustc_session::Limit;
+use rustc_span::def_id::LocalDefId;
use rustc_span::def_id::LOCAL_CRATE;
use rustc_span::Span;
@@ -28,7 +28,7 @@ pub struct Autoderef<'a, 'tcx> {
// Meta infos:
infcx: &'a InferCtxt<'tcx>,
span: Span,
- body_id: hir::HirId,
+ body_id: LocalDefId,
param_env: ty::ParamEnv<'tcx>,
// Current state:
@@ -96,14 +96,14 @@ impl<'a, 'tcx> Autoderef<'a, 'tcx> {
pub fn new(
infcx: &'a InferCtxt<'tcx>,
param_env: ty::ParamEnv<'tcx>,
- body_id: hir::HirId,
+ body_def_id: LocalDefId,
span: Span,
base_ty: Ty<'tcx>,
) -> Autoderef<'a, 'tcx> {
Autoderef {
infcx,
span,
- body_id,
+ body_id: body_def_id,
param_env,
state: AutoderefSnapshot {
steps: vec![],
diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs
index abc1c2d7b..848828175 100644
--- a/compiler/rustc_hir_analysis/src/check/check.rs
+++ b/compiler/rustc_hir_analysis/src/check/check.rs
@@ -14,21 +14,24 @@ use rustc_hir::{ItemKind, Node, PathSegment};
use rustc_infer::infer::opaque_types::ConstrainOpaqueTypeRegionVisitor;
use rustc_infer::infer::outlives::env::OutlivesEnvironment;
use rustc_infer::infer::{DefiningAnchor, RegionVariableOrigin, TyCtxtInferExt};
-use rustc_infer::traits::Obligation;
+use rustc_infer::traits::{Obligation, TraitEngineExt as _};
use rustc_lint::builtin::REPR_TRANSPARENT_EXTERNAL_PRIVATE_FIELDS;
use rustc_middle::hir::nested_filter;
use rustc_middle::middle::stability::EvalResult;
use rustc_middle::ty::layout::{LayoutError, MAX_SIMD_LANES};
use rustc_middle::ty::subst::GenericArgKind;
use rustc_middle::ty::util::{Discr, IntTypeExt};
-use rustc_middle::ty::{self, AdtDef, ParamEnv, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable};
+use rustc_middle::ty::{
+ self, AdtDef, DefIdTree, ParamEnv, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable,
+ TypeVisitableExt,
+};
use rustc_session::lint::builtin::{UNINHABITED_STATIC, UNSUPPORTED_CALLING_CONVENTIONS};
use rustc_span::symbol::sym;
use rustc_span::{self, Span};
use rustc_target::spec::abi::Abi;
use rustc_trait_selection::traits::error_reporting::on_unimplemented::OnUnimplementedDirective;
use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt as _;
-use rustc_trait_selection::traits::{self, ObligationCtxt};
+use rustc_trait_selection::traits::{self, ObligationCtxt, TraitEngine, TraitEngineExt as _};
use std::ops::ControlFlow;
@@ -91,7 +94,7 @@ fn check_union(tcx: TyCtxt<'_>, def_id: LocalDefId) {
/// Check that the fields of the `union` do not need dropping.
fn check_union_fields(tcx: TyCtxt<'_>, span: Span, item_def_id: LocalDefId) -> bool {
- let item_type = tcx.type_of(item_def_id);
+ let item_type = tcx.type_of(item_def_id).subst_identity();
if let ty::Adt(def, substs) = item_type.kind() {
assert!(def.is_union());
@@ -121,7 +124,7 @@ fn check_union_fields(tcx: TyCtxt<'_>, span: Span, item_def_id: LocalDefId) -> b
let param_env = tcx.param_env(item_def_id);
for field in &def.non_enum_variant().fields {
- let field_ty = field.ty(tcx, substs);
+ let field_ty = tcx.normalize_erasing_regions(param_env, field.ty(tcx, substs));
if !allowed_union_field(field_ty, tcx, param_env) {
let (field_span, ty_span) = match tcx.hir().get_if_local(field.did) {
@@ -168,22 +171,14 @@ fn check_static_inhabited(tcx: TyCtxt<'_>, def_id: LocalDefId) {
// would be enough to check this for `extern` statics, as statics with an initializer will
// have UB during initialization if they are uninhabited, but there also seems to be no good
// reason to allow any statics to be uninhabited.
- let ty = tcx.type_of(def_id);
+ let ty = tcx.type_of(def_id).subst_identity();
let span = tcx.def_span(def_id);
let layout = match tcx.layout_of(ParamEnv::reveal_all().and(ty)) {
Ok(l) => l,
// Foreign statics that overflow their allowed size should emit an error
Err(LayoutError::SizeOverflow(_))
- if {
- let node = tcx.hir().get_by_def_id(def_id);
- matches!(
- node,
- hir::Node::ForeignItem(hir::ForeignItem {
- kind: hir::ForeignItemKind::Static(..),
- ..
- })
- )
- } =>
+ if matches!(tcx.def_kind(def_id), DefKind::Static(_)
+ if tcx.def_kind(tcx.local_parent(def_id)) == DefKind::ForeignMod) =>
{
tcx.sess
.struct_span_err(span, "extern static is too large for the current architecture")
@@ -215,7 +210,7 @@ fn check_static_inhabited(tcx: TyCtxt<'_>, def_id: LocalDefId) {
fn check_opaque(tcx: TyCtxt<'_>, id: hir::ItemId) {
let item = tcx.hir().item(id);
let hir::ItemKind::OpaqueTy(hir::OpaqueTy { origin, .. }) = item.kind else {
- tcx.sess.delay_span_bug(tcx.hir().span(id.hir_id()), "expected opaque item");
+ tcx.sess.delay_span_bug(item.span, "expected opaque item");
return;
};
@@ -233,7 +228,7 @@ fn check_opaque(tcx: TyCtxt<'_>, id: hir::ItemId) {
if !tcx.features().impl_trait_projections {
check_opaque_for_inheriting_lifetimes(tcx, item.owner_id.def_id, span);
}
- if tcx.type_of(item.owner_id.def_id).references_error() {
+ if tcx.type_of(item.owner_id.def_id).subst_identity().references_error() {
return;
}
if check_opaque_for_cycles(tcx, item.owner_id.def_id, substs, span, &origin).is_err() {
@@ -261,7 +256,7 @@ pub(super) fn check_opaque_for_inheriting_lifetimes(
selftys: Vec<(Span, Option<String>)>,
}
- impl<'tcx> ty::visit::TypeVisitor<'tcx> for ProhibitOpaqueVisitor<'tcx> {
+ impl<'tcx> ty::visit::TypeVisitor<TyCtxt<'tcx>> for ProhibitOpaqueVisitor<'tcx> {
type BreakTy = Ty<'tcx>;
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
@@ -412,7 +407,6 @@ fn check_opaque_meets_bounds<'tcx>(
span: Span,
origin: &hir::OpaqueTyOrigin,
) {
- let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
let defining_use_anchor = match *origin {
hir::OpaqueTyOrigin::FnReturn(did) | hir::OpaqueTyOrigin::AsyncFn(did) => did,
hir::OpaqueTyOrigin::TyAlias => def_id,
@@ -432,17 +426,18 @@ fn check_opaque_meets_bounds<'tcx>(
//
// FIXME: Consider wrapping the hidden type in an existential `Binder` and instantiating it
// here rather than using ReErased.
- let hidden_ty = tcx.bound_type_of(def_id.to_def_id()).subst(tcx, substs);
+ let hidden_ty = tcx.type_of(def_id.to_def_id()).subst(tcx, substs);
let hidden_ty = tcx.fold_regions(hidden_ty, |re, _dbi| match re.kind() {
ty::ReErased => infcx.next_region_var(RegionVariableOrigin::MiscVariable(span)),
_ => re,
});
- let misc_cause = traits::ObligationCause::misc(span, hir_id);
+ let misc_cause = traits::ObligationCause::misc(span, def_id);
match ocx.eq(&misc_cause, param_env, opaque_ty, hidden_ty) {
Ok(()) => {}
Err(ty_err) => {
+ let ty_err = ty_err.to_string(tcx);
tcx.sess.delay_span_bug(
span,
&format!("could not unify `{hidden_ty}` with revealed type:\n{ty_err}"),
@@ -498,7 +493,7 @@ fn is_enum_of_nonnullable_ptr<'tcx>(
fn check_static_linkage(tcx: TyCtxt<'_>, def_id: LocalDefId) {
if tcx.codegen_fn_attrs(def_id).import_linkage.is_some() {
- if match tcx.type_of(def_id).kind() {
+ if match tcx.type_of(def_id).subst_identity().kind() {
ty::RawPtr(_) => false,
ty::Adt(adt_def, substs) => !is_enum_of_nonnullable_ptr(tcx, *adt_def, *substs),
_ => true,
@@ -529,45 +524,34 @@ fn check_item_type(tcx: TyCtxt<'_>, id: hir::ItemId) {
check_enum(tcx, id.owner_id.def_id);
}
DefKind::Fn => {} // entirely within check_item_body
- DefKind::Impl => {
- let it = tcx.hir().item(id);
- let hir::ItemKind::Impl(impl_) = it.kind else { return };
- debug!("ItemKind::Impl {} with id {:?}", it.ident, it.owner_id);
- if let Some(impl_trait_ref) = tcx.impl_trait_ref(it.owner_id) {
+ DefKind::Impl { of_trait } => {
+ if of_trait && let Some(impl_trait_ref) = tcx.impl_trait_ref(id.owner_id) {
check_impl_items_against_trait(
tcx,
- it.span,
- it.owner_id.def_id,
+ id.owner_id.def_id,
impl_trait_ref.subst_identity(),
- &impl_.items,
);
- check_on_unimplemented(tcx, it);
+ check_on_unimplemented(tcx, id);
}
}
DefKind::Trait => {
- let it = tcx.hir().item(id);
- let hir::ItemKind::Trait(_, _, _, _, items) = it.kind else {
- return;
- };
- check_on_unimplemented(tcx, it);
-
- for item in items.iter() {
- let item = tcx.hir().trait_item(item.id);
- match &item.kind {
- hir::TraitItemKind::Fn(sig, _) => {
- let abi = sig.header.abi;
- fn_maybe_err(tcx, item.ident.span, abi);
+ let assoc_items = tcx.associated_items(id.owner_id);
+ check_on_unimplemented(tcx, id);
+
+ for &assoc_item in assoc_items.in_definition_order() {
+ match assoc_item.kind {
+ ty::AssocKind::Fn => {
+ let abi = tcx.fn_sig(assoc_item.def_id).skip_binder().abi();
+ fn_maybe_err(tcx, assoc_item.ident(tcx).span, abi);
}
- hir::TraitItemKind::Type(.., Some(default)) => {
- let assoc_item = tcx.associated_item(item.owner_id);
+ ty::AssocKind::Type if assoc_item.defaultness(tcx).has_value() => {
let trait_substs =
- InternalSubsts::identity_for_item(tcx, it.owner_id.to_def_id());
+ InternalSubsts::identity_for_item(tcx, id.owner_id.to_def_id());
let _: Result<_, rustc_errors::ErrorGuaranteed> = check_type_bounds(
tcx,
assoc_item,
assoc_item,
- default.span,
- tcx.mk_trait_ref(it.owner_id.to_def_id(), trait_substs),
+ tcx.mk_trait_ref(id.owner_id.to_def_id(), trait_substs),
);
}
_ => {}
@@ -595,7 +579,7 @@ fn check_item_type(tcx: TyCtxt<'_>, id: hir::ItemId) {
}
}
DefKind::TyAlias => {
- let pty_ty = tcx.type_of(id.owner_id);
+ let pty_ty = tcx.type_of(id.owner_id).subst_identity();
let generics = tcx.generics_of(id.owner_id);
check_type_params_are_used(tcx, &generics, pty_ty);
}
@@ -606,59 +590,66 @@ fn check_item_type(tcx: TyCtxt<'_>, id: hir::ItemId) {
};
check_abi(tcx, it.hir_id(), it.span, abi);
- if abi == Abi::RustIntrinsic {
- for item in items {
- let item = tcx.hir().foreign_item(item.id);
- intrinsic::check_intrinsic_type(tcx, item);
- }
- } else if abi == Abi::PlatformIntrinsic {
- for item in items {
- let item = tcx.hir().foreign_item(item.id);
- intrinsic::check_platform_intrinsic_type(tcx, item);
+ match abi {
+ Abi::RustIntrinsic => {
+ for item in items {
+ let item = tcx.hir().foreign_item(item.id);
+ intrinsic::check_intrinsic_type(tcx, item);
+ }
}
- } else {
- for item in items {
- let def_id = item.id.owner_id.def_id;
- let generics = tcx.generics_of(def_id);
- let own_counts = generics.own_counts();
- if generics.params.len() - own_counts.lifetimes != 0 {
- let (kinds, kinds_pl, egs) = match (own_counts.types, own_counts.consts) {
- (_, 0) => ("type", "types", Some("u32")),
- // We don't specify an example value, because we can't generate
- // a valid value for any type.
- (0, _) => ("const", "consts", None),
- _ => ("type or const", "types or consts", None),
- };
- struct_span_err!(
- tcx.sess,
- item.span,
- E0044,
- "foreign items may not have {kinds} parameters",
- )
- .span_label(item.span, &format!("can't have {kinds} parameters"))
- .help(
- // FIXME: once we start storing spans for type arguments, turn this
- // into a suggestion.
- &format!(
- "replace the {} parameters with concrete {}{}",
- kinds,
- kinds_pl,
- egs.map(|egs| format!(" like `{}`", egs)).unwrap_or_default(),
- ),
- )
- .emit();
+
+ Abi::PlatformIntrinsic => {
+ for item in items {
+ let item = tcx.hir().foreign_item(item.id);
+ intrinsic::check_platform_intrinsic_type(tcx, item);
}
+ }
- let item = tcx.hir().foreign_item(item.id);
- match &item.kind {
- hir::ForeignItemKind::Fn(fn_decl, _, _) => {
- require_c_abi_if_c_variadic(tcx, fn_decl, abi, item.span);
+ _ => {
+ for item in items {
+ let def_id = item.id.owner_id.def_id;
+ let generics = tcx.generics_of(def_id);
+ let own_counts = generics.own_counts();
+ if generics.params.len() - own_counts.lifetimes != 0 {
+ let (kinds, kinds_pl, egs) = match (own_counts.types, own_counts.consts)
+ {
+ (_, 0) => ("type", "types", Some("u32")),
+ // We don't specify an example value, because we can't generate
+ // a valid value for any type.
+ (0, _) => ("const", "consts", None),
+ _ => ("type or const", "types or consts", None),
+ };
+ struct_span_err!(
+ tcx.sess,
+ item.span,
+ E0044,
+ "foreign items may not have {kinds} parameters",
+ )
+ .span_label(item.span, &format!("can't have {kinds} parameters"))
+ .help(
+ // FIXME: once we start storing spans for type arguments, turn this
+ // into a suggestion.
+ &format!(
+ "replace the {} parameters with concrete {}{}",
+ kinds,
+ kinds_pl,
+ egs.map(|egs| format!(" like `{}`", egs)).unwrap_or_default(),
+ ),
+ )
+ .emit();
}
- hir::ForeignItemKind::Static(..) => {
- check_static_inhabited(tcx, def_id);
- check_static_linkage(tcx, def_id);
+
+ let item = tcx.hir().foreign_item(item.id);
+ match &item.kind {
+ hir::ForeignItemKind::Fn(fn_decl, _, _) => {
+ require_c_abi_if_c_variadic(tcx, fn_decl, abi, item.span);
+ }
+ hir::ForeignItemKind::Static(..) => {
+ check_static_inhabited(tcx, def_id);
+ check_static_linkage(tcx, def_id);
+ }
+ _ => {}
}
- _ => {}
}
}
}
@@ -666,13 +657,13 @@ fn check_item_type(tcx: TyCtxt<'_>, id: hir::ItemId) {
DefKind::GlobalAsm => {
let it = tcx.hir().item(id);
let hir::ItemKind::GlobalAsm(asm) = it.kind else { span_bug!(it.span, "DefKind::GlobalAsm but got {:#?}", it) };
- InlineAsmCtxt::new_global_asm(tcx).check_asm(asm, id.hir_id());
+ InlineAsmCtxt::new_global_asm(tcx).check_asm(asm, id.owner_id.def_id);
}
_ => {}
}
}
-pub(super) fn check_on_unimplemented(tcx: TyCtxt<'_>, item: &hir::Item<'_>) {
+pub(super) fn check_on_unimplemented(tcx: TyCtxt<'_>, item: hir::ItemId) {
// an error would be reported if this fails.
let _ = OnUnimplementedDirective::of_item(tcx, item.owner_id.to_def_id());
}
@@ -680,9 +671,9 @@ pub(super) fn check_on_unimplemented(tcx: TyCtxt<'_>, item: &hir::Item<'_>) {
pub(super) fn check_specialization_validity<'tcx>(
tcx: TyCtxt<'tcx>,
trait_def: &ty::TraitDef,
- trait_item: &ty::AssocItem,
+ trait_item: ty::AssocItem,
impl_id: DefId,
- impl_item: &hir::ImplItemRef,
+ impl_item: DefId,
) {
let Ok(ancestors) = trait_def.ancestors(tcx, impl_id) else { return };
let mut ancestor_impls = ancestors.skip(1).filter_map(|parent| {
@@ -728,10 +719,8 @@ pub(super) fn check_specialization_validity<'tcx>(
fn check_impl_items_against_trait<'tcx>(
tcx: TyCtxt<'tcx>,
- full_impl_span: Span,
impl_id: LocalDefId,
impl_trait_ref: ty::TraitRef<'tcx>,
- 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`
@@ -740,12 +729,14 @@ fn check_impl_items_against_trait<'tcx>(
return;
}
+ let impl_item_refs = tcx.associated_item_def_ids(impl_id);
+
// Negative impls are not expected to have any items
match tcx.impl_polarity(impl_id) {
ty::ImplPolarity::Reservation | ty::ImplPolarity::Positive => {}
ty::ImplPolarity::Negative => {
if let [first_item_ref, ..] = impl_item_refs {
- let first_item_span = tcx.hir().impl_item(first_item_ref.id).span;
+ let first_item_span = tcx.def_span(first_item_ref);
struct_span_err!(
tcx.sess,
first_item_span,
@@ -760,50 +751,34 @@ fn check_impl_items_against_trait<'tcx>(
let trait_def = tcx.trait_def(impl_trait_ref.def_id);
- for impl_item in impl_item_refs {
- let ty_impl_item = tcx.associated_item(impl_item.id.owner_id);
+ for &impl_item in impl_item_refs {
+ let ty_impl_item = tcx.associated_item(impl_item);
let ty_trait_item = if let Some(trait_item_id) = ty_impl_item.trait_item_def_id {
tcx.associated_item(trait_item_id)
} else {
// Checked in `associated_item`.
- tcx.sess.delay_span_bug(impl_item.span, "missing associated item in trait");
+ tcx.sess.delay_span_bug(tcx.def_span(impl_item), "missing associated item in trait");
continue;
};
- let impl_item_full = tcx.hir().impl_item(impl_item.id);
- match impl_item_full.kind {
- hir::ImplItemKind::Const(..) => {
+ match ty_impl_item.kind {
+ ty::AssocKind::Const => {
let _ = tcx.compare_impl_const((
- impl_item.id.owner_id.def_id,
+ impl_item.expect_local(),
ty_impl_item.trait_item_def_id.unwrap(),
));
}
- hir::ImplItemKind::Fn(..) => {
- let opt_trait_span = tcx.hir().span_if_local(ty_trait_item.def_id);
- compare_impl_method(
- tcx,
- &ty_impl_item,
- &ty_trait_item,
- impl_trait_ref,
- opt_trait_span,
- );
+ ty::AssocKind::Fn => {
+ compare_impl_method(tcx, ty_impl_item, ty_trait_item, impl_trait_ref);
}
- hir::ImplItemKind::Type(impl_ty) => {
- let opt_trait_span = tcx.hir().span_if_local(ty_trait_item.def_id);
- compare_impl_ty(
- tcx,
- &ty_impl_item,
- impl_ty.span,
- &ty_trait_item,
- impl_trait_ref,
- opt_trait_span,
- );
+ ty::AssocKind::Type => {
+ compare_impl_ty(tcx, ty_impl_item, ty_trait_item, impl_trait_ref);
}
}
check_specialization_validity(
tcx,
trait_def,
- &ty_trait_item,
+ ty_trait_item,
impl_id.to_def_id(),
impl_item,
);
@@ -817,8 +792,10 @@ fn check_impl_items_against_trait<'tcx>(
trait_def.must_implement_one_of.as_deref();
for &trait_item_id in tcx.associated_item_def_ids(impl_trait_ref.def_id) {
- let is_implemented = ancestors
- .leaf_def(tcx, trait_item_id)
+ let leaf_def = ancestors.leaf_def(tcx, trait_item_id);
+
+ let is_implemented = leaf_def
+ .as_ref()
.map_or(false, |node_item| node_item.item.defaultness(tcx).has_value());
if !is_implemented && tcx.impl_defaultness(impl_id).is_final() {
@@ -826,11 +803,13 @@ fn check_impl_items_against_trait<'tcx>(
}
// true if this item is specifically implemented in this impl
- let is_implemented_here = ancestors
- .leaf_def(tcx, trait_item_id)
+ let is_implemented_here = leaf_def
+ .as_ref()
.map_or(false, |node_item| !node_item.defining_node.is_from_trait());
if !is_implemented_here {
+ let full_impl_span =
+ tcx.hir().span_with_body(tcx.hir().local_def_id_to_hir_id(impl_id));
match tcx.eval_default_body_stability(trait_item_id, full_impl_span) {
EvalResult::Deny { feature, reason, issue, .. } => default_body_is_unstable(
tcx,
@@ -854,9 +833,41 @@ fn check_impl_items_against_trait<'tcx>(
}
}
}
+
+ if let Some(leaf_def) = &leaf_def
+ && !leaf_def.is_final()
+ && let def_id = leaf_def.item.def_id
+ && tcx.impl_method_has_trait_impl_trait_tys(def_id)
+ {
+ let def_kind = tcx.def_kind(def_id);
+ let descr = tcx.def_kind_descr(def_kind, def_id);
+ let (msg, feature) = if tcx.asyncness(def_id).is_async() {
+ (
+ format!("async {descr} in trait cannot be specialized"),
+ sym::async_fn_in_trait,
+ )
+ } else {
+ (
+ format!(
+ "{descr} with return-position `impl Trait` in trait cannot be specialized"
+ ),
+ sym::return_position_impl_trait_in_trait,
+ )
+ };
+ tcx.sess
+ .struct_span_err(tcx.def_span(def_id), msg)
+ .note(format!(
+ "specialization behaves in inconsistent and \
+ surprising ways with `#![feature({feature})]`, \
+ and for now is disallowed"
+ ))
+ .emit();
+ }
}
if !missing_items.is_empty() {
+ let full_impl_span =
+ tcx.hir().span_with_body(tcx.hir().local_def_id_to_hir_id(impl_id));
missing_items_err(tcx, tcx.def_span(impl_id), &missing_items, full_impl_span);
}
@@ -876,7 +887,7 @@ fn check_impl_items_against_trait<'tcx>(
}
pub fn check_simd(tcx: TyCtxt<'_>, sp: Span, def_id: LocalDefId) {
- let t = tcx.type_of(def_id);
+ let t = tcx.type_of(def_id).subst_identity();
if let ty::Adt(def, substs) = t.kind()
&& def.is_struct()
{
@@ -894,7 +905,7 @@ pub fn check_simd(tcx: TyCtxt<'_>, sp: Span, def_id: LocalDefId) {
}
let len = if let ty::Array(_ty, c) = e.kind() {
- c.try_eval_usize(tcx, tcx.param_env(def.did()))
+ c.try_eval_target_usize(tcx, tcx.param_env(def.did()))
} else {
Some(fields.len() as u64)
};
@@ -996,7 +1007,7 @@ pub(super) fn check_packed(tcx: TyCtxt<'_>, sp: Span, def: ty::AdtDef<'_>) {
&if first {
format!(
"`{}` contains a field of type `{}`",
- tcx.type_of(def.did()),
+ tcx.type_of(def.did()).subst_identity(),
ident
)
} else {
@@ -1018,7 +1029,7 @@ pub(super) fn check_packed_inner(
def_id: DefId,
stack: &mut Vec<DefId>,
) -> Option<Vec<(DefId, Span)>> {
- if let ty::Adt(def, substs) = tcx.type_of(def_id).kind() {
+ if let ty::Adt(def, substs) = tcx.type_of(def_id).subst_identity().kind() {
if def.is_struct() || def.is_union() {
if def.repr().align.is_some() {
return Some(vec![(def.did(), DUMMY_SP)]);
@@ -1440,7 +1451,7 @@ fn opaque_type_cycle_error(
opaques: Vec<DefId>,
closures: Vec<DefId>,
}
- impl<'tcx> ty::visit::TypeVisitor<'tcx> for OpaqueTypeCollector {
+ impl<'tcx> ty::visit::TypeVisitor<TyCtxt<'tcx>> for OpaqueTypeCollector {
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
match *t.kind() {
ty::Alias(ty::Opaque, ty::AliasTy { def_id: def, .. }) => {
@@ -1461,7 +1472,8 @@ fn opaque_type_cycle_error(
for def_id in visitor.opaques {
let ty_span = tcx.def_span(def_id);
if !seen.contains(&ty_span) {
- err.span_label(ty_span, &format!("returning this opaque type `{ty}`"));
+ let descr = if ty.is_impl_trait() { "opaque " } else { "" };
+ err.span_label(ty_span, &format!("returning this {descr}type `{ty}`"));
seen.insert(ty_span);
}
err.span_label(sp, &format!("returning here with type `{ty}`"));
@@ -1481,7 +1493,7 @@ fn opaque_type_cycle_error(
span,
format!(
"{} captures itself here",
- tcx.def_kind(closure_def_id).descr(closure_def_id)
+ tcx.def_descr(closure_def_id)
),
);
}
@@ -1508,3 +1520,34 @@ fn opaque_type_cycle_error(
}
err.emit()
}
+
+pub(super) fn check_generator_obligations(tcx: TyCtxt<'_>, def_id: LocalDefId) {
+ debug_assert!(tcx.sess.opts.unstable_opts.drop_tracking_mir);
+ debug_assert!(matches!(tcx.def_kind(def_id), DefKind::Generator));
+
+ let typeck = tcx.typeck(def_id);
+ let param_env = tcx.param_env(def_id);
+
+ let generator_interior_predicates = &typeck.generator_interior_predicates[&def_id];
+ debug!(?generator_interior_predicates);
+
+ let infcx = tcx
+ .infer_ctxt()
+ // typeck writeback gives us predicates with their regions erased.
+ // As borrowck already has checked lifetimes, we do not need to do it again.
+ .ignoring_regions()
+ // Bind opaque types to `def_id` as they should have been checked by borrowck.
+ .with_opaque_type_inference(DefiningAnchor::Bind(def_id))
+ .build();
+
+ let mut fulfillment_cx = <dyn TraitEngine<'_>>::new(infcx.tcx);
+ for (predicate, cause) in generator_interior_predicates {
+ let obligation = Obligation::new(tcx, cause.clone(), param_env, *predicate);
+ fulfillment_cx.register_predicate_obligation(&infcx, obligation);
+ }
+ let errors = fulfillment_cx.select_all_or_error(&infcx);
+ debug!(?errors);
+ if !errors.is_empty() {
+ infcx.err_ctxt().report_fulfillment_errors(&errors, None);
+ }
+}
diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
index cfebcceef..691d3f8d9 100644
--- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
+++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
@@ -8,7 +8,7 @@ use rustc_errors::{
use rustc_hir as hir;
use rustc_hir::def::{DefKind, Res};
use rustc_hir::intravisit;
-use rustc_hir::{GenericParamKind, ImplItemKind, TraitItemKind};
+use rustc_hir::{GenericParamKind, ImplItemKind};
use rustc_infer::infer::outlives::env::OutlivesEnvironment;
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
use rustc_infer::infer::{self, InferCtxt, TyCtxtInferExt};
@@ -16,7 +16,8 @@ use rustc_infer::traits::util;
use rustc_middle::ty::error::{ExpectedFound, TypeError};
use rustc_middle::ty::util::ExplicitSelf;
use rustc_middle::ty::{
- self, DefIdTree, InternalSubsts, Ty, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitable,
+ self, DefIdTree, InternalSubsts, Ty, TypeFoldable, TypeFolder, TypeSuperFoldable,
+ TypeVisitableExt,
};
use rustc_middle::ty::{GenericParamDefKind, ToPredicate, TyCtxt};
use rustc_span::Span;
@@ -33,31 +34,26 @@ use std::iter;
/// # Parameters
///
/// - `impl_m`: type of the method we are checking
-/// - `impl_m_span`: span to use for reporting errors
/// - `trait_m`: the method in the trait
/// - `impl_trait_ref`: the TraitRef corresponding to the trait implementation
pub(super) fn compare_impl_method<'tcx>(
tcx: TyCtxt<'tcx>,
- impl_m: &ty::AssocItem,
- trait_m: &ty::AssocItem,
+ impl_m: ty::AssocItem,
+ trait_m: ty::AssocItem,
impl_trait_ref: ty::TraitRef<'tcx>,
- trait_item_span: Option<Span>,
) {
debug!("compare_impl_method(impl_trait_ref={:?})", impl_trait_ref);
- let impl_m_span = tcx.def_span(impl_m.def_id);
-
let _: Result<_, ErrorGuaranteed> = try {
- compare_self_type(tcx, impl_m, impl_m_span, trait_m, impl_trait_ref)?;
- compare_number_of_generics(tcx, impl_m, trait_m, trait_item_span, false)?;
+ compare_self_type(tcx, impl_m, trait_m, impl_trait_ref)?;
+ compare_number_of_generics(tcx, impl_m, trait_m, false)?;
compare_generic_param_kinds(tcx, impl_m, trait_m, false)?;
- compare_number_of_method_arguments(tcx, impl_m, impl_m_span, trait_m, trait_item_span)?;
+ compare_number_of_method_arguments(tcx, impl_m, trait_m)?;
compare_synthetic_generics(tcx, impl_m, trait_m)?;
- compare_asyncness(tcx, impl_m, impl_m_span, trait_m, trait_item_span)?;
+ compare_asyncness(tcx, impl_m, trait_m)?;
compare_method_predicate_entailment(
tcx,
impl_m,
- impl_m_span,
trait_m,
impl_trait_ref,
CheckImpliedWfMode::Check,
@@ -131,12 +127,11 @@ pub(super) fn compare_impl_method<'tcx>(
///
/// Finally we register each of these predicates as an obligation and check that
/// they hold.
-#[instrument(level = "debug", skip(tcx, impl_m_span, impl_trait_ref))]
+#[instrument(level = "debug", skip(tcx, impl_trait_ref))]
fn compare_method_predicate_entailment<'tcx>(
tcx: TyCtxt<'tcx>,
- impl_m: &ty::AssocItem,
- impl_m_span: Span,
- trait_m: &ty::AssocItem,
+ impl_m: ty::AssocItem,
+ trait_m: ty::AssocItem,
impl_trait_ref: ty::TraitRef<'tcx>,
check_implied_wf: CheckImpliedWfMode,
) -> Result<(), ErrorGuaranteed> {
@@ -147,12 +142,13 @@ fn compare_method_predicate_entailment<'tcx>(
//
// FIXME(@lcnr): remove that after removing `cause.body_id` from
// obligations.
- let impl_m_hir_id = tcx.hir().local_def_id_to_hir_id(impl_m.def_id.expect_local());
+ let impl_m_def_id = impl_m.def_id.expect_local();
+ let impl_m_span = tcx.def_span(impl_m_def_id);
let cause = ObligationCause::new(
impl_m_span,
- impl_m_hir_id,
+ impl_m_def_id,
ObligationCauseCode::CompareImplItemObligation {
- impl_item_def_id: impl_m.def_id.expect_local(),
+ impl_item_def_id: impl_m_def_id,
trait_item_def_id: trait_m.def_id,
kind: impl_m.kind,
},
@@ -198,9 +194,9 @@ fn compare_method_predicate_entailment<'tcx>(
// Construct trait parameter environment and then shift it into the placeholder viewpoint.
// The key step here is to update the caller_bounds's predicates to be
// the new hybrid bounds we computed.
- let normalize_cause = traits::ObligationCause::misc(impl_m_span, impl_m_hir_id);
+ let normalize_cause = traits::ObligationCause::misc(impl_m_span, impl_m_def_id);
let param_env = ty::ParamEnv::new(
- tcx.intern_predicates(&hybrid_preds.predicates),
+ tcx.mk_predicates(&hybrid_preds.predicates),
Reveal::UserFacing,
hir::Constness::NotConst,
);
@@ -213,14 +209,14 @@ fn compare_method_predicate_entailment<'tcx>(
let impl_m_own_bounds = impl_m_predicates.instantiate_own(tcx, impl_to_placeholder_substs);
for (predicate, span) in impl_m_own_bounds {
- let normalize_cause = traits::ObligationCause::misc(span, impl_m_hir_id);
+ let normalize_cause = traits::ObligationCause::misc(span, impl_m_def_id);
let predicate = ocx.normalize(&normalize_cause, param_env, predicate);
let cause = ObligationCause::new(
span,
- impl_m_hir_id,
+ impl_m_def_id,
ObligationCauseCode::CompareImplItemObligation {
- impl_item_def_id: impl_m.def_id.expect_local(),
+ impl_item_def_id: impl_m_def_id,
trait_item_def_id: trait_m.def_id,
kind: impl_m.kind,
},
@@ -246,18 +242,18 @@ fn compare_method_predicate_entailment<'tcx>(
let mut wf_tys = FxIndexSet::default();
- let unnormalized_impl_sig = infcx.replace_bound_vars_with_fresh_vars(
+ let unnormalized_impl_sig = infcx.instantiate_binder_with_fresh_vars(
impl_m_span,
infer::HigherRankedType,
- tcx.fn_sig(impl_m.def_id),
+ tcx.fn_sig(impl_m.def_id).subst_identity(),
);
let unnormalized_impl_fty = tcx.mk_fn_ptr(ty::Binder::dummy(unnormalized_impl_sig));
- let norm_cause = ObligationCause::misc(impl_m_span, impl_m_hir_id);
+ let norm_cause = ObligationCause::misc(impl_m_span, impl_m_def_id);
let impl_sig = ocx.normalize(&norm_cause, param_env, unnormalized_impl_sig);
debug!("compare_impl_method: impl_fty={:?}", impl_sig);
- let trait_sig = tcx.bound_fn_sig(trait_m.def_id).subst(tcx, trait_to_placeholder_substs);
+ let trait_sig = tcx.fn_sig(trait_m.def_id).subst(tcx, trait_to_placeholder_substs);
let trait_sig = tcx.liberate_late_bound_regions(impl_m.def_id, trait_sig);
// Next, add all inputs and output as well-formed tys. Importantly,
@@ -311,10 +307,10 @@ fn compare_method_predicate_entailment<'tcx>(
if !errors.is_empty() {
match check_implied_wf {
CheckImpliedWfMode::Check => {
+ let impl_m_hir_id = tcx.hir().local_def_id_to_hir_id(impl_m_def_id);
return compare_method_predicate_entailment(
tcx,
impl_m,
- impl_m_span,
trait_m,
impl_trait_ref,
CheckImpliedWfMode::Skip,
@@ -336,7 +332,7 @@ fn compare_method_predicate_entailment<'tcx>(
let outlives_env = OutlivesEnvironment::with_bounds(
param_env,
Some(infcx),
- infcx.implied_bounds_tys(param_env, impl_m_hir_id, wf_tys.clone()),
+ infcx.implied_bounds_tys(param_env, impl_m_def_id, wf_tys.clone()),
);
infcx.process_registered_region_obligations(
outlives_env.region_bound_pairs(),
@@ -346,12 +342,12 @@ fn compare_method_predicate_entailment<'tcx>(
if !errors.is_empty() {
// FIXME(compiler-errors): This can be simplified when IMPLIED_BOUNDS_ENTAILMENT
// becomes a hard error (i.e. ideally we'd just call `resolve_regions_and_report_errors`
+ let impl_m_hir_id = tcx.hir().local_def_id_to_hir_id(impl_m_def_id);
match check_implied_wf {
CheckImpliedWfMode::Check => {
return compare_method_predicate_entailment(
tcx,
impl_m,
- impl_m_span,
trait_m,
impl_trait_ref,
CheckImpliedWfMode::Skip,
@@ -371,7 +367,7 @@ fn compare_method_predicate_entailment<'tcx>(
}
CheckImpliedWfMode::Skip => {
if infcx.tainted_by_errors().is_none() {
- infcx.err_ctxt().report_region_errors(impl_m.def_id.expect_local(), &errors);
+ infcx.err_ctxt().report_region_errors(impl_m_def_id, &errors);
}
return Err(tcx
.sess
@@ -386,8 +382,8 @@ fn compare_method_predicate_entailment<'tcx>(
fn extract_bad_args_for_implies_lint<'tcx>(
tcx: TyCtxt<'tcx>,
errors: &[infer::RegionResolutionError<'tcx>],
- (trait_m, trait_sig): (&ty::AssocItem, ty::FnSig<'tcx>),
- (impl_m, impl_sig): (&ty::AssocItem, ty::FnSig<'tcx>),
+ (trait_m, trait_sig): (ty::AssocItem, ty::FnSig<'tcx>),
+ (impl_m, impl_sig): (ty::AssocItem, ty::FnSig<'tcx>),
hir_id: hir::HirId,
) -> Vec<(Span, Option<String>)> {
let mut blame_generics = vec![];
@@ -420,8 +416,8 @@ fn extract_bad_args_for_implies_lint<'tcx>(
// Map late-bound regions from trait to impl, so the names are right.
let mapping = std::iter::zip(
- tcx.fn_sig(trait_m.def_id).bound_vars(),
- tcx.fn_sig(impl_m.def_id).bound_vars(),
+ tcx.fn_sig(trait_m.def_id).skip_binder().bound_vars(),
+ tcx.fn_sig(impl_m.def_id).skip_binder().bound_vars(),
)
.filter_map(|(impl_bv, trait_bv)| {
if let ty::BoundVariableKind::Region(impl_bv) = impl_bv
@@ -462,21 +458,17 @@ struct RemapLateBound<'a, 'tcx> {
mapping: &'a FxHashMap<ty::BoundRegionKind, ty::BoundRegionKind>,
}
-impl<'tcx> TypeFolder<'tcx> for RemapLateBound<'_, 'tcx> {
- fn tcx(&self) -> TyCtxt<'tcx> {
+impl<'tcx> TypeFolder<TyCtxt<'tcx>> for RemapLateBound<'_, 'tcx> {
+ fn interner(&self) -> TyCtxt<'tcx> {
self.tcx
}
fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
if let ty::ReFree(fr) = *r {
- self.tcx.mk_region(ty::ReFree(ty::FreeRegion {
- bound_region: self
- .mapping
- .get(&fr.bound_region)
- .copied()
- .unwrap_or(fr.bound_region),
- ..fr
- }))
+ self.tcx.mk_re_free(
+ fr.scope,
+ self.mapping.get(&fr.bound_region).copied().unwrap_or(fr.bound_region),
+ )
} else {
r
}
@@ -485,7 +477,7 @@ impl<'tcx> TypeFolder<'tcx> for RemapLateBound<'_, 'tcx> {
fn emit_implied_wf_lint<'tcx>(
tcx: TyCtxt<'tcx>,
- impl_m: &ty::AssocItem,
+ impl_m: ty::AssocItem,
hir_id: hir::HirId,
bad_args: Vec<(Span, Option<String>)>,
) {
@@ -532,13 +524,11 @@ enum CheckImpliedWfMode {
fn compare_asyncness<'tcx>(
tcx: TyCtxt<'tcx>,
- impl_m: &ty::AssocItem,
- impl_m_span: Span,
- trait_m: &ty::AssocItem,
- trait_item_span: Option<Span>,
+ impl_m: ty::AssocItem,
+ trait_m: ty::AssocItem,
) -> Result<(), ErrorGuaranteed> {
if tcx.asyncness(trait_m.def_id) == hir::IsAsync::Async {
- match tcx.fn_sig(impl_m.def_id).skip_binder().output().kind() {
+ match tcx.fn_sig(impl_m.def_id).skip_binder().skip_binder().output().kind() {
ty::Alias(ty::Opaque, ..) => {
// allow both `async fn foo()` and `fn foo() -> impl Future`
}
@@ -547,9 +537,9 @@ fn compare_asyncness<'tcx>(
}
_ => {
return Err(tcx.sess.emit_err(crate::errors::AsyncTraitImplShouldBeAsync {
- span: impl_m_span,
+ span: tcx.def_span(impl_m.def_id),
method_name: trait_m.name,
- trait_item_span,
+ trait_item_span: tcx.hir().span_if_local(trait_m.def_id),
}));
}
};
@@ -604,19 +594,20 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>(
// First, check a few of the same things as `compare_impl_method`,
// just so we don't ICE during substitution later.
- compare_number_of_generics(tcx, impl_m, trait_m, tcx.hir().span_if_local(impl_m.def_id), true)?;
+ compare_number_of_generics(tcx, impl_m, trait_m, true)?;
compare_generic_param_kinds(tcx, impl_m, trait_m, true)?;
check_region_bounds_on_impl_item(tcx, impl_m, trait_m, true)?;
let trait_to_impl_substs = impl_trait_ref.substs;
- let impl_m_hir_id = tcx.hir().local_def_id_to_hir_id(impl_m.def_id.expect_local());
+ let impl_m_def_id = impl_m.def_id.expect_local();
+ let impl_m_hir_id = tcx.hir().local_def_id_to_hir_id(impl_m_def_id);
let return_span = tcx.hir().fn_decl_by_hir_id(impl_m_hir_id).unwrap().output.span();
let cause = ObligationCause::new(
return_span,
- impl_m_hir_id,
+ impl_m_def_id,
ObligationCauseCode::CompareImplItemObligation {
- impl_item_def_id: impl_m.def_id.expect_local(),
+ impl_item_def_id: impl_m_def_id,
trait_item_def_id: trait_m.def_id,
kind: impl_m.kind,
},
@@ -633,14 +624,14 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>(
let ocx = ObligationCtxt::new(infcx);
// Normalize the impl signature with fresh variables for lifetime inference.
- let norm_cause = ObligationCause::misc(return_span, impl_m_hir_id);
+ let norm_cause = ObligationCause::misc(return_span, impl_m_def_id);
let impl_sig = ocx.normalize(
&norm_cause,
param_env,
- infcx.replace_bound_vars_with_fresh_vars(
+ infcx.instantiate_binder_with_fresh_vars(
return_span,
infer::HigherRankedType,
- tcx.fn_sig(impl_m.def_id),
+ tcx.fn_sig(impl_m.def_id).subst_identity(),
),
);
impl_sig.error_reported()?;
@@ -650,13 +641,20 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>(
// the ImplTraitInTraitCollector, which gathers all of the RPITITs and replaces
// them with inference variables.
// We will use these inference variables to collect the hidden types of RPITITs.
- let mut collector = ImplTraitInTraitCollector::new(&ocx, return_span, param_env, impl_m_hir_id);
+ let mut collector = ImplTraitInTraitCollector::new(&ocx, return_span, param_env, impl_m_def_id);
let unnormalized_trait_sig = tcx
.liberate_late_bound_regions(
impl_m.def_id,
- tcx.bound_fn_sig(trait_m.def_id).subst(tcx, trait_to_placeholder_substs),
+ tcx.fn_sig(trait_m.def_id).subst(tcx, trait_to_placeholder_substs),
)
.fold_with(&mut collector);
+
+ debug_assert_ne!(
+ collector.types.len(),
+ 0,
+ "expect >1 RPITITs in call to `collect_return_position_impl_trait_in_trait_tys`"
+ );
+
let trait_sig = ocx.normalize(&norm_cause, param_env, unnormalized_trait_sig);
trait_sig.error_reported()?;
let trait_return_ty = trait_sig.output();
@@ -732,12 +730,11 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>(
let outlives_environment = OutlivesEnvironment::with_bounds(
param_env,
Some(infcx),
- infcx.implied_bounds_tys(param_env, impl_m_hir_id, wf_tys),
+ infcx.implied_bounds_tys(param_env, impl_m_def_id, wf_tys),
);
- infcx.err_ctxt().check_region_obligations_and_report_errors(
- impl_m.def_id.expect_local(),
- &outlives_environment,
- )?;
+ infcx
+ .err_ctxt()
+ .check_region_obligations_and_report_errors(impl_m_def_id, &outlives_environment)?;
let mut collected_tys = FxHashMap::default();
for (def_id, (ty, substs)) in collector.types {
@@ -784,19 +781,13 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>(
}
let Some(ty::ReEarlyBound(e)) = map.get(&region.into()).map(|r| r.expect_region().kind())
else {
- tcx
- .sess
- .delay_span_bug(
- return_span,
- "expected ReFree to map to ReEarlyBound"
- );
- return tcx.lifetimes.re_static;
+ return tcx.mk_re_error_with_message(return_span, "expected ReFree to map to ReEarlyBound")
};
- tcx.mk_region(ty::ReEarlyBound(ty::EarlyBoundRegion {
+ tcx.mk_re_early_bound(ty::EarlyBoundRegion {
def_id: e.def_id,
name: e.name,
index: (e.index as usize - num_trait_substs + num_impl_substs) as u32,
- }))
+ })
});
debug!(%ty);
collected_tys.insert(def_id, ty);
@@ -806,7 +797,7 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>(
return_span,
format!("could not fully resolve: {ty} => {err:?}"),
);
- collected_tys.insert(def_id, tcx.ty_error_with_guaranteed(reported));
+ collected_tys.insert(def_id, tcx.ty_error(reported));
}
}
}
@@ -819,7 +810,7 @@ struct ImplTraitInTraitCollector<'a, 'tcx> {
types: FxHashMap<DefId, (Ty<'tcx>, ty::SubstsRef<'tcx>)>,
span: Span,
param_env: ty::ParamEnv<'tcx>,
- body_id: hir::HirId,
+ body_id: LocalDefId,
}
impl<'a, 'tcx> ImplTraitInTraitCollector<'a, 'tcx> {
@@ -827,20 +818,20 @@ impl<'a, 'tcx> ImplTraitInTraitCollector<'a, 'tcx> {
ocx: &'a ObligationCtxt<'a, 'tcx>,
span: Span,
param_env: ty::ParamEnv<'tcx>,
- body_id: hir::HirId,
+ body_id: LocalDefId,
) -> Self {
ImplTraitInTraitCollector { ocx, types: FxHashMap::default(), span, param_env, body_id }
}
}
-impl<'tcx> TypeFolder<'tcx> for ImplTraitInTraitCollector<'_, 'tcx> {
- fn tcx<'a>(&'a self) -> TyCtxt<'tcx> {
+impl<'tcx> TypeFolder<TyCtxt<'tcx>> for ImplTraitInTraitCollector<'_, 'tcx> {
+ fn interner(&self) -> TyCtxt<'tcx> {
self.ocx.infcx.tcx
}
fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
if let ty::Alias(ty::Projection, proj) = ty.kind()
- && self.tcx().def_kind(proj.def_id) == DefKind::ImplTraitPlaceholder
+ && self.interner().def_kind(proj.def_id) == DefKind::ImplTraitPlaceholder
{
if let Some((ty, _)) = self.types.get(&proj.def_id) {
return *ty;
@@ -856,7 +847,7 @@ impl<'tcx> TypeFolder<'tcx> for ImplTraitInTraitCollector<'_, 'tcx> {
});
self.types.insert(proj.def_id, (infer_ty, proj.substs));
// Recurse into bounds
- for (pred, pred_span) in self.tcx().bound_explicit_item_bounds(proj.def_id).subst_iter_copied(self.tcx(), proj.substs) {
+ for (pred, pred_span) in self.interner().bound_explicit_item_bounds(proj.def_id).subst_iter_copied(self.interner(), proj.substs) {
let pred = pred.fold_with(self);
let pred = self.ocx.normalize(
&ObligationCause::misc(self.span, self.body_id),
@@ -865,7 +856,7 @@ impl<'tcx> TypeFolder<'tcx> for ImplTraitInTraitCollector<'_, 'tcx> {
);
self.ocx.register_obligation(traits::Obligation::new(
- self.tcx(),
+ self.interner(),
ObligationCause::new(
self.span,
self.body_id,
@@ -886,8 +877,8 @@ fn report_trait_method_mismatch<'tcx>(
infcx: &InferCtxt<'tcx>,
mut cause: ObligationCause<'tcx>,
terr: TypeError<'tcx>,
- (trait_m, trait_sig): (&ty::AssocItem, ty::FnSig<'tcx>),
- (impl_m, impl_sig): (&ty::AssocItem, ty::FnSig<'tcx>),
+ (trait_m, trait_sig): (ty::AssocItem, ty::FnSig<'tcx>),
+ (impl_m, impl_sig): (ty::AssocItem, ty::FnSig<'tcx>),
impl_trait_ref: ty::TraitRef<'tcx>,
) -> ErrorGuaranteed {
let tcx = infcx.tcx;
@@ -916,7 +907,7 @@ fn report_trait_method_mismatch<'tcx>(
// When the `impl` receiver is an arbitrary self type, like `self: Box<Self>`, the
// span points only at the type `Box<Self`>, but we want to cover the whole
// argument pattern and type.
- let ImplItemKind::Fn(ref sig, body) = tcx.hir().expect_impl_item(impl_m.def_id.expect_local()).kind else { bug!("{impl_m:?} is not a method") };
+ let (sig, body) = tcx.hir().expect_impl_item(impl_m.def_id.expect_local()).expect_fn();
let span = tcx
.hir()
.body_param_names(body)
@@ -980,8 +971,8 @@ fn report_trait_method_mismatch<'tcx>(
fn check_region_bounds_on_impl_item<'tcx>(
tcx: TyCtxt<'tcx>,
- impl_m: &ty::AssocItem,
- trait_m: &ty::AssocItem,
+ impl_m: ty::AssocItem,
+ trait_m: ty::AssocItem,
delay: bool,
) -> Result<(), ErrorGuaranteed> {
let impl_generics = tcx.generics_of(impl_m.def_id);
@@ -1055,7 +1046,7 @@ fn check_region_bounds_on_impl_item<'tcx>(
.sess
.create_err(LifetimesOrBoundsMismatchOnTrait {
span,
- item_kind: assoc_item_kind_str(impl_m),
+ item_kind: assoc_item_kind_str(&impl_m),
ident: impl_m.ident(tcx),
generics_span,
bounds_span,
@@ -1073,17 +1064,17 @@ fn extract_spans_for_error_reporting<'tcx>(
infcx: &infer::InferCtxt<'tcx>,
terr: TypeError<'_>,
cause: &ObligationCause<'tcx>,
- impl_m: &ty::AssocItem,
- trait_m: &ty::AssocItem,
+ impl_m: ty::AssocItem,
+ trait_m: ty::AssocItem,
) -> (Span, Option<Span>) {
let tcx = infcx.tcx;
let mut impl_args = {
- let ImplItemKind::Fn(sig, _) = &tcx.hir().expect_impl_item(impl_m.def_id.expect_local()).kind else { bug!("{:?} is not a method", impl_m) };
+ let (sig, _) = tcx.hir().expect_impl_item(impl_m.def_id.expect_local()).expect_fn();
sig.decl.inputs.iter().map(|t| t.span).chain(iter::once(sig.decl.output.span()))
};
let trait_args = trait_m.def_id.as_local().map(|def_id| {
- let TraitItemKind::Fn(sig, _) = &tcx.hir().expect_trait_item(def_id).kind else { bug!("{:?} is not a TraitItemKind::Fn", trait_m) };
+ let (sig, _) = tcx.hir().expect_trait_item(def_id).expect_fn();
sig.decl.inputs.iter().map(|t| t.span).chain(iter::once(sig.decl.output.span()))
});
@@ -1097,9 +1088,8 @@ fn extract_spans_for_error_reporting<'tcx>(
fn compare_self_type<'tcx>(
tcx: TyCtxt<'tcx>,
- impl_m: &ty::AssocItem,
- impl_m_span: Span,
- trait_m: &ty::AssocItem,
+ impl_m: ty::AssocItem,
+ trait_m: ty::AssocItem,
impl_trait_ref: ty::TraitRef<'tcx>,
) -> Result<(), ErrorGuaranteed> {
// Try to give more informative error messages about self typing
@@ -1110,17 +1100,17 @@ fn compare_self_type<'tcx>(
// inscrutable, particularly for cases where one method has no
// self.
- let self_string = |method: &ty::AssocItem| {
+ let self_string = |method: ty::AssocItem| {
let untransformed_self_ty = match method.container {
ty::ImplContainer => impl_trait_ref.self_ty(),
ty::TraitContainer => tcx.types.self_param,
};
- let self_arg_ty = tcx.fn_sig(method.def_id).input(0);
+ let self_arg_ty = tcx.fn_sig(method.def_id).subst_identity().input(0);
let param_env = ty::ParamEnv::reveal_all();
let infcx = tcx.infer_ctxt().build();
let self_arg_ty = tcx.liberate_late_bound_regions(method.def_id, self_arg_ty);
- let can_eq_self = |ty| infcx.can_eq(param_env, untransformed_self_ty, ty).is_ok();
+ let can_eq_self = |ty| infcx.can_eq(param_env, untransformed_self_ty, ty);
match ExplicitSelf::determine(self_arg_ty, can_eq_self) {
ExplicitSelf::ByValue => "self".to_owned(),
ExplicitSelf::ByReference(_, hir::Mutability::Not) => "&self".to_owned(),
@@ -1134,6 +1124,7 @@ fn compare_self_type<'tcx>(
(false, true) => {
let self_descr = self_string(impl_m);
+ let impl_m_span = tcx.def_span(impl_m.def_id);
let mut err = struct_span_err!(
tcx.sess,
impl_m_span,
@@ -1153,6 +1144,7 @@ fn compare_self_type<'tcx>(
(true, false) => {
let self_descr = self_string(trait_m);
+ let impl_m_span = tcx.def_span(impl_m.def_id);
let mut err = struct_span_err!(
tcx.sess,
impl_m_span,
@@ -1198,9 +1190,8 @@ fn compare_self_type<'tcx>(
/// [`compare_generic_param_kinds`]. This function also does not handle lifetime parameters
fn compare_number_of_generics<'tcx>(
tcx: TyCtxt<'tcx>,
- impl_: &ty::AssocItem,
- trait_: &ty::AssocItem,
- trait_span: Option<Span>,
+ impl_: ty::AssocItem,
+ trait_: ty::AssocItem,
delay: bool,
) -> Result<(), ErrorGuaranteed> {
let trait_own_counts = tcx.generics_of(trait_.def_id).own_counts();
@@ -1220,7 +1211,7 @@ fn compare_number_of_generics<'tcx>(
("const", trait_own_counts.consts, impl_own_counts.consts),
];
- let item_kind = assoc_item_kind_str(impl_);
+ let item_kind = assoc_item_kind_str(&impl_);
let mut err_occurred = None;
for (kind, trait_count, impl_count) in matchings {
@@ -1260,6 +1251,7 @@ fn compare_number_of_generics<'tcx>(
.collect();
(Some(arg_spans), impl_trait_spans)
} else {
+ let trait_span = tcx.hir().span_if_local(trait_.def_id);
(trait_span.map(|s| vec![s]), vec![])
};
@@ -1341,22 +1333,20 @@ fn compare_number_of_generics<'tcx>(
fn compare_number_of_method_arguments<'tcx>(
tcx: TyCtxt<'tcx>,
- impl_m: &ty::AssocItem,
- impl_m_span: Span,
- trait_m: &ty::AssocItem,
- trait_item_span: Option<Span>,
+ impl_m: ty::AssocItem,
+ trait_m: ty::AssocItem,
) -> Result<(), ErrorGuaranteed> {
let impl_m_fty = tcx.fn_sig(impl_m.def_id);
let trait_m_fty = tcx.fn_sig(trait_m.def_id);
- let trait_number_args = trait_m_fty.inputs().skip_binder().len();
- let impl_number_args = impl_m_fty.inputs().skip_binder().len();
+ let trait_number_args = trait_m_fty.skip_binder().inputs().skip_binder().len();
+ let impl_number_args = impl_m_fty.skip_binder().inputs().skip_binder().len();
if trait_number_args != impl_number_args {
let trait_span = trait_m
.def_id
.as_local()
.and_then(|def_id| {
- let TraitItemKind::Fn(trait_m_sig, _) = &tcx.hir().expect_trait_item(def_id).kind else { bug!("{:?} is not a method", impl_m) };
+ let (trait_m_sig, _) = &tcx.hir().expect_trait_item(def_id).expect_fn();
let pos = trait_number_args.saturating_sub(1);
trait_m_sig.decl.inputs.get(pos).map(|arg| {
if pos == 0 {
@@ -1366,9 +1356,9 @@ fn compare_number_of_method_arguments<'tcx>(
}
})
})
- .or(trait_item_span);
+ .or_else(|| tcx.hir().span_if_local(trait_m.def_id));
- let ImplItemKind::Fn(impl_m_sig, _) = &tcx.hir().expect_impl_item(impl_m.def_id.expect_local()).kind else { bug!("{:?} is not a method", impl_m) };
+ let (impl_m_sig, _) = &tcx.hir().expect_impl_item(impl_m.def_id.expect_local()).expect_fn();
let pos = impl_number_args.saturating_sub(1);
let impl_span = impl_m_sig
.decl
@@ -1381,7 +1371,7 @@ fn compare_number_of_method_arguments<'tcx>(
arg.span.with_lo(impl_m_sig.decl.inputs[0].span.lo())
}
})
- .unwrap_or(impl_m_span);
+ .unwrap_or_else(|| tcx.def_span(impl_m.def_id));
let mut err = struct_span_err!(
tcx.sess,
@@ -1423,8 +1413,8 @@ fn compare_number_of_method_arguments<'tcx>(
fn compare_synthetic_generics<'tcx>(
tcx: TyCtxt<'tcx>,
- impl_m: &ty::AssocItem,
- trait_m: &ty::AssocItem,
+ impl_m: ty::AssocItem,
+ trait_m: ty::AssocItem,
) -> Result<(), ErrorGuaranteed> {
// FIXME(chrisvittal) Clean up this function, list of FIXME items:
// 1. Better messages for the span labels
@@ -1504,7 +1494,7 @@ fn compare_synthetic_generics<'tcx>(
let _: Option<_> = try {
let impl_m = impl_m.def_id.as_local()?;
let impl_m = tcx.hir().expect_impl_item(impl_m);
- let hir::ImplItemKind::Fn(sig, _) = &impl_m.kind else { unreachable!() };
+ let (sig, _) = impl_m.expect_fn();
let input_tys = sig.decl.inputs;
struct Visitor(Option<Span>, hir::def_id::LocalDefId);
@@ -1577,8 +1567,8 @@ fn compare_synthetic_generics<'tcx>(
/// This function does not handle lifetime parameters
fn compare_generic_param_kinds<'tcx>(
tcx: TyCtxt<'tcx>,
- impl_item: &ty::AssocItem,
- trait_item: &ty::AssocItem,
+ impl_item: ty::AssocItem,
+ trait_item: ty::AssocItem,
delay: bool,
) -> Result<(), ErrorGuaranteed> {
assert_eq!(impl_item.kind, trait_item.kind);
@@ -1623,7 +1613,11 @@ fn compare_generic_param_kinds<'tcx>(
let make_param_message = |prefix: &str, param: &ty::GenericParamDef| match param.kind {
Const { .. } => {
- format!("{} const parameter of type `{}`", prefix, tcx.type_of(param.def_id))
+ format!(
+ "{} const parameter of type `{}`",
+ prefix,
+ tcx.type_of(param.def_id).subst_identity()
+ )
}
Type { .. } => format!("{} type parameter", prefix),
Lifetime { .. } => unreachable!(),
@@ -1671,14 +1665,12 @@ pub(super) fn compare_impl_const_raw(
// Create a parameter environment that represents the implementation's
// method.
- let impl_c_hir_id = tcx.hir().local_def_id_to_hir_id(impl_const_item_def);
-
// Compute placeholder form of impl and trait const tys.
- let impl_ty = tcx.type_of(impl_const_item_def.to_def_id());
- let trait_ty = tcx.bound_type_of(trait_const_item_def).subst(tcx, trait_to_impl_substs);
+ let impl_ty = tcx.type_of(impl_const_item_def.to_def_id()).subst_identity();
+ let trait_ty = tcx.type_of(trait_const_item_def).subst(tcx, trait_to_impl_substs);
let mut cause = ObligationCause::new(
impl_c_span,
- impl_c_hir_id,
+ impl_const_item_def,
ObligationCauseCode::CompareImplItemObligation {
impl_item_def_id: impl_const_item_def,
trait_item_def_id: trait_const_item_def,
@@ -1704,7 +1696,7 @@ pub(super) fn compare_impl_const_raw(
);
// Locate the Span containing just the type of the offending impl
- let ImplItemKind::Const(ty, _) = tcx.hir().expect_impl_item(impl_const_item_def).kind else { bug!("{impl_const_item:?} is not a impl const") };
+ let (ty, _) = tcx.hir().expect_impl_item(impl_const_item_def).expect_const();
cause.span = ty.span;
let mut diag = struct_span_err!(
@@ -1717,7 +1709,7 @@ pub(super) fn compare_impl_const_raw(
let trait_c_span = trait_const_item_def.as_local().map(|trait_c_def_id| {
// Add a label to the Span containing just the type of the const
- let TraitItemKind::Const(ty, _) = tcx.hir().expect_trait_item(trait_c_def_id).kind else { bug!("{trait_const_item:?} is not a trait const") };
+ let (ty, _) = tcx.hir().expect_trait_item(trait_c_def_id).expect_const();
ty.span
});
@@ -1752,23 +1744,17 @@ pub(super) fn compare_impl_const_raw(
pub(super) fn compare_impl_ty<'tcx>(
tcx: TyCtxt<'tcx>,
- impl_ty: &ty::AssocItem,
- impl_ty_span: Span,
- trait_ty: &ty::AssocItem,
+ impl_ty: ty::AssocItem,
+ trait_ty: ty::AssocItem,
impl_trait_ref: ty::TraitRef<'tcx>,
- trait_item_span: Option<Span>,
) {
debug!("compare_impl_type(impl_trait_ref={:?})", impl_trait_ref);
let _: Result<(), ErrorGuaranteed> = try {
- compare_number_of_generics(tcx, impl_ty, trait_ty, trait_item_span, false)?;
-
+ compare_number_of_generics(tcx, impl_ty, trait_ty, false)?;
compare_generic_param_kinds(tcx, impl_ty, trait_ty, false)?;
-
- let sp = tcx.def_span(impl_ty.def_id);
- compare_type_predicate_entailment(tcx, impl_ty, sp, trait_ty, impl_trait_ref)?;
-
- check_type_bounds(tcx, trait_ty, impl_ty, impl_ty_span, impl_trait_ref)?;
+ compare_type_predicate_entailment(tcx, impl_ty, trait_ty, impl_trait_ref)?;
+ check_type_bounds(tcx, trait_ty, impl_ty, impl_trait_ref)?;
};
}
@@ -1776,9 +1762,8 @@ pub(super) fn compare_impl_ty<'tcx>(
/// instead of associated functions.
fn compare_type_predicate_entailment<'tcx>(
tcx: TyCtxt<'tcx>,
- impl_ty: &ty::AssocItem,
- impl_ty_span: Span,
- trait_ty: &ty::AssocItem,
+ impl_ty: ty::AssocItem,
+ trait_ty: ty::AssocItem,
impl_trait_ref: ty::TraitRef<'tcx>,
) -> Result<(), ErrorGuaranteed> {
let impl_substs = InternalSubsts::identity_for_item(tcx, impl_ty.def_id);
@@ -1799,7 +1784,7 @@ fn compare_type_predicate_entailment<'tcx>(
// This `HirId` should be used for the `body_id` field on each
// `ObligationCause` (and the `FnCtxt`). This is what
// `regionck_item` expects.
- let impl_ty_hir_id = tcx.hir().local_def_id_to_hir_id(impl_ty.def_id.expect_local());
+ let impl_ty_def_id = impl_ty.def_id.expect_local();
debug!("compare_type_predicate_entailment: trait_to_impl_substs={:?}", trait_to_impl_substs);
// The predicates declared by the impl definition, the trait and the
@@ -1814,9 +1799,10 @@ fn compare_type_predicate_entailment<'tcx>(
debug!("compare_type_predicate_entailment: bounds={:?}", hybrid_preds);
- let normalize_cause = traits::ObligationCause::misc(impl_ty_span, impl_ty_hir_id);
+ let impl_ty_span = tcx.def_span(impl_ty_def_id);
+ let normalize_cause = traits::ObligationCause::misc(impl_ty_span, impl_ty_def_id);
let param_env = ty::ParamEnv::new(
- tcx.intern_predicates(&hybrid_preds.predicates),
+ tcx.mk_predicates(&hybrid_preds.predicates),
Reveal::UserFacing,
hir::Constness::NotConst,
);
@@ -1827,12 +1813,12 @@ fn compare_type_predicate_entailment<'tcx>(
debug!("compare_type_predicate_entailment: caller_bounds={:?}", param_env.caller_bounds());
for (predicate, span) in impl_ty_own_bounds {
- let cause = ObligationCause::misc(span, impl_ty_hir_id);
+ let cause = ObligationCause::misc(span, impl_ty_def_id);
let predicate = ocx.normalize(&cause, param_env, predicate);
let cause = ObligationCause::new(
span,
- impl_ty_hir_id,
+ impl_ty_def_id,
ObligationCauseCode::CompareImplItemObligation {
impl_item_def_id: impl_ty.def_id.expect_local(),
trait_item_def_id: trait_ty.def_id,
@@ -1877,9 +1863,8 @@ fn compare_type_predicate_entailment<'tcx>(
#[instrument(level = "debug", skip(tcx))]
pub(super) fn check_type_bounds<'tcx>(
tcx: TyCtxt<'tcx>,
- trait_ty: &ty::AssocItem,
- impl_ty: &ty::AssocItem,
- impl_ty_span: Span,
+ trait_ty: ty::AssocItem,
+ impl_ty: ty::AssocItem,
impl_trait_ref: ty::TraitRef<'tcx>,
) -> Result<(), ErrorGuaranteed> {
// Given
@@ -1888,7 +1873,7 @@ pub(super) fn check_type_bounds<'tcx>(
// type Bar<C> =...
// }
//
- // - `impl_trait_ref` would be `<(A, B) as Foo<u32>>
+ // - `impl_trait_ref` would be `<(A, B) as Foo<u32>>`
// - `impl_ty_substs` would be `[A, B, ^0.0]` (`^0.0` here is the bound var with db 0 and index 0)
// - `rebased_substs` would be `[(A, B), u32, ^0.0]`, combining the substs from
// the *trait* with the generic associated type parameters (as bound vars).
@@ -1930,23 +1915,23 @@ pub(super) fn check_type_bounds<'tcx>(
smallvec::SmallVec::with_capacity(defs.count());
InternalSubsts::fill_single(&mut substs, defs, &mut |param, _| match param.kind {
GenericParamDefKind::Type { .. } => {
- let kind = ty::BoundTyKind::Param(param.name);
+ let kind = ty::BoundTyKind::Param(param.def_id, param.name);
let bound_var = ty::BoundVariableKind::Ty(kind);
bound_vars.push(bound_var);
- tcx.mk_ty(ty::Bound(
+ tcx.mk_bound(
ty::INNERMOST,
ty::BoundTy { var: ty::BoundVar::from_usize(bound_vars.len() - 1), kind },
- ))
+ )
.into()
}
GenericParamDefKind::Lifetime => {
let kind = ty::BoundRegionKind::BrNamed(param.def_id, param.name);
let bound_var = ty::BoundVariableKind::Region(kind);
bound_vars.push(bound_var);
- tcx.mk_region(ty::ReLateBound(
+ tcx.mk_re_late_bound(
ty::INNERMOST,
ty::BoundRegion { var: ty::BoundVar::from_usize(bound_vars.len() - 1), kind },
- ))
+ )
.into()
}
GenericParamDefKind::Const { .. } => {
@@ -1954,17 +1939,17 @@ pub(super) fn check_type_bounds<'tcx>(
bound_vars.push(bound_var);
tcx.mk_const(
ty::ConstKind::Bound(ty::INNERMOST, ty::BoundVar::from_usize(bound_vars.len() - 1)),
- tcx.type_of(param.def_id),
+ tcx.type_of(param.def_id).subst_identity(),
)
.into()
}
});
- let bound_vars = tcx.mk_bound_variable_kinds(bound_vars.into_iter());
- let impl_ty_substs = tcx.intern_substs(&substs);
+ let bound_vars = tcx.mk_bound_variable_kinds(&bound_vars);
+ let impl_ty_substs = tcx.mk_substs(&substs);
let container_id = impl_ty.container_id(tcx);
let rebased_substs = impl_ty_substs.rebase_onto(tcx, container_id, impl_trait_ref.substs);
- let impl_ty_value = tcx.type_of(impl_ty.def_id);
+ let impl_ty_value = tcx.type_of(impl_ty.def_id).subst_identity();
let param_env = tcx.param_env(impl_ty.def_id);
@@ -2000,27 +1985,30 @@ pub(super) fn check_type_bounds<'tcx>(
.to_predicate(tcx),
),
};
- ty::ParamEnv::new(
- tcx.intern_predicates(&predicates),
- Reveal::UserFacing,
- param_env.constness(),
- )
+ ty::ParamEnv::new(tcx.mk_predicates(&predicates), Reveal::UserFacing, param_env.constness())
};
debug!(?normalize_param_env);
- let impl_ty_hir_id = tcx.hir().local_def_id_to_hir_id(impl_ty.def_id.expect_local());
+ let impl_ty_def_id = impl_ty.def_id.expect_local();
let impl_ty_substs = InternalSubsts::identity_for_item(tcx, impl_ty.def_id);
let rebased_substs = impl_ty_substs.rebase_onto(tcx, container_id, impl_trait_ref.substs);
let infcx = tcx.infer_ctxt().build();
let ocx = ObligationCtxt::new(&infcx);
- let assumed_wf_types =
- ocx.assumed_wf_types(param_env, impl_ty_span, impl_ty.def_id.expect_local());
+ let impl_ty_span = match tcx.hir().get_by_def_id(impl_ty_def_id) {
+ hir::Node::TraitItem(hir::TraitItem {
+ kind: hir::TraitItemKind::Type(_, Some(ty)),
+ ..
+ }) => ty.span,
+ hir::Node::ImplItem(hir::ImplItem { kind: hir::ImplItemKind::Type(ty), .. }) => ty.span,
+ _ => bug!(),
+ };
+ let assumed_wf_types = ocx.assumed_wf_types(param_env, impl_ty_span, impl_ty_def_id);
let normalize_cause = ObligationCause::new(
impl_ty_span,
- impl_ty_hir_id,
+ impl_ty_def_id,
ObligationCauseCode::CheckAssociatedTypeBounds {
impl_item_def_id: impl_ty.def_id.expect_local(),
trait_item_def_id: trait_ty.def_id,
@@ -2032,7 +2020,7 @@ pub(super) fn check_type_bounds<'tcx>(
} else {
traits::BindingObligation(trait_ty.def_id, span)
};
- ObligationCause::new(impl_ty_span, impl_ty_hir_id, code)
+ ObligationCause::new(impl_ty_span, impl_ty_def_id, code)
};
let obligations = tcx
@@ -2063,7 +2051,7 @@ pub(super) fn check_type_bounds<'tcx>(
// Finally, resolve all regions. This catches wily misuses of
// lifetime parameters.
- let implied_bounds = infcx.implied_bounds_tys(param_env, impl_ty_hir_id, assumed_wf_types);
+ let implied_bounds = infcx.implied_bounds_tys(param_env, impl_ty_def_id, assumed_wf_types);
let outlives_environment =
OutlivesEnvironment::with_bounds(param_env, Some(&infcx), implied_bounds);
diff --git a/compiler/rustc_hir_analysis/src/check/dropck.rs b/compiler/rustc_hir_analysis/src/check/dropck.rs
index 64fd61c13..2bb724138 100644
--- a/compiler/rustc_hir_analysis/src/check/dropck.rs
+++ b/compiler/rustc_hir_analysis/src/check/dropck.rs
@@ -27,7 +27,7 @@ use rustc_middle::ty::{self, Predicate, Ty, TyCtxt};
/// cannot do `struct S<T>; impl<T:Clone> Drop for S<T> { ... }`).
///
pub fn check_drop_impl(tcx: TyCtxt<'_>, drop_impl_did: DefId) -> Result<(), ErrorGuaranteed> {
- let dtor_self_type = tcx.type_of(drop_impl_did);
+ let dtor_self_type = tcx.type_of(drop_impl_did).subst_identity();
let dtor_predicates = tcx.predicates_of(drop_impl_did);
match dtor_self_type.kind() {
ty::Adt(adt_def, self_to_impl_substs) => {
@@ -71,7 +71,7 @@ fn ensure_drop_params_and_item_params_correspond<'tcx>(
let drop_impl_span = tcx.def_span(drop_impl_did);
let item_span = tcx.def_span(self_type_did);
- let self_descr = tcx.def_kind(self_type_did).descr(self_type_did);
+ let self_descr = tcx.def_descr(self_type_did);
let mut err =
struct_span_err!(tcx.sess, drop_impl_span, E0366, "`Drop` impls cannot be specialized");
match arg {
@@ -217,7 +217,7 @@ fn ensure_drop_predicates_are_implied_by_item_defn<'tcx>(
if !assumptions_in_impl_context.iter().copied().any(predicate_matches_closure) {
let item_span = tcx.def_span(self_type_did);
- let self_descr = tcx.def_kind(self_type_did).descr(self_type_did.to_def_id());
+ let self_descr = tcx.def_descr(self_type_did.to_def_id());
let reported = struct_span_err!(
tcx.sess,
predicate_sp,
diff --git a/compiler/rustc_hir_analysis/src/check/intrinsic.rs b/compiler/rustc_hir_analysis/src/check/intrinsic.rs
index 598dc2dca..054284cce 100644
--- a/compiler/rustc_hir_analysis/src/check/intrinsic.rs
+++ b/compiler/rustc_hir_analysis/src/check/intrinsic.rs
@@ -15,8 +15,6 @@ use rustc_middle::ty::{self, TyCtxt};
use rustc_span::symbol::{kw, sym, Symbol};
use rustc_target::spec::abi::Abi;
-use std::iter;
-
fn equate_intrinsic_type<'tcx>(
tcx: TyCtxt<'tcx>,
it: &hir::ForeignItem<'_>,
@@ -56,8 +54,14 @@ fn equate_intrinsic_type<'tcx>(
&& gen_count_ok(own_counts.consts, 0, "const")
{
let fty = tcx.mk_fn_ptr(sig);
- let cause = ObligationCause::new(it.span, it.hir_id(), ObligationCauseCode::IntrinsicType);
- require_same_types(tcx, &cause, tcx.mk_fn_ptr(tcx.fn_sig(it.owner_id)), fty);
+ let it_def_id = it.owner_id.def_id;
+ let cause = ObligationCause::new(it.span, it_def_id, ObligationCauseCode::IntrinsicType);
+ require_same_types(
+ tcx,
+ &cause,
+ tcx.mk_fn_ptr(tcx.fn_sig(it.owner_id).subst_identity()),
+ fty,
+ );
}
}
@@ -133,25 +137,21 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) {
let intrinsic_name = tcx.item_name(intrinsic_id);
let name_str = intrinsic_name.as_str();
- let bound_vars = tcx.mk_bound_variable_kinds(
- [
- ty::BoundVariableKind::Region(ty::BrAnon(0, None)),
- ty::BoundVariableKind::Region(ty::BrEnv),
- ]
- .iter()
- .copied(),
- );
+ let bound_vars = tcx.mk_bound_variable_kinds(&[
+ ty::BoundVariableKind::Region(ty::BrAnon(0, None)),
+ ty::BoundVariableKind::Region(ty::BrEnv),
+ ]);
let mk_va_list_ty = |mutbl| {
tcx.lang_items().va_list().map(|did| {
- let region = tcx.mk_region(ty::ReLateBound(
+ let region = tcx.mk_re_late_bound(
ty::INNERMOST,
ty::BoundRegion { var: ty::BoundVar::from_u32(0), kind: ty::BrAnon(0, None) },
- ));
- let env_region = tcx.mk_region(ty::ReLateBound(
+ );
+ let env_region = tcx.mk_re_late_bound(
ty::INNERMOST,
ty::BoundRegion { var: ty::BoundVar::from_u32(1), kind: ty::BrEnv },
- ));
- let va_list_ty = tcx.bound_type_of(did).subst(tcx, &[region.into()]);
+ );
+ let va_list_ty = tcx.type_of(did).subst(tcx, &[region.into()]);
(tcx.mk_ref(env_region, ty::TypeAndMut { ty: va_list_ty, mutbl }), va_list_ty)
})
};
@@ -165,7 +165,7 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) {
"cxchg" | "cxchgweak" => (
1,
vec![tcx.mk_mut_ptr(param(0)), param(0), param(0)],
- tcx.intern_tup(&[param(0), tcx.types.bool]),
+ tcx.mk_tup(&[param(0), tcx.types.bool]),
),
"load" => (1, vec![tcx.mk_imm_ptr(param(0))], param(0)),
"store" => (1, vec![tcx.mk_mut_ptr(param(0)), param(0)], tcx.mk_unit()),
@@ -317,7 +317,7 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) {
| sym::bitreverse => (1, vec![param(0)], param(0)),
sym::add_with_overflow | sym::sub_with_overflow | sym::mul_with_overflow => {
- (1, vec![param(0), param(0)], tcx.intern_tup(&[param(0), tcx.types.bool]))
+ (1, vec![param(0), param(0)], tcx.mk_tup(&[param(0), tcx.types.bool]))
}
sym::ptr_guaranteed_cmp => {
@@ -371,24 +371,22 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) {
ty::BoundRegion { var: ty::BoundVar::from_u32(0), kind: ty::BrAnon(0, None) };
(
1,
- vec![
- tcx.mk_imm_ref(tcx.mk_region(ty::ReLateBound(ty::INNERMOST, br)), param(0)),
- ],
- tcx.mk_projection(discriminant_def_id, tcx.mk_substs([param(0).into()].iter())),
+ vec![tcx.mk_imm_ref(tcx.mk_re_late_bound(ty::INNERMOST, br), param(0))],
+ tcx.mk_projection(discriminant_def_id, tcx.mk_substs(&[param(0).into()])),
)
}
kw::Try => {
let mut_u8 = tcx.mk_mut_ptr(tcx.types.u8);
let try_fn_ty = ty::Binder::dummy(tcx.mk_fn_sig(
- iter::once(mut_u8),
+ [mut_u8],
tcx.mk_unit(),
false,
hir::Unsafety::Normal,
Abi::Rust,
));
let catch_fn_ty = ty::Binder::dummy(tcx.mk_fn_sig(
- [mut_u8, mut_u8].iter().cloned(),
+ [mut_u8, mut_u8],
tcx.mk_unit(),
false,
hir::Unsafety::Normal,
@@ -424,8 +422,7 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) {
sym::raw_eq => {
let br =
ty::BoundRegion { var: ty::BoundVar::from_u32(0), kind: ty::BrAnon(0, None) };
- let param_ty =
- tcx.mk_imm_ref(tcx.mk_region(ty::ReLateBound(ty::INNERMOST, br)), param(0));
+ let param_ty = tcx.mk_imm_ref(tcx.mk_re_late_bound(ty::INNERMOST, br), param(0));
(1, vec![param_ty; 2], tcx.types.bool)
}
@@ -444,7 +441,7 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) {
};
(n_tps, 0, inputs, output, unsafety)
};
- let sig = tcx.mk_fn_sig(inputs.into_iter(), output, false, unsafety, Abi::RustIntrinsic);
+ let sig = tcx.mk_fn_sig(inputs, output, false, unsafety, Abi::RustIntrinsic);
let sig = ty::Binder::bind_with_vars(sig, bound_vars);
equate_intrinsic_type(tcx, it, n_tps, n_lts, sig)
}
@@ -542,13 +539,7 @@ pub fn check_platform_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>)
}
};
- let sig = tcx.mk_fn_sig(
- inputs.into_iter(),
- output,
- false,
- hir::Unsafety::Unsafe,
- Abi::PlatformIntrinsic,
- );
+ let sig = tcx.mk_fn_sig(inputs, output, false, hir::Unsafety::Unsafe, Abi::PlatformIntrinsic);
let sig = ty::Binder::dummy(sig);
equate_intrinsic_type(tcx, it, n_tps, 0, sig)
}
diff --git a/compiler/rustc_hir_analysis/src/check/intrinsicck.rs b/compiler/rustc_hir_analysis/src/check/intrinsicck.rs
index 82030d82f..b1d5a27be 100644
--- a/compiler/rustc_hir_analysis/src/check/intrinsicck.rs
+++ b/compiler/rustc_hir_analysis/src/check/intrinsicck.rs
@@ -1,8 +1,9 @@
use rustc_ast::InlineAsmTemplatePiece;
use rustc_data_structures::fx::FxHashSet;
use rustc_hir as hir;
-use rustc_middle::ty::{self, Article, FloatTy, IntTy, Ty, TyCtxt, TypeVisitable, UintTy};
+use rustc_middle::ty::{self, Article, FloatTy, IntTy, Ty, TyCtxt, TypeVisitableExt, UintTy};
use rustc_session::lint;
+use rustc_span::def_id::LocalDefId;
use rustc_span::{Symbol, DUMMY_SP};
use rustc_target::asm::{InlineAsmReg, InlineAsmRegClass, InlineAsmRegOrRegClass, InlineAsmType};
@@ -253,10 +254,8 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
Some(asm_ty)
}
- pub fn check_asm(&self, asm: &hir::InlineAsm<'tcx>, enclosing_id: hir::HirId) {
- let hir = self.tcx.hir();
- let enclosing_def_id = hir.local_def_id(enclosing_id).to_def_id();
- let target_features = self.tcx.asm_target_features(enclosing_def_id);
+ pub fn check_asm(&self, asm: &hir::InlineAsm<'tcx>, enclosing_id: LocalDefId) {
+ let target_features = self.tcx.asm_target_features(enclosing_id.to_def_id());
let Some(asm_arch) = self.tcx.sess.asm_arch else {
self.tcx.sess.delay_span_bug(DUMMY_SP, "target architecture does not support asm");
return;
@@ -415,7 +414,7 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
// Check that sym actually points to a function. Later passes
// depend on this.
hir::InlineAsmOperand::SymFn { anon_const } => {
- let ty = self.tcx.typeck_body(anon_const.body).node_type(anon_const.hir_id);
+ let ty = self.tcx.type_of(anon_const.def_id).subst_identity();
match ty.kind() {
ty::Never | ty::Error(_) => {}
ty::FnDef(..) => {}
@@ -423,7 +422,7 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
let mut err =
self.tcx.sess.struct_span_err(*op_sp, "invalid `sym` operand");
err.span_label(
- self.tcx.hir().span(anon_const.body.hir_id),
+ self.tcx.def_span(anon_const.def_id),
&format!("is {} `{}`", ty.kind().article(), ty),
);
err.help("`sym` operands must refer to either a function or a static");
diff --git a/compiler/rustc_hir_analysis/src/check/mod.rs b/compiler/rustc_hir_analysis/src/check/mod.rs
index 14bca34b7..9acfc1b3d 100644
--- a/compiler/rustc_hir_analysis/src/check/mod.rs
+++ b/compiler/rustc_hir_analysis/src/check/mod.rs
@@ -75,7 +75,6 @@ pub use check::check_abi;
use check::check_mod_item_types;
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_errors::{pluralize, struct_span_err, Applicability, Diagnostic, DiagnosticBuilder};
-use rustc_hir as hir;
use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_hir::intravisit::Visitor;
use rustc_index::bit_set::BitSet;
@@ -105,6 +104,7 @@ pub fn provide(providers: &mut Providers) {
region_scope_tree,
collect_return_position_impl_trait_in_trait_tys,
compare_impl_const: compare_impl_item::compare_impl_const_raw,
+ check_generator_obligations: check::check_generator_obligations,
..*providers
};
}
@@ -168,27 +168,24 @@ fn maybe_check_static_with_link_section(tcx: TyCtxt<'_>, id: LocalDefId) {
}
}
-fn report_forbidden_specialization(
- tcx: TyCtxt<'_>,
- impl_item: &hir::ImplItemRef,
- parent_impl: DefId,
-) {
+fn report_forbidden_specialization(tcx: TyCtxt<'_>, impl_item: DefId, parent_impl: DefId) {
+ let span = tcx.def_span(impl_item);
+ let ident = tcx.item_name(impl_item);
let mut err = struct_span_err!(
tcx.sess,
- impl_item.span,
+ span,
E0520,
- "`{}` specializes an item from a parent `impl`, but \
- that item is not marked `default`",
- impl_item.ident
+ "`{}` specializes an item from a parent `impl`, but that item is not marked `default`",
+ ident,
);
- err.span_label(impl_item.span, format!("cannot specialize default item `{}`", impl_item.ident));
+ err.span_label(span, format!("cannot specialize default item `{}`", ident));
match tcx.span_of_impl(parent_impl) {
Ok(span) => {
err.span_label(span, "parent `impl` is here");
err.note(&format!(
"to specialize, `{}` in the parent `impl` must be marked `default`",
- impl_item.ident
+ ident
));
}
Err(cname) => {
@@ -202,7 +199,7 @@ fn report_forbidden_specialization(
fn missing_items_err(
tcx: TyCtxt<'_>,
impl_span: Span,
- missing_items: &[&ty::AssocItem],
+ missing_items: &[ty::AssocItem],
full_impl_span: Span,
) {
let missing_items_msg = missing_items
@@ -228,7 +225,7 @@ fn missing_items_err(
let padding =
tcx.sess.source_map().indentation_before(sugg_sp).unwrap_or_else(|| String::new());
- for trait_item in missing_items {
+ for &trait_item in missing_items {
let snippet = suggestion_signature(trait_item, tcx);
let code = format!("{}{}\n{}", padding, snippet, padding);
let msg = format!("implement the missing item: `{snippet}`");
@@ -275,7 +272,7 @@ fn default_body_is_unstable(
reason: Option<Symbol>,
issue: Option<NonZeroU32>,
) {
- let missing_item_name = &tcx.associated_item(item_did).name;
+ let missing_item_name = tcx.associated_item(item_did).name;
let use_of_unstable_library_feature_note = match reason {
Some(r) => format!("use of unstable library feature '{feature}': {r}"),
None => format!("use of unstable library feature '{feature}'"),
@@ -368,7 +365,7 @@ fn fn_sig_suggestion<'tcx>(
sig: ty::FnSig<'tcx>,
ident: Ident,
predicates: ty::GenericPredicates<'tcx>,
- assoc: &ty::AssocItem,
+ assoc: ty::AssocItem,
) -> String {
let args = sig
.inputs()
@@ -436,7 +433,7 @@ pub fn ty_kind_suggestion(ty: Ty<'_>) -> Option<&'static str> {
/// Return placeholder code for the given associated item.
/// Similar to `ty::AssocItem::suggestion`, but appropriate for use as the code snippet of a
/// structured suggestion.
-fn suggestion_signature(assoc: &ty::AssocItem, tcx: TyCtxt<'_>) -> String {
+fn suggestion_signature(assoc: ty::AssocItem, tcx: TyCtxt<'_>) -> String {
match assoc.kind {
ty::AssocKind::Fn => {
// We skip the binder here because the binder would deanonymize all
@@ -445,7 +442,7 @@ fn suggestion_signature(assoc: &ty::AssocItem, tcx: TyCtxt<'_>) -> String {
// regions just fine, showing `fn(&MyType)`.
fn_sig_suggestion(
tcx,
- tcx.fn_sig(assoc.def_id).skip_binder(),
+ tcx.fn_sig(assoc.def_id).subst_identity().skip_binder(),
assoc.ident(tcx),
tcx.predicates_of(assoc.def_id),
assoc,
@@ -453,7 +450,7 @@ fn suggestion_signature(assoc: &ty::AssocItem, tcx: TyCtxt<'_>) -> String {
}
ty::AssocKind::Type => format!("type {} = Type;", assoc.name),
ty::AssocKind::Const => {
- let ty = tcx.type_of(assoc.def_id);
+ let ty = tcx.type_of(assoc.def_id).subst_identity();
let val = ty_kind_suggestion(ty).unwrap_or("value");
format!("const {}: {} = {};", assoc.name, ty, val)
}
diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
index 11237afe8..4cccdf30c 100644
--- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs
+++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
@@ -16,8 +16,8 @@ use rustc_middle::mir::ConstraintCategory;
use rustc_middle::ty::query::Providers;
use rustc_middle::ty::trait_def::TraitSpecializationKind;
use rustc_middle::ty::{
- self, AdtKind, DefIdTree, GenericParamDefKind, Ty, TyCtxt, TypeFoldable, TypeSuperVisitable,
- TypeVisitable, TypeVisitor,
+ self, AdtKind, GenericParamDefKind, Ty, TyCtxt, TypeFoldable, TypeSuperVisitable,
+ TypeVisitable, TypeVisitableExt, TypeVisitor,
};
use rustc_middle::ty::{GenericArgKind, InternalSubsts};
use rustc_session::parse::feature_err;
@@ -37,7 +37,7 @@ use std::ops::{ControlFlow, Deref};
pub(super) struct WfCheckingCtxt<'a, 'tcx> {
pub(super) ocx: ObligationCtxt<'a, 'tcx>,
span: Span,
- body_id: hir::HirId,
+ body_def_id: LocalDefId,
param_env: ty::ParamEnv<'tcx>,
}
impl<'a, 'tcx> Deref for WfCheckingCtxt<'a, 'tcx> {
@@ -56,10 +56,10 @@ impl<'tcx> WfCheckingCtxt<'_, 'tcx> {
// `ObligationCtxt::normalize`, but provides a nice `ObligationCauseCode`.
fn normalize<T>(&self, span: Span, loc: Option<WellFormedLoc>, value: T) -> T
where
- T: TypeFoldable<'tcx>,
+ T: TypeFoldable<TyCtxt<'tcx>>,
{
self.ocx.normalize(
- &ObligationCause::new(span, self.body_id, ObligationCauseCode::WellFormed(loc)),
+ &ObligationCause::new(span, self.body_def_id, ObligationCauseCode::WellFormed(loc)),
self.param_env,
value,
)
@@ -71,8 +71,11 @@ impl<'tcx> WfCheckingCtxt<'_, 'tcx> {
loc: Option<WellFormedLoc>,
arg: ty::GenericArg<'tcx>,
) {
- let cause =
- traits::ObligationCause::new(span, self.body_id, ObligationCauseCode::WellFormed(loc));
+ let cause = traits::ObligationCause::new(
+ span,
+ self.body_def_id,
+ ObligationCauseCode::WellFormed(loc),
+ );
// for a type to be WF, we do not need to check if const trait predicates satisfy.
let param_env = self.param_env.without_const();
self.ocx.register_obligation(traits::Obligation::new(
@@ -93,11 +96,10 @@ pub(super) fn enter_wf_checking_ctxt<'tcx, F>(
F: for<'a> FnOnce(&WfCheckingCtxt<'a, 'tcx>),
{
let param_env = tcx.param_env(body_def_id);
- let body_id = tcx.hir().local_def_id_to_hir_id(body_def_id);
let infcx = &tcx.infer_ctxt().build();
let ocx = ObligationCtxt::new(infcx);
- let mut wfcx = WfCheckingCtxt { ocx, span, body_id, param_env };
+ let mut wfcx = WfCheckingCtxt { ocx, span, body_def_id, param_env };
if !tcx.features().trivial_bounds {
wfcx.check_false_global_bounds()
@@ -105,7 +107,7 @@ pub(super) fn enter_wf_checking_ctxt<'tcx, F>(
f(&mut wfcx);
let assumed_wf_types = wfcx.ocx.assumed_wf_types(param_env, span, body_def_id);
- let implied_bounds = infcx.implied_bounds_tys(param_env, body_id, assumed_wf_types);
+ let implied_bounds = infcx.implied_bounds_tys(param_env, body_def_id, assumed_wf_types);
let errors = wfcx.select_all_or_error();
if !errors.is_empty() {
@@ -275,56 +277,6 @@ fn check_trait_item(tcx: TyCtxt<'_>, trait_item: &hir::TraitItem<'_>) {
};
check_object_unsafe_self_trait_by_name(tcx, trait_item);
check_associated_item(tcx, def_id, span, method_sig);
-
- let encl_trait_def_id = tcx.local_parent(def_id);
- let encl_trait = tcx.hir().expect_item(encl_trait_def_id);
- let encl_trait_def_id = encl_trait.owner_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::Ref(_, _)) {
- tcx.sess
- .struct_span_err(
- self_ty.span,
- &format!(
- "first argument of `call` in `{fn_lang_item_name}` lang item must be a reference",
- ),
- )
- .emit();
- }
- } else {
- tcx.sess
- .struct_span_err(
- *span,
- &format!(
- "`call` function in `{fn_lang_item_name}` lang item takes exactly two arguments",
- ),
- )
- .emit();
- }
- } else {
- tcx.sess
- .struct_span_err(
- trait_item.span,
- &format!(
- "`call` trait item in `{fn_lang_item_name}` lang item must be a function",
- ),
- )
- .emit();
- }
- }
}
/// Require that the user writes where clauses on GATs for the implicit
@@ -374,7 +326,6 @@ fn check_gat_where_clauses(tcx: TyCtxt<'_>, associated_items: &[hir::TraitItemRe
continue;
}
- let item_hir_id = item.id.hir_id();
let param_env = tcx.param_env(item_def_id);
let item_required_bounds = match item.kind {
@@ -385,12 +336,12 @@ fn check_gat_where_clauses(tcx: TyCtxt<'_>, associated_items: &[hir::TraitItemRe
// `Self::Iter<'a>` is a GAT we want to gather any potential missing bounds from.
let sig: ty::FnSig<'_> = tcx.liberate_late_bound_regions(
item_def_id.to_def_id(),
- tcx.fn_sig(item_def_id),
+ tcx.fn_sig(item_def_id).subst_identity(),
);
gather_gat_bounds(
tcx,
param_env,
- item_hir_id,
+ item_def_id,
sig.inputs_and_output,
// We also assume that all of the function signature's parameter types
// are well formed.
@@ -412,7 +363,7 @@ fn check_gat_where_clauses(tcx: TyCtxt<'_>, associated_items: &[hir::TraitItemRe
gather_gat_bounds(
tcx,
param_env,
- item_hir_id,
+ item_def_id,
tcx.explicit_item_bounds(item_def_id).to_vec(),
&FxIndexSet::default(),
gat_def_id.def_id,
@@ -458,7 +409,6 @@ fn check_gat_where_clauses(tcx: TyCtxt<'_>, associated_items: &[hir::TraitItemRe
let gat_item_hir = tcx.hir().expect_trait_item(gat_def_id.def_id);
debug!(?required_bounds);
let param_env = tcx.param_env(gat_def_id);
- let gat_hir = gat_item_hir.hir_id();
let mut unsatisfied_bounds: Vec<_> = required_bounds
.into_iter()
@@ -466,13 +416,25 @@ fn check_gat_where_clauses(tcx: TyCtxt<'_>, associated_items: &[hir::TraitItemRe
ty::PredicateKind::Clause(ty::Clause::RegionOutlives(ty::OutlivesPredicate(
a,
b,
- ))) => {
- !region_known_to_outlive(tcx, gat_hir, param_env, &FxIndexSet::default(), a, b)
- }
+ ))) => !region_known_to_outlive(
+ tcx,
+ gat_def_id.def_id,
+ param_env,
+ &FxIndexSet::default(),
+ a,
+ b,
+ ),
ty::PredicateKind::Clause(ty::Clause::TypeOutlives(ty::OutlivesPredicate(
a,
b,
- ))) => !ty_known_to_outlive(tcx, gat_hir, param_env, &FxIndexSet::default(), a, b),
+ ))) => !ty_known_to_outlive(
+ tcx,
+ gat_def_id.def_id,
+ param_env,
+ &FxIndexSet::default(),
+ a,
+ b,
+ ),
_ => bug!("Unexpected PredicateKind"),
})
.map(|clause| clause.to_string())
@@ -531,8 +493,9 @@ fn augment_param_env<'tcx>(
return param_env;
}
- let bounds =
- tcx.mk_predicates(param_env.caller_bounds().iter().chain(new_predicates.iter().cloned()));
+ let bounds = tcx.mk_predicates_from_iter(
+ param_env.caller_bounds().iter().chain(new_predicates.iter().cloned()),
+ );
// FIXME(compiler-errors): Perhaps there is a case where we need to normalize this
// i.e. traits::normalize_param_env_or_error
ty::ParamEnv::new(bounds, param_env.reveal(), param_env.constness())
@@ -548,10 +511,10 @@ fn augment_param_env<'tcx>(
/// fn into_iter<'a>(&'a self) -> Self::Iter<'a>;
/// }
/// ```
-fn gather_gat_bounds<'tcx, T: TypeFoldable<'tcx>>(
+fn gather_gat_bounds<'tcx, T: TypeFoldable<TyCtxt<'tcx>>>(
tcx: TyCtxt<'tcx>,
param_env: ty::ParamEnv<'tcx>,
- item_hir: hir::HirId,
+ item_def_id: hir::OwnerId,
to_check: T,
wf_tys: &FxIndexSet<Ty<'tcx>>,
gat_def_id: LocalDefId,
@@ -584,24 +547,22 @@ fn gather_gat_bounds<'tcx, T: TypeFoldable<'tcx>>(
// reflected in a where clause on the GAT itself.
for (ty, ty_idx) in &types {
// In our example, requires that `Self: 'a`
- if ty_known_to_outlive(tcx, item_hir, param_env, &wf_tys, *ty, *region_a) {
+ if ty_known_to_outlive(tcx, item_def_id.def_id, param_env, &wf_tys, *ty, *region_a) {
debug!(?ty_idx, ?region_a_idx);
debug!("required clause: {ty} must outlive {region_a}");
// Translate into the generic parameters of the GAT. In
// our example, the type was `Self`, which will also be
// `Self` in the GAT.
let ty_param = gat_generics.param_at(*ty_idx, tcx);
- let ty_param = tcx
- .mk_ty(ty::Param(ty::ParamTy { index: ty_param.index, name: ty_param.name }));
+ let ty_param = tcx.mk_ty_param(ty_param.index, ty_param.name);
// Same for the region. In our example, 'a corresponds
// to the 'me parameter.
let region_param = gat_generics.param_at(*region_a_idx, tcx);
- let region_param =
- tcx.mk_region(ty::RegionKind::ReEarlyBound(ty::EarlyBoundRegion {
- def_id: region_param.def_id,
- index: region_param.index,
- name: region_param.name,
- }));
+ let region_param = tcx.mk_re_early_bound(ty::EarlyBoundRegion {
+ def_id: region_param.def_id,
+ index: region_param.index,
+ name: region_param.name,
+ });
// The predicate we expect to see. (In our example,
// `Self: 'me`.)
let clause = ty::PredicateKind::Clause(ty::Clause::TypeOutlives(
@@ -622,25 +583,30 @@ fn gather_gat_bounds<'tcx, T: TypeFoldable<'tcx>>(
if ty::ReStatic == **region_b || region_a == region_b {
continue;
}
- if region_known_to_outlive(tcx, item_hir, param_env, &wf_tys, *region_a, *region_b) {
+ if region_known_to_outlive(
+ tcx,
+ item_def_id.def_id,
+ param_env,
+ &wf_tys,
+ *region_a,
+ *region_b,
+ ) {
debug!(?region_a_idx, ?region_b_idx);
debug!("required clause: {region_a} must outlive {region_b}");
// Translate into the generic parameters of the GAT.
let region_a_param = gat_generics.param_at(*region_a_idx, tcx);
- let region_a_param =
- tcx.mk_region(ty::RegionKind::ReEarlyBound(ty::EarlyBoundRegion {
- def_id: region_a_param.def_id,
- index: region_a_param.index,
- name: region_a_param.name,
- }));
+ let region_a_param = tcx.mk_re_early_bound(ty::EarlyBoundRegion {
+ def_id: region_a_param.def_id,
+ index: region_a_param.index,
+ name: region_a_param.name,
+ });
// Same for the region.
let region_b_param = gat_generics.param_at(*region_b_idx, tcx);
- let region_b_param =
- tcx.mk_region(ty::RegionKind::ReEarlyBound(ty::EarlyBoundRegion {
- def_id: region_b_param.def_id,
- index: region_b_param.index,
- name: region_b_param.name,
- }));
+ let region_b_param = tcx.mk_re_early_bound(ty::EarlyBoundRegion {
+ def_id: region_b_param.def_id,
+ index: region_b_param.index,
+ name: region_b_param.name,
+ });
// The predicate we expect to see.
let clause = ty::PredicateKind::Clause(ty::Clause::RegionOutlives(
ty::OutlivesPredicate(region_a_param, region_b_param),
@@ -658,7 +624,7 @@ fn gather_gat_bounds<'tcx, T: TypeFoldable<'tcx>>(
/// `ty` outlives `region`.
fn ty_known_to_outlive<'tcx>(
tcx: TyCtxt<'tcx>,
- id: hir::HirId,
+ id: LocalDefId,
param_env: ty::ParamEnv<'tcx>,
wf_tys: &FxIndexSet<Ty<'tcx>>,
ty: Ty<'tcx>,
@@ -675,7 +641,7 @@ fn ty_known_to_outlive<'tcx>(
/// `region_a` outlives `region_b`
fn region_known_to_outlive<'tcx>(
tcx: TyCtxt<'tcx>,
- id: hir::HirId,
+ id: LocalDefId,
param_env: ty::ParamEnv<'tcx>,
wf_tys: &FxIndexSet<Ty<'tcx>>,
region_a: ty::Region<'tcx>,
@@ -699,7 +665,7 @@ fn region_known_to_outlive<'tcx>(
/// to be tested), then resolve region and return errors
fn resolve_regions_with_wf_tys<'tcx>(
tcx: TyCtxt<'tcx>,
- id: hir::HirId,
+ id: LocalDefId,
param_env: ty::ParamEnv<'tcx>,
wf_tys: &FxIndexSet<Ty<'tcx>>,
add_constraints: impl for<'a> FnOnce(&'a InferCtxt<'tcx>, &'a RegionBoundPairs<'tcx>),
@@ -743,7 +709,7 @@ struct GATSubstCollector<'tcx> {
}
impl<'tcx> GATSubstCollector<'tcx> {
- fn visit<T: TypeFoldable<'tcx>>(
+ fn visit<T: TypeFoldable<TyCtxt<'tcx>>>(
gat: DefId,
t: T,
) -> (FxHashSet<(ty::Region<'tcx>, usize)>, FxHashSet<(Ty<'tcx>, usize)>) {
@@ -754,7 +720,7 @@ impl<'tcx> GATSubstCollector<'tcx> {
}
}
-impl<'tcx> TypeVisitor<'tcx> for GATSubstCollector<'tcx> {
+impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for GATSubstCollector<'tcx> {
type BreakTy = !;
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
@@ -822,7 +788,7 @@ fn check_object_unsafe_self_trait_by_name(tcx: TyCtxt<'_>, item: &hir::TraitItem
_ => {}
}
if !trait_should_be_self.is_empty() {
- if tcx.object_safety_violations(trait_def_id).is_empty() {
+ if tcx.check_is_object_safe(trait_def_id) {
return;
}
let sugg = trait_should_be_self.iter().map(|span| (*span, "Self".to_string())).collect();
@@ -859,7 +825,7 @@ fn check_param_wf(tcx: TyCtxt<'_>, param: &hir::GenericParam<'_>) {
// Const parameters are well formed if their type is structural match.
hir::GenericParamKind::Const { ty: hir_ty, default: _ } => {
- let ty = tcx.type_of(param.def_id);
+ let ty = tcx.type_of(param.def_id).subst_identity();
if tcx.features().adt_const_params {
if let Some(non_structural_match_ty) =
@@ -996,17 +962,17 @@ fn check_associated_item(
let self_ty = match item.container {
ty::TraitContainer => tcx.types.self_param,
- ty::ImplContainer => tcx.type_of(item.container_id(tcx)),
+ ty::ImplContainer => tcx.type_of(item.container_id(tcx)).subst_identity(),
};
match item.kind {
ty::AssocKind::Const => {
- let ty = tcx.type_of(item.def_id);
+ let ty = tcx.type_of(item.def_id).subst_identity();
let ty = wfcx.normalize(span, Some(WellFormedLoc::Ty(item_id)), ty);
wfcx.register_wf_obligation(span, loc, ty.into());
}
ty::AssocKind::Fn => {
- let sig = tcx.fn_sig(item.def_id);
+ let sig = tcx.fn_sig(item.def_id).subst_identity();
let hir_sig = sig_if_method.expect("bad signature for method");
check_fn_or_method(
wfcx,
@@ -1022,7 +988,7 @@ fn check_associated_item(
check_associated_type_bounds(wfcx, item, span)
}
if item.defaultness(tcx).has_value() {
- let ty = tcx.type_of(item.def_id);
+ let ty = tcx.type_of(item.def_id).subst_identity();
let ty = wfcx.normalize(span, Some(WellFormedLoc::Ty(item_id)), ty);
wfcx.register_wf_obligation(span, loc, ty.into());
}
@@ -1053,9 +1019,9 @@ fn check_type_defn<'tcx>(tcx: TyCtxt<'tcx>, item: &hir::Item<'tcx>, all_sized: b
// All field types must be well-formed.
for field in &variant.fields {
let field_id = field.did.expect_local();
- let hir::Node::Field(hir::FieldDef { ty: hir_ty, .. }) = tcx.hir().get_by_def_id(field_id)
- else { bug!() };
- let ty = wfcx.normalize(hir_ty.span, None, tcx.type_of(field.did));
+ let hir::FieldDef { ty: hir_ty, .. } =
+ tcx.hir().get_by_def_id(field_id).expect_field();
+ let ty = wfcx.normalize(hir_ty.span, None, tcx.type_of(field.did).subst_identity());
wfcx.register_wf_obligation(
hir_ty.span,
Some(WellFormedLoc::Ty(field_id)),
@@ -1067,7 +1033,7 @@ fn check_type_defn<'tcx>(tcx: TyCtxt<'tcx>, item: &hir::Item<'tcx>, all_sized: b
// intermediate types must be sized.
let needs_drop_copy = || {
packed && {
- let ty = tcx.type_of(variant.fields.last().unwrap().did);
+ let ty = tcx.type_of(variant.fields.last().unwrap().did).subst_identity();
let ty = tcx.erase_regions(ty);
if ty.needs_infer() {
tcx.sess
@@ -1087,13 +1053,13 @@ fn check_type_defn<'tcx>(tcx: TyCtxt<'tcx>, item: &hir::Item<'tcx>, all_sized: b
{
let last = idx == variant.fields.len() - 1;
let field_id = field.did.expect_local();
- let hir::Node::Field(hir::FieldDef { ty: hir_ty, .. }) = tcx.hir().get_by_def_id(field_id)
- else { bug!() };
- let ty = wfcx.normalize(hir_ty.span, None, tcx.type_of(field.did));
+ let hir::FieldDef { ty: hir_ty, .. } =
+ tcx.hir().get_by_def_id(field_id).expect_field();
+ let ty = wfcx.normalize(hir_ty.span, None, tcx.type_of(field.did).subst_identity());
wfcx.register_bound(
traits::ObligationCause::new(
hir_ty.span,
- wfcx.body_id,
+ wfcx.body_def_id,
traits::FieldSized {
adt_kind: match item_adt_kind(&item.kind) {
Some(i) => i,
@@ -1113,7 +1079,7 @@ fn check_type_defn<'tcx>(tcx: TyCtxt<'tcx>, item: &hir::Item<'tcx>, all_sized: b
if let ty::VariantDiscr::Explicit(discr_def_id) = variant.discr {
let cause = traits::ObligationCause::new(
tcx.def_span(discr_def_id),
- wfcx.body_id,
+ wfcx.body_def_id,
traits::MiscObligation,
);
wfcx.register_obligation(traits::Obligation::new(
@@ -1165,7 +1131,7 @@ fn check_trait(tcx: TyCtxt<'_>, item: &hir::Item<'_>) {
///
/// Assuming the defaults are used, check that all predicates (bounds on the
/// assoc type and where clauses on the trait) hold.
-fn check_associated_type_bounds(wfcx: &WfCheckingCtxt<'_, '_>, item: &ty::AssocItem, span: Span) {
+fn check_associated_type_bounds(wfcx: &WfCheckingCtxt<'_, '_>, item: ty::AssocItem, span: Span) {
let bounds = wfcx.tcx().explicit_item_bounds(item.def_id);
debug!("check_associated_type_bounds: bounds={:?}", bounds);
@@ -1174,7 +1140,7 @@ fn check_associated_type_bounds(wfcx: &WfCheckingCtxt<'_, '_>, item: &ty::AssocI
traits::wf::predicate_obligations(
wfcx.infcx,
wfcx.param_env,
- wfcx.body_id,
+ wfcx.body_def_id,
normalized_bound,
bound_span,
)
@@ -1191,7 +1157,7 @@ fn check_item_fn(
decl: &hir::FnDecl<'_>,
) {
enter_wf_checking_ctxt(tcx, span, def_id, |wfcx| {
- let sig = tcx.fn_sig(def_id);
+ let sig = tcx.fn_sig(def_id).subst_identity();
check_fn_or_method(wfcx, ident.span, sig, decl, def_id);
})
}
@@ -1200,7 +1166,7 @@ fn check_item_type(tcx: TyCtxt<'_>, item_id: LocalDefId, ty_span: Span, allow_fo
debug!("check_item_type: {:?}", item_id);
enter_wf_checking_ctxt(tcx, ty_span, item_id, |wfcx| {
- let ty = tcx.type_of(item_id);
+ let ty = tcx.type_of(item_id).subst_identity();
let item_ty = wfcx.normalize(ty_span, Some(WellFormedLoc::Ty(item_id)), ty);
let mut forbid_unsized = true;
@@ -1214,7 +1180,7 @@ fn check_item_type(tcx: TyCtxt<'_>, item_id: LocalDefId, ty_span: Span, allow_fo
wfcx.register_wf_obligation(ty_span, Some(WellFormedLoc::Ty(item_id)), item_ty.into());
if forbid_unsized {
wfcx.register_bound(
- traits::ObligationCause::new(ty_span, wfcx.body_id, traits::WellFormed(None)),
+ traits::ObligationCause::new(ty_span, wfcx.body_def_id, traits::WellFormed(None)),
wfcx.param_env,
item_ty,
tcx.require_lang_item(LangItem::Sized, None),
@@ -1229,7 +1195,7 @@ fn check_item_type(tcx: TyCtxt<'_>, item_id: LocalDefId, ty_span: Span, allow_fo
if should_check_for_sync {
wfcx.register_bound(
- traits::ObligationCause::new(ty_span, wfcx.body_id, traits::SharedStatic),
+ traits::ObligationCause::new(ty_span, wfcx.body_def_id, traits::SharedStatic),
wfcx.param_env,
item_ty,
tcx.require_lang_item(LangItem::Sync, Some(ty_span)),
@@ -1269,7 +1235,7 @@ fn check_impl<'tcx>(
let mut obligations = traits::wf::trait_obligations(
wfcx.infcx,
wfcx.param_env,
- wfcx.body_id,
+ wfcx.body_def_id,
&trait_pred,
ast_trait_ref.path.span,
item,
@@ -1285,7 +1251,7 @@ fn check_impl<'tcx>(
wfcx.register_obligations(obligations);
}
None => {
- let self_ty = tcx.type_of(item.owner_id);
+ let self_ty = tcx.type_of(item.owner_id).subst_identity();
let self_ty = wfcx.normalize(
item.span,
Some(WellFormedLoc::Ty(item.hir_id().expect_owner().def_id)),
@@ -1330,7 +1296,7 @@ fn check_where_clauses<'tcx>(wfcx: &WfCheckingCtxt<'_, 'tcx>, span: Span, def_id
match param.kind {
GenericParamDefKind::Type { .. } => {
if is_our_default(param) {
- let ty = tcx.type_of(param.def_id);
+ let ty = tcx.type_of(param.def_id).subst_identity();
// Ignore dependent defaults -- that is, where the default of one type
// parameter includes another (e.g., `<T, U = T>`). In those cases, we can't
// be sure if it will error or not as user might always specify the other.
@@ -1382,7 +1348,7 @@ fn check_where_clauses<'tcx>(wfcx: &WfCheckingCtxt<'_, 'tcx>, span: Span, def_id
GenericParamDefKind::Type { .. } => {
// If the param has a default, ...
if is_our_default(param) {
- let default_ty = tcx.type_of(param.def_id);
+ let default_ty = tcx.type_of(param.def_id).subst_identity();
// ... and it's not a dependent default, ...
if !default_ty.needs_subst() {
// ... then substitute it with the default.
@@ -1417,7 +1383,7 @@ fn check_where_clauses<'tcx>(wfcx: &WfCheckingCtxt<'_, 'tcx>, span: Span, def_id
struct CountParams {
params: FxHashSet<u32>,
}
- impl<'tcx> ty::visit::TypeVisitor<'tcx> for CountParams {
+ impl<'tcx> ty::visit::TypeVisitor<TyCtxt<'tcx>> for CountParams {
type BreakTy = ();
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
@@ -1466,7 +1432,7 @@ fn check_where_clauses<'tcx>(wfcx: &WfCheckingCtxt<'_, 'tcx>, span: Span, def_id
let pred = wfcx.normalize(sp, None, pred);
let cause = traits::ObligationCause::new(
sp,
- wfcx.body_id,
+ wfcx.body_def_id,
traits::ItemObligation(def_id.to_def_id()),
);
traits::Obligation::new(tcx, cause, wfcx.param_env, pred)
@@ -1482,12 +1448,11 @@ fn check_where_clauses<'tcx>(wfcx: &WfCheckingCtxt<'_, 'tcx>, span: Span, def_id
traits::wf::predicate_obligations(
infcx,
wfcx.param_env.without_const(),
- wfcx.body_id,
+ wfcx.body_def_id,
p,
sp,
)
});
-
let obligations: Vec<_> = wf_obligations.chain(default_obligations).collect();
wfcx.register_obligations(obligations);
}
@@ -1512,7 +1477,7 @@ fn check_fn_or_method<'tcx>(
|idx| hir_decl.inputs.get(idx).map_or(hir_decl.output.span(), |arg: &hir::Ty<'_>| arg.span);
sig.inputs_and_output =
- tcx.mk_type_list(sig.inputs_and_output.iter().enumerate().map(|(idx, ty)| {
+ tcx.mk_type_list_from_iter(sig.inputs_and_output.iter().enumerate().map(|(idx, ty)| {
wfcx.normalize(
arg_span(idx),
Some(WellFormedLoc::Param {
@@ -1549,7 +1514,7 @@ fn check_fn_or_method<'tcx>(
// Check that the argument is a tuple
if let Some(ty) = inputs.next() {
wfcx.register_bound(
- ObligationCause::new(span, wfcx.body_id, ObligationCauseCode::RustCall),
+ ObligationCause::new(span, wfcx.body_def_id, ObligationCauseCode::RustCall),
wfcx.param_env,
*ty,
tcx.require_lang_item(hir::LangItem::Tuple, Some(span)),
@@ -1585,7 +1550,7 @@ fn check_return_position_impl_trait_in_trait_bounds<'tcx>(
{
for arg in fn_output.walk() {
if let ty::GenericArgKind::Type(ty) = arg.unpack()
- && let ty::Alias(ty::Projection, proj) = ty.kind()
+ && let ty::Alias(ty::Opaque, proj) = ty.kind()
&& tcx.def_kind(proj.def_id) == DefKind::ImplTraitPlaceholder
&& tcx.impl_trait_in_trait_parent(proj.def_id) == fn_def_id.to_def_id()
{
@@ -1597,7 +1562,7 @@ fn check_return_position_impl_trait_in_trait_bounds<'tcx>(
traits::wf::predicate_obligations(
wfcx.infcx,
wfcx.param_env,
- wfcx.body_id,
+ wfcx.body_def_id,
normalized_bound,
bound_span,
)
@@ -1616,7 +1581,7 @@ const HELP_FOR_SELF_TYPE: &str = "consider changing to `self`, `&self`, `&mut se
fn check_method_receiver<'tcx>(
wfcx: &WfCheckingCtxt<'_, 'tcx>,
fn_sig: &hir::FnSig<'_>,
- method: &ty::AssocItem,
+ method: ty::AssocItem,
self_ty: Ty<'tcx>,
) {
let tcx = wfcx.tcx();
@@ -1627,7 +1592,7 @@ fn check_method_receiver<'tcx>(
let span = fn_sig.decl.inputs[0].span;
- let sig = tcx.fn_sig(method.def_id);
+ let sig = tcx.fn_sig(method.def_id).subst_identity();
let sig = tcx.liberate_late_bound_regions(method.def_id, sig);
let sig = wfcx.normalize(span, None, sig);
@@ -1697,9 +1662,9 @@ fn receiver_is_valid<'tcx>(
let infcx = wfcx.infcx;
let tcx = wfcx.tcx();
let cause =
- ObligationCause::new(span, wfcx.body_id, traits::ObligationCauseCode::MethodReceiver);
+ ObligationCause::new(span, wfcx.body_def_id, traits::ObligationCauseCode::MethodReceiver);
- let can_eq_self = |ty| infcx.can_eq(wfcx.param_env, self_ty, ty).is_ok();
+ let can_eq_self = |ty| infcx.can_eq(wfcx.param_env, self_ty, ty);
// `self: Self` is always valid.
if can_eq_self(receiver_ty) {
@@ -1709,7 +1674,7 @@ fn receiver_is_valid<'tcx>(
return true;
}
- let mut autoderef = Autoderef::new(infcx, wfcx.param_env, wfcx.body_id, span, receiver_ty);
+ let mut autoderef = Autoderef::new(infcx, wfcx.param_env, wfcx.body_def_id, span, receiver_ty);
// The `arbitrary_self_types` feature allows raw pointer receivers like `self: *const Self`.
if arbitrary_self_types_enabled {
@@ -1799,7 +1764,7 @@ fn check_variances_for_type_defn<'tcx>(
item: &hir::Item<'tcx>,
hir_generics: &hir::Generics<'_>,
) {
- let ty = tcx.type_of(item.owner_id);
+ let ty = tcx.type_of(item.owner_id).subst_identity();
if tcx.has_error_field(ty) {
return;
}
@@ -1894,8 +1859,7 @@ impl<'tcx> WfCheckingCtxt<'_, 'tcx> {
let mut span = self.span;
let empty_env = ty::ParamEnv::empty();
- let def_id = tcx.hir().local_def_id(self.body_id);
- let predicates_with_span = tcx.predicates_of(def_id).predicates.iter().copied();
+ let predicates_with_span = tcx.predicates_of(self.body_def_id).predicates.iter().copied();
// Check elaborated bounds.
let implied_obligations = traits::elaborate_predicates_with_span(tcx, predicates_with_span);
@@ -1910,7 +1874,7 @@ impl<'tcx> WfCheckingCtxt<'_, 'tcx> {
// Match the existing behavior.
if pred.is_global() && !pred.has_late_bound_vars() {
let pred = self.normalize(span, None, pred);
- let hir_node = tcx.hir().find(self.body_id);
+ let hir_node = tcx.hir().find_by_def_id(self.body_def_id);
// only use the span of the predicate clause (#90869)
@@ -1929,7 +1893,7 @@ impl<'tcx> WfCheckingCtxt<'_, 'tcx> {
let obligation = traits::Obligation::new(
tcx,
- traits::ObligationCause::new(span, self.body_id, traits::TrivialBound),
+ traits::ObligationCause::new(span, self.body_def_id, traits::TrivialBound),
empty_env,
pred,
);
diff --git a/compiler/rustc_hir_analysis/src/check_unused.rs b/compiler/rustc_hir_analysis/src/check_unused.rs
index ebb78213a..f3f5851d8 100644
--- a/compiler/rustc_hir_analysis/src/check_unused.rs
+++ b/compiler/rustc_hir_analysis/src/check_unused.rs
@@ -1,12 +1,8 @@
-use crate::errors::{ExternCrateNotIdiomatic, UnusedExternCrate};
-use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::unord::UnordSet;
-use rustc_hir as hir;
use rustc_hir::def::DefKind;
-use rustc_hir::def_id::{DefId, LocalDefId};
+use rustc_hir::def_id::LocalDefId;
use rustc_middle::ty::TyCtxt;
use rustc_session::lint;
-use rustc_span::{Span, Symbol};
pub fn check_crate(tcx: TyCtxt<'_>) {
let mut used_trait_imports: UnordSet<LocalDefId> = Default::default();
@@ -29,7 +25,7 @@ pub fn check_crate(tcx: TyCtxt<'_>) {
if item.span.is_dummy() {
continue;
}
- let hir::ItemKind::Use(path, _) = item.kind else { unreachable!() };
+ let (path, _) = item.expect_use();
let msg = if let Ok(snippet) = tcx.sess.source_map().span_to_snippet(path.span) {
format!("unused import: `{}`", snippet)
} else {
@@ -43,131 +39,4 @@ pub fn check_crate(tcx: TyCtxt<'_>) {
|lint| lint,
);
}
-
- unused_crates_lint(tcx);
-}
-
-fn unused_crates_lint(tcx: TyCtxt<'_>) {
- let lint = lint::builtin::UNUSED_EXTERN_CRATES;
-
- // Collect first the crates that are completely unused. These we
- // can always suggest removing (no matter which edition we are
- // in).
- let unused_extern_crates: FxHashMap<LocalDefId, Span> = tcx
- .maybe_unused_extern_crates(())
- .iter()
- .filter(|&&(def_id, _)| {
- tcx.extern_mod_stmt_cnum(def_id).map_or(true, |cnum| {
- !tcx.is_compiler_builtins(cnum)
- && !tcx.is_panic_runtime(cnum)
- && !tcx.has_global_allocator(cnum)
- && !tcx.has_panic_handler(cnum)
- })
- })
- .cloned()
- .collect();
-
- // Collect all the extern crates (in a reliable order).
- let mut crates_to_lint = vec![];
-
- for id in tcx.hir().items() {
- if matches!(tcx.def_kind(id.owner_id), DefKind::ExternCrate) {
- let item = tcx.hir().item(id);
- if let hir::ItemKind::ExternCrate(orig_name) = item.kind {
- crates_to_lint.push(ExternCrateToLint {
- def_id: item.owner_id.to_def_id(),
- span: item.span,
- orig_name,
- warn_if_unused: !item.ident.as_str().starts_with('_'),
- });
- }
- }
- }
-
- let extern_prelude = &tcx.resolutions(()).extern_prelude;
-
- for extern_crate in &crates_to_lint {
- let def_id = extern_crate.def_id.expect_local();
- let item = tcx.hir().expect_item(def_id);
-
- // If the crate is fully unused, we suggest removing it altogether.
- // We do this in any edition.
- if extern_crate.warn_if_unused {
- if let Some(&span) = unused_extern_crates.get(&def_id) {
- // Removal suggestion span needs to include attributes (Issue #54400)
- let id = tcx.hir().local_def_id_to_hir_id(def_id);
- let span_with_attrs = tcx
- .hir()
- .attrs(id)
- .iter()
- .map(|attr| attr.span)
- .fold(span, |acc, attr_span| acc.to(attr_span));
-
- tcx.emit_spanned_lint(lint, id, span, UnusedExternCrate { span: span_with_attrs });
- continue;
- }
- }
-
- // If we are not in Rust 2018 edition, then we don't make any further
- // suggestions.
- if !tcx.sess.rust_2018() {
- continue;
- }
-
- // If the extern crate isn't in the extern prelude,
- // there is no way it can be written as a `use`.
- let orig_name = extern_crate.orig_name.unwrap_or(item.ident.name);
- if !extern_prelude.get(&orig_name).map_or(false, |from_item| !from_item) {
- continue;
- }
-
- // If the extern crate is renamed, then we cannot suggest replacing it with a use as this
- // would not insert the new name into the prelude, where other imports in the crate may be
- // expecting it.
- if extern_crate.orig_name.is_some() {
- continue;
- }
-
- let id = tcx.hir().local_def_id_to_hir_id(def_id);
- // If the extern crate has any attributes, they may have funky
- // semantics we can't faithfully represent using `use` (most
- // notably `#[macro_use]`). Ignore it.
- if !tcx.hir().attrs(id).is_empty() {
- continue;
- }
-
- let base_replacement = match extern_crate.orig_name {
- Some(orig_name) => format!("use {} as {};", orig_name, item.ident.name),
- None => format!("use {};", item.ident.name),
- };
- let vis = tcx.sess.source_map().span_to_snippet(item.vis_span).unwrap_or_default();
- let add_vis = |to| if vis.is_empty() { to } else { format!("{} {}", vis, to) };
- tcx.emit_spanned_lint(
- lint,
- id,
- extern_crate.span,
- ExternCrateNotIdiomatic {
- span: extern_crate.span,
- msg_code: add_vis("use".to_string()),
- suggestion_code: add_vis(base_replacement),
- },
- );
- }
-}
-
-struct ExternCrateToLint {
- /// `DefId` of the extern crate
- def_id: DefId,
-
- /// span from the item
- span: Span,
-
- /// if `Some`, then this is renamed (`extern crate orig_name as
- /// crate_name`), and -- perhaps surprisingly -- this stores the
- /// *original* name (`item.name` will contain the new name)
- orig_name: Option<Symbol>,
-
- /// if `false`, the original name started with `_`, so we shouldn't lint
- /// about it going unused (but we should still emit idiom lints).
- warn_if_unused: bool,
}
diff --git a/compiler/rustc_hir_analysis/src/coherence/builtin.rs b/compiler/rustc_hir_analysis/src/coherence/builtin.rs
index 28c040878..ffb68abf9 100644
--- a/compiler/rustc_hir_analysis/src/coherence/builtin.rs
+++ b/compiler/rustc_hir_analysis/src/coherence/builtin.rs
@@ -11,7 +11,7 @@ use rustc_infer::infer::outlives::env::OutlivesEnvironment;
use rustc_infer::infer::TyCtxtInferExt;
use rustc_infer::infer::{self, RegionResolutionError};
use rustc_middle::ty::adjustment::CoerceUnsizedInfo;
-use rustc_middle::ty::{self, suggest_constraining_type_params, Ty, TyCtxt, TypeVisitable};
+use rustc_middle::ty::{self, suggest_constraining_type_params, Ty, TyCtxt, TypeVisitableExt};
use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt;
use rustc_trait_selection::traits::misc::{
type_allowed_to_implement_copy, CopyImplementationError, InfringingFieldsReason,
@@ -50,13 +50,13 @@ impl<'tcx> Checker<'tcx> {
fn visit_implementation_of_drop(tcx: TyCtxt<'_>, impl_did: LocalDefId) {
// Destructors only work on local ADT types.
- match tcx.type_of(impl_did).kind() {
+ match tcx.type_of(impl_did).subst_identity().kind() {
ty::Adt(def, _) if def.did().is_local() => return,
ty::Error(_) => return,
_ => {}
}
- let ItemKind::Impl(impl_) = tcx.hir().expect_item(impl_did).kind else { bug!("expected Drop impl item") };
+ let impl_ = tcx.hir().expect_item(impl_did).expect_impl();
tcx.sess.emit_err(DropImplOnWrongItem { span: impl_.self_ty.span });
}
@@ -64,9 +64,7 @@ fn visit_implementation_of_drop(tcx: TyCtxt<'_>, impl_did: LocalDefId) {
fn visit_implementation_of_copy(tcx: TyCtxt<'_>, impl_did: LocalDefId) {
debug!("visit_implementation_of_copy: impl_did={:?}", impl_did);
- let impl_hir_id = tcx.hir().local_def_id_to_hir_id(impl_did);
-
- let self_type = tcx.type_of(impl_did);
+ let self_type = tcx.type_of(impl_did).subst_identity();
debug!("visit_implementation_of_copy: self_type={:?} (bound)", self_type);
let param_env = tcx.param_env(impl_did);
@@ -80,7 +78,7 @@ fn visit_implementation_of_copy(tcx: TyCtxt<'_>, impl_did: LocalDefId) {
_ => bug!("expected Copy impl item"),
};
- let cause = traits::ObligationCause::misc(span, impl_hir_id);
+ let cause = traits::ObligationCause::misc(span, impl_did);
match type_allowed_to_implement_copy(tcx, param_env, self_type, cause) {
Ok(()) => {}
Err(CopyImplementationError::InfrigingFields(fields)) => {
@@ -178,6 +176,7 @@ fn visit_implementation_of_copy(tcx: TyCtxt<'_>, impl_did: LocalDefId) {
bounds.iter().map(|(param, constraint, def_id)| {
(param.as_str(), constraint.as_str(), *def_id)
}),
+ None,
);
err.emit();
}
@@ -203,12 +202,11 @@ fn visit_implementation_of_coerce_unsized(tcx: TyCtxt<'_>, impl_did: LocalDefId)
fn visit_implementation_of_dispatch_from_dyn(tcx: TyCtxt<'_>, impl_did: LocalDefId) {
debug!("visit_implementation_of_dispatch_from_dyn: impl_did={:?}", impl_did);
- let impl_hir_id = tcx.hir().local_def_id_to_hir_id(impl_did);
- let span = tcx.hir().span(impl_hir_id);
+ let span = tcx.def_span(impl_did);
let dispatch_from_dyn_trait = tcx.require_lang_item(LangItem::DispatchFromDyn, Some(span));
- let source = tcx.type_of(impl_did);
+ let source = tcx.type_of(impl_did).subst_identity();
assert!(!source.has_escaping_bound_vars());
let target = {
let trait_ref = tcx.impl_trait_ref(impl_did).unwrap().subst_identity();
@@ -224,7 +222,7 @@ fn visit_implementation_of_dispatch_from_dyn(tcx: TyCtxt<'_>, impl_did: LocalDef
let create_err = |msg: &str| struct_span_err!(tcx.sess, span, E0378, "{}", msg);
let infcx = tcx.infer_ctxt().build();
- let cause = ObligationCause::misc(span, impl_hir_id);
+ let cause = ObligationCause::misc(span, impl_did);
use rustc_type_ir::sty::TyKind::*;
match (source.kind(), target.kind()) {
@@ -372,7 +370,7 @@ pub fn coerce_unsized_info<'tcx>(tcx: TyCtxt<'tcx>, impl_did: DefId) -> CoerceUn
tcx.sess.fatal(&format!("`CoerceUnsized` implementation {}", err.to_string()));
});
- let source = tcx.type_of(impl_did);
+ let source = tcx.type_of(impl_did).subst_identity();
let trait_ref = tcx.impl_trait_ref(impl_did).unwrap().subst_identity();
assert_eq!(trait_ref.def_id, coerce_unsized_trait);
let target = trait_ref.substs.type_at(1);
@@ -386,8 +384,7 @@ pub fn coerce_unsized_info<'tcx>(tcx: TyCtxt<'tcx>, impl_did: DefId) -> CoerceUn
debug!("visit_implementation_of_coerce_unsized: {:?} -> {:?} (free)", source, target);
let infcx = tcx.infer_ctxt().build();
- let impl_hir_id = tcx.hir().local_def_id_to_hir_id(impl_did);
- let cause = ObligationCause::misc(span, impl_hir_id);
+ let cause = ObligationCause::misc(span, impl_did);
let check_mutbl = |mt_a: ty::TypeAndMut<'tcx>,
mt_b: ty::TypeAndMut<'tcx>,
mk_ptr: &dyn Fn(Ty<'tcx>) -> Ty<'tcx>| {
@@ -440,7 +437,7 @@ pub fn coerce_unsized_info<'tcx>(tcx: TyCtxt<'tcx>, impl_did: DefId) -> CoerceUn
}
// Here we are considering a case of converting
- // `S<P0...Pn>` to S<Q0...Qn>`. As an example, let's imagine a struct `Foo<T, U>`,
+ // `S<P0...Pn>` to `S<Q0...Qn>`. As an example, let's imagine a struct `Foo<T, U>`,
// which acts like a pointer to `U`, but carries along some extra data of type `T`:
//
// struct Foo<T, U> {
@@ -485,7 +482,7 @@ pub fn coerce_unsized_info<'tcx>(tcx: TyCtxt<'tcx>, impl_did: DefId) -> CoerceUn
.filter_map(|(i, f)| {
let (a, b) = (f.ty(tcx, substs_a), f.ty(tcx, substs_b));
- if tcx.type_of(f.did).is_phantom_data() {
+ if tcx.type_of(f.did).subst_identity().is_phantom_data() {
// Ignore PhantomData fields
return None;
}
@@ -575,7 +572,7 @@ pub fn coerce_unsized_info<'tcx>(tcx: TyCtxt<'tcx>, impl_did: DefId) -> CoerceUn
};
// Register an obligation for `A: Trait<B>`.
- let cause = traits::ObligationCause::misc(span, impl_hir_id);
+ let cause = traits::ObligationCause::misc(span, impl_did);
let predicate =
predicate_for_trait_def(tcx, param_env, cause, trait_def_id, 0, [source, target]);
let errors = traits::fully_solve_obligation(&infcx, predicate);
diff --git a/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs b/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs
index dfb982409..02f3eeee0 100644
--- a/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs
+++ b/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs
@@ -14,7 +14,6 @@ use rustc_hir::def_id::{CrateNum, DefId, LocalDefId};
use rustc_middle::ty::fast_reject::{simplify_type, SimplifiedType, TreatParams};
use rustc_middle::ty::{self, CrateInherentImpls, Ty, TyCtxt};
use rustc_span::symbol::sym;
-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 {
@@ -57,86 +56,76 @@ const ADD_ATTR: &str =
"alternatively add `#[rustc_allow_incoherent_impl]` to the relevant impl items";
impl<'tcx> InherentCollect<'tcx> {
- fn check_def_id(&mut self, item: &hir::Item<'_>, self_ty: Ty<'tcx>, def_id: DefId) {
- let impl_def_id = item.owner_id;
- if let Some(def_id) = def_id.as_local() {
+ fn check_def_id(&mut self, impl_def_id: LocalDefId, self_ty: Ty<'tcx>, ty_def_id: DefId) {
+ if let Some(ty_def_id) = ty_def_id.as_local() {
// Add the implementation to the mapping from implementation to base
// type def ID, if there is a base type for this implementation and
// the implementation does not have any associated traits.
- let vec = self.impls_map.inherent_impls.entry(def_id).or_default();
+ let vec = self.impls_map.inherent_impls.entry(ty_def_id).or_default();
vec.push(impl_def_id.to_def_id());
return;
}
if self.tcx.features().rustc_attrs {
- let hir::ItemKind::Impl(&hir::Impl { items, .. }) = item.kind else {
- bug!("expected `impl` item: {:?}", item);
- };
+ let items = self.tcx.associated_item_def_ids(impl_def_id);
- if !self.tcx.has_attr(def_id, sym::rustc_has_incoherent_inherent_impls) {
+ if !self.tcx.has_attr(ty_def_id, sym::rustc_has_incoherent_inherent_impls) {
+ let impl_span = self.tcx.def_span(impl_def_id);
struct_span_err!(
self.tcx.sess,
- item.span,
+ impl_span,
E0390,
"cannot define inherent `impl` for a type outside of the crate where the type is defined",
)
.help(INTO_DEFINING_CRATE)
- .span_help(item.span, ADD_ATTR_TO_TY)
+ .span_help(impl_span, ADD_ATTR_TO_TY)
.emit();
return;
}
- for impl_item in items {
- if !self
- .tcx
- .has_attr(impl_item.id.owner_id.to_def_id(), sym::rustc_allow_incoherent_impl)
- {
+ for &impl_item in items {
+ if !self.tcx.has_attr(impl_item, sym::rustc_allow_incoherent_impl) {
+ let impl_span = self.tcx.def_span(impl_def_id);
struct_span_err!(
self.tcx.sess,
- item.span,
+ impl_span,
E0390,
"cannot define inherent `impl` for a type outside of the crate where the type is defined",
)
.help(INTO_DEFINING_CRATE)
- .span_help(impl_item.span, ADD_ATTR)
+ .span_help(self.tcx.def_span(impl_item), ADD_ATTR)
.emit();
return;
}
}
if let Some(simp) = simplify_type(self.tcx, self_ty, TreatParams::AsInfer) {
- self.impls_map.incoherent_impls.entry(simp).or_default().push(impl_def_id.def_id);
+ self.impls_map.incoherent_impls.entry(simp).or_default().push(impl_def_id);
} else {
bug!("unexpected self type: {:?}", self_ty);
}
} else {
+ let impl_span = self.tcx.def_span(impl_def_id);
struct_span_err!(
self.tcx.sess,
- item.span,
+ impl_span,
E0116,
"cannot define inherent `impl` for a type outside of the crate \
where the type is defined"
)
- .span_label(item.span, "impl for type defined outside of crate.")
+ .span_label(impl_span, "impl for type defined outside of crate.")
.note("define and implement a trait or new type instead")
.emit();
}
}
- fn check_primitive_impl(
- &mut self,
- impl_def_id: LocalDefId,
- ty: Ty<'tcx>,
- items: &[hir::ImplItemRef],
- span: Span,
- ) {
+ fn check_primitive_impl(&mut self, impl_def_id: LocalDefId, ty: Ty<'tcx>) {
+ let items = self.tcx.associated_item_def_ids(impl_def_id);
if !self.tcx.hir().rustc_coherence_is_core() {
if self.tcx.features().rustc_attrs {
- for item in items {
- if !self
- .tcx
- .has_attr(item.id.owner_id.to_def_id(), sym::rustc_allow_incoherent_impl)
- {
+ for &impl_item in items {
+ if !self.tcx.has_attr(impl_item, sym::rustc_allow_incoherent_impl) {
+ let span = self.tcx.def_span(impl_def_id);
struct_span_err!(
self.tcx.sess,
span,
@@ -144,12 +133,13 @@ impl<'tcx> InherentCollect<'tcx> {
"cannot define inherent `impl` for primitive types outside of `core`",
)
.help(INTO_CORE)
- .span_help(item.span, ADD_ATTR)
+ .span_help(self.tcx.def_span(impl_item), ADD_ATTR)
.emit();
return;
}
}
} else {
+ let span = self.tcx.def_span(impl_def_id);
let mut err = struct_span_err!(
self.tcx.sess,
span,
@@ -177,34 +167,27 @@ impl<'tcx> InherentCollect<'tcx> {
}
fn check_item(&mut self, id: hir::ItemId) {
- if !matches!(self.tcx.def_kind(id.owner_id), DefKind::Impl) {
+ if !matches!(self.tcx.def_kind(id.owner_id), DefKind::Impl { of_trait: false }) {
return;
}
- let item = self.tcx.hir().item(id);
- let hir::ItemKind::Impl(hir::Impl { of_trait: None, self_ty: ty, items, .. }) = item.kind else {
- return;
- };
-
- let self_ty = self.tcx.type_of(item.owner_id);
+ let id = id.owner_id.def_id;
+ let item_span = self.tcx.def_span(id);
+ let self_ty = self.tcx.type_of(id).subst_identity();
match *self_ty.kind() {
- ty::Adt(def, _) => {
- self.check_def_id(item, self_ty, def.did());
- }
- ty::Foreign(did) => {
- self.check_def_id(item, self_ty, did);
- }
+ ty::Adt(def, _) => self.check_def_id(id, self_ty, def.did()),
+ ty::Foreign(did) => self.check_def_id(id, self_ty, did),
ty::Dynamic(data, ..) if data.principal_def_id().is_some() => {
- self.check_def_id(item, self_ty, data.principal_def_id().unwrap());
+ self.check_def_id(id, self_ty, data.principal_def_id().unwrap());
}
ty::Dynamic(..) => {
struct_span_err!(
self.tcx.sess,
- ty.span,
+ item_span,
E0785,
"cannot define inherent `impl` for a dyn auto trait"
)
- .span_label(ty.span, "impl requires at least one non-auto trait")
+ .span_label(item_span, "impl requires at least one non-auto trait")
.note("define and implement a new trait or type instead")
.emit();
}
@@ -220,18 +203,16 @@ impl<'tcx> InherentCollect<'tcx> {
| ty::Ref(..)
| ty::Never
| ty::FnPtr(_)
- | ty::Tuple(..) => {
- self.check_primitive_impl(item.owner_id.def_id, self_ty, items, ty.span)
- }
+ | ty::Tuple(..) => self.check_primitive_impl(id, self_ty),
ty::Alias(..) | ty::Param(_) => {
let mut err = struct_span_err!(
self.tcx.sess,
- ty.span,
+ item_span,
E0118,
"no nominal type found for inherent implementation"
);
- err.span_label(ty.span, "impl requires a nominal type")
+ err.span_label(item_span, "impl requires a nominal type")
.note("either implement a trait on it or create a newtype to wrap it instead");
err.emit();
@@ -240,10 +221,11 @@ impl<'tcx> InherentCollect<'tcx> {
| ty::Closure(..)
| ty::Generator(..)
| ty::GeneratorWitness(..)
+ | ty::GeneratorWitnessMIR(..)
| ty::Bound(..)
| ty::Placeholder(_)
| ty::Infer(_) => {
- bug!("unexpected impl self type of impl: {:?} {:?}", item.owner_id, self_ty);
+ bug!("unexpected impl self type of impl: {:?} {:?}", id, self_ty);
}
ty::Error(_) => {}
}
diff --git a/compiler/rustc_hir_analysis/src/coherence/inherent_impls_overlap.rs b/compiler/rustc_hir_analysis/src/coherence/inherent_impls_overlap.rs
index a9331af4e..7bca4edcc 100644
--- a/compiler/rustc_hir_analysis/src/coherence/inherent_impls_overlap.rs
+++ b/compiler/rustc_hir_analysis/src/coherence/inherent_impls_overlap.rs
@@ -27,8 +27,8 @@ impl<'tcx> InherentOverlapChecker<'tcx> {
/// namespace.
fn impls_have_common_items(
&self,
- impl_items1: &ty::AssocItems<'_>,
- impl_items2: &ty::AssocItems<'_>,
+ impl_items1: &ty::AssocItems,
+ impl_items2: &ty::AssocItems,
) -> bool {
let mut impl_items1 = &impl_items1;
let mut impl_items2 = &impl_items2;
@@ -38,10 +38,10 @@ impl<'tcx> InherentOverlapChecker<'tcx> {
std::mem::swap(&mut impl_items1, &mut impl_items2);
}
- for item1 in impl_items1.in_definition_order() {
+ for &item1 in impl_items1.in_definition_order() {
let collision = impl_items2
.filter_by_name_unhygienic(item1.name)
- .any(|item2| self.compare_hygienically(item1, item2));
+ .any(|&item2| self.compare_hygienically(item1, item2));
if collision {
return true;
@@ -51,7 +51,7 @@ impl<'tcx> InherentOverlapChecker<'tcx> {
false
}
- fn compare_hygienically(&self, item1: &ty::AssocItem, item2: &ty::AssocItem) -> bool {
+ fn compare_hygienically(&self, item1: ty::AssocItem, item2: ty::AssocItem) -> bool {
// Symbols and namespace match, compare hygienically.
item1.kind.namespace() == item2.kind.namespace()
&& item1.ident(self.tcx).normalize_to_macros_2_0()
@@ -98,10 +98,10 @@ impl<'tcx> InherentOverlapChecker<'tcx> {
let impl_items1 = self.tcx.associated_items(impl1);
let impl_items2 = self.tcx.associated_items(impl2);
- for item1 in impl_items1.in_definition_order() {
+ for &item1 in impl_items1.in_definition_order() {
let collision = impl_items2
.filter_by_name_unhygienic(item1.name)
- .find(|item2| self.compare_hygienically(item1, item2));
+ .find(|&&item2| self.compare_hygienically(item1, item2));
if let Some(item2) = collision {
let name = item1.ident(self.tcx).normalize_to_macros_2_0();
diff --git a/compiler/rustc_hir_analysis/src/coherence/mod.rs b/compiler/rustc_hir_analysis/src/coherence/mod.rs
index d3b5778ba..23490bc09 100644
--- a/compiler/rustc_hir_analysis/src/coherence/mod.rs
+++ b/compiler/rustc_hir_analysis/src/coherence/mod.rs
@@ -8,7 +8,7 @@
use rustc_errors::{error_code, struct_span_err};
use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_middle::ty::query::Providers;
-use rustc_middle::ty::{self, TyCtxt, TypeVisitable};
+use rustc_middle::ty::{self, TyCtxt, TypeVisitableExt};
use rustc_span::sym;
use rustc_trait_selection::traits;
@@ -169,7 +169,7 @@ fn check_object_overlap<'tcx>(
});
for component_def_id in component_def_ids {
- if !tcx.is_object_safe(component_def_id) {
+ if !tcx.check_is_object_safe(component_def_id) {
// Without the 'object_safe_for_dispatch' feature this is an error
// which will be reported by wfcheck. Ignore it here.
// This is tested by `coherence-impl-trait-for-trait-object-safe.rs`.
diff --git a/compiler/rustc_hir_analysis/src/coherence/orphan.rs b/compiler/rustc_hir_analysis/src/coherence/orphan.rs
index 95b03eb82..1f2de3f21 100644
--- a/compiler/rustc_hir_analysis/src/coherence/orphan.rs
+++ b/compiler/rustc_hir_analysis/src/coherence/orphan.rs
@@ -8,7 +8,8 @@ use rustc_hir as hir;
use rustc_middle::ty::subst::InternalSubsts;
use rustc_middle::ty::util::IgnoreRegions;
use rustc_middle::ty::{
- self, ImplPolarity, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitor,
+ self, AliasKind, ImplPolarity, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitableExt,
+ TypeVisitor,
};
use rustc_session::lint;
use rustc_span::def_id::{DefId, LocalDefId};
@@ -39,25 +40,27 @@ fn do_orphan_check_impl<'tcx>(
) -> Result<(), ErrorGuaranteed> {
let trait_def_id = trait_ref.def_id;
- let item = tcx.hir().expect_item(def_id);
- let hir::ItemKind::Impl(impl_) = item.kind else {
- bug!("{:?} is not an impl: {:?}", def_id, item);
- };
- let sp = tcx.def_span(def_id);
- let tr = impl_.of_trait.as_ref().unwrap();
-
- match traits::orphan_check(tcx, item.owner_id.to_def_id()) {
+ match traits::orphan_check(tcx, def_id.to_def_id()) {
Ok(()) => {}
- Err(err) => emit_orphan_check_error(
- tcx,
- sp,
- item.span,
- tr.path.span,
- trait_ref,
- impl_.self_ty.span,
- &impl_.generics,
- err,
- )?,
+ Err(err) => {
+ let item = tcx.hir().expect_item(def_id);
+ let hir::ItemKind::Impl(impl_) = item.kind else {
+ bug!("{:?} is not an impl: {:?}", def_id, item);
+ };
+ let tr = impl_.of_trait.as_ref().unwrap();
+ let sp = tcx.def_span(def_id);
+
+ emit_orphan_check_error(
+ tcx,
+ sp,
+ item.span,
+ tr.path.span,
+ trait_ref,
+ impl_.self_ty.span,
+ &impl_.generics,
+ err,
+ )?
+ }
}
// In addition to the above rules, we restrict impls of auto traits
@@ -86,7 +89,7 @@ fn do_orphan_check_impl<'tcx>(
// struct B { }
// impl Foo for A { }
// impl Foo for B { }
- // impl !Send for (A, B) { }
+ // impl !Foo for (A, B) { }
// ```
//
// This final impl is legal according to the orphan
@@ -99,50 +102,198 @@ fn do_orphan_check_impl<'tcx>(
tcx.trait_is_auto(trait_def_id)
);
- if tcx.trait_is_auto(trait_def_id) && !trait_def_id.is_local() {
+ if tcx.trait_is_auto(trait_def_id) {
let self_ty = trait_ref.self_ty();
- let opt_self_def_id = match *self_ty.kind() {
- ty::Adt(self_def, _) => Some(self_def.did()),
- ty::Foreign(did) => Some(did),
- _ => None,
- };
- let msg = match opt_self_def_id {
- // We only want to permit nominal types, but not *all* nominal types.
- // They must be local to the current crate, so that people
- // can't do `unsafe impl Send for Rc<SomethingLocal>` or
- // `impl !Send for Box<SomethingLocalAndSend>`.
- Some(self_def_id) => {
- if self_def_id.is_local() {
- None
+ // If the impl is in the same crate as the auto-trait, almost anything
+ // goes.
+ //
+ // impl MyAuto for Rc<Something> {} // okay
+ // impl<T> !MyAuto for *const T {} // okay
+ // impl<T> MyAuto for T {} // okay
+ //
+ // But there is one important exception: implementing for a trait object
+ // is not allowed.
+ //
+ // impl MyAuto for dyn Trait {} // NOT OKAY
+ // impl<T: ?Sized> MyAuto for T {} // NOT OKAY
+ //
+ // With this restriction, it's guaranteed that an auto-trait is
+ // implemented for a trait object if and only if the auto-trait is one
+ // of the trait object's trait bounds (or a supertrait of a bound). In
+ // other words `dyn Trait + AutoTrait` always implements AutoTrait,
+ // while `dyn Trait` never implements AutoTrait.
+ //
+ // This is necessary in order for autotrait bounds on methods of trait
+ // objects to be sound.
+ //
+ // auto trait AutoTrait {}
+ //
+ // trait ObjectSafeTrait {
+ // fn f(&self) where Self: AutoTrait;
+ // }
+ //
+ // We can allow f to be called on `dyn ObjectSafeTrait + AutoTrait`.
+ //
+ // If we didn't deny `impl AutoTrait for dyn Trait`, it would be unsound
+ // for the ObjectSafeTrait shown above to be object safe because someone
+ // could take some type implementing ObjectSafeTrait but not AutoTrait,
+ // unsize it to `dyn ObjectSafeTrait`, and call .f() which has no
+ // concrete implementation (issue #50781).
+ enum LocalImpl {
+ Allow,
+ Disallow { problematic_kind: &'static str },
+ }
+
+ // If the auto-trait is from a dependency, it must only be getting
+ // implemented for a nominal type, and specifically one local to the
+ // current crate.
+ //
+ // impl<T> Sync for MyStruct<T> {} // okay
+ //
+ // impl Sync for Rc<MyStruct> {} // NOT OKAY
+ enum NonlocalImpl {
+ Allow,
+ DisallowBecauseNonlocal,
+ DisallowOther,
+ }
+
+ // Exhaustive match considering that this logic is essential for
+ // soundness.
+ let (local_impl, nonlocal_impl) = match self_ty.kind() {
+ // struct Struct<T>;
+ // impl AutoTrait for Struct<Foo> {}
+ ty::Adt(self_def, _) => (
+ LocalImpl::Allow,
+ if self_def.did().is_local() {
+ NonlocalImpl::Allow
} else {
- Some((
- format!(
- "cross-crate traits with a default impl, like `{}`, \
- can only be implemented for a struct/enum type \
- defined in the current crate",
- tcx.def_path_str(trait_def_id)
- ),
- "can't implement cross-crate trait for type in another crate",
- ))
- }
+ NonlocalImpl::DisallowBecauseNonlocal
+ },
+ ),
+
+ // extern { type OpaqueType; }
+ // impl AutoTrait for OpaqueType {}
+ ty::Foreign(did) => (
+ LocalImpl::Allow,
+ if did.is_local() {
+ NonlocalImpl::Allow
+ } else {
+ NonlocalImpl::DisallowBecauseNonlocal
+ },
+ ),
+
+ // impl AutoTrait for dyn Trait {}
+ ty::Dynamic(..) => (
+ LocalImpl::Disallow { problematic_kind: "trait object" },
+ NonlocalImpl::DisallowOther,
+ ),
+
+ // impl<T> AutoTrait for T {}
+ // impl<T: ?Sized> AutoTrait for T {}
+ ty::Param(..) => (
+ if self_ty.is_sized(tcx, tcx.param_env(def_id)) {
+ LocalImpl::Allow
+ } else {
+ LocalImpl::Disallow { problematic_kind: "generic type" }
+ },
+ NonlocalImpl::DisallowOther,
+ ),
+
+ // trait Id { type This: ?Sized; }
+ // impl<T: ?Sized> Id for T {
+ // type This = T;
+ // }
+ // impl<T: ?Sized> AutoTrait for <T as Id>::This {}
+ ty::Alias(AliasKind::Projection, _) => (
+ LocalImpl::Disallow { problematic_kind: "associated type" },
+ NonlocalImpl::DisallowOther,
+ ),
+
+ // type Opaque = impl Trait;
+ // impl AutoTrait for Opaque {}
+ ty::Alias(AliasKind::Opaque, _) => (
+ LocalImpl::Disallow { problematic_kind: "opaque type" },
+ NonlocalImpl::DisallowOther,
+ ),
+
+ ty::Bool
+ | ty::Char
+ | ty::Int(..)
+ | ty::Uint(..)
+ | ty::Float(..)
+ | ty::Str
+ | ty::Array(..)
+ | ty::Slice(..)
+ | ty::RawPtr(..)
+ | ty::Ref(..)
+ | ty::FnDef(..)
+ | ty::FnPtr(..)
+ | ty::Never
+ | ty::Tuple(..) => (LocalImpl::Allow, NonlocalImpl::DisallowOther),
+
+ ty::Closure(..)
+ | ty::Generator(..)
+ | ty::GeneratorWitness(..)
+ | ty::GeneratorWitnessMIR(..)
+ | ty::Bound(..)
+ | ty::Placeholder(..)
+ | ty::Infer(..) => {
+ let sp = tcx.def_span(def_id);
+ span_bug!(sp, "weird self type for autotrait impl")
}
- _ => Some((
- format!(
- "cross-crate traits with a default impl, like `{}`, can \
- only be implemented for a struct/enum type, not `{}`",
- tcx.def_path_str(trait_def_id),
- self_ty
- ),
- "can't implement cross-crate trait with a default impl for \
- non-struct/enum type",
- )),
+
+ ty::Error(..) => (LocalImpl::Allow, NonlocalImpl::Allow),
};
- if let Some((msg, label)) = msg {
- let reported =
- struct_span_err!(tcx.sess, sp, E0321, "{}", msg).span_label(sp, label).emit();
- return Err(reported);
+ if trait_def_id.is_local() {
+ match local_impl {
+ LocalImpl::Allow => {}
+ LocalImpl::Disallow { problematic_kind } => {
+ let msg = format!(
+ "traits with a default impl, like `{trait}`, \
+ cannot be implemented for {problematic_kind} `{self_ty}`",
+ trait = tcx.def_path_str(trait_def_id),
+ );
+ let label = format!(
+ "a trait object implements `{trait}` if and only if `{trait}` \
+ is one of the trait object's trait bounds",
+ trait = tcx.def_path_str(trait_def_id),
+ );
+ let sp = tcx.def_span(def_id);
+ let reported =
+ struct_span_err!(tcx.sess, sp, E0321, "{}", msg).note(label).emit();
+ return Err(reported);
+ }
+ }
+ } else {
+ if let Some((msg, label)) = match nonlocal_impl {
+ NonlocalImpl::Allow => None,
+ NonlocalImpl::DisallowBecauseNonlocal => Some((
+ format!(
+ "cross-crate traits with a default impl, like `{}`, \
+ can only be implemented for a struct/enum type \
+ defined in the current crate",
+ tcx.def_path_str(trait_def_id)
+ ),
+ "can't implement cross-crate trait for type in another crate",
+ )),
+ NonlocalImpl::DisallowOther => Some((
+ format!(
+ "cross-crate traits with a default impl, like `{}`, can \
+ only be implemented for a struct/enum type, not `{}`",
+ tcx.def_path_str(trait_def_id),
+ self_ty
+ ),
+ "can't implement cross-crate trait with a default impl for \
+ non-struct/enum type",
+ )),
+ } {
+ let sp = tcx.def_span(def_id);
+ let reported =
+ struct_span_err!(tcx.sess, sp, E0321, "{}", msg).span_label(sp, label).emit();
+ return Err(reported);
+ }
}
}
@@ -381,7 +532,7 @@ fn lint_auto_trait_impl<'tcx>(
}),
|lint| {
let item_span = tcx.def_span(self_type_did);
- let self_descr = tcx.def_kind(self_type_did).descr(self_type_did);
+ let self_descr = tcx.def_descr(self_type_did);
match arg {
ty::util::NotUniqueParam::DuplicateParam(arg) => {
lint.note(&format!("`{}` is mentioned multiple times", arg));
@@ -409,7 +560,7 @@ fn fast_reject_auto_impl<'tcx>(tcx: TyCtxt<'tcx>, trait_def_id: DefId, self_ty:
seen: FxHashSet<DefId>,
}
- impl<'tcx> TypeVisitor<'tcx> for DisableAutoTraitVisitor<'tcx> {
+ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for DisableAutoTraitVisitor<'tcx> {
type BreakTy = ();
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
let tcx = self.tcx;
diff --git a/compiler/rustc_hir_analysis/src/coherence/unsafety.rs b/compiler/rustc_hir_analysis/src/coherence/unsafety.rs
index fe6119dce..c6b161713 100644
--- a/compiler/rustc_hir_analysis/src/coherence/unsafety.rs
+++ b/compiler/rustc_hir_analysis/src/coherence/unsafety.rs
@@ -3,15 +3,13 @@
use rustc_errors::struct_span_err;
use rustc_hir as hir;
-use rustc_hir::def::DefKind;
use rustc_hir::Unsafety;
use rustc_middle::ty::TyCtxt;
use rustc_span::def_id::LocalDefId;
pub(super) fn check_item(tcx: TyCtxt<'_>, def_id: LocalDefId) {
- debug_assert!(matches!(tcx.def_kind(def_id), DefKind::Impl));
let item = tcx.hir().expect_item(def_id);
- let hir::ItemKind::Impl(impl_) = item.kind else { bug!() };
+ let impl_ = item.expect_impl();
if let Some(trait_ref) = tcx.impl_trait_ref(item.owner_id) {
let trait_ref = trait_ref.subst_identity();
diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs
index c17778ce8..604d54caf 100644
--- a/compiler/rustc_hir_analysis/src/collect.rs
+++ b/compiler/rustc_hir_analysis/src/collect.rs
@@ -25,7 +25,7 @@ use rustc_hir as hir;
use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_hir::intravisit::{self, Visitor};
use rustc_hir::{GenericParamKind, Node};
-use rustc_infer::infer::TyCtxtInferExt;
+use rustc_infer::infer::{InferCtxt, TyCtxtInferExt};
use rustc_infer::traits::ObligationCause;
use rustc_middle::hir::nested_filter;
use rustc_middle::ty::query::Providers;
@@ -41,8 +41,8 @@ use std::iter;
mod generics_of;
mod item_bounds;
-mod lifetimes;
mod predicates_of;
+mod resolve_bound_vars;
mod type_of;
///////////////////////////////////////////////////////////////////////////
@@ -53,7 +53,7 @@ fn collect_mod_item_types(tcx: TyCtxt<'_>, module_def_id: LocalDefId) {
}
pub fn provide(providers: &mut Providers) {
- lifetimes::provide(providers);
+ resolve_bound_vars::provide(providers);
*providers = Providers {
opt_const_param_of: type_of::opt_const_param_of,
type_of: type_of::type_of,
@@ -458,13 +458,11 @@ impl<'tcx> AstConv<'tcx> for ItemCtxt<'tcx> {
self.tcx.replace_late_bound_regions_uncached(
poly_trait_ref,
|_| {
- self.tcx.mk_region(ty::ReEarlyBound(
- ty::EarlyBoundRegion {
- def_id: item_def_id,
- index: 0,
- name: Symbol::intern(&lt_name),
- },
- ))
+ self.tcx.mk_re_early_bound(ty::EarlyBoundRegion {
+ def_id: item_def_id,
+ index: 0,
+ name: Symbol::intern(&lt_name),
+ })
}
),
),
@@ -501,7 +499,7 @@ impl<'tcx> AstConv<'tcx> for ItemCtxt<'tcx> {
}
_ => {}
}
- self.tcx().ty_error_with_guaranteed(err.emit())
+ self.tcx().ty_error(err.emit())
}
}
@@ -517,6 +515,10 @@ impl<'tcx> AstConv<'tcx> for ItemCtxt<'tcx> {
fn record_ty(&self, _hir_id: hir::HirId, _ty: Ty<'tcx>, _span: Span) {
// There's no place to record types from signatures?
}
+
+ fn infcx(&self) -> Option<&InferCtxt<'tcx>> {
+ None
+ }
}
/// Synthesize a new lifetime name that doesn't clash with any of the lifetimes already present.
@@ -903,7 +905,7 @@ fn adt_def(tcx: TyCtxt<'_>, def_id: DefId) -> ty::AdtDef<'_> {
}
_ => bug!(),
};
- tcx.alloc_adt_def(def_id.to_def_id(), kind, variants, repr)
+ tcx.mk_adt_def(def_id.to_def_id(), kind, variants, repr)
}
fn trait_def(tcx: TyCtxt<'_>, def_id: DefId) -> ty::TraitDef {
@@ -930,9 +932,10 @@ fn trait_def(tcx: TyCtxt<'_>, def_id: DefId) -> ty::TraitDef {
}
let is_marker = tcx.has_attr(def_id, sym::marker);
+ let rustc_coinductive = tcx.has_attr(def_id, sym::rustc_coinductive);
let skip_array_during_method_dispatch =
tcx.has_attr(def_id, sym::rustc_skip_array_during_method_dispatch);
- let spec_kind = if tcx.has_attr(def_id, sym::rustc_unsafe_specialization_marker) {
+ let specialization_kind = if tcx.has_attr(def_id, sym::rustc_unsafe_specialization_marker) {
ty::trait_def::TraitSpecializationKind::Marker
} else if tcx.has_attr(def_id, sym::rustc_specialization_trait) {
ty::trait_def::TraitSpecializationKind::AlwaysApplicable
@@ -1032,16 +1035,17 @@ fn trait_def(tcx: TyCtxt<'_>, def_id: DefId) -> ty::TraitDef {
no_dups.then_some(list)
});
- ty::TraitDef::new(
+ ty::TraitDef {
def_id,
unsafety,
paren_sugar,
- is_auto,
+ has_auto_impl: is_auto,
is_marker,
+ is_coinductive: rustc_coinductive || is_auto,
skip_array_during_method_dispatch,
- spec_kind,
+ specialization_kind,
must_implement_one_of,
- )
+ }
}
fn are_suggestable_generic_args(generic_args: &[hir::GenericArg<'_>]) -> bool {
@@ -1087,7 +1091,7 @@ pub fn get_infer_ret_ty<'hir>(output: &'hir hir::FnRetTy<'hir>) -> Option<&'hir
}
#[instrument(level = "debug", skip(tcx))]
-fn fn_sig(tcx: TyCtxt<'_>, def_id: DefId) -> ty::PolyFnSig<'_> {
+fn fn_sig(tcx: TyCtxt<'_>, def_id: DefId) -> ty::EarlyBinder<ty::PolyFnSig<'_>> {
use rustc_hir::Node::*;
use rustc_hir::*;
@@ -1096,7 +1100,7 @@ fn fn_sig(tcx: TyCtxt<'_>, def_id: DefId) -> ty::PolyFnSig<'_> {
let icx = ItemCtxt::new(tcx, def_id.to_def_id());
- match tcx.hir().get(hir_id) {
+ let output = match tcx.hir().get(hir_id) {
TraitItem(hir::TraitItem {
kind: TraitItemKind::Fn(sig, TraitFn::Provided(_)),
generics,
@@ -1139,8 +1143,8 @@ fn fn_sig(tcx: TyCtxt<'_>, def_id: DefId) -> ty::PolyFnSig<'_> {
}
Ctor(data) | Variant(hir::Variant { data, .. }) if data.ctor().is_some() => {
- let ty = tcx.type_of(tcx.hir().get_parent_item(hir_id));
- let inputs = data.fields().iter().map(|f| tcx.type_of(f.def_id));
+ let ty = tcx.type_of(tcx.hir().get_parent_item(hir_id)).subst_identity();
+ let inputs = data.fields().iter().map(|f| tcx.type_of(f.def_id).subst_identity());
ty::Binder::dummy(tcx.mk_fn_sig(
inputs,
ty,
@@ -1169,7 +1173,8 @@ fn fn_sig(tcx: TyCtxt<'_>, def_id: DefId) -> ty::PolyFnSig<'_> {
x => {
bug!("unexpected sort of node in fn_sig(): {:?}", x);
}
- }
+ };
+ ty::EarlyBinder(output)
}
fn infer_return_ty_for_fn_sig<'tcx>(
@@ -1194,28 +1199,22 @@ fn infer_return_ty_for_fn_sig<'tcx>(
visitor.visit_ty(ty);
let mut diag = bad_placeholder(tcx, visitor.0, "return type");
let ret_ty = fn_sig.output();
- if ret_ty.is_suggestable(tcx, false) {
+ if let Some(ret_ty) = ret_ty.make_suggestable(tcx, false) {
diag.span_suggestion(
ty.span,
"replace with the correct return type",
ret_ty,
Applicability::MachineApplicable,
);
- } else if matches!(ret_ty.kind(), ty::FnDef(..)) {
- let fn_sig = ret_ty.fn_sig(tcx);
- if fn_sig
- .skip_binder()
- .inputs_and_output
- .iter()
- .all(|t| t.is_suggestable(tcx, false))
- {
- diag.span_suggestion(
- ty.span,
- "replace with the correct return type",
- fn_sig,
- Applicability::MachineApplicable,
- );
- }
+ } else if matches!(ret_ty.kind(), ty::FnDef(..))
+ && let Some(fn_sig) = ret_ty.fn_sig(tcx).make_suggestable(tcx, false)
+ {
+ diag.span_suggestion(
+ ty.span,
+ "replace with the correct return type",
+ fn_sig,
+ Applicability::MachineApplicable,
+ );
} else if let Some(sugg) = suggest_impl_trait(tcx, ret_ty, ty.span, hir_id, def_id) {
diag.span_suggestion(
ty.span,
@@ -1248,11 +1247,12 @@ fn infer_return_ty_for_fn_sig<'tcx>(
}
}
+// FIXME(vincenzopalazzo): remove the hir item when the refactoring is stable
fn suggest_impl_trait<'tcx>(
tcx: TyCtxt<'tcx>,
ret_ty: Ty<'tcx>,
span: Span,
- hir_id: hir::HirId,
+ _hir_id: hir::HirId,
def_id: LocalDefId,
) -> Option<String> {
let format_as_assoc: fn(_, _, _, _, _) -> _ =
@@ -1274,9 +1274,7 @@ fn suggest_impl_trait<'tcx>(
let trait_name = tcx.item_name(trait_def_id);
let args_tuple = substs.type_at(1);
let ty::Tuple(types) = *args_tuple.kind() else { return None; };
- if !types.is_suggestable(tcx, false) {
- return None;
- }
+ let types = types.make_suggestable(tcx, false)?;
let maybe_ret =
if item_ty.is_unit() { String::new() } else { format!(" -> {item_ty}") };
Some(format!(
@@ -1324,14 +1322,14 @@ fn suggest_impl_trait<'tcx>(
}
let ocx = ObligationCtxt::new_in_snapshot(&infcx);
let item_ty = ocx.normalize(
- &ObligationCause::misc(span, hir_id),
+ &ObligationCause::misc(span, def_id),
param_env,
tcx.mk_projection(assoc_item_def_id, substs),
);
// FIXME(compiler-errors): We may benefit from resolving regions here.
if ocx.select_where_possible().is_empty()
&& let item_ty = infcx.resolve_vars_if_possible(item_ty)
- && item_ty.is_suggestable(tcx, false)
+ && let Some(item_ty) = item_ty.make_suggestable(tcx, false)
&& let Some(sugg) = formatter(tcx, infcx.resolve_vars_if_possible(substs), trait_def_id, assoc_item_def_id, item_ty)
{
return Some(sugg);
@@ -1342,13 +1340,12 @@ fn suggest_impl_trait<'tcx>(
fn impl_trait_ref(tcx: TyCtxt<'_>, def_id: DefId) -> Option<ty::EarlyBinder<ty::TraitRef<'_>>> {
let icx = ItemCtxt::new(tcx, def_id);
- let item = tcx.hir().expect_item(def_id.expect_local());
- let hir::ItemKind::Impl(impl_) = item.kind else { bug!() };
+ let impl_ = tcx.hir().expect_item(def_id.expect_local()).expect_impl();
impl_
.of_trait
.as_ref()
.map(|ast_trait_ref| {
- let selfty = tcx.type_of(def_id);
+ let selfty = tcx.type_of(def_id).subst_identity();
icx.astconv().instantiate_mono_trait_ref(
ast_trait_ref,
selfty,
diff --git a/compiler/rustc_hir_analysis/src/collect/generics_of.rs b/compiler/rustc_hir_analysis/src/collect/generics_of.rs
index 014ee9fcc..127d4fa90 100644
--- a/compiler/rustc_hir_analysis/src/collect/generics_of.rs
+++ b/compiler/rustc_hir_analysis/src/collect/generics_of.rs
@@ -1,4 +1,4 @@
-use crate::middle::resolve_lifetime as rl;
+use crate::middle::resolve_bound_vars as rbv;
use hir::{
intravisit::{self, Visitor},
GenericParamKind, HirId, Node,
@@ -394,10 +394,16 @@ fn has_late_bound_regions<'tcx>(tcx: TyCtxt<'tcx>, node: Node<'tcx>) -> Option<S
return;
}
- match self.tcx.named_region(lt.hir_id) {
- Some(rl::Region::Static | rl::Region::EarlyBound(..)) => {}
- Some(rl::Region::LateBound(debruijn, _, _)) if debruijn < self.outer_index => {}
- Some(rl::Region::LateBound(..) | rl::Region::Free(..)) | None => {
+ match self.tcx.named_bound_var(lt.hir_id) {
+ Some(rbv::ResolvedArg::StaticLifetime | rbv::ResolvedArg::EarlyBound(..)) => {}
+ Some(rbv::ResolvedArg::LateBound(debruijn, _, _))
+ if debruijn < self.outer_index => {}
+ Some(
+ rbv::ResolvedArg::LateBound(..)
+ | rbv::ResolvedArg::Free(..)
+ | rbv::ResolvedArg::Error(_),
+ )
+ | None => {
self.has_late_bound_regions = Some(lt.ident.span);
}
}
diff --git a/compiler/rustc_hir_analysis/src/collect/item_bounds.rs b/compiler/rustc_hir_analysis/src/collect/item_bounds.rs
index 8d479f1c3..9cf3ff65a 100644
--- a/compiler/rustc_hir_analysis/src/collect/item_bounds.rs
+++ b/compiler/rustc_hir_analysis/src/collect/item_bounds.rs
@@ -103,7 +103,7 @@ pub(super) fn item_bounds(
tcx: TyCtxt<'_>,
def_id: DefId,
) -> ty::EarlyBinder<&'_ ty::List<ty::Predicate<'_>>> {
- let bounds = tcx.mk_predicates(
+ let bounds = tcx.mk_predicates_from_iter(
util::elaborate_predicates(
tcx,
tcx.explicit_item_bounds(def_id).iter().map(|&(bound, _span)| bound),
diff --git a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
index 46b277d98..2badd66e3 100644
--- a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
+++ b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
@@ -9,8 +9,8 @@ use rustc_hir::def::DefKind;
use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_hir::intravisit::{self, Visitor};
use rustc_middle::ty::subst::InternalSubsts;
-use rustc_middle::ty::ToPredicate;
use rustc_middle::ty::{self, Ty, TyCtxt};
+use rustc_middle::ty::{GenericPredicates, ToPredicate};
use rustc_span::symbol::{sym, Ident};
use rustc_span::{Span, DUMMY_SP};
@@ -151,7 +151,8 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericP
trace!(?generics);
// Collect the predicates that were written inline by the user on each
- // type parameter (e.g., `<T: Foo>`).
+ // type parameter (e.g., `<T: Foo>`). Also add `ConstArgHasType` predicates
+ // for each const parameter.
for param in ast_generics.params {
match param.kind {
// We already dealt with early bound lifetimes above.
@@ -175,7 +176,19 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericP
trace!(?predicates);
}
GenericParamKind::Const { .. } => {
- // Bounds on const parameters are currently not possible.
+ let name = param.name.ident().name;
+ let param_const = ty::ParamConst::new(index, name);
+
+ let ct_ty = tcx.type_of(param.def_id.to_def_id()).subst_identity();
+
+ let ct = tcx.mk_const(param_const, ct_ty);
+
+ let predicate = ty::Binder::dummy(ty::PredicateKind::Clause(
+ ty::Clause::ConstArgHasType(ct, ct_ty),
+ ))
+ .to_predicate(tcx);
+ predicates.insert((predicate, param.span));
+
index += 1;
}
}
@@ -251,7 +264,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericP
// in trait checking. See `setup_constraining_predicates`
// for details.
if let Node::Item(&Item { kind: ItemKind::Impl { .. }, .. }) = node {
- let self_ty = tcx.type_of(def_id);
+ let self_ty = tcx.type_of(def_id).subst_identity();
let trait_ref = tcx.impl_trait_ref(def_id).map(ty::EarlyBinder::subst_identity);
cgp::setup_constraining_predicates(
tcx,
@@ -280,15 +293,15 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericP
}
let hir::GenericParamKind::Lifetime { .. } = duplicate.kind else { continue };
- let dup_def = tcx.hir().local_def_id(duplicate.hir_id).to_def_id();
+ let dup_def = duplicate.def_id.to_def_id();
let Some(dup_index) = generics.param_def_id_to_index(tcx, dup_def) else { bug!() };
- let dup_region = tcx.mk_region(ty::ReEarlyBound(ty::EarlyBoundRegion {
+ let dup_region = tcx.mk_re_early_bound(ty::EarlyBoundRegion {
def_id: dup_def,
index: dup_index,
name: duplicate.name.ident().name,
- }));
+ });
predicates.push((
ty::Binder::dummy(ty::PredicateKind::Clause(ty::Clause::RegionOutlives(
ty::OutlivesPredicate(orig_region, dup_region),
@@ -439,7 +452,9 @@ pub(super) fn explicit_predicates_of<'tcx>(
let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local());
let parent_def_id = tcx.hir().get_parent_item(hir_id);
- if tcx.hir().opt_const_param_default_param_def_id(hir_id).is_some() {
+ if let Some(defaulted_param_def_id) =
+ tcx.hir().opt_const_param_default_param_def_id(hir_id)
+ {
// 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)
@@ -452,7 +467,39 @@ pub(super) fn explicit_predicates_of<'tcx>(
//
// In the above code we want the anon const to have predicates in its param env for `T: Trait`
// and we would be calling `explicit_predicates_of(Foo)` here
- return tcx.explicit_predicates_of(parent_def_id);
+ let parent_preds = tcx.explicit_predicates_of(parent_def_id);
+
+ // If we dont filter out `ConstArgHasType` predicates then every single defaulted const parameter
+ // will ICE because of #106994. FIXME(generic_const_exprs): remove this when a more general solution
+ // to #106994 is implemented.
+ let filtered_predicates = parent_preds
+ .predicates
+ .into_iter()
+ .filter(|(pred, _)| {
+ if let ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(ct, _)) =
+ pred.kind().skip_binder()
+ {
+ match ct.kind() {
+ ty::ConstKind::Param(param_const) => {
+ let defaulted_param_idx = tcx
+ .generics_of(parent_def_id)
+ .param_def_id_to_index[&defaulted_param_def_id.to_def_id()];
+ param_const.index < defaulted_param_idx
+ }
+ _ => bug!(
+ "`ConstArgHasType` in `predicates_of`\
+ that isn't a `Param` const"
+ ),
+ }
+ } else {
+ true
+ }
+ })
+ .cloned();
+ return GenericPredicates {
+ parent: parent_preds.parent,
+ predicates: { tcx.arena.alloc_from_iter(filtered_predicates) },
+ };
}
let parent_def_kind = tcx.def_kind(parent_def_id);
diff --git a/compiler/rustc_hir_analysis/src/collect/lifetimes.rs b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
index 359122d4e..65a9052a6 100644
--- a/compiler/rustc_hir_analysis/src/collect/lifetimes.rs
+++ b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
@@ -16,67 +16,72 @@ use rustc_hir::intravisit::{self, Visitor};
use rustc_hir::{GenericArg, GenericParam, GenericParamKind, HirIdMap, LifetimeName, Node};
use rustc_middle::bug;
use rustc_middle::hir::nested_filter;
-use rustc_middle::middle::resolve_lifetime::*;
+use rustc_middle::middle::resolve_bound_vars::*;
use rustc_middle::ty::{self, DefIdTree, TyCtxt, TypeSuperVisitable, TypeVisitor};
+use rustc_session::lint;
use rustc_span::def_id::DefId;
use rustc_span::symbol::{sym, Ident};
use rustc_span::Span;
use std::fmt;
+use crate::errors;
+
trait RegionExt {
- fn early(param: &GenericParam<'_>) -> (LocalDefId, Region);
+ fn early(param: &GenericParam<'_>) -> (LocalDefId, ResolvedArg);
- fn late(index: u32, param: &GenericParam<'_>) -> (LocalDefId, Region);
+ fn late(index: u32, param: &GenericParam<'_>) -> (LocalDefId, ResolvedArg);
fn id(&self) -> Option<DefId>;
- fn shifted(self, amount: u32) -> Region;
+ fn shifted(self, amount: u32) -> ResolvedArg;
}
-impl RegionExt for Region {
- fn early(param: &GenericParam<'_>) -> (LocalDefId, Region) {
- debug!("Region::early: def_id={:?}", param.def_id);
- (param.def_id, Region::EarlyBound(param.def_id.to_def_id()))
+impl RegionExt for ResolvedArg {
+ fn early(param: &GenericParam<'_>) -> (LocalDefId, ResolvedArg) {
+ debug!("ResolvedArg::early: def_id={:?}", param.def_id);
+ (param.def_id, ResolvedArg::EarlyBound(param.def_id.to_def_id()))
}
- fn late(idx: u32, param: &GenericParam<'_>) -> (LocalDefId, Region) {
+ fn late(idx: u32, param: &GenericParam<'_>) -> (LocalDefId, ResolvedArg) {
let depth = ty::INNERMOST;
debug!(
- "Region::late: idx={:?}, param={:?} depth={:?} def_id={:?}",
+ "ResolvedArg::late: idx={:?}, param={:?} depth={:?} def_id={:?}",
idx, param, depth, param.def_id,
);
- (param.def_id, Region::LateBound(depth, idx, param.def_id.to_def_id()))
+ (param.def_id, ResolvedArg::LateBound(depth, idx, param.def_id.to_def_id()))
}
fn id(&self) -> Option<DefId> {
match *self {
- Region::Static => None,
+ ResolvedArg::StaticLifetime | ResolvedArg::Error(_) => None,
- Region::EarlyBound(id) | Region::LateBound(_, _, id) | Region::Free(_, id) => Some(id),
+ ResolvedArg::EarlyBound(id)
+ | ResolvedArg::LateBound(_, _, id)
+ | ResolvedArg::Free(_, id) => Some(id),
}
}
- fn shifted(self, amount: u32) -> Region {
+ fn shifted(self, amount: u32) -> ResolvedArg {
match self {
- Region::LateBound(debruijn, idx, id) => {
- Region::LateBound(debruijn.shifted_in(amount), idx, id)
+ ResolvedArg::LateBound(debruijn, idx, id) => {
+ ResolvedArg::LateBound(debruijn.shifted_in(amount), idx, id)
}
_ => self,
}
}
}
-/// Maps the id of each lifetime reference to the lifetime decl
+/// Maps the id of each bound variable reference to the variable decl
/// that it corresponds to.
///
-/// FIXME. This struct gets converted to a `ResolveLifetimes` for
+/// FIXME. This struct gets converted to a `ResolveBoundVars` for
/// actual use. It has the same data, but indexed by `LocalDefId`. This
/// is silly.
#[derive(Debug, Default)]
-struct NamedRegionMap {
- // maps from every use of a named (not anonymous) lifetime to a
- // `Region` describing how that region is bound
- defs: HirIdMap<Region>,
+struct NamedVarMap {
+ // maps from every use of a named (not anonymous) bound var to a
+ // `ResolvedArg` describing how that variable is bound
+ defs: HirIdMap<ResolvedArg>,
// Maps relevant hir items to the bound vars on them. These include:
// - function defs
@@ -87,9 +92,9 @@ struct NamedRegionMap {
late_bound_vars: HirIdMap<Vec<ty::BoundVariableKind>>,
}
-struct LifetimeContext<'a, 'tcx> {
+struct BoundVarContext<'a, 'tcx> {
tcx: TyCtxt<'tcx>,
- map: &'a mut NamedRegionMap,
+ map: &'a mut NamedVarMap,
scope: ScopeRef<'a>,
}
@@ -102,7 +107,7 @@ enum Scope<'a> {
Binder {
/// We use an IndexMap here because we want these lifetimes in order
/// for diagnostics.
- lifetimes: FxIndexMap<LocalDefId, Region>,
+ bound_vars: FxIndexMap<LocalDefId, ResolvedArg>,
scope_type: BinderScopeType,
@@ -141,7 +146,7 @@ enum Scope<'a> {
/// inferred in a function body or potentially error outside one),
/// for the default choice of lifetime in a trait object type.
ObjectLifetimeDefault {
- lifetime: Option<Region>,
+ lifetime: Option<ResolvedArg>,
s: ScopeRef<'a>,
},
@@ -150,7 +155,7 @@ enum Scope<'a> {
/// lifetimes encountered when identifying the trait that an associated type
/// is declared on.
Supertrait {
- lifetimes: Vec<ty::BoundVariableKind>,
+ bound_vars: Vec<ty::BoundVariableKind>,
s: ScopeRef<'a>,
},
@@ -158,6 +163,15 @@ enum Scope<'a> {
s: ScopeRef<'a>,
},
+ /// Disallows capturing non-lifetime binders from parent scopes.
+ ///
+ /// This is necessary for something like `for<T> [(); { /* references T */ }]:`,
+ /// since we don't do something more correct like replacing any captured
+ /// late-bound vars with early-bound params in the const's own generics.
+ AnonConstBoundary {
+ s: ScopeRef<'a>,
+ },
+
Root {
opt_parent_item: Option<LocalDefId>,
},
@@ -185,9 +199,9 @@ struct TruncatedScopeDebug<'a>(&'a Scope<'a>);
impl<'a> fmt::Debug for TruncatedScopeDebug<'a> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self.0 {
- Scope::Binder { lifetimes, scope_type, hir_id, where_bound_origin, s: _ } => f
+ Scope::Binder { bound_vars, scope_type, hir_id, where_bound_origin, s: _ } => f
.debug_struct("Binder")
- .field("lifetimes", lifetimes)
+ .field("bound_vars", bound_vars)
.field("scope_type", scope_type)
.field("hir_id", hir_id)
.field("where_bound_origin", where_bound_origin)
@@ -202,12 +216,13 @@ impl<'a> fmt::Debug for TruncatedScopeDebug<'a> {
.field("lifetime", lifetime)
.field("s", &"..")
.finish(),
- Scope::Supertrait { lifetimes, s: _ } => f
+ Scope::Supertrait { bound_vars, s: _ } => f
.debug_struct("Supertrait")
- .field("lifetimes", lifetimes)
+ .field("bound_vars", bound_vars)
.field("s", &"..")
.finish(),
Scope::TraitRefBoundary { s: _ } => f.debug_struct("TraitRefBoundary").finish(),
+ Scope::AnonConstBoundary { s: _ } => f.debug_struct("AnonConstBoundary").finish(),
Scope::Root { opt_parent_item } => {
f.debug_struct("Root").field("opt_parent_item", &opt_parent_item).finish()
}
@@ -219,27 +234,27 @@ type ScopeRef<'a> = &'a Scope<'a>;
pub(crate) fn provide(providers: &mut ty::query::Providers) {
*providers = ty::query::Providers {
- resolve_lifetimes,
+ resolve_bound_vars,
- named_region_map: |tcx, id| tcx.resolve_lifetimes(id).defs.get(&id),
+ named_variable_map: |tcx, id| tcx.resolve_bound_vars(id).defs.get(&id),
is_late_bound_map,
object_lifetime_default,
- late_bound_vars_map: |tcx, id| tcx.resolve_lifetimes(id).late_bound_vars.get(&id),
+ late_bound_vars_map: |tcx, id| tcx.resolve_bound_vars(id).late_bound_vars.get(&id),
..*providers
};
}
-/// Computes the `ResolveLifetimes` map that contains data for an entire `Item`.
+/// Computes the `ResolveBoundVars` map that contains data for an entire `Item`.
/// You should not read the result of this query directly, but rather use
-/// `named_region_map`, `is_late_bound_map`, etc.
+/// `named_variable_map`, `is_late_bound_map`, etc.
#[instrument(level = "debug", skip(tcx))]
-fn resolve_lifetimes(tcx: TyCtxt<'_>, local_def_id: hir::OwnerId) -> ResolveLifetimes {
- let mut named_region_map =
- NamedRegionMap { defs: Default::default(), late_bound_vars: Default::default() };
- let mut visitor = LifetimeContext {
+fn resolve_bound_vars(tcx: TyCtxt<'_>, local_def_id: hir::OwnerId) -> ResolveBoundVars {
+ let mut named_variable_map =
+ NamedVarMap { defs: Default::default(), late_bound_vars: Default::default() };
+ let mut visitor = BoundVarContext {
tcx,
- map: &mut named_region_map,
+ map: &mut named_variable_map,
scope: &Scope::Root { opt_parent_item: None },
};
match tcx.hir().owner(local_def_id) {
@@ -260,13 +275,13 @@ fn resolve_lifetimes(tcx: TyCtxt<'_>, local_def_id: hir::OwnerId) -> ResolveLife
hir::OwnerNode::Crate(_) => {}
}
- let mut rl = ResolveLifetimes::default();
+ let mut rl = ResolveBoundVars::default();
- for (hir_id, v) in named_region_map.defs {
+ for (hir_id, v) in named_variable_map.defs {
let map = rl.defs.entry(hir_id.owner).or_default();
map.insert(hir_id.local_id, v);
}
- for (hir_id, v) in named_region_map.late_bound_vars {
+ for (hir_id, v) in named_variable_map.late_bound_vars {
let map = rl.late_bound_vars.entry(hir_id.owner).or_default();
map.insert(hir_id.local_id, v);
}
@@ -276,39 +291,53 @@ fn resolve_lifetimes(tcx: TyCtxt<'_>, local_def_id: hir::OwnerId) -> ResolveLife
rl
}
-fn late_region_as_bound_region(tcx: TyCtxt<'_>, region: &Region) -> ty::BoundVariableKind {
- match region {
- Region::LateBound(_, _, def_id) => {
+fn late_arg_as_bound_arg<'tcx>(
+ tcx: TyCtxt<'tcx>,
+ arg: &ResolvedArg,
+ param: &GenericParam<'tcx>,
+) -> ty::BoundVariableKind {
+ match arg {
+ ResolvedArg::LateBound(_, _, def_id) => {
let name = tcx.hir().name(tcx.hir().local_def_id_to_hir_id(def_id.expect_local()));
- ty::BoundVariableKind::Region(ty::BrNamed(*def_id, name))
+ match param.kind {
+ GenericParamKind::Lifetime { .. } => {
+ ty::BoundVariableKind::Region(ty::BrNamed(*def_id, name))
+ }
+ GenericParamKind::Type { .. } => {
+ ty::BoundVariableKind::Ty(ty::BoundTyKind::Param(*def_id, name))
+ }
+ GenericParamKind::Const { .. } => ty::BoundVariableKind::Const,
+ }
}
- _ => bug!("{:?} is not a late region", region),
+ _ => bug!("{:?} is not a late argument", arg),
}
}
-impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
+impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
/// Returns the binders in scope and the type of `Binder` that should be created for a poly trait ref.
fn poly_trait_ref_binder_info(&mut self) -> (Vec<ty::BoundVariableKind>, BinderScopeType) {
let mut scope = self.scope;
- let mut supertrait_lifetimes = vec![];
+ let mut supertrait_bound_vars = vec![];
loop {
match scope {
Scope::Body { .. } | Scope::Root { .. } => {
break (vec![], BinderScopeType::Normal);
}
- Scope::Elision { s, .. } | Scope::ObjectLifetimeDefault { s, .. } => {
+ Scope::Elision { s, .. }
+ | Scope::ObjectLifetimeDefault { s, .. }
+ | Scope::AnonConstBoundary { s } => {
scope = s;
}
- Scope::Supertrait { s, lifetimes } => {
- supertrait_lifetimes = lifetimes.clone();
+ Scope::Supertrait { s, bound_vars } => {
+ supertrait_bound_vars = bound_vars.clone();
scope = s;
}
Scope::TraitRefBoundary { .. } => {
// We should only see super trait lifetimes if there is a `Binder` above
- assert!(supertrait_lifetimes.is_empty());
+ assert!(supertrait_bound_vars.is_empty());
break (vec![], BinderScopeType::Normal);
}
@@ -316,14 +345,64 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
// Nested poly trait refs have the binders concatenated
let mut full_binders =
self.map.late_bound_vars.entry(*hir_id).or_default().clone();
- full_binders.extend(supertrait_lifetimes.into_iter());
+ full_binders.extend(supertrait_bound_vars.into_iter());
break (full_binders, BinderScopeType::Concatenating);
}
}
}
}
+
+ fn visit_poly_trait_ref_inner(
+ &mut self,
+ trait_ref: &'tcx hir::PolyTraitRef<'tcx>,
+ non_lifetime_binder_allowed: NonLifetimeBinderAllowed,
+ ) {
+ debug!("visit_poly_trait_ref(trait_ref={:?})", trait_ref);
+
+ let (mut binders, scope_type) = self.poly_trait_ref_binder_info();
+
+ let initial_bound_vars = binders.len() as u32;
+ let mut bound_vars: FxIndexMap<LocalDefId, ResolvedArg> = FxIndexMap::default();
+ let binders_iter =
+ trait_ref.bound_generic_params.iter().enumerate().map(|(late_bound_idx, param)| {
+ let pair = ResolvedArg::late(initial_bound_vars + late_bound_idx as u32, param);
+ let r = late_arg_as_bound_arg(self.tcx, &pair.1, param);
+ bound_vars.insert(pair.0, pair.1);
+ r
+ });
+ binders.extend(binders_iter);
+
+ if let NonLifetimeBinderAllowed::Deny(where_) = non_lifetime_binder_allowed {
+ deny_non_region_late_bound(self.tcx, &mut bound_vars, where_);
+ }
+
+ debug!(?binders);
+ self.record_late_bound_vars(trait_ref.trait_ref.hir_ref_id, binders);
+
+ // Always introduce a scope here, even if this is in a where clause and
+ // we introduced the binders around the bounded Ty. In that case, we
+ // just reuse the concatenation functionality also present in nested trait
+ // refs.
+ let scope = Scope::Binder {
+ hir_id: trait_ref.trait_ref.hir_ref_id,
+ bound_vars,
+ s: self.scope,
+ scope_type,
+ where_bound_origin: None,
+ };
+ self.with(scope, |this| {
+ walk_list!(this, visit_generic_param, trait_ref.bound_generic_params);
+ this.visit_trait_ref(&trait_ref.trait_ref);
+ });
+ }
+}
+
+enum NonLifetimeBinderAllowed {
+ Deny(&'static str),
+ Allow,
}
-impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
+
+impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> {
type NestedFilter = nested_filter::OnlyBodies;
fn nested_visit_map(&mut self) -> Self::Map {
@@ -386,22 +465,23 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
}
}
- let (lifetimes, binders): (FxIndexMap<LocalDefId, Region>, Vec<_>) =
+ let (mut bound_vars, binders): (FxIndexMap<LocalDefId, ResolvedArg>, Vec<_>) =
bound_generic_params
.iter()
- .filter(|param| matches!(param.kind, GenericParamKind::Lifetime { .. }))
.enumerate()
.map(|(late_bound_idx, param)| {
- let pair = Region::late(late_bound_idx as u32, param);
- let r = late_region_as_bound_region(self.tcx, &pair.1);
+ let pair = ResolvedArg::late(late_bound_idx as u32, param);
+ let r = late_arg_as_bound_arg(self.tcx, &pair.1, param);
(pair, r)
})
.unzip();
+ deny_non_region_late_bound(self.tcx, &mut bound_vars, "closures");
+
self.record_late_bound_vars(e.hir_id, binders);
let scope = Scope::Binder {
hir_id: e.hir_id,
- lifetimes,
+ bound_vars,
s: self.scope,
scope_type: BinderScopeType::Normal,
where_bound_origin: None,
@@ -461,7 +541,8 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
// conservatively add all resolved lifetimes. Otherwise we run into problems in
// cases like `type Foo<'a> = impl Bar<As = impl Baz + 'a>`.
let parent_item = self.tcx.hir().get_parent_item(item.hir_id());
- let resolved_lifetimes: &ResolveLifetimes = self.tcx.resolve_lifetimes(parent_item);
+ let resolved_lifetimes: &ResolveBoundVars =
+ self.tcx.resolve_bound_vars(parent_item);
// We need to add *all* deps, since opaque tys may want them from *us*
for (&owner, defs) in resolved_lifetimes.defs.iter() {
defs.iter().for_each(|(&local_id, region)| {
@@ -478,35 +559,33 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
}
}
hir::ItemKind::OpaqueTy(hir::OpaqueTy {
- origin: hir::OpaqueTyOrigin::FnReturn(_) | hir::OpaqueTyOrigin::AsyncFn(_),
+ origin: hir::OpaqueTyOrigin::FnReturn(parent) | hir::OpaqueTyOrigin::AsyncFn(parent),
generics,
..
}) => {
// We want to start our early-bound indices at the end of the parent scope,
// not including any parent `impl Trait`s.
- let mut lifetimes = FxIndexMap::default();
+ let mut bound_vars = FxIndexMap::default();
debug!(?generics.params);
for param in generics.params {
- match param.kind {
- GenericParamKind::Lifetime { .. } => {
- let (def_id, reg) = Region::early(&param);
- lifetimes.insert(def_id, reg);
- }
- GenericParamKind::Type { .. } | GenericParamKind::Const { .. } => {}
- }
+ let (def_id, reg) = ResolvedArg::early(&param);
+ bound_vars.insert(def_id, reg);
}
- let scope = Scope::Binder {
- hir_id: item.hir_id(),
- lifetimes,
- s: self.scope,
- scope_type: BinderScopeType::Normal,
- where_bound_origin: None,
- };
+ let scope = Scope::Root { opt_parent_item: Some(parent) };
self.with(scope, |this| {
- let scope = Scope::TraitRefBoundary { s: this.scope };
- this.with(scope, |this| intravisit::walk_item(this, item))
- });
+ let scope = Scope::Binder {
+ hir_id: item.hir_id(),
+ bound_vars,
+ s: this.scope,
+ scope_type: BinderScopeType::Normal,
+ where_bound_origin: None,
+ };
+ this.with(scope, |this| {
+ let scope = Scope::TraitRefBoundary { s: this.scope };
+ this.with(scope, |this| intravisit::walk_item(this, item))
+ });
+ })
}
hir::ItemKind::TyAlias(_, generics)
| hir::ItemKind::Enum(_, generics)
@@ -516,18 +595,11 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
| hir::ItemKind::TraitAlias(generics, ..)
| hir::ItemKind::Impl(&hir::Impl { generics, .. }) => {
// These kinds of items have only early-bound lifetime parameters.
- let lifetimes = generics
- .params
- .iter()
- .filter_map(|param| match param.kind {
- GenericParamKind::Lifetime { .. } => Some(Region::early(param)),
- GenericParamKind::Type { .. } | GenericParamKind::Const { .. } => None,
- })
- .collect();
+ let bound_vars = generics.params.iter().map(ResolvedArg::early).collect();
self.record_late_bound_vars(item.hir_id(), vec![]);
let scope = Scope::Binder {
hir_id: item.hir_id(),
- lifetimes,
+ bound_vars,
scope_type: BinderScopeType::Normal,
s: self.scope,
where_bound_origin: None,
@@ -562,21 +634,23 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
fn visit_ty(&mut self, ty: &'tcx hir::Ty<'tcx>) {
match ty.kind {
hir::TyKind::BareFn(c) => {
- let (lifetimes, binders): (FxIndexMap<LocalDefId, Region>, Vec<_>) = c
+ let (mut bound_vars, binders): (FxIndexMap<LocalDefId, ResolvedArg>, Vec<_>) = c
.generic_params
.iter()
- .filter(|param| matches!(param.kind, GenericParamKind::Lifetime { .. }))
.enumerate()
.map(|(late_bound_idx, param)| {
- let pair = Region::late(late_bound_idx as u32, param);
- let r = late_region_as_bound_region(self.tcx, &pair.1);
+ let pair = ResolvedArg::late(late_bound_idx as u32, param);
+ let r = late_arg_as_bound_arg(self.tcx, &pair.1, param);
(pair, r)
})
.unzip();
+
+ deny_non_region_late_bound(self.tcx, &mut bound_vars, "function pointer types");
+
self.record_late_bound_vars(ty.hir_id, binders);
let scope = Scope::Binder {
hir_id: ty.hir_id,
- lifetimes,
+ bound_vars,
s: self.scope,
scope_type: BinderScopeType::Normal,
where_bound_origin: None,
@@ -592,7 +666,10 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
let scope = Scope::TraitRefBoundary { s: self.scope };
self.with(scope, |this| {
for bound in bounds {
- this.visit_poly_trait_ref(bound);
+ this.visit_poly_trait_ref_inner(
+ bound,
+ NonLifetimeBinderAllowed::Deny("trait object types"),
+ );
}
});
match lifetime.res {
@@ -674,7 +751,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
// well-supported at the moment, so this doesn't work.
// In the future, this should be fixed and this error should be removed.
let def = self.map.defs.get(&lifetime.hir_id).cloned();
- let Some(Region::LateBound(_, _, def_id)) = def else {
+ let Some(ResolvedArg::LateBound(_, _, def_id)) = def else {
continue
};
let Some(def_id) = def_id.as_local() else {
@@ -722,18 +799,11 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
}
Type(bounds, ty) => {
let generics = &trait_item.generics;
- let lifetimes = generics
- .params
- .iter()
- .filter_map(|param| match param.kind {
- GenericParamKind::Lifetime { .. } => Some(Region::early(param)),
- GenericParamKind::Type { .. } | GenericParamKind::Const { .. } => None,
- })
- .collect();
+ let bound_vars = generics.params.iter().map(ResolvedArg::early).collect();
self.record_late_bound_vars(trait_item.hir_id(), vec![]);
let scope = Scope::Binder {
hir_id: trait_item.hir_id(),
- lifetimes,
+ bound_vars,
s: self.scope,
scope_type: BinderScopeType::Normal,
where_bound_origin: None,
@@ -768,18 +838,12 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
}),
Type(ty) => {
let generics = &impl_item.generics;
- let lifetimes: FxIndexMap<LocalDefId, Region> = generics
- .params
- .iter()
- .filter_map(|param| match param.kind {
- GenericParamKind::Lifetime { .. } => Some(Region::early(param)),
- GenericParamKind::Const { .. } | GenericParamKind::Type { .. } => None,
- })
- .collect();
+ let bound_vars: FxIndexMap<LocalDefId, ResolvedArg> =
+ generics.params.iter().map(ResolvedArg::early).collect();
self.record_late_bound_vars(impl_item.hir_id(), vec![]);
let scope = Scope::Binder {
hir_id: impl_item.hir_id(),
- lifetimes,
+ bound_vars,
s: self.scope,
scope_type: BinderScopeType::Normal,
where_bound_origin: None,
@@ -803,7 +867,9 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
#[instrument(level = "debug", skip(self))]
fn visit_lifetime(&mut self, lifetime_ref: &'tcx hir::Lifetime) {
match lifetime_ref.res {
- hir::LifetimeName::Static => self.insert_lifetime(lifetime_ref, Region::Static),
+ hir::LifetimeName::Static => {
+ self.insert_lifetime(lifetime_ref, ResolvedArg::StaticLifetime)
+ }
hir::LifetimeName::Param(param_def_id) => {
self.resolve_lifetime_ref(param_def_id, lifetime_ref)
}
@@ -814,13 +880,16 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
}
}
- fn visit_path(&mut self, path: &hir::Path<'tcx>, _: hir::HirId) {
+ fn visit_path(&mut self, path: &hir::Path<'tcx>, hir_id: hir::HirId) {
for (i, segment) in path.segments.iter().enumerate() {
let depth = path.segments.len() - i - 1;
if let Some(args) = segment.args {
self.visit_segment_args(path.res, depth, args);
}
}
+ if let Res::Def(DefKind::TyParam | DefKind::ConstParam, param_def_id) = path.res {
+ self.resolve_type_ref(param_def_id.expect_local(), hir_id);
+ }
}
fn visit_fn(
@@ -829,7 +898,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
fd: &'tcx hir::FnDecl<'tcx>,
body_id: hir::BodyId,
_: Span,
- _: hir::HirId,
+ _: LocalDefId,
) {
let output = match fd.output {
hir::FnRetTy::DefaultReturn(_) => None,
@@ -869,24 +938,16 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
origin,
..
}) => {
- let lifetimes: FxIndexMap<LocalDefId, Region> =
+ let (bound_vars, binders): (FxIndexMap<LocalDefId, ResolvedArg>, Vec<_>) =
bound_generic_params
.iter()
- .filter(|param| {
- matches!(param.kind, GenericParamKind::Lifetime { .. })
- })
.enumerate()
.map(|(late_bound_idx, param)| {
- Region::late(late_bound_idx as u32, param)
- })
- .collect();
- let binders: Vec<_> =
- lifetimes
- .iter()
- .map(|(_, region)| {
- late_region_as_bound_region(this.tcx, region)
+ let pair = ResolvedArg::late(late_bound_idx as u32, param);
+ let r = late_arg_as_bound_arg(this.tcx, &pair.1, param);
+ (pair, r)
})
- .collect();
+ .unzip();
this.record_late_bound_vars(hir_id, binders.clone());
// Even if there are no lifetimes defined here, we still wrap it in a binder
// scope. If there happens to be a nested poly trait ref (an error), that
@@ -894,7 +955,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
// being wrong.
let scope = Scope::Binder {
hir_id,
- lifetimes,
+ bound_vars,
s: this.scope,
scope_type: BinderScopeType::Normal,
where_bound_origin: Some(origin),
@@ -920,21 +981,23 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
if lt.res != hir::LifetimeName::Static {
continue;
}
- this.insert_lifetime(lt, Region::Static);
- this.tcx
- .sess
- .struct_span_warn(
- lifetime.ident.span,
- &format!(
- "unnecessary lifetime parameter `{}`",
+ this.insert_lifetime(lt, ResolvedArg::StaticLifetime);
+ this.tcx.struct_span_lint_hir(
+ lint::builtin::UNUSED_LIFETIMES,
+ lifetime.hir_id,
+ lifetime.ident.span,
+ format!(
+ "unnecessary lifetime parameter `{}`",
+ lifetime.ident
+ ),
+ |lint| {
+ let help = &format!(
+ "you can use the `'static` lifetime directly, in place of `{}`",
lifetime.ident,
- ),
- )
- .help(&format!(
- "you can use the `'static` lifetime directly, in place of `{}`",
- lifetime.ident,
- ))
- .emit();
+ );
+ lint.help(help)
+ },
+ );
}
}
}
@@ -964,7 +1027,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
self.record_late_bound_vars(*hir_id, binders);
let scope = Scope::Binder {
hir_id: *hir_id,
- lifetimes: FxIndexMap::default(),
+ bound_vars: FxIndexMap::default(),
s: self.scope,
scope_type,
where_bound_origin: None,
@@ -978,42 +1041,12 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
}
fn visit_poly_trait_ref(&mut self, trait_ref: &'tcx hir::PolyTraitRef<'tcx>) {
- debug!("visit_poly_trait_ref(trait_ref={:?})", trait_ref);
-
- let (mut binders, scope_type) = self.poly_trait_ref_binder_info();
-
- let initial_bound_vars = binders.len() as u32;
- let mut lifetimes: FxIndexMap<LocalDefId, Region> = FxIndexMap::default();
- let binders_iter = trait_ref
- .bound_generic_params
- .iter()
- .filter(|param| matches!(param.kind, GenericParamKind::Lifetime { .. }))
- .enumerate()
- .map(|(late_bound_idx, param)| {
- let pair = Region::late(initial_bound_vars + late_bound_idx as u32, param);
- let r = late_region_as_bound_region(self.tcx, &pair.1);
- lifetimes.insert(pair.0, pair.1);
- r
- });
- binders.extend(binders_iter);
-
- debug!(?binders);
- self.record_late_bound_vars(trait_ref.trait_ref.hir_ref_id, binders);
+ self.visit_poly_trait_ref_inner(trait_ref, NonLifetimeBinderAllowed::Allow);
+ }
- // Always introduce a scope here, even if this is in a where clause and
- // we introduced the binders around the bounded Ty. In that case, we
- // just reuse the concatenation functionality also present in nested trait
- // refs.
- let scope = Scope::Binder {
- hir_id: trait_ref.trait_ref.hir_ref_id,
- lifetimes,
- s: self.scope,
- scope_type,
- where_bound_origin: None,
- };
- self.with(scope, |this| {
- walk_list!(this, visit_generic_param, trait_ref.bound_generic_params);
- this.visit_trait_ref(&trait_ref.trait_ref);
+ fn visit_anon_const(&mut self, c: &'tcx hir::AnonConst) {
+ self.with(Scope::AnonConstBoundary { s: self.scope }, |this| {
+ intravisit::walk_anon_const(this, c);
});
}
}
@@ -1021,55 +1054,63 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
fn object_lifetime_default(tcx: TyCtxt<'_>, param_def_id: DefId) -> ObjectLifetimeDefault {
debug_assert_eq!(tcx.def_kind(param_def_id), DefKind::TyParam);
let param_def_id = param_def_id.expect_local();
- let parent_def_id = tcx.local_parent(param_def_id);
- let generics = tcx.hir().get_generics(parent_def_id).unwrap();
- let param_hir_id = tcx.local_def_id_to_hir_id(param_def_id);
- let param = generics.params.iter().find(|p| p.hir_id == param_hir_id).unwrap();
-
- // Scan the bounds and where-clauses on parameters to extract bounds
- // of the form `T:'a` so as to determine the `ObjectLifetimeDefault`
- // for each type parameter.
- match param.kind {
- GenericParamKind::Type { .. } => {
- let mut set = Set1::Empty;
-
- // Look for `type: ...` where clauses.
- for bound in generics.bounds_for_param(param_def_id) {
- // Ignore `for<'a> type: ...` as they can change what
- // lifetimes mean (although we could "just" handle it).
- if !bound.bound_generic_params.is_empty() {
- continue;
- }
+ let hir::Node::GenericParam(param) = tcx.hir().get_by_def_id(param_def_id) else {
+ bug!("expected GenericParam for object_lifetime_default");
+ };
+ match param.source {
+ hir::GenericParamSource::Generics => {
+ let parent_def_id = tcx.local_parent(param_def_id);
+ let generics = tcx.hir().get_generics(parent_def_id).unwrap();
+ let param_hir_id = tcx.local_def_id_to_hir_id(param_def_id);
+ let param = generics.params.iter().find(|p| p.hir_id == param_hir_id).unwrap();
+
+ // Scan the bounds and where-clauses on parameters to extract bounds
+ // of the form `T:'a` so as to determine the `ObjectLifetimeDefault`
+ // for each type parameter.
+ match param.kind {
+ GenericParamKind::Type { .. } => {
+ let mut set = Set1::Empty;
+
+ // Look for `type: ...` where clauses.
+ for bound in generics.bounds_for_param(param_def_id) {
+ // Ignore `for<'a> type: ...` as they can change what
+ // lifetimes mean (although we could "just" handle it).
+ if !bound.bound_generic_params.is_empty() {
+ continue;
+ }
- for bound in bound.bounds {
- if let hir::GenericBound::Outlives(lifetime) = bound {
- set.insert(lifetime.res);
+ for bound in bound.bounds {
+ if let hir::GenericBound::Outlives(lifetime) = bound {
+ set.insert(lifetime.res);
+ }
+ }
}
- }
- }
- match set {
- Set1::Empty => ObjectLifetimeDefault::Empty,
- Set1::One(hir::LifetimeName::Static) => ObjectLifetimeDefault::Static,
- Set1::One(hir::LifetimeName::Param(param_def_id)) => {
- ObjectLifetimeDefault::Param(param_def_id.to_def_id())
+ match set {
+ Set1::Empty => ObjectLifetimeDefault::Empty,
+ Set1::One(hir::LifetimeName::Static) => ObjectLifetimeDefault::Static,
+ Set1::One(hir::LifetimeName::Param(param_def_id)) => {
+ ObjectLifetimeDefault::Param(param_def_id.to_def_id())
+ }
+ _ => ObjectLifetimeDefault::Ambiguous,
+ }
+ }
+ _ => {
+ bug!("object_lifetime_default_raw must only be called on a type parameter")
}
- _ => ObjectLifetimeDefault::Ambiguous,
}
}
- _ => {
- bug!("object_lifetime_default_raw must only be called on a type parameter")
- }
+ hir::GenericParamSource::Binder => ObjectLifetimeDefault::Empty,
}
}
-impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
+impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
fn with<F>(&mut self, wrap_scope: Scope<'_>, f: F)
where
- F: for<'b> FnOnce(&mut LifetimeContext<'b, 'tcx>),
+ F: for<'b> FnOnce(&mut BoundVarContext<'b, 'tcx>),
{
- let LifetimeContext { tcx, map, .. } = self;
- let mut this = LifetimeContext { tcx: *tcx, map, scope: &wrap_scope };
+ let BoundVarContext { tcx, map, .. } = self;
+ let mut this = BoundVarContext { tcx: *tcx, map, scope: &wrap_scope };
let span = debug_span!("scope", scope = ?TruncatedScopeDebug(&this.scope));
{
let _enter = span.enter();
@@ -1110,23 +1151,25 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
generics: &'tcx hir::Generics<'tcx>,
walk: F,
) where
- F: for<'b, 'c> FnOnce(&'b mut LifetimeContext<'c, 'tcx>),
+ F: for<'b, 'c> FnOnce(&'b mut BoundVarContext<'c, 'tcx>),
{
let mut named_late_bound_vars = 0;
- let lifetimes: FxIndexMap<LocalDefId, Region> = generics
+ let bound_vars: FxIndexMap<LocalDefId, ResolvedArg> = generics
.params
.iter()
- .filter_map(|param| match param.kind {
+ .map(|param| match param.kind {
GenericParamKind::Lifetime { .. } => {
if self.tcx.is_late_bound(param.hir_id) {
let late_bound_idx = named_late_bound_vars;
named_late_bound_vars += 1;
- Some(Region::late(late_bound_idx, param))
+ ResolvedArg::late(late_bound_idx, param)
} else {
- Some(Region::early(param))
+ ResolvedArg::early(param)
}
}
- GenericParamKind::Type { .. } | GenericParamKind::Const { .. } => None,
+ GenericParamKind::Type { .. } | GenericParamKind::Const { .. } => {
+ ResolvedArg::early(param)
+ }
})
.collect();
@@ -1139,14 +1182,14 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
})
.enumerate()
.map(|(late_bound_idx, param)| {
- let pair = Region::late(late_bound_idx as u32, param);
- late_region_as_bound_region(self.tcx, &pair.1)
+ let pair = ResolvedArg::late(late_bound_idx as u32, param);
+ late_arg_as_bound_arg(self.tcx, &pair.1, param)
})
.collect();
self.record_late_bound_vars(hir_id, binders);
let scope = Scope::Binder {
hir_id,
- lifetimes,
+ bound_vars,
s: self.scope,
scope_type: BinderScopeType::Normal,
where_bound_origin: None,
@@ -1177,15 +1220,15 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
Scope::Root { opt_parent_item } => {
if let Some(parent_item) = opt_parent_item
&& let parent_generics = self.tcx.generics_of(parent_item)
- && parent_generics.param_def_id_to_index.contains_key(&region_def_id.to_def_id())
+ && parent_generics.param_def_id_to_index(self.tcx, region_def_id.to_def_id()).is_some()
{
- break Some(Region::EarlyBound(region_def_id.to_def_id()));
+ break Some(ResolvedArg::EarlyBound(region_def_id.to_def_id()));
}
break None;
}
- Scope::Binder { ref lifetimes, scope_type, s, where_bound_origin, .. } => {
- if let Some(&def) = lifetimes.get(&region_def_id) {
+ Scope::Binder { ref bound_vars, scope_type, s, where_bound_origin, .. } => {
+ if let Some(&def) = bound_vars.get(&region_def_id) {
break Some(def.shifted(late_depth));
}
match scope_type {
@@ -1252,26 +1295,34 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
Scope::Elision { s, .. }
| Scope::ObjectLifetimeDefault { s, .. }
| Scope::Supertrait { s, .. }
- | Scope::TraitRefBoundary { s, .. } => {
+ | Scope::TraitRefBoundary { s, .. }
+ | Scope::AnonConstBoundary { s } => {
scope = s;
}
}
};
if let Some(mut def) = result {
- if let Region::EarlyBound(..) = def {
+ if let ResolvedArg::EarlyBound(..) = def {
// Do not free early-bound regions, only late-bound ones.
} else if let Some(body_id) = outermost_body {
let fn_id = self.tcx.hir().body_owner(body_id);
match self.tcx.hir().get(fn_id) {
- Node::Item(hir::Item { kind: hir::ItemKind::Fn(..), .. })
+ Node::Item(hir::Item { owner_id, kind: hir::ItemKind::Fn(..), .. })
| Node::TraitItem(hir::TraitItem {
- kind: hir::TraitItemKind::Fn(..), ..
+ owner_id,
+ kind: hir::TraitItemKind::Fn(..),
+ ..
})
- | Node::ImplItem(hir::ImplItem { kind: hir::ImplItemKind::Fn(..), .. })
- | Node::Expr(hir::Expr { kind: hir::ExprKind::Closure(..), .. }) => {
- let scope = self.tcx.hir().local_def_id(fn_id);
- def = Region::Free(scope.to_def_id(), def.id().unwrap());
+ | Node::ImplItem(hir::ImplItem {
+ owner_id,
+ kind: hir::ImplItemKind::Fn(..),
+ ..
+ }) => {
+ def = ResolvedArg::Free(owner_id.to_def_id(), def.id().unwrap());
+ }
+ Node::Expr(hir::Expr { kind: hir::ExprKind::Closure(closure), .. }) => {
+ def = ResolvedArg::Free(closure.def_id.to_def_id(), def.id().unwrap());
}
_ => {}
}
@@ -1310,7 +1361,8 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
| Scope::Elision { s, .. }
| Scope::ObjectLifetimeDefault { s, .. }
| Scope::Supertrait { s, .. }
- | Scope::TraitRefBoundary { s, .. } => {
+ | Scope::TraitRefBoundary { s, .. }
+ | Scope::AnonConstBoundary { s } => {
scope = s;
}
}
@@ -1322,6 +1374,87 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
);
}
+ fn resolve_type_ref(&mut self, param_def_id: LocalDefId, hir_id: hir::HirId) {
+ // Walk up the scope chain, tracking the number of fn scopes
+ // that we pass through, until we find a lifetime with the
+ // given name or we run out of scopes.
+ // search.
+ let mut late_depth = 0;
+ let mut scope = self.scope;
+ let mut crossed_anon_const = false;
+ let result = loop {
+ match *scope {
+ Scope::Body { s, .. } => {
+ scope = s;
+ }
+
+ Scope::Root { opt_parent_item } => {
+ if let Some(parent_item) = opt_parent_item
+ && let parent_generics = self.tcx.generics_of(parent_item)
+ && parent_generics.param_def_id_to_index(self.tcx, param_def_id.to_def_id()).is_some()
+ {
+ break Some(ResolvedArg::EarlyBound(param_def_id.to_def_id()));
+ }
+ break None;
+ }
+
+ Scope::Binder { ref bound_vars, scope_type, s, .. } => {
+ if let Some(&def) = bound_vars.get(&param_def_id) {
+ break Some(def.shifted(late_depth));
+ }
+ match scope_type {
+ BinderScopeType::Normal => late_depth += 1,
+ BinderScopeType::Concatenating => {}
+ }
+ scope = s;
+ }
+
+ Scope::Elision { s, .. }
+ | Scope::ObjectLifetimeDefault { s, .. }
+ | Scope::Supertrait { s, .. }
+ | Scope::TraitRefBoundary { s, .. } => {
+ scope = s;
+ }
+
+ Scope::AnonConstBoundary { s } => {
+ crossed_anon_const = true;
+ scope = s;
+ }
+ }
+ };
+
+ if let Some(def) = result {
+ if let ResolvedArg::LateBound(..) = def && crossed_anon_const {
+ let use_span = self.tcx.hir().span(hir_id);
+ let def_span = self.tcx.def_span(param_def_id);
+ match self.tcx.def_kind(param_def_id) {
+ DefKind::ConstParam => {
+ self.tcx.sess.emit_err(errors::CannotCaptureLateBoundInAnonConst::Const {
+ use_span,
+ def_span,
+ });
+ }
+ DefKind::TyParam => {
+ self.tcx.sess.emit_err(errors::CannotCaptureLateBoundInAnonConst::Type {
+ use_span,
+ def_span,
+ });
+ }
+ _ => unreachable!(),
+ }
+ return;
+ }
+
+ self.map.defs.insert(hir_id, def);
+ return;
+ }
+
+ self.tcx.sess.delay_span_bug(
+ self.tcx.hir().span(hir_id),
+ format!("could not resolve {param_def_id:?}"),
+ );
+ }
+
#[instrument(level = "debug", skip(self))]
fn visit_segment_args(
&mut self,
@@ -1390,7 +1523,8 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
| Scope::Elision { s, .. }
| Scope::ObjectLifetimeDefault { s, .. }
| Scope::Supertrait { s, .. }
- | Scope::TraitRefBoundary { s, .. } => {
+ | Scope::TraitRefBoundary { s, .. }
+ | Scope::AnonConstBoundary { s } => {
scope = s;
}
}
@@ -1408,10 +1542,10 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
if in_body {
None
} else {
- Some(Region::Static)
+ Some(ResolvedArg::StaticLifetime)
}
}
- ObjectLifetimeDefault::Static => Some(Region::Static),
+ ObjectLifetimeDefault::Static => Some(ResolvedArg::StaticLifetime),
ObjectLifetimeDefault::Param(param_def_id) => {
// This index can be used with `generic_args` since `parent_count == 0`.
let index = generics.param_def_id_to_index[&param_def_id] as usize;
@@ -1500,18 +1634,19 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
// in the trait ref `YY<...>` in `Item: YY<...>`.
for binding in generic_args.bindings {
let scope = Scope::ObjectLifetimeDefault {
- lifetime: if has_lifetime_parameter { None } else { Some(Region::Static) },
+ lifetime: if has_lifetime_parameter {
+ None
+ } else {
+ Some(ResolvedArg::StaticLifetime)
+ },
s: self.scope,
};
if let Some(type_def_id) = type_def_id {
- let lifetimes = LifetimeContext::supertrait_hrtb_lifetimes(
- self.tcx,
- type_def_id,
- binding.ident,
- );
+ let bound_vars =
+ BoundVarContext::supertrait_hrtb_vars(self.tcx, type_def_id, binding.ident);
self.with(scope, |this| {
let scope = Scope::Supertrait {
- lifetimes: lifetimes.unwrap_or_default(),
+ bound_vars: bound_vars.unwrap_or_default(),
s: this.scope,
};
this.with(scope, |this| this.visit_assoc_type_binding(binding));
@@ -1534,7 +1669,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
/// ```
/// In this case, if we wanted to the supertrait HRTB lifetimes for `As` on
/// the starting trait `Bar`, we would return `Some(['b, 'a])`.
- fn supertrait_hrtb_lifetimes(
+ fn supertrait_hrtb_vars(
tcx: TyCtxt<'tcx>,
def_id: DefId,
assoc_name: Ident,
@@ -1556,7 +1691,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
// See issue #83753. If someone writes an associated type on a non-trait, just treat it as
// there being no supertrait HRTBs.
match tcx.def_kind(def_id) {
- DefKind::Trait | DefKind::TraitAlias | DefKind::Impl => {}
+ DefKind::Trait | DefKind::TraitAlias | DefKind::Impl { .. } => {}
_ => break None,
}
@@ -1619,13 +1754,15 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
scope = s;
}
- Scope::Root { .. } | Scope::Elision { .. } => break Region::Static,
+ Scope::Root { .. } | Scope::Elision { .. } => break ResolvedArg::StaticLifetime,
Scope::Body { .. } | Scope::ObjectLifetimeDefault { lifetime: None, .. } => return,
Scope::ObjectLifetimeDefault { lifetime: Some(l), .. } => break l,
- Scope::Supertrait { s, .. } | Scope::TraitRefBoundary { s, .. } => {
+ Scope::Supertrait { s, .. }
+ | Scope::TraitRefBoundary { s, .. }
+ | Scope::AnonConstBoundary { s } => {
scope = s;
}
}
@@ -1634,7 +1771,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
}
#[instrument(level = "debug", skip(self))]
- fn insert_lifetime(&mut self, lifetime_ref: &'tcx hir::Lifetime, def: Region) {
+ fn insert_lifetime(&mut self, lifetime_ref: &'tcx hir::Lifetime, def: ResolvedArg) {
debug!(span = ?lifetime_ref.ident.span);
self.map.defs.insert(lifetime_ref.hir_id, def);
}
@@ -1642,7 +1779,11 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
/// Sometimes we resolve a lifetime, but later find that it is an
/// error (esp. around impl trait). In that case, we remove the
/// entry into `map.defs` so as not to confuse later code.
- fn uninsert_lifetime_on_error(&mut self, lifetime_ref: &'tcx hir::Lifetime, bad_def: Region) {
+ fn uninsert_lifetime_on_error(
+ &mut self,
+ lifetime_ref: &'tcx hir::Lifetime,
+ bad_def: ResolvedArg,
+ ) {
let old_value = self.map.defs.remove(&lifetime_ref.hir_id);
assert_eq!(old_value, Some(bad_def));
}
@@ -1658,10 +1799,12 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
/// "Constrained" basically means that it appears in any type but
/// not amongst the inputs to a projection. In other words, `<&'a
/// T as Trait<''b>>::Foo` does not constrain `'a` or `'b`.
-fn is_late_bound_map(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<&FxIndexSet<LocalDefId>> {
- let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
- let decl = tcx.hir().fn_decl_by_hir_id(hir_id)?;
- let generics = tcx.hir().get_generics(def_id)?;
+fn is_late_bound_map(
+ tcx: TyCtxt<'_>,
+ owner_id: hir::OwnerId,
+) -> Option<&FxIndexSet<hir::ItemLocalId>> {
+ let decl = tcx.hir().fn_decl_by_hir_id(owner_id.into())?;
+ let generics = tcx.hir().get_generics(owner_id.def_id)?;
let mut late_bound = FxIndexSet::default();
@@ -1695,24 +1838,22 @@ fn is_late_bound_map(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<&FxIndexSet<
hir::GenericParamKind::Type { .. } | hir::GenericParamKind::Const { .. } => continue,
}
- let param_def_id = tcx.hir().local_def_id(param.hir_id);
-
// appears in the where clauses? early-bound.
- if appears_in_where_clause.regions.contains(&param_def_id) {
+ if appears_in_where_clause.regions.contains(&param.def_id) {
continue;
}
// does not appear in the inputs, but appears in the return type? early-bound.
- if !constrained_by_input.regions.contains(&param_def_id)
- && appears_in_output.regions.contains(&param_def_id)
+ if !constrained_by_input.regions.contains(&param.def_id)
+ && appears_in_output.regions.contains(&param.def_id)
{
continue;
}
- debug!("lifetime {:?} with id {:?} is late-bound", param.name.ident(), param.hir_id);
+ debug!("lifetime {:?} with id {:?} is late-bound", param.name.ident(), param.def_id);
- let inserted = late_bound.insert(param_def_id);
- assert!(inserted, "visited lifetime {:?} twice", param.hir_id);
+ let inserted = late_bound.insert(param.hir_id.local_id);
+ assert!(inserted, "visited lifetime {:?} twice", param.def_id);
}
debug!(?late_bound);
@@ -1745,7 +1886,7 @@ fn is_late_bound_map(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<&FxIndexSet<
use std::ops::ControlFlow;
use ty::Ty;
- impl<'tcx> TypeVisitor<'tcx> for ConstrainedCollectorPostAstConv {
+ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for ConstrainedCollectorPostAstConv {
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<!> {
match t.kind() {
ty::Param(param_ty) => {
@@ -1797,7 +1938,7 @@ fn is_late_bound_map(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<&FxIndexSet<
let mut walker = ConstrainedCollectorPostAstConv {
arg_is_constrained: vec![false; generics.params.len()].into_boxed_slice(),
};
- walker.visit_ty(self.tcx.type_of(alias_def));
+ walker.visit_ty(self.tcx.type_of(alias_def).subst_identity());
match segments.last() {
Some(hir::PathSegment { args: Some(args), .. }) => {
@@ -1865,3 +2006,37 @@ fn is_late_bound_map(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<&FxIndexSet<
}
}
}
+
+pub fn deny_non_region_late_bound(
+ tcx: TyCtxt<'_>,
+ bound_vars: &mut FxIndexMap<LocalDefId, ResolvedArg>,
+ where_: &str,
+) {
+ let mut first = true;
+
+ for (var, arg) in bound_vars {
+ let Node::GenericParam(param) = tcx.hir().get_by_def_id(*var) else {
+ bug!();
+ };
+
+ let what = match param.kind {
+ hir::GenericParamKind::Type { .. } => "type",
+ hir::GenericParamKind::Const { .. } => "const",
+ hir::GenericParamKind::Lifetime { .. } => continue,
+ };
+
+ let mut diag = tcx.sess.struct_span_err(
+ param.span,
+ format!("late-bound {what} parameter not allowed on {where_}"),
+ );
+
+ let guar = if tcx.features().non_lifetime_binders && first {
+ diag.emit()
+ } else {
+ diag.delay_as_bug()
+ };
+
+ first = false;
+ *arg = ResolvedArg::Error(guar);
+ }
+}
diff --git a/compiler/rustc_hir_analysis/src/collect/type_of.rs b/compiler/rustc_hir_analysis/src/collect/type_of.rs
index 5e388a2f2..50073d94e 100644
--- a/compiler/rustc_hir_analysis/src/collect/type_of.rs
+++ b/compiler/rustc_hir_analysis/src/collect/type_of.rs
@@ -8,7 +8,9 @@ use rustc_middle::hir::nested_filter;
use rustc_middle::ty::print::with_forced_trimmed_paths;
use rustc_middle::ty::subst::InternalSubsts;
use rustc_middle::ty::util::IntTypeExt;
-use rustc_middle::ty::{self, DefIdTree, Ty, TyCtxt, TypeFolder, TypeSuperFoldable, TypeVisitable};
+use rustc_middle::ty::{
+ self, DefIdTree, IsSuggestable, Ty, TyCtxt, TypeFolder, TypeSuperFoldable, TypeVisitableExt,
+};
use rustc_span::symbol::Ident;
use rustc_span::{Span, DUMMY_SP};
@@ -54,15 +56,14 @@ pub(super) fn opt_const_param_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<
// ty which is a fully resolved projection.
// For the code example above, this would mean converting Self::Assoc<3>
// into a ty::Alias(ty::Projection, <Self as Foo>::Assoc<3>)
- let item_hir_id = tcx
+ let item_def_id = tcx
.hir()
- .parent_iter(hir_id)
- .filter(|(_, node)| matches!(node, Node::Item(_)))
- .map(|(id, _)| id)
- .next()
- .unwrap();
- let item_did = tcx.hir().local_def_id(item_hir_id).to_def_id();
- let item_ctxt = &ItemCtxt::new(tcx, item_did) as &dyn crate::astconv::AstConv<'_>;
+ .parent_owner_iter(hir_id)
+ .find(|(_, node)| matches!(node, OwnerNode::Item(_)))
+ .unwrap()
+ .0
+ .to_def_id();
+ let item_ctxt = &ItemCtxt::new(tcx, item_def_id) as &dyn crate::astconv::AstConv<'_>;
let ty = item_ctxt.ast_ty_to_ty(hir_ty);
// Iterate through the generics of the projection to find the one that corresponds to
@@ -242,7 +243,7 @@ fn get_path_containing_arg_in_pat<'hir>(
arg_path
}
-pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
+pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::EarlyBinder<Ty<'_>> {
let def_id = def_id.expect_local();
use rustc_hir::*;
@@ -250,7 +251,7 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
let icx = ItemCtxt::new(tcx, def_id.to_def_id());
- match tcx.hir().get(hir_id) {
+ let output = match tcx.hir().get(hir_id) {
Node::TraitItem(item) => match item.kind {
TraitItemKind::Fn(..) => {
let substs = InternalSubsts::identity_for_item(tcx, def_id.to_def_id());
@@ -258,13 +259,8 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
}
TraitItemKind::Const(ty, body_id) => body_id
.and_then(|body_id| {
- if is_suggestable_infer_ty(ty) {
- Some(infer_placeholder_type(
- tcx, def_id, body_id, ty.span, item.ident, "constant",
- ))
- } else {
- None
- }
+ is_suggestable_infer_ty(ty)
+ .then(|| infer_placeholder_type(tcx, def_id, body_id, ty.span, item.ident, "constant",))
})
.unwrap_or_else(|| icx.to_ty(ty)),
TraitItemKind::Type(_, Some(ty)) => icx.to_ty(ty),
@@ -323,8 +319,8 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
ItemKind::Impl(hir::Impl { self_ty, .. }) => {
match self_ty.find_self_aliases() {
spans if spans.len() > 0 => {
- tcx.sess.emit_err(crate::errors::SelfInImplSelf { span: spans.into(), note: (), });
- tcx.ty_error()
+ let guar = tcx.sess.emit_err(crate::errors::SelfInImplSelf { span: spans.into(), note: () });
+ tcx.ty_error(guar)
},
_ => icx.to_ty(*self_ty),
}
@@ -381,7 +377,7 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
Node::Ctor(def) | Node::Variant(Variant { data: def, .. }) => match def {
VariantData::Unit(..) | VariantData::Struct(..) => {
- tcx.type_of(tcx.hir().get_parent_item(hir_id))
+ tcx.type_of(tcx.hir().get_parent_item(hir_id)).subst_identity()
}
VariantData::Tuple(..) => {
let substs = InternalSubsts::identity_for_item(tcx, def_id.to_def_id());
@@ -398,7 +394,7 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
Node::AnonConst(_) if let Some(param) = tcx.opt_const_param_of(def_id) => {
// We defer to `type_of` of the corresponding parameter
// for generic arguments.
- tcx.type_of(param)
+ tcx.type_of(param).subst_identity()
}
Node::AnonConst(_) => {
@@ -450,7 +446,7 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
&& e.hir_id == hir_id =>
{
let Some(trait_def_id) = trait_ref.trait_def_id() else {
- return tcx.ty_error_with_message(DUMMY_SP, "Could not find trait");
+ return ty::EarlyBinder(tcx.ty_error_with_message(DUMMY_SP, "Could not find trait"));
};
let assoc_items = tcx.associated_items(trait_def_id);
let assoc_item = assoc_items.find_by_name_and_kind(
@@ -460,7 +456,7 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
def_id.to_def_id(),
);
if let Some(assoc_item) = assoc_item {
- tcx.type_of(assoc_item.def_id)
+ tcx.type_of(assoc_item.def_id).subst_identity()
} else {
// FIXME(associated_const_equality): add a useful error message here.
tcx.ty_error_with_message(
@@ -484,7 +480,7 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
}) =>
{
let Some(trait_def_id) = trait_ref.trait_def_id() else {
- return tcx.ty_error_with_message(DUMMY_SP, "Could not find trait");
+ return ty::EarlyBinder(tcx.ty_error_with_message(DUMMY_SP, "Could not find trait"));
};
let assoc_items = tcx.associated_items(trait_def_id);
let assoc_item = assoc_items.find_by_name_and_kind(
@@ -505,7 +501,7 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
if let Some(param)
= assoc_item.map(|item| &tcx.generics_of(item.def_id).params[idx]).filter(|param| param.kind.is_ty_or_const())
{
- tcx.type_of(param.def_id)
+ tcx.type_of(param.def_id).subst_identity()
} else {
// FIXME(associated_const_equality): add a useful error message here.
tcx.ty_error_with_message(
@@ -519,7 +515,7 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
def_id: param_def_id,
kind: GenericParamKind::Const { default: Some(ct), .. },
..
- }) if ct.hir_id == hir_id => tcx.type_of(param_def_id),
+ }) if ct.hir_id == hir_id => tcx.type_of(param_def_id).subst_identity(),
x => tcx.ty_error_with_message(
DUMMY_SP,
@@ -537,7 +533,8 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
x => {
bug!("unexpected sort of node in type_of(): {:?}", x);
}
- }
+ };
+ ty::EarlyBinder(output)
}
#[instrument(skip(tcx), level = "debug")]
@@ -602,8 +599,9 @@ fn find_opaque_ty_constraints_for_tait(tcx: TyCtxt<'_>, def_id: LocalDefId) -> T
// // constant does not contain interior mutability.
// ```
let tables = self.tcx.typeck(item_def_id);
- if let Some(_) = tables.tainted_by_errors {
- self.found = Some(ty::OpaqueHiddenType { span: DUMMY_SP, ty: self.tcx.ty_error() });
+ if let Some(guar) = tables.tainted_by_errors {
+ self.found =
+ Some(ty::OpaqueHiddenType { span: DUMMY_SP, ty: self.tcx.ty_error(guar) });
return;
}
let Some(&typeck_hidden_ty) = tables.concrete_opaque_types.get(&self.def_id) else {
@@ -621,8 +619,8 @@ fn find_opaque_ty_constraints_for_tait(tcx: TyCtxt<'_>, def_id: LocalDefId) -> T
debug!(?concrete_type, "found constraint");
if let Some(prev) = &mut self.found {
if concrete_type.ty != prev.ty && !(concrete_type, prev.ty).references_error() {
- prev.report_mismatch(&concrete_type, self.tcx);
- prev.ty = self.tcx.ty_error();
+ let guar = prev.report_mismatch(&concrete_type, self.tcx);
+ prev.ty = self.tcx.ty_error(guar);
}
} else {
self.found = Some(concrete_type);
@@ -709,7 +707,7 @@ fn find_opaque_ty_constraints_for_tait(tcx: TyCtxt<'_>, def_id: LocalDefId) -> T
_ => "item",
},
});
- return tcx.ty_error_with_guaranteed(reported);
+ return tcx.ty_error(reported);
};
// Only check against typeck if we didn't already error
@@ -817,11 +815,11 @@ fn find_opaque_ty_constraints_for_rpit(
concrete.map(|concrete| concrete.ty).unwrap_or_else(|| {
let table = tcx.typeck(owner_def_id);
- if let Some(_) = table.tainted_by_errors {
+ if let Some(guar) = table.tainted_by_errors {
// Some error in the
// owner fn prevented us from populating
// the `concrete_opaque_types` table.
- tcx.ty_error()
+ tcx.ty_error(guar)
} else {
table.concrete_opaque_types.get(&def_id).map(|ty| ty.ty).unwrap_or_else(|| {
// We failed to resolve the opaque type or it
@@ -846,35 +844,23 @@ fn infer_placeholder_type<'a>(
) -> Ty<'a> {
// Attempts to make the type nameable by turning FnDefs into FnPtrs.
struct MakeNameable<'tcx> {
- success: bool,
tcx: TyCtxt<'tcx>,
}
- impl<'tcx> MakeNameable<'tcx> {
- fn new(tcx: TyCtxt<'tcx>) -> Self {
- MakeNameable { success: true, tcx }
- }
- }
-
- impl<'tcx> TypeFolder<'tcx> for MakeNameable<'tcx> {
- fn tcx(&self) -> TyCtxt<'tcx> {
+ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for MakeNameable<'tcx> {
+ fn interner(&self) -> TyCtxt<'tcx> {
self.tcx
}
fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
- if !self.success {
- return ty;
- }
-
- match ty.kind() {
- ty::FnDef(def_id, _) => self.tcx.mk_fn_ptr(self.tcx.fn_sig(*def_id)),
- // FIXME: non-capturing closures should also suggest a function pointer
- ty::Closure(..) | ty::Generator(..) => {
- self.success = false;
- ty
+ let ty = match *ty.kind() {
+ ty::FnDef(def_id, substs) => {
+ self.tcx.mk_fn_ptr(self.tcx.fn_sig(def_id).subst(self.tcx, substs))
}
- _ => ty.super_fold_with(self),
- }
+ _ => ty,
+ };
+
+ ty.super_fold_with(self)
}
}
@@ -897,15 +883,11 @@ fn infer_placeholder_type<'a>(
suggestions.clear();
}
- // Suggesting unnameable types won't help.
- let mut mk_nameable = MakeNameable::new(tcx);
- let ty = mk_nameable.fold_ty(ty);
- let sugg_ty = if mk_nameable.success { Some(ty) } else { None };
- if let Some(sugg_ty) = sugg_ty {
+ if let Some(ty) = ty.make_suggestable(tcx, false) {
err.span_suggestion(
span,
&format!("provide a type for the {item}", item = kind),
- format!("{colon} {sugg_ty}"),
+ format!("{colon} {ty}"),
Applicability::MachineApplicable,
);
} else {
@@ -922,15 +904,12 @@ fn infer_placeholder_type<'a>(
let mut diag = bad_placeholder(tcx, vec![span], kind);
if !ty.references_error() {
- let mut mk_nameable = MakeNameable::new(tcx);
- let ty = mk_nameable.fold_ty(ty);
- let sugg_ty = if mk_nameable.success { Some(ty) } else { None };
- if let Some(sugg_ty) = sugg_ty {
+ if let Some(ty) = ty.make_suggestable(tcx, false) {
diag.span_suggestion(
span,
"replace with the correct type",
- sugg_ty,
- Applicability::MaybeIncorrect,
+ ty,
+ Applicability::MachineApplicable,
);
} else {
with_forced_trimmed_paths!(diag.span_note(
diff --git a/compiler/rustc_hir_analysis/src/constrained_generic_params.rs b/compiler/rustc_hir_analysis/src/constrained_generic_params.rs
index 56cc1d8fa..e18b0f082 100644
--- a/compiler/rustc_hir_analysis/src/constrained_generic_params.rs
+++ b/compiler/rustc_hir_analysis/src/constrained_generic_params.rs
@@ -43,7 +43,7 @@ pub fn parameters_for_impl<'tcx>(
/// of parameters whose values are needed in order to constrain `ty` - these
/// differ, with the latter being a superset, in the presence of projections.
pub fn parameters_for<'tcx>(
- t: &impl TypeVisitable<'tcx>,
+ t: &impl TypeVisitable<TyCtxt<'tcx>>,
include_nonconstraining: bool,
) -> Vec<Parameter> {
let mut collector = ParameterCollector { parameters: vec![], include_nonconstraining };
@@ -56,7 +56,7 @@ struct ParameterCollector {
include_nonconstraining: bool,
}
-impl<'tcx> TypeVisitor<'tcx> for ParameterCollector {
+impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for ParameterCollector {
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
match *t.kind() {
ty::Alias(ty::Projection, ..) if !self.include_nonconstraining => {
diff --git a/compiler/rustc_hir_analysis/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs
index 04f5f3f62..3e0692757 100644
--- a/compiler/rustc_hir_analysis/src/errors.rs
+++ b/compiler/rustc_hir_analysis/src/errors.rs
@@ -1,8 +1,11 @@
//! Errors emitted by `rustc_hir_analysis`.
-use rustc_errors::{error_code, Applicability, DiagnosticBuilder, ErrorGuaranteed, Handler};
-use rustc_errors::{IntoDiagnostic, MultiSpan};
-use rustc_macros::{Diagnostic, LintDiagnostic};
+use crate::fluent_generated as fluent;
+use rustc_errors::{
+ error_code, Applicability, DiagnosticBuilder, ErrorGuaranteed, Handler, IntoDiagnostic,
+ MultiSpan,
+};
+use rustc_macros::Diagnostic;
use rustc_middle::ty::Ty;
use rustc_span::{symbol::Ident, Span, Symbol};
@@ -41,11 +44,11 @@ pub struct LifetimesOrBoundsMismatchOnTrait {
#[primary_span]
#[label]
pub span: Span,
- #[label(generics_label)]
+ #[label(hir_analysis_generics_label)]
pub generics_span: Option<Span>,
- #[label(where_label)]
+ #[label(hir_analysis_where_label)]
pub where_span: Option<Span>,
- #[label(bounds_label)]
+ #[label(hir_analysis_bounds_label)]
pub bounds_span: Vec<Span>,
pub item_kind: &'static str,
pub ident: Ident,
@@ -57,7 +60,7 @@ pub struct AsyncTraitImplShouldBeAsync {
#[primary_span]
// #[label]
pub span: Span,
- #[label(trait_item_label)]
+ #[label(hir_analysis_trait_item_label)]
pub trait_item_span: Option<Span>,
pub method_name: Symbol,
}
@@ -77,7 +80,7 @@ pub struct FieldAlreadyDeclared {
#[primary_span]
#[label]
pub span: Span,
- #[label(previous_decl_label)]
+ #[label(hir_analysis_previous_decl_label)]
pub prev_span: Span,
}
@@ -109,7 +112,7 @@ pub struct CopyImplOnNonAdt {
pub struct TraitObjectDeclaredWithNoTraits {
#[primary_span]
pub span: Span,
- #[label(alias_span)]
+ #[label(hir_analysis_alias_span)]
pub trait_alias_span: Option<Span>,
}
@@ -145,7 +148,7 @@ pub struct ValueOfAssociatedStructAlreadySpecified {
#[primary_span]
#[label]
pub span: Span,
- #[label(previous_bound_label)]
+ #[label(hir_analysis_previous_bound_label)]
pub prev_span: Span,
pub item_name: Ident,
pub def_path: String,
@@ -175,7 +178,7 @@ impl<'a> IntoDiagnostic<'a> for MissingTypeParams {
fn into_diagnostic(self, handler: &'a Handler) -> DiagnosticBuilder<'a, ErrorGuaranteed> {
let mut err = handler.struct_span_err_with_code(
self.span,
- rustc_errors::fluent::hir_analysis_missing_type_params,
+ fluent::hir_analysis_missing_type_params,
error_code!(E0393),
);
err.set_arg("parameterCount", self.missing_type_params.len());
@@ -188,7 +191,7 @@ impl<'a> IntoDiagnostic<'a> for MissingTypeParams {
.join(", "),
);
- err.span_label(self.def_span, rustc_errors::fluent::label);
+ err.span_label(self.def_span, fluent::hir_analysis_label);
let mut suggested = false;
// Don't suggest setting the type params if there are some already: the order is
@@ -203,7 +206,7 @@ impl<'a> IntoDiagnostic<'a> for MissingTypeParams {
// least we can clue them to the correct syntax `Iterator<Type>`.
err.span_suggestion(
self.span,
- rustc_errors::fluent::suggestion,
+ fluent::hir_analysis_suggestion,
format!(
"{}<{}>",
snippet,
@@ -219,10 +222,10 @@ impl<'a> IntoDiagnostic<'a> for MissingTypeParams {
}
}
if !suggested {
- err.span_label(self.span, rustc_errors::fluent::no_suggestion_label);
+ err.span_label(self.span, fluent::hir_analysis_no_suggestion_label);
}
- err.note(rustc_errors::fluent::note);
+ err.note(fluent::hir_analysis_note);
err
}
}
@@ -244,26 +247,6 @@ pub struct SubstsOnOverriddenImpl {
pub span: Span,
}
-#[derive(LintDiagnostic)]
-#[diag(hir_analysis_unused_extern_crate)]
-pub struct UnusedExternCrate {
- #[suggestion(applicability = "machine-applicable", code = "")]
- pub span: Span,
-}
-
-#[derive(LintDiagnostic)]
-#[diag(hir_analysis_extern_crate_not_idiomatic)]
-pub struct ExternCrateNotIdiomatic {
- #[suggestion(
- style = "short",
- applicability = "machine-applicable",
- code = "{suggestion_code}"
- )]
- pub span: Span,
- pub msg_code: String,
- pub suggestion_code: String,
-}
-
#[derive(Diagnostic)]
#[diag(hir_analysis_const_impl_for_non_const_trait)]
pub struct ConstImplForNonConstTrait {
@@ -274,7 +257,7 @@ pub struct ConstImplForNonConstTrait {
pub local_trait_span: Option<Span>,
#[note]
pub marking: (),
- #[note(adding)]
+ #[note(hir_analysis_adding)]
pub adding: (),
}
@@ -312,3 +295,107 @@ pub struct AutoDerefReachedRecursionLimit<'a> {
pub suggested_limit: rustc_session::Limit,
pub crate_name: Symbol,
}
+
+#[derive(Diagnostic)]
+#[diag(hir_analysis_where_clause_on_main, code = "E0646")]
+pub(crate) struct WhereClauseOnMain {
+ #[primary_span]
+ pub span: Span,
+ #[label]
+ pub generics_span: Option<Span>,
+}
+
+#[derive(Diagnostic)]
+#[diag(hir_analysis_track_caller_on_main)]
+pub(crate) struct TrackCallerOnMain {
+ #[primary_span]
+ #[suggestion(applicability = "maybe-incorrect", code = "")]
+ pub span: Span,
+ #[label(hir_analysis_track_caller_on_main)]
+ pub annotated: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(hir_analysis_start_not_track_caller)]
+pub(crate) struct StartTrackCaller {
+ #[primary_span]
+ pub span: Span,
+ #[label]
+ pub start: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(hir_analysis_start_not_async, code = "E0752")]
+pub(crate) struct StartAsync {
+ #[primary_span]
+ #[label]
+ pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(hir_analysis_start_function_where, code = "E0647")]
+pub(crate) struct StartFunctionWhere {
+ #[primary_span]
+ #[label]
+ pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(hir_analysis_start_function_parameters, code = "E0132")]
+pub(crate) struct StartFunctionParameters {
+ #[primary_span]
+ #[label]
+ pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(hir_analysis_main_function_return_type_generic, code = "E0131")]
+pub(crate) struct MainFunctionReturnTypeGeneric {
+ #[primary_span]
+ pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(hir_analysis_main_function_async, code = "E0752")]
+pub(crate) struct MainFunctionAsync {
+ #[primary_span]
+ pub span: Span,
+ #[label]
+ pub asyncness: Option<Span>,
+}
+
+#[derive(Diagnostic)]
+#[diag(hir_analysis_main_function_generic_parameters, code = "E0131")]
+pub(crate) struct MainFunctionGenericParameters {
+ #[primary_span]
+ pub span: Span,
+ #[label]
+ pub label_span: Option<Span>,
+}
+
+#[derive(Diagnostic)]
+#[diag(hir_analysis_variadic_function_compatible_convention, code = "E0045")]
+pub(crate) struct VariadicFunctionCompatibleConvention<'a> {
+ #[primary_span]
+ #[label]
+ pub span: Span,
+ pub conventions: &'a str,
+}
+
+#[derive(Diagnostic)]
+pub(crate) enum CannotCaptureLateBoundInAnonConst {
+ #[diag(hir_analysis_cannot_capture_late_bound_ty_in_anon_const)]
+ Type {
+ #[primary_span]
+ use_span: Span,
+ #[label]
+ def_span: Span,
+ },
+ #[diag(hir_analysis_cannot_capture_late_bound_const_in_anon_const)]
+ Const {
+ #[primary_span]
+ use_span: Span,
+ #[label]
+ def_span: Span,
+ },
+}
diff --git a/compiler/rustc_hir_analysis/src/hir_wf_check.rs b/compiler/rustc_hir_analysis/src/hir_wf_check.rs
index 17dbb126b..e330fcc78 100644
--- a/compiler/rustc_hir_analysis/src/hir_wf_check.rs
+++ b/compiler/rustc_hir_analysis/src/hir_wf_check.rs
@@ -1,11 +1,12 @@
use crate::collect::ItemCtxt;
use rustc_hir as hir;
use rustc_hir::intravisit::{self, Visitor};
-use rustc_hir::{ForeignItem, ForeignItemKind, HirId};
+use rustc_hir::{ForeignItem, ForeignItemKind};
use rustc_infer::infer::TyCtxtInferExt;
use rustc_infer::traits::{ObligationCause, WellFormedLoc};
use rustc_middle::ty::query::Providers;
use rustc_middle::ty::{self, Region, TyCtxt, TypeFoldable, TypeFolder};
+use rustc_span::def_id::LocalDefId;
use rustc_trait_selection::traits;
pub fn provide(providers: &mut Providers) {
@@ -57,7 +58,7 @@ fn diagnostic_hir_wf_check<'tcx>(
cause: Option<ObligationCause<'tcx>>,
cause_depth: usize,
icx: ItemCtxt<'tcx>,
- hir_id: HirId,
+ def_id: LocalDefId,
param_env: ty::ParamEnv<'tcx>,
depth: usize,
}
@@ -68,7 +69,7 @@ fn diagnostic_hir_wf_check<'tcx>(
let tcx_ty = self.icx.to_ty(ty).fold_with(&mut EraseAllBoundRegions { tcx: self.tcx });
let cause = traits::ObligationCause::new(
ty.span,
- self.hir_id,
+ self.def_id,
traits::ObligationCauseCode::WellFormed(None),
);
let errors = traits::fully_solve_obligation(
@@ -106,7 +107,7 @@ fn diagnostic_hir_wf_check<'tcx>(
cause: None,
cause_depth: 0,
icx,
- hir_id,
+ def_id,
param_env: tcx.param_env(def_id.to_def_id()),
depth: 0,
};
@@ -188,8 +189,8 @@ struct EraseAllBoundRegions<'tcx> {
// us an inaccurate span for an error message, but cannot
// lead to unsoundness (we call `delay_span_bug` at the start
// of `diagnostic_hir_wf_check`).
-impl<'tcx> TypeFolder<'tcx> for EraseAllBoundRegions<'tcx> {
- fn tcx<'a>(&'a self) -> TyCtxt<'tcx> {
+impl<'tcx> TypeFolder<TyCtxt<'tcx>> for EraseAllBoundRegions<'tcx> {
+ fn interner(&self) -> TyCtxt<'tcx> {
self.tcx
}
fn fold_region(&mut self, r: Region<'tcx>) -> Region<'tcx> {
diff --git a/compiler/rustc_hir_analysis/src/impl_wf_check.rs b/compiler/rustc_hir_analysis/src/impl_wf_check.rs
index 4fe893442..82a96f8e6 100644
--- a/compiler/rustc_hir_analysis/src/impl_wf_check.rs
+++ b/compiler/rustc_hir_analysis/src/impl_wf_check.rs
@@ -16,7 +16,7 @@ use rustc_errors::struct_span_err;
use rustc_hir::def::DefKind;
use rustc_hir::def_id::LocalDefId;
use rustc_middle::ty::query::Providers;
-use rustc_middle::ty::{self, TyCtxt, TypeVisitable};
+use rustc_middle::ty::{self, TyCtxt, TypeVisitableExt};
use rustc_span::{Span, Symbol};
mod min_specialization;
@@ -55,7 +55,7 @@ fn check_mod_impl_wf(tcx: TyCtxt<'_>, module_def_id: LocalDefId) {
let min_specialization = tcx.features().min_specialization;
let module = tcx.hir_module_items(module_def_id);
for id in module.items() {
- if matches!(tcx.def_kind(id.owner_id), DefKind::Impl) {
+ if matches!(tcx.def_kind(id.owner_id), DefKind::Impl { .. }) {
enforce_impl_params_are_constrained(tcx, id.owner_id.def_id);
if min_specialization {
check_min_specialization(tcx, id.owner_id.def_id);
@@ -70,7 +70,7 @@ pub fn provide(providers: &mut Providers) {
fn enforce_impl_params_are_constrained(tcx: TyCtxt<'_>, impl_def_id: LocalDefId) {
// Every lifetime used in an associated type must be constrained.
- let impl_self_ty = tcx.type_of(impl_def_id);
+ let impl_self_ty = tcx.type_of(impl_def_id).subst_identity();
if impl_self_ty.references_error() {
// Don't complain about unconstrained type params when self ty isn't known due to errors.
// (#36836)
@@ -104,7 +104,7 @@ fn enforce_impl_params_are_constrained(tcx: TyCtxt<'_>, impl_def_id: LocalDefId)
match item.kind {
ty::AssocKind::Type => {
if item.defaultness(tcx).has_value() {
- cgp::parameters_for(&tcx.type_of(def_id), true)
+ cgp::parameters_for(&tcx.type_of(def_id).subst_identity(), true)
} else {
Vec::new()
}
diff --git a/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs b/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs
index bcda26c4c..daa5d1570 100644
--- a/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs
+++ b/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs
@@ -76,7 +76,7 @@ use rustc_infer::infer::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, TyCtxt, TypeVisitable};
+use rustc_middle::ty::{self, TyCtxt, TypeVisitableExt};
use rustc_span::Span;
use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt;
use rustc_trait_selection::traits::outlives_bounds::InferCtxtExt as _;
@@ -164,7 +164,6 @@ fn get_impl_substs(
let infcx = &tcx.infer_ctxt().build();
let ocx = ObligationCtxt::new(infcx);
let param_env = tcx.param_env(impl1_def_id);
- let impl1_hir_id = tcx.hir().local_def_id_to_hir_id(impl1_def_id);
let assumed_wf_types =
ocx.assumed_wf_types(param_env, tcx.def_span(impl1_def_id), impl1_def_id);
@@ -179,7 +178,7 @@ fn get_impl_substs(
return None;
}
- let implied_bounds = infcx.implied_bounds_tys(param_env, impl1_hir_id, assumed_wf_types);
+ let implied_bounds = infcx.implied_bounds_tys(param_env, impl1_def_id, assumed_wf_types);
let outlives_env = OutlivesEnvironment::with_bounds(param_env, Some(infcx), implied_bounds);
let _ =
infcx.err_ctxt().check_region_obligations_and_report_errors(impl1_def_id, &outlives_env);
@@ -372,15 +371,9 @@ fn check_predicates<'tcx>(
// Include the well-formed predicates of the type parameters of the impl.
for arg in tcx.impl_trait_ref(impl1_def_id).unwrap().subst_identity().substs {
let infcx = &tcx.infer_ctxt().build();
- let obligations = wf::obligations(
- infcx,
- tcx.param_env(impl1_def_id),
- tcx.hir().local_def_id_to_hir_id(impl1_def_id),
- 0,
- arg,
- span,
- )
- .unwrap();
+ let obligations =
+ wf::obligations(infcx, tcx.param_env(impl1_def_id), impl1_def_id, 0, arg, span)
+ .unwrap();
assert!(!obligations.needs_infer());
impl2_predicates.extend(
@@ -503,6 +496,16 @@ fn check_specialization_on<'tcx>(tcx: TyCtxt<'tcx>, predicate: ty::Predicate<'tc
)
.emit();
}
+ ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(..)) => {
+ // FIXME(min_specialization), FIXME(const_generics):
+ // It probably isn't right to allow _every_ `ConstArgHasType` but I am somewhat unsure
+ // about the actual rules that would be sound. Can't just always error here because otherwise
+ // std/core doesn't even compile as they have `const N: usize` in some specializing impls.
+ //
+ // While we do not support constructs like `<T, const N: T>` there is probably no risk of
+ // soundness bugs, but when we support generic const parameter types this will need to be
+ // revisited.
+ }
_ => {
tcx.sess
.struct_span_err(span, &format!("cannot specialize on predicate `{}`", predicate))
@@ -524,6 +527,8 @@ fn trait_predicate_kind<'tcx>(
ty::PredicateKind::Clause(ty::Clause::RegionOutlives(_))
| ty::PredicateKind::Clause(ty::Clause::TypeOutlives(_))
| ty::PredicateKind::Clause(ty::Clause::Projection(_))
+ | ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(..))
+ | ty::PredicateKind::AliasEq(..)
| ty::PredicateKind::WellFormed(_)
| ty::PredicateKind::Subtype(_)
| ty::PredicateKind::Coerce(_)
diff --git a/compiler/rustc_hir_analysis/src/lib.rs b/compiler/rustc_hir_analysis/src/lib.rs
index 02548ae89..33c132fd5 100644
--- a/compiler/rustc_hir_analysis/src/lib.rs
+++ b/compiler/rustc_hir_analysis/src/lib.rs
@@ -98,29 +98,31 @@ mod outlives;
pub mod structured_errors;
mod variance;
-use rustc_errors::{struct_span_err, ErrorGuaranteed};
+use rustc_errors::ErrorGuaranteed;
+use rustc_errors::{DiagnosticMessage, SubdiagnosticMessage};
use rustc_hir as hir;
-use rustc_hir::def_id::DefId;
-use rustc_hir::{Node, CRATE_HIR_ID};
+use rustc_hir::Node;
use rustc_infer::infer::{InferOk, TyCtxtInferExt};
+use rustc_macros::fluent_messages;
use rustc_middle::middle;
use rustc_middle::ty::query::Providers;
use rustc_middle::ty::{self, Ty, TyCtxt};
use rustc_middle::util;
use rustc_session::{config::EntryFnType, parse::feature_err};
+use rustc_span::def_id::{DefId, LocalDefId, CRATE_DEF_ID};
use rustc_span::{symbol::sym, Span, DUMMY_SP};
use rustc_target::spec::abi::Abi;
use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt as _;
use rustc_trait_selection::traits::{self, ObligationCause, ObligationCauseCode};
-use std::iter;
use std::ops::Not;
use astconv::AstConv;
use bounds::Bounds;
+fluent_messages! { "../locales/en-US.ftl" }
+
fn require_c_abi_if_c_variadic(tcx: TyCtxt<'_>, decl: &hir::FnDecl<'_>, abi: Abi, span: Span) {
- const ERROR_HEAD: &str = "C-variadic function must have a compatible calling convention";
const CONVENTIONS_UNSTABLE: &str = "`C`, `cdecl`, `win64`, `sysv64` or `efiapi`";
const CONVENTIONS_STABLE: &str = "`C` or `cdecl`";
const UNSTABLE_EXPLAIN: &str =
@@ -152,8 +154,7 @@ fn require_c_abi_if_c_variadic(tcx: TyCtxt<'_>, decl: &hir::FnDecl<'_>, abi: Abi
(true, false) => CONVENTIONS_UNSTABLE,
};
- let mut err = struct_span_err!(tcx.sess, span, E0045, "{}, like {}", ERROR_HEAD, conventions);
- err.span_label(span, ERROR_HEAD).emit();
+ tcx.sess.emit_err(errors::VariadicFunctionCompatibleConvention { span, conventions });
}
fn require_same_types<'tcx>(
@@ -182,19 +183,18 @@ fn require_same_types<'tcx>(
}
fn check_main_fn_ty(tcx: TyCtxt<'_>, main_def_id: DefId) {
- let main_fnsig = tcx.fn_sig(main_def_id);
+ let main_fnsig = tcx.fn_sig(main_def_id).subst_identity();
let main_span = tcx.def_span(main_def_id);
- fn main_fn_diagnostics_hir_id(tcx: TyCtxt<'_>, def_id: DefId, sp: Span) -> hir::HirId {
+ fn main_fn_diagnostics_def_id(tcx: TyCtxt<'_>, def_id: DefId, sp: Span) -> LocalDefId {
if let Some(local_def_id) = def_id.as_local() {
- let hir_id = tcx.hir().local_def_id_to_hir_id(local_def_id);
- let hir_type = tcx.type_of(local_def_id);
+ let hir_type = tcx.type_of(local_def_id).subst_identity();
if !matches!(hir_type.kind(), ty::FnDef(..)) {
span_bug!(sp, "main has a non-function type: found `{}`", hir_type);
}
- hir_id
+ local_def_id
} else {
- CRATE_HIR_ID
+ CRATE_DEF_ID
}
}
@@ -205,7 +205,7 @@ 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(_, generics, _), .. })) => {
- generics.params.is_empty().not().then(|| generics.span)
+ generics.params.is_empty().not().then_some(generics.span)
}
_ => {
span_bug!(tcx.def_span(def_id), "main has a non-function type");
@@ -251,58 +251,35 @@ fn check_main_fn_ty(tcx: TyCtxt<'_>, main_def_id: DefId) {
}
let mut error = false;
- let main_diagnostics_hir_id = main_fn_diagnostics_hir_id(tcx, main_def_id, main_span);
+ let main_diagnostics_def_id = main_fn_diagnostics_def_id(tcx, main_def_id, main_span);
let main_fn_generics = tcx.generics_of(main_def_id);
let main_fn_predicates = tcx.predicates_of(main_def_id);
if main_fn_generics.count() != 0 || !main_fnsig.bound_vars().is_empty() {
let generics_param_span = main_fn_generics_params_span(tcx, main_def_id);
- let msg = "`main` function is not allowed to have generic \
- parameters";
- let mut diag =
- struct_span_err!(tcx.sess, generics_param_span.unwrap_or(main_span), E0131, "{}", msg);
- if let Some(generics_param_span) = generics_param_span {
- let label = "`main` cannot have generic parameters";
- diag.span_label(generics_param_span, label);
- }
- diag.emit();
+ tcx.sess.emit_err(errors::MainFunctionGenericParameters {
+ span: generics_param_span.unwrap_or(main_span),
+ label_span: generics_param_span,
+ });
error = true;
} else if !main_fn_predicates.predicates.is_empty() {
// generics may bring in implicit predicates, so we skip this check if generics is present.
let generics_where_clauses_span = main_fn_where_clauses_span(tcx, main_def_id);
- let mut diag = struct_span_err!(
- tcx.sess,
- generics_where_clauses_span.unwrap_or(main_span),
- E0646,
- "`main` function is not allowed to have a `where` clause"
- );
- if let Some(generics_where_clauses_span) = generics_where_clauses_span {
- diag.span_label(generics_where_clauses_span, "`main` cannot have a `where` clause");
- }
- diag.emit();
+ tcx.sess.emit_err(errors::WhereClauseOnMain {
+ span: generics_where_clauses_span.unwrap_or(main_span),
+ generics_span: generics_where_clauses_span,
+ });
error = true;
}
let main_asyncness = tcx.asyncness(main_def_id);
if let hir::IsAsync::Async = main_asyncness {
- let mut diag = struct_span_err!(
- tcx.sess,
- main_span,
- E0752,
- "`main` function is not allowed to be `async`"
- );
let asyncness_span = main_fn_asyncness_span(tcx, main_def_id);
- if let Some(asyncness_span) = asyncness_span {
- diag.span_label(asyncness_span, "`main` function is not allowed to be `async`");
- }
- diag.emit();
+ tcx.sess.emit_err(errors::MainFunctionAsync { span: main_span, asyncness: asyncness_span });
error = true;
}
for attr in tcx.get_attrs(main_def_id, sym::track_caller) {
- tcx.sess
- .struct_span_err(attr.span, "`main` function is not allowed to be `#[track_caller]`")
- .span_label(main_span, "`main` function is not allowed to be `#[track_caller]`")
- .emit();
+ tcx.sess.emit_err(errors::TrackCallerOnMain { span: attr.span, annotated: main_span });
error = true;
}
@@ -315,9 +292,7 @@ fn check_main_fn_ty(tcx: TyCtxt<'_>, main_def_id: DefId) {
let return_ty = main_fnsig.output();
let return_ty_span = main_fn_return_type_span(tcx, main_def_id).unwrap_or(main_span);
if !return_ty.bound_vars().is_empty() {
- let msg = "`main` function return type is not allowed to have generic \
- parameters";
- struct_span_err!(tcx.sess, return_ty_span, E0131, "{}", msg).emit();
+ tcx.sess.emit_err(errors::MainFunctionReturnTypeGeneric { span: return_ty_span });
error = true;
}
let return_ty = return_ty.skip_binder();
@@ -326,7 +301,7 @@ fn check_main_fn_ty(tcx: TyCtxt<'_>, main_def_id: DefId) {
let param_env = ty::ParamEnv::empty();
let cause = traits::ObligationCause::new(
return_ty_span,
- main_diagnostics_hir_id,
+ main_diagnostics_def_id,
ObligationCauseCode::MainFunctionType,
);
let ocx = traits::ObligationCtxt::new(&infcx);
@@ -349,14 +324,14 @@ fn check_main_fn_ty(tcx: TyCtxt<'_>, main_def_id: DefId) {
}
let se_ty = tcx.mk_fn_ptr(expected_return_type.map_bound(|expected_return_type| {
- tcx.mk_fn_sig(iter::empty(), expected_return_type, false, hir::Unsafety::Normal, Abi::Rust)
+ tcx.mk_fn_sig([], expected_return_type, false, hir::Unsafety::Normal, Abi::Rust)
}));
require_same_types(
tcx,
&ObligationCause::new(
main_span,
- main_diagnostics_hir_id,
+ main_diagnostics_def_id,
ObligationCauseCode::MainFunctionType,
),
se_ty,
@@ -367,63 +342,35 @@ fn check_start_fn_ty(tcx: TyCtxt<'_>, start_def_id: DefId) {
let start_def_id = start_def_id.expect_local();
let start_id = tcx.hir().local_def_id_to_hir_id(start_def_id);
let start_span = tcx.def_span(start_def_id);
- let start_t = tcx.type_of(start_def_id);
+ let start_t = tcx.type_of(start_def_id).subst_identity();
match start_t.kind() {
ty::FnDef(..) => {
if let Some(Node::Item(it)) = tcx.hir().find(start_id) {
if let hir::ItemKind::Fn(sig, generics, _) = &it.kind {
let mut error = false;
if !generics.params.is_empty() {
- struct_span_err!(
- tcx.sess,
- generics.span,
- E0132,
- "start function is not allowed to have type parameters"
- )
- .span_label(generics.span, "start function cannot have type parameters")
- .emit();
+ tcx.sess.emit_err(errors::StartFunctionParameters { span: generics.span });
error = true;
}
if generics.has_where_clause_predicates {
- struct_span_err!(
- tcx.sess,
- generics.where_clause_span,
- E0647,
- "start function is not allowed to have a `where` clause"
- )
- .span_label(
- generics.where_clause_span,
- "start function cannot have a `where` clause",
- )
- .emit();
+ tcx.sess.emit_err(errors::StartFunctionWhere {
+ span: generics.where_clause_span,
+ });
error = true;
}
if let hir::IsAsync::Async = sig.header.asyncness {
let span = tcx.def_span(it.owner_id);
- struct_span_err!(
- tcx.sess,
- span,
- E0752,
- "`start` is not allowed to be `async`"
- )
- .span_label(span, "`start` is not allowed to be `async`")
- .emit();
+ tcx.sess.emit_err(errors::StartAsync { span: span });
error = true;
}
let attrs = tcx.hir().attrs(start_id);
for attr in attrs {
if attr.has_name(sym::track_caller) {
- tcx.sess
- .struct_span_err(
- attr.span,
- "`start` is not allowed to be `#[track_caller]`",
- )
- .span_label(
- start_span,
- "`start` is not allowed to be `#[track_caller]`",
- )
- .emit();
+ tcx.sess.emit_err(errors::StartTrackCaller {
+ span: attr.span,
+ start: start_span,
+ });
error = true;
}
}
@@ -435,7 +382,7 @@ fn check_start_fn_ty(tcx: TyCtxt<'_>, start_def_id: DefId) {
}
let se_ty = tcx.mk_fn_ptr(ty::Binder::dummy(tcx.mk_fn_sig(
- [tcx.types.isize, tcx.mk_imm_ptr(tcx.mk_imm_ptr(tcx.types.u8))].iter().cloned(),
+ [tcx.types.isize, tcx.mk_imm_ptr(tcx.mk_imm_ptr(tcx.types.u8))],
tcx.types.isize,
false,
hir::Unsafety::Normal,
@@ -444,9 +391,13 @@ fn check_start_fn_ty(tcx: TyCtxt<'_>, start_def_id: DefId) {
require_same_types(
tcx,
- &ObligationCause::new(start_span, start_id, ObligationCauseCode::StartFunctionType),
+ &ObligationCause::new(
+ start_span,
+ start_def_id,
+ ObligationCauseCode::StartFunctionType,
+ ),
se_ty,
- tcx.mk_fn_ptr(tcx.fn_sig(start_def_id)),
+ tcx.mk_fn_ptr(tcx.fn_sig(start_def_id).subst_identity()),
);
}
_ => {
diff --git a/compiler/rustc_hir_analysis/src/outlives/explicit.rs b/compiler/rustc_hir_analysis/src/outlives/explicit.rs
index 663f1c49d..9ee678597 100644
--- a/compiler/rustc_hir_analysis/src/outlives/explicit.rs
+++ b/compiler/rustc_hir_analysis/src/outlives/explicit.rs
@@ -54,7 +54,9 @@ impl<'tcx> ExplicitPredicatesMap<'tcx> {
ty::PredicateKind::Clause(ty::Clause::Trait(..))
| ty::PredicateKind::Clause(ty::Clause::Projection(..))
+ | ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(..))
| ty::PredicateKind::WellFormed(..)
+ | ty::PredicateKind::AliasEq(..)
| ty::PredicateKind::ObjectSafe(..)
| ty::PredicateKind::ClosureKind(..)
| ty::PredicateKind::Subtype(..)
diff --git a/compiler/rustc_hir_analysis/src/outlives/implicit_infer.rs b/compiler/rustc_hir_analysis/src/outlives/implicit_infer.rs
index 925042436..a8b33c74b 100644
--- a/compiler/rustc_hir_analysis/src/outlives/implicit_infer.rs
+++ b/compiler/rustc_hir_analysis/src/outlives/implicit_infer.rs
@@ -46,7 +46,7 @@ pub(super) fn infer_predicates(
// For field of type &'a T (reference) or Adt
// (struct/enum/union) there will be outlive
// requirements for adt_def.
- let field_ty = tcx.type_of(field_def.did);
+ let field_ty = tcx.type_of(field_def.did).subst_identity();
let field_span = tcx.def_span(field_def.did);
insert_required_predicates_to_be_wf(
tcx,
diff --git a/compiler/rustc_hir_analysis/src/outlives/utils.rs b/compiler/rustc_hir_analysis/src/outlives/utils.rs
index 9459c5f54..c5c5f63a1 100644
--- a/compiler/rustc_hir_analysis/src/outlives/utils.rs
+++ b/compiler/rustc_hir_analysis/src/outlives/utils.rs
@@ -170,6 +170,8 @@ fn is_free_region(region: Region<'_>) -> bool {
// ignore it. We can't put it on the struct header anyway.
ty::ReLateBound(..) => false,
+ ty::ReError(_) => false,
+
// These regions don't appear in types from type declarations:
ty::ReErased | ty::ReVar(..) | ty::RePlaceholder(..) | ty::ReFree(..) => {
bug!("unexpected region in outlives inference: {:?}", region);
diff --git a/compiler/rustc_hir_analysis/src/structured_errors/missing_cast_for_variadic_arg.rs b/compiler/rustc_hir_analysis/src/structured_errors/missing_cast_for_variadic_arg.rs
index 324df313e..089491bef 100644
--- a/compiler/rustc_hir_analysis/src/structured_errors/missing_cast_for_variadic_arg.rs
+++ b/compiler/rustc_hir_analysis/src/structured_errors/missing_cast_for_variadic_arg.rs
@@ -1,6 +1,6 @@
use crate::structured_errors::StructuredDiagnostic;
use rustc_errors::{Applicability, DiagnosticBuilder, DiagnosticId, ErrorGuaranteed};
-use rustc_middle::ty::{Ty, TypeVisitable};
+use rustc_middle::ty::{Ty, TypeVisitableExt};
use rustc_session::Session;
use rustc_span::Span;
diff --git a/compiler/rustc_hir_analysis/src/structured_errors/sized_unsized_cast.rs b/compiler/rustc_hir_analysis/src/structured_errors/sized_unsized_cast.rs
index bb6088054..3b9fb3678 100644
--- a/compiler/rustc_hir_analysis/src/structured_errors/sized_unsized_cast.rs
+++ b/compiler/rustc_hir_analysis/src/structured_errors/sized_unsized_cast.rs
@@ -1,6 +1,6 @@
use crate::structured_errors::StructuredDiagnostic;
use rustc_errors::{DiagnosticBuilder, DiagnosticId, ErrorGuaranteed};
-use rustc_middle::ty::{Ty, TypeVisitable};
+use rustc_middle::ty::{Ty, TypeVisitableExt};
use rustc_session::Session;
use rustc_span::Span;
diff --git a/compiler/rustc_hir_analysis/src/structured_errors/wrong_number_of_generic_args.rs b/compiler/rustc_hir_analysis/src/structured_errors/wrong_number_of_generic_args.rs
index 9133e6540..cae884ae8 100644
--- a/compiler/rustc_hir_analysis/src/structured_errors/wrong_number_of_generic_args.rs
+++ b/compiler/rustc_hir_analysis/src/structured_errors/wrong_number_of_generic_args.rs
@@ -423,7 +423,7 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> {
fn get_unbound_associated_types(&self) -> Vec<String> {
if self.tcx.is_trait(self.def_id) {
- let items: &AssocItems<'_> = self.tcx.associated_items(self.def_id);
+ let items: &AssocItems = self.tcx.associated_items(self.def_id);
items
.in_definition_order()
.filter(|item| item.kind == AssocKind::Type)
@@ -439,7 +439,7 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> {
fn create_error_message(&self) -> String {
let def_path = self.tcx.def_path_str(self.def_id);
- let def_kind = self.tcx.def_kind(self.def_id).descr(self.def_id);
+ let def_kind = self.tcx.def_descr(self.def_id);
let (quantifier, bound) = self.get_quantifier_and_bound();
let kind = self.kind();
let provided_lt_args = self.num_provided_lifetime_args();
@@ -462,7 +462,7 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> {
if self.gen_args.span_ext().is_some() {
format!(
- "this {} takes {}{} {} argument{} but {} {} supplied",
+ "{} takes {}{} {} argument{} but {} {} supplied",
def_kind,
quantifier,
bound,
@@ -990,7 +990,7 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> {
};
let msg = {
- let def_kind = self.tcx.def_kind(self.def_id).descr(self.def_id);
+ let def_kind = self.tcx.def_descr(self.def_id);
let (quantifier, bound) = self.get_quantifier_and_bound();
let params = if bound == 0 {
diff --git a/compiler/rustc_hir_analysis/src/variance/constraints.rs b/compiler/rustc_hir_analysis/src/variance/constraints.rs
index 5e4d82b6f..408bec71e 100644
--- a/compiler/rustc_hir_analysis/src/variance/constraints.rs
+++ b/compiler/rustc_hir_analysis/src/variance/constraints.rs
@@ -101,7 +101,7 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
let inferred_start = self.terms_cx.inferred_starts[&def_id];
let current_item = &CurrentItem { inferred_start };
- match tcx.type_of(def_id).kind() {
+ match tcx.type_of(def_id).subst_identity().kind() {
ty::Adt(def, _) => {
// Not entirely obvious: constraints on structs/enums do not
// affect the variance of their type parameters. See discussion
@@ -112,14 +112,18 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
for field in def.all_fields() {
self.add_constraints_from_ty(
current_item,
- tcx.type_of(field.did),
+ tcx.type_of(field.did).subst_identity(),
self.covariant,
);
}
}
ty::FnDef(..) => {
- self.add_constraints_from_sig(current_item, tcx.fn_sig(def_id), self.covariant);
+ self.add_constraints_from_sig(
+ current_item,
+ tcx.fn_sig(def_id).subst_identity(),
+ self.covariant,
+ );
}
ty::Error(_) => {}
@@ -221,8 +225,7 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
}
ty::Ref(region, ty, mutbl) => {
- let contra = self.contravariant(variance);
- self.add_constraints_from_region(current, region, contra);
+ self.add_constraints_from_region(current, region, variance);
self.add_constraints_from_mt(current, &ty::TypeAndMut { ty, mutbl }, variance);
}
@@ -254,9 +257,8 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
}
ty::Dynamic(data, r, _) => {
- // The type `Foo<T+'a>` is contravariant w/r/t `'a`:
- let contra = self.contravariant(variance);
- self.add_constraints_from_region(current, r, contra);
+ // The type `dyn Trait<T> +'a` is covariant w/r/t `'a`:
+ self.add_constraints_from_region(current, r, variance);
if let Some(poly_trait_ref) = data.principal() {
self.add_constraints_from_invariant_substs(
@@ -291,12 +293,12 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
// types, where we use Error as the Self type
}
- ty::Placeholder(..) | ty::GeneratorWitness(..) | ty::Bound(..) | ty::Infer(..) => {
- bug!(
- "unexpected type encountered in \
- variance inference: {}",
- ty
- );
+ ty::Placeholder(..)
+ | ty::GeneratorWitness(..)
+ | ty::GeneratorWitnessMIR(..)
+ | ty::Bound(..)
+ | ty::Infer(..) => {
+ bug!("unexpected type encountered in variance inference: {}", ty);
}
}
}
@@ -407,6 +409,8 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
// way early-bound regions do, so we skip them here.
}
+ ty::ReError(_) => {}
+
ty::ReFree(..) | ty::ReVar(..) | ty::RePlaceholder(..) | ty::ReErased => {
// We don't expect to see anything but 'static or bound
// regions when visiting member types or method types.
diff --git a/compiler/rustc_hir_analysis/src/variance/mod.rs b/compiler/rustc_hir_analysis/src/variance/mod.rs
index 079070be2..5d5c8ca60 100644
--- a/compiler/rustc_hir_analysis/src/variance/mod.rs
+++ b/compiler/rustc_hir_analysis/src/variance/mod.rs
@@ -99,7 +99,7 @@ fn variance_of_opaque(tcx: TyCtxt<'_>, item_def_id: LocalDefId) -> &[ty::Varianc
}
}
- impl<'tcx> ty::TypeVisitor<'tcx> for OpaqueTypeLifetimeCollector<'tcx> {
+ impl<'tcx> ty::TypeVisitor<TyCtxt<'tcx>> for OpaqueTypeLifetimeCollector<'tcx> {
#[instrument(level = "trace", skip(self), ret)]
fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> {
if let ty::RegionKind::ReEarlyBound(ebr) = r.kind() {
diff --git a/compiler/rustc_hir_analysis/src/variance/solve.rs b/compiler/rustc_hir_analysis/src/variance/solve.rs
index a17edb598..c27c176e3 100644
--- a/compiler/rustc_hir_analysis/src/variance/solve.rs
+++ b/compiler/rustc_hir_analysis/src/variance/solve.rs
@@ -103,7 +103,7 @@ impl<'a, 'tcx> SolveContext<'a, 'tcx> {
self.enforce_const_invariance(generics, variances);
// Functions are permitted to have unused generic parameters: make those invariant.
- if let ty::FnDef(..) = tcx.type_of(def_id).kind() {
+ if let ty::FnDef(..) = tcx.type_of(def_id).subst_identity().kind() {
for variance in variances.iter_mut() {
if *variance == ty::Bivariant {
*variance = ty::Invariant;
diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs
index f74c551a4..c021fca71 100644
--- a/compiler/rustc_hir_pretty/src/lib.rs
+++ b/compiler/rustc_hir_pretty/src/lib.rs
@@ -9,9 +9,7 @@ use rustc_ast_pretty::pp::{self, Breaks};
use rustc_ast_pretty::pprust::{Comments, PrintState};
use rustc_hir as hir;
use rustc_hir::LifetimeParamKind;
-use rustc_hir::{
- BindingAnnotation, ByRef, GenericArg, GenericParam, GenericParamKind, Mutability, Node, Term,
-};
+use rustc_hir::{BindingAnnotation, ByRef, GenericArg, GenericParam, GenericParamKind, Node, Term};
use rustc_hir::{GenericBound, PatKind, RangeEnd, TraitBoundModifier};
use rustc_span::source_map::SourceMap;
use rustc_span::symbol::{kw, Ident, IdentPrinter, Symbol};
@@ -360,7 +358,7 @@ impl<'a> State<'a> {
self.print_anon_const(e);
self.word(")");
}
- hir::TyKind::Err => {
+ hir::TyKind::Err(_) => {
self.popen();
self.word("/*ERROR*/");
self.pclose();
@@ -1561,7 +1559,7 @@ impl<'a> State<'a> {
self.word_space("yield");
self.print_expr_maybe_paren(expr, parser::PREC_JUMP);
}
- hir::ExprKind::Err => {
+ hir::ExprKind::Err(_) => {
self.popen();
self.word("/*ERROR*/");
self.pclose();
@@ -1746,7 +1744,7 @@ impl<'a> State<'a> {
if by_ref == ByRef::Yes {
self.word_nbsp("ref");
}
- if mutbl == Mutability::Mut {
+ if mutbl.is_mut() {
self.word_nbsp("mut");
}
self.print_ident(ident);
diff --git a/compiler/rustc_error_messages/locales/en-US/hir_typeck.ftl b/compiler/rustc_hir_typeck/locales/en-US.ftl
index ca72b7faa..adfcbc36a 100644
--- a/compiler/rustc_error_messages/locales/en-US/hir_typeck.ftl
+++ b/compiler/rustc_hir_typeck/locales/en-US.ftl
@@ -1,17 +1,26 @@
-hir_typeck_fru_note = this expression may have been misinterpreted as a `..` range expression
-hir_typeck_fru_expr = this expression does not end in a comma...
-hir_typeck_fru_expr2 = ... so this is interpreted as a `..` range expression, instead of functional record update syntax
-hir_typeck_fru_suggestion =
- to set the remaining fields{$expr ->
- [NONE]{""}
- *[other] {" "}from `{$expr}`
- }, separate the last named field with a comma
-
hir_typeck_field_multiply_specified_in_initializer =
field `{$ident}` specified more than once
.label = used more than once
.previous_use_label = first use of `{$ident}`
+hir_typeck_copy_impl_on_type_with_dtor =
+ the trait `Copy` may not be implemented for this type; the type has a destructor
+ .label = `Copy` not allowed on types with destructors
+
+hir_typeck_multiple_relaxed_default_bounds =
+ type parameter has more than one relaxed default bound, only one is supported
+
+hir_typeck_copy_impl_on_non_adt =
+ the trait `Copy` may not be implemented for this type
+ .label = type is not a structure or enumeration
+
+hir_typeck_trait_object_declared_with_no_traits =
+ at least one trait is required for an object type
+ .alias_span = this alias does not contain a trait
+
+hir_typeck_functional_record_update_on_non_struct =
+ functional record update syntax requires a struct
+
hir_typeck_return_stmt_outside_of_fn_body =
return statement outside of function body
.encl_body_label = the return is part of this body...
@@ -26,9 +35,6 @@ hir_typeck_struct_expr_non_exhaustive =
hir_typeck_method_call_on_unknown_type =
the type of this value must be known to call a method on a raw pointer on it
-hir_typeck_functional_record_update_on_non_struct =
- functional record update syntax requires a struct
-
hir_typeck_address_of_temporary_taken = cannot take address of a temporary
.label = temporary value
@@ -44,9 +50,6 @@ hir_typeck_missing_parentheses_in_range = can't call method `{$method_name}` on
hir_typeck_add_missing_parentheses_in_range = you must surround the range in parentheses to call its `{$func_name}` function
-hir_typeck_op_trait_generic_params =
- `{$method_name}` must not have any generic parameters
-
hir_typeck_lang_start_incorrect_number_params = incorrect number of parameters for the `start` lang item
hir_typeck_lang_start_incorrect_number_params_note_expected_count = the `start` lang item should have four parameters, but found {$found_param_count}
@@ -57,3 +60,20 @@ hir_typeck_lang_start_incorrect_param = parameter {$param_num} of the `start` la
hir_typeck_lang_start_incorrect_ret_ty = the return type of the `start` lang item is incorrect
.suggestion = change the type from `{$found_ty}` to `{$expected_ty}`
+
+hir_typeck_help_set_edition_cargo = set `edition = "{$edition}"` in `Cargo.toml`
+hir_typeck_help_set_edition_standalone = pass `--edition {$edition}` to `rustc`
+hir_typeck_note_edition_guide = for more on editions, read https://doc.rust-lang.org/edition-guide
+
+hir_typeck_convert_to_str = try converting the passed type into a `&str`
+
+hir_typeck_op_trait_generic_params = `{$method_name}` must not have any generic parameters
+
+hir_typeck_fru_note = this expression may have been misinterpreted as a `..` range expression
+hir_typeck_fru_expr = this expression does not end in a comma...
+hir_typeck_fru_expr2 = ... so this is interpreted as a `..` range expression, instead of functional record update syntax
+hir_typeck_fru_suggestion =
+ to set the remaining fields{$expr ->
+ [NONE]{""}
+ *[other] {" "}from `{$expr}`
+ }, separate the last named field with a comma
diff --git a/compiler/rustc_hir_typeck/src/_match.rs b/compiler/rustc_hir_typeck/src/_match.rs
index b6f19d3cc..e19ef2ff3 100644
--- a/compiler/rustc_hir_typeck/src/_match.rs
+++ b/compiler/rustc_hir_typeck/src/_match.rs
@@ -41,7 +41,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// #55810: Type check patterns first so we get types for all bindings.
let scrut_span = scrut.span.find_ancestor_inside(expr.span).unwrap_or(scrut.span);
for arm in arms {
- self.check_pat_top(&arm.pat, scrutinee_ty, Some(scrut_span), true);
+ self.check_pat_top(&arm.pat, scrutinee_ty, Some(scrut_span), Some(scrut));
}
// Now typecheck the blocks.
@@ -188,8 +188,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let hir = self.tcx.hir();
// First, check that we're actually in the tail of a function.
- let hir::Node::Expr(hir::Expr { kind: hir::ExprKind::Block(block, _), .. }) =
- hir.get(self.body_id) else { return; };
+ let Some(body_id) = hir.maybe_body_owned_by(self.body_id) else { return; };
+ let body = hir.body(body_id);
+ let hir::ExprKind::Block(block, _) = body.value.kind else { return; };
let Some(hir::Stmt { kind: hir::StmtKind::Semi(last_expr), .. })
= block.innermost_block().stmts.last() else { return; };
if last_expr.hir_id != expr.hir_id {
@@ -198,7 +199,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// Next, make sure that we have no type expectation.
let Some(ret) = hir
- .find_by_def_id(self.body_id.owner.def_id)
+ .find_by_def_id(self.body_id)
.and_then(|owner| owner.fn_decl())
.map(|decl| decl.output.span()) else { return; };
let Expectation::IsLast(stmt) = expectation else {
diff --git a/compiler/rustc_hir_typeck/src/callee.rs b/compiler/rustc_hir_typeck/src/callee.rs
index b617821fb..6a0d5c011 100644
--- a/compiler/rustc_hir_typeck/src/callee.rs
+++ b/compiler/rustc_hir_typeck/src/callee.rs
@@ -21,7 +21,7 @@ use rustc_middle::ty::adjustment::{
Adjust, Adjustment, AllowTwoPhase, AutoBorrow, AutoBorrowMutability,
};
use rustc_middle::ty::SubstsRef;
-use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitable};
+use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt};
use rustc_span::def_id::LocalDefId;
use rustc_span::symbol::{sym, Ident};
use rustc_span::Span;
@@ -156,7 +156,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// fnmut vs fnonce. If so, we have to defer further processing.
if self.closure_kind(substs).is_none() {
let closure_sig = substs.as_closure().sig();
- let closure_sig = self.replace_bound_vars_with_fresh_vars(
+ let closure_sig = self.instantiate_binder_with_fresh_vars(
call_expr.span,
infer::FnCall,
closure_sig,
@@ -232,7 +232,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let Some(trait_def_id) = opt_trait_def_id else { continue };
let opt_input_type = opt_arg_exprs.map(|arg_exprs| {
- self.tcx.mk_tup(arg_exprs.iter().map(|e| {
+ self.tcx.mk_tup_from_iter(arg_exprs.iter().map(|e| {
self.next_ty_var(TypeVariableOrigin {
kind: TypeVariableOriginKind::TypeInference,
span: e.span,
@@ -247,6 +247,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
adjusted_ty,
opt_input_type.as_ref().map(slice::from_ref),
) {
+ // Check for `self` receiver on the method, otherwise we can't use this as a `Fn*` trait.
+ if !self.tcx.associated_item(ok.value.def_id).fn_has_self_parameter {
+ self.tcx.sess.delay_span_bug(
+ call_expr.span,
+ "input to overloaded call fn is not a self receiver",
+ );
+ return None;
+ }
+
let method = self.register_infer_ok_obligations(ok);
let mut autoref = None;
if borrow {
@@ -257,7 +266,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// caused an error elsewhere.
self.tcx
.sess
- .delay_span_bug(call_expr.span, "input to call/call_mut is not a ref?");
+ .delay_span_bug(call_expr.span, "input to call/call_mut is not a ref");
return None;
};
@@ -271,6 +280,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
target: method.sig.inputs()[0],
});
}
+
return Some((autoref, method));
}
}
@@ -367,7 +377,7 @@ 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.bound_fn_sig(def_id).subst(self.tcx, 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
@@ -428,7 +438,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let err = self.report_invalid_callee(call_expr, callee_expr, callee_ty, arg_exprs);
- return self.tcx.ty_error_with_guaranteed(err);
+ return self.tcx.ty_error(err);
}
};
@@ -437,7 +447,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// renormalize the associated types at this point, since they
// previously appeared within a `Binder<>` and hence would not
// have been normalized before.
- let fn_sig = self.replace_bound_vars_with_fresh_vars(call_expr.span, infer::FnCall, fn_sig);
+ let fn_sig = self.instantiate_binder_with_fresh_vars(call_expr.span, infer::FnCall, fn_sig);
let fn_sig = self.normalize(call_expr.span, fn_sig);
// Call the generic checker.
@@ -661,7 +671,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
&& !self.type_is_sized_modulo_regions(self.param_env, output_ty, callee_expr.span)
{
let descr = match maybe_def {
- DefIdOrName::DefId(def_id) => self.tcx.def_kind(def_id).descr(def_id),
+ DefIdOrName::DefId(def_id) => self.tcx.def_descr(def_id),
DefIdOrName::Name(name) => name,
};
err.span_label(
@@ -823,7 +833,7 @@ impl<'a, 'tcx> DeferredCallResolution<'tcx> {
);
err.help(
"make sure the `fn`/`fn_mut`/`fn_once` lang items are defined \
- and have associated `call`/`call_mut`/`call_once` functions",
+ and have correctly defined `call`/`call_mut`/`call_once` methods",
);
err.emit();
}
diff --git a/compiler/rustc_hir_typeck/src/cast.rs b/compiler/rustc_hir_typeck/src/cast.rs
index 712f9b87a..316c2a7ee 100644
--- a/compiler/rustc_hir_typeck/src/cast.rs
+++ b/compiler/rustc_hir_typeck/src/cast.rs
@@ -41,7 +41,7 @@ use rustc_middle::mir::Mutability;
use rustc_middle::ty::adjustment::AllowTwoPhase;
use rustc_middle::ty::cast::{CastKind, CastTy};
use rustc_middle::ty::error::TypeError;
-use rustc_middle::ty::{self, Ty, TypeAndMut, TypeVisitable, VariantDef};
+use rustc_middle::ty::{self, Ty, TypeAndMut, TypeVisitableExt, VariantDef};
use rustc_session::lint;
use rustc_session::Session;
use rustc_span::def_id::{DefId, LOCAL_CRATE};
@@ -130,6 +130,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
| ty::Float(_)
| ty::Array(..)
| ty::GeneratorWitness(..)
+ | ty::GeneratorWitnessMIR(..)
| ty::RawPtr(_)
| ty::Ref(..)
| ty::FnDef(..)
diff --git a/compiler/rustc_hir_typeck/src/check.rs b/compiler/rustc_hir_typeck/src/check.rs
index 57feefbca..bf8259ff7 100644
--- a/compiler/rustc_hir_typeck/src/check.rs
+++ b/compiler/rustc_hir_typeck/src/check.rs
@@ -43,7 +43,7 @@ pub(super) fn check_fn<'a, 'tcx>(
let ret_ty =
fcx.register_infer_ok_obligations(fcx.infcx.replace_opaque_types_with_inference_vars(
declared_ret_ty,
- body.value.hir_id,
+ fn_def_id,
decl.output.span(),
fcx.param_env,
));
@@ -74,15 +74,13 @@ pub(super) fn check_fn<'a, 'tcx>(
// C-variadic fns also have a `VaList` input that's not listed in `fn_sig`
// (as it's created inside the body itself, not passed in from outside).
- let maybe_va_list = if fn_sig.c_variadic {
+ let maybe_va_list = fn_sig.c_variadic.then(|| {
let span = body.params.last().unwrap().span;
let va_list_did = tcx.require_lang_item(LangItem::VaList, Some(span));
let region = fcx.next_region_var(RegionVariableOrigin::MiscVariable(span));
- Some(tcx.bound_type_of(va_list_did).subst(tcx, &[region.into()]))
- } else {
- None
- };
+ tcx.type_of(va_list_did).subst(tcx, &[region.into()])
+ });
// Add formal parameters.
let inputs_hir = hir.fn_decl_by_hir_id(fn_id).map(|decl| &decl.inputs);
@@ -90,7 +88,7 @@ pub(super) fn check_fn<'a, 'tcx>(
for (idx, (param_ty, param)) in inputs_fn.chain(maybe_va_list).zip(body.params).enumerate() {
// Check the pattern.
let ty_span = try { inputs_hir?.get(idx)?.span };
- fcx.check_pat_top(&param.pat, param_ty, ty_span, false);
+ fcx.check_pat_top(&param.pat, param_ty, ty_span, None);
// Check that argument is Sized.
// The check for a non-trivial pattern is a hack to avoid duplicate warnings
@@ -130,7 +128,12 @@ pub(super) fn check_fn<'a, 'tcx>(
let gen_ty = if let (Some(_), Some(gen_kind)) = (can_be_generator, body.generator_kind) {
let interior = fcx
.next_ty_var(TypeVariableOrigin { kind: TypeVariableOriginKind::MiscVariable, span });
- fcx.deferred_generator_interiors.borrow_mut().push((body.id(), interior, gen_kind));
+ fcx.deferred_generator_interiors.borrow_mut().push((
+ fn_def_id,
+ body.id(),
+ interior,
+ gen_kind,
+ ));
let (resume_ty, yield_ty) = fcx.resume_yield_tys.unwrap();
Some(GeneratorTypes {
@@ -167,12 +170,12 @@ pub(super) fn check_fn<'a, 'tcx>(
// Check that a function marked as `#[panic_handler]` has signature `fn(&PanicInfo) -> !`
if let Some(panic_impl_did) = tcx.lang_items().panic_impl()
- && panic_impl_did == hir.local_def_id(fn_id).to_def_id()
+ && panic_impl_did == fn_def_id.to_def_id()
{
check_panic_info_fn(tcx, panic_impl_did.expect_local(), fn_sig, decl, declared_ret_ty);
}
- if let Some(lang_start_defid) = tcx.lang_items().start_fn() && lang_start_defid == hir.local_def_id(fn_id).to_def_id() {
+ if let Some(lang_start_defid) = tcx.lang_items().start_fn() && lang_start_defid == fn_def_id.to_def_id() {
check_lang_start_fn(tcx, fn_sig, decl, fn_def_id);
}
@@ -259,11 +262,9 @@ fn check_lang_start_fn<'tcx>(
// for example `start`'s generic should be a type parameter
let generics = tcx.generics_of(def_id);
let fn_generic = generics.param_at(0, tcx);
- let generic_tykind =
- ty::Param(ty::ParamTy { index: fn_generic.index, name: fn_generic.name });
- let generic_ty = tcx.mk_ty(generic_tykind);
+ let generic_ty = tcx.mk_ty_param(fn_generic.index, fn_generic.name);
let expected_fn_sig =
- tcx.mk_fn_sig([].iter(), &generic_ty, false, hir::Unsafety::Normal, Abi::Rust);
+ tcx.mk_fn_sig([], generic_ty, false, hir::Unsafety::Normal, Abi::Rust);
let expected_ty = tcx.mk_fn_ptr(Binder::dummy(expected_fn_sig));
// we emit the same error to suggest changing the arg no matter what's wrong with the arg
diff --git a/compiler/rustc_hir_typeck/src/closure.rs b/compiler/rustc_hir_typeck/src/closure.rs
index 12a2abfa7..d84fabb78 100644
--- a/compiler/rustc_hir_typeck/src/closure.rs
+++ b/compiler/rustc_hir_typeck/src/closure.rs
@@ -3,8 +3,8 @@
use super::{check_fn, Expectation, FnCtxt, GeneratorTypes};
use hir::def::DefKind;
+use rustc_errors::ErrorGuaranteed;
use rustc_hir as hir;
-use rustc_hir::def_id::LocalDefId;
use rustc_hir::lang_items::LangItem;
use rustc_hir_analysis::astconv::AstConv;
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
@@ -12,9 +12,11 @@ use rustc_infer::infer::LateBoundRegionConversionTime;
use rustc_infer::infer::{InferOk, InferResult};
use rustc_macros::{TypeFoldable, TypeVisitable};
use rustc_middle::ty::subst::InternalSubsts;
-use rustc_middle::ty::visit::TypeVisitable;
-use rustc_middle::ty::{self, Ty, TypeSuperVisitable, TypeVisitor};
+use rustc_middle::ty::visit::{TypeVisitable, TypeVisitableExt};
+use rustc_middle::ty::{self, Ty, TyCtxt, TypeSuperVisitable, TypeVisitor};
+use rustc_span::def_id::LocalDefId;
use rustc_span::source_map::Span;
+use rustc_span::sym;
use rustc_target::spec::abi::Abi;
use rustc_trait_selection::traits;
use rustc_trait_selection::traits::error_reporting::ArgKind;
@@ -80,7 +82,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
debug!(?bound_sig, ?liberated_sig);
- let mut fcx = FnCtxt::new(self, self.param_env.without_const(), body.value.hir_id);
+ let mut fcx = FnCtxt::new(self, self.param_env.without_const(), closure.def_id);
let generator_types = check_fn(
&mut fcx,
liberated_sig,
@@ -125,7 +127,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// the `closures` table.
let sig = bound_sig.map_bound(|sig| {
self.tcx.mk_fn_sig(
- iter::once(self.tcx.intern_tup(sig.inputs())),
+ [self.tcx.mk_tup(sig.inputs())],
sig.output(),
sig.c_variadic,
sig.unsafety,
@@ -231,7 +233,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
struct MentionsTy<'tcx> {
expected_ty: Ty<'tcx>,
}
- impl<'tcx> TypeVisitor<'tcx> for MentionsTy<'tcx> {
+ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for MentionsTy<'tcx> {
type BreakTy = ();
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
@@ -288,21 +290,20 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let trait_def_id = projection.trait_def_id(tcx);
let is_fn = tcx.is_fn_trait(trait_def_id);
- let gen_trait = tcx.require_lang_item(LangItem::Generator, cause_span);
- let is_gen = gen_trait == trait_def_id;
+
+ let gen_trait = tcx.lang_items().gen_trait();
+ let is_gen = gen_trait == Some(trait_def_id);
+
if !is_fn && !is_gen {
debug!("not fn or generator");
return None;
}
- if is_gen {
- // Check that we deduce the signature from the `<_ as std::ops::Generator>::Return`
- // associated item and not yield.
- let return_assoc_item = self.tcx.associated_item_def_ids(gen_trait)[1];
- if return_assoc_item != projection.projection_def_id() {
- debug!("not return assoc item of generator");
- return None;
- }
+ // Check that we deduce the signature from the `<_ as std::ops::Generator>::Return`
+ // associated item and not yield.
+ if is_gen && self.tcx.associated_item(projection.projection_def_id()).name != sym::Return {
+ debug!("not `Return` assoc item of `Generator`");
+ return None;
}
let input_tys = if is_fn {
@@ -326,7 +327,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
debug!(?ret_param_ty);
let sig = projection.rebind(self.tcx.mk_fn_sig(
- input_tys.iter(),
+ input_tys,
ret_param_ty,
false,
hir::Unsafety::Normal,
@@ -488,17 +489,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
};
let expected_span =
expected_sig.cause_span.unwrap_or_else(|| self.tcx.def_span(expr_def_id));
- self.report_arg_count_mismatch(
- expected_span,
- closure_span,
- expected_args,
- found_args,
- true,
- closure_arg_span,
- )
- .emit();
-
- let error_sig = self.error_sig_of_closure(decl);
+ let guar = self
+ .report_arg_count_mismatch(
+ expected_span,
+ closure_span,
+ expected_args,
+ found_args,
+ true,
+ closure_arg_span,
+ )
+ .emit();
+
+ let error_sig = self.error_sig_of_closure(decl, guar);
self.closure_sigs(expr_def_id, body, error_sig)
}
@@ -544,7 +546,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
)
.map(|(hir_ty, &supplied_ty)| {
// Instantiate (this part of..) S to S', i.e., with fresh variables.
- self.replace_bound_vars_with_fresh_vars(
+ self.instantiate_binder_with_fresh_vars(
hir_ty.span,
LateBoundRegionConversionTime::FnCall,
// (*) binder moved to here
@@ -561,12 +563,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
) {
// Check that E' = S'.
let cause = self.misc(hir_ty.span);
- let InferOk { value: (), obligations } =
- self.at(&cause, self.param_env).eq(*expected_ty, supplied_ty)?;
+ let InferOk { value: (), obligations } = self
+ .at(&cause, self.param_env)
+ .define_opaque_types(true)
+ .eq(*expected_ty, supplied_ty)?;
all_obligations.extend(obligations);
}
- let supplied_output_ty = self.replace_bound_vars_with_fresh_vars(
+ let supplied_output_ty = self.instantiate_binder_with_fresh_vars(
decl.output.span(),
LateBoundRegionConversionTime::FnCall,
supplied_sig.output(),
@@ -574,6 +578,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let cause = &self.misc(decl.output.span());
let InferOk { value: (), obligations } = self
.at(cause, self.param_env)
+ .define_opaque_types(true)
.eq(expected_sigs.liberated_sig.output(), supplied_output_ty)?;
all_obligations.extend(obligations);
@@ -620,8 +625,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// function.
Some(hir::GeneratorKind::Async(hir::AsyncGeneratorKind::Fn)) => {
debug!("closure is async fn body");
- self.deduce_future_output_from_obligations(expr_def_id, body.id().hir_id)
- .unwrap_or_else(|| {
+ let def_id = self.tcx.hir().body_owner_def_id(body.id());
+ self.deduce_future_output_from_obligations(expr_def_id, def_id).unwrap_or_else(
+ || {
// AFAIK, deducing the future output
// always succeeds *except* in error cases
// like #65159. I'd like to return Error
@@ -630,7 +636,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// *have* reported an
// error. --nikomatsakis
astconv.ty_infer(None, decl.output.span())
- })
+ },
+ )
}
_ => astconv.ty_infer(None, decl.output.span()),
@@ -665,7 +672,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
fn deduce_future_output_from_obligations(
&self,
expr_def_id: LocalDefId,
- body_id: hir::HirId,
+ body_def_id: LocalDefId,
) -> Option<Ty<'tcx>> {
let ret_coercion = self.ret_coercion.as_ref().unwrap_or_else(|| {
span_bug!(self.tcx.def_span(expr_def_id), "async fn generator outside of a fn")
@@ -725,7 +732,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let InferOk { value: output_ty, obligations } = self
.replace_opaque_types_with_inference_vars(
output_ty,
- body_id,
+ body_def_id,
self.tcx.def_span(expr_def_id),
self.param_env,
);
@@ -787,13 +794,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
/// Converts the types that the user supplied, in case that doing
/// so should yield an error, but returns back a signature where
/// all parameters are of type `TyErr`.
- fn error_sig_of_closure(&self, decl: &hir::FnDecl<'_>) -> ty::PolyFnSig<'tcx> {
+ fn error_sig_of_closure(
+ &self,
+ decl: &hir::FnDecl<'_>,
+ guar: ErrorGuaranteed,
+ ) -> ty::PolyFnSig<'tcx> {
let astconv: &dyn AstConv<'_> = self;
+ let err_ty = self.tcx.ty_error(guar);
let supplied_arguments = decl.inputs.iter().map(|a| {
// Convert the types that the user supplied (if any), but ignore them.
astconv.ast_ty_to_ty(a);
- self.tcx.ty_error()
+ err_ty
});
if let hir::FnRetTy::Return(ref output) = decl.output {
@@ -802,7 +814,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let result = ty::Binder::dummy(self.tcx.mk_fn_sig(
supplied_arguments,
- self.tcx.ty_error(),
+ err_ty,
decl.c_variadic,
hir::Unsafety::Normal,
Abi::RustCall,
diff --git a/compiler/rustc_hir_typeck/src/coercion.rs b/compiler/rustc_hir_typeck/src/coercion.rs
index bbf7b81a2..00b86890b 100644
--- a/compiler/rustc_hir_typeck/src/coercion.rs
+++ b/compiler/rustc_hir_typeck/src/coercion.rs
@@ -54,7 +54,7 @@ use rustc_middle::ty::adjustment::{
use rustc_middle::ty::error::TypeError;
use rustc_middle::ty::relate::RelateResult;
use rustc_middle::ty::subst::SubstsRef;
-use rustc_middle::ty::visit::TypeVisitable;
+use rustc_middle::ty::visit::TypeVisitableExt;
use rustc_middle::ty::{self, Ty, TypeAndMut};
use rustc_session::parse::feature_err;
use rustc_span::symbol::sym;
@@ -143,11 +143,11 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
fn unify(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> InferResult<'tcx, Ty<'tcx>> {
debug!("unify(a: {:?}, b: {:?}, use_lub: {})", a, b, self.use_lub);
self.commit_if_ok(|_| {
+ let at = self.at(&self.cause, self.fcx.param_env).define_opaque_types(true);
if self.use_lub {
- self.at(&self.cause, self.fcx.param_env).lub(b, a)
+ at.lub(b, a)
} else {
- self.at(&self.cause, self.fcx.param_env)
- .sup(b, a)
+ at.sup(b, a)
.map(|InferOk { value: (), obligations }| InferOk { value: a, obligations })
}
})
@@ -170,12 +170,14 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
debug!("Coerce.tys({:?} => {:?})", a, b);
// Just ignore error types.
- if a.references_error() || b.references_error() {
+ if let Err(guar) = (a, b).error_reported() {
// Best-effort try to unify these types -- we're already on the error path,
// so this will have the side-effect of making sure we have no ambiguities
// due to `[type error]` and `_` not coercing together.
- let _ = self.commit_if_ok(|_| self.at(&self.cause, self.param_env).eq(a, b));
- return success(vec![], self.fcx.tcx.ty_error(), vec![]);
+ let _ = self.commit_if_ok(|_| {
+ self.at(&self.cause, self.param_env).define_opaque_types(true).eq(a, b)
+ });
+ return success(vec![], self.fcx.tcx.ty_error(guar), vec![]);
}
// Coercing from `!` to any type is allowed:
@@ -765,7 +767,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
self.cause.clone(),
self.param_env,
ty::Binder::dummy(
- self.tcx.at(self.cause.span).mk_trait_ref(hir::LangItem::PointerSized, [a]),
+ self.tcx.at(self.cause.span).mk_trait_ref(hir::LangItem::PointerLike, [a]),
),
));
@@ -995,7 +997,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let (adjustments, _) = self.register_infer_ok_obligations(ok);
self.apply_adjustments(expr, adjustments);
- Ok(if expr_ty.references_error() { self.tcx.ty_error() } else { target })
+ Ok(if let Err(guar) = expr_ty.error_reported() { self.tcx.ty_error(guar) } else { target })
}
/// Same as `try_coerce()`, but without side-effects.
@@ -1046,7 +1048,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
self.param_env,
)
.may_apply()
- .then(|| deref_ty)
+ .then_some(deref_ty)
})
}
@@ -1432,8 +1434,8 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
// If we see any error types, just propagate that error
// upwards.
- if expression_ty.references_error() || self.merged_ty().references_error() {
- self.final_ty = Some(fcx.tcx.ty_error());
+ if let Err(guar) = (expression_ty, self.merged_ty()).error_reported() {
+ self.final_ty = Some(fcx.tcx.ty_error(guar));
return;
}
@@ -1484,6 +1486,8 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
// Another example is `break` with no argument expression.
assert!(expression_ty.is_unit(), "if let hack without unit type");
fcx.at(cause, fcx.param_env)
+ // needed for tests/ui/type-alias-impl-trait/issue-65679-inst-opaque-ty-from-val-twice.rs
+ .define_opaque_types(true)
.eq_exp(label_expression_as_expected, expression_ty, self.merged_ty())
.map(|infer_ok| {
fcx.register_infer_ok_obligations(infer_ok);
@@ -1613,12 +1617,14 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
if visitor.ret_exprs.len() > 0 && let Some(expr) = expression {
self.note_unreachable_loop_return(&mut err, &expr, &visitor.ret_exprs);
}
+
let reported = err.emit_unless(unsized_return);
- self.final_ty = Some(fcx.tcx.ty_error_with_guaranteed(reported));
+ self.final_ty = Some(fcx.tcx.ty_error(reported));
}
}
}
+
fn note_unreachable_loop_return(
&self,
err: &mut Diagnostic,
@@ -1821,7 +1827,7 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
.trait_ref()
.and_then(|t| t.trait_def_id())
.map_or(false, |def_id| {
- fcx.tcx.object_safety_violations(def_id).is_empty()
+ fcx.tcx.check_is_object_safe(def_id)
})
})
}
diff --git a/compiler/rustc_hir_typeck/src/demand.rs b/compiler/rustc_hir_typeck/src/demand.rs
index f4c4d4310..7ba57b3b7 100644
--- a/compiler/rustc_hir_typeck/src/demand.rs
+++ b/compiler/rustc_hir_typeck/src/demand.rs
@@ -1,9 +1,11 @@
use crate::FnCtxt;
use rustc_ast::util::parser::PREC_POSTFIX;
+use rustc_data_structures::fx::FxHashMap;
use rustc_errors::MultiSpan;
use rustc_errors::{Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed};
use rustc_hir as hir;
use rustc_hir::def::CtorKind;
+use rustc_hir::intravisit::Visitor;
use rustc_hir::lang_items::LangItem;
use rustc_hir::{is_range_literal, Node};
use rustc_infer::infer::InferOk;
@@ -11,11 +13,14 @@ use rustc_middle::lint::in_external_macro;
use rustc_middle::middle::stability::EvalResult;
use rustc_middle::ty::adjustment::AllowTwoPhase;
use rustc_middle::ty::error::{ExpectedFound, TypeError};
-use rustc_middle::ty::print::with_no_trimmed_paths;
-use rustc_middle::ty::{self, Article, AssocItem, Ty, TypeAndMut};
+use rustc_middle::ty::fold::{BottomUpFolder, TypeFolder};
+use rustc_middle::ty::print::{with_forced_trimmed_paths, with_no_trimmed_paths};
+use rustc_middle::ty::relate::TypeRelation;
+use rustc_middle::ty::{self, Article, AssocItem, Ty, TypeAndMut, TypeVisitableExt};
use rustc_span::symbol::{sym, Symbol};
use rustc_span::{BytePos, Span};
use rustc_trait_selection::infer::InferCtxtExt as _;
+use rustc_trait_selection::traits::error_reporting::method_chain::CollectAllMismatches;
use rustc_trait_selection::traits::ObligationCause;
use super::method::probe;
@@ -40,7 +45,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
self.annotate_alternative_method_deref(err, expr, error);
// Use `||` to give these suggestions a precedence
- let _ = self.suggest_missing_parentheses(err, expr)
+ let suggested = self.suggest_missing_parentheses(err, expr)
|| self.suggest_remove_last_method_call(err, expr, expected)
|| self.suggest_associated_const(err, expr, expected)
|| self.suggest_deref_ref_or_into(err, expr, expected, expr_ty, expected_ty_expr)
@@ -54,7 +59,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|| self.suggest_copied_or_cloned(err, expr, expr_ty, expected)
|| self.suggest_clone_for_ref(err, expr, expr_ty, expected)
|| self.suggest_into(err, expr, expr_ty, expected)
- || self.suggest_floating_point_literal(err, expr, expected);
+ || self.suggest_floating_point_literal(err, expr, expected)
+ || self.suggest_null_ptr_for_literal_zero_given_to_ptr_arg(err, expr, expected)
+ || self.note_result_coercion(err, expr, expected, expr_ty);
+ if !suggested {
+ self.point_at_expr_source_of_inferred_type(err, expr, expr_ty, expected, expr.span);
+ }
}
pub fn emit_coerce_suggestions(
@@ -73,7 +83,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
self.annotate_expected_due_to_let_ty(err, expr, error);
self.emit_type_mismatch_suggestions(err, expr, expr_ty, expected, expected_ty_expr, error);
self.note_type_is_not_clone(err, expected, expr_ty, expr);
- self.note_need_for_fn_pointer(err, expected, expr_ty);
self.note_internal_mutation_in_method(err, expr, expected, expr_ty);
self.check_for_range_as_method_call(err, expr, expr_ty, expected);
self.check_for_binding_assigned_block_without_tail_expression(err, expr, expr_ty, expected);
@@ -104,7 +113,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
expected: Ty<'tcx>,
actual: Ty<'tcx>,
) -> Option<DiagnosticBuilder<'tcx, ErrorGuaranteed>> {
- match self.at(cause, self.param_env).sup(expected, actual) {
+ match self.at(cause, self.param_env).define_opaque_types(true).sup(expected, actual) {
Ok(InferOk { obligations, value: () }) => {
self.register_predicates(obligations);
None
@@ -134,7 +143,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
expected: Ty<'tcx>,
actual: Ty<'tcx>,
) -> Option<DiagnosticBuilder<'tcx, ErrorGuaranteed>> {
- match self.at(cause, self.param_env).eq(expected, actual) {
+ match self.at(cause, self.param_env).define_opaque_types(true).eq(expected, actual) {
Ok(InferOk { obligations, value: () }) => {
self.register_predicates(obligations);
None
@@ -208,6 +217,223 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
(expected, Some(err))
}
+ pub fn point_at_expr_source_of_inferred_type(
+ &self,
+ err: &mut Diagnostic,
+ expr: &hir::Expr<'_>,
+ found: Ty<'tcx>,
+ expected: Ty<'tcx>,
+ mismatch_span: Span,
+ ) -> bool {
+ let map = self.tcx.hir();
+
+ let hir::ExprKind::Path(hir::QPath::Resolved(None, p)) = expr.kind else { return false; };
+ let [hir::PathSegment { ident, args: None, .. }] = p.segments else { return false; };
+ let hir::def::Res::Local(hir_id) = p.res else { return false; };
+ let Some(hir::Node::Pat(pat)) = map.find(hir_id) else { return false; };
+ let Some(hir::Node::Local(hir::Local {
+ ty: None,
+ init: Some(init),
+ ..
+ })) = map.find_parent(pat.hir_id) else { return false; };
+ let Some(ty) = self.node_ty_opt(init.hir_id) else { return false; };
+ if ty.is_closure() || init.span.overlaps(expr.span) || pat.span.from_expansion() {
+ return false;
+ }
+
+ // Locate all the usages of the relevant binding.
+ struct FindExprs<'hir> {
+ hir_id: hir::HirId,
+ uses: Vec<&'hir hir::Expr<'hir>>,
+ }
+ impl<'v> Visitor<'v> for FindExprs<'v> {
+ fn visit_expr(&mut self, ex: &'v hir::Expr<'v>) {
+ if let hir::ExprKind::Path(hir::QPath::Resolved(None, path)) = ex.kind
+ && let hir::def::Res::Local(hir_id) = path.res
+ && hir_id == self.hir_id
+ {
+ self.uses.push(ex);
+ }
+ hir::intravisit::walk_expr(self, ex);
+ }
+ }
+
+ let mut expr_finder = FindExprs { hir_id, uses: vec![] };
+ let id = map.get_parent_item(hir_id);
+ let hir_id: hir::HirId = id.into();
+
+ let Some(node) = map.find(hir_id) else { return false; };
+ let Some(body_id) = node.body_id() else { return false; };
+ let body = map.body(body_id);
+ expr_finder.visit_expr(body.value);
+ // Hack to make equality checks on types with inference variables and regions useful.
+ let mut eraser = BottomUpFolder {
+ tcx: self.tcx,
+ lt_op: |_| self.tcx.lifetimes.re_erased,
+ ct_op: |c| c,
+ ty_op: |t| match *t.kind() {
+ ty::Infer(ty::TyVar(_)) => self.tcx.mk_ty_var(ty::TyVid::from_u32(0)),
+ ty::Infer(ty::IntVar(_)) => self.tcx.mk_int_var(ty::IntVid { index: 0 }),
+ ty::Infer(ty::FloatVar(_)) => self.tcx.mk_float_var(ty::FloatVid { index: 0 }),
+ _ => t,
+ },
+ };
+ let mut prev = eraser.fold_ty(ty);
+ let mut prev_span: Option<Span> = None;
+
+ for binding in expr_finder.uses {
+ // In every expression where the binding is referenced, we will look at that
+ // expression's type and see if it is where the incorrect found type was fully
+ // "materialized" and point at it. We will also try to provide a suggestion there.
+ if let Some(hir::Node::Expr(expr)
+ | hir::Node::Stmt(hir::Stmt {
+ kind: hir::StmtKind::Expr(expr) | hir::StmtKind::Semi(expr),
+ ..
+ })) = &map.find_parent(binding.hir_id)
+ && let hir::ExprKind::MethodCall(segment, rcvr, args, _span) = expr.kind
+ && rcvr.hir_id == binding.hir_id
+ && let Some(def_id) = self.typeck_results.borrow().type_dependent_def_id(expr.hir_id)
+ {
+ // We special case methods, because they can influence inference through the
+ // call's arguments and we can provide a more explicit span.
+ let sig = self.tcx.fn_sig(def_id).subst_identity();
+ let def_self_ty = sig.input(0).skip_binder();
+ let param_tys = sig.inputs().skip_binder().iter().skip(1);
+ // If there's an arity mismatch, pointing out the call as the source of an inference
+ // can be misleading, so we skip it.
+ if param_tys.len() != args.len() {
+ continue;
+ }
+ let rcvr_ty = self.node_ty(rcvr.hir_id);
+ // Get the evaluated type *after* calling the method call, so that the influence
+ // of the arguments can be reflected in the receiver type. The receiver
+ // expression has the type *before* theis analysis is done.
+ let ty = match self.lookup_probe_for_diagnostic(
+ segment.ident,
+ rcvr_ty,
+ expr,
+ probe::ProbeScope::TraitsInScope,
+ None,
+ ) {
+ Ok(pick) => eraser.fold_ty(pick.self_ty),
+ Err(_) => rcvr_ty,
+ };
+ // Remove one layer of references to account for `&mut self` and
+ // `&self`, so that we can compare it against the binding.
+ let (ty, def_self_ty) = match (ty.kind(), def_self_ty.kind()) {
+ (ty::Ref(_, ty, a), ty::Ref(_, self_ty, b)) if a == b => (*ty, *self_ty),
+ _ => (ty, def_self_ty),
+ };
+ let mut param_args = FxHashMap::default();
+ let mut param_expected = FxHashMap::default();
+ let mut param_found = FxHashMap::default();
+ if self.can_eq(self.param_env, ty, found) {
+ // We only point at the first place where the found type was inferred.
+ for (param_ty, arg) in param_tys.zip(args) {
+ if def_self_ty.contains(*param_ty) && let ty::Param(_) = param_ty.kind() {
+ // We found an argument that references a type parameter in `Self`,
+ // so we assume that this is the argument that caused the found
+ // type, which we know already because of `can_eq` above was first
+ // inferred in this method call.
+ let arg_ty = self.node_ty(arg.hir_id);
+ if !arg.span.overlaps(mismatch_span) {
+ err.span_label(
+ arg.span,
+ &format!(
+ "this is of type `{arg_ty}`, which causes `{ident}` to be \
+ inferred as `{ty}`",
+ ),
+ );
+ }
+ param_args.insert(param_ty, (arg, arg_ty));
+ }
+ }
+ }
+
+ // Here we find, for a type param `T`, the type that `T` is in the current
+ // method call *and* in the original expected type. That way, we can see if we
+ // can give any structured suggestion for the function argument.
+ let mut c = CollectAllMismatches {
+ infcx: &self.infcx,
+ param_env: self.param_env,
+ errors: vec![],
+ };
+ let _ = c.relate(def_self_ty, ty);
+ for error in c.errors {
+ if let TypeError::Sorts(error) = error {
+ param_found.insert(error.expected, error.found);
+ }
+ }
+ c.errors = vec![];
+ let _ = c.relate(def_self_ty, expected);
+ for error in c.errors {
+ if let TypeError::Sorts(error) = error {
+ param_expected.insert(error.expected, error.found);
+ }
+ }
+ for (param, (arg, arg_ty)) in param_args.iter() {
+ let Some(expected) = param_expected.get(param) else { continue; };
+ let Some(found) = param_found.get(param) else { continue; };
+ if !self.can_eq(self.param_env, *arg_ty, *found) { continue; }
+ self.emit_coerce_suggestions(err, arg, *found, *expected, None, None);
+ }
+
+ let ty = eraser.fold_ty(ty);
+ if ty.references_error() {
+ break;
+ }
+ if ty != prev
+ && param_args.is_empty()
+ && self.can_eq(self.param_env, ty, found)
+ {
+ // We only point at the first place where the found type was inferred.
+ if !segment.ident.span.overlaps(mismatch_span) {
+ err.span_label(
+ segment.ident.span,
+ with_forced_trimmed_paths!(format!(
+ "here the type of `{ident}` is inferred to be `{ty}`",
+ )),
+ );}
+ break;
+ } else if !param_args.is_empty() {
+ break;
+ }
+ prev = ty;
+ } else {
+ let ty = eraser.fold_ty(self.node_ty(binding.hir_id));
+ if ty.references_error() {
+ break;
+ }
+ if ty != prev
+ && let Some(span) = prev_span
+ && self.can_eq(self.param_env, ty, found)
+ {
+ // We only point at the first place where the found type was inferred.
+ // We use the *previous* span because if the type is known *here* it means
+ // it was *evaluated earlier*. We don't do this for method calls because we
+ // evaluate the method's self type eagerly, but not in any other case.
+ if !span.overlaps(mismatch_span) {
+ err.span_label(
+ span,
+ with_forced_trimmed_paths!(format!(
+ "here the type of `{ident}` is inferred to be `{ty}`",
+ )),
+ );
+ }
+ break;
+ }
+ prev = ty;
+ }
+ if binding.hir_id == expr.hir_id {
+ // Do not look at expressions that come after the expression we were originally
+ // evaluating and had a type error.
+ break;
+ }
+ prev_span = Some(binding.span);
+ }
+ true
+ }
+
fn annotate_expected_due_to_let_ty(
&self,
err: &mut Diagnostic,
@@ -379,6 +605,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let substs = ty::InternalSubsts::for_item(self.tcx, m.def_id, |param, _| {
self.var_for_def(deref.span, param)
});
+ let mutability =
+ match self.tcx.fn_sig(m.def_id).skip_binder().input(0).skip_binder().kind() {
+ ty::Ref(_, _, hir::Mutability::Mut) => "&mut ",
+ ty::Ref(_, _, _) => "&",
+ _ => "",
+ };
vec![
(
deref.span.until(base.span),
@@ -387,11 +619,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
with_no_trimmed_paths!(
self.tcx.def_path_str_with_substs(m.def_id, substs,)
),
- match self.tcx.fn_sig(m.def_id).input(0).skip_binder().kind() {
- ty::Ref(_, _, hir::Mutability::Mut) => "&mut ",
- ty::Ref(_, _, _) => "&",
- _ => "",
- },
+ mutability,
),
),
match &args[..] {
@@ -479,6 +707,56 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
);
}
+ pub(crate) fn note_result_coercion(
+ &self,
+ err: &mut Diagnostic,
+ expr: &hir::Expr<'tcx>,
+ expected: Ty<'tcx>,
+ found: Ty<'tcx>,
+ ) -> bool {
+ let ty::Adt(e, substs_e) = expected.kind() else { return false; };
+ let ty::Adt(f, substs_f) = found.kind() else { return false; };
+ if e.did() != f.did() {
+ return false;
+ }
+ if Some(e.did()) != self.tcx.get_diagnostic_item(sym::Result) {
+ return false;
+ }
+ let map = self.tcx.hir();
+ if let Some(hir::Node::Expr(expr)) = map.find_parent(expr.hir_id)
+ && let hir::ExprKind::Ret(_) = expr.kind
+ {
+ // `return foo;`
+ } else if map.get_return_block(expr.hir_id).is_some() {
+ // Function's tail expression.
+ } else {
+ return false;
+ }
+ let e = substs_e.type_at(1);
+ let f = substs_f.type_at(1);
+ if self
+ .infcx
+ .type_implements_trait(
+ self.tcx.get_diagnostic_item(sym::Into).unwrap(),
+ [f, e],
+ self.param_env,
+ )
+ .must_apply_modulo_regions()
+ {
+ err.multipart_suggestion(
+ "use `?` to coerce and return an appropriate `Err`, and wrap the resulting value \
+ in `Ok` so the expression remains of type `Result`",
+ vec![
+ (expr.span.shrink_to_lo(), "Ok(".to_string()),
+ (expr.span.shrink_to_hi(), "?)".to_string()),
+ ],
+ Applicability::MaybeIncorrect,
+ );
+ return true;
+ }
+ 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(
@@ -491,7 +769,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
if let ty::Adt(expected_adt, substs) = expected.kind() {
if let hir::ExprKind::Field(base, ident) = expr.kind {
let base_ty = self.typeck_results.borrow().expr_ty(base);
- if self.can_eq(self.param_env, base_ty, expected).is_ok()
+ if self.can_eq(self.param_env, base_ty, expected)
&& let Some(base_span) = base.span.find_ancestor_inside(expr.span)
{
err.span_suggestion_verbose(
@@ -762,7 +1040,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
match method.kind {
ty::AssocKind::Fn => {
method.fn_has_self_parameter
- && self.tcx.fn_sig(method.def_id).inputs().skip_binder().len() == 1
+ && self.tcx.fn_sig(method.def_id).skip_binder().inputs().skip_binder().len()
+ == 1
}
_ => false,
}
@@ -990,10 +1269,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// ```
let ref_ty = match mutability {
hir::Mutability::Mut => {
- self.tcx.mk_mut_ref(self.tcx.mk_region(ty::ReStatic), checked_ty)
+ self.tcx.mk_mut_ref(self.tcx.lifetimes.re_static, checked_ty)
}
hir::Mutability::Not => {
- self.tcx.mk_imm_ref(self.tcx.mk_region(ty::ReStatic), checked_ty)
+ self.tcx.mk_imm_ref(self.tcx.lifetimes.re_static, checked_ty)
}
};
if self.can_coerce(ref_ty, expected) {
@@ -1015,6 +1294,22 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
sugg_sp = receiver.span;
}
}
+
+ if let hir::ExprKind::Unary(hir::UnOp::Deref, ref inner) = expr.kind
+ && let Some(1) = self.deref_steps(expected, checked_ty) {
+ // We have `*&T`, check if what was expected was `&T`.
+ // If so, we may want to suggest removing a `*`.
+ sugg_sp = sugg_sp.with_hi(inner.span.lo());
+ return Some((
+ sugg_sp,
+ "consider removing deref here".to_string(),
+ "".to_string(),
+ Applicability::MachineApplicable,
+ true,
+ false,
+ ));
+ }
+
if let Ok(src) = sm.span_to_snippet(sugg_sp) {
let needs_parens = match expr.kind {
// parenthesize if needed (Issue #46756)
@@ -1067,7 +1362,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
hir::ExprKind::AddrOf(hir::BorrowKind::Ref, _, ref expr),
_,
&ty::Ref(_, checked, _),
- ) if self.can_sub(self.param_env, checked, expected).is_ok() => {
+ ) if self.can_sub(self.param_env, checked, expected) => {
// We have `&T`, check if what was expected was `T`. If so,
// we may want to suggest removing a `&`.
if sm.is_imported(expr.span) {
@@ -1713,7 +2008,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
};
let hir::StmtKind::Semi(tail_expr) = stmt.kind else { return; };
let Some(ty) = self.node_ty_opt(tail_expr.hir_id) else { return; };
- if self.can_eq(self.param_env, expected_ty, ty).is_ok() {
+ if self.can_eq(self.param_env, expected_ty, ty) {
err.span_suggestion_short(
stmt.span.with_lo(tail_expr.span.hi()),
"remove this semicolon",
@@ -1742,7 +2037,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
args: &[hir::Expr<'_>],
kind: CallableKind| {
let arg_idx = args.iter().position(|a| a.hir_id == expr.hir_id).unwrap();
- let fn_ty = self.tcx.bound_type_of(def_id).0;
+ let fn_ty = self.tcx.type_of(def_id).skip_binder();
if !fn_ty.is_fn() {
return;
}
diff --git a/compiler/rustc_hir_typeck/src/errors.rs b/compiler/rustc_hir_typeck/src/errors.rs
index 5b4fd5e4a..3eee2278d 100644
--- a/compiler/rustc_hir_typeck/src/errors.rs
+++ b/compiler/rustc_hir_typeck/src/errors.rs
@@ -1,8 +1,13 @@
//! Errors emitted by `rustc_hir_typeck`.
+use crate::fluent_generated as fluent;
use rustc_errors::{AddToDiagnostic, Applicability, Diagnostic, MultiSpan, SubdiagnosticMessage};
use rustc_macros::{Diagnostic, Subdiagnostic};
use rustc_middle::ty::Ty;
-use rustc_span::{symbol::Ident, Span};
+use rustc_span::{
+ edition::{Edition, LATEST_STABLE_EDITION},
+ symbol::Ident,
+ Span,
+};
#[derive(Diagnostic)]
#[diag(hir_typeck_field_multiply_specified_in_initializer, code = "E0062")]
@@ -10,7 +15,7 @@ pub struct FieldMultiplySpecifiedInInitializer {
#[primary_span]
#[label]
pub span: Span,
- #[label(previous_use_label)]
+ #[label(hir_typeck_previous_use_label)]
pub prev_span: Span,
pub ident: Ident,
}
@@ -20,9 +25,9 @@ pub struct FieldMultiplySpecifiedInInitializer {
pub struct ReturnStmtOutsideOfFnBody {
#[primary_span]
pub span: Span,
- #[label(encl_body_label)]
+ #[label(hir_typeck_encl_body_label)]
pub encl_body_span: Option<Span>,
- #[label(encl_fn_label)]
+ #[label(hir_typeck_encl_fn_label)]
pub encl_fn_span: Option<Span>,
}
@@ -153,20 +158,17 @@ impl AddToDiagnostic for TypeMismatchFruTypo {
// Only explain that `a ..b` is a range if it's split up
if self.expr_span.between(self.fru_span).is_empty() {
- diag.span_note(
- self.expr_span.to(self.fru_span),
- rustc_errors::fluent::hir_typeck_fru_note,
- );
+ diag.span_note(self.expr_span.to(self.fru_span), fluent::hir_typeck_fru_note);
} else {
let mut multispan: MultiSpan = vec![self.expr_span, self.fru_span].into();
- multispan.push_span_label(self.expr_span, rustc_errors::fluent::hir_typeck_fru_expr);
- multispan.push_span_label(self.fru_span, rustc_errors::fluent::hir_typeck_fru_expr2);
- diag.span_note(multispan, rustc_errors::fluent::hir_typeck_fru_note);
+ multispan.push_span_label(self.expr_span, fluent::hir_typeck_fru_expr);
+ multispan.push_span_label(self.fru_span, fluent::hir_typeck_fru_expr2);
+ diag.span_note(multispan, fluent::hir_typeck_fru_note);
}
diag.span_suggestion(
self.expr_span.shrink_to_hi(),
- rustc_errors::fluent::hir_typeck_fru_suggestion,
+ fluent::hir_typeck_fru_suggestion,
", ",
Applicability::MaybeIncorrect,
);
@@ -205,3 +207,24 @@ pub struct LangStartIncorrectRetTy<'tcx> {
pub expected_ty: Ty<'tcx>,
pub found_ty: Ty<'tcx>,
}
+
+#[derive(Subdiagnostic)]
+pub enum HelpUseLatestEdition {
+ #[help(hir_typeck_help_set_edition_cargo)]
+ #[note(hir_typeck_note_edition_guide)]
+ Cargo { edition: Edition },
+ #[help(hir_typeck_help_set_edition_standalone)]
+ #[note(hir_typeck_note_edition_guide)]
+ Standalone { edition: Edition },
+}
+
+impl HelpUseLatestEdition {
+ pub fn new() -> Self {
+ let edition = LATEST_STABLE_EDITION;
+ if std::env::var_os("CARGO").is_some() {
+ Self::Cargo { edition }
+ } else {
+ Self::Standalone { edition }
+ }
+ }
+}
diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs
index bc7474cdf..7fc4ccb04 100644
--- a/compiler/rustc_hir_typeck/src/expr.rs
+++ b/compiler/rustc_hir_typeck/src/expr.rs
@@ -8,7 +8,7 @@ use crate::coercion::DynamicCoerceMany;
use crate::errors::TypeMismatchFruTypo;
use crate::errors::{AddressOfTemporaryTaken, ReturnStmtOutsideOfFnBody, StructExprNonExhaustive};
use crate::errors::{
- FieldMultiplySpecifiedInInitializer, FunctionalRecordUpdateOnNonStruct,
+ FieldMultiplySpecifiedInInitializer, FunctionalRecordUpdateOnNonStruct, HelpUseLatestEdition,
YieldExprOutsideOfGenerator,
};
use crate::fatally_break_rust;
@@ -23,8 +23,8 @@ use rustc_ast as ast;
use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::stack::ensure_sufficient_stack;
use rustc_errors::{
- pluralize, struct_span_err, Applicability, Diagnostic, DiagnosticBuilder, DiagnosticId,
- ErrorGuaranteed, StashKey,
+ pluralize, struct_span_err, AddToDiagnostic, Applicability, Diagnostic, DiagnosticBuilder,
+ DiagnosticId, ErrorGuaranteed, StashKey,
};
use rustc_hir as hir;
use rustc_hir::def::{CtorKind, DefKind, Res};
@@ -42,11 +42,11 @@ use rustc_middle::middle::stability;
use rustc_middle::ty::adjustment::{Adjust, Adjustment, AllowTwoPhase};
use rustc_middle::ty::error::TypeError::FieldMisMatch;
use rustc_middle::ty::subst::SubstsRef;
-use rustc_middle::ty::{self, AdtKind, Ty, TypeVisitable};
+use rustc_middle::ty::{self, AdtKind, Ty, TypeVisitableExt};
use rustc_session::errors::ExprParenthesesNeeded;
use rustc_session::parse::feature_err;
+use rustc_span::edit_distance::find_best_match_for_name;
use rustc_span::hygiene::DesugaringKind;
-use rustc_span::lev_distance::find_best_match_for_name;
use rustc_span::source_map::{Span, Spanned};
use rustc_span::symbol::{kw, sym, Ident, Symbol};
use rustc_target::spec::abi::Abi::RustIntrinsic;
@@ -88,7 +88,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
return if let [Adjustment { kind: Adjust::NeverToAny, target }] = &adjustments[..] {
target.to_owned()
} else {
- self.tcx().ty_error_with_guaranteed(reported)
+ self.tcx().ty_error(reported)
};
}
@@ -313,7 +313,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
tcx.types.never
} else {
// There was an error; make type-check fail.
- tcx.ty_error()
+ tcx.ty_error_misc()
}
}
ExprKind::Ret(ref expr_opt) => self.check_expr_return(expr_opt.as_deref(), expr),
@@ -354,7 +354,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
ExprKind::Field(base, field) => self.check_field(expr, &base, field, expected),
ExprKind::Index(base, idx) => self.check_expr_index(base, idx, expr),
ExprKind::Yield(value, ref src) => self.check_expr_yield(value, expr, src),
- hir::ExprKind::Err => tcx.ty_error(),
+ hir::ExprKind::Err(guar) => tcx.ty_error(guar),
}
}
@@ -402,7 +402,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
{
err.subdiagnostic(ExprParenthesesNeeded::surrounding(*sp));
}
- oprnd_t = tcx.ty_error_with_guaranteed(err.emit());
+ oprnd_t = tcx.ty_error(err.emit());
}
}
hir::UnOp::Not => {
@@ -452,7 +452,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let tm = ty::TypeAndMut { ty, mutbl };
match kind {
- _ if tm.ty.references_error() => self.tcx.ty_error(),
+ _ if tm.ty.references_error() => self.tcx.ty_error_misc(),
hir::BorrowKind::Raw => {
self.check_named_place_expr(oprnd);
self.tcx.mk_ptr(tm)
@@ -531,18 +531,20 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let e =
self.tcx.sess.delay_span_bug(qpath.span(), "`Res::Err` but no error emitted");
self.set_tainted_by_errors(e);
- tcx.ty_error_with_guaranteed(e)
+ tcx.ty_error(e)
}
Res::Def(DefKind::Variant, _) => {
let e = report_unexpected_variant_res(tcx, res, qpath, expr.span, "E0533", "value");
- tcx.ty_error_with_guaranteed(e)
+ tcx.ty_error(e)
}
_ => self.instantiate_value_path(segs, opt_ty, res, expr.span, expr.hir_id).0,
};
if let ty::FnDef(did, ..) = *ty.kind() {
let fn_sig = ty.fn_sig(tcx);
- if tcx.fn_sig(did).abi() == RustIntrinsic && tcx.item_name(did) == sym::transmute {
+ if tcx.fn_sig(did).skip_binder().abi() == RustIntrinsic
+ && tcx.item_name(did) == sym::transmute
+ {
let from = fn_sig.inputs().skip_binder()[0];
let to = fn_sig.output().skip_binder();
// We defer the transmute to the end of typeck, once all inference vars have
@@ -566,7 +568,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// 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(
+ let input = self.instantiate_binder_with_fresh_vars(
span,
infer::LateBoundRegionConversionTime::FnCall,
fn_sig.input(i),
@@ -584,7 +586,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// Also, as we just want to check sizedness, instead of introducing
// placeholder lifetimes with probing, we just replace higher lifetimes
// with fresh vars.
- let output = self.replace_bound_vars_with_fresh_vars(
+ let output = self.instantiate_binder_with_fresh_vars(
expr.span,
infer::LateBoundRegionConversionTime::FnCall,
fn_sig.output(),
@@ -632,7 +634,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// If the loop context is not a `loop { }`, then break with
// a value is illegal, and `opt_coerce_to` will be `None`.
// Just set expectation to error in that case.
- let coerce_to = opt_coerce_to.unwrap_or_else(|| tcx.ty_error());
+ let coerce_to = opt_coerce_to.unwrap_or_else(|| tcx.ty_error_misc());
// Recurse without `enclosing_breakables` borrowed.
e_ty = self.check_expr_with_hint(e, coerce_to);
@@ -852,7 +854,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// Point any obligations that were registered due to opaque type
// inference at the return expression.
self.select_obligations_where_possible(|errors| {
- self.point_at_return_for_opaque_ty_error(errors, span, return_expr_ty);
+ self.point_at_return_for_opaque_ty_error(errors, span, return_expr_ty, return_expr.span);
});
}
}
@@ -862,9 +864,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
errors: &mut Vec<traits::FulfillmentError<'tcx>>,
span: Span,
return_expr_ty: Ty<'tcx>,
+ return_span: Span,
) {
// Don't point at the whole block if it's empty
- if span == self.tcx.hir().span(self.body_id) {
+ if span == return_span {
return;
}
for err in errors {
@@ -1030,7 +1033,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
let result_ty = coerce.complete(self);
- if cond_ty.references_error() { self.tcx.ty_error() } else { result_ty }
+ if let Err(guar) = cond_ty.error_reported() { self.tcx.ty_error(guar) } else { result_ty }
}
/// Type check assignment expression `expr` of form `lhs = rhs`.
@@ -1106,7 +1109,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// If the assignment expression itself is ill-formed, don't
// bother emitting another error
let reported = err.emit_unless(lhs_ty.references_error() || rhs_ty.references_error());
- return self.tcx.ty_error_with_guaranteed(reported);
+ return self.tcx.ty_error(reported);
}
let lhs_ty = self.check_expr_with_needs(&lhs, Needs::MutPlace);
@@ -1152,8 +1155,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
self.require_type_is_sized(lhs_ty, lhs.span, traits::AssignmentLhsSized);
- if lhs_ty.references_error() || rhs_ty.references_error() {
- self.tcx.ty_error()
+ if let Err(guar) = (lhs_ty, rhs_ty).error_reported() {
+ self.tcx.ty_error(guar)
} else {
self.tcx.mk_unit()
}
@@ -1271,8 +1274,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let t_expr = self.resolve_vars_if_possible(t_expr);
// Eagerly check for some obvious errors.
- if t_expr.references_error() || t_cast.references_error() {
- self.tcx.ty_error()
+ if let Err(guar) = (t_expr, t_cast).error_reported() {
+ self.tcx.ty_error(guar)
} else {
// Defer other checks until we're done type checking.
let mut deferred_cast_checks = self.deferred_cast_checks.borrow_mut();
@@ -1293,7 +1296,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
deferred_cast_checks.push(cast_check);
t_cast
}
- Err(_) => self.tcx.ty_error(),
+ Err(guar) => self.tcx.ty_error(guar),
}
}
}
@@ -1374,7 +1377,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let body = self.tcx.hir().body(anon_const.body);
// Create a new function context.
- let fcx = FnCtxt::new(self, self.param_env.with_const(), body.value.hir_id);
+ let def_id = anon_const.def_id;
+ let fcx = FnCtxt::new(self, self.param_env.with_const(), def_id);
crate::GatherLocalsVisitor::new(&fcx).visit_body(body);
let ty = fcx.check_expr_with_expectation(&body.value, expected);
@@ -1392,7 +1396,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
) -> Ty<'tcx> {
let tcx = self.tcx;
let count = self.array_length_to_const(count);
- if let Some(count) = count.try_eval_usize(tcx, self.param_env) {
+ if let Some(count) = count.try_eval_target_usize(tcx, self.param_env) {
self.suggest_array_len(expr, count);
}
@@ -1419,13 +1423,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
};
- if element_ty.references_error() {
- return tcx.ty_error();
+ if let Err(guar) = element_ty.error_reported() {
+ return tcx.ty_error(guar);
}
self.check_repeat_element_needs_copy_bound(element, count, element_ty);
- tcx.mk_ty(ty::Array(t, count))
+ tcx.mk_array_with_const_len(t, count)
}
fn check_repeat_element_needs_copy_bound(
@@ -1459,7 +1463,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// If the length is 0, we don't create any elements, so we don't copy any. If the length is 1, we
// don't copy that one element, we move it. Only check for Copy if the length is larger.
- if count.try_eval_usize(tcx, self.param_env).map_or(true, |len| len > 1) {
+ if count.try_eval_target_usize(tcx, self.param_env).map_or(true, |len| len > 1) {
let lang_item = self.tcx.require_lang_item(LangItem::Copy, None);
let code = traits::ObligationCauseCode::RepeatElementCopy { is_const_fn };
self.require_type_meets(element_ty, element.span, code, lang_item);
@@ -1488,9 +1492,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
_ => self.check_expr_with_expectation(&e, NoExpectation),
});
- let tuple = self.tcx.mk_tup(elt_ts_iter);
- if tuple.references_error() {
- self.tcx.ty_error()
+ let tuple = self.tcx.mk_tup_from_iter(elt_ts_iter);
+ if let Err(guar) = tuple.error_reported() {
+ self.tcx.ty_error(guar)
} else {
self.require_type_is_sized(tuple, expr.span, traits::TupleInitializerSized);
tuple
@@ -1506,9 +1510,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
base_expr: &'tcx Option<&'tcx hir::Expr<'tcx>>,
) -> Ty<'tcx> {
// Find the relevant variant
- let Some((variant, adt_ty)) = self.check_struct_path(qpath, expr.hir_id) else {
- self.check_struct_fields_on_error(fields, base_expr);
- return self.tcx.ty_error();
+ let (variant, adt_ty) = match self.check_struct_path(qpath, expr.hir_id) {
+ Ok(data) => data,
+ Err(guar) => {
+ self.check_struct_fields_on_error(fields, base_expr);
+ return self.tcx.ty_error(guar);
+ }
};
// Prohibit struct expressions when non-exhaustive flag is set.
@@ -1590,12 +1597,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
self.field_ty(field.span, v_field, substs)
} else {
error_happened = true;
- if let Some(prev_span) = seen_fields.get(&ident) {
+ let guar = if let Some(prev_span) = seen_fields.get(&ident) {
tcx.sess.emit_err(FieldMultiplySpecifiedInInitializer {
span: field.ident.span,
prev_span: *prev_span,
ident,
- });
+ })
} else {
self.report_unknown_field(
adt_ty,
@@ -1604,10 +1611,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
ast_fields,
adt.variant_descr(),
expr_span,
- );
- }
+ )
+ };
- tcx.ty_error()
+ tcx.ty_error(guar)
};
// Make sure to give a type to the field even if there's
@@ -1990,14 +1997,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
skip_fields: &[hir::ExprField<'_>],
kind_name: &str,
expr_span: Span,
- ) {
+ ) -> ErrorGuaranteed {
if variant.is_recovered() {
- self.set_tainted_by_errors(
- self.tcx
- .sess
- .delay_span_bug(expr_span, "parser recovered but no error was emitted"),
- );
- return;
+ let guar = self
+ .tcx
+ .sess
+ .delay_span_bug(expr_span, "parser recovered but no error was emitted");
+ self.set_tainted_by_errors(guar);
+ return guar;
}
let mut err = self.err_ctxt().type_error_struct_with_diag(
field.ident.span,
@@ -2111,7 +2118,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
};
}
}
- err.emit();
+ err.emit()
}
// Return a hint about the closest match in field names
@@ -2151,13 +2158,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
variant: &'tcx ty::VariantDef,
access_span: Span,
) -> Vec<Symbol> {
+ let body_owner_hir_id = self.tcx.hir().local_def_id_to_hir_id(self.body_id);
variant
.fields
.iter()
.filter(|field| {
let def_scope = self
.tcx
- .adjust_ident_and_get_scope(field.ident(self.tcx), variant.def_id, self.body_id)
+ .adjust_ident_and_get_scope(
+ field.ident(self.tcx),
+ variant.def_id,
+ body_owner_hir_id,
+ )
.1;
field.vis.is_accessible_from(def_scope, self.tcx)
&& !matches!(
@@ -2199,8 +2211,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
match deref_base_ty.kind() {
ty::Adt(base_def, substs) if !base_def.is_enum() => {
debug!("struct named {:?}", deref_base_ty);
+ let body_hir_id = self.tcx.hir().local_def_id_to_hir_id(self.body_id);
let (ident, def_scope) =
- self.tcx.adjust_ident_and_get_scope(field, base_def.did(), self.body_id);
+ self.tcx.adjust_ident_and_get_scope(field, base_def.did(), body_hir_id);
let fields = &base_def.non_enum_variant().fields;
if let Some(index) = fields
.iter()
@@ -2246,11 +2259,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// (#90483) apply adjustments to avoid ExprUseVisitor from
// creating erroneous projection.
self.apply_adjustments(base, adjustments);
- self.ban_private_field_access(expr, base_ty, field, did, expected.only_has_type(self));
- return self.tcx().ty_error();
+ let guar = self.ban_private_field_access(
+ expr,
+ base_ty,
+ field,
+ did,
+ expected.only_has_type(self),
+ );
+ return self.tcx().ty_error(guar);
}
- if field.name == kw::Empty {
+ let guar = if field.name == kw::Empty {
+ self.tcx.sess.delay_span_bug(field.span, "field name with no name")
} else if self.method_exists(
field,
base_ty,
@@ -2258,9 +2278,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
true,
expected.only_has_type(self),
) {
- self.ban_take_value_of_method(expr, base_ty, field);
+ self.ban_take_value_of_method(expr, base_ty, field)
} else if !base_ty.is_primitive_ty() {
- self.ban_nonexisting_field(field, base, expr, base_ty);
+ self.ban_nonexisting_field(field, base, expr, base_ty)
} else {
let field_name = field.to_string();
let mut err = type_error_struct!(
@@ -2329,10 +2349,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
);
}
}
- err.emit();
- }
+ err.emit()
+ };
- self.tcx().ty_error()
+ self.tcx().ty_error(guar)
}
fn suggest_await_on_field_access(
@@ -2378,7 +2398,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
base: &'tcx hir::Expr<'tcx>,
expr: &'tcx hir::Expr<'tcx>,
base_ty: Ty<'tcx>,
- ) {
+ ) -> ErrorGuaranteed {
debug!(
"ban_nonexisting_field: field={:?}, base={:?}, expr={:?}, base_ty={:?}",
ident, base, expr, base_ty
@@ -2423,10 +2443,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// We know by construction that `<expr>.await` is either on Rust 2015
// or results in `ExprKind::Await`. Suggest switching the edition to 2018.
err.note("to `.await` a `Future`, switch to Rust 2018 or later");
- err.help_use_latest_edition();
+ HelpUseLatestEdition::new().add_to_diagnostic(&mut err);
}
- err.emit();
+ err.emit()
}
fn ban_private_field_access(
@@ -2436,9 +2456,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
field: Ident,
base_did: DefId,
return_ty: Option<Ty<'tcx>>,
- ) {
+ ) -> ErrorGuaranteed {
let struct_path = self.tcx().def_path_str(base_did);
- let kind_name = self.tcx().def_kind(base_did).descr(base_did);
+ let kind_name = self.tcx().def_descr(base_did);
let mut err = struct_span_err!(
self.tcx().sess,
field.span,
@@ -2459,10 +2479,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
None,
);
}
- err.emit();
+ err.emit()
}
- fn ban_take_value_of_method(&self, expr: &hir::Expr<'tcx>, expr_t: Ty<'tcx>, field: Ident) {
+ fn ban_take_value_of_method(
+ &self,
+ expr: &hir::Expr<'tcx>,
+ expr_t: Ty<'tcx>,
+ field: Ident,
+ ) -> ErrorGuaranteed {
let mut err = type_error_struct!(
self.tcx().sess,
field.span,
@@ -2534,11 +2559,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
err.help("methods are immutable and cannot be assigned to");
}
- err.emit();
+ err.emit()
}
fn point_at_param_definition(&self, err: &mut Diagnostic, param: ty::ParamTy) {
- let generics = self.tcx.generics_of(self.body_id.owner.to_def_id());
+ let generics = self.tcx.generics_of(self.body_id);
let generic_param = generics.type_param(&param, self.tcx);
if let ty::GenericParamDefKind::Type { synthetic: true, .. } = generic_param.kind {
return;
@@ -2592,7 +2617,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
len: ty::Const<'tcx>,
) {
if let (Some(len), Ok(user_index)) =
- (len.try_eval_usize(self.tcx, self.param_env), field.as_str().parse::<u64>())
+ (len.try_eval_target_usize(self.tcx, self.param_env), field.as_str().parse::<u64>())
&& let Ok(base) = self.tcx.sess.source_map().span_to_snippet(base.span)
{
let help = "instead of using tuple indexing, use array indexing";
@@ -2819,7 +2844,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
}
let reported = err.emit();
- self.tcx.ty_error_with_guaranteed(reported)
+ self.tcx.ty_error(reported)
}
}
}
diff --git a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs
index c8cda0dc9..b9a058d6b 100644
--- a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs
+++ b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs
@@ -301,7 +301,7 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> {
hir::ExprKind::Continue(..)
| hir::ExprKind::Lit(..)
| hir::ExprKind::ConstBlock(..)
- | hir::ExprKind::Err => {}
+ | hir::ExprKind::Err(_) => {}
hir::ExprKind::Loop(blk, ..) => {
self.walk_block(blk);
diff --git a/compiler/rustc_hir_typeck/src/fallback.rs b/compiler/rustc_hir_typeck/src/fallback.rs
index dde879780..b7ae621c6 100644
--- a/compiler/rustc_hir_typeck/src/fallback.rs
+++ b/compiler/rustc_hir_typeck/src/fallback.rs
@@ -104,7 +104,7 @@ impl<'tcx> FnCtxt<'_, 'tcx> {
// type, `?T` is not considered unsolved, but `?I` is. The
// same is true for float variables.)
let fallback = match ty.kind() {
- _ if let Some(e) = self.tainted_by_errors() => self.tcx.ty_error_with_guaranteed(e),
+ _ if let Some(e) = self.tainted_by_errors() => self.tcx.ty_error(e),
ty::Infer(ty::IntVar(_)) => self.tcx.types.i32,
ty::Infer(ty::FloatVar(_)) => self.tcx.types.f64,
_ => match diverging_fallback.get(&ty) {
@@ -196,8 +196,6 @@ impl<'tcx> FnCtxt<'_, 'tcx> {
) -> FxHashMap<Ty<'tcx>, 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();
@@ -281,9 +279,7 @@ impl<'tcx> FnCtxt<'_, 'tcx> {
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
@@ -297,16 +293,16 @@ impl<'tcx> FnCtxt<'_, 'tcx> {
.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 };
+ let mut found_infer_var_info = ty::InferVarInfo { self_in_trait: false, output: false };
- for (vid, rel) in relationships.iter() {
- if self.root_var(*vid) == root_vid {
- relationship.self_in_trait |= rel.self_in_trait;
- relationship.output |= rel.output;
+ for (vid, info) in self.inh.infer_var_info.borrow().iter() {
+ if self.infcx.root_var(*vid) == root_vid {
+ found_infer_var_info.self_in_trait |= info.self_in_trait;
+ found_infer_var_info.output |= info.output;
}
}
- if relationship.self_in_trait && relationship.output {
+ if found_infer_var_info.self_in_trait && found_infer_var_info.output {
// This case falls back to () to ensure that the code pattern in
// tests/ui/never_type/fallback-closure-ret.rs continues to
// compile when never_type_fallback is enabled.
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
index 6ed8adb47..60e55c7b0 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
@@ -23,16 +23,16 @@ use rustc_infer::infer::InferResult;
use rustc_middle::ty::adjustment::{Adjust, Adjustment, AutoBorrow, AutoBorrowMutability};
use rustc_middle::ty::error::TypeError;
use rustc_middle::ty::fold::TypeFoldable;
-use rustc_middle::ty::visit::TypeVisitable;
+use rustc_middle::ty::visit::{TypeVisitable, TypeVisitableExt};
use rustc_middle::ty::{
- self, AdtKind, CanonicalUserType, DefIdTree, GenericParamDefKind, Ty, UserType,
+ self, AdtKind, CanonicalUserType, DefIdTree, GenericParamDefKind, Ty, TyCtxt, UserType,
};
use rustc_middle::ty::{GenericArgKind, SubstsRef, UserSelfTy, UserSubsts};
use rustc_session::lint;
use rustc_span::def_id::LocalDefId;
use rustc_span::hygiene::DesugaringKind;
use rustc_span::symbol::{kw, sym, Ident};
-use rustc_span::{Span, DUMMY_SP};
+use rustc_span::Span;
use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt as _;
use rustc_trait_selection::traits::{self, NormalizeExt, ObligationCauseCode, ObligationCtxt};
@@ -315,7 +315,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
pub(in super::super) fn normalize<T>(&self, span: Span, value: T) -> T
where
- T: TypeFoldable<'tcx>,
+ T: TypeFoldable<TyCtxt<'tcx>>,
{
self.register_infer_ok_obligations(
self.at(&self.misc(span), self.param_env).normalize(value),
@@ -443,7 +443,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// sufficiently enforced with erased regions. =)
fn can_contain_user_lifetime_bounds<T>(t: T) -> bool
where
- T: TypeVisitable<'tcx>,
+ T: TypeVisitable<TyCtxt<'tcx>>,
{
t.has_free_regions() || t.has_projections() || t.has_infer_types()
}
@@ -451,11 +451,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
pub fn node_ty(&self, id: hir::HirId) -> Ty<'tcx> {
match self.typeck_results.borrow().node_types().get(id) {
Some(&t) => t,
- None if let Some(e) = self.tainted_by_errors() => self.tcx.ty_error_with_guaranteed(e),
+ None if let Some(e) = self.tainted_by_errors() => self.tcx.ty_error(e),
None => {
bug!(
- "no type for node {}: {} in fcx {}",
- id,
+ "no type for node {} in fcx {}",
self.tcx.hir().node_to_string(id),
self.tag()
);
@@ -466,7 +465,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
pub fn node_ty_opt(&self, id: hir::HirId) -> Option<Ty<'tcx>> {
match self.typeck_results.borrow().node_types().get(id) {
Some(&t) => Some(t),
- None if let Some(e) = self.tainted_by_errors() => Some(self.tcx.ty_error_with_guaranteed(e)),
+ None if let Some(e) = self.tainted_by_errors() => Some(self.tcx.ty_error(e)),
None => None,
}
}
@@ -517,16 +516,72 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
pub(in super::super) fn resolve_generator_interiors(&self, def_id: DefId) {
+ if self.tcx.sess.opts.unstable_opts.drop_tracking_mir {
+ self.save_generator_interior_predicates(def_id);
+ return;
+ }
+
+ self.select_obligations_where_possible(|_| {});
+
let mut generators = self.deferred_generator_interiors.borrow_mut();
- for (body_id, interior, kind) in generators.drain(..) {
- self.select_obligations_where_possible(|_| {});
+ for (_, body_id, interior, kind) in generators.drain(..) {
crate::generator_interior::resolve_interior(self, def_id, body_id, interior, kind);
+ self.select_obligations_where_possible(|_| {});
+ }
+ }
+
+ /// Unify the inference variables corresponding to generator witnesses, and save all the
+ /// predicates that were stalled on those inference variables.
+ ///
+ /// This process allows to conservatively save all predicates that do depend on the generator
+ /// interior types, for later processing by `check_generator_obligations`.
+ ///
+ /// We must not attempt to select obligations after this method has run, or risk query cycle
+ /// ICE.
+ #[instrument(level = "debug", skip(self))]
+ fn save_generator_interior_predicates(&self, def_id: DefId) {
+ // Try selecting all obligations that are not blocked on inference variables.
+ // Once we start unifying generator witnesses, trying to select obligations on them will
+ // trigger query cycle ICEs, as doing so requires MIR.
+ self.select_obligations_where_possible(|_| {});
+
+ let generators = std::mem::take(&mut *self.deferred_generator_interiors.borrow_mut());
+ debug!(?generators);
+
+ for &(expr_def_id, body_id, interior, _) in generators.iter() {
+ debug!(?expr_def_id);
+
+ // Create the `GeneratorWitness` type that we will unify with `interior`.
+ let substs = ty::InternalSubsts::identity_for_item(
+ self.tcx,
+ self.tcx.typeck_root_def_id(expr_def_id.to_def_id()),
+ );
+ let witness = self.tcx.mk_generator_witness_mir(expr_def_id.to_def_id(), substs);
+
+ // Unify `interior` with `witness` and collect all the resulting obligations.
+ let span = self.tcx.hir().body(body_id).value.span;
+ let ok = self
+ .at(&self.misc(span), self.param_env)
+ .eq(interior, witness)
+ .expect("Failed to unify generator interior type");
+ let mut obligations = ok.obligations;
+
+ // Also collect the obligations that were unstalled by this unification.
+ obligations
+ .extend(self.fulfillment_cx.borrow_mut().drain_unstalled_obligations(&self.infcx));
+
+ let obligations = obligations.into_iter().map(|o| (o.predicate, o.cause)).collect();
+ debug!(?obligations);
+ self.typeck_results
+ .borrow_mut()
+ .generator_interior_predicates
+ .insert(expr_def_id, obligations);
}
}
#[instrument(skip(self), level = "debug")]
- pub(in super::super) fn select_all_obligations_or_error(&self) {
- let mut errors = self.fulfillment_cx.borrow_mut().select_all_or_error(&self);
+ pub(in super::super) fn report_ambiguity_errors(&self) {
+ let mut errors = self.fulfillment_cx.borrow_mut().collect_remaining_errors();
if !errors.is_empty() {
self.adjust_fulfillment_errors_for_expr_obligation(&mut errors);
@@ -608,12 +663,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
ty::PredicateKind::Clause(ty::Clause::Trait(..))
| ty::PredicateKind::Clause(ty::Clause::Projection(..))
+ | ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(..))
| ty::PredicateKind::Subtype(..)
| ty::PredicateKind::Coerce(..)
| ty::PredicateKind::Clause(ty::Clause::RegionOutlives(..))
| ty::PredicateKind::Clause(ty::Clause::TypeOutlives(..))
| ty::PredicateKind::WellFormed(..)
| ty::PredicateKind::ObjectSafe(..)
+ | ty::PredicateKind::AliasEq(..)
| ty::PredicateKind::ConstEvaluatable(..)
| ty::PredicateKind::ConstEquate(..)
// N.B., this predicate is created by breaking down a
@@ -644,7 +701,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
pub(in super::super) fn err_args(&self, len: usize) -> Vec<Ty<'tcx>> {
- vec![self.tcx.ty_error(); len]
+ let ty_error = self.tcx.ty_error_misc();
+ vec![ty_error; len]
}
/// Unifies the output type with the expected type early, for more coercions
@@ -680,7 +738,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
if let ty::subst::GenericArgKind::Type(ty) = ty.unpack()
&& let ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }) = *ty.kind()
&& let Some(def_id) = def_id.as_local()
- && self.opaque_type_origin(def_id, DUMMY_SP).is_some() {
+ && self.opaque_type_origin(def_id).is_some() {
return None;
}
}
@@ -720,9 +778,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let def_kind = self.tcx.def_kind(def_id);
let item_ty = if let DefKind::Variant = def_kind {
- self.tcx.bound_type_of(self.tcx.parent(def_id))
+ self.tcx.type_of(self.tcx.parent(def_id))
} else {
- self.tcx.bound_type_of(def_id)
+ self.tcx.type_of(def_id)
};
let substs = self.fresh_substs_for_item(span, def_id);
let ty = item_ty.subst(self.tcx, substs);
@@ -866,6 +924,22 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
kind: hir::ImplItemKind::Fn(ref sig, ..),
..
}) => Some((&sig.decl, ident, false)),
+ Node::Expr(&hir::Expr {
+ hir_id,
+ kind: hir::ExprKind::Closure(..),
+ ..
+ }) if let Some(Node::Expr(&hir::Expr {
+ hir_id,
+ kind: hir::ExprKind::Call(..),
+ ..
+ })) = self.tcx.hir().find_parent(hir_id) &&
+ let Some(Node::Item(&hir::Item {
+ ident,
+ kind: hir::ItemKind::Fn(ref sig, ..),
+ ..
+ })) = self.tcx.hir().find_parent(hir_id) => {
+ Some((&sig.decl, ident, ident.name != sym::main))
+ },
_ => None,
}
}
@@ -926,43 +1000,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
}
- pub(in super::super) fn note_need_for_fn_pointer(
- &self,
- err: &mut Diagnostic,
- expected: Ty<'tcx>,
- found: Ty<'tcx>,
- ) {
- let (sig, did, substs) = match (&expected.kind(), &found.kind()) {
- (ty::FnDef(did1, substs1), ty::FnDef(did2, substs2)) => {
- let sig1 = self.tcx.bound_fn_sig(*did1).subst(self.tcx, substs1);
- let sig2 = self.tcx.bound_fn_sig(*did2).subst(self.tcx, substs2);
- if sig1 != sig2 {
- return;
- }
- err.note(
- "different `fn` items always have unique types, even if their signatures are \
- the same",
- );
- (sig1, *did1, substs1)
- }
- (ty::FnDef(did, substs), ty::FnPtr(sig2)) => {
- let sig1 = self.tcx.bound_fn_sig(*did).subst(self.tcx, substs);
- if sig1 != *sig2 {
- return;
- }
- (sig1, *did, substs)
- }
- _ => return,
- };
- err.help(&format!("change the expected type to be function pointer `{}`", sig));
- err.help(&format!(
- "if the expected type is due to type inference, cast the expected `fn` to a function \
- pointer: `{} as {}`",
- self.tcx.def_path_str_with_substs(did, substs),
- sig
- ));
- }
-
// 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")]
@@ -1095,7 +1132,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
.unwrap_or(false);
let (res, self_ctor_substs) = if let Res::SelfCtor(impl_def_id) = res {
- let ty = self.handle_raw_ty(span, tcx.at(span).type_of(impl_def_id));
+ let ty = self.handle_raw_ty(span, tcx.at(span).type_of(impl_def_id).subst_identity());
match ty.normalized.ty_adt_def() {
Some(adt_def) if adt_def.has_ctor() => {
let (ctor_kind, ctor_def_id) = adt_def.non_enum_variant().ctor.unwrap();
@@ -1125,7 +1162,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
}
let reported = err.emit();
- return (tcx.ty_error_with_guaranteed(reported), res);
+ return (tcx.ty_error(reported), res);
}
}
} else {
@@ -1191,7 +1228,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
(GenericParamDefKind::Const { .. }, GenericArg::Infer(inf)) => {
let tcx = self.fcx.tcx();
- self.fcx.ct_infer(tcx.type_of(param.def_id), Some(param), inf.span).into()
+ self.fcx
+ .ct_infer(
+ tcx.type_of(param.def_id)
+ .no_bound_vars()
+ .expect("const parameter types cannot be generic"),
+ Some(param),
+ inf.span,
+ )
+ .into()
}
_ => unreachable!(),
}
@@ -1213,7 +1258,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// If we have a default, then we it doesn't matter that we're not
// inferring the type arguments: we provide the default where any
// is missing.
- tcx.bound_type_of(param.def_id).subst(tcx, substs.unwrap()).into()
+ tcx.type_of(param.def_id).subst(tcx, substs.unwrap()).into()
} else {
// If no type arguments were provided, we have to infer them.
// This case also occurs as a result of some malformed input, e.g.
@@ -1261,7 +1306,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// Substitute the values for the type parameters into the type of
// the referenced item.
- let ty = tcx.bound_type_of(def_id);
+ let ty = tcx.type_of(def_id);
assert!(!substs.has_escaping_bound_vars());
assert!(!ty.0.has_escaping_bound_vars());
let ty_substituted = self.normalize(span, ty.subst(tcx, substs));
@@ -1272,7 +1317,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// type parameters, which we can infer by unifying the provided `Self`
// with the substituted impl type.
// This also occurs for an enum variant on a type alias.
- let impl_ty = self.normalize(span, tcx.bound_type_of(impl_def_id).subst(tcx, substs));
+ let impl_ty = self.normalize(span, tcx.type_of(impl_def_id).subst(tcx, substs));
let self_ty = self.normalize(span, self_ty);
match self.at(&self.misc(span), self.param_env).eq(impl_ty, self_ty) {
Ok(ok) => self.register_infer_ok_obligations(ok),
@@ -1373,7 +1418,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
.emit_inference_failure_err((**self).body_id, sp, ty.into(), E0282, true)
.emit()
});
- let err = self.tcx.ty_error_with_guaranteed(e);
+ let err = self.tcx.ty_error(e);
self.demand_suptype(sp, err, ty);
err
}
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs
new file mode 100644
index 000000000..b09886fe3
--- /dev/null
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs
@@ -0,0 +1,864 @@
+use crate::FnCtxt;
+use rustc_hir as hir;
+use rustc_hir::def::Res;
+use rustc_hir::def_id::DefId;
+use rustc_infer::traits::ObligationCauseCode;
+use rustc_middle::ty::{
+ self, DefIdTree, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitor,
+};
+use rustc_span::{self, Span};
+use rustc_trait_selection::traits;
+
+use std::ops::ControlFlow;
+
+impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
+ pub fn adjust_fulfillment_error_for_expr_obligation(
+ &self,
+ error: &mut traits::FulfillmentError<'tcx>,
+ ) -> bool {
+ let (traits::ExprItemObligation(def_id, hir_id, idx) | traits::ExprBindingObligation(def_id, _, hir_id, idx))
+ = *error.obligation.cause.code().peel_derives() else { return false; };
+ let hir = self.tcx.hir();
+ let hir::Node::Expr(expr) = hir.get(hir_id) else { return false; };
+
+ let Some(unsubstituted_pred) =
+ self.tcx.predicates_of(def_id).instantiate_identity(self.tcx).predicates.into_iter().nth(idx)
+ else { return false; };
+
+ let generics = self.tcx.generics_of(def_id);
+ let predicate_substs = match unsubstituted_pred.kind().skip_binder() {
+ ty::PredicateKind::Clause(ty::Clause::Trait(pred)) => pred.trait_ref.substs,
+ ty::PredicateKind::Clause(ty::Clause::Projection(pred)) => pred.projection_ty.substs,
+ _ => ty::List::empty(),
+ };
+
+ let find_param_matching = |matches: &dyn Fn(&ty::ParamTy) -> bool| {
+ predicate_substs.types().find_map(|ty| {
+ ty.walk().find_map(|arg| {
+ if let ty::GenericArgKind::Type(ty) = arg.unpack()
+ && let ty::Param(param_ty) = ty.kind()
+ && matches(param_ty)
+ {
+ Some(arg)
+ } else {
+ None
+ }
+ })
+ })
+ };
+
+ // Prefer generics that are local to the fn item, since these are likely
+ // to be the cause of the unsatisfied predicate.
+ let mut param_to_point_at = find_param_matching(&|param_ty| {
+ self.tcx.parent(generics.type_param(param_ty, self.tcx).def_id) == def_id
+ });
+ // Fall back to generic that isn't local to the fn item. This will come
+ // from a trait or impl, for example.
+ let mut fallback_param_to_point_at = find_param_matching(&|param_ty| {
+ self.tcx.parent(generics.type_param(param_ty, self.tcx).def_id) != def_id
+ && param_ty.name != rustc_span::symbol::kw::SelfUpper
+ });
+ // Finally, the `Self` parameter is possibly the reason that the predicate
+ // is unsatisfied. This is less likely to be true for methods, because
+ // method probe means that we already kinda check that the predicates due
+ // to the `Self` type are true.
+ let mut self_param_to_point_at =
+ find_param_matching(&|param_ty| param_ty.name == rustc_span::symbol::kw::SelfUpper);
+
+ // Finally, for ambiguity-related errors, we actually want to look
+ // for a parameter that is the source of the inference type left
+ // over in this predicate.
+ if let traits::FulfillmentErrorCode::CodeAmbiguity = error.code {
+ fallback_param_to_point_at = None;
+ self_param_to_point_at = None;
+ param_to_point_at =
+ self.find_ambiguous_parameter_in(def_id, error.root_obligation.predicate);
+ }
+
+ if self.closure_span_overlaps_error(error, expr.span) {
+ return false;
+ }
+
+ match &expr.kind {
+ hir::ExprKind::Path(qpath) => {
+ if let hir::Node::Expr(hir::Expr {
+ kind: hir::ExprKind::Call(callee, args),
+ hir_id: call_hir_id,
+ span: call_span,
+ ..
+ }) = hir.get_parent(expr.hir_id)
+ && callee.hir_id == expr.hir_id
+ {
+ if self.closure_span_overlaps_error(error, *call_span) {
+ return false;
+ }
+
+ for param in
+ [param_to_point_at, fallback_param_to_point_at, self_param_to_point_at]
+ .into_iter()
+ .flatten()
+ {
+ if self.blame_specific_arg_if_possible(
+ error,
+ def_id,
+ param,
+ *call_hir_id,
+ callee.span,
+ None,
+ args,
+ )
+ {
+ return true;
+ }
+ }
+ }
+ // Notably, we only point to params that are local to the
+ // item we're checking, since those are the ones we are able
+ // to look in the final `hir::PathSegment` for. Everything else
+ // would require a deeper search into the `qpath` than I think
+ // is worthwhile.
+ if let Some(param_to_point_at) = param_to_point_at
+ && self.point_at_path_if_possible(error, def_id, param_to_point_at, qpath)
+ {
+ return true;
+ }
+ }
+ hir::ExprKind::MethodCall(segment, receiver, args, ..) => {
+ for param in [param_to_point_at, fallback_param_to_point_at, self_param_to_point_at]
+ .into_iter()
+ .flatten()
+ {
+ if self.blame_specific_arg_if_possible(
+ error,
+ def_id,
+ param,
+ hir_id,
+ segment.ident.span,
+ Some(receiver),
+ args,
+ ) {
+ return true;
+ }
+ }
+ if let Some(param_to_point_at) = param_to_point_at
+ && self.point_at_generic_if_possible(error, def_id, param_to_point_at, segment)
+ {
+ return true;
+ }
+ }
+ hir::ExprKind::Struct(qpath, fields, ..) => {
+ if let Res::Def(
+ hir::def::DefKind::Struct | hir::def::DefKind::Variant,
+ variant_def_id,
+ ) = self.typeck_results.borrow().qpath_res(qpath, hir_id)
+ {
+ for param in
+ [param_to_point_at, fallback_param_to_point_at, self_param_to_point_at]
+ {
+ if let Some(param) = param {
+ let refined_expr = self.point_at_field_if_possible(
+ def_id,
+ param,
+ variant_def_id,
+ fields,
+ );
+
+ match refined_expr {
+ None => {}
+ Some((refined_expr, _)) => {
+ error.obligation.cause.span = refined_expr
+ .span
+ .find_ancestor_in_same_ctxt(error.obligation.cause.span)
+ .unwrap_or(refined_expr.span);
+ return true;
+ }
+ }
+ }
+ }
+ }
+ if let Some(param_to_point_at) = param_to_point_at
+ && self.point_at_path_if_possible(error, def_id, param_to_point_at, qpath)
+ {
+ return true;
+ }
+ }
+ _ => {}
+ }
+
+ false
+ }
+
+ fn point_at_path_if_possible(
+ &self,
+ error: &mut traits::FulfillmentError<'tcx>,
+ def_id: DefId,
+ param: ty::GenericArg<'tcx>,
+ qpath: &hir::QPath<'tcx>,
+ ) -> bool {
+ match qpath {
+ hir::QPath::Resolved(_, path) => {
+ if let Some(segment) = path.segments.last()
+ && self.point_at_generic_if_possible(error, def_id, param, segment)
+ {
+ return true;
+ }
+ }
+ hir::QPath::TypeRelative(_, segment) => {
+ if self.point_at_generic_if_possible(error, def_id, param, segment) {
+ return true;
+ }
+ }
+ _ => {}
+ }
+
+ false
+ }
+
+ fn point_at_generic_if_possible(
+ &self,
+ error: &mut traits::FulfillmentError<'tcx>,
+ def_id: DefId,
+ param_to_point_at: ty::GenericArg<'tcx>,
+ segment: &hir::PathSegment<'tcx>,
+ ) -> bool {
+ let own_substs = self
+ .tcx
+ .generics_of(def_id)
+ .own_substs(ty::InternalSubsts::identity_for_item(self.tcx, def_id));
+ let Some((index, _)) = own_substs
+ .iter()
+ .filter(|arg| matches!(arg.unpack(), ty::GenericArgKind::Type(_)))
+ .enumerate()
+ .find(|(_, arg)| **arg == param_to_point_at) else { return false };
+ let Some(arg) = segment
+ .args()
+ .args
+ .iter()
+ .filter(|arg| matches!(arg, hir::GenericArg::Type(_)))
+ .nth(index) else { return false; };
+ error.obligation.cause.span = arg
+ .span()
+ .find_ancestor_in_same_ctxt(error.obligation.cause.span)
+ .unwrap_or(arg.span());
+ true
+ }
+
+ fn find_ambiguous_parameter_in<T: TypeVisitable<TyCtxt<'tcx>>>(
+ &self,
+ item_def_id: DefId,
+ t: T,
+ ) -> Option<ty::GenericArg<'tcx>> {
+ struct FindAmbiguousParameter<'a, 'tcx>(&'a FnCtxt<'a, 'tcx>, DefId);
+ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for FindAmbiguousParameter<'_, 'tcx> {
+ type BreakTy = ty::GenericArg<'tcx>;
+ fn visit_ty(&mut self, ty: Ty<'tcx>) -> std::ops::ControlFlow<Self::BreakTy> {
+ if let Some(origin) = self.0.type_var_origin(ty)
+ && let rustc_infer::infer::type_variable::TypeVariableOriginKind::TypeParameterDefinition(_, Some(def_id)) =
+ origin.kind
+ && let generics = self.0.tcx.generics_of(self.1)
+ && let Some(index) = generics.param_def_id_to_index(self.0.tcx, def_id)
+ && let Some(subst) = ty::InternalSubsts::identity_for_item(self.0.tcx, self.1)
+ .get(index as usize)
+ {
+ ControlFlow::Break(*subst)
+ } else {
+ ty.super_visit_with(self)
+ }
+ }
+ }
+ t.visit_with(&mut FindAmbiguousParameter(self, item_def_id)).break_value()
+ }
+
+ fn closure_span_overlaps_error(
+ &self,
+ error: &traits::FulfillmentError<'tcx>,
+ span: Span,
+ ) -> bool {
+ if let traits::FulfillmentErrorCode::CodeSelectionError(
+ traits::SelectionError::OutputTypeParameterMismatch(_, expected, _),
+ ) = error.code
+ && let ty::Closure(def_id, _) | ty::Generator(def_id, ..) = expected.skip_binder().self_ty().kind()
+ && span.overlaps(self.tcx.def_span(*def_id))
+ {
+ true
+ } else {
+ false
+ }
+ }
+
+ fn point_at_field_if_possible(
+ &self,
+ def_id: DefId,
+ param_to_point_at: ty::GenericArg<'tcx>,
+ variant_def_id: DefId,
+ expr_fields: &[hir::ExprField<'tcx>],
+ ) -> Option<(&'tcx hir::Expr<'tcx>, Ty<'tcx>)> {
+ let def = self.tcx.adt_def(def_id);
+
+ let identity_substs = ty::InternalSubsts::identity_for_item(self.tcx, def_id);
+ let fields_referencing_param: Vec<_> = def
+ .variant_with_id(variant_def_id)
+ .fields
+ .iter()
+ .filter(|field| {
+ let field_ty = field.ty(self.tcx, identity_substs);
+ Self::find_param_in_ty(field_ty.into(), param_to_point_at)
+ })
+ .collect();
+
+ if let [field] = fields_referencing_param.as_slice() {
+ for expr_field in expr_fields {
+ // Look for the ExprField that matches the field, using the
+ // same rules that check_expr_struct uses for macro hygiene.
+ if self.tcx.adjust_ident(expr_field.ident, variant_def_id) == field.ident(self.tcx)
+ {
+ return Some((expr_field.expr, self.tcx.type_of(field.did).subst_identity()));
+ }
+ }
+ }
+
+ None
+ }
+
+ /// - `blame_specific_*` means that the function will recursively traverse the expression,
+ /// looking for the most-specific-possible span to blame.
+ ///
+ /// - `point_at_*` means that the function will only go "one level", pointing at the specific
+ /// expression mentioned.
+ ///
+ /// `blame_specific_arg_if_possible` will find the most-specific expression anywhere inside
+ /// the provided function call expression, and mark it as responsible for the fullfillment
+ /// error.
+ fn blame_specific_arg_if_possible(
+ &self,
+ error: &mut traits::FulfillmentError<'tcx>,
+ def_id: DefId,
+ param_to_point_at: ty::GenericArg<'tcx>,
+ call_hir_id: hir::HirId,
+ callee_span: Span,
+ receiver: Option<&'tcx hir::Expr<'tcx>>,
+ args: &'tcx [hir::Expr<'tcx>],
+ ) -> bool {
+ let ty = self.tcx.type_of(def_id).subst_identity();
+ if !ty.is_fn() {
+ return false;
+ }
+ let sig = ty.fn_sig(self.tcx).skip_binder();
+ let args_referencing_param: Vec<_> = sig
+ .inputs()
+ .iter()
+ .enumerate()
+ .filter(|(_, ty)| Self::find_param_in_ty((**ty).into(), param_to_point_at))
+ .collect();
+ // If there's one field that references the given generic, great!
+ if let [(idx, _)] = args_referencing_param.as_slice()
+ && let Some(arg) = receiver
+ .map_or(args.get(*idx), |rcvr| if *idx == 0 { Some(rcvr) } else { args.get(*idx - 1) }) {
+
+ error.obligation.cause.span = arg.span.find_ancestor_in_same_ctxt(error.obligation.cause.span).unwrap_or(arg.span);
+
+ if let hir::Node::Expr(arg_expr) = self.tcx.hir().get(arg.hir_id) {
+ // This is more specific than pointing at the entire argument.
+ self.blame_specific_expr_if_possible(error, arg_expr)
+ }
+
+ error.obligation.cause.map_code(|parent_code| {
+ ObligationCauseCode::FunctionArgumentObligation {
+ arg_hir_id: arg.hir_id,
+ call_hir_id,
+ parent_code,
+ }
+ });
+ return true;
+ } else if args_referencing_param.len() > 0 {
+ // If more than one argument applies, then point to the callee span at least...
+ // We have chance to fix this up further in `point_at_generics_if_possible`
+ error.obligation.cause.span = callee_span;
+ }
+
+ false
+ }
+
+ /**
+ * Recursively searches for the most-specific blamable expression.
+ * For example, if you have a chain of constraints like:
+ * - want `Vec<i32>: Copy`
+ * - because `Option<Vec<i32>>: Copy` needs `Vec<i32>: Copy` because `impl <T: Copy> Copy for Option<T>`
+ * - because `(Option<Vec<i32>, bool)` needs `Option<Vec<i32>>: Copy` because `impl <A: Copy, B: Copy> Copy for (A, B)`
+ * then if you pass in `(Some(vec![1, 2, 3]), false)`, this helper `point_at_specific_expr_if_possible`
+ * will find the expression `vec![1, 2, 3]` as the "most blameable" reason for this missing constraint.
+ *
+ * This function only updates the error span.
+ */
+ pub fn blame_specific_expr_if_possible(
+ &self,
+ error: &mut traits::FulfillmentError<'tcx>,
+ expr: &'tcx hir::Expr<'tcx>,
+ ) {
+ // Whether it succeeded or failed, it likely made some amount of progress.
+ // In the very worst case, it's just the same `expr` we originally passed in.
+ let expr = match self.blame_specific_expr_if_possible_for_obligation_cause_code(
+ &error.obligation.cause.code(),
+ expr,
+ ) {
+ Ok(expr) => expr,
+ Err(expr) => expr,
+ };
+
+ // Either way, use this expression to update the error span.
+ // If it doesn't overlap the existing span at all, use the original span.
+ // FIXME: It would possibly be better to do this more continuously, at each level...
+ error.obligation.cause.span = expr
+ .span
+ .find_ancestor_in_same_ctxt(error.obligation.cause.span)
+ .unwrap_or(error.obligation.cause.span);
+ }
+
+ fn blame_specific_expr_if_possible_for_obligation_cause_code(
+ &self,
+ obligation_cause_code: &traits::ObligationCauseCode<'tcx>,
+ expr: &'tcx hir::Expr<'tcx>,
+ ) -> Result<&'tcx hir::Expr<'tcx>, &'tcx hir::Expr<'tcx>> {
+ match obligation_cause_code {
+ traits::ObligationCauseCode::ExprBindingObligation(_, _, _, _) => {
+ // This is the "root"; we assume that the `expr` is already pointing here.
+ // Therefore, we return `Ok` so that this `expr` can be refined further.
+ Ok(expr)
+ }
+ traits::ObligationCauseCode::ImplDerivedObligation(impl_derived) => self
+ .blame_specific_expr_if_possible_for_derived_predicate_obligation(
+ impl_derived,
+ expr,
+ ),
+ _ => {
+ // We don't recognize this kind of constraint, so we cannot refine the expression
+ // any further.
+ Err(expr)
+ }
+ }
+ }
+
+ /// We want to achieve the error span in the following example:
+ ///
+ /// ```ignore (just for demonstration)
+ /// struct Burrito<Filling> {
+ /// filling: Filling,
+ /// }
+ /// impl <Filling: Delicious> Delicious for Burrito<Filling> {}
+ /// fn eat_delicious_food<Food: Delicious>(_food: Food) {}
+ ///
+ /// fn will_type_error() {
+ /// eat_delicious_food(Burrito { filling: Kale });
+ /// } // ^--- The trait bound `Kale: Delicious`
+ /// // is not satisfied
+ /// ```
+ ///
+ /// Without calling this function, the error span will cover the entire argument expression.
+ ///
+ /// Before we do any of this logic, we recursively call `point_at_specific_expr_if_possible` on the parent
+ /// obligation. Hence we refine the `expr` "outwards-in" and bail at the first kind of expression/impl we don't recognize.
+ ///
+ /// This function returns a `Result<&Expr, &Expr>` - either way, it returns the `Expr` whose span should be
+ /// reported as an error. If it is `Ok`, then it means it refined successfull. If it is `Err`, then it may be
+ /// only a partial success - but it cannot be refined even further.
+ fn blame_specific_expr_if_possible_for_derived_predicate_obligation(
+ &self,
+ obligation: &traits::ImplDerivedObligationCause<'tcx>,
+ expr: &'tcx hir::Expr<'tcx>,
+ ) -> Result<&'tcx hir::Expr<'tcx>, &'tcx hir::Expr<'tcx>> {
+ // First, we attempt to refine the `expr` for our span using the parent obligation.
+ // If this cannot be done, then we are already stuck, so we stop early (hence the use
+ // of the `?` try operator here).
+ let expr = self.blame_specific_expr_if_possible_for_obligation_cause_code(
+ &*obligation.derived.parent_code,
+ expr,
+ )?;
+
+ // This is the "trait" (meaning, the predicate "proved" by this `impl`) which provides the `Self` type we care about.
+ // For the purposes of this function, we hope that it is a `struct` type, and that our current `expr` is a literal of
+ // that struct type.
+ let impl_trait_self_ref = if self.tcx.is_trait_alias(obligation.impl_or_alias_def_id) {
+ self.tcx.mk_trait_ref(
+ obligation.impl_or_alias_def_id,
+ ty::InternalSubsts::identity_for_item(self.tcx, obligation.impl_or_alias_def_id),
+ )
+ } else {
+ self.tcx
+ .impl_trait_ref(obligation.impl_or_alias_def_id)
+ .map(|impl_def| impl_def.skip_binder())
+ // It is possible that this is absent. In this case, we make no progress.
+ .ok_or(expr)?
+ };
+
+ // We only really care about the `Self` type itself, which we extract from the ref.
+ let impl_self_ty: Ty<'tcx> = impl_trait_self_ref.self_ty();
+
+ let impl_predicates: ty::GenericPredicates<'tcx> =
+ self.tcx.predicates_of(obligation.impl_or_alias_def_id);
+ let Some(impl_predicate_index) = obligation.impl_def_predicate_index else {
+ // We don't have the index, so we can only guess.
+ return Err(expr);
+ };
+
+ if impl_predicate_index >= impl_predicates.predicates.len() {
+ // This shouldn't happen, but since this is only a diagnostic improvement, avoid breaking things.
+ return Err(expr);
+ }
+ let relevant_broken_predicate: ty::PredicateKind<'tcx> =
+ impl_predicates.predicates[impl_predicate_index].0.kind().skip_binder();
+
+ match relevant_broken_predicate {
+ ty::PredicateKind::Clause(ty::Clause::Trait(broken_trait)) => {
+ // ...
+ self.blame_specific_part_of_expr_corresponding_to_generic_param(
+ broken_trait.trait_ref.self_ty().into(),
+ expr,
+ impl_self_ty.into(),
+ )
+ }
+ _ => Err(expr),
+ }
+ }
+
+ /// Drills into `expr` to arrive at the equivalent location of `find_generic_param` in `in_ty`.
+ /// For example, given
+ /// - expr: `(Some(vec![1, 2, 3]), false)`
+ /// - param: `T`
+ /// - in_ty: `(Option<Vec<T>, bool)`
+ /// we would drill until we arrive at `vec![1, 2, 3]`.
+ ///
+ /// If successful, we return `Ok(refined_expr)`. If unsuccesful, we return `Err(partially_refined_expr`),
+ /// which will go as far as possible. For example, given `(foo(), false)` instead, we would drill to
+ /// `foo()` and then return `Err("foo()")`.
+ ///
+ /// This means that you can (and should) use the `?` try operator to chain multiple calls to this
+ /// function with different types, since you can only continue drilling the second time if you
+ /// succeeded the first time.
+ fn blame_specific_part_of_expr_corresponding_to_generic_param(
+ &self,
+ param: ty::GenericArg<'tcx>,
+ expr: &'tcx hir::Expr<'tcx>,
+ in_ty: ty::GenericArg<'tcx>,
+ ) -> Result<&'tcx hir::Expr<'tcx>, &'tcx hir::Expr<'tcx>> {
+ if param == in_ty {
+ // The types match exactly, so we have drilled as far as we can.
+ return Ok(expr);
+ }
+
+ let ty::GenericArgKind::Type(in_ty) = in_ty.unpack() else {
+ return Err(expr);
+ };
+
+ if let (
+ hir::ExprKind::AddrOf(_borrow_kind, _borrow_mutability, borrowed_expr),
+ ty::Ref(_ty_region, ty_ref_type, _ty_mutability),
+ ) = (&expr.kind, in_ty.kind())
+ {
+ // We can "drill into" the borrowed expression.
+ return self.blame_specific_part_of_expr_corresponding_to_generic_param(
+ param,
+ borrowed_expr,
+ (*ty_ref_type).into(),
+ );
+ }
+
+ if let (hir::ExprKind::Tup(expr_elements), ty::Tuple(in_ty_elements)) =
+ (&expr.kind, in_ty.kind())
+ {
+ if in_ty_elements.len() != expr_elements.len() {
+ return Err(expr);
+ }
+ // Find out which of `in_ty_elements` refer to `param`.
+ // FIXME: It may be better to take the first if there are multiple,
+ // just so that the error points to a smaller expression.
+ let Some((drill_expr, drill_ty)) = Self::is_iterator_singleton(expr_elements.iter().zip( in_ty_elements.iter()).filter(|(_expr_elem, in_ty_elem)| {
+ Self::find_param_in_ty((*in_ty_elem).into(), param)
+ })) else {
+ // The param is not mentioned, or it is mentioned in multiple indexes.
+ return Err(expr);
+ };
+
+ return self.blame_specific_part_of_expr_corresponding_to_generic_param(
+ param,
+ drill_expr,
+ drill_ty.into(),
+ );
+ }
+
+ if let (
+ hir::ExprKind::Struct(expr_struct_path, expr_struct_fields, _expr_struct_rest),
+ ty::Adt(in_ty_adt, in_ty_adt_generic_args),
+ ) = (&expr.kind, in_ty.kind())
+ {
+ // First, confirm that this struct is the same one as in the types, and if so,
+ // find the right variant.
+ let Res::Def(expr_struct_def_kind, expr_struct_def_id) = self.typeck_results.borrow().qpath_res(expr_struct_path, expr.hir_id) else {
+ return Err(expr);
+ };
+
+ let variant_def_id = match expr_struct_def_kind {
+ hir::def::DefKind::Struct => {
+ if in_ty_adt.did() != expr_struct_def_id {
+ // FIXME: Deal with type aliases?
+ return Err(expr);
+ }
+ expr_struct_def_id
+ }
+ hir::def::DefKind::Variant => {
+ // If this is a variant, its parent is the type definition.
+ if in_ty_adt.did() != self.tcx.parent(expr_struct_def_id) {
+ // FIXME: Deal with type aliases?
+ return Err(expr);
+ }
+ expr_struct_def_id
+ }
+ _ => {
+ return Err(expr);
+ }
+ };
+
+ // We need to know which of the generic parameters mentions our target param.
+ // We expect that at least one of them does, since it is expected to be mentioned.
+ let Some((drill_generic_index, generic_argument_type)) =
+ Self::is_iterator_singleton(
+ in_ty_adt_generic_args.iter().enumerate().filter(
+ |(_index, in_ty_generic)| {
+ Self::find_param_in_ty(*in_ty_generic, param)
+ },
+ ),
+ ) else {
+ return Err(expr);
+ };
+
+ let struct_generic_parameters: &ty::Generics = self.tcx.generics_of(in_ty_adt.did());
+ if drill_generic_index >= struct_generic_parameters.params.len() {
+ return Err(expr);
+ }
+
+ let param_to_point_at_in_struct = self.tcx.mk_param_from_def(
+ struct_generic_parameters.param_at(drill_generic_index, self.tcx),
+ );
+
+ // We make 3 steps:
+ // Suppose we have a type like
+ // ```ignore (just for demonstration)
+ // struct ExampleStruct<T> {
+ // enabled: bool,
+ // item: Option<(usize, T, bool)>,
+ // }
+ //
+ // f(ExampleStruct {
+ // enabled: false,
+ // item: Some((0, Box::new(String::new()), 1) }, true)),
+ // });
+ // ```
+ // Here, `f` is passed a `ExampleStruct<Box<String>>`, but it wants
+ // for `String: Copy`, which isn't true here.
+ //
+ // (1) First, we drill into `.item` and highlight that expression
+ // (2) Then we use the template type `Option<(usize, T, bool)>` to
+ // drill into the `T`, arriving at a `Box<String>` expression.
+ // (3) Then we keep going, drilling into this expression using our
+ // outer contextual information.
+
+ // (1) Find the (unique) field which mentions the type in our constraint:
+ let (field_expr, field_type) = self
+ .point_at_field_if_possible(
+ in_ty_adt.did(),
+ param_to_point_at_in_struct,
+ variant_def_id,
+ expr_struct_fields,
+ )
+ .ok_or(expr)?;
+
+ // (2) Continue drilling into the struct, ignoring the struct's
+ // generic argument types.
+ let expr = self.blame_specific_part_of_expr_corresponding_to_generic_param(
+ param_to_point_at_in_struct,
+ field_expr,
+ field_type.into(),
+ )?;
+
+ // (3) Continue drilling into the expression, having "passed
+ // through" the struct entirely.
+ return self.blame_specific_part_of_expr_corresponding_to_generic_param(
+ param,
+ expr,
+ generic_argument_type,
+ );
+ }
+
+ if let (
+ hir::ExprKind::Call(expr_callee, expr_args),
+ ty::Adt(in_ty_adt, in_ty_adt_generic_args),
+ ) = (&expr.kind, in_ty.kind())
+ {
+ let hir::ExprKind::Path(expr_callee_path) = &expr_callee.kind else {
+ // FIXME: This case overlaps with another one worth handling,
+ // which should happen above since it applies to non-ADTs:
+ // we can drill down into regular generic functions.
+ return Err(expr);
+ };
+ // This is (possibly) a constructor call, like `Some(...)` or `MyStruct(a, b, c)`.
+
+ let Res::Def(expr_struct_def_kind, expr_ctor_def_id) = self.typeck_results.borrow().qpath_res(expr_callee_path, expr_callee.hir_id) else {
+ return Err(expr);
+ };
+
+ let variant_def_id = match expr_struct_def_kind {
+ hir::def::DefKind::Ctor(hir::def::CtorOf::Struct, hir::def::CtorKind::Fn) => {
+ if in_ty_adt.did() != self.tcx.parent(expr_ctor_def_id) {
+ // FIXME: Deal with type aliases?
+ return Err(expr);
+ }
+ self.tcx.parent(expr_ctor_def_id)
+ }
+ hir::def::DefKind::Ctor(hir::def::CtorOf::Variant, hir::def::CtorKind::Fn) => {
+ // For a typical enum like
+ // `enum Blah<T> { Variant(T) }`
+ // we get the following resolutions:
+ // - expr_ctor_def_id ::: DefId(0:29 ~ source_file[b442]::Blah::Variant::{constructor#0})
+ // - self.tcx.parent(expr_ctor_def_id) ::: DefId(0:28 ~ source_file[b442]::Blah::Variant)
+ // - self.tcx.parent(self.tcx.parent(expr_ctor_def_id)) ::: DefId(0:26 ~ source_file[b442]::Blah)
+
+ // Therefore, we need to go up once to obtain the variant and up twice to obtain the type.
+ // Note that this pattern still holds even when we `use` a variant or `use` an enum type to rename it, or chain `use` expressions
+ // together; this resolution is handled automatically by `qpath_res`.
+
+ // FIXME: Deal with type aliases?
+ if in_ty_adt.did() == self.tcx.parent(self.tcx.parent(expr_ctor_def_id)) {
+ // The constructor definition refers to the "constructor" of the variant:
+ // For example, `Some(5)` triggers this case.
+ self.tcx.parent(expr_ctor_def_id)
+ } else {
+ // FIXME: Deal with type aliases?
+ return Err(expr);
+ }
+ }
+ _ => {
+ return Err(expr);
+ }
+ };
+
+ // We need to know which of the generic parameters mentions our target param.
+ // We expect that at least one of them does, since it is expected to be mentioned.
+ let Some((drill_generic_index, generic_argument_type)) =
+ Self::is_iterator_singleton(
+ in_ty_adt_generic_args.iter().enumerate().filter(
+ |(_index, in_ty_generic)| {
+ Self::find_param_in_ty(*in_ty_generic, param)
+ },
+ ),
+ ) else {
+ return Err(expr);
+ };
+
+ let struct_generic_parameters: &ty::Generics = self.tcx.generics_of(in_ty_adt.did());
+ if drill_generic_index >= struct_generic_parameters.params.len() {
+ return Err(expr);
+ }
+
+ let param_to_point_at_in_struct = self.tcx.mk_param_from_def(
+ struct_generic_parameters.param_at(drill_generic_index, self.tcx),
+ );
+
+ // We make 3 steps:
+ // Suppose we have a type like
+ // ```ignore (just for demonstration)
+ // struct ExampleStruct<T> {
+ // enabled: bool,
+ // item: Option<(usize, T, bool)>,
+ // }
+ //
+ // f(ExampleStruct {
+ // enabled: false,
+ // item: Some((0, Box::new(String::new()), 1) }, true)),
+ // });
+ // ```
+ // Here, `f` is passed a `ExampleStruct<Box<String>>`, but it wants
+ // for `String: Copy`, which isn't true here.
+ //
+ // (1) First, we drill into `.item` and highlight that expression
+ // (2) Then we use the template type `Option<(usize, T, bool)>` to
+ // drill into the `T`, arriving at a `Box<String>` expression.
+ // (3) Then we keep going, drilling into this expression using our
+ // outer contextual information.
+
+ // (1) Find the (unique) field index which mentions the type in our constraint:
+ let Some((field_index, field_type)) = Self::is_iterator_singleton(
+ in_ty_adt
+ .variant_with_id(variant_def_id)
+ .fields
+ .iter()
+ .map(|field| field.ty(self.tcx, *in_ty_adt_generic_args))
+ .enumerate()
+ .filter(|(_index, field_type)| Self::find_param_in_ty((*field_type).into(), param))
+ ) else {
+ return Err(expr);
+ };
+
+ if field_index >= expr_args.len() {
+ return Err(expr);
+ }
+
+ // (2) Continue drilling into the struct, ignoring the struct's
+ // generic argument types.
+ let expr = self.blame_specific_part_of_expr_corresponding_to_generic_param(
+ param_to_point_at_in_struct,
+ &expr_args[field_index],
+ field_type.into(),
+ )?;
+
+ // (3) Continue drilling into the expression, having "passed
+ // through" the struct entirely.
+ return self.blame_specific_part_of_expr_corresponding_to_generic_param(
+ param,
+ expr,
+ generic_argument_type,
+ );
+ }
+
+ // At this point, none of the basic patterns matched.
+ // One major possibility which remains is that we have a function call.
+ // In this case, it's often possible to dive deeper into the call to find something to blame,
+ // but this is not always possible.
+
+ Err(expr)
+ }
+
+ // FIXME: This can be made into a private, non-impl function later.
+ /// Traverses the given ty (either a `ty::Ty` or a `ty::GenericArg`) and searches for references
+ /// to the given `param_to_point_at`. Returns `true` if it finds any use of the param.
+ pub fn find_param_in_ty(
+ ty: ty::GenericArg<'tcx>,
+ param_to_point_at: ty::GenericArg<'tcx>,
+ ) -> bool {
+ let mut walk = ty.walk();
+ while let Some(arg) = walk.next() {
+ if arg == param_to_point_at {
+ return true;
+ }
+ if let ty::GenericArgKind::Type(ty) = arg.unpack()
+ && let ty::Alias(ty::Projection, ..) = ty.kind()
+ {
+ // This logic may seem a bit strange, but typically when
+ // we have a projection type in a function signature, the
+ // argument that's being passed into that signature is
+ // not actually constraining that projection's substs in
+ // a meaningful way. So we skip it, and see improvements
+ // in some UI tests.
+ walk.skip_current_subtree();
+ }
+ }
+ false
+ }
+
+ // FIXME: This can be made into a private, non-impl function later.
+ /// Returns `Some(iterator.next())` if it has exactly one item, and `None` otherwise.
+ pub fn is_iterator_singleton<T>(mut iterator: impl Iterator<Item = T>) -> Option<T> {
+ match (iterator.next(), iterator.next()) {
+ (_, Some(_)) => None,
+ (first, _) => first,
+ }
+ }
+}
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
index 2d841d53f..a46bdeb41 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
@@ -10,7 +10,9 @@ use crate::{
};
use rustc_ast as ast;
use rustc_data_structures::fx::FxIndexSet;
-use rustc_errors::{pluralize, Applicability, Diagnostic, DiagnosticId, MultiSpan};
+use rustc_errors::{
+ pluralize, Applicability, Diagnostic, DiagnosticId, ErrorGuaranteed, MultiSpan,
+};
use rustc_hir as hir;
use rustc_hir::def::{CtorOf, DefKind, Res};
use rustc_hir::def_id::DefId;
@@ -25,8 +27,8 @@ use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKi
use rustc_infer::infer::InferOk;
use rustc_infer::infer::TypeTrace;
use rustc_middle::ty::adjustment::AllowTwoPhase;
-use rustc_middle::ty::visit::TypeVisitable;
-use rustc_middle::ty::{self, DefIdTree, IsSuggestable, Ty, TypeSuperVisitable, TypeVisitor};
+use rustc_middle::ty::visit::TypeVisitableExt;
+use rustc_middle::ty::{self, DefIdTree, IsSuggestable, Ty};
use rustc_session::Session;
use rustc_span::symbol::{kw, Ident};
use rustc_span::{self, sym, Span};
@@ -34,8 +36,6 @@ use rustc_trait_selection::traits::{self, ObligationCauseCode, SelectionContext}
use std::iter;
use std::mem;
-use std::ops::ControlFlow;
-use std::slice;
impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
pub(in super::super) fn check_casts(&mut self) {
@@ -73,13 +73,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let ty = self.typeck_results.borrow().expr_ty_adjusted(expr);
let ty = self.resolve_vars_if_possible(ty);
if ty.has_non_region_infer() {
- self.tcx.ty_error()
+ self.tcx.ty_error_misc()
} else {
self.tcx.erase_regions(ty)
}
};
InlineAsmCtxt::new_in_fn(self.tcx, self.param_env, get_operand_ty)
- .check_asm(asm, self.tcx.hir().local_def_id_to_hir_id(enclosing_id));
+ .check_asm(asm, enclosing_id);
}
}
@@ -101,7 +101,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let err_inputs = match tuple_arguments {
DontTupleArguments => err_inputs,
- TupleArguments => vec![self.tcx.intern_tup(&err_inputs)],
+ TupleArguments => vec![self.tcx.mk_tup(&err_inputs)],
};
self.check_argument_types(
@@ -114,7 +114,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
tuple_arguments,
method.ok().map(|method| method.def_id),
);
- return self.tcx.ty_error();
+ return self.tcx.ty_error_misc();
}
let method = method.unwrap();
@@ -534,7 +534,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
.typeck_results
.borrow()
.expr_ty_adjusted_opt(*expr)
- .unwrap_or_else(|| tcx.ty_error());
+ .unwrap_or_else(|| tcx.ty_error_misc());
(self.resolve_vars_if_possible(ty), normalize_span(expr.span))
})
.collect();
@@ -641,7 +641,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
&& provided_arg_tys.len() == formal_and_expected_inputs.len() - 1 + tys.len()
{
// Wrap up the N provided arguments starting at this position in a tuple.
- let provided_as_tuple = tcx.mk_tup(
+ let provided_as_tuple = tcx.mk_tup_from_iter(
provided_arg_tys.iter().map(|(ty, _)| *ty).skip(mismatch_idx).take(tys.len()),
);
@@ -756,15 +756,20 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
errors.drain_filter(|error| {
- let Error::Invalid(provided_idx, expected_idx, Compatibility::Incompatible(Some(e))) = error else { return false };
- let (provided_ty, provided_span) = provided_arg_tys[*provided_idx];
- let trace = mk_trace(provided_span, formal_and_expected_inputs[*expected_idx], provided_ty);
- if !matches!(trace.cause.as_failure_code(*e), FailureCode::Error0308(_)) {
- self.err_ctxt().report_and_explain_type_error(trace, *e).emit();
- return true;
- }
- false
- });
+ let Error::Invalid(
+ provided_idx,
+ expected_idx,
+ Compatibility::Incompatible(Some(e)),
+ ) = error else { return false };
+ let (provided_ty, provided_span) = provided_arg_tys[*provided_idx];
+ let trace =
+ mk_trace(provided_span, formal_and_expected_inputs[*expected_idx], provided_ty);
+ if !matches!(trace.cause.as_failure_code(*e), FailureCode::Error0308(_)) {
+ self.err_ctxt().report_and_explain_type_error(trace, *e).emit();
+ return true;
+ }
+ false
+ });
// We're done if we found errors, but we already emitted them.
if errors.is_empty() {
@@ -798,6 +803,24 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
full_call_span,
format!("arguments to this {} are incorrect", call_name),
);
+ if let (Some(callee_ty), hir::ExprKind::MethodCall(_, rcvr, _, _)) =
+ (callee_ty, &call_expr.kind)
+ {
+ // Type that would have accepted this argument if it hadn't been inferred earlier.
+ // FIXME: We leave an inference variable for now, but it'd be nice to get a more
+ // specific type to increase the accuracy of the diagnostic.
+ let expected = self.infcx.next_ty_var(TypeVariableOrigin {
+ kind: TypeVariableOriginKind::MiscVariable,
+ span: full_call_span,
+ });
+ self.point_at_expr_source_of_inferred_type(
+ &mut err,
+ rcvr,
+ expected,
+ callee_ty,
+ provided_arg_span,
+ );
+ }
// Call out where the function is defined
self.label_fn_like(
&mut err,
@@ -847,7 +870,27 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
let mut suggestion_text = SuggestionText::None;
+ let ty_to_snippet = |ty: Ty<'tcx>, expected_idx: ExpectedIdx| {
+ if ty.is_unit() {
+ "()".to_string()
+ } else if ty.is_suggestable(tcx, false) {
+ format!("/* {} */", ty)
+ } else if let Some(fn_def_id) = fn_def_id
+ && self.tcx.def_kind(fn_def_id).is_fn_like()
+ && let self_implicit =
+ matches!(call_expr.kind, hir::ExprKind::MethodCall(..)) as usize
+ && let Some(arg) = self.tcx.fn_arg_names(fn_def_id)
+ .get(expected_idx.as_usize() + self_implicit)
+ && arg.name != kw::SelfLower
+ {
+ format!("/* {} */", arg.name)
+ } else {
+ "/* value */".to_string()
+ }
+ };
+
let mut errors = errors.into_iter().peekable();
+ let mut suggestions = vec![];
while let Some(error) = errors.next() {
match error {
Error::Invalid(provided_idx, expected_idx, compatibility) => {
@@ -888,12 +931,24 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
"".to_string()
};
labels
- .push((provided_span, format!("argument{} unexpected", provided_ty_name)));
- suggestion_text = match suggestion_text {
- SuggestionText::None => SuggestionText::Remove(false),
- SuggestionText::Remove(_) => SuggestionText::Remove(true),
- _ => SuggestionText::DidYouMean,
- };
+ .push((provided_span, format!("unexpected argument{}", provided_ty_name)));
+ let mut span = provided_span;
+ if span.can_be_used_for_suggestions() {
+ if arg_idx.index() > 0
+ && let Some((_, prev)) = provided_arg_tys
+ .get(ProvidedIdx::from_usize(arg_idx.index() - 1)
+ ) {
+ // Include previous comma
+ span = prev.shrink_to_hi().to(span);
+ }
+ suggestions.push((span, String::new()));
+
+ suggestion_text = match suggestion_text {
+ SuggestionText::None => SuggestionText::Remove(false),
+ SuggestionText::Remove(_) => SuggestionText::Remove(true),
+ _ => SuggestionText::DidYouMean,
+ };
+ }
}
Error::Missing(expected_idx) => {
// If there are multiple missing arguments adjacent to each other,
@@ -1078,6 +1133,45 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
}
+ // Incorporate the argument changes in the removal suggestion.
+ // When a type is *missing*, and the rest are additional, we want to suggest these with a
+ // multipart suggestion, but in order to do so we need to figure out *where* the arg that
+ // was provided but had the wrong type should go, because when looking at `expected_idx`
+ // that is the position in the argument list in the definition, while `provided_idx` will
+ // not be present. So we have to look at what the *last* provided position was, and point
+ // one after to suggest the replacement. FIXME(estebank): This is hacky, and there's
+ // probably a better more involved change we can make to make this work.
+ // For example, if we have
+ // ```
+ // fn foo(i32, &'static str) {}
+ // foo((), (), ());
+ // ```
+ // what should be suggested is
+ // ```
+ // foo(/* i32 */, /* &str */);
+ // ```
+ // which includes the replacement of the first two `()` for the correct type, and the
+ // removal of the last `()`.
+ let mut prev = -1;
+ for (expected_idx, provided_idx) in matched_inputs.iter_enumerated() {
+ // We want to point not at the *current* argument expression index, but rather at the
+ // index position where it *should have been*, which is *after* the previous one.
+ if let Some(provided_idx) = provided_idx {
+ prev = provided_idx.index() as i64;
+ }
+ let idx = ProvidedIdx::from_usize((prev + 1) as usize);
+ if let None = provided_idx
+ && let Some((_, arg_span)) = provided_arg_tys.get(idx)
+ {
+ // There is a type that was *not* found anywhere, so it isn't a move, but a
+ // replacement and we look at what type it should have been. This will allow us
+ // To suggest a multipart suggestion when encountering `foo(1, "")` where the def
+ // was `fn foo(())`.
+ let (_, expected_ty) = formal_and_expected_inputs[expected_idx];
+ suggestions.push((*arg_span, ty_to_snippet(expected_ty, expected_idx)));
+ }
+ }
+
// If we have less than 5 things to say, it would be useful to call out exactly what's wrong
if labels.len() <= 5 {
for (span, label) in labels {
@@ -1095,7 +1189,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
Some(format!("provide the argument{}", if plural { "s" } else { "" }))
}
SuggestionText::Remove(plural) => {
- Some(format!("remove the extra argument{}", if plural { "s" } else { "" }))
+ err.multipart_suggestion(
+ &format!("remove the extra argument{}", if plural { "s" } else { "" }),
+ suggestions,
+ Applicability::HasPlaceholders,
+ );
+ None
}
SuggestionText::Swap => Some("swap these arguments".to_string()),
SuggestionText::Reorder => Some("reorder these arguments".to_string()),
@@ -1134,20 +1233,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
} else {
// Propose a placeholder of the correct type
let (_, expected_ty) = formal_and_expected_inputs[expected_idx];
- if expected_ty.is_unit() {
- "()".to_string()
- } else if expected_ty.is_suggestable(tcx, false) {
- format!("/* {} */", expected_ty)
- } else if let Some(fn_def_id) = fn_def_id
- && self.tcx.def_kind(fn_def_id).is_fn_like()
- && let self_implicit = matches!(call_expr.kind, hir::ExprKind::MethodCall(..)) as usize
- && let Some(arg) = self.tcx.fn_arg_names(fn_def_id).get(expected_idx.as_usize() + self_implicit)
- && arg.name != kw::SelfLower
- {
- format!("/* {} */", arg.name)
- } else {
- "/* value */".to_string()
- }
+ ty_to_snippet(expected_ty, expected_idx)
};
suggestion += &suggestion_text;
}
@@ -1201,7 +1287,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
opt_ty.unwrap_or_else(|| self.next_float_var())
}
ast::LitKind::Bool(_) => tcx.types.bool,
- ast::LitKind::Err => tcx.ty_error(),
+ ast::LitKind::Err => tcx.ty_error_misc(),
}
}
@@ -1209,15 +1295,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
&self,
qpath: &QPath<'_>,
hir_id: hir::HirId,
- ) -> Option<(&'tcx ty::VariantDef, Ty<'tcx>)> {
+ ) -> Result<(&'tcx ty::VariantDef, Ty<'tcx>), ErrorGuaranteed> {
let path_span = qpath.span();
let (def, ty) = self.finish_resolving_struct_path(qpath, path_span, hir_id);
let variant = match def {
Res::Err => {
- self.set_tainted_by_errors(
- self.tcx.sess.delay_span_bug(path_span, "`Res::Err` but no error emitted"),
- );
- return None;
+ let guar =
+ self.tcx.sess.delay_span_bug(path_span, "`Res::Err` but no error emitted");
+ self.set_tainted_by_errors(guar);
+ return Err(guar);
}
Res::Def(DefKind::Variant, _) => match ty.normalized.ty_adt_def() {
Some(adt) => {
@@ -1245,28 +1331,26 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// Check bounds on type arguments used in the path.
self.add_required_obligations_for_hir(path_span, did, substs, hir_id);
- Some((variant, ty.normalized))
+ Ok((variant, ty.normalized))
} else {
- match ty.normalized.kind() {
- ty::Error(_) => {
+ Err(match *ty.normalized.kind() {
+ ty::Error(guar) => {
// 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).
+ guar
}
- _ => {
- struct_span_err!(
- self.tcx.sess,
- path_span,
- E0071,
- "expected struct, variant or union type, found {}",
- ty.normalized.sort_string(self.tcx)
- )
- .span_label(path_span, "not a struct")
- .emit();
- }
- }
- None
+ _ => struct_span_err!(
+ self.tcx.sess,
+ path_span,
+ E0071,
+ "expected struct, variant or union type, found {}",
+ ty.normalized.sort_string(self.tcx)
+ )
+ .span_label(path_span, "not a struct")
+ .emit(),
+ })
}
}
@@ -1313,11 +1397,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// Does the expected pattern type originate from an expression and what is the span?
let (origin_expr, ty_span) = match (decl.ty, decl.init) {
- (Some(ty), _) => (false, Some(ty.span)), // Bias towards the explicit user type.
+ (Some(ty), _) => (None, Some(ty.span)), // Bias towards the explicit user type.
(_, Some(init)) => {
- (true, Some(init.span.find_ancestor_inside(decl.span).unwrap_or(init.span)))
+ (Some(init), Some(init.span.find_ancestor_inside(decl.span).unwrap_or(init.span)))
} // No explicit type; so use the scrutinee.
- _ => (false, None), // We have `let $pat;`, so the expected type is unconstrained.
+ _ => (None, None), // We have `let $pat;`, so the expected type is unconstrained.
};
// Type check the pattern. Override if necessary to avoid knock-on errors.
@@ -1422,11 +1506,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let coerce = if blk.targeted_by_break {
CoerceMany::new(coerce_to_ty)
} else {
- let tail_expr: &[&hir::Expr<'_>] = match tail_expr {
- Some(e) => slice::from_ref(e),
- None => &[],
- };
- CoerceMany::with_coercion_sites(coerce_to_ty, tail_expr)
+ CoerceMany::with_coercion_sites(coerce_to_ty, blk.expr.as_slice())
};
let prev_diverges = self.diverges.get();
@@ -1630,9 +1710,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
pat: &'tcx hir::Pat<'tcx>,
ty: Ty<'tcx>,
) {
- if ty.references_error() {
+ if let Err(guar) = ty.error_reported() {
// Override the types everywhere with `err()` to avoid knock on errors.
- let err = self.tcx.ty_error();
+ let err = self.tcx.ty_error(guar);
self.write_ty(hir_id, err);
self.write_ty(pat.hir_id, err);
let local_ty = LocalTy { decl_ty: err, revealed_ty: err };
@@ -1652,7 +1732,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
match *qpath {
QPath::Resolved(ref maybe_qself, ref path) => {
let self_ty = maybe_qself.as_ref().map(|qself| self.to_ty(qself).raw);
- let ty = self.astconv().res_to_ty(self_ty, path, true);
+ let ty = self.astconv().res_to_ty(self_ty, path, hir_id, true);
(path.res, self.handle_raw_ty(path_span, ty))
}
QPath::TypeRelative(ref qself, ref segment) => {
@@ -1661,7 +1741,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let result = self
.astconv()
.associated_path_to_ty(hir_id, path_span, ty.raw, qself, segment, true);
- let ty = result.map(|(ty, _, _)| ty).unwrap_or_else(|_| self.tcx().ty_error());
+ let ty =
+ result.map(|(ty, _, _)| ty).unwrap_or_else(|guar| self.tcx().ty_error(guar));
let ty = self.handle_raw_ty(path_span, ty);
let result = result.map(|(_, kind, def_id)| (kind, def_id));
@@ -1739,353 +1820,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
}
- fn adjust_fulfillment_error_for_expr_obligation(
- &self,
- error: &mut traits::FulfillmentError<'tcx>,
- ) -> bool {
- let (traits::ExprItemObligation(def_id, hir_id, idx) | traits::ExprBindingObligation(def_id, _, hir_id, idx))
- = *error.obligation.cause.code().peel_derives() else { return false; };
- let hir = self.tcx.hir();
- let hir::Node::Expr(expr) = hir.get(hir_id) else { return false; };
-
- let Some(unsubstituted_pred) =
- self.tcx.predicates_of(def_id).instantiate_identity(self.tcx).predicates.into_iter().nth(idx)
- else { return false; };
-
- let generics = self.tcx.generics_of(def_id);
- let predicate_substs = match unsubstituted_pred.kind().skip_binder() {
- ty::PredicateKind::Clause(ty::Clause::Trait(pred)) => pred.trait_ref.substs,
- ty::PredicateKind::Clause(ty::Clause::Projection(pred)) => pred.projection_ty.substs,
- _ => ty::List::empty(),
- };
-
- let find_param_matching = |matches: &dyn Fn(&ty::ParamTy) -> bool| {
- predicate_substs.types().find_map(|ty| {
- ty.walk().find_map(|arg| {
- if let ty::GenericArgKind::Type(ty) = arg.unpack()
- && let ty::Param(param_ty) = ty.kind()
- && matches(param_ty)
- {
- Some(arg)
- } else {
- None
- }
- })
- })
- };
-
- // Prefer generics that are local to the fn item, since these are likely
- // to be the cause of the unsatisfied predicate.
- let mut param_to_point_at = find_param_matching(&|param_ty| {
- self.tcx.parent(generics.type_param(param_ty, self.tcx).def_id) == def_id
- });
- // Fall back to generic that isn't local to the fn item. This will come
- // from a trait or impl, for example.
- let mut fallback_param_to_point_at = find_param_matching(&|param_ty| {
- self.tcx.parent(generics.type_param(param_ty, self.tcx).def_id) != def_id
- && param_ty.name != rustc_span::symbol::kw::SelfUpper
- });
- // Finally, the `Self` parameter is possibly the reason that the predicate
- // is unsatisfied. This is less likely to be true for methods, because
- // method probe means that we already kinda check that the predicates due
- // to the `Self` type are true.
- let mut self_param_to_point_at =
- find_param_matching(&|param_ty| param_ty.name == rustc_span::symbol::kw::SelfUpper);
-
- // Finally, for ambiguity-related errors, we actually want to look
- // for a parameter that is the source of the inference type left
- // over in this predicate.
- if let traits::FulfillmentErrorCode::CodeAmbiguity = error.code {
- fallback_param_to_point_at = None;
- self_param_to_point_at = None;
- param_to_point_at =
- self.find_ambiguous_parameter_in(def_id, error.root_obligation.predicate);
- }
-
- if self.closure_span_overlaps_error(error, expr.span) {
- return false;
- }
-
- match &expr.kind {
- hir::ExprKind::Path(qpath) => {
- if let hir::Node::Expr(hir::Expr {
- kind: hir::ExprKind::Call(callee, args),
- hir_id: call_hir_id,
- span: call_span,
- ..
- }) = hir.get_parent(expr.hir_id)
- && callee.hir_id == expr.hir_id
- {
- if self.closure_span_overlaps_error(error, *call_span) {
- return false;
- }
-
- for param in
- [param_to_point_at, fallback_param_to_point_at, self_param_to_point_at]
- .into_iter()
- .flatten()
- {
- if self.point_at_arg_if_possible(
- error,
- def_id,
- param,
- *call_hir_id,
- callee.span,
- None,
- args,
- )
- {
- return true;
- }
- }
- }
- // Notably, we only point to params that are local to the
- // item we're checking, since those are the ones we are able
- // to look in the final `hir::PathSegment` for. Everything else
- // would require a deeper search into the `qpath` than I think
- // is worthwhile.
- if let Some(param_to_point_at) = param_to_point_at
- && self.point_at_path_if_possible(error, def_id, param_to_point_at, qpath)
- {
- return true;
- }
- }
- hir::ExprKind::MethodCall(segment, receiver, args, ..) => {
- for param in [param_to_point_at, fallback_param_to_point_at, self_param_to_point_at]
- .into_iter()
- .flatten()
- {
- if self.point_at_arg_if_possible(
- error,
- def_id,
- param,
- hir_id,
- segment.ident.span,
- Some(receiver),
- args,
- ) {
- return true;
- }
- }
- if let Some(param_to_point_at) = param_to_point_at
- && self.point_at_generic_if_possible(error, def_id, param_to_point_at, segment)
- {
- return true;
- }
- }
- hir::ExprKind::Struct(qpath, fields, ..) => {
- if let Res::Def(DefKind::Struct | DefKind::Variant, variant_def_id) =
- self.typeck_results.borrow().qpath_res(qpath, hir_id)
- {
- for param in
- [param_to_point_at, fallback_param_to_point_at, self_param_to_point_at]
- {
- if let Some(param) = param
- && self.point_at_field_if_possible(
- error,
- def_id,
- param,
- variant_def_id,
- fields,
- )
- {
- return true;
- }
- }
- }
- if let Some(param_to_point_at) = param_to_point_at
- && self.point_at_path_if_possible(error, def_id, param_to_point_at, qpath)
- {
- return true;
- }
- }
- _ => {}
- }
-
- false
- }
-
- fn closure_span_overlaps_error(
- &self,
- error: &traits::FulfillmentError<'tcx>,
- span: Span,
- ) -> bool {
- if let traits::FulfillmentErrorCode::CodeSelectionError(
- traits::SelectionError::OutputTypeParameterMismatch(_, expected, _),
- ) = error.code
- && let ty::Closure(def_id, _) | ty::Generator(def_id, ..) = expected.skip_binder().self_ty().kind()
- && span.overlaps(self.tcx.def_span(*def_id))
- {
- true
- } else {
- false
- }
- }
-
- fn point_at_arg_if_possible(
- &self,
- error: &mut traits::FulfillmentError<'tcx>,
- def_id: DefId,
- param_to_point_at: ty::GenericArg<'tcx>,
- call_hir_id: hir::HirId,
- callee_span: Span,
- receiver: Option<&'tcx hir::Expr<'tcx>>,
- args: &'tcx [hir::Expr<'tcx>],
- ) -> bool {
- let ty = self.tcx.type_of(def_id);
- if !ty.is_fn() {
- return false;
- }
- let sig = ty.fn_sig(self.tcx).skip_binder();
- let args_referencing_param: Vec<_> = sig
- .inputs()
- .iter()
- .enumerate()
- .filter(|(_, ty)| find_param_in_ty(**ty, param_to_point_at))
- .collect();
- // If there's one field that references the given generic, great!
- if let [(idx, _)] = args_referencing_param.as_slice()
- && let Some(arg) = receiver
- .map_or(args.get(*idx), |rcvr| if *idx == 0 { Some(rcvr) } else { args.get(*idx - 1) }) {
- error.obligation.cause.span = arg.span.find_ancestor_in_same_ctxt(error.obligation.cause.span).unwrap_or(arg.span);
- error.obligation.cause.map_code(|parent_code| {
- ObligationCauseCode::FunctionArgumentObligation {
- arg_hir_id: arg.hir_id,
- call_hir_id,
- parent_code,
- }
- });
- return true;
- } else if args_referencing_param.len() > 0 {
- // If more than one argument applies, then point to the callee span at least...
- // We have chance to fix this up further in `point_at_generics_if_possible`
- error.obligation.cause.span = callee_span;
- }
-
- false
- }
-
- fn point_at_field_if_possible(
- &self,
- error: &mut traits::FulfillmentError<'tcx>,
- def_id: DefId,
- param_to_point_at: ty::GenericArg<'tcx>,
- variant_def_id: DefId,
- expr_fields: &[hir::ExprField<'tcx>],
- ) -> bool {
- let def = self.tcx.adt_def(def_id);
-
- let identity_substs = ty::InternalSubsts::identity_for_item(self.tcx, def_id);
- let fields_referencing_param: Vec<_> = def
- .variant_with_id(variant_def_id)
- .fields
- .iter()
- .filter(|field| {
- let field_ty = field.ty(self.tcx, identity_substs);
- find_param_in_ty(field_ty, param_to_point_at)
- })
- .collect();
-
- if let [field] = fields_referencing_param.as_slice() {
- for expr_field in expr_fields {
- // Look for the ExprField that matches the field, using the
- // same rules that check_expr_struct uses for macro hygiene.
- if self.tcx.adjust_ident(expr_field.ident, variant_def_id) == field.ident(self.tcx)
- {
- error.obligation.cause.span = expr_field
- .expr
- .span
- .find_ancestor_in_same_ctxt(error.obligation.cause.span)
- .unwrap_or(expr_field.span);
- return true;
- }
- }
- }
-
- false
- }
-
- fn point_at_path_if_possible(
- &self,
- error: &mut traits::FulfillmentError<'tcx>,
- def_id: DefId,
- param: ty::GenericArg<'tcx>,
- qpath: &QPath<'tcx>,
- ) -> bool {
- match qpath {
- hir::QPath::Resolved(_, path) => {
- if let Some(segment) = path.segments.last()
- && self.point_at_generic_if_possible(error, def_id, param, segment)
- {
- return true;
- }
- }
- hir::QPath::TypeRelative(_, segment) => {
- if self.point_at_generic_if_possible(error, def_id, param, segment) {
- return true;
- }
- }
- _ => {}
- }
-
- false
- }
-
- fn point_at_generic_if_possible(
- &self,
- error: &mut traits::FulfillmentError<'tcx>,
- def_id: DefId,
- param_to_point_at: ty::GenericArg<'tcx>,
- segment: &hir::PathSegment<'tcx>,
- ) -> bool {
- let own_substs = self
- .tcx
- .generics_of(def_id)
- .own_substs(ty::InternalSubsts::identity_for_item(self.tcx, def_id));
- let Some((index, _)) = own_substs
- .iter()
- .filter(|arg| matches!(arg.unpack(), ty::GenericArgKind::Type(_)))
- .enumerate()
- .find(|(_, arg)| **arg == param_to_point_at) else { return false };
- let Some(arg) = segment
- .args()
- .args
- .iter()
- .filter(|arg| matches!(arg, hir::GenericArg::Type(_)))
- .nth(index) else { return false; };
- error.obligation.cause.span = arg
- .span()
- .find_ancestor_in_same_ctxt(error.obligation.cause.span)
- .unwrap_or(arg.span());
- true
- }
-
- fn find_ambiguous_parameter_in<T: TypeVisitable<'tcx>>(
- &self,
- item_def_id: DefId,
- t: T,
- ) -> Option<ty::GenericArg<'tcx>> {
- struct FindAmbiguousParameter<'a, 'tcx>(&'a FnCtxt<'a, 'tcx>, DefId);
- impl<'tcx> TypeVisitor<'tcx> for FindAmbiguousParameter<'_, 'tcx> {
- type BreakTy = ty::GenericArg<'tcx>;
- fn visit_ty(&mut self, ty: Ty<'tcx>) -> std::ops::ControlFlow<Self::BreakTy> {
- if let Some(origin) = self.0.type_var_origin(ty)
- && let TypeVariableOriginKind::TypeParameterDefinition(_, Some(def_id)) =
- origin.kind
- && let generics = self.0.tcx.generics_of(self.1)
- && let Some(index) = generics.param_def_id_to_index(self.0.tcx, def_id)
- && let Some(subst) = ty::InternalSubsts::identity_for_item(self.0.tcx, self.1)
- .get(index as usize)
- {
- ControlFlow::Break(*subst)
- } else {
- ty.super_visit_with(self)
- }
- }
- }
- t.visit_with(&mut FindAmbiguousParameter(self, item_def_id)).break_value()
- }
-
fn label_fn_like(
&self,
err: &mut Diagnostic,
@@ -2114,7 +1848,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
match *callee_ty.kind() {
ty::Param(param) => {
let param =
- self.tcx.generics_of(self.body_id.owner).type_param(&param, self.tcx);
+ self.tcx.generics_of(self.body_id).type_param(&param, self.tcx);
if param.kind.is_synthetic() {
// if it's `impl Fn() -> ..` then just fall down to the def-id based logic
def_id = param.def_id;
@@ -2123,7 +1857,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// and point at that.
let instantiated = self
.tcx
- .explicit_predicates_of(self.body_id.owner)
+ .explicit_predicates_of(self.body_id)
.instantiate_identity(self.tcx);
// FIXME(compiler-errors): This could be problematic if something has two
// fn-like predicates with different args, but callable types really never
@@ -2200,8 +1934,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
spans.push_span_label(param.span, "");
}
- let def_kind = self.tcx.def_kind(def_id);
- err.span_note(spans, &format!("{} defined here", def_kind.descr(def_id)));
+ err.span_note(spans, &format!("{} defined here", self.tcx.def_descr(def_id)));
} else if let Some(hir::Node::Expr(e)) = self.tcx.hir().get_if_local(def_id)
&& let hir::ExprKind::Closure(hir::Closure { body, .. }) = &e.kind
{
@@ -2214,31 +1947,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
};
err.span_note(span, &format!("{} defined here", kind));
} else {
- let def_kind = self.tcx.def_kind(def_id);
err.span_note(
self.tcx.def_span(def_id),
- &format!("{} defined here", def_kind.descr(def_id)),
+ &format!("{} defined here", self.tcx.def_descr(def_id)),
);
}
}
}
-
-fn find_param_in_ty<'tcx>(ty: Ty<'tcx>, param_to_point_at: ty::GenericArg<'tcx>) -> bool {
- let mut walk = ty.walk();
- while let Some(arg) = walk.next() {
- if arg == param_to_point_at {
- return true;
- } else if let ty::GenericArgKind::Type(ty) = arg.unpack()
- && let ty::Alias(ty::Projection, ..) = ty.kind()
- {
- // This logic may seem a bit strange, but typically when
- // we have a projection type in a function signature, the
- // argument that's being passed into that signature is
- // not actually constraining that projection's substs in
- // a meaningful way. So we skip it, and see improvements
- // in some UI tests.
- walk.skip_current_subtree();
- }
- }
- false
-}
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs
index 428fde642..1dea3e6f9 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs
@@ -1,4 +1,5 @@
mod _impl;
+mod adjust_fulfillment_errors;
mod arg_matrix;
mod checks;
mod suggestions;
@@ -10,14 +11,14 @@ pub use suggestions::*;
use crate::coercion::DynamicCoerceMany;
use crate::{Diverges, EnclosingBreakables, Inherited};
use rustc_hir as hir;
-use rustc_hir::def_id::DefId;
+use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_hir_analysis::astconv::AstConv;
use rustc_infer::infer;
use rustc_infer::infer::error_reporting::TypeErrCtxt;
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
use rustc_middle::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind};
use rustc_middle::ty::subst::GenericArgKind;
-use rustc_middle::ty::{self, Const, Ty, TyCtxt, TypeVisitable};
+use rustc_middle::ty::{self, Const, Ty, TyCtxt, TypeVisitableExt};
use rustc_session::Session;
use rustc_span::symbol::Ident;
use rustc_span::{self, Span, DUMMY_SP};
@@ -38,7 +39,7 @@ use std::ops::Deref;
/// [`ItemCtxt`]: rustc_hir_analysis::collect::ItemCtxt
/// [`InferCtxt`]: infer::InferCtxt
pub struct FnCtxt<'a, 'tcx> {
- pub(super) body_id: hir::HirId,
+ pub(super) body_id: LocalDefId,
/// The parameter environment used for proving trait obligations
/// in this function. This can change when we descend into
@@ -117,7 +118,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
pub fn new(
inh: &'a Inherited<'tcx>,
param_env: ty::ParamEnv<'tcx>,
- body_id: hir::HirId,
+ body_id: LocalDefId,
) -> FnCtxt<'a, 'tcx> {
FnCtxt {
body_id,
@@ -204,7 +205,7 @@ impl<'a, 'tcx> AstConv<'tcx> for FnCtxt<'a, 'tcx> {
}
fn item_def_id(&self) -> DefId {
- self.body_id.owner.to_def_id()
+ self.body_id.to_def_id()
}
fn get_type_parameter_bounds(
@@ -288,7 +289,7 @@ impl<'a, 'tcx> AstConv<'tcx> for FnCtxt<'a, 'tcx> {
item_segment: &hir::PathSegment<'_>,
poly_trait_ref: ty::PolyTraitRef<'tcx>,
) -> Ty<'tcx> {
- let trait_ref = self.replace_bound_vars_with_fresh_vars(
+ let trait_ref = self.instantiate_binder_with_fresh_vars(
span,
infer::LateBoundRegionConversionTime::AssocTypeProjection(item_def_id),
poly_trait_ref,
@@ -324,6 +325,10 @@ impl<'a, 'tcx> AstConv<'tcx> for FnCtxt<'a, 'tcx> {
let ty = if !ty.has_escaping_bound_vars() { self.normalize(span, ty) } else { ty };
self.write_ty(hir_id, ty)
}
+
+ fn infcx(&self) -> Option<&infer::InferCtxt<'tcx>> {
+ Some(&self.infcx)
+ }
}
/// Represents a user-provided type in the raw form (never normalized).
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
index 4d673ac91..c49621b7c 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
@@ -1,6 +1,7 @@
use super::FnCtxt;
use crate::errors::{AddReturnTypeSuggestion, ExpectedReturnTypeLabel};
+use crate::fluent_generated as fluent;
use crate::method::probe::{IsSuggestion, Mode, ProbeScope};
use rustc_ast::util::parser::{ExprPrecedence, PREC_POSTFIX};
use rustc_errors::{Applicability, Diagnostic, MultiSpan};
@@ -13,9 +14,10 @@ use rustc_hir::{
use rustc_hir_analysis::astconv::AstConv;
use rustc_infer::traits::{self, StatementAsExpression};
use rustc_middle::lint::in_external_macro;
+use rustc_middle::ty::print::with_no_trimmed_paths;
use rustc_middle::ty::{
self, suggest_constraining_type_params, Binder, DefIdTree, IsSuggestable, ToPredicate, Ty,
- TypeVisitable,
+ TypeVisitableExt,
};
use rustc_session::errors::ExprParenthesesNeeded;
use rustc_span::source_map::Spanned;
@@ -31,7 +33,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
self.typeck_results
.borrow()
.liberated_fn_sigs()
- .get(self.tcx.hir().parent_id(self.body_id))
+ .get(self.tcx.hir().local_def_id_to_hir_id(self.body_id))
.copied()
}
@@ -119,7 +121,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
DefIdOrName::DefId(def_id) => match self.tcx.def_kind(def_id) {
DefKind::Ctor(CtorOf::Struct, _) => "construct this tuple struct".to_string(),
DefKind::Ctor(CtorOf::Variant, _) => "construct this tuple variant".to_string(),
- kind => format!("call this {}", kind.descr(def_id)),
+ kind => format!("call this {}", self.tcx.def_kind_descr(kind, def_id)),
},
DefIdOrName::Name(name) => format!("call this {name}"),
};
@@ -164,7 +166,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
&self,
ty: Ty<'tcx>,
) -> Option<(DefIdOrName, Ty<'tcx>, Vec<Ty<'tcx>>)> {
- self.err_ctxt().extract_callable_info(self.body_id, self.param_env, ty)
+ let body_hir_id = self.tcx.hir().local_def_id_to_hir_id(self.body_id);
+ self.err_ctxt().extract_callable_info(body_hir_id, self.param_env, ty)
}
pub fn suggest_two_fn_call(
@@ -337,7 +340,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
CtorOf::Variant => "an enum variant",
}));
} else {
- let descr = kind.descr(def_id);
+ let descr = self.tcx.def_kind_descr(kind, def_id);
err.span_label(sp, format!("{descr} `{name}` defined here"));
}
return true;
@@ -413,11 +416,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
if let ty::Adt(adt, _) = peeled.kind()
&& Some(adt.did()) == self.tcx.lang_items().string()
{
+ let sugg = if ref_cnt == 0 {
+ ".as_deref()"
+ } else {
+ ".map(|x| x.as_str())"
+ };
err.span_suggestion_verbose(
expr.span.shrink_to_hi(),
- "try converting the passed type into a `&str`",
- format!(".map(|x| &*{}x)", "*".repeat(ref_cnt)),
- Applicability::MaybeIncorrect,
+ fluent::hir_typeck_convert_to_str,
+ sugg,
+ Applicability::MachineApplicable,
);
return true;
}
@@ -681,7 +689,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
return true;
}
&hir::FnRetTy::DefaultReturn(span) if expected.is_unit() => {
- if found.is_suggestable(self.tcx, false) {
+ if let Some(found) = found.make_suggestable(self.tcx, false) {
err.subdiagnostic(AddReturnTypeSuggestion::Add { span, found: found.to_string() });
return true;
} else if let ty::Closure(_, substs) = found.kind()
@@ -698,10 +706,38 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
}
hir::FnRetTy::Return(ty) => {
+ let span = ty.span;
+
+ if let hir::TyKind::OpaqueDef(item_id, ..) = ty.kind
+ && let hir::Node::Item(hir::Item {
+ kind: hir::ItemKind::OpaqueTy(op_ty),
+ ..
+ }) = self.tcx.hir().get(item_id.hir_id())
+ && let hir::OpaqueTy {
+ bounds: [bound], ..
+ } = op_ty
+ && let hir::GenericBound::LangItemTrait(
+ hir::LangItem::Future, _, _, generic_args) = bound
+ && let hir::GenericArgs { bindings: [ty_binding], .. } = generic_args
+ && let hir::TypeBinding { kind, .. } = ty_binding
+ && let hir::TypeBindingKind::Equality { term } = kind
+ && let hir::Term::Ty(term_ty) = term {
+ // Check if async function's return type was omitted.
+ // Don't emit suggestions if the found type is `impl Future<...>`.
+ debug!("suggest_missing_return_type: found = {:?}", found);
+ if found.is_suggestable(self.tcx, false) {
+ if term_ty.span.is_empty() {
+ err.subdiagnostic(AddReturnTypeSuggestion::Add { span, found: found.to_string() });
+ return true;
+ } else {
+ err.subdiagnostic(ExpectedReturnTypeLabel::Other { span, expected });
+ }
+ }
+ }
+
// Only point to return type if the expected type is the return type, as if they
// are not, the expectation must have been caused by something else.
debug!("suggest_missing_return_type: return type {:?} node {:?}", ty, ty.kind);
- let span = ty.span;
let ty = self.astconv().ast_ty_to_ty(ty);
debug!("suggest_missing_return_type: return type {:?}", ty);
debug!("suggest_missing_return_type: expected type {:?}", ty);
@@ -980,7 +1016,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let expr_inner_ty = substs.type_at(0);
let expected_inner_ty = expected_substs.type_at(0);
if let ty::Ref(_, ty, hir::Mutability::Not) = expr_inner_ty.kind()
- && self.can_eq(self.param_env, *ty, expected_inner_ty).is_ok()
+ && self.can_eq(self.param_env, *ty, expected_inner_ty)
{
let def_path = self.tcx.def_path_str(adt_def.did());
if self.type_is_copy_modulo_regions(self.param_env, *ty, expr.span) {
@@ -1019,7 +1055,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
if let Some(result_did) = self.tcx.get_diagnostic_item(sym::Result)
&& adt_def.did() == result_did
// Check that the error types are equal
- && self.can_eq(self.param_env, substs.type_at(1), expected_substs.type_at(1)).is_ok()
+ && self.can_eq(self.param_env, substs.type_at(1), expected_substs.type_at(1))
{
return suggest_copied_or_cloned();
} else if let Some(option_did) = self.tcx.get_diagnostic_item(sym::Option)
@@ -1238,6 +1274,49 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
}
+ /// Suggest providing `std::ptr::null()` or `std::ptr::null_mut()` if they
+ /// pass in a literal 0 to an raw pointer.
+ #[instrument(skip(self, err))]
+ pub(crate) fn suggest_null_ptr_for_literal_zero_given_to_ptr_arg(
+ &self,
+ err: &mut Diagnostic,
+ expr: &hir::Expr<'_>,
+ expected_ty: Ty<'tcx>,
+ ) -> bool {
+ // Expected type needs to be a raw pointer.
+ let ty::RawPtr(ty::TypeAndMut { mutbl, .. }) = expected_ty.kind() else {
+ return false;
+ };
+
+ // Provided expression needs to be a literal `0`.
+ let ExprKind::Lit(Spanned {
+ node: rustc_ast::LitKind::Int(0, _),
+ span,
+ }) = expr.kind else {
+ return false;
+ };
+
+ // We need to find a null pointer symbol to suggest
+ let null_sym = match mutbl {
+ hir::Mutability::Not => sym::ptr_null,
+ hir::Mutability::Mut => sym::ptr_null_mut,
+ };
+ let Some(null_did) = self.tcx.get_diagnostic_item(null_sym) else {
+ return false;
+ };
+ let null_path_str = with_no_trimmed_paths!(self.tcx.def_path_str(null_did));
+
+ // We have satisfied all requirements to provide a suggestion. Emit it.
+ err.span_suggestion(
+ span,
+ format!("if you meant to create a null pointer, use `{null_path_str}()`"),
+ null_path_str + "()",
+ Applicability::MachineApplicable,
+ );
+
+ true
+ }
+
pub(crate) fn suggest_associated_const(
&self,
err: &mut Diagnostic,
@@ -1258,16 +1337,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
hir::Path { segments: [segment], .. },
))
| hir::ExprKind::Path(QPath::TypeRelative(ty, segment)) => {
- let self_ty = self.astconv().ast_ty_to_ty(ty);
- if let Ok(pick) = self.probe_for_name(
- Mode::Path,
- Ident::new(capitalized_name, segment.ident.span),
- Some(expected_ty),
- IsSuggestion(true),
- self_ty,
- expr.hir_id,
- ProbeScope::TraitsInScope,
- ) {
+ if let Some(self_ty) = self.typeck_results.borrow().node_type_opt(ty.hir_id)
+ && let Ok(pick) = self.probe_for_name(
+ Mode::Path,
+ Ident::new(capitalized_name, segment.ident.span),
+ Some(expected_ty),
+ IsSuggestion(true),
+ self_ty,
+ expr.hir_id,
+ ProbeScope::TraitsInScope,
+ )
+ {
(pick.item, segment)
} else {
return false;
@@ -1299,7 +1379,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// Same item
return false;
}
- let item_ty = self.tcx.type_of(item.def_id);
+ let item_ty = self.tcx.type_of(item.def_id).subst_identity();
// FIXME(compiler-errors): This check is *so* rudimentary
if item_ty.needs_subst() {
return false;
@@ -1379,6 +1459,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
generics,
diag,
vec![(param.name.as_str(), "Clone", Some(clone_trait_did))].into_iter(),
+ None,
);
} else {
self.suggest_derive(diag, &[(trait_ref.to_predicate(self.tcx), None, None)]);
diff --git a/compiler/rustc_hir_typeck/src/gather_locals.rs b/compiler/rustc_hir_typeck/src/gather_locals.rs
index 15dd3412c..38445f284 100644
--- a/compiler/rustc_hir_typeck/src/gather_locals.rs
+++ b/compiler/rustc_hir_typeck/src/gather_locals.rs
@@ -5,6 +5,7 @@ use rustc_hir::PatKind;
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
use rustc_middle::ty::Ty;
use rustc_middle::ty::UserType;
+use rustc_span::def_id::LocalDefId;
use rustc_span::Span;
use rustc_trait_selection::traits;
@@ -156,7 +157,7 @@ impl<'a, 'tcx> Visitor<'tcx> for GatherLocalsVisitor<'a, 'tcx> {
_: &'tcx hir::FnDecl<'tcx>,
_: hir::BodyId,
_: Span,
- _: hir::HirId,
+ _: LocalDefId,
) {
}
}
diff --git a/compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/cfg_build.rs b/compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/cfg_build.rs
index b3dd3031d..7c0402b1c 100644
--- a/compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/cfg_build.rs
+++ b/compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/cfg_build.rs
@@ -12,7 +12,7 @@ use rustc_index::vec::IndexVec;
use rustc_infer::infer::InferCtxt;
use rustc_middle::{
hir::map::Map,
- ty::{ParamEnv, TyCtxt, TypeVisitable, TypeckResults},
+ ty::{ParamEnv, TyCtxt, TypeVisitableExt, TypeckResults},
};
use std::mem::swap;
@@ -219,7 +219,7 @@ impl<'a, 'tcx> DropRangeVisitor<'a, 'tcx> {
| ExprKind::Struct(..)
| ExprKind::Repeat(..)
| ExprKind::Yield(..)
- | ExprKind::Err => (),
+ | ExprKind::Err(_) => (),
}
}
@@ -483,7 +483,7 @@ impl<'a, 'tcx> Visitor<'tcx> for DropRangeVisitor<'a, 'tcx> {
| ExprKind::Closure { .. }
| ExprKind::ConstBlock(..)
| ExprKind::DropTemps(..)
- | ExprKind::Err
+ | ExprKind::Err(_)
| ExprKind::Field(..)
| ExprKind::Index(..)
| ExprKind::InlineAsm(..)
diff --git a/compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/record_consumed_borrow.rs b/compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/record_consumed_borrow.rs
index ed3d89031..fa3887362 100644
--- a/compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/record_consumed_borrow.rs
+++ b/compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/record_consumed_borrow.rs
@@ -9,7 +9,7 @@ use rustc_hir as hir;
use rustc_middle::ty::{ParamEnv, TyCtxt};
use rustc_middle::{
hir::place::{PlaceBase, Projection, ProjectionKind},
- ty::TypeVisitable,
+ ty::TypeVisitableExt,
};
pub(super) fn find_consumed_and_borrowed<'a, 'tcx>(
diff --git a/compiler/rustc_hir_typeck/src/generator_interior/mod.rs b/compiler/rustc_hir_typeck/src/generator_interior/mod.rs
index 7af526053..2e41c2041 100644
--- a/compiler/rustc_hir_typeck/src/generator_interior/mod.rs
+++ b/compiler/rustc_hir_typeck/src/generator_interior/mod.rs
@@ -16,7 +16,7 @@ use rustc_hir::{Arm, Expr, ExprKind, Guard, HirId, Pat, PatKind};
use rustc_infer::infer::RegionVariableOrigin;
use rustc_middle::middle::region::{self, Scope, ScopeData, YieldData};
use rustc_middle::ty::fold::FnMutDelegate;
-use rustc_middle::ty::{self, BoundVariableKind, RvalueScopes, Ty, TyCtxt, TypeVisitable};
+use rustc_middle::ty::{self, BoundVariableKind, RvalueScopes, Ty, TyCtxt, TypeVisitableExt};
use rustc_span::symbol::sym;
use rustc_span::Span;
use smallvec::{smallvec, SmallVec};
@@ -271,15 +271,13 @@ pub fn resolve_interior<'a, 'tcx>(
},
_ => mk_bound_region(None),
};
- let r = fcx.tcx.mk_region(ty::ReLateBound(current_depth, br));
+ let r = fcx.tcx.mk_re_late_bound(current_depth, br);
r
});
- if captured_tys.insert(ty) {
+ captured_tys.insert(ty).then(|| {
cause.ty = ty;
- Some(cause)
- } else {
- None
- }
+ cause
+ })
})
.collect();
@@ -302,7 +300,7 @@ pub fn resolve_interior<'a, 'tcx>(
let var = ty::BoundVar::from_usize(bound_vars.len());
bound_vars.push(ty::BoundVariableKind::Region(kind));
counter += 1;
- fcx.tcx.mk_region(ty::ReLateBound(ty::INNERMOST, ty::BoundRegion { var, kind }))
+ fcx.tcx.mk_re_late_bound(ty::INNERMOST, ty::BoundRegion { var, kind })
},
types: &mut |b| bug!("unexpected bound ty in binder: {b:?}"),
consts: &mut |b, ty| bug!("unexpected bound ct in binder: {b:?} {ty}"),
@@ -313,8 +311,8 @@ pub fn resolve_interior<'a, 'tcx>(
};
// Extract type components to build the witness type.
- let type_list = fcx.tcx.mk_type_list(type_causes.iter().map(|cause| cause.ty));
- let bound_vars = fcx.tcx.mk_bound_variable_kinds(bound_vars.iter());
+ let type_list = fcx.tcx.mk_type_list_from_iter(type_causes.iter().map(|cause| cause.ty));
+ let bound_vars = fcx.tcx.mk_bound_variable_kinds(&bound_vars);
let witness =
fcx.tcx.mk_generator_witness(ty::Binder::bind_with_vars(type_list, bound_vars.clone()));
@@ -364,7 +362,7 @@ impl<'a, 'tcx> Visitor<'tcx> for InteriorVisitor<'a, 'tcx> {
let ty = tcx.mk_ref(
// Use `ReErased` as `resolve_interior` is going to replace all the
// regions anyway.
- tcx.mk_region(ty::ReErased),
+ tcx.lifetimes.re_erased,
ty::TypeAndMut { ty, mutbl: hir::Mutability::Not },
);
self.interior_visitor.record(
@@ -647,7 +645,8 @@ fn check_must_not_suspend_ty<'tcx>(
hir_id,
SuspendCheckData {
descr_pre,
- plural_len: len.try_eval_usize(fcx.tcx, fcx.param_env).unwrap_or(0) as usize
+ plural_len: len.try_eval_target_usize(fcx.tcx, fcx.param_env).unwrap_or(0)
+ as usize
+ 1,
..data
},
diff --git a/compiler/rustc_hir_typeck/src/inherited.rs b/compiler/rustc_hir_typeck/src/inherited.rs
index b33e7b8d6..26020382d 100644
--- a/compiler/rustc_hir_typeck/src/inherited.rs
+++ b/compiler/rustc_hir_typeck/src/inherited.rs
@@ -1,16 +1,17 @@
use super::callee::DeferredCallResolution;
-use rustc_data_structures::fx::FxHashSet;
+use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_hir as hir;
use rustc_hir::def_id::LocalDefId;
use rustc_hir::HirIdMap;
use rustc_infer::infer;
use rustc_infer::infer::{DefiningAnchor, InferCtxt, InferOk, TyCtxtInferExt};
-use rustc_middle::ty::visit::TypeVisitable;
+use rustc_middle::ty::visit::TypeVisitableExt;
use rustc_middle::ty::{self, Ty, TyCtxt};
use rustc_span::def_id::LocalDefIdMap;
use rustc_span::{self, Span};
-use rustc_trait_selection::traits::{self, TraitEngine, TraitEngineExt as _};
+use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt;
+use rustc_trait_selection::traits::{self, PredicateObligation, TraitEngine, TraitEngineExt as _};
use std::cell::RefCell;
use std::ops::Deref;
@@ -55,7 +56,7 @@ pub struct Inherited<'tcx> {
pub(super) deferred_asm_checks: RefCell<Vec<(&'tcx hir::InlineAsm<'tcx>, hir::HirId)>>,
pub(super) deferred_generator_interiors:
- RefCell<Vec<(hir::BodyId, Ty<'tcx>, hir::GeneratorKind)>>,
+ RefCell<Vec<(LocalDefId, hir::BodyId, Ty<'tcx>, hir::GeneratorKind)>>,
pub(super) body_id: Option<hir::BodyId>,
@@ -63,6 +64,8 @@ pub struct Inherited<'tcx> {
/// 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<FxHashSet<Ty<'tcx>>>,
+
+ pub(super) infer_var_info: RefCell<FxHashMap<ty::TyVid, ty::InferVarInfo>>,
}
impl<'tcx> Deref for Inherited<'tcx> {
@@ -128,6 +131,7 @@ impl<'tcx> Inherited<'tcx> {
deferred_generator_interiors: RefCell::new(Vec::new()),
diverging_type_vars: RefCell::new(Default::default()),
body_id,
+ infer_var_info: RefCell::new(Default::default()),
}
}
@@ -136,6 +140,9 @@ impl<'tcx> Inherited<'tcx> {
if obligation.has_escaping_bound_vars() {
span_bug!(obligation.cause.span, "escaping bound vars in predicate {:?}", obligation);
}
+
+ self.update_infer_var_info(&obligation);
+
self.fulfillment_cx.borrow_mut().register_predicate_obligation(self, obligation);
}
@@ -152,4 +159,43 @@ impl<'tcx> Inherited<'tcx> {
self.register_predicates(infer_ok.obligations);
infer_ok.value
}
+
+ pub fn update_infer_var_info(&self, obligation: &PredicateObligation<'tcx>) {
+ let infer_var_info = &mut self.infer_var_info.borrow_mut();
+
+ // (*) binder skipped
+ if let ty::PredicateKind::Clause(ty::Clause::Trait(tpred)) = obligation.predicate.kind().skip_binder()
+ && let Some(ty) = self.shallow_resolve(tpred.self_ty()).ty_vid().map(|t| self.root_var(t))
+ && self.tcx.lang_items().sized_trait().map_or(false, |st| st != tpred.trait_ref.def_id)
+ {
+ let new_self_ty = self.tcx.types.unit;
+
+ // Then construct a new obligation with Self = () added
+ // to the ParamEnv, and see if it holds.
+ let o = obligation.with(self.tcx,
+ obligation
+ .predicate
+ .kind()
+ .rebind(
+ // (*) binder moved here
+ ty::PredicateKind::Clause(ty::Clause::Trait(tpred.with_self_ty(self.tcx, new_self_ty)))
+ ),
+ );
+ // Don't report overflow errors. Otherwise equivalent to may_hold.
+ if let Ok(result) = self.probe(|_| self.evaluate_obligation(&o)) && result.may_apply() {
+ infer_var_info.entry(ty).or_default().self_in_trait = true;
+ }
+ }
+
+ if let ty::PredicateKind::Clause(ty::Clause::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.term.ty().and_then(|ty| ty.ty_vid()) {
+ debug!("infer_var_info: {:?}.output = true", vid);
+ infer_var_info.entry(vid).or_default().output = true;
+ }
+ }
+ }
}
diff --git a/compiler/rustc_hir_typeck/src/intrinsicck.rs b/compiler/rustc_hir_typeck/src/intrinsicck.rs
index 3c873024c..19d2befc4 100644
--- a/compiler/rustc_hir_typeck/src/intrinsicck.rs
+++ b/compiler/rustc_hir_typeck/src/intrinsicck.rs
@@ -3,7 +3,7 @@ use rustc_errors::struct_span_err;
use rustc_hir as hir;
use rustc_index::vec::Idx;
use rustc_middle::ty::layout::{LayoutError, SizeSkeleton};
-use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitable};
+use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt};
use rustc_target::abi::{Pointer, VariantIdx};
use super::FnCtxt;
@@ -38,6 +38,7 @@ fn unpack_option_like<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> {
impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
pub fn check_transmute(&self, from: Ty<'tcx>, to: Ty<'tcx>, hir_id: HirId) {
let tcx = self.tcx;
+ let dl = &tcx.data_layout;
let span = tcx.hir().span(hir_id);
let normalize = |ty| {
let ty = self.resolve_vars_if_possible(ty);
@@ -69,7 +70,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// Special-case transmuting from `typeof(function)` and
// `Option<typeof(function)>` to present a clearer error.
let from = unpack_option_like(tcx, from);
- if let (&ty::FnDef(..), SizeSkeleton::Known(size_to)) = (from.kind(), sk_to) && size_to == Pointer.size(&tcx) {
+ if let (&ty::FnDef(..), SizeSkeleton::Known(size_to)) = (from.kind(), sk_to) && size_to == Pointer(dl.instruction_address_space).size(&tcx) {
struct_span_err!(tcx.sess, span, E0591, "can't transmute zero-sized type")
.note(&format!("source type: {from}"))
.note(&format!("target type: {to}"))
diff --git a/compiler/rustc_hir_typeck/src/lib.rs b/compiler/rustc_hir_typeck/src/lib.rs
index 7ddf9eaa4..e397dfd45 100644
--- a/compiler/rustc_hir_typeck/src/lib.rs
+++ b/compiler/rustc_hir_typeck/src/lib.rs
@@ -5,6 +5,7 @@
#![feature(min_specialization)]
#![feature(control_flow_enum)]
#![feature(drain_filter)]
+#![feature(option_as_slice)]
#![allow(rustc::potential_query_instability)]
#![recursion_limit = "256"]
@@ -53,7 +54,10 @@ use crate::check::check_fn;
use crate::coercion::DynamicCoerceMany;
use crate::gather_locals::GatherLocalsVisitor;
use rustc_data_structures::unord::UnordSet;
-use rustc_errors::{struct_span_err, DiagnosticId, ErrorGuaranteed, MultiSpan};
+use rustc_errors::{
+ struct_span_err, DiagnosticId, DiagnosticMessage, ErrorGuaranteed, MultiSpan,
+ SubdiagnosticMessage,
+};
use rustc_hir as hir;
use rustc_hir::def::{DefKind, Res};
use rustc_hir::intravisit::Visitor;
@@ -61,13 +65,16 @@ use rustc_hir::{HirIdMap, Node};
use rustc_hir_analysis::astconv::AstConv;
use rustc_hir_analysis::check::check_abi;
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
+use rustc_macros::fluent_messages;
use rustc_middle::traits;
use rustc_middle::ty::query::Providers;
use rustc_middle::ty::{self, Ty, TyCtxt};
use rustc_session::config;
use rustc_session::Session;
use rustc_span::def_id::{DefId, LocalDefId};
-use rustc_span::Span;
+use rustc_span::{sym, Span};
+
+fluent_messages! { "../locales/en-US.ftl" }
#[macro_export]
macro_rules! type_error_struct {
@@ -154,7 +161,7 @@ fn typeck_const_arg<'tcx>(
tcx: TyCtxt<'tcx>,
(did, param_did): (LocalDefId, DefId),
) -> &ty::TypeckResults<'tcx> {
- let fallback = move || tcx.type_of(param_did);
+ let fallback = move || tcx.type_of(param_did).subst_identity();
typeck_with_fallback(tcx, did, fallback)
}
@@ -162,7 +169,7 @@ fn typeck<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> &ty::TypeckResults<'tc
if let Some(param_did) = tcx.opt_const_param_of(def_id) {
tcx.typeck_const_arg((def_id, param_did))
} else {
- let fallback = move || tcx.type_of(def_id.to_def_id());
+ let fallback = move || tcx.type_of(def_id.to_def_id()).subst_identity();
typeck_with_fallback(tcx, def_id, fallback)
}
}
@@ -201,13 +208,18 @@ fn typeck_with_fallback<'tcx>(
let typeck_results = Inherited::build(tcx, def_id).enter(|inh| {
let param_env = tcx.param_env(def_id);
- let mut fcx = FnCtxt::new(&inh, param_env, body.value.hir_id);
+ let param_env = if tcx.has_attr(def_id.to_def_id(), sym::rustc_do_not_const_check) {
+ param_env.without_const()
+ } else {
+ param_env
+ };
+ let mut fcx = FnCtxt::new(&inh, param_env, def_id);
if let Some(hir::FnSig { header, decl, .. }) = fn_sig {
let fn_sig = if rustc_hir_analysis::collect::get_infer_ret_ty(&decl.output).is_some() {
fcx.astconv().ty_of_fn(id, header.unsafety, header.abi, decl, None, None)
} else {
- tcx.fn_sig(def_id)
+ tcx.fn_sig(def_id).subst_identity()
};
check_abi(tcx, id, span, fn_sig.abi());
@@ -294,14 +306,24 @@ fn typeck_with_fallback<'tcx>(
// Before the generator analysis, temporary scopes shall be marked to provide more
// precise information on types to be captured.
fcx.resolve_rvalue_scopes(def_id.to_def_id());
- fcx.resolve_generator_interiors(def_id.to_def_id());
for (ty, span, code) in fcx.deferred_sized_obligations.borrow_mut().drain(..) {
let ty = fcx.normalize(span, ty);
fcx.require_type_is_sized(ty, span, code);
}
- fcx.select_all_obligations_or_error();
+ fcx.select_obligations_where_possible(|_| {});
+
+ debug!(pending_obligations = ?fcx.fulfillment_cx.borrow().pending_obligations());
+
+ // This must be the last thing before `report_ambiguity_errors`.
+ fcx.resolve_generator_interiors(def_id.to_def_id());
+
+ debug!(pending_obligations = ?fcx.fulfillment_cx.borrow().pending_obligations());
+
+ if let None = fcx.infcx.tainted_by_errors() {
+ fcx.report_ambiguity_errors();
+ }
if let None = fcx.infcx.tainted_by_errors() {
fcx.check_transmutes();
diff --git a/compiler/rustc_hir_typeck/src/mem_categorization.rs b/compiler/rustc_hir_typeck/src/mem_categorization.rs
index 48c75cde9..4d3969d28 100644
--- a/compiler/rustc_hir_typeck/src/mem_categorization.rs
+++ b/compiler/rustc_hir_typeck/src/mem_categorization.rs
@@ -51,8 +51,7 @@
use rustc_middle::hir::place::*;
use rustc_middle::ty::adjustment;
use rustc_middle::ty::fold::TypeFoldable;
-use rustc_middle::ty::visit::TypeVisitable;
-use rustc_middle::ty::{self, Ty, TyCtxt};
+use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt};
use rustc_data_structures::fx::FxIndexMap;
use rustc_hir as hir;
@@ -127,7 +126,7 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> {
fn resolve_vars_if_possible<T>(&self, value: T) -> T
where
- T: TypeFoldable<'tcx>,
+ T: TypeFoldable<TyCtxt<'tcx>>,
{
self.infcx.resolve_vars_if_possible(value)
}
@@ -155,8 +154,7 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> {
None if self.is_tainted_by_errors() => Err(()),
None => {
bug!(
- "no type for node {}: {} in mem_categorization",
- id,
+ "no type for node {} in mem_categorization",
self.tcx().hir().node_to_string(id)
);
}
@@ -385,7 +383,7 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> {
| hir::ExprKind::Repeat(..)
| hir::ExprKind::InlineAsm(..)
| hir::ExprKind::Box(..)
- | hir::ExprKind::Err => Ok(self.cat_rvalue(expr.hir_id, expr.span, expr_ty)),
+ | hir::ExprKind::Err(_) => Ok(self.cat_rvalue(expr.hir_id, expr.span, expr_ty)),
}
}
@@ -603,7 +601,6 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> {
}
}
- // FIXME(#19596) This is a workaround, but there should be a better way to do this
fn cat_pattern_<F>(
&self,
mut place_with_id: PlaceWithHirId<'tcx>,
@@ -639,7 +636,7 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> {
// `&&Some(x,)` `place_foo`
// `&Some(x,)` `deref { place_foo}`
// `Some(x,)` `deref { deref { place_foo }}`
- // (x,)` `field0 { deref { deref { place_foo }}}` <- resulting place
+ // `(x,)` `field0 { deref { deref { place_foo }}}` <- resulting place
//
// The above example has no adjustments. If the code were instead the (after adjustments,
// equivalent) version
diff --git a/compiler/rustc_hir_typeck/src/method/confirm.rs b/compiler/rustc_hir_typeck/src/method/confirm.rs
index 372ea30eb..169f128e0 100644
--- a/compiler/rustc_hir_typeck/src/method/confirm.rs
+++ b/compiler/rustc_hir_typeck/src/method/confirm.rs
@@ -14,7 +14,7 @@ use rustc_middle::ty::adjustment::{Adjust, Adjustment, PointerCast};
use rustc_middle::ty::adjustment::{AllowTwoPhase, AutoBorrow, AutoBorrowMutability};
use rustc_middle::ty::fold::TypeFoldable;
use rustc_middle::ty::subst::{self, SubstsRef};
-use rustc_middle::ty::{self, GenericParamDefKind, Ty};
+use rustc_middle::ty::{self, GenericParamDefKind, Ty, TyCtxt};
use rustc_middle::ty::{InternalSubsts, UserSubsts, UserType};
use rustc_span::{Span, DUMMY_SP};
use rustc_trait_selection::traits;
@@ -262,7 +262,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
let original_poly_trait_ref = principal.with_self_ty(this.tcx, object_ty);
let upcast_poly_trait_ref = this.upcast(original_poly_trait_ref, trait_def_id);
let upcast_trait_ref =
- this.replace_bound_vars_with_fresh_vars(upcast_poly_trait_ref);
+ this.instantiate_binder_with_fresh_vars(upcast_poly_trait_ref);
debug!(
"original_poly_trait_ref={:?} upcast_trait_ref={:?} target_trait={:?}",
original_poly_trait_ref, upcast_trait_ref, trait_def_id
@@ -285,7 +285,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
probe::WhereClausePick(poly_trait_ref) => {
// Where clauses can have bound regions in them. We need to instantiate
// those to convert from a poly-trait-ref to a trait-ref.
- self.replace_bound_vars_with_fresh_vars(poly_trait_ref).substs
+ self.instantiate_binder_with_fresh_vars(poly_trait_ref).substs
}
}
}
@@ -384,7 +384,15 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
}
(GenericParamDefKind::Const { .. }, GenericArg::Infer(inf)) => {
let tcx = self.cfcx.tcx();
- self.cfcx.ct_infer(tcx.type_of(param.def_id), Some(param), inf.span).into()
+ self.cfcx
+ .ct_infer(
+ tcx.type_of(param.def_id)
+ .no_bound_vars()
+ .expect("const parameter types cannot be generic"),
+ Some(param),
+ inf.span,
+ )
+ .into()
}
_ => unreachable!(),
}
@@ -503,12 +511,10 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
debug!("method_predicates after subst = {:?}", method_predicates);
- let sig = self.tcx.bound_fn_sig(def_id);
-
- let sig = sig.subst(self.tcx, all_substs);
+ let sig = self.tcx.fn_sig(def_id).subst(self.tcx, all_substs);
debug!("type scheme substituted, sig={:?}", sig);
- let sig = self.replace_bound_vars_with_fresh_vars(sig);
+ let sig = self.instantiate_binder_with_fresh_vars(sig);
debug!("late-bound lifetimes from method instantiated, sig={:?}", sig);
(sig, method_predicates)
@@ -627,10 +633,10 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
upcast_trait_refs.into_iter().next().unwrap()
}
- fn replace_bound_vars_with_fresh_vars<T>(&self, value: ty::Binder<'tcx, T>) -> T
+ fn instantiate_binder_with_fresh_vars<T>(&self, value: ty::Binder<'tcx, T>) -> T
where
- T: TypeFoldable<'tcx> + Copy,
+ T: TypeFoldable<TyCtxt<'tcx>> + Copy,
{
- self.fcx.replace_bound_vars_with_fresh_vars(self.span, infer::FnCall, value)
+ self.fcx.instantiate_binder_with_fresh_vars(self.span, infer::FnCall, value)
}
}
diff --git a/compiler/rustc_hir_typeck/src/method/mod.rs b/compiler/rustc_hir_typeck/src/method/mod.rs
index b810a967a..0456dd56c 100644
--- a/compiler/rustc_hir_typeck/src/method/mod.rs
+++ b/compiler/rustc_hir_typeck/src/method/mod.rs
@@ -20,7 +20,7 @@ use rustc_hir::def_id::DefId;
use rustc_infer::infer::{self, InferOk};
use rustc_middle::traits::ObligationCause;
use rustc_middle::ty::subst::{InternalSubsts, SubstsRef};
-use rustc_middle::ty::{self, GenericParamDefKind, Ty, TypeVisitable};
+use rustc_middle::ty::{self, GenericParamDefKind, Ty, TypeVisitableExt};
use rustc_span::symbol::Ident;
use rustc_span::Span;
use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt;
@@ -76,7 +76,7 @@ pub struct NoMatchData<'tcx> {
pub unsatisfied_predicates:
Vec<(ty::Predicate<'tcx>, Option<ty::Predicate<'tcx>>, Option<ObligationCause<'tcx>>)>,
pub out_of_scope_traits: Vec<DefId>,
- pub lev_candidate: Option<ty::AssocItem>,
+ pub similar_candidate: Option<ty::AssocItem>,
pub mode: probe::Mode,
}
@@ -145,7 +145,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
)
.map(|pick| {
let sig = self.tcx.fn_sig(pick.item.def_id);
- sig.inputs().skip_binder().len().saturating_sub(1)
+ sig.skip_binder().inputs().skip_binder().len().saturating_sub(1)
})
.unwrap_or(0);
@@ -380,6 +380,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
);
return None;
};
+
+ if method_item.kind != ty::AssocKind::Fn {
+ self.tcx.sess.delay_span_bug(tcx.def_span(method_item.def_id), "not a method");
+ return None;
+ }
+
let def_id = method_item.def_id;
let generics = tcx.generics_of(def_id);
@@ -399,10 +405,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// N.B., instantiate late-bound regions before normalizing the
// function signature so that normalization does not need to deal
// with bound regions.
- let fn_sig = tcx.bound_fn_sig(def_id);
- let fn_sig = fn_sig.subst(self.tcx, substs);
+ let fn_sig = tcx.fn_sig(def_id).subst(self.tcx, substs);
let fn_sig =
- self.replace_bound_vars_with_fresh_vars(obligation.cause.span, infer::FnCall, fn_sig);
+ self.instantiate_binder_with_fresh_vars(obligation.cause.span, infer::FnCall, fn_sig);
let InferOk { value, obligations: o } =
self.at(&obligation.cause, self.param_env).normalize(fn_sig);
diff --git a/compiler/rustc_hir_typeck/src/method/probe.rs b/compiler/rustc_hir_typeck/src/method/probe.rs
index a24814313..3bef5cfcd 100644
--- a/compiler/rustc_hir_typeck/src/method/probe.rs
+++ b/compiler/rustc_hir_typeck/src/method/probe.rs
@@ -9,24 +9,23 @@ use rustc_data_structures::fx::FxHashSet;
use rustc_errors::Applicability;
use rustc_hir as hir;
use rustc_hir::def::DefKind;
+use rustc_hir_analysis::astconv::InferCtxtExt as _;
use rustc_hir_analysis::autoderef::{self, Autoderef};
use rustc_infer::infer::canonical::OriginalQueryValues;
use rustc_infer::infer::canonical::{Canonical, QueryResponse};
-use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
use rustc_infer::infer::{self, InferOk, TyCtxtInferExt};
-use rustc_middle::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind};
use rustc_middle::middle::stability;
use rustc_middle::ty::fast_reject::{simplify_type, TreatParams};
use rustc_middle::ty::AssocItem;
use rustc_middle::ty::GenericParamDefKind;
use rustc_middle::ty::ToPredicate;
-use rustc_middle::ty::{self, ParamEnvAnd, Ty, TyCtxt, TypeFoldable, TypeVisitable};
+use rustc_middle::ty::{self, ParamEnvAnd, Ty, TyCtxt, TypeFoldable, TypeVisitableExt};
use rustc_middle::ty::{InternalSubsts, SubstsRef};
use rustc_session::lint;
use rustc_span::def_id::DefId;
use rustc_span::def_id::LocalDefId;
-use rustc_span::lev_distance::{
- find_best_match_for_name_with_substrings, lev_distance_with_substrings,
+use rustc_span::edit_distance::{
+ edit_distance_with_substrings, find_best_match_for_name_with_substrings,
};
use rustc_span::symbol::sym;
use rustc_span::{symbol::Ident, Span, Symbol, DUMMY_SP};
@@ -70,7 +69,7 @@ struct ProbeContext<'a, 'tcx> {
impl_dups: FxHashSet<DefId>,
/// When probing for names, include names that are close to the
- /// requested name (by Levenshtein distance)
+ /// requested name (by edit distance)
allow_similar_names: bool,
/// Some(candidate) if there is a private candidate
@@ -461,7 +460,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
static_candidates: Vec::new(),
unsatisfied_predicates: Vec::new(),
out_of_scope_traits: Vec::new(),
- lev_candidate: None,
+ similar_candidate: None,
mode,
}));
}
@@ -508,16 +507,16 @@ fn method_autoderef_steps<'tcx>(
let (ref infcx, goal, inference_vars) = tcx.infer_ctxt().build_with_canonical(DUMMY_SP, &goal);
let ParamEnvAnd { param_env, value: self_ty } = goal;
- let mut autoderef = Autoderef::new(infcx, param_env, hir::CRATE_HIR_ID, DUMMY_SP, self_ty)
- .include_raw_pointers()
- .silence_errors();
+ let mut autoderef =
+ Autoderef::new(infcx, param_env, hir::def_id::CRATE_DEF_ID, DUMMY_SP, self_ty)
+ .include_raw_pointers()
+ .silence_errors();
let mut reached_raw_pointer = false;
let mut steps: Vec<_> = autoderef
.by_ref()
.map(|(ty, d)| {
let step = CandidateStep {
- self_ty: infcx
- .make_query_response_ignoring_pending_obligations(inference_vars.clone(), ty),
+ self_ty: infcx.make_query_response_ignoring_pending_obligations(inference_vars, ty),
autoderefs: d,
from_unsafe_deref: reached_raw_pointer,
unsize: false,
@@ -610,10 +609,9 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
fn push_candidate(&mut self, candidate: Candidate<'tcx>, is_inherent: bool) {
let is_accessible = if let Some(name) = self.method_name {
let item = candidate.item;
- let def_scope = self
- .tcx
- .adjust_ident_and_get_scope(name, item.container_id(self.tcx), self.body_id)
- .1;
+ let hir_id = self.tcx.hir().local_def_id_to_hir_id(self.body_id);
+ let def_scope =
+ self.tcx.adjust_ident_and_get_scope(name, item.container_id(self.tcx), hir_id).1;
item.visibility(self.tcx).is_accessible_from(def_scope, self.tcx)
} else {
true
@@ -736,7 +734,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
debug!("impl_ty: {:?}", impl_ty);
// Determine the receiver type that the method itself expects.
- let (xform_self_ty, xform_ret_ty) = 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
@@ -797,7 +795,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
let new_trait_ref = this.erase_late_bound_regions(new_trait_ref);
let (xform_self_ty, xform_ret_ty) =
- this.xform_self_ty(&item, new_trait_ref.self_ty(), new_trait_ref.substs);
+ this.xform_self_ty(item, new_trait_ref.self_ty(), new_trait_ref.substs);
this.push_candidate(
Candidate {
xform_self_ty,
@@ -827,6 +825,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
}
}
ty::PredicateKind::Subtype(..)
+ | ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(..))
| ty::PredicateKind::Coerce(..)
| ty::PredicateKind::Clause(ty::Clause::Projection(..))
| ty::PredicateKind::Clause(ty::Clause::RegionOutlives(..))
@@ -837,6 +836,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
| ty::PredicateKind::ConstEvaluatable(..)
| ty::PredicateKind::ConstEquate(..)
| ty::PredicateKind::Ambiguous
+ | ty::PredicateKind::AliasEq(..)
| ty::PredicateKind::TypeWellFormedFromEnv(..) => None,
}
});
@@ -845,7 +845,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
let trait_ref = this.erase_late_bound_regions(poly_trait_ref);
let (xform_self_ty, xform_ret_ty) =
- this.xform_self_ty(&item, trait_ref.self_ty(), trait_ref.substs);
+ this.xform_self_ty(item, trait_ref.self_ty(), trait_ref.substs);
// Because this trait derives from a where-clause, it
// should not contain any inference variables or other
@@ -916,31 +916,27 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
fn matches_return_type(
&self,
- method: &ty::AssocItem,
+ method: ty::AssocItem,
self_ty: Option<Ty<'tcx>>,
expected: Ty<'tcx>,
) -> bool {
match method.kind {
- ty::AssocKind::Fn => {
- let fty = self.tcx.bound_fn_sig(method.def_id);
- self.probe(|_| {
- let substs = self.fresh_substs_for_item(self.span, method.def_id);
- let fty = fty.subst(self.tcx, substs);
- let fty =
- self.replace_bound_vars_with_fresh_vars(self.span, infer::FnCall, fty);
-
- if let Some(self_ty) = self_ty {
- if self
- .at(&ObligationCause::dummy(), self.param_env)
- .sup(fty.inputs()[0], self_ty)
- .is_err()
- {
- return false;
- }
+ ty::AssocKind::Fn => self.probe(|_| {
+ let substs = self.fresh_substs_for_item(self.span, method.def_id);
+ let fty = self.tcx.fn_sig(method.def_id).subst(self.tcx, substs);
+ let fty = self.instantiate_binder_with_fresh_vars(self.span, infer::FnCall, fty);
+
+ if let Some(self_ty) = self_ty {
+ if self
+ .at(&ObligationCause::dummy(), self.param_env)
+ .sup(fty.inputs()[0], self_ty)
+ .is_err()
+ {
+ return false;
}
- self.can_sub(self.param_env, fty.output(), expected).is_ok()
- })
- }
+ }
+ self.can_sub(self.param_env, fty.output(), expected)
+ }),
_ => false,
}
}
@@ -955,24 +951,35 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
let trait_ref = self.tcx.mk_trait_ref(trait_def_id, trait_substs);
if self.tcx.is_trait_alias(trait_def_id) {
- // 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);
-
- let (xform_self_ty, xform_ret_ty) =
- this.xform_self_ty(&item, new_trait_ref.self_ty(), new_trait_ref.substs);
- this.push_candidate(
- Candidate {
- xform_self_ty,
- xform_ret_ty,
- item,
- import_ids: import_ids.clone(),
- kind: TraitCandidate(new_trait_ref),
- },
- false,
- );
- });
+ // For trait aliases, recursively assume all explicitly named traits are relevant
+ for expansion in traits::expand_trait_aliases(
+ self.tcx,
+ iter::once((ty::Binder::dummy(trait_ref), self.span)),
+ ) {
+ let bound_trait_ref = expansion.trait_ref();
+ for item in self.impl_or_trait_item(bound_trait_ref.def_id()) {
+ if !self.has_applicable_self(&item) {
+ self.record_static_candidate(CandidateSource::Trait(
+ bound_trait_ref.def_id(),
+ ));
+ } else {
+ let new_trait_ref = self.erase_late_bound_regions(bound_trait_ref);
+
+ let (xform_self_ty, xform_ret_ty) =
+ self.xform_self_ty(item, new_trait_ref.self_ty(), new_trait_ref.substs);
+ self.push_candidate(
+ Candidate {
+ xform_self_ty,
+ xform_ret_ty,
+ item,
+ import_ids: import_ids.clone(),
+ kind: TraitCandidate(new_trait_ref),
+ },
+ false,
+ );
+ }
+ }
+ }
} else {
debug_assert!(self.tcx.is_trait(trait_def_id));
if self.tcx.trait_is_auto(trait_def_id) {
@@ -987,7 +994,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
}
let (xform_self_ty, xform_ret_ty) =
- self.xform_self_ty(&item, trait_ref.self_ty(), trait_substs);
+ self.xform_self_ty(item, trait_ref.self_ty(), trait_substs);
self.push_candidate(
Candidate {
xform_self_ty,
@@ -1014,7 +1021,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
.filter(|candidate| candidate_filter(&candidate.item))
.filter(|candidate| {
if let Some(return_ty) = self.return_type {
- self.matches_return_type(&candidate.item, None, return_ty)
+ self.matches_return_type(candidate.item, None, return_ty)
} else {
true
}
@@ -1076,29 +1083,20 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
if let Some((kind, def_id)) = private_candidate {
return Err(MethodError::PrivateMatch(kind, def_id, out_of_scope_traits));
}
- let lev_candidate = self.probe_for_lev_candidate()?;
+ let similar_candidate = self.probe_for_similar_candidate()?;
Err(MethodError::NoMatch(NoMatchData {
static_candidates,
unsatisfied_predicates,
out_of_scope_traits,
- lev_candidate,
+ similar_candidate,
mode: self.mode,
}))
}
fn pick_core(&self) -> Option<PickResult<'tcx>> {
- let pick = self.pick_all_method(Some(&mut vec![]));
-
- // In this case unstable picking is done by `pick_method`.
- if !self.tcx.sess.opts.unstable_opts.pick_stable_methods_before_any_unstable {
- return pick;
- }
-
- if pick.is_none() {
- return self.pick_all_method(None);
- }
- pick
+ // Pick stable methods only first, and consider unstable candidates if not found.
+ self.pick_all_method(Some(&mut vec![])).or_else(|| self.pick_all_method(None))
}
fn pick_all_method(
@@ -1237,54 +1235,11 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
})
}
- fn pick_method_with_unstable(&self, self_ty: Ty<'tcx>) -> Option<PickResult<'tcx>> {
- debug!("pick_method_with_unstable(self_ty={})", self.ty_to_string(self_ty));
-
- let mut possibly_unsatisfied_predicates = Vec::new();
-
- for (kind, candidates) in
- &[("inherent", &self.inherent_candidates), ("extension", &self.extension_candidates)]
- {
- debug!("searching {} candidates", kind);
- let res = self.consider_candidates(
- self_ty,
- candidates,
- &mut possibly_unsatisfied_predicates,
- Some(&mut vec![]),
- );
- if res.is_some() {
- return res;
- }
- }
-
- for (kind, candidates) in
- &[("inherent", &self.inherent_candidates), ("extension", &self.extension_candidates)]
- {
- debug!("searching unstable {kind} candidates");
- let res = self.consider_candidates(
- self_ty,
- candidates,
- &mut possibly_unsatisfied_predicates,
- None,
- );
- if res.is_some() {
- return res;
- }
- }
-
- self.unsatisfied_predicates.borrow_mut().extend(possibly_unsatisfied_predicates);
- None
- }
-
fn pick_method(
&self,
self_ty: Ty<'tcx>,
mut unstable_candidates: Option<&mut Vec<(Candidate<'tcx>, Symbol)>>,
) -> Option<PickResult<'tcx>> {
- if !self.tcx.sess.opts.unstable_opts.pick_stable_methods_before_any_unstable {
- return self.pick_method_with_unstable(self_ty);
- }
-
debug!("pick_method(self_ty={})", self.ty_to_string(self_ty));
let mut possibly_unsatisfied_predicates = Vec::new();
@@ -1358,13 +1313,12 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
return Some(Err(MethodError::Ambiguity(sources)));
}
- applicable_candidates.pop().map(|(probe, status)| {
- if status == ProbeResult::Match {
+ applicable_candidates.pop().map(|(probe, status)| match status {
+ ProbeResult::Match => {
Ok(probe
.to_unadjusted_pick(self_ty, unstable_candidates.cloned().unwrap_or_default()))
- } else {
- Err(MethodError::BadReturnType)
}
+ ProbeResult::NoMatch | ProbeResult::BadReturnType => Err(MethodError::BadReturnType),
})
}
}
@@ -1412,8 +1366,8 @@ impl<'tcx> Pick<'tcx> {
span,
format!(
"{} {} with this name may be added to the standard library in the future",
- def_kind.article(),
- def_kind.descr(self.item.def_id),
+ tcx.def_kind_descr_article(def_kind, self.item.def_id),
+ tcx.def_kind_descr(def_kind, self.item.def_id),
),
|lint| {
match (self.item.kind, self.item.container) {
@@ -1482,7 +1436,6 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
TraitCandidate(trait_ref) => self.probe(|_| {
let _ = self
.at(&ObligationCause::dummy(), self.param_env)
- .define_opaque_types(false)
.sup(candidate.xform_self_ty, self_ty);
match self.select_trait_candidate(trait_ref) {
Ok(Some(traits::ImplSource::UserDefined(ref impl_data))) => {
@@ -1512,7 +1465,6 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
// First check that the self type can be related.
let sub_obligations = match self
.at(&ObligationCause::dummy(), self.param_env)
- .define_opaque_types(false)
.sup(probe.xform_self_ty, self_ty)
{
Ok(InferOk { obligations, value: () }) => obligations,
@@ -1567,7 +1519,8 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
traits::ImplDerivedObligation(Box::new(
traits::ImplDerivedObligationCause {
derived,
- impl_def_id,
+ impl_or_alias_def_id: impl_def_id,
+ impl_def_predicate_index: None,
span,
},
))
@@ -1728,7 +1681,6 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
if let ProbeResult::Match = result
&& self
.at(&ObligationCause::dummy(), self.param_env)
- .define_opaque_types(false)
.sup(return_ty, xform_ret_ty)
.is_err()
{
@@ -1786,8 +1738,8 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
/// Similarly to `probe_for_return_type`, this method attempts to find the best matching
/// candidate method where the method name may have been misspelled. Similarly to other
- /// Levenshtein based suggestions, we provide at most one such suggestion.
- fn probe_for_lev_candidate(&mut self) -> Result<Option<ty::AssocItem>, MethodError<'tcx>> {
+ /// edit distance based suggestions, we provide at most one such suggestion.
+ fn probe_for_similar_candidate(&mut self) -> Result<Option<ty::AssocItem>, MethodError<'tcx>> {
debug!("probing for method names similar to {:?}", self.method_name);
let steps = self.steps.clone();
@@ -1831,6 +1783,12 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
None,
)
}
+ .or_else(|| {
+ applicable_close_candidates
+ .iter()
+ .find(|cand| self.matches_by_doc_alias(cand.def_id))
+ .map(|cand| cand.name)
+ })
.unwrap();
Ok(applicable_close_candidates.into_iter().find(|method| method.name == best_name))
}
@@ -1867,7 +1825,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
#[instrument(level = "debug", skip(self))]
fn xform_self_ty(
&self,
- item: &ty::AssocItem,
+ item: ty::AssocItem,
impl_ty: Ty<'tcx>,
substs: SubstsRef<'tcx>,
) -> (Ty<'tcx>, Option<Ty<'tcx>>) {
@@ -1881,7 +1839,7 @@ 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.bound_fn_sig(method);
+ let fn_sig = self.tcx.fn_sig(method);
debug!(?fn_sig);
assert!(!substs.has_escaping_bound_vars());
@@ -1924,27 +1882,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
&self,
impl_def_id: DefId,
) -> (ty::EarlyBinder<Ty<'tcx>>, SubstsRef<'tcx>) {
- (self.tcx.bound_type_of(impl_def_id), self.fresh_item_substs(impl_def_id))
- }
-
- fn fresh_item_substs(&self, def_id: DefId) -> SubstsRef<'tcx> {
- InternalSubsts::for_item(self.tcx, def_id, |param, _| match param.kind {
- GenericParamDefKind::Lifetime => self.tcx.lifetimes.re_erased.into(),
- GenericParamDefKind::Type { .. } => self
- .next_ty_var(TypeVariableOrigin {
- kind: TypeVariableOriginKind::SubstitutionPlaceholder,
- span: self.tcx.def_span(def_id),
- })
- .into(),
- GenericParamDefKind::Const { .. } => {
- let span = self.tcx.def_span(def_id);
- let origin = ConstVariableOrigin {
- kind: ConstVariableOriginKind::SubstitutionPlaceholder,
- span,
- };
- self.next_const_var(self.tcx.type_of(param.def_id), origin).into()
- }
- })
+ (self.tcx.type_of(impl_def_id), self.fresh_item_substs(impl_def_id))
}
/// Replaces late-bound-regions bound by `value` with `'static` using
@@ -1967,7 +1905,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
/// so forth.
fn erase_late_bound_regions<T>(&self, value: ty::Binder<'tcx, T>) -> T
where
- T: TypeFoldable<'tcx>,
+ T: TypeFoldable<TyCtxt<'tcx>>,
{
self.tcx.erase_late_bound_regions(value)
}
@@ -1981,6 +1919,38 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
}
}
+ /// Determine if the associated item withe the given DefId matches
+ /// the desired name via a doc alias.
+ fn matches_by_doc_alias(&self, def_id: DefId) -> bool {
+ let Some(name) = self.method_name else { return false; };
+ let Some(local_def_id) = def_id.as_local() else { return false; };
+ let hir_id = self.fcx.tcx.hir().local_def_id_to_hir_id(local_def_id);
+ let attrs = self.fcx.tcx.hir().attrs(hir_id);
+ for attr in attrs {
+ let sym::doc = attr.name_or_empty() else { continue; };
+ let Some(values) = attr.meta_item_list() else { continue; };
+ for v in values {
+ if v.name_or_empty() != sym::alias {
+ continue;
+ }
+ if let Some(nested) = v.meta_item_list() {
+ // #[doc(alias("foo", "bar"))]
+ for n in nested {
+ if let Some(lit) = n.lit() && name.as_str() == lit.symbol.as_str() {
+ return true;
+ }
+ }
+ } else if let Some(meta) = v.meta_item()
+ && let Some(lit) = meta.name_value_literal()
+ && name.as_str() == lit.symbol.as_str() {
+ // #[doc(alias = "foo")]
+ return true;
+ }
+ }
+ }
+ false
+ }
+
/// Finds the method with the appropriate name (or return type, as the case may be). If
/// `allow_similar_names` is set, find methods with close-matching names.
// The length of the returned iterator is nearly always 0 or 1 and this
@@ -1996,8 +1966,14 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
if !self.is_relevant_kind_for_mode(x.kind) {
return false;
}
- match lev_distance_with_substrings(name.as_str(), x.name.as_str(), max_dist)
- {
+ if self.matches_by_doc_alias(x.def_id) {
+ return true;
+ }
+ match edit_distance_with_substrings(
+ name.as_str(),
+ x.name.as_str(),
+ max_dist,
+ ) {
Some(d) => d > 0,
None => false,
}
diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs
index 2e1fc4c38..60d56263d 100644
--- a/compiler/rustc_hir_typeck/src/method/suggest.rs
+++ b/compiler/rustc_hir_typeck/src/method/suggest.rs
@@ -27,11 +27,11 @@ use rustc_middle::traits::util::supertraits;
use rustc_middle::ty::fast_reject::DeepRejectCtxt;
use rustc_middle::ty::fast_reject::{simplify_type, TreatParams};
use rustc_middle::ty::print::{with_crate_prefix, with_forced_trimmed_paths};
-use rustc_middle::ty::{self, DefIdTree, GenericArgKind, Ty, TyCtxt, TypeVisitable};
+use rustc_middle::ty::{self, DefIdTree, GenericArgKind, Ty, TyCtxt, TypeVisitableExt};
use rustc_middle::ty::{IsSuggestable, ToPolyTraitRef};
use rustc_span::symbol::{kw, sym, Ident};
use rustc_span::Symbol;
-use rustc_span::{lev_distance, source_map, ExpnKind, FileName, MacroKind, Span};
+use rustc_span::{edit_distance, source_map, ExpnKind, FileName, MacroKind, Span};
use rustc_trait_selection::traits::error_reporting::on_unimplemented::OnUnimplementedNote;
use rustc_trait_selection::traits::error_reporting::on_unimplemented::TypeErrCtxtExt as _;
use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _;
@@ -160,7 +160,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
MethodError::PrivateMatch(kind, def_id, out_of_scope_traits) => {
- let kind = kind.descr(def_id);
+ let kind = self.tcx.def_kind_descr(kind, def_id);
let mut err = struct_span_err!(
self.tcx.sess,
item_name.span,
@@ -259,10 +259,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let mode = no_match_data.mode;
let tcx = self.tcx;
let rcvr_ty = self.resolve_vars_if_possible(rcvr_ty);
- let ty_str = with_forced_trimmed_paths!(self.ty_to_string(rcvr_ty));
+ let (ty_str, ty_file) = tcx.short_ty_string(rcvr_ty);
+ let short_ty_str = with_forced_trimmed_paths!(rcvr_ty.to_string());
let is_method = mode == Mode::MethodCall;
let unsatisfied_predicates = &no_match_data.unsatisfied_predicates;
- let lev_candidate = no_match_data.lev_candidate;
+ let similar_candidate = no_match_data.similar_candidate;
let item_kind = if is_method {
"method"
} else if rcvr_ty.is_enum() {
@@ -276,11 +277,24 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
};
- if self.suggest_wrapping_range_with_parens(tcx, rcvr_ty, source, span, item_name, &ty_str)
- || self.suggest_constraining_numerical_ty(
- tcx, rcvr_ty, source, span, item_kind, item_name, &ty_str,
- )
- {
+ // We could pass the file for long types into these two, but it isn't strictly necessary
+ // given how targetted they are.
+ if self.suggest_wrapping_range_with_parens(
+ tcx,
+ rcvr_ty,
+ source,
+ span,
+ item_name,
+ &short_ty_str,
+ ) || self.suggest_constraining_numerical_ty(
+ tcx,
+ rcvr_ty,
+ source,
+ span,
+ item_kind,
+ item_name,
+ &short_ty_str,
+ ) {
return None;
}
span = item_name.span;
@@ -319,6 +333,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
rcvr_ty.prefix_string(self.tcx),
ty_str_reported,
);
+ if tcx.sess.source_map().is_multiline(sugg_span) {
+ err.span_label(sugg_span.with_hi(span.lo()), "");
+ }
+ let ty_str = if short_ty_str.len() < ty_str.len() && ty_str.len() > 10 {
+ short_ty_str
+ } else {
+ ty_str
+ };
+ if let Some(file) = ty_file {
+ err.note(&format!("the full type name has been written to '{}'", file.display(),));
+ }
if rcvr_ty.references_error() {
err.downgrade_to_delayed_bug();
}
@@ -352,7 +377,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let ty_span = match rcvr_ty.kind() {
ty::Param(param_type) => {
- Some(param_type.span_from_generics(self.tcx, self.body_id.owner.to_def_id()))
+ Some(param_type.span_from_generics(self.tcx, self.body_id.to_def_id()))
}
ty::Adt(def, _) if def.did().is_local() => Some(tcx.def_span(def.did())),
_ => None,
@@ -403,7 +428,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
args,
sugg_span,
);
-
self.note_candidates_on_method_error(
rcvr_ty,
item_name,
@@ -496,9 +520,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
ty::Param(_) => {
// Account for `fn` items like in `issue-35677.rs` to
// suggest restricting its type params.
- let parent_body =
- hir.body_owner(hir::BodyId { hir_id: self.body_id });
- Some(hir.get(parent_body))
+ Some(hir.get_by_def_id(self.body_id))
}
ty::Adt(def, _) => {
def.did().as_local().map(|def_id| hir.get_by_def_id(def_id))
@@ -555,7 +577,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// `<Foo as Iterator>::Item = String`.
let projection_ty = pred.skip_binder().projection_ty;
- let substs_with_infer_self = tcx.mk_substs(
+ let substs_with_infer_self = tcx.mk_substs_from_iter(
iter::once(tcx.mk_ty_var(ty::TyVid::from_u32(0)).into())
.chain(projection_ty.substs.iter().skip(1)),
);
@@ -597,7 +619,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
ObligationCauseCode::ImplDerivedObligation(data)
if matches!(p.kind().skip_binder(), ty::PredicateKind::Clause(_)) =>
{
- Some((p, parent, data.impl_def_id, data))
+ Some((p, parent, data.impl_or_alias_def_id, data))
}
_ => None,
})
@@ -695,7 +717,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
);
}
Some(Node::Item(hir::Item {
- ident, kind: hir::ItemKind::Trait(..), ..
+ ident,
+ kind: hir::ItemKind::Trait(..) | hir::ItemKind::TraitAlias(..),
+ ..
})) => {
skip_list.insert(p);
let entry = spanned_predicates.entry(ident.span);
@@ -829,7 +853,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let primary_message = primary_message.unwrap_or_else(|| {
format!(
"the {item_kind} `{item_name}` exists for {actual_prefix} `{ty_str}`, \
- but its trait bounds were not satisfied"
+ but its trait bounds were not satisfied"
)
});
err.set_primary_message(&primary_message);
@@ -887,8 +911,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// different from the received one
// So we avoid suggestion method with Box<Self>
// for instance
- self.tcx.at(span).type_of(*def_id) != rcvr_ty
- && self.tcx.at(span).type_of(*def_id) != rcvr_ty
+ self.tcx.at(span).type_of(*def_id).subst_identity()
+ != rcvr_ty
+ && self.tcx.at(span).type_of(*def_id).subst_identity()
+ != rcvr_ty
}
(Mode::Path, false, _) => true,
_ => false,
@@ -908,7 +934,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
.iter()
.take(limit)
.map(|impl_item| {
- format!("- `{}`", self.tcx.at(span).type_of(*impl_item))
+ format!(
+ "- `{}`",
+ self.tcx.at(span).type_of(*impl_item).subst_identity()
+ )
})
.collect::<Vec<_>>()
.join("\n");
@@ -937,7 +966,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// give a helping note that it has to be called as `(x.f)(...)`.
if let SelfSource::MethodCall(expr) = source {
if !self.suggest_calling_field_as_fn(span, rcvr_ty, expr, item_name, &mut err)
- && lev_candidate.is_none()
+ && similar_candidate.is_none()
&& !custom_span_label
{
label_span_not_found(&mut err);
@@ -988,7 +1017,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// that had unsatisfied trait bounds
if unsatisfied_predicates.is_empty() && rcvr_ty.is_enum() {
let adt_def = rcvr_ty.ty_adt_def().expect("enum is not an ADT");
- if let Some(suggestion) = lev_distance::find_best_match_for_name(
+ if let Some(suggestion) = edit_distance::find_best_match_for_name(
&adt_def.variants().iter().map(|s| s.name).collect::<Vec<_>>(),
item_name.name,
None,
@@ -1015,20 +1044,20 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
if fallback_span {
err.span_label(span, msg);
}
- } else if let Some(lev_candidate) = lev_candidate {
+ } else if let Some(similar_candidate) = similar_candidate {
// Don't emit a suggestion if we found an actual method
// that had unsatisfied trait bounds
if unsatisfied_predicates.is_empty() {
- let def_kind = lev_candidate.kind.as_def_kind();
+ let def_kind = similar_candidate.kind.as_def_kind();
// Methods are defined within the context of a struct and their first parameter is always self,
// which represents the instance of the struct the method is being called on
// Associated functions don’t take self as a parameter and
// they are not methods because they don’t have an instance of the struct to work with.
- if def_kind == DefKind::AssocFn && lev_candidate.fn_has_self_parameter {
+ if def_kind == DefKind::AssocFn && similar_candidate.fn_has_self_parameter {
err.span_suggestion(
span,
"there is a method with a similar name",
- lev_candidate.name,
+ similar_candidate.name,
Applicability::MaybeIncorrect,
);
} else {
@@ -1036,10 +1065,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
span,
&format!(
"there is {} {} with a similar name",
- def_kind.article(),
- def_kind.descr(lev_candidate.def_id),
+ self.tcx.def_kind_descr_article(def_kind, similar_candidate.def_id),
+ self.tcx.def_kind_descr(def_kind, similar_candidate.def_id)
),
- lev_candidate.name,
+ similar_candidate.name,
Applicability::MaybeIncorrect,
);
}
@@ -1085,7 +1114,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
None
};
- let impl_ty = self.tcx.at(span).type_of(impl_did);
+ let impl_ty = self.tcx.at(span).type_of(impl_did).subst_identity();
let insertion = match self.tcx.impl_trait_ref(impl_did) {
None => String::new(),
@@ -1131,6 +1160,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
ty::AssocKind::Fn => self
.tcx
.fn_sig(item.def_id)
+ .subst_identity()
.inputs()
.skip_binder()
.get(0)
@@ -1145,7 +1175,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
path,
ty,
item.kind,
- item.def_id,
+ self.tcx.def_kind_descr(item.kind.as_def_kind(), item.def_id),
sugg_span,
idx,
self.tcx.sess.source_map(),
@@ -1181,7 +1211,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
path,
rcvr_ty,
item.kind,
- item.def_id,
+ self.tcx.def_kind_descr(item.kind.as_def_kind(), item.def_id),
sugg_span,
idx,
self.tcx.sess.source_map(),
@@ -1213,7 +1243,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// When the "method" is resolved through dereferencing, we really want the
// original type that has the associated function for accurate suggestions.
// (#61411)
- let impl_ty = self.tcx.type_of(*impl_did);
+ let impl_ty = self.tcx.type_of(*impl_did).subst_identity();
let target_ty = self
.autoderef(sugg_span, rcvr_ty)
.find(|(rcvr_ty, _)| {
@@ -1225,7 +1255,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
if let ty::Adt(def, substs) = target_ty.kind() {
// If there are any inferred arguments, (`{integer}`), we should replace
// them with underscores to allow the compiler to infer them
- let infer_substs = self.tcx.mk_substs(substs.into_iter().map(|arg| {
+ let infer_substs = self.tcx.mk_substs_from_iter(substs.into_iter().map(|arg| {
if !arg.is_suggestable(self.tcx, true) {
has_unsuggestable_args = true;
match arg.unpack() {
@@ -1267,7 +1297,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
&& let Some(assoc) = self.associated_value(*impl_did, item_name)
&& assoc.kind == ty::AssocKind::Fn
{
- let sig = self.tcx.fn_sig(assoc.def_id);
+ let sig = self.tcx.fn_sig(assoc.def_id).subst_identity();
sig.inputs().skip_binder().get(0).and_then(|first| if first.peel_refs() == rcvr_ty.peel_refs() {
None
} else {
@@ -1343,7 +1373,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
_ => None,
});
if let Some((field, field_ty)) = field_receiver {
- let scope = tcx.parent_module(self.body_id);
+ let scope = tcx.parent_module_from_def_id(self.body_id);
let is_accessible = field.vis.is_accessible_from(scope, tcx);
if is_accessible {
@@ -1433,8 +1463,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
let range_def_id = self.tcx.require_lang_item(lang_item.unwrap(), None);
- let range_ty =
- self.tcx.bound_type_of(range_def_id).subst(self.tcx, &[actual.into()]);
+ let range_ty = self.tcx.type_of(range_def_id).subst(self.tcx, &[actual.into()]);
let pick = self.lookup_probe_for_diagnostic(
item_name,
@@ -1593,7 +1622,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
else { return };
let map = self.infcx.tcx.hir();
- let body = map.body(rustc_hir::BodyId { hir_id: self.body_id });
+ let body_id = self.tcx.hir().body_owned_by(self.body_id);
+ let body = map.body(body_id);
struct LetVisitor<'a> {
result: Option<&'a hir::Expr<'a>>,
ident_name: Symbol,
@@ -2100,7 +2130,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// just changing the path.
&& pick.item.fn_has_self_parameter
&& let Some(self_ty) =
- self.tcx.fn_sig(pick.item.def_id).inputs().skip_binder().get(0)
+ self.tcx.fn_sig(pick.item.def_id).subst_identity().inputs().skip_binder().get(0)
&& self_ty.is_ref()
{
let suggested_path = match deref_ty.kind() {
@@ -2195,7 +2225,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
true
});
- let module_did = self.tcx.parent_module(self.body_id);
+ let module_did = self.tcx.parent_module_from_def_id(self.body_id);
let (module, _, _) = self.tcx.hir().get_module(module_did);
let span = module.spans.inject_use_span;
@@ -2353,7 +2383,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// implement the `AsRef` trait.
let skip = skippable.contains(&did)
|| (("Pin::new" == *pre) && (sym::as_ref == item_name.name))
- || inputs_len.map_or(false, |inputs_len| pick.item.kind == ty::AssocKind::Fn && self.tcx.fn_sig(pick.item.def_id).skip_binder().inputs().len() != inputs_len);
+ || inputs_len.map_or(false, |inputs_len| pick.item.kind == ty::AssocKind::Fn && self.tcx.fn_sig(pick.item.def_id).skip_binder().skip_binder().inputs().len() != inputs_len);
// Make sure the method is defined for the *actual* receiver: we don't
// want to treat `Box<Self>` as a receiver if it only works because of
// an autoderef to `&self`
@@ -2517,7 +2547,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
};
// Obtain the span for `param` and use it for a structured suggestion.
if let Some(param) = param_type {
- let generics = self.tcx.generics_of(self.body_id.owner.to_def_id());
+ let generics = self.tcx.generics_of(self.body_id.to_def_id());
let type_param = generics.type_param(param, self.tcx);
let hir = self.tcx.hir();
if let Some(def_id) = type_param.def_id.as_local() {
@@ -2733,7 +2763,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// check the method arguments number
if let Ok(pick) = probe &&
let fn_sig = self.tcx.fn_sig(pick.item.def_id) &&
- let fn_args = fn_sig.skip_binder().inputs() &&
+ let fn_args = fn_sig.skip_binder().skip_binder().inputs() &&
fn_args.len() == args.len() + 1 {
err.span_suggestion_verbose(
method_name.span.shrink_to_hi(),
@@ -2826,7 +2856,7 @@ fn print_disambiguation_help<'tcx>(
trait_name: String,
rcvr_ty: Ty<'_>,
kind: ty::AssocKind,
- def_id: DefId,
+ def_kind_descr: &'static str,
span: Span,
candidate: Option<usize>,
source_map: &source_map::SourceMap,
@@ -2859,7 +2889,7 @@ fn print_disambiguation_help<'tcx>(
span,
&format!(
"disambiguate the {} for {}",
- kind.as_def_kind().descr(def_id),
+ def_kind_descr,
if let Some(candidate) = candidate {
format!("candidate #{}", candidate)
} else {
diff --git a/compiler/rustc_hir_typeck/src/op.rs b/compiler/rustc_hir_typeck/src/op.rs
index 78cea1f4d..80279ed96 100644
--- a/compiler/rustc_hir_typeck/src/op.rs
+++ b/compiler/rustc_hir_typeck/src/op.rs
@@ -13,7 +13,7 @@ use rustc_middle::ty::adjustment::{
};
use rustc_middle::ty::print::with_no_trimmed_paths;
use rustc_middle::ty::{
- self, DefIdTree, IsSuggestable, Ty, TyCtxt, TypeFolder, TypeSuperFoldable, TypeVisitable,
+ self, DefIdTree, IsSuggestable, Ty, TyCtxt, TypeFolder, TypeSuperFoldable, TypeVisitableExt,
};
use rustc_session::errors::ExprParenthesesNeeded;
use rustc_span::source_map::Spanned;
@@ -297,7 +297,9 @@ 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(_) if lhs_ty.references_error() || rhs_ty.references_error() => {
+ self.tcx.ty_error_misc()
+ }
Err(errors) => {
let (_, trait_def_id) =
lang_item_for_op(self.tcx, Op::Binary(op, is_assign), op.span);
@@ -335,7 +337,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
format!("cannot divide `{lhs_ty}` by `{rhs_ty}`")
}
hir::BinOpKind::Rem => {
- format!("cannot mod `{lhs_ty}` by `{rhs_ty}`")
+ format!(
+ "cannot calculate the remainder of `{lhs_ty}` divided by `{rhs_ty}`"
+ )
}
hir::BinOpKind::BitAnd => {
format!("no implementation for `{lhs_ty} & {rhs_ty}`")
@@ -488,9 +492,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
if let Some(output_def_id) = output_def_id
&& let Some(trait_def_id) = trait_def_id
&& self.tcx.parent(output_def_id) == trait_def_id
- && output_ty.is_suggestable(self.tcx, false)
+ && let Some(output_ty) = output_ty.make_suggestable(self.tcx, false)
{
- Some(("Output", *output_ty))
+ Some(("Output", output_ty))
} else {
None
}
@@ -516,7 +520,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
}
let reported = err.emit();
- self.tcx.ty_error_with_guaranteed(reported)
+ self.tcx.ty_error(reported)
}
};
@@ -629,7 +633,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
Err(errors) => {
let actual = self.resolve_vars_if_possible(operand_ty);
- if !actual.references_error() {
+ let guar = actual.error_reported().err().unwrap_or_else(|| {
let mut err = struct_span_err!(
self.tcx.sess,
ex.span,
@@ -699,9 +703,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
}
}
- err.emit();
- }
- self.tcx.ty_error()
+ err.emit()
+ });
+ self.tcx.ty_error(guar)
}
}
}
@@ -745,14 +749,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
let opname = Ident::with_dummy_span(opname);
- let input_types =
- opt_rhs.as_ref().map(|(_, ty)| std::slice::from_ref(ty)).unwrap_or_default();
+ let (opt_rhs_expr, opt_rhs_ty) = opt_rhs.unzip();
+ let input_types = opt_rhs_ty.as_slice();
let cause = self.cause(
span,
traits::BinOp {
- rhs_span: opt_rhs.map(|(expr, _)| expr.span),
- is_lit: opt_rhs
- .map_or(false, |(expr, _)| matches!(expr.kind, hir::ExprKind::Lit(_))),
+ rhs_span: opt_rhs_expr.map(|expr| expr.span),
+ is_lit: opt_rhs_expr
+ .map_or(false, |expr| matches!(expr.kind, hir::ExprKind::Lit(_))),
output_ty: expected.only_has_type(self),
},
);
@@ -961,8 +965,8 @@ fn is_builtin_binop<'tcx>(lhs: Ty<'tcx>, rhs: Ty<'tcx>, op: hir::BinOp) -> bool
struct TypeParamEraser<'a, 'tcx>(&'a FnCtxt<'a, 'tcx>, Span);
-impl<'tcx> TypeFolder<'tcx> for TypeParamEraser<'_, 'tcx> {
- fn tcx(&self) -> TyCtxt<'tcx> {
+impl<'tcx> TypeFolder<TyCtxt<'tcx>> for TypeParamEraser<'_, 'tcx> {
+ fn interner(&self) -> TyCtxt<'tcx> {
self.0.tcx
}
diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs
index 467992452..c36c75e44 100644
--- a/compiler/rustc_hir_typeck/src/pat.rs
+++ b/compiler/rustc_hir_typeck/src/pat.rs
@@ -12,10 +12,10 @@ use rustc_hir::{HirId, Pat, PatKind};
use rustc_infer::infer;
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
use rustc_middle::middle::stability::EvalResult;
-use rustc_middle::ty::{self, Adt, BindingMode, Ty, TypeVisitable};
+use rustc_middle::ty::{self, Adt, BindingMode, Ty, TypeVisitableExt};
use rustc_session::lint::builtin::NON_EXHAUSTIVE_OMITTED_PATTERNS;
+use rustc_span::edit_distance::find_best_match_for_name;
use rustc_span::hygiene::DesugaringKind;
-use rustc_span::lev_distance::find_best_match_for_name;
use rustc_span::source_map::{Span, Spanned};
use rustc_span::symbol::{kw, sym, Ident};
use rustc_span::{BytePos, DUMMY_SP};
@@ -46,7 +46,7 @@ struct TopInfo<'tcx> {
/// Was the origin of the `span` from a scrutinee expression?
///
/// Otherwise there is no scrutinee and it could be e.g. from the type of a formal parameter.
- origin_expr: bool,
+ origin_expr: Option<&'tcx hir::Expr<'tcx>>,
/// The span giving rise to the `expected` type, if one could be provided.
///
/// If `origin_expr` is `true`, then this is the span of the scrutinee as in:
@@ -74,7 +74,8 @@ struct TopInfo<'tcx> {
impl<'tcx> FnCtxt<'_, 'tcx> {
fn pattern_cause(&self, ti: TopInfo<'tcx>, cause_span: Span) -> ObligationCause<'tcx> {
- let code = Pattern { span: ti.span, root_ty: ti.expected, origin_expr: ti.origin_expr };
+ let code =
+ Pattern { span: ti.span, root_ty: ti.expected, origin_expr: ti.origin_expr.is_some() };
self.cause(cause_span, code)
}
@@ -85,7 +86,14 @@ impl<'tcx> FnCtxt<'_, 'tcx> {
actual: Ty<'tcx>,
ti: TopInfo<'tcx>,
) -> Option<DiagnosticBuilder<'tcx, ErrorGuaranteed>> {
- self.demand_eqtype_with_origin(&self.pattern_cause(ti, cause_span), expected, actual)
+ let mut diag =
+ self.demand_eqtype_with_origin(&self.pattern_cause(ti, cause_span), expected, actual)?;
+ if let Some(expr) = ti.origin_expr {
+ self.suggest_fn_call(&mut diag, expr, expected, |output| {
+ self.can_eq(self.param_env, output, actual)
+ });
+ }
+ Some(diag)
}
fn demand_eqtype_pat(
@@ -127,7 +135,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
pat: &'tcx Pat<'tcx>,
expected: Ty<'tcx>,
span: Option<Span>,
- origin_expr: bool,
+ origin_expr: Option<&'tcx hir::Expr<'tcx>>,
) {
let info = TopInfo { expected, origin_expr, span };
self.check_pat(pat, expected, INITIAL_BM, info);
@@ -467,8 +475,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
if let (Some((true, ..)), _) | (_, Some((true, ..))) = (lhs, rhs) {
// There exists a side that didn't meet our criteria that the end-point
// be of a numeric or char type, as checked in `calc_side` above.
- self.emit_err_pat_range(span, lhs, rhs);
- return self.tcx.ty_error();
+ let guar = self.emit_err_pat_range(span, lhs, rhs);
+ return self.tcx.ty_error(guar);
}
// Unify each side with `expected`.
@@ -488,7 +496,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
demand_eqtype(&mut rhs, lhs);
if let (Some((true, ..)), _) | (_, Some((true, ..))) = (lhs, rhs) {
- return self.tcx.ty_error();
+ return self.tcx.ty_error_misc();
}
// Find the unified type and check if it's of numeric or char type again.
@@ -503,8 +511,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
if let Some((ref mut fail, _, _)) = rhs {
*fail = true;
}
- self.emit_err_pat_range(span, lhs, rhs);
- return self.tcx.ty_error();
+ let guar = self.emit_err_pat_range(span, lhs, rhs);
+ return self.tcx.ty_error(guar);
}
ty
}
@@ -520,7 +528,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
span: Span,
lhs: Option<(bool, Ty<'tcx>, Span)>,
rhs: Option<(bool, Ty<'tcx>, Span)>,
- ) {
+ ) -> ErrorGuaranteed {
let span = match (lhs, rhs) {
(Some((true, ..)), Some((true, ..))) => span,
(Some((true, _, sp)), _) => sp,
@@ -565,7 +573,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
type between two end-points, you can use a guard.",
);
}
- err.emit();
+ err.emit()
}
fn check_pat_ident(
@@ -667,7 +675,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
) {
match (expected.kind(), actual.kind(), ba) {
(ty::Ref(_, inner_ty, _), _, hir::BindingAnnotation::NONE)
- if self.can_eq(self.param_env, *inner_ty, actual).is_ok() =>
+ if self.can_eq(self.param_env, *inner_ty, actual) =>
{
err.span_suggestion_verbose(
span.shrink_to_lo(),
@@ -677,7 +685,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
);
}
(_, ty::Ref(_, inner_ty, _), hir::BindingAnnotation::REF)
- if self.can_eq(self.param_env, expected, *inner_ty).is_ok() =>
+ if self.can_eq(self.param_env, expected, *inner_ty) =>
{
err.span_suggestion_verbose(
span.with_hi(span.lo() + BytePos(4)),
@@ -799,29 +807,33 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
}
- pub fn check_dereferenceable(&self, span: Span, expected: Ty<'tcx>, inner: &Pat<'_>) -> bool {
+ pub fn check_dereferenceable(
+ &self,
+ span: Span,
+ expected: Ty<'tcx>,
+ inner: &Pat<'_>,
+ ) -> Result<(), ErrorGuaranteed> {
if let PatKind::Binding(..) = inner.kind
&& let Some(mt) = self.shallow_resolve(expected).builtin_deref(true)
&& let ty::Dynamic(..) = mt.ty.kind()
{
- // This is "x = SomeTrait" being reduced from
- // "let &x = &SomeTrait" or "let box x = Box<SomeTrait>", an error.
- let type_str = self.ty_to_string(expected);
- let mut err = struct_span_err!(
- self.tcx.sess,
- span,
- E0033,
- "type `{}` cannot be dereferenced",
- type_str
- );
- err.span_label(span, format!("type `{type_str}` cannot be dereferenced"));
- if self.tcx.sess.teach(&err.get_code().unwrap()) {
- err.note(CANNOT_IMPLICITLY_DEREF_POINTER_TRAIT_OBJ);
- }
- err.emit();
- return false;
- }
- true
+ // This is "x = SomeTrait" being reduced from
+ // "let &x = &SomeTrait" or "let box x = Box<SomeTrait>", an error.
+ let type_str = self.ty_to_string(expected);
+ let mut err = struct_span_err!(
+ self.tcx.sess,
+ span,
+ E0033,
+ "type `{}` cannot be dereferenced",
+ type_str
+ );
+ err.span_label(span, format!("type `{type_str}` cannot be dereferenced"));
+ if self.tcx.sess.teach(&err.get_code().unwrap()) {
+ err.note(CANNOT_IMPLICITLY_DEREF_POINTER_TRAIT_OBJ);
+ }
+ return Err(err.emit());
+ }
+ Ok(())
}
fn check_pat_struct(
@@ -835,13 +847,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
ti: TopInfo<'tcx>,
) -> Ty<'tcx> {
// Resolve the path and check the definition for errors.
- let Some((variant, pat_ty)) = self.check_struct_path(qpath, pat.hir_id) else {
- let err = self.tcx.ty_error();
- for field in fields {
- let ti = ti;
- self.check_pat(field.pat, err, def_bm, ti);
+ let (variant, pat_ty) = match self.check_struct_path(qpath, pat.hir_id) {
+ Ok(data) => data,
+ Err(guar) => {
+ let err = self.tcx.ty_error(guar);
+ for field in fields {
+ let ti = ti;
+ self.check_pat(field.pat, err, def_bm, ti);
+ }
+ return err;
}
- return err;
};
// Type-check the path.
@@ -851,7 +866,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
if self.check_struct_pat_fields(pat_ty, &pat, variant, fields, has_rest_pat, def_bm, ti) {
pat_ty
} else {
- self.tcx.ty_error()
+ self.tcx.ty_error_misc()
}
}
@@ -871,12 +886,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
Res::Err => {
let e = tcx.sess.delay_span_bug(qpath.span(), "`Res::Err` but no error emitted");
self.set_tainted_by_errors(e);
- return tcx.ty_error_with_guaranteed(e);
+ return tcx.ty_error(e);
}
Res::Def(DefKind::AssocFn | DefKind::Ctor(_, CtorKind::Fn) | DefKind::Variant, _) => {
let expected = "unit struct, unit variant or constant";
let e = report_unexpected_variant_res(tcx, res, qpath, pat.span, "E0533", expected);
- return tcx.ty_error_with_guaranteed(e);
+ return tcx.ty_error(e);
}
Res::SelfCtor(..)
| Res::Def(
@@ -1019,7 +1034,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let tcx = self.tcx;
let on_error = |e| {
for pat in subpats {
- self.check_pat(pat, tcx.ty_error_with_guaranteed(e), def_bm, ti);
+ self.check_pat(pat, tcx.ty_error(e), def_bm, ti);
}
};
let report_unexpected_res = |res: Res| {
@@ -1036,7 +1051,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let e = tcx.sess.delay_span_bug(pat.span, "`Res::Err` but no error emitted");
self.set_tainted_by_errors(e);
on_error(e);
- return tcx.ty_error_with_guaranteed(e);
+ return tcx.ty_error(e);
}
// Type-check the path.
@@ -1044,7 +1059,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
self.instantiate_value_path(segments, opt_ty, res, pat.span, pat.hir_id);
if !pat_ty.is_fn() {
let e = report_unexpected_res(res);
- return tcx.ty_error_with_guaranteed(e);
+ return tcx.ty_error(e);
}
let variant = match res {
@@ -1052,11 +1067,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let e = tcx.sess.delay_span_bug(pat.span, "`Res::Err` but no error emitted");
self.set_tainted_by_errors(e);
on_error(e);
- return tcx.ty_error_with_guaranteed(e);
+ return tcx.ty_error(e);
}
Res::Def(DefKind::AssocConst | DefKind::AssocFn, _) => {
let e = report_unexpected_res(res);
- return tcx.ty_error_with_guaranteed(e);
+ return tcx.ty_error(e);
}
Res::Def(DefKind::Ctor(_, CtorKind::Fn), _) => tcx.expect_variant_res(res),
_ => bug!("unexpected pattern resolution: {:?}", res),
@@ -1097,7 +1112,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// Pattern has wrong number of fields.
let e = self.e0023(pat.span, res, qpath, subpats, &variant.fields, expected, had_err);
on_error(e);
- return tcx.ty_error_with_guaranteed(e);
+ return tcx.ty_error(e);
}
pat_ty
}
@@ -1287,17 +1302,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
TypeVariableOrigin { kind: TypeVariableOriginKind::TypeInference, span },
)
});
- let element_tys = tcx.mk_type_list(element_tys_iter);
- let pat_ty = tcx.mk_ty(ty::Tuple(element_tys));
+ let element_tys = tcx.mk_type_list_from_iter(element_tys_iter);
+ let pat_ty = tcx.mk_tup(element_tys);
if let Some(mut err) = self.demand_eqtype_pat_diag(span, expected, pat_ty, ti) {
let reported = err.emit();
// Walk subpatterns with an expected type of `err` in this case to silence
// further errors being emitted when using the bindings. #50333
- let element_tys_iter = (0..max_len).map(|_| tcx.ty_error_with_guaranteed(reported));
+ let element_tys_iter = (0..max_len).map(|_| tcx.ty_error(reported));
for (_, elem) in elements.iter().enumerate_and_adjust(max_len, ddpos) {
- self.check_pat(elem, tcx.ty_error_with_guaranteed(reported), def_bm, ti);
+ self.check_pat(elem, tcx.ty_error(reported), def_bm, ti);
}
- tcx.mk_tup(element_tys_iter)
+ tcx.mk_tup_from_iter(element_tys_iter)
} else {
for (i, elem) in elements.iter().enumerate_and_adjust(max_len, ddpos) {
self.check_pat(elem, element_tys[i], def_bm, ti);
@@ -1341,9 +1356,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let ident = tcx.adjust_ident(field.ident, variant.def_id);
let field_ty = match used_fields.entry(ident) {
Occupied(occupied) => {
- self.error_field_already_bound(span, field.ident, *occupied.get());
no_field_errors = false;
- tcx.ty_error()
+ let guar = self.error_field_already_bound(span, field.ident, *occupied.get());
+ tcx.ty_error(guar)
}
Vacant(vacant) => {
vacant.insert(span);
@@ -1357,7 +1372,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
.unwrap_or_else(|| {
inexistent_fields.push(field);
no_field_errors = false;
- tcx.ty_error()
+ tcx.ty_error_misc()
})
}
};
@@ -1528,7 +1543,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
err.emit();
}
- fn error_field_already_bound(&self, span: Span, ident: Ident, other_field: Span) {
+ fn error_field_already_bound(
+ &self,
+ span: Span,
+ ident: Ident,
+ other_field: Span,
+ ) -> ErrorGuaranteed {
struct_span_err!(
self.tcx.sess,
span,
@@ -1538,7 +1558,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
)
.span_label(span, format!("multiple uses of `{ident}` in pattern"))
.span_label(other_field, format!("first use of `{ident}`"))
- .emit();
+ .emit()
}
fn error_inexistent_fields(
@@ -1911,19 +1931,22 @@ 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) {
- // 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 {
- kind: TypeVariableOriginKind::TypeInference,
- span: inner.span,
- });
- let box_ty = tcx.mk_box(inner_ty);
- self.demand_eqtype_pat(span, expected, box_ty, ti);
- (box_ty, inner_ty)
- } else {
- let err = tcx.ty_error();
- (err, err)
+ let (box_ty, inner_ty) = match self.check_dereferenceable(span, expected, inner) {
+ Ok(()) => {
+ // 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 {
+ kind: TypeVariableOriginKind::TypeInference,
+ span: inner.span,
+ });
+ let box_ty = tcx.mk_box(inner_ty);
+ self.demand_eqtype_pat(span, expected, box_ty, ti);
+ (box_ty, inner_ty)
+ }
+ Err(guar) => {
+ let err = tcx.ty_error(guar);
+ (err, err)
+ }
};
self.check_pat(inner, inner_ty, def_bm, ti);
box_ty
@@ -1941,37 +1964,40 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
) -> Ty<'tcx> {
let tcx = self.tcx;
let expected = self.shallow_resolve(expected);
- let (ref_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.
-
- // Take region, inner-type from expected type if we can,
- // to avoid creating needless variables. This also helps with
- // the bad interactions of the given hack detailed in (note_1).
- debug!("check_pat_ref: expected={:?}", expected);
- match *expected.kind() {
- ty::Ref(_, r_ty, r_mutbl) if r_mutbl == mutbl => (expected, r_ty),
- _ => {
- let inner_ty = self.next_ty_var(TypeVariableOrigin {
- kind: TypeVariableOriginKind::TypeInference,
- span: inner.span,
- });
- let ref_ty = self.new_ref_ty(pat.span, mutbl, inner_ty);
- debug!("check_pat_ref: demanding {:?} = {:?}", expected, ref_ty);
- let err = self.demand_eqtype_pat_diag(pat.span, expected, ref_ty, ti);
-
- // 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);
- err.emit();
+ let (ref_ty, inner_ty) = match self.check_dereferenceable(pat.span, expected, inner) {
+ Ok(()) => {
+ // `demand::subtype` would be good enough, but using `eqtype` turns
+ // out to be equally general. See (note_1) for details.
+
+ // Take region, inner-type from expected type if we can,
+ // to avoid creating needless variables. This also helps with
+ // the bad interactions of the given hack detailed in (note_1).
+ debug!("check_pat_ref: expected={:?}", expected);
+ match *expected.kind() {
+ ty::Ref(_, r_ty, r_mutbl) if r_mutbl == mutbl => (expected, r_ty),
+ _ => {
+ let inner_ty = self.next_ty_var(TypeVariableOrigin {
+ kind: TypeVariableOriginKind::TypeInference,
+ span: inner.span,
+ });
+ let ref_ty = self.new_ref_ty(pat.span, mutbl, inner_ty);
+ debug!("check_pat_ref: demanding {:?} = {:?}", expected, ref_ty);
+ let err = self.demand_eqtype_pat_diag(pat.span, expected, ref_ty, ti);
+
+ // 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);
+ err.emit();
+ }
+ (ref_ty, inner_ty)
}
- (ref_ty, inner_ty)
}
}
- } else {
- let err = tcx.ty_error();
- (err, err)
+ Err(guar) => {
+ let err = tcx.ty_error(guar);
+ (err, err)
+ }
};
self.check_pat(inner, inner_ty, def_bm, ti);
ref_ty
@@ -2019,10 +2045,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
ty::Slice(element_ty) => (element_ty, Some(expected), expected),
// The expected type must be an array or slice, but was neither, so error.
_ => {
- if !expected.references_error() {
- self.error_expected_array_or_slice(span, expected, ti);
- }
- let err = self.tcx.ty_error();
+ let guar = expected
+ .error_reported()
+ .err()
+ .unwrap_or_else(|| self.error_expected_array_or_slice(span, expected, ti));
+ let err = self.tcx.ty_error(guar);
(err, Some(err), err)
}
};
@@ -2055,7 +2082,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
len: ty::Const<'tcx>,
min_len: u64,
) -> (Option<Ty<'tcx>>, Ty<'tcx>) {
- if let Some(len) = len.try_eval_usize(self.tcx, self.param_env) {
+ let guar = if let Some(len) = len.try_eval_target_usize(self.tcx, self.param_env) {
// Now we know the length...
if slice.is_none() {
// ...and since there is no variable-length pattern,
@@ -2065,7 +2092,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
return (None, arr_ty);
}
- self.error_scrutinee_inconsistent_length(span, min_len, len);
+ self.error_scrutinee_inconsistent_length(span, min_len, len)
} else if let Some(pat_len) = len.checked_sub(min_len) {
// The variable-length pattern was there,
// so it has an array type with the remaining elements left as its size...
@@ -2073,7 +2100,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
} else {
// ...however, in this case, there were no remaining elements.
// That is, the slice pattern requires more than the array type offers.
- self.error_scrutinee_with_rest_inconsistent_length(span, min_len, len);
+ self.error_scrutinee_with_rest_inconsistent_length(span, min_len, len)
}
} else if slice.is_none() {
// We have a pattern with a fixed length,
@@ -2085,14 +2112,19 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// We have a variable-length pattern and don't know the array length.
// This happens if we have e.g.,
// `let [a, b, ..] = arr` where `arr: [T; N]` where `const N: usize`.
- self.error_scrutinee_unfixed_length(span);
- }
+ self.error_scrutinee_unfixed_length(span)
+ };
// If we get here, we must have emitted an error.
- (Some(self.tcx.ty_error()), arr_ty)
+ (Some(self.tcx.ty_error(guar)), arr_ty)
}
- fn error_scrutinee_inconsistent_length(&self, span: Span, min_len: u64, size: u64) {
+ fn error_scrutinee_inconsistent_length(
+ &self,
+ span: Span,
+ min_len: u64,
+ size: u64,
+ ) -> ErrorGuaranteed {
struct_span_err!(
self.tcx.sess,
span,
@@ -2103,10 +2135,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
size,
)
.span_label(span, format!("expected {} element{}", size, pluralize!(size)))
- .emit();
+ .emit()
}
- fn error_scrutinee_with_rest_inconsistent_length(&self, span: Span, min_len: u64, size: u64) {
+ fn error_scrutinee_with_rest_inconsistent_length(
+ &self,
+ span: Span,
+ min_len: u64,
+ size: u64,
+ ) -> ErrorGuaranteed {
struct_span_err!(
self.tcx.sess,
span,
@@ -2120,20 +2157,25 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
span,
format!("pattern cannot match array of {} element{}", size, pluralize!(size),),
)
- .emit();
+ .emit()
}
- fn error_scrutinee_unfixed_length(&self, span: Span) {
+ fn error_scrutinee_unfixed_length(&self, span: Span) -> ErrorGuaranteed {
struct_span_err!(
self.tcx.sess,
span,
E0730,
"cannot pattern-match on an array without a fixed length",
)
- .emit();
+ .emit()
}
- fn error_expected_array_or_slice(&self, span: Span, expected_ty: Ty<'tcx>, ti: TopInfo<'tcx>) {
+ fn error_expected_array_or_slice(
+ &self,
+ span: Span,
+ expected_ty: Ty<'tcx>,
+ ti: TopInfo<'tcx>,
+ ) -> ErrorGuaranteed {
let mut err = struct_span_err!(
self.tcx.sess,
span,
@@ -2146,7 +2188,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
err.help("the semantics of slice patterns changed recently; see issue #62254");
} else if self.autoderef(span, expected_ty)
.any(|(ty, _)| matches!(ty.kind(), ty::Slice(..) | ty::Array(..)))
- && let (Some(span), true) = (ti.span, ti.origin_expr)
+ && let Some(span) = ti.span
+ && let Some(_) = ti.origin_expr
&& let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span)
{
let ty = self.resolve_vars_if_possible(ti.expected);
@@ -2176,7 +2219,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
}
err.span_label(span, format!("pattern cannot match with input type `{expected_ty}`"));
- err.emit();
+ err.emit()
}
fn is_slice_or_array_or_vector(&self, ty: Ty<'tcx>) -> (bool, Ty<'tcx>) {
diff --git a/compiler/rustc_hir_typeck/src/place_op.rs b/compiler/rustc_hir_typeck/src/place_op.rs
index ae0df5aa8..2cca45de5 100644
--- a/compiler/rustc_hir_typeck/src/place_op.rs
+++ b/compiler/rustc_hir_typeck/src/place_op.rs
@@ -11,7 +11,6 @@ use rustc_middle::ty::adjustment::{AllowTwoPhase, AutoBorrow, AutoBorrowMutabili
use rustc_middle::ty::{self, Ty};
use rustc_span::symbol::{sym, Ident};
use rustc_span::Span;
-use std::slice;
impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
/// Type-check `*oprnd_expr` with `oprnd_expr` type-checked already.
@@ -91,10 +90,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
);
}
let reported = err.emit();
- Some((
- self.tcx.ty_error_with_guaranteed(reported),
- self.tcx.ty_error_with_guaranteed(reported),
- ))
+ Some((self.tcx.ty_error(reported), self.tcx.ty_error(reported)))
}
/// To type-check `base_expr[index_expr]`, we progressively autoderef
@@ -396,11 +392,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
Some(self.typeck_results.borrow().node_substs(expr.hir_id).type_at(1))
}
};
- let arg_tys = match arg_ty {
- None => &[],
- Some(ref ty) => slice::from_ref(ty),
- };
-
+ let arg_tys = arg_ty.as_slice();
let method = self.try_mutable_overloaded_place_op(expr.span, base_ty, arg_tys, op);
let method = match method {
Some(ok) => self.register_infer_ok_obligations(ok),
diff --git a/compiler/rustc_hir_typeck/src/upvar.rs b/compiler/rustc_hir_typeck/src/upvar.rs
index e12a575d5..4a432328c 100644
--- a/compiler/rustc_hir_typeck/src/upvar.rs
+++ b/compiler/rustc_hir_typeck/src/upvar.rs
@@ -231,7 +231,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// We now fake capture information for all variables that are mentioned within the closure
// We do this after handling migrations so that min_captures computes before
- if !enable_precise_capture(self.tcx, span) {
+ if !enable_precise_capture(span) {
let mut capture_information: InferredCaptureInformation<'tcx> = Default::default();
if let Some(upvars) = self.tcx.upvars_mentioned(closure_def_id) {
@@ -265,7 +265,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// If we have an origin, store it.
if let Some(origin) = origin {
- let origin = if enable_precise_capture(self.tcx, span) {
+ let origin = if enable_precise_capture(span) {
(origin.0, origin.1)
} else {
(origin.0, Place { projections: vec![], ..origin.1 })
@@ -301,7 +301,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// Build a tuple (U0..Un) of the final upvar types U0..Un
// and unify the upvar tuple type in the closure with it:
- let final_tupled_upvars_type = self.tcx.mk_tup(final_upvar_tys.iter());
+ let final_tupled_upvars_type = self.tcx.mk_tup(&final_upvar_tys);
self.demand_suptype(span, substs.tupled_upvars_ty(), final_tupled_upvars_type);
let fake_reads = delegate
@@ -315,8 +315,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
self.typeck_results.borrow_mut().closure_size_eval.insert(
closure_def_id,
ClosureSizeProfileData {
- before_feature_tys: self.tcx.mk_tup(before_feature_tys.into_iter()),
- after_feature_tys: self.tcx.mk_tup(after_feature_tys.into_iter()),
+ before_feature_tys: self.tcx.mk_tup(&before_feature_tys),
+ after_feature_tys: self.tcx.mk_tup(&after_feature_tys),
},
);
}
@@ -526,10 +526,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
PlaceBase::Upvar(upvar_id) => upvar_id.var_path.hir_id,
base => bug!("Expected upvar, found={:?}", base),
};
+ let var_ident = self.tcx.hir().ident(var_hir_id);
let Some(min_cap_list) = root_var_min_capture_list.get_mut(&var_hir_id) else {
let mutability = self.determine_capture_mutability(&typeck_results, &place);
let min_cap_list = vec![ty::CapturedPlace {
+ var_ident,
place,
info: capture_info,
mutability,
@@ -628,6 +630,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
if !ancestor_found {
let mutability = self.determine_capture_mutability(&typeck_results, &place);
let captured_place = ty::CapturedPlace {
+ var_ident,
place,
info: updated_capture_info,
mutability,
@@ -1240,8 +1243,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
///
/// This will make more sense with an example:
///
- /// ```rust
- /// #![feature(capture_disjoint_fields)]
+ /// ```rust,edition2021
///
/// struct FancyInteger(i32); // This implements Drop
///
@@ -2221,7 +2223,7 @@ fn determine_place_ancestry_relation<'tcx>(
/// || drop(&*m.a.field_of_a)
/// // Here we really do want to capture `*m.a` because that outlives `'static`
///
-/// // If we capture `m`, then the closure no longer outlives `'static'
+/// // If we capture `m`, then the closure no longer outlives `'static`
/// // it is constrained to `'a`
/// }
/// ```
@@ -2247,12 +2249,10 @@ fn truncate_capture_for_optimization(
(place, curr_mode)
}
-/// Precise capture is enabled if the feature gate `capture_disjoint_fields` is enabled or if
-/// user is using Rust Edition 2021 or higher.
-///
+/// Precise capture is enabled if user is using Rust Edition 2021 or higher.
/// `span` is the span of the closure.
-fn enable_precise_capture(tcx: TyCtxt<'_>, span: Span) -> bool {
+fn enable_precise_capture(span: Span) -> bool {
// We use span here to ensure that if the closure was generated by a macro with a different
// edition.
- tcx.features().capture_disjoint_fields || span.rust_2021()
+ span.rust_2021()
}
diff --git a/compiler/rustc_hir_typeck/src/writeback.rs b/compiler/rustc_hir_typeck/src/writeback.rs
index 250f4cd3f..00348f3af 100644
--- a/compiler/rustc_hir_typeck/src/writeback.rs
+++ b/compiler/rustc_hir_typeck/src/writeback.rs
@@ -14,7 +14,7 @@ use rustc_middle::hir::place::Place as HirPlace;
use rustc_middle::mir::FakeReadCause;
use rustc_middle::ty::adjustment::{Adjust, Adjustment, PointerCast};
use rustc_middle::ty::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable};
-use rustc_middle::ty::visit::{TypeSuperVisitable, TypeVisitable};
+use rustc_middle::ty::visit::{TypeSuperVisitable, TypeVisitable, TypeVisitableExt};
use rustc_middle::ty::TypeckResults;
use rustc_middle::ty::{self, ClosureSizeProfileData, Ty, TyCtxt};
use rustc_span::symbol::sym;
@@ -40,8 +40,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
&self,
body: &'tcx hir::Body<'tcx>,
) -> &'tcx ty::TypeckResults<'tcx> {
- let item_id = self.tcx.hir().body_owner(body.id());
- let item_def_id = self.tcx.hir().local_def_id(item_id);
+ let item_def_id = self.tcx.hir().body_owner_def_id(body.id());
// This attribute causes us to dump some writeback information
// in the form of errors, which is used for unit tests.
@@ -55,7 +54,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// Type only exists for constants and statics, not functions.
match self.tcx.hir().body_owner_kind(item_def_id) {
hir::BodyOwnerKind::Const | hir::BodyOwnerKind::Static(_) => {
- wbcx.visit_node_id(body.value.span, item_id);
+ let item_hir_id = self.tcx.hir().local_def_id_to_hir_id(item_def_id);
+ wbcx.visit_node_id(body.value.span, item_hir_id);
}
hir::BodyOwnerKind::Closure | hir::BodyOwnerKind::Fn => (),
}
@@ -545,6 +545,10 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
assert_eq!(fcx_typeck_results.hir_owner, self.typeck_results.hir_owner);
self.typeck_results.generator_interior_types =
fcx_typeck_results.generator_interior_types.clone();
+ for (&expr_def_id, predicates) in fcx_typeck_results.generator_interior_predicates.iter() {
+ let predicates = self.resolve(predicates.clone(), &self.fcx.tcx.def_span(expr_def_id));
+ self.typeck_results.generator_interior_predicates.insert(expr_def_id, predicates);
+ }
}
#[instrument(skip(self), level = "debug")]
@@ -557,7 +561,7 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
struct RecursionChecker {
def_id: LocalDefId,
}
- impl<'tcx> ty::TypeVisitor<'tcx> for RecursionChecker {
+ impl<'tcx> ty::TypeVisitor<TyCtxt<'tcx>> for RecursionChecker {
type BreakTy = ();
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
if let ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }) = *t.kind() {
@@ -681,7 +685,7 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
fn resolve<T>(&mut self, x: T, span: &dyn Locatable) -> T
where
- T: TypeFoldable<'tcx>,
+ T: TypeFoldable<TyCtxt<'tcx>>,
{
let mut resolver = Resolver::new(self.fcx, span, self.body);
let x = x.fold_with(&mut resolver);
@@ -759,8 +763,8 @@ struct EraseEarlyRegions<'tcx> {
tcx: TyCtxt<'tcx>,
}
-impl<'tcx> TypeFolder<'tcx> for EraseEarlyRegions<'tcx> {
- fn tcx<'b>(&'b self) -> TyCtxt<'tcx> {
+impl<'tcx> TypeFolder<TyCtxt<'tcx>> for EraseEarlyRegions<'tcx> {
+ fn interner(&self) -> TyCtxt<'tcx> {
self.tcx
}
fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
@@ -775,8 +779,8 @@ impl<'tcx> TypeFolder<'tcx> for EraseEarlyRegions<'tcx> {
}
}
-impl<'cx, 'tcx> TypeFolder<'tcx> for Resolver<'cx, 'tcx> {
- fn tcx<'a>(&'a self) -> TyCtxt<'tcx> {
+impl<'cx, 'tcx> TypeFolder<TyCtxt<'tcx>> for Resolver<'cx, 'tcx> {
+ fn interner(&self) -> TyCtxt<'tcx> {
self.tcx
}
@@ -793,7 +797,7 @@ impl<'cx, 'tcx> TypeFolder<'tcx> for Resolver<'cx, 'tcx> {
debug!("Resolver::fold_ty: input type `{:?}` not fully resolvable", t);
let e = self.report_error(t);
self.replaced_with_error = Some(e);
- self.tcx().ty_error_with_guaranteed(e)
+ self.interner().ty_error(e)
}
}
}
@@ -810,7 +814,7 @@ impl<'cx, 'tcx> TypeFolder<'tcx> for Resolver<'cx, 'tcx> {
debug!("Resolver::fold_const: input const `{:?}` not fully resolvable", ct);
let e = self.report_error(ct);
self.replaced_with_error = Some(e);
- self.tcx().const_error_with_guaranteed(ct.ty(), e)
+ self.interner().const_error_with_guaranteed(ct.ty(), e)
}
}
}
diff --git a/compiler/rustc_incremental/Cargo.toml b/compiler/rustc_incremental/Cargo.toml
index 179e85f32..ad8939395 100644
--- a/compiler/rustc_incremental/Cargo.toml
+++ b/compiler/rustc_incremental/Cargo.toml
@@ -6,16 +6,17 @@ edition = "2021"
[lib]
[dependencies]
-rustc_graphviz = { path = "../rustc_graphviz" }
-tracing = "0.1"
rand = "0.8.4"
-rustc_middle = { path = "../rustc_middle" }
+rustc_ast = { path = "../rustc_ast" }
rustc_data_structures = { path = "../rustc_data_structures" }
+rustc_errors = { path = "../rustc_errors" }
+rustc_fs_util = { path = "../rustc_fs_util" }
+rustc_graphviz = { path = "../rustc_graphviz" }
rustc_hir = { path = "../rustc_hir" }
-rustc_serialize = { path = "../rustc_serialize" }
-rustc_ast = { path = "../rustc_ast" }
rustc_macros = { path = "../rustc_macros" }
-rustc_span = { path = "../rustc_span" }
-rustc_fs_util = { path = "../rustc_fs_util" }
+rustc_middle = { path = "../rustc_middle" }
+rustc_serialize = { path = "../rustc_serialize" }
rustc_session = { path = "../rustc_session" }
-rustc_errors = { path = "../rustc_errors" }
+rustc_span = { path = "../rustc_span" }
+thin-vec = "0.2.12"
+tracing = "0.1"
diff --git a/compiler/rustc_incremental/locales/en-US.ftl b/compiler/rustc_incremental/locales/en-US.ftl
new file mode 100644
index 000000000..4852ee0d9
--- /dev/null
+++ b/compiler/rustc_incremental/locales/en-US.ftl
@@ -0,0 +1,118 @@
+incremental_unrecognized_depnode = unrecognized `DepNode` variant: {$name}
+
+incremental_missing_depnode = missing `DepNode` variant
+
+incremental_missing_if_this_changed = no `#[rustc_if_this_changed]` annotation detected
+
+incremental_no_path = no path from `{$source}` to `{$target}`
+
+incremental_ok = OK
+
+incremental_unknown_reuse_kind = unknown cgu-reuse-kind `{$kind}` specified
+
+incremental_missing_query_depgraph =
+ found CGU-reuse attribute but `-Zquery-dep-graph` was not specified
+
+incremental_malformed_cgu_name =
+ found malformed codegen unit name `{$user_path}`. codegen units names must always start with the name of the crate (`{$crate_name}` in this case).
+
+incremental_no_module_named =
+ no module named `{$user_path}` (mangled: {$cgu_name}). available modules: {$cgu_names}
+
+incremental_field_associated_value_expected = associated value expected for `{$name}`
+
+incremental_no_field = no field `{$name}`
+
+incremental_assertion_auto =
+ `except` specified DepNodes that can not be affected for \"{$name}\": \"{$e}\"
+
+incremental_undefined_clean_dirty_assertions_item =
+ clean/dirty auto-assertions not yet defined for Node::Item.node={$kind}
+
+incremental_undefined_clean_dirty_assertions =
+ clean/dirty auto-assertions not yet defined for {$kind}
+
+incremental_repeated_depnode_label = dep-node label `{$label}` is repeated
+
+incremental_unrecognized_depnode_label = dep-node label `{$label}` not recognized
+
+incremental_not_dirty = `{$dep_node_str}` should be dirty but is not
+
+incremental_not_clean = `{$dep_node_str}` should be clean but is not
+
+incremental_not_loaded = `{$dep_node_str}` should have been loaded from disk but it was not
+
+incremental_unknown_item = unknown item `{$name}`
+
+incremental_no_cfg = no cfg attribute
+
+incremental_associated_value_expected_for = associated value expected for `{$ident}`
+
+incremental_associated_value_expected = expected an associated value
+
+incremental_unchecked_clean = found unchecked `#[rustc_clean]` attribute
+
+incremental_delete_old = unable to delete old {$name} at `{$path}`: {$err}
+
+incremental_create_new = failed to create {$name} at `{$path}`: {$err}
+
+incremental_write_new = failed to write {$name} to `{$path}`: {$err}
+
+incremental_canonicalize_path = incremental compilation: error canonicalizing path `{$path}`: {$err}
+
+incremental_create_incr_comp_dir =
+ could not create incremental compilation {$tag} directory `{$path}`: {$err}
+
+incremental_create_lock =
+ incremental compilation: could not create session directory lock file: {$lock_err}
+incremental_lock_unsupported =
+ the filesystem for the incremental path at {$session_dir} does not appear to support locking, consider changing the incremental path to a filesystem that supports locking or disable incremental compilation
+incremental_cargo_help_1 =
+ incremental compilation can be disabled by setting the environment variable CARGO_INCREMENTAL=0 (see https://doc.rust-lang.org/cargo/reference/profiles.html#incremental)
+incremental_cargo_help_2 =
+ the entire build directory can be changed to a different filesystem by setting the environment variable CARGO_TARGET_DIR to a different path (see https://doc.rust-lang.org/cargo/reference/config.html#buildtarget-dir)
+
+incremental_delete_lock =
+ error deleting lock file for incremental compilation session directory `{$path}`: {$err}
+
+incremental_hard_link_failed =
+ hard linking files in the incremental compilation cache failed. copying files instead. consider moving the cache directory to a file system which supports hard linking in session dir `{$path}`
+
+incremental_delete_partial = failed to delete partly initialized session dir `{$path}`: {$err}
+
+incremental_delete_full = error deleting incremental compilation session directory `{$path}`: {$err}
+
+incremental_finalize = error finalizing incremental compilation session directory `{$path}`: {$err}
+
+incremental_invalid_gc_failed =
+ failed to garbage collect invalid incremental compilation session directory `{$path}`: {$err}
+
+incremental_finalized_gc_failed =
+ failed to garbage collect finalized incremental compilation session directory `{$path}`: {$err}
+
+incremental_session_gc_failed =
+ failed to garbage collect incremental compilation session directory `{$path}`: {$err}
+
+incremental_assert_not_loaded =
+ we asserted that the incremental cache should not be loaded, but it was loaded
+
+incremental_assert_loaded =
+ we asserted that an existing incremental cache directory should be successfully loaded, but it was not
+
+incremental_delete_incompatible =
+ failed to delete invalidated or incompatible incremental compilation session directory contents `{$path}`: {$err}
+
+incremental_load_dep_graph = could not load dep-graph from `{$path}`: {$err}
+
+incremental_decode_incr_cache = could not decode incremental cache: {$err}
+
+incremental_write_dep_graph = failed to write dependency graph to `{$path}`: {$err}
+
+incremental_move_dep_graph = failed to move dependency graph from `{$from}` to `{$to}`: {$err}
+
+incremental_create_dep_graph = failed to create dependency graph at `{$path}`: {$err}
+
+incremental_copy_workproduct_to_cache =
+ error copying object file `{$from}` to incremental directory as `{$to}`: {$err}
+
+incremental_delete_workproduct = file-system error deleting outdated file `{$path}`: {$err}
diff --git a/compiler/rustc_incremental/src/assert_dep_graph.rs b/compiler/rustc_incremental/src/assert_dep_graph.rs
index 33a9a0cab..22bd12f2e 100644
--- a/compiler/rustc_incremental/src/assert_dep_graph.rs
+++ b/compiler/rustc_incremental/src/assert_dep_graph.rs
@@ -33,12 +33,13 @@
//! fn baz() { foo(); }
//! ```
+use crate::errors;
use rustc_ast as ast;
use rustc_data_structures::fx::FxHashSet;
use rustc_data_structures::graph::implementation::{Direction, NodeIndex, INCOMING, OUTGOING};
use rustc_graphviz as dot;
use rustc_hir as hir;
-use rustc_hir::def_id::DefId;
+use rustc_hir::def_id::{DefId, LocalDefId, CRATE_DEF_ID};
use rustc_hir::intravisit::{self, Visitor};
use rustc_middle::dep_graph::{
DepGraphQuery, DepKind, DepNode, DepNodeExt, DepNodeFilter, EdgeFilter,
@@ -74,7 +75,7 @@ pub fn assert_dep_graph(tcx: TyCtxt<'_>) {
let (if_this_changed, then_this_would_need) = {
let mut visitor =
IfThisChanged { tcx, if_this_changed: vec![], then_this_would_need: vec![] };
- visitor.process_attrs(hir::CRATE_HIR_ID);
+ visitor.process_attrs(CRATE_DEF_ID);
tcx.hir().visit_all_item_likes_in_crate(&mut visitor);
(visitor.if_this_changed, visitor.then_this_would_need)
};
@@ -119,9 +120,9 @@ impl<'tcx> IfThisChanged<'tcx> {
value
}
- fn process_attrs(&mut self, hir_id: hir::HirId) {
- let def_id = self.tcx.hir().local_def_id(hir_id);
+ fn process_attrs(&mut self, def_id: LocalDefId) {
let def_path_hash = self.tcx.def_path_hash(def_id.to_def_id());
+ let hir_id = self.tcx.hir().local_def_id_to_hir_id(def_id);
let attrs = self.tcx.hir().attrs(hir_id);
for attr in attrs {
if attr.has_name(sym::rustc_if_this_changed) {
@@ -133,12 +134,10 @@ impl<'tcx> IfThisChanged<'tcx> {
Some(n) => {
match DepNode::from_label_string(self.tcx, n.as_str(), def_path_hash) {
Ok(n) => n,
- Err(()) => {
- self.tcx.sess.span_fatal(
- attr.span,
- &format!("unrecognized DepNode variant {:?}", n),
- );
- }
+ Err(()) => self.tcx.sess.emit_fatal(errors::UnrecognizedDepNode {
+ span: attr.span,
+ name: n,
+ }),
}
}
};
@@ -149,16 +148,14 @@ impl<'tcx> IfThisChanged<'tcx> {
Some(n) => {
match DepNode::from_label_string(self.tcx, n.as_str(), def_path_hash) {
Ok(n) => n,
- Err(()) => {
- self.tcx.sess.span_fatal(
- attr.span,
- &format!("unrecognized DepNode variant {:?}", n),
- );
- }
+ Err(()) => self.tcx.sess.emit_fatal(errors::UnrecognizedDepNode {
+ span: attr.span,
+ name: n,
+ }),
}
}
None => {
- self.tcx.sess.span_fatal(attr.span, "missing DepNode variant");
+ self.tcx.sess.emit_fatal(errors::MissingDepNode { span: attr.span });
}
};
self.then_this_would_need.push((
@@ -180,22 +177,22 @@ impl<'tcx> Visitor<'tcx> for IfThisChanged<'tcx> {
}
fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {
- self.process_attrs(item.hir_id());
+ self.process_attrs(item.owner_id.def_id);
intravisit::walk_item(self, item);
}
fn visit_trait_item(&mut self, trait_item: &'tcx hir::TraitItem<'tcx>) {
- self.process_attrs(trait_item.hir_id());
+ self.process_attrs(trait_item.owner_id.def_id);
intravisit::walk_trait_item(self, trait_item);
}
fn visit_impl_item(&mut self, impl_item: &'tcx hir::ImplItem<'tcx>) {
- self.process_attrs(impl_item.hir_id());
+ self.process_attrs(impl_item.owner_id.def_id);
intravisit::walk_impl_item(self, impl_item);
}
fn visit_field_def(&mut self, s: &'tcx hir::FieldDef<'tcx>) {
- self.process_attrs(s.hir_id);
+ self.process_attrs(s.def_id);
intravisit::walk_field_def(self, s);
}
}
@@ -204,7 +201,7 @@ fn check_paths<'tcx>(tcx: TyCtxt<'tcx>, if_this_changed: &Sources, then_this_wou
// Return early here so as not to construct the query, which is not cheap.
if if_this_changed.is_empty() {
for &(target_span, _, _, _) in then_this_would_need {
- tcx.sess.span_err(target_span, "no `#[rustc_if_this_changed]` annotation detected");
+ tcx.sess.emit_err(errors::MissingIfThisChanged { span: target_span });
}
return;
}
@@ -213,16 +210,13 @@ fn check_paths<'tcx>(tcx: TyCtxt<'tcx>, if_this_changed: &Sources, then_this_wou
let dependents = query.transitive_predecessors(source_dep_node);
for &(target_span, ref target_pass, _, ref target_dep_node) in then_this_would_need {
if !dependents.contains(&target_dep_node) {
- tcx.sess.span_err(
- target_span,
- &format!(
- "no path from `{}` to `{}`",
- tcx.def_path_str(source_def_id),
- target_pass
- ),
- );
+ tcx.sess.emit_err(errors::NoPath {
+ span: target_span,
+ source: tcx.def_path_str(source_def_id),
+ target: *target_pass,
+ });
} else {
- tcx.sess.span_err(target_span, "OK");
+ tcx.sess.emit_err(errors::Ok { span: target_span });
}
}
}
diff --git a/compiler/rustc_incremental/src/assert_module_sources.rs b/compiler/rustc_incremental/src/assert_module_sources.rs
index 89d419bc8..c550e553b 100644
--- a/compiler/rustc_incremental/src/assert_module_sources.rs
+++ b/compiler/rustc_incremental/src/assert_module_sources.rs
@@ -18,10 +18,11 @@
//! the HIR doesn't change as a result of the annotations, which might
//! perturb the reuse results.
//!
-//! `#![rustc_expected_cgu_reuse(module="spike", cfg="rpass2", kind="post-lto")]
+//! `#![rustc_expected_cgu_reuse(module="spike", cfg="rpass2", kind="post-lto")]`
//! allows for doing a more fine-grained check to see if pre- or post-lto data
//! was re-used.
+use crate::errors;
use rustc_ast as ast;
use rustc_data_structures::fx::FxHashSet;
use rustc_hir::def_id::LOCAL_CRATE;
@@ -29,6 +30,7 @@ use rustc_middle::mir::mono::CodegenUnitNameBuilder;
use rustc_middle::ty::TyCtxt;
use rustc_session::cgu_reuse_tracker::*;
use rustc_span::symbol::{sym, Symbol};
+use thin_vec::ThinVec;
#[allow(missing_docs)]
pub fn assert_module_sources(tcx: TyCtxt<'_>) {
@@ -66,10 +68,9 @@ impl<'tcx> AssertModuleSource<'tcx> {
sym::post_dash_lto => (CguReuse::PostLto, ComparisonKind::Exact),
sym::any => (CguReuse::PreLto, ComparisonKind::AtLeast),
other => {
- self.tcx.sess.span_fatal(
- attr.span,
- &format!("unknown cgu-reuse-kind `{}` specified", other),
- );
+ self.tcx
+ .sess
+ .emit_fatal(errors::UnknownReuseKind { span: attr.span, kind: other });
}
}
} else {
@@ -77,10 +78,7 @@ impl<'tcx> AssertModuleSource<'tcx> {
};
if !self.tcx.sess.opts.unstable_opts.query_dep_graph {
- self.tcx.sess.span_fatal(
- attr.span,
- "found CGU-reuse attribute but `-Zquery-dep-graph` was not specified",
- );
+ self.tcx.sess.emit_fatal(errors::MissingQueryDepGraph { span: attr.span });
}
if !self.check_config(attr) {
@@ -92,13 +90,11 @@ impl<'tcx> AssertModuleSource<'tcx> {
let crate_name = self.tcx.crate_name(LOCAL_CRATE).to_string();
if !user_path.starts_with(&crate_name) {
- let msg = format!(
- "Found malformed codegen unit name `{}`. \
- Codegen units names must always start with the name of the \
- crate (`{}` in this case).",
- user_path, crate_name
- );
- self.tcx.sess.span_fatal(attr.span, &msg);
+ self.tcx.sess.emit_fatal(errors::MalformedCguName {
+ span: attr.span,
+ user_path,
+ crate_name,
+ });
}
// Split of the "special suffix" if there is one.
@@ -125,15 +121,12 @@ impl<'tcx> AssertModuleSource<'tcx> {
let mut cgu_names: Vec<&str> =
self.available_cgus.iter().map(|cgu| cgu.as_str()).collect();
cgu_names.sort();
- self.tcx.sess.span_err(
- attr.span,
- &format!(
- "no module named `{}` (mangled: {}). Available modules: {}",
- user_path,
- cgu_name,
- cgu_names.join(", ")
- ),
- );
+ self.tcx.sess.emit_err(errors::NoModuleNamed {
+ span: attr.span,
+ user_path,
+ cgu_name,
+ cgu_names: cgu_names.join(", "),
+ });
}
self.tcx.sess.cgu_reuse_tracker.set_expectation(
@@ -146,20 +139,20 @@ impl<'tcx> AssertModuleSource<'tcx> {
}
fn field(&self, attr: &ast::Attribute, name: Symbol) -> Symbol {
- for item in attr.meta_item_list().unwrap_or_else(Vec::new) {
+ for item in attr.meta_item_list().unwrap_or_else(ThinVec::new) {
if item.has_name(name) {
if let Some(value) = item.value_str() {
return value;
} else {
- self.tcx.sess.span_fatal(
- item.span(),
- &format!("associated value expected for `{}`", name),
- );
+ self.tcx.sess.emit_fatal(errors::FieldAssociatedValueExpected {
+ span: item.span(),
+ name,
+ });
}
}
}
- self.tcx.sess.span_fatal(attr.span, &format!("no field `{}`", name));
+ self.tcx.sess.emit_fatal(errors::NoField { span: attr.span, name });
}
/// Scan for a `cfg="foo"` attribute and check whether we have a
diff --git a/compiler/rustc_incremental/src/errors.rs b/compiler/rustc_incremental/src/errors.rs
new file mode 100644
index 000000000..deb876783
--- /dev/null
+++ b/compiler/rustc_incremental/src/errors.rs
@@ -0,0 +1,364 @@
+use rustc_macros::Diagnostic;
+use rustc_span::{symbol::Ident, Span, Symbol};
+use std::path::{Path, PathBuf};
+
+#[derive(Diagnostic)]
+#[diag(incremental_unrecognized_depnode)]
+pub struct UnrecognizedDepNode {
+ #[primary_span]
+ pub span: Span,
+ pub name: Symbol,
+}
+
+#[derive(Diagnostic)]
+#[diag(incremental_missing_depnode)]
+pub struct MissingDepNode {
+ #[primary_span]
+ pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(incremental_missing_if_this_changed)]
+pub struct MissingIfThisChanged {
+ #[primary_span]
+ pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(incremental_ok)]
+pub struct Ok {
+ #[primary_span]
+ pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(incremental_no_path)]
+pub struct NoPath {
+ #[primary_span]
+ pub span: Span,
+ pub target: Symbol,
+ pub source: String,
+}
+
+#[derive(Diagnostic)]
+#[diag(incremental_unknown_reuse_kind)]
+pub struct UnknownReuseKind {
+ #[primary_span]
+ pub span: Span,
+ pub kind: Symbol,
+}
+
+#[derive(Diagnostic)]
+#[diag(incremental_missing_query_depgraph)]
+pub struct MissingQueryDepGraph {
+ #[primary_span]
+ pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(incremental_malformed_cgu_name)]
+pub struct MalformedCguName {
+ #[primary_span]
+ pub span: Span,
+ pub user_path: String,
+ pub crate_name: String,
+}
+
+#[derive(Diagnostic)]
+#[diag(incremental_no_module_named)]
+pub struct NoModuleNamed<'a> {
+ #[primary_span]
+ pub span: Span,
+ pub user_path: &'a str,
+ pub cgu_name: Symbol,
+ pub cgu_names: String,
+}
+
+#[derive(Diagnostic)]
+#[diag(incremental_field_associated_value_expected)]
+pub struct FieldAssociatedValueExpected {
+ #[primary_span]
+ pub span: Span,
+ pub name: Symbol,
+}
+
+#[derive(Diagnostic)]
+#[diag(incremental_no_field)]
+pub struct NoField {
+ #[primary_span]
+ pub span: Span,
+ pub name: Symbol,
+}
+
+#[derive(Diagnostic)]
+#[diag(incremental_assertion_auto)]
+pub struct AssertionAuto<'a> {
+ #[primary_span]
+ pub span: Span,
+ pub name: &'a str,
+ pub e: &'a str,
+}
+
+#[derive(Diagnostic)]
+#[diag(incremental_undefined_clean_dirty_assertions_item)]
+pub struct UndefinedCleanDirtyItem {
+ #[primary_span]
+ pub span: Span,
+ pub kind: String,
+}
+
+#[derive(Diagnostic)]
+#[diag(incremental_undefined_clean_dirty_assertions)]
+pub struct UndefinedCleanDirty {
+ #[primary_span]
+ pub span: Span,
+ pub kind: String,
+}
+
+#[derive(Diagnostic)]
+#[diag(incremental_repeated_depnode_label)]
+pub struct RepeatedDepNodeLabel<'a> {
+ #[primary_span]
+ pub span: Span,
+ pub label: &'a str,
+}
+
+#[derive(Diagnostic)]
+#[diag(incremental_unrecognized_depnode_label)]
+pub struct UnrecognizedDepNodeLabel<'a> {
+ #[primary_span]
+ pub span: Span,
+ pub label: &'a str,
+}
+
+#[derive(Diagnostic)]
+#[diag(incremental_not_dirty)]
+pub struct NotDirty<'a> {
+ #[primary_span]
+ pub span: Span,
+ pub dep_node_str: &'a str,
+}
+
+#[derive(Diagnostic)]
+#[diag(incremental_not_clean)]
+pub struct NotClean<'a> {
+ #[primary_span]
+ pub span: Span,
+ pub dep_node_str: &'a str,
+}
+
+#[derive(Diagnostic)]
+#[diag(incremental_not_loaded)]
+pub struct NotLoaded<'a> {
+ #[primary_span]
+ pub span: Span,
+ pub dep_node_str: &'a str,
+}
+
+#[derive(Diagnostic)]
+#[diag(incremental_unknown_item)]
+pub struct UnknownItem {
+ #[primary_span]
+ pub span: Span,
+ pub name: Symbol,
+}
+
+#[derive(Diagnostic)]
+#[diag(incremental_no_cfg)]
+pub struct NoCfg {
+ #[primary_span]
+ pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(incremental_associated_value_expected_for)]
+pub struct AssociatedValueExpectedFor {
+ #[primary_span]
+ pub span: Span,
+ pub ident: Ident,
+}
+
+#[derive(Diagnostic)]
+#[diag(incremental_associated_value_expected)]
+pub struct AssociatedValueExpected {
+ #[primary_span]
+ pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(incremental_unchecked_clean)]
+pub struct UncheckedClean {
+ #[primary_span]
+ pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(incremental_delete_old)]
+pub struct DeleteOld<'a> {
+ pub name: &'a str,
+ pub path: PathBuf,
+ pub err: std::io::Error,
+}
+
+#[derive(Diagnostic)]
+#[diag(incremental_create_new)]
+pub struct CreateNew<'a> {
+ pub name: &'a str,
+ pub path: PathBuf,
+ pub err: std::io::Error,
+}
+
+#[derive(Diagnostic)]
+#[diag(incremental_write_new)]
+pub struct WriteNew<'a> {
+ pub name: &'a str,
+ pub path: PathBuf,
+ pub err: std::io::Error,
+}
+
+#[derive(Diagnostic)]
+#[diag(incremental_canonicalize_path)]
+pub struct CanonicalizePath {
+ pub path: PathBuf,
+ pub err: std::io::Error,
+}
+
+#[derive(Diagnostic)]
+#[diag(incremental_create_incr_comp_dir)]
+pub struct CreateIncrCompDir<'a> {
+ pub tag: &'a str,
+ pub path: &'a Path,
+ pub err: std::io::Error,
+}
+
+#[derive(Diagnostic)]
+#[diag(incremental_create_lock)]
+pub struct CreateLock<'a> {
+ pub lock_err: std::io::Error,
+ pub session_dir: &'a Path,
+ #[note(incremental_lock_unsupported)]
+ pub is_unsupported_lock: Option<()>,
+ #[help(incremental_cargo_help_1)]
+ #[help(incremental_cargo_help_2)]
+ pub is_cargo: Option<()>,
+}
+
+#[derive(Diagnostic)]
+#[diag(incremental_delete_lock)]
+pub struct DeleteLock<'a> {
+ pub path: &'a Path,
+ pub err: std::io::Error,
+}
+
+#[derive(Diagnostic)]
+#[diag(incremental_hard_link_failed)]
+pub struct HardLinkFailed<'a> {
+ pub path: &'a Path,
+}
+
+#[derive(Diagnostic)]
+#[diag(incremental_delete_partial)]
+pub struct DeletePartial<'a> {
+ pub path: &'a Path,
+ pub err: std::io::Error,
+}
+
+#[derive(Diagnostic)]
+#[diag(incremental_delete_full)]
+pub struct DeleteFull<'a> {
+ pub path: &'a Path,
+ pub err: std::io::Error,
+}
+
+#[derive(Diagnostic)]
+#[diag(incremental_finalize)]
+pub struct Finalize<'a> {
+ pub path: &'a Path,
+ pub err: std::io::Error,
+}
+
+#[derive(Diagnostic)]
+#[diag(incremental_invalid_gc_failed)]
+pub struct InvalidGcFailed<'a> {
+ pub path: &'a Path,
+ pub err: std::io::Error,
+}
+
+#[derive(Diagnostic)]
+#[diag(incremental_finalized_gc_failed)]
+pub struct FinalizedGcFailed<'a> {
+ pub path: &'a Path,
+ pub err: std::io::Error,
+}
+
+#[derive(Diagnostic)]
+#[diag(incremental_session_gc_failed)]
+pub struct SessionGcFailed<'a> {
+ pub path: &'a Path,
+ pub err: std::io::Error,
+}
+
+#[derive(Diagnostic)]
+#[diag(incremental_assert_not_loaded)]
+pub struct AssertNotLoaded;
+
+#[derive(Diagnostic)]
+#[diag(incremental_assert_loaded)]
+pub struct AssertLoaded;
+
+#[derive(Diagnostic)]
+#[diag(incremental_delete_incompatible)]
+pub struct DeleteIncompatible {
+ pub path: PathBuf,
+ pub err: std::io::Error,
+}
+
+#[derive(Diagnostic)]
+#[diag(incremental_load_dep_graph)]
+pub struct LoadDepGraph {
+ pub path: PathBuf,
+ pub err: std::io::Error,
+}
+
+#[derive(Diagnostic)]
+#[diag(incremental_decode_incr_cache)]
+pub struct DecodeIncrCache {
+ pub err: String,
+}
+
+#[derive(Diagnostic)]
+#[diag(incremental_write_dep_graph)]
+pub struct WriteDepGraph<'a> {
+ pub path: &'a Path,
+ pub err: std::io::Error,
+}
+
+#[derive(Diagnostic)]
+#[diag(incremental_move_dep_graph)]
+pub struct MoveDepGraph<'a> {
+ pub from: &'a Path,
+ pub to: &'a Path,
+ pub err: std::io::Error,
+}
+
+#[derive(Diagnostic)]
+#[diag(incremental_create_dep_graph)]
+pub struct CreateDepGraph<'a> {
+ pub path: &'a Path,
+ pub err: std::io::Error,
+}
+
+#[derive(Diagnostic)]
+#[diag(incremental_copy_workproduct_to_cache)]
+pub struct CopyWorkProductToCache<'a> {
+ pub from: &'a Path,
+ pub to: &'a Path,
+ pub err: std::io::Error,
+}
+
+#[derive(Diagnostic)]
+#[diag(incremental_delete_workproduct)]
+pub struct DeleteWorkProduct<'a> {
+ pub path: &'a Path,
+ pub err: std::io::Error,
+}
diff --git a/compiler/rustc_incremental/src/lib.rs b/compiler/rustc_incremental/src/lib.rs
index 83dd9a67e..511e466c2 100644
--- a/compiler/rustc_incremental/src/lib.rs
+++ b/compiler/rustc_incremental/src/lib.rs
@@ -2,8 +2,11 @@
#![deny(missing_docs)]
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
+#![feature(never_type)]
#![recursion_limit = "256"]
#![allow(rustc::potential_query_instability)]
+#![deny(rustc::untranslatable_diagnostic)]
+#![deny(rustc::diagnostic_outside_of_impl)]
#[macro_use]
extern crate rustc_middle;
@@ -12,6 +15,7 @@ extern crate tracing;
mod assert_dep_graph;
pub mod assert_module_sources;
+mod errors;
mod persist;
use assert_dep_graph::assert_dep_graph;
@@ -27,3 +31,8 @@ pub use persist::save_dep_graph;
pub use persist::save_work_product_index;
pub use persist::LoadResult;
pub use persist::{build_dep_graph, load_dep_graph, DepGraphFuture};
+
+use rustc_errors::{DiagnosticMessage, SubdiagnosticMessage};
+use rustc_macros::fluent_messages;
+
+fluent_messages! { "../locales/en-US.ftl" }
diff --git a/compiler/rustc_incremental/src/persist/dirty_clean.rs b/compiler/rustc_incremental/src/persist/dirty_clean.rs
index ed7b272b1..b839416c9 100644
--- a/compiler/rustc_incremental/src/persist/dirty_clean.rs
+++ b/compiler/rustc_incremental/src/persist/dirty_clean.rs
@@ -19,6 +19,7 @@
//! Errors are reported if we are in the suitable configuration but
//! the required condition is not met.
+use crate::errors;
use rustc_ast::{self as ast, Attribute, NestedMetaItem};
use rustc_data_structures::fx::FxHashSet;
use rustc_hir::def_id::LocalDefId;
@@ -30,6 +31,8 @@ use rustc_middle::hir::nested_filter;
use rustc_middle::ty::TyCtxt;
use rustc_span::symbol::{sym, Symbol};
use rustc_span::Span;
+use std::iter::FromIterator;
+use thin_vec::ThinVec;
const LOADED_FROM_DISK: Symbol = sym::loaded_from_disk;
const EXCEPT: Symbol = sym::except;
@@ -196,11 +199,7 @@ impl<'tcx> DirtyCleanVisitor<'tcx> {
let loaded_from_disk = self.loaded_from_disk(attr);
for e in except.iter() {
if !auto.remove(e) {
- let msg = format!(
- "`except` specified DepNodes that can not be affected for \"{}\": \"{}\"",
- name, e
- );
- self.tcx.sess.span_fatal(attr.span, &msg);
+ self.tcx.sess.emit_fatal(errors::AssertionAuto { span: attr.span, name, e });
}
}
Assertion { clean: auto, dirty: except, loaded_from_disk }
@@ -208,7 +207,7 @@ impl<'tcx> DirtyCleanVisitor<'tcx> {
/// `loaded_from_disk=` attribute value
fn loaded_from_disk(&self, attr: &Attribute) -> Labels {
- for item in attr.meta_item_list().unwrap_or_else(Vec::new) {
+ for item in attr.meta_item_list().unwrap_or_else(ThinVec::new) {
if item.has_name(LOADED_FROM_DISK) {
let value = expect_associated_value(self.tcx, &item);
return self.resolve_labels(&item, value);
@@ -220,7 +219,7 @@ impl<'tcx> DirtyCleanVisitor<'tcx> {
/// `except=` attribute value
fn except(&self, attr: &Attribute) -> Labels {
- for item in attr.meta_item_list().unwrap_or_else(Vec::new) {
+ for item in attr.meta_item_list().unwrap_or_else(ThinVec::new) {
if item.has_name(EXCEPT) {
let value = expect_associated_value(self.tcx, &item);
return self.resolve_labels(&item, value);
@@ -282,14 +281,10 @@ impl<'tcx> DirtyCleanVisitor<'tcx> {
// An implementation, eg `impl<A> Trait for Foo { .. }`
HirItem::Impl { .. } => ("ItemKind::Impl", LABELS_IMPL),
- _ => self.tcx.sess.span_fatal(
- attr.span,
- &format!(
- "clean/dirty auto-assertions not yet defined \
- for Node::Item.node={:?}",
- item.kind
- ),
- ),
+ _ => self.tcx.sess.emit_fatal(errors::UndefinedCleanDirtyItem {
+ span: attr.span,
+ kind: format!("{:?}", item.kind),
+ }),
}
}
HirNode::TraitItem(item) => match item.kind {
@@ -302,10 +297,10 @@ impl<'tcx> DirtyCleanVisitor<'tcx> {
ImplItemKind::Const(..) => ("NodeImplConst", LABELS_CONST_IN_IMPL),
ImplItemKind::Type(..) => ("NodeImplType", LABELS_CONST_IN_IMPL),
},
- _ => self.tcx.sess.span_fatal(
- attr.span,
- &format!("clean/dirty auto-assertions not yet defined for {:?}", node),
- ),
+ _ => self.tcx.sess.emit_fatal(errors::UndefinedCleanDirty {
+ span: attr.span,
+ kind: format!("{:?}", node),
+ }),
};
let labels =
Labels::from_iter(labels.iter().flat_map(|s| s.iter().map(|l| (*l).to_string())));
@@ -318,16 +313,15 @@ impl<'tcx> DirtyCleanVisitor<'tcx> {
let label = label.trim();
if DepNode::has_label_string(label) {
if out.contains(label) {
- self.tcx.sess.span_fatal(
- item.span(),
- &format!("dep-node label `{}` is repeated", label),
- );
+ self.tcx
+ .sess
+ .emit_fatal(errors::RepeatedDepNodeLabel { span: item.span(), label });
}
out.insert(label.to_string());
} else {
self.tcx
.sess
- .span_fatal(item.span(), &format!("dep-node label `{}` not recognized", label));
+ .emit_fatal(errors::UnrecognizedDepNodeLabel { span: item.span(), label });
}
}
out
@@ -348,7 +342,7 @@ impl<'tcx> DirtyCleanVisitor<'tcx> {
let dep_node_str = self.dep_node_str(&dep_node);
self.tcx
.sess
- .span_err(item_span, &format!("`{}` should be dirty but is not", dep_node_str));
+ .emit_err(errors::NotDirty { span: item_span, dep_node_str: &dep_node_str });
}
}
@@ -359,7 +353,7 @@ impl<'tcx> DirtyCleanVisitor<'tcx> {
let dep_node_str = self.dep_node_str(&dep_node);
self.tcx
.sess
- .span_err(item_span, &format!("`{}` should be clean but is not", dep_node_str));
+ .emit_err(errors::NotClean { span: item_span, dep_node_str: &dep_node_str });
}
}
@@ -368,10 +362,9 @@ impl<'tcx> DirtyCleanVisitor<'tcx> {
if !self.tcx.dep_graph.debug_was_loaded_from_disk(dep_node) {
let dep_node_str = self.dep_node_str(&dep_node);
- self.tcx.sess.span_err(
- item_span,
- &format!("`{}` should have been loaded from disk but it was not", dep_node_str),
- );
+ self.tcx
+ .sess
+ .emit_err(errors::NotLoaded { span: item_span, dep_node_str: &dep_node_str });
}
}
@@ -406,18 +399,18 @@ fn check_config(tcx: TyCtxt<'_>, attr: &Attribute) -> bool {
let config = &tcx.sess.parse_sess.config;
debug!("check_config: config={:?}", config);
let mut cfg = None;
- for item in attr.meta_item_list().unwrap_or_else(Vec::new) {
+ for item in attr.meta_item_list().unwrap_or_else(ThinVec::new) {
if item.has_name(CFG) {
let value = expect_associated_value(tcx, &item);
debug!("check_config: searching for cfg {:?}", value);
cfg = Some(config.contains(&(value, None)));
} else if !(item.has_name(EXCEPT) || item.has_name(LOADED_FROM_DISK)) {
- tcx.sess.span_err(attr.span, &format!("unknown item `{}`", item.name_or_empty()));
+ tcx.sess.emit_err(errors::UnknownItem { span: attr.span, name: item.name_or_empty() });
}
}
match cfg {
- None => tcx.sess.span_fatal(attr.span, "no cfg attribute"),
+ None => tcx.sess.emit_fatal(errors::NoCfg { span: attr.span }),
Some(c) => c,
}
}
@@ -426,13 +419,11 @@ fn expect_associated_value(tcx: TyCtxt<'_>, item: &NestedMetaItem) -> Symbol {
if let Some(value) = item.value_str() {
value
} else {
- let msg = if let Some(ident) = item.ident() {
- format!("associated value expected for `{}`", ident)
+ if let Some(ident) = item.ident() {
+ tcx.sess.emit_fatal(errors::AssociatedValueExpectedFor { span: item.span(), ident });
} else {
- "expected an associated value".to_string()
- };
-
- tcx.sess.span_fatal(item.span(), &msg);
+ tcx.sess.emit_fatal(errors::AssociatedValueExpected { span: item.span() });
+ }
}
}
@@ -456,7 +447,7 @@ impl<'tcx> FindAllAttrs<'tcx> {
fn report_unchecked_attrs(&self, mut checked_attrs: FxHashSet<ast::AttrId>) {
for attr in &self.found_attrs {
if !checked_attrs.contains(&attr.id) {
- self.tcx.sess.span_err(attr.span, "found unchecked `#[rustc_clean]` attribute");
+ self.tcx.sess.emit_err(errors::UncheckedClean { span: attr.span });
checked_attrs.insert(attr.id);
}
}
diff --git a/compiler/rustc_incremental/src/persist/file_format.rs b/compiler/rustc_incremental/src/persist/file_format.rs
index 2dbd4b6bc..dc981c617 100644
--- a/compiler/rustc_incremental/src/persist/file_format.rs
+++ b/compiler/rustc_incremental/src/persist/file_format.rs
@@ -9,15 +9,15 @@
//! compiler versions don't change frequently for the typical user, being
//! conservative here practically has no downside.
-use std::env;
-use std::fs;
-use std::io::{self, Read};
-use std::path::{Path, PathBuf};
-
+use crate::errors;
use rustc_data_structures::memmap::Mmap;
use rustc_serialize::opaque::{FileEncodeResult, FileEncoder};
use rustc_serialize::Encoder;
use rustc_session::Session;
+use std::env;
+use std::fs;
+use std::io::{self, Read};
+use std::path::{Path, PathBuf};
/// The first few bytes of files generated by incremental compilation.
const FILE_MAGIC: &[u8] = b"RSIC";
@@ -60,12 +60,7 @@ where
}
Err(err) if err.kind() == io::ErrorKind::NotFound => (),
Err(err) => {
- sess.err(&format!(
- "unable to delete old {} at `{}`: {}",
- name,
- path_buf.display(),
- err
- ));
+ sess.emit_err(errors::DeleteOld { name, path: path_buf, err });
return;
}
}
@@ -73,7 +68,7 @@ where
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));
+ sess.emit_err(errors::CreateNew { name, path: path_buf, err });
return;
}
};
@@ -90,7 +85,7 @@ where
debug!("save: data written to disk successfully");
}
Err(err) => {
- sess.err(&format!("failed to write {} to `{}`: {}", name, path_buf.display(), err));
+ sess.emit_err(errors::WriteNew { name, path: path_buf, err });
}
}
}
diff --git a/compiler/rustc_incremental/src/persist/fs.rs b/compiler/rustc_incremental/src/persist/fs.rs
index 1fd2b9b0d..73d7e3bec 100644
--- a/compiler/rustc_incremental/src/persist/fs.rs
+++ b/compiler/rustc_incremental/src/persist/fs.rs
@@ -103,6 +103,7 @@
//! unsupported file system and emit a warning in that case. This is not yet
//! implemented.
+use crate::errors;
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_data_structures::svh::Svh;
use rustc_data_structures::{base_n, flock};
@@ -225,12 +226,7 @@ pub fn prepare_session_directory(
let crate_dir = match crate_dir.canonicalize() {
Ok(v) => v,
Err(err) => {
- let reported = sess.err(&format!(
- "incremental compilation: error canonicalizing path `{}`: {}",
- crate_dir.display(),
- err
- ));
- return Err(reported);
+ return Err(sess.emit_err(errors::CanonicalizePath { path: crate_dir, err }));
}
};
@@ -273,14 +269,7 @@ pub fn prepare_session_directory(
debug!("successfully copied data from: {}", source_directory.display());
if !allows_links {
- sess.warn(&format!(
- "Hard linking files in the incremental \
- compilation cache failed. Copying files \
- instead. Consider moving the cache \
- directory to a file system which supports \
- hard linking in session dir `{}`",
- session_dir.display()
- ));
+ sess.emit_warning(errors::HardLinkFailed { path: &session_dir });
}
sess.init_incr_comp_session(session_dir, directory_lock, true);
@@ -295,12 +284,7 @@ pub fn prepare_session_directory(
// Try to remove the session directory we just allocated. We don't
// know if there's any garbage in it from the failed copy action.
if let Err(err) = safe_remove_dir_all(&session_dir) {
- sess.warn(&format!(
- "Failed to delete partly initialized \
- session dir `{}`: {}",
- session_dir.display(),
- err
- ));
+ sess.emit_warning(errors::DeletePartial { path: &session_dir, err });
}
delete_session_dir_lock_file(sess, &lock_file_path);
@@ -332,12 +316,7 @@ pub fn finalize_session_directory(sess: &Session, svh: Svh) {
);
if let Err(err) = safe_remove_dir_all(&*incr_comp_session_dir) {
- sess.warn(&format!(
- "Error deleting incremental compilation \
- session directory `{}`: {}",
- incr_comp_session_dir.display(),
- err
- ));
+ sess.emit_warning(errors::DeleteFull { path: &incr_comp_session_dir, err });
}
let lock_file_path = lock_file_path(&*incr_comp_session_dir);
@@ -380,12 +359,7 @@ pub fn finalize_session_directory(sess: &Session, svh: Svh) {
}
Err(e) => {
// Warn about the error. However, no need to abort compilation now.
- sess.warn(&format!(
- "Error finalizing incremental compilation \
- session directory `{}`: {}",
- incr_comp_session_dir.display(),
- e
- ));
+ sess.emit_warning(errors::Finalize { path: &incr_comp_session_dir, err: e });
debug!("finalize_session_directory() - error, marking as invalid");
// Drop the file lock, so we can garage collect
@@ -488,16 +462,7 @@ fn create_dir(sess: &Session, path: &Path, dir_tag: &str) -> Result<(), ErrorGua
debug!("{} directory created successfully", dir_tag);
Ok(())
}
- Err(err) => {
- let reported = sess.err(&format!(
- "Could not create incremental compilation {} \
- directory `{}`: {}",
- dir_tag,
- path.display(),
- err
- ));
- Err(reported)
- }
+ Err(err) => Err(sess.emit_err(errors::CreateIncrCompDir { tag: dir_tag, path, err })),
}
}
@@ -518,46 +483,20 @@ fn lock_directory(
// the lock should be exclusive
Ok(lock) => Ok((lock, lock_file_path)),
Err(lock_err) => {
- let mut err = sess.struct_err(&format!(
- "incremental compilation: could not create \
- session directory lock file: {}",
- lock_err
- ));
- if flock::Lock::error_unsupported(&lock_err) {
- err.note(&format!(
- "the filesystem for the incremental path at {} \
- does not appear to support locking, consider changing the \
- incremental path to a filesystem that supports locking \
- or disable incremental compilation",
- session_dir.display()
- ));
- if std::env::var_os("CARGO").is_some() {
- err.help(
- "incremental compilation can be disabled by setting the \
- environment variable CARGO_INCREMENTAL=0 (see \
- https://doc.rust-lang.org/cargo/reference/profiles.html#incremental)",
- );
- err.help(
- "the entire build directory can be changed to a different \
- filesystem by setting the environment variable CARGO_TARGET_DIR \
- to a different path (see \
- https://doc.rust-lang.org/cargo/reference/config.html#buildtarget-dir)",
- );
- }
- }
- Err(err.emit())
+ let is_unsupported_lock = flock::Lock::error_unsupported(&lock_err).then_some(());
+ Err(sess.emit_err(errors::CreateLock {
+ lock_err,
+ session_dir,
+ is_unsupported_lock,
+ is_cargo: std::env::var_os("CARGO").map(|_| ()),
+ }))
}
}
}
fn delete_session_dir_lock_file(sess: &Session, lock_file_path: &Path) {
if let Err(err) = safe_remove_file(&lock_file_path) {
- sess.warn(&format!(
- "Error deleting lock file for incremental \
- compilation session directory `{}`: {}",
- lock_file_path.display(),
- err
- ));
+ sess.emit_warning(errors::DeleteLock { path: lock_file_path, err });
}
}
@@ -774,12 +713,7 @@ pub fn garbage_collect_session_directories(sess: &Session) -> io::Result<()> {
if !lock_file_to_session_dir.values().any(|dir| *dir == directory_name) {
let path = crate_directory.join(directory_name);
if let Err(err) = safe_remove_dir_all(&path) {
- sess.warn(&format!(
- "Failed to garbage collect invalid incremental \
- compilation session directory `{}`: {}",
- path.display(),
- err
- ));
+ sess.emit_warning(errors::InvalidGcFailed { path: &path, err });
}
}
}
@@ -885,12 +819,7 @@ pub fn garbage_collect_session_directories(sess: &Session) -> io::Result<()> {
debug!("garbage_collect_session_directories() - deleting `{}`", path.display());
if let Err(err) = safe_remove_dir_all(&path) {
- sess.warn(&format!(
- "Failed to garbage collect finalized incremental \
- compilation session directory `{}`: {}",
- path.display(),
- err
- ));
+ sess.emit_warning(errors::FinalizedGcFailed { path: &path, err });
} else {
delete_session_dir_lock_file(sess, &lock_file_path(&path));
}
@@ -907,11 +836,7 @@ fn delete_old(sess: &Session, path: &Path) {
debug!("garbage_collect_session_directories() - deleting `{}`", path.display());
if let Err(err) = safe_remove_dir_all(&path) {
- sess.warn(&format!(
- "Failed to garbage collect incremental compilation session directory `{}`: {}",
- path.display(),
- err
- ));
+ sess.emit_warning(errors::SessionGcFailed { path: &path, err });
} else {
delete_session_dir_lock_file(sess, &lock_file_path(&path));
}
diff --git a/compiler/rustc_incremental/src/persist/load.rs b/compiler/rustc_incremental/src/persist/load.rs
index 1c5fd9169..d5097065d 100644
--- a/compiler/rustc_incremental/src/persist/load.rs
+++ b/compiler/rustc_incremental/src/persist/load.rs
@@ -1,5 +1,6 @@
//! Code to save/load the dep-graph from files.
+use crate::errors;
use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::memmap::Mmap;
use rustc_middle::dep_graph::{SerializedDepGraph, WorkProduct, WorkProductId};
@@ -8,7 +9,7 @@ use rustc_serialize::opaque::MemDecoder;
use rustc_serialize::Decodable;
use rustc_session::config::IncrementalStateAssertion;
use rustc_session::Session;
-use std::path::Path;
+use std::path::{Path, PathBuf};
use super::data::*;
use super::file_format;
@@ -27,11 +28,10 @@ pub enum LoadResult<T> {
},
/// The file either didn't exist or was produced by an incompatible compiler version.
DataOutOfDate,
- /// An error occurred.
- Error {
- #[allow(missing_docs)]
- message: String,
- },
+ /// Loading the dep graph failed.
+ LoadDepGraph(PathBuf, std::io::Error),
+ /// Decoding loaded incremental cache failed.
+ DecodeIncrCache(Box<dyn std::any::Any + Send>),
}
impl<T: Default> LoadResult<T> {
@@ -40,36 +40,31 @@ impl<T: Default> LoadResult<T> {
// Check for errors when using `-Zassert-incremental-state`
match (sess.opts.assert_incr_state, &self) {
(Some(IncrementalStateAssertion::NotLoaded), LoadResult::Ok { .. }) => {
- sess.fatal(
- "We asserted that the incremental cache should not be loaded, \
- but it was loaded.",
- );
+ sess.emit_fatal(errors::AssertNotLoaded);
}
(
Some(IncrementalStateAssertion::Loaded),
- LoadResult::Error { .. } | LoadResult::DataOutOfDate,
+ LoadResult::LoadDepGraph(..)
+ | LoadResult::DecodeIncrCache(..)
+ | LoadResult::DataOutOfDate,
) => {
- sess.fatal(
- "We asserted that an existing incremental cache directory should \
- be successfully loaded, but it was not.",
- );
+ sess.emit_fatal(errors::AssertLoaded);
}
_ => {}
};
match self {
- LoadResult::Error { message } => {
- sess.warn(&message);
+ LoadResult::LoadDepGraph(path, err) => {
+ sess.emit_warning(errors::LoadDepGraph { path, err });
+ Default::default()
+ }
+ LoadResult::DecodeIncrCache(err) => {
+ sess.emit_warning(errors::DecodeIncrCache { err: format!("{err:?}") });
Default::default()
}
LoadResult::DataOutOfDate => {
if let Err(err) = delete_all_session_dir_contents(sess) {
- sess.err(&format!(
- "Failed to delete invalidated or incompatible \
- incremental compilation session directory contents `{}`: {}.",
- dep_graph_path(sess).display(),
- err
- ));
+ sess.emit_err(errors::DeleteIncompatible { path: dep_graph_path(sess), err });
}
Default::default()
}
@@ -90,9 +85,7 @@ fn load_data(
// compiler version. Neither is an error.
LoadResult::DataOutOfDate
}
- Err(err) => LoadResult::Error {
- message: format!("could not load dep-graph from `{}`: {}", path.display(), err),
- },
+ Err(err) => LoadResult::LoadDepGraph(path.to_path_buf(), err),
}
}
@@ -114,9 +107,9 @@ impl<T> MaybeAsync<LoadResult<T>> {
pub fn open(self) -> LoadResult<T> {
match self {
MaybeAsync::Sync(result) => result,
- MaybeAsync::Async(handle) => handle.join().unwrap_or_else(|e| LoadResult::Error {
- message: format!("could not decode incremental cache: {:?}", e),
- }),
+ MaybeAsync::Async(handle) => {
+ handle.join().unwrap_or_else(|e| LoadResult::DecodeIncrCache(e))
+ }
}
}
}
@@ -185,7 +178,8 @@ pub fn load_dep_graph(sess: &Session) -> DepGraphFuture {
match load_data(report_incremental_info, &path, nightly_build) {
LoadResult::DataOutOfDate => LoadResult::DataOutOfDate,
- LoadResult::Error { message } => LoadResult::Error { message },
+ LoadResult::LoadDepGraph(path, err) => LoadResult::LoadDepGraph(path, err),
+ LoadResult::DecodeIncrCache(err) => LoadResult::DecodeIncrCache(err),
LoadResult::Ok { data: (bytes, start_pos) } => {
let mut decoder = MemDecoder::new(&bytes, start_pos);
let prev_commandline_args_hash = u64::decode(&mut decoder);
diff --git a/compiler/rustc_incremental/src/persist/save.rs b/compiler/rustc_incremental/src/persist/save.rs
index 6e9dcdd98..27be56eac 100644
--- a/compiler/rustc_incremental/src/persist/save.rs
+++ b/compiler/rustc_incremental/src/persist/save.rs
@@ -1,3 +1,4 @@
+use crate::errors;
use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::sync::join;
use rustc_middle::dep_graph::{DepGraph, SerializedDepGraph, WorkProduct, WorkProductId};
@@ -59,19 +60,14 @@ pub fn save_dep_graph(tcx: TyCtxt<'_>) {
move || {
sess.time("incr_comp_persist_dep_graph", || {
if let Err(err) = tcx.dep_graph.encode(&tcx.sess.prof) {
- sess.err(&format!(
- "failed to write dependency graph to `{}`: {}",
- staging_dep_graph_path.display(),
- err
- ));
+ sess.emit_err(errors::WriteDepGraph { path: &staging_dep_graph_path, err });
}
if let Err(err) = fs::rename(&staging_dep_graph_path, &dep_graph_path) {
- sess.err(&format!(
- "failed to move dependency graph from `{}` to `{}`: {}",
- staging_dep_graph_path.display(),
- dep_graph_path.display(),
- err
- ));
+ sess.emit_err(errors::MoveDepGraph {
+ from: &staging_dep_graph_path,
+ to: &dep_graph_path,
+ err,
+ });
}
});
},
@@ -163,11 +159,7 @@ pub fn build_dep_graph(
let mut encoder = match FileEncoder::new(&path_buf) {
Ok(encoder) => encoder,
Err(err) => {
- sess.err(&format!(
- "failed to create dependency graph at `{}`: {}",
- path_buf.display(),
- err
- ));
+ sess.emit_err(errors::CreateDepGraph { path: &path_buf, err });
return None;
}
};
diff --git a/compiler/rustc_incremental/src/persist/work_product.rs b/compiler/rustc_incremental/src/persist/work_product.rs
index 2f1853c44..dc98fbeb0 100644
--- a/compiler/rustc_incremental/src/persist/work_product.rs
+++ b/compiler/rustc_incremental/src/persist/work_product.rs
@@ -2,6 +2,7 @@
//!
//! [work products]: WorkProduct
+use crate::errors;
use crate::persist::fs::*;
use rustc_data_structures::fx::FxHashMap;
use rustc_fs_util::link_or_copy;
@@ -28,12 +29,11 @@ pub fn copy_cgu_workproduct_to_incr_comp_cache_dir(
let _ = saved_files.insert(ext.to_string(), file_name);
}
Err(err) => {
- sess.warn(&format!(
- "error copying object file `{}` to incremental directory as `{}`: {}",
- path.display(),
- path_in_incr_dir.display(),
- err
- ));
+ sess.emit_warning(errors::CopyWorkProductToCache {
+ from: &path,
+ to: &path_in_incr_dir,
+ err,
+ });
}
}
}
@@ -49,11 +49,7 @@ pub fn delete_workproduct_files(sess: &Session, work_product: &WorkProduct) {
for (_, path) in &work_product.saved_files {
let path = in_incr_comp_dir_sess(sess, path);
if let Err(err) = std_fs::remove_file(&path) {
- sess.warn(&format!(
- "file-system error deleting outdated file `{}`: {}",
- path.display(),
- err
- ));
+ sess.emit_warning(errors::DeleteWorkProduct { path: &path, err });
}
}
}
diff --git a/compiler/rustc_index/src/bit_set.rs b/compiler/rustc_index/src/bit_set.rs
index 15179392c..cbf169afb 100644
--- a/compiler/rustc_index/src/bit_set.rs
+++ b/compiler/rustc_index/src/bit_set.rs
@@ -1870,7 +1870,7 @@ impl<R: Idx, C: Idx> SparseBitMatrix<R, C> {
}
}
- /// Subtracts `set from `row`. `set` can be either `BitSet` or
+ /// Subtracts `set` from `row`. `set` can be either `BitSet` or
/// `HybridBitSet`. Has no effect if `row` does not exist.
///
/// Returns true if the row was changed.
diff --git a/compiler/rustc_infer/Cargo.toml b/compiler/rustc_infer/Cargo.toml
index aced787d6..02ac83a5e 100644
--- a/compiler/rustc_infer/Cargo.toml
+++ b/compiler/rustc_infer/Cargo.toml
@@ -15,7 +15,6 @@ 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" }
smallvec = { version = "1.8.1", features = ["union", "may_dangle"] }
diff --git a/compiler/rustc_error_messages/locales/en-US/infer.ftl b/compiler/rustc_infer/locales/en-US.ftl
index cc38d71b4..15780898d 100644
--- a/compiler/rustc_error_messages/locales/en-US/infer.ftl
+++ b/compiler/rustc_infer/locales/en-US.ftl
@@ -79,7 +79,7 @@ infer_subtype = ...so that the {$requirement ->
[if_else_different] `if` and `else` have incompatible types
[no_else] `if` missing an `else` returns `()`
[fn_main_correct_type] `main` function has the correct type
- [fn_start_correct_type] #[start]` function has the correct type
+ [fn_start_correct_type] `#[start]` function has the correct type
[intristic_correct_type] intrinsic has the correct type
[method_correct_type] method receiver has the correct type
*[other] types are compatible
@@ -92,7 +92,7 @@ infer_subtype_2 = ...so that {$requirement ->
[if_else_different] `if` and `else` have incompatible types
[no_else] `if` missing an `else` returns `()`
[fn_main_correct_type] `main` function has the correct type
- [fn_start_correct_type] #[start]` function has the correct type
+ [fn_start_correct_type] `#[start]` function has the correct type
[intristic_correct_type] intrinsic has the correct type
[method_correct_type] method receiver has the correct type
*[other] types are compatible
@@ -140,6 +140,18 @@ infer_lifetime_param_suggestion_elided = each elided lifetime in input position
infer_region_explanation = {$pref_kind ->
*[should_not_happen] [{$pref_kind}]
+ [ref_valid_for] ...the reference is valid for
+ [content_valid_for] ...but the borrowed content is only valid for
+ [type_obj_valid_for] object type is valid for
+ [source_pointer_valid_for] source pointer is only valid for
+ [type_satisfy] type must satisfy
+ [type_outlive] type must outlive
+ [lf_param_instantiated_with] lifetime parameter instantiated with
+ [lf_param_must_outlive] but lifetime parameter must outlive
+ [lf_instantiated_with] lifetime instantiated with
+ [lf_must_outlive] but lifetime must outlive
+ [pointer_valid_for] the pointer is valid for
+ [data_valid_for] but the referenced data is only valid for
[empty] {""}
}{$pref_kind ->
[empty] {""}
@@ -147,10 +159,7 @@ infer_region_explanation = {$pref_kind ->
}{$desc_kind ->
*[should_not_happen] [{$desc_kind}]
[restatic] the static lifetime
- [reempty] the empty lifetime
- [reemptyuni] the empty lifetime in universe {$desc_arg}
[revar] lifetime {$desc_arg}
-
[as_defined] the lifetime `{$desc_arg}` as defined here
[as_defined_anon] the anonymous lifetime as defined here
[defined_here] the anonymous lifetime defined here
@@ -160,8 +169,16 @@ infer_region_explanation = {$pref_kind ->
*[should_not_happen] [{$suff_kind}]
[empty]{""}
[continues] ...
+ [req_by_binding] {" "}as required by this binding
}
+infer_outlives_content = lifetime of reference outlives lifetime of borrowed content...
+infer_outlives_bound = lifetime of the source pointer does not outlive lifetime bound of the object type
+infer_fullfill_req_lifetime = the type `{$ty}` does not fulfill the required lifetime
+infer_lf_bound_not_satisfied = lifetime bound not satisfied
+infer_borrowed_too_long = a value of type `{$ty}` is borrowed for too long
+infer_ref_longer_than_data = in type `{$ty}`, reference has a longer lifetime than the data it references
+
infer_mismatched_static_lifetime = incompatible lifetime on type
infer_does_not_outlive_static_from_impl = ...does not necessarily outlive the static lifetime introduced by the compatible `impl`
infer_implicit_static_lifetime_note = this has an implicit `'static` lifetime requirement
@@ -260,7 +277,7 @@ infer_tid_consider_borrowing = consider borrowing this type parameter in the tra
infer_tid_param_help = the lifetime requirements from the `impl` do not correspond to the requirements in the `trait`
infer_dtcs_has_lifetime_req_label = this has an implicit `'static` lifetime requirement
-infer_dtcs_introduces_requirement = calling this method introduces the `impl`'s 'static` requirement
+infer_dtcs_introduces_requirement = calling this method introduces the `impl`'s `'static` requirement
infer_dtcs_has_req_note = the used `impl` has a `'static` requirement
infer_dtcs_suggestion = consider relaxing the implicit `'static` requirement
@@ -268,45 +285,66 @@ infer_but_calling_introduces = {$has_param_name ->
[true] `{$param_name}`
*[false] `fn` parameter
} has {$lifetime_kind ->
- [named] lifetime `{$lifetime}`
- *[anon] an anonymous lifetime `'_`
-} but calling `{assoc_item}` introduces an implicit `'static` lifetime requirement
+ [true] lifetime `{$lifetime}`
+ *[false] an anonymous lifetime `'_`
+} but calling `{$assoc_item}` introduces an implicit `'static` lifetime requirement
.label1 = {$has_lifetime ->
- [named] lifetime `{$lifetime}`
- *[anon] an anonymous lifetime `'_`
+ [true] lifetime `{$lifetime}`
+ *[false] an anonymous lifetime `'_`
}
.label2 = ...is used and required to live as long as `'static` here because of an implicit lifetime bound on the {$has_impl_path ->
- [named] `impl` of `{$impl_path}`
- *[anon] inherent `impl`
+ [true] `impl` of `{$impl_path}`
+ *[false] inherent `impl`
}
infer_but_needs_to_satisfy = {$has_param_name ->
[true] `{$param_name}`
*[false] `fn` parameter
} has {$has_lifetime ->
- [named] lifetime `{$lifetime}`
- *[anon] an anonymous lifetime `'_`
+ [true] lifetime `{$lifetime}`
+ *[false] an anonymous lifetime `'_`
} but it needs to satisfy a `'static` lifetime requirement
.influencer = this data with {$has_lifetime ->
- [named] lifetime `{$lifetime}`
- *[anon] an anonymous lifetime `'_`
+ [true] lifetime `{$lifetime}`
+ *[false] an anonymous lifetime `'_`
}...
.require = {$spans_empty ->
*[true] ...is used and required to live as long as `'static` here
[false] ...and is required to live as long as `'static` here
}
.used_here = ...is used here...
- .introduced_by_bound = 'static` lifetime requirement introduced by this bound
+ .introduced_by_bound = `'static` lifetime requirement introduced by this bound
infer_more_targeted = {$has_param_name ->
[true] `{$param_name}`
*[false] `fn` parameter
} has {$has_lifetime ->
- [named] lifetime `{$lifetime}`
- *[anon] an anonymous lifetime `'_`
+ [true] lifetime `{$lifetime}`
+ *[false] an anonymous lifetime `'_`
} but calling `{$ident}` introduces an implicit `'static` lifetime requirement
infer_ril_introduced_here = `'static` requirement introduced here
infer_ril_introduced_by = requirement introduced by this return type
infer_ril_because_of = because of this returned expression
infer_ril_static_introduced_by = "`'static` lifetime requirement introduced by the return type
+
+infer_where_remove = remove the `where` clause
+infer_where_copy_predicates = copy the `where` clause predicates from the trait
+
+infer_srs_remove_and_box = consider removing this semicolon and boxing the expressions
+infer_srs_remove = consider removing this semicolon
+infer_srs_add = consider returning the local binding `{$ident}`
+infer_srs_add_one = consider returning one of these bindings
+
+infer_await_both_futures = consider `await`ing on both `Future`s
+infer_await_future = consider `await`ing on the `Future`
+infer_await_note = calling an async function returns a future
+
+infer_prlf_defined_with_sub = the lifetime `{$sub_symbol}` defined here...
+infer_prlf_defined_without_sub = the lifetime defined here...
+infer_prlf_must_oultive_with_sup = ...must outlive the lifetime `{$sup_symbol}` defined here
+infer_prlf_must_oultive_without_sup = ...must outlive the lifetime defined here
+infer_prlf_known_limitation = this is a known limitation that will be removed in the future (see issue #100013 <https://github.com/rust-lang/rust/issues/100013> for more information)
+
+infer_opaque_captures_lifetime = hidden type for `{$opaque_ty}` captures lifetime that does not appear in bounds
+ .label = opaque type defined here
diff --git a/compiler/rustc_infer/src/errors/mod.rs b/compiler/rustc_infer/src/errors/mod.rs
index 033a1842e..6bbd3fd3e 100644
--- a/compiler/rustc_infer/src/errors/mod.rs
+++ b/compiler/rustc_infer/src/errors/mod.rs
@@ -1,6 +1,6 @@
use hir::GenericParamKind;
use rustc_errors::{
- fluent, AddToDiagnostic, Applicability, Diagnostic, DiagnosticMessage, DiagnosticStyledString,
+ AddToDiagnostic, Applicability, Diagnostic, DiagnosticMessage, DiagnosticStyledString,
IntoDiagnosticArg, MultiSpan, SubdiagnosticMessage,
};
use rustc_hir as hir;
@@ -12,9 +12,10 @@ use rustc_span::symbol::kw;
use rustc_span::Symbol;
use rustc_span::{symbol::Ident, BytePos, Span};
-use crate::infer::error_reporting::nice_region_error::placeholder_error::Highlighted;
+use crate::fluent_generated as fluent;
use crate::infer::error_reporting::{
need_type_info::{GeneratorKindAsDiagArg, UnderspecifiedArgKind},
+ nice_region_error::placeholder_error::Highlighted,
ObligationCauseAsDiagArg,
};
@@ -26,9 +27,9 @@ pub struct OpaqueHiddenTypeDiag {
#[primary_span]
#[label]
pub span: Span,
- #[note(opaque_type)]
+ #[note(infer_opaque_type)]
pub opaque_type: Span,
- #[note(hidden_type)]
+ #[note(infer_hidden_type)]
pub hidden_type: Span,
}
@@ -768,11 +769,11 @@ impl<'tcx> ActualImplExplNotes<'tcx> {
pub struct TraitPlaceholderMismatch<'tcx> {
#[primary_span]
pub span: Span,
- #[label(label_satisfy)]
+ #[label(infer_label_satisfy)]
pub satisfy_span: Option<Span>,
- #[label(label_where)]
+ #[label(infer_label_where)]
pub where_span: Option<Span>,
- #[label(label_dup)]
+ #[label(infer_label_dup)]
pub dup_span: Option<Span>,
pub def_id: String,
pub trait_def_id: String,
@@ -808,11 +809,11 @@ pub struct RelationshipHelp;
#[diag(infer_trait_impl_diff)]
pub struct TraitImplDiff {
#[primary_span]
- #[label(found)]
+ #[label(infer_found)]
pub sp: Span,
- #[label(expected)]
+ #[label(infer_expected)]
pub trait_sp: Span,
- #[note(expected_found)]
+ #[note(infer_expected_found)]
pub note: (),
#[subdiagnostic]
pub param_help: ConsiderBorrowingParamHelp,
@@ -852,10 +853,10 @@ impl AddToDiagnostic for DynTraitConstraintSuggestion {
#[derive(Diagnostic)]
#[diag(infer_but_calling_introduces, code = "E0772")]
pub struct ButCallingIntroduces {
- #[label(label1)]
+ #[label(infer_label1)]
pub param_ty_span: Span,
#[primary_span]
- #[label(label2)]
+ #[label(infer_label2)]
pub cause_span: Span,
pub has_param_name: bool,
@@ -913,21 +914,246 @@ impl AddToDiagnostic for MoreTargeted {
pub struct ButNeedsToSatisfy {
#[primary_span]
pub sp: Span,
- #[label(influencer)]
+ #[label(infer_influencer)]
pub influencer_point: Span,
- #[label(used_here)]
+ #[label(infer_used_here)]
pub spans: Vec<Span>,
- #[label(require)]
+ #[label(infer_require)]
pub require_span_as_label: Option<Span>,
- #[note(require)]
+ #[note(infer_require)]
pub require_span_as_note: Option<Span>,
- #[note(introduced_by_bound)]
+ #[note(infer_introduced_by_bound)]
pub bound: Option<Span>,
#[subdiagnostic]
pub req_introduces_loc: Option<ReqIntroducedLocations>,
+ pub has_param_name: bool,
+ pub param_name: String,
pub spans_empty: bool,
pub has_lifetime: bool,
pub lifetime: String,
}
+
+#[derive(Diagnostic)]
+#[diag(infer_outlives_content, code = "E0312")]
+pub struct OutlivesContent<'a> {
+ #[primary_span]
+ pub span: Span,
+ #[subdiagnostic]
+ pub notes: Vec<note_and_explain::RegionExplanation<'a>>,
+}
+
+#[derive(Diagnostic)]
+#[diag(infer_outlives_bound, code = "E0476")]
+pub struct OutlivesBound<'a> {
+ #[primary_span]
+ pub span: Span,
+ #[subdiagnostic]
+ pub notes: Vec<note_and_explain::RegionExplanation<'a>>,
+}
+
+#[derive(Diagnostic)]
+#[diag(infer_fullfill_req_lifetime, code = "E0477")]
+pub struct FullfillReqLifetime<'a> {
+ #[primary_span]
+ pub span: Span,
+ pub ty: Ty<'a>,
+ #[subdiagnostic]
+ pub note: Option<note_and_explain::RegionExplanation<'a>>,
+}
+
+#[derive(Diagnostic)]
+#[diag(infer_lf_bound_not_satisfied, code = "E0478")]
+pub struct LfBoundNotSatisfied<'a> {
+ #[primary_span]
+ pub span: Span,
+ #[subdiagnostic]
+ pub notes: Vec<note_and_explain::RegionExplanation<'a>>,
+}
+
+#[derive(Diagnostic)]
+#[diag(infer_ref_longer_than_data, code = "E0491")]
+pub struct RefLongerThanData<'a> {
+ #[primary_span]
+ pub span: Span,
+ pub ty: Ty<'a>,
+ #[subdiagnostic]
+ pub notes: Vec<note_and_explain::RegionExplanation<'a>>,
+}
+
+#[derive(Subdiagnostic)]
+pub enum WhereClauseSuggestions {
+ #[suggestion(
+ infer_where_remove,
+ code = "",
+ applicability = "machine-applicable",
+ style = "verbose"
+ )]
+ Remove {
+ #[primary_span]
+ span: Span,
+ },
+ #[suggestion(
+ infer_where_copy_predicates,
+ code = "{space}where {trait_predicates}",
+ applicability = "machine-applicable",
+ style = "verbose"
+ )]
+ CopyPredicates {
+ #[primary_span]
+ span: Span,
+ space: &'static str,
+ trait_predicates: String,
+ },
+}
+
+#[derive(Subdiagnostic)]
+pub enum SuggestRemoveSemiOrReturnBinding {
+ #[multipart_suggestion(infer_srs_remove_and_box, applicability = "machine-applicable")]
+ RemoveAndBox {
+ #[suggestion_part(code = "Box::new(")]
+ first_lo: Span,
+ #[suggestion_part(code = ")")]
+ first_hi: Span,
+ #[suggestion_part(code = "Box::new(")]
+ second_lo: Span,
+ #[suggestion_part(code = ")")]
+ second_hi: Span,
+ #[suggestion_part(code = "")]
+ sp: Span,
+ },
+ #[suggestion(
+ infer_srs_remove,
+ style = "short",
+ code = "",
+ applicability = "machine-applicable"
+ )]
+ Remove {
+ #[primary_span]
+ sp: Span,
+ },
+ #[suggestion(
+ infer_srs_add,
+ style = "verbose",
+ code = "{code}",
+ applicability = "maybe-incorrect"
+ )]
+ Add {
+ #[primary_span]
+ sp: Span,
+ code: String,
+ ident: Ident,
+ },
+ #[note(infer_srs_add_one)]
+ AddOne {
+ #[primary_span]
+ spans: MultiSpan,
+ },
+}
+
+#[derive(Subdiagnostic)]
+pub enum ConsiderAddingAwait {
+ #[help(infer_await_both_futures)]
+ BothFuturesHelp,
+ #[multipart_suggestion(infer_await_both_futures, applicability = "maybe-incorrect")]
+ BothFuturesSugg {
+ #[suggestion_part(code = ".await")]
+ first: Span,
+ #[suggestion_part(code = ".await")]
+ second: Span,
+ },
+ #[suggestion(
+ infer_await_future,
+ code = ".await",
+ style = "verbose",
+ applicability = "maybe-incorrect"
+ )]
+ FutureSugg {
+ #[primary_span]
+ span: Span,
+ },
+ #[note(infer_await_note)]
+ FutureSuggNote {
+ #[primary_span]
+ span: Span,
+ },
+ #[multipart_suggestion(
+ infer_await_future,
+ style = "verbose",
+ applicability = "maybe-incorrect"
+ )]
+ FutureSuggMultiple {
+ #[suggestion_part(code = ".await")]
+ spans: Vec<Span>,
+ },
+}
+
+#[derive(Diagnostic)]
+pub enum PlaceholderRelationLfNotSatisfied {
+ #[diag(infer_lf_bound_not_satisfied)]
+ HasBoth {
+ #[primary_span]
+ span: Span,
+ #[note(infer_prlf_defined_with_sub)]
+ sub_span: Span,
+ #[note(infer_prlf_must_oultive_with_sup)]
+ sup_span: Span,
+ sub_symbol: Symbol,
+ sup_symbol: Symbol,
+ #[note(infer_prlf_known_limitation)]
+ note: (),
+ },
+ #[diag(infer_lf_bound_not_satisfied)]
+ HasSub {
+ #[primary_span]
+ span: Span,
+ #[note(infer_prlf_defined_with_sub)]
+ sub_span: Span,
+ #[note(infer_prlf_must_oultive_without_sup)]
+ sup_span: Span,
+ sub_symbol: Symbol,
+ #[note(infer_prlf_known_limitation)]
+ note: (),
+ },
+ #[diag(infer_lf_bound_not_satisfied)]
+ HasSup {
+ #[primary_span]
+ span: Span,
+ #[note(infer_prlf_defined_without_sub)]
+ sub_span: Span,
+ #[note(infer_prlf_must_oultive_with_sup)]
+ sup_span: Span,
+ sup_symbol: Symbol,
+ #[note(infer_prlf_known_limitation)]
+ note: (),
+ },
+ #[diag(infer_lf_bound_not_satisfied)]
+ HasNone {
+ #[primary_span]
+ span: Span,
+ #[note(infer_prlf_defined_without_sub)]
+ sub_span: Span,
+ #[note(infer_prlf_must_oultive_without_sup)]
+ sup_span: Span,
+ #[note(infer_prlf_known_limitation)]
+ note: (),
+ },
+ #[diag(infer_lf_bound_not_satisfied)]
+ OnlyPrimarySpan {
+ #[primary_span]
+ span: Span,
+ #[note(infer_prlf_known_limitation)]
+ note: (),
+ },
+}
+
+#[derive(Diagnostic)]
+#[diag(infer_opaque_captures_lifetime, code = "E0700")]
+pub struct OpaqueCapturesLifetime<'tcx> {
+ #[primary_span]
+ pub span: Span,
+ #[label]
+ pub opaque_ty_span: Span,
+ pub opaque_ty: Ty<'tcx>,
+}
diff --git a/compiler/rustc_infer/src/errors/note_and_explain.rs b/compiler/rustc_infer/src/errors/note_and_explain.rs
index 7aaa5ce2f..ef543b1fb 100644
--- a/compiler/rustc_infer/src/errors/note_and_explain.rs
+++ b/compiler/rustc_infer/src/errors/note_and_explain.rs
@@ -1,7 +1,6 @@
+use crate::fluent_generated as fluent;
use crate::infer::error_reporting::nice_region_error::find_anon_type;
-use rustc_errors::{
- self, fluent, AddToDiagnostic, Diagnostic, IntoDiagnosticArg, SubdiagnosticMessage,
-};
+use rustc_errors::{self, AddToDiagnostic, Diagnostic, IntoDiagnosticArg, SubdiagnosticMessage};
use rustc_middle::ty::{self, TyCtxt};
use rustc_span::{symbol::kw, Span};
@@ -31,6 +30,8 @@ impl<'a> DescriptionCtx<'a> {
ty::RePlaceholder(_) => return None,
+ ty::ReError(_) => return None,
+
// FIXME(#13998) RePlaceholder should probably print like
// ReFree rather than dumping Debug output on the user.
//
@@ -119,16 +120,42 @@ impl<'a> DescriptionCtx<'a> {
pub enum PrefixKind {
Empty,
+ RefValidFor,
+ ContentValidFor,
+ TypeObjValidFor,
+ SourcePointerValidFor,
+ TypeSatisfy,
+ TypeOutlive,
+ LfParamInstantiatedWith,
+ LfParamMustOutlive,
+ LfInstantiatedWith,
+ LfMustOutlive,
+ PointerValidFor,
+ DataValidFor,
}
pub enum SuffixKind {
+ Empty,
Continues,
+ ReqByBinding,
}
impl IntoDiagnosticArg for PrefixKind {
fn into_diagnostic_arg(self) -> rustc_errors::DiagnosticArgValue<'static> {
let kind = match self {
Self::Empty => "empty",
+ Self::RefValidFor => "ref_valid_for",
+ Self::ContentValidFor => "content_valid_for",
+ Self::TypeObjValidFor => "type_obj_valid_for",
+ Self::SourcePointerValidFor => "source_pointer_valid_for",
+ Self::TypeSatisfy => "type_satisfy",
+ Self::TypeOutlive => "type_outlive",
+ Self::LfParamInstantiatedWith => "lf_param_instantiated_with",
+ Self::LfParamMustOutlive => "lf_param_must_outlive",
+ Self::LfInstantiatedWith => "lf_instantiated_with",
+ Self::LfMustOutlive => "lf_must_outlive",
+ Self::PointerValidFor => "pointer_valid_for",
+ Self::DataValidFor => "data_valid_for",
}
.into();
rustc_errors::DiagnosticArgValue::Str(kind)
@@ -138,7 +165,9 @@ impl IntoDiagnosticArg for PrefixKind {
impl IntoDiagnosticArg for SuffixKind {
fn into_diagnostic_arg(self) -> rustc_errors::DiagnosticArgValue<'static> {
let kind = match self {
+ Self::Empty => "empty",
Self::Continues => "continues",
+ Self::ReqByBinding => "req_by_binding",
}
.into();
rustc_errors::DiagnosticArgValue::Str(kind)
@@ -164,17 +193,19 @@ impl RegionExplanation<'_> {
}
impl AddToDiagnostic for RegionExplanation<'_> {
- fn add_to_diagnostic_with<F>(self, diag: &mut Diagnostic, _: F)
+ fn add_to_diagnostic_with<F>(self, diag: &mut Diagnostic, f: F)
where
F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage,
{
- if let Some(span) = self.desc.span {
- diag.span_note(span, fluent::infer_region_explanation);
- } else {
- diag.note(fluent::infer_region_explanation);
- }
- self.desc.add_to(diag);
diag.set_arg("pref_kind", self.prefix);
diag.set_arg("suff_kind", self.suffix);
+ let desc_span = self.desc.span;
+ self.desc.add_to(diag);
+ let msg = f(diag, fluent::infer_region_explanation.into());
+ if let Some(span) = desc_span {
+ diag.span_note(span, msg);
+ } else {
+ diag.note(msg);
+ }
}
}
diff --git a/compiler/rustc_infer/src/infer/at.rs b/compiler/rustc_infer/src/infer/at.rs
index d816a9ed3..7d9bae735 100644
--- a/compiler/rustc_infer/src/infer/at.rs
+++ b/compiler/rustc_infer/src/infer/at.rs
@@ -55,7 +55,7 @@ impl<'tcx> InferCtxt<'tcx> {
cause: &'a ObligationCause<'tcx>,
param_env: ty::ParamEnv<'tcx>,
) -> At<'a, 'tcx> {
- At { infcx: self, cause, param_env, define_opaque_types: true }
+ At { infcx: self, cause, param_env, define_opaque_types: false }
}
/// Forks the inference context, creating a new inference context with the same inference
@@ -369,6 +369,34 @@ impl<'tcx> ToTrace<'tcx> for Const<'tcx> {
}
}
+impl<'tcx> ToTrace<'tcx> for ty::GenericArg<'tcx> {
+ fn to_trace(
+ _: TyCtxt<'tcx>,
+ cause: &ObligationCause<'tcx>,
+ a_is_expected: bool,
+ a: Self,
+ b: Self,
+ ) -> TypeTrace<'tcx> {
+ use GenericArgKind::*;
+ TypeTrace {
+ cause: cause.clone(),
+ values: match (a.unpack(), b.unpack()) {
+ (Lifetime(a), Lifetime(b)) => Regions(ExpectedFound::new(a_is_expected, a, b)),
+ (Type(a), Type(b)) => Terms(ExpectedFound::new(a_is_expected, a.into(), b.into())),
+ (Const(a), Const(b)) => {
+ Terms(ExpectedFound::new(a_is_expected, a.into(), b.into()))
+ }
+
+ (Lifetime(_), Type(_) | Const(_))
+ | (Type(_), Lifetime(_) | Const(_))
+ | (Const(_), Lifetime(_) | Type(_)) => {
+ bug!("relating different kinds: {a:?} {b:?}")
+ }
+ },
+ }
+ }
+}
+
impl<'tcx> ToTrace<'tcx> for ty::Term<'tcx> {
fn to_trace(
_: TyCtxt<'tcx>,
diff --git a/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs b/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs
index 091635e6c..678c4a0be 100644
--- a/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs
+++ b/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs
@@ -12,7 +12,7 @@ use crate::infer::InferCtxt;
use rustc_middle::ty::flags::FlagComputation;
use rustc_middle::ty::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable};
use rustc_middle::ty::subst::GenericArg;
-use rustc_middle::ty::{self, BoundVar, InferConst, List, Ty, TyCtxt, TypeFlags};
+use rustc_middle::ty::{self, BoundVar, InferConst, List, Ty, TyCtxt, TypeFlags, TypeVisitableExt};
use std::sync::atomic::Ordering;
use rustc_data_structures::fx::FxHashMap;
@@ -41,7 +41,7 @@ impl<'tcx> InferCtxt<'tcx> {
query_state: &mut OriginalQueryValues<'tcx>,
) -> Canonical<'tcx, V>
where
- V: TypeFoldable<'tcx>,
+ V: TypeFoldable<TyCtxt<'tcx>>,
{
self.tcx.sess.perf_stats.queries_canonicalized.fetch_add(1, Ordering::Relaxed);
@@ -50,7 +50,7 @@ impl<'tcx> InferCtxt<'tcx> {
/// Like [Self::canonicalize_query], but preserves distinct universes. For
/// example, canonicalizing `&'?0: Trait<'?1>`, where `'?0` is in `U1` and
- /// `'?1` is in `U3` would be canonicalized to have ?0` in `U1` and `'?1`
+ /// `'?1` is in `U3` would be canonicalized to have `?0` in `U1` and `'?1`
/// in `U2`.
///
/// This is used for Chalk integration.
@@ -60,7 +60,7 @@ impl<'tcx> InferCtxt<'tcx> {
query_state: &mut OriginalQueryValues<'tcx>,
) -> Canonical<'tcx, V>
where
- V: TypeFoldable<'tcx>,
+ V: TypeFoldable<TyCtxt<'tcx>>,
{
self.tcx.sess.perf_stats.queries_canonicalized.fetch_add(1, Ordering::Relaxed);
@@ -100,7 +100,7 @@ impl<'tcx> InferCtxt<'tcx> {
/// [c]: https://rust-lang.github.io/chalk/book/canonical_queries/canonicalization.html#canonicalizing-the-query-result
pub fn canonicalize_response<V>(&self, value: V) -> Canonical<'tcx, V>
where
- V: TypeFoldable<'tcx>,
+ V: TypeFoldable<TyCtxt<'tcx>>,
{
let mut query_state = OriginalQueryValues::default();
Canonicalizer::canonicalize(
@@ -114,7 +114,7 @@ impl<'tcx> InferCtxt<'tcx> {
pub fn canonicalize_user_type_annotation<V>(&self, value: V) -> Canonical<'tcx, V>
where
- V: TypeFoldable<'tcx>,
+ V: TypeFoldable<TyCtxt<'tcx>>,
{
let mut query_state = OriginalQueryValues::default();
Canonicalizer::canonicalize(
@@ -136,7 +136,7 @@ impl<'tcx> InferCtxt<'tcx> {
query_state: &mut OriginalQueryValues<'tcx>,
) -> Canonical<'tcx, V>
where
- V: TypeFoldable<'tcx>,
+ V: TypeFoldable<TyCtxt<'tcx>>,
{
self.tcx.sess.perf_stats.queries_canonicalized.fetch_add(1, Ordering::Relaxed);
@@ -203,12 +203,10 @@ impl CanonicalizeMode for CanonicalizeQueryResponse {
// rust-lang/rust#57464: `impl Trait` can leak local
// scopes (in manner violating typeck). Therefore, use
// `delay_span_bug` to allow type error over an ICE.
- ty::tls::with(|tcx| {
- tcx.sess.delay_span_bug(
- rustc_span::DUMMY_SP,
- &format!("unexpected region in query response: `{:?}`", r),
- );
- });
+ canonicalizer.tcx.sess.delay_span_bug(
+ rustc_span::DUMMY_SP,
+ &format!("unexpected region in query response: `{:?}`", r),
+ );
r
}
}
@@ -328,14 +326,14 @@ struct Canonicalizer<'cx, 'tcx> {
binder_index: ty::DebruijnIndex,
}
-impl<'cx, 'tcx> TypeFolder<'tcx> for Canonicalizer<'cx, 'tcx> {
- fn tcx<'b>(&'b self) -> TyCtxt<'tcx> {
+impl<'cx, 'tcx> TypeFolder<TyCtxt<'tcx>> for Canonicalizer<'cx, 'tcx> {
+ fn interner(&self) -> TyCtxt<'tcx> {
self.tcx
}
fn fold_binder<T>(&mut self, t: ty::Binder<'tcx, T>) -> ty::Binder<'tcx, T>
where
- T: TypeFoldable<'tcx>,
+ T: TypeFoldable<TyCtxt<'tcx>>,
{
self.binder_index.shift_in(1);
let t = t.super_fold_with(self);
@@ -365,12 +363,13 @@ impl<'cx, 'tcx> TypeFolder<'tcx> for Canonicalizer<'cx, 'tcx> {
opportunistically resolved to {:?}",
vid, resolved_vid
);
- let r = self.tcx.reuse_or_mk_region(r, ty::ReVar(resolved_vid));
+ let r = self.tcx.mk_re_var(resolved_vid);
self.canonicalize_mode.canonicalize_free_region(self, r)
}
ty::ReStatic
| ty::ReEarlyBound(..)
+ | ty::ReError(_)
| ty::ReFree(_)
| ty::RePlaceholder(..)
| ty::ReErased => self.canonicalize_mode.canonicalize_free_region(self, r),
@@ -419,10 +418,15 @@ impl<'cx, 'tcx> TypeFolder<'tcx> for Canonicalizer<'cx, 'tcx> {
bug!("encountered a fresh type during canonicalization")
}
- ty::Placeholder(placeholder) => self.canonicalize_ty_var(
- CanonicalVarInfo { kind: CanonicalVarKind::PlaceholderTy(placeholder) },
- t,
- ),
+ ty::Placeholder(mut placeholder) => {
+ if !self.canonicalize_mode.preserve_universes() {
+ placeholder.universe = ty::UniverseIndex::ROOT;
+ }
+ self.canonicalize_ty_var(
+ CanonicalVarInfo { kind: CanonicalVarKind::PlaceholderTy(placeholder) },
+ t,
+ )
+ }
ty::Bound(debruijn, _) => {
if debruijn >= self.binder_index {
@@ -435,6 +439,7 @@ impl<'cx, 'tcx> TypeFolder<'tcx> for Canonicalizer<'cx, 'tcx> {
ty::Closure(..)
| ty::Generator(..)
| ty::GeneratorWitness(..)
+ | ty::GeneratorWitnessMIR(..)
| ty::Bool
| ty::Char
| ty::Int(..)
@@ -525,7 +530,7 @@ impl<'cx, 'tcx> Canonicalizer<'cx, 'tcx> {
query_state: &mut OriginalQueryValues<'tcx>,
) -> Canonical<'tcx, V>
where
- V: TypeFoldable<'tcx>,
+ V: TypeFoldable<TyCtxt<'tcx>>,
{
let needs_canonical_flags = if canonicalize_region_mode.any() {
TypeFlags::NEEDS_INFER |
@@ -567,7 +572,7 @@ impl<'cx, 'tcx> Canonicalizer<'cx, 'tcx> {
debug_assert!(!out_value.needs_infer() && !out_value.has_placeholders());
let canonical_variables =
- tcx.intern_canonical_var_infos(&canonicalizer.universe_canonicalized_variables());
+ tcx.mk_canonical_var_infos(&canonicalizer.universe_canonicalized_variables());
let max_universe = canonical_variables
.iter()
@@ -737,8 +742,7 @@ impl<'cx, 'tcx> Canonicalizer<'cx, 'tcx> {
) -> ty::Region<'tcx> {
let var = self.canonical_var(info, r.into());
let br = ty::BoundRegion { var, kind: ty::BrAnon(var.as_u32(), None) };
- let region = ty::ReLateBound(self.binder_index, br);
- self.tcx().mk_region(region)
+ self.interner().mk_re_late_bound(self.binder_index, br)
}
/// Given a type variable `ty_var` of the given kind, first check
@@ -752,7 +756,7 @@ impl<'cx, 'tcx> Canonicalizer<'cx, 'tcx> {
self.fold_ty(bound_to)
} else {
let var = self.canonical_var(info, ty_var.into());
- self.tcx().mk_ty(ty::Bound(self.binder_index, var.into()))
+ self.interner().mk_bound(self.binder_index, var.into())
}
}
@@ -771,7 +775,7 @@ impl<'cx, 'tcx> Canonicalizer<'cx, 'tcx> {
self.fold_const(bound_to)
} else {
let var = self.canonical_var(info, const_var.into());
- self.tcx().mk_const(
+ self.interner().mk_const(
ty::ConstKind::Bound(self.binder_index, var),
self.fold_ty(const_var.ty()),
)
diff --git a/compiler/rustc_infer/src/infer/canonical/mod.rs b/compiler/rustc_infer/src/infer/canonical/mod.rs
index e59715b70..ce230afda 100644
--- a/compiler/rustc_infer/src/infer/canonical/mod.rs
+++ b/compiler/rustc_infer/src/infer/canonical/mod.rs
@@ -26,11 +26,11 @@ use crate::infer::{InferCtxt, RegionVariableOrigin, TypeVariableOrigin, TypeVari
use rustc_index::vec::IndexVec;
use rustc_middle::ty::fold::TypeFoldable;
use rustc_middle::ty::subst::GenericArg;
-use rustc_middle::ty::{self, BoundVar, List};
+use rustc_middle::ty::{self, List, TyCtxt};
use rustc_span::source_map::Span;
pub use rustc_middle::infer::canonical::*;
-use substitute::CanonicalExt;
+pub use substitute::CanonicalExt;
mod canonicalizer;
pub mod query_response;
@@ -55,7 +55,7 @@ impl<'tcx> InferCtxt<'tcx> {
canonical: &Canonical<'tcx, T>,
) -> (T, CanonicalVarValues<'tcx>)
where
- T: TypeFoldable<'tcx>,
+ T: TypeFoldable<TyCtxt<'tcx>>,
{
// For each universe that is referred to in the incoming
// query, create a universe in our local inference context. In
@@ -87,19 +87,24 @@ impl<'tcx> InferCtxt<'tcx> {
variables: &List<CanonicalVarInfo<'tcx>>,
universe_map: impl Fn(ty::UniverseIndex) -> ty::UniverseIndex,
) -> CanonicalVarValues<'tcx> {
- let var_values: IndexVec<BoundVar, GenericArg<'tcx>> = variables
- .iter()
- .map(|info| self.instantiate_canonical_var(span, info, &universe_map))
- .collect();
-
- CanonicalVarValues { var_values }
+ CanonicalVarValues {
+ var_values: self.tcx.mk_substs_from_iter(
+ variables
+ .iter()
+ .map(|info| self.instantiate_canonical_var(span, info, &universe_map)),
+ ),
+ }
}
/// Given the "info" about a canonical variable, creates a fresh
/// variable for it. If this is an existentially quantified
/// variable, then you'll get a new inference variable; if it is a
/// universally quantified variable, you get a placeholder.
- fn instantiate_canonical_var(
+ ///
+ /// FIXME(-Ztrait-solver=next): This is public because it's used by the
+ /// new trait solver which has a different canonicalization routine.
+ /// We should somehow deduplicate all of this.
+ pub fn instantiate_canonical_var(
&self,
span: Span,
cv_info: CanonicalVarInfo<'tcx>,
@@ -123,7 +128,7 @@ impl<'tcx> InferCtxt<'tcx> {
CanonicalVarKind::PlaceholderTy(ty::PlaceholderType { universe, name }) => {
let universe_mapped = universe_map(universe);
let placeholder_mapped = ty::PlaceholderType { universe: universe_mapped, name };
- self.tcx.mk_ty(ty::Placeholder(placeholder_mapped)).into()
+ self.tcx.mk_placeholder(placeholder_mapped).into()
}
CanonicalVarKind::Region(ui) => self
@@ -136,7 +141,7 @@ impl<'tcx> InferCtxt<'tcx> {
CanonicalVarKind::PlaceholderRegion(ty::PlaceholderRegion { universe, name }) => {
let universe_mapped = universe_map(universe);
let placeholder_mapped = ty::PlaceholderRegion { universe: universe_mapped, name };
- self.tcx.mk_region(ty::RePlaceholder(placeholder_mapped)).into()
+ self.tcx.mk_re_placeholder(placeholder_mapped).into()
}
CanonicalVarKind::Const(ui, ty) => self
diff --git a/compiler/rustc_infer/src/infer/canonical/query_response.rs b/compiler/rustc_infer/src/infer/canonical/query_response.rs
index 3d49182f0..436d29c24 100644
--- a/compiler/rustc_infer/src/infer/canonical/query_response.rs
+++ b/compiler/rustc_infer/src/infer/canonical/query_response.rs
@@ -12,12 +12,12 @@ use crate::infer::canonical::{
Canonical, CanonicalQueryResponse, CanonicalVarValues, Certainty, OriginalQueryValues,
QueryOutlivesConstraint, QueryRegionConstraints, QueryResponse,
};
-use crate::infer::nll_relate::{NormalizationStrategy, TypeRelating, TypeRelatingDelegate};
+use crate::infer::nll_relate::{TypeRelating, TypeRelatingDelegate};
use crate::infer::region_constraints::{Constraint, RegionConstraintData};
use crate::infer::{InferCtxt, InferOk, InferResult, NllRegionVariableOrigin};
use crate::traits::query::{Fallible, NoSolution};
use crate::traits::{Obligation, ObligationCause, PredicateObligation};
-use crate::traits::{PredicateObligations, TraitEngine};
+use crate::traits::{PredicateObligations, TraitEngine, TraitEngineExt};
use rustc_data_structures::captures::Captures;
use rustc_index::vec::Idx;
use rustc_index::vec::IndexVec;
@@ -27,7 +27,7 @@ use rustc_middle::ty::fold::TypeFoldable;
use rustc_middle::ty::relate::TypeRelation;
use rustc_middle::ty::subst::{GenericArg, GenericArgKind};
use rustc_middle::ty::{self, BoundVar, ToPredicate, Ty, TyCtxt};
-use rustc_span::Span;
+use rustc_span::{Span, Symbol};
use std::fmt::Debug;
use std::iter;
@@ -59,7 +59,7 @@ impl<'tcx> InferCtxt<'tcx> {
fulfill_cx: &mut dyn TraitEngine<'tcx>,
) -> Fallible<CanonicalQueryResponse<'tcx, T>>
where
- T: Debug + TypeFoldable<'tcx>,
+ T: Debug + TypeFoldable<TyCtxt<'tcx>>,
Canonical<'tcx, QueryResponse<'tcx, T>>: ArenaAllocatable<'tcx>,
{
let query_response = self.make_query_response(inference_vars, answer, fulfill_cx)?;
@@ -85,7 +85,7 @@ impl<'tcx> InferCtxt<'tcx> {
answer: T,
) -> Canonical<'tcx, QueryResponse<'tcx, T>>
where
- T: Debug + TypeFoldable<'tcx>,
+ T: Debug + TypeFoldable<TyCtxt<'tcx>>,
{
self.canonicalize_response(QueryResponse {
var_values: inference_vars,
@@ -106,7 +106,7 @@ impl<'tcx> InferCtxt<'tcx> {
fulfill_cx: &mut dyn TraitEngine<'tcx>,
) -> Result<QueryResponse<'tcx, T>, NoSolution>
where
- T: Debug + TypeFoldable<'tcx>,
+ T: Debug + TypeFoldable<TyCtxt<'tcx>>,
{
let tcx = self.tcx;
@@ -151,11 +151,21 @@ impl<'tcx> InferCtxt<'tcx> {
})
}
- /// FIXME: This method should only be used for canonical queries and therefore be private.
- ///
- /// As the new solver does canonicalization slightly differently, this is also used there
- /// for now. This should hopefully change fairly soon.
- pub fn take_opaque_types_for_query_response(&self) -> Vec<(Ty<'tcx>, Ty<'tcx>)> {
+ /// Used by the new solver as that one takes the opaque types at the end of a probe
+ /// to deal with multiple candidates without having to recompute them.
+ pub fn clone_opaque_types_for_query_response(&self) -> Vec<(Ty<'tcx>, Ty<'tcx>)> {
+ self.inner
+ .borrow()
+ .opaque_type_storage
+ .opaque_types
+ .iter()
+ .map(|&(k, ref v)| {
+ (self.tcx.mk_opaque(k.def_id.to_def_id(), k.substs), v.hidden_type.ty)
+ })
+ .collect()
+ }
+
+ fn take_opaque_types_for_query_response(&self) -> Vec<(Ty<'tcx>, Ty<'tcx>)> {
std::mem::take(&mut self.inner.borrow_mut().opaque_type_storage.opaque_types)
.into_iter()
.map(|(k, v)| (self.tcx.mk_opaque(k.def_id.to_def_id(), k.substs), v.hidden_type.ty))
@@ -180,7 +190,7 @@ impl<'tcx> InferCtxt<'tcx> {
query_response: &Canonical<'tcx, QueryResponse<'tcx, R>>,
) -> InferResult<'tcx, R>
where
- R: Debug + TypeFoldable<'tcx>,
+ R: Debug + TypeFoldable<TyCtxt<'tcx>>,
{
let InferOk { value: result_subst, mut obligations } =
self.query_response_substitution(cause, param_env, original_values, query_response)?;
@@ -242,7 +252,7 @@ impl<'tcx> InferCtxt<'tcx> {
output_query_region_constraints: &mut QueryRegionConstraints<'tcx>,
) -> InferResult<'tcx, R>
where
- R: Debug + TypeFoldable<'tcx>,
+ R: Debug + TypeFoldable<TyCtxt<'tcx>>,
{
let InferOk { value: result_subst, mut obligations } = self
.query_response_substitution_guess(cause, param_env, original_values, query_response)?;
@@ -268,14 +278,12 @@ impl<'tcx> InferCtxt<'tcx> {
(GenericArgKind::Lifetime(v_o), GenericArgKind::Lifetime(v_r)) => {
// To make `v_o = v_r`, we emit `v_o: v_r` and `v_r: v_o`.
if v_o != v_r {
- output_query_region_constraints.outlives.push((
- ty::Binder::dummy(ty::OutlivesPredicate(v_o.into(), v_r)),
- constraint_category,
- ));
- output_query_region_constraints.outlives.push((
- ty::Binder::dummy(ty::OutlivesPredicate(v_r.into(), v_o)),
- constraint_category,
- ));
+ output_query_region_constraints
+ .outlives
+ .push((ty::OutlivesPredicate(v_o.into(), v_r), constraint_category));
+ output_query_region_constraints
+ .outlives
+ .push((ty::OutlivesPredicate(v_r.into(), v_o), constraint_category));
}
}
@@ -318,10 +326,8 @@ impl<'tcx> InferCtxt<'tcx> {
query_response.value.region_constraints.outlives.iter().filter_map(|&r_c| {
let r_c = substitute_value(self.tcx, &result_subst, r_c);
- // Screen out `'a: 'a` cases -- we skip the binder here but
- // only compare the inner values to one another, so they are still at
- // consistent binding levels.
- let ty::OutlivesPredicate(k1, r2) = r_c.0.skip_binder();
+ // Screen out `'a: 'a` cases.
+ let ty::OutlivesPredicate(k1, r2) = r_c.0;
if k1 != r2.into() { Some(r_c) } else { None }
}),
);
@@ -360,7 +366,7 @@ impl<'tcx> InferCtxt<'tcx> {
query_response: &Canonical<'tcx, QueryResponse<'tcx, R>>,
) -> InferResult<'tcx, CanonicalVarValues<'tcx>>
where
- R: Debug + TypeFoldable<'tcx>,
+ R: Debug + TypeFoldable<TyCtxt<'tcx>>,
{
debug!(
"query_response_substitution(original_values={:#?}, query_response={:#?})",
@@ -397,6 +403,7 @@ impl<'tcx> InferCtxt<'tcx> {
/// will instantiate fresh inference variables for each canonical
/// variable instead. Therefore, the result of this method must be
/// properly unified
+ #[instrument(level = "debug", skip(self, cause, param_env))]
fn query_response_substitution_guess<R>(
&self,
cause: &ObligationCause<'tcx>,
@@ -405,13 +412,8 @@ impl<'tcx> InferCtxt<'tcx> {
query_response: &Canonical<'tcx, QueryResponse<'tcx, R>>,
) -> InferResult<'tcx, CanonicalVarValues<'tcx>>
where
- R: Debug + TypeFoldable<'tcx>,
+ R: Debug + TypeFoldable<TyCtxt<'tcx>>,
{
- debug!(
- "query_response_substitution_guess(original_values={:#?}, query_response={:#?})",
- original_values, query_response,
- );
-
// For each new universe created in the query result that did
// not appear in the original query, create a local
// superuniverse.
@@ -482,11 +484,8 @@ impl<'tcx> InferCtxt<'tcx> {
// given variable in the loop above, use that. Otherwise, use
// a fresh inference variable.
let result_subst = CanonicalVarValues {
- var_values: query_response
- .variables
- .iter()
- .enumerate()
- .map(|(index, info)| {
+ var_values: self.tcx.mk_substs_from_iter(
+ query_response.variables.iter().enumerate().map(|(index, info)| {
if info.is_existential() {
match opt_values[BoundVar::new(index)] {
Some(k) => k,
@@ -499,8 +498,8 @@ impl<'tcx> InferCtxt<'tcx> {
universe_map[u.as_usize()]
})
}
- })
- .collect(),
+ }),
+ ),
};
let mut obligations = vec![];
@@ -509,7 +508,9 @@ impl<'tcx> InferCtxt<'tcx> {
for &(a, b) in &query_response.value.opaque_types {
let a = substitute_value(self.tcx, &result_subst, a);
let b = substitute_value(self.tcx, &result_subst, b);
- obligations.extend(self.at(cause, param_env).eq(a, b)?.obligations);
+ debug!(?a, ?b, "constrain opaque type");
+ obligations
+ .extend(self.at(cause, param_env).define_opaque_types(true).eq(a, b)?.obligations);
}
Ok(InferOk { value: result_subst, obligations })
@@ -530,7 +531,7 @@ impl<'tcx> InferCtxt<'tcx> {
query_response: &Canonical<'tcx, QueryResponse<'tcx, R>>,
) -> InferResult<'tcx, ()>
where
- R: Debug + TypeFoldable<'tcx>,
+ R: Debug + TypeFoldable<TyCtxt<'tcx>>,
{
// A closure that yields the result value for the given
// canonical variable; this is taken from
@@ -562,11 +563,11 @@ impl<'tcx> InferCtxt<'tcx> {
pub fn query_outlives_constraint_to_obligation(
&self,
- predicate: QueryOutlivesConstraint<'tcx>,
+ (predicate, _): QueryOutlivesConstraint<'tcx>,
cause: ObligationCause<'tcx>,
param_env: ty::ParamEnv<'tcx>,
) -> Obligation<'tcx, ty::Predicate<'tcx>> {
- let ty::OutlivesPredicate(k1, r2) = predicate.0.skip_binder();
+ let ty::OutlivesPredicate(k1, r2) = predicate;
let atom = match k1.unpack() {
GenericArgKind::Lifetime(r1) => {
@@ -581,7 +582,7 @@ impl<'tcx> InferCtxt<'tcx> {
span_bug!(cause.span, "unexpected const outlives {:?}", predicate);
}
};
- let predicate = predicate.0.rebind(atom);
+ let predicate = ty::Binder::dummy(atom);
Obligation::new(self.tcx, cause, param_env, predicate)
}
@@ -646,31 +647,25 @@ pub fn make_query_region_constraints<'tcx>(
let outlives: Vec<_> = constraints
.iter()
.map(|(k, origin)| {
- // no bound vars in the code above
- let constraint = ty::Binder::dummy(match *k {
+ let constraint = match *k {
// Swap regions because we are going from sub (<=) to outlives
// (>=).
- Constraint::VarSubVar(v1, v2) => ty::OutlivesPredicate(
- tcx.mk_region(ty::ReVar(v2)).into(),
- tcx.mk_region(ty::ReVar(v1)),
- ),
+ Constraint::VarSubVar(v1, v2) => {
+ ty::OutlivesPredicate(tcx.mk_re_var(v2).into(), tcx.mk_re_var(v1))
+ }
Constraint::VarSubReg(v1, r2) => {
- ty::OutlivesPredicate(r2.into(), tcx.mk_region(ty::ReVar(v1)))
+ ty::OutlivesPredicate(r2.into(), tcx.mk_re_var(v1))
}
Constraint::RegSubVar(r1, v2) => {
- ty::OutlivesPredicate(tcx.mk_region(ty::ReVar(v2)).into(), r1)
+ ty::OutlivesPredicate(tcx.mk_re_var(v2).into(), r1)
}
Constraint::RegSubReg(r1, r2) => ty::OutlivesPredicate(r2.into(), r1),
- });
+ };
(constraint, origin.to_constraint_category())
})
- .chain(
- outlives_obligations
- // no bound vars in the code above
- .map(|(ty, r, constraint_category)| {
- (ty::Binder::dummy(ty::OutlivesPredicate(ty.into(), r)), constraint_category)
- }),
- )
+ .chain(outlives_obligations.map(|(ty, r, constraint_category)| {
+ (ty::OutlivesPredicate(ty.into(), r), constraint_category)
+ }))
.collect();
QueryRegionConstraints { outlives, member_constraints: member_constraints.clone() }
@@ -696,13 +691,17 @@ impl<'tcx> TypeRelatingDelegate<'tcx> for QueryTypeRelatingDelegate<'_, 'tcx> {
self.infcx.create_next_universe()
}
- fn next_existential_region_var(&mut self, from_forall: bool) -> ty::Region<'tcx> {
+ fn next_existential_region_var(
+ &mut self,
+ from_forall: bool,
+ _name: Option<Symbol>,
+ ) -> 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.infcx.tcx.mk_region(ty::RePlaceholder(placeholder))
+ self.infcx.tcx.mk_re_placeholder(placeholder)
}
fn generalize_existential(&mut self, universe: ty::UniverseIndex) -> ty::Region<'tcx> {
@@ -729,10 +728,6 @@ impl<'tcx> TypeRelatingDelegate<'tcx> for QueryTypeRelatingDelegate<'_, 'tcx> {
});
}
- fn normalization() -> NormalizationStrategy {
- NormalizationStrategy::Eager
- }
-
fn forbid_inference_vars() -> bool {
true
}
diff --git a/compiler/rustc_infer/src/infer/canonical/substitute.rs b/compiler/rustc_infer/src/infer/canonical/substitute.rs
index 389afe22e..cac3b4072 100644
--- a/compiler/rustc_infer/src/infer/canonical/substitute.rs
+++ b/compiler/rustc_infer/src/infer/canonical/substitute.rs
@@ -11,12 +11,14 @@ use rustc_middle::ty::fold::{FnMutDelegate, TypeFoldable};
use rustc_middle::ty::subst::GenericArgKind;
use rustc_middle::ty::{self, TyCtxt};
-pub(super) trait CanonicalExt<'tcx, V> {
+/// FIXME(-Ztrait-solver=next): This or public because it is shared with the
+/// new trait solver implementation. We should deduplicate canonicalization.
+pub trait CanonicalExt<'tcx, V> {
/// Instantiate the wrapped value, replacing each canonical value
/// with the value given in `var_values`.
fn substitute(&self, tcx: TyCtxt<'tcx>, var_values: &CanonicalVarValues<'tcx>) -> V
where
- V: TypeFoldable<'tcx>;
+ V: TypeFoldable<TyCtxt<'tcx>>;
/// Allows one to apply a substitute to some subset of
/// `self.value`. Invoke `projection_fn` with `self.value` to get
@@ -31,13 +33,13 @@ pub(super) trait CanonicalExt<'tcx, V> {
projection_fn: impl FnOnce(&V) -> T,
) -> T
where
- T: TypeFoldable<'tcx>;
+ T: TypeFoldable<TyCtxt<'tcx>>;
}
impl<'tcx, V> CanonicalExt<'tcx, V> for Canonical<'tcx, V> {
fn substitute(&self, tcx: TyCtxt<'tcx>, var_values: &CanonicalVarValues<'tcx>) -> V
where
- V: TypeFoldable<'tcx>,
+ V: TypeFoldable<TyCtxt<'tcx>>,
{
self.substitute_projected(tcx, var_values, |value| value.clone())
}
@@ -49,7 +51,7 @@ impl<'tcx, V> CanonicalExt<'tcx, V> for Canonical<'tcx, V> {
projection_fn: impl FnOnce(&V) -> T,
) -> T
where
- T: TypeFoldable<'tcx>,
+ T: TypeFoldable<TyCtxt<'tcx>>,
{
assert_eq!(self.variables.len(), var_values.len());
let value = projection_fn(&self.value);
@@ -66,22 +68,21 @@ pub(super) fn substitute_value<'tcx, T>(
value: T,
) -> T
where
- T: TypeFoldable<'tcx>,
+ T: TypeFoldable<TyCtxt<'tcx>>,
{
if var_values.var_values.is_empty() {
value
} else {
let delegate = FnMutDelegate {
- regions: &mut |br: ty::BoundRegion| match var_values.var_values[br.var].unpack() {
+ regions: &mut |br: ty::BoundRegion| match var_values[br.var].unpack() {
GenericArgKind::Lifetime(l) => l,
r => bug!("{:?} is a region but value is {:?}", br, r),
},
- types: &mut |bound_ty: ty::BoundTy| match var_values.var_values[bound_ty.var].unpack() {
+ types: &mut |bound_ty: ty::BoundTy| match var_values[bound_ty.var].unpack() {
GenericArgKind::Type(ty) => ty,
r => bug!("{:?} is a type but value is {:?}", bound_ty, r),
},
- consts: &mut |bound_ct: ty::BoundVar, _| match var_values.var_values[bound_ct].unpack()
- {
+ consts: &mut |bound_ct: ty::BoundVar, _| match var_values[bound_ct].unpack() {
GenericArgKind::Const(ct) => ct,
c => bug!("{:?} is a const but value is {:?}", bound_ct, c),
},
diff --git a/compiler/rustc_infer/src/infer/combine.rs b/compiler/rustc_infer/src/infer/combine.rs
index 72676b718..33292e871 100644
--- a/compiler/rustc_infer/src/infer/combine.rs
+++ b/compiler/rustc_infer/src/infer/combine.rs
@@ -31,13 +31,18 @@ use super::{InferCtxt, MiscVariable, TypeTrace};
use crate::traits::{Obligation, PredicateObligations};
use rustc_data_structures::sso::SsoHashMap;
use rustc_hir::def_id::DefId;
+use rustc_middle::infer::canonical::OriginalQueryValues;
use rustc_middle::infer::unify_key::{ConstVarValue, ConstVariableValue};
use rustc_middle::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind};
+use rustc_middle::traits::query::NoSolution;
use rustc_middle::traits::ObligationCause;
use rustc_middle::ty::error::{ExpectedFound, TypeError};
use rustc_middle::ty::relate::{self, Relate, RelateResult, TypeRelation};
use rustc_middle::ty::subst::SubstsRef;
-use rustc_middle::ty::{self, InferConst, Ty, TyCtxt, TypeVisitable};
+use rustc_middle::ty::{
+ self, AliasKind, FallibleTypeFolder, InferConst, ToPredicate, Ty, TyCtxt, TypeFoldable,
+ TypeSuperFoldable, TypeVisitableExt,
+};
use rustc_middle::ty::{IntType, UintType};
use rustc_span::{Span, DUMMY_SP};
@@ -71,7 +76,7 @@ impl<'tcx> InferCtxt<'tcx> {
b: Ty<'tcx>,
) -> RelateResult<'tcx, Ty<'tcx>>
where
- R: TypeRelation<'tcx>,
+ R: ObligationEmittingRelation<'tcx>,
{
let a_is_expected = relation.a_is_expected();
@@ -119,6 +124,15 @@ impl<'tcx> InferCtxt<'tcx> {
Err(TypeError::Sorts(ty::relate::expected_found(relation, a, b)))
}
+ (ty::Alias(AliasKind::Projection, _), _) if self.tcx.trait_solver_next() => {
+ relation.register_type_equate_obligation(a, b);
+ Ok(b)
+ }
+ (_, ty::Alias(AliasKind::Projection, _)) if self.tcx.trait_solver_next() => {
+ relation.register_type_equate_obligation(b, a);
+ Ok(a)
+ }
+
_ => ty::relate::super_relate_tys(relation, a, b),
}
}
@@ -130,7 +144,7 @@ impl<'tcx> InferCtxt<'tcx> {
b: ty::Const<'tcx>,
) -> RelateResult<'tcx, ty::Const<'tcx>>
where
- R: ConstEquateRelation<'tcx>,
+ R: ObligationEmittingRelation<'tcx>,
{
debug!("{}.consts({:?}, {:?})", relation.tag(), a, b);
if a == b {
@@ -140,7 +154,33 @@ impl<'tcx> InferCtxt<'tcx> {
let a = self.shallow_resolve(a);
let b = self.shallow_resolve(b);
- let a_is_expected = relation.a_is_expected();
+ // We should never have to relate the `ty` field on `Const` as it is checked elsewhere that consts have the
+ // correct type for the generic param they are an argument for. However there have been a number of cases
+ // historically where asserting that the types are equal has found bugs in the compiler so this is valuable
+ // to check even if it is a bit nasty impl wise :(
+ //
+ // This probe is probably not strictly necessary but it seems better to be safe and not accidentally find
+ // ourselves with a check to find bugs being required for code to compile because it made inference progress.
+ self.probe(|_| {
+ if a.ty() == b.ty() {
+ return;
+ }
+
+ // We don't have access to trait solving machinery in `rustc_infer` so the logic for determining if the
+ // two const param's types are able to be equal has to go through a canonical query with the actual logic
+ // in `rustc_trait_selection`.
+ let canonical = self.canonicalize_query(
+ (relation.param_env(), a.ty(), b.ty()),
+ &mut OriginalQueryValues::default(),
+ );
+
+ if let Err(NoSolution) = self.tcx.check_tys_might_be_eq(canonical) {
+ self.tcx.sess.delay_span_bug(
+ DUMMY_SP,
+ &format!("cannot relate consts of different types (a={:?}, b={:?})", a, b,),
+ );
+ }
+ });
match (a.kind(), b.kind()) {
(
@@ -158,17 +198,17 @@ impl<'tcx> InferCtxt<'tcx> {
}
(ty::ConstKind::Infer(InferConst::Var(vid)), _) => {
- return self.unify_const_variable(relation.param_env(), vid, b, a_is_expected);
+ return self.unify_const_variable(vid, b);
}
(_, ty::ConstKind::Infer(InferConst::Var(vid))) => {
- return self.unify_const_variable(relation.param_env(), vid, a, !a_is_expected);
+ return self.unify_const_variable(vid, a);
}
(ty::ConstKind::Unevaluated(..), _) if self.tcx.lazy_normalization() => {
// FIXME(#59490): Need to remove the leak check to accommodate
// escaping bound variables here.
if !a.has_escaping_bound_vars() && !b.has_escaping_bound_vars() {
- relation.const_equate_obligation(a, b);
+ relation.register_const_equate_obligation(a, b);
}
return Ok(b);
}
@@ -176,7 +216,7 @@ impl<'tcx> InferCtxt<'tcx> {
// FIXME(#59490): Need to remove the leak check to accommodate
// escaping bound variables here.
if !a.has_escaping_bound_vars() && !b.has_escaping_bound_vars() {
- relation.const_equate_obligation(a, b);
+ relation.register_const_equate_obligation(a, b);
}
return Ok(a);
}
@@ -223,10 +263,8 @@ impl<'tcx> InferCtxt<'tcx> {
#[instrument(level = "debug", skip(self))]
fn unify_const_variable(
&self,
- param_env: ty::ParamEnv<'tcx>,
target_vid: ty::ConstVid<'tcx>,
ct: ty::Const<'tcx>,
- vid_is_expected: bool,
) -> RelateResult<'tcx, ty::Const<'tcx>> {
let (for_universe, span) = {
let mut inner = self.inner.borrow_mut();
@@ -239,8 +277,12 @@ impl<'tcx> InferCtxt<'tcx> {
ConstVariableValue::Unknown { universe } => (universe, var_value.origin.span),
}
};
- let value = ConstInferUnifier { infcx: self, span, param_env, for_universe, target_vid }
- .relate(ct, ct)?;
+ let value = ct.try_fold_with(&mut ConstInferUnifier {
+ infcx: self,
+ span,
+ for_universe,
+ target_vid,
+ })?;
self.inner.borrow_mut().const_unification_table().union_value(
target_vid,
@@ -432,32 +474,18 @@ impl<'infcx, 'tcx> CombineFields<'infcx, 'tcx> {
Ok(Generalization { ty, needs_wf })
}
- pub fn add_const_equate_obligation(
- &mut self,
- a_is_expected: bool,
- a: ty::Const<'tcx>,
- b: ty::Const<'tcx>,
- ) {
- let predicate = if a_is_expected {
- ty::PredicateKind::ConstEquate(a, b)
- } else {
- ty::PredicateKind::ConstEquate(b, a)
- };
- self.obligations.push(Obligation::new(
- self.tcx(),
- self.trace.cause.clone(),
- self.param_env,
- ty::Binder::dummy(predicate),
- ));
+ pub fn register_obligations(&mut self, obligations: PredicateObligations<'tcx>) {
+ self.obligations.extend(obligations.into_iter());
+ }
+
+ pub fn register_predicates(&mut self, obligations: impl IntoIterator<Item: ToPredicate<'tcx>>) {
+ self.obligations.extend(obligations.into_iter().map(|to_pred| {
+ Obligation::new(self.infcx.tcx, self.trace.cause.clone(), self.param_env, to_pred)
+ }))
}
pub fn mark_ambiguous(&mut self) {
- self.obligations.push(Obligation::new(
- self.tcx(),
- self.trace.cause.clone(),
- self.param_env,
- ty::Binder::dummy(ty::PredicateKind::Ambiguous),
- ));
+ self.register_predicates([ty::Binder::dummy(ty::PredicateKind::Ambiguous)]);
}
}
@@ -702,6 +730,10 @@ impl<'tcx> TypeRelation<'tcx> for Generalizer<'_, 'tcx> {
return Ok(r);
}
+ ty::ReError(_) => {
+ return Ok(r);
+ }
+
ty::RePlaceholder(..)
| ty::ReVar(..)
| ty::ReStatic
@@ -772,11 +804,39 @@ impl<'tcx> TypeRelation<'tcx> for Generalizer<'_, 'tcx> {
}
}
-pub trait ConstEquateRelation<'tcx>: TypeRelation<'tcx> {
+pub trait ObligationEmittingRelation<'tcx>: TypeRelation<'tcx> {
+ /// Register obligations that must hold in order for this relation to hold
+ fn register_obligations(&mut self, obligations: PredicateObligations<'tcx>);
+
+ /// Register predicates that must hold in order for this relation to hold. Uses
+ /// a default obligation cause, [`ObligationEmittingRelation::register_obligations`] should
+ /// be used if control over the obligaton causes is required.
+ fn register_predicates(&mut self, obligations: impl IntoIterator<Item: ToPredicate<'tcx>>);
+
/// Register an obligation that both constants must be equal to each other.
///
/// If they aren't equal then the relation doesn't hold.
- fn const_equate_obligation(&mut self, a: ty::Const<'tcx>, b: ty::Const<'tcx>);
+ fn register_const_equate_obligation(&mut self, a: ty::Const<'tcx>, b: ty::Const<'tcx>) {
+ let (a, b) = if self.a_is_expected() { (a, b) } else { (b, a) };
+
+ self.register_predicates([ty::Binder::dummy(if self.tcx().trait_solver_next() {
+ ty::PredicateKind::AliasEq(a.into(), b.into())
+ } else {
+ ty::PredicateKind::ConstEquate(a, b)
+ })]);
+ }
+
+ /// Register an obligation that both types must be equal to each other.
+ ///
+ /// If they aren't equal then the relation doesn't hold.
+ fn register_type_equate_obligation(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) {
+ let (a, b) = if self.a_is_expected() { (a, b) } else { (b, a) };
+
+ self.register_predicates([ty::Binder::dummy(ty::PredicateKind::AliasEq(
+ a.into(),
+ b.into(),
+ ))]);
+ }
}
fn int_unification_error<'tcx>(
@@ -800,8 +860,6 @@ struct ConstInferUnifier<'cx, 'tcx> {
span: Span,
- param_env: ty::ParamEnv<'tcx>,
-
for_universe: ty::UniverseIndex,
/// The vid of the const variable that is in the process of being
@@ -810,61 +868,15 @@ struct ConstInferUnifier<'cx, 'tcx> {
target_vid: ty::ConstVid<'tcx>,
}
-// We use `TypeRelation` here to propagate `RelateResult` upwards.
-//
-// Both inputs are expected to be the same.
-impl<'tcx> TypeRelation<'tcx> for ConstInferUnifier<'_, 'tcx> {
- fn tcx(&self) -> TyCtxt<'tcx> {
- self.infcx.tcx
- }
-
- fn intercrate(&self) -> bool {
- assert!(!self.infcx.intercrate);
- false
- }
-
- fn param_env(&self) -> ty::ParamEnv<'tcx> {
- self.param_env
- }
-
- fn tag(&self) -> &'static str {
- "ConstInferUnifier"
- }
-
- fn a_is_expected(&self) -> bool {
- true
- }
-
- fn mark_ambiguous(&mut self) {
- bug!()
- }
+impl<'tcx> FallibleTypeFolder<TyCtxt<'tcx>> for ConstInferUnifier<'_, 'tcx> {
+ type Error = TypeError<'tcx>;
- fn relate_with_variance<T: Relate<'tcx>>(
- &mut self,
- _variance: ty::Variance,
- _info: ty::VarianceDiagInfo<'tcx>,
- a: T,
- b: T,
- ) -> RelateResult<'tcx, T> {
- // We don't care about variance here.
- self.relate(a, b)
- }
-
- fn binders<T>(
- &mut self,
- a: ty::Binder<'tcx, T>,
- b: ty::Binder<'tcx, T>,
- ) -> RelateResult<'tcx, ty::Binder<'tcx, T>>
- where
- T: Relate<'tcx>,
- {
- Ok(a.rebind(self.relate(a.skip_binder(), b.skip_binder())?))
+ fn interner(&self) -> TyCtxt<'tcx> {
+ self.infcx.tcx
}
#[instrument(level = "debug", skip(self), ret)]
- fn tys(&mut self, t: Ty<'tcx>, _t: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> {
- debug_assert_eq!(t, _t);
-
+ fn try_fold_ty(&mut self, t: Ty<'tcx>) -> Result<Ty<'tcx>, TypeError<'tcx>> {
match t.kind() {
&ty::Infer(ty::TyVar(vid)) => {
let vid = self.infcx.inner.borrow_mut().type_variables().root_var(vid);
@@ -872,7 +884,7 @@ impl<'tcx> TypeRelation<'tcx> for ConstInferUnifier<'_, 'tcx> {
match probe {
TypeVariableValue::Known { value: u } => {
debug!("ConstOccursChecker: known value {:?}", u);
- self.tys(u, u)
+ u.try_fold_with(self)
}
TypeVariableValue::Unknown { universe } => {
if self.for_universe.can_name(universe) {
@@ -887,27 +899,26 @@ impl<'tcx> TypeRelation<'tcx> for ConstInferUnifier<'_, 'tcx> {
.borrow_mut()
.type_variables()
.new_var(self.for_universe, origin);
- Ok(self.tcx().mk_ty_var(new_var_id))
+ Ok(self.interner().mk_ty_var(new_var_id))
}
}
}
ty::Infer(ty::IntVar(_) | ty::FloatVar(_)) => Ok(t),
- _ => relate::super_relate_tys(self, t, t),
+ _ => t.try_super_fold_with(self),
}
}
- fn regions(
+ #[instrument(level = "debug", skip(self), ret)]
+ fn try_fold_region(
&mut self,
r: ty::Region<'tcx>,
- _r: ty::Region<'tcx>,
- ) -> RelateResult<'tcx, ty::Region<'tcx>> {
- debug_assert_eq!(r, _r);
+ ) -> Result<ty::Region<'tcx>, TypeError<'tcx>> {
debug!("ConstInferUnifier: r={:?}", r);
match *r {
// Never make variables for regions bound within the type itself,
// nor for erased regions.
- ty::ReLateBound(..) | ty::ReErased => {
+ ty::ReLateBound(..) | ty::ReErased | ty::ReError(_) => {
return Ok(r);
}
@@ -930,14 +941,8 @@ impl<'tcx> TypeRelation<'tcx> for ConstInferUnifier<'_, 'tcx> {
}
}
- #[instrument(level = "debug", skip(self))]
- fn consts(
- &mut self,
- c: ty::Const<'tcx>,
- _c: ty::Const<'tcx>,
- ) -> RelateResult<'tcx, ty::Const<'tcx>> {
- debug_assert_eq!(c, _c);
-
+ #[instrument(level = "debug", skip(self), ret)]
+ fn try_fold_const(&mut self, c: ty::Const<'tcx>) -> Result<ty::Const<'tcx>, TypeError<'tcx>> {
match c.kind() {
ty::ConstKind::Infer(InferConst::Var(vid)) => {
// Check if the current unification would end up
@@ -958,7 +963,7 @@ impl<'tcx> TypeRelation<'tcx> for ConstInferUnifier<'_, 'tcx> {
let var_value =
self.infcx.inner.borrow_mut().const_unification_table().probe_value(vid);
match var_value.val {
- ConstVariableValue::Known { value: u } => self.consts(u, u),
+ ConstVariableValue::Known { value: u } => u.try_fold_with(self),
ConstVariableValue::Unknown { universe } => {
if self.for_universe.can_name(universe) {
Ok(c)
@@ -972,22 +977,12 @@ impl<'tcx> TypeRelation<'tcx> for ConstInferUnifier<'_, 'tcx> {
},
},
);
- Ok(self.tcx().mk_const(new_var_id, c.ty()))
+ Ok(self.interner().mk_const(new_var_id, c.ty()))
}
}
}
}
- ty::ConstKind::Unevaluated(ty::UnevaluatedConst { def, substs }) => {
- let substs = self.relate_with_variance(
- ty::Variance::Invariant,
- ty::VarianceDiagInfo::default(),
- substs,
- substs,
- )?;
-
- Ok(self.tcx().mk_const(ty::UnevaluatedConst { def, substs }, c.ty()))
- }
- _ => relate::super_relate_consts(self, c, c),
+ _ => c.try_super_fold_with(self),
}
}
}
diff --git a/compiler/rustc_infer/src/infer/equate.rs b/compiler/rustc_infer/src/infer/equate.rs
index 46e7813d9..54a62326e 100644
--- a/compiler/rustc_infer/src/infer/equate.rs
+++ b/compiler/rustc_infer/src/infer/equate.rs
@@ -1,10 +1,12 @@
-use super::combine::{CombineFields, ConstEquateRelation, RelationDir};
+use crate::traits::PredicateObligations;
+
+use super::combine::{CombineFields, ObligationEmittingRelation, RelationDir};
use super::Subtype;
use rustc_middle::ty::relate::{self, Relate, RelateResult, TypeRelation};
use rustc_middle::ty::subst::SubstsRef;
use rustc_middle::ty::TyVar;
-use rustc_middle::ty::{self, Ty, TyCtxt};
+use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt};
use rustc_hir::def_id::DefId;
@@ -129,7 +131,7 @@ impl<'tcx> TypeRelation<'tcx> for Equate<'_, '_, 'tcx> {
let a_types = infcx.tcx.anonymize_bound_vars(a_types);
let b_types = infcx.tcx.anonymize_bound_vars(b_types);
if a_types.bound_vars() == b_types.bound_vars() {
- let (a_types, b_types) = infcx.replace_bound_vars_with_placeholders(
+ let (a_types, b_types) = infcx.instantiate_binder_with_placeholders(
a_types.map_bound(|a_types| (a_types, b_types.skip_binder())),
);
for (a, b) in std::iter::zip(a_types, b_types) {
@@ -198,8 +200,12 @@ impl<'tcx> TypeRelation<'tcx> for Equate<'_, '_, 'tcx> {
}
}
-impl<'tcx> ConstEquateRelation<'tcx> for Equate<'_, '_, 'tcx> {
- fn const_equate_obligation(&mut self, a: ty::Const<'tcx>, b: ty::Const<'tcx>) {
- self.fields.add_const_equate_obligation(self.a_is_expected, a, b);
+impl<'tcx> ObligationEmittingRelation<'tcx> for Equate<'_, '_, 'tcx> {
+ fn register_predicates(&mut self, obligations: impl IntoIterator<Item: ty::ToPredicate<'tcx>>) {
+ self.fields.register_predicates(obligations);
+ }
+
+ fn register_obligations(&mut self, obligations: PredicateObligations<'tcx>) {
+ self.fields.register_obligations(obligations);
}
}
diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs
index 28fd03b87..8a2b800af 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs
@@ -49,6 +49,7 @@ use super::lexical_region_resolve::RegionResolutionError;
use super::region_constraints::GenericKind;
use super::{InferCtxt, RegionVariableOrigin, SubregionOrigin, TypeTrace, ValuePairs};
+use crate::errors;
use crate::infer;
use crate::infer::error_reporting::nice_region_error::find_anon_type::find_anon_type;
use crate::infer::ExpectedFound;
@@ -60,17 +61,19 @@ use crate::traits::{
use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
use rustc_errors::{pluralize, struct_span_err, Diagnostic, ErrorGuaranteed, IntoDiagnosticArg};
-use rustc_errors::{Applicability, DiagnosticBuilder, DiagnosticStyledString, MultiSpan};
+use rustc_errors::{Applicability, DiagnosticBuilder, DiagnosticStyledString};
use rustc_hir as hir;
use rustc_hir::def::DefKind;
use rustc_hir::def_id::{DefId, LocalDefId};
+use rustc_hir::intravisit::Visitor;
use rustc_hir::lang_items::LangItem;
use rustc_hir::Node;
use rustc_middle::dep_graph::DepContext;
+use rustc_middle::ty::print::with_forced_trimmed_paths;
use rustc_middle::ty::relate::{self, RelateResult, TypeRelation};
use rustc_middle::ty::{
self, error::TypeError, List, Region, Ty, TyCtxt, TypeFoldable, TypeSuperVisitable,
- TypeVisitable,
+ TypeVisitable, TypeVisitableExt,
};
use rustc_span::{sym, symbol::kw, BytePos, DesugaringKind, Pos, Span};
use rustc_target::spec::abi;
@@ -79,6 +82,7 @@ use std::path::PathBuf;
use std::{cmp, fmt, iter};
mod note;
+mod note_and_explain;
mod suggest;
pub(crate) mod need_type_info;
@@ -126,19 +130,16 @@ pub(super) fn note_and_explain_region<'tcx>(
alt_span: Option<Span>,
) {
let (description, span) = match *region {
- ty::ReEarlyBound(_) | ty::ReFree(_) | ty::ReStatic => {
- msg_span_from_free_region(tcx, region, alt_span)
+ ty::ReEarlyBound(_) | ty::ReFree(_) | ty::RePlaceholder(_) | ty::ReStatic => {
+ msg_span_from_named_region(tcx, region, alt_span)
}
- ty::RePlaceholder(_) => return,
+ ty::ReError(_) => return,
- // FIXME(#13998) RePlaceholder should probably print like
- // ReFree rather than dumping Debug output on the user.
- //
// We shouldn't really be having unification failures with ReVar
// and ReLateBound though.
ty::ReVar(_) | ty::ReLateBound(..) | ty::ReErased => {
- (format!("lifetime {:?}", region), alt_span)
+ (format!("lifetime `{region}`"), alt_span)
}
};
@@ -152,12 +153,12 @@ fn explain_free_region<'tcx>(
region: ty::Region<'tcx>,
suffix: &str,
) {
- let (description, span) = msg_span_from_free_region(tcx, region, None);
+ let (description, span) = msg_span_from_named_region(tcx, region, None);
label_msg_span(err, prefix, description, span, suffix);
}
-fn msg_span_from_free_region<'tcx>(
+fn msg_span_from_named_region<'tcx>(
tcx: TyCtxt<'tcx>,
region: ty::Region<'tcx>,
alt_span: Option<Span>,
@@ -168,6 +169,18 @@ fn msg_span_from_free_region<'tcx>(
(msg, Some(span))
}
ty::ReStatic => ("the static lifetime".to_owned(), alt_span),
+ ty::RePlaceholder(ty::PlaceholderRegion {
+ name: ty::BoundRegionKind::BrNamed(def_id, name),
+ ..
+ }) => (format!("the lifetime `{name}` as defined here"), Some(tcx.def_span(def_id))),
+ ty::RePlaceholder(ty::PlaceholderRegion {
+ name: ty::BoundRegionKind::BrAnon(_, Some(span)),
+ ..
+ }) => (format!("the anonymous lifetime defined here"), Some(span)),
+ ty::RePlaceholder(ty::PlaceholderRegion {
+ name: ty::BoundRegionKind::BrAnon(_, None),
+ ..
+ }) => (format!("an anonymous lifetime"), None),
_ => bug!("{:?}", region),
}
}
@@ -269,15 +282,13 @@ pub fn unexpected_hidden_region_diagnostic<'tcx>(
span: Span,
hidden_ty: Ty<'tcx>,
hidden_region: ty::Region<'tcx>,
- opaque_ty: ty::OpaqueTypeKey<'tcx>,
+ opaque_ty_key: ty::OpaqueTypeKey<'tcx>,
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
- let opaque_ty = tcx.mk_opaque(opaque_ty.def_id.to_def_id(), opaque_ty.substs);
- let mut err = struct_span_err!(
- tcx.sess,
+ let mut err = tcx.sess.create_err(errors::OpaqueCapturesLifetime {
span,
- E0700,
- "hidden type for `{opaque_ty}` captures lifetime that does not appear in bounds",
- );
+ opaque_ty: tcx.mk_opaque(opaque_ty_key.def_id.to_def_id(), opaque_ty_key.substs),
+ opaque_ty_span: tcx.def_span(opaque_ty_key.def_id),
+ });
// Explain the region we are capturing.
match *hidden_region {
@@ -311,6 +322,9 @@ pub fn unexpected_hidden_region_diagnostic<'tcx>(
)
}
}
+ ty::ReError(_) => {
+ err.delay_as_bug();
+ }
_ => {
// Ugh. This is a painful case: the hidden region is not one
// that we can easily summarize or explain. This can happen
@@ -743,15 +757,16 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
};
let msg = "`match` arms have incompatible types";
err.span_label(outer, msg);
- self.suggest_remove_semi_or_return_binding(
- err,
+ if let Some(subdiag) = self.suggest_remove_semi_or_return_binding(
prior_arm_block_id,
prior_arm_ty,
prior_arm_span,
arm_block_id,
arm_ty,
arm_span,
- );
+ ) {
+ err.subdiagnostic(subdiag);
+ }
if let Some(ret_sp) = opt_suggest_box_span {
// Get return type span and point to it.
self.suggest_boxing_for_return_impl_trait(
@@ -776,15 +791,16 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
if let Some(sp) = outer_span {
err.span_label(sp, "`if` and `else` have incompatible types");
}
- self.suggest_remove_semi_or_return_binding(
- err,
+ if let Some(subdiag) = self.suggest_remove_semi_or_return_binding(
Some(then_id),
then_ty,
then_span,
Some(else_id),
else_ty,
else_span,
- );
+ ) {
+ err.subdiagnostic(subdiag);
+ }
if let Some(ret_sp) = opt_suggest_box_span {
self.suggest_boxing_for_return_impl_trait(
err,
@@ -908,7 +924,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
) -> Option<()> {
// FIXME/HACK: Go back to `SubstsRef` to use its inherent methods,
// ideally that shouldn't be necessary.
- let sub = self.tcx.intern_substs(sub);
+ let sub = self.tcx.mk_substs(sub);
for (i, ta) in sub.types().enumerate() {
if ta == other_ty {
self.highlight_outer(&mut t1_out, &mut t2_out, path, sub, i, other_ty);
@@ -1344,8 +1360,8 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
}
(ty::FnDef(did1, substs1), ty::FnDef(did2, substs2)) => {
- let sig1 = self.tcx.bound_fn_sig(*did1).subst(self.tcx, substs1);
- let sig2 = self.tcx.bound_fn_sig(*did2).subst(self.tcx, substs2);
+ let sig1 = self.tcx.fn_sig(*did1).subst(self.tcx, substs1);
+ let sig2 = self.tcx.fn_sig(*did2).subst(self.tcx, substs2);
let mut values = self.cmp_fn_sig(&sig1, &sig2);
let path1 = format!(" {{{}}}", self.tcx.def_path_str_with_substs(*did1, substs1));
let path2 = format!(" {{{}}}", self.tcx.def_path_str_with_substs(*did2, substs2));
@@ -1356,7 +1372,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
}
(ty::FnDef(did1, substs1), ty::FnPtr(sig2)) => {
- let sig1 = self.tcx.bound_fn_sig(*did1).subst(self.tcx, substs1);
+ let sig1 = self.tcx.fn_sig(*did1).subst(self.tcx, substs1);
let mut values = self.cmp_fn_sig(&sig1, sig2);
values.0.push_highlighted(format!(
" {{{}}}",
@@ -1366,7 +1382,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
}
(ty::FnPtr(sig1), ty::FnDef(did2, substs2)) => {
- let sig2 = self.tcx.bound_fn_sig(*did2).subst(self.tcx, substs2);
+ let sig2 = self.tcx.fn_sig(*did2).subst(self.tcx, substs2);
let mut values = self.cmp_fn_sig(sig1, &sig2);
values.1.push_normal(format!(
" {{{}}}",
@@ -1433,8 +1449,8 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
impl<'tcx> OpaqueTypesVisitor<'tcx> {
fn visit_expected_found(
tcx: TyCtxt<'tcx>,
- expected: impl TypeVisitable<'tcx>,
- found: impl TypeVisitable<'tcx>,
+ expected: impl TypeVisitable<TyCtxt<'tcx>>,
+ found: impl TypeVisitable<TyCtxt<'tcx>>,
ignore_span: Span,
) -> Self {
let mut types_visitor = OpaqueTypesVisitor {
@@ -1468,57 +1484,23 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
for (key, values) in types.iter() {
let count = values.len();
let kind = key.descr();
- let mut returned_async_output_error = false;
for &sp in values {
- if sp.is_desugaring(DesugaringKind::Async) && !returned_async_output_error {
- if [sp] != err.span.primary_spans() {
- let mut span: MultiSpan = sp.into();
- span.push_span_label(
- sp,
- format!(
- "checked the `Output` of this `async fn`, {}{} {}{}",
- if count > 1 { "one of the " } else { "" },
- target,
- kind,
- pluralize!(count),
- ),
- );
- err.span_note(
- span,
- "while checking the return type of the `async fn`",
- );
- } else {
- err.span_label(
- sp,
- format!(
- "checked the `Output` of this `async fn`, {}{} {}{}",
- if count > 1 { "one of the " } else { "" },
- target,
- kind,
- pluralize!(count),
- ),
- );
- err.note("while checking the return type of the `async fn`");
- }
- returned_async_output_error = true;
- } else {
- err.span_label(
- sp,
- format!(
- "{}{} {}{}",
- if count == 1 { "the " } else { "one of the " },
- target,
- kind,
- pluralize!(count),
- ),
- );
- }
+ err.span_label(
+ sp,
+ format!(
+ "{}{} {}{}",
+ if count == 1 { "the " } else { "one of the " },
+ target,
+ kind,
+ pluralize!(count),
+ ),
+ );
}
}
}
}
- impl<'tcx> ty::visit::TypeVisitor<'tcx> for OpaqueTypesVisitor<'tcx> {
+ impl<'tcx> ty::visit::TypeVisitor<TyCtxt<'tcx>> for OpaqueTypesVisitor<'tcx> {
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
if let Some((kind, def_id)) = TyCategory::from_ty(self.tcx, t) {
let span = self.tcx.def_span(def_id);
@@ -1535,7 +1517,11 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
// |
// = note: expected unit type `()`
// found closure `[closure@$DIR/issue-20862.rs:2:5: 2:14 x:_]`
- if !self.ignore_span.overlaps(span) {
+ //
+ // Also ignore opaque `Future`s that come from async fns.
+ if !self.ignore_span.overlaps(span)
+ && !span.is_desugaring(DesugaringKind::Async)
+ {
self.types.entry(kind).or_default().insert(span);
}
}
@@ -1611,16 +1597,31 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
{
format!("expected this to be `{}`", expected)
} else {
- terr.to_string()
+ terr.to_string(self.tcx).to_string()
};
label_or_note(sp, &terr);
label_or_note(span, &msg);
} else {
- label_or_note(span, &terr.to_string());
+ label_or_note(span, &terr.to_string(self.tcx));
label_or_note(sp, &msg);
}
} else {
- label_or_note(span, &terr.to_string());
+ if let Some(values) = values
+ && let Some((e, f)) = values.ty()
+ && let TypeError::ArgumentSorts(..) | TypeError::Sorts(_) = terr
+ {
+ let e = self.tcx.erase_regions(e);
+ let f = self.tcx.erase_regions(f);
+ let expected = with_forced_trimmed_paths!(e.sort_string(self.tcx));
+ let found = with_forced_trimmed_paths!(f.sort_string(self.tcx));
+ if expected == found {
+ label_or_note(span, &terr.to_string(self.tcx));
+ } else {
+ label_or_note(span, &format!("expected {expected}, found {found}"));
+ }
+ } else {
+ label_or_note(span, &terr.to_string(self.tcx));
+ }
}
if let Some((expected, found, exp_p, found_p)) = expected_found {
@@ -1688,7 +1689,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
format!("{name} is defined in the current crate")
} else {
let crate_name = self.tcx.crate_name(defid.krate);
- format!("{name} is defined in crate `{crate_name}")
+ format!("{name} is defined in crate `{crate_name}`")
};
diagnostic.span_note(def_span, msg);
};
@@ -1791,14 +1792,24 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
}
}))
{
- diag.note_expected_found_extra(
- &expected_label,
- expected,
- &found_label,
- found,
- &sort_string(values.expected, exp_p),
- &sort_string(values.found, found_p),
- );
+ if let Some(ExpectedFound { found: found_ty, .. }) = exp_found {
+ // `Future` is a special opaque type that the compiler
+ // will try to hide in some case such as `async fn`, so
+ // to make an error more use friendly we will
+ // avoid to suggest a mismatch type with a
+ // type that the user usually are not usign
+ // directly such as `impl Future<Output = u8>`.
+ if !self.tcx.ty_is_opaque_future(found_ty) {
+ diag.note_expected_found_extra(
+ &expected_label,
+ expected,
+ &found_label,
+ found,
+ &sort_string(values.expected, exp_p),
+ &sort_string(values.found, found_p),
+ );
+ }
+ }
}
}
_ => {
@@ -1841,19 +1852,25 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
self.suggest_as_ref_where_appropriate(span, &exp_found, diag);
self.suggest_accessing_field_where_appropriate(cause, &exp_found, diag);
self.suggest_await_on_expect_found(cause, span, &exp_found, diag);
+ self.suggest_function_pointers(cause, span, &exp_found, diag);
}
}
- // In some (most?) cases cause.body_id points to actual body, but in some cases
- // it's an actual definition. According to the comments (e.g. in
- // rustc_hir_analysis/check/compare_impl_item.rs:compare_predicate_entailment) the latter
- // is relied upon by some other code. This might (or might not) need cleanup.
- let body_owner_def_id =
- self.tcx.hir().opt_local_def_id(cause.body_id).unwrap_or_else(|| {
- self.tcx.hir().body_owner_def_id(hir::BodyId { hir_id: cause.body_id })
- });
self.check_and_note_conflicting_crates(diag, terr);
- self.tcx.note_and_explain_type_err(diag, terr, cause, span, body_owner_def_id.to_def_id());
+
+ self.note_and_explain_type_err(diag, terr, cause, span, cause.body_id.to_def_id());
+ if let Some(exp_found) = exp_found
+ && let exp_found = TypeError::Sorts(exp_found)
+ && exp_found != terr
+ {
+ self.note_and_explain_type_err(
+ diag,
+ exp_found,
+ cause,
+ span,
+ cause.body_id.to_def_id(),
+ );
+ }
if let Some(ValuePairs::PolyTraitRefs(exp_found)) = values
&& let ty::Closure(def_id, _) = exp_found.expected.skip_binder().self_ty().kind()
@@ -1929,7 +1946,8 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
(ty::Uint(ty::UintTy::U8), ty::Char) => {
if let Ok(code) = self.tcx.sess().source_map().span_to_snippet(span)
&& let Some(code) = code.strip_prefix('\'').and_then(|s| s.strip_suffix('\''))
- && code.chars().next().map_or(false, |c| c.is_ascii())
+ && !code.starts_with("\\u") // forbid all Unicode escapes
+ && code.chars().next().map_or(false, |c| c.is_ascii()) // forbids literal Unicode characters beyond ASCII
{
err.span_suggestion(
span,
@@ -1976,6 +1994,70 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
(ty::Bool, ty::Tuple(list)) => if list.len() == 0 {
self.suggest_let_for_letchains(&mut err, &trace.cause, span);
}
+ (ty::Array(_, _), ty::Array(_, _)) => 'block: {
+ let hir = self.tcx.hir();
+ let TypeError::FixedArraySize(sz) = terr else {
+ break 'block;
+ };
+ let tykind = match hir.find_by_def_id(trace.cause.body_id) {
+ Some(hir::Node::Item(hir::Item {
+ kind: hir::ItemKind::Fn(_, _, body_id),
+ ..
+ })) => {
+ let body = hir.body(*body_id);
+ struct LetVisitor<'v> {
+ span: Span,
+ result: Option<&'v hir::Ty<'v>>,
+ }
+ impl<'v> Visitor<'v> for LetVisitor<'v> {
+ fn visit_stmt(&mut self, s: &'v hir::Stmt<'v>) {
+ if self.result.is_some() {
+ return;
+ }
+ // Find a local statement where the initializer has
+ // the same span as the error and the type is specified.
+ if let hir::Stmt {
+ kind: hir::StmtKind::Local(hir::Local {
+ init: Some(hir::Expr {
+ span: init_span,
+ ..
+ }),
+ ty: Some(array_ty),
+ ..
+ }),
+ ..
+ } = s
+ && init_span == &self.span {
+ self.result = Some(*array_ty);
+ }
+ }
+ }
+ let mut visitor = LetVisitor {span, result: None};
+ visitor.visit_body(body);
+ visitor.result.map(|r| &r.peel_refs().kind)
+ }
+ Some(hir::Node::Item(hir::Item {
+ kind: hir::ItemKind::Const(ty, _),
+ ..
+ })) => {
+ Some(&ty.peel_refs().kind)
+ }
+ _ => None
+ };
+
+ if let Some(tykind) = tykind
+ && let hir::TyKind::Array(_, length) = tykind
+ && let hir::ArrayLen::Body(hir::AnonConst { hir_id, .. }) = length
+ && let Some(span) = self.tcx.hir().opt_span(*hir_id)
+ {
+ err.span_suggestion(
+ span,
+ "consider specifying the actual array length",
+ sz.found,
+ Applicability::MaybeIncorrect,
+ );
+ }
+ }
_ => {}
}
}
@@ -2123,7 +2205,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
}
/// Returns a string of the form "expected `{}`, found `{}`".
- fn expected_found_str<T: fmt::Display + TypeFoldable<'tcx>>(
+ fn expected_found_str<T: fmt::Display + TypeFoldable<TyCtxt<'tcx>>>(
&self,
exp_found: ty::error::ExpectedFound<T>,
) -> Option<(DiagnosticStyledString, DiagnosticStyledString, Option<PathBuf>, Option<PathBuf>)>
@@ -2552,7 +2634,11 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
);
err.note_expected_found(&"", sup_expected, &"", sup_found);
- err.emit();
+ if sub_region.is_error() | sup_region.is_error() {
+ err.delay_as_bug();
+ } else {
+ err.emit();
+ }
return;
}
@@ -2568,7 +2654,11 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
);
self.note_region_origin(&mut err, &sub_origin);
- err.emit();
+ if sub_region.is_error() | sup_region.is_error() {
+ err.delay_as_bug();
+ } else {
+ err.emit();
+ }
}
/// Determine whether an error associated with the given span and definition
@@ -2585,7 +2675,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
/// with the other type. A TyVar inference type is compatible with any type, and an IntVar or
/// FloatVar inference type are compatible with themselves or their concrete types (Int and
/// Float types, respectively). When comparing two ADTs, these rules apply recursively.
- pub fn same_type_modulo_infer(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> bool {
+ pub fn same_type_modulo_infer<T: relate::Relate<'tcx>>(&self, a: T, b: T) -> bool {
let (a, b) = self.resolve_vars_if_possible((a, b));
SameTypeModuloInfer(self).relate(a, b).is_ok()
}
@@ -2847,6 +2937,7 @@ impl IntoDiagnosticArg for ObligationCauseAsDiagArg<'_> {
pub enum TyCategory {
Closure,
Opaque,
+ OpaqueFuture,
Generator(hir::GeneratorKind),
Foreign,
}
@@ -2856,6 +2947,7 @@ impl TyCategory {
match self {
Self::Closure => "closure",
Self::Opaque => "opaque type",
+ Self::OpaqueFuture => "future",
Self::Generator(gk) => gk.descr(),
Self::Foreign => "foreign type",
}
@@ -2864,7 +2956,11 @@ impl TyCategory {
pub fn from_ty(tcx: TyCtxt<'_>, ty: Ty<'_>) -> Option<(Self, DefId)> {
match *ty.kind() {
ty::Closure(def_id, _) => Some((Self::Closure, def_id)),
- ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }) => Some((Self::Opaque, def_id)),
+ ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }) => {
+ let kind =
+ if tcx.ty_is_opaque_future(ty) { Self::OpaqueFuture } else { Self::Opaque };
+ Some((kind, def_id))
+ }
ty::Generator(def_id, ..) => {
Some((Self::Generator(tcx.generator_kind(def_id).unwrap()), def_id))
}
diff --git a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs
index b8c843a8a..e242900fd 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs
@@ -122,7 +122,7 @@ impl InferenceDiagnosticsParentData {
tcx.def_key(parent_def_id).disambiguated_data.data.get_opt_name()?.to_string();
Some(InferenceDiagnosticsParentData {
- prefix: tcx.def_kind(parent_def_id).descr(parent_def_id),
+ prefix: tcx.def_descr(parent_def_id),
name: parent_name,
})
}
@@ -158,8 +158,12 @@ fn fmt_printer<'a, 'tcx>(infcx: &'a InferCtxt<'tcx>, ns: Namespace) -> FmtPrinte
if infcx.probe_ty_var(ty_vid).is_ok() {
warn!("resolved ty var in error message");
}
- if let TypeVariableOriginKind::TypeParameterDefinition(name, _) =
- infcx.inner.borrow_mut().type_variables().var_origin(ty_vid).kind
+
+ let mut infcx_inner = infcx.inner.borrow_mut();
+ let ty_vars = infcx_inner.type_variables();
+ let var_origin = ty_vars.var_origin(ty_vid);
+ if let TypeVariableOriginKind::TypeParameterDefinition(name, _) = var_origin.kind
+ && !var_origin.span.from_expansion()
{
Some(name)
} else {
@@ -254,7 +258,7 @@ impl<'tcx> InferCtxt<'tcx> {
if let TypeVariableOriginKind::TypeParameterDefinition(name, def_id) =
var_origin.kind
{
- if name != kw::SelfUpper {
+ if name != kw::SelfUpper && !var_origin.span.from_expansion() {
return InferenceDiagnosticsData {
name: name.to_string(),
span: Some(var_origin.span),
@@ -780,7 +784,7 @@ impl<'a, 'tcx> FindInferSourceVisitor<'a, 'tcx> {
// The sources are listed in order of preference here.
let tcx = self.infcx.tcx;
let ctx = CostCtxt { tcx };
- let base_cost = match source.kind {
+ match source.kind {
InferSourceKind::LetBinding { ty, .. } => ctx.ty_cost(ty),
InferSourceKind::ClosureArg { ty, .. } => ctx.ty_cost(ty),
InferSourceKind::GenericArg { def_id, generic_args, .. } => {
@@ -797,17 +801,17 @@ impl<'a, 'tcx> FindInferSourceVisitor<'a, 'tcx> {
InferSourceKind::ClosureReturn { ty, should_wrap_expr, .. } => {
30 + ctx.ty_cost(ty) + if should_wrap_expr.is_some() { 10 } else { 0 }
}
- };
-
- let suggestion_may_apply = if source.from_expansion() { 10000 } else { 0 };
-
- base_cost + suggestion_may_apply
+ }
}
/// Uses `fn source_cost` to determine whether this inference source is preferable to
/// previous sources. We generally prefer earlier sources.
#[instrument(level = "debug", skip(self))]
fn update_infer_source(&mut self, mut new_source: InferSource<'tcx>) {
+ if new_source.from_expansion() {
+ return;
+ }
+
let cost = self.source_cost(&new_source) + self.attempt;
debug!(?cost);
self.attempt += 1;
@@ -819,6 +823,7 @@ impl<'a, 'tcx> FindInferSourceVisitor<'a, 'tcx> {
// `let x: _ = iter.collect();`, as this is a very common case.
*def_id = Some(did);
}
+
if cost < self.infer_source_cost {
self.infer_source_cost = cost;
self.infer_source = Some(new_source);
@@ -1056,8 +1061,8 @@ impl<'a, 'tcx> FindInferSourceVisitor<'a, 'tcx> {
};
let parent_def_id = generics.parent.unwrap();
- if tcx.def_kind(parent_def_id) == DefKind::Impl {
- let parent_ty = tcx.bound_type_of(parent_def_id).subst(tcx, substs);
+ if let DefKind::Impl { .. } = tcx.def_kind(parent_def_id) {
+ let parent_ty = tcx.type_of(parent_def_id).subst(tcx, substs);
match (parent_ty.kind(), &ty.kind) {
(
ty::Adt(def, substs),
diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/find_anon_type.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/find_anon_type.rs
index 39f4d5022..fec04af23 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/find_anon_type.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/find_anon_type.rs
@@ -2,7 +2,7 @@ use rustc_hir as hir;
use rustc_hir::intravisit::{self, Visitor};
use rustc_middle::hir::map::Map;
use rustc_middle::hir::nested_filter;
-use rustc_middle::middle::resolve_lifetime as rl;
+use rustc_middle::middle::resolve_bound_vars as rbv;
use rustc_middle::ty::{self, Region, TyCtxt};
/// This function calls the `visit_ty` method for the parameters
@@ -99,11 +99,11 @@ impl<'tcx> Visitor<'tcx> for FindNestedTypeVisitor<'tcx> {
hir::TyKind::Ref(ref lifetime, _) => {
// the lifetime of the Ref
let hir_id = lifetime.hir_id;
- match (self.tcx.named_region(hir_id), self.bound_region) {
+ match (self.tcx.named_bound_var(hir_id), self.bound_region) {
// Find the index of the named region that was part of the
// error. We will then search the function parameters for a bound
// region at the right depth with the same index
- (Some(rl::Region::EarlyBound(id)), ty::BrNamed(def_id, _)) => {
+ (Some(rbv::ResolvedArg::EarlyBound(id)), ty::BrNamed(def_id, _)) => {
debug!("EarlyBound id={:?} def_id={:?}", id, def_id);
if id == def_id {
self.found_type = Some(arg);
@@ -115,7 +115,7 @@ impl<'tcx> Visitor<'tcx> for FindNestedTypeVisitor<'tcx> {
// error. We will then search the function parameters for a bound
// region at the right depth with the same index
(
- Some(rl::Region::LateBound(debruijn_index, _, id)),
+ Some(rbv::ResolvedArg::LateBound(debruijn_index, _, id)),
ty::BrNamed(def_id, _),
) => {
debug!(
@@ -131,10 +131,11 @@ impl<'tcx> Visitor<'tcx> for FindNestedTypeVisitor<'tcx> {
(
Some(
- rl::Region::Static
- | rl::Region::Free(_, _)
- | rl::Region::EarlyBound(_)
- | rl::Region::LateBound(_, _, _),
+ rbv::ResolvedArg::StaticLifetime
+ | rbv::ResolvedArg::Free(_, _)
+ | rbv::ResolvedArg::EarlyBound(_)
+ | rbv::ResolvedArg::LateBound(_, _, _)
+ | rbv::ResolvedArg::Error(_),
)
| None,
_,
@@ -186,9 +187,9 @@ impl<'tcx> Visitor<'tcx> for TyPathVisitor<'tcx> {
}
fn visit_lifetime(&mut self, lifetime: &hir::Lifetime) {
- match (self.tcx.named_region(lifetime.hir_id), self.bound_region) {
+ match (self.tcx.named_bound_var(lifetime.hir_id), self.bound_region) {
// the lifetime of the TyPath!
- (Some(rl::Region::EarlyBound(id)), ty::BrNamed(def_id, _)) => {
+ (Some(rbv::ResolvedArg::EarlyBound(id)), ty::BrNamed(def_id, _)) => {
debug!("EarlyBound id={:?} def_id={:?}", id, def_id);
if id == def_id {
self.found_it = true;
@@ -196,7 +197,7 @@ impl<'tcx> Visitor<'tcx> for TyPathVisitor<'tcx> {
}
}
- (Some(rl::Region::LateBound(debruijn_index, _, id)), ty::BrNamed(def_id, _)) => {
+ (Some(rbv::ResolvedArg::LateBound(debruijn_index, _, id)), ty::BrNamed(def_id, _)) => {
debug!("FindNestedTypeVisitor::visit_ty: LateBound depth = {:?}", debruijn_index,);
debug!("id={:?}", id);
debug!("def_id={:?}", def_id);
@@ -208,10 +209,11 @@ impl<'tcx> Visitor<'tcx> for TyPathVisitor<'tcx> {
(
Some(
- rl::Region::Static
- | rl::Region::EarlyBound(_)
- | rl::Region::LateBound(_, _, _)
- | rl::Region::Free(_, _),
+ rbv::ResolvedArg::StaticLifetime
+ | rbv::ResolvedArg::EarlyBound(_)
+ | rbv::ResolvedArg::LateBound(_, _, _)
+ | rbv::ResolvedArg::Free(_, _)
+ | rbv::ResolvedArg::Error(_),
)
| None,
_,
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 1067ccda2..2c63a3904 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
@@ -72,7 +72,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
};
// Next, let's figure out the set of trait objects with implicit static bounds
- let ty = self.tcx().type_of(*impl_def_id);
+ let ty = self.tcx().type_of(*impl_def_id).subst_identity();
let mut v = super::static_impl_trait::TraitObjectVisitor(FxIndexSet::default());
v.visit_ty(ty);
let mut traits = vec![];
diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs
index 99431567e..c1ea0a0d9 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs
@@ -14,7 +14,7 @@ use rustc_hir::def_id::DefId;
use rustc_middle::ty::error::ExpectedFound;
use rustc_middle::ty::print::{FmtPrinter, Print, RegionHighlightMode};
use rustc_middle::ty::subst::SubstsRef;
-use rustc_middle::ty::{self, RePlaceholder, ReVar, Region, TyCtxt};
+use rustc_middle::ty::{self, RePlaceholder, Region, TyCtxt};
use std::fmt;
@@ -79,7 +79,7 @@ impl<'tcx> NiceRegionError<'_, 'tcx> {
sup_placeholder @ Region(Interned(RePlaceholder(_), _)),
_,
)) => self.try_report_trait_placeholder_mismatch(
- Some(self.tcx().mk_region(ReVar(*vid))),
+ Some(self.tcx().mk_re_var(*vid)),
cause,
Some(*sub_placeholder),
Some(*sup_placeholder),
@@ -95,7 +95,7 @@ impl<'tcx> NiceRegionError<'_, 'tcx> {
_,
_,
)) => self.try_report_trait_placeholder_mismatch(
- Some(self.tcx().mk_region(ReVar(*vid))),
+ Some(self.tcx().mk_re_var(*vid)),
cause,
Some(*sub_placeholder),
None,
@@ -111,7 +111,7 @@ impl<'tcx> NiceRegionError<'_, 'tcx> {
sup_placeholder @ Region(Interned(RePlaceholder(_), _)),
_,
)) => self.try_report_trait_placeholder_mismatch(
- Some(self.tcx().mk_region(ReVar(*vid))),
+ Some(self.tcx().mk_re_var(*vid)),
cause,
None,
Some(*sup_placeholder),
@@ -127,7 +127,7 @@ impl<'tcx> NiceRegionError<'_, 'tcx> {
sup_placeholder @ Region(Interned(RePlaceholder(_), _)),
_,
)) => self.try_report_trait_placeholder_mismatch(
- Some(self.tcx().mk_region(ReVar(*vid))),
+ Some(self.tcx().mk_re_var(*vid)),
cause,
None,
Some(*sup_placeholder),
@@ -141,7 +141,7 @@ impl<'tcx> NiceRegionError<'_, 'tcx> {
SubregionOrigin::Subtype(box TypeTrace { cause, values }),
sup_placeholder @ Region(Interned(RePlaceholder(_), _)),
)) => self.try_report_trait_placeholder_mismatch(
- Some(self.tcx().mk_region(ReVar(*vid))),
+ Some(self.tcx().mk_re_var(*vid)),
cause,
None,
Some(*sup_placeholder),
diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_relation.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_relation.rs
index 9534bce54..e8d94f0c0 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_relation.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_relation.rs
@@ -1,5 +1,8 @@
-use crate::infer::{
- error_reporting::nice_region_error::NiceRegionError, RegionResolutionError, SubregionOrigin,
+use crate::{
+ errors::PlaceholderRelationLfNotSatisfied,
+ infer::{
+ error_reporting::nice_region_error::NiceRegionError, RegionResolutionError, SubregionOrigin,
+ },
};
use rustc_data_structures::intern::Interned;
use rustc_errors::{DiagnosticBuilder, ErrorGuaranteed};
@@ -16,8 +19,7 @@ impl<'tcx> NiceRegionError<'_, 'tcx> {
Region(Interned(RePlaceholder(ty::Placeholder { name: sub_name, .. }), _)),
Region(Interned(RePlaceholder(ty::Placeholder { name: sup_name, .. }), _)),
)) => {
- let msg = "lifetime bound not satisfied";
- let mut err = self.tcx().sess.struct_span_err(*span, msg);
+ let span = *span;
let (sub_span, sub_symbol) = match sub_name {
ty::BrNamed(def_id, symbol) => {
(Some(self.tcx().def_span(def_id)), Some(symbol))
@@ -32,41 +34,47 @@ impl<'tcx> NiceRegionError<'_, 'tcx> {
ty::BrAnon(_, span) => (*span, None),
ty::BrEnv => (None, None),
};
- match (sub_span, sup_span, sub_symbol, sup_symbol) {
- (Some(sub_span), Some(sup_span), Some(sub_symbol), Some(sup_symbol)) => {
- err.span_note(
+ let diag = match (sub_span, sup_span, sub_symbol, sup_symbol) {
+ (Some(sub_span), Some(sup_span), Some(&sub_symbol), Some(&sup_symbol)) => {
+ PlaceholderRelationLfNotSatisfied::HasBoth {
+ span,
sub_span,
- format!("the lifetime `{sub_symbol}` defined here..."),
- );
- err.span_note(
sup_span,
- format!("...must outlive the lifetime `{sup_symbol}` defined here"),
- );
+ sub_symbol,
+ sup_symbol,
+ note: (),
+ }
}
- (Some(sub_span), Some(sup_span), _, Some(sup_symbol)) => {
- err.span_note(sub_span, "the lifetime defined here...");
- err.span_note(
+ (Some(sub_span), Some(sup_span), _, Some(&sup_symbol)) => {
+ PlaceholderRelationLfNotSatisfied::HasSup {
+ span,
+ sub_span,
sup_span,
- format!("...must outlive the lifetime `{sup_symbol}` defined here"),
- );
+ sup_symbol,
+ note: (),
+ }
}
- (Some(sub_span), Some(sup_span), Some(sub_symbol), _) => {
- err.span_note(
+ (Some(sub_span), Some(sup_span), Some(&sub_symbol), _) => {
+ PlaceholderRelationLfNotSatisfied::HasSub {
+ span,
sub_span,
- format!("the lifetime `{sub_symbol}` defined here..."),
- );
- err.span_note(sup_span, "...must outlive the lifetime defined here");
+ sup_span,
+ sub_symbol,
+ note: (),
+ }
}
(Some(sub_span), Some(sup_span), _, _) => {
- err.span_note(sub_span, "the lifetime defined here...");
- err.span_note(sup_span, "...must outlive the lifetime defined here");
+ PlaceholderRelationLfNotSatisfied::HasNone {
+ span,
+ sub_span,
+ sup_span,
+ note: (),
+ }
}
- _ => {}
- }
- err.note("this is a known limitation that will be removed in the future (see issue #100013 <https://github.com/rust-lang/rust/issues/100013> for more information)");
- Some(err)
+ _ => PlaceholderRelationLfNotSatisfied::OnlyPrimarySpan { span, note: () },
+ };
+ Some(self.tcx().sess.create_err(diag))
}
-
_ => None,
}
}
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 49ad3ce50..b06ff10d8 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
@@ -98,6 +98,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
let sp = var_origin.span();
let return_sp = sub_origin.span();
let param = self.find_param_with_region(*sup_r, *sub_r)?;
+ let simple_ident = param.param.pat.simple_ident();
let lifetime_name = if sup_r.has_name() { sup_r.to_string() } else { "'_".to_owned() };
let (mention_influencer, influencer_point) =
@@ -187,7 +188,9 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
req_introduces_loc: subdiag,
has_lifetime: sup_r.has_name(),
- lifetime: sup_r.to_string(),
+ lifetime: lifetime_name.clone(),
+ has_param_name: simple_ident.is_some(),
+ param_name: simple_ident.map(|x| x.to_string()).unwrap_or_default(),
spans_empty,
bound,
};
@@ -536,7 +539,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
/// Collect all the trait objects in a type that could have received an implicit `'static` lifetime.
pub struct TraitObjectVisitor(pub FxIndexSet<DefId>);
-impl<'tcx> TypeVisitor<'tcx> for TraitObjectVisitor {
+impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for TraitObjectVisitor {
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
match t.kind() {
ty::Dynamic(preds, re, _) if re.is_static() => {
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 40c0c806e..2875448ee 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
@@ -75,7 +75,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
}
}
- impl<'tcx> ty::visit::TypeVisitor<'tcx> for HighlightBuilder<'tcx> {
+ impl<'tcx> ty::visit::TypeVisitor<TyCtxt<'tcx>> for HighlightBuilder<'tcx> {
fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> {
if !r.has_name() && self.counter <= 3 {
self.highlight.highlighting_region(r, self.counter);
diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/util.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/util.rs
index fd26d7d29..db4b8af46 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/util.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/util.rs
@@ -65,7 +65,7 @@ pub fn find_param_with_region<'tcx>(
let owner_id = hir.body_owner(body_id);
let fn_decl = hir.fn_decl_by_hir_id(owner_id).unwrap();
- let poly_fn_sig = tcx.fn_sig(id);
+ let poly_fn_sig = tcx.fn_sig(id).subst_identity();
let fn_sig = tcx.liberate_late_bound_regions(id, poly_fn_sig);
let body = hir.body(body_id);
@@ -90,20 +90,18 @@ pub fn find_param_with_region<'tcx>(
r
}
});
- if found_anon_region {
+ found_anon_region.then(|| {
let ty_hir_id = fn_decl.inputs[index].hir_id;
let param_ty_span = hir.span(ty_hir_id);
let is_first = index == 0;
- Some(AnonymousParamInfo {
+ AnonymousParamInfo {
param,
param_ty: new_param_ty,
param_ty_span,
bound_region,
is_first,
- })
- } else {
- None
- }
+ }
+ })
})
}
@@ -125,7 +123,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
br: ty::BoundRegionKind,
hir_sig: &hir::FnSig<'_>,
) -> Option<Span> {
- let fn_ty = self.tcx().type_of(scope_def_id);
+ let fn_ty = self.tcx().type_of(scope_def_id).subst_identity();
if let ty::FnDef(_, _) = fn_ty.kind() {
let ret_ty = fn_ty.fn_sig(self.tcx()).output();
let span = hir_sig.decl.output.span();
@@ -145,7 +143,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
fn includes_region(
&self,
- ty: Binder<'tcx, impl TypeVisitable<'tcx>>,
+ ty: Binder<'tcx, impl TypeVisitable<TyCtxt<'tcx>>>,
region: ty::BoundRegionKind,
) -> bool {
let late_bound_regions = self.tcx().collect_referenced_late_bound_regions(&ty);
diff --git a/compiler/rustc_infer/src/infer/error_reporting/note.rs b/compiler/rustc_infer/src/infer/error_reporting/note.rs
index b18cbd404..7ffe1fd20 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/note.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/note.rs
@@ -1,9 +1,12 @@
-use crate::errors::RegionOriginNote;
+use crate::errors::{
+ note_and_explain, FullfillReqLifetime, LfBoundNotSatisfied, OutlivesBound, OutlivesContent,
+ RefLongerThanData, RegionOriginNote, WhereClauseSuggestions,
+};
+use crate::fluent_generated as fluent;
use crate::infer::error_reporting::{note_and_explain_region, TypeErrCtxt};
use crate::infer::{self, SubregionOrigin};
use rustc_errors::{
- fluent, struct_span_err, AddToDiagnostic, Applicability, Diagnostic, DiagnosticBuilder,
- ErrorGuaranteed,
+ AddToDiagnostic, Diagnostic, DiagnosticBuilder, ErrorGuaranteed, IntoDiagnostic,
};
use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_middle::traits::ObligationCauseCode;
@@ -78,7 +81,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
sub: Region<'tcx>,
sup: Region<'tcx>,
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
- match origin {
+ let mut err = match origin {
infer::Subtype(box trace) => {
let terr = TypeError::RegionsDoesNotOutlive(sup, sub);
let mut err = self.report_and_explain_type_error(trace, terr);
@@ -119,130 +122,105 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
err
}
infer::Reborrow(span) => {
- let mut err = struct_span_err!(
- self.tcx.sess,
- span,
- E0312,
- "lifetime of reference outlives lifetime of borrowed content..."
- );
- note_and_explain_region(
+ let reference_valid = note_and_explain::RegionExplanation::new(
self.tcx,
- &mut err,
- "...the reference is valid for ",
sub,
- "...",
None,
+ note_and_explain::PrefixKind::RefValidFor,
+ note_and_explain::SuffixKind::Continues,
);
- note_and_explain_region(
+ let content_valid = note_and_explain::RegionExplanation::new(
self.tcx,
- &mut err,
- "...but the borrowed content is only valid for ",
sup,
- "",
None,
+ note_and_explain::PrefixKind::ContentValidFor,
+ note_and_explain::SuffixKind::Empty,
);
- err
+ OutlivesContent {
+ span,
+ notes: reference_valid.into_iter().chain(content_valid).collect(),
+ }
+ .into_diagnostic(&self.tcx.sess.parse_sess.span_diagnostic)
}
infer::RelateObjectBound(span) => {
- let mut err = struct_span_err!(
- self.tcx.sess,
- span,
- E0476,
- "lifetime of the source pointer does not outlive lifetime bound of the \
- object type"
- );
- note_and_explain_region(
+ let object_valid = note_and_explain::RegionExplanation::new(
self.tcx,
- &mut err,
- "object type is valid for ",
sub,
- "",
None,
+ note_and_explain::PrefixKind::TypeObjValidFor,
+ note_and_explain::SuffixKind::Empty,
);
- note_and_explain_region(
+ let pointer_valid = note_and_explain::RegionExplanation::new(
self.tcx,
- &mut err,
- "source pointer is only valid for ",
sup,
- "",
None,
+ note_and_explain::PrefixKind::SourcePointerValidFor,
+ note_and_explain::SuffixKind::Empty,
);
- err
+ OutlivesBound {
+ span,
+ notes: object_valid.into_iter().chain(pointer_valid).collect(),
+ }
+ .into_diagnostic(&self.tcx.sess.parse_sess.span_diagnostic)
}
infer::RelateParamBound(span, ty, opt_span) => {
- let mut err = struct_span_err!(
- self.tcx.sess,
- span,
- E0477,
- "the type `{}` does not fulfill the required lifetime",
- self.ty_to_string(ty)
+ let prefix = match *sub {
+ ty::ReStatic => note_and_explain::PrefixKind::TypeSatisfy,
+ _ => note_and_explain::PrefixKind::TypeOutlive,
+ };
+ let suffix = if opt_span.is_some() {
+ note_and_explain::SuffixKind::ReqByBinding
+ } else {
+ note_and_explain::SuffixKind::Empty
+ };
+ let note = note_and_explain::RegionExplanation::new(
+ self.tcx, sub, opt_span, prefix, suffix,
);
- match *sub {
- ty::ReStatic => note_and_explain_region(
- self.tcx,
- &mut err,
- "type must satisfy ",
- sub,
- if opt_span.is_some() { " as required by this binding" } else { "" },
- opt_span,
- ),
- _ => note_and_explain_region(
- self.tcx,
- &mut err,
- "type must outlive ",
- sub,
- if opt_span.is_some() { " as required by this binding" } else { "" },
- opt_span,
- ),
- }
- err
+ FullfillReqLifetime { span, ty: self.resolve_vars_if_possible(ty), note }
+ .into_diagnostic(&self.tcx.sess.parse_sess.span_diagnostic)
}
infer::RelateRegionParamBound(span) => {
- let mut err =
- struct_span_err!(self.tcx.sess, span, E0478, "lifetime bound not satisfied");
- note_and_explain_region(
+ let param_instantiated = note_and_explain::RegionExplanation::new(
self.tcx,
- &mut err,
- "lifetime parameter instantiated with ",
sup,
- "",
None,
+ note_and_explain::PrefixKind::LfParamInstantiatedWith,
+ note_and_explain::SuffixKind::Empty,
);
- note_and_explain_region(
+ let param_must_outlive = note_and_explain::RegionExplanation::new(
self.tcx,
- &mut err,
- "but lifetime parameter must outlive ",
sub,
- "",
None,
+ note_and_explain::PrefixKind::LfParamMustOutlive,
+ note_and_explain::SuffixKind::Empty,
);
- err
+ LfBoundNotSatisfied {
+ span,
+ notes: param_instantiated.into_iter().chain(param_must_outlive).collect(),
+ }
+ .into_diagnostic(&self.tcx.sess.parse_sess.span_diagnostic)
}
infer::ReferenceOutlivesReferent(ty, span) => {
- let mut err = struct_span_err!(
- self.tcx.sess,
- span,
- E0491,
- "in type `{}`, reference has a longer lifetime than the data it references",
- self.ty_to_string(ty)
- );
- note_and_explain_region(
+ let pointer_valid = note_and_explain::RegionExplanation::new(
self.tcx,
- &mut err,
- "the pointer is valid for ",
sub,
- "",
None,
+ note_and_explain::PrefixKind::PointerValidFor,
+ note_and_explain::SuffixKind::Empty,
);
- note_and_explain_region(
+ let data_valid = note_and_explain::RegionExplanation::new(
self.tcx,
- &mut err,
- "but the referenced data is only valid for ",
sup,
- "",
None,
+ note_and_explain::PrefixKind::DataValidFor,
+ note_and_explain::SuffixKind::Empty,
);
- err
+ RefLongerThanData {
+ span,
+ ty: self.resolve_vars_if_possible(ty),
+ notes: pointer_valid.into_iter().chain(data_valid).collect(),
+ }
+ .into_diagnostic(&self.tcx.sess.parse_sess.span_diagnostic)
}
infer::CompareImplItemObligation { span, impl_item_def_id, trait_item_def_id } => {
let mut err = self.report_extra_impl_obligation(
@@ -279,27 +257,31 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
err
}
infer::AscribeUserTypeProvePredicate(span) => {
- let mut err =
- struct_span_err!(self.tcx.sess, span, E0478, "lifetime bound not satisfied");
- note_and_explain_region(
+ let instantiated = note_and_explain::RegionExplanation::new(
self.tcx,
- &mut err,
- "lifetime instantiated with ",
sup,
- "",
None,
+ note_and_explain::PrefixKind::LfInstantiatedWith,
+ note_and_explain::SuffixKind::Empty,
);
- note_and_explain_region(
+ let must_outlive = note_and_explain::RegionExplanation::new(
self.tcx,
- &mut err,
- "but lifetime must outlive ",
sub,
- "",
None,
+ note_and_explain::PrefixKind::LfMustOutlive,
+ note_and_explain::SuffixKind::Empty,
);
- err
+ LfBoundNotSatisfied {
+ span,
+ notes: instantiated.into_iter().chain(must_outlive).collect(),
+ }
+ .into_diagnostic(&self.tcx.sess.parse_sess.span_diagnostic)
}
+ };
+ if sub.is_error() || sup.is_error() {
+ err.delay_as_bug();
}
+ err
}
pub fn suggest_copy_trait_method_bounds(
@@ -343,22 +325,17 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
let Some(generics) = self.tcx.hir().get_generics(impl_item_def_id) else { return; };
- if trait_predicates.is_empty() {
- err.span_suggestion_verbose(
- generics.where_clause_span,
- "remove the `where` clause",
- String::new(),
- Applicability::MachineApplicable,
- );
+ let suggestion = if trait_predicates.is_empty() {
+ WhereClauseSuggestions::Remove { span: generics.where_clause_span }
} else {
let space = if generics.where_clause_span.is_empty() { " " } else { "" };
- err.span_suggestion_verbose(
- generics.where_clause_span,
- "copy the `where` clause predicates from the trait",
- format!("{space}where {}", trait_predicates.join(", ")),
- Applicability::MachineApplicable,
- );
- }
+ WhereClauseSuggestions::CopyPredicates {
+ span: generics.where_clause_span,
+ space,
+ trait_predicates: trait_predicates.join(", "),
+ }
+ };
+ err.subdiagnostic(suggestion);
}
pub(super) fn report_placeholder_failure(
diff --git a/compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs b/compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs
new file mode 100644
index 000000000..b33729d0b
--- /dev/null
+++ b/compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs
@@ -0,0 +1,700 @@
+use super::TypeErrCtxt;
+use rustc_errors::Applicability::{MachineApplicable, MaybeIncorrect};
+use rustc_errors::{pluralize, Diagnostic, MultiSpan};
+use rustc_hir::{self as hir, def::DefKind};
+use rustc_middle::traits::ObligationCauseCode;
+use rustc_middle::ty::error::ExpectedFound;
+use rustc_middle::ty::print::Printer;
+use rustc_middle::{
+ traits::ObligationCause,
+ ty::{self, error::TypeError, print::FmtPrinter, suggest_constraining_type_param, Ty},
+};
+use rustc_span::{def_id::DefId, sym, BytePos, Span, Symbol};
+
+impl<'tcx> TypeErrCtxt<'_, 'tcx> {
+ pub fn note_and_explain_type_err(
+ &self,
+ diag: &mut Diagnostic,
+ err: TypeError<'tcx>,
+ cause: &ObligationCause<'tcx>,
+ sp: Span,
+ body_owner_def_id: DefId,
+ ) {
+ use ty::error::TypeError::*;
+ debug!("note_and_explain_type_err err={:?} cause={:?}", err, cause);
+
+ let tcx = self.tcx;
+
+ match err {
+ ArgumentSorts(values, _) | Sorts(values) => {
+ match (values.expected.kind(), values.found.kind()) {
+ (ty::Closure(..), ty::Closure(..)) => {
+ diag.note("no two closures, even if identical, have the same type");
+ diag.help("consider boxing your closure and/or using it as a trait object");
+ }
+ (ty::Alias(ty::Opaque, ..), ty::Alias(ty::Opaque, ..)) => {
+ // Issue #63167
+ diag.note("distinct uses of `impl Trait` result in different opaque types");
+ }
+ (ty::Float(_), ty::Infer(ty::IntVar(_)))
+ if let Ok(
+ // Issue #53280
+ snippet,
+ ) = tcx.sess.source_map().span_to_snippet(sp) =>
+ {
+ if snippet.chars().all(|c| c.is_digit(10) || c == '-' || c == '_') {
+ diag.span_suggestion(
+ sp,
+ "use a float literal",
+ format!("{}.0", snippet),
+ MachineApplicable,
+ );
+ }
+ }
+ (ty::Param(expected), ty::Param(found)) => {
+ let generics = tcx.generics_of(body_owner_def_id);
+ let e_span = tcx.def_span(generics.type_param(expected, tcx).def_id);
+ if !sp.contains(e_span) {
+ diag.span_label(e_span, "expected type parameter");
+ }
+ let f_span = tcx.def_span(generics.type_param(found, tcx).def_id);
+ if !sp.contains(f_span) {
+ diag.span_label(f_span, "found type parameter");
+ }
+ diag.note(
+ "a type parameter was expected, but a different one was found; \
+ you might be missing a type parameter or trait bound",
+ );
+ diag.note(
+ "for more information, visit \
+ https://doc.rust-lang.org/book/ch10-02-traits.html\
+ #traits-as-parameters",
+ );
+ }
+ (ty::Alias(ty::Projection, _), ty::Alias(ty::Projection, _)) => {
+ diag.note("an associated type was expected, but a different one was found");
+ }
+ (ty::Param(p), ty::Alias(ty::Projection, proj)) | (ty::Alias(ty::Projection, proj), ty::Param(p))
+ if tcx.def_kind(proj.def_id) != DefKind::ImplTraitPlaceholder =>
+ {
+ let p_def_id = tcx
+ .generics_of(body_owner_def_id)
+ .type_param(p, tcx)
+ .def_id;
+ let p_span = tcx.def_span(p_def_id);
+ if !sp.contains(p_span) {
+ diag.span_label(p_span, "this type parameter");
+ }
+ let hir = tcx.hir();
+ let mut note = true;
+ let parent = p_def_id
+ .as_local()
+ .and_then(|id| {
+ let local_id = hir.local_def_id_to_hir_id(id);
+ let generics = tcx.hir().find_parent(local_id)?.generics()?;
+ Some((id, generics))
+ });
+ if let Some((local_id, generics)) = parent
+ {
+ // Synthesize the associated type restriction `Add<Output = Expected>`.
+ // FIXME: extract this logic for use in other diagnostics.
+ let (trait_ref, assoc_substs) = proj.trait_ref_and_own_substs(tcx);
+ let item_name = tcx.item_name(proj.def_id);
+ let item_args = self.format_generic_args(assoc_substs);
+
+ // Here, we try to see if there's an existing
+ // trait implementation that matches the one that
+ // we're suggesting to restrict. If so, find the
+ // "end", whether it be at the end of the trait
+ // or the end of the generic arguments.
+ let mut matching_span = None;
+ let mut matched_end_of_args = false;
+ for bound in generics.bounds_for_param(local_id) {
+ let potential_spans = bound
+ .bounds
+ .iter()
+ .find_map(|bound| {
+ let bound_trait_path = bound.trait_ref()?.path;
+ let def_id = bound_trait_path.res.opt_def_id()?;
+ let generic_args = bound_trait_path.segments.iter().last().map(|path| path.args());
+ (def_id == trait_ref.def_id).then_some((bound_trait_path.span, generic_args))
+ });
+
+ if let Some((end_of_trait, end_of_args)) = potential_spans {
+ let args_span = end_of_args.and_then(|args| args.span());
+ matched_end_of_args = args_span.is_some();
+ matching_span = args_span
+ .or_else(|| Some(end_of_trait))
+ .map(|span| span.shrink_to_hi());
+ break;
+ }
+ }
+
+ if matched_end_of_args {
+ // Append suggestion to the end of our args
+ let path = format!(", {}{} = {}",item_name, item_args, p);
+ note = !suggest_constraining_type_param(
+ tcx,
+ generics,
+ diag,
+ &format!("{}", proj.self_ty()),
+ &path,
+ None,
+ matching_span,
+ );
+ } else {
+ // Suggest adding a bound to an existing trait
+ // or if the trait doesn't exist, add the trait
+ // and the suggested bounds.
+ let path = format!("<{}{} = {}>", item_name, item_args, p);
+ note = !suggest_constraining_type_param(
+ tcx,
+ generics,
+ diag,
+ &format!("{}", proj.self_ty()),
+ &path,
+ None,
+ matching_span,
+ );
+ }
+ }
+ if note {
+ diag.note("you might be missing a type parameter or trait bound");
+ }
+ }
+ (ty::Param(p), ty::Dynamic(..) | ty::Alias(ty::Opaque, ..))
+ | (ty::Dynamic(..) | ty::Alias(ty::Opaque, ..), ty::Param(p)) => {
+ let generics = tcx.generics_of(body_owner_def_id);
+ let p_span = tcx.def_span(generics.type_param(p, tcx).def_id);
+ if !sp.contains(p_span) {
+ diag.span_label(p_span, "this type parameter");
+ }
+ diag.help("type parameters must be constrained to match other types");
+ if tcx.sess.teach(&diag.get_code().unwrap()) {
+ diag.help(
+ "given a type parameter `T` and a method `foo`:
+```
+trait Trait<T> { fn foo(&self) -> T; }
+```
+the only ways to implement method `foo` are:
+- constrain `T` with an explicit type:
+```
+impl Trait<String> for X {
+ fn foo(&self) -> String { String::new() }
+}
+```
+- add a trait bound to `T` and call a method on that trait that returns `Self`:
+```
+impl<T: std::default::Default> Trait<T> for X {
+ fn foo(&self) -> T { <T as std::default::Default>::default() }
+}
+```
+- change `foo` to return an argument of type `T`:
+```
+impl<T> Trait<T> for X {
+ fn foo(&self, x: T) -> T { x }
+}
+```",
+ );
+ }
+ diag.note(
+ "for more information, visit \
+ https://doc.rust-lang.org/book/ch10-02-traits.html\
+ #traits-as-parameters",
+ );
+ }
+ (ty::Param(p), ty::Closure(..) | ty::Generator(..)) => {
+ let generics = tcx.generics_of(body_owner_def_id);
+ let p_span = tcx.def_span(generics.type_param(p, tcx).def_id);
+ if !sp.contains(p_span) {
+ diag.span_label(p_span, "this type parameter");
+ }
+ diag.help(&format!(
+ "every closure has a distinct type and so could not always match the \
+ caller-chosen type of parameter `{}`",
+ p
+ ));
+ }
+ (ty::Param(p), _) | (_, ty::Param(p)) => {
+ let generics = tcx.generics_of(body_owner_def_id);
+ let p_span = tcx.def_span(generics.type_param(p, tcx).def_id);
+ if !sp.contains(p_span) {
+ diag.span_label(p_span, "this type parameter");
+ }
+ }
+ (ty::Alias(ty::Projection, proj_ty), _) if tcx.def_kind(proj_ty.def_id) != DefKind::ImplTraitPlaceholder => {
+ self.expected_projection(
+ diag,
+ proj_ty,
+ values,
+ body_owner_def_id,
+ cause.code(),
+ );
+ }
+ (_, ty::Alias(ty::Projection, proj_ty)) if tcx.def_kind(proj_ty.def_id) != DefKind::ImplTraitPlaceholder => {
+ let msg = format!(
+ "consider constraining the associated type `{}` to `{}`",
+ values.found, values.expected,
+ );
+ if !(self.suggest_constraining_opaque_associated_type(
+ diag,
+ &msg,
+ proj_ty,
+ values.expected,
+ ) || self.suggest_constraint(
+ diag,
+ &msg,
+ body_owner_def_id,
+ proj_ty,
+ values.expected,
+ )) {
+ diag.help(&msg);
+ diag.note(
+ "for more information, visit \
+ https://doc.rust-lang.org/book/ch19-03-advanced-traits.html",
+ );
+ }
+ }
+ (ty::FnPtr(_), ty::FnDef(def, _))
+ if let hir::def::DefKind::Fn = tcx.def_kind(def) => {
+ diag.note(
+ "when the arguments and return types match, functions can be coerced \
+ to function pointers",
+ );
+ }
+ _ => {}
+ }
+ debug!(
+ "note_and_explain_type_err expected={:?} ({:?}) found={:?} ({:?})",
+ values.expected,
+ values.expected.kind(),
+ values.found,
+ values.found.kind(),
+ );
+ }
+ CyclicTy(ty) => {
+ // Watch out for various cases of cyclic types and try to explain.
+ if ty.is_closure() || ty.is_generator() {
+ diag.note(
+ "closures cannot capture themselves or take themselves as argument;\n\
+ this error may be the result of a recent compiler bug-fix,\n\
+ see issue #46062 <https://github.com/rust-lang/rust/issues/46062>\n\
+ for more information",
+ );
+ }
+ }
+ TargetFeatureCast(def_id) => {
+ let target_spans = tcx.get_attrs(def_id, sym::target_feature).map(|attr| attr.span);
+ diag.note(
+ "functions with `#[target_feature]` can only be coerced to `unsafe` function pointers"
+ );
+ diag.span_labels(target_spans, "`#[target_feature]` added here");
+ }
+ _ => {}
+ }
+ }
+
+ fn suggest_constraint(
+ &self,
+ diag: &mut Diagnostic,
+ msg: &str,
+ body_owner_def_id: DefId,
+ proj_ty: &ty::AliasTy<'tcx>,
+ ty: Ty<'tcx>,
+ ) -> bool {
+ let tcx = self.tcx;
+ let assoc = tcx.associated_item(proj_ty.def_id);
+ let (trait_ref, assoc_substs) = proj_ty.trait_ref_and_own_substs(tcx);
+ if let Some(item) = tcx.hir().get_if_local(body_owner_def_id) {
+ if let Some(hir_generics) = item.generics() {
+ // Get the `DefId` for the type parameter corresponding to `A` in `<A as T>::Foo`.
+ // This will also work for `impl Trait`.
+ let def_id = if let ty::Param(param_ty) = proj_ty.self_ty().kind() {
+ let generics = tcx.generics_of(body_owner_def_id);
+ generics.type_param(param_ty, tcx).def_id
+ } else {
+ return false;
+ };
+ let Some(def_id) = def_id.as_local() else {
+ return false;
+ };
+
+ // First look in the `where` clause, as this might be
+ // `fn foo<T>(x: T) where T: Trait`.
+ for pred in hir_generics.bounds_for_param(def_id) {
+ if self.constrain_generic_bound_associated_type_structured_suggestion(
+ diag,
+ &trait_ref,
+ pred.bounds,
+ assoc,
+ assoc_substs,
+ ty,
+ msg,
+ false,
+ ) {
+ return true;
+ }
+ }
+ }
+ }
+ false
+ }
+
+ /// An associated type was expected and a different type was found.
+ ///
+ /// We perform a few different checks to see what we can suggest:
+ ///
+ /// - In the current item, look for associated functions that return the expected type and
+ /// suggest calling them. (Not a structured suggestion.)
+ /// - If any of the item's generic bounds can be constrained, we suggest constraining the
+ /// associated type to the found type.
+ /// - If the associated type has a default type and was expected inside of a `trait`, we
+ /// mention that this is disallowed.
+ /// - If all other things fail, and the error is not because of a mismatch between the `trait`
+ /// and the `impl`, we provide a generic `help` to constrain the assoc type or call an assoc
+ /// fn that returns the type.
+ fn expected_projection(
+ &self,
+ diag: &mut Diagnostic,
+ proj_ty: &ty::AliasTy<'tcx>,
+ values: ExpectedFound<Ty<'tcx>>,
+ body_owner_def_id: DefId,
+ cause_code: &ObligationCauseCode<'_>,
+ ) {
+ let tcx = self.tcx;
+
+ let msg = format!(
+ "consider constraining the associated type `{}` to `{}`",
+ values.expected, values.found
+ );
+ let body_owner = tcx.hir().get_if_local(body_owner_def_id);
+ let current_method_ident = body_owner.and_then(|n| n.ident()).map(|i| i.name);
+
+ // We don't want to suggest calling an assoc fn in a scope where that isn't feasible.
+ let callable_scope = matches!(
+ body_owner,
+ Some(
+ hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(..), .. })
+ | hir::Node::TraitItem(hir::TraitItem { kind: hir::TraitItemKind::Fn(..), .. })
+ | hir::Node::ImplItem(hir::ImplItem { kind: hir::ImplItemKind::Fn(..), .. }),
+ )
+ );
+ let impl_comparison =
+ matches!(cause_code, ObligationCauseCode::CompareImplItemObligation { .. });
+ let assoc = tcx.associated_item(proj_ty.def_id);
+ if !callable_scope || impl_comparison {
+ // We do not want to suggest calling functions when the reason of the
+ // type error is a comparison of an `impl` with its `trait` or when the
+ // scope is outside of a `Body`.
+ } else {
+ // If we find a suitable associated function that returns the expected type, we don't
+ // want the more general suggestion later in this method about "consider constraining
+ // the associated type or calling a method that returns the associated type".
+ let point_at_assoc_fn = self.point_at_methods_that_satisfy_associated_type(
+ diag,
+ assoc.container_id(tcx),
+ current_method_ident,
+ proj_ty.def_id,
+ values.expected,
+ );
+ // Possibly suggest constraining the associated type to conform to the
+ // found type.
+ if self.suggest_constraint(diag, &msg, body_owner_def_id, proj_ty, values.found)
+ || point_at_assoc_fn
+ {
+ return;
+ }
+ }
+
+ self.suggest_constraining_opaque_associated_type(diag, &msg, proj_ty, values.found);
+
+ if self.point_at_associated_type(diag, body_owner_def_id, values.found) {
+ return;
+ }
+
+ if !impl_comparison {
+ // Generic suggestion when we can't be more specific.
+ if callable_scope {
+ diag.help(&format!(
+ "{} or calling a method that returns `{}`",
+ msg, values.expected
+ ));
+ } else {
+ diag.help(&msg);
+ }
+ diag.note(
+ "for more information, visit \
+ https://doc.rust-lang.org/book/ch19-03-advanced-traits.html",
+ );
+ }
+ if tcx.sess.teach(&diag.get_code().unwrap()) {
+ diag.help(
+ "given an associated type `T` and a method `foo`:
+```
+trait Trait {
+type T;
+fn foo(&self) -> Self::T;
+}
+```
+the only way of implementing method `foo` is to constrain `T` with an explicit associated type:
+```
+impl Trait for X {
+type T = String;
+fn foo(&self) -> Self::T { String::new() }
+}
+```",
+ );
+ }
+ }
+
+ /// When the expected `impl Trait` is not defined in the current item, it will come from
+ /// a return type. This can occur when dealing with `TryStream` (#71035).
+ fn suggest_constraining_opaque_associated_type(
+ &self,
+ diag: &mut Diagnostic,
+ msg: &str,
+ proj_ty: &ty::AliasTy<'tcx>,
+ ty: Ty<'tcx>,
+ ) -> bool {
+ let tcx = self.tcx;
+
+ let assoc = tcx.associated_item(proj_ty.def_id);
+ if let ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }) = *proj_ty.self_ty().kind() {
+ let opaque_local_def_id = def_id.as_local();
+ let opaque_hir_ty = if let Some(opaque_local_def_id) = opaque_local_def_id {
+ match &tcx.hir().expect_item(opaque_local_def_id).kind {
+ hir::ItemKind::OpaqueTy(opaque_hir_ty) => opaque_hir_ty,
+ _ => bug!("The HirId comes from a `ty::Opaque`"),
+ }
+ } else {
+ return false;
+ };
+
+ let (trait_ref, assoc_substs) = proj_ty.trait_ref_and_own_substs(tcx);
+
+ self.constrain_generic_bound_associated_type_structured_suggestion(
+ diag,
+ &trait_ref,
+ opaque_hir_ty.bounds,
+ assoc,
+ assoc_substs,
+ ty,
+ msg,
+ true,
+ )
+ } else {
+ false
+ }
+ }
+
+ fn point_at_methods_that_satisfy_associated_type(
+ &self,
+ diag: &mut Diagnostic,
+ assoc_container_id: DefId,
+ current_method_ident: Option<Symbol>,
+ proj_ty_item_def_id: DefId,
+ expected: Ty<'tcx>,
+ ) -> bool {
+ let tcx = self.tcx;
+
+ let items = tcx.associated_items(assoc_container_id);
+ // Find all the methods in the trait that could be called to construct the
+ // expected associated type.
+ // FIXME: consider suggesting the use of associated `const`s.
+ let methods: Vec<(Span, String)> = items
+ .in_definition_order()
+ .filter(|item| {
+ ty::AssocKind::Fn == item.kind
+ && Some(item.name) != current_method_ident
+ && !tcx.is_doc_hidden(item.def_id)
+ })
+ .filter_map(|item| {
+ let method = tcx.fn_sig(item.def_id).subst_identity();
+ match *method.output().skip_binder().kind() {
+ ty::Alias(ty::Projection, ty::AliasTy { def_id: item_def_id, .. })
+ if item_def_id == proj_ty_item_def_id =>
+ {
+ Some((
+ tcx.def_span(item.def_id),
+ format!("consider calling `{}`", tcx.def_path_str(item.def_id)),
+ ))
+ }
+ _ => None,
+ }
+ })
+ .collect();
+ if !methods.is_empty() {
+ // Use a single `help:` to show all the methods in the trait that can
+ // be used to construct the expected associated type.
+ let mut span: MultiSpan =
+ methods.iter().map(|(sp, _)| *sp).collect::<Vec<Span>>().into();
+ let msg = format!(
+ "{some} method{s} {are} available that return{r} `{ty}`",
+ some = if methods.len() == 1 { "a" } else { "some" },
+ s = pluralize!(methods.len()),
+ are = pluralize!("is", methods.len()),
+ r = if methods.len() == 1 { "s" } else { "" },
+ ty = expected
+ );
+ for (sp, label) in methods.into_iter() {
+ span.push_span_label(sp, label);
+ }
+ diag.span_help(span, &msg);
+ return true;
+ }
+ false
+ }
+
+ fn point_at_associated_type(
+ &self,
+ diag: &mut Diagnostic,
+ body_owner_def_id: DefId,
+ found: Ty<'tcx>,
+ ) -> bool {
+ let tcx = self.tcx;
+
+ let Some(hir_id) = body_owner_def_id.as_local() else {
+ return false;
+ };
+ let hir_id = tcx.hir().local_def_id_to_hir_id(hir_id);
+ // When `body_owner` is an `impl` or `trait` item, look in its associated types for
+ // `expected` and point at it.
+ let parent_id = tcx.hir().get_parent_item(hir_id);
+ let item = tcx.hir().find_by_def_id(parent_id.def_id);
+
+ debug!("expected_projection parent item {:?}", item);
+
+ let param_env = tcx.param_env(body_owner_def_id);
+
+ match item {
+ Some(hir::Node::Item(hir::Item { kind: hir::ItemKind::Trait(.., items), .. })) => {
+ // FIXME: account for `#![feature(specialization)]`
+ for item in &items[..] {
+ match item.kind {
+ hir::AssocItemKind::Type => {
+ // FIXME: account for returning some type in a trait fn impl that has
+ // an assoc type as a return type (#72076).
+ if let hir::Defaultness::Default { has_value: true } =
+ tcx.impl_defaultness(item.id.owner_id)
+ {
+ let assoc_ty = tcx.type_of(item.id.owner_id).subst_identity();
+ if self.infcx.can_eq(param_env, assoc_ty, found) {
+ diag.span_label(
+ item.span,
+ "associated type defaults can't be assumed inside the \
+ trait defining them",
+ );
+ return true;
+ }
+ }
+ }
+ _ => {}
+ }
+ }
+ }
+ Some(hir::Node::Item(hir::Item {
+ kind: hir::ItemKind::Impl(hir::Impl { items, .. }),
+ ..
+ })) => {
+ for item in &items[..] {
+ if let hir::AssocItemKind::Type = item.kind {
+ let assoc_ty = tcx.type_of(item.id.owner_id).subst_identity();
+
+ if self.infcx.can_eq(param_env, assoc_ty, found) {
+ diag.span_label(item.span, "expected this associated type");
+ return true;
+ }
+ }
+ }
+ }
+ _ => {}
+ }
+ false
+ }
+
+ /// Given a slice of `hir::GenericBound`s, if any of them corresponds to the `trait_ref`
+ /// requirement, provide a structured suggestion to constrain it to a given type `ty`.
+ ///
+ /// `is_bound_surely_present` indicates whether we know the bound we're looking for is
+ /// inside `bounds`. If that's the case then we can consider `bounds` containing only one
+ /// trait bound as the one we're looking for. This can help in cases where the associated
+ /// type is defined on a supertrait of the one present in the bounds.
+ fn constrain_generic_bound_associated_type_structured_suggestion(
+ &self,
+ diag: &mut Diagnostic,
+ trait_ref: &ty::TraitRef<'tcx>,
+ bounds: hir::GenericBounds<'_>,
+ assoc: ty::AssocItem,
+ assoc_substs: &[ty::GenericArg<'tcx>],
+ ty: Ty<'tcx>,
+ msg: &str,
+ is_bound_surely_present: bool,
+ ) -> bool {
+ // FIXME: we would want to call `resolve_vars_if_possible` on `ty` before suggesting.
+
+ let trait_bounds = bounds.iter().filter_map(|bound| match bound {
+ hir::GenericBound::Trait(ptr, hir::TraitBoundModifier::None) => Some(ptr),
+ _ => None,
+ });
+
+ let matching_trait_bounds = trait_bounds
+ .clone()
+ .filter(|ptr| ptr.trait_ref.trait_def_id() == Some(trait_ref.def_id))
+ .collect::<Vec<_>>();
+
+ let span = match &matching_trait_bounds[..] {
+ &[ptr] => ptr.span,
+ &[] if is_bound_surely_present => match &trait_bounds.collect::<Vec<_>>()[..] {
+ &[ptr] => ptr.span,
+ _ => return false,
+ },
+ _ => return false,
+ };
+
+ self.constrain_associated_type_structured_suggestion(
+ diag,
+ span,
+ assoc,
+ assoc_substs,
+ ty,
+ msg,
+ )
+ }
+
+ /// Given a span corresponding to a bound, provide a structured suggestion to set an
+ /// associated type to a given type `ty`.
+ fn constrain_associated_type_structured_suggestion(
+ &self,
+ diag: &mut Diagnostic,
+ span: Span,
+ assoc: ty::AssocItem,
+ assoc_substs: &[ty::GenericArg<'tcx>],
+ ty: Ty<'tcx>,
+ msg: &str,
+ ) -> bool {
+ let tcx = self.tcx;
+
+ if let Ok(has_params) =
+ tcx.sess.source_map().span_to_snippet(span).map(|snippet| snippet.ends_with('>'))
+ {
+ let (span, sugg) = if has_params {
+ let pos = span.hi() - BytePos(1);
+ let span = Span::new(pos, pos, span.ctxt(), span.parent());
+ (span, format!(", {} = {}", assoc.ident(tcx), ty))
+ } else {
+ let item_args = self.format_generic_args(assoc_substs);
+ (span.shrink_to_hi(), format!("<{}{} = {}>", assoc.ident(tcx), item_args, ty))
+ };
+ diag.span_suggestion_verbose(span, msg, sugg, MaybeIncorrect);
+ return true;
+ }
+ false
+ }
+
+ pub fn format_generic_args(&self, args: &[ty::GenericArg<'tcx>]) -> String {
+ FmtPrinter::new(self.tcx, hir::def::Namespace::TypeNS)
+ .path_generic_args(Ok, args)
+ .expect("could not write to `String`.")
+ .into_buffer()
+ }
+}
diff --git a/compiler/rustc_infer/src/infer/error_reporting/suggest.rs b/compiler/rustc_infer/src/infer/error_reporting/suggest.rs
index 5b02956a1..55dcfd05e 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/suggest.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/suggest.rs
@@ -8,24 +8,25 @@ use rustc_middle::traits::{
StatementAsExpression,
};
use rustc_middle::ty::print::with_no_trimmed_paths;
-use rustc_middle::ty::{self as ty, Ty, TypeVisitable};
+use rustc_middle::ty::{self as ty, IsSuggestable, Ty, TypeVisitableExt};
use rustc_span::{sym, BytePos, Span};
-use crate::errors::SuggAddLetForLetChains;
+use crate::errors::{
+ ConsiderAddingAwait, SuggAddLetForLetChains, SuggestRemoveSemiOrReturnBinding,
+};
use super::TypeErrCtxt;
impl<'tcx> TypeErrCtxt<'_, 'tcx> {
pub(super) fn suggest_remove_semi_or_return_binding(
&self,
- err: &mut Diagnostic,
first_id: Option<hir::HirId>,
first_ty: Ty<'tcx>,
first_span: Span,
second_id: Option<hir::HirId>,
second_ty: Ty<'tcx>,
second_span: Span,
- ) {
+ ) -> Option<SuggestRemoveSemiOrReturnBinding> {
let remove_semicolon = [
(first_id, self.resolve_vars_if_possible(second_ty)),
(second_id, self.resolve_vars_if_possible(first_ty)),
@@ -37,35 +38,29 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
});
match remove_semicolon {
Some((sp, StatementAsExpression::NeedsBoxing)) => {
- err.multipart_suggestion(
- "consider removing this semicolon and boxing the expressions",
- vec![
- (first_span.shrink_to_lo(), "Box::new(".to_string()),
- (first_span.shrink_to_hi(), ")".to_string()),
- (second_span.shrink_to_lo(), "Box::new(".to_string()),
- (second_span.shrink_to_hi(), ")".to_string()),
- (sp, String::new()),
- ],
- Applicability::MachineApplicable,
- );
+ Some(SuggestRemoveSemiOrReturnBinding::RemoveAndBox {
+ first_lo: first_span.shrink_to_lo(),
+ first_hi: first_span.shrink_to_hi(),
+ second_lo: second_span.shrink_to_lo(),
+ second_hi: second_span.shrink_to_hi(),
+ sp,
+ })
}
Some((sp, StatementAsExpression::CorrectType)) => {
- err.span_suggestion_short(
- sp,
- "consider removing this semicolon",
- "",
- Applicability::MachineApplicable,
- );
+ Some(SuggestRemoveSemiOrReturnBinding::Remove { sp })
}
None => {
+ let mut ret = None;
for (id, ty) in [(first_id, second_ty), (second_id, first_ty)] {
if let Some(id) = id
&& let hir::Node::Block(blk) = self.tcx.hir().get(id)
- && self.consider_returning_binding(blk, ty, err)
+ && let Some(diag) = self.consider_returning_binding_diag(blk, ty)
{
+ ret = Some(diag);
break;
}
}
+ ret
}
}
}
@@ -198,7 +193,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
return;
}
- match (
+ let subdiag = match (
self.get_impl_future_output_ty(exp_found.expected),
self.get_impl_future_output_ty(exp_found.found),
) {
@@ -207,82 +202,68 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
{
ObligationCauseCode::IfExpression(box IfExpressionCause { then_id, .. }) => {
let then_span = self.find_block_span_from_hir_id(*then_id);
- diag.multipart_suggestion(
- "consider `await`ing on both `Future`s",
- vec![
- (then_span.shrink_to_hi(), ".await".to_string()),
- (exp_span.shrink_to_hi(), ".await".to_string()),
- ],
- Applicability::MaybeIncorrect,
- );
+ Some(ConsiderAddingAwait::BothFuturesSugg {
+ first: then_span.shrink_to_hi(),
+ second: exp_span.shrink_to_hi(),
+ })
}
ObligationCauseCode::MatchExpressionArm(box MatchExpressionArmCause {
prior_arms,
..
}) => {
if let [.., arm_span] = &prior_arms[..] {
- diag.multipart_suggestion(
- "consider `await`ing on both `Future`s",
- vec![
- (arm_span.shrink_to_hi(), ".await".to_string()),
- (exp_span.shrink_to_hi(), ".await".to_string()),
- ],
- Applicability::MaybeIncorrect,
- );
+ Some(ConsiderAddingAwait::BothFuturesSugg {
+ first: arm_span.shrink_to_hi(),
+ second: exp_span.shrink_to_hi(),
+ })
} else {
- diag.help("consider `await`ing on both `Future`s");
+ Some(ConsiderAddingAwait::BothFuturesHelp)
}
}
- _ => {
- diag.help("consider `await`ing on both `Future`s");
- }
+ _ => Some(ConsiderAddingAwait::BothFuturesHelp),
},
(_, Some(ty)) if self.same_type_modulo_infer(exp_found.expected, ty) => {
- diag.span_suggestion_verbose(
- exp_span.shrink_to_hi(),
- "consider `await`ing on the `Future`",
- ".await",
- Applicability::MaybeIncorrect,
- );
+ // FIXME: Seems like we can't have a suggestion and a note with different spans in a single subdiagnostic
+ diag.subdiagnostic(ConsiderAddingAwait::FutureSugg {
+ span: exp_span.shrink_to_hi(),
+ });
+ Some(ConsiderAddingAwait::FutureSuggNote { span: exp_span })
}
(Some(ty), _) if self.same_type_modulo_infer(ty, exp_found.found) => match cause.code()
{
ObligationCauseCode::Pattern { span: Some(then_span), .. } => {
- diag.span_suggestion_verbose(
- then_span.shrink_to_hi(),
- "consider `await`ing on the `Future`",
- ".await",
- Applicability::MaybeIncorrect,
- );
+ Some(ConsiderAddingAwait::FutureSugg { span: then_span.shrink_to_hi() })
}
ObligationCauseCode::IfExpression(box IfExpressionCause { then_id, .. }) => {
let then_span = self.find_block_span_from_hir_id(*then_id);
- diag.span_suggestion_verbose(
- then_span.shrink_to_hi(),
- "consider `await`ing on the `Future`",
- ".await",
- Applicability::MaybeIncorrect,
- );
+ Some(ConsiderAddingAwait::FutureSugg { span: then_span.shrink_to_hi() })
}
ObligationCauseCode::MatchExpressionArm(box MatchExpressionArmCause {
ref prior_arms,
..
- }) => {
- diag.multipart_suggestion_verbose(
- "consider `await`ing on the `Future`",
- prior_arms
- .iter()
- .map(|arm| (arm.shrink_to_hi(), ".await".to_string()))
- .collect(),
- Applicability::MaybeIncorrect,
- );
- }
- _ => {}
+ }) => Some({
+ ConsiderAddingAwait::FutureSuggMultiple {
+ spans: prior_arms.iter().map(|arm| arm.shrink_to_hi()).collect(),
+ }
+ }),
+ _ => None,
},
- _ => {}
+ _ => None,
+ };
+ if let Some(subdiag) = subdiag {
+ diag.subdiagnostic(subdiag);
}
}
+ pub fn suggest_await_on_future(&self, diag: &mut Diagnostic, sp: Span) {
+ diag.span_suggestion_verbose(
+ sp.shrink_to_hi(),
+ "consider `await`ing on the `Future`",
+ ".await",
+ Applicability::MaybeIncorrect,
+ );
+ }
+
pub(super) fn suggest_accessing_field_where_appropriate(
&self,
cause: &ObligationCause<'tcx>,
@@ -351,6 +332,118 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
}
}
+ pub(super) fn suggest_function_pointers(
+ &self,
+ cause: &ObligationCause<'tcx>,
+ span: Span,
+ exp_found: &ty::error::ExpectedFound<Ty<'tcx>>,
+ diag: &mut Diagnostic,
+ ) {
+ debug!("suggest_function_pointers(cause={:?}, exp_found={:?})", cause, exp_found);
+ let ty::error::ExpectedFound { expected, found } = exp_found;
+ let expected_inner = expected.peel_refs();
+ let found_inner = found.peel_refs();
+ if !expected_inner.is_fn() || !found_inner.is_fn() {
+ return;
+ }
+ match (&expected_inner.kind(), &found_inner.kind()) {
+ (ty::FnPtr(sig), ty::FnDef(did, substs)) => {
+ let expected_sig = &(self.normalize_fn_sig)(*sig);
+ let found_sig =
+ &(self.normalize_fn_sig)(self.tcx.fn_sig(*did).subst(self.tcx, substs));
+
+ let fn_name = self.tcx.def_path_str_with_substs(*did, substs);
+
+ if !self.same_type_modulo_infer(*found_sig, *expected_sig)
+ || !sig.is_suggestable(self.tcx, true)
+ || ty::util::is_intrinsic(self.tcx, *did)
+ {
+ return;
+ }
+
+ let (msg, sug) = match (expected.is_ref(), found.is_ref()) {
+ (true, false) => {
+ let msg = "consider using a reference";
+ let sug = format!("&{fn_name}");
+ (msg, sug)
+ }
+ (false, true) => {
+ let msg = "consider removing the reference";
+ let sug = format!("{fn_name}");
+ (msg, sug)
+ }
+ (true, true) => {
+ diag.note("fn items are distinct from fn pointers");
+ let msg = "consider casting to a fn pointer";
+ let sug = format!("&({fn_name} as {sig})");
+ (msg, sug)
+ }
+ (false, false) => {
+ diag.note("fn items are distinct from fn pointers");
+ let msg = "consider casting to a fn pointer";
+ let sug = format!("{fn_name} as {sig}");
+ (msg, sug)
+ }
+ };
+ diag.span_suggestion_verbose(span, msg, sug, Applicability::MaybeIncorrect);
+ }
+ (ty::FnDef(did1, substs1), ty::FnDef(did2, substs2)) => {
+ let expected_sig =
+ &(self.normalize_fn_sig)(self.tcx.fn_sig(*did1).subst(self.tcx, substs1));
+ let found_sig =
+ &(self.normalize_fn_sig)(self.tcx.fn_sig(*did2).subst(self.tcx, substs2));
+
+ if self.same_type_modulo_infer(*expected_sig, *found_sig) {
+ diag.note("different fn items have unique types, even if their signatures are the same");
+ }
+
+ if !self.same_type_modulo_infer(*found_sig, *expected_sig)
+ || !found_sig.is_suggestable(self.tcx, true)
+ || !expected_sig.is_suggestable(self.tcx, true)
+ || ty::util::is_intrinsic(self.tcx, *did1)
+ || ty::util::is_intrinsic(self.tcx, *did2)
+ {
+ return;
+ }
+
+ let fn_name = self.tcx.def_path_str_with_substs(*did2, substs2);
+ let sug = if found.is_ref() {
+ format!("&({fn_name} as {found_sig})")
+ } else {
+ format!("{fn_name} as {found_sig}")
+ };
+
+ let msg = format!(
+ "consider casting both fn items to fn pointers using `as {expected_sig}`"
+ );
+
+ diag.span_suggestion_hidden(span, msg, sug, Applicability::MaybeIncorrect);
+ }
+ (ty::FnDef(did, substs), ty::FnPtr(sig)) => {
+ let expected_sig =
+ &(self.normalize_fn_sig)(self.tcx.fn_sig(*did).subst(self.tcx, substs));
+ let found_sig = &(self.normalize_fn_sig)(*sig);
+
+ if !self.same_type_modulo_infer(*found_sig, *expected_sig) {
+ return;
+ }
+
+ let fn_name = self.tcx.def_path_str_with_substs(*did, substs);
+
+ let casting = if expected.is_ref() {
+ format!("&({fn_name} as {found_sig})")
+ } else {
+ format!("{fn_name} as {found_sig}")
+ };
+
+ diag.help(&format!("consider casting the fn item to a fn pointer: `{}`", casting));
+ }
+ _ => {
+ return;
+ }
+ };
+ }
+
pub fn should_suggest_as_ref(&self, expected: Ty<'tcx>, found: Ty<'tcx>) -> Option<&str> {
if let (ty::Adt(exp_def, exp_substs), ty::Ref(_, found_ty, _)) =
(expected.kind(), found.kind())
@@ -411,8 +504,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
span: Span,
) {
let hir = self.tcx.hir();
- let fn_hir_id = hir.parent_id(cause.body_id);
- if let Some(node) = self.tcx.hir().find(fn_hir_id) &&
+ if let Some(node) = self.tcx.hir().find_by_def_id(cause.body_id) &&
let hir::Node::Item(hir::Item {
kind: hir::ItemKind::Fn(_sig, _, body_id), ..
}) = node {
@@ -549,16 +641,15 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
/// Suggest returning a local binding with a compatible type if the block
/// has no return expression.
- pub fn consider_returning_binding(
+ pub fn consider_returning_binding_diag(
&self,
blk: &'tcx hir::Block<'tcx>,
expected_ty: Ty<'tcx>,
- err: &mut Diagnostic,
- ) -> bool {
+ ) -> Option<SuggestRemoveSemiOrReturnBinding> {
let blk = blk.innermost_block();
// Do not suggest if we have a tail expr.
if blk.expr.is_some() {
- return false;
+ return None;
}
let mut shadowed = FxIndexSet::default();
let mut candidate_idents = vec![];
@@ -627,7 +718,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
match &candidate_idents[..] {
[(ident, _ty)] => {
let sm = self.tcx.sess.source_map();
- if let Some(stmt) = blk.stmts.last() {
+ let (span, sugg) = if let Some(stmt) = blk.stmts.last() {
let stmt_span = sm.stmt_span(stmt.span, blk.span);
let sugg = if sm.is_multiline(blk.span)
&& let Some(spacing) = sm.indentation_before(stmt_span)
@@ -636,12 +727,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
} else {
format!(" {ident}")
};
- err.span_suggestion_verbose(
- stmt_span.shrink_to_hi(),
- format!("consider returning the local binding `{ident}`"),
- sugg,
- Applicability::MaybeIncorrect,
- );
+ (stmt_span.shrink_to_hi(), sugg)
} else {
let sugg = if sm.is_multiline(blk.span)
&& let Some(spacing) = sm.indentation_before(blk.span.shrink_to_lo())
@@ -651,21 +737,34 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
format!(" {ident} ")
};
let left_span = sm.span_through_char(blk.span, '{').shrink_to_hi();
- err.span_suggestion_verbose(
+ (
sm.span_extend_while(left_span, |c| c.is_whitespace()).unwrap_or(left_span),
- format!("consider returning the local binding `{ident}`"),
sugg,
- Applicability::MaybeIncorrect,
- );
- }
- true
+ )
+ };
+ Some(SuggestRemoveSemiOrReturnBinding::Add { sp: span, code: sugg, ident: *ident })
}
values if (1..3).contains(&values.len()) => {
let spans = values.iter().map(|(ident, _)| ident.span).collect::<Vec<_>>();
- err.span_note(spans, "consider returning one of these bindings");
+ Some(SuggestRemoveSemiOrReturnBinding::AddOne { spans: spans.into() })
+ }
+ _ => None,
+ }
+ }
+
+ pub fn consider_returning_binding(
+ &self,
+ blk: &'tcx hir::Block<'tcx>,
+ expected_ty: Ty<'tcx>,
+ err: &mut Diagnostic,
+ ) -> bool {
+ let diag = self.consider_returning_binding_diag(blk, expected_ty);
+ match diag {
+ Some(diag) => {
+ err.subdiagnostic(diag);
true
}
- _ => false,
+ None => false,
}
}
}
diff --git a/compiler/rustc_infer/src/infer/freshen.rs b/compiler/rustc_infer/src/infer/freshen.rs
index 8f53b1ccd..f09f93abf 100644
--- a/compiler/rustc_infer/src/infer/freshen.rs
+++ b/compiler/rustc_infer/src/infer/freshen.rs
@@ -34,7 +34,7 @@ use super::InferCtxt;
use rustc_data_structures::fx::FxHashMap;
use rustc_middle::infer::unify_key::ToType;
use rustc_middle::ty::fold::TypeFolder;
-use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable, TypeSuperFoldable, TypeVisitable};
+use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable, TypeSuperFoldable, TypeVisitableExt};
use std::collections::hash_map::Entry;
pub struct TypeFreshener<'a, 'tcx> {
@@ -58,14 +58,9 @@ impl<'a, 'tcx> TypeFreshener<'a, 'tcx> {
}
}
- fn freshen_ty<F>(
- &mut self,
- opt_ty: Option<Ty<'tcx>>,
- key: ty::InferTy,
- freshener: F,
- ) -> Ty<'tcx>
+ fn freshen_ty<F>(&mut self, opt_ty: Option<Ty<'tcx>>, key: ty::InferTy, mk_fresh: F) -> Ty<'tcx>
where
- F: FnOnce(u32) -> ty::InferTy,
+ F: FnOnce(u32) -> Ty<'tcx>,
{
if let Some(ty) = opt_ty {
return ty.fold_with(self);
@@ -76,7 +71,7 @@ impl<'a, 'tcx> TypeFreshener<'a, 'tcx> {
Entry::Vacant(entry) => {
let index = self.ty_freshen_count;
self.ty_freshen_count += 1;
- let t = self.infcx.tcx.mk_ty_infer(freshener(index));
+ let t = mk_fresh(index);
entry.insert(t);
t
}
@@ -110,8 +105,8 @@ impl<'a, 'tcx> TypeFreshener<'a, 'tcx> {
}
}
-impl<'a, 'tcx> TypeFolder<'tcx> for TypeFreshener<'a, 'tcx> {
- fn tcx<'b>(&'b self) -> TyCtxt<'tcx> {
+impl<'a, 'tcx> TypeFolder<TyCtxt<'tcx>> for TypeFreshener<'a, 'tcx> {
+ fn interner(&self) -> TyCtxt<'tcx> {
self.infcx.tcx
}
@@ -126,92 +121,36 @@ impl<'a, 'tcx> TypeFolder<'tcx> for TypeFreshener<'a, 'tcx> {
| ty::ReFree(_)
| ty::ReVar(_)
| ty::RePlaceholder(..)
+ | ty::ReError(_)
| ty::ReErased => {
// replace all free regions with 'erased
- self.tcx().lifetimes.re_erased
+ self.interner().lifetimes.re_erased
}
ty::ReStatic => {
if self.keep_static {
r
} else {
- self.tcx().lifetimes.re_erased
+ self.interner().lifetimes.re_erased
}
}
}
}
+ #[inline]
fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
if !t.needs_infer() && !t.has_erasable_regions() {
- return t;
- }
+ t
+ } else {
+ match *t.kind() {
+ ty::Infer(v) => self.fold_infer_ty(v).unwrap_or(t),
- let tcx = self.infcx.tcx;
+ // This code is hot enough that a non-debug assertion here makes a noticeable
+ // difference on benchmarks like `wg-grammar`.
+ #[cfg(debug_assertions)]
+ ty::Placeholder(..) | ty::Bound(..) => bug!("unexpected type {:?}", t),
- match *t.kind() {
- ty::Infer(ty::TyVar(v)) => {
- let opt_ty = self.infcx.inner.borrow_mut().type_variables().probe(v).known();
- self.freshen_ty(opt_ty, ty::TyVar(v), ty::FreshTy)
+ _ => t.super_fold_with(self),
}
-
- ty::Infer(ty::IntVar(v)) => self.freshen_ty(
- self.infcx
- .inner
- .borrow_mut()
- .int_unification_table()
- .probe_value(v)
- .map(|v| v.to_type(tcx)),
- ty::IntVar(v),
- ty::FreshIntTy,
- ),
-
- ty::Infer(ty::FloatVar(v)) => self.freshen_ty(
- self.infcx
- .inner
- .borrow_mut()
- .float_unification_table()
- .probe_value(v)
- .map(|v| v.to_type(tcx)),
- ty::FloatVar(v),
- ty::FreshFloatTy,
- ),
-
- ty::Infer(ty::FreshTy(ct) | ty::FreshIntTy(ct) | ty::FreshFloatTy(ct)) => {
- if ct >= self.ty_freshen_count {
- bug!(
- "Encountered a freshend type with id {} \
- but our counter is only at {}",
- ct,
- self.ty_freshen_count
- );
- }
- t
- }
-
- ty::Generator(..)
- | ty::Bool
- | ty::Char
- | ty::Int(..)
- | ty::Uint(..)
- | ty::Float(..)
- | ty::Adt(..)
- | ty::Str
- | ty::Error(_)
- | ty::Array(..)
- | ty::Slice(..)
- | ty::RawPtr(..)
- | ty::Ref(..)
- | ty::FnDef(..)
- | ty::FnPtr(_)
- | ty::Dynamic(..)
- | ty::Never
- | ty::Tuple(..)
- | ty::Alias(..)
- | ty::Foreign(..)
- | ty::Param(..)
- | ty::Closure(..)
- | ty::GeneratorWitness(..) => t.super_fold_with(self),
-
- ty::Placeholder(..) | ty::Bound(..) => bug!("unexpected type {:?}", t),
}
}
@@ -252,3 +191,54 @@ impl<'a, 'tcx> TypeFolder<'tcx> for TypeFreshener<'a, 'tcx> {
}
}
}
+
+impl<'a, 'tcx> TypeFreshener<'a, 'tcx> {
+ // This is separate from `fold_ty` to keep that method small and inlinable.
+ #[inline(never)]
+ fn fold_infer_ty(&mut self, v: ty::InferTy) -> Option<Ty<'tcx>> {
+ match v {
+ ty::TyVar(v) => {
+ let opt_ty = self.infcx.inner.borrow_mut().type_variables().probe(v).known();
+ Some(self.freshen_ty(opt_ty, ty::TyVar(v), |n| self.infcx.tcx.mk_fresh_ty(n)))
+ }
+
+ ty::IntVar(v) => Some(
+ self.freshen_ty(
+ self.infcx
+ .inner
+ .borrow_mut()
+ .int_unification_table()
+ .probe_value(v)
+ .map(|v| v.to_type(self.infcx.tcx)),
+ ty::IntVar(v),
+ |n| self.infcx.tcx.mk_fresh_int_ty(n),
+ ),
+ ),
+
+ ty::FloatVar(v) => Some(
+ self.freshen_ty(
+ self.infcx
+ .inner
+ .borrow_mut()
+ .float_unification_table()
+ .probe_value(v)
+ .map(|v| v.to_type(self.infcx.tcx)),
+ ty::FloatVar(v),
+ |n| self.infcx.tcx.mk_fresh_float_ty(n),
+ ),
+ ),
+
+ ty::FreshTy(ct) | ty::FreshIntTy(ct) | ty::FreshFloatTy(ct) => {
+ if ct >= self.ty_freshen_count {
+ bug!(
+ "Encountered a freshend type with id {} \
+ but our counter is only at {}",
+ ct,
+ self.ty_freshen_count
+ );
+ }
+ None
+ }
+ }
+ }
+}
diff --git a/compiler/rustc_infer/src/infer/fudge.rs b/compiler/rustc_infer/src/infer/fudge.rs
index 6dd6c4e1f..86c2c2be4 100644
--- a/compiler/rustc_infer/src/infer/fudge.rs
+++ b/compiler/rustc_infer/src/infer/fudge.rs
@@ -98,7 +98,7 @@ impl<'tcx> InferCtxt<'tcx> {
pub fn fudge_inference_if_ok<T, E, F>(&self, f: F) -> Result<T, E>
where
F: FnOnce() -> Result<T, E>,
- T: TypeFoldable<'tcx>,
+ T: TypeFoldable<TyCtxt<'tcx>>,
{
let variable_lengths = self.variable_lengths();
let (mut fudger, value) = self.probe(|_| {
@@ -175,8 +175,8 @@ pub struct InferenceFudger<'a, 'tcx> {
const_vars: (Range<ConstVid<'tcx>>, Vec<ConstVariableOrigin>),
}
-impl<'a, 'tcx> TypeFolder<'tcx> for InferenceFudger<'a, 'tcx> {
- fn tcx<'b>(&'b self) -> TyCtxt<'tcx> {
+impl<'a, 'tcx> TypeFolder<TyCtxt<'tcx>> for InferenceFudger<'a, 'tcx> {
+ fn interner(&self) -> TyCtxt<'tcx> {
self.infcx.tcx
}
diff --git a/compiler/rustc_infer/src/infer/glb.rs b/compiler/rustc_infer/src/infer/glb.rs
index 21b68ce99..49df393d8 100644
--- a/compiler/rustc_infer/src/infer/glb.rs
+++ b/compiler/rustc_infer/src/infer/glb.rs
@@ -1,14 +1,13 @@
//! Greatest lower bound. See [`lattice`].
-use super::combine::CombineFields;
+use super::combine::{CombineFields, ObligationEmittingRelation};
use super::lattice::{self, LatticeDir};
use super::InferCtxt;
use super::Subtype;
-use crate::infer::combine::ConstEquateRelation;
-use crate::traits::{ObligationCause, PredicateObligation};
+use crate::traits::{ObligationCause, PredicateObligations};
use rustc_middle::ty::relate::{Relate, RelateResult, TypeRelation};
-use rustc_middle::ty::{self, Ty, TyCtxt};
+use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt};
/// "Greatest lower bound" (common subtype)
pub struct Glb<'combine, 'infcx, 'tcx> {
@@ -79,7 +78,8 @@ impl<'tcx> TypeRelation<'tcx> for Glb<'_, '_, 'tcx> {
debug!("{}.regions({:?}, {:?})", self.tag(), a, b);
let origin = Subtype(Box::new(self.fields.trace.clone()));
- Ok(self.fields.infcx.inner.borrow_mut().unwrap_region_constraints().glb_regions(
+ // GLB(&'static u8, &'a u8) == &RegionLUB('static, 'a) u8 == &'static u8
+ Ok(self.fields.infcx.inner.borrow_mut().unwrap_region_constraints().lub_regions(
self.tcx(),
origin,
a,
@@ -135,10 +135,6 @@ impl<'combine, 'infcx, 'tcx> LatticeDir<'infcx, 'tcx> for Glb<'combine, 'infcx,
&self.fields.trace.cause
}
- fn add_obligations(&mut self, obligations: Vec<PredicateObligation<'tcx>>) {
- self.fields.obligations.extend(obligations)
- }
-
fn relate_bound(&mut self, v: Ty<'tcx>, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, ()> {
let mut sub = self.fields.sub(self.a_is_expected);
sub.relate(v, a)?;
@@ -151,8 +147,12 @@ impl<'combine, 'infcx, 'tcx> LatticeDir<'infcx, 'tcx> for Glb<'combine, 'infcx,
}
}
-impl<'tcx> ConstEquateRelation<'tcx> for Glb<'_, '_, 'tcx> {
- fn const_equate_obligation(&mut self, a: ty::Const<'tcx>, b: ty::Const<'tcx>) {
- self.fields.add_const_equate_obligation(self.a_is_expected, a, b);
+impl<'tcx> ObligationEmittingRelation<'tcx> for Glb<'_, '_, 'tcx> {
+ fn register_predicates(&mut self, obligations: impl IntoIterator<Item: ty::ToPredicate<'tcx>>) {
+ self.fields.register_predicates(obligations);
+ }
+
+ fn register_obligations(&mut self, obligations: PredicateObligations<'tcx>) {
+ self.fields.register_obligations(obligations);
}
}
diff --git a/compiler/rustc_infer/src/infer/higher_ranked/mod.rs b/compiler/rustc_infer/src/infer/higher_ranked/mod.rs
index 817ae10c7..d1897cf24 100644
--- a/compiler/rustc_infer/src/infer/higher_ranked/mod.rs
+++ b/compiler/rustc_infer/src/infer/higher_ranked/mod.rs
@@ -6,7 +6,7 @@ use super::{HigherRankedType, InferCtxt};
use crate::infer::CombinedSnapshot;
use rustc_middle::ty::fold::FnMutDelegate;
use rustc_middle::ty::relate::{Relate, RelateResult, TypeRelation};
-use rustc_middle::ty::{self, Binder, TypeFoldable};
+use rustc_middle::ty::{self, Binder, TyCtxt, TypeFoldable};
impl<'a, 'tcx> CombineFields<'a, 'tcx> {
/// Checks whether `for<..> sub <: for<..> sup` holds.
@@ -38,13 +38,13 @@ impl<'a, 'tcx> CombineFields<'a, 'tcx> {
// First, we instantiate each bound region in the supertype with a
// fresh placeholder region. Note that this automatically creates
// a new universe if needed.
- let sup_prime = self.infcx.replace_bound_vars_with_placeholders(sup);
+ let sup_prime = self.infcx.instantiate_binder_with_placeholders(sup);
// Next, we instantiate each bound region in the subtype
// with a fresh region variable. These region variables --
// but no other pre-existing region variables -- can name
// the placeholders.
- let sub_prime = self.infcx.replace_bound_vars_with_fresh_vars(span, HigherRankedType, sub);
+ let sub_prime = self.infcx.instantiate_binder_with_fresh_vars(span, HigherRankedType, sub);
debug!("a_prime={:?}", sub_prime);
debug!("b_prime={:?}", sup_prime);
@@ -70,9 +70,9 @@ impl<'tcx> InferCtxt<'tcx> {
///
/// [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/traits/hrtb.html
#[instrument(level = "debug", skip(self), ret)]
- pub fn replace_bound_vars_with_placeholders<T>(&self, binder: ty::Binder<'tcx, T>) -> T
+ pub fn instantiate_binder_with_placeholders<T>(&self, binder: ty::Binder<'tcx, T>) -> T
where
- T: TypeFoldable<'tcx> + Copy,
+ T: TypeFoldable<TyCtxt<'tcx>> + Copy,
{
if let Some(inner) = binder.no_bound_vars() {
return inner;
@@ -82,16 +82,16 @@ impl<'tcx> InferCtxt<'tcx> {
let delegate = FnMutDelegate {
regions: &mut |br: ty::BoundRegion| {
- self.tcx.mk_region(ty::RePlaceholder(ty::PlaceholderRegion {
+ self.tcx.mk_re_placeholder(ty::PlaceholderRegion {
universe: next_universe,
name: br.kind,
- }))
+ })
},
types: &mut |bound_ty: ty::BoundTy| {
- self.tcx.mk_ty(ty::Placeholder(ty::PlaceholderType {
+ self.tcx.mk_placeholder(ty::PlaceholderType {
universe: next_universe,
- name: bound_ty.var,
- }))
+ name: bound_ty.kind,
+ })
},
consts: &mut |bound_var: ty::BoundVar, ty| {
self.tcx
diff --git a/compiler/rustc_infer/src/infer/lattice.rs b/compiler/rustc_infer/src/infer/lattice.rs
index 4dbb4b4d7..f377ac1d1 100644
--- a/compiler/rustc_infer/src/infer/lattice.rs
+++ b/compiler/rustc_infer/src/infer/lattice.rs
@@ -17,11 +17,12 @@
//!
//! [lattices]: https://en.wikipedia.org/wiki/Lattice_(order)
+use super::combine::ObligationEmittingRelation;
use super::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
use super::InferCtxt;
-use crate::traits::{ObligationCause, PredicateObligation};
-use rustc_middle::ty::relate::{RelateResult, TypeRelation};
+use crate::traits::ObligationCause;
+use rustc_middle::ty::relate::RelateResult;
use rustc_middle::ty::TyVar;
use rustc_middle::ty::{self, Ty};
@@ -30,13 +31,11 @@ use rustc_middle::ty::{self, Ty};
///
/// GLB moves "down" the lattice (to smaller values); LUB moves
/// "up" the lattice (to bigger values).
-pub trait LatticeDir<'f, 'tcx>: TypeRelation<'tcx> {
+pub trait LatticeDir<'f, 'tcx>: ObligationEmittingRelation<'tcx> {
fn infcx(&self) -> &'f InferCtxt<'tcx>;
fn cause(&self) -> &ObligationCause<'tcx>;
- fn add_obligations(&mut self, obligations: Vec<PredicateObligation<'tcx>>);
-
fn define_opaque_types(&self) -> bool;
// Relates the type `v` to `a` and `b` such that `v` represents
@@ -113,7 +112,7 @@ where
| (_, &ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }))
if this.define_opaque_types() && def_id.is_local() =>
{
- this.add_obligations(
+ this.register_obligations(
infcx
.handle_opaque_type(a, b, this.a_is_expected(), this.cause(), this.param_env())?
.obligations,
diff --git a/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs b/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs
index ce8aec804..2c4803550 100644
--- a/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs
+++ b/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs
@@ -17,7 +17,7 @@ use rustc_index::vec::{Idx, IndexVec};
use rustc_middle::ty::fold::TypeFoldable;
use rustc_middle::ty::PlaceholderRegion;
use rustc_middle::ty::{self, Ty, TyCtxt};
-use rustc_middle::ty::{ReEarlyBound, ReErased, ReFree, ReStatic};
+use rustc_middle::ty::{ReEarlyBound, ReErased, ReError, ReFree, ReStatic};
use rustc_middle::ty::{ReLateBound, RePlaceholder, ReVar};
use rustc_middle::ty::{Region, RegionVid};
use rustc_span::Span;
@@ -70,7 +70,7 @@ pub enum RegionResolutionError<'tcx> {
/// `o` requires that `a <= b`, but this does not hold
ConcreteFailure(SubregionOrigin<'tcx>, Region<'tcx>, Region<'tcx>),
- /// `GenericBoundFailure(p, s, a)
+ /// `GenericBoundFailure(p, s, a)`:
///
/// The parameter/associated-type `p` must be known to outlive the lifetime
/// `a` (but none of the known bounds are sufficient).
@@ -216,6 +216,8 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
Ok(self.tcx().lifetimes.re_static)
}
+ ReError(_) => Ok(a_region),
+
ReEarlyBound(_) | ReFree(_) => {
// All empty regions are less than early-bound, free,
// and scope regions.
@@ -380,7 +382,7 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
// name the placeholder, then the placeholder is
// larger; otherwise, the only ancestor is `'static`.
Err(placeholder) if empty_ui.can_name(placeholder.universe) => {
- self.tcx().mk_region(RePlaceholder(placeholder))
+ self.tcx().mk_re_placeholder(placeholder)
}
Err(_) => self.tcx().lifetimes.re_static,
};
@@ -436,6 +438,10 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
}
(VarValue::Value(a), VarValue::Empty(_)) => {
match *a {
+ // this is always on an error path,
+ // so it doesn't really matter if it's shorter or longer than an empty region
+ ReError(_) => false,
+
ReLateBound(..) | ReErased => {
bug!("cannot relate region: {:?}", a);
}
@@ -465,6 +471,10 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
}
(VarValue::Empty(a_ui), VarValue::Value(b)) => {
match *b {
+ // this is always on an error path,
+ // so it doesn't really matter if it's shorter or longer than an empty region
+ ReError(_) => false,
+
ReLateBound(..) | ReErased => {
bug!("cannot relate region: {:?}", b);
}
@@ -546,6 +556,10 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
);
}
+ (ReError(_), _) => a,
+
+ (_, ReError(_)) => b,
+
(ReStatic, _) | (_, ReStatic) => {
// nothing lives longer than `'static`
self.tcx().lifetimes.re_static
@@ -1018,7 +1032,7 @@ impl<'tcx> fmt::Debug for RegionAndOrigin<'tcx> {
impl<'tcx> LexicalRegionResolutions<'tcx> {
fn normalize<T>(&self, tcx: TyCtxt<'tcx>, value: T) -> T
where
- T: TypeFoldable<'tcx>,
+ T: TypeFoldable<TyCtxt<'tcx>>,
{
tcx.fold_regions(value, |r, _db| self.resolve_region(tcx, r))
}
diff --git a/compiler/rustc_infer/src/infer/lub.rs b/compiler/rustc_infer/src/infer/lub.rs
index c07ac1d3a..c871ccb21 100644
--- a/compiler/rustc_infer/src/infer/lub.rs
+++ b/compiler/rustc_infer/src/infer/lub.rs
@@ -1,14 +1,13 @@
//! Least upper bound. See [`lattice`].
-use super::combine::CombineFields;
+use super::combine::{CombineFields, ObligationEmittingRelation};
use super::lattice::{self, LatticeDir};
use super::InferCtxt;
use super::Subtype;
-use crate::infer::combine::ConstEquateRelation;
-use crate::traits::{ObligationCause, PredicateObligation};
+use crate::traits::{ObligationCause, PredicateObligations};
use rustc_middle::ty::relate::{Relate, RelateResult, TypeRelation};
-use rustc_middle::ty::{self, Ty, TyCtxt};
+use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt};
/// "Least upper bound" (common supertype)
pub struct Lub<'combine, 'infcx, 'tcx> {
@@ -79,7 +78,8 @@ impl<'tcx> TypeRelation<'tcx> for Lub<'_, '_, 'tcx> {
debug!("{}.regions({:?}, {:?})", self.tag(), a, b);
let origin = Subtype(Box::new(self.fields.trace.clone()));
- Ok(self.fields.infcx.inner.borrow_mut().unwrap_region_constraints().lub_regions(
+ // LUB(&'static u8, &'a u8) == &RegionGLB('static, 'a) u8 == &'a u8
+ Ok(self.fields.infcx.inner.borrow_mut().unwrap_region_constraints().glb_regions(
self.tcx(),
origin,
a,
@@ -126,12 +126,6 @@ impl<'tcx> TypeRelation<'tcx> for Lub<'_, '_, 'tcx> {
}
}
-impl<'tcx> ConstEquateRelation<'tcx> for Lub<'_, '_, 'tcx> {
- fn const_equate_obligation(&mut self, a: ty::Const<'tcx>, b: ty::Const<'tcx>) {
- self.fields.add_const_equate_obligation(self.a_is_expected, a, b);
- }
-}
-
impl<'combine, 'infcx, 'tcx> LatticeDir<'infcx, 'tcx> for Lub<'combine, 'infcx, 'tcx> {
fn infcx(&self) -> &'infcx InferCtxt<'tcx> {
self.fields.infcx
@@ -141,10 +135,6 @@ impl<'combine, 'infcx, 'tcx> LatticeDir<'infcx, 'tcx> for Lub<'combine, 'infcx,
&self.fields.trace.cause
}
- fn add_obligations(&mut self, obligations: Vec<PredicateObligation<'tcx>>) {
- self.fields.obligations.extend(obligations)
- }
-
fn relate_bound(&mut self, v: Ty<'tcx>, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, ()> {
let mut sub = self.fields.sub(self.a_is_expected);
sub.relate(a, v)?;
@@ -156,3 +146,13 @@ impl<'combine, 'infcx, 'tcx> LatticeDir<'infcx, 'tcx> for Lub<'combine, 'infcx,
self.fields.define_opaque_types
}
}
+
+impl<'tcx> ObligationEmittingRelation<'tcx> for Lub<'_, '_, 'tcx> {
+ fn register_predicates(&mut self, obligations: impl IntoIterator<Item: ty::ToPredicate<'tcx>>) {
+ self.fields.register_predicates(obligations);
+ }
+
+ fn register_obligations(&mut self, obligations: PredicateObligations<'tcx>) {
+ self.fields.register_obligations(obligations)
+ }
+}
diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs
index f0e42c1fc..bd1f96635 100644
--- a/compiler/rustc_infer/src/infer/mod.rs
+++ b/compiler/rustc_infer/src/infer/mod.rs
@@ -4,6 +4,7 @@ pub use self::LateBoundRegionConversionTime::*;
pub use self::RegionVariableOrigin::*;
pub use self::SubregionOrigin::*;
pub use self::ValuePairs::*;
+pub use combine::ObligationEmittingRelation;
use self::opaque_types::OpaqueTypeStorage;
pub(crate) use self::undo_log::{InferCtxtUndoLogs, Snapshot, UndoLog};
@@ -28,9 +29,9 @@ use rustc_middle::ty::fold::BoundVarReplacerDelegate;
use rustc_middle::ty::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable};
use rustc_middle::ty::relate::RelateResult;
use rustc_middle::ty::subst::{GenericArg, GenericArgKind, InternalSubsts, SubstsRef};
-use rustc_middle::ty::visit::TypeVisitable;
+use rustc_middle::ty::visit::{TypeVisitable, TypeVisitableExt};
pub use rustc_middle::ty::IntVarValue;
-use rustc_middle::ty::{self, GenericParamDefKind, InferConst, Ty, TyCtxt};
+use rustc_middle::ty::{self, GenericParamDefKind, InferConst, InferTy, Ty, TyCtxt};
use rustc_middle::ty::{ConstVid, FloatVid, IntVid, TyVid};
use rustc_span::symbol::Symbol;
use rustc_span::Span;
@@ -155,7 +156,7 @@ pub struct InferCtxtInner<'tcx> {
undo_log: InferCtxtUndoLogs<'tcx>,
/// Caches for opaque type inference.
- pub opaque_type_storage: OpaqueTypeStorage<'tcx>,
+ opaque_type_storage: OpaqueTypeStorage<'tcx>,
}
impl<'tcx> InferCtxtInner<'tcx> {
@@ -194,41 +195,17 @@ impl<'tcx> InferCtxtInner<'tcx> {
}
#[inline]
- fn int_unification_table(
- &mut self,
- ) -> ut::UnificationTable<
- ut::InPlace<
- ty::IntVid,
- &mut ut::UnificationStorage<ty::IntVid>,
- &mut InferCtxtUndoLogs<'tcx>,
- >,
- > {
+ fn int_unification_table(&mut self) -> UnificationTable<'_, 'tcx, ty::IntVid> {
self.int_unification_storage.with_log(&mut self.undo_log)
}
#[inline]
- fn float_unification_table(
- &mut self,
- ) -> ut::UnificationTable<
- ut::InPlace<
- ty::FloatVid,
- &mut ut::UnificationStorage<ty::FloatVid>,
- &mut InferCtxtUndoLogs<'tcx>,
- >,
- > {
+ fn float_unification_table(&mut self) -> UnificationTable<'_, 'tcx, ty::FloatVid> {
self.float_unification_storage.with_log(&mut self.undo_log)
}
#[inline]
- fn const_unification_table(
- &mut self,
- ) -> ut::UnificationTable<
- ut::InPlace<
- ty::ConstVid<'tcx>,
- &mut ut::UnificationStorage<ty::ConstVid<'tcx>>,
- &mut InferCtxtUndoLogs<'tcx>,
- >,
- > {
+ fn const_unification_table(&mut self) -> UnificationTable<'_, 'tcx, ty::ConstVid<'tcx>> {
self.const_unification_storage.with_log(&mut self.undo_log)
}
@@ -263,7 +240,7 @@ pub struct InferCtxt<'tcx> {
/// short lived InferCtxt within queries. The opaque type obligations are forwarded
/// to the outside until the end up in an `InferCtxt` for typeck or borrowck.
///
- /// It is default value is `DefiningAnchor::Error`, this way it is easier to catch errors that
+ /// Its default value is `DefiningAnchor::Error`, this way it is easier to catch errors that
/// might come up during inference or typeck.
pub defining_use_anchor: DefiningAnchor,
@@ -616,7 +593,7 @@ impl<'tcx> InferCtxtBuilder<'tcx> {
canonical: &Canonical<'tcx, T>,
) -> (InferCtxt<'tcx>, T, CanonicalVarValues<'tcx>)
where
- T: TypeFoldable<'tcx>,
+ T: TypeFoldable<TyCtxt<'tcx>>,
{
let infcx = self.build();
let (value, subst) = infcx.instantiate_canonical_with_fresh_inference_vars(span, canonical);
@@ -696,7 +673,7 @@ impl<'tcx> InferCtxt<'tcx> {
self.in_snapshot.get()
}
- pub fn freshen<T: TypeFoldable<'tcx>>(&self, t: T) -> T {
+ pub fn freshen<T: TypeFoldable<TyCtxt<'tcx>>>(&self, t: T) -> T {
t.fold_with(&mut self.freshener())
}
@@ -879,30 +856,20 @@ impl<'tcx> InferCtxt<'tcx> {
self.inner.borrow_mut().unwrap_region_constraints().add_given(sub, sup);
}
- pub fn can_sub<T>(&self, param_env: ty::ParamEnv<'tcx>, a: T, b: T) -> UnitResult<'tcx>
+ pub fn can_sub<T>(&self, param_env: ty::ParamEnv<'tcx>, a: T, b: T) -> bool
where
T: at::ToTrace<'tcx>,
{
let origin = &ObligationCause::dummy();
- self.probe(|_| {
- self.at(origin, param_env).sub(a, b).map(|InferOk { obligations: _, .. }| {
- // Ignore obligations, since we are unrolling
- // everything anyway.
- })
- })
+ self.probe(|_| self.at(origin, param_env).sub(a, b).is_ok())
}
- pub fn can_eq<T>(&self, param_env: ty::ParamEnv<'tcx>, a: T, b: T) -> UnitResult<'tcx>
+ pub fn can_eq<T>(&self, param_env: ty::ParamEnv<'tcx>, a: T, b: T) -> bool
where
T: at::ToTrace<'tcx>,
{
let origin = &ObligationCause::dummy();
- self.probe(|_| {
- self.at(origin, param_env).eq(a, b).map(|InferOk { obligations: _, .. }| {
- // Ignore obligations, since we are unrolling
- // everything anyway.
- })
- })
+ self.probe(|_| self.at(origin, param_env).eq(a, b).is_ok())
}
#[instrument(skip(self), level = "debug")]
@@ -995,7 +962,7 @@ impl<'tcx> InferCtxt<'tcx> {
Ok(self.commit_if_ok(|_snapshot| {
let ty::SubtypePredicate { a_is_expected, a, b } =
- self.replace_bound_vars_with_placeholders(predicate);
+ self.instantiate_binder_with_placeholders(predicate);
let ok = self.at(cause, param_env).sub_exp(a_is_expected, a, b)?;
@@ -1008,7 +975,7 @@ impl<'tcx> InferCtxt<'tcx> {
cause: &traits::ObligationCause<'tcx>,
predicate: ty::PolyRegionOutlivesPredicate<'tcx>,
) {
- let ty::OutlivesPredicate(r_a, r_b) = self.replace_bound_vars_with_placeholders(predicate);
+ let ty::OutlivesPredicate(r_a, r_b) = self.instantiate_binder_with_placeholders(predicate);
let origin =
SubregionOrigin::from_obligation_cause(cause, || RelateRegionParamBound(cause.span));
self.sub_regions(origin, r_b, r_a); // `b : a` ==> `a <= b`
@@ -1102,7 +1069,7 @@ impl<'tcx> InferCtxt<'tcx> {
) -> ty::Region<'tcx> {
let region_var =
self.inner.borrow_mut().unwrap_region_constraints().new_region_var(universe, origin);
- self.tcx.mk_region(ty::ReVar(region_var))
+ self.tcx.mk_re_var(region_var)
}
/// Return the universe that the region `r` was created in. For
@@ -1120,11 +1087,13 @@ impl<'tcx> InferCtxt<'tcx> {
}
/// Just a convenient wrapper of `next_region_var` for using during NLL.
+ #[instrument(skip(self), level = "debug")]
pub fn next_nll_region_var(&self, origin: NllRegionVariableOrigin) -> ty::Region<'tcx> {
self.next_region_var(RegionVariableOrigin::Nll(origin))
}
/// Just a convenient wrapper of `next_region_var` for using during NLL.
+ #[instrument(skip(self), level = "debug")]
pub fn next_nll_region_var_in_universe(
&self,
origin: NllRegionVariableOrigin,
@@ -1175,7 +1144,15 @@ impl<'tcx> InferCtxt<'tcx> {
origin,
val: ConstVariableValue::Unknown { universe: self.universe() },
});
- self.tcx.mk_const(const_var_id, self.tcx.type_of(param.def_id)).into()
+ self.tcx
+ .mk_const(
+ const_var_id,
+ self.tcx
+ .type_of(param.def_id)
+ .no_bound_vars()
+ .expect("const parameter types cannot be generic"),
+ )
+ .into()
}
}
}
@@ -1370,7 +1347,7 @@ impl<'tcx> InferCtxt<'tcx> {
/// will be resolving them as well, e.g. in a loop).
pub fn shallow_resolve<T>(&self, value: T) -> T
where
- T: TypeFoldable<'tcx>,
+ T: TypeFoldable<TyCtxt<'tcx>>,
{
value.fold_with(&mut ShallowResolver { infcx: self })
}
@@ -1387,10 +1364,10 @@ impl<'tcx> InferCtxt<'tcx> {
/// at will.
pub fn resolve_vars_if_possible<T>(&self, value: T) -> T
where
- T: TypeFoldable<'tcx>,
+ T: TypeFoldable<TyCtxt<'tcx>>,
{
- if !value.needs_infer() {
- return value; // Avoid duplicated subst-folding.
+ if !value.has_non_region_infer() {
+ return value;
}
let mut r = resolve::OpportunisticVarResolver::new(self);
value.fold_with(&mut r)
@@ -1398,7 +1375,7 @@ impl<'tcx> InferCtxt<'tcx> {
pub fn resolve_numeric_literals_with_default<T>(&self, value: T) -> T
where
- T: TypeFoldable<'tcx>,
+ T: TypeFoldable<TyCtxt<'tcx>>,
{
if !value.needs_infer() {
return value; // Avoid duplicated subst-folding.
@@ -1413,7 +1390,7 @@ impl<'tcx> InferCtxt<'tcx> {
value: &T,
) -> Option<(ty::Term<'tcx>, Option<Span>)>
where
- T: TypeVisitable<'tcx>,
+ T: TypeVisitable<TyCtxt<'tcx>>,
{
value.visit_with(&mut resolve::UnresolvedTypeOrConstFinder::new(self)).break_value()
}
@@ -1428,17 +1405,14 @@ impl<'tcx> InferCtxt<'tcx> {
}
}
- pub fn fully_resolve<T: TypeFoldable<'tcx>>(&self, value: T) -> FixupResult<'tcx, T> {
- /*!
- * Attempts to resolve all type/region/const variables in
- * `value`. Region inference must have been run already (e.g.,
- * by calling `resolve_regions_and_report_errors`). If some
- * variable was never unified, an `Err` results.
- *
- * This method is idempotent, but it not typically not invoked
- * except during the writeback phase.
- */
-
+ /// Attempts to resolve all type/region/const variables in
+ /// `value`. Region inference must have been run already (e.g.,
+ /// by calling `resolve_regions_and_report_errors`). If some
+ /// variable was never unified, an `Err` results.
+ ///
+ /// This method is idempotent, but it not typically not invoked
+ /// except during the writeback phase.
+ pub fn fully_resolve<T: TypeFoldable<TyCtxt<'tcx>>>(&self, value: T) -> FixupResult<'tcx, T> {
let value = resolve::fully_resolve(self, value);
assert!(
value.as_ref().map_or(true, |value| !value.needs_infer()),
@@ -1447,14 +1421,21 @@ impl<'tcx> InferCtxt<'tcx> {
value
}
- pub fn replace_bound_vars_with_fresh_vars<T>(
+ // Instantiates the bound variables in a given binder with fresh inference
+ // variables in the current universe.
+ //
+ // Use this method if you'd like to find some substitution of the binder's
+ // variables (e.g. during a method call). If there isn't a [`LateBoundRegionConversionTime`]
+ // that corresponds to your use case, consider whether or not you should
+ // use [`InferCtxt::instantiate_binder_with_placeholders`] instead.
+ pub fn instantiate_binder_with_fresh_vars<T>(
&self,
span: Span,
lbrct: LateBoundRegionConversionTime,
value: ty::Binder<'tcx, T>,
) -> T
where
- T: TypeFoldable<'tcx> + Copy,
+ T: TypeFoldable<TyCtxt<'tcx>> + Copy,
{
if let Some(inner) = value.no_bound_vars() {
return inner;
@@ -1746,7 +1727,6 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
// in this case. The typechecker should only ever report type errors involving mismatched
// types using one of these methods, and should not call span_err directly for such
// errors.
-
pub fn type_error_struct_with_diag<M>(
&self,
sp: Span,
@@ -1844,8 +1824,8 @@ struct InferenceLiteralEraser<'tcx> {
tcx: TyCtxt<'tcx>,
}
-impl<'tcx> TypeFolder<'tcx> for InferenceLiteralEraser<'tcx> {
- fn tcx(&self) -> TyCtxt<'tcx> {
+impl<'tcx> TypeFolder<TyCtxt<'tcx>> for InferenceLiteralEraser<'tcx> {
+ fn interner(&self) -> TyCtxt<'tcx> {
self.tcx
}
@@ -1862,17 +1842,41 @@ struct ShallowResolver<'a, 'tcx> {
infcx: &'a InferCtxt<'tcx>,
}
-impl<'a, 'tcx> TypeFolder<'tcx> for ShallowResolver<'a, 'tcx> {
- fn tcx<'b>(&'b self) -> TyCtxt<'tcx> {
+impl<'a, 'tcx> TypeFolder<TyCtxt<'tcx>> for ShallowResolver<'a, 'tcx> {
+ fn interner(&self) -> TyCtxt<'tcx> {
self.infcx.tcx
}
/// If `ty` is a type variable of some kind, resolve it one level
/// (but do not resolve types found in the result). If `typ` is
/// not a type variable, just return it unmodified.
+ #[inline]
fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
- match *ty.kind() {
- ty::Infer(ty::TyVar(v)) => {
+ if let ty::Infer(v) = ty.kind() { self.fold_infer_ty(*v).unwrap_or(ty) } else { ty }
+ }
+
+ fn fold_const(&mut self, ct: ty::Const<'tcx>) -> ty::Const<'tcx> {
+ if let ty::ConstKind::Infer(InferConst::Var(vid)) = ct.kind() {
+ self.infcx
+ .inner
+ .borrow_mut()
+ .const_unification_table()
+ .probe_value(vid)
+ .val
+ .known()
+ .unwrap_or(ct)
+ } else {
+ ct
+ }
+ }
+}
+
+impl<'a, 'tcx> ShallowResolver<'a, 'tcx> {
+ // This is separate from `fold_ty` to keep that method small and inlinable.
+ #[inline(never)]
+ fn fold_infer_ty(&mut self, v: InferTy) -> Option<Ty<'tcx>> {
+ match v {
+ ty::TyVar(v) => {
// Not entirely obvious: if `typ` is a type variable,
// it can be resolved to an int/float variable, which
// can then be recursively resolved, hence the
@@ -1886,41 +1890,26 @@ impl<'a, 'tcx> TypeFolder<'tcx> for ShallowResolver<'a, 'tcx> {
// Note: if these two lines are combined into one we get
// dynamic borrow errors on `self.inner`.
let known = self.infcx.inner.borrow_mut().type_variables().probe(v).known();
- known.map_or(ty, |t| self.fold_ty(t))
+ known.map(|t| self.fold_ty(t))
}
- ty::Infer(ty::IntVar(v)) => self
+ ty::IntVar(v) => self
.infcx
.inner
.borrow_mut()
.int_unification_table()
.probe_value(v)
- .map_or(ty, |v| v.to_type(self.infcx.tcx)),
+ .map(|v| v.to_type(self.infcx.tcx)),
- ty::Infer(ty::FloatVar(v)) => self
+ ty::FloatVar(v) => self
.infcx
.inner
.borrow_mut()
.float_unification_table()
.probe_value(v)
- .map_or(ty, |v| v.to_type(self.infcx.tcx)),
-
- _ => ty,
- }
- }
+ .map(|v| v.to_type(self.infcx.tcx)),
- fn fold_const(&mut self, ct: ty::Const<'tcx>) -> ty::Const<'tcx> {
- if let ty::ConstKind::Infer(InferConst::Var(vid)) = ct.kind() {
- self.infcx
- .inner
- .borrow_mut()
- .const_unification_table()
- .probe_value(vid)
- .val
- .known()
- .unwrap_or(ct)
- } else {
- ct
+ ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_) => None,
}
}
}
@@ -2044,24 +2033,24 @@ fn replace_param_and_infer_substs_with_placeholder<'tcx>(
) -> SubstsRef<'tcx> {
struct ReplaceParamAndInferWithPlaceholder<'tcx> {
tcx: TyCtxt<'tcx>,
- idx: usize,
+ idx: u32,
}
- impl<'tcx> TypeFolder<'tcx> for ReplaceParamAndInferWithPlaceholder<'tcx> {
- fn tcx(&self) -> TyCtxt<'tcx> {
+ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for ReplaceParamAndInferWithPlaceholder<'tcx> {
+ fn interner(&self) -> TyCtxt<'tcx> {
self.tcx
}
fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
if let ty::Infer(_) = t.kind() {
- self.tcx.mk_ty(ty::Placeholder(ty::PlaceholderType {
+ self.tcx.mk_placeholder(ty::PlaceholderType {
universe: ty::UniverseIndex::ROOT,
- name: ty::BoundVar::from_usize({
+ name: ty::BoundTyKind::Anon({
let idx = self.idx;
self.idx += 1;
idx
}),
- }))
+ })
} else {
t.super_fold_with(self)
}
@@ -2077,7 +2066,7 @@ fn replace_param_and_infer_substs_with_placeholder<'tcx>(
self.tcx.mk_const(
ty::PlaceholderConst {
universe: ty::UniverseIndex::ROOT,
- name: ty::BoundVar::from_usize({
+ name: ty::BoundVar::from_u32({
let idx = self.idx;
self.idx += 1;
idx
diff --git a/compiler/rustc_infer/src/infer/nll_relate/mod.rs b/compiler/rustc_infer/src/infer/nll_relate/mod.rs
index f235cb5ab..573cd91a2 100644
--- a/compiler/rustc_infer/src/infer/nll_relate/mod.rs
+++ b/compiler/rustc_infer/src/infer/nll_relate/mod.rs
@@ -21,26 +21,21 @@
//! thing we relate in chalk are basically domain goals and their
//! constituents)
-use crate::infer::combine::ConstEquateRelation;
use crate::infer::InferCtxt;
use crate::infer::{ConstVarValue, ConstVariableValue};
use crate::infer::{TypeVariableOrigin, TypeVariableOriginKind};
-use crate::traits::{Obligation, PredicateObligation};
+use crate::traits::{Obligation, PredicateObligations};
use rustc_data_structures::fx::FxHashMap;
use rustc_middle::traits::ObligationCause;
use rustc_middle::ty::error::TypeError;
use rustc_middle::ty::relate::{self, Relate, RelateResult, TypeRelation};
-use rustc_middle::ty::visit::{TypeSuperVisitable, TypeVisitable, TypeVisitor};
+use rustc_middle::ty::visit::{TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor};
use rustc_middle::ty::{self, InferConst, Ty, TyCtxt};
-use rustc_span::Span;
+use rustc_span::{Span, Symbol};
use std::fmt::Debug;
use std::ops::ControlFlow;
-#[derive(PartialEq)]
-pub enum NormalizationStrategy {
- Lazy,
- Eager,
-}
+use super::combine::ObligationEmittingRelation;
pub struct TypeRelating<'me, 'tcx, D>
where
@@ -55,7 +50,7 @@ where
///
/// - Covariant means `a <: b`.
/// - Contravariant means `b <: a`.
- /// - Invariant means `a == b.
+ /// - Invariant means `a == b`.
/// - Bivariant means that it doesn't matter.
ambient_variance: ty::Variance,
@@ -92,7 +87,7 @@ pub trait TypeRelatingDelegate<'tcx> {
info: ty::VarianceDiagInfo<'tcx>,
);
- fn register_obligations(&mut self, obligations: Vec<PredicateObligation<'tcx>>);
+ fn register_obligations(&mut self, obligations: PredicateObligations<'tcx>);
/// Creates a new universe index. Used when instantiating placeholders.
fn create_next_universe(&mut self) -> ty::UniverseIndex;
@@ -105,7 +100,11 @@ pub trait TypeRelatingDelegate<'tcx> {
/// we will invoke this method to instantiate `'a` with an
/// inference variable (though `'b` would be instantiated first,
/// as a placeholder).
- fn next_existential_region_var(&mut self, was_placeholder: bool) -> ty::Region<'tcx>;
+ fn next_existential_region_var(
+ &mut self,
+ was_placeholder: bool,
+ name: Option<Symbol>,
+ ) -> ty::Region<'tcx>;
/// Creates a new region variable representing a
/// higher-ranked region that is instantiated universally.
@@ -125,9 +124,6 @@ pub trait TypeRelatingDelegate<'tcx> {
/// relation stating that `'?0: 'a`).
fn generalize_existential(&mut self, universe: ty::UniverseIndex) -> ty::Region<'tcx>;
- /// Define the normalization strategy to use, eager or lazy.
- fn normalization() -> NormalizationStrategy;
-
/// Enables some optimizations if we do not expect inference variables
/// in the RHS of the relation.
fn forbid_inference_vars() -> bool;
@@ -196,7 +192,7 @@ where
let placeholder = ty::PlaceholderRegion { universe, name: br.kind };
delegate.next_placeholder_region(placeholder)
} else {
- delegate.next_existential_region_var(true)
+ delegate.next_existential_region_var(true, br.kind.get_name())
}
}
};
@@ -265,38 +261,6 @@ where
self.delegate.push_outlives(sup, sub, info);
}
- /// Relate a projection type and some value type lazily. This will always
- /// succeed, but we push an additional `ProjectionEq` goal depending
- /// on the value type:
- /// - if the value type is any type `T` which is not a projection, we push
- /// `ProjectionEq(projection = T)`.
- /// - if the value type is another projection `other_projection`, we create
- /// a new inference variable `?U` and push the two goals
- /// `ProjectionEq(projection = ?U)`, `ProjectionEq(other_projection = ?U)`.
- fn relate_projection_ty(
- &mut self,
- projection_ty: ty::AliasTy<'tcx>,
- value_ty: Ty<'tcx>,
- ) -> Ty<'tcx> {
- use rustc_span::DUMMY_SP;
-
- match *value_ty.kind() {
- ty::Alias(ty::Projection, other_projection_ty) => {
- let var = self.infcx.next_ty_var(TypeVariableOrigin {
- kind: TypeVariableOriginKind::MiscVariable,
- span: DUMMY_SP,
- });
- // FIXME(lazy-normalization): This will always ICE, because the recursive
- // call will end up in the _ arm below.
- self.relate_projection_ty(projection_ty, var);
- self.relate_projection_ty(other_projection_ty, var);
- var
- }
-
- _ => bug!("should never be invoked with eager normalization"),
- }
- }
-
/// Relate a type inference variable with a value type. This works
/// by creating a "generalization" G of the value where all the
/// lifetimes are replaced with fresh inference values. This
@@ -335,12 +299,6 @@ where
return Ok(value_ty);
}
- ty::Alias(ty::Projection, projection_ty)
- if D::normalization() == NormalizationStrategy::Lazy =>
- {
- return Ok(self.relate_projection_ty(projection_ty, self.infcx.tcx.mk_ty_var(vid)));
- }
-
_ => (),
}
@@ -627,18 +585,6 @@ where
self.relate_opaques(a, b)
}
- (&ty::Alias(ty::Projection, projection_ty), _)
- if D::normalization() == NormalizationStrategy::Lazy =>
- {
- Ok(self.relate_projection_ty(projection_ty, b))
- }
-
- (_, &ty::Alias(ty::Projection, projection_ty))
- if D::normalization() == NormalizationStrategy::Lazy =>
- {
- Ok(self.relate_projection_ty(projection_ty, a))
- }
-
_ => {
debug!(?a, ?b, ?self.ambient_variance);
@@ -663,13 +609,13 @@ where
debug!(?v_b);
if self.ambient_covariance() {
- // Covariance: a <= b. Hence, `b: a`.
- self.push_outlives(v_b, v_a, self.ambient_variance_info);
+ // Covariant: &'a u8 <: &'b u8. Hence, `'a: 'b`.
+ self.push_outlives(v_a, v_b, 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);
+ // Contravariant: &'b u8 <: &'a u8. Hence, `'b: 'a`.
+ self.push_outlives(v_b, v_a, self.ambient_variance_info);
}
Ok(a)
@@ -813,16 +759,23 @@ where
}
}
-impl<'tcx, D> ConstEquateRelation<'tcx> for TypeRelating<'_, 'tcx, D>
+impl<'tcx, D> ObligationEmittingRelation<'tcx> for TypeRelating<'_, 'tcx, D>
where
D: TypeRelatingDelegate<'tcx>,
{
- fn const_equate_obligation(&mut self, _a: ty::Const<'tcx>, _b: ty::Const<'tcx>) {
- // We don't have to worry about the equality of consts during borrow checking
- // as consts always have a static lifetime.
- // FIXME(oli-obk): is this really true? We can at least have HKL and with
- // inline consts we may have further lifetimes that may be unsound to treat as
- // 'static.
+ fn register_predicates(&mut self, obligations: impl IntoIterator<Item: ty::ToPredicate<'tcx>>) {
+ self.delegate.register_obligations(
+ obligations
+ .into_iter()
+ .map(|to_pred| {
+ Obligation::new(self.tcx(), ObligationCause::dummy(), self.param_env(), to_pred)
+ })
+ .collect(),
+ );
+ }
+
+ fn register_obligations(&mut self, obligations: PredicateObligations<'tcx>) {
+ self.delegate.register_obligations(obligations);
}
}
@@ -840,8 +793,8 @@ struct ScopeInstantiator<'me, 'tcx> {
bound_region_scope: &'me mut BoundRegionScope<'tcx>,
}
-impl<'me, 'tcx> TypeVisitor<'tcx> for ScopeInstantiator<'me, 'tcx> {
- fn visit_binder<T: TypeVisitable<'tcx>>(
+impl<'me, 'tcx> TypeVisitor<TyCtxt<'tcx>> for ScopeInstantiator<'me, 'tcx> {
+ fn visit_binder<T: TypeVisitable<TyCtxt<'tcx>>>(
&mut self,
t: &ty::Binder<'tcx, T>,
) -> ControlFlow<Self::BreakTy> {
diff --git a/compiler/rustc_infer/src/infer/opaque_types.rs b/compiler/rustc_infer/src/infer/opaque_types.rs
index c54c66eab..d5c824d4c 100644
--- a/compiler/rustc_infer/src/infer/opaque_types.rs
+++ b/compiler/rustc_infer/src/infer/opaque_types.rs
@@ -3,7 +3,7 @@ use crate::infer::{DefiningAnchor, InferCtxt, InferOk};
use crate::traits;
use hir::def::DefKind;
use hir::def_id::{DefId, LocalDefId};
-use hir::{HirId, OpaqueTyOrigin};
+use hir::OpaqueTyOrigin;
use rustc_data_structures::sync::Lrc;
use rustc_data_structures::vec_map::VecMap;
use rustc_hir as hir;
@@ -13,7 +13,7 @@ use rustc_middle::ty::fold::BottomUpFolder;
use rustc_middle::ty::GenericArgKind;
use rustc_middle::ty::{
self, OpaqueHiddenType, OpaqueTypeKey, Ty, TyCtxt, TypeFoldable, TypeSuperVisitable,
- TypeVisitable, TypeVisitor,
+ TypeVisitable, TypeVisitableExt, TypeVisitor,
};
use rustc_span::Span;
@@ -45,10 +45,10 @@ pub struct OpaqueTypeDecl<'tcx> {
impl<'tcx> InferCtxt<'tcx> {
/// This is a backwards compatibility hack to prevent breaking changes from
/// lazy TAIT around RPIT handling.
- pub fn replace_opaque_types_with_inference_vars<T: TypeFoldable<'tcx>>(
+ pub fn replace_opaque_types_with_inference_vars<T: TypeFoldable<TyCtxt<'tcx>>>(
&self,
value: T,
- body_id: HirId,
+ body_id: LocalDefId,
span: Span,
param_env: ty::ParamEnv<'tcx>,
) -> InferOk<'tcx, T> {
@@ -57,9 +57,7 @@ impl<'tcx> InferCtxt<'tcx> {
}
let mut obligations = vec![];
let replace_opaque_type = |def_id: DefId| {
- def_id
- .as_local()
- .map_or(false, |def_id| self.opaque_type_origin(def_id, span).is_some())
+ def_id.as_local().map_or(false, |def_id| self.opaque_type_origin(def_id).is_some())
};
let value = value.fold_with(&mut BottomUpFolder {
tcx: self.tcx,
@@ -144,9 +142,9 @@ impl<'tcx> InferCtxt<'tcx> {
// let x = || foo(); // returns the Opaque assoc with `foo`
// }
// ```
- self.opaque_type_origin(def_id, cause.span)?
+ self.opaque_type_origin(def_id)?
}
- DefiningAnchor::Bubble => self.opaque_ty_origin_unchecked(def_id, cause.span),
+ DefiningAnchor::Bubble => self.opaque_type_origin_unchecked(def_id),
DefiningAnchor::Error => return None,
};
if let ty::Alias(ty::Opaque, ty::AliasTy { def_id: b_def_id, .. }) = *b.kind() {
@@ -155,9 +153,8 @@ impl<'tcx> InferCtxt<'tcx> {
// no one encounters it in practice.
// It does occur however in `fn fut() -> impl Future<Output = i32> { async { 42 } }`,
// where it is of no concern, so we only check for TAITs.
- if let Some(OpaqueTyOrigin::TyAlias) = b_def_id
- .as_local()
- .and_then(|b_def_id| self.opaque_type_origin(b_def_id, cause.span))
+ if let Some(OpaqueTyOrigin::TyAlias) =
+ b_def_id.as_local().and_then(|b_def_id| self.opaque_type_origin(b_def_id))
{
self.tcx.sess.emit_err(OpaqueHiddenTypeDiag {
span: cause.span,
@@ -371,24 +368,18 @@ impl<'tcx> InferCtxt<'tcx> {
});
}
+ /// Returns the origin of the opaque type `def_id` if we're currently
+ /// in its defining scope.
#[instrument(skip(self), level = "trace", ret)]
- pub fn opaque_type_origin(&self, def_id: LocalDefId, span: Span) -> Option<OpaqueTyOrigin> {
+ pub fn opaque_type_origin(&self, def_id: LocalDefId) -> Option<OpaqueTyOrigin> {
let opaque_hir_id = self.tcx.hir().local_def_id_to_hir_id(def_id);
let parent_def_id = match self.defining_use_anchor {
DefiningAnchor::Bubble | DefiningAnchor::Error => return None,
DefiningAnchor::Bind(bind) => bind,
};
- let item_kind = &self.tcx.hir().expect_item(def_id).kind;
-
- let hir::ItemKind::OpaqueTy(hir::OpaqueTy { origin, .. }) = item_kind else {
- span_bug!(
- span,
- "weird opaque type: {:#?}, {:#?}",
- def_id,
- item_kind
- )
- };
- let in_definition_scope = match *origin {
+
+ let origin = self.opaque_type_origin_unchecked(def_id);
+ let in_definition_scope = match origin {
// Async `impl Trait`
hir::OpaqueTyOrigin::AsyncFn(parent) => parent == parent_def_id,
// Anonymous `impl Trait`
@@ -398,16 +389,17 @@ impl<'tcx> InferCtxt<'tcx> {
may_define_opaque_type(self.tcx, parent_def_id, opaque_hir_id)
}
};
- trace!(?origin);
- in_definition_scope.then_some(*origin)
+ in_definition_scope.then_some(origin)
}
+ /// Returns the origin of the opaque type `def_id` even if we are not in its
+ /// defining scope.
#[instrument(skip(self), level = "trace", ret)]
- fn opaque_ty_origin_unchecked(&self, def_id: LocalDefId, span: Span) -> OpaqueTyOrigin {
+ fn opaque_type_origin_unchecked(&self, def_id: LocalDefId) -> OpaqueTyOrigin {
match self.tcx.hir().expect_item(def_id).kind {
hir::ItemKind::OpaqueTy(hir::OpaqueTy { origin, .. }) => origin,
ref itemkind => {
- span_bug!(span, "weird opaque type: {:?}, {:#?}", def_id, itemkind)
+ bug!("weird opaque type: {:?}, {:#?}", def_id, itemkind)
}
}
}
@@ -431,11 +423,11 @@ pub struct ConstrainOpaqueTypeRegionVisitor<'tcx, OP: FnMut(ty::Region<'tcx>)> {
pub op: OP,
}
-impl<'tcx, OP> TypeVisitor<'tcx> for ConstrainOpaqueTypeRegionVisitor<'tcx, OP>
+impl<'tcx, OP> TypeVisitor<TyCtxt<'tcx>> for ConstrainOpaqueTypeRegionVisitor<'tcx, OP>
where
OP: FnMut(ty::Region<'tcx>),
{
- fn visit_binder<T: TypeVisitable<'tcx>>(
+ fn visit_binder<T: TypeVisitable<TyCtxt<'tcx>>>(
&mut self,
t: &ty::Binder<'tcx, T>,
) -> ControlFlow<Self::BreakTy> {
@@ -553,8 +545,11 @@ impl<'tcx> InferCtxt<'tcx> {
origin,
);
if let Some(prev) = prev {
- obligations =
- self.at(&cause, param_env).eq_exp(a_is_expected, prev, hidden_ty)?.obligations;
+ obligations = self
+ .at(&cause, param_env)
+ .define_opaque_types(true)
+ .eq_exp(a_is_expected, prev, hidden_ty)?
+ .obligations;
}
let item_bounds = tcx.bound_explicit_item_bounds(def_id.to_def_id());
diff --git a/compiler/rustc_infer/src/infer/outlives/components.rs b/compiler/rustc_infer/src/infer/outlives/components.rs
index 3d86279b0..ff23087fe 100644
--- a/compiler/rustc_infer/src/infer/outlives/components.rs
+++ b/compiler/rustc_infer/src/infer/outlives/components.rs
@@ -4,7 +4,7 @@
use rustc_data_structures::sso::SsoHashSet;
use rustc_middle::ty::subst::{GenericArg, GenericArgKind};
-use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitable};
+use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt};
use smallvec::{smallvec, SmallVec};
#[derive(Debug)]
@@ -112,7 +112,7 @@ fn compute_components<'tcx>(
}
// All regions are bound inside a witness
- ty::GeneratorWitness(..) => (),
+ ty::GeneratorWitness(..) | ty::GeneratorWitnessMIR(..) => (),
// OutlivesTypeParameterEnv -- the actual checking that `X:'a`
// is implied by the environment is done in regionck.
diff --git a/compiler/rustc_infer/src/infer/outlives/mod.rs b/compiler/rustc_infer/src/infer/outlives/mod.rs
index 4daa25767..83f3d5a74 100644
--- a/compiler/rustc_infer/src/infer/outlives/mod.rs
+++ b/compiler/rustc_infer/src/infer/outlives/mod.rs
@@ -21,6 +21,8 @@ pub fn explicit_outlives_bounds<'tcx>(
.filter_map(move |kind| match kind {
ty::PredicateKind::Clause(ty::Clause::Projection(..))
| ty::PredicateKind::Clause(ty::Clause::Trait(..))
+ | ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(..))
+ | ty::PredicateKind::AliasEq(..)
| ty::PredicateKind::Coerce(..)
| ty::PredicateKind::Subtype(..)
| ty::PredicateKind::WellFormed(..)
diff --git a/compiler/rustc_infer/src/infer/outlives/obligations.rs b/compiler/rustc_infer/src/infer/outlives/obligations.rs
index 0194549a8..bbe7d4c63 100644
--- a/compiler/rustc_infer/src/infer/outlives/obligations.rs
+++ b/compiler/rustc_infer/src/infer/outlives/obligations.rs
@@ -69,7 +69,7 @@ use crate::traits::{ObligationCause, ObligationCauseCode};
use rustc_data_structures::undo_log::UndoLogs;
use rustc_middle::mir::ConstraintCategory;
use rustc_middle::ty::subst::GenericArgKind;
-use rustc_middle::ty::{self, Region, SubstsRef, Ty, TyCtxt, TypeVisitable};
+use rustc_middle::ty::{self, Region, SubstsRef, Ty, TyCtxt, TypeVisitableExt};
use smallvec::smallvec;
impl<'tcx> InferCtxt<'tcx> {
diff --git a/compiler/rustc_infer/src/infer/outlives/test_type_match.rs b/compiler/rustc_infer/src/infer/outlives/test_type_match.rs
index 10b474efd..3c6cc2b90 100644
--- a/compiler/rustc_infer/src/infer/outlives/test_type_match.rs
+++ b/compiler/rustc_infer/src/infer/outlives/test_type_match.rs
@@ -1,7 +1,7 @@
use std::collections::hash_map::Entry;
use rustc_data_structures::fx::FxHashMap;
-use rustc_middle::ty::TypeVisitable;
+use rustc_middle::ty::TypeVisitableExt;
use rustc_middle::ty::{
self,
error::TypeError,
@@ -186,7 +186,8 @@ impl<'tcx> TypeRelation<'tcx> for Match<'tcx> {
#[instrument(skip(self), level = "debug")]
fn tys(&mut self, pattern: Ty<'tcx>, value: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> {
- if let ty::Error(_) = pattern.kind() {
+ // FIXME(non_lifetime_binders): What to do here?
+ if matches!(pattern.kind(), ty::Error(_) | ty::Bound(..)) {
// Unlike normal `TypeRelation` rules, `ty::Error` does not equal any type.
self.no_match()
} else if pattern == value {
diff --git a/compiler/rustc_infer/src/infer/outlives/verify.rs b/compiler/rustc_infer/src/infer/outlives/verify.rs
index 94de9bc2d..bae246418 100644
--- a/compiler/rustc_infer/src/infer/outlives/verify.rs
+++ b/compiler/rustc_infer/src/infer/outlives/verify.rs
@@ -207,6 +207,7 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> {
///
/// In some cases, such as when `erased_ty` represents a `ty::Param`, however,
/// the result is precise.
+ #[instrument(level = "debug", skip(self))]
fn declared_generic_bounds_from_env_for_erased_ty(
&self,
erased_ty: Ty<'tcx>,
diff --git a/compiler/rustc_infer/src/infer/projection.rs b/compiler/rustc_infer/src/infer/projection.rs
index 4667d99ff..f79504770 100644
--- a/compiler/rustc_infer/src/infer/projection.rs
+++ b/compiler/rustc_infer/src/infer/projection.rs
@@ -21,16 +21,28 @@ impl<'tcx> InferCtxt<'tcx> {
recursion_depth: usize,
obligations: &mut Vec<PredicateObligation<'tcx>>,
) -> Ty<'tcx> {
- let def_id = projection_ty.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, term: ty_var.into() });
- let obligation =
- Obligation::with_depth(self.tcx, cause, recursion_depth, param_env, projection);
- obligations.push(obligation);
- ty_var
+ if self.tcx.trait_solver_next() {
+ // FIXME(-Ztrait-solver=next): Instead of branching here,
+ // completely change the normalization routine with the new solver.
+ //
+ // The new solver correctly handles projection equality so this hack
+ // is not necessary. if re-enabled it should emit `PredicateKind::AliasEq`
+ // not `PredicateKind::Clause(Clause::Projection(..))` as in the new solver
+ // `Projection` is used as `normalizes-to` which will fail for `<T as Trait>::Assoc eq ?0`.
+ return projection_ty.to_ty(self.tcx);
+ } else {
+ let def_id = projection_ty.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::PredicateKind::Clause(ty::Clause::Projection(
+ ty::ProjectionPredicate { projection_ty, term: ty_var.into() },
+ )));
+ let obligation =
+ Obligation::with_depth(self.tcx, cause, recursion_depth, param_env, projection);
+ obligations.push(obligation);
+ ty_var
+ }
}
}
diff --git a/compiler/rustc_infer/src/infer/region_constraints/leak_check.rs b/compiler/rustc_infer/src/infer/region_constraints/leak_check.rs
index c46edc33f..e413b2bb5 100644
--- a/compiler/rustc_infer/src/infer/region_constraints/leak_check.rs
+++ b/compiler/rustc_infer/src/infer/region_constraints/leak_check.rs
@@ -280,7 +280,7 @@ impl<'me, 'tcx> LeakCheck<'me, 'tcx> {
placeholder1: ty::PlaceholderRegion,
placeholder2: ty::PlaceholderRegion,
) -> TypeError<'tcx> {
- self.error(placeholder1, self.tcx.mk_region(ty::RePlaceholder(placeholder2)))
+ self.error(placeholder1, self.tcx.mk_re_placeholder(placeholder2))
}
fn error(
@@ -413,19 +413,19 @@ impl<'tcx> MiniGraph<'tcx> {
for undo_entry in undo_log {
match undo_entry {
&AddConstraint(Constraint::VarSubVar(a, b)) => {
- each_edge(tcx.mk_region(ReVar(a)), tcx.mk_region(ReVar(b)));
+ each_edge(tcx.mk_re_var(a), tcx.mk_re_var(b));
}
&AddConstraint(Constraint::RegSubVar(a, b)) => {
- each_edge(a, tcx.mk_region(ReVar(b)));
+ each_edge(a, tcx.mk_re_var(b));
}
&AddConstraint(Constraint::VarSubReg(a, b)) => {
- each_edge(tcx.mk_region(ReVar(a)), b);
+ each_edge(tcx.mk_re_var(a), b);
}
&AddConstraint(Constraint::RegSubReg(a, b)) => {
each_edge(a, b);
}
&AddGiven(a, b) => {
- each_edge(a, tcx.mk_region(ReVar(b)));
+ each_edge(a, tcx.mk_re_var(b));
}
&AddVerify(i) => span_bug!(
verifys[i].origin.span(),
diff --git a/compiler/rustc_infer/src/infer/region_constraints/mod.rs b/compiler/rustc_infer/src/infer/region_constraints/mod.rs
index 0428481b7..872f61747 100644
--- a/compiler/rustc_infer/src/infer/region_constraints/mod.rs
+++ b/compiler/rustc_infer/src/infer/region_constraints/mod.rs
@@ -249,7 +249,7 @@ pub enum VerifyBound<'tcx> {
/// in that case we can show `'b: 'c`. But if `'?x` winds up being something
/// else, the bound isn't relevant.
///
-/// In the [`VerifyBound`], this struct is enclosed in `Binder to account
+/// In the [`VerifyBound`], this struct is enclosed in `Binder` to account
/// for cases like
///
/// ```rust
@@ -651,7 +651,7 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> {
let unified_region = self.unification_table().probe_value(rid);
unified_region.0.unwrap_or_else(|| {
let root = self.unification_table().find(rid).vid;
- tcx.reuse_or_mk_region(region, ty::ReVar(root))
+ tcx.mk_re_var(root)
})
}
_ => region,
@@ -675,7 +675,7 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> {
) -> Region<'tcx> {
let vars = TwoRegions { a, b };
if let Some(&c) = self.combine_map(t).get(&vars) {
- return tcx.mk_region(ReVar(c));
+ return tcx.mk_re_var(c);
}
let a_universe = self.universe(a);
let b_universe = self.universe(b);
@@ -683,7 +683,7 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> {
let c = self.new_region_var(c_universe, MiscVariable(origin.span()));
self.combine_map(t).insert(vars, c);
self.undo_log.push(AddCombination(t, vars));
- let new_r = tcx.mk_region(ReVar(c));
+ let new_r = tcx.mk_re_var(c);
for old_r in [a, b] {
match t {
Glb => self.make_subregion(origin.clone(), new_r, old_r),
@@ -696,9 +696,11 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> {
pub fn universe(&self, region: Region<'tcx>) -> ty::UniverseIndex {
match *region {
- ty::ReStatic | ty::ReErased | ty::ReFree(..) | ty::ReEarlyBound(..) => {
- ty::UniverseIndex::ROOT
- }
+ ty::ReStatic
+ | ty::ReErased
+ | ty::ReFree(..)
+ | ty::ReEarlyBound(..)
+ | ty::ReError(_) => ty::UniverseIndex::ROOT,
ty::RePlaceholder(placeholder) => placeholder.universe,
ty::ReVar(vid) => self.var_universe(vid),
ty::ReLateBound(..) => bug!("universe(): encountered bound region {:?}", region),
diff --git a/compiler/rustc_infer/src/infer/resolve.rs b/compiler/rustc_infer/src/infer/resolve.rs
index 65b90aa3d..5bb358329 100644
--- a/compiler/rustc_infer/src/infer/resolve.rs
+++ b/compiler/rustc_infer/src/infer/resolve.rs
@@ -2,8 +2,8 @@ use super::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
use super::{FixupError, FixupResult, InferCtxt, Span};
use rustc_middle::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind};
use rustc_middle::ty::fold::{FallibleTypeFolder, TypeFolder, TypeSuperFoldable};
-use rustc_middle::ty::visit::{TypeSuperVisitable, TypeVisitor};
-use rustc_middle::ty::{self, Const, InferConst, Ty, TyCtxt, TypeFoldable, TypeVisitable};
+use rustc_middle::ty::visit::{TypeSuperVisitable, TypeVisitableExt, TypeVisitor};
+use rustc_middle::ty::{self, Const, InferConst, Ty, TyCtxt, TypeFoldable};
use std::ops::ControlFlow;
@@ -16,26 +16,29 @@ use std::ops::ControlFlow;
/// useful for printing messages etc but also required at various
/// points for correctness.
pub struct OpportunisticVarResolver<'a, 'tcx> {
- infcx: &'a InferCtxt<'tcx>,
+ // The shallow resolver is used to resolve inference variables at every
+ // level of the type.
+ shallow_resolver: crate::infer::ShallowResolver<'a, 'tcx>,
}
impl<'a, 'tcx> OpportunisticVarResolver<'a, 'tcx> {
#[inline]
pub fn new(infcx: &'a InferCtxt<'tcx>) -> Self {
- OpportunisticVarResolver { infcx }
+ OpportunisticVarResolver { shallow_resolver: crate::infer::ShallowResolver { infcx } }
}
}
-impl<'a, 'tcx> TypeFolder<'tcx> for OpportunisticVarResolver<'a, 'tcx> {
- fn tcx<'b>(&'b self) -> TyCtxt<'tcx> {
- self.infcx.tcx
+impl<'a, 'tcx> TypeFolder<TyCtxt<'tcx>> for OpportunisticVarResolver<'a, 'tcx> {
+ fn interner(&self) -> TyCtxt<'tcx> {
+ TypeFolder::interner(&self.shallow_resolver)
}
+ #[inline]
fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
if !t.has_non_region_infer() {
t // micro-optimize -- if there is nothing in this type that this fold affects...
} else {
- let t = self.infcx.shallow_resolve(t);
+ let t = self.shallow_resolver.fold_ty(t);
t.super_fold_with(self)
}
}
@@ -44,7 +47,7 @@ impl<'a, 'tcx> TypeFolder<'tcx> for OpportunisticVarResolver<'a, 'tcx> {
if !ct.has_non_region_infer() {
ct // micro-optimize -- if there is nothing in this const that this fold affects...
} else {
- let ct = self.infcx.shallow_resolve(ct);
+ let ct = self.shallow_resolver.fold_const(ct);
ct.super_fold_with(self)
}
}
@@ -67,8 +70,8 @@ impl<'a, 'tcx> OpportunisticRegionResolver<'a, 'tcx> {
}
}
-impl<'a, 'tcx> TypeFolder<'tcx> for OpportunisticRegionResolver<'a, 'tcx> {
- fn tcx<'b>(&'b self) -> TyCtxt<'tcx> {
+impl<'a, 'tcx> TypeFolder<TyCtxt<'tcx>> for OpportunisticRegionResolver<'a, 'tcx> {
+ fn interner(&self) -> TyCtxt<'tcx> {
self.infcx.tcx
}
@@ -89,7 +92,7 @@ impl<'a, 'tcx> TypeFolder<'tcx> for OpportunisticRegionResolver<'a, 'tcx> {
.borrow_mut()
.unwrap_region_constraints()
.opportunistic_resolve_var(rid);
- TypeFolder::tcx(self).reuse_or_mk_region(r, ty::ReVar(resolved))
+ TypeFolder::interner(self).mk_re_var(resolved)
}
_ => r,
}
@@ -121,7 +124,7 @@ impl<'a, 'tcx> UnresolvedTypeOrConstFinder<'a, 'tcx> {
}
}
-impl<'a, 'tcx> TypeVisitor<'tcx> for UnresolvedTypeOrConstFinder<'a, 'tcx> {
+impl<'a, 'tcx> TypeVisitor<TyCtxt<'tcx>> for UnresolvedTypeOrConstFinder<'a, 'tcx> {
type BreakTy = (ty::Term<'tcx>, Option<Span>);
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
let t = self.infcx.shallow_resolve(t);
@@ -194,7 +197,7 @@ impl<'a, 'tcx> TypeVisitor<'tcx> for UnresolvedTypeOrConstFinder<'a, 'tcx> {
/// then an `Err` result is returned.
pub fn fully_resolve<'tcx, T>(infcx: &InferCtxt<'tcx>, value: T) -> FixupResult<'tcx, T>
where
- T: TypeFoldable<'tcx>,
+ T: TypeFoldable<TyCtxt<'tcx>>,
{
value.try_fold_with(&mut FullTypeResolver { infcx })
}
@@ -205,10 +208,10 @@ struct FullTypeResolver<'a, 'tcx> {
infcx: &'a InferCtxt<'tcx>,
}
-impl<'a, 'tcx> FallibleTypeFolder<'tcx> for FullTypeResolver<'a, 'tcx> {
+impl<'a, 'tcx> FallibleTypeFolder<TyCtxt<'tcx>> for FullTypeResolver<'a, 'tcx> {
type Error = FixupError<'tcx>;
- fn tcx<'b>(&'b self) -> TyCtxt<'tcx> {
+ fn interner(&self) -> TyCtxt<'tcx> {
self.infcx.tcx
}
diff --git a/compiler/rustc_infer/src/infer/sub.rs b/compiler/rustc_infer/src/infer/sub.rs
index bd38b52ba..3e8c2052d 100644
--- a/compiler/rustc_infer/src/infer/sub.rs
+++ b/compiler/rustc_infer/src/infer/sub.rs
@@ -1,10 +1,9 @@
use super::combine::{CombineFields, RelationDir};
-use super::SubregionOrigin;
+use super::{ObligationEmittingRelation, SubregionOrigin};
-use crate::infer::combine::ConstEquateRelation;
-use crate::traits::Obligation;
+use crate::traits::{Obligation, PredicateObligations};
use rustc_middle::ty::relate::{Cause, Relate, RelateResult, TypeRelation};
-use rustc_middle::ty::visit::TypeVisitable;
+use rustc_middle::ty::visit::TypeVisitableExt;
use rustc_middle::ty::TyVar;
use rustc_middle::ty::{self, Ty, TyCtxt};
use std::mem;
@@ -127,7 +126,7 @@ impl<'tcx> TypeRelation<'tcx> for Sub<'_, '_, 'tcx> {
(&ty::Error(e), _) | (_, &ty::Error(e)) => {
infcx.set_tainted_by_errors(e);
- Ok(self.tcx().ty_error_with_guaranteed(e))
+ Ok(self.tcx().ty_error(e))
}
(
@@ -161,7 +160,7 @@ impl<'tcx> TypeRelation<'tcx> for Sub<'_, '_, 'tcx> {
let a_types = infcx.tcx.anonymize_bound_vars(a_types);
let b_types = infcx.tcx.anonymize_bound_vars(b_types);
if a_types.bound_vars() == b_types.bound_vars() {
- let (a_types, b_types) = infcx.replace_bound_vars_with_placeholders(
+ let (a_types, b_types) = infcx.instantiate_binder_with_placeholders(
a_types.map_bound(|a_types| (a_types, b_types.skip_binder())),
);
for (a, b) in std::iter::zip(a_types, b_types) {
@@ -191,12 +190,13 @@ impl<'tcx> TypeRelation<'tcx> for Sub<'_, '_, 'tcx> {
// from the "cause" field, we could perhaps give more tailored
// error messages.
let origin = SubregionOrigin::Subtype(Box::new(self.fields.trace.clone()));
+ // Subtype(&'a u8, &'b u8) => Outlives('a: 'b) => SubRegion('b, 'a)
self.fields
.infcx
.inner
.borrow_mut()
.unwrap_region_constraints()
- .make_subregion(origin, a, b);
+ .make_subregion(origin, b, a);
Ok(a)
}
@@ -227,8 +227,12 @@ impl<'tcx> TypeRelation<'tcx> for Sub<'_, '_, 'tcx> {
}
}
-impl<'tcx> ConstEquateRelation<'tcx> for Sub<'_, '_, 'tcx> {
- fn const_equate_obligation(&mut self, a: ty::Const<'tcx>, b: ty::Const<'tcx>) {
- self.fields.add_const_equate_obligation(self.a_is_expected, a, b);
+impl<'tcx> ObligationEmittingRelation<'tcx> for Sub<'_, '_, 'tcx> {
+ fn register_predicates(&mut self, obligations: impl IntoIterator<Item: ty::ToPredicate<'tcx>>) {
+ self.fields.register_predicates(obligations);
+ }
+
+ fn register_obligations(&mut self, obligations: PredicateObligations<'tcx>) {
+ self.fields.register_obligations(obligations);
}
}
diff --git a/compiler/rustc_infer/src/lib.rs b/compiler/rustc_infer/src/lib.rs
index 4c119a443..bdc313c21 100644
--- a/compiler/rustc_infer/src/lib.rs
+++ b/compiler/rustc_infer/src/lib.rs
@@ -13,6 +13,7 @@
//! This API is completely unstable and subject to change.
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
+#![feature(associated_type_bounds)]
#![feature(box_patterns)]
#![feature(control_flow_enum)]
#![feature(extend_one)]
@@ -33,6 +34,11 @@ extern crate tracing;
#[macro_use]
extern crate rustc_middle;
+use rustc_errors::{DiagnosticMessage, SubdiagnosticMessage};
+use rustc_macros::fluent_messages;
+
mod errors;
pub mod infer;
pub mod traits;
+
+fluent_messages! { "../locales/en-US.ftl" }
diff --git a/compiler/rustc_infer/src/traits/engine.rs b/compiler/rustc_infer/src/traits/engine.rs
index d3519f4b3..f75344f20 100644
--- a/compiler/rustc_infer/src/traits/engine.rs
+++ b/compiler/rustc_infer/src/traits/engine.rs
@@ -1,6 +1,5 @@
use crate::infer::InferCtxt;
use crate::traits::Obligation;
-use rustc_data_structures::fx::FxHashMap;
use rustc_hir::def_id::DefId;
use rustc_middle::ty::{self, ToPredicate, Ty};
@@ -37,13 +36,19 @@ pub trait TraitEngine<'tcx>: 'tcx {
obligation: PredicateObligation<'tcx>,
);
- fn select_all_or_error(&mut self, infcx: &InferCtxt<'tcx>) -> Vec<FulfillmentError<'tcx>>;
-
fn select_where_possible(&mut self, infcx: &InferCtxt<'tcx>) -> Vec<FulfillmentError<'tcx>>;
+ fn collect_remaining_errors(&mut self) -> Vec<FulfillmentError<'tcx>>;
+
fn pending_obligations(&self) -> Vec<PredicateObligation<'tcx>>;
- fn relationships(&mut self) -> &mut FxHashMap<ty::TyVid, ty::FoundRelationships>;
+ /// Among all pending obligations, collect those are stalled on a inference variable which has
+ /// changed since the last call to `select_where_possible`. Those obligations are marked as
+ /// successful and returned.
+ fn drain_unstalled_obligations(
+ &mut self,
+ infcx: &InferCtxt<'tcx>,
+ ) -> Vec<PredicateObligation<'tcx>>;
}
pub trait TraitEngineExt<'tcx> {
@@ -52,6 +57,8 @@ pub trait TraitEngineExt<'tcx> {
infcx: &InferCtxt<'tcx>,
obligations: impl IntoIterator<Item = PredicateObligation<'tcx>>,
);
+
+ fn select_all_or_error(&mut self, infcx: &InferCtxt<'tcx>) -> Vec<FulfillmentError<'tcx>>;
}
impl<'tcx, T: ?Sized + TraitEngine<'tcx>> TraitEngineExt<'tcx> for T {
@@ -64,4 +71,13 @@ impl<'tcx, T: ?Sized + TraitEngine<'tcx>> TraitEngineExt<'tcx> for T {
self.register_predicate_obligation(infcx, obligation);
}
}
+
+ fn select_all_or_error(&mut self, infcx: &InferCtxt<'tcx>) -> Vec<FulfillmentError<'tcx>> {
+ let errors = self.select_where_possible(infcx);
+ if !errors.is_empty() {
+ return errors;
+ }
+
+ self.collect_remaining_errors()
+ }
}
diff --git a/compiler/rustc_infer/src/traits/mod.rs b/compiler/rustc_infer/src/traits/mod.rs
index 026713b6a..3a8289966 100644
--- a/compiler/rustc_infer/src/traits/mod.rs
+++ b/compiler/rustc_infer/src/traits/mod.rs
@@ -8,6 +8,7 @@ mod project;
mod structural_impls;
pub mod util;
+use hir::def_id::LocalDefId;
use rustc_hir as hir;
use rustc_middle::ty::error::{ExpectedFound, TypeError};
use rustc_middle::ty::{self, Const, ToPredicate, Ty, TyCtxt};
@@ -146,7 +147,7 @@ impl<'tcx, O> Obligation<'tcx, O> {
pub fn misc(
tcx: TyCtxt<'tcx>,
span: Span,
- body_id: hir::HirId,
+ body_id: LocalDefId,
param_env: ty::ParamEnv<'tcx>,
trait_ref: impl ToPredicate<'tcx, O>,
) -> Obligation<'tcx, O> {
diff --git a/compiler/rustc_infer/src/traits/structural_impls.rs b/compiler/rustc_infer/src/traits/structural_impls.rs
index 1c6ab6a08..3a5273b03 100644
--- a/compiler/rustc_infer/src/traits/structural_impls.rs
+++ b/compiler/rustc_infer/src/traits/structural_impls.rs
@@ -1,8 +1,8 @@
use crate::traits;
use crate::traits::project::Normalized;
-use rustc_middle::ty;
use rustc_middle::ty::fold::{FallibleTypeFolder, TypeFoldable};
use rustc_middle::ty::visit::{TypeVisitable, TypeVisitor};
+use rustc_middle::ty::{self, TyCtxt};
use std::fmt;
use std::ops::ControlFlow;
@@ -61,8 +61,13 @@ impl<'tcx> fmt::Debug for traits::MismatchedProjectionTypes<'tcx> {
///////////////////////////////////////////////////////////////////////////
// TypeFoldable implementations.
-impl<'tcx, O: TypeFoldable<'tcx>> TypeFoldable<'tcx> for traits::Obligation<'tcx, O> {
- fn try_fold_with<F: FallibleTypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> {
+impl<'tcx, O: TypeFoldable<TyCtxt<'tcx>>> TypeFoldable<TyCtxt<'tcx>>
+ for traits::Obligation<'tcx, O>
+{
+ fn try_fold_with<F: FallibleTypeFolder<TyCtxt<'tcx>>>(
+ self,
+ folder: &mut F,
+ ) -> Result<Self, F::Error> {
Ok(traits::Obligation {
cause: self.cause,
recursion_depth: self.recursion_depth,
@@ -72,8 +77,10 @@ impl<'tcx, O: TypeFoldable<'tcx>> TypeFoldable<'tcx> for traits::Obligation<'tcx
}
}
-impl<'tcx, O: TypeVisitable<'tcx>> TypeVisitable<'tcx> for traits::Obligation<'tcx, O> {
- fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
+impl<'tcx, O: TypeVisitable<TyCtxt<'tcx>>> TypeVisitable<TyCtxt<'tcx>>
+ for traits::Obligation<'tcx, O>
+{
+ fn visit_with<V: TypeVisitor<TyCtxt<'tcx>>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
self.predicate.visit_with(visitor)?;
self.param_env.visit_with(visitor)
}
diff --git a/compiler/rustc_infer/src/traits/util.rs b/compiler/rustc_infer/src/traits/util.rs
index cd5bde2a7..c07ff5165 100644
--- a/compiler/rustc_infer/src/traits/util.rs
+++ b/compiler/rustc_infer/src/traits/util.rs
@@ -116,11 +116,11 @@ pub fn elaborate_predicates_with_span<'tcx>(
pub fn elaborate_obligations<'tcx>(
tcx: TyCtxt<'tcx>,
- mut obligations: Vec<PredicateObligation<'tcx>>,
+ obligations: Vec<PredicateObligation<'tcx>>,
) -> Elaborator<'tcx> {
- let mut visited = PredicateSet::new(tcx);
- obligations.retain(|obligation| visited.insert(obligation.predicate));
- Elaborator { stack: obligations, visited }
+ let mut elaborator = Elaborator { stack: Vec::new(), visited: PredicateSet::new(tcx) };
+ elaborator.extend_deduped(obligations);
+ elaborator
}
fn predicate_obligation<'tcx>(
@@ -132,6 +132,15 @@ fn predicate_obligation<'tcx>(
}
impl<'tcx> Elaborator<'tcx> {
+ fn extend_deduped(&mut self, obligations: impl IntoIterator<Item = PredicateObligation<'tcx>>) {
+ // Only keep those bounds that we haven't already seen.
+ // This is necessary to prevent infinite recursion in some
+ // cases. One common case is when people define
+ // `trait Sized: Sized { }` rather than `trait Sized { }`.
+ // let visited = &mut self.visited;
+ self.stack.extend(obligations.into_iter().filter(|o| self.visited.insert(o.predicate)));
+ }
+
pub fn filter_to_traits(self) -> FilterToTraits<Self> {
FilterToTraits::new(self)
}
@@ -145,40 +154,34 @@ impl<'tcx> Elaborator<'tcx> {
// Get predicates declared on the trait.
let predicates = tcx.super_predicates_of(data.def_id());
- let obligations = predicates.predicates.iter().map(|&(mut pred, span)| {
- // when parent predicate is non-const, elaborate it to non-const predicates.
- if data.constness == ty::BoundConstness::NotConst {
- pred = pred.without_const(tcx);
- }
-
- let cause = obligation.cause.clone().derived_cause(
- bound_predicate.rebind(data),
- |derived| {
- traits::ImplDerivedObligation(Box::new(
- traits::ImplDerivedObligationCause {
- derived,
- impl_def_id: data.def_id(),
- span,
- },
- ))
- },
- );
- predicate_obligation(
- pred.subst_supertrait(tcx, &bound_predicate.rebind(data.trait_ref)),
- obligation.param_env,
- cause,
- )
- });
+ let obligations =
+ predicates.predicates.iter().enumerate().map(|(index, &(mut pred, span))| {
+ // when parent predicate is non-const, elaborate it to non-const predicates.
+ if data.constness == ty::BoundConstness::NotConst {
+ pred = pred.without_const(tcx);
+ }
+
+ let cause = obligation.cause.clone().derived_cause(
+ bound_predicate.rebind(data),
+ |derived| {
+ traits::ImplDerivedObligation(Box::new(
+ traits::ImplDerivedObligationCause {
+ derived,
+ impl_or_alias_def_id: data.def_id(),
+ impl_def_predicate_index: Some(index),
+ span,
+ },
+ ))
+ },
+ );
+ predicate_obligation(
+ pred.subst_supertrait(tcx, &bound_predicate.rebind(data.trait_ref)),
+ obligation.param_env,
+ cause,
+ )
+ });
debug!(?data, ?obligations, "super_predicates");
-
- // Only keep those bounds that we haven't already seen.
- // This is necessary to prevent infinite recursion in some
- // cases. One common case is when people define
- // `trait Sized: Sized { }` rather than `trait Sized { }`.
- let visited = &mut self.visited;
- let obligations = obligations.filter(|o| visited.insert(o.predicate));
-
- self.stack.extend(obligations);
+ self.extend_deduped(obligations);
}
ty::PredicateKind::WellFormed(..) => {
// Currently, we do not elaborate WF predicates,
@@ -235,10 +238,9 @@ impl<'tcx> Elaborator<'tcx> {
return;
}
- let visited = &mut self.visited;
let mut components = smallvec![];
push_outlives_components(tcx, ty_max, &mut components);
- self.stack.extend(
+ self.extend_deduped(
components
.into_iter()
.filter_map(|component| match component {
@@ -278,7 +280,6 @@ impl<'tcx> Elaborator<'tcx> {
.map(|predicate_kind| {
bound_predicate.rebind(predicate_kind).to_predicate(tcx)
})
- .filter(|&predicate| visited.insert(predicate))
.map(|predicate| {
predicate_obligation(
predicate,
@@ -292,6 +293,12 @@ impl<'tcx> Elaborator<'tcx> {
// Nothing to elaborate
}
ty::PredicateKind::Ambiguous => {}
+ ty::PredicateKind::AliasEq(..) => {
+ // No
+ }
+ ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(..)) => {
+ // Nothing to elaborate
+ }
}
}
}
diff --git a/compiler/rustc_interface/Cargo.toml b/compiler/rustc_interface/Cargo.toml
index f817c5bc1..ac6e8fca6 100644
--- a/compiler/rustc_interface/Cargo.toml
+++ b/compiler/rustc_interface/Cargo.toml
@@ -20,11 +20,11 @@ rustc_macros = { path = "../rustc_macros" }
rustc_parse = { path = "../rustc_parse" }
rustc_session = { path = "../rustc_session" }
rustc_span = { path = "../rustc_span" }
-rustc_serialize = { path = "../rustc_serialize" }
rustc_middle = { path = "../rustc_middle" }
rustc_ast_lowering = { path = "../rustc_ast_lowering" }
rustc_ast_passes = { path = "../rustc_ast_passes" }
rustc_incremental = { path = "../rustc_incremental" }
+rustc_index = { path = "../rustc_index" }
rustc_traits = { path = "../rustc_traits" }
rustc_data_structures = { path = "../rustc_data_structures" }
rustc_codegen_ssa = { path = "../rustc_codegen_ssa" }
@@ -49,9 +49,6 @@ rustc_target = { path = "../rustc_target" }
rustc_trait_selection = { path = "../rustc_trait_selection" }
rustc_ty_utils = { path = "../rustc_ty_utils" }
-[dev-dependencies]
-rustc_target = { path = "../rustc_target" }
-
[features]
llvm = ['rustc_codegen_llvm']
rustc_use_parallel_compiler = ['rayon', 'rustc-rayon-core', 'rustc_query_impl/rustc_use_parallel_compiler', 'rustc_errors/rustc_use_parallel_compiler']
diff --git a/compiler/rustc_error_messages/locales/en-US/interface.ftl b/compiler/rustc_interface/locales/en-US.ftl
index 688b04472..37994899a 100644
--- a/compiler/rustc_error_messages/locales/en-US/interface.ftl
+++ b/compiler/rustc_interface/locales/en-US.ftl
@@ -11,10 +11,6 @@ interface_mixed_bin_crate =
interface_mixed_proc_macro_crate =
cannot mix `proc-macro` crate type with others
-interface_proc_macro_doc_without_arg =
- Trying to document proc macro crate without passing '--crate-type proc-macro to rustdoc
- .warn = The generated documentation may be incorrect
-
interface_error_writing_dependencies =
error writing dependencies to `{$path}`: {$error}
@@ -37,10 +33,20 @@ interface_rustc_error_fatal =
fatal error triggered by #[rustc_error]
interface_rustc_error_unexpected_annotation =
- unexpected annotation used with `#[rustc_error(...)]!
+ unexpected annotation used with `#[rustc_error(...)]`!
interface_failed_writing_file =
failed to write file {$path}: {$error}"
interface_proc_macro_crate_panic_abort =
building proc macro crate with `panic=abort` may crash the compiler should the proc-macro panic
+
+interface_unsupported_crate_type_for_target =
+ dropping unsupported crate type `{$crate_type}` for target `{$target_triple}`
+
+interface_multiple_output_types_adaption =
+ due to multiple output types requested, the explicitly specified output file name will be adapted for each output type
+
+interface_ignoring_extra_filename = ignoring -C extra-filename flag due to -o flag
+
+interface_ignoring_out_dir = ignoring --out-dir flag due to -o flag
diff --git a/compiler/rustc_interface/src/callbacks.rs b/compiler/rustc_interface/src/callbacks.rs
index ee0552d77..bc6d7c209 100644
--- a/compiler/rustc_interface/src/callbacks.rs
+++ b/compiler/rustc_interface/src/callbacks.rs
@@ -38,7 +38,7 @@ fn track_diagnostic(diagnostic: &mut Diagnostic, f: &mut dyn FnMut(&mut Diagnost
// Diagnostics are tracked, we can ignore the dependency.
let icx = tls::ImplicitCtxt { task_deps: TaskDepsRef::Ignore, ..icx.clone() };
- return tls::enter_context(&icx, move |_| (*f)(diagnostic));
+ return tls::enter_context(&icx, move || (*f)(diagnostic));
}
// In any other case, invoke diagnostics anyway.
diff --git a/compiler/rustc_interface/src/errors.rs b/compiler/rustc_interface/src/errors.rs
index 15d7e977b..0eedee250 100644
--- a/compiler/rustc_interface/src/errors.rs
+++ b/compiler/rustc_interface/src/errors.rs
@@ -1,5 +1,7 @@
use rustc_macros::Diagnostic;
+use rustc_session::config::CrateType;
use rustc_span::{Span, Symbol};
+use rustc_target::spec::TargetTriple;
use std::io;
use std::path::Path;
@@ -30,10 +32,6 @@ pub struct MixedBinCrate;
pub struct MixedProcMacroCrate;
#[derive(Diagnostic)]
-#[diag(interface_proc_macro_doc_without_arg)]
-pub struct ProcMacroDocWithoutArg;
-
-#[derive(Diagnostic)]
#[diag(interface_error_writing_dependencies)]
pub struct ErrorWritingDependencies<'a> {
pub path: &'a Path,
@@ -91,3 +89,22 @@ pub struct FailedWritingFile<'a> {
#[derive(Diagnostic)]
#[diag(interface_proc_macro_crate_panic_abort)]
pub struct ProcMacroCratePanicAbort;
+
+#[derive(Diagnostic)]
+#[diag(interface_unsupported_crate_type_for_target)]
+pub struct UnsupportedCrateTypeForTarget<'a> {
+ pub crate_type: CrateType,
+ pub target_triple: &'a TargetTriple,
+}
+
+#[derive(Diagnostic)]
+#[diag(interface_multiple_output_types_adaption)]
+pub struct MultipleOutputTypesAdaption;
+
+#[derive(Diagnostic)]
+#[diag(interface_ignoring_extra_filename)]
+pub struct IgnoringExtraFilename;
+
+#[derive(Diagnostic)]
+#[diag(interface_ignoring_out_dir)]
+pub struct IgnoringOutDir;
diff --git a/compiler/rustc_interface/src/interface.rs b/compiler/rustc_interface/src/interface.rs
index 7a5e45ada..5e38ca034 100644
--- a/compiler/rustc_interface/src/interface.rs
+++ b/compiler/rustc_interface/src/interface.rs
@@ -1,4 +1,3 @@
-pub use crate::passes::BoxedResolver;
use crate::util;
use rustc_ast::token;
@@ -223,6 +222,7 @@ pub struct Config {
pub output_dir: Option<PathBuf>,
pub output_file: Option<PathBuf>,
pub file_loader: Option<Box<dyn FileLoader + Send + Sync>>,
+ pub locale_resources: &'static [&'static str],
pub lint_caps: FxHashMap<lint::LintId, lint::Level>,
@@ -268,6 +268,7 @@ pub fn run_compiler<R: Send>(config: Config, f: impl FnOnce(&Compiler) -> R + Se
config.opts,
config.crate_cfg,
config.crate_check_cfg,
+ config.locale_resources,
config.file_loader,
CompilerIO {
input: config.input,
diff --git a/compiler/rustc_interface/src/lib.rs b/compiler/rustc_interface/src/lib.rs
index 82bc4770b..1abbe8d4f 100644
--- a/compiler/rustc_interface/src/lib.rs
+++ b/compiler/rustc_interface/src/lib.rs
@@ -12,6 +12,9 @@
#[macro_use]
extern crate tracing;
+use rustc_errors::{DiagnosticMessage, SubdiagnosticMessage};
+use rustc_macros::fluent_messages;
+
mod callbacks;
mod errors;
pub mod interface;
@@ -27,3 +30,5 @@ pub use queries::Queries;
#[cfg(test)]
mod tests;
+
+fluent_messages! { "../locales/en-US.ftl" }
diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs
index 379a76528..81c1d665e 100644
--- a/compiler/rustc_interface/src/passes.rs
+++ b/compiler/rustc_interface/src/passes.rs
@@ -1,9 +1,4 @@
-use crate::errors::{
- CantEmitMIR, EmojiIdentifier, ErrorWritingDependencies, FerrisIdentifier,
- GeneratedFileConflictsWithDirectory, InputFileWouldBeOverWritten, MixedBinCrate,
- MixedProcMacroCrate, OutDirError, ProcMacroCratePanicAbort, ProcMacroDocWithoutArg,
- TempsDirError,
-};
+use crate::errors;
use crate::interface::{Compiler, Result};
use crate::proc_macro_decls;
use crate::util;
@@ -13,11 +8,12 @@ use rustc_ast::{self as ast, visit};
use rustc_borrowck as mir_borrowck;
use rustc_codegen_ssa::traits::CodegenBackend;
use rustc_data_structures::parallel;
+use rustc_data_structures::steal::Steal;
use rustc_data_structures::sync::{Lrc, OnceCell, WorkerLocal};
-use rustc_errors::{ErrorGuaranteed, PResult};
+use rustc_errors::PResult;
use rustc_expand::base::{ExtCtxt, LintStoreExpand, ResolverExpand};
-use rustc_hir::def_id::StableCrateId;
-use rustc_lint::{BufferedEarlyLint, EarlyCheckNode, LintStore};
+use rustc_hir::def_id::{StableCrateId, LOCAL_CRATE};
+use rustc_lint::{unerased_lint_store, BufferedEarlyLint, EarlyCheckNode, LintStore};
use rustc_metadata::creader::CStore;
use rustc_middle::arena::Arena;
use rustc_middle::dep_graph::DepGraph;
@@ -28,9 +24,9 @@ use rustc_parse::{parse_crate_from_file, parse_crate_from_source_str, validate_a
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_resolve::Resolver;
use rustc_session::config::{CrateType, Input, OutputFilenames, OutputType};
-use rustc_session::cstore::{MetadataLoader, MetadataLoaderDyn, Untracked};
+use rustc_session::cstore::{CrateStoreDyn, MetadataLoader, Untracked};
use rustc_session::output::filename_for_input;
use rustc_session::search_paths::PathKind;
use rustc_session::{Limit, Session};
@@ -40,14 +36,10 @@ use rustc_target::spec::PanicStrategy;
use rustc_trait_selection::traits;
use std::any::Any;
-use std::cell::RefCell;
use std::ffi::OsString;
use std::io::{self, BufWriter, Write};
-use std::marker::PhantomPinned;
use std::path::{Path, PathBuf};
-use std::pin::Pin;
-use std::rc::Rc;
-use std::sync::LazyLock;
+use std::sync::{Arc, LazyLock};
use std::{env, fs, iter};
pub fn parse<'a>(sess: &'a Session) -> PResult<'a, ast::Crate> {
@@ -80,93 +72,6 @@ fn count_nodes(krate: &ast::Crate) -> usize {
counter.count
}
-pub use boxed_resolver::BoxedResolver;
-mod boxed_resolver {
- use super::*;
-
- pub struct BoxedResolver(Pin<Box<BoxedResolverInner>>);
-
- struct BoxedResolverInner {
- session: Lrc<Session>,
- resolver_arenas: Option<ResolverArenas<'static>>,
- resolver: Option<Resolver<'static>>,
- _pin: PhantomPinned,
- }
-
- // Note: Drop order is important to prevent dangling references. Resolver must be dropped first,
- // then resolver_arenas and session.
- impl Drop for BoxedResolverInner {
- fn drop(&mut self) {
- self.resolver.take();
- self.resolver_arenas.take();
- }
- }
-
- impl BoxedResolver {
- pub(super) fn new(
- session: Lrc<Session>,
- make_resolver: impl for<'a> FnOnce(&'a Session, &'a ResolverArenas<'a>) -> Resolver<'a>,
- ) -> BoxedResolver {
- let mut boxed_resolver = Box::new(BoxedResolverInner {
- session,
- resolver_arenas: Some(Resolver::arenas()),
- resolver: None,
- _pin: PhantomPinned,
- });
- // SAFETY: `make_resolver` takes a resolver arena with an arbitrary lifetime and
- // returns a resolver with the same lifetime as the arena. We ensure that the arena
- // outlives the resolver in the drop impl and elsewhere so these transmutes are sound.
- unsafe {
- let resolver = make_resolver(
- std::mem::transmute::<&Session, &Session>(&boxed_resolver.session),
- std::mem::transmute::<&ResolverArenas<'_>, &ResolverArenas<'_>>(
- boxed_resolver.resolver_arenas.as_ref().unwrap(),
- ),
- );
- boxed_resolver.resolver = Some(resolver);
- BoxedResolver(Pin::new_unchecked(boxed_resolver))
- }
- }
-
- pub fn access<F: for<'a> FnOnce(&mut Resolver<'a>) -> R, R>(&mut self, f: F) -> R {
- // SAFETY: The resolver doesn't need to be pinned.
- let mut resolver = unsafe {
- self.0.as_mut().map_unchecked_mut(|boxed_resolver| &mut boxed_resolver.resolver)
- };
- f((&mut *resolver).as_mut().unwrap())
- }
-
- pub fn to_resolver_outputs(resolver: Rc<RefCell<BoxedResolver>>) -> ty::ResolverOutputs {
- match Rc::try_unwrap(resolver) {
- Ok(resolver) => {
- let mut resolver = resolver.into_inner();
- // SAFETY: The resolver doesn't need to be pinned.
- let mut resolver = unsafe {
- resolver
- .0
- .as_mut()
- .map_unchecked_mut(|boxed_resolver| &mut boxed_resolver.resolver)
- };
- resolver.take().unwrap().into_outputs()
- }
- Err(resolver) => resolver.borrow_mut().access(|resolver| resolver.clone_outputs()),
- }
- }
- }
-}
-
-pub fn create_resolver(
- sess: Lrc<Session>,
- metadata_loader: Box<MetadataLoaderDyn>,
- krate: &ast::Crate,
- crate_name: Symbol,
-) -> BoxedResolver {
- trace!("create_resolver");
- BoxedResolver::new(sess, move |sess, resolver_arenas| {
- Resolver::new(sess, krate, crate_name, metadata_loader, resolver_arenas)
- })
-}
-
pub fn register_plugins<'a>(
sess: &'a Session,
metadata_loader: &'a dyn MetadataLoader,
@@ -267,14 +172,12 @@ impl LintStoreExpand for LintStoreExpandImpl<'_> {
/// syntax expansion, secondary `cfg` expansion, synthesis of a test
/// harness if one is to be provided, injection of a dependency on the
/// standard library and prelude, and name resolution.
-pub fn configure_and_expand(
- sess: &Session,
- lint_store: &LintStore,
- mut krate: ast::Crate,
- crate_name: Symbol,
- resolver: &mut Resolver<'_>,
-) -> Result<ast::Crate> {
- trace!("configure_and_expand");
+#[instrument(level = "trace", skip(krate, resolver))]
+fn configure_and_expand(mut krate: ast::Crate, resolver: &mut Resolver<'_, '_>) -> ast::Crate {
+ let tcx = resolver.tcx();
+ let sess = tcx.sess;
+ let lint_store = unerased_lint_store(tcx);
+ let crate_name = tcx.crate_name(LOCAL_CRATE);
pre_expansion_lint(sess, lint_store, resolver.registered_tools(), &krate, crate_name);
rustc_builtin_macros::register_builtin_macros(resolver);
@@ -345,20 +248,19 @@ pub fn configure_and_expand(
ecx.check_unused_macros();
});
- let recursion_limit_hit = ecx.reduced_recursion_limit.is_some();
+ // If we hit a recursion limit, exit early to avoid later passes getting overwhelmed
+ // with a large AST
+ if ecx.reduced_recursion_limit.is_some() {
+ sess.abort_if_errors();
+ unreachable!();
+ }
if cfg!(windows) {
env::set_var("PATH", &old_path);
}
- if recursion_limit_hit {
- // If we hit a recursion limit, exit early to avoid later passes getting overwhelmed
- // with a large AST
- Err(ErrorGuaranteed::unchecked_claim_error_was_emitted())
- } else {
- Ok(krate)
- }
- })?;
+ krate
+ });
sess.time("maybe_building_test_harness", || {
rustc_builtin_macros::test_harness::inject(sess, resolver, &mut krate)
@@ -374,39 +276,29 @@ pub fn configure_and_expand(
if crate_types.len() > 1 {
if is_executable_crate {
- sess.emit_err(MixedBinCrate);
+ sess.emit_err(errors::MixedBinCrate);
}
if is_proc_macro_crate {
- sess.emit_err(MixedProcMacroCrate);
+ sess.emit_err(errors::MixedProcMacroCrate);
}
}
if is_proc_macro_crate && sess.panic_strategy() == PanicStrategy::Abort {
- sess.emit_warning(ProcMacroCratePanicAbort);
+ sess.emit_warning(errors::ProcMacroCratePanicAbort);
}
- // For backwards compatibility, we don't try to run proc macro injection
- // if rustdoc is run on a proc macro crate without '--crate-type proc-macro' being
- // specified. This should only affect users who manually invoke 'rustdoc', as
- // 'cargo doc' will automatically pass the proper '--crate-type' flags.
- // However, we do emit a warning, to let such users know that they should
- // start passing '--crate-type proc-macro'
- if has_proc_macro_decls && sess.opts.actually_rustdoc && !is_proc_macro_crate {
- sess.emit_warning(ProcMacroDocWithoutArg);
- } else {
- krate = sess.time("maybe_create_a_macro_crate", || {
- let is_test_crate = sess.opts.test;
- rustc_builtin_macros::proc_macro_harness::inject(
- sess,
- resolver,
- krate,
- is_proc_macro_crate,
- has_proc_macro_decls,
- is_test_crate,
- sess.diagnostic(),
- )
- });
- }
+ krate = sess.time("maybe_create_a_macro_crate", || {
+ let is_test_crate = sess.opts.test;
+ rustc_builtin_macros::proc_macro_harness::inject(
+ sess,
+ resolver,
+ krate,
+ is_proc_macro_crate,
+ has_proc_macro_decls,
+ is_test_crate,
+ sess.diagnostic(),
+ )
+ });
// Done with macro expansion!
@@ -441,9 +333,9 @@ pub fn configure_and_expand(
spans.sort();
if ident == sym::ferris {
let first_span = spans[0];
- sess.emit_err(FerrisIdentifier { spans, first_span });
+ sess.emit_err(errors::FerrisIdentifier { spans, first_span });
} else {
- sess.emit_err(EmojiIdentifier { spans, ident });
+ sess.emit_err(errors::EmojiIdentifier { spans, ident });
}
}
});
@@ -461,7 +353,7 @@ pub fn configure_and_expand(
)
});
- Ok(krate)
+ krate
}
// Returns all the paths that correspond to generated files.
@@ -548,7 +440,7 @@ fn escape_dep_env(symbol: Symbol) -> String {
fn write_out_deps(
sess: &Session,
- boxed_resolver: &RefCell<BoxedResolver>,
+ cstore: &CrateStoreDyn,
outputs: &OutputFilenames,
out_filenames: &[PathBuf],
) {
@@ -600,20 +492,19 @@ fn write_out_deps(
}
}
- boxed_resolver.borrow_mut().access(|resolver| {
- for cnum in resolver.cstore().crates_untracked() {
- let source = resolver.cstore().crate_source_untracked(cnum);
- if let Some((path, _)) = &source.dylib {
- files.push(escape_dep_filename(&path.display().to_string()));
- }
- if let Some((path, _)) = &source.rlib {
- files.push(escape_dep_filename(&path.display().to_string()));
- }
- if let Some((path, _)) = &source.rmeta {
- files.push(escape_dep_filename(&path.display().to_string()));
- }
+ let cstore = cstore.as_any().downcast_ref::<CStore>().unwrap();
+ for cnum in cstore.crates_untracked() {
+ let source = cstore.crate_source_untracked(cnum);
+ if let Some((path, _)) = &source.dylib {
+ files.push(escape_dep_filename(&path.display().to_string()));
+ }
+ if let Some((path, _)) = &source.rlib {
+ files.push(escape_dep_filename(&path.display().to_string()));
}
- });
+ if let Some((path, _)) = &source.rmeta {
+ files.push(escape_dep_filename(&path.display().to_string()));
+ }
+ }
}
let mut file = BufWriter::new(fs::File::create(&deps_filename)?);
@@ -656,18 +547,38 @@ fn write_out_deps(
}
}
Err(error) => {
- sess.emit_fatal(ErrorWritingDependencies { path: &deps_filename, error });
+ sess.emit_fatal(errors::ErrorWritingDependencies { path: &deps_filename, error });
}
}
}
-pub fn prepare_outputs(
- sess: &Session,
- krate: &ast::Crate,
- boxed_resolver: &RefCell<BoxedResolver>,
- crate_name: Symbol,
-) -> Result<OutputFilenames> {
+fn resolver_for_lowering<'tcx>(
+ tcx: TyCtxt<'tcx>,
+ (): (),
+) -> &'tcx Steal<(ty::ResolverAstLowering, Lrc<ast::Crate>)> {
+ let arenas = Resolver::arenas();
+ let krate = tcx.crate_for_resolver(()).steal();
+ let mut resolver = Resolver::new(tcx, &krate, &arenas);
+ let krate = configure_and_expand(krate, &mut resolver);
+
+ // Make sure we don't mutate the cstore from here on.
+ tcx.untracked().cstore.leak();
+
+ let ty::ResolverOutputs {
+ global_ctxt: untracked_resolutions,
+ ast_lowering: untracked_resolver_for_lowering,
+ } = resolver.into_outputs();
+
+ let feed = tcx.feed_unit_query();
+ feed.resolutions(tcx.arena.alloc(untracked_resolutions));
+ tcx.arena.alloc(Steal::new((untracked_resolver_for_lowering, Lrc::new(krate))))
+}
+
+fn output_filenames(tcx: TyCtxt<'_>, (): ()) -> Arc<OutputFilenames> {
+ let sess = tcx.sess;
let _timer = sess.timer("prepare_outputs");
+ let (_, krate) = &*tcx.resolver_for_lowering(()).borrow();
+ let crate_name = tcx.crate_name(LOCAL_CRATE);
// FIXME: rustdoc passes &[] instead of &krate.attrs here
let outputs = util::build_output_filenames(&krate.attrs, sess);
@@ -679,25 +590,24 @@ pub fn prepare_outputs(
if let Some(ref input_path) = sess.io.input.opt_path() {
if sess.opts.will_create_output_file() {
if output_contains_path(&output_paths, input_path) {
- let reported = sess.emit_err(InputFileWouldBeOverWritten { path: input_path });
- return Err(reported);
+ sess.emit_fatal(errors::InputFileWouldBeOverWritten { path: input_path });
}
if let Some(ref dir_path) = output_conflicts_with_dir(&output_paths) {
- let reported =
- sess.emit_err(GeneratedFileConflictsWithDirectory { input_path, dir_path });
- return Err(reported);
+ sess.emit_fatal(errors::GeneratedFileConflictsWithDirectory {
+ input_path,
+ dir_path,
+ });
}
}
}
if let Some(ref dir) = sess.io.temps_dir {
if fs::create_dir_all(dir).is_err() {
- let reported = sess.emit_err(TempsDirError);
- return Err(reported);
+ sess.emit_fatal(errors::TempsDirError);
}
}
- write_out_deps(sess, boxed_resolver, &outputs, &output_paths);
+ write_out_deps(sess, &*tcx.cstore_untracked(), &outputs, &output_paths);
let only_dep_info = sess.opts.output_types.contains_key(&OutputType::DepInfo)
&& sess.opts.output_types.len() == 1;
@@ -705,19 +615,20 @@ pub fn prepare_outputs(
if !only_dep_info {
if let Some(ref dir) = sess.io.output_dir {
if fs::create_dir_all(dir).is_err() {
- let reported = sess.emit_err(OutDirError);
- return Err(reported);
+ sess.emit_fatal(errors::OutDirError);
}
}
}
- Ok(outputs)
+ outputs.into()
}
pub static DEFAULT_QUERY_PROVIDERS: LazyLock<Providers> = LazyLock::new(|| {
let providers = &mut Providers::default();
providers.analysis = analysis;
providers.hir_crate = rustc_ast_lowering::lower_to_hir;
+ providers.output_filenames = output_filenames;
+ providers.resolver_for_lowering = resolver_for_lowering;
proc_macro_decls::provide(providers);
rustc_const_eval::provide(providers);
rustc_middle::hir::provide(providers);
@@ -747,30 +658,16 @@ pub static DEFAULT_EXTERN_QUERY_PROVIDERS: LazyLock<ExternProviders> = LazyLock:
extern_providers
});
-pub struct QueryContext<'tcx> {
- gcx: &'tcx GlobalCtxt<'tcx>,
-}
-
-impl<'tcx> QueryContext<'tcx> {
- pub fn enter<F, R>(&mut self, f: F) -> R
- where
- F: FnOnce(TyCtxt<'tcx>) -> R,
- {
- let icx = ty::tls::ImplicitCtxt::new(self.gcx);
- ty::tls::enter_context(&icx, |_| f(icx.tcx))
- }
-}
-
pub fn create_global_ctxt<'tcx>(
compiler: &'tcx Compiler,
lint_store: Lrc<LintStore>,
dep_graph: DepGraph,
untracked: Untracked,
queries: &'tcx OnceCell<TcxQueries<'tcx>>,
- global_ctxt: &'tcx OnceCell<GlobalCtxt<'tcx>>,
+ gcx_cell: &'tcx OnceCell<GlobalCtxt<'tcx>>,
arena: &'tcx WorkerLocal<Arena<'tcx>>,
hir_arena: &'tcx WorkerLocal<rustc_hir::Arena<'tcx>>,
-) -> QueryContext<'tcx> {
+) -> &'tcx GlobalCtxt<'tcx> {
// We're constructing the HIR here; we don't care what we will
// read, since we haven't even constructed the *input* to
// incr. comp. yet.
@@ -794,8 +691,8 @@ pub fn create_global_ctxt<'tcx>(
TcxQueries::new(local_providers, extern_providers, query_result_on_disk_cache)
});
- let gcx = sess.time("setup_global_ctxt", || {
- global_ctxt.get_or_init(move || {
+ sess.time("setup_global_ctxt", || {
+ gcx_cell.get_or_init(move || {
TyCtxt::create_global_ctxt(
sess,
lint_store,
@@ -808,9 +705,7 @@ pub fn create_global_ctxt<'tcx>(
rustc_query_impl::query_callbacks(arena),
)
})
- });
-
- QueryContext { gcx }
+ })
}
/// Runs the resolution, type-checking, region checking and other
@@ -900,6 +795,15 @@ fn analysis(tcx: TyCtxt<'_>, (): ()) -> Result<()> {
}
});
+ if tcx.sess.opts.unstable_opts.drop_tracking_mir {
+ tcx.hir().par_body_owners(|def_id| {
+ if let rustc_hir::def::DefKind::Generator = tcx.def_kind(def_id) {
+ tcx.ensure().mir_generator_witnesses(def_id);
+ tcx.ensure().check_generator_obligations(def_id);
+ }
+ });
+ }
+
sess.time("layout_testing", || layout_test::test_layout(tcx));
// Avoid overwhelming user with errors if borrow checking failed.
@@ -975,7 +879,7 @@ pub fn start_codegen<'tcx>(
if tcx.sess.opts.output_types.contains_key(&OutputType::Mir) {
if let Err(error) = rustc_mir_transform::dump_mir::emit_mir(tcx) {
- tcx.sess.emit_err(CantEmitMIR { error });
+ tcx.sess.emit_err(errors::CantEmitMIR { error });
tcx.sess.abort_if_errors();
}
}
diff --git a/compiler/rustc_interface/src/queries.rs b/compiler/rustc_interface/src/queries.rs
index d5a49dd75..a96cc95a3 100644
--- a/compiler/rustc_interface/src/queries.rs
+++ b/compiler/rustc_interface/src/queries.rs
@@ -1,27 +1,29 @@
use crate::errors::{FailedWritingFile, RustcErrorFatal, RustcErrorUnexpectedAnnotation};
use crate::interface::{Compiler, Result};
-use crate::passes::{self, BoxedResolver, QueryContext};
+use crate::passes;
use rustc_ast as ast;
use rustc_codegen_ssa::traits::CodegenBackend;
use rustc_codegen_ssa::CodegenResults;
use rustc_data_structures::steal::Steal;
use rustc_data_structures::svh::Svh;
-use rustc_data_structures::sync::{Lrc, OnceCell, WorkerLocal};
-use rustc_hir::def_id::LOCAL_CRATE;
+use rustc_data_structures::sync::{AppendOnlyVec, Lrc, OnceCell, RwLock, WorkerLocal};
+use rustc_hir::def_id::{CRATE_DEF_ID, LOCAL_CRATE};
+use rustc_hir::definitions::Definitions;
use rustc_incremental::DepGraphFuture;
use rustc_lint::LintStore;
+use rustc_metadata::creader::CStore;
use rustc_middle::arena::Arena;
use rustc_middle::dep_graph::DepGraph;
-use rustc_middle::ty::{self, GlobalCtxt, TyCtxt};
+use rustc_middle::ty::{GlobalCtxt, TyCtxt};
use rustc_query_impl::Queries as TcxQueries;
use rustc_session::config::{self, OutputFilenames, OutputType};
+use rustc_session::cstore::Untracked;
use rustc_session::{output::find_crate_name, Session};
use rustc_span::symbol::sym;
use rustc_span::Symbol;
use std::any::Any;
use std::cell::{RefCell, RefMut};
-use std::rc::Rc;
use std::sync::Arc;
/// Represent the result of a query.
@@ -64,8 +66,8 @@ impl<'a, T> std::ops::DerefMut for QueryResult<'a, T> {
}
}
-impl<'a, 'tcx> QueryResult<'a, QueryContext<'tcx>> {
- pub fn enter<T>(mut self, f: impl FnOnce(TyCtxt<'tcx>) -> T) -> T {
+impl<'a, 'tcx> QueryResult<'a, &'tcx GlobalCtxt<'tcx>> {
+ pub fn enter<T>(&mut self, f: impl FnOnce(TyCtxt<'tcx>) -> T) -> T {
(*self.0).get_mut().enter(f)
}
}
@@ -78,7 +80,7 @@ impl<T> Default for Query<T> {
pub struct Queries<'tcx> {
compiler: &'tcx Compiler,
- gcx: OnceCell<GlobalCtxt<'tcx>>,
+ gcx_cell: OnceCell<GlobalCtxt<'tcx>>,
queries: OnceCell<TcxQueries<'tcx>>,
arena: WorkerLocal<Arena<'tcx>>,
@@ -88,9 +90,9 @@ pub struct Queries<'tcx> {
parse: Query<ast::Crate>,
crate_name: Query<Symbol>,
register_plugins: Query<(ast::Crate, Lrc<LintStore>)>,
- expansion: Query<(Lrc<ast::Crate>, Rc<RefCell<BoxedResolver>>, Lrc<LintStore>)>,
dep_graph: Query<DepGraph>,
- global_ctxt: Query<QueryContext<'tcx>>,
+ // This just points to what's in `gcx_cell`.
+ gcx: Query<&'tcx GlobalCtxt<'tcx>>,
ongoing_codegen: Query<Box<dyn Any>>,
}
@@ -98,7 +100,7 @@ impl<'tcx> Queries<'tcx> {
pub fn new(compiler: &'tcx Compiler) -> Queries<'tcx> {
Queries {
compiler,
- gcx: OnceCell::new(),
+ gcx_cell: OnceCell::new(),
queries: OnceCell::new(),
arena: WorkerLocal::new(|_| Arena::default()),
hir_arena: WorkerLocal::new(|_| rustc_hir::Arena::default()),
@@ -106,9 +108,8 @@ impl<'tcx> Queries<'tcx> {
parse: Default::default(),
crate_name: Default::default(),
register_plugins: Default::default(),
- expansion: Default::default(),
dep_graph: Default::default(),
- global_ctxt: Default::default(),
+ gcx: Default::default(),
ongoing_codegen: Default::default(),
}
}
@@ -168,29 +169,6 @@ impl<'tcx> Queries<'tcx> {
})
}
- pub fn expansion(
- &self,
- ) -> Result<QueryResult<'_, (Lrc<ast::Crate>, Rc<RefCell<BoxedResolver>>, Lrc<LintStore>)>>
- {
- trace!("expansion");
- self.expansion.compute(|| {
- let crate_name = *self.crate_name()?.borrow();
- let (krate, lint_store) = self.register_plugins()?.steal();
- let _timer = self.session().timer("configure_and_expand");
- let sess = self.session();
- let mut resolver = passes::create_resolver(
- sess.clone(),
- self.codegen_backend().metadata_loader(),
- &krate,
- crate_name,
- );
- let krate = resolver.access(|resolver| {
- passes::configure_and_expand(sess, &lint_store, krate, crate_name, resolver)
- })?;
- Ok((Lrc::new(krate), Rc::new(RefCell::new(resolver)), lint_store))
- })
- }
-
fn dep_graph(&self) -> Result<QueryResult<'_, DepGraph>> {
self.dep_graph.compute(|| {
let sess = self.session();
@@ -207,40 +185,41 @@ impl<'tcx> Queries<'tcx> {
})
}
- pub fn global_ctxt(&'tcx self) -> Result<QueryResult<'_, QueryContext<'tcx>>> {
- self.global_ctxt.compute(|| {
+ pub fn global_ctxt(&'tcx self) -> Result<QueryResult<'_, &'tcx GlobalCtxt<'tcx>>> {
+ self.gcx.compute(|| {
let crate_name = *self.crate_name()?.borrow();
- let (krate, resolver, lint_store) = self.expansion()?.steal();
+ let (krate, lint_store) = self.register_plugins()?.steal();
- let outputs = passes::prepare_outputs(self.session(), &krate, &resolver, crate_name)?;
+ let sess = self.session();
- let ty::ResolverOutputs {
- untracked,
- global_ctxt: untracked_resolutions,
- ast_lowering: untracked_resolver_for_lowering,
- } = BoxedResolver::to_resolver_outputs(resolver);
+ let cstore = RwLock::new(Box::new(CStore::new(sess)) as _);
+ let definitions = RwLock::new(Definitions::new(sess.local_stable_crate_id()));
+ let source_span = AppendOnlyVec::new();
+ let _id = source_span.push(krate.spans.inner_span);
+ debug_assert_eq!(_id, CRATE_DEF_ID);
+ let untracked = Untracked { cstore, source_span, definitions };
- let mut qcx = passes::create_global_ctxt(
+ let qcx = passes::create_global_ctxt(
self.compiler,
lint_store,
self.dep_graph()?.steal(),
untracked,
&self.queries,
- &self.gcx,
+ &self.gcx_cell,
&self.arena,
&self.hir_arena,
);
qcx.enter(|tcx| {
+ let feed = tcx.feed_local_crate();
+ feed.crate_name(crate_name);
+
let feed = tcx.feed_unit_query();
- feed.resolver_for_lowering(
- tcx.arena.alloc(Steal::new((untracked_resolver_for_lowering, krate))),
+ feed.crate_for_resolver(tcx.arena.alloc(Steal::new(krate)));
+ feed.metadata_loader(
+ tcx.arena.alloc(Steal::new(self.codegen_backend().metadata_loader())),
);
- feed.resolutions(tcx.arena.alloc(untracked_resolutions));
- feed.output_filenames(tcx.arena.alloc(std::sync::Arc::new(outputs)));
feed.features_query(tcx.sess.features_untracked());
- let feed = tcx.feed_local_crate();
- feed.crate_name(crate_name);
});
Ok(qcx)
})
@@ -390,7 +369,7 @@ impl Compiler {
// NOTE: intentionally does not compute the global context if it hasn't been built yet,
// since that likely means there was a parse error.
- if let Some(Ok(gcx)) = &mut *queries.global_ctxt.result.borrow_mut() {
+ if let Some(Ok(gcx)) = &mut *queries.gcx.result.borrow_mut() {
let gcx = gcx.get_mut();
// We assume that no queries are run past here. If there are new queries
// after this point, they'll show up as "<unknown>" in self-profiling data.
diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs
index f94bc4d4c..18d84a702 100644
--- a/compiler/rustc_interface/src/tests.rs
+++ b/compiler/rustc_interface/src/tests.rs
@@ -5,6 +5,7 @@ use rustc_data_structures::fx::FxHashSet;
use rustc_errors::{emitter::HumanReadableErrorType, registry, ColorConfig};
use rustc_session::config::rustc_optgroups;
use rustc_session::config::Input;
+use rustc_session::config::InstrumentXRay;
use rustc_session::config::TraitSolver;
use rustc_session::config::{build_configuration, build_session_options, to_crate_config};
use rustc_session::config::{
@@ -49,7 +50,7 @@ fn mk_session(matches: getopts::Matches) -> (Session, CfgSpecs) {
output_file: None,
temps_dir,
};
- let sess = build_session(sessopts, io, None, registry, Default::default(), None, None);
+ let sess = build_session(sessopts, io, None, registry, vec![], Default::default(), None, None);
(sess, cfg)
}
@@ -690,7 +691,6 @@ fn test_unstable_options_tracking_hash() {
untracked!(proc_macro_execution_strategy, ProcMacroExecutionStrategy::CrossThread);
untracked!(profile_closures, true);
untracked!(query_dep_graph, true);
- untracked!(save_analysis, true);
untracked!(self_profile, SwitchWithOptPath::Enabled(None));
untracked!(self_profile_events, Some(vec![String::new()]));
untracked!(span_debug, true);
@@ -755,10 +755,11 @@ fn test_unstable_options_tracking_hash() {
tracked!(inline_mir_threshold, Some(123));
tracked!(instrument_coverage, Some(InstrumentCoverage::All));
tracked!(instrument_mcount, true);
+ tracked!(instrument_xray, Some(InstrumentXRay::default()));
+ tracked!(link_directives, false);
tracked!(link_only, true);
tracked!(llvm_plugins, vec![String::from("plugin_name")]);
tracked!(location_detail, LocationDetail { file: true, line: false, column: false });
- tracked!(log_backtrace, Some("filter".to_string()));
tracked!(maximal_hir_to_mir_coverage, true);
tracked!(merge_functions, Some(MergeFunctions::Disabled));
tracked!(mir_emit_retag, true);
@@ -776,7 +777,6 @@ fn test_unstable_options_tracking_hash() {
tracked!(packed_bundled_libs, true);
tracked!(panic_abort_tests, true);
tracked!(panic_in_drop, PanicStrategy::Abort);
- tracked!(pick_stable_methods_before_any_unstable, false);
tracked!(plt, Some(true));
tracked!(polonius, true);
tracked!(precise_enum_drop_elaboration, false);
@@ -802,6 +802,7 @@ fn test_unstable_options_tracking_hash() {
tracked!(teach, true);
tracked!(thinlto, Some(true));
tracked!(thir_unsafeck, true);
+ tracked!(tiny_const_eval_limit, true);
tracked!(tls_model, Some(TlsModel::GeneralDynamic));
tracked!(trait_solver, TraitSolver::Chalk);
tracked!(translate_remapped_path_to_local_path, false);
diff --git a/compiler/rustc_interface/src/util.rs b/compiler/rustc_interface/src/util.rs
index 54363e07b..e5d2fb2ea 100644
--- a/compiler/rustc_interface/src/util.rs
+++ b/compiler/rustc_interface/src/util.rs
@@ -1,3 +1,4 @@
+use crate::errors;
use info;
use libloading::Library;
use rustc_ast as ast;
@@ -13,8 +14,8 @@ use rustc_session::filesearch::sysroot_candidates;
use rustc_session::lint::{self, BuiltinLintDiagnostics, LintBuffer};
use rustc_session::parse::CrateConfig;
use rustc_session::{early_error, filesearch, output, Session};
+use rustc_span::edit_distance::find_best_match_for_name;
use rustc_span::edition::Edition;
-use rustc_span::lev_distance::find_best_match_for_name;
use rustc_span::source_map::FileLoader;
use rustc_span::symbol::{sym, Symbol};
use session::CompilerIO;
@@ -58,6 +59,7 @@ pub fn create_session(
sopts: config::Options,
cfg: FxHashSet<(String, Option<String>)>,
check_cfg: CheckCfg,
+ locale_resources: &'static [&'static str],
file_loader: Option<Box<dyn FileLoader + Send + Sync + 'static>>,
io: CompilerIO,
lint_caps: FxHashMap<lint::LintId, lint::Level>,
@@ -88,11 +90,15 @@ pub fn create_session(
}
};
+ let mut locale_resources = Vec::from(locale_resources);
+ locale_resources.push(codegen_backend.locale_resource());
+
let mut sess = session::build_session(
sopts,
io,
bundle,
descriptions,
+ locale_resources,
lint_caps,
file_loader,
target_override,
@@ -472,16 +478,15 @@ pub fn collect_crate_types(session: &Session, attrs: &[ast::Attribute]) -> Vec<C
}
base.retain(|crate_type| {
- let res = !output::invalid_output_for_target(session, *crate_type);
-
- if !res {
- session.warn(&format!(
- "dropping unsupported crate type `{}` for target `{}`",
- *crate_type, session.opts.target_triple
- ));
+ if output::invalid_output_for_target(session, *crate_type) {
+ session.emit_warning(errors::UnsupportedCrateTypeForTarget {
+ crate_type: *crate_type,
+ target_triple: &session.opts.target_triple,
+ });
+ false
+ } else {
+ true
}
-
- res
});
base
@@ -517,19 +522,16 @@ pub fn build_output_filenames(attrs: &[ast::Attribute], sess: &Session) -> Outpu
let unnamed_output_types =
sess.opts.output_types.values().filter(|a| a.is_none()).count();
let ofile = if unnamed_output_types > 1 {
- sess.warn(
- "due to multiple output types requested, the explicitly specified \
- output file name will be adapted for each output type",
- );
+ sess.emit_warning(errors::MultipleOutputTypesAdaption);
None
} else {
if !sess.opts.cg.extra_filename.is_empty() {
- sess.warn("ignoring -C extra-filename flag due to -o flag");
+ sess.emit_warning(errors::IgnoringExtraFilename);
}
Some(out_file.clone())
};
if sess.io.output_dir != None {
- sess.warn("ignoring --out-dir flag due to -o flag");
+ sess.emit_warning(errors::IgnoringOutDir);
}
OutputFilenames::new(
diff --git a/compiler/rustc_lexer/src/lib.rs b/compiler/rustc_lexer/src/lib.rs
index 6e815863d..b3f4b5cd5 100644
--- a/compiler/rustc_lexer/src/lib.rs
+++ b/compiler/rustc_lexer/src/lib.rs
@@ -166,15 +166,17 @@ pub enum DocStyle {
Inner,
}
-// Note that the suffix is *not* considered when deciding the `LiteralKind` in
-// this type. This means that float literals like `1f32` are classified by this
-// type as `Int`. (Compare against `rustc_ast::token::LitKind` and
-// `rustc_ast::ast::LitKind.)
+/// Enum representing the literal types supported by the lexer.
+///
+/// Note that the suffix is *not* considered when deciding the `LiteralKind` in
+/// this type. This means that float literals like `1f32` are classified by this
+/// type as `Int`. (Compare against `rustc_ast::token::LitKind` and
+/// `rustc_ast::ast::LitKind`).
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)]
pub enum LiteralKind {
/// "12_u8", "0o100", "0b120i99", "1f32".
Int { base: Base, empty_int: bool },
- /// "12.34f32", "1e3", but not "1f32`.
+ /// "12.34f32", "1e3", but not "1f32".
Float { base: Base, empty_exponent: bool },
/// "'a'", "'\\'", "'''", "';"
Char { terminated: bool },
diff --git a/compiler/rustc_error_messages/locales/en-US/lint.ftl b/compiler/rustc_lint/locales/en-US.ftl
index d63ff77d8..68e62c978 100644
--- a/compiler/rustc_error_messages/locales/en-US/lint.ftl
+++ b/compiler/rustc_lint/locales/en-US.ftl
@@ -24,6 +24,13 @@ lint_for_loops_over_fallibles =
.use_while_let = to check pattern in a loop use `while let`
.use_question_mark = consider unwrapping the `Result` with `?` to iterate over its contents
+lint_map_unit_fn = `Iterator::map` call that discard the iterator's values
+ .note = `Iterator::map`, like many of the methods on `Iterator`, gets executed lazily, meaning that its effects won't be visible until it is iterated
+ .function_label = this function returns `()`, which is likely not what you wanted
+ .argument_label = called `Iterator::map` with callable that returns `()`
+ .map_label = after this call to map, the resulting iterator is `impl Iterator<Item = ()>`, which means the only information carried by the iterator is the number of items
+ .suggestion = you might have meant to use `Iterator::for_each`
+
lint_non_binding_let_on_sync_lock =
non-binding let on a synchronization lock
@@ -100,6 +107,8 @@ lint_cstring_ptr = getting the inner pointer of a temporary `CString`
.note = pointers do not have a lifetime; when calling `as_ptr` the `CString` will be deallocated at the end of the statement because nothing is referencing it as far as the type system is concerned
.help = for more information, see https://doc.rust-lang.org/reference/destructors.html
+lint_multple_supertrait_upcastable = `{$ident}` is object-safe and has multiple supertraits
+
lint_identifier_non_ascii_char = identifier contains non-ASCII characters
lint_identifier_uncommon_codepoints = identifier contains uncommon Unicode codepoints
@@ -307,6 +316,7 @@ lint_unused_generator =
.note = generators are lazy and do nothing unless resumed
lint_unused_def = unused {$pre}`{$def}`{$post} that must be used
+ .suggestion = use `let _ = ...` to ignore the resulting value
lint_path_statement_drop = path statement drops value
.suggestion = use `drop` to clarify the intent
diff --git a/compiler/rustc_lint/src/array_into_iter.rs b/compiler/rustc_lint/src/array_into_iter.rs
index 3593f141d..bccb0a94e 100644
--- a/compiler/rustc_lint/src/array_into_iter.rs
+++ b/compiler/rustc_lint/src/array_into_iter.rs
@@ -1,5 +1,7 @@
-use crate::lints::{ArrayIntoIterDiag, ArrayIntoIterDiagSub};
-use crate::{LateContext, LateLintPass, LintContext};
+use crate::{
+ lints::{ArrayIntoIterDiag, ArrayIntoIterDiagSub},
+ LateContext, LateLintPass, LintContext,
+};
use rustc_hir as hir;
use rustc_middle::ty;
use rustc_middle::ty::adjustment::{Adjust, Adjustment};
diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs
index fe188162c..5b2100b5d 100644
--- a/compiler/rustc_lint/src/builtin.rs
+++ b/compiler/rustc_lint/src/builtin.rs
@@ -20,6 +20,7 @@
//! If you define a new `LateLintPass`, you will also need to add it to the
//! `late_lint_methods!` invocation in `lib.rs`.
+use crate::fluent_generated as fluent;
use crate::{
errors::BuiltinEllpisisInclusiveRangePatterns,
lints::{
@@ -50,15 +51,13 @@ use rustc_ast::{self as ast, *};
use rustc_ast_pretty::pprust::{self, expr_to_string};
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_data_structures::stack::ensure_sufficient_stack;
-use rustc_errors::{fluent, Applicability, DecorateLint, MultiSpan};
+use rustc_errors::{Applicability, DecorateLint, MultiSpan};
use rustc_feature::{deprecated_attributes, AttributeGate, BuiltinAttribute, GateIssue, Stability};
use rustc_hir as hir;
use rustc_hir::def::{DefKind, Res};
use rustc_hir::def_id::{DefId, LocalDefId, LocalDefIdSet, CRATE_DEF_ID};
use rustc_hir::intravisit::FnKind as HirFnKind;
-use rustc_hir::{
- Body, FnDecl, ForeignItemKind, GenericParamKind, HirId, Node, PatKind, PredicateOrigin,
-};
+use rustc_hir::{Body, FnDecl, ForeignItemKind, GenericParamKind, Node, PatKind, PredicateOrigin};
use rustc_index::vec::Idx;
use rustc_middle::lint::in_external_macro;
use rustc_middle::ty::layout::{LayoutError, LayoutOf};
@@ -185,7 +184,7 @@ impl<'tcx> LateLintPass<'tcx> for BoxPointers {
| hir::ItemKind::Enum(..)
| hir::ItemKind::Struct(..)
| hir::ItemKind::Union(..) => {
- self.check_heap_type(cx, it.span, cx.tcx.type_of(it.owner_id))
+ self.check_heap_type(cx, it.span, cx.tcx.type_of(it.owner_id).subst_identity())
}
_ => (),
}
@@ -194,7 +193,11 @@ impl<'tcx> LateLintPass<'tcx> for BoxPointers {
match it.kind {
hir::ItemKind::Struct(ref struct_def, _) | hir::ItemKind::Union(ref struct_def, _) => {
for field in struct_def.fields() {
- self.check_heap_type(cx, field.span, cx.tcx.type_of(field.def_id));
+ self.check_heap_type(
+ cx,
+ field.span,
+ cx.tcx.type_of(field.def_id).subst_identity(),
+ );
}
}
_ => (),
@@ -582,26 +585,28 @@ impl<'tcx> LateLintPass<'tcx> for MissingDoc {
}
fn check_impl_item(&mut self, cx: &LateContext<'_>, impl_item: &hir::ImplItem<'_>) {
- // If the method is an impl for a trait, don't doc.
- if method_context(cx, impl_item.hir_id()) == MethodLateContext::TraitImpl {
- return;
- }
-
- // If the method is an impl for an item with docs_hidden, don't doc.
- if method_context(cx, impl_item.hir_id()) == MethodLateContext::PlainImpl {
- let parent = cx.tcx.hir().get_parent_item(impl_item.hir_id());
- let impl_ty = cx.tcx.type_of(parent);
- let outerdef = match impl_ty.kind() {
- ty::Adt(def, _) => Some(def.did()),
- ty::Foreign(def_id) => Some(*def_id),
- _ => None,
- };
- let is_hidden = match outerdef {
- Some(id) => cx.tcx.is_doc_hidden(id),
- None => false,
- };
- if is_hidden {
- return;
+ let context = method_context(cx, impl_item.owner_id.def_id);
+
+ match context {
+ // If the method is an impl for a trait, don't doc.
+ MethodLateContext::TraitImpl => return,
+ MethodLateContext::TraitAutoImpl => {}
+ // If the method is an impl for an item with docs_hidden, don't doc.
+ MethodLateContext::PlainImpl => {
+ let parent = cx.tcx.hir().get_parent_item(impl_item.hir_id());
+ let impl_ty = cx.tcx.type_of(parent).subst_identity();
+ let outerdef = match impl_ty.kind() {
+ ty::Adt(def, _) => Some(def.did()),
+ ty::Foreign(def_id) => Some(*def_id),
+ _ => None,
+ };
+ let is_hidden = match outerdef {
+ Some(id) => cx.tcx.is_doc_hidden(id),
+ None => false,
+ };
+ if is_hidden {
+ return;
+ }
}
}
@@ -672,21 +677,21 @@ impl<'tcx> LateLintPass<'tcx> for MissingCopyImplementations {
return;
}
let def = cx.tcx.adt_def(item.owner_id);
- (def, cx.tcx.mk_adt(def, cx.tcx.intern_substs(&[])))
+ (def, cx.tcx.mk_adt(def, ty::List::empty()))
}
hir::ItemKind::Union(_, ref ast_generics) => {
if !ast_generics.params.is_empty() {
return;
}
let def = cx.tcx.adt_def(item.owner_id);
- (def, cx.tcx.mk_adt(def, cx.tcx.intern_substs(&[])))
+ (def, cx.tcx.mk_adt(def, ty::List::empty()))
}
hir::ItemKind::Enum(_, ref ast_generics) => {
if !ast_generics.params.is_empty() {
return;
}
let def = cx.tcx.adt_def(item.owner_id);
- (def, cx.tcx.mk_adt(def, cx.tcx.intern_substs(&[])))
+ (def, cx.tcx.mk_adt(def, ty::List::empty()))
}
_ => return,
};
@@ -698,7 +703,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingCopyImplementations {
// and recommending Copy might be a bad idea.
for field in def.all_fields() {
let did = field.did;
- if cx.tcx.type_of(did).is_unsafe_ptr() {
+ if cx.tcx.type_of(did).subst_identity().is_unsafe_ptr() {
return;
}
}
@@ -732,7 +737,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingCopyImplementations {
cx.tcx,
param_env,
ty,
- traits::ObligationCause::misc(item.span, item.hir_id()),
+ traits::ObligationCause::misc(item.span, item.owner_id.def_id),
)
.is_ok()
{
@@ -798,7 +803,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingDebugImplementations {
if self.impling_types.is_none() {
let mut impls = LocalDefIdSet::default();
cx.tcx.for_each_impl(debug, |d| {
- if let Some(ty_def) = cx.tcx.type_of(d).ty_adt_def() {
+ if let Some(ty_def) = cx.tcx.type_of(d).subst_identity().ty_adt_def() {
if let Some(def_id) = ty_def.did().as_local() {
impls.insert(def_id);
}
@@ -1283,7 +1288,7 @@ declare_lint! {
}
declare_lint_pass!(
- /// Explains corresponding feature flag must be enabled for the `#[track_caller] attribute to
+ /// Explains corresponding feature flag must be enabled for the `#[track_caller]` attribute to
/// do anything
UngatedAsyncFnTrackCaller => [UNGATED_ASYNC_FN_TRACK_CALLER]
);
@@ -1296,19 +1301,18 @@ impl<'tcx> LateLintPass<'tcx> for UngatedAsyncFnTrackCaller {
_: &'tcx FnDecl<'_>,
_: &'tcx Body<'_>,
span: Span,
- hir_id: HirId,
+ def_id: LocalDefId,
) {
if fn_kind.asyncness() == IsAsync::Async
&& !cx.tcx.features().closure_track_caller
- && let attrs = cx.tcx.hir().attrs(hir_id)
// Now, check if the function has the `#[track_caller]` attribute
- && let Some(attr) = attrs.iter().find(|attr| attr.has_name(sym::track_caller))
- {
- cx.emit_spanned_lint(UNGATED_ASYNC_FN_TRACK_CALLER, attr.span, BuiltinUngatedAsyncFnTrackCaller {
- label: span,
- parse_sess: &cx.tcx.sess.parse_sess,
- });
- }
+ && let Some(attr) = cx.tcx.get_attr(def_id.to_def_id(), sym::track_caller)
+ {
+ cx.emit_spanned_lint(UNGATED_ASYNC_FN_TRACK_CALLER, attr.span, BuiltinUngatedAsyncFnTrackCaller {
+ label: span,
+ parse_sess: &cx.tcx.sess.parse_sess,
+ });
+ }
}
}
@@ -1580,7 +1584,7 @@ declare_lint_pass!(
impl<'tcx> LateLintPass<'tcx> for TrivialConstraints {
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'tcx>) {
- use rustc_middle::ty::visit::TypeVisitable;
+ use rustc_middle::ty::visit::TypeVisitableExt;
use rustc_middle::ty::Clause;
use rustc_middle::ty::PredicateKind::*;
@@ -1592,15 +1596,19 @@ impl<'tcx> LateLintPass<'tcx> for TrivialConstraints {
Clause(Clause::TypeOutlives(..)) |
Clause(Clause::RegionOutlives(..)) => "lifetime",
+ // `ConstArgHasType` is never global as `ct` is always a param
+ Clause(Clause::ConstArgHasType(..)) |
// Ignore projections, as they can only be global
// if the trait bound is global
Clause(Clause::Projection(..)) |
+ AliasEq(..) |
// Ignore bounds that a user can't type
WellFormed(..) |
ObjectSafe(..) |
ClosureKind(..) |
Subtype(..) |
Coerce(..) |
+ // FIXME(generic_const_exprs): `ConstEvaluatable` can be written
ConstEvaluatable(..) |
ConstEquate(..) |
Ambiguous |
@@ -2006,7 +2014,7 @@ impl ExplicitOutlivesRequirements {
inferred_outlives: &[ty::Region<'tcx>],
predicate_span: Span,
) -> Vec<(usize, Span)> {
- use rustc_middle::middle::resolve_lifetime::Region;
+ use rustc_middle::middle::resolve_bound_vars::ResolvedArg;
bounds
.iter()
@@ -2016,8 +2024,8 @@ impl ExplicitOutlivesRequirements {
return None;
};
- let is_inferred = match tcx.named_region(lifetime.hir_id) {
- Some(Region::EarlyBound(def_id)) => inferred_outlives
+ let is_inferred = match tcx.named_bound_var(lifetime.hir_id) {
+ Some(ResolvedArg::EarlyBound(def_id)) => inferred_outlives
.iter()
.any(|r| matches!(**r, ty::ReEarlyBound(ebr) if { ebr.def_id == def_id })),
_ => false,
@@ -2096,7 +2104,7 @@ impl ExplicitOutlivesRequirements {
impl<'tcx> LateLintPass<'tcx> for ExplicitOutlivesRequirements {
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'_>) {
- use rustc_middle::middle::resolve_lifetime::Region;
+ use rustc_middle::middle::resolve_bound_vars::ResolvedArg;
let def_id = item.owner_id.def_id;
if let hir::ItemKind::Struct(_, hir_generics)
@@ -2119,8 +2127,8 @@ impl<'tcx> LateLintPass<'tcx> for ExplicitOutlivesRequirements {
let (relevant_lifetimes, bounds, predicate_span, in_where_clause) =
match where_predicate {
hir::WherePredicate::RegionPredicate(predicate) => {
- if let Some(Region::EarlyBound(region_def_id)) =
- cx.tcx.named_region(predicate.lifetime.hir_id)
+ if let Some(ResolvedArg::EarlyBound(region_def_id)) =
+ cx.tcx.named_bound_var(predicate.lifetime.hir_id)
{
(
Self::lifetimes_outliving_lifetime(
@@ -2175,13 +2183,31 @@ impl<'tcx> LateLintPass<'tcx> for ExplicitOutlivesRequirements {
dropped_predicate_count += 1;
}
- if drop_predicate && !in_where_clause {
- lint_spans.push(predicate_span);
- } else if drop_predicate && i + 1 < num_predicates {
- // If all the bounds on a predicate were inferable and there are
- // further predicates, we want to eat the trailing comma.
- let next_predicate_span = hir_generics.predicates[i + 1].span();
- where_lint_spans.push(predicate_span.to(next_predicate_span.shrink_to_lo()));
+ if drop_predicate {
+ if !in_where_clause {
+ lint_spans.push(predicate_span);
+ } else if predicate_span.from_expansion() {
+ // Don't try to extend the span if it comes from a macro expansion.
+ where_lint_spans.push(predicate_span);
+ } else if i + 1 < num_predicates {
+ // If all the bounds on a predicate were inferable and there are
+ // further predicates, we want to eat the trailing comma.
+ let next_predicate_span = hir_generics.predicates[i + 1].span();
+ if next_predicate_span.from_expansion() {
+ where_lint_spans.push(predicate_span);
+ } else {
+ where_lint_spans
+ .push(predicate_span.to(next_predicate_span.shrink_to_lo()));
+ }
+ } else {
+ // Eat the optional trailing comma after the last predicate.
+ let where_span = hir_generics.where_clause_span;
+ if where_span.from_expansion() {
+ where_lint_spans.push(predicate_span);
+ } else {
+ where_lint_spans.push(predicate_span.to(where_span.shrink_to_hi()));
+ }
+ }
} else {
where_lint_spans.extend(self.consolidate_outlives_bound_spans(
predicate_span.shrink_to_lo(),
@@ -2225,6 +2251,11 @@ impl<'tcx> LateLintPass<'tcx> for ExplicitOutlivesRequirements {
Applicability::MaybeIncorrect
};
+ // Due to macros, there might be several predicates with the same span
+ // and we only want to suggest removing them once.
+ lint_spans.sort_unstable();
+ lint_spans.dedup();
+
cx.emit_spanned_lint(
EXPLICIT_OUTLIVES_REQUIREMENTS,
lint_spans.clone(),
@@ -2284,11 +2315,8 @@ impl EarlyLintPass for IncompleteFeatures {
.for_each(|(&name, &span)| {
let note = rustc_feature::find_feature_issue(name, GateIssue::Language)
.map(|n| BuiltinIncompleteFeaturesNote { n });
- let help = if HAS_MIN_FEATURES.contains(&name) {
- Some(BuiltinIncompleteFeaturesHelp)
- } else {
- None
- };
+ let help =
+ HAS_MIN_FEATURES.contains(&name).then_some(BuiltinIncompleteFeaturesHelp);
cx.emit_spanned_lint(
INCOMPLETE_FEATURES,
span,
@@ -2581,7 +2609,7 @@ impl<'tcx> LateLintPass<'tcx> for InvalidValue {
ty.tuple_fields().iter().find_map(|field| ty_find_init_error(cx, field, init))
}
Array(ty, len) => {
- if matches!(len.try_eval_usize(cx.tcx, cx.param_env), Some(v) if v > 0) {
+ if matches!(len.try_eval_target_usize(cx.tcx, cx.param_env), Some(v) if v > 0) {
// Array length known at array non-empty -- recurse.
ty_find_init_error(cx, *ty, init)
} else {
@@ -2608,7 +2636,13 @@ impl<'tcx> LateLintPass<'tcx> for InvalidValue {
cx.emit_spanned_lint(
INVALID_VALUE,
expr.span,
- BuiltinUnpermittedTypeInit { msg, ty: conjured_ty, label: expr.span, sub },
+ BuiltinUnpermittedTypeInit {
+ msg,
+ ty: conjured_ty,
+ label: expr.span,
+ sub,
+ tcx: cx.tcx,
+ },
);
}
}
@@ -2661,7 +2695,7 @@ pub struct ClashingExternDeclarations {
/// the symbol should be reported as a clashing declaration.
// FIXME: Technically, we could just store a &'tcx str here without issue; however, the
// `impl_lint_pass` macro doesn't currently support lints parametric over a lifetime.
- seen_decls: FxHashMap<Symbol, HirId>,
+ seen_decls: FxHashMap<Symbol, hir::OwnerId>,
}
/// Differentiate between whether the name for an extern decl came from the link_name attribute or
@@ -2687,19 +2721,20 @@ impl ClashingExternDeclarations {
pub(crate) fn new() -> Self {
ClashingExternDeclarations { seen_decls: FxHashMap::default() }
}
+
/// Insert a new foreign item into the seen set. If a symbol with the same name already exists
/// for the item, return its HirId without updating the set.
- fn insert(&mut self, tcx: TyCtxt<'_>, fi: &hir::ForeignItem<'_>) -> Option<HirId> {
+ fn insert(&mut self, tcx: TyCtxt<'_>, fi: &hir::ForeignItem<'_>) -> Option<hir::OwnerId> {
let did = fi.owner_id.to_def_id();
let instance = Instance::new(did, ty::List::identity_for_item(tcx, did));
let name = Symbol::intern(tcx.symbol_name(instance).name);
- if let Some(&hir_id) = self.seen_decls.get(&name) {
+ if let Some(&existing_id) = self.seen_decls.get(&name) {
// Avoid updating the map with the new entry when we do find a collision. We want to
// make sure we're always pointing to the first definition as the previous declaration.
// This lets us avoid emitting "knock-on" diagnostics.
- Some(hir_id)
+ Some(existing_id)
} else {
- self.seen_decls.insert(name, fi.hir_id())
+ self.seen_decls.insert(name, fi.owner_id)
}
}
@@ -2830,8 +2865,8 @@ impl ClashingExternDeclarations {
structurally_same_type_impl(
seen_types,
cx,
- tcx.type_of(a_did),
- tcx.type_of(b_did),
+ tcx.type_of(a_did).subst_identity(),
+ tcx.type_of(b_did).subst_identity(),
ckind,
)
},
@@ -2926,16 +2961,16 @@ impl ClashingExternDeclarations {
impl_lint_pass!(ClashingExternDeclarations => [CLASHING_EXTERN_DECLARATIONS]);
impl<'tcx> LateLintPass<'tcx> for ClashingExternDeclarations {
+ #[instrument(level = "trace", skip(self, cx))]
fn check_foreign_item(&mut self, cx: &LateContext<'tcx>, this_fi: &hir::ForeignItem<'_>) {
- trace!("ClashingExternDeclarations: check_foreign_item: {:?}", this_fi);
if let ForeignItemKind::Fn(..) = this_fi.kind {
let tcx = cx.tcx;
- if let Some(existing_hid) = self.insert(tcx, this_fi) {
- let existing_decl_ty = tcx.type_of(tcx.hir().local_def_id(existing_hid));
- let this_decl_ty = tcx.type_of(this_fi.owner_id);
+ if let Some(existing_did) = self.insert(tcx, this_fi) {
+ let existing_decl_ty = tcx.type_of(existing_did).skip_binder();
+ let this_decl_ty = tcx.type_of(this_fi.owner_id).subst_identity();
debug!(
"ClashingExternDeclarations: Comparing existing {:?}: {:?} to this {:?}: {:?}",
- existing_hid, existing_decl_ty, this_fi.owner_id, this_decl_ty
+ existing_did, existing_decl_ty, this_fi.owner_id, this_decl_ty
);
// Check that the declarations match.
if !Self::structurally_same_type(
@@ -2944,7 +2979,7 @@ impl<'tcx> LateLintPass<'tcx> for ClashingExternDeclarations {
this_decl_ty,
CItemKind::Declaration,
) {
- let orig_fi = tcx.hir().expect_foreign_item(existing_hid.expect_owner());
+ let orig_fi = tcx.hir().expect_foreign_item(existing_did);
let orig = Self::name_of_extern_decl(tcx, orig_fi);
// We want to ensure that we use spans for both decls that include where the
diff --git a/compiler/rustc_lint/src/context.rs b/compiler/rustc_lint/src/context.rs
index 8046cc21c..f5a711315 100644
--- a/compiler/rustc_lint/src/context.rs
+++ b/compiler/rustc_lint/src/context.rs
@@ -39,7 +39,7 @@ use rustc_middle::ty::{self, print::Printer, subst::GenericArg, RegisteredTools,
use rustc_session::lint::{BuiltinLintDiagnostics, LintExpectationId};
use rustc_session::lint::{FutureIncompatibleInfo, Level, Lint, LintBuffer, LintId};
use rustc_session::Session;
-use rustc_span::lev_distance::find_best_match_for_name;
+use rustc_span::edit_distance::find_best_match_for_name;
use rustc_span::symbol::{sym, Ident, Symbol};
use rustc_span::{BytePos, Span};
use rustc_target::abi;
@@ -487,7 +487,7 @@ impl LintStore {
let mut groups: Vec<_> = self
.lint_groups
.iter()
- .filter_map(|(k, LintGroup { depr, .. })| if depr.is_none() { Some(k) } else { None })
+ .filter_map(|(k, LintGroup { depr, .. })| depr.is_none().then_some(k))
.collect();
groups.sort();
let groups = groups.iter().map(|k| Symbol::intern(k));
@@ -837,9 +837,17 @@ pub trait LintContext: Sized {
(use_span, "'_".to_owned())
};
debug!(?deletion_span, ?use_span);
+
+ // issue 107998 for the case such as a wrong function pointer type
+ // `deletion_span` is empty and there is no need to report lifetime uses here
+ let suggestions = if deletion_span.is_empty() {
+ vec![(use_span, replace_lt)]
+ } else {
+ vec![(deletion_span, String::new()), (use_span, replace_lt)]
+ };
db.multipart_suggestion(
msg,
- vec![(deletion_span, String::new()), (use_span, replace_lt)],
+ suggestions,
Applicability::MachineApplicable,
);
}
@@ -882,6 +890,26 @@ pub trait LintContext: Sized {
);
}
}
+ BuiltinLintDiagnostics::ByteSliceInPackedStructWithDerive => {
+ db.help("consider implementing the trait by hand, or remove the `packed` attribute");
+ }
+ BuiltinLintDiagnostics::UnusedExternCrate { removal_span }=> {
+ db.span_suggestion(
+ removal_span,
+ "remove it",
+ "",
+ Applicability::MachineApplicable,
+ );
+ }
+ BuiltinLintDiagnostics::ExternCrateNotIdiomatic { vis_span, ident_span }=> {
+ let suggestion_span = vis_span.between(ident_span);
+ db.span_suggestion_verbose(
+ suggestion_span,
+ "convert it to a `use`",
+ if vis_span.is_empty() { "use " } else { " use " },
+ Applicability::MachineApplicable,
+ );
+ }
}
// Rewrap `db`, and pass control to the user.
decorate(db)
@@ -1101,11 +1129,9 @@ impl<'tcx> LateContext<'tcx> {
.maybe_typeck_results()
.filter(|typeck_results| typeck_results.hir_owner == id.owner)
.or_else(|| {
- if self.tcx.has_typeck_results(id.owner.to_def_id()) {
- Some(self.tcx.typeck(id.owner.def_id))
- } else {
- None
- }
+ self.tcx
+ .has_typeck_results(id.owner.to_def_id())
+ .then(|| self.tcx.typeck(id.owner.def_id))
})
.and_then(|typeck_results| typeck_results.type_dependent_def(id))
.map_or(Res::Err, |(kind, def_id)| Res::Def(kind, def_id)),
diff --git a/compiler/rustc_lint/src/deref_into_dyn_supertrait.rs b/compiler/rustc_lint/src/deref_into_dyn_supertrait.rs
index a45d8156c..ccf95992a 100644
--- a/compiler/rustc_lint/src/deref_into_dyn_supertrait.rs
+++ b/compiler/rustc_lint/src/deref_into_dyn_supertrait.rs
@@ -59,7 +59,7 @@ impl<'tcx> LateLintPass<'tcx> for DerefIntoDynSupertrait {
// `Deref` is being implemented for `t`
if let hir::ItemKind::Impl(impl_) = item.kind
&& let Some(trait_) = &impl_.of_trait
- && let t = cx.tcx.type_of(item.owner_id)
+ && let t = cx.tcx.type_of(item.owner_id).subst_identity()
&& let opt_did @ Some(did) = trait_.trait_def_id()
&& opt_did == cx.tcx.lang_items().deref_trait()
// `t` is `dyn t_principal`
diff --git a/compiler/rustc_lint/src/enum_intrinsics_non_enums.rs b/compiler/rustc_lint/src/enum_intrinsics_non_enums.rs
index 73bd41732..f1ba192f2 100644
--- a/compiler/rustc_lint/src/enum_intrinsics_non_enums.rs
+++ b/compiler/rustc_lint/src/enum_intrinsics_non_enums.rs
@@ -4,7 +4,7 @@ use crate::{
LateContext, LateLintPass,
};
use rustc_hir as hir;
-use rustc_middle::ty::{visit::TypeVisitable, Ty};
+use rustc_middle::ty::{visit::TypeVisitableExt, Ty};
use rustc_span::{symbol::sym, Span};
declare_lint! {
diff --git a/compiler/rustc_lint/src/errors.rs b/compiler/rustc_lint/src/errors.rs
index f3ae26091..9af5284df 100644
--- a/compiler/rustc_lint/src/errors.rs
+++ b/compiler/rustc_lint/src/errors.rs
@@ -1,6 +1,6 @@
+use crate::fluent_generated as fluent;
use rustc_errors::{
- fluent, AddToDiagnostic, Diagnostic, ErrorGuaranteed, Handler, IntoDiagnostic,
- SubdiagnosticMessage,
+ AddToDiagnostic, Diagnostic, ErrorGuaranteed, Handler, IntoDiagnostic, SubdiagnosticMessage,
};
use rustc_macros::{Diagnostic, Subdiagnostic};
use rustc_session::lint::Level;
@@ -116,7 +116,7 @@ impl IntoDiagnostic<'_> for CheckNameUnknown {
let mut diag = handler.struct_err(fluent::lint_check_name_unknown);
diag.code(rustc_errors::error_code!(E0602));
if let Some(suggestion) = self.suggestion {
- diag.help(fluent::help);
+ diag.help(fluent::lint_help);
diag.set_arg("suggestion", suggestion);
}
diag.set_arg("lint_name", self.lint_name);
diff --git a/compiler/rustc_lint/src/for_loops_over_fallibles.rs b/compiler/rustc_lint/src/for_loops_over_fallibles.rs
index 5219992ee..a3367ae4a 100644
--- a/compiler/rustc_lint/src/for_loops_over_fallibles.rs
+++ b/compiler/rustc_lint/src/for_loops_over_fallibles.rs
@@ -65,11 +65,8 @@ impl<'tcx> LateLintPass<'tcx> for ForLoopsOverFallibles {
} else {
ForLoopsOverFalliblesLoopSub::UseWhileLet { start_span: expr.span.with_hi(pat.span.lo()), end_span: pat.span.between(arg.span), var }
} ;
- let question_mark = if suggest_question_mark(cx, adt, substs, expr.span) {
- Some(ForLoopsOverFalliblesQuestionMark { suggestion: arg.span.shrink_to_hi() })
- } else {
- None
- };
+ let question_mark = suggest_question_mark(cx, adt, substs, expr.span)
+ .then(|| ForLoopsOverFalliblesQuestionMark { suggestion: arg.span.shrink_to_hi() });
let suggestion = ForLoopsOverFalliblesSuggestion {
var,
start_span: expr.span.with_hi(pat.span.lo()),
@@ -139,9 +136,10 @@ fn suggest_question_mark<'tcx>(
let ty = substs.type_at(0);
let infcx = cx.tcx.infer_ctxt().build();
+ let body_def_id = cx.tcx.hir().body_owner_def_id(body_id);
let cause = ObligationCause::new(
span,
- body_id.hir_id,
+ body_def_id,
rustc_infer::traits::ObligationCauseCode::MiscObligation,
);
let errors = rustc_trait_selection::traits::fully_solve_bound(
diff --git a/compiler/rustc_lint/src/internal.rs b/compiler/rustc_lint/src/internal.rs
index 6cefaea2b..2fd0ef3cd 100644
--- a/compiler/rustc_lint/src/internal.rs
+++ b/compiler/rustc_lint/src/internal.rs
@@ -216,7 +216,7 @@ fn is_ty_or_ty_ctxt(cx: &LateContext<'_>, path: &Path<'_>) -> Option<String> {
}
// Only lint on `&Ty` and `&TyCtxt` if it is used outside of a trait.
Res::SelfTyAlias { alias_to: did, is_trait_impl: false, .. } => {
- if let ty::Adt(adt, substs) = cx.tcx.type_of(did).kind() {
+ if let ty::Adt(adt, substs) = cx.tcx.type_of(did).subst_identity().kind() {
if let Some(name @ (sym::Ty | sym::TyCtxt)) = cx.tcx.get_diagnostic_name(adt.did())
{
// NOTE: This path is currently unreachable as `Ty<'tcx>` is
diff --git a/compiler/rustc_lint/src/late.rs b/compiler/rustc_lint/src/late.rs
index b2a265674..b42878a02 100644
--- a/compiler/rustc_lint/src/late.rs
+++ b/compiler/rustc_lint/src/late.rs
@@ -66,13 +66,12 @@ impl<'tcx, T: LateLintPass<'tcx>> LateContextAndPass<'tcx, T> {
self.context.last_node_with_lint_attrs = prev;
}
- fn with_param_env<F>(&mut self, id: hir::HirId, f: F)
+ fn with_param_env<F>(&mut self, id: hir::OwnerId, f: F)
where
F: FnOnce(&mut Self),
{
let old_param_env = self.context.param_env;
- self.context.param_env =
- self.context.tcx.param_env(self.context.tcx.hir().local_def_id(id));
+ self.context.param_env = self.context.tcx.param_env(id);
f(self);
self.context.param_env = old_param_env;
}
@@ -132,7 +131,7 @@ impl<'tcx, T: LateLintPass<'tcx>> hir_visit::Visitor<'tcx> for LateContextAndPas
let old_cached_typeck_results = self.context.cached_typeck_results.take();
let old_enclosing_body = self.context.enclosing_body.take();
self.with_lint_attrs(it.hir_id(), |cx| {
- cx.with_param_env(it.hir_id(), |cx| {
+ cx.with_param_env(it.owner_id, |cx| {
lint_callback!(cx, check_item, it);
hir_visit::walk_item(cx, it);
lint_callback!(cx, check_item_post, it);
@@ -145,7 +144,7 @@ impl<'tcx, T: LateLintPass<'tcx>> hir_visit::Visitor<'tcx> for LateContextAndPas
fn visit_foreign_item(&mut self, it: &'tcx hir::ForeignItem<'tcx>) {
self.with_lint_attrs(it.hir_id(), |cx| {
- cx.with_param_env(it.hir_id(), |cx| {
+ cx.with_param_env(it.owner_id, |cx| {
lint_callback!(cx, check_foreign_item, it);
hir_visit::walk_foreign_item(cx, it);
});
@@ -180,7 +179,7 @@ impl<'tcx, T: LateLintPass<'tcx>> hir_visit::Visitor<'tcx> for LateContextAndPas
decl: &'tcx hir::FnDecl<'tcx>,
body_id: hir::BodyId,
span: Span,
- id: hir::HirId,
+ id: LocalDefId,
) {
// Wrap in typeck results here, not just in visit_nested_body,
// in order for `check_fn` to be able to use them.
@@ -268,7 +267,7 @@ impl<'tcx, T: LateLintPass<'tcx>> hir_visit::Visitor<'tcx> for LateContextAndPas
let generics = self.context.generics.take();
self.context.generics = Some(&trait_item.generics);
self.with_lint_attrs(trait_item.hir_id(), |cx| {
- cx.with_param_env(trait_item.hir_id(), |cx| {
+ cx.with_param_env(trait_item.owner_id, |cx| {
lint_callback!(cx, check_trait_item, trait_item);
hir_visit::walk_trait_item(cx, trait_item);
});
@@ -280,7 +279,7 @@ impl<'tcx, T: LateLintPass<'tcx>> hir_visit::Visitor<'tcx> for LateContextAndPas
let generics = self.context.generics.take();
self.context.generics = Some(&impl_item.generics);
self.with_lint_attrs(impl_item.hir_id(), |cx| {
- cx.with_param_env(impl_item.hir_id(), |cx| {
+ cx.with_param_env(impl_item.owner_id, |cx| {
lint_callback!(cx, check_impl_item, impl_item);
hir_visit::walk_impl_item(cx, impl_item);
lint_callback!(cx, check_impl_item_post, impl_item);
diff --git a/compiler/rustc_lint/src/levels.rs b/compiler/rustc_lint/src/levels.rs
index cca36913d..bc7488fab 100644
--- a/compiler/rustc_lint/src/levels.rs
+++ b/compiler/rustc_lint/src/levels.rs
@@ -1,13 +1,16 @@
-use crate::context::{CheckLintNameResult, LintStore};
-use crate::late::unerased_lint_store;
-use crate::lints::{
- DeprecatedLintName, IgnoredUnlessCrateSpecified, OverruledAtributeLint, RenamedOrRemovedLint,
- RenamedOrRemovedLintSuggestion, UnknownLint, UnknownLintSuggestion,
+use crate::{
+ context::{CheckLintNameResult, LintStore},
+ fluent_generated as fluent,
+ late::unerased_lint_store,
+ lints::{
+ DeprecatedLintName, IgnoredUnlessCrateSpecified, OverruledAtributeLint,
+ RenamedOrRemovedLint, RenamedOrRemovedLintSuggestion, UnknownLint, UnknownLintSuggestion,
+ },
};
use rustc_ast as ast;
use rustc_ast_pretty::pprust;
use rustc_data_structures::fx::FxHashMap;
-use rustc_errors::{fluent, DecorateLint, DiagnosticBuilder, DiagnosticMessage, MultiSpan};
+use rustc_errors::{DecorateLint, DiagnosticBuilder, DiagnosticMessage, MultiSpan};
use rustc_hir as hir;
use rustc_hir::intravisit::{self, Visitor};
use rustc_hir::HirId;
@@ -983,7 +986,7 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> {
fluent::lint_unknown_gated_lint,
|lint| {
lint.set_arg("name", lint_id.lint.name_lower());
- lint.note(fluent::note);
+ lint.note(fluent::lint_note);
add_feature_diagnostics(lint, &self.sess.parse_sess, feature);
lint
},
diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs
index d6be4da03..35dc533e5 100644
--- a/compiler/rustc_lint/src/lib.rs
+++ b/compiler/rustc_lint/src/lib.rs
@@ -63,7 +63,9 @@ mod late;
mod let_underscore;
mod levels;
mod lints;
+mod map_unit_fn;
mod methods;
+mod multiple_supertrait_upcastable;
mod non_ascii_idents;
mod non_fmt_panic;
mod nonstandard_style;
@@ -79,8 +81,10 @@ mod unused;
pub use array_into_iter::ARRAY_INTO_ITER;
use rustc_ast as ast;
+use rustc_errors::{DiagnosticMessage, SubdiagnosticMessage};
use rustc_hir as hir;
use rustc_hir::def_id::LocalDefId;
+use rustc_macros::fluent_messages;
use rustc_middle::ty::query::Providers;
use rustc_middle::ty::TyCtxt;
use rustc_session::lint::builtin::{
@@ -97,7 +101,9 @@ use for_loops_over_fallibles::*;
use hidden_unicode_codepoints::*;
use internal::*;
use let_underscore::*;
+use map_unit_fn::*;
use methods::*;
+use multiple_supertrait_upcastable::*;
use non_ascii_idents::*;
use non_fmt_panic::NonPanicFmt;
use nonstandard_style::*;
@@ -120,6 +126,8 @@ pub use rustc_session::lint::Level::{self, *};
pub use rustc_session::lint::{BufferedEarlyLint, FutureIncompatibleInfo, Lint, LintId};
pub use rustc_session::lint::{LintArray, LintPass};
+fluent_messages! { "../locales/en-US.ftl" }
+
pub fn provide(providers: &mut Providers) {
levels::provide(providers);
expect::provide(providers);
@@ -232,6 +240,8 @@ late_lint_methods!(
InvalidAtomicOrdering: InvalidAtomicOrdering,
NamedAsmLabels: NamedAsmLabels,
OpaqueHiddenInferredBound: OpaqueHiddenInferredBound,
+ MultipleSupertraitUpcastable: MultipleSupertraitUpcastable,
+ MapUnitFn: MapUnitFn,
]
]
);
@@ -291,7 +301,8 @@ fn register_builtins(store: &mut LintStore) {
UNUSED_LABELS,
UNUSED_PARENS,
UNUSED_BRACES,
- REDUNDANT_SEMICOLONS
+ REDUNDANT_SEMICOLONS,
+ MAP_UNIT_FN
);
add_lint_group!("let_underscore", LET_UNDERSCORE_DROP, LET_UNDERSCORE_LOCK);
@@ -321,7 +332,6 @@ fn register_builtins(store: &mut LintStore) {
store.register_renamed("exceeding_bitshifts", "arithmetic_overflow");
store.register_renamed("redundant_semicolon", "redundant_semicolons");
store.register_renamed("overlapping_patterns", "overlapping_range_endpoints");
- store.register_renamed("safe_packed_borrows", "unaligned_references");
store.register_renamed("disjoint_capture_migration", "rust_2021_incompatible_closure_captures");
store.register_renamed("or_patterns_back_compat", "rust_2021_incompatible_or_patterns");
store.register_renamed("non_fmt_panic", "non_fmt_panics");
@@ -484,6 +494,16 @@ fn register_builtins(store: &mut LintStore) {
"converted into hard error, see issue #71800 \
<https://github.com/rust-lang/rust/issues/71800> for more information",
);
+ store.register_removed(
+ "safe_packed_borrows",
+ "converted into hard error, see issue #82523 \
+ <https://github.com/rust-lang/rust/issues/82523> for more information",
+ );
+ store.register_removed(
+ "unaligned_references",
+ "converted into hard error, see issue #82523 \
+ <https://github.com/rust-lang/rust/issues/82523> for more information",
+ );
}
fn register_internals(store: &mut LintStore) {
diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs
index 329ece28e..20ab0af58 100644
--- a/compiler/rustc_lint/src/lints.rs
+++ b/compiler/rustc_lint/src/lints.rs
@@ -2,13 +2,16 @@
#![allow(rustc::diagnostic_outside_of_impl)]
use std::num::NonZeroU32;
+use crate::fluent_generated as fluent;
use rustc_errors::{
- fluent, AddToDiagnostic, Applicability, DecorateLint, DiagnosticMessage,
- DiagnosticStyledString, SuggestionStyle,
+ AddToDiagnostic, Applicability, DecorateLint, DiagnosticMessage, DiagnosticStyledString,
+ SuggestionStyle,
};
use rustc_hir::def_id::DefId;
use rustc_macros::{LintDiagnostic, Subdiagnostic};
-use rustc_middle::ty::{PolyExistentialTraitRef, Predicate, Ty, TyCtxt};
+use rustc_middle::ty::{
+ inhabitedness::InhabitedPredicate, PolyExistentialTraitRef, Predicate, Ty, TyCtxt,
+};
use rustc_session::parse::ParseSess;
use rustc_span::{edition::Edition, sym, symbol::Ident, Span, Symbol};
@@ -21,7 +24,7 @@ use crate::{
#[diag(lint_array_into_iter)]
pub struct ArrayIntoIterDiag<'a> {
pub target: &'a str,
- #[suggestion(use_iter_suggestion, code = "iter", applicability = "machine-applicable")]
+ #[suggestion(lint_use_iter_suggestion, code = "iter", applicability = "machine-applicable")]
pub suggestion: Span,
#[subdiagnostic]
pub sub: Option<ArrayIntoIterDiagSub>,
@@ -29,12 +32,15 @@ pub struct ArrayIntoIterDiag<'a> {
#[derive(Subdiagnostic)]
pub enum ArrayIntoIterDiagSub {
- #[suggestion(remove_into_iter_suggestion, code = "", applicability = "maybe-incorrect")]
+ #[suggestion(lint_remove_into_iter_suggestion, code = "", applicability = "maybe-incorrect")]
RemoveIntoIter {
#[primary_span]
span: Span,
},
- #[multipart_suggestion(use_explicit_into_iter_suggestion, applicability = "maybe-incorrect")]
+ #[multipart_suggestion(
+ lint_use_explicit_into_iter_suggestion,
+ applicability = "maybe-incorrect"
+ )]
UseExplicitIntoIter {
#[suggestion_part(code = "IntoIterator::into_iter(")]
start_span: Span,
@@ -161,13 +167,13 @@ pub struct BuiltinDeprecatedAttrLink<'a> {
#[derive(Subdiagnostic)]
pub enum BuiltinDeprecatedAttrLinkSuggestion<'a> {
- #[suggestion(msg_suggestion, code = "", applicability = "machine-applicable")]
+ #[suggestion(lint_msg_suggestion, code = "", applicability = "machine-applicable")]
Msg {
#[primary_span]
suggestion: Span,
msg: &'a str,
},
- #[suggestion(default_suggestion, code = "", applicability = "machine-applicable")]
+ #[suggestion(lint_default_suggestion, code = "", applicability = "machine-applicable")]
Default {
#[primary_span]
suggestion: Span,
@@ -199,9 +205,9 @@ pub struct BuiltinUnusedDocComment<'a> {
#[derive(Subdiagnostic)]
pub enum BuiltinUnusedDocCommentSub {
- #[help(plain_help)]
+ #[help(lint_plain_help)]
PlainHelp,
- #[help(block_help)]
+ #[help(lint_block_help)]
BlockHelp,
}
@@ -240,7 +246,7 @@ impl<'a> DecorateLint<'a, ()> for BuiltinUngatedAsyncFnTrackCaller<'_> {
self,
diag: &'b mut rustc_errors::DiagnosticBuilder<'a, ()>,
) -> &'b mut rustc_errors::DiagnosticBuilder<'a, ()> {
- diag.span_label(self.label, fluent::label);
+ diag.span_label(self.label, fluent::lint_label);
rustc_session::parse::add_feature_diagnostics(
diag,
&self.parse_sess,
@@ -335,7 +341,7 @@ impl AddToDiagnostic for BuiltinTypeAliasGenericBoundsSuggestion {
) -> rustc_errors::SubdiagnosticMessage,
{
diag.multipart_suggestion(
- fluent::suggestion,
+ fluent::lint_suggestion,
self.suggestions,
Applicability::MachineApplicable,
);
@@ -386,7 +392,7 @@ pub struct BuiltinExplicitOutlives {
}
#[derive(Subdiagnostic)]
-#[multipart_suggestion(suggestion)]
+#[multipart_suggestion(lint_suggestion)]
pub struct BuiltinExplicitOutlivesSuggestion {
#[suggestion_part(code = "")]
pub spans: Vec<Span>,
@@ -405,11 +411,11 @@ pub struct BuiltinIncompleteFeatures {
}
#[derive(Subdiagnostic)]
-#[help(help)]
+#[help(lint_help)]
pub struct BuiltinIncompleteFeaturesHelp;
#[derive(Subdiagnostic)]
-#[note(note)]
+#[note(lint_note)]
pub struct BuiltinIncompleteFeaturesNote {
pub n: NonZeroU32,
}
@@ -419,6 +425,7 @@ pub struct BuiltinUnpermittedTypeInit<'a> {
pub ty: Ty<'a>,
pub label: Span,
pub sub: BuiltinUnpermittedTypeInitSub,
+ pub tcx: TyCtxt<'a>,
}
impl<'a> DecorateLint<'a, ()> for BuiltinUnpermittedTypeInit<'_> {
@@ -428,7 +435,13 @@ impl<'a> DecorateLint<'a, ()> for BuiltinUnpermittedTypeInit<'_> {
) -> &'b mut rustc_errors::DiagnosticBuilder<'a, ()> {
diag.set_arg("ty", self.ty);
diag.span_label(self.label, fluent::lint_builtin_unpermitted_type_init_label);
- diag.span_label(self.label, fluent::lint_builtin_unpermitted_type_init_label_suggestion);
+ if let InhabitedPredicate::True = self.ty.inhabited_predicate(self.tcx) {
+ // Only suggest late `MaybeUninit::assume_init` initialization if the type is inhabited.
+ diag.span_label(
+ self.label,
+ fluent::lint_builtin_unpermitted_type_init_label_suggestion,
+ );
+ }
self.sub.add_to_diagnostic(diag);
diag
}
@@ -473,9 +486,9 @@ pub enum BuiltinClashingExtern<'a> {
SameName {
this: Symbol,
orig: Symbol,
- #[label(previous_decl_label)]
+ #[label(lint_previous_decl_label)]
previous_decl_label: Span,
- #[label(mismatch_label)]
+ #[label(lint_mismatch_label)]
mismatch_label: Span,
#[subdiagnostic]
sub: BuiltinClashingExternSub<'a>,
@@ -484,9 +497,9 @@ pub enum BuiltinClashingExtern<'a> {
DiffName {
this: Symbol,
orig: Symbol,
- #[label(previous_decl_label)]
+ #[label(lint_previous_decl_label)]
previous_decl_label: Span,
- #[label(mismatch_label)]
+ #[label(lint_mismatch_label)]
mismatch_label: Span,
#[subdiagnostic]
sub: BuiltinClashingExternSub<'a>,
@@ -562,7 +575,7 @@ pub struct SupertraitAsDerefTarget<'a> {
}
#[derive(Subdiagnostic)]
-#[label(label)]
+#[label(lint_label)]
pub struct SupertraitAsDerefTargetLabel {
#[primary_span]
pub label: Span,
@@ -595,7 +608,7 @@ pub struct Expectation {
}
#[derive(Subdiagnostic)]
-#[note(rationale)]
+#[note(lint_rationale)]
pub struct ExpectationNote {
pub rationale: Symbol,
}
@@ -616,13 +629,13 @@ pub struct ForLoopsOverFalliblesDiag<'a> {
#[derive(Subdiagnostic)]
pub enum ForLoopsOverFalliblesLoopSub<'a> {
- #[suggestion(remove_next, code = ".by_ref()", applicability = "maybe-incorrect")]
+ #[suggestion(lint_remove_next, code = ".by_ref()", applicability = "maybe-incorrect")]
RemoveNext {
#[primary_span]
suggestion: Span,
recv_snip: String,
},
- #[multipart_suggestion(use_while_let, applicability = "maybe-incorrect")]
+ #[multipart_suggestion(lint_use_while_let, applicability = "maybe-incorrect")]
UseWhileLet {
#[suggestion_part(code = "while let {var}(")]
start_span: Span,
@@ -633,14 +646,14 @@ pub enum ForLoopsOverFalliblesLoopSub<'a> {
}
#[derive(Subdiagnostic)]
-#[suggestion(use_question_mark, code = "?", applicability = "maybe-incorrect")]
+#[suggestion(lint_use_question_mark, code = "?", applicability = "maybe-incorrect")]
pub struct ForLoopsOverFalliblesQuestionMark {
#[primary_span]
pub suggestion: Span,
}
#[derive(Subdiagnostic)]
-#[multipart_suggestion(suggestion, applicability = "maybe-incorrect")]
+#[multipart_suggestion(lint_suggestion, applicability = "maybe-incorrect")]
pub struct ForLoopsOverFalliblesSuggestion<'a> {
pub var: &'a str,
#[suggestion_part(code = "if let {var}(")]
@@ -699,13 +712,13 @@ impl AddToDiagnostic for HiddenUnicodeCodepointsDiagSub {
match self {
HiddenUnicodeCodepointsDiagSub::Escape { spans } => {
diag.multipart_suggestion_with_style(
- fluent::suggestion_remove,
+ fluent::lint_suggestion_remove,
spans.iter().map(|(_, span)| (*span, "".to_string())).collect(),
Applicability::MachineApplicable,
SuggestionStyle::HideCodeAlways,
);
diag.multipart_suggestion(
- fluent::suggestion_escape,
+ fluent::lint_suggestion_escape,
spans
.into_iter()
.map(|(c, span)| {
@@ -728,13 +741,29 @@ impl AddToDiagnostic for HiddenUnicodeCodepointsDiagSub {
.collect::<Vec<String>>()
.join(", "),
);
- diag.note(fluent::suggestion_remove);
- diag.note(fluent::no_suggestion_note_escape);
+ diag.note(fluent::lint_suggestion_remove);
+ diag.note(fluent::lint_no_suggestion_note_escape);
}
}
}
}
+// map_unit_fn.rs
+#[derive(LintDiagnostic)]
+#[diag(lint_map_unit_fn)]
+#[note]
+pub struct MappingToUnit {
+ #[label(lint_function_label)]
+ pub function_label: Span,
+ #[label(lint_argument_label)]
+ pub argument_label: Span,
+ #[label(lint_map_label)]
+ pub map_label: Span,
+ #[suggestion(style = "verbose", code = "{replace}", applicability = "maybe-incorrect")]
+ pub suggestion: Span,
+ pub replace: String,
+}
+
// internal.rs
#[derive(LintDiagnostic)]
#[diag(lint_default_hash_types)]
@@ -874,7 +903,7 @@ pub struct RenamedOrRemovedLint<'a> {
}
#[derive(Subdiagnostic)]
-#[suggestion(suggestion, code = "{replace}", applicability = "machine-applicable")]
+#[suggestion(lint_suggestion, code = "{replace}", applicability = "machine-applicable")]
pub struct RenamedOrRemovedLintSuggestion<'a> {
#[primary_span]
pub suggestion: Span,
@@ -890,7 +919,7 @@ pub struct UnknownLint {
}
#[derive(Subdiagnostic)]
-#[suggestion(suggestion, code = "{replace}", applicability = "maybe-incorrect")]
+#[suggestion(lint_suggestion, code = "{replace}", applicability = "maybe-incorrect")]
pub struct UnknownLintSuggestion {
#[primary_span]
pub suggestion: Span,
@@ -910,12 +939,19 @@ pub struct IgnoredUnlessCrateSpecified<'a> {
#[note]
#[help]
pub struct CStringPtr {
- #[label(as_ptr_label)]
+ #[label(lint_as_ptr_label)]
pub as_ptr: Span,
- #[label(unwrap_label)]
+ #[label(lint_unwrap_label)]
pub unwrap: Span,
}
+// multiple_supertrait_upcastable.rs
+#[derive(LintDiagnostic)]
+#[diag(lint_multple_supertrait_upcastable)]
+pub struct MultipleSupertraitUpcastable {
+ pub ident: Ident,
+}
+
// non_ascii_idents.rs
#[derive(LintDiagnostic)]
#[diag(lint_identifier_non_ascii_char)]
@@ -936,7 +972,7 @@ pub struct ConfusableIdentifierPair {
#[derive(LintDiagnostic)]
#[diag(lint_mixed_script_confusables)]
-#[note(includes_note)]
+#[note(lint_includes_note)]
#[note]
pub struct MixedScriptConfusables {
pub set: String,
@@ -956,17 +992,17 @@ impl<'a> DecorateLint<'a, ()> for NonFmtPanicUnused {
diag: &'b mut rustc_errors::DiagnosticBuilder<'a, ()>,
) -> &'b mut rustc_errors::DiagnosticBuilder<'a, ()> {
diag.set_arg("count", self.count);
- diag.note(fluent::note);
+ diag.note(fluent::lint_note);
if let Some(span) = self.suggestion {
diag.span_suggestion(
span.shrink_to_hi(),
- fluent::add_args_suggestion,
+ fluent::lint_add_args_suggestion,
", ...",
Applicability::HasPlaceholders,
);
diag.span_suggestion(
span.shrink_to_lo(),
- fluent::add_fmt_suggestion,
+ fluent::lint_add_fmt_suggestion,
"\"{}\", ",
Applicability::MachineApplicable,
);
@@ -1000,12 +1036,12 @@ pub struct NonCamelCaseType<'a> {
#[derive(Subdiagnostic)]
pub enum NonCamelCaseTypeSub {
- #[label(label)]
+ #[label(lint_label)]
Label {
#[primary_span]
span: Span,
},
- #[suggestion(suggestion, code = "{replace}", applicability = "maybe-incorrect")]
+ #[suggestion(lint_suggestion, code = "{replace}", applicability = "maybe-incorrect")]
Suggestion {
#[primary_span]
span: Span,
@@ -1041,15 +1077,15 @@ impl AddToDiagnostic for NonSnakeCaseDiagSub {
{
match self {
NonSnakeCaseDiagSub::Label { span } => {
- diag.span_label(span, fluent::label);
+ diag.span_label(span, fluent::lint_label);
}
NonSnakeCaseDiagSub::Help => {
- diag.help(fluent::help);
+ diag.help(fluent::lint_help);
}
NonSnakeCaseDiagSub::ConvertSuggestion { span, suggestion } => {
diag.span_suggestion(
span,
- fluent::convert_suggestion,
+ fluent::lint_convert_suggestion,
suggestion,
Applicability::MaybeIncorrect,
);
@@ -1057,16 +1093,16 @@ impl AddToDiagnostic for NonSnakeCaseDiagSub {
NonSnakeCaseDiagSub::RenameOrConvertSuggestion { span, suggestion } => {
diag.span_suggestion(
span,
- fluent::rename_or_convert_suggestion,
+ fluent::lint_rename_or_convert_suggestion,
suggestion,
Applicability::MaybeIncorrect,
);
}
NonSnakeCaseDiagSub::SuggestionAndNote { span } => {
- diag.note(fluent::cannot_convert_note);
+ diag.note(fluent::lint_cannot_convert_note);
diag.span_suggestion(
span,
- fluent::rename_suggestion,
+ fluent::lint_rename_suggestion,
"",
Applicability::MaybeIncorrect,
);
@@ -1086,12 +1122,12 @@ pub struct NonUpperCaseGlobal<'a> {
#[derive(Subdiagnostic)]
pub enum NonUpperCaseGlobalSub {
- #[label(label)]
+ #[label(lint_label)]
Label {
#[primary_span]
span: Span,
},
- #[suggestion(suggestion, code = "{replace}", applicability = "maybe-incorrect")]
+ #[suggestion(lint_suggestion, code = "{replace}", applicability = "maybe-incorrect")]
Suggestion {
#[primary_span]
span: Span,
@@ -1209,11 +1245,11 @@ impl AddToDiagnostic for OverflowingBinHexSign {
{
match self {
OverflowingBinHexSign::Positive => {
- diag.note(fluent::positive_note);
+ diag.note(fluent::lint_positive_note);
}
OverflowingBinHexSign::Negative => {
- diag.note(fluent::negative_note);
- diag.note(fluent::negative_becomes_note);
+ diag.note(fluent::lint_negative_note);
+ diag.note(fluent::lint_negative_becomes_note);
}
}
}
@@ -1222,7 +1258,7 @@ impl AddToDiagnostic for OverflowingBinHexSign {
#[derive(Subdiagnostic)]
pub enum OverflowingBinHexSub<'a> {
#[suggestion(
- suggestion,
+ lint_suggestion,
code = "{sans_suffix}{suggestion_ty}",
applicability = "machine-applicable"
)]
@@ -1232,7 +1268,7 @@ pub enum OverflowingBinHexSub<'a> {
suggestion_ty: &'a str,
sans_suffix: &'a str,
},
- #[help(help)]
+ #[help(lint_help)]
Help { suggestion_ty: &'a str },
}
@@ -1249,7 +1285,7 @@ pub struct OverflowingInt<'a> {
}
#[derive(Subdiagnostic)]
-#[help(help)]
+#[help(lint_help)]
pub struct OverflowingIntHelp<'a> {
pub suggestion_ty: &'a str,
}
@@ -1301,13 +1337,13 @@ impl<'a> DecorateLint<'a, ()> for ImproperCTypes<'_> {
) -> &'b mut rustc_errors::DiagnosticBuilder<'a, ()> {
diag.set_arg("ty", self.ty);
diag.set_arg("desc", self.desc);
- diag.span_label(self.label, fluent::label);
+ diag.span_label(self.label, fluent::lint_label);
if let Some(help) = self.help {
diag.help(help);
}
diag.note(self.note);
if let Some(note) = self.span_note {
- diag.span_note(note, fluent::note);
+ diag.span_note(note, fluent::lint_note);
}
diag
}
@@ -1394,6 +1430,21 @@ pub struct UnusedDef<'a, 'b> {
pub cx: &'a LateContext<'b>,
pub def_id: DefId,
pub note: Option<Symbol>,
+ pub suggestion: Option<UnusedDefSuggestion>,
+}
+
+#[derive(Subdiagnostic)]
+pub enum UnusedDefSuggestion {
+ #[suggestion(
+ lint_suggestion,
+ style = "verbose",
+ code = "let _ = ",
+ applicability = "machine-applicable"
+ )]
+ Default {
+ #[primary_span]
+ span: Span,
+ },
}
// Needed because of def_path_str
@@ -1409,6 +1460,9 @@ impl<'a> DecorateLint<'a, ()> for UnusedDef<'_, '_> {
if let Some(note) = self.note {
diag.note(note.as_str());
}
+ if let Some(sugg) = self.suggestion {
+ diag.subdiagnostic(sugg);
+ }
diag
}
@@ -1426,13 +1480,13 @@ pub struct PathStatementDrop {
#[derive(Subdiagnostic)]
pub enum PathStatementDropSub {
- #[suggestion(suggestion, code = "drop({snippet});", applicability = "machine-applicable")]
+ #[suggestion(lint_suggestion, code = "drop({snippet});", applicability = "machine-applicable")]
Suggestion {
#[primary_span]
span: Span,
snippet: String,
},
- #[help(help)]
+ #[help(lint_help)]
Help {
#[primary_span]
span: Span,
@@ -1453,7 +1507,7 @@ pub struct UnusedDelim<'a> {
}
#[derive(Subdiagnostic)]
-#[multipart_suggestion(suggestion, applicability = "machine-applicable")]
+#[multipart_suggestion(lint_suggestion, applicability = "machine-applicable")]
pub struct UnusedDelimSuggestion {
#[suggestion_part(code = "{start_replace}")]
pub start_span: Span,
diff --git a/compiler/rustc_lint/src/map_unit_fn.rs b/compiler/rustc_lint/src/map_unit_fn.rs
new file mode 100644
index 000000000..62e8b4fe9
--- /dev/null
+++ b/compiler/rustc_lint/src/map_unit_fn.rs
@@ -0,0 +1,120 @@
+use crate::lints::MappingToUnit;
+use crate::{LateContext, LateLintPass, LintContext};
+
+use rustc_hir::{Expr, ExprKind, HirId, Stmt, StmtKind};
+use rustc_middle::{
+ query::Key,
+ ty::{self, Ty},
+};
+
+declare_lint! {
+ /// The `map_unit_fn` lint checks for `Iterator::map` receive
+ /// a callable that returns `()`.
+ ///
+ /// ### Example
+ ///
+ /// ```rust
+ /// fn foo(items: &mut Vec<u8>) {
+ /// items.sort();
+ /// }
+ ///
+ /// fn main() {
+ /// let mut x: Vec<Vec<u8>> = vec![
+ /// vec![0, 2, 1],
+ /// vec![5, 4, 3],
+ /// ];
+ /// x.iter_mut().map(foo);
+ /// }
+ /// ```
+ ///
+ /// {{produces}}
+ ///
+ /// ### Explanation
+ ///
+ /// Mapping to `()` is almost always a mistake.
+ pub MAP_UNIT_FN,
+ Warn,
+ "`Iterator::map` call that discard the iterator's values"
+}
+
+declare_lint_pass!(MapUnitFn => [MAP_UNIT_FN]);
+
+impl<'tcx> LateLintPass<'tcx> for MapUnitFn {
+ fn check_stmt(&mut self, cx: &LateContext<'tcx>, stmt: &Stmt<'_>) {
+ if stmt.span.from_expansion() {
+ return;
+ }
+
+ if let StmtKind::Semi(expr) = stmt.kind {
+ if let ExprKind::MethodCall(path, receiver, args, span) = expr.kind {
+ if path.ident.name.as_str() == "map" {
+ if receiver.span.from_expansion()
+ || args.iter().any(|e| e.span.from_expansion())
+ || !is_impl_slice(cx, receiver)
+ || !is_diagnostic_name(cx, expr.hir_id, "IteratorMap")
+ {
+ return;
+ }
+ let arg_ty = cx.typeck_results().expr_ty(&args[0]);
+ if let ty::FnDef(id, _) = arg_ty.kind() {
+ let fn_ty = cx.tcx.fn_sig(id).skip_binder();
+ let ret_ty = fn_ty.output().skip_binder();
+ if is_unit_type(ret_ty) {
+ cx.emit_spanned_lint(
+ MAP_UNIT_FN,
+ span,
+ MappingToUnit {
+ function_label: cx.tcx.span_of_impl(*id).unwrap(),
+ argument_label: args[0].span,
+ map_label: arg_ty.default_span(cx.tcx),
+ suggestion: path.ident.span,
+ replace: "for_each".to_string(),
+ },
+ )
+ }
+ } else if let ty::Closure(id, subs) = arg_ty.kind() {
+ let cl_ty = subs.as_closure().sig();
+ let ret_ty = cl_ty.output().skip_binder();
+ if is_unit_type(ret_ty) {
+ cx.emit_spanned_lint(
+ MAP_UNIT_FN,
+ span,
+ MappingToUnit {
+ function_label: cx.tcx.span_of_impl(*id).unwrap(),
+ argument_label: args[0].span,
+ map_label: arg_ty.default_span(cx.tcx),
+ suggestion: path.ident.span,
+ replace: "for_each".to_string(),
+ },
+ )
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+fn is_impl_slice(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
+ if let Some(method_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id) {
+ if let Some(impl_id) = cx.tcx.impl_of_method(method_id) {
+ return cx.tcx.type_of(impl_id).skip_binder().is_slice();
+ }
+ }
+ false
+}
+
+fn is_unit_type(ty: Ty<'_>) -> bool {
+ ty.is_unit() || ty.is_never()
+}
+
+fn is_diagnostic_name(cx: &LateContext<'_>, id: HirId, name: &str) -> bool {
+ if let Some(def_id) = cx.typeck_results().type_dependent_def_id(id) {
+ if let Some(item) = cx.tcx.get_diagnostic_name(def_id) {
+ if item.as_str() == name {
+ return true;
+ }
+ }
+ }
+ false
+}
diff --git a/compiler/rustc_lint/src/multiple_supertrait_upcastable.rs b/compiler/rustc_lint/src/multiple_supertrait_upcastable.rs
new file mode 100644
index 000000000..c2ed0e19f
--- /dev/null
+++ b/compiler/rustc_lint/src/multiple_supertrait_upcastable.rs
@@ -0,0 +1,60 @@
+use crate::{LateContext, LateLintPass, LintContext};
+
+use rustc_hir as hir;
+use rustc_span::sym;
+
+declare_lint! {
+ /// The `multiple_supertrait_upcastable` lint detects when an object-safe trait has multiple
+ /// supertraits.
+ ///
+ /// ### Example
+ ///
+ /// ```rust
+ /// trait A {}
+ /// trait B {}
+ ///
+ /// #[warn(multiple_supertrait_upcastable)]
+ /// trait C: A + B {}
+ /// ```
+ ///
+ /// {{produces}}
+ ///
+ /// ### Explanation
+ ///
+ /// To support upcasting with multiple supertraits, we need to store multiple vtables and this
+ /// can result in extra space overhead, even if no code actually uses upcasting.
+ /// This lint allows users to identify when such scenarios occur and to decide whether the
+ /// additional overhead is justified.
+ pub MULTIPLE_SUPERTRAIT_UPCASTABLE,
+ Allow,
+ "detect when an object-safe trait has multiple supertraits",
+ @feature_gate = sym::multiple_supertrait_upcastable;
+}
+
+declare_lint_pass!(MultipleSupertraitUpcastable => [MULTIPLE_SUPERTRAIT_UPCASTABLE]);
+
+impl<'tcx> LateLintPass<'tcx> for MultipleSupertraitUpcastable {
+ fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'tcx>) {
+ let def_id = item.owner_id.to_def_id();
+ // NOTE(nbdd0121): use `object_safety_violations` instead of `check_is_object_safe` because
+ // the latter will report `where_clause_object_safety` lint.
+ if let hir::ItemKind::Trait(_, _, _, _, _) = item.kind
+ && cx.tcx.object_safety_violations(def_id).is_empty()
+ {
+ let direct_super_traits_iter = cx.tcx
+ .super_predicates_of(def_id)
+ .predicates
+ .into_iter()
+ .filter_map(|(pred, _)| pred.to_opt_poly_trait_pred());
+ if direct_super_traits_iter.count() > 1 {
+ cx.emit_spanned_lint(
+ MULTIPLE_SUPERTRAIT_UPCASTABLE,
+ cx.tcx.def_span(def_id),
+ crate::lints::MultipleSupertraitUpcastable {
+ ident: item.ident
+ },
+ );
+ }
+ }
+ }
+}
diff --git a/compiler/rustc_lint/src/non_fmt_panic.rs b/compiler/rustc_lint/src/non_fmt_panic.rs
index 4a02c6cce..5bb1abfd2 100644
--- a/compiler/rustc_lint/src/non_fmt_panic.rs
+++ b/compiler/rustc_lint/src/non_fmt_panic.rs
@@ -1,7 +1,7 @@
use crate::lints::{NonFmtPanicBraces, NonFmtPanicUnused};
-use crate::{LateContext, LateLintPass, LintContext};
+use crate::{fluent_generated as fluent, LateContext, LateLintPass, LintContext};
use rustc_ast as ast;
-use rustc_errors::{fluent, Applicability};
+use rustc_errors::Applicability;
use rustc_hir as hir;
use rustc_infer::infer::TyCtxtInferExt;
use rustc_middle::lint::in_external_macro;
@@ -122,18 +122,18 @@ fn check_panic<'tcx>(cx: &LateContext<'tcx>, f: &'tcx hir::Expr<'tcx>, arg: &'tc
#[allow(rustc::diagnostic_outside_of_impl)]
cx.struct_span_lint(NON_FMT_PANICS, arg_span, fluent::lint_non_fmt_panic, |lint| {
lint.set_arg("name", symbol);
- lint.note(fluent::note);
- lint.note(fluent::more_info_note);
+ lint.note(fluent::lint_note);
+ lint.note(fluent::lint_more_info_note);
if !is_arg_inside_call(arg_span, span) {
// No clue where this argument is coming from.
return lint;
}
if arg_macro.map_or(false, |id| cx.tcx.is_diagnostic_item(sym::format_macro, id)) {
// A case of `panic!(format!(..))`.
- lint.note(fluent::supports_fmt_note);
+ lint.note(fluent::lint_supports_fmt_note);
if let Some((open, close, _)) = find_delimiters(cx, arg_span) {
lint.multipart_suggestion(
- fluent::supports_fmt_suggestion,
+ fluent::lint_supports_fmt_suggestion,
vec![
(arg_span.until(open.shrink_to_hi()), "".into()),
(close.until(arg_span.shrink_to_hi()), "".into()),
@@ -146,7 +146,7 @@ fn check_panic<'tcx>(cx: &LateContext<'tcx>, f: &'tcx hir::Expr<'tcx>, arg: &'tc
// If this is a &str or String, we can confidently give the `"{}", ` suggestion.
let is_str = matches!(
ty.kind(),
- ty::Ref(_, r, _) if *r.kind() == ty::Str,
+ ty::Ref(_, r, _) if r.is_str(),
) || matches!(
ty.ty_adt_def(),
Some(ty_def) if Some(ty_def.did()) == cx.tcx.lang_items().string(),
@@ -179,7 +179,7 @@ fn check_panic<'tcx>(cx: &LateContext<'tcx>, f: &'tcx hir::Expr<'tcx>, arg: &'tc
if suggest_display {
lint.span_suggestion_verbose(
arg_span.shrink_to_lo(),
- fluent::display_suggestion,
+ fluent::lint_display_suggestion,
"\"{}\", ",
fmt_applicability,
);
@@ -187,7 +187,7 @@ fn check_panic<'tcx>(cx: &LateContext<'tcx>, f: &'tcx hir::Expr<'tcx>, arg: &'tc
lint.set_arg("ty", ty);
lint.span_suggestion_verbose(
arg_span.shrink_to_lo(),
- fluent::debug_suggestion,
+ fluent::lint_debug_suggestion,
"\"{:?}\", ",
fmt_applicability,
);
@@ -197,7 +197,7 @@ fn check_panic<'tcx>(cx: &LateContext<'tcx>, f: &'tcx hir::Expr<'tcx>, arg: &'tc
if let Some((open, close, del)) = find_delimiters(cx, span) {
lint.set_arg("already_suggested", suggest_display || suggest_debug);
lint.multipart_suggestion(
- fluent::panic_suggestion,
+ fluent::lint_panic_suggestion,
if del == '(' {
vec![(span.until(open), "std::panic::panic_any".into())]
} else {
diff --git a/compiler/rustc_lint/src/nonstandard_style.rs b/compiler/rustc_lint/src/nonstandard_style.rs
index 74d234fab..71e2e66bd 100644
--- a/compiler/rustc_lint/src/nonstandard_style.rs
+++ b/compiler/rustc_lint/src/nonstandard_style.rs
@@ -10,8 +10,9 @@ use rustc_hir::def::{DefKind, Res};
use rustc_hir::intravisit::FnKind;
use rustc_hir::{GenericParamKind, PatKind};
use rustc_middle::ty;
-use rustc_span::symbol::sym;
-use rustc_span::{symbol::Ident, BytePos, Span};
+use rustc_span::def_id::LocalDefId;
+use rustc_span::symbol::{sym, Ident};
+use rustc_span::{BytePos, Span};
use rustc_target::spec::abi::Abi;
#[derive(PartialEq)]
@@ -21,9 +22,8 @@ pub enum MethodLateContext {
PlainImpl,
}
-pub fn method_context(cx: &LateContext<'_>, id: hir::HirId) -> MethodLateContext {
- let def_id = cx.tcx.hir().local_def_id(id);
- let item = cx.tcx.associated_item(def_id);
+pub fn method_context(cx: &LateContext<'_>, id: LocalDefId) -> MethodLateContext {
+ let item = cx.tcx.associated_item(id);
match item.container {
ty::TraitContainer => MethodLateContext::TraitAutoImpl,
ty::ImplContainer => match cx.tcx.impl_trait_ref(item.container_id(cx.tcx)) {
@@ -379,13 +379,13 @@ impl<'tcx> LateLintPass<'tcx> for NonSnakeCase {
_: &hir::FnDecl<'_>,
_: &hir::Body<'_>,
_: Span,
- id: hir::HirId,
+ id: LocalDefId,
) {
- let attrs = cx.tcx.hir().attrs(id);
match &fk {
FnKind::Method(ident, sig, ..) => match method_context(cx, id) {
MethodLateContext::PlainImpl => {
- if sig.header.abi != Abi::Rust && cx.sess().contains_name(attrs, sym::no_mangle)
+ if sig.header.abi != Abi::Rust
+ && cx.tcx.has_attr(id.to_def_id(), sym::no_mangle)
{
return;
}
@@ -398,7 +398,7 @@ impl<'tcx> LateLintPass<'tcx> for NonSnakeCase {
},
FnKind::ItemFn(ident, _, header) => {
// Skip foreign-ABI #[no_mangle] functions (Issue #31924)
- if header.abi != Abi::Rust && cx.sess().contains_name(attrs, sym::no_mangle) {
+ if header.abi != Abi::Rust && cx.tcx.has_attr(id.to_def_id(), sym::no_mangle) {
return;
}
self.check_snake_case(cx, "function", ident);
diff --git a/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs b/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs
index 42442cfb1..883a56cb3 100644
--- a/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs
+++ b/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs
@@ -149,7 +149,7 @@ impl<'tcx> LateLintPass<'tcx> for OpaqueHiddenInferredBound {
struct OpaqueHiddenInferredBoundLint<'tcx> {
ty: Ty<'tcx>,
proj_ty: Ty<'tcx>,
- #[label(specifically)]
+ #[label(lint_specifically)]
assoc_pred_span: Span,
#[subdiagnostic]
add_bound: Option<AddBound<'tcx>>,
diff --git a/compiler/rustc_lint/src/pass_by_value.rs b/compiler/rustc_lint/src/pass_by_value.rs
index 392e13f2f..2bb2a3aab 100644
--- a/compiler/rustc_lint/src/pass_by_value.rs
+++ b/compiler/rustc_lint/src/pass_by_value.rs
@@ -50,7 +50,7 @@ fn path_for_pass_by_value(cx: &LateContext<'_>, ty: &hir::Ty<'_>) -> Option<Stri
return Some(format!("{}{}", name, gen_args(cx, path_segment)));
}
Res::SelfTyAlias { alias_to: did, is_trait_impl: false, .. } => {
- if let ty::Adt(adt, substs) = cx.tcx.type_of(did).kind() {
+ if let ty::Adt(adt, substs) = cx.tcx.type_of(did).subst_identity().kind() {
if cx.tcx.has_attr(adt.did(), sym::rustc_pass_by_value) {
return Some(cx.tcx.def_path_str_with_substs(adt.did(), substs));
}
diff --git a/compiler/rustc_lint/src/passes.rs b/compiler/rustc_lint/src/passes.rs
index 0bf01c4e5..16964565b 100644
--- a/compiler/rustc_lint/src/passes.rs
+++ b/compiler/rustc_lint/src/passes.rs
@@ -4,6 +4,7 @@ use rustc_ast as ast;
use rustc_hir as hir;
use rustc_session::lint::builtin::HardwiredLints;
use rustc_session::lint::LintPass;
+use rustc_span::def_id::LocalDefId;
use rustc_span::symbol::Ident;
use rustc_span::Span;
@@ -36,7 +37,7 @@ macro_rules! late_lint_methods {
b: &'tcx hir::FnDecl<'tcx>,
c: &'tcx hir::Body<'tcx>,
d: Span,
- e: hir::HirId);
+ e: LocalDefId);
fn check_trait_item(a: &'tcx hir::TraitItem<'tcx>);
fn check_impl_item(a: &'tcx hir::ImplItem<'tcx>);
fn check_impl_item_post(a: &'tcx hir::ImplItem<'tcx>);
diff --git a/compiler/rustc_lint/src/types.rs b/compiler/rustc_lint/src/types.rs
index be47a3e23..85958c417 100644
--- a/compiler/rustc_lint/src/types.rs
+++ b/compiler/rustc_lint/src/types.rs
@@ -1,19 +1,25 @@
-use crate::lints::{
- AtomicOrderingFence, AtomicOrderingLoad, AtomicOrderingStore, ImproperCTypes,
- InvalidAtomicOrderingDiag, OnlyCastu8ToChar, OverflowingBinHex, OverflowingBinHexSign,
- OverflowingBinHexSub, OverflowingInt, OverflowingIntHelp, OverflowingLiteral, OverflowingUInt,
- RangeEndpointOutOfRange, UnusedComparisons, VariantSizeDifferencesDiag,
+use crate::{
+ fluent_generated as fluent,
+ lints::{
+ AtomicOrderingFence, AtomicOrderingLoad, AtomicOrderingStore, ImproperCTypes,
+ InvalidAtomicOrderingDiag, OnlyCastu8ToChar, OverflowingBinHex, OverflowingBinHexSign,
+ OverflowingBinHexSub, OverflowingInt, OverflowingIntHelp, OverflowingLiteral,
+ OverflowingUInt, RangeEndpointOutOfRange, UnusedComparisons, VariantSizeDifferencesDiag,
+ },
};
use crate::{LateContext, LateLintPass, LintContext};
use rustc_ast as ast;
use rustc_attr as attr;
use rustc_data_structures::fx::FxHashSet;
-use rustc_errors::{fluent, DiagnosticMessage};
+use rustc_errors::DiagnosticMessage;
use rustc_hir as hir;
use rustc_hir::{is_range_literal, Expr, ExprKind, Node};
use rustc_middle::ty::layout::{IntegerExt, LayoutOf, SizeSkeleton};
use rustc_middle::ty::subst::SubstsRef;
-use rustc_middle::ty::{self, AdtKind, DefIdTree, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable};
+use rustc_middle::ty::{
+ self, AdtKind, DefIdTree, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitableExt,
+};
+use rustc_span::def_id::LocalDefId;
use rustc_span::source_map;
use rustc_span::symbol::sym;
use rustc_span::{Span, Symbol};
@@ -650,7 +656,7 @@ pub fn transparent_newtype_field<'a, 'tcx>(
) -> Option<&'a ty::FieldDef> {
let param_env = tcx.param_env(variant.def_id);
variant.fields.iter().find(|field| {
- let field_ty = tcx.type_of(field.did);
+ let field_ty = tcx.type_of(field.did).subst_identity();
let is_zst = tcx.layout_of(param_env.and(field_ty)).map_or(false, |layout| layout.is_zst());
!is_zst
})
@@ -1107,6 +1113,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
| ty::Closure(..)
| ty::Generator(..)
| ty::GeneratorWitness(..)
+ | ty::GeneratorWitnessMIR(..)
| ty::Placeholder(..)
| ty::FnDef(..) => bug!("unexpected type in foreign function: {:?}", ty),
}
@@ -1142,7 +1149,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
fn check_for_opaque_ty(&mut self, sp: Span, ty: Ty<'tcx>) -> bool {
struct ProhibitOpaqueTypes;
- impl<'tcx> ty::visit::TypeVisitor<'tcx> for ProhibitOpaqueTypes {
+ impl<'tcx> ty::visit::TypeVisitor<TyCtxt<'tcx>> for ProhibitOpaqueTypes {
type BreakTy = Ty<'tcx>;
fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
@@ -1223,9 +1230,8 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
}
}
- fn check_foreign_fn(&mut self, id: hir::HirId, decl: &hir::FnDecl<'_>) {
- let def_id = self.cx.tcx.hir().local_def_id(id);
- let sig = self.cx.tcx.fn_sig(def_id);
+ fn check_foreign_fn(&mut self, def_id: LocalDefId, decl: &hir::FnDecl<'_>) {
+ let sig = self.cx.tcx.fn_sig(def_id).subst_identity();
let sig = self.cx.tcx.erase_late_bound_regions(sig);
for (input_ty, input_hir) in iter::zip(sig.inputs(), decl.inputs) {
@@ -1238,9 +1244,8 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
}
}
- fn check_foreign_static(&mut self, id: hir::HirId, span: Span) {
- let def_id = self.cx.tcx.hir().local_def_id(id);
- let ty = self.cx.tcx.type_of(def_id);
+ fn check_foreign_static(&mut self, id: hir::OwnerId, span: Span) {
+ let ty = self.cx.tcx.type_of(id).subst_identity();
self.check_type_for_ffi_and_report_errors(span, ty, true, false);
}
@@ -1260,10 +1265,10 @@ impl<'tcx> LateLintPass<'tcx> for ImproperCTypesDeclarations {
if !vis.is_internal_abi(abi) {
match it.kind {
hir::ForeignItemKind::Fn(ref decl, _, _) => {
- vis.check_foreign_fn(it.hir_id(), decl);
+ vis.check_foreign_fn(it.owner_id.def_id, decl);
}
hir::ForeignItemKind::Static(ref ty, _) => {
- vis.check_foreign_static(it.hir_id(), ty.span);
+ vis.check_foreign_static(it.owner_id, ty.span);
}
hir::ForeignItemKind::Type => (),
}
@@ -1279,7 +1284,7 @@ impl<'tcx> LateLintPass<'tcx> for ImproperCTypesDefinitions {
decl: &'tcx hir::FnDecl<'_>,
_: &'tcx hir::Body<'_>,
_: Span,
- hir_id: hir::HirId,
+ id: LocalDefId,
) {
use hir::intravisit::FnKind;
@@ -1291,7 +1296,7 @@ impl<'tcx> LateLintPass<'tcx> for ImproperCTypesDefinitions {
let mut vis = ImproperCTypesVisitor { cx, mode: CItemKind::Definition };
if !vis.is_internal_abi(abi) {
- vis.check_foreign_fn(hir_id, decl);
+ vis.check_foreign_fn(id, decl);
}
}
}
@@ -1301,7 +1306,7 @@ declare_lint_pass!(VariantSizeDifferences => [VARIANT_SIZE_DIFFERENCES]);
impl<'tcx> LateLintPass<'tcx> for VariantSizeDifferences {
fn check_item(&mut self, cx: &LateContext<'_>, it: &hir::Item<'_>) {
if let hir::ItemKind::Enum(ref enum_definition, _) = it.kind {
- let t = cx.tcx.type_of(it.owner_id);
+ let t = cx.tcx.type_of(it.owner_id).subst_identity();
let ty = cx.tcx.erase_regions(t);
let Ok(layout) = cx.layout_of(ty) else { return };
let Variants::Multiple {
@@ -1421,7 +1426,7 @@ impl InvalidAtomicOrdering {
&& recognized_names.contains(&method_path.ident.name)
&& let Some(m_def_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id)
&& let Some(impl_did) = cx.tcx.impl_of_method(m_def_id)
- && let Some(adt) = cx.tcx.type_of(impl_did).ty_adt_def()
+ && let Some(adt) = cx.tcx.type_of(impl_did).subst_identity().ty_adt_def()
// skip extension traits, only lint functions from the standard library
&& cx.tcx.trait_id_of_impl(impl_did).is_none()
&& let parent = cx.tcx.parent(adt.did())
diff --git a/compiler/rustc_lint/src/unused.rs b/compiler/rustc_lint/src/unused.rs
index 4c9b3df2d..3a92f5806 100644
--- a/compiler/rustc_lint/src/unused.rs
+++ b/compiler/rustc_lint/src/unused.rs
@@ -1,7 +1,7 @@
use crate::lints::{
PathStatementDrop, PathStatementDropSub, PathStatementNoEffect, UnusedAllocationDiag,
- UnusedAllocationMutDiag, UnusedClosure, UnusedDef, UnusedDelim, UnusedDelimSuggestion,
- UnusedGenerator, UnusedImportBracesDiag, UnusedOp, UnusedResult,
+ UnusedAllocationMutDiag, UnusedClosure, UnusedDef, UnusedDefSuggestion, UnusedDelim,
+ UnusedDelimSuggestion, UnusedGenerator, UnusedImportBracesDiag, UnusedOp, UnusedResult,
};
use crate::Lint;
use crate::{EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintContext};
@@ -309,7 +309,7 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults {
None
}
}
- ty::Array(ty, len) => match len.try_eval_usize(cx.tcx, cx.param_env) {
+ ty::Array(ty, len) => match len.try_eval_target_usize(cx.tcx, cx.param_env) {
// If the array is empty we don't lint, to avoid false positives
Some(0) | None => None,
// If the array is definitely non-empty, we can do `#[must_use]` checking.
@@ -418,6 +418,19 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults {
);
}
MustUsePath::Def(span, def_id, reason) => {
+ let suggestion = if matches!(
+ cx.tcx.get_diagnostic_name(*def_id),
+ Some(sym::add)
+ | Some(sym::sub)
+ | Some(sym::mul)
+ | Some(sym::div)
+ | Some(sym::rem)
+ | Some(sym::neg),
+ ) {
+ Some(UnusedDefSuggestion::Default { span: span.shrink_to_lo() })
+ } else {
+ None
+ };
cx.emit_spanned_lint(
UNUSED_MUST_USE,
*span,
@@ -427,6 +440,7 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults {
cx,
def_id: *def_id,
note: *reason,
+ suggestion,
},
);
}
@@ -495,6 +509,7 @@ enum UnusedDelimsCtx {
ArrayLenExpr,
AnonConst,
MatchArmExpr,
+ IndexExpr,
}
impl From<UnusedDelimsCtx> for &'static str {
@@ -514,6 +529,7 @@ impl From<UnusedDelimsCtx> for &'static str {
UnusedDelimsCtx::LetScrutineeExpr => "`let` scrutinee expression",
UnusedDelimsCtx::ArrayLenExpr | UnusedDelimsCtx::AnonConst => "const expression",
UnusedDelimsCtx::MatchArmExpr => "match arm expression",
+ UnusedDelimsCtx::IndexExpr => "index expression",
}
}
}
@@ -661,6 +677,10 @@ trait UnusedDelimLint {
keep_space: (bool, bool),
) {
let primary_span = if let Some((lo, hi)) = spans {
+ if hi.is_empty() {
+ // do not point at delims that do not exist
+ return;
+ }
MultiSpan::from(vec![lo, hi])
} else {
MultiSpan::from(value_span)
@@ -733,6 +753,8 @@ trait UnusedDelimLint {
(value, UnusedDelimsCtx::ReturnValue, false, Some(left), None)
}
+ Index(_, ref value) => (value, UnusedDelimsCtx::IndexExpr, false, None, None),
+
Assign(_, ref value, _) | AssignOp(.., ref value) => {
(value, UnusedDelimsCtx::AssignedValue, false, None, None)
}
diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs
index b6481d70b..46ec1a2dc 100644
--- a/compiler/rustc_lint_defs/src/builtin.rs
+++ b/compiler/rustc_lint_defs/src/builtin.rs
@@ -1188,51 +1188,6 @@ declare_lint! {
}
declare_lint! {
- /// The `unaligned_references` lint detects unaligned references to fields
- /// of [packed] structs.
- ///
- /// [packed]: https://doc.rust-lang.org/reference/type-layout.html#the-alignment-modifiers
- ///
- /// ### Example
- ///
- /// ```rust,compile_fail
- /// #[repr(packed)]
- /// pub struct Foo {
- /// field1: u64,
- /// field2: u8,
- /// }
- ///
- /// fn main() {
- /// unsafe {
- /// let foo = Foo { field1: 0, field2: 0 };
- /// let _ = &foo.field1;
- /// println!("{}", foo.field1); // An implicit `&` is added here, triggering the lint.
- /// }
- /// }
- /// ```
- ///
- /// {{produces}}
- ///
- /// ### Explanation
- ///
- /// Creating a reference to an insufficiently aligned packed field is [undefined behavior] and
- /// should be disallowed. Using an `unsafe` block does not change anything about this. Instead,
- /// the code should do a copy of the data in the packed field or use raw pointers and unaligned
- /// accesses. See [issue #82523] for more information.
- ///
- /// [undefined behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html
- /// [issue #82523]: https://github.com/rust-lang/rust/issues/82523
- pub UNALIGNED_REFERENCES,
- Deny,
- "detects unaligned references to fields of packed structs",
- @future_incompatible = FutureIncompatibleInfo {
- reference: "issue #82523 <https://github.com/rust-lang/rust/issues/82523>",
- reason: FutureIncompatibilityReason::FutureReleaseErrorReportNow,
- };
- report_in_external_macro
-}
-
-declare_lint! {
/// The `const_item_mutation` lint detects attempts to mutate a `const`
/// item.
///
@@ -3308,7 +3263,6 @@ declare_lint_pass! {
PUB_USE_OF_PRIVATE_EXTERN_CRATE,
INVALID_TYPE_PARAM_DEFAULT,
RENAMED_AND_REMOVED_LINTS,
- UNALIGNED_REFERENCES,
CONST_ITEM_MUTATION,
PATTERNS_IN_FNS_WITHOUT_BODY,
MISSING_FRAGMENT_SPECIFIER,
@@ -3381,6 +3335,7 @@ declare_lint_pass! {
REPR_TRANSPARENT_EXTERNAL_PRIVATE_FIELDS,
NAMED_ARGUMENTS_USED_POSITIONALLY,
IMPLIED_BOUNDS_ENTAILMENT,
+ BYTE_SLICE_IN_PACKED_STRUCT_WITH_DERIVE,
]
}
@@ -3531,9 +3486,15 @@ declare_lint! {
///
/// ### Explanation
///
- /// Previously, there were very like checks being performed on `#[doc(..)]`
- /// unlike the other attributes. It'll now catch all the issues that it
- /// silently ignored previously.
+ /// Previously, incorrect usage of the `#[doc(..)]` attribute was not
+ /// being validated. Usually these should be rejected as a hard error,
+ /// but this lint was introduced to avoid breaking any existing
+ /// crates which included them.
+ ///
+ /// This is a [future-incompatible] lint to transition this to a hard
+ /// error in the future. See [issue #82730] for more details.
+ ///
+ /// [issue #82730]: https://github.com/rust-lang/rust/issues/82730
pub INVALID_DOC_ATTRIBUTES,
Warn,
"detects invalid `#[doc(...)]` attributes",
@@ -4109,3 +4070,66 @@ declare_lint! {
reason: FutureIncompatibilityReason::FutureReleaseErrorReportNow,
};
}
+
+declare_lint! {
+ /// The `byte_slice_in_packed_struct_with_derive` lint detects cases where a byte slice field
+ /// (`[u8]`) or string slice field (`str`) is used in a `packed` struct that derives one or
+ /// more built-in traits.
+ ///
+ /// ### Example
+ ///
+ /// ```rust
+ /// #[repr(packed)]
+ /// #[derive(Hash)]
+ /// struct FlexZeroSlice {
+ /// width: u8,
+ /// data: [u8],
+ /// }
+ /// ```
+ ///
+ /// {{produces}}
+ ///
+ /// ### Explanation
+ ///
+ /// This was previously accepted but is being phased out, because fields in packed structs are
+ /// now required to implement `Copy` for `derive` to work. Byte slices and string slices are a
+ /// temporary exception because certain crates depended on them.
+ pub BYTE_SLICE_IN_PACKED_STRUCT_WITH_DERIVE,
+ Warn,
+ "`[u8]` or `str` used in a packed struct with `derive`",
+ @future_incompatible = FutureIncompatibleInfo {
+ reference: "issue #107457 <https://github.com/rust-lang/rust/issues/107457>",
+ reason: FutureIncompatibilityReason::FutureReleaseErrorReportNow,
+ };
+ report_in_external_macro
+}
+
+declare_lint! {
+ /// The `invalid_macro_export_arguments` lint detects cases where `#[macro_export]` is being used with invalid arguments.
+ ///
+ /// ### Example
+ ///
+ /// ```rust,compile_fail
+ /// #![deny(invalid_macro_export_arguments)]
+ ///
+ /// #[macro_export(invalid_parameter)]
+ /// macro_rules! myMacro {
+ /// () => {
+ /// // [...]
+ /// }
+ /// }
+ ///
+ /// #[macro_export(too, many, items)]
+ /// ```
+ ///
+ /// {{produces}}
+ ///
+ /// ### Explanation
+ ///
+ /// The only valid argument is `#[macro_export(local_inner_macros)]` or no argument (`#[macro_export]`).
+ /// You can't have multiple arguments in a `#[macro_export(..)]`, or mention arguments other than `local_inner_macros`.
+ ///
+ pub INVALID_MACRO_EXPORT_ARGUMENTS,
+ Warn,
+ "\"invalid_parameter\" isn't a valid argument for `#[macro_export]`",
+}
diff --git a/compiler/rustc_lint_defs/src/lib.rs b/compiler/rustc_lint_defs/src/lib.rs
index 7054d1e9f..534aff7fb 100644
--- a/compiler/rustc_lint_defs/src/lib.rs
+++ b/compiler/rustc_lint_defs/src/lib.rs
@@ -521,6 +521,14 @@ pub enum BuiltinLintDiagnostics {
/// Indicates if the named argument is used as a width/precision for formatting
is_formatting_arg: bool,
},
+ ByteSliceInPackedStructWithDerive,
+ UnusedExternCrate {
+ removal_span: Span,
+ },
+ ExternCrateNotIdiomatic {
+ vis_span: Span,
+ ident_span: Span,
+ },
}
/// Lints that are buffered up early on in the `Session` before the
diff --git a/compiler/rustc_llvm/llvm-wrapper/LLVMWrapper.h b/compiler/rustc_llvm/llvm-wrapper/LLVMWrapper.h
index 727cfc441..058906283 100644
--- a/compiler/rustc_llvm/llvm-wrapper/LLVMWrapper.h
+++ b/compiler/rustc_llvm/llvm-wrapper/LLVMWrapper.h
@@ -4,7 +4,6 @@
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/SmallVector.h"
-#include "llvm/ADT/Triple.h"
#include "llvm/Analysis/Lint.h"
#include "llvm/Analysis/Passes.h"
#include "llvm/IR/IRBuilder.h"
@@ -15,6 +14,7 @@
#include "llvm/Support/Debug.h"
#include "llvm/Support/DynamicLibrary.h"
#include "llvm/Support/FormattedStream.h"
+#include "llvm/Support/JSON.h"
#include "llvm/Support/Host.h"
#include "llvm/Support/Memory.h"
#include "llvm/Support/SourceMgr.h"
@@ -44,6 +44,12 @@
#include "llvm/IR/IRPrintingPasses.h"
#include "llvm/Linker/Linker.h"
+#if LLVM_VERSION_GE(16, 0)
+#include "llvm/TargetParser/Triple.h"
+#else
+#include "llvm/ADT/Triple.h"
+#endif
+
extern "C" void LLVMRustSetLastError(const char *);
enum class LLVMRustResult { Success, Failure };
diff --git a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp
index f728bff0e..4761ce83f 100644
--- a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp
+++ b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp
@@ -9,11 +9,11 @@
#include "llvm/Analysis/TargetLibraryInfo.h"
#include "llvm/Analysis/TargetTransformInfo.h"
#include "llvm/CodeGen/TargetSubtargetInfo.h"
-#include "llvm/InitializePasses.h"
#include "llvm/IR/AutoUpgrade.h"
#include "llvm/IR/AssemblyAnnotationWriter.h"
#include "llvm/IR/IntrinsicInst.h"
#include "llvm/IR/Verifier.h"
+#include "llvm/MC/TargetRegistry.h"
#include "llvm/Object/ObjectFile.h"
#include "llvm/Object/IRObjectFile.h"
#include "llvm/Passes/PassBuilder.h"
@@ -21,12 +21,10 @@
#include "llvm/Passes/StandardInstrumentations.h"
#include "llvm/Support/CBindingWrapping.h"
#include "llvm/Support/FileSystem.h"
-#include "llvm/Support/Host.h"
-#if LLVM_VERSION_LT(14, 0)
-#include "llvm/Support/TargetRegistry.h"
-#else
-#include "llvm/MC/TargetRegistry.h"
+#if LLVM_VERSION_GE(17, 0)
+#include "llvm/Support/VirtualFileSystem.h"
#endif
+#include "llvm/Support/Host.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Transforms/IPO/PassManagerBuilder.h"
#include "llvm/Transforms/IPO/AlwaysInliner.h"
@@ -59,22 +57,6 @@ typedef struct LLVMOpaqueTargetMachine *LLVMTargetMachineRef;
DEFINE_STDCXX_CONVERSION_FUNCTIONS(Pass, LLVMPassRef)
DEFINE_STDCXX_CONVERSION_FUNCTIONS(TargetMachine, LLVMTargetMachineRef)
-extern "C" void LLVMInitializePasses() {
- PassRegistry &Registry = *PassRegistry::getPassRegistry();
- initializeCore(Registry);
- initializeCodeGen(Registry);
- initializeScalarOpts(Registry);
- initializeVectorization(Registry);
- initializeIPO(Registry);
- initializeAnalysis(Registry);
- initializeTransformUtils(Registry);
- initializeInstCombine(Registry);
-#if LLVM_VERSION_LT(16, 0)
- initializeInstrumentation(Registry);
-#endif
- initializeTarget(Registry);
-}
-
extern "C" void LLVMTimeTraceProfilerInitialize() {
timeTraceProfilerInitialize(
/* TimeTraceGranularity */ 0,
@@ -264,10 +246,6 @@ enum class LLVMRustPassBuilderOptLevel {
Oz,
};
-#if LLVM_VERSION_LT(14,0)
-using OptimizationLevel = PassBuilder::OptimizationLevel;
-#endif
-
static OptimizationLevel fromRust(LLVMRustPassBuilderOptLevel Level) {
switch (Level) {
case LLVMRustPassBuilderOptLevel::O0:
@@ -599,6 +577,8 @@ struct LLVMRustSanitizerOptions {
bool SanitizeThread;
bool SanitizeHWAddress;
bool SanitizeHWAddressRecover;
+ bool SanitizeKernelAddress;
+ bool SanitizeKernelAddressRecover;
};
extern "C" LLVMRustResult
@@ -652,20 +632,39 @@ LLVMRustOptimize(
#else
std::optional<PGOOptions> PGOOpt;
#endif
+#if LLVM_VERSION_GE(17, 0)
+ auto FS = vfs::getRealFileSystem();
+#endif
if (PGOGenPath) {
assert(!PGOUsePath && !PGOSampleUsePath);
- PGOOpt = PGOOptions(PGOGenPath, "", "", PGOOptions::IRInstr,
- PGOOptions::NoCSAction, DebugInfoForProfiling);
+ PGOOpt = PGOOptions(PGOGenPath, "", "",
+#if LLVM_VERSION_GE(17, 0)
+ FS,
+#endif
+ PGOOptions::IRInstr, PGOOptions::NoCSAction,
+ DebugInfoForProfiling);
} else if (PGOUsePath) {
assert(!PGOSampleUsePath);
- PGOOpt = PGOOptions(PGOUsePath, "", "", PGOOptions::IRUse,
- PGOOptions::NoCSAction, DebugInfoForProfiling);
+ PGOOpt = PGOOptions(PGOUsePath, "", "",
+#if LLVM_VERSION_GE(17, 0)
+ FS,
+#endif
+ PGOOptions::IRUse, PGOOptions::NoCSAction,
+ DebugInfoForProfiling);
} else if (PGOSampleUsePath) {
- PGOOpt = PGOOptions(PGOSampleUsePath, "", "", PGOOptions::SampleUse,
- PGOOptions::NoCSAction, DebugInfoForProfiling);
+ PGOOpt = PGOOptions(PGOSampleUsePath, "", "",
+#if LLVM_VERSION_GE(17, 0)
+ FS,
+#endif
+ PGOOptions::SampleUse, PGOOptions::NoCSAction,
+ DebugInfoForProfiling);
} else if (DebugInfoForProfiling) {
- PGOOpt = PGOOptions("", "", "", PGOOptions::NoAction,
- PGOOptions::NoCSAction, DebugInfoForProfiling);
+ PGOOpt = PGOOptions("", "", "",
+#if LLVM_VERSION_GE(17, 0)
+ FS,
+#endif
+ PGOOptions::NoAction, PGOOptions::NoCSAction,
+ DebugInfoForProfiling);
}
PassBuilder PB(TM, PTO, PGOOpt, &PIC);
@@ -725,28 +724,19 @@ LLVMRustOptimize(
if (SanitizerOptions) {
if (SanitizerOptions->SanitizeMemory) {
-#if LLVM_VERSION_GE(14, 0)
MemorySanitizerOptions Options(
SanitizerOptions->SanitizeMemoryTrackOrigins,
SanitizerOptions->SanitizeMemoryRecover,
/*CompileKernel=*/false,
/*EagerChecks=*/true);
-#else
- MemorySanitizerOptions Options(
- SanitizerOptions->SanitizeMemoryTrackOrigins,
- SanitizerOptions->SanitizeMemoryRecover,
- /*CompileKernel=*/false);
-#endif
OptimizerLastEPCallbacks.push_back(
[Options](ModulePassManager &MPM, OptimizationLevel Level) {
-#if LLVM_VERSION_GE(14, 0) && LLVM_VERSION_LT(16, 0)
+#if LLVM_VERSION_LT(16, 0)
MPM.addPass(ModuleMemorySanitizerPass(Options));
+ MPM.addPass(createModuleToFunctionPassAdaptor(MemorySanitizerPass(Options)));
#else
MPM.addPass(MemorySanitizerPass(Options));
#endif
-#if LLVM_VERSION_LT(16, 0)
- MPM.addPass(createModuleToFunctionPassAdaptor(MemorySanitizerPass(Options)));
-#endif
}
);
}
@@ -754,26 +744,23 @@ LLVMRustOptimize(
if (SanitizerOptions->SanitizeThread) {
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()));
}
);
}
- if (SanitizerOptions->SanitizeAddress) {
+ if (SanitizerOptions->SanitizeAddress || SanitizerOptions->SanitizeKernelAddress) {
OptimizerLastEPCallbacks.push_back(
[SanitizerOptions](ModulePassManager &MPM, OptimizationLevel Level) {
+ auto CompileKernel = SanitizerOptions->SanitizeKernelAddress;
#if LLVM_VERSION_LT(15, 0)
MPM.addPass(RequireAnalysisPass<ASanGlobalsMetadataAnalysis, Module>());
#endif
-#if LLVM_VERSION_GE(14, 0)
AddressSanitizerOptions opts = AddressSanitizerOptions{
- /*CompileKernel=*/false,
- SanitizerOptions->SanitizeAddressRecover,
+ CompileKernel,
+ SanitizerOptions->SanitizeAddressRecover
+ || SanitizerOptions->SanitizeKernelAddressRecover,
/*UseAfterScope=*/true,
AsanDetectStackUseAfterReturnMode::Runtime,
};
@@ -782,28 +769,16 @@ LLVMRustOptimize(
#else
MPM.addPass(AddressSanitizerPass(opts));
#endif
-#else
- MPM.addPass(ModuleAddressSanitizerPass(
- /*CompileKernel=*/false, SanitizerOptions->SanitizeAddressRecover));
- MPM.addPass(createModuleToFunctionPassAdaptor(AddressSanitizerPass(
- /*CompileKernel=*/false, SanitizerOptions->SanitizeAddressRecover,
- /*UseAfterScope=*/true)));
-#endif
}
);
}
if (SanitizerOptions->SanitizeHWAddress) {
OptimizerLastEPCallbacks.push_back(
[SanitizerOptions](ModulePassManager &MPM, OptimizationLevel Level) {
-#if LLVM_VERSION_GE(14, 0)
HWAddressSanitizerOptions opts(
/*CompileKernel=*/false, SanitizerOptions->SanitizeHWAddressRecover,
/*DisableOptimization=*/false);
MPM.addPass(HWAddressSanitizerPass(opts));
-#else
- MPM.addPass(HWAddressSanitizerPass(
- /*CompileKernel=*/false, SanitizerOptions->SanitizeHWAddressRecover));
-#endif
}
);
}
@@ -1012,23 +987,8 @@ LLVMRustPrintModule(LLVMModuleRef M, const char *Path, DemangleFn Demangle) {
}
extern "C" void LLVMRustPrintPasses() {
- LLVMInitializePasses();
- struct MyListener : PassRegistrationListener {
- void passEnumerate(const PassInfo *Info) {
- StringRef PassArg = Info->getPassArgument();
- StringRef PassName = Info->getPassName();
- if (!PassArg.empty()) {
- // These unsigned->signed casts could theoretically overflow, but
- // realistically never will (and even if, the result is implementation
- // defined rather plain UB).
- printf("%15.*s - %.*s\n", (int)PassArg.size(), PassArg.data(),
- (int)PassName.size(), PassName.data());
- }
- }
- } Listener;
-
- PassRegistry *PR = PassRegistry::getPassRegistry();
- PR->enumerateWith(&Listener);
+ PassBuilder PB;
+ PB.printPassNames(outs());
}
extern "C" void LLVMRustRunRestrictionPass(LLVMModuleRef M, char **Symbols,
@@ -1306,11 +1266,7 @@ 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;
}
diff --git a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp
index 87b0e1273..e3493caaa 100644
--- a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp
+++ b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp
@@ -63,11 +63,7 @@ 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;
@@ -249,18 +245,10 @@ static Attribute::AttrKind fromRust(LLVMRustAttribute Kind) {
template<typename T> static inline void AddAttributes(T *t, unsigned Index,
LLVMAttributeRef *Attrs, size_t AttrsLen) {
AttributeList PAL = t->getAttributes();
- AttributeList PALNew;
-#if LLVM_VERSION_LT(14, 0)
- AttrBuilder B;
- for (LLVMAttributeRef Attr : makeArrayRef(Attrs, AttrsLen))
- B.addAttribute(unwrap(Attr));
- PALNew = PAL.addAttributes(t->getContext(), Index, B);
-#else
AttrBuilder B(t->getContext());
for (LLVMAttributeRef Attr : ArrayRef<LLVMAttributeRef>(Attrs, AttrsLen))
B.addAttribute(unwrap(Attr));
- PALNew = PAL.addAttributesAtIndex(t->getContext(), Index, B);
-#endif
+ AttributeList PALNew = PAL.addAttributesAtIndex(t->getContext(), Index, B);
t->setAttributes(PALNew);
}
@@ -1763,6 +1751,19 @@ LLVMRustModuleCost(LLVMModuleRef M) {
return std::distance(std::begin(f), std::end(f));
}
+extern "C" void
+LLVMRustModuleInstructionStats(LLVMModuleRef M, RustStringRef Str)
+{
+ RawRustStringOstream OS(Str);
+ llvm::json::OStream JOS(OS);
+ auto Module = unwrap(M);
+
+ JOS.object([&] {
+ JOS.attribute("module", Module->getName());
+ JOS.attribute("total", Module->getInstructionCount());
+ });
+}
+
// Vector reductions:
extern "C" LLVMValueRef
LLVMRustBuildVectorReduceFAdd(LLVMBuilderRef B, LLVMValueRef Acc, LLVMValueRef Src) {
diff --git a/compiler/rustc_log/src/lib.rs b/compiler/rustc_log/src/lib.rs
index fc1cabd2d..22924efa9 100644
--- a/compiler/rustc_log/src/lib.rs
+++ b/compiler/rustc_log/src/lib.rs
@@ -14,7 +14,7 @@
//!
//! ```
//! fn main() {
-//! rustc_log::init_rustc_env_logger().unwrap();
+//! rustc_log::init_env_logger("LOG").unwrap();
//!
//! let edition = rustc_span::edition::Edition::Edition2021;
//! rustc_span::create_session_globals_then(edition, || {
@@ -23,9 +23,9 @@
//! }
//! ```
//!
-//! Now `RUSTC_LOG=debug cargo run` will run your minimal main.rs and show
+//! Now `LOG=debug cargo run` will run your minimal main.rs and show
//! rustc's debug logging. In a workflow like this, one might also add
-//! `std::env::set_var("RUSTC_LOG", "debug")` to the top of main so that `cargo
+//! `std::env::set_var("LOG", "debug")` to the top of main so that `cargo
//! run` by itself is sufficient to get logs.
//!
//! The reason rustc_log is a tiny separate crate, as opposed to exposing the
@@ -53,26 +53,7 @@ use tracing_subscriber::fmt::{
};
use tracing_subscriber::layer::SubscriberExt;
-pub fn init_rustc_env_logger() -> Result<(), Error> {
- init_rustc_env_logger_with_backtrace_option(&None)
-}
-
-pub fn init_rustc_env_logger_with_backtrace_option(
- backtrace_target: &Option<String>,
-) -> Result<(), Error> {
- init_env_logger_with_backtrace_option("RUSTC_LOG", backtrace_target)
-}
-
-/// In contrast to `init_rustc_env_logger` this allows you to choose an env var
-/// other than `RUSTC_LOG`.
pub fn init_env_logger(env: &str) -> Result<(), Error> {
- init_env_logger_with_backtrace_option(env, &None)
-}
-
-pub fn init_env_logger_with_backtrace_option(
- env: &str,
- backtrace_target: &Option<String>,
-) -> Result<(), Error> {
let filter = match env::var(env) {
Ok(env) => EnvFilter::new(env),
_ => EnvFilter::default().add_directive(Directive::from(LevelFilter::WARN)),
@@ -106,16 +87,16 @@ pub fn init_env_logger_with_backtrace_option(
let layer = layer.with_thread_ids(true).with_thread_names(true);
let subscriber = tracing_subscriber::Registry::default().with(filter).with(layer);
- match backtrace_target {
- Some(str) => {
+ match env::var(format!("{env}_BACKTRACE")) {
+ Ok(str) => {
let fmt_layer = tracing_subscriber::fmt::layer()
.with_writer(io::stderr)
.without_time()
- .event_format(BacktraceFormatter { backtrace_target: str.to_string() });
+ .event_format(BacktraceFormatter { backtrace_target: str });
let subscriber = subscriber.with(fmt_layer);
tracing::subscriber::set_global_default(subscriber).unwrap();
}
- None => {
+ Err(_) => {
tracing::subscriber::set_global_default(subscriber).unwrap();
}
};
diff --git a/compiler/rustc_macros/src/diagnostics/diagnostic.rs b/compiler/rustc_macros/src/diagnostics/diagnostic.rs
index 9ff944864..12a954258 100644
--- a/compiler/rustc_macros/src/diagnostics/diagnostic.rs
+++ b/compiler/rustc_macros/src/diagnostics/diagnostic.rs
@@ -57,7 +57,7 @@ impl<'a> DiagnosticDerive<'a> {
}
Some(slug) => {
quote! {
- let mut #diag = #handler.struct_diagnostic(rustc_errors::fluent::#slug);
+ let mut #diag = #handler.struct_diagnostic(crate::fluent_generated::#slug);
}
}
};
@@ -149,7 +149,7 @@ impl<'a> LintDiagnosticDerive<'a> {
}
Some(slug) => {
quote! {
- rustc_errors::fluent::#slug.into()
+ crate::fluent_generated::#slug.into()
}
}
}
diff --git a/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs b/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs
index e405462bb..46068f8c8 100644
--- a/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs
+++ b/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs
@@ -322,11 +322,7 @@ impl<'a> DiagnosticDeriveVariantBuilder<'a> {
let generated_code = self
.generate_inner_field_code(
attr,
- FieldInfo {
- binding: binding_info,
- ty: inner_ty.inner_type().unwrap_or(&field.ty),
- span: &field.span(),
- },
+ FieldInfo { binding: binding_info, ty: inner_ty, span: &field.span() },
binding,
)
.unwrap_or_else(|v| v.to_compile_error());
@@ -418,9 +414,9 @@ impl<'a> DiagnosticDeriveVariantBuilder<'a> {
Ok(self.add_spanned_subdiagnostic(binding, &fn_ident, slug))
}
SubdiagnosticKind::Note | SubdiagnosticKind::Help | SubdiagnosticKind::Warn => {
- if type_matches_path(info.ty, &["rustc_span", "Span"]) {
+ if type_matches_path(info.ty.inner_type(), &["rustc_span", "Span"]) {
Ok(self.add_spanned_subdiagnostic(binding, &fn_ident, slug))
- } else if type_is_unit(info.ty) {
+ } else if type_is_unit(info.ty.inner_type()) {
Ok(self.add_subdiagnostic(&fn_ident, slug))
} else {
report_type_error(attr, "`Span` or `()`")?
@@ -432,6 +428,15 @@ impl<'a> DiagnosticDeriveVariantBuilder<'a> {
code_field,
code_init,
} => {
+ if let FieldInnerTy::Vec(_) = info.ty {
+ throw_invalid_attr!(attr, &meta, |diag| {
+ diag
+ .note("`#[suggestion(...)]` applied to `Vec` field is ambiguous")
+ .help("to show a suggestion consisting of multiple parts, use a `Subdiagnostic` annotated with `#[multipart_suggestion(...)]`")
+ .help("to show a variable set of suggestions, use a `Vec` of `Subdiagnostic`s annotated with `#[suggestion(...)]`")
+ });
+ }
+
let (span_field, mut applicability) = self.span_and_applicability_of_ty(info)?;
if let Some((static_applicability, span)) = static_applicability {
@@ -447,7 +452,7 @@ impl<'a> DiagnosticDeriveVariantBuilder<'a> {
Ok(quote! {
#diag.span_suggestions_with_style(
#span_field,
- rustc_errors::fluent::#slug,
+ crate::fluent_generated::#slug,
#code_field,
#applicability,
#style
@@ -471,7 +476,7 @@ impl<'a> DiagnosticDeriveVariantBuilder<'a> {
quote! {
#diag.#fn_name(
#field_binding,
- rustc_errors::fluent::#fluent_attr_identifier
+ crate::fluent_generated::#fluent_attr_identifier
);
}
}
@@ -481,7 +486,7 @@ impl<'a> DiagnosticDeriveVariantBuilder<'a> {
fn add_subdiagnostic(&self, kind: &Ident, fluent_attr_identifier: Path) -> TokenStream {
let diag = &self.parent.diag;
quote! {
- #diag.#kind(rustc_errors::fluent::#fluent_attr_identifier);
+ #diag.#kind(crate::fluent_generated::#fluent_attr_identifier);
}
}
@@ -489,7 +494,7 @@ impl<'a> DiagnosticDeriveVariantBuilder<'a> {
&self,
info: FieldInfo<'_>,
) -> Result<(TokenStream, SpannedOption<TokenStream>), DiagnosticDeriveError> {
- match &info.ty {
+ match &info.ty.inner_type() {
// If `ty` is `Span` w/out applicability, then use `Applicability::Unspecified`.
ty @ Type::Path(..) if type_matches_path(ty, &["rustc_span", "Span"]) => {
let binding = &info.binding.binding;
diff --git a/compiler/rustc_macros/src/diagnostics/fluent.rs b/compiler/rustc_macros/src/diagnostics/fluent.rs
index 32338f9df..38c0f4895 100644
--- a/compiler/rustc_macros/src/diagnostics/fluent.rs
+++ b/compiler/rustc_macros/src/diagnostics/fluent.rs
@@ -4,7 +4,10 @@ use annotate_snippets::{
};
use fluent_bundle::{FluentBundle, FluentError, FluentResource};
use fluent_syntax::{
- ast::{Attribute, Entry, Identifier, Message},
+ ast::{
+ Attribute, Entry, Expression, Identifier, InlineExpression, Message, Pattern,
+ PatternElement,
+ },
parser::ParserError,
};
use proc_macro::{Diagnostic, Level, Span};
@@ -16,52 +19,9 @@ use std::{
io::Read,
path::{Path, PathBuf},
};
-use syn::{
- parse::{Parse, ParseStream},
- parse_macro_input,
- punctuated::Punctuated,
- token, Ident, LitStr, Result,
-};
+use syn::{parse_macro_input, Ident, LitStr};
use unic_langid::langid;
-struct Resource {
- krate: Ident,
- #[allow(dead_code)]
- fat_arrow_token: token::FatArrow,
- resource_path: LitStr,
-}
-
-impl Parse for Resource {
- fn parse(input: ParseStream<'_>) -> Result<Self> {
- Ok(Resource {
- krate: input.parse()?,
- fat_arrow_token: input.parse()?,
- resource_path: input.parse()?,
- })
- }
-}
-
-struct Resources(Punctuated<Resource, token::Comma>);
-
-impl Parse for Resources {
- fn parse(input: ParseStream<'_>) -> Result<Self> {
- let mut resources = Punctuated::new();
- loop {
- if input.is_empty() || input.peek(token::Brace) {
- break;
- }
- let value = input.parse()?;
- resources.push_value(value);
- if !input.peek(token::Comma) {
- break;
- }
- let punct = input.parse()?;
- resources.push_punct(punct);
- }
- Ok(Resources(resources))
- }
-}
-
/// Helper function for returning an absolute path for macro-invocation relative file paths.
///
/// If the input is already absolute, then the input is returned. If the input is not absolute,
@@ -81,224 +41,285 @@ fn invocation_relative_path_to_absolute(span: Span, path: &str) -> PathBuf {
}
}
+/// Tokens to be returned when the macro cannot proceed.
+fn failed(crate_name: &Ident) -> proc_macro::TokenStream {
+ quote! {
+ pub static DEFAULT_LOCALE_RESOURCE: &'static str = "";
+
+ #[allow(non_upper_case_globals)]
+ #[doc(hidden)]
+ pub(crate) mod fluent_generated {
+ pub mod #crate_name {
+ }
+
+ pub mod _subdiag {
+ pub const help: crate::SubdiagnosticMessage =
+ crate::SubdiagnosticMessage::FluentAttr(std::borrow::Cow::Borrowed("help"));
+ pub const note: crate::SubdiagnosticMessage =
+ crate::SubdiagnosticMessage::FluentAttr(std::borrow::Cow::Borrowed("note"));
+ pub const warn: crate::SubdiagnosticMessage =
+ crate::SubdiagnosticMessage::FluentAttr(std::borrow::Cow::Borrowed("warn"));
+ pub const label: crate::SubdiagnosticMessage =
+ crate::SubdiagnosticMessage::FluentAttr(std::borrow::Cow::Borrowed("label"));
+ pub const suggestion: crate::SubdiagnosticMessage =
+ crate::SubdiagnosticMessage::FluentAttr(std::borrow::Cow::Borrowed("suggestion"));
+ }
+ }
+ }
+ .into()
+}
+
/// See [rustc_macros::fluent_messages].
pub(crate) fn fluent_messages(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
- let resources = parse_macro_input!(input as Resources);
+ let crate_name = std::env::var("CARGO_PKG_NAME")
+ // If `CARGO_PKG_NAME` is missing, then we're probably running in a test, so use
+ // `no_crate`.
+ .unwrap_or_else(|_| "no_crate".to_string())
+ .replace("rustc_", "");
// Cannot iterate over individual messages in a bundle, so do that using the
// `FluentResource` instead. Construct a bundle anyway to find out if there are conflicting
// messages in the resources.
let mut bundle = FluentBundle::new(vec![langid!("en-US")]);
- // Map of Fluent identifiers to the `Span` of the resource that defined them, used for better
- // diagnostics.
- let mut previous_defns = HashMap::new();
-
// Set of Fluent attribute names already output, to avoid duplicate type errors - any given
// constant created for a given attribute is the same.
let mut previous_attrs = HashSet::new();
- let mut includes = TokenStream::new();
- let mut generated = TokenStream::new();
+ let resource_str = parse_macro_input!(input as LitStr);
+ let resource_span = resource_str.span().unwrap();
+ let relative_ftl_path = resource_str.value();
+ let absolute_ftl_path = invocation_relative_path_to_absolute(resource_span, &relative_ftl_path);
- for res in resources.0 {
- let krate_span = res.krate.span().unwrap();
- let path_span = res.resource_path.span().unwrap();
+ let crate_name = Ident::new(&crate_name, resource_str.span());
- let relative_ftl_path = res.resource_path.value();
- let absolute_ftl_path =
- invocation_relative_path_to_absolute(krate_span, &relative_ftl_path);
- // As this macro also outputs an `include_str!` for this file, the macro will always be
- // re-executed when the file changes.
- let mut resource_file = match File::open(absolute_ftl_path) {
- Ok(resource_file) => resource_file,
- Err(e) => {
- Diagnostic::spanned(path_span, Level::Error, "could not open Fluent resource")
- .note(e.to_string())
- .emit();
- continue;
- }
- };
- let mut resource_contents = String::new();
- if let Err(e) = resource_file.read_to_string(&mut resource_contents) {
- Diagnostic::spanned(path_span, Level::Error, "could not read Fluent resource")
+ // As this macro also outputs an `include_str!` for this file, the macro will always be
+ // re-executed when the file changes.
+ let mut resource_file = match File::open(absolute_ftl_path) {
+ Ok(resource_file) => resource_file,
+ Err(e) => {
+ Diagnostic::spanned(resource_span, Level::Error, "could not open Fluent resource")
.note(e.to_string())
.emit();
- continue;
+ return failed(&crate_name);
}
- let resource = match FluentResource::try_new(resource_contents) {
- Ok(resource) => resource,
- Err((this, errs)) => {
- Diagnostic::spanned(path_span, Level::Error, "could not parse Fluent resource")
- .help("see additional errors emitted")
- .emit();
- for ParserError { pos, slice: _, kind } in errs {
- let mut err = kind.to_string();
- // Entirely unnecessary string modification so that the error message starts
- // with a lowercase as rustc errors do.
- err.replace_range(
- 0..1,
- &err.chars().next().unwrap().to_lowercase().to_string(),
- );
+ };
+ let mut resource_contents = String::new();
+ if let Err(e) = resource_file.read_to_string(&mut resource_contents) {
+ Diagnostic::spanned(resource_span, Level::Error, "could not read Fluent resource")
+ .note(e.to_string())
+ .emit();
+ return failed(&crate_name);
+ }
+
+ let resource = match FluentResource::try_new(resource_contents) {
+ Ok(resource) => resource,
+ Err((this, errs)) => {
+ Diagnostic::spanned(resource_span, Level::Error, "could not parse Fluent resource")
+ .help("see additional errors emitted")
+ .emit();
+ for ParserError { pos, slice: _, kind } in errs {
+ let mut err = kind.to_string();
+ // Entirely unnecessary string modification so that the error message starts
+ // with a lowercase as rustc errors do.
+ err.replace_range(0..1, &err.chars().next().unwrap().to_lowercase().to_string());
- let line_starts: Vec<usize> = std::iter::once(0)
- .chain(
- this.source()
- .char_indices()
- .filter_map(|(i, c)| Some(i + 1).filter(|_| c == '\n')),
- )
- .collect();
- let line_start = line_starts
- .iter()
- .enumerate()
- .map(|(line, idx)| (line + 1, idx))
- .filter(|(_, idx)| **idx <= pos.start)
- .last()
- .unwrap()
- .0;
+ let line_starts: Vec<usize> = std::iter::once(0)
+ .chain(
+ this.source()
+ .char_indices()
+ .filter_map(|(i, c)| Some(i + 1).filter(|_| c == '\n')),
+ )
+ .collect();
+ let line_start = line_starts
+ .iter()
+ .enumerate()
+ .map(|(line, idx)| (line + 1, idx))
+ .filter(|(_, idx)| **idx <= pos.start)
+ .last()
+ .unwrap()
+ .0;
- let snippet = Snippet {
- title: Some(Annotation {
- label: Some(&err),
- id: None,
+ let snippet = Snippet {
+ title: Some(Annotation {
+ label: Some(&err),
+ id: None,
+ annotation_type: AnnotationType::Error,
+ }),
+ footer: vec![],
+ slices: vec![Slice {
+ source: this.source(),
+ line_start,
+ origin: Some(&relative_ftl_path),
+ fold: true,
+ annotations: vec![SourceAnnotation {
+ label: "",
annotation_type: AnnotationType::Error,
- }),
- footer: vec![],
- slices: vec![Slice {
- source: this.source(),
- line_start,
- origin: Some(&relative_ftl_path),
- fold: true,
- annotations: vec![SourceAnnotation {
- label: "",
- annotation_type: AnnotationType::Error,
- range: (pos.start, pos.end - 1),
- }],
+ range: (pos.start, pos.end - 1),
}],
- opt: Default::default(),
- };
- let dl = DisplayList::from(snippet);
- eprintln!("{dl}\n");
+ }],
+ opt: Default::default(),
+ };
+ let dl = DisplayList::from(snippet);
+ eprintln!("{dl}\n");
+ }
+
+ return failed(&crate_name);
+ }
+ };
+
+ let mut constants = TokenStream::new();
+ let mut previous_defns = HashMap::new();
+ let mut message_refs = Vec::new();
+ for entry in resource.entries() {
+ if let Entry::Message(Message { id: Identifier { name }, attributes, value, .. }) = entry {
+ let _ = previous_defns.entry(name.to_string()).or_insert(resource_span);
+ if name.contains('-') {
+ Diagnostic::spanned(
+ resource_span,
+ Level::Error,
+ format!("name `{name}` contains a '-' character"),
+ )
+ .help("replace any '-'s with '_'s")
+ .emit();
+ }
+
+ if let Some(Pattern { elements }) = value {
+ for elt in elements {
+ if let PatternElement::Placeable {
+ expression:
+ Expression::Inline(InlineExpression::MessageReference { id, .. }),
+ } = elt
+ {
+ message_refs.push((id.name, *name));
+ }
}
+ }
+
+ // `typeck_foo_bar` => `foo_bar` (in `typeck.ftl`)
+ // `const_eval_baz` => `baz` (in `const_eval.ftl`)
+ // `const-eval-hyphen-having` => `hyphen_having` (in `const_eval.ftl`)
+ // The last case we error about above, but we want to fall back gracefully
+ // so that only the error is being emitted and not also one about the macro
+ // failing.
+ let crate_prefix = format!("{crate_name}_");
+
+ let snake_name = name.replace('-', "_");
+ if !snake_name.starts_with(&crate_prefix) {
+ Diagnostic::spanned(
+ resource_span,
+ Level::Error,
+ format!("name `{name}` does not start with the crate name"),
+ )
+ .help(format!(
+ "prepend `{crate_prefix}` to the slug name: `{crate_prefix}{snake_name}`"
+ ))
+ .emit();
+ };
+ let snake_name = Ident::new(&snake_name, resource_str.span());
+
+ if !previous_attrs.insert(snake_name.clone()) {
continue;
}
- };
- let mut constants = TokenStream::new();
- for entry in resource.entries() {
- let span = res.krate.span();
- if let Entry::Message(Message { id: Identifier { name }, attributes, .. }) = entry {
- let _ = previous_defns.entry(name.to_string()).or_insert(path_span);
+ let msg = format!("Constant referring to Fluent message `{name}` from `{crate_name}`");
+ constants.extend(quote! {
+ #[doc = #msg]
+ pub const #snake_name: crate::DiagnosticMessage =
+ crate::DiagnosticMessage::FluentIdentifier(
+ std::borrow::Cow::Borrowed(#name),
+ None
+ );
+ });
- if name.contains('-') {
- Diagnostic::spanned(
- path_span,
- Level::Error,
- format!("name `{name}` contains a '-' character"),
- )
- .help("replace any '-'s with '_'s")
- .emit();
+ for Attribute { id: Identifier { name: attr_name }, .. } in attributes {
+ let snake_name = Ident::new(
+ &format!("{}{}", &crate_prefix, &attr_name.replace('-', "_")),
+ resource_str.span(),
+ );
+ if !previous_attrs.insert(snake_name.clone()) {
+ continue;
}
- // Require that the message name starts with the crate name
- // `hir_typeck_foo_bar` (in `hir_typeck.ftl`)
- // `const_eval_baz` (in `const_eval.ftl`)
- // `const-eval-hyphen-having` => `hyphen_having` (in `const_eval.ftl`)
- // The last case we error about above, but we want to fall back gracefully
- // so that only the error is being emitted and not also one about the macro
- // failing.
- let crate_prefix = format!("{}_", res.krate);
-
- let snake_name = name.replace('-', "_");
- if !snake_name.starts_with(&crate_prefix) {
+ if attr_name.contains('-') {
Diagnostic::spanned(
- path_span,
+ resource_span,
Level::Error,
- format!("name `{name}` does not start with the crate name"),
+ format!("attribute `{attr_name}` contains a '-' character"),
)
- .help(format!(
- "prepend `{crate_prefix}` to the slug name: `{crate_prefix}{snake_name}`"
- ))
+ .help("replace any '-'s with '_'s")
.emit();
- };
-
- let snake_name = Ident::new(&snake_name, span);
+ }
+ let msg = format!(
+ "Constant referring to Fluent message `{name}.{attr_name}` from `{crate_name}`"
+ );
constants.extend(quote! {
- pub const #snake_name: crate::DiagnosticMessage =
- crate::DiagnosticMessage::FluentIdentifier(
- std::borrow::Cow::Borrowed(#name),
- None
+ #[doc = #msg]
+ pub const #snake_name: crate::SubdiagnosticMessage =
+ crate::SubdiagnosticMessage::FluentAttr(
+ std::borrow::Cow::Borrowed(#attr_name)
);
});
-
- for Attribute { id: Identifier { name: attr_name }, .. } in attributes {
- let snake_name = Ident::new(&attr_name.replace('-', "_"), span);
- if !previous_attrs.insert(snake_name.clone()) {
- continue;
- }
-
- if attr_name.contains('-') {
- Diagnostic::spanned(
- path_span,
- Level::Error,
- format!("attribute `{attr_name}` contains a '-' character"),
- )
- .help("replace any '-'s with '_'s")
- .emit();
- }
-
- constants.extend(quote! {
- pub const #snake_name: crate::SubdiagnosticMessage =
- crate::SubdiagnosticMessage::FluentAttr(
- std::borrow::Cow::Borrowed(#attr_name)
- );
- });
- }
}
}
+ }
- if let Err(errs) = bundle.add_resource(resource) {
- for e in errs {
- match e {
- FluentError::Overriding { kind, id } => {
- Diagnostic::spanned(
- path_span,
- Level::Error,
- format!("overrides existing {kind}: `{id}`"),
- )
- .span_help(previous_defns[&id], "previously defined in this resource")
- .emit();
- }
- FluentError::ResolverError(_) | FluentError::ParserError(_) => unreachable!(),
+ for (mref, name) in message_refs.into_iter() {
+ if !previous_defns.contains_key(mref) {
+ Diagnostic::spanned(
+ resource_span,
+ Level::Error,
+ format!("referenced message `{mref}` does not exist (in message `{name}`)"),
+ )
+ .help(&format!("you may have meant to use a variable reference (`{{${mref}}}`)"))
+ .emit();
+ }
+ }
+
+ if let Err(errs) = bundle.add_resource(resource) {
+ for e in errs {
+ match e {
+ FluentError::Overriding { kind, id } => {
+ Diagnostic::spanned(
+ resource_span,
+ Level::Error,
+ format!("overrides existing {kind}: `{id}`"),
+ )
+ .emit();
}
+ FluentError::ResolverError(_) | FluentError::ParserError(_) => unreachable!(),
}
}
-
- includes.extend(quote! { include_str!(#relative_ftl_path), });
-
- generated.extend(constants);
}
quote! {
+ /// Raw content of Fluent resource for this crate, generated by `fluent_messages` macro,
+ /// imported by `rustc_driver` to include all crates' resources in one bundle.
+ pub static DEFAULT_LOCALE_RESOURCE: &'static str = include_str!(#relative_ftl_path);
+
#[allow(non_upper_case_globals)]
#[doc(hidden)]
- pub mod fluent_generated {
- pub static DEFAULT_LOCALE_RESOURCES: &'static [&'static str] = &[
- #includes
- ];
-
- #generated
+ /// Auto-generated constants for type-checked references to Fluent messages.
+ pub(crate) mod fluent_generated {
+ #constants
+ /// Constants expected to exist by the diagnostic derive macros to use as default Fluent
+ /// identifiers for different subdiagnostic kinds.
pub mod _subdiag {
+ /// Default for `#[help]`
pub const help: crate::SubdiagnosticMessage =
crate::SubdiagnosticMessage::FluentAttr(std::borrow::Cow::Borrowed("help"));
+ /// Default for `#[note]`
pub const note: crate::SubdiagnosticMessage =
crate::SubdiagnosticMessage::FluentAttr(std::borrow::Cow::Borrowed("note"));
+ /// Default for `#[warn]`
pub const warn: crate::SubdiagnosticMessage =
crate::SubdiagnosticMessage::FluentAttr(std::borrow::Cow::Borrowed("warn"));
+ /// Default for `#[label]`
pub const label: crate::SubdiagnosticMessage =
crate::SubdiagnosticMessage::FluentAttr(std::borrow::Cow::Borrowed("label"));
+ /// Default for `#[suggestion]`
pub const suggestion: crate::SubdiagnosticMessage =
crate::SubdiagnosticMessage::FluentAttr(std::borrow::Cow::Borrowed("suggestion"));
}
diff --git a/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs b/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs
index baffd3cec..90660fc1f 100644
--- a/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs
+++ b/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs
@@ -247,11 +247,7 @@ impl<'parent, 'a> SubdiagnosticDeriveVariantBuilder<'parent, 'a> {
return quote! {};
}
- let info = FieldInfo {
- binding,
- ty: inner_ty.inner_type().unwrap_or(&ast.ty),
- span: &ast.span(),
- };
+ let info = FieldInfo { binding, ty: inner_ty, span: &ast.span() };
let generated = self
.generate_field_code_inner(kind_stats, attr, info, inner_ty.will_iterate())
@@ -312,6 +308,21 @@ impl<'parent, 'a> SubdiagnosticDeriveVariantBuilder<'parent, 'a> {
let binding = info.binding.binding.clone();
// FIXME(#100717): support `Option<Span>` on `primary_span` like in the
// diagnostic derive
+ if !matches!(info.ty, FieldInnerTy::Plain(_)) {
+ throw_invalid_attr!(attr, &Meta::Path(path), |diag| {
+ let diag = diag.note("there must be exactly one primary span");
+
+ if kind_stats.has_normal_suggestion {
+ diag.help(
+ "to create a suggestion with multiple spans, \
+ use `#[multipart_suggestion]` instead",
+ )
+ } else {
+ diag
+ }
+ });
+ }
+
self.span_field.set_once(binding, span);
}
@@ -501,7 +512,9 @@ impl<'parent, 'a> SubdiagnosticDeriveVariantBuilder<'parent, 'a> {
let mut calls = TokenStream::new();
for (kind, slug) in kind_slugs {
let message = format_ident!("__message");
- calls.extend(quote! { let #message = #f(#diag, rustc_errors::fluent::#slug.into()); });
+ calls.extend(
+ quote! { let #message = #f(#diag, crate::fluent_generated::#slug.into()); },
+ );
let name = format_ident!("{}{}", if span_field.is_some() { "span_" } else { "" }, kind);
let call = match kind {
diff --git a/compiler/rustc_macros/src/diagnostics/utils.rs b/compiler/rustc_macros/src/diagnostics/utils.rs
index 6f52a3de1..27b8f676f 100644
--- a/compiler/rustc_macros/src/diagnostics/utils.rs
+++ b/compiler/rustc_macros/src/diagnostics/utils.rs
@@ -80,7 +80,7 @@ fn report_error_if_not_applied_to_ty(
path: &[&str],
ty_name: &str,
) -> Result<(), DiagnosticDeriveError> {
- if !type_matches_path(info.ty, path) {
+ if !type_matches_path(info.ty.inner_type(), path) {
report_type_error(attr, ty_name)?;
}
@@ -105,8 +105,8 @@ pub(crate) fn report_error_if_not_applied_to_span(
attr: &Attribute,
info: &FieldInfo<'_>,
) -> Result<(), DiagnosticDeriveError> {
- if !type_matches_path(info.ty, &["rustc_span", "Span"])
- && !type_matches_path(info.ty, &["rustc_errors", "MultiSpan"])
+ if !type_matches_path(info.ty.inner_type(), &["rustc_span", "Span"])
+ && !type_matches_path(info.ty.inner_type(), &["rustc_errors", "MultiSpan"])
{
report_type_error(attr, "`Span` or `MultiSpan`")?;
}
@@ -115,44 +115,50 @@ pub(crate) fn report_error_if_not_applied_to_span(
}
/// Inner type of a field and type of wrapper.
+#[derive(Copy, Clone)]
pub(crate) enum FieldInnerTy<'ty> {
/// Field is wrapped in a `Option<$inner>`.
Option(&'ty Type),
/// Field is wrapped in a `Vec<$inner>`.
Vec(&'ty Type),
/// Field isn't wrapped in an outer type.
- None,
+ Plain(&'ty Type),
}
impl<'ty> FieldInnerTy<'ty> {
/// Returns inner type for a field, if there is one.
///
- /// - If `ty` is an `Option`, returns `FieldInnerTy::Option { inner: (inner type) }`.
- /// - If `ty` is a `Vec`, returns `FieldInnerTy::Vec { inner: (inner type) }`.
- /// - Otherwise returns `None`.
+ /// - If `ty` is an `Option<Inner>`, returns `FieldInnerTy::Option(Inner)`.
+ /// - If `ty` is a `Vec<Inner>`, returns `FieldInnerTy::Vec(Inner)`.
+ /// - Otherwise returns `FieldInnerTy::Plain(ty)`.
pub(crate) fn from_type(ty: &'ty Type) -> Self {
- let variant: &dyn Fn(&'ty Type) -> FieldInnerTy<'ty> =
- if type_matches_path(ty, &["std", "option", "Option"]) {
- &FieldInnerTy::Option
- } else if type_matches_path(ty, &["std", "vec", "Vec"]) {
- &FieldInnerTy::Vec
- } else {
- return FieldInnerTy::None;
+ fn single_generic_type(ty: &Type) -> &Type {
+ let Type::Path(ty_path) = ty else {
+ panic!("expected path type");
};
- if let Type::Path(ty_path) = ty {
let path = &ty_path.path;
let ty = path.segments.iter().last().unwrap();
- if let syn::PathArguments::AngleBracketed(bracketed) = &ty.arguments {
- if bracketed.args.len() == 1 {
- if let syn::GenericArgument::Type(ty) = &bracketed.args[0] {
- return variant(ty);
- }
- }
- }
+ let syn::PathArguments::AngleBracketed(bracketed) = &ty.arguments else {
+ panic!("expected bracketed generic arguments");
+ };
+
+ assert_eq!(bracketed.args.len(), 1);
+
+ let syn::GenericArgument::Type(ty) = &bracketed.args[0] else {
+ panic!("expected generic parameter to be a type generic");
+ };
+
+ ty
}
- unreachable!();
+ if type_matches_path(ty, &["std", "option", "Option"]) {
+ FieldInnerTy::Option(single_generic_type(ty))
+ } else if type_matches_path(ty, &["std", "vec", "Vec"]) {
+ FieldInnerTy::Vec(single_generic_type(ty))
+ } else {
+ FieldInnerTy::Plain(ty)
+ }
}
/// Returns `true` if `FieldInnerTy::with` will result in iteration for this inner type (i.e.
@@ -160,15 +166,16 @@ impl<'ty> FieldInnerTy<'ty> {
pub(crate) fn will_iterate(&self) -> bool {
match self {
FieldInnerTy::Vec(..) => true,
- FieldInnerTy::Option(..) | FieldInnerTy::None => false,
+ FieldInnerTy::Option(..) | FieldInnerTy::Plain(_) => false,
}
}
- /// Returns `Option` containing inner type if there is one.
- pub(crate) fn inner_type(&self) -> Option<&'ty Type> {
+ /// Returns the inner type.
+ pub(crate) fn inner_type(&self) -> &'ty Type {
match self {
- FieldInnerTy::Option(inner) | FieldInnerTy::Vec(inner) => Some(inner),
- FieldInnerTy::None => None,
+ FieldInnerTy::Option(inner) | FieldInnerTy::Vec(inner) | FieldInnerTy::Plain(inner) => {
+ inner
+ }
}
}
@@ -185,7 +192,7 @@ impl<'ty> FieldInnerTy<'ty> {
#inner
}
},
- FieldInnerTy::None => quote! { #inner },
+ FieldInnerTy::Plain(..) => quote! { #inner },
}
}
}
@@ -194,7 +201,7 @@ impl<'ty> FieldInnerTy<'ty> {
/// `generate_*` methods from walking the attributes themselves.
pub(crate) struct FieldInfo<'a> {
pub(crate) binding: &'a BindingInfo<'a>,
- pub(crate) ty: &'a Type,
+ pub(crate) ty: FieldInnerTy<'a>,
pub(crate) span: &'a proc_macro2::Span,
}
diff --git a/compiler/rustc_macros/src/lib.rs b/compiler/rustc_macros/src/lib.rs
index bb3722fe1..737500cc2 100644
--- a/compiler/rustc_macros/src/lib.rs
+++ b/compiler/rustc_macros/src/lib.rs
@@ -61,9 +61,7 @@ pub fn newtype_index(input: TokenStream) -> TokenStream {
/// For example, given the following invocation of the macro..
///
/// ```ignore (rust)
-/// fluent_messages! {
-/// typeck => "./typeck.ftl",
-/// }
+/// fluent_messages! { "./typeck.ftl" }
/// ```
/// ..where `typeck.ftl` has the following contents..
///
@@ -77,9 +75,7 @@ pub fn newtype_index(input: TokenStream) -> TokenStream {
/// will generate the following code:
///
/// ```ignore (rust)
-/// pub static DEFAULT_LOCALE_RESOURCES: &'static [&'static str] = &[
-/// include_str!("./typeck.ftl"),
-/// ];
+/// pub static DEFAULT_LOCALE_RESOURCE: &'static [&'static str] = include_str!("./typeck.ftl");
///
/// mod fluent_generated {
/// mod typeck {
@@ -124,8 +120,27 @@ decl_derive!([TyDecodable] => serialize::type_decodable_derive);
decl_derive!([TyEncodable] => serialize::type_encodable_derive);
decl_derive!([MetadataDecodable] => serialize::meta_decodable_derive);
decl_derive!([MetadataEncodable] => serialize::meta_encodable_derive);
-decl_derive!([TypeFoldable, attributes(type_foldable)] => type_foldable::type_foldable_derive);
-decl_derive!([TypeVisitable, attributes(type_visitable)] => type_visitable::type_visitable_derive);
+decl_derive!(
+ [TypeFoldable, attributes(type_foldable)] =>
+ /// Derives `TypeFoldable` for the annotated `struct` or `enum` (`union` is not supported).
+ ///
+ /// The fold will produce a value of the same struct or enum variant as the input, with
+ /// each field respectively folded using the `TypeFoldable` implementation for its type.
+ /// However, if a field of a struct or an enum variant is annotated with
+ /// `#[type_foldable(identity)]` then that field will retain its incumbent value (and its
+ /// type is not required to implement `TypeFoldable`).
+ type_foldable::type_foldable_derive
+);
+decl_derive!(
+ [TypeVisitable, attributes(type_visitable)] =>
+ /// Derives `TypeVisitable` for the annotated `struct` or `enum` (`union` is not supported).
+ ///
+ /// Each field of the struct or enum variant will be visited in definition order, using the
+ /// `TypeVisitable` implementation for its type. However, if a field of a struct or an enum
+ /// variant is annotated with `#[type_visitable(ignore)]` then that field will not be
+ /// visited (and its type is not required to implement `TypeVisitable`).
+ type_visitable::type_visitable_derive
+);
decl_derive!([Lift, attributes(lift)] => lift::lift_derive);
decl_derive!(
[Diagnostic, attributes(
diff --git a/compiler/rustc_macros/src/serialize.rs b/compiler/rustc_macros/src/serialize.rs
index 82e6972d0..8d017d149 100644
--- a/compiler/rustc_macros/src/serialize.rs
+++ b/compiler/rustc_macros/src/serialize.rs
@@ -42,6 +42,12 @@ fn decodable_body(
}
let ty_name = s.ast().ident.to_string();
let decode_body = match s.variants() {
+ [] => {
+ let message = format!("`{}` has no variants to decode", ty_name);
+ quote! {
+ panic!(#message)
+ }
+ }
[vi] => vi.construct(|field, _index| decode_field(field)),
variants => {
let match_inner: TokenStream = variants
@@ -139,6 +145,11 @@ fn encodable_body(
});
let encode_body = match s.variants() {
+ [] => {
+ quote! {
+ match *self {}
+ }
+ }
[_] => {
let encode_inner = s.each_variant(|vi| {
vi.bindings()
@@ -160,6 +171,23 @@ fn encodable_body(
}
}
_ => {
+ let disc = {
+ let mut variant_idx = 0usize;
+ let encode_inner = s.each_variant(|_| {
+ let result = quote! {
+ #variant_idx
+ };
+ variant_idx += 1;
+ result
+ });
+ quote! {
+ let disc = match *self {
+ #encode_inner
+ };
+ ::rustc_serialize::Encoder::emit_usize(__encoder, disc);
+ }
+ };
+
let mut variant_idx = 0usize;
let encode_inner = s.each_variant(|vi| {
let encode_fields: TokenStream = vi
@@ -176,26 +204,11 @@ fn encodable_body(
result
})
.collect();
-
- let result = if !vi.bindings().is_empty() {
- quote! {
- ::rustc_serialize::Encoder::emit_enum_variant(
- __encoder,
- #variant_idx,
- |__encoder| { #encode_fields }
- )
- }
- } else {
- quote! {
- ::rustc_serialize::Encoder::emit_fieldless_enum_variant::<#variant_idx>(
- __encoder,
- )
- }
- };
variant_idx += 1;
- result
+ encode_fields
});
quote! {
+ #disc
match *self {
#encode_inner
}
diff --git a/compiler/rustc_macros/src/type_foldable.rs b/compiler/rustc_macros/src/type_foldable.rs
index 23e619221..388e254cd 100644
--- a/compiler/rustc_macros/src/type_foldable.rs
+++ b/compiler/rustc_macros/src/type_foldable.rs
@@ -1,5 +1,5 @@
-use quote::quote;
-use syn::parse_quote;
+use quote::{quote, ToTokens};
+use syn::{parse_quote, Attribute, Meta, NestedMeta};
pub fn type_foldable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::TokenStream {
if let syn::Data::Union(_) = s.ast().data {
@@ -16,16 +16,37 @@ pub fn type_foldable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::
let bindings = vi.bindings();
vi.construct(|_, index| {
let bind = &bindings[index];
- quote! {
- ::rustc_middle::ty::fold::TypeFoldable::try_fold_with(#bind, __folder)?
+
+ // retain value of fields with #[type_foldable(identity)]
+ let fixed = bind
+ .ast()
+ .attrs
+ .iter()
+ .map(Attribute::parse_meta)
+ .filter_map(Result::ok)
+ .flat_map(|attr| match attr {
+ Meta::List(list) if list.path.is_ident("type_foldable") => list.nested,
+ _ => Default::default(),
+ })
+ .any(|nested| match nested {
+ NestedMeta::Meta(Meta::Path(path)) => path.is_ident("identity"),
+ _ => false,
+ });
+
+ if fixed {
+ bind.to_token_stream()
+ } else {
+ quote! {
+ ::rustc_middle::ty::fold::TypeFoldable::try_fold_with(#bind, __folder)?
+ }
}
})
});
s.bound_impl(
- quote!(::rustc_middle::ty::fold::TypeFoldable<'tcx>),
+ quote!(::rustc_middle::ty::fold::TypeFoldable<::rustc_middle::ty::TyCtxt<'tcx>>),
quote! {
- fn try_fold_with<__F: ::rustc_middle::ty::fold::FallibleTypeFolder<'tcx>>(
+ fn try_fold_with<__F: ::rustc_middle::ty::fold::FallibleTypeFolder<::rustc_middle::ty::TyCtxt<'tcx>>>(
self,
__folder: &mut __F
) -> Result<Self, __F::Error> {
diff --git a/compiler/rustc_macros/src/type_visitable.rs b/compiler/rustc_macros/src/type_visitable.rs
index 1f95661ce..f6f4c4779 100644
--- a/compiler/rustc_macros/src/type_visitable.rs
+++ b/compiler/rustc_macros/src/type_visitable.rs
@@ -1,11 +1,28 @@
use quote::quote;
-use syn::parse_quote;
+use syn::{parse_quote, Attribute, Meta, NestedMeta};
pub fn type_visitable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::TokenStream {
if let syn::Data::Union(_) = s.ast().data {
panic!("cannot derive on union")
}
+ // ignore fields with #[type_visitable(ignore)]
+ s.filter(|bi| {
+ !bi.ast()
+ .attrs
+ .iter()
+ .map(Attribute::parse_meta)
+ .filter_map(Result::ok)
+ .flat_map(|attr| match attr {
+ Meta::List(list) if list.path.is_ident("type_visitable") => list.nested,
+ _ => Default::default(),
+ })
+ .any(|nested| match nested {
+ NestedMeta::Meta(Meta::Path(path)) => path.is_ident("ignore"),
+ _ => false,
+ })
+ });
+
if !s.ast().generics.lifetimes().any(|lt| lt.lifetime.ident == "tcx") {
s.add_impl_generic(parse_quote! { 'tcx });
}
@@ -19,9 +36,9 @@ pub fn type_visitable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2:
s.bind_with(|_| synstructure::BindStyle::Move);
s.bound_impl(
- quote!(::rustc_middle::ty::visit::TypeVisitable<'tcx>),
+ quote!(::rustc_middle::ty::visit::TypeVisitable<::rustc_middle::ty::TyCtxt<'tcx>>),
quote! {
- fn visit_with<__V: ::rustc_middle::ty::visit::TypeVisitor<'tcx>>(
+ fn visit_with<__V: ::rustc_middle::ty::visit::TypeVisitor<::rustc_middle::ty::TyCtxt<'tcx>>>(
&self,
__visitor: &mut __V
) -> ::std::ops::ControlFlow<__V::BreakTy> {
diff --git a/compiler/rustc_metadata/Cargo.toml b/compiler/rustc_metadata/Cargo.toml
index 6d85103c9..bee5c8541 100644
--- a/compiler/rustc_metadata/Cargo.toml
+++ b/compiler/rustc_metadata/Cargo.toml
@@ -6,6 +6,7 @@ edition = "2021"
[lib]
[dependencies]
+bitflags = "1.2.1"
libloading = "0.7.1"
odht = { version = "0.3.1", features = ["nightly"] }
snap = "1"
diff --git a/compiler/rustc_error_messages/locales/en-US/metadata.ftl b/compiler/rustc_metadata/locales/en-US.ftl
index 79b8b4172..79b8b4172 100644
--- a/compiler/rustc_error_messages/locales/en-US/metadata.ftl
+++ b/compiler/rustc_metadata/locales/en-US.ftl
diff --git a/compiler/rustc_metadata/src/creader.rs b/compiler/rustc_metadata/src/creader.rs
index 653f2b39d..b05626311 100644
--- a/compiler/rustc_metadata/src/creader.rs
+++ b/compiler/rustc_metadata/src/creader.rs
@@ -1,10 +1,6 @@
//! Validates all used crates and extern libraries and loads their metadata
-use crate::errors::{
- ConflictingAllocErrorHandler, ConflictingGlobalAlloc, CrateNotPanicRuntime,
- GlobalAllocRequired, NoMultipleAllocErrorHandler, NoMultipleGlobalAlloc, NoPanicStrategy,
- NoTransitiveNeedsDep, NotProfilerRuntime, ProfilerBuiltinsNeedsCore,
-};
+use crate::errors;
use crate::locator::{CrateError, CrateLocator, CratePaths};
use crate::rmeta::{CrateDep, CrateMetadata, CrateNumMap, CrateRoot, MetadataBlob};
@@ -12,15 +8,15 @@ use rustc_ast::expand::allocator::AllocatorKind;
use rustc_ast::{self as ast, *};
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_data_structures::svh::Svh;
-use rustc_data_structures::sync::{Lrc, ReadGuard};
+use rustc_data_structures::sync::MappedReadGuard;
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::ty::TyCtxt;
use rustc_session::config::{self, CrateType, ExternLocation};
+use rustc_session::cstore::ExternCrateSource;
use rustc_session::cstore::{CrateDepKind, CrateSource, ExternCrate};
-use rustc_session::cstore::{ExternCrateSource, MetadataLoaderDyn};
use rustc_session::lint;
use rustc_session::output::validate_crate_name;
use rustc_session::search_paths::PathKind;
@@ -33,11 +29,11 @@ use rustc_target::spec::{PanicStrategy, TargetTriple};
use proc_macro::bridge::client::ProcMacro;
use std::ops::Fn;
use std::path::Path;
-use std::{cmp, env};
+use std::time::Duration;
+use std::{cmp, env, iter};
-#[derive(Clone)]
pub struct CStore {
- metas: IndexVec<CrateNum, Option<Lrc<CrateMetadata>>>,
+ metas: IndexVec<CrateNum, Option<Box<CrateMetadata>>>,
injected_panic_runtime: Option<CrateNum>,
/// This crate needs an allocator and either provides it itself, or finds it in a dependency.
/// If the above is true, then this field denotes the kind of the found allocator.
@@ -64,17 +60,22 @@ impl std::fmt::Debug for CStore {
}
}
-pub struct CrateLoader<'a> {
+pub struct CrateLoader<'a, 'tcx: 'a> {
// Immutable configuration.
- sess: &'a Session,
- metadata_loader: &'a MetadataLoaderDyn,
- definitions: ReadGuard<'a, Definitions>,
- local_crate_name: Symbol,
+ tcx: TyCtxt<'tcx>,
// Mutable output.
cstore: &'a mut CStore,
used_extern_options: &'a mut FxHashSet<Symbol>,
}
+impl<'a, 'tcx> std::ops::Deref for CrateLoader<'a, 'tcx> {
+ type Target = TyCtxt<'tcx>;
+
+ fn deref(&self) -> &Self::Target {
+ &self.tcx
+ }
+}
+
pub enum LoadedMacro {
MacroDef(ast::Item, Edition),
ProcMacro(SyntaxExtension),
@@ -131,11 +132,10 @@ impl<'a> std::fmt::Debug for CrateDump<'a> {
}
impl CStore {
- pub fn from_tcx(tcx: TyCtxt<'_>) -> &CStore {
- tcx.cstore_untracked()
- .as_any()
- .downcast_ref::<CStore>()
- .expect("`tcx.cstore` is not a `CStore`")
+ pub fn from_tcx(tcx: TyCtxt<'_>) -> MappedReadGuard<'_, CStore> {
+ MappedReadGuard::map(tcx.cstore_untracked(), |c| {
+ c.as_any().downcast_ref::<CStore>().expect("`tcx.cstore` is not a `CStore`")
+ })
}
fn alloc_new_crate_num(&mut self) -> CrateNum {
@@ -156,7 +156,7 @@ impl CStore {
fn set_crate_data(&mut self, cnum: CrateNum, data: CrateMetadata) {
assert!(self.metas[cnum].is_none(), "Overwriting crate metadata entry");
- self.metas[cnum] = Some(Lrc::new(data));
+ self.metas[cnum] = Some(Box::new(data));
}
pub(crate) fn iter_crate_data(&self) -> impl Iterator<Item = (CrateNum, &CrateMetadata)> {
@@ -248,7 +248,7 @@ impl CStore {
// order to make array indices in `metas` match with the
// corresponding `CrateNum`. This first entry will always remain
// `None`.
- metas: IndexVec::from_elem_n(None, 1),
+ metas: IndexVec::from_iter(iter::once(None)),
injected_panic_runtime: None,
allocator_kind: None,
alloc_error_handler_kind: None,
@@ -260,23 +260,13 @@ impl CStore {
}
}
-impl<'a> CrateLoader<'a> {
+impl<'a, 'tcx> CrateLoader<'a, 'tcx> {
pub fn new(
- sess: &'a Session,
- metadata_loader: &'a MetadataLoaderDyn,
- local_crate_name: Symbol,
+ tcx: TyCtxt<'tcx>,
cstore: &'a mut CStore,
- definitions: ReadGuard<'a, Definitions>,
used_extern_options: &'a mut FxHashSet<Symbol>,
) -> Self {
- CrateLoader {
- sess,
- metadata_loader,
- local_crate_name,
- cstore,
- used_extern_options,
- definitions,
- }
+ CrateLoader { tcx, cstore, used_extern_options }
}
pub fn cstore(&self) -> &CStore {
&self.cstore
@@ -359,7 +349,12 @@ impl<'a> CrateLoader<'a> {
for (_, other) in self.cstore.iter_crate_data() {
// Same stable crate id but different SVH
if other.stable_crate_id() == root.stable_crate_id() && other.hash() != root.hash() {
- return Err(CrateError::SymbolConflictsOthers(root.name()));
+ bug!(
+ "Previously returned E0523 here. \
+ See https://github.com/rust-lang/rust/pull/100599 for additional discussion.\
+ root.name() = {}.",
+ root.name()
+ );
}
}
@@ -562,9 +557,10 @@ impl<'a> CrateLoader<'a> {
(LoadResult::Previous(cnum), None)
} else {
info!("falling back to a load");
+ let metadata_loader = self.tcx.metadata_loader(()).borrow();
let mut locator = CrateLocator::new(
self.sess,
- &*self.metadata_loader,
+ &**metadata_loader,
name,
hash,
extra_filename,
@@ -689,8 +685,7 @@ impl<'a> CrateLoader<'a> {
) -> Result<&'static [ProcMacro], CrateError> {
// Make sure the path contains a / or the linker will search for it.
let path = env::current_dir().unwrap().join(path);
- let lib = unsafe { libloading::Library::new(path) }
- .map_err(|err| CrateError::DlOpen(err.to_string()))?;
+ let lib = load_dylib(&path, 5).map_err(|err| CrateError::DlOpen(err))?;
let sym_name = self.sess.generate_proc_macro_decls_symbol(stable_crate_id);
let sym = unsafe { lib.get::<*const &[ProcMacro]>(sym_name.as_bytes()) }
@@ -768,10 +763,11 @@ impl<'a> CrateLoader<'a> {
// Sanity check the loaded crate to ensure it is indeed a panic runtime
// and the panic strategy is indeed what we thought it was.
if !data.is_panic_runtime() {
- self.sess.emit_err(CrateNotPanicRuntime { crate_name: name });
+ self.sess.emit_err(errors::CrateNotPanicRuntime { crate_name: name });
}
if data.required_panic_strategy() != Some(desired_strategy) {
- self.sess.emit_err(NoPanicStrategy { crate_name: name, strategy: desired_strategy });
+ self.sess
+ .emit_err(errors::NoPanicStrategy { crate_name: name, strategy: desired_strategy });
}
self.cstore.injected_panic_runtime = Some(cnum);
@@ -791,7 +787,7 @@ impl<'a> CrateLoader<'a> {
let name = Symbol::intern(&self.sess.opts.unstable_opts.profiler_runtime);
if name == sym::profiler_builtins && self.sess.contains_name(&krate.attrs, sym::no_core) {
- self.sess.emit_err(ProfilerBuiltinsNeedsCore);
+ self.sess.emit_err(errors::ProfilerBuiltinsNeedsCore);
}
let Some(cnum) = self.resolve_crate(name, DUMMY_SP, CrateDepKind::Implicit) else { return; };
@@ -799,21 +795,22 @@ impl<'a> CrateLoader<'a> {
// Sanity check the loaded crate to ensure it is indeed a profiler runtime
if !data.is_profiler_runtime() {
- self.sess.emit_err(NotProfilerRuntime { crate_name: name });
+ self.sess.emit_err(errors::NotProfilerRuntime { crate_name: name });
}
}
fn inject_allocator_crate(&mut self, krate: &ast::Crate) {
self.cstore.has_global_allocator = match &*global_allocator_spans(&self.sess, krate) {
[span1, span2, ..] => {
- self.sess.emit_err(NoMultipleGlobalAlloc { span2: *span2, span1: *span1 });
+ self.sess.emit_err(errors::NoMultipleGlobalAlloc { span2: *span2, span1: *span1 });
true
}
spans => !spans.is_empty(),
};
self.cstore.has_alloc_error_handler = match &*alloc_error_handler_spans(&self.sess, krate) {
[span1, span2, ..] => {
- self.sess.emit_err(NoMultipleAllocErrorHandler { span2: *span2, span1: *span1 });
+ self.sess
+ .emit_err(errors::NoMultipleAllocErrorHandler { span2: *span2, span1: *span1 });
true
}
spans => !spans.is_empty(),
@@ -849,7 +846,7 @@ impl<'a> CrateLoader<'a> {
if data.has_global_allocator() {
match global_allocator {
Some(other_crate) => {
- self.sess.emit_err(ConflictingGlobalAlloc {
+ self.sess.emit_err(errors::ConflictingGlobalAlloc {
crate_name: data.name(),
other_crate_name: other_crate,
});
@@ -864,7 +861,7 @@ impl<'a> CrateLoader<'a> {
if data.has_alloc_error_handler() {
match alloc_error_handler {
Some(other_crate) => {
- self.sess.emit_err(ConflictingAllocErrorHandler {
+ self.sess.emit_err(errors::ConflictingAllocErrorHandler {
crate_name: data.name(),
other_crate_name: other_crate,
});
@@ -884,7 +881,7 @@ impl<'a> CrateLoader<'a> {
if !self.sess.contains_name(&krate.attrs, sym::default_lib_allocator)
&& !self.cstore.iter_crate_data().any(|(_, data)| data.has_default_lib_allocator())
{
- self.sess.emit_err(GlobalAllocRequired);
+ self.sess.emit_err(errors::GlobalAllocRequired);
}
self.cstore.allocator_kind = Some(AllocatorKind::Default);
}
@@ -917,7 +914,7 @@ impl<'a> CrateLoader<'a> {
for dep in self.cstore.crate_dependencies_in_reverse_postorder(krate) {
let data = self.cstore.get_crate_data(dep);
if needs_dep(&data) {
- self.sess.emit_err(NoTransitiveNeedsDep {
+ self.sess.emit_err(errors::NoTransitiveNeedsDep {
crate_name: self.cstore.get_crate_data(krate).name(),
needs_crate_name: what,
deps_crate_name: data.name(),
@@ -968,7 +965,7 @@ impl<'a> CrateLoader<'a> {
&format!(
"external crate `{}` unused in `{}`: remove the dependency or add `use {} as _;`",
name,
- self.local_crate_name,
+ self.tcx.crate_name(LOCAL_CRATE),
name),
);
}
@@ -988,6 +985,7 @@ impl<'a> CrateLoader<'a> {
&mut self,
item: &ast::Item,
def_id: LocalDefId,
+ definitions: &Definitions,
) -> Option<CrateNum> {
match item.kind {
ast::ItemKind::ExternCrate(orig_name) => {
@@ -1010,7 +1008,7 @@ impl<'a> CrateLoader<'a> {
let cnum = self.resolve_crate(name, item.span, dep_kind)?;
- let path_len = self.definitions.def_path(def_id).data.len();
+ let path_len = definitions.def_path(def_id).data.len();
self.update_extern_crate(
cnum,
ExternCrate {
@@ -1093,3 +1091,41 @@ fn alloc_error_handler_spans(sess: &Session, krate: &ast::Crate) -> Vec<Span> {
visit::walk_crate(&mut f, krate);
f.spans
}
+
+// On Windows the compiler would sometimes intermittently fail to open the
+// proc-macro DLL with `Error::LoadLibraryExW`. It is suspected that something in the
+// system still holds a lock on the file, so we retry a few times before calling it
+// an error.
+fn load_dylib(path: &Path, max_attempts: usize) -> Result<libloading::Library, String> {
+ assert!(max_attempts > 0);
+
+ let mut last_error = None;
+
+ for attempt in 0..max_attempts {
+ match unsafe { libloading::Library::new(&path) } {
+ Ok(lib) => {
+ if attempt > 0 {
+ debug!(
+ "Loaded proc-macro `{}` after {} attempts.",
+ path.display(),
+ attempt + 1
+ );
+ }
+ return Ok(lib);
+ }
+ Err(err) => {
+ // Only try to recover from this specific error.
+ if !matches!(err, libloading::Error::LoadLibraryExW { .. }) {
+ return Err(err.to_string());
+ }
+
+ last_error = Some(err);
+ std::thread::sleep(Duration::from_millis(100));
+ debug!("Failed to load proc-macro `{}`. Retrying.", path.display());
+ }
+ }
+ }
+
+ debug!("Failed to load proc-macro `{}` even after {} attempts.", path.display(), max_attempts);
+ Err(format!("{} (retried {} times)", last_error.unwrap(), max_attempts))
+}
diff --git a/compiler/rustc_metadata/src/dependency_format.rs b/compiler/rustc_metadata/src/dependency_format.rs
index cee4ba56a..39ef4276f 100644
--- a/compiler/rustc_metadata/src/dependency_format.rs
+++ b/compiler/rustc_metadata/src/dependency_format.rs
@@ -113,37 +113,37 @@ fn calculate_type(tcx: TyCtxt<'_>, ty: CrateType) -> DependencyList {
CrateType::Staticlib => Linkage::Static,
};
- if preferred_linkage == Linkage::NotLinked {
+ match preferred_linkage {
// If the crate is not linked, there are no link-time dependencies.
- return Vec::new();
- }
-
- if preferred_linkage == Linkage::Static {
- // Attempt static linkage first. For dylibs and executables, we may be
- // able to retry below with dynamic linkage.
- if let Some(v) = attempt_static(tcx) {
- return v;
- }
+ Linkage::NotLinked => return Vec::new(),
+ Linkage::Static => {
+ // Attempt static linkage first. For dylibs and executables, we may be
+ // able to retry below with dynamic linkage.
+ if let Some(v) = attempt_static(tcx) {
+ return v;
+ }
- // Staticlibs and static executables must have all static dependencies.
- // If any are not found, generate some nice pretty errors.
- if ty == CrateType::Staticlib
- || (ty == CrateType::Executable
- && sess.crt_static(Some(ty))
- && !sess.target.crt_static_allows_dylibs)
- {
- for &cnum in tcx.crates(()).iter() {
- if tcx.dep_kind(cnum).macros_only() {
- continue;
+ // Staticlibs and static executables must have all static dependencies.
+ // If any are not found, generate some nice pretty errors.
+ if ty == CrateType::Staticlib
+ || (ty == CrateType::Executable
+ && sess.crt_static(Some(ty))
+ && !sess.target.crt_static_allows_dylibs)
+ {
+ for &cnum in tcx.crates(()).iter() {
+ if tcx.dep_kind(cnum).macros_only() {
+ continue;
+ }
+ let src = tcx.used_crate_source(cnum);
+ if src.rlib.is_some() {
+ continue;
+ }
+ sess.emit_err(RlibRequired { crate_name: tcx.crate_name(cnum) });
}
- let src = tcx.used_crate_source(cnum);
- if src.rlib.is_some() {
- continue;
- }
- sess.emit_err(RlibRequired { crate_name: tcx.crate_name(cnum) });
+ return Vec::new();
}
- return Vec::new();
}
+ Linkage::Dynamic | Linkage::IncludedFromDylib => {}
}
let mut formats = FxHashMap::default();
@@ -283,12 +283,9 @@ fn attempt_static(tcx: TyCtxt<'_>) -> Option<DependencyList> {
let mut ret = tcx
.crates(())
.iter()
- .map(|&cnum| {
- if tcx.dep_kind(cnum) == CrateDepKind::Explicit {
- Linkage::Static
- } else {
- Linkage::NotLinked
- }
+ .map(|&cnum| match tcx.dep_kind(cnum) {
+ CrateDepKind::Explicit => Linkage::Static,
+ CrateDepKind::MacrosOnly | CrateDepKind::Implicit => Linkage::NotLinked,
})
.collect::<Vec<_>>();
diff --git a/compiler/rustc_metadata/src/errors.rs b/compiler/rustc_metadata/src/errors.rs
index 02c03114e..51b41b5f6 100644
--- a/compiler/rustc_metadata/src/errors.rs
+++ b/compiler/rustc_metadata/src/errors.rs
@@ -9,6 +9,7 @@ use rustc_session::config;
use rustc_span::{sym, Span, Symbol};
use rustc_target::spec::{PanicStrategy, TargetTriple};
+use crate::fluent_generated as fluent;
use crate::locator::CrateFlavor;
#[derive(Diagnostic)]
@@ -491,7 +492,7 @@ impl IntoDiagnostic<'_> for MultipleCandidates {
self,
handler: &'_ rustc_errors::Handler,
) -> rustc_errors::DiagnosticBuilder<'_, ErrorGuaranteed> {
- let mut diag = handler.struct_err(rustc_errors::fluent::metadata_multiple_candidates);
+ let mut diag = handler.struct_err(fluent::metadata_multiple_candidates);
diag.set_arg("crate_name", self.crate_name);
diag.set_arg("flavor", self.flavor);
diag.code(error_code!(E0464));
@@ -512,14 +513,6 @@ pub struct SymbolConflictsCurrent {
}
#[derive(Diagnostic)]
-#[diag(metadata_symbol_conflicts_others, code = "E0523")]
-pub struct SymbolConflictsOthers {
- #[primary_span]
- pub span: Span,
- pub crate_name: Symbol,
-}
-
-#[derive(Diagnostic)]
#[diag(metadata_stable_crate_id_collision)]
pub struct StableCrateIdCollision {
#[primary_span]
@@ -598,7 +591,7 @@ impl IntoDiagnostic<'_> for InvalidMetadataFiles {
self,
handler: &'_ rustc_errors::Handler,
) -> rustc_errors::DiagnosticBuilder<'_, ErrorGuaranteed> {
- let mut diag = handler.struct_err(rustc_errors::fluent::metadata_invalid_meta_files);
+ let mut diag = handler.struct_err(fluent::metadata_invalid_meta_files);
diag.set_arg("crate_name", self.crate_name);
diag.set_arg("add_info", self.add_info);
diag.code(error_code!(E0786));
@@ -627,7 +620,7 @@ impl IntoDiagnostic<'_> for CannotFindCrate {
self,
handler: &'_ rustc_errors::Handler,
) -> rustc_errors::DiagnosticBuilder<'_, ErrorGuaranteed> {
- let mut diag = handler.struct_err(rustc_errors::fluent::metadata_cannot_find_crate);
+ let mut diag = handler.struct_err(fluent::metadata_cannot_find_crate);
diag.set_arg("crate_name", self.crate_name);
diag.set_arg("current_crate", self.current_crate);
diag.set_arg("add_info", self.add_info);
@@ -638,32 +631,32 @@ impl IntoDiagnostic<'_> for CannotFindCrate {
&& self.locator_triple != TargetTriple::from_triple(config::host_triple())
{
if self.missing_core {
- diag.note(rustc_errors::fluent::metadata_target_not_installed);
+ diag.note(fluent::metadata_target_not_installed);
} else {
- diag.note(rustc_errors::fluent::metadata_target_no_std_support);
+ diag.note(fluent::metadata_target_no_std_support);
}
// NOTE: this suggests using rustup, even though the user may not have it installed.
// That's because they could choose to install it; or this may give them a hint which
// target they need to install from their distro.
if self.missing_core {
- diag.help(rustc_errors::fluent::metadata_consider_downloading_target);
+ diag.help(fluent::metadata_consider_downloading_target);
}
// Suggest using #![no_std]. #[no_core] is unstable and not really supported anyway.
// NOTE: this is a dummy span if `extern crate std` was injected by the compiler.
// If it's not a dummy, that means someone added `extern crate std` explicitly and
// `#![no_std]` won't help.
if !self.missing_core && self.span.is_dummy() {
- diag.note(rustc_errors::fluent::metadata_std_required);
+ diag.note(fluent::metadata_std_required);
}
if self.is_nightly_build {
- diag.help(rustc_errors::fluent::metadata_consider_building_std);
+ diag.help(fluent::metadata_consider_building_std);
}
} else if self.crate_name == self.profiler_runtime {
- diag.note(rustc_errors::fluent::metadata_compiler_missing_profiler);
+ diag.note(fluent::metadata_compiler_missing_profiler);
} else if self.crate_name.as_str().starts_with("rustc_") {
- diag.help(rustc_errors::fluent::metadata_install_missing_components);
+ diag.help(fluent::metadata_install_missing_components);
}
- diag.span_label(self.span, rustc_errors::fluent::metadata_cant_find_crate);
+ diag.span_label(self.span, fluent::metadata_cant_find_crate);
diag
}
}
diff --git a/compiler/rustc_metadata/src/lib.rs b/compiler/rustc_metadata/src/lib.rs
index 1987f88e6..6f6d3731c 100644
--- a/compiler/rustc_metadata/src/lib.rs
+++ b/compiler/rustc_metadata/src/lib.rs
@@ -30,6 +30,8 @@ extern crate rustc_data_structures;
extern crate tracing;
pub use rmeta::{provide, provide_extern};
+use rustc_errors::{DiagnosticMessage, SubdiagnosticMessage};
+use rustc_macros::fluent_messages;
mod dependency_format;
mod foreign_modules;
@@ -44,3 +46,5 @@ pub mod locator;
pub use fs::{emit_wrapper_file, METADATA_FILENAME};
pub use native_libs::find_native_static_library;
pub use rmeta::{encode_metadata, EncodedMetadata, METADATA_HEADER};
+
+fluent_messages! { "../locales/en-US.ftl" }
diff --git a/compiler/rustc_metadata/src/locator.rs b/compiler/rustc_metadata/src/locator.rs
index 0f5f74007..755a24253 100644
--- a/compiler/rustc_metadata/src/locator.rs
+++ b/compiler/rustc_metadata/src/locator.rs
@@ -213,12 +213,7 @@
//! metadata::locator or metadata::creader for all the juicy details!
use crate::creader::Library;
-use crate::errors::{
- CannotFindCrate, CrateLocationUnknownType, DlError, ExternLocationNotExist,
- ExternLocationNotFile, FoundStaticlib, IncompatibleRustc, InvalidMetadataFiles,
- LibFilenameForm, MultipleCandidates, NewerCrateVersion, NoCrateWithTriple, NoDylibPlugin,
- NonAsciiName, StableCrateIdCollision, SymbolConflictsCurrent, SymbolConflictsOthers,
-};
+use crate::errors;
use crate::rmeta::{rustc_version, MetadataBlob, METADATA_HEADER};
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
@@ -950,7 +945,6 @@ pub(crate) enum CrateError {
ExternLocationNotFile(Symbol, PathBuf),
MultipleCandidates(Symbol, CrateFlavor, Vec<PathBuf>),
SymbolConflictsCurrent(Symbol),
- SymbolConflictsOthers(Symbol),
StableCrateIdCollision(Symbol, Symbol),
DlOpen(String),
DlSym(String),
@@ -980,28 +974,25 @@ impl CrateError {
pub(crate) fn report(self, sess: &Session, span: Span, missing_core: bool) {
match self {
CrateError::NonAsciiName(crate_name) => {
- sess.emit_err(NonAsciiName { span, crate_name });
+ sess.emit_err(errors::NonAsciiName { span, crate_name });
}
CrateError::ExternLocationNotExist(crate_name, loc) => {
- sess.emit_err(ExternLocationNotExist { span, crate_name, location: &loc });
+ sess.emit_err(errors::ExternLocationNotExist { span, crate_name, location: &loc });
}
CrateError::ExternLocationNotFile(crate_name, loc) => {
- sess.emit_err(ExternLocationNotFile { span, crate_name, location: &loc });
+ sess.emit_err(errors::ExternLocationNotFile { span, crate_name, location: &loc });
}
CrateError::MultipleCandidates(crate_name, flavor, candidates) => {
- sess.emit_err(MultipleCandidates { span, crate_name, flavor, candidates });
+ sess.emit_err(errors::MultipleCandidates { span, crate_name, flavor, candidates });
}
CrateError::SymbolConflictsCurrent(root_name) => {
- sess.emit_err(SymbolConflictsCurrent { span, crate_name: root_name });
- }
- CrateError::SymbolConflictsOthers(root_name) => {
- sess.emit_err(SymbolConflictsOthers { span, crate_name: root_name });
+ sess.emit_err(errors::SymbolConflictsCurrent { span, crate_name: root_name });
}
CrateError::StableCrateIdCollision(crate_name0, crate_name1) => {
- sess.emit_err(StableCrateIdCollision { span, crate_name0, crate_name1 });
+ sess.emit_err(errors::StableCrateIdCollision { span, crate_name0, crate_name1 });
}
CrateError::DlOpen(s) | CrateError::DlSym(s) => {
- sess.emit_err(DlError { span, err: s });
+ sess.emit_err(errors::DlError { span, err: s });
}
CrateError::LocatorCombined(locator) => {
let crate_name = locator.crate_name;
@@ -1012,8 +1003,12 @@ impl CrateError {
if !locator.crate_rejections.via_filename.is_empty() {
let mismatches = locator.crate_rejections.via_filename.iter();
for CrateMismatch { path, .. } in mismatches {
- sess.emit_err(CrateLocationUnknownType { span, path: &path, crate_name });
- sess.emit_err(LibFilenameForm {
+ sess.emit_err(errors::CrateLocationUnknownType {
+ span,
+ path: &path,
+ crate_name,
+ });
+ sess.emit_err(errors::LibFilenameForm {
span,
dll_prefix: &locator.dll_prefix,
dll_suffix: &locator.dll_suffix,
@@ -1039,7 +1034,7 @@ impl CrateError {
));
}
}
- sess.emit_err(NewerCrateVersion {
+ sess.emit_err(errors::NewerCrateVersion {
span,
crate_name: crate_name,
add_info,
@@ -1055,7 +1050,7 @@ impl CrateError {
path.display(),
));
}
- sess.emit_err(NoCrateWithTriple {
+ sess.emit_err(errors::NoCrateWithTriple {
span,
crate_name,
locator_triple: locator.triple.triple(),
@@ -1071,7 +1066,12 @@ impl CrateError {
path.display()
));
}
- sess.emit_err(FoundStaticlib { span, crate_name, add_info, found_crates });
+ sess.emit_err(errors::FoundStaticlib {
+ span,
+ crate_name,
+ add_info,
+ found_crates,
+ });
} else if !locator.crate_rejections.via_version.is_empty() {
let mismatches = locator.crate_rejections.via_version.iter();
for CrateMismatch { path, got } in mismatches {
@@ -1082,7 +1082,7 @@ impl CrateError {
path.display(),
));
}
- sess.emit_err(IncompatibleRustc {
+ sess.emit_err(errors::IncompatibleRustc {
span,
crate_name,
add_info,
@@ -1094,14 +1094,14 @@ impl CrateError {
for CrateMismatch { path: _, got } in locator.crate_rejections.via_invalid {
crate_rejections.push(got);
}
- sess.emit_err(InvalidMetadataFiles {
+ sess.emit_err(errors::InvalidMetadataFiles {
span,
crate_name,
add_info,
crate_rejections,
});
} else {
- sess.emit_err(CannotFindCrate {
+ sess.emit_err(errors::CannotFindCrate {
span,
crate_name,
add_info,
@@ -1118,7 +1118,7 @@ impl CrateError {
}
}
CrateError::NonDylibPlugin(crate_name) => {
- sess.emit_err(NoDylibPlugin { span, crate_name });
+ sess.emit_err(errors::NoDylibPlugin { span, crate_name });
}
}
}
diff --git a/compiler/rustc_metadata/src/native_libs.rs b/compiler/rustc_metadata/src/native_libs.rs
index 6f05c76e8..d6f68b2e1 100644
--- a/compiler/rustc_metadata/src/native_libs.rs
+++ b/compiler/rustc_metadata/src/native_libs.rs
@@ -13,17 +13,7 @@ use rustc_session::Session;
use rustc_span::symbol::{sym, Symbol};
use rustc_target::spec::abi::Abi;
-use crate::errors::{
- AsNeededCompatibility, BundleNeedsStatic, EmptyLinkName, EmptyRenamingTarget,
- FrameworkOnlyWindows, ImportNameTypeForm, ImportNameTypeRaw, ImportNameTypeX86,
- IncompatibleWasmLink, InvalidLinkModifier, LibFrameworkApple, LinkCfgForm,
- LinkCfgSinglePredicate, LinkFrameworkApple, LinkKindForm, LinkModifiersForm, LinkNameForm,
- LinkOrdinalRawDylib, LinkRequiresName, MissingNativeLibrary, MultipleCfgs,
- MultipleImportNameType, MultipleKindsInLink, MultipleLinkModifiers, MultipleModifiers,
- MultipleNamesInLink, MultipleRenamings, MultipleWasmImport, NoLinkModOverride, RawDylibNoNul,
- RenamingNoLink, UnexpectedLinkArg, UnknownImportNameType, UnknownLinkKind, UnknownLinkModifier,
- UnsupportedAbi, UnsupportedAbiI686, WasmImportForm, WholeArchiveNeedsStatic,
-};
+use crate::errors;
use std::path::PathBuf;
@@ -52,27 +42,28 @@ pub fn find_native_static_library(
}
}
- sess.emit_fatal(MissingNativeLibrary::new(name, verbatim));
+ sess.emit_fatal(errors::MissingNativeLibrary::new(name, verbatim));
}
fn find_bundled_library(
name: Option<Symbol>,
verbatim: Option<bool>,
kind: NativeLibKind,
+ has_cfg: bool,
sess: &Session,
) -> Option<Symbol> {
- if sess.opts.unstable_opts.packed_bundled_libs &&
- sess.crate_types().iter().any(|ct| ct == &CrateType::Rlib || ct == &CrateType::Staticlib) &&
- let NativeLibKind::Static { bundle: Some(true) | None, .. } = kind {
- find_native_static_library(
- name.unwrap().as_str(),
- verbatim.unwrap_or(false),
- &sess.target_filesearch(PathKind::Native).search_path_dirs(),
- sess,
- ).file_name().and_then(|s| s.to_str()).map(Symbol::intern)
- } else {
- None
+ if let NativeLibKind::Static { bundle: Some(true) | None, whole_archive } = kind
+ && sess.crate_types().iter().any(|t| matches!(t, &CrateType::Rlib | CrateType::Staticlib))
+ && (sess.opts.unstable_opts.packed_bundled_libs || has_cfg || whole_archive == Some(true))
+ {
+ let verbatim = verbatim.unwrap_or(false);
+ let search_paths = &sess.target_filesearch(PathKind::Native).search_path_dirs();
+ return find_native_static_library(name.unwrap().as_str(), verbatim, search_paths, sess)
+ .file_name()
+ .and_then(|s| s.to_str())
+ .map(Symbol::intern);
}
+ None
}
pub(crate) fn collect(tcx: TyCtxt<'_>) -> Vec<NativeLib> {
@@ -107,13 +98,18 @@ impl<'tcx> Collector<'tcx> {
return;
};
- if abi == Abi::Rust || abi == Abi::RustIntrinsic || abi == Abi::PlatformIntrinsic {
+ if matches!(abi, Abi::Rust | Abi::RustIntrinsic | Abi::PlatformIntrinsic) {
return;
}
// Process all of the #[link(..)]-style arguments
- let sess = &self.tcx.sess;
+ let sess = self.tcx.sess;
let features = self.tcx.features();
+
+ if !sess.opts.unstable_opts.link_directives {
+ return;
+ }
+
for m in self.tcx.hir().attrs(it.hir_id()).iter().filter(|a| a.has_name(sym::link)) {
let Some(items) = m.meta_item_list() else {
continue;
@@ -129,26 +125,26 @@ impl<'tcx> Collector<'tcx> {
match item.name_or_empty() {
sym::name => {
if name.is_some() {
- sess.emit_err(MultipleNamesInLink { span: item.span() });
+ sess.emit_err(errors::MultipleNamesInLink { span: item.span() });
continue;
}
let Some(link_name) = item.value_str() else {
- sess.emit_err(LinkNameForm { span: item.span() });
+ sess.emit_err(errors::LinkNameForm { span: item.span() });
continue;
};
let span = item.name_value_literal_span().unwrap();
if link_name.is_empty() {
- sess.emit_err(EmptyLinkName { span });
+ sess.emit_err(errors::EmptyLinkName { span });
}
name = Some((link_name, span));
}
sym::kind => {
if kind.is_some() {
- sess.emit_err(MultipleKindsInLink { span: item.span() });
+ sess.emit_err(errors::MultipleKindsInLink { span: item.span() });
continue;
}
let Some(link_kind) = item.value_str() else {
- sess.emit_err(LinkKindForm { span: item.span() });
+ sess.emit_err(errors::LinkKindForm { span: item.span() });
continue;
};
@@ -158,13 +154,13 @@ impl<'tcx> Collector<'tcx> {
"dylib" => NativeLibKind::Dylib { as_needed: None },
"framework" => {
if !sess.target.is_like_osx {
- sess.emit_err(LinkFrameworkApple { span });
+ sess.emit_err(errors::LinkFrameworkApple { span });
}
NativeLibKind::Framework { as_needed: None }
}
"raw-dylib" => {
if !sess.target.is_like_windows {
- sess.emit_err(FrameworkOnlyWindows { span });
+ sess.emit_err(errors::FrameworkOnlyWindows { span });
} else if !features.raw_dylib && sess.target.arch == "x86" {
feature_err(
&sess.parse_sess,
@@ -177,7 +173,7 @@ impl<'tcx> Collector<'tcx> {
NativeLibKind::RawDylib
}
kind => {
- sess.emit_err(UnknownLinkKind { span, kind });
+ sess.emit_err(errors::UnknownLinkKind { span, kind });
continue;
}
};
@@ -185,26 +181,26 @@ impl<'tcx> Collector<'tcx> {
}
sym::modifiers => {
if modifiers.is_some() {
- sess.emit_err(MultipleLinkModifiers { span: item.span() });
+ sess.emit_err(errors::MultipleLinkModifiers { span: item.span() });
continue;
}
let Some(link_modifiers) = item.value_str() else {
- sess.emit_err(LinkModifiersForm { span: item.span() });
+ sess.emit_err(errors::LinkModifiersForm { span: item.span() });
continue;
};
modifiers = Some((link_modifiers, item.name_value_literal_span().unwrap()));
}
sym::cfg => {
if cfg.is_some() {
- sess.emit_err(MultipleCfgs { span: item.span() });
+ sess.emit_err(errors::MultipleCfgs { span: item.span() });
continue;
}
let Some(link_cfg) = item.meta_item_list() else {
- sess.emit_err(LinkCfgForm { span: item.span() });
+ sess.emit_err(errors::LinkCfgForm { span: item.span() });
continue;
};
let [NestedMetaItem::MetaItem(link_cfg)] = link_cfg else {
- sess.emit_err(LinkCfgSinglePredicate { span: item.span() });
+ sess.emit_err(errors::LinkCfgSinglePredicate { span: item.span() });
continue;
};
if !features.link_cfg {
@@ -220,26 +216,26 @@ impl<'tcx> Collector<'tcx> {
}
sym::wasm_import_module => {
if wasm_import_module.is_some() {
- sess.emit_err(MultipleWasmImport { span: item.span() });
+ sess.emit_err(errors::MultipleWasmImport { span: item.span() });
continue;
}
let Some(link_wasm_import_module) = item.value_str() else {
- sess.emit_err(WasmImportForm { span: item.span() });
+ sess.emit_err(errors::WasmImportForm { span: item.span() });
continue;
};
wasm_import_module = Some((link_wasm_import_module, item.span()));
}
sym::import_name_type => {
if import_name_type.is_some() {
- sess.emit_err(MultipleImportNameType { span: item.span() });
+ sess.emit_err(errors::MultipleImportNameType { span: item.span() });
continue;
}
let Some(link_import_name_type) = item.value_str() else {
- sess.emit_err(ImportNameTypeForm { span: item.span() });
+ sess.emit_err(errors::ImportNameTypeForm { span: item.span() });
continue;
};
if self.tcx.sess.target.arch != "x86" {
- sess.emit_err(ImportNameTypeX86 { span: item.span() });
+ sess.emit_err(errors::ImportNameTypeX86 { span: item.span() });
continue;
}
@@ -248,7 +244,7 @@ impl<'tcx> Collector<'tcx> {
"noprefix" => PeImportNameType::NoPrefix,
"undecorated" => PeImportNameType::Undecorated,
import_name_type => {
- sess.emit_err(UnknownImportNameType {
+ sess.emit_err(errors::UnknownImportNameType {
span: item.span(),
import_name_type,
});
@@ -268,7 +264,7 @@ impl<'tcx> Collector<'tcx> {
import_name_type = Some((link_import_name_type, item.span()));
}
_ => {
- sess.emit_err(UnexpectedLinkArg { span: item.span() });
+ sess.emit_err(errors::UnexpectedLinkArg { span: item.span() });
}
}
}
@@ -280,7 +276,7 @@ impl<'tcx> Collector<'tcx> {
let (modifier, value) = match modifier.strip_prefix(&['+', '-']) {
Some(m) => (m, modifier.starts_with('+')),
None => {
- sess.emit_err(InvalidLinkModifier { span });
+ sess.emit_err(errors::InvalidLinkModifier { span });
continue;
}
};
@@ -298,7 +294,7 @@ impl<'tcx> Collector<'tcx> {
}
let assign_modifier = |dst: &mut Option<bool>| {
if dst.is_some() {
- sess.emit_err(MultipleModifiers { span, modifier });
+ sess.emit_err(errors::MultipleModifiers { span, modifier });
} else {
*dst = Some(value);
}
@@ -308,7 +304,7 @@ impl<'tcx> Collector<'tcx> {
assign_modifier(bundle)
}
("bundle", _) => {
- sess.emit_err(BundleNeedsStatic { span });
+ sess.emit_err(errors::BundleNeedsStatic { span });
}
("verbatim", _) => assign_modifier(&mut verbatim),
@@ -317,7 +313,7 @@ impl<'tcx> Collector<'tcx> {
assign_modifier(whole_archive)
}
("whole-archive", _) => {
- sess.emit_err(WholeArchiveNeedsStatic { span });
+ sess.emit_err(errors::WholeArchiveNeedsStatic { span });
}
("as-needed", Some(NativeLibKind::Dylib { as_needed }))
@@ -326,11 +322,11 @@ impl<'tcx> Collector<'tcx> {
assign_modifier(as_needed)
}
("as-needed", _) => {
- sess.emit_err(AsNeededCompatibility { span });
+ sess.emit_err(errors::AsNeededCompatibility { span });
}
_ => {
- sess.emit_err(UnknownLinkModifier { span, modifier });
+ sess.emit_err(errors::UnknownLinkModifier { span, modifier });
}
}
}
@@ -338,23 +334,23 @@ impl<'tcx> Collector<'tcx> {
if let Some((_, span)) = wasm_import_module {
if name.is_some() || kind.is_some() || modifiers.is_some() || cfg.is_some() {
- sess.emit_err(IncompatibleWasmLink { span });
+ sess.emit_err(errors::IncompatibleWasmLink { span });
}
} else if name.is_none() {
- sess.emit_err(LinkRequiresName { span: m.span });
+ sess.emit_err(errors::LinkRequiresName { span: m.span });
}
// Do this outside of the loop so that `import_name_type` can be specified before `kind`.
if let Some((_, span)) = import_name_type {
if kind != Some(NativeLibKind::RawDylib) {
- sess.emit_err(ImportNameTypeRaw { span });
+ sess.emit_err(errors::ImportNameTypeRaw { span });
}
}
let dll_imports = match kind {
Some(NativeLibKind::RawDylib) => {
if let Some((name, span)) = name && name.as_str().contains('\0') {
- sess.emit_err(RawDylibNoNul { span });
+ sess.emit_err(errors::RawDylibNoNul { span });
}
foreign_mod_items
.iter()
@@ -383,7 +379,9 @@ impl<'tcx> Collector<'tcx> {
.iter()
.find(|a| a.has_name(sym::link_ordinal))
.unwrap();
- sess.emit_err(LinkOrdinalRawDylib { span: link_ordinal_attr.span });
+ sess.emit_err(errors::LinkOrdinalRawDylib {
+ span: link_ordinal_attr.span,
+ });
}
}
@@ -393,7 +391,7 @@ impl<'tcx> Collector<'tcx> {
let name = name.map(|(name, _)| name);
let kind = kind.unwrap_or(NativeLibKind::Unspecified);
- let filename = find_bundled_library(name, verbatim, kind, sess);
+ let filename = find_bundled_library(name, verbatim, kind, cfg.is_some(), sess);
self.libs.push(NativeLib {
name,
filename,
@@ -414,7 +412,7 @@ impl<'tcx> Collector<'tcx> {
for lib in &self.tcx.sess.opts.libs {
if let NativeLibKind::Framework { .. } = lib.kind && !self.tcx.sess.target.is_like_osx {
// Cannot check this when parsing options because the target is not yet available.
- self.tcx.sess.emit_err(LibFrameworkApple);
+ self.tcx.sess.emit_err(errors::LibFrameworkApple);
}
if let Some(ref new_name) = lib.new_name {
let any_duplicate = self
@@ -423,11 +421,11 @@ impl<'tcx> Collector<'tcx> {
.filter_map(|lib| lib.name.as_ref())
.any(|n| n.as_str() == lib.name);
if new_name.is_empty() {
- self.tcx.sess.emit_err(EmptyRenamingTarget { lib_name: &lib.name });
+ self.tcx.sess.emit_err(errors::EmptyRenamingTarget { lib_name: &lib.name });
} else if !any_duplicate {
- self.tcx.sess.emit_err(RenamingNoLink { lib_name: &lib.name });
+ self.tcx.sess.emit_err(errors::RenamingNoLink { lib_name: &lib.name });
} else if !renames.insert(&lib.name) {
- self.tcx.sess.emit_err(MultipleRenamings { lib_name: &lib.name });
+ self.tcx.sess.emit_err(errors::MultipleRenamings { lib_name: &lib.name });
}
}
}
@@ -453,12 +451,15 @@ impl<'tcx> Collector<'tcx> {
// explicit `:rename` in particular.
if lib.has_modifiers() || passed_lib.has_modifiers() {
match lib.foreign_module {
- Some(def_id) => self.tcx.sess.emit_err(NoLinkModOverride {
- span: Some(self.tcx.def_span(def_id)),
- }),
- None => {
- self.tcx.sess.emit_err(NoLinkModOverride { span: None })
+ Some(def_id) => {
+ self.tcx.sess.emit_err(errors::NoLinkModOverride {
+ span: Some(self.tcx.def_span(def_id)),
+ })
}
+ None => self
+ .tcx
+ .sess
+ .emit_err(errors::NoLinkModOverride { span: None }),
};
}
if passed_lib.kind != NativeLibKind::Unspecified {
@@ -480,7 +481,7 @@ impl<'tcx> Collector<'tcx> {
let name = Some(Symbol::intern(new_name.unwrap_or(&passed_lib.name)));
let sess = self.tcx.sess;
let filename =
- find_bundled_library(name, passed_lib.verbatim, passed_lib.kind, sess);
+ find_bundled_library(name, passed_lib.verbatim, passed_lib.kind, false, sess);
self.libs.push(NativeLib {
name,
filename,
@@ -503,9 +504,10 @@ impl<'tcx> Collector<'tcx> {
let argument_types: &List<Ty<'_>> = self.tcx.erase_late_bound_regions(
self.tcx
.type_of(item.id.owner_id)
+ .subst_identity()
.fn_sig(self.tcx)
.inputs()
- .map_bound(|slice| self.tcx.mk_type_list(slice.iter())),
+ .map_bound(|slice| self.tcx.mk_type_list(slice)),
);
argument_types
@@ -542,14 +544,14 @@ impl<'tcx> Collector<'tcx> {
DllCallingConvention::Vectorcall(self.i686_arg_list_size(item))
}
_ => {
- self.tcx.sess.emit_fatal(UnsupportedAbiI686 { span: item.span });
+ self.tcx.sess.emit_fatal(errors::UnsupportedAbiI686 { span: item.span });
}
}
} else {
match abi {
Abi::C { .. } | Abi::Win64 { .. } | Abi::System { .. } => DllCallingConvention::C,
_ => {
- self.tcx.sess.emit_fatal(UnsupportedAbi { span: item.span });
+ self.tcx.sess.emit_fatal(errors::UnsupportedAbi { span: item.span });
}
}
};
diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs
index 143d8f2f1..b1e59b0a4 100644
--- a/compiler/rustc_metadata/src/rmeta/decoder.rs
+++ b/compiler/rustc_metadata/src/rmeta/decoder.rs
@@ -11,7 +11,7 @@ use rustc_data_structures::sync::{Lock, LockGuard, Lrc, OnceCell};
use rustc_data_structures::unhash::UnhashMap;
use rustc_expand::base::{SyntaxExtension, SyntaxExtensionKind};
use rustc_expand::proc_macro::{AttrProcMacro, BangProcMacro, DeriveProcMacro};
-use rustc_hir::def::{CtorKind, DefKind, Res};
+use rustc_hir::def::{CtorKind, DefKind, DocLinkResMap, 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;
@@ -654,7 +654,7 @@ impl<'a, 'tcx, T> Decodable<DecodeContext<'a, 'tcx>> for LazyValue<T> {
impl<'a, 'tcx, T> Decodable<DecodeContext<'a, 'tcx>> for LazyArray<T> {
fn decode(decoder: &mut DecodeContext<'a, 'tcx>) -> Self {
let len = decoder.read_usize();
- if len == 0 { LazyArray::empty() } else { decoder.read_lazy_array(len) }
+ if len == 0 { LazyArray::default() } else { decoder.read_lazy_array(len) }
}
}
@@ -864,7 +864,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
.tables
.children
.get(self, index)
- .unwrap_or_else(LazyArray::empty)
+ .expect("fields are not encoded for a variant")
.decode(self)
.map(|index| ty::FieldDef {
did: self.local_def_id(index),
@@ -896,7 +896,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
.tables
.children
.get(self, item_id)
- .unwrap_or_else(LazyArray::empty)
+ .expect("variants are not encoded for an enum")
.decode(self)
.filter_map(|index| {
let kind = self.def_kind(index);
@@ -910,7 +910,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
std::iter::once(self.get_variant(&kind, item_id, did)).collect()
};
- tcx.alloc_adt_def(did, adt_kind, variants, repr)
+ tcx.mk_adt_def(did, adt_kind, variants, repr)
}
fn get_generics(self, item_id: DefIndex, sess: &Session) -> ty::Generics {
@@ -985,7 +985,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
let vis = self.get_visibility(id);
let span = self.get_span(id, sess);
let macro_rules = match kind {
- DefKind::Macro(..) => self.root.tables.macro_rules.get(self, id).is_some(),
+ DefKind::Macro(..) => self.root.tables.is_macro_rules.get(self, id),
_ => false,
};
@@ -1045,7 +1045,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
.tables
.fn_arg_names
.get(self, id)
- .unwrap_or_else(LazyArray::empty)
+ .expect("argument names not encoded for a function")
.decode((self, sess))
.nth(0)
.map_or(false, |ident| ident.name == kw::SelfLower)
@@ -1060,7 +1060,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
.tables
.children
.get(self, id)
- .unwrap_or_else(LazyArray::empty)
+ .expect("associated items not encoded for an item")
.decode((self, sess))
.map(move |child_index| self.local_def_id(child_index))
}
@@ -1068,13 +1068,12 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
fn get_associated_item(self, id: DefIndex, sess: &'a Session) -> ty::AssocItem {
let name = self.item_name(id);
- let kind = match self.def_kind(id) {
- DefKind::AssocConst => ty::AssocKind::Const,
- DefKind::AssocFn => ty::AssocKind::Fn,
- DefKind::AssocTy => ty::AssocKind::Type,
+ let (kind, has_self) = match self.def_kind(id) {
+ DefKind::AssocConst => (ty::AssocKind::Const, false),
+ DefKind::AssocFn => (ty::AssocKind::Fn, self.get_fn_has_self_parameter(id, sess)),
+ DefKind::AssocTy => (ty::AssocKind::Type, false),
_ => bug!("cannot get associated-item of `{:?}`", self.def_key(id)),
};
- let has_self = self.get_fn_has_self_parameter(id, sess);
let container = self.root.tables.assoc_container.get(self, id).unwrap();
ty::AssocItem {
@@ -1131,7 +1130,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
.tables
.children
.get(self, id)
- .unwrap_or_else(LazyArray::empty)
+ .expect("fields not encoded for a struct")
.decode(self)
.map(move |index| respan(self.get_span(index, sess), self.item_name(index)))
}
@@ -1144,7 +1143,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
.tables
.children
.get(self, id)
- .unwrap_or_else(LazyArray::empty)
+ .expect("fields not encoded for a struct")
.decode(self)
.map(move |field_index| self.get_visibility(field_index))
}
@@ -1159,52 +1158,23 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
.tables
.inherent_impls
.get(self, id)
- .unwrap_or_else(LazyArray::empty)
.decode(self)
.map(|index| self.local_def_id(index)),
)
}
- /// Decodes all inherent impls in the crate (for rustdoc).
- fn get_inherent_impls(self) -> impl Iterator<Item = (DefId, DefId)> + 'a {
- (0..self.root.tables.inherent_impls.size()).flat_map(move |i| {
- let ty_index = DefIndex::from_usize(i);
- let ty_def_id = self.local_def_id(ty_index);
- self.root
- .tables
- .inherent_impls
- .get(self, ty_index)
- .unwrap_or_else(LazyArray::empty)
- .decode(self)
- .map(move |impl_index| (ty_def_id, self.local_def_id(impl_index)))
- })
- }
-
/// Decodes all traits in the crate (for rustdoc and rustc diagnostics).
fn get_traits(self) -> impl Iterator<Item = DefId> + 'a {
self.root.traits.decode(self).map(move |index| self.local_def_id(index))
}
/// Decodes all trait impls in the crate (for rustdoc).
- fn get_trait_impls(self) -> impl Iterator<Item = (DefId, DefId, Option<SimplifiedType>)> + 'a {
- self.cdata.trait_impls.iter().flat_map(move |(&(trait_cnum_raw, trait_index), impls)| {
- let trait_def_id = DefId {
- krate: self.cnum_map[CrateNum::from_u32(trait_cnum_raw)],
- index: trait_index,
- };
- impls.decode(self).map(move |(impl_index, simplified_self_ty)| {
- (trait_def_id, self.local_def_id(impl_index), simplified_self_ty)
- })
+ fn get_trait_impls(self) -> impl Iterator<Item = DefId> + 'a {
+ self.cdata.trait_impls.values().flat_map(move |impls| {
+ impls.decode(self).map(move |(impl_index, _)| self.local_def_id(impl_index))
})
}
- fn get_all_incoherent_impls(self) -> impl Iterator<Item = DefId> + 'a {
- self.cdata
- .incoherent_impls
- .values()
- .flat_map(move |impls| impls.decode(self).map(move |idx| self.local_def_id(idx)))
- }
-
fn get_incoherent_impls(self, tcx: TyCtxt<'tcx>, simp: SimplifiedType) -> &'tcx [DefId] {
if let Some(impls) = self.cdata.incoherent_impls.get(&simp) {
tcx.arena.alloc_from_iter(impls.decode(self).map(|idx| self.local_def_id(idx)))
@@ -1283,7 +1253,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
fn get_macro(self, id: DefIndex, sess: &Session) -> ast::MacroDef {
match self.def_kind(id) {
DefKind::Macro(_) => {
- let macro_rules = self.root.tables.macro_rules.get(self, id).is_some();
+ let macro_rules = self.root.tables.is_macro_rules.get(self, id);
let body =
self.root.tables.macro_definition.get(self, id).unwrap().decode((self, sess));
ast::MacroDef { macro_rules, body: ast::ptr::P(body) }
@@ -1322,7 +1292,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
) -> DefPathHash {
*def_path_hashes
.entry(index)
- .or_insert_with(|| self.root.tables.def_path_hashes.get(self, index).unwrap())
+ .or_insert_with(|| self.root.tables.def_path_hashes.get(self, index))
}
#[inline]
@@ -1594,12 +1564,30 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
})
}
- fn get_may_have_doc_links(self, index: DefIndex) -> bool {
- self.root.tables.may_have_doc_links.get(self, index).is_some()
+ fn get_attr_flags(self, index: DefIndex) -> AttrFlags {
+ self.root.tables.attr_flags.get(self, index)
}
fn get_is_intrinsic(self, index: DefIndex) -> bool {
- self.root.tables.is_intrinsic.get(self, index).is_some()
+ self.root.tables.is_intrinsic.get(self, index)
+ }
+
+ fn get_doc_link_resolutions(self, index: DefIndex) -> DocLinkResMap {
+ self.root
+ .tables
+ .doc_link_resolutions
+ .get(self, index)
+ .expect("no resolutions for a doc link")
+ .decode(self)
+ }
+
+ fn get_doc_link_traits_in_scope(self, index: DefIndex) -> impl Iterator<Item = DefId> + 'a {
+ self.root
+ .tables
+ .doc_link_traits_in_scope
+ .get(self, index)
+ .expect("no traits in scope for a doc link")
+ .decode(self)
}
}
diff --git a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs
index 6fd5bd52a..83a0e833e 100644
--- a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs
+++ b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs
@@ -1,6 +1,8 @@
use crate::creader::{CStore, LoadedMacro};
use crate::foreign_modules;
use crate::native_libs;
+use crate::rmeta::table::IsDefault;
+use crate::rmeta::AttrFlags;
use rustc_ast as ast;
use rustc_attr::Deprecation;
@@ -87,6 +89,14 @@ macro_rules! provide_one {
}
}
};
+ ($tcx:ident, $def_id:ident, $other:ident, $cdata:ident, $name:ident => { table_defaulted_array }) => {
+ provide_one! {
+ $tcx, $def_id, $other, $cdata, $name => {
+ let lazy = $cdata.root.tables.$name.get($cdata, $def_id.index);
+ if lazy.is_default() { &[] } else { $tcx.arena.alloc_from_iter(lazy.decode(($cdata, $tcx))) }
+ }
+ }
+ };
($tcx:ident, $def_id:ident, $other:ident, $cdata:ident, $name:ident => { table_direct }) => {
provide_one! {
$tcx, $def_id, $other, $cdata, $name => {
@@ -104,7 +114,7 @@ macro_rules! provide_one {
fn $name<'tcx>(
$tcx: TyCtxt<'tcx>,
def_id_arg: ty::query::query_keys::$name<'tcx>,
- ) -> ty::query::query_values::$name<'tcx> {
+ ) -> ty::query::query_provided::$name<'tcx> {
let _prof_timer =
$tcx.prof.generic_activity(concat!("metadata_decode_entry_", stringify!($name)));
@@ -120,7 +130,13 @@ macro_rules! provide_one {
$tcx.ensure().crate_hash($def_id.krate);
}
- let $cdata = CStore::from_tcx($tcx).get_crate_data($def_id.krate);
+ let cdata = rustc_data_structures::sync::MappedReadGuard::map(CStore::from_tcx($tcx), |c| {
+ c.get_crate_data($def_id.krate).cdata
+ });
+ let $cdata = crate::creader::CrateMetadataRef {
+ cdata: &cdata,
+ cstore: &CStore::from_tcx($tcx),
+ };
$compute
}
@@ -186,10 +202,10 @@ impl IntoArgs for (CrateNum, SimplifiedType) {
}
provide! { tcx, def_id, other, cdata,
- explicit_item_bounds => { table }
+ explicit_item_bounds => { table_defaulted_array }
explicit_predicates_of => { table }
generics_of => { table }
- inferred_outlives_of => { table }
+ inferred_outlives_of => { table_defaulted_array }
super_predicates_of => { table }
type_of => { table }
variances_of => { table }
@@ -201,6 +217,7 @@ provide! { tcx, def_id, other, cdata,
thir_abstract_const => { table }
optimized_mir => { table }
mir_for_ctfe => { table }
+ mir_generator_witnesses => { table }
promoted_mir => { table }
def_span => { table }
def_ident_span => { table }
@@ -225,12 +242,7 @@ provide! { tcx, def_id, other, cdata,
deduced_param_attrs => { table }
is_type_alias_impl_trait => {
debug_assert_eq!(tcx.def_kind(def_id), DefKind::OpaqueTy);
- cdata
- .root
- .tables
- .is_type_alias_impl_trait
- .get(cdata, def_id.index)
- .is_some()
+ cdata.root.tables.is_type_alias_impl_trait.get(cdata, def_id.index)
}
collect_return_position_impl_trait_in_trait_tys => {
Ok(cdata
@@ -242,6 +254,8 @@ provide! { tcx, def_id, other, cdata,
.process_decoded(tcx, || panic!("{def_id:?} does not have trait_impl_trait_tys")))
}
+ associated_items_for_impl_trait_in_trait => { table_defaulted_array }
+
visibility => { cdata.get_visibility(def_id.index) }
adt_def => { cdata.get_adt_def(def_id.index, tcx) }
adt_destructor => {
@@ -298,6 +312,7 @@ provide! { tcx, def_id, other, cdata,
extra_filename => { cdata.root.extra_filename.clone() }
traits_in_crate => { tcx.arena.alloc_from_iter(cdata.get_traits()) }
+ trait_impls_in_crate => { tcx.arena.alloc_from_iter(cdata.get_trait_impls()) }
implementations_of_trait => { cdata.get_implementations_of_trait(tcx, other) }
crate_incoherent_impls => { cdata.get_incoherent_impls(tcx, other) }
@@ -338,6 +353,11 @@ provide! { tcx, def_id, other, cdata,
crate_extern_paths => { cdata.source().paths().cloned().collect() }
expn_that_defined => { cdata.get_expn_that_defined(def_id.index, tcx.sess) }
generator_diagnostic_data => { cdata.get_generator_diagnostic_data(tcx, def_id.index) }
+ is_doc_hidden => { cdata.get_attr_flags(def_id.index).contains(AttrFlags::IS_DOC_HIDDEN) }
+ doc_link_resolutions => { tcx.arena.alloc(cdata.get_doc_link_resolutions(def_id.index)) }
+ doc_link_traits_in_scope => {
+ tcx.arena.alloc_from_iter(cdata.get_doc_link_traits_in_scope(def_id.index))
+ }
}
pub(in crate::rmeta) fn provide(providers: &mut Providers) {
@@ -425,7 +445,7 @@ pub(in crate::rmeta) fn provide(providers: &mut Providers) {
return;
}
- if ty::util::is_doc_hidden(tcx, parent) {
+ if tcx.is_doc_hidden(parent) {
fallback_map.push((def_id, parent));
return;
}
@@ -597,42 +617,6 @@ impl CStore {
) -> Span {
self.get_crate_data(cnum).get_proc_macro_quoted_span(id, sess)
}
-
- /// Decodes all trait impls in the crate (for rustdoc).
- pub fn trait_impls_in_crate_untracked(
- &self,
- cnum: CrateNum,
- ) -> impl Iterator<Item = (DefId, DefId, Option<SimplifiedType>)> + '_ {
- self.get_crate_data(cnum).get_trait_impls()
- }
-
- /// Decodes all inherent impls in the crate (for rustdoc).
- pub fn inherent_impls_in_crate_untracked(
- &self,
- cnum: CrateNum,
- ) -> impl Iterator<Item = (DefId, DefId)> + '_ {
- self.get_crate_data(cnum).get_inherent_impls()
- }
-
- /// Decodes all incoherent inherent impls in the crate (for rustdoc).
- pub fn incoherent_impls_in_crate_untracked(
- &self,
- cnum: CrateNum,
- ) -> impl Iterator<Item = DefId> + '_ {
- self.get_crate_data(cnum).get_all_incoherent_impls()
- }
-
- pub fn associated_item_def_ids_untracked<'a>(
- &'a self,
- def_id: DefId,
- sess: &'a Session,
- ) -> impl Iterator<Item = DefId> + 'a {
- self.get_crate_data(def_id.krate).get_associated_item_def_ids(def_id.index, sess)
- }
-
- pub fn may_have_doc_links_untracked(&self, def_id: DefId) -> bool {
- self.get_crate_data(def_id.krate).get_may_have_doc_links(def_id.index)
- }
}
impl CrateStore for CStore {
diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs
index 8f7a61b72..3ab01f780 100644
--- a/compiler/rustc_metadata/src/rmeta/encoder.rs
+++ b/compiler/rustc_metadata/src/rmeta/encoder.rs
@@ -38,7 +38,6 @@ use rustc_span::symbol::{sym, Symbol};
use rustc_span::{
self, DebuggerVisualizerFile, ExternalSource, FileName, SourceFile, Span, SyntaxContext,
};
-use rustc_target::abi::VariantIdx;
use std::borrow::Borrow;
use std::collections::hash_map::Entry;
use std::hash::Hash;
@@ -76,13 +75,13 @@ pub(super) struct EncodeContext<'a, 'tcx> {
symbol_table: FxHashMap<Symbol, usize>,
}
-/// If the current crate is a proc-macro, returns early with `LazyArray::empty()`.
+/// If the current crate is a proc-macro, returns early with `LazyArray::default()`.
/// This is useful for skipping the encoding of things that aren't needed
/// for proc-macro crates.
macro_rules! empty_proc_macro {
($self:ident) => {
if $self.is_proc_macro {
- return LazyArray::empty();
+ return LazyArray::default();
}
};
}
@@ -365,25 +364,35 @@ impl<'a, 'tcx> TyEncoder for EncodeContext<'a, 'tcx> {
}
}
-// Shorthand for `$self.$tables.$table.set($def_id.index, $self.lazy_value($value))`, which would
+// Shorthand for `$self.$tables.$table.set_some($def_id.index, $self.lazy_value($value))`, which would
// normally need extra variables to avoid errors about multiple mutable borrows.
macro_rules! record {
($self:ident.$tables:ident.$table:ident[$def_id:expr] <- $value:expr) => {{
{
let value = $value;
let lazy = $self.lazy(value);
- $self.$tables.$table.set($def_id.index, lazy);
+ $self.$tables.$table.set_some($def_id.index, lazy);
}
}};
}
-// Shorthand for `$self.$tables.$table.set($def_id.index, $self.lazy_value($value))`, which would
+// Shorthand for `$self.$tables.$table.set_some($def_id.index, $self.lazy_value($value))`, which would
// normally need extra variables to avoid errors about multiple mutable borrows.
macro_rules! record_array {
($self:ident.$tables:ident.$table:ident[$def_id:expr] <- $value:expr) => {{
{
let value = $value;
let lazy = $self.lazy_array(value);
+ $self.$tables.$table.set_some($def_id.index, lazy);
+ }
+ }};
+}
+
+macro_rules! record_defaulted_array {
+ ($self:ident.$tables:ident.$table:ident[$def_id:expr] <- $value:expr) => {{
+ {
+ let value = $value;
+ let lazy = $self.lazy_array(value);
$self.$tables.$table.set($def_id.index, lazy);
}
}};
@@ -467,13 +476,13 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
{
let def_key = self.lazy(table.def_key(def_index));
let def_path_hash = table.def_path_hash(def_index);
- self.tables.def_keys.set(def_index, def_key);
+ self.tables.def_keys.set_some(def_index, def_key);
self.tables.def_path_hashes.set(def_index, def_path_hash);
}
} else {
for (def_index, def_key, def_path_hash) in table.enumerated_keys_and_path_hashes() {
let def_key = self.lazy(def_key);
- self.tables.def_keys.set(def_index, def_key);
+ self.tables.def_keys.set_some(def_index, def_key);
self.tables.def_path_hashes.set(def_index, *def_path_hash);
}
}
@@ -483,7 +492,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
self.lazy(DefPathHashMapRef::BorrowedFromTcx(self.tcx.def_path_hash_to_def_index_map()))
}
- fn encode_source_map(&mut self) -> LazyTable<u32, LazyValue<rustc_span::SourceFile>> {
+ fn encode_source_map(&mut self) -> LazyTable<u32, Option<LazyValue<rustc_span::SourceFile>>> {
let source_map = self.tcx.sess.source_map();
let all_source_files = source_map.files();
@@ -548,7 +557,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
let on_disk_index: u32 =
on_disk_index.try_into().expect("cannot export more than U32_MAX files");
- adapted.set(on_disk_index, self.lazy(source_file));
+ adapted.set_some(on_disk_index, self.lazy(source_file));
}
adapted.encode(&mut self.opaque)
@@ -760,36 +769,50 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
}
}
+struct AnalyzeAttrState {
+ is_exported: bool,
+ is_doc_hidden: bool,
+}
+
/// Returns whether an attribute needs to be recorded in metadata, that is, if it's usable and
/// useful in downstream crates. Local-only attributes are an obvious example, but some
/// rustdoc-specific attributes can equally be of use while documenting the current crate only.
///
/// Removing these superfluous attributes speeds up compilation by making the metadata smaller.
///
-/// Note: the `is_def_id_public` parameter is used to cache whether the given `DefId` has a public
+/// Note: the `is_exported` parameter is used to cache whether the given `DefId` has a public
/// visibility: this is a piece of data that can be computed once per defid, and not once per
/// attribute. Some attributes would only be usable downstream if they are public.
#[inline]
-fn should_encode_attr(
- tcx: TyCtxt<'_>,
- attr: &Attribute,
- def_id: LocalDefId,
- is_def_id_public: &mut Option<bool>,
-) -> bool {
+fn analyze_attr(attr: &Attribute, state: &mut AnalyzeAttrState) -> bool {
+ let mut should_encode = false;
if rustc_feature::is_builtin_only_local(attr.name_or_empty()) {
// Attributes marked local-only don't need to be encoded for downstream crates.
- false
} else if attr.doc_str().is_some() {
- // We keep all public doc comments because they might be "imported" into downstream crates
- // if they use `#[doc(inline)]` to copy an item's documentation into their own.
- *is_def_id_public.get_or_insert_with(|| tcx.effective_visibilities(()).is_exported(def_id))
+ // We keep all doc comments reachable to rustdoc because they might be "imported" into
+ // downstream crates if they use `#[doc(inline)]` to copy an item's documentation into
+ // their own.
+ if state.is_exported {
+ should_encode = true;
+ }
} else if attr.has_name(sym::doc) {
- // If this is a `doc` attribute, and it's marked `inline` (as in `#[doc(inline)]`), we can
- // remove it. It won't be inlinable in downstream crates.
- attr.meta_item_list().map(|l| l.iter().any(|l| !l.has_name(sym::inline))).unwrap_or(false)
+ // If this is a `doc` attribute that doesn't have anything except maybe `inline` (as in
+ // `#[doc(inline)]`), then we can remove it. It won't be inlinable in downstream crates.
+ if let Some(item_list) = attr.meta_item_list() {
+ for item in item_list {
+ if !item.has_name(sym::inline) {
+ should_encode = true;
+ if item.has_name(sym::hidden) {
+ state.is_doc_hidden = true;
+ break;
+ }
+ }
+ }
+ }
} else {
- true
+ should_encode = true;
}
+ should_encode
}
fn should_encode_visibility(def_kind: DefKind) -> bool {
@@ -815,7 +838,7 @@ fn should_encode_visibility(def_kind: DefKind) -> bool {
| DefKind::ForeignMod
| DefKind::OpaqueTy
| DefKind::ImplTraitPlaceholder
- | DefKind::Impl
+ | DefKind::Impl { .. }
| DefKind::Field => true,
DefKind::TyParam
| DefKind::ConstParam
@@ -850,7 +873,7 @@ fn should_encode_stability(def_kind: DefKind) -> bool {
| DefKind::ImplTraitPlaceholder
| DefKind::Enum
| DefKind::Union
- | DefKind::Impl
+ | DefKind::Impl { .. }
| DefKind::Trait
| DefKind::TraitAlias
| DefKind::Macro(..)
@@ -928,7 +951,7 @@ fn should_encode_variances(def_kind: DefKind) -> bool {
| DefKind::Const
| DefKind::ForeignMod
| DefKind::TyAlias
- | DefKind::Impl
+ | DefKind::Impl { .. }
| DefKind::Trait
| DefKind::TraitAlias
| DefKind::Macro(..)
@@ -965,7 +988,7 @@ fn should_encode_generics(def_kind: DefKind) -> bool {
| DefKind::InlineConst
| DefKind::OpaqueTy
| DefKind::ImplTraitPlaceholder
- | DefKind::Impl
+ | DefKind::Impl { .. }
| DefKind::Field
| DefKind::TyParam
| DefKind::Closure
@@ -995,7 +1018,7 @@ fn should_encode_type(tcx: TyCtxt<'_>, def_id: LocalDefId, def_kind: DefKind) ->
| DefKind::TyAlias
| DefKind::OpaqueTy
| DefKind::ForeignTy
- | DefKind::Impl
+ | DefKind::Impl { .. }
| DefKind::AssocFn
| DefKind::AssocConst
| DefKind::Closure
@@ -1058,7 +1081,7 @@ fn should_encode_const(def_kind: DefKind) -> bool {
| DefKind::OpaqueTy
| DefKind::ImplTraitPlaceholder
| DefKind::ForeignTy
- | DefKind::Impl
+ | DefKind::Impl { .. }
| DefKind::AssocFn
| DefKind::Closure
| DefKind::Generator
@@ -1078,49 +1101,40 @@ fn should_encode_const(def_kind: DefKind) -> bool {
}
}
-fn should_encode_trait_impl_trait_tys(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
- if tcx.def_kind(def_id) != DefKind::AssocFn {
- return false;
- }
-
- let Some(item) = tcx.opt_associated_item(def_id) else { return false; };
- if item.container != ty::AssocItemContainer::ImplContainer {
- return false;
+// We only encode impl trait in trait when using `lower-impl-trait-in-trait-to-assoc-ty` unstable
+// option.
+fn should_encode_fn_impl_trait_in_trait<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> bool {
+ if tcx.sess.opts.unstable_opts.lower_impl_trait_in_trait_to_assoc_ty
+ && let Some(assoc_item) = tcx.opt_associated_item(def_id)
+ && assoc_item.container == ty::AssocItemContainer::TraitContainer
+ && assoc_item.kind == ty::AssocKind::Fn
+ {
+ true
+ } else {
+ false
}
-
- let Some(trait_item_def_id) = item.trait_item_def_id else { return false; };
-
- // FIXME(RPITIT): This does a somewhat manual walk through the signature
- // of the trait fn to look for any RPITITs, but that's kinda doing a lot
- // of work. We can probably remove this when we refactor RPITITs to be
- // associated types.
- tcx.fn_sig(trait_item_def_id).skip_binder().output().walk().any(|arg| {
- if let ty::GenericArgKind::Type(ty) = arg.unpack()
- && let ty::Alias(ty::Projection, data) = ty.kind()
- && tcx.def_kind(data.def_id) == DefKind::ImplTraitPlaceholder
- {
- true
- } else {
- false
- }
- })
}
impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
fn encode_attrs(&mut self, def_id: LocalDefId) {
let tcx = self.tcx;
- let mut is_public: Option<bool> = None;
-
- let mut attrs = tcx
- .hir()
- .attrs(tcx.hir().local_def_id_to_hir_id(def_id))
+ let mut state = AnalyzeAttrState {
+ is_exported: tcx.effective_visibilities(()).is_exported(def_id),
+ is_doc_hidden: false,
+ };
+ let attr_iter = tcx
+ .opt_local_def_id_to_hir_id(def_id)
+ .map_or(Default::default(), |hir_id| tcx.hir().attrs(hir_id))
.iter()
- .filter(move |attr| should_encode_attr(tcx, attr, def_id, &mut is_public));
+ .filter(|attr| analyze_attr(attr, &mut state));
+
+ record_array!(self.tables.attributes[def_id.to_def_id()] <- attr_iter);
- record_array!(self.tables.attributes[def_id.to_def_id()] <- attrs.clone());
- if attrs.any(|attr| attr.may_have_doc_links()) {
- self.tables.may_have_doc_links.set(def_id.local_def_index, ());
+ let mut attr_flags = AttrFlags::empty();
+ if state.is_doc_hidden {
+ attr_flags |= AttrFlags::IS_DOC_HIDDEN;
}
+ self.tables.attr_flags.set(def_id.local_def_index, attr_flags);
}
fn encode_def_ids(&mut self) {
@@ -1132,7 +1146,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
let def_id = local_id.to_def_id();
let def_kind = tcx.opt_def_kind(local_id);
let Some(def_kind) = def_kind else { continue };
- self.tables.opt_def_kind.set(def_id.index, def_kind);
+ self.tables.opt_def_kind.set_some(def_id.index, def_kind);
let def_span = tcx.def_span(local_id);
record!(self.tables.def_span[def_id] <- def_span);
self.encode_attrs(local_id);
@@ -1163,9 +1177,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
record!(self.tables.generics_of[def_id] <- g);
record!(self.tables.explicit_predicates_of[def_id] <- self.tcx.explicit_predicates_of(def_id));
let inferred_outlives = self.tcx.inferred_outlives_of(def_id);
- if !inferred_outlives.is_empty() {
- record_array!(self.tables.inferred_outlives_of[def_id] <- inferred_outlives);
- }
+ record_defaulted_array!(self.tables.inferred_outlives_of[def_id] <- inferred_outlives);
}
if should_encode_type(tcx, local_id, def_kind) {
record!(self.tables.type_of[def_id] <- self.tcx.type_of(def_id));
@@ -1178,70 +1190,85 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
record!(self.tables.super_predicates_of[def_id] <- self.tcx.super_predicates_of(def_id));
}
if let DefKind::Enum | DefKind::Struct | DefKind::Union = def_kind {
- let params_in_repr = self.tcx.params_in_repr(def_id);
- record!(self.tables.params_in_repr[def_id] <- params_in_repr);
+ self.encode_info_for_adt(def_id);
}
- if should_encode_trait_impl_trait_tys(tcx, def_id)
+ if tcx.impl_method_has_trait_impl_trait_tys(def_id)
&& let Ok(table) = self.tcx.collect_return_position_impl_trait_in_trait_tys(def_id)
{
record!(self.tables.trait_impl_trait_tys[def_id] <- table);
}
+ if should_encode_fn_impl_trait_in_trait(tcx, def_id) {
+ let table = tcx.associated_items_for_impl_trait_in_trait(def_id);
+ record_defaulted_array!(self.tables.associated_items_for_impl_trait_in_trait[def_id] <- table);
+ }
}
+
let inherent_impls = tcx.with_stable_hashing_context(|hcx| {
tcx.crate_inherent_impls(()).inherent_impls.to_sorted(&hcx, true)
});
-
- for (def_id, implementations) in inherent_impls {
- if implementations.is_empty() {
- continue;
- }
- record_array!(self.tables.inherent_impls[def_id.to_def_id()] <- implementations.iter().map(|&def_id| {
+ for (def_id, impls) in inherent_impls {
+ record_defaulted_array!(self.tables.inherent_impls[def_id.to_def_id()] <- impls.iter().map(|def_id| {
assert!(def_id.is_local());
def_id.index
}));
}
+
+ for (def_id, res_map) in &tcx.resolutions(()).doc_link_resolutions {
+ record!(self.tables.doc_link_resolutions[def_id.to_def_id()] <- res_map);
+ }
+
+ for (def_id, traits) in &tcx.resolutions(()).doc_link_traits_in_scope {
+ record_array!(self.tables.doc_link_traits_in_scope[def_id.to_def_id()] <- traits);
+ }
}
- fn encode_enum_variant_info(&mut self, def: ty::AdtDef<'tcx>, index: VariantIdx) {
+ #[instrument(level = "trace", skip(self))]
+ fn encode_info_for_adt(&mut self, def_id: DefId) {
let tcx = self.tcx;
- let variant = &def.variant(index);
- let def_id = variant.def_id;
- debug!("EncodeContext::encode_enum_variant_info({:?})", def_id);
-
- let data = VariantData {
- discr: variant.discr,
- ctor: variant.ctor.map(|(kind, def_id)| (kind, def_id.index)),
- is_non_exhaustive: variant.is_field_list_non_exhaustive(),
- };
+ let adt_def = tcx.adt_def(def_id);
+ record!(self.tables.repr_options[def_id] <- adt_def.repr());
+
+ let params_in_repr = self.tcx.params_in_repr(def_id);
+ record!(self.tables.params_in_repr[def_id] <- params_in_repr);
- record!(self.tables.variant_data[def_id] <- data);
- self.tables.constness.set(def_id.index, hir::Constness::Const);
- record_array!(self.tables.children[def_id] <- variant.fields.iter().map(|f| {
- assert!(f.did.is_local());
- f.did.index
- }));
- if let Some((CtorKind::Fn, ctor_def_id)) = variant.ctor {
- // FIXME(eddyb) encode signature only in `encode_enum_variant_ctor`.
- record!(self.tables.fn_sig[def_id] <- tcx.fn_sig(ctor_def_id));
+ if adt_def.is_enum() {
+ record_array!(self.tables.children[def_id] <- iter::from_generator(||
+ for variant in tcx.adt_def(def_id).variants() {
+ yield variant.def_id.index;
+ // Encode constructors which take a separate slot in value namespace.
+ if let Some(ctor_def_id) = variant.ctor_def_id() {
+ yield ctor_def_id.index;
+ }
+ }
+ ));
+ } else {
+ // For non-enum, there is only one variant, and its def_id is the adt's.
+ debug_assert_eq!(adt_def.variants().len(), 1);
+ debug_assert_eq!(adt_def.non_enum_variant().def_id, def_id);
+ // Therefore, the loop over variants will encode its fields as the adt's children.
}
- }
- fn encode_enum_variant_ctor(&mut self, def: ty::AdtDef<'tcx>, index: VariantIdx) {
- let variant = &def.variant(index);
- let Some((ctor_kind, def_id)) = variant.ctor else { return };
- debug!("EncodeContext::encode_enum_variant_ctor({:?})", def_id);
+ for variant in adt_def.variants().iter() {
+ let data = VariantData {
+ discr: variant.discr,
+ ctor: variant.ctor.map(|(kind, def_id)| (kind, def_id.index)),
+ is_non_exhaustive: variant.is_field_list_non_exhaustive(),
+ };
+ record!(self.tables.variant_data[variant.def_id] <- data);
- // FIXME(eddyb) encode only the `CtorKind` for constructors.
- let data = VariantData {
- discr: variant.discr,
- ctor: Some((ctor_kind, def_id.index)),
- is_non_exhaustive: variant.is_field_list_non_exhaustive(),
- };
+ self.tables.constness.set_some(variant.def_id.index, hir::Constness::Const);
+ record_array!(self.tables.children[variant.def_id] <- variant.fields.iter().map(|f| {
+ assert!(f.did.is_local());
+ f.did.index
+ }));
- record!(self.tables.variant_data[def_id] <- data);
- self.tables.constness.set(def_id.index, hir::Constness::Const);
- if ctor_kind == CtorKind::Fn {
- record!(self.tables.fn_sig[def_id] <- self.tcx.fn_sig(def_id));
+ if let Some((CtorKind::Fn, ctor_def_id)) = variant.ctor {
+ self.tables.constness.set_some(ctor_def_id.index, hir::Constness::Const);
+ let fn_sig = tcx.fn_sig(ctor_def_id);
+ record!(self.tables.fn_sig[ctor_def_id] <- fn_sig);
+ // FIXME only encode signature for ctor_def_id
+ record!(self.tables.fn_sig[variant.def_id] <- fn_sig);
+ }
}
}
@@ -1275,8 +1302,8 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
hir::ItemKind::Struct(ref vdata, _) => {
yield item_id.owner_id.def_id.local_def_index;
// Encode constructors which take a separate slot in value namespace.
- if let Some(ctor_hir_id) = vdata.ctor_hir_id() {
- yield tcx.hir().local_def_id(ctor_hir_id).local_def_index;
+ if let Some(ctor_def_id) = vdata.ctor_def_id() {
+ yield ctor_def_id.local_def_index;
}
}
_ if tcx.def_key(item_id.owner_id.to_def_id()).get_opt_name().is_some() => {
@@ -1294,31 +1321,10 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
}
}
- fn encode_struct_ctor(&mut self, adt_def: ty::AdtDef<'tcx>) {
- let variant = adt_def.non_enum_variant();
- let Some((ctor_kind, def_id)) = variant.ctor else { return };
- debug!("EncodeContext::encode_struct_ctor({:?})", def_id);
-
- let data = VariantData {
- discr: variant.discr,
- ctor: Some((ctor_kind, def_id.index)),
- is_non_exhaustive: variant.is_field_list_non_exhaustive(),
- };
-
- record!(self.tables.repr_options[def_id] <- adt_def.repr());
- record!(self.tables.variant_data[def_id] <- data);
- self.tables.constness.set(def_id.index, hir::Constness::Const);
- if ctor_kind == CtorKind::Fn {
- record!(self.tables.fn_sig[def_id] <- self.tcx.fn_sig(def_id));
- }
- }
-
fn encode_explicit_item_bounds(&mut self, def_id: DefId) {
debug!("EncodeContext::encode_explicit_item_bounds({:?})", def_id);
let bounds = self.tcx.explicit_item_bounds(def_id);
- if !bounds.is_empty() {
- record_array!(self.tables.explicit_item_bounds[def_id] <- bounds);
- }
+ record_defaulted_array!(self.tables.explicit_item_bounds[def_id] <- bounds);
}
fn encode_info_for_trait_item(&mut self, def_id: DefId) {
@@ -1326,16 +1332,16 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
let tcx = self.tcx;
let impl_defaultness = tcx.impl_defaultness(def_id.expect_local());
- self.tables.impl_defaultness.set(def_id.index, impl_defaultness);
+ self.tables.impl_defaultness.set_some(def_id.index, impl_defaultness);
let trait_item = tcx.associated_item(def_id);
- self.tables.assoc_container.set(def_id.index, trait_item.container);
+ self.tables.assoc_container.set_some(def_id.index, trait_item.container);
match trait_item.kind {
ty::AssocKind::Const => {}
ty::AssocKind::Fn => {
record_array!(self.tables.fn_arg_names[def_id] <- tcx.fn_arg_names(def_id));
- self.tables.asyncness.set(def_id.index, tcx.asyncness(def_id));
- self.tables.constness.set(def_id.index, hir::Constness::NotConst);
+ self.tables.asyncness.set_some(def_id.index, tcx.asyncness(def_id));
+ self.tables.constness.set_some(def_id.index, hir::Constness::NotConst);
}
ty::AssocKind::Type => {
self.encode_explicit_item_bounds(def_id);
@@ -1351,14 +1357,14 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
let tcx = self.tcx;
let ast_item = self.tcx.hir().expect_impl_item(def_id.expect_local());
- self.tables.impl_defaultness.set(def_id.index, ast_item.defaultness);
+ self.tables.impl_defaultness.set_some(def_id.index, ast_item.defaultness);
let impl_item = self.tcx.associated_item(def_id);
- self.tables.assoc_container.set(def_id.index, impl_item.container);
+ self.tables.assoc_container.set_some(def_id.index, impl_item.container);
match impl_item.kind {
ty::AssocKind::Fn => {
let hir::ImplItemKind::Fn(ref sig, body) = ast_item.kind else { bug!() };
- self.tables.asyncness.set(def_id.index, sig.header.asyncness);
+ self.tables.asyncness.set_some(def_id.index, sig.header.asyncness);
record_array!(self.tables.fn_arg_names[def_id] <- self.tcx.hir().body_param_names(body));
// Can be inside `impl const Trait`, so using sig.header.constness is not reliable
let constness = if self.tcx.is_const_fn_raw(def_id) {
@@ -1366,18 +1372,16 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
} else {
hir::Constness::NotConst
};
- self.tables.constness.set(def_id.index, constness);
+ self.tables.constness.set_some(def_id.index, constness);
}
ty::AssocKind::Const | ty::AssocKind::Type => {}
}
if let Some(trait_item_def_id) = impl_item.trait_item_def_id {
- self.tables.trait_item_def_id.set(def_id.index, trait_item_def_id.into());
+ self.tables.trait_item_def_id.set_some(def_id.index, trait_item_def_id.into());
}
if impl_item.kind == ty::AssocKind::Fn {
record!(self.tables.fn_sig[def_id] <- tcx.fn_sig(def_id));
- if tcx.is_intrinsic(def_id) {
- self.tables.is_intrinsic.set(def_id.index, ());
- }
+ self.tables.is_intrinsic.set(def_id.index, tcx.is_intrinsic(def_id));
}
}
@@ -1398,6 +1402,10 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
debug!("EntryBuilder::encode_mir({:?})", def_id);
if encode_opt {
record!(self.tables.optimized_mir[def_id.to_def_id()] <- tcx.optimized_mir(def_id));
+
+ if tcx.sess.opts.unstable_opts.drop_tracking_mir && let DefKind::Generator = self.tcx.def_kind(def_id) {
+ record!(self.tables.mir_generator_witnesses[def_id.to_def_id()] <- tcx.mir_generator_witnesses(def_id));
+ }
}
if encode_const {
record!(self.tables.mir_for_ctfe[def_id.to_def_id()] <- tcx.mir_for_ctfe(def_id));
@@ -1502,14 +1510,12 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
match item.kind {
hir::ItemKind::Fn(ref sig, .., body) => {
- self.tables.asyncness.set(def_id.index, sig.header.asyncness);
+ self.tables.asyncness.set_some(def_id.index, sig.header.asyncness);
record_array!(self.tables.fn_arg_names[def_id] <- self.tcx.hir().body_param_names(body));
- self.tables.constness.set(def_id.index, sig.header.constness);
+ self.tables.constness.set_some(def_id.index, sig.header.constness);
}
hir::ItemKind::Macro(ref macro_def, _) => {
- if macro_def.macro_rules {
- self.tables.macro_rules.set(def_id.index, ());
- }
+ self.tables.is_macro_rules.set(def_id.index, macro_def.macro_rules);
record!(self.tables.macro_definition[def_id] <- &*macro_def.body);
}
hir::ItemKind::Mod(ref m) => {
@@ -1517,47 +1523,21 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
}
hir::ItemKind::OpaqueTy(ref opaque) => {
self.encode_explicit_item_bounds(def_id);
- if matches!(opaque.origin, hir::OpaqueTyOrigin::TyAlias) {
- self.tables.is_type_alias_impl_trait.set(def_id.index, ());
- }
- }
- hir::ItemKind::Enum(..) => {
- let adt_def = self.tcx.adt_def(def_id);
- record!(self.tables.repr_options[def_id] <- adt_def.repr());
- }
- hir::ItemKind::Struct(..) => {
- let adt_def = self.tcx.adt_def(def_id);
- record!(self.tables.repr_options[def_id] <- adt_def.repr());
- self.tables.constness.set(def_id.index, hir::Constness::Const);
-
- let variant = adt_def.non_enum_variant();
- record!(self.tables.variant_data[def_id] <- VariantData {
- discr: variant.discr,
- ctor: variant.ctor.map(|(kind, def_id)| (kind, def_id.index)),
- is_non_exhaustive: variant.is_field_list_non_exhaustive(),
- });
- }
- hir::ItemKind::Union(..) => {
- let adt_def = self.tcx.adt_def(def_id);
- record!(self.tables.repr_options[def_id] <- adt_def.repr());
-
- let variant = adt_def.non_enum_variant();
- record!(self.tables.variant_data[def_id] <- VariantData {
- discr: variant.discr,
- ctor: variant.ctor.map(|(kind, def_id)| (kind, def_id.index)),
- is_non_exhaustive: variant.is_field_list_non_exhaustive(),
- });
+ self.tables
+ .is_type_alias_impl_trait
+ .set(def_id.index, matches!(opaque.origin, hir::OpaqueTyOrigin::TyAlias));
}
hir::ItemKind::Impl(hir::Impl { defaultness, constness, .. }) => {
- self.tables.impl_defaultness.set(def_id.index, *defaultness);
- self.tables.constness.set(def_id.index, *constness);
+ self.tables.impl_defaultness.set_some(def_id.index, *defaultness);
+ self.tables.constness.set_some(def_id.index, *constness);
- let trait_ref = self.tcx.impl_trait_ref(def_id).map(ty::EarlyBinder::skip_binder);
+ let trait_ref = self.tcx.impl_trait_ref(def_id);
if let Some(trait_ref) = trait_ref {
+ let trait_ref = trait_ref.skip_binder();
let trait_def = self.tcx.trait_def(trait_ref.def_id);
if let Ok(mut an) = trait_def.ancestors(self.tcx, def_id) {
if let Some(specialization_graph::Node::Impl(parent)) = an.nth(1) {
- self.tables.impl_parent.set(def_id.index, parent.into());
+ self.tables.impl_parent.set_some(def_id.index, parent.into());
}
}
@@ -1571,7 +1551,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
}
let polarity = self.tcx.impl_polarity(def_id);
- self.tables.impl_polarity.set(def_id.index, polarity);
+ self.tables.impl_polarity.set_some(def_id.index, polarity);
}
hir::ItemKind::Trait(..) => {
let trait_def = self.tcx.trait_def(def_id);
@@ -1586,31 +1566,15 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
}
hir::ItemKind::Static(..)
| hir::ItemKind::Const(..)
+ | hir::ItemKind::Enum(..)
+ | hir::ItemKind::Struct(..)
+ | hir::ItemKind::Union(..)
| hir::ItemKind::ForeignMod { .. }
| hir::ItemKind::GlobalAsm(..)
| hir::ItemKind::TyAlias(..) => {}
};
// FIXME(eddyb) there should be a nicer way to do this.
match item.kind {
- hir::ItemKind::Enum(..) => {
- record_array!(self.tables.children[def_id] <- iter::from_generator(||
- for variant in tcx.adt_def(def_id).variants() {
- yield variant.def_id.index;
- // Encode constructors which take a separate slot in value namespace.
- if let Some(ctor_def_id) = variant.ctor_def_id() {
- yield ctor_def_id.index;
- }
- }
- ))
- }
- hir::ItemKind::Struct(..) | hir::ItemKind::Union(..) => {
- record_array!(self.tables.children[def_id] <-
- self.tcx.adt_def(def_id).non_enum_variant().fields.iter().map(|f| {
- assert!(f.did.is_local());
- f.did.index
- })
- )
- }
hir::ItemKind::Impl { .. } | hir::ItemKind::Trait(..) => {
let associated_item_def_ids = self.tcx.associated_item_def_ids(def_id);
record_array!(self.tables.children[def_id] <-
@@ -1624,9 +1588,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
}
if let hir::ItemKind::Fn(..) = item.kind {
record!(self.tables.fn_sig[def_id] <- tcx.fn_sig(def_id));
- if tcx.is_intrinsic(def_id) {
- self.tables.is_intrinsic.set(def_id.index, ());
- }
+ self.tables.is_intrinsic.set(def_id.index, tcx.is_intrinsic(def_id));
}
if let hir::ItemKind::Impl { .. } = item.kind {
if let Some(trait_ref) = self.tcx.impl_trait_ref(def_id) {
@@ -1638,17 +1600,6 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
// so it's easier to do that here then to wait until we would encounter
// normally in the visitor walk.
match item.kind {
- hir::ItemKind::Enum(..) => {
- let def = self.tcx.adt_def(item.owner_id.to_def_id());
- for (i, _) in def.variants().iter_enumerated() {
- self.encode_enum_variant_info(def, i);
- self.encode_enum_variant_ctor(def, i);
- }
- }
- hir::ItemKind::Struct(..) => {
- let def = self.tcx.adt_def(item.owner_id.to_def_id());
- self.encode_struct_ctor(def);
- }
hir::ItemKind::Impl { .. } => {
for &trait_item_def_id in
self.tcx.associated_item_def_ids(item.owner_id.to_def_id()).iter()
@@ -1670,7 +1621,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
#[instrument(level = "debug", skip(self))]
fn encode_info_for_closure(&mut self, def_id: LocalDefId) {
// NOTE(eddyb) `tcx.type_of(def_id)` isn't used because it's fully generic,
- // including on the signature, which is inferred in `typeck.
+ // including on the signature, which is inferred in `typeck`.
let typeck_result: &'tcx ty::TypeckResults<'tcx> = self.tcx.typeck(def_id);
let hir_id = self.tcx.hir().local_def_id_to_hir_id(def_id);
let ty = typeck_result.node_type(hir_id);
@@ -1684,8 +1635,8 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
ty::Closure(_, substs) => {
let constness = self.tcx.constness(def_id.to_def_id());
- self.tables.constness.set(def_id.to_def_id().index, constness);
- record!(self.tables.fn_sig[def_id.to_def_id()] <- substs.as_closure().sig());
+ self.tables.constness.set_some(def_id.to_def_id().index, constness);
+ record!(self.tables.fn_sig[def_id.to_def_id()] <- ty::EarlyBinder(substs.as_closure().sig()));
}
_ => bug!("closure that is neither generator nor closure"),
@@ -1712,12 +1663,12 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
self.hygiene_ctxt.encode(
&mut (&mut *self, &mut syntax_contexts, &mut expn_data_table, &mut expn_hash_table),
|(this, syntax_contexts, _, _), index, ctxt_data| {
- syntax_contexts.set(index, this.lazy(ctxt_data));
+ syntax_contexts.set_some(index, this.lazy(ctxt_data));
},
|(this, _, expn_data_table, expn_hash_table), index, expn_data, hash| {
if let Some(index) = index.as_local() {
- expn_data_table.set(index.as_raw(), this.lazy(expn_data));
- expn_hash_table.set(index.as_raw(), this.lazy(hash));
+ expn_data_table.set_some(index.as_raw(), this.lazy(expn_data));
+ expn_hash_table.set_some(index.as_raw(), this.lazy(hash));
}
},
);
@@ -1742,10 +1693,10 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
let spans = self.tcx.sess.parse_sess.proc_macro_quoted_spans();
for (i, span) in spans.into_iter().enumerate() {
let span = self.lazy(span);
- self.tables.proc_macro_quoted_spans.set(i, span);
+ self.tables.proc_macro_quoted_spans.set_some(i, span);
}
- self.tables.opt_def_kind.set(LOCAL_CRATE.as_def_id().index, DefKind::Mod);
+ self.tables.opt_def_kind.set_some(LOCAL_CRATE.as_def_id().index, DefKind::Mod);
record!(self.tables.def_span[LOCAL_CRATE.as_def_id()] <- tcx.def_span(LOCAL_CRATE.as_def_id()));
self.encode_attrs(LOCAL_CRATE.as_def_id().expect_local());
let vis = tcx.local_visibility(CRATE_DEF_ID).map_id(|def_id| def_id.local_def_index);
@@ -1754,6 +1705,12 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
record!(self.tables.lookup_stability[LOCAL_CRATE.as_def_id()] <- stability);
}
self.encode_deprecation(LOCAL_CRATE.as_def_id());
+ if let Some(res_map) = tcx.resolutions(()).doc_link_resolutions.get(&CRATE_DEF_ID) {
+ record!(self.tables.doc_link_resolutions[LOCAL_CRATE.as_def_id()] <- res_map);
+ }
+ if let Some(traits) = tcx.resolutions(()).doc_link_traits_in_scope.get(&CRATE_DEF_ID) {
+ record_array!(self.tables.doc_link_traits_in_scope[LOCAL_CRATE.as_def_id()] <- traits);
+ }
// Normally, this information is encoded when we walk the items
// defined in this crate. However, we skip doing that for proc-macro crates,
@@ -1787,8 +1744,8 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
def_key.disambiguated_data.data = DefPathData::MacroNs(name);
let def_id = id.to_def_id();
- self.tables.opt_def_kind.set(def_id.index, DefKind::Macro(macro_kind));
- self.tables.proc_macro.set(def_id.index, macro_kind);
+ self.tables.opt_def_kind.set_some(def_id.index, DefKind::Macro(macro_kind));
+ self.tables.proc_macro.set_some(def_id.index, macro_kind);
self.encode_attrs(id);
record!(self.tables.def_keys[def_id] <- def_key);
record!(self.tables.def_ident_span[def_id] <- span);
@@ -1894,7 +1851,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
FxHashMap::default();
for id in tcx.hir().items() {
- if matches!(tcx.def_kind(id.owner_id), DefKind::Impl) {
+ if matches!(tcx.def_kind(id.owner_id), DefKind::Impl { .. }) {
if let Some(trait_ref) = tcx.impl_trait_ref(id.owner_id) {
let trait_ref = trait_ref.subst_identity();
@@ -2003,7 +1960,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
Linkage::Static => Some(LinkagePreference::RequireStatic),
}));
}
- LazyArray::empty()
+ LazyArray::default()
}
fn encode_info_for_foreign_item(&mut self, def_id: DefId, nitem: &hir::ForeignItem<'_>) {
@@ -2013,22 +1970,20 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
match nitem.kind {
hir::ForeignItemKind::Fn(_, ref names, _) => {
- self.tables.asyncness.set(def_id.index, hir::IsAsync::NotAsync);
+ self.tables.asyncness.set_some(def_id.index, hir::IsAsync::NotAsync);
record_array!(self.tables.fn_arg_names[def_id] <- *names);
let constness = if self.tcx.is_const_fn_raw(def_id) {
hir::Constness::Const
} else {
hir::Constness::NotConst
};
- self.tables.constness.set(def_id.index, constness);
+ self.tables.constness.set_some(def_id.index, constness);
record!(self.tables.fn_sig[def_id] <- tcx.fn_sig(def_id));
}
hir::ForeignItemKind::Static(..) | hir::ForeignItemKind::Type => {}
}
if let hir::ForeignItemKind::Fn(..) = nitem.kind {
- if tcx.is_intrinsic(def_id) {
- self.tables.is_intrinsic.set(def_id.index, ());
- }
+ self.tables.is_intrinsic.set(def_id.index, tcx.is_intrinsic(def_id));
}
}
}
@@ -2266,6 +2221,18 @@ fn encode_metadata_impl(tcx: TyCtxt<'_>, path: &Path) {
pub fn provide(providers: &mut Providers) {
*providers = Providers {
+ doc_link_resolutions: |tcx, def_id| {
+ tcx.resolutions(())
+ .doc_link_resolutions
+ .get(&def_id.expect_local())
+ .expect("no resolutions for a doc link")
+ },
+ doc_link_traits_in_scope: |tcx, def_id| {
+ tcx.resolutions(())
+ .doc_link_traits_in_scope
+ .get(&def_id.expect_local())
+ .expect("no traits in scope for a doc link")
+ },
traits_in_crate: |tcx, cnum| {
assert_eq!(cnum, LOCAL_CRATE);
@@ -2280,6 +2247,22 @@ pub fn provide(providers: &mut Providers) {
traits.sort_by_cached_key(|&def_id| tcx.def_path_hash(def_id));
tcx.arena.alloc_slice(&traits)
},
+ trait_impls_in_crate: |tcx, cnum| {
+ assert_eq!(cnum, LOCAL_CRATE);
+
+ let mut trait_impls = Vec::new();
+ for id in tcx.hir().items() {
+ if matches!(tcx.def_kind(id.owner_id), DefKind::Impl { .. })
+ && tcx.impl_trait_ref(id.owner_id).is_some()
+ {
+ trait_impls.push(id.owner_id.to_def_id())
+ }
+ }
+
+ // Bring everything into deterministic order.
+ trait_impls.sort_by_cached_key(|&def_id| tcx.def_path_hash(def_id));
+ tcx.arena.alloc_slice(&trait_impls)
+ },
..*providers
}
diff --git a/compiler/rustc_metadata/src/rmeta/mod.rs b/compiler/rustc_metadata/src/rmeta/mod.rs
index 5066dbbb9..a7ec2d790 100644
--- a/compiler/rustc_metadata/src/rmeta/mod.rs
+++ b/compiler/rustc_metadata/src/rmeta/mod.rs
@@ -9,7 +9,7 @@ use rustc_attr as attr;
use rustc_data_structures::svh::Svh;
use rustc_data_structures::sync::MetadataRef;
use rustc_hir as hir;
-use rustc_hir::def::{CtorKind, DefKind};
+use rustc_hir::def::{CtorKind, DefKind, DocLinkResMap};
use rustc_hir::def_id::{CrateNum, DefId, DefIndex, DefPathHash, StableCrateId};
use rustc_hir::definitions::DefKey;
use rustc_hir::lang_items::LangItem;
@@ -18,7 +18,7 @@ use rustc_index::vec::IndexVec;
use rustc_middle::metadata::ModChild;
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrs;
use rustc_middle::middle::exported_symbols::{ExportedSymbol, SymbolExportInfo};
-use rustc_middle::middle::resolve_lifetime::ObjectLifetimeDefault;
+use rustc_middle::middle::resolve_bound_vars::ObjectLifetimeDefault;
use rustc_middle::mir;
use rustc_middle::ty::fast_reject::SimplifiedType;
use rustc_middle::ty::query::Providers;
@@ -115,14 +115,16 @@ impl<T: ParameterizedOverTcx> ParameterizedOverTcx for LazyArray<T> {
type Value<'tcx> = LazyArray<T::Value<'tcx>>;
}
+impl<T> Default for LazyArray<T> {
+ fn default() -> LazyArray<T> {
+ LazyArray::from_position_and_num_elems(NonZeroUsize::new(1).unwrap(), 0)
+ }
+}
+
impl<T> LazyArray<T> {
fn from_position_and_num_elems(position: NonZeroUsize, num_elems: usize) -> LazyArray<T> {
LazyArray { position, num_elems, _marker: PhantomData }
}
-
- fn empty() -> LazyArray<T> {
- LazyArray::from_position_and_num_elems(NonZeroUsize::new(1).unwrap(), 0)
- }
}
/// A list of lazily-decoded values, with the added capability of random access.
@@ -185,9 +187,9 @@ enum LazyState {
Previous(NonZeroUsize),
}
-type SyntaxContextTable = LazyTable<u32, LazyValue<SyntaxContextData>>;
-type ExpnDataTable = LazyTable<ExpnIndex, LazyValue<ExpnData>>;
-type ExpnHashTable = LazyTable<ExpnIndex, LazyValue<ExpnHash>>;
+type SyntaxContextTable = LazyTable<u32, Option<LazyValue<SyntaxContextData>>>;
+type ExpnDataTable = LazyTable<ExpnIndex, Option<LazyValue<ExpnData>>>;
+type ExpnHashTable = LazyTable<ExpnIndex, Option<LazyValue<ExpnHash>>>;
#[derive(MetadataEncodable, MetadataDecodable)]
pub(crate) struct ProcMacroData {
@@ -253,7 +255,7 @@ pub(crate) struct CrateRoot {
def_path_hash_map: LazyValue<DefPathHashMapRef<'static>>,
- source_map: LazyTable<u32, LazyValue<rustc_span::SourceFile>>,
+ source_map: LazyTable<u32, Option<LazyValue<rustc_span::SourceFile>>>,
compiler_builtins: bool,
needs_allocator: bool,
@@ -315,21 +317,27 @@ pub(crate) struct IncoherentImpls {
/// Define `LazyTables` and `TableBuilders` at the same time.
macro_rules! define_tables {
- ($($name:ident: Table<$IDX:ty, $T:ty>),+ $(,)?) => {
+ (
+ - defaulted: $($name1:ident: Table<$IDX1:ty, $T1:ty>,)+
+ - optional: $($name2:ident: Table<$IDX2:ty, $T2:ty>,)+
+ ) => {
#[derive(MetadataEncodable, MetadataDecodable)]
pub(crate) struct LazyTables {
- $($name: LazyTable<$IDX, $T>),+
+ $($name1: LazyTable<$IDX1, $T1>,)+
+ $($name2: LazyTable<$IDX2, Option<$T2>>,)+
}
#[derive(Default)]
struct TableBuilders {
- $($name: TableBuilder<$IDX, $T>),+
+ $($name1: TableBuilder<$IDX1, $T1>,)+
+ $($name2: TableBuilder<$IDX2, Option<$T2>>,)+
}
impl TableBuilders {
fn encode(&self, buf: &mut FileEncoder) -> LazyTables {
LazyTables {
- $($name: self.$name.encode(buf)),+
+ $($name1: self.$name1.encode(buf),)+
+ $($name2: self.$name2.encode(buf),)+
}
}
}
@@ -337,9 +345,20 @@ macro_rules! define_tables {
}
define_tables! {
+- defaulted:
+ is_intrinsic: Table<DefIndex, bool>,
+ is_macro_rules: Table<DefIndex, bool>,
+ is_type_alias_impl_trait: Table<DefIndex, bool>,
+ attr_flags: Table<DefIndex, AttrFlags>,
+ def_path_hashes: Table<DefIndex, DefPathHash>,
+ explicit_item_bounds: Table<DefIndex, LazyArray<(ty::Predicate<'static>, Span)>>,
+ inferred_outlives_of: Table<DefIndex, LazyArray<(ty::Clause<'static>, Span)>>,
+ inherent_impls: Table<DefIndex, LazyArray<DefIndex>>,
+ associated_items_for_impl_trait_in_trait: Table<DefIndex, LazyArray<DefId>>,
+
+- optional:
attributes: Table<DefIndex, LazyArray<ast::Attribute>>,
children: Table<DefIndex, LazyArray<DefIndex>>,
-
opt_def_kind: Table<DefIndex, DefKind>,
visibility: Table<DefIndex, LazyValue<ty::Visibility<DefIndex>>>,
def_span: Table<DefIndex, LazyValue<Span>>,
@@ -348,29 +367,25 @@ define_tables! {
lookup_const_stability: Table<DefIndex, LazyValue<attr::ConstStability>>,
lookup_default_body_stability: Table<DefIndex, LazyValue<attr::DefaultBodyStability>>,
lookup_deprecation_entry: Table<DefIndex, LazyValue<attr::Deprecation>>,
- // As an optimization, a missing entry indicates an empty `&[]`.
- explicit_item_bounds: Table<DefIndex, LazyArray<(ty::Predicate<'static>, Span)>>,
explicit_predicates_of: Table<DefIndex, LazyValue<ty::GenericPredicates<'static>>>,
generics_of: Table<DefIndex, LazyValue<ty::Generics>>,
- // As an optimization, a missing entry indicates an empty `&[]`.
- inferred_outlives_of: Table<DefIndex, LazyArray<(ty::Clause<'static>, Span)>>,
super_predicates_of: Table<DefIndex, LazyValue<ty::GenericPredicates<'static>>>,
- type_of: Table<DefIndex, LazyValue<Ty<'static>>>,
+ type_of: Table<DefIndex, LazyValue<ty::EarlyBinder<Ty<'static>>>>,
variances_of: Table<DefIndex, LazyArray<ty::Variance>>,
- fn_sig: Table<DefIndex, LazyValue<ty::PolyFnSig<'static>>>,
+ fn_sig: Table<DefIndex, LazyValue<ty::EarlyBinder<ty::PolyFnSig<'static>>>>,
codegen_fn_attrs: Table<DefIndex, LazyValue<CodegenFnAttrs>>,
impl_trait_ref: Table<DefIndex, LazyValue<ty::EarlyBinder<ty::TraitRef<'static>>>>,
const_param_default: Table<DefIndex, LazyValue<ty::EarlyBinder<rustc_middle::ty::Const<'static>>>>,
object_lifetime_default: Table<DefIndex, LazyValue<ObjectLifetimeDefault>>,
optimized_mir: Table<DefIndex, LazyValue<mir::Body<'static>>>,
mir_for_ctfe: Table<DefIndex, LazyValue<mir::Body<'static>>>,
+ mir_generator_witnesses: Table<DefIndex, LazyValue<mir::GeneratorLayout<'static>>>,
promoted_mir: Table<DefIndex, LazyValue<IndexVec<mir::Promoted, mir::Body<'static>>>>,
// FIXME(compiler-errors): Why isn't this a LazyArray?
thir_abstract_const: Table<DefIndex, LazyValue<ty::Const<'static>>>,
impl_parent: Table<DefIndex, RawDefId>,
impl_polarity: Table<DefIndex, ty::ImplPolarity>,
constness: Table<DefIndex, hir::Constness>,
- is_intrinsic: Table<DefIndex, ()>,
impl_defaultness: Table<DefIndex, hir::Defaultness>,
// FIXME(eddyb) perhaps compute this on the fly if cheap enough?
coerce_unsized_info: Table<DefIndex, LazyValue<ty::adjustment::CoerceUnsizedInfo>>,
@@ -380,9 +395,7 @@ define_tables! {
fn_arg_names: Table<DefIndex, LazyArray<Ident>>,
generator_kind: Table<DefIndex, LazyValue<hir::GeneratorKind>>,
trait_def: Table<DefIndex, LazyValue<ty::TraitDef>>,
-
trait_item_def_id: Table<DefIndex, RawDefId>,
- inherent_impls: Table<DefIndex, LazyArray<DefIndex>>,
expn_that_defined: Table<DefIndex, LazyValue<ExpnId>>,
unused_generic_params: Table<DefIndex, LazyValue<UnusedGenericParams>>,
params_in_repr: Table<DefIndex, LazyValue<BitSet<u32>>>,
@@ -392,22 +405,17 @@ define_tables! {
// `DefPathTable` up front, since we may only ever use a few
// definitions from any given crate.
def_keys: Table<DefIndex, LazyValue<DefKey>>,
- def_path_hashes: Table<DefIndex, DefPathHash>,
proc_macro_quoted_spans: Table<usize, LazyValue<Span>>,
generator_diagnostic_data: Table<DefIndex, LazyValue<GeneratorDiagnosticData<'static>>>,
- may_have_doc_links: Table<DefIndex, ()>,
variant_data: Table<DefIndex, LazyValue<VariantData>>,
assoc_container: Table<DefIndex, ty::AssocItemContainer>,
- // Slot is full when macro is macro_rules.
- macro_rules: Table<DefIndex, ()>,
macro_definition: Table<DefIndex, LazyValue<ast::DelimArgs>>,
proc_macro: Table<DefIndex, MacroKind>,
module_reexports: Table<DefIndex, LazyArray<ModChild>>,
deduced_param_attrs: Table<DefIndex, LazyArray<DeducedParamAttrs>>,
- // Slot is full when opaque is TAIT.
- is_type_alias_impl_trait: Table<DefIndex, ()>,
-
trait_impl_trait_tys: Table<DefIndex, LazyValue<FxHashMap<DefId, Ty<'static>>>>,
+ doc_link_resolutions: Table<DefIndex, LazyValue<DocLinkResMap>>,
+ doc_link_traits_in_scope: Table<DefIndex, LazyArray<DefId>>,
}
#[derive(TyEncodable, TyDecodable)]
@@ -418,6 +426,13 @@ struct VariantData {
is_non_exhaustive: bool,
}
+bitflags::bitflags! {
+ #[derive(Default)]
+ pub struct AttrFlags: u8 {
+ const IS_DOC_HIDDEN = 1 << 0;
+ }
+}
+
// Tags used for encoding Spans:
const TAG_VALID_SPAN_LOCAL: u8 = 0;
const TAG_VALID_SPAN_FOREIGN: u8 = 1;
@@ -440,4 +455,5 @@ trivially_parameterized_over_tcx! {
IncoherentImpls,
CrateRoot,
CrateDep,
+ AttrFlags,
}
diff --git a/compiler/rustc_metadata/src/rmeta/table.rs b/compiler/rustc_metadata/src/rmeta/table.rs
index 716655c7f..b89d48ec1 100644
--- a/compiler/rustc_metadata/src/rmeta/table.rs
+++ b/compiler/rustc_metadata/src/rmeta/table.rs
@@ -10,18 +10,61 @@ use rustc_span::hygiene::MacroKind;
use std::marker::PhantomData;
use std::num::NonZeroUsize;
+pub(super) trait IsDefault: Default {
+ fn is_default(&self) -> bool;
+}
+
+impl<T> IsDefault for Option<T> {
+ fn is_default(&self) -> bool {
+ self.is_none()
+ }
+}
+
+impl IsDefault for AttrFlags {
+ fn is_default(&self) -> bool {
+ self.is_empty()
+ }
+}
+
+impl IsDefault for bool {
+ fn is_default(&self) -> bool {
+ !self
+ }
+}
+
+impl IsDefault for u32 {
+ fn is_default(&self) -> bool {
+ *self == 0
+ }
+}
+
+impl<T> IsDefault for LazyArray<T> {
+ fn is_default(&self) -> bool {
+ self.num_elems == 0
+ }
+}
+
+impl IsDefault for DefPathHash {
+ fn is_default(&self) -> bool {
+ self.0 == Fingerprint::ZERO
+ }
+}
+
/// Helper trait, for encoding to, and decoding from, a fixed number of bytes.
/// Used mainly for Lazy positions and lengths.
/// Unchecked invariant: `Self::default()` should encode as `[0; BYTE_LEN]`,
/// but this has no impact on safety.
-pub(super) trait FixedSizeEncoding: Default {
+pub(super) trait FixedSizeEncoding: IsDefault {
/// This should be `[u8; BYTE_LEN]`;
+ /// Cannot use an associated `const BYTE_LEN: usize` instead due to const eval limitations.
type ByteArray;
fn from_bytes(b: &Self::ByteArray) -> Self;
fn write_to_bytes(self, b: &mut Self::ByteArray);
}
+/// This implementation is not used generically, but for reading/writing
+/// concrete `u32` fields in `Lazy*` structures, which may be zero.
impl FixedSizeEncoding for u32 {
type ByteArray = [u8; 4];
@@ -57,7 +100,7 @@ macro_rules! fixed_size_enum {
fn write_to_bytes(self, b: &mut [u8;1]) {
use $ty::*;
b[0] = match self {
- None => 0,
+ None => unreachable!(),
$(Some($($pat)*) => 1 + ${index()},)*
}
}
@@ -93,7 +136,8 @@ fixed_size_enum! {
( Field )
( LifetimeParam )
( GlobalAsm )
- ( Impl )
+ ( Impl { of_trait: false } )
+ ( Impl { of_trait: true } )
( Closure )
( Generator )
( Static(ast::Mutability::Not) )
@@ -154,20 +198,18 @@ fixed_size_enum! {
}
// We directly encode `DefPathHash` because a `LazyValue` would incur a 25% cost.
-impl FixedSizeEncoding for Option<DefPathHash> {
+impl FixedSizeEncoding for DefPathHash {
type ByteArray = [u8; 16];
#[inline]
fn from_bytes(b: &[u8; 16]) -> Self {
- Some(DefPathHash(Fingerprint::from_le_bytes(*b)))
+ DefPathHash(Fingerprint::from_le_bytes(*b))
}
#[inline]
fn write_to_bytes(self, b: &mut [u8; 16]) {
- let Some(DefPathHash(fingerprint)) = self else {
- panic!("Trying to encode absent DefPathHash.")
- };
- *b = fingerprint.to_le_bytes();
+ debug_assert!(!self.is_default());
+ *b = self.0.to_le_bytes();
}
}
@@ -178,17 +220,17 @@ impl FixedSizeEncoding for Option<RawDefId> {
#[inline]
fn from_bytes(b: &[u8; 8]) -> Self {
let krate = u32::from_le_bytes(b[0..4].try_into().unwrap());
- let index = u32::from_le_bytes(b[4..8].try_into().unwrap());
if krate == 0 {
return None;
}
+ let index = u32::from_le_bytes(b[4..8].try_into().unwrap());
Some(RawDefId { krate: krate - 1, index })
}
#[inline]
fn write_to_bytes(self, b: &mut [u8; 8]) {
match self {
- None => *b = [0; 8],
+ None => unreachable!(),
Some(RawDefId { krate, index }) => {
// CrateNum is less than `CrateNum::MAX_AS_U32`.
debug_assert!(krate < u32::MAX);
@@ -199,17 +241,33 @@ impl FixedSizeEncoding for Option<RawDefId> {
}
}
-impl FixedSizeEncoding for Option<()> {
+impl FixedSizeEncoding for AttrFlags {
+ type ByteArray = [u8; 1];
+
+ #[inline]
+ fn from_bytes(b: &[u8; 1]) -> Self {
+ AttrFlags::from_bits_truncate(b[0])
+ }
+
+ #[inline]
+ fn write_to_bytes(self, b: &mut [u8; 1]) {
+ debug_assert!(!self.is_default());
+ b[0] = self.bits();
+ }
+}
+
+impl FixedSizeEncoding for bool {
type ByteArray = [u8; 1];
#[inline]
fn from_bytes(b: &[u8; 1]) -> Self {
- (b[0] != 0).then(|| ())
+ b[0] != 0
}
#[inline]
fn write_to_bytes(self, b: &mut [u8; 1]) {
- b[0] = self.is_some() as u8
+ debug_assert!(!self.is_default());
+ b[0] = self as u8
}
}
@@ -227,76 +285,115 @@ impl<T> FixedSizeEncoding for Option<LazyValue<T>> {
#[inline]
fn write_to_bytes(self, b: &mut [u8; 4]) {
- let position = self.map_or(0, |lazy| lazy.position.get());
+ match self {
+ None => unreachable!(),
+ Some(lazy) => {
+ let position = lazy.position.get();
+ let position: u32 = position.try_into().unwrap();
+ position.write_to_bytes(b)
+ }
+ }
+ }
+}
+
+impl<T> LazyArray<T> {
+ #[inline]
+ fn write_to_bytes_impl(self, b: &mut [u8; 8]) {
+ let ([position_bytes, meta_bytes],[])= b.as_chunks_mut::<4>() else { panic!() };
+
+ let position = self.position.get();
let position: u32 = position.try_into().unwrap();
- position.write_to_bytes(b)
+ position.write_to_bytes(position_bytes);
+
+ let len = self.num_elems;
+ let len: u32 = len.try_into().unwrap();
+ len.write_to_bytes(meta_bytes);
+ }
+
+ fn from_bytes_impl(position_bytes: &[u8; 4], meta_bytes: &[u8; 4]) -> Option<LazyArray<T>> {
+ let position = NonZeroUsize::new(u32::from_bytes(position_bytes) as usize)?;
+ let len = u32::from_bytes(meta_bytes) as usize;
+ Some(LazyArray::from_position_and_num_elems(position, len))
}
}
-impl<T> FixedSizeEncoding for Option<LazyArray<T>> {
+impl<T> FixedSizeEncoding for LazyArray<T> {
type ByteArray = [u8; 8];
#[inline]
fn from_bytes(b: &[u8; 8]) -> Self {
- let ([ref position_bytes, ref meta_bytes],[])= b.as_chunks::<4>() else { panic!() };
- let position = NonZeroUsize::new(u32::from_bytes(position_bytes) as usize)?;
- let len = u32::from_bytes(meta_bytes) as usize;
- Some(LazyArray::from_position_and_num_elems(position, len))
+ let ([position_bytes, meta_bytes],[])= b.as_chunks::<4>() else { panic!() };
+ if *meta_bytes == [0; 4] {
+ return Default::default();
+ }
+ LazyArray::from_bytes_impl(position_bytes, meta_bytes).unwrap()
}
#[inline]
fn write_to_bytes(self, b: &mut [u8; 8]) {
- let ([ref mut position_bytes, ref mut meta_bytes],[])= b.as_chunks_mut::<4>() else { panic!() };
+ assert!(!self.is_default());
+ self.write_to_bytes_impl(b)
+ }
+}
- let position = self.map_or(0, |lazy| lazy.position.get());
- let position: u32 = position.try_into().unwrap();
- position.write_to_bytes(position_bytes);
+impl<T> FixedSizeEncoding for Option<LazyArray<T>> {
+ type ByteArray = [u8; 8];
- let len = self.map_or(0, |lazy| lazy.num_elems);
- let len: u32 = len.try_into().unwrap();
- len.write_to_bytes(meta_bytes);
+ #[inline]
+ fn from_bytes(b: &[u8; 8]) -> Self {
+ let ([position_bytes, meta_bytes],[])= b.as_chunks::<4>() else { panic!() };
+ LazyArray::from_bytes_impl(position_bytes, meta_bytes)
+ }
+
+ #[inline]
+ fn write_to_bytes(self, b: &mut [u8; 8]) {
+ match self {
+ None => unreachable!(),
+ Some(lazy) => lazy.write_to_bytes_impl(b),
+ }
}
}
/// Helper for constructing a table's serialization (also see `Table`).
-pub(super) struct TableBuilder<I: Idx, T>
-where
- Option<T>: FixedSizeEncoding,
-{
- blocks: IndexVec<I, <Option<T> as FixedSizeEncoding>::ByteArray>,
+pub(super) struct TableBuilder<I: Idx, T: FixedSizeEncoding> {
+ blocks: IndexVec<I, T::ByteArray>,
_marker: PhantomData<T>,
}
-impl<I: Idx, T> Default for TableBuilder<I, T>
-where
- Option<T>: FixedSizeEncoding,
-{
+impl<I: Idx, T: FixedSizeEncoding> Default for TableBuilder<I, T> {
fn default() -> Self {
TableBuilder { blocks: Default::default(), _marker: PhantomData }
}
}
-impl<I: Idx, T> TableBuilder<I, T>
+impl<I: Idx, const N: usize, T> TableBuilder<I, Option<T>>
where
- Option<T>: FixedSizeEncoding,
+ Option<T>: FixedSizeEncoding<ByteArray = [u8; N]>,
{
- pub(crate) fn set<const N: usize>(&mut self, i: I, value: T)
- where
- Option<T>: FixedSizeEncoding<ByteArray = [u8; N]>,
- {
- // FIXME(eddyb) investigate more compact encodings for sparse tables.
- // On the PR @michaelwoerister mentioned:
- // > Space requirements could perhaps be optimized by using the HAMT `popcnt`
- // > trick (i.e. divide things into buckets of 32 or 64 items and then
- // > store bit-masks of which item in each bucket is actually serialized).
- self.blocks.ensure_contains_elem(i, || [0; N]);
- Some(value).write_to_bytes(&mut self.blocks[i]);
- }
-
- pub(crate) fn encode<const N: usize>(&self, buf: &mut FileEncoder) -> LazyTable<I, T>
- where
- Option<T>: FixedSizeEncoding<ByteArray = [u8; N]>,
- {
+ pub(crate) fn set_some(&mut self, i: I, value: T) {
+ self.set(i, Some(value))
+ }
+}
+
+impl<I: Idx, const N: usize, T: FixedSizeEncoding<ByteArray = [u8; N]>> TableBuilder<I, T> {
+ /// Sets the table value if it is not default.
+ /// ATTENTION: For optimization default values are simply ignored by this function, because
+ /// right now metadata tables never need to reset non-default values to default. If such need
+ /// arises in the future then a new method (e.g. `clear` or `reset`) will need to be introduced
+ /// for doing that explicitly.
+ pub(crate) fn set(&mut self, i: I, value: T) {
+ if !value.is_default() {
+ // FIXME(eddyb) investigate more compact encodings for sparse tables.
+ // On the PR @michaelwoerister mentioned:
+ // > Space requirements could perhaps be optimized by using the HAMT `popcnt`
+ // > trick (i.e. divide things into buckets of 32 or 64 items and then
+ // > store bit-masks of which item in each bucket is actually serialized).
+ self.blocks.ensure_contains_elem(i, || [0; N]);
+ value.write_to_bytes(&mut self.blocks[i]);
+ }
+ }
+
+ pub(crate) fn encode(&self, buf: &mut FileEncoder) -> LazyTable<I, T> {
let pos = buf.position();
for block in &self.blocks {
buf.emit_raw_bytes(block);
@@ -309,34 +406,24 @@ where
}
}
-impl<I: Idx, T: ParameterizedOverTcx> LazyTable<I, T>
+impl<I: Idx, const N: usize, T: FixedSizeEncoding<ByteArray = [u8; N]> + ParameterizedOverTcx>
+ LazyTable<I, T>
where
- Option<T>: FixedSizeEncoding,
+ for<'tcx> T::Value<'tcx>: FixedSizeEncoding<ByteArray = [u8; N]>,
{
/// Given the metadata, extract out the value at a particular index (if any).
#[inline(never)]
- pub(super) fn get<'a, 'tcx, M: Metadata<'a, 'tcx>, const N: usize>(
- &self,
- metadata: M,
- i: I,
- ) -> Option<T::Value<'tcx>>
- where
- Option<T::Value<'tcx>>: FixedSizeEncoding<ByteArray = [u8; N]>,
- {
+ pub(super) fn get<'a, 'tcx, M: Metadata<'a, 'tcx>>(&self, metadata: M, i: I) -> T::Value<'tcx> {
debug!("LazyTable::lookup: index={:?} len={:?}", i, self.encoded_size);
let start = self.position.get();
let bytes = &metadata.blob()[start..start + self.encoded_size];
let (bytes, []) = bytes.as_chunks::<N>() else { panic!() };
- let bytes = bytes.get(i.index())?;
- FixedSizeEncoding::from_bytes(bytes)
+ bytes.get(i.index()).map_or_else(Default::default, FixedSizeEncoding::from_bytes)
}
/// Size of the table in entries, including possible gaps.
- pub(super) fn size<const N: usize>(&self) -> usize
- where
- for<'tcx> Option<T::Value<'tcx>>: FixedSizeEncoding<ByteArray = [u8; N]>,
- {
+ pub(super) fn size(&self) -> usize {
self.encoded_size / N
}
}
diff --git a/compiler/rustc_middle/Cargo.toml b/compiler/rustc_middle/Cargo.toml
index 543bd56a2..a2b78cc29 100644
--- a/compiler/rustc_middle/Cargo.toml
+++ b/compiler/rustc_middle/Cargo.toml
@@ -34,7 +34,7 @@ rustc_span = { path = "../rustc_span" }
rustc_target = { path = "../rustc_target" }
rustc_type_ir = { path = "../rustc_type_ir" }
smallvec = { version = "1.8.1", features = ["union", "may_dangle"] }
-thin-vec = "0.2.9"
+thin-vec = "0.2.12"
tracing = "0.1"
[features]
diff --git a/compiler/rustc_error_messages/locales/en-US/middle.ftl b/compiler/rustc_middle/locales/en-US.ftl
index 4f4e5c6a2..4f4e5c6a2 100644
--- a/compiler/rustc_error_messages/locales/en-US/middle.ftl
+++ b/compiler/rustc_middle/locales/en-US.ftl
diff --git a/compiler/rustc_middle/src/arena.rs b/compiler/rustc_middle/src/arena.rs
index f816d6145..62e44b629 100644
--- a/compiler/rustc_middle/src/arena.rs
+++ b/compiler/rustc_middle/src/arena.rs
@@ -8,7 +8,7 @@
macro_rules! arena_types {
($macro:path) => (
$macro!([
- [] layout: rustc_target::abi::LayoutS<rustc_target::abi::VariantIdx>,
+ [] layout: rustc_target::abi::LayoutS,
[] fn_abi: rustc_target::abi::call::FnAbi<'tcx, rustc_middle::ty::Ty<'tcx>>,
// AdtDef are interned and compared by address
[decode] adt_def: rustc_middle::ty::AdtDefData,
@@ -35,6 +35,8 @@ macro_rules! arena_types {
rustc_data_structures::sync::Lrc<rustc_ast::Crate>,
)>,
[] output_filenames: std::sync::Arc<rustc_session::config::OutputFilenames>,
+ [] metadata_loader: rustc_data_structures::steal::Steal<Box<rustc_session::cstore::MetadataLoaderDyn>>,
+ [] crate_for_resolver: rustc_data_structures::steal::Steal<rustc_ast::ast::Crate>,
[] resolutions: rustc_middle::ty::ResolverGlobalCtxt,
[decode] unsafety_check_result: rustc_middle::mir::UnsafetyCheckResult,
[decode] code_region: rustc_middle::mir::coverage::CodeRegion,
@@ -105,13 +107,16 @@ macro_rules! arena_types {
// (during lowering) and the `librustc_middle` arena (for decoding MIR)
[decode] asm_template: rustc_ast::InlineAsmTemplatePiece,
[decode] used_trait_imports: rustc_data_structures::unord::UnordSet<rustc_hir::def_id::LocalDefId>,
- [decode] is_late_bound_map: rustc_data_structures::fx::FxIndexSet<rustc_hir::def_id::LocalDefId>,
+ [decode] is_late_bound_map: rustc_data_structures::fx::FxIndexSet<rustc_hir::ItemLocalId>,
[decode] impl_source: rustc_middle::traits::ImplSource<'tcx, ()>,
[] dep_kind: rustc_middle::dep_graph::DepKindStruct<'tcx>,
[decode] trait_impl_trait_tys: rustc_data_structures::fx::FxHashMap<rustc_hir::def_id::DefId, rustc_middle::ty::Ty<'tcx>>,
[] bit_set_u32: rustc_index::bit_set::BitSet<u32>,
+ [] external_constraints: rustc_middle::traits::solve::ExternalConstraintsData<'tcx>,
+ [decode] doc_link_resolutions: rustc_hir::def::DocLinkResMap,
+ [] closure_kind_origin: (rustc_span::Span, rustc_middle::hir::place::Place<'tcx>),
]);
)
}
diff --git a/compiler/rustc_middle/src/dep_graph/mod.rs b/compiler/rustc_middle/src/dep_graph/mod.rs
index 2e62bebc8..84510fe21 100644
--- a/compiler/rustc_middle/src/dep_graph/mod.rs
+++ b/compiler/rustc_middle/src/dep_graph/mod.rs
@@ -55,7 +55,7 @@ impl rustc_query_system::dep_graph::DepKind for DepKind {
ty::tls::with_context(|icx| {
let icx = ty::tls::ImplicitCtxt { task_deps, ..icx.clone() };
- ty::tls::enter_context(&icx, |_| op())
+ ty::tls::enter_context(&icx, op)
})
}
@@ -74,8 +74,8 @@ impl<'tcx> DepContext for TyCtxt<'tcx> {
type DepKind = DepKind;
#[inline]
- fn with_stable_hashing_context<R>(&self, f: impl FnOnce(StableHashingContext<'_>) -> R) -> R {
- TyCtxt::with_stable_hashing_context(*self, f)
+ fn with_stable_hashing_context<R>(self, f: impl FnOnce(StableHashingContext<'_>) -> R) -> R {
+ TyCtxt::with_stable_hashing_context(self, f)
}
#[inline]
diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs
index 9e63c2bd2..4b5bacac8 100644
--- a/compiler/rustc_middle/src/hir/map/mod.rs
+++ b/compiler/rustc_middle/src/hir/map/mod.rs
@@ -18,24 +18,30 @@ use rustc_span::Span;
use rustc_target::spec::abi::Abi;
#[inline]
-pub fn associated_body(node: Node<'_>) -> Option<BodyId> {
+pub fn associated_body(node: Node<'_>) -> Option<(LocalDefId, BodyId)> {
match node {
Node::Item(Item {
+ owner_id,
kind: ItemKind::Const(_, body) | ItemKind::Static(.., body) | ItemKind::Fn(.., body),
..
})
| Node::TraitItem(TraitItem {
+ owner_id,
kind:
TraitItemKind::Const(_, Some(body)) | TraitItemKind::Fn(_, TraitFn::Provided(body)),
..
})
| Node::ImplItem(ImplItem {
+ owner_id,
kind: ImplItemKind::Const(_, body) | ImplItemKind::Fn(_, body),
..
- })
- | Node::Expr(Expr { kind: ExprKind::Closure(Closure { body, .. }), .. }) => Some(*body),
+ }) => Some((owner_id.def_id, *body)),
+
+ Node::Expr(Expr { kind: ExprKind::Closure(Closure { def_id, body, .. }), .. }) => {
+ Some((*def_id, *body))
+ }
- Node::AnonConst(constant) => Some(constant.body),
+ Node::AnonConst(constant) => Some((constant.def_id, constant.body)),
_ => None,
}
@@ -43,7 +49,7 @@ pub fn associated_body(node: Node<'_>) -> Option<BodyId> {
fn is_body_owner(node: Node<'_>, hir_id: HirId) -> bool {
match associated_body(node) {
- Some(b) => b.hir_id == hir_id,
+ Some((_, b)) => b.hir_id == hir_id,
None => false,
}
}
@@ -154,10 +160,6 @@ impl<'hir> Map<'hir> {
self.tcx.definitions_untracked().def_key(def_id)
}
- pub fn def_path_from_hir_id(self, id: HirId) -> Option<DefPath> {
- self.opt_local_def_id(id).map(|def_id| self.def_path(def_id))
- }
-
pub fn def_path(self, def_id: LocalDefId) -> DefPath {
// Accessing the DefPath is ok, since it is part of DefPathHash.
self.tcx.definitions_untracked().def_path(def_id)
@@ -170,32 +172,6 @@ impl<'hir> Map<'hir> {
}
#[inline]
- #[track_caller]
- pub fn local_def_id(self, hir_id: HirId) -> LocalDefId {
- self.opt_local_def_id(hir_id).unwrap_or_else(|| {
- bug!(
- "local_def_id: no entry for `{:?}`, which has a map of `{:?}`",
- hir_id,
- self.find(hir_id)
- )
- })
- }
-
- #[inline]
- pub fn opt_local_def_id(self, hir_id: HirId) -> Option<LocalDefId> {
- if hir_id.local_id == ItemLocalId::new(0) {
- Some(hir_id.owner.def_id)
- } else {
- self.tcx
- .hir_owner_nodes(hir_id.owner)
- .as_owner()?
- .local_id_to_def_id
- .get(&hir_id.local_id)
- .copied()
- }
- }
-
- #[inline]
pub fn local_def_id_to_hir_id(self, def_id: LocalDefId) -> HirId {
self.tcx.local_def_id_to_hir_id(def_id)
}
@@ -227,7 +203,7 @@ impl<'hir> Map<'hir> {
ItemKind::Use(..) => DefKind::Use,
ItemKind::ForeignMod { .. } => DefKind::ForeignMod,
ItemKind::GlobalAsm(..) => DefKind::GlobalAsm,
- ItemKind::Impl { .. } => DefKind::Impl,
+ ItemKind::Impl(impl_) => DefKind::Impl { of_trait: impl_.of_trait.is_some() },
},
Node::ForeignItem(item) => match item.kind {
ForeignItemKind::Fn(..) => DefKind::Fn,
@@ -314,7 +290,7 @@ impl<'hir> Map<'hir> {
#[track_caller]
pub fn parent_id(self, hir_id: HirId) -> HirId {
self.opt_parent_id(hir_id)
- .unwrap_or_else(|| bug!("No parent for node {:?}", self.node_to_string(hir_id)))
+ .unwrap_or_else(|| bug!("No parent for node {}", self.node_to_string(hir_id)))
}
pub fn get_parent(self, hir_id: HirId) -> Node<'hir> {
@@ -410,8 +386,8 @@ impl<'hir> Map<'hir> {
#[track_caller]
pub fn enclosing_body_owner(self, hir_id: HirId) -> LocalDefId {
for (_, node) in self.parent_iter(hir_id) {
- if let Some(body) = associated_body(node) {
- return self.body_owner_def_id(body);
+ if let Some((def_id, _)) = associated_body(node) {
+ return def_id;
}
}
@@ -427,14 +403,17 @@ impl<'hir> Map<'hir> {
parent
}
- pub fn body_owner_def_id(self, id: BodyId) -> LocalDefId {
- self.local_def_id(self.body_owner(id))
+ pub fn body_owner_def_id(self, BodyId { hir_id }: BodyId) -> LocalDefId {
+ let parent = self.parent_id(hir_id);
+ associated_body(self.get(parent)).unwrap().0
}
/// Given a `LocalDefId`, returns the `BodyId` associated with it,
/// if the node is a body owner, otherwise returns `None`.
pub fn maybe_body_owned_by(self, id: LocalDefId) -> Option<BodyId> {
- self.find_by_def_id(id).and_then(associated_body)
+ let node = self.find_by_def_id(id)?;
+ let (_, body_id) = associated_body(node)?;
+ Some(body_id)
}
/// Given a body owner's id, returns the `BodyId` associated with it.
@@ -870,6 +849,13 @@ impl<'hir> Map<'hir> {
}
}
+ pub fn get_fn_output(self, def_id: LocalDefId) -> Option<&'hir FnRetTy<'hir>> {
+ match self.tcx.hir_owner(OwnerId { def_id }) {
+ Some(Owner { node, .. }) => node.fn_decl().map(|fn_decl| &fn_decl.output),
+ _ => None,
+ }
+ }
+
pub fn expect_variant(self, id: HirId) -> &'hir Variant<'hir> {
match self.find(id) {
Some(Node::Variant(variant)) => variant,
@@ -917,6 +903,11 @@ impl<'hir> Map<'hir> {
}
#[inline]
+ pub fn ident(self, id: HirId) -> Ident {
+ self.opt_ident(id).unwrap()
+ }
+
+ #[inline]
pub fn opt_name(self, id: HirId) -> Option<Symbol> {
self.opt_ident(id).map(|ident| ident.name)
}
@@ -1083,7 +1074,7 @@ impl<'hir> Map<'hir> {
}
pub fn span_if_local(self, id: DefId) -> Option<Span> {
- if id.is_local() { Some(self.tcx.def_span(id)) } else { None }
+ id.is_local().then(|| self.tcx.def_span(id))
}
pub fn res_span(self, res: Res) -> Option<Span> {
@@ -1212,12 +1203,10 @@ fn upstream_crates(tcx: TyCtxt<'_>) -> Vec<(StableCrateId, Svh)> {
}
fn hir_id_to_string(map: Map<'_>, id: HirId) -> String {
- let id_str = format!(" (hir_id={})", id);
-
let path_str = |def_id: LocalDefId| map.tcx.def_path_str(def_id.to_def_id());
let span_str = || map.tcx.sess.source_map().span_to_snippet(map.span(id)).unwrap_or_default();
- let node_str = |prefix| format!("{} {}{}", prefix, span_str(), id_str);
+ let node_str = |prefix| format!("{id} ({prefix} `{}`)", span_str());
match map.find(id) {
Some(Node::Item(item)) => {
@@ -1246,10 +1235,10 @@ fn hir_id_to_string(map: Map<'_>, id: HirId) -> String {
ItemKind::TraitAlias(..) => "trait alias",
ItemKind::Impl { .. } => "impl",
};
- format!("{} {}{}", item_str, path_str(item.owner_id.def_id), id_str)
+ format!("{id} ({item_str} {})", path_str(item.owner_id.def_id))
}
Some(Node::ForeignItem(item)) => {
- format!("foreign item {}{}", path_str(item.owner_id.def_id), id_str)
+ format!("{id} (foreign item {})", path_str(item.owner_id.def_id))
}
Some(Node::ImplItem(ii)) => {
let kind = match ii.kind {
@@ -1257,7 +1246,7 @@ fn hir_id_to_string(map: Map<'_>, id: HirId) -> String {
ImplItemKind::Fn(..) => "method",
ImplItemKind::Type(_) => "assoc type",
};
- format!("{} {} in {}{}", kind, ii.ident, path_str(ii.owner_id.def_id), id_str)
+ format!("{id} ({kind} `{}` in {})", ii.ident, path_str(ii.owner_id.def_id))
}
Some(Node::TraitItem(ti)) => {
let kind = match ti.kind {
@@ -1266,13 +1255,13 @@ fn hir_id_to_string(map: Map<'_>, id: HirId) -> String {
TraitItemKind::Type(..) => "assoc type",
};
- format!("{} {} in {}{}", kind, ti.ident, path_str(ti.owner_id.def_id), id_str)
+ format!("{id} ({kind} `{}` in {})", ti.ident, path_str(ti.owner_id.def_id))
}
Some(Node::Variant(ref variant)) => {
- format!("variant {} in {}{}", variant.ident, path_str(variant.def_id), id_str)
+ format!("{id} (variant `{}` in {})", variant.ident, path_str(variant.def_id))
}
Some(Node::Field(ref field)) => {
- format!("field {} in {}{}", field.ident, path_str(field.def_id), id_str)
+ format!("{id} (field `{}` in {})", field.ident, path_str(field.def_id))
}
Some(Node::AnonConst(_)) => node_str("const"),
Some(Node::Expr(_)) => node_str("expr"),
@@ -1290,16 +1279,15 @@ fn hir_id_to_string(map: Map<'_>, id: HirId) -> String {
Some(Node::Infer(_)) => node_str("infer"),
Some(Node::Local(_)) => node_str("local"),
Some(Node::Ctor(ctor)) => format!(
- "ctor {}{}",
+ "{id} (ctor {})",
ctor.ctor_def_id().map_or("<missing path>".into(), |def_id| path_str(def_id)),
- id_str
),
Some(Node::Lifetime(_)) => node_str("lifetime"),
Some(Node::GenericParam(ref param)) => {
- format!("generic_param {}{}", path_str(param.def_id), id_str)
+ format!("{id} (generic_param {})", path_str(param.def_id))
}
- Some(Node::Crate(..)) => String::from("root_crate"),
- None => format!("unknown node{}", id_str),
+ Some(Node::Crate(..)) => String::from("(root_crate)"),
+ None => format!("{id} (unknown node)"),
}
}
diff --git a/compiler/rustc_middle/src/hir/mod.rs b/compiler/rustc_middle/src/hir/mod.rs
index dedc65f4c..c9da711e5 100644
--- a/compiler/rustc_middle/src/hir/mod.rs
+++ b/compiler/rustc_middle/src/hir/mod.rs
@@ -64,13 +64,17 @@ impl ModuleItems {
self.foreign_items.iter().copied()
}
- pub fn definitions(&self) -> impl Iterator<Item = LocalDefId> + '_ {
+ pub fn owners(&self) -> impl Iterator<Item = OwnerId> + '_ {
self.items
.iter()
- .map(|id| id.owner_id.def_id)
- .chain(self.trait_items.iter().map(|id| id.owner_id.def_id))
- .chain(self.impl_items.iter().map(|id| id.owner_id.def_id))
- .chain(self.foreign_items.iter().map(|id| id.owner_id.def_id))
+ .map(|id| id.owner_id)
+ .chain(self.trait_items.iter().map(|id| id.owner_id))
+ .chain(self.impl_items.iter().map(|id| id.owner_id))
+ .chain(self.foreign_items.iter().map(|id| id.owner_id))
+ }
+
+ pub fn definitions(&self) -> impl Iterator<Item = LocalDefId> + '_ {
+ self.owners().map(|id| id.def_id)
}
pub fn par_items(&self, f: impl Fn(ItemId) + Send + Sync) {
@@ -104,7 +108,7 @@ impl<'tcx> TyCtxt<'tcx> {
self.impl_trait_ref(def_id)
.map(|t| t.subst_identity())
.map(ImplSubject::Trait)
- .unwrap_or_else(|| ImplSubject::Inherent(self.type_of(def_id)))
+ .unwrap_or_else(|| ImplSubject::Inherent(self.type_of(def_id).subst_identity()))
}
}
@@ -121,13 +125,13 @@ pub fn provide(providers: &mut Providers) {
let node = owner.node();
Some(Owner { node, hash_without_bodies: owner.nodes.hash_without_bodies })
};
- providers.local_def_id_to_hir_id = |tcx, id| {
+ providers.opt_local_def_id_to_hir_id = |tcx, id| {
let owner = tcx.hir_crate(()).owners[id].map(|_| ());
- match owner {
+ Some(match owner {
MaybeOwner::Owner(_) => HirId::make_owner(id),
MaybeOwner::Phantom => bug!("No HirId for {:?}", id),
MaybeOwner::NonOwner(hir_id) => hir_id,
- }
+ })
};
providers.hir_owner_nodes = |tcx, id| tcx.hir_crate(()).owners[id.def_id].map(|i| &i.nodes);
providers.hir_owner_parent = |tcx, id| {
@@ -173,6 +177,7 @@ pub fn provide(providers: &mut Providers) {
}
};
providers.opt_def_kind = |tcx, def_id| tcx.hir().opt_def_kind(def_id.expect_local());
+ providers.opt_rpitit_info = |_, _| None;
providers.all_local_trait_impls = |tcx, ()| &tcx.resolutions(()).trait_impls;
providers.expn_that_defined = |tcx, id| {
let id = id.expect_local();
diff --git a/compiler/rustc_middle/src/infer/canonical.rs b/compiler/rustc_middle/src/infer/canonical.rs
index 43583b572..7f8fc1774 100644
--- a/compiler/rustc_middle/src/infer/canonical.rs
+++ b/compiler/rustc_middle/src/infer/canonical.rs
@@ -25,10 +25,8 @@ use crate::infer::MemberConstraint;
use crate::mir::ConstraintCategory;
use crate::ty::subst::GenericArg;
use crate::ty::{self, BoundVar, List, Region, Ty, TyCtxt};
-use rustc_index::vec::IndexVec;
use rustc_macros::HashStable;
use smallvec::SmallVec;
-use std::iter;
use std::ops::Index;
/// A "canonicalized" type `V` is one where all free inference
@@ -44,12 +42,12 @@ pub struct Canonical<'tcx, V> {
pub type CanonicalVarInfos<'tcx> = &'tcx List<CanonicalVarInfo<'tcx>>;
-impl<'tcx> ty::TypeFoldable<'tcx> for CanonicalVarInfos<'tcx> {
- fn try_fold_with<F: ty::FallibleTypeFolder<'tcx>>(
+impl<'tcx> ty::TypeFoldable<TyCtxt<'tcx>> for CanonicalVarInfos<'tcx> {
+ fn try_fold_with<F: ty::FallibleTypeFolder<TyCtxt<'tcx>>>(
self,
folder: &mut F,
) -> Result<Self, F::Error> {
- ty::util::fold_list(self, folder, |tcx, v| tcx.intern_canonical_var_infos(v))
+ ty::util::fold_list(self, folder, |tcx, v| tcx.mk_canonical_var_infos(v))
}
}
@@ -62,23 +60,23 @@ impl<'tcx> ty::TypeFoldable<'tcx> for CanonicalVarInfos<'tcx> {
/// vectors with the original values that were replaced by canonical
/// variables. You will need to supply it later to instantiate the
/// canonicalized query response.
-#[derive(Clone, Debug, PartialEq, Eq, Hash, TyDecodable, TyEncodable)]
+#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, TyDecodable, TyEncodable)]
#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)]
pub struct CanonicalVarValues<'tcx> {
- pub var_values: IndexVec<BoundVar, GenericArg<'tcx>>,
+ pub var_values: ty::SubstsRef<'tcx>,
}
impl CanonicalVarValues<'_> {
pub fn is_identity(&self) -> bool {
- self.var_values.iter_enumerated().all(|(bv, arg)| match arg.unpack() {
+ self.var_values.iter().enumerate().all(|(bv, arg)| match arg.unpack() {
ty::GenericArgKind::Lifetime(r) => {
- matches!(*r, ty::ReLateBound(ty::INNERMOST, br) if br.var == bv)
+ matches!(*r, ty::ReLateBound(ty::INNERMOST, br) if br.var.as_usize() == bv)
}
ty::GenericArgKind::Type(ty) => {
- matches!(*ty.kind(), ty::Bound(ty::INNERMOST, bt) if bt.var == bv)
+ matches!(*ty.kind(), ty::Bound(ty::INNERMOST, bt) if bt.var.as_usize() == bv)
}
ty::GenericArgKind::Const(ct) => {
- matches!(ct.kind(), ty::ConstKind::Bound(ty::INNERMOST, bc) if bc == bv)
+ matches!(ct.kind(), ty::ConstKind::Bound(ty::INNERMOST, bc) if bc.as_usize() == bv)
}
})
}
@@ -125,6 +123,11 @@ impl<'tcx> CanonicalVarInfo<'tcx> {
self.kind.universe()
}
+ #[must_use]
+ pub fn with_updated_universe(self, ui: ty::UniverseIndex) -> CanonicalVarInfo<'tcx> {
+ CanonicalVarInfo { kind: self.kind.with_updated_universe(ui) }
+ }
+
pub fn is_existential(&self) -> bool {
match self.kind {
CanonicalVarKind::Ty(_) => true,
@@ -135,6 +138,28 @@ impl<'tcx> CanonicalVarInfo<'tcx> {
CanonicalVarKind::PlaceholderConst(_, _) => false,
}
}
+
+ pub fn is_region(&self) -> bool {
+ match self.kind {
+ CanonicalVarKind::Region(_) | CanonicalVarKind::PlaceholderRegion(_) => true,
+ CanonicalVarKind::Ty(_)
+ | CanonicalVarKind::PlaceholderTy(_)
+ | CanonicalVarKind::Const(_, _)
+ | CanonicalVarKind::PlaceholderConst(_, _) => false,
+ }
+ }
+
+ pub fn expect_anon_placeholder(self) -> u32 {
+ match self.kind {
+ CanonicalVarKind::Ty(_)
+ | CanonicalVarKind::Region(_)
+ | CanonicalVarKind::Const(_, _) => bug!("expected placeholder: {self:?}"),
+
+ CanonicalVarKind::PlaceholderRegion(placeholder) => placeholder.name.expect_anon(),
+ CanonicalVarKind::PlaceholderTy(placeholder) => placeholder.name.expect_anon(),
+ CanonicalVarKind::PlaceholderConst(placeholder, _) => placeholder.name.as_u32(),
+ }
+ }
}
/// Describes the "kind" of the canonical variable. This is a "kind"
@@ -179,6 +204,38 @@ impl<'tcx> CanonicalVarKind<'tcx> {
CanonicalVarKind::PlaceholderConst(placeholder, _) => placeholder.universe,
}
}
+
+ /// Replaces the universe of this canonical variable with `ui`.
+ ///
+ /// In case this is a float or int variable, this causes an ICE if
+ /// the updated universe is not the root.
+ pub fn with_updated_universe(self, ui: ty::UniverseIndex) -> CanonicalVarKind<'tcx> {
+ match self {
+ CanonicalVarKind::Ty(kind) => match kind {
+ CanonicalTyVarKind::General(_) => {
+ CanonicalVarKind::Ty(CanonicalTyVarKind::General(ui))
+ }
+ CanonicalTyVarKind::Int | CanonicalTyVarKind::Float => {
+ assert_eq!(ui, ty::UniverseIndex::ROOT);
+ CanonicalVarKind::Ty(kind)
+ }
+ },
+ CanonicalVarKind::PlaceholderTy(placeholder) => {
+ CanonicalVarKind::PlaceholderTy(ty::Placeholder { universe: ui, ..placeholder })
+ }
+ CanonicalVarKind::Region(_) => CanonicalVarKind::Region(ui),
+ CanonicalVarKind::PlaceholderRegion(placeholder) => {
+ CanonicalVarKind::PlaceholderRegion(ty::Placeholder { universe: ui, ..placeholder })
+ }
+ CanonicalVarKind::Const(_, ty) => CanonicalVarKind::Const(ui, ty),
+ CanonicalVarKind::PlaceholderConst(placeholder, ty) => {
+ CanonicalVarKind::PlaceholderConst(
+ ty::Placeholder { universe: ui, ..placeholder },
+ ty,
+ )
+ }
+ }
+ }
}
/// Rust actually has more than one category of type variables;
@@ -215,7 +272,8 @@ pub struct QueryResponse<'tcx, R> {
pub value: R,
}
-#[derive(Clone, Debug, Default, HashStable, TypeFoldable, TypeVisitable, Lift)]
+#[derive(Clone, Debug, Default, PartialEq, Eq, Hash)]
+#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)]
pub struct QueryRegionConstraints<'tcx> {
pub outlives: Vec<QueryOutlivesConstraint<'tcx>>,
pub member_constraints: Vec<MemberConstraint<'tcx>>,
@@ -326,10 +384,8 @@ impl<'tcx, V> Canonical<'tcx, V> {
}
}
-pub type QueryOutlivesConstraint<'tcx> = (
- ty::Binder<'tcx, ty::OutlivesPredicate<GenericArg<'tcx>, Region<'tcx>>>,
- ConstraintCategory<'tcx>,
-);
+pub type QueryOutlivesConstraint<'tcx> =
+ (ty::OutlivesPredicate<GenericArg<'tcx>, Region<'tcx>>, ConstraintCategory<'tcx>);
TrivialTypeTraversalAndLiftImpls! {
for <'tcx> {
@@ -339,57 +395,57 @@ TrivialTypeTraversalAndLiftImpls! {
}
impl<'tcx> CanonicalVarValues<'tcx> {
+ // Given a list of canonical variables, construct a set of values which are
+ // the identity response.
+ pub fn make_identity(
+ tcx: TyCtxt<'tcx>,
+ infos: CanonicalVarInfos<'tcx>,
+ ) -> CanonicalVarValues<'tcx> {
+ CanonicalVarValues {
+ var_values: tcx.mk_substs_from_iter(infos.iter().enumerate().map(
+ |(i, info)| -> ty::GenericArg<'tcx> {
+ match info.kind {
+ CanonicalVarKind::Ty(_) | CanonicalVarKind::PlaceholderTy(_) => {
+ tcx.mk_bound(ty::INNERMOST, ty::BoundVar::from_usize(i).into()).into()
+ }
+ CanonicalVarKind::Region(_) | CanonicalVarKind::PlaceholderRegion(_) => {
+ let br = ty::BoundRegion {
+ var: ty::BoundVar::from_usize(i),
+ kind: ty::BrAnon(i as u32, None),
+ };
+ tcx.mk_re_late_bound(ty::INNERMOST, br).into()
+ }
+ CanonicalVarKind::Const(_, ty)
+ | CanonicalVarKind::PlaceholderConst(_, ty) => tcx
+ .mk_const(
+ ty::ConstKind::Bound(ty::INNERMOST, ty::BoundVar::from_usize(i)),
+ ty,
+ )
+ .into(),
+ }
+ },
+ )),
+ }
+ }
+
/// Creates dummy var values which should not be used in a
/// canonical response.
pub fn dummy() -> CanonicalVarValues<'tcx> {
- CanonicalVarValues { var_values: Default::default() }
+ CanonicalVarValues { var_values: ty::List::empty() }
}
#[inline]
pub fn len(&self) -> usize {
self.var_values.len()
}
-
- /// Makes an identity substitution from this one: each bound var
- /// is matched to the same bound var, preserving the original kinds.
- /// For example, if we have:
- /// `self.var_values == [Type(u32), Lifetime('a), Type(u64)]`
- /// we'll return a substitution `subst` with:
- /// `subst.var_values == [Type(^0), Lifetime(^1), Type(^2)]`.
- pub fn make_identity(&self, tcx: TyCtxt<'tcx>) -> Self {
- use crate::ty::subst::GenericArgKind;
-
- CanonicalVarValues {
- var_values: iter::zip(&self.var_values, 0..)
- .map(|(kind, i)| match kind.unpack() {
- GenericArgKind::Type(..) => {
- tcx.mk_ty(ty::Bound(ty::INNERMOST, ty::BoundVar::from_u32(i).into())).into()
- }
- GenericArgKind::Lifetime(..) => {
- let br = ty::BoundRegion {
- var: ty::BoundVar::from_u32(i),
- kind: ty::BrAnon(i, None),
- };
- tcx.mk_region(ty::ReLateBound(ty::INNERMOST, br)).into()
- }
- GenericArgKind::Const(ct) => tcx
- .mk_const(
- ty::ConstKind::Bound(ty::INNERMOST, ty::BoundVar::from_u32(i)),
- ct.ty(),
- )
- .into(),
- })
- .collect(),
- }
- }
}
impl<'a, 'tcx> IntoIterator for &'a CanonicalVarValues<'tcx> {
type Item = GenericArg<'tcx>;
- type IntoIter = ::std::iter::Cloned<::std::slice::Iter<'a, GenericArg<'tcx>>>;
+ type IntoIter = ::std::iter::Copied<::std::slice::Iter<'a, GenericArg<'tcx>>>;
fn into_iter(self) -> Self::IntoIter {
- self.var_values.iter().cloned()
+ self.var_values.iter()
}
}
@@ -397,6 +453,6 @@ impl<'tcx> Index<BoundVar> for CanonicalVarValues<'tcx> {
type Output = GenericArg<'tcx>;
fn index(&self, value: BoundVar) -> &GenericArg<'tcx> {
- &self.var_values[value]
+ &self.var_values[value.as_usize()]
}
}
diff --git a/compiler/rustc_middle/src/infer/mod.rs b/compiler/rustc_middle/src/infer/mod.rs
index 38868c210..2db59f37f 100644
--- a/compiler/rustc_middle/src/infer/mod.rs
+++ b/compiler/rustc_middle/src/infer/mod.rs
@@ -12,7 +12,8 @@ use rustc_span::Span;
/// ```text
/// R0 member of [O1..On]
/// ```
-#[derive(Debug, Clone, HashStable, TypeFoldable, TypeVisitable, Lift)]
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)]
pub struct MemberConstraint<'tcx> {
/// The `DefId` and substs of the opaque type causing this constraint.
/// Used for error reporting.
diff --git a/compiler/rustc_middle/src/lib.rs b/compiler/rustc_middle/src/lib.rs
index 7e4063c2f..c33b9d84e 100644
--- a/compiler/rustc_middle/src/lib.rs
+++ b/compiler/rustc_middle/src/lib.rs
@@ -34,6 +34,7 @@
#![feature(get_mut_unchecked)]
#![feature(if_let_guard)]
#![feature(iter_from_generator)]
+#![feature(local_key_cell_methods)]
#![feature(negative_impls)]
#![feature(never_type)]
#![feature(extern_types)]
@@ -43,21 +44,21 @@
#![feature(min_specialization)]
#![feature(trusted_len)]
#![feature(type_alias_impl_trait)]
+#![feature(strict_provenance)]
#![feature(associated_type_bounds)]
#![feature(rustc_attrs)]
#![feature(control_flow_enum)]
-#![feature(associated_type_defaults)]
#![feature(trusted_step)]
#![feature(try_blocks)]
#![feature(try_reserve_kind)]
#![feature(nonzero_ops)]
-#![feature(unwrap_infallible)]
#![feature(decl_macro)]
#![feature(drain_filter)]
#![feature(intra_doc_pointers)]
#![feature(yeet_expr)]
#![feature(result_option_inspect)]
#![feature(const_option)]
+#![feature(trait_alias)]
#![recursion_limit = "512"]
#![allow(rustc::potential_query_instability)]
@@ -72,6 +73,9 @@ extern crate tracing;
#[macro_use]
extern crate smallvec;
+use rustc_errors::{DiagnosticMessage, SubdiagnosticMessage};
+use rustc_macros::fluent_messages;
+
#[cfg(test)]
mod tests;
@@ -104,3 +108,5 @@ pub mod util {
// Allows macros to refer to this crate as `::rustc_middle`
extern crate self as rustc_middle;
+
+fluent_messages! { "../locales/en-US.ftl" }
diff --git a/compiler/rustc_middle/src/macros.rs b/compiler/rustc_middle/src/macros.rs
index 250f3d079..a8d71ce03 100644
--- a/compiler/rustc_middle/src/macros.rs
+++ b/compiler/rustc_middle/src/macros.rs
@@ -69,8 +69,8 @@ macro_rules! CloneLiftImpls {
macro_rules! TrivialTypeTraversalImpls {
(for <$tcx:lifetime> { $($ty:ty,)+ }) => {
$(
- impl<$tcx> $crate::ty::fold::TypeFoldable<$tcx> for $ty {
- fn try_fold_with<F: $crate::ty::fold::FallibleTypeFolder<$tcx>>(
+ impl<$tcx> $crate::ty::fold::TypeFoldable<$crate::ty::TyCtxt<$tcx>> for $ty {
+ fn try_fold_with<F: $crate::ty::fold::FallibleTypeFolder<$crate::ty::TyCtxt<$tcx>>>(
self,
_: &mut F,
) -> ::std::result::Result<Self, F::Error> {
@@ -78,7 +78,7 @@ macro_rules! TrivialTypeTraversalImpls {
}
#[inline]
- fn fold_with<F: $crate::ty::fold::TypeFolder<$tcx>>(
+ fn fold_with<F: $crate::ty::fold::TypeFolder<$crate::ty::TyCtxt<$tcx>>>(
self,
_: &mut F,
) -> Self {
@@ -86,9 +86,9 @@ macro_rules! TrivialTypeTraversalImpls {
}
}
- impl<$tcx> $crate::ty::visit::TypeVisitable<$tcx> for $ty {
+ impl<$tcx> $crate::ty::visit::TypeVisitable<$crate::ty::TyCtxt<$tcx>> for $ty {
#[inline]
- fn visit_with<F: $crate::ty::visit::TypeVisitor<$tcx>>(
+ fn visit_with<F: $crate::ty::visit::TypeVisitor<$crate::ty::TyCtxt<$tcx>>>(
&self,
_: &mut F)
-> ::std::ops::ControlFlow<F::BreakTy>
@@ -101,7 +101,7 @@ macro_rules! TrivialTypeTraversalImpls {
($($ty:ty,)+) => {
TrivialTypeTraversalImpls! {
- for <'tcx> {
+ for<'tcx> {
$($ty,)+
}
}
@@ -115,145 +115,3 @@ macro_rules! TrivialTypeTraversalAndLiftImpls {
CloneLiftImpls! { $($t)* }
}
}
-
-#[macro_export]
-macro_rules! EnumTypeTraversalImpl {
- (impl<$($p:tt),*> TypeFoldable<$tcx:tt> for $s:path {
- $($variants:tt)*
- } $(where $($wc:tt)*)*) => {
- impl<$($p),*> $crate::ty::fold::TypeFoldable<$tcx> for $s
- $(where $($wc)*)*
- {
- fn try_fold_with<V: $crate::ty::fold::FallibleTypeFolder<$tcx>>(
- self,
- folder: &mut V,
- ) -> ::std::result::Result<Self, V::Error> {
- EnumTypeTraversalImpl!(@FoldVariants(self, folder) input($($variants)*) output())
- }
- }
- };
-
- (impl<$($p:tt),*> TypeVisitable<$tcx:tt> for $s:path {
- $($variants:tt)*
- } $(where $($wc:tt)*)*) => {
- impl<$($p),*> $crate::ty::visit::TypeVisitable<$tcx> for $s
- $(where $($wc)*)*
- {
- fn visit_with<V: $crate::ty::visit::TypeVisitor<$tcx>>(
- &self,
- visitor: &mut V,
- ) -> ::std::ops::ControlFlow<V::BreakTy> {
- EnumTypeTraversalImpl!(@VisitVariants(self, visitor) input($($variants)*) output())
- }
- }
- };
-
- (@FoldVariants($this:expr, $folder:expr) input() output($($output:tt)*)) => {
- Ok(match $this {
- $($output)*
- })
- };
-
- (@FoldVariants($this:expr, $folder:expr)
- input( ($variant:path) ( $($variant_arg:ident),* ) , $($input:tt)*)
- output( $($output:tt)*) ) => {
- EnumTypeTraversalImpl!(
- @FoldVariants($this, $folder)
- input($($input)*)
- output(
- $variant ( $($variant_arg),* ) => {
- $variant (
- $($crate::ty::fold::TypeFoldable::try_fold_with($variant_arg, $folder)?),*
- )
- }
- $($output)*
- )
- )
- };
-
- (@FoldVariants($this:expr, $folder:expr)
- input( ($variant:path) { $($variant_arg:ident),* $(,)? } , $($input:tt)*)
- output( $($output:tt)*) ) => {
- EnumTypeTraversalImpl!(
- @FoldVariants($this, $folder)
- input($($input)*)
- output(
- $variant { $($variant_arg),* } => {
- $variant {
- $($variant_arg: $crate::ty::fold::TypeFoldable::fold_with(
- $variant_arg, $folder
- )?),* }
- }
- $($output)*
- )
- )
- };
-
- (@FoldVariants($this:expr, $folder:expr)
- input( ($variant:path), $($input:tt)*)
- output( $($output:tt)*) ) => {
- EnumTypeTraversalImpl!(
- @FoldVariants($this, $folder)
- input($($input)*)
- output(
- $variant => { $variant }
- $($output)*
- )
- )
- };
-
- (@VisitVariants($this:expr, $visitor:expr) input() output($($output:tt)*)) => {
- match $this {
- $($output)*
- }
- };
-
- (@VisitVariants($this:expr, $visitor:expr)
- input( ($variant:path) ( $($variant_arg:ident),* ) , $($input:tt)*)
- output( $($output:tt)*) ) => {
- EnumTypeTraversalImpl!(
- @VisitVariants($this, $visitor)
- input($($input)*)
- output(
- $variant ( $($variant_arg),* ) => {
- $($crate::ty::visit::TypeVisitable::visit_with(
- $variant_arg, $visitor
- )?;)*
- ::std::ops::ControlFlow::Continue(())
- }
- $($output)*
- )
- )
- };
-
- (@VisitVariants($this:expr, $visitor:expr)
- input( ($variant:path) { $($variant_arg:ident),* $(,)? } , $($input:tt)*)
- output( $($output:tt)*) ) => {
- EnumTypeTraversalImpl!(
- @VisitVariants($this, $visitor)
- input($($input)*)
- output(
- $variant { $($variant_arg),* } => {
- $($crate::ty::visit::TypeVisitable::visit_with(
- $variant_arg, $visitor
- )?;)*
- ::std::ops::ControlFlow::Continue(())
- }
- $($output)*
- )
- )
- };
-
- (@VisitVariants($this:expr, $visitor:expr)
- input( ($variant:path), $($input:tt)*)
- output( $($output:tt)*) ) => {
- EnumTypeTraversalImpl!(
- @VisitVariants($this, $visitor)
- input($($input)*)
- output(
- $variant => { ::std::ops::ControlFlow::Continue(()) }
- $($output)*
- )
- )
- };
-}
diff --git a/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs b/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs
index bea884c85..c4601a1fb 100644
--- a/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs
+++ b/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs
@@ -91,7 +91,8 @@ bitflags! {
/// the MIR `InstrumentCoverage` pass and not added to the coverage map
/// during codegen.
const NO_COVERAGE = 1 << 15;
- /// `#[used(linker)]`: indicates that LLVM nor the linker can eliminate this function.
+ /// `#[used(linker)]`:
+ /// indicates that neither LLVM nor the linker will eliminate this function.
const USED_LINKER = 1 << 16;
/// `#[rustc_deallocator]`: a hint to LLVM that the function only deallocates memory.
const DEALLOCATOR = 1 << 17;
diff --git a/compiler/rustc_middle/src/middle/mod.rs b/compiler/rustc_middle/src/middle/mod.rs
index 8dc68b1f5..0b6774f1b 100644
--- a/compiler/rustc_middle/src/middle/mod.rs
+++ b/compiler/rustc_middle/src/middle/mod.rs
@@ -29,7 +29,7 @@ pub mod lib_features {
pub mod limits;
pub mod privacy;
pub mod region;
-pub mod resolve_lifetime;
+pub mod resolve_bound_vars;
pub mod stability;
pub fn provide(providers: &mut crate::ty::query::Providers) {
diff --git a/compiler/rustc_middle/src/middle/privacy.rs b/compiler/rustc_middle/src/middle/privacy.rs
index 0e18ba73d..893bf54b8 100644
--- a/compiler/rustc_middle/src/middle/privacy.rs
+++ b/compiler/rustc_middle/src/middle/privacy.rs
@@ -194,11 +194,6 @@ impl EffectiveVisibilities {
}
}
-pub trait IntoDefIdTree {
- type Tree: DefIdTree;
- fn tree(self) -> Self::Tree;
-}
-
impl<Id: Eq + Hash> EffectiveVisibilities<Id> {
pub fn iter(&self) -> impl Iterator<Item = (&Id, &EffectiveVisibility)> {
self.map.iter()
@@ -217,25 +212,21 @@ impl<Id: Eq + Hash> EffectiveVisibilities<Id> {
self.map.entry(id).or_insert_with(|| EffectiveVisibility::from_vis(lazy_private_vis()))
}
- pub fn update<T: IntoDefIdTree>(
+ pub fn update(
&mut self,
id: Id,
nominal_vis: Visibility,
- lazy_private_vis: impl FnOnce(T) -> (Visibility, T),
+ lazy_private_vis: impl FnOnce() -> Visibility,
inherited_effective_vis: EffectiveVisibility,
level: Level,
- mut into_tree: T,
+ tree: impl DefIdTree,
) -> bool {
let mut changed = false;
- let mut current_effective_vis = match self.map.get(&id).copied() {
- Some(eff_vis) => eff_vis,
- None => {
- let private_vis;
- (private_vis, into_tree) = lazy_private_vis(into_tree);
- EffectiveVisibility::from_vis(private_vis)
- }
- };
- let tree = into_tree.tree();
+ let mut current_effective_vis = self
+ .map
+ .get(&id)
+ .copied()
+ .unwrap_or_else(|| EffectiveVisibility::from_vis(lazy_private_vis()));
let mut inherited_effective_vis_at_prev_level = *inherited_effective_vis.at_level(level);
let mut calculated_effective_vis = inherited_effective_vis_at_prev_level;
diff --git a/compiler/rustc_middle/src/middle/resolve_lifetime.rs b/compiler/rustc_middle/src/middle/resolve_bound_vars.rs
index c3bf1c717..c59704fc0 100644
--- a/compiler/rustc_middle/src/middle/resolve_lifetime.rs
+++ b/compiler/rustc_middle/src/middle/resolve_bound_vars.rs
@@ -1,18 +1,20 @@
-//! Name resolution for lifetimes: type declarations.
+//! Name resolution for lifetimes and late-bound type and const variables: type declarations.
use crate::ty;
use rustc_data_structures::fx::FxHashMap;
+use rustc_errors::ErrorGuaranteed;
use rustc_hir::def_id::DefId;
use rustc_hir::{ItemLocalId, OwnerId};
use rustc_macros::HashStable;
#[derive(Clone, Copy, PartialEq, Eq, Hash, TyEncodable, TyDecodable, Debug, HashStable)]
-pub enum Region {
- Static,
- EarlyBound(/* lifetime decl */ DefId),
- LateBound(ty::DebruijnIndex, /* late-bound index */ u32, /* lifetime decl */ DefId),
+pub enum ResolvedArg {
+ StaticLifetime,
+ EarlyBound(/* decl */ DefId),
+ LateBound(ty::DebruijnIndex, /* late-bound index */ u32, /* decl */ DefId),
Free(DefId, /* lifetime decl */ DefId),
+ Error(ErrorGuaranteed),
}
/// A set containing, at most, one known element.
@@ -46,10 +48,10 @@ pub enum ObjectLifetimeDefault {
/// Maps the id of each lifetime reference to the lifetime decl
/// that it corresponds to.
#[derive(Default, HashStable, Debug)]
-pub struct ResolveLifetimes {
+pub struct ResolveBoundVars {
/// Maps from every use of a named (not anonymous) lifetime to a
/// `Region` describing how that region is bound
- pub defs: FxHashMap<OwnerId, FxHashMap<ItemLocalId, Region>>,
+ pub defs: FxHashMap<OwnerId, FxHashMap<ItemLocalId, ResolvedArg>>,
pub late_bound_vars: FxHashMap<OwnerId, FxHashMap<ItemLocalId, Vec<ty::BoundVariableKind>>>,
}
diff --git a/compiler/rustc_middle/src/middle/stability.rs b/compiler/rustc_middle/src/middle/stability.rs
index 0836f236e..354c84e22 100644
--- a/compiler/rustc_middle/src/middle/stability.rs
+++ b/compiler/rustc_middle/src/middle/stability.rs
@@ -255,7 +255,7 @@ fn late_report_deprecation(
let method_span = method_span.unwrap_or(span);
tcx.struct_span_lint_hir(lint, hir_id, method_span, message, |diag| {
if let hir::Node::Expr(_) = tcx.hir().get(hir_id) {
- let kind = tcx.def_kind(def_id).descr(def_id);
+ let kind = tcx.def_descr(def_id);
deprecation_suggestion(diag, kind, suggestion, method_span);
}
diag
@@ -392,7 +392,7 @@ impl<'tcx> TyCtxt<'tcx> {
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);
+ let def_kind = self.def_descr(def_id);
late_report_deprecation(
self,
diff --git a/compiler/rustc_middle/src/mir/basic_blocks.rs b/compiler/rustc_middle/src/mir/basic_blocks.rs
index 752cbdeae..b93871769 100644
--- a/compiler/rustc_middle/src/mir/basic_blocks.rs
+++ b/compiler/rustc_middle/src/mir/basic_blocks.rs
@@ -1,41 +1,46 @@
-use crate::mir::graph_cyclic_cache::GraphIsCyclicCache;
-use crate::mir::predecessors::{PredecessorCache, Predecessors};
-use crate::mir::switch_sources::{SwitchSourceCache, SwitchSources};
-use crate::mir::traversal::PostorderCache;
-use crate::mir::{BasicBlock, BasicBlockData, Successors, START_BLOCK};
+use crate::mir::traversal::Postorder;
+use crate::mir::{BasicBlock, BasicBlockData, Successors, Terminator, TerminatorKind, START_BLOCK};
+use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::graph;
use rustc_data_structures::graph::dominators::{dominators, Dominators};
+use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
+use rustc_data_structures::sync::OnceCell;
use rustc_index::vec::IndexVec;
+use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
+use smallvec::SmallVec;
#[derive(Clone, TyEncodable, TyDecodable, Debug, HashStable, TypeFoldable, TypeVisitable)]
pub struct BasicBlocks<'tcx> {
basic_blocks: IndexVec<BasicBlock, BasicBlockData<'tcx>>,
- predecessor_cache: PredecessorCache,
- switch_source_cache: SwitchSourceCache,
- is_cyclic: GraphIsCyclicCache,
- postorder_cache: PostorderCache,
+ cache: Cache,
+}
+
+// Typically 95%+ of basic blocks have 4 or fewer predecessors.
+pub type Predecessors = IndexVec<BasicBlock, SmallVec<[BasicBlock; 4]>>;
+
+pub type SwitchSources = FxHashMap<(BasicBlock, BasicBlock), SmallVec<[Option<u128>; 1]>>;
+
+#[derive(Clone, Default, Debug)]
+struct Cache {
+ predecessors: OnceCell<Predecessors>,
+ switch_sources: OnceCell<SwitchSources>,
+ is_cyclic: OnceCell<bool>,
+ postorder: OnceCell<Vec<BasicBlock>>,
}
impl<'tcx> BasicBlocks<'tcx> {
#[inline]
pub fn new(basic_blocks: IndexVec<BasicBlock, BasicBlockData<'tcx>>) -> Self {
- BasicBlocks {
- basic_blocks,
- predecessor_cache: PredecessorCache::new(),
- switch_source_cache: SwitchSourceCache::new(),
- is_cyclic: GraphIsCyclicCache::new(),
- postorder_cache: PostorderCache::new(),
- }
+ BasicBlocks { basic_blocks, cache: Cache::default() }
}
/// Returns true if control-flow graph contains a cycle reachable from the `START_BLOCK`.
#[inline]
pub fn is_cfg_cyclic(&self) -> bool {
- self.is_cyclic.is_cyclic(self)
+ *self.cache.is_cyclic.get_or_init(|| graph::is_cyclic(self))
}
- #[inline]
pub fn dominators(&self) -> Dominators<BasicBlock> {
dominators(&self)
}
@@ -43,20 +48,46 @@ impl<'tcx> BasicBlocks<'tcx> {
/// Returns predecessors for each basic block.
#[inline]
pub fn predecessors(&self) -> &Predecessors {
- self.predecessor_cache.compute(&self.basic_blocks)
+ self.cache.predecessors.get_or_init(|| {
+ let mut preds = IndexVec::from_elem(SmallVec::new(), &self.basic_blocks);
+ for (bb, data) in self.basic_blocks.iter_enumerated() {
+ if let Some(term) = &data.terminator {
+ for succ in term.successors() {
+ preds[succ].push(bb);
+ }
+ }
+ }
+ preds
+ })
}
/// Returns basic blocks in a postorder.
#[inline]
pub fn postorder(&self) -> &[BasicBlock] {
- self.postorder_cache.compute(&self.basic_blocks)
+ self.cache.postorder.get_or_init(|| {
+ Postorder::new(&self.basic_blocks, START_BLOCK).map(|(bb, _)| bb).collect()
+ })
}
/// `switch_sources()[&(target, switch)]` returns a list of switch
/// values that lead to a `target` block from a `switch` block.
#[inline]
pub fn switch_sources(&self) -> &SwitchSources {
- self.switch_source_cache.compute(&self.basic_blocks)
+ self.cache.switch_sources.get_or_init(|| {
+ let mut switch_sources: SwitchSources = FxHashMap::default();
+ for (bb, data) in self.basic_blocks.iter_enumerated() {
+ if let Some(Terminator {
+ kind: TerminatorKind::SwitchInt { targets, .. }, ..
+ }) = &data.terminator
+ {
+ for (value, target) in targets.iter() {
+ switch_sources.entry((target, bb)).or_default().push(Some(value));
+ }
+ switch_sources.entry((targets.otherwise(), bb)).or_default().push(None);
+ }
+ }
+ switch_sources
+ })
}
/// Returns mutable reference to basic blocks. Invalidates CFG cache.
@@ -88,10 +119,7 @@ impl<'tcx> BasicBlocks<'tcx> {
/// All other methods that allow you to mutate the basic blocks also call this method
/// themselves, thereby avoiding any risk of accidentally cache invalidation.
pub fn invalidate_cfg_cache(&mut self) {
- self.predecessor_cache.invalidate();
- self.switch_source_cache.invalidate();
- self.is_cyclic.invalidate();
- self.postorder_cache.invalidate();
+ self.cache = Cache::default();
}
}
@@ -145,3 +173,24 @@ impl<'tcx> graph::WithPredecessors for BasicBlocks<'tcx> {
self.predecessors()[node].iter().copied()
}
}
+
+TrivialTypeTraversalAndLiftImpls! {
+ Cache,
+}
+
+impl<S: Encoder> Encodable<S> for Cache {
+ #[inline]
+ fn encode(&self, _s: &mut S) {}
+}
+
+impl<D: Decoder> Decodable<D> for Cache {
+ #[inline]
+ fn decode(_: &mut D) -> Self {
+ Default::default()
+ }
+}
+
+impl<CTX> HashStable<CTX> for Cache {
+ #[inline]
+ fn hash_stable(&self, _: &mut CTX, _: &mut StableHasher) {}
+}
diff --git a/compiler/rustc_middle/src/mir/coverage.rs b/compiler/rustc_middle/src/mir/coverage.rs
index e7bb3ab0b..db24dae11 100644
--- a/compiler/rustc_middle/src/mir/coverage.rs
+++ b/compiler/rustc_middle/src/mir/coverage.rs
@@ -135,7 +135,10 @@ impl Debug for CoverageKind {
"Expression({:?}) = {} {} {}",
id.index(),
lhs.index(),
- if *op == Op::Add { "+" } else { "-" },
+ match op {
+ Op::Add => "+",
+ Op::Subtract => "-",
+ },
rhs.index(),
),
Unreachable => write!(fmt, "Unreachable"),
diff --git a/compiler/rustc_middle/src/mir/graph_cyclic_cache.rs b/compiler/rustc_middle/src/mir/graph_cyclic_cache.rs
deleted file mode 100644
index f97bf2883..000000000
--- a/compiler/rustc_middle/src/mir/graph_cyclic_cache.rs
+++ /dev/null
@@ -1,63 +0,0 @@
-use rustc_data_structures::graph::{
- self, DirectedGraph, WithNumNodes, WithStartNode, WithSuccessors,
-};
-use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
-use rustc_data_structures::sync::OnceCell;
-use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
-
-/// Helper type to cache the result of `graph::is_cyclic`.
-#[derive(Clone, Debug)]
-pub(super) struct GraphIsCyclicCache {
- cache: OnceCell<bool>,
-}
-
-impl GraphIsCyclicCache {
- #[inline]
- pub(super) fn new() -> Self {
- GraphIsCyclicCache { cache: OnceCell::new() }
- }
-
- pub(super) fn is_cyclic<G>(&self, graph: &G) -> bool
- where
- G: ?Sized + DirectedGraph + WithStartNode + WithSuccessors + WithNumNodes,
- {
- *self.cache.get_or_init(|| graph::is_cyclic(graph))
- }
-
- /// Invalidates the cache.
- #[inline]
- pub(super) fn invalidate(&mut self) {
- // Invalidating the cache requires mutating the MIR, which in turn requires a unique
- // reference (`&mut`) to the `mir::Body`. Because of this, we can assume that all
- // callers of `invalidate` have a unique reference to the MIR and thus to the
- // cache. This means we never need to do synchronization when `invalidate` is called,
- // we can simply reinitialize the `OnceCell`.
- self.cache = OnceCell::new();
- }
-}
-
-impl<S: Encoder> Encodable<S> for GraphIsCyclicCache {
- #[inline]
- fn encode(&self, s: &mut S) {
- Encodable::encode(&(), s);
- }
-}
-
-impl<D: Decoder> Decodable<D> for GraphIsCyclicCache {
- #[inline]
- fn decode(d: &mut D) -> Self {
- let () = Decodable::decode(d);
- Self::new()
- }
-}
-
-impl<CTX> HashStable<CTX> for GraphIsCyclicCache {
- #[inline]
- fn hash_stable(&self, _: &mut CTX, _: &mut StableHasher) {
- // do nothing
- }
-}
-
-TrivialTypeTraversalAndLiftImpls! {
- GraphIsCyclicCache,
-}
diff --git a/compiler/rustc_middle/src/mir/graphviz.rs b/compiler/rustc_middle/src/mir/graphviz.rs
index 5de56dad0..cf6d46e1e 100644
--- a/compiler/rustc_middle/src/mir/graphviz.rs
+++ b/compiler/rustc_middle/src/mir/graphviz.rs
@@ -110,7 +110,7 @@ fn write_graph_label<'tcx, W: std::fmt::Write>(
let decl = &body.local_decls[local];
write!(w, "let ")?;
- if decl.mutability == Mutability::Mut {
+ if decl.mutability.is_mut() {
write!(w, "mut ")?;
}
diff --git a/compiler/rustc_middle/src/mir/interpret/allocation.rs b/compiler/rustc_middle/src/mir/interpret/allocation.rs
index 221105ac4..48375ed30 100644
--- a/compiler/rustc_middle/src/mir/interpret/allocation.rs
+++ b/compiler/rustc_middle/src/mir/interpret/allocation.rs
@@ -8,7 +8,8 @@ mod tests;
use std::borrow::Cow;
use std::fmt;
use std::hash;
-use std::ops::Range;
+use std::hash::Hash;
+use std::ops::{Deref, DerefMut, Range};
use std::ptr;
use either::{Left, Right};
@@ -29,6 +30,39 @@ use provenance_map::*;
pub use init_mask::{InitChunk, InitChunkIter};
+/// Functionality required for the bytes of an `Allocation`.
+pub trait AllocBytes:
+ Clone + fmt::Debug + Eq + PartialEq + Hash + Deref<Target = [u8]> + DerefMut<Target = [u8]>
+{
+ /// Adjust the bytes to the specified alignment -- by default, this is a no-op.
+ fn adjust_to_align(self, _align: Align) -> Self;
+
+ /// Create an `AllocBytes` from a slice of `u8`.
+ fn from_bytes<'a>(slice: impl Into<Cow<'a, [u8]>>, _align: Align) -> Self;
+
+ /// Create a zeroed `AllocBytes` of the specified size and alignment;
+ /// call the callback error handler if there is an error in allocating the memory.
+ fn zeroed(size: Size, _align: Align) -> Option<Self>;
+}
+
+// Default `bytes` for `Allocation` is a `Box<[u8]>`.
+impl AllocBytes for Box<[u8]> {
+ fn adjust_to_align(self, _align: Align) -> Self {
+ self
+ }
+
+ fn from_bytes<'a>(slice: impl Into<Cow<'a, [u8]>>, _align: Align) -> Self {
+ Box::<[u8]>::from(slice.into())
+ }
+
+ fn zeroed(size: Size, _align: Align) -> Option<Self> {
+ let bytes = Box::<[u8]>::try_new_zeroed_slice(size.bytes_usize()).ok()?;
+ // SAFETY: the box was zero-allocated, which is a valid initial value for Box<[u8]>
+ let bytes = unsafe { bytes.assume_init() };
+ Some(bytes)
+ }
+}
+
/// This type represents an Allocation in the Miri/CTFE core engine.
///
/// Its public API is rather low-level, working directly with allocation offsets and a custom error
@@ -38,10 +72,10 @@ pub use init_mask::{InitChunk, InitChunkIter};
// hashed. (see the `Hash` impl below for more details), so the impl is not derived.
#[derive(Clone, Eq, PartialEq, TyEncodable, TyDecodable)]
#[derive(HashStable)]
-pub struct Allocation<Prov: Provenance = AllocId, Extra = ()> {
+pub struct Allocation<Prov: Provenance = AllocId, Extra = (), Bytes = Box<[u8]>> {
/// The actual bytes of the allocation.
/// Note that the bytes of a pointer represent the offset of the pointer.
- bytes: Box<[u8]>,
+ bytes: Bytes,
/// Maps from byte addresses to extra provenance data for each pointer.
/// Only the first byte of a pointer is inserted into the map; i.e.,
/// every entry in this map applies to `pointer_size` consecutive bytes starting
@@ -220,14 +254,27 @@ impl AllocRange {
}
// The constructors are all without extra; the extra gets added by a machine hook later.
-impl<Prov: Provenance> Allocation<Prov> {
+impl<Prov: Provenance, Bytes: AllocBytes> Allocation<Prov, (), Bytes> {
+ /// Creates an allocation from an existing `Bytes` value - this is needed for miri FFI support
+ pub fn from_raw_bytes(bytes: Bytes, align: Align, mutability: Mutability) -> Self {
+ let size = Size::from_bytes(bytes.len());
+ Self {
+ bytes,
+ provenance: ProvenanceMap::new(),
+ init_mask: InitMask::new(size, true),
+ align,
+ mutability,
+ extra: (),
+ }
+ }
+
/// Creates an allocation initialized by the given bytes
pub fn from_bytes<'a>(
slice: impl Into<Cow<'a, [u8]>>,
align: Align,
mutability: Mutability,
) -> Self {
- let bytes = Box::<[u8]>::from(slice.into());
+ let bytes = Bytes::from_bytes(slice, align);
let size = Size::from_bytes(bytes.len());
Self {
bytes,
@@ -248,7 +295,7 @@ impl<Prov: Provenance> Allocation<Prov> {
///
/// If `panic_on_fail` is true, this will never return `Err`.
pub fn uninit<'tcx>(size: Size, align: Align, panic_on_fail: bool) -> InterpResult<'tcx, Self> {
- let bytes = Box::<[u8]>::try_new_zeroed_slice(size.bytes_usize()).map_err(|_| {
+ let bytes = Bytes::zeroed(size, align).ok_or_else(|| {
// This results in an error that can happen non-deterministically, since the memory
// available to the compiler can change between runs. Normally queries are always
// deterministic. However, we can be non-deterministic here because all uses of const
@@ -262,8 +309,7 @@ impl<Prov: Provenance> Allocation<Prov> {
});
InterpError::ResourceExhaustion(ResourceExhaustionInfo::MemoryExhausted)
})?;
- // SAFETY: the box was zero-allocated, which is a valid initial value for Box<[u8]>
- let bytes = unsafe { bytes.assume_init() };
+
Ok(Allocation {
bytes,
provenance: ProvenanceMap::new(),
@@ -275,7 +321,7 @@ impl<Prov: Provenance> Allocation<Prov> {
}
}
-impl Allocation {
+impl<Bytes: AllocBytes> Allocation<AllocId, (), Bytes> {
/// Adjust allocation from the ones in tcx to a custom Machine instance
/// with a different Provenance and Extra type.
pub fn adjust_from_tcx<Prov: Provenance, Extra, Err>(
@@ -283,9 +329,11 @@ impl Allocation {
cx: &impl HasDataLayout,
extra: Extra,
mut adjust_ptr: impl FnMut(Pointer<AllocId>) -> Result<Pointer<Prov>, Err>,
- ) -> Result<Allocation<Prov, Extra>, Err> {
- // Compute new pointer provenance, which also adjusts the bytes.
- let mut bytes = self.bytes;
+ ) -> Result<Allocation<Prov, Extra, Bytes>, Err> {
+ // Compute new pointer provenance, which also adjusts the bytes, and realign the pointer if
+ // necessary.
+ let mut bytes = self.bytes.adjust_to_align(self.align);
+
let mut new_provenance = Vec::with_capacity(self.provenance.ptrs().len());
let ptr_size = cx.data_layout().pointer_size.bytes_usize();
let endian = cx.data_layout().endian;
@@ -311,7 +359,7 @@ impl Allocation {
}
/// Raw accessors. Provide access to otherwise private bytes.
-impl<Prov: Provenance, Extra> Allocation<Prov, Extra> {
+impl<Prov: Provenance, Extra, Bytes: AllocBytes> Allocation<Prov, Extra, Bytes> {
pub fn len(&self) -> usize {
self.bytes.len()
}
@@ -340,7 +388,11 @@ impl<Prov: Provenance, Extra> Allocation<Prov, Extra> {
}
/// Byte accessors.
-impl<Prov: Provenance, Extra> Allocation<Prov, Extra> {
+impl<Prov: Provenance, Extra, Bytes: AllocBytes> Allocation<Prov, Extra, Bytes> {
+ pub fn base_addr(&self) -> *const u8 {
+ self.bytes.as_ptr()
+ }
+
/// This is the entirely abstraction-violating way to just grab the raw bytes without
/// caring about provenance or initialization.
///
@@ -412,7 +464,7 @@ impl<Prov: Provenance, Extra> Allocation<Prov, Extra> {
}
/// Reading and writing.
-impl<Prov: Provenance, Extra> Allocation<Prov, Extra> {
+impl<Prov: Provenance, Extra, Bytes: AllocBytes> Allocation<Prov, Extra, Bytes> {
/// Sets the init bit for the given range.
fn mark_init(&mut self, range: AllocRange, is_init: bool) {
if range.size.bytes() == 0 {
diff --git a/compiler/rustc_middle/src/mir/interpret/error.rs b/compiler/rustc_middle/src/mir/interpret/error.rs
index bd9cd53e1..c5137cf06 100644
--- a/compiler/rustc_middle/src/mir/interpret/error.rs
+++ b/compiler/rustc_middle/src/mir/interpret/error.rs
@@ -323,7 +323,7 @@ impl fmt::Display for UndefinedBehaviorInfo {
write!(
f,
"{msg}{pointer} is a dangling pointer (it has no provenance)",
- pointer = Pointer::<Option<AllocId>>::from_addr(*i),
+ pointer = Pointer::<Option<AllocId>>::from_addr_invalid(*i),
)
}
AlignmentCheckFailed { required, has } => write!(
@@ -430,8 +430,10 @@ pub enum ResourceExhaustionInfo {
///
/// The exact limit is set by the `const_eval_limit` attribute.
StepLimitReached,
- /// There is not enough memory to perform an allocation.
+ /// There is not enough memory (on the host) to perform an allocation.
MemoryExhausted,
+ /// The address space (of the target) is full.
+ AddressSpaceFull,
}
impl fmt::Display for ResourceExhaustionInfo {
@@ -447,6 +449,9 @@ impl fmt::Display for ResourceExhaustionInfo {
MemoryExhausted => {
write!(f, "tried to allocate more memory than available to compiler")
}
+ AddressSpaceFull => {
+ write!(f, "there are no more free addresses in the address space")
+ }
}
}
}
diff --git a/compiler/rustc_middle/src/mir/interpret/mod.rs b/compiler/rustc_middle/src/mir/interpret/mod.rs
index 5f425a287..1766d7a66 100644
--- a/compiler/rustc_middle/src/mir/interpret/mod.rs
+++ b/compiler/rustc_middle/src/mir/interpret/mod.rs
@@ -110,7 +110,7 @@ use rustc_hir::def_id::DefId;
use rustc_macros::HashStable;
use rustc_middle::ty::print::with_no_trimmed_paths;
use rustc_serialize::{Decodable, Encodable};
-use rustc_target::abi::Endian;
+use rustc_target::abi::{AddressSpace, Endian, HasDataLayout};
use crate::mir;
use crate::ty::codec::{TyDecoder, TyEncoder};
@@ -127,8 +127,8 @@ pub use self::error::{
pub use self::value::{get_slice_bytes, ConstAlloc, ConstValue, Scalar};
pub use self::allocation::{
- alloc_range, AllocError, AllocRange, AllocResult, Allocation, ConstAllocation, InitChunk,
- InitChunkIter,
+ alloc_range, AllocBytes, AllocError, AllocRange, AllocResult, Allocation, ConstAllocation,
+ InitChunk, InitChunkIter,
};
pub use self::pointer::{Pointer, PointerArithmetic, Provenance};
@@ -438,6 +438,17 @@ impl<'tcx> GlobalAlloc<'tcx> {
_ => bug!("expected vtable, got {:?}", self),
}
}
+
+ /// The address space that this `GlobalAlloc` should be placed in.
+ #[inline]
+ pub fn address_space(&self, cx: &impl HasDataLayout) -> AddressSpace {
+ match self {
+ GlobalAlloc::Function(..) => cx.data_layout().instruction_address_space,
+ GlobalAlloc::Static(..) | GlobalAlloc::Memory(..) | GlobalAlloc::VTable(..) => {
+ AddressSpace::DATA
+ }
+ }
+ }
}
pub(crate) struct AllocMap<'tcx> {
diff --git a/compiler/rustc_middle/src/mir/interpret/pointer.rs b/compiler/rustc_middle/src/mir/interpret/pointer.rs
index b08309910..60927eed8 100644
--- a/compiler/rustc_middle/src/mir/interpret/pointer.rs
+++ b/compiler/rustc_middle/src/mir/interpret/pointer.rs
@@ -19,29 +19,29 @@ pub trait PointerArithmetic: HasDataLayout {
#[inline(always)]
fn max_size_of_val(&self) -> Size {
- Size::from_bytes(self.machine_isize_max())
+ Size::from_bytes(self.target_isize_max())
}
#[inline]
- fn machine_usize_max(&self) -> u64 {
+ fn target_usize_max(&self) -> u64 {
self.pointer_size().unsigned_int_max().try_into().unwrap()
}
#[inline]
- fn machine_isize_min(&self) -> i64 {
+ fn target_isize_min(&self) -> i64 {
self.pointer_size().signed_int_min().try_into().unwrap()
}
#[inline]
- fn machine_isize_max(&self) -> i64 {
+ fn target_isize_max(&self) -> i64 {
self.pointer_size().signed_int_max().try_into().unwrap()
}
#[inline]
- fn machine_usize_to_isize(&self, val: u64) -> i64 {
+ fn target_usize_to_isize(&self, val: u64) -> i64 {
let val = val as i64;
// Now wrap-around into the machine_isize range.
- if val > self.machine_isize_max() {
+ if val > self.target_isize_max() {
// This can only happen if the ptr size is < 64, so we know max_usize_plus_1 fits into
// i64.
debug_assert!(self.pointer_size().bits() < 64);
@@ -76,11 +76,11 @@ pub trait PointerArithmetic: HasDataLayout {
let n = i.unsigned_abs();
if i >= 0 {
let (val, over) = self.overflowing_offset(val, n);
- (val, over || i > self.machine_isize_max())
+ (val, over || i > self.target_isize_max())
} else {
let res = val.overflowing_sub(n);
let (val, over) = self.truncate_to_ptr(res);
- (val, over || i < self.machine_isize_min())
+ (val, over || i < self.target_isize_min())
}
}
@@ -251,14 +251,16 @@ impl<Prov> Pointer<Option<Prov>> {
}
impl<Prov> Pointer<Option<Prov>> {
+ /// Creates a pointer to the given address, with invalid provenance (i.e., cannot be used for
+ /// any memory access).
#[inline(always)]
- pub fn from_addr(addr: u64) -> Self {
+ pub fn from_addr_invalid(addr: u64) -> Self {
Pointer { provenance: None, offset: Size::from_bytes(addr) }
}
#[inline(always)]
pub fn null() -> Self {
- Pointer::from_addr(0)
+ Pointer::from_addr_invalid(0)
}
}
diff --git a/compiler/rustc_middle/src/mir/interpret/queries.rs b/compiler/rustc_middle/src/mir/interpret/queries.rs
index b6c6e9d55..856d821a5 100644
--- a/compiler/rustc_middle/src/mir/interpret/queries.rs
+++ b/compiler/rustc_middle/src/mir/interpret/queries.rs
@@ -2,7 +2,7 @@ use super::{ErrorHandled, EvalToConstValueResult, EvalToValTreeResult, GlobalId}
use crate::mir;
use crate::ty::subst::InternalSubsts;
-use crate::ty::visit::TypeVisitable;
+use crate::ty::visit::TypeVisitableExt;
use crate::ty::{self, query::TyCtxtAt, query::TyCtxtEnsure, TyCtxt};
use rustc_hir::def::DefKind;
use rustc_hir::def_id::DefId;
diff --git a/compiler/rustc_middle/src/mir/interpret/value.rs b/compiler/rustc_middle/src/mir/interpret/value.rs
index 88fb14eb3..36dbbe4bf 100644
--- a/compiler/rustc_middle/src/mir/interpret/value.rs
+++ b/compiler/rustc_middle/src/mir/interpret/value.rs
@@ -75,8 +75,8 @@ impl<'tcx> ConstValue<'tcx> {
self.try_to_scalar_int()?.try_into().ok()
}
- pub fn try_to_machine_usize(&self, tcx: TyCtxt<'tcx>) -> Option<u64> {
- self.try_to_scalar_int()?.try_to_machine_usize(tcx).ok()
+ pub fn try_to_target_usize(&self, tcx: TyCtxt<'tcx>) -> Option<u64> {
+ self.try_to_scalar_int()?.try_to_target_usize(tcx).ok()
}
pub fn try_to_bits_for_ty(
@@ -97,8 +97,8 @@ impl<'tcx> ConstValue<'tcx> {
ConstValue::Scalar(Scalar::from_u64(i))
}
- pub fn from_machine_usize(i: u64, cx: &impl HasDataLayout) -> Self {
- ConstValue::Scalar(Scalar::from_machine_usize(i, cx))
+ pub fn from_target_usize(i: u64, cx: &impl HasDataLayout) -> Self {
+ ConstValue::Scalar(Scalar::from_target_usize(i, cx))
}
}
@@ -241,7 +241,7 @@ impl<Prov> Scalar<Prov> {
}
#[inline]
- pub fn from_machine_usize(i: u64, cx: &impl HasDataLayout) -> Self {
+ pub fn from_target_usize(i: u64, cx: &impl HasDataLayout) -> Self {
Self::from_uint(i, cx.data_layout().pointer_size)
}
@@ -268,7 +268,7 @@ impl<Prov> Scalar<Prov> {
}
#[inline]
- pub fn from_machine_isize(i: i64, cx: &impl HasDataLayout) -> Self {
+ pub fn from_target_isize(i: i64, cx: &impl HasDataLayout) -> Self {
Self::from_int(i, cx.data_layout().pointer_size)
}
@@ -322,7 +322,7 @@ impl<'tcx, Prov: Provenance> Scalar<Prov> {
Right(ptr) => Ok(ptr.into()),
Left(bits) => {
let addr = u64::try_from(bits).unwrap();
- Ok(Pointer::from_addr(addr))
+ Ok(Pointer::from_addr_invalid(addr))
}
}
}
@@ -429,7 +429,7 @@ impl<'tcx, Prov: Provenance> Scalar<Prov> {
/// Converts the scalar to produce a machine-pointer-sized unsigned integer.
/// Fails if the scalar is a pointer.
- pub fn to_machine_usize(self, cx: &impl HasDataLayout) -> InterpResult<'tcx, u64> {
+ pub fn to_target_usize(self, cx: &impl HasDataLayout) -> InterpResult<'tcx, u64> {
let b = self.to_uint(cx.data_layout().pointer_size)?;
Ok(u64::try_from(b).unwrap())
}
@@ -469,7 +469,7 @@ impl<'tcx, Prov: Provenance> Scalar<Prov> {
/// Converts the scalar to produce a machine-pointer-sized signed integer.
/// Fails if the scalar is a pointer.
- pub fn to_machine_isize(self, cx: &impl HasDataLayout) -> InterpResult<'tcx, i64> {
+ pub fn to_target_isize(self, cx: &impl HasDataLayout) -> InterpResult<'tcx, i64> {
let b = self.to_int(cx.data_layout().pointer_size)?;
Ok(i64::try_from(b).unwrap())
}
diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs
index e52b243ec..99cdb769d 100644
--- a/compiler/rustc_middle/src/mir/mod.rs
+++ b/compiler/rustc_middle/src/mir/mod.rs
@@ -9,7 +9,7 @@ use crate::mir::visit::MirVisitable;
use crate::ty::codec::{TyDecoder, TyEncoder};
use crate::ty::fold::{FallibleTypeFolder, TypeFoldable};
use crate::ty::print::{FmtPrinter, Printer};
-use crate::ty::visit::{TypeVisitable, TypeVisitor};
+use crate::ty::visit::{TypeVisitable, TypeVisitableExt, TypeVisitor};
use crate::ty::{self, DefIdTree, List, Ty, TyCtxt};
use crate::ty::{AdtDef, InstanceDef, ScalarInt, UserTypeAnnotationIndex};
use crate::ty::{GenericArg, InternalSubsts, SubstsRef};
@@ -27,7 +27,6 @@ use polonius_engine::Atom;
pub use rustc_ast::Mutability;
use rustc_data_structures::fx::FxHashSet;
use rustc_data_structures::graph::dominators::Dominators;
-use rustc_index::bit_set::BitMatrix;
use rustc_index::vec::{Idx, IndexVec};
use rustc_serialize::{Decodable, Encodable};
use rustc_span::symbol::Symbol;
@@ -47,25 +46,21 @@ mod basic_blocks;
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;
mod syntax;
pub use syntax::*;
-mod switch_sources;
pub mod tcx;
pub mod terminator;
pub use terminator::*;
pub mod traversal;
mod type_foldable;
-mod type_visitable;
pub mod visit;
pub use self::generic_graph::graphviz_safe_def_name;
@@ -419,11 +414,7 @@ impl<'tcx> Body<'tcx> {
(self.arg_count + 1..self.local_decls.len()).filter_map(move |index| {
let local = Local::new(index);
let decl = &self.local_decls[local];
- if decl.is_user_variable() && decl.mutability == Mutability::Mut {
- Some(local)
- } else {
- None
- }
+ (decl.is_user_variable() && decl.mutability.is_mut()).then_some(local)
})
}
@@ -712,7 +703,11 @@ pub enum BindingForm<'tcx> {
RefForGuard,
}
-TrivialTypeTraversalAndLiftImpls! { BindingForm<'tcx>, }
+TrivialTypeTraversalAndLiftImpls! {
+ for<'tcx> {
+ BindingForm<'tcx>,
+ }
+}
mod binding_form_impl {
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
@@ -905,6 +900,8 @@ pub enum LocalInfo<'tcx> {
AggregateTemp,
/// A temporary created during the pass `Derefer` to avoid it's retagging
DerefTemp,
+ /// A temporary created for borrow checking.
+ FakeBorrow,
}
impl<'tcx> LocalDecl<'tcx> {
@@ -1464,6 +1461,7 @@ impl Debug for Statement<'_> {
}
Coverage(box ref coverage) => write!(fmt, "Coverage::{:?}", coverage.kind),
Intrinsic(box ref intrinsic) => write!(fmt, "{intrinsic}"),
+ ConstEvalCounter => write!(fmt, "ConstEvalCounter"),
Nop => write!(fmt, "nop"),
}
}
@@ -1622,7 +1620,7 @@ impl<'tcx> Place<'tcx> {
&v
};
- Place { local: self.local, projection: tcx.intern_place_elems(new_projections) }
+ Place { local: self.local, projection: tcx.mk_place_elems(new_projections) }
}
}
@@ -1644,6 +1642,14 @@ impl<'tcx> PlaceRef<'tcx> {
}
}
+ /// Returns `true` if this `Place` contains a `Deref` projection.
+ ///
+ /// If `Place::is_indirect` returns false, the caller knows that the `Place` refers to the
+ /// same region of memory as its base.
+ pub fn is_indirect(&self) -> bool {
+ self.projection.iter().any(|elem| elem.is_indirect())
+ }
+
/// If MirPhase >= Derefered and if projection contains Deref,
/// It's guaranteed to be in the first place
pub fn has_deref(&self) -> bool {
@@ -2102,10 +2108,7 @@ impl<'tcx> Debug for Rvalue<'tcx> {
AggregateKind::Closure(def_id, substs) => ty::tls::with(|tcx| {
let name = if tcx.sess.opts.unstable_opts.span_free_formats {
let substs = tcx.lift(substs).unwrap();
- format!(
- "[closure@{}]",
- tcx.def_path_str_with_substs(def_id.to_def_id(), substs),
- )
+ format!("[closure@{}]", tcx.def_path_str_with_substs(def_id, substs),)
} else {
let span = tcx.def_span(def_id);
format!(
@@ -2116,11 +2119,17 @@ impl<'tcx> Debug for Rvalue<'tcx> {
let mut struct_fmt = fmt.debug_struct(&name);
// FIXME(project-rfc-2229#48): This should be a list of capture names/places
- if let Some(upvars) = tcx.upvars_mentioned(def_id) {
+ if let Some(def_id) = def_id.as_local()
+ && let Some(upvars) = tcx.upvars_mentioned(def_id)
+ {
for (&var_id, place) in iter::zip(upvars.keys(), places) {
let var_name = tcx.hir().name(var_id);
struct_fmt.field(var_name.as_str(), place);
}
+ } else {
+ for (index, place) in places.iter().enumerate() {
+ struct_fmt.field(&format!("{index}"), place);
+ }
}
struct_fmt.finish()
@@ -2131,11 +2140,17 @@ impl<'tcx> Debug for Rvalue<'tcx> {
let mut struct_fmt = fmt.debug_struct(&name);
// FIXME(project-rfc-2229#48): This should be a list of capture names/places
- if let Some(upvars) = tcx.upvars_mentioned(def_id) {
+ if let Some(def_id) = def_id.as_local()
+ && let Some(upvars) = tcx.upvars_mentioned(def_id)
+ {
for (&var_id, place) in iter::zip(upvars.keys(), places) {
let var_name = tcx.hir().name(var_id);
struct_fmt.field(var_name.as_str(), place);
}
+ } else {
+ for (index, place) in places.iter().enumerate() {
+ struct_fmt.field(&format!("{index}"), place);
+ }
}
struct_fmt.finish()
@@ -2335,13 +2350,17 @@ impl<'tcx> ConstantKind<'tcx> {
}
#[inline]
- pub fn try_eval_usize(&self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> Option<u64> {
+ pub fn try_eval_target_usize(
+ &self,
+ tcx: TyCtxt<'tcx>,
+ param_env: ty::ParamEnv<'tcx>,
+ ) -> Option<u64> {
match self {
- Self::Ty(ct) => ct.try_eval_usize(tcx, param_env),
- Self::Val(val, _) => val.try_to_machine_usize(tcx),
+ Self::Ty(ct) => ct.try_eval_target_usize(tcx, param_env),
+ Self::Val(val, _) => val.try_to_target_usize(tcx),
Self::Unevaluated(uneval, _) => {
match tcx.const_eval_resolve(param_env, *uneval, None) {
- Ok(val) => val.try_to_machine_usize(tcx),
+ Ok(val) => val.try_to_target_usize(tcx),
Err(_) => None,
}
}
@@ -2478,7 +2497,7 @@ impl<'tcx> ConstantKind<'tcx> {
};
debug!("expr.kind: {:?}", expr.kind);
- let ty = tcx.type_of(def.def_id_for_type_of());
+ let ty = tcx.type_of(def.def_id_for_type_of()).subst_identity();
debug!(?ty);
// FIXME(const_generics): We currently have to special case parameters because `min_const_generics`
@@ -2506,20 +2525,19 @@ impl<'tcx> ConstantKind<'tcx> {
}
let hir_id = tcx.hir().local_def_id_to_hir_id(def.did);
- let parent_substs = if let Some(parent_hir_id) = tcx.hir().opt_parent_id(hir_id) {
- if let Some(parent_did) = tcx.hir().opt_local_def_id(parent_hir_id) {
- InternalSubsts::identity_for_item(tcx, parent_did.to_def_id())
- } else {
- tcx.mk_substs(Vec::<GenericArg<'tcx>>::new().into_iter())
- }
+ let parent_substs = if let Some(parent_hir_id) = tcx.hir().opt_parent_id(hir_id)
+ && let Some(parent_did) = parent_hir_id.as_owner()
+ {
+ InternalSubsts::identity_for_item(tcx, parent_did.to_def_id())
} else {
- tcx.mk_substs(Vec::<GenericArg<'tcx>>::new().into_iter())
+ List::empty()
};
debug!(?parent_substs);
let did = def.did.to_def_id();
let child_substs = InternalSubsts::identity_for_item(tcx, did);
- let substs = tcx.mk_substs(parent_substs.into_iter().chain(child_substs.into_iter()));
+ let substs =
+ tcx.mk_substs_from_iter(parent_substs.into_iter().chain(child_substs.into_iter()));
debug!(?substs);
let hir_id = tcx.hir().local_def_id_to_hir_id(def.did);
@@ -2737,8 +2755,11 @@ impl UserTypeProjection {
}
}
-impl<'tcx> TypeFoldable<'tcx> for UserTypeProjection {
- fn try_fold_with<F: FallibleTypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> {
+impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for UserTypeProjection {
+ fn try_fold_with<F: FallibleTypeFolder<TyCtxt<'tcx>>>(
+ self,
+ folder: &mut F,
+ ) -> Result<Self, F::Error> {
Ok(UserTypeProjection {
base: self.base.try_fold_with(folder)?,
projs: self.projs.try_fold_with(folder)?,
@@ -2746,8 +2767,11 @@ impl<'tcx> TypeFoldable<'tcx> for UserTypeProjection {
}
}
-impl<'tcx> TypeVisitable<'tcx> for UserTypeProjection {
- fn visit_with<Vs: TypeVisitor<'tcx>>(&self, visitor: &mut Vs) -> ControlFlow<Vs::BreakTy> {
+impl<'tcx> TypeVisitable<TyCtxt<'tcx>> for UserTypeProjection {
+ fn visit_with<Vs: TypeVisitor<TyCtxt<'tcx>>>(
+ &self,
+ visitor: &mut Vs,
+ ) -> ControlFlow<Vs::BreakTy> {
self.base.visit_with(visitor)
// Note: there's nothing in `self.proj` to visit.
}
@@ -2884,7 +2908,7 @@ fn pretty_print_const_value<'tcx>(
// the `destructure_const` query with an empty `ty::ParamEnv` without
// introducing ICEs (e.g. via `layout_of`) from missing bounds.
// E.g. `transmute([0usize; 2]): (u8, *mut T)` needs to know `T: Sized`
- // to be able to destructure the tuple into `(0u8, *mut T)
+ // to be able to destructure the tuple into `(0u8, *mut T)`
//
// FIXME(eddyb) for `--emit=mir`/`-Z dump-mir`, we should provide the
// correct `ty::ParamEnv` to allow printing *all* constant values.
@@ -3049,7 +3073,7 @@ impl Location {
if self.block == other.block {
self.statement_index <= other.statement_index
} else {
- dominators.is_dominated_by(other.block, self.block)
+ dominators.dominates(self.block, other.block)
}
}
}
diff --git a/compiler/rustc_middle/src/mir/mono.rs b/compiler/rustc_middle/src/mir/mono.rs
index 1e8d5f7ea..7a05ee2ff 100644
--- a/compiler/rustc_middle/src/mir/mono.rs
+++ b/compiler/rustc_middle/src/mir/mono.rs
@@ -318,16 +318,19 @@ impl<'tcx> CodegenUnit<'tcx> {
base_n::encode(hash, base_n::CASE_INSENSITIVE)
}
- pub fn estimate_size(&mut self, tcx: TyCtxt<'tcx>) {
+ pub fn create_size_estimate(&mut self, tcx: TyCtxt<'tcx>) {
// Estimate the size of a codegen unit as (approximately) the number of MIR
// statements it corresponds to.
self.size_estimate = Some(self.items.keys().map(|mi| mi.size_estimate(tcx)).sum());
}
#[inline]
+ /// Should only be called if [`create_size_estimate`] has previously been called.
+ ///
+ /// [`create_size_estimate`]: Self::create_size_estimate
pub fn size_estimate(&self) -> usize {
- // Should only be called if `estimate_size` has previously been called.
- self.size_estimate.expect("estimate_size must be called before getting a size_estimate")
+ self.size_estimate
+ .expect("create_size_estimate must be called before getting a size_estimate")
}
pub fn modify_size_estimate(&mut self, delta: usize) {
diff --git a/compiler/rustc_middle/src/mir/predecessors.rs b/compiler/rustc_middle/src/mir/predecessors.rs
deleted file mode 100644
index 5f1fadaf3..000000000
--- a/compiler/rustc_middle/src/mir/predecessors.rs
+++ /dev/null
@@ -1,78 +0,0 @@
-//! Lazily compute the reverse control-flow graph for the MIR.
-
-use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
-use rustc_data_structures::sync::OnceCell;
-use rustc_index::vec::IndexVec;
-use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
-use smallvec::SmallVec;
-
-use crate::mir::{BasicBlock, BasicBlockData};
-
-// Typically 95%+ of basic blocks have 4 or fewer predecessors.
-pub type Predecessors = IndexVec<BasicBlock, SmallVec<[BasicBlock; 4]>>;
-
-#[derive(Clone, Debug)]
-pub(super) struct PredecessorCache {
- cache: OnceCell<Predecessors>,
-}
-
-impl PredecessorCache {
- #[inline]
- pub(super) fn new() -> Self {
- PredecessorCache { cache: OnceCell::new() }
- }
-
- /// Invalidates the predecessor cache.
- #[inline]
- pub(super) fn invalidate(&mut self) {
- // Invalidating the predecessor cache requires mutating the MIR, which in turn requires a
- // unique reference (`&mut`) to the `mir::Body`. Because of this, we can assume that all
- // callers of `invalidate` have a unique reference to the MIR and thus to the predecessor
- // cache. This means we never need to do synchronization when `invalidate` is called, we can
- // simply reinitialize the `OnceCell`.
- self.cache = OnceCell::new();
- }
-
- /// Returns the predecessor graph for this MIR.
- #[inline]
- pub(super) fn compute(
- &self,
- basic_blocks: &IndexVec<BasicBlock, BasicBlockData<'_>>,
- ) -> &Predecessors {
- self.cache.get_or_init(|| {
- let mut preds = IndexVec::from_elem(SmallVec::new(), basic_blocks);
- for (bb, data) in basic_blocks.iter_enumerated() {
- if let Some(term) = &data.terminator {
- for succ in term.successors() {
- preds[succ].push(bb);
- }
- }
- }
-
- preds
- })
- }
-}
-
-impl<S: Encoder> Encodable<S> for PredecessorCache {
- #[inline]
- fn encode(&self, _s: &mut S) {}
-}
-
-impl<D: Decoder> Decodable<D> for PredecessorCache {
- #[inline]
- fn decode(_: &mut D) -> Self {
- Self::new()
- }
-}
-
-impl<CTX> HashStable<CTX> for PredecessorCache {
- #[inline]
- fn hash_stable(&self, _: &mut CTX, _: &mut StableHasher) {
- // do nothing
- }
-}
-
-TrivialTypeTraversalAndLiftImpls! {
- PredecessorCache,
-}
diff --git a/compiler/rustc_middle/src/mir/pretty.rs b/compiler/rustc_middle/src/mir/pretty.rs
index 40289af25..d8829e3e7 100644
--- a/compiler/rustc_middle/src/mir/pretty.rs
+++ b/compiler/rustc_middle/src/mir/pretty.rs
@@ -12,8 +12,8 @@ use rustc_data_structures::fx::FxHashMap;
use rustc_hir::def_id::DefId;
use rustc_index::vec::Idx;
use rustc_middle::mir::interpret::{
- alloc_range, read_target_uint, AllocId, Allocation, ConstAllocation, ConstValue, GlobalAlloc,
- Pointer, Provenance,
+ alloc_range, read_target_uint, AllocBytes, AllocId, Allocation, ConstAllocation, ConstValue,
+ GlobalAlloc, Pointer, Provenance,
};
use rustc_middle::mir::visit::Visitor;
use rustc_middle::mir::*;
@@ -580,7 +580,7 @@ fn write_scope_tree(
continue;
}
- let mut_str = if local_decl.mutability == Mutability::Mut { "mut " } else { "" };
+ let mut_str = local_decl.mutability.prefix_str();
let mut indented_decl =
format!("{0:1$}let {2}{3:?}: {4:?}", INDENT, indent, mut_str, local, local_decl.ty);
@@ -787,21 +787,21 @@ pub fn write_allocations<'tcx>(
/// After the hex dump, an ascii dump follows, replacing all unprintable characters (control
/// characters or characters whose value is larger than 127) with a `.`
/// This also prints provenance adequately.
-pub fn display_allocation<'a, 'tcx, Prov: Provenance, Extra>(
+pub fn display_allocation<'a, 'tcx, Prov: Provenance, Extra, Bytes: AllocBytes>(
tcx: TyCtxt<'tcx>,
- alloc: &'a Allocation<Prov, Extra>,
-) -> RenderAllocation<'a, 'tcx, Prov, Extra> {
+ alloc: &'a Allocation<Prov, Extra, Bytes>,
+) -> RenderAllocation<'a, 'tcx, Prov, Extra, Bytes> {
RenderAllocation { tcx, alloc }
}
#[doc(hidden)]
-pub struct RenderAllocation<'a, 'tcx, Prov: Provenance, Extra> {
+pub struct RenderAllocation<'a, 'tcx, Prov: Provenance, Extra, Bytes: AllocBytes> {
tcx: TyCtxt<'tcx>,
- alloc: &'a Allocation<Prov, Extra>,
+ alloc: &'a Allocation<Prov, Extra, Bytes>,
}
-impl<'a, 'tcx, Prov: Provenance, Extra> std::fmt::Display
- for RenderAllocation<'a, 'tcx, Prov, Extra>
+impl<'a, 'tcx, Prov: Provenance, Extra, Bytes: AllocBytes> std::fmt::Display
+ for RenderAllocation<'a, 'tcx, Prov, Extra, Bytes>
{
fn fmt(&self, w: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let RenderAllocation { tcx, alloc } = *self;
@@ -845,9 +845,9 @@ fn write_allocation_newline(
/// The `prefix` argument allows callers to add an arbitrary prefix before each line (even if there
/// is only one line). Note that your prefix should contain a trailing space as the lines are
/// printed directly after it.
-fn write_allocation_bytes<'tcx, Prov: Provenance, Extra>(
+fn write_allocation_bytes<'tcx, Prov: Provenance, Extra, Bytes: AllocBytes>(
tcx: TyCtxt<'tcx>,
- alloc: &Allocation<Prov, Extra>,
+ alloc: &Allocation<Prov, Extra, Bytes>,
w: &mut dyn std::fmt::Write,
prefix: &str,
) -> std::fmt::Result {
diff --git a/compiler/rustc_middle/src/mir/query.rs b/compiler/rustc_middle/src/mir/query.rs
index a8a453222..b964c1852 100644
--- a/compiler/rustc_middle/src/mir/query.rs
+++ b/compiler/rustc_middle/src/mir/query.rs
@@ -8,7 +8,7 @@ use rustc_errors::ErrorGuaranteed;
use rustc_hir as hir;
use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_index::bit_set::BitMatrix;
-use rustc_index::vec::IndexVec;
+use rustc_index::vec::{Idx, IndexVec};
use rustc_span::Span;
use rustc_target::abi::VariantIdx;
use smallvec::SmallVec;
@@ -135,11 +135,20 @@ rustc_index::newtype_index! {
pub struct GeneratorSavedLocal {}
}
+#[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable, TypeFoldable, TypeVisitable)]
+pub struct GeneratorSavedTy<'tcx> {
+ pub ty: Ty<'tcx>,
+ /// Source info corresponding to the local in the original MIR body.
+ pub source_info: SourceInfo,
+ /// Whether the local should be ignored for trait bound computations.
+ pub ignore_for_traits: bool,
+}
+
/// The layout of generator state.
#[derive(Clone, TyEncodable, TyDecodable, HashStable, TypeFoldable, TypeVisitable)]
pub struct GeneratorLayout<'tcx> {
/// The type of every local stored inside the generator.
- pub field_tys: IndexVec<GeneratorSavedLocal, Ty<'tcx>>,
+ pub field_tys: IndexVec<GeneratorSavedLocal, GeneratorSavedTy<'tcx>>,
/// Which of the above fields are in each variant. Note that one field may
/// be stored in multiple variants.
@@ -152,6 +161,8 @@ pub struct GeneratorLayout<'tcx> {
/// Which saved locals are storage-live at the same time. Locals that do not
/// have conflicts with each other are allowed to overlap in the computed
/// layout.
+ #[type_foldable(identity)]
+ #[type_visitable(ignore)]
pub storage_conflicts: BitMatrix<GeneratorSavedLocal, GeneratorSavedLocal>,
}
@@ -278,13 +289,6 @@ pub struct ConstQualifs {
/// instance of the closure is created, the corresponding free regions
/// can be extracted from its type and constrained to have the given
/// outlives relationship.
-///
-/// In some cases, we have to record outlives requirements between types and
-/// regions as well. In that case, if those types include any regions, those
-/// regions are recorded using their external names (`ReStatic`,
-/// `ReEarlyBound`, `ReFree`). We use these because in a query response we
-/// cannot use `ReVar` (which is what we use internally within the rest of the
-/// NLL code).
#[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable)]
pub struct ClosureRegionRequirements<'tcx> {
/// The number of external regions defined on the closure. In our
@@ -381,16 +385,59 @@ pub enum ClosureOutlivesSubject<'tcx> {
/// Subject is a type, typically a type parameter, but could also
/// be a projection. Indicates a requirement like `T: 'a` being
/// passed to the caller, where the type here is `T`.
- ///
- /// The type here is guaranteed not to contain any free regions at
- /// present.
- Ty(Ty<'tcx>),
+ Ty(ClosureOutlivesSubjectTy<'tcx>),
/// Subject is a free region from the closure. Indicates a requirement
/// like `'a: 'b` being passed to the caller; the region here is `'a`.
Region(ty::RegionVid),
}
+/// Represents a `ty::Ty` for use in [`ClosureOutlivesSubject`].
+///
+/// This abstraction is necessary because the type may include `ReVar` regions,
+/// which is what we use internally within NLL code, and they can't be used in
+/// a query response.
+///
+/// DO NOT implement `TypeVisitable` or `TypeFoldable` traits, because this
+/// type is not recognized as a binder for late-bound region.
+#[derive(Copy, Clone, Debug, TyEncodable, TyDecodable, HashStable)]
+pub struct ClosureOutlivesSubjectTy<'tcx> {
+ inner: Ty<'tcx>,
+}
+
+impl<'tcx> ClosureOutlivesSubjectTy<'tcx> {
+ /// All regions of `ty` must be of kind `ReVar` and must represent
+ /// universal regions *external* to the closure.
+ pub fn bind(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Self {
+ let inner = tcx.fold_regions(ty, |r, depth| match r.kind() {
+ ty::ReVar(vid) => {
+ let br = ty::BoundRegion {
+ var: ty::BoundVar::new(vid.index()),
+ kind: ty::BrAnon(vid.as_u32(), None),
+ };
+ tcx.mk_re_late_bound(depth, br)
+ }
+ _ => bug!("unexpected region in ClosureOutlivesSubjectTy: {r:?}"),
+ });
+
+ Self { inner }
+ }
+
+ pub fn instantiate(
+ self,
+ tcx: TyCtxt<'tcx>,
+ mut map: impl FnMut(ty::RegionVid) -> ty::Region<'tcx>,
+ ) -> Ty<'tcx> {
+ tcx.fold_regions(self.inner, |r, depth| match r.kind() {
+ ty::ReLateBound(debruijn, br) => {
+ debug_assert_eq!(debruijn, depth);
+ map(ty::RegionVid::new(br.var.index()))
+ }
+ _ => bug!("unexpected region {r:?}"),
+ })
+ }
+}
+
/// The constituent parts of a mir constant of kind ADT or array.
#[derive(Copy, Clone, Debug, HashStable)]
pub struct DestructuredConstant<'tcx> {
diff --git a/compiler/rustc_middle/src/mir/spanview.rs b/compiler/rustc_middle/src/mir/spanview.rs
index 887ee5715..28a3b51b7 100644
--- a/compiler/rustc_middle/src/mir/spanview.rs
+++ b/compiler/rustc_middle/src/mir/spanview.rs
@@ -11,7 +11,7 @@ use std::io::{self, Write};
pub const TOOLTIP_INDENT: &str = " ";
const CARET: char = '\u{2038}'; // Unicode `CARET`
-const ANNOTATION_LEFT_BRACKET: char = '\u{298a}'; // Unicode `Z NOTATION RIGHT BINDING BRACKET
+const ANNOTATION_LEFT_BRACKET: char = '\u{298a}'; // Unicode `Z NOTATION RIGHT BINDING BRACKET`
const ANNOTATION_RIGHT_BRACKET: char = '\u{2989}'; // Unicode `Z NOTATION LEFT BINDING BRACKET`
const NEW_LINE_SPAN: &str = "</span>\n<span class=\"line\">";
const HEADER: &str = r#"<!DOCTYPE html>
@@ -250,6 +250,7 @@ pub fn statement_kind_name(statement: &Statement<'_>) -> &'static str {
AscribeUserType(..) => "AscribeUserType",
Coverage(..) => "Coverage",
Intrinsic(..) => "Intrinsic",
+ ConstEvalCounter => "ConstEvalCounter",
Nop => "Nop",
}
}
@@ -670,7 +671,7 @@ fn fn_span(tcx: TyCtxt<'_>, def_id: DefId) -> Span {
fn hir_body(tcx: TyCtxt<'_>, def_id: DefId) -> Option<&rustc_hir::Body<'_>> {
let hir_node = tcx.hir().get_if_local(def_id).expect("expected DefId is local");
- hir::map::associated_body(hir_node).map(|fn_body_id| tcx.hir().body(fn_body_id))
+ hir::map::associated_body(hir_node).map(|(_, fn_body_id)| tcx.hir().body(fn_body_id))
}
fn escape_html(s: &str) -> String {
diff --git a/compiler/rustc_middle/src/mir/switch_sources.rs b/compiler/rustc_middle/src/mir/switch_sources.rs
deleted file mode 100644
index b91c0c257..000000000
--- a/compiler/rustc_middle/src/mir/switch_sources.rs
+++ /dev/null
@@ -1,78 +0,0 @@
-//! Lazily compute the inverse of each `SwitchInt`'s switch targets. Modeled after
-//! `Predecessors`/`PredecessorCache`.
-
-use rustc_data_structures::fx::FxHashMap;
-use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
-use rustc_data_structures::sync::OnceCell;
-use rustc_index::vec::IndexVec;
-use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
-use smallvec::SmallVec;
-
-use crate::mir::{BasicBlock, BasicBlockData, Terminator, TerminatorKind};
-
-pub type SwitchSources = FxHashMap<(BasicBlock, BasicBlock), SmallVec<[Option<u128>; 1]>>;
-
-#[derive(Clone, Debug)]
-pub(super) struct SwitchSourceCache {
- cache: OnceCell<SwitchSources>,
-}
-
-impl SwitchSourceCache {
- #[inline]
- pub(super) fn new() -> Self {
- SwitchSourceCache { cache: OnceCell::new() }
- }
-
- /// Invalidates the switch source cache.
- #[inline]
- pub(super) fn invalidate(&mut self) {
- self.cache = OnceCell::new();
- }
-
- /// Returns the switch sources for this MIR.
- #[inline]
- pub(super) fn compute(
- &self,
- basic_blocks: &IndexVec<BasicBlock, BasicBlockData<'_>>,
- ) -> &SwitchSources {
- self.cache.get_or_init(|| {
- let mut switch_sources: SwitchSources = FxHashMap::default();
- for (bb, data) in basic_blocks.iter_enumerated() {
- if let Some(Terminator {
- kind: TerminatorKind::SwitchInt { targets, .. }, ..
- }) = &data.terminator
- {
- for (value, target) in targets.iter() {
- switch_sources.entry((target, bb)).or_default().push(Some(value));
- }
- switch_sources.entry((targets.otherwise(), bb)).or_default().push(None);
- }
- }
-
- switch_sources
- })
- }
-}
-
-impl<S: Encoder> Encodable<S> for SwitchSourceCache {
- #[inline]
- fn encode(&self, _s: &mut S) {}
-}
-
-impl<D: Decoder> Decodable<D> for SwitchSourceCache {
- #[inline]
- fn decode(_: &mut D) -> Self {
- Self::new()
- }
-}
-
-impl<CTX> HashStable<CTX> for SwitchSourceCache {
- #[inline]
- fn hash_stable(&self, _: &mut CTX, _: &mut StableHasher) {
- // do nothing
- }
-}
-
-TrivialTypeTraversalAndLiftImpls! {
- SwitchSourceCache,
-}
diff --git a/compiler/rustc_middle/src/mir/syntax.rs b/compiler/rustc_middle/src/mir/syntax.rs
index 52c2b10cb..ae09562a8 100644
--- a/compiler/rustc_middle/src/mir/syntax.rs
+++ b/compiler/rustc_middle/src/mir/syntax.rs
@@ -355,6 +355,12 @@ pub enum StatementKind<'tcx> {
/// This avoids adding a new block and a terminator for simple intrinsics.
Intrinsic(Box<NonDivergingIntrinsic<'tcx>>),
+ /// Instructs the const eval interpreter to increment a counter; this counter is used to track
+ /// how many steps the interpreter has taken. It is used to prevent the user from writing const
+ /// code that runs for too long or infinitely. Other than in the const eval interpreter, this
+ /// is a no-op.
+ ConstEvalCounter,
+
/// No-op. Useful for deleting instructions without affecting statement indices.
Nop,
}
@@ -665,6 +671,12 @@ pub enum TerminatorKind<'tcx> {
/// as parameters, and `None` for the destination. Keep in mind that the `cleanup` path is not
/// necessarily executed even in the case of a panic, for example in `-C panic=abort`. If the
/// assertion does not fail, execution continues at the specified basic block.
+ ///
+ /// When overflow checking is disabled and this is run-time MIR (as opposed to compile-time MIR
+ /// that is used for CTFE), the following variants of this terminator behave as `goto target`:
+ /// - `OverflowNeg(..)`,
+ /// - `Overflow(op, ..)` if op is a "checkable" operation (add, sub, mul, shl, shr, but NOT
+ /// div or rem).
Assert {
cond: Operand<'tcx>,
expected: bool,
@@ -1097,10 +1109,6 @@ pub enum Rvalue<'tcx> {
/// Same as `BinaryOp`, but yields `(T, bool)` with a `bool` indicating an error condition.
///
- /// When overflow checking is disabled and we are generating run-time code, the error condition
- /// is false. Otherwise, and always during CTFE, the error condition is determined as described
- /// below.
- ///
/// For addition, subtraction, and multiplication on integers the error condition is set when
/// the infinite precision result would be unequal to the actual result.
///
@@ -1197,10 +1205,8 @@ pub enum AggregateKind<'tcx> {
/// active field index would identity the field `c`
Adt(DefId, VariantIdx, SubstsRef<'tcx>, Option<UserTypeAnnotationIndex>, Option<usize>),
- // Note: We can use LocalDefId since closures and generators a deaggregated
- // before codegen.
- Closure(LocalDefId, SubstsRef<'tcx>),
- Generator(LocalDefId, SubstsRef<'tcx>, hir::Movability),
+ Closure(DefId, SubstsRef<'tcx>),
+ Generator(DefId, SubstsRef<'tcx>, hir::Movability),
}
#[derive(Copy, Clone, Debug, PartialEq, Eq, TyEncodable, TyDecodable, Hash, HashStable)]
diff --git a/compiler/rustc_middle/src/mir/tcx.rs b/compiler/rustc_middle/src/mir/tcx.rs
index 599f0b9d3..0aa2c500f 100644
--- a/compiler/rustc_middle/src/mir/tcx.rs
+++ b/compiler/rustc_middle/src/mir/tcx.rs
@@ -97,7 +97,7 @@ impl<'tcx> PlaceTy<'tcx> {
ty::Slice(..) => self.ty,
ty::Array(inner, _) if !from_end => tcx.mk_array(*inner, (to - from) as u64),
ty::Array(inner, size) if from_end => {
- let size = size.eval_usize(tcx, param_env);
+ let size = size.eval_target_usize(tcx, param_env);
let len = size - (from as u64) - (to as u64);
tcx.mk_array(*inner, len)
}
@@ -162,10 +162,10 @@ impl<'tcx> Rvalue<'tcx> {
match *self {
Rvalue::Use(ref operand) => operand.ty(local_decls, tcx),
Rvalue::Repeat(ref operand, count) => {
- tcx.mk_ty(ty::Array(operand.ty(local_decls, tcx), count))
+ tcx.mk_array_with_const_len(operand.ty(local_decls, tcx), count)
}
Rvalue::ThreadLocalRef(did) => {
- let static_ty = tcx.type_of(did);
+ let static_ty = tcx.type_of(did).subst_identity();
if tcx.is_mutable_static(did) {
tcx.mk_mut_ptr(static_ty)
} else if tcx.is_foreign_item(did) {
@@ -194,20 +194,20 @@ impl<'tcx> Rvalue<'tcx> {
let lhs_ty = lhs.ty(local_decls, tcx);
let rhs_ty = rhs.ty(local_decls, tcx);
let ty = op.ty(tcx, lhs_ty, rhs_ty);
- tcx.intern_tup(&[ty, tcx.types.bool])
+ tcx.mk_tup(&[ty, tcx.types.bool])
}
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::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))),
- AggregateKind::Adt(did, _, substs, _, _) => {
- tcx.bound_type_of(did).subst(tcx, substs)
+ AggregateKind::Tuple => {
+ tcx.mk_tup_from_iter(ops.iter().map(|op| op.ty(local_decls, tcx)))
}
- AggregateKind::Closure(did, substs) => tcx.mk_closure(did.to_def_id(), substs),
+ AggregateKind::Adt(did, _, substs, _, _) => tcx.type_of(did).subst(tcx, substs),
+ AggregateKind::Closure(did, substs) => tcx.mk_closure(did, substs),
AggregateKind::Generator(did, substs, movability) => {
- tcx.mk_generator(did.to_def_id(), substs, movability)
+ tcx.mk_generator(did, substs, movability)
}
},
Rvalue::ShallowInitBox(_, ty) => tcx.mk_box(ty),
diff --git a/compiler/rustc_middle/src/mir/traversal.rs b/compiler/rustc_middle/src/mir/traversal.rs
index 0b461d1ce..f37222cb2 100644
--- a/compiler/rustc_middle/src/mir/traversal.rs
+++ b/compiler/rustc_middle/src/mir/traversal.rs
@@ -1,7 +1,4 @@
-use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
-use rustc_data_structures::sync::OnceCell;
use rustc_index::bit_set::BitSet;
-use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
use super::*;
@@ -339,50 +336,3 @@ pub fn reverse_postorder<'a, 'tcx>(body: &'a Body<'tcx>) -> ReversePostorderIter
let len = blocks.len();
ReversePostorderIter { body, blocks, idx: len }
}
-
-#[derive(Clone, Debug)]
-pub(super) struct PostorderCache {
- cache: OnceCell<Vec<BasicBlock>>,
-}
-
-impl PostorderCache {
- #[inline]
- pub(super) fn new() -> Self {
- PostorderCache { cache: OnceCell::new() }
- }
-
- /// Invalidates the postorder cache.
- #[inline]
- pub(super) fn invalidate(&mut self) {
- self.cache = OnceCell::new();
- }
-
- /// Returns the `&[BasicBlocks]` represents the postorder graph for this MIR.
- #[inline]
- pub(super) fn compute(&self, body: &IndexVec<BasicBlock, BasicBlockData<'_>>) -> &[BasicBlock] {
- self.cache.get_or_init(|| Postorder::new(body, START_BLOCK).map(|(bb, _)| bb).collect())
- }
-}
-
-impl<S: Encoder> Encodable<S> for PostorderCache {
- #[inline]
- fn encode(&self, _s: &mut S) {}
-}
-
-impl<D: Decoder> Decodable<D> for PostorderCache {
- #[inline]
- fn decode(_: &mut D) -> Self {
- Self::new()
- }
-}
-
-impl<CTX> HashStable<CTX> for PostorderCache {
- #[inline]
- fn hash_stable(&self, _: &mut CTX, _: &mut StableHasher) {
- // do nothing
- }
-}
-
-TrivialTypeTraversalAndLiftImpls! {
- PostorderCache,
-}
diff --git a/compiler/rustc_middle/src/mir/type_foldable.rs b/compiler/rustc_middle/src/mir/type_foldable.rs
index 0705b4cff..988158321 100644
--- a/compiler/rustc_middle/src/mir/type_foldable.rs
+++ b/compiler/rustc_middle/src/mir/type_foldable.rs
@@ -30,26 +30,29 @@ TrivialTypeTraversalImpls! {
}
}
-impl<'tcx> TypeFoldable<'tcx> for &'tcx [InlineAsmTemplatePiece] {
- fn try_fold_with<F: FallibleTypeFolder<'tcx>>(self, _folder: &mut F) -> Result<Self, F::Error> {
+impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for &'tcx [InlineAsmTemplatePiece] {
+ fn try_fold_with<F: FallibleTypeFolder<TyCtxt<'tcx>>>(
+ self,
+ _folder: &mut F,
+ ) -> Result<Self, F::Error> {
Ok(self)
}
}
-impl<'tcx> TypeFoldable<'tcx> for &'tcx [Span] {
- fn try_fold_with<F: FallibleTypeFolder<'tcx>>(self, _folder: &mut F) -> Result<Self, F::Error> {
+impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for &'tcx [Span] {
+ fn try_fold_with<F: FallibleTypeFolder<TyCtxt<'tcx>>>(
+ self,
+ _folder: &mut F,
+ ) -> Result<Self, F::Error> {
Ok(self)
}
}
-impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::List<PlaceElem<'tcx>> {
- fn try_fold_with<F: FallibleTypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> {
- ty::util::fold_list(self, folder, |tcx, v| tcx.intern_place_elems(v))
- }
-}
-
-impl<'tcx, R: Idx, C: Idx> TypeFoldable<'tcx> for BitMatrix<R, C> {
- fn try_fold_with<F: FallibleTypeFolder<'tcx>>(self, _: &mut F) -> Result<Self, F::Error> {
- Ok(self)
+impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for &'tcx ty::List<PlaceElem<'tcx>> {
+ fn try_fold_with<F: FallibleTypeFolder<TyCtxt<'tcx>>>(
+ self,
+ folder: &mut F,
+ ) -> Result<Self, F::Error> {
+ ty::util::fold_list(self, folder, |tcx, v| tcx.mk_place_elems(v))
}
}
diff --git a/compiler/rustc_middle/src/mir/type_visitable.rs b/compiler/rustc_middle/src/mir/type_visitable.rs
deleted file mode 100644
index d44c6809b..000000000
--- a/compiler/rustc_middle/src/mir/type_visitable.rs
+++ /dev/null
@@ -1,9 +0,0 @@
-//! `TypeVisitable` implementations for MIR types
-
-use super::*;
-
-impl<'tcx, R: Idx, C: Idx> TypeVisitable<'tcx> for BitMatrix<R, C> {
- fn visit_with<V: TypeVisitor<'tcx>>(&self, _: &mut V) -> ControlFlow<V::BreakTy> {
- ControlFlow::Continue(())
- }
-}
diff --git a/compiler/rustc_middle/src/mir/visit.rs b/compiler/rustc_middle/src/mir/visit.rs
index 1a264d2d5..5c056b299 100644
--- a/compiler/rustc_middle/src/mir/visit.rs
+++ b/compiler/rustc_middle/src/mir/visit.rs
@@ -323,7 +323,7 @@ macro_rules! make_mir_visitor {
self.visit_source_scope($(& $mutability)? *parent_scope);
}
if let Some((callee, callsite_span)) = inlined {
- let location = START_BLOCK.start_location();
+ let location = Location::START;
self.visit_span($(& $mutability)? *callsite_span);
@@ -427,6 +427,7 @@ macro_rules! make_mir_visitor {
}
}
}
+ StatementKind::ConstEvalCounter => {}
StatementKind::Nop => {}
}
}
@@ -836,7 +837,7 @@ macro_rules! make_mir_visitor {
} = var_debug_info;
self.visit_source_info(source_info);
- let location = START_BLOCK.start_location();
+ let location = Location::START;
match value {
VarDebugInfoContents::Const(c) => self.visit_constant(c, location),
VarDebugInfoContents::Place(place) =>
@@ -1025,7 +1026,7 @@ macro_rules! super_body {
$self.visit_span($(& $mutability)? $body.span);
for const_ in &$($mutability)? $body.required_consts {
- let location = START_BLOCK.start_location();
+ let location = Location::START;
$self.visit_constant(const_, location);
}
}
@@ -1044,7 +1045,7 @@ macro_rules! visit_place_fns {
self.visit_local(&mut place.local, context, location);
if let Some(new_projection) = self.process_projection(&place.projection, location) {
- place.projection = self.tcx().intern_place_elems(&new_projection);
+ place.projection = self.tcx().mk_place_elems(&new_projection);
}
}
@@ -1213,7 +1214,7 @@ impl<'tcx> MirVisitable<'tcx> for Option<Terminator<'tcx>> {
/// Extra information passed to `visit_ty` and friends to give context
/// about where the type etc appears.
-#[derive(Debug)]
+#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
pub enum TyContext {
LocalDecl {
/// The index of the local variable we are visiting.
diff --git a/compiler/rustc_middle/src/query/keys.rs b/compiler/rustc_middle/src/query/keys.rs
index e4bb3ce3d..78ee8a6a8 100644
--- a/compiler/rustc_middle/src/query/keys.rs
+++ b/compiler/rustc_middle/src/query/keys.rs
@@ -4,11 +4,12 @@ use crate::infer::canonical::Canonical;
use crate::mir;
use crate::traits;
use crate::ty::fast_reject::SimplifiedType;
+use crate::ty::layout::{TyAndLayout, ValidityRequirement};
use crate::ty::subst::{GenericArg, SubstsRef};
-use crate::ty::{self, layout::TyAndLayout, Ty, TyCtxt};
+use crate::ty::{self, Ty, TyCtxt};
use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, LOCAL_CRATE};
use rustc_hir::hir_id::{HirId, OwnerId};
-use rustc_query_system::query::{DefaultCacheSelector, VecCacheSelector};
+use rustc_query_system::query::{DefaultCacheSelector, SingleCacheSelector, VecCacheSelector};
use rustc_span::symbol::{Ident, Symbol};
use rustc_span::{Span, DUMMY_SP};
@@ -45,7 +46,7 @@ pub trait Key: Sized {
}
impl Key for () {
- type CacheSelector = DefaultCacheSelector<Self>;
+ type CacheSelector = SingleCacheSelector;
#[inline(always)]
fn query_crate_is_local(&self) -> bool {
@@ -696,3 +697,24 @@ impl Key for HirId {
None
}
}
+
+impl<'tcx> Key for (ValidityRequirement, ty::ParamEnvAnd<'tcx, Ty<'tcx>>) {
+ type CacheSelector = DefaultCacheSelector<Self>;
+
+ // Just forward to `Ty<'tcx>`
+ #[inline(always)]
+ fn query_crate_is_local(&self) -> bool {
+ true
+ }
+
+ fn default_span(&self, _: TyCtxt<'_>) -> Span {
+ DUMMY_SP
+ }
+
+ fn ty_adt_id(&self) -> Option<DefId> {
+ match self.1.value.kind() {
+ ty::Adt(adt, _) => Some(adt.did()),
+ _ => None,
+ }
+ }
+}
diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs
index 6bbf7fa39..5133da342 100644
--- a/compiler/rustc_middle/src/query/mod.rs
+++ b/compiler/rustc_middle/src/query/mod.rs
@@ -33,7 +33,7 @@ rustc_queries! {
}
query resolver_for_lowering(_: ()) -> &'tcx Steal<(ty::ResolverAstLowering, Lrc<ast::Crate>)> {
- feedable
+ eval_always
no_hash
desc { "getting the resolver for lowering" }
}
@@ -54,14 +54,14 @@ rustc_queries! {
/// This is because the `hir_crate` query gives you access to all other items.
/// To avoid this fate, do not call `tcx.hir().krate()`; instead,
/// prefer wrappers like `tcx.visit_all_items_in_krate()`.
- query hir_crate(key: ()) -> Crate<'tcx> {
+ query hir_crate(key: ()) -> &'tcx Crate<'tcx> {
arena_cache
eval_always
desc { "getting the crate HIR" }
}
/// All items in the crate.
- query hir_crate_items(_: ()) -> rustc_middle::hir::ModuleItems {
+ query hir_crate_items(_: ()) -> &'tcx rustc_middle::hir::ModuleItems {
arena_cache
eval_always
desc { "getting HIR crate items" }
@@ -71,7 +71,7 @@ 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) -> rustc_middle::hir::ModuleItems {
+ query hir_module_items(key: LocalDefId) -> &'tcx rustc_middle::hir::ModuleItems {
arena_cache
desc { |tcx| "getting HIR module items in `{}`", tcx.def_path_str(key.to_def_id()) }
cache_on_disk_if { true }
@@ -85,12 +85,12 @@ rustc_queries! {
desc { |tcx| "getting HIR owner of `{}`", tcx.def_path_str(key.to_def_id()) }
}
- /// Gives access to the HIR ID for the given `LocalDefId` owner `key`.
+ /// Gives access to the HIR ID for the given `LocalDefId` owner `key` if any.
///
- /// This can be conveniently accessed by methods on `tcx.hir()`.
- /// Avoid calling this query directly.
- query local_def_id_to_hir_id(key: LocalDefId) -> hir::HirId {
+ /// Definitions that were generated with no HIR, would be feeded to return `None`.
+ query opt_local_def_id_to_hir_id(key: LocalDefId) -> Option<hir::HirId>{
desc { |tcx| "getting HIR ID of `{}`", tcx.def_path_str(key.to_def_id()) }
+ feedable
}
/// Gives access to the HIR node's parent for the HIR owner `key`.
@@ -152,7 +152,7 @@ rustc_queries! {
/// to an alias, it will "skip" this alias to return the aliased type.
///
/// [`DefId`]: rustc_hir::def_id::DefId
- query type_of(key: DefId) -> Ty<'tcx> {
+ query type_of(key: DefId) -> ty::EarlyBinder<Ty<'tcx>> {
desc { |tcx|
"{action} `{path}`",
action = {
@@ -167,6 +167,7 @@ rustc_queries! {
}
cache_on_disk_if { key.is_local() }
separate_provide_extern
+ feedable
}
query collect_return_position_impl_trait_in_trait_tys(key: DefId)
@@ -183,6 +184,15 @@ rustc_queries! {
separate_provide_extern
}
+ query unsizing_params_for_adt(key: DefId) -> &'tcx rustc_index::bit_set::BitSet<u32>
+ {
+ arena_cache
+ desc { |tcx|
+ "determining what parameters of `{}` can participate in unsizing",
+ tcx.def_path_str(key),
+ }
+ }
+
query analysis(key: ()) -> Result<(), ErrorGuaranteed> {
eval_always
desc { "running analysis passes on this crate" }
@@ -209,11 +219,12 @@ rustc_queries! {
/// Maps from the `DefId` of an item (trait/struct/enum/fn) to its
/// associated generics.
- query generics_of(key: DefId) -> ty::Generics {
+ query generics_of(key: DefId) -> &'tcx ty::Generics {
desc { |tcx| "computing generics of `{}`", tcx.def_path_str(key) }
arena_cache
cache_on_disk_if { key.is_local() }
separate_provide_extern
+ feedable
}
/// Maps from the `DefId` of an item (trait/struct/enum/fn) to the
@@ -256,6 +267,7 @@ rustc_queries! {
desc { |tcx| "finding item bounds for `{}`", tcx.def_path_str(key) }
cache_on_disk_if { key.is_local() }
separate_provide_extern
+ feedable
}
/// Elaborated version of the predicates from `explicit_item_bounds`.
@@ -286,19 +298,19 @@ rustc_queries! {
/// These are assembled from the following places:
/// - `extern` blocks (depending on their `link` attributes)
/// - the `libs` (`-l`) option
- query native_libraries(_: CrateNum) -> Vec<NativeLib> {
+ query native_libraries(_: CrateNum) -> &'tcx Vec<NativeLib> {
arena_cache
desc { "looking up the native libraries of a linked crate" }
separate_provide_extern
}
- query shallow_lint_levels_on(key: hir::OwnerId) -> rustc_middle::lint::ShallowLintLevelMap {
+ query shallow_lint_levels_on(key: hir::OwnerId) -> &'tcx rustc_middle::lint::ShallowLintLevelMap {
eval_always // fetches `resolutions`
arena_cache
desc { |tcx| "looking up lint levels for `{}`", tcx.def_path_str(key.to_def_id()) }
}
- query lint_expectations(_: ()) -> Vec<(LintExpectationId, LintExpectation)> {
+ query lint_expectations(_: ()) -> &'tcx Vec<(LintExpectationId, LintExpectation)> {
arena_cache
desc { "computing `#[expect]`ed lints in this crate" }
}
@@ -338,7 +350,7 @@ rustc_queries! {
}
/// Set of param indexes for type params that are in the type's representation
- query params_in_repr(key: DefId) -> rustc_index::bit_set::BitSet<u32> {
+ query params_in_repr(key: DefId) -> &'tcx rustc_index::bit_set::BitSet<u32> {
desc { "finding type parameters in the representation" }
arena_cache
no_hash
@@ -355,16 +367,23 @@ rustc_queries! {
}
/// Create a THIR tree for debugging.
- query thir_tree(key: ty::WithOptConstParam<LocalDefId>) -> String {
+ query thir_tree(key: ty::WithOptConstParam<LocalDefId>) -> &'tcx String {
no_hash
arena_cache
desc { |tcx| "constructing THIR tree for `{}`", tcx.def_path_str(key.did.to_def_id()) }
}
+ /// Create a list-like THIR representation for debugging.
+ query thir_flat(key: ty::WithOptConstParam<LocalDefId>) -> &'tcx String {
+ no_hash
+ arena_cache
+ desc { |tcx| "constructing flat THIR representation for `{}`", tcx.def_path_str(key.did.to_def_id()) }
+ }
+
/// Set of all the `DefId`s in this crate that have MIR associated with
/// them. This includes all the body owners, but also things like struct
/// constructors.
- query mir_keys(_: ()) -> rustc_data_structures::fx::FxIndexSet<LocalDefId> {
+ query mir_keys(_: ()) -> &'tcx rustc_data_structures::fx::FxIndexSet<LocalDefId> {
arena_cache
desc { "getting a list of all mir_keys" }
}
@@ -460,17 +479,24 @@ rustc_queries! {
}
}
- query symbols_for_closure_captures(
- key: (LocalDefId, LocalDefId)
- ) -> Vec<rustc_span::Symbol> {
- arena_cache
+ query closure_typeinfo(key: LocalDefId) -> ty::ClosureTypeInfo<'tcx> {
desc {
- |tcx| "finding symbols for captures of closure `{}` in `{}`",
- tcx.def_path_str(key.1.to_def_id()),
- tcx.def_path_str(key.0.to_def_id())
+ |tcx| "finding symbols for captures of closure `{}`",
+ tcx.def_path_str(key.to_def_id())
}
}
+ query mir_generator_witnesses(key: DefId) -> &'tcx mir::GeneratorLayout<'tcx> {
+ arena_cache
+ desc { |tcx| "generator witness types for `{}`", tcx.def_path_str(key) }
+ cache_on_disk_if { key.is_local() }
+ separate_provide_extern
+ }
+
+ query check_generator_obligations(key: LocalDefId) {
+ desc { |tcx| "verify auto trait bounds for generator interior type `{}`", tcx.def_path_str(key.to_def_id()) }
+ }
+
/// MIR after our optimization passes have run. This is MIR that is ready
/// for codegen. This is also the only query that can fetch non-local MIR, at present.
query optimized_mir(key: DefId) -> &'tcx mir::Body<'tcx> {
@@ -481,14 +507,14 @@ rustc_queries! {
/// Returns coverage summary info for a function, after executing the `InstrumentCoverage`
/// MIR pass (assuming the -Cinstrument-coverage option is enabled).
- query coverageinfo(key: ty::InstanceDef<'tcx>) -> mir::CoverageInfo {
+ query coverageinfo(key: ty::InstanceDef<'tcx>) -> &'tcx mir::CoverageInfo {
desc { |tcx| "retrieving coverage info from MIR for `{}`", tcx.def_path_str(key.def_id()) }
arena_cache
}
/// Returns the `CodeRegions` for a function that has instrumented coverage, in case the
/// function was optimized out before codegen, and before being added to the Coverage Map.
- query covered_code_regions(key: DefId) -> Vec<&'tcx mir::coverage::CodeRegion> {
+ query covered_code_regions(key: DefId) -> &'tcx Vec<&'tcx mir::coverage::CodeRegion> {
desc {
|tcx| "retrieving the covered `CodeRegion`s, if instrumented, for `{}`",
tcx.def_path_str(key)
@@ -530,7 +556,7 @@ rustc_queries! {
desc { "erasing regions from `{}`", ty }
}
- query wasm_import_module_map(_: CrateNum) -> FxHashMap<DefId, String> {
+ query wasm_import_module_map(_: CrateNum) -> &'tcx FxHashMap<DefId, String> {
arena_cache
desc { "getting wasm import module map" }
}
@@ -566,6 +592,7 @@ rustc_queries! {
desc { |tcx| "computing explicit predicates of `{}`", tcx.def_path_str(key) }
cache_on_disk_if { key.is_local() }
separate_provide_extern
+ feedable
}
/// Returns the inferred outlives predicates (e.g., for `struct
@@ -574,6 +601,7 @@ rustc_queries! {
desc { |tcx| "computing inferred outlives predicates of `{}`", tcx.def_path_str(key) }
cache_on_disk_if { key.is_local() }
separate_provide_extern
+ feedable
}
/// Maps from the `DefId` of a trait to the list of
@@ -605,7 +633,7 @@ rustc_queries! {
desc { |tcx| "computing the bounds for type parameter `{}`", tcx.hir().ty_param_name(key.1) }
}
- query trait_def(key: DefId) -> ty::TraitDef {
+ query trait_def(key: DefId) -> &'tcx ty::TraitDef {
desc { |tcx| "computing trait definition for `{}`", tcx.def_path_str(key) }
arena_cache
cache_on_disk_if { key.is_local() }
@@ -676,7 +704,7 @@ rustc_queries! {
}
/// Gets a map with the variance of every item; use `item_variance` instead.
- query crate_variances(_: ()) -> ty::CrateVariancesMap<'tcx> {
+ query crate_variances(_: ()) -> &'tcx ty::CrateVariancesMap<'tcx> {
arena_cache
desc { "computing the variances for items in this crate" }
}
@@ -689,7 +717,7 @@ rustc_queries! {
}
/// Maps from thee `DefId` of a type to its (inferred) outlives.
- query inferred_outlives_crate(_: ()) -> ty::CratePredicatesMap<'tcx> {
+ query inferred_outlives_crate(_: ()) -> &'tcx ty::CratePredicatesMap<'tcx> {
arena_cache
desc { "computing the inferred outlives predicates for items in this crate" }
}
@@ -704,13 +732,13 @@ rustc_queries! {
/// Maps from a trait item to the trait item "descriptor".
query associated_item(key: DefId) -> ty::AssocItem {
desc { |tcx| "computing associated item data for `{}`", tcx.def_path_str(key) }
- arena_cache
cache_on_disk_if { key.is_local() }
separate_provide_extern
+ feedable
}
/// Collects the associated items defined on a trait or impl.
- query associated_items(key: DefId) -> ty::AssocItems<'tcx> {
+ query associated_items(key: DefId) -> &'tcx ty::AssocItems {
arena_cache
desc { |tcx| "collecting associated items of `{}`", tcx.def_path_str(key) }
}
@@ -736,11 +764,31 @@ rustc_queries! {
///
/// The map returned for `tcx.impl_item_implementor_ids(impl_id)` would be
///`{ trait_f: impl_f, trait_g: impl_g }`
- query impl_item_implementor_ids(impl_id: DefId) -> FxHashMap<DefId, DefId> {
+ query impl_item_implementor_ids(impl_id: DefId) -> &'tcx FxHashMap<DefId, DefId> {
arena_cache
desc { |tcx| "comparing impl items against trait for `{}`", tcx.def_path_str(impl_id) }
}
+ /// Given `fn_def_id` of a trait or of an impl that implements a given trait:
+ /// if `fn_def_id` is the def id of a function defined inside a trait, then it creates and returns
+ /// the associated items that correspond to each impl trait in return position for that trait.
+ /// if `fn_def_id` is the def id of a function defined inside an impl that implements a trait, then it
+ /// creates and returns the associated items that correspond to each impl trait in return position
+ /// of the implemented trait.
+ query associated_items_for_impl_trait_in_trait(fn_def_id: DefId) -> &'tcx [DefId] {
+ desc { |tcx| "creating associated items for impl trait in trait returned by `{}`", tcx.def_path_str(fn_def_id) }
+ cache_on_disk_if { fn_def_id.is_local() }
+ separate_provide_extern
+ }
+
+ /// Given an impl trait in trait `opaque_ty_def_id`, create and return the corresponding
+ /// associated item.
+ query associated_item_for_impl_trait_in_trait(opaque_ty_def_id: LocalDefId) -> LocalDefId {
+ desc { |tcx| "creates the associated item corresponding to the opaque type `{}`", tcx.def_path_str(opaque_ty_def_id.to_def_id()) }
+ cache_on_disk_if { true }
+ separate_provide_extern
+ }
+
/// Given an `impl_id`, return the trait it implements.
/// Return `None` if this is an inherent impl.
query impl_trait_ref(impl_id: DefId) -> Option<ty::EarlyBinder<ty::TraitRef<'tcx>>> {
@@ -754,7 +802,7 @@ rustc_queries! {
separate_provide_extern
}
- query issue33140_self_ty(key: DefId) -> Option<ty::Ty<'tcx>> {
+ query issue33140_self_ty(key: DefId) -> Option<ty::EarlyBinder<ty::Ty<'tcx>>> {
desc { |tcx| "computing Self type wrt issue #33140 `{}`", tcx.def_path_str(key) }
}
@@ -796,15 +844,6 @@ rustc_queries! {
}
}
- /// HACK: when evaluated, this reports an "unsafe derive on repr(packed)" error.
- ///
- /// Unsafety checking is executed for each method separately, but we only want
- /// to emit this error once per derive. As there are some impls with multiple
- /// methods, we use a query for deduplication.
- query unsafe_derive_on_repr_packed(key: LocalDefId) -> () {
- desc { |tcx| "processing `{}`", tcx.def_path_str(key.to_def_id()) }
- }
-
/// Returns the types assumed to be well formed while "inside" of the given item.
///
/// Note that we've liberated the late bound regions of function signatures, so
@@ -814,7 +853,7 @@ rustc_queries! {
}
/// Computes the signature of the function.
- query fn_sig(key: DefId) -> ty::PolyFnSig<'tcx> {
+ query fn_sig(key: DefId) -> ty::EarlyBinder<ty::PolyFnSig<'tcx>> {
desc { |tcx| "computing function signature of `{}`", tcx.def_path_str(key) }
cache_on_disk_if { key.is_local() }
separate_provide_extern
@@ -866,7 +905,7 @@ rustc_queries! {
///
/// The second return value maps from ADTs to ignored derived traits (e.g. Debug and Clone) and
/// their respective impl (i.e., part of the derive macro)
- query live_symbols_and_ignored_derived_traits(_: ()) -> (
+ query live_symbols_and_ignored_derived_traits(_: ()) -> &'tcx (
FxHashSet<LocalDefId>,
FxHashMap<LocalDefId, Vec<(DefId, DefId)>>
) {
@@ -946,7 +985,7 @@ rustc_queries! {
/// Gets a complete map from all types to their inherent impls.
/// Not meant to be used directly outside of coherence.
- query crate_inherent_impls(k: ()) -> CrateInherentImpls {
+ query crate_inherent_impls(k: ()) -> &'tcx CrateInherentImpls {
arena_cache
desc { "finding all inherent impls defined in crate" }
}
@@ -1081,7 +1120,7 @@ rustc_queries! {
desc { "checking for private elements in public interfaces" }
}
- query reachable_set(_: ()) -> FxHashSet<LocalDefId> {
+ query reachable_set(_: ()) -> &'tcx FxHashSet<LocalDefId> {
arena_cache
desc { "reachability" }
}
@@ -1093,7 +1132,7 @@ rustc_queries! {
}
/// Generates a MIR body for the shim.
- query mir_shims(key: ty::InstanceDef<'tcx>) -> mir::Body<'tcx> {
+ query mir_shims(key: ty::InstanceDef<'tcx>) -> &'tcx mir::Body<'tcx> {
arena_cache
desc { |tcx| "generating MIR shim for `{}`", tcx.def_path_str(key.def_id()) }
}
@@ -1110,6 +1149,15 @@ rustc_queries! {
desc { |tcx| "looking up definition kind of `{}`", tcx.def_path_str(def_id) }
cache_on_disk_if { def_id.is_local() }
separate_provide_extern
+ feedable
+ }
+
+ /// The `opt_rpitit_info` query returns the pair of the def id of the function where the RPIT
+ /// is defined and the opaque def id if any.
+ query opt_rpitit_info(def_id: DefId) -> Option<ty::ImplTraitInTraitData> {
+ desc { |tcx| "opt_rpitit_info `{}`", tcx.def_path_str(def_id) }
+ cache_on_disk_if { def_id.is_local() }
+ feedable
}
/// Gets the span for the definition.
@@ -1125,6 +1173,7 @@ rustc_queries! {
desc { |tcx| "looking up span for `{}`'s identifier", tcx.def_path_str(def_id) }
cache_on_disk_if { def_id.is_local() }
separate_provide_extern
+ feedable
}
query lookup_stability(def_id: DefId) -> Option<attr::Stability> {
@@ -1157,6 +1206,7 @@ rustc_queries! {
/// Determines whether an item is annotated with `doc(hidden)`.
query is_doc_hidden(def_id: DefId) -> bool {
desc { |tcx| "checking whether `{}` is `doc(hidden)`", tcx.def_path_str(def_id) }
+ separate_provide_extern
}
/// Determines whether an item is annotated with `doc(notable_trait)`.
@@ -1172,7 +1222,7 @@ rustc_queries! {
separate_provide_extern
}
- query codegen_fn_attrs(def_id: DefId) -> CodegenFnAttrs {
+ query codegen_fn_attrs(def_id: DefId) -> &'tcx CodegenFnAttrs {
desc { |tcx| "computing codegen attributes of `{}`", tcx.def_path_str(def_id) }
arena_cache
cache_on_disk_if { def_id.is_local() }
@@ -1190,7 +1240,7 @@ rustc_queries! {
}
/// Gets the rendered value of the specified constant or associated constant.
/// Used by rustdoc.
- query rendered_const(def_id: DefId) -> String {
+ query rendered_const(def_id: DefId) -> &'tcx String {
arena_cache
desc { |tcx| "rendering constant initializer of `{}`", tcx.def_path_str(def_id) }
cache_on_disk_if { def_id.is_local() }
@@ -1249,12 +1299,12 @@ rustc_queries! {
}
/// Given a trait `trait_id`, return all known `impl` blocks.
- query trait_impls_of(trait_id: DefId) -> ty::trait_def::TraitImpls {
+ query trait_impls_of(trait_id: DefId) -> &'tcx ty::trait_def::TraitImpls {
arena_cache
desc { |tcx| "finding trait impls of `{}`", tcx.def_path_str(trait_id) }
}
- query specialization_graph_of(trait_id: DefId) -> specialization_graph::Graph {
+ query specialization_graph_of(trait_id: DefId) -> &'tcx specialization_graph::Graph {
arena_cache
desc { |tcx| "building specialization graph of trait `{}`", tcx.def_path_str(trait_id) }
cache_on_disk_if { true }
@@ -1262,6 +1312,9 @@ rustc_queries! {
query object_safety_violations(trait_id: DefId) -> &'tcx [traits::ObjectSafetyViolation] {
desc { |tcx| "determining object safety of trait `{}`", tcx.def_path_str(trait_id) }
}
+ query check_is_object_safe(trait_id: DefId) -> bool {
+ desc { |tcx| "checking if trait `{}` is object safe", tcx.def_path_str(trait_id) }
+ }
/// Gets the ParameterEnvironment for a given item; this environment
/// will be in "user-facing" mode, meaning that it is suitable for
@@ -1381,7 +1434,7 @@ rustc_queries! {
separate_provide_extern
}
- query dependency_formats(_: ()) -> Lrc<crate::middle::dependency_format::Dependencies> {
+ query dependency_formats(_: ()) -> &'tcx Lrc<crate::middle::dependency_format::Dependencies> {
arena_cache
desc { "getting the linkage format of all dependencies" }
}
@@ -1462,6 +1515,7 @@ rustc_queries! {
desc { |tcx| "looking up whether `{}` is a default impl", tcx.def_path_str(def_id) }
cache_on_disk_if { def_id.is_local() }
separate_provide_extern
+ feedable
}
query check_well_formed(key: hir::OwnerId) -> () {
@@ -1481,7 +1535,7 @@ rustc_queries! {
// Does not include external symbols that don't have a corresponding DefId,
// like the compiler-generated `main` function and so on.
query reachable_non_generics(_: CrateNum)
- -> DefIdMap<SymbolExportInfo> {
+ -> &'tcx DefIdMap<SymbolExportInfo> {
arena_cache
desc { "looking up the exported symbols of a crate" }
separate_provide_extern
@@ -1504,7 +1558,7 @@ rustc_queries! {
/// added or removed in any upstream crate. Instead use the narrower
/// `upstream_monomorphizations_for`, `upstream_drop_glue_for`, or, even
/// better, `Instance::upstream_monomorphization()`.
- query upstream_monomorphizations(_: ()) -> DefIdMap<FxHashMap<SubstsRef<'tcx>, CrateNum>> {
+ query upstream_monomorphizations(_: ()) -> &'tcx DefIdMap<FxHashMap<SubstsRef<'tcx>, CrateNum>> {
arena_cache
desc { "collecting available upstream monomorphizations" }
}
@@ -1519,7 +1573,6 @@ rustc_queries! {
query upstream_monomorphizations_for(def_id: DefId)
-> Option<&'tcx FxHashMap<SubstsRef<'tcx>, CrateNum>>
{
- arena_cache
desc { |tcx|
"collecting available upstream monomorphizations for `{}`",
tcx.def_path_str(def_id),
@@ -1547,7 +1600,7 @@ rustc_queries! {
}
/// Returns a list of all `extern` blocks of a crate.
- query foreign_modules(_: CrateNum) -> FxHashMap<DefId, ForeignModule> {
+ query foreign_modules(_: CrateNum) -> &'tcx FxHashMap<DefId, ForeignModule> {
arena_cache
desc { "looking up the foreign modules of a linked crate" }
separate_provide_extern
@@ -1581,7 +1634,7 @@ rustc_queries! {
/// Gets the extra data to put in each output filename for a crate.
/// For example, compiling the `foo` crate with `extra-filename=-a` creates a `libfoo-b.rlib` file.
- query extra_filename(_: CrateNum) -> String {
+ query extra_filename(_: CrateNum) -> &'tcx String {
arena_cache
eval_always
desc { "looking up the extra filename for a crate" }
@@ -1589,7 +1642,7 @@ rustc_queries! {
}
/// Gets the paths where the crate came from in the file system.
- query crate_extern_paths(_: CrateNum) -> Vec<PathBuf> {
+ query crate_extern_paths(_: CrateNum) -> &'tcx Vec<PathBuf> {
arena_cache
eval_always
desc { "looking up the paths for extern crates" }
@@ -1619,16 +1672,16 @@ rustc_queries! {
/// Does lifetime resolution on items. Importantly, we can't resolve
/// lifetimes directly on things like trait methods, because of trait params.
- /// See `rustc_resolve::late::lifetimes for details.
- query resolve_lifetimes(_: hir::OwnerId) -> ResolveLifetimes {
+ /// See `rustc_resolve::late::lifetimes` for details.
+ query resolve_bound_vars(_: hir::OwnerId) -> &'tcx ResolveBoundVars {
arena_cache
desc { "resolving lifetimes" }
}
- query named_region_map(_: hir::OwnerId) ->
- Option<&'tcx FxHashMap<ItemLocalId, Region>> {
+ query named_variable_map(_: hir::OwnerId) ->
+ Option<&'tcx FxHashMap<ItemLocalId, ResolvedArg>> {
desc { "looking up a named region" }
}
- query is_late_bound_map(_: LocalDefId) -> Option<&'tcx FxIndexSet<LocalDefId>> {
+ query is_late_bound_map(_: hir::OwnerId) -> Option<&'tcx FxIndexSet<ItemLocalId>> {
desc { "testing if a region is late bound" }
}
/// For a given item's generic parameter, gets the default lifetimes to be used
@@ -1660,6 +1713,7 @@ rustc_queries! {
query visibility(def_id: DefId) -> ty::Visibility<DefId> {
desc { |tcx| "computing visibility of `{}`", tcx.def_path_str(def_id) }
separate_provide_extern
+ feedable
}
query inhabited_predicate_adt(key: DefId) -> ty::inhabitedness::InhabitedPredicate<'tcx> {
@@ -1691,7 +1745,7 @@ rustc_queries! {
desc { |tcx| "computing crate imported by `{}`", tcx.def_path_str(def_id.to_def_id()) }
}
- query lib_features(_: ()) -> LibFeatures {
+ query lib_features(_: ()) -> &'tcx LibFeatures {
arena_cache
desc { "calculating the lib features map" }
}
@@ -1699,7 +1753,7 @@ rustc_queries! {
desc { "calculating the lib features defined in a crate" }
separate_provide_extern
}
- query stability_implications(_: CrateNum) -> FxHashMap<Symbol, Symbol> {
+ query stability_implications(_: CrateNum) -> &'tcx FxHashMap<Symbol, Symbol> {
arena_cache
desc { "calculating the implications between `#[unstable]` features defined in a crate" }
separate_provide_extern
@@ -1710,14 +1764,14 @@ rustc_queries! {
separate_provide_extern
}
/// Returns the lang items defined in another crate by loading it from metadata.
- query get_lang_items(_: ()) -> LanguageItems {
+ query get_lang_items(_: ()) -> &'tcx LanguageItems {
arena_cache
eval_always
desc { "calculating the lang items map" }
}
/// Returns all diagnostic items defined in all crates.
- query all_diagnostic_items(_: ()) -> rustc_hir::diagnostic_items::DiagnosticItems {
+ query all_diagnostic_items(_: ()) -> &'tcx rustc_hir::diagnostic_items::DiagnosticItems {
arena_cache
eval_always
desc { "calculating the diagnostic items map" }
@@ -1730,7 +1784,7 @@ rustc_queries! {
}
/// Returns the diagnostic items defined in a crate.
- query diagnostic_items(_: CrateNum) -> rustc_hir::diagnostic_items::DiagnosticItems {
+ query diagnostic_items(_: CrateNum) -> &'tcx rustc_hir::diagnostic_items::DiagnosticItems {
arena_cache
desc { "calculating the diagnostic items map in a crate" }
separate_provide_extern
@@ -1740,11 +1794,11 @@ rustc_queries! {
desc { "calculating the missing lang items in a crate" }
separate_provide_extern
}
- query visible_parent_map(_: ()) -> DefIdMap<DefId> {
+ query visible_parent_map(_: ()) -> &'tcx DefIdMap<DefId> {
arena_cache
desc { "calculating the visible parent map" }
}
- query trimmed_def_paths(_: ()) -> FxHashMap<DefId, Symbol> {
+ query trimmed_def_paths(_: ()) -> &'tcx FxHashMap<DefId, Symbol> {
arena_cache
desc { "calculating trimmed def paths" }
}
@@ -1753,14 +1807,14 @@ rustc_queries! {
desc { "seeing if we're missing an `extern crate` item for this crate" }
separate_provide_extern
}
- query used_crate_source(_: CrateNum) -> Lrc<CrateSource> {
+ query used_crate_source(_: CrateNum) -> &'tcx Lrc<CrateSource> {
arena_cache
eval_always
desc { "looking at the source for a crate" }
separate_provide_extern
}
/// Returns the debugger visualizers defined for this crate.
- query debugger_visualizers(_: CrateNum) -> Vec<rustc_span::DebuggerVisualizerFile> {
+ query debugger_visualizers(_: CrateNum) -> &'tcx Vec<rustc_span::DebuggerVisualizerFile> {
arena_cache
desc { "looking up the debugger visualizers for this crate" }
separate_provide_extern
@@ -1791,14 +1845,11 @@ rustc_queries! {
query maybe_unused_trait_imports(_: ()) -> &'tcx FxIndexSet<LocalDefId> {
desc { "fetching potentially unused trait imports" }
}
- query maybe_unused_extern_crates(_: ()) -> &'tcx [(LocalDefId, Span)] {
- desc { "looking up all possibly unused extern crates" }
- }
query names_imported_by_glob_use(def_id: LocalDefId) -> &'tcx FxHashSet<Symbol> {
desc { |tcx| "finding names imported by glob use for `{}`", tcx.def_path_str(def_id.to_def_id()) }
}
- query stability_index(_: ()) -> stability::Index {
+ query stability_index(_: ()) -> &'tcx stability::Index {
arena_cache
eval_always
desc { "calculating the stability index for the local crate" }
@@ -1815,6 +1866,11 @@ rustc_queries! {
separate_provide_extern
}
+ query trait_impls_in_crate(_: CrateNum) -> &'tcx [DefId] {
+ desc { "fetching all trait impls in a crate" }
+ separate_provide_extern
+ }
+
/// The list of symbols exported from the given crate.
///
/// - All names contained in `exported_symbols(cnum)` are guaranteed to
@@ -1865,6 +1921,7 @@ rustc_queries! {
query output_filenames(_: ()) -> &'tcx Arc<OutputFilenames> {
feedable
desc { "getting output filenames" }
+ arena_cache
}
/// Do not call this query directly: invoke `normalize` instead.
@@ -2034,7 +2091,7 @@ rustc_queries! {
remap_env_constness
}
- query supported_target_features(_: CrateNum) -> FxHashMap<String, Option<Symbol>> {
+ query supported_target_features(_: CrateNum) -> &'tcx FxHashMap<String, Option<Symbol>> {
arena_cache
eval_always
desc { "looking up supported target features" }
@@ -2051,6 +2108,18 @@ rustc_queries! {
desc { "looking up enabled feature gates" }
}
+ query metadata_loader((): ()) -> &'tcx Steal<Box<rustc_session::cstore::MetadataLoaderDyn>> {
+ feedable
+ no_hash
+ desc { "raw operations for metadata file access" }
+ }
+
+ query crate_for_resolver((): ()) -> &'tcx Steal<rustc_ast::ast::Crate> {
+ feedable
+ no_hash
+ desc { "the ast before macro expansion and name resolution" }
+ }
+
/// Attempt to resolve the given `DefId` to an `Instance`, for the
/// given generics args (`SubstsRef`), returning one of:
/// * `Ok(Some(instance))` on success
@@ -2093,34 +2162,31 @@ rustc_queries! {
/// span) for an *existing* error. Therefore, it is best-effort, and may never handle
/// all of the cases that the normal `ty::Ty`-based wfcheck does. This is fine,
/// because the `ty::Ty`-based wfcheck is always run.
- query diagnostic_hir_wf_check(key: (ty::Predicate<'tcx>, traits::WellFormedLoc)) -> Option<traits::ObligationCause<'tcx>> {
+ query diagnostic_hir_wf_check(
+ key: (ty::Predicate<'tcx>, traits::WellFormedLoc)
+ ) -> &'tcx Option<traits::ObligationCause<'tcx>> {
arena_cache
eval_always
no_hash
desc { "performing HIR wf-checking for predicate `{:?}` at item `{:?}`", key.0, key.1 }
}
-
/// The list of backend features computed from CLI flags (`-Ctarget-cpu`, `-Ctarget-feature`,
/// `--target` and similar).
- query global_backend_features(_: ()) -> Vec<String> {
+ query global_backend_features(_: ()) -> &'tcx Vec<String> {
arena_cache
eval_always
desc { "computing the backend features for CLI flags" }
}
- query generator_diagnostic_data(key: DefId) -> Option<GeneratorDiagnosticData<'tcx>> {
+ query generator_diagnostic_data(key: DefId) -> &'tcx Option<GeneratorDiagnosticData<'tcx>> {
arena_cache
desc { |tcx| "looking up generator diagnostic data of `{}`", tcx.def_path_str(key) }
separate_provide_extern
}
- query permits_uninit_init(key: TyAndLayout<'tcx>) -> bool {
- desc { "checking to see if `{}` permits being left uninit", key.ty }
- }
-
- query permits_zero_init(key: TyAndLayout<'tcx>) -> bool {
- desc { "checking to see if `{}` permits being left zeroed", key.ty }
+ query check_validity_requirement(key: (ValidityRequirement, ty::ParamEnvAnd<'tcx, Ty<'tcx>>)) -> Result<bool, ty::layout::LayoutError<'tcx>> {
+ desc { "checking validity requirement for `{}`: {}", key.1.value, key.0 }
}
query compare_impl_const(
@@ -2133,4 +2199,23 @@ rustc_queries! {
desc { |tcx| "deducing parameter attributes for {}", tcx.def_path_str(def_id) }
separate_provide_extern
}
+
+ query doc_link_resolutions(def_id: DefId) -> &'tcx DocLinkResMap {
+ eval_always
+ desc { "resolutions for documentation links for a module" }
+ separate_provide_extern
+ }
+
+ query doc_link_traits_in_scope(def_id: DefId) -> &'tcx [DefId] {
+ eval_always
+ desc { "traits in scope for documentation links for a module" }
+ separate_provide_extern
+ }
+
+ /// Used in `super_combine_consts` to ICE if the type of the two consts are definitely not going to end up being
+ /// equal to eachother. This might return `Ok` even if the types are unequal, but will never return `Err` if
+ /// the types might be equal.
+ query check_tys_might_be_eq(arg: Canonical<'tcx, (ty::ParamEnv<'tcx>, Ty<'tcx>, Ty<'tcx>)>) -> Result<(), NoSolution> {
+ desc { "check whether two const param are definitely not equal to eachother"}
+ }
}
diff --git a/compiler/rustc_middle/src/thir.rs b/compiler/rustc_middle/src/thir.rs
index 5f320708c..3b11fab8c 100644
--- a/compiler/rustc_middle/src/thir.rs
+++ b/compiler/rustc_middle/src/thir.rs
@@ -20,7 +20,7 @@ use rustc_middle::mir::interpret::AllocId;
use rustc_middle::mir::{self, BinOp, BorrowKind, FakeReadCause, Field, Mutability, UnOp};
use rustc_middle::ty::adjustment::PointerCast;
use rustc_middle::ty::subst::SubstsRef;
-use rustc_middle::ty::{self, AdtDef, Ty, UpvarSubsts};
+use rustc_middle::ty::{self, AdtDef, FnSig, Ty, UpvarSubsts};
use rustc_middle::ty::{CanonicalUserType, CanonicalUserTypeAnnotation};
use rustc_span::def_id::LocalDefId;
use rustc_span::{sym, Span, Symbol, DUMMY_SP};
@@ -32,7 +32,12 @@ use std::ops::Index;
pub mod visit;
macro_rules! thir_with_elements {
- ($($name:ident: $id:ty => $value:ty => $format:literal,)*) => {
+ (
+ $($field_name:ident: $field_ty:ty,)*
+
+ @elements:
+ $($name:ident: $id:ty => $value:ty => $format:literal,)*
+ ) => {
$(
newtype_index! {
#[derive(HashStable)]
@@ -47,14 +52,20 @@ macro_rules! thir_with_elements {
#[derive(Debug, HashStable, Clone)]
pub struct Thir<'tcx> {
$(
+ pub $field_name: $field_ty,
+ )*
+ $(
pub $name: IndexVec<$id, $value>,
)*
}
impl<'tcx> Thir<'tcx> {
- pub fn new() -> Thir<'tcx> {
+ pub fn new($($field_name: $field_ty,)*) -> Thir<'tcx> {
Thir {
$(
+ $field_name,
+ )*
+ $(
$name: IndexVec::new(),
)*
}
@@ -75,6 +86,9 @@ macro_rules! thir_with_elements {
pub const UPVAR_ENV_PARAM: ParamId = ParamId::from_u32(0);
thir_with_elements! {
+ body_type: BodyTy<'tcx>,
+
+@elements:
arms: ArmId => Arm<'tcx> => "a{}",
blocks: BlockId => Block => "b{}",
exprs: ExprId => Expr<'tcx> => "e{}",
@@ -82,6 +96,12 @@ thir_with_elements! {
params: ParamId => Param<'tcx> => "p{}",
}
+#[derive(Debug, HashStable, Clone)]
+pub enum BodyTy<'tcx> {
+ Const(Ty<'tcx>),
+ Fn(FnSig<'tcx>),
+}
+
/// Description of a type-checked function parameter.
#[derive(Clone, Debug, HashStable)]
pub struct Param<'tcx> {
@@ -217,6 +237,9 @@ pub struct LocalVarId(pub hir::HirId);
/// A THIR expression.
#[derive(Clone, Debug, HashStable)]
pub struct Expr<'tcx> {
+ /// kind of expression
+ pub kind: ExprKind<'tcx>,
+
/// The type of this expression
pub ty: Ty<'tcx>,
@@ -226,9 +249,6 @@ pub struct Expr<'tcx> {
/// span of the expression in the source
pub span: Span,
-
- /// kind of expression
- pub kind: ExprKind<'tcx>,
}
#[derive(Clone, Debug, HashStable)]
diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs
index d00b26a5a..6231dd9b6 100644
--- a/compiler/rustc_middle/src/traits/mod.rs
+++ b/compiler/rustc_middle/src/traits/mod.rs
@@ -5,6 +5,7 @@
mod chalk;
pub mod query;
pub mod select;
+pub mod solve;
pub mod specialization_graph;
mod structural_impls;
pub mod util;
@@ -18,7 +19,8 @@ use crate::ty::{self, AdtKind, Ty, TyCtxt};
use rustc_data_structures::sync::Lrc;
use rustc_errors::{Applicability, Diagnostic};
use rustc_hir as hir;
-use rustc_hir::def_id::{DefId, LocalDefId};
+use rustc_hir::def_id::DefId;
+use rustc_span::def_id::{LocalDefId, CRATE_DEF_ID};
use rustc_span::symbol::Symbol;
use rustc_span::{Span, DUMMY_SP};
use smallvec::SmallVec;
@@ -36,7 +38,7 @@ pub use self::chalk::{ChalkEnvironmentAndGoal, RustInterner as ChalkRustInterner
/// Depending on the stage of compilation, we want projection to be
/// more or less conservative.
-#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, HashStable)]
+#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, HashStable, Encodable, Decodable)]
pub enum Reveal {
/// At type-checking time, we refuse to project any associated
/// type that is marked `default`. Non-`default` ("final") types
@@ -89,7 +91,8 @@ pub enum Reveal {
///
/// We do not want to intern this as there are a lot of obligation causes which
/// only live for a short period of time.
-#[derive(Clone, Debug, PartialEq, Eq, Lift)]
+#[derive(Clone, Debug, PartialEq, Eq, Lift, HashStable, TyEncodable, TyDecodable)]
+#[derive(TypeVisitable, TypeFoldable)]
pub struct ObligationCause<'tcx> {
pub span: Span,
@@ -99,7 +102,7 @@ pub struct ObligationCause<'tcx> {
/// (in particular, closures can add new assumptions). See the
/// field `region_obligations` of the `FulfillmentContext` for more
/// information.
- pub body_id: hir::HirId,
+ pub body_id: LocalDefId,
code: InternedObligationCauseCode<'tcx>,
}
@@ -120,13 +123,13 @@ impl<'tcx> ObligationCause<'tcx> {
#[inline]
pub fn new(
span: Span,
- body_id: hir::HirId,
+ body_id: LocalDefId,
code: ObligationCauseCode<'tcx>,
) -> ObligationCause<'tcx> {
ObligationCause { span, body_id, code: code.into() }
}
- pub fn misc(span: Span, body_id: hir::HirId) -> ObligationCause<'tcx> {
+ pub fn misc(span: Span, body_id: LocalDefId) -> ObligationCause<'tcx> {
ObligationCause::new(span, body_id, MiscObligation)
}
@@ -137,7 +140,7 @@ impl<'tcx> ObligationCause<'tcx> {
#[inline(always)]
pub fn dummy_with_span(span: Span) -> ObligationCause<'tcx> {
- ObligationCause { span, body_id: hir::CRATE_HIR_ID, code: Default::default() }
+ ObligationCause { span, body_id: CRATE_DEF_ID, code: Default::default() }
}
pub fn span(&self) -> Span {
@@ -196,14 +199,16 @@ impl<'tcx> ObligationCause<'tcx> {
}
}
-#[derive(Clone, Debug, PartialEq, Eq, Hash, Lift)]
+#[derive(Clone, Debug, PartialEq, Eq, Hash, Lift, HashStable, TyEncodable, TyDecodable)]
+#[derive(TypeVisitable, TypeFoldable)]
pub struct UnifyReceiverContext<'tcx> {
pub assoc_item: ty::AssocItem,
pub param_env: ty::ParamEnv<'tcx>,
pub substs: SubstsRef<'tcx>,
}
-#[derive(Clone, PartialEq, Eq, Hash, Lift, Default)]
+#[derive(Clone, PartialEq, Eq, Hash, Lift, Default, HashStable)]
+#[derive(TypeVisitable, TypeFoldable, TyEncodable, TyDecodable)]
pub struct InternedObligationCauseCode<'tcx> {
/// `None` for `ObligationCauseCode::MiscObligation` (a common case, occurs ~60% of
/// the time). `Some` otherwise.
@@ -238,7 +243,8 @@ impl<'tcx> std::ops::Deref for InternedObligationCauseCode<'tcx> {
}
}
-#[derive(Clone, Debug, PartialEq, Eq, Hash, Lift)]
+#[derive(Clone, Debug, PartialEq, Eq, Hash, Lift, HashStable, TyEncodable, TyDecodable)]
+#[derive(TypeVisitable, TypeFoldable)]
pub enum ObligationCauseCode<'tcx> {
/// Not well classified or should be obvious from the span.
MiscObligation,
@@ -446,7 +452,8 @@ pub enum ObligationCauseCode<'tcx> {
/// This information is used to obtain an `hir::Ty`, which
/// we can walk in order to obtain precise spans for any
/// 'nested' types (e.g. `Foo` in `Option<Foo>`).
-#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, HashStable)]
+#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, HashStable, Encodable, Decodable)]
+#[derive(TypeVisitable, TypeFoldable)]
pub enum WellFormedLoc {
/// Use the type of the provided definition.
Ty(LocalDefId),
@@ -463,10 +470,17 @@ pub enum WellFormedLoc {
},
}
-#[derive(Clone, Debug, PartialEq, Eq, Hash, Lift)]
+#[derive(Clone, Debug, PartialEq, Eq, Hash, Lift, HashStable, TyEncodable, TyDecodable)]
+#[derive(TypeVisitable, TypeFoldable)]
pub struct ImplDerivedObligationCause<'tcx> {
pub derived: DerivedObligationCause<'tcx>,
- pub impl_def_id: DefId,
+ /// The `DefId` of the `impl` that gave rise to the `derived` obligation.
+ /// If the `derived` obligation arose from a trait alias, which conceptually has a synthetic impl,
+ /// then this will be the `DefId` of that trait alias. Care should therefore be taken to handle
+ /// that exceptional case where appropriate.
+ pub impl_or_alias_def_id: DefId,
+ /// The index of the derived predicate in the parent impl's predicates.
+ pub impl_def_predicate_index: Option<usize>,
pub span: Span,
}
@@ -517,7 +531,8 @@ impl<'tcx> ty::Lift<'tcx> for StatementAsExpression {
}
}
-#[derive(Clone, Debug, PartialEq, Eq, Hash, Lift)]
+#[derive(Clone, Debug, PartialEq, Eq, Hash, Lift, HashStable, TyEncodable, TyDecodable)]
+#[derive(TypeVisitable, TypeFoldable)]
pub struct MatchExpressionArmCause<'tcx> {
pub arm_block_id: Option<hir::HirId>,
pub arm_ty: Ty<'tcx>,
@@ -533,7 +548,7 @@ pub struct MatchExpressionArmCause<'tcx> {
}
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
-#[derive(Lift, TypeFoldable, TypeVisitable)]
+#[derive(Lift, TypeFoldable, TypeVisitable, HashStable, TyEncodable, TyDecodable)]
pub struct IfExpressionCause<'tcx> {
pub then_id: hir::HirId,
pub else_id: hir::HirId,
@@ -543,7 +558,8 @@ pub struct IfExpressionCause<'tcx> {
pub opt_suggest_box_span: Option<Span>,
}
-#[derive(Clone, Debug, PartialEq, Eq, Hash, Lift)]
+#[derive(Clone, Debug, PartialEq, Eq, Hash, Lift, HashStable, TyEncodable, TyDecodable)]
+#[derive(TypeVisitable, TypeFoldable)]
pub struct DerivedObligationCause<'tcx> {
/// The trait predicate of the parent obligation that led to the
/// current obligation. Note that only trait obligations lead to
diff --git a/compiler/rustc_middle/src/traits/query.rs b/compiler/rustc_middle/src/traits/query.rs
index 615154a55..c4f871875 100644
--- a/compiler/rustc_middle/src/traits/query.rs
+++ b/compiler/rustc_middle/src/traits/query.rs
@@ -14,7 +14,7 @@ use rustc_span::source_map::Span;
pub mod type_op {
use crate::ty::fold::TypeFoldable;
- use crate::ty::{Predicate, Ty, UserType};
+ use crate::ty::{Predicate, Ty, TyCtxt, UserType};
use std::fmt;
#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, HashStable, Lift)]
@@ -64,7 +64,7 @@ pub mod type_op {
impl<'tcx, T> Normalize<T>
where
- T: fmt::Debug + TypeFoldable<'tcx>,
+ T: fmt::Debug + TypeFoldable<TyCtxt<'tcx>>,
{
pub fn new(value: T) -> Self {
Self { value }
diff --git a/compiler/rustc_middle/src/traits/solve.rs b/compiler/rustc_middle/src/traits/solve.rs
new file mode 100644
index 000000000..bd43867a3
--- /dev/null
+++ b/compiler/rustc_middle/src/traits/solve.rs
@@ -0,0 +1,66 @@
+use std::ops::ControlFlow;
+
+use rustc_data_structures::intern::Interned;
+
+use crate::infer::canonical::QueryRegionConstraints;
+use crate::ty::{
+ FallibleTypeFolder, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeVisitable, TypeVisitor,
+};
+
+#[derive(Debug, PartialEq, Eq, Copy, Clone, Hash)]
+pub struct ExternalConstraints<'tcx>(pub(crate) Interned<'tcx, ExternalConstraintsData<'tcx>>);
+
+impl<'tcx> std::ops::Deref for ExternalConstraints<'tcx> {
+ type Target = ExternalConstraintsData<'tcx>;
+
+ fn deref(&self) -> &Self::Target {
+ &*self.0
+ }
+}
+
+/// Additional constraints returned on success.
+#[derive(Debug, PartialEq, Eq, Clone, Hash, Default, TypeFoldable, TypeVisitable)]
+pub struct ExternalConstraintsData<'tcx> {
+ // FIXME: implement this.
+ pub region_constraints: QueryRegionConstraints<'tcx>,
+ pub opaque_types: Vec<(Ty<'tcx>, Ty<'tcx>)>,
+}
+
+// FIXME: Having to clone `region_constraints` for folding feels bad and
+// probably isn't great wrt performance.
+//
+// Not sure how to fix this, maybe we should also intern `opaque_types` and
+// `region_constraints` here or something.
+impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for ExternalConstraints<'tcx> {
+ fn try_fold_with<F: FallibleTypeFolder<TyCtxt<'tcx>>>(
+ self,
+ folder: &mut F,
+ ) -> Result<Self, F::Error> {
+ Ok(FallibleTypeFolder::interner(folder).mk_external_constraints(ExternalConstraintsData {
+ region_constraints: self.region_constraints.clone().try_fold_with(folder)?,
+ opaque_types: self
+ .opaque_types
+ .iter()
+ .map(|opaque| opaque.try_fold_with(folder))
+ .collect::<Result<_, F::Error>>()?,
+ }))
+ }
+
+ fn fold_with<F: TypeFolder<TyCtxt<'tcx>>>(self, folder: &mut F) -> Self {
+ TypeFolder::interner(folder).mk_external_constraints(ExternalConstraintsData {
+ region_constraints: self.region_constraints.clone().fold_with(folder),
+ opaque_types: self.opaque_types.iter().map(|opaque| opaque.fold_with(folder)).collect(),
+ })
+ }
+}
+
+impl<'tcx> TypeVisitable<TyCtxt<'tcx>> for ExternalConstraints<'tcx> {
+ fn visit_with<V: TypeVisitor<TyCtxt<'tcx>>>(
+ &self,
+ visitor: &mut V,
+ ) -> std::ops::ControlFlow<V::BreakTy> {
+ self.region_constraints.visit_with(visitor)?;
+ self.opaque_types.visit_with(visitor)?;
+ ControlFlow::Continue(())
+ }
+}
diff --git a/compiler/rustc_middle/src/traits/specialization_graph.rs b/compiler/rustc_middle/src/traits/specialization_graph.rs
index aad5b2fbe..c016f7227 100644
--- a/compiler/rustc_middle/src/traits/specialization_graph.rs
+++ b/compiler/rustc_middle/src/traits/specialization_graph.rs
@@ -1,6 +1,6 @@
use crate::error::StrictCoherenceNeedsNegativeCoherence;
use crate::ty::fast_reject::SimplifiedType;
-use crate::ty::visit::TypeVisitable;
+use crate::ty::visit::TypeVisitableExt;
use crate::ty::{self, TyCtxt};
use rustc_data_structures::fx::FxIndexMap;
use rustc_errors::ErrorGuaranteed;
@@ -133,11 +133,7 @@ impl Node {
///
/// If this returns `None`, the item can potentially still be found in
/// parents of this node.
- pub fn item<'tcx>(
- &self,
- tcx: TyCtxt<'tcx>,
- trait_item_def_id: DefId,
- ) -> Option<&'tcx ty::AssocItem> {
+ pub fn item<'tcx>(&self, tcx: TyCtxt<'tcx>, trait_item_def_id: DefId) -> Option<ty::AssocItem> {
match *self {
Node::Trait(_) => Some(tcx.associated_item(trait_item_def_id)),
Node::Impl(impl_def_id) => {
@@ -239,7 +235,7 @@ impl<'tcx> Ancestors<'tcx> {
}
}
- Some(LeafDef { item: *item, defining_node: node, finalizing_node })
+ Some(LeafDef { item, defining_node: node, finalizing_node })
} else {
// Item not mentioned. This "finalizes" any defaulted item provided by an ancestor.
finalizing_node = Some(node);
@@ -263,7 +259,7 @@ pub fn ancestors(
if let Some(reported) = specialization_graph.has_errored {
Err(reported)
- } else if let Err(reported) = tcx.type_of(start_from_impl).error_reported() {
+ } else if let Err(reported) = tcx.type_of(start_from_impl).subst_identity().error_reported() {
Err(reported)
} else {
Ok(Ancestors {
diff --git a/compiler/rustc_middle/src/ty/_match.rs b/compiler/rustc_middle/src/ty/_match.rs
index b9c5a4e0d..df9aa765d 100644
--- a/compiler/rustc_middle/src/ty/_match.rs
+++ b/compiler/rustc_middle/src/ty/_match.rs
@@ -89,9 +89,7 @@ impl<'tcx> TypeRelation<'tcx> for Match<'tcx> {
Err(TypeError::Sorts(relate::expected_found(self, a, b)))
}
- (&ty::Error(guar), _) | (_, &ty::Error(guar)) => {
- Ok(self.tcx().ty_error_with_guaranteed(guar))
- }
+ (&ty::Error(guar), _) | (_, &ty::Error(guar)) => Ok(self.tcx().ty_error(guar)),
_ => relate::super_relate_tys(self, a, b),
}
diff --git a/compiler/rustc_middle/src/ty/abstract_const.rs b/compiler/rustc_middle/src/ty/abstract_const.rs
index 5de758ad9..f889ce827 100644
--- a/compiler/rustc_middle/src/ty/abstract_const.rs
+++ b/compiler/rustc_middle/src/ty/abstract_const.rs
@@ -1,7 +1,7 @@
//! A subset of a mir body used for const evaluatability checking.
use crate::ty::{
self, Const, EarlyBinder, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable,
- TypeVisitable,
+ TypeVisitableExt,
};
use rustc_errors::ErrorGuaranteed;
use rustc_hir::def_id::DefId;
@@ -48,13 +48,13 @@ impl<'tcx> TyCtxt<'tcx> {
Ok(ac?.map(|ac| EarlyBinder(ac)))
}
- pub fn expand_abstract_consts<T: TypeFoldable<'tcx>>(self, ac: T) -> T {
+ pub fn expand_abstract_consts<T: TypeFoldable<TyCtxt<'tcx>>>(self, ac: T) -> T {
struct Expander<'tcx> {
tcx: TyCtxt<'tcx>,
}
- impl<'tcx> TypeFolder<'tcx> for Expander<'tcx> {
- fn tcx(&self) -> TyCtxt<'tcx> {
+ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for Expander<'tcx> {
+ fn interner(&self) -> TyCtxt<'tcx> {
self.tcx
}
fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
diff --git a/compiler/rustc_middle/src/ty/adt.rs b/compiler/rustc_middle/src/ty/adt.rs
index d3d667f68..ec21030b3 100644
--- a/compiler/rustc_middle/src/ty/adt.rs
+++ b/compiler/rustc_middle/src/ty/adt.rs
@@ -54,7 +54,7 @@ bitflags! {
/// The definition of a user-defined type, e.g., a `struct`, `enum`, or `union`.
///
-/// These are all interned (by `alloc_adt_def`) into the global arena.
+/// These are all interned (by `mk_adt_def`) into the global arena.
///
/// The initialism *ADT* stands for an [*algebraic data type (ADT)*][adt].
/// This is slightly wrong because `union`s are not ADTs.
@@ -188,7 +188,7 @@ impl<'tcx> AdtDef<'tcx> {
}
}
-#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash, TyEncodable, TyDecodable)]
+#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash, HashStable, TyEncodable, TyDecodable)]
pub enum AdtKind {
Struct,
Union,
@@ -406,6 +406,7 @@ impl<'tcx> AdtDef<'tcx> {
}
/// Return the index of `VariantDef` given a variant id.
+ #[inline]
pub fn variant_index_with_id(self, vid: DefId) -> VariantIdx {
self.variants()
.iter_enumerated()
diff --git a/compiler/rustc_middle/src/ty/assoc.rs b/compiler/rustc_middle/src/ty/assoc.rs
index bb7fba3ee..f1a9e50a4 100644
--- a/compiler/rustc_middle/src/ty/assoc.rs
+++ b/compiler/rustc_middle/src/ty/assoc.rs
@@ -79,11 +79,11 @@ impl AssocItem {
// late-bound regions, and we don't want method signatures to show up
// `as for<'r> fn(&'r MyType)`. Pretty-printing handles late-bound
// regions just fine, showing `fn(&MyType)`.
- tcx.fn_sig(self.def_id).skip_binder().to_string()
+ tcx.fn_sig(self.def_id).subst_identity().skip_binder().to_string()
}
ty::AssocKind::Type => format!("type {};", self.name),
ty::AssocKind::Const => {
- format!("const {}: {:?};", self.name, tcx.type_of(self.def_id))
+ format!("const {}: {:?};", self.name, tcx.type_of(self.def_id).subst_identity())
}
}
}
@@ -129,13 +129,13 @@ impl std::fmt::Display for AssocKind {
/// it is relatively expensive. Instead, items are indexed by `Symbol` and hygienic comparison is
/// done only on items with the same name.
#[derive(Debug, Clone, PartialEq, HashStable)]
-pub struct AssocItems<'tcx> {
- pub(super) items: SortedIndexMultiMap<u32, Symbol, &'tcx ty::AssocItem>,
+pub struct AssocItems {
+ items: SortedIndexMultiMap<u32, Symbol, ty::AssocItem>,
}
-impl<'tcx> AssocItems<'tcx> {
+impl AssocItems {
/// Constructs an `AssociatedItems` map from a series of `ty::AssocItem`s in definition order.
- pub fn new(items_in_def_order: impl IntoIterator<Item = &'tcx ty::AssocItem>) -> Self {
+ pub fn new(items_in_def_order: impl IntoIterator<Item = ty::AssocItem>) -> Self {
let items = items_in_def_order.into_iter().map(|item| (item.name, item)).collect();
AssocItems { items }
}
@@ -145,7 +145,7 @@ impl<'tcx> AssocItems<'tcx> {
/// New code should avoid relying on definition order. If you need a particular associated item
/// for a known trait, make that trait a lang item instead of indexing this array.
pub fn in_definition_order(&self) -> impl '_ + Iterator<Item = &ty::AssocItem> {
- self.items.iter().map(|(_, v)| *v)
+ self.items.iter().map(|(_, v)| v)
}
pub fn len(&self) -> usize {
@@ -157,7 +157,7 @@ impl<'tcx> AssocItems<'tcx> {
&self,
name: Symbol,
) -> impl '_ + Iterator<Item = &ty::AssocItem> {
- self.items.get_by_key(name).copied()
+ self.items.get_by_key(name)
}
/// Returns the associated item with the given name and `AssocKind`, if one exists.
diff --git a/compiler/rustc_middle/src/ty/closure.rs b/compiler/rustc_middle/src/ty/closure.rs
index 6ade8935f..dc2bd54b7 100644
--- a/compiler/rustc_middle/src/ty/closure.rs
+++ b/compiler/rustc_middle/src/ty/closure.rs
@@ -5,10 +5,10 @@ use crate::{mir, ty};
use std::fmt::Write;
-use hir::LangItem;
use rustc_data_structures::fx::{FxHashMap, FxIndexMap};
-use rustc_hir as hir;
use rustc_hir::def_id::{DefId, LocalDefId};
+use rustc_hir::{self as hir, LangItem};
+use rustc_span::symbol::Ident;
use rustc_span::{Span, Symbol};
use super::{Ty, TyCtxt};
@@ -129,6 +129,9 @@ impl<'tcx> ClosureKind {
#[derive(PartialEq, Clone, Debug, TyEncodable, TyDecodable, HashStable)]
#[derive(TypeFoldable, TypeVisitable)]
pub struct CapturedPlace<'tcx> {
+ /// Name and span where the binding happens.
+ pub var_ident: Ident,
+
/// The `Place` that is captured.
pub place: HirPlace<'tcx>,
@@ -148,12 +151,8 @@ impl<'tcx> CapturedPlace<'tcx> {
}
/// Returns a symbol of the captured upvar, which looks like `name__field1__field2`.
- fn to_symbol(&self, tcx: TyCtxt<'tcx>) -> Symbol {
- let hir_id = match self.place.base {
- HirPlaceBase::Upvar(upvar_id) => upvar_id.var_path.hir_id,
- base => bug!("Expected an upvar, found {:?}", base),
- };
- let mut symbol = tcx.hir().name(hir_id).as_str().to_string();
+ pub fn to_symbol(&self) -> Symbol {
+ let mut symbol = self.var_ident.to_string();
let mut ty = self.place.base_ty;
for proj in self.place.projections.iter() {
@@ -169,11 +168,7 @@ impl<'tcx> CapturedPlace<'tcx> {
.unwrap();
}
ty => {
- span_bug!(
- self.get_capture_kind_span(tcx),
- "Unexpected type {:?} for `Field` projection",
- ty
- )
+ bug!("Unexpected type {:?} for `Field` projection", ty)
}
},
@@ -238,10 +233,39 @@ impl<'tcx> CapturedPlace<'tcx> {
}
}
-fn symbols_for_closure_captures(tcx: TyCtxt<'_>, def_id: (LocalDefId, LocalDefId)) -> Vec<Symbol> {
- let typeck_results = tcx.typeck(def_id.0);
- let captures = typeck_results.closure_min_captures_flattened(def_id.1);
- captures.into_iter().map(|captured_place| captured_place.to_symbol(tcx)).collect()
+#[derive(Copy, Clone, Debug, HashStable)]
+pub struct ClosureTypeInfo<'tcx> {
+ user_provided_sig: ty::CanonicalPolyFnSig<'tcx>,
+ captures: &'tcx [&'tcx ty::CapturedPlace<'tcx>],
+ kind_origin: Option<&'tcx (Span, HirPlace<'tcx>)>,
+}
+
+fn closure_typeinfo<'tcx>(tcx: TyCtxt<'tcx>, def: LocalDefId) -> ClosureTypeInfo<'tcx> {
+ debug_assert!(tcx.is_closure(def.to_def_id()));
+ let typeck_results = tcx.typeck(def);
+ let user_provided_sig = typeck_results.user_provided_sigs[&def];
+ let captures = typeck_results.closure_min_captures_flattened(def);
+ let captures = tcx.arena.alloc_from_iter(captures);
+ let hir_id = tcx.hir().local_def_id_to_hir_id(def);
+ let kind_origin = typeck_results.closure_kind_origins().get(hir_id);
+ ClosureTypeInfo { user_provided_sig, captures, kind_origin }
+}
+
+impl<'tcx> TyCtxt<'tcx> {
+ pub fn closure_kind_origin(self, def_id: LocalDefId) -> Option<&'tcx (Span, HirPlace<'tcx>)> {
+ self.closure_typeinfo(def_id).kind_origin
+ }
+
+ pub fn closure_user_provided_sig(self, def_id: LocalDefId) -> ty::CanonicalPolyFnSig<'tcx> {
+ self.closure_typeinfo(def_id).user_provided_sig
+ }
+
+ pub fn closure_captures(self, def_id: LocalDefId) -> &'tcx [&'tcx ty::CapturedPlace<'tcx>] {
+ if !self.is_closure(def_id.to_def_id()) {
+ return &[];
+ };
+ self.closure_typeinfo(def_id).captures
+ }
}
/// Return true if the `proj_possible_ancestor` represents an ancestor path
@@ -434,5 +458,5 @@ impl BorrowKind {
}
pub fn provide(providers: &mut ty::query::Providers) {
- *providers = ty::query::Providers { symbols_for_closure_captures, ..*providers }
+ *providers = ty::query::Providers { closure_typeinfo, ..*providers }
}
diff --git a/compiler/rustc_middle/src/ty/codec.rs b/compiler/rustc_middle/src/ty/codec.rs
index 8cc8286c1..3ce80e06a 100644
--- a/compiler/rustc_middle/src/ty/codec.rs
+++ b/compiler/rustc_middle/src/ty/codec.rs
@@ -157,6 +157,14 @@ impl<'tcx, E: TyEncoder<I = TyCtxt<'tcx>>> Encodable<E> for AllocId {
}
}
+impl<'tcx, E: TyEncoder<I = TyCtxt<'tcx>>> Encodable<E> for ty::ParamEnv<'tcx> {
+ fn encode(&self, e: &mut E) {
+ self.caller_bounds().encode(e);
+ self.reveal().encode(e);
+ self.constness().encode(e);
+ }
+}
+
#[inline]
fn decode_arena_allocable<
'tcx,
@@ -199,7 +207,7 @@ impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> Decodable<D> for Ty<'tcx> {
})
} else {
let tcx = decoder.interner();
- tcx.mk_ty(rustc_type_ir::TyKind::decode(decoder))
+ tcx.mk_ty_from_kind(rustc_type_ir::TyKind::decode(decoder))
}
}
}
@@ -236,7 +244,7 @@ impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> Decodable<D> for SubstsRef<'tcx> {
fn decode(decoder: &mut D) -> Self {
let len = decoder.read_usize();
let tcx = decoder.interner();
- tcx.mk_substs(
+ tcx.mk_substs_from_iter(
(0..len).map::<ty::subst::GenericArg<'tcx>, _>(|_| Decodable::decode(decoder)),
)
}
@@ -246,7 +254,7 @@ impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> Decodable<D> for mir::Place<'tcx> {
fn decode(decoder: &mut D) -> Self {
let local: mir::Local = Decodable::decode(decoder);
let len = decoder.read_usize();
- let projection = decoder.interner().mk_place_elems(
+ let projection = decoder.interner().mk_place_elems_from_iter(
(0..len).map::<mir::PlaceElem<'tcx>, _>(|_| Decodable::decode(decoder)),
);
mir::Place { local, projection }
@@ -255,16 +263,16 @@ impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> Decodable<D> for mir::Place<'tcx> {
impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> Decodable<D> for ty::Region<'tcx> {
fn decode(decoder: &mut D) -> Self {
- decoder.interner().mk_region(Decodable::decode(decoder))
+ decoder.interner().mk_region_from_kind(Decodable::decode(decoder))
}
}
impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> Decodable<D> for CanonicalVarInfos<'tcx> {
fn decode(decoder: &mut D) -> Self {
let len = decoder.read_usize();
- let interned: Vec<CanonicalVarInfo<'tcx>> =
- (0..len).map(|_| Decodable::decode(decoder)).collect();
- decoder.interner().intern_canonical_var_infos(interned.as_slice())
+ decoder.interner().mk_canonical_var_infos_from_iter(
+ (0..len).map::<CanonicalVarInfo<'tcx>, _>(|_| Decodable::decode(decoder)),
+ )
}
}
@@ -280,8 +288,17 @@ impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> Decodable<D> for ty::SymbolName<'tcx>
}
}
+impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> Decodable<D> for ty::ParamEnv<'tcx> {
+ fn decode(d: &mut D) -> Self {
+ let caller_bounds = Decodable::decode(d);
+ let reveal = Decodable::decode(d);
+ let constness = Decodable::decode(d);
+ ty::ParamEnv::new(caller_bounds, reveal, constness)
+ }
+}
+
macro_rules! impl_decodable_via_ref {
- ($($t:ty),+) => {
+ ($($t:ty,)+) => {
$(impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> Decodable<D> for $t {
fn decode(decoder: &mut D) -> Self {
RefDecodable::decode(decoder)
@@ -293,7 +310,9 @@ macro_rules! impl_decodable_via_ref {
impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> RefDecodable<'tcx, D> for ty::List<Ty<'tcx>> {
fn decode(decoder: &mut D) -> &'tcx Self {
let len = decoder.read_usize();
- decoder.interner().mk_type_list((0..len).map::<Ty<'tcx>, _>(|_| Decodable::decode(decoder)))
+ decoder
+ .interner()
+ .mk_type_list_from_iter((0..len).map::<Ty<'tcx>, _>(|_| Decodable::decode(decoder)))
}
}
@@ -302,7 +321,7 @@ impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> RefDecodable<'tcx, D>
{
fn decode(decoder: &mut D) -> &'tcx Self {
let len = decoder.read_usize();
- decoder.interner().mk_poly_existential_predicates(
+ decoder.interner().mk_poly_existential_predicates_from_iter(
(0..len).map::<ty::Binder<'tcx, _>, _>(|_| Decodable::decode(decoder)),
)
}
@@ -325,13 +344,13 @@ impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> RefDecodable<'tcx, D> for [ty::ValTre
impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> Decodable<D> for ConstAllocation<'tcx> {
fn decode(decoder: &mut D) -> Self {
- decoder.interner().intern_const_alloc(Decodable::decode(decoder))
+ decoder.interner().mk_const_alloc(Decodable::decode(decoder))
}
}
impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> Decodable<D> for AdtDef<'tcx> {
fn decode(decoder: &mut D) -> Self {
- decoder.interner().intern_adt_def(Decodable::decode(decoder))
+ decoder.interner().mk_adt_def_from_data(Decodable::decode(decoder))
}
}
@@ -358,7 +377,7 @@ impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> RefDecodable<'tcx, D>
{
fn decode(decoder: &mut D) -> &'tcx Self {
let len = decoder.read_usize();
- decoder.interner().mk_bound_variable_kinds(
+ decoder.interner().mk_bound_variable_kinds_from_iter(
(0..len).map::<ty::BoundVariableKind, _>(|_| Decodable::decode(decoder)),
)
}
@@ -367,9 +386,18 @@ impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> RefDecodable<'tcx, D>
impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> RefDecodable<'tcx, D> for ty::List<ty::Const<'tcx>> {
fn decode(decoder: &mut D) -> &'tcx Self {
let len = decoder.read_usize();
- decoder
- .interner()
- .mk_const_list((0..len).map::<ty::Const<'tcx>, _>(|_| Decodable::decode(decoder)))
+ decoder.interner().mk_const_list_from_iter(
+ (0..len).map::<ty::Const<'tcx>, _>(|_| Decodable::decode(decoder)),
+ )
+ }
+}
+
+impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> RefDecodable<'tcx, D> for ty::List<ty::Predicate<'tcx>> {
+ fn decode(decoder: &mut D) -> &'tcx Self {
+ let len = decoder.read_usize();
+ decoder.interner().mk_predicates_from_iter(
+ (0..len).map::<ty::Predicate<'tcx>, _>(|_| Decodable::decode(decoder)),
+ )
}
}
@@ -382,7 +410,8 @@ impl_decodable_via_ref! {
&'tcx mir::UnsafetyCheckResult,
&'tcx mir::BorrowCheckResult<'tcx>,
&'tcx mir::coverage::CodeRegion,
- &'tcx ty::List<ty::BoundVariableKind>
+ &'tcx ty::List<ty::BoundVariableKind>,
+ &'tcx ty::List<ty::Predicate<'tcx>>,
}
#[macro_export]
@@ -519,6 +548,8 @@ macro_rules! impl_binder_encode_decode {
impl_binder_encode_decode! {
&'tcx ty::List<Ty<'tcx>>,
ty::FnSig<'tcx>,
+ ty::Predicate<'tcx>,
+ ty::TraitPredicate<'tcx>,
ty::ExistentialPredicate<'tcx>,
ty::TraitRef<'tcx>,
Vec<ty::GeneratorInteriorTypeCause<'tcx>>,
diff --git a/compiler/rustc_middle/src/ty/consts.rs b/compiler/rustc_middle/src/ty/consts.rs
index 65cbac3e8..527ec9f6e 100644
--- a/compiler/rustc_middle/src/ty/consts.rs
+++ b/compiler/rustc_middle/src/ty/consts.rs
@@ -1,7 +1,9 @@
+use crate::middle::resolve_bound_vars as rbv;
use crate::mir::interpret::LitToConstInput;
use crate::ty::{self, DefIdTree, InternalSubsts, ParamEnv, ParamEnvAnd, Ty, TyCtxt};
use rustc_data_structures::intern::Interned;
use rustc_hir as hir;
+use rustc_hir::def::{DefKind, Res};
use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_macros::HashStable;
use std::fmt;
@@ -14,7 +16,7 @@ pub use int::*;
pub use kind::*;
pub use valtree::*;
-/// Use this rather than `ConstData, whenever possible.
+/// Use this rather than `ConstData`, whenever possible.
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, HashStable)]
#[rustc_pass_by_value]
pub struct Const<'tcx>(pub(super) Interned<'tcx, ConstData<'tcx>>);
@@ -71,7 +73,10 @@ impl<'tcx> Const<'tcx> {
let expr = &tcx.hir().body(body_id).value;
debug!(?expr);
- let ty = tcx.type_of(def.def_id_for_type_of());
+ let ty = tcx
+ .type_of(def.def_id_for_type_of())
+ .no_bound_vars()
+ .expect("const parameter types cannot be generic");
match Self::try_eval_lit_or_param(tcx, ty, expr) {
Some(v) => v,
@@ -125,16 +130,30 @@ impl<'tcx> Const<'tcx> {
}
}
- use hir::{def::DefKind::ConstParam, def::Res, ExprKind, Path, QPath};
match expr.kind {
- ExprKind::Path(QPath::Resolved(_, &Path { res: Res::Def(ConstParam, def_id), .. })) => {
- // Find the name and index of the const parameter by indexing the generics of
- // the parent item and construct a `ParamConst`.
- let item_def_id = tcx.parent(def_id);
- let generics = tcx.generics_of(item_def_id);
- let index = generics.param_def_id_to_index[&def_id];
- let name = tcx.item_name(def_id);
- Some(tcx.mk_const(ty::ParamConst::new(index, name), ty))
+ hir::ExprKind::Path(hir::QPath::Resolved(
+ _,
+ &hir::Path { res: Res::Def(DefKind::ConstParam, def_id), .. },
+ )) => {
+ match tcx.named_bound_var(expr.hir_id) {
+ Some(rbv::ResolvedArg::EarlyBound(_)) => {
+ // Find the name and index of the const parameter by indexing the generics of
+ // the parent item and construct a `ParamConst`.
+ let item_def_id = tcx.parent(def_id);
+ let generics = tcx.generics_of(item_def_id);
+ let index = generics.param_def_id_to_index[&def_id];
+ let name = tcx.item_name(def_id);
+ Some(tcx.mk_const(ty::ParamConst::new(index, name), ty))
+ }
+ Some(rbv::ResolvedArg::LateBound(debruijn, index, _)) => Some(tcx.mk_const(
+ ty::ConstKind::Bound(debruijn, ty::BoundVar::from_u32(index)),
+ ty,
+ )),
+ Some(rbv::ResolvedArg::Error(guar)) => {
+ Some(tcx.const_error_with_guaranteed(ty, guar))
+ }
+ arg => bug!("unexpected bound var resolution for {:?}: {arg:?}", expr.hir_id),
+ }
}
_ => None,
}
@@ -175,7 +194,7 @@ impl<'tcx> Const<'tcx> {
#[inline]
/// Creates an interned usize constant.
- pub fn from_usize(tcx: TyCtxt<'tcx>, n: u64) -> Self {
+ pub fn from_target_usize(tcx: TyCtxt<'tcx>, n: u64) -> Self {
Self::from_bits(tcx, n as u128, ParamEnv::empty().and(tcx.types.usize))
}
@@ -201,8 +220,12 @@ impl<'tcx> Const<'tcx> {
}
#[inline]
- pub fn try_eval_usize(self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>) -> Option<u64> {
- self.kind().eval(tcx, param_env).try_to_machine_usize(tcx)
+ pub fn try_eval_target_usize(
+ self,
+ tcx: TyCtxt<'tcx>,
+ param_env: ParamEnv<'tcx>,
+ ) -> Option<u64> {
+ self.kind().eval(tcx, param_env).try_to_target_usize(tcx)
}
#[inline]
@@ -229,8 +252,8 @@ impl<'tcx> Const<'tcx> {
#[inline]
/// Panics if the value cannot be evaluated or doesn't contain a valid `usize`.
- pub fn eval_usize(self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>) -> u64 {
- self.try_eval_usize(tcx, param_env)
+ pub fn eval_target_usize(self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>) -> u64 {
+ self.try_eval_target_usize(tcx, param_env)
.unwrap_or_else(|| bug!("expected usize, got {:#?}", self))
}
diff --git a/compiler/rustc_middle/src/ty/consts/int.rs b/compiler/rustc_middle/src/ty/consts/int.rs
index 48958e0d9..eecd78ab6 100644
--- a/compiler/rustc_middle/src/ty/consts/int.rs
+++ b/compiler/rustc_middle/src/ty/consts/int.rs
@@ -232,7 +232,7 @@ impl ScalarInt {
}
#[inline]
- pub fn try_to_machine_usize(&self, tcx: TyCtxt<'_>) -> Result<u64, Size> {
+ pub fn try_to_target_usize(&self, tcx: TyCtxt<'_>) -> Result<u64, Size> {
Ok(self.to_bits(tcx.data_layout.pointer_size)? as u64)
}
diff --git a/compiler/rustc_middle/src/ty/consts/kind.rs b/compiler/rustc_middle/src/ty/consts/kind.rs
index d9721863a..560caa041 100644
--- a/compiler/rustc_middle/src/ty/consts/kind.rs
+++ b/compiler/rustc_middle/src/ty/consts/kind.rs
@@ -4,7 +4,7 @@ use crate::mir::interpret::{AllocId, ConstValue, Scalar};
use crate::ty::abstract_const::CastKind;
use crate::ty::subst::{InternalSubsts, SubstsRef};
use crate::ty::ParamEnv;
-use crate::ty::{self, List, Ty, TyCtxt, TypeVisitable};
+use crate::ty::{self, List, Ty, TyCtxt, TypeVisitableExt};
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
use rustc_errors::ErrorGuaranteed;
use rustc_hir::def_id::DefId;
@@ -125,8 +125,8 @@ impl<'tcx> ConstKind<'tcx> {
}
#[inline]
- pub fn try_to_machine_usize(self, tcx: TyCtxt<'tcx>) -> Option<u64> {
- self.try_to_value()?.try_to_machine_usize(tcx)
+ pub fn try_to_target_usize(self, tcx: TyCtxt<'tcx>) -> Option<u64> {
+ self.try_to_value()?.try_to_target_usize(tcx)
}
}
@@ -217,23 +217,21 @@ impl<'tcx> ConstKind<'tcx> {
// Note that we erase regions *before* calling `with_reveal_all_normalized`,
// so that we don't try to invoke this query with
// any region variables.
- let param_env_and = tcx
- .erase_regions(param_env)
- .with_reveal_all_normalized(tcx)
- .and(tcx.erase_regions(unevaluated));
// HACK(eddyb) when the query key would contain inference variables,
// attempt using identity substs and `ParamEnv` instead, that will succeed
// when the expression doesn't depend on any parameters.
// FIXME(eddyb, skinny121) pass `InferCtxt` into here when it's available, so that
// we can call `infcx.const_eval_resolve` which handles inference variables.
- let param_env_and = if param_env_and.needs_infer() {
+ let param_env_and = if (param_env, unevaluated).has_non_region_infer() {
tcx.param_env(unevaluated.def.did).and(ty::UnevaluatedConst {
def: unevaluated.def,
substs: InternalSubsts::identity_for_item(tcx, unevaluated.def.did),
})
} else {
- param_env_and
+ tcx.erase_regions(param_env)
+ .with_reveal_all_normalized(tcx)
+ .and(tcx.erase_regions(unevaluated))
};
// FIXME(eddyb) maybe the `const_eval_*` methods should take
diff --git a/compiler/rustc_middle/src/ty/consts/valtree.rs b/compiler/rustc_middle/src/ty/consts/valtree.rs
index a803fca0d..5ed4af2e9 100644
--- a/compiler/rustc_middle/src/ty/consts/valtree.rs
+++ b/compiler/rustc_middle/src/ty/consts/valtree.rs
@@ -78,8 +78,8 @@ impl<'tcx> ValTree<'tcx> {
}
}
- pub fn try_to_machine_usize(self, tcx: TyCtxt<'tcx>) -> Option<u64> {
- self.try_to_scalar_int().map(|s| s.try_to_machine_usize(tcx).ok()).flatten()
+ pub fn try_to_target_usize(self, tcx: TyCtxt<'tcx>) -> Option<u64> {
+ self.try_to_scalar_int().map(|s| s.try_to_target_usize(tcx).ok()).flatten()
}
/// Get the values inside the ValTree as a slice of bytes. This only works for
diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs
index ce04d8d21..d9af2fd74 100644
--- a/compiler/rustc_middle/src/ty/context.rs
+++ b/compiler/rustc_middle/src/ty/context.rs
@@ -2,12 +2,14 @@
#![allow(rustc::usage_of_ty_tykind)]
+pub mod tls;
+
use crate::arena::Arena;
use crate::dep_graph::{DepGraph, DepKindStruct};
-use crate::infer::canonical::{CanonicalVarInfo, CanonicalVarInfos};
+use crate::infer::canonical::CanonicalVarInfo;
use crate::lint::struct_lint_level;
use crate::middle::codegen_fn_attrs::CodegenFnAttrs;
-use crate::middle::resolve_lifetime;
+use crate::middle::resolve_bound_vars;
use crate::middle::stability;
use crate::mir::interpret::{self, Allocation, ConstAllocation};
use crate::mir::{
@@ -15,6 +17,7 @@ use crate::mir::{
};
use crate::thir::Thir;
use crate::traits;
+use crate::traits::solve::{ExternalConstraints, ExternalConstraintsData};
use crate::ty::query::{self, TyCtxtAt};
use crate::ty::{
self, AdtDef, AdtDefData, AdtKind, Binder, Const, ConstData, DefIdTree, FloatTy, FloatVar,
@@ -33,7 +36,7 @@ use rustc_data_structures::profiling::SelfProfilerRef;
use rustc_data_structures::sharded::{IntoPointer, ShardedHashMap};
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
use rustc_data_structures::steal::Steal;
-use rustc_data_structures::sync::{self, Lock, Lrc, ReadGuard, WorkerLocal};
+use rustc_data_structures::sync::{self, Lock, Lrc, MappedReadGuard, ReadGuard, WorkerLocal};
use rustc_errors::{
DecorateLint, DiagnosticBuilder, DiagnosticMessage, ErrorGuaranteed, MultiSpan,
};
@@ -64,7 +67,7 @@ use rustc_target::abi::{Layout, LayoutS, TargetDataLayout, VariantIdx};
use rustc_target::spec::abi;
use rustc_type_ir::sty::TyKind::*;
use rustc_type_ir::WithCachedTypeInfo;
-use rustc_type_ir::{DynKind, InternAs, InternIteratorElement, Interner, TypeFlags};
+use rustc_type_ir::{CollectAndApply, DynKind, Interner, TypeFlags};
use std::any::Any;
use std::borrow::Borrow;
@@ -75,6 +78,8 @@ use std::iter;
use std::mem;
use std::ops::{Bound, Deref};
+const TINY_CONST_EVAL_LIMIT: Limit = Limit(20);
+
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: Mmap, start_pos: usize) -> Self
@@ -95,9 +100,11 @@ impl<'tcx> Interner for TyCtxt<'tcx> {
type AdtDef = ty::AdtDef<'tcx>;
type SubstsRef = ty::SubstsRef<'tcx>;
type DefId = DefId;
+ type Binder<T> = Binder<'tcx, T>;
type Ty = Ty<'tcx>;
type Const = ty::Const<'tcx>;
type Region = Region<'tcx>;
+ type Predicate = Predicate<'tcx>;
type TypeAndMut = TypeAndMut<'tcx>;
type Mutability = hir::Mutability;
type Movability = hir::Movability;
@@ -142,8 +149,9 @@ pub struct CtxtInterners<'tcx> {
const_: InternedSet<'tcx, ConstData<'tcx>>,
const_allocation: InternedSet<'tcx, Allocation>,
bound_variable_kinds: InternedSet<'tcx, List<ty::BoundVariableKind>>,
- layout: InternedSet<'tcx, LayoutS<VariantIdx>>,
+ layout: InternedSet<'tcx, LayoutS>,
adt_def: InternedSet<'tcx, AdtDefData>,
+ external_constraints: InternedSet<'tcx, ExternalConstraintsData<'tcx>>,
}
impl<'tcx> CtxtInterners<'tcx> {
@@ -165,10 +173,11 @@ impl<'tcx> CtxtInterners<'tcx> {
bound_variable_kinds: Default::default(),
layout: Default::default(),
adt_def: Default::default(),
+ external_constraints: Default::default(),
}
}
- /// Interns a type.
+ /// Interns a type. (Use `mk_*` functions instead, where possible.)
#[allow(rustc::usage_of_ty_tykind)]
#[inline(never)]
fn intern_ty(&self, kind: TyKind<'tcx>, sess: &Session, untracked: &Untracked) -> Ty<'tcx> {
@@ -208,6 +217,7 @@ impl<'tcx> CtxtInterners<'tcx> {
}
}
+ /// Interns a predicate. (Use `mk_predicate` instead, where possible.)
#[inline(never)]
fn intern_predicate(
&self,
@@ -234,6 +244,20 @@ impl<'tcx> CtxtInterners<'tcx> {
}
}
+// For these preinterned values, an alternative would be to have
+// variable-length vectors that grow as needed. But that turned out to be
+// slightly more complex and no faster.
+
+const NUM_PREINTERNED_TY_VARS: u32 = 100;
+const NUM_PREINTERNED_FRESH_TYS: u32 = 20;
+const NUM_PREINTERNED_FRESH_INT_TYS: u32 = 3;
+const NUM_PREINTERNED_FRESH_FLOAT_TYS: u32 = 3;
+
+// This number may seem high, but it is reached in all but the smallest crates.
+const NUM_PREINTERNED_RE_VARS: u32 = 500;
+const NUM_PREINTERNED_RE_LATE_BOUNDS_I: u32 = 2;
+const NUM_PREINTERNED_RE_LATE_BOUNDS_V: u32 = 20;
+
pub struct CommonTypes<'tcx> {
pub unit: Ty<'tcx>,
pub bool: Ty<'tcx>,
@@ -259,7 +283,20 @@ pub struct CommonTypes<'tcx> {
/// Dummy type used for the `Self` of a `TraitRef` created for converting
/// a trait object, and which gets removed in `ExistentialTraitRef`.
/// This type must not appear anywhere in other converted types.
+ /// `Infer(ty::FreshTy(0))` does the job.
pub trait_object_dummy_self: Ty<'tcx>,
+
+ /// Pre-interned `Infer(ty::TyVar(n))` for small values of `n`.
+ pub ty_vars: Vec<Ty<'tcx>>,
+
+ /// Pre-interned `Infer(ty::FreshTy(n))` for small values of `n`.
+ pub fresh_tys: Vec<Ty<'tcx>>,
+
+ /// Pre-interned `Infer(ty::FreshIntTy(n))` for small values of `n`.
+ pub fresh_int_tys: Vec<Ty<'tcx>>,
+
+ /// Pre-interned `Infer(ty::FreshFloatTy(n))` for small values of `n`.
+ pub fresh_float_tys: Vec<Ty<'tcx>>,
}
pub struct CommonLifetimes<'tcx> {
@@ -268,6 +305,14 @@ pub struct CommonLifetimes<'tcx> {
/// Erased region, used outside of type inference.
pub re_erased: Region<'tcx>,
+
+ /// Pre-interned `ReVar(ty::RegionVar(n))` for small values of `n`.
+ pub re_vars: Vec<Region<'tcx>>,
+
+ /// Pre-interned values of the form:
+ /// `ReLateBound(DebruijnIndex(i), BoundRegion { var: v, kind: BrAnon(v, None) })`
+ /// for small values of `i` and `v`.
+ pub re_late_bounds: Vec<Vec<Region<'tcx>>>,
}
pub struct CommonConsts<'tcx> {
@@ -282,6 +327,15 @@ impl<'tcx> CommonTypes<'tcx> {
) -> CommonTypes<'tcx> {
let mk = |ty| interners.intern_ty(ty, sess, untracked);
+ let ty_vars =
+ (0..NUM_PREINTERNED_TY_VARS).map(|n| mk(Infer(ty::TyVar(TyVid::from(n))))).collect();
+ let fresh_tys: Vec<_> =
+ (0..NUM_PREINTERNED_FRESH_TYS).map(|n| mk(Infer(ty::FreshTy(n)))).collect();
+ let fresh_int_tys: Vec<_> =
+ (0..NUM_PREINTERNED_FRESH_INT_TYS).map(|n| mk(Infer(ty::FreshIntTy(n)))).collect();
+ let fresh_float_tys: Vec<_> =
+ (0..NUM_PREINTERNED_FRESH_FLOAT_TYS).map(|n| mk(Infer(ty::FreshFloatTy(n)))).collect();
+
CommonTypes {
unit: mk(Tuple(List::empty())),
bool: mk(Bool),
@@ -304,7 +358,12 @@ impl<'tcx> CommonTypes<'tcx> {
str_: mk(Str),
self_param: mk(ty::Param(ty::ParamTy { index: 0, name: kw::SelfUpper })),
- trait_object_dummy_self: mk(Infer(ty::FreshTy(0))),
+ trait_object_dummy_self: fresh_tys[0],
+
+ ty_vars,
+ fresh_tys,
+ fresh_int_tys,
+ fresh_float_tys,
}
}
}
@@ -317,7 +376,31 @@ impl<'tcx> CommonLifetimes<'tcx> {
))
};
- CommonLifetimes { re_static: mk(ty::ReStatic), re_erased: mk(ty::ReErased) }
+ let re_vars =
+ (0..NUM_PREINTERNED_RE_VARS).map(|n| mk(ty::ReVar(ty::RegionVid::from(n)))).collect();
+
+ let re_late_bounds = (0..NUM_PREINTERNED_RE_LATE_BOUNDS_I)
+ .map(|i| {
+ (0..NUM_PREINTERNED_RE_LATE_BOUNDS_V)
+ .map(|v| {
+ mk(ty::ReLateBound(
+ ty::DebruijnIndex::from(i),
+ ty::BoundRegion {
+ var: ty::BoundVar::from(v),
+ kind: ty::BrAnon(v, None),
+ },
+ ))
+ })
+ .collect()
+ })
+ .collect();
+
+ CommonLifetimes {
+ re_static: mk(ty::ReStatic),
+ re_erased: mk(ty::ReErased),
+ re_vars,
+ re_late_bounds,
+ }
}
}
@@ -438,7 +521,7 @@ pub struct GlobalCtxt<'tcx> {
pub on_disk_cache: Option<&'tcx dyn OnDiskCache<'tcx>>,
pub queries: &'tcx dyn query::QueryEngine<'tcx>,
- pub query_caches: query::QueryCaches<'tcx>,
+ pub query_system: query::QuerySystem<'tcx>,
pub(crate) query_kinds: &'tcx [DepKindStruct<'tcx>],
// Internal caches for metadata decoding. No need to track deps on this.
@@ -461,6 +544,18 @@ pub struct GlobalCtxt<'tcx> {
pub(crate) alloc_map: Lock<interpret::AllocMap<'tcx>>,
}
+impl<'tcx> GlobalCtxt<'tcx> {
+ /// Installs `self` in a `TyCtxt` and `ImplicitCtxt` for the duration of
+ /// `f`.
+ pub fn enter<'a: 'tcx, F, R>(&'a self, f: F) -> R
+ where
+ F: FnOnce(TyCtxt<'tcx>) -> R,
+ {
+ let icx = tls::ImplicitCtxt::new(self);
+ tls::enter_context(&icx, || f(icx.tcx))
+ }
+}
+
impl<'tcx> TyCtxt<'tcx> {
/// Expects a body and returns its codegen attributes.
///
@@ -521,21 +616,21 @@ impl<'tcx> TyCtxt<'tcx> {
self.arena.alloc(Steal::new(promoted))
}
- pub fn alloc_adt_def(
+ pub fn mk_adt_def(
self,
did: DefId,
kind: AdtKind,
variants: IndexVec<VariantIdx, ty::VariantDef>,
repr: ReprOptions,
) -> ty::AdtDef<'tcx> {
- self.intern_adt_def(ty::AdtDefData::new(self, did, kind, variants, repr))
+ self.mk_adt_def_from_data(ty::AdtDefData::new(self, did, kind, variants, repr))
}
/// 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.
let alloc = interpret::Allocation::from_bytes_byte_aligned_immutable(bytes);
- let alloc = self.intern_const_alloc(alloc);
+ let alloc = self.mk_const_alloc(alloc);
self.create_memory_alloc(alloc)
}
@@ -611,7 +706,7 @@ impl<'tcx> TyCtxt<'tcx> {
untracked,
on_disk_cache,
queries,
- query_caches: query::QueryCaches::default(),
+ query_system: Default::default(),
query_kinds,
ty_rcache: Default::default(),
pred_rcache: Default::default(),
@@ -624,13 +719,13 @@ impl<'tcx> TyCtxt<'tcx> {
/// Constructs a `TyKind::Error` type with current `ErrorGuaranteed`
#[track_caller]
- pub fn ty_error_with_guaranteed(self, reported: ErrorGuaranteed) -> Ty<'tcx> {
- self.mk_ty(Error(reported))
+ pub fn ty_error(self, reported: ErrorGuaranteed) -> Ty<'tcx> {
+ self.mk_ty_from_kind(Error(reported))
}
/// Constructs a `TyKind::Error` type and registers a `delay_span_bug` to ensure it gets used.
#[track_caller]
- pub fn ty_error(self) -> Ty<'tcx> {
+ pub fn ty_error_misc(self) -> Ty<'tcx> {
self.ty_error_with_message(DUMMY_SP, "TyKind::Error constructed but no error reported")
}
@@ -639,7 +734,31 @@ impl<'tcx> TyCtxt<'tcx> {
#[track_caller]
pub fn ty_error_with_message<S: Into<MultiSpan>>(self, span: S, msg: &str) -> Ty<'tcx> {
let reported = self.sess.delay_span_bug(span, msg);
- self.mk_ty(Error(reported))
+ self.mk_ty_from_kind(Error(reported))
+ }
+
+ /// Constructs a `RegionKind::ReError` lifetime.
+ #[track_caller]
+ pub fn mk_re_error(self, reported: ErrorGuaranteed) -> Region<'tcx> {
+ self.intern_region(ty::ReError(reported))
+ }
+
+ /// Constructs a `RegionKind::ReError` lifetime and registers a `delay_span_bug` to ensure it
+ /// gets used.
+ #[track_caller]
+ pub fn mk_re_error_misc(self) -> Region<'tcx> {
+ self.mk_re_error_with_message(
+ DUMMY_SP,
+ "RegionKind::ReError constructed but no error reported",
+ )
+ }
+
+ /// Constructs a `RegionKind::ReError` lifetime and registers a `delay_span_bug` with the given
+ /// `msg` to ensure it gets used.
+ #[track_caller]
+ pub fn mk_re_error_with_message<S: Into<MultiSpan>>(self, span: S, msg: &str) -> Region<'tcx> {
+ let reported = self.sess.delay_span_bug(span, msg);
+ self.mk_re_error(reported)
}
/// Like [TyCtxt::ty_error] but for constants, with current `ErrorGuaranteed`
@@ -675,8 +794,7 @@ impl<'tcx> TyCtxt<'tcx> {
}
pub fn consider_optimizing<T: Fn() -> String>(self, msg: T) -> bool {
- let cname = self.crate_name(LOCAL_CRATE);
- self.sess.consider_optimizing(cname.as_str(), msg)
+ self.sess.consider_optimizing(|| self.crate_name(LOCAL_CRATE), msg)
}
/// Obtain all lang items of this crate and all dependencies (recursively)
@@ -718,7 +836,7 @@ impl<'tcx> TyCtxt<'tcx> {
if let Some(id) = id.as_local() {
self.definitions_untracked().def_key(id)
} else {
- self.untracked.cstore.def_key(id)
+ self.cstore_untracked().def_key(id)
}
}
@@ -732,7 +850,7 @@ impl<'tcx> TyCtxt<'tcx> {
if let Some(id) = id.as_local() {
self.definitions_untracked().def_path(id)
} else {
- self.untracked.cstore.def_path(id)
+ self.cstore_untracked().def_path(id)
}
}
@@ -742,7 +860,7 @@ impl<'tcx> TyCtxt<'tcx> {
if let Some(def_id) = def_id.as_local() {
self.definitions_untracked().def_path_hash(def_id)
} else {
- self.untracked.cstore.def_path_hash(def_id)
+ self.cstore_untracked().def_path_hash(def_id)
}
}
@@ -751,7 +869,7 @@ impl<'tcx> TyCtxt<'tcx> {
if crate_num == LOCAL_CRATE {
self.sess.local_stable_crate_id()
} else {
- self.untracked.cstore.stable_crate_id(crate_num)
+ self.cstore_untracked().stable_crate_id(crate_num)
}
}
@@ -762,7 +880,7 @@ impl<'tcx> TyCtxt<'tcx> {
if stable_crate_id == self.sess.local_stable_crate_id() {
LOCAL_CRATE
} else {
- self.untracked.cstore.stable_crate_id_to_crate_num(stable_crate_id)
+ self.cstore_untracked().stable_crate_id_to_crate_num(stable_crate_id)
}
}
@@ -781,7 +899,7 @@ impl<'tcx> TyCtxt<'tcx> {
} else {
// If this is a DefPathHash from an upstream crate, let the CrateStore map
// it to a DefId.
- let cstore = &*self.untracked.cstore;
+ let cstore = &*self.cstore_untracked();
let cnum = cstore.stable_crate_id_to_crate_num(stable_crate_id);
cstore.def_path_hash_to_def_id(cnum, hash)
}
@@ -795,7 +913,7 @@ impl<'tcx> TyCtxt<'tcx> {
let (crate_name, stable_crate_id) = if def_id.is_local() {
(self.crate_name(LOCAL_CRATE), self.sess.local_stable_crate_id())
} else {
- let cstore = &*self.untracked.cstore;
+ let cstore = &*self.cstore_untracked();
(cstore.crate_name(def_id.krate), cstore.stable_crate_id(def_id.krate))
};
@@ -893,10 +1011,15 @@ impl<'tcx> TyCtxt<'tcx> {
/// 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 CrateStoreDyn {
- &*self.untracked.cstore
+ #[inline]
+ pub fn cstore_untracked(self) -> MappedReadGuard<'tcx, CrateStoreDyn> {
+ ReadGuard::map(self.untracked.cstore.read(), |c| &**c)
}
+ /// Give out access to the untracked data without any sanity checks.
+ pub fn untracked(self) -> &'tcx Untracked {
+ &self.untracked
+ }
/// Note that this is *untracked* and should only be used within the query
/// system if the result is otherwise tracked through queries
#[inline]
@@ -908,7 +1031,7 @@ impl<'tcx> TyCtxt<'tcx> {
/// system if the result is otherwise tracked through queries
#[inline]
pub fn source_span_untracked(self, def_id: LocalDefId) -> Span {
- self.untracked.source_span.get(def_id).copied().unwrap_or(DUMMY_SP)
+ self.untracked.source_span.get(def_id).unwrap_or(DUMMY_SP)
}
#[inline(always)]
@@ -997,6 +1120,30 @@ impl<'tcx> TyCtxt<'tcx> {
v.0
}
+ /// Given a `DefId` for an `fn`, return all the `dyn` and `impl` traits in its return type and associated alias span when type alias is used
+ pub fn return_type_impl_or_dyn_traits_with_type_alias(
+ self,
+ scope_def_id: LocalDefId,
+ ) -> Option<(Vec<&'tcx hir::Ty<'tcx>>, Span)> {
+ let hir_id = self.hir().local_def_id_to_hir_id(scope_def_id);
+ let mut v = TraitObjectVisitor(vec![], self.hir());
+ // when the return type is a type alias
+ if let Some(hir::FnDecl { output: hir::FnRetTy::Return(hir_output), .. }) = self.hir().fn_decl_by_hir_id(hir_id)
+ && let hir::TyKind::Path(hir::QPath::Resolved(
+ None,
+ hir::Path { res: hir::def::Res::Def(DefKind::TyAlias, def_id), .. }, )) = hir_output.kind
+ && let Some(local_id) = def_id.as_local()
+ && let Some(alias_ty) = self.hir().get_by_def_id(local_id).alias_ty() // it is type alias
+ && let Some(alias_generics) = self.hir().get_by_def_id(local_id).generics()
+ {
+ v.visit_ty(alias_ty);
+ if !v.0.is_empty() {
+ return Some((v.0, alias_generics.span));
+ }
+ }
+ return None;
+ }
+
pub fn return_type_impl_trait(self, scope_def_id: LocalDefId) -> Option<(Ty<'tcx>, Span)> {
// `type_of()` will fail on these (#55796, #86483), so only allow `fn`s or closures.
match self.hir().get_by_def_id(scope_def_id) {
@@ -1007,18 +1154,16 @@ impl<'tcx> TyCtxt<'tcx> {
_ => return None,
}
- let ret_ty = self.type_of(scope_def_id);
+ let ret_ty = self.type_of(scope_def_id).subst_identity();
match ret_ty.kind() {
ty::FnDef(_, _) => {
let sig = ret_ty.fn_sig(self);
let output = self.erase_late_bound_regions(sig.output());
- if output.is_impl_trait() {
+ output.is_impl_trait().then(|| {
let hir_id = self.hir().local_def_id_to_hir_id(scope_def_id);
let fn_decl = self.hir().fn_decl_by_hir_id(hir_id).unwrap();
- Some((output, fn_decl.output.span()))
- } else {
- None
- }
+ (output, fn_decl.output.span())
+ })
}
_ => None,
}
@@ -1049,20 +1194,15 @@ impl<'tcx> TyCtxt<'tcx> {
pub fn caller_location_ty(self) -> Ty<'tcx> {
self.mk_imm_ref(
self.lifetimes.re_static,
- self.bound_type_of(self.require_lang_item(LangItem::PanicLocation, None))
- .subst(self, self.mk_substs([self.lifetimes.re_static.into()].iter())),
+ self.type_of(self.require_lang_item(LangItem::PanicLocation, None))
+ .subst(self, self.mk_substs(&[self.lifetimes.re_static.into()])),
)
}
/// Returns a displayable description and article for the given `def_id` (e.g. `("a", "struct")`).
pub fn article_and_description(self, def_id: DefId) -> (&'static str, &'static str) {
- match self.def_kind(def_id) {
- DefKind::Generator => match self.generator_kind(def_id).unwrap() {
- rustc_hir::GeneratorKind::Async(..) => ("an", "async closure"),
- rustc_hir::GeneratorKind::Gen => ("a", "generator"),
- },
- def_kind => (def_kind.article(), def_kind.descr(def_id)),
- }
+ let kind = self.def_kind(def_id);
+ (self.def_kind_descr_article(kind, def_id), self.def_kind_descr(kind, def_id))
}
pub fn type_length_limit(self) -> Limit {
@@ -1078,7 +1218,11 @@ impl<'tcx> TyCtxt<'tcx> {
}
pub fn const_eval_limit(self) -> Limit {
- self.limits(()).const_eval_limit
+ if self.sess.opts.unstable_opts.tiny_const_eval_limit {
+ TINY_CONST_EVAL_LIMIT
+ } else {
+ self.limits(()).const_eval_limit
+ }
}
pub fn all_traits(self) -> impl Iterator<Item = DefId> + 'tcx {
@@ -1120,13 +1264,12 @@ macro_rules! nop_lift {
impl<'a, 'tcx> Lift<'tcx> for $ty {
type Lifted = $lifted;
fn lift_to_tcx(self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
- if tcx.interners.$set.contains_pointer_to(&InternedInSet(&*self.0.0)) {
+ tcx.interners
+ .$set
+ .contains_pointer_to(&InternedInSet(&*self.0.0))
// SAFETY: `self` is interned and therefore valid
// for the entire lifetime of the `TyCtxt`.
- Some(unsafe { mem::transmute(self) })
- } else {
- None
- }
+ .then(|| unsafe { mem::transmute(self) })
}
}
};
@@ -1134,20 +1277,20 @@ macro_rules! nop_lift {
// Can't use the macros as we have reuse the `substs` here.
//
-// See `intern_type_list` for more info.
+// See `mk_type_list` for more info.
impl<'a, 'tcx> Lift<'tcx> for &'a List<Ty<'a>> {
type Lifted = &'tcx List<Ty<'tcx>>;
fn lift_to_tcx(self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
if self.is_empty() {
return Some(List::empty());
}
- if tcx.interners.substs.contains_pointer_to(&InternedInSet(self.as_substs())) {
+
+ tcx.interners
+ .substs
+ .contains_pointer_to(&InternedInSet(self.as_substs()))
// SAFETY: `self` is interned and therefore valid
// for the entire lifetime of the `TyCtxt`.
- Some(unsafe { mem::transmute::<&'a List<Ty<'a>>, &'tcx List<Ty<'tcx>>>(self) })
- } else {
- None
- }
+ .then(|| unsafe { mem::transmute::<&'a List<Ty<'a>>, &'tcx List<Ty<'tcx>>>(self) })
}
}
@@ -1159,11 +1302,10 @@ macro_rules! nop_list_lift {
if self.is_empty() {
return Some(List::empty());
}
- if tcx.interners.$set.contains_pointer_to(&InternedInSet(self)) {
- Some(unsafe { mem::transmute(self) })
- } else {
- None
- }
+ tcx.interners
+ .$set
+ .contains_pointer_to(&InternedInSet(self))
+ .then(|| unsafe { mem::transmute(self) })
}
}
};
@@ -1188,178 +1330,6 @@ CloneLiftImpls! { for<'tcx> {
Constness, traits::WellFormedLoc, ImplPolarity, crate::mir::ReturnConstraint,
} }
-pub mod tls {
- use super::{ptr_eq, GlobalCtxt, TyCtxt};
-
- use crate::dep_graph::TaskDepsRef;
- use crate::ty::query;
- use rustc_data_structures::sync::{self, Lock};
- use rustc_errors::Diagnostic;
- use std::mem;
- use thin_vec::ThinVec;
-
- #[cfg(not(parallel_compiler))]
- use std::cell::Cell;
-
- #[cfg(parallel_compiler)]
- use rustc_rayon_core as rayon_core;
-
- /// This is the implicit state of rustc. It contains the current
- /// `TyCtxt` and query. It is updated when creating a local interner or
- /// executing a new query. Whenever there's a `TyCtxt` value available
- /// you should also have access to an `ImplicitCtxt` through the functions
- /// in this module.
- #[derive(Clone)]
- pub struct ImplicitCtxt<'a, 'tcx> {
- /// The current `TyCtxt`.
- pub tcx: TyCtxt<'tcx>,
-
- /// The current query job, if any. This is updated by `JobOwner::start` in
- /// `ty::query::plumbing` when executing a query.
- pub query: Option<query::QueryJobId>,
-
- /// Where to store diagnostics for the current query job, if any.
- /// This is updated by `JobOwner::start` in `ty::query::plumbing` when executing a query.
- pub diagnostics: Option<&'a Lock<ThinVec<Diagnostic>>>,
-
- /// Used to prevent queries from calling too deeply.
- pub query_depth: usize,
-
- /// The current dep graph task. This is used to add dependencies to queries
- /// when executing them.
- pub task_deps: TaskDepsRef<'a>,
- }
-
- impl<'a, 'tcx> ImplicitCtxt<'a, 'tcx> {
- pub fn new(gcx: &'tcx GlobalCtxt<'tcx>) -> Self {
- let tcx = TyCtxt { gcx };
- ImplicitCtxt {
- tcx,
- query: None,
- diagnostics: None,
- query_depth: 0,
- task_deps: TaskDepsRef::Ignore,
- }
- }
- }
-
- /// Sets Rayon's thread-local variable, which is preserved for Rayon jobs
- /// to `value` during the call to `f`. It is restored to its previous value after.
- /// This is used to set the pointer to the new `ImplicitCtxt`.
- #[cfg(parallel_compiler)]
- #[inline]
- fn set_tlv<F: FnOnce() -> R, R>(value: usize, f: F) -> R {
- rayon_core::tlv::with(value, f)
- }
-
- /// Gets Rayon's thread-local variable, which is preserved for Rayon jobs.
- /// This is used to get the pointer to the current `ImplicitCtxt`.
- #[cfg(parallel_compiler)]
- #[inline]
- pub fn get_tlv() -> usize {
- rayon_core::tlv::get()
- }
-
- #[cfg(not(parallel_compiler))]
- thread_local! {
- /// A thread local variable that stores a pointer to the current `ImplicitCtxt`.
- static TLV: Cell<usize> = const { Cell::new(0) };
- }
-
- /// Sets TLV to `value` during the call to `f`.
- /// It is restored to its previous value after.
- /// This is used to set the pointer to the new `ImplicitCtxt`.
- #[cfg(not(parallel_compiler))]
- #[inline]
- fn set_tlv<F: FnOnce() -> R, R>(value: usize, f: F) -> R {
- let old = get_tlv();
- let _reset = rustc_data_structures::OnDrop(move || TLV.with(|tlv| tlv.set(old)));
- TLV.with(|tlv| tlv.set(value));
- f()
- }
-
- /// Gets the pointer to the current `ImplicitCtxt`.
- #[cfg(not(parallel_compiler))]
- #[inline]
- fn get_tlv() -> usize {
- TLV.with(|tlv| tlv.get())
- }
-
- /// Sets `context` as the new current `ImplicitCtxt` for the duration of the function `f`.
- #[inline]
- pub fn enter_context<'a, 'tcx, F, R>(context: &ImplicitCtxt<'a, 'tcx>, f: F) -> R
- where
- F: FnOnce(&ImplicitCtxt<'a, 'tcx>) -> R,
- {
- set_tlv(context as *const _ as usize, || f(&context))
- }
-
- /// Allows access to the current `ImplicitCtxt` in a closure if one is available.
- #[inline]
- pub fn with_context_opt<F, R>(f: F) -> R
- where
- F: for<'a, 'tcx> FnOnce(Option<&ImplicitCtxt<'a, 'tcx>>) -> R,
- {
- let context = get_tlv();
- if context == 0 {
- f(None)
- } else {
- // We could get an `ImplicitCtxt` pointer from another thread.
- // Ensure that `ImplicitCtxt` is `Sync`.
- sync::assert_sync::<ImplicitCtxt<'_, '_>>();
-
- unsafe { f(Some(&*(context as *const ImplicitCtxt<'_, '_>))) }
- }
- }
-
- /// Allows access to the current `ImplicitCtxt`.
- /// Panics if there is no `ImplicitCtxt` available.
- #[inline]
- pub fn with_context<F, R>(f: F) -> R
- where
- F: for<'a, 'tcx> FnOnce(&ImplicitCtxt<'a, 'tcx>) -> R,
- {
- with_context_opt(|opt_context| f(opt_context.expect("no ImplicitCtxt stored in tls")))
- }
-
- /// Allows access to the current `ImplicitCtxt` whose tcx field is the same as the tcx argument
- /// passed in. This means the closure is given an `ImplicitCtxt` with the same `'tcx` lifetime
- /// as the `TyCtxt` passed in.
- /// This will panic if you pass it a `TyCtxt` which is different from the current
- /// `ImplicitCtxt`'s `tcx` field.
- #[inline]
- pub fn with_related_context<'tcx, F, R>(tcx: TyCtxt<'tcx>, f: F) -> R
- where
- F: FnOnce(&ImplicitCtxt<'_, 'tcx>) -> R,
- {
- with_context(|context| unsafe {
- assert!(ptr_eq(context.tcx.gcx, tcx.gcx));
- let context: &ImplicitCtxt<'_, '_> = mem::transmute(context);
- f(context)
- })
- }
-
- /// Allows access to the `TyCtxt` in the current `ImplicitCtxt`.
- /// Panics if there is no `ImplicitCtxt` available.
- #[inline]
- pub fn with<F, R>(f: F) -> R
- where
- F: for<'tcx> FnOnce(TyCtxt<'tcx>) -> R,
- {
- with_context(|context| f(context.tcx))
- }
-
- /// Allows access to the `TyCtxt` in the current `ImplicitCtxt`.
- /// The closure is passed None if there is no `ImplicitCtxt` available.
- #[inline]
- pub fn with_opt<F, R>(f: F) -> R
- where
- F: for<'tcx> FnOnce(Option<TyCtxt<'tcx>>) -> R,
- {
- with_context_opt(|opt_context| f(opt_context.map(|context| context.tcx)))
- }
-}
-
macro_rules! sty_debug_print {
($fmt: expr, $ctxt: expr, $($variant: ident),*) => {{
// Curious inner module to allow variant names to be used as
@@ -1452,6 +1422,7 @@ impl<'tcx> TyCtxt<'tcx> {
Placeholder,
Generator,
GeneratorWitness,
+ GeneratorWitnessMIR,
Dynamic,
Closure,
Tuple,
@@ -1547,7 +1518,7 @@ impl<'tcx, T: Hash> Hash for InternedInSet<'tcx, List<T>> {
}
macro_rules! direct_interners {
- ($($name:ident: $method:ident($ty:ty): $ret_ctor:ident -> $ret_ty:ty,)+) => {
+ ($($name:ident: $vis:vis $method:ident($ty:ty): $ret_ctor:ident -> $ret_ty:ty,)+) => {
$(impl<'tcx> Borrow<$ty> for InternedInSet<'tcx, $ty> {
fn borrow<'a>(&'a self) -> &'a $ty {
&self.0
@@ -1573,7 +1544,7 @@ macro_rules! direct_interners {
}
impl<'tcx> TyCtxt<'tcx> {
- pub fn $method(self, v: $ty) -> $ret_ty {
+ $vis fn $method(self, v: $ty) -> $ret_ty {
$ret_ctor(Interned::new_unchecked(self.interners.$name.intern(v, |v| {
InternedInSet(self.interners.arena.alloc(v))
}).0))
@@ -1582,36 +1553,47 @@ macro_rules! direct_interners {
}
}
+// Functions with a `mk_` prefix are intended for use outside this file and
+// crate. Functions with an `intern_` prefix are intended for use within this
+// file only, and have a corresponding `mk_` function.
direct_interners! {
- region: mk_region(RegionKind<'tcx>): Region -> Region<'tcx>,
- const_: mk_const_internal(ConstData<'tcx>): Const -> Const<'tcx>,
- const_allocation: intern_const_alloc(Allocation): ConstAllocation -> ConstAllocation<'tcx>,
- layout: intern_layout(LayoutS<VariantIdx>): Layout -> Layout<'tcx>,
- adt_def: intern_adt_def(AdtDefData): AdtDef -> AdtDef<'tcx>,
+ region: intern_region(RegionKind<'tcx>): Region -> Region<'tcx>,
+ const_: intern_const(ConstData<'tcx>): Const -> Const<'tcx>,
+ const_allocation: pub mk_const_alloc(Allocation): ConstAllocation -> ConstAllocation<'tcx>,
+ layout: pub mk_layout(LayoutS): Layout -> Layout<'tcx>,
+ adt_def: pub mk_adt_def_from_data(AdtDefData): AdtDef -> AdtDef<'tcx>,
+ external_constraints: pub mk_external_constraints(ExternalConstraintsData<'tcx>):
+ ExternalConstraints -> ExternalConstraints<'tcx>,
}
macro_rules! slice_interners {
- ($($field:ident: $method:ident($ty:ty)),+ $(,)?) => (
+ ($($field:ident: $vis:vis $method:ident($ty:ty)),+ $(,)?) => (
impl<'tcx> TyCtxt<'tcx> {
- $(pub fn $method(self, v: &[$ty]) -> &'tcx List<$ty> {
- self.interners.$field.intern_ref(v, || {
- InternedInSet(List::from_arena(&*self.arena, v))
- }).0
+ $($vis fn $method(self, v: &[$ty]) -> &'tcx List<$ty> {
+ if v.is_empty() {
+ List::empty()
+ } else {
+ self.interners.$field.intern_ref(v, || {
+ InternedInSet(List::from_arena(&*self.arena, v))
+ }).0
+ }
})+
}
);
}
+// These functions intern slices. They all have a corresponding
+// `mk_foo_from_iter` function that interns an iterator. The slice version
+// should be used when possible, because it's faster.
slice_interners!(
- const_lists: _intern_const_list(Const<'tcx>),
- substs: _intern_substs(GenericArg<'tcx>),
- canonical_var_infos: _intern_canonical_var_infos(CanonicalVarInfo<'tcx>),
- poly_existential_predicates:
- _intern_poly_existential_predicates(PolyExistentialPredicate<'tcx>),
- predicates: _intern_predicates(Predicate<'tcx>),
- projs: _intern_projs(ProjectionKind),
- place_elems: _intern_place_elems(PlaceElem<'tcx>),
- bound_variable_kinds: _intern_bound_variable_kinds(ty::BoundVariableKind),
+ const_lists: pub mk_const_list(Const<'tcx>),
+ substs: pub mk_substs(GenericArg<'tcx>),
+ canonical_var_infos: pub mk_canonical_var_infos(CanonicalVarInfo<'tcx>),
+ poly_existential_predicates: intern_poly_existential_predicates(PolyExistentialPredicate<'tcx>),
+ predicates: intern_predicates(Predicate<'tcx>),
+ projs: pub mk_projs(ProjectionKind),
+ place_elems: pub mk_place_elems(PlaceElem<'tcx>),
+ bound_variable_kinds: pub mk_bound_variable_kinds(ty::BoundVariableKind),
);
impl<'tcx> TyCtxt<'tcx> {
@@ -1688,24 +1670,18 @@ impl<'tcx> TyCtxt<'tcx> {
unsafety: hir::Unsafety,
) -> PolyFnSig<'tcx> {
sig.map_bound(|s| {
- let params_iter = match s.inputs()[0].kind() {
- ty::Tuple(params) => params.into_iter(),
+ let params = match s.inputs()[0].kind() {
+ ty::Tuple(params) => *params,
_ => bug!(),
};
- self.mk_fn_sig(params_iter, s.output(), s.c_variadic, unsafety, abi::Abi::Rust)
+ self.mk_fn_sig(params, s.output(), s.c_variadic, unsafety, abi::Abi::Rust)
})
}
- /// Same a `self.mk_region(kind)`, but avoids accessing the interners if
- /// `*r == kind`.
- #[inline]
- pub fn reuse_or_mk_region(self, r: Region<'tcx>, kind: RegionKind<'tcx>) -> Region<'tcx> {
- if *r == kind { r } else { self.mk_region(kind) }
- }
-
+ // Avoid this in favour of more specific `mk_*` methods, where possible.
#[allow(rustc::usage_of_ty_tykind)]
#[inline]
- pub fn mk_ty(self, st: TyKind<'tcx>) -> Ty<'tcx> {
+ pub fn mk_ty_from_kind(self, st: TyKind<'tcx>) -> Ty<'tcx> {
self.interners.intern_ty(
st,
self.sess,
@@ -1770,12 +1746,12 @@ impl<'tcx> TyCtxt<'tcx> {
#[inline]
pub fn mk_adt(self, def: AdtDef<'tcx>, substs: SubstsRef<'tcx>) -> Ty<'tcx> {
// Take a copy of substs so that we own the vectors inside.
- self.mk_ty(Adt(def, substs))
+ self.mk_ty_from_kind(Adt(def, substs))
}
#[inline]
pub fn mk_foreign(self, def_id: DefId) -> Ty<'tcx> {
- self.mk_ty(Foreign(def_id))
+ self.mk_ty_from_kind(Foreign(def_id))
}
fn mk_generic_adt(self, wrapper_def_id: DefId, ty_param: Ty<'tcx>) -> Ty<'tcx> {
@@ -1788,11 +1764,11 @@ impl<'tcx> TyCtxt<'tcx> {
ty_param.into()
} else {
assert!(has_default);
- self.bound_type_of(param.def_id).subst(self, substs).into()
+ self.type_of(param.def_id).subst(self, substs).into()
}
}
});
- self.mk_ty(Adt(adt_def, substs))
+ self.mk_ty_from_kind(Adt(adt_def, substs))
}
#[inline]
@@ -1821,12 +1797,12 @@ impl<'tcx> TyCtxt<'tcx> {
#[inline]
pub fn mk_ptr(self, tm: TypeAndMut<'tcx>) -> Ty<'tcx> {
- self.mk_ty(RawPtr(tm))
+ self.mk_ty_from_kind(RawPtr(tm))
}
#[inline]
pub fn mk_ref(self, r: Region<'tcx>, tm: TypeAndMut<'tcx>) -> Ty<'tcx> {
- self.mk_ty(Ref(r, tm.ty, tm.mutbl))
+ self.mk_ty_from_kind(Ref(r, tm.ty, tm.mutbl))
}
#[inline]
@@ -1851,21 +1827,34 @@ impl<'tcx> TyCtxt<'tcx> {
#[inline]
pub fn mk_array(self, ty: Ty<'tcx>, n: u64) -> Ty<'tcx> {
- self.mk_ty(Array(ty, ty::Const::from_usize(self, n)))
+ self.mk_ty_from_kind(Array(ty, ty::Const::from_target_usize(self, n)))
+ }
+
+ #[inline]
+ pub fn mk_array_with_const_len(self, ty: Ty<'tcx>, ct: Const<'tcx>) -> Ty<'tcx> {
+ self.mk_ty_from_kind(Array(ty, ct))
}
#[inline]
pub fn mk_slice(self, ty: Ty<'tcx>) -> Ty<'tcx> {
- self.mk_ty(Slice(ty))
+ self.mk_ty_from_kind(Slice(ty))
}
#[inline]
- pub fn intern_tup(self, ts: &[Ty<'tcx>]) -> Ty<'tcx> {
- self.mk_ty(Tuple(self.intern_type_list(&ts)))
+ pub fn mk_tup(self, ts: &[Ty<'tcx>]) -> Ty<'tcx> {
+ if ts.is_empty() {
+ self.types.unit
+ } else {
+ self.mk_ty_from_kind(Tuple(self.mk_type_list(&ts)))
+ }
}
- pub fn mk_tup<I: InternAs<Ty<'tcx>, Ty<'tcx>>>(self, iter: I) -> I::Output {
- iter.intern_with(|ts| self.mk_ty(Tuple(self.intern_type_list(&ts))))
+ pub fn mk_tup_from_iter<I, T>(self, iter: I) -> T::Output
+ where
+ I: Iterator<Item = T>,
+ T: CollectAndApply<Ty<'tcx>, Ty<'tcx>>,
+ {
+ T::collect_and_apply(iter, |ts| self.mk_tup(ts))
}
#[inline]
@@ -1882,17 +1871,17 @@ impl<'tcx> TyCtxt<'tcx> {
pub fn mk_fn_def(
self,
def_id: DefId,
- substs: impl IntoIterator<Item = impl Into<GenericArg<'tcx>>>,
+ substs: impl IntoIterator<Item: Into<GenericArg<'tcx>>>,
) -> Ty<'tcx> {
- let substs = self.check_substs(def_id, substs);
- self.mk_ty(FnDef(def_id, substs))
+ let substs = self.check_and_mk_substs(def_id, substs);
+ self.mk_ty_from_kind(FnDef(def_id, substs))
}
#[inline(always)]
- fn check_substs(
+ fn check_and_mk_substs(
self,
_def_id: DefId,
- substs: impl IntoIterator<Item = impl Into<GenericArg<'tcx>>>,
+ substs: impl IntoIterator<Item: Into<GenericArg<'tcx>>>,
) -> SubstsRef<'tcx> {
let substs = substs.into_iter().map(Into::into);
#[cfg(debug_assertions)]
@@ -1905,12 +1894,12 @@ impl<'tcx> TyCtxt<'tcx> {
substs.collect::<Vec<_>>(),
);
}
- self.mk_substs(substs)
+ self.mk_substs_from_iter(substs)
}
#[inline]
pub fn mk_fn_ptr(self, fty: PolyFnSig<'tcx>) -> Ty<'tcx> {
- self.mk_ty(FnPtr(fty))
+ self.mk_ty_from_kind(FnPtr(fty))
}
#[inline]
@@ -1920,21 +1909,21 @@ impl<'tcx> TyCtxt<'tcx> {
reg: ty::Region<'tcx>,
repr: DynKind,
) -> Ty<'tcx> {
- self.mk_ty(Dynamic(obj, reg, repr))
+ self.mk_ty_from_kind(Dynamic(obj, reg, repr))
}
#[inline]
pub fn mk_projection(
self,
item_def_id: DefId,
- substs: impl IntoIterator<Item = impl Into<GenericArg<'tcx>>>,
+ substs: impl IntoIterator<Item: Into<GenericArg<'tcx>>>,
) -> Ty<'tcx> {
- self.mk_ty(Alias(ty::Projection, self.mk_alias_ty(item_def_id, substs)))
+ self.mk_alias(ty::Projection, self.mk_alias_ty(item_def_id, substs))
}
#[inline]
pub fn mk_closure(self, closure_id: DefId, closure_substs: SubstsRef<'tcx>) -> Ty<'tcx> {
- self.mk_ty(Closure(closure_id, closure_substs))
+ self.mk_ty_from_kind(Closure(closure_id, closure_substs))
}
#[inline]
@@ -1944,71 +1933,183 @@ impl<'tcx> TyCtxt<'tcx> {
generator_substs: SubstsRef<'tcx>,
movability: hir::Movability,
) -> Ty<'tcx> {
- self.mk_ty(Generator(id, generator_substs, movability))
+ self.mk_ty_from_kind(Generator(id, generator_substs, movability))
}
#[inline]
pub fn mk_generator_witness(self, types: ty::Binder<'tcx, &'tcx List<Ty<'tcx>>>) -> Ty<'tcx> {
- self.mk_ty(GeneratorWitness(types))
+ self.mk_ty_from_kind(GeneratorWitness(types))
}
/// Creates a `&mut Context<'_>` [`Ty`] with erased lifetimes.
pub fn mk_task_context(self) -> Ty<'tcx> {
let context_did = self.require_lang_item(LangItem::Context, None);
let context_adt_ref = self.adt_def(context_did);
- let context_substs = self.intern_substs(&[self.lifetimes.re_erased.into()]);
+ let context_substs = self.mk_substs(&[self.lifetimes.re_erased.into()]);
let context_ty = self.mk_adt(context_adt_ref, context_substs);
self.mk_mut_ref(self.lifetimes.re_erased, context_ty)
}
#[inline]
- pub fn mk_ty_var(self, v: TyVid) -> Ty<'tcx> {
- self.mk_ty_infer(TyVar(v))
+ pub fn mk_generator_witness_mir(self, id: DefId, substs: SubstsRef<'tcx>) -> Ty<'tcx> {
+ self.mk_ty_from_kind(GeneratorWitnessMIR(id, substs))
}
#[inline]
pub fn mk_const(self, kind: impl Into<ty::ConstKind<'tcx>>, ty: Ty<'tcx>) -> Const<'tcx> {
- self.mk_const_internal(ty::ConstData { kind: kind.into(), ty })
+ self.intern_const(ty::ConstData { kind: kind.into(), ty })
+ }
+
+ #[inline]
+ pub fn mk_ty_var(self, v: TyVid) -> Ty<'tcx> {
+ // Use a pre-interned one when possible.
+ self.types
+ .ty_vars
+ .get(v.as_usize())
+ .copied()
+ .unwrap_or_else(|| self.mk_ty_from_kind(Infer(TyVar(v))))
}
#[inline]
pub fn mk_int_var(self, v: IntVid) -> Ty<'tcx> {
- self.mk_ty_infer(IntVar(v))
+ self.mk_ty_from_kind(Infer(IntVar(v)))
}
#[inline]
pub fn mk_float_var(self, v: FloatVid) -> Ty<'tcx> {
- self.mk_ty_infer(FloatVar(v))
+ self.mk_ty_from_kind(Infer(FloatVar(v)))
+ }
+
+ #[inline]
+ pub fn mk_fresh_ty(self, n: u32) -> Ty<'tcx> {
+ // Use a pre-interned one when possible.
+ self.types
+ .fresh_tys
+ .get(n as usize)
+ .copied()
+ .unwrap_or_else(|| self.mk_ty_from_kind(Infer(ty::FreshTy(n))))
}
#[inline]
- pub fn mk_ty_infer(self, it: InferTy) -> Ty<'tcx> {
- self.mk_ty(Infer(it))
+ pub fn mk_fresh_int_ty(self, n: u32) -> Ty<'tcx> {
+ // Use a pre-interned one when possible.
+ self.types
+ .fresh_int_tys
+ .get(n as usize)
+ .copied()
+ .unwrap_or_else(|| self.mk_ty_from_kind(Infer(ty::FreshIntTy(n))))
+ }
+
+ #[inline]
+ pub fn mk_fresh_float_ty(self, n: u32) -> Ty<'tcx> {
+ // Use a pre-interned one when possible.
+ self.types
+ .fresh_float_tys
+ .get(n as usize)
+ .copied()
+ .unwrap_or_else(|| self.mk_ty_from_kind(Infer(ty::FreshFloatTy(n))))
}
#[inline]
pub fn mk_ty_param(self, index: u32, name: Symbol) -> Ty<'tcx> {
- self.mk_ty(Param(ParamTy { index, name }))
+ self.mk_ty_from_kind(Param(ParamTy { index, name }))
}
pub fn mk_param_from_def(self, param: &ty::GenericParamDef) -> GenericArg<'tcx> {
match param.kind {
GenericParamDefKind::Lifetime => {
- self.mk_region(ty::ReEarlyBound(param.to_early_bound_region_data())).into()
+ self.mk_re_early_bound(param.to_early_bound_region_data()).into()
}
GenericParamDefKind::Type { .. } => self.mk_ty_param(param.index, param.name).into(),
GenericParamDefKind::Const { .. } => self
.mk_const(
ParamConst { index: param.index, name: param.name },
- self.type_of(param.def_id),
+ self.type_of(param.def_id)
+ .no_bound_vars()
+ .expect("const parameter types cannot be generic"),
)
.into(),
}
}
#[inline]
+ pub fn mk_bound(self, index: ty::DebruijnIndex, bound_ty: ty::BoundTy) -> Ty<'tcx> {
+ self.mk_ty_from_kind(Bound(index, bound_ty))
+ }
+
+ #[inline]
+ pub fn mk_placeholder(self, placeholder: ty::PlaceholderType) -> Ty<'tcx> {
+ self.mk_ty_from_kind(Placeholder(placeholder))
+ }
+
+ #[inline]
+ pub fn mk_alias(self, kind: ty::AliasKind, alias_ty: ty::AliasTy<'tcx>) -> Ty<'tcx> {
+ self.mk_ty_from_kind(Alias(kind, alias_ty))
+ }
+
+ #[inline]
pub fn mk_opaque(self, def_id: DefId, substs: SubstsRef<'tcx>) -> Ty<'tcx> {
- self.mk_ty(Alias(ty::Opaque, self.mk_alias_ty(def_id, substs)))
+ self.mk_alias(ty::Opaque, self.mk_alias_ty(def_id, substs))
+ }
+
+ #[inline]
+ pub fn mk_re_early_bound(self, early_bound_region: ty::EarlyBoundRegion) -> Region<'tcx> {
+ self.intern_region(ty::ReEarlyBound(early_bound_region))
+ }
+
+ #[inline]
+ pub fn mk_re_late_bound(
+ self,
+ debruijn: ty::DebruijnIndex,
+ bound_region: ty::BoundRegion,
+ ) -> Region<'tcx> {
+ // Use a pre-interned one when possible.
+ if let ty::BoundRegion { var, kind: ty::BrAnon(v, None) } = bound_region
+ && var.as_u32() == v
+ && let Some(inner) = self.lifetimes.re_late_bounds.get(debruijn.as_usize())
+ && let Some(re) = inner.get(v as usize).copied()
+ {
+ re
+ } else {
+ self.intern_region(ty::ReLateBound(debruijn, bound_region))
+ }
+ }
+
+ #[inline]
+ pub fn mk_re_free(self, scope: DefId, bound_region: ty::BoundRegionKind) -> Region<'tcx> {
+ self.intern_region(ty::ReFree(ty::FreeRegion { scope, bound_region }))
+ }
+
+ #[inline]
+ pub fn mk_re_var(self, v: ty::RegionVid) -> Region<'tcx> {
+ // Use a pre-interned one when possible.
+ self.lifetimes
+ .re_vars
+ .get(v.as_usize())
+ .copied()
+ .unwrap_or_else(|| self.intern_region(ty::ReVar(v)))
+ }
+
+ #[inline]
+ pub fn mk_re_placeholder(self, placeholder: ty::PlaceholderRegion) -> Region<'tcx> {
+ self.intern_region(ty::RePlaceholder(placeholder))
+ }
+
+ // Avoid this in favour of more specific `mk_re_*` methods, where possible,
+ // to avoid the cost of the `match`.
+ pub fn mk_region_from_kind(self, kind: ty::RegionKind<'tcx>) -> Region<'tcx> {
+ match kind {
+ ty::ReEarlyBound(region) => self.mk_re_early_bound(region),
+ ty::ReLateBound(debruijn, region) => self.mk_re_late_bound(debruijn, region),
+ ty::ReFree(ty::FreeRegion { scope, bound_region }) => {
+ self.mk_re_free(scope, bound_region)
+ }
+ ty::ReStatic => self.lifetimes.re_static,
+ ty::ReVar(vid) => self.mk_re_var(vid),
+ ty::RePlaceholder(region) => self.mk_re_placeholder(region),
+ ty::ReErased => self.lifetimes.re_erased,
+ ty::ReError(reported) => self.mk_re_error(reported),
+ }
}
pub fn mk_place_field(self, place: Place<'tcx>, f: Field, ty: Ty<'tcx>) -> Place<'tcx> {
@@ -2050,10 +2151,10 @@ impl<'tcx> TyCtxt<'tcx> {
let mut projection = place.projection.to_vec();
projection.push(elem);
- Place { local: place.local, projection: self.intern_place_elems(&projection) }
+ Place { local: place.local, projection: self.mk_place_elems(&projection) }
}
- pub fn intern_poly_existential_predicates(
+ pub fn mk_poly_existential_predicates(
self,
eps: &[PolyExistentialPredicate<'tcx>],
) -> &'tcx List<PolyExistentialPredicate<'tcx>> {
@@ -2063,125 +2164,109 @@ impl<'tcx> TyCtxt<'tcx> {
.all(|[a, b]| a.skip_binder().stable_cmp(self, &b.skip_binder())
!= Ordering::Greater)
);
- self._intern_poly_existential_predicates(eps)
+ self.intern_poly_existential_predicates(eps)
}
- pub fn intern_predicates(self, preds: &[Predicate<'tcx>]) -> &'tcx List<Predicate<'tcx>> {
+ pub fn mk_predicates(self, preds: &[Predicate<'tcx>]) -> &'tcx List<Predicate<'tcx>> {
// FIXME consider asking the input slice to be sorted to avoid
// re-interning permutations, in which case that would be asserted
// here.
- if preds.is_empty() {
- // The macro-generated method below asserts we don't intern an empty slice.
- List::empty()
- } else {
- self._intern_predicates(preds)
- }
- }
-
- pub fn mk_const_list<I: InternAs<ty::Const<'tcx>, &'tcx List<ty::Const<'tcx>>>>(
- self,
- iter: I,
- ) -> I::Output {
- iter.intern_with(|xs| self.intern_const_list(xs))
- }
-
- pub fn intern_const_list(self, cs: &[ty::Const<'tcx>]) -> &'tcx List<ty::Const<'tcx>> {
- if cs.is_empty() { List::empty() } else { self._intern_const_list(cs) }
- }
-
- pub fn intern_type_list(self, ts: &[Ty<'tcx>]) -> &'tcx List<Ty<'tcx>> {
- if ts.is_empty() {
- List::empty()
- } else {
- // Actually intern type lists as lists of `GenericArg`s.
- //
- // Transmuting from `Ty<'tcx>` to `GenericArg<'tcx>` is sound
- // as explained in ty_slice_as_generic_arg`. With this,
- // we guarantee that even when transmuting between `List<Ty<'tcx>>`
- // and `List<GenericArg<'tcx>>`, the uniqueness requirement for
- // lists is upheld.
- let substs = self._intern_substs(ty::subst::ty_slice_as_generic_args(ts));
- substs.try_as_type_list().unwrap()
- }
- }
-
- pub fn intern_substs(self, ts: &[GenericArg<'tcx>]) -> &'tcx List<GenericArg<'tcx>> {
- if ts.is_empty() { List::empty() } else { self._intern_substs(ts) }
+ self.intern_predicates(preds)
}
- pub fn intern_projs(self, ps: &[ProjectionKind]) -> &'tcx List<ProjectionKind> {
- if ps.is_empty() { List::empty() } else { self._intern_projs(ps) }
- }
-
- pub fn intern_place_elems(self, ts: &[PlaceElem<'tcx>]) -> &'tcx List<PlaceElem<'tcx>> {
- if ts.is_empty() { List::empty() } else { self._intern_place_elems(ts) }
- }
-
- pub fn intern_canonical_var_infos(
- self,
- ts: &[CanonicalVarInfo<'tcx>],
- ) -> CanonicalVarInfos<'tcx> {
- if ts.is_empty() { List::empty() } else { self._intern_canonical_var_infos(ts) }
- }
-
- pub fn intern_bound_variable_kinds(
- self,
- ts: &[ty::BoundVariableKind],
- ) -> &'tcx List<ty::BoundVariableKind> {
- if ts.is_empty() { List::empty() } else { self._intern_bound_variable_kinds(ts) }
+ pub fn mk_const_list_from_iter<I, T>(self, iter: I) -> T::Output
+ where
+ I: Iterator<Item = T>,
+ T: CollectAndApply<ty::Const<'tcx>, &'tcx List<ty::Const<'tcx>>>,
+ {
+ T::collect_and_apply(iter, |xs| self.mk_const_list(xs))
}
- pub fn mk_fn_sig<I>(
+ pub fn mk_type_list(self, ts: &[Ty<'tcx>]) -> &'tcx List<Ty<'tcx>> {
+ // Actually intern type lists as lists of `GenericArg`s.
+ //
+ // Transmuting from `Ty<'tcx>` to `GenericArg<'tcx>` is sound
+ // as explained in `ty_slice_as_generic_arg`. With this,
+ // we guarantee that even when transmuting between `List<Ty<'tcx>>`
+ // and `List<GenericArg<'tcx>>`, the uniqueness requirement for
+ // lists is upheld.
+ let substs = self.mk_substs(ty::subst::ty_slice_as_generic_args(ts));
+ substs.try_as_type_list().unwrap()
+ }
+
+ // Unlike various other `mk_*_from_iter` functions, this one uses `I:
+ // IntoIterator` instead of `I: Iterator`, and it doesn't have a slice
+ // variant, because of the need to combine `inputs` and `output`. This
+ // explains the lack of `_from_iter` suffix.
+ pub fn mk_fn_sig<I, T>(
self,
inputs: I,
output: I::Item,
c_variadic: bool,
unsafety: hir::Unsafety,
abi: abi::Abi,
- ) -> <I::Item as InternIteratorElement<Ty<'tcx>, ty::FnSig<'tcx>>>::Output
+ ) -> T::Output
where
- I: Iterator<Item: InternIteratorElement<Ty<'tcx>, ty::FnSig<'tcx>>>,
+ I: IntoIterator<Item = T>,
+ T: CollectAndApply<Ty<'tcx>, ty::FnSig<'tcx>>,
{
- inputs.chain(iter::once(output)).intern_with(|xs| ty::FnSig {
- inputs_and_output: self.intern_type_list(xs),
+ T::collect_and_apply(inputs.into_iter().chain(iter::once(output)), |xs| ty::FnSig {
+ inputs_and_output: self.mk_type_list(xs),
c_variadic,
unsafety,
abi,
})
}
- pub fn mk_poly_existential_predicates<
- I: InternAs<PolyExistentialPredicate<'tcx>, &'tcx List<PolyExistentialPredicate<'tcx>>>,
- >(
- self,
- iter: I,
- ) -> I::Output {
- iter.intern_with(|xs| self.intern_poly_existential_predicates(xs))
+ pub fn mk_poly_existential_predicates_from_iter<I, T>(self, iter: I) -> T::Output
+ where
+ I: Iterator<Item = T>,
+ T: CollectAndApply<
+ PolyExistentialPredicate<'tcx>,
+ &'tcx List<PolyExistentialPredicate<'tcx>>,
+ >,
+ {
+ T::collect_and_apply(iter, |xs| self.mk_poly_existential_predicates(xs))
}
- pub fn mk_predicates<I: InternAs<Predicate<'tcx>, &'tcx List<Predicate<'tcx>>>>(
- self,
- iter: I,
- ) -> I::Output {
- iter.intern_with(|xs| self.intern_predicates(xs))
+ pub fn mk_predicates_from_iter<I, T>(self, iter: I) -> T::Output
+ where
+ I: Iterator<Item = T>,
+ T: CollectAndApply<Predicate<'tcx>, &'tcx List<Predicate<'tcx>>>,
+ {
+ T::collect_and_apply(iter, |xs| self.mk_predicates(xs))
}
- pub fn mk_type_list<I: InternAs<Ty<'tcx>, &'tcx List<Ty<'tcx>>>>(self, iter: I) -> I::Output {
- iter.intern_with(|xs| self.intern_type_list(xs))
+ pub fn mk_type_list_from_iter<I, T>(self, iter: I) -> T::Output
+ where
+ I: Iterator<Item = T>,
+ T: CollectAndApply<Ty<'tcx>, &'tcx List<Ty<'tcx>>>,
+ {
+ T::collect_and_apply(iter, |xs| self.mk_type_list(xs))
}
- pub fn mk_substs<I: InternAs<GenericArg<'tcx>, &'tcx List<GenericArg<'tcx>>>>(
- self,
- iter: I,
- ) -> I::Output {
- iter.intern_with(|xs| self.intern_substs(xs))
+ pub fn mk_substs_from_iter<I, T>(self, iter: I) -> T::Output
+ where
+ I: Iterator<Item = T>,
+ T: CollectAndApply<GenericArg<'tcx>, &'tcx List<GenericArg<'tcx>>>,
+ {
+ T::collect_and_apply(iter, |xs| self.mk_substs(xs))
}
- pub fn mk_place_elems<I: InternAs<PlaceElem<'tcx>, &'tcx List<PlaceElem<'tcx>>>>(
- self,
- iter: I,
- ) -> I::Output {
- iter.intern_with(|xs| self.intern_place_elems(xs))
+ pub fn mk_canonical_var_infos_from_iter<I, T>(self, iter: I) -> T::Output
+ where
+ I: Iterator<Item = T>,
+ T: CollectAndApply<CanonicalVarInfo<'tcx>, &'tcx List<CanonicalVarInfo<'tcx>>>,
+ {
+ T::collect_and_apply(iter, |xs| self.mk_canonical_var_infos(xs))
+ }
+
+ pub fn mk_place_elems_from_iter<I, T>(self, iter: I) -> T::Output
+ where
+ I: Iterator<Item = T>,
+ T: CollectAndApply<PlaceElem<'tcx>, &'tcx List<PlaceElem<'tcx>>>,
+ {
+ T::collect_and_apply(iter, |xs| self.mk_place_elems(xs))
}
pub fn mk_substs_trait(
@@ -2189,34 +2274,33 @@ impl<'tcx> TyCtxt<'tcx> {
self_ty: Ty<'tcx>,
rest: impl IntoIterator<Item = GenericArg<'tcx>>,
) -> SubstsRef<'tcx> {
- self.mk_substs(iter::once(self_ty.into()).chain(rest))
+ self.mk_substs_from_iter(iter::once(self_ty.into()).chain(rest))
}
pub fn mk_trait_ref(
self,
trait_def_id: DefId,
- substs: impl IntoIterator<Item = impl Into<GenericArg<'tcx>>>,
+ substs: impl IntoIterator<Item: Into<GenericArg<'tcx>>>,
) -> ty::TraitRef<'tcx> {
- let substs = self.check_substs(trait_def_id, substs);
+ let substs = self.check_and_mk_substs(trait_def_id, substs);
ty::TraitRef { def_id: trait_def_id, substs, _use_mk_trait_ref_instead: () }
}
pub fn mk_alias_ty(
self,
def_id: DefId,
- substs: impl IntoIterator<Item = impl Into<GenericArg<'tcx>>>,
+ substs: impl IntoIterator<Item: Into<GenericArg<'tcx>>>,
) -> ty::AliasTy<'tcx> {
- let substs = self.check_substs(def_id, substs);
+ let substs = self.check_and_mk_substs(def_id, substs);
ty::AliasTy { def_id, substs, _use_mk_alias_ty_instead: () }
}
- pub fn mk_bound_variable_kinds<
- I: InternAs<ty::BoundVariableKind, &'tcx List<ty::BoundVariableKind>>,
- >(
- self,
- iter: I,
- ) -> I::Output {
- iter.intern_with(|xs| self.intern_bound_variable_kinds(xs))
+ pub fn mk_bound_variable_kinds_from_iter<I, T>(self, iter: I) -> T::Output
+ where
+ I: Iterator<Item = T>,
+ T: CollectAndApply<ty::BoundVariableKind, &'tcx List<ty::BoundVariableKind>>,
+ {
+ T::collect_and_apply(iter, |xs| self.mk_bound_variable_kinds(xs))
}
/// Emit a lint at `span` from a lint struct (some type that implements `DecorateLint`,
@@ -2291,26 +2375,23 @@ impl<'tcx> TyCtxt<'tcx> {
Some(&*candidates)
}
- pub fn named_region(self, id: HirId) -> Option<resolve_lifetime::Region> {
+ pub fn named_bound_var(self, id: HirId) -> Option<resolve_bound_vars::ResolvedArg> {
debug!(?id, "named_region");
- self.named_region_map(id.owner).and_then(|map| map.get(&id.local_id).cloned())
+ self.named_variable_map(id.owner).and_then(|map| map.get(&id.local_id).cloned())
}
pub fn is_late_bound(self, id: HirId) -> bool {
- self.is_late_bound_map(id.owner.def_id).map_or(false, |set| {
- let def_id = self.hir().local_def_id(id);
- set.contains(&def_id)
- })
+ self.is_late_bound_map(id.owner).map_or(false, |set| set.contains(&id.local_id))
}
pub fn late_bound_vars(self, id: HirId) -> &'tcx List<ty::BoundVariableKind> {
self.mk_bound_variable_kinds(
- self.late_bound_vars_map(id.owner)
+ &self
+ .late_bound_vars_map(id.owner)
.and_then(|map| map.get(&id.local_id).cloned())
.unwrap_or_else(|| {
- bug!("No bound vars found for {:?} ({:?})", self.hir().node_to_string(id), id)
- })
- .iter(),
+ bug!("No bound vars found for {}", self.hir().node_to_string(id))
+ }),
)
}
@@ -2351,16 +2432,24 @@ impl<'tcx> TyCtxt<'tcx> {
})
)
}
+
+ pub fn local_def_id_to_hir_id(self, local_def_id: LocalDefId) -> HirId {
+ self.opt_local_def_id_to_hir_id(local_def_id).unwrap()
+ }
+
+ pub fn trait_solver_next(self) -> bool {
+ self.sess.opts.unstable_opts.trait_solver == rustc_session::config::TraitSolver::Next
+ }
}
impl<'tcx> TyCtxtAt<'tcx> {
/// Constructs a `TyKind::Error` type and registers a `delay_span_bug` to ensure it gets used.
#[track_caller]
- pub fn ty_error(self) -> Ty<'tcx> {
+ pub fn ty_error_misc(self) -> Ty<'tcx> {
self.tcx.ty_error_with_message(self.span, "TyKind::Error constructed but no error reported")
}
- /// Constructs a `TyKind::Error` type and registers a `delay_span_bug` with the given `msg to
+ /// Constructs a `TyKind::Error` type and registers a `delay_span_bug` with the given `msg` to
/// ensure it gets used.
#[track_caller]
pub fn ty_error_with_message(self, msg: &str) -> Ty<'tcx> {
@@ -2370,7 +2459,7 @@ impl<'tcx> TyCtxtAt<'tcx> {
pub fn mk_trait_ref(
self,
trait_lang_item: LangItem,
- substs: impl IntoIterator<Item = impl Into<ty::GenericArg<'tcx>>>,
+ substs: impl IntoIterator<Item: Into<ty::GenericArg<'tcx>>>,
) -> ty::TraitRef<'tcx> {
let trait_def_id = self.require_lang_item(trait_lang_item, Some(self.span));
self.tcx.mk_trait_ref(trait_def_id, substs)
@@ -2392,19 +2481,11 @@ pub struct DeducedParamAttrs {
pub read_only: bool,
}
-// We are comparing types with different invariant lifetimes, so `ptr::eq`
-// won't work for us.
-fn ptr_eq<T, U>(t: *const T, u: *const U) -> bool {
- t as *const () == u as *const ()
-}
-
pub fn provide(providers: &mut ty::query::Providers) {
providers.module_reexports =
|tcx, id| tcx.resolutions(()).reexport_map.get(&id).map(|v| &v[..]);
providers.maybe_unused_trait_imports =
|tcx, ()| &tcx.resolutions(()).maybe_unused_trait_imports;
- providers.maybe_unused_extern_crates =
- |tcx, ()| &tcx.resolutions(()).maybe_unused_extern_crates[..];
providers.names_imported_by_glob_use = |tcx, id| {
tcx.arena.alloc(tcx.resolutions(()).glob_map.get(&id).cloned().unwrap_or_default())
};
@@ -2424,6 +2505,5 @@ pub fn provide(providers: &mut ty::query::Providers) {
// We want to check if the panic handler was defined in this crate
tcx.lang_items().panic_impl().map_or(false, |did| did.is_local())
};
- providers.source_span =
- |tcx, def_id| tcx.untracked.source_span.get(def_id).copied().unwrap_or(DUMMY_SP);
+ providers.source_span = |tcx, def_id| tcx.untracked.source_span.get(def_id).unwrap_or(DUMMY_SP);
}
diff --git a/compiler/rustc_middle/src/ty/context/tls.rs b/compiler/rustc_middle/src/ty/context/tls.rs
new file mode 100644
index 000000000..5426ac8d7
--- /dev/null
+++ b/compiler/rustc_middle/src/ty/context/tls.rs
@@ -0,0 +1,186 @@
+use super::{GlobalCtxt, TyCtxt};
+
+use crate::dep_graph::TaskDepsRef;
+use crate::ty::query;
+use rustc_data_structures::sync::{self, Lock};
+use rustc_errors::Diagnostic;
+use std::mem;
+use std::ptr;
+use thin_vec::ThinVec;
+
+/// This is the implicit state of rustc. It contains the current
+/// `TyCtxt` and query. It is updated when creating a local interner or
+/// executing a new query. Whenever there's a `TyCtxt` value available
+/// you should also have access to an `ImplicitCtxt` through the functions
+/// in this module.
+#[derive(Clone)]
+pub struct ImplicitCtxt<'a, 'tcx> {
+ /// The current `TyCtxt`.
+ pub tcx: TyCtxt<'tcx>,
+
+ /// The current query job, if any. This is updated by `JobOwner::start` in
+ /// `ty::query::plumbing` when executing a query.
+ pub query: Option<query::QueryJobId>,
+
+ /// Where to store diagnostics for the current query job, if any.
+ /// This is updated by `JobOwner::start` in `ty::query::plumbing` when executing a query.
+ pub diagnostics: Option<&'a Lock<ThinVec<Diagnostic>>>,
+
+ /// Used to prevent queries from calling too deeply.
+ pub query_depth: usize,
+
+ /// The current dep graph task. This is used to add dependencies to queries
+ /// when executing them.
+ pub task_deps: TaskDepsRef<'a>,
+}
+
+impl<'a, 'tcx> ImplicitCtxt<'a, 'tcx> {
+ pub fn new(gcx: &'tcx GlobalCtxt<'tcx>) -> Self {
+ let tcx = TyCtxt { gcx };
+ ImplicitCtxt {
+ tcx,
+ query: None,
+ diagnostics: None,
+ query_depth: 0,
+ task_deps: TaskDepsRef::Ignore,
+ }
+ }
+}
+
+#[cfg(parallel_compiler)]
+mod tlv {
+ use rustc_rayon_core as rayon_core;
+ use std::ptr;
+
+ /// Gets Rayon's thread-local variable, which is preserved for Rayon jobs.
+ /// This is used to get the pointer to the current `ImplicitCtxt`.
+ #[inline]
+ pub(super) fn get_tlv() -> *const () {
+ ptr::from_exposed_addr(rayon_core::tlv::get())
+ }
+
+ /// Sets Rayon's thread-local variable, which is preserved for Rayon jobs
+ /// to `value` during the call to `f`. It is restored to its previous value after.
+ /// This is used to set the pointer to the new `ImplicitCtxt`.
+ #[inline]
+ pub(super) fn with_tlv<F: FnOnce() -> R, R>(value: *const (), f: F) -> R {
+ rayon_core::tlv::with(value.expose_addr(), f)
+ }
+}
+
+#[cfg(not(parallel_compiler))]
+mod tlv {
+ use std::cell::Cell;
+ use std::ptr;
+
+ thread_local! {
+ /// A thread local variable that stores a pointer to the current `ImplicitCtxt`.
+ static TLV: Cell<*const ()> = const { Cell::new(ptr::null()) };
+ }
+
+ /// Gets the pointer to the current `ImplicitCtxt`.
+ #[inline]
+ pub(super) fn get_tlv() -> *const () {
+ TLV.with(|tlv| tlv.get())
+ }
+
+ /// Sets TLV to `value` during the call to `f`.
+ /// It is restored to its previous value after.
+ /// This is used to set the pointer to the new `ImplicitCtxt`.
+ #[inline]
+ pub(super) fn with_tlv<F: FnOnce() -> R, R>(value: *const (), f: F) -> R {
+ let old = TLV.replace(value);
+ let _reset = rustc_data_structures::OnDrop(move || TLV.set(old));
+ f()
+ }
+}
+
+#[inline]
+fn erase(context: &ImplicitCtxt<'_, '_>) -> *const () {
+ context as *const _ as *const ()
+}
+
+#[inline]
+unsafe fn downcast<'a, 'tcx>(context: *const ()) -> &'a ImplicitCtxt<'a, 'tcx> {
+ &*(context as *const ImplicitCtxt<'a, 'tcx>)
+}
+
+/// Sets `context` as the new current `ImplicitCtxt` for the duration of the function `f`.
+#[inline]
+pub fn enter_context<'a, 'tcx, F, R>(context: &ImplicitCtxt<'a, 'tcx>, f: F) -> R
+where
+ F: FnOnce() -> R,
+{
+ tlv::with_tlv(erase(context), f)
+}
+
+/// Allows access to the current `ImplicitCtxt` in a closure if one is available.
+#[inline]
+pub fn with_context_opt<F, R>(f: F) -> R
+where
+ F: for<'a, 'tcx> FnOnce(Option<&ImplicitCtxt<'a, 'tcx>>) -> R,
+{
+ let context = tlv::get_tlv();
+ if context.is_null() {
+ f(None)
+ } else {
+ // We could get an `ImplicitCtxt` pointer from another thread.
+ // Ensure that `ImplicitCtxt` is `Sync`.
+ sync::assert_sync::<ImplicitCtxt<'_, '_>>();
+
+ unsafe { f(Some(downcast(context))) }
+ }
+}
+
+/// Allows access to the current `ImplicitCtxt`.
+/// Panics if there is no `ImplicitCtxt` available.
+#[inline]
+pub fn with_context<F, R>(f: F) -> R
+where
+ F: for<'a, 'tcx> FnOnce(&ImplicitCtxt<'a, 'tcx>) -> R,
+{
+ with_context_opt(|opt_context| f(opt_context.expect("no ImplicitCtxt stored in tls")))
+}
+
+/// Allows access to the current `ImplicitCtxt` whose tcx field is the same as the tcx argument
+/// passed in. This means the closure is given an `ImplicitCtxt` with the same `'tcx` lifetime
+/// as the `TyCtxt` passed in.
+/// This will panic if you pass it a `TyCtxt` which is different from the current
+/// `ImplicitCtxt`'s `tcx` field.
+#[inline]
+pub fn with_related_context<'tcx, F, R>(tcx: TyCtxt<'tcx>, f: F) -> R
+where
+ F: FnOnce(&ImplicitCtxt<'_, 'tcx>) -> R,
+{
+ with_context(|context| {
+ // The two gcx have different invariant lifetimes, so we need to erase them for the comparison.
+ assert!(ptr::eq(
+ context.tcx.gcx as *const _ as *const (),
+ tcx.gcx as *const _ as *const ()
+ ));
+
+ let context: &ImplicitCtxt<'_, '_> = unsafe { mem::transmute(context) };
+
+ f(context)
+ })
+}
+
+/// Allows access to the `TyCtxt` in the current `ImplicitCtxt`.
+/// Panics if there is no `ImplicitCtxt` available.
+#[inline]
+pub fn with<F, R>(f: F) -> R
+where
+ F: for<'tcx> FnOnce(TyCtxt<'tcx>) -> R,
+{
+ with_context(|context| f(context.tcx))
+}
+
+/// Allows access to the `TyCtxt` in the current `ImplicitCtxt`.
+/// The closure is passed None if there is no `ImplicitCtxt` available.
+#[inline]
+pub fn with_opt<F, R>(f: F) -> R
+where
+ F: for<'tcx> FnOnce(Option<TyCtxt<'tcx>>) -> R,
+{
+ with_context_opt(|opt_context| f(opt_context.map(|context| context.tcx)))
+}
diff --git a/compiler/rustc_middle/src/ty/diagnostics.rs b/compiler/rustc_middle/src/ty/diagnostics.rs
index 4b4518f61..e894e1aaf 100644
--- a/compiler/rustc_middle/src/ty/diagnostics.rs
+++ b/compiler/rustc_middle/src/ty/diagnostics.rs
@@ -3,8 +3,9 @@
use std::ops::ControlFlow;
use crate::ty::{
- visit::TypeVisitable, AliasTy, Const, ConstKind, DefIdTree, InferConst, InferTy, Opaque,
- PolyTraitPredicate, Projection, Ty, TyCtxt, TypeSuperVisitable, TypeVisitor,
+ AliasTy, Const, ConstKind, DefIdTree, FallibleTypeFolder, InferConst, InferTy, Opaque,
+ PolyTraitPredicate, Projection, Ty, TyCtxt, TypeFoldable, TypeSuperFoldable,
+ TypeSuperVisitable, TypeVisitable, TypeVisitor,
};
use rustc_data_structures::fx::FxHashMap;
@@ -76,7 +77,7 @@ impl<'tcx> Ty<'tcx> {
}
}
-pub trait IsSuggestable<'tcx> {
+pub trait IsSuggestable<'tcx>: Sized {
/// Whether this makes sense to suggest in a diagnostic.
///
/// We filter out certain types and constants since they don't provide
@@ -87,15 +88,21 @@ pub trait IsSuggestable<'tcx> {
/// Only if `infer_suggestable` is true, we consider type and const
/// inference variables to be suggestable.
fn is_suggestable(self, tcx: TyCtxt<'tcx>, infer_suggestable: bool) -> bool;
+
+ fn make_suggestable(self, tcx: TyCtxt<'tcx>, infer_suggestable: bool) -> Option<Self>;
}
impl<'tcx, T> IsSuggestable<'tcx> for T
where
- T: TypeVisitable<'tcx>,
+ T: TypeVisitable<TyCtxt<'tcx>> + TypeFoldable<TyCtxt<'tcx>>,
{
fn is_suggestable(self, tcx: TyCtxt<'tcx>, infer_suggestable: bool) -> bool {
self.visit_with(&mut IsSuggestableVisitor { tcx, infer_suggestable }).is_continue()
}
+
+ fn make_suggestable(self, tcx: TyCtxt<'tcx>, infer_suggestable: bool) -> Option<T> {
+ self.try_fold_with(&mut MakeSuggestableFolder { tcx, infer_suggestable }).ok()
+ }
}
pub fn suggest_arbitrary_trait_bound<'tcx>(
@@ -186,6 +193,9 @@ fn suggest_removing_unsized_bound(
}
/// Suggest restricting a type param with a new bound.
+///
+/// If `span_to_replace` is provided, then that span will be replaced with the
+/// `constraint`. If one wasn't provided, then the full bound will be suggested.
pub fn suggest_constraining_type_param(
tcx: TyCtxt<'_>,
generics: &hir::Generics<'_>,
@@ -193,12 +203,14 @@ pub fn suggest_constraining_type_param(
param_name: &str,
constraint: &str,
def_id: Option<DefId>,
+ span_to_replace: Option<Span>,
) -> bool {
suggest_constraining_type_params(
tcx,
generics,
err,
[(param_name, constraint, def_id)].into_iter(),
+ span_to_replace,
)
}
@@ -208,6 +220,7 @@ pub fn suggest_constraining_type_params<'a>(
generics: &hir::Generics<'_>,
err: &mut Diagnostic,
param_names_and_constraints: impl Iterator<Item = (&'a str, &'a str, Option<DefId>)>,
+ span_to_replace: Option<Span>,
) -> bool {
let mut grouped = FxHashMap::default();
param_names_and_constraints.for_each(|(param_name, constraint, def_id)| {
@@ -246,7 +259,9 @@ pub fn suggest_constraining_type_params<'a>(
let mut suggest_restrict = |span, bound_list_non_empty| {
suggestions.push((
span,
- if bound_list_non_empty {
+ if span_to_replace.is_some() {
+ constraint.clone()
+ } else if bound_list_non_empty {
format!(" + {}", constraint)
} else {
format!(" {}", constraint)
@@ -255,6 +270,11 @@ pub fn suggest_constraining_type_params<'a>(
))
};
+ if let Some(span) = span_to_replace {
+ suggest_restrict(span, true);
+ continue;
+ }
+
// When the type parameter has been provided bounds
//
// Message:
@@ -440,7 +460,7 @@ pub struct IsSuggestableVisitor<'tcx> {
infer_suggestable: bool,
}
-impl<'tcx> TypeVisitor<'tcx> for IsSuggestableVisitor<'tcx> {
+impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for IsSuggestableVisitor<'tcx> {
type BreakTy = ();
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
@@ -460,8 +480,9 @@ impl<'tcx> TypeVisitor<'tcx> for IsSuggestableVisitor<'tcx> {
Alias(Opaque, AliasTy { def_id, .. }) => {
let parent = self.tcx.parent(def_id);
+ let parent_ty = self.tcx.type_of(parent).subst_identity();
if let DefKind::TyAlias | DefKind::AssocTy = self.tcx.def_kind(parent)
- && let Alias(Opaque, AliasTy { def_id: parent_opaque_def_id, .. }) = *self.tcx.type_of(parent).kind()
+ && let Alias(Opaque, AliasTy { def_id: parent_opaque_def_id, .. }) = *parent_ty.kind()
&& parent_opaque_def_id == def_id
{
// Okay
@@ -509,3 +530,92 @@ impl<'tcx> TypeVisitor<'tcx> for IsSuggestableVisitor<'tcx> {
c.super_visit_with(self)
}
}
+
+pub struct MakeSuggestableFolder<'tcx> {
+ tcx: TyCtxt<'tcx>,
+ infer_suggestable: bool,
+}
+
+impl<'tcx> FallibleTypeFolder<TyCtxt<'tcx>> for MakeSuggestableFolder<'tcx> {
+ type Error = ();
+
+ fn interner(&self) -> TyCtxt<'tcx> {
+ self.tcx
+ }
+
+ fn try_fold_ty(&mut self, t: Ty<'tcx>) -> Result<Ty<'tcx>, Self::Error> {
+ let t = match *t.kind() {
+ Infer(InferTy::TyVar(_)) if self.infer_suggestable => t,
+
+ FnDef(def_id, substs) => {
+ self.tcx.mk_fn_ptr(self.tcx.fn_sig(def_id).subst(self.tcx, substs))
+ }
+
+ // FIXME(compiler-errors): We could replace these with infer, I guess.
+ Closure(..)
+ | Infer(..)
+ | Generator(..)
+ | GeneratorWitness(..)
+ | Bound(_, _)
+ | Placeholder(_)
+ | Error(_) => {
+ return Err(());
+ }
+
+ Alias(Opaque, AliasTy { def_id, .. }) => {
+ let parent = self.tcx.parent(def_id);
+ let parent_ty = self.tcx.type_of(parent).subst_identity();
+ if let hir::def::DefKind::TyAlias | hir::def::DefKind::AssocTy = self.tcx.def_kind(parent)
+ && let Alias(Opaque, AliasTy { def_id: parent_opaque_def_id, .. }) = *parent_ty.kind()
+ && parent_opaque_def_id == def_id
+ {
+ t
+ } else {
+ return Err(());
+ }
+ }
+
+ Param(param) => {
+ // FIXME: It would be nice to make this not use string manipulation,
+ // but it's pretty hard to do this, since `ty::ParamTy` is missing
+ // sufficient info to determine if it is synthetic, and we don't
+ // always have a convenient way of getting `ty::Generics` at the call
+ // sites we invoke `IsSuggestable::is_suggestable`.
+ if param.name.as_str().starts_with("impl ") {
+ return Err(());
+ }
+
+ t
+ }
+
+ _ => t,
+ };
+
+ t.try_super_fold_with(self)
+ }
+
+ fn try_fold_const(&mut self, c: Const<'tcx>) -> Result<Const<'tcx>, ()> {
+ let c = match c.kind() {
+ ConstKind::Infer(InferConst::Var(_)) if self.infer_suggestable => c,
+
+ ConstKind::Infer(..)
+ | ConstKind::Bound(..)
+ | ConstKind::Placeholder(..)
+ | ConstKind::Error(..) => {
+ return Err(());
+ }
+
+ _ => c,
+ };
+
+ c.try_super_fold_with(self)
+ }
+}
+
+#[derive(Diagnostic)]
+#[diag(middle_const_not_used_in_type_alias)]
+pub(super) struct ConstNotUsedTraitAlias {
+ pub ct: String,
+ #[primary_span]
+ pub span: Span,
+}
diff --git a/compiler/rustc_middle/src/ty/erase_regions.rs b/compiler/rustc_middle/src/ty/erase_regions.rs
index 9e4f90caa..383773248 100644
--- a/compiler/rustc_middle/src/ty/erase_regions.rs
+++ b/compiler/rustc_middle/src/ty/erase_regions.rs
@@ -1,6 +1,5 @@
use crate::ty::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable};
-use crate::ty::visit::TypeVisitable;
-use crate::ty::{self, Ty, TyCtxt, TypeFlags};
+use crate::ty::{self, Ty, TyCtxt, TypeFlags, TypeVisitableExt};
pub(super) fn provide(providers: &mut ty::query::Providers) {
*providers = ty::query::Providers { erase_regions_ty, ..*providers };
@@ -18,7 +17,7 @@ impl<'tcx> TyCtxt<'tcx> {
/// subtyping, but they are anonymized and normalized as well)..
pub fn erase_regions<T>(self, value: T) -> T
where
- T: TypeFoldable<'tcx>,
+ T: TypeFoldable<TyCtxt<'tcx>>,
{
// If there's nothing to erase avoid performing the query at all
if !value.has_type_flags(TypeFlags::HAS_LATE_BOUND | TypeFlags::HAS_FREE_REGIONS) {
@@ -35,8 +34,8 @@ struct RegionEraserVisitor<'tcx> {
tcx: TyCtxt<'tcx>,
}
-impl<'tcx> TypeFolder<'tcx> for RegionEraserVisitor<'tcx> {
- fn tcx<'b>(&'b self) -> TyCtxt<'tcx> {
+impl<'tcx> TypeFolder<TyCtxt<'tcx>> for RegionEraserVisitor<'tcx> {
+ fn interner(&self) -> TyCtxt<'tcx> {
self.tcx
}
@@ -46,7 +45,7 @@ impl<'tcx> TypeFolder<'tcx> for RegionEraserVisitor<'tcx> {
fn fold_binder<T>(&mut self, t: ty::Binder<'tcx, T>) -> ty::Binder<'tcx, T>
where
- T: TypeFoldable<'tcx>,
+ T: TypeFoldable<TyCtxt<'tcx>>,
{
let u = self.tcx.anonymize_bound_vars(t);
u.super_fold_with(self)
diff --git a/compiler/rustc_middle/src/ty/error.rs b/compiler/rustc_middle/src/ty/error.rs
index 5d394f71f..9c171a69d 100644
--- a/compiler/rustc_middle/src/ty/error.rs
+++ b/compiler/rustc_middle/src/ty/error.rs
@@ -1,24 +1,16 @@
-use crate::traits::{ObligationCause, ObligationCauseCode};
-use crate::ty::diagnostics::suggest_constraining_type_param;
-use crate::ty::print::{with_forced_trimmed_paths, FmtPrinter, Printer};
+use crate::ty::print::{with_forced_trimmed_paths, FmtPrinter, PrettyPrinter};
use crate::ty::{self, BoundRegionKind, Region, Ty, TyCtxt};
-use rustc_errors::Applicability::{MachineApplicable, MaybeIncorrect};
-use rustc_errors::{pluralize, Diagnostic, MultiSpan};
+use rustc_errors::pluralize;
use rustc_hir as hir;
use rustc_hir::def::{CtorOf, DefKind};
use rustc_hir::def_id::DefId;
-use rustc_span::symbol::{sym, Symbol};
-use rustc_span::{BytePos, Span};
+use rustc_span::symbol::Symbol;
use rustc_target::spec::abi;
-
use std::borrow::Cow;
use std::collections::hash_map::DefaultHasher;
-use std::fmt;
use std::hash::{Hash, Hasher};
use std::path::PathBuf;
-use super::print::PrettyPrinter;
-
#[derive(Clone, Copy, Debug, PartialEq, Eq, TypeFoldable, TypeVisitable, Lift)]
pub struct ExpectedFound<T> {
pub expected: T,
@@ -36,7 +28,7 @@ impl<T> ExpectedFound<T> {
}
// Data structures used in type unification
-#[derive(Copy, Clone, Debug, TypeFoldable, TypeVisitable, Lift)]
+#[derive(Copy, Clone, Debug, TypeFoldable, TypeVisitable, Lift, PartialEq, Eq)]
#[rustc_pass_by_value]
pub enum TypeError<'tcx> {
Mismatch,
@@ -93,20 +85,16 @@ impl TypeError<'_> {
/// in parentheses after some larger message. You should also invoke `note_and_explain_type_err()`
/// afterwards to present additional details, particularly when it comes to lifetime-related
/// errors.
-impl<'tcx> fmt::Display for TypeError<'tcx> {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+impl<'tcx> TypeError<'tcx> {
+ pub fn to_string(self, tcx: TyCtxt<'tcx>) -> Cow<'static, str> {
use self::TypeError::*;
- fn report_maybe_different(
- f: &mut fmt::Formatter<'_>,
- expected: &str,
- found: &str,
- ) -> fmt::Result {
+ fn report_maybe_different(expected: &str, found: &str) -> String {
// A naive approach to making sure that we're not reporting silly errors such as:
// (expected closure, found closure).
if expected == found {
- write!(f, "expected {}, found a different {}", expected, found)
+ format!("expected {}, found a different {}", expected, found)
} else {
- write!(f, "expected {}, found {}", expected, found)
+ format!("expected {}, found {}", expected, found)
}
}
@@ -115,64 +103,63 @@ impl<'tcx> fmt::Display for TypeError<'tcx> {
_ => String::new(),
};
- match *self {
- CyclicTy(_) => write!(f, "cyclic type of infinite size"),
- CyclicConst(_) => write!(f, "encountered a self-referencing constant"),
- Mismatch => write!(f, "types differ"),
+ match self {
+ CyclicTy(_) => "cyclic type of infinite size".into(),
+ CyclicConst(_) => "encountered a self-referencing constant".into(),
+ Mismatch => "types differ".into(),
ConstnessMismatch(values) => {
- write!(f, "expected {} bound, found {} bound", values.expected, values.found)
+ format!("expected {} bound, found {} bound", values.expected, values.found).into()
}
PolarityMismatch(values) => {
- write!(f, "expected {} polarity, found {} polarity", values.expected, values.found)
+ format!("expected {} polarity, found {} polarity", values.expected, values.found)
+ .into()
}
UnsafetyMismatch(values) => {
- write!(f, "expected {} fn, found {} fn", values.expected, values.found)
+ format!("expected {} fn, found {} fn", values.expected, values.found).into()
}
AbiMismatch(values) => {
- write!(f, "expected {} fn, found {} fn", values.expected, values.found)
+ format!("expected {} fn, found {} fn", values.expected, values.found).into()
}
- ArgumentMutability(_) | Mutability => write!(f, "types differ in mutability"),
- TupleSize(values) => write!(
- f,
+ ArgumentMutability(_) | Mutability => "types differ in mutability".into(),
+ TupleSize(values) => format!(
"expected a tuple with {} element{}, found one with {} element{}",
values.expected,
pluralize!(values.expected),
values.found,
pluralize!(values.found)
- ),
- FixedArraySize(values) => write!(
- f,
+ )
+ .into(),
+ FixedArraySize(values) => format!(
"expected an array with a fixed size of {} element{}, found one with {} element{}",
values.expected,
pluralize!(values.expected),
values.found,
pluralize!(values.found)
- ),
- ArgCount => write!(f, "incorrect number of function parameters"),
- FieldMisMatch(adt, field) => write!(f, "field type mismatch: {}.{}", adt, field),
- RegionsDoesNotOutlive(..) => write!(f, "lifetime mismatch"),
+ )
+ .into(),
+ ArgCount => "incorrect number of function parameters".into(),
+ FieldMisMatch(adt, field) => format!("field type mismatch: {}.{}", adt, field).into(),
+ RegionsDoesNotOutlive(..) => "lifetime mismatch".into(),
// Actually naming the region here is a bit confusing because context is lacking
RegionsInsufficientlyPolymorphic(..) => {
- write!(f, "one type is more general than the other")
+ "one type is more general than the other".into()
}
- RegionsOverlyPolymorphic(br, _) => write!(
- f,
+ RegionsOverlyPolymorphic(br, _) => format!(
"expected concrete lifetime, found bound lifetime parameter{}",
br_string(br)
- ),
- RegionsPlaceholderMismatch => write!(f, "one type is more general than the other"),
- ArgumentSorts(values, _) | Sorts(values) => ty::tls::with(|tcx| {
- let (mut expected, mut found) = with_forced_trimmed_paths!((
- values.expected.sort_string(tcx),
- values.found.sort_string(tcx),
- ));
+ )
+ .into(),
+ RegionsPlaceholderMismatch => "one type is more general than the other".into(),
+ ArgumentSorts(values, _) | Sorts(values) => {
+ let mut expected = values.expected.sort_string(tcx);
+ let mut found = values.found.sort_string(tcx);
if expected == found {
expected = values.expected.sort_string(tcx);
found = values.found.sort_string(tcx);
}
- report_maybe_different(f, &expected, &found)
- }),
- Traits(values) => ty::tls::with(|tcx| {
+ report_maybe_different(&expected, &found).into()
+ }
+ Traits(values) => {
let (mut expected, mut found) = with_forced_trimmed_paths!((
tcx.def_path_str(values.expected),
tcx.def_path_str(values.found),
@@ -181,12 +168,9 @@ impl<'tcx> fmt::Display for TypeError<'tcx> {
expected = tcx.def_path_str(values.expected);
found = tcx.def_path_str(values.found);
}
- report_maybe_different(
- f,
- &format!("trait `{expected}`"),
- &format!("trait `{found}`"),
- )
- }),
+ report_maybe_different(&format!("trait `{expected}`"), &format!("trait `{found}`"))
+ .into()
+ }
IntMismatch(ref values) => {
let expected = match values.expected {
ty::IntVarValue::IntType(ty) => ty.name_str(),
@@ -196,43 +180,38 @@ impl<'tcx> fmt::Display for TypeError<'tcx> {
ty::IntVarValue::IntType(ty) => ty.name_str(),
ty::IntVarValue::UintType(ty) => ty.name_str(),
};
- write!(f, "expected `{}`, found `{}`", expected, found)
+ format!("expected `{}`, found `{}`", expected, found).into()
}
- FloatMismatch(ref values) => {
- write!(
- f,
- "expected `{}`, found `{}`",
- values.expected.name_str(),
- values.found.name_str()
- )
- }
- VariadicMismatch(ref values) => write!(
- f,
+ FloatMismatch(ref values) => format!(
+ "expected `{}`, found `{}`",
+ values.expected.name_str(),
+ values.found.name_str()
+ )
+ .into(),
+ VariadicMismatch(ref values) => format!(
"expected {} fn, found {} function",
if values.expected { "variadic" } else { "non-variadic" },
if values.found { "variadic" } else { "non-variadic" }
- ),
- ProjectionMismatched(ref values) => ty::tls::with(|tcx| {
- write!(
- f,
- "expected {}, found {}",
- tcx.def_path_str(values.expected),
- tcx.def_path_str(values.found)
- )
- }),
+ )
+ .into(),
+ ProjectionMismatched(ref values) => format!(
+ "expected `{}`, found `{}`",
+ tcx.def_path_str(values.expected),
+ tcx.def_path_str(values.found)
+ )
+ .into(),
ExistentialMismatch(ref values) => report_maybe_different(
- f,
&format!("trait `{}`", values.expected),
&format!("trait `{}`", values.found),
- ),
+ )
+ .into(),
ConstMismatch(ref values) => {
- write!(f, "expected `{}`, found `{}`", values.expected, values.found)
+ format!("expected `{}`, found `{}`", values.expected, values.found).into()
+ }
+ IntrinsicCast => "cannot coerce intrinsics to function pointers".into(),
+ TargetFeatureCast(_) => {
+ "cannot coerce functions with `#[target_feature]` to safe function pointers".into()
}
- IntrinsicCast => write!(f, "cannot coerce intrinsics to function pointers"),
- TargetFeatureCast(_) => write!(
- f,
- "cannot coerce functions with `#[target_feature]` to safe function pointers"
- ),
}
}
}
@@ -265,60 +244,9 @@ impl<'tcx> TypeError<'tcx> {
}
impl<'tcx> Ty<'tcx> {
- pub fn sort_string(self, tcx: TyCtxt<'_>) -> Cow<'static, str> {
+ pub fn sort_string(self, tcx: TyCtxt<'tcx>) -> Cow<'static, str> {
match *self.kind() {
- ty::Bool | ty::Char | ty::Int(_) | ty::Uint(_) | ty::Float(_) | ty::Str | ty::Never => {
- format!("`{}`", self).into()
- }
- ty::Tuple(ref tys) if tys.is_empty() => format!("`{}`", self).into(),
-
- ty::Adt(def, _) => format!("{} `{}`", def.descr(), tcx.def_path_str(def.did())).into(),
ty::Foreign(def_id) => format!("extern type `{}`", tcx.def_path_str(def_id)).into(),
- ty::Array(t, n) => {
- if t.is_simple_ty() {
- return format!("array `{}`", self).into();
- }
-
- let n = tcx.lift(n).unwrap();
- if let ty::ConstKind::Value(v) = n.kind() {
- if let Some(n) = v.try_to_machine_usize(tcx) {
- return format!("array of {} element{}", n, pluralize!(n)).into();
- }
- }
- "array".into()
- }
- ty::Slice(ty) if ty.is_simple_ty() => format!("slice `{}`", self).into(),
- ty::Slice(_) => "slice".into(),
- ty::RawPtr(tymut) => {
- let tymut_string = match tymut.mutbl {
- hir::Mutability::Mut => tymut.to_string(),
- hir::Mutability::Not => format!("const {}", tymut.ty),
- };
-
- if tymut_string != "_" && (tymut.ty.is_simple_text() || tymut_string.len() < "const raw pointer".len()) {
- format!("`*{}`", tymut_string).into()
- } else {
- // Unknown type name, it's long or has type arguments
- "raw pointer".into()
- }
- },
- ty::Ref(_, ty, mutbl) => {
- let tymut = ty::TypeAndMut { ty, mutbl };
- let tymut_string = tymut.to_string();
-
- if tymut_string != "_"
- && (ty.is_simple_text() || tymut_string.len() < "mutable reference".len())
- {
- format!("`&{}`", tymut_string).into()
- } else {
- // Unknown type name, it's long or has type arguments
- match mutbl {
- hir::Mutability::Mut => "mutable reference",
- _ => "reference",
- }
- .into()
- }
- }
ty::FnDef(def_id, ..) => match tcx.def_kind(def_id) {
DefKind::Ctor(CtorOf::Struct, _) => "struct constructor".into(),
DefKind::Ctor(CtorOf::Variant, _) => "enum constructor".into(),
@@ -326,13 +254,13 @@ impl<'tcx> Ty<'tcx> {
},
ty::FnPtr(_) => "fn pointer".into(),
ty::Dynamic(ref inner, ..) if let Some(principal) = inner.principal() => {
- format!("trait object `dyn {}`", tcx.def_path_str(principal.def_id())).into()
+ format!("`dyn {}`", tcx.def_path_str(principal.def_id())).into()
}
ty::Dynamic(..) => "trait object".into(),
ty::Closure(..) => "closure".into(),
ty::Generator(def_id, ..) => tcx.generator_kind(def_id).unwrap().descr().into(),
- ty::GeneratorWitness(..) => "generator witness".into(),
- ty::Tuple(..) => "tuple".into(),
+ ty::GeneratorWitness(..) |
+ ty::GeneratorWitnessMIR(..) => "generator witness".into(),
ty::Infer(ty::TyVar(_)) => "inferred type".into(),
ty::Infer(ty::IntVar(_)) => "integer".into(),
ty::Infer(ty::FloatVar(_)) => "floating-point number".into(),
@@ -342,9 +270,14 @@ impl<'tcx> Ty<'tcx> {
ty::Infer(ty::FreshIntTy(_)) => "fresh integral type".into(),
ty::Infer(ty::FreshFloatTy(_)) => "fresh floating-point type".into(),
ty::Alias(ty::Projection, _) => "associated type".into(),
- ty::Param(p) => format!("type parameter `{}`", p).into(),
- ty::Alias(ty::Opaque, ..) => "opaque type".into(),
+ ty::Param(p) => format!("type parameter `{p}`").into(),
+ ty::Alias(ty::Opaque, ..) => if tcx.ty_is_opaque_future(self) { "future".into() } else { "opaque type".into() },
ty::Error(_) => "type error".into(),
+ _ => {
+ let width = tcx.sess.diagnostic_width();
+ let length_limit = std::cmp::max(width / 4, 15);
+ format!("`{}`", tcx.ty_string_with_limit(self, length_limit)).into()
+ }
}
}
@@ -379,7 +312,7 @@ impl<'tcx> Ty<'tcx> {
ty::Dynamic(..) => "trait object".into(),
ty::Closure(..) => "closure".into(),
ty::Generator(def_id, ..) => tcx.generator_kind(def_id).unwrap().descr().into(),
- ty::GeneratorWitness(..) => "generator witness".into(),
+ ty::GeneratorWitness(..) | ty::GeneratorWitnessMIR(..) => "generator witness".into(),
ty::Tuple(..) => "tuple".into(),
ty::Placeholder(..) => "higher-ranked type".into(),
ty::Bound(..) => "bound type variable".into(),
@@ -391,630 +324,14 @@ impl<'tcx> Ty<'tcx> {
}
impl<'tcx> TyCtxt<'tcx> {
- pub fn note_and_explain_type_err(
- self,
- diag: &mut Diagnostic,
- err: TypeError<'tcx>,
- cause: &ObligationCause<'tcx>,
- sp: Span,
- body_owner_def_id: DefId,
- ) {
- use self::TypeError::*;
- debug!("note_and_explain_type_err err={:?} cause={:?}", err, cause);
- match err {
- ArgumentSorts(values, _) | Sorts(values) => {
- match (values.expected.kind(), values.found.kind()) {
- (ty::Closure(..), ty::Closure(..)) => {
- diag.note("no two closures, even if identical, have the same type");
- diag.help("consider boxing your closure and/or using it as a trait object");
- }
- (ty::Alias(ty::Opaque, ..), ty::Alias(ty::Opaque, ..)) => {
- // Issue #63167
- diag.note("distinct uses of `impl Trait` result in different opaque types");
- }
- (ty::Float(_), ty::Infer(ty::IntVar(_)))
- if let Ok(
- // Issue #53280
- snippet,
- ) = self.sess.source_map().span_to_snippet(sp) =>
- {
- if snippet.chars().all(|c| c.is_digit(10) || c == '-' || c == '_') {
- diag.span_suggestion(
- sp,
- "use a float literal",
- format!("{}.0", snippet),
- MachineApplicable,
- );
- }
- }
- (ty::Param(expected), ty::Param(found)) => {
- let generics = self.generics_of(body_owner_def_id);
- let e_span = self.def_span(generics.type_param(expected, self).def_id);
- if !sp.contains(e_span) {
- diag.span_label(e_span, "expected type parameter");
- }
- let f_span = self.def_span(generics.type_param(found, self).def_id);
- if !sp.contains(f_span) {
- diag.span_label(f_span, "found type parameter");
- }
- diag.note(
- "a type parameter was expected, but a different one was found; \
- you might be missing a type parameter or trait bound",
- );
- diag.note(
- "for more information, visit \
- https://doc.rust-lang.org/book/ch10-02-traits.html\
- #traits-as-parameters",
- );
- }
- (ty::Alias(ty::Projection, _), ty::Alias(ty::Projection, _)) => {
- diag.note("an associated type was expected, but a different one was found");
- }
- (ty::Param(p), ty::Alias(ty::Projection, proj)) | (ty::Alias(ty::Projection, proj), ty::Param(p))
- if self.def_kind(proj.def_id) != DefKind::ImplTraitPlaceholder =>
- {
- let generics = self.generics_of(body_owner_def_id);
- let p_span = self.def_span(generics.type_param(p, self).def_id);
- if !sp.contains(p_span) {
- diag.span_label(p_span, "this type parameter");
- }
- let hir = self.hir();
- let mut note = true;
- if let Some(generics) = generics
- .type_param(p, self)
- .def_id
- .as_local()
- .map(|id| hir.local_def_id_to_hir_id(id))
- .and_then(|id| self.hir().find_parent(id))
- .as_ref()
- .and_then(|node| node.generics())
- {
- // Synthesize the associated type restriction `Add<Output = Expected>`.
- // FIXME: extract this logic for use in other diagnostics.
- let (trait_ref, assoc_substs) = proj.trait_ref_and_own_substs(self);
- let path =
- self.def_path_str_with_substs(trait_ref.def_id, trait_ref.substs);
- let item_name = self.item_name(proj.def_id);
- let item_args = self.format_generic_args(assoc_substs);
-
- let path = if path.ends_with('>') {
- format!(
- "{}, {}{} = {}>",
- &path[..path.len() - 1],
- item_name,
- item_args,
- p
- )
- } else {
- format!("{}<{}{} = {}>", path, item_name, item_args, p)
- };
- note = !suggest_constraining_type_param(
- self,
- generics,
- diag,
- &format!("{}", proj.self_ty()),
- &path,
- None,
- );
- }
- if note {
- diag.note("you might be missing a type parameter or trait bound");
- }
- }
- (ty::Param(p), ty::Dynamic(..) | ty::Alias(ty::Opaque, ..))
- | (ty::Dynamic(..) | ty::Alias(ty::Opaque, ..), ty::Param(p)) => {
- let generics = self.generics_of(body_owner_def_id);
- let p_span = self.def_span(generics.type_param(p, self).def_id);
- if !sp.contains(p_span) {
- diag.span_label(p_span, "this type parameter");
- }
- diag.help("type parameters must be constrained to match other types");
- if self.sess.teach(&diag.get_code().unwrap()) {
- diag.help(
- "given a type parameter `T` and a method `foo`:
-```
-trait Trait<T> { fn foo(&self) -> T; }
-```
-the only ways to implement method `foo` are:
-- constrain `T` with an explicit type:
-```
-impl Trait<String> for X {
- fn foo(&self) -> String { String::new() }
-}
-```
-- add a trait bound to `T` and call a method on that trait that returns `Self`:
-```
-impl<T: std::default::Default> Trait<T> for X {
- fn foo(&self) -> T { <T as std::default::Default>::default() }
-}
-```
-- change `foo` to return an argument of type `T`:
-```
-impl<T> Trait<T> for X {
- fn foo(&self, x: T) -> T { x }
-}
-```",
- );
- }
- diag.note(
- "for more information, visit \
- https://doc.rust-lang.org/book/ch10-02-traits.html\
- #traits-as-parameters",
- );
- }
- (ty::Param(p), ty::Closure(..) | ty::Generator(..)) => {
- let generics = self.generics_of(body_owner_def_id);
- let p_span = self.def_span(generics.type_param(p, self).def_id);
- if !sp.contains(p_span) {
- diag.span_label(p_span, "this type parameter");
- }
- diag.help(&format!(
- "every closure has a distinct type and so could not always match the \
- caller-chosen type of parameter `{}`",
- p
- ));
- }
- (ty::Param(p), _) | (_, ty::Param(p)) => {
- let generics = self.generics_of(body_owner_def_id);
- let p_span = self.def_span(generics.type_param(p, self).def_id);
- if !sp.contains(p_span) {
- diag.span_label(p_span, "this type parameter");
- }
- }
- (ty::Alias(ty::Projection, proj_ty), _) if self.def_kind(proj_ty.def_id) != DefKind::ImplTraitPlaceholder => {
- self.expected_projection(
- diag,
- proj_ty,
- values,
- body_owner_def_id,
- cause.code(),
- );
- }
- (_, ty::Alias(ty::Projection, proj_ty)) if self.def_kind(proj_ty.def_id) != DefKind::ImplTraitPlaceholder => {
- let msg = format!(
- "consider constraining the associated type `{}` to `{}`",
- values.found, values.expected,
- );
- if !(self.suggest_constraining_opaque_associated_type(
- diag,
- &msg,
- proj_ty,
- values.expected,
- ) || self.suggest_constraint(
- diag,
- &msg,
- body_owner_def_id,
- proj_ty,
- values.expected,
- )) {
- diag.help(&msg);
- diag.note(
- "for more information, visit \
- https://doc.rust-lang.org/book/ch19-03-advanced-traits.html",
- );
- }
- }
- _ => {}
- }
- debug!(
- "note_and_explain_type_err expected={:?} ({:?}) found={:?} ({:?})",
- values.expected,
- values.expected.kind(),
- values.found,
- values.found.kind(),
- );
- }
- CyclicTy(ty) => {
- // Watch out for various cases of cyclic types and try to explain.
- if ty.is_closure() || ty.is_generator() {
- diag.note(
- "closures cannot capture themselves or take themselves as argument;\n\
- this error may be the result of a recent compiler bug-fix,\n\
- see issue #46062 <https://github.com/rust-lang/rust/issues/46062>\n\
- for more information",
- );
- }
- }
- TargetFeatureCast(def_id) => {
- let target_spans =
- self.get_attrs(def_id, sym::target_feature).map(|attr| attr.span);
- diag.note(
- "functions with `#[target_feature]` can only be coerced to `unsafe` function pointers"
- );
- diag.span_labels(target_spans, "`#[target_feature]` added here");
- }
- _ => {}
- }
- }
-
- fn suggest_constraint(
- self,
- diag: &mut Diagnostic,
- msg: &str,
- body_owner_def_id: DefId,
- proj_ty: &ty::AliasTy<'tcx>,
- ty: Ty<'tcx>,
- ) -> bool {
- let assoc = self.associated_item(proj_ty.def_id);
- let (trait_ref, assoc_substs) = proj_ty.trait_ref_and_own_substs(self);
- if let Some(item) = self.hir().get_if_local(body_owner_def_id) {
- if let Some(hir_generics) = item.generics() {
- // Get the `DefId` for the type parameter corresponding to `A` in `<A as T>::Foo`.
- // This will also work for `impl Trait`.
- let def_id = if let ty::Param(param_ty) = proj_ty.self_ty().kind() {
- let generics = self.generics_of(body_owner_def_id);
- generics.type_param(param_ty, self).def_id
- } else {
- return false;
- };
- let Some(def_id) = def_id.as_local() else {
- return false;
- };
-
- // First look in the `where` clause, as this might be
- // `fn foo<T>(x: T) where T: Trait`.
- for pred in hir_generics.bounds_for_param(def_id) {
- if self.constrain_generic_bound_associated_type_structured_suggestion(
- diag,
- &trait_ref,
- pred.bounds,
- &assoc,
- assoc_substs,
- ty,
- msg,
- false,
- ) {
- return true;
- }
- }
- }
- }
- false
- }
-
- /// An associated type was expected and a different type was found.
- ///
- /// We perform a few different checks to see what we can suggest:
- ///
- /// - In the current item, look for associated functions that return the expected type and
- /// suggest calling them. (Not a structured suggestion.)
- /// - If any of the item's generic bounds can be constrained, we suggest constraining the
- /// associated type to the found type.
- /// - If the associated type has a default type and was expected inside of a `trait`, we
- /// mention that this is disallowed.
- /// - If all other things fail, and the error is not because of a mismatch between the `trait`
- /// and the `impl`, we provide a generic `help` to constrain the assoc type or call an assoc
- /// fn that returns the type.
- fn expected_projection(
- self,
- diag: &mut Diagnostic,
- proj_ty: &ty::AliasTy<'tcx>,
- values: ExpectedFound<Ty<'tcx>>,
- body_owner_def_id: DefId,
- cause_code: &ObligationCauseCode<'_>,
- ) {
- let msg = format!(
- "consider constraining the associated type `{}` to `{}`",
- values.expected, values.found
- );
- let body_owner = self.hir().get_if_local(body_owner_def_id);
- let current_method_ident = body_owner.and_then(|n| n.ident()).map(|i| i.name);
-
- // We don't want to suggest calling an assoc fn in a scope where that isn't feasible.
- let callable_scope = matches!(
- body_owner,
- Some(
- hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(..), .. })
- | hir::Node::TraitItem(hir::TraitItem { kind: hir::TraitItemKind::Fn(..), .. })
- | hir::Node::ImplItem(hir::ImplItem { kind: hir::ImplItemKind::Fn(..), .. }),
- )
- );
- let impl_comparison =
- matches!(cause_code, ObligationCauseCode::CompareImplItemObligation { .. });
- let assoc = self.associated_item(proj_ty.def_id);
- if !callable_scope || impl_comparison {
- // We do not want to suggest calling functions when the reason of the
- // type error is a comparison of an `impl` with its `trait` or when the
- // scope is outside of a `Body`.
- } else {
- // If we find a suitable associated function that returns the expected type, we don't
- // want the more general suggestion later in this method about "consider constraining
- // the associated type or calling a method that returns the associated type".
- let point_at_assoc_fn = self.point_at_methods_that_satisfy_associated_type(
- diag,
- assoc.container_id(self),
- current_method_ident,
- proj_ty.def_id,
- values.expected,
- );
- // Possibly suggest constraining the associated type to conform to the
- // found type.
- if self.suggest_constraint(diag, &msg, body_owner_def_id, proj_ty, values.found)
- || point_at_assoc_fn
- {
- return;
- }
- }
-
- self.suggest_constraining_opaque_associated_type(diag, &msg, proj_ty, values.found);
-
- if self.point_at_associated_type(diag, body_owner_def_id, values.found) {
- return;
- }
-
- if !impl_comparison {
- // Generic suggestion when we can't be more specific.
- if callable_scope {
- diag.help(&format!(
- "{} or calling a method that returns `{}`",
- msg, values.expected
- ));
- } else {
- diag.help(&msg);
- }
- diag.note(
- "for more information, visit \
- https://doc.rust-lang.org/book/ch19-03-advanced-traits.html",
- );
- }
- if self.sess.teach(&diag.get_code().unwrap()) {
- diag.help(
- "given an associated type `T` and a method `foo`:
-```
-trait Trait {
-type T;
-fn foo(&self) -> Self::T;
-}
-```
-the only way of implementing method `foo` is to constrain `T` with an explicit associated type:
-```
-impl Trait for X {
-type T = String;
-fn foo(&self) -> Self::T { String::new() }
-}
-```",
- );
- }
- }
-
- /// When the expected `impl Trait` is not defined in the current item, it will come from
- /// a return type. This can occur when dealing with `TryStream` (#71035).
- fn suggest_constraining_opaque_associated_type(
- self,
- diag: &mut Diagnostic,
- msg: &str,
- proj_ty: &ty::AliasTy<'tcx>,
- ty: Ty<'tcx>,
- ) -> bool {
- let assoc = self.associated_item(proj_ty.def_id);
- if let ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }) = *proj_ty.self_ty().kind() {
- let opaque_local_def_id = def_id.as_local();
- let opaque_hir_ty = if let Some(opaque_local_def_id) = opaque_local_def_id {
- match &self.hir().expect_item(opaque_local_def_id).kind {
- hir::ItemKind::OpaqueTy(opaque_hir_ty) => opaque_hir_ty,
- _ => bug!("The HirId comes from a `ty::Opaque`"),
- }
- } else {
- return false;
- };
-
- let (trait_ref, assoc_substs) = proj_ty.trait_ref_and_own_substs(self);
-
- self.constrain_generic_bound_associated_type_structured_suggestion(
- diag,
- &trait_ref,
- opaque_hir_ty.bounds,
- assoc,
- assoc_substs,
- ty,
- msg,
- true,
- )
- } else {
- false
- }
- }
-
- fn point_at_methods_that_satisfy_associated_type(
- self,
- diag: &mut Diagnostic,
- assoc_container_id: DefId,
- current_method_ident: Option<Symbol>,
- proj_ty_item_def_id: DefId,
- expected: Ty<'tcx>,
- ) -> bool {
- let items = self.associated_items(assoc_container_id);
- // Find all the methods in the trait that could be called to construct the
- // expected associated type.
- // FIXME: consider suggesting the use of associated `const`s.
- let methods: Vec<(Span, String)> = items
- .items
- .iter()
- .filter(|(name, item)| {
- ty::AssocKind::Fn == item.kind && Some(**name) != current_method_ident
- })
- .filter_map(|(_, item)| {
- let method = self.fn_sig(item.def_id);
- match *method.output().skip_binder().kind() {
- ty::Alias(ty::Projection, ty::AliasTy { def_id: item_def_id, .. })
- if item_def_id == proj_ty_item_def_id =>
- {
- Some((
- self.def_span(item.def_id),
- format!("consider calling `{}`", self.def_path_str(item.def_id)),
- ))
- }
- _ => None,
- }
- })
- .collect();
- if !methods.is_empty() {
- // Use a single `help:` to show all the methods in the trait that can
- // be used to construct the expected associated type.
- let mut span: MultiSpan =
- methods.iter().map(|(sp, _)| *sp).collect::<Vec<Span>>().into();
- let msg = format!(
- "{some} method{s} {are} available that return{r} `{ty}`",
- some = if methods.len() == 1 { "a" } else { "some" },
- s = pluralize!(methods.len()),
- are = pluralize!("is", methods.len()),
- r = if methods.len() == 1 { "s" } else { "" },
- ty = expected
- );
- for (sp, label) in methods.into_iter() {
- span.push_span_label(sp, label);
- }
- diag.span_help(span, &msg);
- return true;
- }
- false
- }
-
- fn point_at_associated_type(
- self,
- diag: &mut Diagnostic,
- body_owner_def_id: DefId,
- found: Ty<'tcx>,
- ) -> bool {
- let Some(hir_id) = body_owner_def_id.as_local() else {
- return false;
- };
- let hir_id = self.hir().local_def_id_to_hir_id(hir_id);
- // When `body_owner` is an `impl` or `trait` item, look in its associated types for
- // `expected` and point at it.
- let parent_id = self.hir().get_parent_item(hir_id);
- let item = self.hir().find_by_def_id(parent_id.def_id);
- debug!("expected_projection parent item {:?}", item);
- match item {
- Some(hir::Node::Item(hir::Item { kind: hir::ItemKind::Trait(.., items), .. })) => {
- // FIXME: account for `#![feature(specialization)]`
- for item in &items[..] {
- match item.kind {
- hir::AssocItemKind::Type => {
- // FIXME: account for returning some type in a trait fn impl that has
- // an assoc type as a return type (#72076).
- if let hir::Defaultness::Default { has_value: true } =
- self.impl_defaultness(item.id.owner_id)
- {
- if self.type_of(item.id.owner_id) == found {
- diag.span_label(
- item.span,
- "associated type defaults can't be assumed inside the \
- trait defining them",
- );
- return true;
- }
- }
- }
- _ => {}
- }
- }
- }
- Some(hir::Node::Item(hir::Item {
- kind: hir::ItemKind::Impl(hir::Impl { items, .. }),
- ..
- })) => {
- for item in &items[..] {
- if let hir::AssocItemKind::Type = item.kind {
- if self.type_of(item.id.owner_id) == found {
- diag.span_label(item.span, "expected this associated type");
- return true;
- }
- }
- }
- }
- _ => {}
- }
- false
- }
-
- /// Given a slice of `hir::GenericBound`s, if any of them corresponds to the `trait_ref`
- /// requirement, provide a structured suggestion to constrain it to a given type `ty`.
- ///
- /// `is_bound_surely_present` indicates whether we know the bound we're looking for is
- /// inside `bounds`. If that's the case then we can consider `bounds` containing only one
- /// trait bound as the one we're looking for. This can help in cases where the associated
- /// type is defined on a supertrait of the one present in the bounds.
- fn constrain_generic_bound_associated_type_structured_suggestion(
- self,
- diag: &mut Diagnostic,
- trait_ref: &ty::TraitRef<'tcx>,
- bounds: hir::GenericBounds<'_>,
- assoc: &ty::AssocItem,
- assoc_substs: &[ty::GenericArg<'tcx>],
- ty: Ty<'tcx>,
- msg: &str,
- is_bound_surely_present: bool,
- ) -> bool {
- // FIXME: we would want to call `resolve_vars_if_possible` on `ty` before suggesting.
-
- let trait_bounds = bounds.iter().filter_map(|bound| match bound {
- hir::GenericBound::Trait(ptr, hir::TraitBoundModifier::None) => Some(ptr),
- _ => None,
- });
-
- let matching_trait_bounds = trait_bounds
- .clone()
- .filter(|ptr| ptr.trait_ref.trait_def_id() == Some(trait_ref.def_id))
- .collect::<Vec<_>>();
-
- let span = match &matching_trait_bounds[..] {
- &[ptr] => ptr.span,
- &[] if is_bound_surely_present => match &trait_bounds.collect::<Vec<_>>()[..] {
- &[ptr] => ptr.span,
- _ => return false,
- },
- _ => return false,
- };
-
- self.constrain_associated_type_structured_suggestion(
- diag,
- span,
- assoc,
- assoc_substs,
- ty,
- msg,
- )
- }
-
- /// Given a span corresponding to a bound, provide a structured suggestion to set an
- /// associated type to a given type `ty`.
- fn constrain_associated_type_structured_suggestion(
- self,
- diag: &mut Diagnostic,
- span: Span,
- assoc: &ty::AssocItem,
- assoc_substs: &[ty::GenericArg<'tcx>],
- ty: Ty<'tcx>,
- msg: &str,
- ) -> bool {
- if let Ok(has_params) =
- self.sess.source_map().span_to_snippet(span).map(|snippet| snippet.ends_with('>'))
- {
- let (span, sugg) = if has_params {
- let pos = span.hi() - BytePos(1);
- let span = Span::new(pos, pos, span.ctxt(), span.parent());
- (span, format!(", {} = {}", assoc.ident(self), ty))
- } else {
- let item_args = self.format_generic_args(assoc_substs);
- (span.shrink_to_hi(), format!("<{}{} = {}>", assoc.ident(self), item_args, ty))
- };
- diag.span_suggestion_verbose(span, msg, sugg, MaybeIncorrect);
- return true;
- }
- false
- }
-
- pub fn short_ty_string(self, ty: Ty<'tcx>) -> (String, Option<PathBuf>) {
- let width = self.sess.diagnostic_width();
- let length_limit = width.saturating_sub(30);
+ pub fn ty_string_with_limit(self, ty: Ty<'tcx>, length_limit: usize) -> String {
let mut type_limit = 50;
let regular = FmtPrinter::new(self, hir::def::Namespace::TypeNS)
.pretty_print_type(ty)
.expect("could not write to `String`")
.into_buffer();
- if regular.len() <= width {
- return (regular, None);
+ if regular.len() <= length_limit {
+ return regular;
}
let mut short;
loop {
@@ -1034,6 +351,20 @@ fn foo(&self) -> Self::T { String::new() }
}
type_limit -= 1;
}
+ short
+ }
+
+ pub fn short_ty_string(self, ty: Ty<'tcx>) -> (String, Option<PathBuf>) {
+ let width = self.sess.diagnostic_width();
+ let length_limit = width.saturating_sub(30);
+ let regular = FmtPrinter::new(self, hir::def::Namespace::TypeNS)
+ .pretty_print_type(ty)
+ .expect("could not write to `String`")
+ .into_buffer();
+ if regular.len() <= width {
+ return (regular, None);
+ }
+ let short = self.ty_string_with_limit(ty, length_limit);
if regular == short {
return (regular, None);
}
@@ -1047,11 +378,4 @@ fn foo(&self) -> Self::T { String::new() }
Err(_) => (regular, None),
}
}
-
- fn format_generic_args(self, args: &[ty::GenericArg<'tcx>]) -> String {
- FmtPrinter::new(self, hir::def::Namespace::TypeNS)
- .path_generic_args(Ok, args)
- .expect("could not write to `String`.")
- .into_buffer()
- }
}
diff --git a/compiler/rustc_middle/src/ty/fast_reject.rs b/compiler/rustc_middle/src/ty/fast_reject.rs
index f785fb5c4..59deade0a 100644
--- a/compiler/rustc_middle/src/ty/fast_reject.rs
+++ b/compiler/rustc_middle/src/ty/fast_reject.rs
@@ -1,6 +1,6 @@
use crate::mir::Mutability;
use crate::ty::subst::GenericArgKind;
-use crate::ty::{self, Ty, TyCtxt, TypeVisitable};
+use crate::ty::{self, Ty, TyCtxt, TypeVisitableExt};
use rustc_hir::def_id::DefId;
use std::fmt::Debug;
use std::hash::Hash;
@@ -32,6 +32,7 @@ pub enum SimplifiedType {
ClosureSimplifiedType(DefId),
GeneratorSimplifiedType(DefId),
GeneratorWitnessSimplifiedType(usize),
+ GeneratorWitnessMIRSimplifiedType(DefId),
FunctionSimplifiedType(usize),
PlaceholderSimplifiedType,
}
@@ -108,6 +109,7 @@ pub fn simplify_type<'tcx>(
ty::FnDef(def_id, _) | ty::Closure(def_id, _) => Some(ClosureSimplifiedType(def_id)),
ty::Generator(def_id, _, _) => Some(GeneratorSimplifiedType(def_id)),
ty::GeneratorWitness(tys) => Some(GeneratorWitnessSimplifiedType(tys.skip_binder().len())),
+ ty::GeneratorWitnessMIR(def_id, _) => Some(GeneratorWitnessMIRSimplifiedType(def_id)),
ty::Never => Some(NeverSimplifiedType),
ty::Tuple(tys) => Some(TupleSimplifiedType(tys.len())),
ty::FnPtr(f) => Some(FunctionSimplifiedType(f.skip_binder().inputs().len())),
@@ -139,7 +141,8 @@ impl SimplifiedType {
| ForeignSimplifiedType(d)
| TraitSimplifiedType(d)
| ClosureSimplifiedType(d)
- | GeneratorSimplifiedType(d) => Some(d),
+ | GeneratorSimplifiedType(d)
+ | GeneratorWitnessMIRSimplifiedType(d) => Some(d),
_ => None,
}
}
@@ -208,6 +211,7 @@ impl DeepRejectCtxt {
| ty::Closure(..)
| ty::Generator(..)
| ty::GeneratorWitness(..)
+ | ty::GeneratorWitnessMIR(..)
| ty::Placeholder(..)
| ty::Bound(..)
| ty::Infer(_) => bug!("unexpected impl_ty: {impl_ty}"),
@@ -286,7 +290,7 @@ impl DeepRejectCtxt {
// Impls cannot contain these types as these cannot be named directly.
ty::FnDef(..) | ty::Closure(..) | ty::Generator(..) => false,
- ty::Placeholder(..) => false,
+ ty::Placeholder(..) | ty::Bound(..) => false,
// Depending on the value of `treat_obligation_params`, we either
// treat generic parameters like placeholders or like inference variables.
@@ -306,7 +310,7 @@ impl DeepRejectCtxt {
ty::Error(_) => true,
- ty::GeneratorWitness(..) | ty::Bound(..) => {
+ ty::GeneratorWitness(..) | ty::GeneratorWitnessMIR(..) => {
bug!("unexpected obligation type: {:?}", obligation_ty)
}
}
diff --git a/compiler/rustc_middle/src/ty/flags.rs b/compiler/rustc_middle/src/ty/flags.rs
index b7eafc4b4..91241ff40 100644
--- a/compiler/rustc_middle/src/ty/flags.rs
+++ b/compiler/rustc_middle/src/ty/flags.rs
@@ -125,6 +125,16 @@ impl FlagComputation {
self.bound_computation(ts, |flags, ts| flags.add_tys(ts));
}
+ ty::GeneratorWitnessMIR(_, substs) => {
+ let should_remove_further_specializable =
+ !self.flags.contains(TypeFlags::STILL_FURTHER_SPECIALIZABLE);
+ self.add_substs(substs);
+ if should_remove_further_specializable {
+ self.flags -= TypeFlags::STILL_FURTHER_SPECIALIZABLE;
+ }
+ self.add_flags(TypeFlags::HAS_TY_GENERATOR);
+ }
+
&ty::Closure(_, substs) => {
let substs = substs.as_closure();
let should_remove_further_specializable =
@@ -241,6 +251,10 @@ impl FlagComputation {
self.add_ty(ty);
self.add_region(region);
}
+ ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(ct, ty)) => {
+ self.add_const(ct);
+ self.add_ty(ty);
+ }
ty::PredicateKind::Subtype(ty::SubtypePredicate { a_is_expected: _, a, b }) => {
self.add_ty(a);
self.add_ty(b);
@@ -254,10 +268,7 @@ impl FlagComputation {
term,
})) => {
self.add_projection_ty(projection_ty);
- match term.unpack() {
- ty::TermKind::Ty(ty) => self.add_ty(ty),
- ty::TermKind::Const(c) => self.add_const(c),
- }
+ self.add_term(term);
}
ty::PredicateKind::WellFormed(arg) => {
self.add_substs(slice::from_ref(&arg));
@@ -277,6 +288,10 @@ impl FlagComputation {
self.add_ty(ty);
}
ty::PredicateKind::Ambiguous => {}
+ ty::PredicateKind::AliasEq(t1, t2) => {
+ self.add_term(t1);
+ self.add_term(t2);
+ }
}
}
@@ -370,4 +385,11 @@ impl FlagComputation {
}
}
}
+
+ fn add_term(&mut self, term: ty::Term<'_>) {
+ match term.unpack() {
+ ty::TermKind::Ty(ty) => self.add_ty(ty),
+ ty::TermKind::Const(ct) => self.add_const(ct),
+ }
+ }
}
diff --git a/compiler/rustc_middle/src/ty/fold.rs b/compiler/rustc_middle/src/ty/fold.rs
index 6b9a37d84..d66f436f9 100644
--- a/compiler/rustc_middle/src/ty/fold.rs
+++ b/compiler/rustc_middle/src/ty/fold.rs
@@ -1,210 +1,10 @@
-//! A folding traversal mechanism for complex data structures that contain type
-//! information.
-//!
-//! This is a modifying traversal. It consumes the data structure, producing a
-//! (possibly) modified version of it. Both fallible and infallible versions are
-//! available. The name is potentially confusing, because this traversal is more
-//! like `Iterator::map` than `Iterator::fold`.
-//!
-//! This traversal has limited flexibility. Only a small number of "types of
-//! interest" within the complex data structures can receive custom
-//! modification. These are the ones containing the most important type-related
-//! information, such as `Ty`, `Predicate`, `Region`, and `Const`.
-//!
-//! There are three groups of traits involved in each traversal.
-//! - `TypeFoldable`. This is implemented once for many types, including:
-//! - Types of interest, for which the methods delegate to the folder.
-//! - All other types, including generic containers like `Vec` and `Option`.
-//! It defines a "skeleton" of how they should be folded.
-//! - `TypeSuperFoldable`. This is implemented only for each type of interest,
-//! and defines the folding "skeleton" for these types.
-//! - `TypeFolder`/`FallibleTypeFolder. One of these is implemented for each
-//! folder. This defines how types of interest are folded.
-//!
-//! This means each fold is a mixture of (a) generic folding operations, and (b)
-//! custom fold operations that are specific to the folder.
-//! - The `TypeFoldable` impls handle most of the traversal, and call into
-//! `TypeFolder`/`FallibleTypeFolder` when they encounter a type of interest.
-//! - A `TypeFolder`/`FallibleTypeFolder` may call into another `TypeFoldable`
-//! impl, because some of the types of interest are recursive and can contain
-//! other types of interest.
-//! - A `TypeFolder`/`FallibleTypeFolder` may also call into a `TypeSuperFoldable`
-//! impl, because each folder might provide custom handling only for some types
-//! of interest, or only for some variants of each type of interest, and then
-//! use default traversal for the remaining cases.
-//!
-//! For example, if you have `struct S(Ty, U)` where `S: TypeFoldable` and `U:
-//! TypeFoldable`, and an instance `s = S(ty, u)`, it would be folded like so:
-//! ```text
-//! s.fold_with(folder) calls
-//! - ty.fold_with(folder) calls
-//! - folder.fold_ty(ty) may call
-//! - ty.super_fold_with(folder)
-//! - u.fold_with(folder)
-//! ```
-use crate::ty::{self, Binder, BoundTy, Ty, TyCtxt, TypeVisitable};
+use crate::ty::{self, Binder, BoundTy, Ty, TyCtxt, TypeVisitableExt};
use rustc_data_structures::fx::FxIndexMap;
use rustc_hir::def_id::DefId;
use std::collections::BTreeMap;
-/// This trait is implemented for every type that can be folded,
-/// providing the skeleton of the traversal.
-///
-/// To implement this conveniently, use the derive macro located in
-/// `rustc_macros`.
-pub trait TypeFoldable<'tcx>: TypeVisitable<'tcx> {
- /// The entry point for folding. To fold a value `t` with a folder `f`
- /// call: `t.try_fold_with(f)`.
- ///
- /// For most types, this just traverses the value, calling `try_fold_with`
- /// on each field/element.
- ///
- /// For types of interest (such as `Ty`), the implementation of method
- /// calls a folder method specifically for that type (such as
- /// `F::try_fold_ty`). This is where control transfers from `TypeFoldable`
- /// to `TypeFolder`.
- fn try_fold_with<F: FallibleTypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error>;
-
- /// A convenient alternative to `try_fold_with` for use with infallible
- /// folders. Do not override this method, to ensure coherence with
- /// `try_fold_with`.
- fn fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Self {
- self.try_fold_with(folder).into_ok()
- }
-}
-
-// This trait is implemented for types of interest.
-pub trait TypeSuperFoldable<'tcx>: TypeFoldable<'tcx> {
- /// Provides a default fold for a type of interest. This should only be
- /// called within `TypeFolder` methods, when a non-custom traversal is
- /// desired for the value of the type of interest passed to that method.
- /// For example, in `MyFolder::try_fold_ty(ty)`, it is valid to call
- /// `ty.try_super_fold_with(self)`, but any other folding should be done
- /// with `xyz.try_fold_with(self)`.
- fn try_super_fold_with<F: FallibleTypeFolder<'tcx>>(
- self,
- folder: &mut F,
- ) -> Result<Self, F::Error>;
-
- /// A convenient alternative to `try_super_fold_with` for use with
- /// infallible folders. Do not override this method, to ensure coherence
- /// with `try_super_fold_with`.
- fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Self {
- self.try_super_fold_with(folder).into_ok()
- }
-}
-
-/// This trait is implemented for every infallible folding traversal. There is
-/// a fold method defined for every type of interest. Each such method has a
-/// default that does an "identity" fold. Implementations of these methods
-/// often fall back to a `super_fold_with` method if the primary argument
-/// doesn't satisfy a particular condition.
-///
-/// A blanket implementation of [`FallibleTypeFolder`] will defer to
-/// the infallible methods of this trait to ensure that the two APIs
-/// are coherent.
-pub trait TypeFolder<'tcx>: FallibleTypeFolder<'tcx, Error = !> {
- fn tcx<'a>(&'a self) -> TyCtxt<'tcx>;
-
- fn fold_binder<T>(&mut self, t: Binder<'tcx, T>) -> Binder<'tcx, T>
- where
- T: TypeFoldable<'tcx>,
- {
- t.super_fold_with(self)
- }
-
- fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
- t.super_fold_with(self)
- }
-
- fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
- r.super_fold_with(self)
- }
-
- fn fold_const(&mut self, c: ty::Const<'tcx>) -> ty::Const<'tcx> {
- c.super_fold_with(self)
- }
-
- fn fold_predicate(&mut self, p: ty::Predicate<'tcx>) -> ty::Predicate<'tcx> {
- p.super_fold_with(self)
- }
-}
-
-/// This trait is implemented for every folding traversal. There is a fold
-/// method defined for every type of interest. Each such method has a default
-/// that does an "identity" fold.
-///
-/// A blanket implementation of this trait (that defers to the relevant
-/// method of [`TypeFolder`]) is provided for all infallible folders in
-/// order to ensure the two APIs are coherent.
-pub trait FallibleTypeFolder<'tcx>: Sized {
- type Error;
-
- fn tcx<'a>(&'a self) -> TyCtxt<'tcx>;
-
- fn try_fold_binder<T>(&mut self, t: Binder<'tcx, T>) -> Result<Binder<'tcx, T>, Self::Error>
- where
- T: TypeFoldable<'tcx>,
- {
- t.try_super_fold_with(self)
- }
-
- fn try_fold_ty(&mut self, t: Ty<'tcx>) -> Result<Ty<'tcx>, Self::Error> {
- t.try_super_fold_with(self)
- }
-
- fn try_fold_region(&mut self, r: ty::Region<'tcx>) -> Result<ty::Region<'tcx>, Self::Error> {
- r.try_super_fold_with(self)
- }
-
- fn try_fold_const(&mut self, c: ty::Const<'tcx>) -> Result<ty::Const<'tcx>, Self::Error> {
- c.try_super_fold_with(self)
- }
-
- fn try_fold_predicate(
- &mut self,
- p: ty::Predicate<'tcx>,
- ) -> Result<ty::Predicate<'tcx>, Self::Error> {
- p.try_super_fold_with(self)
- }
-}
-
-// This blanket implementation of the fallible trait for infallible folders
-// delegates to infallible methods to ensure coherence.
-impl<'tcx, F> FallibleTypeFolder<'tcx> for F
-where
- F: TypeFolder<'tcx>,
-{
- type Error = !;
-
- fn tcx<'a>(&'a self) -> TyCtxt<'tcx> {
- TypeFolder::tcx(self)
- }
-
- fn try_fold_binder<T>(&mut self, t: Binder<'tcx, T>) -> Result<Binder<'tcx, T>, !>
- where
- T: TypeFoldable<'tcx>,
- {
- Ok(self.fold_binder(t))
- }
-
- fn try_fold_ty(&mut self, t: Ty<'tcx>) -> Result<Ty<'tcx>, !> {
- Ok(self.fold_ty(t))
- }
-
- fn try_fold_region(&mut self, r: ty::Region<'tcx>) -> Result<ty::Region<'tcx>, !> {
- Ok(self.fold_region(r))
- }
-
- fn try_fold_const(&mut self, c: ty::Const<'tcx>) -> Result<ty::Const<'tcx>, !> {
- Ok(self.fold_const(c))
- }
-
- fn try_fold_predicate(&mut self, p: ty::Predicate<'tcx>) -> Result<ty::Predicate<'tcx>, !> {
- Ok(self.fold_predicate(p))
- }
-}
+pub use rustc_type_ir::fold::{FallibleTypeFolder, TypeFoldable, TypeFolder, TypeSuperFoldable};
///////////////////////////////////////////////////////////////////////////
// Some sample folders
@@ -221,13 +21,13 @@ where
pub ct_op: H,
}
-impl<'tcx, F, G, H> TypeFolder<'tcx> for BottomUpFolder<'tcx, F, G, H>
+impl<'tcx, F, G, H> TypeFolder<TyCtxt<'tcx>> for BottomUpFolder<'tcx, F, G, H>
where
F: FnMut(Ty<'tcx>) -> Ty<'tcx>,
G: FnMut(ty::Region<'tcx>) -> ty::Region<'tcx>,
H: FnMut(ty::Const<'tcx>) -> ty::Const<'tcx>,
{
- fn tcx<'b>(&'b self) -> TyCtxt<'tcx> {
+ fn interner(&self) -> TyCtxt<'tcx> {
self.tcx
}
@@ -260,7 +60,7 @@ impl<'tcx> TyCtxt<'tcx> {
mut f: impl FnMut(ty::Region<'tcx>, ty::DebruijnIndex) -> ty::Region<'tcx>,
) -> T
where
- T: TypeFoldable<'tcx>,
+ T: TypeFoldable<TyCtxt<'tcx>>,
{
value.fold_with(&mut RegionFolder::new(self, &mut f))
}
@@ -271,7 +71,7 @@ impl<'tcx> TyCtxt<'tcx> {
mut f: impl FnMut(ty::Region<'tcx>, ty::DebruijnIndex) -> ty::Region<'tcx>,
) -> T
where
- T: TypeSuperFoldable<'tcx>,
+ T: TypeSuperFoldable<TyCtxt<'tcx>>,
{
value.super_fold_with(&mut RegionFolder::new(self, &mut f))
}
@@ -311,12 +111,12 @@ impl<'a, 'tcx> RegionFolder<'a, 'tcx> {
}
}
-impl<'a, 'tcx> TypeFolder<'tcx> for RegionFolder<'a, 'tcx> {
- fn tcx<'b>(&'b self) -> TyCtxt<'tcx> {
+impl<'a, 'tcx> TypeFolder<TyCtxt<'tcx>> for RegionFolder<'a, 'tcx> {
+ fn interner(&self) -> TyCtxt<'tcx> {
self.tcx
}
- fn fold_binder<T: TypeFoldable<'tcx>>(
+ fn fold_binder<T: TypeFoldable<TyCtxt<'tcx>>>(
&mut self,
t: ty::Binder<'tcx, T>,
) -> ty::Binder<'tcx, T> {
@@ -385,15 +185,15 @@ impl<'tcx, D: BoundVarReplacerDelegate<'tcx>> BoundVarReplacer<'tcx, D> {
}
}
-impl<'tcx, D> TypeFolder<'tcx> for BoundVarReplacer<'tcx, D>
+impl<'tcx, D> TypeFolder<TyCtxt<'tcx>> for BoundVarReplacer<'tcx, D>
where
D: BoundVarReplacerDelegate<'tcx>,
{
- fn tcx<'b>(&'b self) -> TyCtxt<'tcx> {
+ fn interner(&self) -> TyCtxt<'tcx> {
self.tcx
}
- fn fold_binder<T: TypeFoldable<'tcx>>(
+ fn fold_binder<T: TypeFoldable<TyCtxt<'tcx>>>(
&mut self,
t: ty::Binder<'tcx, T>,
) -> ty::Binder<'tcx, T> {
@@ -425,7 +225,7 @@ where
// debruijn index. Then we adjust it to the
// correct depth.
assert_eq!(debruijn1, ty::INNERMOST);
- self.tcx.reuse_or_mk_region(region, ty::ReLateBound(debruijn, br))
+ self.tcx.mk_re_late_bound(debruijn, br)
} else {
region
}
@@ -471,7 +271,7 @@ impl<'tcx> TyCtxt<'tcx> {
) -> (T, BTreeMap<ty::BoundRegion, ty::Region<'tcx>>)
where
F: FnMut(ty::BoundRegion) -> ty::Region<'tcx>,
- T: TypeFoldable<'tcx>,
+ T: TypeFoldable<TyCtxt<'tcx>>,
{
let mut region_map = BTreeMap::new();
let real_fld_r = |br: ty::BoundRegion| *region_map.entry(br).or_insert_with(|| fld_r(br));
@@ -486,7 +286,7 @@ impl<'tcx> TyCtxt<'tcx> {
) -> T
where
F: FnMut(ty::BoundRegion) -> ty::Region<'tcx>,
- T: TypeFoldable<'tcx>,
+ T: TypeFoldable<TyCtxt<'tcx>>,
{
let value = value.skip_binder();
if !value.has_escaping_bound_vars() {
@@ -505,7 +305,7 @@ impl<'tcx> TyCtxt<'tcx> {
/// Replaces all escaping bound vars. The `fld_r` closure replaces escaping
/// bound regions; the `fld_t` closure replaces escaping bound types and the `fld_c`
/// closure replaces escaping bound consts.
- pub fn replace_escaping_bound_vars_uncached<T: TypeFoldable<'tcx>>(
+ pub fn replace_escaping_bound_vars_uncached<T: TypeFoldable<TyCtxt<'tcx>>>(
self,
value: T,
delegate: impl BoundVarReplacerDelegate<'tcx>,
@@ -521,7 +321,7 @@ impl<'tcx> TyCtxt<'tcx> {
/// Replaces all types or regions bound by the given `Binder`. The `fld_r`
/// closure replaces bound regions, the `fld_t` closure replaces bound
/// types, and `fld_c` replaces bound constants.
- pub fn replace_bound_vars_uncached<T: TypeFoldable<'tcx>>(
+ pub fn replace_bound_vars_uncached<T: TypeFoldable<TyCtxt<'tcx>>>(
self,
value: Binder<'tcx, T>,
delegate: impl BoundVarReplacerDelegate<'tcx>,
@@ -537,35 +337,29 @@ impl<'tcx> TyCtxt<'tcx> {
value: ty::Binder<'tcx, T>,
) -> T
where
- T: TypeFoldable<'tcx>,
+ T: TypeFoldable<TyCtxt<'tcx>>,
{
self.replace_late_bound_regions_uncached(value, |br| {
- self.mk_region(ty::ReFree(ty::FreeRegion {
- scope: all_outlive_scope,
- bound_region: br.kind,
- }))
+ self.mk_re_free(all_outlive_scope, br.kind)
})
}
pub fn shift_bound_var_indices<T>(self, bound_vars: usize, value: T) -> T
where
- T: TypeFoldable<'tcx>,
+ T: TypeFoldable<TyCtxt<'tcx>>,
{
let shift_bv = |bv: ty::BoundVar| ty::BoundVar::from_usize(bv.as_usize() + bound_vars);
self.replace_escaping_bound_vars_uncached(
value,
FnMutDelegate {
regions: &mut |r: ty::BoundRegion| {
- self.mk_region(ty::ReLateBound(
+ self.mk_re_late_bound(
ty::INNERMOST,
ty::BoundRegion { var: shift_bv(r.var), kind: r.kind },
- ))
+ )
},
types: &mut |t: ty::BoundTy| {
- self.mk_ty(ty::Bound(
- ty::INNERMOST,
- ty::BoundTy { var: shift_bv(t.var), kind: t.kind },
- ))
+ self.mk_bound(ty::INNERMOST, ty::BoundTy { var: shift_bv(t.var), kind: t.kind })
},
consts: &mut |c, ty: Ty<'tcx>| {
self.mk_const(ty::ConstKind::Bound(ty::INNERMOST, shift_bv(c)), ty)
@@ -578,7 +372,7 @@ impl<'tcx> TyCtxt<'tcx> {
/// method lookup and a few other places where precise region relationships are not required.
pub fn erase_late_bound_regions<T>(self, value: Binder<'tcx, T>) -> T
where
- T: TypeFoldable<'tcx>,
+ T: TypeFoldable<TyCtxt<'tcx>>,
{
self.replace_late_bound_regions(value, |_| self.lifetimes.re_erased).0
}
@@ -586,7 +380,7 @@ impl<'tcx> TyCtxt<'tcx> {
/// Anonymize all bound variables in `value`, this is mostly used to improve caching.
pub fn anonymize_bound_vars<T>(self, value: Binder<'tcx, T>) -> Binder<'tcx, T>
where
- T: TypeFoldable<'tcx>,
+ T: TypeFoldable<TyCtxt<'tcx>>,
{
struct Anonymize<'a, 'tcx> {
tcx: TyCtxt<'tcx>,
@@ -603,16 +397,18 @@ impl<'tcx> TyCtxt<'tcx> {
})
.expect_region();
let br = ty::BoundRegion { var, kind };
- self.tcx.mk_region(ty::ReLateBound(ty::INNERMOST, br))
+ self.tcx.mk_re_late_bound(ty::INNERMOST, br)
}
fn replace_ty(&mut self, bt: ty::BoundTy) -> Ty<'tcx> {
let entry = self.map.entry(bt.var);
let index = entry.index();
let var = ty::BoundVar::from_usize(index);
let kind = entry
- .or_insert_with(|| ty::BoundVariableKind::Ty(ty::BoundTyKind::Anon))
+ .or_insert_with(|| {
+ ty::BoundVariableKind::Ty(ty::BoundTyKind::Anon(index as u32))
+ })
.expect_ty();
- self.tcx.mk_ty(ty::Bound(ty::INNERMOST, BoundTy { var, kind }))
+ self.tcx.mk_bound(ty::INNERMOST, BoundTy { var, kind })
}
fn replace_const(&mut self, bv: ty::BoundVar, ty: Ty<'tcx>) -> ty::Const<'tcx> {
let entry = self.map.entry(bv);
@@ -626,7 +422,7 @@ impl<'tcx> TyCtxt<'tcx> {
let mut map = Default::default();
let delegate = Anonymize { tcx: self, map: &mut map };
let inner = self.replace_escaping_bound_vars_uncached(value.skip_binder(), delegate);
- let bound_vars = self.mk_bound_variable_kinds(map.into_values());
+ let bound_vars = self.mk_bound_variable_kinds_from_iter(map.into_values());
Binder::bind_with_vars(inner, bound_vars)
}
}
@@ -652,12 +448,12 @@ impl<'tcx> Shifter<'tcx> {
}
}
-impl<'tcx> TypeFolder<'tcx> for Shifter<'tcx> {
- fn tcx<'b>(&'b self) -> TyCtxt<'tcx> {
+impl<'tcx> TypeFolder<TyCtxt<'tcx>> for Shifter<'tcx> {
+ fn interner(&self) -> TyCtxt<'tcx> {
self.tcx
}
- fn fold_binder<T: TypeFoldable<'tcx>>(
+ fn fold_binder<T: TypeFoldable<TyCtxt<'tcx>>>(
&mut self,
t: ty::Binder<'tcx, T>,
) -> ty::Binder<'tcx, T> {
@@ -671,8 +467,7 @@ impl<'tcx> TypeFolder<'tcx> for Shifter<'tcx> {
match *r {
ty::ReLateBound(debruijn, br) if debruijn >= self.current_index => {
let debruijn = debruijn.shifted_in(self.amount);
- let shifted = ty::ReLateBound(debruijn, br);
- self.tcx.mk_region(shifted)
+ self.tcx.mk_re_late_bound(debruijn, br)
}
_ => r,
}
@@ -682,7 +477,7 @@ impl<'tcx> TypeFolder<'tcx> for Shifter<'tcx> {
match *ty.kind() {
ty::Bound(debruijn, bound_ty) if debruijn >= self.current_index => {
let debruijn = debruijn.shifted_in(self.amount);
- self.tcx.mk_ty(ty::Bound(debruijn, bound_ty))
+ self.tcx.mk_bound(debruijn, bound_ty)
}
_ if ty.has_vars_bound_at_or_above(self.current_index) => ty.super_fold_with(self),
@@ -713,7 +508,7 @@ pub fn shift_region<'tcx>(
) -> ty::Region<'tcx> {
match *region {
ty::ReLateBound(debruijn, br) if amount > 0 => {
- tcx.mk_region(ty::ReLateBound(debruijn.shifted_in(amount), br))
+ tcx.mk_re_late_bound(debruijn.shifted_in(amount), br)
}
_ => region,
}
@@ -721,7 +516,7 @@ pub fn shift_region<'tcx>(
pub fn shift_vars<'tcx, T>(tcx: TyCtxt<'tcx>, value: T, amount: u32) -> T
where
- T: TypeFoldable<'tcx>,
+ T: TypeFoldable<TyCtxt<'tcx>>,
{
debug!("shift_vars(value={:?}, amount={})", value, amount);
diff --git a/compiler/rustc_middle/src/ty/generics.rs b/compiler/rustc_middle/src/ty/generics.rs
index 801ca6004..baef4ffed 100644
--- a/compiler/rustc_middle/src/ty/generics.rs
+++ b/compiler/rustc_middle/src/ty/generics.rs
@@ -85,7 +85,7 @@ impl GenericParamDef {
) -> Option<EarlyBinder<ty::GenericArg<'tcx>>> {
match self.kind {
GenericParamDefKind::Type { has_default, .. } if has_default => {
- Some(tcx.bound_type_of(self.def_id).map_bound(|t| t.into()))
+ Some(tcx.type_of(self.def_id).map_bound(|t| t.into()))
}
GenericParamDefKind::Const { has_default } if has_default => {
Some(tcx.const_param_default(self.def_id).map_bound(|c| c.into()))
@@ -100,10 +100,10 @@ impl GenericParamDef {
preceding_substs: &[ty::GenericArg<'tcx>],
) -> ty::GenericArg<'tcx> {
match &self.kind {
- ty::GenericParamDefKind::Lifetime => tcx.lifetimes.re_static.into(),
- ty::GenericParamDefKind::Type { .. } => tcx.ty_error().into(),
+ ty::GenericParamDefKind::Lifetime => tcx.mk_re_error_misc().into(),
+ ty::GenericParamDefKind::Type { .. } => tcx.ty_error_misc().into(),
ty::GenericParamDefKind::Const { .. } => {
- tcx.const_error(tcx.bound_type_of(self.def_id).subst(tcx, preceding_substs)).into()
+ tcx.const_error(tcx.type_of(self.def_id).subst(tcx, preceding_substs)).into()
}
}
}
diff --git a/compiler/rustc_middle/src/ty/impls_ty.rs b/compiler/rustc_middle/src/ty/impls_ty.rs
index 3e59c0b96..4c7822acd 100644
--- a/compiler/rustc_middle/src/ty/impls_ty.rs
+++ b/compiler/rustc_middle/src/ty/impls_ty.rs
@@ -79,7 +79,7 @@ impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for ty::subst::GenericArgKin
// WARNING: We dedup cache the `HashStable` results for `List`
// while ignoring types and freely transmute
// between `List<Ty<'tcx>>` and `List<GenericArg<'tcx>>`.
- // See `fn intern_type_list` for more details.
+ // See `fn mk_type_list` for more details.
//
// We therefore hash types without adding a hash for their discriminant.
//
diff --git a/compiler/rustc_middle/src/ty/inhabitedness/inhabited_predicate.rs b/compiler/rustc_middle/src/ty/inhabitedness/inhabited_predicate.rs
index 33f727297..e268553f8 100644
--- a/compiler/rustc_middle/src/ty/inhabitedness/inhabited_predicate.rs
+++ b/compiler/rustc_middle/src/ty/inhabitedness/inhabited_predicate.rs
@@ -57,7 +57,7 @@ impl<'tcx> InhabitedPredicate<'tcx> {
match self {
Self::False => Ok(false),
Self::True => Ok(true),
- Self::ConstIsZero(const_) => match const_.try_eval_usize(tcx, param_env) {
+ Self::ConstIsZero(const_) => match const_.try_eval_target_usize(tcx, param_env) {
None | Some(0) => Ok(true),
Some(1..) => Ok(false),
},
@@ -159,7 +159,7 @@ impl<'tcx> InhabitedPredicate<'tcx> {
match self {
Self::ConstIsZero(c) => {
let c = ty::EarlyBinder(c).subst(tcx, substs);
- let pred = match c.kind().try_to_machine_usize(tcx) {
+ let pred = match c.kind().try_to_target_usize(tcx) {
Some(0) => Self::True,
Some(1..) => Self::False,
None => Self::ConstIsZero(c),
diff --git a/compiler/rustc_middle/src/ty/inhabitedness/mod.rs b/compiler/rustc_middle/src/ty/inhabitedness/mod.rs
index 5d5089cec..92a040068 100644
--- a/compiler/rustc_middle/src/ty/inhabitedness/mod.rs
+++ b/compiler/rustc_middle/src/ty/inhabitedness/mod.rs
@@ -87,7 +87,7 @@ impl<'tcx> VariantDef {
InhabitedPredicate::all(
tcx,
self.fields.iter().map(|field| {
- let pred = tcx.type_of(field.did).inhabited_predicate(tcx);
+ let pred = tcx.type_of(field.did).subst_identity().inhabited_predicate(tcx);
if adt.is_enum() {
return pred;
}
@@ -105,7 +105,7 @@ impl<'tcx> VariantDef {
impl<'tcx> Ty<'tcx> {
pub fn inhabited_predicate(self, tcx: TyCtxt<'tcx>) -> InhabitedPredicate<'tcx> {
match self.kind() {
- // For now, union`s are always considered inhabited
+ // For now, unions are always considered inhabited
Adt(adt, _) if adt.is_union() => InhabitedPredicate::True,
// Non-exhaustive ADTs from other crates are always considered inhabited
Adt(adt, _) if adt.is_variant_list_non_exhaustive() && !adt.did().is_local() => {
@@ -191,7 +191,7 @@ fn inhabited_predicate_type<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> InhabitedP
// If we can evaluate the array length before having a `ParamEnv`, then
// we can simplify the predicate. This is an optimization.
- Array(ty, len) => match len.kind().try_to_machine_usize(tcx) {
+ Array(ty, len) => match len.kind().try_to_target_usize(tcx) {
Some(0) => InhabitedPredicate::True,
Some(1..) => ty.inhabited_predicate(tcx),
None => ty.inhabited_predicate(tcx).or(tcx, InhabitedPredicate::ConstIsZero(len)),
diff --git a/compiler/rustc_middle/src/ty/instance.rs b/compiler/rustc_middle/src/ty/instance.rs
index 6ac00d16c..f4028a5a9 100644
--- a/compiler/rustc_middle/src/ty/instance.rs
+++ b/compiler/rustc_middle/src/ty/instance.rs
@@ -1,7 +1,7 @@
use crate::middle::codegen_fn_attrs::CodegenFnAttrFlags;
use crate::ty::print::{FmtPrinter, Printer};
-use crate::ty::{self, Ty, TyCtxt, TypeFoldable, TypeSuperFoldable, TypeVisitable};
-use crate::ty::{EarlyBinder, InternalSubsts, SubstsRef};
+use crate::ty::{self, Ty, TyCtxt, TypeFoldable, TypeSuperFoldable};
+use crate::ty::{EarlyBinder, InternalSubsts, SubstsRef, TypeVisitableExt};
use rustc_errors::ErrorGuaranteed;
use rustc_hir::def::Namespace;
use rustc_hir::def_id::{CrateNum, DefId};
@@ -103,7 +103,7 @@ impl<'tcx> Instance<'tcx> {
/// lifetimes erased, allowing a `ParamEnv` to be specified for use during normalization.
pub fn ty(&self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> Ty<'tcx> {
let ty = tcx.type_of(self.def.def_id());
- tcx.subst_and_normalize_erasing_regions(self.substs, param_env, ty)
+ tcx.subst_and_normalize_erasing_regions(self.substs, param_env, ty.skip_binder())
}
/// Finds a crate that contains a monomorphization of this instance that
@@ -459,7 +459,7 @@ impl<'tcx> Instance<'tcx> {
substs: SubstsRef<'tcx>,
) -> Option<Instance<'tcx>> {
debug!("resolve_for_vtable(def_id={:?}, substs={:?})", def_id, substs);
- let fn_sig = tcx.fn_sig(def_id);
+ let fn_sig = tcx.fn_sig(def_id).subst_identity();
let is_vtable_shim = !fn_sig.inputs().skip_binder().is_empty()
&& fn_sig.input(0).skip_binder().is_param(0)
&& tcx.generics_of(def_id).has_self;
@@ -540,7 +540,7 @@ impl<'tcx> Instance<'tcx> {
pub fn resolve_drop_in_place(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> ty::Instance<'tcx> {
let def_id = tcx.require_lang_item(LangItem::DropInPlace, None);
- let substs = tcx.intern_substs(&[ty.into()]);
+ let substs = tcx.mk_substs(&[ty.into()]);
Instance::expect_resolve(tcx, ty::ParamEnv::reveal_all(), def_id, substs)
}
@@ -584,12 +584,12 @@ impl<'tcx> Instance<'tcx> {
/// this function returns `None`, then the MIR body does not require substitution during
/// codegen.
fn substs_for_mir_body(&self) -> Option<SubstsRef<'tcx>> {
- if self.def.has_polymorphic_mir_body() { Some(self.substs) } else { None }
+ self.def.has_polymorphic_mir_body().then_some(self.substs)
}
pub fn subst_mir<T>(&self, tcx: TyCtxt<'tcx>, v: &T) -> T
where
- T: TypeFoldable<'tcx> + Copy,
+ T: TypeFoldable<TyCtxt<'tcx>> + Copy,
{
if let Some(substs) = self.substs_for_mir_body() {
EarlyBinder(*v).subst(tcx, substs)
@@ -606,7 +606,7 @@ impl<'tcx> Instance<'tcx> {
v: T,
) -> T
where
- T: TypeFoldable<'tcx> + Clone,
+ T: TypeFoldable<TyCtxt<'tcx>> + Clone,
{
if let Some(substs) = self.substs_for_mir_body() {
tcx.subst_and_normalize_erasing_regions(substs, param_env, v)
@@ -623,7 +623,7 @@ impl<'tcx> Instance<'tcx> {
v: T,
) -> Result<T, NormalizationError<'tcx>>
where
- T: TypeFoldable<'tcx> + Clone,
+ T: TypeFoldable<TyCtxt<'tcx>> + Clone,
{
if let Some(substs) = self.substs_for_mir_body() {
tcx.try_subst_and_normalize_erasing_regions(substs, param_env, v)
@@ -662,7 +662,7 @@ fn polymorphize<'tcx>(
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() {
+ } else if tcx.type_of(def_id).skip_binder().is_generator() {
Some(substs.as_generator().tupled_upvars_ty())
} else {
None
@@ -674,8 +674,8 @@ fn polymorphize<'tcx>(
tcx: TyCtxt<'tcx>,
}
- impl<'tcx> ty::TypeFolder<'tcx> for PolymorphizationFolder<'tcx> {
- fn tcx<'a>(&'a self) -> TyCtxt<'tcx> {
+ impl<'tcx> ty::TypeFolder<TyCtxt<'tcx>> for PolymorphizationFolder<'tcx> {
+ fn interner(&self) -> TyCtxt<'tcx> {
self.tcx
}
diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs
index dfd016569..254ffc33c 100644
--- a/compiler/rustc_middle/src/ty/layout.rs
+++ b/compiler/rustc_middle/src/ty/layout.rs
@@ -1,11 +1,13 @@
+use crate::fluent_generated as fluent;
use crate::middle::codegen_fn_attrs::CodegenFnAttrFlags;
use crate::ty::normalize_erasing_regions::NormalizationError;
-use crate::ty::{self, ReprOptions, Ty, TyCtxt, TypeVisitable};
+use crate::ty::{self, ReprOptions, Ty, TyCtxt, TypeVisitableExt};
use rustc_errors::{DiagnosticBuilder, Handler, IntoDiagnostic};
use rustc_hir as hir;
use rustc_hir::def_id::DefId;
use rustc_index::vec::Idx;
use rustc_session::config::OptLevel;
+use rustc_span::symbol::{sym, Symbol};
use rustc_span::{Span, DUMMY_SP};
use rustc_target::abi::call::FnAbi;
use rustc_target::abi::*;
@@ -91,7 +93,7 @@ impl IntegerExt for Integer {
if discr < fit {
bug!(
"Integer::repr_discr: `#[repr]` hint too small for \
- discriminant range of enum `{}",
+ discriminant range of enum `{}`",
ty
)
}
@@ -128,7 +130,8 @@ impl PrimitiveExt for Primitive {
Int(i, signed) => i.to_ty(tcx, signed),
F32 => tcx.types.f32,
F64 => tcx.types.f64,
- Pointer => tcx.mk_mut_ptr(tcx.mk_unit()),
+ // FIXME(erikdesjardins): handle non-default addrspace ptr sizes
+ Pointer(_) => tcx.mk_mut_ptr(tcx.mk_unit()),
}
}
@@ -138,7 +141,11 @@ impl PrimitiveExt for Primitive {
fn to_int_ty<'tcx>(&self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> {
match *self {
Int(i, signed) => i.to_ty(tcx, signed),
- Pointer => tcx.types.usize,
+ // FIXME(erikdesjardins): handle non-default addrspace ptr sizes
+ Pointer(_) => {
+ let signed = false;
+ tcx.data_layout().ptr_sized_integer().to_ty(tcx, signed)
+ }
F32 | F64 => bug!("floats do not have an int type"),
}
}
@@ -163,6 +170,41 @@ 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;
+/// Used in `check_validity_requirement` to indicate the kind of initialization
+/// that is checked to be valid
+#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, HashStable)]
+pub enum ValidityRequirement {
+ Inhabited,
+ Zero,
+ /// The return value of mem::uninitialized, 0x01
+ /// (unless -Zstrict-init-checks is on, in which case it's the same as Uninit).
+ UninitMitigated0x01Fill,
+ /// True uninitialized memory.
+ Uninit,
+}
+
+impl ValidityRequirement {
+ pub fn from_intrinsic(intrinsic: Symbol) -> Option<Self> {
+ match intrinsic {
+ sym::assert_inhabited => Some(Self::Inhabited),
+ sym::assert_zero_valid => Some(Self::Zero),
+ sym::assert_mem_uninitialized_valid => Some(Self::UninitMitigated0x01Fill),
+ _ => None,
+ }
+ }
+}
+
+impl fmt::Display for ValidityRequirement {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ match self {
+ Self::Inhabited => f.write_str("is inhabited"),
+ Self::Zero => f.write_str("allows being left zeroed"),
+ Self::UninitMitigated0x01Fill => f.write_str("allows being filled with 0x01"),
+ Self::Uninit => f.write_str("allows being left uninitialized"),
+ }
+ }
+}
+
#[derive(Copy, Clone, Debug, HashStable, TyEncodable, TyDecodable)]
pub enum LayoutError<'tcx> {
Unknown(Ty<'tcx>),
@@ -177,16 +219,16 @@ impl IntoDiagnostic<'_, !> for LayoutError<'_> {
match self {
LayoutError::Unknown(ty) => {
diag.set_arg("ty", ty);
- diag.set_primary_message(rustc_errors::fluent::middle_unknown_layout);
+ diag.set_primary_message(fluent::middle_unknown_layout);
}
LayoutError::SizeOverflow(ty) => {
diag.set_arg("ty", ty);
- diag.set_primary_message(rustc_errors::fluent::middle_values_too_big);
+ diag.set_primary_message(fluent::middle_values_too_big);
}
LayoutError::NormalizationFailure(ty, e) => {
diag.set_arg("ty", ty);
diag.set_arg("failure_ty", e.get_type_for_failure());
- diag.set_primary_message(rustc_errors::fluent::middle_cannot_be_normalized);
+ diag.set_primary_message(fluent::middle_cannot_be_normalized);
}
}
diag
@@ -590,7 +632,7 @@ where
ty::Adt(def, _) => def.variant(variant_index).fields.len(),
_ => bug!(),
};
- tcx.intern_layout(LayoutS {
+ tcx.mk_layout(LayoutS {
variants: Variants::Single { index: variant_index },
fields: match NonZeroUsize::new(fields) {
Some(fields) => FieldsShape::Union(fields),
@@ -603,7 +645,7 @@ where
})
}
- Variants::Multiple { ref variants, .. } => cx.tcx().intern_layout(variants[variant_index].clone()),
+ Variants::Multiple { ref variants, .. } => cx.tcx().mk_layout(variants[variant_index].clone()),
};
assert_eq!(*layout.variants(), Variants::Single { index: variant_index });
@@ -625,7 +667,7 @@ where
let tcx = cx.tcx();
let tag_layout = |tag: Scalar| -> TyAndLayout<'tcx> {
TyAndLayout {
- layout: tcx.intern_layout(LayoutS::scalar(cx, tag)),
+ layout: tcx.mk_layout(LayoutS::scalar(cx, tag)),
ty: tag.primitive().to_ty(tcx),
}
};
@@ -640,6 +682,7 @@ where
| ty::Never
| ty::FnDef(..)
| ty::GeneratorWitness(..)
+ | ty::GeneratorWitnessMIR(..)
| ty::Foreign(..)
| ty::Dynamic(_, _, ty::Dyn) => {
bug!("TyAndLayout::field({:?}): not applicable", this)
@@ -764,7 +807,7 @@ where
ty::Dynamic(_, _, ty::DynStar) => {
if i == 0 {
- TyMaybeWithLayout::Ty(tcx.types.usize)
+ TyMaybeWithLayout::Ty(tcx.mk_mut_ptr(tcx.types.unit))
} else if i == 1 {
// FIXME(dyn-star) same FIXME as above applies here too
TyMaybeWithLayout::Ty(
@@ -812,17 +855,12 @@ where
let tcx = cx.tcx();
let param_env = cx.param_env();
- let addr_space_of_ty = |ty: Ty<'tcx>| {
- if ty.is_fn() { cx.data_layout().instruction_address_space } else { AddressSpace::DATA }
- };
-
let pointee_info = match *this.ty.kind() {
ty::RawPtr(mt) if offset.bytes() == 0 => {
tcx.layout_of(param_env.and(mt.ty)).ok().map(|layout| PointeeInfo {
size: layout.size,
align: layout.align.abi,
safe: None,
- address_space: addr_space_of_ty(mt.ty),
})
}
ty::FnPtr(fn_sig) if offset.bytes() == 0 => {
@@ -830,44 +868,26 @@ where
size: layout.size,
align: layout.align.abi,
safe: None,
- address_space: cx.data_layout().instruction_address_space,
})
}
ty::Ref(_, ty, mt) if offset.bytes() == 0 => {
- let address_space = addr_space_of_ty(ty);
- let kind = if tcx.sess.opts.optimize == OptLevel::No {
- // Use conservative pointer kind if not optimizing. This saves us the
- // Freeze/Unpin queries, and can save time in the codegen backend (noalias
- // attributes in LLVM have compile-time cost even in unoptimized builds).
- PointerKind::SharedMutable
- } else {
- match mt {
- hir::Mutability::Not => {
- if ty.is_freeze(tcx, cx.param_env()) {
- PointerKind::Frozen
- } else {
- PointerKind::SharedMutable
- }
- }
- hir::Mutability::Mut => {
- // References to self-referential structures should not be considered
- // noalias, as another pointer to the structure can be obtained, that
- // is not based-on the original reference. We consider all !Unpin
- // types to be potentially self-referential here.
- if ty.is_unpin(tcx, cx.param_env()) {
- PointerKind::UniqueBorrowed
- } else {
- PointerKind::UniqueBorrowedPinned
- }
- }
- }
+ // Use conservative pointer kind if not optimizing. This saves us the
+ // Freeze/Unpin queries, and can save time in the codegen backend (noalias
+ // attributes in LLVM have compile-time cost even in unoptimized builds).
+ let optimize = tcx.sess.opts.optimize != OptLevel::No;
+ let kind = match mt {
+ hir::Mutability::Not => PointerKind::SharedRef {
+ frozen: optimize && ty.is_freeze(tcx, cx.param_env()),
+ },
+ hir::Mutability::Mut => PointerKind::MutableRef {
+ unpin: optimize && ty.is_unpin(tcx, cx.param_env()),
+ },
};
tcx.layout_of(param_env.and(ty)).ok().map(|layout| PointeeInfo {
size: layout.size,
align: layout.align.abi,
safe: Some(kind),
- address_space,
})
}
@@ -904,7 +924,9 @@ where
let mut result = None;
if let Some(variant) = data_variant {
- let ptr_end = offset + Pointer.size(cx);
+ // FIXME(erikdesjardins): handle non-default addrspace ptr sizes
+ // (requires passing in the expected address space from the caller)
+ let ptr_end = offset + Pointer(AddressSpace::DATA).size(cx);
for i in 0..variant.fields.count() {
let field_start = variant.fields.offset(i);
if field_start <= offset {
@@ -930,7 +952,10 @@ where
if let Some(ref mut pointee) = result {
if let ty::Adt(def, _) = this.ty.kind() {
if def.is_box() && offset.bytes() == 0 {
- pointee.safe = Some(PointerKind::UniqueOwned);
+ let optimize = tcx.sess.opts.optimize != OptLevel::No;
+ pointee.safe = Some(PointerKind::Box {
+ unpin: optimize && this.ty.boxed_ty().is_unpin(tcx, cx.param_env()),
+ });
}
}
}
diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs
index 7dfcd1bb5..dce18a585 100644
--- a/compiler/rustc_middle/src/ty/mod.rs
+++ b/compiler/rustc_middle/src/ty/mod.rs
@@ -12,7 +12,7 @@
#![allow(rustc::usage_of_ty_tykind)]
pub use self::fold::{FallibleTypeFolder, TypeFoldable, TypeFolder, TypeSuperFoldable};
-pub use self::visit::{TypeSuperVisitable, TypeVisitable, TypeVisitor};
+pub use self::visit::{TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor};
pub use self::AssocItemContainer::*;
pub use self::BorrowKind::*;
pub use self::IntVarValue::*;
@@ -31,23 +31,22 @@ pub use generics::*;
use rustc_ast as ast;
use rustc_ast::node_id::NodeMap;
use rustc_attr as attr;
-use rustc_data_structures::fingerprint::Fingerprint;
use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap, FxIndexSet};
use rustc_data_structures::intern::Interned;
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
use rustc_data_structures::tagged_ptr::CopyTaggedPtr;
+use rustc_errors::ErrorGuaranteed;
use rustc_hir as hir;
-use rustc_hir::def::{CtorKind, CtorOf, DefKind, LifetimeRes, Res};
+use rustc_hir::def::{CtorKind, CtorOf, DefKind, DocLinkResMap, LifetimeRes, Res};
use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, LocalDefId, LocalDefIdMap};
use rustc_hir::Node;
use rustc_index::vec::IndexVec;
use rustc_macros::HashStable;
use rustc_query_system::ich::StableHashingContext;
use rustc_serialize::{Decodable, Encodable};
-use rustc_session::cstore::Untracked;
use rustc_span::hygiene::MacroKind;
use rustc_span::symbol::{kw, sym, Ident, Symbol};
-use rustc_span::{ExpnId, Span};
+use rustc_span::{ExpnId, ExpnKind, Span};
use rustc_target::abi::{Align, Integer, IntegerType, VariantIdx};
pub use rustc_target::abi::{ReprFlags, ReprOptions};
use rustc_type_ir::WithCachedTypeInfo;
@@ -74,7 +73,7 @@ pub use self::binding::BindingMode;
pub use self::binding::BindingMode::*;
pub use self::closure::{
is_ancestor_or_same_capture, place_to_string_for_capture, BorrowKind, CaptureInfo,
- CapturedPlace, ClosureKind, MinCaptureInformationMap, MinCaptureList,
+ CapturedPlace, ClosureKind, ClosureTypeInfo, MinCaptureInformationMap, MinCaptureList,
RootVariableMinCaptureList, UpvarCapture, UpvarCaptureMap, UpvarId, UpvarListMap, UpvarPath,
CAPTURE_STRUCT_LOCAL,
};
@@ -154,7 +153,6 @@ pub type RegisteredTools = FxHashSet<Ident>;
pub struct ResolverOutputs {
pub global_ctxt: ResolverGlobalCtxt,
pub ast_lowering: ResolverAstLowering,
- pub untracked: Untracked,
}
#[derive(Debug)]
@@ -167,12 +165,8 @@ pub struct ResolverGlobalCtxt {
pub effective_visibilities: EffectiveVisibilities,
pub extern_crate_map: FxHashMap<LocalDefId, CrateNum>,
pub maybe_unused_trait_imports: FxIndexSet<LocalDefId>,
- pub maybe_unused_extern_crates: Vec<(LocalDefId, Span)>,
pub reexport_map: FxHashMap<LocalDefId, Vec<ModChild>>,
pub glob_map: FxHashMap<LocalDefId, FxHashSet<Symbol>>,
- /// Extern prelude entries. The value is `true` if the entry was introduced
- /// via `extern crate` item and not `--extern` option or compiler built-in.
- pub extern_prelude: FxHashMap<Symbol, bool>,
pub main_def: Option<MainDefinition>,
pub trait_impls: FxIndexMap<DefId, Vec<LocalDefId>>,
/// A list of proc macro LocalDefIds, written out in the order in which
@@ -182,6 +176,9 @@ pub struct ResolverGlobalCtxt {
/// exist under `std`. For example, wrote `str::from_utf8` instead of `std::str::from_utf8`.
pub confused_type_with_std_module: FxHashMap<Span, Span>,
pub registered_tools: RegisteredTools,
+ pub doc_link_resolutions: FxHashMap<LocalDefId, DocLinkResMap>,
+ pub doc_link_traits_in_scope: FxHashMap<LocalDefId, Vec<DefId>>,
+ pub all_macro_rules: FxHashMap<Symbol, Res<ast::NodeId>>,
}
/// Resolutions that should only be used for lowering.
@@ -453,18 +450,6 @@ pub struct CReaderCacheKey {
#[rustc_pass_by_value]
pub struct Ty<'tcx>(Interned<'tcx, WithCachedTypeInfo<TyKind<'tcx>>>);
-impl<'tcx> TyCtxt<'tcx> {
- /// A "bool" type used in rustc_mir_transform unit tests when we
- /// have not spun up a TyCtxt.
- pub const BOOL_TY_FOR_UNIT_TESTING: Ty<'tcx> =
- Ty(Interned::new_unchecked(&WithCachedTypeInfo {
- internee: ty::Bool,
- stable_hash: Fingerprint::ZERO,
- flags: TypeFlags::empty(),
- outer_exclusive_binder: DebruijnIndex::from_usize(0),
- }));
-}
-
impl ty::EarlyBoundRegion {
/// Does this early bound region have a name? Early bound regions normally
/// always have names except when using anonymous lifetimes (`'_`).
@@ -558,6 +543,8 @@ impl<'tcx> Predicate<'tcx> {
| PredicateKind::Clause(Clause::RegionOutlives(_))
| PredicateKind::Clause(Clause::TypeOutlives(_))
| PredicateKind::Clause(Clause::Projection(_))
+ | PredicateKind::Clause(Clause::ConstArgHasType(..))
+ | PredicateKind::AliasEq(..)
| PredicateKind::ObjectSafe(_)
| PredicateKind::ClosureKind(_, _, _)
| PredicateKind::Subtype(_)
@@ -595,6 +582,10 @@ pub enum Clause<'tcx> {
/// `where <T as TraitRef>::Name == X`, approximately.
/// See the `ProjectionPredicate` struct for details.
Projection(ProjectionPredicate<'tcx>),
+
+ /// Ensures that a const generic argument to a parameter `const N: u8`
+ /// is of type `u8`.
+ ConstArgHasType(Const<'tcx>, Ty<'tcx>),
}
#[derive(Clone, Copy, PartialEq, Eq, Hash, TyEncodable, TyDecodable)]
@@ -645,6 +636,12 @@ pub enum PredicateKind<'tcx> {
/// A marker predicate that is always ambiguous.
/// Used for coherence to mark opaque types as possibly equal to each other but ambiguous.
Ambiguous,
+
+ /// Separate from `Clause::Projection` which is used for normalization in new solver.
+ /// This predicate requires two terms to be equal to eachother.
+ ///
+ /// Only used for new solver
+ AliasEq(Term<'tcx>, Term<'tcx>),
}
/// The crate outlives map is computed during typeck and contains the
@@ -713,7 +710,7 @@ impl<'tcx> Predicate<'tcx> {
// The substitution from the input trait-ref is therefore going to be
// `'a => 'x` (where `'x` has a DB index of 1).
// - 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
+ // 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
// a DB index of 1, and thus we'll have `for<'x,'b> Bar1<'x,'b>`
@@ -756,7 +753,7 @@ impl<'tcx> Predicate<'tcx> {
let new = EarlyBinder(shifted_pred).subst(tcx, trait_ref.skip_binder().substs);
// 3) ['x] + ['b] -> ['x, 'b]
let bound_vars =
- tcx.mk_bound_variable_kinds(trait_bound_vars.iter().chain(pred_bound_vars));
+ tcx.mk_bound_variable_kinds_from_iter(trait_bound_vars.iter().chain(pred_bound_vars));
tcx.reuse_or_mk_predicate(self, ty::Binder::bind_with_vars(new, bound_vars))
}
}
@@ -917,14 +914,17 @@ impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for Term<'tcx> {
}
}
-impl<'tcx> TypeFoldable<'tcx> for Term<'tcx> {
- fn try_fold_with<F: FallibleTypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> {
+impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for Term<'tcx> {
+ fn try_fold_with<F: FallibleTypeFolder<TyCtxt<'tcx>>>(
+ self,
+ folder: &mut F,
+ ) -> Result<Self, F::Error> {
Ok(self.unpack().try_fold_with(folder)?.pack())
}
}
-impl<'tcx> TypeVisitable<'tcx> for Term<'tcx> {
- fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
+impl<'tcx> TypeVisitable<TyCtxt<'tcx>> for Term<'tcx> {
+ fn visit_with<V: TypeVisitor<TyCtxt<'tcx>>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
self.unpack().visit_with(visitor)
}
}
@@ -976,6 +976,33 @@ impl<'tcx> Term<'tcx> {
TermKind::Const(c) => c.into(),
}
}
+
+ /// This function returns `None` for `AliasKind::Opaque`.
+ ///
+ /// FIXME: rename `AliasTy` to `AliasTerm` and make sure we correctly
+ /// deal with constants.
+ pub fn to_alias_term_no_opaque(&self, tcx: TyCtxt<'tcx>) -> Option<AliasTy<'tcx>> {
+ match self.unpack() {
+ TermKind::Ty(ty) => match ty.kind() {
+ ty::Alias(kind, alias_ty) => match kind {
+ AliasKind::Projection => Some(*alias_ty),
+ AliasKind::Opaque => None,
+ },
+ _ => None,
+ },
+ TermKind::Const(ct) => match ct.kind() {
+ ConstKind::Unevaluated(uv) => Some(tcx.mk_alias_ty(uv.def.did, uv.substs)),
+ _ => None,
+ },
+ }
+ }
+
+ pub fn is_infer(&self) -> bool {
+ match self.unpack() {
+ TermKind::Ty(ty) => ty.is_ty_or_numeric_infer(),
+ TermKind::Const(ct) => ct.is_ct_infer(),
+ }
+ }
}
const TAG_MASK: usize = 0b11;
@@ -1165,6 +1192,8 @@ impl<'tcx> Predicate<'tcx> {
match predicate.skip_binder() {
PredicateKind::Clause(Clause::Trait(t)) => Some(predicate.rebind(t)),
PredicateKind::Clause(Clause::Projection(..))
+ | PredicateKind::Clause(Clause::ConstArgHasType(..))
+ | PredicateKind::AliasEq(..)
| PredicateKind::Subtype(..)
| PredicateKind::Coerce(..)
| PredicateKind::Clause(Clause::RegionOutlives(..))
@@ -1184,6 +1213,8 @@ impl<'tcx> Predicate<'tcx> {
match predicate.skip_binder() {
PredicateKind::Clause(Clause::Projection(t)) => Some(predicate.rebind(t)),
PredicateKind::Clause(Clause::Trait(..))
+ | PredicateKind::Clause(Clause::ConstArgHasType(..))
+ | PredicateKind::AliasEq(..)
| PredicateKind::Subtype(..)
| PredicateKind::Coerce(..)
| PredicateKind::Clause(Clause::RegionOutlives(..))
@@ -1203,7 +1234,9 @@ impl<'tcx> Predicate<'tcx> {
match predicate.skip_binder() {
PredicateKind::Clause(Clause::TypeOutlives(data)) => Some(predicate.rebind(data)),
PredicateKind::Clause(Clause::Trait(..))
+ | PredicateKind::Clause(Clause::ConstArgHasType(..))
| PredicateKind::Clause(Clause::Projection(..))
+ | PredicateKind::AliasEq(..)
| PredicateKind::Subtype(..)
| PredicateKind::Coerce(..)
| PredicateKind::Clause(Clause::RegionOutlives(..))
@@ -1322,7 +1355,7 @@ pub struct OpaqueHiddenType<'tcx> {
}
impl<'tcx> OpaqueHiddenType<'tcx> {
- pub fn report_mismatch(&self, other: &Self, tcx: TyCtxt<'tcx>) {
+ pub fn report_mismatch(&self, other: &Self, tcx: TyCtxt<'tcx>) -> ErrorGuaranteed {
// Found different concrete types for the opaque type.
let sub_diag = if self.span == other.span {
TypeMismatchReason::ConflictType { span: self.span }
@@ -1334,7 +1367,7 @@ impl<'tcx> OpaqueHiddenType<'tcx> {
other_ty: other.ty,
other_span: other.span,
sub: sub_diag,
- });
+ })
}
#[instrument(level = "debug", skip(tcx), ret)]
@@ -1382,7 +1415,7 @@ pub struct Placeholder<T> {
pub type PlaceholderRegion = Placeholder<BoundRegionKind>;
-pub type PlaceholderType = Placeholder<BoundVar>;
+pub type PlaceholderType = Placeholder<BoundTyKind>;
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, HashStable)]
#[derive(TyEncodable, TyDecodable, PartialOrd, Ord)]
@@ -1589,8 +1622,8 @@ impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for ParamEnv<'tcx> {
}
}
-impl<'tcx> TypeFoldable<'tcx> for ParamEnv<'tcx> {
- fn try_fold_with<F: ty::fold::FallibleTypeFolder<'tcx>>(
+impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for ParamEnv<'tcx> {
+ fn try_fold_with<F: ty::fold::FallibleTypeFolder<TyCtxt<'tcx>>>(
self,
folder: &mut F,
) -> Result<Self, F::Error> {
@@ -1602,8 +1635,8 @@ impl<'tcx> TypeFoldable<'tcx> for ParamEnv<'tcx> {
}
}
-impl<'tcx> TypeVisitable<'tcx> for ParamEnv<'tcx> {
- fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
+impl<'tcx> TypeVisitable<TyCtxt<'tcx>> for ParamEnv<'tcx> {
+ fn visit_with<V: TypeVisitor<TyCtxt<'tcx>>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
self.caller_bounds().visit_with(visitor)?;
self.reveal().visit_with(visitor)
}
@@ -1728,7 +1761,7 @@ impl<'tcx> ParamEnv<'tcx> {
/// `where Box<u32>: Copy`, which are clearly never
/// satisfiable. We generally want to behave as if they were true,
/// although the surrounding function is never reachable.
- pub fn and<T: TypeVisitable<'tcx>>(self, value: T) -> ParamEnvAnd<'tcx, T> {
+ pub fn and<T: TypeVisitable<TyCtxt<'tcx>>>(self, value: T) -> ParamEnvAnd<'tcx, T> {
match self.reveal() {
Reveal::UserFacing => ParamEnvAnd { param_env: self, value },
@@ -1986,7 +2019,7 @@ impl<'tcx> FieldDef {
/// Returns the type of this field. The resulting type is not normalized. The `subst` is
/// typically obtained via the second field of [`TyKind::Adt`].
pub fn ty(&self, tcx: TyCtxt<'tcx>, subst: SubstsRef<'tcx>) -> Ty<'tcx> {
- tcx.bound_type_of(self.did).subst(tcx, subst)
+ tcx.type_of(self.did).subst(tcx, subst)
}
/// Computes the `Ident` of this variant by looking up the `Span`
@@ -2038,6 +2071,12 @@ pub enum ImplOverlapKind {
Issue33140,
}
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, TyEncodable, TyDecodable, HashStable)]
+pub enum ImplTraitInTraitData {
+ Trait { fn_def_id: DefId, opaque_def_id: DefId },
+ Impl { fn_def_id: DefId },
+}
+
impl<'tcx> TyCtxt<'tcx> {
pub fn typeck_body(self, body: hir::BodyId) -> &'tcx TypeckResults<'tcx> {
self.typeck(self.hir().body_owner_def_id(body))
@@ -2167,7 +2206,7 @@ impl<'tcx> TyCtxt<'tcx> {
Some(Ident::new(def, span))
}
- pub fn opt_associated_item(self, def_id: DefId) -> Option<&'tcx AssocItem> {
+ pub fn opt_associated_item(self, def_id: DefId) -> Option<AssocItem> {
if let DefKind::AssocConst | DefKind::AssocFn | DefKind::AssocTy = self.def_kind(def_id) {
Some(self.associated_item(def_id))
} else {
@@ -2357,15 +2396,17 @@ impl<'tcx> TyCtxt<'tcx> {
self.trait_def(trait_def_id).has_auto_impl
}
+ /// Returns `true` if this is coinductive, either because it is
+ /// an auto trait or because it has the `#[rustc_coinductive]` attribute.
+ pub fn trait_is_coinductive(self, trait_def_id: DefId) -> bool {
+ self.trait_def(trait_def_id).is_coinductive
+ }
+
/// Returns `true` if this is a trait alias.
pub fn trait_is_alias(self, trait_def_id: DefId) -> bool {
self.def_kind(trait_def_id) == DefKind::TraitAlias
}
- pub fn trait_is_coinductive(self, trait_def_id: DefId) -> bool {
- self.trait_is_auto(trait_def_id) || self.lang_items().sized_trait() == Some(trait_def_id)
- }
-
/// Returns layout of a generator. Layout might be unavailable if the
/// generator is tainted by errors.
pub fn generator_layout(self, def_id: DefId) -> Option<&'tcx GeneratorLayout<'tcx>> {
@@ -2396,15 +2437,30 @@ impl<'tcx> TyCtxt<'tcx> {
pub fn impl_of_method(self, def_id: DefId) -> Option<DefId> {
if let DefKind::AssocConst | DefKind::AssocFn | DefKind::AssocTy = self.def_kind(def_id) {
let parent = self.parent(def_id);
- if let DefKind::Impl = self.def_kind(parent) {
+ if let DefKind::Impl { .. } = self.def_kind(parent) {
return Some(parent);
}
}
None
}
- /// If the given `DefId` belongs to a trait that was automatically derived, returns `true`.
- pub fn is_builtin_derive(self, def_id: DefId) -> bool {
+ /// Check if the given `DefId` is `#\[automatically_derived\]`, *and*
+ /// whether it was produced by expanding a builtin derive macro.
+ pub fn is_builtin_derived(self, def_id: DefId) -> bool {
+ if self.is_automatically_derived(def_id)
+ && let Some(def_id) = def_id.as_local()
+ && let outer = self.def_span(def_id).ctxt().outer_expn_data()
+ && matches!(outer.kind, ExpnKind::Macro(MacroKind::Derive, _))
+ && self.has_attr(outer.macro_def_id.unwrap(), sym::rustc_builtin_macro)
+ {
+ true
+ } else {
+ false
+ }
+ }
+
+ /// Check if the given `DefId` is `#\[automatically_derived\]`.
+ pub fn is_automatically_derived(self, def_id: DefId) -> bool {
self.has_attr(def_id, sym::automatically_derived)
}
@@ -2437,6 +2493,7 @@ impl<'tcx> TyCtxt<'tcx> {
ident
}
+ // FIXME(vincenzoapalzzo): move the HirId to a LocalDefId
pub fn adjust_ident_and_get_scope(
self,
mut ident: Ident,
@@ -2470,10 +2527,6 @@ impl<'tcx> TyCtxt<'tcx> {
}
}
- pub fn is_object_safe(self, key: DefId) -> bool {
- self.object_safety_violations(key).is_empty()
- }
-
#[inline]
pub fn is_const_fn_raw(self, def_id: DefId) -> bool {
matches!(
@@ -2494,6 +2547,34 @@ impl<'tcx> TyCtxt<'tcx> {
}
def_id
}
+
+ pub fn impl_method_has_trait_impl_trait_tys(self, def_id: DefId) -> bool {
+ if self.def_kind(def_id) != DefKind::AssocFn {
+ return false;
+ }
+
+ let Some(item) = self.opt_associated_item(def_id) else { return false; };
+ if item.container != ty::AssocItemContainer::ImplContainer {
+ return false;
+ }
+
+ let Some(trait_item_def_id) = item.trait_item_def_id else { return false; };
+
+ // FIXME(RPITIT): This does a somewhat manual walk through the signature
+ // of the trait fn to look for any RPITITs, but that's kinda doing a lot
+ // of work. We can probably remove this when we refactor RPITITs to be
+ // associated types.
+ self.fn_sig(trait_item_def_id).subst_identity().skip_binder().output().walk().any(|arg| {
+ if let ty::GenericArgKind::Type(ty) = arg.unpack()
+ && let ty::Alias(ty::Projection, data) = ty.kind()
+ && self.def_kind(data.def_id) == DefKind::ImplTraitPlaceholder
+ {
+ true
+ } else {
+ false
+ }
+ })
+ }
}
/// Yields the parent function's `LocalDefId` if `def_id` is an `impl Trait` definition.
@@ -2619,7 +2700,7 @@ impl<'tcx> fmt::Debug for SymbolName<'tcx> {
}
#[derive(Debug, Default, Copy, Clone)]
-pub struct FoundRelationships {
+pub struct InferVarInfo {
/// This is true if we identified that this Ty (`?T`) is found in a `?T: Foo`
/// obligation, where:
///
diff --git a/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs b/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs
index ee13920d5..7c59879a1 100644
--- a/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs
+++ b/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs
@@ -7,16 +7,14 @@
//! `normalize_generic_arg_after_erasing_regions` query for each type
//! or constant found within. (This underlying query is what is cached.)
-use crate::mir;
use crate::traits::query::NoSolution;
use crate::ty::fold::{FallibleTypeFolder, TypeFoldable, TypeFolder};
-use crate::ty::{self, EarlyBinder, SubstsRef, Ty, TyCtxt};
+use crate::ty::{self, EarlyBinder, SubstsRef, Ty, TyCtxt, TypeVisitableExt};
#[derive(Debug, Copy, Clone, HashStable, TyEncodable, TyDecodable)]
pub enum NormalizationError<'tcx> {
Type(Ty<'tcx>),
Const(ty::Const<'tcx>),
- ConstantKind(mir::ConstantKind<'tcx>),
}
impl<'tcx> NormalizationError<'tcx> {
@@ -24,7 +22,6 @@ impl<'tcx> NormalizationError<'tcx> {
match self {
NormalizationError::Type(t) => format!("{}", t),
NormalizationError::Const(c) => format!("{}", c),
- NormalizationError::ConstantKind(ck) => format!("{}", ck),
}
}
}
@@ -38,7 +35,7 @@ impl<'tcx> TyCtxt<'tcx> {
#[tracing::instrument(level = "debug", skip(self, param_env))]
pub fn normalize_erasing_regions<T>(self, param_env: ty::ParamEnv<'tcx>, value: T) -> T
where
- T: TypeFoldable<'tcx>,
+ T: TypeFoldable<TyCtxt<'tcx>>,
{
debug!(
"normalize_erasing_regions::<{}>(value={:?}, param_env={:?})",
@@ -70,7 +67,7 @@ impl<'tcx> TyCtxt<'tcx> {
value: T,
) -> Result<T, NormalizationError<'tcx>>
where
- T: TypeFoldable<'tcx>,
+ T: TypeFoldable<TyCtxt<'tcx>>,
{
debug!(
"try_normalize_erasing_regions::<{}>(value={:?}, param_env={:?})",
@@ -107,7 +104,7 @@ impl<'tcx> TyCtxt<'tcx> {
value: ty::Binder<'tcx, T>,
) -> T
where
- T: TypeFoldable<'tcx>,
+ T: TypeFoldable<TyCtxt<'tcx>>,
{
let value = self.erase_late_bound_regions(value);
self.normalize_erasing_regions(param_env, value)
@@ -127,7 +124,7 @@ impl<'tcx> TyCtxt<'tcx> {
value: ty::Binder<'tcx, T>,
) -> Result<T, NormalizationError<'tcx>>
where
- T: TypeFoldable<'tcx>,
+ T: TypeFoldable<TyCtxt<'tcx>>,
{
let value = self.erase_late_bound_regions(value);
self.try_normalize_erasing_regions(param_env, value)
@@ -145,7 +142,7 @@ impl<'tcx> TyCtxt<'tcx> {
value: T,
) -> T
where
- T: TypeFoldable<'tcx>,
+ T: TypeFoldable<TyCtxt<'tcx>>,
{
debug!(
"subst_and_normalize_erasing_regions(\
@@ -169,7 +166,7 @@ impl<'tcx> TyCtxt<'tcx> {
value: T,
) -> Result<T, NormalizationError<'tcx>>
where
- T: TypeFoldable<'tcx>,
+ T: TypeFoldable<TyCtxt<'tcx>>,
{
debug!(
"subst_and_normalize_erasing_regions(\
@@ -196,14 +193,14 @@ impl<'tcx> NormalizeAfterErasingRegionsFolder<'tcx> {
let arg = self.param_env.and(arg);
self.tcx.try_normalize_generic_arg_after_erasing_regions(arg).unwrap_or_else(|_| bug!(
- "Failed to normalize {:?}, maybe try to call `try_normalize_erasing_regions` instead",
- arg.value
- ))
+ "Failed to normalize {:?}, maybe try to call `try_normalize_erasing_regions` instead",
+ arg.value
+ ))
}
}
-impl<'tcx> TypeFolder<'tcx> for NormalizeAfterErasingRegionsFolder<'tcx> {
- fn tcx(&self) -> TyCtxt<'tcx> {
+impl<'tcx> TypeFolder<TyCtxt<'tcx>> for NormalizeAfterErasingRegionsFolder<'tcx> {
+ fn interner(&self) -> TyCtxt<'tcx> {
self.tcx
}
@@ -238,10 +235,10 @@ impl<'tcx> TryNormalizeAfterErasingRegionsFolder<'tcx> {
}
}
-impl<'tcx> FallibleTypeFolder<'tcx> for TryNormalizeAfterErasingRegionsFolder<'tcx> {
+impl<'tcx> FallibleTypeFolder<TyCtxt<'tcx>> for TryNormalizeAfterErasingRegionsFolder<'tcx> {
type Error = NormalizationError<'tcx>;
- fn tcx(&self) -> TyCtxt<'tcx> {
+ fn interner(&self) -> TyCtxt<'tcx> {
self.tcx
}
diff --git a/compiler/rustc_middle/src/ty/opaque_types.rs b/compiler/rustc_middle/src/ty/opaque_types.rs
index 98cd92007..751f3066c 100644
--- a/compiler/rustc_middle/src/ty/opaque_types.rs
+++ b/compiler/rustc_middle/src/ty/opaque_types.rs
@@ -3,6 +3,7 @@ use crate::ty::fold::{TypeFolder, TypeSuperFoldable};
use crate::ty::subst::{GenericArg, GenericArgKind};
use crate::ty::{self, Ty, TyCtxt, TypeFoldable};
use rustc_data_structures::fx::FxHashMap;
+use rustc_span::def_id::DefId;
use rustc_span::Span;
/// Converts generic params of a TypeFoldable from one
@@ -47,10 +48,51 @@ impl<'tcx> ReverseMapper<'tcx> {
assert!(!self.do_not_error);
kind.fold_with(self)
}
+
+ fn fold_closure_substs(
+ &mut self,
+ def_id: DefId,
+ substs: ty::SubstsRef<'tcx>,
+ ) -> ty::SubstsRef<'tcx> {
+ // I am a horrible monster and I pray for death. When
+ // we encounter a closure here, it is always a closure
+ // from within the function that we are currently
+ // type-checking -- one that is now being encapsulated
+ // in an opaque type. Ideally, we would
+ // go through the types/lifetimes that it references
+ // and treat them just like we would any other type,
+ // which means we would error out if we find any
+ // reference to a type/region that is not in the
+ // "reverse map".
+ //
+ // **However,** in the case of closures, there is a
+ // somewhat subtle (read: hacky) consideration. The
+ // problem is that our closure types currently include
+ // all the lifetime parameters declared on the
+ // enclosing function, even if they are unused by the
+ // closure itself. We can't readily filter them out,
+ // so here we replace those values with `'empty`. This
+ // can't really make a difference to the rest of the
+ // compiler; those regions are ignored for the
+ // outlives relation, and hence don't affect trait
+ // selection or auto traits, and they are erased
+ // during codegen.
+
+ let generics = self.tcx.generics_of(def_id);
+ self.tcx.mk_substs_from_iter(substs.iter().enumerate().map(|(index, kind)| {
+ if index < generics.parent_count {
+ // Accommodate missing regions in the parent kinds...
+ self.fold_kind_no_missing_regions_error(kind)
+ } else {
+ // ...but not elsewhere.
+ self.fold_kind_normally(kind)
+ }
+ }))
+ }
}
-impl<'tcx> TypeFolder<'tcx> for ReverseMapper<'tcx> {
- fn tcx(&self) -> TyCtxt<'tcx> {
+impl<'tcx> TypeFolder<TyCtxt<'tcx>> for ReverseMapper<'tcx> {
+ fn interner(&self) -> TyCtxt<'tcx> {
self.tcx
}
@@ -67,6 +109,8 @@ impl<'tcx> TypeFolder<'tcx> for ReverseMapper<'tcx> {
// them.
ty::ReErased => return r,
+ ty::ReError(_) => return r,
+
// The regions that we expect from borrow checking.
ty::ReEarlyBound(_) | ty::ReFree(_) => {}
@@ -83,20 +127,21 @@ impl<'tcx> TypeFolder<'tcx> for ReverseMapper<'tcx> {
Some(u) => panic!("region mapped to unexpected kind: {:?}", u),
None if self.do_not_error => self.tcx.lifetimes.re_static,
None => {
- self.tcx
+ let e = self
+ .tcx
.sess
.struct_span_err(self.span, "non-defining opaque type use in defining scope")
.span_label(
self.span,
format!(
"lifetime `{}` is part of concrete type but not used in \
- parameter list of the `impl Trait` type alias",
+ parameter list of the `impl Trait` type alias",
r
),
)
.emit();
- self.tcx().lifetimes.re_static
+ self.interner().mk_re_error(e)
}
}
}
@@ -104,59 +149,20 @@ impl<'tcx> TypeFolder<'tcx> for ReverseMapper<'tcx> {
fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
match *ty.kind() {
ty::Closure(def_id, substs) => {
- // I am a horrible monster and I pray for death. When
- // we encounter a closure here, it is always a closure
- // from within the function that we are currently
- // type-checking -- one that is now being encapsulated
- // in an opaque type. Ideally, we would
- // go through the types/lifetimes that it references
- // and treat them just like we would any other type,
- // which means we would error out if we find any
- // reference to a type/region that is not in the
- // "reverse map".
- //
- // **However,** in the case of closures, there is a
- // somewhat subtle (read: hacky) consideration. The
- // problem is that our closure types currently include
- // all the lifetime parameters declared on the
- // enclosing function, even if they are unused by the
- // closure itself. We can't readily filter them out,
- // so here we replace those values with `'empty`. This
- // can't really make a difference to the rest of the
- // compiler; those regions are ignored for the
- // outlives relation, and hence don't affect trait
- // selection or auto traits, and they are erased
- // during codegen.
-
- let generics = self.tcx.generics_of(def_id);
- let substs = self.tcx.mk_substs(substs.iter().enumerate().map(|(index, kind)| {
- if index < generics.parent_count {
- // Accommodate missing regions in the parent kinds...
- self.fold_kind_no_missing_regions_error(kind)
- } else {
- // ...but not elsewhere.
- self.fold_kind_normally(kind)
- }
- }));
-
+ let substs = self.fold_closure_substs(def_id, substs);
self.tcx.mk_closure(def_id, substs)
}
ty::Generator(def_id, substs, movability) => {
- let generics = self.tcx.generics_of(def_id);
- let substs = self.tcx.mk_substs(substs.iter().enumerate().map(|(index, kind)| {
- if index < generics.parent_count {
- // Accommodate missing regions in the parent kinds...
- self.fold_kind_no_missing_regions_error(kind)
- } else {
- // ...but not elsewhere.
- self.fold_kind_normally(kind)
- }
- }));
-
+ let substs = self.fold_closure_substs(def_id, substs);
self.tcx.mk_generator(def_id, substs, movability)
}
+ ty::GeneratorWitnessMIR(def_id, substs) => {
+ let substs = self.fold_closure_substs(def_id, substs);
+ self.tcx.mk_generator_witness_mir(def_id, substs)
+ }
+
ty::Param(param) => {
// Look it up in the substitution list.
match self.map.get(&ty.into()).map(|k| k.unpack()) {
@@ -180,7 +186,7 @@ impl<'tcx> TypeFolder<'tcx> for ReverseMapper<'tcx> {
.emit();
}
- self.tcx().ty_error()
+ self.interner().ty_error_misc()
}
}
}
@@ -208,7 +214,7 @@ impl<'tcx> TypeFolder<'tcx> for ReverseMapper<'tcx> {
});
}
- self.tcx().const_error(ct.ty())
+ self.interner().const_error(ct.ty())
}
}
}
diff --git a/compiler/rustc_middle/src/ty/parameterized.rs b/compiler/rustc_middle/src/ty/parameterized.rs
index 24f3d1acf..8849e7eab 100644
--- a/compiler/rustc_middle/src/ty/parameterized.rs
+++ b/compiler/rustc_middle/src/ty/parameterized.rs
@@ -57,7 +57,7 @@ trivially_parameterized_over_tcx! {
crate::metadata::ModChild,
crate::middle::codegen_fn_attrs::CodegenFnAttrs,
crate::middle::exported_symbols::SymbolExportInfo,
- crate::middle::resolve_lifetime::ObjectLifetimeDefault,
+ crate::middle::resolve_bound_vars::ObjectLifetimeDefault,
crate::mir::ConstQualifs,
ty::AssocItemContainer,
ty::DeducedParamAttrs,
@@ -81,6 +81,8 @@ trivially_parameterized_over_tcx! {
rustc_hir::IsAsync,
rustc_hir::LangItem,
rustc_hir::def::DefKind,
+ rustc_hir::def::DocLinkResMap,
+ rustc_hir::def_id::DefId,
rustc_hir::def_id::DefIndex,
rustc_hir::definitions::DefKey,
rustc_index::bit_set::BitSet<u32>,
@@ -117,6 +119,7 @@ macro_rules! parameterized_over_tcx {
parameterized_over_tcx! {
crate::middle::exported_symbols::ExportedSymbol,
crate::mir::Body,
+ crate::mir::GeneratorLayout,
ty::Ty,
ty::FnSig,
ty::GenericPredicates,
diff --git a/compiler/rustc_middle/src/ty/print/mod.rs b/compiler/rustc_middle/src/ty/print/mod.rs
index c302c4611..021c20b58 100644
--- a/compiler/rustc_middle/src/ty/print/mod.rs
+++ b/compiler/rustc_middle/src/ty/print/mod.rs
@@ -115,7 +115,7 @@ pub trait Printer<'tcx>: Sized {
DefPathData::Impl => {
let generics = self.tcx().generics_of(def_id);
- let self_ty = self.tcx().bound_type_of(def_id);
+ let self_ty = self.tcx().type_of(def_id);
let impl_trait_ref = self.tcx().impl_trait_ref(def_id);
let (self_ty, impl_trait_ref) = if substs.len() >= generics.count() {
(
@@ -265,6 +265,7 @@ fn characteristic_def_id_of_type_cached<'a>(
ty::FnDef(def_id, _)
| ty::Closure(def_id, _)
| ty::Generator(def_id, _, _)
+ | ty::GeneratorWitnessMIR(def_id, _)
| ty::Foreign(def_id) => Some(def_id),
ty::Bool
diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs
index ae7c20fff..6a053c368 100644
--- a/compiler/rustc_middle/src/ty/print/pretty.rs
+++ b/compiler/rustc_middle/src/ty/print/pretty.rs
@@ -1,7 +1,7 @@
use crate::mir::interpret::{AllocRange, GlobalAlloc, Pointer, Provenance, Scalar};
use crate::ty::{
self, ConstInt, DefIdTree, ParamConst, ScalarInt, Term, TermKind, Ty, TyCtxt, TypeFoldable,
- TypeSuperFoldable, TypeSuperVisitable, TypeVisitable,
+ TypeSuperFoldable, TypeSuperVisitable, TypeVisitable, TypeVisitableExt,
};
use crate::ty::{GenericArg, GenericArgKind};
use rustc_apfloat::ieee::{Double, Single};
@@ -22,7 +22,6 @@ use rustc_target::spec::abi::Abi;
use smallvec::SmallVec;
use std::cell::Cell;
-use std::char;
use std::collections::BTreeMap;
use std::fmt::{self, Write as _};
use std::iter;
@@ -183,7 +182,7 @@ impl<'tcx> RegionHighlightMode<'tcx> {
/// Convenience wrapper for `highlighting_region`.
pub fn highlighting_region_vid(&mut self, vid: ty::RegionVid, number: usize) {
- self.highlighting_region(self.tcx.mk_region(ty::ReVar(vid)), number)
+ self.highlighting_region(self.tcx.mk_re_var(vid), number)
}
/// Returns `Some(n)` with the number to use for the given region, if any.
@@ -226,7 +225,7 @@ pub trait PrettyPrinter<'tcx>:
fn in_binder<T>(self, value: &ty::Binder<'tcx, T>) -> Result<Self, Self::Error>
where
- T: Print<'tcx, Self, Output = Self, Error = Self::Error> + TypeFoldable<'tcx>,
+ T: Print<'tcx, Self, Output = Self, Error = Self::Error> + TypeFoldable<TyCtxt<'tcx>>,
{
value.as_ref().skip_binder().print(self)
}
@@ -237,7 +236,7 @@ pub trait PrettyPrinter<'tcx>:
f: F,
) -> Result<Self, Self::Error>
where
- T: Print<'tcx, Self, Output = Self, Error = Self::Error> + TypeFoldable<'tcx>,
+ T: Print<'tcx, Self, Output = Self, Error = Self::Error> + TypeFoldable<TyCtxt<'tcx>>,
{
f(value.as_ref().skip_binder(), self)
}
@@ -675,8 +674,12 @@ pub trait PrettyPrinter<'tcx>:
p!(")")
}
ty::FnDef(def_id, substs) => {
- let sig = self.tcx().bound_fn_sig(def_id).subst(self.tcx(), substs);
- p!(print(sig), " {{", print_value_path(def_id, substs), "}}");
+ if NO_QUERIES.with(|q| q.get()) {
+ p!(print_def_path(def_id, substs));
+ } else {
+ let sig = self.tcx().fn_sig(def_id).subst(self.tcx(), substs);
+ p!(print(sig), " {{", print_value_path(def_id, substs), "}}");
+ }
}
ty::FnPtr(ref bare_fn) => p!(print(bare_fn)),
ty::Infer(infer_ty) => {
@@ -698,8 +701,10 @@ pub trait PrettyPrinter<'tcx>:
ty::Error(_) => p!("[type error]"),
ty::Param(ref param_ty) => p!(print(param_ty)),
ty::Bound(debruijn, bound_ty) => match bound_ty.kind {
- ty::BoundTyKind::Anon => self.pretty_print_bound_var(debruijn, bound_ty.var)?,
- ty::BoundTyKind::Param(p) => p!(write("{}", p)),
+ ty::BoundTyKind::Anon(bv) => {
+ self.pretty_print_bound_var(debruijn, ty::BoundVar::from_u32(bv))?
+ }
+ ty::BoundTyKind::Param(_, s) => p!(write("{}", s)),
},
ty::Adt(def, substs) => {
p!(print_def_path(def.did(), substs));
@@ -730,15 +735,18 @@ pub trait PrettyPrinter<'tcx>:
p!(print(data))
}
}
- ty::Placeholder(placeholder) => p!(write("Placeholder({:?})", placeholder)),
+ ty::Placeholder(placeholder) => match placeholder.name {
+ ty::BoundTyKind::Anon(_) => p!(write("Placeholder({:?})", placeholder)),
+ ty::BoundTyKind::Param(_, name) => p!(write("{}", name)),
+ },
ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. }) => {
- // FIXME(eddyb) print this with `print_def_path`.
// We use verbose printing in 'NO_QUERIES' mode, to
// avoid needing to call `predicates_of`. This should
// only affect certain debug messages (e.g. messages printed
// from `rustc_middle::ty` during the computation of `tcx.predicates_of`),
// and should have no effect on any compiler output.
- if self.should_print_verbose() || NO_QUERIES.with(|q| q.get()) {
+ if self.should_print_verbose() {
+ // FIXME(eddyb) print this with `print_def_path`.
p!(write("Opaque({:?}, {:?})", def_id, substs));
return Ok(self);
}
@@ -746,8 +754,10 @@ pub trait PrettyPrinter<'tcx>:
let parent = self.tcx().parent(def_id);
match self.tcx().def_kind(parent) {
DefKind::TyAlias | DefKind::AssocTy => {
+ // NOTE: I know we should check for NO_QUERIES here, but it's alright.
+ // `type_of` on a type alias or assoc type should never cause a cycle.
if let ty::Alias(ty::Opaque, ty::AliasTy { def_id: d, .. }) =
- *self.tcx().type_of(parent).kind()
+ *self.tcx().type_of(parent).subst_identity().kind()
{
if d == def_id {
// If the type alias directly starts with the `impl` of the
@@ -760,7 +770,14 @@ pub trait PrettyPrinter<'tcx>:
p!(print_def_path(def_id, substs));
return Ok(self);
}
- _ => return self.pretty_print_opaque_impl_type(def_id, substs),
+ _ => {
+ if NO_QUERIES.with(|q| q.get()) {
+ p!(print_def_path(def_id, &[]));
+ return Ok(self);
+ } else {
+ return self.pretty_print_opaque_impl_type(def_id, substs);
+ }
+ }
}
}
ty::Str => p!("str"),
@@ -811,6 +828,28 @@ pub trait PrettyPrinter<'tcx>:
ty::GeneratorWitness(types) => {
p!(in_binder(&types));
}
+ ty::GeneratorWitnessMIR(did, substs) => {
+ p!(write("["));
+ if !self.tcx().sess.verbose() {
+ p!("generator witness");
+ // FIXME(eddyb) should use `def_span`.
+ if let Some(did) = did.as_local() {
+ let span = self.tcx().def_span(did);
+ p!(write(
+ "@{}",
+ // This may end up in stderr diagnostics but it may also be emitted
+ // into MIR. Hence we use the remapped path if available
+ self.tcx().sess.source_map().span_to_embeddable_string(span)
+ ));
+ } else {
+ p!(write("@"), print_def_path(did, substs));
+ }
+ } else {
+ p!(print_def_path(did, substs));
+ }
+
+ p!("]")
+ }
ty::Closure(did, substs) => {
p!(write("["));
if !self.should_print_verbose() {
@@ -1062,9 +1101,11 @@ pub trait PrettyPrinter<'tcx>:
write!(self, "Sized")?;
}
- for re in lifetimes {
- write!(self, " + ")?;
- self = self.print_region(re)?;
+ if !FORCE_TRIMMED_PATH.with(|flag| flag.get()) {
+ for re in lifetimes {
+ write!(self, " + ")?;
+ self = self.print_region(re)?;
+ }
}
Ok(self)
@@ -1171,7 +1212,7 @@ pub trait PrettyPrinter<'tcx>:
// in order to place the projections inside the `<...>`.
if !resugared {
// Use a type that can't appear in defaults of type parameters.
- let dummy_cx = cx.tcx().mk_ty_infer(ty::FreshTy(0));
+ let dummy_cx = cx.tcx().mk_fresh_ty(0);
let principal = principal.with_self_ty(cx.tcx(), dummy_cx);
let args = cx
@@ -1992,7 +2033,7 @@ impl<'tcx> PrettyPrinter<'tcx> for FmtPrinter<'_, 'tcx> {
fn in_binder<T>(self, value: &ty::Binder<'tcx, T>) -> Result<Self, Self::Error>
where
- T: Print<'tcx, Self, Output = Self, Error = Self::Error> + TypeFoldable<'tcx>,
+ T: Print<'tcx, Self, Output = Self, Error = Self::Error> + TypeFoldable<TyCtxt<'tcx>>,
{
self.pretty_in_binder(value)
}
@@ -2003,7 +2044,7 @@ impl<'tcx> PrettyPrinter<'tcx> for FmtPrinter<'_, 'tcx> {
f: C,
) -> Result<Self, Self::Error>
where
- T: Print<'tcx, Self, Output = Self, Error = Self::Error> + TypeFoldable<'tcx>,
+ T: Print<'tcx, Self, Output = Self, Error = Self::Error> + TypeFoldable<TyCtxt<'tcx>>,
{
self.pretty_wrap_binder(value, f)
}
@@ -2048,6 +2089,10 @@ impl<'tcx> PrettyPrinter<'tcx> for FmtPrinter<'_, 'tcx> {
return true;
}
+ if FORCE_TRIMMED_PATH.with(|flag| flag.get()) {
+ return false;
+ }
+
let identify_regions = self.tcx.sess.opts.unstable_opts.identify_regions;
match *region {
@@ -2071,7 +2116,7 @@ impl<'tcx> PrettyPrinter<'tcx> for FmtPrinter<'_, 'tcx> {
ty::ReVar(_) if identify_regions => true,
- ty::ReVar(_) | ty::ReErased => false,
+ ty::ReVar(_) | ty::ReErased | ty::ReError(_) => false,
ty::ReStatic => true,
}
@@ -2151,6 +2196,7 @@ impl<'tcx> FmtPrinter<'_, 'tcx> {
}
ty::ReVar(_) => {}
ty::ReErased => {}
+ ty::ReError(_) => {}
ty::ReStatic => {
p!("'static");
return Ok(self);
@@ -2178,12 +2224,12 @@ struct RegionFolder<'a, 'tcx> {
),
}
-impl<'a, 'tcx> ty::TypeFolder<'tcx> for RegionFolder<'a, 'tcx> {
- fn tcx<'b>(&'b self) -> TyCtxt<'tcx> {
+impl<'a, 'tcx> ty::TypeFolder<TyCtxt<'tcx>> for RegionFolder<'a, 'tcx> {
+ fn interner(&self) -> TyCtxt<'tcx> {
self.tcx
}
- fn fold_binder<T: TypeFoldable<'tcx>>(
+ fn fold_binder<T: TypeFoldable<TyCtxt<'tcx>>>(
&mut self,
t: ty::Binder<'tcx, T>,
) -> ty::Binder<'tcx, T> {
@@ -2228,7 +2274,7 @@ impl<'a, 'tcx> ty::TypeFolder<'tcx> for RegionFolder<'a, 'tcx> {
};
if let ty::ReLateBound(debruijn1, br) = *region {
assert_eq!(debruijn1, ty::INNERMOST);
- self.tcx.mk_region(ty::ReLateBound(self.current_index, br))
+ self.tcx.mk_re_late_bound(self.current_index, br)
} else {
region
}
@@ -2243,7 +2289,7 @@ impl<'tcx> FmtPrinter<'_, 'tcx> {
value: &ty::Binder<'tcx, T>,
) -> Result<(Self, T, BTreeMap<ty::BoundRegion, ty::Region<'tcx>>), fmt::Error>
where
- T: Print<'tcx, Self, Output = Self, Error = fmt::Error> + TypeFoldable<'tcx>,
+ T: Print<'tcx, Self, Output = Self, Error = fmt::Error> + TypeFoldable<TyCtxt<'tcx>>,
{
fn name_by_region_index(
index: usize,
@@ -2324,6 +2370,7 @@ impl<'tcx> FmtPrinter<'_, 'tcx> {
} else {
let tcx = self.tcx;
+ let trim_path = FORCE_TRIMMED_PATH.with(|flag| flag.get());
// Closure used in `RegionFolder` to create names for anonymous late-bound
// regions. We use two `DebruijnIndex`es (one for the currently folded
// late-bound region and the other for the binder level) to determine
@@ -2339,10 +2386,10 @@ impl<'tcx> FmtPrinter<'_, 'tcx> {
if let Some(lt_idx) = lifetime_idx {
if lt_idx > binder_level_idx {
let kind = ty::BrNamed(CRATE_DEF_ID.to_def_id(), name);
- return tcx.mk_region(ty::ReLateBound(
+ return tcx.mk_re_late_bound(
ty::INNERMOST,
ty::BoundRegion { var: br.var, kind },
- ));
+ );
}
}
@@ -2354,10 +2401,10 @@ impl<'tcx> FmtPrinter<'_, 'tcx> {
if let Some(lt_idx) = lifetime_idx {
if lt_idx > binder_level_idx {
let kind = ty::BrNamed(def_id, name);
- return tcx.mk_region(ty::ReLateBound(
+ return tcx.mk_re_late_bound(
ty::INNERMOST,
ty::BoundRegion { var: br.var, kind },
- ));
+ );
}
}
@@ -2367,10 +2414,10 @@ impl<'tcx> FmtPrinter<'_, 'tcx> {
if let Some(lt_idx) = lifetime_idx {
if lt_idx > binder_level_idx {
let kind = br.kind;
- return tcx.mk_region(ty::ReLateBound(
+ return tcx.mk_re_late_bound(
ty::INNERMOST,
ty::BoundRegion { var: br.var, kind },
- ));
+ );
}
}
@@ -2378,9 +2425,11 @@ impl<'tcx> FmtPrinter<'_, 'tcx> {
}
};
- start_or_continue(&mut self, "for<", ", ");
- do_continue(&mut self, name);
- tcx.mk_region(ty::ReLateBound(ty::INNERMOST, ty::BoundRegion { var: br.var, kind }))
+ if !trim_path {
+ start_or_continue(&mut self, "for<", ", ");
+ do_continue(&mut self, name);
+ }
+ tcx.mk_re_late_bound(ty::INNERMOST, ty::BoundRegion { var: br.var, kind })
};
let mut folder = RegionFolder {
tcx,
@@ -2390,7 +2439,9 @@ impl<'tcx> FmtPrinter<'_, 'tcx> {
};
let new_value = value.clone().skip_binder().fold_with(&mut folder);
let region_map = folder.region_map;
- start_or_continue(&mut self, "", "> ");
+ if !trim_path {
+ start_or_continue(&mut self, "", "> ");
+ }
(new_value, region_map)
};
@@ -2401,7 +2452,7 @@ impl<'tcx> FmtPrinter<'_, 'tcx> {
pub fn pretty_in_binder<T>(self, value: &ty::Binder<'tcx, T>) -> Result<Self, fmt::Error>
where
- T: Print<'tcx, Self, Output = Self, Error = fmt::Error> + TypeFoldable<'tcx>,
+ T: Print<'tcx, Self, Output = Self, Error = fmt::Error> + TypeFoldable<TyCtxt<'tcx>>,
{
let old_region_index = self.region_index;
let (new, new_value, _) = self.name_all_regions(value)?;
@@ -2417,7 +2468,7 @@ impl<'tcx> FmtPrinter<'_, 'tcx> {
f: C,
) -> Result<Self, fmt::Error>
where
- T: Print<'tcx, Self, Output = Self, Error = fmt::Error> + TypeFoldable<'tcx>,
+ T: Print<'tcx, Self, Output = Self, Error = fmt::Error> + TypeFoldable<TyCtxt<'tcx>>,
{
let old_region_index = self.region_index;
let (new, new_value, _) = self.name_all_regions(value)?;
@@ -2429,7 +2480,7 @@ impl<'tcx> FmtPrinter<'_, 'tcx> {
fn prepare_region_info<T>(&mut self, value: &ty::Binder<'tcx, T>)
where
- T: TypeVisitable<'tcx>,
+ T: TypeVisitable<TyCtxt<'tcx>>,
{
struct RegionNameCollector<'tcx> {
used_region_names: FxHashSet<Symbol>,
@@ -2445,7 +2496,7 @@ impl<'tcx> FmtPrinter<'_, 'tcx> {
}
}
- impl<'tcx> ty::visit::TypeVisitor<'tcx> for RegionNameCollector<'tcx> {
+ impl<'tcx> ty::visit::TypeVisitor<TyCtxt<'tcx>> for RegionNameCollector<'tcx> {
type BreakTy = ();
fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> {
@@ -2482,7 +2533,7 @@ impl<'tcx> FmtPrinter<'_, 'tcx> {
impl<'tcx, T, P: PrettyPrinter<'tcx>> Print<'tcx, P> for ty::Binder<'tcx, T>
where
- T: Print<'tcx, P, Output = P, Error = P::Error> + TypeFoldable<'tcx>,
+ T: Print<'tcx, P, Output = P, Error = P::Error> + TypeFoldable<TyCtxt<'tcx>>,
{
type Output = P;
type Error = P::Error;
@@ -2648,7 +2699,7 @@ define_print_and_forward_display! {
ty::ExistentialTraitRef<'tcx> {
// Use a type that can't appear in defaults of type parameters.
- let dummy_self = cx.tcx().mk_ty_infer(ty::FreshTy(0));
+ let dummy_self = cx.tcx().mk_fresh_ty(0);
let trait_ref = self.with_self_ty(cx.tcx(), dummy_self);
p!(print(trait_ref.print_only_trait_path()))
}
@@ -2774,15 +2825,18 @@ define_print_and_forward_display! {
ty::PredicateKind::Clause(ty::Clause::RegionOutlives(predicate)) => p!(print(predicate)),
ty::PredicateKind::Clause(ty::Clause::TypeOutlives(predicate)) => p!(print(predicate)),
ty::PredicateKind::Clause(ty::Clause::Projection(predicate)) => p!(print(predicate)),
+ ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(ct, ty)) => {
+ p!("the constant `", print(ct), "` has type `", print(ty), "`")
+ },
ty::PredicateKind::WellFormed(arg) => p!(print(arg), " well-formed"),
ty::PredicateKind::ObjectSafe(trait_def_id) => {
p!("the trait `", print_def_path(trait_def_id, &[]), "` is object-safe")
}
- ty::PredicateKind::ClosureKind(closure_def_id, _closure_substs, kind) => {
- p!("the closure `",
+ ty::PredicateKind::ClosureKind(closure_def_id, _closure_substs, kind) => p!(
+ "the closure `",
print_value_path(closure_def_id, &[]),
- write("` implements the trait `{}`", kind))
- }
+ write("` implements the trait `{}`", kind)
+ ),
ty::PredicateKind::ConstEvaluatable(ct) => {
p!("the constant `", print(ct), "` can be evaluated")
}
@@ -2793,6 +2847,7 @@ define_print_and_forward_display! {
p!("the type `", print(ty), "` is found in the environment")
}
ty::PredicateKind::Ambiguous => p!("ambiguous"),
+ ty::PredicateKind::AliasEq(t1, t2) => p!(print(t1), " == ", print(t2)),
}
}
diff --git a/compiler/rustc_middle/src/ty/query.rs b/compiler/rustc_middle/src/ty/query.rs
index 9d4ee22a7..2bc51baf8 100644
--- a/compiler/rustc_middle/src/ty/query.rs
+++ b/compiler/rustc_middle/src/ty/query.rs
@@ -1,3 +1,5 @@
+#![allow(unused_parens)]
+
use crate::dep_graph;
use crate::infer::canonical::{self, Canonical};
use crate::lint::LintExpectation;
@@ -6,7 +8,7 @@ use crate::middle::codegen_fn_attrs::CodegenFnAttrs;
use crate::middle::exported_symbols::{ExportedSymbol, SymbolExportInfo};
use crate::middle::lib_features::LibFeatures;
use crate::middle::privacy::EffectiveVisibilities;
-use crate::middle::resolve_lifetime::{ObjectLifetimeDefault, Region, ResolveLifetimes};
+use crate::middle::resolve_bound_vars::{ObjectLifetimeDefault, ResolveBoundVars, ResolvedArg};
use crate::middle::stability::{self, DeprecationEntry};
use crate::mir;
use crate::mir::interpret::GlobalId;
@@ -30,11 +32,12 @@ use crate::traits::specialization_graph;
use crate::traits::{self, ImplSource};
use crate::ty::context::TyCtxtFeed;
use crate::ty::fast_reject::SimplifiedType;
-use crate::ty::layout::TyAndLayout;
+use crate::ty::layout::ValidityRequirement;
use crate::ty::subst::{GenericArg, SubstsRef};
use crate::ty::util::AlwaysRequiresDrop;
use crate::ty::GeneratorDiagnosticData;
use crate::ty::{self, CrateInherentImpls, ParamEnvAnd, Ty, TyCtxt, UnusedGenericParams};
+use rustc_arena::TypedArena;
use rustc_ast as ast;
use rustc_ast::expand::allocator::AllocatorKind;
use rustc_attr as attr;
@@ -42,10 +45,11 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap, FxIndexSet};
use rustc_data_structures::steal::Steal;
use rustc_data_structures::svh::Svh;
use rustc_data_structures::sync::Lrc;
+use rustc_data_structures::sync::WorkerLocal;
use rustc_data_structures::unord::UnordSet;
use rustc_errors::ErrorGuaranteed;
use rustc_hir as hir;
-use rustc_hir::def::DefKind;
+use rustc_hir::def::{DefKind, DocLinkResMap};
use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, DefIdSet, LocalDefId};
use rustc_hir::hir_id::OwnerId;
use rustc_hir::lang_items::{LangItem, LanguageItems};
@@ -60,6 +64,7 @@ use rustc_span::symbol::Symbol;
use rustc_span::{Span, DUMMY_SP};
use rustc_target::abi;
use rustc_target::spec::PanicStrategy;
+use std::mem;
use std::ops::Deref;
use std::path::PathBuf;
use std::sync::Arc;
@@ -67,6 +72,12 @@ use std::sync::Arc;
pub(crate) use rustc_query_system::query::QueryJobId;
use rustc_query_system::query::*;
+#[derive(Default)]
+pub struct QuerySystem<'tcx> {
+ pub arenas: QueryArenas<'tcx>,
+ pub caches: QueryCaches<'tcx>,
+}
+
#[derive(Copy, Clone)]
pub struct TyCtxtAt<'tcx> {
pub tcx: TyCtxt<'tcx>,
@@ -106,30 +117,21 @@ impl<'tcx> TyCtxt<'tcx> {
}
}
-/// Helper for `TyCtxtEnsure` to avoid a closure.
-#[inline(always)]
-fn noop<T>(_: &T) {}
-
-/// Helper to ensure that queries only return `Copy` types.
-#[inline(always)]
-fn copy<T: Copy>(x: &T) -> T {
- *x
-}
-
macro_rules! query_helper_param_ty {
(DefId) => { impl IntoQueryParam<DefId> };
+ (LocalDefId) => { impl IntoQueryParam<LocalDefId> };
($K:ty) => { $K };
}
-macro_rules! query_storage {
- ([][$K:ty, $V:ty]) => {
- <<$K as Key>::CacheSelector as CacheSelector<'tcx, $V>>::Cache
+macro_rules! query_if_arena {
+ ([] $arena:tt $no_arena:tt) => {
+ $no_arena
};
- ([(arena_cache) $($rest:tt)*][$K:ty, $V:ty]) => {
- <<$K as Key>::CacheSelector as CacheSelector<'tcx, $V>>::ArenaCache
+ ([(arena_cache) $($rest:tt)*] $arena:tt $no_arena:tt) => {
+ $arena
};
- ([$other:tt $($modifiers:tt)*][$($args:tt)*]) => {
- query_storage!([$($modifiers)*][$($args)*])
+ ([$other:tt $($modifiers:tt)*]$($args:tt)*) => {
+ query_if_arena!([$($modifiers)*]$($args)*)
};
}
@@ -141,7 +143,7 @@ macro_rules! separate_provide_extern_decl {
for<'tcx> fn(
TyCtxt<'tcx>,
query_keys::$name<'tcx>,
- ) -> query_values::$name<'tcx>
+ ) -> query_provided::$name<'tcx>
};
([$other:tt $($modifiers:tt)*][$($args:tt)*]) => {
separate_provide_extern_decl!([$($modifiers)*][$($args)*])
@@ -199,17 +201,71 @@ macro_rules! define_callbacks {
$(pub type $name<'tcx> = $V;)*
}
+
+ /// This module specifies the type returned from query providers and the type used for
+ /// decoding. For regular queries this is the declared returned type `V`, but
+ /// `arena_cache` will use `<V as Deref>::Target` instead.
#[allow(nonstandard_style, unused_lifetimes)]
- pub mod query_storage {
+ pub mod query_provided {
use super::*;
- $(pub type $name<'tcx> = query_storage!([$($modifiers)*][$($K)*, $V]);)*
+ $(
+ pub type $name<'tcx> = query_if_arena!([$($modifiers)*] (<$V as Deref>::Target) ($V));
+ )*
}
+
+ /// This module has a function per query which takes a `query_provided` value and coverts
+ /// it to a regular `V` value by allocating it on an arena if the query has the
+ /// `arena_cache` modifier. This will happen when computing the query using a provider or
+ /// decoding a stored result.
#[allow(nonstandard_style, unused_lifetimes)]
- pub mod query_stored {
+ pub mod query_provided_to_value {
use super::*;
- $(pub type $name<'tcx> = <query_storage::$name<'tcx> as QueryStorage>::Stored;)*
+ $(
+ #[inline(always)]
+ pub fn $name<'tcx>(
+ _tcx: TyCtxt<'tcx>,
+ value: query_provided::$name<'tcx>,
+ ) -> query_values::$name<'tcx> {
+ query_if_arena!([$($modifiers)*]
+ {
+ if mem::needs_drop::<query_provided::$name<'tcx>>() {
+ &*_tcx.query_system.arenas.$name.alloc(value)
+ } else {
+ &*_tcx.arena.dropless.alloc(value)
+ }
+ }
+ (value)
+ )
+ }
+ )*
+ }
+ #[allow(nonstandard_style, unused_lifetimes)]
+ pub mod query_storage {
+ use super::*;
+
+ $(
+ pub type $name<'tcx> = <<$($K)* as Key>::CacheSelector as CacheSelector<'tcx, $V>>::Cache;
+ )*
+ }
+
+ pub struct QueryArenas<'tcx> {
+ $($(#[$attr])* pub $name: query_if_arena!([$($modifiers)*]
+ (WorkerLocal<TypedArena<<$V as Deref>::Target>>)
+ ()
+ ),)*
+ }
+
+ impl Default for QueryArenas<'_> {
+ fn default() -> Self {
+ Self {
+ $($name: query_if_arena!([$($modifiers)*]
+ (WorkerLocal::new(|_| Default::default()))
+ ()
+ ),)*
+ }
+ }
}
#[derive(Default)]
@@ -224,14 +280,10 @@ macro_rules! define_callbacks {
let key = key.into_query_param();
opt_remap_env_constness!([$($modifiers)*][key]);
- let cached = try_get_cached(self.tcx, &self.tcx.query_caches.$name, &key, noop);
-
- match cached {
- Ok(()) => return,
- Err(()) => (),
- }
-
- self.tcx.queries.$name(self.tcx, DUMMY_SP, key, QueryMode::Ensure);
+ match try_get_cached(self.tcx, &self.tcx.query_system.caches.$name, &key) {
+ Some(_) => return,
+ None => self.tcx.queries.$name(self.tcx, DUMMY_SP, key, QueryMode::Ensure),
+ };
})*
}
@@ -239,7 +291,7 @@ macro_rules! define_callbacks {
$($(#[$attr])*
#[inline(always)]
#[must_use]
- pub fn $name(self, key: query_helper_param_ty!($($K)*)) -> query_stored::$name<'tcx>
+ pub fn $name(self, key: query_helper_param_ty!($($K)*)) -> $V
{
self.at(DUMMY_SP).$name(key)
})*
@@ -248,19 +300,15 @@ macro_rules! define_callbacks {
impl<'tcx> TyCtxtAt<'tcx> {
$($(#[$attr])*
#[inline(always)]
- pub fn $name(self, key: query_helper_param_ty!($($K)*)) -> query_stored::$name<'tcx>
+ pub fn $name(self, key: query_helper_param_ty!($($K)*)) -> $V
{
let key = key.into_query_param();
opt_remap_env_constness!([$($modifiers)*][key]);
- let cached = try_get_cached(self.tcx, &self.tcx.query_caches.$name, &key, copy);
-
- match cached {
- Ok(value) => return value,
- Err(()) => (),
+ match try_get_cached(self.tcx, &self.tcx.query_system.caches.$name, &key) {
+ Some(value) => value,
+ None => self.tcx.queries.$name(self.tcx, self.span, key, QueryMode::Get).unwrap(),
}
-
- self.tcx.queries.$name(self.tcx, self.span, key, QueryMode::Get).unwrap()
})*
}
@@ -268,7 +316,7 @@ macro_rules! define_callbacks {
$(pub $name: for<'tcx> fn(
TyCtxt<'tcx>,
query_keys::$name<'tcx>,
- ) -> query_values::$name<'tcx>,)*
+ ) -> query_provided::$name<'tcx>,)*
}
pub struct ExternProviders {
@@ -281,8 +329,9 @@ macro_rules! define_callbacks {
Providers {
$($name: |_, key| bug!(
- "`tcx.{}({:?})` is not supported for {} crate;\n
- hint: Queries can be either made to the local crate, or the external crate. This error means you tried to use it for one that's not supported.\n
+ "`tcx.{}({:?})` is not supported for {} crate;\n\
+ hint: Queries can be either made to the local crate, or the external crate. \
+ This error means you tried to use it for one that's not supported.\n\
If that's not the case, {} was likely never assigned to a provider function.\n",
stringify!($name),
key,
@@ -323,7 +372,7 @@ macro_rules! define_callbacks {
span: Span,
key: query_keys::$name<'tcx>,
mode: QueryMode,
- ) -> Option<query_stored::$name<'tcx>>;)*
+ ) -> Option<$V>;)*
}
};
}
@@ -345,34 +394,34 @@ macro_rules! define_feedable {
$(impl<'tcx, K: IntoQueryParam<$($K)*> + Copy> TyCtxtFeed<'tcx, K> {
$(#[$attr])*
#[inline(always)]
- pub fn $name(self, value: $V) -> query_stored::$name<'tcx> {
+ pub fn $name(self, value: query_provided::$name<'tcx>) -> $V {
let key = self.key().into_query_param();
opt_remap_env_constness!([$($modifiers)*][key]);
let tcx = self.tcx;
- let cache = &tcx.query_caches.$name;
-
- let cached = try_get_cached(tcx, cache, &key, copy);
+ let value = query_provided_to_value::$name(tcx, value);
+ let cache = &tcx.query_system.caches.$name;
- match cached {
- Ok(old) => {
+ match try_get_cached(tcx, cache, &key) {
+ Some(old) => {
bug!(
"Trying to feed an already recorded value for query {} key={key:?}:\nold value: {old:?}\nnew value: {value:?}",
stringify!($name),
+ )
+ }
+ None => {
+ let dep_node = dep_graph::DepNode::construct(tcx, dep_graph::DepKind::$name, &key);
+ let dep_node_index = tcx.dep_graph.with_feed_task(
+ dep_node,
+ tcx,
+ key,
+ &value,
+ hash_result!([$($modifiers)*]),
);
+ cache.complete(key, value, dep_node_index);
+ value
}
- Err(()) => (),
}
-
- let dep_node = dep_graph::DepNode::construct(tcx, dep_graph::DepKind::$name, &key);
- let dep_node_index = tcx.dep_graph.with_feed_task(
- dep_node,
- tcx,
- key,
- &value,
- hash_result!([$($modifiers)*]),
- );
- cache.complete(key, value, dep_node_index)
}
})*
}
@@ -418,6 +467,13 @@ mod sealed {
}
}
+ impl IntoQueryParam<LocalDefId> for OwnerId {
+ #[inline(always)]
+ fn into_query_param(self) -> LocalDefId {
+ self.def_id
+ }
+ }
+
impl IntoQueryParam<DefId> for LocalDefId {
#[inline(always)]
fn into_query_param(self) -> DefId {
diff --git a/compiler/rustc_middle/src/ty/relate.rs b/compiler/rustc_middle/src/ty/relate.rs
index 65fd8d975..3fc5f5bed 100644
--- a/compiler/rustc_middle/src/ty/relate.rs
+++ b/compiler/rustc_middle/src/ty/relate.rs
@@ -9,7 +9,6 @@ use crate::ty::{self, Expr, ImplSubject, Term, TermKind, Ty, TyCtxt, TypeFoldabl
use crate::ty::{GenericArg, GenericArgKind, SubstsRef};
use rustc_hir as ast;
use rustc_hir::def_id::DefId;
-use rustc_span::DUMMY_SP;
use rustc_target::spec::abi;
use std::iter;
@@ -106,7 +105,7 @@ pub trait TypeRelation<'tcx>: Sized {
T: Relate<'tcx>;
}
-pub trait Relate<'tcx>: TypeFoldable<'tcx> + PartialEq + Copy {
+pub trait Relate<'tcx>: TypeFoldable<TyCtxt<'tcx>> + PartialEq + Copy {
fn relate<R: TypeRelation<'tcx>>(
relation: &mut R,
a: Self,
@@ -145,7 +144,7 @@ pub fn relate_substs<'tcx, R: TypeRelation<'tcx>>(
a_subst: SubstsRef<'tcx>,
b_subst: SubstsRef<'tcx>,
) -> RelateResult<'tcx, SubstsRef<'tcx>> {
- relation.tcx().mk_substs(iter::zip(a_subst, b_subst).map(|(a, b)| {
+ relation.tcx().mk_substs_from_iter(iter::zip(a_subst, b_subst).map(|(a, b)| {
relation.relate_with_variance(ty::Invariant, ty::VarianceDiagInfo::default(), a, b)
}))
}
@@ -164,8 +163,7 @@ pub fn relate_substs_with_variances<'tcx, R: TypeRelation<'tcx>>(
let params = iter::zip(a_subst, b_subst).enumerate().map(|(i, (a, b))| {
let variance = variances[i];
let variance_info = if variance == ty::Invariant && fetch_ty_for_diag {
- let ty =
- *cached_ty.get_or_insert_with(|| tcx.bound_type_of(ty_def_id).subst(tcx, a_subst));
+ let ty = *cached_ty.get_or_insert_with(|| tcx.type_of(ty_def_id).subst(tcx, a_subst));
ty::VarianceDiagInfo::Invariant { ty, param_index: i.try_into().unwrap() }
} else {
ty::VarianceDiagInfo::default()
@@ -173,7 +171,7 @@ pub fn relate_substs_with_variances<'tcx, R: TypeRelation<'tcx>>(
relation.relate_with_variance(variance, variance_info, a, b)
});
- tcx.mk_substs(params)
+ tcx.mk_substs_from_iter(params)
}
impl<'tcx> Relate<'tcx> for ty::FnSig<'tcx> {
@@ -224,7 +222,7 @@ impl<'tcx> Relate<'tcx> for ty::FnSig<'tcx> {
r => r,
});
Ok(ty::FnSig {
- inputs_and_output: tcx.mk_type_list(inputs_and_output)?,
+ inputs_and_output: tcx.mk_type_list_from_iter(inputs_and_output)?,
c_variadic: a.c_variadic,
unsafety,
abi,
@@ -354,7 +352,8 @@ impl<'tcx> Relate<'tcx> for GeneratorWitness<'tcx> {
) -> RelateResult<'tcx, GeneratorWitness<'tcx>> {
assert_eq!(a.0.len(), b.0.len());
let tcx = relation.tcx();
- let types = tcx.mk_type_list(iter::zip(a.0, b.0).map(|(a, b)| relation.relate(a, b)))?;
+ let types =
+ tcx.mk_type_list_from_iter(iter::zip(a.0, b.0).map(|(a, b)| relation.relate(a, b)))?;
Ok(GeneratorWitness(types))
}
}
@@ -414,7 +413,7 @@ pub fn super_relate_tys<'tcx, R: TypeRelation<'tcx>>(
bug!("bound types encountered in super_relate_tys")
}
- (&ty::Error(guar), _) | (_, &ty::Error(guar)) => Ok(tcx.ty_error_with_guaranteed(guar)),
+ (&ty::Error(guar), _) | (_, &ty::Error(guar)) => Ok(tcx.ty_error(guar)),
(&ty::Never, _)
| (&ty::Char, _)
@@ -443,12 +442,7 @@ pub fn super_relate_tys<'tcx, R: TypeRelation<'tcx>>(
if a_repr == b_repr =>
{
let region_bound = relation.with_cause(Cause::ExistentialRegionBound, |relation| {
- relation.relate_with_variance(
- ty::Contravariant,
- ty::VarianceDiagInfo::default(),
- a_region,
- b_region,
- )
+ relation.relate(a_region, b_region)
})?;
Ok(tcx.mk_dynamic(relation.relate(a_obj, b_obj)?, region_bound, a_repr))
}
@@ -473,6 +467,16 @@ pub fn super_relate_tys<'tcx, R: TypeRelation<'tcx>>(
Ok(tcx.mk_generator_witness(types))
}
+ (&ty::GeneratorWitnessMIR(a_id, a_substs), &ty::GeneratorWitnessMIR(b_id, b_substs))
+ if a_id == b_id =>
+ {
+ // All GeneratorWitness types with the same id represent
+ // the (anonymous) type of the same generator expression. So
+ // all of their regions should be equated.
+ let substs = relation.relate(a_substs, b_substs)?;
+ Ok(tcx.mk_generator_witness_mir(a_id, substs))
+ }
+
(&ty::Closure(a_id, a_substs), &ty::Closure(b_id, b_substs)) if a_id == b_id => {
// All Closure types with the same id represent
// the (anonymous) type of the same closure expression. So
@@ -487,12 +491,7 @@ pub fn super_relate_tys<'tcx, R: TypeRelation<'tcx>>(
}
(&ty::Ref(a_r, a_ty, a_mutbl), &ty::Ref(b_r, b_ty, b_mutbl)) => {
- let r = relation.relate_with_variance(
- ty::Contravariant,
- ty::VarianceDiagInfo::default(),
- a_r,
- b_r,
- )?;
+ let r = relation.relate(a_r, b_r)?;
let a_mt = ty::TypeAndMut { ty: a_ty, mutbl: a_mutbl };
let b_mt = ty::TypeAndMut { ty: b_ty, mutbl: b_mutbl };
let mt = relate_type_and_mut(relation, a_mt, b_mt, a)?;
@@ -502,7 +501,7 @@ pub fn super_relate_tys<'tcx, R: TypeRelation<'tcx>>(
(&ty::Array(a_t, sz_a), &ty::Array(b_t, sz_b)) => {
let t = relation.relate(a_t, b_t)?;
match relation.relate(sz_a, sz_b) {
- Ok(sz) => Ok(tcx.mk_ty(ty::Array(t, sz))),
+ Ok(sz) => Ok(tcx.mk_array_with_const_len(t, sz)),
Err(err) => {
// Check whether the lengths are both concrete/known values,
// but are unequal, for better diagnostics.
@@ -511,8 +510,8 @@ pub fn super_relate_tys<'tcx, R: TypeRelation<'tcx>>(
// we however cannot end up with errors in `Relate` during both
// `type_of` and `predicates_of`. This means that evaluating the
// constants should not cause cycle errors here.
- let sz_a = sz_a.try_eval_usize(tcx, relation.param_env());
- let sz_b = sz_b.try_eval_usize(tcx, relation.param_env());
+ let sz_a = sz_a.try_eval_target_usize(tcx, relation.param_env());
+ let sz_b = sz_b.try_eval_target_usize(tcx, relation.param_env());
match (sz_a, sz_b) {
(Some(sz_a_val), Some(sz_b_val)) if sz_a_val != sz_b_val => Err(
TypeError::FixedArraySize(expected_found(relation, sz_a_val, sz_b_val)),
@@ -530,7 +529,7 @@ pub fn super_relate_tys<'tcx, R: TypeRelation<'tcx>>(
(&ty::Tuple(as_), &ty::Tuple(bs)) => {
if as_.len() == bs.len() {
- Ok(tcx.mk_tup(iter::zip(as_, bs).map(|(a, b)| relation.relate(a, b)))?)
+ Ok(tcx.mk_tup_from_iter(iter::zip(as_, bs).map(|(a, b)| relation.relate(a, b)))?)
} else if !(as_.is_empty() || bs.is_empty()) {
Err(TypeError::TupleSize(expected_found(relation, as_.len(), bs.len())))
} else {
@@ -594,25 +593,6 @@ pub fn super_relate_consts<'tcx, R: TypeRelation<'tcx>>(
debug!("{}.super_relate_consts(a = {:?}, b = {:?})", relation.tag(), a, b);
let tcx = relation.tcx();
- let a_ty;
- let b_ty;
- if relation.tcx().features().adt_const_params {
- a_ty = tcx.normalize_erasing_regions(relation.param_env(), a.ty());
- b_ty = tcx.normalize_erasing_regions(relation.param_env(), b.ty());
- } else {
- a_ty = tcx.erase_regions(a.ty());
- b_ty = tcx.erase_regions(b.ty());
- }
- if a_ty != b_ty {
- relation.tcx().sess.delay_span_bug(
- DUMMY_SP,
- &format!(
- "cannot relate constants ({:?}, {:?}) of different types: {} != {}",
- a, b, a_ty, b_ty
- ),
- );
- }
-
// HACK(const_generics): We still need to eagerly evaluate consts when
// relating them because during `normalize_param_env_or_error`,
// we may relate an evaluated constant in a obligation against
@@ -629,6 +609,8 @@ pub fn super_relate_consts<'tcx, R: TypeRelation<'tcx>>(
b = tcx.expand_abstract_consts(b);
}
+ debug!("{}.super_relate_consts(normed_a = {:?}, normed_b = {:?})", relation.tag(), a, b);
+
// Currently, the values that can be unified are primitive types,
// and those that derive both `PartialEq` and `Eq`, corresponding
// to structural-match types.
@@ -665,36 +647,34 @@ pub fn super_relate_consts<'tcx, R: TypeRelation<'tcx>>(
// FIXME(generic_const_exprs): is it possible to relate two consts which are not identical
// exprs? Should we care about that?
+ // FIXME(generic_const_exprs): relating the `ty()`s is a little weird since it is supposed to
+ // ICE If they mismatch. Unfortunately `ConstKind::Expr` is a little special and can be thought
+ // of as being generic over the argument types, however this is implicit so these types don't get
+ // related when we relate the substs of the item this const arg is for.
let expr = match (ae, be) {
- (Expr::Binop(a_op, al, ar), Expr::Binop(b_op, bl, br))
- if a_op == b_op && al.ty() == bl.ty() && ar.ty() == br.ty() =>
- {
+ (Expr::Binop(a_op, al, ar), Expr::Binop(b_op, bl, br)) if a_op == b_op => {
+ r.relate(al.ty(), bl.ty())?;
+ r.relate(ar.ty(), br.ty())?;
Expr::Binop(a_op, r.consts(al, bl)?, r.consts(ar, br)?)
}
- (Expr::UnOp(a_op, av), Expr::UnOp(b_op, bv))
- if a_op == b_op && av.ty() == bv.ty() =>
- {
+ (Expr::UnOp(a_op, av), Expr::UnOp(b_op, bv)) if a_op == b_op => {
+ r.relate(av.ty(), bv.ty())?;
Expr::UnOp(a_op, r.consts(av, bv)?)
}
- (Expr::Cast(ak, av, at), Expr::Cast(bk, bv, bt))
- if ak == bk && av.ty() == bv.ty() =>
- {
+ (Expr::Cast(ak, av, at), Expr::Cast(bk, bv, bt)) if ak == bk => {
+ r.relate(av.ty(), bv.ty())?;
Expr::Cast(ak, r.consts(av, bv)?, r.tys(at, bt)?)
}
(Expr::FunctionCall(af, aa), Expr::FunctionCall(bf, ba))
- if aa.len() == ba.len()
- && af.ty() == bf.ty()
- && aa
- .iter()
- .zip(ba.iter())
- .all(|(a_arg, b_arg)| a_arg.ty() == b_arg.ty()) =>
+ if aa.len() == ba.len() =>
{
+ r.relate(af.ty(), bf.ty())?;
let func = r.consts(af, bf)?;
let mut related_args = Vec::with_capacity(aa.len());
for (a_arg, b_arg) in aa.iter().zip(ba.iter()) {
related_args.push(r.consts(a_arg, b_arg)?);
}
- let related_args = tcx.mk_const_list(related_args.iter());
+ let related_args = tcx.mk_const_list(&related_args);
Expr::FunctionCall(func, related_args)
}
_ => return Err(TypeError::ConstMismatch(expected_found(r, a, b))),
@@ -741,7 +721,7 @@ impl<'tcx> Relate<'tcx> for &'tcx ty::List<ty::PolyExistentialPredicate<'tcx>> {
_ => Err(TypeError::ExistentialMismatch(expected_found(relation, a, b))),
}
});
- tcx.mk_poly_existential_predicates(v)
+ tcx.mk_poly_existential_predicates_from_iter(v)
}
}
diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs
index 7d4d35b7f..ef643531b 100644
--- a/compiler/rustc_middle/src/ty/structural_impls.rs
+++ b/compiler/rustc_middle/src/ty/structural_impls.rs
@@ -1,6 +1,7 @@
-//! This module contains implements of the `Lift` and `TypeFoldable`
-//! traits for various types in the Rust compiler. Most are written by
-//! hand, though we've recently added some macros and proc-macros to help with the tedium.
+//! This module contains implementations of the `Lift`, `TypeFoldable` and
+//! `TypeVisitable` traits for various types in the Rust compiler. Most are
+//! written by hand, though we've recently added some macros and proc-macros
+//! to help with the tedium.
use crate::mir::interpret;
use crate::mir::{Field, ProjectionKind};
@@ -8,12 +9,11 @@ use crate::ty::fold::{FallibleTypeFolder, TypeFoldable, TypeSuperFoldable};
use crate::ty::print::{with_no_trimmed_paths, FmtPrinter, Printer};
use crate::ty::visit::{TypeSuperVisitable, TypeVisitable, TypeVisitor};
use crate::ty::{self, AliasTy, InferConst, Lift, Term, TermKind, Ty, TyCtxt};
-use rustc_data_structures::functor::IdFunctor;
use rustc_hir::def::Namespace;
use rustc_index::vec::{Idx, IndexVec};
+use rustc_target::abi::TyAndLayout;
use std::fmt;
-use std::mem::ManuallyDrop;
use std::ops::ControlFlow;
use std::rc::Rc;
use std::sync::Arc;
@@ -147,6 +147,7 @@ impl<'tcx> fmt::Debug for ty::Predicate<'tcx> {
impl<'tcx> fmt::Debug for ty::Clause<'tcx> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match *self {
+ ty::Clause::ConstArgHasType(ct, ty) => write!(f, "ConstArgHasType({ct:?}, {ty:?})"),
ty::Clause::Trait(ref a) => a.fmt(f),
ty::Clause::RegionOutlives(ref pair) => pair.fmt(f),
ty::Clause::TypeOutlives(ref pair) => pair.fmt(f),
@@ -176,6 +177,7 @@ impl<'tcx> fmt::Debug for ty::PredicateKind<'tcx> {
write!(f, "TypeWellFormedFromEnv({:?})", ty)
}
ty::PredicateKind::Ambiguous => write!(f, "Ambiguous"),
+ ty::PredicateKind::AliasEq(t1, t2) => write!(f, "AliasEq({t1:?}, {t2:?})"),
}
}
}
@@ -193,16 +195,27 @@ impl<'tcx> fmt::Debug for AliasTy<'tcx> {
// Atomic structs
//
// For things that don't carry any arena-allocated data (and are
-// copy...), just add them to this list.
+// copy...), just add them to one of these lists as appropriat.
-TrivialTypeTraversalAndLiftImpls! {
+// For things for which the type library provides traversal implementations
+// for all Interners, we only need to provide a Lift implementation:
+CloneLiftImpls! {
(),
bool,
usize,
- ::rustc_target::abi::VariantIdx,
+ u16,
u32,
u64,
String,
+ rustc_type_ir::DebruijnIndex,
+}
+
+// For things about which the type library does not know, or does not
+// provide any traversal implementations, we need to provide both a Lift
+// implementation and traversal implementations (the latter only for
+// TyCtxt<'_> interners).
+TrivialTypeTraversalAndLiftImpls! {
+ ::rustc_target::abi::VariantIdx,
crate::middle::region::Scope,
crate::ty::FloatTy,
::rustc_ast::InlineAsmOptions,
@@ -238,6 +251,7 @@ TrivialTypeTraversalAndLiftImpls! {
crate::ty::AssocKind,
crate::ty::AliasKind,
crate::ty::Placeholder<crate::ty::BoundRegionKind>,
+ crate::ty::Placeholder<crate::ty::BoundTyKind>,
crate::ty::ClosureKind,
crate::ty::FreeRegion,
crate::ty::InferTy,
@@ -249,11 +263,11 @@ TrivialTypeTraversalAndLiftImpls! {
crate::ty::UniverseIndex,
crate::ty::Variance,
::rustc_span::Span,
+ ::rustc_span::symbol::Ident,
::rustc_errors::ErrorGuaranteed,
Field,
interpret::Scalar,
rustc_target::abi::Size,
- rustc_type_ir::DebruijnIndex,
ty::BoundVar,
ty::Placeholder<ty::BoundVar>,
}
@@ -356,281 +370,106 @@ impl<'a, 'tcx> Lift<'tcx> for ty::ParamEnv<'a> {
}
///////////////////////////////////////////////////////////////////////////
-// TypeFoldable implementations.
+// Traversal implementations.
/// AdtDefs are basically the same as a DefId.
-impl<'tcx> TypeFoldable<'tcx> for ty::AdtDef<'tcx> {
- fn try_fold_with<F: FallibleTypeFolder<'tcx>>(self, _folder: &mut F) -> Result<Self, F::Error> {
+impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for ty::AdtDef<'tcx> {
+ fn try_fold_with<F: FallibleTypeFolder<TyCtxt<'tcx>>>(
+ self,
+ _folder: &mut F,
+ ) -> Result<Self, F::Error> {
Ok(self)
}
}
-impl<'tcx> TypeVisitable<'tcx> for ty::AdtDef<'tcx> {
- fn visit_with<V: TypeVisitor<'tcx>>(&self, _visitor: &mut V) -> ControlFlow<V::BreakTy> {
+impl<'tcx> TypeVisitable<TyCtxt<'tcx>> for ty::AdtDef<'tcx> {
+ fn visit_with<V: TypeVisitor<TyCtxt<'tcx>>>(
+ &self,
+ _visitor: &mut V,
+ ) -> ControlFlow<V::BreakTy> {
ControlFlow::Continue(())
}
}
-impl<'tcx, T: TypeFoldable<'tcx>, U: TypeFoldable<'tcx>> TypeFoldable<'tcx> for (T, U) {
- fn try_fold_with<F: FallibleTypeFolder<'tcx>>(
+impl<'tcx, T: TypeFoldable<TyCtxt<'tcx>>> TypeFoldable<TyCtxt<'tcx>> for ty::Binder<'tcx, T> {
+ fn try_fold_with<F: FallibleTypeFolder<TyCtxt<'tcx>>>(
self,
folder: &mut F,
- ) -> Result<(T, U), F::Error> {
- Ok((self.0.try_fold_with(folder)?, self.1.try_fold_with(folder)?))
+ ) -> Result<Self, F::Error> {
+ folder.try_fold_binder(self)
}
}
-impl<'tcx, T: TypeVisitable<'tcx>, U: TypeVisitable<'tcx>> TypeVisitable<'tcx> for (T, U) {
- fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
- self.0.visit_with(visitor)?;
- self.1.visit_with(visitor)
+impl<'tcx, T: TypeVisitable<TyCtxt<'tcx>>> TypeVisitable<TyCtxt<'tcx>> for ty::Binder<'tcx, T> {
+ fn visit_with<V: TypeVisitor<TyCtxt<'tcx>>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
+ visitor.visit_binder(self)
}
}
-impl<'tcx, A: TypeFoldable<'tcx>, B: TypeFoldable<'tcx>, C: TypeFoldable<'tcx>> TypeFoldable<'tcx>
- for (A, B, C)
-{
- fn try_fold_with<F: FallibleTypeFolder<'tcx>>(
+impl<'tcx, T: TypeFoldable<TyCtxt<'tcx>>> TypeSuperFoldable<TyCtxt<'tcx>> for ty::Binder<'tcx, T> {
+ fn try_super_fold_with<F: FallibleTypeFolder<TyCtxt<'tcx>>>(
self,
folder: &mut F,
- ) -> Result<(A, B, C), F::Error> {
- Ok((
- self.0.try_fold_with(folder)?,
- self.1.try_fold_with(folder)?,
- self.2.try_fold_with(folder)?,
- ))
+ ) -> Result<Self, F::Error> {
+ self.try_map_bound(|ty| ty.try_fold_with(folder))
}
}
-impl<'tcx, A: TypeVisitable<'tcx>, B: TypeVisitable<'tcx>, C: TypeVisitable<'tcx>>
- TypeVisitable<'tcx> for (A, B, C)
+impl<'tcx, T: TypeVisitable<TyCtxt<'tcx>>> TypeSuperVisitable<TyCtxt<'tcx>>
+ for ty::Binder<'tcx, T>
{
- fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
- self.0.visit_with(visitor)?;
- self.1.visit_with(visitor)?;
- self.2.visit_with(visitor)
+ fn super_visit_with<V: TypeVisitor<TyCtxt<'tcx>>>(
+ &self,
+ visitor: &mut V,
+ ) -> ControlFlow<V::BreakTy> {
+ self.as_ref().skip_binder().visit_with(visitor)
}
}
-EnumTypeTraversalImpl! {
- impl<'tcx, T> TypeFoldable<'tcx> for Option<T> {
- (Some)(a),
- (None),
- } where T: TypeFoldable<'tcx>
-}
-EnumTypeTraversalImpl! {
- impl<'tcx, T> TypeVisitable<'tcx> for Option<T> {
- (Some)(a),
- (None),
- } where T: TypeVisitable<'tcx>
-}
-
-EnumTypeTraversalImpl! {
- impl<'tcx, T, E> TypeFoldable<'tcx> for Result<T, E> {
- (Ok)(a),
- (Err)(a),
- } where T: TypeFoldable<'tcx>, E: TypeFoldable<'tcx>,
-}
-EnumTypeTraversalImpl! {
- impl<'tcx, T, E> TypeVisitable<'tcx> for Result<T, E> {
- (Ok)(a),
- (Err)(a),
- } where T: TypeVisitable<'tcx>, E: TypeVisitable<'tcx>,
-}
-
-impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for Rc<T> {
- fn try_fold_with<F: FallibleTypeFolder<'tcx>>(
- mut self,
+impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for &'tcx ty::List<ty::PolyExistentialPredicate<'tcx>> {
+ fn try_fold_with<F: FallibleTypeFolder<TyCtxt<'tcx>>>(
+ self,
folder: &mut F,
) -> Result<Self, F::Error> {
- // We merely want to replace the contained `T`, if at all possible,
- // so that we don't needlessly allocate a new `Rc` or indeed clone
- // the contained type.
- unsafe {
- // First step is to ensure that we have a unique reference to
- // the contained type, which `Rc::make_mut` will accomplish (by
- // allocating a new `Rc` and cloning the `T` only if required).
- // This is done *before* casting to `Rc<ManuallyDrop<T>>` so that
- // panicking during `make_mut` does not leak the `T`.
- Rc::make_mut(&mut self);
-
- // Casting to `Rc<ManuallyDrop<T>>` is safe because `ManuallyDrop`
- // is `repr(transparent)`.
- let ptr = Rc::into_raw(self).cast::<ManuallyDrop<T>>();
- let mut unique = Rc::from_raw(ptr);
-
- // Call to `Rc::make_mut` above guarantees that `unique` is the
- // sole reference to the contained value, so we can avoid doing
- // a checked `get_mut` here.
- let slot = Rc::get_mut_unchecked(&mut unique);
-
- // Semantically move the contained type out from `unique`, fold
- // it, then move the folded value back into `unique`. Should
- // folding fail, `ManuallyDrop` ensures that the "moved-out"
- // value is not re-dropped.
- let owned = ManuallyDrop::take(slot);
- let folded = owned.try_fold_with(folder)?;
- *slot = ManuallyDrop::new(folded);
-
- // Cast back to `Rc<T>`.
- Ok(Rc::from_raw(Rc::into_raw(unique).cast()))
- }
+ ty::util::fold_list(self, folder, |tcx, v| tcx.mk_poly_existential_predicates(v))
}
}
-impl<'tcx, T: TypeVisitable<'tcx>> TypeVisitable<'tcx> for Rc<T> {
- fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
- (**self).visit_with(visitor)
- }
-}
-
-impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for Arc<T> {
- fn try_fold_with<F: FallibleTypeFolder<'tcx>>(
- mut self,
+impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for &'tcx ty::List<ty::Const<'tcx>> {
+ fn try_fold_with<F: FallibleTypeFolder<TyCtxt<'tcx>>>(
+ self,
folder: &mut F,
) -> Result<Self, F::Error> {
- // We merely want to replace the contained `T`, if at all possible,
- // so that we don't needlessly allocate a new `Arc` or indeed clone
- // the contained type.
- unsafe {
- // First step is to ensure that we have a unique reference to
- // the contained type, which `Arc::make_mut` will accomplish (by
- // allocating a new `Arc` and cloning the `T` only if required).
- // This is done *before* casting to `Arc<ManuallyDrop<T>>` so that
- // panicking during `make_mut` does not leak the `T`.
- Arc::make_mut(&mut self);
-
- // Casting to `Arc<ManuallyDrop<T>>` is safe because `ManuallyDrop`
- // is `repr(transparent)`.
- let ptr = Arc::into_raw(self).cast::<ManuallyDrop<T>>();
- let mut unique = Arc::from_raw(ptr);
-
- // Call to `Arc::make_mut` above guarantees that `unique` is the
- // sole reference to the contained value, so we can avoid doing
- // a checked `get_mut` here.
- let slot = Arc::get_mut_unchecked(&mut unique);
-
- // Semantically move the contained type out from `unique`, fold
- // it, then move the folded value back into `unique`. Should
- // folding fail, `ManuallyDrop` ensures that the "moved-out"
- // value is not re-dropped.
- let owned = ManuallyDrop::take(slot);
- let folded = owned.try_fold_with(folder)?;
- *slot = ManuallyDrop::new(folded);
-
- // Cast back to `Arc<T>`.
- Ok(Arc::from_raw(Arc::into_raw(unique).cast()))
- }
- }
-}
-
-impl<'tcx, T: TypeVisitable<'tcx>> TypeVisitable<'tcx> for Arc<T> {
- fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
- (**self).visit_with(visitor)
- }
-}
-
-impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for Box<T> {
- fn try_fold_with<F: FallibleTypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> {
- self.try_map_id(|value| value.try_fold_with(folder))
- }
-}
-
-impl<'tcx, T: TypeVisitable<'tcx>> TypeVisitable<'tcx> for Box<T> {
- fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
- (**self).visit_with(visitor)
- }
-}
-
-impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for Vec<T> {
- fn try_fold_with<F: FallibleTypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> {
- self.try_map_id(|t| t.try_fold_with(folder))
- }
-}
-
-impl<'tcx, T: TypeVisitable<'tcx>> TypeVisitable<'tcx> for Vec<T> {
- fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
- self.iter().try_for_each(|t| t.visit_with(visitor))
- }
-}
-
-impl<'tcx, T: TypeVisitable<'tcx>> TypeVisitable<'tcx> for &[T] {
- fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
- self.iter().try_for_each(|t| t.visit_with(visitor))
- }
-}
-
-impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for Box<[T]> {
- fn try_fold_with<F: FallibleTypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> {
- self.try_map_id(|t| t.try_fold_with(folder))
- }
-}
-
-impl<'tcx, T: TypeVisitable<'tcx>> TypeVisitable<'tcx> for Box<[T]> {
- fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
- self.iter().try_for_each(|t| t.visit_with(visitor))
+ ty::util::fold_list(self, folder, |tcx, v| tcx.mk_const_list(v))
}
}
-impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for ty::Binder<'tcx, T> {
- fn try_fold_with<F: FallibleTypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> {
- folder.try_fold_binder(self)
- }
-}
-
-impl<'tcx, T: TypeVisitable<'tcx>> TypeVisitable<'tcx> for ty::Binder<'tcx, T> {
- fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
- visitor.visit_binder(self)
- }
-}
-
-impl<'tcx, T: TypeFoldable<'tcx>> TypeSuperFoldable<'tcx> for ty::Binder<'tcx, T> {
- fn try_super_fold_with<F: FallibleTypeFolder<'tcx>>(
+impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for &'tcx ty::List<ProjectionKind> {
+ fn try_fold_with<F: FallibleTypeFolder<TyCtxt<'tcx>>>(
self,
folder: &mut F,
) -> Result<Self, F::Error> {
- self.try_map_bound(|ty| ty.try_fold_with(folder))
+ ty::util::fold_list(self, folder, |tcx, v| tcx.mk_projs(v))
}
}
-impl<'tcx, T: TypeVisitable<'tcx>> TypeSuperVisitable<'tcx> for ty::Binder<'tcx, T> {
- fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
- self.as_ref().skip_binder().visit_with(visitor)
- }
-}
-
-impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::List<ty::PolyExistentialPredicate<'tcx>> {
- fn try_fold_with<F: FallibleTypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> {
- ty::util::fold_list(self, folder, |tcx, v| tcx.intern_poly_existential_predicates(v))
- }
-}
-
-impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::List<ty::Const<'tcx>> {
- fn try_fold_with<F: FallibleTypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> {
- ty::util::fold_list(self, folder, |tcx, v| tcx.mk_const_list(v.iter()))
- }
-}
-
-impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::List<ProjectionKind> {
- fn try_fold_with<F: FallibleTypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> {
- ty::util::fold_list(self, folder, |tcx, v| tcx.intern_projs(v))
- }
-}
-
-impl<'tcx> TypeFoldable<'tcx> for Ty<'tcx> {
- fn try_fold_with<F: FallibleTypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> {
+impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for Ty<'tcx> {
+ fn try_fold_with<F: FallibleTypeFolder<TyCtxt<'tcx>>>(
+ self,
+ folder: &mut F,
+ ) -> Result<Self, F::Error> {
folder.try_fold_ty(self)
}
}
-impl<'tcx> TypeVisitable<'tcx> for Ty<'tcx> {
- fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
+impl<'tcx> TypeVisitable<TyCtxt<'tcx>> for Ty<'tcx> {
+ fn visit_with<V: TypeVisitor<TyCtxt<'tcx>>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
visitor.visit_ty(*self)
}
}
-impl<'tcx> TypeSuperFoldable<'tcx> for Ty<'tcx> {
- fn try_super_fold_with<F: FallibleTypeFolder<'tcx>>(
+impl<'tcx> TypeSuperFoldable<TyCtxt<'tcx>> for Ty<'tcx> {
+ fn try_super_fold_with<F: FallibleTypeFolder<TyCtxt<'tcx>>>(
self,
folder: &mut F,
) -> Result<Self, F::Error> {
@@ -654,6 +493,9 @@ impl<'tcx> TypeSuperFoldable<'tcx> for Ty<'tcx> {
ty::Generator(did, substs.try_fold_with(folder)?, movability)
}
ty::GeneratorWitness(types) => ty::GeneratorWitness(types.try_fold_with(folder)?),
+ ty::GeneratorWitnessMIR(did, substs) => {
+ ty::GeneratorWitnessMIR(did, substs.try_fold_with(folder)?)
+ }
ty::Closure(did, substs) => ty::Closure(did, substs.try_fold_with(folder)?),
ty::Alias(kind, data) => ty::Alias(kind, data.try_fold_with(folder)?),
@@ -672,12 +514,15 @@ impl<'tcx> TypeSuperFoldable<'tcx> for Ty<'tcx> {
| ty::Foreign(..) => return Ok(self),
};
- Ok(if *self.kind() == kind { self } else { folder.tcx().mk_ty(kind) })
+ Ok(if *self.kind() == kind { self } else { folder.interner().mk_ty_from_kind(kind) })
}
}
-impl<'tcx> TypeSuperVisitable<'tcx> for Ty<'tcx> {
- fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
+impl<'tcx> TypeSuperVisitable<TyCtxt<'tcx>> for Ty<'tcx> {
+ fn super_visit_with<V: TypeVisitor<TyCtxt<'tcx>>>(
+ &self,
+ visitor: &mut V,
+ ) -> ControlFlow<V::BreakTy> {
match self.kind() {
ty::RawPtr(ref tm) => tm.visit_with(visitor),
ty::Array(typ, sz) => {
@@ -699,6 +544,7 @@ impl<'tcx> TypeSuperVisitable<'tcx> for Ty<'tcx> {
}
ty::Generator(_did, ref substs, _) => substs.visit_with(visitor),
ty::GeneratorWitness(ref types) => types.visit_with(visitor),
+ ty::GeneratorWitnessMIR(_did, ref substs) => substs.visit_with(visitor),
ty::Closure(_did, ref substs) => substs.visit_with(visitor),
ty::Alias(_, ref data) => data.visit_with(visitor),
@@ -719,20 +565,23 @@ impl<'tcx> TypeSuperVisitable<'tcx> for Ty<'tcx> {
}
}
-impl<'tcx> TypeFoldable<'tcx> for ty::Region<'tcx> {
- fn try_fold_with<F: FallibleTypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> {
+impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for ty::Region<'tcx> {
+ fn try_fold_with<F: FallibleTypeFolder<TyCtxt<'tcx>>>(
+ self,
+ folder: &mut F,
+ ) -> Result<Self, F::Error> {
folder.try_fold_region(self)
}
}
-impl<'tcx> TypeVisitable<'tcx> for ty::Region<'tcx> {
- fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
+impl<'tcx> TypeVisitable<TyCtxt<'tcx>> for ty::Region<'tcx> {
+ fn visit_with<V: TypeVisitor<TyCtxt<'tcx>>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
visitor.visit_region(*self)
}
}
-impl<'tcx> TypeSuperFoldable<'tcx> for ty::Region<'tcx> {
- fn try_super_fold_with<F: FallibleTypeFolder<'tcx>>(
+impl<'tcx> TypeSuperFoldable<TyCtxt<'tcx>> for ty::Region<'tcx> {
+ fn try_super_fold_with<F: FallibleTypeFolder<TyCtxt<'tcx>>>(
self,
_folder: &mut F,
) -> Result<Self, F::Error> {
@@ -740,116 +589,127 @@ impl<'tcx> TypeSuperFoldable<'tcx> for ty::Region<'tcx> {
}
}
-impl<'tcx> TypeSuperVisitable<'tcx> for ty::Region<'tcx> {
- fn super_visit_with<V: TypeVisitor<'tcx>>(&self, _visitor: &mut V) -> ControlFlow<V::BreakTy> {
+impl<'tcx> TypeSuperVisitable<TyCtxt<'tcx>> for ty::Region<'tcx> {
+ fn super_visit_with<V: TypeVisitor<TyCtxt<'tcx>>>(
+ &self,
+ _visitor: &mut V,
+ ) -> ControlFlow<V::BreakTy> {
ControlFlow::Continue(())
}
}
-impl<'tcx> TypeFoldable<'tcx> for ty::Predicate<'tcx> {
- fn try_fold_with<F: FallibleTypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> {
+impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for ty::Predicate<'tcx> {
+ fn try_fold_with<F: FallibleTypeFolder<TyCtxt<'tcx>>>(
+ self,
+ folder: &mut F,
+ ) -> Result<Self, F::Error> {
folder.try_fold_predicate(self)
}
}
-impl<'tcx> TypeVisitable<'tcx> for ty::Predicate<'tcx> {
- fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
+impl<'tcx> TypeVisitable<TyCtxt<'tcx>> for ty::Predicate<'tcx> {
+ fn visit_with<V: TypeVisitor<TyCtxt<'tcx>>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
visitor.visit_predicate(*self)
}
-
- #[inline]
- fn has_vars_bound_at_or_above(&self, binder: ty::DebruijnIndex) -> bool {
- self.outer_exclusive_binder() > binder
- }
-
- #[inline]
- fn has_type_flags(&self, flags: ty::TypeFlags) -> bool {
- self.flags().intersects(flags)
- }
}
-impl<'tcx> TypeSuperFoldable<'tcx> for ty::Predicate<'tcx> {
- fn try_super_fold_with<F: FallibleTypeFolder<'tcx>>(
+impl<'tcx> TypeSuperFoldable<TyCtxt<'tcx>> for ty::Predicate<'tcx> {
+ fn try_super_fold_with<F: FallibleTypeFolder<TyCtxt<'tcx>>>(
self,
folder: &mut F,
) -> Result<Self, F::Error> {
let new = self.kind().try_fold_with(folder)?;
- Ok(folder.tcx().reuse_or_mk_predicate(self, new))
+ Ok(folder.interner().reuse_or_mk_predicate(self, new))
}
}
-impl<'tcx> TypeSuperVisitable<'tcx> for ty::Predicate<'tcx> {
- fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
+impl<'tcx> TypeSuperVisitable<TyCtxt<'tcx>> for ty::Predicate<'tcx> {
+ fn super_visit_with<V: TypeVisitor<TyCtxt<'tcx>>>(
+ &self,
+ visitor: &mut V,
+ ) -> ControlFlow<V::BreakTy> {
self.kind().visit_with(visitor)
}
}
-impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::List<ty::Predicate<'tcx>> {
- fn try_fold_with<F: FallibleTypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> {
- ty::util::fold_list(self, folder, |tcx, v| tcx.intern_predicates(v))
- }
-}
-
-impl<'tcx, T: TypeFoldable<'tcx>, I: Idx> TypeFoldable<'tcx> for IndexVec<I, T> {
- fn try_fold_with<F: FallibleTypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> {
- self.try_map_id(|x| x.try_fold_with(folder))
- }
-}
-
-impl<'tcx, T: TypeVisitable<'tcx>, I: Idx> TypeVisitable<'tcx> for IndexVec<I, T> {
- fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
- self.iter().try_for_each(|t| t.visit_with(visitor))
+impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for &'tcx ty::List<ty::Predicate<'tcx>> {
+ fn try_fold_with<F: FallibleTypeFolder<TyCtxt<'tcx>>>(
+ self,
+ folder: &mut F,
+ ) -> Result<Self, F::Error> {
+ ty::util::fold_list(self, folder, |tcx, v| tcx.mk_predicates(v))
}
}
-impl<'tcx> TypeFoldable<'tcx> for ty::Const<'tcx> {
- fn try_fold_with<F: FallibleTypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> {
+impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for ty::Const<'tcx> {
+ fn try_fold_with<F: FallibleTypeFolder<TyCtxt<'tcx>>>(
+ self,
+ folder: &mut F,
+ ) -> Result<Self, F::Error> {
folder.try_fold_const(self)
}
}
-impl<'tcx> TypeVisitable<'tcx> for ty::Const<'tcx> {
- fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
+impl<'tcx> TypeVisitable<TyCtxt<'tcx>> for ty::Const<'tcx> {
+ fn visit_with<V: TypeVisitor<TyCtxt<'tcx>>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
visitor.visit_const(*self)
}
}
-impl<'tcx> TypeSuperFoldable<'tcx> for ty::Const<'tcx> {
- fn try_super_fold_with<F: FallibleTypeFolder<'tcx>>(
+impl<'tcx> TypeSuperFoldable<TyCtxt<'tcx>> for ty::Const<'tcx> {
+ fn try_super_fold_with<F: FallibleTypeFolder<TyCtxt<'tcx>>>(
self,
folder: &mut F,
) -> Result<Self, F::Error> {
let ty = self.ty().try_fold_with(folder)?;
let kind = self.kind().try_fold_with(folder)?;
if ty != self.ty() || kind != self.kind() {
- Ok(folder.tcx().mk_const(kind, ty))
+ Ok(folder.interner().mk_const(kind, ty))
} else {
Ok(self)
}
}
}
-impl<'tcx> TypeSuperVisitable<'tcx> for ty::Const<'tcx> {
- fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
+impl<'tcx> TypeSuperVisitable<TyCtxt<'tcx>> for ty::Const<'tcx> {
+ fn super_visit_with<V: TypeVisitor<TyCtxt<'tcx>>>(
+ &self,
+ visitor: &mut V,
+ ) -> ControlFlow<V::BreakTy> {
self.ty().visit_with(visitor)?;
self.kind().visit_with(visitor)
}
}
-impl<'tcx> TypeFoldable<'tcx> for InferConst<'tcx> {
- fn try_fold_with<F: FallibleTypeFolder<'tcx>>(self, _folder: &mut F) -> Result<Self, F::Error> {
+impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for InferConst<'tcx> {
+ fn try_fold_with<F: FallibleTypeFolder<TyCtxt<'tcx>>>(
+ self,
+ _folder: &mut F,
+ ) -> Result<Self, F::Error> {
Ok(self)
}
}
-impl<'tcx> TypeVisitable<'tcx> for InferConst<'tcx> {
- fn visit_with<V: TypeVisitor<'tcx>>(&self, _visitor: &mut V) -> ControlFlow<V::BreakTy> {
+impl<'tcx> TypeVisitable<TyCtxt<'tcx>> for InferConst<'tcx> {
+ fn visit_with<V: TypeVisitor<TyCtxt<'tcx>>>(
+ &self,
+ _visitor: &mut V,
+ ) -> ControlFlow<V::BreakTy> {
ControlFlow::Continue(())
}
}
-impl<'tcx> TypeSuperVisitable<'tcx> for ty::UnevaluatedConst<'tcx> {
- fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
+impl<'tcx> TypeSuperVisitable<TyCtxt<'tcx>> for ty::UnevaluatedConst<'tcx> {
+ fn super_visit_with<V: TypeVisitor<TyCtxt<'tcx>>>(
+ &self,
+ visitor: &mut V,
+ ) -> ControlFlow<V::BreakTy> {
self.substs.visit_with(visitor)
}
}
+
+impl<'tcx> TypeVisitable<TyCtxt<'tcx>> for TyAndLayout<'tcx, Ty<'tcx>> {
+ fn visit_with<V: TypeVisitor<TyCtxt<'tcx>>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
+ visitor.visit_ty(self.ty)
+ }
+}
diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs
index 91a7d5d38..e6a73e8bb 100644
--- a/compiler/rustc_middle/src/ty/sty.rs
+++ b/compiler/rustc_middle/src/ty/sty.rs
@@ -8,7 +8,7 @@ use crate::ty::visit::ValidateBoundVars;
use crate::ty::InferTy::*;
use crate::ty::{
self, AdtDef, DefIdTree, Discr, FallibleTypeFolder, Term, Ty, TyCtxt, TypeFlags, TypeFoldable,
- TypeSuperFoldable, TypeSuperVisitable, TypeVisitable, TypeVisitor,
+ TypeSuperFoldable, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor,
};
use crate::ty::{List, ParamEnv};
use hir::def::DefKind;
@@ -107,6 +107,15 @@ impl BoundRegionKind {
_ => None,
}
}
+
+ pub fn expect_anon(&self) -> u32 {
+ match *self {
+ BoundRegionKind::BrNamed(_, _) | BoundRegionKind::BrEnv => {
+ bug!("expected anon region: {self:?}")
+ }
+ BoundRegionKind::BrAnon(idx, _) => idx,
+ }
+ }
}
pub trait Article {
@@ -250,7 +259,7 @@ impl<'tcx> ClosureSubsts<'tcx> {
parts: ClosureSubstsParts<'tcx, Ty<'tcx>>,
) -> ClosureSubsts<'tcx> {
ClosureSubsts {
- substs: tcx.mk_substs(
+ substs: tcx.mk_substs_from_iter(
parts.parent_substs.iter().copied().chain(
[parts.closure_kind_ty, parts.closure_sig_as_fn_ptr_ty, parts.tupled_upvars_ty]
.iter()
@@ -377,7 +386,7 @@ impl<'tcx> GeneratorSubsts<'tcx> {
parts: GeneratorSubstsParts<'tcx, Ty<'tcx>>,
) -> GeneratorSubsts<'tcx> {
GeneratorSubsts {
- substs: tcx.mk_substs(
+ substs: tcx.mk_substs_from_iter(
parts.parent_substs.iter().copied().chain(
[
parts.resume_ty,
@@ -568,12 +577,12 @@ impl<'tcx> GeneratorSubsts<'tcx> {
self,
def_id: DefId,
tcx: TyCtxt<'tcx>,
- ) -> impl Iterator<Item = impl Iterator<Item = Ty<'tcx>> + Captures<'tcx>> {
+ ) -> impl Iterator<Item: Iterator<Item = Ty<'tcx>> + Captures<'tcx>> {
let layout = tcx.generator_layout(def_id).unwrap();
layout.variant_fields.iter().map(move |variant| {
- variant
- .iter()
- .map(move |field| ty::EarlyBinder(layout.field_tys[*field]).subst(tcx, self.substs))
+ variant.iter().map(move |field| {
+ ty::EarlyBinder(layout.field_tys[*field].ty).subst(tcx, self.substs)
+ })
})
}
@@ -655,7 +664,7 @@ impl<'tcx> InlineConstSubsts<'tcx> {
parts: InlineConstSubstsParts<'tcx, Ty<'tcx>>,
) -> InlineConstSubsts<'tcx> {
InlineConstSubsts {
- substs: tcx.mk_substs(
+ substs: tcx.mk_substs_from_iter(
parts.parent_substs.iter().copied().chain(std::iter::once(parts.ty.into())),
),
}
@@ -853,7 +862,7 @@ impl<'tcx> TraitRef<'tcx> {
substs: SubstsRef<'tcx>,
) -> ty::TraitRef<'tcx> {
let defs = tcx.generics_of(trait_id);
- tcx.mk_trait_ref(trait_id, tcx.intern_substs(&substs[..defs.params.len()]))
+ tcx.mk_trait_ref(trait_id, tcx.mk_substs(&substs[..defs.params.len()]))
}
}
@@ -899,7 +908,7 @@ impl<'tcx> ExistentialTraitRef<'tcx> {
ty::ExistentialTraitRef {
def_id: trait_ref.def_id,
- substs: tcx.intern_substs(&trait_ref.substs[1..]),
+ substs: tcx.mk_substs(&trait_ref.substs[1..]),
}
}
@@ -983,7 +992,7 @@ pub struct Binder<'tcx, T>(T, &'tcx List<BoundVariableKind>);
impl<'tcx, T> Binder<'tcx, T>
where
- T: TypeVisitable<'tcx>,
+ T: TypeVisitable<TyCtxt<'tcx>>,
{
/// Wraps `value` in a binder, asserting that `value` does not
/// contain any bound vars that would be bound by the
@@ -1051,14 +1060,14 @@ impl<'tcx, T> Binder<'tcx, T> {
Binder(value, self.1)
}
- pub fn map_bound_ref<F, U: TypeVisitable<'tcx>>(&self, f: F) -> Binder<'tcx, U>
+ pub fn map_bound_ref<F, U: TypeVisitable<TyCtxt<'tcx>>>(&self, f: F) -> Binder<'tcx, U>
where
F: FnOnce(&T) -> U,
{
self.as_ref().map_bound(f)
}
- pub fn map_bound<F, U: TypeVisitable<'tcx>>(self, f: F) -> Binder<'tcx, U>
+ pub fn map_bound<F, U: TypeVisitable<TyCtxt<'tcx>>>(self, f: F) -> Binder<'tcx, U>
where
F: FnOnce(T) -> U,
{
@@ -1070,7 +1079,10 @@ impl<'tcx, T> Binder<'tcx, T> {
Binder(value, self.1)
}
- pub fn try_map_bound<F, U: TypeVisitable<'tcx>, E>(self, f: F) -> Result<Binder<'tcx, U>, E>
+ pub fn try_map_bound<F, U: TypeVisitable<TyCtxt<'tcx>>, E>(
+ self,
+ f: F,
+ ) -> Result<Binder<'tcx, U>, E>
where
F: FnOnce(T) -> Result<U, E>,
{
@@ -1093,7 +1105,7 @@ impl<'tcx, T> Binder<'tcx, T> {
/// in `bind`. This may be (debug) asserted in the future.
pub fn rebind<U>(&self, value: U) -> Binder<'tcx, U>
where
- U: TypeVisitable<'tcx>,
+ U: TypeVisitable<TyCtxt<'tcx>>,
{
if cfg!(debug_assertions) {
let mut validator = ValidateBoundVars::new(self.bound_vars());
@@ -1114,7 +1126,7 @@ impl<'tcx, T> Binder<'tcx, T> {
/// would not be that useful.)
pub fn no_bound_vars(self) -> Option<T>
where
- T: TypeVisitable<'tcx>,
+ T: TypeVisitable<TyCtxt<'tcx>>,
{
if self.0.has_escaping_bound_vars() { None } else { Some(self.skip_binder()) }
}
@@ -1153,16 +1165,16 @@ struct SkipBindersAt<'tcx> {
index: ty::DebruijnIndex,
}
-impl<'tcx> FallibleTypeFolder<'tcx> for SkipBindersAt<'tcx> {
+impl<'tcx> FallibleTypeFolder<TyCtxt<'tcx>> for SkipBindersAt<'tcx> {
type Error = ();
- fn tcx(&self) -> TyCtxt<'tcx> {
+ fn interner(&self) -> TyCtxt<'tcx> {
self.tcx
}
fn try_fold_binder<T>(&mut self, t: Binder<'tcx, T>) -> Result<Binder<'tcx, T>, Self::Error>
where
- T: ty::TypeFoldable<'tcx>,
+ T: ty::TypeFoldable<TyCtxt<'tcx>>,
{
self.index.shift_in(1);
let value = t.try_map_bound(|t| t.try_fold_with(self));
@@ -1177,7 +1189,7 @@ impl<'tcx> FallibleTypeFolder<'tcx> for SkipBindersAt<'tcx> {
if index == self.index {
Err(())
} else {
- Ok(self.tcx().mk_ty(ty::Bound(index.shifted_out(1), bv)))
+ Ok(self.interner().mk_bound(index.shifted_out(1), bv))
}
} else {
ty.try_super_fold_with(self)
@@ -1191,7 +1203,7 @@ impl<'tcx> FallibleTypeFolder<'tcx> for SkipBindersAt<'tcx> {
if index == self.index {
Err(())
} else {
- Ok(self.tcx().mk_region(ty::ReLateBound(index.shifted_out(1), bv)))
+ Ok(self.interner().mk_re_late_bound(index.shifted_out(1), bv))
}
} else {
r.try_super_fold_with(self)
@@ -1205,7 +1217,7 @@ impl<'tcx> FallibleTypeFolder<'tcx> for SkipBindersAt<'tcx> {
if index == self.index {
Err(())
} else {
- Ok(self.tcx().mk_const(
+ Ok(self.interner().mk_const(
ty::ConstKind::Bound(index.shifted_out(1), bv),
ct.ty().try_fold_with(self)?,
))
@@ -1266,7 +1278,7 @@ impl<'tcx> AliasTy<'tcx> {
}
pub fn to_ty(self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> {
- tcx.mk_ty(ty::Alias(self.kind(tcx), self))
+ tcx.mk_alias(self.kind(tcx), self)
}
}
@@ -1510,13 +1522,22 @@ pub struct BoundTy {
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, TyEncodable, TyDecodable)]
#[derive(HashStable)]
pub enum BoundTyKind {
- Anon,
- Param(Symbol),
+ Anon(u32),
+ Param(DefId, Symbol),
+}
+
+impl BoundTyKind {
+ pub fn expect_anon(self) -> u32 {
+ match self {
+ BoundTyKind::Anon(i) => i,
+ _ => bug!(),
+ }
+ }
}
impl From<BoundVar> for BoundTy {
fn from(var: BoundVar) -> Self {
- BoundTy { var, kind: BoundTyKind::Anon }
+ BoundTy { var, kind: BoundTyKind::Anon(var.as_u32()) }
}
}
@@ -1539,7 +1560,7 @@ impl<'tcx> ExistentialProjection<'tcx> {
pub fn trait_ref(&self, tcx: TyCtxt<'tcx>) -> ty::ExistentialTraitRef<'tcx> {
let def_id = tcx.parent(self.def_id);
let subst_count = tcx.generics_of(def_id).count() - 1;
- let substs = tcx.intern_substs(&self.substs[..subst_count]);
+ let substs = tcx.mk_substs(&self.substs[..subst_count]);
ty::ExistentialTraitRef { def_id, substs }
}
@@ -1567,7 +1588,7 @@ impl<'tcx> ExistentialProjection<'tcx> {
Self {
def_id: projection_predicate.projection_ty.def_id,
- substs: tcx.intern_substs(&projection_predicate.projection_ty.substs[1..]),
+ substs: tcx.mk_substs(&projection_predicate.projection_ty.substs[1..]),
term: projection_predicate.term,
}
}
@@ -1620,10 +1641,16 @@ impl<'tcx> Region<'tcx> {
ty::ReVar(..) => false,
ty::RePlaceholder(placeholder) => placeholder.name.is_named(),
ty::ReErased => false,
+ ty::ReError(_) => false,
}
}
#[inline]
+ pub fn is_error(self) -> bool {
+ matches!(*self, ty::ReError(_))
+ }
+
+ #[inline]
pub fn is_static(self) -> bool {
matches!(*self, ty::ReStatic)
}
@@ -1683,6 +1710,7 @@ impl<'tcx> Region<'tcx> {
ty::ReErased => {
flags = flags | TypeFlags::HAS_RE_ERASED;
}
+ ty::ReError(_) => {}
}
debug!("type_flags({:?}) = {:?}", self, flags);
@@ -1733,6 +1761,13 @@ impl<'tcx> Region<'tcx> {
pub fn is_var(self) -> bool {
matches!(self.kind(), ty::ReVar(_))
}
+
+ pub fn as_var(self) -> Option<RegionVid> {
+ match self.kind() {
+ ty::ReVar(vid) => Some(vid),
+ _ => None,
+ }
+ }
}
/// Type utilities
@@ -1867,7 +1902,7 @@ impl<'tcx> Ty<'tcx> {
// The way we evaluate the `N` in `[T; N]` here only works since we use
// `simd_size_and_type` post-monomorphization. It will probably start to ICE
// if we use it in generic code. See the `simd-array-trait` ui test.
- (f0_len.eval_usize(tcx, ParamEnv::empty()) as u64, *f0_elem_ty)
+ (f0_len.eval_target_usize(tcx, ParamEnv::empty()) as u64, *f0_elem_ty)
}
// Otherwise, the fields of this Adt are the SIMD components (and we assume they
// all have the same type).
@@ -2028,7 +2063,7 @@ impl<'tcx> Ty<'tcx> {
pub fn contains(self, other: Ty<'tcx>) -> bool {
struct ContainsTyVisitor<'tcx>(Ty<'tcx>);
- impl<'tcx> TypeVisitor<'tcx> for ContainsTyVisitor<'tcx> {
+ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for ContainsTyVisitor<'tcx> {
type BreakTy = ();
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
@@ -2040,6 +2075,28 @@ impl<'tcx> Ty<'tcx> {
cf.is_break()
}
+ /// Checks whether a type recursively contains any closure
+ ///
+ /// Example: `Option<[closure@file.rs:4:20]>` returns true
+ pub fn contains_closure(self) -> bool {
+ struct ContainsClosureVisitor;
+
+ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for ContainsClosureVisitor {
+ type BreakTy = ();
+
+ fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
+ if let ty::Closure(_, _) = t.kind() {
+ ControlFlow::Break(())
+ } else {
+ t.super_visit_with(self)
+ }
+ }
+ }
+
+ let cf = self.visit_with(&mut ContainsClosureVisitor);
+ cf.is_break()
+ }
+
/// Returns the type and mutability of `*ty`.
///
/// The parameter `explicit` indicates if this is an *explicit* dereference.
@@ -2065,7 +2122,7 @@ impl<'tcx> Ty<'tcx> {
pub fn fn_sig(self, tcx: TyCtxt<'tcx>) -> PolyFnSig<'tcx> {
match self.kind() {
- FnDef(def_id, substs) => tcx.bound_fn_sig(*def_id).subst(tcx, substs),
+ FnDef(def_id, substs) => tcx.fn_sig(*def_id).subst(tcx, substs),
FnPtr(f) => *f,
Error(_) => {
// ignore errors (#54954)
@@ -2161,7 +2218,7 @@ impl<'tcx> Ty<'tcx> {
let assoc_items = tcx.associated_item_def_ids(
tcx.require_lang_item(hir::LangItem::DiscriminantKind, None),
);
- tcx.mk_projection(assoc_items[0], tcx.intern_substs(&[self.into()]))
+ tcx.mk_projection(assoc_items[0], tcx.mk_substs(&[self.into()]))
}
ty::Bool
@@ -2181,6 +2238,7 @@ impl<'tcx> Ty<'tcx> {
| ty::Dynamic(..)
| ty::Closure(..)
| ty::GeneratorWitness(..)
+ | ty::GeneratorWitnessMIR(..)
| ty::Never
| ty::Tuple(_)
| ty::Error(_)
@@ -2216,6 +2274,7 @@ impl<'tcx> Ty<'tcx> {
| ty::Ref(..)
| ty::Generator(..)
| ty::GeneratorWitness(..)
+ | ty::GeneratorWitnessMIR(..)
| ty::Array(..)
| ty::Closure(..)
| ty::Never
@@ -2232,7 +2291,7 @@ impl<'tcx> Ty<'tcx> {
ty::Str | ty::Slice(_) => (tcx.types.usize, false),
ty::Dynamic(..) => {
let dyn_metadata = tcx.require_lang_item(LangItem::DynMetadata, None);
- (tcx.bound_type_of(dyn_metadata).subst(tcx, &[tail.into()]), false)
+ (tcx.type_of(dyn_metadata).subst(tcx, &[tail.into()]), false)
},
// type parameters only have unit metadata if they're sized, so return true
@@ -2302,6 +2361,7 @@ impl<'tcx> Ty<'tcx> {
| ty::Ref(..)
| ty::Generator(..)
| ty::GeneratorWitness(..)
+ | ty::GeneratorWitnessMIR(..)
| ty::Array(..)
| ty::Closure(..)
| ty::Never
@@ -2366,7 +2426,7 @@ impl<'tcx> Ty<'tcx> {
// anything with custom metadata it might be more complicated.
ty::Ref(_, _, hir::Mutability::Not) | ty::RawPtr(..) => false,
- ty::Generator(..) | ty::GeneratorWitness(..) => false,
+ ty::Generator(..) | ty::GeneratorWitness(..) | ty::GeneratorWitnessMIR(..) => false,
// Might be, but not "trivial" so just giving the safe answer.
ty::Adt(..) | ty::Closure(..) => false,
diff --git a/compiler/rustc_middle/src/ty/subst.rs b/compiler/rustc_middle/src/ty/subst.rs
index a07582fc8..b090bd9d8 100644
--- a/compiler/rustc_middle/src/ty/subst.rs
+++ b/compiler/rustc_middle/src/ty/subst.rs
@@ -3,7 +3,7 @@
use crate::ty::codec::{TyDecoder, TyEncoder};
use crate::ty::fold::{FallibleTypeFolder, TypeFoldable, TypeFolder, TypeSuperFoldable};
use crate::ty::sty::{ClosureSubsts, GeneratorSubsts, InlineConstSubsts};
-use crate::ty::visit::{TypeVisitable, TypeVisitor};
+use crate::ty::visit::{TypeVisitable, TypeVisitableExt, TypeVisitor};
use crate::ty::{self, Lift, List, ParamConst, Ty, TyCtxt};
use rustc_data_structures::intern::Interned;
@@ -71,7 +71,7 @@ impl<'tcx> List<Ty<'tcx>> {
/// Allows to freely switch between `List<Ty<'tcx>>` and `List<GenericArg<'tcx>>`.
///
/// As lists are interned, `List<Ty<'tcx>>` and `List<GenericArg<'tcx>>` have
- /// be interned together, see `intern_type_list` for more details.
+ /// be interned together, see `mk_type_list` for more details.
#[inline]
pub fn as_substs(&'tcx self) -> SubstsRef<'tcx> {
assert_eq!(TYPE_TAG, 0);
@@ -227,8 +227,11 @@ impl<'a, 'tcx> Lift<'tcx> for GenericArg<'a> {
}
}
-impl<'tcx> TypeFoldable<'tcx> for GenericArg<'tcx> {
- fn try_fold_with<F: FallibleTypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> {
+impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for GenericArg<'tcx> {
+ fn try_fold_with<F: FallibleTypeFolder<TyCtxt<'tcx>>>(
+ self,
+ folder: &mut F,
+ ) -> Result<Self, F::Error> {
match self.unpack() {
GenericArgKind::Lifetime(lt) => lt.try_fold_with(folder).map(Into::into),
GenericArgKind::Type(ty) => ty.try_fold_with(folder).map(Into::into),
@@ -237,8 +240,8 @@ impl<'tcx> TypeFoldable<'tcx> for GenericArg<'tcx> {
}
}
-impl<'tcx> TypeVisitable<'tcx> for GenericArg<'tcx> {
- fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
+impl<'tcx> TypeVisitable<TyCtxt<'tcx>> for GenericArg<'tcx> {
+ fn visit_with<V: TypeVisitor<TyCtxt<'tcx>>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
match self.unpack() {
GenericArgKind::Lifetime(lt) => lt.visit_with(visitor),
GenericArgKind::Type(ty) => ty.visit_with(visitor),
@@ -267,13 +270,11 @@ pub type SubstsRef<'tcx> = &'tcx InternalSubsts<'tcx>;
impl<'tcx> InternalSubsts<'tcx> {
/// Checks whether all elements of this list are types, if so, transmute.
pub fn try_as_type_list(&'tcx self) -> Option<&'tcx List<Ty<'tcx>>> {
- if self.iter().all(|arg| matches!(arg.unpack(), GenericArgKind::Type(_))) {
+ self.iter().all(|arg| matches!(arg.unpack(), GenericArgKind::Type(_))).then(|| {
assert_eq!(TYPE_TAG, 0);
// SAFETY: All elements are types, see `List<Ty<'tcx>>::as_substs`.
- Some(unsafe { &*(self as *const List<GenericArg<'tcx>> as *const List<Ty<'tcx>>) })
- } else {
- None
- }
+ unsafe { &*(self as *const List<GenericArg<'tcx>> as *const List<Ty<'tcx>>) }
+ })
}
/// Interpret these substitutions as the substitutions of a closure type.
@@ -318,7 +319,7 @@ impl<'tcx> InternalSubsts<'tcx> {
let count = defs.count();
let mut substs = SmallVec::with_capacity(count);
Self::fill_item(&mut substs, tcx, defs, &mut mk_kind);
- tcx.intern_substs(&substs)
+ tcx.mk_substs(&substs)
}
pub fn extend_to<F>(&self, tcx: TyCtxt<'tcx>, def_id: DefId, mut mk_kind: F) -> SubstsRef<'tcx>
@@ -467,26 +468,33 @@ impl<'tcx> InternalSubsts<'tcx> {
target_substs: SubstsRef<'tcx>,
) -> SubstsRef<'tcx> {
let defs = tcx.generics_of(source_ancestor);
- tcx.mk_substs(target_substs.iter().chain(self.iter().skip(defs.params.len())))
+ tcx.mk_substs_from_iter(target_substs.iter().chain(self.iter().skip(defs.params.len())))
}
pub fn truncate_to(&self, tcx: TyCtxt<'tcx>, generics: &ty::Generics) -> SubstsRef<'tcx> {
- tcx.mk_substs(self.iter().take(generics.count()))
+ tcx.mk_substs_from_iter(self.iter().take(generics.count()))
}
}
-impl<'tcx> TypeFoldable<'tcx> for SubstsRef<'tcx> {
- fn try_fold_with<F: FallibleTypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> {
+impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for SubstsRef<'tcx> {
+ fn try_fold_with<F: FallibleTypeFolder<TyCtxt<'tcx>>>(
+ self,
+ folder: &mut F,
+ ) -> Result<Self, F::Error> {
// This code is hot enough that it's worth specializing for the most
// common length lists, to avoid the overhead of `SmallVec` creation.
// The match arms are in order of frequency. The 1, 2, and 0 cases are
// typically hit in 90--99.99% of cases. When folding doesn't change
// the substs, it's faster to reuse the existing substs rather than
- // calling `intern_substs`.
+ // calling `mk_substs`.
match self.len() {
1 => {
let param0 = self[0].try_fold_with(folder)?;
- if param0 == self[0] { Ok(self) } else { Ok(folder.tcx().intern_substs(&[param0])) }
+ if param0 == self[0] {
+ Ok(self)
+ } else {
+ Ok(folder.interner().mk_substs(&[param0]))
+ }
}
2 => {
let param0 = self[0].try_fold_with(folder)?;
@@ -494,17 +502,20 @@ impl<'tcx> TypeFoldable<'tcx> for SubstsRef<'tcx> {
if param0 == self[0] && param1 == self[1] {
Ok(self)
} else {
- Ok(folder.tcx().intern_substs(&[param0, param1]))
+ Ok(folder.interner().mk_substs(&[param0, param1]))
}
}
0 => Ok(self),
- _ => ty::util::fold_list(self, folder, |tcx, v| tcx.intern_substs(v)),
+ _ => ty::util::fold_list(self, folder, |tcx, v| tcx.mk_substs(v)),
}
}
}
-impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::List<Ty<'tcx>> {
- fn try_fold_with<F: FallibleTypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> {
+impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for &'tcx ty::List<Ty<'tcx>> {
+ fn try_fold_with<F: FallibleTypeFolder<TyCtxt<'tcx>>>(
+ self,
+ folder: &mut F,
+ ) -> Result<Self, F::Error> {
// This code is fairly hot, though not as hot as `SubstsRef`.
//
// When compiling stage 2, I get the following results:
@@ -527,17 +538,17 @@ impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::List<Ty<'tcx>> {
if param0 == self[0] && param1 == self[1] {
Ok(self)
} else {
- Ok(folder.tcx().intern_type_list(&[param0, param1]))
+ Ok(folder.interner().mk_type_list(&[param0, param1]))
}
}
- _ => ty::util::fold_list(self, folder, |tcx, v| tcx.intern_type_list(v)),
+ _ => ty::util::fold_list(self, folder, |tcx, v| tcx.mk_type_list(v)),
}
}
}
-impl<'tcx, T: TypeVisitable<'tcx>> TypeVisitable<'tcx> for &'tcx ty::List<T> {
+impl<'tcx, T: TypeVisitable<TyCtxt<'tcx>>> TypeVisitable<TyCtxt<'tcx>> for &'tcx ty::List<T> {
#[inline]
- fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
+ fn visit_with<V: TypeVisitor<TyCtxt<'tcx>>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
self.iter().try_for_each(|t| t.visit_with(visitor))
}
}
@@ -553,8 +564,8 @@ impl<'tcx, T: TypeVisitable<'tcx>> TypeVisitable<'tcx> for &'tcx ty::List<T> {
pub struct EarlyBinder<T>(pub T);
/// For early binders, you should first call `subst` before using any visitors.
-impl<'tcx, T> !TypeFoldable<'tcx> for ty::EarlyBinder<T> {}
-impl<'tcx, T> !TypeVisitable<'tcx> for ty::EarlyBinder<T> {}
+impl<'tcx, T> !TypeFoldable<TyCtxt<'tcx>> for ty::EarlyBinder<T> {}
+impl<'tcx, T> !TypeVisitable<TyCtxt<'tcx>> for ty::EarlyBinder<T> {}
impl<T> EarlyBinder<T> {
pub fn as_ref(&self) -> EarlyBinder<&T> {
@@ -615,7 +626,7 @@ impl<T, U> EarlyBinder<(T, U)> {
impl<'tcx, 's, I: IntoIterator> EarlyBinder<I>
where
- I::Item: TypeFoldable<'tcx>,
+ I::Item: TypeFoldable<TyCtxt<'tcx>>,
{
pub fn subst_iter(
self,
@@ -634,7 +645,7 @@ pub struct SubstIter<'s, 'tcx, I: IntoIterator> {
impl<'tcx, I: IntoIterator> Iterator for SubstIter<'_, 'tcx, I>
where
- I::Item: TypeFoldable<'tcx>,
+ I::Item: TypeFoldable<TyCtxt<'tcx>>,
{
type Item = I::Item;
@@ -650,7 +661,7 @@ where
impl<'tcx, I: IntoIterator> DoubleEndedIterator for SubstIter<'_, 'tcx, I>
where
I::IntoIter: DoubleEndedIterator,
- I::Item: TypeFoldable<'tcx>,
+ I::Item: TypeFoldable<TyCtxt<'tcx>>,
{
fn next_back(&mut self) -> Option<Self::Item> {
Some(EarlyBinder(self.it.next_back()?).subst(self.tcx, self.substs))
@@ -660,14 +671,14 @@ where
impl<'tcx, I: IntoIterator> ExactSizeIterator for SubstIter<'_, 'tcx, I>
where
I::IntoIter: ExactSizeIterator,
- I::Item: TypeFoldable<'tcx>,
+ I::Item: TypeFoldable<TyCtxt<'tcx>>,
{
}
impl<'tcx, 's, I: IntoIterator> EarlyBinder<I>
where
I::Item: Deref,
- <I::Item as Deref>::Target: Copy + TypeFoldable<'tcx>,
+ <I::Item as Deref>::Target: Copy + TypeFoldable<TyCtxt<'tcx>>,
{
pub fn subst_iter_copied(
self,
@@ -687,7 +698,7 @@ pub struct SubstIterCopied<'a, 'tcx, I: IntoIterator> {
impl<'tcx, I: IntoIterator> Iterator for SubstIterCopied<'_, 'tcx, I>
where
I::Item: Deref,
- <I::Item as Deref>::Target: Copy + TypeFoldable<'tcx>,
+ <I::Item as Deref>::Target: Copy + TypeFoldable<TyCtxt<'tcx>>,
{
type Item = <I::Item as Deref>::Target;
@@ -704,7 +715,7 @@ impl<'tcx, I: IntoIterator> DoubleEndedIterator for SubstIterCopied<'_, 'tcx, I>
where
I::IntoIter: DoubleEndedIterator,
I::Item: Deref,
- <I::Item as Deref>::Target: Copy + TypeFoldable<'tcx>,
+ <I::Item as Deref>::Target: Copy + TypeFoldable<TyCtxt<'tcx>>,
{
fn next_back(&mut self) -> Option<Self::Item> {
Some(EarlyBinder(*self.it.next_back()?).subst(self.tcx, self.substs))
@@ -715,7 +726,7 @@ impl<'tcx, I: IntoIterator> ExactSizeIterator for SubstIterCopied<'_, 'tcx, I>
where
I::IntoIter: ExactSizeIterator,
I::Item: Deref,
- <I::Item as Deref>::Target: Copy + TypeFoldable<'tcx>,
+ <I::Item as Deref>::Target: Copy + TypeFoldable<TyCtxt<'tcx>>,
{
}
@@ -741,7 +752,7 @@ impl<T: Iterator> Iterator for EarlyBinderIter<T> {
}
}
-impl<'tcx, T: TypeFoldable<'tcx>> ty::EarlyBinder<T> {
+impl<'tcx, T: TypeFoldable<TyCtxt<'tcx>>> ty::EarlyBinder<T> {
pub fn subst(self, tcx: TyCtxt<'tcx>, substs: &[GenericArg<'tcx>]) -> T {
let mut folder = SubstFolder { tcx, substs, binders_passed: 0 };
self.0.fold_with(&mut folder)
@@ -758,6 +769,11 @@ impl<'tcx, T: TypeFoldable<'tcx>> ty::EarlyBinder<T> {
pub fn subst_identity(self) -> T {
self.0
}
+
+ /// Returns the inner value, but only if it contains no bound vars.
+ pub fn no_bound_vars(self) -> Option<T> {
+ if !self.0.needs_subst() { Some(self.0) } else { None }
+ }
}
///////////////////////////////////////////////////////////////////////////
@@ -771,13 +787,13 @@ struct SubstFolder<'a, 'tcx> {
binders_passed: u32,
}
-impl<'a, 'tcx> TypeFolder<'tcx> for SubstFolder<'a, 'tcx> {
+impl<'a, 'tcx> TypeFolder<TyCtxt<'tcx>> for SubstFolder<'a, 'tcx> {
#[inline]
- fn tcx<'b>(&'b self) -> TyCtxt<'tcx> {
+ fn interner(&self) -> TyCtxt<'tcx> {
self.tcx
}
- fn fold_binder<T: TypeFoldable<'tcx>>(
+ fn fold_binder<T: TypeFoldable<TyCtxt<'tcx>>>(
&mut self,
t: ty::Binder<'tcx, T>,
) -> ty::Binder<'tcx, T> {
@@ -970,7 +986,7 @@ impl<'a, 'tcx> SubstFolder<'a, 'tcx> {
/// As indicated in the diagram, here the same type `&'a i32` is substituted once, but in the
/// first case we do not increase the De Bruijn index and in the second case we do. The reason
/// is that only in the second case have we passed through a fn binder.
- fn shift_vars_through_binders<T: TypeFoldable<'tcx>>(&self, val: T) -> T {
+ fn shift_vars_through_binders<T: TypeFoldable<TyCtxt<'tcx>>>(&self, val: T) -> T {
debug!(
"shift_vars(val={:?}, binders_passed={:?}, has_escaping_bound_vars={:?})",
val,
@@ -982,7 +998,7 @@ impl<'a, 'tcx> SubstFolder<'a, 'tcx> {
return val;
}
- let result = ty::fold::shift_vars(TypeFolder::tcx(self), val, self.binders_passed);
+ let result = ty::fold::shift_vars(TypeFolder::interner(self), val, self.binders_passed);
debug!("shift_vars: shifted result = {:?}", result);
result
diff --git a/compiler/rustc_middle/src/ty/trait_def.rs b/compiler/rustc_middle/src/ty/trait_def.rs
index b38a5fbf2..233c0df2d 100644
--- a/compiler/rustc_middle/src/ty/trait_def.rs
+++ b/compiler/rustc_middle/src/ty/trait_def.rs
@@ -1,6 +1,6 @@
use crate::traits::specialization_graph;
use crate::ty::fast_reject::{self, SimplifiedType, TreatParams};
-use crate::ty::visit::TypeVisitable;
+use crate::ty::visit::TypeVisitableExt;
use crate::ty::{Ident, Ty, TyCtxt};
use hir::def_id::LOCAL_CRATE;
use rustc_hir as hir;
@@ -31,6 +31,15 @@ pub struct TraitDef {
/// and thus `impl`s of it are allowed to overlap.
pub is_marker: bool,
+ /// If `true`, then this trait has to `#[rustc_coinductive]` attribute or
+ /// is an auto trait. This indicates that trait solver cycles involving an
+ /// `X: ThisTrait` goal are accepted.
+ ///
+ /// In the future all traits should be coinductive, but we need a better
+ /// formal understanding of what exactly that means and should probably
+ /// also have already switched to the new trait solver.
+ pub is_coinductive: bool,
+
/// If `true`, then this trait has the `#[rustc_skip_array_during_method_dispatch]`
/// attribute, indicating that editions before 2021 should not consider this trait
/// during method dispatch if the receiver is an array.
@@ -81,28 +90,6 @@ impl TraitImpls {
}
impl<'tcx> TraitDef {
- pub fn new(
- def_id: DefId,
- unsafety: hir::Unsafety,
- paren_sugar: bool,
- has_auto_impl: bool,
- is_marker: bool,
- skip_array_during_method_dispatch: bool,
- specialization_kind: TraitSpecializationKind,
- must_implement_one_of: Option<Box<[Ident]>>,
- ) -> TraitDef {
- TraitDef {
- def_id,
- unsafety,
- paren_sugar,
- has_auto_impl,
- is_marker,
- skip_array_during_method_dispatch,
- specialization_kind,
- must_implement_one_of,
- }
- }
-
pub fn ancestors(
&self,
tcx: TyCtxt<'tcx>,
@@ -238,7 +225,7 @@ pub(super) fn trait_impls_of_provider(tcx: TyCtxt<'_>, trait_id: DefId) -> Trait
for &impl_def_id in tcx.hir().trait_impls(trait_id) {
let impl_def_id = impl_def_id.to_def_id();
- let impl_self_ty = tcx.type_of(impl_def_id);
+ let impl_self_ty = tcx.type_of(impl_def_id).subst_identity();
if impl_self_ty.references_error() {
continue;
}
diff --git a/compiler/rustc_middle/src/ty/typeck_results.rs b/compiler/rustc_middle/src/ty/typeck_results.rs
index 2902c6dc5..586958247 100644
--- a/compiler/rustc_middle/src/ty/typeck_results.rs
+++ b/compiler/rustc_middle/src/ty/typeck_results.rs
@@ -1,6 +1,7 @@
use crate::{
hir::place::Place as HirPlace,
infer::canonical::Canonical,
+ traits::ObligationCause,
ty::{
self, tls, BindingMode, BoundVar, CanonicalPolyFnSig, ClosureSizeProfileData,
GenericArgKind, InternalSubsts, SubstsRef, Ty, UserSubsts,
@@ -193,6 +194,11 @@ pub struct TypeckResults<'tcx> {
/// that are live across the yield of this generator (if a generator).
pub generator_interior_types: ty::Binder<'tcx, Vec<GeneratorInteriorTypeCause<'tcx>>>,
+ /// Stores the predicates that apply on generator witness types.
+ /// formatting modified file tests/ui/generator/retain-resume-ref.rs
+ pub generator_interior_predicates:
+ FxHashMap<LocalDefId, Vec<(ty::Predicate<'tcx>, ObligationCause<'tcx>)>>,
+
/// We sometimes treat byte string literals (which are of type `&[u8; N]`)
/// as `&[u8]`, depending on the pattern in which they are used.
/// This hashset records all instances where we behave
@@ -271,6 +277,7 @@ impl<'tcx> TypeckResults<'tcx> {
closure_fake_reads: Default::default(),
rvalue_scopes: Default::default(),
generator_interior_types: ty::Binder::dummy(Default::default()),
+ generator_interior_predicates: Default::default(),
treat_byte_string_as_slice: Default::default(),
closure_size_eval: Default::default(),
}
@@ -365,7 +372,7 @@ impl<'tcx> TypeckResults<'tcx> {
pub fn node_type(&self, id: hir::HirId) -> Ty<'tcx> {
self.node_type_opt(id).unwrap_or_else(|| {
- bug!("node_type: no type for node `{}`", tls::with(|tcx| tcx.hir().node_to_string(id)))
+ bug!("node_type: no type for node {}", tls::with(|tcx| tcx.hir().node_to_string(id)))
})
}
@@ -544,9 +551,8 @@ fn validate_hir_id_for_typeck_results(hir_owner: OwnerId, hir_id: hir::HirId) {
fn invalid_hir_id_for_typeck_results(hir_owner: OwnerId, hir_id: hir::HirId) {
ty::tls::with(|tcx| {
bug!(
- "node {} with HirId::owner {:?} cannot be placed in TypeckResults with hir_owner {:?}",
+ "node {} cannot be placed in TypeckResults with hir_owner {:?}",
tcx.hir().node_to_string(hir_id),
- hir_id.owner,
hir_owner
)
});
@@ -563,7 +569,7 @@ impl<'a, V> LocalTableInContext<'a, V> {
self.data.contains_key(&id.local_id)
}
- pub fn get(&self, id: hir::HirId) -> Option<&V> {
+ pub fn get(&self, id: hir::HirId) -> Option<&'a V> {
validate_hir_id_for_typeck_results(self.hir_owner, id);
self.data.get(&id.local_id)
}
diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs
index d0d1dcc58..90270e0ee 100644
--- a/compiler/rustc_middle/src/ty/util.rs
+++ b/compiler/rustc_middle/src/ty/util.rs
@@ -3,10 +3,9 @@
use crate::middle::codegen_fn_attrs::CodegenFnAttrFlags;
use crate::mir;
use crate::ty::layout::IntegerExt;
-use crate::ty::query::TyCtxtAt;
use crate::ty::{
- self, DefIdTree, FallibleTypeFolder, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable,
- TypeVisitable,
+ self, DefIdTree, FallibleTypeFolder, ToPredicate, Ty, TyCtxt, TypeFoldable, TypeFolder,
+ TypeSuperFoldable, TypeVisitableExt,
};
use crate::ty::{GenericArgKind, SubstsRef};
use rustc_apfloat::Float as _;
@@ -168,7 +167,7 @@ impl<'tcx> TyCtxt<'tcx> {
| DefKind::Fn
| DefKind::AssocFn
| DefKind::AssocConst
- | DefKind::Impl,
+ | DefKind::Impl { .. },
def_id,
) => Some(def_id),
Res::Err => None,
@@ -363,7 +362,7 @@ impl<'tcx> TyCtxt<'tcx> {
let drop_trait = self.lang_items().drop_trait()?;
self.ensure().coherent_trait(drop_trait);
- let ty = self.type_of(adt_did);
+ let ty = self.type_of(adt_did).subst_identity();
let (did, constness) = self.find_map_relevant_impl(drop_trait, ty, |impl_did| {
if let Some(item_id) = self.associated_item_def_ids(impl_did).first() {
if validate(self, impl_did).is_ok() {
@@ -416,12 +415,12 @@ impl<'tcx> TyCtxt<'tcx> {
// <P1, P2, P0>, and then look up which of the impl substs refer to
// parameters marked as pure.
- let impl_substs = match *self.type_of(impl_def_id).kind() {
+ let impl_substs = match *self.type_of(impl_def_id).subst_identity().kind() {
ty::Adt(def_, substs) if def_ == def => substs,
_ => bug!(),
};
- let item_substs = match *self.type_of(def.did()).kind() {
+ let item_substs = match *self.type_of(def.did()).subst_identity().kind() {
ty::Adt(def_, substs) if def_ == def => substs,
_ => bug!(),
};
@@ -565,14 +564,14 @@ impl<'tcx> TyCtxt<'tcx> {
self,
closure_def_id: DefId,
closure_substs: SubstsRef<'tcx>,
- env_region: ty::RegionKind<'tcx>,
+ env_region: ty::Region<'tcx>,
) -> Option<Ty<'tcx>> {
let closure_ty = self.mk_closure(closure_def_id, closure_substs);
let closure_kind_ty = closure_substs.as_closure().kind_ty();
let closure_kind = closure_kind_ty.to_opt_closure_kind()?;
let env_ty = match closure_kind {
- ty::ClosureKind::Fn => self.mk_imm_ref(self.mk_region(env_region), closure_ty),
- ty::ClosureKind::FnMut => self.mk_mut_ref(self.mk_region(env_region), closure_ty),
+ ty::ClosureKind::Fn => self.mk_imm_ref(env_region, closure_ty),
+ ty::ClosureKind::FnMut => self.mk_mut_ref(env_region, closure_ty),
ty::ClosureKind::FnOnce => closure_ty,
};
Some(env_ty)
@@ -603,7 +602,10 @@ impl<'tcx> TyCtxt<'tcx> {
/// Get the type of the pointer to the static that we use in MIR.
pub fn static_ptr_ty(self, def_id: DefId) -> Ty<'tcx> {
// Make sure that any constants in the static's type are evaluated.
- let static_ty = self.normalize_erasing_regions(ty::ParamEnv::empty(), self.type_of(def_id));
+ let static_ty = self.normalize_erasing_regions(
+ ty::ParamEnv::empty(),
+ self.type_of(def_id).subst_identity(),
+ );
// Make sure that accesses to unsafe statics end up using raw pointers.
// For thread-locals, this needs to be kept in sync with `Rvalue::ty`.
@@ -616,6 +618,36 @@ impl<'tcx> TyCtxt<'tcx> {
}
}
+ /// Return the set of types that should be taken into accound when checking
+ /// trait bounds on a generator's internal state.
+ pub fn generator_hidden_types(
+ self,
+ def_id: DefId,
+ ) -> impl Iterator<Item = ty::EarlyBinder<Ty<'tcx>>> {
+ let generator_layout = &self.mir_generator_witnesses(def_id);
+ generator_layout
+ .field_tys
+ .iter()
+ .filter(|decl| !decl.ignore_for_traits)
+ .map(|decl| ty::EarlyBinder(decl.ty))
+ }
+
+ /// Normalizes all opaque types in the given value, replacing them
+ /// with their underlying types.
+ pub fn expand_opaque_types(self, val: Ty<'tcx>) -> Ty<'tcx> {
+ let mut visitor = OpaqueTypeExpander {
+ seen_opaque_tys: FxHashSet::default(),
+ expanded_cache: FxHashMap::default(),
+ primary_def_id: None,
+ found_recursion: false,
+ found_any_recursion: false,
+ check_recursion: false,
+ expand_generators: false,
+ tcx: self,
+ };
+ val.fold_with(&mut visitor)
+ }
+
/// Expands the given impl trait type, stopping if the type is recursive.
#[instrument(skip(self), level = "debug", ret)]
pub fn try_expand_impl_trait_type(
@@ -630,6 +662,7 @@ impl<'tcx> TyCtxt<'tcx> {
found_recursion: false,
found_any_recursion: false,
check_recursion: true,
+ expand_generators: true,
tcx: self,
};
@@ -637,10 +670,6 @@ impl<'tcx> TyCtxt<'tcx> {
if visitor.found_recursion { Err(expanded_type) } else { Ok(expanded_type) }
}
- pub fn bound_type_of(self, def_id: DefId) -> ty::EarlyBinder<Ty<'tcx>> {
- ty::EarlyBinder(self.type_of(def_id))
- }
-
pub fn bound_return_position_impl_trait_in_trait_tys(
self,
def_id: DefId,
@@ -648,10 +677,6 @@ impl<'tcx> TyCtxt<'tcx> {
ty::EarlyBinder(self.collect_return_position_impl_trait_in_trait_tys(def_id))
}
- pub fn bound_fn_sig(self, def_id: DefId) -> ty::EarlyBinder<ty::PolyFnSig<'tcx>> {
- ty::EarlyBinder(self.fn_sig(def_id))
- }
-
pub fn bound_explicit_item_bounds(
self,
def_id: DefId,
@@ -736,11 +761,39 @@ impl<'tcx> TyCtxt<'tcx> {
}
(generator_layout, generator_saved_local_names)
}
-}
-impl<'tcx> TyCtxtAt<'tcx> {
- pub fn bound_type_of(self, def_id: DefId) -> ty::EarlyBinder<Ty<'tcx>> {
- ty::EarlyBinder(self.type_of(def_id))
+ /// Query and get an English description for the item's kind.
+ pub fn def_descr(self, def_id: DefId) -> &'static str {
+ self.def_kind_descr(self.def_kind(def_id), def_id)
+ }
+
+ /// Get an English description for the item's kind.
+ pub fn def_kind_descr(self, def_kind: DefKind, def_id: DefId) -> &'static str {
+ match def_kind {
+ DefKind::AssocFn if self.associated_item(def_id).fn_has_self_parameter => "method",
+ DefKind::Generator => match self.generator_kind(def_id).unwrap() {
+ rustc_hir::GeneratorKind::Async(..) => "async closure",
+ rustc_hir::GeneratorKind::Gen => "generator",
+ },
+ _ => def_kind.descr(def_id),
+ }
+ }
+
+ /// Gets an English article for the [`TyCtxt::def_descr`].
+ pub fn def_descr_article(self, def_id: DefId) -> &'static str {
+ self.def_kind_descr_article(self.def_kind(def_id), def_id)
+ }
+
+ /// Gets an English article for the [`TyCtxt::def_kind_descr`].
+ pub fn def_kind_descr_article(self, def_kind: DefKind, def_id: DefId) -> &'static str {
+ match def_kind {
+ DefKind::AssocFn if self.associated_item(def_id).fn_has_self_parameter => "a",
+ DefKind::Generator => match self.generator_kind(def_id).unwrap() {
+ rustc_hir::GeneratorKind::Async(..) => "an",
+ rustc_hir::GeneratorKind::Gen => "a",
+ },
+ _ => def_kind.article(),
+ }
}
}
@@ -756,6 +809,7 @@ struct OpaqueTypeExpander<'tcx> {
primary_def_id: Option<DefId>,
found_recursion: bool,
found_any_recursion: bool,
+ expand_generators: bool,
/// Whether or not to check for recursive opaque types.
/// This is `true` when we're explicitly checking for opaque type
/// recursion, and 'false' otherwise to avoid unnecessary work.
@@ -773,7 +827,7 @@ impl<'tcx> OpaqueTypeExpander<'tcx> {
let expanded_ty = match self.expanded_cache.get(&(def_id, substs)) {
Some(expanded_ty) => *expanded_ty,
None => {
- let generic_ty = self.tcx.bound_type_of(def_id);
+ let generic_ty = self.tcx.type_of(def_id);
let concrete_ty = generic_ty.subst(self.tcx, substs);
let expanded_ty = self.fold_ty(concrete_ty);
self.expanded_cache.insert((def_id, substs), expanded_ty);
@@ -792,20 +846,77 @@ impl<'tcx> OpaqueTypeExpander<'tcx> {
None
}
}
+
+ fn expand_generator(&mut self, def_id: DefId, substs: SubstsRef<'tcx>) -> Option<Ty<'tcx>> {
+ if self.found_any_recursion {
+ return None;
+ }
+ let substs = substs.fold_with(self);
+ if !self.check_recursion || self.seen_opaque_tys.insert(def_id) {
+ let expanded_ty = match self.expanded_cache.get(&(def_id, substs)) {
+ Some(expanded_ty) => *expanded_ty,
+ None => {
+ for bty in self.tcx.generator_hidden_types(def_id) {
+ let hidden_ty = bty.subst(self.tcx, substs);
+ self.fold_ty(hidden_ty);
+ }
+ let expanded_ty = self.tcx.mk_generator_witness_mir(def_id, substs);
+ self.expanded_cache.insert((def_id, substs), expanded_ty);
+ expanded_ty
+ }
+ };
+ if self.check_recursion {
+ self.seen_opaque_tys.remove(&def_id);
+ }
+ Some(expanded_ty)
+ } else {
+ // If another opaque type that we contain is recursive, then it
+ // will report the error, so we don't have to.
+ self.found_any_recursion = true;
+ self.found_recursion = def_id == *self.primary_def_id.as_ref().unwrap();
+ None
+ }
+ }
}
-impl<'tcx> TypeFolder<'tcx> for OpaqueTypeExpander<'tcx> {
- fn tcx(&self) -> TyCtxt<'tcx> {
+impl<'tcx> TypeFolder<TyCtxt<'tcx>> for OpaqueTypeExpander<'tcx> {
+ fn interner(&self) -> TyCtxt<'tcx> {
self.tcx
}
fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
- if let ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. }) = *t.kind() {
+ let mut t = if let ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. }) = *t.kind() {
self.expand_opaque_ty(def_id, substs).unwrap_or(t)
- } else if t.has_opaque_types() {
+ } else if t.has_opaque_types() || t.has_generators() {
t.super_fold_with(self)
} else {
t
+ };
+ if self.expand_generators {
+ if let ty::GeneratorWitnessMIR(def_id, substs) = *t.kind() {
+ t = self.expand_generator(def_id, substs).unwrap_or(t);
+ }
+ }
+ t
+ }
+
+ fn fold_predicate(&mut self, p: ty::Predicate<'tcx>) -> ty::Predicate<'tcx> {
+ if let ty::PredicateKind::Clause(clause) = p.kind().skip_binder()
+ && let ty::Clause::Projection(projection_pred) = clause
+ {
+ p.kind()
+ .rebind(ty::ProjectionPredicate {
+ projection_ty: projection_pred.projection_ty.fold_with(self),
+ // Don't fold the term on the RHS of the projection predicate.
+ // This is because for default trait methods with RPITITs, we
+ // install a `NormalizesTo(Projection(RPITIT) -> Opaque(RPITIT))`
+ // predicate, which would trivially cause a cycle when we do
+ // anything that requires `ParamEnv::with_reveal_all_normalized`.
+ term: projection_pred.term,
+ })
+ .to_predicate(self.tcx)
+ } else {
+ p.super_fold_with(self)
}
}
}
@@ -911,6 +1022,7 @@ impl<'tcx> Ty<'tcx> {
| ty::Foreign(_)
| ty::Generator(..)
| ty::GeneratorWitness(_)
+ | ty::GeneratorWitnessMIR(..)
| ty::Infer(_)
| ty::Alias(..)
| ty::Param(_)
@@ -950,6 +1062,7 @@ impl<'tcx> Ty<'tcx> {
| ty::Foreign(_)
| ty::Generator(..)
| ty::GeneratorWitness(_)
+ | ty::GeneratorWitnessMIR(..)
| ty::Infer(_)
| ty::Alias(..)
| ty::Param(_)
@@ -1077,7 +1190,10 @@ impl<'tcx> Ty<'tcx> {
false
}
- ty::Foreign(_) | ty::GeneratorWitness(..) | ty::Error(_) => false,
+ ty::Foreign(_)
+ | ty::GeneratorWitness(..)
+ | ty::GeneratorWitnessMIR(..)
+ | ty::Error(_) => false,
}
}
@@ -1173,6 +1289,7 @@ pub fn needs_drop_components<'tcx>(
| ty::FnPtr(_)
| ty::Char
| ty::GeneratorWitness(..)
+ | ty::GeneratorWitnessMIR(..)
| ty::RawPtr(_)
| ty::Ref(..)
| ty::Str => Ok(SmallVec::new()),
@@ -1243,7 +1360,11 @@ pub fn is_trivially_const_drop(ty: Ty<'_>) -> bool {
// Not trivial because they have components, and instead of looking inside,
// we'll just perform trait selection.
- ty::Closure(..) | ty::Generator(..) | ty::GeneratorWitness(_) | ty::Adt(..) => false,
+ ty::Closure(..)
+ | ty::Generator(..)
+ | ty::GeneratorWitness(_)
+ | ty::GeneratorWitnessMIR(..)
+ | ty::Adt(..) => false,
ty::Array(ty, _) | ty::Slice(ty) => is_trivially_const_drop(ty),
@@ -1262,8 +1383,8 @@ pub fn fold_list<'tcx, F, T>(
intern: impl FnOnce(TyCtxt<'tcx>, &[T]) -> &'tcx ty::List<T>,
) -> Result<&'tcx ty::List<T>, F::Error>
where
- F: FallibleTypeFolder<'tcx>,
- T: TypeFoldable<'tcx> + PartialEq + Copy,
+ F: FallibleTypeFolder<TyCtxt<'tcx>>,
+ T: TypeFoldable<TyCtxt<'tcx>> + PartialEq + Copy,
{
let mut iter = list.iter();
// Look for the first element that changed
@@ -1279,7 +1400,7 @@ where
for t in iter {
new_list.push(t.try_fold_with(folder)?)
}
- Ok(intern(folder.tcx(), &new_list))
+ Ok(intern(folder.interner(), &new_list))
}
Some((_, Err(err))) => {
return Err(err);
@@ -1304,13 +1425,15 @@ pub fn reveal_opaque_types_in_bounds<'tcx>(
found_recursion: false,
found_any_recursion: false,
check_recursion: false,
+ expand_generators: false,
tcx,
};
val.fold_with(&mut visitor)
}
/// Determines whether an item is annotated with `doc(hidden)`.
-pub fn is_doc_hidden(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
+fn is_doc_hidden(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
+ assert!(def_id.is_local());
tcx.get_attrs(def_id, sym::doc)
.filter_map(|attr| attr.meta_item_list())
.any(|items| items.iter().any(|item| item.has_name(sym::hidden)))
@@ -1325,7 +1448,7 @@ pub fn is_doc_notable_trait(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
/// Determines whether an item is an intrinsic by Abi.
pub fn is_intrinsic(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
- matches!(tcx.fn_sig(def_id).abi(), Abi::RustIntrinsic | Abi::PlatformIntrinsic)
+ matches!(tcx.fn_sig(def_id).skip_binder().abi(), Abi::RustIntrinsic | Abi::PlatformIntrinsic)
}
pub fn provide(providers: &mut ty::query::Providers) {
diff --git a/compiler/rustc_middle/src/ty/visit.rs b/compiler/rustc_middle/src/ty/visit.rs
index bee3cc4d7..6814cadb9 100644
--- a/compiler/rustc_middle/src/ty/visit.rs
+++ b/compiler/rustc_middle/src/ty/visit.rs
@@ -1,69 +1,13 @@
-//! A visiting traversal mechanism for complex data structures that contain type
-//! information.
-//!
-//! This is a read-only traversal of the data structure.
-//!
-//! This traversal has limited flexibility. Only a small number of "types of
-//! interest" within the complex data structures can receive custom
-//! visitation. These are the ones containing the most important type-related
-//! information, such as `Ty`, `Predicate`, `Region`, and `Const`.
-//!
-//! There are three groups of traits involved in each traversal.
-//! - `TypeVisitable`. This is implemented once for many types, including:
-//! - Types of interest, for which the methods delegate to the visitor.
-//! - All other types, including generic containers like `Vec` and `Option`.
-//! It defines a "skeleton" of how they should be visited.
-//! - `TypeSuperVisitable`. This is implemented only for each type of interest,
-//! and defines the visiting "skeleton" for these types.
-//! - `TypeVisitor`. This is implemented for each visitor. This defines how
-//! types of interest are visited.
-//!
-//! This means each visit is a mixture of (a) generic visiting operations, and (b)
-//! custom visit operations that are specific to the visitor.
-//! - The `TypeVisitable` impls handle most of the traversal, and call into
-//! `TypeVisitor` when they encounter a type of interest.
-//! - A `TypeVisitor` may call into another `TypeVisitable` impl, because some of
-//! the types of interest are recursive and can contain other types of interest.
-//! - A `TypeVisitor` may also call into a `TypeSuperVisitable` impl, because each
-//! visitor might provide custom handling only for some types of interest, or
-//! only for some variants of each type of interest, and then use default
-//! traversal for the remaining cases.
-//!
-//! For example, if you have `struct S(Ty, U)` where `S: TypeVisitable` and `U:
-//! TypeVisitable`, and an instance `s = S(ty, u)`, it would be visited like so:
-//! ```text
-//! s.visit_with(visitor) calls
-//! - ty.visit_with(visitor) calls
-//! - visitor.visit_ty(ty) may call
-//! - ty.super_visit_with(visitor)
-//! - u.visit_with(visitor)
-//! ```
use crate::ty::{self, flags::FlagComputation, Binder, Ty, TyCtxt, TypeFlags};
use rustc_errors::ErrorGuaranteed;
use rustc_data_structures::fx::FxHashSet;
use rustc_data_structures::sso::SsoHashSet;
-use std::fmt;
use std::ops::ControlFlow;
-/// This trait is implemented for every type that can be visited,
-/// providing the skeleton of the traversal.
-///
-/// To implement this conveniently, use the derive macro located in
-/// `rustc_macros`.
-pub trait TypeVisitable<'tcx>: fmt::Debug + Clone {
- /// The entry point for visiting. To visit a value `t` with a visitor `v`
- /// call: `t.visit_with(v)`.
- ///
- /// For most types, this just traverses the value, calling `visit_with` on
- /// each field/element.
- ///
- /// For types of interest (such as `Ty`), the implementation of this method
- /// that calls a visitor method specifically for that type (such as
- /// `V::visit_ty`). This is where control transfers from `TypeFoldable` to
- /// `TypeVisitor`.
- fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy>;
+pub use rustc_type_ir::visit::{TypeSuperVisitable, TypeVisitable, TypeVisitor};
+pub trait TypeVisitableExt<'tcx>: TypeVisitable<TyCtxt<'tcx>> {
/// Returns `true` if `self` has any late-bound regions that are either
/// bound by `binder` or bound by some binder outside of `binder`.
/// If `binder` is `ty::INNERMOST`, this indicates whether
@@ -100,6 +44,9 @@ pub trait TypeVisitable<'tcx>: fmt::Debug + Clone {
fn has_opaque_types(&self) -> bool {
self.has_type_flags(TypeFlags::HAS_TY_OPAQUE)
}
+ fn has_generators(&self) -> bool {
+ self.has_type_flags(TypeFlags::HAS_TY_GENERATOR)
+ }
fn references_error(&self) -> bool {
self.has_type_flags(TypeFlags::HAS_ERROR)
}
@@ -182,45 +129,7 @@ pub trait TypeVisitable<'tcx>: fmt::Debug + Clone {
}
}
-pub trait TypeSuperVisitable<'tcx>: TypeVisitable<'tcx> {
- /// Provides a default visit for a type of interest. This should only be
- /// called within `TypeVisitor` methods, when a non-custom traversal is
- /// desired for the value of the type of interest passed to that method.
- /// For example, in `MyVisitor::visit_ty(ty)`, it is valid to call
- /// `ty.super_visit_with(self)`, but any other visiting should be done
- /// with `xyz.visit_with(self)`.
- fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy>;
-}
-
-/// This trait is implemented for every visiting traversal. There is a visit
-/// method defined for every type of interest. Each such method has a default
-/// that recurses into the type's fields in a non-custom fashion.
-pub trait TypeVisitor<'tcx>: Sized {
- type BreakTy = !;
-
- fn visit_binder<T: TypeVisitable<'tcx>>(
- &mut self,
- t: &Binder<'tcx, T>,
- ) -> ControlFlow<Self::BreakTy> {
- t.super_visit_with(self)
- }
-
- fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
- t.super_visit_with(self)
- }
-
- fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> {
- r.super_visit_with(self)
- }
-
- fn visit_const(&mut self, c: ty::Const<'tcx>) -> ControlFlow<Self::BreakTy> {
- c.super_visit_with(self)
- }
-
- fn visit_predicate(&mut self, p: ty::Predicate<'tcx>) -> ControlFlow<Self::BreakTy> {
- p.super_visit_with(self)
- }
-}
+impl<'tcx, T: TypeVisitable<TyCtxt<'tcx>>> TypeVisitableExt<'tcx> for T {}
///////////////////////////////////////////////////////////////////////////
// Region folder
@@ -229,7 +138,7 @@ impl<'tcx> TyCtxt<'tcx> {
/// Invoke `callback` on every region appearing free in `value`.
pub fn for_each_free_region(
self,
- value: &impl TypeVisitable<'tcx>,
+ value: &impl TypeVisitable<TyCtxt<'tcx>>,
mut callback: impl FnMut(ty::Region<'tcx>),
) {
self.any_free_region_meets(value, |r| {
@@ -241,7 +150,7 @@ impl<'tcx> TyCtxt<'tcx> {
/// Returns `true` if `callback` returns true for every region appearing free in `value`.
pub fn all_free_regions_meet(
self,
- value: &impl TypeVisitable<'tcx>,
+ value: &impl TypeVisitable<TyCtxt<'tcx>>,
mut callback: impl FnMut(ty::Region<'tcx>) -> bool,
) -> bool {
!self.any_free_region_meets(value, |r| !callback(r))
@@ -250,7 +159,7 @@ impl<'tcx> TyCtxt<'tcx> {
/// Returns `true` if `callback` returns true for some region appearing free in `value`.
pub fn any_free_region_meets(
self,
- value: &impl TypeVisitable<'tcx>,
+ value: &impl TypeVisitable<TyCtxt<'tcx>>,
callback: impl FnMut(ty::Region<'tcx>) -> bool,
) -> bool {
struct RegionVisitor<F> {
@@ -275,13 +184,13 @@ impl<'tcx> TyCtxt<'tcx> {
callback: F,
}
- impl<'tcx, F> TypeVisitor<'tcx> for RegionVisitor<F>
+ impl<'tcx, F> TypeVisitor<TyCtxt<'tcx>> for RegionVisitor<F>
where
F: FnMut(ty::Region<'tcx>) -> bool,
{
type BreakTy = ();
- fn visit_binder<T: TypeVisitable<'tcx>>(
+ fn visit_binder<T: TypeVisitable<TyCtxt<'tcx>>>(
&mut self,
t: &Binder<'tcx, T>,
) -> ControlFlow<Self::BreakTy> {
@@ -328,7 +237,7 @@ impl<'tcx> TyCtxt<'tcx> {
value: &Binder<'tcx, T>,
) -> FxHashSet<ty::BoundRegionKind>
where
- T: TypeVisitable<'tcx>,
+ T: TypeVisitable<TyCtxt<'tcx>>,
{
self.collect_late_bound_regions(value, true)
}
@@ -339,7 +248,7 @@ impl<'tcx> TyCtxt<'tcx> {
value: &Binder<'tcx, T>,
) -> FxHashSet<ty::BoundRegionKind>
where
- T: TypeVisitable<'tcx>,
+ T: TypeVisitable<TyCtxt<'tcx>>,
{
self.collect_late_bound_regions(value, false)
}
@@ -350,7 +259,7 @@ impl<'tcx> TyCtxt<'tcx> {
just_constraint: bool,
) -> FxHashSet<ty::BoundRegionKind>
where
- T: TypeVisitable<'tcx>,
+ T: TypeVisitable<TyCtxt<'tcx>>,
{
let mut collector = LateBoundRegionsCollector::new(just_constraint);
let result = value.as_ref().skip_binder().visit_with(&mut collector);
@@ -377,10 +286,10 @@ impl<'tcx> ValidateBoundVars<'tcx> {
}
}
-impl<'tcx> TypeVisitor<'tcx> for ValidateBoundVars<'tcx> {
+impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for ValidateBoundVars<'tcx> {
type BreakTy = ();
- fn visit_binder<T: TypeVisitable<'tcx>>(
+ fn visit_binder<T: TypeVisitable<TyCtxt<'tcx>>>(
&mut self,
t: &Binder<'tcx, T>,
) -> ControlFlow<Self::BreakTy> {
@@ -489,10 +398,10 @@ struct HasEscapingVarsVisitor {
outer_index: ty::DebruijnIndex,
}
-impl<'tcx> TypeVisitor<'tcx> for HasEscapingVarsVisitor {
+impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for HasEscapingVarsVisitor {
type BreakTy = FoundEscapingVars;
- fn visit_binder<T: TypeVisitable<'tcx>>(
+ fn visit_binder<T: TypeVisitable<TyCtxt<'tcx>>>(
&mut self,
t: &Binder<'tcx, T>,
) -> ControlFlow<Self::BreakTy> {
@@ -566,7 +475,7 @@ impl std::fmt::Debug for HasTypeFlagsVisitor {
}
}
-impl<'tcx> TypeVisitor<'tcx> for HasTypeFlagsVisitor {
+impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for HasTypeFlagsVisitor {
type BreakTy = FoundFlags;
#[inline]
@@ -636,8 +545,8 @@ impl LateBoundRegionsCollector {
}
}
-impl<'tcx> TypeVisitor<'tcx> for LateBoundRegionsCollector {
- fn visit_binder<T: TypeVisitable<'tcx>>(
+impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for LateBoundRegionsCollector {
+ fn visit_binder<T: TypeVisitable<TyCtxt<'tcx>>>(
&mut self,
t: &Binder<'tcx, T>,
) -> ControlFlow<Self::BreakTy> {
@@ -698,7 +607,7 @@ impl MaxUniverse {
}
}
-impl<'tcx> TypeVisitor<'tcx> for MaxUniverse {
+impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for MaxUniverse {
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
if let ty::Placeholder(placeholder) = t.kind() {
self.max_universe = ty::UniverseIndex::from_u32(
diff --git a/compiler/rustc_middle/src/ty/vtable.rs b/compiler/rustc_middle/src/ty/vtable.rs
index f77bd9f0c..b9b1cd73a 100644
--- a/compiler/rustc_middle/src/ty/vtable.rs
+++ b/compiler/rustc_middle/src/ty/vtable.rs
@@ -112,5 +112,5 @@ pub(super) fn vtable_allocation_provider<'tcx>(
}
vtable.mutability = Mutability::Not;
- tcx.create_memory_alloc(tcx.intern_const_alloc(vtable))
+ tcx.create_memory_alloc(tcx.mk_const_alloc(vtable))
}
diff --git a/compiler/rustc_middle/src/ty/walk.rs b/compiler/rustc_middle/src/ty/walk.rs
index 708a5e4d0..182945b9c 100644
--- a/compiler/rustc_middle/src/ty/walk.rs
+++ b/compiler/rustc_middle/src/ty/walk.rs
@@ -190,6 +190,7 @@ fn push_inner<'tcx>(stack: &mut TypeWalkerStack<'tcx>, parent: GenericArg<'tcx>)
ty::Adt(_, substs)
| ty::Closure(_, substs)
| ty::Generator(_, substs, _)
+ | ty::GeneratorWitnessMIR(_, substs)
| ty::FnDef(_, substs) => {
stack.extend(substs.iter().rev());
}
diff --git a/compiler/rustc_middle/src/values.rs b/compiler/rustc_middle/src/values.rs
index 34e8a5597..c4f526dbd 100644
--- a/compiler/rustc_middle/src/values.rs
+++ b/compiler/rustc_middle/src/values.rs
@@ -2,7 +2,7 @@ use crate::dep_graph::DepKind;
use rustc_data_structures::fx::FxHashSet;
use rustc_errors::{pluralize, struct_span_err, Applicability, MultiSpan};
use rustc_hir as hir;
-use rustc_hir::def::DefKind;
+use rustc_hir::def::{DefKind, Res};
use rustc_middle::ty::Representability;
use rustc_middle::ty::{self, DefIdTree, Ty, TyCtxt};
use rustc_query_system::query::QueryInfo;
@@ -16,7 +16,7 @@ impl<'tcx> Value<TyCtxt<'tcx>, DepKind> for Ty<'_> {
fn from_cycle_error(tcx: TyCtxt<'tcx>, _: &[QueryInfo<DepKind>]) -> Self {
// SAFETY: This is never called when `Self` is not `Ty<'tcx>`.
// FIXME: Represent the above fact in the trait system somehow.
- unsafe { std::mem::transmute::<Ty<'tcx>, Ty<'_>>(tcx.ty_error()) }
+ unsafe { std::mem::transmute::<Ty<'tcx>, Ty<'_>>(tcx.ty_error_misc()) }
}
}
@@ -34,7 +34,7 @@ impl<'tcx> Value<TyCtxt<'tcx>, DepKind> for ty::SymbolName<'_> {
impl<'tcx> Value<TyCtxt<'tcx>, DepKind> for ty::Binder<'_, ty::FnSig<'_>> {
fn from_cycle_error(tcx: TyCtxt<'tcx>, stack: &[QueryInfo<DepKind>]) -> Self {
- let err = tcx.ty_error();
+ let err = tcx.ty_error_misc();
let arity = if let Some(frame) = stack.get(0)
&& frame.query.dep_kind == DepKind::fn_sig
@@ -199,7 +199,8 @@ fn find_item_ty_spans(
) {
match ty.kind {
hir::TyKind::Path(hir::QPath::Resolved(_, path)) => {
- if let Some(def_id) = path.res.opt_def_id() {
+ if let Res::Def(kind, def_id) = path.res
+ && kind != DefKind::TyAlias {
let check_params = def_id.as_local().map_or(true, |def_id| {
if def_id == needle {
spans.push(ty.span);
diff --git a/compiler/rustc_mir_build/Cargo.toml b/compiler/rustc_mir_build/Cargo.toml
index 4ad3343d3..f24b165d7 100644
--- a/compiler/rustc_mir_build/Cargo.toml
+++ b/compiler/rustc_mir_build/Cargo.toml
@@ -11,7 +11,6 @@ tracing = "0.1"
either = "1"
rustc_middle = { path = "../rustc_middle" }
rustc_apfloat = { path = "../rustc_apfloat" }
-rustc_attr = { path = "../rustc_attr" }
rustc_data_structures = { path = "../rustc_data_structures" }
rustc_index = { path = "../rustc_index" }
rustc_errors = { path = "../rustc_errors" }
diff --git a/compiler/rustc_error_messages/locales/en-US/mir_build.ftl b/compiler/rustc_mir_build/locales/en-US.ftl
index 224855fff..93e7fb330 100644
--- a/compiler/rustc_error_messages/locales/en-US/mir_build.ftl
+++ b/compiler/rustc_mir_build/locales/en-US.ftl
@@ -299,10 +299,18 @@ mir_build_borrow_of_moved_value = borrow of moved value
.suggestion = borrow this binding in the pattern to avoid moving the value
mir_build_multiple_mut_borrows = cannot borrow value as mutable more than once at a time
- .label = first mutable borrow, by `{$name}`, occurs here
- .mutable_borrow = another mutable borrow, by `{$name_mut}`, occurs here
- .immutable_borrow = also borrowed as immutable, by `{$name_immut}`, here
- .moved = also moved into `{$name_moved}` here
+
+mir_build_already_borrowed = cannot borrow value as mutable because it is also borrowed as immutable
+
+mir_build_already_mut_borrowed = cannot borrow value as immutable because it is also borrowed as mutable
+
+mir_build_moved_while_borrowed = cannot move out of value because it is borrowed
+
+mir_build_mutable_borrow = value is mutably borrowed by `{$name}` here
+
+mir_build_borrow = value is borrowed by `{$name}` here
+
+mir_build_moved = value is moved into `{$name}` here
mir_build_union_pattern = cannot use unions in constant patterns
@@ -366,3 +374,9 @@ mir_build_suggest_let_else = you might want to use `let else` to handle the {$co
} matched
mir_build_suggest_attempted_int_lit = alternatively, you could prepend the pattern with an underscore to define a new named variable; identifiers cannot begin with digits
+
+
+mir_build_rustc_box_attribute_error = `#[rustc_box]` attribute used incorrectly
+ .attributes = no other attributes may be applied
+ .not_box = `#[rustc_box]` may only be applied to a `Box::new()` call
+ .missing_box = `#[rustc_box]` requires the `owned_box` lang item
diff --git a/compiler/rustc_mir_build/src/build/custom/parse/instruction.rs b/compiler/rustc_mir_build/src/build/custom/parse/instruction.rs
index 0bca02589..dbba529ae 100644
--- a/compiler/rustc_mir_build/src/build/custom/parse/instruction.rs
+++ b/compiler/rustc_mir_build/src/build/custom/parse/instruction.rs
@@ -18,6 +18,9 @@ impl<'tcx, 'body> ParseCtxt<'tcx, 'body> {
@call("mir_storage_dead", args) => {
Ok(StatementKind::StorageDead(self.parse_local(args[0])?))
},
+ @call("mir_deinit", args) => {
+ Ok(StatementKind::Deinit(Box::new(self.parse_place(args[0])?)))
+ },
@call("mir_retag", args) => {
Ok(StatementKind::Retag(RetagKind::Default, Box::new(self.parse_place(args[0])?)))
},
@@ -141,12 +144,29 @@ impl<'tcx, 'body> ParseCtxt<'tcx, 'body> {
fn parse_rvalue(&self, expr_id: ExprId) -> PResult<Rvalue<'tcx>> {
parse_by_kind!(self, expr_id, _, "rvalue",
@call("mir_discriminant", args) => self.parse_place(args[0]).map(Rvalue::Discriminant),
+ @call("mir_checked", args) => {
+ parse_by_kind!(self, args[0], _, "binary op",
+ ExprKind::Binary { op, lhs, rhs } => Ok(Rvalue::CheckedBinaryOp(
+ *op, Box::new((self.parse_operand(*lhs)?, self.parse_operand(*rhs)?))
+ )),
+ )
+ },
+ @call("mir_len", args) => Ok(Rvalue::Len(self.parse_place(args[0])?)),
ExprKind::Borrow { borrow_kind, arg } => Ok(
Rvalue::Ref(self.tcx.lifetimes.re_erased, *borrow_kind, self.parse_place(*arg)?)
),
ExprKind::AddressOf { mutability, arg } => Ok(
Rvalue::AddressOf(*mutability, self.parse_place(*arg)?)
),
+ ExprKind::Binary { op, lhs, rhs } => Ok(
+ Rvalue::BinaryOp(*op, Box::new((self.parse_operand(*lhs)?, self.parse_operand(*rhs)?)))
+ ),
+ ExprKind::Unary { op, arg } => Ok(
+ Rvalue::UnaryOp(*op, self.parse_operand(*arg)?)
+ ),
+ ExprKind::Repeat { value, count } => Ok(
+ Rvalue::Repeat(self.parse_operand(*value)?, *count)
+ ),
_ => self.parse_operand(expr_id).map(Rvalue::Use),
)
}
diff --git a/compiler/rustc_mir_build/src/build/expr/as_constant.rs b/compiler/rustc_mir_build/src/build/expr/as_constant.rs
index 1d96893c7..cfacb5ea3 100644
--- a/compiler/rustc_mir_build/src/build/expr/as_constant.rs
+++ b/compiler/rustc_mir_build/src/build/expr/as_constant.rs
@@ -55,7 +55,7 @@ pub fn as_constant_inner<'tcx>(
ConstantKind::Ty(tcx.const_error_with_guaranteed(ty, guar))
}
Err(LitToConstError::TypeError) => {
- bug!("encountered type error in `lit_to_mir_constant")
+ bug!("encountered type error in `lit_to_mir_constant`")
}
};
@@ -132,14 +132,14 @@ pub(crate) fn lit_to_mir_constant<'tcx>(
(ast::LitKind::Str(s, _), ty::Ref(_, inner_ty, _)) if inner_ty.is_str() => {
let s = s.as_str();
let allocation = Allocation::from_bytes_byte_aligned_immutable(s.as_bytes());
- let allocation = tcx.intern_const_alloc(allocation);
+ let allocation = tcx.mk_const_alloc(allocation);
ConstValue::Slice { data: allocation, start: 0, end: s.len() }
}
(ast::LitKind::ByteStr(data, _), ty::Ref(_, inner_ty, _))
if matches!(inner_ty.kind(), ty::Slice(_)) =>
{
let allocation = Allocation::from_bytes_byte_aligned_immutable(data as &[u8]);
- let allocation = tcx.intern_const_alloc(allocation);
+ let allocation = tcx.mk_const_alloc(allocation);
ConstValue::Slice { data: allocation, start: 0, end: data.len() }
}
(ast::LitKind::ByteStr(data, _), ty::Ref(_, inner_ty, _)) if inner_ty.is_array() => {
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 c621efb3b..ff3198847 100644
--- a/compiler/rustc_mir_build/src/build/expr/as_operand.rs
+++ b/compiler/rustc_mir_build/src/build/expr/as_operand.rs
@@ -170,7 +170,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
// Return the operand *tmp0 to be used as the call argument
let place = Place {
local: operand,
- projection: tcx.intern_place_elems(&[PlaceElem::Deref]),
+ projection: tcx.mk_place_elems(&[PlaceElem::Deref]),
};
return block.and(Operand::Move(place));
diff --git a/compiler/rustc_mir_build/src/build/expr/as_place.rs b/compiler/rustc_mir_build/src/build/expr/as_place.rs
index e22fa6365..33200b80a 100644
--- a/compiler/rustc_mir_build/src/build/expr/as_place.rs
+++ b/compiler/rustc_mir_build/src/build/expr/as_place.rs
@@ -11,7 +11,7 @@ use rustc_middle::mir::AssertKind::BoundsCheck;
use rustc_middle::mir::*;
use rustc_middle::thir::*;
use rustc_middle::ty::AdtDef;
-use rustc_middle::ty::{self, CanonicalUserTypeAnnotation, Ty, TyCtxt, Variance};
+use rustc_middle::ty::{self, CanonicalUserTypeAnnotation, Ty, Variance};
use rustc_span::Span;
use rustc_target::abi::VariantIdx;
@@ -183,7 +183,7 @@ fn to_upvars_resolved_place_builder<'tcx>(
&projection,
) else {
let closure_span = cx.tcx.def_span(closure_def_id);
- if !enable_precise_capture(cx.tcx, closure_span) {
+ if !enable_precise_capture(closure_span) {
bug!(
"No associated capture found for {:?}[{:#?}] even though \
capture_disjoint_fields isn't enabled",
@@ -263,7 +263,7 @@ impl<'tcx> PlaceBuilder<'tcx> {
let resolved = self.resolve_upvar(cx);
let builder = resolved.as_ref().unwrap_or(self);
let PlaceBase::Local(local) = builder.base else { return None };
- let projection = cx.tcx.intern_place_elems(&builder.projection);
+ let projection = cx.tcx.mk_place_elems(&builder.projection);
Some(Place { local, projection })
}
@@ -692,7 +692,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
tcx.mk_imm_ref(tcx.lifetimes.re_erased, fake_borrow_deref_ty);
let fake_borrow_temp =
self.local_decls.push(LocalDecl::new(fake_borrow_ty, expr_span));
- let projection = tcx.intern_place_elems(&base_place.projection[..idx]);
+ let projection = tcx.mk_place_elems(&base_place.projection[..idx]);
self.cfg.push_assign(
block,
source_info,
@@ -745,8 +745,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
}
}
-/// Precise capture is enabled if the feature gate `capture_disjoint_fields` is enabled or if
-/// user is using Rust Edition 2021 or higher.
-fn enable_precise_capture(tcx: TyCtxt<'_>, closure_span: Span) -> bool {
- tcx.features().capture_disjoint_fields || closure_span.rust_2021()
+/// Precise capture is enabled if user is using Rust Edition 2021 or higher.
+fn enable_precise_capture(closure_span: Span) -> bool {
+ closure_span.rust_2021()
}
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 c7b3eb44d..a4e48c154 100644
--- a/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs
+++ b/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs
@@ -55,7 +55,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
})
}
ExprKind::Repeat { value, count } => {
- if Some(0) == count.try_eval_usize(this.tcx, this.param_env) {
+ if Some(0) == count.try_eval_target_usize(this.tcx, this.param_env) {
this.build_zero_repeat(block, value, scope, source_info)
} else {
let value_operand = unpack!(
@@ -439,10 +439,14 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
// We implicitly set the discriminant to 0. See
// librustc_mir/transform/deaggregator.rs for details.
let movability = movability.unwrap();
- Box::new(AggregateKind::Generator(closure_id, substs, movability))
+ Box::new(AggregateKind::Generator(
+ closure_id.to_def_id(),
+ substs,
+ movability,
+ ))
}
UpvarSubsts::Closure(substs) => {
- Box::new(AggregateKind::Closure(closure_id, substs))
+ Box::new(AggregateKind::Closure(closure_id.to_def_id(), substs))
}
};
block.and(Rvalue::Aggregate(result, operands))
@@ -516,7 +520,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
let source_info = self.source_info(span);
let bool_ty = self.tcx.types.bool;
if self.check_overflow && op.is_checkable() && ty.is_integral() {
- let result_tup = self.tcx.intern_tup(&[ty, bool_ty]);
+ let result_tup = self.tcx.mk_tup(&[ty, bool_ty]);
let result_value = self.temp(result_tup, span);
self.cfg.push_assign(
diff --git a/compiler/rustc_mir_build/src/build/expr/as_temp.rs b/compiler/rustc_mir_build/src/build/expr/as_temp.rs
index 0ca4e3745..3d3cf7555 100644
--- a/compiler/rustc_mir_build/src/build/expr/as_temp.rs
+++ b/compiler/rustc_mir_build/src/build/expr/as_temp.rs
@@ -44,7 +44,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
let expr_ty = expr.ty;
let temp = {
let mut local_decl = LocalDecl::new(expr_ty, expr_span);
- if mutability == Mutability::Not {
+ if mutability.is_not() {
local_decl = local_decl.immutable();
}
diff --git a/compiler/rustc_mir_build/src/build/expr/into.rs b/compiler/rustc_mir_build/src/build/expr/into.rs
index 38b1fa91d..dac9bf0a8 100644
--- a/compiler/rustc_mir_build/src/build/expr/into.rs
+++ b/compiler/rustc_mir_build/src/build/expr/into.rs
@@ -319,7 +319,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
// See the notes for `ExprKind::Array` in `as_rvalue` and for
// `ExprKind::Borrow` above.
let is_union = adt_def.is_union();
- let active_field_index = if is_union { Some(fields[0].name.index()) } else { None };
+ let active_field_index = is_union.then(|| fields[0].name.index());
let scope = this.local_scope();
diff --git a/compiler/rustc_mir_build/src/build/matches/mod.rs b/compiler/rustc_mir_build/src/build/matches/mod.rs
index 0961ce11e..de2851a1a 100644
--- a/compiler/rustc_mir_build/src/build/matches/mod.rs
+++ b/compiler/rustc_mir_build/src/build/matches/mod.rs
@@ -1206,7 +1206,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
fake_borrows.insert(Place {
local: source.local,
- projection: self.tcx.intern_place_elems(proj_base),
+ projection: self.tcx.mk_place_elems(proj_base),
});
}
}
@@ -1743,12 +1743,14 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
.map(|matched_place_ref| {
let matched_place = Place {
local: matched_place_ref.local,
- projection: tcx.intern_place_elems(matched_place_ref.projection),
+ projection: tcx.mk_place_elems(matched_place_ref.projection),
};
let fake_borrow_deref_ty = matched_place.ty(&self.local_decls, tcx).ty;
let fake_borrow_ty = tcx.mk_imm_ref(tcx.lifetimes.re_erased, fake_borrow_deref_ty);
- let fake_borrow_temp =
- self.local_decls.push(LocalDecl::new(fake_borrow_ty, temp_span));
+ let mut fake_borrow_temp = LocalDecl::new(fake_borrow_ty, temp_span);
+ fake_borrow_temp.internal = self.local_decls[matched_place.local].internal;
+ fake_borrow_temp.local_info = Some(Box::new(LocalInfo::FakeBorrow));
+ let fake_borrow_temp = self.local_decls.push(fake_borrow_temp);
(matched_place, fake_borrow_temp)
})
diff --git a/compiler/rustc_mir_build/src/build/matches/test.rs b/compiler/rustc_mir_build/src/build/matches/test.rs
index ad7a568a2..2de89f67d 100644
--- a/compiler/rustc_mir_build/src/build/matches/test.rs
+++ b/compiler/rustc_mir_build/src/build/matches/test.rs
@@ -563,14 +563,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
let not_contained =
self.values_not_contained_in_range(&*range, options).unwrap_or(false);
- if not_contained {
+ not_contained.then(|| {
// No switch values are contained in the pattern range,
// so the pattern can be matched only if this test fails.
- let otherwise = options.len();
- Some(otherwise)
- } else {
- None
- }
+ options.len()
+ })
}
(&TestKind::SwitchInt { .. }, _) => None,
@@ -835,7 +832,7 @@ fn trait_method<'tcx>(
tcx: TyCtxt<'tcx>,
trait_def_id: DefId,
method_name: Symbol,
- substs: impl IntoIterator<Item = impl Into<GenericArg<'tcx>>>,
+ substs: impl IntoIterator<Item: Into<GenericArg<'tcx>>>,
) -> ConstantKind<'tcx> {
// The unhygienic comparison here is acceptable because this is only
// used on known traits.
diff --git a/compiler/rustc_mir_build/src/build/matches/util.rs b/compiler/rustc_mir_build/src/build/matches/util.rs
index cbd494862..c34105174 100644
--- a/compiler/rustc_mir_build/src/build/matches/util.rs
+++ b/compiler/rustc_mir_build/src/build/matches/util.rs
@@ -5,7 +5,7 @@ use crate::build::Builder;
use rustc_middle::mir::*;
use rustc_middle::thir::*;
use rustc_middle::ty;
-use rustc_middle::ty::TypeVisitable;
+use rustc_middle::ty::TypeVisitableExt;
use smallvec::SmallVec;
impl<'a, 'tcx> Builder<'a, 'tcx> {
@@ -35,7 +35,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
let tcx = self.tcx;
let (min_length, exact_size) = if let Some(place_resolved) = place.try_to_place(self) {
match place_resolved.ty(&self.local_decls, tcx).ty.kind() {
- ty::Array(_, length) => (length.eval_usize(tcx, self.param_env), true),
+ ty::Array(_, length) => (length.eval_target_usize(tcx, self.param_env), true),
_ => ((prefix.len() + suffix.len()).try_into().unwrap(), false),
}
} else {
diff --git a/compiler/rustc_mir_build/src/build/mod.rs b/compiler/rustc_mir_build/src/build/mod.rs
index 9daf68a15..b3f9d8282 100644
--- a/compiler/rustc_mir_build/src/build/mod.rs
+++ b/compiler/rustc_mir_build/src/build/mod.rs
@@ -20,7 +20,7 @@ use rustc_middle::mir::*;
use rustc_middle::thir::{
self, BindingMode, Expr, ExprId, LintLevel, LocalVarId, Param, ParamId, PatKind, Thir,
};
-use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitable, TypeckResults};
+use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt};
use rustc_span::symbol::sym;
use rustc_span::Span;
use rustc_span::Symbol;
@@ -47,8 +47,6 @@ pub(crate) fn mir_built(
/// Construct the MIR for a given `DefId`.
fn mir_build(tcx: TyCtxt<'_>, def: ty::WithOptConstParam<LocalDefId>) -> Body<'_> {
- let body_owner_kind = tcx.hir().body_owner_kind(def.did);
-
// 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
@@ -65,16 +63,15 @@ fn mir_build(tcx: TyCtxt<'_>, def: ty::WithOptConstParam<LocalDefId>) -> Body<'_
}
let body = match tcx.thir_body(def) {
- Err(error_reported) => construct_error(tcx, def.did, body_owner_kind, error_reported),
+ Err(error_reported) => construct_error(tcx, def.did, error_reported),
Ok((thir, expr)) => {
// We ran all queries that depended on THIR at the beginning
// of `mir_build`, so now we can steal it
let thir = thir.steal();
- if body_owner_kind.is_fn_or_closure() {
- construct_fn(tcx, def, &thir, expr)
- } else {
- construct_const(tcx, def, &thir, expr)
+ match thir.body_type {
+ thir::BodyTy::Fn(fn_sig) => construct_fn(tcx, def, &thir, expr, fn_sig),
+ thir::BodyTy::Const(ty) => construct_const(tcx, def, &thir, expr, ty),
}
}
};
@@ -158,13 +155,13 @@ struct BlockContext(Vec<BlockFrame>);
struct Builder<'a, 'tcx> {
tcx: TyCtxt<'tcx>,
infcx: InferCtxt<'tcx>,
- typeck_results: &'tcx TypeckResults<'tcx>,
region_scope_tree: &'tcx region::ScopeTree,
param_env: ty::ParamEnv<'tcx>,
thir: &'a Thir<'tcx>,
cfg: CFG<'tcx>,
+ def: ty::WithOptConstParam<LocalDefId>,
def_id: DefId,
hir_id: hir::HirId,
parent_module: DefId,
@@ -434,11 +431,16 @@ fn construct_fn<'tcx>(
fn_def: ty::WithOptConstParam<LocalDefId>,
thir: &Thir<'tcx>,
expr: ExprId,
+ fn_sig: ty::FnSig<'tcx>,
) -> Body<'tcx> {
let span = tcx.def_span(fn_def.did);
let fn_id = tcx.hir().local_def_id_to_hir_id(fn_def.did);
let generator_kind = tcx.generator_kind(fn_def.did);
+ // The representation of thir for `-Zunpretty=thir-tree` relies on
+ // the entry expression being the last element of `thir.exprs`.
+ assert_eq!(expr.as_usize(), thir.exprs.len() - 1);
+
// Figure out what primary body this item has.
let body_id = tcx.hir().body_owned_by(fn_def.did);
let span_with_body = tcx.hir().span_with_body(fn_id);
@@ -449,11 +451,6 @@ fn construct_fn<'tcx>(
.output
.span();
- // fetch the fully liberated fn signature (that is, all bound
- // types/lifetimes replaced)
- let typeck_results = tcx.typeck_opt_const_arg(fn_def);
- let fn_sig = typeck_results.liberated_fn_sigs()[fn_id];
-
let safety = match fn_sig.unsafety {
hir::Unsafety::Normal => Safety::Safe,
hir::Unsafety::Unsafe => Safety::FnUnsafe,
@@ -525,13 +522,7 @@ fn construct_fn<'tcx>(
let return_block =
unpack!(builder.in_breakable_scope(None, Place::return_place(), fn_end, |builder| {
Some(builder.in_scope(arg_scope_s, LintLevel::Inherited, |builder| {
- builder.args_and_body(
- START_BLOCK,
- fn_def.did,
- arguments,
- arg_scope,
- &thir[expr],
- )
+ builder.args_and_body(START_BLOCK, arguments, arg_scope, &thir[expr])
}))
}));
let source_info = builder.source_info(fn_end);
@@ -559,6 +550,7 @@ fn construct_const<'a, 'tcx>(
def: ty::WithOptConstParam<LocalDefId>,
thir: &'a Thir<'tcx>,
expr: ExprId,
+ const_ty: Ty<'tcx>,
) -> Body<'tcx> {
let hir_id = tcx.hir().local_def_id_to_hir_id(def.did);
@@ -582,20 +574,6 @@ fn construct_const<'a, 'tcx>(
_ => span_bug!(tcx.def_span(def.did), "can't build MIR for {:?}", def.did),
};
- // Get the revealed type of this const. This is *not* the adjusted
- // type of its body, which may be a subtype of this type. For
- // example:
- //
- // fn foo(_: &()) {}
- // static X: fn(&'static ()) = foo;
- //
- // The adjusted type of the body of X is `for<'a> fn(&'a ())` which
- // is not the same as the type of X. We need the type of the return
- // place to be the type of the constant because NLL typeck will
- // equate them.
- let typeck_results = tcx.typeck_opt_const_arg(def);
- let const_ty = typeck_results.node_type(hir_id);
-
let infcx = tcx.infer_ctxt().build();
let mut builder = Builder::new(
thir,
@@ -625,21 +603,17 @@ fn construct_const<'a, 'tcx>(
///
/// This is required because we may still want to run MIR passes on an item
/// with type errors, but normal MIR construction can't handle that in general.
-fn construct_error(
- tcx: TyCtxt<'_>,
- def: LocalDefId,
- body_owner_kind: hir::BodyOwnerKind,
- err: ErrorGuaranteed,
-) -> Body<'_> {
+fn construct_error(tcx: TyCtxt<'_>, def: LocalDefId, err: ErrorGuaranteed) -> Body<'_> {
let span = tcx.def_span(def);
let hir_id = tcx.hir().local_def_id_to_hir_id(def);
let generator_kind = tcx.generator_kind(def);
+ let body_owner_kind = tcx.hir().body_owner_kind(def);
- let ty = tcx.ty_error();
+ let ty = tcx.ty_error(err);
let num_params = match body_owner_kind {
- hir::BodyOwnerKind::Fn => tcx.fn_sig(def).inputs().skip_binder().len(),
+ hir::BodyOwnerKind::Fn => tcx.fn_sig(def).skip_binder().inputs().skip_binder().len(),
hir::BodyOwnerKind::Closure => {
- let ty = tcx.type_of(def);
+ let ty = tcx.type_of(def).subst_identity();
match ty.kind() {
ty::Closure(_, substs) => {
1 + substs.as_closure().sig().inputs().skip_binder().len()
@@ -724,9 +698,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
thir,
tcx,
infcx,
- typeck_results: tcx.typeck_opt_const_arg(def),
region_scope_tree: tcx.region_scope_tree(def.did),
param_env,
+ def,
def_id: def.did.to_def_id(),
hir_id,
parent_module: tcx.parent_module(hir_id).to_def_id(),
@@ -776,14 +750,78 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
self.var_debug_info,
self.fn_span,
self.generator_kind,
- self.typeck_results.tainted_by_errors,
+ None,
)
}
+ fn insert_upvar_arg(&mut self) {
+ let Some(closure_arg) = self.local_decls.get(ty::CAPTURE_STRUCT_LOCAL) else { return };
+
+ let mut closure_ty = closure_arg.ty;
+ let mut closure_env_projs = vec![];
+ if let ty::Ref(_, ty, _) = closure_ty.kind() {
+ closure_env_projs.push(ProjectionElem::Deref);
+ closure_ty = *ty;
+ }
+
+ let upvar_substs = match closure_ty.kind() {
+ ty::Closure(_, substs) => ty::UpvarSubsts::Closure(substs),
+ ty::Generator(_, substs, _) => ty::UpvarSubsts::Generator(substs),
+ _ => return,
+ };
+
+ // In analyze_closure() in upvar.rs we gathered a list of upvars used by an
+ // indexed closure and we stored in a map called closure_min_captures in TypeckResults
+ // with the closure's DefId. Here, we run through that vec of UpvarIds for
+ // the given closure and use the necessary information to create upvar
+ // debuginfo and to fill `self.upvars`.
+ let capture_tys = upvar_substs.upvar_tys();
+
+ let tcx = self.tcx;
+ self.upvars = tcx
+ .closure_captures(self.def.did)
+ .iter()
+ .zip(capture_tys)
+ .enumerate()
+ .map(|(i, (captured_place, ty))| {
+ let name = captured_place.to_symbol();
+
+ let capture = captured_place.info.capture_kind;
+ let var_id = match captured_place.place.base {
+ HirPlaceBase::Upvar(upvar_id) => upvar_id.var_path.hir_id,
+ _ => bug!("Expected an upvar"),
+ };
+
+ let mutability = captured_place.mutability;
+
+ let mut projs = closure_env_projs.clone();
+ projs.push(ProjectionElem::Field(Field::new(i), ty));
+ match capture {
+ ty::UpvarCapture::ByValue => {}
+ ty::UpvarCapture::ByRef(..) => {
+ projs.push(ProjectionElem::Deref);
+ }
+ };
+
+ let use_place = Place {
+ local: ty::CAPTURE_STRUCT_LOCAL,
+ projection: tcx.mk_place_elems(&projs),
+ };
+ self.var_debug_info.push(VarDebugInfo {
+ name,
+ source_info: SourceInfo::outermost(captured_place.var_ident.span),
+ value: VarDebugInfoContents::Place(use_place),
+ });
+
+ let capture = Capture { captured_place, use_place, mutability };
+ (var_id, capture)
+ })
+ .collect();
+ }
+
fn args_and_body(
&mut self,
mut block: BasicBlock,
- fn_def_id: LocalDefId,
arguments: &IndexVec<ParamId, Param<'tcx>>,
argument_scope: region::Scope,
expr: &Expr<'tcx>,
@@ -805,69 +843,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
}
}
- let tcx = self.tcx;
- let tcx_hir = tcx.hir();
- let hir_typeck_results = self.typeck_results;
-
- // In analyze_closure() in upvar.rs we gathered a list of upvars used by an
- // indexed closure and we stored in a map called closure_min_captures in TypeckResults
- // with the closure's DefId. Here, we run through that vec of UpvarIds for
- // the given closure and use the necessary information to create upvar
- // debuginfo and to fill `self.upvars`.
- if hir_typeck_results.closure_min_captures.get(&fn_def_id).is_some() {
- let mut closure_env_projs = vec![];
- let mut closure_ty = self.local_decls[ty::CAPTURE_STRUCT_LOCAL].ty;
- if let ty::Ref(_, ty, _) = closure_ty.kind() {
- closure_env_projs.push(ProjectionElem::Deref);
- closure_ty = *ty;
- }
- let upvar_substs = match closure_ty.kind() {
- ty::Closure(_, substs) => ty::UpvarSubsts::Closure(substs),
- ty::Generator(_, substs, _) => ty::UpvarSubsts::Generator(substs),
- _ => span_bug!(self.fn_span, "upvars with non-closure env ty {:?}", closure_ty),
- };
- let def_id = self.def_id.as_local().unwrap();
- let capture_syms = tcx.symbols_for_closure_captures((def_id, fn_def_id));
- let capture_tys = upvar_substs.upvar_tys();
- let captures_with_tys = hir_typeck_results
- .closure_min_captures_flattened(fn_def_id)
- .zip(capture_tys.zip(capture_syms));
-
- self.upvars = captures_with_tys
- .enumerate()
- .map(|(i, (captured_place, (ty, sym)))| {
- let capture = captured_place.info.capture_kind;
- let var_id = match captured_place.place.base {
- HirPlaceBase::Upvar(upvar_id) => upvar_id.var_path.hir_id,
- _ => bug!("Expected an upvar"),
- };
-
- let mutability = captured_place.mutability;
-
- let mut projs = closure_env_projs.clone();
- projs.push(ProjectionElem::Field(Field::new(i), ty));
- match capture {
- ty::UpvarCapture::ByValue => {}
- ty::UpvarCapture::ByRef(..) => {
- projs.push(ProjectionElem::Deref);
- }
- };
-
- let use_place = Place {
- local: ty::CAPTURE_STRUCT_LOCAL,
- projection: tcx.intern_place_elems(&projs),
- };
- self.var_debug_info.push(VarDebugInfo {
- name: *sym,
- source_info: SourceInfo::outermost(tcx_hir.span(var_id)),
- value: VarDebugInfoContents::Place(use_place),
- });
-
- let capture = Capture { captured_place, use_place, mutability };
- (var_id, capture)
- })
- .collect();
- }
+ self.insert_upvar_arg();
let mut scope = None;
// Bind the argument patterns
diff --git a/compiler/rustc_mir_build/src/errors.rs b/compiler/rustc_mir_build/src/errors.rs
index 7f81aef1c..dc4d2276e 100644
--- a/compiler/rustc_mir_build/src/errors.rs
+++ b/compiler/rustc_mir_build/src/errors.rs
@@ -1,9 +1,10 @@
-use crate::thir::pattern::deconstruct_pat::DeconstructedPat;
-use crate::thir::pattern::MatchCheckCtxt;
-use rustc_errors::Handler;
+use crate::{
+ fluent_generated as fluent,
+ thir::pattern::{deconstruct_pat::DeconstructedPat, MatchCheckCtxt},
+};
use rustc_errors::{
error_code, AddToDiagnostic, Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed,
- IntoDiagnostic, MultiSpan, SubdiagnosticMessage,
+ Handler, IntoDiagnostic, MultiSpan, SubdiagnosticMessage,
};
use rustc_hir::def::Res;
use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic};
@@ -358,7 +359,7 @@ impl<'a> IntoDiagnostic<'a> for NonExhaustivePatternsTypeNotEmpty<'_, '_, '_> {
fn into_diagnostic(self, handler: &'a Handler) -> DiagnosticBuilder<'_, ErrorGuaranteed> {
let mut diag = handler.struct_span_err_with_code(
self.span,
- rustc_errors::fluent::mir_build_non_exhaustive_patterns_type_not_empty,
+ fluent::mir_build_non_exhaustive_patterns_type_not_empty,
error_code!(E0004),
);
@@ -380,7 +381,7 @@ impl<'a> IntoDiagnostic<'a> for NonExhaustivePatternsTypeNotEmpty<'_, '_, '_> {
let mut span: MultiSpan = def_span.into();
span.push_span_label(def_span, "");
- diag.span_note(span, rustc_errors::fluent::def_note);
+ diag.span_note(span, fluent::mir_build_def_note);
}
let is_variant_list_non_exhaustive = match self.ty.kind() {
@@ -391,14 +392,14 @@ impl<'a> IntoDiagnostic<'a> for NonExhaustivePatternsTypeNotEmpty<'_, '_, '_> {
};
if is_variant_list_non_exhaustive {
- diag.note(rustc_errors::fluent::non_exhaustive_type_note);
+ diag.note(fluent::mir_build_non_exhaustive_type_note);
} else {
- diag.note(rustc_errors::fluent::type_note);
+ diag.note(fluent::mir_build_type_note);
}
if let ty::Ref(_, sub_ty, _) = self.ty.kind() {
if !sub_ty.is_inhabited_from(self.cx.tcx, self.cx.module, self.cx.param_env) {
- diag.note(rustc_errors::fluent::reference_note);
+ diag.note(fluent::mir_build_reference_note);
}
}
@@ -424,12 +425,12 @@ impl<'a> IntoDiagnostic<'a> for NonExhaustivePatternsTypeNotEmpty<'_, '_, '_> {
if let Some((span, sugg)) = suggestion {
diag.span_suggestion_verbose(
span,
- rustc_errors::fluent::suggestion,
+ fluent::mir_build_suggestion,
sugg,
Applicability::HasPlaceholders,
);
} else {
- diag.help(rustc_errors::fluent::help);
+ diag.help(fluent::mir_build_help);
}
diag
@@ -469,7 +470,7 @@ pub struct NonConstPath {
pub struct UnreachablePattern {
#[label]
pub span: Option<Span>,
- #[label(catchall_label)]
+ #[label(mir_build_catchall_label)]
pub catchall: Option<Span>,
}
@@ -493,7 +494,7 @@ pub struct LowerRangeBoundMustBeLessThanOrEqualToUpper {
#[primary_span]
#[label]
pub span: Span,
- #[note(teach_note)]
+ #[note(mir_build_teach_note)]
pub teach: Option<()>,
}
@@ -585,9 +586,9 @@ pub struct BorrowOfMovedValue<'tcx> {
#[primary_span]
pub span: Span,
#[label]
- #[label(occurs_because_label)]
+ #[label(mir_build_occurs_because_label)]
pub binding_span: Span,
- #[label(value_borrowed_label)]
+ #[label(mir_build_value_borrowed_label)]
pub conflicts_ref: Vec<Span>,
pub name: Ident,
pub ty: Ty<'tcx>,
@@ -600,32 +601,56 @@ pub struct BorrowOfMovedValue<'tcx> {
pub struct MultipleMutBorrows {
#[primary_span]
pub span: Span,
- #[label]
- pub binding_span: Span,
#[subdiagnostic]
- pub occurences: Vec<MultipleMutBorrowOccurence>,
- pub name: Ident,
+ pub occurences: Vec<Conflict>,
+}
+
+#[derive(Diagnostic)]
+#[diag(mir_build_already_borrowed)]
+pub struct AlreadyBorrowed {
+ #[primary_span]
+ pub span: Span,
+ #[subdiagnostic]
+ pub occurences: Vec<Conflict>,
+}
+
+#[derive(Diagnostic)]
+#[diag(mir_build_already_mut_borrowed)]
+pub struct AlreadyMutBorrowed {
+ #[primary_span]
+ pub span: Span,
+ #[subdiagnostic]
+ pub occurences: Vec<Conflict>,
+}
+
+#[derive(Diagnostic)]
+#[diag(mir_build_moved_while_borrowed)]
+pub struct MovedWhileBorrowed {
+ #[primary_span]
+ pub span: Span,
+ #[subdiagnostic]
+ pub occurences: Vec<Conflict>,
}
#[derive(Subdiagnostic)]
-pub enum MultipleMutBorrowOccurence {
- #[label(mutable_borrow)]
- Mutable {
+pub enum Conflict {
+ #[label(mir_build_mutable_borrow)]
+ Mut {
#[primary_span]
span: Span,
- name_mut: Ident,
+ name: Ident,
},
- #[label(immutable_borrow)]
- Immutable {
+ #[label(mir_build_borrow)]
+ Ref {
#[primary_span]
span: Span,
- name_immut: Ident,
+ name: Ident,
},
- #[label(moved)]
+ #[label(mir_build_moved)]
Moved {
#[primary_span]
span: Span,
- name_moved: Ident,
+ name: Ident,
},
}
@@ -684,7 +709,7 @@ pub struct NontrivialStructuralMatch<'tcx> {
#[diag(mir_build_overlapping_range_endpoints)]
#[note]
pub struct OverlappingRangeEndpoints<'tcx> {
- #[label(range)]
+ #[label(mir_build_range)]
pub range: Span,
#[subdiagnostic]
pub overlap: Vec<Overlap<'tcx>>,
@@ -764,7 +789,7 @@ pub(crate) struct PatternNotCovered<'s, 'tcx> {
pub interpreted_as_const: Option<InterpretedAsConst>,
#[subdiagnostic]
pub adt_defined_here: Option<AdtDefinedHere<'tcx>>,
- #[note(pattern_ty)]
+ #[note(mir_build_pattern_ty)]
pub _p: (),
pub pattern_ty: Ty<'tcx>,
#[subdiagnostic]
@@ -799,10 +824,10 @@ impl<'tcx> AddToDiagnostic for AdtDefinedHere<'tcx> {
let mut spans = MultiSpan::from(self.adt_def_span);
for Variant { span } in self.variants {
- spans.push_span_label(span, rustc_errors::fluent::mir_build_variant_defined_here);
+ spans.push_span_label(span, fluent::mir_build_variant_defined_here);
}
- diag.span_note(spans, rustc_errors::fluent::mir_build_adt_defined_here);
+ diag.span_note(spans, fluent::mir_build_adt_defined_here);
}
}
@@ -863,3 +888,22 @@ pub enum MiscPatternSuggestion {
start_span: Span,
},
}
+
+#[derive(Diagnostic)]
+#[diag(mir_build_rustc_box_attribute_error)]
+pub struct RustcBoxAttributeError {
+ #[primary_span]
+ pub span: Span,
+ #[subdiagnostic]
+ pub reason: RustcBoxAttrReason,
+}
+
+#[derive(Subdiagnostic)]
+pub enum RustcBoxAttrReason {
+ #[note(mir_build_attributes)]
+ Attributes,
+ #[note(mir_build_not_box)]
+ NotBoxNew,
+ #[note(mir_build_missing_box)]
+ MissingBox,
+}
diff --git a/compiler/rustc_mir_build/src/lib.rs b/compiler/rustc_mir_build/src/lib.rs
index a428180a4..e10a264d3 100644
--- a/compiler/rustc_mir_build/src/lib.rs
+++ b/compiler/rustc_mir_build/src/lib.rs
@@ -25,6 +25,11 @@ pub mod thir;
use rustc_middle::ty::query::Providers;
+use rustc_errors::{DiagnosticMessage, SubdiagnosticMessage};
+use rustc_macros::fluent_messages;
+
+fluent_messages! { "../locales/en-US.ftl" }
+
pub fn provide(providers: &mut Providers) {
providers.check_match = thir::pattern::check_match;
providers.lit_to_const = thir::constant::lit_to_const;
@@ -33,5 +38,6 @@ pub fn provide(providers: &mut Providers) {
providers.thir_check_unsafety = check_unsafety::thir_check_unsafety;
providers.thir_check_unsafety_for_const_arg = check_unsafety::thir_check_unsafety_for_const_arg;
providers.thir_body = thir::cx::thir_body;
- providers.thir_tree = thir::cx::thir_tree;
+ providers.thir_tree = thir::print::thir_tree;
+ providers.thir_flat = thir::print::thir_flat;
}
diff --git a/compiler/rustc_mir_build/src/thir/cx/expr.rs b/compiler/rustc_mir_build/src/thir/cx/expr.rs
index 261b95ba9..9086412c0 100644
--- a/compiler/rustc_mir_build/src/thir/cx/expr.rs
+++ b/compiler/rustc_mir_build/src/thir/cx/expr.rs
@@ -1,3 +1,4 @@
+use crate::errors;
use crate::thir::cx::region::Scope;
use crate::thir::cx::Cx;
use crate::thir::util::UserAnnotatedTyHelpers;
@@ -18,7 +19,7 @@ use rustc_middle::ty::subst::InternalSubsts;
use rustc_middle::ty::{
self, AdtKind, InlineConstSubsts, InlineConstSubstsParts, ScalarInt, Ty, UpvarSubsts, UserType,
};
-use rustc_span::Span;
+use rustc_span::{sym, Span};
use rustc_target::abi::VariantIdx;
impl<'tcx> Cx<'tcx> {
@@ -33,8 +34,6 @@ impl<'tcx> Cx<'tcx> {
#[instrument(level = "trace", skip(self, hir_expr))]
pub(super) fn mirror_expr_inner(&mut self, hir_expr: &'tcx hir::Expr<'tcx>) -> ExprId {
- let temp_lifetime =
- self.rvalue_scopes.temporary_scope(self.region_scope_tree, hir_expr.hir_id.local_id);
let expr_scope =
region::Scope { id: hir_expr.hir_id.local_id, data: region::ScopeData::Node };
@@ -67,7 +66,7 @@ impl<'tcx> Cx<'tcx> {
// Next, wrap this up in the expr's scope.
expr = Expr {
- temp_lifetime,
+ temp_lifetime: expr.temp_lifetime,
ty: expr.ty,
span: hir_expr.span,
kind: ExprKind::Scope {
@@ -82,7 +81,7 @@ impl<'tcx> Cx<'tcx> {
self.region_scope_tree.opt_destruction_scope(hir_expr.hir_id.local_id)
{
expr = Expr {
- temp_lifetime,
+ temp_lifetime: expr.temp_lifetime,
ty: expr.ty,
span: hir_expr.span,
kind: ExprKind::Scope {
@@ -262,6 +261,7 @@ impl<'tcx> Cx<'tcx> {
}
}
+ #[instrument(level = "debug", skip(self), ret)]
fn make_mirror_unadjusted(&mut self, expr: &'tcx hir::Expr<'tcx>) -> Expr<'tcx> {
let tcx = self.tcx;
let expr_ty = self.typeck_results().expr_ty(expr);
@@ -307,7 +307,7 @@ impl<'tcx> Cx<'tcx> {
let arg_tys = args.iter().map(|e| self.typeck_results().expr_ty_adjusted(e));
let tupled_args = Expr {
- ty: tcx.mk_tup(arg_tys),
+ ty: tcx.mk_tup_from_iter(arg_tys),
temp_lifetime,
span: expr.span,
kind: ExprKind::Tuple { fields: self.mirror_exprs(args) },
@@ -322,6 +322,34 @@ impl<'tcx> Cx<'tcx> {
fn_span: expr.span,
}
} else {
+ let attrs = tcx.hir().attrs(expr.hir_id);
+ if attrs.iter().any(|a| a.name_or_empty() == sym::rustc_box) {
+ if attrs.len() != 1 {
+ tcx.sess.emit_err(errors::RustcBoxAttributeError {
+ span: attrs[0].span,
+ reason: errors::RustcBoxAttrReason::Attributes,
+ });
+ } else if let Some(box_item) = tcx.lang_items().owned_box() {
+ if let hir::ExprKind::Path(hir::QPath::TypeRelative(ty, fn_path)) = fun.kind
+ && let hir::TyKind::Path(hir::QPath::Resolved(_, path)) = ty.kind
+ && path.res.opt_def_id().map_or(false, |did| did == box_item)
+ && fn_path.ident.name == sym::new
+ && let [value] = args
+ {
+ return Expr { temp_lifetime, ty: expr_ty, span: expr.span, kind: ExprKind::Box { value: self.mirror_expr(value) } }
+ } else {
+ tcx.sess.emit_err(errors::RustcBoxAttributeError {
+ span: expr.span,
+ reason: errors::RustcBoxAttrReason::NotBoxNew
+ });
+ }
+ } else {
+ tcx.sess.emit_err(errors::RustcBoxAttributeError {
+ span: attrs[0].span,
+ reason: errors::RustcBoxAttrReason::MissingBox,
+ });
+ }
+ }
let adt_data =
if let hir::ExprKind::Path(hir::QPath::Resolved(_, ref path)) = fun.kind {
// Tuple-like ADTs are represented as ExprKind::Call. We convert them here.
@@ -541,8 +569,9 @@ impl<'tcx> Cx<'tcx> {
let def_id = def_id.expect_local();
let upvars = self
- .typeck_results
- .closure_min_captures_flattened(def_id)
+ .tcx
+ .closure_captures(def_id)
+ .iter()
.zip(substs.upvar_tys())
.map(|(captured_place, ty)| {
let upvars = self.capture_upvar(expr, captured_place, ty);
@@ -758,7 +787,7 @@ impl<'tcx> Cx<'tcx> {
hir::ExprKind::Tup(ref fields) => ExprKind::Tuple { fields: self.mirror_exprs(fields) },
hir::ExprKind::Yield(ref v, _) => ExprKind::Yield { value: self.mirror_expr(v) },
- hir::ExprKind::Err => unreachable!(),
+ hir::ExprKind::Err(_) => unreachable!(),
};
Expr { temp_lifetime, ty: expr_ty, span: expr.span, kind }
diff --git a/compiler/rustc_mir_build/src/thir/cx/mod.rs b/compiler/rustc_mir_build/src/thir/cx/mod.rs
index a355e1bda..070544446 100644
--- a/compiler/rustc_mir_build/src/thir/cx/mod.rs
+++ b/compiler/rustc_mir_build/src/thir/cx/mod.rs
@@ -52,13 +52,6 @@ pub(crate) fn thir_body(
Ok((tcx.alloc_steal_thir(cx.thir), expr))
}
-pub(crate) fn thir_tree(tcx: TyCtxt<'_>, owner_def: ty::WithOptConstParam<LocalDefId>) -> String {
- match thir_body(tcx, owner_def) {
- Ok((thir, _)) => format!("{:#?}", thir.steal()),
- Err(_) => "error".into(),
- }
-}
-
struct Cx<'tcx> {
tcx: TyCtxt<'tcx>,
thir: Thir<'tcx>,
@@ -89,9 +82,30 @@ impl<'tcx> Cx<'tcx> {
let typeck_results = tcx.typeck_opt_const_arg(def);
let did = def.did;
let hir = tcx.hir();
+ let hir_id = hir.local_def_id_to_hir_id(did);
+
+ let body_type = if hir.body_owner_kind(did).is_fn_or_closure() {
+ // fetch the fully liberated fn signature (that is, all bound
+ // types/lifetimes replaced)
+ BodyTy::Fn(typeck_results.liberated_fn_sigs()[hir_id])
+ } else {
+ // Get the revealed type of this const. This is *not* the adjusted
+ // type of its body, which may be a subtype of this type. For
+ // example:
+ //
+ // fn foo(_: &()) {}
+ // static X: fn(&'static ()) = foo;
+ //
+ // The adjusted type of the body of X is `for<'a> fn(&'a ())` which
+ // is not the same as the type of X. We need the type of the return
+ // place to be the type of the constant because NLL typeck will
+ // equate them.
+ BodyTy::Const(typeck_results.node_type(hir_id))
+ };
+
Cx {
tcx,
- thir: Thir::new(),
+ thir: Thir::new(body_type),
param_env: tcx.param_env(def.did),
region_scope_tree: tcx.region_scope_tree(def.did),
typeck_results,
@@ -99,7 +113,7 @@ impl<'tcx> Cx<'tcx> {
body_owner: did.to_def_id(),
adjustment_span: None,
apply_adjustments: hir
- .attrs(hir.local_def_id_to_hir_id(did))
+ .attrs(hir_id)
.iter()
.all(|attr| attr.name_or_empty() != rustc_span::sym::custom_mir),
}
@@ -123,14 +137,13 @@ impl<'tcx> Cx<'tcx> {
bug!("closure expr does not have closure type: {:?}", closure_ty);
};
- let bound_vars = self.tcx.mk_bound_variable_kinds(std::iter::once(
- ty::BoundVariableKind::Region(ty::BrEnv),
- ));
+ let bound_vars =
+ self.tcx.mk_bound_variable_kinds(&[ty::BoundVariableKind::Region(ty::BrEnv)]);
let br = ty::BoundRegion {
var: ty::BoundVar::from_usize(bound_vars.len() - 1),
kind: ty::BrEnv,
};
- let env_region = ty::ReLateBound(ty::INNERMOST, br);
+ let env_region = self.tcx.mk_re_late_bound(ty::INNERMOST, br);
let closure_env_ty =
self.tcx.closure_env_ty(closure_def_id, closure_substs, env_region).unwrap();
let liberated_closure_env_ty = self.tcx.erase_late_bound_regions(
@@ -183,7 +196,7 @@ impl<'tcx> Cx<'tcx> {
let va_list_did = self.tcx.require_lang_item(LangItem::VaList, Some(param.span));
self.tcx
- .bound_type_of(va_list_did)
+ .type_of(va_list_did)
.subst(self.tcx, &[self.tcx.lifetimes.re_erased.into()])
} else {
fn_sig.inputs()[index]
diff --git a/compiler/rustc_mir_build/src/thir/mod.rs b/compiler/rustc_mir_build/src/thir/mod.rs
index e0e6ac266..ca26cc13b 100644
--- a/compiler/rustc_mir_build/src/thir/mod.rs
+++ b/compiler/rustc_mir_build/src/thir/mod.rs
@@ -5,9 +5,7 @@
//! structures.
pub(crate) mod constant;
-
pub(crate) mod cx;
-
pub(crate) mod pattern;
-
+pub(crate) mod print;
mod util;
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 34e637f59..2640ca56b 100644
--- a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs
+++ b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs
@@ -208,9 +208,9 @@ impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> {
// Don't report arm reachability of desugared `match $iter.into_iter() { iter => .. }`
// when the iterator is an uninhabited type. unreachable_code will trigger instead.
hir::MatchSource::ForLoopDesugar if arms.len() == 1 => {}
- hir::MatchSource::ForLoopDesugar | hir::MatchSource::Normal => {
- report_arm_reachability(&cx, &report)
- }
+ hir::MatchSource::ForLoopDesugar
+ | hir::MatchSource::Normal
+ | hir::MatchSource::FormatArgs => 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 => {}
@@ -926,58 +926,55 @@ fn check_borrow_conflicts_in_at_patterns(cx: &MatchVisitor<'_, '_, '_>, pat: &Pa
sub.each_binding(|_, hir_id, span, name| {
match typeck_results.extract_binding_mode(sess, hir_id, span) {
Some(ty::BindByReference(mut_inner)) => match (mut_outer, mut_inner) {
- (Mutability::Not, Mutability::Not) => {} // Both sides are `ref`.
- (Mutability::Mut, Mutability::Mut) => conflicts_mut_mut.push((span, name)), // 2x `ref mut`.
- _ => conflicts_mut_ref.push((span, name)), // `ref` + `ref mut` in either direction.
+ // Both sides are `ref`.
+ (Mutability::Not, Mutability::Not) => {}
+ // 2x `ref mut`.
+ (Mutability::Mut, Mutability::Mut) => {
+ conflicts_mut_mut.push(Conflict::Mut { span, name })
+ }
+ (Mutability::Not, Mutability::Mut) => {
+ conflicts_mut_ref.push(Conflict::Mut { span, name })
+ }
+ (Mutability::Mut, Mutability::Not) => {
+ conflicts_mut_ref.push(Conflict::Ref { span, name })
+ }
},
Some(ty::BindByValue(_)) if is_binding_by_move(cx, hir_id) => {
- conflicts_move.push((span, name)) // `ref mut?` + by-move conflict.
+ conflicts_move.push(Conflict::Moved { span, name }) // `ref mut?` + by-move conflict.
}
Some(ty::BindByValue(_)) | None => {} // `ref mut?` + by-copy is fine.
}
});
+ let report_mut_mut = !conflicts_mut_mut.is_empty();
+ let report_mut_ref = !conflicts_mut_ref.is_empty();
+ let report_move_conflict = !conflicts_move.is_empty();
+
+ let mut occurences = match mut_outer {
+ Mutability::Mut => vec![Conflict::Mut { span: binding_span, name }],
+ Mutability::Not => vec![Conflict::Ref { span: binding_span, name }],
+ };
+ occurences.extend(conflicts_mut_mut);
+ occurences.extend(conflicts_mut_ref);
+ occurences.extend(conflicts_move);
+
// Report errors if any.
- if !conflicts_mut_mut.is_empty() {
+ if report_mut_mut {
// Report mutability conflicts for e.g. `ref mut x @ Some(ref mut y)`.
- let mut occurences = vec![];
-
- for (span, name_mut) in conflicts_mut_mut {
- occurences.push(MultipleMutBorrowOccurence::Mutable { span, name_mut });
- }
- for (span, name_immut) in conflicts_mut_ref {
- occurences.push(MultipleMutBorrowOccurence::Immutable { span, name_immut });
- }
- for (span, name_moved) in conflicts_move {
- occurences.push(MultipleMutBorrowOccurence::Moved { span, name_moved });
- }
- sess.emit_err(MultipleMutBorrows { span: pat.span, binding_span, occurences, name });
- } else if !conflicts_mut_ref.is_empty() {
+ sess.emit_err(MultipleMutBorrows { span: pat.span, occurences });
+ } else if report_mut_ref {
// Report mutability conflicts for e.g. `ref x @ Some(ref mut y)` or the converse.
- let (primary, also) = match mut_outer {
- Mutability::Mut => ("mutable", "immutable"),
- Mutability::Not => ("immutable", "mutable"),
+ match mut_outer {
+ Mutability::Mut => {
+ sess.emit_err(AlreadyMutBorrowed { span: pat.span, occurences });
+ }
+ Mutability::Not => {
+ sess.emit_err(AlreadyBorrowed { span: pat.span, occurences });
+ }
};
- let msg =
- format!("cannot borrow value as {} because it is also borrowed as {}", also, primary);
- let mut err = sess.struct_span_err(pat.span, &msg);
- err.span_label(binding_span, format!("{} borrow, by `{}`, occurs here", primary, name));
- for (span, name) in conflicts_mut_ref {
- err.span_label(span, format!("{} borrow, by `{}`, occurs here", also, name));
- }
- for (span, name) in conflicts_move {
- err.span_label(span, format!("also moved into `{}` here", name));
- }
- err.emit();
- } else if !conflicts_move.is_empty() {
+ } else if report_move_conflict {
// Report by-ref and by-move conflicts, e.g. `ref x @ y`.
- let mut err =
- sess.struct_span_err(pat.span, "cannot move out of value because it is borrowed");
- err.span_label(binding_span, format!("value borrowed, by `{}`, here", name));
- for (span, name) in conflicts_move {
- err.span_label(span, format!("value moved into `{}` here", name));
- }
- err.emit();
+ sess.emit_err(MovedWhileBorrowed { span: pat.span, occurences });
}
}
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 7f3519945..ff88d0013 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
@@ -192,7 +192,7 @@ impl<'tcx> ConstToPat<'tcx> {
let obligation: PredicateObligation<'_> = predicate_for_trait_def(
self.tcx(),
self.param_env,
- ObligationCause::misc(self.span, self.id),
+ ObligationCause::misc(self.span, self.id.owner.def_id),
partial_eq_trait_id,
0,
[ty, ty],
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 aba5429da..e5b7d685c 100644
--- a/compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs
+++ b/compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs
@@ -172,7 +172,7 @@ impl IntRange {
ty: Ty<'tcx>,
end: &RangeEnd,
) -> Option<IntRange> {
- if Self::is_integral(ty) {
+ Self::is_integral(ty).then(|| {
// Perform a shift if the underlying types are signed,
// which makes the interval arithmetic simpler.
let bias = IntRange::signed_bias(tcx, ty);
@@ -182,10 +182,8 @@ impl IntRange {
// This should have been caught earlier by E0030.
bug!("malformed range pattern: {}..={}", lo, (hi - offset));
}
- Some(IntRange { range: lo..=(hi - offset), bias })
- } else {
- None
- }
+ IntRange { range: lo..=(hi - offset), bias }
+ })
}
// The return value of `signed_bias` should be XORed with an endpoint to encode/decode it.
@@ -922,8 +920,8 @@ impl<'tcx> SplitWildcard<'tcx> {
// `cx.is_uninhabited()`).
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) as usize;
+ ty::Array(sub_ty, len) if len.try_eval_target_usize(cx.tcx, cx.param_env).is_some() => {
+ let len = len.eval_target_usize(cx.tcx, cx.param_env) as usize;
if len != 0 && cx.is_uninhabited(*sub_ty) {
smallvec![]
} else {
@@ -1406,7 +1404,9 @@ impl<'p, 'tcx> DeconstructedPat<'p, 'tcx> {
}
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::Array(_, length) => {
+ Some(length.eval_target_usize(cx.tcx, cx.param_env) as usize)
+ }
ty::Slice(_) => None,
_ => span_bug!(pat.span, "bad ty {:?} for slice pattern", pat.ty),
};
diff --git a/compiler/rustc_mir_build/src/thir/pattern/mod.rs b/compiler/rustc_mir_build/src/thir/pattern/mod.rs
index 3a6ef87c9..41306dd80 100644
--- a/compiler/rustc_mir_build/src/thir/pattern/mod.rs
+++ b/compiler/rustc_mir_build/src/thir/pattern/mod.rs
@@ -203,11 +203,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
if !lower_overflow && !higher_overflow {
self.tcx.sess.emit_err(LowerRangeBoundMustBeLessThanOrEqualToUpper {
span,
- teach: if self.tcx.sess.teach(&error_code!(E0030)) {
- Some(())
- } else {
- None
- },
+ teach: self.tcx.sess.teach(&error_code!(E0030)).then_some(()),
});
}
PatKind::Wild
@@ -416,7 +412,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
ty::Slice(..) => PatKind::Slice { prefix, slice, suffix },
// Fixed-length array, `[T; len]`.
ty::Array(_, len) => {
- let len = len.eval_usize(self.tcx, self.param_env);
+ let len = len.eval_target_usize(self.tcx, self.param_env);
assert!(len >= prefix.len() as u64 + suffix.len() as u64);
PatKind::Array { prefix, slice, suffix }
}
diff --git a/compiler/rustc_mir_build/src/thir/print.rs b/compiler/rustc_mir_build/src/thir/print.rs
new file mode 100644
index 000000000..8028227aa
--- /dev/null
+++ b/compiler/rustc_mir_build/src/thir/print.rs
@@ -0,0 +1,892 @@
+use rustc_middle::thir::*;
+use rustc_middle::ty::{self, TyCtxt};
+use rustc_span::def_id::LocalDefId;
+use std::fmt::{self, Write};
+
+pub(crate) fn thir_tree(tcx: TyCtxt<'_>, owner_def: ty::WithOptConstParam<LocalDefId>) -> String {
+ match super::cx::thir_body(tcx, owner_def) {
+ Ok((thir, _)) => {
+ let thir = thir.steal();
+ let mut printer = ThirPrinter::new(&thir);
+ printer.print();
+ printer.into_buffer()
+ }
+ Err(_) => "error".into(),
+ }
+}
+
+pub(crate) fn thir_flat(tcx: TyCtxt<'_>, owner_def: ty::WithOptConstParam<LocalDefId>) -> String {
+ match super::cx::thir_body(tcx, owner_def) {
+ Ok((thir, _)) => format!("{:#?}", thir.steal()),
+ Err(_) => "error".into(),
+ }
+}
+
+struct ThirPrinter<'a, 'tcx> {
+ thir: &'a Thir<'tcx>,
+ fmt: String,
+}
+
+const INDENT: &str = " ";
+
+macro_rules! print_indented {
+ ($writer:ident, $s:expr, $indent_lvl:expr) => {
+ let indent = (0..$indent_lvl).map(|_| INDENT).collect::<Vec<_>>().concat();
+ writeln!($writer, "{}{}", indent, $s).expect("unable to write to ThirPrinter");
+ };
+}
+
+impl<'a, 'tcx> Write for ThirPrinter<'a, 'tcx> {
+ fn write_str(&mut self, s: &str) -> fmt::Result {
+ self.fmt.push_str(s);
+ Ok(())
+ }
+}
+
+impl<'a, 'tcx> ThirPrinter<'a, 'tcx> {
+ fn new(thir: &'a Thir<'tcx>) -> Self {
+ Self { thir, fmt: String::new() }
+ }
+
+ fn print(&mut self) {
+ print_indented!(self, "params: [", 0);
+ for param in self.thir.params.iter() {
+ self.print_param(param, 1);
+ }
+ print_indented!(self, "]", 0);
+
+ print_indented!(self, "body:", 0);
+ let expr = ExprId::from_usize(self.thir.exprs.len() - 1);
+ self.print_expr(expr, 1);
+ }
+
+ fn into_buffer(self) -> String {
+ self.fmt
+ }
+
+ fn print_param(&mut self, param: &Param<'tcx>, depth_lvl: usize) {
+ let Param { pat, ty, ty_span, self_kind, hir_id } = param;
+
+ print_indented!(self, "Param {", depth_lvl);
+ print_indented!(self, format!("ty: {:?}", ty), depth_lvl + 1);
+ print_indented!(self, format!("ty_span: {:?}", ty_span), depth_lvl + 1);
+ print_indented!(self, format!("self_kind: {:?}", self_kind), depth_lvl + 1);
+ print_indented!(self, format!("hir_id: {:?}", hir_id), depth_lvl + 1);
+
+ if let Some(pat) = pat {
+ print_indented!(self, "param: Some( ", depth_lvl + 1);
+ self.print_pat(pat, depth_lvl + 2);
+ print_indented!(self, ")", depth_lvl + 1);
+ } else {
+ print_indented!(self, "param: None", depth_lvl + 1);
+ }
+
+ print_indented!(self, "}", depth_lvl);
+ }
+
+ fn print_block(&mut self, block_id: BlockId, depth_lvl: usize) {
+ let Block {
+ targeted_by_break,
+ opt_destruction_scope,
+ span,
+ region_scope,
+ stmts,
+ expr,
+ safety_mode,
+ } = &self.thir.blocks[block_id];
+
+ print_indented!(self, "Block {", depth_lvl);
+ print_indented!(self, format!("targeted_by_break: {}", targeted_by_break), depth_lvl + 1);
+ print_indented!(
+ self,
+ format!("opt_destruction_scope: {:?}", opt_destruction_scope),
+ depth_lvl + 1
+ );
+ print_indented!(self, format!("span: {:?}", span), depth_lvl + 1);
+ print_indented!(self, format!("region_scope: {:?}", region_scope), depth_lvl + 1);
+ print_indented!(self, format!("safety_mode: {:?}", safety_mode), depth_lvl + 1);
+
+ if stmts.len() > 0 {
+ print_indented!(self, "stmts: [", depth_lvl + 1);
+ for stmt in stmts.iter() {
+ self.print_stmt(*stmt, depth_lvl + 2);
+ }
+ print_indented!(self, "]", depth_lvl + 1);
+ } else {
+ print_indented!(self, "stmts: []", depth_lvl + 1);
+ }
+
+ if let Some(expr_id) = expr {
+ print_indented!(self, "expr:", depth_lvl + 1);
+ self.print_expr(*expr_id, depth_lvl + 2);
+ } else {
+ print_indented!(self, "expr: []", depth_lvl + 1);
+ }
+
+ print_indented!(self, "}", depth_lvl);
+ }
+
+ fn print_stmt(&mut self, stmt_id: StmtId, depth_lvl: usize) {
+ let Stmt { kind, opt_destruction_scope } = &self.thir.stmts[stmt_id];
+
+ print_indented!(self, "Stmt {", depth_lvl);
+ print_indented!(
+ self,
+ format!("opt_destruction_scope: {:?}", opt_destruction_scope),
+ depth_lvl + 1
+ );
+
+ match kind {
+ StmtKind::Expr { scope, expr } => {
+ print_indented!(self, "kind: Expr {", depth_lvl + 1);
+ print_indented!(self, format!("scope: {:?}", scope), depth_lvl + 2);
+ print_indented!(self, "expr:", depth_lvl + 2);
+ self.print_expr(*expr, depth_lvl + 3);
+ print_indented!(self, "}", depth_lvl + 1);
+ }
+ StmtKind::Let {
+ remainder_scope,
+ init_scope,
+ pattern,
+ initializer,
+ else_block,
+ lint_level,
+ } => {
+ print_indented!(self, "kind: Let {", depth_lvl + 1);
+ print_indented!(
+ self,
+ format!("remainder_scope: {:?}", remainder_scope),
+ depth_lvl + 2
+ );
+ print_indented!(self, format!("init_scope: {:?}", init_scope), depth_lvl + 2);
+
+ print_indented!(self, "pattern: ", depth_lvl + 2);
+ self.print_pat(pattern, depth_lvl + 3);
+ print_indented!(self, ",", depth_lvl + 2);
+
+ if let Some(init) = initializer {
+ print_indented!(self, "initializer: Some(", depth_lvl + 2);
+ self.print_expr(*init, depth_lvl + 3);
+ print_indented!(self, ")", depth_lvl + 2);
+ } else {
+ print_indented!(self, "initializer: None", depth_lvl + 2);
+ }
+
+ if let Some(else_block) = else_block {
+ print_indented!(self, "else_block: Some(", depth_lvl + 2);
+ self.print_block(*else_block, depth_lvl + 3);
+ print_indented!(self, ")", depth_lvl + 2);
+ } else {
+ print_indented!(self, "else_block: None", depth_lvl + 2);
+ }
+
+ print_indented!(self, format!("lint_level: {:?}", lint_level), depth_lvl + 2);
+ print_indented!(self, "}", depth_lvl + 1);
+ }
+ }
+
+ print_indented!(self, "}", depth_lvl);
+ }
+
+ fn print_expr(&mut self, expr: ExprId, depth_lvl: usize) {
+ let Expr { ty, temp_lifetime, span, kind } = &self.thir[expr];
+ print_indented!(self, "Expr {", depth_lvl);
+ print_indented!(self, format!("ty: {:?}", ty), depth_lvl + 1);
+ print_indented!(self, format!("temp_lifetime: {:?}", temp_lifetime), depth_lvl + 1);
+ print_indented!(self, format!("span: {:?}", span), depth_lvl + 1);
+ print_indented!(self, "kind: ", depth_lvl + 1);
+ self.print_expr_kind(kind, depth_lvl + 2);
+ print_indented!(self, "}", depth_lvl);
+ }
+
+ fn print_expr_kind(&mut self, expr_kind: &ExprKind<'tcx>, depth_lvl: usize) {
+ use rustc_middle::thir::ExprKind::*;
+
+ match expr_kind {
+ Scope { region_scope, value, lint_level } => {
+ print_indented!(self, "Scope {", depth_lvl);
+ print_indented!(self, format!("region_scope: {:?}", region_scope), depth_lvl + 1);
+ print_indented!(self, format!("lint_level: {:?}", lint_level), depth_lvl + 1);
+ print_indented!(self, "value:", depth_lvl + 1);
+ self.print_expr(*value, depth_lvl + 2);
+ print_indented!(self, "}", depth_lvl);
+ }
+ Box { value } => {
+ print_indented!(self, "Box {", depth_lvl);
+ self.print_expr(*value, depth_lvl + 1);
+ print_indented!(self, "}", depth_lvl);
+ }
+ If { if_then_scope, cond, then, else_opt } => {
+ print_indented!(self, "If {", depth_lvl);
+ print_indented!(self, format!("if_then_scope: {:?}", if_then_scope), depth_lvl + 1);
+ print_indented!(self, "cond:", depth_lvl + 1);
+ self.print_expr(*cond, depth_lvl + 2);
+ print_indented!(self, "then:", depth_lvl + 1);
+ self.print_expr(*then, depth_lvl + 2);
+
+ if let Some(else_expr) = else_opt {
+ print_indented!(self, "else:", depth_lvl + 1);
+ self.print_expr(*else_expr, depth_lvl + 2);
+ }
+
+ print_indented!(self, "}", depth_lvl);
+ }
+ Call { fun, args, ty, from_hir_call, fn_span } => {
+ print_indented!(self, "Call {", depth_lvl);
+ print_indented!(self, format!("ty: {:?}", ty), depth_lvl + 1);
+ print_indented!(self, format!("from_hir_call: {}", from_hir_call), depth_lvl + 1);
+ print_indented!(self, format!("fn_span: {:?}", fn_span), depth_lvl + 1);
+ print_indented!(self, "fun:", depth_lvl + 1);
+ self.print_expr(*fun, depth_lvl + 2);
+
+ if args.len() > 0 {
+ print_indented!(self, "args: [", depth_lvl + 1);
+ for arg in args.iter() {
+ self.print_expr(*arg, depth_lvl + 2);
+ }
+ print_indented!(self, "]", depth_lvl + 1);
+ } else {
+ print_indented!(self, "args: []", depth_lvl + 1);
+ }
+
+ print_indented!(self, "}", depth_lvl);
+ }
+ Deref { arg } => {
+ print_indented!(self, "Deref {", depth_lvl);
+ self.print_expr(*arg, depth_lvl + 1);
+ print_indented!(self, "}", depth_lvl);
+ }
+ Binary { op, lhs, rhs } => {
+ print_indented!(self, "Binary {", depth_lvl);
+ print_indented!(self, format!("op: {:?}", op), depth_lvl + 1);
+ print_indented!(self, "lhs:", depth_lvl + 1);
+ self.print_expr(*lhs, depth_lvl + 2);
+ print_indented!(self, "rhs:", depth_lvl + 1);
+ self.print_expr(*rhs, depth_lvl + 2);
+ print_indented!(self, "}", depth_lvl);
+ }
+ LogicalOp { op, lhs, rhs } => {
+ print_indented!(self, "LogicalOp {", depth_lvl);
+ print_indented!(self, format!("op: {:?}", op), depth_lvl + 1);
+ print_indented!(self, "lhs:", depth_lvl + 1);
+ self.print_expr(*lhs, depth_lvl + 2);
+ print_indented!(self, "rhs:", depth_lvl + 1);
+ self.print_expr(*rhs, depth_lvl + 2);
+ print_indented!(self, "}", depth_lvl);
+ }
+ Unary { op, arg } => {
+ print_indented!(self, "Unary {", depth_lvl);
+ print_indented!(self, format!("op: {:?}", op), depth_lvl + 1);
+ print_indented!(self, "arg:", depth_lvl + 1);
+ self.print_expr(*arg, depth_lvl + 2);
+ print_indented!(self, "}", depth_lvl);
+ }
+ Cast { source } => {
+ print_indented!(self, "Cast {", depth_lvl);
+ print_indented!(self, "source:", depth_lvl + 1);
+ self.print_expr(*source, depth_lvl + 2);
+ print_indented!(self, "}", depth_lvl);
+ }
+ Use { source } => {
+ print_indented!(self, "Use {", depth_lvl);
+ print_indented!(self, "source:", depth_lvl + 1);
+ self.print_expr(*source, depth_lvl + 2);
+ print_indented!(self, "}", depth_lvl);
+ }
+ NeverToAny { source } => {
+ print_indented!(self, "NeverToAny {", depth_lvl);
+ print_indented!(self, "source:", depth_lvl + 1);
+ self.print_expr(*source, depth_lvl + 2);
+ print_indented!(self, "}", depth_lvl);
+ }
+ Pointer { cast, source } => {
+ print_indented!(self, "Pointer {", depth_lvl);
+ print_indented!(self, format!("cast: {:?}", cast), depth_lvl + 1);
+ print_indented!(self, "source:", depth_lvl + 1);
+ self.print_expr(*source, depth_lvl + 2);
+ print_indented!(self, "}", depth_lvl);
+ }
+ Loop { body } => {
+ print_indented!(self, "Loop (", depth_lvl);
+ print_indented!(self, "body:", depth_lvl + 1);
+ self.print_expr(*body, depth_lvl + 2);
+ print_indented!(self, ")", depth_lvl);
+ }
+ Let { expr, pat } => {
+ print_indented!(self, "Let {", depth_lvl);
+ print_indented!(self, "expr:", depth_lvl + 1);
+ self.print_expr(*expr, depth_lvl + 2);
+ print_indented!(self, format!("pat: {:?}", pat), depth_lvl + 1);
+ print_indented!(self, "}", depth_lvl);
+ }
+ Match { scrutinee, arms } => {
+ print_indented!(self, "Match {", depth_lvl);
+ print_indented!(self, "scrutinee:", depth_lvl + 1);
+ self.print_expr(*scrutinee, depth_lvl + 2);
+
+ print_indented!(self, "arms: [", depth_lvl + 1);
+ for arm_id in arms.iter() {
+ self.print_arm(*arm_id, depth_lvl + 2);
+ }
+ print_indented!(self, "]", depth_lvl + 1);
+ print_indented!(self, "}", depth_lvl);
+ }
+ Block { block } => self.print_block(*block, depth_lvl),
+ Assign { lhs, rhs } => {
+ print_indented!(self, "Assign {", depth_lvl);
+ print_indented!(self, "lhs:", depth_lvl + 1);
+ self.print_expr(*lhs, depth_lvl + 2);
+ print_indented!(self, "rhs:", depth_lvl + 1);
+ self.print_expr(*rhs, depth_lvl + 2);
+ print_indented!(self, "}", depth_lvl);
+ }
+ AssignOp { op, lhs, rhs } => {
+ print_indented!(self, "AssignOp {", depth_lvl);
+ print_indented!(self, format!("op: {:?}", op), depth_lvl + 1);
+ print_indented!(self, "lhs:", depth_lvl + 1);
+ self.print_expr(*lhs, depth_lvl + 2);
+ print_indented!(self, "rhs:", depth_lvl + 1);
+ self.print_expr(*rhs, depth_lvl + 2);
+ print_indented!(self, "}", depth_lvl);
+ }
+ Field { lhs, variant_index, name } => {
+ print_indented!(self, "Field {", depth_lvl);
+ print_indented!(self, format!("variant_index: {:?}", variant_index), depth_lvl + 1);
+ print_indented!(self, format!("name: {:?}", name), depth_lvl + 1);
+ print_indented!(self, "lhs:", depth_lvl + 1);
+ self.print_expr(*lhs, depth_lvl + 2);
+ print_indented!(self, "}", depth_lvl);
+ }
+ Index { lhs, index } => {
+ print_indented!(self, "Index {", depth_lvl);
+ print_indented!(self, format!("index: {:?}", index), depth_lvl + 1);
+ print_indented!(self, "lhs:", depth_lvl + 1);
+ self.print_expr(*lhs, depth_lvl + 2);
+ print_indented!(self, "}", depth_lvl);
+ }
+ VarRef { id } => {
+ print_indented!(self, "VarRef {", depth_lvl);
+ print_indented!(self, format!("id: {:?}", id), depth_lvl + 1);
+ print_indented!(self, "}", depth_lvl);
+ }
+ UpvarRef { closure_def_id, var_hir_id } => {
+ print_indented!(self, "UpvarRef {", depth_lvl);
+ print_indented!(
+ self,
+ format!("closure_def_id: {:?}", closure_def_id),
+ depth_lvl + 1
+ );
+ print_indented!(self, format!("var_hir_id: {:?}", var_hir_id), depth_lvl + 1);
+ print_indented!(self, "}", depth_lvl);
+ }
+ Borrow { borrow_kind, arg } => {
+ print_indented!(self, "Borrow (", depth_lvl);
+ print_indented!(self, format!("borrow_kind: {:?}", borrow_kind), depth_lvl + 1);
+ print_indented!(self, "arg:", depth_lvl + 1);
+ self.print_expr(*arg, depth_lvl + 2);
+ print_indented!(self, ")", depth_lvl);
+ }
+ AddressOf { mutability, arg } => {
+ print_indented!(self, "AddressOf {", depth_lvl);
+ print_indented!(self, format!("mutability: {:?}", mutability), depth_lvl + 1);
+ print_indented!(self, "arg:", depth_lvl + 1);
+ self.print_expr(*arg, depth_lvl + 2);
+ print_indented!(self, "}", depth_lvl);
+ }
+ Break { label, value } => {
+ print_indented!(self, "Break (", depth_lvl);
+ print_indented!(self, format!("label: {:?}", label), depth_lvl + 1);
+
+ if let Some(value) = value {
+ print_indented!(self, "value:", depth_lvl + 1);
+ self.print_expr(*value, depth_lvl + 2);
+ }
+
+ print_indented!(self, ")", depth_lvl);
+ }
+ Continue { label } => {
+ print_indented!(self, "Continue {", depth_lvl);
+ print_indented!(self, format!("label: {:?}", label), depth_lvl + 1);
+ print_indented!(self, "}", depth_lvl);
+ }
+ Return { value } => {
+ print_indented!(self, "Return {", depth_lvl);
+ print_indented!(self, "value:", depth_lvl + 1);
+
+ if let Some(value) = value {
+ self.print_expr(*value, depth_lvl + 2);
+ }
+
+ print_indented!(self, "}", depth_lvl);
+ }
+ ConstBlock { did, substs } => {
+ print_indented!(self, "ConstBlock {", depth_lvl);
+ print_indented!(self, format!("did: {:?}", did), depth_lvl + 1);
+ print_indented!(self, format!("substs: {:?}", substs), depth_lvl + 1);
+ print_indented!(self, "}", depth_lvl);
+ }
+ Repeat { value, count } => {
+ print_indented!(self, "Repeat {", depth_lvl);
+ print_indented!(self, format!("count: {:?}", count), depth_lvl + 1);
+ print_indented!(self, "value:", depth_lvl + 1);
+ self.print_expr(*value, depth_lvl + 2);
+ print_indented!(self, "}", depth_lvl);
+ }
+ Array { fields } => {
+ print_indented!(self, "Array {", depth_lvl);
+ print_indented!(self, "fields: [", depth_lvl + 1);
+ for field_id in fields.iter() {
+ self.print_expr(*field_id, depth_lvl + 2);
+ }
+ print_indented!(self, "]", depth_lvl + 1);
+ print_indented!(self, "}", depth_lvl);
+ }
+ Tuple { fields } => {
+ print_indented!(self, "Tuple {", depth_lvl);
+ print_indented!(self, "fields: [", depth_lvl + 1);
+ for field_id in fields.iter() {
+ self.print_expr(*field_id, depth_lvl + 2);
+ }
+ print_indented!(self, "]", depth_lvl + 1);
+ print_indented!(self, "}", depth_lvl);
+ }
+ Adt(adt_expr) => {
+ print_indented!(self, "Adt {", depth_lvl);
+ self.print_adt_expr(&**adt_expr, depth_lvl + 1);
+ print_indented!(self, "}", depth_lvl);
+ }
+ PlaceTypeAscription { source, user_ty } => {
+ print_indented!(self, "PlaceTypeAscription {", depth_lvl);
+ print_indented!(self, format!("user_ty: {:?}", user_ty), depth_lvl + 1);
+ print_indented!(self, "source:", depth_lvl + 1);
+ self.print_expr(*source, depth_lvl + 2);
+ print_indented!(self, "}", depth_lvl);
+ }
+ ValueTypeAscription { source, user_ty } => {
+ print_indented!(self, "ValueTypeAscription {", depth_lvl);
+ print_indented!(self, format!("user_ty: {:?}", user_ty), depth_lvl + 1);
+ print_indented!(self, "source:", depth_lvl + 1);
+ self.print_expr(*source, depth_lvl + 2);
+ print_indented!(self, "}", depth_lvl);
+ }
+ Closure(closure_expr) => {
+ print_indented!(self, "Closure {", depth_lvl);
+ print_indented!(self, "closure_expr:", depth_lvl + 1);
+ self.print_closure_expr(&**closure_expr, depth_lvl + 2);
+ print_indented!(self, "}", depth_lvl);
+ }
+ Literal { lit, neg } => {
+ print_indented!(
+ self,
+ format!("Literal( lit: {:?}, neg: {:?})\n", lit, neg),
+ depth_lvl
+ );
+ }
+ NonHirLiteral { lit, user_ty } => {
+ print_indented!(self, "NonHirLiteral {", depth_lvl);
+ print_indented!(self, format!("lit: {:?}", lit), depth_lvl + 1);
+ print_indented!(self, format!("user_ty: {:?}", user_ty), depth_lvl + 1);
+ print_indented!(self, "}", depth_lvl);
+ }
+ ZstLiteral { user_ty } => {
+ print_indented!(self, format!("ZstLiteral(user_ty: {:?})", user_ty), depth_lvl);
+ }
+ NamedConst { def_id, substs, user_ty } => {
+ print_indented!(self, "NamedConst {", depth_lvl);
+ print_indented!(self, format!("def_id: {:?}", def_id), depth_lvl + 1);
+ print_indented!(self, format!("user_ty: {:?}", user_ty), depth_lvl + 1);
+ print_indented!(self, format!("substs: {:?}", substs), depth_lvl + 1);
+ print_indented!(self, "}", depth_lvl);
+ }
+ ConstParam { param, def_id } => {
+ print_indented!(self, "ConstParam {", depth_lvl);
+ print_indented!(self, format!("def_id: {:?}", def_id), depth_lvl + 1);
+ print_indented!(self, format!("param: {:?}", param), depth_lvl + 1);
+ print_indented!(self, "}", depth_lvl);
+ }
+ StaticRef { alloc_id, ty, def_id } => {
+ print_indented!(self, "StaticRef {", depth_lvl);
+ print_indented!(self, format!("def_id: {:?}", def_id), depth_lvl + 1);
+ print_indented!(self, format!("ty: {:?}", ty), depth_lvl + 1);
+ print_indented!(self, format!("alloc_id: {:?}", alloc_id), depth_lvl + 1);
+ print_indented!(self, "}", depth_lvl);
+ }
+ InlineAsm(expr) => {
+ print_indented!(self, "InlineAsm {", depth_lvl);
+ print_indented!(self, "expr:", depth_lvl + 1);
+ self.print_inline_asm_expr(&**expr, depth_lvl + 2);
+ print_indented!(self, "}", depth_lvl);
+ }
+ ThreadLocalRef(def_id) => {
+ print_indented!(self, "ThreadLocalRef {", depth_lvl);
+ print_indented!(self, format!("def_id: {:?}", def_id), depth_lvl + 1);
+ print_indented!(self, "}", depth_lvl);
+ }
+ Yield { value } => {
+ print_indented!(self, "Yield {", depth_lvl);
+ print_indented!(self, "value:", depth_lvl + 1);
+ self.print_expr(*value, depth_lvl + 2);
+ print_indented!(self, "}", depth_lvl);
+ }
+ }
+ }
+
+ fn print_adt_expr(&mut self, adt_expr: &AdtExpr<'tcx>, depth_lvl: usize) {
+ print_indented!(self, "adt_def:", depth_lvl);
+ self.print_adt_def(adt_expr.adt_def, depth_lvl + 1);
+ print_indented!(
+ self,
+ format!("variant_index: {:?}", adt_expr.variant_index),
+ depth_lvl + 1
+ );
+ print_indented!(self, format!("substs: {:?}", adt_expr.substs), depth_lvl + 1);
+ print_indented!(self, format!("user_ty: {:?}", adt_expr.user_ty), depth_lvl + 1);
+
+ for (i, field_expr) in adt_expr.fields.iter().enumerate() {
+ print_indented!(self, format!("field {}:", i), depth_lvl + 1);
+ self.print_expr(field_expr.expr, depth_lvl + 2);
+ }
+
+ if let Some(ref base) = adt_expr.base {
+ print_indented!(self, "base:", depth_lvl + 1);
+ self.print_fru_info(base, depth_lvl + 2);
+ } else {
+ print_indented!(self, "base: None", depth_lvl + 1);
+ }
+ }
+
+ fn print_adt_def(&mut self, adt_def: ty::AdtDef<'tcx>, depth_lvl: usize) {
+ print_indented!(self, "AdtDef {", depth_lvl);
+ print_indented!(self, format!("did: {:?}", adt_def.did()), depth_lvl + 1);
+ print_indented!(self, format!("variants: {:?}", adt_def.variants()), depth_lvl + 1);
+ print_indented!(self, format!("flags: {:?}", adt_def.flags()), depth_lvl + 1);
+ print_indented!(self, format!("repr: {:?}", adt_def.repr()), depth_lvl + 1);
+ }
+
+ fn print_fru_info(&mut self, fru_info: &FruInfo<'tcx>, depth_lvl: usize) {
+ print_indented!(self, "FruInfo {", depth_lvl);
+ print_indented!(self, "base: ", depth_lvl + 1);
+ self.print_expr(fru_info.base, depth_lvl + 2);
+ print_indented!(self, "field_types: [", depth_lvl + 1);
+ for ty in fru_info.field_types.iter() {
+ print_indented!(self, format!("ty: {:?}", ty), depth_lvl + 2);
+ }
+ print_indented!(self, "}", depth_lvl);
+ }
+
+ fn print_arm(&mut self, arm_id: ArmId, depth_lvl: usize) {
+ print_indented!(self, "Arm {", depth_lvl);
+
+ let arm = &self.thir.arms[arm_id];
+ let Arm { pattern, guard, body, lint_level, scope, span } = arm;
+
+ print_indented!(self, "pattern: ", depth_lvl + 1);
+ self.print_pat(pattern, depth_lvl + 2);
+
+ if let Some(guard) = guard {
+ print_indented!(self, "guard: ", depth_lvl + 1);
+ self.print_guard(guard, depth_lvl + 2);
+ } else {
+ print_indented!(self, "guard: None", depth_lvl + 1);
+ }
+
+ print_indented!(self, "body: ", depth_lvl + 1);
+ self.print_expr(*body, depth_lvl + 2);
+ print_indented!(self, format!("lint_level: {:?}", lint_level), depth_lvl + 1);
+ print_indented!(self, format!("scope: {:?}", scope), depth_lvl + 1);
+ print_indented!(self, format!("span: {:?}", span), depth_lvl + 1);
+ print_indented!(self, "}", depth_lvl);
+ }
+
+ fn print_pat(&mut self, pat: &Box<Pat<'tcx>>, depth_lvl: usize) {
+ let Pat { ty, span, kind } = &**pat;
+
+ print_indented!(self, "Pat: {", depth_lvl);
+ print_indented!(self, format!("ty: {:?}", ty), depth_lvl + 1);
+ print_indented!(self, format!("span: {:?}", span), depth_lvl + 1);
+ self.print_pat_kind(kind, depth_lvl + 1);
+ print_indented!(self, "}", depth_lvl);
+ }
+
+ fn print_pat_kind(&mut self, pat_kind: &PatKind<'tcx>, depth_lvl: usize) {
+ print_indented!(self, "kind: PatKind {", depth_lvl);
+
+ match pat_kind {
+ PatKind::Wild => {
+ print_indented!(self, "Wild", depth_lvl + 1);
+ }
+ PatKind::AscribeUserType { ascription, subpattern } => {
+ print_indented!(self, "AscribeUserType: {", depth_lvl + 1);
+ print_indented!(self, format!("ascription: {:?}", ascription), depth_lvl + 2);
+ print_indented!(self, "subpattern: ", depth_lvl + 2);
+ self.print_pat(subpattern, depth_lvl + 3);
+ print_indented!(self, "}", depth_lvl + 1);
+ }
+ PatKind::Binding { mutability, name, mode, var, ty, subpattern, is_primary } => {
+ print_indented!(self, "Binding {", depth_lvl + 1);
+ print_indented!(self, format!("mutability: {:?}", mutability), depth_lvl + 2);
+ print_indented!(self, format!("name: {:?}", name), depth_lvl + 2);
+ print_indented!(self, format!("mode: {:?}", mode), depth_lvl + 2);
+ print_indented!(self, format!("var: {:?}", var), depth_lvl + 2);
+ print_indented!(self, format!("ty: {:?}", ty), depth_lvl + 2);
+ print_indented!(self, format!("is_primary: {:?}", is_primary), depth_lvl + 2);
+
+ if let Some(subpattern) = subpattern {
+ print_indented!(self, "subpattern: Some( ", depth_lvl + 2);
+ self.print_pat(subpattern, depth_lvl + 3);
+ print_indented!(self, ")", depth_lvl + 2);
+ } else {
+ print_indented!(self, "subpattern: None", depth_lvl + 2);
+ }
+
+ print_indented!(self, "}", depth_lvl + 1);
+ }
+ PatKind::Variant { adt_def, substs, variant_index, subpatterns } => {
+ print_indented!(self, "Variant {", depth_lvl + 1);
+ print_indented!(self, "adt_def: ", depth_lvl + 2);
+ self.print_adt_def(*adt_def, depth_lvl + 3);
+ print_indented!(self, format!("substs: {:?}", substs), depth_lvl + 2);
+ print_indented!(self, format!("variant_index: {:?}", variant_index), depth_lvl + 2);
+
+ if subpatterns.len() > 0 {
+ print_indented!(self, "subpatterns: [", depth_lvl + 2);
+ for field_pat in subpatterns.iter() {
+ self.print_pat(&field_pat.pattern, depth_lvl + 3);
+ }
+ print_indented!(self, "]", depth_lvl + 2);
+ } else {
+ print_indented!(self, "subpatterns: []", depth_lvl + 2);
+ }
+
+ print_indented!(self, "}", depth_lvl + 1);
+ }
+ PatKind::Leaf { subpatterns } => {
+ print_indented!(self, "Leaf { ", depth_lvl + 1);
+ print_indented!(self, "subpatterns: [", depth_lvl + 2);
+ for field_pat in subpatterns.iter() {
+ self.print_pat(&field_pat.pattern, depth_lvl + 3);
+ }
+ print_indented!(self, "]", depth_lvl + 2);
+ print_indented!(self, "}", depth_lvl + 1);
+ }
+ PatKind::Deref { subpattern } => {
+ print_indented!(self, "Deref { ", depth_lvl + 1);
+ print_indented!(self, "subpattern: ", depth_lvl + 2);
+ self.print_pat(subpattern, depth_lvl + 2);
+ print_indented!(self, "}", depth_lvl + 1);
+ }
+ PatKind::Constant { value } => {
+ print_indented!(self, "Constant {", depth_lvl + 1);
+ print_indented!(self, format!("value: {:?}", value), depth_lvl + 2);
+ print_indented!(self, "}", depth_lvl + 1);
+ }
+ PatKind::Range(pat_range) => {
+ print_indented!(self, format!("Range ( {:?} )", pat_range), depth_lvl + 1);
+ }
+ PatKind::Slice { prefix, slice, suffix } => {
+ print_indented!(self, "Slice {", depth_lvl + 1);
+
+ print_indented!(self, "prefix: [", depth_lvl + 2);
+ for prefix_pat in prefix.iter() {
+ self.print_pat(prefix_pat, depth_lvl + 3);
+ }
+ print_indented!(self, "]", depth_lvl + 2);
+
+ if let Some(slice) = slice {
+ print_indented!(self, "slice: ", depth_lvl + 2);
+ self.print_pat(slice, depth_lvl + 3);
+ }
+
+ print_indented!(self, "suffix: [", depth_lvl + 2);
+ for suffix_pat in suffix.iter() {
+ self.print_pat(suffix_pat, depth_lvl + 3);
+ }
+ print_indented!(self, "]", depth_lvl + 2);
+
+ print_indented!(self, "}", depth_lvl + 1);
+ }
+ PatKind::Array { prefix, slice, suffix } => {
+ print_indented!(self, "Array {", depth_lvl + 1);
+
+ print_indented!(self, "prefix: [", depth_lvl + 2);
+ for prefix_pat in prefix.iter() {
+ self.print_pat(prefix_pat, depth_lvl + 3);
+ }
+ print_indented!(self, "]", depth_lvl + 2);
+
+ if let Some(slice) = slice {
+ print_indented!(self, "slice: ", depth_lvl + 2);
+ self.print_pat(slice, depth_lvl + 3);
+ }
+
+ print_indented!(self, "suffix: [", depth_lvl + 2);
+ for suffix_pat in suffix.iter() {
+ self.print_pat(suffix_pat, depth_lvl + 3);
+ }
+ print_indented!(self, "]", depth_lvl + 2);
+
+ print_indented!(self, "}", depth_lvl + 1);
+ }
+ PatKind::Or { pats } => {
+ print_indented!(self, "Or {", depth_lvl + 1);
+ print_indented!(self, "pats: [", depth_lvl + 2);
+ for pat in pats.iter() {
+ self.print_pat(pat, depth_lvl + 3);
+ }
+ print_indented!(self, "]", depth_lvl + 2);
+ print_indented!(self, "}", depth_lvl + 1);
+ }
+ }
+
+ print_indented!(self, "}", depth_lvl);
+ }
+
+ fn print_guard(&mut self, guard: &Guard<'tcx>, depth_lvl: usize) {
+ print_indented!(self, "Guard {", depth_lvl);
+
+ match guard {
+ Guard::If(expr_id) => {
+ print_indented!(self, "If (", depth_lvl + 1);
+ self.print_expr(*expr_id, depth_lvl + 2);
+ print_indented!(self, ")", depth_lvl + 1);
+ }
+ Guard::IfLet(pat, expr_id) => {
+ print_indented!(self, "IfLet (", depth_lvl + 1);
+ self.print_pat(pat, depth_lvl + 2);
+ print_indented!(self, ",", depth_lvl + 1);
+ self.print_expr(*expr_id, depth_lvl + 2);
+ print_indented!(self, ")", depth_lvl + 1);
+ }
+ }
+
+ print_indented!(self, "}", depth_lvl);
+ }
+
+ fn print_closure_expr(&mut self, expr: &ClosureExpr<'tcx>, depth_lvl: usize) {
+ let ClosureExpr { closure_id, substs, upvars, movability, fake_reads } = expr;
+
+ print_indented!(self, "ClosureExpr {", depth_lvl);
+ print_indented!(self, format!("closure_id: {:?}", closure_id), depth_lvl + 1);
+ print_indented!(self, format!("substs: {:?}", substs), depth_lvl + 1);
+
+ if upvars.len() > 0 {
+ print_indented!(self, "upvars: [", depth_lvl + 1);
+ for upvar in upvars.iter() {
+ self.print_expr(*upvar, depth_lvl + 2);
+ print_indented!(self, ",", depth_lvl + 1);
+ }
+ print_indented!(self, "]", depth_lvl + 1);
+ } else {
+ print_indented!(self, "upvars: []", depth_lvl + 1);
+ }
+
+ print_indented!(self, format!("movability: {:?}", movability), depth_lvl + 1);
+
+ if fake_reads.len() > 0 {
+ print_indented!(self, "fake_reads: [", depth_lvl + 1);
+ for (fake_read_expr, cause, hir_id) in fake_reads.iter() {
+ print_indented!(self, "(", depth_lvl + 2);
+ self.print_expr(*fake_read_expr, depth_lvl + 3);
+ print_indented!(self, ",", depth_lvl + 2);
+ print_indented!(self, format!("cause: {:?}", cause), depth_lvl + 3);
+ print_indented!(self, ",", depth_lvl + 2);
+ print_indented!(self, format!("hir_id: {:?}", hir_id), depth_lvl + 3);
+ print_indented!(self, "),", depth_lvl + 2);
+ }
+ print_indented!(self, "]", depth_lvl + 1);
+ } else {
+ print_indented!(self, "fake_reads: []", depth_lvl + 1);
+ }
+
+ print_indented!(self, "}", depth_lvl);
+ }
+
+ fn print_inline_asm_expr(&mut self, expr: &InlineAsmExpr<'tcx>, depth_lvl: usize) {
+ let InlineAsmExpr { template, operands, options, line_spans } = expr;
+
+ print_indented!(self, "InlineAsmExpr {", depth_lvl);
+
+ print_indented!(self, "template: [", depth_lvl + 1);
+ for template_piece in template.iter() {
+ print_indented!(self, format!("{:?}", template_piece), depth_lvl + 2);
+ }
+ print_indented!(self, "]", depth_lvl + 1);
+
+ print_indented!(self, "operands: [", depth_lvl + 1);
+ for operand in operands.iter() {
+ self.print_inline_operand(operand, depth_lvl + 2);
+ }
+ print_indented!(self, "]", depth_lvl + 1);
+
+ print_indented!(self, format!("options: {:?}", options), depth_lvl + 1);
+ print_indented!(self, format!("line_spans: {:?}", line_spans), depth_lvl + 1);
+ }
+
+ fn print_inline_operand(&mut self, operand: &InlineAsmOperand<'tcx>, depth_lvl: usize) {
+ match operand {
+ InlineAsmOperand::In { reg, expr } => {
+ print_indented!(self, "InlineAsmOperand::In {", depth_lvl);
+ print_indented!(self, format!("reg: {:?}", reg), depth_lvl + 1);
+ print_indented!(self, "expr: ", depth_lvl + 1);
+ self.print_expr(*expr, depth_lvl + 2);
+ print_indented!(self, "}", depth_lvl + 1);
+ }
+ InlineAsmOperand::Out { reg, late, expr } => {
+ print_indented!(self, "InlineAsmOperand::Out {", depth_lvl);
+ print_indented!(self, format!("reg: {:?}", reg), depth_lvl + 1);
+ print_indented!(self, format!("late: {:?}", late), depth_lvl + 1);
+
+ if let Some(out) = expr {
+ print_indented!(self, "place: Some( ", depth_lvl + 1);
+ self.print_expr(*out, depth_lvl + 2);
+ print_indented!(self, ")", depth_lvl + 1);
+ } else {
+ print_indented!(self, "place: None", depth_lvl + 1);
+ }
+ print_indented!(self, "}", depth_lvl + 1);
+ }
+ InlineAsmOperand::InOut { reg, late, expr } => {
+ print_indented!(self, "InlineAsmOperand::InOut {", depth_lvl);
+ print_indented!(self, format!("reg: {:?}", reg), depth_lvl + 1);
+ print_indented!(self, format!("late: {:?}", late), depth_lvl + 1);
+ print_indented!(self, "expr: ", depth_lvl + 1);
+ self.print_expr(*expr, depth_lvl + 2);
+ print_indented!(self, "}", depth_lvl + 1);
+ }
+ InlineAsmOperand::SplitInOut { reg, late, in_expr, out_expr } => {
+ print_indented!(self, "InlineAsmOperand::SplitInOut {", depth_lvl);
+ print_indented!(self, format!("reg: {:?}", reg), depth_lvl + 1);
+ print_indented!(self, format!("late: {:?}", late), depth_lvl + 1);
+ print_indented!(self, "in_expr: ", depth_lvl + 1);
+ self.print_expr(*in_expr, depth_lvl + 2);
+
+ if let Some(out_expr) = out_expr {
+ print_indented!(self, "out_expr: Some( ", depth_lvl + 1);
+ self.print_expr(*out_expr, depth_lvl + 2);
+ print_indented!(self, ")", depth_lvl + 1);
+ } else {
+ print_indented!(self, "out_expr: None", depth_lvl + 1);
+ }
+
+ print_indented!(self, "}", depth_lvl + 1);
+ }
+ InlineAsmOperand::Const { value, span } => {
+ print_indented!(self, "InlineAsmOperand::Const {", depth_lvl);
+ print_indented!(self, format!("value: {:?}", value), depth_lvl + 1);
+ print_indented!(self, format!("span: {:?}", span), depth_lvl + 1);
+ print_indented!(self, "}", depth_lvl + 1);
+ }
+ InlineAsmOperand::SymFn { value, span } => {
+ print_indented!(self, "InlineAsmOperand::SymFn {", depth_lvl);
+ print_indented!(self, format!("value: {:?}", *value), depth_lvl + 1);
+ print_indented!(self, format!("span: {:?}", span), depth_lvl + 1);
+ print_indented!(self, "}", depth_lvl + 1);
+ }
+ InlineAsmOperand::SymStatic { def_id } => {
+ print_indented!(self, "InlineAsmOperand::SymStatic {", depth_lvl);
+ print_indented!(self, format!("def_id: {:?}", def_id), depth_lvl + 1);
+ print_indented!(self, "}", depth_lvl + 1);
+ }
+ }
+ }
+}
diff --git a/compiler/rustc_mir_dataflow/Cargo.toml b/compiler/rustc_mir_dataflow/Cargo.toml
index 324644b67..68c61a18d 100644
--- a/compiler/rustc_mir_dataflow/Cargo.toml
+++ b/compiler/rustc_mir_dataflow/Cargo.toml
@@ -19,6 +19,5 @@ rustc_index = { path = "../rustc_index" }
rustc_macros = { path = "../rustc_macros" }
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_error_messages/locales/en-US/mir_dataflow.ftl b/compiler/rustc_mir_dataflow/locales/en-US.ftl
index 988541525..988541525 100644
--- a/compiler/rustc_error_messages/locales/en-US/mir_dataflow.ftl
+++ b/compiler/rustc_mir_dataflow/locales/en-US.ftl
diff --git a/compiler/rustc_mir_dataflow/src/drop_flag_effects.rs b/compiler/rustc_mir_dataflow/src/drop_flag_effects.rs
index 3224e13f7..0d466bbe5 100644
--- a/compiler/rustc_mir_dataflow/src/drop_flag_effects.rs
+++ b/compiler/rustc_mir_dataflow/src/drop_flag_effects.rs
@@ -1,5 +1,5 @@
use crate::elaborate_drops::DropFlagState;
-use rustc_middle::mir::{self, Body, Location};
+use rustc_middle::mir::{self, Body, Location, Terminator, TerminatorKind};
use rustc_middle::ty::{self, TyCtxt};
use rustc_target::abi::VariantIdx;
@@ -194,6 +194,17 @@ pub fn drop_flag_effects_for_location<'tcx, F>(
on_all_children_bits(tcx, body, move_data, path, |mpi| callback(mpi, DropFlagState::Absent))
}
+ // Drop does not count as a move but we should still consider the variable uninitialized.
+ if let Some(Terminator { kind: TerminatorKind::Drop { place, .. }, .. }) =
+ body.stmt_at(loc).right()
+ {
+ if let LookupResult::Exact(mpi) = move_data.rev_lookup.find(place.as_ref()) {
+ on_all_children_bits(tcx, body, move_data, mpi, |mpi| {
+ callback(mpi, DropFlagState::Absent)
+ })
+ }
+ }
+
debug!("drop_flag_effects: assignment for location({:?})", loc);
for_location_inits(tcx, body, move_data, loc, |mpi| callback(mpi, DropFlagState::Present));
diff --git a/compiler/rustc_mir_dataflow/src/elaborate_drops.rs b/compiler/rustc_mir_dataflow/src/elaborate_drops.rs
index 7836ae2e7..bd1208762 100644
--- a/compiler/rustc_mir_dataflow/src/elaborate_drops.rs
+++ b/compiler/rustc_mir_dataflow/src/elaborate_drops.rs
@@ -890,7 +890,7 @@ where
}
ty::Dynamic(..) => self.complete_drop(self.succ, self.unwind),
ty::Array(ety, size) => {
- let size = size.try_eval_usize(self.tcx(), self.elaborator.param_env());
+ let size = size.try_eval_target_usize(self.tcx(), self.elaborator.param_env());
self.open_drop_for_array(*ety, size)
}
ty::Slice(ety) => self.open_drop_for_array(*ety, None),
diff --git a/compiler/rustc_mir_dataflow/src/framework/direction.rs b/compiler/rustc_mir_dataflow/src/framework/direction.rs
index 077a21fc8..2ae3ae02f 100644
--- a/compiler/rustc_mir_dataflow/src/framework/direction.rs
+++ b/compiler/rustc_mir_dataflow/src/framework/direction.rs
@@ -1,4 +1,3 @@
-use rustc_index::bit_set::BitSet;
use rustc_middle::mir::{self, BasicBlock, Location, SwitchTargets};
use rustc_middle::ty::TyCtxt;
use std::ops::RangeInclusive;
@@ -54,7 +53,6 @@ pub trait Direction {
analysis: &A,
tcx: TyCtxt<'tcx>,
body: &mir::Body<'tcx>,
- dead_unwinds: Option<&BitSet<BasicBlock>>,
exit_state: &mut A::Domain,
block: (BasicBlock, &'_ mir::BasicBlockData<'tcx>),
propagate: impl FnMut(BasicBlock, &A::Domain),
@@ -221,7 +219,6 @@ impl Direction for Backward {
analysis: &A,
_tcx: TyCtxt<'tcx>,
body: &mir::Body<'tcx>,
- dead_unwinds: Option<&BitSet<BasicBlock>>,
exit_state: &mut A::Domain,
(bb, _bb_data): (BasicBlock, &'_ mir::BasicBlockData<'tcx>),
mut propagate: impl FnMut(BasicBlock, &A::Domain),
@@ -278,20 +275,6 @@ impl Direction for Backward {
}
}
- // Ignore dead unwinds.
- mir::TerminatorKind::Call { cleanup: Some(unwind), .. }
- | mir::TerminatorKind::Assert { cleanup: Some(unwind), .. }
- | mir::TerminatorKind::Drop { unwind: Some(unwind), .. }
- | mir::TerminatorKind::DropAndReplace { unwind: Some(unwind), .. }
- | mir::TerminatorKind::FalseUnwind { unwind: Some(unwind), .. }
- | mir::TerminatorKind::InlineAsm { cleanup: Some(unwind), .. }
- if unwind == bb =>
- {
- if dead_unwinds.map_or(true, |dead| !dead.contains(pred)) {
- propagate(pred, exit_state);
- }
- }
-
_ => propagate(pred, exit_state),
}
}
@@ -304,7 +287,6 @@ struct BackwardSwitchIntEdgeEffectsApplier<'a, 'tcx, D, F> {
exit_state: &'a mut D,
bb: BasicBlock,
propagate: &'a mut F,
-
effects_applied: bool,
}
@@ -484,7 +466,6 @@ impl Direction for Forward {
analysis: &A,
_tcx: TyCtxt<'tcx>,
_body: &mir::Body<'tcx>,
- dead_unwinds: Option<&BitSet<BasicBlock>>,
exit_state: &mut A::Domain,
(bb, bb_data): (BasicBlock, &'_ mir::BasicBlockData<'tcx>),
mut propagate: impl FnMut(BasicBlock, &A::Domain),
@@ -502,9 +483,7 @@ impl Direction for Forward {
| DropAndReplace { target, unwind, value: _, place: _ }
| FalseUnwind { real_target: target, unwind } => {
if let Some(unwind) = unwind {
- if dead_unwinds.map_or(true, |dead| !dead.contains(bb)) {
- propagate(unwind, exit_state);
- }
+ propagate(unwind, exit_state);
}
propagate(target, exit_state);
@@ -534,9 +513,7 @@ impl Direction for Forward {
fn_span: _,
} => {
if let Some(unwind) = cleanup {
- if dead_unwinds.map_or(true, |dead| !dead.contains(bb)) {
- propagate(unwind, exit_state);
- }
+ propagate(unwind, exit_state);
}
if let Some(target) = target {
@@ -560,9 +537,7 @@ impl Direction for Forward {
cleanup,
} => {
if let Some(unwind) = cleanup {
- if dead_unwinds.map_or(true, |dead| !dead.contains(bb)) {
- propagate(unwind, exit_state);
- }
+ propagate(unwind, exit_state);
}
if let Some(target) = destination {
diff --git a/compiler/rustc_mir_dataflow/src/framework/engine.rs b/compiler/rustc_mir_dataflow/src/framework/engine.rs
index 6ddbe69e1..91c3bf0ad 100644
--- a/compiler/rustc_mir_dataflow/src/framework/engine.rs
+++ b/compiler/rustc_mir_dataflow/src/framework/engine.rs
@@ -12,7 +12,6 @@ use rustc_ast as ast;
use rustc_data_structures::work_queue::WorkQueue;
use rustc_graphviz as dot;
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};
@@ -78,7 +77,6 @@ where
{
tcx: TyCtxt<'tcx>,
body: &'a mir::Body<'tcx>,
- dead_unwinds: Option<&'a BitSet<BasicBlock>>,
entry_sets: IndexVec<BasicBlock, A::Domain>,
pass_name: Option<&'static str>,
analysis: A,
@@ -154,25 +152,7 @@ where
bug!("`initialize_start_block` is not yet supported for backward dataflow analyses");
}
- Engine {
- analysis,
- tcx,
- body,
- dead_unwinds: None,
- pass_name: None,
- entry_sets,
- apply_trans_for_block,
- }
- }
-
- /// Signals that we do not want dataflow state to propagate across unwind edges for these
- /// `BasicBlock`s.
- ///
- /// You must take care that `dead_unwinds` does not contain a `BasicBlock` that *can* actually
- /// unwind during execution. Otherwise, your dataflow results will not be correct.
- pub fn dead_unwinds(mut self, dead_unwinds: &'a BitSet<BasicBlock>) -> Self {
- self.dead_unwinds = Some(dead_unwinds);
- self
+ Engine { analysis, tcx, body, pass_name: None, entry_sets, apply_trans_for_block }
}
/// Adds an identifier to the graphviz output for this particular run of a dataflow analysis.
@@ -190,14 +170,7 @@ where
A::Domain: DebugWithContext<A>,
{
let Engine {
- analysis,
- body,
- dead_unwinds,
- mut entry_sets,
- tcx,
- apply_trans_for_block,
- pass_name,
- ..
+ analysis, body, mut entry_sets, tcx, apply_trans_for_block, pass_name, ..
} = self;
let mut dirty_queue: WorkQueue<BasicBlock> = WorkQueue::with_none(body.basic_blocks.len());
@@ -236,7 +209,6 @@ where
&analysis,
tcx,
body,
- dead_unwinds,
&mut state,
(bb, bb_data),
|target: BasicBlock, state: &A::Domain| {
diff --git a/compiler/rustc_mir_dataflow/src/impls/borrowed_locals.rs b/compiler/rustc_mir_dataflow/src/impls/borrowed_locals.rs
index 0f8e86d1d..6f4e7fd46 100644
--- a/compiler/rustc_mir_dataflow/src/impls/borrowed_locals.rs
+++ b/compiler/rustc_mir_dataflow/src/impls/borrowed_locals.rs
@@ -121,7 +121,9 @@ where
// for now. See discussion on [#61069].
//
// [#61069]: https://github.com/rust-lang/rust/pull/61069
- self.trans.gen(dropped_place.local);
+ if !dropped_place.is_indirect() {
+ self.trans.gen(dropped_place.local);
+ }
}
TerminatorKind::Abort
diff --git a/compiler/rustc_mir_dataflow/src/impls/liveness.rs b/compiler/rustc_mir_dataflow/src/impls/liveness.rs
index 923dc16c1..633a5674f 100644
--- a/compiler/rustc_mir_dataflow/src/impls/liveness.rs
+++ b/compiler/rustc_mir_dataflow/src/impls/liveness.rs
@@ -254,13 +254,7 @@ impl<'a, 'tcx> Analysis<'tcx> for MaybeTransitiveLiveLocals<'a> {
) {
// Compute the place that we are storing to, if any
let destination = match &statement.kind {
- StatementKind::Assign(assign) => {
- if assign.1.is_safe_to_remove() {
- Some(assign.0)
- } else {
- None
- }
- }
+ StatementKind::Assign(assign) => assign.1.is_safe_to_remove().then_some(assign.0),
StatementKind::SetDiscriminant { place, .. } | StatementKind::Deinit(place) => {
Some(**place)
}
@@ -271,6 +265,7 @@ impl<'a, 'tcx> Analysis<'tcx> for MaybeTransitiveLiveLocals<'a> {
| StatementKind::AscribeUserType(..)
| StatementKind::Coverage(..)
| StatementKind::Intrinsic(..)
+ | StatementKind::ConstEvalCounter
| StatementKind::Nop => None,
};
if let Some(destination) = destination {
diff --git a/compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs b/compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs
index 8d379b90a..fcf0ce9d8 100644
--- a/compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs
+++ b/compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs
@@ -141,6 +141,7 @@ impl<'mir, 'tcx> crate::GenKillAnalysis<'tcx> for MaybeRequiresStorage<'mir, 'tc
StatementKind::AscribeUserType(..)
| StatementKind::Coverage(..)
| StatementKind::FakeRead(..)
+ | StatementKind::ConstEvalCounter
| StatementKind::Nop
| StatementKind::Retag(..)
| StatementKind::Intrinsic(..)
diff --git a/compiler/rustc_mir_dataflow/src/lib.rs b/compiler/rustc_mir_dataflow/src/lib.rs
index 7f40cfca3..b1e03faff 100644
--- a/compiler/rustc_mir_dataflow/src/lib.rs
+++ b/compiler/rustc_mir_dataflow/src/lib.rs
@@ -1,6 +1,7 @@
#![feature(associated_type_defaults)]
#![feature(box_patterns)]
#![feature(exact_size_is_empty)]
+#![feature(let_chains)]
#![feature(min_specialization)]
#![feature(once_cell)]
#![feature(stmt_expr_attributes)]
@@ -15,7 +16,9 @@ extern crate tracing;
extern crate rustc_middle;
use rustc_ast::MetaItem;
+use rustc_errors::{DiagnosticMessage, SubdiagnosticMessage};
use rustc_hir::def_id::DefId;
+use rustc_macros::fluent_messages;
use rustc_middle::ty::{self, TyCtxt};
use rustc_span::symbol::{sym, Symbol};
@@ -43,6 +46,8 @@ pub mod storage;
pub mod un_derefer;
pub mod value_analysis;
+fluent_messages! { "../locales/en-US.ftl" }
+
pub(crate) mod indexes {
pub(crate) use super::move_paths::MovePathIndex;
}
diff --git a/compiler/rustc_mir_dataflow/src/move_paths/builder.rs b/compiler/rustc_mir_dataflow/src/move_paths/builder.rs
index f46fd118b..4a163028f 100644
--- a/compiler/rustc_mir_dataflow/src/move_paths/builder.rs
+++ b/compiler/rustc_mir_dataflow/src/move_paths/builder.rs
@@ -126,7 +126,7 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> {
BorrowedContent {
target_place: Place {
local: place.local,
- projection: tcx.intern_place_elems(proj),
+ projection: tcx.mk_place_elems(proj),
},
},
));
@@ -165,7 +165,7 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> {
if union_path.is_none() {
base = self.add_move_path(base, elem, |tcx| Place {
local: place.local,
- projection: tcx.intern_place_elems(&place.projection[..i + 1]),
+ projection: tcx.mk_place_elems(&place.projection[..i + 1]),
});
}
}
@@ -331,6 +331,7 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> {
| StatementKind::AscribeUserType(..)
| StatementKind::Coverage(..)
| StatementKind::Intrinsic(..)
+ | StatementKind::ConstEvalCounter
| StatementKind::Nop => {}
}
}
@@ -375,7 +376,8 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> {
| TerminatorKind::Resume
| TerminatorKind::Abort
| TerminatorKind::GeneratorDrop
- | TerminatorKind::Unreachable => {}
+ | TerminatorKind::Unreachable
+ | TerminatorKind::Drop { .. } => {}
TerminatorKind::Assert { ref cond, .. } => {
self.gather_operand(cond);
@@ -390,10 +392,6 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> {
self.create_move_path(place);
self.gather_init(place.as_ref(), InitKind::Deep);
}
-
- TerminatorKind::Drop { place, target: _, unwind: _ } => {
- self.gather_move(place);
- }
TerminatorKind::DropAndReplace { place, ref value, .. } => {
self.create_move_path(place);
self.gather_operand(value);
@@ -478,7 +476,7 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> {
// `ConstIndex` patterns. This is done to ensure that all move paths
// are disjoint, which is expected by drop elaboration.
let base_place =
- Place { local: place.local, projection: self.builder.tcx.intern_place_elems(base) };
+ Place { local: place.local, projection: self.builder.tcx.mk_place_elems(base) };
let base_path = match self.move_path_for(base_place) {
Ok(path) => path,
Err(MoveError::UnionMove { path }) => {
@@ -492,7 +490,9 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> {
};
let base_ty = base_place.ty(self.builder.body, self.builder.tcx).ty;
let len: u64 = match base_ty.kind() {
- ty::Array(_, size) => size.eval_usize(self.builder.tcx, self.builder.param_env),
+ ty::Array(_, size) => {
+ size.eval_target_usize(self.builder.tcx, self.builder.param_env)
+ }
_ => bug!("from_end: false slice pattern of non-array type"),
};
for offset in from..to {
diff --git a/compiler/rustc_mir_dataflow/src/value_analysis.rs b/compiler/rustc_mir_dataflow/src/value_analysis.rs
index 0522c6579..401db890a 100644
--- a/compiler/rustc_mir_dataflow/src/value_analysis.rs
+++ b/compiler/rustc_mir_dataflow/src/value_analysis.rs
@@ -24,7 +24,7 @@
//! - The bottom state denotes uninitialized memory. Because we are only doing a sound approximation
//! of the actual execution, we can also use this state for places where access would be UB.
//!
-//! - The assignment logic in `State::assign_place_idx` assumes that the places are non-overlapping,
+//! - The assignment logic in `State::insert_place_idx` assumes that the places are non-overlapping,
//! or identical. Note that this refers to place expressions, not memory locations.
//!
//! - Currently, places that have their reference taken cannot be tracked. Although this would be
@@ -35,6 +35,7 @@
use std::fmt::{Debug, Formatter};
use rustc_data_structures::fx::FxHashMap;
+use rustc_index::bit_set::BitSet;
use rustc_index::vec::IndexVec;
use rustc_middle::mir::visit::{MutatingUseContext, PlaceContext, Visitor};
use rustc_middle::mir::*;
@@ -64,10 +65,8 @@ pub trait ValueAnalysis<'tcx> {
StatementKind::Assign(box (place, rvalue)) => {
self.handle_assign(*place, rvalue, state);
}
- StatementKind::SetDiscriminant { .. } => {
- // Could treat this as writing a constant to a pseudo-place.
- // But discriminants are currently not tracked, so we do nothing.
- // Related: https://github.com/rust-lang/unsafe-code-guidelines/issues/84
+ StatementKind::SetDiscriminant { box ref place, .. } => {
+ state.flood_discr(place.as_ref(), self.map());
}
StatementKind::Intrinsic(box intrinsic) => {
self.handle_intrinsic(intrinsic, state);
@@ -84,7 +83,8 @@ pub trait ValueAnalysis<'tcx> {
StatementKind::Retag(..) => {
// We don't track references.
}
- StatementKind::Nop
+ StatementKind::ConstEvalCounter
+ | StatementKind::Nop
| StatementKind::FakeRead(..)
| StatementKind::Coverage(..)
| StatementKind::AscribeUserType(..) => (),
@@ -222,13 +222,13 @@ pub trait ValueAnalysis<'tcx> {
self.super_terminator(terminator, state)
}
- fn super_terminator(&self, terminator: &Terminator<'tcx>, _state: &mut State<Self::Value>) {
+ fn super_terminator(&self, terminator: &Terminator<'tcx>, state: &mut State<Self::Value>) {
match &terminator.kind {
TerminatorKind::Call { .. } | TerminatorKind::InlineAsm { .. } => {
// Effect is applied by `handle_call_return`.
}
- TerminatorKind::Drop { .. } => {
- // We don't track dropped places.
+ TerminatorKind::Drop { place, .. } => {
+ state.flood_with(place.as_ref(), self.map(), Self::Value::bottom());
}
TerminatorKind::DropAndReplace { .. } | TerminatorKind::Yield { .. } => {
// They would have an effect, but are not allowed in this phase.
@@ -445,26 +445,51 @@ impl<V: Clone + HasTop + HasBottom> State<V> {
}
pub fn flood_with(&mut self, place: PlaceRef<'_>, map: &Map, value: V) {
- if let Some(root) = map.find(place) {
- self.flood_idx_with(root, map, value);
- }
+ let StateData::Reachable(values) = &mut self.0 else { return };
+ map.for_each_aliasing_place(place, None, &mut |place| {
+ if let Some(vi) = map.places[place].value_index {
+ values[vi] = value.clone();
+ }
+ });
}
pub fn flood(&mut self, place: PlaceRef<'_>, map: &Map) {
self.flood_with(place, map, V::top())
}
- pub fn flood_idx_with(&mut self, place: PlaceIndex, map: &Map, value: V) {
+ pub fn flood_discr_with(&mut self, place: PlaceRef<'_>, map: &Map, value: V) {
let StateData::Reachable(values) = &mut self.0 else { return };
- map.preorder_invoke(place, &mut |place| {
+ map.for_each_aliasing_place(place, Some(TrackElem::Discriminant), &mut |place| {
if let Some(vi) = map.places[place].value_index {
values[vi] = value.clone();
}
});
}
- pub fn flood_idx(&mut self, place: PlaceIndex, map: &Map) {
- self.flood_idx_with(place, map, V::top())
+ pub fn flood_discr(&mut self, place: PlaceRef<'_>, map: &Map) {
+ self.flood_discr_with(place, map, V::top())
+ }
+
+ /// Low-level method that assigns to a place.
+ /// This does nothing if the place is not tracked.
+ ///
+ /// The target place must have been flooded before calling this method.
+ pub fn insert_idx(&mut self, target: PlaceIndex, result: ValueOrPlace<V>, map: &Map) {
+ match result {
+ ValueOrPlace::Value(value) => self.insert_value_idx(target, value, map),
+ ValueOrPlace::Place(source) => self.insert_place_idx(target, source, map),
+ }
+ }
+
+ /// Low-level method that assigns a value to a place.
+ /// This does nothing if the place is not tracked.
+ ///
+ /// The target place must have been flooded before calling this method.
+ pub fn insert_value_idx(&mut self, target: PlaceIndex, value: V, map: &Map) {
+ let StateData::Reachable(values) = &mut self.0 else { return };
+ if let Some(value_index) = map.places[target].value_index {
+ values[value_index] = value;
+ }
}
/// Copies `source` to `target`, including all tracked places beneath.
@@ -472,50 +497,41 @@ impl<V: Clone + HasTop + HasBottom> State<V> {
/// If `target` contains a place that is not contained in `source`, it will be overwritten with
/// Top. Also, because this will copy all entries one after another, it may only be used for
/// places that are non-overlapping or identical.
- pub fn assign_place_idx(&mut self, target: PlaceIndex, source: PlaceIndex, map: &Map) {
+ ///
+ /// The target place must have been flooded before calling this method.
+ fn insert_place_idx(&mut self, target: PlaceIndex, source: PlaceIndex, map: &Map) {
let StateData::Reachable(values) = &mut self.0 else { return };
- // If both places are tracked, we copy the value to the target. If the target is tracked,
- // but the source is not, we have to invalidate the value in target. If the target is not
- // tracked, then we don't have to do anything.
+ // If both places are tracked, we copy the value to the target.
+ // If the target is tracked, but the source is not, we do nothing, as invalidation has
+ // already been performed.
if let Some(target_value) = map.places[target].value_index {
if let Some(source_value) = map.places[source].value_index {
values[target_value] = values[source_value].clone();
- } else {
- values[target_value] = V::top();
}
}
for target_child in map.children(target) {
// Try to find corresponding child and recurse. Reasoning is similar as above.
let projection = map.places[target_child].proj_elem.unwrap();
if let Some(source_child) = map.projections.get(&(source, projection)) {
- self.assign_place_idx(target_child, *source_child, map);
- } else {
- self.flood_idx(target_child, map);
+ self.insert_place_idx(target_child, *source_child, map);
}
}
}
+ /// Helper method to interpret `target = result`.
pub fn assign(&mut self, target: PlaceRef<'_>, result: ValueOrPlace<V>, map: &Map) {
+ self.flood(target, map);
if let Some(target) = map.find(target) {
- self.assign_idx(target, result, map);
- } else {
- // We don't track this place nor any projections, assignment can be ignored.
+ self.insert_idx(target, result, map);
}
}
- pub fn assign_idx(&mut self, target: PlaceIndex, result: ValueOrPlace<V>, map: &Map) {
- match result {
- ValueOrPlace::Value(value) => {
- // First flood the target place in case we also track any projections (although
- // this scenario is currently not well-supported by the API).
- self.flood_idx(target, map);
- let StateData::Reachable(values) = &mut self.0 else { return };
- if let Some(value_index) = map.places[target].value_index {
- values[value_index] = value;
- }
- }
- ValueOrPlace::Place(source) => self.assign_place_idx(target, source, map),
+ /// Helper method for assignments to a discriminant.
+ pub fn assign_discr(&mut self, target: PlaceRef<'_>, result: ValueOrPlace<V>, map: &Map) {
+ self.flood_discr(target, map);
+ if let Some(target) = map.find_discr(target) {
+ self.insert_idx(target, result, map);
}
}
@@ -524,6 +540,14 @@ impl<V: Clone + HasTop + HasBottom> State<V> {
map.find(place).map(|place| self.get_idx(place, map)).unwrap_or(V::top())
}
+ /// Retrieve the value stored for a place, or ⊤ if it is not tracked.
+ pub fn get_discr(&self, place: PlaceRef<'_>, map: &Map) -> V {
+ match map.find_discr(place) {
+ Some(place) => self.get_idx(place, map),
+ None => V::top(),
+ }
+ }
+
/// Retrieve the value stored for a place index, or ⊤ if it is not tracked.
pub fn get_idx(&self, place: PlaceIndex, map: &Map) -> V {
match &self.0 {
@@ -580,15 +604,15 @@ impl Map {
/// This is currently the only way to create a [`Map`]. The way in which the tracked places are
/// chosen is an implementation detail and may not be relied upon (other than that their type
/// passes the filter).
- #[instrument(skip_all, level = "debug")]
pub fn from_filter<'tcx>(
tcx: TyCtxt<'tcx>,
body: &Body<'tcx>,
filter: impl FnMut(Ty<'tcx>) -> bool,
+ place_limit: Option<usize>,
) -> Self {
let mut map = Self::new();
let exclude = excluded_locals(body);
- map.register_with_filter(tcx, body, filter, &exclude);
+ map.register_with_filter(tcx, body, filter, exclude, place_limit);
debug!("registered {} places ({} nodes in total)", map.value_count, map.places.len());
map
}
@@ -599,20 +623,28 @@ impl Map {
tcx: TyCtxt<'tcx>,
body: &Body<'tcx>,
mut filter: impl FnMut(Ty<'tcx>) -> bool,
- exclude: &IndexVec<Local, bool>,
+ exclude: BitSet<Local>,
+ place_limit: Option<usize>,
) {
// We use this vector as stack, pushing and popping projections.
let mut projection = Vec::new();
for (local, decl) in body.local_decls.iter_enumerated() {
- if !exclude[local] {
- self.register_with_filter_rec(tcx, local, &mut projection, decl.ty, &mut filter);
+ if !exclude.contains(local) {
+ self.register_with_filter_rec(
+ tcx,
+ local,
+ &mut projection,
+ decl.ty,
+ &mut filter,
+ place_limit,
+ );
}
}
}
/// Potentially register the (local, projection) place and its fields, recursively.
///
- /// Invariant: The projection must only contain fields.
+ /// Invariant: The projection must only contain trackable elements.
fn register_with_filter_rec<'tcx>(
&mut self,
tcx: TyCtxt<'tcx>,
@@ -620,27 +652,56 @@ impl Map {
projection: &mut Vec<PlaceElem<'tcx>>,
ty: Ty<'tcx>,
filter: &mut impl FnMut(Ty<'tcx>) -> bool,
+ place_limit: Option<usize>,
) {
- // Note: The framework supports only scalars for now.
- if filter(ty) && ty.is_scalar() {
- // We know that the projection only contains trackable elements.
- let place = self.make_place(local, projection).unwrap();
+ if let Some(place_limit) = place_limit && self.value_count >= place_limit {
+ return
+ }
- // Allocate a value slot if it doesn't have one.
- if self.places[place].value_index.is_none() {
- self.places[place].value_index = Some(self.value_count.into());
- self.value_count += 1;
+ // We know that the projection only contains trackable elements.
+ let place = self.make_place(local, projection).unwrap();
+
+ // Allocate a value slot if it doesn't have one, and the user requested one.
+ if self.places[place].value_index.is_none() && filter(ty) {
+ self.places[place].value_index = Some(self.value_count.into());
+ self.value_count += 1;
+ }
+
+ if ty.is_enum() {
+ let discr_ty = ty.discriminant_ty(tcx);
+ if filter(discr_ty) {
+ let discr = *self
+ .projections
+ .entry((place, TrackElem::Discriminant))
+ .or_insert_with(|| {
+ // Prepend new child to the linked list.
+ let next = self.places.push(PlaceInfo::new(Some(TrackElem::Discriminant)));
+ self.places[next].next_sibling = self.places[place].first_child;
+ self.places[place].first_child = Some(next);
+ next
+ });
+
+ // Allocate a value slot if it doesn't have one.
+ if self.places[discr].value_index.is_none() {
+ self.places[discr].value_index = Some(self.value_count.into());
+ self.value_count += 1;
+ }
}
}
// Recurse with all fields of this place.
iter_fields(ty, tcx, |variant, field, ty| {
- if variant.is_some() {
- // Downcasts are currently not supported.
+ if let Some(variant) = variant {
+ projection.push(PlaceElem::Downcast(None, variant));
+ let _ = self.make_place(local, projection);
+ projection.push(PlaceElem::Field(field, ty));
+ self.register_with_filter_rec(tcx, local, projection, ty, filter, place_limit);
+ projection.pop();
+ projection.pop();
return;
}
projection.push(PlaceElem::Field(field, ty));
- self.register_with_filter_rec(tcx, local, projection, ty, filter);
+ self.register_with_filter_rec(tcx, local, projection, ty, filter, place_limit);
projection.pop();
});
}
@@ -683,23 +744,105 @@ impl Map {
}
/// Locates the given place, if it exists in the tree.
- pub fn find(&self, place: PlaceRef<'_>) -> Option<PlaceIndex> {
+ pub fn find_extra(
+ &self,
+ place: PlaceRef<'_>,
+ extra: impl IntoIterator<Item = TrackElem>,
+ ) -> Option<PlaceIndex> {
let mut index = *self.locals.get(place.local)?.as_ref()?;
for &elem in place.projection {
index = self.apply(index, elem.try_into().ok()?)?;
}
+ for elem in extra {
+ index = self.apply(index, elem)?;
+ }
Some(index)
}
+ /// Locates the given place, if it exists in the tree.
+ pub fn find(&self, place: PlaceRef<'_>) -> Option<PlaceIndex> {
+ self.find_extra(place, [])
+ }
+
+ /// Locates the given place and applies `Discriminant`, if it exists in the tree.
+ pub fn find_discr(&self, place: PlaceRef<'_>) -> Option<PlaceIndex> {
+ self.find_extra(place, [TrackElem::Discriminant])
+ }
+
/// Iterate over all direct children.
pub fn children(&self, parent: PlaceIndex) -> impl Iterator<Item = PlaceIndex> + '_ {
Children::new(self, parent)
}
+ /// Invoke a function on the given place and all places that may alias it.
+ ///
+ /// In particular, when the given place has a variant downcast, we invoke the function on all
+ /// the other variants.
+ ///
+ /// `tail_elem` allows to support discriminants that are not a place in MIR, but that we track
+ /// as such.
+ pub fn for_each_aliasing_place(
+ &self,
+ place: PlaceRef<'_>,
+ tail_elem: Option<TrackElem>,
+ f: &mut impl FnMut(PlaceIndex),
+ ) {
+ if place.is_indirect() {
+ // We do not track indirect places.
+ return;
+ }
+ let Some(&Some(mut index)) = self.locals.get(place.local) else {
+ // The local is not tracked at all, so it does not alias anything.
+ return;
+ };
+ let elems = place
+ .projection
+ .iter()
+ .map(|&elem| elem.try_into())
+ .chain(tail_elem.map(Ok).into_iter());
+ for elem in elems {
+ // A field aliases the parent place.
+ f(index);
+
+ let Ok(elem) = elem else { return };
+ let sub = self.apply(index, elem);
+ if let TrackElem::Variant(..) | TrackElem::Discriminant = elem {
+ // Enum variant fields and enum discriminants alias each another.
+ self.for_each_variant_sibling(index, sub, f);
+ }
+ if let Some(sub) = sub {
+ index = sub
+ } else {
+ return;
+ }
+ }
+ self.preorder_invoke(index, f);
+ }
+
+ /// Invoke the given function on all the descendants of the given place, except one branch.
+ fn for_each_variant_sibling(
+ &self,
+ parent: PlaceIndex,
+ preserved_child: Option<PlaceIndex>,
+ f: &mut impl FnMut(PlaceIndex),
+ ) {
+ for sibling in self.children(parent) {
+ let elem = self.places[sibling].proj_elem;
+ // Only invalidate variants and discriminant. Fields (for generators) are not
+ // invalidated by assignment to a variant.
+ if let Some(TrackElem::Variant(..) | TrackElem::Discriminant) = elem
+ // Only invalidate the other variants, the current one is fine.
+ && Some(sibling) != preserved_child
+ {
+ self.preorder_invoke(sibling, f);
+ }
+ }
+ }
+
/// Invoke a function on the given place and all descendants.
- pub fn preorder_invoke(&self, root: PlaceIndex, f: &mut impl FnMut(PlaceIndex)) {
+ fn preorder_invoke(&self, root: PlaceIndex, f: &mut impl FnMut(PlaceIndex)) {
f(root);
for child in self.children(root) {
self.preorder_invoke(child, f);
@@ -758,6 +901,7 @@ impl<'a> Iterator for Children<'a> {
}
/// Used as the result of an operand or r-value.
+#[derive(Debug)]
pub enum ValueOrPlace<V> {
Value(V),
Place(PlaceIndex),
@@ -775,6 +919,8 @@ impl<V: HasTop> ValueOrPlace<V> {
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
pub enum TrackElem {
Field(Field),
+ Variant(VariantIdx),
+ Discriminant,
}
impl<V, T> TryFrom<ProjectionElem<V, T>> for TrackElem {
@@ -783,13 +929,14 @@ impl<V, T> TryFrom<ProjectionElem<V, T>> for TrackElem {
fn try_from(value: ProjectionElem<V, T>) -> Result<Self, Self::Error> {
match value {
ProjectionElem::Field(field, _) => Ok(TrackElem::Field(field)),
+ ProjectionElem::Downcast(_, idx) => Ok(TrackElem::Variant(idx)),
_ => Err(()),
}
}
}
/// Invokes `f` on all direct fields of `ty`.
-fn iter_fields<'tcx>(
+pub fn iter_fields<'tcx>(
ty: Ty<'tcx>,
tcx: TyCtxt<'tcx>,
mut f: impl FnMut(Option<VariantIdx>, Field, Ty<'tcx>),
@@ -823,26 +970,27 @@ fn iter_fields<'tcx>(
}
/// Returns all locals with projections that have their reference or address taken.
-fn excluded_locals(body: &Body<'_>) -> IndexVec<Local, bool> {
+pub fn excluded_locals(body: &Body<'_>) -> BitSet<Local> {
struct Collector {
- result: IndexVec<Local, bool>,
+ result: BitSet<Local>,
}
impl<'tcx> Visitor<'tcx> for Collector {
fn visit_place(&mut self, place: &Place<'tcx>, context: PlaceContext, _location: Location) {
- if context.is_borrow()
+ if (context.is_borrow()
|| context.is_address_of()
|| context.is_drop()
- || context == PlaceContext::MutatingUse(MutatingUseContext::AsmOutput)
+ || context == PlaceContext::MutatingUse(MutatingUseContext::AsmOutput))
+ && !place.is_indirect()
{
// A pointer to a place could be used to access other places with the same local,
// hence we have to exclude the local completely.
- self.result[place.local] = true;
+ self.result.insert(place.local);
}
}
}
- let mut collector = Collector { result: IndexVec::from_elem(false, &body.local_decls) };
+ let mut collector = Collector { result: BitSet::new_empty(body.local_decls.len()) };
collector.visit_body(body);
collector.result
}
@@ -898,6 +1046,12 @@ fn debug_with_context_rec<V: Debug + Eq>(
for child in map.children(place) {
let info_elem = map.places[child].proj_elem.unwrap();
let child_place_str = match info_elem {
+ TrackElem::Discriminant => {
+ format!("discriminant({})", place_str)
+ }
+ TrackElem::Variant(idx) => {
+ format!("({} as {:?})", place_str, idx)
+ }
TrackElem::Field(field) => {
if place_str.starts_with('*') {
format!("({}).{}", place_str, field.index())
diff --git a/compiler/rustc_mir_transform/src/abort_unwinding_calls.rs b/compiler/rustc_mir_transform/src/abort_unwinding_calls.rs
index d8f85d2e3..9b4b72070 100644
--- a/compiler/rustc_mir_transform/src/abort_unwinding_calls.rs
+++ b/compiler/rustc_mir_transform/src/abort_unwinding_calls.rs
@@ -41,7 +41,7 @@ impl<'tcx> MirPass<'tcx> for AbortUnwindingCalls {
//
// Here we test for this function itself whether its ABI allows
// unwinding or not.
- let body_ty = tcx.type_of(def_id);
+ let body_ty = tcx.type_of(def_id).skip_binder();
let body_abi = match body_ty.kind() {
ty::FnDef(..) => body_ty.fn_sig(tcx).abi(),
ty::Closure(..) => Abi::RustCall,
diff --git a/compiler/rustc_mir_transform/src/check_const_item_mutation.rs b/compiler/rustc_mir_transform/src/check_const_item_mutation.rs
index fa5f392fa..536745d2c 100644
--- a/compiler/rustc_mir_transform/src/check_const_item_mutation.rs
+++ b/compiler/rustc_mir_transform/src/check_const_item_mutation.rs
@@ -74,7 +74,7 @@ impl<'tcx> ConstMutationChecker<'_, 'tcx> {
//
// `unsafe { *FOO = 0; *BAR.field = 1; }`
// `unsafe { &mut *FOO }`
- // `unsafe { (*ARRAY)[0] = val; }
+ // `unsafe { (*ARRAY)[0] = val; }`
if !place.projection.iter().any(|p| matches!(p, PlaceElem::Deref)) {
let source_info = self.body.source_info(location);
let lint_root = self.body.source_scopes[source_info.scope]
diff --git a/compiler/rustc_mir_transform/src/check_packed_ref.rs b/compiler/rustc_mir_transform/src/check_packed_ref.rs
index 51abcf511..f5f1c1010 100644
--- a/compiler/rustc_mir_transform/src/check_packed_ref.rs
+++ b/compiler/rustc_mir_transform/src/check_packed_ref.rs
@@ -1,17 +1,11 @@
-use rustc_hir::def_id::LocalDefId;
+use rustc_errors::struct_span_err;
use rustc_middle::mir::visit::{PlaceContext, Visitor};
use rustc_middle::mir::*;
-use rustc_middle::ty::query::Providers;
use rustc_middle::ty::{self, TyCtxt};
-use rustc_session::lint::builtin::UNALIGNED_REFERENCES;
use crate::util;
use crate::MirLint;
-pub(crate) fn provide(providers: &mut Providers) {
- *providers = Providers { unsafe_derive_on_repr_packed, ..*providers };
-}
-
pub struct CheckPackedRef;
impl<'tcx> MirLint<'tcx> for CheckPackedRef {
@@ -30,32 +24,6 @@ struct PackedRefChecker<'a, 'tcx> {
source_info: SourceInfo,
}
-fn unsafe_derive_on_repr_packed(tcx: TyCtxt<'_>, def_id: LocalDefId) {
- let lint_hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
-
- // FIXME: when we make this a hard error, this should have its
- // own error code.
-
- let extra = if tcx.generics_of(def_id).own_requires_monomorphization() {
- "with type or const parameters"
- } else {
- "that does not derive `Copy`"
- };
- let message = format!(
- "`{}` can't be derived on this `#[repr(packed)]` struct {}",
- tcx.item_name(tcx.trait_id_of_impl(def_id.to_def_id()).expect("derived trait name")),
- extra
- );
-
- tcx.struct_span_lint_hir(
- UNALIGNED_REFERENCES,
- lint_hir_id,
- tcx.def_span(def_id),
- message,
- |lint| lint,
- );
-}
-
impl<'tcx> Visitor<'tcx> for PackedRefChecker<'_, 'tcx> {
fn visit_terminator(&mut self, terminator: &Terminator<'tcx>, location: Location) {
// Make sure we know where in the MIR we are.
@@ -73,40 +41,30 @@ impl<'tcx> Visitor<'tcx> for PackedRefChecker<'_, 'tcx> {
if context.is_borrow() {
if util::is_disaligned(self.tcx, self.body, self.param_env, *place) {
let def_id = self.body.source.instance.def_id();
- if let Some(impl_def_id) = self
- .tcx
- .impl_of_method(def_id)
- .filter(|&def_id| self.tcx.is_builtin_derive(def_id))
+ if let Some(impl_def_id) = self.tcx.impl_of_method(def_id)
+ && self.tcx.is_builtin_derived(impl_def_id)
{
- // If a method is defined in the local crate,
- // the impl containing that method should also be.
- self.tcx.ensure().unsafe_derive_on_repr_packed(impl_def_id.expect_local());
+ // If we ever reach here it means that the generated derive
+ // code is somehow doing an unaligned reference, which it
+ // shouldn't do.
+ span_bug!(self.source_info.span, "builtin derive created an unaligned reference");
} else {
- let source_info = self.source_info;
- let lint_root = self.body.source_scopes[source_info.scope]
- .local_data
- .as_ref()
- .assert_crate_local()
- .lint_root;
- self.tcx.struct_span_lint_hir(
- UNALIGNED_REFERENCES,
- lint_root,
- source_info.span,
- "reference to packed field is unaligned",
- |lint| {
- lint
- .note(
- "fields of packed structs are not properly aligned, and creating \
- a misaligned reference is undefined behavior (even if that \
- reference is never dereferenced)",
- )
- .help(
- "copy the field contents to a local variable, or replace the \
- reference with a raw pointer and use `read_unaligned`/`write_unaligned` \
- (loads and stores via `*p` must be properly aligned even when using raw pointers)"
- )
- },
- );
+ struct_span_err!(
+ self.tcx.sess,
+ self.source_info.span,
+ E0793,
+ "reference to packed field is unaligned"
+ )
+ .note(
+ "fields of packed structs are not properly aligned, and creating \
+ a misaligned reference is undefined behavior (even if that \
+ reference is never dereferenced)",
+ ).help(
+ "copy the field contents to a local variable, or replace the \
+ reference with a raw pointer and use `read_unaligned`/`write_unaligned` \
+ (loads and stores via `*p` must be properly aligned even when using raw pointers)"
+ )
+ .emit();
}
}
}
diff --git a/compiler/rustc_mir_transform/src/check_unsafety.rs b/compiler/rustc_mir_transform/src/check_unsafety.rs
index adf6ae4c7..d00ee1f4b 100644
--- a/compiler/rustc_mir_transform/src/check_unsafety.rs
+++ b/compiler/rustc_mir_transform/src/check_unsafety.rs
@@ -104,6 +104,7 @@ impl<'tcx> Visitor<'tcx> for UnsafetyChecker<'_, 'tcx> {
| StatementKind::AscribeUserType(..)
| StatementKind::Coverage(..)
| StatementKind::Intrinsic(..)
+ | StatementKind::ConstEvalCounter
| StatementKind::Nop => {
// safe (at least as emitted during MIR construction)
}
@@ -125,6 +126,7 @@ impl<'tcx> Visitor<'tcx> for UnsafetyChecker<'_, 'tcx> {
}
}
&AggregateKind::Closure(def_id, _) | &AggregateKind::Generator(def_id, _, _) => {
+ let def_id = def_id.expect_local();
let UnsafetyCheckResult { violations, used_unsafe_blocks, .. } =
self.tcx.unsafety_check_result(def_id);
self.register_violations(violations, used_unsafe_blocks.iter().copied());
@@ -445,7 +447,7 @@ impl<'tcx> intravisit::Visitor<'tcx> for UnusedUnsafeVisitor<'_, 'tcx> {
_fd: &'tcx hir::FnDecl<'tcx>,
b: hir::BodyId,
_s: rustc_span::Span,
- _id: HirId,
+ _id: LocalDefId,
) {
if matches!(fk, intravisit::FnKind::Closure) {
self.visit_body(self.tcx.hir().body(b))
diff --git a/compiler/rustc_mir_transform/src/const_goto.rs b/compiler/rustc_mir_transform/src/const_goto.rs
index 40eefda4f..da101ca7a 100644
--- a/compiler/rustc_mir_transform/src/const_goto.rs
+++ b/compiler/rustc_mir_transform/src/const_goto.rs
@@ -57,6 +57,15 @@ impl<'tcx> MirPass<'tcx> for ConstGoto {
}
impl<'tcx> Visitor<'tcx> for ConstGotoOptimizationFinder<'_, 'tcx> {
+ fn visit_basic_block_data(&mut self, block: BasicBlock, data: &BasicBlockData<'tcx>) {
+ if data.is_cleanup {
+ // Because of the restrictions around control flow in cleanup blocks, we don't perform
+ // this optimization at all in such blocks.
+ return;
+ }
+ self.super_basic_block_data(block, data);
+ }
+
fn visit_terminator(&mut self, terminator: &Terminator<'tcx>, location: Location) {
let _: Option<_> = try {
let target = terminator.kind.as_goto()?;
diff --git a/compiler/rustc_mir_transform/src/const_prop.rs b/compiler/rustc_mir_transform/src/const_prop.rs
index 5c45abc5a..6b2eefce2 100644
--- a/compiler/rustc_mir_transform/src/const_prop.rs
+++ b/compiler/rustc_mir_transform/src/const_prop.rs
@@ -5,7 +5,6 @@ use std::cell::Cell;
use either::Right;
-use rustc_ast::Mutability;
use rustc_const_eval::const_eval::CheckAlignment;
use rustc_data_structures::fx::FxHashSet;
use rustc_hir::def::DefKind;
@@ -14,14 +13,10 @@ use rustc_index::vec::IndexVec;
use rustc_middle::mir::visit::{
MutVisitor, MutatingUseContext, NonMutatingUseContext, PlaceContext, Visitor,
};
-use rustc_middle::mir::{
- BasicBlock, BinOp, Body, Constant, ConstantKind, Local, LocalDecl, LocalKind, Location,
- Operand, Place, Rvalue, SourceInfo, Statement, StatementKind, Terminator, TerminatorKind, UnOp,
- RETURN_PLACE,
-};
+use rustc_middle::mir::*;
use rustc_middle::ty::layout::{LayoutError, LayoutOf, LayoutOfHelpers, TyAndLayout};
use rustc_middle::ty::InternalSubsts;
-use rustc_middle::ty::{self, ConstKind, Instance, ParamEnv, Ty, TyCtxt, TypeVisitable};
+use rustc_middle::ty::{self, ConstKind, Instance, ParamEnv, Ty, TyCtxt, TypeVisitableExt};
use rustc_span::{def_id::DefId, Span};
use rustc_target::abi::{self, Align, HasDataLayout, Size, TargetDataLayout};
use rustc_target::spec::abi::Abi as CallAbi;
@@ -83,7 +78,7 @@ impl<'tcx> MirPass<'tcx> for ConstProp {
return;
}
- let is_generator = tcx.type_of(def_id.to_def_id()).is_generator();
+ let is_generator = tcx.type_of(def_id.to_def_id()).subst_identity().is_generator();
// FIXME(welseywiser) const prop doesn't work on generators because of query cycles
// computing their layout.
if is_generator {
@@ -289,7 +284,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for ConstPropMachine<'mir, 'tcx>
}
// If the static allocation is mutable, then we can't const prop it as its content
// might be different at runtime.
- if alloc.inner().mutability == Mutability::Mut {
+ if alloc.inner().mutability.is_mut() {
throw_machine_stop_str!("can't access mutable globals in ConstProp");
}
@@ -457,27 +452,6 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
};
}
- fn use_ecx<F, T>(&mut self, f: F) -> Option<T>
- where
- F: FnOnce(&mut Self) -> InterpResult<'tcx, T>,
- {
- match f(self) {
- Ok(val) => Some(val),
- Err(error) => {
- trace!("InterpCx operation failed: {:?}", error);
- // Some errors shouldn't come up because creating them causes
- // an allocation, which we should avoid. When that happens,
- // dedicated error variants should be introduced instead.
- assert!(
- !error.kind().formatted_string(),
- "const-prop encountered formatting error: {}",
- error
- );
- None
- }
- }
- }
-
/// Returns the value, if any, of evaluating `c`.
fn eval_constant(&mut self, c: &Constant<'tcx>) -> Option<OpTy<'tcx>> {
// FIXME we need to revisit this for #67176
@@ -492,7 +466,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
/// Returns the value, if any, of evaluating `place`.
fn eval_place(&mut self, place: Place<'tcx>) -> Option<OpTy<'tcx>> {
trace!("eval_place(place={:?})", place);
- self.use_ecx(|this| this.ecx.eval_place_to_op(place, None))
+ self.ecx.eval_place_to_op(place, None).ok()
}
/// Returns the value, if any, of evaluating `op`. Calls upon `eval_constant`
@@ -504,55 +478,6 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
}
}
- fn check_unary_op(&mut self, op: UnOp, arg: &Operand<'tcx>) -> Option<()> {
- if self.use_ecx(|this| {
- let val = this.ecx.read_immediate(&this.ecx.eval_operand(arg, None)?)?;
- let (_res, overflow, _ty) = this.ecx.overflowing_unary_op(op, &val)?;
- Ok(overflow)
- })? {
- // `AssertKind` only has an `OverflowNeg` variant, so make sure that is
- // appropriate to use.
- assert_eq!(op, UnOp::Neg, "Neg is the only UnOp that can overflow");
- return None;
- }
-
- Some(())
- }
-
- fn check_binary_op(
- &mut self,
- op: BinOp,
- left: &Operand<'tcx>,
- right: &Operand<'tcx>,
- ) -> Option<()> {
- let r = self.use_ecx(|this| this.ecx.read_immediate(&this.ecx.eval_operand(right, None)?));
- let l = self.use_ecx(|this| this.ecx.read_immediate(&this.ecx.eval_operand(left, None)?));
- // Check for exceeding shifts *even if* we cannot evaluate the LHS.
- if op == BinOp::Shr || op == BinOp::Shl {
- let r = r.clone()?;
- // We need the type of the LHS. We cannot use `place_layout` as that is the type
- // of the result, which for checked binops is not the same!
- let left_ty = left.ty(self.local_decls, self.tcx);
- let left_size = self.ecx.layout_of(left_ty).ok()?.size;
- let right_size = r.layout.size;
- let r_bits = r.to_scalar().to_bits(right_size).ok();
- if r_bits.map_or(false, |b| b >= left_size.bits() as u128) {
- return None;
- }
- }
-
- if let (Some(l), Some(r)) = (&l, &r) {
- // The remaining operators are handled through `overflowing_binary_op`.
- if self.use_ecx(|this| {
- let (_res, overflow, _ty) = this.ecx.overflowing_binary_op(op, l, r)?;
- Ok(overflow)
- })? {
- return None;
- }
- }
- Some(())
- }
-
fn propagate_operand(&mut self, operand: &mut Operand<'tcx>) {
match *operand {
Operand::Copy(l) | Operand::Move(l) => {
@@ -588,28 +513,6 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
// 2. Working around bugs in other parts of the compiler
// - In this case, we'll return `None` from this function to stop evaluation.
match rvalue {
- // Additional checking: give lints to the user if an overflow would occur.
- // We do this here and not in the `Assert` terminator as that terminator is
- // only sometimes emitted (overflow checks can be disabled), but we want to always
- // lint.
- Rvalue::UnaryOp(op, arg) => {
- trace!("checking UnaryOp(op = {:?}, arg = {:?})", op, arg);
- self.check_unary_op(*op, arg)?;
- }
- Rvalue::BinaryOp(op, box (left, right)) => {
- trace!("checking BinaryOp(op = {:?}, left = {:?}, right = {:?})", op, left, right);
- self.check_binary_op(*op, left, right)?;
- }
- Rvalue::CheckedBinaryOp(op, box (left, right)) => {
- trace!(
- "checking CheckedBinaryOp(op = {:?}, left = {:?}, right = {:?})",
- op,
- left,
- right
- );
- self.check_binary_op(*op, left, right)?;
- }
-
// Do not try creating references (#67862)
Rvalue::AddressOf(_, place) | Rvalue::Ref(_, _, place) => {
trace!("skipping AddressOf | Ref for {:?}", place);
@@ -639,7 +542,10 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
| Rvalue::Cast(..)
| Rvalue::ShallowInitBox(..)
| Rvalue::Discriminant(..)
- | Rvalue::NullaryOp(..) => {}
+ | Rvalue::NullaryOp(..)
+ | Rvalue::UnaryOp(..)
+ | Rvalue::BinaryOp(..)
+ | Rvalue::CheckedBinaryOp(..) => {}
}
// FIXME we need to revisit this for #67176
@@ -664,35 +570,37 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
rvalue: &Rvalue<'tcx>,
place: Place<'tcx>,
) -> Option<()> {
- self.use_ecx(|this| match rvalue {
+ match rvalue {
Rvalue::BinaryOp(op, box (left, right))
| Rvalue::CheckedBinaryOp(op, box (left, right)) => {
- let l = this.ecx.eval_operand(left, None).and_then(|x| this.ecx.read_immediate(&x));
+ let l = self.ecx.eval_operand(left, None).and_then(|x| self.ecx.read_immediate(&x));
let r =
- this.ecx.eval_operand(right, None).and_then(|x| this.ecx.read_immediate(&x));
+ self.ecx.eval_operand(right, None).and_then(|x| self.ecx.read_immediate(&x));
let const_arg = match (l, r) {
(Ok(x), Err(_)) | (Err(_), Ok(x)) => x, // exactly one side is known
- (Err(e), Err(_)) => return Err(e), // neither side is known
- (Ok(_), Ok(_)) => return this.ecx.eval_rvalue_into_place(rvalue, place), // both sides are known
+ (Err(_), Err(_)) => return None, // neither side is known
+ (Ok(_), Ok(_)) => return self.ecx.eval_rvalue_into_place(rvalue, place).ok(), // both sides are known
};
if !matches!(const_arg.layout.abi, abi::Abi::Scalar(..)) {
// We cannot handle Scalar Pair stuff.
// No point in calling `eval_rvalue_into_place`, since only one side is known
- throw_machine_stop_str!("cannot optimize this")
+ return None;
}
- let arg_value = const_arg.to_scalar().to_bits(const_arg.layout.size)?;
- let dest = this.ecx.eval_place(place)?;
+ let arg_value = const_arg.to_scalar().to_bits(const_arg.layout.size).ok()?;
+ let dest = self.ecx.eval_place(place).ok()?;
match op {
- BinOp::BitAnd if arg_value == 0 => this.ecx.write_immediate(*const_arg, &dest),
+ BinOp::BitAnd if arg_value == 0 => {
+ self.ecx.write_immediate(*const_arg, &dest).ok()
+ }
BinOp::BitOr
if arg_value == const_arg.layout.size.truncate(u128::MAX)
|| (const_arg.layout.ty.is_bool() && arg_value == 1) =>
{
- this.ecx.write_immediate(*const_arg, &dest)
+ self.ecx.write_immediate(*const_arg, &dest).ok()
}
BinOp::Mul if const_arg.layout.ty.is_integral() && arg_value == 0 => {
if let Rvalue::CheckedBinaryOp(_, _) = rvalue {
@@ -700,16 +608,16 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
const_arg.to_scalar(),
Scalar::from_bool(false),
);
- this.ecx.write_immediate(val, &dest)
+ self.ecx.write_immediate(val, &dest).ok()
} else {
- this.ecx.write_immediate(*const_arg, &dest)
+ self.ecx.write_immediate(*const_arg, &dest).ok()
}
}
- _ => throw_machine_stop_str!("cannot optimize this"),
+ _ => None,
}
}
- _ => this.ecx.eval_rvalue_into_place(rvalue, place),
- })
+ _ => self.ecx.eval_rvalue_into_place(rvalue, place).ok(),
+ }
}
/// Creates a new `Operand::Constant` from a `Scalar` value
@@ -751,7 +659,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
}
// FIXME> figure out what to do when read_immediate_raw fails
- let imm = self.use_ecx(|this| this.ecx.read_immediate_raw(value));
+ let imm = self.ecx.read_immediate_raw(value).ok();
if let Some(Right(imm)) = imm {
match *imm {
@@ -771,25 +679,23 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
if let ty::Tuple(types) = ty.kind() {
// Only do it if tuple is also a pair with two scalars
if let [ty1, ty2] = types[..] {
- let alloc = self.use_ecx(|this| {
- let ty_is_scalar = |ty| {
- this.ecx.layout_of(ty).ok().map(|layout| layout.abi.is_scalar())
- == Some(true)
- };
- if ty_is_scalar(ty1) && ty_is_scalar(ty2) {
- let alloc = this
- .ecx
- .intern_with_temp_alloc(value.layout, |ecx, dest| {
- ecx.write_immediate(*imm, dest)
- })
- .unwrap();
- Ok(Some(alloc))
- } else {
- Ok(None)
- }
- });
-
- if let Some(Some(alloc)) = alloc {
+ let ty_is_scalar = |ty| {
+ self.ecx.layout_of(ty).ok().map(|layout| layout.abi.is_scalar())
+ == Some(true)
+ };
+ let alloc = if ty_is_scalar(ty1) && ty_is_scalar(ty2) {
+ let alloc = self
+ .ecx
+ .intern_with_temp_alloc(value.layout, |ecx, dest| {
+ ecx.write_immediate(*imm, dest)
+ })
+ .unwrap();
+ Some(alloc)
+ } else {
+ None
+ };
+
+ if let Some(alloc) = alloc {
// Assign entire constant in a single statement.
// We can't use aggregates, as we run after the aggregate-lowering `MirPhase`.
let const_val = ConstValue::ByRef { alloc, offset: Size::ZERO };
@@ -990,84 +896,80 @@ impl<'tcx> MutVisitor<'tcx> for ConstPropagator<'_, 'tcx> {
trace!("visit_statement: {:?}", statement);
let source_info = statement.source_info;
self.source_info = Some(source_info);
- if let StatementKind::Assign(box (place, ref mut rval)) = statement.kind {
- let can_const_prop = self.ecx.machine.can_const_prop[place.local];
- if let Some(()) = self.const_prop(rval, place) {
- // This will return None if the above `const_prop` invocation only "wrote" a
- // type whose creation requires no write. E.g. a generator whose initial state
- // consists solely of uninitialized memory (so it doesn't capture any locals).
- if let Some(ref value) = self.get_const(place) && self.should_const_prop(value) {
- trace!("replacing {:?} with {:?}", rval, value);
- self.replace_with_const(rval, value, source_info);
- if can_const_prop == ConstPropMode::FullConstProp
- || can_const_prop == ConstPropMode::OnlyInsideOwnBlock
- {
- trace!("propagated into {:?}", place);
+ match statement.kind {
+ StatementKind::Assign(box (place, ref mut rval)) => {
+ let can_const_prop = self.ecx.machine.can_const_prop[place.local];
+ if let Some(()) = self.const_prop(rval, place) {
+ // This will return None if the above `const_prop` invocation only "wrote" a
+ // type whose creation requires no write. E.g. a generator whose initial state
+ // consists solely of uninitialized memory (so it doesn't capture any locals).
+ if let Some(ref value) = self.get_const(place) && self.should_const_prop(value) {
+ trace!("replacing {:?} with {:?}", rval, value);
+ self.replace_with_const(rval, value, source_info);
+ if can_const_prop == ConstPropMode::FullConstProp
+ || can_const_prop == ConstPropMode::OnlyInsideOwnBlock
+ {
+ trace!("propagated into {:?}", place);
+ }
}
- }
- match can_const_prop {
- ConstPropMode::OnlyInsideOwnBlock => {
- trace!(
- "found local restricted to its block. \
+ match can_const_prop {
+ ConstPropMode::OnlyInsideOwnBlock => {
+ trace!(
+ "found local restricted to its block. \
Will remove it from const-prop after block is finished. Local: {:?}",
- place.local
- );
- }
- ConstPropMode::OnlyPropagateInto | ConstPropMode::NoPropagation => {
- trace!("can't propagate into {:?}", place);
- if place.local != RETURN_PLACE {
- Self::remove_const(&mut self.ecx, place.local);
+ place.local
+ );
}
- }
- ConstPropMode::FullConstProp => {}
- }
- } else {
- // Const prop failed, so erase the destination, ensuring that whatever happens
- // from here on, does not know about the previous value.
- // This is important in case we have
- // ```rust
- // let mut x = 42;
- // x = SOME_MUTABLE_STATIC;
- // // x must now be uninit
- // ```
- // FIXME: we overzealously erase the entire local, because that's easier to
- // implement.
- trace!(
- "propagation into {:?} failed.
- Nuking the entire site from orbit, it's the only way to be sure",
- place,
- );
- Self::remove_const(&mut self.ecx, place.local);
- }
- } else {
- match statement.kind {
- StatementKind::SetDiscriminant { ref place, .. } => {
- match self.ecx.machine.can_const_prop[place.local] {
- ConstPropMode::FullConstProp | ConstPropMode::OnlyInsideOwnBlock => {
- if self.use_ecx(|this| this.ecx.statement(statement)).is_some() {
- trace!("propped discriminant into {:?}", place);
- } else {
+ ConstPropMode::OnlyPropagateInto | ConstPropMode::NoPropagation => {
+ trace!("can't propagate into {:?}", place);
+ if place.local != RETURN_PLACE {
Self::remove_const(&mut self.ecx, place.local);
}
}
- ConstPropMode::OnlyPropagateInto | ConstPropMode::NoPropagation => {
- Self::remove_const(&mut self.ecx, place.local);
- }
+ ConstPropMode::FullConstProp => {}
}
+ } else {
+ // Const prop failed, so erase the destination, ensuring that whatever happens
+ // from here on, does not know about the previous value.
+ // This is important in case we have
+ // ```rust
+ // let mut x = 42;
+ // x = SOME_MUTABLE_STATIC;
+ // // x must now be uninit
+ // ```
+ // FIXME: we overzealously erase the entire local, because that's easier to
+ // implement.
+ trace!(
+ "propagation into {:?} failed.
+ Nuking the entire site from orbit, it's the only way to be sure",
+ place,
+ );
+ Self::remove_const(&mut self.ecx, place.local);
}
- StatementKind::StorageLive(local) | StatementKind::StorageDead(local) => {
- let frame = self.ecx.frame_mut();
- frame.locals[local].value =
- if let StatementKind::StorageLive(_) = statement.kind {
- LocalValue::Live(interpret::Operand::Immediate(
- interpret::Immediate::Uninit,
- ))
+ }
+ StatementKind::SetDiscriminant { ref place, .. } => {
+ match self.ecx.machine.can_const_prop[place.local] {
+ ConstPropMode::FullConstProp | ConstPropMode::OnlyInsideOwnBlock => {
+ if self.ecx.statement(statement).is_ok() {
+ trace!("propped discriminant into {:?}", place);
} else {
- LocalValue::Dead
- };
+ Self::remove_const(&mut self.ecx, place.local);
+ }
+ }
+ ConstPropMode::OnlyPropagateInto | ConstPropMode::NoPropagation => {
+ Self::remove_const(&mut self.ecx, place.local);
+ }
}
- _ => {}
}
+ StatementKind::StorageLive(local) | StatementKind::StorageDead(local) => {
+ let frame = self.ecx.frame_mut();
+ frame.locals[local].value = if let StatementKind::StorageLive(_) = statement.kind {
+ LocalValue::Live(interpret::Operand::Immediate(interpret::Immediate::Uninit))
+ } else {
+ LocalValue::Dead
+ };
+ }
+ _ => {}
}
self.super_statement(statement, location);
@@ -1077,34 +979,19 @@ impl<'tcx> MutVisitor<'tcx> for ConstPropagator<'_, 'tcx> {
let source_info = terminator.source_info;
self.source_info = Some(source_info);
self.super_terminator(terminator, location);
- // Do NOT early return in this function, it does some crucial fixup of the state at the end!
+
match &mut terminator.kind {
TerminatorKind::Assert { expected, ref mut cond, .. } => {
- if let Some(ref value) = self.eval_operand(&cond) {
+ if let Some(ref value) = self.eval_operand(&cond)
+ && let Ok(value_const) = self.ecx.read_scalar(&value)
+ && self.should_const_prop(value)
+ {
trace!("assertion on {:?} should be {:?}", value, expected);
- let expected = Scalar::from_bool(*expected);
- // FIXME should be used use_ecx rather than a local match... but we have
- // quite a few of these read_scalar/read_immediate that need fixing.
- if let Ok(value_const) = self.ecx.read_scalar(&value) {
- if expected != value_const {
- // Poison all places this operand references so that further code
- // doesn't use the invalid value
- match cond {
- Operand::Move(ref place) | Operand::Copy(ref place) => {
- Self::remove_const(&mut self.ecx, place.local);
- }
- Operand::Constant(_) => {}
- }
- } else {
- if self.should_const_prop(value) {
- *cond = self.operand_from_scalar(
- value_const,
- self.tcx.types.bool,
- source_info.span,
- );
- }
- }
- }
+ *cond = self.operand_from_scalar(
+ value_const,
+ self.tcx.types.bool,
+ source_info.span,
+ );
}
}
TerminatorKind::SwitchInt { ref mut discr, .. } => {
@@ -1132,6 +1019,10 @@ impl<'tcx> MutVisitor<'tcx> for ConstPropagator<'_, 'tcx> {
// gated on `mir_opt_level=3`.
TerminatorKind::Call { .. } => {}
}
+ }
+
+ fn visit_basic_block_data(&mut self, block: BasicBlock, data: &mut BasicBlockData<'tcx>) {
+ self.super_basic_block_data(block, data);
// We remove all Locals which are restricted in propagation to their containing blocks and
// which were modified in the current block.
diff --git a/compiler/rustc_mir_transform/src/const_prop_lint.rs b/compiler/rustc_mir_transform/src/const_prop_lint.rs
index 0ab67228f..fd9475748 100644
--- a/compiler/rustc_mir_transform/src/const_prop_lint.rs
+++ b/compiler/rustc_mir_transform/src/const_prop_lint.rs
@@ -21,7 +21,9 @@ use rustc_middle::mir::{
};
use rustc_middle::ty::layout::{LayoutError, LayoutOf, LayoutOfHelpers, TyAndLayout};
use rustc_middle::ty::InternalSubsts;
-use rustc_middle::ty::{self, ConstInt, Instance, ParamEnv, ScalarInt, Ty, TyCtxt, TypeVisitable};
+use rustc_middle::ty::{
+ self, ConstInt, Instance, ParamEnv, ScalarInt, Ty, TyCtxt, TypeVisitableExt,
+};
use rustc_session::lint;
use rustc_span::Span;
use rustc_target::abi::{HasDataLayout, Size, TargetDataLayout};
@@ -57,7 +59,7 @@ impl<'tcx> MirLint<'tcx> for ConstProp {
return;
}
- let is_generator = tcx.type_of(def_id.to_def_id()).is_generator();
+ let is_generator = tcx.type_of(def_id.to_def_id()).subst_identity().is_generator();
// FIXME(welseywiser) const prop doesn't work on generators because of query cycles
// computing their layout.
if is_generator {
@@ -296,7 +298,15 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
return None;
}
- self.use_ecx(source_info, |this| this.ecx.eval_mir_constant(&c.literal, Some(c.span), None))
+ // Normalization needed b/c const prop lint runs in
+ // `mir_drops_elaborated_and_const_checked`, which happens before
+ // optimized MIR. Only after optimizing the MIR can we guarantee
+ // that the `RevealAll` pass has happened and that the body's consts
+ // are normalized, so any call to resolve before that needs to be
+ // manually normalized.
+ let val = self.tcx.try_normalize_erasing_regions(self.param_env, c.literal).ok()?;
+
+ self.use_ecx(source_info, |this| this.ecx.eval_mir_constant(&val, Some(c.span), None))
}
/// Returns the value, if any, of evaluating `place`.
@@ -368,7 +378,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
this.ecx.read_immediate(&this.ecx.eval_operand(left, None)?)
});
// Check for exceeding shifts *even if* we cannot evaluate the LHS.
- if op == BinOp::Shr || op == BinOp::Shl {
+ if matches!(op, BinOp::Shr | BinOp::Shl) {
let r = r.clone()?;
// We need the type of the LHS. We cannot use `place_layout` as that is the type
// of the result, which for checked binops is not the same!
diff --git a/compiler/rustc_mir_transform/src/copy_prop.rs b/compiler/rustc_mir_transform/src/copy_prop.rs
new file mode 100644
index 000000000..f27beb64a
--- /dev/null
+++ b/compiler/rustc_mir_transform/src/copy_prop.rs
@@ -0,0 +1,182 @@
+use rustc_index::bit_set::BitSet;
+use rustc_index::vec::IndexVec;
+use rustc_middle::mir::visit::*;
+use rustc_middle::mir::*;
+use rustc_middle::ty::TyCtxt;
+use rustc_mir_dataflow::impls::borrowed_locals;
+
+use crate::ssa::SsaLocals;
+use crate::MirPass;
+
+/// Unify locals that copy each other.
+///
+/// We consider patterns of the form
+/// _a = rvalue
+/// _b = move? _a
+/// _c = move? _a
+/// _d = move? _c
+/// where each of the locals is only assigned once.
+///
+/// We want to replace all those locals by `_a`, either copied or moved.
+pub struct CopyProp;
+
+impl<'tcx> MirPass<'tcx> for CopyProp {
+ fn is_enabled(&self, sess: &rustc_session::Session) -> bool {
+ sess.mir_opt_level() >= 1
+ }
+
+ #[instrument(level = "trace", skip(self, tcx, body))]
+ fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
+ debug!(def_id = ?body.source.def_id());
+ propagate_ssa(tcx, body);
+ }
+}
+
+fn propagate_ssa<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
+ let param_env = tcx.param_env_reveal_all_normalized(body.source.def_id());
+ let borrowed_locals = borrowed_locals(body);
+ let ssa = SsaLocals::new(tcx, param_env, body, &borrowed_locals);
+
+ let fully_moved = fully_moved_locals(&ssa, body);
+ debug!(?fully_moved);
+
+ let mut storage_to_remove = BitSet::new_empty(fully_moved.domain_size());
+ for (local, &head) in ssa.copy_classes().iter_enumerated() {
+ if local != head {
+ storage_to_remove.insert(head);
+ }
+ }
+
+ let any_replacement = ssa.copy_classes().iter_enumerated().any(|(l, &h)| l != h);
+
+ Replacer {
+ tcx,
+ copy_classes: &ssa.copy_classes(),
+ fully_moved,
+ borrowed_locals,
+ storage_to_remove,
+ }
+ .visit_body_preserves_cfg(body);
+
+ if any_replacement {
+ crate::simplify::remove_unused_definitions(body);
+ }
+}
+
+/// `SsaLocals` computed equivalence classes between locals considering copy/move assignments.
+///
+/// This function also returns whether all the `move?` in the pattern are `move` and not copies.
+/// A local which is in the bitset can be replaced by `move _a`. Otherwise, it must be
+/// replaced by `copy _a`, as we cannot move multiple times from `_a`.
+///
+/// If an operand copies `_c`, it must happen before the assignment `_d = _c`, otherwise it is UB.
+/// This means that replacing it by a copy of `_a` if ok, since this copy happens before `_c` is
+/// moved, and therefore that `_d` is moved.
+#[instrument(level = "trace", skip(ssa, body))]
+fn fully_moved_locals(ssa: &SsaLocals, body: &Body<'_>) -> BitSet<Local> {
+ let mut fully_moved = BitSet::new_filled(body.local_decls.len());
+
+ for (_, rvalue) in ssa.assignments(body) {
+ let (Rvalue::Use(Operand::Copy(place) | Operand::Move(place)) | Rvalue::CopyForDeref(place))
+ = rvalue
+ else { continue };
+
+ let Some(rhs) = place.as_local() else { continue };
+ if !ssa.is_ssa(rhs) {
+ continue;
+ }
+
+ if let Rvalue::Use(Operand::Copy(_)) | Rvalue::CopyForDeref(_) = rvalue {
+ fully_moved.remove(rhs);
+ }
+ }
+
+ ssa.meet_copy_equivalence(&mut fully_moved);
+
+ fully_moved
+}
+
+/// Utility to help performing substitution of `*pattern` by `target`.
+struct Replacer<'a, 'tcx> {
+ tcx: TyCtxt<'tcx>,
+ fully_moved: BitSet<Local>,
+ storage_to_remove: BitSet<Local>,
+ borrowed_locals: BitSet<Local>,
+ copy_classes: &'a IndexVec<Local, Local>,
+}
+
+impl<'tcx> MutVisitor<'tcx> for Replacer<'_, 'tcx> {
+ fn tcx(&self) -> TyCtxt<'tcx> {
+ self.tcx
+ }
+
+ fn visit_local(&mut self, local: &mut Local, ctxt: PlaceContext, _: Location) {
+ let new_local = self.copy_classes[*local];
+ match ctxt {
+ // Do not modify the local in storage statements.
+ PlaceContext::NonUse(NonUseContext::StorageLive | NonUseContext::StorageDead) => {}
+ // The local should have been marked as non-SSA.
+ PlaceContext::MutatingUse(_) => assert_eq!(*local, new_local),
+ // We access the value.
+ _ => *local = new_local,
+ }
+ }
+
+ fn visit_place(&mut self, place: &mut Place<'tcx>, ctxt: PlaceContext, loc: Location) {
+ if let Some(new_projection) = self.process_projection(&place.projection, loc) {
+ place.projection = self.tcx().mk_place_elems(&new_projection);
+ }
+
+ let observes_address = match ctxt {
+ PlaceContext::NonMutatingUse(
+ NonMutatingUseContext::SharedBorrow
+ | NonMutatingUseContext::ShallowBorrow
+ | NonMutatingUseContext::UniqueBorrow
+ | NonMutatingUseContext::AddressOf,
+ ) => true,
+ // For debuginfo, merging locals is ok.
+ PlaceContext::NonUse(NonUseContext::VarDebugInfo) => {
+ self.borrowed_locals.contains(place.local)
+ }
+ _ => false,
+ };
+ if observes_address && !place.is_indirect() {
+ // We observe the address of `place.local`. Do not replace it.
+ } else {
+ self.visit_local(
+ &mut place.local,
+ PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy),
+ loc,
+ )
+ }
+ }
+
+ fn visit_operand(&mut self, operand: &mut Operand<'tcx>, loc: Location) {
+ if let Operand::Move(place) = *operand
+ // A move out of a projection of a copy is equivalent to a copy of the original projection.
+ && !place.has_deref()
+ && !self.fully_moved.contains(place.local)
+ {
+ *operand = Operand::Copy(place);
+ }
+ self.super_operand(operand, loc);
+ }
+
+ fn visit_statement(&mut self, stmt: &mut Statement<'tcx>, loc: Location) {
+ match stmt.kind {
+ // When removing storage statements, we need to remove both (#107511).
+ StatementKind::StorageLive(l) | StatementKind::StorageDead(l)
+ if self.storage_to_remove.contains(l) =>
+ {
+ stmt.make_nop()
+ }
+ StatementKind::Assign(box (ref place, ref mut rvalue))
+ if place.as_local().is_some() =>
+ {
+ // Do not replace assignments.
+ self.visit_rvalue(rvalue, loc)
+ }
+ _ => self.super_statement(stmt, loc),
+ }
+ }
+}
diff --git a/compiler/rustc_mir_transform/src/coverage/counters.rs b/compiler/rustc_mir_transform/src/coverage/counters.rs
index 45de0c280..658e01d93 100644
--- a/compiler/rustc_mir_transform/src/coverage/counters.rs
+++ b/compiler/rustc_mir_transform/src/coverage/counters.rs
@@ -520,7 +520,7 @@ impl<'a> BcbCounters<'a> {
let mut found_loop_exit = false;
for &branch in branches.iter() {
if backedge_from_bcbs.iter().any(|&backedge_from_bcb| {
- self.bcb_is_dominated_by(backedge_from_bcb, branch.target_bcb)
+ self.bcb_dominates(branch.target_bcb, backedge_from_bcb)
}) {
if let Some(reloop_branch) = some_reloop_branch {
if reloop_branch.counter(&self.basic_coverage_blocks).is_none() {
@@ -603,8 +603,8 @@ impl<'a> BcbCounters<'a> {
}
#[inline]
- fn bcb_is_dominated_by(&self, node: BasicCoverageBlock, dom: BasicCoverageBlock) -> bool {
- self.basic_coverage_blocks.is_dominated_by(node, dom)
+ fn bcb_dominates(&self, dom: BasicCoverageBlock, node: BasicCoverageBlock) -> bool {
+ self.basic_coverage_blocks.dominates(dom, node)
}
#[inline]
diff --git a/compiler/rustc_mir_transform/src/coverage/debug.rs b/compiler/rustc_mir_transform/src/coverage/debug.rs
index d6a298fad..22ea8710e 100644
--- a/compiler/rustc_mir_transform/src/coverage/debug.rs
+++ b/compiler/rustc_mir_transform/src/coverage/debug.rs
@@ -323,7 +323,10 @@ impl DebugCounters {
String::new()
},
self.format_operand(lhs),
- if op == Op::Add { "+" } else { "-" },
+ match op {
+ Op::Add => "+",
+ Op::Subtract => "-",
+ },
self.format_operand(rhs),
);
}
diff --git a/compiler/rustc_mir_transform/src/coverage/graph.rs b/compiler/rustc_mir_transform/src/coverage/graph.rs
index 78d28f1eb..a2671eef2 100644
--- a/compiler/rustc_mir_transform/src/coverage/graph.rs
+++ b/compiler/rustc_mir_transform/src/coverage/graph.rs
@@ -209,8 +209,8 @@ impl CoverageGraph {
}
#[inline(always)]
- pub fn is_dominated_by(&self, node: BasicCoverageBlock, dom: BasicCoverageBlock) -> bool {
- self.dominators.as_ref().unwrap().is_dominated_by(node, dom)
+ pub fn dominates(&self, dom: BasicCoverageBlock, node: BasicCoverageBlock) -> bool {
+ self.dominators.as_ref().unwrap().dominates(dom, node)
}
#[inline(always)]
@@ -312,7 +312,7 @@ rustc_index::newtype_index! {
/// to the BCB's primary counter or expression).
///
/// The BCB CFG is critical to simplifying the coverage analysis by ensuring graph path-based
-/// queries (`is_dominated_by()`, `predecessors`, `successors`, etc.) have branch (control flow)
+/// queries (`dominates()`, `predecessors`, `successors`, etc.) have branch (control flow)
/// significance.
#[derive(Debug, Clone)]
pub(super) struct BasicCoverageBlockData {
@@ -594,7 +594,7 @@ impl TraverseCoverageGraphWithLoops {
// branching block would have given an `Expression` (or vice versa).
let (some_successor_to_add, some_loop_header) =
if let Some((_, loop_header)) = context.loop_backedges {
- if basic_coverage_blocks.is_dominated_by(successor, loop_header) {
+ if basic_coverage_blocks.dominates(loop_header, successor) {
(Some(successor), Some(loop_header))
} else {
(None, None)
@@ -666,15 +666,15 @@ pub(super) fn find_loop_backedges(
//
// The overall complexity appears to be comparable to many other MIR transform algorithms, and I
// don't expect that this function is creating a performance hot spot, but if this becomes an
- // issue, there may be ways to optimize the `is_dominated_by` algorithm (as indicated by an
+ // issue, there may be ways to optimize the `dominates` algorithm (as indicated by an
// existing `FIXME` comment in that code), or possibly ways to optimize it's usage here, perhaps
// by keeping track of results for visited `BasicCoverageBlock`s if they can be used to short
- // circuit downstream `is_dominated_by` checks.
+ // circuit downstream `dominates` checks.
//
// For now, that kind of optimization seems unnecessarily complicated.
for (bcb, _) in basic_coverage_blocks.iter_enumerated() {
for &successor in &basic_coverage_blocks.successors[bcb] {
- if basic_coverage_blocks.is_dominated_by(bcb, successor) {
+ if basic_coverage_blocks.dominates(successor, bcb) {
let loop_header = successor;
let backedge_from_bcb = bcb;
debug!(
diff --git a/compiler/rustc_mir_transform/src/coverage/mod.rs b/compiler/rustc_mir_transform/src/coverage/mod.rs
index 1468afc64..9a6171598 100644
--- a/compiler/rustc_mir_transform/src/coverage/mod.rs
+++ b/compiler/rustc_mir_transform/src/coverage/mod.rs
@@ -540,7 +540,8 @@ fn fn_sig_and_body(
// FIXME(#79625): Consider improving MIR to provide the information needed, to avoid going back
// to HIR for it.
let hir_node = tcx.hir().get_if_local(def_id).expect("expected DefId is local");
- let fn_body_id = hir::map::associated_body(hir_node).expect("HIR node is a function with body");
+ let (_, fn_body_id) =
+ hir::map::associated_body(hir_node).expect("HIR node is a function with body");
(hir_node.fn_sig(), tcx.hir().body(fn_body_id))
}
diff --git a/compiler/rustc_mir_transform/src/coverage/spans.rs b/compiler/rustc_mir_transform/src/coverage/spans.rs
index c54348404..8ee316773 100644
--- a/compiler/rustc_mir_transform/src/coverage/spans.rs
+++ b/compiler/rustc_mir_transform/src/coverage/spans.rs
@@ -63,7 +63,7 @@ impl CoverageStatement {
/// Note: A `CoverageStatement` merged into another CoverageSpan may come from a `BasicBlock` that
/// is not part of the `CoverageSpan` bcb if the statement was included because it's `Span` matches
/// or is subsumed by the `Span` associated with this `CoverageSpan`, and it's `BasicBlock`
-/// `is_dominated_by()` the `BasicBlock`s in this `CoverageSpan`.
+/// `dominates()` the `BasicBlock`s in this `CoverageSpan`.
#[derive(Debug, Clone)]
pub(super) struct CoverageSpan {
pub span: Span,
@@ -407,7 +407,7 @@ impl<'a, 'tcx> CoverageSpans<'a, 'tcx> {
if self.prev().is_macro_expansion() && self.curr().is_macro_expansion() {
// Macros that expand to include branching (such as
// `assert_eq!()`, `assert_ne!()`, `info!()`, `debug!()`, or
- // `trace!()) typically generate callee spans with identical
+ // `trace!()`) typically generate callee spans with identical
// ranges (typically the full span of the macro) for all
// `BasicBlocks`. This makes it impossible to distinguish
// the condition (`if val1 != val2`) from the optional
@@ -694,7 +694,7 @@ impl<'a, 'tcx> CoverageSpans<'a, 'tcx> {
/// `prev.span.hi()` will be greater than (further right of) `prev_original_span.hi()`.
/// If prev.span() was split off to the right of a closure, prev.span().lo() will be
/// greater than prev_original_span.lo(). The actual span of `prev_original_span` is
- /// not as important as knowing that `prev()` **used to have the same span** as `curr(),
+ /// not as important as knowing that `prev()` **used to have the same span** as `curr()`,
/// which means their sort order is still meaningful for determining the dominator
/// relationship.
///
@@ -705,12 +705,12 @@ impl<'a, 'tcx> CoverageSpans<'a, 'tcx> {
fn hold_pending_dups_unless_dominated(&mut self) {
// Equal coverage spans are ordered by dominators before dominated (if any), so it should be
// impossible for `curr` to dominate any previous `CoverageSpan`.
- debug_assert!(!self.span_bcb_is_dominated_by(self.prev(), self.curr()));
+ debug_assert!(!self.span_bcb_dominates(self.curr(), self.prev()));
let initial_pending_count = self.pending_dups.len();
if initial_pending_count > 0 {
let mut pending_dups = self.pending_dups.split_off(0);
- pending_dups.retain(|dup| !self.span_bcb_is_dominated_by(self.curr(), dup));
+ pending_dups.retain(|dup| !self.span_bcb_dominates(dup, self.curr()));
self.pending_dups.append(&mut pending_dups);
if self.pending_dups.len() < initial_pending_count {
debug!(
@@ -721,7 +721,7 @@ impl<'a, 'tcx> CoverageSpans<'a, 'tcx> {
}
}
- if self.span_bcb_is_dominated_by(self.curr(), self.prev()) {
+ if self.span_bcb_dominates(self.prev(), self.curr()) {
debug!(
" different bcbs but SAME spans, and prev dominates curr. Discard prev={:?}",
self.prev()
@@ -787,8 +787,8 @@ impl<'a, 'tcx> CoverageSpans<'a, 'tcx> {
}
}
- fn span_bcb_is_dominated_by(&self, covspan: &CoverageSpan, dom_covspan: &CoverageSpan) -> bool {
- self.basic_coverage_blocks.is_dominated_by(covspan.bcb, dom_covspan.bcb)
+ fn span_bcb_dominates(&self, dom_covspan: &CoverageSpan, covspan: &CoverageSpan) -> bool {
+ self.basic_coverage_blocks.dominates(dom_covspan.bcb, covspan.bcb)
}
}
@@ -802,6 +802,8 @@ pub(super) fn filtered_statement_span(statement: &Statement<'_>) -> Option<Span>
| StatementKind::StorageDead(_)
// Coverage should not be encountered, but don't inject coverage coverage
| StatementKind::Coverage(_)
+ // Ignore `ConstEvalCounter`s
+ | StatementKind::ConstEvalCounter
// Ignore `Nop`s
| StatementKind::Nop => None,
diff --git a/compiler/rustc_mir_transform/src/ctfe_limit.rs b/compiler/rustc_mir_transform/src/ctfe_limit.rs
new file mode 100644
index 000000000..1b3ac78fb
--- /dev/null
+++ b/compiler/rustc_mir_transform/src/ctfe_limit.rs
@@ -0,0 +1,58 @@
+//! A pass that inserts the `ConstEvalCounter` instruction into any blocks that have a back edge
+//! (thus indicating there is a loop in the CFG), or whose terminator is a function call.
+use crate::MirPass;
+
+use rustc_data_structures::graph::dominators::Dominators;
+use rustc_middle::mir::{
+ BasicBlock, BasicBlockData, Body, Statement, StatementKind, TerminatorKind,
+};
+use rustc_middle::ty::TyCtxt;
+
+pub struct CtfeLimit;
+
+impl<'tcx> MirPass<'tcx> for CtfeLimit {
+ #[instrument(skip(self, _tcx, body))]
+ fn run_pass(&self, _tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
+ let doms = body.basic_blocks.dominators();
+ let indices: Vec<BasicBlock> = body
+ .basic_blocks
+ .iter_enumerated()
+ .filter_map(|(node, node_data)| {
+ if matches!(node_data.terminator().kind, TerminatorKind::Call { .. })
+ // Back edges in a CFG indicate loops
+ || has_back_edge(&doms, node, &node_data)
+ {
+ Some(node)
+ } else {
+ None
+ }
+ })
+ .collect();
+ for index in indices {
+ insert_counter(
+ body.basic_blocks_mut()
+ .get_mut(index)
+ .expect("basic_blocks index {index} should exist"),
+ );
+ }
+ }
+}
+
+fn has_back_edge(
+ doms: &Dominators<BasicBlock>,
+ node: BasicBlock,
+ node_data: &BasicBlockData<'_>,
+) -> bool {
+ if !doms.is_reachable(node) {
+ return false;
+ }
+ // Check if any of the dominators of the node are also the node's successor.
+ doms.dominators(node).any(|dom| node_data.terminator().successors().any(|succ| succ == dom))
+}
+
+fn insert_counter(basic_block_data: &mut BasicBlockData<'_>) {
+ basic_block_data.statements.push(Statement {
+ source_info: basic_block_data.terminator().source_info,
+ kind: StatementKind::ConstEvalCounter,
+ });
+}
diff --git a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs
index c75fe2327..49ded10ba 100644
--- a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs
+++ b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs
@@ -5,6 +5,7 @@
use rustc_const_eval::const_eval::CheckAlignment;
use rustc_const_eval::interpret::{ConstValue, ImmTy, Immediate, InterpCx, Scalar};
use rustc_data_structures::fx::FxHashMap;
+use rustc_hir::def::DefKind;
use rustc_middle::mir::visit::{MutVisitor, Visitor};
use rustc_middle::mir::*;
use rustc_middle::ty::{self, Ty, TyCtxt};
@@ -12,6 +13,7 @@ use rustc_mir_dataflow::value_analysis::{Map, State, TrackElem, ValueAnalysis, V
use rustc_mir_dataflow::{lattice::FlatSet, Analysis, ResultsVisitor, SwitchIntEdgeEffects};
use rustc_span::DUMMY_SP;
use rustc_target::abi::Align;
+use rustc_target::abi::VariantIdx;
use crate::MirPass;
@@ -29,14 +31,12 @@ impl<'tcx> MirPass<'tcx> for DataflowConstProp {
#[instrument(skip_all level = "debug")]
fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
+ debug!(def_id = ?body.source.def_id());
if tcx.sess.mir_opt_level() < 4 && body.basic_blocks.len() > BLOCK_LIMIT {
debug!("aborted dataflow const prop due too many basic blocks");
return;
}
- // Decide which places to track during the analysis.
- let map = Map::from_filter(tcx, body, Ty::is_scalar);
-
// We want to have a somewhat linear runtime w.r.t. the number of statements/terminators.
// Let's call this number `n`. Dataflow analysis has `O(h*n)` transfer function
// applications, where `h` is the height of the lattice. Because the height of our lattice
@@ -45,10 +45,10 @@ impl<'tcx> MirPass<'tcx> for DataflowConstProp {
// `O(num_nodes * tracked_places * n)` in terms of time complexity. Since the number of
// map nodes is strongly correlated to the number of tracked places, this becomes more or
// less `O(n)` if we place a constant limit on the number of tracked places.
- if tcx.sess.mir_opt_level() < 4 && map.tracked_places() > PLACE_LIMIT {
- debug!("aborted dataflow const prop due to too many tracked places");
- return;
- }
+ let place_limit = if tcx.sess.mir_opt_level() < 4 { Some(PLACE_LIMIT) } else { None };
+
+ // Decide which places to track during the analysis.
+ let map = Map::from_filter(tcx, body, Ty::is_scalar, place_limit);
// Perform the actual dataflow analysis.
let analysis = ConstAnalysis::new(tcx, body, map);
@@ -62,14 +62,31 @@ impl<'tcx> MirPass<'tcx> for DataflowConstProp {
}
}
-struct ConstAnalysis<'tcx> {
+struct ConstAnalysis<'a, 'tcx> {
map: Map,
tcx: TyCtxt<'tcx>,
+ local_decls: &'a LocalDecls<'tcx>,
ecx: InterpCx<'tcx, 'tcx, DummyMachine>,
param_env: ty::ParamEnv<'tcx>,
}
-impl<'tcx> ValueAnalysis<'tcx> for ConstAnalysis<'tcx> {
+impl<'tcx> ConstAnalysis<'_, 'tcx> {
+ fn eval_discriminant(
+ &self,
+ enum_ty: Ty<'tcx>,
+ variant_index: VariantIdx,
+ ) -> Option<ScalarTy<'tcx>> {
+ if !enum_ty.is_enum() {
+ return None;
+ }
+ let discr = enum_ty.discriminant_for_variant(self.tcx, variant_index)?;
+ let discr_layout = self.tcx.layout_of(self.param_env.and(discr.ty)).ok()?;
+ let discr_value = Scalar::try_from_uint(discr.val, discr_layout.size)?;
+ Some(ScalarTy(discr_value, discr.ty))
+ }
+}
+
+impl<'tcx> ValueAnalysis<'tcx> for ConstAnalysis<'_, 'tcx> {
type Value = FlatSet<ScalarTy<'tcx>>;
const NAME: &'static str = "ConstAnalysis";
@@ -78,6 +95,25 @@ impl<'tcx> ValueAnalysis<'tcx> for ConstAnalysis<'tcx> {
&self.map
}
+ fn handle_statement(&self, statement: &Statement<'tcx>, state: &mut State<Self::Value>) {
+ match statement.kind {
+ StatementKind::SetDiscriminant { box ref place, variant_index } => {
+ state.flood_discr(place.as_ref(), &self.map);
+ if self.map.find_discr(place.as_ref()).is_some() {
+ let enum_ty = place.ty(self.local_decls, self.tcx).ty;
+ if let Some(discr) = self.eval_discriminant(enum_ty, variant_index) {
+ state.assign_discr(
+ place.as_ref(),
+ ValueOrPlace::Value(FlatSet::Elem(discr)),
+ &self.map,
+ );
+ }
+ }
+ }
+ _ => self.super_statement(statement, state),
+ }
+ }
+
fn handle_assign(
&self,
target: Place<'tcx>,
@@ -85,13 +121,59 @@ impl<'tcx> ValueAnalysis<'tcx> for ConstAnalysis<'tcx> {
state: &mut State<Self::Value>,
) {
match rvalue {
+ Rvalue::Aggregate(kind, operands) => {
+ // If we assign `target = Enum::Variant#0(operand)`,
+ // we must make sure that all `target as Variant#i` are `Top`.
+ state.flood(target.as_ref(), self.map());
+
+ if let Some(target_idx) = self.map().find(target.as_ref()) {
+ let (variant_target, variant_index) = match **kind {
+ AggregateKind::Tuple | AggregateKind::Closure(..) => {
+ (Some(target_idx), None)
+ }
+ AggregateKind::Adt(def_id, variant_index, ..) => {
+ match self.tcx.def_kind(def_id) {
+ DefKind::Struct => (Some(target_idx), None),
+ DefKind::Enum => (
+ self.map.apply(target_idx, TrackElem::Variant(variant_index)),
+ Some(variant_index),
+ ),
+ _ => (None, None),
+ }
+ }
+ _ => (None, None),
+ };
+ if let Some(variant_target_idx) = variant_target {
+ for (field_index, operand) in operands.iter().enumerate() {
+ if let Some(field) = self.map().apply(
+ variant_target_idx,
+ TrackElem::Field(Field::from_usize(field_index)),
+ ) {
+ let result = self.handle_operand(operand, state);
+ state.insert_idx(field, result, self.map());
+ }
+ }
+ }
+ if let Some(variant_index) = variant_index
+ && let Some(discr_idx) = self.map().apply(target_idx, TrackElem::Discriminant)
+ {
+ // We are assigning the discriminant as part of an aggregate.
+ // This discriminant can only alias a variant field's value if the operand
+ // had an invalid value for that type.
+ // Using invalid values is UB, so we are allowed to perform the assignment
+ // without extra flooding.
+ let enum_ty = target.ty(self.local_decls, self.tcx).ty;
+ if let Some(discr_val) = self.eval_discriminant(enum_ty, variant_index) {
+ state.insert_value_idx(discr_idx, FlatSet::Elem(discr_val), &self.map);
+ }
+ }
+ }
+ }
Rvalue::CheckedBinaryOp(op, box (left, right)) => {
+ // Flood everything now, so we can use `insert_value_idx` directly later.
+ state.flood(target.as_ref(), self.map());
+
let target = self.map().find(target.as_ref());
- if let Some(target) = target {
- // We should not track any projections other than
- // what is overwritten below, but just in case...
- state.flood_idx(target, self.map());
- }
let value_target = target
.and_then(|target| self.map().apply(target, TrackElem::Field(0_u32.into())));
@@ -102,26 +184,19 @@ impl<'tcx> ValueAnalysis<'tcx> for ConstAnalysis<'tcx> {
let (val, overflow) = self.binary_op(state, *op, left, right);
if let Some(value_target) = value_target {
- state.assign_idx(value_target, ValueOrPlace::Value(val), self.map());
+ // We have flooded `target` earlier.
+ state.insert_value_idx(value_target, val, self.map());
}
if let Some(overflow_target) = overflow_target {
let overflow = match overflow {
FlatSet::Top => FlatSet::Top,
FlatSet::Elem(overflow) => {
- if overflow {
- // Overflow cannot be reliably propagated. See: https://github.com/rust-lang/rust/pull/101168#issuecomment-1288091446
- FlatSet::Top
- } else {
- self.wrap_scalar(Scalar::from_bool(false), self.tcx.types.bool)
- }
+ self.wrap_scalar(Scalar::from_bool(overflow), self.tcx.types.bool)
}
FlatSet::Bottom => FlatSet::Bottom,
};
- state.assign_idx(
- overflow_target,
- ValueOrPlace::Value(overflow),
- self.map(),
- );
+ // We have flooded `target` earlier.
+ state.insert_value_idx(overflow_target, overflow, self.map());
}
}
}
@@ -170,6 +245,9 @@ impl<'tcx> ValueAnalysis<'tcx> for ConstAnalysis<'tcx> {
FlatSet::Bottom => ValueOrPlace::Value(FlatSet::Bottom),
FlatSet::Top => ValueOrPlace::Value(FlatSet::Top),
},
+ Rvalue::Discriminant(place) => {
+ ValueOrPlace::Value(state.get_discr(place.as_ref(), self.map()))
+ }
_ => self.super_rvalue(rvalue, state),
}
}
@@ -243,12 +321,13 @@ impl<'tcx> std::fmt::Debug for ScalarTy<'tcx> {
}
}
-impl<'tcx> ConstAnalysis<'tcx> {
- pub fn new(tcx: TyCtxt<'tcx>, body: &Body<'tcx>, map: Map) -> Self {
+impl<'a, 'tcx> ConstAnalysis<'a, 'tcx> {
+ pub fn new(tcx: TyCtxt<'tcx>, body: &'a Body<'tcx>, map: Map) -> Self {
let param_env = tcx.param_env(body.source.def_id());
Self {
map,
tcx,
+ local_decls: &body.local_decls,
ecx: InterpCx::new(tcx, DUMMY_SP, param_env, DummyMachine),
param_env: param_env,
}
@@ -441,6 +520,21 @@ impl<'tcx, 'map, 'a> Visitor<'tcx> for OperandCollector<'tcx, 'map, 'a> {
_ => (),
}
}
+
+ fn visit_rvalue(&mut self, rvalue: &Rvalue<'tcx>, location: Location) {
+ match rvalue {
+ Rvalue::Discriminant(place) => {
+ match self.state.get_discr(place.as_ref(), self.visitor.map) {
+ FlatSet::Top => (),
+ FlatSet::Elem(value) => {
+ self.visitor.before_effect.insert((location, *place), value);
+ }
+ FlatSet::Bottom => (),
+ }
+ }
+ _ => self.super_rvalue(rvalue, location),
+ }
+ }
}
struct DummyMachine;
diff --git a/compiler/rustc_mir_transform/src/dead_store_elimination.rs b/compiler/rustc_mir_transform/src/dead_store_elimination.rs
index 09546330c..9dbfb089d 100644
--- a/compiler/rustc_mir_transform/src/dead_store_elimination.rs
+++ b/compiler/rustc_mir_transform/src/dead_store_elimination.rs
@@ -53,6 +53,7 @@ pub fn eliminate<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>, borrowed: &BitS
| StatementKind::StorageDead(_)
| StatementKind::Coverage(_)
| StatementKind::Intrinsic(_)
+ | StatementKind::ConstEvalCounter
| StatementKind::Nop => (),
StatementKind::FakeRead(_) | StatementKind::AscribeUserType(_, _) => {
diff --git a/compiler/rustc_mir_transform/src/deaggregator.rs b/compiler/rustc_mir_transform/src/deaggregator.rs
deleted file mode 100644
index fe272de20..000000000
--- a/compiler/rustc_mir_transform/src/deaggregator.rs
+++ /dev/null
@@ -1,45 +0,0 @@
-use crate::util::expand_aggregate;
-use crate::MirPass;
-use rustc_middle::mir::*;
-use rustc_middle::ty::TyCtxt;
-
-pub struct Deaggregator;
-
-impl<'tcx> MirPass<'tcx> for Deaggregator {
- fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
- let basic_blocks = body.basic_blocks.as_mut_preserves_cfg();
- for bb in basic_blocks {
- bb.expand_statements(|stmt| {
- // FIXME(eddyb) don't match twice on `stmt.kind` (post-NLL).
- match stmt.kind {
- // FIXME(#48193) Deaggregate arrays when it's cheaper to do so.
- StatementKind::Assign(box (
- _,
- Rvalue::Aggregate(box AggregateKind::Array(_), _),
- )) => {
- return None;
- }
- StatementKind::Assign(box (_, Rvalue::Aggregate(_, _))) => {}
- _ => return None,
- }
-
- let stmt = stmt.replace_nop();
- let source_info = stmt.source_info;
- let StatementKind::Assign(box (lhs, Rvalue::Aggregate(kind, operands))) = stmt.kind else {
- bug!();
- };
-
- Some(expand_aggregate(
- lhs,
- operands.into_iter().map(|op| {
- let ty = op.ty(&body.local_decls, tcx);
- (op, ty)
- }),
- *kind,
- source_info,
- tcx,
- ))
- });
- }
- }
-}
diff --git a/compiler/rustc_mir_transform/src/deduce_param_attrs.rs b/compiler/rustc_mir_transform/src/deduce_param_attrs.rs
index ddab7bbb2..89ca04a15 100644
--- a/compiler/rustc_mir_transform/src/deduce_param_attrs.rs
+++ b/compiler/rustc_mir_transform/src/deduce_param_attrs.rs
@@ -163,7 +163,7 @@ pub fn deduced_param_attrs<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> &'tcx [Ded
// Codegen won't use this information for anything if all the function parameters are passed
// directly. Detect that and bail, for compilation speed.
- let fn_ty = tcx.type_of(def_id);
+ let fn_ty = tcx.type_of(def_id).subst_identity();
if matches!(fn_ty.kind(), ty::FnDef(..)) {
if fn_ty
.fn_sig(tcx)
diff --git a/compiler/rustc_mir_transform/src/dest_prop.rs b/compiler/rustc_mir_transform/src/dest_prop.rs
index 08e296a83..2e481b972 100644
--- a/compiler/rustc_mir_transform/src/dest_prop.rs
+++ b/compiler/rustc_mir_transform/src/dest_prop.rs
@@ -136,8 +136,8 @@ use rustc_index::bit_set::BitSet;
use rustc_middle::mir::visit::{MutVisitor, PlaceContext, Visitor};
use rustc_middle::mir::{dump_mir, PassWhere};
use rustc_middle::mir::{
- traversal, BasicBlock, Body, InlineAsmOperand, Local, LocalKind, Location, Operand, Place,
- Rvalue, Statement, StatementKind, TerminatorKind,
+ traversal, Body, InlineAsmOperand, Local, LocalKind, Location, Operand, Place, Rvalue,
+ Statement, StatementKind, TerminatorKind,
};
use rustc_middle::ty::TyCtxt;
use rustc_mir_dataflow::impls::MaybeLiveLocals;
@@ -328,7 +328,8 @@ impl<'a, 'tcx> MutVisitor<'tcx> for Merger<'a, 'tcx> {
match &statement.kind {
StatementKind::Assign(box (dest, rvalue)) => {
match rvalue {
- Rvalue::Use(Operand::Copy(place) | Operand::Move(place)) => {
+ Rvalue::CopyForDeref(place)
+ | Rvalue::Use(Operand::Copy(place) | Operand::Move(place)) => {
// These might've been turned into self-assignments by the replacement
// (this includes the original statement we wanted to eliminate).
if dest == place {
@@ -467,7 +468,7 @@ impl<'a, 'body, 'alloc, 'tcx> FilterInformation<'a, 'body, 'alloc, 'tcx> {
// to reuse the allocation.
write_info: write_info_alloc,
// Doesn't matter what we put here, will be overwritten before being used
- at: Location { block: BasicBlock::from_u32(0), statement_index: 0 },
+ at: Location::START,
};
this.internal_filter_liveness();
}
@@ -577,6 +578,7 @@ impl WriteInfo {
self.add_place(**place);
}
StatementKind::Intrinsic(_)
+ | StatementKind::ConstEvalCounter
| StatementKind::Nop
| StatementKind::Coverage(_)
| StatementKind::StorageLive(_)
@@ -754,7 +756,7 @@ impl<'tcx> Visitor<'tcx> for FindAssignments<'_, '_, 'tcx> {
fn visit_statement(&mut self, statement: &Statement<'tcx>, _: Location) {
if let StatementKind::Assign(box (
lhs,
- Rvalue::Use(Operand::Copy(rhs) | Operand::Move(rhs)),
+ Rvalue::CopyForDeref(rhs) | Rvalue::Use(Operand::Copy(rhs) | Operand::Move(rhs)),
)) = &statement.kind
{
let Some((src, dest)) = places_to_candidate_pair(*lhs, *rhs, self.body) else {
diff --git a/compiler/rustc_mir_transform/src/elaborate_box_derefs.rs b/compiler/rustc_mir_transform/src/elaborate_box_derefs.rs
index 932134bd6..954bb5aff 100644
--- a/compiler/rustc_mir_transform/src/elaborate_box_derefs.rs
+++ b/compiler/rustc_mir_transform/src/elaborate_box_derefs.rs
@@ -17,9 +17,9 @@ pub fn build_ptr_tys<'tcx>(
unique_did: DefId,
nonnull_did: DefId,
) -> (Ty<'tcx>, Ty<'tcx>, Ty<'tcx>) {
- let substs = tcx.intern_substs(&[pointee.into()]);
- let unique_ty = tcx.bound_type_of(unique_did).subst(tcx, substs);
- let nonnull_ty = tcx.bound_type_of(nonnull_did).subst(tcx, substs);
+ let substs = tcx.mk_substs(&[pointee.into()]);
+ let unique_ty = tcx.type_of(unique_did).subst(tcx, substs);
+ let nonnull_ty = tcx.type_of(nonnull_did).subst(tcx, substs);
let ptr_ty = tcx.mk_imm_ptr(pointee);
(unique_ty, nonnull_ty, ptr_ty)
@@ -93,7 +93,7 @@ impl<'tcx> MirPass<'tcx> for ElaborateBoxDerefs {
if let Some(def_id) = tcx.lang_items().owned_box() {
let unique_did = tcx.adt_def(def_id).non_enum_variant().fields[0].did;
- let Some(nonnull_def) = tcx.type_of(unique_did).ty_adt_def() else {
+ let Some(nonnull_def) = tcx.type_of(unique_did).subst_identity().ty_adt_def() else {
span_bug!(tcx.def_span(unique_did), "expected Box to contain Unique")
};
@@ -138,7 +138,7 @@ impl<'tcx> MirPass<'tcx> for ElaborateBoxDerefs {
if let Some(mut new_projections) = new_projections {
new_projections.extend_from_slice(&place.projection[last_deref..]);
- place.projection = tcx.intern_place_elems(&new_projections);
+ place.projection = tcx.mk_place_elems(&new_projections);
}
}
}
diff --git a/compiler/rustc_mir_transform/src/elaborate_drops.rs b/compiler/rustc_mir_transform/src/elaborate_drops.rs
index 65f4956d2..bdfd8dc6e 100644
--- a/compiler/rustc_mir_transform/src/elaborate_drops.rs
+++ b/compiler/rustc_mir_transform/src/elaborate_drops.rs
@@ -18,6 +18,35 @@ use rustc_span::Span;
use rustc_target::abi::VariantIdx;
use std::fmt;
+/// During MIR building, Drop and DropAndReplace terminators are inserted in every place where a drop may occur.
+/// However, in this phase, the presence of these terminators does not guarantee that a destructor will run,
+/// as the target of the drop may be uninitialized.
+/// In general, the compiler cannot determine at compile time whether a destructor will run or not.
+///
+/// At a high level, this pass refines Drop and DropAndReplace to only run the destructor if the
+/// target is initialized. The way this is achievied is by inserting drop flags for every variable
+/// that may be dropped, and then using those flags to determine whether a destructor should run.
+/// This pass also removes DropAndReplace, replacing it with a Drop paired with an assign statement.
+/// Once this is complete, Drop terminators in the MIR correspond to a call to the "drop glue" or
+/// "drop shim" for the type of the dropped place.
+///
+/// This pass relies on dropped places having an associated move path, which is then used to determine
+/// the initialization status of the place and its descendants.
+/// It's worth noting that a MIR containing a Drop without an associated move path is probably ill formed,
+/// as it would allow running a destructor on a place behind a reference:
+///
+/// ```text
+// fn drop_term<T>(t: &mut T) {
+// mir!(
+// {
+// Drop(*t, exit)
+// }
+// exit = {
+// Return()
+// }
+// )
+// }
+/// ```
pub struct ElaborateDrops;
impl<'tcx> MirPass<'tcx> for ElaborateDrops {
@@ -38,13 +67,11 @@ impl<'tcx> MirPass<'tcx> for ElaborateDrops {
};
let un_derefer = UnDerefer { tcx: tcx, derefer_sidetable: side_table };
let elaborate_patch = {
- let body = &*body;
let env = MoveDataParamEnv { move_data, param_env };
- let dead_unwinds = find_dead_unwinds(tcx, body, &env, &un_derefer);
+ remove_dead_unwinds(tcx, body, &env, &un_derefer);
let inits = MaybeInitializedPlaces::new(tcx, body, &env)
.into_engine(tcx, body)
- .dead_unwinds(&dead_unwinds)
.pass_name("elaborate_drops")
.iterate_to_fixpoint()
.into_results_cursor(body);
@@ -52,11 +79,12 @@ impl<'tcx> MirPass<'tcx> for ElaborateDrops {
let uninits = MaybeUninitializedPlaces::new(tcx, body, &env)
.mark_inactive_variants_as_uninit()
.into_engine(tcx, body)
- .dead_unwinds(&dead_unwinds)
.pass_name("elaborate_drops")
.iterate_to_fixpoint()
.into_results_cursor(body);
+ let reachable = traversal::reachable_as_bitset(body);
+
ElaborateDropsCtxt {
tcx,
body,
@@ -65,6 +93,7 @@ impl<'tcx> MirPass<'tcx> for ElaborateDrops {
drop_flags: Default::default(),
patch: MirPatch::new(body),
un_derefer: un_derefer,
+ reachable,
}
.elaborate()
};
@@ -73,22 +102,21 @@ impl<'tcx> MirPass<'tcx> for ElaborateDrops {
}
}
-/// Returns the set of basic blocks whose unwind edges are known
-/// to not be reachable, because they are `drop` terminators
+/// Removes unwind edges which are known to be unreachable, because they are in `drop` terminators
/// that can't drop anything.
-fn find_dead_unwinds<'tcx>(
+fn remove_dead_unwinds<'tcx>(
tcx: TyCtxt<'tcx>,
- body: &Body<'tcx>,
+ body: &mut Body<'tcx>,
env: &MoveDataParamEnv<'tcx>,
und: &UnDerefer<'tcx>,
-) -> BitSet<BasicBlock> {
- debug!("find_dead_unwinds({:?})", body.span);
+) {
+ debug!("remove_dead_unwinds({:?})", body.span);
// We only need to do this pass once, because unwind edges can only
// reach cleanup blocks, which can't have unwind edges themselves.
- let mut dead_unwinds = BitSet::new_empty(body.basic_blocks.len());
+ let mut dead_unwinds = Vec::new();
let mut flow_inits = MaybeInitializedPlaces::new(tcx, body, &env)
.into_engine(tcx, body)
- .pass_name("find_dead_unwinds")
+ .pass_name("remove_dead_unwinds")
.iterate_to_fixpoint()
.into_results_cursor(body);
for (bb, bb_data) in body.basic_blocks.iter_enumerated() {
@@ -100,16 +128,16 @@ fn find_dead_unwinds<'tcx>(
_ => continue,
};
- debug!("find_dead_unwinds @ {:?}: {:?}", bb, bb_data);
+ debug!("remove_dead_unwinds @ {:?}: {:?}", bb, bb_data);
let LookupResult::Exact(path) = env.move_data.rev_lookup.find(place.as_ref()) else {
- debug!("find_dead_unwinds: has parent; skipping");
+ debug!("remove_dead_unwinds: has parent; skipping");
continue;
};
flow_inits.seek_before_primary_effect(body.terminator_loc(bb));
debug!(
- "find_dead_unwinds @ {:?}: path({:?})={:?}; init_data={:?}",
+ "remove_dead_unwinds @ {:?}: path({:?})={:?}; init_data={:?}",
bb,
place,
path,
@@ -121,13 +149,22 @@ fn find_dead_unwinds<'tcx>(
maybe_live |= flow_inits.contains(child);
});
- debug!("find_dead_unwinds @ {:?}: maybe_live={}", bb, maybe_live);
+ debug!("remove_dead_unwinds @ {:?}: maybe_live={}", bb, maybe_live);
if !maybe_live {
- dead_unwinds.insert(bb);
+ dead_unwinds.push(bb);
}
}
- dead_unwinds
+ if dead_unwinds.is_empty() {
+ return;
+ }
+
+ let basic_blocks = body.basic_blocks.as_mut();
+ for &bb in dead_unwinds.iter() {
+ if let Some(unwind) = basic_blocks[bb].terminator_mut().unwind_mut() {
+ *unwind = None;
+ }
+ }
}
struct InitializationData<'mir, 'tcx> {
@@ -261,6 +298,7 @@ struct ElaborateDropsCtxt<'a, 'tcx> {
drop_flags: FxHashMap<MovePathIndex, Local>,
patch: MirPatch<'tcx>,
un_derefer: UnDerefer<'tcx>,
+ reachable: BitSet<BasicBlock>,
}
impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> {
@@ -300,6 +338,9 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> {
fn collect_drop_flags(&mut self) {
for (bb, data) in self.body.basic_blocks.iter_enumerated() {
+ if !self.reachable.contains(bb) {
+ continue;
+ }
let terminator = data.terminator();
let place = match terminator.kind {
TerminatorKind::Drop { ref place, .. }
@@ -355,6 +396,9 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> {
fn elaborate_drops(&mut self) {
for (bb, data) in self.body.basic_blocks.iter_enumerated() {
+ if !self.reachable.contains(bb) {
+ continue;
+ }
let loc = Location { block: bb, statement_index: data.statements.len() };
let terminator = data.terminator();
@@ -512,6 +556,9 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> {
fn drop_flags_for_fn_rets(&mut self) {
for (bb, data) in self.body.basic_blocks.iter_enumerated() {
+ if !self.reachable.contains(bb) {
+ continue;
+ }
if let TerminatorKind::Call {
destination, target: Some(tgt), cleanup: Some(_), ..
} = data.terminator().kind
@@ -547,6 +594,9 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> {
// clobbered before they are read.
for (bb, data) in self.body.basic_blocks.iter_enumerated() {
+ if !self.reachable.contains(bb) {
+ continue;
+ }
debug!("drop_flags_for_locs({:?})", data);
for i in 0..(data.statements.len() + 1) {
debug!("drop_flag_for_locs: stmt {}", i);
diff --git a/compiler/rustc_mir_transform/src/ffi_unwind_calls.rs b/compiler/rustc_mir_transform/src/ffi_unwind_calls.rs
index 1244c1802..e6546911a 100644
--- a/compiler/rustc_mir_transform/src/ffi_unwind_calls.rs
+++ b/compiler/rustc_mir_transform/src/ffi_unwind_calls.rs
@@ -49,7 +49,7 @@ fn has_ffi_unwind_calls(tcx: TyCtxt<'_>, local_def_id: LocalDefId) -> bool {
let body = &*tcx.mir_built(ty::WithOptConstParam::unknown(local_def_id)).borrow();
- let body_ty = tcx.type_of(def_id);
+ let body_ty = tcx.type_of(def_id).skip_binder();
let body_abi = match body_ty.kind() {
ty::FnDef(..) => body_ty.fn_sig(tcx).abi(),
ty::Closure(..) => Abi::RustCall,
diff --git a/compiler/rustc_mir_transform/src/function_item_references.rs b/compiler/rustc_mir_transform/src/function_item_references.rs
index b708d780b..66d32b954 100644
--- a/compiler/rustc_mir_transform/src/function_item_references.rs
+++ b/compiler/rustc_mir_transform/src/function_item_references.rs
@@ -79,7 +79,7 @@ impl<'tcx> FunctionItemRefChecker<'_, 'tcx> {
for bound in bounds {
if let Some(bound_ty) = self.is_pointer_trait(&bound.kind().skip_binder()) {
// Get the argument types as they appear in the function signature.
- let arg_defs = self.tcx.fn_sig(def_id).skip_binder().inputs();
+ let arg_defs = self.tcx.fn_sig(def_id).subst_identity().skip_binder().inputs();
for (arg_num, arg_def) in arg_defs.iter().enumerate() {
// For all types reachable from the argument type in the fn sig
for generic_inner_ty in arg_def.walk() {
@@ -111,11 +111,9 @@ impl<'tcx> FunctionItemRefChecker<'_, 'tcx> {
/// If the given predicate is the trait `fmt::Pointer`, returns the bound parameter type.
fn is_pointer_trait(&self, bound: &PredicateKind<'tcx>) -> Option<Ty<'tcx>> {
if let ty::PredicateKind::Clause(ty::Clause::Trait(predicate)) = bound {
- if self.tcx.is_diagnostic_item(sym::Pointer, predicate.def_id()) {
- Some(predicate.trait_ref.self_ty())
- } else {
- None
- }
+ self.tcx
+ .is_diagnostic_item(sym::Pointer, predicate.def_id())
+ .then(|| predicate.trait_ref.self_ty())
} else {
None
}
@@ -161,7 +159,8 @@ impl<'tcx> FunctionItemRefChecker<'_, 'tcx> {
.as_ref()
.assert_crate_local()
.lint_root;
- let fn_sig = self.tcx.fn_sig(fn_id);
+ // FIXME: use existing printing routines to print the function signature
+ let fn_sig = self.tcx.fn_sig(fn_id).subst(self.tcx, fn_substs);
let unsafety = fn_sig.unsafety().prefix_str();
let abi = match fn_sig.abi() {
Abi::Rust => String::from(""),
diff --git a/compiler/rustc_mir_transform/src/generator.rs b/compiler/rustc_mir_transform/src/generator.rs
index 39c61a34a..2e97312ee 100644
--- a/compiler/rustc_mir_transform/src/generator.rs
+++ b/compiler/rustc_mir_transform/src/generator.rs
@@ -52,9 +52,9 @@
use crate::deref_separator::deref_finder;
use crate::simplify;
-use crate::util::expand_aggregate;
use crate::MirPass;
-use rustc_data_structures::fx::FxHashMap;
+use rustc_data_structures::fx::{FxHashMap, FxHashSet};
+use rustc_errors::pluralize;
use rustc_hir as hir;
use rustc_hir::lang_items::LangItem;
use rustc_hir::GeneratorKind;
@@ -70,6 +70,9 @@ use rustc_mir_dataflow::impls::{
};
use rustc_mir_dataflow::storage::always_storage_live_locals;
use rustc_mir_dataflow::{self, Analysis};
+use rustc_span::def_id::DefId;
+use rustc_span::symbol::sym;
+use rustc_span::Span;
use rustc_target::abi::VariantIdx;
use rustc_target::spec::PanicStrategy;
use std::{iter, ops};
@@ -123,7 +126,7 @@ impl<'tcx> MutVisitor<'tcx> for DerefArgVisitor<'tcx> {
place,
Place {
local: SELF_ARG,
- projection: self.tcx().intern_place_elems(&[ProjectionElem::Deref]),
+ projection: self.tcx().mk_place_elems(&[ProjectionElem::Deref]),
},
self.tcx,
);
@@ -159,10 +162,9 @@ impl<'tcx> MutVisitor<'tcx> for PinArgVisitor<'tcx> {
place,
Place {
local: SELF_ARG,
- projection: self.tcx().intern_place_elems(&[ProjectionElem::Field(
- Field::new(0),
- self.ref_gen_ty,
- )]),
+ projection: self
+ .tcx()
+ .mk_place_elems(&[ProjectionElem::Field(Field::new(0), self.ref_gen_ty)]),
},
self.tcx,
);
@@ -184,7 +186,7 @@ fn replace_base<'tcx>(place: &mut Place<'tcx>, new_base: Place<'tcx>, tcx: TyCtx
let mut new_projection = new_base.projection.to_vec();
new_projection.append(&mut place.projection.to_vec());
- place.projection = tcx.intern_place_elems(&new_projection);
+ place.projection = tcx.mk_place_elems(&new_projection);
}
const SELF_ARG: Local = Local::from_u32(1);
@@ -268,31 +270,26 @@ impl<'tcx> TransformVisitor<'tcx> {
assert_eq!(self.state_adt_ref.variant(idx).fields.len(), 0);
// FIXME(swatinem): assert that `val` is indeed unit?
- statements.extend(expand_aggregate(
- Place::return_place(),
- std::iter::empty(),
- kind,
+ statements.push(Statement {
+ kind: StatementKind::Assign(Box::new((
+ Place::return_place(),
+ Rvalue::Aggregate(Box::new(kind), vec![]),
+ ))),
source_info,
- self.tcx,
- ));
+ });
return;
}
// else: `Poll::Ready(x)`, `GeneratorState::Yielded(x)` or `GeneratorState::Complete(x)`
assert_eq!(self.state_adt_ref.variant(idx).fields.len(), 1);
- let ty = self
- .tcx
- .bound_type_of(self.state_adt_ref.variant(idx).fields[0].did)
- .subst(self.tcx, self.state_substs);
-
- statements.extend(expand_aggregate(
- Place::return_place(),
- std::iter::once((val, ty)),
- kind,
+ statements.push(Statement {
+ kind: StatementKind::Assign(Box::new((
+ Place::return_place(),
+ Rvalue::Aggregate(Box::new(kind), vec![val]),
+ ))),
source_info,
- self.tcx,
- ));
+ });
}
// Create a Place referencing a generator struct field
@@ -302,7 +299,7 @@ impl<'tcx> TransformVisitor<'tcx> {
let mut projection = base.projection.to_vec();
projection.push(ProjectionElem::Field(Field::new(idx), ty));
- Place { local: base.local, projection: self.tcx.intern_place_elems(&projection) }
+ Place { local: base.local, projection: self.tcx.mk_place_elems(&projection) }
}
// Create a statement which changes the discriminant
@@ -429,7 +426,7 @@ fn make_generator_state_argument_pinned<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body
let pin_did = tcx.require_lang_item(LangItem::Pin, Some(body.span));
let pin_adt_ref = tcx.adt_def(pin_did);
- let substs = tcx.intern_substs(&[ref_gen_ty.into()]);
+ let substs = tcx.mk_substs(&[ref_gen_ty.into()]);
let pin_ref_gen_ty = tcx.mk_adt(pin_adt_ref, substs);
// Replace the by ref generator argument
@@ -489,7 +486,7 @@ fn transform_async_context<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
let get_context_def_id = tcx.require_lang_item(LangItem::GetContext, None);
- for bb in BasicBlock::new(0)..body.basic_blocks.next_index() {
+ for bb in START_BLOCK..body.basic_blocks.next_index() {
let bb_data = &body[bb];
if bb_data.is_cleanup {
continue;
@@ -854,7 +851,7 @@ fn sanitize_witness<'tcx>(
body: &Body<'tcx>,
witness: Ty<'tcx>,
upvars: Vec<Ty<'tcx>>,
- saved_locals: &GeneratorSavedLocals,
+ layout: &GeneratorLayout<'tcx>,
) {
let did = body.source.def_id();
let param_env = tcx.param_env(did);
@@ -873,31 +870,36 @@ fn sanitize_witness<'tcx>(
}
};
- for (local, decl) in body.local_decls.iter_enumerated() {
- // Ignore locals which are internal or not saved between yields.
- if !saved_locals.contains(local) || decl.internal {
+ let mut mismatches = Vec::new();
+ for fty in &layout.field_tys {
+ if fty.ignore_for_traits {
continue;
}
- let decl_ty = tcx.normalize_erasing_regions(param_env, decl.ty);
+ let decl_ty = tcx.normalize_erasing_regions(param_env, fty.ty);
// Sanity check that typeck knows about the type of locals which are
// live across a suspension point
if !allowed.contains(&decl_ty) && !allowed_upvars.contains(&decl_ty) {
- span_bug!(
- body.span,
- "Broken MIR: generator contains type {} in MIR, \
- but typeck only knows about {} and {:?}",
- decl_ty,
- allowed,
- allowed_upvars
- );
+ mismatches.push(decl_ty);
}
}
+
+ if !mismatches.is_empty() {
+ span_bug!(
+ body.span,
+ "Broken MIR: generator contains type {:?} in MIR, \
+ but typeck only knows about {} and {:?}",
+ mismatches,
+ allowed,
+ allowed_upvars
+ );
+ }
}
fn compute_layout<'tcx>(
+ tcx: TyCtxt<'tcx>,
liveness: LivenessInfo,
- body: &mut Body<'tcx>,
+ body: &Body<'tcx>,
) -> (
FxHashMap<Local, (Ty<'tcx>, VariantIdx, usize)>,
GeneratorLayout<'tcx>,
@@ -915,9 +917,33 @@ fn compute_layout<'tcx>(
let mut locals = IndexVec::<GeneratorSavedLocal, _>::new();
let mut tys = IndexVec::<GeneratorSavedLocal, _>::new();
for (saved_local, local) in saved_locals.iter_enumerated() {
- locals.push(local);
- tys.push(body.local_decls[local].ty);
debug!("generator saved local {:?} => {:?}", saved_local, local);
+
+ locals.push(local);
+ let decl = &body.local_decls[local];
+ debug!(?decl);
+
+ let ignore_for_traits = if tcx.sess.opts.unstable_opts.drop_tracking_mir {
+ match decl.local_info {
+ // Do not include raw pointers created from accessing `static` items, as those could
+ // well be re-created by another access to the same static.
+ Some(box LocalInfo::StaticRef { is_thread_local, .. }) => !is_thread_local,
+ // Fake borrows are only read by fake reads, so do not have any reality in
+ // post-analysis MIR.
+ Some(box LocalInfo::FakeBorrow) => true,
+ _ => false,
+ }
+ } else {
+ // FIXME(#105084) HIR-based drop tracking does not account for all the temporaries that
+ // MIR building may introduce. This leads to wrongly ignored types, but this is
+ // necessary for internal consistency and to avoid ICEs.
+ decl.internal
+ };
+ let decl =
+ GeneratorSavedTy { ty: decl.ty, source_info: decl.source_info, ignore_for_traits };
+ debug!(?decl);
+
+ tys.push(decl);
}
// Leave empty variants for the UNRESUMED, RETURNED, and POISONED states.
@@ -947,7 +973,7 @@ fn compute_layout<'tcx>(
// just use the first one here. That's fine; fields do not move
// around inside generators, so it doesn't matter which variant
// index we access them by.
- remap.entry(locals[saved_local]).or_insert((tys[saved_local], variant_index, idx));
+ remap.entry(locals[saved_local]).or_insert((tys[saved_local].ty, variant_index, idx));
}
variant_fields.push(fields);
variant_source_info.push(source_info_at_suspension_points[suspension_point_idx]);
@@ -957,6 +983,7 @@ fn compute_layout<'tcx>(
let layout =
GeneratorLayout { field_tys: tys, variant_fields, variant_source_info, storage_conflicts };
+ debug!(?layout);
(remap, layout, storage_liveness)
}
@@ -1227,7 +1254,7 @@ fn create_generator_resume_function<'tcx>(
use rustc_middle::mir::AssertKind::{ResumedAfterPanic, ResumedAfterReturn};
// Jump to the entry point on the unresumed
- cases.insert(0, (UNRESUMED, BasicBlock::new(0)));
+ cases.insert(0, (UNRESUMED, START_BLOCK));
// Panic when resumed on the returned or poisoned state
let generator_kind = body.generator_kind().unwrap();
@@ -1351,6 +1378,42 @@ fn create_cases<'tcx>(
.collect()
}
+#[instrument(level = "debug", skip(tcx), ret)]
+pub(crate) fn mir_generator_witnesses<'tcx>(
+ tcx: TyCtxt<'tcx>,
+ def_id: DefId,
+) -> GeneratorLayout<'tcx> {
+ assert!(tcx.sess.opts.unstable_opts.drop_tracking_mir);
+ let def_id = def_id.expect_local();
+
+ let (body, _) = tcx.mir_promoted(ty::WithOptConstParam::unknown(def_id));
+ let body = body.borrow();
+ let body = &*body;
+
+ // The first argument is the generator type passed by value
+ let gen_ty = body.local_decls[ty::CAPTURE_STRUCT_LOCAL].ty;
+
+ // Get the interior types and substs which typeck computed
+ let movable = match *gen_ty.kind() {
+ ty::Generator(_, _, movability) => movability == hir::Movability::Movable,
+ _ => span_bug!(body.span, "unexpected generator type {}", gen_ty),
+ };
+
+ // When first entering the generator, move the resume argument into its new local.
+ let always_live_locals = always_storage_live_locals(&body);
+
+ let liveness_info = locals_live_across_suspend_points(tcx, body, &always_live_locals, movable);
+
+ // Extract locals which are live across suspension point into `layout`
+ // `remap` gives a mapping from local indices onto generator struct indices
+ // `storage_liveness` tells us which locals have live storage at suspension points
+ let (_, generator_layout, _) = compute_layout(tcx, liveness_info, body);
+
+ check_suspend_tys(tcx, &generator_layout, &body);
+
+ generator_layout
+}
+
impl<'tcx> MirPass<'tcx> for StateTransform {
fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
let Some(yield_ty) = body.yield_ty() else {
@@ -1363,14 +1426,14 @@ impl<'tcx> MirPass<'tcx> for StateTransform {
// The first argument is the generator type passed by value
let gen_ty = body.local_decls.raw[1].ty;
- // Get the interior types and substs which typeck computed
- let (upvars, interior, discr_ty, movable) = match *gen_ty.kind() {
+ // Get the discriminant type and substs which typeck computed
+ let (discr_ty, upvars, interior, movable) = match *gen_ty.kind() {
ty::Generator(_, substs, movability) => {
let substs = substs.as_generator();
(
- substs.upvar_tys().collect(),
- substs.witness(),
substs.discr_ty(tcx),
+ substs.upvar_tys().collect::<Vec<_>>(),
+ substs.witness(),
movability == hir::Movability::Movable,
)
}
@@ -1386,13 +1449,13 @@ impl<'tcx> MirPass<'tcx> for StateTransform {
// Compute Poll<return_ty>
let poll_did = tcx.require_lang_item(LangItem::Poll, None);
let poll_adt_ref = tcx.adt_def(poll_did);
- let poll_substs = tcx.intern_substs(&[body.return_ty().into()]);
+ let poll_substs = tcx.mk_substs(&[body.return_ty().into()]);
(poll_adt_ref, poll_substs)
} else {
// Compute GeneratorState<yield_ty, return_ty>
let state_did = tcx.require_lang_item(LangItem::GeneratorState, None);
let state_adt_ref = tcx.adt_def(state_did);
- let state_substs = tcx.intern_substs(&[yield_ty.into(), body.return_ty().into()]);
+ let state_substs = tcx.mk_substs(&[yield_ty.into(), body.return_ty().into()]);
(state_adt_ref, state_substs)
};
let ret_ty = tcx.mk_adt(state_adt_ref, state_substs);
@@ -1417,7 +1480,7 @@ impl<'tcx> MirPass<'tcx> for StateTransform {
// When first entering the generator, move the resume argument into its new local.
let source_info = SourceInfo::outermost(body.span);
- let stmts = &mut body.basic_blocks_mut()[BasicBlock::new(0)].statements;
+ let stmts = &mut body.basic_blocks_mut()[START_BLOCK].statements;
stmts.insert(
0,
Statement {
@@ -1434,8 +1497,6 @@ impl<'tcx> MirPass<'tcx> for StateTransform {
let liveness_info =
locals_live_across_suspend_points(tcx, body, &always_live_locals, movable);
- sanitize_witness(tcx, body, interior, upvars, &liveness_info.saved_locals);
-
if tcx.sess.opts.unstable_opts.validate_mir {
let mut vis = EnsureGeneratorFieldAssignmentsNeverAlias {
assigned_local: None,
@@ -1449,7 +1510,13 @@ impl<'tcx> MirPass<'tcx> for StateTransform {
// Extract locals which are live across suspension point into `layout`
// `remap` gives a mapping from local indices onto generator struct indices
// `storage_liveness` tells us which locals have live storage at suspension points
- let (remap, layout, storage_liveness) = compute_layout(liveness_info, body);
+ let (remap, layout, storage_liveness) = compute_layout(tcx, liveness_info, body);
+
+ if tcx.sess.opts.unstable_opts.validate_mir
+ && !tcx.sess.opts.unstable_opts.drop_tracking_mir
+ {
+ sanitize_witness(tcx, body, interior, upvars, &layout);
+ }
let can_return = can_return(tcx, body, tcx.param_env(body.source.def_id()));
@@ -1583,6 +1650,7 @@ impl<'tcx> Visitor<'tcx> for EnsureGeneratorFieldAssignmentsNeverAlias<'_> {
| StatementKind::AscribeUserType(..)
| StatementKind::Coverage(..)
| StatementKind::Intrinsic(..)
+ | StatementKind::ConstEvalCounter
| StatementKind::Nop => {}
}
}
@@ -1631,3 +1699,212 @@ impl<'tcx> Visitor<'tcx> for EnsureGeneratorFieldAssignmentsNeverAlias<'_> {
}
}
}
+
+fn check_suspend_tys<'tcx>(tcx: TyCtxt<'tcx>, layout: &GeneratorLayout<'tcx>, body: &Body<'tcx>) {
+ let mut linted_tys = FxHashSet::default();
+
+ // We want a user-facing param-env.
+ let param_env = tcx.param_env(body.source.def_id());
+
+ for (variant, yield_source_info) in
+ layout.variant_fields.iter().zip(&layout.variant_source_info)
+ {
+ debug!(?variant);
+ for &local in variant {
+ let decl = &layout.field_tys[local];
+ debug!(?decl);
+
+ if !decl.ignore_for_traits && linted_tys.insert(decl.ty) {
+ let Some(hir_id) = decl.source_info.scope.lint_root(&body.source_scopes) else { continue };
+
+ check_must_not_suspend_ty(
+ tcx,
+ decl.ty,
+ hir_id,
+ param_env,
+ SuspendCheckData {
+ source_span: decl.source_info.span,
+ yield_span: yield_source_info.span,
+ plural_len: 1,
+ ..Default::default()
+ },
+ );
+ }
+ }
+ }
+}
+
+#[derive(Default)]
+struct SuspendCheckData<'a> {
+ 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 proceeding 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 precedent in the compiler
+fn check_must_not_suspend_ty<'tcx>(
+ tcx: TyCtxt<'tcx>,
+ ty: Ty<'tcx>,
+ hir_id: hir::HirId,
+ param_env: ty::ParamEnv<'tcx>,
+ data: SuspendCheckData<'_>,
+) -> bool {
+ if ty.is_unit() {
+ return false;
+ }
+
+ let plural_suffix = pluralize!(data.plural_len);
+
+ debug!("Checking must_not_suspend for {}", ty);
+
+ 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(
+ tcx,
+ boxed_ty,
+ hir_id,
+ param_env,
+ SuspendCheckData { descr_pre, ..data },
+ )
+ }
+ ty::Adt(def, _) => check_must_not_suspend_def(tcx, def.did(), hir_id, data),
+ // FIXME: support adding the attribute to TAITs
+ ty::Alias(ty::Opaque, ty::AliasTy { def_id: def, .. }) => {
+ let mut has_emitted = false;
+ for &(predicate, _) in tcx.explicit_item_bounds(def) {
+ // We only look at the `DefId`, so it is safe to skip the binder here.
+ if let ty::PredicateKind::Clause(ty::Clause::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(
+ 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(
+ tcx,
+ def_id,
+ hir_id,
+ SuspendCheckData { descr_post, ..data },
+ ) {
+ has_emitted = true;
+ break;
+ }
+ }
+ }
+ has_emitted
+ }
+ ty::Tuple(fields) => {
+ let mut has_emitted = false;
+ for (i, ty) in fields.iter().enumerate() {
+ let descr_post = &format!(" in tuple element {i}");
+ if check_must_not_suspend_ty(
+ tcx,
+ ty,
+ hir_id,
+ param_env,
+ SuspendCheckData { descr_post, ..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(
+ tcx,
+ ty,
+ hir_id,
+ param_env,
+ SuspendCheckData {
+ descr_pre,
+ plural_len: len.try_eval_target_usize(tcx, param_env).unwrap_or(0) as usize + 1,
+ ..data
+ },
+ )
+ }
+ // If drop tracking is enabled, we want to look through references, since the referrent
+ // may not be considered live across the await point.
+ ty::Ref(_region, ty, _mutability) => {
+ let descr_pre = &format!("{}reference{} to ", data.descr_pre, plural_suffix);
+ check_must_not_suspend_ty(
+ tcx,
+ ty,
+ hir_id,
+ param_env,
+ SuspendCheckData { descr_pre, ..data },
+ )
+ }
+ _ => false,
+ }
+}
+
+fn check_must_not_suspend_def(
+ tcx: TyCtxt<'_>,
+ def_id: DefId,
+ hir_id: hir::HirId,
+ data: SuspendCheckData<'_>,
+) -> bool {
+ if let Some(attr) = tcx.get_attr(def_id, sym::must_not_suspend) {
+ let msg = format!(
+ "{}`{}`{} held across a suspend point, but should not be",
+ data.descr_pre,
+ tcx.def_path_str(def_id),
+ data.descr_post,
+ );
+ tcx.struct_span_lint_hir(
+ rustc_session::lint::builtin::MUST_NOT_SUSPEND,
+ hir_id,
+ data.source_span,
+ msg,
+ |lint| {
+ // add span pointing to the offending yield/await
+ lint.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
+ lint.span_note(data.source_span, note.as_str());
+ }
+
+ // Add some quick suggestions on what to do
+ // FIXME: can `drop` work as a suggestion here as well?
+ lint.span_help(
+ data.source_span,
+ "consider using a block (`{ ... }`) \
+ to shrink the value's scope, ending before the suspend point",
+ )
+ },
+ );
+
+ true
+ } else {
+ false
+ }
+}
diff --git a/compiler/rustc_mir_transform/src/inline.rs b/compiler/rustc_mir_transform/src/inline.rs
index 28c9080d3..6e6d6566f 100644
--- a/compiler/rustc_mir_transform/src/inline.rs
+++ b/compiler/rustc_mir_transform/src/inline.rs
@@ -96,7 +96,7 @@ fn inline<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) -> bool {
history: Vec::new(),
changed: false,
};
- let blocks = BasicBlock::new(0)..body.basic_blocks.next_index();
+ let blocks = START_BLOCK..body.basic_blocks.next_index();
this.process_blocks(body, blocks);
this.changed
}
@@ -331,7 +331,7 @@ impl<'tcx> Inliner<'tcx> {
return None;
}
- let fn_sig = self.tcx.bound_fn_sig(def_id).subst(self.tcx, substs);
+ let fn_sig = self.tcx.fn_sig(def_id).subst(self.tcx, substs);
let source_info = SourceInfo { span: fn_span, ..terminator.source_info };
return Some(CallSite { callee, fn_sig, block: bb, target, source_info });
@@ -888,7 +888,7 @@ impl<'tcx> Visitor<'tcx> for CostChecker<'_, 'tcx> {
location: Location,
) {
if let ProjectionElem::Field(f, ty) = elem {
- let parent = Place { local, projection: self.tcx.intern_place_elems(proj_base) };
+ let parent = Place { local, projection: self.tcx.mk_place_elems(proj_base) };
let parent_ty = parent.ty(&self.callee_body.local_decls, self.tcx);
let check_equal = |this: &mut Self, f_ty| {
if !util::is_equal_up_to_subtyping(this.tcx, this.param_env, ty, f_ty) {
@@ -900,7 +900,7 @@ impl<'tcx> Visitor<'tcx> for CostChecker<'_, 'tcx> {
let kind = match parent_ty.ty.kind() {
&ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. }) => {
- self.tcx.bound_type_of(def_id).subst(self.tcx, substs).kind()
+ self.tcx.type_of(def_id).subst(self.tcx, substs).kind()
}
kind => kind,
};
@@ -947,12 +947,12 @@ impl<'tcx> Visitor<'tcx> for CostChecker<'_, 'tcx> {
return;
};
- let Some(&f_ty) = layout.field_tys.get(local) else {
+ let Some(f_ty) = layout.field_tys.get(local) else {
self.validation = Err("malformed MIR");
return;
};
- f_ty
+ f_ty.ty
} else {
let Some(f_ty) = substs.as_generator().prefix_tys().nth(f.index()) else {
self.validation = Err("malformed MIR");
diff --git a/compiler/rustc_mir_transform/src/inline/cycle.rs b/compiler/rustc_mir_transform/src/inline/cycle.rs
index b027f9492..792457c80 100644
--- a/compiler/rustc_mir_transform/src/inline/cycle.rs
+++ b/compiler/rustc_mir_transform/src/inline/cycle.rs
@@ -2,7 +2,7 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexSet};
use rustc_data_structures::stack::ensure_sufficient_stack;
use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_middle::mir::TerminatorKind;
-use rustc_middle::ty::TypeVisitable;
+use rustc_middle::ty::TypeVisitableExt;
use rustc_middle::ty::{self, subst::SubstsRef, InstanceDef, TyCtxt};
use rustc_session::Limit;
diff --git a/compiler/rustc_mir_transform/src/instcombine.rs b/compiler/rustc_mir_transform/src/instcombine.rs
index 2f3c65869..4182da195 100644
--- a/compiler/rustc_mir_transform/src/instcombine.rs
+++ b/compiler/rustc_mir_transform/src/instcombine.rs
@@ -6,7 +6,9 @@ use rustc_middle::mir::{
BinOp, Body, Constant, ConstantKind, LocalDecls, Operand, Place, ProjectionElem, Rvalue,
SourceInfo, Statement, StatementKind, Terminator, TerminatorKind, UnOp,
};
-use rustc_middle::ty::{self, TyCtxt};
+use rustc_middle::ty::layout::ValidityRequirement;
+use rustc_middle::ty::{self, ParamEnv, SubstsRef, Ty, TyCtxt};
+use rustc_span::symbol::Symbol;
pub struct InstCombine;
@@ -16,7 +18,11 @@ impl<'tcx> MirPass<'tcx> for InstCombine {
}
fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
- let ctx = InstCombineContext { tcx, local_decls: &body.local_decls };
+ let ctx = InstCombineContext {
+ tcx,
+ local_decls: &body.local_decls,
+ param_env: tcx.param_env_reveal_all_normalized(body.source.def_id()),
+ };
for block in body.basic_blocks.as_mut() {
for statement in block.statements.iter_mut() {
match statement.kind {
@@ -24,6 +30,7 @@ impl<'tcx> MirPass<'tcx> for InstCombine {
ctx.combine_bool_cmp(&statement.source_info, rvalue);
ctx.combine_ref_deref(&statement.source_info, rvalue);
ctx.combine_len(&statement.source_info, rvalue);
+ ctx.combine_cast(&statement.source_info, rvalue);
}
_ => {}
}
@@ -33,6 +40,10 @@ impl<'tcx> MirPass<'tcx> for InstCombine {
&mut block.terminator.as_mut().unwrap(),
&mut block.statements,
);
+ ctx.combine_intrinsic_assert(
+ &mut block.terminator.as_mut().unwrap(),
+ &mut block.statements,
+ );
}
}
}
@@ -40,6 +51,7 @@ impl<'tcx> MirPass<'tcx> for InstCombine {
struct InstCombineContext<'tcx, 'a> {
tcx: TyCtxt<'tcx>,
local_decls: &'a LocalDecls<'tcx>,
+ param_env: ParamEnv<'tcx>,
}
impl<'tcx> InstCombineContext<'tcx, '_> {
@@ -99,11 +111,7 @@ impl<'tcx> InstCombineContext<'tcx, '_> {
fn combine_ref_deref(&self, source_info: &SourceInfo, rvalue: &mut Rvalue<'tcx>) {
if let Rvalue::Ref(_, _, place) = rvalue {
if let Some((base, ProjectionElem::Deref)) = place.as_ref().last_projection() {
- if let ty::Ref(_, _, Mutability::Not) =
- base.ty(self.local_decls, self.tcx).ty.kind()
- {
- // The dereferenced place must have type `&_`, so that we don't copy `&mut _`.
- } else {
+ if rvalue.ty(self.local_decls, self.tcx) != base.ty(self.local_decls, self.tcx).ty {
return;
}
@@ -113,7 +121,7 @@ impl<'tcx> InstCombineContext<'tcx, '_> {
*rvalue = Rvalue::Use(Operand::Copy(Place {
local: base.local,
- projection: self.tcx.intern_place_elems(base.projection),
+ projection: self.tcx.mk_place_elems(base.projection),
}));
}
}
@@ -135,6 +143,14 @@ impl<'tcx> InstCombineContext<'tcx, '_> {
}
}
+ fn combine_cast(&self, _source_info: &SourceInfo, rvalue: &mut Rvalue<'tcx>) {
+ if let Rvalue::Cast(_kind, operand, ty) = rvalue {
+ if operand.ty(self.local_decls, self.tcx) == *ty {
+ *rvalue = Rvalue::Use(operand.clone());
+ }
+ }
+ }
+
fn combine_primitive_clone(
&self,
terminator: &mut Terminator<'tcx>,
@@ -200,4 +216,58 @@ impl<'tcx> InstCombineContext<'tcx, '_> {
});
terminator.kind = TerminatorKind::Goto { target: destination_block };
}
+
+ fn combine_intrinsic_assert(
+ &self,
+ terminator: &mut Terminator<'tcx>,
+ _statements: &mut Vec<Statement<'tcx>>,
+ ) {
+ let TerminatorKind::Call { func, target, .. } = &mut terminator.kind else { return; };
+ let Some(target_block) = target else { return; };
+ let func_ty = func.ty(self.local_decls, self.tcx);
+ let Some((intrinsic_name, substs)) = resolve_rust_intrinsic(self.tcx, func_ty) else {
+ return;
+ };
+ // The intrinsics we are interested in have one generic parameter
+ if substs.is_empty() {
+ return;
+ }
+ let ty = substs.type_at(0);
+
+ let known_is_valid = intrinsic_assert_panics(self.tcx, self.param_env, ty, intrinsic_name);
+ match known_is_valid {
+ // We don't know the layout or it's not validity assertion at all, don't touch it
+ None => {}
+ Some(true) => {
+ // If we know the assert panics, indicate to later opts that the call diverges
+ *target = None;
+ }
+ Some(false) => {
+ // If we know the assert does not panic, turn the call into a Goto
+ terminator.kind = TerminatorKind::Goto { target: *target_block };
+ }
+ }
+ }
+}
+
+fn intrinsic_assert_panics<'tcx>(
+ tcx: TyCtxt<'tcx>,
+ param_env: ty::ParamEnv<'tcx>,
+ ty: Ty<'tcx>,
+ intrinsic_name: Symbol,
+) -> Option<bool> {
+ let requirement = ValidityRequirement::from_intrinsic(intrinsic_name)?;
+ Some(!tcx.check_validity_requirement((requirement, param_env.and(ty))).ok()?)
+}
+
+fn resolve_rust_intrinsic<'tcx>(
+ tcx: TyCtxt<'tcx>,
+ func_ty: Ty<'tcx>,
+) -> Option<(Symbol, SubstsRef<'tcx>)> {
+ if let ty::FnDef(def_id, substs) = *func_ty.kind() {
+ if tcx.is_intrinsic(def_id) {
+ return Some((tcx.item_name(def_id), substs));
+ }
+ }
+ None
}
diff --git a/compiler/rustc_mir_transform/src/large_enums.rs b/compiler/rustc_mir_transform/src/large_enums.rs
new file mode 100644
index 000000000..89e0a007d
--- /dev/null
+++ b/compiler/rustc_mir_transform/src/large_enums.rs
@@ -0,0 +1,294 @@
+use crate::rustc_middle::ty::util::IntTypeExt;
+use crate::MirPass;
+use rustc_data_structures::fx::FxHashMap;
+use rustc_middle::mir::interpret::AllocId;
+use rustc_middle::mir::*;
+use rustc_middle::ty::{self, AdtDef, ParamEnv, Ty, TyCtxt};
+use rustc_session::Session;
+use rustc_target::abi::{HasDataLayout, Size, TagEncoding, Variants};
+
+/// A pass that seeks to optimize unnecessary moves of large enum types, if there is a large
+/// enough discrepancy between them.
+///
+/// i.e. If there is are two variants:
+/// ```
+/// enum Example {
+/// Small,
+/// Large([u32; 1024]),
+/// }
+/// ```
+/// Instead of emitting moves of the large variant,
+/// Perform a memcpy instead.
+/// Based off of [this HackMD](https://hackmd.io/@ft4bxUsFT5CEUBmRKYHr7w/rJM8BBPzD).
+///
+/// In summary, what this does is at runtime determine which enum variant is active,
+/// and instead of copying all the bytes of the largest possible variant,
+/// copy only the bytes for the currently active variant.
+pub struct EnumSizeOpt {
+ pub(crate) discrepancy: u64,
+}
+
+impl<'tcx> MirPass<'tcx> for EnumSizeOpt {
+ fn is_enabled(&self, sess: &Session) -> bool {
+ sess.opts.unstable_opts.unsound_mir_opts || sess.mir_opt_level() >= 3
+ }
+ fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
+ // NOTE: This pass may produce different MIR based on the alignment of the target
+ // platform, but it will still be valid.
+ self.optim(tcx, body);
+ }
+}
+
+impl EnumSizeOpt {
+ fn candidate<'tcx>(
+ &self,
+ tcx: TyCtxt<'tcx>,
+ param_env: ParamEnv<'tcx>,
+ ty: Ty<'tcx>,
+ alloc_cache: &mut FxHashMap<Ty<'tcx>, AllocId>,
+ ) -> Option<(AdtDef<'tcx>, usize, AllocId)> {
+ let adt_def = match ty.kind() {
+ ty::Adt(adt_def, _substs) if adt_def.is_enum() => adt_def,
+ _ => return None,
+ };
+ let layout = tcx.layout_of(param_env.and(ty)).ok()?;
+ let variants = match &layout.variants {
+ Variants::Single { .. } => return None,
+ Variants::Multiple { tag_encoding, .. }
+ if matches!(tag_encoding, TagEncoding::Niche { .. }) =>
+ {
+ return None;
+ }
+ Variants::Multiple { variants, .. } if variants.len() <= 1 => return None,
+ Variants::Multiple { variants, .. } => variants,
+ };
+ let min = variants.iter().map(|v| v.size).min().unwrap();
+ let max = variants.iter().map(|v| v.size).max().unwrap();
+ if max.bytes() - min.bytes() < self.discrepancy {
+ return None;
+ }
+
+ let num_discrs = adt_def.discriminants(tcx).count();
+ if variants.iter_enumerated().any(|(var_idx, _)| {
+ let discr_for_var = adt_def.discriminant_for_variant(tcx, var_idx).val;
+ (discr_for_var > usize::MAX as u128) || (discr_for_var as usize >= num_discrs)
+ }) {
+ return None;
+ }
+ if let Some(alloc_id) = alloc_cache.get(&ty) {
+ return Some((*adt_def, num_discrs, *alloc_id));
+ }
+
+ let data_layout = tcx.data_layout();
+ let ptr_sized_int = data_layout.ptr_sized_integer();
+ let target_bytes = ptr_sized_int.size().bytes() as usize;
+ let mut data = vec![0; target_bytes * num_discrs];
+ macro_rules! encode_store {
+ ($curr_idx: expr, $endian: expr, $bytes: expr) => {
+ let bytes = match $endian {
+ rustc_target::abi::Endian::Little => $bytes.to_le_bytes(),
+ rustc_target::abi::Endian::Big => $bytes.to_be_bytes(),
+ };
+ for (i, b) in bytes.into_iter().enumerate() {
+ data[$curr_idx + i] = b;
+ }
+ };
+ }
+
+ for (var_idx, layout) in variants.iter_enumerated() {
+ let curr_idx =
+ target_bytes * adt_def.discriminant_for_variant(tcx, var_idx).val as usize;
+ let sz = layout.size;
+ match ptr_sized_int {
+ rustc_target::abi::Integer::I32 => {
+ encode_store!(curr_idx, data_layout.endian, sz.bytes() as u32);
+ }
+ rustc_target::abi::Integer::I64 => {
+ encode_store!(curr_idx, data_layout.endian, sz.bytes());
+ }
+ _ => unreachable!(),
+ };
+ }
+ let alloc = interpret::Allocation::from_bytes(
+ data,
+ tcx.data_layout.ptr_sized_integer().align(&tcx.data_layout).abi,
+ Mutability::Not,
+ );
+ let alloc = tcx.create_memory_alloc(tcx.mk_const_alloc(alloc));
+ Some((*adt_def, num_discrs, *alloc_cache.entry(ty).or_insert(alloc)))
+ }
+ fn optim<'tcx>(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
+ let mut alloc_cache = FxHashMap::default();
+ let body_did = body.source.def_id();
+ let param_env = tcx.param_env(body_did);
+
+ let blocks = body.basic_blocks.as_mut();
+ let local_decls = &mut body.local_decls;
+
+ for bb in blocks {
+ bb.expand_statements(|st| {
+ if let StatementKind::Assign(box (
+ lhs,
+ Rvalue::Use(Operand::Copy(rhs) | Operand::Move(rhs)),
+ )) = &st.kind
+ {
+ let ty = lhs.ty(local_decls, tcx).ty;
+
+ let source_info = st.source_info;
+ let span = source_info.span;
+
+ let (adt_def, num_variants, alloc_id) =
+ self.candidate(tcx, param_env, ty, &mut alloc_cache)?;
+ let alloc = tcx.global_alloc(alloc_id).unwrap_memory();
+
+ let tmp_ty = tcx.mk_array(tcx.types.usize, num_variants as u64);
+
+ let size_array_local = local_decls.push(LocalDecl::new(tmp_ty, span));
+ let store_live = Statement {
+ source_info,
+ kind: StatementKind::StorageLive(size_array_local),
+ };
+
+ let place = Place::from(size_array_local);
+ let constant_vals = Constant {
+ span,
+ user_ty: None,
+ literal: ConstantKind::Val(
+ interpret::ConstValue::ByRef { alloc, offset: Size::ZERO },
+ tmp_ty,
+ ),
+ };
+ let rval = Rvalue::Use(Operand::Constant(box (constant_vals)));
+
+ let const_assign =
+ Statement { source_info, kind: StatementKind::Assign(box (place, rval)) };
+
+ let discr_place = Place::from(
+ local_decls
+ .push(LocalDecl::new(adt_def.repr().discr_type().to_ty(tcx), span)),
+ );
+
+ let store_discr = Statement {
+ source_info,
+ kind: StatementKind::Assign(box (discr_place, Rvalue::Discriminant(*rhs))),
+ };
+
+ let discr_cast_place =
+ Place::from(local_decls.push(LocalDecl::new(tcx.types.usize, span)));
+
+ let cast_discr = Statement {
+ source_info,
+ kind: StatementKind::Assign(box (
+ discr_cast_place,
+ Rvalue::Cast(
+ CastKind::IntToInt,
+ Operand::Copy(discr_place),
+ tcx.types.usize,
+ ),
+ )),
+ };
+
+ let size_place =
+ Place::from(local_decls.push(LocalDecl::new(tcx.types.usize, span)));
+
+ let store_size = Statement {
+ source_info,
+ kind: StatementKind::Assign(box (
+ size_place,
+ Rvalue::Use(Operand::Copy(Place {
+ local: size_array_local,
+ projection: tcx
+ .mk_place_elems(&[PlaceElem::Index(discr_cast_place.local)]),
+ })),
+ )),
+ };
+
+ let dst =
+ Place::from(local_decls.push(LocalDecl::new(tcx.mk_mut_ptr(ty), span)));
+
+ let dst_ptr = Statement {
+ source_info,
+ kind: StatementKind::Assign(box (
+ dst,
+ Rvalue::AddressOf(Mutability::Mut, *lhs),
+ )),
+ };
+
+ let dst_cast_ty = tcx.mk_mut_ptr(tcx.types.u8);
+ let dst_cast_place =
+ Place::from(local_decls.push(LocalDecl::new(dst_cast_ty, span)));
+
+ let dst_cast = Statement {
+ source_info,
+ kind: StatementKind::Assign(box (
+ dst_cast_place,
+ Rvalue::Cast(CastKind::PtrToPtr, Operand::Copy(dst), dst_cast_ty),
+ )),
+ };
+
+ let src =
+ Place::from(local_decls.push(LocalDecl::new(tcx.mk_imm_ptr(ty), span)));
+
+ let src_ptr = Statement {
+ source_info,
+ kind: StatementKind::Assign(box (
+ src,
+ Rvalue::AddressOf(Mutability::Not, *rhs),
+ )),
+ };
+
+ let src_cast_ty = tcx.mk_imm_ptr(tcx.types.u8);
+ let src_cast_place =
+ Place::from(local_decls.push(LocalDecl::new(src_cast_ty, span)));
+
+ let src_cast = Statement {
+ source_info,
+ kind: StatementKind::Assign(box (
+ src_cast_place,
+ Rvalue::Cast(CastKind::PtrToPtr, Operand::Copy(src), src_cast_ty),
+ )),
+ };
+
+ let deinit_old =
+ Statement { source_info, kind: StatementKind::Deinit(box dst) };
+
+ let copy_bytes = Statement {
+ source_info,
+ kind: StatementKind::Intrinsic(
+ box NonDivergingIntrinsic::CopyNonOverlapping(CopyNonOverlapping {
+ src: Operand::Copy(src_cast_place),
+ dst: Operand::Copy(dst_cast_place),
+ count: Operand::Copy(size_place),
+ }),
+ ),
+ };
+
+ let store_dead = Statement {
+ source_info,
+ kind: StatementKind::StorageDead(size_array_local),
+ };
+ let iter = [
+ store_live,
+ const_assign,
+ store_discr,
+ cast_discr,
+ store_size,
+ dst_ptr,
+ dst_cast,
+ src_ptr,
+ src_cast,
+ deinit_old,
+ copy_bytes,
+ store_dead,
+ ]
+ .into_iter();
+
+ st.make_nop();
+ Some(iter)
+ } else {
+ None
+ }
+ });
+ }
+ }
+}
diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs
index 20b7fdcfe..cdd28ae0c 100644
--- a/compiler/rustc_mir_transform/src/lib.rs
+++ b/compiler/rustc_mir_transform/src/lib.rs
@@ -1,6 +1,7 @@
#![allow(rustc::potential_query_instability)]
#![feature(box_patterns)]
#![feature(drain_filter)]
+#![feature(box_syntax)]
#![feature(let_chains)]
#![feature(map_try_insert)]
#![feature(min_specialization)]
@@ -23,6 +24,7 @@ use rustc_const_eval::util;
use rustc_data_structures::fx::FxIndexSet;
use rustc_data_structures::steal::Steal;
use rustc_hir as hir;
+use rustc_hir::def::DefKind;
use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_hir::intravisit::{self, Visitor};
use rustc_index::vec::IndexVec;
@@ -33,7 +35,7 @@ use rustc_middle::mir::{
TerminatorKind,
};
use rustc_middle::ty::query::Providers;
-use rustc_middle::ty::{self, TyCtxt, TypeVisitable};
+use rustc_middle::ty::{self, TyCtxt, TypeVisitableExt};
use rustc_span::sym;
#[macro_use]
@@ -54,10 +56,11 @@ mod const_debuginfo;
mod const_goto;
mod const_prop;
mod const_prop_lint;
+mod copy_prop;
mod coverage;
+mod ctfe_limit;
mod dataflow_const_prop;
mod dead_store_elimination;
-mod deaggregator;
mod deduce_param_attrs;
mod deduplicate_blocks;
mod deref_separator;
@@ -71,6 +74,7 @@ mod function_item_references;
mod generator;
mod inline;
mod instcombine;
+mod large_enums;
mod lower_intrinsics;
mod lower_slice_len;
mod match_branches;
@@ -86,11 +90,11 @@ mod required_consts;
mod reveal_all;
mod separate_const_switch;
mod shim;
+mod ssa;
// This pass is public to allow external drivers to perform MIR cleanup
pub mod simplify;
mod simplify_branches;
mod simplify_comparison_integral;
-mod simplify_try;
mod sroa;
mod uninhabited_enum_branching;
mod unreachable_prop;
@@ -102,7 +106,6 @@ use rustc_mir_dataflow::rustc_peek;
pub fn provide(providers: &mut Providers) {
check_unsafety::provide(providers);
- check_packed_ref::provide(providers);
coverage::query::provide(providers);
ffi_unwind_calls::provide(providers);
shim::provide(providers);
@@ -124,6 +127,7 @@ pub fn provide(providers: &mut Providers) {
mir_drops_elaborated_and_const_checked,
mir_for_ctfe,
mir_for_ctfe_of_const_arg,
+ mir_generator_witnesses: generator::mir_generator_witnesses,
optimized_mir,
is_mir_available,
is_ctfe_mir_available: |tcx, did| is_mir_available(tcx, did),
@@ -188,7 +192,7 @@ fn remap_mir_for_const_eval_select<'tcx>(
let arguments = (0..num_args).map(|x| {
let mut place_elems = place_elems.to_vec();
place_elems.push(ProjectionElem::Field(x.into(), fields[x]));
- let projection = tcx.intern_place_elems(&place_elems);
+ let projection = tcx.mk_place_elems(&place_elems);
let place = Place {
local: place.local,
projection,
@@ -244,7 +248,7 @@ fn mir_const_qualif(tcx: TyCtxt<'_>, def: ty::WithOptConstParam<LocalDefId>) ->
// N.B., this `borrow()` is guaranteed to be valid (i.e., the value
// cannot yet be stolen), because `mir_promoted()`, which steals
- // from `mir_const(), forces this query to execute before
+ // from `mir_const()`, forces this query to execute before
// performing the steal.
let body = &tcx.mir_const(def).borrow();
@@ -410,6 +414,8 @@ fn inner_mir_for_ctfe(tcx: TyCtxt<'_>, def: ty::WithOptConstParam<LocalDefId>) -
}
}
+ pm::run_passes(tcx, &mut body, &[&ctfe_limit::CtfeLimit], None);
+
debug_assert!(!body.has_free_regions(), "Free regions in MIR for CTFE");
body
@@ -426,6 +432,11 @@ fn mir_drops_elaborated_and_const_checked(
return tcx.mir_drops_elaborated_and_const_checked(def);
}
+ if tcx.sess.opts.unstable_opts.drop_tracking_mir
+ && let DefKind::Generator = tcx.def_kind(def.did)
+ {
+ tcx.ensure().mir_generator_witnesses(def.did);
+ }
let mir_borrowck = tcx.mir_borrowck_opt_const_arg(def);
let is_fn_like = tcx.def_kind(def.did).is_fn_like();
@@ -513,9 +524,6 @@ fn run_runtime_lowering_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
&elaborate_box_derefs::ElaborateBoxDerefs,
&generator::StateTransform,
&add_retag::AddRetag,
- // Deaggregator is necessary for const prop. We may want to consider implementing
- // CTFE support for aggregates.
- &deaggregator::Deaggregator,
&Lint(const_prop_lint::ConstProp),
];
pm::run_passes_no_validate(tcx, body, passes, Some(MirPhase::Runtime(RuntimePhase::Initial)));
@@ -541,13 +549,13 @@ fn run_optimization_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
&[
&reveal_all::RevealAll, // has to be done before inlining, since inlined code is in RevealAll mode.
&lower_slice_len::LowerSliceLenCalls, // has to be done before inlining, otherwise actual call will be almost always inlined. Also simple, so can just do first
- &normalize_array_len::NormalizeArrayLen, // has to run after `slice::len` lowering
&unreachable_prop::UnreachablePropagation,
&uninhabited_enum_branching::UninhabitedEnumBranching,
&o1(simplify::SimplifyCfg::new("after-uninhabited-enum-branching")),
&inline::Inline,
&remove_storage_markers::RemoveStorageMarkers,
&remove_zsts::RemoveZsts,
+ &normalize_array_len::NormalizeArrayLen, // has to run after `slice::len` lowering
&const_goto::ConstGoto,
&remove_unneeded_drops::RemoveUnneededDrops,
&sroa::ScalarReplacementOfAggregates,
@@ -557,6 +565,7 @@ fn run_optimization_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
&instcombine::InstCombine,
&separate_const_switch::SeparateConstSwitch,
&simplify::SimplifyLocals::new("before-const-prop"),
+ &copy_prop::CopyProp,
//
// FIXME(#70073): This pass is responsible for both optimization as well as some lints.
&const_prop::ConstProp,
@@ -567,8 +576,6 @@ fn run_optimization_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
&o1(simplify_branches::SimplifyConstCondition::new("after-const-prop")),
&early_otherwise_branch::EarlyOtherwiseBranch,
&simplify_comparison_integral::SimplifyComparisonIntegral,
- &simplify_try::SimplifyArmIdentity,
- &simplify_try::SimplifyBranchSame,
&dead_store_elimination::DeadStoreElimination,
&dest_prop::DestinationPropagation,
&o1(simplify_branches::SimplifyConstCondition::new("final")),
@@ -578,6 +585,7 @@ fn run_optimization_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
&simplify::SimplifyLocals::new("final"),
&multiple_return_terminators::MultipleReturnTerminators,
&deduplicate_blocks::DeduplicateBlocks,
+ &large_enums::EnumSizeOpt { discrepancy: 128 },
// Some cleanup necessary at least for LLVM and potentially other codegen backends.
&add_call_guards::CriticalCallEdges,
// Dump the end result for testing and debugging purposes.
diff --git a/compiler/rustc_mir_transform/src/lower_intrinsics.rs b/compiler/rustc_mir_transform/src/lower_intrinsics.rs
index 9892580e6..f596cc180 100644
--- a/compiler/rustc_mir_transform/src/lower_intrinsics.rs
+++ b/compiler/rustc_mir_transform/src/lower_intrinsics.rs
@@ -107,9 +107,29 @@ impl<'tcx> MirPass<'tcx> for LowerIntrinsics {
}
}
sym::add_with_overflow | sym::sub_with_overflow | sym::mul_with_overflow => {
- // The checked binary operations are not suitable target for lowering here,
- // since their semantics depend on the value of overflow-checks flag used
- // during codegen. Issue #35310.
+ if let Some(target) = *target {
+ let lhs;
+ let rhs;
+ {
+ let mut args = args.drain(..);
+ lhs = args.next().unwrap();
+ rhs = args.next().unwrap();
+ }
+ let bin_op = match intrinsic_name {
+ sym::add_with_overflow => BinOp::Add,
+ sym::sub_with_overflow => BinOp::Sub,
+ sym::mul_with_overflow => BinOp::Mul,
+ _ => bug!("unexpected intrinsic"),
+ };
+ block.statements.push(Statement {
+ source_info: terminator.source_info,
+ kind: StatementKind::Assign(Box::new((
+ *destination,
+ Rvalue::CheckedBinaryOp(bin_op, Box::new((lhs, rhs))),
+ ))),
+ });
+ terminator.kind = TerminatorKind::Goto { target };
+ }
}
sym::size_of | sym::min_align_of => {
if let Some(target) = *target {
diff --git a/compiler/rustc_mir_transform/src/lower_slice_len.rs b/compiler/rustc_mir_transform/src/lower_slice_len.rs
index 2f02d00ec..c6e7468aa 100644
--- a/compiler/rustc_mir_transform/src/lower_slice_len.rs
+++ b/compiler/rustc_mir_transform/src/lower_slice_len.rs
@@ -68,8 +68,11 @@ fn lower_slice_len_call<'tcx>(
ty::FnDef(fn_def_id, _) if fn_def_id == &slice_len_fn_item_def_id => {
// perform modifications
// from something like `_5 = core::slice::<impl [u8]>::len(move _6) -> bb1`
- // into `_5 = Len(*_6)
+ // into:
+ // ```
+ // _5 = Len(*_6)
// goto bb1
+ // ```
// make new RValue for Len
let deref_arg = tcx.mk_place_deref(arg);
diff --git a/compiler/rustc_mir_transform/src/normalize_array_len.rs b/compiler/rustc_mir_transform/src/normalize_array_len.rs
index 1708b287e..b36c8a0bd 100644
--- a/compiler/rustc_mir_transform/src/normalize_array_len.rs
+++ b/compiler/rustc_mir_transform/src/normalize_array_len.rs
@@ -1,288 +1,104 @@
//! 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::ssa::SsaLocals;
use crate::MirPass;
-use rustc_data_structures::fx::FxIndexMap;
-use rustc_data_structures::intern::Interned;
-use rustc_index::bit_set::BitSet;
use rustc_index::vec::IndexVec;
+use rustc_middle::mir::visit::*;
use rustc_middle::mir::*;
-use rustc_middle::ty::{self, ReErased, Region, TyCtxt};
-
-const MAX_NUM_BLOCKS: usize = 800;
-const MAX_NUM_LOCALS: usize = 3000;
+use rustc_middle::ty::{self, TyCtxt};
+use rustc_mir_dataflow::impls::borrowed_locals;
pub struct NormalizeArrayLen;
impl<'tcx> MirPass<'tcx> for NormalizeArrayLen {
fn is_enabled(&self, sess: &rustc_session::Session) -> bool {
- // See #105929
- sess.mir_opt_level() >= 4 && sess.opts.unstable_opts.unsound_mir_opts
+ sess.mir_opt_level() >= 3
}
+ #[instrument(level = "trace", skip(self, tcx, body))]
fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
- // 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;
- }
+ debug!(def_id = ?body.source.def_id());
normalize_array_len_calls(tcx, body)
}
}
-pub fn normalize_array_len_calls<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
- // We don't ever touch terminators, so no need to invalidate the CFG cache
- let basic_blocks = body.basic_blocks.as_mut_preserves_cfg();
- let local_decls = &mut body.local_decls;
+fn normalize_array_len_calls<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
+ let param_env = tcx.param_env_reveal_all_normalized(body.source.def_id());
+ let borrowed_locals = borrowed_locals(body);
+ let ssa = SsaLocals::new(tcx, param_env, body, &borrowed_locals);
- // 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();
- }
-}
+ let slice_lengths = compute_slice_length(tcx, &ssa, body);
+ debug!(?slice_lengths);
-struct Patcher<'a, 'tcx> {
- tcx: TyCtxt<'tcx>,
- patches_scratchpad: &'a FxIndexMap<usize, usize>,
- replacements_scratchpad: &'a mut FxIndexMap<usize, Local>,
- local_decls: &'a mut IndexVec<Local, LocalDecl<'tcx>>,
- statement_idx: usize,
+ Replacer { tcx, slice_lengths }.visit_body_preserves_cfg(body);
}
-impl<'tcx> Patcher<'_, 'tcx> {
- fn patch_expand_statement(
- &mut self,
- statement: &mut Statement<'tcx>,
- ) -> Option<std::vec::IntoIter<Statement<'tcx>>> {
- 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::new((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")
+fn compute_slice_length<'tcx>(
+ tcx: TyCtxt<'tcx>,
+ ssa: &SsaLocals,
+ body: &Body<'tcx>,
+) -> IndexVec<Local, Option<ty::Const<'tcx>>> {
+ let mut slice_lengths = IndexVec::from_elem(None, &body.local_decls);
+
+ for (local, rvalue) in ssa.assignments(body) {
+ match rvalue {
+ Rvalue::Cast(
+ CastKind::Pointer(ty::adjustment::PointerCast::Unsize),
+ operand,
+ cast_ty,
+ ) => {
+ let operand_ty = operand.ty(body, tcx);
+ debug!(?operand_ty);
+ if let Some(operand_ty) = operand_ty.builtin_deref(true)
+ && let ty::Array(_, len) = operand_ty.ty.kind()
+ && let Some(cast_ty) = cast_ty.builtin_deref(true)
+ && let ty::Slice(..) = cast_ty.ty.kind()
+ {
+ slice_lengths[local] = Some(*len);
}
}
-
- 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::new((*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();
+ // The length information is stored in the fat pointer, so we treat `operand` as a value.
+ Rvalue::Use(operand) => {
+ if let Some(rhs) = operand.place() && let Some(rhs) = rhs.as_local() {
+ slice_lengths[local] = slice_lengths[rhs];
}
- _ => {
- unreachable!("it's a bug in the implementation")
+ }
+ // The length information is stored in the fat pointer.
+ // Reborrowing copies length information from one pointer to the other.
+ Rvalue::Ref(_, _, rhs) | Rvalue::AddressOf(_, rhs) => {
+ if let [PlaceElem::Deref] = rhs.projection[..] {
+ slice_lengths[local] = slice_lengths[rhs.local];
}
}
-
- self.statement_idx += 1;
-
- Some(statements.into_iter())
- } else {
- self.statement_idx += 1;
- None
+ _ => {}
}
}
+
+ slice_lengths
}
-fn normalize_array_len_call<'tcx>(
+struct Replacer<'tcx> {
tcx: TyCtxt<'tcx>,
- block: &mut BasicBlockData<'tcx>,
- local_decls: &mut IndexVec<Local, LocalDecl<'tcx>>,
- interesting_locals: &BitSet<Local>,
- state: &mut FxIndexMap<Local, usize>,
- patches_scratchpad: &mut FxIndexMap<usize, usize>,
- replacements_scratchpad: &mut FxIndexMap<usize, Local>,
-) {
- 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 Some(local) = place.as_local() else { return };
- match operand {
- Operand::Copy(place) | Operand::Move(place) => {
- let Some(operand_local) = place.local_or_deref_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(
- Region(Interned(ReErased, _)),
- operand_ty,
- Mutability::Not,
- ),
- ty::Ref(
- Region(Interned(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 Some(local) = place.local_or_deref_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);
- }
- }
- }
- _ => {}
- }
- }
+ slice_lengths: IndexVec<Local, Option<ty::Const<'tcx>>>,
+}
- let mut patcher = Patcher {
- tcx,
- patches_scratchpad: &*patches_scratchpad,
- replacements_scratchpad,
- local_decls,
- statement_idx: 0,
- };
+impl<'tcx> MutVisitor<'tcx> for Replacer<'tcx> {
+ fn tcx(&self) -> TyCtxt<'tcx> {
+ self.tcx
+ }
- block.expand_statements(|st| patcher.patch_expand_statement(st));
+ fn visit_rvalue(&mut self, rvalue: &mut Rvalue<'tcx>, loc: Location) {
+ if let Rvalue::Len(place) = rvalue
+ && let [PlaceElem::Deref] = &place.projection[..]
+ && let Some(len) = self.slice_lengths[place.local]
+ {
+ *rvalue = Rvalue::Use(Operand::Constant(Box::new(Constant {
+ span: rustc_span::DUMMY_SP,
+ user_ty: None,
+ literal: ConstantKind::from_const(len, self.tcx),
+ })));
+ }
+ self.super_rvalue(rvalue, loc);
+ }
}
diff --git a/compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs b/compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs
index f1bbf2ea7..e3a03aa08 100644
--- a/compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs
+++ b/compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs
@@ -35,6 +35,7 @@ impl RemoveNoopLandingPads {
| StatementKind::StorageDead(_)
| StatementKind::AscribeUserType(..)
| StatementKind::Coverage(..)
+ | StatementKind::ConstEvalCounter
| StatementKind::Nop => {
// These are all noops in a landing pad
}
diff --git a/compiler/rustc_mir_transform/src/remove_zsts.rs b/compiler/rustc_mir_transform/src/remove_zsts.rs
index 6cabef92d..1becfddb2 100644
--- a/compiler/rustc_mir_transform/src/remove_zsts.rs
+++ b/compiler/rustc_mir_transform/src/remove_zsts.rs
@@ -13,7 +13,7 @@ impl<'tcx> MirPass<'tcx> for RemoveZsts {
fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
// Avoid query cycles (generators require optimized MIR for layout).
- if tcx.type_of(body.source.def_id()).is_generator() {
+ if tcx.type_of(body.source.def_id()).subst_identity().is_generator() {
return;
}
let param_env = tcx.param_env(body.source.def_id());
diff --git a/compiler/rustc_mir_transform/src/separate_const_switch.rs b/compiler/rustc_mir_transform/src/separate_const_switch.rs
index 2f116aaa9..a24d2d34d 100644
--- a/compiler/rustc_mir_transform/src/separate_const_switch.rs
+++ b/compiler/rustc_mir_transform/src/separate_const_switch.rs
@@ -250,6 +250,7 @@ fn is_likely_const<'tcx>(mut tracked_place: Place<'tcx>, block: &BasicBlockData<
| StatementKind::Coverage(_)
| StatementKind::StorageDead(_)
| StatementKind::Intrinsic(_)
+ | StatementKind::ConstEvalCounter
| StatementKind::Nop => {}
}
}
@@ -318,6 +319,7 @@ fn find_determining_place<'tcx>(
| StatementKind::AscribeUserType(_, _)
| StatementKind::Coverage(_)
| StatementKind::Intrinsic(_)
+ | StatementKind::ConstEvalCounter
| StatementKind::Nop => {}
// If the discriminant is set, it is always set
diff --git a/compiler/rustc_mir_transform/src/shim.rs b/compiler/rustc_mir_transform/src/shim.rs
index dace540fa..ebe63d6cb 100644
--- a/compiler/rustc_mir_transform/src/shim.rs
+++ b/compiler/rustc_mir_transform/src/shim.rs
@@ -15,7 +15,6 @@ use rustc_target::spec::abi::Abi;
use std::fmt;
use std::iter;
-use crate::util::expand_aggregate;
use crate::{
abort_unwinding_calls, add_call_guards, add_moves_for_packed_drops, deref_separator,
pass_manager as pm, remove_noop_landing_pads, simplify,
@@ -148,11 +147,11 @@ fn build_drop_shim<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, ty: Option<Ty<'tcx>>)
assert!(!matches!(ty, Some(ty) if ty.is_generator()));
let substs = if let Some(ty) = ty {
- tcx.intern_substs(&[ty.into()])
+ tcx.mk_substs(&[ty.into()])
} else {
InternalSubsts::identity_for_item(tcx, def_id)
};
- let sig = tcx.bound_fn_sig(def_id).subst(tcx, substs);
+ let sig = tcx.fn_sig(def_id).subst(tcx, substs);
let sig = tcx.erase_late_bound_regions(sig);
let span = tcx.def_span(def_id);
@@ -363,7 +362,7 @@ impl<'tcx> CloneShimBuilder<'tcx> {
// we must subst the self_ty because it's
// otherwise going to be TySelf and we can't index
// or access fields of a Place of type TySelf.
- let sig = tcx.bound_fn_sig(def_id).subst(tcx, &[self_ty.into()]);
+ let sig = tcx.fn_sig(def_id).subst(tcx, &[self_ty.into()]);
let sig = tcx.erase_late_bound_regions(sig);
let span = tcx.def_span(def_id);
@@ -427,7 +426,7 @@ impl<'tcx> CloneShimBuilder<'tcx> {
fn make_place(&mut self, mutability: Mutability, ty: Ty<'tcx>) -> Place<'tcx> {
let span = self.span;
let mut local = LocalDecl::new(ty, span);
- if mutability == Mutability::Not {
+ if mutability.is_not() {
local = local.immutable();
}
Place::from(self.local_decls.push(local))
@@ -598,7 +597,7 @@ fn build_call_shim<'tcx>(
let untuple_args = sig.inputs();
// Create substitutions for the `Self` and `Args` generic parameters of the shim body.
- let arg_tup = tcx.mk_tup(untuple_args.iter());
+ let arg_tup = tcx.mk_tup(untuple_args);
(Some([ty.into(), arg_tup.into()]), Some(untuple_args))
} else {
@@ -606,7 +605,7 @@ fn build_call_shim<'tcx>(
};
let def_id = instance.def_id();
- let sig = tcx.bound_fn_sig(def_id);
+ let sig = tcx.fn_sig(def_id);
let sig = sig.map_bound(|sig| tcx.erase_late_bound_regions(sig));
assert_eq!(sig_substs.is_some(), !instance.has_polymorphic_mir_body());
@@ -633,7 +632,7 @@ fn build_call_shim<'tcx>(
Adjustment::Deref => tcx.mk_imm_ptr(fnty),
Adjustment::RefMut => tcx.mk_mut_ptr(fnty),
};
- sig.inputs_and_output = tcx.intern_type_list(&inputs_and_output);
+ sig.inputs_and_output = tcx.mk_type_list(&inputs_and_output);
}
// FIXME(eddyb) avoid having this snippet both here and in
@@ -644,7 +643,7 @@ fn build_call_shim<'tcx>(
let self_arg = &mut inputs_and_output[0];
debug_assert!(tcx.generics_of(def_id).has_self && *self_arg == tcx.types.self_param);
*self_arg = tcx.mk_mut_ptr(*self_arg);
- sig.inputs_and_output = tcx.intern_type_list(&inputs_and_output);
+ sig.inputs_and_output = tcx.mk_type_list(&inputs_and_output);
}
let span = tcx.def_span(def_id);
@@ -693,7 +692,7 @@ fn build_call_shim<'tcx>(
// `FnDef` call with optional receiver.
CallKind::Direct(def_id) => {
- let ty = tcx.type_of(def_id);
+ let ty = tcx.type_of(def_id).subst_identity();
(
Operand::Constant(Box::new(Constant {
span,
@@ -798,7 +797,11 @@ pub fn build_adt_ctor(tcx: TyCtxt<'_>, ctor_id: DefId) -> Body<'_> {
let param_env = tcx.param_env(ctor_id);
// Normalize the sig.
- let sig = tcx.fn_sig(ctor_id).no_bound_vars().expect("LBR in ADT constructor signature");
+ let sig = tcx
+ .fn_sig(ctor_id)
+ .subst_identity()
+ .no_bound_vars()
+ .expect("LBR in ADT constructor signature");
let sig = tcx.normalize_erasing_regions(param_env, sig);
let ty::Adt(adt_def, substs) = sig.output().kind() else {
@@ -827,19 +830,23 @@ pub fn build_adt_ctor(tcx: TyCtxt<'_>, ctor_id: DefId) -> Body<'_> {
// return;
debug!("build_ctor: variant_index={:?}", variant_index);
- let statements = expand_aggregate(
- Place::return_place(),
- adt_def.variant(variant_index).fields.iter().enumerate().map(|(idx, field_def)| {
- (Operand::Move(Place::from(Local::new(idx + 1))), field_def.ty(tcx, substs))
- }),
- AggregateKind::Adt(adt_def.did(), variant_index, substs, None, None),
+ let kind = AggregateKind::Adt(adt_def.did(), variant_index, substs, None, None);
+ let variant = adt_def.variant(variant_index);
+ let statement = Statement {
+ kind: StatementKind::Assign(Box::new((
+ Place::return_place(),
+ Rvalue::Aggregate(
+ Box::new(kind),
+ (0..variant.fields.len())
+ .map(|idx| Operand::Move(Place::from(Local::new(idx + 1))))
+ .collect(),
+ ),
+ ))),
source_info,
- tcx,
- )
- .collect();
+ };
let start_block = BasicBlockData {
- statements,
+ statements: vec![statement],
terminator: Some(Terminator { source_info, kind: TerminatorKind::Return }),
is_cleanup: false,
};
diff --git a/compiler/rustc_mir_transform/src/simplify.rs b/compiler/rustc_mir_transform/src/simplify.rs
index 8f6abe7a9..9ef55c558 100644
--- a/compiler/rustc_mir_transform/src/simplify.rs
+++ b/compiler/rustc_mir_transform/src/simplify.rs
@@ -404,6 +404,18 @@ impl<'tcx> MirPass<'tcx> for SimplifyLocals {
}
}
+pub fn remove_unused_definitions<'tcx>(body: &mut Body<'tcx>) {
+ // First, we're going to get a count of *actual* uses for every `Local`.
+ let mut used_locals = UsedLocals::new(body);
+
+ // Next, we're going to remove any `Local` with zero actual uses. When we remove those
+ // `Locals`, we're also going to subtract any uses of other `Locals` from the `used_locals`
+ // count. For example, if we removed `_2 = discriminant(_1)`, then we'll subtract one from
+ // `use_counts[_1]`. That in turn might make `_1` unused, so we loop until we hit a
+ // fixedpoint where there are no more unused locals.
+ remove_unused_definitions_helper(&mut used_locals, body);
+}
+
pub fn simplify_locals<'tcx>(body: &mut Body<'tcx>, tcx: TyCtxt<'tcx>) {
// First, we're going to get a count of *actual* uses for every `Local`.
let mut used_locals = UsedLocals::new(body);
@@ -413,7 +425,7 @@ pub fn simplify_locals<'tcx>(body: &mut Body<'tcx>, tcx: TyCtxt<'tcx>) {
// count. For example, if we removed `_2 = discriminant(_1)`, then we'll subtract one from
// `use_counts[_1]`. That in turn might make `_1` unused, so we loop until we hit a
// fixedpoint where there are no more unused locals.
- remove_unused_definitions(&mut used_locals, body);
+ remove_unused_definitions_helper(&mut used_locals, body);
// Finally, we'll actually do the work of shrinking `body.local_decls` and remapping the `Local`s.
let map = make_local_map(&mut body.local_decls, &used_locals);
@@ -484,7 +496,7 @@ impl UsedLocals {
self.increment = false;
// The location of the statement is irrelevant.
- let location = Location { block: START_BLOCK, statement_index: 0 };
+ let location = Location::START;
self.visit_statement(statement, location);
}
@@ -517,7 +529,7 @@ impl<'tcx> Visitor<'tcx> for UsedLocals {
self.super_statement(statement, location);
}
- StatementKind::Nop => {}
+ StatementKind::ConstEvalCounter | StatementKind::Nop => {}
StatementKind::StorageLive(_local) | StatementKind::StorageDead(_local) => {}
@@ -548,7 +560,7 @@ impl<'tcx> Visitor<'tcx> for UsedLocals {
}
/// Removes unused definitions. Updates the used locals to reflect the changes made.
-fn remove_unused_definitions(used_locals: &mut UsedLocals, body: &mut Body<'_>) {
+fn remove_unused_definitions_helper(used_locals: &mut UsedLocals, body: &mut Body<'_>) {
// The use counts are updated as we remove the statements. A local might become unused
// during the retain operation, leading to a temporary inconsistency (storage statements or
// definitions referencing the local might remain). For correctness it is crucial that this
diff --git a/compiler/rustc_mir_transform/src/simplify_try.rs b/compiler/rustc_mir_transform/src/simplify_try.rs
deleted file mode 100644
index e4f3ace9a..000000000
--- a/compiler/rustc_mir_transform/src/simplify_try.rs
+++ /dev/null
@@ -1,822 +0,0 @@
-//! The general point of the optimizations provided here is to simplify something like:
-//!
-//! ```rust
-//! # fn foo<T, E>(x: Result<T, E>) -> Result<T, E> {
-//! match x {
-//! Ok(x) => Ok(x),
-//! Err(x) => Err(x)
-//! }
-//! # }
-//! ```
-//!
-//! into just `x`.
-
-use crate::{simplify, MirPass};
-use itertools::Itertools as _;
-use rustc_index::{bit_set::BitSet, vec::IndexVec};
-use rustc_middle::mir::visit::{NonUseContext, PlaceContext, Visitor};
-use rustc_middle::mir::*;
-use rustc_middle::ty::{self, List, Ty, TyCtxt};
-use rustc_target::abi::VariantIdx;
-use std::iter::{once, Enumerate, Peekable};
-use std::slice::Iter;
-
-/// Simplifies arms of form `Variant(x) => Variant(x)` to just a move.
-///
-/// This is done by transforming basic blocks where the statements match:
-///
-/// ```ignore (MIR)
-/// _LOCAL_TMP = ((_LOCAL_1 as Variant ).FIELD: TY );
-/// _TMP_2 = _LOCAL_TMP;
-/// ((_LOCAL_0 as Variant).FIELD: TY) = move _TMP_2;
-/// discriminant(_LOCAL_0) = VAR_IDX;
-/// ```
-///
-/// into:
-///
-/// ```ignore (MIR)
-/// _LOCAL_0 = move _LOCAL_1
-/// ```
-pub struct SimplifyArmIdentity;
-
-#[derive(Debug)]
-struct ArmIdentityInfo<'tcx> {
- /// Storage location for the variant's field
- local_temp_0: Local,
- /// Storage location holding the variant being read from
- local_1: Local,
- /// The variant field being read from
- vf_s0: VarField<'tcx>,
- /// Index of the statement which loads the variant being read
- get_variant_field_stmt: usize,
-
- /// Tracks each assignment to a temporary of the variant's field
- field_tmp_assignments: Vec<(Local, Local)>,
-
- /// Storage location holding the variant's field that was read from
- local_tmp_s1: Local,
- /// Storage location holding the enum that we are writing to
- local_0: Local,
- /// The variant field being written to
- vf_s1: VarField<'tcx>,
-
- /// Storage location that the discriminant is being written to
- set_discr_local: Local,
- /// The variant being written
- set_discr_var_idx: VariantIdx,
-
- /// Index of the statement that should be overwritten as a move
- stmt_to_overwrite: usize,
- /// SourceInfo for the new move
- source_info: SourceInfo,
-
- /// Indices of matching Storage{Live,Dead} statements encountered.
- /// (StorageLive index,, StorageDead index, Local)
- storage_stmts: Vec<(usize, usize, Local)>,
-
- /// The statements that should be removed (turned into nops)
- stmts_to_remove: Vec<usize>,
-
- /// Indices of debug variables that need to be adjusted to point to
- // `{local_0}.{dbg_projection}`.
- dbg_info_to_adjust: Vec<usize>,
-
- /// The projection used to rewrite debug info.
- dbg_projection: &'tcx List<PlaceElem<'tcx>>,
-}
-
-fn get_arm_identity_info<'a, 'tcx>(
- stmts: &'a [Statement<'tcx>],
- locals_count: usize,
- debug_info: &'a [VarDebugInfo<'tcx>],
-) -> Option<ArmIdentityInfo<'tcx>> {
- // This can't possibly match unless there are at least 3 statements in the block
- // so fail fast on tiny blocks.
- if stmts.len() < 3 {
- return None;
- }
-
- let mut tmp_assigns = Vec::new();
- let mut nop_stmts = Vec::new();
- let mut storage_stmts = Vec::new();
- let mut storage_live_stmts = Vec::new();
- let mut storage_dead_stmts = Vec::new();
-
- type StmtIter<'a, 'tcx> = Peekable<Enumerate<Iter<'a, Statement<'tcx>>>>;
-
- fn is_storage_stmt(stmt: &Statement<'_>) -> bool {
- matches!(stmt.kind, StatementKind::StorageLive(_) | StatementKind::StorageDead(_))
- }
-
- /// Eats consecutive Statements which match `test`, performing the specified `action` for each.
- /// The iterator `stmt_iter` is not advanced if none were matched.
- fn try_eat<'a, 'tcx>(
- stmt_iter: &mut StmtIter<'a, 'tcx>,
- test: impl Fn(&'a Statement<'tcx>) -> bool,
- mut action: impl FnMut(usize, &'a Statement<'tcx>),
- ) {
- while stmt_iter.peek().map_or(false, |(_, stmt)| test(stmt)) {
- let (idx, stmt) = stmt_iter.next().unwrap();
-
- action(idx, stmt);
- }
- }
-
- /// Eats consecutive `StorageLive` and `StorageDead` Statements.
- /// The iterator `stmt_iter` is not advanced if none were found.
- fn try_eat_storage_stmts(
- stmt_iter: &mut StmtIter<'_, '_>,
- storage_live_stmts: &mut Vec<(usize, Local)>,
- storage_dead_stmts: &mut Vec<(usize, Local)>,
- ) {
- try_eat(stmt_iter, is_storage_stmt, |idx, stmt| {
- if let StatementKind::StorageLive(l) = stmt.kind {
- storage_live_stmts.push((idx, l));
- } else if let StatementKind::StorageDead(l) = stmt.kind {
- storage_dead_stmts.push((idx, l));
- }
- })
- }
-
- fn is_tmp_storage_stmt(stmt: &Statement<'_>) -> bool {
- use rustc_middle::mir::StatementKind::Assign;
- if let Assign(box (place, Rvalue::Use(Operand::Copy(p) | Operand::Move(p)))) = &stmt.kind {
- place.as_local().is_some() && p.as_local().is_some()
- } else {
- false
- }
- }
-
- /// Eats consecutive `Assign` Statements.
- // The iterator `stmt_iter` is not advanced if none were found.
- fn try_eat_assign_tmp_stmts(
- stmt_iter: &mut StmtIter<'_, '_>,
- tmp_assigns: &mut Vec<(Local, Local)>,
- nop_stmts: &mut Vec<usize>,
- ) {
- try_eat(stmt_iter, is_tmp_storage_stmt, |idx, stmt| {
- use rustc_middle::mir::StatementKind::Assign;
- if let Assign(box (place, Rvalue::Use(Operand::Copy(p) | Operand::Move(p)))) =
- &stmt.kind
- {
- tmp_assigns.push((place.as_local().unwrap(), p.as_local().unwrap()));
- nop_stmts.push(idx);
- }
- })
- }
-
- fn find_storage_live_dead_stmts_for_local(
- local: Local,
- stmts: &[Statement<'_>],
- ) -> Option<(usize, usize)> {
- trace!("looking for {:?}", local);
- let mut storage_live_stmt = None;
- let mut storage_dead_stmt = None;
- for (idx, stmt) in stmts.iter().enumerate() {
- if stmt.kind == StatementKind::StorageLive(local) {
- storage_live_stmt = Some(idx);
- } else if stmt.kind == StatementKind::StorageDead(local) {
- storage_dead_stmt = Some(idx);
- }
- }
-
- Some((storage_live_stmt?, storage_dead_stmt.unwrap_or(usize::MAX)))
- }
-
- // Try to match the expected MIR structure with the basic block we're processing.
- // We want to see something that looks like:
- // ```
- // (StorageLive(_) | StorageDead(_));*
- // _LOCAL_INTO = ((_LOCAL_FROM as Variant).FIELD: TY);
- // (StorageLive(_) | StorageDead(_));*
- // (tmp_n+1 = tmp_n);*
- // (StorageLive(_) | StorageDead(_));*
- // (tmp_n+1 = tmp_n);*
- // ((LOCAL_FROM as Variant).FIELD: TY) = move tmp;
- // discriminant(LOCAL_FROM) = VariantIdx;
- // (StorageLive(_) | StorageDead(_));*
- // ```
- let mut stmt_iter = stmts.iter().enumerate().peekable();
-
- try_eat_storage_stmts(&mut stmt_iter, &mut storage_live_stmts, &mut storage_dead_stmts);
-
- let (get_variant_field_stmt, stmt) = stmt_iter.next()?;
- let (local_tmp_s0, local_1, vf_s0, dbg_projection) = match_get_variant_field(stmt)?;
-
- try_eat_storage_stmts(&mut stmt_iter, &mut storage_live_stmts, &mut storage_dead_stmts);
-
- try_eat_assign_tmp_stmts(&mut stmt_iter, &mut tmp_assigns, &mut nop_stmts);
-
- try_eat_storage_stmts(&mut stmt_iter, &mut storage_live_stmts, &mut storage_dead_stmts);
-
- try_eat_assign_tmp_stmts(&mut stmt_iter, &mut tmp_assigns, &mut nop_stmts);
-
- let (idx, stmt) = stmt_iter.next()?;
- let (local_tmp_s1, local_0, vf_s1) = match_set_variant_field(stmt)?;
- nop_stmts.push(idx);
-
- let (idx, stmt) = stmt_iter.next()?;
- let (set_discr_local, set_discr_var_idx) = match_set_discr(stmt)?;
- let discr_stmt_source_info = stmt.source_info;
- nop_stmts.push(idx);
-
- try_eat_storage_stmts(&mut stmt_iter, &mut storage_live_stmts, &mut storage_dead_stmts);
-
- for (live_idx, live_local) in storage_live_stmts {
- if let Some(i) = storage_dead_stmts.iter().rposition(|(_, l)| *l == live_local) {
- let (dead_idx, _) = storage_dead_stmts.swap_remove(i);
- storage_stmts.push((live_idx, dead_idx, live_local));
-
- if live_local == local_tmp_s0 {
- nop_stmts.push(get_variant_field_stmt);
- }
- }
- }
- // We sort primitive usize here so we can use unstable sort
- nop_stmts.sort_unstable();
-
- // Use one of the statements we're going to discard between the point
- // where the storage location for the variant field becomes live and
- // is killed.
- let (live_idx, dead_idx) = find_storage_live_dead_stmts_for_local(local_tmp_s0, stmts)?;
- let stmt_to_overwrite =
- nop_stmts.iter().find(|stmt_idx| live_idx < **stmt_idx && **stmt_idx < dead_idx);
-
- let mut tmp_assigned_vars = BitSet::new_empty(locals_count);
- for (l, r) in &tmp_assigns {
- tmp_assigned_vars.insert(*l);
- tmp_assigned_vars.insert(*r);
- }
-
- let dbg_info_to_adjust: Vec<_> = debug_info
- .iter()
- .enumerate()
- .filter_map(|(i, var_info)| {
- if let VarDebugInfoContents::Place(p) = var_info.value {
- if tmp_assigned_vars.contains(p.local) {
- return Some(i);
- }
- }
-
- None
- })
- .collect();
-
- Some(ArmIdentityInfo {
- local_temp_0: local_tmp_s0,
- local_1,
- vf_s0,
- get_variant_field_stmt,
- field_tmp_assignments: tmp_assigns,
- local_tmp_s1,
- local_0,
- vf_s1,
- set_discr_local,
- set_discr_var_idx,
- stmt_to_overwrite: *stmt_to_overwrite?,
- source_info: discr_stmt_source_info,
- storage_stmts,
- stmts_to_remove: nop_stmts,
- dbg_info_to_adjust,
- dbg_projection,
- })
-}
-
-fn optimization_applies<'tcx>(
- opt_info: &ArmIdentityInfo<'tcx>,
- local_decls: &IndexVec<Local, LocalDecl<'tcx>>,
- local_uses: &IndexVec<Local, usize>,
- var_debug_info: &[VarDebugInfo<'tcx>],
-) -> bool {
- trace!("testing if optimization applies...");
-
- // FIXME(wesleywiser): possibly relax this restriction?
- if opt_info.local_0 == opt_info.local_1 {
- trace!("NO: moving into ourselves");
- return false;
- } else if opt_info.vf_s0 != opt_info.vf_s1 {
- trace!("NO: the field-and-variant information do not match");
- return false;
- } else if local_decls[opt_info.local_0].ty != local_decls[opt_info.local_1].ty {
- // FIXME(Centril,oli-obk): possibly relax to same layout?
- trace!("NO: source and target locals have different types");
- return false;
- } else if (opt_info.local_0, opt_info.vf_s0.var_idx)
- != (opt_info.set_discr_local, opt_info.set_discr_var_idx)
- {
- trace!("NO: the discriminants do not match");
- return false;
- }
-
- // Verify the assignment chain consists of the form b = a; c = b; d = c; etc...
- if opt_info.field_tmp_assignments.is_empty() {
- trace!("NO: no assignments found");
- return false;
- }
- let mut last_assigned_to = opt_info.field_tmp_assignments[0].1;
- let source_local = last_assigned_to;
- for (l, r) in &opt_info.field_tmp_assignments {
- if *r != last_assigned_to {
- trace!("NO: found unexpected assignment {:?} = {:?}", l, r);
- return false;
- }
-
- last_assigned_to = *l;
- }
-
- // Check that the first and last used locals are only used twice
- // since they are of the form:
- //
- // ```
- // _first = ((_x as Variant).n: ty);
- // _n = _first;
- // ...
- // ((_y as Variant).n: ty) = _n;
- // discriminant(_y) = z;
- // ```
- for (l, r) in &opt_info.field_tmp_assignments {
- if local_uses[*l] != 2 {
- warn!("NO: FAILED assignment chain local {:?} was used more than twice", l);
- return false;
- } else if local_uses[*r] != 2 {
- warn!("NO: FAILED assignment chain local {:?} was used more than twice", r);
- return false;
- }
- }
-
- // Check that debug info only points to full Locals and not projections.
- for dbg_idx in &opt_info.dbg_info_to_adjust {
- let dbg_info = &var_debug_info[*dbg_idx];
- if let VarDebugInfoContents::Place(p) = dbg_info.value {
- if !p.projection.is_empty() {
- trace!("NO: debug info for {:?} had a projection {:?}", dbg_info.name, p);
- return false;
- }
- }
- }
-
- if source_local != opt_info.local_temp_0 {
- trace!(
- "NO: start of assignment chain does not match enum variant temp: {:?} != {:?}",
- source_local,
- opt_info.local_temp_0
- );
- return false;
- } else if last_assigned_to != opt_info.local_tmp_s1 {
- trace!(
- "NO: end of assignment chain does not match written enum temp: {:?} != {:?}",
- last_assigned_to,
- opt_info.local_tmp_s1
- );
- return false;
- }
-
- trace!("SUCCESS: optimization applies!");
- true
-}
-
-impl<'tcx> MirPass<'tcx> for SimplifyArmIdentity {
- fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
- // FIXME(77359): This optimization can result in unsoundness.
- if !tcx.sess.opts.unstable_opts.unsound_mir_opts {
- return;
- }
-
- let source = body.source;
- trace!("running SimplifyArmIdentity on {:?}", source);
-
- let local_uses = LocalUseCounter::get_local_uses(body);
- for bb in body.basic_blocks.as_mut() {
- if let Some(opt_info) =
- get_arm_identity_info(&bb.statements, body.local_decls.len(), &body.var_debug_info)
- {
- trace!("got opt_info = {:#?}", opt_info);
- if !optimization_applies(
- &opt_info,
- &body.local_decls,
- &local_uses,
- &body.var_debug_info,
- ) {
- debug!("optimization skipped for {:?}", source);
- continue;
- }
-
- // Also remove unused Storage{Live,Dead} statements which correspond
- // to temps used previously.
- for (live_idx, dead_idx, local) in &opt_info.storage_stmts {
- // The temporary that we've read the variant field into is scoped to this block,
- // so we can remove the assignment.
- if *local == opt_info.local_temp_0 {
- bb.statements[opt_info.get_variant_field_stmt].make_nop();
- }
-
- for (left, right) in &opt_info.field_tmp_assignments {
- if local == left || local == right {
- bb.statements[*live_idx].make_nop();
- bb.statements[*dead_idx].make_nop();
- }
- }
- }
-
- // Right shape; transform
- for stmt_idx in opt_info.stmts_to_remove {
- bb.statements[stmt_idx].make_nop();
- }
-
- let stmt = &mut bb.statements[opt_info.stmt_to_overwrite];
- stmt.source_info = opt_info.source_info;
- stmt.kind = StatementKind::Assign(Box::new((
- opt_info.local_0.into(),
- Rvalue::Use(Operand::Move(opt_info.local_1.into())),
- )));
-
- bb.statements.retain(|stmt| stmt.kind != StatementKind::Nop);
-
- // Fix the debug info to point to the right local
- for dbg_index in opt_info.dbg_info_to_adjust {
- let dbg_info = &mut body.var_debug_info[dbg_index];
- assert!(
- matches!(dbg_info.value, VarDebugInfoContents::Place(_)),
- "value was not a Place"
- );
- if let VarDebugInfoContents::Place(p) = &mut dbg_info.value {
- assert!(p.projection.is_empty());
- p.local = opt_info.local_0;
- p.projection = opt_info.dbg_projection;
- }
- }
-
- trace!("block is now {:?}", bb.statements);
- }
- }
- }
-}
-
-struct LocalUseCounter {
- local_uses: IndexVec<Local, usize>,
-}
-
-impl LocalUseCounter {
- fn get_local_uses(body: &Body<'_>) -> IndexVec<Local, usize> {
- let mut counter = LocalUseCounter { local_uses: IndexVec::from_elem(0, &body.local_decls) };
- counter.visit_body(body);
- counter.local_uses
- }
-}
-
-impl Visitor<'_> for LocalUseCounter {
- fn visit_local(&mut self, local: Local, context: PlaceContext, _location: Location) {
- if context.is_storage_marker()
- || context == PlaceContext::NonUse(NonUseContext::VarDebugInfo)
- {
- return;
- }
-
- self.local_uses[local] += 1;
- }
-}
-
-/// Match on:
-/// ```ignore (MIR)
-/// _LOCAL_INTO = ((_LOCAL_FROM as Variant).FIELD: TY);
-/// ```
-fn match_get_variant_field<'tcx>(
- stmt: &Statement<'tcx>,
-) -> Option<(Local, Local, VarField<'tcx>, &'tcx List<PlaceElem<'tcx>>)> {
- match &stmt.kind {
- StatementKind::Assign(box (
- place_into,
- Rvalue::Use(Operand::Copy(pf) | Operand::Move(pf)),
- )) => {
- let local_into = place_into.as_local()?;
- let (local_from, vf) = match_variant_field_place(*pf)?;
- Some((local_into, local_from, vf, pf.projection))
- }
- _ => None,
- }
-}
-
-/// Match on:
-/// ```ignore (MIR)
-/// ((_LOCAL_FROM as Variant).FIELD: TY) = move _LOCAL_INTO;
-/// ```
-fn match_set_variant_field<'tcx>(stmt: &Statement<'tcx>) -> Option<(Local, Local, VarField<'tcx>)> {
- match &stmt.kind {
- StatementKind::Assign(box (place_from, Rvalue::Use(Operand::Move(place_into)))) => {
- let local_into = place_into.as_local()?;
- let (local_from, vf) = match_variant_field_place(*place_from)?;
- Some((local_into, local_from, vf))
- }
- _ => None,
- }
-}
-
-/// Match on:
-/// ```ignore (MIR)
-/// discriminant(_LOCAL_TO_SET) = VAR_IDX;
-/// ```
-fn match_set_discr(stmt: &Statement<'_>) -> Option<(Local, VariantIdx)> {
- match &stmt.kind {
- StatementKind::SetDiscriminant { place, variant_index } => {
- Some((place.as_local()?, *variant_index))
- }
- _ => None,
- }
-}
-
-#[derive(PartialEq, Debug)]
-struct VarField<'tcx> {
- field: Field,
- field_ty: Ty<'tcx>,
- var_idx: VariantIdx,
-}
-
-/// Match on `((_LOCAL as Variant).FIELD: TY)`.
-fn match_variant_field_place(place: Place<'_>) -> Option<(Local, VarField<'_>)> {
- match place.as_ref() {
- PlaceRef {
- local,
- projection: &[ProjectionElem::Downcast(_, var_idx), ProjectionElem::Field(field, ty)],
- } => Some((local, VarField { field, field_ty: ty, var_idx })),
- _ => None,
- }
-}
-
-/// Simplifies `SwitchInt(_) -> [targets]`,
-/// where all the `targets` have the same form,
-/// into `goto -> target_first`.
-pub struct SimplifyBranchSame;
-
-impl<'tcx> MirPass<'tcx> for SimplifyBranchSame {
- fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
- // This optimization is disabled by default for now due to
- // soundness concerns; see issue #89485 and PR #89489.
- if !tcx.sess.opts.unstable_opts.unsound_mir_opts {
- return;
- }
-
- trace!("Running SimplifyBranchSame on {:?}", body.source);
- let finder = SimplifyBranchSameOptimizationFinder { body, tcx };
- let opts = finder.find();
-
- let did_remove_blocks = opts.len() > 0;
- for opt in opts.iter() {
- trace!("SUCCESS: Applying optimization {:?}", opt);
- // Replace `SwitchInt(..) -> [bb_first, ..];` with a `goto -> bb_first;`.
- body.basic_blocks_mut()[opt.bb_to_opt_terminator].terminator_mut().kind =
- TerminatorKind::Goto { target: opt.bb_to_goto };
- }
-
- if did_remove_blocks {
- // We have dead blocks now, so remove those.
- simplify::remove_dead_blocks(tcx, body);
- }
- }
-}
-
-#[derive(Debug)]
-struct SimplifyBranchSameOptimization {
- /// All basic blocks are equal so go to this one
- bb_to_goto: BasicBlock,
- /// Basic block where the terminator can be simplified to a goto
- bb_to_opt_terminator: BasicBlock,
-}
-
-struct SwitchTargetAndValue {
- target: BasicBlock,
- // None in case of the `otherwise` case
- value: Option<u128>,
-}
-
-struct SimplifyBranchSameOptimizationFinder<'a, 'tcx> {
- body: &'a Body<'tcx>,
- tcx: TyCtxt<'tcx>,
-}
-
-impl<'tcx> SimplifyBranchSameOptimizationFinder<'_, 'tcx> {
- fn find(&self) -> Vec<SimplifyBranchSameOptimization> {
- self.body
- .basic_blocks
- .iter_enumerated()
- .filter_map(|(bb_idx, bb)| {
- let (discr_switched_on, targets_and_values) = match &bb.terminator().kind {
- TerminatorKind::SwitchInt { targets, discr, .. } => {
- let targets_and_values: Vec<_> = targets.iter()
- .map(|(val, target)| SwitchTargetAndValue { target, value: Some(val) })
- .chain(once(SwitchTargetAndValue { target: targets.otherwise(), value: None }))
- .collect();
- (discr, targets_and_values)
- },
- _ => return None,
- };
-
- // find the adt that has its discriminant read
- // assuming this must be the last statement of the block
- let adt_matched_on = match &bb.statements.last()?.kind {
- StatementKind::Assign(box (place, rhs))
- if Some(*place) == discr_switched_on.place() =>
- {
- match rhs {
- Rvalue::Discriminant(adt_place) if adt_place.ty(self.body, self.tcx).ty.is_enum() => adt_place,
- _ => {
- trace!("NO: expected a discriminant read of an enum instead of: {:?}", rhs);
- return None;
- }
- }
- }
- other => {
- trace!("NO: expected an assignment of a discriminant read to a place. Found: {:?}", other);
- return None
- },
- };
-
- let mut iter_bbs_reachable = targets_and_values
- .iter()
- .map(|target_and_value| (target_and_value, &self.body.basic_blocks[target_and_value.target]))
- .filter(|(_, bb)| {
- // Reaching `unreachable` is UB so assume it doesn't happen.
- bb.terminator().kind != TerminatorKind::Unreachable
- })
- .peekable();
-
- let bb_first = iter_bbs_reachable.peek().map_or(&targets_and_values[0], |(idx, _)| *idx);
- let mut all_successors_equivalent = StatementEquality::TrivialEqual;
-
- // All successor basic blocks must be equal or contain statements that are pairwise considered equal.
- for ((target_and_value_l,bb_l), (target_and_value_r,bb_r)) in iter_bbs_reachable.tuple_windows() {
- let trivial_checks = bb_l.is_cleanup == bb_r.is_cleanup
- && bb_l.terminator().kind == bb_r.terminator().kind
- && bb_l.statements.len() == bb_r.statements.len();
- let statement_check = || {
- bb_l.statements.iter().zip(&bb_r.statements).try_fold(StatementEquality::TrivialEqual, |acc,(l,r)| {
- let stmt_equality = self.statement_equality(*adt_matched_on, &l, target_and_value_l, &r, target_and_value_r);
- if matches!(stmt_equality, StatementEquality::NotEqual) {
- // short circuit
- None
- } else {
- Some(acc.combine(&stmt_equality))
- }
- })
- .unwrap_or(StatementEquality::NotEqual)
- };
- if !trivial_checks {
- all_successors_equivalent = StatementEquality::NotEqual;
- break;
- }
- all_successors_equivalent = all_successors_equivalent.combine(&statement_check());
- };
-
- match all_successors_equivalent{
- StatementEquality::TrivialEqual => {
- // statements are trivially equal, so just take first
- trace!("Statements are trivially equal");
- Some(SimplifyBranchSameOptimization {
- bb_to_goto: bb_first.target,
- bb_to_opt_terminator: bb_idx,
- })
- }
- StatementEquality::ConsideredEqual(bb_to_choose) => {
- trace!("Statements are considered equal");
- Some(SimplifyBranchSameOptimization {
- bb_to_goto: bb_to_choose,
- bb_to_opt_terminator: bb_idx,
- })
- }
- StatementEquality::NotEqual => {
- trace!("NO: not all successors of basic block {:?} were equivalent", bb_idx);
- None
- }
- }
- })
- .collect()
- }
-
- /// Tests if two statements can be considered equal
- ///
- /// Statements can be trivially equal if the kinds match.
- /// But they can also be considered equal in the following case A:
- /// ```ignore (MIR)
- /// discriminant(_0) = 0; // bb1
- /// _0 = move _1; // bb2
- /// ```
- /// In this case the two statements are equal iff
- /// - `_0` is an enum where the variant index 0 is fieldless, and
- /// - bb1 was targeted by a switch where the discriminant of `_1` was switched on
- fn statement_equality(
- &self,
- adt_matched_on: Place<'tcx>,
- x: &Statement<'tcx>,
- x_target_and_value: &SwitchTargetAndValue,
- y: &Statement<'tcx>,
- y_target_and_value: &SwitchTargetAndValue,
- ) -> StatementEquality {
- let helper = |rhs: &Rvalue<'tcx>,
- place: &Place<'tcx>,
- variant_index: VariantIdx,
- switch_value: u128,
- side_to_choose| {
- let place_type = place.ty(self.body, self.tcx).ty;
- let adt = match *place_type.kind() {
- ty::Adt(adt, _) if adt.is_enum() => adt,
- _ => return StatementEquality::NotEqual,
- };
- // We need to make sure that the switch value that targets the bb with
- // SetDiscriminant is the same as the variant discriminant.
- let variant_discr = adt.discriminant_for_variant(self.tcx, variant_index).val;
- if variant_discr != switch_value {
- trace!(
- "NO: variant discriminant {} does not equal switch value {}",
- variant_discr,
- switch_value
- );
- return StatementEquality::NotEqual;
- }
- let variant_is_fieldless = adt.variant(variant_index).fields.is_empty();
- if !variant_is_fieldless {
- trace!("NO: variant {:?} was not fieldless", variant_index);
- return StatementEquality::NotEqual;
- }
-
- match rhs {
- Rvalue::Use(operand) if operand.place() == Some(adt_matched_on) => {
- StatementEquality::ConsideredEqual(side_to_choose)
- }
- _ => {
- trace!(
- "NO: RHS of assignment was {:?}, but expected it to match the adt being matched on in the switch, which is {:?}",
- rhs,
- adt_matched_on
- );
- StatementEquality::NotEqual
- }
- }
- };
- match (&x.kind, &y.kind) {
- // trivial case
- (x, y) if x == y => StatementEquality::TrivialEqual,
-
- // check for case A
- (
- StatementKind::Assign(box (_, rhs)),
- &StatementKind::SetDiscriminant { ref place, variant_index },
- ) if y_target_and_value.value.is_some() => {
- // choose basic block of x, as that has the assign
- helper(
- rhs,
- place,
- variant_index,
- y_target_and_value.value.unwrap(),
- x_target_and_value.target,
- )
- }
- (
- &StatementKind::SetDiscriminant { ref place, variant_index },
- &StatementKind::Assign(box (_, ref rhs)),
- ) if x_target_and_value.value.is_some() => {
- // choose basic block of y, as that has the assign
- helper(
- rhs,
- place,
- variant_index,
- x_target_and_value.value.unwrap(),
- y_target_and_value.target,
- )
- }
- _ => {
- trace!("NO: statements `{:?}` and `{:?}` not considered equal", x, y);
- StatementEquality::NotEqual
- }
- }
- }
-}
-
-#[derive(Copy, Clone, Eq, PartialEq)]
-enum StatementEquality {
- /// The two statements are trivially equal; same kind
- TrivialEqual,
- /// The two statements are considered equal, but may be of different kinds. The BasicBlock field is the basic block to jump to when performing the branch-same optimization.
- /// For example, `_0 = _1` and `discriminant(_0) = discriminant(0)` are considered equal if 0 is a fieldless variant of an enum. But we don't want to jump to the basic block with the SetDiscriminant, as that is not legal if _1 is not the 0 variant index
- ConsideredEqual(BasicBlock),
- /// The two statements are not equal
- NotEqual,
-}
-
-impl StatementEquality {
- fn combine(&self, other: &StatementEquality) -> StatementEquality {
- use StatementEquality::*;
- match (self, other) {
- (TrivialEqual, TrivialEqual) => TrivialEqual,
- (TrivialEqual, ConsideredEqual(b)) | (ConsideredEqual(b), TrivialEqual) => {
- ConsideredEqual(*b)
- }
- (ConsideredEqual(b1), ConsideredEqual(b2)) => {
- if b1 == b2 {
- ConsideredEqual(*b1)
- } else {
- NotEqual
- }
- }
- (_, NotEqual) | (NotEqual, _) => NotEqual,
- }
- }
-}
diff --git a/compiler/rustc_mir_transform/src/sroa.rs b/compiler/rustc_mir_transform/src/sroa.rs
index 42124f5a4..13168e9a2 100644
--- a/compiler/rustc_mir_transform/src/sroa.rs
+++ b/compiler/rustc_mir_transform/src/sroa.rs
@@ -1,10 +1,11 @@
use crate::MirPass;
-use rustc_data_structures::fx::{FxIndexMap, IndexEntry};
-use rustc_index::bit_set::BitSet;
+use rustc_index::bit_set::{BitSet, GrowableBitSet};
use rustc_index::vec::IndexVec;
+use rustc_middle::mir::patch::MirPatch;
use rustc_middle::mir::visit::*;
use rustc_middle::mir::*;
-use rustc_middle::ty::TyCtxt;
+use rustc_middle::ty::{Ty, TyCtxt};
+use rustc_mir_dataflow::value_analysis::{excluded_locals, iter_fields};
pub struct ScalarReplacementOfAggregates;
@@ -13,27 +14,43 @@ impl<'tcx> MirPass<'tcx> for ScalarReplacementOfAggregates {
sess.mir_opt_level() >= 3
}
+ #[instrument(level = "debug", skip(self, tcx, body))]
fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
- let escaping = escaping_locals(&*body);
- debug!(?escaping);
- let replacements = compute_flattening(tcx, body, escaping);
- debug!(?replacements);
- replace_flattened_locals(tcx, body, replacements);
+ debug!(def_id = ?body.source.def_id());
+ let mut excluded = excluded_locals(body);
+ loop {
+ debug!(?excluded);
+ let escaping = escaping_locals(&excluded, body);
+ debug!(?escaping);
+ let replacements = compute_flattening(tcx, body, escaping);
+ debug!(?replacements);
+ let all_dead_locals = replace_flattened_locals(tcx, body, replacements);
+ if !all_dead_locals.is_empty() {
+ excluded.union(&all_dead_locals);
+ excluded = {
+ let mut growable = GrowableBitSet::from(excluded);
+ growable.ensure(body.local_decls.len());
+ growable.into()
+ };
+ } else {
+ break;
+ }
+ }
}
}
/// Identify all locals that are not eligible for SROA.
///
/// There are 3 cases:
-/// - the aggegated local is used or passed to other code (function parameters and arguments);
+/// - the aggregated local is used or passed to other code (function parameters and arguments);
/// - the locals is a union or an enum;
/// - the local's address is taken, and thus the relative addresses of the fields are observable to
/// client code.
-fn escaping_locals(body: &Body<'_>) -> BitSet<Local> {
+fn escaping_locals(excluded: &BitSet<Local>, body: &Body<'_>) -> BitSet<Local> {
let mut set = BitSet::new_empty(body.local_decls.len());
set.insert_range(RETURN_PLACE..=Local::from_usize(body.arg_count));
for (local, decl) in body.local_decls().iter_enumerated() {
- if decl.ty.is_union() || decl.ty.is_enum() {
+ if decl.ty.is_union() || decl.ty.is_enum() || excluded.contains(local) {
set.insert(local);
}
}
@@ -58,41 +75,33 @@ fn escaping_locals(body: &Body<'_>) -> BitSet<Local> {
self.super_place(place, context, location);
}
- fn visit_rvalue(&mut self, rvalue: &Rvalue<'tcx>, location: Location) {
- if let Rvalue::AddressOf(.., place) | Rvalue::Ref(.., place) = rvalue {
- if !place.is_indirect() {
- // Raw pointers may be used to access anything inside the enclosing place.
- self.set.insert(place.local);
- return;
+ fn visit_assign(
+ &mut self,
+ lvalue: &Place<'tcx>,
+ rvalue: &Rvalue<'tcx>,
+ location: Location,
+ ) {
+ if lvalue.as_local().is_some() {
+ match rvalue {
+ // Aggregate assignments are expanded in run_pass.
+ Rvalue::Aggregate(..) | Rvalue::Use(..) => {
+ self.visit_rvalue(rvalue, location);
+ return;
+ }
+ _ => {}
}
}
- self.super_rvalue(rvalue, location)
+ self.super_assign(lvalue, rvalue, location)
}
fn visit_statement(&mut self, statement: &Statement<'tcx>, location: Location) {
- if let StatementKind::StorageLive(..)
- | StatementKind::StorageDead(..)
- | StatementKind::Deinit(..) = statement.kind
- {
+ match statement.kind {
// Storage statements are expanded in run_pass.
- return;
+ StatementKind::StorageLive(..)
+ | StatementKind::StorageDead(..)
+ | StatementKind::Deinit(..) => return,
+ _ => self.super_statement(statement, location),
}
- self.super_statement(statement, location)
- }
-
- fn visit_terminator(&mut self, terminator: &Terminator<'tcx>, location: Location) {
- // Drop implicitly calls `drop_in_place`, which takes a `&mut`.
- // This implies that `Drop` implicitly takes the address of the place.
- if let TerminatorKind::Drop { place, .. }
- | TerminatorKind::DropAndReplace { place, .. } = terminator.kind
- {
- if !place.is_indirect() {
- // Raw pointers may be used to access anything inside the enclosing place.
- self.set.insert(place.local);
- return;
- }
- }
- self.super_terminator(terminator, location);
}
// We ignore anything that happens in debuginfo, since we expand it using
@@ -103,7 +112,30 @@ fn escaping_locals(body: &Body<'_>) -> BitSet<Local> {
#[derive(Default, Debug)]
struct ReplacementMap<'tcx> {
- fields: FxIndexMap<PlaceRef<'tcx>, Local>,
+ /// Pre-computed list of all "new" locals for each "old" local. This is used to expand storage
+ /// and deinit statement and debuginfo.
+ fragments: IndexVec<Local, Option<IndexVec<Field, Option<(Ty<'tcx>, Local)>>>>,
+}
+
+impl<'tcx> ReplacementMap<'tcx> {
+ fn replace_place(&self, tcx: TyCtxt<'tcx>, place: PlaceRef<'tcx>) -> Option<Place<'tcx>> {
+ let &[PlaceElem::Field(f, _), ref rest @ ..] = place.projection else { return None; };
+ let fields = self.fragments[place.local].as_ref()?;
+ let (_, new_local) = fields[f]?;
+ Some(Place { local: new_local, projection: tcx.mk_place_elems(&rest) })
+ }
+
+ fn place_fragments(
+ &self,
+ place: Place<'tcx>,
+ ) -> Option<impl Iterator<Item = (Field, Ty<'tcx>, Local)> + '_> {
+ let local = place.as_local()?;
+ let fields = self.fragments[local].as_ref()?;
+ Some(fields.iter_enumerated().filter_map(|(field, &opt_ty_local)| {
+ let (ty, local) = opt_ty_local?;
+ Some((field, ty, local))
+ }))
+ }
}
/// Compute the replacement of flattened places into locals.
@@ -115,53 +147,25 @@ fn compute_flattening<'tcx>(
body: &mut Body<'tcx>,
escaping: BitSet<Local>,
) -> ReplacementMap<'tcx> {
- let mut visitor = PreFlattenVisitor {
- tcx,
- escaping,
- local_decls: &mut body.local_decls,
- map: Default::default(),
- };
- for (block, bbdata) in body.basic_blocks.iter_enumerated() {
- visitor.visit_basic_block_data(block, bbdata);
- }
- return visitor.map;
-
- struct PreFlattenVisitor<'tcx, 'll> {
- tcx: TyCtxt<'tcx>,
- local_decls: &'ll mut LocalDecls<'tcx>,
- escaping: BitSet<Local>,
- map: ReplacementMap<'tcx>,
- }
-
- impl<'tcx, 'll> PreFlattenVisitor<'tcx, 'll> {
- fn create_place(&mut self, place: PlaceRef<'tcx>) {
- if self.escaping.contains(place.local) {
- return;
- }
+ let mut fragments = IndexVec::from_elem(None, &body.local_decls);
- match self.map.fields.entry(place) {
- IndexEntry::Occupied(_) => {}
- IndexEntry::Vacant(v) => {
- let ty = place.ty(&*self.local_decls, self.tcx).ty;
- let local = self.local_decls.push(LocalDecl {
- ty,
- user_ty: None,
- ..self.local_decls[place.local].clone()
- });
- v.insert(local);
- }
- }
- }
- }
-
- impl<'tcx, 'll> Visitor<'tcx> for PreFlattenVisitor<'tcx, 'll> {
- fn visit_place(&mut self, place: &Place<'tcx>, _: PlaceContext, _: Location) {
- if let &[PlaceElem::Field(..), ..] = &place.projection[..] {
- let pr = PlaceRef { local: place.local, projection: &place.projection[..1] };
- self.create_place(pr)
- }
+ for local in body.local_decls.indices() {
+ if escaping.contains(local) {
+ continue;
}
+ let decl = body.local_decls[local].clone();
+ let ty = decl.ty;
+ iter_fields(ty, tcx, |variant, field, field_ty| {
+ if variant.is_some() {
+ // Downcasts are currently not supported.
+ return;
+ };
+ let new_local =
+ body.local_decls.push(LocalDecl { ty: field_ty, user_ty: None, ..decl.clone() });
+ fragments.get_or_insert_with(local, IndexVec::new).insert(field, (field_ty, new_local));
+ });
}
+ ReplacementMap { fragments }
}
/// Perform the replacement computed by `compute_flattening`.
@@ -169,29 +173,24 @@ fn replace_flattened_locals<'tcx>(
tcx: TyCtxt<'tcx>,
body: &mut Body<'tcx>,
replacements: ReplacementMap<'tcx>,
-) {
- let mut all_dead_locals = BitSet::new_empty(body.local_decls.len());
- for p in replacements.fields.keys() {
- all_dead_locals.insert(p.local);
+) -> BitSet<Local> {
+ let mut all_dead_locals = BitSet::new_empty(replacements.fragments.len());
+ for (local, replacements) in replacements.fragments.iter_enumerated() {
+ if replacements.is_some() {
+ all_dead_locals.insert(local);
+ }
}
debug!(?all_dead_locals);
if all_dead_locals.is_empty() {
- return;
+ return all_dead_locals;
}
- let mut fragments = IndexVec::new();
- for (k, v) in &replacements.fields {
- fragments.ensure_contains_elem(k.local, || Vec::new());
- fragments[k.local].push((k.projection, *v));
- }
- debug!(?fragments);
-
let mut visitor = ReplacementVisitor {
tcx,
local_decls: &body.local_decls,
- replacements,
+ replacements: &replacements,
all_dead_locals,
- fragments,
+ patch: MirPatch::new(body),
};
for (bb, data) in body.basic_blocks.as_mut_preserves_cfg().iter_enumerated_mut() {
visitor.visit_basic_block_data(bb, data);
@@ -205,6 +204,9 @@ fn replace_flattened_locals<'tcx>(
for var_debug_info in &mut body.var_debug_info {
visitor.visit_var_debug_info(var_debug_info);
}
+ let ReplacementVisitor { patch, all_dead_locals, .. } = visitor;
+ patch.apply(body);
+ all_dead_locals
}
struct ReplacementVisitor<'tcx, 'll> {
@@ -212,40 +214,23 @@ struct ReplacementVisitor<'tcx, 'll> {
/// This is only used to compute the type for `VarDebugInfoContents::Composite`.
local_decls: &'ll LocalDecls<'tcx>,
/// Work to do.
- replacements: ReplacementMap<'tcx>,
+ replacements: &'ll ReplacementMap<'tcx>,
/// This is used to check that we are not leaving references to replaced locals behind.
all_dead_locals: BitSet<Local>,
- /// Pre-computed list of all "new" locals for each "old" local. This is used to expand storage
- /// and deinit statement and debuginfo.
- fragments: IndexVec<Local, Vec<(&'tcx [PlaceElem<'tcx>], Local)>>,
+ patch: MirPatch<'tcx>,
}
-impl<'tcx, 'll> ReplacementVisitor<'tcx, 'll> {
- fn gather_debug_info_fragments(
- &self,
- place: PlaceRef<'tcx>,
- ) -> Vec<VarDebugInfoFragment<'tcx>> {
+impl<'tcx> ReplacementVisitor<'tcx, '_> {
+ fn gather_debug_info_fragments(&self, local: Local) -> Option<Vec<VarDebugInfoFragment<'tcx>>> {
let mut fragments = Vec::new();
- let parts = &self.fragments[place.local];
- for (proj, replacement_local) in parts {
- if proj.starts_with(place.projection) {
- fragments.push(VarDebugInfoFragment {
- projection: proj[place.projection.len()..].to_vec(),
- contents: Place::from(*replacement_local),
- });
- }
- }
- fragments
- }
-
- fn replace_place(&self, place: PlaceRef<'tcx>) -> Option<Place<'tcx>> {
- if let &[PlaceElem::Field(..), ref rest @ ..] = place.projection {
- let pr = PlaceRef { local: place.local, projection: &place.projection[..1] };
- let local = self.replacements.fields.get(&pr)?;
- Some(Place { local: *local, projection: self.tcx.intern_place_elems(&rest) })
- } else {
- None
+ let parts = self.replacements.place_fragments(local.into())?;
+ for (field, ty, replacement_local) in parts {
+ fragments.push(VarDebugInfoFragment {
+ projection: vec![PlaceElem::Field(field, ty)],
+ contents: Place::from(replacement_local),
+ });
}
+ Some(fragments)
}
}
@@ -254,94 +239,188 @@ impl<'tcx, 'll> MutVisitor<'tcx> for ReplacementVisitor<'tcx, 'll> {
self.tcx
}
- fn visit_statement(&mut self, statement: &mut Statement<'tcx>, location: Location) {
- if let StatementKind::StorageLive(..)
- | StatementKind::StorageDead(..)
- | StatementKind::Deinit(..) = statement.kind
- {
- // Storage statements are expanded in run_pass.
- return;
- }
- self.super_statement(statement, location)
- }
-
fn visit_place(&mut self, place: &mut Place<'tcx>, context: PlaceContext, location: Location) {
- if let Some(repl) = self.replace_place(place.as_ref()) {
+ if let Some(repl) = self.replacements.replace_place(self.tcx, place.as_ref()) {
*place = repl
} else {
self.super_place(place, context, location)
}
}
+ #[instrument(level = "trace", skip(self))]
+ fn visit_statement(&mut self, statement: &mut Statement<'tcx>, location: Location) {
+ match statement.kind {
+ // Duplicate storage and deinit statements, as they pretty much apply to all fields.
+ StatementKind::StorageLive(l) => {
+ if let Some(final_locals) = self.replacements.place_fragments(l.into()) {
+ for (_, _, fl) in final_locals {
+ self.patch.add_statement(location, StatementKind::StorageLive(fl));
+ }
+ statement.make_nop();
+ }
+ return;
+ }
+ StatementKind::StorageDead(l) => {
+ if let Some(final_locals) = self.replacements.place_fragments(l.into()) {
+ for (_, _, fl) in final_locals {
+ self.patch.add_statement(location, StatementKind::StorageDead(fl));
+ }
+ statement.make_nop();
+ }
+ return;
+ }
+ StatementKind::Deinit(box place) => {
+ if let Some(final_locals) = self.replacements.place_fragments(place) {
+ for (_, _, fl) in final_locals {
+ self.patch
+ .add_statement(location, StatementKind::Deinit(Box::new(fl.into())));
+ }
+ statement.make_nop();
+ return;
+ }
+ }
+
+ // We have `a = Struct { 0: x, 1: y, .. }`.
+ // We replace it by
+ // ```
+ // a_0 = x
+ // a_1 = y
+ // ...
+ // ```
+ StatementKind::Assign(box (place, Rvalue::Aggregate(_, ref mut operands))) => {
+ if let Some(local) = place.as_local()
+ && let Some(final_locals) = &self.replacements.fragments[local]
+ {
+ // This is ok as we delete the statement later.
+ let operands = std::mem::take(operands);
+ for (&opt_ty_local, mut operand) in final_locals.iter().zip(operands) {
+ if let Some((_, new_local)) = opt_ty_local {
+ // Replace mentions of SROA'd locals that appear in the operand.
+ self.visit_operand(&mut operand, location);
+
+ let rvalue = Rvalue::Use(operand);
+ self.patch.add_statement(
+ location,
+ StatementKind::Assign(Box::new((new_local.into(), rvalue))),
+ );
+ }
+ }
+ statement.make_nop();
+ return;
+ }
+ }
+
+ // We have `a = some constant`
+ // We add the projections.
+ // ```
+ // a_0 = a.0
+ // a_1 = a.1
+ // ...
+ // ```
+ // ConstProp will pick up the pieces and replace them by actual constants.
+ StatementKind::Assign(box (place, Rvalue::Use(Operand::Constant(_)))) => {
+ if let Some(final_locals) = self.replacements.place_fragments(place) {
+ // Put the deaggregated statements *after* the original one.
+ let location = location.successor_within_block();
+ for (field, ty, new_local) in final_locals {
+ let rplace = self.tcx.mk_place_field(place, field, ty);
+ let rvalue = Rvalue::Use(Operand::Move(rplace));
+ self.patch.add_statement(
+ location,
+ StatementKind::Assign(Box::new((new_local.into(), rvalue))),
+ );
+ }
+ // We still need `place.local` to exist, so don't make it nop.
+ return;
+ }
+ }
+
+ // We have `a = move? place`
+ // We replace it by
+ // ```
+ // a_0 = move? place.0
+ // a_1 = move? place.1
+ // ...
+ // ```
+ StatementKind::Assign(box (lhs, Rvalue::Use(ref op))) => {
+ let (rplace, copy) = match *op {
+ Operand::Copy(rplace) => (rplace, true),
+ Operand::Move(rplace) => (rplace, false),
+ Operand::Constant(_) => bug!(),
+ };
+ if let Some(final_locals) = self.replacements.place_fragments(lhs) {
+ for (field, ty, new_local) in final_locals {
+ let rplace = self.tcx.mk_place_field(rplace, field, ty);
+ debug!(?rplace);
+ let rplace = self
+ .replacements
+ .replace_place(self.tcx, rplace.as_ref())
+ .unwrap_or(rplace);
+ debug!(?rplace);
+ let rvalue = if copy {
+ Rvalue::Use(Operand::Copy(rplace))
+ } else {
+ Rvalue::Use(Operand::Move(rplace))
+ };
+ self.patch.add_statement(
+ location,
+ StatementKind::Assign(Box::new((new_local.into(), rvalue))),
+ );
+ }
+ statement.make_nop();
+ return;
+ }
+ }
+
+ _ => {}
+ }
+ self.super_statement(statement, location)
+ }
+
+ #[instrument(level = "trace", skip(self))]
fn visit_var_debug_info(&mut self, var_debug_info: &mut VarDebugInfo<'tcx>) {
match &mut var_debug_info.value {
VarDebugInfoContents::Place(ref mut place) => {
- if let Some(repl) = self.replace_place(place.as_ref()) {
+ if let Some(repl) = self.replacements.replace_place(self.tcx, place.as_ref()) {
*place = repl;
- } else if self.all_dead_locals.contains(place.local) {
+ } else if let Some(local) = place.as_local()
+ && let Some(fragments) = self.gather_debug_info_fragments(local)
+ {
let ty = place.ty(self.local_decls, self.tcx).ty;
- let fragments = self.gather_debug_info_fragments(place.as_ref());
var_debug_info.value = VarDebugInfoContents::Composite { ty, fragments };
}
}
VarDebugInfoContents::Composite { ty: _, ref mut fragments } => {
let mut new_fragments = Vec::new();
+ debug!(?fragments);
fragments
.drain_filter(|fragment| {
- if let Some(repl) = self.replace_place(fragment.contents.as_ref()) {
+ if let Some(repl) =
+ self.replacements.replace_place(self.tcx, fragment.contents.as_ref())
+ {
fragment.contents = repl;
- true
- } else if self.all_dead_locals.contains(fragment.contents.local) {
- let frg = self.gather_debug_info_fragments(fragment.contents.as_ref());
+ false
+ } else if let Some(local) = fragment.contents.as_local()
+ && let Some(frg) = self.gather_debug_info_fragments(local)
+ {
new_fragments.extend(frg.into_iter().map(|mut f| {
f.projection.splice(0..0, fragment.projection.iter().copied());
f
}));
- false
- } else {
true
+ } else {
+ false
}
})
.for_each(drop);
+ debug!(?fragments);
+ debug!(?new_fragments);
fragments.extend(new_fragments);
}
VarDebugInfoContents::Const(_) => {}
}
}
- fn visit_basic_block_data(&mut self, bb: BasicBlock, bbdata: &mut BasicBlockData<'tcx>) {
- self.super_basic_block_data(bb, bbdata);
-
- #[derive(Debug)]
- enum Stmt {
- StorageLive,
- StorageDead,
- Deinit,
- }
-
- bbdata.expand_statements(|stmt| {
- let source_info = stmt.source_info;
- let (stmt, origin_local) = match &stmt.kind {
- StatementKind::StorageLive(l) => (Stmt::StorageLive, *l),
- StatementKind::StorageDead(l) => (Stmt::StorageDead, *l),
- StatementKind::Deinit(p) if let Some(l) = p.as_local() => (Stmt::Deinit, l),
- _ => return None,
- };
- if !self.all_dead_locals.contains(origin_local) {
- return None;
- }
- let final_locals = self.fragments.get(origin_local)?;
- Some(final_locals.iter().map(move |&(_, l)| {
- let kind = match stmt {
- Stmt::StorageLive => StatementKind::StorageLive(l),
- Stmt::StorageDead => StatementKind::StorageDead(l),
- Stmt::Deinit => StatementKind::Deinit(Box::new(l.into())),
- };
- Statement { source_info, kind }
- }))
- });
- }
-
fn visit_local(&mut self, local: &mut Local, _: PlaceContext, _: Location) {
assert!(!self.all_dead_locals.contains(*local));
}
diff --git a/compiler/rustc_mir_transform/src/ssa.rs b/compiler/rustc_mir_transform/src/ssa.rs
new file mode 100644
index 000000000..c1e7f62de
--- /dev/null
+++ b/compiler/rustc_mir_transform/src/ssa.rs
@@ -0,0 +1,257 @@
+use either::Either;
+use rustc_data_structures::graph::dominators::Dominators;
+use rustc_index::bit_set::BitSet;
+use rustc_index::vec::IndexVec;
+use rustc_middle::middle::resolve_bound_vars::Set1;
+use rustc_middle::mir::visit::*;
+use rustc_middle::mir::*;
+use rustc_middle::ty::{ParamEnv, TyCtxt};
+
+#[derive(Debug)]
+pub struct SsaLocals {
+ /// Assignments to each local. This defines whether the local is SSA.
+ assignments: IndexVec<Local, Set1<LocationExtended>>,
+ /// We visit the body in reverse postorder, to ensure each local is assigned before it is used.
+ /// We remember the order in which we saw the assignments to compute the SSA values in a single
+ /// pass.
+ assignment_order: Vec<Local>,
+ /// Copy equivalence classes between locals. See `copy_classes` for documentation.
+ copy_classes: IndexVec<Local, Local>,
+}
+
+/// We often encounter MIR bodies with 1 or 2 basic blocks. In those cases, it's unnecessary to
+/// actually compute dominators, we can just compare block indices because bb0 is always the first
+/// block, and in any body all other blocks are always always dominated by bb0.
+struct SmallDominators {
+ inner: Option<Dominators<BasicBlock>>,
+}
+
+trait DomExt {
+ fn dominates(self, _other: Self, dominators: &SmallDominators) -> bool;
+}
+
+impl DomExt for Location {
+ fn dominates(self, other: Location, dominators: &SmallDominators) -> bool {
+ if self.block == other.block {
+ self.statement_index <= other.statement_index
+ } else {
+ dominators.dominates(self.block, other.block)
+ }
+ }
+}
+
+impl SmallDominators {
+ fn dominates(&self, dom: BasicBlock, node: BasicBlock) -> bool {
+ if let Some(inner) = &self.inner { inner.dominates(dom, node) } else { dom < node }
+ }
+}
+
+impl SsaLocals {
+ pub fn new<'tcx>(
+ tcx: TyCtxt<'tcx>,
+ param_env: ParamEnv<'tcx>,
+ body: &Body<'tcx>,
+ borrowed_locals: &BitSet<Local>,
+ ) -> SsaLocals {
+ let assignment_order = Vec::new();
+
+ let assignments = IndexVec::from_elem(Set1::Empty, &body.local_decls);
+ let dominators =
+ if body.basic_blocks.len() > 2 { Some(body.basic_blocks.dominators()) } else { None };
+ let dominators = SmallDominators { inner: dominators };
+ let mut visitor = SsaVisitor { assignments, assignment_order, dominators };
+
+ for (local, decl) in body.local_decls.iter_enumerated() {
+ if matches!(body.local_kind(local), LocalKind::Arg) {
+ visitor.assignments[local] = Set1::One(LocationExtended::Arg);
+ }
+ if borrowed_locals.contains(local) && !decl.ty.is_freeze(tcx, param_env) {
+ visitor.assignments[local] = Set1::Many;
+ }
+ }
+
+ if body.basic_blocks.len() > 2 {
+ for (bb, data) in traversal::reverse_postorder(body) {
+ visitor.visit_basic_block_data(bb, data);
+ }
+ } else {
+ for (bb, data) in body.basic_blocks.iter_enumerated() {
+ visitor.visit_basic_block_data(bb, data);
+ }
+ }
+
+ for var_debug_info in &body.var_debug_info {
+ visitor.visit_var_debug_info(var_debug_info);
+ }
+
+ debug!(?visitor.assignments);
+
+ visitor
+ .assignment_order
+ .retain(|&local| matches!(visitor.assignments[local], Set1::One(_)));
+ debug!(?visitor.assignment_order);
+
+ let copy_classes = compute_copy_classes(&visitor, body);
+
+ SsaLocals {
+ assignments: visitor.assignments,
+ assignment_order: visitor.assignment_order,
+ copy_classes,
+ }
+ }
+
+ pub fn is_ssa(&self, local: Local) -> bool {
+ matches!(self.assignments[local], Set1::One(_))
+ }
+
+ pub fn assignments<'a, 'tcx>(
+ &'a self,
+ body: &'a Body<'tcx>,
+ ) -> impl Iterator<Item = (Local, &'a Rvalue<'tcx>)> + 'a {
+ self.assignment_order.iter().filter_map(|&local| {
+ if let Set1::One(LocationExtended::Plain(loc)) = self.assignments[local] {
+ // `loc` must point to a direct assignment to `local`.
+ let Either::Left(stmt) = body.stmt_at(loc) else { bug!() };
+ let Some((target, rvalue)) = stmt.kind.as_assign() else { bug!() };
+ assert_eq!(target.as_local(), Some(local));
+ Some((local, rvalue))
+ } else {
+ None
+ }
+ })
+ }
+
+ /// Compute the equivalence classes for locals, based on copy statements.
+ ///
+ /// The returned vector maps each local to the one it copies. In the following case:
+ /// _a = &mut _0
+ /// _b = move? _a
+ /// _c = move? _a
+ /// _d = move? _c
+ /// We return the mapping
+ /// _a => _a // not a copy so, represented by itself
+ /// _b => _a
+ /// _c => _a
+ /// _d => _a // transitively through _c
+ ///
+ /// Exception: we do not see through the return place, as it cannot be substituted.
+ pub fn copy_classes(&self) -> &IndexVec<Local, Local> {
+ &self.copy_classes
+ }
+
+ /// Make a property uniform on a copy equivalence class by removing elements.
+ pub fn meet_copy_equivalence(&self, property: &mut BitSet<Local>) {
+ // Consolidate to have a local iff all its copies are.
+ //
+ // `copy_classes` defines equivalence classes between locals. The `local`s that recursively
+ // move/copy the same local all have the same `head`.
+ for (local, &head) in self.copy_classes.iter_enumerated() {
+ // If any copy does not have `property`, then the head is not.
+ if !property.contains(local) {
+ property.remove(head);
+ }
+ }
+ for (local, &head) in self.copy_classes.iter_enumerated() {
+ // If any copy does not have `property`, then the head doesn't either,
+ // then no copy has `property`.
+ if !property.contains(head) {
+ property.remove(local);
+ }
+ }
+
+ // Verify that we correctly computed equivalence classes.
+ #[cfg(debug_assertions)]
+ for (local, &head) in self.copy_classes.iter_enumerated() {
+ assert_eq!(property.contains(local), property.contains(head));
+ }
+ }
+}
+
+#[derive(Copy, Clone, Debug, PartialEq, Eq)]
+enum LocationExtended {
+ Plain(Location),
+ Arg,
+}
+
+struct SsaVisitor {
+ dominators: SmallDominators,
+ assignments: IndexVec<Local, Set1<LocationExtended>>,
+ assignment_order: Vec<Local>,
+}
+
+impl<'tcx> Visitor<'tcx> for SsaVisitor {
+ fn visit_local(&mut self, local: Local, ctxt: PlaceContext, loc: Location) {
+ match ctxt {
+ PlaceContext::MutatingUse(MutatingUseContext::Store) => {
+ self.assignments[local].insert(LocationExtended::Plain(loc));
+ self.assignment_order.push(local);
+ }
+ // Anything can happen with raw pointers, so remove them.
+ PlaceContext::NonMutatingUse(NonMutatingUseContext::AddressOf)
+ | PlaceContext::MutatingUse(_) => self.assignments[local] = Set1::Many,
+ // Immutable borrows are taken into account in `SsaLocals::new` by
+ // removing non-freeze locals.
+ PlaceContext::NonMutatingUse(_) => {
+ let set = &mut self.assignments[local];
+ let assign_dominates = match *set {
+ Set1::Empty | Set1::Many => false,
+ Set1::One(LocationExtended::Arg) => true,
+ Set1::One(LocationExtended::Plain(assign)) => {
+ assign.successor_within_block().dominates(loc, &self.dominators)
+ }
+ };
+ // We are visiting a use that is not dominated by an assignment.
+ // Either there is a cycle involved, or we are reading for uninitialized local.
+ // Bail out.
+ if !assign_dominates {
+ *set = Set1::Many;
+ }
+ }
+ PlaceContext::NonUse(_) => {}
+ }
+ }
+}
+
+#[instrument(level = "trace", skip(ssa, body))]
+fn compute_copy_classes(ssa: &SsaVisitor, body: &Body<'_>) -> IndexVec<Local, Local> {
+ let mut copies = IndexVec::from_fn_n(|l| l, body.local_decls.len());
+
+ for &local in &ssa.assignment_order {
+ debug!(?local);
+
+ if local == RETURN_PLACE {
+ // `_0` is special, we cannot rename it.
+ continue;
+ }
+
+ // This is not SSA: mark that we don't know the value.
+ debug!(assignments = ?ssa.assignments[local]);
+ let Set1::One(LocationExtended::Plain(loc)) = ssa.assignments[local] else { continue };
+
+ // `loc` must point to a direct assignment to `local`.
+ let Either::Left(stmt) = body.stmt_at(loc) else { bug!() };
+ let Some((_target, rvalue)) = stmt.kind.as_assign() else { bug!() };
+ assert_eq!(_target.as_local(), Some(local));
+
+ let (Rvalue::Use(Operand::Copy(place) | Operand::Move(place)) | Rvalue::CopyForDeref(place))
+ = rvalue
+ else { continue };
+
+ let Some(rhs) = place.as_local() else { continue };
+ let Set1::One(_) = ssa.assignments[rhs] else { continue };
+
+ // We visit in `assignment_order`, ie. reverse post-order, so `rhs` has been
+ // visited before `local`, and we just have to copy the representing local.
+ copies[local] = copies[rhs];
+ }
+
+ debug!(?copies);
+
+ // Invariant: `copies` must point to the head of an equivalence class.
+ #[cfg(debug_assertions)]
+ for &head in copies.iter() {
+ assert_eq!(copies[head], head);
+ }
+
+ copies
+}
diff --git a/compiler/rustc_error_messages/locales/en-US/monomorphize.ftl b/compiler/rustc_monomorphize/locales/en-US.ftl
index 243d10bfa..6cea6a603 100644
--- a/compiler/rustc_error_messages/locales/en-US/monomorphize.ftl
+++ b/compiler/rustc_monomorphize/locales/en-US.ftl
@@ -24,3 +24,9 @@ monomorphize_large_assignments =
monomorphize_couldnt_dump_mono_stats =
unexpected error occurred while dumping monomorphization stats: {$error}
+
+monomorphize_encountered_error_while_instantiating =
+ the above error was encountered while instantiating `{$formatted_item}`
+
+monomorphize_unknown_cgu_collection_mode =
+ unknown codegen-item collection mode '{$mode}', falling back to 'lazy' mode
diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs
index ec1de3056..45e659eab 100644
--- a/compiler/rustc_monomorphize/src/collector.rs
+++ b/compiler/rustc_monomorphize/src/collector.rs
@@ -190,7 +190,7 @@ use rustc_middle::ty::print::with_no_trimmed_paths;
use rustc_middle::ty::query::TyCtxtAt;
use rustc_middle::ty::subst::{GenericArgKind, InternalSubsts};
use rustc_middle::ty::{
- self, GenericParamDefKind, Instance, Ty, TyCtxt, TypeFoldable, TypeVisitable, VtblEntry,
+ self, GenericParamDefKind, Instance, Ty, TyCtxt, TypeFoldable, TypeVisitableExt, VtblEntry,
};
use rustc_middle::{middle::codegen_fn_attrs::CodegenFnAttrFlags, mir::visit::TyContext};
use rustc_session::config::EntryFnType;
@@ -201,7 +201,9 @@ use rustc_target::abi::Size;
use std::ops::Range;
use std::path::PathBuf;
-use crate::errors::{LargeAssignmentsLint, RecursionLimit, TypeLengthLimit};
+use crate::errors::{
+ EncounteredErrorWhileInstantiating, LargeAssignmentsLint, RecursionLimit, TypeLengthLimit,
+};
#[derive(PartialEq)]
pub enum MonoItemCollectionMode {
@@ -524,10 +526,10 @@ fn collect_items_rec<'tcx>(
&& starting_point.node.is_user_defined()
{
let formatted_item = with_no_trimmed_paths!(starting_point.node.to_string());
- tcx.sess.span_note_without_error(
- starting_point.span,
- &format!("the above error was encountered while instantiating `{formatted_item}`"),
- );
+ tcx.sess.emit_note(EncounteredErrorWhileInstantiating {
+ span: starting_point.span,
+ formatted_item,
+ });
}
inlining_map.lock_mut().record_accesses(starting_point.node, &neighbors.items);
@@ -658,7 +660,7 @@ struct MirNeighborCollector<'a, 'tcx> {
impl<'a, 'tcx> MirNeighborCollector<'a, 'tcx> {
pub fn monomorphize<T>(&self, value: T) -> T
where
- T: TypeFoldable<'tcx>,
+ T: TypeFoldable<TyCtxt<'tcx>>,
{
debug!("monomorphize: self.instance={:?}", self.instance);
self.instance.subst_mir_and_normalize_erasing_regions(
@@ -1191,28 +1193,13 @@ impl<'v> RootCollector<'_, 'v> {
fn process_item(&mut self, id: hir::ItemId) {
match self.tcx.def_kind(id.owner_id) {
DefKind::Enum | DefKind::Struct | DefKind::Union => {
- let item = self.tcx.hir().item(id);
- match item.kind {
- hir::ItemKind::Enum(_, ref generics)
- | hir::ItemKind::Struct(_, ref generics)
- | hir::ItemKind::Union(_, ref generics) => {
- if generics.params.is_empty() {
- if self.mode == MonoItemCollectionMode::Eager {
- debug!(
- "RootCollector: ADT drop-glue for {}",
- self.tcx.def_path_str(item.owner_id.to_def_id())
- );
-
- let ty = Instance::new(
- item.owner_id.to_def_id(),
- InternalSubsts::empty(),
- )
- .ty(self.tcx, ty::ParamEnv::reveal_all());
- visit_drop_use(self.tcx, ty, true, DUMMY_SP, self.output);
- }
- }
- }
- _ => bug!(),
+ if self.mode == MonoItemCollectionMode::Eager
+ && self.tcx.generics_of(id.owner_id).count() == 0
+ {
+ debug!("RootCollector: ADT drop-glue for `{id:?}`",);
+
+ let ty = self.tcx.type_of(id.owner_id.to_def_id()).no_bound_vars().unwrap();
+ visit_drop_use(self.tcx, ty, true, DUMMY_SP, self.output);
}
}
DefKind::GlobalAsm => {
@@ -1238,10 +1225,9 @@ impl<'v> RootCollector<'_, 'v> {
collect_const_value(self.tcx, val, &mut self.output);
}
}
- DefKind::Impl => {
+ DefKind::Impl { .. } => {
if self.mode == MonoItemCollectionMode::Eager {
- let item = self.tcx.hir().item(id);
- create_mono_items_for_default_impls(self.tcx, item, self.output);
+ create_mono_items_for_default_impls(self.tcx, id, self.output);
}
}
DefKind::Fn => {
@@ -1296,7 +1282,7 @@ impl<'v> RootCollector<'_, 'v> {
};
let start_def_id = self.tcx.require_lang_item(LangItem::Start, None);
- let main_ret_ty = self.tcx.fn_sig(main_def_id).output();
+ let main_ret_ty = self.tcx.fn_sig(main_def_id).no_bound_vars().unwrap().output();
// Given that `main()` has no arguments,
// then its return type cannot have
@@ -1312,7 +1298,7 @@ impl<'v> RootCollector<'_, 'v> {
self.tcx,
ty::ParamEnv::reveal_all(),
start_def_id,
- self.tcx.intern_substs(&[main_ret_ty.into()]),
+ self.tcx.mk_substs(&[main_ret_ty.into()]),
)
.unwrap()
.unwrap();
@@ -1326,66 +1312,51 @@ fn item_requires_monomorphization(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool {
generics.requires_monomorphization(tcx)
}
+#[instrument(level = "debug", skip(tcx, output))]
fn create_mono_items_for_default_impls<'tcx>(
tcx: TyCtxt<'tcx>,
- item: &'tcx hir::Item<'tcx>,
+ item: hir::ItemId,
output: &mut MonoItems<'tcx>,
) {
- match item.kind {
- hir::ItemKind::Impl(ref impl_) => {
- if matches!(impl_.polarity, hir::ImplPolarity::Negative(_)) {
- return;
- }
+ let polarity = tcx.impl_polarity(item.owner_id);
+ if matches!(polarity, ty::ImplPolarity::Negative) {
+ return;
+ }
- for param in impl_.generics.params {
- match param.kind {
- hir::GenericParamKind::Lifetime { .. } => {}
- hir::GenericParamKind::Type { .. } | hir::GenericParamKind::Const { .. } => {
- return;
- }
- }
- }
+ if tcx.generics_of(item.owner_id).own_requires_monomorphization() {
+ return;
+ }
- debug!(
- "create_mono_items_for_default_impls(item={})",
- tcx.def_path_str(item.owner_id.to_def_id())
- );
+ let Some(trait_ref) = tcx.impl_trait_ref(item.owner_id) else {
+ return;
+ };
- if let Some(trait_ref) = tcx.impl_trait_ref(item.owner_id) {
- let trait_ref = trait_ref.subst_identity();
+ let trait_ref = trait_ref.subst_identity();
- let param_env = ty::ParamEnv::reveal_all();
- let trait_ref = tcx.normalize_erasing_regions(param_env, trait_ref);
- let overridden_methods = tcx.impl_item_implementor_ids(item.owner_id);
- for method in tcx.provided_trait_methods(trait_ref.def_id) {
- if overridden_methods.contains_key(&method.def_id) {
- continue;
- }
+ let param_env = ty::ParamEnv::reveal_all();
+ let trait_ref = tcx.normalize_erasing_regions(param_env, trait_ref);
+ let overridden_methods = tcx.impl_item_implementor_ids(item.owner_id);
+ for method in tcx.provided_trait_methods(trait_ref.def_id) {
+ if overridden_methods.contains_key(&method.def_id) {
+ continue;
+ }
- if tcx.generics_of(method.def_id).own_requires_monomorphization() {
- continue;
- }
+ if tcx.generics_of(method.def_id).own_requires_monomorphization() {
+ continue;
+ }
- let substs =
- InternalSubsts::for_item(tcx, method.def_id, |param, _| match param.kind {
- GenericParamDefKind::Lifetime => tcx.lifetimes.re_erased.into(),
- GenericParamDefKind::Type { .. }
- | GenericParamDefKind::Const { .. } => {
- trait_ref.substs[param.index as usize]
- }
- });
- let instance =
- ty::Instance::expect_resolve(tcx, param_env, method.def_id, substs);
-
- let mono_item = create_fn_mono_item(tcx, instance, DUMMY_SP);
- if mono_item.node.is_instantiable(tcx) && should_codegen_locally(tcx, &instance)
- {
- output.push(mono_item);
- }
- }
+ let substs = InternalSubsts::for_item(tcx, method.def_id, |param, _| match param.kind {
+ GenericParamDefKind::Lifetime => tcx.lifetimes.re_erased.into(),
+ GenericParamDefKind::Type { .. } | GenericParamDefKind::Const { .. } => {
+ trait_ref.substs[param.index as usize]
}
+ });
+ let instance = ty::Instance::expect_resolve(tcx, param_env, method.def_id, substs);
+
+ let mono_item = create_fn_mono_item(tcx, instance, DUMMY_SP);
+ if mono_item.node.is_instantiable(tcx) && should_codegen_locally(tcx, &instance) {
+ output.push(mono_item);
}
- _ => bug!(),
}
}
diff --git a/compiler/rustc_monomorphize/src/errors.rs b/compiler/rustc_monomorphize/src/errors.rs
index 5233cfb21..495a73490 100644
--- a/compiler/rustc_monomorphize/src/errors.rs
+++ b/compiler/rustc_monomorphize/src/errors.rs
@@ -1,5 +1,6 @@
use std::path::PathBuf;
+use crate::fluent_generated as fluent;
use rustc_errors::ErrorGuaranteed;
use rustc_errors::IntoDiagnostic;
use rustc_macros::{Diagnostic, LintDiagnostic};
@@ -44,7 +45,7 @@ impl IntoDiagnostic<'_> for UnusedGenericParamsHint {
self,
handler: &'_ rustc_errors::Handler,
) -> rustc_errors::DiagnosticBuilder<'_, ErrorGuaranteed> {
- let mut diag = handler.struct_err(rustc_errors::fluent::monomorphize_unused_generic_params);
+ let mut diag = handler.struct_err(fluent::monomorphize_unused_generic_params);
diag.set_span(self.span);
for (span, name) in self.param_spans.into_iter().zip(self.param_names) {
// FIXME: I can figure out how to do a label with a fluent string with a fixed message,
@@ -83,3 +84,17 @@ pub struct SymbolAlreadyDefined {
pub struct CouldntDumpMonoStats {
pub error: String,
}
+
+#[derive(Diagnostic)]
+#[diag(monomorphize_encountered_error_while_instantiating)]
+pub struct EncounteredErrorWhileInstantiating {
+ #[primary_span]
+ pub span: Span,
+ pub formatted_item: String,
+}
+
+#[derive(Diagnostic)]
+#[diag(monomorphize_unknown_cgu_collection_mode)]
+pub struct UnknownCguCollectionMode<'a> {
+ pub mode: &'a str,
+}
diff --git a/compiler/rustc_monomorphize/src/lib.rs b/compiler/rustc_monomorphize/src/lib.rs
index f88155e4f..f6b791f29 100644
--- a/compiler/rustc_monomorphize/src/lib.rs
+++ b/compiler/rustc_monomorphize/src/lib.rs
@@ -9,7 +9,9 @@ extern crate tracing;
#[macro_use]
extern crate rustc_middle;
+use rustc_errors::{DiagnosticMessage, SubdiagnosticMessage};
use rustc_hir::lang_items::LangItem;
+use rustc_macros::fluent_messages;
use rustc_middle::traits;
use rustc_middle::ty::adjustment::CustomCoerceUnsized;
use rustc_middle::ty::query::{Providers, TyCtxtAt};
@@ -21,6 +23,8 @@ mod partitioning;
mod polymorphize;
mod util;
+fluent_messages! { "../locales/en-US.ftl" }
+
fn custom_coerce_unsize_info<'tcx>(
tcx: TyCtxtAt<'tcx>,
source_ty: Ty<'tcx>,
diff --git a/compiler/rustc_monomorphize/src/partitioning/default.rs b/compiler/rustc_monomorphize/src/partitioning/default.rs
index 29009c480..2c56edd89 100644
--- a/compiler/rustc_monomorphize/src/partitioning/default.rs
+++ b/compiler/rustc_monomorphize/src/partitioning/default.rs
@@ -9,7 +9,7 @@ use rustc_middle::middle::exported_symbols::{SymbolExportInfo, 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, visit::TypeVisitable, DefIdTree, InstanceDef, TyCtxt};
+use rustc_middle::ty::{self, visit::TypeVisitableExt, DefIdTree, InstanceDef, TyCtxt};
use rustc_span::symbol::Symbol;
use super::PartitioningCx;
@@ -308,7 +308,7 @@ fn characteristic_def_id_of_mono_item<'tcx>(
let impl_self_ty = tcx.subst_and_normalize_erasing_regions(
instance.substs,
ty::ParamEnv::reveal_all(),
- tcx.type_of(impl_def_id),
+ tcx.type_of(impl_def_id).skip_binder(),
);
if let Some(def_id) = characteristic_def_id_of_type(impl_self_ty) {
return Some(def_id);
diff --git a/compiler/rustc_monomorphize/src/partitioning/mod.rs b/compiler/rustc_monomorphize/src/partitioning/mod.rs
index fd6bcad18..524c51d88 100644
--- a/compiler/rustc_monomorphize/src/partitioning/mod.rs
+++ b/compiler/rustc_monomorphize/src/partitioning/mod.rs
@@ -114,7 +114,9 @@ use rustc_span::symbol::Symbol;
use crate::collector::InliningMap;
use crate::collector::{self, MonoItemCollectionMode};
-use crate::errors::{CouldntDumpMonoStats, SymbolAlreadyDefined, UnknownPartitionStrategy};
+use crate::errors::{
+ CouldntDumpMonoStats, SymbolAlreadyDefined, UnknownCguCollectionMode, UnknownPartitionStrategy,
+};
pub struct PartitioningCx<'a, 'tcx> {
tcx: TyCtxt<'tcx>,
@@ -180,7 +182,7 @@ pub fn partition<'tcx>(
partitioner.place_root_mono_items(cx, mono_items)
};
- initial_partitioning.codegen_units.iter_mut().for_each(|cgu| cgu.estimate_size(tcx));
+ initial_partitioning.codegen_units.iter_mut().for_each(|cgu| cgu.create_size_estimate(tcx));
debug_dump(tcx, "INITIAL PARTITIONING:", initial_partitioning.codegen_units.iter());
@@ -200,7 +202,7 @@ pub fn partition<'tcx>(
partitioner.place_inlined_mono_items(cx, initial_partitioning)
};
- post_inlining.codegen_units.iter_mut().for_each(|cgu| cgu.estimate_size(tcx));
+ post_inlining.codegen_units.iter_mut().for_each(|cgu| cgu.create_size_estimate(tcx));
debug_dump(tcx, "POST INLINING:", post_inlining.codegen_units.iter());
@@ -348,17 +350,13 @@ where
fn collect_and_partition_mono_items(tcx: TyCtxt<'_>, (): ()) -> (&DefIdSet, &[CodegenUnit<'_>]) {
let collection_mode = match tcx.sess.opts.unstable_opts.print_mono_items {
Some(ref s) => {
- let mode_string = s.to_lowercase();
- let mode_string = mode_string.trim();
- if mode_string == "eager" {
+ let mode = s.to_lowercase();
+ let mode = mode.trim();
+ if mode == "eager" {
MonoItemCollectionMode::Eager
} else {
- if mode_string != "lazy" {
- let message = format!(
- "Unknown codegen-item collection mode '{mode_string}'. \
- Falling back to 'lazy' mode."
- );
- tcx.sess.warn(&message);
+ if mode != "lazy" {
+ tcx.sess.emit_warning(UnknownCguCollectionMode { mode });
}
MonoItemCollectionMode::Lazy
diff --git a/compiler/rustc_monomorphize/src/polymorphize.rs b/compiler/rustc_monomorphize/src/polymorphize.rs
index cf13d4584..b7c3dbcc0 100644
--- a/compiler/rustc_monomorphize/src/polymorphize.rs
+++ b/compiler/rustc_monomorphize/src/polymorphize.rs
@@ -15,7 +15,7 @@ use rustc_middle::ty::{
self,
query::Providers,
subst::SubstsRef,
- visit::{TypeSuperVisitable, TypeVisitable, TypeVisitor},
+ visit::{TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor},
Const, Ty, TyCtxt, UnusedGenericParams,
};
use rustc_span::symbol::sym;
@@ -172,7 +172,7 @@ fn mark_used_by_default_parameters<'tcx>(
| DefKind::Field
| DefKind::LifetimeParam
| DefKind::GlobalAsm
- | DefKind::Impl => {
+ | DefKind::Impl { .. } => {
for param in &generics.params {
debug!(?param, "(other)");
if let ty::GenericParamDefKind::Lifetime = param.kind {
@@ -296,7 +296,7 @@ impl<'a, 'tcx> Visitor<'tcx> for MarkUsedGenericParams<'a, 'tcx> {
}
}
-impl<'a, 'tcx> TypeVisitor<'tcx> for MarkUsedGenericParams<'a, 'tcx> {
+impl<'a, 'tcx> TypeVisitor<TyCtxt<'tcx>> for MarkUsedGenericParams<'a, 'tcx> {
#[instrument(level = "debug", skip(self))]
fn visit_const(&mut self, c: Const<'tcx>) -> ControlFlow<Self::BreakTy> {
if !c.has_non_region_param() {
diff --git a/compiler/rustc_parse/Cargo.toml b/compiler/rustc_parse/Cargo.toml
index dbcfb3903..3eb158c81 100644
--- a/compiler/rustc_parse/Cargo.toml
+++ b/compiler/rustc_parse/Cargo.toml
@@ -16,7 +16,7 @@ rustc_lexer = { path = "../rustc_lexer" }
rustc_macros = { path = "../rustc_macros" }
rustc_session = { path = "../rustc_session" }
rustc_span = { path = "../rustc_span" }
-thin-vec = "0.2.8"
+thin-vec = "0.2.12"
tracing = "0.1"
unicode-normalization = "0.1.11"
unicode-width = "0.1.4"
diff --git a/compiler/rustc_error_messages/locales/en-US/parse.ftl b/compiler/rustc_parse/locales/en-US.ftl
index 8f063f508..e76e91fc1 100644
--- a/compiler/rustc_error_messages/locales/en-US/parse.ftl
+++ b/compiler/rustc_parse/locales/en-US.ftl
@@ -93,6 +93,26 @@ parse_do_catch_syntax_removed = found removed `do catch` syntax
parse_float_literal_requires_integer_part = float literals must have an integer part
.suggestion = must have an integer part
+parse_invalid_int_literal_width = invalid width `{$width}` for integer literal
+ .help = valid widths are 8, 16, 32, 64 and 128
+
+parse_invalid_num_literal_base_prefix = invalid base prefix for number literal
+ .note = base prefixes (`0xff`, `0b1010`, `0o755`) are lowercase
+ .suggestion = try making the prefix lowercase
+
+parse_invalid_num_literal_suffix = invalid suffix `{$suffix}` for number literal
+ .label = invalid suffix `{$suffix}`
+ .help = the suffix must be one of the numeric types (`u32`, `isize`, `f32`, etc.)
+
+parse_invalid_float_literal_width = invalid width `{$width}` for float literal
+ .help = valid widths are 32 and 64
+
+parse_invalid_float_literal_suffix = invalid suffix `{$suffix}` for float literal
+ .label = invalid suffix `{$suffix}`
+ .help = valid suffixes are `f32` and `f64`
+
+parse_int_literal_too_large = integer literal is too large
+
parse_missing_semicolon_before_array = expected `;`, found `[`
.suggestion = consider adding `;` here
@@ -128,6 +148,13 @@ parse_missing_in_in_for_loop = missing `in` in `for` loop
.use_in_not_of = try using `in` here instead
.add_in = try adding `in` here
+parse_missing_expression_in_for_loop = missing expression to iterate on in `for` loop
+ .suggestion = try adding an expression to the `for` loop
+
+parse_loop_else = `{$loop_kind}...else` loops are not supported
+ .note = consider moving this `else` clause to a separate `if` statement and use a `bool` variable to control if it should run
+ .loop_keyword = `else` is attached to this loop
+
parse_missing_comma_after_match_arm = expected `,` following `match` arm
.suggestion = missing a comma here to end this `match` arm
@@ -197,13 +224,33 @@ parse_match_arm_body_without_braces = `match` arm body without braces
[one] statement
*[other] statements
} with a body
- .suggestion_use_comma_not_semicolon = use a comma to end a `match` arm expression
+ .suggestion_use_comma_not_semicolon = replace `;` with `,` to end a `match` arm expression
+
+parse_inclusive_range_extra_equals = unexpected `=` after inclusive range
+ .suggestion_remove_eq = use `..=` instead
+ .note = inclusive ranges end with a single equals sign (`..=`)
+
+parse_inclusive_range_match_arrow = unexpected `>` after inclusive range
+ .label = this is parsed as an inclusive range `..=`
+ .suggestion = add a space between the pattern and `=>`
+
+parse_inclusive_range_no_end = inclusive range with no end
+ .suggestion_open_range = use `..` instead
+ .note = inclusive ranges must be bounded at the end (`..=b` or `a..=b`)
parse_struct_literal_not_allowed_here = struct literals are not allowed here
.suggestion = surround the struct literal with parentheses
parse_invalid_interpolated_expression = invalid interpolated expression
+parse_hexadecimal_float_literal_not_supported = hexadecimal float literal is not supported
+parse_octal_float_literal_not_supported = octal float literal is not supported
+parse_binary_float_literal_not_supported = binary float literal is not supported
+parse_not_supported = not supported
+
+parse_invalid_literal_suffix = suffixes on {$kind} literals are invalid
+ .label = invalid suffix `{$suffix}`
+
parse_invalid_literal_suffix_on_tuple_index = suffixes on a tuple index are invalid
.label = invalid suffix `{$suffix}`
.tuple_exception_line_1 = `{$suffix}` is *temporarily* accepted on tuple index fields as it was incorrectly accepted on stable for a few releases
@@ -238,6 +285,7 @@ parse_const_let_mutually_exclusive = `const` and `let` are mutually exclusive
parse_invalid_expression_in_let_else = a `{$operator}` expression cannot be directly assigned in `let...else`
parse_invalid_curly_in_let_else = right curly brace `{"}"}` before `else` in a `let...else` statement not allowed
+parse_extra_if_in_let_else = remove the `if` if you meant to write a `let...else` statement
parse_compound_assignment_expression_in_let = can't reassign to an uninitialized variable
.suggestion = initialize the variable
@@ -378,3 +426,309 @@ parse_where_clause_before_tuple_struct_body = where clauses are not allowed befo
.name_label = while parsing this tuple struct
.body_label = the struct body
.suggestion = move the body before the where clause
+
+parse_async_fn_in_2015 = `async fn` is not permitted in Rust 2015
+ .label = to use `async fn`, switch to Rust 2018 or later
+
+parse_async_block_in_2015 = `async` blocks are only allowed in Rust 2018 or later
+
+parse_self_argument_pointer = cannot pass `self` by raw pointer
+ .label = cannot pass `self` by raw pointer
+
+parse_visibility_not_followed_by_item = visibility `{$vis}` is not followed by an item
+ .label = the visibility
+ .help = you likely meant to define an item, e.g., `{$vis} fn foo() {"{}"}`
+
+parse_default_not_followed_by_item = `default` is not followed by an item
+ .label = the `default` qualifier
+ .note = only `fn`, `const`, `type`, or `impl` items may be prefixed by `default`
+
+parse_missing_struct_for_struct_definition = missing `struct` for struct definition
+ .suggestion = add `struct` here to parse `{$ident}` as a public struct
+
+parse_missing_fn_for_function_definition = missing `fn` for function definition
+ .suggestion = add `fn` here to parse `{$ident}` as a public function
+
+parse_missing_fn_for_method_definition = missing `fn` for method definition
+ .suggestion = add `fn` here to parse `{$ident}` as a public method
+
+parse_ambiguous_missing_keyword_for_item_definition = missing `fn` or `struct` for function or struct definition
+ .suggestion = if you meant to call a macro, try
+ .help = if you meant to call a macro, remove the `pub` and add a trailing `!` after the identifier
+
+parse_missing_trait_in_trait_impl = missing trait in a trait impl
+ .suggestion_add_trait = add a trait here
+ .suggestion_remove_for = for an inherent impl, drop this `for`
+
+parse_missing_for_in_trait_impl = missing `for` in a trait impl
+ .suggestion = add `for` here
+
+parse_expected_trait_in_trait_impl_found_type = expected a trait, found type
+
+parse_non_item_in_item_list = non-item in item list
+ .suggestion_use_const_not_let = consider using `const` instead of `let` for associated const
+ .label_list_start = item list starts here
+ .label_non_item = non-item starts here
+ .label_list_end = item list ends here
+ .suggestion_remove_semicolon = consider removing this semicolon
+
+parse_bounds_not_allowed_on_trait_aliases = bounds are not allowed on trait aliases
+
+parse_trait_alias_cannot_be_auto = trait aliases cannot be `auto`
+parse_trait_alias_cannot_be_unsafe = trait aliases cannot be `unsafe`
+
+parse_associated_static_item_not_allowed = associated `static` items are not allowed
+
+parse_extern_crate_name_with_dashes = crate name using dashes are not valid in `extern crate` statements
+ .label = dash-separated idents are not valid
+ .suggestion = if the original crate name uses dashes you need to use underscores in the code
+
+parse_extern_item_cannot_be_const = extern items cannot be `const`
+ .suggestion = try using a static value
+ .note = for more information, visit https://doc.rust-lang.org/std/keyword.extern.html
+
+parse_const_global_cannot_be_mutable = const globals cannot be mutable
+ .label = cannot be mutable
+ .suggestion = you might want to declare a static instead
+
+parse_missing_const_type = missing type for `{$kind}` item
+ .suggestion = provide a type for the item
+
+parse_enum_struct_mutually_exclusive = `enum` and `struct` are mutually exclusive
+ .suggestion = replace `enum struct` with
+
+parse_unexpected_token_after_struct_name = expected `where`, `{"{"}`, `(`, or `;` after struct name
+parse_unexpected_token_after_struct_name_found_reserved_identifier = expected `where`, `{"{"}`, `(`, or `;` after struct name, found reserved identifier `{$token}`
+parse_unexpected_token_after_struct_name_found_keyword = expected `where`, `{"{"}`, `(`, or `;` after struct name, found keyword `{$token}`
+parse_unexpected_token_after_struct_name_found_reserved_keyword = expected `where`, `{"{"}`, `(`, or `;` after struct name, found reserved keyword `{$token}`
+parse_unexpected_token_after_struct_name_found_doc_comment = expected `where`, `{"{"}`, `(`, or `;` after struct name, found doc comment `{$token}`
+parse_unexpected_token_after_struct_name_found_other = expected `where`, `{"{"}`, `(`, or `;` after struct name, found `{$token}`
+
+parse_unexpected_self_in_generic_parameters = unexpected keyword `Self` in generic parameters
+ .note = you cannot use `Self` as a generic parameter because it is reserved for associated items
+
+parse_unexpected_default_value_for_lifetime_in_generic_parameters = unexpected default lifetime parameter
+ .label = lifetime parameters cannot have default values
+
+parse_multiple_where_clauses = cannot define duplicate `where` clauses on an item
+ .label = previous `where` clause starts here
+ .suggestion = consider joining the two `where` clauses into one
+
+parse_nonterminal_expected_item_keyword = expected an item keyword
+parse_nonterminal_expected_statement = expected a statement
+parse_nonterminal_expected_ident = expected ident, found `{$token}`
+parse_nonterminal_expected_lifetime = expected a lifetime, found `{$token}`
+
+parse_or_pattern_not_allowed_in_let_binding = top-level or-patterns are not allowed in `let` bindings
+parse_or_pattern_not_allowed_in_fn_parameters = top-level or-patterns are not allowed in function parameters
+parse_sugg_remove_leading_vert_in_pattern = remove the `|`
+parse_sugg_wrap_pattern_in_parens = wrap the pattern in parentheses
+
+parse_note_pattern_alternatives_use_single_vert = alternatives in or-patterns are separated with `|`, not `||`
+
+parse_unexpected_vert_vert_before_function_parameter = unexpected `||` before function parameter
+ .suggestion = remove the `||`
+
+parse_label_while_parsing_or_pattern_here = while parsing this or-pattern starting here
+
+parse_unexpected_vert_vert_in_pattern = unexpected token `||` in pattern
+ .suggestion = use a single `|` to separate multiple alternative patterns
+
+parse_trailing_vert_not_allowed = a trailing `|` is not allowed in an or-pattern
+ .suggestion = remove the `{$token}`
+
+parse_dotdotdot_rest_pattern = unexpected `...`
+ .label = not a valid pattern
+ .suggestion = for a rest pattern, use `..` instead of `...`
+
+parse_pattern_on_wrong_side_of_at = pattern on wrong side of `@`
+ .label_pattern = pattern on the left, should be on the right
+ .label_binding = binding on the right, should be on the left
+ .suggestion = switch the order
+
+parse_expected_binding_left_of_at = left-hand side of `@` must be a binding
+ .label_lhs = interpreted as a pattern, not a binding
+ .label_rhs = also a pattern
+ .note = bindings are `x`, `mut x`, `ref x`, and `ref mut x`
+
+parse_ambiguous_range_pattern = the range pattern here has ambiguous interpretation
+ .suggestion = add parentheses to clarify the precedence
+
+parse_unexpected_lifetime_in_pattern = unexpected lifetime `{$symbol}` in pattern
+ .suggestion = remove the lifetime
+
+parse_ref_mut_order_incorrect = the order of `mut` and `ref` is incorrect
+ .suggestion = try switching the order
+
+parse_mut_on_nested_ident_pattern = `mut` must be attached to each individual binding
+ .suggestion = add `mut` to each binding
+parse_mut_on_non_ident_pattern = `mut` must be followed by a named binding
+ .suggestion = remove the `mut` prefix
+parse_note_mut_pattern_usage = `mut` may be followed by `variable` and `variable @ pattern`
+
+parse_repeated_mut_in_pattern = `mut` on a binding may not be repeated
+ .suggestion = remove the additional `mut`s
+
+parse_dot_dot_dot_range_to_pattern_not_allowed = range-to patterns with `...` are not allowed
+ .suggestion = use `..=` instead
+
+parse_enum_pattern_instead_of_identifier = expected identifier, found enum pattern
+
+parse_dot_dot_dot_for_remaining_fields = expected field pattern, found `{$token_str}`
+ .suggestion = to omit remaining fields, use `..`
+
+parse_expected_comma_after_pattern_field = expected `,`
+
+parse_return_types_use_thin_arrow = return types are denoted using `->`
+ .suggestion = use `->` instead
+
+parse_need_plus_after_trait_object_lifetime = lifetime in trait object type must be followed by `+`
+
+parse_expected_mut_or_const_in_raw_pointer_type = expected `mut` or `const` keyword in raw pointer type
+ .suggestion = add `mut` or `const` here
+
+parse_lifetime_after_mut = lifetime must precede `mut`
+ .suggestion = place the lifetime before `mut`
+
+parse_dyn_after_mut = `mut` must precede `dyn`
+ .suggestion = place `mut` before `dyn`
+
+parse_fn_pointer_cannot_be_const = an `fn` pointer type cannot be `const`
+ .label = `const` because of this
+ .suggestion = remove the `const` qualifier
+
+parse_fn_pointer_cannot_be_async = an `fn` pointer type cannot be `async`
+ .label = `async` because of this
+ .suggestion = remove the `async` qualifier
+
+parse_nested_c_variadic_type = C-variadic type `...` may not be nested inside another type
+
+parse_invalid_dyn_keyword = invalid `dyn` keyword
+ .help = `dyn` is only needed at the start of a trait `+`-separated list
+ .suggestion = remove this keyword
+
+parse_negative_bounds_not_supported = negative bounds are not supported
+ .label = negative bounds are not supported
+ .suggestion = {$num_bounds ->
+ [one] remove the bound
+ *[other] remove the bounds
+ }
+
+parse_help_set_edition_cargo = set `edition = "{$edition}"` in `Cargo.toml`
+parse_help_set_edition_standalone = pass `--edition {$edition}` to `rustc`
+parse_note_edition_guide = for more on editions, read https://doc.rust-lang.org/edition-guide
+
+parse_unexpected_token_after_dot = unexpected token: `{$actual}`
+
+parse_cannot_be_raw_ident = `{$ident}` cannot be a raw identifier
+
+parse_cr_doc_comment = bare CR not allowed in {$block ->
+ [true] block doc-comment
+ *[false] doc-comment
+}
+
+parse_no_digits_literal = no valid digits found for number
+
+parse_invalid_digit_literal = invalid digit for a base {$base} literal
+
+parse_empty_exponent_float = expected at least one digit in exponent
+
+parse_float_literal_unsupported_base = {$base} float literal is not supported
+
+parse_more_than_one_char = character literal may only contain one codepoint
+ .followed_by = this `{$chr}` is followed by the combining {$len ->
+ [one] mark
+ *[other] marks
+ } `{$escaped_marks}`
+ .non_printing = there are non-printing characters, the full sequence is `{$escaped}`
+ .consider_normalized = consider using the normalized form `{$ch}` of this character
+ .remove_non = consider removing the non-printing characters
+ .use_double_quotes = if you meant to write a {$is_byte ->
+ [true] byte string
+ *[false] `str`
+ } literal, use double quotes
+
+parse_no_brace_unicode_escape = incorrect unicode escape sequence
+ .label = {parse_no_brace_unicode_escape}
+ .use_braces = format of unicode escape sequences uses braces
+ .format_of_unicode = format of unicode escape sequences is `\u{"{...}"}`
+
+parse_invalid_unicode_escape = invalid unicode character escape
+ .label = invalid escape
+ .help = unicode escape must {$surrogate ->
+ [true] not be a surrogate
+ *[false] be at most 10FFFF
+ }
+
+parse_escape_only_char = {$byte ->
+ [true] byte
+ *[false] character
+ } constant must be escaped: `{$escaped_msg}`
+ .escape = escape the character
+
+parse_bare_cr = {$double_quotes ->
+ [true] bare CR not allowed in string, use `\r` instead
+ *[false] character constant must be escaped: `\r`
+ }
+ .escape = escape the character
+
+parse_bare_cr_in_raw_string = bare CR not allowed in raw string
+
+parse_too_short_hex_escape = numeric character escape is too short
+
+parse_invalid_char_in_escape = {parse_invalid_char_in_escape_msg}: `{$ch}`
+ .label = {parse_invalid_char_in_escape_msg}
+
+parse_invalid_char_in_escape_msg = invalid character in {$is_hex ->
+ [true] numeric character
+ *[false] unicode
+ } escape
+
+parse_out_of_range_hex_escape = out of range hex escape
+ .label = must be a character in the range [\x00-\x7f]
+
+parse_leading_underscore_unicode_escape = {parse_leading_underscore_unicode_escape_label}: `_`
+parse_leading_underscore_unicode_escape_label = invalid start of unicode escape
+
+parse_overlong_unicode_escape = overlong unicode escape
+ .label = must have at most 6 hex digits
+
+parse_unclosed_unicode_escape = unterminated unicode escape
+ .label = missing a closing `{"}"}`
+ .terminate = terminate the unicode escape
+
+parse_unicode_escape_in_byte = unicode escape in byte string
+ .label = {parse_unicode_escape_in_byte}
+ .help = unicode escape sequences cannot be used as a byte or in a byte string
+
+parse_empty_unicode_escape = empty unicode escape
+ .label = this escape must have at least 1 hex digit
+
+parse_zero_chars = empty character literal
+ .label = {parse_zero_chars}
+
+parse_lone_slash = invalid trailing slash in literal
+ .label = {parse_lone_slash}
+
+parse_unskipped_whitespace = non-ASCII whitespace symbol '{$ch}' is not skipped
+ .label = {parse_unskipped_whitespace}
+
+parse_multiple_skipped_lines = multiple lines skipped by escaped newline
+ .label = skipping everything up to and including this point
+
+parse_unknown_prefix = prefix `{$prefix}` is unknown
+ .label = unknown prefix
+ .note = prefixed identifiers and literals are reserved since Rust 2021
+ .suggestion_br = use `br` for a raw byte string
+ .suggestion_whitespace = consider inserting whitespace here
+
+parse_too_many_hashes = too many `#` symbols: raw strings may be delimited by up to 255 `#` symbols, but found {$num}
+
+parse_unknown_start_of_token = unknown start of token: {$escaped}
+ .sugg_quotes = Unicode characters '“' (Left Double Quotation Mark) and '”' (Right Double Quotation Mark) look like '{$ascii_str}' ({$ascii_name}), but are not
+ .sugg_other = Unicode character '{$ch}' ({$u_name}) looks like '{$ascii_str}' ({$ascii_name}), but it is not
+ .help_null = source files must contain UTF-8 encoded text, unexpected null bytes might occur when a different encoding is used
+ .note_repeats = character appears {$repeats ->
+ [one] once more
+ *[other] {$repeats} more times
+ }
diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs
index 06b970ad9..1662db36d 100644
--- a/compiler/rustc_parse/src/errors.rs
+++ b/compiler/rustc_parse/src/errors.rs
@@ -1,11 +1,15 @@
+use std::borrow::Cow;
+
use rustc_ast::token::Token;
-use rustc_ast::Path;
-use rustc_errors::{fluent, AddToDiagnostic, Applicability, EmissionGuarantee, IntoDiagnostic};
+use rustc_ast::{Path, Visibility};
+use rustc_errors::{AddToDiagnostic, Applicability, EmissionGuarantee, IntoDiagnostic};
use rustc_macros::{Diagnostic, Subdiagnostic};
use rustc_session::errors::ExprParenthesesNeeded;
+use rustc_span::edition::{Edition, LATEST_STABLE_EDITION};
use rustc_span::symbol::Ident;
use rustc_span::{Span, Symbol};
+use crate::fluent_generated as fluent;
use crate::parser::TokenDescription;
#[derive(Diagnostic)]
@@ -75,7 +79,7 @@ pub(crate) struct IncorrectSemicolon<'a> {
#[diag(parse_incorrect_use_of_await)]
pub(crate) struct IncorrectUseOfAwait {
#[primary_span]
- #[suggestion(parentheses_suggestion, code = "", applicability = "machine-applicable")]
+ #[suggestion(parse_parentheses_suggestion, code = "", applicability = "machine-applicable")]
pub span: Span,
}
@@ -84,7 +88,7 @@ pub(crate) struct IncorrectUseOfAwait {
pub(crate) struct IncorrectAwait {
#[primary_span]
pub span: Span,
- #[suggestion(postfix_suggestion, code = "{expr}.await{question_mark}")]
+ #[suggestion(parse_postfix_suggestion, code = "{expr}.await{question_mark}")]
pub sugg_span: (Span, Applicability),
pub expr: String,
pub question_mark: &'static str,
@@ -137,7 +141,7 @@ pub(crate) struct InvalidComparisonOperator {
#[derive(Subdiagnostic)]
pub(crate) enum InvalidComparisonOperatorSub {
#[suggestion(
- use_instead,
+ parse_use_instead,
style = "short",
applicability = "machine-applicable",
code = "{correct}"
@@ -148,7 +152,7 @@ pub(crate) enum InvalidComparisonOperatorSub {
invalid: String,
correct: String,
},
- #[label(spaceship_operator_invalid)]
+ #[label(parse_spaceship_operator_invalid)]
Spaceship(#[primary_span] Span),
}
@@ -166,14 +170,14 @@ pub(crate) struct InvalidLogicalOperator {
#[derive(Subdiagnostic)]
pub(crate) enum InvalidLogicalOperatorSub {
#[suggestion(
- use_amp_amp_for_conjunction,
+ parse_use_amp_amp_for_conjunction,
style = "short",
applicability = "machine-applicable",
code = "&&"
)]
Conjunction(#[primary_span] Span),
#[suggestion(
- use_pipe_pipe_for_disjunction,
+ parse_use_pipe_pipe_for_disjunction,
style = "short",
applicability = "machine-applicable",
code = "||"
@@ -259,14 +263,14 @@ pub(crate) struct UnexpectedTokenAfterLabel {
#[primary_span]
#[label(parse_unexpected_token_after_label)]
pub span: Span,
- #[suggestion(suggestion_remove_label, style = "verbose", code = "")]
+ #[suggestion(parse_suggestion_remove_label, style = "verbose", code = "")]
pub remove_label: Option<Span>,
#[subdiagnostic]
pub enclose_in_block: Option<UnexpectedTokenAfterLabelSugg>,
}
#[derive(Subdiagnostic)]
-#[multipart_suggestion(suggestion_enclose_in_block, applicability = "machine-applicable")]
+#[multipart_suggestion(parse_suggestion_enclose_in_block, applicability = "machine-applicable")]
pub(crate) struct UnexpectedTokenAfterLabelSugg {
#[suggestion_part(code = "{{ ")]
pub left: Span,
@@ -337,24 +341,33 @@ pub(crate) struct IfExpressionMissingThenBlock {
#[primary_span]
pub if_span: Span,
#[subdiagnostic]
- pub sub: IfExpressionMissingThenBlockSub,
+ pub missing_then_block_sub: IfExpressionMissingThenBlockSub,
+ #[subdiagnostic]
+ pub let_else_sub: Option<IfExpressionLetSomeSub>,
}
#[derive(Subdiagnostic)]
pub(crate) enum IfExpressionMissingThenBlockSub {
- #[help(condition_possibly_unfinished)]
+ #[help(parse_condition_possibly_unfinished)]
UnfinishedCondition(#[primary_span] Span),
- #[help(add_then_block)]
+ #[help(parse_add_then_block)]
AddThenBlock(#[primary_span] Span),
}
+#[derive(Subdiagnostic)]
+#[suggestion(parse_extra_if_in_let_else, applicability = "maybe-incorrect", code = "")]
+pub(crate) struct IfExpressionLetSomeSub {
+ #[primary_span]
+ pub if_span: Span,
+}
+
#[derive(Diagnostic)]
#[diag(parse_if_expression_missing_condition)]
pub(crate) struct IfExpressionMissingCondition {
#[primary_span]
- #[label(condition_label)]
+ #[label(parse_condition_label)]
pub if_span: Span,
- #[label(block_label)]
+ #[label(parse_block_label)]
pub block_span: Span,
}
@@ -392,10 +405,10 @@ pub(crate) struct OuterAttributeNotAllowedOnIfElse {
#[primary_span]
pub last: Span,
- #[label(branch_label)]
+ #[label(parse_branch_label)]
pub branch_span: Span,
- #[label(ctx_label)]
+ #[label(parse_ctx_label)]
pub ctx_span: Span,
pub ctx: String,
@@ -415,13 +428,41 @@ pub(crate) struct MissingInInForLoop {
#[derive(Subdiagnostic)]
pub(crate) enum MissingInInForLoopSub {
// Has been misleading, at least in the past (closed Issue #48492), thus maybe-incorrect
- #[suggestion(use_in_not_of, style = "short", applicability = "maybe-incorrect", code = "in")]
+ #[suggestion(
+ parse_use_in_not_of,
+ style = "short",
+ applicability = "maybe-incorrect",
+ code = "in"
+ )]
InNotOf(#[primary_span] Span),
- #[suggestion(add_in, style = "short", applicability = "maybe-incorrect", code = " in ")]
+ #[suggestion(parse_add_in, style = "short", applicability = "maybe-incorrect", code = " in ")]
AddIn(#[primary_span] Span),
}
#[derive(Diagnostic)]
+#[diag(parse_missing_expression_in_for_loop)]
+pub(crate) struct MissingExpressionInForLoop {
+ #[primary_span]
+ #[suggestion(
+ code = "/* expression */ ",
+ applicability = "has-placeholders",
+ style = "verbose"
+ )]
+ pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(parse_loop_else)]
+#[note]
+pub(crate) struct LoopElseNotSupported {
+ #[primary_span]
+ pub span: Span,
+ pub loop_kind: &'static str,
+ #[label(parse_loop_keyword)]
+ pub loop_kw: Span,
+}
+
+#[derive(Diagnostic)]
#[diag(parse_missing_comma_after_match_arm)]
pub(crate) struct MissingCommaAfterMatchArm {
#[primary_span]
@@ -460,8 +501,8 @@ pub(crate) struct EqFieldInit {
#[diag(parse_dotdotdot)]
pub(crate) struct DotDotDot {
#[primary_span]
- #[suggestion(suggest_exclusive_range, applicability = "maybe-incorrect", code = "..")]
- #[suggestion(suggest_inclusive_range, applicability = "maybe-incorrect", code = "..=")]
+ #[suggestion(parse_suggest_exclusive_range, applicability = "maybe-incorrect", code = "..")]
+ #[suggestion(parse_suggest_inclusive_range, applicability = "maybe-incorrect", code = "..=")]
pub span: Span,
}
@@ -501,10 +542,10 @@ pub(crate) struct UseEmptyBlockNotSemi {
#[diag(parse_comparison_interpreted_as_generic)]
pub(crate) struct ComparisonInterpretedAsGeneric {
#[primary_span]
- #[label(label_comparison)]
+ #[label(parse_label_comparison)]
pub comparison: Span,
pub r#type: Path,
- #[label(label_args)]
+ #[label(parse_label_args)]
pub args: Span,
#[subdiagnostic]
pub suggestion: ComparisonOrShiftInterpretedAsGenericSugg,
@@ -514,17 +555,17 @@ pub(crate) struct ComparisonInterpretedAsGeneric {
#[diag(parse_shift_interpreted_as_generic)]
pub(crate) struct ShiftInterpretedAsGeneric {
#[primary_span]
- #[label(label_comparison)]
+ #[label(parse_label_comparison)]
pub shift: Span,
pub r#type: Path,
- #[label(label_args)]
+ #[label(parse_label_args)]
pub args: Span,
#[subdiagnostic]
pub suggestion: ComparisonOrShiftInterpretedAsGenericSugg,
}
#[derive(Subdiagnostic)]
-#[multipart_suggestion(suggestion, applicability = "machine-applicable")]
+#[multipart_suggestion(parse_suggestion, applicability = "machine-applicable")]
pub(crate) struct ComparisonOrShiftInterpretedAsGenericSugg {
#[suggestion_part(code = "(")]
pub left: Span,
@@ -550,7 +591,7 @@ pub(crate) struct LeadingPlusNotSupported {
#[label]
pub span: Span,
#[suggestion(
- suggestion_remove_plus,
+ parse_suggestion_remove_plus,
style = "verbose",
code = "",
applicability = "machine-applicable"
@@ -573,7 +614,7 @@ pub(crate) struct ParenthesesWithStructFields {
}
#[derive(Subdiagnostic)]
-#[multipart_suggestion(suggestion_braces_for_struct, applicability = "maybe-incorrect")]
+#[multipart_suggestion(parse_suggestion_braces_for_struct, applicability = "maybe-incorrect")]
pub(crate) struct BracesForStructLiteral {
#[suggestion_part(code = " {{ ")]
pub first: Span,
@@ -582,7 +623,7 @@ pub(crate) struct BracesForStructLiteral {
}
#[derive(Subdiagnostic)]
-#[multipart_suggestion(suggestion_no_fields_for_fn, applicability = "maybe-incorrect")]
+#[multipart_suggestion(parse_suggestion_no_fields_for_fn, applicability = "maybe-incorrect")]
pub(crate) struct NoFieldsForFnCall {
#[suggestion_part(code = "")]
pub fields: Vec<Span>,
@@ -619,7 +660,7 @@ pub(crate) struct ArrayBracketsInsteadOfSpaces {
}
#[derive(Subdiagnostic)]
-#[multipart_suggestion(suggestion, applicability = "maybe-incorrect")]
+#[multipart_suggestion(parse_suggestion, applicability = "maybe-incorrect")]
pub(crate) struct ArrayBracketsInsteadOfSpacesSugg {
#[suggestion_part(code = "[")]
pub left: Span,
@@ -631,18 +672,57 @@ pub(crate) struct ArrayBracketsInsteadOfSpacesSugg {
#[diag(parse_match_arm_body_without_braces)]
pub(crate) struct MatchArmBodyWithoutBraces {
#[primary_span]
- #[label(label_statements)]
+ #[label(parse_label_statements)]
pub statements: Span,
- #[label(label_arrow)]
+ #[label(parse_label_arrow)]
pub arrow: Span,
pub num_statements: usize,
#[subdiagnostic]
pub sub: MatchArmBodyWithoutBracesSugg,
}
+#[derive(Diagnostic)]
+#[diag(parse_inclusive_range_extra_equals)]
+#[note]
+pub(crate) struct InclusiveRangeExtraEquals {
+ #[primary_span]
+ #[suggestion(
+ parse_suggestion_remove_eq,
+ style = "short",
+ code = "..=",
+ applicability = "maybe-incorrect"
+ )]
+ pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(parse_inclusive_range_match_arrow)]
+pub(crate) struct InclusiveRangeMatchArrow {
+ #[primary_span]
+ pub arrow: Span,
+ #[label]
+ pub span: Span,
+ #[suggestion(style = "verbose", code = " ", applicability = "machine-applicable")]
+ pub after_pat: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(parse_inclusive_range_no_end, code = "E0586")]
+#[note]
+pub(crate) struct InclusiveRangeNoEnd {
+ #[primary_span]
+ #[suggestion(
+ parse_suggestion_open_range,
+ code = "..",
+ applicability = "machine-applicable",
+ style = "short"
+ )]
+ pub span: Span,
+}
+
#[derive(Subdiagnostic)]
pub(crate) enum MatchArmBodyWithoutBracesSugg {
- #[multipart_suggestion(suggestion_add_braces, applicability = "machine-applicable")]
+ #[multipart_suggestion(parse_suggestion_add_braces, applicability = "machine-applicable")]
AddBraces {
#[suggestion_part(code = "{{ ")]
left: Span,
@@ -650,7 +730,7 @@ pub(crate) enum MatchArmBodyWithoutBracesSugg {
right: Span,
},
#[suggestion(
- suggestion_use_comma_not_semicolon,
+ parse_suggestion_use_comma_not_semicolon,
code = ",",
applicability = "machine-applicable"
)]
@@ -670,7 +750,7 @@ pub(crate) struct StructLiteralNotAllowedHere {
}
#[derive(Subdiagnostic)]
-#[multipart_suggestion(suggestion, applicability = "machine-applicable")]
+#[multipart_suggestion(parse_suggestion, applicability = "machine-applicable")]
pub(crate) struct StructLiteralNotAllowedHereSugg {
#[suggestion_part(code = "(")]
pub left: Span,
@@ -692,9 +772,9 @@ pub(crate) struct InvalidLiteralSuffixOnTupleIndex {
#[label]
pub span: Span,
pub suffix: Symbol,
- #[help(tuple_exception_line_1)]
- #[help(tuple_exception_line_2)]
- #[help(tuple_exception_line_3)]
+ #[help(parse_tuple_exception_line_1)]
+ #[help(parse_tuple_exception_line_2)]
+ #[help(parse_tuple_exception_line_3)]
pub exception: Option<()>,
}
@@ -712,11 +792,11 @@ pub(crate) struct MismatchedClosingDelimiter {
#[primary_span]
pub spans: Vec<Span>,
pub delimiter: String,
- #[label(label_unmatched)]
+ #[label(parse_label_unmatched)]
pub unmatched: Span,
- #[label(label_opening_candidate)]
+ #[label(parse_label_opening_candidate)]
pub opening_candidate: Option<Span>,
- #[label(label_unclosed)]
+ #[label(parse_label_unclosed)]
pub unclosed: Option<Span>,
}
@@ -867,7 +947,7 @@ impl<'a, G: EmissionGuarantee> IntoDiagnostic<'a, G> for ExpectedIdentifier {
self,
handler: &'a rustc_errors::Handler,
) -> rustc_errors::DiagnosticBuilder<'a, G> {
- let token_descr = super::parser::TokenDescription::from_token(&self.token);
+ let token_descr = TokenDescription::from_token(&self.token);
let mut diag = handler.struct_diagnostic(match token_descr {
Some(TokenDescription::ReservedIdentifier) => {
@@ -913,7 +993,7 @@ impl<'a, G: EmissionGuarantee> IntoDiagnostic<'a, G> for ExpectedSemi {
self,
handler: &'a rustc_errors::Handler,
) -> rustc_errors::DiagnosticBuilder<'a, G> {
- let token_descr = super::parser::TokenDescription::from_token(&self.token);
+ let token_descr = TokenDescription::from_token(&self.token);
let mut diag = handler.struct_diagnostic(match token_descr {
Some(TokenDescription::ReservedIdentifier) => {
@@ -962,7 +1042,7 @@ pub(crate) struct StructLiteralBodyWithoutPath {
}
#[derive(Subdiagnostic)]
-#[multipart_suggestion(suggestion, applicability = "has-placeholders")]
+#[multipart_suggestion(parse_suggestion, applicability = "has-placeholders")]
pub(crate) struct StructLiteralBodyWithoutPathSugg {
#[suggestion_part(code = "{{ SomeStruct ")]
pub before: Span,
@@ -980,7 +1060,7 @@ pub(crate) struct StructLiteralNeedingParens {
}
#[derive(Subdiagnostic)]
-#[multipart_suggestion(suggestion, applicability = "machine-applicable")]
+#[multipart_suggestion(parse_suggestion, applicability = "machine-applicable")]
pub(crate) struct StructLiteralNeedingParensSugg {
#[suggestion_part(code = "(")]
pub before: Span,
@@ -1007,7 +1087,7 @@ pub(crate) struct GenericParamsWithoutAngleBrackets {
}
#[derive(Subdiagnostic)]
-#[multipart_suggestion(suggestion, applicability = "machine-applicable")]
+#[multipart_suggestion(parse_suggestion, applicability = "machine-applicable")]
pub(crate) struct GenericParamsWithoutAngleBracketsSugg {
#[suggestion_part(code = "<")]
pub left: Span,
@@ -1028,7 +1108,7 @@ pub(crate) struct ComparisonOperatorsCannotBeChained {
)]
pub suggest_turbofish: Option<Span>,
#[help(parse_sugg_turbofish_syntax)]
- #[help(sugg_parentheses_for_function_args)]
+ #[help(parse_sugg_parentheses_for_function_args)]
pub help_turbofish: Option<()>,
#[subdiagnostic]
pub chaining_sugg: Option<ComparisonOperatorsCannotBeChainedSugg>,
@@ -1037,7 +1117,7 @@ pub(crate) struct ComparisonOperatorsCannotBeChained {
#[derive(Subdiagnostic)]
pub(crate) enum ComparisonOperatorsCannotBeChainedSugg {
#[suggestion(
- sugg_split_comparison,
+ parse_sugg_split_comparison,
style = "verbose",
code = " && {middle_term}",
applicability = "maybe-incorrect"
@@ -1047,7 +1127,7 @@ pub(crate) enum ComparisonOperatorsCannotBeChainedSugg {
span: Span,
middle_term: String,
},
- #[multipart_suggestion(sugg_parenthesize, applicability = "maybe-incorrect")]
+ #[multipart_suggestion(parse_sugg_parenthesize, applicability = "maybe-incorrect")]
Parenthesize {
#[suggestion_part(code = "(")]
left: Span,
@@ -1067,7 +1147,7 @@ pub(crate) struct QuestionMarkInType {
}
#[derive(Subdiagnostic)]
-#[multipart_suggestion(suggestion, applicability = "machine-applicable")]
+#[multipart_suggestion(parse_suggestion, applicability = "machine-applicable")]
pub(crate) struct QuestionMarkInTypeSugg {
#[suggestion_part(code = "Option<")]
pub left: Span,
@@ -1085,7 +1165,7 @@ pub(crate) struct ParenthesesInForHead {
}
#[derive(Subdiagnostic)]
-#[multipart_suggestion(suggestion, applicability = "machine-applicable")]
+#[multipart_suggestion(parse_suggestion, applicability = "machine-applicable")]
pub(crate) struct ParenthesesInForHeadSugg {
#[suggestion_part(code = "{left_snippet}")]
pub left: Span,
@@ -1145,7 +1225,7 @@ pub(crate) struct ConstGenericWithoutBraces {
}
#[derive(Subdiagnostic)]
-#[multipart_suggestion(suggestion, applicability = "machine-applicable")]
+#[multipart_suggestion(parse_suggestion, applicability = "machine-applicable")]
pub(crate) struct ConstGenericWithoutBracesSugg {
#[suggestion_part(code = "{{ ")]
pub left: Span,
@@ -1165,7 +1245,7 @@ pub(crate) struct UnexpectedConstParamDeclaration {
#[derive(Subdiagnostic)]
pub(crate) enum UnexpectedConstParamDeclarationSugg {
- #[multipart_suggestion(suggestion, applicability = "machine-applicable")]
+ #[multipart_suggestion(parse_suggestion, applicability = "machine-applicable")]
AddParam {
#[suggestion_part(code = "<{snippet}>")]
impl_generics: Span,
@@ -1174,7 +1254,7 @@ pub(crate) enum UnexpectedConstParamDeclarationSugg {
snippet: String,
ident: String,
},
- #[multipart_suggestion(suggestion, applicability = "machine-applicable")]
+ #[multipart_suggestion(parse_suggestion, applicability = "machine-applicable")]
AppendParam {
#[suggestion_part(code = ", {snippet}")]
impl_generics_end: Span,
@@ -1221,7 +1301,7 @@ pub(crate) struct FnPtrWithGenerics {
}
#[derive(Subdiagnostic)]
-#[multipart_suggestion(suggestion, applicability = "maybe-incorrect")]
+#[multipart_suggestion(parse_suggestion, applicability = "maybe-incorrect")]
pub(crate) struct FnPtrWithGenericsSugg {
#[suggestion_part(code = "{snippet}")]
pub left: Span,
@@ -1262,16 +1342,16 @@ pub(crate) struct WhereClauseBeforeTupleStructBody {
#[primary_span]
#[label]
pub span: Span,
- #[label(name_label)]
+ #[label(parse_name_label)]
pub name: Span,
- #[label(body_label)]
+ #[label(parse_body_label)]
pub body: Span,
#[subdiagnostic]
pub sugg: Option<WhereClauseBeforeTupleStructBodySugg>,
}
#[derive(Subdiagnostic)]
-#[multipart_suggestion(suggestion, applicability = "machine-applicable")]
+#[multipart_suggestion(parse_suggestion, applicability = "machine-applicable")]
pub(crate) struct WhereClauseBeforeTupleStructBodySugg {
#[suggestion_part(code = "{snippet}")]
pub left: Span,
@@ -1279,3 +1359,943 @@ pub(crate) struct WhereClauseBeforeTupleStructBodySugg {
#[suggestion_part(code = "")]
pub right: Span,
}
+
+#[derive(Diagnostic)]
+#[diag(parse_async_fn_in_2015, code = "E0670")]
+pub(crate) struct AsyncFnIn2015 {
+ #[primary_span]
+ #[label]
+ pub span: Span,
+ #[subdiagnostic]
+ pub help: HelpUseLatestEdition,
+}
+
+#[derive(Subdiagnostic)]
+#[label(parse_async_block_in_2015)]
+pub(crate) struct AsyncBlockIn2015 {
+ #[primary_span]
+ pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(parse_self_argument_pointer)]
+pub(crate) struct SelfArgumentPointer {
+ #[primary_span]
+ #[label]
+ pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(parse_unexpected_token_after_dot)]
+pub struct UnexpectedTokenAfterDot<'a> {
+ #[primary_span]
+ pub span: Span,
+ pub actual: Cow<'a, str>,
+}
+
+#[derive(Diagnostic)]
+#[diag(parse_visibility_not_followed_by_item)]
+#[help]
+pub(crate) struct VisibilityNotFollowedByItem {
+ #[primary_span]
+ #[label]
+ pub span: Span,
+ pub vis: Visibility,
+}
+
+#[derive(Diagnostic)]
+#[diag(parse_default_not_followed_by_item)]
+#[note]
+pub(crate) struct DefaultNotFollowedByItem {
+ #[primary_span]
+ #[label]
+ pub span: Span,
+}
+
+#[derive(Diagnostic)]
+pub(crate) enum MissingKeywordForItemDefinition {
+ #[diag(parse_missing_struct_for_struct_definition)]
+ Struct {
+ #[primary_span]
+ #[suggestion(style = "short", applicability = "maybe-incorrect", code = " struct ")]
+ span: Span,
+ ident: Ident,
+ },
+ #[diag(parse_missing_fn_for_function_definition)]
+ Function {
+ #[primary_span]
+ #[suggestion(style = "short", applicability = "maybe-incorrect", code = " fn ")]
+ span: Span,
+ ident: Ident,
+ },
+ #[diag(parse_missing_fn_for_method_definition)]
+ Method {
+ #[primary_span]
+ #[suggestion(style = "short", applicability = "maybe-incorrect", code = " fn ")]
+ span: Span,
+ ident: Ident,
+ },
+ #[diag(parse_ambiguous_missing_keyword_for_item_definition)]
+ Ambiguous {
+ #[primary_span]
+ span: Span,
+ #[subdiagnostic]
+ subdiag: Option<AmbiguousMissingKwForItemSub>,
+ },
+}
+
+#[derive(Subdiagnostic)]
+pub(crate) enum AmbiguousMissingKwForItemSub {
+ #[suggestion(parse_suggestion, applicability = "maybe-incorrect", code = "{snippet}!")]
+ SuggestMacro {
+ #[primary_span]
+ span: Span,
+ snippet: String,
+ },
+ #[help(parse_help)]
+ HelpMacro,
+}
+
+#[derive(Diagnostic)]
+#[diag(parse_missing_trait_in_trait_impl)]
+pub(crate) struct MissingTraitInTraitImpl {
+ #[primary_span]
+ #[suggestion(parse_suggestion_add_trait, code = " Trait ", applicability = "has-placeholders")]
+ pub span: Span,
+ #[suggestion(parse_suggestion_remove_for, code = "", applicability = "maybe-incorrect")]
+ pub for_span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(parse_missing_for_in_trait_impl)]
+pub(crate) struct MissingForInTraitImpl {
+ #[primary_span]
+ #[suggestion(style = "short", code = " for ", applicability = "machine-applicable")]
+ pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(parse_expected_trait_in_trait_impl_found_type)]
+pub(crate) struct ExpectedTraitInTraitImplFoundType {
+ #[primary_span]
+ pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(parse_bounds_not_allowed_on_trait_aliases)]
+pub(crate) struct BoundsNotAllowedOnTraitAliases {
+ #[primary_span]
+ pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(parse_trait_alias_cannot_be_auto)]
+pub(crate) struct TraitAliasCannotBeAuto {
+ #[primary_span]
+ #[label(parse_trait_alias_cannot_be_auto)]
+ pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(parse_trait_alias_cannot_be_unsafe)]
+pub(crate) struct TraitAliasCannotBeUnsafe {
+ #[primary_span]
+ #[label(parse_trait_alias_cannot_be_unsafe)]
+ pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(parse_associated_static_item_not_allowed)]
+pub(crate) struct AssociatedStaticItemNotAllowed {
+ #[primary_span]
+ pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(parse_extern_crate_name_with_dashes)]
+pub(crate) struct ExternCrateNameWithDashes {
+ #[primary_span]
+ #[label]
+ pub span: Span,
+ #[subdiagnostic]
+ pub sugg: ExternCrateNameWithDashesSugg,
+}
+
+#[derive(Subdiagnostic)]
+#[multipart_suggestion(parse_suggestion, applicability = "machine-applicable")]
+pub(crate) struct ExternCrateNameWithDashesSugg {
+ #[suggestion_part(code = "_")]
+ pub dashes: Vec<Span>,
+}
+
+#[derive(Diagnostic)]
+#[diag(parse_extern_item_cannot_be_const)]
+#[note]
+pub(crate) struct ExternItemCannotBeConst {
+ #[primary_span]
+ pub ident_span: Span,
+ #[suggestion(code = "static ", applicability = "machine-applicable")]
+ pub const_span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(parse_const_global_cannot_be_mutable)]
+pub(crate) struct ConstGlobalCannotBeMutable {
+ #[primary_span]
+ #[label]
+ pub ident_span: Span,
+ #[suggestion(code = "static", applicability = "maybe-incorrect")]
+ pub const_span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(parse_missing_const_type)]
+pub(crate) struct MissingConstType {
+ #[primary_span]
+ #[suggestion(code = "{colon} <type>", applicability = "has-placeholders")]
+ pub span: Span,
+
+ pub kind: &'static str,
+ pub colon: &'static str,
+}
+
+#[derive(Diagnostic)]
+#[diag(parse_enum_struct_mutually_exclusive)]
+pub(crate) struct EnumStructMutuallyExclusive {
+ #[primary_span]
+ #[suggestion(code = "enum", applicability = "machine-applicable")]
+ pub span: Span,
+}
+
+#[derive(Diagnostic)]
+pub(crate) enum UnexpectedTokenAfterStructName {
+ #[diag(parse_unexpected_token_after_struct_name_found_reserved_identifier)]
+ ReservedIdentifier {
+ #[primary_span]
+ #[label(parse_unexpected_token_after_struct_name)]
+ span: Span,
+ token: Token,
+ },
+ #[diag(parse_unexpected_token_after_struct_name_found_keyword)]
+ Keyword {
+ #[primary_span]
+ #[label(parse_unexpected_token_after_struct_name)]
+ span: Span,
+ token: Token,
+ },
+ #[diag(parse_unexpected_token_after_struct_name_found_reserved_keyword)]
+ ReservedKeyword {
+ #[primary_span]
+ #[label(parse_unexpected_token_after_struct_name)]
+ span: Span,
+ token: Token,
+ },
+ #[diag(parse_unexpected_token_after_struct_name_found_doc_comment)]
+ DocComment {
+ #[primary_span]
+ #[label(parse_unexpected_token_after_struct_name)]
+ span: Span,
+ token: Token,
+ },
+ #[diag(parse_unexpected_token_after_struct_name_found_other)]
+ Other {
+ #[primary_span]
+ #[label(parse_unexpected_token_after_struct_name)]
+ span: Span,
+ token: Token,
+ },
+}
+
+impl UnexpectedTokenAfterStructName {
+ pub fn new(span: Span, token: Token) -> Self {
+ match TokenDescription::from_token(&token) {
+ Some(TokenDescription::ReservedIdentifier) => Self::ReservedIdentifier { span, token },
+ Some(TokenDescription::Keyword) => Self::Keyword { span, token },
+ Some(TokenDescription::ReservedKeyword) => Self::ReservedKeyword { span, token },
+ Some(TokenDescription::DocComment) => Self::DocComment { span, token },
+ None => Self::Other { span, token },
+ }
+ }
+}
+
+#[derive(Diagnostic)]
+#[diag(parse_unexpected_self_in_generic_parameters)]
+#[note]
+pub(crate) struct UnexpectedSelfInGenericParameters {
+ #[primary_span]
+ pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(parse_unexpected_default_value_for_lifetime_in_generic_parameters)]
+pub(crate) struct UnexpectedDefaultValueForLifetimeInGenericParameters {
+ #[primary_span]
+ #[label]
+ pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(parse_multiple_where_clauses)]
+pub(crate) struct MultipleWhereClauses {
+ #[primary_span]
+ pub span: Span,
+ #[label]
+ pub previous: Span,
+ #[suggestion(style = "verbose", code = ",", applicability = "maybe-incorrect")]
+ pub between: Span,
+}
+
+#[derive(Diagnostic)]
+pub(crate) enum UnexpectedNonterminal {
+ #[diag(parse_nonterminal_expected_item_keyword)]
+ Item(#[primary_span] Span),
+ #[diag(parse_nonterminal_expected_statement)]
+ Statement(#[primary_span] Span),
+ #[diag(parse_nonterminal_expected_ident)]
+ Ident {
+ #[primary_span]
+ span: Span,
+ token: Token,
+ },
+ #[diag(parse_nonterminal_expected_lifetime)]
+ Lifetime {
+ #[primary_span]
+ span: Span,
+ token: Token,
+ },
+}
+
+#[derive(Diagnostic)]
+pub(crate) enum TopLevelOrPatternNotAllowed {
+ #[diag(parse_or_pattern_not_allowed_in_let_binding)]
+ LetBinding {
+ #[primary_span]
+ span: Span,
+ #[subdiagnostic]
+ sub: Option<TopLevelOrPatternNotAllowedSugg>,
+ },
+ #[diag(parse_or_pattern_not_allowed_in_fn_parameters)]
+ FunctionParameter {
+ #[primary_span]
+ span: Span,
+ #[subdiagnostic]
+ sub: Option<TopLevelOrPatternNotAllowedSugg>,
+ },
+}
+
+#[derive(Diagnostic)]
+#[diag(parse_cannot_be_raw_ident)]
+pub struct CannotBeRawIdent {
+ #[primary_span]
+ pub span: Span,
+ pub ident: Symbol,
+}
+
+#[derive(Diagnostic)]
+#[diag(parse_cr_doc_comment)]
+pub struct CrDocComment {
+ #[primary_span]
+ pub span: Span,
+ pub block: bool,
+}
+
+#[derive(Diagnostic)]
+#[diag(parse_no_digits_literal, code = "E0768")]
+pub struct NoDigitsLiteral {
+ #[primary_span]
+ pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(parse_invalid_digit_literal)]
+pub struct InvalidDigitLiteral {
+ #[primary_span]
+ pub span: Span,
+ pub base: u32,
+}
+
+#[derive(Diagnostic)]
+#[diag(parse_empty_exponent_float)]
+pub struct EmptyExponentFloat {
+ #[primary_span]
+ pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(parse_float_literal_unsupported_base)]
+pub struct FloatLiteralUnsupportedBase {
+ #[primary_span]
+ pub span: Span,
+ pub base: &'static str,
+}
+
+#[derive(Diagnostic)]
+#[diag(parse_unknown_prefix)]
+#[note]
+pub struct UnknownPrefix<'a> {
+ #[primary_span]
+ #[label]
+ pub span: Span,
+ pub prefix: &'a str,
+ #[subdiagnostic]
+ pub sugg: Option<UnknownPrefixSugg>,
+}
+
+#[derive(Subdiagnostic)]
+pub enum UnknownPrefixSugg {
+ #[suggestion(
+ parse_suggestion_br,
+ code = "br",
+ applicability = "maybe-incorrect",
+ style = "verbose"
+ )]
+ UseBr(#[primary_span] Span),
+ #[suggestion(
+ parse_suggestion_whitespace,
+ code = " ",
+ applicability = "maybe-incorrect",
+ style = "verbose"
+ )]
+ Whitespace(#[primary_span] Span),
+}
+
+#[derive(Diagnostic)]
+#[diag(parse_too_many_hashes)]
+pub struct TooManyHashes {
+ #[primary_span]
+ pub span: Span,
+ pub num: u32,
+}
+
+#[derive(Diagnostic)]
+#[diag(parse_unknown_start_of_token)]
+pub struct UnknownTokenStart {
+ #[primary_span]
+ pub span: Span,
+ pub escaped: String,
+ #[subdiagnostic]
+ pub sugg: Option<TokenSubstitution>,
+ #[subdiagnostic]
+ pub null: Option<UnknownTokenNull>,
+ #[subdiagnostic]
+ pub repeat: Option<UnknownTokenRepeat>,
+}
+
+#[derive(Subdiagnostic)]
+pub enum TokenSubstitution {
+ #[suggestion(parse_sugg_quotes, code = "{suggestion}", applicability = "maybe-incorrect")]
+ DirectedQuotes {
+ #[primary_span]
+ span: Span,
+ suggestion: String,
+ ascii_str: &'static str,
+ ascii_name: &'static str,
+ },
+ #[suggestion(parse_sugg_other, code = "{suggestion}", applicability = "maybe-incorrect")]
+ Other {
+ #[primary_span]
+ span: Span,
+ suggestion: String,
+ ch: String,
+ u_name: &'static str,
+ ascii_str: &'static str,
+ ascii_name: &'static str,
+ },
+}
+
+#[derive(Subdiagnostic)]
+#[note(parse_note_repeats)]
+pub struct UnknownTokenRepeat {
+ pub repeats: usize,
+}
+
+#[derive(Subdiagnostic)]
+#[help(parse_help_null)]
+pub struct UnknownTokenNull;
+
+#[derive(Diagnostic)]
+pub enum UnescapeError {
+ #[diag(parse_invalid_unicode_escape)]
+ #[help]
+ InvalidUnicodeEscape {
+ #[primary_span]
+ #[label]
+ span: Span,
+ surrogate: bool,
+ },
+ #[diag(parse_escape_only_char)]
+ EscapeOnlyChar {
+ #[primary_span]
+ span: Span,
+ #[suggestion(parse_escape, applicability = "machine-applicable", code = "{escaped_sugg}")]
+ char_span: Span,
+ escaped_sugg: String,
+ escaped_msg: String,
+ byte: bool,
+ },
+ #[diag(parse_bare_cr)]
+ BareCr {
+ #[primary_span]
+ #[suggestion(parse_escape, applicability = "machine-applicable", code = "\\r")]
+ span: Span,
+ double_quotes: bool,
+ },
+ #[diag(parse_bare_cr_in_raw_string)]
+ BareCrRawString(#[primary_span] Span),
+ #[diag(parse_too_short_hex_escape)]
+ TooShortHexEscape(#[primary_span] Span),
+ #[diag(parse_invalid_char_in_escape)]
+ InvalidCharInEscape {
+ #[primary_span]
+ #[label]
+ span: Span,
+ is_hex: bool,
+ ch: String,
+ },
+ #[diag(parse_out_of_range_hex_escape)]
+ OutOfRangeHexEscape(
+ #[primary_span]
+ #[label]
+ Span,
+ ),
+ #[diag(parse_leading_underscore_unicode_escape)]
+ LeadingUnderscoreUnicodeEscape {
+ #[primary_span]
+ #[label(parse_leading_underscore_unicode_escape_label)]
+ span: Span,
+ ch: String,
+ },
+ #[diag(parse_overlong_unicode_escape)]
+ OverlongUnicodeEscape(
+ #[primary_span]
+ #[label]
+ Span,
+ ),
+ #[diag(parse_unclosed_unicode_escape)]
+ UnclosedUnicodeEscape(
+ #[primary_span]
+ #[label]
+ Span,
+ #[suggestion(
+ parse_terminate,
+ code = "}}",
+ applicability = "maybe-incorrect",
+ style = "verbose"
+ )]
+ Span,
+ ),
+ #[diag(parse_no_brace_unicode_escape)]
+ NoBraceInUnicodeEscape {
+ #[primary_span]
+ span: Span,
+ #[label]
+ label: Option<Span>,
+ #[subdiagnostic]
+ sub: NoBraceUnicodeSub,
+ },
+ #[diag(parse_unicode_escape_in_byte)]
+ #[help]
+ UnicodeEscapeInByte(
+ #[primary_span]
+ #[label]
+ Span,
+ ),
+ #[diag(parse_empty_unicode_escape)]
+ EmptyUnicodeEscape(
+ #[primary_span]
+ #[label]
+ Span,
+ ),
+ #[diag(parse_zero_chars)]
+ ZeroChars(
+ #[primary_span]
+ #[label]
+ Span,
+ ),
+ #[diag(parse_lone_slash)]
+ LoneSlash(
+ #[primary_span]
+ #[label]
+ Span,
+ ),
+ #[diag(parse_unskipped_whitespace)]
+ UnskippedWhitespace {
+ #[primary_span]
+ span: Span,
+ #[label]
+ char_span: Span,
+ ch: String,
+ },
+ #[diag(parse_multiple_skipped_lines)]
+ MultipleSkippedLinesWarning(
+ #[primary_span]
+ #[label]
+ Span,
+ ),
+ #[diag(parse_more_than_one_char)]
+ MoreThanOneChar {
+ #[primary_span]
+ span: Span,
+ #[subdiagnostic]
+ note: Option<MoreThanOneCharNote>,
+ #[subdiagnostic]
+ suggestion: MoreThanOneCharSugg,
+ },
+}
+
+#[derive(Subdiagnostic)]
+pub enum MoreThanOneCharSugg {
+ #[suggestion(
+ parse_consider_normalized,
+ code = "{normalized}",
+ applicability = "machine-applicable"
+ )]
+ NormalizedForm {
+ #[primary_span]
+ span: Span,
+ ch: String,
+ normalized: String,
+ },
+ #[suggestion(parse_remove_non, code = "{ch}", applicability = "maybe-incorrect")]
+ RemoveNonPrinting {
+ #[primary_span]
+ span: Span,
+ ch: String,
+ },
+ #[suggestion(parse_use_double_quotes, code = "{sugg}", applicability = "machine-applicable")]
+ Quotes {
+ #[primary_span]
+ span: Span,
+ is_byte: bool,
+ sugg: String,
+ },
+}
+
+#[derive(Subdiagnostic)]
+pub enum MoreThanOneCharNote {
+ #[note(parse_followed_by)]
+ AllCombining {
+ #[primary_span]
+ span: Span,
+ chr: String,
+ len: usize,
+ escaped_marks: String,
+ },
+ #[note(parse_non_printing)]
+ NonPrinting {
+ #[primary_span]
+ span: Span,
+ escaped: String,
+ },
+}
+
+#[derive(Subdiagnostic)]
+pub enum NoBraceUnicodeSub {
+ #[suggestion(parse_use_braces, code = "{suggestion}", applicability = "maybe-incorrect")]
+ Suggestion {
+ #[primary_span]
+ span: Span,
+ suggestion: String,
+ },
+ #[help(parse_format_of_unicode)]
+ Help,
+}
+
+#[derive(Subdiagnostic)]
+pub(crate) enum TopLevelOrPatternNotAllowedSugg {
+ #[suggestion(
+ parse_sugg_remove_leading_vert_in_pattern,
+ code = "{pat}",
+ applicability = "machine-applicable"
+ )]
+ RemoveLeadingVert {
+ #[primary_span]
+ span: Span,
+ pat: String,
+ },
+ #[suggestion(
+ parse_sugg_wrap_pattern_in_parens,
+ code = "({pat})",
+ applicability = "machine-applicable"
+ )]
+ WrapInParens {
+ #[primary_span]
+ span: Span,
+ pat: String,
+ },
+}
+
+#[derive(Diagnostic)]
+#[diag(parse_unexpected_vert_vert_before_function_parameter)]
+#[note(parse_note_pattern_alternatives_use_single_vert)]
+pub(crate) struct UnexpectedVertVertBeforeFunctionParam {
+ #[primary_span]
+ #[suggestion(code = "", applicability = "machine-applicable")]
+ pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(parse_unexpected_vert_vert_in_pattern)]
+pub(crate) struct UnexpectedVertVertInPattern {
+ #[primary_span]
+ #[suggestion(code = "|", applicability = "machine-applicable")]
+ pub span: Span,
+ #[label(parse_label_while_parsing_or_pattern_here)]
+ pub start: Option<Span>,
+}
+
+#[derive(Diagnostic)]
+#[diag(parse_trailing_vert_not_allowed)]
+pub(crate) struct TrailingVertNotAllowed {
+ #[primary_span]
+ #[suggestion(code = "", applicability = "machine-applicable")]
+ pub span: Span,
+ #[label(parse_label_while_parsing_or_pattern_here)]
+ pub start: Option<Span>,
+ pub token: Token,
+ #[note(parse_note_pattern_alternatives_use_single_vert)]
+ pub note_double_vert: Option<()>,
+}
+
+#[derive(Diagnostic)]
+#[diag(parse_dotdotdot_rest_pattern)]
+pub(crate) struct DotDotDotRestPattern {
+ #[primary_span]
+ #[suggestion(style = "short", code = "..", applicability = "machine-applicable")]
+ #[label]
+ pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(parse_pattern_on_wrong_side_of_at)]
+pub(crate) struct PatternOnWrongSideOfAt {
+ #[primary_span]
+ #[suggestion(code = "{whole_pat}", applicability = "machine-applicable")]
+ pub whole_span: Span,
+ pub whole_pat: String,
+ #[label(parse_label_pattern)]
+ pub pattern: Span,
+ #[label(parse_label_binding)]
+ pub binding: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(parse_expected_binding_left_of_at)]
+#[note]
+pub(crate) struct ExpectedBindingLeftOfAt {
+ #[primary_span]
+ pub whole_span: Span,
+ #[label(parse_label_lhs)]
+ pub lhs: Span,
+ #[label(parse_label_rhs)]
+ pub rhs: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(parse_ambiguous_range_pattern)]
+pub(crate) struct AmbiguousRangePattern {
+ #[primary_span]
+ #[suggestion(code = "({pat})", applicability = "maybe-incorrect")]
+ pub span: Span,
+ pub pat: String,
+}
+
+#[derive(Diagnostic)]
+#[diag(parse_unexpected_lifetime_in_pattern)]
+pub(crate) struct UnexpectedLifetimeInPattern {
+ #[primary_span]
+ #[suggestion(code = "", applicability = "machine-applicable")]
+ pub span: Span,
+ pub symbol: Symbol,
+}
+
+#[derive(Diagnostic)]
+#[diag(parse_ref_mut_order_incorrect)]
+pub(crate) struct RefMutOrderIncorrect {
+ #[primary_span]
+ #[suggestion(code = "ref mut", applicability = "machine-applicable")]
+ pub span: Span,
+}
+
+#[derive(Diagnostic)]
+pub(crate) enum InvalidMutInPattern {
+ #[diag(parse_mut_on_nested_ident_pattern)]
+ #[note(parse_note_mut_pattern_usage)]
+ NestedIdent {
+ #[primary_span]
+ #[suggestion(code = "{pat}", applicability = "machine-applicable")]
+ span: Span,
+ pat: String,
+ },
+ #[diag(parse_mut_on_non_ident_pattern)]
+ #[note(parse_note_mut_pattern_usage)]
+ NonIdent {
+ #[primary_span]
+ #[suggestion(code = "{pat}", applicability = "machine-applicable")]
+ span: Span,
+ pat: String,
+ },
+}
+
+#[derive(Diagnostic)]
+#[diag(parse_repeated_mut_in_pattern)]
+pub(crate) struct RepeatedMutInPattern {
+ #[primary_span]
+ #[suggestion(code = "", applicability = "machine-applicable")]
+ pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(parse_dot_dot_dot_range_to_pattern_not_allowed)]
+pub(crate) struct DotDotDotRangeToPatternNotAllowed {
+ #[primary_span]
+ #[suggestion(style = "short", code = "..=", applicability = "machine-applicable")]
+ pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(parse_enum_pattern_instead_of_identifier)]
+pub(crate) struct EnumPatternInsteadOfIdentifier {
+ #[primary_span]
+ pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(parse_dot_dot_dot_for_remaining_fields)]
+pub(crate) struct DotDotDotForRemainingFields {
+ #[primary_span]
+ #[suggestion(code = "..", style = "verbose", applicability = "machine-applicable")]
+ pub span: Span,
+ pub token_str: Cow<'static, str>,
+}
+
+#[derive(Diagnostic)]
+#[diag(parse_expected_comma_after_pattern_field)]
+pub(crate) struct ExpectedCommaAfterPatternField {
+ #[primary_span]
+ pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(parse_return_types_use_thin_arrow)]
+pub(crate) struct ReturnTypesUseThinArrow {
+ #[primary_span]
+ #[suggestion(style = "short", code = "->", applicability = "machine-applicable")]
+ pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(parse_need_plus_after_trait_object_lifetime)]
+pub(crate) struct NeedPlusAfterTraitObjectLifetime {
+ #[primary_span]
+ pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(parse_expected_mut_or_const_in_raw_pointer_type)]
+pub(crate) struct ExpectedMutOrConstInRawPointerType {
+ #[primary_span]
+ pub span: Span,
+ #[suggestion(code("mut ", "const "), applicability = "has-placeholders")]
+ pub after_asterisk: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(parse_lifetime_after_mut)]
+pub(crate) struct LifetimeAfterMut {
+ #[primary_span]
+ pub span: Span,
+ #[suggestion(code = "&{snippet} mut", applicability = "maybe-incorrect")]
+ pub suggest_lifetime: Option<Span>,
+ pub snippet: String,
+}
+
+#[derive(Diagnostic)]
+#[diag(parse_dyn_after_mut)]
+pub(crate) struct DynAfterMut {
+ #[primary_span]
+ #[suggestion(code = "&mut dyn", applicability = "machine-applicable")]
+ pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(parse_fn_pointer_cannot_be_const)]
+pub(crate) struct FnPointerCannotBeConst {
+ #[primary_span]
+ pub span: Span,
+ #[suggestion(code = "", applicability = "maybe-incorrect")]
+ #[label]
+ pub qualifier: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(parse_fn_pointer_cannot_be_async)]
+pub(crate) struct FnPointerCannotBeAsync {
+ #[primary_span]
+ pub span: Span,
+ #[suggestion(code = "", applicability = "maybe-incorrect")]
+ #[label]
+ pub qualifier: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(parse_nested_c_variadic_type, code = "E0743")]
+pub(crate) struct NestedCVariadicType {
+ #[primary_span]
+ pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(parse_invalid_dyn_keyword)]
+#[help]
+pub(crate) struct InvalidDynKeyword {
+ #[primary_span]
+ #[suggestion(code = "", applicability = "machine-applicable")]
+ pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(parse_negative_bounds_not_supported)]
+pub(crate) struct NegativeBoundsNotSupported {
+ #[primary_span]
+ pub negative_bounds: Vec<Span>,
+ #[label]
+ pub last_span: Span,
+ #[subdiagnostic]
+ pub sub: Option<NegativeBoundsNotSupportedSugg>,
+}
+
+#[derive(Subdiagnostic)]
+#[suggestion(
+ parse_suggestion,
+ style = "tool-only",
+ code = "{fixed}",
+ applicability = "machine-applicable"
+)]
+pub(crate) struct NegativeBoundsNotSupportedSugg {
+ #[primary_span]
+ pub bound_list: Span,
+ pub num_bounds: usize,
+ pub fixed: String,
+}
+
+#[derive(Subdiagnostic)]
+pub enum HelpUseLatestEdition {
+ #[help(parse_help_set_edition_cargo)]
+ #[note(parse_note_edition_guide)]
+ Cargo { edition: Edition },
+ #[help(parse_help_set_edition_standalone)]
+ #[note(parse_note_edition_guide)]
+ Standalone { edition: Edition },
+}
+
+impl HelpUseLatestEdition {
+ pub fn new() -> Self {
+ let edition = LATEST_STABLE_EDITION;
+ if std::env::var_os("CARGO").is_some() {
+ Self::Cargo { edition }
+ } else {
+ Self::Standalone { edition }
+ }
+ }
+}
diff --git a/compiler/rustc_parse/src/lexer/diagnostics.rs b/compiler/rustc_parse/src/lexer/diagnostics.rs
new file mode 100644
index 000000000..27f4428d3
--- /dev/null
+++ b/compiler/rustc_parse/src/lexer/diagnostics.rs
@@ -0,0 +1,119 @@
+use super::UnmatchedDelim;
+use rustc_ast::token::Delimiter;
+use rustc_errors::Diagnostic;
+use rustc_span::source_map::SourceMap;
+use rustc_span::Span;
+
+#[derive(Default)]
+pub struct TokenTreeDiagInfo {
+ /// Stack of open delimiters and their spans. Used for error message.
+ pub open_braces: Vec<(Delimiter, Span)>,
+ pub unmatched_delims: Vec<UnmatchedDelim>,
+
+ /// Used only for error recovery when arriving to EOF with mismatched braces.
+ pub last_unclosed_found_span: Option<Span>,
+
+ /// Collect empty block spans that might have been auto-inserted by editors.
+ pub empty_block_spans: Vec<Span>,
+
+ /// Collect the spans of braces (Open, Close). Used only
+ /// for detecting if blocks are empty and only braces.
+ pub matching_block_spans: Vec<(Span, Span)>,
+}
+
+pub fn same_identation_level(sm: &SourceMap, open_sp: Span, close_sp: Span) -> bool {
+ match (sm.span_to_margin(open_sp), sm.span_to_margin(close_sp)) {
+ (Some(open_padding), Some(close_padding)) => open_padding == close_padding,
+ _ => false,
+ }
+}
+
+// When we get a `)` or `]` for `{`, we should emit help message here
+// it's more friendly compared to report `unmatched error` in later phase
+pub fn report_missing_open_delim(
+ err: &mut Diagnostic,
+ unmatched_delims: &[UnmatchedDelim],
+) -> bool {
+ let mut reported_missing_open = false;
+ for unmatch_brace in unmatched_delims.iter() {
+ if let Some(delim) = unmatch_brace.found_delim
+ && matches!(delim, Delimiter::Parenthesis | Delimiter::Bracket)
+ {
+ let missed_open = match delim {
+ Delimiter::Parenthesis => "(",
+ Delimiter::Bracket => "[",
+ _ => unreachable!(),
+ };
+ err.span_label(
+ unmatch_brace.found_span.shrink_to_lo(),
+ format!("missing open `{}` for this delimiter", missed_open),
+ );
+ reported_missing_open = true;
+ }
+ }
+ reported_missing_open
+}
+
+pub fn report_suspicious_mismatch_block(
+ err: &mut Diagnostic,
+ diag_info: &TokenTreeDiagInfo,
+ sm: &SourceMap,
+ delim: Delimiter,
+) {
+ if report_missing_open_delim(err, &diag_info.unmatched_delims) {
+ return;
+ }
+
+ let mut matched_spans: Vec<(Span, bool)> = diag_info
+ .matching_block_spans
+ .iter()
+ .map(|&(open, close)| (open.with_hi(close.lo()), same_identation_level(sm, open, close)))
+ .collect();
+
+ // sort by `lo`, so the large block spans in the front
+ matched_spans.sort_by(|a, b| a.0.lo().cmp(&b.0.lo()));
+
+ // We use larger block whose identation is well to cover those inner mismatched blocks
+ // O(N^2) here, but we are on error reporting path, so it is fine
+ for i in 0..matched_spans.len() {
+ let (block_span, same_ident) = matched_spans[i];
+ if same_ident {
+ for j in i + 1..matched_spans.len() {
+ let (inner_block, inner_same_ident) = matched_spans[j];
+ if block_span.contains(inner_block) && !inner_same_ident {
+ matched_spans[j] = (inner_block, true);
+ }
+ }
+ }
+ }
+
+ // Find the inner-most span candidate for final report
+ let candidate_span =
+ matched_spans.into_iter().rev().find(|&(_, same_ident)| !same_ident).map(|(span, _)| span);
+
+ if let Some(block_span) = candidate_span {
+ err.span_label(block_span.shrink_to_lo(), "this delimiter might not be properly closed...");
+ err.span_label(
+ block_span.shrink_to_hi(),
+ "...as it matches this but it has different indentation",
+ );
+
+ // If there is a empty block in the mismatched span, note it
+ if delim == Delimiter::Brace {
+ for span in diag_info.empty_block_spans.iter() {
+ if block_span.contains(*span) {
+ err.span_label(*span, "block is empty, you might have not meant to close it");
+ break;
+ }
+ }
+ }
+ } else {
+ // If there is no suspicious span, give the last properly closed block may help
+ if let Some(parent) = diag_info.matching_block_spans.last()
+ && diag_info.open_braces.last().is_none()
+ && diag_info.empty_block_spans.iter().all(|&sp| sp != parent.0.to(parent.1)) {
+ err.span_label(parent.0, "this opening brace...");
+ err.span_label(parent.1, "...matches this closing brace");
+ }
+ }
+}
diff --git a/compiler/rustc_parse/src/lexer/mod.rs b/compiler/rustc_parse/src/lexer/mod.rs
index 9fe8d9836..59958a309 100644
--- a/compiler/rustc_parse/src/lexer/mod.rs
+++ b/compiler/rustc_parse/src/lexer/mod.rs
@@ -1,11 +1,11 @@
+use crate::errors;
use crate::lexer::unicode_chars::UNICODE_ARRAY;
+use crate::make_unclosed_delims_error;
use rustc_ast::ast::{self, AttrStyle};
use rustc_ast::token::{self, CommentKind, Delimiter, Token, TokenKind};
use rustc_ast::tokenstream::TokenStream;
use rustc_ast::util::unicode::contains_text_flow_control_chars;
-use rustc_errors::{
- error_code, Applicability, DiagnosticBuilder, ErrorGuaranteed, PResult, StashKey,
-};
+use rustc_errors::{error_code, Applicability, Diagnostic, DiagnosticBuilder, StashKey};
use rustc_lexer::unescape::{self, Mode};
use rustc_lexer::Cursor;
use rustc_lexer::{Base, DocStyle, RawStrError};
@@ -17,6 +17,7 @@ use rustc_session::parse::ParseSess;
use rustc_span::symbol::{sym, Symbol};
use rustc_span::{edition::Edition, BytePos, Pos, Span};
+mod diagnostics;
mod tokentrees;
mod unescape_error_reporting;
mod unicode_chars;
@@ -31,7 +32,7 @@ use unescape_error_reporting::{emit_unescape_error, escaped_char};
rustc_data_structures::static_assert_size!(rustc_lexer::Token, 12);
#[derive(Clone, Debug)]
-pub struct UnmatchedBrace {
+pub struct UnmatchedDelim {
pub expected_delim: Delimiter,
pub found_delim: Option<Delimiter>,
pub found_span: Span,
@@ -44,7 +45,7 @@ pub(crate) fn parse_token_trees<'a>(
mut src: &'a str,
mut start_pos: BytePos,
override_span: Option<Span>,
-) -> (PResult<'a, TokenStream>, Vec<UnmatchedBrace>) {
+) -> Result<TokenStream, Vec<Diagnostic>> {
// Skip `#!`, if present.
if let Some(shebang_len) = rustc_lexer::strip_shebang(src) {
src = &src[shebang_len..];
@@ -61,7 +62,29 @@ pub(crate) fn parse_token_trees<'a>(
override_span,
nbsp_is_whitespace: false,
};
- tokentrees::TokenTreesReader::parse_all_token_trees(string_reader)
+ let (token_trees, unmatched_delims) =
+ tokentrees::TokenTreesReader::parse_all_token_trees(string_reader);
+ match token_trees {
+ Ok(stream) if unmatched_delims.is_empty() => Ok(stream),
+ _ => {
+ // Return error if there are unmatched delimiters or unclosng delimiters.
+ // We emit delimiter mismatch errors first, then emit the unclosing delimiter mismatch
+ // because the delimiter mismatch is more likely to be the root cause of error
+
+ let mut buffer = Vec::with_capacity(1);
+ // Not using `emit_unclosed_delims` to use `db.buffer`
+ for unmatched in unmatched_delims {
+ if let Some(err) = make_unclosed_delims_error(unmatched, &sess) {
+ err.buffer(&mut buffer);
+ }
+ }
+ if let Err(err) = token_trees {
+ // Add unclosing delimiter error
+ err.buffer(&mut buffer);
+ }
+ Err(buffer)
+ }
+ }
}
struct StringReader<'a> {
@@ -150,7 +173,7 @@ impl<'a> StringReader<'a> {
let span = self.mk_sp(start, self.pos);
self.sess.symbol_gallery.insert(sym, span);
if !sym.can_be_raw() {
- self.err_span(span, &format!("`{}` cannot be a raw identifier", sym));
+ self.sess.emit_err(errors::CannotBeRawIdent { span, ident: sym });
}
self.sess.raw_identifier_spans.borrow_mut().push(span);
token::Ident(sym, true)
@@ -261,27 +284,24 @@ impl<'a> StringReader<'a> {
self.nbsp_is_whitespace = true;
}
let repeats = it.take_while(|c1| *c1 == c).count();
- let mut err =
- self.struct_err_span_char(start, self.pos + Pos::from_usize(repeats * c.len_utf8()), "unknown start of token", c);
// FIXME: the lexer could be used to turn the ASCII version of unicode
// homoglyphs, instead of keeping a table in `check_for_substitution`into the
// token. Ideally, this should be inside `rustc_lexer`. However, we should
// first remove compound tokens like `<<` from `rustc_lexer`, and then add
// fancier error recovery to it, as there will be less overall work to do this
// way.
- let token = unicode_chars::check_for_substitution(self, start, c, &mut err, repeats+1);
- if c == '\x00' {
- err.help("source files must contain UTF-8 encoded text, unexpected null bytes might occur when a different encoding is used");
- }
- if repeats > 0 {
- if repeats == 1 {
- err.note(format!("character appears once more"));
- } else {
- err.note(format!("character appears {repeats} more times"));
- }
- swallow_next_invalid = repeats;
- }
- err.emit();
+ let (token, sugg) = unicode_chars::check_for_substitution(self, start, c, repeats+1);
+ self.sess.emit_err(errors::UnknownTokenStart {
+ span: self.mk_sp(start, self.pos + Pos::from_usize(repeats * c.len_utf8())),
+ escaped: escaped_char(c),
+ sugg,
+ null: if c == '\x00' {Some(errors::UnknownTokenNull)} else {None},
+ repeat: if repeats > 0 {
+ swallow_next_invalid = repeats;
+ Some(errors::UnknownTokenRepeat { repeats })
+ } else {None}
+ });
+
if let Some(token) = token {
token
} else {
@@ -296,26 +316,6 @@ impl<'a> StringReader<'a> {
}
}
- /// Report a fatal lexical error with a given span.
- fn fatal_span(&self, sp: Span, m: &str) -> ! {
- self.sess.span_diagnostic.span_fatal(sp, m)
- }
-
- /// Report a lexical error with a given span.
- fn err_span(&self, sp: Span, m: &str) {
- self.sess.span_diagnostic.struct_span_err(sp, m).emit();
- }
-
- /// Report a fatal error spanning [`from_pos`, `to_pos`).
- fn fatal_span_(&self, from_pos: BytePos, to_pos: BytePos, m: &str) -> ! {
- self.fatal_span(self.mk_sp(from_pos, to_pos), m)
- }
-
- /// Report a lexical error spanning [`from_pos`, `to_pos`).
- fn err_span_(&self, from_pos: BytePos, to_pos: BytePos, m: &str) {
- self.err_span(self.mk_sp(from_pos, to_pos), m)
- }
-
fn struct_fatal_span_char(
&self,
from_pos: BytePos,
@@ -328,18 +328,6 @@ impl<'a> StringReader<'a> {
.struct_span_fatal(self.mk_sp(from_pos, to_pos), &format!("{}: {}", m, escaped_char(c)))
}
- fn struct_err_span_char(
- &self,
- from_pos: BytePos,
- to_pos: BytePos,
- m: &str,
- c: char,
- ) -> DiagnosticBuilder<'a, ErrorGuaranteed> {
- self.sess
- .span_diagnostic
- .struct_span_err(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) {
@@ -367,14 +355,12 @@ impl<'a> StringReader<'a> {
) -> TokenKind {
if content.contains('\r') {
for (idx, _) in content.char_indices().filter(|&(_, c)| c == '\r') {
- self.err_span_(
+ let span = self.mk_sp(
content_start + BytePos(idx as u32),
content_start + BytePos(idx as u32 + 1),
- match comment_kind {
- CommentKind::Line => "bare CR not allowed in doc-comment",
- CommentKind::Block => "bare CR not allowed in block doc-comment",
- },
);
+ let block = matches!(comment_kind, CommentKind::Block);
+ self.sess.emit_err(errors::CrDocComment { span, block });
}
}
@@ -453,26 +439,20 @@ impl<'a> StringReader<'a> {
}
rustc_lexer::LiteralKind::Int { base, empty_int } => {
if empty_int {
- self.sess
- .span_diagnostic
- .struct_span_err_with_code(
- self.mk_sp(start, end),
- "no valid digits found for number",
- error_code!(E0768),
- )
- .emit();
+ let span = self.mk_sp(start, end);
+ self.sess.emit_err(errors::NoDigitsLiteral { span });
(token::Integer, sym::integer(0))
} else {
if matches!(base, Base::Binary | Base::Octal) {
let base = base as u32;
let s = self.str_from_to(start + BytePos(2), end);
for (idx, c) in s.char_indices() {
+ let span = self.mk_sp(
+ start + BytePos::from_usize(2 + idx),
+ start + BytePos::from_usize(2 + idx + c.len_utf8()),
+ );
if c != '_' && c.to_digit(base).is_none() {
- self.err_span_(
- start + BytePos::from_usize(2 + idx),
- start + BytePos::from_usize(2 + idx + c.len_utf8()),
- &format!("invalid digit for a base {} literal", base),
- );
+ self.sess.emit_err(errors::InvalidDigitLiteral { span, base });
}
}
}
@@ -481,19 +461,18 @@ impl<'a> StringReader<'a> {
}
rustc_lexer::LiteralKind::Float { base, empty_exponent } => {
if empty_exponent {
- self.err_span_(start, self.pos, "expected at least one digit in exponent");
+ let span = self.mk_sp(start, self.pos);
+ self.sess.emit_err(errors::EmptyExponentFloat { span });
}
- match base {
- Base::Hexadecimal => {
- self.err_span_(start, end, "hexadecimal float literal is not supported")
- }
- Base::Octal => {
- self.err_span_(start, end, "octal float literal is not supported")
- }
- Base::Binary => {
- self.err_span_(start, end, "binary float literal is not supported")
- }
- _ => {}
+ let base = match base {
+ Base::Hexadecimal => Some("hexadecimal"),
+ Base::Octal => Some("octal"),
+ Base::Binary => Some("binary"),
+ _ => None,
+ };
+ if let Some(base) = base {
+ let span = self.mk_sp(start, end);
+ self.sess.emit_err(errors::FloatLiteralUnsupportedBase { span, base });
}
(token::Float, self.symbol_from_to(start, end))
}
@@ -643,54 +622,34 @@ impl<'a> StringReader<'a> {
// identifier tokens.
fn report_unknown_prefix(&self, start: BytePos) {
let prefix_span = self.mk_sp(start, self.pos);
- let prefix_str = self.str_from_to(start, self.pos);
- let msg = format!("prefix `{}` is unknown", prefix_str);
+ let prefix = self.str_from_to(start, self.pos);
let expn_data = prefix_span.ctxt().outer_expn_data();
if expn_data.edition >= Edition::Edition2021 {
// In Rust 2021, this is a hard error.
- let mut err = self.sess.span_diagnostic.struct_span_err(prefix_span, &msg);
- err.span_label(prefix_span, "unknown prefix");
- if prefix_str == "rb" {
- err.span_suggestion_verbose(
- prefix_span,
- "use `br` for a raw byte string",
- "br",
- Applicability::MaybeIncorrect,
- );
+ let sugg = if prefix == "rb" {
+ Some(errors::UnknownPrefixSugg::UseBr(prefix_span))
} else if expn_data.is_root() {
- err.span_suggestion_verbose(
- prefix_span.shrink_to_hi(),
- "consider inserting whitespace here",
- " ",
- Applicability::MaybeIncorrect,
- );
- }
- err.note("prefixed identifiers and literals are reserved since Rust 2021");
- err.emit();
+ Some(errors::UnknownPrefixSugg::Whitespace(prefix_span.shrink_to_hi()))
+ } else {
+ None
+ };
+ self.sess.emit_err(errors::UnknownPrefix { span: prefix_span, prefix, sugg });
} else {
// Before Rust 2021, only emit a lint for migration.
self.sess.buffer_lint_with_diagnostic(
&RUST_2021_PREFIXES_INCOMPATIBLE_SYNTAX,
prefix_span,
ast::CRATE_NODE_ID,
- &msg,
+ &format!("prefix `{prefix}` is unknown"),
BuiltinLintDiagnostics::ReservedPrefix(prefix_span),
);
}
}
- fn report_too_many_hashes(&self, start: BytePos, found: u32) -> ! {
- self.fatal_span_(
- start,
- self.pos,
- &format!(
- "too many `#` symbols: raw strings may be delimited \
- by up to 255 `#` symbols, but found {}",
- found
- ),
- )
+ fn report_too_many_hashes(&self, start: BytePos, num: u32) -> ! {
+ self.sess.emit_fatal(errors::TooManyHashes { span: self.mk_sp(start, self.pos), num });
}
fn cook_quoted(
diff --git a/compiler/rustc_parse/src/lexer/tokentrees.rs b/compiler/rustc_parse/src/lexer/tokentrees.rs
index b2701817d..36fd1e37d 100644
--- a/compiler/rustc_parse/src/lexer/tokentrees.rs
+++ b/compiler/rustc_parse/src/lexer/tokentrees.rs
@@ -1,47 +1,31 @@
-use super::{StringReader, UnmatchedBrace};
+use super::diagnostics::report_suspicious_mismatch_block;
+use super::diagnostics::same_identation_level;
+use super::diagnostics::TokenTreeDiagInfo;
+use super::{StringReader, UnmatchedDelim};
use rustc_ast::token::{self, Delimiter, Token};
use rustc_ast::tokenstream::{DelimSpan, Spacing, TokenStream, TokenTree};
use rustc_ast_pretty::pprust::token_to_string;
-use rustc_data_structures::fx::FxHashMap;
use rustc_errors::{PErr, PResult};
-use rustc_span::Span;
pub(super) struct TokenTreesReader<'a> {
string_reader: StringReader<'a>,
/// The "next" token, which has been obtained from the `StringReader` but
/// not yet handled by the `TokenTreesReader`.
token: Token,
- /// Stack of open delimiters and their spans. Used for error message.
- open_braces: Vec<(Delimiter, Span)>,
- unmatched_braces: Vec<UnmatchedBrace>,
- /// The type and spans for all braces
- ///
- /// Used only for error recovery when arriving to EOF with mismatched braces.
- matching_delim_spans: Vec<(Delimiter, Span, Span)>,
- last_unclosed_found_span: Option<Span>,
- /// Collect empty block spans that might have been auto-inserted by editors.
- last_delim_empty_block_spans: FxHashMap<Delimiter, Span>,
- /// Collect the spans of braces (Open, Close). Used only
- /// for detecting if blocks are empty and only braces.
- matching_block_spans: Vec<(Span, Span)>,
+ diag_info: TokenTreeDiagInfo,
}
impl<'a> TokenTreesReader<'a> {
pub(super) fn parse_all_token_trees(
string_reader: StringReader<'a>,
- ) -> (PResult<'a, TokenStream>, Vec<UnmatchedBrace>) {
+ ) -> (PResult<'a, TokenStream>, Vec<UnmatchedDelim>) {
let mut tt_reader = TokenTreesReader {
string_reader,
token: Token::dummy(),
- open_braces: Vec::new(),
- unmatched_braces: Vec::new(),
- matching_delim_spans: Vec::new(),
- last_unclosed_found_span: None,
- last_delim_empty_block_spans: FxHashMap::default(),
- matching_block_spans: Vec::new(),
+ diag_info: TokenTreeDiagInfo::default(),
};
let res = tt_reader.parse_token_trees(/* is_delimited */ false);
- (res, tt_reader.unmatched_braces)
+ (res, tt_reader.diag_info.unmatched_delims)
}
// Parse a stream of tokens into a list of `TokenTree`s.
@@ -50,7 +34,7 @@ impl<'a> TokenTreesReader<'a> {
let mut buf = Vec::new();
loop {
match self.token.kind {
- token::OpenDelim(delim) => buf.push(self.parse_token_tree_open_delim(delim)),
+ token::OpenDelim(delim) => buf.push(self.parse_token_tree_open_delim(delim)?),
token::CloseDelim(delim) => {
return if is_delimited {
Ok(TokenStream::new(buf))
@@ -59,10 +43,11 @@ impl<'a> TokenTreesReader<'a> {
};
}
token::Eof => {
- if is_delimited {
- self.eof_err().emit();
- }
- return Ok(TokenStream::new(buf));
+ return if is_delimited {
+ Err(self.eof_err())
+ } else {
+ Ok(TokenStream::new(buf))
+ };
}
_ => {
// Get the next normal token. This might require getting multiple adjacent
@@ -92,9 +77,9 @@ impl<'a> TokenTreesReader<'a> {
fn eof_err(&mut self) -> PErr<'a> {
let msg = "this file contains an unclosed delimiter";
let mut err = self.string_reader.sess.span_diagnostic.struct_span_err(self.token.span, msg);
- for &(_, sp) in &self.open_braces {
+ for &(_, sp) in &self.diag_info.open_braces {
err.span_label(sp, "unclosed delimiter");
- self.unmatched_braces.push(UnmatchedBrace {
+ self.diag_info.unmatched_delims.push(UnmatchedDelim {
expected_delim: Delimiter::Brace,
found_delim: None,
found_span: self.token.span,
@@ -103,69 +88,53 @@ impl<'a> TokenTreesReader<'a> {
});
}
- if let Some((delim, _)) = self.open_braces.last() {
- if let Some((_, open_sp, close_sp)) =
- self.matching_delim_spans.iter().find(|(d, open_sp, close_sp)| {
- let sm = self.string_reader.sess.source_map();
- if let Some(close_padding) = sm.span_to_margin(*close_sp) {
- if let Some(open_padding) = sm.span_to_margin(*open_sp) {
- return delim == d && close_padding != open_padding;
- }
- }
- false
- })
- // these are in reverse order as they get inserted on close, but
- {
- // we want the last open/first close
- err.span_label(*open_sp, "this delimiter might not be properly closed...");
- err.span_label(*close_sp, "...as it matches this but it has different indentation");
- }
+ if let Some((delim, _)) = self.diag_info.open_braces.last() {
+ report_suspicious_mismatch_block(
+ &mut err,
+ &self.diag_info,
+ &self.string_reader.sess.source_map(),
+ *delim,
+ )
}
err
}
- fn parse_token_tree_open_delim(&mut self, open_delim: Delimiter) -> TokenTree {
+ fn parse_token_tree_open_delim(&mut self, open_delim: Delimiter) -> PResult<'a, TokenTree> {
// The span for beginning of the delimited section
let pre_span = self.token.span;
- self.open_braces.push((open_delim, self.token.span));
+ self.diag_info.open_braces.push((open_delim, self.token.span));
// Parse the token trees within the delimiters.
// We stop at any delimiter so we can try to recover if the user
// uses an incorrect delimiter.
- let tts = self.parse_token_trees(/* is_delimited */ true).unwrap();
+ let tts = self.parse_token_trees(/* is_delimited */ true)?;
// Expand to cover the entire delimited token tree
let delim_span = DelimSpan::from_pair(pre_span, self.token.span);
+ let sm = self.string_reader.sess.source_map();
match self.token.kind {
// Correct delimiter.
token::CloseDelim(close_delim) if close_delim == open_delim => {
- let (open_brace, open_brace_span) = self.open_braces.pop().unwrap();
+ let (open_brace, open_brace_span) = self.diag_info.open_braces.pop().unwrap();
let close_brace_span = self.token.span;
- if tts.is_empty() {
+ if tts.is_empty() && close_delim == Delimiter::Brace {
let empty_block_span = open_brace_span.to(close_brace_span);
- let sm = self.string_reader.sess.source_map();
if !sm.is_multiline(empty_block_span) {
// Only track if the block is in the form of `{}`, otherwise it is
// likely that it was written on purpose.
- self.last_delim_empty_block_spans.insert(open_delim, empty_block_span);
+ self.diag_info.empty_block_spans.push(empty_block_span);
}
}
- //only add braces
+ // only add braces
if let (Delimiter::Brace, Delimiter::Brace) = (open_brace, open_delim) {
- self.matching_block_spans.push((open_brace_span, close_brace_span));
+ // Add all the matching spans, we will sort by span later
+ self.diag_info.matching_block_spans.push((open_brace_span, close_brace_span));
}
- if self.open_braces.is_empty() {
- // Clear up these spans to avoid suggesting them as we've found
- // properly matched delimiters so far for an entire block.
- self.matching_delim_spans.clear();
- } else {
- self.matching_delim_spans.push((open_brace, open_brace_span, close_brace_span));
- }
// Move past the closing delimiter.
self.token = self.string_reader.next_token().0;
}
@@ -174,28 +143,25 @@ impl<'a> TokenTreesReader<'a> {
let mut unclosed_delimiter = None;
let mut candidate = None;
- if self.last_unclosed_found_span != Some(self.token.span) {
+ if self.diag_info.last_unclosed_found_span != Some(self.token.span) {
// do not complain about the same unclosed delimiter multiple times
- self.last_unclosed_found_span = Some(self.token.span);
+ self.diag_info.last_unclosed_found_span = Some(self.token.span);
// This is a conservative error: only report the last unclosed
// delimiter. The previous unclosed delimiters could actually be
// closed! The parser just hasn't gotten to them yet.
- if let Some(&(_, sp)) = self.open_braces.last() {
+ if let Some(&(_, sp)) = self.diag_info.open_braces.last() {
unclosed_delimiter = Some(sp);
};
- let sm = self.string_reader.sess.source_map();
- if let Some(current_padding) = sm.span_to_margin(self.token.span) {
- for (brace, brace_span) in &self.open_braces {
- if let Some(padding) = sm.span_to_margin(*brace_span) {
- // high likelihood of these two corresponding
- if current_padding == padding && brace == &close_delim {
- candidate = Some(*brace_span);
- }
- }
+ for (brace, brace_span) in &self.diag_info.open_braces {
+ if same_identation_level(&sm, self.token.span, *brace_span)
+ && brace == &close_delim
+ {
+ // high likelihood of these two corresponding
+ candidate = Some(*brace_span);
}
}
- let (tok, _) = self.open_braces.pop().unwrap();
- self.unmatched_braces.push(UnmatchedBrace {
+ let (tok, _) = self.diag_info.open_braces.pop().unwrap();
+ self.diag_info.unmatched_delims.push(UnmatchedDelim {
expected_delim: tok,
found_delim: Some(close_delim),
found_span: self.token.span,
@@ -203,7 +169,7 @@ impl<'a> TokenTreesReader<'a> {
candidate_span: candidate,
});
} else {
- self.open_braces.pop();
+ self.diag_info.open_braces.pop();
}
// If the incorrect delimiter matches an earlier opening
@@ -213,7 +179,7 @@ impl<'a> TokenTreesReader<'a> {
// fn foo() {
// bar(baz(
// } // Incorrect delimiter but matches the earlier `{`
- if !self.open_braces.iter().any(|&(b, _)| b == close_delim) {
+ if !self.diag_info.open_braces.iter().any(|&(b, _)| b == close_delim) {
self.token = self.string_reader.next_token().0;
}
}
@@ -225,7 +191,7 @@ impl<'a> TokenTreesReader<'a> {
_ => unreachable!(),
}
- TokenTree::Delimited(delim_span, open_delim, tts)
+ Ok(TokenTree::Delimited(delim_span, open_delim, tts))
}
fn close_delim_err(&mut self, delim: Delimiter) -> PErr<'a> {
@@ -236,22 +202,12 @@ impl<'a> TokenTreesReader<'a> {
let mut err =
self.string_reader.sess.span_diagnostic.struct_span_err(self.token.span, &msg);
- // Braces are added at the end, so the last element is the biggest block
- if let Some(parent) = self.matching_block_spans.last() {
- if let Some(span) = self.last_delim_empty_block_spans.remove(&delim) {
- // Check if the (empty block) is in the last properly closed block
- if (parent.0.to(parent.1)).contains(span) {
- err.span_label(span, "block is empty, you might have not meant to close it");
- } else {
- err.span_label(parent.0, "this opening brace...");
- err.span_label(parent.1, "...matches this closing brace");
- }
- } else {
- err.span_label(parent.0, "this opening brace...");
- err.span_label(parent.1, "...matches this closing brace");
- }
- }
-
+ report_suspicious_mismatch_block(
+ &mut err,
+ &self.diag_info,
+ &self.string_reader.sess.source_map(),
+ delim,
+ );
err.span_label(self.token.span, "unexpected closing delimiter");
err
}
diff --git a/compiler/rustc_parse/src/lexer/unescape_error_reporting.rs b/compiler/rustc_parse/src/lexer/unescape_error_reporting.rs
index 6373f5b4f..0d12ec608 100644
--- a/compiler/rustc_parse/src/lexer/unescape_error_reporting.rs
+++ b/compiler/rustc_parse/src/lexer/unescape_error_reporting.rs
@@ -3,10 +3,12 @@
use std::iter::once;
use std::ops::Range;
-use rustc_errors::{pluralize, Applicability, Handler};
+use rustc_errors::{Applicability, Handler};
use rustc_lexer::unescape::{EscapeError, Mode};
use rustc_span::{BytePos, Span};
+use crate::errors::{MoreThanOneCharNote, MoreThanOneCharSugg, NoBraceUnicodeSub, UnescapeError};
+
pub(crate) fn emit_unescape_error(
handler: &Handler,
// interior part of the literal, without quotes
@@ -31,53 +33,32 @@ pub(crate) fn emit_unescape_error(
};
match error {
EscapeError::LoneSurrogateUnicodeEscape => {
- handler
- .struct_span_err(span, "invalid unicode character escape")
- .span_label(span, "invalid escape")
- .help("unicode escape must not be a surrogate")
- .emit();
+ handler.emit_err(UnescapeError::InvalidUnicodeEscape { span, surrogate: true });
}
EscapeError::OutOfRangeUnicodeEscape => {
- handler
- .struct_span_err(span, "invalid unicode character escape")
- .span_label(span, "invalid escape")
- .help("unicode escape must be at most 10FFFF")
- .emit();
+ handler.emit_err(UnescapeError::InvalidUnicodeEscape { span, surrogate: false });
}
EscapeError::MoreThanOneChar => {
use unicode_normalization::{char::is_combining_mark, UnicodeNormalization};
+ let mut sugg = None;
+ let mut note = None;
- 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::<Vec<_>>();
- handler.span_note(
- span,
- &format!(
- "this `{}` is followed by the combining mark{} `{}`",
- lit.chars().next().unwrap(),
- pluralize!(escaped_marks.len()),
- escaped_marks.join(""),
- ),
- );
+ let lit_chars = lit.chars().collect::<Vec<_>>();
+ let (first, rest) = lit_chars.split_first().unwrap();
+ if rest.iter().copied().all(is_combining_mark) {
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,
- );
+ let ch = normalized.chars().next().unwrap().escape_default().to_string();
+ sugg = Some(MoreThanOneCharSugg::NormalizedForm { span, ch, normalized });
}
+ let escaped_marks =
+ rest.iter().map(|c| c.escape_default().to_string()).collect::<Vec<_>>();
+ note = Some(MoreThanOneCharNote::AllCombining {
+ span,
+ chr: format!("{first}"),
+ len: escaped_marks.len(),
+ escaped_marks: escaped_marks.join(""),
+ });
} else {
let printable: Vec<char> = lit
.chars()
@@ -87,32 +68,18 @@ pub(crate) fn emit_unescape_error(
})
.collect();
- if let [ch] = printable.as_slice() {
- has_help = true;
-
- handler.span_note(
+ if let &[ch] = printable.as_slice() {
+ sugg =
+ Some(MoreThanOneCharSugg::RemoveNonPrinting { span, ch: ch.to_string() });
+ note = Some(MoreThanOneCharNote::NonPrinting {
span,
- &format!(
- "there are non-printing characters, the full sequence is `{}`",
- lit.escape_default(),
- ),
- );
-
- handler.span_suggestion(
- span,
- "consider removing the non-printing characters",
- ch,
- Applicability::MaybeIncorrect,
- );
+ escaped: lit.escape_default().to_string(),
+ });
}
- }
-
- if !has_help {
- let (prefix, msg) = if mode.is_byte() {
- ("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")
- };
+ };
+ let sugg = sugg.unwrap_or_else(|| {
+ let is_byte = mode.is_byte();
+ let prefix = if is_byte { "b" } else { "" };
let mut escaped = String::with_capacity(lit.len());
let mut chrs = lit.chars().peekable();
while let Some(first) = chrs.next() {
@@ -129,54 +96,32 @@ pub(crate) fn emit_unescape_error(
(c, _) => escaped.push(c),
};
}
- handler.span_suggestion(
- span_with_quotes,
- msg,
- format!("{prefix}\"{escaped}\""),
- Applicability::MachineApplicable,
- );
- }
-
- handler.emit();
+ let sugg = format!("{prefix}\"{escaped}\"");
+ MoreThanOneCharSugg::Quotes { span: span_with_quotes, is_byte, sugg }
+ });
+ handler.emit_err(UnescapeError::MoreThanOneChar {
+ span: span_with_quotes,
+ note,
+ suggestion: sugg,
+ });
}
EscapeError::EscapeOnlyChar => {
let (c, char_span) = last_char();
-
- let msg = if mode.is_byte() {
- "byte constant must be escaped"
- } else {
- "character constant must be escaped"
- };
- handler
- .struct_span_err(span, &format!("{}: `{}`", msg, escaped_char(c)))
- .span_suggestion(
- char_span,
- "escape the character",
- c.escape_default(),
- Applicability::MachineApplicable,
- )
- .emit();
+ handler.emit_err(UnescapeError::EscapeOnlyChar {
+ span,
+ char_span,
+ escaped_sugg: c.escape_default().to_string(),
+ escaped_msg: escaped_char(c),
+ byte: mode.is_byte(),
+ });
}
EscapeError::BareCarriageReturn => {
- let msg = if mode.in_double_quotes() {
- "bare CR not allowed in string, use `\\r` instead"
- } else {
- "character constant must be escaped: `\\r`"
- };
- handler
- .struct_span_err(span, msg)
- .span_suggestion(
- span,
- "escape the character",
- "\\r",
- Applicability::MachineApplicable,
- )
- .emit();
+ let double_quotes = mode.in_double_quotes();
+ handler.emit_err(UnescapeError::BareCr { span, double_quotes });
}
EscapeError::BareCarriageReturnInRawString => {
assert!(mode.in_double_quotes());
- let msg = "bare CR not allowed in raw string";
- handler.span_err(span, msg);
+ handler.emit_err(UnescapeError::BareCrRawString(span));
}
EscapeError::InvalidEscape => {
let (c, span) = last_char();
@@ -213,22 +158,13 @@ pub(crate) fn emit_unescape_error(
diag.emit();
}
EscapeError::TooShortHexEscape => {
- handler.span_err(span, "numeric character escape is too short");
+ handler.emit_err(UnescapeError::TooShortHexEscape(span));
}
EscapeError::InvalidCharInHexEscape | EscapeError::InvalidCharInUnicodeEscape => {
let (c, span) = last_char();
-
- let msg = if error == EscapeError::InvalidCharInHexEscape {
- "invalid character in numeric character escape"
- } else {
- "invalid character in unicode escape"
- };
- let c = escaped_char(c);
-
- handler
- .struct_span_err(span, &format!("{}: `{}`", msg, c))
- .span_label(span, msg)
- .emit();
+ let is_hex = error == EscapeError::InvalidCharInHexEscape;
+ let ch = escaped_char(c);
+ handler.emit_err(UnescapeError::InvalidCharInEscape { span, is_hex, ch });
}
EscapeError::NonAsciiCharInByte => {
let (c, span) = last_char();
@@ -278,41 +214,22 @@ pub(crate) fn emit_unescape_error(
err.emit();
}
EscapeError::OutOfRangeHexEscape => {
- handler
- .struct_span_err(span, "out of range hex escape")
- .span_label(span, "must be a character in the range [\\x00-\\x7f]")
- .emit();
+ handler.emit_err(UnescapeError::OutOfRangeHexEscape(span));
}
EscapeError::LeadingUnderscoreUnicodeEscape => {
let (c, span) = last_char();
- let msg = "invalid start of unicode escape";
- handler
- .struct_span_err(span, &format!("{}: `{}`", msg, c))
- .span_label(span, msg)
- .emit();
+ handler.emit_err(UnescapeError::LeadingUnderscoreUnicodeEscape {
+ span,
+ ch: escaped_char(c),
+ });
}
EscapeError::OverlongUnicodeEscape => {
- handler
- .struct_span_err(span, "overlong unicode escape")
- .span_label(span, "must have at most 6 hex digits")
- .emit();
+ handler.emit_err(UnescapeError::OverlongUnicodeEscape(span));
}
EscapeError::UnclosedUnicodeEscape => {
- handler
- .struct_span_err(span, "unterminated unicode escape")
- .span_label(span, "missing a closing `}`")
- .span_suggestion_verbose(
- span.shrink_to_hi(),
- "terminate the unicode escape",
- "}",
- Applicability::MaybeIncorrect,
- )
- .emit();
+ handler.emit_err(UnescapeError::UnclosedUnicodeEscape(span, span.shrink_to_hi()));
}
EscapeError::NoBraceInUnicodeEscape => {
- let msg = "incorrect unicode escape sequence";
- let mut diag = handler.struct_span_err(span, msg);
-
let mut suggestion = "\\u{".to_owned();
let mut suggestion_len = 0;
let (c, char_span) = last_char();
@@ -322,54 +239,37 @@ pub(crate) fn emit_unescape_error(
suggestion_len += c.len_utf8();
}
- if suggestion_len > 0 {
+ let (label, sub) = if suggestion_len > 0 {
suggestion.push('}');
let hi = char_span.lo() + BytePos(suggestion_len as u32);
- diag.span_suggestion(
- span.with_hi(hi),
- "format of unicode escape sequences uses braces",
- suggestion,
- Applicability::MaybeIncorrect,
- );
+ (None, NoBraceUnicodeSub::Suggestion { span: span.with_hi(hi), suggestion })
} else {
- diag.span_label(span, msg);
- diag.help("format of unicode escape sequences is `\\u{...}`");
- }
-
- diag.emit();
+ (Some(span), NoBraceUnicodeSub::Help)
+ };
+ handler.emit_err(UnescapeError::NoBraceInUnicodeEscape { span, label, sub });
}
EscapeError::UnicodeEscapeInByte => {
- let msg = "unicode escape in byte string";
- handler
- .struct_span_err(span, msg)
- .span_label(span, msg)
- .help("unicode escape sequences cannot be used as a byte or in a byte string")
- .emit();
+ handler.emit_err(UnescapeError::UnicodeEscapeInByte(span));
}
EscapeError::EmptyUnicodeEscape => {
- handler
- .struct_span_err(span, "empty unicode escape")
- .span_label(span, "this escape must have at least 1 hex digit")
- .emit();
+ handler.emit_err(UnescapeError::EmptyUnicodeEscape(span));
}
EscapeError::ZeroChars => {
- let msg = "empty character literal";
- handler.struct_span_err(span, msg).span_label(span, msg).emit();
+ handler.emit_err(UnescapeError::ZeroChars(span));
}
EscapeError::LoneSlash => {
- let msg = "invalid trailing slash in literal";
- handler.struct_span_err(span, msg).span_label(span, msg).emit();
+ handler.emit_err(UnescapeError::LoneSlash(span));
}
EscapeError::UnskippedWhitespaceWarning => {
let (c, char_span) = last_char();
- let msg =
- format!("non-ASCII whitespace symbol '{}' is not skipped", c.escape_unicode());
- handler.struct_span_warn(span, &msg).span_label(char_span, &msg).emit();
+ handler.emit_warning(UnescapeError::UnskippedWhitespace {
+ span,
+ ch: escaped_char(c),
+ char_span,
+ });
}
EscapeError::MultipleSkippedLinesWarning => {
- let msg = "multiple lines skipped by escaped newline";
- let bottom_msg = "skipping everything up to and including this point";
- handler.struct_span_warn(span, msg).span_label(span, bottom_msg).emit();
+ handler.emit_warning(UnescapeError::MultipleSkippedLinesWarning(span));
}
}
}
diff --git a/compiler/rustc_parse/src/lexer/unicode_chars.rs b/compiler/rustc_parse/src/lexer/unicode_chars.rs
index 34d003ccf..d4f971d5b 100644
--- a/compiler/rustc_parse/src/lexer/unicode_chars.rs
+++ b/compiler/rustc_parse/src/lexer/unicode_chars.rs
@@ -2,8 +2,10 @@
//! <https://www.unicode.org/Public/security/10.0.0/confusables.txt>
use super::StringReader;
-use crate::token::{self, Delimiter};
-use rustc_errors::{Applicability, Diagnostic};
+use crate::{
+ errors::TokenSubstitution,
+ token::{self, Delimiter},
+};
use rustc_span::{symbol::kw, BytePos, Pos, Span};
#[rustfmt::skip] // for line breaks
@@ -338,48 +340,44 @@ pub(super) fn check_for_substitution<'a>(
reader: &StringReader<'a>,
pos: BytePos,
ch: char,
- err: &mut Diagnostic,
count: usize,
-) -> Option<token::TokenKind> {
- let &(_, u_name, ascii_str) = UNICODE_ARRAY.iter().find(|&&(c, _, _)| c == ch)?;
+) -> (Option<token::TokenKind>, Option<TokenSubstitution>) {
+ let Some(&(_, u_name, ascii_str)) = UNICODE_ARRAY.iter().find(|&&(c, _, _)| c == ch) else {
+ return (None, None);
+ };
let span = Span::with_root_ctxt(pos, pos + Pos::from_usize(ch.len_utf8() * count));
let Some((_, ascii_name, token)) = ASCII_ARRAY.iter().find(|&&(s, _, _)| s == ascii_str) else {
let msg = format!("substitution character not found for '{}'", ch);
reader.sess.span_diagnostic.span_bug_no_panic(span, &msg);
- return None;
+ return (None, None);
};
// special help suggestion for "directed" double quotes
- if let Some(s) = peek_delimited(&reader.src[reader.src_index(pos)..], '“', '”') {
- let msg = format!(
- "Unicode characters '“' (Left Double Quotation Mark) and \
- '”' (Right Double Quotation Mark) look like '{}' ({}), but are not",
- ascii_str, ascii_name
- );
- err.span_suggestion(
- Span::with_root_ctxt(
- pos,
- pos + Pos::from_usize('“'.len_utf8() + s.len() + '”'.len_utf8()),
- ),
- &msg,
- format!("\"{}\"", s),
- Applicability::MaybeIncorrect,
+ let sugg = if let Some(s) = peek_delimited(&reader.src[reader.src_index(pos)..], '“', '”') {
+ let span = Span::with_root_ctxt(
+ pos,
+ pos + Pos::from_usize('“'.len_utf8() + s.len() + '”'.len_utf8()),
);
+ Some(TokenSubstitution::DirectedQuotes {
+ span,
+ suggestion: format!("\"{s}\""),
+ ascii_str,
+ ascii_name,
+ })
} else {
- let msg = format!(
- "Unicode character '{}' ({}) looks like '{}' ({}), but it is not",
- ch, u_name, ascii_str, ascii_name
- );
- err.span_suggestion(
+ let suggestion = ascii_str.to_string().repeat(count);
+ Some(TokenSubstitution::Other {
span,
- &msg,
- ascii_str.to_string().repeat(count),
- Applicability::MaybeIncorrect,
- );
- }
- token.clone()
+ suggestion,
+ ch: ch.to_string(),
+ u_name,
+ ascii_str,
+ ascii_name,
+ })
+ };
+ (token.clone(), sugg)
}
/// Extract string if found at current position with given delimiters
diff --git a/compiler/rustc_parse/src/lib.rs b/compiler/rustc_parse/src/lib.rs
index b49a01d75..d1c3fd0cd 100644
--- a/compiler/rustc_parse/src/lib.rs
+++ b/compiler/rustc_parse/src/lib.rs
@@ -19,6 +19,8 @@ use rustc_ast::{AttrItem, Attribute, MetaItem};
use rustc_ast_pretty::pprust;
use rustc_data_structures::sync::Lrc;
use rustc_errors::{Applicability, Diagnostic, FatalError, Level, PResult};
+use rustc_errors::{DiagnosticMessage, SubdiagnosticMessage};
+use rustc_macros::fluent_messages;
use rustc_session::parse::ParseSess;
use rustc_span::{FileName, SourceFile, Span};
@@ -28,12 +30,14 @@ pub const MACRO_ARGUMENTS: Option<&str> = Some("macro arguments");
#[macro_use]
pub mod parser;
-use parser::{emit_unclosed_delims, make_unclosed_delims_error, Parser};
+use parser::{make_unclosed_delims_error, Parser};
pub mod lexer;
pub mod validate_attr;
mod errors;
+fluent_messages! { "../locales/en-US.ftl" }
+
// A bunch of utility functions of the form `parse_<thing>_from_<source>`
// where <thing> includes crate, expr, item, stmt, tts, and one that
// uses a HOF to parse anything, and <source> includes file and
@@ -92,10 +96,7 @@ pub fn parse_stream_from_source_str(
sess: &ParseSess,
override_span: Option<Span>,
) -> TokenStream {
- let (stream, mut errors) =
- source_file_to_stream(sess, sess.source_map().new_source_file(name, source), override_span);
- emit_unclosed_delims(&mut errors, &sess);
- stream
+ source_file_to_stream(sess, sess.source_map().new_source_file(name, source), override_span)
}
/// Creates a new parser from a source string.
@@ -131,9 +132,8 @@ fn maybe_source_file_to_parser(
source_file: Lrc<SourceFile>,
) -> Result<Parser<'_>, Vec<Diagnostic>> {
let end_pos = source_file.end_pos;
- let (stream, unclosed_delims) = maybe_file_to_stream(sess, source_file, None)?;
+ let stream = maybe_file_to_stream(sess, source_file, None)?;
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(), None);
}
@@ -178,7 +178,7 @@ pub fn source_file_to_stream(
sess: &ParseSess,
source_file: Lrc<SourceFile>,
override_span: Option<Span>,
-) -> (TokenStream, Vec<lexer::UnmatchedBrace>) {
+) -> TokenStream {
panictry_buffer!(&sess.span_diagnostic, maybe_file_to_stream(sess, source_file, override_span))
}
@@ -188,7 +188,7 @@ pub fn maybe_file_to_stream(
sess: &ParseSess,
source_file: Lrc<SourceFile>,
override_span: Option<Span>,
-) -> Result<(TokenStream, Vec<lexer::UnmatchedBrace>), Vec<Diagnostic>> {
+) -> Result<TokenStream, Vec<Diagnostic>> {
let src = source_file.src.as_ref().unwrap_or_else(|| {
sess.span_diagnostic.bug(&format!(
"cannot lex `source_file` without source: {}",
@@ -196,23 +196,7 @@ pub fn maybe_file_to_stream(
));
});
- let (token_trees, unmatched_braces) =
- lexer::parse_token_trees(sess, src.as_str(), source_file.start_pos, override_span);
-
- match token_trees {
- Ok(stream) => Ok((stream, unmatched_braces)),
- Err(err) => {
- let mut buffer = Vec::with_capacity(1);
- err.buffer(&mut buffer);
- // Not using `emit_unclosed_delims` to use `db.buffer`
- for unmatched in unmatched_braces {
- if let Some(err) = make_unclosed_delims_error(unmatched, &sess) {
- err.buffer(&mut buffer);
- }
- }
- Err(buffer)
- }
- }
+ lexer::parse_token_trees(sess, src.as_str(), source_file.start_pos, override_span)
}
/// Given a stream and the `ParseSess`, produces a parser.
diff --git a/compiler/rustc_parse/src/parser/attr.rs b/compiler/rustc_parse/src/parser/attr.rs
index 686454a8f..e3e7c63e3 100644
--- a/compiler/rustc_parse/src/parser/attr.rs
+++ b/compiler/rustc_parse/src/parser/attr.rs
@@ -1,11 +1,15 @@
use crate::errors::{InvalidMetaItem, SuffixedLiteralInAttribute};
+use crate::fluent_generated as fluent;
use super::{AttrWrapper, Capturing, FnParseMode, ForceCollect, Parser, PathStyle};
use rustc_ast as ast;
use rustc_ast::attr;
use rustc_ast::token::{self, Delimiter, Nonterminal};
-use rustc_errors::{error_code, fluent, Diagnostic, IntoDiagnostic, PResult};
+use rustc_errors::{error_code, Diagnostic, IntoDiagnostic, PResult};
use rustc_span::{sym, BytePos, Span};
+use std::convert::TryInto;
+use thin_vec::ThinVec;
+use tracing::debug;
// Public for rustfmt usage
#[derive(Debug)]
@@ -65,10 +69,10 @@ impl<'a> Parser<'a> {
token::CommentKind::Block => OuterAttributeType::DocBlockComment,
},
) {
- err.note(fluent::note);
+ err.note(fluent::parse_note);
err.span_suggestion_verbose(
replacement_span,
- fluent::suggestion,
+ fluent::parse_suggestion,
"",
rustc_errors::Applicability::MachineApplicable,
);
@@ -172,10 +176,10 @@ impl<'a> Parser<'a> {
Ok(Some(item)) => {
// FIXME(#100717)
err.set_arg("item", item.kind.descr());
- err.span_label(item.span, fluent::label_does_not_annotate_this);
+ err.span_label(item.span, fluent::parse_label_does_not_annotate_this);
err.span_suggestion_verbose(
replacement_span,
- fluent::sugg_change_inner_to_outer,
+ fluent::parse_sugg_change_inner_to_outer,
match attr_type {
OuterAttributeType::Attribute => "",
OuterAttributeType::DocBlockComment => "*",
@@ -201,8 +205,8 @@ impl<'a> Parser<'a> {
attr_sp,
fluent::parse_inner_attr_not_permitted_after_outer_doc_comment,
);
- diag.span_label(attr_sp, fluent::label_attr)
- .span_label(prev_doc_comment_span, fluent::label_prev_doc_comment);
+ diag.span_label(attr_sp, fluent::parse_label_attr)
+ .span_label(prev_doc_comment_span, fluent::parse_label_prev_doc_comment);
diag
}
Some(InnerAttrForbiddenReason::AfterOuterAttribute { prev_outer_attr_sp }) => {
@@ -210,8 +214,8 @@ impl<'a> Parser<'a> {
attr_sp,
fluent::parse_inner_attr_not_permitted_after_outer_attr,
);
- diag.span_label(attr_sp, fluent::label_attr)
- .span_label(prev_outer_attr_sp, fluent::label_prev_attr);
+ diag.span_label(attr_sp, fluent::parse_label_attr)
+ .span_label(prev_outer_attr_sp, fluent::parse_label_prev_attr);
diag
}
Some(InnerAttrForbiddenReason::InCodeBlock) | None => {
@@ -346,9 +350,9 @@ impl<'a> Parser<'a> {
}
/// Matches `COMMASEP(meta_item_inner)`.
- pub(crate) fn parse_meta_seq_top(&mut self) -> PResult<'a, Vec<ast::NestedMetaItem>> {
+ pub(crate) fn parse_meta_seq_top(&mut self) -> PResult<'a, ThinVec<ast::NestedMetaItem>> {
// Presumably, the majority of the time there will only be one attr.
- let mut nmis = Vec::with_capacity(1);
+ let mut nmis = ThinVec::with_capacity(1);
while self.token.kind != token::Eof {
nmis.push(self.parse_meta_item_inner()?);
if !self.eat(&token::Comma) {
diff --git a/compiler/rustc_parse/src/parser/attr_wrapper.rs b/compiler/rustc_parse/src/parser/attr_wrapper.rs
index b97f22417..b0ab0f106 100644
--- a/compiler/rustc_parse/src/parser/attr_wrapper.rs
+++ b/compiler/rustc_parse/src/parser/attr_wrapper.rs
@@ -134,11 +134,11 @@ impl ToAttrTokenStream for LazyAttrTokenStreamImpl {
// Process the replace ranges, starting from the highest start
// position and working our way back. If have tokens like:
//
- // `#[cfg(FALSE)]` struct Foo { #[cfg(FALSE)] field: bool }`
+ // `#[cfg(FALSE)] struct Foo { #[cfg(FALSE)] field: bool }`
//
// Then we will generate replace ranges for both
// the `#[cfg(FALSE)] field: bool` and the entire
- // `#[cfg(FALSE)]` struct Foo { #[cfg(FALSE)] field: bool }`
+ // `#[cfg(FALSE)] struct Foo { #[cfg(FALSE)] field: bool }`
//
// By starting processing from the replace range with the greatest
// start position, we ensure that any replace range which encloses
@@ -469,6 +469,6 @@ mod size_asserts {
use rustc_data_structures::static_assert_size;
// tidy-alphabetical-start
static_assert_size!(AttrWrapper, 16);
- static_assert_size!(LazyAttrTokenStreamImpl, 144);
+ static_assert_size!(LazyAttrTokenStreamImpl, 120);
// tidy-alphabetical-end
}
diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs
index 4c918c670..a051dbe9f 100644
--- a/compiler/rustc_parse/src/parser/diagnostics.rs
+++ b/compiler/rustc_parse/src/parser/diagnostics.rs
@@ -18,7 +18,8 @@ use crate::errors::{
UseEqInstead,
};
-use crate::lexer::UnmatchedBrace;
+use crate::fluent_generated as fluent;
+use crate::lexer::UnmatchedDelim;
use crate::parser;
use rustc_ast as ast;
use rustc_ast::ptr::P;
@@ -32,10 +33,9 @@ use rustc_ast::{
use rustc_ast_pretty::pprust;
use rustc_data_structures::fx::FxHashSet;
use rustc_errors::{
- fluent, Applicability, DiagnosticBuilder, DiagnosticMessage, FatalError, Handler, MultiSpan,
- PResult,
+ pluralize, Applicability, Diagnostic, DiagnosticBuilder, DiagnosticMessage, ErrorGuaranteed,
+ FatalError, Handler, IntoDiagnostic, MultiSpan, PResult,
};
-use rustc_errors::{pluralize, Diagnostic, ErrorGuaranteed, IntoDiagnostic};
use rustc_session::errors::ExprParenthesesNeeded;
use rustc_span::source_map::Spanned;
use rustc_span::symbol::{kw, sym, Ident};
@@ -165,8 +165,6 @@ enum IsStandalone {
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
enum IncOrDec {
Inc,
- // FIXME: `i--` recovery isn't implemented yet
- #[allow(dead_code)]
Dec,
}
@@ -222,7 +220,7 @@ impl MultiSugg {
/// is dropped.
pub struct SnapshotParser<'a> {
parser: Parser<'a>,
- unclosed_delims: Vec<UnmatchedBrace>,
+ unclosed_delims: Vec<UnmatchedDelim>,
}
impl<'a> Deref for SnapshotParser<'a> {
@@ -264,7 +262,7 @@ impl<'a> Parser<'a> {
self.unclosed_delims.extend(snapshot.unclosed_delims);
}
- pub fn unclosed_delims(&self) -> &[UnmatchedBrace] {
+ pub fn unclosed_delims(&self) -> &[UnmatchedDelim] {
&self.unclosed_delims
}
@@ -284,7 +282,7 @@ impl<'a> Parser<'a> {
self.sess.source_map().span_to_snippet(span)
}
- pub(super) fn expected_ident_found(&self) -> DiagnosticBuilder<'a, ErrorGuaranteed> {
+ pub(super) fn expected_ident_found(&mut self) -> DiagnosticBuilder<'a, ErrorGuaranteed> {
let valid_follow = &[
TokenKind::Eq,
TokenKind::Colon,
@@ -324,7 +322,61 @@ impl<'a> Parser<'a> {
suggest_raw,
suggest_remove_comma,
};
- err.into_diagnostic(&self.sess.span_diagnostic)
+ let mut err = err.into_diagnostic(&self.sess.span_diagnostic);
+
+ // if the token we have is a `<`
+ // it *might* be a misplaced generic
+ if self.token == token::Lt {
+ // all keywords that could have generic applied
+ let valid_prev_keywords =
+ [kw::Fn, kw::Type, kw::Struct, kw::Enum, kw::Union, kw::Trait];
+
+ // If we've expected an identifier,
+ // and the current token is a '<'
+ // if the previous token is a valid keyword
+ // that might use a generic, then suggest a correct
+ // generic placement (later on)
+ let maybe_keyword = self.prev_token.clone();
+ if valid_prev_keywords.into_iter().any(|x| maybe_keyword.is_keyword(x)) {
+ // if we have a valid keyword, attempt to parse generics
+ // also obtain the keywords symbol
+ match self.parse_generics() {
+ Ok(generic) => {
+ if let TokenKind::Ident(symbol, _) = maybe_keyword.kind {
+ let ident_name = symbol;
+ // at this point, we've found something like
+ // `fn <T>id`
+ // and current token should be Ident with the item name (i.e. the function name)
+ // if there is a `<` after the fn name, then don't show a suggestion, show help
+
+ if !self.look_ahead(1, |t| *t == token::Lt) &&
+ let Ok(snippet) = self.sess.source_map().span_to_snippet(generic.span) {
+ err.multipart_suggestion_verbose(
+ format!("place the generic parameter name after the {ident_name} name"),
+ vec![
+ (self.token.span.shrink_to_hi(), snippet),
+ (generic.span, String::new())
+ ],
+ Applicability::MaybeIncorrect,
+ );
+ } else {
+ err.help(format!(
+ "place the generic parameter name after the {ident_name} name"
+ ));
+ }
+ }
+ }
+ Err(err) => {
+ // if there's an error parsing the generics,
+ // then don't do a misplaced generics suggestion
+ // and emit the expected ident error instead;
+ err.cancel();
+ }
+ }
+ }
+ }
+
+ err
}
pub(super) fn expected_one_of_not_found(
@@ -639,7 +691,7 @@ impl<'a> Parser<'a> {
span: self.prev_token.span.shrink_to_lo(),
tokens: None,
};
- let struct_expr = snapshot.parse_struct_expr(None, path, false);
+ let struct_expr = snapshot.parse_expr_struct(None, path, false);
let block_tail = self.parse_block_tail(lo, s, AttemptLocalParseRecovery::No);
return Some(match (struct_expr, block_tail) {
(Ok(expr), Err(mut err)) => {
@@ -654,7 +706,7 @@ impl<'a> Parser<'a> {
err.delay_as_bug();
self.restore_snapshot(snapshot);
let mut tail = self.mk_block(
- vec![self.mk_stmt_err(expr.span)],
+ thin_vec![self.mk_stmt_err(expr.span)],
s,
lo.to(self.prev_token.span),
);
@@ -1303,6 +1355,20 @@ impl<'a> Parser<'a> {
self.recover_from_inc_dec(operand_expr, kind, op_span)
}
+ pub(super) fn recover_from_postfix_decrement(
+ &mut self,
+ operand_expr: P<Expr>,
+ op_span: Span,
+ start_stmt: bool,
+ ) -> PResult<'a, P<Expr>> {
+ let kind = IncDecRecovery {
+ standalone: if start_stmt { IsStandalone::Standalone } else { IsStandalone::Subexpr },
+ op: IncOrDec::Dec,
+ fixity: UnaryFixity::Post,
+ };
+ self.recover_from_inc_dec(operand_expr, kind, op_span)
+ }
+
fn recover_from_inc_dec(
&mut self,
base: P<Expr>,
@@ -1570,7 +1636,7 @@ impl<'a> Parser<'a> {
// Handle `await { <expr> }`.
// This needs to be handled separately from the next arm to avoid
// interpreting `await { <expr> }?` as `<expr>?.await`.
- self.parse_block_expr(None, self.token.span, BlockCheckMode::Default)
+ self.parse_expr_block(None, self.token.span, BlockCheckMode::Default)
} else {
self.parse_expr()
}
@@ -2030,7 +2096,7 @@ impl<'a> Parser<'a> {
}
pub(super) fn recover_arg_parse(&mut self) -> PResult<'a, (P<ast::Pat>, P<ast::Ty>)> {
- let pat = self.parse_pat_no_top_alt(Some("argument name"))?;
+ let pat = self.parse_pat_no_top_alt(Some(Expected::ArgumentName))?;
self.expect(&token::Colon)?;
let ty = self.parse_ty()?;
@@ -2121,7 +2187,7 @@ impl<'a> Parser<'a> {
/// the parameters are *names* (so we don't emit errors about not being able to find `b` in
/// the local scope), but if we find the same name multiple times, like in `fn foo(i8, i8)`,
/// we deduplicate them to not complain about duplicated parameter names.
- pub(super) fn deduplicate_recovered_params_names(&self, fn_inputs: &mut Vec<Param>) {
+ pub(super) fn deduplicate_recovered_params_names(&self, fn_inputs: &mut ThinVec<Param>) {
let mut seen_inputs = FxHashSet::default();
for input in fn_inputs.iter_mut() {
let opt_ident = if let (PatKind::Ident(_, ident, _), TyKind::Err) =
@@ -2145,7 +2211,7 @@ impl<'a> Parser<'a> {
/// like the user has forgotten them.
pub fn handle_ambiguous_unbraced_const_arg(
&mut self,
- args: &mut Vec<AngleBracketedArg>,
+ args: &mut ThinVec<AngleBracketedArg>,
) -> PResult<'a, bool> {
// If we haven't encountered a closing `>`, then the argument is malformed.
// It's likely that the user has written a const expression without enclosing it
@@ -2353,6 +2419,28 @@ impl<'a> Parser<'a> {
Err(err)
}
+ /// Try to recover from an unbraced const argument whose first token [could begin a type][ty].
+ ///
+ /// [ty]: token::Token::can_begin_type
+ pub(crate) fn recover_unbraced_const_arg_that_can_begin_ty(
+ &mut self,
+ mut snapshot: SnapshotParser<'a>,
+ ) -> Option<P<ast::Expr>> {
+ match snapshot.parse_expr_res(Restrictions::CONST_EXPR, None) {
+ // Since we don't know the exact reason why we failed to parse the type or the
+ // expression, employ a simple heuristic to weed out some pathological cases.
+ Ok(expr) if let token::Comma | token::Gt = snapshot.token.kind => {
+ self.restore_snapshot(snapshot);
+ Some(expr)
+ }
+ Ok(_) => None,
+ Err(err) => {
+ err.cancel();
+ None
+ }
+ }
+ }
+
/// Creates a dummy const argument, and reports that the expression must be enclosed in braces
pub fn dummy_const_arg_needs_braces(
&self,
@@ -2375,7 +2463,7 @@ impl<'a> Parser<'a> {
pub(crate) fn maybe_recover_colon_colon_in_pat_typo(
&mut self,
mut first_pat: P<Pat>,
- expected: Expected,
+ expected: Option<Expected>,
) -> P<Pat> {
if token::Colon != self.token.kind {
return first_pat;
@@ -2383,26 +2471,42 @@ impl<'a> Parser<'a> {
if !matches!(first_pat.kind, PatKind::Ident(_, _, None) | PatKind::Path(..))
|| !self.look_ahead(1, |token| token.is_ident() && !token.is_reserved_ident())
{
+ let mut snapshot_type = self.create_snapshot_for_diagnostic();
+ snapshot_type.bump(); // `:`
+ match snapshot_type.parse_ty() {
+ Err(inner_err) => {
+ inner_err.cancel();
+ }
+ Ok(ty) => {
+ let Err(mut err) = self.expected_one_of_not_found(&[], &[]) else {
+ return first_pat;
+ };
+ err.span_label(ty.span, "specifying the type of a pattern isn't supported");
+ self.restore_snapshot(snapshot_type);
+ let span = first_pat.span.to(ty.span);
+ first_pat = self.mk_pat(span, PatKind::Wild);
+ err.emit();
+ }
+ }
return first_pat;
}
// The pattern looks like it might be a path with a `::` -> `:` typo:
// `match foo { bar:baz => {} }`
- let span = self.token.span;
+ let colon_span = self.token.span;
// We only emit "unexpected `:`" error here if we can successfully parse the
// whole pattern correctly in that case.
- let snapshot = self.create_snapshot_for_diagnostic();
+ let mut snapshot_pat = self.create_snapshot_for_diagnostic();
+ let mut snapshot_type = self.create_snapshot_for_diagnostic();
// Create error for "unexpected `:`".
match self.expected_one_of_not_found(&[], &[]) {
Err(mut err) => {
- self.bump(); // Skip the `:`.
- match self.parse_pat_no_top_alt(expected) {
+ // Skip the `:`.
+ snapshot_pat.bump();
+ snapshot_type.bump();
+ match snapshot_pat.parse_pat_no_top_alt(expected) {
Err(inner_err) => {
- // Carry on as if we had not done anything, callers will emit a
- // reasonable error.
inner_err.cancel();
- err.cancel();
- self.restore_snapshot(snapshot);
}
Ok(mut pat) => {
// We've parsed the rest of the pattern.
@@ -2466,8 +2570,8 @@ impl<'a> Parser<'a> {
_ => {}
}
if show_sugg {
- err.span_suggestion(
- span,
+ err.span_suggestion_verbose(
+ colon_span.until(self.look_ahead(1, |t| t.span)),
"maybe write a path separator here",
"::",
Applicability::MaybeIncorrect,
@@ -2475,13 +2579,24 @@ impl<'a> Parser<'a> {
} else {
first_pat = self.mk_pat(new_span, PatKind::Wild);
}
- err.emit();
+ self.restore_snapshot(snapshot_pat);
+ }
+ }
+ match snapshot_type.parse_ty() {
+ Err(inner_err) => {
+ inner_err.cancel();
+ }
+ Ok(ty) => {
+ err.span_label(ty.span, "specifying the type of a pattern isn't supported");
+ self.restore_snapshot(snapshot_type);
+ let new_span = first_pat.span.to(ty.span);
+ first_pat = self.mk_pat(new_span, PatKind::Wild);
}
}
+ err.emit();
}
_ => {
// Carry on as if we had not done anything. This should be unreachable.
- self.restore_snapshot(snapshot);
}
};
first_pat
diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs
index bf93a89f0..95a7ca80d 100644
--- a/compiler/rustc_parse/src/parser/expr.rs
+++ b/compiler/rustc_parse/src/parser/expr.rs
@@ -1,29 +1,12 @@
use super::diagnostics::SnapshotParser;
-use super::pat::{CommaRecoveryMode, RecoverColon, RecoverComma, PARAM_EXPECTED};
+use super::pat::{CommaRecoveryMode, Expected, RecoverColon, RecoverComma};
use super::ty::{AllowPlus, RecoverQPath, RecoverReturnSign};
use super::{
AttrWrapper, BlockMode, ClosureSpans, ForceCollect, Parser, PathStyle, Restrictions,
SemiColonMode, SeqSep, TokenExpectType, TokenType, TrailingToken,
};
-use crate::errors::{
- ArrayBracketsInsteadOfSpaces, ArrayBracketsInsteadOfSpacesSugg, AsyncMoveOrderIncorrect,
- BracesForStructLiteral, CatchAfterTry, CommaAfterBaseStruct, ComparisonInterpretedAsGeneric,
- ComparisonOrShiftInterpretedAsGenericSugg, DoCatchSyntaxRemoved, DotDotDot, EqFieldInit,
- ExpectedElseBlock, ExpectedEqForLetExpr, ExpectedExpressionFoundLet,
- FieldExpressionWithGeneric, FloatLiteralRequiresIntegerPart, FoundExprWouldBeStmt,
- IfExpressionMissingCondition, IfExpressionMissingThenBlock, IfExpressionMissingThenBlockSub,
- InvalidBlockMacroSegment, InvalidComparisonOperator, InvalidComparisonOperatorSub,
- InvalidInterpolatedExpression, InvalidLiteralSuffixOnTupleIndex, InvalidLogicalOperator,
- InvalidLogicalOperatorSub, LabeledLoopInBreak, LeadingPlusNotSupported, LeftArrowOperator,
- LifetimeInBorrowExpression, MacroInvocationWithQualifiedPath, MalformedLoopLabel,
- MatchArmBodyWithoutBraces, MatchArmBodyWithoutBracesSugg, MissingCommaAfterMatchArm,
- MissingDotDot, MissingInInForLoop, MissingInInForLoopSub, MissingSemicolonBeforeArray,
- NoFieldsForFnCall, NotAsNegationOperator, NotAsNegationOperatorSub,
- OuterAttributeNotAllowedOnIfElse, ParenthesesWithStructFields,
- RequireColonAfterLabeledExpression, ShiftInterpretedAsGeneric, StructLiteralNotAllowedHere,
- StructLiteralNotAllowedHereSugg, TildeAsUnaryOperator, UnexpectedIfWithIf,
- UnexpectedTokenAfterLabel, UnexpectedTokenAfterLabelSugg, WrapExpressionInParentheses,
-};
+
+use crate::errors;
use crate::maybe_recover_from_interpolated_ty_qpath;
use core::mem;
use rustc_ast::ptr::P;
@@ -39,8 +22,8 @@ use rustc_ast::{Arm, Async, BlockCheckMode, Expr, ExprKind, Label, Movability, R
use rustc_ast::{ClosureBinder, MetaItemLit, StmtKind};
use rustc_ast_pretty::pprust;
use rustc_errors::{
- Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed, IntoDiagnostic, PResult,
- StashKey,
+ AddToDiagnostic, Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed, IntoDiagnostic,
+ PResult, StashKey,
};
use rustc_session::errors::{report_lit_error, ExprParenthesesNeeded};
use rustc_session::lint::builtin::BREAK_WITH_LABEL_AND_LOOP;
@@ -48,6 +31,7 @@ use rustc_session::lint::BuiltinLintDiagnostics;
use rustc_span::source_map::{self, Span, Spanned};
use rustc_span::symbol::{kw, sym, Ident, Symbol};
use rustc_span::{BytePos, Pos};
+use thin_vec::{thin_vec, ThinVec};
/// Possibly accepts an `token::Interpolated` expression (a pre-parsed expression
/// dropped into the token stream, which happens while parsing the result of
@@ -119,7 +103,7 @@ impl<'a> Parser<'a> {
self.collect_tokens_no_attrs(|this| this.parse_expr())
}
- pub fn parse_anon_const_expr(&mut self) -> PResult<'a, AnonConst> {
+ pub fn parse_expr_anon_const(&mut self) -> PResult<'a, AnonConst> {
self.parse_expr().map(|value| AnonConst { id: DUMMY_NODE_ID, value })
}
@@ -141,7 +125,7 @@ impl<'a> Parser<'a> {
}
/// Parses a sequence of expressions delimited by parentheses.
- fn parse_paren_expr_seq(&mut self) -> PResult<'a, Vec<P<Expr>>> {
+ fn parse_expr_paren_seq(&mut self) -> PResult<'a, ThinVec<P<Expr>>> {
self.parse_paren_comma_seq(|p| p.parse_expr_catch_underscore()).map(|(r, _)| r)
}
@@ -152,7 +136,7 @@ impl<'a> Parser<'a> {
r: Restrictions,
already_parsed_attrs: Option<AttrWrapper>,
) -> PResult<'a, P<Expr>> {
- self.with_res(r, |this| this.parse_assoc_expr(already_parsed_attrs))
+ self.with_res(r, |this| this.parse_expr_assoc(already_parsed_attrs))
}
/// Parses an associative expression.
@@ -160,15 +144,15 @@ impl<'a> Parser<'a> {
/// This parses an expression accounting for associativity and precedence of the operators in
/// the expression.
#[inline]
- fn parse_assoc_expr(
+ fn parse_expr_assoc(
&mut self,
already_parsed_attrs: Option<AttrWrapper>,
) -> PResult<'a, P<Expr>> {
- self.parse_assoc_expr_with(0, already_parsed_attrs.into())
+ self.parse_expr_assoc_with(0, already_parsed_attrs.into())
}
/// Parses an associative expression with operators of at least `min_prec` precedence.
- pub(super) fn parse_assoc_expr_with(
+ pub(super) fn parse_expr_assoc_with(
&mut self,
min_prec: usize,
lhs: LhsExpr,
@@ -183,9 +167,9 @@ impl<'a> Parser<'a> {
_ => None,
};
if self.token.is_range_separator() {
- return self.parse_prefix_range_expr(attrs);
+ return self.parse_expr_prefix_range(attrs);
} else {
- self.parse_prefix_expr(attrs)?
+ self.parse_expr_prefix(attrs)?
}
};
let last_type_ascription_set = self.last_type_ascription.is_some();
@@ -243,10 +227,10 @@ impl<'a> Parser<'a> {
}
.into();
let invalid = format!("{}=", &sugg);
- self.sess.emit_err(InvalidComparisonOperator {
+ self.sess.emit_err(errors::InvalidComparisonOperator {
span: sp,
invalid: invalid.clone(),
- sub: InvalidComparisonOperatorSub::Correctable {
+ sub: errors::InvalidComparisonOperatorSub::Correctable {
span: sp,
invalid,
correct: sugg,
@@ -261,10 +245,10 @@ impl<'a> Parser<'a> {
&& self.prev_token.span.hi() == self.token.span.lo()
{
let sp = op.span.to(self.token.span);
- self.sess.emit_err(InvalidComparisonOperator {
+ self.sess.emit_err(errors::InvalidComparisonOperator {
span: sp,
invalid: "<>".into(),
- sub: InvalidComparisonOperatorSub::Correctable {
+ sub: errors::InvalidComparisonOperatorSub::Correctable {
span: sp,
invalid: "<>".into(),
correct: "!=".into(),
@@ -279,10 +263,10 @@ impl<'a> Parser<'a> {
&& self.prev_token.span.hi() == self.token.span.lo()
{
let sp = op.span.to(self.token.span);
- self.sess.emit_err(InvalidComparisonOperator {
+ self.sess.emit_err(errors::InvalidComparisonOperator {
span: sp,
invalid: "<=>".into(),
- sub: InvalidComparisonOperatorSub::Spaceship(sp),
+ sub: errors::InvalidComparisonOperatorSub::Spaceship(sp),
});
self.bump();
}
@@ -298,6 +282,18 @@ impl<'a> Parser<'a> {
continue;
}
+ if self.prev_token == token::BinOp(token::Minus)
+ && self.token == token::BinOp(token::Minus)
+ && self.prev_token.span.between(self.token.span).is_empty()
+ && !self.look_ahead(1, |tok| tok.can_begin_expr())
+ {
+ let op_span = self.prev_token.span.to(self.token.span);
+ // Eat the second `-`
+ self.bump();
+ lhs = self.recover_from_postfix_decrement(lhs, op_span, starts_stmt)?;
+ continue;
+ }
+
let op = op.node;
// Special cases:
if op == AssocOp::As {
@@ -309,7 +305,7 @@ impl<'a> Parser<'a> {
} else if op == AssocOp::DotDot || op == AssocOp::DotDotEq {
// If we didn't have to handle `x..`/`x..=`, it would be pretty easy to
// generalise it to the Fixity::None code.
- lhs = self.parse_range_expr(prec, lhs, op, cur_op_span)?;
+ lhs = self.parse_expr_range(prec, lhs, op, cur_op_span)?;
break;
}
@@ -322,7 +318,7 @@ impl<'a> Parser<'a> {
Fixity::None => 1,
};
let rhs = self.with_res(restrictions - Restrictions::STMT_EXPR, |this| {
- this.parse_assoc_expr_with(prec + prec_adjustment, LhsExpr::NotYetParsed)
+ this.parse_expr_assoc_with(prec + prec_adjustment, LhsExpr::NotYetParsed)
})?;
let span = self.mk_expr_sp(&lhs, lhs_span, rhs.span);
@@ -419,7 +415,7 @@ impl<'a> Parser<'a> {
/// but the next token implies this should be parsed as an expression.
/// For example: `if let Some(x) = x { x } else { 0 } / 2`.
fn error_found_expr_would_be_stmt(&self, lhs: &Expr) {
- self.sess.emit_err(FoundExprWouldBeStmt {
+ self.sess.emit_err(errors::FoundExprWouldBeStmt {
span: self.token.span,
token: self.token.clone(),
suggestion: ExprParenthesesNeeded::surrounding(lhs.span),
@@ -446,18 +442,18 @@ impl<'a> Parser<'a> {
}
(Some(op), _) => (op, self.token.span),
(None, Some((Ident { name: sym::and, span }, false))) if self.may_recover() => {
- self.sess.emit_err(InvalidLogicalOperator {
+ self.sess.emit_err(errors::InvalidLogicalOperator {
span: self.token.span,
incorrect: "and".into(),
- sub: InvalidLogicalOperatorSub::Conjunction(self.token.span),
+ sub: errors::InvalidLogicalOperatorSub::Conjunction(self.token.span),
});
(AssocOp::LAnd, span)
}
(None, Some((Ident { name: sym::or, span }, false))) if self.may_recover() => {
- self.sess.emit_err(InvalidLogicalOperator {
+ self.sess.emit_err(errors::InvalidLogicalOperator {
span: self.token.span,
incorrect: "or".into(),
- sub: InvalidLogicalOperatorSub::Disjunction(self.token.span),
+ sub: errors::InvalidLogicalOperatorSub::Disjunction(self.token.span),
});
(AssocOp::LOr, span)
}
@@ -474,7 +470,7 @@ impl<'a> Parser<'a> {
/// Parses `x..y`, `x..=y`, and `x..`/`x..=`.
/// The other two variants are handled in `parse_prefix_range_expr` below.
- fn parse_range_expr(
+ fn parse_expr_range(
&mut self,
prec: usize,
lhs: P<Expr>,
@@ -482,7 +478,7 @@ impl<'a> Parser<'a> {
cur_op_span: Span,
) -> PResult<'a, P<Expr>> {
let rhs = if self.is_at_start_of_range_notation_rhs() {
- Some(self.parse_assoc_expr_with(prec + 1, LhsExpr::NotYetParsed)?)
+ Some(self.parse_expr_assoc_with(prec + 1, LhsExpr::NotYetParsed)?)
} else {
None
};
@@ -507,7 +503,7 @@ impl<'a> Parser<'a> {
}
/// Parses prefix-forms of range notation: `..expr`, `..`, `..=expr`.
- fn parse_prefix_range_expr(&mut self, attrs: Option<AttrWrapper>) -> PResult<'a, P<Expr>> {
+ fn parse_expr_prefix_range(&mut self, attrs: Option<AttrWrapper>) -> PResult<'a, P<Expr>> {
// Check for deprecated `...` syntax.
if self.token == token::DotDotDot {
self.err_dotdotdot_syntax(self.token.span);
@@ -534,7 +530,7 @@ impl<'a> Parser<'a> {
this.bump();
let (span, opt_end) = if this.is_at_start_of_range_notation_rhs() {
// RHS must be parsed with more associativity than the dots.
- this.parse_assoc_expr_with(op.unwrap().precedence() + 1, LhsExpr::NotYetParsed)
+ this.parse_expr_assoc_with(op.unwrap().precedence() + 1, LhsExpr::NotYetParsed)
.map(|x| (lo.to(x.span), Some(x)))?
} else {
(lo, None)
@@ -545,7 +541,7 @@ impl<'a> Parser<'a> {
}
/// Parses a prefix-unary-operator expr.
- fn parse_prefix_expr(&mut self, attrs: Option<AttrWrapper>) -> PResult<'a, P<Expr>> {
+ fn parse_expr_prefix(&mut self, attrs: Option<AttrWrapper>) -> PResult<'a, P<Expr>> {
let attrs = self.parse_or_use_outer_attributes(attrs)?;
let lo = self.token.span;
@@ -563,25 +559,28 @@ impl<'a> Parser<'a> {
// Note: when adding new unary operators, don't forget to adjust TokenKind::can_begin_expr()
match this.token.uninterpolate().kind {
// `!expr`
- token::Not => make_it!(this, attrs, |this, _| this.parse_unary_expr(lo, UnOp::Not)),
+ token::Not => make_it!(this, attrs, |this, _| this.parse_expr_unary(lo, UnOp::Not)),
// `~expr`
token::Tilde => make_it!(this, attrs, |this, _| this.recover_tilde_expr(lo)),
// `-expr`
token::BinOp(token::Minus) => {
- make_it!(this, attrs, |this, _| this.parse_unary_expr(lo, UnOp::Neg))
+ make_it!(this, attrs, |this, _| this.parse_expr_unary(lo, UnOp::Neg))
}
// `*expr`
token::BinOp(token::Star) => {
- make_it!(this, attrs, |this, _| this.parse_unary_expr(lo, UnOp::Deref))
+ make_it!(this, attrs, |this, _| this.parse_expr_unary(lo, UnOp::Deref))
}
// `&expr` and `&&expr`
token::BinOp(token::And) | token::AndAnd => {
- make_it!(this, attrs, |this, _| this.parse_borrow_expr(lo))
+ make_it!(this, attrs, |this, _| this.parse_expr_borrow(lo))
}
// `+lit`
token::BinOp(token::Plus) if this.look_ahead(1, |tok| tok.is_numeric_lit()) => {
- let mut err =
- LeadingPlusNotSupported { span: lo, remove_plus: None, add_parentheses: None };
+ let mut err = errors::LeadingPlusNotSupported {
+ span: lo,
+ remove_plus: None,
+ add_parentheses: None,
+ };
// 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) {
@@ -592,7 +591,7 @@ impl<'a> Parser<'a> {
this.sess.emit_err(err);
this.bump();
- this.parse_prefix_expr(None)
+ this.parse_expr_prefix(None)
}
// Recover from `++x`:
token::BinOp(token::Plus)
@@ -605,41 +604,41 @@ impl<'a> Parser<'a> {
this.bump();
this.bump();
- let operand_expr = this.parse_dot_or_call_expr(Default::default())?;
+ let operand_expr = this.parse_expr_dot_or_call(Default::default())?;
this.recover_from_prefix_increment(operand_expr, pre_span, starts_stmt)
}
token::Ident(..) if this.token.is_keyword(kw::Box) => {
- make_it!(this, attrs, |this, _| this.parse_box_expr(lo))
+ make_it!(this, attrs, |this, _| this.parse_expr_box(lo))
}
token::Ident(..) if this.may_recover() && this.is_mistaken_not_ident_negation() => {
make_it!(this, attrs, |this, _| this.recover_not_expr(lo))
}
- _ => return this.parse_dot_or_call_expr(Some(attrs)),
+ _ => return this.parse_expr_dot_or_call(Some(attrs)),
}
}
- fn parse_prefix_expr_common(&mut self, lo: Span) -> PResult<'a, (Span, P<Expr>)> {
+ fn parse_expr_prefix_common(&mut self, lo: Span) -> PResult<'a, (Span, P<Expr>)> {
self.bump();
- let expr = self.parse_prefix_expr(None);
+ let expr = self.parse_expr_prefix(None);
let (span, expr) = self.interpolated_or_expr_span(expr)?;
Ok((lo.to(span), expr))
}
- fn parse_unary_expr(&mut self, lo: Span, op: UnOp) -> PResult<'a, (Span, ExprKind)> {
- let (span, expr) = self.parse_prefix_expr_common(lo)?;
+ fn parse_expr_unary(&mut self, lo: Span, op: UnOp) -> PResult<'a, (Span, ExprKind)> {
+ let (span, expr) = self.parse_expr_prefix_common(lo)?;
Ok((span, self.mk_unary(op, expr)))
}
/// Recover on `~expr` in favor of `!expr`.
fn recover_tilde_expr(&mut self, lo: Span) -> PResult<'a, (Span, ExprKind)> {
- self.sess.emit_err(TildeAsUnaryOperator(lo));
+ self.sess.emit_err(errors::TildeAsUnaryOperator(lo));
- self.parse_unary_expr(lo, UnOp::Not)
+ self.parse_expr_unary(lo, UnOp::Not)
}
/// Parse `box expr`.
- fn parse_box_expr(&mut self, lo: Span) -> PResult<'a, (Span, ExprKind)> {
- let (span, expr) = self.parse_prefix_expr_common(lo)?;
+ fn parse_expr_box(&mut self, lo: Span) -> PResult<'a, (Span, ExprKind)> {
+ let (span, expr) = self.parse_expr_prefix_common(lo)?;
self.sess.gated_spans.gate(sym::box_syntax, span);
Ok((span, ExprKind::Box(expr)))
}
@@ -660,14 +659,14 @@ impl<'a> Parser<'a> {
let negated_token = self.look_ahead(1, |t| t.clone());
let sub_diag = if negated_token.is_numeric_lit() {
- NotAsNegationOperatorSub::SuggestNotBitwise
+ errors::NotAsNegationOperatorSub::SuggestNotBitwise
} else if negated_token.is_bool_lit() {
- NotAsNegationOperatorSub::SuggestNotLogical
+ errors::NotAsNegationOperatorSub::SuggestNotLogical
} else {
- NotAsNegationOperatorSub::SuggestNotDefault
+ errors::NotAsNegationOperatorSub::SuggestNotDefault
};
- self.sess.emit_err(NotAsNegationOperator {
+ self.sess.emit_err(errors::NotAsNegationOperator {
negated: negated_token.span,
negated_desc: super::token_descr(&negated_token),
// Span the `not` plus trailing whitespace to avoid
@@ -677,7 +676,7 @@ impl<'a> Parser<'a> {
),
});
- self.parse_unary_expr(lo, UnOp::Not)
+ self.parse_expr_unary(lo, UnOp::Not)
}
/// Returns the span of expr, if it was not interpolated or the span of the interpolated token.
@@ -735,10 +734,10 @@ impl<'a> Parser<'a> {
segments[0].ident.span,
),
};
- match self.parse_labeled_expr(label, false) {
+ match self.parse_expr_labeled(label, false) {
Ok(expr) => {
type_err.cancel();
- self.sess.emit_err(MalformedLoopLabel {
+ self.sess.emit_err(errors::MalformedLoopLabel {
span: label.ident.span,
correct_label: label.ident,
});
@@ -763,20 +762,22 @@ impl<'a> Parser<'a> {
);
let args_span = self.look_ahead(1, |t| t.span).to(span_after_type);
- let suggestion = ComparisonOrShiftInterpretedAsGenericSugg {
+ let suggestion = errors::ComparisonOrShiftInterpretedAsGenericSugg {
left: expr.span.shrink_to_lo(),
right: expr.span.shrink_to_hi(),
};
match self.token.kind {
- token::Lt => self.sess.emit_err(ComparisonInterpretedAsGeneric {
- comparison: self.token.span,
- r#type: path,
- args: args_span,
- suggestion,
- }),
+ token::Lt => {
+ self.sess.emit_err(errors::ComparisonInterpretedAsGeneric {
+ comparison: self.token.span,
+ r#type: path,
+ args: args_span,
+ suggestion,
+ })
+ }
token::BinOp(token::Shl) => {
- self.sess.emit_err(ShiftInterpretedAsGeneric {
+ self.sess.emit_err(errors::ShiftInterpretedAsGeneric {
shift: self.token.span,
r#type: path,
args: args_span,
@@ -827,7 +828,7 @@ impl<'a> Parser<'a> {
("cast", None)
};
- let with_postfix = self.parse_dot_or_call_expr_with_(cast_expr, span)?;
+ let with_postfix = self.parse_expr_dot_or_call_with_(cast_expr, span)?;
// Check if an illegal postfix operator has been added after the cast.
// If the resulting expression is not a cast, it is an illegal postfix operator.
@@ -898,15 +899,15 @@ impl<'a> Parser<'a> {
}
/// Parse `& mut? <expr>` or `& raw [ const | mut ] <expr>`.
- fn parse_borrow_expr(&mut self, lo: Span) -> PResult<'a, (Span, ExprKind)> {
+ fn parse_expr_borrow(&mut self, lo: Span) -> PResult<'a, (Span, ExprKind)> {
self.expect_and()?;
let has_lifetime = self.token.is_lifetime() && self.look_ahead(1, |t| t != &token::Colon);
let lifetime = has_lifetime.then(|| self.expect_lifetime()); // For recovery, see below.
let (borrow_kind, mutbl) = self.parse_borrow_modifiers(lo);
let expr = if self.token.is_range_separator() {
- self.parse_prefix_range_expr(None)
+ self.parse_expr_prefix_range(None)
} else {
- self.parse_prefix_expr(None)
+ self.parse_expr_prefix(None)
};
let (hi, expr) = self.interpolated_or_expr_span(expr)?;
let span = lo.to(hi);
@@ -917,7 +918,7 @@ impl<'a> Parser<'a> {
}
fn error_remove_borrow_lifetime(&self, span: Span, lt_span: Span) {
- self.sess.emit_err(LifetimeInBorrowExpression { span, lifetime_span: lt_span });
+ self.sess.emit_err(errors::LifetimeInBorrowExpression { span, lifetime_span: lt_span });
}
/// Parse `mut?` or `raw [ const | mut ]`.
@@ -936,16 +937,16 @@ impl<'a> Parser<'a> {
}
/// Parses `a.b` or `a(13)` or `a[4]` or just `a`.
- fn parse_dot_or_call_expr(&mut self, attrs: Option<AttrWrapper>) -> PResult<'a, P<Expr>> {
+ fn parse_expr_dot_or_call(&mut self, attrs: Option<AttrWrapper>) -> PResult<'a, P<Expr>> {
let attrs = self.parse_or_use_outer_attributes(attrs)?;
self.collect_tokens_for_expr(attrs, |this, attrs| {
- let base = this.parse_bottom_expr();
+ let base = this.parse_expr_bottom();
let (span, base) = this.interpolated_or_expr_span(base)?;
- this.parse_dot_or_call_expr_with(base, span, attrs)
+ this.parse_expr_dot_or_call_with(base, span, attrs)
})
}
- pub(super) fn parse_dot_or_call_expr_with(
+ pub(super) fn parse_expr_dot_or_call_with(
&mut self,
e0: P<Expr>,
lo: Span,
@@ -954,7 +955,7 @@ impl<'a> Parser<'a> {
// Stitch the list of outer attributes onto the return value.
// A little bit ugly, but the best way given the current code
// structure
- let res = self.parse_dot_or_call_expr_with_(e0, lo);
+ let res = self.parse_expr_dot_or_call_with_(e0, lo);
if attrs.is_empty() {
res
} else {
@@ -968,7 +969,7 @@ impl<'a> Parser<'a> {
}
}
- fn parse_dot_or_call_expr_with_(&mut self, mut e: P<Expr>, lo: Span) -> PResult<'a, P<Expr>> {
+ fn parse_expr_dot_or_call_with_(&mut self, mut e: P<Expr>, lo: Span) -> PResult<'a, P<Expr>> {
loop {
let has_question = if self.prev_token.kind == TokenKind::Ident(kw::Return, false) {
// we are using noexpect here because we don't expect a `?` directly after a `return`
@@ -991,15 +992,15 @@ impl<'a> Parser<'a> {
};
if has_dot {
// expr.f
- e = self.parse_dot_suffix_expr(lo, e)?;
+ e = self.parse_expr_dot_suffix(lo, e)?;
continue;
}
if self.expr_is_complete(&e) {
return Ok(e);
}
e = match self.token.kind {
- token::OpenDelim(Delimiter::Parenthesis) => self.parse_fn_call_expr(lo, e),
- token::OpenDelim(Delimiter::Bracket) => self.parse_index_expr(lo, e)?,
+ token::OpenDelim(Delimiter::Parenthesis) => self.parse_expr_fn_call(lo, e),
+ token::OpenDelim(Delimiter::Bracket) => self.parse_expr_index(lo, e)?,
_ => return Ok(e),
}
}
@@ -1011,14 +1012,14 @@ impl<'a> Parser<'a> {
&& self.look_ahead(3, |t| t.can_begin_expr())
}
- fn parse_dot_suffix_expr(&mut self, lo: Span, base: P<Expr>) -> PResult<'a, P<Expr>> {
+ fn parse_expr_dot_suffix(&mut self, lo: Span, base: P<Expr>) -> PResult<'a, P<Expr>> {
match self.token.uninterpolate().kind {
token::Ident(..) => self.parse_dot_suffix(base, lo),
token::Literal(token::Lit { kind: token::Integer, symbol, suffix }) => {
- Ok(self.parse_tuple_field_access_expr(lo, base, symbol, suffix, None))
+ Ok(self.parse_expr_tuple_field_access(lo, base, symbol, suffix, None))
}
token::Literal(token::Lit { kind: token::Float, symbol, suffix }) => {
- Ok(self.parse_tuple_field_access_expr_float(lo, base, symbol, suffix))
+ Ok(self.parse_expr_tuple_field_access_float(lo, base, symbol, suffix))
}
_ => {
self.error_unexpected_after_dot();
@@ -1030,7 +1031,7 @@ impl<'a> Parser<'a> {
fn error_unexpected_after_dot(&self) {
// FIXME Could factor this out into non_fatal_unexpected or something.
let actual = pprust::token_to_string(&self.token);
- self.struct_span_err(self.token.span, &format!("unexpected token: `{actual}`")).emit();
+ self.sess.emit_err(errors::UnexpectedTokenAfterDot { span: self.token.span, actual });
}
// We need an identifier or integer, but the next token is a float.
@@ -1040,7 +1041,7 @@ impl<'a> Parser<'a> {
// support pushing "future tokens" (would be also helpful to `break_and_eat`), or
// we should break everything including floats into more basic proc-macro style
// tokens in the lexer (probably preferable).
- fn parse_tuple_field_access_expr_float(
+ fn parse_expr_tuple_field_access_float(
&mut self,
lo: Span,
base: P<Expr>,
@@ -1083,7 +1084,7 @@ impl<'a> Parser<'a> {
match &*components {
// 1e2
[IdentLike(i)] => {
- self.parse_tuple_field_access_expr(lo, base, Symbol::intern(&i), suffix, None)
+ self.parse_expr_tuple_field_access(lo, base, Symbol::intern(&i), suffix, None)
}
// 1.
[IdentLike(i), Punct('.')] => {
@@ -1099,7 +1100,7 @@ impl<'a> Parser<'a> {
let symbol = Symbol::intern(&i);
self.token = Token::new(token::Ident(symbol, false), ident_span);
let next_token = (Token::new(token::Dot, dot_span), self.token_spacing);
- self.parse_tuple_field_access_expr(lo, base, symbol, None, Some(next_token))
+ self.parse_expr_tuple_field_access(lo, base, symbol, None, Some(next_token))
}
// 1.2 | 1.2e3
[IdentLike(i1), Punct('.'), IdentLike(i2)] => {
@@ -1120,11 +1121,11 @@ impl<'a> Parser<'a> {
// See issue #76399 and PR #76285 for more details
let next_token1 = (Token::new(token::Dot, dot_span), Spacing::Alone);
let base1 =
- self.parse_tuple_field_access_expr(lo, base, symbol1, None, Some(next_token1));
+ self.parse_expr_tuple_field_access(lo, base, symbol1, None, Some(next_token1));
let symbol2 = Symbol::intern(&i2);
let next_token2 = Token::new(token::Ident(symbol2, false), ident2_span);
self.bump_with((next_token2, self.token_spacing)); // `.`
- self.parse_tuple_field_access_expr(lo, base1, symbol2, suffix, None)
+ self.parse_expr_tuple_field_access(lo, base1, symbol2, suffix, None)
}
// 1e+ | 1e- (recovered)
[IdentLike(_), Punct('+' | '-')] |
@@ -1142,7 +1143,7 @@ impl<'a> Parser<'a> {
}
}
- fn parse_tuple_field_access_expr(
+ fn parse_expr_tuple_field_access(
&mut self,
lo: Span,
base: P<Expr>,
@@ -1163,7 +1164,7 @@ impl<'a> Parser<'a> {
}
/// Parse a function call expression, `expr(...)`.
- fn parse_fn_call_expr(&mut self, lo: Span, fun: P<Expr>) -> P<Expr> {
+ fn parse_expr_fn_call(&mut self, lo: Span, fun: P<Expr>) -> P<Expr> {
let snapshot = if self.token.kind == token::OpenDelim(Delimiter::Parenthesis)
&& self.look_ahead_type_ascription_as_field()
{
@@ -1174,7 +1175,7 @@ impl<'a> Parser<'a> {
let open_paren = self.token.span;
let mut seq = self
- .parse_paren_expr_seq()
+ .parse_expr_paren_seq()
.map(|args| self.mk_expr(lo.to(self.prev_token.span), self.mk_call(fun, args)));
if let Some(expr) =
self.maybe_recover_struct_lit_bad_delims(lo, open_paren, &mut seq, snapshot)
@@ -1209,16 +1210,21 @@ impl<'a> Parser<'a> {
// `Enum::Foo { a: 3, b: 4 }` or `Enum::Foo(3, 4)`.
self.restore_snapshot(snapshot);
let close_paren = self.prev_token.span;
- let span = lo.to(self.prev_token.span);
- if !fields.is_empty() {
- let mut replacement_err = ParenthesesWithStructFields {
+ let span = lo.to(close_paren);
+ if !fields.is_empty() &&
+ // `token.kind` should not be compared here.
+ // This is because the `snapshot.token.kind` is treated as the same as
+ // that of the open delim in `TokenTreesReader::parse_token_tree`, even if they are different.
+ self.span_to_snippet(close_paren).map_or(false, |snippet| snippet == ")")
+ {
+ let mut replacement_err = errors::ParenthesesWithStructFields {
span,
r#type: path,
- braces_for_struct: BracesForStructLiteral {
+ braces_for_struct: errors::BracesForStructLiteral {
first: open_paren,
second: close_paren,
},
- no_fields_for_fn: NoFieldsForFnCall {
+ no_fields_for_fn: errors::NoFieldsForFnCall {
fields: fields
.into_iter()
.map(|field| field.span.until(field.expr.span))
@@ -1247,7 +1253,7 @@ impl<'a> Parser<'a> {
}
/// Parse an indexing expression `expr[...]`.
- fn parse_index_expr(&mut self, lo: Span, base: P<Expr>) -> PResult<'a, P<Expr>> {
+ fn parse_expr_index(&mut self, lo: Span, base: P<Expr>) -> PResult<'a, P<Expr>> {
let prev_span = self.prev_token.span;
let open_delim_span = self.token.span;
self.bump(); // `[`
@@ -1270,7 +1276,7 @@ impl<'a> Parser<'a> {
if self.check(&token::OpenDelim(Delimiter::Parenthesis)) {
// Method call `expr.f()`
- let args = self.parse_paren_expr_seq()?;
+ let args = self.parse_expr_paren_seq()?;
let fn_span = fn_span_lo.to(self.prev_token.span);
let span = lo.to(self.prev_token.span);
Ok(self.mk_expr(
@@ -1285,7 +1291,7 @@ impl<'a> Parser<'a> {
} else {
// Field access `expr.f`
if let Some(args) = seg.args {
- self.sess.emit_err(FieldExpressionWithGeneric(args.span()));
+ self.sess.emit_err(errors::FieldExpressionWithGeneric(args.span()));
}
let span = lo.to(self.prev_token.span);
@@ -1298,7 +1304,7 @@ impl<'a> Parser<'a> {
///
/// N.B., this does not parse outer attributes, and is private because it only works
/// correctly if called from `parse_dot_or_call_expr()`.
- fn parse_bottom_expr(&mut self) -> PResult<'a, P<Expr>> {
+ fn parse_expr_bottom(&mut self) -> PResult<'a, P<Expr>> {
maybe_recover_from_interpolated_ty_qpath!(self, true);
maybe_whole_expr!(self);
@@ -1311,13 +1317,13 @@ impl<'a> Parser<'a> {
// This match arm is a special-case of the `_` match arm below and
// could be removed without changing functionality, but it's faster
// to have it here, especially for programs with large constants.
- self.parse_lit_expr()
+ self.parse_expr_lit()
} else if self.check(&token::OpenDelim(Delimiter::Parenthesis)) {
- self.parse_tuple_parens_expr()
+ self.parse_expr_tuple_parens()
} else if self.check(&token::OpenDelim(Delimiter::Brace)) {
- self.parse_block_expr(None, lo, BlockCheckMode::Default)
+ self.parse_expr_block(None, lo, BlockCheckMode::Default)
} else if self.check(&token::BinOp(token::Or)) || self.check(&token::OrOr) {
- self.parse_closure_expr().map_err(|mut err| {
+ self.parse_expr_closure().map_err(|mut err| {
// If the input is something like `if a { 1 } else { 2 } | if a { 3 } else { 4 }`
// then suggest parens around the lhs.
if let Some(sp) = self.sess.ambiguous_block_expr_parse.borrow().get(&lo) {
@@ -1326,42 +1332,42 @@ impl<'a> Parser<'a> {
err
})
} else if self.check(&token::OpenDelim(Delimiter::Bracket)) {
- self.parse_array_or_repeat_expr(Delimiter::Bracket)
+ self.parse_expr_array_or_repeat(Delimiter::Bracket)
} else if self.check_path() {
- self.parse_path_start_expr()
+ self.parse_expr_path_start()
} else if self.check_keyword(kw::Move)
|| self.check_keyword(kw::Static)
|| self.check_const_closure()
{
- self.parse_closure_expr()
+ self.parse_expr_closure()
} else if self.eat_keyword(kw::If) {
- self.parse_if_expr()
+ self.parse_expr_if()
} else if self.check_keyword(kw::For) {
if self.choose_generics_over_qpath(1) {
- self.parse_closure_expr()
+ self.parse_expr_closure()
} else {
assert!(self.eat_keyword(kw::For));
- self.parse_for_expr(None, self.prev_token.span)
+ self.parse_expr_for(None, self.prev_token.span)
}
} else if self.eat_keyword(kw::While) {
- self.parse_while_expr(None, self.prev_token.span)
+ self.parse_expr_while(None, self.prev_token.span)
} else if let Some(label) = self.eat_label() {
- self.parse_labeled_expr(label, true)
+ self.parse_expr_labeled(label, true)
} else if self.eat_keyword(kw::Loop) {
let sp = self.prev_token.span;
- self.parse_loop_expr(None, self.prev_token.span).map_err(|mut err| {
+ self.parse_expr_loop(None, self.prev_token.span).map_err(|mut err| {
err.span_label(sp, "while parsing this `loop` expression");
err
})
} else if self.eat_keyword(kw::Match) {
let match_sp = self.prev_token.span;
- self.parse_match_expr().map_err(|mut err| {
+ self.parse_expr_match().map_err(|mut err| {
err.span_label(match_sp, "while parsing this `match` expression");
err
})
} else if self.eat_keyword(kw::Unsafe) {
let sp = self.prev_token.span;
- self.parse_block_expr(None, lo, BlockCheckMode::Unsafe(ast::UserProvided)).map_err(
+ self.parse_expr_block(None, lo, BlockCheckMode::Unsafe(ast::UserProvided)).map_err(
|mut err| {
err.span_label(sp, "while parsing this `unsafe` expression");
err
@@ -1375,17 +1381,17 @@ impl<'a> Parser<'a> {
self.expect_keyword(kw::Try)?;
self.parse_try_block(lo)
} else if self.eat_keyword(kw::Return) {
- self.parse_return_expr()
+ self.parse_expr_return()
} else if self.eat_keyword(kw::Continue) {
- self.parse_continue_expr(lo)
+ self.parse_expr_continue(lo)
} else if self.eat_keyword(kw::Break) {
- self.parse_break_expr()
+ self.parse_expr_break()
} else if self.eat_keyword(kw::Yield) {
- self.parse_yield_expr()
+ self.parse_expr_yield()
} else if self.is_do_yeet() {
- self.parse_yeet_expr()
+ self.parse_expr_yeet()
} else if self.check_keyword(kw::Let) {
- self.parse_let_expr()
+ self.parse_expr_let()
} else if self.eat_keyword(kw::Underscore) {
Ok(self.mk_expr(self.prev_token.span, ExprKind::Underscore))
} else if !self.unclosed_delims.is_empty() && self.check(&token::Semi) {
@@ -1408,19 +1414,19 @@ impl<'a> Parser<'a> {
// Check for `async {` and `async move {`.
self.parse_async_block()
} else {
- self.parse_closure_expr()
+ self.parse_expr_closure()
}
} else if self.eat_keyword(kw::Await) {
self.recover_incorrect_await_syntax(lo, self.prev_token.span)
} else {
- self.parse_lit_expr()
+ self.parse_expr_lit()
}
} else {
- self.parse_lit_expr()
+ self.parse_expr_lit()
}
}
- fn parse_lit_expr(&mut self) -> PResult<'a, P<Expr>> {
+ fn parse_expr_lit(&mut self) -> PResult<'a, P<Expr>> {
let lo = self.token.span;
match self.parse_opt_token_lit() {
Some((token_lit, _)) => {
@@ -1431,7 +1437,7 @@ impl<'a> Parser<'a> {
}
}
- fn parse_tuple_parens_expr(&mut self) -> PResult<'a, P<Expr>> {
+ fn parse_expr_tuple_parens(&mut self) -> PResult<'a, P<Expr>> {
let lo = self.token.span;
self.expect(&token::OpenDelim(Delimiter::Parenthesis))?;
let (es, trailing_comma) = match self.parse_seq_to_end(
@@ -1455,20 +1461,20 @@ impl<'a> Parser<'a> {
self.maybe_recover_from_bad_qpath(expr)
}
- fn parse_array_or_repeat_expr(&mut self, close_delim: Delimiter) -> PResult<'a, P<Expr>> {
+ fn parse_expr_array_or_repeat(&mut self, close_delim: Delimiter) -> PResult<'a, P<Expr>> {
let lo = self.token.span;
self.bump(); // `[` or other open delim
let close = &token::CloseDelim(close_delim);
let kind = if self.eat(close) {
// Empty vector
- ExprKind::Array(Vec::new())
+ ExprKind::Array(ThinVec::new())
} else {
// Non-empty vector
let first_expr = self.parse_expr()?;
if self.eat(&token::Semi) {
// Repeating array syntax: `[ 0; 512 ]`
- let count = self.parse_anon_const_expr()?;
+ let count = self.parse_expr_anon_const()?;
self.expect(close)?;
ExprKind::Repeat(first_expr, count)
} else if self.eat(&token::Comma) {
@@ -1480,14 +1486,14 @@ impl<'a> Parser<'a> {
} else {
// Vector with one element
self.expect(close)?;
- ExprKind::Array(vec![first_expr])
+ ExprKind::Array(thin_vec![first_expr])
}
};
let expr = self.mk_expr(lo.to(self.prev_token.span), kind);
self.maybe_recover_from_bad_qpath(expr)
}
- fn parse_path_start_expr(&mut self) -> PResult<'a, P<Expr>> {
+ fn parse_expr_path_start(&mut self) -> PResult<'a, P<Expr>> {
let (qself, path) = if self.eat_lt() {
let (qself, path) = self.parse_qpath(PathStyle::Expr)?;
(Some(qself), path)
@@ -1499,7 +1505,7 @@ impl<'a> Parser<'a> {
let (span, kind) = if self.eat(&token::Not) {
// MACRO INVOCATION expression
if qself.is_some() {
- self.sess.emit_err(MacroInvocationWithQualifiedPath(path.span));
+ self.sess.emit_err(errors::MacroInvocationWithQualifiedPath(path.span));
}
let lo = path.span;
let mac = P(MacCall {
@@ -1524,7 +1530,7 @@ impl<'a> Parser<'a> {
}
/// Parse `'label: $expr`. The label is already parsed.
- fn parse_labeled_expr(
+ fn parse_expr_labeled(
&mut self,
label_: Label,
mut consume_colon: bool,
@@ -1533,15 +1539,15 @@ impl<'a> Parser<'a> {
let label = Some(label_);
let ate_colon = self.eat(&token::Colon);
let expr = if self.eat_keyword(kw::While) {
- self.parse_while_expr(label, lo)
+ self.parse_expr_while(label, lo)
} else if self.eat_keyword(kw::For) {
- self.parse_for_expr(label, lo)
+ self.parse_expr_for(label, lo)
} else if self.eat_keyword(kw::Loop) {
- self.parse_loop_expr(label, lo)
+ self.parse_expr_loop(label, lo)
} else if self.check_noexpect(&token::OpenDelim(Delimiter::Brace))
|| self.token.is_whole_block()
{
- self.parse_block_expr(label, lo, BlockCheckMode::Default)
+ self.parse_expr_block(label, lo, BlockCheckMode::Default)
} else if !ate_colon
&& self.may_recover()
&& (matches!(self.token.kind, token::CloseDelim(_) | token::Comma)
@@ -1549,7 +1555,7 @@ impl<'a> Parser<'a> {
{
let (lit, _) =
self.recover_unclosed_char(label_.ident, Parser::mk_token_lit_char, |self_| {
- self_.sess.create_err(UnexpectedTokenAfterLabel {
+ self_.sess.create_err(errors::UnexpectedTokenAfterLabel {
span: self_.token.span,
remove_label: None,
enclose_in_block: None,
@@ -1561,7 +1567,7 @@ impl<'a> Parser<'a> {
&& (self.check_noexpect(&TokenKind::Comma) || self.check_noexpect(&TokenKind::Gt))
{
// We're probably inside of a `Path<'a>` that needs a turbofish
- self.sess.emit_err(UnexpectedTokenAfterLabel {
+ self.sess.emit_err(errors::UnexpectedTokenAfterLabel {
span: self.token.span,
remove_label: None,
enclose_in_block: None,
@@ -1569,7 +1575,7 @@ impl<'a> Parser<'a> {
consume_colon = false;
Ok(self.mk_expr_err(lo))
} else {
- let mut err = UnexpectedTokenAfterLabel {
+ let mut err = errors::UnexpectedTokenAfterLabel {
span: self.token.span,
remove_label: None,
enclose_in_block: None,
@@ -1605,14 +1611,14 @@ impl<'a> Parser<'a> {
return expr;
}
- err.enclose_in_block = Some(UnexpectedTokenAfterLabelSugg {
+ err.enclose_in_block = Some(errors::UnexpectedTokenAfterLabelSugg {
left: span.shrink_to_lo(),
right: span.shrink_to_hi(),
});
// Replace `'label: non_block_expr` with `'label: {non_block_expr}` in order to suppress future errors about `break 'label`.
let stmt = self.mk_stmt(span, StmtKind::Expr(expr));
- let blk = self.mk_block(vec![stmt], BlockCheckMode::Default, span);
+ let blk = self.mk_block(thin_vec![stmt], BlockCheckMode::Default, span);
self.mk_expr(span, ExprKind::Block(blk, label))
});
@@ -1621,7 +1627,7 @@ impl<'a> Parser<'a> {
}?;
if !ate_colon && consume_colon {
- self.sess.emit_err(RequireColonAfterLabeledExpression {
+ self.sess.emit_err(errors::RequireColonAfterLabeledExpression {
span: expr.span,
label: lo,
label_end: lo.shrink_to_hi(),
@@ -1670,7 +1676,7 @@ impl<'a> Parser<'a> {
self.bump(); // `catch`
let span = lo.to(self.prev_token.span);
- self.sess.emit_err(DoCatchSyntaxRemoved { span });
+ self.sess.emit_err(errors::DoCatchSyntaxRemoved { span });
self.parse_try_block(lo)
}
@@ -1681,7 +1687,7 @@ impl<'a> Parser<'a> {
}
/// Parse `"return" expr?`.
- fn parse_return_expr(&mut self) -> PResult<'a, P<Expr>> {
+ fn parse_expr_return(&mut self) -> PResult<'a, P<Expr>> {
let lo = self.prev_token.span;
let kind = ExprKind::Ret(self.parse_expr_opt()?);
let expr = self.mk_expr(lo.to(self.prev_token.span), kind);
@@ -1689,7 +1695,7 @@ impl<'a> Parser<'a> {
}
/// Parse `"do" "yeet" expr?`.
- fn parse_yeet_expr(&mut self) -> PResult<'a, P<Expr>> {
+ fn parse_expr_yeet(&mut self) -> PResult<'a, P<Expr>> {
let lo = self.token.span;
self.bump(); // `do`
@@ -1711,16 +1717,16 @@ impl<'a> Parser<'a> {
/// `break 'lbl: loop {}`); a labeled break with an unlabeled loop as its value
/// expression only gets a warning for compatibility reasons; and a labeled break
/// with a labeled loop does not even get a warning because there is no ambiguity.
- fn parse_break_expr(&mut self) -> PResult<'a, P<Expr>> {
+ fn parse_expr_break(&mut self) -> PResult<'a, P<Expr>> {
let lo = self.prev_token.span;
let mut label = self.eat_label();
let kind = if self.token == token::Colon && let Some(label) = label.take() {
// The value expression can be a labeled loop, see issue #86948, e.g.:
// `loop { break 'label: loop { break 'label 42; }; }`
- let lexpr = self.parse_labeled_expr(label, true)?;
- self.sess.emit_err(LabeledLoopInBreak {
+ let lexpr = self.parse_expr_labeled(label, true)?;
+ self.sess.emit_err(errors::LabeledLoopInBreak {
span: lexpr.span,
- sub: WrapExpressionInParentheses {
+ sub: errors::WrapExpressionInParentheses {
left: lexpr.span.shrink_to_lo(),
right: lexpr.span.shrink_to_hi(),
},
@@ -1770,7 +1776,7 @@ impl<'a> Parser<'a> {
}
/// Parse `"continue" label?`.
- fn parse_continue_expr(&mut self, lo: Span) -> PResult<'a, P<Expr>> {
+ fn parse_expr_continue(&mut self, lo: Span) -> PResult<'a, P<Expr>> {
let mut label = self.eat_label();
// Recover `continue label` -> `continue 'label`
@@ -1787,7 +1793,7 @@ impl<'a> Parser<'a> {
}
/// Parse `"yield" expr?`.
- fn parse_yield_expr(&mut self) -> PResult<'a, P<Expr>> {
+ fn parse_expr_yield(&mut self) -> PResult<'a, P<Expr>> {
let lo = self.prev_token.span;
let kind = ExprKind::Yield(self.parse_expr_opt()?);
let span = lo.to(self.prev_token.span);
@@ -1840,7 +1846,7 @@ impl<'a> Parser<'a> {
};
if let Some(expr) = expr {
if matches!(expr.kind, ExprKind::Err) {
- let mut err = InvalidInterpolatedExpression { span: self.token.span }
+ let mut err = errors::InvalidInterpolatedExpression { span: self.token.span }
.into_diagnostic(&self.sess.span_diagnostic);
err.downgrade_to_delayed_bug();
return Err(err);
@@ -1882,7 +1888,16 @@ impl<'a> Parser<'a> {
if let token::Literal(token::Lit { kind: token::Integer, symbol, suffix }) =
next_token.kind
{
- if self.token.span.hi() == next_token.span.lo() {
+ // If this integer looks like a float, then recover as such.
+ //
+ // We will never encounter the exponent part of a floating
+ // point literal here, since there's no use of the exponent
+ // syntax that also constitutes a valid integer, so we need
+ // not check for that.
+ if suffix.map_or(true, |s| s == sym::f32 || s == sym::f64)
+ && symbol.as_str().chars().all(|c| c.is_numeric() || c == '_')
+ && self.token.span.hi() == next_token.span.lo()
+ {
let s = String::from("0.") + symbol.as_str();
let kind = TokenKind::lit(token::Float, Symbol::intern(&s), suffix);
return Some(Token::new(kind, self.token.span.to(next_token.span)));
@@ -1892,7 +1907,7 @@ impl<'a> Parser<'a> {
});
if let Some(token) = &recovered {
self.bump();
- self.sess.emit_err(FloatLiteralRequiresIntegerPart {
+ self.sess.emit_err(errors::FloatLiteralRequiresIntegerPart {
span: token.span,
correct: pprust::token_to_string(token).into_owned(),
});
@@ -1953,13 +1968,17 @@ impl<'a> Parser<'a> {
if [sym::i32, sym::u32, sym::isize, sym::usize].contains(&suffix) {
// #59553: warn instead of reject out of hand to allow the fix to percolate
// through the ecosystem when people fix their macros
- self.sess.emit_warning(InvalidLiteralSuffixOnTupleIndex {
+ self.sess.emit_warning(errors::InvalidLiteralSuffixOnTupleIndex {
span,
suffix,
exception: Some(()),
});
} else {
- self.sess.emit_err(InvalidLiteralSuffixOnTupleIndex { span, suffix, exception: None });
+ self.sess.emit_err(errors::InvalidLiteralSuffixOnTupleIndex {
+ span,
+ suffix,
+ exception: None,
+ });
}
}
@@ -1991,11 +2010,11 @@ impl<'a> Parser<'a> {
/// expression.
fn maybe_suggest_brackets_instead_of_braces(&mut self, lo: Span) -> Option<P<Expr>> {
let mut snapshot = self.create_snapshot_for_diagnostic();
- match snapshot.parse_array_or_repeat_expr(Delimiter::Brace) {
+ match snapshot.parse_expr_array_or_repeat(Delimiter::Brace) {
Ok(arr) => {
- self.sess.emit_err(ArrayBracketsInsteadOfSpaces {
+ self.sess.emit_err(errors::ArrayBracketsInsteadOfSpaces {
span: arr.span,
- sub: ArrayBracketsInsteadOfSpacesSugg {
+ sub: errors::ArrayBracketsInsteadOfSpacesSugg {
left: lo,
right: snapshot.prev_token.span,
},
@@ -2041,7 +2060,7 @@ impl<'a> Parser<'a> {
.span_to_snippet(snapshot.token.span)
.map_or(false, |snippet| snippet == "]") =>
{
- return Err(MissingSemicolonBeforeArray {
+ return Err(errors::MissingSemicolonBeforeArray {
open_delim: open_delim_span,
semicolon: prev_span.shrink_to_hi(),
}.into_diagnostic(&self.sess.span_diagnostic));
@@ -2054,7 +2073,7 @@ impl<'a> Parser<'a> {
}
/// Parses a block or unsafe block.
- pub(super) fn parse_block_expr(
+ pub(super) fn parse_expr_block(
&mut self,
opt_label: Option<Label>,
lo: Span,
@@ -2067,7 +2086,7 @@ impl<'a> Parser<'a> {
}
if self.token.is_whole_block() {
- self.sess.emit_err(InvalidBlockMacroSegment {
+ self.sess.emit_err(errors::InvalidBlockMacroSegment {
span: self.token.span,
context: lo.to(self.token.span),
});
@@ -2084,7 +2103,7 @@ impl<'a> Parser<'a> {
}
/// Parses a closure expression (e.g., `move |args| expr`).
- fn parse_closure_expr(&mut self) -> PResult<'a, P<Expr>> {
+ fn parse_expr_closure(&mut self) -> PResult<'a, P<Expr>> {
let lo = self.token.span;
let binder = if self.check_keyword(kw::For) {
@@ -2094,12 +2113,12 @@ impl<'a> Parser<'a> {
self.sess.gated_spans.gate(sym::closure_lifetime_binder, span);
- ClosureBinder::For { span, generic_params: P::from_vec(lifetime_defs) }
+ ClosureBinder::For { span, generic_params: lifetime_defs }
} else {
ClosureBinder::NotPresent
};
- let constness = self.parse_constness(Case::Sensitive);
+ let constness = self.parse_closure_constness(Case::Sensitive);
let movability =
if self.eat_keyword(kw::Static) { Movability::Static } else { Movability::Movable };
@@ -2121,7 +2140,7 @@ impl<'a> Parser<'a> {
_ => {
// If an explicit return type is given, require a block to appear (RFC 968).
let body_lo = self.token.span;
- self.parse_block_expr(None, body_lo, BlockCheckMode::Default)?
+ self.parse_expr_block(None, body_lo, BlockCheckMode::Default)?
}
};
@@ -2131,7 +2150,7 @@ impl<'a> Parser<'a> {
}
if self.token.kind == TokenKind::Semi
- && matches!(self.token_cursor.frame.delim_sp, Some((Delimiter::Parenthesis, _)))
+ && matches!(self.token_cursor.stack.last(), Some((_, Delimiter::Parenthesis, _)))
&& self.may_recover()
{
// It is likely that the closure body is a block but where the
@@ -2171,7 +2190,7 @@ impl<'a> Parser<'a> {
// Check for `move async` and recover
if self.check_keyword(kw::Async) {
let move_async_span = self.token.span.with_lo(self.prev_token.span.data().lo);
- Err(AsyncMoveOrderIncorrect { span: move_async_span }
+ Err(errors::AsyncMoveOrderIncorrect { span: move_async_span }
.into_diagnostic(&self.sess.span_diagnostic))
} else {
Ok(CaptureBy::Value)
@@ -2186,7 +2205,7 @@ impl<'a> Parser<'a> {
let arg_start = self.token.span.lo();
let inputs = if self.eat(&token::OrOr) {
- Vec::new()
+ ThinVec::new()
} else {
self.expect(&token::BinOp(token::Or))?;
let args = self
@@ -2212,7 +2231,7 @@ impl<'a> Parser<'a> {
let lo = self.token.span;
let attrs = self.parse_outer_attributes()?;
self.collect_tokens_trailing_token(attrs, ForceCollect::No, |this, attrs| {
- let pat = this.parse_pat_no_top_alt(PARAM_EXPECTED)?;
+ let pat = this.parse_pat_no_top_alt(Some(Expected::ParameterName))?;
let ty = if this.eat(&token::Colon) {
this.parse_ty()?
} else {
@@ -2234,9 +2253,9 @@ impl<'a> Parser<'a> {
}
/// Parses an `if` expression (`if` token already eaten).
- fn parse_if_expr(&mut self) -> PResult<'a, P<Expr>> {
+ fn parse_expr_if(&mut self) -> PResult<'a, P<Expr>> {
let lo = self.prev_token.span;
- let cond = self.parse_cond_expr()?;
+ let cond = self.parse_expr_cond()?;
self.parse_if_after_cond(lo, cond)
}
@@ -2249,16 +2268,17 @@ impl<'a> Parser<'a> {
let block = match &mut cond.kind {
ExprKind::Binary(Spanned { span: binop_span, .. }, _, right)
if let ExprKind::Block(_, None) = right.kind => {
- self.sess.emit_err(IfExpressionMissingThenBlock {
+ self.sess.emit_err(errors::IfExpressionMissingThenBlock {
if_span: lo,
- sub: IfExpressionMissingThenBlockSub::UnfinishedCondition(
- cond_span.shrink_to_lo().to(*binop_span)
- ),
+ missing_then_block_sub:
+ errors::IfExpressionMissingThenBlockSub::UnfinishedCondition(cond_span.shrink_to_lo().to(*binop_span)),
+ let_else_sub: None,
+
});
std::mem::replace(right, this.mk_expr_err(binop_span.shrink_to_hi()))
},
ExprKind::Block(_, None) => {
- self.sess.emit_err(IfExpressionMissingCondition {
+ self.sess.emit_err(errors::IfExpressionMissingCondition {
if_span: lo.shrink_to_hi(),
block_span: self.sess.source_map().start_point(cond_span),
});
@@ -2279,9 +2299,15 @@ impl<'a> Parser<'a> {
if let Some(block) = recover_block_from_condition(self) {
block
} else {
- self.sess.emit_err(IfExpressionMissingThenBlock {
+ let let_else_sub = matches!(cond.kind, ExprKind::Let(..))
+ .then(|| errors::IfExpressionLetSomeSub { if_span: lo.until(cond_span) });
+
+ self.sess.emit_err(errors::IfExpressionMissingThenBlock {
if_span: lo,
- sub: IfExpressionMissingThenBlockSub::AddThenBlock(cond_span.shrink_to_hi()),
+ missing_then_block_sub: errors::IfExpressionMissingThenBlockSub::AddThenBlock(
+ cond_span.shrink_to_hi(),
+ ),
+ let_else_sub,
});
self.mk_block_err(cond_span.shrink_to_hi())
}
@@ -2307,12 +2333,12 @@ impl<'a> Parser<'a> {
self.error_on_if_block_attrs(lo, false, block.span, attrs);
block
};
- let els = if self.eat_keyword(kw::Else) { Some(self.parse_else_expr()?) } else { None };
+ let els = if self.eat_keyword(kw::Else) { Some(self.parse_expr_else()?) } else { None };
Ok(self.mk_expr(lo.to(self.prev_token.span), ExprKind::If(cond, thn, els)))
}
/// Parses the condition of a `if` or `while` expression.
- fn parse_cond_expr(&mut self) -> PResult<'a, P<Expr>> {
+ fn parse_expr_cond(&mut self) -> PResult<'a, P<Expr>> {
let cond =
self.parse_expr_res(Restrictions::NO_STRUCT_LITERAL | Restrictions::ALLOW_LET, None)?;
@@ -2325,7 +2351,7 @@ impl<'a> Parser<'a> {
}
/// Parses a `let $pat = $expr` pseudo-expression.
- fn parse_let_expr(&mut self) -> PResult<'a, P<Expr>> {
+ fn parse_expr_let(&mut self) -> PResult<'a, P<Expr>> {
// This is a *approximate* heuristic that detects if `let` chains are
// being parsed in the right position. It's approximate because it
// doesn't deny all invalid `let` expressions, just completely wrong usages.
@@ -2334,7 +2360,7 @@ impl<'a> Parser<'a> {
TokenKind::AndAnd | TokenKind::Ident(kw::If, _) | TokenKind::Ident(kw::While, _)
);
if !self.restrictions.contains(Restrictions::ALLOW_LET) || not_in_chain {
- self.sess.emit_err(ExpectedExpressionFoundLet { span: self.token.span });
+ self.sess.emit_err(errors::ExpectedExpressionFoundLet { span: self.token.span });
}
self.bump(); // Eat `let` token
@@ -2346,7 +2372,7 @@ impl<'a> Parser<'a> {
CommaRecoveryMode::LikelyTuple,
)?;
if self.token == token::EqEq {
- self.sess.emit_err(ExpectedEqForLetExpr {
+ self.sess.emit_err(errors::ExpectedEqForLetExpr {
span: self.token.span,
sugg_span: self.token.span,
});
@@ -2355,7 +2381,7 @@ impl<'a> Parser<'a> {
self.expect(&token::Eq)?;
}
let expr = self.with_res(self.restrictions | Restrictions::NO_STRUCT_LITERAL, |this| {
- this.parse_assoc_expr_with(1 + prec_let_scrutinee_needs_par(), None.into())
+ this.parse_expr_assoc_with(1 + prec_let_scrutinee_needs_par(), None.into())
})?;
let span = lo.to(expr.span);
self.sess.gated_spans.gate(sym::let_chains, span);
@@ -2363,11 +2389,11 @@ impl<'a> Parser<'a> {
}
/// Parses an `else { ... }` expression (`else` token already eaten).
- fn parse_else_expr(&mut self) -> PResult<'a, P<Expr>> {
+ fn parse_expr_else(&mut self) -> PResult<'a, P<Expr>> {
let else_span = self.prev_token.span; // `else`
let attrs = self.parse_outer_attributes()?; // For recovery.
let expr = if self.eat_keyword(kw::If) {
- self.parse_if_expr()?
+ self.parse_expr_if()?
} else if self.check(&TokenKind::OpenDelim(Delimiter::Brace)) {
self.parse_simple_block()?
} else {
@@ -2381,7 +2407,7 @@ impl<'a> Parser<'a> {
if self.check(&TokenKind::OpenDelim(Delimiter::Brace))
&& classify::expr_requires_semi_to_be_stmt(&cond) =>
{
- self.sess.emit_err(ExpectedElseBlock {
+ self.sess.emit_err(errors::ExpectedElseBlock {
first_tok_span,
first_tok,
else_span,
@@ -2421,7 +2447,7 @@ impl<'a> Parser<'a> {
[x0 @ xn] | [x0, .., xn] => (x0.span.to(xn.span), xn.span),
};
let ctx = if is_ctx_else { "else" } else { "if" };
- self.sess.emit_err(OuterAttributeNotAllowedOnIfElse {
+ self.sess.emit_err(errors::OuterAttributeNotAllowedOnIfElse {
last,
branch_span,
ctx_span,
@@ -2434,14 +2460,14 @@ impl<'a> Parser<'a> {
if let ExprKind::Binary(Spanned { span: binop_span, node: binop}, _, right) = &cond.kind &&
let BinOpKind::And = binop &&
let ExprKind::If(cond, ..) = &right.kind {
- Err(self.sess.create_err(UnexpectedIfWithIf(binop_span.shrink_to_hi().to(cond.span.shrink_to_lo()))))
+ Err(self.sess.create_err(errors::UnexpectedIfWithIf(binop_span.shrink_to_hi().to(cond.span.shrink_to_lo()))))
} else {
Ok(())
}
}
/// Parses `for <src_pat> in <src_expr> <src_loop_block>` (`for` token already eaten).
- fn parse_for_expr(&mut self, opt_label: Option<Label>, lo: Span) -> PResult<'a, P<Expr>> {
+ fn parse_expr_for(&mut self, opt_label: Option<Label>, lo: Span) -> PResult<'a, P<Expr>> {
// Record whether we are about to parse `for (`.
// This is used below for recovery in case of `for ( $stuff ) $block`
// in which case we will suggest `for $stuff $block`.
@@ -2464,28 +2490,61 @@ impl<'a> Parser<'a> {
let pat = self.recover_parens_around_for_head(pat, begin_paren);
+ // Recover from missing expression in `for` loop
+ if matches!(expr.kind, ExprKind::Block(..))
+ && !matches!(self.token.kind, token::OpenDelim(token::Delimiter::Brace))
+ && self.may_recover()
+ {
+ self.sess
+ .emit_err(errors::MissingExpressionInForLoop { span: expr.span.shrink_to_lo() });
+ let err_expr = self.mk_expr(expr.span, ExprKind::Err);
+ let block = self.mk_block(thin_vec![], BlockCheckMode::Default, self.prev_token.span);
+ return Ok(self.mk_expr(
+ lo.to(self.prev_token.span),
+ ExprKind::ForLoop(pat, err_expr, block, opt_label),
+ ));
+ }
+
let (attrs, loop_block) = self.parse_inner_attrs_and_block()?;
let kind = ExprKind::ForLoop(pat, expr, loop_block, opt_label);
+
+ self.recover_loop_else("for", lo)?;
+
Ok(self.mk_expr_with_attrs(lo.to(self.prev_token.span), kind, attrs))
}
+ /// Recovers from an `else` clause after a loop (`for...else`, `while...else`)
+ fn recover_loop_else(&mut self, loop_kind: &'static str, loop_kw: Span) -> PResult<'a, ()> {
+ if self.token.is_keyword(kw::Else) && self.may_recover() {
+ let else_span = self.token.span;
+ self.bump();
+ let else_clause = self.parse_expr_else()?;
+ self.sess.emit_err(errors::LoopElseNotSupported {
+ span: else_span.to(else_clause.span),
+ loop_kind,
+ loop_kw,
+ });
+ }
+ Ok(())
+ }
+
fn error_missing_in_for_loop(&mut self) {
let (span, sub): (_, fn(_) -> _) = if self.token.is_ident_named(sym::of) {
// Possibly using JS syntax (#75311).
let span = self.token.span;
self.bump();
- (span, MissingInInForLoopSub::InNotOf)
+ (span, errors::MissingInInForLoopSub::InNotOf)
} else {
- (self.prev_token.span.between(self.token.span), MissingInInForLoopSub::AddIn)
+ (self.prev_token.span.between(self.token.span), errors::MissingInInForLoopSub::AddIn)
};
- self.sess.emit_err(MissingInInForLoop { span, sub: sub(span) });
+ self.sess.emit_err(errors::MissingInInForLoop { span, sub: sub(span) });
}
/// Parses a `while` or `while let` expression (`while` token already eaten).
- fn parse_while_expr(&mut self, opt_label: Option<Label>, lo: Span) -> PResult<'a, P<Expr>> {
- let cond = self.parse_cond_expr().map_err(|mut err| {
+ fn parse_expr_while(&mut self, opt_label: Option<Label>, lo: Span) -> PResult<'a, P<Expr>> {
+ let cond = self.parse_expr_cond().map_err(|mut err| {
err.span_label(lo, "while parsing the condition of this `while` expression");
err
})?;
@@ -2494,6 +2553,9 @@ impl<'a> Parser<'a> {
err.span_label(cond.span, "this `while` condition successfully parsed");
err
})?;
+
+ self.recover_loop_else("while", lo)?;
+
Ok(self.mk_expr_with_attrs(
lo.to(self.prev_token.span),
ExprKind::While(cond, body, opt_label),
@@ -2502,9 +2564,10 @@ impl<'a> Parser<'a> {
}
/// Parses `loop { ... }` (`loop` token already eaten).
- fn parse_loop_expr(&mut self, opt_label: Option<Label>, lo: Span) -> PResult<'a, P<Expr>> {
+ fn parse_expr_loop(&mut self, opt_label: Option<Label>, lo: Span) -> PResult<'a, P<Expr>> {
let loop_span = self.prev_token.span;
let (attrs, body) = self.parse_inner_attrs_and_block()?;
+ self.recover_loop_else("loop", lo)?;
Ok(self.mk_expr_with_attrs(
lo.to(self.prev_token.span),
ExprKind::Loop(body, opt_label, loop_span),
@@ -2520,7 +2583,7 @@ impl<'a> Parser<'a> {
}
/// Parses a `match ... { ... }` expression (`match` token already eaten).
- fn parse_match_expr(&mut self) -> PResult<'a, P<Expr>> {
+ fn parse_expr_match(&mut self) -> PResult<'a, P<Expr>> {
let match_span = self.prev_token.span;
let lo = self.prev_token.span;
let scrutinee = self.parse_expr_res(Restrictions::NO_STRUCT_LITERAL, None)?;
@@ -2542,7 +2605,7 @@ impl<'a> Parser<'a> {
}
let attrs = self.parse_inner_attributes()?;
- let mut arms: Vec<Arm> = Vec::new();
+ let mut arms = ThinVec::new();
while self.token != token::CloseDelim(Delimiter::Brace) {
match self.parse_arm() {
Ok(arm) => arms.push(arm),
@@ -2584,17 +2647,17 @@ impl<'a> Parser<'a> {
let err = |this: &Parser<'_>, stmts: Vec<ast::Stmt>| {
let span = stmts[0].span.to(stmts[stmts.len() - 1].span);
- this.sess.emit_err(MatchArmBodyWithoutBraces {
+ this.sess.emit_err(errors::MatchArmBodyWithoutBraces {
statements: span,
arrow: arrow_span,
num_statements: stmts.len(),
sub: if stmts.len() > 1 {
- MatchArmBodyWithoutBracesSugg::AddBraces {
+ errors::MatchArmBodyWithoutBracesSugg::AddBraces {
left: span.shrink_to_lo(),
right: span.shrink_to_hi(),
}
} else {
- MatchArmBodyWithoutBracesSugg::UseComma { semicolon: semi_sp }
+ errors::MatchArmBodyWithoutBracesSugg::UseComma { semicolon: semi_sp }
},
});
this.mk_expr_err(span)
@@ -2700,6 +2763,14 @@ impl<'a> Parser<'a> {
);
err.emit();
this.bump();
+ } else if matches!(
+ (&this.prev_token.kind, &this.token.kind),
+ (token::DotDotEq, token::Gt)
+ ) {
+ // `error_inclusive_range_match_arrow` handles cases like `0..=> {}`,
+ // so we supress the error here
+ err.delay_as_bug();
+ this.bump();
} else {
return Err(err);
}
@@ -2777,7 +2848,7 @@ impl<'a> Parser<'a> {
.is_ok();
if pattern_follows && snapshot.check(&TokenKind::FatArrow) {
err.cancel();
- this.sess.emit_err(MissingCommaAfterMatchArm {
+ this.sess.emit_err(errors::MissingCommaAfterMatchArm {
span: hi.shrink_to_hi(),
});
return Ok(true);
@@ -2809,7 +2880,7 @@ impl<'a> Parser<'a> {
fn parse_try_block(&mut self, span_lo: Span) -> PResult<'a, P<Expr>> {
let (attrs, body) = self.parse_inner_attrs_and_block()?;
if self.eat_keyword(kw::Catch) {
- Err(CatchAfterTry { span: self.prev_token.span }
+ Err(errors::CatchAfterTry { span: self.prev_token.span }
.into_diagnostic(&self.sess.span_diagnostic))
} else {
let span = span_lo.to(body.span);
@@ -2882,12 +2953,12 @@ impl<'a> Parser<'a> {
if let Err(err) = self.expect(&token::OpenDelim(Delimiter::Brace)) {
return Some(Err(err));
}
- let expr = self.parse_struct_expr(qself.clone(), path.clone(), true);
+ let expr = self.parse_expr_struct(qself.clone(), path.clone(), true);
if let (Ok(expr), false) = (&expr, struct_allowed) {
// This is a struct literal, but we don't can't accept them here.
- self.sess.emit_err(StructLiteralNotAllowedHere {
+ self.sess.emit_err(errors::StructLiteralNotAllowedHere {
span: expr.span,
- sub: StructLiteralNotAllowedHereSugg {
+ sub: errors::StructLiteralNotAllowedHereSugg {
left: path.span.shrink_to_lo(),
right: expr.span.shrink_to_hi(),
},
@@ -2903,15 +2974,15 @@ impl<'a> Parser<'a> {
pth: ast::Path,
recover: bool,
close_delim: Delimiter,
- ) -> PResult<'a, (Vec<ExprField>, ast::StructRest, bool)> {
- let mut fields = Vec::new();
+ ) -> PResult<'a, (ThinVec<ExprField>, ast::StructRest, bool)> {
+ let mut fields = ThinVec::new();
let mut base = ast::StructRest::None;
let mut recover_async = false;
let mut async_block_err = |e: &mut Diagnostic, span: Span| {
recover_async = true;
- e.span_label(span, "`async` blocks are only allowed in Rust 2018 or later");
- e.help_use_latest_edition();
+ errors::AsyncBlockIn2015 { span }.add_to_diagnostic(e);
+ errors::HelpUseLatestEdition::new().add_to_diagnostic(e);
};
while self.token != token::CloseDelim(close_delim) {
@@ -3011,7 +3082,7 @@ impl<'a> Parser<'a> {
}
/// Precondition: already parsed the '{'.
- pub(super) fn parse_struct_expr(
+ pub(super) fn parse_expr_struct(
&mut self,
qself: Option<P<ast::QSelf>>,
pth: ast::Path,
@@ -3055,7 +3126,7 @@ impl<'a> Parser<'a> {
if self.token != token::Comma {
return;
}
- self.sess.emit_err(CommaAfterBaseStruct {
+ self.sess.emit_err(errors::CommaAfterBaseStruct {
span: span.to(self.prev_token.span),
comma: self.token.span,
});
@@ -3068,7 +3139,7 @@ impl<'a> Parser<'a> {
{
// recover from typo of `...`, suggest `..`
let span = self.prev_token.span;
- self.sess.emit_err(MissingDotDot { token_span: span, sugg_span: span });
+ self.sess.emit_err(errors::MissingDotDot { token_span: span, sugg_span: span });
return true;
}
false
@@ -3136,18 +3207,18 @@ impl<'a> Parser<'a> {
return;
}
- self.sess.emit_err(EqFieldInit {
+ self.sess.emit_err(errors::EqFieldInit {
span: self.token.span,
eq: field_name.span.shrink_to_hi().to(self.token.span),
});
}
fn err_dotdotdot_syntax(&self, span: Span) {
- self.sess.emit_err(DotDotDot { span });
+ self.sess.emit_err(errors::DotDotDot { span });
}
fn err_larrow_operator(&self, span: Span) {
- self.sess.emit_err(LeftArrowOperator { span });
+ self.sess.emit_err(errors::LeftArrowOperator { span });
}
fn mk_assign_op(&self, binop: BinOp, lhs: P<Expr>, rhs: P<Expr>) -> ExprKind {
@@ -3161,7 +3232,7 @@ impl<'a> Parser<'a> {
limits: RangeLimits,
) -> ExprKind {
if end.is_none() && limits == RangeLimits::Closed {
- self.inclusive_range_with_incorrect_end(self.prev_token.span);
+ self.inclusive_range_with_incorrect_end();
ExprKind::Err
} else {
ExprKind::Range(start, end, limits)
@@ -3180,7 +3251,7 @@ impl<'a> Parser<'a> {
ExprKind::Index(expr, idx)
}
- fn mk_call(&self, f: P<Expr>, args: Vec<P<Expr>>) -> ExprKind {
+ fn mk_call(&self, f: P<Expr>, args: ThinVec<P<Expr>>) -> ExprKind {
ExprKind::Call(f, args)
}
diff --git a/compiler/rustc_parse/src/parser/generics.rs b/compiler/rustc_parse/src/parser/generics.rs
index 8ba811715..8d0f168e0 100644
--- a/compiler/rustc_parse/src/parser/generics.rs
+++ b/compiler/rustc_parse/src/parser/generics.rs
@@ -1,4 +1,8 @@
-use crate::errors::{WhereClauseBeforeTupleStructBody, WhereClauseBeforeTupleStructBodySugg};
+use crate::errors::{
+ MultipleWhereClauses, UnexpectedDefaultValueForLifetimeInGenericParameters,
+ UnexpectedSelfInGenericParameters, WhereClauseBeforeTupleStructBody,
+ WhereClauseBeforeTupleStructBodySugg,
+};
use super::{ForceCollect, Parser, TrailingToken};
@@ -10,10 +14,11 @@ use rustc_ast::{
use rustc_errors::{Applicability, PResult};
use rustc_span::symbol::{kw, Ident};
use rustc_span::Span;
+use thin_vec::ThinVec;
enum PredicateOrStructBody {
Predicate(ast::WherePredicate),
- StructBody(Vec<ast::FieldDef>),
+ StructBody(ThinVec<ast::FieldDef>),
}
impl<'a> Parser<'a> {
@@ -117,8 +122,8 @@ impl<'a> Parser<'a> {
/// Parses a (possibly empty) list of lifetime and type parameters, possibly including
/// a trailing comma and erroneous trailing attributes.
- pub(super) fn parse_generic_params(&mut self) -> PResult<'a, Vec<ast::GenericParam>> {
- let mut params = Vec::new();
+ pub(super) fn parse_generic_params(&mut self) -> PResult<'a, ThinVec<ast::GenericParam>> {
+ let mut params = ThinVec::new();
let mut done = false;
while !done {
let attrs = self.parse_outer_attributes()?;
@@ -127,12 +132,9 @@ impl<'a> Parser<'a> {
if this.eat_keyword_noexpect(kw::SelfUpper) {
// `Self` as a generic param is invalid. Here we emit the diagnostic and continue parsing
// as if `Self` never existed.
- this.struct_span_err(
- this.prev_token.span,
- "unexpected keyword `Self` in generic parameters",
- )
- .note("you cannot use `Self` as a generic parameter because it is reserved for associated items")
- .emit();
+ this.sess.emit_err(UnexpectedSelfInGenericParameters {
+ span: this.prev_token.span,
+ });
this.eat(&token::Comma);
}
@@ -145,6 +147,20 @@ impl<'a> Parser<'a> {
} else {
(None, Vec::new())
};
+
+ if this.check_noexpect(&token::Eq)
+ && this.look_ahead(1, |t| t.is_lifetime())
+ {
+ let lo = this.token.span;
+ // Parse `= 'lifetime`.
+ this.bump(); // `=`
+ this.bump(); // `'lifetime`
+ let span = lo.to(this.prev_token.span);
+ this.sess.emit_err(
+ UnexpectedDefaultValueForLifetimeInGenericParameters { span },
+ );
+ }
+
Some(ast::GenericParam {
ident: lifetime.ident,
id: lifetime.id,
@@ -236,13 +252,13 @@ impl<'a> Parser<'a> {
self.expect_gt()?;
(params, span_lo.to(self.prev_token.span))
} else {
- (vec![], self.prev_token.span.shrink_to_hi())
+ (ThinVec::new(), self.prev_token.span.shrink_to_hi())
};
Ok(ast::Generics {
params,
where_clause: WhereClause {
has_where_token: false,
- predicates: Vec::new(),
+ predicates: ThinVec::new(),
span: self.prev_token.span.shrink_to_hi(),
},
span,
@@ -262,17 +278,17 @@ impl<'a> Parser<'a> {
&mut self,
struct_name: Ident,
body_insertion_point: Span,
- ) -> PResult<'a, (WhereClause, Option<Vec<ast::FieldDef>>)> {
+ ) -> PResult<'a, (WhereClause, Option<ThinVec<ast::FieldDef>>)> {
self.parse_where_clause_common(Some((struct_name, body_insertion_point)))
}
fn parse_where_clause_common(
&mut self,
struct_: Option<(Ident, Span)>,
- ) -> PResult<'a, (WhereClause, Option<Vec<ast::FieldDef>>)> {
+ ) -> PResult<'a, (WhereClause, Option<ThinVec<ast::FieldDef>>)> {
let mut where_clause = WhereClause {
has_where_token: false,
- predicates: Vec::new(),
+ predicates: ThinVec::new(),
span: self.prev_token.span.shrink_to_hi(),
};
let mut tuple_struct_body = None;
@@ -329,16 +345,11 @@ impl<'a> Parser<'a> {
let ate_comma = self.eat(&token::Comma);
if self.eat_keyword_noexpect(kw::Where) {
- let msg = "cannot define duplicate `where` clauses on an item";
- let mut err = self.struct_span_err(self.token.span, msg);
- err.span_label(pred_lo, "previous `where` clause starts here");
- err.span_suggestion_verbose(
- prev_token.shrink_to_hi().to(self.prev_token.span),
- "consider joining the two `where` clauses into one",
- ",",
- Applicability::MaybeIncorrect,
- );
- err.emit();
+ self.sess.emit_err(MultipleWhereClauses {
+ span: self.token.span,
+ previous: pred_lo,
+ between: prev_token.shrink_to_hi().to(self.prev_token.span),
+ });
} else if !ate_comma {
break;
}
diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs
index 53680a82b..9d9ae154a 100644
--- a/compiler/rustc_parse/src/parser/item.rs
+++ b/compiler/rustc_parse/src/parser/item.rs
@@ -1,9 +1,8 @@
-use crate::errors::{DocCommentDoesNotDocumentAnything, UseEmptyBlockNotSemi};
+use crate::errors;
use super::diagnostics::{dummy_arg, ConsumeClosingDelim};
use super::ty::{AllowPlus, RecoverQPath, RecoverReturnSign};
use super::{AttrWrapper, FollowedByType, ForceCollect, Parser, PathStyle, TrailingToken};
-use crate::errors::FnTypoWithImpl;
use rustc_ast::ast::*;
use rustc_ast::ptr::P;
use rustc_ast::token::{self, Delimiter, TokenKind};
@@ -16,14 +15,18 @@ use rustc_ast::{EnumDef, FieldDef, Generics, TraitRef, Ty, TyKind, Variant, Vari
use rustc_ast::{FnHeader, ForeignItem, Path, PathSegment, Visibility, VisibilityKind};
use rustc_ast::{MacCall, MacDelimiter};
use rustc_ast_pretty::pprust;
-use rustc_errors::{struct_span_err, Applicability, IntoDiagnostic, PResult, StashKey};
+use rustc_errors::{
+ struct_span_err, Applicability, DiagnosticBuilder, ErrorGuaranteed, IntoDiagnostic, PResult,
+ StashKey,
+};
+use rustc_span::edit_distance::edit_distance;
use rustc_span::edition::Edition;
-use rustc_span::lev_distance::lev_distance;
use rustc_span::source_map::{self, Span};
use rustc_span::symbol::{kw, sym, Ident, Symbol};
use rustc_span::DUMMY_SP;
+use std::fmt::Write;
use std::mem;
-use thin_vec::ThinVec;
+use thin_vec::{thin_vec, ThinVec};
impl<'a> Parser<'a> {
/// Parses a source module as a crate. This is the main entry point for the parser.
@@ -53,12 +56,12 @@ impl<'a> Parser<'a> {
pub fn parse_mod(
&mut self,
term: &TokenKind,
- ) -> PResult<'a, (AttrVec, Vec<P<Item>>, ModSpans)> {
+ ) -> PResult<'a, (AttrVec, ThinVec<P<Item>>, ModSpans)> {
let lo = self.token.span;
let attrs = self.parse_inner_attributes()?;
let post_attr_lo = self.token.span;
- let mut items = vec![];
+ let mut items = ThinVec::new();
while let Some(item) = self.parse_item(ForceCollect::No)? {
items.push(item);
self.maybe_consume_incorrect_semicolon(&items);
@@ -163,35 +166,18 @@ impl<'a> Parser<'a> {
}
// At this point, we have failed to parse an item.
- self.error_on_unmatched_vis(&vis);
- self.error_on_unmatched_defaultness(def);
- if !attrs_allowed {
- self.recover_attrs_no_item(&attrs)?;
+ if !matches!(vis.kind, VisibilityKind::Inherited) {
+ self.sess.emit_err(errors::VisibilityNotFollowedByItem { span: vis.span, vis });
}
- Ok(None)
- }
- /// Error in-case a non-inherited visibility was parsed but no item followed.
- fn error_on_unmatched_vis(&self, vis: &Visibility) {
- if let VisibilityKind::Inherited = vis.kind {
- return;
+ if let Defaultness::Default(span) = def {
+ self.sess.emit_err(errors::DefaultNotFollowedByItem { span });
}
- let vs = pprust::vis_to_string(&vis);
- let vs = vs.trim_end();
- self.struct_span_err(vis.span, &format!("visibility `{vs}` is not followed by an item"))
- .span_label(vis.span, "the visibility")
- .help(&format!("you likely meant to define an item, e.g., `{vs} fn foo() {{}}`"))
- .emit();
- }
- /// Error in-case a `default` was parsed but no item followed.
- fn error_on_unmatched_defaultness(&self, def: Defaultness) {
- if let Defaultness::Default(sp) = def {
- self.struct_span_err(sp, "`default` is not followed by an item")
- .span_label(sp, "the `default` qualifier")
- .note("only `fn`, `const`, `type`, or `impl` items may be prefixed by `default`")
- .emit();
+ if !attrs_allowed {
+ self.recover_attrs_no_item(&attrs)?;
}
+ Ok(None)
}
/// Error in-case `default` was parsed in an in-appropriate context.
@@ -384,86 +370,74 @@ impl<'a> Parser<'a> {
let sp = self.prev_token.span.between(self.token.span);
let full_sp = self.prev_token.span.to(self.token.span);
let ident_sp = self.token.span;
- if self.look_ahead(1, |t| *t == token::OpenDelim(Delimiter::Brace)) {
+
+ let ident = if self.look_ahead(1, |t| {
+ [
+ token::Lt,
+ token::OpenDelim(Delimiter::Brace),
+ token::OpenDelim(Delimiter::Parenthesis),
+ ]
+ .contains(&t.kind)
+ }) {
+ self.parse_ident().unwrap()
+ } else {
+ return Ok(());
+ };
+
+ let mut found_generics = false;
+ if self.check(&token::Lt) {
+ found_generics = true;
+ self.eat_to_tokens(&[&token::Gt]);
+ self.bump(); // `>`
+ }
+
+ let err = if self.check(&token::OpenDelim(Delimiter::Brace)) {
// possible public struct definition where `struct` was forgotten
- let ident = self.parse_ident().unwrap();
- let msg = format!("add `struct` here to parse `{ident}` as a public struct");
- let mut err = self.struct_span_err(sp, "missing `struct` for struct definition");
- err.span_suggestion_short(
- sp,
- &msg,
- " struct ",
- Applicability::MaybeIncorrect, // speculative
- );
- Err(err)
- } else if self.look_ahead(1, |t| *t == token::OpenDelim(Delimiter::Parenthesis)) {
- let ident = self.parse_ident().unwrap();
+ Some(errors::MissingKeywordForItemDefinition::Struct { span: sp, ident })
+ } else if self.check(&token::OpenDelim(Delimiter::Parenthesis)) {
+ // possible public function or tuple struct definition where `fn`/`struct` was
+ // forgotten
self.bump(); // `(`
- let kw_name = self.recover_first_param();
+ let is_method = self.recover_self_param();
+
self.consume_block(Delimiter::Parenthesis, ConsumeClosingDelim::Yes);
- let (kw, kw_name, ambiguous) = if self.check(&token::RArrow) {
- self.eat_to_tokens(&[&token::OpenDelim(Delimiter::Brace)]);
- self.bump(); // `{`
- ("fn", kw_name, false)
- } else if self.check(&token::OpenDelim(Delimiter::Brace)) {
- self.bump(); // `{`
- ("fn", kw_name, false)
- } else if self.check(&token::Colon) {
- let kw = "struct";
- (kw, kw, false)
- } else {
- ("fn` or `struct", "function or struct", true)
- };
- let msg = format!("missing `{kw}` for {kw_name} definition");
- let mut err = self.struct_span_err(sp, &msg);
- if !ambiguous {
- self.consume_block(Delimiter::Brace, ConsumeClosingDelim::Yes);
- let suggestion =
- format!("add `{kw}` here to parse `{ident}` as a public {kw_name}");
- err.span_suggestion_short(
- sp,
- &suggestion,
- format!(" {kw} "),
- Applicability::MachineApplicable,
- );
- } else if let Ok(snippet) = self.span_to_snippet(ident_sp) {
- err.span_suggestion(
- full_sp,
- "if you meant to call a macro, try",
- format!("{}!", snippet),
- // this is the `ambiguous` conditional branch
- Applicability::MaybeIncorrect,
- );
- } else {
- err.help(
- "if you meant to call a macro, remove the `pub` \
- and add a trailing `!` after the identifier",
- );
- }
- Err(err)
- } else if self.look_ahead(1, |t| *t == token::Lt) {
- let ident = self.parse_ident().unwrap();
- self.eat_to_tokens(&[&token::Gt]);
- self.bump(); // `>`
- let (kw, kw_name, ambiguous) = if self.eat(&token::OpenDelim(Delimiter::Parenthesis)) {
- ("fn", self.recover_first_param(), false)
- } else if self.check(&token::OpenDelim(Delimiter::Brace)) {
- ("struct", "struct", false)
- } else {
- ("fn` or `struct", "function or struct", true)
- };
- let msg = format!("missing `{kw}` for {kw_name} definition");
- let mut err = self.struct_span_err(sp, &msg);
- if !ambiguous {
- err.span_suggestion_short(
- sp,
- &format!("add `{kw}` here to parse `{ident}` as a public {kw_name}"),
- format!(" {} ", kw),
- Applicability::MachineApplicable,
- );
- }
- Err(err)
+ let err =
+ if self.check(&token::RArrow) || self.check(&token::OpenDelim(Delimiter::Brace)) {
+ self.eat_to_tokens(&[&token::OpenDelim(Delimiter::Brace)]);
+ self.bump(); // `{`
+ self.consume_block(Delimiter::Brace, ConsumeClosingDelim::Yes);
+ if is_method {
+ errors::MissingKeywordForItemDefinition::Method { span: sp, ident }
+ } else {
+ errors::MissingKeywordForItemDefinition::Function { span: sp, ident }
+ }
+ } else if self.check(&token::Semi) {
+ errors::MissingKeywordForItemDefinition::Struct { span: sp, ident }
+ } else {
+ errors::MissingKeywordForItemDefinition::Ambiguous {
+ span: sp,
+ subdiag: if found_generics {
+ None
+ } else if let Ok(snippet) = self.span_to_snippet(ident_sp) {
+ Some(errors::AmbiguousMissingKwForItemSub::SuggestMacro {
+ span: full_sp,
+ snippet,
+ })
+ } else {
+ Some(errors::AmbiguousMissingKwForItemSub::HelpMacro)
+ },
+ }
+ };
+ Some(err)
+ } else if found_generics {
+ Some(errors::MissingKeywordForItemDefinition::Ambiguous { span: sp, subdiag: None })
+ } else {
+ None
+ };
+
+ if let Some(err) = err {
+ Err(err.into_diagnostic(&self.sess.span_diagnostic))
} else {
Ok(())
}
@@ -485,7 +459,8 @@ impl<'a> Parser<'a> {
// Maybe the user misspelled `macro_rules` (issue #91227)
if self.token.is_ident()
&& path.segments.len() == 1
- && lev_distance("macro_rules", &path.segments[0].ident.to_string(), 3).is_some()
+ && edit_distance("macro_rules", &path.segments[0].ident.to_string(), 2)
+ .is_some()
{
err.span_suggestion(
path.span,
@@ -512,16 +487,13 @@ impl<'a> Parser<'a> {
let mut err = self.struct_span_err(end.span, msg);
if end.is_doc_comment() {
err.span_label(end.span, "this doc comment doesn't document anything");
- }
- if end.meta_kind().is_some() {
- if self.token.kind == TokenKind::Semi {
- err.span_suggestion_verbose(
- self.token.span,
- "consider removing this semicolon",
- "",
- Applicability::MaybeIncorrect,
- );
- }
+ } else if self.token.kind == TokenKind::Semi {
+ err.span_suggestion_verbose(
+ self.token.span,
+ "consider removing this semicolon",
+ "",
+ Applicability::MaybeIncorrect,
+ );
}
if let [.., penultimate, _] = attrs {
err.span_label(start.span.to(penultimate.span), "other attributes here");
@@ -588,20 +560,11 @@ 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")
- .span_suggestion(
- span,
- "add a trait here",
- " Trait ",
- Applicability::HasPlaceholders,
- )
- .span_suggestion(
- span.to(self.token.span),
- "for an inherent impl, drop this `for`",
- "",
- Applicability::MaybeIncorrect,
- )
- .emit();
+ self.sess.emit_err(errors::MissingTraitInTraitImpl {
+ span,
+ for_span: span.to(self.token.span),
+ });
+
P(Ty {
kind: TyKind::Path(None, err_path(span)),
span,
@@ -634,14 +597,7 @@ impl<'a> Parser<'a> {
Some(ty_second) => {
// impl Trait for Type
if !has_for {
- self.struct_span_err(missing_for_span, "missing `for` in a trait impl")
- .span_suggestion_short(
- missing_for_span,
- "add `for` here",
- " for ",
- Applicability::MachineApplicable,
- )
- .emit();
+ self.sess.emit_err(errors::MissingForInTraitImpl { span: missing_for_span });
}
let ty_first = ty_first.into_inner();
@@ -649,7 +605,9 @@ impl<'a> Parser<'a> {
// This notably includes paths passed through `ty` macro fragments (#46438).
TyKind::Path(None, path) => path,
_ => {
- self.struct_span_err(ty_first.span, "expected a trait, found type").emit();
+ self.sess.emit_err(errors::ExpectedTraitInTraitImplFoundType {
+ span: ty_first.span,
+ });
err_path(ty_first.span)
}
};
@@ -688,20 +646,20 @@ impl<'a> Parser<'a> {
&mut self,
attrs: &mut AttrVec,
mut parse_item: impl FnMut(&mut Parser<'a>) -> PResult<'a, Option<Option<T>>>,
- ) -> PResult<'a, Vec<T>> {
+ ) -> PResult<'a, ThinVec<T>> {
let open_brace_span = self.token.span;
// Recover `impl Ty;` instead of `impl Ty {}`
if self.token == TokenKind::Semi {
- self.sess.emit_err(UseEmptyBlockNotSemi { span: self.token.span });
+ self.sess.emit_err(errors::UseEmptyBlockNotSemi { span: self.token.span });
self.bump();
- return Ok(vec![]);
+ return Ok(ThinVec::new());
}
self.expect(&token::OpenDelim(Delimiter::Brace))?;
attrs.extend(self.parse_inner_attributes()?);
- let mut items = Vec::new();
+ let mut items = ThinVec::new();
while !self.eat(&token::CloseDelim(Delimiter::Brace)) {
if self.recover_doc_comment_before_brace() {
continue;
@@ -783,6 +741,7 @@ impl<'a> Parser<'a> {
fn recover_doc_comment_before_brace(&mut self) -> bool {
if let token::DocComment(..) = self.token.kind {
if self.look_ahead(1, |tok| tok == &token::CloseDelim(Delimiter::Brace)) {
+ // FIXME: merge with `DocCommentDoesNotDocumentAnything` (E0585)
struct_span_err!(
self.diagnostic(),
self.token.span,
@@ -849,7 +808,7 @@ impl<'a> Parser<'a> {
// It's a trait alias.
if had_colon {
let span = span_at_colon.to(span_before_eq);
- self.struct_span_err(span, "bounds are not allowed on trait aliases").emit();
+ self.sess.emit_err(errors::BoundsNotAllowedOnTraitAliases { span });
}
let bounds = self.parse_generic_bounds(None)?;
@@ -858,12 +817,10 @@ impl<'a> Parser<'a> {
let whole_span = lo.to(self.prev_token.span);
if is_auto == IsAuto::Yes {
- let msg = "trait aliases cannot be `auto`";
- self.struct_span_err(whole_span, msg).span_label(whole_span, msg).emit();
+ self.sess.emit_err(errors::TraitAliasCannotBeAuto { span: whole_span });
}
if let Unsafe::Yes(_) = unsafety {
- let msg = "trait aliases cannot be `unsafe`";
- self.struct_span_err(whole_span, msg).span_label(whole_span, msg).emit();
+ self.sess.emit_err(errors::TraitAliasCannotBeUnsafe { span: whole_span });
}
self.sess.gated_spans.gate(sym::trait_alias, whole_span);
@@ -909,8 +866,7 @@ impl<'a> Parser<'a> {
Ok(kind) => kind,
Err(kind) => match kind {
ItemKind::Static(a, _, b) => {
- self.struct_span_err(span, "associated `static` items are not allowed")
- .emit();
+ self.sess.emit_err(errors::AssociatedStaticItemNotAllowed { span });
AssocItemKind::Const(Defaultness::Final, a, b)
}
_ => return self.error_bad_item_kind(span, &kind, "`trait`s or `impl`s"),
@@ -1041,7 +997,7 @@ impl<'a> Parser<'a> {
/// ```text
/// USE_TREE_LIST = Ø | (USE_TREE `,`)* USE_TREE [`,`]
/// ```
- fn parse_use_tree_list(&mut self) -> PResult<'a, Vec<(UseTree, ast::NodeId)>> {
+ fn parse_use_tree_list(&mut self) -> PResult<'a, ThinVec<(UseTree, ast::NodeId)>> {
self.parse_delim_comma_seq(Delimiter::Brace, |p| {
p.recover_diff_marker();
Ok((p.parse_use_tree()?, DUMMY_NODE_ID))
@@ -1084,41 +1040,37 @@ impl<'a> Parser<'a> {
}
fn parse_crate_name_with_dashes(&mut self) -> PResult<'a, Ident> {
- let error_msg = "crate name using dashes are not valid in `extern crate` statements";
- let suggestion_msg = "if the original crate name uses dashes you need to use underscores \
- in the code";
- let mut ident = if self.token.is_keyword(kw::SelfLower) {
+ let ident = if self.token.is_keyword(kw::SelfLower) {
self.parse_path_segment_ident()
} else {
self.parse_ident()
}?;
- let mut idents = vec![];
- let mut replacement = vec![];
- let mut fixed_crate_name = false;
- // Accept `extern crate name-like-this` for better diagnostics.
+
let dash = token::BinOp(token::BinOpToken::Minus);
- if self.token == dash {
- // Do not include `-` as part of the expected tokens list.
- while self.eat(&dash) {
- fixed_crate_name = true;
- replacement.push((self.prev_token.span, "_".to_string()));
- idents.push(self.parse_ident()?);
- }
+ if self.token != dash {
+ return Ok(ident);
}
- if fixed_crate_name {
- let fixed_name_sp = ident.span.to(idents.last().unwrap().span);
- let mut fixed_name = ident.name.to_string();
- for part in idents {
- fixed_name.push_str(&format!("_{}", part.name));
- }
- ident = Ident::from_str_and_span(&fixed_name, fixed_name_sp);
- self.struct_span_err(fixed_name_sp, error_msg)
- .span_label(fixed_name_sp, "dash-separated idents are not valid")
- .multipart_suggestion(suggestion_msg, replacement, Applicability::MachineApplicable)
- .emit();
+ // Accept `extern crate name-like-this` for better diagnostics.
+ let mut dashes = vec![];
+ let mut idents = vec![];
+ while self.eat(&dash) {
+ dashes.push(self.prev_token.span);
+ idents.push(self.parse_ident()?);
}
- Ok(ident)
+
+ let fixed_name_sp = ident.span.to(idents.last().unwrap().span);
+ let mut fixed_name = ident.name.to_string();
+ for part in idents {
+ write!(fixed_name, "_{}", part.name).unwrap();
+ }
+
+ self.sess.emit_err(errors::ExternCrateNameWithDashes {
+ span: fixed_name_sp,
+ sugg: errors::ExternCrateNameWithDashesSugg { dashes },
+ });
+
+ Ok(Ident::from_str_and_span(&fixed_name, fixed_name_sp))
}
/// Parses `extern` for foreign ABIs modules.
@@ -1166,7 +1118,10 @@ impl<'a> Parser<'a> {
Ok(kind) => kind,
Err(kind) => match kind {
ItemKind::Const(_, a, b) => {
- self.error_on_foreign_const(span, ident);
+ self.sess.emit_err(errors::ExternItemCannotBeConst {
+ ident_span: ident.span,
+ const_span: span.with_hi(ident.span.lo()),
+ });
ForeignItemKind::Static(a, Mutability::Not, b)
}
_ => return self.error_bad_item_kind(span, &kind, "`extern` blocks"),
@@ -1178,6 +1133,7 @@ impl<'a> Parser<'a> {
}
fn error_bad_item_kind<T>(&self, span: Span, kind: &ItemKind, ctx: &str) -> Option<T> {
+ // FIXME(#100717): needs variant for each `ItemKind` (instead of using `ItemKind::descr()`)
let span = self.sess.source_map().guess_head_span(span);
let descr = kind.descr();
self.struct_span_err(span, &format!("{descr} is not supported in {ctx}"))
@@ -1186,18 +1142,6 @@ impl<'a> Parser<'a> {
None
}
- fn error_on_foreign_const(&self, span: Span, ident: Ident) {
- self.struct_span_err(ident.span, "extern items cannot be `const`")
- .span_suggestion(
- span.with_hi(ident.span.lo()),
- "try using a static value",
- "static ",
- Applicability::MachineApplicable,
- )
- .note("for more information, visit https://doc.rust-lang.org/std/keyword.extern.html")
- .emit();
- }
-
fn is_unsafe_foreign_mod(&self) -> bool {
self.token.is_keyword(kw::Unsafe)
&& self.is_keyword_ahead(1, &[kw::Extern])
@@ -1225,25 +1169,10 @@ impl<'a> Parser<'a> {
fn recover_const_mut(&mut self, const_span: Span) {
if self.eat_keyword(kw::Mut) {
let span = self.prev_token.span;
- self.struct_span_err(span, "const globals cannot be mutable")
- .span_label(span, "cannot be mutable")
- .span_suggestion(
- const_span,
- "you might want to declare a static instead",
- "static",
- Applicability::MaybeIncorrect,
- )
- .emit();
+ self.sess.emit_err(errors::ConstGlobalCannotBeMutable { ident_span: span, const_span });
} else if self.eat_keyword(kw::Let) {
let span = self.prev_token.span;
- self.struct_span_err(const_span.to(span), "`const` and `let` are mutually exclusive")
- .span_suggestion(
- const_span.to(span),
- "remove `let`",
- "const",
- Applicability::MaybeIncorrect,
- )
- .emit();
+ self.sess.emit_err(errors::ConstLetMutuallyExclusive { span: const_span.to(span) });
}
}
@@ -1328,13 +1257,9 @@ impl<'a> Parser<'a> {
};
let span = self.prev_token.span.shrink_to_hi();
- let mut err = self.struct_span_err(span, &format!("missing type for `{kind}` item"));
- err.span_suggestion(
- span,
- "provide a type for the item",
- format!("{colon} <type>"),
- Applicability::HasPlaceholders,
- );
+ let err: DiagnosticBuilder<'_, ErrorGuaranteed> =
+ errors::MissingConstType { span, colon, kind }
+ .into_diagnostic(&self.sess.span_diagnostic);
err.stash(span, StashKey::ItemNoType);
// The user intended that the type be inferred,
@@ -1346,18 +1271,12 @@ impl<'a> Parser<'a> {
fn parse_item_enum(&mut self) -> PResult<'a, ItemInfo> {
if self.token.is_keyword(kw::Struct) {
let span = self.prev_token.span.to(self.token.span);
- let mut err = self.struct_span_err(span, "`enum` and `struct` are mutually exclusive");
- err.span_suggestion(
- span,
- "replace `enum struct` with",
- "enum",
- Applicability::MachineApplicable,
- );
+ let err = errors::EnumStructMutuallyExclusive { span };
if self.look_ahead(1, |t| t.is_ident()) {
self.bump();
- err.emit();
+ self.sess.emit_err(err);
} else {
- return Err(err);
+ return Err(err.into_diagnostic(&self.sess.span_diagnostic));
}
}
@@ -1367,9 +1286,9 @@ impl<'a> Parser<'a> {
// Possibly recover `enum Foo;` instead of `enum Foo {}`
let (variants, _) = if self.token == TokenKind::Semi {
- self.sess.emit_err(UseEmptyBlockNotSemi { span: self.token.span });
+ self.sess.emit_err(errors::UseEmptyBlockNotSemi { span: self.token.span });
self.bump();
- (vec![], false)
+ (thin_vec![], false)
} else {
self.parse_delim_comma_seq(Delimiter::Brace, |p| p.parse_enum_variant()).map_err(
|mut e| {
@@ -1412,7 +1331,7 @@ impl<'a> Parser<'a> {
};
let disr_expr =
- if this.eat(&token::Eq) { Some(this.parse_anon_const_expr()?) } else { None };
+ if this.eat(&token::Eq) { Some(this.parse_expr_anon_const()?) } else { None };
let vr = ast::Variant {
ident,
@@ -1493,13 +1412,9 @@ impl<'a> Parser<'a> {
self.expect_semi()?;
body
} else {
- let token_str = super::token_descr(&self.token);
- let msg = &format!(
- "expected `where`, `{{`, `(`, or `;` after struct name, found {token_str}"
- );
- let mut err = self.struct_span_err(self.token.span, msg);
- err.span_label(self.token.span, "expected `where`, `{`, `(`, or `;` after struct name");
- return Err(err);
+ let err =
+ errors::UnexpectedTokenAfterStructName::new(self.token.span, self.token.clone());
+ return Err(err.into_diagnostic(&self.sess.span_diagnostic));
};
Ok((class_name, ItemKind::Struct(vdata, generics)))
@@ -1542,8 +1457,8 @@ impl<'a> Parser<'a> {
adt_ty: &str,
ident_span: Span,
parsed_where: bool,
- ) -> PResult<'a, (Vec<FieldDef>, /* recovered */ bool)> {
- let mut fields = Vec::new();
+ ) -> PResult<'a, (ThinVec<FieldDef>, /* recovered */ bool)> {
+ let mut fields = ThinVec::new();
let mut recovered = false;
if self.eat(&token::OpenDelim(Delimiter::Brace)) {
while self.token != token::CloseDelim(Delimiter::Brace) {
@@ -1583,7 +1498,7 @@ impl<'a> Parser<'a> {
Ok((fields, recovered))
}
- pub(super) fn parse_tuple_struct_body(&mut self) -> PResult<'a, Vec<FieldDef>> {
+ pub(super) fn parse_tuple_struct_body(&mut self) -> PResult<'a, ThinVec<FieldDef>> {
// This is the case where we find `struct Foo<T>(T) where T: Copy;`
// Unit like structs are handled in parse_item_struct function
self.parse_paren_comma_seq(|p| {
@@ -1676,7 +1591,7 @@ impl<'a> Parser<'a> {
token::CloseDelim(Delimiter::Brace) => {}
token::DocComment(..) => {
let previous_span = self.prev_token.span;
- let mut err = DocCommentDoesNotDocumentAnything {
+ let mut err = errors::DocCommentDoesNotDocumentAnything {
span: self.token.span,
missing_comma: None,
};
@@ -1807,7 +1722,7 @@ impl<'a> Parser<'a> {
}
if self.token.kind == token::Eq {
self.bump();
- let const_expr = self.parse_anon_const_expr()?;
+ let const_expr = self.parse_expr_anon_const()?;
let sp = ty.span.shrink_to_hi().to(const_expr.value.span);
self.struct_span_err(sp, "default values on `struct` fields aren't supported")
.span_suggestion(
@@ -2186,7 +2101,7 @@ impl<'a> Parser<'a> {
// If we see `for Ty ...` then user probably meant `impl` item.
if self.token.is_keyword(kw::For) {
old_err.cancel();
- return Err(self.sess.create_err(FnTypoWithImpl { fn_span }));
+ return Err(self.sess.create_err(errors::FnTypoWithImpl { fn_span }));
} else {
return Err(old_err);
}
@@ -2330,7 +2245,12 @@ impl<'a> Parser<'a> {
let ext = self.parse_extern(case);
if let Async::Yes { span, .. } = asyncness {
- self.ban_async_in_2015(span);
+ if span.is_rust_2015() {
+ self.sess.emit_err(errors::AsyncFnIn2015 {
+ span,
+ help: errors::HelpUseLatestEdition::new(),
+ });
+ }
}
if !self.eat_keyword_case(kw::Fn, case) {
@@ -2440,17 +2360,6 @@ impl<'a> Parser<'a> {
Ok(FnHeader { constness, unsafety, asyncness, ext })
}
- /// We are parsing `async fn`. If we are on Rust 2015, emit an error.
- fn ban_async_in_2015(&self, span: Span) {
- if span.rust_2015() {
- let diag = self.diagnostic();
- struct_span_err!(diag, span, E0670, "`async fn` is not permitted in Rust 2015")
- .span_label(span, "to use `async fn`, switch to Rust 2018 or later")
- .help_use_latest_edition()
- .emit();
- }
- }
-
/// Parses the parameter list and result type of a function declaration.
pub(super) fn parse_fn_decl(
&mut self,
@@ -2465,7 +2374,7 @@ impl<'a> Parser<'a> {
}
/// Parses the parameter list of a function, including the `(` and `)` delimiters.
- pub(super) fn parse_fn_params(&mut self, req_name: ReqName) -> PResult<'a, Vec<Param>> {
+ pub(super) fn parse_fn_params(&mut self, req_name: ReqName) -> PResult<'a, ThinVec<Param>> {
let mut first_param = true;
// Parse the arguments, starting out with `self` being allowed...
let (mut params, _) = self.parse_paren_comma_seq(|p| {
@@ -2593,9 +2502,7 @@ impl<'a> Parser<'a> {
};
// Recover for the grammar `*self`, `*const self`, and `*mut self`.
let recover_self_ptr = |this: &mut Self| {
- let msg = "cannot pass `self` by raw pointer";
- let span = this.token.span;
- this.struct_span_err(span, msg).span_label(span, msg).emit();
+ self.sess.emit_err(errors::SelfArgumentPointer { span: this.token.span });
Ok((SelfKind::Value(Mutability::Not), expect_self_ident(this), this.prev_token.span))
};
@@ -2676,14 +2583,14 @@ impl<'a> Parser<'a> {
&& self.look_ahead(offset + 1, |t| t == &token::Colon)
}
- fn recover_first_param(&mut self) -> &'static str {
+ fn recover_self_param(&mut self) -> bool {
match self
.parse_outer_attributes()
.and_then(|_| self.parse_self_param())
.map_err(|e| e.cancel())
{
- Ok(Some(_)) => "method",
- _ => "function",
+ Ok(Some(_)) => true,
+ _ => false,
}
}
}
diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs
index ffb23b50a..da82e4724 100644
--- a/compiler/rustc_parse/src/parser/mod.rs
+++ b/compiler/rustc_parse/src/parser/mod.rs
@@ -10,7 +10,7 @@ mod path;
mod stmt;
mod ty;
-use crate::lexer::UnmatchedBrace;
+use crate::lexer::UnmatchedDelim;
pub use attr_wrapper::AttrWrapper;
pub use diagnostics::AttemptLocalParseRecovery;
pub(crate) use item::FnParseMode;
@@ -19,9 +19,8 @@ pub use path::PathStyle;
use rustc_ast::ptr::P;
use rustc_ast::token::{self, Delimiter, Nonterminal, Token, TokenKind};
-use rustc_ast::tokenstream::AttributesData;
-use rustc_ast::tokenstream::{self, DelimSpan, Spacing};
-use rustc_ast::tokenstream::{TokenStream, TokenTree};
+use rustc_ast::tokenstream::{AttributesData, DelimSpan, Spacing};
+use rustc_ast::tokenstream::{TokenStream, TokenTree, TokenTreeCursor};
use rustc_ast::util::case::Case;
use rustc_ast::AttrId;
use rustc_ast::DUMMY_NODE_ID;
@@ -37,9 +36,10 @@ use rustc_errors::{
use rustc_session::parse::ParseSess;
use rustc_span::source_map::{Span, DUMMY_SP};
use rustc_span::symbol::{kw, sym, Ident, Symbol};
-
use std::ops::Range;
use std::{cmp, mem, slice};
+use thin_vec::ThinVec;
+use tracing::debug;
use crate::errors::{
DocCommentDoesNotDocumentAnything, IncorrectVisibilityRestriction, MismatchedClosingDelimiter,
@@ -149,7 +149,7 @@ pub struct Parser<'a> {
/// A list of all unclosed delimiters found by the lexer. If an entry is used for error recovery
/// it gets removed from here. Every entry left at the end gets emitted as an independent
/// error.
- pub(super) unclosed_delims: Vec<UnmatchedBrace>,
+ pub(super) unclosed_delims: Vec<UnmatchedDelim>,
last_unexpected_token_span: Option<Span>,
/// Span pointing at the `:` for the last type ascription the parser has seen, and whether it
/// looked like it could have been a mistyped path or literal `Option:Some(42)`).
@@ -168,7 +168,7 @@ pub struct Parser<'a> {
// This type is used a lot, e.g. it's cloned when matching many declarative macro rules with nonterminals. Make sure
// it doesn't unintentionally get bigger.
#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
-rustc_data_structures::static_assert_size!(Parser<'_>, 336);
+rustc_data_structures::static_assert_size!(Parser<'_>, 312);
/// Stores span information about a closure.
#[derive(Clone)]
@@ -221,18 +221,27 @@ impl<'a> Drop for Parser<'a> {
}
}
+/// Iterator over a `TokenStream` that produces `Token`s. It's a bit odd that
+/// we (a) lex tokens into a nice tree structure (`TokenStream`), and then (b)
+/// use this type to emit them as a linear sequence. But a linear sequence is
+/// what the parser expects, for the most part.
#[derive(Clone)]
struct TokenCursor {
- // The current (innermost) frame. `frame` and `stack` could be combined,
- // but it's faster to have them separately to access `frame` directly
- // rather than via something like `stack.last().unwrap()` or
- // `stack[stack.len() - 1]`.
- frame: TokenCursorFrame,
- // Additional frames that enclose `frame`.
- stack: Vec<TokenCursorFrame>,
+ // Cursor for the current (innermost) token stream. The delimiters for this
+ // token stream are found in `self.stack.last()`; when that is `None` then
+ // we are in the outermost token stream which never has delimiters.
+ tree_cursor: TokenTreeCursor,
+
+ // Token streams surrounding the current one. The delimiters for stack[n]'s
+ // tokens are in `stack[n-1]`. `stack[0]` (when present) has no delimiters
+ // because it's the outermost token stream which never has delimiters.
+ stack: Vec<(TokenTreeCursor, Delimiter, DelimSpan)>,
+
desugar_doc_comments: bool,
+
// Counts the number of calls to `{,inlined_}next`.
num_next_calls: usize,
+
// During parsing, we may sometimes need to 'unglue' a
// glued token into two component tokens
// (e.g. '>>' into '>' and '>), so that the parser
@@ -257,18 +266,6 @@ struct TokenCursor {
break_last_token: bool,
}
-#[derive(Clone)]
-struct TokenCursorFrame {
- delim_sp: Option<(Delimiter, DelimSpan)>,
- tree_cursor: tokenstream::Cursor,
-}
-
-impl TokenCursorFrame {
- fn new(delim_sp: Option<(Delimiter, DelimSpan)>, tts: TokenStream) -> Self {
- TokenCursorFrame { delim_sp, tree_cursor: tts.into_trees() }
- }
-}
-
impl TokenCursor {
fn next(&mut self, desugar_doc_comments: bool) -> (Token, Spacing) {
self.inlined_next(desugar_doc_comments)
@@ -281,38 +278,47 @@ impl TokenCursor {
// FIXME: we currently don't return `Delimiter` open/close delims. To fix #67062 we will
// need to, whereupon the `delim != Delimiter::Invisible` conditions below can be
// removed.
- if let Some(tree) = self.frame.tree_cursor.next_ref() {
+ if let Some(tree) = self.tree_cursor.next_ref() {
match tree {
&TokenTree::Token(ref token, spacing) => match (desugar_doc_comments, token) {
(true, &Token { kind: token::DocComment(_, attr_style, data), span }) => {
- return self.desugar(attr_style, data, span);
+ let desugared = self.desugar(attr_style, data, span);
+ self.tree_cursor.replace_prev_and_rewind(desugared);
+ // Continue to get the first token of the desugared doc comment.
+ }
+ _ => {
+ debug_assert!(!matches!(
+ token.kind,
+ token::OpenDelim(_) | token::CloseDelim(_)
+ ));
+ return (token.clone(), spacing);
}
- _ => return (token.clone(), spacing),
},
&TokenTree::Delimited(sp, delim, ref tts) => {
- // Set `open_delim` to true here because we deal with it immediately.
- let frame = TokenCursorFrame::new(Some((delim, sp)), tts.clone());
- self.stack.push(mem::replace(&mut self.frame, frame));
+ let trees = tts.clone().into_trees();
+ self.stack.push((mem::replace(&mut self.tree_cursor, trees), delim, sp));
if delim != Delimiter::Invisible {
return (Token::new(token::OpenDelim(delim), sp.open), Spacing::Alone);
}
// No open delimiter to return; continue on to the next iteration.
}
};
- } else if let Some(frame) = self.stack.pop() {
- if let Some((delim, span)) = self.frame.delim_sp && delim != Delimiter::Invisible {
- self.frame = frame;
+ } else if let Some((tree_cursor, delim, span)) = self.stack.pop() {
+ // We have exhausted this token stream. Move back to its parent token stream.
+ self.tree_cursor = tree_cursor;
+ if delim != Delimiter::Invisible {
return (Token::new(token::CloseDelim(delim), span.close), Spacing::Alone);
}
- self.frame = frame;
// No close delimiter to return; continue on to the next iteration.
} else {
+ // We have exhausted the outermost token stream.
return (Token::new(token::Eof, DUMMY_SP), Spacing::Alone);
}
}
}
- fn desugar(&mut self, attr_style: AttrStyle, data: Symbol, span: Span) -> (Token, Spacing) {
+ // Desugar a doc comment into something like `#[doc = r"foo"]`.
+ fn desugar(&mut self, attr_style: AttrStyle, data: Symbol, span: Span) -> Vec<TokenTree> {
// Searches for the occurrences of `"#*` and returns the minimum number of `#`s
// required to wrap the text. E.g.
// - `abc d` is wrapped as `r"abc d"` (num_of_hashes = 0)
@@ -329,7 +335,7 @@ impl TokenCursor {
num_of_hashes = cmp::max(num_of_hashes, count);
}
- // `/// foo` becomes `doc = r"foo".
+ // `/// foo` becomes `doc = r"foo"`.
let delim_span = DelimSpan::from_single(span);
let body = TokenTree::Delimited(
delim_span,
@@ -346,27 +352,15 @@ impl TokenCursor {
.collect::<TokenStream>(),
);
- self.stack.push(mem::replace(
- &mut self.frame,
- TokenCursorFrame::new(
- None,
- if attr_style == AttrStyle::Inner {
- [
- TokenTree::token_alone(token::Pound, span),
- TokenTree::token_alone(token::Not, span),
- body,
- ]
- .into_iter()
- .collect::<TokenStream>()
- } else {
- [TokenTree::token_alone(token::Pound, span), body]
- .into_iter()
- .collect::<TokenStream>()
- },
- ),
- ));
-
- self.next(/* desugar_doc_comments */ false)
+ if attr_style == AttrStyle::Inner {
+ vec![
+ TokenTree::token_alone(token::Pound, span),
+ TokenTree::token_alone(token::Not, span),
+ body,
+ ]
+ } else {
+ vec![TokenTree::token_alone(token::Pound, span), body]
+ }
}
}
@@ -475,7 +469,7 @@ impl<'a> Parser<'a> {
restrictions: Restrictions::empty(),
expected_tokens: Vec::new(),
token_cursor: TokenCursor {
- frame: TokenCursorFrame::new(None, tokens),
+ tree_cursor: tokens.into_trees(),
stack: Vec::new(),
num_next_calls: 0,
desugar_doc_comments,
@@ -739,9 +733,10 @@ impl<'a> Parser<'a> {
fn check_const_closure(&self) -> bool {
self.is_keyword_ahead(0, &[kw::Const])
&& self.look_ahead(1, |t| match &t.kind {
- token::Ident(kw::Move | kw::Static | kw::Async, _)
- | token::OrOr
- | token::BinOp(token::Or) => true,
+ // async closures do not work with const closures, so we do not parse that here.
+ token::Ident(kw::Move | kw::Static, _) | token::OrOr | token::BinOp(token::Or) => {
+ true
+ }
_ => false,
})
}
@@ -859,11 +854,11 @@ impl<'a> Parser<'a> {
sep: SeqSep,
expect: TokenExpectType,
mut f: impl FnMut(&mut Parser<'a>) -> PResult<'a, T>,
- ) -> PResult<'a, (Vec<T>, bool /* trailing */, bool /* recovered */)> {
+ ) -> PResult<'a, (ThinVec<T>, bool /* trailing */, bool /* recovered */)> {
let mut first = true;
let mut recovered = false;
let mut trailing = false;
- let mut v = vec![];
+ let mut v = ThinVec::new();
let unclosed_delims = !self.unclosed_delims.is_empty();
while !self.expect_any_with_type(kets, expect) {
@@ -987,7 +982,11 @@ impl<'a> Parser<'a> {
let initial_semicolon = self.token.span;
while self.eat(&TokenKind::Semi) {
- let _ = self.parse_stmt(ForceCollect::Yes)?;
+ let _ =
+ self.parse_stmt_without_recovery(false, ForceCollect::Yes).unwrap_or_else(|e| {
+ e.cancel();
+ None
+ });
}
expect_err.set_primary_message(
@@ -1043,7 +1042,7 @@ impl<'a> Parser<'a> {
ket: &TokenKind,
sep: SeqSep,
f: impl FnMut(&mut Parser<'a>) -> PResult<'a, T>,
- ) -> PResult<'a, (Vec<T>, bool, bool)> {
+ ) -> PResult<'a, (ThinVec<T>, bool, bool)> {
self.parse_seq_to_before_tokens(&[ket], sep, TokenExpectType::Expect, f)
}
@@ -1055,7 +1054,7 @@ impl<'a> Parser<'a> {
ket: &TokenKind,
sep: SeqSep,
f: impl FnMut(&mut Parser<'a>) -> PResult<'a, T>,
- ) -> PResult<'a, (Vec<T>, bool /* trailing */)> {
+ ) -> PResult<'a, (ThinVec<T>, bool /* trailing */)> {
let (val, trailing, recovered) = self.parse_seq_to_before_end(ket, sep, f)?;
if !recovered {
self.eat(ket);
@@ -1072,7 +1071,7 @@ impl<'a> Parser<'a> {
ket: &TokenKind,
sep: SeqSep,
f: impl FnMut(&mut Parser<'a>) -> PResult<'a, T>,
- ) -> PResult<'a, (Vec<T>, bool)> {
+ ) -> PResult<'a, (ThinVec<T>, bool)> {
self.expect(bra)?;
self.parse_seq_to_end(ket, sep, f)
}
@@ -1081,7 +1080,7 @@ impl<'a> Parser<'a> {
&mut self,
delim: Delimiter,
f: impl FnMut(&mut Parser<'a>) -> PResult<'a, T>,
- ) -> PResult<'a, (Vec<T>, bool)> {
+ ) -> PResult<'a, (ThinVec<T>, bool)> {
self.parse_unspanned_seq(
&token::OpenDelim(delim),
&token::CloseDelim(delim),
@@ -1093,7 +1092,7 @@ impl<'a> Parser<'a> {
fn parse_paren_comma_seq<T>(
&mut self,
f: impl FnMut(&mut Parser<'a>) -> PResult<'a, T>,
- ) -> PResult<'a, (Vec<T>, bool)> {
+ ) -> PResult<'a, (ThinVec<T>, bool)> {
self.parse_delim_comma_seq(Delimiter::Parenthesis, f)
}
@@ -1142,14 +1141,16 @@ impl<'a> Parser<'a> {
return looker(&self.token);
}
- let frame = &self.token_cursor.frame;
- if let Some((delim, span)) = frame.delim_sp && delim != Delimiter::Invisible {
+ let tree_cursor = &self.token_cursor.tree_cursor;
+ if let Some(&(_, delim, span)) = self.token_cursor.stack.last()
+ && delim != Delimiter::Invisible
+ {
let all_normal = (0..dist).all(|i| {
- let token = frame.tree_cursor.look_ahead(i);
+ let token = tree_cursor.look_ahead(i);
!matches!(token, Some(TokenTree::Delimited(_, Delimiter::Invisible, _)))
});
if all_normal {
- return match frame.tree_cursor.look_ahead(dist - 1) {
+ return match tree_cursor.look_ahead(dist - 1) {
Some(tree) => match tree {
TokenTree::Token(token, _) => looker(token),
TokenTree::Delimited(dspan, delim, _) => {
@@ -1203,8 +1204,18 @@ impl<'a> Parser<'a> {
/// Parses constness: `const` or nothing.
fn parse_constness(&mut self, case: Case) -> Const {
- // Avoid const blocks to be parsed as const items
- if self.look_ahead(1, |t| t != &token::OpenDelim(Delimiter::Brace))
+ self.parse_constness_(case, false)
+ }
+
+ /// Parses constness for closures
+ fn parse_closure_constness(&mut self, case: Case) -> Const {
+ self.parse_constness_(case, true)
+ }
+
+ fn parse_constness_(&mut self, case: Case, is_closure: bool) -> Const {
+ // Avoid const blocks and const closures to be parsed as const items
+ if (self.check_const_closure() == is_closure)
+ && self.look_ahead(1, |t| t != &token::OpenDelim(Delimiter::Brace))
&& self.eat_keyword_case(kw::Const, case)
{
Const::Yes(self.prev_token.uninterpolated_span())
@@ -1277,22 +1288,16 @@ impl<'a> Parser<'a> {
}
fn parse_delim_args_inner(&mut self) -> Option<DelimArgs> {
- if self.check(&token::OpenDelim(Delimiter::Parenthesis))
+ let delimited = self.check(&token::OpenDelim(Delimiter::Parenthesis))
|| self.check(&token::OpenDelim(Delimiter::Bracket))
- || self.check(&token::OpenDelim(Delimiter::Brace))
- {
- match self.parse_token_tree() {
- // We've confirmed above that there is a delimiter so unwrapping is OK.
- TokenTree::Delimited(dspan, delim, tokens) => Some(DelimArgs {
- dspan,
- delim: MacDelimiter::from_token(delim).unwrap(),
- tokens,
- }),
- _ => unreachable!(),
- }
- } else {
- None
- }
+ || self.check(&token::OpenDelim(Delimiter::Brace));
+
+ delimited.then(|| {
+ // We've confirmed above that there is a delimiter so unwrapping is OK.
+ let TokenTree::Delimited(dspan, delim, tokens) = self.parse_token_tree() else { unreachable!() };
+
+ DelimArgs { dspan, delim: MacDelimiter::from_token(delim).unwrap(), tokens }
+ })
}
fn parse_or_use_outer_attributes(
@@ -1310,10 +1315,10 @@ impl<'a> Parser<'a> {
pub(crate) fn parse_token_tree(&mut self) -> TokenTree {
match self.token.kind {
token::OpenDelim(..) => {
- // Grab the tokens from this frame.
- let frame = &self.token_cursor.frame;
- let stream = frame.tree_cursor.stream.clone();
- let (delim, span) = frame.delim_sp.unwrap();
+ // Grab the tokens within the delimiters.
+ let tree_cursor = &self.token_cursor.tree_cursor;
+ let stream = tree_cursor.stream.clone();
+ let (_, delim, span) = *self.token_cursor.stack.last().unwrap();
// Advance the token cursor through the entire delimited
// sequence. After getting the `OpenDelim` we are *within* the
@@ -1516,11 +1521,11 @@ impl<'a> Parser<'a> {
}
pub(crate) fn make_unclosed_delims_error(
- unmatched: UnmatchedBrace,
+ unmatched: UnmatchedDelim,
sess: &ParseSess,
) -> Option<DiagnosticBuilder<'_, ErrorGuaranteed>> {
// `None` here means an `Eof` was found. We already emit those errors elsewhere, we add them to
- // `unmatched_braces` only for error recovery in the `Parser`.
+ // `unmatched_delims` only for error recovery in the `Parser`.
let found_delim = unmatched.found_delim?;
let mut spans = vec![unmatched.found_span];
if let Some(sp) = unmatched.unclosed_span {
@@ -1537,7 +1542,7 @@ pub(crate) fn make_unclosed_delims_error(
Some(err)
}
-pub fn emit_unclosed_delims(unclosed_delims: &mut Vec<UnmatchedBrace>, sess: &ParseSess) {
+pub fn emit_unclosed_delims(unclosed_delims: &mut Vec<UnmatchedDelim>, sess: &ParseSess) {
*sess.reached_eof.borrow_mut() |=
unclosed_delims.iter().any(|unmatched_delim| unmatched_delim.found_delim.is_none());
for unmatched in unclosed_delims.drain(..) {
diff --git a/compiler/rustc_parse/src/parser/nonterminal.rs b/compiler/rustc_parse/src/parser/nonterminal.rs
index 239ed79ce..7a4d53ed8 100644
--- a/compiler/rustc_parse/src/parser/nonterminal.rs
+++ b/compiler/rustc_parse/src/parser/nonterminal.rs
@@ -2,9 +2,11 @@ use rustc_ast::ptr::P;
use rustc_ast::token::{self, Delimiter, NonterminalKind, Token};
use rustc_ast::HasTokens;
use rustc_ast_pretty::pprust;
+use rustc_errors::IntoDiagnostic;
use rustc_errors::PResult;
use rustc_span::symbol::{kw, Ident};
+use crate::errors::UnexpectedNonterminal;
use crate::parser::pat::{CommaRecoveryMode, RecoverColon, RecoverComma};
use crate::parser::{FollowedByType, ForceCollect, NtOrTt, Parser, PathStyle};
@@ -113,7 +115,8 @@ impl<'a> Parser<'a> {
NonterminalKind::Item => match self.parse_item(ForceCollect::Yes)? {
Some(item) => token::NtItem(item),
None => {
- return Err(self.struct_span_err(self.token.span, "expected an item keyword"));
+ return Err(UnexpectedNonterminal::Item(self.token.span)
+ .into_diagnostic(&self.sess.span_diagnostic));
}
},
NonterminalKind::Block => {
@@ -124,7 +127,8 @@ impl<'a> Parser<'a> {
NonterminalKind::Stmt => match self.parse_stmt(ForceCollect::Yes)? {
Some(s) => token::NtStmt(P(s)),
None => {
- return Err(self.struct_span_err(self.token.span, "expected a statement"));
+ return Err(UnexpectedNonterminal::Statement(self.token.span)
+ .into_diagnostic(&self.sess.span_diagnostic));
}
},
NonterminalKind::PatParam { .. } | NonterminalKind::PatWithOr { .. } => {
@@ -160,9 +164,10 @@ impl<'a> Parser<'a> {
token::NtIdent(ident, is_raw)
}
NonterminalKind::Ident => {
- let token_str = pprust::token_to_string(&self.token);
- let msg = &format!("expected ident, found {}", &token_str);
- return Err(self.struct_span_err(self.token.span, msg));
+ return Err(UnexpectedNonterminal::Ident {
+ span: self.token.span,
+ token: self.token.clone(),
+ }.into_diagnostic(&self.sess.span_diagnostic));
}
NonterminalKind::Path => token::NtPath(
P(self.collect_tokens_no_attrs(|this| this.parse_path(PathStyle::Type))?),
@@ -175,9 +180,10 @@ impl<'a> Parser<'a> {
if self.check_lifetime() {
token::NtLifetime(self.expect_lifetime().ident)
} else {
- let token_str = pprust::token_to_string(&self.token);
- let msg = &format!("expected a lifetime, found `{}`", &token_str);
- return Err(self.struct_span_err(self.token.span, msg));
+ return Err(UnexpectedNonterminal::Lifetime {
+ span: self.token.span,
+ token: self.token.clone(),
+ }.into_diagnostic(&self.sess.span_diagnostic));
}
}
};
diff --git a/compiler/rustc_parse/src/parser/pat.rs b/compiler/rustc_parse/src/parser/pat.rs
index e73a17ced..8e920f1c4 100644
--- a/compiler/rustc_parse/src/parser/pat.rs
+++ b/compiler/rustc_parse/src/parser/pat.rs
@@ -1,5 +1,14 @@
use super::{ForceCollect, Parser, PathStyle, TrailingToken};
-use crate::errors::RemoveLet;
+use crate::errors::{
+ AmbiguousRangePattern, DotDotDotForRemainingFields, DotDotDotRangeToPatternNotAllowed,
+ DotDotDotRestPattern, EnumPatternInsteadOfIdentifier, ExpectedBindingLeftOfAt,
+ ExpectedCommaAfterPatternField, InclusiveRangeExtraEquals, InclusiveRangeMatchArrow,
+ InclusiveRangeNoEnd, InvalidMutInPattern, PatternOnWrongSideOfAt, RefMutOrderIncorrect,
+ RemoveLet, RepeatedMutInPattern, TopLevelOrPatternNotAllowed, TopLevelOrPatternNotAllowedSugg,
+ TrailingVertNotAllowed, UnexpectedLifetimeInPattern, UnexpectedVertVertBeforeFunctionParam,
+ UnexpectedVertVertInPattern,
+};
+use crate::fluent_generated as fluent;
use crate::{maybe_recover_from_interpolated_ty_qpath, maybe_whole};
use rustc_ast::mut_visit::{noop_visit_pat, MutVisitor};
use rustc_ast::ptr::P;
@@ -9,15 +18,32 @@ use rustc_ast::{
PatField, PatKind, Path, QSelf, RangeEnd, RangeSyntax,
};
use rustc_ast_pretty::pprust;
-use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder, ErrorGuaranteed, PResult};
+use rustc_errors::{Applicability, DiagnosticBuilder, ErrorGuaranteed, IntoDiagnostic, PResult};
use rustc_session::errors::ExprParenthesesNeeded;
use rustc_span::source_map::{respan, Span, Spanned};
use rustc_span::symbol::{kw, sym, Ident};
+use thin_vec::{thin_vec, ThinVec};
-pub(super) type Expected = Option<&'static str>;
+#[derive(PartialEq, Copy, Clone)]
+pub enum Expected {
+ ParameterName,
+ ArgumentName,
+ Identifier,
+ BindingPattern,
+}
-/// `Expected` for function and lambda parameter patterns.
-pub(super) const PARAM_EXPECTED: Expected = Some("parameter name");
+impl Expected {
+ // FIXME(#100717): migrate users of this to proper localization
+ fn to_string_or_fallback(expected: Option<Expected>) -> &'static str {
+ match expected {
+ Some(Expected::ParameterName) => "parameter name",
+ Some(Expected::ArgumentName) => "argument name",
+ Some(Expected::Identifier) => "identifier",
+ Some(Expected::BindingPattern) => "binding pattern",
+ None => "pattern",
+ }
+ }
+}
const WHILE_PARSING_OR_MSG: &str = "while parsing this or-pattern starting here";
@@ -54,13 +80,19 @@ enum EatOrResult {
None,
}
+/// The syntax location of a given pattern. Used for diagnostics.
+pub(super) enum PatternLocation {
+ LetBinding,
+ FunctionParameter,
+}
+
impl<'a> Parser<'a> {
/// Parses a pattern.
///
/// Corresponds to `pat<no_top_alt>` in RFC 2535 and does not admit or-patterns
/// at the top level. Used when parsing the parameters of lambda expressions,
/// functions, function pointers, and `pat` macro fragments.
- pub fn parse_pat_no_top_alt(&mut self, expected: Expected) -> PResult<'a, P<Pat>> {
+ pub fn parse_pat_no_top_alt(&mut self, expected: Option<Expected>) -> PResult<'a, P<Pat>> {
self.parse_pat_with_range_pat(true, expected)
}
@@ -74,7 +106,7 @@ impl<'a> Parser<'a> {
/// simplify the grammar somewhat.
pub fn parse_pat_allow_top_alt(
&mut self,
- expected: Expected,
+ expected: Option<Expected>,
rc: RecoverComma,
ra: RecoverColon,
rt: CommaRecoveryMode,
@@ -86,7 +118,7 @@ impl<'a> Parser<'a> {
/// recovered).
fn parse_pat_allow_top_alt_inner(
&mut self,
- expected: Expected,
+ expected: Option<Expected>,
rc: RecoverComma,
ra: RecoverColon,
rt: CommaRecoveryMode,
@@ -123,7 +155,7 @@ impl<'a> Parser<'a> {
// If there was a leading vert, treat this as an or-pattern. This improves
// diagnostics.
let span = leading_vert_span.to(self.prev_token.span);
- return Ok((self.mk_pat(span, PatKind::Or(vec![first_pat])), trailing_vert));
+ return Ok((self.mk_pat(span, PatKind::Or(thin_vec![first_pat])), trailing_vert));
}
return Ok((first_pat, trailing_vert));
@@ -131,7 +163,7 @@ impl<'a> Parser<'a> {
// Parse the patterns `p_1 | ... | p_n` where `n > 0`.
let lo = leading_vert_span.unwrap_or(first_pat.span);
- let mut pats = vec![first_pat];
+ let mut pats = thin_vec![first_pat];
loop {
match self.eat_or_separator(Some(lo)) {
EatOrResult::AteOr => {}
@@ -165,9 +197,9 @@ impl<'a> Parser<'a> {
/// otherwise).
pub(super) fn parse_pat_before_ty(
&mut self,
- expected: Expected,
+ expected: Option<Expected>,
rc: RecoverComma,
- syntax_loc: &str,
+ syntax_loc: PatternLocation,
) -> PResult<'a, (P<Pat>, bool)> {
// We use `parse_pat_allow_top_alt` regardless of whether we actually want top-level
// or-patterns so that we can detect when a user tries to use it. This allows us to print a
@@ -181,27 +213,41 @@ impl<'a> Parser<'a> {
let colon = self.eat(&token::Colon);
if let PatKind::Or(pats) = &pat.kind {
- let msg = format!("top-level or-patterns are not allowed in {}", syntax_loc);
- let (help, fix) = if pats.len() == 1 {
- // If all we have is a leading vert, then print a special message. This is the case
- // if `parse_pat_allow_top_alt` returns an or-pattern with one variant.
- let msg = "remove the `|`";
- let fix = pprust::pat_to_string(&pat);
- (msg, fix)
- } else {
- let msg = "wrap the pattern in parentheses";
- let fix = format!("({})", pprust::pat_to_string(&pat));
- (msg, fix)
- };
+ let span = pat.span;
if trailing_vert {
// We already emitted an error and suggestion to remove the trailing vert. Don't
// emit again.
- self.sess.span_diagnostic.delay_span_bug(pat.span, &msg);
+
+ // FIXME(#100717): pass `TopLevelOrPatternNotAllowed::* { sub: None }` to
+ // `delay_span_bug()` instead of fluent message
+ self.sess.span_diagnostic.delay_span_bug(
+ span,
+ match syntax_loc {
+ PatternLocation::LetBinding => {
+ fluent::parse_or_pattern_not_allowed_in_let_binding
+ }
+ PatternLocation::FunctionParameter => {
+ fluent::parse_or_pattern_not_allowed_in_fn_parameters
+ }
+ },
+ );
} else {
- self.struct_span_err(pat.span, &msg)
- .span_suggestion(pat.span, help, fix, Applicability::MachineApplicable)
- .emit();
+ let pat = pprust::pat_to_string(&pat);
+ let sub = if pats.len() == 1 {
+ Some(TopLevelOrPatternNotAllowedSugg::RemoveLeadingVert { span, pat })
+ } else {
+ Some(TopLevelOrPatternNotAllowedSugg::WrapInParens { span, pat })
+ };
+
+ self.sess.emit_err(match syntax_loc {
+ PatternLocation::LetBinding => {
+ TopLevelOrPatternNotAllowed::LetBinding { span, sub }
+ }
+ PatternLocation::FunctionParameter => {
+ TopLevelOrPatternNotAllowed::FunctionParameter { span, sub }
+ }
+ });
}
}
@@ -218,15 +264,15 @@ impl<'a> Parser<'a> {
// a leading `||` probably doesn't indicate an or-pattern attempt, so we handle that
// separately.
if let token::OrOr = self.token.kind {
- let span = self.token.span;
- let mut err = self.struct_span_err(span, "unexpected `||` before function parameter");
- err.span_suggestion(span, "remove the `||`", "", Applicability::MachineApplicable);
- err.note("alternatives in or-patterns are separated with `|`, not `||`");
- err.emit();
+ self.sess.emit_err(UnexpectedVertVertBeforeFunctionParam { span: self.token.span });
self.bump();
}
- self.parse_pat_before_ty(PARAM_EXPECTED, RecoverComma::No, "function parameters")
+ self.parse_pat_before_ty(
+ Some(Expected::ParameterName),
+ RecoverComma::No,
+ PatternLocation::FunctionParameter,
+ )
}
/// Eat the or-pattern `|` separator.
@@ -236,7 +282,7 @@ impl<'a> Parser<'a> {
EatOrResult::TrailingVert
} else if matches!(self.token.kind, token::OrOr) {
// Found `||`; Recover and pretend we parsed `|`.
- self.ban_unexpected_or_or(lo);
+ self.sess.emit_err(UnexpectedVertVertInPattern { span: self.token.span, start: lo });
self.bump();
EatOrResult::AteOr
} else if self.eat(&token::BinOp(token::Or)) {
@@ -270,7 +316,13 @@ impl<'a> Parser<'a> {
});
match (is_end_ahead, &self.token.kind) {
(true, token::BinOp(token::Or) | token::OrOr) => {
- self.ban_illegal_vert(lo, "trailing", "not allowed in an or-pattern");
+ // A `|` or possibly `||` token shouldn't be here. Ban it.
+ self.sess.emit_err(TrailingVertNotAllowed {
+ span: self.token.span,
+ start: lo,
+ token: self.token.clone(),
+ note_double_vert: matches!(self.token.kind, token::OrOr).then_some(()),
+ });
self.bump();
true
}
@@ -278,46 +330,12 @@ impl<'a> Parser<'a> {
}
}
- /// We have parsed `||` instead of `|`. Error and suggest `|` instead.
- fn ban_unexpected_or_or(&mut self, lo: Option<Span>) {
- let mut err = self.struct_span_err(self.token.span, "unexpected token `||` in pattern");
- err.span_suggestion(
- self.token.span,
- "use a single `|` to separate multiple alternative patterns",
- "|",
- Applicability::MachineApplicable,
- );
- if let Some(lo) = lo {
- err.span_label(lo, WHILE_PARSING_OR_MSG);
- }
- err.emit();
- }
-
- /// A `|` or possibly `||` token shouldn't be here. Ban it.
- fn ban_illegal_vert(&mut self, lo: Option<Span>, pos: &str, ctx: &str) {
- let span = self.token.span;
- let mut err = self.struct_span_err(span, &format!("a {} `|` is {}", pos, ctx));
- err.span_suggestion(
- span,
- &format!("remove the `{}`", pprust::token_to_string(&self.token)),
- "",
- Applicability::MachineApplicable,
- );
- if let Some(lo) = lo {
- err.span_label(lo, WHILE_PARSING_OR_MSG);
- }
- if let token::OrOr = self.token.kind {
- err.note("alternatives in or-patterns are separated with `|`, not `||`");
- }
- err.emit();
- }
-
/// Parses a pattern, with a setting whether modern range patterns (e.g., `a..=b`, `a..b` are
/// allowed).
fn parse_pat_with_range_pat(
&mut self,
allow_range_pat: bool,
- expected: Expected,
+ expected: Option<Expected>,
) -> PResult<'a, P<Pat>> {
maybe_recover_from_interpolated_ty_qpath!(self, true);
maybe_whole!(self, NtPat, |x| x);
@@ -413,7 +431,7 @@ impl<'a> Parser<'a> {
let lt = self.expect_lifetime();
let (lit, _) =
self.recover_unclosed_char(lt.ident, Parser::mk_token_lit_char, |self_| {
- let expected = expected.unwrap_or("pattern");
+ let expected = Expected::to_string_or_fallback(expected);
let msg = format!(
"expected {}, found {}",
expected,
@@ -454,15 +472,7 @@ impl<'a> Parser<'a> {
self.bump(); // `...`
// The user probably mistook `...` for a rest pattern `..`.
- self.struct_span_err(lo, "unexpected `...`")
- .span_label(lo, "not a valid pattern")
- .span_suggestion_short(
- lo,
- "for a rest pattern, use `..` instead of `...`",
- "..",
- Applicability::MachineApplicable,
- )
- .emit();
+ self.sess.emit_err(DotDotDotRestPattern { span: lo });
PatKind::Rest
}
@@ -487,7 +497,7 @@ impl<'a> Parser<'a> {
// At this point we attempt to parse `@ $pat_rhs` and emit an error.
self.bump(); // `@`
let mut rhs = self.parse_pat_no_top_alt(None)?;
- let sp = lhs.span.to(rhs.span);
+ let whole_span = lhs.span.to(rhs.span);
if let PatKind::Ident(_, _, sub @ None) = &mut rhs.kind {
// The user inverted the order, so help them fix that.
@@ -496,27 +506,23 @@ impl<'a> Parser<'a> {
// The RHS is now the full pattern.
*sub = Some(lhs);
- self.struct_span_err(sp, "pattern on wrong side of `@`")
- .span_label(lhs_span, "pattern on the left, should be on the right")
- .span_label(rhs.span, "binding on the right, should be on the left")
- .span_suggestion(
- sp,
- "switch the order",
- pprust::pat_to_string(&rhs),
- Applicability::MachineApplicable,
- )
- .emit();
+ self.sess.emit_err(PatternOnWrongSideOfAt {
+ whole_span,
+ whole_pat: pprust::pat_to_string(&rhs),
+ pattern: lhs_span,
+ binding: rhs.span,
+ });
} else {
// The special case above doesn't apply so we may have e.g. `A(x) @ B(y)`.
rhs.kind = PatKind::Wild;
- self.struct_span_err(sp, "left-hand side of `@` must be a binding")
- .span_label(lhs.span, "interpreted as a pattern, not a binding")
- .span_label(rhs.span, "also a pattern")
- .note("bindings are `x`, `mut x`, `ref x`, and `ref mut x`")
- .emit();
+ self.sess.emit_err(ExpectedBindingLeftOfAt {
+ whole_span,
+ lhs: lhs.span,
+ rhs: rhs.span,
+ });
}
- rhs.span = sp;
+ rhs.span = whole_span;
Ok(rhs)
}
@@ -531,35 +537,23 @@ impl<'a> Parser<'a> {
_ => return,
}
- self.struct_span_err(pat.span, "the range pattern here has ambiguous interpretation")
- .span_suggestion(
- pat.span,
- "add parentheses to clarify the precedence",
- format!("({})", pprust::pat_to_string(&pat)),
- // "ambiguous interpretation" implies that we have to be guessing
- Applicability::MaybeIncorrect,
- )
- .emit();
+ self.sess
+ .emit_err(AmbiguousRangePattern { span: pat.span, pat: pprust::pat_to_string(&pat) });
}
/// Parse `&pat` / `&mut pat`.
- fn parse_pat_deref(&mut self, expected: Expected) -> PResult<'a, PatKind> {
+ fn parse_pat_deref(&mut self, expected: Option<Expected>) -> PResult<'a, PatKind> {
self.expect_and()?;
- self.recover_lifetime_in_deref_pat();
- let mutbl = self.parse_mutability();
- let subpat = self.parse_pat_with_range_pat(false, expected)?;
- Ok(PatKind::Ref(subpat, mutbl))
- }
-
- fn recover_lifetime_in_deref_pat(&mut self) {
if let token::Lifetime(name) = self.token.kind {
self.bump(); // `'a`
- let span = self.prev_token.span;
- self.struct_span_err(span, &format!("unexpected lifetime `{}` in pattern", name))
- .span_suggestion(span, "remove the lifetime", "", Applicability::MachineApplicable)
- .emit();
+ self.sess
+ .emit_err(UnexpectedLifetimeInPattern { span: self.prev_token.span, symbol: name });
}
+
+ let mutbl = self.parse_mutability();
+ let subpat = self.parse_pat_with_range_pat(false, expected)?;
+ Ok(PatKind::Ref(subpat, mutbl))
}
/// Parse a tuple or parenthesis pattern.
@@ -587,7 +581,8 @@ impl<'a> Parser<'a> {
let mut_span = self.prev_token.span;
if self.eat_keyword(kw::Ref) {
- return self.recover_mut_ref_ident(mut_span);
+ self.sess.emit_err(RefMutOrderIncorrect { span: mut_span.to(self.prev_token.span) });
+ return self.parse_pat_ident(BindingAnnotation::REF_MUT);
}
self.recover_additional_muts();
@@ -600,7 +595,7 @@ impl<'a> Parser<'a> {
}
// Parse the pattern we hope to be an identifier.
- let mut pat = self.parse_pat_no_top_alt(Some("identifier"))?;
+ let mut pat = self.parse_pat_no_top_alt(Some(Expected::Identifier))?;
// If we don't have `mut $ident (@ pat)?`, error.
if let PatKind::Ident(BindingAnnotation(ByRef::No, m @ Mutability::Not), ..) = &mut pat.kind
@@ -617,22 +612,6 @@ impl<'a> Parser<'a> {
Ok(pat.into_inner().kind)
}
- /// Recover on `mut ref? ident @ pat` and suggest
- /// that the order of `mut` and `ref` is incorrect.
- fn recover_mut_ref_ident(&mut self, lo: Span) -> PResult<'a, PatKind> {
- let mutref_span = lo.to(self.prev_token.span);
- self.struct_span_err(mutref_span, "the order of `mut` and `ref` is incorrect")
- .span_suggestion(
- mutref_span,
- "try switching the order",
- "ref mut",
- Applicability::MachineApplicable,
- )
- .emit();
-
- self.parse_pat_ident(BindingAnnotation::REF_MUT)
- }
-
/// Turn all by-value immutable bindings in a pattern into mutable bindings.
/// Returns `true` if any change was made.
fn make_all_value_bindings_mutable(pat: &mut P<Pat>) -> bool {
@@ -657,16 +636,13 @@ impl<'a> Parser<'a> {
/// Error on `mut $pat` where `$pat` is not an ident.
fn ban_mut_general_pat(&self, lo: Span, pat: &Pat, changed_any_binding: bool) {
let span = lo.to(pat.span);
- let fix = pprust::pat_to_string(&pat);
- let (problem, suggestion) = if changed_any_binding {
- ("`mut` must be attached to each individual binding", "add `mut` to each binding")
+ let pat = pprust::pat_to_string(&pat);
+
+ self.sess.emit_err(if changed_any_binding {
+ InvalidMutInPattern::NestedIdent { span, pat }
} else {
- ("`mut` must be followed by a named binding", "remove the `mut` prefix")
- };
- self.struct_span_err(span, problem)
- .span_suggestion(span, suggestion, fix, Applicability::MachineApplicable)
- .note("`mut` may be followed by `variable` and `variable @ pattern`")
- .emit();
+ InvalidMutInPattern::NonIdent { span, pat }
+ });
}
/// Eat any extraneous `mut`s and error + recover if we ate any.
@@ -677,15 +653,7 @@ impl<'a> Parser<'a> {
return;
}
- let span = lo.to(self.prev_token.span);
- self.struct_span_err(span, "`mut` on a binding may not be repeated")
- .span_suggestion(
- span,
- "remove the additional `mut`s",
- "",
- Applicability::MachineApplicable,
- )
- .emit();
+ self.sess.emit_err(RepeatedMutInPattern { span: lo.to(self.prev_token.span) });
}
/// Parse macro invocation
@@ -699,11 +667,11 @@ impl<'a> Parser<'a> {
fn fatal_unexpected_non_pat(
&mut self,
err: DiagnosticBuilder<'a, ErrorGuaranteed>,
- expected: Expected,
+ expected: Option<Expected>,
) -> PResult<'a, P<Pat>> {
err.cancel();
- let expected = expected.unwrap_or("pattern");
+ let expected = Expected::to_string_or_fallback(expected);
let msg = format!("expected {}, found {}", expected, super::token_descr(&self.token));
let mut err = self.struct_span_err(self.token.span, &msg);
@@ -745,49 +713,44 @@ impl<'a> Parser<'a> {
// Parsing e.g. `X..`.
if let RangeEnd::Included(_) = re.node {
// FIXME(Centril): Consider semantic errors instead in `ast_validation`.
- self.inclusive_range_with_incorrect_end(re.span);
+ self.inclusive_range_with_incorrect_end();
}
None
};
Ok(PatKind::Range(Some(begin), end, re))
}
- pub(super) fn inclusive_range_with_incorrect_end(&mut self, span: Span) {
+ pub(super) fn inclusive_range_with_incorrect_end(&mut self) {
let tok = &self.token;
-
+ let span = self.prev_token.span;
// If the user typed "..==" instead of "..=", we want to give them
// a specific error message telling them to use "..=".
+ // If they typed "..=>", suggest they use ".. =>".
// Otherwise, we assume that they meant to type a half open exclusive
// range and give them an error telling them to do that instead.
- if matches!(tok.kind, token::Eq) && tok.span.lo() == span.hi() {
- let span_with_eq = span.to(tok.span);
+ let no_space = tok.span.lo() == span.hi();
+ match tok.kind {
+ token::Eq if no_space => {
+ let span_with_eq = span.to(tok.span);
- // Ensure the user doesn't receive unhelpful unexpected token errors
- self.bump();
- if self.is_pat_range_end_start(0) {
- let _ = self.parse_pat_range_end().map_err(|e| e.cancel());
- }
+ // Ensure the user doesn't receive unhelpful unexpected token errors
+ self.bump();
+ if self.is_pat_range_end_start(0) {
+ let _ = self.parse_pat_range_end().map_err(|e| e.cancel());
+ }
- self.error_inclusive_range_with_extra_equals(span_with_eq);
- } else {
- self.error_inclusive_range_with_no_end(span);
+ self.sess.emit_err(InclusiveRangeExtraEquals { span: span_with_eq });
+ }
+ token::Gt if no_space => {
+ let after_pat = span.with_hi(span.hi() - rustc_span::BytePos(1)).shrink_to_hi();
+ self.sess.emit_err(InclusiveRangeMatchArrow { span, arrow: tok.span, after_pat });
+ }
+ _ => {
+ self.sess.emit_err(InclusiveRangeNoEnd { span });
+ }
}
}
- fn error_inclusive_range_with_extra_equals(&self, span: Span) {
- self.struct_span_err(span, "unexpected `=` after inclusive range")
- .span_suggestion_short(span, "use `..=` instead", "..=", Applicability::MaybeIncorrect)
- .note("inclusive ranges end with a single equals sign (`..=`)")
- .emit();
- }
-
- fn error_inclusive_range_with_no_end(&self, span: Span) {
- struct_span_err!(self.sess.span_diagnostic, span, E0586, "inclusive range with no end")
- .span_suggestion_short(span, "use `..` instead", "..", Applicability::MachineApplicable)
- .note("inclusive ranges must be bounded at the end (`..=b` or `a..=b`)")
- .emit();
- }
-
/// Parse a range-to pattern, `..X` or `..=X` where `X` remains to be parsed.
///
/// The form `...X` is prohibited to reduce confusion with the potential
@@ -796,14 +759,7 @@ impl<'a> Parser<'a> {
let end = self.parse_pat_range_end()?;
if let RangeEnd::Included(syn @ RangeSyntax::DotDotDot) = &mut re.node {
*syn = RangeSyntax::DotDotEq;
- self.struct_span_err(re.span, "range-to patterns with `...` are not allowed")
- .span_suggestion_short(
- re.span,
- "use `..=` instead",
- "..=",
- Applicability::MachineApplicable,
- )
- .emit();
+ self.sess.emit_err(DotDotDotRangeToPatternNotAllowed { span: re.span });
}
Ok(PatKind::Range(None, Some(end), re))
}
@@ -868,7 +824,7 @@ impl<'a> Parser<'a> {
fn parse_pat_ident(&mut self, binding_annotation: BindingAnnotation) -> PResult<'a, PatKind> {
let ident = self.parse_ident()?;
let sub = if self.eat(&token::At) {
- Some(self.parse_pat_no_top_alt(Some("binding pattern"))?)
+ Some(self.parse_pat_no_top_alt(Some(Expected::BindingPattern))?)
} else {
None
};
@@ -879,8 +835,8 @@ impl<'a> Parser<'a> {
// binding mode then we do not end up here, because the lookahead
// will direct us over to `parse_enum_variant()`.
if self.token == token::OpenDelim(Delimiter::Parenthesis) {
- return Err(self
- .struct_span_err(self.prev_token.span, "expected identifier, found enum pattern"));
+ return Err(EnumPatternInsteadOfIdentifier { span: self.prev_token.span }
+ .into_diagnostic(&self.sess.span_diagnostic));
}
Ok(PatKind::Ident(binding_annotation, ident, sub))
@@ -897,7 +853,7 @@ impl<'a> Parser<'a> {
e.span_label(path.span, "while parsing the fields for this pattern");
e.emit();
self.recover_stmt();
- (vec![], true)
+ (ThinVec::new(), true)
});
self.bump();
Ok(PatKind::Struct(qself, path, fields, etc))
@@ -962,7 +918,7 @@ impl<'a> Parser<'a> {
// We cannot use `parse_pat_ident()` since it will complain `box`
// is not an identifier.
let sub = if self.eat(&token::At) {
- Some(self.parse_pat_no_top_alt(Some("binding pattern"))?)
+ Some(self.parse_pat_no_top_alt(Some(Expected::BindingPattern))?)
} else {
None
};
@@ -976,8 +932,8 @@ impl<'a> Parser<'a> {
}
/// Parses the fields of a struct-like pattern.
- fn parse_pat_fields(&mut self) -> PResult<'a, (Vec<PatField>, bool)> {
- let mut fields = Vec::new();
+ fn parse_pat_fields(&mut self) -> PResult<'a, (ThinVec<PatField>, bool)> {
+ let mut fields = ThinVec::new();
let mut etc = false;
let mut ate_comma = true;
let mut delayed_err: Option<DiagnosticBuilder<'a, ErrorGuaranteed>> = None;
@@ -997,7 +953,8 @@ impl<'a> Parser<'a> {
// check that a comma comes after every field
if !ate_comma {
- let err = self.struct_span_err(self.token.span, "expected `,`");
+ let err = ExpectedCommaAfterPatternField { span: self.token.span }
+ .into_diagnostic(&self.sess.span_diagnostic);
if let Some(mut delayed) = delayed_err {
delayed.emit();
}
@@ -1005,12 +962,15 @@ impl<'a> Parser<'a> {
}
ate_comma = false;
- if self.check(&token::DotDot) || self.token == token::DotDotDot {
+ if self.check(&token::DotDot)
+ || self.check_noexpect(&token::DotDotDot)
+ || self.check_keyword(kw::Underscore)
+ {
etc = true;
let mut etc_sp = self.token.span;
- self.recover_one_fewer_dotdot();
- self.bump(); // `..` || `...`
+ self.recover_bad_dot_dot();
+ self.bump(); // `..` || `...` || `_`
if self.token == token::CloseDelim(Delimiter::Brace) {
etc_span = Some(etc_sp);
@@ -1103,21 +1063,15 @@ impl<'a> Parser<'a> {
Ok((fields, etc))
}
- /// Recover on `...` as if it were `..` to avoid further errors.
+ /// Recover on `...` or `_` as if it were `..` to avoid further errors.
/// See issue #46718.
- fn recover_one_fewer_dotdot(&self) {
- if self.token != token::DotDotDot {
+ fn recover_bad_dot_dot(&self) {
+ if self.token == token::DotDot {
return;
}
- self.struct_span_err(self.token.span, "expected field pattern, found `...`")
- .span_suggestion(
- self.token.span,
- "to omit remaining fields, use one fewer `.`",
- "..",
- Applicability::MachineApplicable,
- )
- .emit();
+ let token_str = pprust::token_to_string(&self.token);
+ self.sess.emit_err(DotDotDotForRemainingFields { span: self.token.span, token_str });
}
fn parse_pat_field(&mut self, lo: Span, attrs: AttrVec) -> PResult<'a, PatField> {
diff --git a/compiler/rustc_parse/src/parser/path.rs b/compiler/rustc_parse/src/parser/path.rs
index 5333d3b85..b50d2984a 100644
--- a/compiler/rustc_parse/src/parser/path.rs
+++ b/compiler/rustc_parse/src/parser/path.rs
@@ -332,7 +332,7 @@ impl<'a> Parser<'a> {
style: PathStyle,
lo: Span,
ty_generics: Option<&Generics>,
- ) -> PResult<'a, Vec<AngleBracketedArg>> {
+ ) -> PResult<'a, ThinVec<AngleBracketedArg>> {
// We need to detect whether there are extra leading left angle brackets and produce an
// appropriate error and suggestion. This cannot be implemented by looking ahead at
// upcoming tokens for a matching `>` character - if there are unmatched `<` tokens
@@ -404,7 +404,7 @@ impl<'a> Parser<'a> {
let is_first_invocation = style == PathStyle::Expr;
// Take a snapshot before attempting to parse - we can restore this later.
- let snapshot = if is_first_invocation { Some(self.clone()) } else { None };
+ let snapshot = is_first_invocation.then(|| self.clone());
debug!("parse_generic_args_with_leading_angle_bracket_recovery: (snapshotting)");
match self.parse_angle_args(ty_generics) {
@@ -472,8 +472,8 @@ impl<'a> Parser<'a> {
pub(super) fn parse_angle_args(
&mut self,
ty_generics: Option<&Generics>,
- ) -> PResult<'a, Vec<AngleBracketedArg>> {
- let mut args = Vec::new();
+ ) -> PResult<'a, ThinVec<AngleBracketedArg>> {
+ let mut args = ThinVec::new();
while let Some(arg) = self.parse_angle_arg(ty_generics)? {
args.push(arg);
if !self.eat(&token::Comma) {
@@ -653,7 +653,7 @@ impl<'a> Parser<'a> {
pub(super) fn parse_const_arg(&mut self) -> PResult<'a, AnonConst> {
// Parse const argument.
let value = if let token::OpenDelim(Delimiter::Brace) = self.token.kind {
- self.parse_block_expr(None, self.token.span, BlockCheckMode::Default)?
+ self.parse_expr_block(None, self.token.span, BlockCheckMode::Default)?
} else {
self.handle_unambiguous_unbraced_const_arg()?
};
@@ -675,22 +675,42 @@ impl<'a> Parser<'a> {
GenericArg::Const(self.parse_const_arg()?)
} else if self.check_type() {
// Parse type argument.
- let is_const_fn =
- self.look_ahead(1, |t| t.kind == token::OpenDelim(Delimiter::Parenthesis));
- let mut snapshot = self.create_snapshot_for_diagnostic();
+
+ // Proactively create a parser snapshot enabling us to rewind and try to reparse the
+ // input as a const expression in case we fail to parse a type. If we successfully
+ // do so, we will report an error that it needs to be wrapped in braces.
+ let mut snapshot = None;
+ if self.may_recover() && self.token.can_begin_expr() {
+ snapshot = Some(self.create_snapshot_for_diagnostic());
+ }
+
match self.parse_ty() {
- Ok(ty) => GenericArg::Type(ty),
+ Ok(ty) => {
+ // Since the type parser recovers from some malformed slice and array types and
+ // successfully returns a type, we need to look for `TyKind::Err`s in the
+ // type to determine if error recovery has occurred and if the input is not a
+ // syntactically valid type after all.
+ if let ast::TyKind::Slice(inner_ty) | ast::TyKind::Array(inner_ty, _) = &ty.kind
+ && let ast::TyKind::Err = inner_ty.kind
+ && let Some(snapshot) = snapshot
+ && let Some(expr) = self.recover_unbraced_const_arg_that_can_begin_ty(snapshot)
+ {
+ return Ok(Some(self.dummy_const_arg_needs_braces(
+ self.struct_span_err(expr.span, "invalid const generic expression"),
+ expr.span,
+ )));
+ }
+
+ GenericArg::Type(ty)
+ }
Err(err) => {
- if is_const_fn {
- match (*snapshot).parse_expr_res(Restrictions::CONST_EXPR, None) {
- Ok(expr) => {
- self.restore_snapshot(snapshot);
- return Ok(Some(self.dummy_const_arg_needs_braces(err, expr.span)));
- }
- Err(err) => {
- err.cancel();
- }
- }
+ if let Some(snapshot) = snapshot
+ && let Some(expr) = self.recover_unbraced_const_arg_that_can_begin_ty(snapshot)
+ {
+ return Ok(Some(self.dummy_const_arg_needs_braces(
+ err,
+ expr.span,
+ )));
}
// Try to recover from possible `const` arg without braces.
return self.recover_const_arg(start, err).map(Some);
diff --git a/compiler/rustc_parse/src/parser/stmt.rs b/compiler/rustc_parse/src/parser/stmt.rs
index 4ff9927aa..92a22ffc2 100644
--- a/compiler/rustc_parse/src/parser/stmt.rs
+++ b/compiler/rustc_parse/src/parser/stmt.rs
@@ -1,18 +1,13 @@
use super::attr::InnerAttrForbiddenReason;
use super::diagnostics::AttemptLocalParseRecovery;
use super::expr::LhsExpr;
-use super::pat::RecoverComma;
+use super::pat::{PatternLocation, RecoverComma};
use super::path::PathStyle;
use super::TrailingToken;
use super::{
AttrWrapper, BlockMode, FnParseMode, ForceCollect, Parser, Restrictions, SemiColonMode,
};
-use crate::errors::{
- AssignmentElseNotAllowed, CompoundAssignmentExpressionInLet, ConstLetMutuallyExclusive,
- DocCommentDoesNotDocumentAnything, ExpectedStatementAfterOuterAttr, InvalidCurlyInLetElse,
- InvalidExpressionInLetElse, InvalidIdentiferStartsWithNumber, InvalidVariableDeclaration,
- InvalidVariableDeclarationSub, WrapExpressionInParentheses,
-};
+use crate::errors;
use crate::maybe_whole;
use rustc_ast as ast;
@@ -25,8 +20,8 @@ use rustc_ast::{StmtKind, DUMMY_NODE_ID};
use rustc_errors::{Applicability, DiagnosticBuilder, ErrorGuaranteed, PResult};
use rustc_span::source_map::{BytePos, Span};
use rustc_span::symbol::{kw, sym};
-
use std::mem;
+use thin_vec::{thin_vec, ThinVec};
impl<'a> Parser<'a> {
/// Parses a statement. This stops just before trailing semicolons on everything but items.
@@ -64,40 +59,45 @@ impl<'a> Parser<'a> {
if self.token.is_keyword(kw::Mut) && self.is_keyword_ahead(1, &[kw::Let]) {
self.bump();
let mut_let_span = lo.to(self.token.span);
- self.sess.emit_err(InvalidVariableDeclaration {
+ self.sess.emit_err(errors::InvalidVariableDeclaration {
span: mut_let_span,
- sub: InvalidVariableDeclarationSub::SwitchMutLetOrder(mut_let_span),
+ sub: errors::InvalidVariableDeclarationSub::SwitchMutLetOrder(mut_let_span),
});
}
Ok(Some(if self.token.is_keyword(kw::Let) {
self.parse_local_mk(lo, attrs, capture_semi, force_collect)?
} else if self.is_kw_followed_by_ident(kw::Mut) && self.may_recover() {
- self.recover_stmt_local_after_let(lo, attrs, InvalidVariableDeclarationSub::MissingLet)?
+ self.recover_stmt_local_after_let(
+ lo,
+ attrs,
+ errors::InvalidVariableDeclarationSub::MissingLet,
+ )?
} else if self.is_kw_followed_by_ident(kw::Auto) && self.may_recover() {
self.bump(); // `auto`
self.recover_stmt_local_after_let(
lo,
attrs,
- InvalidVariableDeclarationSub::UseLetNotAuto,
+ errors::InvalidVariableDeclarationSub::UseLetNotAuto,
)?
} else if self.is_kw_followed_by_ident(sym::var) && self.may_recover() {
self.bump(); // `var`
self.recover_stmt_local_after_let(
lo,
attrs,
- InvalidVariableDeclarationSub::UseLetNotVar,
+ errors::InvalidVariableDeclarationSub::UseLetNotVar,
)?
} else if self.check_path() && !self.token.is_qpath_start() && !self.is_path_start_item() {
// We have avoided contextual keywords like `union`, items with `crate` visibility,
// or `auto trait` items. We aim to parse an arbitrary path `a::b` but not something
// that starts like a path (1 token), but it fact not a path.
// Also, we avoid stealing syntax from `parse_item_`.
- if force_collect == ForceCollect::Yes {
- self.collect_tokens_no_attrs(|this| this.parse_stmt_path_start(lo, attrs))
- } else {
- self.parse_stmt_path_start(lo, attrs)
- }?
+ match force_collect {
+ ForceCollect::Yes => {
+ self.collect_tokens_no_attrs(|this| this.parse_stmt_path_start(lo, attrs))?
+ }
+ ForceCollect::No => self.parse_stmt_path_start(lo, attrs)?,
+ }
} else if let Some(item) = self.parse_item_common(
attrs.clone(),
false,
@@ -113,18 +113,17 @@ impl<'a> Parser<'a> {
self.mk_stmt(lo, StmtKind::Empty)
} else if self.token != token::CloseDelim(Delimiter::Brace) {
// Remainder are line-expr stmts.
- let e = if force_collect == ForceCollect::Yes {
- self.collect_tokens_no_attrs(|this| {
+ let e = match force_collect {
+ ForceCollect::Yes => self.collect_tokens_no_attrs(|this| {
this.parse_expr_res(Restrictions::STMT_EXPR, Some(attrs))
- })
- } else {
- self.parse_expr_res(Restrictions::STMT_EXPR, Some(attrs))
- }?;
+ })?,
+ ForceCollect::No => self.parse_expr_res(Restrictions::STMT_EXPR, Some(attrs))?,
+ };
if matches!(e.kind, ExprKind::Assign(..)) && self.eat_keyword(kw::Else) {
let bl = self.parse_block()?;
// Destructuring assignment ... else.
// This is not allowed, but point it out in a nice way.
- self.sess.emit_err(AssignmentElseNotAllowed { span: e.span.to(bl.span) });
+ self.sess.emit_err(errors::AssignmentElseNotAllowed { span: e.span.to(bl.span) });
}
self.mk_stmt(lo.to(e.span), StmtKind::Expr(e))
} else {
@@ -147,14 +146,14 @@ impl<'a> Parser<'a> {
}
let expr = if this.eat(&token::OpenDelim(Delimiter::Brace)) {
- this.parse_struct_expr(None, path, true)?
+ this.parse_expr_struct(None, path, true)?
} else {
let hi = this.prev_token.span;
this.mk_expr(lo.to(hi), ExprKind::Path(None, path))
};
let expr = this.with_res(Restrictions::STMT_EXPR, |this| {
- this.parse_dot_or_call_expr_with(expr, lo, attrs)
+ this.parse_expr_dot_or_call_with(expr, lo, attrs)
})?;
// `DUMMY_SP` will get overwritten later in this function
Ok((this.mk_stmt(rustc_span::DUMMY_SP, StmtKind::Expr(expr)), TrailingToken::None))
@@ -164,7 +163,7 @@ impl<'a> Parser<'a> {
// Perform this outside of the `collect_tokens_trailing_token` closure,
// since our outer attributes do not apply to this part of the expression
let expr = self.with_res(Restrictions::STMT_EXPR, |this| {
- this.parse_assoc_expr_with(
+ this.parse_expr_assoc_with(
0,
LhsExpr::AlreadyParsed { expr, starts_statement: true },
)
@@ -200,8 +199,8 @@ impl<'a> Parser<'a> {
// Since none of the above applied, this is an expression statement macro.
let e = self.mk_expr(lo.to(hi), ExprKind::MacCall(mac));
let e = self.maybe_recover_from_bad_qpath(e)?;
- let e = self.parse_dot_or_call_expr_with(e, lo, attrs)?;
- let e = self.parse_assoc_expr_with(
+ let e = self.parse_expr_dot_or_call_with(e, lo, attrs)?;
+ let e = self.parse_expr_assoc_with(
0,
LhsExpr::AlreadyParsed { expr: e, starts_statement: false },
)?;
@@ -217,12 +216,12 @@ impl<'a> Parser<'a> {
&& let attrs = attrs.take_for_recovery(self.sess)
&& let attrs @ [.., last] = &*attrs {
if last.is_doc_comment() {
- self.sess.emit_err(DocCommentDoesNotDocumentAnything {
+ self.sess.emit_err(errors::DocCommentDoesNotDocumentAnything {
span: last.span,
missing_comma: None,
});
} else if attrs.iter().any(|a| a.style == AttrStyle::Outer) {
- self.sess.emit_err(ExpectedStatementAfterOuterAttr { span: last.span });
+ self.sess.emit_err(errors::ExpectedStatementAfterOuterAttr { span: last.span });
}
}
}
@@ -231,7 +230,7 @@ impl<'a> Parser<'a> {
&mut self,
lo: Span,
attrs: AttrWrapper,
- subdiagnostic: fn(Span) -> InvalidVariableDeclarationSub,
+ subdiagnostic: fn(Span) -> errors::InvalidVariableDeclarationSub,
) -> PResult<'a, Stmt> {
let stmt =
self.collect_tokens_trailing_token(attrs, ForceCollect::Yes, |this, attrs| {
@@ -242,7 +241,7 @@ impl<'a> Parser<'a> {
TrailingToken::None,
))
})?;
- self.sess.emit_err(InvalidVariableDeclaration { span: lo, sub: subdiagnostic(lo) });
+ self.sess.emit_err(errors::InvalidVariableDeclaration { span: lo, sub: subdiagnostic(lo) });
Ok(stmt)
}
@@ -270,12 +269,13 @@ impl<'a> Parser<'a> {
let lo = self.prev_token.span;
if self.token.is_keyword(kw::Const) && self.look_ahead(1, |t| t.is_ident()) {
- self.sess.emit_err(ConstLetMutuallyExclusive { span: lo.to(self.token.span) });
+ self.sess.emit_err(errors::ConstLetMutuallyExclusive { span: lo.to(self.token.span) });
self.bump();
}
self.report_invalid_identifier_error()?;
- let (pat, colon) = self.parse_pat_before_ty(None, RecoverComma::Yes, "`let` bindings")?;
+ let (pat, colon) =
+ self.parse_pat_before_ty(None, RecoverComma::Yes, PatternLocation::LetBinding)?;
let (err, ty) = if colon {
// Save the state of the parser before parsing type normally, in case there is a `:`
@@ -372,7 +372,7 @@ impl<'a> Parser<'a> {
rustc_ast::MetaItemLit::from_token(&self.token).is_none() &&
(lit.kind == token::LitKind::Integer || lit.kind == token::LitKind::Float) &&
self.look_ahead(1, |t| matches!(t.kind, token::Eq) || matches!(t.kind, token::Colon ) ) {
- return Err(self.sess.create_err(InvalidIdentiferStartsWithNumber { span: self.token.span }));
+ return Err(self.sess.create_err(errors::InvalidIdentiferStartsWithNumber { span: self.token.span }));
}
Ok(())
}
@@ -380,10 +380,10 @@ impl<'a> Parser<'a> {
fn check_let_else_init_bool_expr(&self, init: &ast::Expr) {
if let ast::ExprKind::Binary(op, ..) = init.kind {
if op.node.lazy() {
- self.sess.emit_err(InvalidExpressionInLetElse {
+ self.sess.emit_err(errors::InvalidExpressionInLetElse {
span: init.span,
operator: op.node.to_string(),
- sugg: WrapExpressionInParentheses {
+ sugg: errors::WrapExpressionInParentheses {
left: init.span.shrink_to_lo(),
right: init.span.shrink_to_hi(),
},
@@ -394,9 +394,9 @@ impl<'a> Parser<'a> {
fn check_let_else_init_trailing_brace(&self, init: &ast::Expr) {
if let Some(trailing) = classify::expr_trailing_brace(init) {
- self.sess.emit_err(InvalidCurlyInLetElse {
+ self.sess.emit_err(errors::InvalidCurlyInLetElse {
span: trailing.span.with_lo(trailing.span.hi() - BytePos(1)),
- sugg: WrapExpressionInParentheses {
+ sugg: errors::WrapExpressionInParentheses {
left: trailing.span.shrink_to_lo(),
right: trailing.span.shrink_to_hi(),
},
@@ -409,7 +409,8 @@ impl<'a> Parser<'a> {
let eq_consumed = match self.token.kind {
token::BinOpEq(..) => {
// Recover `let x <op>= 1` as `let x = 1`
- self.sess.emit_err(CompoundAssignmentExpressionInLet { span: self.token.span });
+ self.sess
+ .emit_err(errors::CompoundAssignmentExpressionInLet { span: self.token.span });
self.bump();
true
}
@@ -543,7 +544,7 @@ impl<'a> Parser<'a> {
s: BlockCheckMode,
recover: AttemptLocalParseRecovery,
) -> PResult<'a, P<Block>> {
- let mut stmts = vec![];
+ let mut stmts = ThinVec::new();
let mut snapshot = None;
while !self.eat(&token::CloseDelim(Delimiter::Brace)) {
if self.token == token::Eof {
@@ -661,7 +662,12 @@ impl<'a> Parser<'a> {
Ok(Some(stmt))
}
- pub(super) fn mk_block(&self, stmts: Vec<Stmt>, rules: BlockCheckMode, span: Span) -> P<Block> {
+ pub(super) fn mk_block(
+ &self,
+ stmts: ThinVec<Stmt>,
+ rules: BlockCheckMode,
+ span: Span,
+ ) -> P<Block> {
P(Block {
stmts,
id: DUMMY_NODE_ID,
@@ -681,6 +687,6 @@ impl<'a> Parser<'a> {
}
pub(super) fn mk_block_err(&self, span: Span) -> P<Block> {
- self.mk_block(vec![self.mk_stmt_err(span)], BlockCheckMode::Default, span)
+ self.mk_block(thin_vec![self.mk_stmt_err(span)], BlockCheckMode::Default, span)
}
}
diff --git a/compiler/rustc_parse/src/parser/ty.rs b/compiler/rustc_parse/src/parser/ty.rs
index 867974672..6fe4da71f 100644
--- a/compiler/rustc_parse/src/parser/ty.rs
+++ b/compiler/rustc_parse/src/parser/ty.rs
@@ -1,6 +1,12 @@
use super::{Parser, PathStyle, TokenType};
-use crate::errors::{ExpectedFnPathFoundFnKeyword, FnPtrWithGenerics, FnPtrWithGenericsSugg};
+use crate::errors::{
+ DynAfterMut, ExpectedFnPathFoundFnKeyword, ExpectedMutOrConstInRawPointerType,
+ FnPointerCannotBeAsync, FnPointerCannotBeConst, FnPtrWithGenerics, FnPtrWithGenericsSugg,
+ InvalidDynKeyword, LifetimeAfterMut, NeedPlusAfterTraitObjectLifetime,
+ NegativeBoundsNotSupported, NegativeBoundsNotSupportedSugg, NestedCVariadicType,
+ ReturnTypesUseThinArrow,
+};
use crate::{maybe_recover_from_interpolated_ty_qpath, maybe_whole};
use ast::DUMMY_NODE_ID;
@@ -11,11 +17,11 @@ use rustc_ast::{
self as ast, BareFnTy, FnRetTy, GenericBound, GenericBounds, GenericParam, Generics, Lifetime,
MacCall, MutTy, Mutability, PolyTraitRef, TraitBoundModifier, TraitObjectSyntax, Ty, TyKind,
};
-use rustc_errors::{pluralize, struct_span_err, Applicability, PResult};
+use rustc_errors::{Applicability, PResult};
use rustc_span::source_map::Span;
use rustc_span::symbol::{kw, sym, Ident};
use rustc_span::Symbol;
-use thin_vec::thin_vec;
+use thin_vec::{thin_vec, ThinVec};
/// Any `?` or `~const` modifiers that appear at the start of a bound.
struct BoundModifiers {
@@ -217,14 +223,7 @@ impl<'a> Parser<'a> {
// Don't `eat` to prevent `=>` from being added as an expected token which isn't
// actually expected and could only confuse users
self.bump();
- self.struct_span_err(self.prev_token.span, "return types are denoted using `->`")
- .span_suggestion_short(
- self.prev_token.span,
- "use `->` instead",
- "->",
- Applicability::MachineApplicable,
- )
- .emit();
+ self.sess.emit_err(ReturnTypesUseThinArrow { span: self.prev_token.span });
let ty = self.parse_ty_common(
allow_plus,
AllowCVariadic::No,
@@ -274,7 +273,7 @@ impl<'a> Parser<'a> {
TyKind::Infer
} else if self.check_fn_front_matter(false, Case::Sensitive) {
// Function pointer type
- self.parse_ty_bare_fn(lo, Vec::new(), None, recover_return_sign)?
+ self.parse_ty_bare_fn(lo, ThinVec::new(), None, recover_return_sign)?
} else if self.check_keyword(kw::For) {
// Function pointer type or bound list (trait object type) starting with a poly-trait.
// `for<'lt> [unsafe] [extern "ABI"] fn (&'lt S) -> T`
@@ -305,13 +304,14 @@ impl<'a> Parser<'a> {
} else if self.can_begin_bound() {
self.parse_bare_trait_object(lo, allow_plus)?
} else if self.eat(&token::DotDotDot) {
- if allow_c_variadic == AllowCVariadic::Yes {
- TyKind::CVarArgs
- } else {
- // FIXME(Centril): Should we just allow `...` syntactically
- // anywhere in a type and use semantic restrictions instead?
- self.error_illegal_c_varadic_ty(lo);
- TyKind::Err
+ match allow_c_variadic {
+ AllowCVariadic::Yes => TyKind::CVarArgs,
+ AllowCVariadic::No => {
+ // FIXME(Centril): Should we just allow `...` syntactically
+ // anywhere in a type and use semantic restrictions instead?
+ self.sess.emit_err(NestedCVariadicType { span: lo.to(self.prev_token.span) });
+ TyKind::Err
+ }
}
} else {
let msg = format!("expected type, found {}", super::token_descr(&self.token));
@@ -325,10 +325,9 @@ impl<'a> Parser<'a> {
let mut ty = self.mk_ty(span, kind);
// Try to recover from use of `+` with incorrect priority.
- if matches!(allow_plus, AllowPlus::Yes) {
- self.maybe_recover_from_bad_type_plus(&ty)?;
- } else {
- self.maybe_report_ambiguous_plus(impl_dyn_multi, &ty);
+ match allow_plus {
+ AllowPlus::Yes => self.maybe_recover_from_bad_type_plus(&ty)?,
+ AllowPlus::No => self.maybe_report_ambiguous_plus(impl_dyn_multi, &ty),
}
if let RecoverQuestionMark::Yes = recover_question_mark {
ty = self.maybe_recover_from_question_mark(ty);
@@ -353,7 +352,7 @@ impl<'a> Parser<'a> {
match ty.kind {
// `(TY_BOUND_NOPAREN) + BOUND + ...`.
TyKind::Path(None, path) if maybe_bounds => {
- self.parse_remaining_bounds_path(Vec::new(), path, lo, true)
+ self.parse_remaining_bounds_path(ThinVec::new(), path, lo, true)
}
TyKind::TraitObject(bounds, TraitObjectSyntax::None)
if maybe_bounds && bounds.len() == 1 && !trailing_plus =>
@@ -372,15 +371,14 @@ impl<'a> Parser<'a> {
let lt_no_plus = self.check_lifetime() && !self.look_ahead(1, |t| t.is_like_plus());
let bounds = self.parse_generic_bounds_common(allow_plus, None)?;
if lt_no_plus {
- self.struct_span_err(lo, "lifetime in trait object type must be followed by `+`")
- .emit();
+ self.sess.emit_err(NeedPlusAfterTraitObjectLifetime { span: lo });
}
Ok(TyKind::TraitObject(bounds, TraitObjectSyntax::None))
}
fn parse_remaining_bounds_path(
&mut self,
- generic_params: Vec<GenericParam>,
+ generic_params: ThinVec<GenericParam>,
path: ast::Path,
lo: Span,
parse_plus: bool,
@@ -407,14 +405,10 @@ impl<'a> Parser<'a> {
fn parse_ty_ptr(&mut self) -> PResult<'a, TyKind> {
let mutbl = self.parse_const_or_mut().unwrap_or_else(|| {
let span = self.prev_token.span;
- self.struct_span_err(span, "expected `mut` or `const` keyword in raw pointer type")
- .span_suggestions(
- span.shrink_to_hi(),
- "add `mut` or `const` here",
- ["mut ".to_string(), "const ".to_string()],
- Applicability::HasPlaceholders,
- )
- .emit();
+ self.sess.emit_err(ExpectedMutOrConstInRawPointerType {
+ span,
+ after_asterisk: span.shrink_to_hi(),
+ });
Mutability::Not
});
let ty = self.parse_ty_no_plus()?;
@@ -439,7 +433,7 @@ impl<'a> Parser<'a> {
};
let ty = if self.eat(&token::Semi) {
- let mut length = self.parse_anon_const_expr()?;
+ let mut length = self.parse_expr_anon_const()?;
if let Err(e) = self.expect(&token::CloseDelim(Delimiter::Bracket)) {
// Try to recover from `X<Y, ...>` when `X::<Y, ...>` works
self.check_mistyped_turbofish_with_multiple_type_params(e, &mut length.value)?;
@@ -456,8 +450,7 @@ impl<'a> Parser<'a> {
fn parse_borrowed_pointee(&mut self) -> PResult<'a, TyKind> {
let and_span = self.prev_token.span;
- let mut opt_lifetime =
- if self.check_lifetime() { Some(self.expect_lifetime()) } else { None };
+ let mut opt_lifetime = self.check_lifetime().then(|| self.expect_lifetime());
let mut mutbl = self.parse_mutability();
if self.token.is_lifetime() && mutbl == Mutability::Mut && opt_lifetime.is_none() {
// A lifetime is invalid here: it would be part of a bare trait bound, which requires
@@ -469,16 +462,13 @@ impl<'a> Parser<'a> {
let lifetime_span = self.token.span;
let span = and_span.to(lifetime_span);
- let mut err = self.struct_span_err(span, "lifetime must precede `mut`");
- if let Ok(lifetime_src) = self.span_to_snippet(lifetime_span) {
- err.span_suggestion(
- span,
- "place the lifetime before `mut`",
- format!("&{} mut", lifetime_src),
- Applicability::MaybeIncorrect,
- );
- }
- err.emit();
+ let (suggest_lifetime, snippet) =
+ if let Ok(lifetime_src) = self.span_to_snippet(lifetime_span) {
+ (Some(span), lifetime_src)
+ } else {
+ (None, String::new())
+ };
+ self.sess.emit_err(LifetimeAfterMut { span, suggest_lifetime, snippet });
opt_lifetime = Some(self.expect_lifetime());
}
@@ -488,14 +478,7 @@ impl<'a> Parser<'a> {
{
// We have `&dyn mut ...`, which is invalid and should be `&mut dyn ...`.
let span = and_span.to(self.look_ahead(1, |t| t.span));
- let mut err = self.struct_span_err(span, "`mut` must precede `dyn`");
- err.span_suggestion(
- span,
- "place `mut` before `dyn`",
- "&mut dyn",
- Applicability::MachineApplicable,
- );
- err.emit();
+ self.sess.emit_err(DynAfterMut { span });
// Recovery
mutbl = Mutability::Mut;
@@ -511,7 +494,7 @@ impl<'a> Parser<'a> {
// To avoid ambiguity, the type is surrounded by parentheses.
fn parse_typeof_ty(&mut self) -> PResult<'a, TyKind> {
self.expect(&token::OpenDelim(Delimiter::Parenthesis))?;
- let expr = self.parse_anon_const_expr()?;
+ let expr = self.parse_expr_anon_const()?;
self.expect(&token::CloseDelim(Delimiter::Parenthesis))?;
Ok(TyKind::Typeof(expr))
}
@@ -528,7 +511,7 @@ impl<'a> Parser<'a> {
fn parse_ty_bare_fn(
&mut self,
lo: Span,
- mut params: Vec<GenericParam>,
+ mut params: ThinVec<GenericParam>,
param_insertion_point: Option<Span>,
recover_return_sign: RecoverReturnSign,
) -> PResult<'a, TyKind> {
@@ -549,10 +532,10 @@ impl<'a> Parser<'a> {
// If we ever start to allow `const fn()`, then update
// feature gating for `#![feature(const_extern_fn)]` to
// cover it.
- self.error_fn_ptr_bad_qualifier(whole_span, span, "const");
+ self.sess.emit_err(FnPointerCannotBeConst { span: whole_span, qualifier: span });
}
if let ast::Async::Yes { span, .. } = asyncness {
- self.error_fn_ptr_bad_qualifier(whole_span, span, "async");
+ self.sess.emit_err(FnPointerCannotBeAsync { span: whole_span, qualifier: span });
}
let decl_span = span_start.to(self.token.span);
Ok(TyKind::BareFn(P(BareFnTy { ext, unsafety, generic_params: params, decl, decl_span })))
@@ -562,13 +545,13 @@ impl<'a> Parser<'a> {
fn recover_fn_ptr_with_generics(
&mut self,
lo: Span,
- params: &mut Vec<GenericParam>,
+ params: &mut ThinVec<GenericParam>,
param_insertion_point: Option<Span>,
) -> PResult<'a, ()> {
let generics = self.parse_generics()?;
let arity = generics.params.len();
- let mut lifetimes: Vec<_> = generics
+ let mut lifetimes: ThinVec<_> = generics
.params
.into_iter()
.filter(|param| matches!(param.kind, ast::GenericParamKind::Lifetime))
@@ -600,19 +583,6 @@ impl<'a> Parser<'a> {
Ok(())
}
- /// Emit an error for the given bad function pointer qualifier.
- fn error_fn_ptr_bad_qualifier(&self, span: Span, qual_span: Span, qual: &str) {
- self.struct_span_err(span, &format!("an `fn` pointer type cannot be `{}`", qual))
- .span_label(qual_span, format!("`{}` because of this", qual))
- .span_suggestion_short(
- qual_span,
- &format!("remove the `{}` qualifier", qual),
- "",
- Applicability::MaybeIncorrect,
- )
- .emit();
- }
-
/// Parses an `impl B0 + ... + Bn` type.
fn parse_impl_ty(&mut self, impl_dyn_multi: &mut bool) -> PResult<'a, TyKind> {
// Always parse bounds greedily for better error recovery.
@@ -643,7 +613,7 @@ impl<'a> Parser<'a> {
/// Is a `dyn B0 + ... + Bn` type allowed here?
fn is_explicit_dyn_type(&mut self) -> bool {
self.check_keyword(kw::Dyn)
- && (!self.token.uninterpolated_span().rust_2015()
+ && (self.token.uninterpolated_span().rust_2018()
|| self.look_ahead(1, |t| {
(t.can_begin_bound() || t.kind == TokenKind::BinOp(token::Star))
&& !can_continue_type_after_non_fn_ident(t)
@@ -692,23 +662,13 @@ impl<'a> Parser<'a> {
})))
} else if allow_plus == AllowPlus::Yes && self.check_plus() {
// `Trait1 + Trait2 + 'a`
- self.parse_remaining_bounds_path(Vec::new(), path, lo, true)
+ self.parse_remaining_bounds_path(ThinVec::new(), path, lo, true)
} else {
// Just a type path.
Ok(TyKind::Path(None, path))
}
}
- fn error_illegal_c_varadic_ty(&self, lo: Span) {
- struct_span_err!(
- self.sess.span_diagnostic,
- lo.to(self.prev_token.span),
- E0743,
- "C-variadic type `...` may not be nested inside another type",
- )
- .emit();
- }
-
pub(super) fn parse_generic_bounds(
&mut self,
colon_span: Option<Span>,
@@ -739,15 +699,7 @@ impl<'a> Parser<'a> {
{
if self.token.is_keyword(kw::Dyn) {
// Account for `&dyn Trait + dyn Other`.
- self.struct_span_err(self.token.span, "invalid `dyn` keyword")
- .help("`dyn` is only needed at the start of a trait `+`-separated list")
- .span_suggestion(
- self.token.span,
- "remove this keyword",
- "",
- Applicability::MachineApplicable,
- )
- .emit();
+ self.sess.emit_err(InvalidDynKeyword { span: self.token.span });
self.bump();
}
match self.parse_generic_bound()? {
@@ -784,11 +736,7 @@ impl<'a> Parser<'a> {
bounds: &[GenericBound],
negative_bounds: Vec<Span>,
) {
- let negative_bounds_len = negative_bounds.len();
- let last_span = *negative_bounds.last().expect("no negative bounds, but still error?");
- let mut err = self.struct_span_err(negative_bounds, "negative bounds are not supported");
- err.span_label(last_span, "negative bounds are not supported");
- if let Some(bound_list) = colon_span {
+ let sub = if let Some(bound_list) = colon_span {
let bound_list = bound_list.to(self.prev_token.span);
let mut new_bound_list = String::new();
if !bounds.is_empty() {
@@ -799,14 +747,18 @@ impl<'a> Parser<'a> {
}
new_bound_list = new_bound_list.replacen(" +", ":", 1);
}
- err.tool_only_span_suggestion(
+
+ Some(NegativeBoundsNotSupportedSugg {
bound_list,
- &format!("remove the bound{}", pluralize!(negative_bounds_len)),
- new_bound_list,
- Applicability::MachineApplicable,
- );
- }
- err.emit();
+ num_bounds: negative_bounds.len(),
+ fixed: new_bound_list,
+ })
+ } else {
+ None
+ };
+
+ let last_span = *negative_bounds.last().expect("no negative bounds, but still error?");
+ self.sess.emit_err(NegativeBoundsNotSupported { negative_bounds, last_span, sub });
}
/// Parses a bound according to the grammar:
@@ -918,7 +870,7 @@ impl<'a> Parser<'a> {
None
};
- let maybe = if self.eat(&token::Question) { Some(self.prev_token.span) } else { None };
+ let maybe = self.eat(&token::Question).then_some(self.prev_token.span);
Ok(BoundModifiers { maybe, maybe_const })
}
@@ -990,7 +942,7 @@ impl<'a> Parser<'a> {
self.parse_remaining_bounds(bounds, true)?;
self.expect(&token::CloseDelim(Delimiter::Parenthesis))?;
let sp = vec![lo, self.prev_token.span];
- let sugg: Vec<_> = sp.iter().map(|sp| (*sp, String::new())).collect();
+ let sugg = vec![(lo, String::from(" ")), (self.prev_token.span, String::new())];
self.struct_span_err(sp, "incorrect braces around trait bounds")
.multipart_suggestion(
"remove the parentheses",
@@ -1041,7 +993,7 @@ impl<'a> Parser<'a> {
}
/// Optionally parses `for<$generic_params>`.
- pub(super) fn parse_late_bound_lifetime_defs(&mut self) -> PResult<'a, Vec<GenericParam>> {
+ pub(super) fn parse_late_bound_lifetime_defs(&mut self) -> PResult<'a, ThinVec<GenericParam>> {
if self.eat_keyword(kw::For) {
self.expect_lt()?;
let params = self.parse_generic_params()?;
@@ -1050,7 +1002,7 @@ impl<'a> Parser<'a> {
// parameters, and the lifetime parameters must not have bounds.
Ok(params)
} else {
- Ok(Vec::new())
+ Ok(ThinVec::new())
}
}
@@ -1060,7 +1012,7 @@ impl<'a> Parser<'a> {
fn recover_fn_trait_with_lifetime_params(
&mut self,
fn_path: &mut ast::Path,
- lifetime_defs: &mut Vec<GenericParam>,
+ lifetime_defs: &mut ThinVec<GenericParam>,
) -> PResult<'a, ()> {
let fn_path_segment = fn_path.segments.last_mut().unwrap();
let generic_args = if let Some(p_args) = &fn_path_segment.args {
@@ -1094,7 +1046,7 @@ impl<'a> Parser<'a> {
// Parse `(T, U) -> R`.
let inputs_lo = self.token.span;
- let inputs: Vec<_> =
+ let inputs: ThinVec<_> =
self.parse_fn_params(|_| false)?.into_iter().map(|input| input.ty).collect();
let inputs_span = inputs_lo.to(self.prev_token.span);
let output = self.parse_ret_ty(AllowPlus::No, RecoverQPath::No, RecoverReturnSign::No)?;
@@ -1120,7 +1072,7 @@ impl<'a> Parser<'a> {
kind: ast::GenericParamKind::Lifetime,
colon_span: None,
})
- .collect::<Vec<GenericParam>>();
+ .collect::<ThinVec<GenericParam>>();
lifetime_defs.append(&mut generic_params);
let generic_args_span = generic_args.span();
diff --git a/compiler/rustc_parse_format/src/lib.rs b/compiler/rustc_parse_format/src/lib.rs
index 7b016cada..8a3cedfee 100644
--- a/compiler/rustc_parse_format/src/lib.rs
+++ b/compiler/rustc_parse_format/src/lib.rs
@@ -16,7 +16,6 @@
pub use Alignment::*;
pub use Count::*;
-pub use Flag::*;
pub use Piece::*;
pub use Position::*;
@@ -111,8 +110,14 @@ pub struct FormatSpec<'a> {
pub fill: Option<char>,
/// Optionally specified alignment.
pub align: Alignment,
- /// Packed version of various flags provided.
- pub flags: u32,
+ /// The `+` or `-` flag.
+ pub sign: Option<Sign>,
+ /// The `#` flag.
+ pub alternate: bool,
+ /// The `0` flag.
+ pub zero_pad: bool,
+ /// The `x` or `X` flag. (Only for `Debug`.)
+ pub debug_hex: Option<DebugHex>,
/// The integer precision to use.
pub precision: Count<'a>,
/// The span of the precision formatting flag (for diagnostics).
@@ -162,24 +167,22 @@ pub enum Alignment {
AlignUnknown,
}
-/// Various flags which can be applied to format strings. The meaning of these
-/// flags is defined by the formatters themselves.
+/// Enum for the sign flags.
#[derive(Copy, Clone, Debug, PartialEq)]
-pub enum Flag {
- /// A `+` will be used to denote positive numbers.
- FlagSignPlus,
- /// A `-` will be used to denote negative numbers. This is the default.
- FlagSignMinus,
- /// An alternate form will be used for the value. In the case of numbers,
- /// this means that the number will be prefixed with the supplied string.
- FlagAlternate,
- /// For numbers, this means that the number will be padded with zeroes,
- /// and the sign (`+` or `-`) will precede them.
- FlagSignAwareZeroPad,
- /// For Debug / `?`, format integers in lower-case hexadecimal.
- FlagDebugLowerHex,
- /// For Debug / `?`, format integers in upper-case hexadecimal.
- FlagDebugUpperHex,
+pub enum Sign {
+ /// The `+` flag.
+ Plus,
+ /// The `-` flag.
+ Minus,
+}
+
+/// Enum for the debug hex flags.
+#[derive(Copy, Clone, Debug, PartialEq)]
+pub enum DebugHex {
+ /// The `x` flag in `{:x?}`.
+ Lower,
+ /// The `X` flag in `{:X?}`.
+ Upper,
}
/// A count is used for the precision and width parameters of an integer, and
@@ -270,7 +273,13 @@ impl<'a> Iterator for Parser<'a> {
);
}
} else {
- self.suggest_positional_arg_instead_of_captured_arg(arg);
+ if let Some(&(_, maybe)) = self.cur.peek() {
+ if maybe == '?' {
+ self.suggest_format();
+ } else {
+ self.suggest_positional_arg_instead_of_captured_arg(arg);
+ }
+ }
}
Some(NextArgument(Box::new(arg)))
}
@@ -597,7 +606,10 @@ impl<'a> Parser<'a> {
let mut spec = FormatSpec {
fill: None,
align: AlignUnknown,
- flags: 0,
+ sign: None,
+ alternate: false,
+ zero_pad: false,
+ debug_hex: None,
precision: CountImplied,
precision_span: None,
width: CountImplied,
@@ -626,13 +638,13 @@ impl<'a> Parser<'a> {
}
// Sign flags
if self.consume('+') {
- spec.flags |= 1 << (FlagSignPlus as u32);
+ spec.sign = Some(Sign::Plus);
} else if self.consume('-') {
- spec.flags |= 1 << (FlagSignMinus as u32);
+ spec.sign = Some(Sign::Minus);
}
// Alternate marker
if self.consume('#') {
- spec.flags |= 1 << (FlagAlternate as u32);
+ spec.alternate = true;
}
// Width and precision
let mut havewidth = false;
@@ -647,7 +659,7 @@ impl<'a> Parser<'a> {
spec.width_span = Some(self.span(end - 1, end + 1));
havewidth = true;
} else {
- spec.flags |= 1 << (FlagSignAwareZeroPad as u32);
+ spec.zero_pad = true;
}
}
@@ -678,14 +690,14 @@ impl<'a> Parser<'a> {
// Optional radix followed by the actual format specifier
if self.consume('x') {
if self.consume('?') {
- spec.flags |= 1 << (FlagDebugLowerHex as u32);
+ spec.debug_hex = Some(DebugHex::Lower);
spec.ty = "?";
} else {
spec.ty = "x";
}
} else if self.consume('X') {
if self.consume('?') {
- spec.flags |= 1 << (FlagDebugUpperHex as u32);
+ spec.debug_hex = Some(DebugHex::Upper);
spec.ty = "?";
} else {
spec.ty = "X";
@@ -708,7 +720,10 @@ impl<'a> Parser<'a> {
let mut spec = FormatSpec {
fill: None,
align: AlignUnknown,
- flags: 0,
+ sign: None,
+ alternate: false,
+ zero_pad: false,
+ debug_hex: None,
precision: CountImplied,
precision_span: None,
width: CountImplied,
@@ -820,7 +835,26 @@ impl<'a> Parser<'a> {
);
}
- if found { Some(cur) } else { None }
+ found.then_some(cur)
+ }
+
+ fn suggest_format(&mut self) {
+ if let (Some(pos), Some(_)) = (self.consume_pos('?'), self.consume_pos(':')) {
+ let word = self.word();
+ let _end = self.current_pos();
+ let pos = self.to_span_index(pos);
+ self.errors.insert(
+ 0,
+ ParseError {
+ description: "expected format parameter to occur after `:`".to_owned(),
+ note: Some(format!("`?` comes after `:`, try `{}:{}` instead", word, "?")),
+ label: "expected `?` to occur after `:`".to_owned(),
+ span: pos.to(pos),
+ secondary_label: None,
+ should_be_replaced_with_positional_argument: false,
+ },
+ );
+ }
}
fn suggest_positional_arg_instead_of_captured_arg(&mut self, arg: Argument<'a>) {
diff --git a/compiler/rustc_parse_format/src/tests.rs b/compiler/rustc_parse_format/src/tests.rs
index 2992ba845..45314e2fb 100644
--- a/compiler/rustc_parse_format/src/tests.rs
+++ b/compiler/rustc_parse_format/src/tests.rs
@@ -10,7 +10,10 @@ fn fmtdflt() -> FormatSpec<'static> {
return FormatSpec {
fill: None,
align: AlignUnknown,
- flags: 0,
+ sign: None,
+ alternate: false,
+ zero_pad: false,
+ debug_hex: None,
precision: CountImplied,
width: CountImplied,
precision_span: None,
@@ -126,7 +129,10 @@ fn format_type() {
format: FormatSpec {
fill: None,
align: AlignUnknown,
- flags: 0,
+ sign: None,
+ alternate: false,
+ zero_pad: false,
+ debug_hex: None,
precision: CountImplied,
width: CountImplied,
precision_span: None,
@@ -147,7 +153,10 @@ fn format_align_fill() {
format: FormatSpec {
fill: None,
align: AlignRight,
- flags: 0,
+ sign: None,
+ alternate: false,
+ zero_pad: false,
+ debug_hex: None,
precision: CountImplied,
width: CountImplied,
precision_span: None,
@@ -165,7 +174,10 @@ fn format_align_fill() {
format: FormatSpec {
fill: Some('0'),
align: AlignLeft,
- flags: 0,
+ sign: None,
+ alternate: false,
+ zero_pad: false,
+ debug_hex: None,
precision: CountImplied,
width: CountImplied,
precision_span: None,
@@ -183,7 +195,10 @@ fn format_align_fill() {
format: FormatSpec {
fill: Some('*'),
align: AlignLeft,
- flags: 0,
+ sign: None,
+ alternate: false,
+ zero_pad: false,
+ debug_hex: None,
precision: CountImplied,
width: CountImplied,
precision_span: None,
@@ -204,7 +219,10 @@ fn format_counts() {
format: FormatSpec {
fill: None,
align: AlignUnknown,
- flags: 0,
+ sign: None,
+ alternate: false,
+ zero_pad: false,
+ debug_hex: None,
precision: CountImplied,
precision_span: None,
width: CountIs(10),
@@ -222,7 +240,10 @@ fn format_counts() {
format: FormatSpec {
fill: None,
align: AlignUnknown,
- flags: 0,
+ sign: None,
+ alternate: false,
+ zero_pad: false,
+ debug_hex: None,
precision: CountIs(10),
precision_span: Some(InnerSpan { start: 6, end: 9 }),
width: CountIsParam(10),
@@ -240,7 +261,10 @@ fn format_counts() {
format: FormatSpec {
fill: None,
align: AlignUnknown,
- flags: 0,
+ sign: None,
+ alternate: false,
+ zero_pad: false,
+ debug_hex: None,
precision: CountIs(10),
precision_span: Some(InnerSpan { start: 6, end: 9 }),
width: CountIsParam(0),
@@ -258,7 +282,10 @@ fn format_counts() {
format: FormatSpec {
fill: None,
align: AlignUnknown,
- flags: 0,
+ sign: None,
+ alternate: false,
+ zero_pad: false,
+ debug_hex: None,
precision: CountIsStar(0),
precision_span: Some(InnerSpan { start: 3, end: 5 }),
width: CountImplied,
@@ -276,7 +303,10 @@ fn format_counts() {
format: FormatSpec {
fill: None,
align: AlignUnknown,
- flags: 0,
+ sign: None,
+ alternate: false,
+ zero_pad: false,
+ debug_hex: None,
precision: CountIsParam(10),
width: CountImplied,
precision_span: Some(InnerSpan::new(3, 7)),
@@ -294,7 +324,10 @@ fn format_counts() {
format: FormatSpec {
fill: None,
align: AlignUnknown,
- flags: 0,
+ sign: None,
+ alternate: false,
+ zero_pad: false,
+ debug_hex: None,
precision: CountIsName("b", InnerSpan { start: 6, end: 7 }),
precision_span: Some(InnerSpan { start: 5, end: 8 }),
width: CountIsName("a", InnerSpan { start: 3, end: 4 }),
@@ -312,7 +345,10 @@ fn format_counts() {
format: FormatSpec {
fill: None,
align: AlignUnknown,
- flags: 0,
+ sign: None,
+ alternate: false,
+ zero_pad: false,
+ debug_hex: None,
precision: CountIs(4),
precision_span: Some(InnerSpan { start: 3, end: 5 }),
width: CountImplied,
@@ -333,7 +369,10 @@ fn format_flags() {
format: FormatSpec {
fill: None,
align: AlignUnknown,
- flags: (1 << FlagSignMinus as u32),
+ sign: Some(Sign::Minus),
+ alternate: false,
+ zero_pad: false,
+ debug_hex: None,
precision: CountImplied,
width: CountImplied,
precision_span: None,
@@ -351,7 +390,10 @@ fn format_flags() {
format: FormatSpec {
fill: None,
align: AlignUnknown,
- flags: (1 << FlagSignPlus as u32) | (1 << FlagAlternate as u32),
+ sign: Some(Sign::Plus),
+ alternate: true,
+ zero_pad: false,
+ debug_hex: None,
precision: CountImplied,
width: CountImplied,
precision_span: None,
@@ -374,7 +416,10 @@ fn format_mixture() {
format: FormatSpec {
fill: None,
align: AlignUnknown,
- flags: 0,
+ sign: None,
+ alternate: false,
+ zero_pad: false,
+ debug_hex: None,
precision: CountImplied,
width: CountImplied,
precision_span: None,
diff --git a/compiler/rustc_error_messages/locales/en-US/passes.ftl b/compiler/rustc_passes/locales/en-US.ftl
index 91857dd22..3fa78efc2 100644
--- a/compiler/rustc_error_messages/locales/en-US/passes.ftl
+++ b/compiler/rustc_passes/locales/en-US.ftl
@@ -182,6 +182,18 @@ passes_has_incoherent_inherent_impl =
`rustc_has_incoherent_inherent_impls` attribute should be applied to types or traits.
.label = only adts, extern types and traits are supported
+passes_both_ffi_const_and_pure =
+ `#[ffi_const]` function cannot be `#[ffi_pure]`
+
+passes_ffi_pure_invalid_target =
+ `#[ffi_pure]` may only be used on foreign functions
+
+passes_ffi_const_invalid_target =
+ `#[ffi_const]` may only be used on foreign functions
+
+passes_ffi_returns_twice_invalid_target =
+ `#[ffi_returns_twice]` may only be used on foreign functions
+
passes_must_use_async =
`must_use` attribute on `async` functions applies to the anonymous `Future` returned by the function, not the value within
.label = this attribute does nothing, the `Future`s returned by async functions are already `must_use`
@@ -390,15 +402,12 @@ passes_invalid_attr_at_crate_level =
`{$name}` attribute cannot be used at crate level
.suggestion = perhaps you meant to use an outer attribute
-passes_duplicate_diagnostic_item =
- duplicate diagnostic item found: `{$name}`.
-
passes_duplicate_diagnostic_item_in_crate =
duplicate diagnostic item in crate `{$crate_name}`: `{$name}`.
+ .note = the diagnostic item is first defined in crate `{$orig_crate_name}`.
passes_diagnostic_item_first_defined =
the diagnostic item is first defined here
- .note = the diagnostic item is first defined in crate `{$orig_crate_name}`.
passes_abi =
abi: {$abi}
@@ -710,3 +719,30 @@ passes_ignored_derived_impls =
[one] trait {$trait_list}, but this is
*[other] traits {$trait_list}, but these are
} intentionally ignored during dead code analysis
+
+passes_proc_macro_typeerror = mismatched {$kind} signature
+ .label = found {$found}, expected type `proc_macro::TokenStream`
+ .note = {$kind}s must have a signature of `{$expected_signature}`
+
+passes_proc_macro_diff_arg_count = mismatched {$kind} signature
+ .label = found unexpected {$count ->
+ [one] argument
+ *[other] arguments
+ }
+ .note = {$kind}s must have a signature of `{$expected_signature}`
+
+passes_proc_macro_missing_args = mismatched {$kind} signature
+ .label = {$kind} must have {$expected_input_count ->
+ [one] one argument
+ *[other] two arguments
+ } of type `proc_macro::TokenStream`
+
+passes_proc_macro_invalid_abi = proc macro functions may not be `extern "{$abi}"`
+
+passes_proc_macro_unsafe = proc macro functions may not be `unsafe`
+
+passes_skipping_const_checks = skipping const checks
+
+passes_invalid_macro_export_arguments = `{$name}` isn't a valid `#[macro_export]` argument
+
+passes_invalid_macro_export_arguments_too_many_items = `#[macro_export]` can only take 1 or 0 arguments
diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs
index f9f9799d3..5ef3e13ef 100644
--- a/compiler/rustc_passes/src/check_attr.rs
+++ b/compiler/rustc_passes/src/check_attr.rs
@@ -4,13 +4,10 @@
//! conflicts between multiple such attributes attached to the same
//! item.
-use crate::errors::{
- self, AttrApplication, DebugVisualizerUnreadable, InvalidAttrAtCrateLevel, ObjectLifetimeErr,
- OnlyHasEffectOn, TransparentIncompatible, UnrecognizedReprHint,
-};
+use crate::{errors, fluent_generated as fluent};
use rustc_ast::{ast, AttrStyle, Attribute, LitKind, MetaItemKind, MetaItemLit, NestedMetaItem};
use rustc_data_structures::fx::FxHashMap;
-use rustc_errors::{fluent, Applicability, MultiSpan};
+use rustc_errors::{Applicability, IntoDiagnosticArg, MultiSpan};
use rustc_expand::base::resolve_path;
use rustc_feature::{AttributeDuplicates, AttributeType, BuiltinAttribute, BUILTIN_ATTRIBUTE_MAP};
use rustc_hir as hir;
@@ -19,18 +16,21 @@ use rustc_hir::intravisit::{self, Visitor};
use rustc_hir::{
self, FnSig, ForeignItem, HirId, Item, ItemKind, TraitItem, CRATE_HIR_ID, CRATE_OWNER_ID,
};
-use rustc_hir::{MethodKind, Target};
+use rustc_hir::{MethodKind, Target, Unsafety};
use rustc_middle::hir::nested_filter;
-use rustc_middle::middle::resolve_lifetime::ObjectLifetimeDefault;
+use rustc_middle::middle::resolve_bound_vars::ObjectLifetimeDefault;
+use rustc_middle::ty::fast_reject::{DeepRejectCtxt, TreatParams};
use rustc_middle::ty::query::Providers;
-use rustc_middle::ty::TyCtxt;
+use rustc_middle::ty::{ParamEnv, TyCtxt};
use rustc_session::lint::builtin::{
- CONFLICTING_REPR_HINTS, INVALID_DOC_ATTRIBUTES, UNUSED_ATTRIBUTES,
+ CONFLICTING_REPR_HINTS, INVALID_DOC_ATTRIBUTES, INVALID_MACRO_EXPORT_ARGUMENTS,
+ UNUSED_ATTRIBUTES,
};
use rustc_session::parse::feature_err;
use rustc_span::symbol::{kw, sym, Symbol};
use rustc_span::{Span, DUMMY_SP};
use rustc_target::spec::abi::Abi;
+use std::cell::Cell;
use std::collections::hash_map::Entry;
pub(crate) fn target_from_impl_item<'tcx>(
@@ -62,8 +62,29 @@ enum ItemLike<'tcx> {
ForeignItem,
}
+#[derive(Copy, Clone)]
+pub(crate) enum ProcMacroKind {
+ FunctionLike,
+ Derive,
+ Attribute,
+}
+
+impl IntoDiagnosticArg for ProcMacroKind {
+ fn into_diagnostic_arg(self) -> rustc_errors::DiagnosticArgValue<'static> {
+ match self {
+ ProcMacroKind::Attribute => "attribute proc macro",
+ ProcMacroKind::Derive => "derive proc macro",
+ ProcMacroKind::FunctionLike => "function-like proc macro",
+ }
+ .into_diagnostic_arg()
+ }
+}
+
struct CheckAttrVisitor<'tcx> {
tcx: TyCtxt<'tcx>,
+
+ // Whether or not this visitor should abort after finding errors
+ abort: Cell<bool>,
}
impl CheckAttrVisitor<'_> {
@@ -136,6 +157,7 @@ impl CheckAttrVisitor<'_> {
| sym::rustc_dirty
| sym::rustc_if_this_changed
| sym::rustc_then_this_would_need => self.check_rustc_dirty_clean(&attr),
+ sym::rustc_coinductive => self.check_rustc_coinductive(&attr, span, target),
sym::cmse_nonsecure_entry => {
self.check_cmse_nonsecure_entry(hir_id, attr, span, target)
}
@@ -150,6 +172,9 @@ impl CheckAttrVisitor<'_> {
sym::rustc_has_incoherent_inherent_impls => {
self.check_has_incoherent_inherent_impls(&attr, span, target)
}
+ sym::ffi_pure => self.check_ffi_pure(attr.span, attrs, target),
+ sym::ffi_const => self.check_ffi_const(attr.span, target),
+ sym::ffi_returns_twice => self.check_ffi_returns_twice(attr.span, target),
sym::rustc_const_unstable
| sym::rustc_const_stable
| sym::unstable
@@ -173,7 +198,7 @@ impl CheckAttrVisitor<'_> {
sym::path => self.check_generic_attr(hir_id, attr, target, Target::Mod),
sym::plugin_registrar => self.check_plugin_registrar(hir_id, attr, target),
sym::macro_export => self.check_macro_export(hir_id, attr, target),
- sym::ignore | sym::should_panic | sym::proc_macro_derive => {
+ sym::ignore | sym::should_panic => {
self.check_generic_attr(hir_id, attr, target, Target::Fn)
}
sym::automatically_derived => {
@@ -183,6 +208,16 @@ impl CheckAttrVisitor<'_> {
self.check_generic_attr(hir_id, attr, target, Target::Mod)
}
sym::rustc_object_lifetime_default => self.check_object_lifetime_default(hir_id),
+ sym::proc_macro => {
+ self.check_proc_macro(hir_id, target, ProcMacroKind::FunctionLike)
+ }
+ sym::proc_macro_attribute => {
+ self.check_proc_macro(hir_id, target, ProcMacroKind::Attribute);
+ }
+ sym::proc_macro_derive => {
+ self.check_generic_attr(hir_id, attr, target, Target::Fn);
+ self.check_proc_macro(hir_id, target, ProcMacroKind::Derive)
+ }
_ => {}
}
@@ -362,7 +397,7 @@ impl CheckAttrVisitor<'_> {
UNUSED_ATTRIBUTES,
hir_id,
attr.span,
- OnlyHasEffectOn {
+ errors::OnlyHasEffectOn {
attr_name: attr.name_or_empty(),
target_name: allowed_target.name().replace(' ', "_"),
},
@@ -419,7 +454,9 @@ impl CheckAttrVisitor<'_> {
/// Debugging aid for `object_lifetime_default` query.
fn check_object_lifetime_default(&self, hir_id: HirId) {
let tcx = self.tcx;
- if let Some(generics) = tcx.hir().get_generics(tcx.hir().local_def_id(hir_id)) {
+ if let Some(owner_id) = hir_id.as_owner()
+ && let Some(generics) = tcx.hir().get_generics(owner_id.def_id)
+ {
for p in generics.params {
let hir::GenericParamKind::Type { .. } = p.kind else { continue };
let default = tcx.object_lifetime_default(p.def_id);
@@ -429,7 +466,7 @@ impl CheckAttrVisitor<'_> {
ObjectLifetimeDefault::Param(def_id) => tcx.item_name(def_id).to_string(),
ObjectLifetimeDefault::Ambiguous => "Ambiguous".to_owned(),
};
- tcx.sess.emit_err(ObjectLifetimeErr { span: p.span, repr });
+ tcx.sess.emit_err(errors::ObjectLifetimeErr { span: p.span, repr });
}
}
}
@@ -828,33 +865,39 @@ impl CheckAttrVisitor<'_> {
target: Target,
specified_inline: &mut Option<(bool, Span)>,
) -> bool {
- if target == Target::Use || target == Target::ExternCrate {
- let do_inline = meta.name_or_empty() == sym::inline;
- if let Some((prev_inline, prev_span)) = *specified_inline {
- if do_inline != prev_inline {
- let mut spans = MultiSpan::from_spans(vec![prev_span, meta.span()]);
- spans.push_span_label(prev_span, fluent::passes_doc_inline_conflict_first);
- spans.push_span_label(meta.span(), fluent::passes_doc_inline_conflict_second);
- self.tcx.sess.emit_err(errors::DocKeywordConflict { spans });
- return false;
+ match target {
+ Target::Use | Target::ExternCrate => {
+ let do_inline = meta.name_or_empty() == sym::inline;
+ if let Some((prev_inline, prev_span)) = *specified_inline {
+ if do_inline != prev_inline {
+ let mut spans = MultiSpan::from_spans(vec![prev_span, meta.span()]);
+ spans.push_span_label(prev_span, fluent::passes_doc_inline_conflict_first);
+ spans.push_span_label(
+ meta.span(),
+ fluent::passes_doc_inline_conflict_second,
+ );
+ self.tcx.sess.emit_err(errors::DocKeywordConflict { spans });
+ return false;
+ }
+ true
+ } else {
+ *specified_inline = Some((do_inline, meta.span()));
+ true
}
- true
- } else {
- *specified_inline = Some((do_inline, meta.span()));
- true
}
- } else {
- self.tcx.emit_spanned_lint(
- INVALID_DOC_ATTRIBUTES,
- hir_id,
- meta.span(),
- errors::DocInlineOnlyUse {
- attr_span: meta.span(),
- item_span: (attr.style == AttrStyle::Outer)
- .then(|| self.tcx.hir().span(hir_id)),
- },
- );
- false
+ _ => {
+ self.tcx.emit_spanned_lint(
+ INVALID_DOC_ATTRIBUTES,
+ hir_id,
+ meta.span(),
+ errors::DocInlineOnlyUse {
+ attr_span: meta.span(),
+ item_span: (attr.style == AttrStyle::Outer)
+ .then(|| self.tcx.hir().span(hir_id)),
+ },
+ );
+ false
+ }
}
}
@@ -893,15 +936,15 @@ impl CheckAttrVisitor<'_> {
src.insert(1, '!');
err.span_suggestion_verbose(
attr.span,
- fluent::suggestion,
+ fluent::passes_suggestion,
src,
Applicability::MaybeIncorrect,
);
} else {
- err.span_help(attr.span, fluent::help);
+ err.span_help(attr.span, fluent::passes_help);
}
}
- err.note(fluent::note);
+ err.note(fluent::passes_note);
err
},
);
@@ -1101,7 +1144,7 @@ impl CheckAttrVisitor<'_> {
errors::DocTestUnknownInclude {
path,
value: value.to_string(),
- inner: if attr.style == AttrStyle::Inner { "!" } else { "" },
+ inner: match attr.style { AttrStyle::Inner=> "!" , AttrStyle::Outer => "" },
sugg: (attr.meta().unwrap().span, applicability),
}
);
@@ -1171,6 +1214,38 @@ impl CheckAttrVisitor<'_> {
}
}
+ fn check_ffi_pure(&self, attr_span: Span, attrs: &[Attribute], target: Target) -> bool {
+ if target != Target::ForeignFn {
+ self.tcx.sess.emit_err(errors::FfiPureInvalidTarget { attr_span });
+ return false;
+ }
+ if attrs.iter().any(|a| a.has_name(sym::ffi_const)) {
+ // `#[ffi_const]` functions cannot be `#[ffi_pure]`
+ self.tcx.sess.emit_err(errors::BothFfiConstAndPure { attr_span });
+ false
+ } else {
+ true
+ }
+ }
+
+ fn check_ffi_const(&self, attr_span: Span, target: Target) -> bool {
+ if target == Target::ForeignFn {
+ true
+ } else {
+ self.tcx.sess.emit_err(errors::FfiConstInvalidTarget { attr_span });
+ false
+ }
+ }
+
+ fn check_ffi_returns_twice(&self, attr_span: Span, target: Target) -> bool {
+ if target == Target::ForeignFn {
+ true
+ } else {
+ self.tcx.sess.emit_err(errors::FfiReturnsTwiceInvalidTarget { attr_span });
+ false
+ }
+ }
+
/// Warns against some misuses of `#[must_use]`
fn check_must_use(&self, hir_id: HirId, attr: &Attribute, target: Target) -> bool {
if !matches!(
@@ -1535,6 +1610,20 @@ impl CheckAttrVisitor<'_> {
}
}
+ /// Checks if the `#[rustc_coinductive]` attribute is applied to a trait.
+ fn check_rustc_coinductive(&self, attr: &Attribute, span: Span, target: Target) -> bool {
+ match target {
+ Target::Trait => true,
+ _ => {
+ self.tcx.sess.emit_err(errors::AttrShouldBeAppliedToTrait {
+ attr_span: attr.span,
+ defn_span: span,
+ });
+ false
+ }
+ }
+ }
+
/// Checks if `#[link_section]` is applied to a function or static.
fn check_link_section(&self, hir_id: HirId, attr: &Attribute, span: Span, target: Target) {
match target {
@@ -1638,7 +1727,7 @@ impl CheckAttrVisitor<'_> {
match target {
Target::Struct | Target::Union | Target::Enum => continue,
_ => {
- self.tcx.sess.emit_err(AttrApplication::StructEnumUnion {
+ self.tcx.sess.emit_err(errors::AttrApplication::StructEnumUnion {
hint_span: hint.span(),
span,
});
@@ -1659,16 +1748,18 @@ impl CheckAttrVisitor<'_> {
match target {
Target::Struct | Target::Union | Target::Enum | Target::Fn => continue,
_ => {
- self.tcx.sess.emit_err(AttrApplication::StructEnumFunctionUnion {
- hint_span: hint.span(),
- span,
- });
+ self.tcx.sess.emit_err(
+ errors::AttrApplication::StructEnumFunctionUnion {
+ hint_span: hint.span(),
+ span,
+ },
+ );
}
}
}
sym::packed => {
if target != Target::Struct && target != Target::Union {
- self.tcx.sess.emit_err(AttrApplication::StructUnion {
+ self.tcx.sess.emit_err(errors::AttrApplication::StructUnion {
hint_span: hint.span(),
span,
});
@@ -1679,9 +1770,10 @@ impl CheckAttrVisitor<'_> {
sym::simd => {
is_simd = true;
if target != Target::Struct {
- self.tcx
- .sess
- .emit_err(AttrApplication::Struct { hint_span: hint.span(), span });
+ self.tcx.sess.emit_err(errors::AttrApplication::Struct {
+ hint_span: hint.span(),
+ span,
+ });
} else {
continue;
}
@@ -1691,7 +1783,7 @@ impl CheckAttrVisitor<'_> {
match target {
Target::Struct | Target::Union | Target::Enum => continue,
_ => {
- self.tcx.sess.emit_err(AttrApplication::StructEnumUnion {
+ self.tcx.sess.emit_err(errors::AttrApplication::StructEnumUnion {
hint_span: hint.span(),
span,
});
@@ -1712,15 +1804,16 @@ impl CheckAttrVisitor<'_> {
| sym::usize => {
int_reprs += 1;
if target != Target::Enum {
- self.tcx
- .sess
- .emit_err(AttrApplication::Enum { hint_span: hint.span(), span });
+ self.tcx.sess.emit_err(errors::AttrApplication::Enum {
+ hint_span: hint.span(),
+ span,
+ });
} else {
continue;
}
}
_ => {
- self.tcx.sess.emit_err(UnrecognizedReprHint { span: hint.span() });
+ self.tcx.sess.emit_err(errors::UnrecognizedReprHint { span: hint.span() });
continue;
}
};
@@ -1733,9 +1826,10 @@ impl CheckAttrVisitor<'_> {
// Error on repr(transparent, <anything else>).
if is_transparent && hints.len() > 1 {
let hint_spans: Vec<_> = hint_spans.clone().collect();
- self.tcx
- .sess
- .emit_err(TransparentIncompatible { hint_spans, target: target.to_string() });
+ self.tcx.sess.emit_err(errors::TransparentIncompatible {
+ hint_spans,
+ target: target.to_string(),
+ });
}
// Warn on repr(u8, u16), repr(C, simd), and c-like-enum-repr(C, u8)
if (int_reprs > 1)
@@ -1888,7 +1982,7 @@ impl CheckAttrVisitor<'_> {
match std::fs::File::open(&file) {
Ok(_) => true,
Err(error) => {
- self.tcx.sess.emit_err(DebugVisualizerUnreadable {
+ self.tcx.sess.emit_err(errors::DebugVisualizerUnreadable {
span: meta_item.span,
file: &file,
error,
@@ -1909,7 +2003,7 @@ impl CheckAttrVisitor<'_> {
) -> bool {
match target {
Target::Fn | Target::Method(_)
- if self.tcx.is_const_fn_raw(self.tcx.hir().local_def_id(hir_id).to_def_id()) =>
+ if self.tcx.is_const_fn_raw(hir_id.expect_owner().to_def_id()) =>
{
true
}
@@ -2009,7 +2103,33 @@ impl CheckAttrVisitor<'_> {
fn check_macro_export(&self, hir_id: HirId, attr: &Attribute, target: Target) {
if target != Target::MacroDef {
- self.tcx.emit_spanned_lint(UNUSED_ATTRIBUTES, hir_id, attr.span, errors::MacroExport);
+ self.tcx.emit_spanned_lint(
+ UNUSED_ATTRIBUTES,
+ hir_id,
+ attr.span,
+ errors::MacroExport::Normal,
+ );
+ } else if let Some(meta_item_list) = attr.meta_item_list() &&
+ !meta_item_list.is_empty() {
+ if meta_item_list.len() > 1 {
+ self.tcx.emit_spanned_lint(
+ INVALID_MACRO_EXPORT_ARGUMENTS,
+ hir_id,
+ attr.span,
+ errors::MacroExport::TooManyItems,
+ );
+ } else {
+ if meta_item_list[0].name_or_empty() != sym::local_inner_macros {
+ self.tcx.emit_spanned_lint(
+ INVALID_MACRO_EXPORT_ARGUMENTS,
+ hir_id,
+ meta_item_list[0].span(),
+ errors::MacroExport::UnknownItem {
+ name: meta_item_list[0].name_or_empty(),
+ },
+ );
+ }
+ }
}
}
@@ -2063,6 +2183,107 @@ impl CheckAttrVisitor<'_> {
errors::Unused { attr_span: attr.span, note },
);
}
+
+ /// A best effort attempt to create an error for a mismatching proc macro signature.
+ ///
+ /// If this best effort goes wrong, it will just emit a worse error later (see #102923)
+ fn check_proc_macro(&self, hir_id: HirId, target: Target, kind: ProcMacroKind) {
+ let expected_input_count = match kind {
+ ProcMacroKind::Attribute => 2,
+ ProcMacroKind::Derive | ProcMacroKind::FunctionLike => 1,
+ };
+
+ let expected_signature = match kind {
+ ProcMacroKind::Attribute => "fn(TokenStream, TokenStream) -> TokenStream",
+ ProcMacroKind::Derive | ProcMacroKind::FunctionLike => "fn(TokenStream) -> TokenStream",
+ };
+
+ let tcx = self.tcx;
+ if target == Target::Fn {
+ let Some(tokenstream) = tcx.get_diagnostic_item(sym::TokenStream) else {return};
+ let tokenstream = tcx.type_of(tokenstream).subst_identity();
+
+ let id = hir_id.expect_owner();
+ let hir_sig = tcx.hir().fn_sig_by_hir_id(hir_id).unwrap();
+
+ let sig =
+ tcx.liberate_late_bound_regions(id.to_def_id(), tcx.fn_sig(id).subst_identity());
+ let sig = tcx.normalize_erasing_regions(ParamEnv::empty(), sig);
+
+ // We don't currently require that the function signature is equal to
+ // `fn(TokenStream) -> TokenStream`, but instead monomorphizes to
+ // `fn(TokenStream) -> TokenStream` after some substitution of generic arguments.
+ //
+ // Properly checking this means pulling in additional `rustc` crates, so we don't.
+ let drcx = DeepRejectCtxt { treat_obligation_params: TreatParams::AsInfer };
+
+ if sig.abi != Abi::Rust {
+ tcx.sess.emit_err(errors::ProcMacroInvalidAbi {
+ span: hir_sig.span,
+ abi: sig.abi.name(),
+ });
+ self.abort.set(true);
+ }
+
+ if sig.unsafety == Unsafety::Unsafe {
+ tcx.sess.emit_err(errors::ProcMacroUnsafe { span: hir_sig.span });
+ self.abort.set(true);
+ }
+
+ let output = sig.output();
+
+ // Typecheck the output
+ if !drcx.types_may_unify(output, tokenstream) {
+ tcx.sess.emit_err(errors::ProcMacroTypeError {
+ span: hir_sig.decl.output.span(),
+ found: output,
+ kind,
+ expected_signature,
+ });
+ self.abort.set(true);
+ }
+
+ if sig.inputs().len() < expected_input_count {
+ tcx.sess.emit_err(errors::ProcMacroMissingArguments {
+ expected_input_count,
+ span: hir_sig.span,
+ kind,
+ expected_signature,
+ });
+ self.abort.set(true);
+ }
+
+ // Check that the inputs are correct, if there are enough.
+ if sig.inputs().len() >= expected_input_count {
+ for (arg, input) in
+ sig.inputs().iter().zip(hir_sig.decl.inputs).take(expected_input_count)
+ {
+ if !drcx.types_may_unify(*arg, tokenstream) {
+ tcx.sess.emit_err(errors::ProcMacroTypeError {
+ span: input.span,
+ found: *arg,
+ kind,
+ expected_signature,
+ });
+ self.abort.set(true);
+ }
+ }
+ }
+
+ // Check that there are not too many arguments
+ let body_id = tcx.hir().body_owned_by(id.def_id);
+ let excess = tcx.hir().body(body_id).params.get(expected_input_count..);
+ if let Some(excess @ [begin @ end] | excess @ [begin, .., end]) = excess {
+ tcx.sess.emit_err(errors::ProcMacroDiffArguments {
+ span: begin.span.to(end.span),
+ count: excess.len(),
+ kind,
+ expected_signature,
+ });
+ self.abort.set(true);
+ }
+ }
+ }
}
impl<'tcx> Visitor<'tcx> for CheckAttrVisitor<'tcx> {
@@ -2203,7 +2424,7 @@ fn check_invalid_crate_level_attr(tcx: TyCtxt<'_>, attrs: &[Attribute]) {
if attr.style == AttrStyle::Inner {
for attr_to_check in ATTRS_TO_CHECK {
if attr.has_name(*attr_to_check) {
- tcx.sess.emit_err(InvalidAttrAtCrateLevel {
+ tcx.sess.emit_err(errors::InvalidAttrAtCrateLevel {
span: attr.span,
snippet: tcx.sess.source_map().span_to_snippet(attr.span).ok(),
name: *attr_to_check,
@@ -2225,12 +2446,15 @@ fn check_non_exported_macro_for_invalid_attrs(tcx: TyCtxt<'_>, item: &Item<'_>)
}
fn check_mod_attrs(tcx: TyCtxt<'_>, module_def_id: LocalDefId) {
- let check_attr_visitor = &mut CheckAttrVisitor { tcx };
+ let check_attr_visitor = &mut CheckAttrVisitor { tcx, abort: Cell::new(false) };
tcx.hir().visit_item_likes_in_module(module_def_id, check_attr_visitor);
if module_def_id.is_top_level_module() {
check_attr_visitor.check_attributes(CRATE_HIR_ID, DUMMY_SP, Target::Mod, None);
check_invalid_crate_level_attr(tcx, tcx.hir().krate_attrs());
}
+ if check_attr_visitor.abort.get() {
+ tcx.sess.abort_if_errors()
+ }
}
pub(crate) fn provide(providers: &mut Providers) {
diff --git a/compiler/rustc_passes/src/check_const.rs b/compiler/rustc_passes/src/check_const.rs
index aa726d6cd..526b829bf 100644
--- a/compiler/rustc_passes/src/check_const.rs
+++ b/compiler/rustc_passes/src/check_const.rs
@@ -17,7 +17,7 @@ use rustc_middle::ty::TyCtxt;
use rustc_session::parse::feature_err;
use rustc_span::{sym, Span, Symbol};
-use crate::errors::ExprNotAllowedInContext;
+use crate::errors::{ExprNotAllowedInContext, SkippingConstChecks};
/// An expression that is not *always* legal in a const context.
#[derive(Clone, Copy)]
@@ -48,7 +48,7 @@ impl NonConstExpr {
Self::Match(TryDesugar) => &[sym::const_try],
// All other expressions are allowed.
- Self::Loop(Loop | While) | Self::Match(Normal) => &[],
+ Self::Loop(Loop | While) | Self::Match(Normal | FormatArgs) => &[],
};
Some(gates)
@@ -124,7 +124,7 @@ impl<'tcx> CheckConstVisitor<'tcx> {
// corresponding feature gate. This encourages nightly users to use feature gates when
// possible.
None if tcx.sess.opts.unstable_opts.unleash_the_miri_inside_of_you => {
- tcx.sess.span_warn(span, "skipping const checks");
+ tcx.sess.emit_warning(SkippingConstChecks { span });
return;
}
diff --git a/compiler/rustc_passes/src/dead.rs b/compiler/rustc_passes/src/dead.rs
index 94171b4b0..e2f858a34 100644
--- a/compiler/rustc_passes/src/dead.rs
+++ b/compiler/rustc_passes/src/dead.rs
@@ -259,7 +259,7 @@ impl<'tcx> MarkSymbolVisitor<'tcx> {
/// for discussion).
fn should_ignore_item(&mut 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) {
+ if !self.tcx.is_automatically_derived(impl_of) {
return false;
}
@@ -315,7 +315,7 @@ impl<'tcx> MarkSymbolVisitor<'tcx> {
//// This is done to handle the case where, for example, the static
//// method of a private type is used, but the type itself is never
//// called directly.
- let self_ty = self.tcx.type_of(item);
+ let self_ty = self.tcx.type_of(item).subst_identity();
match *self_ty.kind() {
ty::Adt(def, _) => self.check_def_id(def.did()),
ty::Foreign(did) => self.check_def_id(did),
@@ -395,6 +395,9 @@ impl<'tcx> Visitor<'tcx> for MarkSymbolVisitor<'tcx> {
self.mark_as_used_if_union(*adt, fields);
}
}
+ hir::ExprKind::Closure(cls) => {
+ self.insert_def_id(cls.def_id.to_def_id());
+ }
_ => (),
}
@@ -451,47 +454,40 @@ impl<'tcx> Visitor<'tcx> for MarkSymbolVisitor<'tcx> {
// referenced by it should be considered as used.
let in_pat = mem::replace(&mut self.in_pat, false);
- self.live_symbols.insert(self.tcx.hir().local_def_id(c.hir_id));
+ self.live_symbols.insert(c.def_id);
intravisit::walk_anon_const(self, c);
self.in_pat = in_pat;
}
}
-fn has_allow_dead_code_or_lang_attr_helper(
- tcx: TyCtxt<'_>,
- id: hir::HirId,
- lint: &'static lint::Lint,
-) -> bool {
- let attrs = tcx.hir().attrs(id);
- if tcx.sess.contains_name(attrs, sym::lang) {
- return true;
+fn has_allow_dead_code_or_lang_attr(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool {
+ fn has_lang_attr(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool {
+ tcx.has_attr(def_id.to_def_id(), sym::lang)
+ // Stable attribute for #[lang = "panic_impl"]
+ || tcx.has_attr(def_id.to_def_id(), sym::panic_handler)
}
- // Stable attribute for #[lang = "panic_impl"]
- if tcx.sess.contains_name(attrs, sym::panic_handler) {
- return true;
+ fn has_allow_dead_code(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool {
+ let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
+ tcx.lint_level_at_node(lint::builtin::DEAD_CODE, hir_id).0 == lint::Allow
}
- let def_id = tcx.hir().local_def_id(id);
- if tcx.def_kind(def_id).has_codegen_attrs() {
- let cg_attrs = tcx.codegen_fn_attrs(def_id);
+ fn has_used_like_attr(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool {
+ tcx.def_kind(def_id).has_codegen_attrs() && {
+ let cg_attrs = tcx.codegen_fn_attrs(def_id);
- // #[used], #[no_mangle], #[export_name], etc also keeps the item alive
- // forcefully, e.g., for placing it in a specific section.
- if cg_attrs.contains_extern_indicator()
- || cg_attrs.flags.contains(CodegenFnAttrFlags::USED)
- || cg_attrs.flags.contains(CodegenFnAttrFlags::USED_LINKER)
- {
- return true;
+ // #[used], #[no_mangle], #[export_name], etc also keeps the item alive
+ // forcefully, e.g., for placing it in a specific section.
+ cg_attrs.contains_extern_indicator()
+ || cg_attrs.flags.contains(CodegenFnAttrFlags::USED)
+ || cg_attrs.flags.contains(CodegenFnAttrFlags::USED_LINKER)
}
}
- tcx.lint_level_at_node(lint, id).0 == lint::Allow
-}
-
-fn has_allow_dead_code_or_lang_attr(tcx: TyCtxt<'_>, id: hir::HirId) -> bool {
- has_allow_dead_code_or_lang_attr_helper(tcx, id, lint::builtin::DEAD_CODE)
+ has_allow_dead_code(tcx, def_id)
+ || has_used_like_attr(tcx, def_id)
+ || has_lang_attr(tcx, def_id)
}
// These check_* functions seeds items that
@@ -513,7 +509,7 @@ fn check_item<'tcx>(
struct_constructors: &mut FxHashMap<LocalDefId, LocalDefId>,
id: hir::ItemId,
) {
- let allow_dead_code = has_allow_dead_code_or_lang_attr(tcx, id.hir_id());
+ let allow_dead_code = has_allow_dead_code_or_lang_attr(tcx, id.owner_id.def_id);
if allow_dead_code {
worklist.push(id.owner_id.def_id);
}
@@ -533,10 +529,8 @@ fn check_item<'tcx>(
}
}
}
- DefKind::Impl => {
- let of_trait = tcx.impl_trait_ref(id.owner_id);
-
- if of_trait.is_some() {
+ DefKind::Impl { of_trait } => {
+ if of_trait {
worklist.push(id.owner_id.def_id);
}
@@ -548,9 +542,7 @@ fn check_item<'tcx>(
// And we access the Map here to get HirId from LocalDefId
for id in local_def_ids {
- if of_trait.is_some()
- || has_allow_dead_code_or_lang_attr(tcx, tcx.hir().local_def_id_to_hir_id(id))
- {
+ if of_trait || has_allow_dead_code_or_lang_attr(tcx, id) {
worklist.push(id);
}
}
@@ -558,9 +550,9 @@ fn check_item<'tcx>(
DefKind::Struct => {
let item = tcx.hir().item(id);
if let hir::ItemKind::Struct(ref variant_data, _) = item.kind
- && let Some(ctor_hir_id) = variant_data.ctor_hir_id()
+ && let Some(ctor_def_id) = variant_data.ctor_def_id()
{
- struct_constructors.insert(tcx.hir().local_def_id(ctor_hir_id), item.owner_id.def_id);
+ struct_constructors.insert(ctor_def_id, item.owner_id.def_id);
}
}
DefKind::GlobalAsm => {
@@ -576,7 +568,7 @@ fn check_trait_item(tcx: TyCtxt<'_>, worklist: &mut Vec<LocalDefId>, id: hir::Tr
if matches!(tcx.def_kind(id.owner_id), DefKind::AssocConst | DefKind::AssocFn) {
let trait_item = tcx.hir().trait_item(id);
if matches!(trait_item.kind, Const(_, Some(_)) | Fn(_, hir::TraitFn::Provided(_)))
- && has_allow_dead_code_or_lang_attr(tcx, trait_item.hir_id())
+ && has_allow_dead_code_or_lang_attr(tcx, trait_item.owner_id.def_id)
{
worklist.push(trait_item.owner_id.def_id);
}
@@ -585,7 +577,7 @@ fn check_trait_item(tcx: TyCtxt<'_>, worklist: &mut Vec<LocalDefId>, id: hir::Tr
fn check_foreign_item(tcx: TyCtxt<'_>, worklist: &mut Vec<LocalDefId>, id: hir::ForeignItemId) {
if matches!(tcx.def_kind(id.owner_id), DefKind::Static(_) | DefKind::Fn)
- && has_allow_dead_code_or_lang_attr(tcx, id.hir_id())
+ && has_allow_dead_code_or_lang_attr(tcx, id.owner_id.def_id)
{
worklist.push(id.owner_id.def_id);
}
@@ -665,7 +657,7 @@ impl<'tcx> DeadVisitor<'tcx> {
if self.live_symbols.contains(&field.did.expect_local()) {
return ShouldWarnAboutField::No;
}
- let field_type = self.tcx.type_of(field.did);
+ let field_type = self.tcx.type_of(field.did).subst_identity();
if field_type.is_phantom_data() {
return ShouldWarnAboutField::No;
}
@@ -702,7 +694,7 @@ impl<'tcx> DeadVisitor<'tcx> {
})
.collect();
- let descr = tcx.def_kind(first_id).descr(first_id.to_def_id());
+ let descr = tcx.def_descr(first_id.to_def_id());
let num = dead_codes.len();
let multiple = num > 6;
let name_list = names.into();
@@ -714,7 +706,7 @@ impl<'tcx> DeadVisitor<'tcx> {
};
let parent_info = if let Some(parent_item) = parent_item {
- let parent_descr = tcx.def_kind(parent_item).descr(parent_item.to_def_id());
+ let parent_descr = tcx.def_descr(parent_item.to_def_id());
Some(ParentInfo {
num,
descr,
@@ -806,8 +798,7 @@ impl<'tcx> DeadVisitor<'tcx> {
if self.live_symbols.contains(&def_id) {
return;
}
- let hir_id = self.tcx.hir().local_def_id_to_hir_id(def_id);
- if has_allow_dead_code_or_lang_attr(self.tcx, hir_id) {
+ if has_allow_dead_code_or_lang_attr(self.tcx, def_id) {
return;
}
let Some(name) = self.tcx.opt_item_name(def_id.to_def_id()) else {
diff --git a/compiler/rustc_passes/src/diagnostic_items.rs b/compiler/rustc_passes/src/diagnostic_items.rs
index 10ffa87ef..110eb210d 100644
--- a/compiler/rustc_passes/src/diagnostic_items.rs
+++ b/compiler/rustc_passes/src/diagnostic_items.rs
@@ -11,19 +11,19 @@
use rustc_ast as ast;
use rustc_hir::diagnostic_items::DiagnosticItems;
+use rustc_hir::OwnerId;
use rustc_middle::ty::query::Providers;
use rustc_middle::ty::TyCtxt;
-use rustc_span::def_id::{CrateNum, DefId, LocalDefId, LOCAL_CRATE};
-use rustc_span::symbol::{kw::Empty, sym, Symbol};
+use rustc_span::def_id::{CrateNum, DefId, LOCAL_CRATE};
+use rustc_span::symbol::{sym, Symbol};
-use crate::errors::{DuplicateDiagnosticItem, DuplicateDiagnosticItemInCrate};
+use crate::errors::DuplicateDiagnosticItemInCrate;
-fn observe_item(tcx: TyCtxt<'_>, diagnostic_items: &mut DiagnosticItems, def_id: LocalDefId) {
- let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
- let attrs = tcx.hir().attrs(hir_id);
+fn observe_item<'tcx>(tcx: TyCtxt<'tcx>, diagnostic_items: &mut DiagnosticItems, owner: OwnerId) {
+ let attrs = tcx.hir().attrs(owner.into());
if let Some(name) = extract(attrs) {
// insert into our table
- collect_item(tcx, diagnostic_items, name, def_id.to_def_id());
+ collect_item(tcx, diagnostic_items, name, owner.to_def_id());
}
}
@@ -31,26 +31,29 @@ fn collect_item(tcx: TyCtxt<'_>, items: &mut DiagnosticItems, name: Symbol, item
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 orig_span = tcx.hir().span_if_local(original_def_id);
- let orig_crate_name = if orig_span.is_some() {
- None
- } else {
- Some(tcx.crate_name(original_def_id.krate))
- };
- match tcx.hir().span_if_local(item_def_id) {
- Some(span) => tcx.sess.emit_err(DuplicateDiagnosticItem { span, name }),
- None => tcx.sess.emit_err(DuplicateDiagnosticItemInCrate {
- span: orig_span,
- orig_crate_name: orig_crate_name.unwrap_or(Empty),
- have_orig_crate_name: orig_crate_name.map(|_| ()),
- crate_name: tcx.crate_name(item_def_id.krate),
- name,
- }),
- };
+ report_duplicate_item(tcx, name, original_def_id, item_def_id);
}
}
}
+fn report_duplicate_item(
+ tcx: TyCtxt<'_>,
+ name: Symbol,
+ original_def_id: DefId,
+ item_def_id: DefId,
+) {
+ let orig_span = tcx.hir().span_if_local(original_def_id);
+ let duplicate_span = tcx.hir().span_if_local(item_def_id);
+ tcx.sess.emit_err(DuplicateDiagnosticItemInCrate {
+ duplicate_span,
+ orig_span,
+ crate_name: tcx.crate_name(item_def_id.krate),
+ orig_crate_name: tcx.crate_name(original_def_id.krate),
+ different_crates: (item_def_id.krate != original_def_id.krate).then_some(()),
+ name,
+ });
+}
+
/// Extract the first `rustc_diagnostic_item = "$name"` out of a list of attributes.
fn extract(attrs: &[ast::Attribute]) -> Option<Symbol> {
attrs.iter().find_map(|attr| {
@@ -67,21 +70,8 @@ fn diagnostic_items(tcx: TyCtxt<'_>, cnum: CrateNum) -> DiagnosticItems {
// Collect diagnostic items in this crate.
let crate_items = tcx.hir_crate_items(());
-
- for id in crate_items.items() {
- observe_item(tcx, &mut diagnostic_items, id.owner_id.def_id);
- }
-
- for id in crate_items.trait_items() {
- observe_item(tcx, &mut diagnostic_items, id.owner_id.def_id);
- }
-
- for id in crate_items.impl_items() {
- observe_item(tcx, &mut diagnostic_items, id.owner_id.def_id);
- }
-
- for id in crate_items.foreign_items() {
- observe_item(tcx, &mut diagnostic_items, id.owner_id.def_id);
+ for id in crate_items.owners() {
+ observe_item(tcx, &mut diagnostic_items, id);
}
diagnostic_items
diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs
index 9c6519ea4..9f1c0b5a0 100644
--- a/compiler/rustc_passes/src/errors.rs
+++ b/compiler/rustc_passes/src/errors.rs
@@ -3,6 +3,7 @@ use std::{
path::{Path, PathBuf},
};
+use crate::fluent_generated as fluent;
use rustc_ast::Label;
use rustc_errors::{
error_code, Applicability, DiagnosticSymbolList, ErrorGuaranteed, IntoDiagnostic, MultiSpan,
@@ -12,6 +13,7 @@ use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic};
use rustc_middle::ty::{MainDefinition, Ty};
use rustc_span::{Span, Symbol, DUMMY_SP};
+use crate::check_attr::ProcMacroKind;
use crate::lang_items::Duplicate;
#[derive(Diagnostic)]
@@ -260,7 +262,7 @@ pub struct DocKeywordConflict {
pub struct DocInlineOnlyUse {
#[label]
pub attr_span: Span,
- #[label(not_a_use_item_label)]
+ #[label(passes_not_a_use_item_label)]
pub item_span: Option<Span>,
}
@@ -299,7 +301,7 @@ pub struct DocTestUnknownAny {
#[derive(LintDiagnostic)]
#[diag(passes_doc_test_unknown_spotlight)]
#[note]
-#[note(no_op_note)]
+#[note(passes_no_op_note)]
pub struct DocTestUnknownSpotlight {
pub path: String,
#[suggestion(style = "short", applicability = "machine-applicable", code = "notable_trait")]
@@ -347,6 +349,34 @@ pub struct HasIncoherentInherentImpl {
pub span: Span,
}
+#[derive(Diagnostic)]
+#[diag(passes_both_ffi_const_and_pure, code = "E0757")]
+pub struct BothFfiConstAndPure {
+ #[primary_span]
+ pub attr_span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(passes_ffi_pure_invalid_target, code = "E0755")]
+pub struct FfiPureInvalidTarget {
+ #[primary_span]
+ pub attr_span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(passes_ffi_const_invalid_target, code = "E0756")]
+pub struct FfiConstInvalidTarget {
+ #[primary_span]
+ pub attr_span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(passes_ffi_returns_twice_invalid_target, code = "E0724")]
+pub struct FfiReturnsTwiceInvalidTarget {
+ #[primary_span]
+ pub attr_span: Span,
+}
+
#[derive(LintDiagnostic)]
#[diag(passes_must_use_async)]
pub struct MustUseAsync {
@@ -544,9 +574,9 @@ pub struct DebugVisualizerPlacement {
#[derive(Diagnostic)]
#[diag(passes_debug_visualizer_invalid)]
-#[note(note_1)]
-#[note(note_2)]
-#[note(note_3)]
+#[note(passes_note_1)]
+#[note(passes_note_2)]
+#[note(passes_note_3)]
pub struct DebugVisualizerInvalid {
#[primary_span]
pub span: Span,
@@ -611,8 +641,16 @@ pub struct MacroUse {
}
#[derive(LintDiagnostic)]
-#[diag(passes_macro_export)]
-pub struct MacroExport;
+pub enum MacroExport {
+ #[diag(passes_macro_export)]
+ Normal,
+
+ #[diag(passes_invalid_macro_export_arguments)]
+ UnknownItem { name: Symbol },
+
+ #[diag(passes_invalid_macro_export_arguments_too_many_items)]
+ TooManyItems,
+}
#[derive(LintDiagnostic)]
#[diag(passes_plugin_registrar)]
@@ -753,7 +791,7 @@ impl IntoDiagnostic<'_> for InvalidAttrAtCrateLevel {
self,
handler: &'_ rustc_errors::Handler,
) -> rustc_errors::DiagnosticBuilder<'_, ErrorGuaranteed> {
- let mut diag = handler.struct_err(rustc_errors::fluent::passes_invalid_attr_at_crate_level);
+ let mut diag = handler.struct_err(fluent::passes_invalid_attr_at_crate_level);
diag.set_span(self.span);
diag.set_arg("name", self.name);
// Only emit an error with a suggestion if we can create a string out
@@ -762,7 +800,7 @@ impl IntoDiagnostic<'_> for InvalidAttrAtCrateLevel {
let replacement = src.replace("#!", "#");
diag.span_suggestion_verbose(
self.span,
- rustc_errors::fluent::suggestion,
+ fluent::passes_suggestion,
replacement,
rustc_errors::Applicability::MachineApplicable,
);
@@ -772,22 +810,16 @@ impl IntoDiagnostic<'_> for InvalidAttrAtCrateLevel {
}
#[derive(Diagnostic)]
-#[diag(passes_duplicate_diagnostic_item)]
-pub struct DuplicateDiagnosticItem {
- #[primary_span]
- pub span: Span,
- pub name: Symbol,
-}
-
-#[derive(Diagnostic)]
#[diag(passes_duplicate_diagnostic_item_in_crate)]
pub struct DuplicateDiagnosticItemInCrate {
+ #[primary_span]
+ pub duplicate_span: Option<Span>,
#[note(passes_diagnostic_item_first_defined)]
- pub span: Option<Span>,
- pub orig_crate_name: Symbol,
+ pub orig_span: Option<Span>,
#[note]
- pub have_orig_crate_name: Option<()>,
+ pub different_crates: Option<()>,
pub crate_name: Symbol,
+ pub orig_crate_name: Symbol,
pub name: Symbol,
}
@@ -888,17 +920,17 @@ impl<'a> IntoDiagnostic<'_> for BreakNonLoop<'a> {
) -> rustc_errors::DiagnosticBuilder<'_, ErrorGuaranteed> {
let mut diag = handler.struct_span_err_with_code(
self.span,
- rustc_errors::fluent::passes_break_non_loop,
+ fluent::passes_break_non_loop,
error_code!(E0571),
);
diag.set_arg("kind", self.kind);
- diag.span_label(self.span, rustc_errors::fluent::label);
+ diag.span_label(self.span, fluent::passes_label);
if let Some(head) = self.head {
- diag.span_label(head, rustc_errors::fluent::label2);
+ diag.span_label(head, fluent::passes_label2);
}
diag.span_suggestion(
self.span,
- rustc_errors::fluent::suggestion,
+ fluent::passes_suggestion,
self.suggestion,
Applicability::MaybeIncorrect,
);
@@ -916,7 +948,7 @@ impl<'a> IntoDiagnostic<'_> for BreakNonLoop<'a> {
_ => {
diag.span_suggestion(
self.break_expr_span,
- rustc_errors::fluent::break_expr_suggestion,
+ fluent::passes_break_expr_suggestion,
label.ident,
Applicability::MaybeIncorrect,
);
@@ -933,7 +965,7 @@ pub struct ContinueLabeledBlock {
#[primary_span]
#[label]
pub span: Span,
- #[label(block_label)]
+ #[label(passes_block_label)]
pub block_span: Span,
}
@@ -943,7 +975,7 @@ pub struct BreakInsideClosure<'a> {
#[primary_span]
#[label]
pub span: Span,
- #[label(closure_label)]
+ #[label(passes_closure_label)]
pub closure_span: Span,
pub name: &'a str,
}
@@ -954,7 +986,7 @@ pub struct BreakInsideAsyncBlock<'a> {
#[primary_span]
#[label]
pub span: Span,
- #[label(async_block_label)]
+ #[label(passes_async_block_label)]
pub closure_span: Span,
pub name: &'a str,
}
@@ -1027,14 +1059,14 @@ impl IntoDiagnostic<'_> for NakedFunctionsAsmBlock {
) -> rustc_errors::DiagnosticBuilder<'_, ErrorGuaranteed> {
let mut diag = handler.struct_span_err_with_code(
self.span,
- rustc_errors::fluent::passes_naked_functions_asm_block,
+ fluent::passes_naked_functions_asm_block,
error_code!(E0787),
);
for span in self.multiple_asms.iter() {
- diag.span_label(*span, rustc_errors::fluent::label_multiple_asm);
+ diag.span_label(*span, fluent::passes_label_multiple_asm);
}
for span in self.non_asms.iter() {
- diag.span_label(*span, rustc_errors::fluent::label_non_asm);
+ diag.span_label(*span, fluent::passes_label_non_asm);
}
diag
}
@@ -1093,9 +1125,9 @@ pub struct AttrOnlyInFunctions {
pub struct MultipleRustcMain {
#[primary_span]
pub span: Span,
- #[label(first)]
+ #[label(passes_first)]
pub first: Span,
- #[label(additional)]
+ #[label(passes_additional)]
pub additional: Span,
}
@@ -1106,7 +1138,7 @@ pub struct MultipleStartFunctions {
pub span: Span,
#[label]
pub labeled: Span,
- #[label(previous)]
+ #[label(passes_previous)]
pub previous: Span,
}
@@ -1151,7 +1183,7 @@ impl<'a> IntoDiagnostic<'a> for NoMainErr {
) -> rustc_errors::DiagnosticBuilder<'a, ErrorGuaranteed> {
let mut diag = handler.struct_span_err_with_code(
DUMMY_SP,
- rustc_errors::fluent::passes_no_main_function,
+ fluent::passes_no_main_function,
error_code!(E0601),
);
diag.set_arg("crate_name", self.crate_name);
@@ -1159,16 +1191,16 @@ impl<'a> IntoDiagnostic<'a> for NoMainErr {
diag.set_arg("has_filename", self.has_filename);
let note = if !self.non_main_fns.is_empty() {
for &span in &self.non_main_fns {
- diag.span_note(span, rustc_errors::fluent::here_is_main);
+ diag.span_note(span, fluent::passes_here_is_main);
}
- diag.note(rustc_errors::fluent::one_or_more_possible_main);
- diag.help(rustc_errors::fluent::consider_moving_main);
+ diag.note(fluent::passes_one_or_more_possible_main);
+ diag.help(fluent::passes_consider_moving_main);
// There were some functions named `main` though. Try to give the user a hint.
- rustc_errors::fluent::main_must_be_defined_at_crate
+ fluent::passes_main_must_be_defined_at_crate
} else if self.has_filename {
- rustc_errors::fluent::consider_adding_main_to_file
+ fluent::passes_consider_adding_main_to_file
} else {
- rustc_errors::fluent::consider_adding_main_at_crate
+ fluent::passes_consider_adding_main_at_crate
};
if self.file_empty {
diag.note(note);
@@ -1179,11 +1211,11 @@ impl<'a> IntoDiagnostic<'a> for NoMainErr {
if let Some(main_def) = self.main_def_opt && main_def.opt_fn_def_id().is_none(){
// There is something at `crate::main`, but it is not a function definition.
- diag.span_label(main_def.span, rustc_errors::fluent::non_function_main);
+ diag.span_label(main_def.span, fluent::passes_non_function_main);
}
if self.add_teach_note {
- diag.note(rustc_errors::fluent::teach_note);
+ diag.note(fluent::passes_teach_note);
}
diag
}
@@ -1212,12 +1244,9 @@ impl IntoDiagnostic<'_> for DuplicateLangItem {
) -> rustc_errors::DiagnosticBuilder<'_, ErrorGuaranteed> {
let mut diag = handler.struct_err_with_code(
match self.duplicate {
- Duplicate::Plain => rustc_errors::fluent::passes_duplicate_lang_item,
-
- Duplicate::Crate => rustc_errors::fluent::passes_duplicate_lang_item_crate,
- Duplicate::CrateDepends => {
- rustc_errors::fluent::passes_duplicate_lang_item_crate_depends
- }
+ Duplicate::Plain => fluent::passes_duplicate_lang_item,
+ Duplicate::Crate => fluent::passes_duplicate_lang_item_crate,
+ Duplicate::CrateDepends => fluent::passes_duplicate_lang_item_crate_depends,
},
error_code!(E0152),
);
@@ -1232,24 +1261,24 @@ impl IntoDiagnostic<'_> for DuplicateLangItem {
diag.set_span(span);
}
if let Some(span) = self.first_defined_span {
- diag.span_note(span, rustc_errors::fluent::first_defined_span);
+ diag.span_note(span, fluent::passes_first_defined_span);
} else {
if self.orig_dependency_of.is_empty() {
- diag.note(rustc_errors::fluent::first_defined_crate);
+ diag.note(fluent::passes_first_defined_crate);
} else {
- diag.note(rustc_errors::fluent::first_defined_crate_depends);
+ diag.note(fluent::passes_first_defined_crate_depends);
}
if self.orig_is_local {
- diag.note(rustc_errors::fluent::first_definition_local);
+ diag.note(fluent::passes_first_definition_local);
} else {
- diag.note(rustc_errors::fluent::first_definition_path);
+ diag.note(fluent::passes_first_definition_path);
}
if self.is_local {
- diag.note(rustc_errors::fluent::second_definition_local);
+ diag.note(fluent::passes_second_definition_local);
} else {
- diag.note(rustc_errors::fluent::second_definition_path);
+ diag.note(fluent::passes_second_definition_path);
}
}
diag
@@ -1360,7 +1389,7 @@ pub struct UselessStability {
#[primary_span]
#[label]
pub span: Span,
- #[label(item)]
+ #[label(passes_item)]
pub item_sp: Span,
}
@@ -1370,7 +1399,7 @@ pub struct InvalidStability {
#[primary_span]
#[label]
pub span: Span,
- #[label(item)]
+ #[label(passes_item)]
pub item_sp: Span,
}
@@ -1380,7 +1409,7 @@ pub struct CannotStabilizeDeprecated {
#[primary_span]
#[label]
pub span: Span,
- #[label(item)]
+ #[label(passes_item)]
pub item_sp: Span,
}
@@ -1390,7 +1419,7 @@ pub struct InvalidDeprecationVersion {
#[primary_span]
#[label]
pub span: Span,
- #[label(item)]
+ #[label(passes_item)]
pub item_sp: Span,
}
@@ -1515,3 +1544,59 @@ pub struct ChangeFieldsToBeOfUnitType {
#[suggestion_part(code = "()")]
pub spans: Vec<Span>,
}
+
+#[derive(Diagnostic)]
+#[diag(passes_proc_macro_typeerror)]
+#[note]
+pub(crate) struct ProcMacroTypeError<'tcx> {
+ #[primary_span]
+ #[label]
+ pub span: Span,
+ pub found: Ty<'tcx>,
+ pub kind: ProcMacroKind,
+ pub expected_signature: &'static str,
+}
+
+#[derive(Diagnostic)]
+#[diag(passes_proc_macro_diff_arg_count)]
+pub(crate) struct ProcMacroDiffArguments {
+ #[primary_span]
+ #[label]
+ pub span: Span,
+ pub count: usize,
+ pub kind: ProcMacroKind,
+ pub expected_signature: &'static str,
+}
+
+#[derive(Diagnostic)]
+#[diag(passes_proc_macro_missing_args)]
+pub(crate) struct ProcMacroMissingArguments {
+ #[primary_span]
+ #[label]
+ pub span: Span,
+ pub expected_input_count: usize,
+ pub kind: ProcMacroKind,
+ pub expected_signature: &'static str,
+}
+
+#[derive(Diagnostic)]
+#[diag(passes_proc_macro_invalid_abi)]
+pub(crate) struct ProcMacroInvalidAbi {
+ #[primary_span]
+ pub span: Span,
+ pub abi: &'static str,
+}
+
+#[derive(Diagnostic)]
+#[diag(passes_proc_macro_unsafe)]
+pub(crate) struct ProcMacroUnsafe {
+ #[primary_span]
+ pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(passes_skipping_const_checks)]
+pub struct SkippingConstChecks {
+ #[primary_span]
+ pub span: Span,
+}
diff --git a/compiler/rustc_passes/src/hir_id_validator.rs b/compiler/rustc_passes/src/hir_id_validator.rs
index d143adb2e..de0e50a65 100644
--- a/compiler/rustc_passes/src/hir_id_validator.rs
+++ b/compiler/rustc_passes/src/hir_id_validator.rs
@@ -74,37 +74,26 @@ impl<'a, 'hir> HirIdValidator<'a, 'hir> {
.expect("owning item has no entry");
if max != self.hir_ids_seen.len() - 1 {
- // Collect the missing ItemLocalIds
- let missing: Vec<_> = (0..=max as u32)
- .filter(|&i| !self.hir_ids_seen.contains(ItemLocalId::from_u32(i)))
- .collect();
-
- // Try to map those to something more useful
- let mut missing_items = Vec::with_capacity(missing.len());
+ let hir = self.tcx.hir();
+ let pretty_owner = hir.def_path(owner.def_id).to_string_no_crate_verbose();
- for local_id in missing {
- let hir_id = HirId { owner, local_id: ItemLocalId::from_u32(local_id) };
+ let missing_items: Vec<_> = (0..=max as u32)
+ .map(|i| ItemLocalId::from_u32(i))
+ .filter(|&local_id| !self.hir_ids_seen.contains(local_id))
+ .map(|local_id| hir.node_to_string(HirId { owner, local_id }))
+ .collect();
- trace!("missing hir id {:#?}", hir_id);
+ let seen_items: Vec<_> = self
+ .hir_ids_seen
+ .iter()
+ .map(|local_id| hir.node_to_string(HirId { owner, local_id }))
+ .collect();
- missing_items.push(format!(
- "[local_id: {}, owner: {}]",
- local_id,
- self.tcx.hir().def_path(owner.def_id).to_string_no_crate_verbose()
- ));
- }
self.error(|| {
format!(
"ItemLocalIds not assigned densely in {}. \
- Max ItemLocalId = {}, missing IDs = {:#?}; seens IDs = {:#?}",
- self.tcx.hir().def_path(owner.def_id).to_string_no_crate_verbose(),
- max,
- missing_items,
- self.hir_ids_seen
- .iter()
- .map(|local_id| HirId { owner, local_id })
- .map(|h| format!("({:?} {})", h, self.tcx.hir().node_to_string(h)))
- .collect::<Vec<_>>()
+ Max ItemLocalId = {}, missing IDs = {:#?}; seen IDs = {:#?}",
+ pretty_owner, max, missing_items, seen_items
)
});
}
diff --git a/compiler/rustc_passes/src/hir_stats.rs b/compiler/rustc_passes/src/hir_stats.rs
index b86d23168..5e2d2d3e5 100644
--- a/compiler/rustc_passes/src/hir_stats.rs
+++ b/compiler/rustc_passes/src/hir_stats.rs
@@ -12,6 +12,7 @@ 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::def_id::LocalDefId;
use rustc_span::Span;
#[derive(Copy, Clone, PartialEq, Eq, Hash)]
@@ -363,7 +364,7 @@ impl<'v> hir_visit::Visitor<'v> for StatCollector<'v> {
fd: &'v hir::FnDecl<'v>,
b: hir::BodyId,
_: Span,
- id: hir::HirId,
+ id: LocalDefId,
) {
self.record("FnDecl", Id::None, fd);
hir_visit::walk_fn(self, fk, fd, b, id)
@@ -567,7 +568,7 @@ impl<'v> ast_visit::Visitor<'v> for StatCollector<'v> {
Box, Array, ConstBlock, Call, MethodCall, Tup, Binary, Unary, Lit, Cast, Type, Let,
If, While, ForLoop, Loop, Match, Closure, Block, Async, Await, TryBlock, Assign,
AssignOp, Field, Index, Range, Underscore, Path, AddrOf, Break, Continue, Ret,
- InlineAsm, MacCall, Struct, Repeat, Paren, Try, Yield, Yeet, IncludedBytes, Err
+ InlineAsm, FormatArgs, MacCall, Struct, Repeat, Paren, Try, Yield, Yeet, IncludedBytes, Err
]
);
ast_visit::walk_expr(self, e)
@@ -645,7 +646,7 @@ impl<'v> ast_visit::Visitor<'v> for StatCollector<'v> {
}
// `UseTree` has one inline use (in `ast::ItemKind::Use`) and one
- // non-inline use (in `ast::UseTreeKind::Nested). The former case is more
+ // non-inline use (in `ast::UseTreeKind::Nested`). The former case is more
// common, so we don't implement `visit_use_tree` and tolerate the missed
// coverage in the latter case.
diff --git a/compiler/rustc_passes/src/lang_items.rs b/compiler/rustc_passes/src/lang_items.rs
index 9a40b847d..fdd0e5dab 100644
--- a/compiler/rustc_passes/src/lang_items.rs
+++ b/compiler/rustc_passes/src/lang_items.rs
@@ -15,9 +15,9 @@ use crate::weak_lang_items;
use rustc_hir as hir;
use rustc_hir::def::DefKind;
-use rustc_hir::def_id::DefId;
+use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_hir::lang_items::{extract, GenericRequirement};
-use rustc_hir::{HirId, LangItem, LanguageItems, Target};
+use rustc_hir::{LangItem, LanguageItems, Target};
use rustc_middle::ty::TyCtxt;
use rustc_session::cstore::ExternCrate;
use rustc_span::{symbol::kw::Empty, Span};
@@ -40,13 +40,13 @@ impl<'tcx> LanguageItemCollector<'tcx> {
LanguageItemCollector { tcx, items: LanguageItems::new() }
}
- fn check_for_lang(&mut self, actual_target: Target, hir_id: HirId) {
- let attrs = self.tcx.hir().attrs(hir_id);
+ fn check_for_lang(&mut self, actual_target: Target, def_id: LocalDefId) {
+ let attrs = self.tcx.hir().attrs(self.tcx.hir().local_def_id_to_hir_id(def_id));
if let Some((name, span)) = extract(&attrs) {
match LangItem::from_name(name) {
// Known lang item with attribute on correct target.
Some(lang_item) if actual_target == lang_item.target() => {
- self.collect_item_extended(lang_item, hir_id, span);
+ self.collect_item_extended(lang_item, def_id, span);
}
// Known lang item with attribute on incorrect target.
Some(lang_item) => {
@@ -142,8 +142,7 @@ impl<'tcx> LanguageItemCollector<'tcx> {
// Like collect_item() above, but also checks whether the lang item is declared
// with the right number of generic arguments.
- fn collect_item_extended(&mut self, lang_item: LangItem, hir_id: HirId, span: Span) {
- let item_def_id = self.tcx.hir().local_def_id(hir_id).to_def_id();
+ fn collect_item_extended(&mut self, lang_item: LangItem, item_def_id: LocalDefId, span: Span) {
let name = lang_item.name();
// Now check whether the lang_item has the expected number of generic
@@ -154,7 +153,8 @@ impl<'tcx> LanguageItemCollector<'tcx> {
// Some other types like Box and various functions like drop_in_place
// have minimum requirements.
- if let hir::Node::Item(hir::Item { kind, span: item_span, .. }) = self.tcx.hir().get(hir_id)
+ if let hir::Node::Item(hir::Item { kind, span: item_span, .. }) =
+ self.tcx.hir().get_by_def_id(item_def_id)
{
let (actual_num, generics_span) = match kind.generics() {
Some(generics) => (generics.params.len(), generics.span),
@@ -191,7 +191,7 @@ impl<'tcx> LanguageItemCollector<'tcx> {
}
}
- self.collect_item(lang_item, item_def_id);
+ self.collect_item(lang_item, item_def_id.to_def_id());
}
}
@@ -211,13 +211,14 @@ fn get_lang_items(tcx: TyCtxt<'_>, (): ()) -> LanguageItems {
let crate_items = tcx.hir_crate_items(());
for id in crate_items.items() {
- collector.check_for_lang(Target::from_def_kind(tcx.def_kind(id.owner_id)), id.hir_id());
+ collector
+ .check_for_lang(Target::from_def_kind(tcx.def_kind(id.owner_id)), id.owner_id.def_id);
if matches!(tcx.def_kind(id.owner_id), DefKind::Enum) {
let item = tcx.hir().item(id);
if let hir::ItemKind::Enum(def, ..) = &item.kind {
for variant in def.variants {
- collector.check_for_lang(Target::Variant, variant.hir_id);
+ collector.check_for_lang(Target::Variant, variant.def_id);
}
}
}
@@ -226,13 +227,13 @@ fn get_lang_items(tcx: TyCtxt<'_>, (): ()) -> LanguageItems {
// FIXME: avoid calling trait_item() when possible
for id in crate_items.trait_items() {
let item = tcx.hir().trait_item(id);
- collector.check_for_lang(Target::from_trait_item(item), item.hir_id())
+ collector.check_for_lang(Target::from_trait_item(item), item.owner_id.def_id)
}
// FIXME: avoid calling impl_item() when possible
for id in crate_items.impl_items() {
let item = tcx.hir().impl_item(id);
- collector.check_for_lang(target_from_impl_item(tcx, item), item.hir_id())
+ collector.check_for_lang(target_from_impl_item(tcx, item), item.owner_id.def_id)
}
// Extract out the found lang items.
diff --git a/compiler/rustc_passes/src/layout_test.rs b/compiler/rustc_passes/src/layout_test.rs
index 827d86780..047b9b525 100644
--- a/compiler/rustc_passes/src/layout_test.rs
+++ b/compiler/rustc_passes/src/layout_test.rs
@@ -29,7 +29,7 @@ pub fn test_layout(tcx: TyCtxt<'_>) {
fn dump_layout_of(tcx: TyCtxt<'_>, item_def_id: LocalDefId, attr: &Attribute) {
let tcx = tcx;
let param_env = tcx.param_env(item_def_id);
- let ty = tcx.type_of(item_def_id);
+ let ty = tcx.type_of(item_def_id).subst_identity();
match tcx.layout_of(param_env.and(ty)) {
Ok(ty_layout) => {
// Check out the `#[rustc_layout(..)]` attribute to tell what to dump.
diff --git a/compiler/rustc_passes/src/lib.rs b/compiler/rustc_passes/src/lib.rs
index 6e621b7eb..0cb842408 100644
--- a/compiler/rustc_passes/src/lib.rs
+++ b/compiler/rustc_passes/src/lib.rs
@@ -18,6 +18,8 @@ extern crate rustc_middle;
#[macro_use]
extern crate tracing;
+use rustc_errors::{DiagnosticMessage, SubdiagnosticMessage};
+use rustc_macros::fluent_messages;
use rustc_middle::ty::query::Providers;
mod check_attr;
@@ -40,6 +42,8 @@ pub mod stability;
mod upvars;
mod weak_lang_items;
+fluent_messages! { "../locales/en-US.ftl" }
+
pub fn provide(providers: &mut Providers) {
check_attr::provide(providers);
check_const::provide(providers);
diff --git a/compiler/rustc_passes/src/lib_features.rs b/compiler/rustc_passes/src/lib_features.rs
index 4c6a9b23f..f4da1aaec 100644
--- a/compiler/rustc_passes/src/lib_features.rs
+++ b/compiler/rustc_passes/src/lib_features.rs
@@ -4,7 +4,7 @@
//! but are not declared in one single location (unlike lang features), which means we need to
//! collect them instead.
-use rustc_ast::{Attribute, MetaItemKind};
+use rustc_ast::Attribute;
use rustc_attr::{rust_version_symbol, VERSION_PLACEHOLDER};
use rustc_hir::intravisit::Visitor;
use rustc_middle::hir::nested_filter;
@@ -42,8 +42,7 @@ impl<'tcx> LibFeatureCollector<'tcx> {
// Find a stability attribute: one of #[stable(…)], #[unstable(…)],
// #[rustc_const_stable(…)], #[rustc_const_unstable(…)] or #[rustc_default_body_unstable].
if let Some(stab_attr) = stab_attrs.iter().find(|stab_attr| attr.has_name(**stab_attr)) {
- let meta_kind = attr.meta_kind();
- if let Some(MetaItemKind::List(ref metas)) = meta_kind {
+ if let Some(metas) = attr.meta_item_list() {
let mut feature = None;
let mut since = None;
for meta in metas {
diff --git a/compiler/rustc_passes/src/liveness.rs b/compiler/rustc_passes/src/liveness.rs
index 6afdcc37f..df5c8f53e 100644
--- a/compiler/rustc_passes/src/liveness.rs
+++ b/compiler/rustc_passes/src/liveness.rs
@@ -145,7 +145,7 @@ fn check_liveness(tcx: TyCtxt<'_>, def_id: DefId) {
// Don't run unused pass for #[derive()]
let parent = tcx.local_parent(local_def_id);
- if let DefKind::Impl = tcx.def_kind(parent)
+ if let DefKind::Impl { .. } = tcx.def_kind(parent)
&& tcx.has_attr(parent.to_def_id(), sym::automatically_derived)
{
return;
@@ -475,7 +475,7 @@ impl<'tcx> Visitor<'tcx> for IrMaps<'tcx> {
| hir::ExprKind::InlineAsm(..)
| hir::ExprKind::Box(..)
| hir::ExprKind::Type(..)
- | hir::ExprKind::Err
+ | hir::ExprKind::Err(_)
| hir::ExprKind::Path(hir::QPath::TypeRelative(..))
| hir::ExprKind::Path(hir::QPath::LangItem(..)) => {
intravisit::walk_expr(self, expr);
@@ -1129,7 +1129,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
hir::ExprKind::Lit(..)
| hir::ExprKind::ConstBlock(..)
- | hir::ExprKind::Err
+ | hir::ExprKind::Err(_)
| hir::ExprKind::Path(hir::QPath::TypeRelative(..))
| hir::ExprKind::Path(hir::QPath::LangItem(..)) => succ,
@@ -1427,7 +1427,7 @@ fn check_expr<'tcx>(this: &mut Liveness<'_, 'tcx>, expr: &'tcx Expr<'tcx>) {
| hir::ExprKind::Yield(..)
| hir::ExprKind::Box(..)
| hir::ExprKind::Type(..)
- | hir::ExprKind::Err => {}
+ | hir::ExprKind::Err(_) => {}
}
}
diff --git a/compiler/rustc_passes/src/liveness/rwu_table.rs b/compiler/rustc_passes/src/liveness/rwu_table.rs
index 6d5983f53..053bf5c23 100644
--- a/compiler/rustc_passes/src/liveness/rwu_table.rs
+++ b/compiler/rustc_passes/src/liveness/rwu_table.rs
@@ -9,7 +9,7 @@ pub(super) struct RWU {
}
/// Conceptually, this is like a `Vec<Vec<RWU>>`. But the number of
-/// RWU`s can get very large, so it uses a more compact representation.
+/// RWU's can get very large, so it uses a more compact representation.
pub(super) struct RWUTable {
/// Total number of live nodes.
live_nodes: usize,
diff --git a/compiler/rustc_passes/src/naked_functions.rs b/compiler/rustc_passes/src/naked_functions.rs
index acc54e7e1..c5b5cf7f5 100644
--- a/compiler/rustc_passes/src/naked_functions.rs
+++ b/compiler/rustc_passes/src/naked_functions.rs
@@ -219,7 +219,7 @@ impl<'tcx> CheckInlineAssembly<'tcx> {
hir::intravisit::walk_expr(self, expr);
}
- ExprKind::Err => {
+ ExprKind::Err(_) => {
self.items.push((ItemKind::Err, span));
}
}
diff --git a/compiler/rustc_passes/src/reachable.rs b/compiler/rustc_passes/src/reachable.rs
index ad0952203..051100c56 100644
--- a/compiler/rustc_passes/src/reachable.rs
+++ b/compiler/rustc_passes/src/reachable.rs
@@ -320,31 +320,28 @@ fn check_item<'tcx>(
worklist.push(id.owner_id.def_id);
}
- if !matches!(tcx.def_kind(id.owner_id), DefKind::Impl) {
+ if !matches!(tcx.def_kind(id.owner_id), DefKind::Impl { of_trait: true }) {
return;
}
// We need only trait impls here, not inherent impls, and only non-exported ones
- let item = tcx.hir().item(id);
- if let hir::ItemKind::Impl(hir::Impl { of_trait: Some(ref trait_ref), ref items, .. }) =
- item.kind
- {
- if !effective_visibilities.is_reachable(item.owner_id.def_id) {
- worklist.extend(items.iter().map(|ii_ref| ii_ref.id.owner_id.def_id));
+ if effective_visibilities.is_reachable(id.owner_id.def_id) {
+ return;
+ }
- let Res::Def(DefKind::Trait, trait_def_id) = trait_ref.path.res else {
- unreachable!();
- };
+ let items = tcx.associated_item_def_ids(id.owner_id);
+ worklist.extend(items.iter().map(|ii_ref| ii_ref.expect_local()));
- if !trait_def_id.is_local() {
- return;
- }
+ let Some(trait_def_id) = tcx.trait_id_of_impl(id.owner_id.to_def_id()) else {
+ unreachable!();
+ };
- worklist.extend(
- tcx.provided_trait_methods(trait_def_id).map(|assoc| assoc.def_id.expect_local()),
- );
- }
+ if !trait_def_id.is_local() {
+ return;
}
+
+ worklist
+ .extend(tcx.provided_trait_methods(trait_def_id).map(|assoc| assoc.def_id.expect_local()));
}
fn has_custom_linkage(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool {
diff --git a/compiler/rustc_passes/src/stability.rs b/compiler/rustc_passes/src/stability.rs
index 34e1abb78..16194a6f1 100644
--- a/compiler/rustc_passes/src/stability.rs
+++ b/compiler/rustc_passes/src/stability.rs
@@ -1,12 +1,7 @@
//! A pass that annotates every item and method with its stability level,
//! propagating default levels lexically from parent to children ast nodes.
-use crate::errors::{
- self, CannotStabilizeDeprecated, DeprecatedAttribute, DuplicateFeatureErr,
- FeatureOnlyOnNightly, ImpliedFeatureNotExist, InvalidDeprecationVersion, InvalidStability,
- MissingConstErr, MissingConstStabAttr, MissingStabilityAttr, TraitImplConstStable,
- UnknownFeature, UselessStability,
-};
+use crate::errors;
use rustc_attr::{
self as attr, rust_version_symbol, ConstStability, Stability, StabilityLevel, Unstable,
UnstableReason, VERSION_PLACEHOLDER,
@@ -125,7 +120,7 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> {
if let Some((depr, span)) = &depr {
is_deprecated = true;
- if kind == AnnotationKind::Prohibited || kind == AnnotationKind::DeprecationProhibited {
+ if matches!(kind, AnnotationKind::Prohibited | AnnotationKind::DeprecationProhibited) {
let hir_id = self.tcx.hir().local_def_id_to_hir_id(def_id);
self.tcx.emit_spanned_lint(
USELESS_DEPRECATED,
@@ -185,7 +180,7 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> {
{
self.tcx
.sess
- .emit_err(MissingConstErr { fn_sig_span: fn_sig.span, const_span });
+ .emit_err(errors::MissingConstErr { fn_sig_span: fn_sig.span, const_span });
}
}
}
@@ -203,7 +198,7 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> {
if let Some((rustc_attr::Deprecation { is_since_rustc_version: true, .. }, span)) = &depr {
if stab.is_none() {
- self.tcx.sess.emit_err(DeprecatedAttribute { span: *span });
+ self.tcx.sess.emit_err(errors::DeprecatedAttribute { span: *span });
}
}
@@ -219,7 +214,7 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> {
if kind == AnnotationKind::Prohibited
|| (kind == AnnotationKind::Container && stab.level.is_stable() && is_deprecated)
{
- self.tcx.sess.emit_err(UselessStability { span, item_sp });
+ self.tcx.sess.emit_err(errors::UselessStability { span, item_sp });
}
debug!("annotate: found {:?}", stab);
@@ -235,15 +230,16 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> {
{
match stab_v.parse::<u64>() {
Err(_) => {
- self.tcx.sess.emit_err(InvalidStability { span, item_sp });
+ self.tcx.sess.emit_err(errors::InvalidStability { span, item_sp });
break;
}
Ok(stab_vp) => match dep_v.parse::<u64>() {
Ok(dep_vp) => match dep_vp.cmp(&stab_vp) {
Ordering::Less => {
- self.tcx
- .sess
- .emit_err(CannotStabilizeDeprecated { span, item_sp });
+ self.tcx.sess.emit_err(errors::CannotStabilizeDeprecated {
+ span,
+ item_sp,
+ });
break;
}
Ordering::Equal => continue,
@@ -251,9 +247,10 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> {
},
Err(_) => {
if dep_v != "TBD" {
- self.tcx
- .sess
- .emit_err(InvalidDeprecationVersion { span, item_sp });
+ self.tcx.sess.emit_err(errors::InvalidDeprecationVersion {
+ span,
+ item_sp,
+ });
}
break;
}
@@ -284,7 +281,7 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> {
self.recurse_with_stability_attrs(
depr.map(|(d, _)| DeprecationEntry::local(d, def_id)),
stab,
- if inherit_const_stability.yes() { const_stab } else { None },
+ inherit_const_stability.yes().then_some(const_stab).flatten(),
visit_children,
);
}
@@ -526,8 +523,8 @@ impl<'tcx> MissingStabilityAnnotations<'tcx> {
&& stab.is_none()
&& self.effective_visibilities.is_reachable(def_id)
{
- let descr = self.tcx.def_kind(def_id).descr(def_id.to_def_id());
- self.tcx.sess.emit_err(MissingStabilityAttr { span, descr });
+ let descr = self.tcx.def_descr(def_id.to_def_id());
+ self.tcx.sess.emit_err(errors::MissingStabilityAttr { span, descr });
}
}
@@ -540,7 +537,7 @@ impl<'tcx> MissingStabilityAnnotations<'tcx> {
// then it would be "stable" at least for the impl.
// We gate usages of it using `feature(const_trait_impl)` anyways
// so there is no unstable leakage
- if self.tcx.is_builtin_derive(def_id.to_def_id()) {
+ if self.tcx.is_automatically_derived(def_id.to_def_id()) {
return;
}
@@ -554,8 +551,8 @@ impl<'tcx> MissingStabilityAnnotations<'tcx> {
let is_reachable = self.effective_visibilities.is_reachable(def_id);
if is_const && is_stable && missing_const_stability_attribute && is_reachable {
- let descr = self.tcx.def_kind(def_id).descr(def_id.to_def_id());
- self.tcx.sess.emit_err(MissingConstStabAttr { span, descr });
+ let descr = self.tcx.def_descr(def_id.to_def_id());
+ self.tcx.sess.emit_err(errors::MissingConstStabAttr { span, descr });
}
}
}
@@ -751,7 +748,10 @@ impl<'tcx> Visitor<'tcx> for Checker<'tcx> {
let mut c = CheckTraitImplStable { tcx: self.tcx, fully_stable: true };
c.visit_ty(self_ty);
c.visit_trait_ref(t);
- if c.fully_stable {
+
+ // do not lint when the trait isn't resolved, since resolution error should
+ // be fixed first
+ if t.path.res != Res::Err && c.fully_stable {
self.tcx.struct_span_lint_hir(
INEFFECTIVE_UNSTABLE_TRAIT_IMPL,
item.hir_id(),
@@ -768,7 +768,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'tcx> {
&& *constness == hir::Constness::Const
&& const_stab.map_or(false, |(stab, _)| stab.is_const_stable())
{
- self.tcx.sess.emit_err(TraitImplConstStable { span: item.span });
+ self.tcx.sess.emit_err(errors::TraitImplConstStable { span: item.span });
}
}
@@ -855,7 +855,8 @@ impl<'tcx> Visitor<'tcx> for Checker<'tcx> {
/// See issue #94972 for details on why this is a special case
fn is_unstable_reexport(tcx: TyCtxt<'_>, id: hir::HirId) -> bool {
// Get the LocalDefId so we can lookup the item to check the kind.
- let Some(def_id) = tcx.hir().opt_local_def_id(id) else { return false; };
+ let Some(owner) = id.as_owner() else { return false; };
+ let def_id = owner.def_id;
let Some(stab) = tcx.stability().local_stability(def_id) else {
return false;
@@ -946,7 +947,7 @@ pub fn check_unused_or_stable_features(tcx: TyCtxt<'_>) {
}
if !lang_features.insert(feature) {
// Warn if the user enables a lang feature multiple times.
- tcx.sess.emit_err(DuplicateFeatureErr { span, feature });
+ tcx.sess.emit_err(errors::DuplicateFeatureErr { span, feature });
}
}
@@ -954,14 +955,14 @@ pub fn check_unused_or_stable_features(tcx: TyCtxt<'_>) {
let mut remaining_lib_features = FxIndexMap::default();
for (feature, span) in declared_lib_features {
if !tcx.sess.opts.unstable_features.is_nightly_build() {
- tcx.sess.emit_err(FeatureOnlyOnNightly {
+ tcx.sess.emit_err(errors::FeatureOnlyOnNightly {
span: *span,
release_channel: env!("CFG_RELEASE_CHANNEL"),
});
}
if remaining_lib_features.contains_key(&feature) {
// Warn if the user enables a lib feature multiple times.
- tcx.sess.emit_err(DuplicateFeatureErr { span: *span, feature: *feature });
+ tcx.sess.emit_err(errors::DuplicateFeatureErr { span: *span, feature: *feature });
}
remaining_lib_features.insert(feature, *span);
}
@@ -1062,7 +1063,7 @@ pub fn check_unused_or_stable_features(tcx: TyCtxt<'_>) {
}
for (feature, span) in remaining_lib_features {
- tcx.sess.emit_err(UnknownFeature { span, feature: *feature });
+ tcx.sess.emit_err(errors::UnknownFeature { span, feature: *feature });
}
for (implied_by, feature) in remaining_implications {
@@ -1073,7 +1074,7 @@ pub fn check_unused_or_stable_features(tcx: TyCtxt<'_>) {
.map(|(_, span)| span)
.or_else(|| local_defined_features.unstable.get(&feature))
.expect("feature that implied another does not exist");
- tcx.sess.emit_err(ImpliedFeatureNotExist { span, feature, implied_by });
+ tcx.sess.emit_err(errors::ImpliedFeatureNotExist { span, feature, implied_by });
}
// FIXME(#44232): the `used_features` table no longer exists, so we
diff --git a/compiler/rustc_error_messages/locales/en-US/plugin_impl.ftl b/compiler/rustc_plugin_impl/locales/en-US.ftl
index 8db32a42c..8db32a42c 100644
--- a/compiler/rustc_error_messages/locales/en-US/plugin_impl.ftl
+++ b/compiler/rustc_plugin_impl/locales/en-US.ftl
diff --git a/compiler/rustc_plugin_impl/src/lib.rs b/compiler/rustc_plugin_impl/src/lib.rs
index 9ac27c65d..3f03eef9e 100644
--- a/compiler/rustc_plugin_impl/src/lib.rs
+++ b/compiler/rustc_plugin_impl/src/lib.rs
@@ -11,11 +11,15 @@
#![deny(rustc::untranslatable_diagnostic)]
#![deny(rustc::diagnostic_outside_of_impl)]
+use rustc_errors::{DiagnosticMessage, SubdiagnosticMessage};
use rustc_lint::LintStore;
+use rustc_macros::fluent_messages;
mod errors;
pub mod load;
+fluent_messages! { "../locales/en-US.ftl" }
+
/// Structure used to register plugins.
///
/// A plugin registrar function takes an `&mut Registry` and should call
diff --git a/compiler/rustc_privacy/Cargo.toml b/compiler/rustc_privacy/Cargo.toml
index 832fdc9f0..744cb77dd 100644
--- a/compiler/rustc_privacy/Cargo.toml
+++ b/compiler/rustc_privacy/Cargo.toml
@@ -13,6 +13,5 @@ rustc_macros = { path = "../rustc_macros" }
rustc_middle = { path = "../rustc_middle" }
rustc_session = { path = "../rustc_session" }
rustc_span = { path = "../rustc_span" }
-rustc_trait_selection = { path = "../rustc_trait_selection" }
rustc_hir_analysis = { path = "../rustc_hir_analysis" }
tracing = "0.1"
diff --git a/compiler/rustc_error_messages/locales/en-US/privacy.ftl b/compiler/rustc_privacy/locales/en-US.ftl
index a26d1b2b3..a26d1b2b3 100644
--- a/compiler/rustc_error_messages/locales/en-US/privacy.ftl
+++ b/compiler/rustc_privacy/locales/en-US.ftl
diff --git a/compiler/rustc_privacy/src/errors.rs b/compiler/rustc_privacy/src/errors.rs
index a6c95f1a8..72b53eefa 100644
--- a/compiler/rustc_privacy/src/errors.rs
+++ b/compiler/rustc_privacy/src/errors.rs
@@ -57,7 +57,7 @@ pub struct InPublicInterfaceTraits<'a> {
pub vis_descr: &'static str,
pub kind: &'a str,
pub descr: DiagnosticArgFromDisplay<'a>,
- #[label(visibility_label)]
+ #[label(privacy_visibility_label)]
pub vis_span: Span,
}
@@ -71,7 +71,7 @@ pub struct InPublicInterface<'a> {
pub vis_descr: &'static str,
pub kind: &'a str,
pub descr: DiagnosticArgFromDisplay<'a>,
- #[label(visibility_label)]
+ #[label(privacy_visibility_label)]
pub vis_span: Span,
}
diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs
index 9a5d3cceb..50176c802 100644
--- a/compiler/rustc_privacy/src/lib.rs
+++ b/compiler/rustc_privacy/src/lib.rs
@@ -16,11 +16,13 @@ use rustc_ast::MacroDef;
use rustc_attr as attr;
use rustc_data_structures::fx::FxHashSet;
use rustc_data_structures::intern::Interned;
+use rustc_errors::{DiagnosticMessage, SubdiagnosticMessage};
use rustc_hir as hir;
use rustc_hir::def::{DefKind, Res};
-use rustc_hir::def_id::{DefId, LocalDefId, LocalDefIdSet, CRATE_DEF_ID};
+use rustc_hir::def_id::{DefId, LocalDefId, CRATE_DEF_ID};
use rustc_hir::intravisit::{self, Visitor};
use rustc_hir::{AssocItemKind, HirIdSet, ItemId, Node, PatKind};
+use rustc_macros::fluent_messages;
use rustc_middle::bug;
use rustc_middle::hir::nested_filter;
use rustc_middle::middle::privacy::{EffectiveVisibilities, Level};
@@ -44,6 +46,8 @@ use errors::{
UnnamedItemIsPrivate,
};
+fluent_messages! { "../locales/en-US.ftl" }
+
////////////////////////////////////////////////////////////////////////////////
/// Generic infrastructure used to implement specific visitors below.
////////////////////////////////////////////////////////////////////////////////
@@ -81,7 +85,10 @@ trait DefIdVisitor<'tcx> {
dummy: Default::default(),
}
}
- fn visit(&mut self, ty_fragment: impl TypeVisitable<'tcx>) -> ControlFlow<Self::BreakTy> {
+ fn visit(
+ &mut self,
+ ty_fragment: impl TypeVisitable<TyCtxt<'tcx>>,
+ ) -> ControlFlow<Self::BreakTy> {
ty_fragment.visit_with(&mut self.skeleton())
}
fn visit_trait(&mut self, trait_ref: TraitRef<'tcx>) -> ControlFlow<Self::BreakTy> {
@@ -159,9 +166,21 @@ where
_region,
))) => ty.visit_with(self),
ty::PredicateKind::Clause(ty::Clause::RegionOutlives(..)) => ControlFlow::Continue(()),
+ ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(ct, ty)) => {
+ ct.visit_with(self)?;
+ ty.visit_with(self)
+ }
ty::PredicateKind::ConstEvaluatable(ct) => ct.visit_with(self),
ty::PredicateKind::WellFormed(arg) => arg.visit_with(self),
- _ => bug!("unexpected predicate: {:?}", predicate),
+
+ ty::PredicateKind::ObjectSafe(_)
+ | ty::PredicateKind::ClosureKind(_, _, _)
+ | ty::PredicateKind::Subtype(_)
+ | ty::PredicateKind::Coerce(_)
+ | ty::PredicateKind::ConstEquate(_, _)
+ | ty::PredicateKind::TypeWellFormedFromEnv(_)
+ | ty::PredicateKind::Ambiguous
+ | ty::PredicateKind::AliasEq(_, _) => bug!("unexpected predicate: {:?}", predicate),
}
}
@@ -174,7 +193,7 @@ where
}
}
-impl<'tcx, V> TypeVisitor<'tcx> for DefIdVisitorSkeleton<'_, 'tcx, V>
+impl<'tcx, V> TypeVisitor<TyCtxt<'tcx>> for DefIdVisitorSkeleton<'_, 'tcx, V>
where
V: DefIdVisitor<'tcx> + ?Sized,
{
@@ -198,7 +217,8 @@ where
// Something like `fn() -> Priv {my_func}` is considered a private type even if
// `my_func` is public, so we need to visit signatures.
if let ty::FnDef(..) = ty.kind() {
- tcx.fn_sig(def_id).visit_with(self)?;
+ // FIXME: this should probably use `substs` from `FnDef`
+ tcx.fn_sig(def_id).subst_identity().visit_with(self)?;
}
// Inherent static methods don't have self type in substs.
// Something like `fn() {my_method}` type of the method
@@ -206,7 +226,7 @@ where
// so we need to visit the self type additionally.
if let Some(assoc_item) = tcx.opt_associated_item(def_id) {
if let Some(impl_def_id) = assoc_item.impl_container(tcx) {
- tcx.type_of(impl_def_id).visit_with(self)?;
+ tcx.type_of(impl_def_id).subst_identity().visit_with(self)?;
}
}
}
@@ -269,9 +289,11 @@ where
| ty::Ref(..)
| ty::FnPtr(..)
| ty::Param(..)
+ | ty::Bound(..)
| ty::Error(_)
- | ty::GeneratorWitness(..) => {}
- ty::Bound(..) | ty::Placeholder(..) | ty::Infer(..) => {
+ | ty::GeneratorWitness(..)
+ | ty::GeneratorWitnessMIR(..) => {}
+ ty::Placeholder(..) | ty::Infer(..) => {
bug!("unexpected type: {:?}", ty)
}
}
@@ -339,7 +361,7 @@ trait VisibilityLike: Sized {
effective_visibilities: &EffectiveVisibilities,
) -> Self {
let mut find = FindMin { tcx, effective_visibilities, min: Self::MAX };
- find.visit(tcx.type_of(def_id));
+ find.visit(tcx.type_of(def_id).subst_identity());
if let Some(trait_ref) = tcx.impl_trait_ref(def_id) {
find.visit_trait(trait_ref.subst_identity());
}
@@ -591,7 +613,7 @@ impl<'tcx> EmbargoVisitor<'tcx> {
| DefKind::InlineConst
| DefKind::Field
| DefKind::GlobalAsm
- | DefKind::Impl
+ | DefKind::Impl { .. }
| DefKind::Closure
| DefKind::Generator => (),
}
@@ -835,11 +857,11 @@ impl ReachEverythingInTheInterfaceVisitor<'_, '_> {
GenericParamDefKind::Lifetime => {}
GenericParamDefKind::Type { has_default, .. } => {
if has_default {
- self.visit(self.ev.tcx.type_of(param.def_id));
+ self.visit(self.ev.tcx.type_of(param.def_id).subst_identity());
}
}
GenericParamDefKind::Const { has_default } => {
- self.visit(self.ev.tcx.type_of(param.def_id));
+ self.visit(self.ev.tcx.type_of(param.def_id).subst_identity());
if has_default {
self.visit(self.ev.tcx.const_param_default(param.def_id).subst_identity());
}
@@ -855,7 +877,7 @@ impl ReachEverythingInTheInterfaceVisitor<'_, '_> {
}
fn ty(&mut self) -> &mut Self {
- self.visit(self.ev.tcx.type_of(self.item_def_id));
+ self.visit(self.ev.tcx.type_of(self.item_def_id).subst_identity());
self
}
@@ -1266,7 +1288,7 @@ impl<'tcx> Visitor<'tcx> for TypePrivacyVisitor<'tcx> {
// Method calls have to be checked specially.
self.span = segment.ident.span;
if let Some(def_id) = self.typeck_results().type_dependent_def_id(expr.hir_id) {
- if self.visit(self.tcx.type_of(def_id)).is_break() {
+ if self.visit(self.tcx.type_of(def_id).subst_identity()).is_break() {
return;
}
} else {
@@ -1314,7 +1336,7 @@ impl<'tcx> Visitor<'tcx> for TypePrivacyVisitor<'tcx> {
hir::QPath::Resolved(_, path) => Some(self.tcx.def_path_str(path.res.def_id())),
hir::QPath::TypeRelative(_, segment) => Some(segment.ident.to_string()),
};
- let kind = kind.descr(def_id);
+ let kind = self.tcx.def_descr(def_id);
let sess = self.tcx.sess;
let _ = match name {
Some(name) => {
@@ -1740,12 +1762,12 @@ impl SearchInterfaceForPrivateItemsVisitor<'_> {
GenericParamDefKind::Lifetime => {}
GenericParamDefKind::Type { has_default, .. } => {
if has_default {
- self.visit(self.tcx.type_of(param.def_id));
+ self.visit(self.tcx.type_of(param.def_id).subst_identity());
}
}
// FIXME(generic_const_exprs): May want to look inside const here
GenericParamDefKind::Const { .. } => {
- self.visit(self.tcx.type_of(param.def_id));
+ self.visit(self.tcx.type_of(param.def_id).subst_identity());
}
}
}
@@ -1772,7 +1794,7 @@ impl SearchInterfaceForPrivateItemsVisitor<'_> {
}
fn ty(&mut self) -> &mut Self {
- self.visit(self.tcx.type_of(self.item_def_id));
+ self.visit(self.tcx.type_of(self.item_def_id).subst_identity());
self
}
@@ -1877,7 +1899,7 @@ impl<'tcx> DefIdVisitor<'tcx> for SearchInterfaceForPrivateItemsVisitor<'tcx> {
struct PrivateItemsInPublicInterfacesChecker<'tcx> {
tcx: TyCtxt<'tcx>,
- old_error_set_ancestry: LocalDefIdSet,
+ old_error_set_ancestry: HirIdSet,
}
impl<'tcx> PrivateItemsInPublicInterfacesChecker<'tcx> {
@@ -1890,7 +1912,9 @@ impl<'tcx> PrivateItemsInPublicInterfacesChecker<'tcx> {
tcx: self.tcx,
item_def_id: def_id,
required_visibility,
- has_old_errors: self.old_error_set_ancestry.contains(&def_id),
+ has_old_errors: self
+ .old_error_set_ancestry
+ .contains(&self.tcx.hir().local_def_id_to_hir_id(def_id)),
in_assoc_ty: false,
}
}
@@ -1993,7 +2017,7 @@ impl<'tcx> PrivateItemsInPublicInterfacesChecker<'tcx> {
// Subitems of inherent impls have their own publicity.
// A trait impl is public when both its type and its trait are public
// Subitems of trait impls have inherited publicity.
- DefKind::Impl => {
+ DefKind::Impl { .. } => {
let item = tcx.hir().item(id);
if let hir::ItemKind::Impl(ref impl_) = item.kind {
let impl_vis =
@@ -2156,15 +2180,7 @@ fn check_private_in_public(tcx: TyCtxt<'_>, (): ()) {
}
// Check for private types and traits in public interfaces.
- let mut checker = PrivateItemsInPublicInterfacesChecker {
- tcx,
- // Only definition IDs are ever searched in `old_error_set_ancestry`,
- // so we can filter away all non-definition IDs at this point.
- old_error_set_ancestry: old_error_set_ancestry
- .into_iter()
- .filter_map(|hir_id| tcx.hir().opt_local_def_id(hir_id))
- .collect(),
- };
+ let mut checker = PrivateItemsInPublicInterfacesChecker { tcx, old_error_set_ancestry };
for id in tcx.hir().items() {
checker.check_item(id);
diff --git a/compiler/rustc_query_impl/Cargo.toml b/compiler/rustc_query_impl/Cargo.toml
index 46e776264..3e8a88c7e 100644
--- a/compiler/rustc_query_impl/Cargo.toml
+++ b/compiler/rustc_query_impl/Cargo.toml
@@ -20,8 +20,7 @@ rustc-rayon-core = { version = "0.4.0", optional = true }
rustc_serialize = { path = "../rustc_serialize" }
rustc_session = { path = "../rustc_session" }
rustc_span = { path = "../rustc_span" }
-rustc_target = { path = "../rustc_target" }
-thin-vec = "0.2.9"
+thin-vec = "0.2.12"
tracing = "0.1"
[features]
diff --git a/compiler/rustc_query_impl/src/lib.rs b/compiler/rustc_query_impl/src/lib.rs
index 2d243e13c..d7708a3bc 100644
--- a/compiler/rustc_query_impl/src/lib.rs
+++ b/compiler/rustc_query_impl/src/lib.rs
@@ -21,7 +21,9 @@ use rustc_data_structures::sync::AtomicU64;
use rustc_middle::arena::Arena;
use rustc_middle::dep_graph::{self, DepKindStruct};
use rustc_middle::query::Key;
-use rustc_middle::ty::query::{query_keys, query_storage, query_stored, query_values};
+use rustc_middle::ty::query::{
+ query_keys, query_provided, query_provided_to_value, query_storage, query_values,
+};
use rustc_middle::ty::query::{ExternProviders, Providers, QueryEngine};
use rustc_middle::ty::TyCtxt;
use rustc_span::Span;
diff --git a/compiler/rustc_query_impl/src/on_disk_cache.rs b/compiler/rustc_query_impl/src/on_disk_cache.rs
index 70c481fb0..46e34462c 100644
--- a/compiler/rustc_query_impl/src/on_disk_cache.rs
+++ b/compiler/rustc_query_impl/src/on_disk_cache.rs
@@ -333,7 +333,7 @@ impl<'sess> rustc_middle::ty::OnDiskCache<'sess> for OnDiskCache<'sess> {
},
);
- // `Encode the file footer.
+ // Encode the file footer.
let footer_pos = encoder.position() as u64;
encoder.encode_tagged(
TAG_FILE_FOOTER,
diff --git a/compiler/rustc_query_impl/src/plumbing.rs b/compiler/rustc_query_impl/src/plumbing.rs
index 6125ad4ef..a8592bd70 100644
--- a/compiler/rustc_query_impl/src/plumbing.rs
+++ b/compiler/rustc_query_impl/src/plumbing.rs
@@ -53,7 +53,7 @@ impl<'tcx> HasDepContext for QueryCtxt<'tcx> {
}
impl QueryContext for QueryCtxt<'_> {
- fn next_job_id(&self) -> QueryJobId {
+ fn next_job_id(self) -> QueryJobId {
QueryJobId(
NonZeroU64::new(
self.queries.jobs.fetch_add(1, rustc_data_structures::sync::Ordering::Relaxed),
@@ -62,31 +62,31 @@ impl QueryContext for QueryCtxt<'_> {
)
}
- fn current_query_job(&self) -> Option<QueryJobId> {
- tls::with_related_context(**self, |icx| icx.query)
+ fn current_query_job(self) -> Option<QueryJobId> {
+ tls::with_related_context(*self, |icx| icx.query)
}
- fn try_collect_active_jobs(&self) -> Option<QueryMap<DepKind>> {
- self.queries.try_collect_active_jobs(**self)
+ fn try_collect_active_jobs(self) -> Option<QueryMap<DepKind>> {
+ self.queries.try_collect_active_jobs(*self)
}
// Interactions with on_disk_cache
- fn load_side_effects(&self, prev_dep_node_index: SerializedDepNodeIndex) -> QuerySideEffects {
+ fn load_side_effects(self, prev_dep_node_index: SerializedDepNodeIndex) -> QuerySideEffects {
self.queries
.on_disk_cache
.as_ref()
- .map(|c| c.load_side_effects(**self, prev_dep_node_index))
+ .map(|c| c.load_side_effects(*self, prev_dep_node_index))
.unwrap_or_default()
}
- fn store_side_effects(&self, dep_node_index: DepNodeIndex, side_effects: QuerySideEffects) {
+ fn store_side_effects(self, dep_node_index: DepNodeIndex, side_effects: QuerySideEffects) {
if let Some(c) = self.queries.on_disk_cache.as_ref() {
c.store_side_effects(dep_node_index, side_effects)
}
}
fn store_side_effects_for_anon_node(
- &self,
+ self,
dep_node_index: DepNodeIndex,
side_effects: QuerySideEffects,
) {
@@ -100,7 +100,7 @@ impl QueryContext for QueryCtxt<'_> {
/// captured during execution and the actual result.
#[inline(always)]
fn start_query<R>(
- &self,
+ self,
token: QueryJobId,
depth_limit: bool,
diagnostics: Option<&Lock<ThinVec<Diagnostic>>>,
@@ -109,14 +109,14 @@ impl QueryContext for QueryCtxt<'_> {
// The `TyCtxt` stored in TLS has the same global interner lifetime
// as `self`, so we use `with_related_context` to relate the 'tcx lifetimes
// when accessing the `ImplicitCtxt`.
- tls::with_related_context(**self, move |current_icx| {
+ tls::with_related_context(*self, move |current_icx| {
if depth_limit && !self.recursion_limit().value_within_limit(current_icx.query_depth) {
self.depth_limit_error(token);
}
// Update the `ImplicitCtxt` to point to our new query job.
let new_icx = ImplicitCtxt {
- tcx: **self,
+ tcx: *self,
query: Some(token),
diagnostics,
query_depth: current_icx.query_depth + depth_limit as usize,
@@ -124,13 +124,11 @@ impl QueryContext for QueryCtxt<'_> {
};
// Use the `ImplicitCtxt` while we execute the query.
- tls::enter_context(&new_icx, |_| {
- rustc_data_structures::stack::ensure_sufficient_stack(compute)
- })
+ tls::enter_context(&new_icx, compute)
})
}
- fn depth_limit_error(&self, job: QueryJobId) {
+ fn depth_limit_error(self, job: QueryJobId) {
let mut span = None;
let mut layout_of_depth = None;
if let Some(map) = self.try_collect_active_jobs() {
@@ -293,14 +291,14 @@ macro_rules! get_provider {
}
macro_rules! should_ever_cache_on_disk {
- ([]) => {{
- None
+ ([]$yes:tt $no:tt) => {{
+ $no
}};
- ([(cache) $($rest:tt)*]) => {{
- Some($crate::plumbing::try_load_from_disk::<Self::Value>)
+ ([(cache) $($rest:tt)*]$yes:tt $no:tt) => {{
+ $yes
}};
- ([$other:tt $($modifiers:tt)*]) => {
- should_ever_cache_on_disk!([$($modifiers)*])
+ ([$other:tt $($modifiers:tt)*]$yes:tt $no:tt) => {
+ should_ever_cache_on_disk!([$($modifiers)*]$yes $no)
};
}
@@ -314,11 +312,14 @@ pub(crate) fn create_query_frame<
kind: DepKind,
name: &'static str,
) -> QueryStackFrame<DepKind> {
- // 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!(
- // Force filename-line mode to avoid invoking `type_of` query.
- ty::print::with_forced_impl_filename_line!(do_describe(tcx.tcx, key))
+ // Avoid calling queries while formatting the description
+ let description = ty::print::with_no_queries!(
+ // Disable visible paths printing for performance reasons.
+ // Showing visible path instead of any path is not that important in production.
+ ty::print::with_no_visible_paths!(
+ // Force filename-line mode to avoid invoking `type_of` query.
+ ty::print::with_forced_impl_filename_line!(do_describe(tcx.tcx, key))
+ )
);
let description =
if tcx.sess.verbose() { format!("{description} [{name:?}]") } else { description };
@@ -469,7 +470,6 @@ macro_rules! define_queries {
$(impl<'tcx> QueryConfig<QueryCtxt<'tcx>> for queries::$name<'tcx> {
type Key = query_keys::$name<'tcx>;
type Value = query_values::$name<'tcx>;
- type Stored = query_stored::$name<'tcx>;
const NAME: &'static str = stringify!($name);
#[inline]
@@ -490,24 +490,39 @@ macro_rules! define_queries {
fn query_cache<'a>(tcx: QueryCtxt<'tcx>) -> &'a Self::Cache
where 'tcx:'a
{
- &tcx.query_caches.$name
+ &tcx.query_system.caches.$name
}
- fn execute_query(tcx: TyCtxt<'tcx>, key: Self::Key) -> Self::Stored {
+ fn execute_query(tcx: TyCtxt<'tcx>, key: Self::Key) -> Self::Value {
tcx.$name(key)
}
#[inline]
- // key is only sometimes used
#[allow(unused_variables)]
- fn compute(qcx: QueryCtxt<'tcx>, key: &Self::Key) -> fn(TyCtxt<'tcx>, Self::Key) -> Self::Value {
- get_provider!([$($modifiers)*][qcx, $name, key])
+ fn compute(qcx: QueryCtxt<'tcx>, key: Self::Key) -> Self::Value {
+ query_provided_to_value::$name(
+ qcx.tcx,
+ get_provider!([$($modifiers)*][qcx, $name, key])(qcx.tcx, key)
+ )
}
#[inline]
- fn try_load_from_disk(qcx: QueryCtxt<'tcx>, key: &Self::Key) -> rustc_query_system::query::TryLoadFromDisk<QueryCtxt<'tcx>, Self> {
- let cache_on_disk = Self::cache_on_disk(qcx.tcx, key);
- if cache_on_disk { should_ever_cache_on_disk!([$($modifiers)*]) } else { None }
+ fn try_load_from_disk(_qcx: QueryCtxt<'tcx>, _key: &Self::Key) -> rustc_query_system::query::TryLoadFromDisk<QueryCtxt<'tcx>, Self> {
+ should_ever_cache_on_disk!([$($modifiers)*] {
+ if Self::cache_on_disk(_qcx.tcx, _key) {
+ Some(|qcx: QueryCtxt<'tcx>, dep_node| {
+ let value = $crate::plumbing::try_load_from_disk::<query_provided::$name<'tcx>>(
+ qcx,
+ dep_node
+ );
+ value.map(|value| query_provided_to_value::$name(qcx.tcx, value))
+ })
+ } else {
+ None
+ }
+ } {
+ None
+ })
}
const ANON: bool = is_anon!([$($modifiers)*]);
@@ -630,7 +645,7 @@ macro_rules! define_queries {
$crate::profiling_support::alloc_self_profile_query_strings_for_query_cache(
tcx,
stringify!($name),
- &tcx.query_caches.$name,
+ &tcx.query_system.caches.$name,
string_cache,
)
},
@@ -722,7 +737,7 @@ macro_rules! define_queries_struct {
span: Span,
key: <queries::$name<'tcx> as QueryConfig<QueryCtxt<'tcx>>>::Key,
mode: QueryMode,
- ) -> Option<query_stored::$name<'tcx>> {
+ ) -> Option<query_values::$name<'tcx>> {
let qcx = QueryCtxt { tcx, queries: self };
get_query::<queries::$name<'tcx>, _, rustc_middle::dep_graph::DepKind>(qcx, span, key, mode)
})*
diff --git a/compiler/rustc_query_system/Cargo.toml b/compiler/rustc_query_system/Cargo.toml
index 028756b5a..7d8f75e25 100644
--- a/compiler/rustc_query_system/Cargo.toml
+++ b/compiler/rustc_query_system/Cargo.toml
@@ -22,7 +22,7 @@ rustc_span = { path = "../rustc_span" }
rustc_target = { path = "../rustc_target" }
rustc_type_ir = { path = "../rustc_type_ir" }
smallvec = { version = "1.8.1", features = ["union", "may_dangle"] }
-thin-vec = "0.2.9"
+thin-vec = "0.2.12"
tracing = "0.1"
[features]
diff --git a/compiler/rustc_error_messages/locales/en-US/query_system.ftl b/compiler/rustc_query_system/locales/en-US.ftl
index 870e82403..870e82403 100644
--- a/compiler/rustc_error_messages/locales/en-US/query_system.ftl
+++ b/compiler/rustc_query_system/locales/en-US.ftl
diff --git a/compiler/rustc_query_system/src/dep_graph/graph.rs b/compiler/rustc_query_system/src/dep_graph/graph.rs
index 47b2fd8f8..59e0c3597 100644
--- a/compiler/rustc_query_system/src/dep_graph/graph.rs
+++ b/compiler/rustc_query_system/src/dep_graph/graph.rs
@@ -6,6 +6,7 @@ use rustc_data_structures::sharded::{self, Sharded};
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
use rustc_data_structures::steal::Steal;
use rustc_data_structures::sync::{AtomicU32, AtomicU64, Lock, Lrc, Ordering};
+use rustc_data_structures::OnDrop;
use rustc_index::vec::IndexVec;
use rustc_serialize::opaque::{FileEncodeResult, FileEncoder};
use smallvec::{smallvec, SmallVec};
@@ -47,7 +48,7 @@ impl DepNodeIndex {
}
impl From<DepNodeIndex> for QueryInvocationId {
- #[inline]
+ #[inline(always)]
fn from(dep_node_index: DepNodeIndex) -> Self {
QueryInvocationId(dep_node_index.as_u32())
}
@@ -278,6 +279,7 @@ impl<K: DepKind> DepGraph<K> {
/// `arg` parameter.
///
/// [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/incremental-compilation.html
+ #[inline(always)]
pub fn with_task<Ctxt: HasDepContext<DepKind = K>, A: Debug, R>(
&self,
key: DepNode<K>,
@@ -297,6 +299,7 @@ impl<K: DepKind> DepGraph<K> {
}
}
+ #[inline(always)]
fn with_task_impl<Ctxt: HasDepContext<DepKind = K>, A: Debug, R>(
&self,
key: DepNode<K>,
@@ -597,6 +600,7 @@ impl<K: DepKind> DepGraph<K> {
self.data.is_some() && self.dep_node_index_of_opt(dep_node).is_some()
}
+ #[inline]
pub fn prev_fingerprint_of(&self, dep_node: &DepNode<K>) -> Option<Fingerprint> {
self.data.as_ref().unwrap().previous.fingerprint_of(dep_node)
}
@@ -671,17 +675,24 @@ impl<K: DepKind> DepGraph<K> {
let prev_index = data.previous.node_to_index_opt(dep_node)?;
match data.colors.get(prev_index) {
- Some(DepNodeColor::Green(dep_node_index)) => Some((prev_index, dep_node_index)),
- Some(DepNodeColor::Red) => None,
- None => {
- // This DepNode and the corresponding query invocation existed
- // in the previous compilation session too, so we can try to
- // mark it as green by recursively marking all of its
- // dependencies green.
- self.try_mark_previous_green(qcx, data, prev_index, &dep_node)
- .map(|dep_node_index| (prev_index, dep_node_index))
- }
+ Some(DepNodeColor::Green(dep_node_index)) => return Some((prev_index, dep_node_index)),
+ Some(DepNodeColor::Red) => return None,
+ None => {}
}
+
+ let backtrace = backtrace_printer(qcx.dep_context().sess(), data, prev_index);
+
+ // This DepNode and the corresponding query invocation existed
+ // in the previous compilation session too, so we can try to
+ // mark it as green by recursively marking all of its
+ // dependencies green.
+ let ret = self
+ .try_mark_previous_green(qcx, data, prev_index, &dep_node)
+ .map(|dep_node_index| (prev_index, dep_node_index));
+
+ // We succeeded, no backtrace.
+ backtrace.disable();
+ return ret;
}
#[instrument(skip(self, qcx, data, parent_dep_node_index), level = "debug")]
@@ -794,7 +805,10 @@ impl<K: DepKind> DepGraph<K> {
let prev_deps = data.previous.edge_targets_from(prev_dep_node_index);
for &dep_dep_node_index in prev_deps {
- self.try_mark_parent_green(qcx, data, dep_dep_node_index, dep_node)?
+ let backtrace = backtrace_printer(qcx.dep_context().sess(), data, dep_dep_node_index);
+ let success = self.try_mark_parent_green(qcx, data, dep_dep_node_index, dep_node);
+ backtrace.disable();
+ success?;
}
// If we got here without hitting a `return` that means that all
@@ -1116,6 +1130,7 @@ impl<K: DepKind> CurrentDepGraph<K> {
/// Writes the node to the current dep-graph and allocates a `DepNodeIndex` for it.
/// Assumes that this is a node that has no equivalent in the previous dep-graph.
+ #[inline(always)]
fn intern_new_node(
&self,
profiler: &SelfProfilerRef,
@@ -1354,6 +1369,7 @@ impl DepNodeColorMap {
}
}
+ #[inline]
fn insert(&self, index: SerializedDepNodeIndex, color: DepNodeColor) {
self.values[index].store(
match color {
@@ -1364,3 +1380,26 @@ impl DepNodeColorMap {
)
}
}
+
+fn backtrace_printer<'a, K: DepKind>(
+ sess: &'a rustc_session::Session,
+ graph: &'a DepGraphData<K>,
+ node: SerializedDepNodeIndex,
+) -> OnDrop<impl Fn() + 'a> {
+ OnDrop(
+ #[inline(never)]
+ #[cold]
+ move || {
+ let node = graph.previous.index_to_node(node);
+ // Do not try to rely on DepNode's Debug implementation, since it may panic.
+ let diag = rustc_errors::Diagnostic::new(
+ rustc_errors::Level::FailureNote,
+ &format!(
+ "encountered while trying to mark dependency green: {:?}({})",
+ node.kind, node.hash
+ ),
+ );
+ sess.diagnostic().force_print_diagnostic(diag);
+ },
+ )
+}
diff --git a/compiler/rustc_query_system/src/dep_graph/mod.rs b/compiler/rustc_query_system/src/dep_graph/mod.rs
index e370c6990..6969f2dbe 100644
--- a/compiler/rustc_query_system/src/dep_graph/mod.rs
+++ b/compiler/rustc_query_system/src/dep_graph/mod.rs
@@ -23,7 +23,7 @@ pub trait DepContext: Copy {
type DepKind: self::DepKind;
/// Create a hashing context for hashing new results.
- fn with_stable_hashing_context<R>(&self, f: impl FnOnce(StableHashingContext<'_>) -> R) -> R;
+ fn with_stable_hashing_context<R>(self, f: impl FnOnce(StableHashingContext<'_>) -> R) -> R;
/// Access the DepGraph.
fn dep_graph(&self) -> &DepGraph<Self::DepKind>;
@@ -37,7 +37,7 @@ pub trait DepContext: Copy {
fn dep_kind_info(&self, dep_node: Self::DepKind) -> &DepKindStruct<Self>;
#[inline(always)]
- fn fingerprint_style(&self, kind: Self::DepKind) -> FingerprintStyle {
+ fn fingerprint_style(self, kind: Self::DepKind) -> FingerprintStyle {
let data = self.dep_kind_info(kind);
if data.is_anon {
return FingerprintStyle::Opaque;
@@ -47,7 +47,7 @@ pub trait DepContext: Copy {
#[inline(always)]
/// Return whether this kind always require evaluation.
- fn is_eval_always(&self, kind: Self::DepKind) -> bool {
+ fn is_eval_always(self, kind: Self::DepKind) -> bool {
self.dep_kind_info(kind).is_eval_always
}
diff --git a/compiler/rustc_query_system/src/dep_graph/serialized.rs b/compiler/rustc_query_system/src/dep_graph/serialized.rs
index a81595b24..29513df46 100644
--- a/compiler/rustc_query_system/src/dep_graph/serialized.rs
+++ b/compiler/rustc_query_system/src/dep_graph/serialized.rs
@@ -242,8 +242,7 @@ impl<K: DepKind + Encodable<FileEncoder>> GraphEncoder<K> {
record_graph: bool,
record_stats: bool,
) -> Self {
- let record_graph =
- if record_graph { Some(Lock::new(DepGraphQuery::new(prev_node_count))) } else { None };
+ let record_graph = record_graph.then(|| Lock::new(DepGraphQuery::new(prev_node_count)));
let status = Lock::new(EncoderState::new(encoder, record_stats));
GraphEncoder { status, record_graph }
}
diff --git a/compiler/rustc_query_system/src/ich/hcx.rs b/compiler/rustc_query_system/src/ich/hcx.rs
index 163da59ed..5593a1541 100644
--- a/compiler/rustc_query_system/src/ich/hcx.rs
+++ b/compiler/rustc_query_system/src/ich/hcx.rs
@@ -90,7 +90,7 @@ impl<'a> StableHashingContext<'a> {
if let Some(def_id) = def_id.as_local() {
self.local_def_path_hash(def_id)
} else {
- self.untracked.cstore.def_path_hash(def_id)
+ self.untracked.cstore.read().def_path_hash(def_id)
}
}
@@ -146,7 +146,7 @@ impl<'a> rustc_span::HashStableContext for StableHashingContext<'a> {
#[inline]
fn def_span(&self, def_id: LocalDefId) -> Span {
- *self.untracked.source_span.get(def_id).unwrap_or(&DUMMY_SP)
+ self.untracked.source_span.get(def_id).unwrap_or(DUMMY_SP)
}
#[inline]
diff --git a/compiler/rustc_query_system/src/lib.rs b/compiler/rustc_query_system/src/lib.rs
index f47760e9a..6cc4c9a7e 100644
--- a/compiler/rustc_query_system/src/lib.rs
+++ b/compiler/rustc_query_system/src/lib.rs
@@ -3,6 +3,7 @@
#![feature(hash_raw_entry)]
#![feature(min_specialization)]
#![feature(extern_types)]
+#![feature(let_chains)]
#![allow(rustc::potential_query_instability)]
#![deny(rustc::untranslatable_diagnostic)]
#![deny(rustc::diagnostic_outside_of_impl)]
@@ -14,6 +15,9 @@ extern crate rustc_data_structures;
#[macro_use]
extern crate rustc_macros;
+use rustc_errors::{DiagnosticMessage, SubdiagnosticMessage};
+use rustc_macros::fluent_messages;
+
pub mod cache;
pub mod dep_graph;
mod error;
@@ -25,3 +29,5 @@ pub use error::HandleCycleError;
pub use error::LayoutOfDepth;
pub use error::QueryOverflow;
pub use values::Value;
+
+fluent_messages! { "../locales/en-US.ftl" }
diff --git a/compiler/rustc_query_system/src/query/caches.rs b/compiler/rustc_query_system/src/query/caches.rs
index 77d0d0314..4b3cd16c2 100644
--- a/compiler/rustc_query_system/src/query/caches.rs
+++ b/compiler/rustc_query_system/src/query/caches.rs
@@ -1,13 +1,10 @@
use crate::dep_graph::DepNodeIndex;
-use rustc_arena::TypedArena;
use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::sharded;
#[cfg(parallel_compiler)]
use rustc_data_structures::sharded::Sharded;
-#[cfg(not(parallel_compiler))]
use rustc_data_structures::sync::Lock;
-use rustc_data_structures::sync::WorkerLocal;
use rustc_index::vec::{Idx, IndexVec};
use std::fmt::Debug;
use std::hash::Hash;
@@ -16,36 +13,23 @@ use std::marker::PhantomData;
pub trait CacheSelector<'tcx, V> {
type Cache
where
- V: Clone;
- type ArenaCache;
+ V: Copy;
}
pub trait QueryStorage {
- type Value: Debug;
- type Stored: Clone;
-
- /// Store a value without putting it in the cache.
- /// This is meant to be used with cycle errors.
- fn store_nocache(&self, value: Self::Value) -> Self::Stored;
+ type Value: Copy;
}
pub trait QueryCache: QueryStorage + Sized {
- type Key: Hash + Eq + Clone + Debug;
+ type Key: Hash + Eq + Copy + Debug;
/// Checks if the query is already computed and in the cache.
/// It returns the shard index and a lock guard to the shard,
/// which will be used if the query is not in the cache and we need
/// to compute it.
- fn lookup<R, OnHit>(
- &self,
- key: &Self::Key,
- // `on_hit` can be called while holding a lock to the query state shard.
- on_hit: OnHit,
- ) -> Result<R, ()>
- where
- OnHit: FnOnce(&Self::Stored, DepNodeIndex) -> R;
+ fn lookup(&self, key: &Self::Key) -> Option<(Self::Value, DepNodeIndex)>;
- fn complete(&self, key: Self::Key, value: Self::Value, index: DepNodeIndex) -> Self::Stored;
+ fn complete(&self, key: Self::Key, value: Self::Value, index: DepNodeIndex);
fn iter(&self, f: &mut dyn FnMut(&Self::Key, &Self::Value, DepNodeIndex));
}
@@ -55,8 +39,7 @@ pub struct DefaultCacheSelector<K>(PhantomData<K>);
impl<'tcx, K: Eq + Hash, V: 'tcx> CacheSelector<'tcx, V> for DefaultCacheSelector<K> {
type Cache = DefaultCache<K, V>
where
- V: Clone;
- type ArenaCache = ArenaCache<'tcx, K, V>;
+ V: Copy;
}
pub struct DefaultCache<K, V> {
@@ -72,29 +55,19 @@ impl<K, V> Default for DefaultCache<K, V> {
}
}
-impl<K: Eq + Hash, V: Clone + Debug> QueryStorage for DefaultCache<K, V> {
+impl<K: Eq + Hash, V: Copy + Debug> QueryStorage for DefaultCache<K, V> {
type Value = V;
- type Stored = V;
-
- #[inline]
- fn store_nocache(&self, value: Self::Value) -> Self::Stored {
- // We have no dedicated storage
- value
- }
}
impl<K, V> QueryCache for DefaultCache<K, V>
where
- K: Eq + Hash + Clone + Debug,
- V: Clone + Debug,
+ K: Eq + Hash + Copy + Debug,
+ V: Copy + Debug,
{
type Key = K;
#[inline(always)]
- fn lookup<R, OnHit>(&self, key: &K, on_hit: OnHit) -> Result<R, ()>
- where
- OnHit: FnOnce(&V, DepNodeIndex) -> R,
- {
+ fn lookup(&self, key: &K) -> Option<(V, DepNodeIndex)> {
let key_hash = sharded::make_hash(key);
#[cfg(parallel_compiler)]
let lock = self.cache.get_shard_by_hash(key_hash).lock();
@@ -102,24 +75,18 @@ where
let lock = self.cache.lock();
let result = lock.raw_entry().from_key_hashed_nocheck(key_hash, key);
- if let Some((_, value)) = result {
- let hit_result = on_hit(&value.0, value.1);
- Ok(hit_result)
- } else {
- Err(())
- }
+ if let Some((_, value)) = result { Some(*value) } else { None }
}
#[inline]
- fn complete(&self, key: K, value: V, index: DepNodeIndex) -> Self::Stored {
+ fn complete(&self, key: K, value: V, index: DepNodeIndex) {
#[cfg(parallel_compiler)]
let mut lock = self.cache.get_shard_by_value(&key).lock();
#[cfg(not(parallel_compiler))]
let mut lock = self.cache.lock();
// We may be overwriting another value. This is all right, since the dep-graph
// will check that the fingerprint matches.
- lock.insert(key, (value.clone(), index));
- value
+ lock.insert(key, (value, index));
}
fn iter(&self, f: &mut dyn FnMut(&Self::Key, &Self::Value, DepNodeIndex)) {
@@ -142,90 +109,46 @@ where
}
}
-pub struct ArenaCache<'tcx, K, V> {
- arena: WorkerLocal<TypedArena<(V, DepNodeIndex)>>,
- #[cfg(parallel_compiler)]
- cache: Sharded<FxHashMap<K, &'tcx (V, DepNodeIndex)>>,
- #[cfg(not(parallel_compiler))]
- cache: Lock<FxHashMap<K, &'tcx (V, DepNodeIndex)>>,
+pub struct SingleCacheSelector;
+
+impl<'tcx, V: 'tcx> CacheSelector<'tcx, V> for SingleCacheSelector {
+ type Cache = SingleCache<V>
+ where
+ V: Copy;
}
-impl<'tcx, K, V> Default for ArenaCache<'tcx, K, V> {
+pub struct SingleCache<V> {
+ cache: Lock<Option<(V, DepNodeIndex)>>,
+}
+
+impl<V> Default for SingleCache<V> {
fn default() -> Self {
- ArenaCache { arena: WorkerLocal::new(|_| TypedArena::default()), cache: Default::default() }
+ SingleCache { cache: Lock::new(None) }
}
}
-impl<'tcx, K: Eq + Hash, V: Debug + 'tcx> QueryStorage for ArenaCache<'tcx, K, V> {
+impl<V: Copy + Debug> QueryStorage for SingleCache<V> {
type Value = V;
- type Stored = &'tcx V;
-
- #[inline]
- fn store_nocache(&self, value: Self::Value) -> Self::Stored {
- let value = self.arena.alloc((value, DepNodeIndex::INVALID));
- let value = unsafe { &*(&value.0 as *const _) };
- &value
- }
}
-impl<'tcx, K, V: 'tcx> QueryCache for ArenaCache<'tcx, K, V>
+impl<V> QueryCache for SingleCache<V>
where
- K: Eq + Hash + Clone + Debug,
- V: Debug,
+ V: Copy + Debug,
{
- type Key = K;
+ type Key = ();
#[inline(always)]
- fn lookup<R, OnHit>(&self, key: &K, on_hit: OnHit) -> Result<R, ()>
- where
- OnHit: FnOnce(&&'tcx V, DepNodeIndex) -> R,
- {
- let key_hash = sharded::make_hash(key);
- #[cfg(parallel_compiler)]
- let lock = self.cache.get_shard_by_hash(key_hash).lock();
- #[cfg(not(parallel_compiler))]
- let lock = self.cache.lock();
- let result = lock.raw_entry().from_key_hashed_nocheck(key_hash, key);
-
- if let Some((_, value)) = result {
- let hit_result = on_hit(&&value.0, value.1);
- Ok(hit_result)
- } else {
- Err(())
- }
+ fn lookup(&self, _key: &()) -> Option<(V, DepNodeIndex)> {
+ *self.cache.lock()
}
#[inline]
- fn complete(&self, key: K, value: V, index: DepNodeIndex) -> Self::Stored {
- let value = self.arena.alloc((value, index));
- let value = unsafe { &*(value as *const _) };
- #[cfg(parallel_compiler)]
- let mut lock = self.cache.get_shard_by_value(&key).lock();
- #[cfg(not(parallel_compiler))]
- let mut lock = self.cache.lock();
- // We may be overwriting another value. This is all right, since the dep-graph
- // will check that the fingerprint matches.
- lock.insert(key, value);
- &value.0
+ fn complete(&self, _key: (), value: V, index: DepNodeIndex) {
+ *self.cache.lock() = Some((value, index));
}
fn iter(&self, f: &mut dyn FnMut(&Self::Key, &Self::Value, DepNodeIndex)) {
- #[cfg(parallel_compiler)]
- {
- let shards = self.cache.lock_shards();
- for shard in shards.iter() {
- for (k, v) in shard.iter() {
- f(k, &v.0, v.1);
- }
- }
- }
- #[cfg(not(parallel_compiler))]
- {
- let map = self.cache.lock();
- for (k, v) in map.iter() {
- f(k, &v.0, v.1);
- }
- }
+ self.cache.lock().as_ref().map(|value| f(&(), &value.0, value.1));
}
}
@@ -234,8 +157,7 @@ pub struct VecCacheSelector<K>(PhantomData<K>);
impl<'tcx, K: Idx, V: 'tcx> CacheSelector<'tcx, V> for VecCacheSelector<K> {
type Cache = VecCache<K, V>
where
- V: Clone;
- type ArenaCache = VecArenaCache<'tcx, K, V>;
+ V: Copy;
}
pub struct VecCache<K: Idx, V> {
@@ -251,138 +173,33 @@ impl<K: Idx, V> Default for VecCache<K, V> {
}
}
-impl<K: Eq + Idx, V: Clone + Debug> QueryStorage for VecCache<K, V> {
+impl<K: Eq + Idx, V: Copy + Debug> QueryStorage for VecCache<K, V> {
type Value = V;
- type Stored = V;
-
- #[inline]
- fn store_nocache(&self, value: Self::Value) -> Self::Stored {
- // We have no dedicated storage
- value
- }
}
impl<K, V> QueryCache for VecCache<K, V>
where
- K: Eq + Idx + Clone + Debug,
- V: Clone + Debug,
-{
- type Key = K;
-
- #[inline(always)]
- fn lookup<R, OnHit>(&self, key: &K, on_hit: OnHit) -> Result<R, ()>
- where
- OnHit: FnOnce(&V, DepNodeIndex) -> R,
- {
- #[cfg(parallel_compiler)]
- let lock = self.cache.get_shard_by_hash(key.index() as u64).lock();
- #[cfg(not(parallel_compiler))]
- let lock = self.cache.lock();
- if let Some(Some(value)) = lock.get(*key) {
- let hit_result = on_hit(&value.0, value.1);
- Ok(hit_result)
- } else {
- Err(())
- }
- }
-
- #[inline]
- fn complete(&self, key: K, value: V, index: DepNodeIndex) -> Self::Stored {
- #[cfg(parallel_compiler)]
- let mut lock = self.cache.get_shard_by_hash(key.index() as u64).lock();
- #[cfg(not(parallel_compiler))]
- let mut lock = self.cache.lock();
- lock.insert(key, (value.clone(), index));
- value
- }
-
- fn iter(&self, f: &mut dyn FnMut(&Self::Key, &Self::Value, DepNodeIndex)) {
- #[cfg(parallel_compiler)]
- {
- let shards = self.cache.lock_shards();
- for shard in shards.iter() {
- for (k, v) in shard.iter_enumerated() {
- if let Some(v) = v {
- f(&k, &v.0, v.1);
- }
- }
- }
- }
- #[cfg(not(parallel_compiler))]
- {
- let map = self.cache.lock();
- for (k, v) in map.iter_enumerated() {
- if let Some(v) = v {
- f(&k, &v.0, v.1);
- }
- }
- }
- }
-}
-
-pub struct VecArenaCache<'tcx, K: Idx, V> {
- arena: WorkerLocal<TypedArena<(V, DepNodeIndex)>>,
- #[cfg(parallel_compiler)]
- cache: Sharded<IndexVec<K, Option<&'tcx (V, DepNodeIndex)>>>,
- #[cfg(not(parallel_compiler))]
- cache: Lock<IndexVec<K, Option<&'tcx (V, DepNodeIndex)>>>,
-}
-
-impl<'tcx, K: Idx, V> Default for VecArenaCache<'tcx, K, V> {
- fn default() -> Self {
- VecArenaCache {
- arena: WorkerLocal::new(|_| TypedArena::default()),
- cache: Default::default(),
- }
- }
-}
-
-impl<'tcx, K: Eq + Idx, V: Debug + 'tcx> QueryStorage for VecArenaCache<'tcx, K, V> {
- type Value = V;
- type Stored = &'tcx V;
-
- #[inline]
- fn store_nocache(&self, value: Self::Value) -> Self::Stored {
- let value = self.arena.alloc((value, DepNodeIndex::INVALID));
- let value = unsafe { &*(&value.0 as *const _) };
- &value
- }
-}
-
-impl<'tcx, K, V: 'tcx> QueryCache for VecArenaCache<'tcx, K, V>
-where
- K: Eq + Idx + Clone + Debug,
- V: Debug,
+ K: Eq + Idx + Copy + Debug,
+ V: Copy + Debug,
{
type Key = K;
#[inline(always)]
- fn lookup<R, OnHit>(&self, key: &K, on_hit: OnHit) -> Result<R, ()>
- where
- OnHit: FnOnce(&&'tcx V, DepNodeIndex) -> R,
- {
+ fn lookup(&self, key: &K) -> Option<(V, DepNodeIndex)> {
#[cfg(parallel_compiler)]
let lock = self.cache.get_shard_by_hash(key.index() as u64).lock();
#[cfg(not(parallel_compiler))]
let lock = self.cache.lock();
- if let Some(Some(value)) = lock.get(*key) {
- let hit_result = on_hit(&&value.0, value.1);
- Ok(hit_result)
- } else {
- Err(())
- }
+ if let Some(Some(value)) = lock.get(*key) { Some(*value) } else { None }
}
#[inline]
- fn complete(&self, key: K, value: V, index: DepNodeIndex) -> Self::Stored {
- let value = self.arena.alloc((value, index));
- let value = unsafe { &*(value as *const _) };
+ fn complete(&self, key: K, value: V, index: DepNodeIndex) {
#[cfg(parallel_compiler)]
let mut lock = self.cache.get_shard_by_hash(key.index() as u64).lock();
#[cfg(not(parallel_compiler))]
let mut lock = self.cache.lock();
- lock.insert(key, value);
- &value.0
+ lock.insert(key, (value, index));
}
fn iter(&self, f: &mut dyn FnMut(&Self::Key, &Self::Value, DepNodeIndex)) {
diff --git a/compiler/rustc_query_system/src/query/config.rs b/compiler/rustc_query_system/src/query/config.rs
index 8c0330e43..d56373873 100644
--- a/compiler/rustc_query_system/src/query/config.rs
+++ b/compiler/rustc_query_system/src/query/config.rs
@@ -19,11 +19,12 @@ pub type TryLoadFromDisk<Qcx, Q> =
pub trait QueryConfig<Qcx: QueryContext> {
const NAME: &'static str;
- type Key: DepNodeParams<Qcx::DepContext> + Eq + Hash + Clone + Debug;
- type Value: Debug;
- type Stored: Debug + Clone + std::borrow::Borrow<Self::Value>;
+ // `Key` and `Value` are `Copy` instead of `Clone` to ensure copying them stays cheap,
+ // but it isn't necessary.
+ type Key: DepNodeParams<Qcx::DepContext> + Eq + Hash + Copy + Debug;
+ type Value: Debug + Copy;
- type Cache: QueryCache<Key = Self::Key, Stored = Self::Stored, Value = Self::Value>;
+ type Cache: QueryCache<Key = Self::Key, Value = Self::Value>;
// Don't use this method to access query results, instead use the methods on TyCtxt
fn query_state<'a>(tcx: Qcx) -> &'a QueryState<Self::Key, Qcx::DepKind>
@@ -38,9 +39,9 @@ pub trait QueryConfig<Qcx: QueryContext> {
fn cache_on_disk(tcx: Qcx::DepContext, key: &Self::Key) -> bool;
// Don't use this method to compute query results, instead use the methods on TyCtxt
- fn execute_query(tcx: Qcx::DepContext, k: Self::Key) -> Self::Stored;
+ fn execute_query(tcx: Qcx::DepContext, k: Self::Key) -> Self::Value;
- fn compute(tcx: Qcx, key: &Self::Key) -> fn(Qcx::DepContext, Self::Key) -> Self::Value;
+ fn compute(tcx: Qcx, key: Self::Key) -> Self::Value;
fn try_load_from_disk(qcx: Qcx, idx: &Self::Key) -> TryLoadFromDisk<Qcx, Self>;
diff --git a/compiler/rustc_query_system/src/query/mod.rs b/compiler/rustc_query_system/src/query/mod.rs
index d308af192..383c63cd2 100644
--- a/compiler/rustc_query_system/src/query/mod.rs
+++ b/compiler/rustc_query_system/src/query/mod.rs
@@ -8,7 +8,8 @@ pub use self::job::{print_query_stack, QueryInfo, QueryJob, QueryJobId, QueryJob
mod caches;
pub use self::caches::{
- CacheSelector, DefaultCacheSelector, QueryCache, QueryStorage, VecCacheSelector,
+ CacheSelector, DefaultCacheSelector, QueryCache, QueryStorage, SingleCacheSelector,
+ VecCacheSelector,
};
mod config;
@@ -100,22 +101,22 @@ impl QuerySideEffects {
}
pub trait QueryContext: HasDepContext {
- fn next_job_id(&self) -> QueryJobId;
+ fn next_job_id(self) -> QueryJobId;
/// Get the query information from the TLS context.
- fn current_query_job(&self) -> Option<QueryJobId>;
+ fn current_query_job(self) -> Option<QueryJobId>;
- fn try_collect_active_jobs(&self) -> Option<QueryMap<Self::DepKind>>;
+ fn try_collect_active_jobs(self) -> Option<QueryMap<Self::DepKind>>;
/// Load side effects associated to the node in the previous session.
- fn load_side_effects(&self, prev_dep_node_index: SerializedDepNodeIndex) -> QuerySideEffects;
+ fn load_side_effects(self, prev_dep_node_index: SerializedDepNodeIndex) -> QuerySideEffects;
/// Register diagnostics for the given node, for use in next session.
- fn store_side_effects(&self, dep_node_index: DepNodeIndex, side_effects: QuerySideEffects);
+ fn store_side_effects(self, dep_node_index: DepNodeIndex, side_effects: QuerySideEffects);
/// Register diagnostics for the given node, for use in next session.
fn store_side_effects_for_anon_node(
- &self,
+ self,
dep_node_index: DepNodeIndex,
side_effects: QuerySideEffects,
);
@@ -124,12 +125,12 @@ pub trait QueryContext: HasDepContext {
/// new query job while it executes. It returns the diagnostics
/// captured during execution and the actual result.
fn start_query<R>(
- &self,
+ self,
token: QueryJobId,
depth_limit: bool,
diagnostics: Option<&Lock<ThinVec<Diagnostic>>>,
compute: impl FnOnce() -> R,
) -> R;
- fn depth_limit_error(&self, job: QueryJobId);
+ fn depth_limit_error(self, job: QueryJobId);
}
diff --git a/compiler/rustc_query_system/src/query/plumbing.rs b/compiler/rustc_query_system/src/query/plumbing.rs
index b3b939eae..5f003fa70 100644
--- a/compiler/rustc_query_system/src/query/plumbing.rs
+++ b/compiler/rustc_query_system/src/query/plumbing.rs
@@ -2,7 +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, DepNodeIndex};
+use crate::dep_graph::{DepContext, DepKind, DepNode, DepNodeIndex, DepNodeParams};
use crate::ich::StableHashingContext;
use crate::query::caches::QueryCache;
use crate::query::job::{report_cycle, QueryInfo, QueryJob, QueryJobId, QueryJobInfo};
@@ -15,17 +15,16 @@ use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::profiling::TimingGuard;
#[cfg(parallel_compiler)]
use rustc_data_structures::sharded::Sharded;
+use rustc_data_structures::stack::ensure_sufficient_stack;
use rustc_data_structures::sync::Lock;
use rustc_errors::{DiagnosticBuilder, ErrorGuaranteed, FatalError};
use rustc_session::Session;
use rustc_span::{Span, DUMMY_SP};
-use std::borrow::Borrow;
use std::cell::Cell;
use std::collections::hash_map::Entry;
use std::fmt::Debug;
use std::hash::Hash;
use std::mem;
-use std::ptr;
use thin_vec::ThinVec;
use super::QueryConfig;
@@ -49,7 +48,7 @@ enum QueryResult<D: DepKind> {
impl<K, D> QueryState<K, D>
where
- K: Eq + Hash + Clone + Debug,
+ K: Eq + Hash + Copy + Debug,
D: DepKind,
{
pub fn all_inactive(&self) -> bool {
@@ -78,7 +77,7 @@ where
for shard in shards.iter() {
for (k, v) in shard.iter() {
if let QueryResult::Started(ref job) = *v {
- let query = make_query(qcx, k.clone());
+ let query = make_query(qcx, *k);
jobs.insert(job.id, QueryJobInfo { query, job: job.clone() });
}
}
@@ -92,7 +91,7 @@ where
// really hurt much.)
for (k, v) in self.active.try_lock()?.iter() {
if let QueryResult::Started(ref job) = *v {
- let query = make_query(qcx, k.clone());
+ let query = make_query(qcx, *k);
jobs.insert(job.id, QueryJobInfo { query, job: job.clone() });
}
}
@@ -112,7 +111,7 @@ impl<K, D: DepKind> Default for QueryState<K, D> {
/// This will poison the relevant query if dropped.
struct JobOwner<'tcx, K, D: DepKind>
where
- K: Eq + Hash + Clone,
+ K: Eq + Hash + Copy,
{
state: &'tcx QueryState<K, D>,
key: K,
@@ -121,20 +120,17 @@ where
#[cold]
#[inline(never)]
-fn mk_cycle<Qcx, V, R, D: DepKind>(
+fn mk_cycle<Qcx, R, D: DepKind>(
qcx: Qcx,
cycle_error: CycleError<D>,
handler: HandleCycleError,
- cache: &dyn crate::query::QueryStorage<Value = V, Stored = R>,
) -> R
where
Qcx: QueryContext + crate::query::HasDepContext<DepKind = D>,
- V: std::fmt::Debug + Value<Qcx::DepContext, Qcx::DepKind>,
- R: Clone,
+ R: std::fmt::Debug + Value<Qcx::DepContext, Qcx::DepKind>,
{
let error = report_cycle(qcx.dep_context().sess(), &cycle_error);
- let value = handle_cycle_error(*qcx.dep_context(), &cycle_error, error, handler);
- cache.store_nocache(value)
+ handle_cycle_error(*qcx.dep_context(), &cycle_error, error, handler)
}
fn handle_cycle_error<Tcx, V>(
@@ -167,7 +163,7 @@ where
impl<'tcx, K, D: DepKind> JobOwner<'tcx, K, D>
where
- K: Eq + Hash + Clone,
+ K: Eq + Hash + Copy,
{
/// Either gets a `JobOwner` corresponding the query, allowing us to
/// start executing the query, or returns with the result of the query.
@@ -192,14 +188,14 @@ where
#[cfg(not(parallel_compiler))]
let mut state_lock = state.active.lock();
let lock = &mut *state_lock;
+ let current_job_id = qcx.current_query_job();
match lock.entry(key) {
Entry::Vacant(entry) => {
let id = qcx.next_job_id();
- let job = qcx.current_query_job();
- let job = QueryJob::new(id, span, job);
+ let job = QueryJob::new(id, span, current_job_id);
- let key = entry.key().clone();
+ let key = *entry.key();
entry.insert(QueryResult::Started(job));
let owner = JobOwner { state, id, key };
@@ -216,7 +212,7 @@ where
// so we just return the error.
return TryGetJob::Cycle(id.find_cycle_in_stack(
qcx.try_collect_active_jobs().unwrap(),
- &qcx.current_query_job(),
+ &current_job_id,
span,
));
}
@@ -234,7 +230,7 @@ where
// With parallel queries we might just have to wait on some other
// thread.
- let result = latch.wait_on(qcx.current_query_job(), span);
+ let result = latch.wait_on(current_job_id, span);
match result {
Ok(()) => TryGetJob::JobCompleted(query_blocked_prof_timer),
@@ -249,40 +245,38 @@ 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<C>(self, cache: &C, result: C::Value, dep_node_index: DepNodeIndex) -> C::Stored
+ fn complete<C>(self, cache: &C, result: C::Value, dep_node_index: DepNodeIndex)
where
C: QueryCache<Key = K>,
{
- // We can move out of `self` here because we `mem::forget` it below
- let key = unsafe { ptr::read(&self.key) };
+ let key = self.key;
let state = self.state;
// Forget ourself so our destructor won't poison the query
mem::forget(self);
- let (job, result) = {
- let job = {
- #[cfg(parallel_compiler)]
- let mut lock = state.active.get_shard_by_value(&key).lock();
- #[cfg(not(parallel_compiler))]
- let mut lock = state.active.lock();
- match lock.remove(&key).unwrap() {
- QueryResult::Started(job) => job,
- QueryResult::Poisoned => panic!(),
- }
- };
- let result = cache.complete(key, result, dep_node_index);
- (job, result)
+ // Mark as complete before we remove the job from the active state
+ // so no other thread can re-execute this query.
+ cache.complete(key, result, dep_node_index);
+
+ let job = {
+ #[cfg(parallel_compiler)]
+ let mut lock = state.active.get_shard_by_value(&key).lock();
+ #[cfg(not(parallel_compiler))]
+ let mut lock = state.active.lock();
+ match lock.remove(&key).unwrap() {
+ QueryResult::Started(job) => job,
+ QueryResult::Poisoned => panic!(),
+ }
};
job.signal_complete();
- result
}
}
impl<'tcx, K, D> Drop for JobOwner<'tcx, K, D>
where
- K: Eq + Hash + Clone,
+ K: Eq + Hash + Copy,
D: DepKind,
{
#[inline(never)]
@@ -299,7 +293,7 @@ where
QueryResult::Started(job) => job,
QueryResult::Poisoned => panic!(),
};
- shard.insert(self.key.clone(), QueryResult::Poisoned);
+ shard.insert(self.key, QueryResult::Poisoned);
job
};
// Also signal the completion of the job, so waiters
@@ -318,7 +312,7 @@ pub(crate) struct CycleError<D: DepKind> {
/// The result of `try_start`.
enum TryGetJob<'tcx, K, D>
where
- K: Eq + Hash + Clone,
+ K: Eq + Hash + Copy,
D: DepKind,
{
/// The query is not yet started. Contains a guard to the cache eventually used to start it.
@@ -339,74 +333,62 @@ where
/// which will be used if the query is not in the cache and we need
/// to compute it.
#[inline]
-pub fn try_get_cached<Tcx, C, R, OnHit>(
- tcx: Tcx,
- cache: &C,
- key: &C::Key,
- // `on_hit` can be called while holding a lock to the query cache
- on_hit: OnHit,
-) -> Result<R, ()>
+pub fn try_get_cached<Tcx, C>(tcx: Tcx, cache: &C, key: &C::Key) -> Option<C::Value>
where
C: QueryCache,
Tcx: DepContext,
- OnHit: FnOnce(&C::Stored) -> R,
{
- cache.lookup(&key, |value, index| {
- if std::intrinsics::unlikely(tcx.profiler().enabled()) {
+ match cache.lookup(&key) {
+ Some((value, index)) => {
tcx.profiler().query_cache_hit(index.into());
+ tcx.dep_graph().read_index(index);
+ Some(value)
}
- tcx.dep_graph().read_index(index);
- on_hit(value)
- })
+ None => None,
+ }
}
+#[inline(never)]
fn try_execute_query<Q, Qcx>(
qcx: Qcx,
- state: &QueryState<Q::Key, Qcx::DepKind>,
- cache: &Q::Cache,
span: Span,
key: Q::Key,
dep_node: Option<DepNode<Qcx::DepKind>>,
-) -> (Q::Stored, Option<DepNodeIndex>)
+) -> (Q::Value, Option<DepNodeIndex>)
where
Q: QueryConfig<Qcx>,
Qcx: QueryContext,
{
- match JobOwner::<'_, Q::Key, Qcx::DepKind>::try_start(&qcx, state, span, key.clone()) {
+ let state = Q::query_state(qcx);
+ match JobOwner::<'_, Q::Key, Qcx::DepKind>::try_start(&qcx, state, span, key) {
TryGetJob::NotYetStarted(job) => {
- let (result, dep_node_index) =
- execute_job::<Q, Qcx>(qcx, key.clone(), dep_node, job.id);
+ let (result, dep_node_index) = execute_job::<Q, Qcx>(qcx, key, dep_node, job.id);
+ let cache = Q::query_cache(qcx);
if Q::FEEDABLE {
- // We may have put a value inside the cache from inside the execution.
- // Verify that it has the same hash as what we have now, to ensure consistency.
- let _ = cache.lookup(&key, |cached_result, _| {
- let hasher = Q::HASH_RESULT.expect("feedable forbids no_hash");
-
- let old_hash = qcx.dep_context().with_stable_hashing_context(|mut hcx| hasher(&mut hcx, cached_result.borrow()));
- let new_hash = qcx.dep_context().with_stable_hashing_context(|mut hcx| hasher(&mut hcx, &result));
- debug_assert_eq!(
- old_hash, new_hash,
- "Computed query value for {:?}({:?}) is inconsistent with fed value,\ncomputed={:#?}\nfed={:#?}",
- Q::DEP_KIND, key, result, cached_result,
+ // We should not compute queries that also got a value via feeding.
+ // This can't happen, as query feeding adds the very dependencies to the fed query
+ // as its feeding query had. So if the fed query is red, so is its feeder, which will
+ // get evaluated first, and re-feed the query.
+ if let Some((cached_result, _)) = cache.lookup(&key) {
+ panic!(
+ "fed query later has its value computed. The already cached value: {cached_result:?}"
);
- });
+ }
}
- let result = job.complete(cache, result, dep_node_index);
+ job.complete(cache, result, dep_node_index);
(result, Some(dep_node_index))
}
TryGetJob::Cycle(error) => {
- let result = mk_cycle(qcx, error, Q::HANDLE_CYCLE_ERROR, cache);
+ let result = mk_cycle(qcx, error, Q::HANDLE_CYCLE_ERROR);
(result, None)
}
#[cfg(parallel_compiler)]
TryGetJob::JobCompleted(query_blocked_prof_timer) => {
- let (v, index) = cache
- .lookup(&key, |value, index| (value.clone(), index))
- .unwrap_or_else(|_| panic!("value must be in cache after waiting"));
+ let Some((v, index)) = Q::query_cache(qcx).lookup(&key) else {
+ panic!("value must be in cache after waiting")
+ };
- if std::intrinsics::unlikely(qcx.dep_context().profiler().enabled()) {
- qcx.dep_context().profiler().query_cache_hit(index.into());
- }
+ qcx.dep_context().profiler().query_cache_hit(index.into());
query_blocked_prof_timer.finish_with_query_invocation_id(index.into());
(v, Some(index))
@@ -414,6 +396,7 @@ where
}
}
+#[inline(always)]
fn execute_job<Q, Qcx>(
qcx: Qcx,
key: Q::Key,
@@ -428,12 +411,27 @@ where
// Fast path for when incr. comp. is off.
if !dep_graph.is_fully_enabled() {
+ // Fingerprint the key, just to assert that it doesn't
+ // have anything we don't consider hashable
+ if cfg!(debug_assertions) {
+ let _ = key.to_fingerprint(*qcx.dep_context());
+ }
+
let prof_timer = qcx.dep_context().profiler().query_provider();
- let result = qcx.start_query(job_id, Q::DEPTH_LIMIT, None, || {
- Q::compute(qcx, &key)(*qcx.dep_context(), key)
- });
+ let result = qcx.start_query(job_id, Q::DEPTH_LIMIT, None, || Q::compute(qcx, key));
let dep_node_index = dep_graph.next_virtual_depnode_index();
prof_timer.finish_with_query_invocation_id(dep_node_index.into());
+
+ // Similarly, fingerprint the result to assert that
+ // it doesn't have anything not considered hashable.
+ if cfg!(debug_assertions)
+ && let Some(hash_result) = Q::HASH_RESULT
+ {
+ qcx.dep_context().with_stable_hashing_context(|mut hcx| {
+ hash_result(&mut hcx, &result);
+ });
+ }
+
return (result, dep_node_index);
}
@@ -457,17 +455,15 @@ where
let (result, dep_node_index) =
qcx.start_query(job_id, Q::DEPTH_LIMIT, Some(&diagnostics), || {
if Q::ANON {
- return dep_graph.with_anon_task(*qcx.dep_context(), Q::DEP_KIND, || {
- Q::compute(qcx, &key)(*qcx.dep_context(), key)
- });
+ return dep_graph
+ .with_anon_task(*qcx.dep_context(), Q::DEP_KIND, || Q::compute(qcx, key));
}
// `to_dep_node` is expensive for some `DepKind`s.
let dep_node =
dep_node_opt.unwrap_or_else(|| Q::construct_dep_node(*qcx.dep_context(), &key));
- let task = Q::compute(qcx, &key);
- dep_graph.with_task(dep_node, *qcx.dep_context(), key, task, Q::HASH_RESULT)
+ dep_graph.with_task(dep_node, qcx, key, Q::compute, Q::HASH_RESULT)
});
prof_timer.finish_with_query_invocation_id(dep_node_index.into());
@@ -486,6 +482,7 @@ where
(result, dep_node_index)
}
+#[inline(always)]
fn try_load_from_disk_and_cache_in_memory<Q, Qcx>(
qcx: Qcx,
key: &Q::Key,
@@ -558,7 +555,7 @@ where
let prof_timer = qcx.dep_context().profiler().query_provider();
// The dep-graph for this computation is already in-place.
- let result = dep_graph.with_ignore(|| Q::compute(qcx, key)(*qcx.dep_context(), key.clone()));
+ let result = dep_graph.with_ignore(|| Q::compute(qcx, *key));
prof_timer.finish_with_query_invocation_id(dep_node_index.into());
@@ -576,6 +573,7 @@ where
Some((result, dep_node_index))
}
+#[inline]
#[instrument(skip(tcx, result, hash_result), level = "debug")]
pub(crate) fn incremental_verify_ich<Tcx, V: Debug>(
tcx: Tcx,
@@ -730,7 +728,8 @@ pub enum QueryMode {
Ensure,
}
-pub fn get_query<Q, Qcx, D>(qcx: Qcx, span: Span, key: Q::Key, mode: QueryMode) -> Option<Q::Stored>
+#[inline(always)]
+pub fn get_query<Q, Qcx, D>(qcx: Qcx, span: Span, key: Q::Key, mode: QueryMode) -> Option<Q::Value>
where
D: DepKind,
Q: QueryConfig<Qcx>,
@@ -747,14 +746,8 @@ where
None
};
- let (result, dep_node_index) = try_execute_query::<Q, Qcx>(
- qcx,
- Q::query_state(qcx),
- Q::query_cache(qcx),
- span,
- key,
- dep_node,
- );
+ let (result, dep_node_index) =
+ ensure_sufficient_stack(|| try_execute_query::<Q, Qcx>(qcx, span, key, dep_node));
if let Some(dep_node_index) = dep_node_index {
qcx.dep_context().dep_graph().read_index(dep_node_index)
}
@@ -770,20 +763,12 @@ where
{
// We may be concurrently trying both execute and force a query.
// Ensure that only one of them runs the query.
- let cache = Q::query_cache(qcx);
- let cached = cache.lookup(&key, |_, index| {
- if std::intrinsics::unlikely(qcx.dep_context().profiler().enabled()) {
- qcx.dep_context().profiler().query_cache_hit(index.into());
- }
- });
-
- match cached {
- Ok(()) => return,
- Err(()) => {}
+ if let Some((_, index)) = Q::query_cache(qcx).lookup(&key) {
+ qcx.dep_context().profiler().query_cache_hit(index.into());
+ return;
}
- let state = Q::query_state(qcx);
debug_assert!(!Q::ANON);
- try_execute_query::<Q, _>(qcx, state, cache, DUMMY_SP, key, Some(dep_node));
+ ensure_sufficient_stack(|| try_execute_query::<Q, _>(qcx, DUMMY_SP, key, Some(dep_node)));
}
diff --git a/compiler/rustc_resolve/Cargo.toml b/compiler/rustc_resolve/Cargo.toml
index 7c3a0f8f2..5c4ec44d2 100644
--- a/compiler/rustc_resolve/Cargo.toml
+++ b/compiler/rustc_resolve/Cargo.toml
@@ -7,6 +7,7 @@ edition = "2021"
[dependencies]
bitflags = "1.2.1"
+pulldown-cmark = { version = "0.9.2", default-features = false }
rustc_arena = { path = "../rustc_arena" }
rustc_ast = { path = "../rustc_ast" }
rustc_ast_pretty = { path = "../rustc_ast_pretty" }
@@ -24,5 +25,5 @@ rustc_query_system = { path = "../rustc_query_system" }
rustc_session = { path = "../rustc_session" }
rustc_span = { path = "../rustc_span" }
smallvec = { version = "1.8.1", features = ["union", "may_dangle"] }
-thin-vec = "0.2.8"
+thin-vec = "0.2.12"
tracing = "0.1"
diff --git a/compiler/rustc_error_messages/locales/en-US/resolve.ftl b/compiler/rustc_resolve/locales/en-US.ftl
index 817bb83ed..817bb83ed 100644
--- a/compiler/rustc_error_messages/locales/en-US/resolve.ftl
+++ b/compiler/rustc_resolve/locales/en-US.ftl
diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs
index b1b04c92a..b1e023f2c 100644
--- a/compiler/rustc_resolve/src/build_reduced_graph.rs
+++ b/compiler/rustc_resolve/src/build_reduced_graph.rs
@@ -65,7 +65,7 @@ impl<'a, Id: Into<DefId>> ToNameBinding<'a> for (Res, ty::Visibility<Id>, Span,
}
}
-impl<'a> Resolver<'a> {
+impl<'a, 'tcx> Resolver<'a, 'tcx> {
/// Defines `name` in namespace `ns` of module `parent` to be `def` if it is not yet defined;
/// otherwise, reports an error.
pub(crate) fn define<T>(&mut self, parent: Module<'a>, ident: Ident, ns: Namespace, def: T)
@@ -95,7 +95,7 @@ impl<'a> Resolver<'a> {
/// Reachable macros with block module parents exist due to `#[macro_export] macro_rules!`,
/// but they cannot use def-site hygiene, so the assumption holds
/// (<https://github.com/rust-lang/rust/pull/77984#issuecomment-712445508>).
- pub fn get_nearest_non_block_module(&mut self, mut def_id: DefId) -> Module<'a> {
+ pub(crate) 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,
@@ -104,7 +104,7 @@ impl<'a> Resolver<'a> {
}
}
- pub fn expect_module(&mut self, def_id: DefId) -> Module<'a> {
+ pub(crate) fn expect_module(&mut self, def_id: DefId) -> Module<'a> {
self.get_module(def_id).expect("argument `DefId` is not a module")
}
@@ -130,11 +130,13 @@ impl<'a> Resolver<'a> {
def_key.disambiguated_data.data.get_opt_name().expect("module without name")
};
+ let expn_id = self.cstore().module_expansion_untracked(def_id, &self.tcx.sess);
+ let span = self.cstore().get_span_untracked(def_id, &self.tcx.sess);
Some(self.new_module(
parent,
ModuleKind::Def(def_kind, def_id, name),
- self.cstore().module_expansion_untracked(def_id, &self.session),
- self.cstore().get_span_untracked(def_id, &self.session),
+ expn_id,
+ span,
// FIXME: Account for `#[no_implicit_prelude]` attributes.
parent.map_or(false, |module| module.no_implicit_prelude),
))
@@ -179,7 +181,8 @@ impl<'a> Resolver<'a> {
return macro_data.clone();
}
- let (ext, macro_rules) = match self.cstore().load_macro_untracked(def_id, &self.session) {
+ let load_macro_untracked = self.cstore().load_macro_untracked(def_id, &self.tcx.sess);
+ let (ext, macro_rules) = match load_macro_untracked {
LoadedMacro::MacroDef(item, edition) => (
Lrc::new(self.compile_macro(&item, edition).0),
matches!(item.kind, ItemKind::MacroDef(def) if def.macro_rules),
@@ -204,9 +207,9 @@ impl<'a> Resolver<'a> {
}
pub(crate) fn build_reduced_graph_external(&mut self, module: Module<'a>) {
- for child in
- Vec::from_iter(self.cstore().module_children_untracked(module.def_id(), self.session))
- {
+ let children =
+ Vec::from_iter(self.cstore().module_children_untracked(module.def_id(), self.tcx.sess));
+ for child in children {
let parent_scope = ParentScope::module(module, self);
BuildReducedGraphVisitor { r: self, parent_scope }
.build_reduced_graph_for_external_crate_res(child);
@@ -214,18 +217,18 @@ impl<'a> Resolver<'a> {
}
}
-struct BuildReducedGraphVisitor<'a, 'b> {
- r: &'b mut Resolver<'a>,
+struct BuildReducedGraphVisitor<'a, 'b, 'tcx> {
+ r: &'b mut Resolver<'a, 'tcx>,
parent_scope: ParentScope<'a>,
}
-impl<'a> AsMut<Resolver<'a>> for BuildReducedGraphVisitor<'a, '_> {
- fn as_mut(&mut self) -> &mut Resolver<'a> {
+impl<'a, 'tcx> AsMut<Resolver<'a, 'tcx>> for BuildReducedGraphVisitor<'a, '_, 'tcx> {
+ fn as_mut(&mut self) -> &mut Resolver<'a, 'tcx> {
self.r
}
}
-impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
+impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> {
fn resolve_visibility(&mut self, vis: &ast::Visibility) -> ty::Visibility {
self.try_resolve_visibility(vis, true).unwrap_or_else(|err| {
self.r.report_vis_error(err);
@@ -265,7 +268,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
let ident = path.segments.get(0).expect("empty path in visibility").ident;
let crate_root = if ident.is_path_segment_keyword() {
None
- } else if ident.span.rust_2015() {
+ } else if ident.span.is_rust_2015() {
Some(Segment::from_ident(Ident::new(
kw::PathRoot,
path.span.shrink_to_lo().with_ctxt(ident.span.ctxt()),
@@ -298,14 +301,15 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
self.r.record_partial_res(id, PartialRes::new(res));
}
if module.is_normal() {
- if res == Res::Err {
- Ok(ty::Visibility::Public)
- } else {
- let vis = ty::Visibility::Restricted(res.def_id());
- if self.r.is_accessible_from(vis, parent_scope.module) {
- Ok(vis.expect_local())
- } else {
- Err(VisResolutionError::AncestorOnly(path.span))
+ match res {
+ Res::Err => Ok(ty::Visibility::Public),
+ _ => {
+ let vis = ty::Visibility::Restricted(res.def_id());
+ if self.r.is_accessible_from(vis, parent_scope.module) {
+ Ok(vis.expect_local())
+ } else {
+ Err(VisResolutionError::AncestorOnly(path.span))
+ }
}
}
} else {
@@ -345,7 +349,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
fn insert_field_names_extern(&mut self, def_id: DefId) {
let field_names =
- self.r.cstore().struct_field_names_untracked(def_id, self.r.session).collect();
+ self.r.cstore().struct_field_names_untracked(def_id, self.r.tcx.sess).collect();
self.r.field_names.insert(def_id, field_names);
}
@@ -434,10 +438,10 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
// appears, so imports in braced groups can have roots prepended independently.
let is_glob = matches!(use_tree.kind, ast::UseTreeKind::Glob);
let crate_root = match prefix_iter.peek() {
- Some(seg) if !seg.ident.is_path_segment_keyword() && seg.ident.span.rust_2015() => {
+ Some(seg) if !seg.ident.is_path_segment_keyword() && seg.ident.span.is_rust_2015() => {
Some(seg.ident.span.ctxt())
}
- None if is_glob && use_tree.span.rust_2015() => Some(use_tree.span.ctxt()),
+ None if is_glob && use_tree.span.is_rust_2015() => Some(use_tree.span.ctxt()),
_ => None,
}
.map(|ctxt| {
@@ -538,14 +542,15 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
}
self.r
- .session
+ .tcx
+ .sess
.struct_span_err(item.span, "`$crate` may not be imported")
.emit();
}
}
if ident.name == kw::Crate {
- self.r.session.span_err(
+ self.r.tcx.sess.span_err(
ident.span,
"crate root imports need to be explicitly named: \
`use crate as name;`",
@@ -574,7 +579,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
}
ast::UseTreeKind::Glob => {
let kind = ImportKind::Glob {
- is_prelude: self.r.session.contains_name(&item.attrs, sym::prelude_import),
+ is_prelude: self.r.tcx.sess.contains_name(&item.attrs, sym::prelude_import),
max_vis: Cell::new(None),
id,
};
@@ -689,7 +694,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
expansion.to_expn_id(),
item.span,
parent.no_implicit_prelude
- || self.r.session.contains_name(&item.attrs, sym::no_implicit_prelude),
+ || self.r.tcx.sess.contains_name(&item.attrs, sym::no_implicit_prelude),
);
self.r.define(parent, ident, TypeNS, (module, vis, sp, expansion));
@@ -754,7 +759,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
// If the structure is marked as non_exhaustive then lower the visibility
// to within the crate.
let mut ctor_vis = if vis.is_public()
- && self.r.session.contains_name(&item.attrs, sym::non_exhaustive)
+ && self.r.tcx.sess.contains_name(&item.attrs, sym::non_exhaustive)
{
ty::Visibility::Restricted(CRATE_DEF_ID)
} else {
@@ -836,7 +841,8 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
let (used, module, binding) = if orig_name.is_none() && ident.name == kw::SelfLower {
self.r
- .session
+ .tcx
+ .sess
.struct_span_err(item.span, "`extern crate self;` requires renaming")
.span_suggestion(
item.span,
@@ -849,7 +855,10 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
} else if orig_name == Some(kw::SelfLower) {
Some(self.r.graph_root)
} else {
- let crate_id = self.r.crate_loader().process_extern_crate(item, local_def_id);
+ let tcx = self.r.tcx;
+ let crate_id = self.r.crate_loader(|c| {
+ c.process_extern_crate(item, local_def_id, &tcx.definitions_untracked())
+ });
crate_id.map(|crate_id| {
self.r.extern_crate_map.insert(local_def_id, crate_id);
self.r.expect_module(crate_id.as_def_id())
@@ -886,7 +895,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
{
let msg = "macro-expanded `extern crate` items cannot \
shadow names passed with `--extern`";
- self.r.session.span_err(item.span, msg);
+ self.r.tcx.sess.span_err(item.span, msg);
}
}
let entry = self.r.extern_prelude.entry(ident.normalize_to_macros_2_0()).or_insert(
@@ -986,7 +995,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
| DefKind::LifetimeParam
| DefKind::GlobalAsm
| DefKind::Closure
- | DefKind::Impl
+ | DefKind::Impl { .. }
| DefKind::Generator,
_,
)
@@ -997,23 +1006,26 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
| Res::Err => bug!("unexpected resolution: {:?}", res),
}
// Record some extra data for better diagnostics.
- let cstore = self.r.cstore();
match res {
Res::Def(DefKind::Struct, def_id) => {
+ let cstore = self.r.cstore();
if let Some((ctor_kind, ctor_def_id)) = cstore.ctor_untracked(def_id) {
let ctor_res = Res::Def(DefKind::Ctor(CtorOf::Struct, ctor_kind), ctor_def_id);
let ctor_vis = cstore.visibility_untracked(ctor_def_id);
let field_visibilities =
cstore.struct_field_visibilities_untracked(def_id).collect();
+ drop(cstore);
self.r
.struct_constructors
.insert(def_id, (ctor_res, ctor_vis, field_visibilities));
+ } else {
+ drop(cstore);
}
self.insert_field_names_extern(def_id)
}
Res::Def(DefKind::Union, def_id) => self.insert_field_names_extern(def_id),
Res::Def(DefKind::AssocFn, def_id) => {
- if cstore.fn_has_self_parameter_untracked(def_id, self.r.session) {
+ if self.r.cstore().fn_has_self_parameter_untracked(def_id, self.r.tcx.sess) {
self.r.has_self.insert(def_id);
}
}
@@ -1032,7 +1044,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
let msg = format!("`{}` is already in scope", name);
let note =
"macro-expanded `#[macro_use]`s may not shadow existing macros (see RFC 1560)";
- self.r.session.struct_span_err(span, &msg).note(note).emit();
+ self.r.tcx.sess.struct_span_err(span, &msg).note(note).emit();
}
}
@@ -1044,7 +1056,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
if attr.has_name(sym::macro_use) {
if self.parent_scope.module.parent.is_some() {
struct_span_err!(
- self.r.session,
+ self.r.tcx.sess,
item.span,
E0468,
"an `extern crate` loading macros must be at the crate root"
@@ -1054,7 +1066,8 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
if let ItemKind::ExternCrate(Some(orig_name)) = item.kind {
if orig_name == kw::SelfLower {
self.r
- .session
+ .tcx
+ .sess
.struct_span_err(
attr.span,
"`#[macro_use]` is not supported on `extern crate self`",
@@ -1063,7 +1076,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
}
}
let ill_formed = |span| {
- struct_span_err!(self.r.session, span, E0466, "bad macro import").emit();
+ struct_span_err!(self.r.tcx.sess, span, E0466, "bad macro import").emit();
};
match attr.meta() {
Some(meta) => match meta.kind {
@@ -1134,8 +1147,13 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
allow_shadowing,
);
} else {
- struct_span_err!(self.r.session, ident.span, E0469, "imported macro not found")
- .emit();
+ struct_span_err!(
+ self.r.tcx.sess,
+ ident.span,
+ E0469,
+ "imported macro not found"
+ )
+ .emit();
}
}
}
@@ -1147,7 +1165,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
for attr in attrs {
if attr.has_name(sym::macro_escape) {
let msg = "`#[macro_escape]` is a deprecated synonym for `#[macro_use]`";
- let mut err = self.r.session.struct_span_warn(attr.span, msg);
+ let mut err = self.r.tcx.sess.struct_span_warn(attr.span, msg);
if let ast::AttrStyle::Inner = attr.style {
err.help("try an outer attribute: `#[macro_use]`").emit();
} else {
@@ -1158,7 +1176,10 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
}
if !attr.is_word() {
- self.r.session.span_err(attr.span, "arguments to `macro_use` are not allowed here");
+ self.r
+ .tcx
+ .sess
+ .span_err(attr.span, "arguments to `macro_use` are not allowed here");
}
return true;
}
@@ -1182,11 +1203,11 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
}
fn proc_macro_stub(&self, item: &ast::Item) -> Option<(MacroKind, Ident, Span)> {
- if self.r.session.contains_name(&item.attrs, sym::proc_macro) {
+ if self.r.tcx.sess.contains_name(&item.attrs, sym::proc_macro) {
return Some((MacroKind::Bang, item.ident, item.span));
- } else if self.r.session.contains_name(&item.attrs, sym::proc_macro_attribute) {
+ } else if self.r.tcx.sess.contains_name(&item.attrs, sym::proc_macro_attribute) {
return Some((MacroKind::Attr, item.ident, item.span));
- } else if let Some(attr) = self.r.session.find_by_name(&item.attrs, sym::proc_macro_derive)
+ } else if let Some(attr) = self.r.tcx.sess.find_by_name(&item.attrs, sym::proc_macro_derive)
{
if let Some(nested_meta) = attr.meta_item_list().and_then(|list| list.get(0).cloned()) {
if let Some(ident) = nested_meta.ident() {
@@ -1221,7 +1242,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
let def_id = self.r.local_def_id(item.id);
let (ext, ident, span, macro_rules, rule_spans) = match &item.kind {
ItemKind::MacroDef(def) => {
- let (ext, rule_spans) = self.r.compile_macro(item, self.r.session.edition());
+ let (ext, rule_spans) = self.r.compile_macro(item, self.r.tcx.sess.edition());
let ext = Lrc::new(ext);
(ext, item.ident, item.span, def.macro_rules, rule_spans)
}
@@ -1242,7 +1263,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
if macro_rules {
let ident = ident.normalize_to_macros_2_0();
self.r.macro_names.insert(ident);
- let is_macro_export = self.r.session.contains_name(&item.attrs, sym::macro_export);
+ let is_macro_export = self.r.tcx.sess.contains_name(&item.attrs, sym::macro_export);
let vis = if is_macro_export {
ty::Visibility::Public
} else {
@@ -1250,6 +1271,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
};
let binding = (res, vis, span, expansion).to_name_binding(self.r.arenas);
self.r.set_binding_parent_module(binding, parent_scope.module);
+ self.r.all_macro_rules.insert(ident.name, res);
if is_macro_export {
let import = self.r.arenas.alloc_import(Import {
kind: ImportKind::MacroExport,
@@ -1313,7 +1335,7 @@ macro_rules! method {
};
}
-impl<'a, 'b> Visitor<'b> for BuildReducedGraphVisitor<'a, 'b> {
+impl<'a, 'b, 'tcx> Visitor<'b> for BuildReducedGraphVisitor<'a, 'b, 'tcx> {
method!(visit_expr: ast::Expr, ast::ExprKind::MacCall, walk_expr);
method!(visit_pat: ast::Pat, ast::PatKind::MacCall, walk_pat);
method!(visit_ty: ast::Ty, ast::TyKind::MacCall, walk_ty);
@@ -1505,7 +1527,7 @@ impl<'a, 'b> Visitor<'b> for BuildReducedGraphVisitor<'a, 'b> {
// If the variant is marked as non_exhaustive then lower the visibility to within the crate.
let ctor_vis = if vis.is_public()
- && self.r.session.contains_name(&variant.attrs, sym::non_exhaustive)
+ && self.r.tcx.sess.contains_name(&variant.attrs, sym::non_exhaustive)
{
ty::Visibility::Restricted(CRATE_DEF_ID)
} else {
diff --git a/compiler/rustc_resolve/src/check_unused.rs b/compiler/rustc_resolve/src/check_unused.rs
index eae4c9992..b2578e4c4 100644
--- a/compiler/rustc_resolve/src/check_unused.rs
+++ b/compiler/rustc_resolve/src/check_unused.rs
@@ -29,11 +29,12 @@ use crate::Resolver;
use rustc_ast as ast;
use rustc_ast::visit::{self, Visitor};
-use rustc_data_structures::fx::FxIndexMap;
+use rustc_data_structures::fx::{FxHashMap, FxIndexMap};
use rustc_data_structures::unord::UnordSet;
use rustc_errors::{pluralize, MultiSpan};
-use rustc_session::lint::builtin::{MACRO_USE_EXTERN_CRATE, UNUSED_IMPORTS};
+use rustc_session::lint::builtin::{MACRO_USE_EXTERN_CRATE, UNUSED_EXTERN_CRATES, UNUSED_IMPORTS};
use rustc_session::lint::BuiltinLintDiagnostics;
+use rustc_span::symbol::Ident;
use rustc_span::{Span, DUMMY_SP};
struct UnusedImport<'a> {
@@ -49,16 +50,33 @@ impl<'a> UnusedImport<'a> {
}
}
-struct UnusedImportCheckVisitor<'a, 'b> {
- r: &'a mut Resolver<'b>,
+struct UnusedImportCheckVisitor<'a, 'b, 'tcx> {
+ r: &'a mut Resolver<'b, 'tcx>,
/// All the (so far) unused imports, grouped path list
unused_imports: FxIndexMap<ast::NodeId, UnusedImport<'a>>,
+ extern_crate_items: Vec<ExternCrateToLint>,
base_use_tree: Option<&'a ast::UseTree>,
base_id: ast::NodeId,
item_span: Span,
}
-impl<'a, 'b> UnusedImportCheckVisitor<'a, 'b> {
+struct ExternCrateToLint {
+ id: ast::NodeId,
+ /// Span from the item
+ span: Span,
+ /// Span to use to suggest complete removal.
+ span_with_attributes: Span,
+ /// Span of the visibility, if any.
+ vis_span: Span,
+ /// Whether the item has attrs.
+ has_attrs: bool,
+ /// Name used to refer to the crate.
+ ident: Ident,
+ /// Whether the statement renames the crate `extern crate orig_name as new_name;`.
+ renames: bool,
+}
+
+impl<'a, 'b, 'tcx> UnusedImportCheckVisitor<'a, 'b, 'tcx> {
// We have information about whether `use` (import) items are actually
// used now. If an import is not used at all, we signal a lint error.
fn check_import(&mut self, id: ast::NodeId) {
@@ -94,20 +112,29 @@ impl<'a, 'b> UnusedImportCheckVisitor<'a, 'b> {
}
}
-impl<'a, 'b> Visitor<'a> for UnusedImportCheckVisitor<'a, 'b> {
+impl<'a, 'b, 'tcx> Visitor<'a> for UnusedImportCheckVisitor<'a, 'b, 'tcx> {
fn visit_item(&mut self, item: &'a ast::Item) {
- self.item_span = item.span_with_attributes();
-
- // Ignore is_public import statements because there's no way to be sure
- // whether they're used or not. Also ignore imports with a dummy span
- // because this means that they were generated in some fashion by the
- // compiler and we don't need to consider them.
- if let ast::ItemKind::Use(..) = item.kind {
- if item.vis.kind.is_pub() || item.span.is_dummy() {
- return;
+ match item.kind {
+ // Ignore is_public import statements because there's no way to be sure
+ // whether they're used or not. Also ignore imports with a dummy span
+ // because this means that they were generated in some fashion by the
+ // compiler and we don't need to consider them.
+ ast::ItemKind::Use(..) if item.vis.kind.is_pub() || item.span.is_dummy() => return,
+ ast::ItemKind::ExternCrate(orig_name) => {
+ self.extern_crate_items.push(ExternCrateToLint {
+ id: item.id,
+ span: item.span,
+ vis_span: item.vis.span,
+ span_with_attributes: item.span_with_attributes(),
+ has_attrs: !item.attrs.is_empty(),
+ ident: item.ident,
+ renames: orig_name.is_some(),
+ });
}
+ _ => {}
}
+ self.item_span = item.span_with_attributes();
visit::walk_item(self, item);
}
@@ -222,8 +249,11 @@ fn calc_unused_spans(
}
}
-impl Resolver<'_> {
+impl Resolver<'_, '_> {
pub(crate) fn check_unused(&mut self, krate: &ast::Crate) {
+ let tcx = self.tcx;
+ let mut maybe_unused_extern_crates = FxHashMap::default();
+
for import in self.potentially_unused_imports.iter() {
match import.kind {
_ if import.used.get()
@@ -246,7 +276,14 @@ impl Resolver<'_> {
}
ImportKind::ExternCrate { id, .. } => {
let def_id = self.local_def_id(id);
- self.maybe_unused_extern_crates.push((def_id, import.span));
+ if self.extern_crate_map.get(&def_id).map_or(true, |&cnum| {
+ !tcx.is_compiler_builtins(cnum)
+ && !tcx.is_panic_runtime(cnum)
+ && !tcx.has_global_allocator(cnum)
+ && !tcx.has_panic_handler(cnum)
+ }) {
+ maybe_unused_extern_crates.insert(id, import.span);
+ }
}
ImportKind::MacroUse => {
let msg = "unused `#[macro_use]` import";
@@ -259,6 +296,7 @@ impl Resolver<'_> {
let mut visitor = UnusedImportCheckVisitor {
r: self,
unused_imports: Default::default(),
+ extern_crate_items: Default::default(),
base_use_tree: None,
base_id: ast::DUMMY_NODE_ID,
item_span: DUMMY_SP,
@@ -290,7 +328,7 @@ impl Resolver<'_> {
let ms = MultiSpan::from_spans(spans.clone());
let mut span_snippets = spans
.iter()
- .filter_map(|s| match visitor.r.session.source_map().span_to_snippet(*s) {
+ .filter_map(|s| match tcx.sess.source_map().span_to_snippet(*s) {
Ok(s) => Some(format!("`{}`", s)),
_ => None,
})
@@ -317,7 +355,7 @@ impl Resolver<'_> {
// If we are in the `--test` mode, suppress a help that adds the `#[cfg(test)]`
// attribute; however, if not, suggest adding the attribute. There is no way to
// retrieve attributes here because we do not have a `TyCtxt` yet.
- let test_module_span = if visitor.r.session.opts.test {
+ let test_module_span = if tcx.sess.opts.test {
None
} else {
let parent_module = visitor.r.get_nearest_non_block_module(
@@ -346,5 +384,74 @@ impl Resolver<'_> {
BuiltinLintDiagnostics::UnusedImports(fix_msg.into(), fixes, test_module_span),
);
}
+
+ for extern_crate in visitor.extern_crate_items {
+ let warn_if_unused = !extern_crate.ident.name.as_str().starts_with('_');
+
+ // If the crate is fully unused, we suggest removing it altogether.
+ // We do this in any edition.
+ if warn_if_unused {
+ if let Some(&span) = maybe_unused_extern_crates.get(&extern_crate.id) {
+ visitor.r.lint_buffer.buffer_lint_with_diagnostic(
+ UNUSED_EXTERN_CRATES,
+ extern_crate.id,
+ span,
+ "unused extern crate",
+ BuiltinLintDiagnostics::UnusedExternCrate {
+ removal_span: extern_crate.span_with_attributes,
+ },
+ );
+ continue;
+ }
+ }
+
+ // If we are not in Rust 2018 edition, then we don't make any further
+ // suggestions.
+ if !tcx.sess.rust_2018() {
+ continue;
+ }
+
+ // If the extern crate has any attributes, they may have funky
+ // semantics we can't faithfully represent using `use` (most
+ // notably `#[macro_use]`). Ignore it.
+ if extern_crate.has_attrs {
+ continue;
+ }
+
+ // If the extern crate is renamed, then we cannot suggest replacing it with a use as this
+ // would not insert the new name into the prelude, where other imports in the crate may be
+ // expecting it.
+ if extern_crate.renames {
+ continue;
+ }
+
+ // If the extern crate isn't in the extern prelude,
+ // there is no way it can be written as a `use`.
+ if !visitor
+ .r
+ .extern_prelude
+ .get(&extern_crate.ident)
+ .map_or(false, |entry| !entry.introduced_by_item)
+ {
+ continue;
+ }
+
+ let vis_span = extern_crate
+ .vis_span
+ .find_ancestor_inside(extern_crate.span)
+ .unwrap_or(extern_crate.vis_span);
+ let ident_span = extern_crate
+ .ident
+ .span
+ .find_ancestor_inside(extern_crate.span)
+ .unwrap_or(extern_crate.ident.span);
+ visitor.r.lint_buffer.buffer_lint_with_diagnostic(
+ UNUSED_EXTERN_CRATES,
+ extern_crate.id,
+ extern_crate.span,
+ "`extern crate` is not idiomatic in the new edition",
+ BuiltinLintDiagnostics::ExternCrateNotIdiomatic { vis_span, ident_span },
+ );
+ }
}
}
diff --git a/compiler/rustc_resolve/src/def_collector.rs b/compiler/rustc_resolve/src/def_collector.rs
index 2764a6c28..e7ff236f8 100644
--- a/compiler/rustc_resolve/src/def_collector.rs
+++ b/compiler/rustc_resolve/src/def_collector.rs
@@ -9,7 +9,7 @@ use rustc_span::symbol::sym;
use rustc_span::Span;
pub(crate) fn collect_definitions(
- resolver: &mut Resolver<'_>,
+ resolver: &mut Resolver<'_, '_>,
fragment: &AstFragment,
expansion: LocalExpnId,
) {
@@ -18,14 +18,14 @@ pub(crate) fn collect_definitions(
}
/// Creates `DefId`s for nodes in the AST.
-struct DefCollector<'a, 'b> {
- resolver: &'a mut Resolver<'b>,
+struct DefCollector<'a, 'b, 'tcx> {
+ resolver: &'a mut Resolver<'b, 'tcx>,
parent_def: LocalDefId,
impl_trait_context: ImplTraitContext,
expansion: LocalExpnId,
}
-impl<'a, 'b> DefCollector<'a, 'b> {
+impl<'a, 'b, 'tcx> DefCollector<'a, 'b, 'tcx> {
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);
@@ -81,7 +81,7 @@ impl<'a, 'b> DefCollector<'a, 'b> {
}
}
-impl<'a, 'b> visit::Visitor<'a> for DefCollector<'a, 'b> {
+impl<'a, 'b, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'b, 'tcx> {
fn visit_item(&mut self, i: &'a Item) {
debug!("visit_item: {:?}", i);
diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs
index 366086152..7add59ac6 100644
--- a/compiler/rustc_resolve/src/diagnostics.rs
+++ b/compiler/rustc_resolve/src/diagnostics.rs
@@ -12,25 +12,24 @@ use rustc_errors::{struct_span_err, SuggestionStyle};
use rustc_feature::BUILTIN_ATTRIBUTES;
use rustc_hir::def::Namespace::{self, *};
use rustc_hir::def::{self, CtorKind, CtorOf, DefKind, NonMacroAttrKind, PerNS};
-use rustc_hir::def_id::{DefId, LocalDefId, CRATE_DEF_ID, LOCAL_CRATE};
+use rustc_hir::def_id::{DefId, CRATE_DEF_ID, LOCAL_CRATE};
use rustc_hir::PrimTy;
-use rustc_index::vec::IndexVec;
use rustc_middle::bug;
-use rustc_middle::ty::DefIdTree;
+use rustc_middle::ty::{DefIdTree, TyCtxt};
use rustc_session::lint::builtin::ABSOLUTE_PATHS_NOT_STARTING_WITH_CRATE;
use rustc_session::lint::builtin::MACRO_EXPANDED_MACRO_EXPORTS_ACCESSED_BY_ABSOLUTE_PATHS;
use rustc_session::lint::BuiltinLintDiagnostics;
use rustc_session::Session;
+use rustc_span::edit_distance::find_best_match_for_name;
use rustc_span::edition::Edition;
use rustc_span::hygiene::MacroKind;
-use rustc_span::lev_distance::find_best_match_for_name;
use rustc_span::source_map::SourceMap;
use rustc_span::symbol::{kw, sym, Ident, Symbol};
use rustc_span::{BytePos, Span, SyntaxContext};
use thin_vec::ThinVec;
use crate::errors as errs;
-use crate::imports::{Import, ImportKind, ImportResolver};
+use crate::imports::{Import, ImportKind};
use crate::late::{PatternSource, Rib};
use crate::path_names_to_string;
use crate::{AmbiguityError, AmbiguityErrorMisc, AmbiguityKind, BindingError, Finalize};
@@ -114,7 +113,7 @@ fn reduce_impl_span_to_impl_keyword(sm: &SourceMap, impl_span: Span) -> Span {
sm.span_until_whitespace(impl_span)
}
-impl<'a> Resolver<'a> {
+impl<'a, 'tcx> Resolver<'a, 'tcx> {
pub(crate) fn report_errors(&mut self, krate: &Crate) {
self.report_with_use_injections(krate);
@@ -154,8 +153,7 @@ impl<'a> Resolver<'a> {
if !candidates.is_empty() {
show_candidates(
- &self.session,
- &self.untracked.source_span,
+ self.tcx,
&mut err,
span,
&candidates,
@@ -191,6 +189,8 @@ impl<'a> Resolver<'a> {
}
let container = match parent.kind {
+ // Avoid using TyCtxt::def_kind_descr in the resolver, because it
+ // indirectly *calls* the resolver, and would cause a query cycle.
ModuleKind::Def(kind, _, _) => kind.descr(parent.def_id()),
ModuleKind::Block => "block",
};
@@ -206,7 +206,7 @@ impl<'a> Resolver<'a> {
};
let (name, span) =
- (ident.name, self.session.source_map().guess_head_span(new_binding.span));
+ (ident.name, self.tcx.sess.source_map().guess_head_span(new_binding.span));
if let Some(s) = self.name_already_seen.get(&name) {
if s == &span {
@@ -226,15 +226,15 @@ impl<'a> Resolver<'a> {
let msg = format!("the name `{}` is defined multiple times", name);
let mut err = match (old_binding.is_extern_crate(), new_binding.is_extern_crate()) {
- (true, true) => struct_span_err!(self.session, span, E0259, "{}", msg),
+ (true, true) => struct_span_err!(self.tcx.sess, span, E0259, "{}", msg),
(true, _) | (_, true) => match new_binding.is_import() && old_binding.is_import() {
- true => struct_span_err!(self.session, span, E0254, "{}", msg),
- false => struct_span_err!(self.session, span, E0260, "{}", msg),
+ true => struct_span_err!(self.tcx.sess, span, E0254, "{}", msg),
+ false => struct_span_err!(self.tcx.sess, span, E0260, "{}", msg),
},
_ => match (old_binding.is_import_user_facing(), new_binding.is_import_user_facing()) {
- (false, false) => struct_span_err!(self.session, span, E0428, "{}", msg),
- (true, true) => struct_span_err!(self.session, span, E0252, "{}", msg),
- _ => struct_span_err!(self.session, span, E0255, "{}", msg),
+ (false, false) => struct_span_err!(self.tcx.sess, span, E0428, "{}", msg),
+ (true, true) => struct_span_err!(self.tcx.sess, span, E0252, "{}", msg),
+ _ => struct_span_err!(self.tcx.sess, span, E0255, "{}", msg),
},
};
@@ -248,7 +248,7 @@ impl<'a> Resolver<'a> {
err.span_label(span, format!("`{}` re{} here", name, new_participle));
if !old_binding.span.is_dummy() && old_binding.span != span {
err.span_label(
- self.session.source_map().guess_head_span(old_binding.span),
+ self.tcx.sess.source_map().guess_head_span(old_binding.span),
format!("previous {} of the {} `{}` here", old_noun, old_kind, name),
);
}
@@ -352,7 +352,7 @@ impl<'a> Resolver<'a> {
if let Some(pos) =
source.span.hi().0.checked_sub(binding_span.lo().0).map(|pos| pos as usize)
{
- if let Ok(snippet) = self.session.source_map().span_to_snippet(binding_span) {
+ if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(binding_span) {
if pos <= snippet.len() {
suggestion = Some(format!(
"{} as {}{}",
@@ -426,12 +426,12 @@ impl<'a> Resolver<'a> {
// `a` and `import.use_span` is `issue_52891::{d, e, a};`.
let (found_closing_brace, span) =
- find_span_of_binding_until_next_binding(self.session, binding_span, import.use_span);
+ find_span_of_binding_until_next_binding(self.tcx.sess, binding_span, import.use_span);
// If there was a closing brace then identify the span to remove any trailing commas from
// previous imports.
if found_closing_brace {
- if let Some(span) = extend_span_to_previous_binding(self.session, span) {
+ if let Some(span) = extend_span_to_previous_binding(self.tcx.sess, span) {
err.tool_only_span_suggestion(span, message, "", Applicability::MaybeIncorrect);
} else {
// Remove the entire line if we cannot extend the span back, this indicates an
@@ -462,7 +462,9 @@ impl<'a> Resolver<'a> {
let first_name = match path.get(0) {
// In the 2018 edition this lint is a hard error, so nothing to do
- Some(seg) if seg.ident.span.rust_2015() && self.session.rust_2015() => seg.ident.name,
+ Some(seg) if seg.ident.span.is_rust_2015() && self.tcx.sess.is_rust_2015() => {
+ seg.ident.name
+ }
_ => return,
};
@@ -539,14 +541,14 @@ impl<'a> Resolver<'a> {
match resolution_error {
ResolutionError::GenericParamsFromOuterFunction(outer_res, has_generic_params) => {
let mut err = struct_span_err!(
- self.session,
+ self.tcx.sess,
span,
E0401,
"can't use generic parameters from outer function",
);
err.span_label(span, "use of generic parameter from outer function");
- let sm = self.session.source_map();
+ let sm = self.tcx.sess.source_map();
let def_id = match outer_res {
Res::SelfTyParam { .. } => {
err.span_label(span, "can't use `Self` here");
@@ -603,10 +605,11 @@ impl<'a> Resolver<'a> {
err
}
ResolutionError::NameAlreadyUsedInParameterList(name, first_use_span) => self
- .session
+ .tcx
+ .sess
.create_err(errs::NameAlreadyUsedInParameterList { span, first_use_span, name }),
ResolutionError::MethodNotMemberOfTrait(method, trait_, candidate) => {
- self.session.create_err(errs::MethodNotMemberOfTrait {
+ self.tcx.sess.create_err(errs::MethodNotMemberOfTrait {
span,
method,
trait_,
@@ -617,7 +620,7 @@ impl<'a> Resolver<'a> {
})
}
ResolutionError::TypeNotMemberOfTrait(type_, trait_, candidate) => {
- self.session.create_err(errs::TypeNotMemberOfTrait {
+ self.tcx.sess.create_err(errs::TypeNotMemberOfTrait {
span,
type_,
trait_,
@@ -628,7 +631,7 @@ impl<'a> Resolver<'a> {
})
}
ResolutionError::ConstNotMemberOfTrait(const_, trait_, candidate) => {
- self.session.create_err(errs::ConstNotMemberOfTrait {
+ self.tcx.sess.create_err(errs::ConstNotMemberOfTrait {
span,
const_,
trait_,
@@ -646,7 +649,7 @@ impl<'a> Resolver<'a> {
let msp = MultiSpan::from_spans(target_sp.clone());
let mut err = struct_span_err!(
- self.session,
+ self.tcx.sess,
msp,
E0408,
"variable `{}` is not bound in all patterns",
@@ -684,8 +687,7 @@ impl<'a> Resolver<'a> {
err.span_help(span, &help_msg);
}
show_candidates(
- &self.session,
- &self.untracked.source_span,
+ self.tcx,
&mut err,
Some(span),
&import_suggestions,
@@ -699,17 +701,19 @@ impl<'a> Resolver<'a> {
err
}
ResolutionError::VariableBoundWithDifferentMode(variable_name, first_binding_span) => {
- self.session.create_err(errs::VariableBoundWithDifferentMode {
+ self.tcx.sess.create_err(errs::VariableBoundWithDifferentMode {
span,
first_binding_span,
variable_name,
})
}
ResolutionError::IdentifierBoundMoreThanOnceInParameterList(identifier) => self
- .session
+ .tcx
+ .sess
.create_err(errs::IdentifierBoundMoreThanOnceInParameterList { span, identifier }),
ResolutionError::IdentifierBoundMoreThanOnceInSamePattern(identifier) => self
- .session
+ .tcx
+ .sess
.create_err(errs::IdentifierBoundMoreThanOnceInSamePattern { span, identifier }),
ResolutionError::UndeclaredLabel { name, suggestion } => {
let ((sub_reachable, sub_reachable_suggestion), sub_unreachable) = match suggestion
@@ -735,7 +739,7 @@ impl<'a> Resolver<'a> {
// No similarly-named labels exist.
None => ((None, None), None),
};
- self.session.create_err(errs::UndeclaredLabel {
+ self.tcx.sess.create_err(errs::UndeclaredLabel {
span,
name,
sub_reachable,
@@ -760,21 +764,22 @@ impl<'a> Resolver<'a> {
};
(Some(suggestion), Some(mpart_suggestion))
};
- self.session.create_err(errs::SelfImportsOnlyAllowedWithin {
+ self.tcx.sess.create_err(errs::SelfImportsOnlyAllowedWithin {
span,
suggestion,
mpart_suggestion,
})
}
ResolutionError::SelfImportCanOnlyAppearOnceInTheList => {
- self.session.create_err(errs::SelfImportCanOnlyAppearOnceInTheList { span })
- }
- ResolutionError::SelfImportOnlyInImportListWithNonEmptyPrefix => {
- self.session.create_err(errs::SelfImportOnlyInImportListWithNonEmptyPrefix { span })
+ self.tcx.sess.create_err(errs::SelfImportCanOnlyAppearOnceInTheList { span })
}
+ ResolutionError::SelfImportOnlyInImportListWithNonEmptyPrefix => self
+ .tcx
+ .sess
+ .create_err(errs::SelfImportOnlyInImportListWithNonEmptyPrefix { span }),
ResolutionError::FailedToResolve { label, suggestion } => {
let mut err =
- struct_span_err!(self.session, span, E0433, "failed to resolve: {}", &label);
+ struct_span_err!(self.tcx.sess, span, E0433, "failed to resolve: {}", &label);
err.span_label(span, label);
if let Some((suggestions, msg, applicability)) = suggestion {
@@ -788,7 +793,7 @@ impl<'a> Resolver<'a> {
err
}
ResolutionError::CannotCaptureDynamicEnvironmentInFnItem => {
- self.session.create_err(errs::CannotCaptureDynamicEnvironmentInFnItem { span })
+ self.tcx.sess.create_err(errs::CannotCaptureDynamicEnvironmentInFnItem { span })
}
ResolutionError::AttemptToUseNonConstantValueInConstant(ident, suggestion, current) => {
// let foo =...
@@ -800,12 +805,13 @@ impl<'a> Resolver<'a> {
// the further the two are apart, the higher the chance of the suggestion being wrong
let sp = self
- .session
+ .tcx
+ .sess
.source_map()
.span_extend_to_prev_str(ident.span, current, true, false);
let ((with, with_label), without) = match sp {
- Some(sp) if !self.session.source_map().is_multiline(sp) => {
+ Some(sp) if !self.tcx.sess.source_map().is_multiline(sp) => {
let sp = sp.with_lo(BytePos(sp.lo().0 - (current.len() as u32)));
(
(Some(errs::AttemptToUseNonConstantValueInConstantWithSuggestion {
@@ -826,7 +832,7 @@ impl<'a> Resolver<'a> {
),
};
- self.session.create_err(errs::AttemptToUseNonConstantValueInConstant {
+ self.tcx.sess.create_err(errs::AttemptToUseNonConstantValueInConstant {
span,
with,
with_label,
@@ -840,7 +846,7 @@ impl<'a> Resolver<'a> {
article,
shadowed_binding,
shadowed_binding_span,
- } => self.session.create_err(errs::BindingShadowsSomethingUnacceptable {
+ } => self.tcx.sess.create_err(errs::BindingShadowsSomethingUnacceptable {
span,
shadowing_binding,
shadowed_binding,
@@ -857,13 +863,13 @@ impl<'a> Resolver<'a> {
name,
}),
ResolutionError::ForwardDeclaredGenericParam => {
- self.session.create_err(errs::ForwardDeclaredGenericParam { span })
+ self.tcx.sess.create_err(errs::ForwardDeclaredGenericParam { span })
}
ResolutionError::ParamInTyOfConstParam(name) => {
- self.session.create_err(errs::ParamInTyOfConstParam { span, name })
+ self.tcx.sess.create_err(errs::ParamInTyOfConstParam { span, name })
}
ResolutionError::ParamInNonTrivialAnonConst { name, is_type } => {
- self.session.create_err(errs::ParamInNonTrivialAnonConst {
+ self.tcx.sess.create_err(errs::ParamInNonTrivialAnonConst {
span,
name,
sub_is_type: if is_type {
@@ -872,13 +878,14 @@ impl<'a> Resolver<'a> {
errs::ParamInNonTrivialAnonConstIsType::NotAType { name }
},
help: self
- .session
+ .tcx
+ .sess
.is_nightly_build()
.then_some(errs::ParamInNonTrivialAnonConstHelp),
})
}
ResolutionError::SelfInGenericParamDefault => {
- self.session.create_err(errs::SelfInGenericParamDefault { span })
+ self.tcx.sess.create_err(errs::SelfInGenericParamDefault { span })
}
ResolutionError::UnreachableLabel { name, definition_span, suggestion } => {
let ((sub_suggestion_label, sub_suggestion), sub_unreachable_label) =
@@ -906,7 +913,7 @@ impl<'a> Resolver<'a> {
// No similarly-named labels exist.
None => ((None, None), None),
};
- self.session.create_err(errs::UnreachableLabel {
+ self.tcx.sess.create_err(errs::UnreachableLabel {
span,
name,
definition_span,
@@ -922,7 +929,7 @@ impl<'a> Resolver<'a> {
trait_item_span,
trait_path,
} => {
- let mut err = self.session.struct_span_err_with_code(
+ let mut err = self.tcx.sess.struct_span_err_with_code(
span,
&format!(
"item `{}` is an associated {}, which doesn't match its trait `{}`",
@@ -935,9 +942,12 @@ impl<'a> Resolver<'a> {
err
}
ResolutionError::TraitImplDuplicate { name, trait_item_span, old_span } => self
- .session
+ .tcx
+ .sess
.create_err(errs::TraitImplDuplicate { span, name, trait_item_span, old_span }),
- ResolutionError::InvalidAsmSym => self.session.create_err(errs::InvalidAsmSym { span }),
+ ResolutionError::InvalidAsmSym => {
+ self.tcx.sess.create_err(errs::InvalidAsmSym { span })
+ }
}
}
@@ -947,7 +957,7 @@ impl<'a> Resolver<'a> {
) -> ErrorGuaranteed {
match vis_resolution_error {
VisResolutionError::Relative2018(span, path) => {
- self.session.create_err(errs::Relative2018 {
+ self.tcx.sess.create_err(errs::Relative2018 {
span,
path_span: path.span,
// intentionally converting to String, as the text would also be used as
@@ -956,18 +966,20 @@ impl<'a> Resolver<'a> {
})
}
VisResolutionError::AncestorOnly(span) => {
- self.session.create_err(errs::AncestorOnly(span))
+ self.tcx.sess.create_err(errs::AncestorOnly(span))
}
VisResolutionError::FailedToResolve(span, label, suggestion) => {
self.into_struct_error(span, ResolutionError::FailedToResolve { label, suggestion })
}
VisResolutionError::ExpectedFound(span, path_str, res) => {
- self.session.create_err(errs::ExpectedFound { span, res, path_str })
+ self.tcx.sess.create_err(errs::ExpectedFound { span, res, path_str })
}
VisResolutionError::Indeterminate(span) => {
- self.session.create_err(errs::Indeterminate(span))
+ self.tcx.sess.create_err(errs::Indeterminate(span))
+ }
+ VisResolutionError::ModuleOnly(span) => {
+ self.tcx.sess.create_err(errs::ModuleOnly(span))
}
- VisResolutionError::ModuleOnly(span) => self.session.create_err(errs::ModuleOnly(span)),
}
.emit()
}
@@ -1204,7 +1216,7 @@ impl<'a> Resolver<'a> {
// a note about editions
let note = if let Some(did) = did {
let requires_note = !did.is_local()
- && this.cstore().item_attrs_untracked(did, this.session).any(
+ && this.cstore().item_attrs_untracked(did, this.tcx.sess).any(
|attr| {
if attr.has_name(sym::rustc_diagnostic_item) {
[sym::TryInto, sym::TryFrom, sym::FromIterator]
@@ -1302,7 +1314,7 @@ impl<'a> Resolver<'a> {
// otherwise cause duplicate suggestions.
continue;
}
- let crate_id = self.crate_loader().maybe_process_path_extern(ident.name);
+ let crate_id = self.crate_loader(|c| c.maybe_process_path_extern(ident.name));
if let Some(crate_id) = crate_id {
let crate_root = self.expect_module(crate_id.as_def_id());
suggestions.extend(self.lookup_import_candidates_from_module(
@@ -1339,8 +1351,7 @@ impl<'a> Resolver<'a> {
let import_suggestions =
self.lookup_import_candidates(ident, Namespace::MacroNS, parent_scope, is_expected);
show_candidates(
- &self.session,
- &self.untracked.source_span,
+ self.tcx,
err,
None,
&import_suggestions,
@@ -1364,7 +1375,7 @@ impl<'a> Resolver<'a> {
&& let ModuleKind::Def(DefKind::Enum, def_id, _) = parent_scope.module.kind
&& let Some(span) = self.opt_span(def_id)
{
- let source_map = self.session.source_map();
+ let source_map = self.tcx.sess.source_map();
let head_span = source_map.guess_head_span(span);
if let Ok(head) = source_map.span_to_snippet(head_span) {
err.span_suggestion(head_span, "consider adding a derive", format!("#[derive(Default)]\n{head}"), Applicability::MaybeIncorrect);
@@ -1441,7 +1452,7 @@ impl<'a> Resolver<'a> {
};
let def_span = suggestion.res.opt_def_id().and_then(|def_id| match def_id.krate {
LOCAL_CRATE => self.opt_span(def_id),
- _ => Some(self.cstore().get_span_untracked(def_id, self.session)),
+ _ => Some(self.cstore().get_span_untracked(def_id, self.tcx.sess)),
});
if let Some(def_span) = def_span {
if span.overlaps(def_span) {
@@ -1471,7 +1482,7 @@ impl<'a> Resolver<'a> {
};
err.span_label(
- self.session.source_map().guess_head_span(def_span),
+ self.tcx.sess.source_map().guess_head_span(def_span),
&format!(
"{}{} `{}` defined here",
prefix,
@@ -1496,7 +1507,7 @@ impl<'a> Resolver<'a> {
fn binding_description(&self, b: &NameBinding<'_>, ident: Ident, from_prelude: bool) -> String {
let res = b.res();
- if b.span.is_dummy() || !self.session.source_map().is_span_accessible(b.span) {
+ if b.span.is_dummy() || !self.tcx.sess.source_map().is_span_accessible(b.span) {
// These already contain the "built-in" prefix or look bad with it.
let add_built_in =
!matches!(b.res(), Res::NonMacroAttr(..) | Res::PrimTy(..) | Res::ToolMod);
@@ -1504,7 +1515,7 @@ impl<'a> Resolver<'a> {
("", " from prelude")
} else if b.is_extern_crate()
&& !b.is_import()
- && self.session.opts.externs.get(ident.as_str()).is_some()
+ && self.tcx.sess.opts.externs.get(ident.as_str()).is_some()
{
("", " passed with `--extern`")
} else if add_built_in {
@@ -1530,7 +1541,7 @@ impl<'a> Resolver<'a> {
(b1, b2, misc1, misc2, false)
};
- let mut err = struct_span_err!(self.session, ident.span, E0659, "`{ident}` is ambiguous");
+ let mut err = struct_span_err!(self.tcx.sess, ident.span, E0659, "`{ident}` is ambiguous");
err.span_label(ident.span, "ambiguous name");
err.note(&format!("ambiguous because of {}", kind.descr()));
@@ -1552,12 +1563,12 @@ impl<'a> Resolver<'a> {
if b.is_extern_crate() && ident.span.rust_2018() {
help_msgs.push(format!("use `::{ident}` to refer to this {thing} unambiguously"))
}
- if misc == AmbiguityErrorMisc::SuggestCrate {
- help_msgs
- .push(format!("use `crate::{ident}` to refer to this {thing} unambiguously"))
- } else if misc == AmbiguityErrorMisc::SuggestSelf {
- help_msgs
- .push(format!("use `self::{ident}` to refer to this {thing} unambiguously"))
+ match misc {
+ AmbiguityErrorMisc::SuggestCrate => help_msgs
+ .push(format!("use `crate::{ident}` to refer to this {thing} unambiguously")),
+ AmbiguityErrorMisc::SuggestSelf => help_msgs
+ .push(format!("use `self::{ident}` to refer to this {thing} unambiguously")),
+ AmbiguityErrorMisc::FromPrelude | AmbiguityErrorMisc::None => {}
}
err.span_note(b.span, &note_msg);
@@ -1602,7 +1613,7 @@ impl<'a> Resolver<'a> {
// Print the primary message.
let descr = get_descr(binding);
let mut err =
- struct_span_err!(self.session, ident.span, E0603, "{} `{}` is private", descr, ident);
+ struct_span_err!(self.tcx.sess, ident.span, E0603, "{} `{}` is private", descr, ident);
err.span_label(ident.span, &format!("private {}", descr));
if let Some(span) = ctor_fields_span {
err.span_label(span, "a constructor is private if any of the fields is private");
@@ -1648,7 +1659,7 @@ impl<'a> Resolver<'a> {
which = if first { "" } else { " which" },
dots = if next_binding.is_some() { "..." } else { "" },
);
- let def_span = self.session.source_map().guess_head_span(binding.span);
+ let def_span = self.tcx.sess.source_map().guess_head_span(binding.span);
let mut note_span = MultiSpan::from_span(def_span);
if !first && binding.vis.is_public() {
note_span.push_span_label(def_span, "consider importing it directly");
@@ -1717,7 +1728,7 @@ impl<'a> Resolver<'a> {
Applicability::MaybeIncorrect,
)),
)
- } else if self.session.edition() == Edition::Edition2015 {
+ } else if self.tcx.sess.is_rust_2015() {
(
format!("maybe a missing crate `{ident}`?"),
Some((
@@ -1736,7 +1747,7 @@ impl<'a> Resolver<'a> {
let parent = match parent {
// ::foo is mounted at the crate root for 2015, and is the extern
// prelude for 2018+
- kw::PathRoot if self.session.edition() > Edition::Edition2015 => {
+ kw::PathRoot if self.tcx.sess.edition() > Edition::Edition2015 => {
"the list of imported crates".to_owned()
}
kw::PathRoot | kw::Crate => "the crate root".to_owned(),
@@ -1795,6 +1806,8 @@ impl<'a> Resolver<'a> {
found("module")
} else {
match binding.res() {
+ // Avoid using TyCtxt::def_kind_descr in the resolver, because it
+ // indirectly *calls* the resolver, and would cause a query cycle.
Res::Def(kind, id) => found(kind.descr(id)),
_ => found(ns_to_try.descr()),
}
@@ -1879,15 +1892,13 @@ impl<'a> Resolver<'a> {
(format!("use of undeclared crate or module `{}`", ident), suggestion)
}
}
-}
-impl<'a, 'b> ImportResolver<'a, 'b> {
/// Adds suggestions for a path that cannot be resolved.
pub(crate) fn make_path_suggestion(
&mut self,
span: Span,
mut path: Vec<Segment>,
- parent_scope: &ParentScope<'b>,
+ parent_scope: &ParentScope<'a>,
) -> Option<(Vec<Segment>, Option<String>)> {
debug!("make_path_suggestion: span={:?} path={:?}", span, path);
@@ -1922,11 +1933,11 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
fn make_missing_self_suggestion(
&mut self,
mut path: Vec<Segment>,
- parent_scope: &ParentScope<'b>,
+ parent_scope: &ParentScope<'a>,
) -> Option<(Vec<Segment>, Option<String>)> {
// Replace first ident with `self` and check if that is valid.
path[0].ident.name = kw::SelfLower;
- let result = self.r.maybe_resolve_path(&path, None, parent_scope);
+ let result = self.maybe_resolve_path(&path, None, parent_scope);
debug!("make_missing_self_suggestion: path={:?} result={:?}", path, result);
if let PathResult::Module(..) = result { Some((path, None)) } else { None }
}
@@ -1941,11 +1952,11 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
fn make_missing_crate_suggestion(
&mut self,
mut path: Vec<Segment>,
- parent_scope: &ParentScope<'b>,
+ parent_scope: &ParentScope<'a>,
) -> Option<(Vec<Segment>, Option<String>)> {
// Replace first ident with `crate` and check if that is valid.
path[0].ident.name = kw::Crate;
- let result = self.r.maybe_resolve_path(&path, None, parent_scope);
+ let result = self.maybe_resolve_path(&path, None, parent_scope);
debug!("make_missing_crate_suggestion: path={:?} result={:?}", path, result);
if let PathResult::Module(..) = result {
Some((
@@ -1972,11 +1983,11 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
fn make_missing_super_suggestion(
&mut self,
mut path: Vec<Segment>,
- parent_scope: &ParentScope<'b>,
+ parent_scope: &ParentScope<'a>,
) -> Option<(Vec<Segment>, Option<String>)> {
// Replace first ident with `crate` and check if that is valid.
path[0].ident.name = kw::Super;
- let result = self.r.maybe_resolve_path(&path, None, parent_scope);
+ let result = self.maybe_resolve_path(&path, None, parent_scope);
debug!("make_missing_super_suggestion: path={:?} result={:?}", path, result);
if let PathResult::Module(..) = result { Some((path, None)) } else { None }
}
@@ -1994,9 +2005,9 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
fn make_external_crate_suggestion(
&mut self,
mut path: Vec<Segment>,
- parent_scope: &ParentScope<'b>,
+ parent_scope: &ParentScope<'a>,
) -> Option<(Vec<Segment>, Option<String>)> {
- if path[1].ident.span.rust_2015() {
+ if path[1].ident.span.is_rust_2015() {
return None;
}
@@ -2004,13 +2015,13 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
// 1) some consistent ordering for emitted diagnostics, and
// 2) `std` suggestions before `core` suggestions.
let mut extern_crate_names =
- self.r.extern_prelude.iter().map(|(ident, _)| ident.name).collect::<Vec<_>>();
+ self.extern_prelude.iter().map(|(ident, _)| ident.name).collect::<Vec<_>>();
extern_crate_names.sort_by(|a, b| b.as_str().partial_cmp(a.as_str()).unwrap());
for name in extern_crate_names.into_iter() {
// Replace first ident with a crate name and check if that is valid.
path[0].ident.name = name;
- let result = self.r.maybe_resolve_path(&path, None, parent_scope);
+ let result = self.maybe_resolve_path(&path, None, parent_scope);
debug!(
"make_external_crate_suggestion: name={:?} path={:?} result={:?}",
name, path, result
@@ -2037,8 +2048,8 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
/// ```
pub(crate) fn check_for_module_export_macro(
&mut self,
- import: &'b Import<'b>,
- module: ModuleOrUniformRoot<'b>,
+ import: &'a Import<'a>,
+ module: ModuleOrUniformRoot<'a>,
ident: Ident,
) -> Option<(Option<Suggestion>, Option<String>)> {
let ModuleOrUniformRoot::Module(mut crate_module) = module else {
@@ -2055,8 +2066,8 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
return None;
}
- let resolutions = self.r.resolutions(crate_module).borrow();
- let resolution = resolutions.get(&self.r.new_key(ident, MacroNS))?;
+ let resolutions = self.resolutions(crate_module).borrow();
+ let resolution = resolutions.get(&self.new_key(ident, MacroNS))?;
let binding = resolution.borrow().binding()?;
if let Res::Def(DefKind::Macro(MacroKind::Bang), _) = binding.res() {
let module_name = crate_module.kind.name().unwrap();
@@ -2077,7 +2088,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
// ie. `use a::b::{c, d, e};`
// ^^^
let (found_closing_brace, binding_span) = find_span_of_binding_until_next_binding(
- self.r.session,
+ self.tcx.sess,
import.span,
import.use_span,
);
@@ -2096,7 +2107,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
// ie. `use a::b::{c, d};`
// ^^^
if let Some(previous_span) =
- extend_span_to_previous_binding(self.r.session, binding_span)
+ extend_span_to_previous_binding(self.tcx.sess, binding_span)
{
debug!("check_for_module_export_macro: previous_span={:?}", previous_span);
removal_span = removal_span.with_lo(previous_span.lo());
@@ -2114,7 +2125,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
// or `use a::{b, c, d}};`
// ^^^^^^^^^^^
let (has_nested, after_crate_name) = find_span_immediately_after_crate_name(
- self.r.session,
+ self.tcx.sess,
module_name,
import.use_span,
);
@@ -2123,7 +2134,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
has_nested, after_crate_name
);
- let source_map = self.r.session.source_map();
+ let source_map = self.tcx.sess.source_map();
// Make sure this is actually crate-relative.
let is_definitely_crate = import
@@ -2345,8 +2356,7 @@ pub(crate) enum DiagnosticMode {
}
pub(crate) fn import_candidates(
- session: &Session,
- source_span: &IndexVec<LocalDefId, Span>,
+ tcx: TyCtxt<'_>,
err: &mut Diagnostic,
// This is `None` if all placement locations are inside expansions
use_placement_span: Option<Span>,
@@ -2355,8 +2365,7 @@ pub(crate) fn import_candidates(
append: &str,
) {
show_candidates(
- session,
- source_span,
+ tcx,
err,
use_placement_span,
candidates,
@@ -2372,8 +2381,7 @@ pub(crate) fn import_candidates(
/// entities with that name in all crates. This method allows outputting the
/// results of this search in a programmer-friendly way
fn show_candidates(
- session: &Session,
- source_span: &IndexVec<LocalDefId, Span>,
+ tcx: TyCtxt<'_>,
err: &mut Diagnostic,
// This is `None` if all placement locations are inside expansions
use_placement_span: Option<Span>,
@@ -2498,8 +2506,8 @@ fn show_candidates(
);
if let Some(local_def_id) = def_id.and_then(|did| did.as_local()) {
- let span = source_span[local_def_id];
- let span = session.source_map().guess_head_span(span);
+ let span = tcx.source_span(local_def_id);
+ let span = tcx.sess.source_map().guess_head_span(span);
let mut multi_span = MultiSpan::from_span(span);
multi_span.push_span_label(span, "not accessible");
err.span_note(multi_span, &msg);
@@ -2529,8 +2537,8 @@ fn show_candidates(
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 = source_span[local_def_id];
- let span = session.source_map().guess_head_span(span);
+ let span = tcx.source_span(local_def_id);
+ let span = tcx.sess.source_map().guess_head_span(span);
spans.push((name, span));
} else {
if !has_colon {
diff --git a/compiler/rustc_resolve/src/effective_visibilities.rs b/compiler/rustc_resolve/src/effective_visibilities.rs
index b8efa3f8b..7bd90d7e3 100644
--- a/compiler/rustc_resolve/src/effective_visibilities.rs
+++ b/compiler/rustc_resolve/src/effective_visibilities.rs
@@ -1,4 +1,4 @@
-use crate::{NameBinding, NameBindingKind, Resolver, ResolverTree};
+use crate::{NameBinding, NameBindingKind, Resolver};
use rustc_ast::ast;
use rustc_ast::visit;
use rustc_ast::visit::Visitor;
@@ -7,8 +7,8 @@ use rustc_ast::EnumDef;
use rustc_data_structures::intern::Interned;
use rustc_hir::def_id::LocalDefId;
use rustc_hir::def_id::CRATE_DEF_ID;
+use rustc_middle::middle::privacy::Level;
use rustc_middle::middle::privacy::{EffectiveVisibilities, EffectiveVisibility};
-use rustc_middle::middle::privacy::{IntoDefIdTree, Level};
use rustc_middle::ty::{DefIdTree, Visibility};
use std::mem;
@@ -29,8 +29,8 @@ impl ParentId<'_> {
}
}
-pub struct EffectiveVisibilitiesVisitor<'r, 'a> {
- r: &'r mut Resolver<'a>,
+pub(crate) struct EffectiveVisibilitiesVisitor<'r, 'a, 'tcx> {
+ r: &'r mut Resolver<'a, 'tcx>,
def_effective_visibilities: EffectiveVisibilities,
/// While walking import chains we need to track effective visibilities per-binding, and def id
/// keys in `Resolver::effective_visibilities` are not enough for that, because multiple
@@ -41,7 +41,7 @@ pub struct EffectiveVisibilitiesVisitor<'r, 'a> {
changed: bool,
}
-impl Resolver<'_> {
+impl Resolver<'_, '_> {
fn nearest_normal_mod(&mut self, def_id: LocalDefId) -> LocalDefId {
self.get_nearest_non_block_module(def_id.to_def_id()).nearest_parent_mod().expect_local()
}
@@ -67,18 +67,14 @@ impl Resolver<'_> {
}
}
-impl<'a, 'b> IntoDefIdTree for &'b mut Resolver<'a> {
- type Tree = &'b Resolver<'a>;
- fn tree(self) -> Self::Tree {
- self
- }
-}
-
-impl<'r, 'a> EffectiveVisibilitiesVisitor<'r, 'a> {
+impl<'r, 'a, 'tcx> EffectiveVisibilitiesVisitor<'r, 'a, 'tcx> {
/// Fills the `Resolver::effective_visibilities` table with public & exported items
/// For now, this doesn't resolve macros (FIXME) and cannot resolve Impl, as we
/// need access to a TyCtxt for that.
- pub fn compute_effective_visibilities<'c>(r: &'r mut Resolver<'a>, krate: &'c Crate) {
+ pub(crate) fn compute_effective_visibilities<'c>(
+ r: &'r mut Resolver<'a, 'tcx>,
+ krate: &'c Crate,
+ ) {
let mut visitor = EffectiveVisibilitiesVisitor {
r,
def_effective_visibilities: Default::default(),
@@ -104,11 +100,7 @@ impl<'r, 'a> EffectiveVisibilitiesVisitor<'r, 'a> {
for (binding, eff_vis) in visitor.import_effective_visibilities.iter() {
let NameBindingKind::Import { import, .. } = binding.kind else { unreachable!() };
if let Some(node_id) = import.id() {
- r.effective_visibilities.update_eff_vis(
- r.local_def_id(node_id),
- eff_vis,
- ResolverTree(&r.untracked),
- )
+ r.effective_visibilities.update_eff_vis(r.local_def_id(node_id), eff_vis, r.tcx)
}
}
@@ -164,26 +156,28 @@ impl<'r, 'a> EffectiveVisibilitiesVisitor<'r, 'a> {
let nominal_vis = binding.vis.expect_local();
let private_vis = self.cheap_private_vis(parent_id);
let inherited_eff_vis = self.effective_vis_or_private(parent_id);
+ let tcx = self.r.tcx;
self.changed |= self.import_effective_visibilities.update(
binding,
nominal_vis,
- |r| (private_vis.unwrap_or_else(|| r.private_vis_import(binding)), r),
+ || private_vis.unwrap_or_else(|| self.r.private_vis_import(binding)),
inherited_eff_vis,
parent_id.level(),
- &mut *self.r,
+ tcx,
);
}
fn update_def(&mut self, def_id: LocalDefId, nominal_vis: Visibility, parent_id: ParentId<'a>) {
let private_vis = self.cheap_private_vis(parent_id);
let inherited_eff_vis = self.effective_vis_or_private(parent_id);
+ let tcx = self.r.tcx;
self.changed |= self.def_effective_visibilities.update(
def_id,
nominal_vis,
- |r| (private_vis.unwrap_or_else(|| r.private_vis_def(def_id)), r),
+ || private_vis.unwrap_or_else(|| self.r.private_vis_def(def_id)),
inherited_eff_vis,
parent_id.level(),
- &mut *self.r,
+ tcx,
);
}
@@ -192,7 +186,7 @@ impl<'r, 'a> EffectiveVisibilitiesVisitor<'r, 'a> {
}
}
-impl<'r, 'ast> Visitor<'ast> for EffectiveVisibilitiesVisitor<'ast, 'r> {
+impl<'r, 'ast, 'tcx> Visitor<'ast> for EffectiveVisibilitiesVisitor<'ast, 'r, 'tcx> {
fn visit_item(&mut self, item: &'ast ast::Item) {
let def_id = self.r.local_def_id(item.id);
// Update effective visibilities of nested items.
diff --git a/compiler/rustc_resolve/src/errors.rs b/compiler/rustc_resolve/src/errors.rs
index 2c4427746..867363f42 100644
--- a/compiler/rustc_resolve/src/errors.rs
+++ b/compiler/rustc_resolve/src/errors.rs
@@ -38,7 +38,7 @@ pub(crate) struct NameAlreadyUsedInParameterList {
#[primary_span]
#[label]
pub(crate) span: Span,
- #[label(first_use_of_name)]
+ #[label(resolve_first_use_of_name)]
pub(crate) first_use_span: Span,
pub(crate) name: Symbol,
}
@@ -121,7 +121,7 @@ pub(crate) struct VariableBoundWithDifferentMode {
#[primary_span]
#[label]
pub(crate) span: Span,
- #[label(first_binding_span)]
+ #[label(resolve_first_binding_span)]
pub(crate) first_binding_span: Span,
pub(crate) variable_name: Symbol,
}
@@ -293,7 +293,7 @@ pub(crate) struct BindingShadowsSomethingUnacceptable<'a> {
pub(crate) article: &'a str,
#[subdiagnostic]
pub(crate) sub_suggestion: Option<BindingShadowsSomethingUnacceptableSuggestion>,
- #[label(label_shadowed_binding)]
+ #[label(resolve_label_shadowed_binding)]
pub(crate) shadowed_binding_span: Span,
pub(crate) participle: &'a str,
pub(crate) name: Symbol,
@@ -369,7 +369,7 @@ pub(crate) struct UnreachableLabel {
#[label]
pub(crate) span: Span,
pub(crate) name: Symbol,
- #[label(label_definition_span)]
+ #[label(resolve_label_definition_span)]
pub(crate) definition_span: Span,
#[subdiagnostic]
pub(crate) sub_suggestion: Option<UnreachableLabelSubSuggestion>,
@@ -413,7 +413,7 @@ pub(crate) struct TraitImplMismatch {
pub(crate) span: Span,
pub(crate) name: Symbol,
pub(crate) kind: String,
- #[label(label_trait_item)]
+ #[label(resolve_label_trait_item)]
pub(crate) trait_item_span: Span,
pub(crate) trait_path: String,
pub(crate) code: String,
@@ -434,9 +434,9 @@ pub(crate) struct TraitImplDuplicate {
#[primary_span]
#[label]
pub(crate) span: Span,
- #[label(old_span_label)]
+ #[label(resolve_old_span_label)]
pub(crate) old_span: Span,
- #[label(trait_item_span)]
+ #[label(resolve_trait_item_span)]
pub(crate) trait_item_span: Span,
pub(crate) name: Symbol,
}
diff --git a/compiler/rustc_resolve/src/ident.rs b/compiler/rustc_resolve/src/ident.rs
index a84652a31..52f0b65fa 100644
--- a/compiler/rustc_resolve/src/ident.rs
+++ b/compiler/rustc_resolve/src/ident.rs
@@ -7,7 +7,6 @@ use rustc_middle::ty;
use rustc_session::lint::builtin::PROC_MACRO_DERIVE_RESOLUTION_FALLBACK;
use rustc_session::lint::BuiltinLintDiagnostics;
use rustc_span::def_id::LocalDefId;
-use rustc_span::edition::Edition;
use rustc_span::hygiene::{ExpnId, ExpnKind, LocalExpnId, MacroKind, SyntaxContext};
use rustc_span::symbol::{kw, Ident};
use rustc_span::{Span, DUMMY_SP};
@@ -29,7 +28,7 @@ use RibKind::*;
type Visibility = ty::Visibility<LocalDefId>;
-impl<'a> Resolver<'a> {
+impl<'a, 'tcx> Resolver<'a, 'tcx> {
/// A generic scope visitor.
/// Visits scopes in order to resolve some identifier in them or perform other actions.
/// If the callback returns `Some` result, we stop visiting scopes and return it.
@@ -86,7 +85,7 @@ impl<'a> Resolver<'a> {
// 4c. Standard library prelude (de-facto closed, controlled).
// 6. Language prelude: builtin attributes (closed, controlled).
- let rust_2015 = ctxt.edition() == Edition::Edition2015;
+ let rust_2015 = ctxt.edition().is_rust_2015();
let (ns, macro_kind, is_absolute_path) = match scope_set {
ScopeSet::All(ns, _) => (ns, None, false),
ScopeSet::AbsolutePath(ns) => (ns, None, true),
@@ -369,7 +368,7 @@ impl<'a> Resolver<'a> {
/// This is a variation of `fn resolve_ident_in_lexical_scope` that can be run during
/// expansion and import resolution (perhaps they can be merged in the future).
/// The function is used for resolving initial segments of macro paths (e.g., `foo` in
- /// `foo::bar!(); or `foo!();`) and also for import paths on 2018 edition.
+ /// `foo::bar!();` or `foo!();`) and also for import paths on 2018 edition.
#[instrument(level = "debug", skip(self, scope_set))]
pub(crate) fn early_resolve_ident_in_lexical_scope(
&mut self,
@@ -1180,7 +1179,7 @@ impl<'a> Resolver<'a> {
}
ConstantItemRibKind(trivial, _) => {
- let features = self.session.features_untracked();
+ let features = self.tcx.sess.features_untracked();
// HACK(min_const_generics): We currently only allow `N` or `{ N }`.
if !(trivial == ConstantHasGenerics::Yes
|| features.generic_const_exprs)
@@ -1209,7 +1208,7 @@ impl<'a> Resolver<'a> {
is_type: true,
},
);
- self.session.delay_span_bug(span, CG_BUG_STR);
+ self.tcx.sess.delay_span_bug(span, CG_BUG_STR);
}
return Res::Err;
@@ -1256,7 +1255,7 @@ impl<'a> Resolver<'a> {
| ForwardGenericParamBanRibKind => continue,
ConstantItemRibKind(trivial, _) => {
- let features = self.session.features_untracked();
+ let features = self.tcx.sess.features_untracked();
// HACK(min_const_generics): We currently only allow `N` or `{ N }`.
if !(trivial == ConstantHasGenerics::Yes
|| features.generic_const_exprs)
@@ -1269,7 +1268,7 @@ impl<'a> Resolver<'a> {
is_type: false,
},
);
- self.session.delay_span_bug(span, CG_BUG_STR);
+ self.tcx.sess.delay_span_bug(span, CG_BUG_STR);
}
return Res::Err;
@@ -1398,7 +1397,10 @@ impl<'a> Resolver<'a> {
module = Some(ModuleOrUniformRoot::ExternPrelude);
continue;
}
- if name == kw::PathRoot && ident.span.rust_2015() && self.session.rust_2018() {
+ if name == kw::PathRoot
+ && ident.span.is_rust_2015()
+ && self.tcx.sess.rust_2018()
+ {
// `::a::b` from 2015 macro on 2018 global edition
module = Some(ModuleOrUniformRoot::CrateRootAndExternPrelude);
continue;
@@ -1494,7 +1496,8 @@ impl<'a> Resolver<'a> {
record_segment_res(self, res);
} else if res == Res::ToolMod && i + 1 != path.len() {
if binding.is_import() {
- self.session
+ self.tcx
+ .sess
.struct_span_err(
ident.span,
"cannot use a tool module through an import",
diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs
index 00f65ac37..4dab0836d 100644
--- a/compiler/rustc_resolve/src/imports.rs
+++ b/compiler/rustc_resolve/src/imports.rs
@@ -21,8 +21,8 @@ use rustc_middle::span_bug;
use rustc_middle::ty;
use rustc_session::lint::builtin::{PUB_USE_OF_PRIVATE_EXTERN_CRATE, UNUSED_IMPORTS};
use rustc_session::lint::BuiltinLintDiagnostics;
+use rustc_span::edit_distance::find_best_match_for_name;
use rustc_span::hygiene::LocalExpnId;
-use rustc_span::lev_distance::find_best_match_for_name;
use rustc_span::symbol::{kw, Ident, Symbol};
use rustc_span::Span;
@@ -33,7 +33,7 @@ type Res = def::Res<NodeId>;
/// Contains data for specific kinds of imports.
#[derive(Clone)]
-pub enum ImportKind<'a> {
+pub(crate) enum ImportKind<'a> {
Single {
/// `source` in `use prefix::source as target`.
source: Ident,
@@ -157,11 +157,11 @@ pub(crate) struct Import<'a> {
}
impl<'a> Import<'a> {
- pub fn is_glob(&self) -> bool {
+ pub(crate) fn is_glob(&self) -> bool {
matches!(self.kind, ImportKind::Glob { .. })
}
- pub fn is_nested(&self) -> bool {
+ pub(crate) fn is_nested(&self) -> bool {
match self.kind {
ImportKind::Single { nested, .. } => nested,
_ => false,
@@ -210,6 +210,17 @@ impl<'a> NameResolution<'a> {
}
}
+/// An error that may be transformed into a diagnostic later. Used to combine multiple unresolved
+/// import errors within the same use tree into a single diagnostic.
+#[derive(Debug, Clone)]
+struct UnresolvedImportError {
+ span: Span,
+ label: Option<String>,
+ note: Option<String>,
+ suggestion: Option<Suggestion>,
+ candidates: Option<Vec<ImportSuggestion>>,
+}
+
// Reexports of the form `pub use foo as bar;` where `foo` is `extern crate foo;`
// are permitted for backward-compatibility under a deprecation lint.
fn pub_use_of_private_extern_crate_hack(import: &Import<'_>, binding: &NameBinding<'_>) -> bool {
@@ -225,7 +236,7 @@ fn pub_use_of_private_extern_crate_hack(import: &Import<'_>, binding: &NameBindi
}
}
-impl<'a> Resolver<'a> {
+impl<'a, 'tcx> Resolver<'a, 'tcx> {
/// Given a binding and an import that resolves to it,
/// return the corresponding binding defined by the import.
pub(crate) fn import(
@@ -333,7 +344,7 @@ impl<'a> Resolver<'a> {
// If the resolution becomes a success, define it in the module's glob importers.
fn update_resolution<T, F>(&mut self, module: Module<'a>, key: BindingKey, f: F) -> T
where
- F: FnOnce(&mut Resolver<'a>, &mut NameResolution<'a>) -> T,
+ F: FnOnce(&mut Resolver<'a, 'tcx>, &mut NameResolution<'a>) -> T,
{
// Ensure that `resolution` isn't borrowed when defining in the module's glob importers,
// during which the resolution might end up getting re-defined via a glob cycle.
@@ -392,24 +403,7 @@ impl<'a> Resolver<'a> {
}
}
}
-}
-
-/// An error that may be transformed into a diagnostic later. Used to combine multiple unresolved
-/// import errors within the same use tree into a single diagnostic.
-#[derive(Debug, Clone)]
-struct UnresolvedImportError {
- span: Span,
- label: Option<String>,
- note: Option<String>,
- suggestion: Option<Suggestion>,
- candidates: Option<Vec<ImportSuggestion>>,
-}
-
-pub struct ImportResolver<'a, 'b> {
- pub r: &'a mut Resolver<'b>,
-}
-impl<'a, 'b> ImportResolver<'a, 'b> {
// Import resolution
//
// This is a fixed-point algorithm. We resolve imports until our efforts
@@ -420,29 +414,29 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
/// Resolves all imports for the crate. This method performs the fixed-
/// point iteration.
- pub fn resolve_imports(&mut self) {
- let mut prev_num_indeterminates = self.r.indeterminate_imports.len() + 1;
- while self.r.indeterminate_imports.len() < prev_num_indeterminates {
- prev_num_indeterminates = self.r.indeterminate_imports.len();
- for import in mem::take(&mut self.r.indeterminate_imports) {
+ pub(crate) fn resolve_imports(&mut self) {
+ let mut prev_num_indeterminates = self.indeterminate_imports.len() + 1;
+ while self.indeterminate_imports.len() < prev_num_indeterminates {
+ prev_num_indeterminates = self.indeterminate_imports.len();
+ for import in mem::take(&mut self.indeterminate_imports) {
match self.resolve_import(&import) {
- true => self.r.determined_imports.push(import),
- false => self.r.indeterminate_imports.push(import),
+ true => self.determined_imports.push(import),
+ false => self.indeterminate_imports.push(import),
}
}
}
}
- pub fn finalize_imports(&mut self) {
- for module in self.r.arenas.local_modules().iter() {
+ pub(crate) fn finalize_imports(&mut self) {
+ for module in self.arenas.local_modules().iter() {
self.finalize_resolutions_in(module);
}
let mut seen_spans = FxHashSet::default();
let mut errors = vec![];
let mut prev_root_id: NodeId = NodeId::from_u32(0);
- let determined_imports = mem::take(&mut self.r.determined_imports);
- let indeterminate_imports = mem::take(&mut self.r.indeterminate_imports);
+ let determined_imports = mem::take(&mut self.determined_imports);
+ let indeterminate_imports = mem::take(&mut self.indeterminate_imports);
for (is_indeterminate, import) in determined_imports
.into_iter()
@@ -453,7 +447,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
// If this import is unresolved then create a dummy import
// resolution for it so that later resolve stages won't complain.
- self.r.import_dummy_binding(import);
+ self.import_dummy_binding(import);
if let Some(err) = unresolved_import_error {
if let ImportKind::Single { source, ref source_bindings, .. } = import.kind {
@@ -526,7 +520,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
.collect::<Vec<_>>();
let msg = format!("unresolved import{} {}", pluralize!(paths.len()), paths.join(", "),);
- let mut diag = struct_span_err!(self.r.session, span, E0432, "{}", &msg);
+ let mut diag = struct_span_err!(self.tcx.sess, span, E0432, "{}", &msg);
if let Some((_, UnresolvedImportError { note: Some(note), .. })) = errors.iter().last() {
diag.note(note);
@@ -548,8 +542,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
if let Some(candidates) = &err.candidates {
match &import.kind {
ImportKind::Single { nested: false, source, target, .. } => import_candidates(
- self.r.session,
- &self.r.untracked.source_span,
+ self.tcx,
&mut diag,
Some(err.span),
&candidates,
@@ -561,8 +554,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
),
ImportKind::Single { nested: true, source, target, .. } => {
import_candidates(
- self.r.session,
- &self.r.untracked.source_span,
+ self.tcx,
&mut diag,
None,
&candidates,
@@ -583,7 +575,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
/// Attempts to resolve the given import, returning true if its resolution is determined.
/// If successful, the resolved bindings are written into the module.
- fn resolve_import(&mut self, import: &'b Import<'b>) -> bool {
+ fn resolve_import(&mut self, import: &'a Import<'a>) -> bool {
debug!(
"(resolving import for module) resolving import `{}::...` in `{}`",
Segment::names_to_string(&import.module_path),
@@ -596,8 +588,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
// For better failure detection, pretend that the import will
// not define any names while resolving its module path.
let orig_vis = import.vis.take();
- let path_res =
- self.r.maybe_resolve_path(&import.module_path, None, &import.parent_scope);
+ let path_res = self.maybe_resolve_path(&import.module_path, None, &import.parent_scope);
import.vis.set(orig_vis);
match path_res {
@@ -625,7 +616,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
};
let mut indeterminate = false;
- self.r.per_ns(|this, ns| {
+ self.per_ns(|this, ns| {
if !type_ns_only || ns == TypeNS {
if let Err(Undetermined) = source_bindings[ns].get() {
// For better failure detection, pretend that the import will
@@ -658,7 +649,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
source_binding @ (Ok(..) | Err(Determined)) => {
if source_binding.is_ok() {
let msg = format!("`{}` is not directly importable", target);
- struct_span_err!(this.session, import.span, E0253, "{}", &msg)
+ struct_span_err!(this.tcx.sess, import.span, E0253, "{}", &msg)
.span_label(import.span, "cannot be imported directly")
.emit();
}
@@ -678,15 +669,15 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
///
/// Optionally returns an unresolved import error. This error is buffered and used to
/// consolidate multiple unresolved import errors into a single diagnostic.
- fn finalize_import(&mut self, import: &'b Import<'b>) -> Option<UnresolvedImportError> {
+ fn finalize_import(&mut self, import: &'a Import<'a>) -> Option<UnresolvedImportError> {
let orig_vis = import.vis.take();
let ignore_binding = match &import.kind {
ImportKind::Single { target_bindings, .. } => target_bindings[TypeNS].get(),
_ => None,
};
- let prev_ambiguity_errors_len = self.r.ambiguity_errors.len();
+ let prev_ambiguity_errors_len = self.ambiguity_errors.len();
let finalize = Finalize::with_root_span(import.root_id, import.span, import.root_span);
- let path_res = self.r.resolve_path(
+ let path_res = self.resolve_path(
&import.module_path,
None,
&import.parent_scope,
@@ -694,7 +685,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
ignore_binding,
);
- let no_ambiguity = self.r.ambiguity_errors.len() == prev_ambiguity_errors_len;
+ let no_ambiguity = self.ambiguity_errors.len() == prev_ambiguity_errors_len;
import.vis.set(orig_vis);
let module = match path_res {
PathResult::Module(module) => {
@@ -703,10 +694,10 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
if !ModuleOrUniformRoot::same_def(module, initial_module) && no_ambiguity {
span_bug!(import.span, "inconsistent resolution for an import");
}
- } else if self.r.privacy_errors.is_empty() {
+ } else if self.privacy_errors.is_empty() {
let msg = "cannot determine resolution for the import";
let msg_note = "import resolution is stuck, try simplifying other imports";
- self.r.session.struct_span_err(import.span, msg).note(msg_note).emit();
+ self.tcx.sess.struct_span_err(import.span, msg).note(msg_note).emit();
}
module
@@ -714,8 +705,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
PathResult::Failed { is_error_from_last_segment: false, span, label, suggestion } => {
if no_ambiguity {
assert!(import.imported_module.get().is_none());
- self.r
- .report_error(span, ResolutionError::FailedToResolve { label, suggestion });
+ self.report_error(span, ResolutionError::FailedToResolve { label, suggestion });
}
return None;
}
@@ -777,7 +767,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
// 2 segments, so the `resolve_path` above won't trigger it.
let mut full_path = import.module_path.clone();
full_path.push(Segment::from_ident(Ident::empty()));
- self.r.lint_if_path_starts_with_module(Some(finalize), &full_path, None);
+ self.lint_if_path_starts_with_module(Some(finalize), &full_path, None);
}
if let ModuleOrUniformRoot::Module(module) = module {
@@ -796,10 +786,10 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
}
if !is_prelude
&& let Some(max_vis) = max_vis.get()
- && !max_vis.is_at_least(import.expect_vis(), &*self.r)
+ && !max_vis.is_at_least(import.expect_vis(), &*self)
{
let msg = "glob import doesn't reexport anything because no candidate is public enough";
- self.r.lint_buffer.buffer_lint(UNUSED_IMPORTS, id, import.span, msg);
+ self.lint_buffer.buffer_lint(UNUSED_IMPORTS, id, import.span, msg);
}
return None;
}
@@ -807,7 +797,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
};
let mut all_ns_err = true;
- self.r.per_ns(|this, ns| {
+ self.per_ns(|this, ns| {
if !type_ns_only || ns == TypeNS {
let orig_vis = import.vis.take();
let binding = this.resolve_ident_in_module(
@@ -859,7 +849,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
let msg = "cannot determine resolution for the import";
let msg_note =
"import resolution is stuck, try simplifying other imports";
- this.session.struct_span_err(import.span, msg).note(msg_note).emit();
+ this.tcx.sess.struct_span_err(import.span, msg).note(msg_note).emit();
}
}
Err(..) => {
@@ -876,7 +866,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
if all_ns_err {
let mut all_ns_failed = true;
- self.r.per_ns(|this, ns| {
+ self.per_ns(|this, ns| {
if !type_ns_only || ns == TypeNS {
let binding = this.resolve_ident_in_module(
module,
@@ -894,9 +884,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
return if all_ns_failed {
let resolutions = match module {
- ModuleOrUniformRoot::Module(module) => {
- Some(self.r.resolutions(module).borrow())
- }
+ ModuleOrUniformRoot::Module(module) => Some(self.resolutions(module).borrow()),
_ => None,
};
let resolutions = resolutions.as_ref().into_iter().flat_map(|r| r.iter());
@@ -965,7 +953,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
};
let parent_suggestion =
- self.r.lookup_import_candidates(ident, TypeNS, &import.parent_scope, |_| true);
+ self.lookup_import_candidates(ident, TypeNS, &import.parent_scope, |_| true);
Some(UnresolvedImportError {
span: import.span,
@@ -987,7 +975,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
let mut reexport_error = None;
let mut any_successful_reexport = false;
let mut crate_private_reexport = false;
- self.r.per_ns(|this, ns| {
+ self.per_ns(|this, ns| {
if let Ok(binding) = source_bindings[ns].get() {
if !binding.vis.is_at_least(import.expect_vis(), &*this) {
reexport_error = Some((ns, binding));
@@ -1012,7 +1000,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
`pub`",
ident
);
- self.r.lint_buffer.buffer_lint(
+ self.lint_buffer.buffer_lint(
PUB_USE_OF_PRIVATE_EXTERN_CRATE,
import_id,
import.span,
@@ -1035,17 +1023,17 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
format!("re-export of private `{}`", ident)
};
- struct_span_err!(self.r.session, import.span, E0365, "{}", error_msg)
+ struct_span_err!(self.tcx.sess, import.span, E0365, "{}", error_msg)
.span_label(import.span, label_msg)
.note(&format!("consider declaring type or module `{}` with `pub`", ident))
.emit();
} else {
let mut err =
- struct_span_err!(self.r.session, import.span, E0364, "{error_msg}");
+ struct_span_err!(self.tcx.sess, import.span, E0364, "{error_msg}");
match binding.kind {
NameBindingKind::Res(Res::Def(DefKind::Macro(_), def_id))
// exclude decl_macro
- if self.r.get_macro_by_def_id(def_id).macro_rules =>
+ if self.get_macro_by_def_id(def_id).macro_rules =>
{
err.span_help(
binding.span,
@@ -1071,7 +1059,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
// 2 segments, so the `resolve_path` above won't trigger it.
let mut full_path = import.module_path.clone();
full_path.push(Segment::from_ident(ident));
- self.r.per_ns(|this, ns| {
+ self.per_ns(|this, ns| {
if let Ok(binding) = source_bindings[ns].get() {
this.lint_if_path_starts_with_module(Some(finalize), &full_path, Some(binding));
}
@@ -1081,7 +1069,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
// Record what this import resolves to for later uses in documentation,
// this may resolve to either a value or a type, but for documentation
// purposes it's good enough to just favor one over the other.
- self.r.per_ns(|this, ns| {
+ self.per_ns(|this, ns| {
if let Ok(binding) = source_bindings[ns].get() {
this.import_res_map.entry(import_id).or_default()[ns] = Some(binding.res());
}
@@ -1096,9 +1084,9 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
fn check_for_redundant_imports(
&mut self,
ident: Ident,
- import: &'b Import<'b>,
- source_bindings: &PerNS<Cell<Result<&'b NameBinding<'b>, Determinacy>>>,
- target_bindings: &PerNS<Cell<Option<&'b NameBinding<'b>>>>,
+ import: &'a Import<'a>,
+ source_bindings: &PerNS<Cell<Result<&'a NameBinding<'a>, Determinacy>>>,
+ target_bindings: &PerNS<Cell<Option<&'a NameBinding<'a>>>>,
target: Ident,
) {
// This function is only called for single imports.
@@ -1119,7 +1107,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
let mut redundant_span = PerNS { value_ns: None, type_ns: None, macro_ns: None };
- self.r.per_ns(|this, ns| {
+ self.per_ns(|this, ns| {
if let Ok(binding) = source_bindings[ns].get() {
if binding.res() == Res::Err {
return;
@@ -1149,7 +1137,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
let mut redundant_spans: Vec<_> = redundant_span.present_items().collect();
redundant_spans.sort();
redundant_spans.dedup();
- self.r.lint_buffer.buffer_lint_with_diagnostic(
+ self.lint_buffer.buffer_lint_with_diagnostic(
UNUSED_IMPORTS,
id,
import.span,
@@ -1159,22 +1147,22 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
}
}
- fn resolve_glob_import(&mut self, import: &'b Import<'b>) {
+ fn resolve_glob_import(&mut self, import: &'a Import<'a>) {
// This function is only called for glob imports.
let ImportKind::Glob { id, is_prelude, .. } = import.kind else { unreachable!() };
let ModuleOrUniformRoot::Module(module) = import.imported_module.get().unwrap() else {
- self.r.session.span_err(import.span, "cannot glob-import all possible crates");
+ self.tcx.sess.span_err(import.span, "cannot glob-import all possible crates");
return;
};
if module.is_trait() {
- self.r.session.span_err(import.span, "items in traits are not importable");
+ self.tcx.sess.span_err(import.span, "items in traits are not importable");
return;
} else if ptr::eq(module, import.parent_scope.module) {
return;
} else if is_prelude {
- self.r.prelude = Some(module);
+ self.prelude = Some(module);
return;
}
@@ -1184,7 +1172,6 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
// Ensure that `resolutions` isn't borrowed during `try_define`,
// since it might get updated via a glob cycle.
let bindings = self
- .r
.resolutions(module)
.borrow()
.iter()
@@ -1194,30 +1181,30 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
.collect::<Vec<_>>();
for (mut key, binding) in bindings {
let scope = match key.ident.span.reverse_glob_adjust(module.expansion, import.span) {
- Some(Some(def)) => self.r.expn_def_scope(def),
+ Some(Some(def)) => self.expn_def_scope(def),
Some(None) => import.parent_scope.module,
None => continue,
};
- if self.r.is_accessible_from(binding.vis, scope) {
- let imported_binding = self.r.import(binding, import);
- let _ = self.r.try_define(import.parent_scope.module, key, imported_binding);
+ if self.is_accessible_from(binding.vis, scope) {
+ let imported_binding = self.import(binding, import);
+ let _ = self.try_define(import.parent_scope.module, key, imported_binding);
}
}
// Record the destination of this import
- self.r.record_partial_res(id, PartialRes::new(module.res().unwrap()));
+ self.record_partial_res(id, PartialRes::new(module.res().unwrap()));
}
// Miscellaneous post-processing, including recording re-exports,
// reporting conflicts, and reporting unresolved imports.
- fn finalize_resolutions_in(&mut self, module: Module<'b>) {
+ fn finalize_resolutions_in(&mut self, module: Module<'a>) {
// Since import resolution is finished, globs will not define any more names.
*module.globs.borrow_mut() = Vec::new();
if let Some(def_id) = module.opt_def_id() {
let mut reexports = Vec::new();
- module.for_each_child(self.r, |this, ident, _, binding| {
+ module.for_each_child(self, |this, ident, _, binding| {
if let Some(res) = this.is_reexport(binding) {
reexports.push(ModChild {
ident,
@@ -1232,7 +1219,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
if !reexports.is_empty() {
// Call to `expect_local` should be fine because current
// code is only called for local modules.
- self.r.reexport_map.insert(def_id.expect_local(), reexports);
+ self.reexport_map.insert(def_id.expect_local(), reexports);
}
}
}
diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs
index 83932c089..7df17376b 100644
--- a/compiler/rustc_resolve/src/late.rs
+++ b/compiler/rustc_resolve/src/late.rs
@@ -8,7 +8,7 @@
use RibKind::*;
-use crate::{path_names_to_string, BindingError, Finalize, LexicalScopeBinding};
+use crate::{path_names_to_string, rustdoc, BindingError, Finalize, LexicalScopeBinding};
use crate::{Module, ModuleOrUniformRoot, NameBinding, ParentScope, PathResult};
use crate::{ResolutionError, Resolver, Segment, UseError};
@@ -21,15 +21,16 @@ use rustc_hir::def::Namespace::{self, *};
use rustc_hir::def::{self, CtorKind, DefKind, LifetimeRes, PartialRes, PerNS};
use rustc_hir::def_id::{DefId, LocalDefId, CRATE_DEF_ID, LOCAL_CRATE};
use rustc_hir::{BindingAnnotation, PrimTy, TraitCandidate};
-use rustc_middle::middle::resolve_lifetime::Set1;
+use rustc_middle::middle::resolve_bound_vars::Set1;
use rustc_middle::ty::DefIdTree;
use rustc_middle::{bug, span_bug};
+use rustc_session::config::{CrateType, ResolveDocLinks};
use rustc_session::lint;
+use rustc_span::source_map::{respan, Spanned};
use rustc_span::symbol::{kw, sym, Ident, Symbol};
-use rustc_span::{BytePos, Span};
+use rustc_span::{BytePos, Span, SyntaxContext};
use smallvec::{smallvec, SmallVec};
-use rustc_span::source_map::{respan, Spanned};
use std::assert_matches::debug_assert_matches;
use std::borrow::Cow;
use std::collections::{hash_map::Entry, BTreeSet};
@@ -55,7 +56,7 @@ struct BindingInfo {
}
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
-pub enum PatternSource {
+pub(crate) enum PatternSource {
Match,
Let,
For,
@@ -69,7 +70,7 @@ enum IsRepeatExpr {
}
impl PatternSource {
- pub fn descr(self) -> &'static str {
+ fn descr(self) -> &'static str {
match self {
PatternSource::Match => "match binding",
PatternSource::Let => "let binding",
@@ -493,6 +494,30 @@ impl<'a> PathSource<'a> {
}
}
+/// At this point for most items we can answer whether that item is exported or not,
+/// but some items like impls require type information to determine exported-ness, so we make a
+/// conservative estimate for them (e.g. based on nominal visibility).
+#[derive(Clone, Copy)]
+enum MaybeExported<'a> {
+ Ok(NodeId),
+ Impl(Option<DefId>),
+ ImplItem(Result<DefId, &'a Visibility>),
+}
+
+impl MaybeExported<'_> {
+ fn eval(self, r: &Resolver<'_, '_>) -> bool {
+ let def_id = match self {
+ MaybeExported::Ok(node_id) => Some(r.local_def_id(node_id)),
+ MaybeExported::Impl(Some(trait_def_id)) | MaybeExported::ImplItem(Ok(trait_def_id)) => {
+ trait_def_id.as_local()
+ }
+ MaybeExported::Impl(None) => return true,
+ MaybeExported::ImplItem(Err(vis)) => return vis.kind.is_pub(),
+ };
+ def_id.map_or(true, |def_id| r.effective_visibilities.is_exported(def_id))
+ }
+}
+
#[derive(Default)]
struct DiagnosticMetadata<'ast> {
/// The current trait's associated items' ident, used for diagnostic suggestions.
@@ -559,8 +584,8 @@ struct DiagnosticMetadata<'ast> {
current_elision_failures: Vec<MissingLifetime>,
}
-struct LateResolutionVisitor<'a, 'b, 'ast> {
- r: &'b mut Resolver<'a>,
+struct LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
+ r: &'b mut Resolver<'a, 'tcx>,
/// The module that represents the current item scope.
parent_scope: ParentScope<'a>,
@@ -603,7 +628,7 @@ struct LateResolutionVisitor<'a, 'b, 'ast> {
}
/// Walks the whole crate in DFS order, visiting each item, resolving names as it goes.
-impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> {
+impl<'a: 'ast, 'ast, 'tcx> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
fn visit_attribute(&mut self, _: &'ast Attribute) {
// We do not want to resolve expressions that appear in attributes,
// as they do not correspond to actual code.
@@ -620,7 +645,9 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> {
self.resolve_arm(arm);
}
fn visit_block(&mut self, block: &'ast Block) {
+ let old_macro_rules = self.parent_scope.macro_rules;
self.resolve_block(block);
+ self.parent_scope.macro_rules = old_macro_rules;
}
fn visit_anon_const(&mut self, constant: &'ast AnonConst) {
// We deal with repeat expressions explicitly in `resolve_expr`.
@@ -655,7 +682,7 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> {
// Elided lifetime in reference: we resolve as if there was some lifetime `'_` with
// NodeId `ty.id`.
// This span will be used in case of elision failure.
- let span = self.r.session.source_map().start_point(ty.span);
+ let span = self.r.tcx.sess.source_map().start_point(ty.span);
self.resolve_elided_lifetime(ty.id, span);
visit::walk_ty(self, ty);
}
@@ -771,6 +798,7 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> {
);
}
fn visit_foreign_item(&mut self, foreign_item: &'ast ForeignItem) {
+ self.resolve_doc_links(&foreign_item.attrs, MaybeExported::Ok(foreign_item.id));
match foreign_item.kind {
ForeignItemKind::TyAlias(box TyAlias { ref generics, .. }) => {
self.with_generic_param_rib(
@@ -1159,10 +1187,20 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> {
})
});
}
+
+ fn visit_variant(&mut self, v: &'ast Variant) {
+ self.resolve_doc_links(&v.attrs, MaybeExported::Ok(v.id));
+ visit::walk_variant(self, v)
+ }
+
+ fn visit_field_def(&mut self, f: &'ast FieldDef) {
+ self.resolve_doc_links(&f.attrs, MaybeExported::Ok(f.id));
+ visit::walk_field_def(self, f)
+ }
}
-impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
- fn new(resolver: &'b mut Resolver<'a>) -> LateResolutionVisitor<'a, 'b, 'ast> {
+impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
+ fn new(resolver: &'b mut Resolver<'a, 'tcx>) -> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
// During late resolution we only track the module component of the parent scope,
// although it may be useful to track other components as well for diagnostics.
let graph_root = resolver.graph_root;
@@ -1533,7 +1571,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
("`'_` cannot be used here", "`'_` is a reserved lifetime name")
};
let mut diag = rustc_errors::struct_span_err!(
- self.r.session,
+ self.r.tcx.sess,
lifetime.ident.span,
E0637,
"{}",
@@ -1710,7 +1748,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
// impl Foo for std::cell::Ref<u32> // note lack of '_
// async fn foo(_: std::cell::Ref<u32>) { ... }
LifetimeRibKind::AnonymousCreateParameter { report_in_path: true, .. } => {
- let sess = self.r.session;
+ let sess = self.r.tcx.sess;
let mut err = rustc_errors::struct_span_err!(
sess,
path_span,
@@ -1725,7 +1763,6 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
!segment.has_generic_args,
elided_lifetime_span,
);
- err.note("assuming a `'static` lifetime...");
err.emit();
should_lint = false;
@@ -1992,13 +2029,13 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
/// List all the lifetimes that appear in the provided type.
fn find_lifetime_for_self(&self, ty: &'ast Ty) -> Set1<LifetimeRes> {
- struct SelfVisitor<'r, 'a> {
- r: &'r Resolver<'a>,
+ struct SelfVisitor<'r, 'a, 'tcx> {
+ r: &'r Resolver<'a, 'tcx>,
impl_self: Option<Res>,
lifetime: Set1<LifetimeRes>,
}
- impl SelfVisitor<'_, '_> {
+ impl SelfVisitor<'_, '_, '_> {
// Look for `self: &'a Self` - also desugared from `&'a self`,
// and if that matches, use it for elision and return early.
fn is_self_ty(&self, ty: &Ty) -> bool {
@@ -2016,7 +2053,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
}
}
- impl<'a> Visitor<'a> for SelfVisitor<'_, '_> {
+ impl<'a> Visitor<'a> for SelfVisitor<'_, '_, '_> {
fn visit_ty(&mut self, ty: &'a Ty) {
trace!("SelfVisitor considering ty={:?}", ty);
if let TyKind::Ref(lt, ref mt) = ty.kind && self.is_self_ty(&mt.ty) {
@@ -2145,7 +2182,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
let segments = &use_tree.prefix.segments;
if !segments.is_empty() {
let ident = segments[0].ident;
- if ident.is_path_segment_keyword() || ident.span.rust_2015() {
+ if ident.is_path_segment_keyword() || ident.span.is_rust_2015() {
return;
}
@@ -2157,7 +2194,8 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
let what = if ns == TypeNS { "type parameters" } else { "local variables" };
if this.should_report_errs() {
this.r
- .session
+ .tcx
+ .sess
.span_err(ident.span, &format!("imports cannot refer to {}", what));
}
};
@@ -2185,6 +2223,12 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
}
fn resolve_item(&mut self, item: &'ast Item) {
+ let mod_inner_docs =
+ matches!(item.kind, ItemKind::Mod(..)) && rustdoc::inner_docs(&item.attrs);
+ if !mod_inner_docs && !matches!(item.kind, ItemKind::Impl(..)) {
+ self.resolve_doc_links(&item.attrs, MaybeExported::Ok(item.id));
+ }
+
let name = item.ident.name;
debug!("(resolving item) resolving {} ({:?})", name, item.kind);
@@ -2229,7 +2273,14 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
..
}) => {
self.diagnostic_metadata.current_impl_items = Some(impl_items);
- self.resolve_implementation(generics, of_trait, &self_ty, item.id, impl_items);
+ self.resolve_implementation(
+ &item.attrs,
+ generics,
+ of_trait,
+ &self_ty,
+ item.id,
+ impl_items,
+ );
self.diagnostic_metadata.current_impl_items = None;
}
@@ -2274,9 +2325,20 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
);
}
- ItemKind::Mod(..) | ItemKind::ForeignMod(_) => {
+ ItemKind::Mod(..) => {
self.with_scope(item.id, |this| {
+ if mod_inner_docs {
+ this.resolve_doc_links(&item.attrs, MaybeExported::Ok(item.id));
+ }
+ let old_macro_rules = this.parent_scope.macro_rules;
visit::walk_item(this, item);
+ // Maintain macro_rules scopes in the same way as during early resolution
+ // for diagnostics and doc links.
+ if item.attrs.iter().all(|attr| {
+ !attr.has_name(sym::macro_use) && !attr.has_name(sym::macro_escape)
+ }) {
+ this.parent_scope.macro_rules = old_macro_rules;
+ }
});
}
@@ -2309,14 +2371,21 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
self.future_proof_import(use_tree);
}
- ItemKind::ExternCrate(..) | ItemKind::MacroDef(..) => {
- // do nothing, these are just around to be encoded
+ ItemKind::MacroDef(ref macro_def) => {
+ // Maintain macro_rules scopes in the same way as during early resolution
+ // for diagnostics and doc links.
+ if macro_def.macro_rules {
+ let def_id = self.r.local_def_id(item.id);
+ self.parent_scope.macro_rules = self.r.macro_rules_scopes[&def_id];
+ }
}
- ItemKind::GlobalAsm(_) => {
+ ItemKind::ForeignMod(_) | ItemKind::GlobalAsm(_) => {
visit::walk_item(self, item);
}
+ ItemKind::ExternCrate(..) => {}
+
ItemKind::MacCall(_) => panic!("unexpanded macro in resolve!"),
}
}
@@ -2370,7 +2439,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
if let GenericParamKind::Lifetime = param.kind
&& let Some(&original) = seen_lifetimes.get(&ident)
{
- diagnostics::signal_lifetime_shadowing(self.r.session, original, param.ident);
+ diagnostics::signal_lifetime_shadowing(self.r.tcx.sess, original, param.ident);
// Record lifetime res, so lowering knows there is something fishy.
self.record_lifetime_param(param.id, LifetimeRes::Error);
continue;
@@ -2394,7 +2463,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
if param.ident.name == kw::UnderscoreLifetime {
rustc_errors::struct_span_err!(
- self.r.session,
+ self.r.tcx.sess,
param.ident.span,
E0637,
"`'_` cannot be used here"
@@ -2408,7 +2477,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
if param.ident.name == kw::StaticLifetime {
rustc_errors::struct_span_err!(
- self.r.session,
+ self.r.tcx.sess,
param.ident.span,
E0262,
"invalid lifetime parameter name: `{}`",
@@ -2437,7 +2506,13 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
let res = match kind {
ItemRibKind(..) | AssocItemRibKind => Res::Def(def_kind, def_id.to_def_id()),
- NormalRibKind => Res::Err,
+ NormalRibKind => {
+ if self.r.tcx.sess.features_untracked().non_lifetime_binders {
+ Res::Def(def_kind, def_id.to_def_id())
+ } else {
+ Res::Err
+ }
+ }
_ => span_bug!(param.ident.span, "Unexpected rib kind {:?}", kind),
};
self.r.record_partial_res(param.id, PartialRes::new(res));
@@ -2544,6 +2619,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
};
for item in trait_items {
+ self.resolve_doc_links(&item.attrs, MaybeExported::Ok(item.id));
match &item.kind {
AssocItemKind::Const(_, ty, default) => {
self.visit_ty(ty);
@@ -2631,6 +2707,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
fn resolve_implementation(
&mut self,
+ attrs: &[ast::Attribute],
generics: &'ast Generics,
opt_trait_reference: &'ast Option<TraitRef>,
self_type: &'ast Ty,
@@ -2661,6 +2738,8 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
opt_trait_reference.as_ref(),
self_type,
|this, trait_id| {
+ this.resolve_doc_links(attrs, MaybeExported::Impl(trait_id));
+
let item_def_id = this.r.local_def_id(item_id);
// Register the trait definitions from here.
@@ -2694,7 +2773,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
debug!("resolve_implementation with_self_rib_ns(ValueNS, ...)");
let mut seen_trait_items = Default::default();
for item in impl_items {
- this.resolve_impl_item(&**item, &mut seen_trait_items);
+ this.resolve_impl_item(&**item, &mut seen_trait_items, trait_id);
}
});
});
@@ -2712,8 +2791,10 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
&mut self,
item: &'ast AssocItem,
seen_trait_items: &mut FxHashMap<DefId, Span>,
+ trait_id: Option<DefId>,
) {
use crate::ResolutionError::*;
+ self.resolve_doc_links(&item.attrs, MaybeExported::ImplItem(trait_id.ok_or(&item.vis)));
match &item.kind {
AssocItemKind::Const(_, ty, default) => {
debug!("resolve_implementation AssocItemKind::Const");
@@ -3304,7 +3385,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
Res::SelfCtor(_) => {
// We resolve `Self` in pattern position as an ident sometimes during recovery,
// so delay a bug instead of ICEing.
- self.r.session.delay_span_bug(
+ self.r.tcx.sess.delay_span_bug(
ident.span,
"unexpected `SelfCtor` in pattern, expected identifier"
);
@@ -3584,7 +3665,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
#[inline]
/// If we're actually rustdoc then avoid giving a name resolution error for `cfg()` items.
fn should_report_errs(&self) -> bool {
- !(self.r.session.opts.actually_rustdoc && self.in_func_body)
+ !(self.r.tcx.sess.opts.actually_rustdoc && self.in_func_body)
}
// Resolve in alternative namespaces if resolution in the primary namespace fails.
@@ -3749,7 +3830,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
}
if let Ok((_, orig_span)) = self.resolve_label(label.ident) {
- diagnostics::signal_label_shadowing(self.r.session, orig_span, label.ident)
+ diagnostics::signal_label_shadowing(self.r.tcx.sess, orig_span, label.ident)
}
self.with_label_rib(NormalRibKind, |this| {
@@ -4055,9 +4136,9 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
fn record_candidate_traits_for_expr_if_necessary(&mut self, expr: &'ast Expr) {
match expr.kind {
ExprKind::Field(_, ident) => {
- // FIXME(#6890): Even though you can't treat a method like a
- // field, we need to add any trait methods we find that match
- // the field name so that we can do some nice error reporting
+ // #6890: Even though you can't treat a method like a field,
+ // we need to add any trait methods we find that match the
+ // field name so that we can do some nice error reporting
// later on in typeck.
let traits = self.traits_in_scope(ident, ValueNS);
self.r.trait_map.insert(expr.id, traits);
@@ -4116,15 +4197,116 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
self.r.extra_lifetime_params_map.insert(async_node_id, extra_lifetime_params);
}
}
+
+ fn resolve_and_cache_rustdoc_path(&mut self, path_str: &str, ns: Namespace) -> bool {
+ // FIXME: This caching may be incorrect in case of multiple `macro_rules`
+ // items with the same name in the same module.
+ // Also hygiene is not considered.
+ let mut doc_link_resolutions = std::mem::take(&mut self.r.doc_link_resolutions);
+ let res = doc_link_resolutions
+ .entry(self.parent_scope.module.nearest_parent_mod().expect_local())
+ .or_default()
+ .entry((Symbol::intern(path_str), ns))
+ .or_insert_with_key(|(path, ns)| {
+ let res = self.r.resolve_rustdoc_path(path.as_str(), *ns, self.parent_scope);
+ if let Some(res) = res
+ && let Some(def_id) = res.opt_def_id()
+ && !def_id.is_local()
+ && self.r.tcx.sess.crate_types().contains(&CrateType::ProcMacro)
+ && matches!(self.r.tcx.sess.opts.resolve_doc_links, ResolveDocLinks::ExportedMetadata) {
+ // Encoding foreign def ids in proc macro crate metadata will ICE.
+ return None;
+ }
+ res
+ })
+ .is_some();
+ self.r.doc_link_resolutions = doc_link_resolutions;
+ res
+ }
+
+ fn resolve_doc_links(&mut self, attrs: &[Attribute], maybe_exported: MaybeExported<'_>) {
+ match self.r.tcx.sess.opts.resolve_doc_links {
+ ResolveDocLinks::None => return,
+ ResolveDocLinks::ExportedMetadata
+ if !self.r.tcx.sess.crate_types().iter().copied().any(CrateType::has_metadata)
+ || !maybe_exported.eval(self.r) =>
+ {
+ return;
+ }
+ ResolveDocLinks::Exported if !maybe_exported.eval(self.r) => {
+ return;
+ }
+ ResolveDocLinks::ExportedMetadata
+ | ResolveDocLinks::Exported
+ | ResolveDocLinks::All => {}
+ }
+
+ if !attrs.iter().any(|attr| attr.may_have_doc_links()) {
+ return;
+ }
+
+ let mut need_traits_in_scope = false;
+ for path_str in rustdoc::attrs_to_preprocessed_links(attrs) {
+ // Resolve all namespaces due to no disambiguator or for diagnostics.
+ let mut any_resolved = false;
+ let mut need_assoc = false;
+ for ns in [TypeNS, ValueNS, MacroNS] {
+ if self.resolve_and_cache_rustdoc_path(&path_str, ns) {
+ any_resolved = true;
+ } else if ns != MacroNS {
+ need_assoc = true;
+ }
+ }
+
+ // Resolve all prefixes for type-relative resolution or for diagnostics.
+ if need_assoc || !any_resolved {
+ let mut path = &path_str[..];
+ while let Some(idx) = path.rfind("::") {
+ path = &path[..idx];
+ need_traits_in_scope = true;
+ for ns in [TypeNS, ValueNS, MacroNS] {
+ self.resolve_and_cache_rustdoc_path(path, ns);
+ }
+ }
+ }
+ }
+
+ if need_traits_in_scope {
+ // FIXME: hygiene is not considered.
+ let mut doc_link_traits_in_scope = std::mem::take(&mut self.r.doc_link_traits_in_scope);
+ doc_link_traits_in_scope
+ .entry(self.parent_scope.module.nearest_parent_mod().expect_local())
+ .or_insert_with(|| {
+ self.r
+ .traits_in_scope(None, &self.parent_scope, SyntaxContext::root(), None)
+ .into_iter()
+ .filter_map(|tr| {
+ if !tr.def_id.is_local()
+ && self.r.tcx.sess.crate_types().contains(&CrateType::ProcMacro)
+ && matches!(
+ self.r.tcx.sess.opts.resolve_doc_links,
+ ResolveDocLinks::ExportedMetadata
+ )
+ {
+ // Encoding foreign def ids in proc macro crate metadata will ICE.
+ return None;
+ }
+ Some(tr.def_id)
+ })
+ .collect()
+ });
+ self.r.doc_link_traits_in_scope = doc_link_traits_in_scope;
+ }
+ }
}
-struct LifetimeCountVisitor<'a, 'b> {
- r: &'b mut Resolver<'a>,
+struct LifetimeCountVisitor<'a, 'b, 'tcx> {
+ r: &'b mut Resolver<'a, 'tcx>,
}
/// Walks the whole crate in DFS order, visiting each item, counting the declared number of
/// lifetime generic parameters.
-impl<'ast> Visitor<'ast> for LifetimeCountVisitor<'_, '_> {
+impl<'ast> Visitor<'ast> for LifetimeCountVisitor<'_, '_, '_> {
fn visit_item(&mut self, item: &'ast Item) {
match &item.kind {
ItemKind::TyAlias(box TyAlias { ref generics, .. })
@@ -4158,10 +4340,11 @@ impl<'ast> Visitor<'ast> for LifetimeCountVisitor<'_, '_> {
}
}
-impl<'a> Resolver<'a> {
+impl<'a, 'tcx> Resolver<'a, 'tcx> {
pub(crate) fn late_resolve_crate(&mut self, krate: &Crate) {
visit::walk_crate(&mut LifetimeCountVisitor { r: self }, krate);
let mut late_resolution_visitor = LateResolutionVisitor::new(self);
+ late_resolution_visitor.resolve_doc_links(&krate.attrs, MaybeExported::Ok(CRATE_NODE_ID));
visit::walk_crate(&mut late_resolution_visitor, krate);
for (id, span) in late_resolution_visitor.diagnostic_metadata.unused_labels.iter() {
self.lint_buffer.buffer_lint(lint::builtin::UNUSED_LABELS, *id, *span, "unused label");
diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs
index 6d448433e..b8ddc4552 100644
--- a/compiler/rustc_resolve/src/late/diagnostics.rs
+++ b/compiler/rustc_resolve/src/late/diagnostics.rs
@@ -25,9 +25,9 @@ use rustc_middle::ty::DefIdTree;
use rustc_session::lint;
use rustc_session::parse::feature_err;
use rustc_session::Session;
+use rustc_span::edit_distance::find_best_match_for_name;
use rustc_span::edition::Edition;
use rustc_span::hygiene::MacroKind;
-use rustc_span::lev_distance::find_best_match_for_name;
use rustc_span::symbol::{kw, sym, Ident, Symbol};
use rustc_span::{BytePos, Span};
@@ -166,11 +166,11 @@ impl TypoCandidate {
}
}
-impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
+impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
fn def_span(&self, def_id: DefId) -> Option<Span> {
match def_id.krate {
LOCAL_CRATE => self.r.opt_span(def_id),
- _ => Some(self.r.cstore().get_span_untracked(def_id, self.r.session)),
+ _ => Some(self.r.cstore().get_span_untracked(def_id, self.r.tcx.sess)),
}
}
@@ -200,7 +200,8 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
Res::Def(DefKind::Fn, _) => {
// Verify whether this is a fn call or an Fn used as a type.
self.r
- .session
+ .tcx
+ .sess
.source_map()
.span_to_snippet(span)
.map(|snippet| snippet.ends_with(')'))
@@ -227,20 +228,27 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
&& let Some(FnCtxt::Assoc(_)) = fn_kind.ctxt()
&& let Some(items) = self.diagnostic_metadata.current_impl_items
&& let Some(item) = items.iter().find(|i| {
- if let AssocItemKind::Fn(_) = &i.kind && i.ident.name == item_str.name
+ if let AssocItemKind::Fn(..) | AssocItemKind::Const(..) = &i.kind
+ && i.ident.name == item_str.name
{
debug!(?item_str.name);
return true
}
false
})
- && let AssocItemKind::Fn(fn_) = &item.kind
{
- debug!(?fn_);
- let self_sugg = if fn_.sig.decl.has_self() { "self." } else { "Self::" };
+ let self_sugg = match &item.kind {
+ AssocItemKind::Fn(fn_) if fn_.sig.decl.has_self() => "self.",
+ _ => "Self::",
+ };
+
Some((
item_span.shrink_to_lo(),
- "consider using the associated function",
+ match &item.kind {
+ AssocItemKind::Fn(..) => "consider using the associated function",
+ AssocItemKind::Const(..) => "consider using the associated constant",
+ _ => unreachable!("item kind was filtered above"),
+ },
self_sugg.to_string()
))
} else {
@@ -248,7 +256,7 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
};
(String::new(), "this scope".to_string(), suggestion)
} else if path.len() == 2 && path[0].ident.name == kw::PathRoot {
- if self.r.session.edition() > Edition::Edition2015 {
+ if self.r.tcx.sess.edition() > Edition::Edition2015 {
// In edition 2018 onwards, the `::foo` syntax may only pull from the extern prelude
// which overrides all other expectations of item type
expected = "crate";
@@ -311,12 +319,12 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
span: Span,
source: PathSource<'_>,
res: Option<Res>,
- ) -> (DiagnosticBuilder<'a, ErrorGuaranteed>, Vec<ImportSuggestion>) {
+ ) -> (DiagnosticBuilder<'tcx, ErrorGuaranteed>, Vec<ImportSuggestion>) {
debug!(?res, ?source);
let base_error = self.make_base_error(path, span, source, res);
let code = source.error_code(res.is_some());
let mut err =
- self.r.session.struct_span_err_with_code(base_error.span, &base_error.msg, code);
+ self.r.tcx.sess.struct_span_err_with_code(base_error.span, &base_error.msg, code);
self.suggest_swapping_misplaced_self_ty_and_trait(&mut err, source, res, base_error.span);
@@ -425,7 +433,8 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
} else {
(
self.r
- .session
+ .tcx
+ .sess
.source_map()
.span_through_char(*fn_span, '(')
.shrink_to_hi(),
@@ -498,7 +507,8 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
{
if self
.r
- .session
+ .tcx
+ .sess
.parse_sess
.type_ascription_path_suggestions
.borrow()
@@ -535,7 +545,7 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
}
}
- // Try Levenshtein algorithm.
+ // Try finding a suitable replacement.
let typo_sugg =
self.lookup_typo_candidate(path, source.namespace(), is_expected).to_opt_suggestion();
if path.len() == 1 && self.self_type_is_available() {
@@ -589,7 +599,7 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
if let Some((call_span, args_span)) = self.call_has_self_arg(source) {
let mut args_snippet = String::new();
if let Some(args_span) = args_span {
- if let Ok(snippet) = self.r.session.source_map().span_to_snippet(args_span) {
+ if let Ok(snippet) = self.r.tcx.sess.source_map().span_to_snippet(args_span) {
args_snippet = snippet;
}
}
@@ -725,7 +735,7 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
let ident_span = path.last().map_or(span, |ident| ident.ident.span);
let typo_sugg = self.lookup_typo_candidate(path, source.namespace(), is_expected);
let is_in_same_file = &|sp1, sp2| {
- let source_map = self.r.session.source_map();
+ let source_map = self.r.tcx.sess.source_map();
let file1 = source_map.span_to_filename(sp1);
let file2 = source_map.span_to_filename(sp2);
file1 == file2
@@ -763,7 +773,7 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
_ => {}
}
- // If the trait has a single item (which wasn't matched by Levenshtein), suggest it
+ // If the trait has a single item (which wasn't matched by the algorithm), suggest it
let suggestion = self.get_single_associated_item(&path, &source, is_expected);
if !self.r.add_typo_suggestion(err, suggestion, ident_span) {
fallback = !self.let_binding_suggestion(err, ident_span);
@@ -868,7 +878,7 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
);
let is_assoc_fn = self.self_type_is_available();
if let Some((fn_kind, span)) = &self.diagnostic_metadata.current_function {
- // The current function has a `self' parameter, but we were unable to resolve
+ // The current function has a `self` parameter, but we were unable to resolve
// a reference to `self`. This can only happen if the `self` identifier we
// are resolving came from a different hygiene context.
if fn_kind.decl().inputs.get(0).map_or(false, |p| p.is_self()) {
@@ -888,7 +898,8 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
.map_or(*span, |ident| span.with_lo(ident.span.hi()));
(
self.r
- .session
+ .tcx
+ .sess
.source_map()
.span_through_char(span, '(')
.shrink_to_hi(),
@@ -942,9 +953,9 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
&& let PathSource::Trait(_) = source
&& let Some(Res::Def(DefKind::Struct | DefKind::Enum | DefKind::Union, _)) = res
&& let Ok(self_ty_str) =
- self.r.session.source_map().span_to_snippet(self_ty.span)
+ self.r.tcx.sess.source_map().span_to_snippet(self_ty.span)
&& let Ok(trait_ref_str) =
- self.r.session.source_map().span_to_snippet(trait_ref.path.span)
+ self.r.tcx.sess.source_map().span_to_snippet(trait_ref.path.span)
{
err.multipart_suggestion(
"`impl` items mention the trait being implemented first and the type it is being implemented for second",
@@ -1088,7 +1099,8 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
format!(
"{}: {}<{} = {}>",
self.r
- .session
+ .tcx
+ .sess
.source_map()
.span_to_snippet(ty.span) // Account for `<&'a T as Foo>::Bar`.
.unwrap_or_else(|_| constrain_ident.to_string()),
@@ -1157,7 +1169,7 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
// parser issue where a struct literal is being used on an expression
// where a brace being opened means a block is being started. Look
// ahead for the next text to see if `span` is followed by a `{`.
- let sm = self.r.session.source_map();
+ let sm = self.r.tcx.sess.source_map();
let sp = sm.span_look_ahead(span, None, Some(50));
let followed_by_brace = matches!(sm.span_to_snippet(sp), Ok(ref snippet) if snippet == "{");
// In case this could be a struct literal that needs to be surrounded
@@ -1205,7 +1217,7 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
true
} else if kind == DefKind::Struct
&& let Some(lhs_source_span) = lhs_span.find_ancestor_inside(expr.span)
- && let Ok(snippet) = self.r.session.source_map().span_to_snippet(lhs_source_span)
+ && let Ok(snippet) = self.r.tcx.sess.source_map().span_to_snippet(lhs_source_span)
{
// The LHS is a type that originates from a macro call.
// We have to add angle brackets around it.
@@ -1336,7 +1348,7 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
"!",
Applicability::MaybeIncorrect,
);
- if path_str == "try" && span.rust_2015() {
+ if path_str == "try" && span.is_rust_2015() {
err.note("if you want the `try` keyword, you need Rust 2018 or later");
}
}
@@ -1345,11 +1357,11 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
}
(Res::Def(DefKind::TyAlias, def_id), PathSource::Trait(_)) => {
err.span_label(span, "type aliases cannot be used as traits");
- if self.r.session.is_nightly_build() {
+ if self.r.tcx.sess.is_nightly_build() {
let msg = "you might have meant to use `#![feature(trait_alias)]` instead of a \
`type` alias";
if let Some(span) = self.def_span(def_id) {
- if let Ok(snip) = self.r.session.source_map().span_to_snippet(span) {
+ if let Ok(snip) = self.r.tcx.sess.source_map().span_to_snippet(span) {
// The span contains a type alias so we should be able to
// replace `type` with `trait`.
let snip = snip.replacen("type", "trait", 1);
@@ -1380,7 +1392,8 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
.last()
.map(|sp| {
self.r
- .session
+ .tcx
+ .sess
.parse_sess
.type_ascription_path_suggestions
.borrow()
@@ -1687,17 +1700,14 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
let extern_prelude = self.r.extern_prelude.clone();
names.extend(extern_prelude.iter().flat_map(|(ident, _)| {
self.r
- .crate_loader()
- .maybe_process_path_extern(ident.name)
+ .crate_loader(|c| c.maybe_process_path_extern(ident.name))
.and_then(|crate_id| {
let crate_mod =
Res::Def(DefKind::Mod, crate_id.as_def_id());
- if filter_fn(crate_mod) {
- Some(TypoSuggestion::typo_from_ident(*ident, crate_mod))
- } else {
- None
- }
+ filter_fn(crate_mod).then(|| {
+ TypoSuggestion::typo_from_ident(*ident, crate_mod)
+ })
})
}));
@@ -1769,12 +1779,12 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
/// Only used in a specific case of type ascription suggestions
fn get_colon_suggestion_span(&self, start: Span) -> Span {
- let sm = self.r.session.source_map();
+ let sm = self.r.tcx.sess.source_map();
start.to(sm.next_point(start))
}
fn type_ascription_suggestion(&self, err: &mut Diagnostic, base_span: Span) -> bool {
- let sm = self.r.session.source_map();
+ let sm = self.r.tcx.sess.source_map();
let base_snippet = sm.span_to_snippet(base_span);
if let Some(&sp) = self.diagnostic_metadata.current_type_ascription.last() {
if let Ok(snippet) = sm.span_to_snippet(sp) {
@@ -1804,7 +1814,8 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
show_label = false;
if !self
.r
- .session
+ .tcx
+ .sess
.parse_sess
.type_ascription_path_suggestions
.borrow_mut()
@@ -2237,19 +2248,23 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
}
None => {
debug!(?param.ident, ?param.ident.span);
-
let deletion_span = deletion_span();
- self.r.lint_buffer.buffer_lint_with_diagnostic(
- lint::builtin::UNUSED_LIFETIMES,
- param.id,
- param.ident.span,
- &format!("lifetime parameter `{}` never used", param.ident),
- lint::BuiltinLintDiagnostics::SingleUseLifetime {
- param_span: param.ident.span,
- use_span: None,
- deletion_span,
- },
- );
+ // the give lifetime originates from expanded code so we won't be able to remove it #104432
+ let lifetime_only_in_expanded_code =
+ deletion_span.map(|sp| sp.in_derive_expansion()).unwrap_or(true);
+ if !lifetime_only_in_expanded_code {
+ self.r.lint_buffer.buffer_lint_with_diagnostic(
+ lint::builtin::UNUSED_LIFETIMES,
+ param.id,
+ param.ident.span,
+ &format!("lifetime parameter `{}` never used", param.ident),
+ lint::BuiltinLintDiagnostics::SingleUseLifetime {
+ param_span: param.ident.span,
+ use_span: None,
+ deletion_span,
+ },
+ );
+ }
}
}
}
@@ -2263,7 +2278,7 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
debug_assert_ne!(lifetime_ref.ident.name, kw::UnderscoreLifetime);
let mut err = if let Some(outer) = outer_lifetime_ref {
let mut err = struct_span_err!(
- self.r.session,
+ self.r.tcx.sess,
lifetime_ref.ident.span,
E0401,
"can't use generic parameters from outer item",
@@ -2273,7 +2288,7 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
err
} else {
let mut err = struct_span_err!(
- self.r.session,
+ self.r.tcx.sess,
lifetime_ref.ident.span,
E0261,
"use of undeclared lifetime name `{}`",
@@ -2331,8 +2346,13 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
);
(span, sugg)
} else {
- let span =
- self.r.session.source_map().span_through_char(span, '<').shrink_to_hi();
+ let span = self
+ .r
+ .tcx
+ .sess
+ .source_map()
+ .span_through_char(span, '<')
+ .shrink_to_hi();
let sugg = format!("{}, ", name.unwrap_or("'a"));
(span, sugg)
};
@@ -2366,7 +2386,7 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
pub(crate) fn emit_non_static_lt_in_const_generic_error(&self, lifetime_ref: &ast::Lifetime) {
struct_span_err!(
- self.r.session,
+ self.r.tcx.sess,
lifetime_ref.ident.span,
E0771,
"use of non-static lifetime `{}` in const generic",
@@ -2386,10 +2406,10 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
&self,
lifetime_ref: &ast::Lifetime,
) {
- let feature_active = self.r.session.features_untracked().generic_const_exprs;
+ let feature_active = self.r.tcx.sess.features_untracked().generic_const_exprs;
if !feature_active {
feature_err(
- &self.r.session.parse_sess,
+ &self.r.tcx.sess.parse_sess,
sym::generic_const_exprs,
lifetime_ref.ident.span,
"a non-static lifetime is not allowed in a `const`",
@@ -2407,7 +2427,7 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
let spans: Vec<_> = lifetime_refs.iter().map(|lt| lt.span).collect();
let mut err = struct_span_err!(
- self.r.session,
+ self.r.tcx.sess,
spans,
E0106,
"missing lifetime specifier{}",
@@ -2615,7 +2635,7 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
}
/// Report lifetime/lifetime shadowing as an error.
-pub fn signal_lifetime_shadowing(sess: &Session, orig: Ident, shadower: Ident) {
+pub(super) fn signal_lifetime_shadowing(sess: &Session, orig: Ident, shadower: Ident) {
let mut err = struct_span_err!(
sess,
shadower.span,
@@ -2630,7 +2650,7 @@ pub fn signal_lifetime_shadowing(sess: &Session, orig: Ident, shadower: Ident) {
/// Shadowing involving a label is only a warning for historical reasons.
//FIXME: make this a proper lint.
-pub fn signal_label_shadowing(sess: &Session, orig: Span, shadower: Ident) {
+pub(super) fn signal_label_shadowing(sess: &Session, orig: Span, shadower: Ident) {
let name = shadower.name;
let shadower = shadower.span;
let mut err = sess.struct_span_warn(
diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs
index 1b181b714..1fdfb1a53 100644
--- a/compiler/rustc_resolve/src/lib.rs
+++ b/compiler/rustc_resolve/src/lib.rs
@@ -21,34 +21,34 @@
#[macro_use]
extern crate tracing;
-pub use rustc_hir::def::{Namespace, PerNS};
-
use rustc_arena::{DroplessArena, TypedArena};
use rustc_ast::node_id::NodeMap;
use rustc_ast::{self as ast, NodeId, CRATE_NODE_ID};
use rustc_ast::{AngleBracketedArg, Crate, Expr, ExprKind, GenericArg, GenericArgs, LitKind, Path};
use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap, FxIndexSet};
use rustc_data_structures::intern::Interned;
-use rustc_data_structures::sync::{Lrc, RwLock};
-use rustc_errors::{Applicability, DiagnosticBuilder, ErrorGuaranteed};
+use rustc_data_structures::sync::{Lrc, MappedReadGuard};
+use rustc_errors::{
+ Applicability, DiagnosticBuilder, DiagnosticMessage, ErrorGuaranteed, SubdiagnosticMessage,
+};
use rustc_expand::base::{DeriveResolutions, SyntaxExtension, SyntaxExtensionKind};
-use rustc_hir::def::Namespace::*;
-use rustc_hir::def::{self, CtorOf, DefKind, LifetimeRes, PartialRes};
+use rustc_hir::def::Namespace::{self, *};
+use rustc_hir::def::{self, CtorOf, DefKind, DocLinkResMap, LifetimeRes, PartialRes, PerNS};
use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, LocalDefId};
use rustc_hir::def_id::{CRATE_DEF_ID, LOCAL_CRATE};
-use rustc_hir::definitions::{DefPathData, Definitions};
+use rustc_hir::definitions::DefPathData;
use rustc_hir::TraitCandidate;
use rustc_index::vec::IndexVec;
+use rustc_macros::fluent_messages;
use rustc_metadata::creader::{CStore, CrateLoader};
use rustc_middle::metadata::ModChild;
use rustc_middle::middle::privacy::EffectiveVisibilities;
use rustc_middle::span_bug;
-use rustc_middle::ty::{self, DefIdTree, MainDefinition, RegisteredTools};
+use rustc_middle::ty::{self, DefIdTree, MainDefinition, RegisteredTools, TyCtxt};
use rustc_middle::ty::{ResolverGlobalCtxt, ResolverOutputs};
use rustc_query_system::ich::StableHashingContext;
-use rustc_session::cstore::{CrateStore, MetadataLoaderDyn, Untracked};
+use rustc_session::cstore::CrateStore;
use rustc_session::lint::LintBuffer;
-use rustc_session::Session;
use rustc_span::hygiene::{ExpnId, LocalExpnId, MacroKind, SyntaxContext, Transparency};
use rustc_span::source_map::Spanned;
use rustc_span::symbol::{kw, sym, Ident, Symbol};
@@ -60,7 +60,7 @@ use std::collections::BTreeSet;
use std::{fmt, ptr};
use diagnostics::{ImportSuggestion, LabelSuggestion, Suggestion};
-use imports::{Import, ImportKind, ImportResolver, NameResolution};
+use imports::{Import, ImportKind, NameResolution};
use late::{HasGenericParams, PathSource, PatternSource};
use macros::{MacroRulesBinding, MacroRulesScope, MacroRulesScopeRef};
@@ -78,6 +78,9 @@ mod ident;
mod imports;
mod late;
mod macros;
+pub mod rustdoc;
+
+fluent_messages! { "../locales/en-US.ftl" }
enum Weak {
Yes,
@@ -85,7 +88,7 @@ enum Weak {
}
#[derive(Copy, Clone, PartialEq, Debug)]
-pub enum Determinacy {
+enum Determinacy {
Determined,
Undetermined,
}
@@ -138,17 +141,17 @@ enum ScopeSet<'a> {
/// This struct is currently used only for early resolution (imports and macros),
/// but not for late resolution yet.
#[derive(Clone, Copy, Debug)]
-pub struct ParentScope<'a> {
- pub module: Module<'a>,
+struct ParentScope<'a> {
+ module: Module<'a>,
expansion: LocalExpnId,
- pub macro_rules: MacroRulesScopeRef<'a>,
+ macro_rules: MacroRulesScopeRef<'a>,
derives: &'a [ast::Path],
}
impl<'a> ParentScope<'a> {
/// Creates a parent scope with the passed argument used as the module scope component,
/// and other scope components set to default empty values.
- pub fn module(module: Module<'a>, resolver: &Resolver<'a>) -> ParentScope<'a> {
+ fn module(module: Module<'a>, resolver: &Resolver<'a, '_>) -> ParentScope<'a> {
ParentScope {
module,
expansion: LocalExpnId::ROOT,
@@ -256,7 +259,7 @@ enum VisResolutionError<'a> {
/// A minimal representation of a path segment. We use this in resolve because we synthesize 'path
/// segments' which don't have the rest of an AST or HIR `PathSegment`.
#[derive(Clone, Copy, Debug)]
-pub struct Segment {
+struct Segment {
ident: Ident,
id: Option<NodeId>,
/// Signals whether this `PathSegment` has generic arguments. Used to avoid providing
@@ -379,7 +382,7 @@ impl ModuleOrUniformRoot<'_> {
}
}
-#[derive(Clone, Debug)]
+#[derive(Debug)]
enum PathResult<'a> {
Module(ModuleOrUniformRoot<'a>),
NonModule(PartialRes),
@@ -434,7 +437,7 @@ enum ModuleKind {
impl ModuleKind {
/// Get name of the module.
- pub fn name(&self) -> Option<Symbol> {
+ fn name(&self) -> Option<Symbol> {
match self {
ModuleKind::Block => None,
ModuleKind::Def(.., name) => Some(*name),
@@ -470,7 +473,7 @@ type Resolutions<'a> = RefCell<FxIndexMap<BindingKey, &'a RefCell<NameResolution
/// * curly-braced block with statements
///
/// You can use [`ModuleData::kind`] to determine the kind of module this is.
-pub struct ModuleData<'a> {
+struct ModuleData<'a> {
/// The direct parent module (it may not be a `mod`, however).
parent: Option<Module<'a>>,
/// What kind of module this is, because this may not be a `mod`.
@@ -529,9 +532,9 @@ impl<'a> ModuleData<'a> {
}
}
- fn for_each_child<R, F>(&'a self, resolver: &mut R, mut f: F)
+ fn for_each_child<'tcx, R, F>(&'a self, resolver: &mut R, mut f: F)
where
- R: AsMut<Resolver<'a>>,
+ R: AsMut<Resolver<'a, 'tcx>>,
F: FnMut(&mut R, Ident, Namespace, &'a NameBinding<'a>),
{
for (key, name_resolution) in resolver.as_mut().resolutions(self).borrow().iter() {
@@ -542,9 +545,9 @@ impl<'a> ModuleData<'a> {
}
/// This modifies `self` in place. The traits will be stored in `self.traits`.
- fn ensure_traits<R>(&'a self, resolver: &mut R)
+ fn ensure_traits<'tcx, R>(&'a self, resolver: &mut R)
where
- R: AsMut<Resolver<'a>>,
+ R: AsMut<Resolver<'a, 'tcx>>,
{
let mut traits = self.traits.borrow_mut();
if traits.is_none() {
@@ -569,7 +572,7 @@ impl<'a> ModuleData<'a> {
}
// Public for rustdoc.
- pub fn def_id(&self) -> DefId {
+ fn def_id(&self) -> DefId {
self.opt_def_id().expect("`ModuleData::def_id` is called on a block module")
}
@@ -627,7 +630,7 @@ impl<'a> fmt::Debug for ModuleData<'a> {
/// Records a possibly-private value, type, or module definition.
#[derive(Clone, Debug)]
-pub struct NameBinding<'a> {
+struct NameBinding<'a> {
kind: NameBindingKind<'a>,
ambiguity: Option<(&'a NameBinding<'a>, AmbiguityKind)>,
expansion: LocalExpnId,
@@ -635,7 +638,7 @@ pub struct NameBinding<'a> {
vis: ty::Visibility<DefId>,
}
-pub trait ToNameBinding<'a> {
+trait ToNameBinding<'a> {
fn to_name_binding(self, arenas: &'a ResolverArenas<'a>) -> &'a NameBinding<'a>;
}
@@ -839,9 +842,9 @@ impl<'a> NameBinding<'a> {
}
#[derive(Default, Clone)]
-pub struct ExternPreludeEntry<'a> {
+struct ExternPreludeEntry<'a> {
extern_crate_item: Option<&'a NameBinding<'a>>,
- pub introduced_by_item: bool,
+ introduced_by_item: bool,
}
/// Used for better errors for E0773
@@ -865,8 +868,8 @@ struct MacroData {
/// The main resolver class.
///
/// This is the visitor that walks the whole crate.
-pub struct Resolver<'a> {
- session: &'a Session,
+pub struct Resolver<'a, 'tcx> {
+ tcx: TyCtxt<'tcx>,
/// Item with a given `LocalDefId` was defined during macro expansion with ID `ExpnId`.
expn_that_defined: FxHashMap<LocalDefId, ExpnId>,
@@ -943,23 +946,19 @@ pub struct Resolver<'a> {
has_pub_restricted: bool,
used_imports: FxHashSet<NodeId>,
maybe_unused_trait_imports: FxIndexSet<LocalDefId>,
- maybe_unused_extern_crates: Vec<(LocalDefId, Span)>,
/// Privacy errors are delayed until the end in order to deduplicate them.
privacy_errors: Vec<PrivacyError<'a>>,
/// Ambiguity errors are delayed for deduplication.
ambiguity_errors: Vec<AmbiguityError<'a>>,
/// `use` injections are delayed for better placement and deduplication.
- use_injections: Vec<UseError<'a>>,
+ use_injections: Vec<UseError<'tcx>>,
/// Crate-local macro expanded `macro_export` referred to by a module-relative path.
macro_expanded_macro_export_errors: BTreeSet<(Span, Span)>,
arenas: &'a ResolverArenas<'a>,
dummy_binding: &'a NameBinding<'a>,
- local_crate_name: Symbol,
- metadata_loader: Box<MetadataLoaderDyn>,
- untracked: Untracked,
used_extern_options: FxHashSet<Symbol>,
macro_names: FxHashSet<Ident>,
builtin_macros: FxHashMap<Symbol, BuiltinMacroState>,
@@ -1046,6 +1045,9 @@ pub struct Resolver<'a> {
lifetime_elision_allowed: FxHashSet<NodeId>,
effective_visibilities: EffectiveVisibilities,
+ doc_link_resolutions: FxHashMap<LocalDefId, DocLinkResMap>,
+ doc_link_traits_in_scope: FxHashMap<LocalDefId, Vec<DefId>>,
+ all_macro_rules: FxHashMap<Symbol, Res>,
}
/// Nothing really interesting here; it just provides memory for the rest of the crate.
@@ -1109,42 +1111,25 @@ impl<'a> ResolverArenas<'a> {
}
}
-impl<'a> AsMut<Resolver<'a>> for Resolver<'a> {
- fn as_mut(&mut self) -> &mut Resolver<'a> {
+impl<'a, 'tcx> AsMut<Resolver<'a, 'tcx>> for Resolver<'a, 'tcx> {
+ fn as_mut(&mut self) -> &mut Resolver<'a, 'tcx> {
self
}
}
-/// A minimal subset of resolver that can implemenent `DefIdTree`, sometimes
-/// required to satisfy borrow checker by avoiding borrowing the whole resolver.
-#[derive(Clone, Copy)]
-struct ResolverTree<'a>(&'a Untracked);
-
-impl DefIdTree for ResolverTree<'_> {
- #[inline]
- fn opt_parent(self, id: DefId) -> Option<DefId> {
- let ResolverTree(Untracked { definitions, cstore, .. }) = self;
- match id.as_local() {
- Some(id) => definitions.read().def_key(id).parent,
- None => cstore.as_any().downcast_ref::<CStore>().unwrap().def_key(id).parent,
- }
- .map(|index| DefId { index, ..id })
- }
-}
-
-impl<'a, 'b> DefIdTree for &'a Resolver<'b> {
+impl<'a, 'b, 'tcx> DefIdTree for &'a Resolver<'b, 'tcx> {
#[inline]
fn opt_parent(self, id: DefId) -> Option<DefId> {
- ResolverTree(&self.untracked).opt_parent(id)
+ self.tcx.opt_parent(id)
}
}
-impl<'a> Resolver<'a> {
+impl<'tcx> Resolver<'_, 'tcx> {
fn opt_local_def_id(&self, node: NodeId) -> Option<LocalDefId> {
self.node_id_to_def_id.get(&node).copied()
}
- pub fn local_def_id(&self, node: NodeId) -> LocalDefId {
+ fn local_def_id(&self, node: NodeId) -> LocalDefId {
self.opt_local_def_id(node).unwrap_or_else(|| panic!("no entry for node id: `{:?}`", node))
}
@@ -1162,10 +1147,11 @@ impl<'a> Resolver<'a> {
"adding a def'n for node-id {:?} and data {:?} but a previous def'n exists: {:?}",
node_id,
data,
- self.untracked.definitions.read().def_key(self.node_id_to_def_id[&node_id]),
+ self.tcx.definitions_untracked().def_key(self.node_id_to_def_id[&node_id]),
);
- let def_id = self.untracked.definitions.write().create_def(parent, data);
+ // FIXME: remove `def_span` body, pass in the right spans here and call `tcx.at().create_def()`
+ let def_id = self.tcx.untracked().definitions.write().create_def(parent, data);
// Create the definition.
if expn_id != ExpnId::root() {
@@ -1174,7 +1160,7 @@ impl<'a> Resolver<'a> {
// A relative span's parent must be an absolute span.
debug_assert_eq!(span.data_untracked().parent, None);
- let _id = self.untracked.source_span.push(span);
+ let _id = self.tcx.untracked().source_span.push(span);
debug_assert_eq!(_id, def_id);
// Some things for which we allocate `LocalDefId`s don't correspond to
@@ -1193,23 +1179,21 @@ impl<'a> Resolver<'a> {
if let Some(def_id) = def_id.as_local() {
self.item_generics_num_lifetimes[&def_id]
} else {
- self.cstore().item_generics_num_lifetimes(def_id, self.session)
+ self.cstore().item_generics_num_lifetimes(def_id, self.tcx.sess)
}
}
- pub fn sess(&self) -> &'a Session {
- self.session
+ pub fn tcx(&self) -> TyCtxt<'tcx> {
+ self.tcx
}
}
-impl<'a> Resolver<'a> {
+impl<'a, 'tcx> Resolver<'a, 'tcx> {
pub fn new(
- session: &'a Session,
+ tcx: TyCtxt<'tcx>,
krate: &Crate,
- crate_name: Symbol,
- metadata_loader: Box<MetadataLoaderDyn>,
arenas: &'a ResolverArenas<'a>,
- ) -> Resolver<'a> {
+ ) -> Resolver<'a, 'tcx> {
let root_def_id = CRATE_DEF_ID.to_def_id();
let mut module_map = FxHashMap::default();
let graph_root = arenas.new_module(
@@ -1217,7 +1201,7 @@ impl<'a> Resolver<'a> {
ModuleKind::Def(DefKind::Mod, root_def_id, kw::Empty),
ExpnId::root(),
krate.spans.inner_span,
- session.contains_name(&krate.attrs, sym::no_implicit_prelude),
+ tcx.sess.contains_name(&krate.attrs, sym::no_implicit_prelude),
&mut module_map,
);
let empty_module = arenas.new_module(
@@ -1229,8 +1213,6 @@ impl<'a> Resolver<'a> {
&mut FxHashMap::default(),
);
- let definitions = Definitions::new(session.local_stable_crate_id());
-
let mut visibilities = FxHashMap::default();
visibilities.insert(CRATE_DEF_ID, ty::Visibility::Public);
@@ -1242,11 +1224,8 @@ impl<'a> Resolver<'a> {
let mut invocation_parents = FxHashMap::default();
invocation_parents.insert(LocalExpnId::ROOT, (CRATE_DEF_ID, ImplTraitContext::Existential));
- let mut source_span = IndexVec::default();
- let _id = source_span.push(krate.spans.inner_span);
- debug_assert_eq!(_id, CRATE_DEF_ID);
-
- let mut extern_prelude: FxHashMap<Ident, ExternPreludeEntry<'_>> = session
+ let mut extern_prelude: FxHashMap<Ident, ExternPreludeEntry<'_>> = tcx
+ .sess
.opts
.externs
.iter()
@@ -1254,19 +1233,19 @@ impl<'a> Resolver<'a> {
.map(|(name, _)| (Ident::from_str(name), Default::default()))
.collect();
- if !session.contains_name(&krate.attrs, sym::no_core) {
+ if !tcx.sess.contains_name(&krate.attrs, sym::no_core) {
extern_prelude.insert(Ident::with_dummy_span(sym::core), Default::default());
- if !session.contains_name(&krate.attrs, sym::no_std) {
+ if !tcx.sess.contains_name(&krate.attrs, sym::no_std) {
extern_prelude.insert(Ident::with_dummy_span(sym::std), Default::default());
}
}
- let registered_tools = macros::registered_tools(session, &krate.attrs);
+ let registered_tools = macros::registered_tools(tcx.sess, &krate.attrs);
- let features = session.features_untracked();
+ let features = tcx.sess.features_untracked();
let mut resolver = Resolver {
- session,
+ tcx,
expn_that_defined: Default::default(),
@@ -1304,7 +1283,6 @@ impl<'a> Resolver<'a> {
has_pub_restricted: false,
used_imports: FxHashSet::default(),
maybe_unused_trait_imports: Default::default(),
- maybe_unused_extern_crates: Vec::new(),
privacy_errors: Vec::new(),
ambiguity_errors: Vec::new(),
@@ -1320,23 +1298,16 @@ impl<'a> Resolver<'a> {
vis: ty::Visibility::Public,
}),
- metadata_loader,
- local_crate_name: crate_name,
used_extern_options: Default::default(),
- untracked: Untracked {
- cstore: Box::new(CStore::new(session)),
- source_span,
- definitions: RwLock::new(definitions),
- },
macro_names: FxHashSet::default(),
builtin_macros: Default::default(),
builtin_macro_kinds: Default::default(),
registered_tools,
macro_use_prelude: FxHashMap::default(),
macro_map: FxHashMap::default(),
- dummy_ext_bang: Lrc::new(SyntaxExtension::dummy_bang(session.edition())),
- dummy_ext_derive: Lrc::new(SyntaxExtension::dummy_derive(session.edition())),
- non_macro_attr: Lrc::new(SyntaxExtension::non_macro_attr(session.edition())),
+ dummy_ext_bang: Lrc::new(SyntaxExtension::dummy_bang(tcx.sess.edition())),
+ dummy_ext_derive: Lrc::new(SyntaxExtension::dummy_derive(tcx.sess.edition())),
+ non_macro_attr: Lrc::new(SyntaxExtension::non_macro_attr(tcx.sess.edition())),
invocation_parent_scopes: Default::default(),
output_macro_rules_scopes: Default::default(),
macro_rules_scopes: Default::default(),
@@ -1374,6 +1345,9 @@ impl<'a> Resolver<'a> {
confused_type_with_std_module: Default::default(),
lifetime_elision_allowed: Default::default(),
effective_visibilities: Default::default(),
+ doc_link_resolutions: Default::default(),
+ doc_link_traits_in_scope: Default::default(),
+ all_macro_rules: Default::default(),
};
let root_parent_scope = ParentScope::module(graph_root, &resolver);
@@ -1394,14 +1368,14 @@ impl<'a> Resolver<'a> {
self.arenas.new_module(parent, kind, expn_id, span, no_implicit_prelude, module_map)
}
- pub fn next_node_id(&mut self) -> NodeId {
+ fn next_node_id(&mut self) -> NodeId {
let start = self.next_node_id;
let next = start.as_u32().checked_add(1).expect("input too large; ran out of NodeIds");
self.next_node_id = ast::NodeId::from_u32(next);
start
}
- pub fn next_node_ids(&mut self, count: usize) -> std::ops::Range<NodeId> {
+ fn next_node_ids(&mut self, count: usize) -> std::ops::Range<NodeId> {
let start = self.next_node_id;
let end = start.as_usize().checked_add(count).expect("input too large; ran out of NodeIds");
self.next_node_id = ast::NodeId::from_usize(end);
@@ -1424,12 +1398,10 @@ impl<'a> Resolver<'a> {
let extern_crate_map = self.extern_crate_map;
let reexport_map = self.reexport_map;
let maybe_unused_trait_imports = self.maybe_unused_trait_imports;
- let maybe_unused_extern_crates = self.maybe_unused_extern_crates;
let glob_map = self.glob_map;
let main_def = self.main_def;
let confused_type_with_std_module = self.confused_type_with_std_module;
let effective_visibilities = self.effective_visibilities;
- let untracked = self.untracked;
let global_ctxt = ResolverGlobalCtxt {
expn_that_defined,
visibilities,
@@ -1439,17 +1411,14 @@ impl<'a> Resolver<'a> {
reexport_map,
glob_map,
maybe_unused_trait_imports,
- maybe_unused_extern_crates,
- extern_prelude: self
- .extern_prelude
- .iter()
- .map(|(ident, entry)| (ident.name, entry.introduced_by_item))
- .collect(),
main_def,
trait_impls: self.trait_impls,
proc_macros,
confused_type_with_std_module,
registered_tools: self.registered_tools,
+ doc_link_resolutions: self.doc_link_resolutions,
+ doc_link_traits_in_scope: self.doc_link_traits_in_scope,
+ all_macro_rules: self.all_macro_rules,
};
let ast_lowering = ty::ResolverAstLowering {
legacy_const_generic_args: self.legacy_const_generic_args,
@@ -1465,70 +1434,21 @@ impl<'a> Resolver<'a> {
builtin_macro_kinds: self.builtin_macro_kinds,
lifetime_elision_allowed: self.lifetime_elision_allowed,
};
- ResolverOutputs { global_ctxt, ast_lowering, untracked }
- }
-
- pub fn clone_outputs(&self) -> ResolverOutputs {
- let proc_macros = self.proc_macros.iter().map(|id| self.local_def_id(*id)).collect();
- let definitions = self.untracked.definitions.clone();
- let cstore = Box::new(self.cstore().clone());
- let untracked =
- Untracked { cstore, source_span: self.untracked.source_span.clone(), definitions };
- let global_ctxt = ResolverGlobalCtxt {
- expn_that_defined: self.expn_that_defined.clone(),
- visibilities: self.visibilities.clone(),
- has_pub_restricted: self.has_pub_restricted,
- extern_crate_map: self.extern_crate_map.clone(),
- reexport_map: self.reexport_map.clone(),
- glob_map: self.glob_map.clone(),
- maybe_unused_trait_imports: self.maybe_unused_trait_imports.clone(),
- maybe_unused_extern_crates: self.maybe_unused_extern_crates.clone(),
- extern_prelude: self
- .extern_prelude
- .iter()
- .map(|(ident, entry)| (ident.name, entry.introduced_by_item))
- .collect(),
- 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(),
- registered_tools: self.registered_tools.clone(),
- effective_visibilities: self.effective_visibilities.clone(),
- };
- let ast_lowering = ty::ResolverAstLowering {
- legacy_const_generic_args: self.legacy_const_generic_args.clone(),
- partial_res_map: self.partial_res_map.clone(),
- import_res_map: self.import_res_map.clone(),
- label_res_map: self.label_res_map.clone(),
- lifetimes_res_map: self.lifetimes_res_map.clone(),
- extra_lifetime_params_map: self.extra_lifetime_params_map.clone(),
- next_node_id: self.next_node_id,
- node_id_to_def_id: self.node_id_to_def_id.clone(),
- def_id_to_node_id: self.def_id_to_node_id.clone(),
- trait_map: self.trait_map.clone(),
- builtin_macro_kinds: self.builtin_macro_kinds.clone(),
- lifetime_elision_allowed: self.lifetime_elision_allowed.clone(),
- };
- ResolverOutputs { global_ctxt, ast_lowering, untracked }
+ ResolverOutputs { global_ctxt, ast_lowering }
}
fn create_stable_hashing_context(&self) -> StableHashingContext<'_> {
- StableHashingContext::new(self.session, &self.untracked)
+ StableHashingContext::new(self.tcx.sess, self.tcx.untracked())
}
- pub fn crate_loader(&mut self) -> CrateLoader<'_> {
- CrateLoader::new(
- &self.session,
- &*self.metadata_loader,
- self.local_crate_name,
- &mut *self.untracked.cstore.untracked_as_any().downcast_mut().unwrap(),
- self.untracked.definitions.read(),
- &mut self.used_extern_options,
- )
+ fn crate_loader<T>(&mut self, f: impl FnOnce(&mut CrateLoader<'_, '_>) -> T) -> T {
+ let mut cstore = self.tcx.untracked().cstore.write();
+ let cstore = cstore.untracked_as_any().downcast_mut().unwrap();
+ f(&mut CrateLoader::new(self.tcx, &mut *cstore, &mut self.used_extern_options))
}
- pub fn cstore(&self) -> &CStore {
- self.untracked.cstore.as_any().downcast_ref().unwrap()
+ fn cstore(&self) -> MappedReadGuard<'_, CStore> {
+ CStore::from_tcx(self.tcx)
}
fn dummy_ext(&self, macro_kind: MacroKind) -> Lrc<SyntaxExtension> {
@@ -1561,21 +1481,26 @@ impl<'a> Resolver<'a> {
/// Entry point to crate resolution.
pub fn resolve_crate(&mut self, krate: &Crate) {
- self.session.time("resolve_crate", || {
- self.session.time("finalize_imports", || ImportResolver { r: self }.finalize_imports());
- self.session.time("compute_effective_visibilities", || {
+ self.tcx.sess.time("resolve_crate", || {
+ self.tcx.sess.time("finalize_imports", || self.finalize_imports());
+ self.tcx.sess.time("compute_effective_visibilities", || {
EffectiveVisibilitiesVisitor::compute_effective_visibilities(self, krate)
});
- self.session.time("finalize_macro_resolutions", || self.finalize_macro_resolutions());
- self.session.time("late_resolve_crate", || self.late_resolve_crate(krate));
- self.session.time("resolve_main", || self.resolve_main());
- self.session.time("resolve_check_unused", || self.check_unused(krate));
- self.session.time("resolve_report_errors", || self.report_errors(krate));
- self.session.time("resolve_postprocess", || self.crate_loader().postprocess(krate));
+ self.tcx.sess.time("finalize_macro_resolutions", || self.finalize_macro_resolutions());
+ self.tcx.sess.time("late_resolve_crate", || self.late_resolve_crate(krate));
+ self.tcx.sess.time("resolve_main", || self.resolve_main());
+ self.tcx.sess.time("resolve_check_unused", || self.check_unused(krate));
+ self.tcx.sess.time("resolve_report_errors", || self.report_errors(krate));
+ self.tcx
+ .sess
+ .time("resolve_postprocess", || self.crate_loader(|c| c.postprocess(krate)));
});
+
+ // Make sure we don't mutate the cstore from here on.
+ self.tcx.untracked().cstore.leak();
}
- pub fn traits_in_scope(
+ fn traits_in_scope(
&mut self,
current_trait: Option<Module<'a>>,
parent_scope: &ParentScope<'a>,
@@ -1911,10 +1836,10 @@ impl<'a> Resolver<'a> {
} else {
let crate_id = if finalize {
let Some(crate_id) =
- self.crate_loader().process_path_extern(ident.name, ident.span) else { return Some(self.dummy_binding); };
+ self.crate_loader(|c| c.process_path_extern(ident.name, ident.span)) else { return Some(self.dummy_binding); };
crate_id
} else {
- self.crate_loader().maybe_process_path_extern(ident.name)?
+ self.crate_loader(|c| c.maybe_process_path_extern(ident.name))?
};
let crate_root = self.expect_module(crate_id.as_def_id());
let vis = ty::Visibility::<LocalDefId>::Public;
@@ -1927,7 +1852,7 @@ impl<'a> Resolver<'a> {
/// isn't something that can be returned because it can't be made to live that long,
/// and also it's a private type. Fortunately rustdoc doesn't need to know the error,
/// just that an error occurred.
- pub fn resolve_rustdoc_path(
+ fn resolve_rustdoc_path(
&mut self,
path_str: &str,
ns: Namespace,
@@ -1959,41 +1884,17 @@ impl<'a> Resolver<'a> {
}
}
- /// For rustdoc.
- /// For local modules returns only reexports, for external modules returns all children.
- pub fn module_children_or_reexports(&self, def_id: DefId) -> Vec<ModChild> {
- if let Some(def_id) = def_id.as_local() {
- self.reexport_map.get(&def_id).cloned().unwrap_or_default()
- } else {
- self.cstore().module_children_untracked(def_id, self.session).collect()
- }
- }
-
- /// For rustdoc.
- pub fn macro_rules_scope(&self, def_id: LocalDefId) -> (MacroRulesScopeRef<'a>, Res) {
- let scope = *self.macro_rules_scopes.get(&def_id).expect("not a `macro_rules` item");
- match scope.get() {
- MacroRulesScope::Binding(mb) => (scope, mb.binding.res()),
- _ => unreachable!(),
- }
- }
-
- /// For rustdoc.
- pub fn get_partial_res(&self, node_id: NodeId) -> Option<PartialRes> {
- self.partial_res_map.get(&node_id).copied()
- }
-
/// Retrieves the span of the given `DefId` if `DefId` is in the local crate.
#[inline]
- pub fn opt_span(&self, def_id: DefId) -> Option<Span> {
- def_id.as_local().map(|def_id| self.untracked.source_span[def_id])
+ fn opt_span(&self, def_id: DefId) -> Option<Span> {
+ def_id.as_local().map(|def_id| self.tcx.source_span(def_id))
}
/// Retrieves the name of the given `DefId`.
#[inline]
- pub fn opt_name(&self, def_id: DefId) -> Option<Symbol> {
+ fn opt_name(&self, def_id: DefId) -> Option<Symbol> {
let def_key = match def_id.as_local() {
- Some(def_id) => self.untracked.definitions.read().def_key(def_id),
+ Some(def_id) => self.tcx.definitions_untracked().def_key(def_id),
None => self.cstore().def_key(def_id),
};
def_key.get_opt_name()
@@ -2002,7 +1903,7 @@ impl<'a> Resolver<'a> {
/// Checks if an expression refers to a function marked with
/// `#[rustc_legacy_const_generics]` and returns the argument index list
/// from the attribute.
- pub fn legacy_const_generic_args(&mut self, expr: &Expr) -> Option<Vec<usize>> {
+ fn legacy_const_generic_args(&mut self, expr: &Expr) -> Option<Vec<usize>> {
if let ExprKind::Path(None, path) = &expr.kind {
// Don't perform legacy const generics rewriting if the path already
// has generic arguments.
@@ -2025,7 +1926,7 @@ impl<'a> Resolver<'a> {
let attr = self
.cstore()
- .item_attrs_untracked(def_id, self.session)
+ .item_attrs_untracked(def_id, self.tcx.sess)
.find(|a| a.has_name(sym::rustc_legacy_const_generics))?;
let mut ret = Vec::new();
for meta in attr.meta_item_list()? {
diff --git a/compiler/rustc_resolve/src/macros.rs b/compiler/rustc_resolve/src/macros.rs
index b5b1602c5..b38c11e8b 100644
--- a/compiler/rustc_resolve/src/macros.rs
+++ b/compiler/rustc_resolve/src/macros.rs
@@ -1,7 +1,6 @@
//! A bunch of methods and structures more or less related to resolving macros and
//! interface provided by `Resolver` to macro expander.
-use crate::imports::ImportResolver;
use crate::Namespace::*;
use crate::{BuiltinMacroState, Determinacy};
use crate::{DeriveData, Finalize, ParentScope, ResolutionError, Resolver, ScopeSet};
@@ -39,7 +38,7 @@ type Res = def::Res<NodeId>;
/// Binding produced by a `macro_rules` item.
/// Not modularized, can shadow previous `macro_rules` bindings, etc.
#[derive(Debug)]
-pub struct MacroRulesBinding<'a> {
+pub(crate) struct MacroRulesBinding<'a> {
pub(crate) binding: &'a NameBinding<'a>,
/// `macro_rules` scope into which the `macro_rules` item was planted.
pub(crate) parent_macro_rules_scope: MacroRulesScopeRef<'a>,
@@ -52,7 +51,7 @@ pub struct MacroRulesBinding<'a> {
/// Some macro invocations need to introduce `macro_rules` scopes too because they
/// can potentially expand into macro definitions.
#[derive(Copy, Clone, Debug)]
-pub enum MacroRulesScope<'a> {
+pub(crate) enum MacroRulesScope<'a> {
/// Empty "root" scope at the crate start containing no names.
Empty,
/// The scope introduced by a `macro_rules!` macro definition.
@@ -160,7 +159,7 @@ fn soft_custom_inner_attributes_gate(path: &ast::Path, invoc: &Invocation) -> bo
false
}
-impl<'a> ResolverExpand for Resolver<'a> {
+impl<'a, 'tcx> ResolverExpand for Resolver<'a, 'tcx> {
fn next_node_id(&mut self) -> NodeId {
self.next_node_id()
}
@@ -195,7 +194,8 @@ impl<'a> ResolverExpand for Resolver<'a> {
fn register_builtin_macro(&mut self, name: Symbol, ext: SyntaxExtensionKind) {
if self.builtin_macros.insert(name, BuiltinMacroState::NotYetSeen(ext)).is_some() {
- self.session
+ self.tcx
+ .sess
.diagnostic()
.bug(&format!("built-in macro `{}` was already registered", name));
}
@@ -216,7 +216,7 @@ impl<'a> ResolverExpand for Resolver<'a> {
ExpnData::allow_unstable(
ExpnKind::AstPass(pass),
call_site,
- self.session.edition(),
+ self.tcx.sess.edition(),
features.into(),
None,
parent_module,
@@ -232,7 +232,7 @@ impl<'a> ResolverExpand for Resolver<'a> {
}
fn resolve_imports(&mut self) {
- ImportResolver { r: self }.resolve_imports()
+ self.resolve_imports()
}
fn resolve_macro_invocation(
@@ -430,7 +430,7 @@ impl<'a> ResolverExpand for Resolver<'a> {
PathResult::NonModule(..) |
// HACK(Urgau): This shouldn't be necessary
PathResult::Failed { is_error_from_last_segment: false, .. } => {
- self.session
+ self.tcx.sess
.struct_span_err(span, "not sure whether the path is accessible or not")
.note("the type may have associated items, but we are currently not checking them")
.emit();
@@ -455,7 +455,7 @@ impl<'a> ResolverExpand for Resolver<'a> {
}
fn get_proc_macro_quoted_span(&self, krate: CrateNum, id: usize) -> Span {
- self.cstore().get_proc_macro_quoted_span_untracked(krate, id, self.session)
+ self.cstore().get_proc_macro_quoted_span_untracked(krate, id, self.tcx.sess)
}
fn declare_proc_macro(&mut self, id: NodeId) {
@@ -467,7 +467,7 @@ impl<'a> ResolverExpand for Resolver<'a> {
}
}
-impl<'a> Resolver<'a> {
+impl<'a, 'tcx> Resolver<'a, 'tcx> {
/// Resolve macro path with error reporting and recovery.
/// Uses dummy syntax extensions for unresolved macros or macros with unexpected resolutions
/// for better error recovery.
@@ -493,10 +493,10 @@ impl<'a> Resolver<'a> {
// Report errors for the resolved macro.
for segment in &path.segments {
if let Some(args) = &segment.args {
- self.session.span_err(args.span(), "generic arguments in macro path");
+ self.tcx.sess.span_err(args.span(), "generic arguments in macro path");
}
if kind == MacroKind::Attr && segment.ident.as_str().starts_with("rustc") {
- self.session.span_err(
+ self.tcx.sess.span_err(
segment.ident.span,
"attributes starting with `rustc` are reserved for use by the `rustc` compiler",
);
@@ -508,7 +508,7 @@ impl<'a> Resolver<'a> {
if let Some(def_id) = def_id.as_local() {
self.unused_macros.remove(&def_id);
if self.proc_macro_stubs.contains(&def_id) {
- self.session.span_err(
+ self.tcx.sess.span_err(
path.span,
"can't use a procedural macro from the same crate that defines it",
);
@@ -540,7 +540,8 @@ impl<'a> Resolver<'a> {
if let Some((article, expected)) = unexpected_res {
let path_str = pprust::path_to_string(path);
let msg = format!("expected {}, found {} `{}`", expected, res.descr(), path_str);
- self.session
+ self.tcx
+ .sess
.struct_span_err(path.span, &msg)
.span_label(path.span, format!("not {} {}", article, expected))
.emit();
@@ -550,7 +551,7 @@ impl<'a> Resolver<'a> {
// We are trying to avoid reporting this error if other related errors were reported.
if res != Res::Err
&& inner_attr
- && !self.session.features_untracked().custom_inner_attributes
+ && !self.tcx.sess.features_untracked().custom_inner_attributes
{
let msg = match res {
Res::Def(..) => "inner macro attributes are unstable",
@@ -558,17 +559,22 @@ impl<'a> Resolver<'a> {
_ => unreachable!(),
};
if soft_custom_inner_attributes_gate {
- self.session.parse_sess.buffer_lint(SOFT_UNSTABLE, path.span, node_id, msg);
+ self.tcx.sess.parse_sess.buffer_lint(SOFT_UNSTABLE, path.span, node_id, msg);
} else {
- feature_err(&self.session.parse_sess, sym::custom_inner_attributes, path.span, msg)
- .emit();
+ feature_err(
+ &self.tcx.sess.parse_sess,
+ sym::custom_inner_attributes,
+ path.span,
+ msg,
+ )
+ .emit();
}
}
Ok((ext, res))
}
- pub fn resolve_macro_path(
+ pub(crate) fn resolve_macro_path(
&mut self,
path: &ast::Path,
kind: Option<MacroKind>,
@@ -655,7 +661,7 @@ impl<'a> Resolver<'a> {
// Make sure compilation does not succeed if preferred macro resolution
// has changed after the macro had been expanded. In theory all such
// situations should be reported as errors, so this is a bug.
- this.session.delay_span_bug(span, "inconsistent resolution for a macro");
+ this.tcx.sess.delay_span_bug(span, "inconsistent resolution for a macro");
}
} else {
// It's possible that the macro was unresolved (indeterminate) and silently
@@ -672,7 +678,7 @@ impl<'a> Resolver<'a> {
Segment::names_to_string(path)
);
let msg_note = "import resolution is stuck, try simplifying macro imports";
- this.session.struct_span_err(span, &msg).note(msg_note).emit();
+ this.tcx.sess.struct_span_err(span, &msg).note(msg_note).emit();
}
}
};
@@ -699,7 +705,7 @@ impl<'a> Resolver<'a> {
// try to suggest if it's not a macro, maybe a function
if let PathResult::NonModule(partial_res) = self.maybe_resolve_path(&path, Some(ValueNS), &parent_scope)
&& partial_res.unresolved_segments() == 0 {
- let sm = self.session.source_map();
+ let sm = self.tcx.sess.source_map();
let exclamation_span = sm.next_point(span);
suggestion = Some((
vec![(exclamation_span, "".to_string())],
@@ -762,7 +768,7 @@ impl<'a> Resolver<'a> {
Err(..) => {
let expected = kind.descr_expected();
let msg = format!("cannot find {} `{}` in this scope", expected, ident);
- let mut err = self.session.struct_span_err(ident.span, &msg);
+ let mut err = self.tcx.sess.struct_span_err(ident.span, &msg);
self.unresolved_macro_suggestions(&mut err, kind, &parent_scope, ident);
err.emit();
}
@@ -804,7 +810,7 @@ impl<'a> Resolver<'a> {
let soft_handler =
|lint, span, msg: &_| lint_buffer.buffer_lint(lint, node_id, span, msg);
stability::report_unstable(
- self.session,
+ self.tcx.sess,
feature,
reason.to_opt_reason(),
issue,
@@ -840,7 +846,7 @@ impl<'a> Resolver<'a> {
if kind != NonMacroAttrKind::Tool && binding.map_or(true, |b| b.is_import()) {
let msg =
format!("cannot use {} {} through an import", kind.article(), kind.descr());
- let mut err = self.session.struct_span_err(span, &msg);
+ let mut err = self.tcx.sess.struct_span_err(span, &msg);
if let Some(binding) = binding {
err.span_note(binding.span, &format!("the {} imported here", kind.descr()));
}
@@ -855,7 +861,7 @@ impl<'a> Resolver<'a> {
if ident.name == sym::cfg || ident.name == sym::cfg_attr {
let macro_kind = self.get_macro(res).map(|macro_data| macro_data.ext.macro_kind());
if macro_kind.is_some() && sub_namespace_match(macro_kind, Some(MacroKind::Attr)) {
- self.session.span_err(
+ self.tcx.sess.span_err(
ident.span,
&format!("name `{}` is reserved in attribute namespace", ident),
);
@@ -871,12 +877,7 @@ impl<'a> Resolver<'a> {
item: &ast::Item,
edition: Edition,
) -> (SyntaxExtension, Vec<(usize, Span)>) {
- let (mut result, mut rule_spans) = compile_declarative_macro(
- &self.session,
- self.session.features_untracked(),
- item,
- edition,
- );
+ let (mut result, mut rule_spans) = compile_declarative_macro(self.tcx.sess, item, edition);
if let Some(builtin_name) = result.builtin_name {
// The macro was marked with `#[rustc_builtin_macro]`.
@@ -895,7 +896,7 @@ impl<'a> Resolver<'a> {
}
BuiltinMacroState::AlreadySeen(span) => {
struct_span_err!(
- self.session,
+ self.tcx.sess,
item.span,
E0773,
"attempted to define built-in macro more than once"
@@ -906,7 +907,7 @@ impl<'a> Resolver<'a> {
}
} else {
let msg = format!("cannot find a built-in macro with name `{}`", item.ident);
- self.session.span_err(item.span, &msg);
+ self.tcx.sess.span_err(item.span, &msg);
}
}
diff --git a/compiler/rustc_resolve/src/rustdoc.rs b/compiler/rustc_resolve/src/rustdoc.rs
new file mode 100644
index 000000000..b8853c174
--- /dev/null
+++ b/compiler/rustc_resolve/src/rustdoc.rs
@@ -0,0 +1,388 @@
+use pulldown_cmark::{BrokenLink, Event, LinkType, Options, Parser, Tag};
+use rustc_ast as ast;
+use rustc_ast::util::comments::beautify_doc_string;
+use rustc_data_structures::fx::FxHashMap;
+use rustc_span::def_id::DefId;
+use rustc_span::symbol::{kw, Symbol};
+use rustc_span::Span;
+use std::{cmp, mem};
+
+#[derive(Clone, Copy, PartialEq, Eq, Debug)]
+pub enum DocFragmentKind {
+ /// A doc fragment created from a `///` or `//!` doc comment.
+ SugaredDoc,
+ /// A doc fragment created from a "raw" `#[doc=""]` attribute.
+ RawDoc,
+}
+
+/// A portion of documentation, extracted from a `#[doc]` attribute.
+///
+/// Each variant contains the line number within the complete doc-comment where the fragment
+/// starts, as well as the Span where the corresponding doc comment or attribute is located.
+///
+/// Included files are kept separate from inline doc comments so that proper line-number
+/// information can be given when a doctest fails. Sugared doc comments and "raw" doc comments are
+/// kept separate because of issue #42760.
+#[derive(Clone, PartialEq, Eq, Debug)]
+pub struct DocFragment {
+ pub span: Span,
+ /// The module this doc-comment came from.
+ ///
+ /// This allows distinguishing between the original documentation and a pub re-export.
+ /// If it is `None`, the item was not re-exported.
+ pub parent_module: Option<DefId>,
+ pub doc: Symbol,
+ pub kind: DocFragmentKind,
+ pub indent: usize,
+}
+
+#[derive(Clone, Copy, Debug)]
+pub enum MalformedGenerics {
+ /// This link has unbalanced angle brackets.
+ ///
+ /// For example, `Vec<T` should trigger this, as should `Vec<T>>`.
+ UnbalancedAngleBrackets,
+ /// The generics are not attached to a type.
+ ///
+ /// For example, `<T>` should trigger this.
+ ///
+ /// This is detected by checking if the path is empty after the generics are stripped.
+ MissingType,
+ /// The link uses fully-qualified syntax, which is currently unsupported.
+ ///
+ /// For example, `<Vec as IntoIterator>::into_iter` should trigger this.
+ ///
+ /// This is detected by checking if ` as ` (the keyword `as` with spaces around it) is inside
+ /// angle brackets.
+ HasFullyQualifiedSyntax,
+ /// The link has an invalid path separator.
+ ///
+ /// For example, `Vec:<T>:new()` should trigger this. Note that `Vec:new()` will **not**
+ /// trigger this because it has no generics and thus [`strip_generics_from_path`] will not be
+ /// called.
+ ///
+ /// Note that this will also **not** be triggered if the invalid path separator is inside angle
+ /// brackets because rustdoc mostly ignores what's inside angle brackets (except for
+ /// [`HasFullyQualifiedSyntax`](MalformedGenerics::HasFullyQualifiedSyntax)).
+ ///
+ /// This is detected by checking if there is a colon followed by a non-colon in the link.
+ InvalidPathSeparator,
+ /// The link has too many angle brackets.
+ ///
+ /// For example, `Vec<<T>>` should trigger this.
+ TooManyAngleBrackets,
+ /// The link has empty angle brackets.
+ ///
+ /// For example, `Vec<>` should trigger this.
+ EmptyAngleBrackets,
+}
+
+/// Removes excess indentation on comments in order for the Markdown
+/// to be parsed correctly. This is necessary because the convention for
+/// writing documentation is to provide a space between the /// or //! marker
+/// and the doc text, but Markdown is whitespace-sensitive. For example,
+/// a block of text with four-space indentation is parsed as a code block,
+/// so if we didn't unindent comments, these list items
+///
+/// /// A list:
+/// ///
+/// /// - Foo
+/// /// - Bar
+///
+/// would be parsed as if they were in a code block, which is likely not what the user intended.
+pub fn unindent_doc_fragments(docs: &mut [DocFragment]) {
+ // `add` is used in case the most common sugared doc syntax is used ("/// "). The other
+ // fragments kind's lines are never starting with a whitespace unless they are using some
+ // markdown formatting requiring it. Therefore, if the doc block have a mix between the two,
+ // we need to take into account the fact that the minimum indent minus one (to take this
+ // whitespace into account).
+ //
+ // For example:
+ //
+ // /// hello!
+ // #[doc = "another"]
+ //
+ // In this case, you want "hello! another" and not "hello! another".
+ let add = if docs.windows(2).any(|arr| arr[0].kind != arr[1].kind)
+ && docs.iter().any(|d| d.kind == DocFragmentKind::SugaredDoc)
+ {
+ // In case we have a mix of sugared doc comments and "raw" ones, we want the sugared one to
+ // "decide" how much the minimum indent will be.
+ 1
+ } else {
+ 0
+ };
+
+ // `min_indent` is used to know how much whitespaces from the start of each lines must be
+ // removed. Example:
+ //
+ // /// hello!
+ // #[doc = "another"]
+ //
+ // In here, the `min_indent` is 1 (because non-sugared fragment are always counted with minimum
+ // 1 whitespace), meaning that "hello!" will be considered a codeblock because it starts with 4
+ // (5 - 1) whitespaces.
+ let Some(min_indent) = docs
+ .iter()
+ .map(|fragment| {
+ fragment.doc.as_str().lines().fold(usize::MAX, |min_indent, line| {
+ if line.chars().all(|c| c.is_whitespace()) {
+ min_indent
+ } else {
+ // Compare against either space or tab, ignoring whether they are
+ // mixed or not.
+ let whitespace = line.chars().take_while(|c| *c == ' ' || *c == '\t').count();
+ cmp::min(min_indent, whitespace)
+ + if fragment.kind == DocFragmentKind::SugaredDoc { 0 } else { add }
+ }
+ })
+ })
+ .min()
+ else {
+ return;
+ };
+
+ for fragment in docs {
+ if fragment.doc == kw::Empty {
+ continue;
+ }
+
+ let min_indent = if fragment.kind != DocFragmentKind::SugaredDoc && min_indent > 0 {
+ min_indent - add
+ } else {
+ min_indent
+ };
+
+ fragment.indent = min_indent;
+ }
+}
+
+/// The goal of this function is to apply the `DocFragment` transformation that is required when
+/// transforming into the final Markdown, which is applying the computed indent to each line in
+/// each doc fragment (a `DocFragment` can contain multiple lines in case of `#[doc = ""]`).
+///
+/// Note: remove the trailing newline where appropriate
+pub fn add_doc_fragment(out: &mut String, frag: &DocFragment) {
+ let s = frag.doc.as_str();
+ let mut iter = s.lines();
+ if s.is_empty() {
+ out.push('\n');
+ return;
+ }
+ while let Some(line) = iter.next() {
+ if line.chars().any(|c| !c.is_whitespace()) {
+ assert!(line.len() >= frag.indent);
+ out.push_str(&line[frag.indent..]);
+ } else {
+ out.push_str(line);
+ }
+ out.push('\n');
+ }
+}
+
+pub fn attrs_to_doc_fragments<'a>(
+ attrs: impl Iterator<Item = (&'a ast::Attribute, Option<DefId>)>,
+ doc_only: bool,
+) -> (Vec<DocFragment>, ast::AttrVec) {
+ let mut doc_fragments = Vec::new();
+ let mut other_attrs = ast::AttrVec::new();
+ for (attr, parent_module) in attrs {
+ if let Some((doc_str, comment_kind)) = attr.doc_str_and_comment_kind() {
+ let doc = beautify_doc_string(doc_str, comment_kind);
+ let kind = if attr.is_doc_comment() {
+ DocFragmentKind::SugaredDoc
+ } else {
+ DocFragmentKind::RawDoc
+ };
+ let fragment = DocFragment { span: attr.span, doc, kind, parent_module, indent: 0 };
+ doc_fragments.push(fragment);
+ } else if !doc_only {
+ other_attrs.push(attr.clone());
+ }
+ }
+
+ unindent_doc_fragments(&mut doc_fragments);
+
+ (doc_fragments, other_attrs)
+}
+
+/// Return the doc-comments on this item, grouped by the module they came from.
+/// The module can be different if this is a re-export with added documentation.
+///
+/// The last newline is not trimmed so the produced strings are reusable between
+/// early and late doc link resolution regardless of their position.
+pub fn prepare_to_doc_link_resolution(
+ doc_fragments: &[DocFragment],
+) -> FxHashMap<Option<DefId>, String> {
+ let mut res = FxHashMap::default();
+ for fragment in doc_fragments {
+ let out_str = res.entry(fragment.parent_module).or_default();
+ add_doc_fragment(out_str, fragment);
+ }
+ res
+}
+
+/// Options for rendering Markdown in the main body of documentation.
+pub fn main_body_opts() -> Options {
+ Options::ENABLE_TABLES
+ | Options::ENABLE_FOOTNOTES
+ | Options::ENABLE_STRIKETHROUGH
+ | Options::ENABLE_TASKLISTS
+ | Options::ENABLE_SMART_PUNCTUATION
+}
+
+fn strip_generics_from_path_segment(segment: Vec<char>) -> Result<String, MalformedGenerics> {
+ let mut stripped_segment = String::new();
+ let mut param_depth = 0;
+
+ let mut latest_generics_chunk = String::new();
+
+ for c in segment {
+ if c == '<' {
+ param_depth += 1;
+ latest_generics_chunk.clear();
+ } else if c == '>' {
+ param_depth -= 1;
+ if latest_generics_chunk.contains(" as ") {
+ // The segment tries to use fully-qualified syntax, which is currently unsupported.
+ // Give a helpful error message instead of completely ignoring the angle brackets.
+ return Err(MalformedGenerics::HasFullyQualifiedSyntax);
+ }
+ } else {
+ if param_depth == 0 {
+ stripped_segment.push(c);
+ } else {
+ latest_generics_chunk.push(c);
+ }
+ }
+ }
+
+ if param_depth == 0 {
+ Ok(stripped_segment)
+ } else {
+ // The segment has unbalanced angle brackets, e.g. `Vec<T` or `Vec<T>>`
+ Err(MalformedGenerics::UnbalancedAngleBrackets)
+ }
+}
+
+pub fn strip_generics_from_path(path_str: &str) -> Result<Box<str>, MalformedGenerics> {
+ if !path_str.contains(['<', '>']) {
+ return Ok(path_str.into());
+ }
+ let mut stripped_segments = vec![];
+ let mut path = path_str.chars().peekable();
+ let mut segment = Vec::new();
+
+ while let Some(chr) = path.next() {
+ match chr {
+ ':' => {
+ if path.next_if_eq(&':').is_some() {
+ let stripped_segment =
+ strip_generics_from_path_segment(mem::take(&mut segment))?;
+ if !stripped_segment.is_empty() {
+ stripped_segments.push(stripped_segment);
+ }
+ } else {
+ return Err(MalformedGenerics::InvalidPathSeparator);
+ }
+ }
+ '<' => {
+ segment.push(chr);
+
+ match path.next() {
+ Some('<') => {
+ return Err(MalformedGenerics::TooManyAngleBrackets);
+ }
+ Some('>') => {
+ return Err(MalformedGenerics::EmptyAngleBrackets);
+ }
+ Some(chr) => {
+ segment.push(chr);
+
+ while let Some(chr) = path.next_if(|c| *c != '>') {
+ segment.push(chr);
+ }
+ }
+ None => break,
+ }
+ }
+ _ => segment.push(chr),
+ }
+ trace!("raw segment: {:?}", segment);
+ }
+
+ if !segment.is_empty() {
+ let stripped_segment = strip_generics_from_path_segment(segment)?;
+ if !stripped_segment.is_empty() {
+ stripped_segments.push(stripped_segment);
+ }
+ }
+
+ debug!("path_str: {:?}\nstripped segments: {:?}", path_str, &stripped_segments);
+
+ let stripped_path = stripped_segments.join("::");
+
+ if !stripped_path.is_empty() {
+ Ok(stripped_path.into())
+ } else {
+ Err(MalformedGenerics::MissingType)
+ }
+}
+
+/// Returns whether the first doc-comment is an inner attribute.
+///
+//// If there are no doc-comments, return true.
+/// FIXME(#78591): Support both inner and outer attributes on the same item.
+pub fn inner_docs(attrs: &[ast::Attribute]) -> bool {
+ attrs.iter().find(|a| a.doc_str().is_some()).map_or(true, |a| a.style == ast::AttrStyle::Inner)
+}
+
+/// Simplified version of the corresponding function in rustdoc.
+/// If the rustdoc version returns a successful result, this function must return the same result.
+/// Otherwise this function may return anything.
+fn preprocess_link(link: &str) -> Box<str> {
+ let link = link.replace('`', "");
+ let link = link.split('#').next().unwrap();
+ let link = link.trim();
+ let link = link.rsplit('@').next().unwrap();
+ let link = link.strip_suffix("()").unwrap_or(link);
+ let link = link.strip_suffix("{}").unwrap_or(link);
+ let link = link.strip_suffix("[]").unwrap_or(link);
+ let link = if link != "!" { link.strip_suffix('!').unwrap_or(link) } else { link };
+ strip_generics_from_path(link).unwrap_or_else(|_| link.into())
+}
+
+/// Keep inline and reference links `[]`,
+/// but skip autolinks `<>` which we never consider to be intra-doc links.
+pub fn may_be_doc_link(link_type: LinkType) -> bool {
+ match link_type {
+ LinkType::Inline
+ | LinkType::Reference
+ | LinkType::ReferenceUnknown
+ | LinkType::Collapsed
+ | LinkType::CollapsedUnknown
+ | LinkType::Shortcut
+ | LinkType::ShortcutUnknown => true,
+ LinkType::Autolink | LinkType::Email => false,
+ }
+}
+
+/// Simplified version of `preprocessed_markdown_links` from rustdoc.
+/// Must return at least the same links as it, but may add some more links on top of that.
+pub(crate) fn attrs_to_preprocessed_links(attrs: &[ast::Attribute]) -> Vec<Box<str>> {
+ let (doc_fragments, _) = attrs_to_doc_fragments(attrs.iter().map(|attr| (attr, None)), true);
+ let doc = prepare_to_doc_link_resolution(&doc_fragments).into_values().next().unwrap();
+
+ Parser::new_with_broken_link_callback(
+ &doc,
+ main_body_opts(),
+ Some(&mut |link: BrokenLink<'_>| Some((link.reference, "".into()))),
+ )
+ .filter_map(|event| match event {
+ Event::Start(Tag::Link(link_type, dest, _)) if may_be_doc_link(link_type) => {
+ Some(preprocess_link(&dest))
+ }
+ _ => None,
+ })
+ .collect()
+}
diff --git a/compiler/rustc_save_analysis/Cargo.toml b/compiler/rustc_save_analysis/Cargo.toml
deleted file mode 100644
index 181e27f33..000000000
--- a/compiler/rustc_save_analysis/Cargo.toml
+++ /dev/null
@@ -1,21 +0,0 @@
-[package]
-name = "rustc_save_analysis"
-version = "0.0.0"
-edition = "2021"
-
-[dependencies]
-tracing = "0.1"
-rustc_middle = { path = "../rustc_middle" }
-rustc_ast = { path = "../rustc_ast" }
-rustc_ast_pretty = { path = "../rustc_ast_pretty" }
-rustc_data_structures = { path = "../rustc_data_structures" }
-rustc_errors = { path = "../rustc_errors" }
-rustc_hir = { path = "../rustc_hir" }
-rustc_hir_pretty = { path = "../rustc_hir_pretty" }
-rustc_lexer = { path = "../rustc_lexer" }
-rustc_macros = { path = "../rustc_macros" }
-serde_json = "1"
-rustc_session = { path = "../rustc_session" }
-rustc_span = { path = "../rustc_span" }
-rls-data = "0.19"
-rls-span = "0.5"
diff --git a/compiler/rustc_save_analysis/src/dump_visitor.rs b/compiler/rustc_save_analysis/src/dump_visitor.rs
deleted file mode 100644
index a5f09de1c..000000000
--- a/compiler/rustc_save_analysis/src/dump_visitor.rs
+++ /dev/null
@@ -1,1471 +0,0 @@
-//! Write the output of rustc's analysis to an implementor of Dump.
-//!
-//! Dumping the analysis is implemented by walking the AST and getting a bunch of
-//! info out from all over the place. We use `DefId`s to identify objects. The
-//! tricky part is getting syntactic (span, source text) and semantic (reference
-//! `DefId`s) information for parts of expressions which the compiler has discarded.
-//! E.g., in a path `foo::bar::baz`, the compiler only keeps a span for the whole
-//! path and a reference to `baz`, but we want spans and references for all three
-//! idents.
-//!
-//! SpanUtils is used to manipulate spans. In particular, to extract sub-spans
-//! from spans (e.g., the span for `bar` from the above example path).
-//! DumpVisitor walks the AST and processes it, and Dumper is used for
-//! recording the output.
-
-use rustc_ast as ast;
-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, 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::nested_filter;
-use rustc_middle::span_bug;
-use rustc_middle::ty::{self, DefIdTree, TyCtxt};
-use rustc_session::config::Input;
-use rustc_span::symbol::Ident;
-use rustc_span::*;
-
-use std::env;
-use std::path::Path;
-
-use crate::dumper::{Access, Dumper};
-use crate::sig;
-use crate::span_utils::SpanUtils;
-use crate::{
- escape, generated_code, id_from_def_id, id_from_hir_id, lower_attributes, PathCollector,
- SaveContext,
-};
-
-use rls_data::{
- CompilationOptions, CratePreludeData, Def, DefKind, GlobalCrateId, Import, ImportKind, Ref,
- RefKind, Relation, RelationKind, SpanData,
-};
-
-#[rustfmt::skip] // https://github.com/rust-lang/rustfmt/issues/5213
-macro_rules! down_cast_data {
- ($id:ident, $kind:ident, $sp:expr) => {
- let super::Data::$kind($id) = $id else {
- span_bug!($sp, "unexpected data kind: {:?}", $id);
- };
- };
-}
-
-macro_rules! access_from {
- ($save_ctxt:expr, $id:expr) => {
- Access {
- public: $save_ctxt.tcx.visibility($id).is_public(),
- reachable: $save_ctxt.effective_visibilities.is_reachable($id),
- }
- };
-}
-
-pub struct DumpVisitor<'tcx> {
- pub save_ctxt: SaveContext<'tcx>,
- tcx: TyCtxt<'tcx>,
- dumper: Dumper,
-
- span: SpanUtils<'tcx>,
- // Set of macro definition (callee) spans, and the set
- // of macro use (callsite) spans. We store these to ensure
- // we only write one macro def per unique macro definition, and
- // one macro use per unique callsite span.
- // mac_defs: FxHashSet<Span>,
- // macro_calls: FxHashSet<Span>,
-}
-
-impl<'tcx> DumpVisitor<'tcx> {
- pub fn new(save_ctxt: SaveContext<'tcx>) -> DumpVisitor<'tcx> {
- let span_utils = SpanUtils::new(&save_ctxt.tcx.sess);
- let dumper = Dumper::new(save_ctxt.config.clone());
- DumpVisitor { tcx: save_ctxt.tcx, save_ctxt, dumper, span: span_utils }
- }
-
- pub fn analysis(&self) -> &rls_data::Analysis {
- self.dumper.analysis()
- }
-
- fn nest_typeck_results<F>(&mut self, item_def_id: LocalDefId, f: F)
- where
- F: FnOnce(&mut Self),
- {
- let typeck_results = if self.tcx.has_typeck_results(item_def_id) {
- Some(self.tcx.typeck(item_def_id))
- } else {
- None
- };
-
- let old_maybe_typeck_results = self.save_ctxt.maybe_typeck_results;
- self.save_ctxt.maybe_typeck_results = typeck_results;
- f(self);
- self.save_ctxt.maybe_typeck_results = old_maybe_typeck_results;
- }
-
- fn span_from_span(&self, span: Span) -> SpanData {
- self.save_ctxt.span_from_span(span)
- }
-
- fn lookup_def_id(&self, ref_id: hir::HirId) -> Option<DefId> {
- self.save_ctxt.lookup_def_id(ref_id)
- }
-
- pub fn dump_crate_info(&mut self, name: Symbol) {
- let crate_root = self.tcx.sess.local_crate_source_file().map(|source_file| {
- match source_file.file_name() {
- Some(_) => source_file.parent().unwrap().display(),
- None => source_file.display(),
- }
- .to_string()
- });
-
- let data = CratePreludeData {
- crate_id: GlobalCrateId {
- name: name.to_string(),
- disambiguator: (self.tcx.sess.local_stable_crate_id().to_u64(), 0),
- },
- crate_root: crate_root.unwrap_or_else(|| "<no source>".to_owned()),
- external_crates: self.save_ctxt.get_external_crates(),
- span: self.span_from_span(self.tcx.def_span(CRATE_DEF_ID)),
- };
-
- self.dumper.crate_prelude(data);
- }
-
- pub fn dump_compilation_options(&mut self, input: &Input, crate_name: Symbol) {
- // Apply possible `remap-path-prefix` remapping to the input source file
- // (and don't include remapping args anymore)
- let (program, arguments) = {
- let remap_arg_indices = {
- let mut indices = FxHashSet::default();
- // Args are guaranteed to be valid UTF-8 (checked early)
- for (i, e) in env::args().enumerate() {
- if e.starts_with("--remap-path-prefix=") {
- indices.insert(i);
- } else if e == "--remap-path-prefix" {
- indices.insert(i);
- indices.insert(i + 1);
- }
- }
- indices
- };
-
- let mut args = env::args()
- .enumerate()
- .filter(|(i, _)| !remap_arg_indices.contains(i))
- .map(|(_, arg)| match input {
- Input::File(ref path) if path == Path::new(&arg) => self
- .tcx
- .sess
- .local_crate_source_file()
- .as_ref()
- .unwrap()
- .to_string_lossy()
- .into(),
- _ => arg,
- });
-
- (args.next().unwrap(), args.collect())
- };
-
- let data = CompilationOptions {
- directory: self.tcx.sess.opts.working_dir.remapped_path_if_available().into(),
- program,
- arguments,
- output: self.save_ctxt.compilation_output(crate_name),
- };
-
- self.dumper.compilation_opts(data);
- }
-
- fn write_segments(&mut self, segments: impl IntoIterator<Item = &'tcx hir::PathSegment<'tcx>>) {
- for seg in segments {
- if let Some(data) = self.save_ctxt.get_path_segment_data(seg) {
- self.dumper.dump_ref(data);
- }
- }
- }
-
- fn write_sub_paths<R>(&mut self, path: &'tcx hir::Path<'tcx, R>) {
- self.write_segments(path.segments)
- }
-
- // As write_sub_paths, but does not process the last ident in the path (assuming it
- // will be processed elsewhere). See note on write_sub_paths about global.
- fn write_sub_paths_truncated<R>(&mut self, path: &'tcx hir::Path<'tcx, R>) {
- if let [segments @ .., _] = path.segments {
- self.write_segments(segments)
- }
- }
-
- fn process_formals(&mut self, formals: &'tcx [hir::Param<'tcx>], qualname: &str) {
- for arg in formals {
- self.visit_pat(&arg.pat);
- let mut collector = PathCollector::new(self.tcx);
- collector.visit_pat(&arg.pat);
-
- for (hir_id, ident, ..) in collector.collected_idents {
- let typ = match self.save_ctxt.typeck_results().node_type_opt(hir_id) {
- Some(s) => s.to_string(),
- None => continue,
- };
- if !self.span.filter_generated(ident.span) {
- let id = id_from_hir_id(hir_id, &self.save_ctxt);
- let span = self.span_from_span(ident.span);
-
- self.dumper.dump_def(
- &Access { public: false, reachable: false },
- Def {
- kind: DefKind::Local,
- id,
- span,
- name: ident.to_string(),
- qualname: format!("{}::{}", qualname, ident),
- value: typ,
- parent: None,
- children: vec![],
- decl_id: None,
- docs: String::new(),
- sig: None,
- attributes: vec![],
- },
- );
- }
- }
- }
- }
-
- fn process_method(
- &mut self,
- sig: &'tcx hir::FnSig<'tcx>,
- body: Option<hir::BodyId>,
- def_id: LocalDefId,
- ident: Ident,
- generics: &'tcx hir::Generics<'tcx>,
- span: Span,
- ) {
- debug!("process_method: {:?}:{}", def_id, ident);
-
- let map = self.tcx.hir();
- let hir_id = map.local_def_id_to_hir_id(def_id);
- self.nest_typeck_results(def_id, |v| {
- if let Some(mut method_data) = v.save_ctxt.get_method_data(hir_id, ident, span) {
- if let Some(body) = body {
- v.process_formals(map.body(body).params, &method_data.qualname);
- }
- v.process_generic_params(&generics, &method_data.qualname, hir_id);
-
- method_data.value =
- fn_to_string(sig.decl, sig.header, Some(ident.name), generics, &[], None);
- method_data.sig = sig::method_signature(hir_id, ident, generics, sig, &v.save_ctxt);
-
- v.dumper.dump_def(&access_from!(v.save_ctxt, def_id), method_data);
- }
-
- // walk arg and return types
- for arg in sig.decl.inputs {
- v.visit_ty(arg);
- }
-
- if let hir::FnRetTy::Return(ref ret_ty) = sig.decl.output {
- v.visit_ty(ret_ty)
- }
-
- // walk the fn body
- if let Some(body) = body {
- v.visit_expr(&map.body(body).value);
- }
- });
- }
-
- fn process_struct_field_def(
- &mut self,
- field: &'tcx hir::FieldDef<'tcx>,
- parent_id: hir::HirId,
- ) {
- let field_data = self.save_ctxt.get_field_data(field, parent_id);
- if let Some(field_data) = field_data {
- self.dumper.dump_def(
- &access_from!(self.save_ctxt, self.tcx.hir().local_def_id(field.hir_id)),
- field_data,
- );
- }
- }
-
- // Dump generic params bindings, then visit_generics
- fn process_generic_params(
- &mut self,
- generics: &'tcx hir::Generics<'tcx>,
- prefix: &str,
- id: hir::HirId,
- ) {
- for param in generics.params {
- match param.kind {
- hir::GenericParamKind::Lifetime { .. } => {}
- hir::GenericParamKind::Type { .. } => {
- let param_ss = param.name.ident().span;
- let name = escape(self.span.snippet(param_ss));
- // Append $id to name to make sure each one is unique.
- let qualname = format!("{}::{}${}", prefix, name, id);
- if !self.span.filter_generated(param_ss) {
- let id = id_from_hir_id(param.hir_id, &self.save_ctxt);
- let span = self.span_from_span(param_ss);
-
- self.dumper.dump_def(
- &Access { public: false, reachable: false },
- Def {
- kind: DefKind::Type,
- id,
- span,
- name,
- qualname,
- value: String::new(),
- parent: None,
- children: vec![],
- decl_id: None,
- docs: String::new(),
- sig: None,
- attributes: vec![],
- },
- );
- }
- }
- hir::GenericParamKind::Const { .. } => {}
- }
- }
-
- self.visit_generics(generics)
- }
-
- fn process_fn(
- &mut self,
- item: &'tcx hir::Item<'tcx>,
- decl: &'tcx hir::FnDecl<'tcx>,
- _header: &'tcx hir::FnHeader,
- ty_params: &'tcx hir::Generics<'tcx>,
- body: hir::BodyId,
- ) {
- let map = self.tcx.hir();
- self.nest_typeck_results(item.owner_id.def_id, |v| {
- let body = map.body(body);
- if let Some(fn_data) = v.save_ctxt.get_item_data(item) {
- down_cast_data!(fn_data, DefData, item.span);
- v.process_formals(body.params, &fn_data.qualname);
- v.process_generic_params(ty_params, &fn_data.qualname, item.hir_id());
-
- v.dumper.dump_def(&access_from!(v.save_ctxt, item.owner_id.def_id), fn_data);
- }
-
- for arg in decl.inputs {
- v.visit_ty(arg)
- }
-
- if let hir::FnRetTy::Return(ref ret_ty) = decl.output {
- v.visit_ty(ret_ty)
- }
-
- v.visit_expr(&body.value);
- });
- }
-
- fn process_static_or_const_item(
- &mut self,
- item: &'tcx hir::Item<'tcx>,
- typ: &'tcx hir::Ty<'tcx>,
- expr: &'tcx hir::Expr<'tcx>,
- ) {
- self.nest_typeck_results(item.owner_id.def_id, |v| {
- if let Some(var_data) = v.save_ctxt.get_item_data(item) {
- down_cast_data!(var_data, DefData, item.span);
- v.dumper.dump_def(&access_from!(v.save_ctxt, item.owner_id.def_id), var_data);
- }
- v.visit_ty(&typ);
- v.visit_expr(expr);
- });
- }
-
- fn process_assoc_const(
- &mut self,
- def_id: LocalDefId,
- ident: Ident,
- typ: &'tcx hir::Ty<'tcx>,
- expr: Option<&'tcx hir::Expr<'tcx>>,
- parent_id: DefId,
- attrs: &'tcx [ast::Attribute],
- ) {
- let qualname = format!("::{}", self.tcx.def_path_str(def_id.to_def_id()));
-
- if !self.span.filter_generated(ident.span) {
- let hir_id = self.tcx.hir().local_def_id_to_hir_id(def_id);
- let sig = sig::assoc_const_signature(hir_id, ident.name, typ, expr, &self.save_ctxt);
- let span = self.span_from_span(ident.span);
-
- self.dumper.dump_def(
- &access_from!(self.save_ctxt, def_id),
- Def {
- kind: DefKind::Const,
- id: id_from_hir_id(hir_id, &self.save_ctxt),
- span,
- name: ident.name.to_string(),
- qualname,
- value: ty_to_string(&typ),
- parent: Some(id_from_def_id(parent_id)),
- children: vec![],
- decl_id: None,
- docs: self.save_ctxt.docs_for_attrs(attrs),
- sig,
- attributes: lower_attributes(attrs.to_owned(), &self.save_ctxt),
- },
- );
- }
-
- // walk type and init value
- self.nest_typeck_results(def_id, |v| {
- v.visit_ty(typ);
- if let Some(expr) = expr {
- v.visit_expr(expr);
- }
- });
- }
-
- // FIXME tuple structs should generate tuple-specific data.
- fn process_struct(
- &mut self,
- item: &'tcx hir::Item<'tcx>,
- def: &'tcx hir::VariantData<'tcx>,
- ty_params: &'tcx hir::Generics<'tcx>,
- ) {
- debug!("process_struct {:?} {:?}", item, item.span);
- let name = item.ident.to_string();
- let qualname = format!("::{}", self.tcx.def_path_str(item.owner_id.to_def_id()));
-
- let kind = match item.kind {
- hir::ItemKind::Struct(_, _) => DefKind::Struct,
- hir::ItemKind::Union(_, _) => DefKind::Union,
- _ => unreachable!(),
- };
-
- let (value, fields) = match item.kind {
- hir::ItemKind::Struct(hir::VariantData::Struct(ref fields, ..), ..)
- | hir::ItemKind::Union(hir::VariantData::Struct(ref fields, ..), ..) => {
- let include_priv_fields = !self.save_ctxt.config.pub_only;
- let fields_str = fields
- .iter()
- .filter_map(|f| {
- if include_priv_fields {
- return Some(f.ident.to_string());
- }
- let def_id = self.save_ctxt.tcx.hir().local_def_id(f.hir_id);
- if self.save_ctxt.tcx.visibility(def_id).is_public() {
- Some(f.ident.to_string())
- } else {
- None
- }
- })
- .collect::<Vec<_>>()
- .join(", ");
- let value = format!("{} {{ {} }}", name, fields_str);
- (value, fields.iter().map(|f| id_from_hir_id(f.hir_id, &self.save_ctxt)).collect())
- }
- _ => (String::new(), vec![]),
- };
-
- if !self.span.filter_generated(item.ident.span) {
- let span = self.span_from_span(item.ident.span);
- let attrs = self.tcx.hir().attrs(item.hir_id());
- self.dumper.dump_def(
- &access_from!(self.save_ctxt, item.owner_id.def_id),
- Def {
- kind,
- id: id_from_def_id(item.owner_id.to_def_id()),
- span,
- name,
- qualname: qualname.clone(),
- value,
- parent: None,
- children: fields,
- decl_id: None,
- docs: self.save_ctxt.docs_for_attrs(attrs),
- sig: sig::item_signature(item, &self.save_ctxt),
- attributes: lower_attributes(attrs.to_vec(), &self.save_ctxt),
- },
- );
- }
-
- self.nest_typeck_results(item.owner_id.def_id, |v| {
- for field in def.fields() {
- v.process_struct_field_def(field, item.hir_id());
- v.visit_ty(&field.ty);
- }
-
- v.process_generic_params(ty_params, &qualname, item.hir_id());
- });
- }
-
- fn process_enum(
- &mut self,
- item: &'tcx hir::Item<'tcx>,
- enum_definition: &'tcx hir::EnumDef<'tcx>,
- ty_params: &'tcx hir::Generics<'tcx>,
- ) {
- let enum_data = self.save_ctxt.get_item_data(item);
- let Some(enum_data) = enum_data else {
- return;
- };
- down_cast_data!(enum_data, DefData, item.span);
-
- let access = access_from!(self.save_ctxt, item.owner_id.def_id);
-
- for variant in enum_definition.variants {
- let name = variant.ident.name.to_string();
- let qualname = format!("{}::{}", enum_data.qualname, name);
- let name_span = variant.ident.span;
-
- match variant.data {
- hir::VariantData::Struct(ref fields, ..) => {
- let fields_str =
- fields.iter().map(|f| f.ident.to_string()).collect::<Vec<_>>().join(", ");
- let value = format!("{}::{} {{ {} }}", enum_data.name, name, fields_str);
- if !self.span.filter_generated(name_span) {
- let span = self.span_from_span(name_span);
- let id = id_from_hir_id(variant.hir_id, &self.save_ctxt);
- let parent = Some(id_from_def_id(item.owner_id.to_def_id()));
- let attrs = self.tcx.hir().attrs(variant.hir_id);
-
- self.dumper.dump_def(
- &access,
- Def {
- kind: DefKind::StructVariant,
- id,
- span,
- name,
- qualname,
- value,
- parent,
- children: vec![],
- decl_id: None,
- docs: self.save_ctxt.docs_for_attrs(attrs),
- sig: sig::variant_signature(variant, &self.save_ctxt),
- attributes: lower_attributes(attrs.to_vec(), &self.save_ctxt),
- },
- );
- }
- }
- ref v => {
- let mut value = format!("{}::{}", enum_data.name, name);
- if let hir::VariantData::Tuple(fields, _, _) = v {
- value.push('(');
- value.push_str(
- &fields
- .iter()
- .map(|f| ty_to_string(&f.ty))
- .collect::<Vec<_>>()
- .join(", "),
- );
- value.push(')');
- }
- if !self.span.filter_generated(name_span) {
- let span = self.span_from_span(name_span);
- let id = id_from_hir_id(variant.hir_id, &self.save_ctxt);
- let parent = Some(id_from_def_id(item.owner_id.to_def_id()));
- let attrs = self.tcx.hir().attrs(variant.hir_id);
-
- self.dumper.dump_def(
- &access,
- Def {
- kind: DefKind::TupleVariant,
- id,
- span,
- name,
- qualname,
- value,
- parent,
- children: vec![],
- decl_id: None,
- docs: self.save_ctxt.docs_for_attrs(attrs),
- sig: sig::variant_signature(variant, &self.save_ctxt),
- attributes: lower_attributes(attrs.to_vec(), &self.save_ctxt),
- },
- );
- }
- }
- }
-
- for field in variant.data.fields() {
- self.process_struct_field_def(field, variant.hir_id);
- self.visit_ty(field.ty);
- }
- }
- self.process_generic_params(ty_params, &enum_data.qualname, item.hir_id());
- self.dumper.dump_def(&access, enum_data);
- }
-
- fn process_impl(&mut self, item: &'tcx hir::Item<'tcx>, impl_: &'tcx hir::Impl<'tcx>) {
- if let Some(impl_data) = self.save_ctxt.get_item_data(item) {
- if !self.span.filter_generated(item.span) {
- if let super::Data::RelationData(rel, imp) = impl_data {
- self.dumper.dump_relation(rel);
- self.dumper.dump_impl(imp);
- } else {
- span_bug!(item.span, "unexpected data kind: {:?}", impl_data);
- }
- }
- }
-
- let map = self.tcx.hir();
- self.nest_typeck_results(item.owner_id.def_id, |v| {
- v.visit_ty(&impl_.self_ty);
- if let Some(trait_ref) = &impl_.of_trait {
- v.process_path(trait_ref.hir_ref_id, &hir::QPath::Resolved(None, &trait_ref.path));
- }
- v.process_generic_params(&impl_.generics, "", item.hir_id());
- for impl_item in impl_.items {
- v.process_impl_item(map.impl_item(impl_item.id), item.owner_id.to_def_id());
- }
- });
- }
-
- fn process_trait(
- &mut self,
- item: &'tcx hir::Item<'tcx>,
- generics: &'tcx hir::Generics<'tcx>,
- trait_refs: hir::GenericBounds<'tcx>,
- methods: &'tcx [hir::TraitItemRef],
- ) {
- let name = item.ident.to_string();
- let qualname = format!("::{}", self.tcx.def_path_str(item.owner_id.to_def_id()));
- let mut val = name.clone();
- if !generics.params.is_empty() {
- val.push_str(&generic_params_to_string(generics.params));
- }
- if !trait_refs.is_empty() {
- val.push_str(": ");
- val.push_str(&bounds_to_string(trait_refs));
- }
- if !self.span.filter_generated(item.ident.span) {
- let id = id_from_def_id(item.owner_id.to_def_id());
- let span = self.span_from_span(item.ident.span);
- let children =
- methods.iter().map(|i| id_from_def_id(i.id.owner_id.to_def_id())).collect();
- let attrs = self.tcx.hir().attrs(item.hir_id());
- self.dumper.dump_def(
- &access_from!(self.save_ctxt, item.owner_id.def_id),
- Def {
- kind: DefKind::Trait,
- id,
- span,
- name,
- qualname: qualname.clone(),
- value: val,
- parent: None,
- children,
- decl_id: None,
- docs: self.save_ctxt.docs_for_attrs(attrs),
- sig: sig::item_signature(item, &self.save_ctxt),
- attributes: lower_attributes(attrs.to_vec(), &self.save_ctxt),
- },
- );
- }
-
- // supertraits
- for super_bound in trait_refs.iter() {
- let (def_id, sub_span) = match *super_bound {
- hir::GenericBound::Trait(ref trait_ref, _) => (
- self.lookup_def_id(trait_ref.trait_ref.hir_ref_id),
- trait_ref.trait_ref.path.segments.last().unwrap().ident.span,
- ),
- hir::GenericBound::LangItemTrait(lang_item, span, _, _) => {
- (Some(self.tcx.require_lang_item(lang_item, Some(span))), span)
- }
- hir::GenericBound::Outlives(..) => continue,
- };
-
- if let Some(id) = def_id {
- if !self.span.filter_generated(sub_span) {
- let span = self.span_from_span(sub_span);
- self.dumper.dump_ref(Ref {
- kind: RefKind::Type,
- span: span.clone(),
- ref_id: id_from_def_id(id),
- });
-
- self.dumper.dump_relation(Relation {
- kind: RelationKind::SuperTrait,
- span,
- from: id_from_def_id(id),
- to: id_from_def_id(item.owner_id.to_def_id()),
- });
- }
- }
- }
-
- // walk generics and methods
- self.process_generic_params(generics, &qualname, item.hir_id());
- for method in methods {
- let map = self.tcx.hir();
- self.process_trait_item(map.trait_item(method.id), item.owner_id.to_def_id())
- }
- }
-
- // `item` is the module in question, represented as an( item.
- fn process_mod(&mut self, item: &'tcx hir::Item<'tcx>) {
- if let Some(mod_data) = self.save_ctxt.get_item_data(item) {
- down_cast_data!(mod_data, DefData, item.span);
- self.dumper.dump_def(&access_from!(self.save_ctxt, item.owner_id.def_id), mod_data);
- }
- }
-
- fn dump_path_ref(&mut self, id: hir::HirId, path: &hir::QPath<'tcx>) {
- let path_data = self.save_ctxt.get_path_data(id, path);
- if let Some(path_data) = path_data {
- self.dumper.dump_ref(path_data);
- }
- }
-
- fn dump_path_segment_ref(&mut self, id: hir::HirId, segment: &hir::PathSegment<'tcx>) {
- let segment_data = self.save_ctxt.get_path_segment_data_with_id(segment, id);
- if let Some(segment_data) = segment_data {
- self.dumper.dump_ref(segment_data);
- }
- }
-
- fn process_path(&mut self, id: hir::HirId, path: &hir::QPath<'tcx>) {
- if self.span.filter_generated(path.span()) {
- return;
- }
- self.dump_path_ref(id, path);
-
- // Type arguments
- let segments = match path {
- hir::QPath::Resolved(ty, path) => {
- if let Some(ty) = ty {
- self.visit_ty(ty);
- }
- path.segments
- }
- hir::QPath::TypeRelative(ty, segment) => {
- self.visit_ty(ty);
- std::slice::from_ref(*segment)
- }
- hir::QPath::LangItem(..) => return,
- };
- for seg in segments {
- if let Some(ref generic_args) = seg.args {
- for arg in generic_args.args {
- if let hir::GenericArg::Type(ref ty) = arg {
- self.visit_ty(ty);
- }
- }
- }
- }
-
- if let hir::QPath::Resolved(_, path) = path {
- self.write_sub_paths_truncated(path);
- }
- }
-
- fn process_struct_lit(
- &mut self,
- ex: &'tcx hir::Expr<'tcx>,
- path: &'tcx hir::QPath<'tcx>,
- fields: &'tcx [hir::ExprField<'tcx>],
- variant: &'tcx ty::VariantDef,
- rest: Option<&'tcx hir::Expr<'tcx>>,
- ) {
- if let Some(_ex_res_data) = self.save_ctxt.get_expr_data(ex) {
- if let hir::QPath::Resolved(_, path) = path {
- self.write_sub_paths_truncated(path);
- }
- // For MyEnum::MyVariant, get_expr_data gives us MyEnum, not MyVariant.
- // For recording the span's ref id, we want MyVariant.
- if !generated_code(ex.span) {
- let sub_span = path.last_segment_span();
- let span = self.save_ctxt.span_from_span(sub_span);
- let reff =
- Ref { kind: RefKind::Type, span, ref_id: id_from_def_id(variant.def_id) };
- self.dumper.dump_ref(reff);
- }
-
- for field in fields {
- if let Some(field_data) = self.save_ctxt.get_field_ref_data(field, variant) {
- self.dumper.dump_ref(field_data);
- }
-
- self.visit_expr(&field.expr)
- }
- }
-
- if let Some(base) = rest {
- self.visit_expr(&base);
- }
- }
-
- fn process_method_call(
- &mut self,
- ex: &'tcx hir::Expr<'tcx>,
- seg: &'tcx hir::PathSegment<'tcx>,
- receiver: &'tcx hir::Expr<'tcx>,
- args: &'tcx [hir::Expr<'tcx>],
- ) {
- debug!("process_method_call {:?} {:?}", ex, ex.span);
- if let Some(mcd) = self.save_ctxt.get_expr_data(ex) {
- down_cast_data!(mcd, RefData, ex.span);
- if !generated_code(ex.span) {
- self.dumper.dump_ref(mcd);
- }
- }
-
- // Explicit types in the turbo-fish.
- if let Some(generic_args) = seg.args {
- for arg in generic_args.args {
- if let hir::GenericArg::Type(ty) = arg {
- self.visit_ty(&ty)
- };
- }
- }
-
- // walk receiver and args
- self.visit_expr(receiver);
- walk_list!(self, visit_expr, args);
- }
-
- fn process_pat(&mut self, p: &'tcx hir::Pat<'tcx>) {
- match p.kind {
- hir::PatKind::Struct(ref _path, fields, _) => {
- // FIXME do something with _path?
- let adt = match self.save_ctxt.typeck_results().node_type_opt(p.hir_id) {
- Some(ty) if ty.ty_adt_def().is_some() => ty.ty_adt_def().unwrap(),
- _ => {
- intravisit::walk_pat(self, p);
- return;
- }
- };
- let variant = adt.variant_of_res(self.save_ctxt.get_path_res(p.hir_id));
-
- for field in fields {
- if let Some(index) = self.tcx.find_field_index(field.ident, variant) {
- if !self.span.filter_generated(field.ident.span) {
- let span = self.span_from_span(field.ident.span);
- self.dumper.dump_ref(Ref {
- kind: RefKind::Variable,
- span,
- ref_id: id_from_def_id(variant.fields[index].did),
- });
- }
- }
- self.visit_pat(&field.pat);
- }
- }
- _ => intravisit::walk_pat(self, p),
- }
- }
-
- fn process_var_decl(&mut self, pat: &'tcx hir::Pat<'tcx>) {
- // The pattern could declare multiple new vars,
- // we must walk the pattern and collect them all.
- let mut collector = PathCollector::new(self.tcx);
- collector.visit_pat(&pat);
- self.visit_pat(&pat);
-
- // Process collected paths.
- for (id, ident, _) in collector.collected_idents {
- let res = self.save_ctxt.get_path_res(id);
- match res {
- Res::Local(hir_id) => {
- let typ = self
- .save_ctxt
- .typeck_results()
- .node_type_opt(hir_id)
- .map(|t| t.to_string())
- .unwrap_or_default();
-
- // Rust uses the id of the pattern for var lookups, so we'll use it too.
- if !self.span.filter_generated(ident.span) {
- let qualname = format!("{}${}", ident, hir_id);
- let id = id_from_hir_id(hir_id, &self.save_ctxt);
- let span = self.span_from_span(ident.span);
-
- self.dumper.dump_def(
- &Access { public: false, reachable: false },
- Def {
- kind: DefKind::Local,
- id,
- span,
- name: ident.to_string(),
- qualname,
- value: typ,
- parent: None,
- children: vec![],
- decl_id: None,
- docs: String::new(),
- sig: None,
- attributes: vec![],
- },
- );
- }
- }
- Res::Def(
- HirDefKind::Ctor(..)
- | HirDefKind::Const
- | HirDefKind::AssocConst
- | HirDefKind::Struct
- | HirDefKind::Variant
- | HirDefKind::TyAlias
- | HirDefKind::AssocTy,
- _,
- )
- | Res::SelfTyParam { .. }
- | Res::SelfTyAlias { .. } => {
- self.dump_path_segment_ref(
- id,
- &hir::PathSegment::new(ident, hir::HirId::INVALID, Res::Err),
- );
- }
- def => {
- error!("unexpected definition kind when processing collected idents: {:?}", def)
- }
- }
- }
-
- for (id, ref path) in collector.collected_paths {
- self.process_path(id, path);
- }
- }
-
- /// Extracts macro use and definition information from the AST node defined
- /// by the given NodeId, using the expansion information from the node's
- /// span.
- ///
- /// If the span is not macro-generated, do nothing, else use callee and
- /// callsite spans to record macro definition and use data, using the
- /// mac_uses and mac_defs sets to prevent multiples.
- fn process_macro_use(&mut self, _span: Span) {
- // FIXME if we're not dumping the defs (see below), there is no point
- // dumping refs either.
- // let source_span = span.source_callsite();
- // if !self.macro_calls.insert(source_span) {
- // return;
- // }
-
- // let data = match self.save_ctxt.get_macro_use_data(span) {
- // None => return,
- // Some(data) => data,
- // };
-
- // self.dumper.macro_use(data);
-
- // FIXME write the macro def
- // let mut hasher = DefaultHasher::new();
- // data.callee_span.hash(&mut hasher);
- // let hash = hasher.finish();
- // let qualname = format!("{}::{}", data.name, hash);
- // Don't write macro definition for imported macros
- // if !self.mac_defs.contains(&data.callee_span)
- // && !data.imported {
- // self.mac_defs.insert(data.callee_span);
- // if let Some(sub_span) = self.span.span_for_macro_def_name(data.callee_span) {
- // self.dumper.macro_data(MacroData {
- // span: sub_span,
- // name: data.name.clone(),
- // qualname: qualname.clone(),
- // // FIXME where do macro docs come from?
- // docs: String::new(),
- // }.lower(self.tcx));
- // }
- // }
- }
-
- fn process_trait_item(&mut self, trait_item: &'tcx hir::TraitItem<'tcx>, trait_id: DefId) {
- self.process_macro_use(trait_item.span);
- match trait_item.kind {
- hir::TraitItemKind::Const(ref ty, body) => {
- let body = body.map(|b| self.tcx.hir().body(b).value);
- let attrs = self.tcx.hir().attrs(trait_item.hir_id());
- self.process_assoc_const(
- trait_item.owner_id.def_id,
- trait_item.ident,
- &ty,
- body,
- trait_id,
- attrs,
- );
- }
- hir::TraitItemKind::Fn(ref sig, ref trait_fn) => {
- let body =
- if let hir::TraitFn::Provided(body) = trait_fn { Some(*body) } else { None };
- self.process_method(
- sig,
- body,
- trait_item.owner_id.def_id,
- trait_item.ident,
- &trait_item.generics,
- trait_item.span,
- );
- }
- hir::TraitItemKind::Type(ref bounds, ref default_ty) => {
- // FIXME do something with _bounds (for type refs)
- let name = trait_item.ident.name.to_string();
- let qualname =
- format!("::{}", self.tcx.def_path_str(trait_item.owner_id.to_def_id()));
-
- if !self.span.filter_generated(trait_item.ident.span) {
- let span = self.span_from_span(trait_item.ident.span);
- let id = id_from_def_id(trait_item.owner_id.to_def_id());
- let attrs = self.tcx.hir().attrs(trait_item.hir_id());
-
- self.dumper.dump_def(
- &Access { public: true, reachable: true },
- Def {
- kind: DefKind::Type,
- id,
- span,
- name,
- qualname,
- value: self.span.snippet(trait_item.span),
- parent: Some(id_from_def_id(trait_id)),
- children: vec![],
- decl_id: None,
- docs: self.save_ctxt.docs_for_attrs(attrs),
- sig: sig::assoc_type_signature(
- trait_item.hir_id(),
- trait_item.ident,
- Some(bounds),
- default_ty.as_deref(),
- &self.save_ctxt,
- ),
- attributes: lower_attributes(attrs.to_vec(), &self.save_ctxt),
- },
- );
- }
-
- if let Some(default_ty) = default_ty {
- self.visit_ty(default_ty)
- }
- }
- }
- }
-
- fn process_impl_item(&mut self, impl_item: &'tcx hir::ImplItem<'tcx>, impl_id: DefId) {
- self.process_macro_use(impl_item.span);
- match impl_item.kind {
- hir::ImplItemKind::Const(ref ty, body) => {
- let body = self.tcx.hir().body(body);
- let attrs = self.tcx.hir().attrs(impl_item.hir_id());
- self.process_assoc_const(
- impl_item.owner_id.def_id,
- impl_item.ident,
- &ty,
- Some(&body.value),
- impl_id,
- attrs,
- );
- }
- hir::ImplItemKind::Fn(ref sig, body) => {
- self.process_method(
- sig,
- Some(body),
- impl_item.owner_id.def_id,
- impl_item.ident,
- &impl_item.generics,
- impl_item.span,
- );
- }
- hir::ImplItemKind::Type(ref ty) => {
- // FIXME: uses of the assoc type should ideally point to this
- // 'def' and the name here should be a ref to the def in the
- // trait.
- self.visit_ty(ty)
- }
- }
- }
-
- 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 = self.tcx.hir().root_module();
- let filename = sm.span_to_filename(krate_mod.spans.inner_span);
- let data_id = id_from_hir_id(id, &self.save_ctxt);
- let children =
- krate_mod.item_ids.iter().map(|i| id_from_def_id(i.owner_id.to_def_id())).collect();
- let span = self.span_from_span(krate_mod.spans.inner_span);
- let attrs = self.tcx.hir().attrs(id);
-
- self.dumper.dump_def(
- &Access { public: true, reachable: true },
- Def {
- kind: DefKind::Mod,
- id: data_id,
- name: String::new(),
- qualname,
- span,
- value: filename.prefer_remapped().to_string(),
- children,
- parent: None,
- decl_id: None,
- docs: self.save_ctxt.docs_for_attrs(attrs),
- sig: None,
- attributes: lower_attributes(attrs.to_owned(), &self.save_ctxt),
- },
- );
- self.tcx.hir().walk_toplevel_module(self);
- }
-
- fn process_bounds(&mut self, bounds: hir::GenericBounds<'tcx>) {
- for bound in bounds {
- if let hir::GenericBound::Trait(ref trait_ref, _) = *bound {
- self.process_path(
- trait_ref.trait_ref.hir_ref_id,
- &hir::QPath::Resolved(None, &trait_ref.trait_ref.path),
- )
- }
- }
- }
-}
-
-impl<'tcx> Visitor<'tcx> for DumpVisitor<'tcx> {
- type NestedFilter = nested_filter::All;
-
- fn nested_visit_map(&mut self) -> Self::Map {
- self.tcx.hir()
- }
-
- fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {
- self.process_macro_use(item.span);
- match item.kind {
- hir::ItemKind::Use(path, hir::UseKind::Single) => {
- let sub_span = path.segments.last().unwrap().ident.span;
- if !self.span.filter_generated(sub_span) {
- let access = access_from!(self.save_ctxt, item.owner_id.def_id);
- let ref_id = self.lookup_def_id(item.hir_id()).map(id_from_def_id);
- let span = self.span_from_span(sub_span);
- let parent = self.save_ctxt.tcx.local_parent(item.owner_id.def_id);
- self.dumper.import(
- &access,
- Import {
- kind: ImportKind::Use,
- ref_id,
- span,
- alias_span: None,
- name: item.ident.to_string(),
- value: String::new(),
- parent: Some(id_from_def_id(parent.to_def_id())),
- },
- );
- self.write_sub_paths_truncated(&path);
- }
- }
- hir::ItemKind::Use(path, hir::UseKind::Glob) => {
- // Make a comma-separated list of names of imported modules.
- let names = self.tcx.names_imported_by_glob_use(item.owner_id.def_id);
- let names: Vec<_> = names.iter().map(|n| n.to_string()).collect();
-
- // Otherwise it's a span with wrong macro expansion info, which
- // we don't want to track anyway, since it's probably macro-internal `use`
- if let Some(sub_span) = self.span.sub_span_of_star(item.span) {
- if !self.span.filter_generated(item.span) {
- let access = access_from!(self.save_ctxt, item.owner_id.def_id);
- let span = self.span_from_span(sub_span);
- let parent = self.save_ctxt.tcx.local_parent(item.owner_id.def_id);
- self.dumper.import(
- &access,
- Import {
- kind: ImportKind::GlobUse,
- ref_id: None,
- span,
- alias_span: None,
- name: "*".to_owned(),
- value: names.join(", "),
- parent: Some(id_from_def_id(parent.to_def_id())),
- },
- );
- self.write_sub_paths(&path);
- }
- }
- }
- hir::ItemKind::ExternCrate(_) => {
- let name_span = item.ident.span;
- if !self.span.filter_generated(name_span) {
- let span = self.span_from_span(name_span);
- let parent = self.save_ctxt.tcx.local_parent(item.owner_id.def_id);
- self.dumper.import(
- &Access { public: false, reachable: false },
- Import {
- kind: ImportKind::ExternCrate,
- ref_id: None,
- span,
- alias_span: None,
- name: item.ident.to_string(),
- value: String::new(),
- parent: Some(id_from_def_id(parent.to_def_id())),
- },
- );
- }
- }
- hir::ItemKind::Fn(ref sig, ref ty_params, body) => {
- self.process_fn(item, sig.decl, &sig.header, ty_params, body)
- }
- hir::ItemKind::Static(ref typ, _, body) => {
- let body = self.tcx.hir().body(body);
- self.process_static_or_const_item(item, typ, &body.value)
- }
- hir::ItemKind::Const(ref typ, body) => {
- let body = self.tcx.hir().body(body);
- self.process_static_or_const_item(item, typ, &body.value)
- }
- hir::ItemKind::Struct(ref def, ref ty_params)
- | hir::ItemKind::Union(ref def, ref ty_params) => {
- self.process_struct(item, def, ty_params)
- }
- hir::ItemKind::Enum(ref def, ref ty_params) => self.process_enum(item, def, ty_params),
- hir::ItemKind::Impl(ref impl_) => self.process_impl(item, impl_),
- hir::ItemKind::Trait(_, _, ref generics, ref trait_refs, methods) => {
- self.process_trait(item, generics, trait_refs, methods)
- }
- hir::ItemKind::Mod(ref m) => {
- self.process_mod(item);
- intravisit::walk_mod(self, m, item.hir_id());
- }
- hir::ItemKind::TyAlias(ty, ref generics) => {
- let qualname = format!("::{}", self.tcx.def_path_str(item.owner_id.to_def_id()));
- let value = ty_to_string(&ty);
- if !self.span.filter_generated(item.ident.span) {
- let span = self.span_from_span(item.ident.span);
- let id = id_from_def_id(item.owner_id.to_def_id());
- let attrs = self.tcx.hir().attrs(item.hir_id());
-
- self.dumper.dump_def(
- &access_from!(self.save_ctxt, item.owner_id.def_id),
- Def {
- kind: DefKind::Type,
- id,
- span,
- name: item.ident.to_string(),
- qualname: qualname.clone(),
- value,
- parent: None,
- children: vec![],
- decl_id: None,
- docs: self.save_ctxt.docs_for_attrs(attrs),
- sig: sig::item_signature(item, &self.save_ctxt),
- attributes: lower_attributes(attrs.to_vec(), &self.save_ctxt),
- },
- );
- }
-
- self.visit_ty(ty);
- self.process_generic_params(generics, &qualname, item.hir_id());
- }
- _ => intravisit::walk_item(self, item),
- }
- }
-
- fn visit_generics(&mut self, generics: &'tcx hir::Generics<'tcx>) {
- for param in generics.params {
- match param.kind {
- hir::GenericParamKind::Lifetime { .. } => {}
- hir::GenericParamKind::Type { ref default, .. } => {
- if let Some(ref ty) = default {
- self.visit_ty(ty);
- }
- }
- hir::GenericParamKind::Const { ref ty, ref default } => {
- self.visit_ty(ty);
- if let Some(default) = default {
- self.visit_anon_const(default);
- }
- }
- }
- }
- for pred in generics.predicates {
- if let hir::WherePredicate::BoundPredicate(ref wbp) = *pred {
- self.process_bounds(wbp.bounds);
- self.visit_ty(wbp.bounded_ty);
- }
- }
- }
-
- fn visit_ty(&mut self, t: &'tcx hir::Ty<'tcx>) {
- self.process_macro_use(t.span);
- match t.kind {
- hir::TyKind::Path(ref path) => {
- if generated_code(t.span) {
- return;
- }
-
- if let Some(id) = self.lookup_def_id(t.hir_id) {
- let sub_span = path.last_segment_span();
- let span = self.span_from_span(sub_span);
- self.dumper.dump_ref(Ref {
- kind: RefKind::Type,
- span,
- ref_id: id_from_def_id(id),
- });
- }
-
- if let hir::QPath::Resolved(_, path) = path {
- self.write_sub_paths_truncated(path);
- }
- intravisit::walk_qpath(self, path, t.hir_id);
- }
- hir::TyKind::Array(ref ty, ref length) => {
- self.visit_ty(ty);
- let map = self.tcx.hir();
- match length {
- // FIXME(generic_arg_infer): We probably want to
- // output the inferred type here? :shrug:
- hir::ArrayLen::Infer(..) => {}
- hir::ArrayLen::Body(anon_const) => self
- .nest_typeck_results(self.tcx.hir().local_def_id(anon_const.hir_id), |v| {
- v.visit_expr(&map.body(anon_const.body).value)
- }),
- }
- }
- hir::TyKind::OpaqueDef(item_id, _, _) => {
- let item = self.tcx.hir().item(item_id);
- self.nest_typeck_results(item_id.owner_id.def_id, |v| v.visit_item(item));
- }
- _ => intravisit::walk_ty(self, t),
- }
- }
-
- fn visit_expr(&mut self, ex: &'tcx hir::Expr<'tcx>) {
- debug!("visit_expr {:?}", ex.kind);
- self.process_macro_use(ex.span);
- match ex.kind {
- hir::ExprKind::Struct(ref path, ref fields, ref rest) => {
- let hir_expr = self.save_ctxt.tcx.hir().expect_expr(ex.hir_id);
- let adt = match self.save_ctxt.typeck_results().expr_ty_opt(&hir_expr) {
- Some(ty) if ty.ty_adt_def().is_some() => ty.ty_adt_def().unwrap(),
- _ => {
- intravisit::walk_expr(self, ex);
- return;
- }
- };
- let res = self.save_ctxt.get_path_res(hir_expr.hir_id);
- self.process_struct_lit(ex, path, fields, adt.variant_of_res(res), *rest)
- }
- hir::ExprKind::MethodCall(ref seg, receiver, args, _) => {
- self.process_method_call(ex, seg, receiver, args)
- }
- hir::ExprKind::Field(ref sub_ex, _) => {
- self.visit_expr(&sub_ex);
-
- if let Some(field_data) = self.save_ctxt.get_expr_data(ex) {
- down_cast_data!(field_data, RefData, ex.span);
- if !generated_code(ex.span) {
- self.dumper.dump_ref(field_data);
- }
- }
- }
- hir::ExprKind::Closure(&hir::Closure { ref fn_decl, body, .. }) => {
- let id = format!("${}", ex.hir_id);
-
- // walk arg and return types
- for ty in fn_decl.inputs {
- self.visit_ty(ty);
- }
-
- if let hir::FnRetTy::Return(ref ret_ty) = fn_decl.output {
- self.visit_ty(ret_ty);
- }
-
- // walk the body
- let map = self.tcx.hir();
- self.nest_typeck_results(self.tcx.hir().local_def_id(ex.hir_id), |v| {
- let body = map.body(body);
- v.process_formals(body.params, &id);
- v.visit_expr(&body.value)
- });
- }
- hir::ExprKind::Repeat(ref expr, ref length) => {
- self.visit_expr(expr);
- let map = self.tcx.hir();
- match length {
- // FIXME(generic_arg_infer): We probably want to
- // output the inferred type here? :shrug:
- hir::ArrayLen::Infer(..) => {}
- hir::ArrayLen::Body(anon_const) => self
- .nest_typeck_results(self.tcx.hir().local_def_id(anon_const.hir_id), |v| {
- v.visit_expr(&map.body(anon_const.body).value)
- }),
- }
- }
- // In particular, we take this branch for call and path expressions,
- // where we'll index the idents involved just by continuing to walk.
- _ => intravisit::walk_expr(self, ex),
- }
- }
-
- fn visit_pat(&mut self, p: &'tcx hir::Pat<'tcx>) {
- self.process_macro_use(p.span);
- self.process_pat(p);
- }
-
- fn visit_arm(&mut self, arm: &'tcx hir::Arm<'tcx>) {
- self.process_var_decl(&arm.pat);
- if let Some(hir::Guard::If(expr)) = &arm.guard {
- self.visit_expr(expr);
- }
- self.visit_expr(&arm.body);
- }
-
- fn visit_qpath(&mut self, path: &'tcx hir::QPath<'tcx>, id: hir::HirId, _: Span) {
- self.process_path(id, path);
- }
-
- fn visit_stmt(&mut self, s: &'tcx hir::Stmt<'tcx>) {
- self.process_macro_use(s.span);
- intravisit::walk_stmt(self, s)
- }
-
- fn visit_local(&mut self, l: &'tcx hir::Local<'tcx>) {
- self.process_macro_use(l.span);
- self.process_var_decl(&l.pat);
-
- // Just walk the initializer, the else branch and type (don't want to walk the pattern again).
- walk_list!(self, visit_ty, &l.ty);
- walk_list!(self, visit_expr, &l.init);
- walk_list!(self, visit_block, l.els);
- }
-
- fn visit_foreign_item(&mut self, item: &'tcx hir::ForeignItem<'tcx>) {
- let access = access_from!(self.save_ctxt, item.owner_id.def_id);
-
- match item.kind {
- hir::ForeignItemKind::Fn(decl, _, ref generics) => {
- if let Some(fn_data) = self.save_ctxt.get_extern_item_data(item) {
- down_cast_data!(fn_data, DefData, item.span);
-
- self.process_generic_params(generics, &fn_data.qualname, item.hir_id());
- self.dumper.dump_def(&access, fn_data);
- }
-
- for ty in decl.inputs {
- self.visit_ty(ty);
- }
-
- if let hir::FnRetTy::Return(ref ret_ty) = decl.output {
- self.visit_ty(ret_ty);
- }
- }
- hir::ForeignItemKind::Static(ref ty, _) => {
- if let Some(var_data) = self.save_ctxt.get_extern_item_data(item) {
- down_cast_data!(var_data, DefData, item.span);
- self.dumper.dump_def(&access, var_data);
- }
-
- self.visit_ty(ty);
- }
- hir::ForeignItemKind::Type => {
- if let Some(var_data) = self.save_ctxt.get_extern_item_data(item) {
- down_cast_data!(var_data, DefData, item.span);
- self.dumper.dump_def(&access, var_data);
- }
- }
- }
- }
-}
diff --git a/compiler/rustc_save_analysis/src/dumper.rs b/compiler/rustc_save_analysis/src/dumper.rs
deleted file mode 100644
index 5a2628287..000000000
--- a/compiler/rustc_save_analysis/src/dumper.rs
+++ /dev/null
@@ -1,91 +0,0 @@
-use rls_data::config::Config;
-use rls_data::{
- self, Analysis, CompilationOptions, CratePreludeData, Def, DefKind, Impl, Import, MacroRef,
- Ref, RefKind, Relation,
-};
-use rls_span::{Column, Row};
-
-#[derive(Debug)]
-pub struct Access {
- pub reachable: bool,
- pub public: bool,
-}
-
-pub struct Dumper {
- result: Analysis,
- config: Config,
-}
-
-impl Dumper {
- pub fn new(config: Config) -> Dumper {
- Dumper { config: config.clone(), result: Analysis::new(config) }
- }
-
- pub fn analysis(&self) -> &Analysis {
- &self.result
- }
-}
-
-impl Dumper {
- pub fn crate_prelude(&mut self, data: CratePreludeData) {
- self.result.prelude = Some(data)
- }
-
- pub fn compilation_opts(&mut self, data: CompilationOptions) {
- self.result.compilation = Some(data);
- }
-
- pub fn _macro_use(&mut self, data: MacroRef) {
- if self.config.pub_only || self.config.reachable_only {
- return;
- }
- self.result.macro_refs.push(data);
- }
-
- pub fn import(&mut self, access: &Access, import: Import) {
- if !access.public && self.config.pub_only || !access.reachable && self.config.reachable_only
- {
- return;
- }
- self.result.imports.push(import);
- }
-
- pub fn dump_ref(&mut self, data: Ref) {
- if self.config.pub_only || self.config.reachable_only {
- return;
- }
- self.result.refs.push(data);
- }
-
- pub fn dump_def(&mut self, access: &Access, mut data: Def) {
- if !access.public && self.config.pub_only || !access.reachable && self.config.reachable_only
- {
- return;
- }
- if data.kind == DefKind::Mod && data.span.file_name.to_str().unwrap() != data.value {
- // If the module is an out-of-line definition, then we'll make the
- // definition the first character in the module's file and turn
- // the declaration into a reference to it.
- let rf = Ref { kind: RefKind::Mod, span: data.span, ref_id: data.id };
- self.result.refs.push(rf);
- data.span = rls_data::SpanData {
- file_name: data.value.clone().into(),
- byte_start: 0,
- byte_end: 0,
- line_start: Row::new_one_indexed(1),
- line_end: Row::new_one_indexed(1),
- column_start: Column::new_one_indexed(1),
- column_end: Column::new_one_indexed(1),
- }
- }
- self.result.defs.push(data);
- }
-
- pub fn dump_relation(&mut self, data: Relation) {
- self.result.relations.push(data);
- }
-
- pub fn dump_impl(&mut self, data: Impl) {
- self.result.impls.push(data);
- }
-}
diff --git a/compiler/rustc_save_analysis/src/errors.rs b/compiler/rustc_save_analysis/src/errors.rs
deleted file mode 100644
index 585aac8c1..000000000
--- a/compiler/rustc_save_analysis/src/errors.rs
+++ /dev/null
@@ -1,10 +0,0 @@
-use rustc_macros::Diagnostic;
-
-use std::path::Path;
-
-#[derive(Diagnostic)]
-#[diag(save_analysis_could_not_open)]
-pub(crate) struct CouldNotOpen<'a> {
- pub file_name: &'a Path,
- pub err: std::io::Error,
-}
diff --git a/compiler/rustc_save_analysis/src/lib.rs b/compiler/rustc_save_analysis/src/lib.rs
deleted file mode 100644
index a8d82de02..000000000
--- a/compiler/rustc_save_analysis/src/lib.rs
+++ /dev/null
@@ -1,1072 +0,0 @@
-#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
-#![feature(if_let_guard)]
-#![recursion_limit = "256"]
-#![allow(rustc::potential_query_instability)]
-#![feature(never_type)]
-#![deny(rustc::untranslatable_diagnostic)]
-#![deny(rustc::diagnostic_outside_of_impl)]
-
-#[macro_use]
-extern crate tracing;
-
-mod dump_visitor;
-mod dumper;
-#[macro_use]
-mod span_utils;
-mod errors;
-mod sig;
-
-use rustc_ast as ast;
-use rustc_ast::util::comments::beautify_doc_string;
-use rustc_ast_pretty::pprust::attribute_to_string;
-use rustc_hir as hir;
-use rustc_hir::def::{DefKind as HirDefKind, Res};
-use rustc_hir::def_id::{DefId, LOCAL_CRATE};
-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::nested_filter;
-use rustc_middle::middle::privacy::EffectiveVisibilities;
-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::symbol::Ident;
-use rustc_span::*;
-
-use std::cell::Cell;
-use std::env;
-use std::fs::File;
-use std::io::BufWriter;
-use std::path::{Path, PathBuf};
-
-use dump_visitor::DumpVisitor;
-use span_utils::SpanUtils;
-
-use rls_data::config::Config;
-use rls_data::{
- Analysis, Def, DefKind, ExternalCrateData, GlobalCrateId, Impl, ImplKind, MacroRef, Ref,
- RefKind, Relation, RelationKind, SpanData,
-};
-
-pub struct SaveContext<'tcx> {
- tcx: TyCtxt<'tcx>,
- maybe_typeck_results: Option<&'tcx ty::TypeckResults<'tcx>>,
- effective_visibilities: &'tcx EffectiveVisibilities,
- span_utils: SpanUtils<'tcx>,
- config: Config,
- impl_counter: Cell<u32>,
-}
-
-#[derive(Debug)]
-pub enum Data {
- RefData(Ref),
- DefData(Def),
- RelationData(Relation, Impl),
-}
-
-impl<'tcx> SaveContext<'tcx> {
- /// Gets the type-checking results for the current body.
- /// As this will ICE if called outside bodies, only call when working with
- /// `Expr` or `Pat` nodes (they are guaranteed to be found only in bodies).
- #[track_caller]
- fn typeck_results(&self) -> &'tcx ty::TypeckResults<'tcx> {
- self.maybe_typeck_results.expect("`SaveContext::typeck_results` called outside of body")
- }
-
- fn span_from_span(&self, span: Span) -> SpanData {
- use rls_span::{Column, Row};
-
- let sm = self.tcx.sess.source_map();
- let start = sm.lookup_char_pos(span.lo());
- let end = sm.lookup_char_pos(span.hi());
-
- SpanData {
- file_name: start.file.name.prefer_remapped().to_string().into(),
- byte_start: span.lo().0,
- byte_end: span.hi().0,
- line_start: Row::new_one_indexed(start.line as u32),
- line_end: Row::new_one_indexed(end.line as u32),
- column_start: Column::new_one_indexed(start.col.0 as u32 + 1),
- column_end: Column::new_one_indexed(end.col.0 as u32 + 1),
- }
- }
-
- /// Returns path to the compilation output (e.g., libfoo-12345678.rmeta)
- pub fn compilation_output(&self, crate_name: Symbol) -> PathBuf {
- let sess = &self.tcx.sess;
- // Save-analysis is emitted per whole session, not per each crate type
- let crate_type = sess.crate_types()[0];
- let outputs = &*self.tcx.output_filenames(());
-
- if outputs.outputs.contains_key(&OutputType::Metadata) {
- filename_for_metadata(sess, crate_name, outputs)
- } else if outputs.outputs.should_codegen() {
- out_filename(sess, crate_type, outputs, crate_name)
- } else {
- // Otherwise it's only a DepInfo, in which case we return early and
- // not even reach the analysis stage.
- unreachable!()
- }
- }
-
- /// List external crates used by the current crate.
- pub fn get_external_crates(&self) -> Vec<ExternalCrateData> {
- let mut result = Vec::with_capacity(self.tcx.crates(()).len());
-
- for &n in self.tcx.crates(()).iter() {
- let Some(&ExternCrate { span, .. }) = self.tcx.extern_crate(n.as_def_id()) else {
- debug!("skipping crate {}, no data", n);
- continue;
- };
- let lo_loc = self.span_utils.sess.source_map().lookup_char_pos(span.lo());
- result.push(ExternalCrateData {
- // FIXME: change file_name field to PathBuf in rls-data
- // https://github.com/nrc/rls-data/issues/7
- file_name: self.span_utils.make_filename_string(&lo_loc.file),
- num: n.as_u32(),
- id: GlobalCrateId {
- name: self.tcx.crate_name(n).to_string(),
- disambiguator: (
- self.tcx.def_path_hash(n.as_def_id()).stable_crate_id().to_u64(),
- 0,
- ),
- },
- });
- }
-
- result
- }
-
- pub fn get_extern_item_data(&self, item: &hir::ForeignItem<'_>) -> Option<Data> {
- let def_id = item.owner_id.to_def_id();
- let qualname = format!("::{}", self.tcx.def_path_str(def_id));
- let attrs = self.tcx.hir().attrs(item.hir_id());
- match item.kind {
- hir::ForeignItemKind::Fn(ref decl, arg_names, ref generics) => {
- filter!(self.span_utils, item.ident.span);
-
- Some(Data::DefData(Def {
- kind: DefKind::ForeignFunction,
- id: id_from_def_id(def_id),
- span: self.span_from_span(item.ident.span),
- name: item.ident.to_string(),
- qualname,
- value: fn_to_string(
- decl,
- hir::FnHeader {
- // functions in extern block are implicitly unsafe
- unsafety: hir::Unsafety::Unsafe,
- // functions in extern block cannot be const
- constness: hir::Constness::NotConst,
- abi: self.tcx.hir().get_foreign_abi(item.hir_id()),
- // functions in extern block cannot be async
- asyncness: hir::IsAsync::NotAsync,
- },
- Some(item.ident.name),
- generics,
- arg_names,
- None,
- ),
- parent: None,
- children: vec![],
- decl_id: None,
- docs: self.docs_for_attrs(attrs),
- sig: sig::foreign_item_signature(item, self),
- attributes: lower_attributes(attrs.to_vec(), self),
- }))
- }
- hir::ForeignItemKind::Static(ref ty, _) => {
- filter!(self.span_utils, item.ident.span);
-
- let id = id_from_def_id(def_id);
- let span = self.span_from_span(item.ident.span);
-
- Some(Data::DefData(Def {
- kind: DefKind::ForeignStatic,
- id,
- span,
- name: item.ident.to_string(),
- qualname,
- value: ty_to_string(ty),
- parent: None,
- children: vec![],
- decl_id: None,
- docs: self.docs_for_attrs(attrs),
- sig: sig::foreign_item_signature(item, self),
- attributes: lower_attributes(attrs.to_vec(), self),
- }))
- }
- // FIXME(plietar): needs a new DefKind in rls-data
- hir::ForeignItemKind::Type => None,
- }
- }
-
- pub fn get_item_data(&self, item: &hir::Item<'_>) -> Option<Data> {
- let def_id = item.owner_id.to_def_id();
- let attrs = self.tcx.hir().attrs(item.hir_id());
- match item.kind {
- hir::ItemKind::Fn(ref sig, ref generics, _) => {
- let qualname = format!("::{}", self.tcx.def_path_str(def_id));
- filter!(self.span_utils, item.ident.span);
- Some(Data::DefData(Def {
- kind: DefKind::Function,
- id: id_from_def_id(def_id),
- span: self.span_from_span(item.ident.span),
- name: item.ident.to_string(),
- qualname,
- value: fn_to_string(
- sig.decl,
- sig.header,
- Some(item.ident.name),
- generics,
- &[],
- None,
- ),
- parent: None,
- children: vec![],
- decl_id: None,
- docs: self.docs_for_attrs(attrs),
- sig: sig::item_signature(item, self),
- attributes: lower_attributes(attrs.to_vec(), self),
- }))
- }
- hir::ItemKind::Static(ref typ, ..) => {
- let qualname = format!("::{}", self.tcx.def_path_str(def_id));
-
- filter!(self.span_utils, item.ident.span);
-
- let id = id_from_def_id(def_id);
- let span = self.span_from_span(item.ident.span);
-
- Some(Data::DefData(Def {
- kind: DefKind::Static,
- id,
- span,
- name: item.ident.to_string(),
- qualname,
- value: ty_to_string(&typ),
- parent: None,
- children: vec![],
- decl_id: None,
- docs: self.docs_for_attrs(attrs),
- sig: sig::item_signature(item, self),
- attributes: lower_attributes(attrs.to_vec(), self),
- }))
- }
- hir::ItemKind::Const(ref typ, _) => {
- let qualname = format!("::{}", self.tcx.def_path_str(def_id));
- filter!(self.span_utils, item.ident.span);
-
- let id = id_from_def_id(def_id);
- let span = self.span_from_span(item.ident.span);
-
- Some(Data::DefData(Def {
- kind: DefKind::Const,
- id,
- span,
- name: item.ident.to_string(),
- qualname,
- value: ty_to_string(typ),
- parent: None,
- children: vec![],
- decl_id: None,
- docs: self.docs_for_attrs(attrs),
- sig: sig::item_signature(item, self),
- attributes: lower_attributes(attrs.to_vec(), self),
- }))
- }
- hir::ItemKind::Mod(ref m) => {
- let qualname = format!("::{}", self.tcx.def_path_str(def_id));
-
- let sm = self.tcx.sess.source_map();
- let filename = sm.span_to_filename(m.spans.inner_span);
-
- filter!(self.span_utils, item.ident.span);
-
- Some(Data::DefData(Def {
- kind: DefKind::Mod,
- id: id_from_def_id(def_id),
- name: item.ident.to_string(),
- qualname,
- span: self.span_from_span(item.ident.span),
- value: filename.prefer_remapped().to_string(),
- parent: None,
- children: m
- .item_ids
- .iter()
- .map(|i| id_from_def_id(i.owner_id.to_def_id()))
- .collect(),
- decl_id: None,
- docs: self.docs_for_attrs(attrs),
- sig: sig::item_signature(item, self),
- attributes: lower_attributes(attrs.to_vec(), self),
- }))
- }
- hir::ItemKind::Enum(ref def, ref generics) => {
- let name = item.ident.to_string();
- let qualname = format!("::{}", self.tcx.def_path_str(def_id));
- filter!(self.span_utils, item.ident.span);
- let value =
- enum_def_to_string(def, generics, item.ident.name, item.span);
- Some(Data::DefData(Def {
- kind: DefKind::Enum,
- id: id_from_def_id(def_id),
- span: self.span_from_span(item.ident.span),
- name,
- qualname,
- value,
- parent: None,
- children: def.variants.iter().map(|v| id_from_hir_id(v.hir_id, self)).collect(),
- decl_id: None,
- docs: self.docs_for_attrs(attrs),
- sig: sig::item_signature(item, self),
- attributes: lower_attributes(attrs.to_vec(), self),
- }))
- }
- hir::ItemKind::Impl(hir::Impl { ref of_trait, ref self_ty, ref items, .. })
- if let hir::TyKind::Path(hir::QPath::Resolved(_, ref path)) = self_ty.kind =>
- {
- // Common case impl for a struct or something basic.
- if generated_code(path.span) {
- return None;
- }
- let sub_span = path.segments.last().unwrap().ident.span;
- filter!(self.span_utils, sub_span);
-
- let impl_id = self.next_impl_id();
- let span = self.span_from_span(sub_span);
-
- let type_data = self.lookup_def_id(self_ty.hir_id);
- type_data.map(|type_data| {
- Data::RelationData(
- Relation {
- kind: RelationKind::Impl { id: impl_id },
- span: span.clone(),
- from: id_from_def_id(type_data),
- to: of_trait
- .as_ref()
- .and_then(|t| self.lookup_def_id(t.hir_ref_id))
- .map(id_from_def_id)
- .unwrap_or_else(null_id),
- },
- Impl {
- id: impl_id,
- kind: match *of_trait {
- Some(_) => ImplKind::Direct,
- None => ImplKind::Inherent,
- },
- span,
- value: String::new(),
- parent: None,
- children: items
- .iter()
- .map(|i| id_from_def_id(i.id.owner_id.to_def_id()))
- .collect(),
- docs: String::new(),
- sig: None,
- attributes: vec![],
- },
- )
- })
- }
- hir::ItemKind::Impl(_) => None,
- _ => {
- // FIXME
- bug!();
- }
- }
- }
-
- pub fn get_field_data(&self, field: &hir::FieldDef<'_>, scope: hir::HirId) -> Option<Def> {
- let name = field.ident.to_string();
- let scope_def_id = self.tcx.hir().local_def_id(scope).to_def_id();
- let qualname = format!("::{}::{}", self.tcx.def_path_str(scope_def_id), field.ident);
- filter!(self.span_utils, field.ident.span);
- let field_def_id = self.tcx.hir().local_def_id(field.hir_id).to_def_id();
- let typ = self.tcx.type_of(field_def_id).to_string();
-
- let id = id_from_def_id(field_def_id);
- let span = self.span_from_span(field.ident.span);
- let attrs = self.tcx.hir().attrs(field.hir_id);
-
- Some(Def {
- kind: DefKind::Field,
- id,
- span,
- name,
- qualname,
- value: typ,
- parent: Some(id_from_def_id(scope_def_id)),
- children: vec![],
- decl_id: None,
- docs: self.docs_for_attrs(attrs),
- sig: sig::field_signature(field, self),
- attributes: lower_attributes(attrs.to_vec(), self),
- })
- }
-
- // FIXME would be nice to take a MethodItem here, but the ast provides both
- // trait and impl flavours, so the caller must do the disassembly.
- pub fn get_method_data(&self, hir_id: hir::HirId, ident: Ident, span: Span) -> Option<Def> {
- // The qualname for a method is the trait name or name of the struct in an impl in
- // which the method is declared in, followed by the method's name.
- let def_id = self.tcx.hir().local_def_id(hir_id).to_def_id();
- let (qualname, parent_scope, decl_id, docs, attributes) =
- match self.tcx.impl_of_method(def_id) {
- Some(impl_id) => match self.tcx.hir().get_if_local(impl_id) {
- Some(Node::Item(item)) => match item.kind {
- hir::ItemKind::Impl(hir::Impl { ref self_ty, .. }) => {
- let hir = self.tcx.hir();
-
- let mut qualname = String::from("<");
- qualname
- .push_str(&rustc_hir_pretty::id_to_string(&hir, self_ty.hir_id));
-
- let trait_id = self.tcx.trait_id_of_impl(impl_id);
- let mut docs = String::new();
- let mut attrs = vec![];
- if let Some(Node::ImplItem(_)) = hir.find(hir_id) {
- attrs = self.tcx.hir().attrs(hir_id).to_vec();
- docs = self.docs_for_attrs(&attrs);
- }
-
- let mut decl_id = None;
- if let Some(def_id) = trait_id {
- // A method in a trait impl.
- qualname.push_str(" as ");
- qualname.push_str(&self.tcx.def_path_str(def_id));
-
- decl_id = self
- .tcx
- .associated_items(def_id)
- .filter_by_name_unhygienic(ident.name)
- .next()
- .map(|item| item.def_id);
- }
- qualname.push('>');
-
- (qualname, trait_id, decl_id, docs, attrs)
- }
- _ => {
- span_bug!(
- span,
- "Container {:?} for method {} not an impl?",
- impl_id,
- hir_id
- );
- }
- },
- r => {
- span_bug!(
- span,
- "Container {:?} for method {} is not a node item {:?}",
- impl_id,
- hir_id,
- r
- );
- }
- },
- None => match self.tcx.trait_of_item(def_id) {
- Some(def_id) => {
- let mut docs = String::new();
- let mut attrs = vec![];
-
- if let Some(Node::TraitItem(_)) = self.tcx.hir().find(hir_id) {
- attrs = self.tcx.hir().attrs(hir_id).to_vec();
- docs = self.docs_for_attrs(&attrs);
- }
-
- (
- format!("::{}", self.tcx.def_path_str(def_id)),
- Some(def_id),
- None,
- docs,
- attrs,
- )
- }
- None => {
- debug!("could not find container for method {} at {:?}", hir_id, span);
- // This is not necessarily a bug, if there was a compilation error,
- // the typeck results we need might not exist.
- return None;
- }
- },
- };
-
- let qualname = format!("{}::{}", qualname, ident.name);
-
- filter!(self.span_utils, ident.span);
-
- Some(Def {
- kind: DefKind::Method,
- id: id_from_def_id(def_id),
- span: self.span_from_span(ident.span),
- name: ident.name.to_string(),
- qualname,
- // FIXME you get better data here by using the visitor.
- value: String::new(),
- parent: parent_scope.map(id_from_def_id),
- children: vec![],
- decl_id: decl_id.map(id_from_def_id),
- docs,
- sig: None,
- attributes: lower_attributes(attributes, self),
- })
- }
-
- pub fn get_expr_data(&self, expr: &hir::Expr<'_>) -> Option<Data> {
- let ty = self.typeck_results().expr_ty_adjusted_opt(expr)?;
- if matches!(ty.kind(), ty::Error(_)) {
- return None;
- }
- match expr.kind {
- hir::ExprKind::Field(ref sub_ex, ident) => {
- match self.typeck_results().expr_ty_adjusted(&sub_ex).kind() {
- ty::Adt(def, _) if !def.is_enum() => {
- let variant = &def.non_enum_variant();
- filter!(self.span_utils, ident.span);
- let span = self.span_from_span(ident.span);
- Some(Data::RefData(Ref {
- kind: RefKind::Variable,
- span,
- ref_id: self
- .tcx
- .find_field_index(ident, variant)
- .map(|index| id_from_def_id(variant.fields[index].did))
- .unwrap_or_else(null_id),
- }))
- }
- ty::Tuple(..) => None,
- _ => {
- debug!("expected struct or union type, found {:?}", ty);
- None
- }
- }
- }
- hir::ExprKind::Struct(qpath, ..) => match ty.kind() {
- ty::Adt(def, _) => {
- let sub_span = qpath.last_segment_span();
- filter!(self.span_utils, sub_span);
- let span = self.span_from_span(sub_span);
- Some(Data::RefData(Ref {
- kind: RefKind::Type,
- span,
- ref_id: id_from_def_id(def.did()),
- }))
- }
- _ => {
- debug!("expected adt, found {:?}", ty);
- None
- }
- },
- hir::ExprKind::MethodCall(ref seg, ..) => {
- let Some(method_id) = self.typeck_results().type_dependent_def_id(expr.hir_id) else {
- debug!("could not resolve method id for {:?}", expr);
- return None;
- };
- let (def_id, decl_id) = match self.tcx.associated_item(method_id).container {
- ty::ImplContainer => (Some(method_id), None),
- ty::TraitContainer => (None, Some(method_id)),
- };
- let sub_span = seg.ident.span;
- filter!(self.span_utils, sub_span);
- let span = self.span_from_span(sub_span);
- Some(Data::RefData(Ref {
- kind: RefKind::Function,
- span,
- ref_id: def_id.or(decl_id).map(id_from_def_id).unwrap_or_else(null_id),
- }))
- }
- hir::ExprKind::Path(ref path) => {
- self.get_path_data(expr.hir_id, path).map(Data::RefData)
- }
- _ => {
- // FIXME
- bug!("invalid expression: {:?}", expr);
- }
- }
- }
-
- pub fn get_path_res(&self, hir_id: hir::HirId) -> Res {
- match self.tcx.hir().get(hir_id) {
- Node::TraitRef(tr) => tr.path.res,
-
- Node::Item(&hir::Item { kind: hir::ItemKind::Use(path, _), .. }) => {
- path.res.get(0).copied().unwrap_or(Res::Err)
- }
- Node::PathSegment(seg) => {
- if seg.res != Res::Err {
- seg.res
- } else {
- let parent_node = self.tcx.hir().parent_id(hir_id);
- self.get_path_res(parent_node)
- }
- }
-
- Node::Expr(&hir::Expr { kind: hir::ExprKind::Struct(ref qpath, ..), .. }) => {
- self.typeck_results().qpath_res(qpath, hir_id)
- }
-
- Node::Expr(&hir::Expr { kind: hir::ExprKind::Path(ref qpath), .. })
- | Node::Pat(&hir::Pat {
- kind:
- hir::PatKind::Path(ref qpath)
- | hir::PatKind::Struct(ref qpath, ..)
- | hir::PatKind::TupleStruct(ref qpath, ..),
- ..
- })
- | Node::Ty(&hir::Ty { kind: hir::TyKind::Path(ref qpath), .. }) => match qpath {
- hir::QPath::Resolved(_, path) => path.res,
- hir::QPath::TypeRelative(..) | hir::QPath::LangItem(..) => {
- // #75962: `self.typeck_results` may be different from the `hir_id`'s result.
- if self.tcx.has_typeck_results(hir_id.owner.to_def_id()) {
- self.tcx.typeck(hir_id.owner.def_id).qpath_res(qpath, hir_id)
- } else {
- Res::Err
- }
- }
- },
-
- Node::Pat(&hir::Pat { kind: hir::PatKind::Binding(_, canonical_id, ..), .. }) => {
- Res::Local(canonical_id)
- }
-
- _ => Res::Err,
- }
- }
-
- pub fn get_path_data(&self, id: hir::HirId, path: &hir::QPath<'_>) -> Option<Ref> {
- let segment = match path {
- hir::QPath::Resolved(_, path) => path.segments.last(),
- hir::QPath::TypeRelative(_, segment) => Some(*segment),
- hir::QPath::LangItem(..) => None,
- };
- segment.and_then(|seg| {
- self.get_path_segment_data(seg).or_else(|| self.get_path_segment_data_with_id(seg, id))
- })
- }
-
- pub fn get_path_segment_data(&self, path_seg: &hir::PathSegment<'_>) -> Option<Ref> {
- self.get_path_segment_data_with_id(path_seg, path_seg.hir_id)
- }
-
- pub fn get_path_segment_data_with_id(
- &self,
- path_seg: &hir::PathSegment<'_>,
- id: hir::HirId,
- ) -> Option<Ref> {
- // Returns true if the path is function type sugar, e.g., `Fn(A) -> B`.
- fn fn_type(seg: &hir::PathSegment<'_>) -> bool {
- seg.args.map_or(false, |args| args.parenthesized)
- }
-
- let res = self.get_path_res(id);
- let span = path_seg.ident.span;
- filter!(self.span_utils, span);
- let span = self.span_from_span(span);
-
- match res {
- Res::Local(id) => {
- Some(Ref { kind: RefKind::Variable, span, ref_id: id_from_hir_id(id, self) })
- }
- Res::Def(HirDefKind::Trait, def_id) if fn_type(path_seg) => {
- Some(Ref { kind: RefKind::Type, span, ref_id: id_from_def_id(def_id) })
- }
- Res::Def(
- HirDefKind::Struct
- | HirDefKind::Variant
- | HirDefKind::Union
- | HirDefKind::Enum
- | HirDefKind::TyAlias
- | HirDefKind::ForeignTy
- | HirDefKind::TraitAlias
- | HirDefKind::AssocTy
- | HirDefKind::Trait
- | HirDefKind::OpaqueTy
- | HirDefKind::ImplTraitPlaceholder
- | HirDefKind::TyParam,
- def_id,
- ) => Some(Ref { kind: RefKind::Type, span, ref_id: id_from_def_id(def_id) }),
- Res::Def(HirDefKind::ConstParam, def_id) => {
- Some(Ref { kind: RefKind::Variable, span, ref_id: id_from_def_id(def_id) })
- }
- Res::Def(HirDefKind::Ctor(..), def_id) => {
- // This is a reference to a tuple struct or an enum variant where the def_id points
- // to an invisible constructor function. That is not a very useful
- // def, so adjust to point to the tuple struct or enum variant itself.
- let parent_def_id = self.tcx.parent(def_id);
- Some(Ref { kind: RefKind::Type, span, ref_id: id_from_def_id(parent_def_id) })
- }
- Res::Def(HirDefKind::Static(_) | HirDefKind::Const | HirDefKind::AssocConst, _) => {
- Some(Ref { kind: RefKind::Variable, span, ref_id: id_from_def_id(res.def_id()) })
- }
- Res::Def(HirDefKind::AssocFn, decl_id) => {
- let def_id = if decl_id.is_local() {
- if self.tcx.impl_defaultness(decl_id).has_value() {
- Some(decl_id)
- } else {
- None
- }
- } else {
- None
- };
- Some(Ref {
- kind: RefKind::Function,
- span,
- ref_id: id_from_def_id(def_id.unwrap_or(decl_id)),
- })
- }
- Res::Def(HirDefKind::Fn, def_id) => {
- Some(Ref { kind: RefKind::Function, span, ref_id: id_from_def_id(def_id) })
- }
- Res::Def(HirDefKind::Mod, def_id) => {
- Some(Ref { kind: RefKind::Mod, span, ref_id: id_from_def_id(def_id) })
- }
-
- Res::Def(
- HirDefKind::Macro(..)
- | HirDefKind::ExternCrate
- | HirDefKind::ForeignMod
- | HirDefKind::LifetimeParam
- | HirDefKind::AnonConst
- | HirDefKind::InlineConst
- | HirDefKind::Use
- | HirDefKind::Field
- | HirDefKind::GlobalAsm
- | HirDefKind::Impl
- | HirDefKind::Closure
- | HirDefKind::Generator,
- _,
- )
- | Res::PrimTy(..)
- | Res::SelfTyParam { .. }
- | Res::SelfTyAlias { .. }
- | Res::ToolMod
- | Res::NonMacroAttr(..)
- | Res::SelfCtor(..)
- | Res::Err => None,
- }
- }
-
- pub fn get_field_ref_data(
- &self,
- field_ref: &hir::ExprField<'_>,
- variant: &ty::VariantDef,
- ) -> Option<Ref> {
- filter!(self.span_utils, field_ref.ident.span);
- self.tcx.find_field_index(field_ref.ident, variant).map(|index| {
- let span = self.span_from_span(field_ref.ident.span);
- Ref { kind: RefKind::Variable, span, ref_id: id_from_def_id(variant.fields[index].did) }
- })
- }
-
- /// Attempt to return MacroRef for any AST node.
- ///
- /// For a given piece of AST defined by the supplied Span and NodeId,
- /// returns `None` if the node is not macro-generated or the span is malformed,
- /// else uses the expansion callsite and callee to return some MacroRef.
- ///
- /// FIXME: [`DumpVisitor::process_macro_use`] should actually dump this data
- #[allow(dead_code)]
- fn get_macro_use_data(&self, span: Span) -> Option<MacroRef> {
- if !generated_code(span) {
- return None;
- }
- // Note we take care to use the source callsite/callee, to handle
- // nested expansions and ensure we only generate data for source-visible
- // macro uses.
- let callsite = span.source_callsite();
- let callsite_span = self.span_from_span(callsite);
- let callee = span.source_callee()?;
-
- let mac_name = match callee.kind {
- ExpnKind::Macro(kind, name) => match kind {
- MacroKind::Bang => name,
-
- // Ignore attribute macros, their spans are usually mangled
- // FIXME(eddyb) is this really the case anymore?
- MacroKind::Attr | MacroKind::Derive => return None,
- },
-
- // These are not macros.
- // FIXME(eddyb) maybe there is a way to handle them usefully?
- ExpnKind::Inlined | ExpnKind::Root | ExpnKind::AstPass(_) | ExpnKind::Desugaring(_) => {
- return None;
- }
- };
-
- let callee_span = self.span_from_span(callee.def_site);
- Some(MacroRef {
- span: callsite_span,
- qualname: mac_name.to_string(), // FIXME: generate the real qualname
- callee_span,
- })
- }
-
- fn lookup_def_id(&self, ref_id: hir::HirId) -> Option<DefId> {
- match self.get_path_res(ref_id) {
- Res::PrimTy(_) | Res::SelfTyParam { .. } | Res::SelfTyAlias { .. } | Res::Err => None,
- def => def.opt_def_id(),
- }
- }
-
- fn docs_for_attrs(&self, attrs: &[ast::Attribute]) -> String {
- let mut result = String::new();
-
- for attr in attrs {
- if let Some((val, kind)) = attr.doc_str_and_comment_kind() {
- // FIXME: Should save-analysis beautify doc strings itself or leave it to users?
- result.push_str(beautify_doc_string(val, kind).as_str());
- result.push('\n');
- }
- }
-
- if !self.config.full_docs {
- if let Some(index) = result.find("\n\n") {
- result.truncate(index);
- }
- }
-
- result
- }
-
- fn next_impl_id(&self) -> u32 {
- let next = self.impl_counter.get();
- self.impl_counter.set(next + 1);
- next
- }
-}
-
-// An AST visitor for collecting paths (e.g., the names of structs) and formal
-// variables (idents) from patterns.
-struct PathCollector<'l> {
- tcx: TyCtxt<'l>,
- collected_paths: Vec<(hir::HirId, &'l hir::QPath<'l>)>,
- collected_idents: Vec<(hir::HirId, Ident, hir::Mutability)>,
-}
-
-impl<'l> PathCollector<'l> {
- fn new(tcx: TyCtxt<'l>) -> PathCollector<'l> {
- PathCollector { tcx, collected_paths: vec![], collected_idents: vec![] }
- }
-}
-
-impl<'l> Visitor<'l> for PathCollector<'l> {
- type NestedFilter = nested_filter::All;
-
- fn nested_visit_map(&mut self) -> Self::Map {
- self.tcx.hir()
- }
-
- fn visit_pat(&mut self, p: &'l hir::Pat<'l>) {
- match p.kind {
- hir::PatKind::Struct(ref path, ..) => {
- self.collected_paths.push((p.hir_id, path));
- }
- hir::PatKind::TupleStruct(ref path, ..) | hir::PatKind::Path(ref path) => {
- self.collected_paths.push((p.hir_id, path));
- }
- hir::PatKind::Binding(hir::BindingAnnotation(_, mutbl), _, ident, _) => {
- debug!(
- "PathCollector, visit ident in pat {}: {:?} {:?}",
- ident, p.span, ident.span
- );
- self.collected_idents.push((p.hir_id, ident, mutbl));
- }
- _ => {}
- }
- intravisit::walk_pat(self, p);
- }
-}
-
-/// Defines what to do with the results of saving the analysis.
-pub trait SaveHandler {
- fn save(&mut self, save_ctxt: &SaveContext<'_>, analysis: &Analysis);
-}
-
-/// Dump the save-analysis results to a file.
-pub struct DumpHandler<'a> {
- odir: Option<&'a Path>,
- cratename: String,
-}
-
-impl<'a> DumpHandler<'a> {
- pub fn new(odir: Option<&'a Path>, cratename: Symbol) -> DumpHandler<'a> {
- DumpHandler { odir, cratename: cratename.to_string() }
- }
-
- fn output_file(&self, ctx: &SaveContext<'_>) -> (BufWriter<File>, PathBuf) {
- let sess = &ctx.tcx.sess;
- let file_name = match ctx.config.output_file {
- Some(ref s) => PathBuf::from(s),
- None => {
- let mut root_path = match self.odir {
- Some(val) => val.join("save-analysis"),
- None => PathBuf::from("save-analysis-temp"),
- };
-
- if let Err(e) = std::fs::create_dir_all(&root_path) {
- error!("Could not create directory {}: {}", root_path.display(), e);
- }
-
- let executable = sess.crate_types().iter().any(|ct| *ct == CrateType::Executable);
- let mut out_name = if executable { String::new() } else { "lib".to_owned() };
- out_name.push_str(&self.cratename);
- out_name.push_str(&sess.opts.cg.extra_filename);
- out_name.push_str(".json");
- root_path.push(&out_name);
-
- root_path
- }
- };
-
- info!("Writing output to {}", file_name.display());
-
- let output_file = BufWriter::new(File::create(&file_name).unwrap_or_else(|e| {
- sess.emit_fatal(errors::CouldNotOpen { file_name: file_name.as_path(), err: e })
- }));
-
- (output_file, file_name)
- }
-}
-
-impl SaveHandler for DumpHandler<'_> {
- fn save(&mut self, save_ctxt: &SaveContext<'_>, analysis: &Analysis) {
- let sess = &save_ctxt.tcx.sess;
- let (output, file_name) = self.output_file(&save_ctxt);
- if let Err(e) = serde_json::to_writer(output, &analysis) {
- error!("Can't serialize save-analysis: {:?}", e);
- }
-
- if sess.opts.json_artifact_notifications {
- sess.parse_sess.span_diagnostic.emit_artifact_notification(&file_name, "save-analysis");
- }
- }
-}
-
-/// Call a callback with the results of save-analysis.
-pub struct CallbackHandler<'b> {
- pub callback: &'b mut dyn FnMut(&rls_data::Analysis),
-}
-
-impl SaveHandler for CallbackHandler<'_> {
- fn save(&mut self, _: &SaveContext<'_>, analysis: &Analysis) {
- (self.callback)(analysis)
- }
-}
-
-pub fn process_crate<H: SaveHandler>(
- tcx: TyCtxt<'_>,
- cratename: Symbol,
- input: &Input,
- config: Option<Config>,
- mut handler: H,
-) {
- with_no_trimmed_paths!({
- tcx.dep_graph.with_ignore(|| {
- info!("Dumping crate {}", cratename);
-
- // Privacy checking must be done outside of type inference; use a
- // fallback in case effective visibilities couldn't have been correctly computed.
- let effective_visibilities = match tcx.sess.compile_status() {
- Ok(..) => tcx.effective_visibilities(()),
- Err(..) => tcx.arena.alloc(EffectiveVisibilities::default()),
- };
-
- let save_ctxt = SaveContext {
- tcx,
- maybe_typeck_results: None,
- effective_visibilities: &effective_visibilities,
- span_utils: SpanUtils::new(&tcx.sess),
- config: find_config(config),
- impl_counter: Cell::new(0),
- };
-
- let mut visitor = DumpVisitor::new(save_ctxt);
-
- visitor.dump_crate_info(cratename);
- visitor.dump_compilation_options(input, cratename);
- visitor.process_crate();
-
- handler.save(&visitor.save_ctxt, &visitor.analysis())
- })
- })
-}
-
-fn find_config(supplied: Option<Config>) -> Config {
- if let Some(config) = supplied {
- return config;
- }
-
- match env::var_os("RUST_SAVE_ANALYSIS_CONFIG") {
- None => Config::default(),
- Some(config) => config
- .to_str()
- .ok_or(())
- .map_err(|_| error!("`RUST_SAVE_ANALYSIS_CONFIG` isn't UTF-8"))
- .and_then(|cfg| {
- serde_json::from_str(cfg)
- .map_err(|_| error!("Could not deserialize save-analysis config"))
- })
- .unwrap_or_default(),
- }
-}
-
-// Utility functions for the module.
-
-// Helper function to escape quotes in a string
-fn escape(s: String) -> String {
- s.replace('\"', "\"\"")
-}
-
-// Helper function to determine if a span came from a
-// macro expansion or syntax extension.
-fn generated_code(span: Span) -> bool {
- span.from_expansion() || span.is_dummy()
-}
-
-// DefId::index is a newtype and so the JSON serialisation is ugly. Therefore
-// we use our own Id which is the same, but without the newtype.
-fn id_from_def_id(id: DefId) -> rls_data::Id {
- rls_data::Id { krate: id.krate.as_u32(), index: id.index.as_u32() }
-}
-
-fn id_from_hir_id(id: hir::HirId, scx: &SaveContext<'_>) -> rls_data::Id {
- let def_id = scx.tcx.hir().opt_local_def_id(id);
- def_id.map(|id| id_from_def_id(id.to_def_id())).unwrap_or_else(|| {
- // Create a *fake* `DefId` out of a `HirId` by combining the owner
- // `local_def_index` and the `local_id`.
- // This will work unless you have *billions* of definitions in a single
- // crate (very unlikely to actually happen).
- rls_data::Id {
- krate: LOCAL_CRATE.as_u32(),
- index: id.owner.def_id.local_def_index.as_u32() | id.local_id.as_u32().reverse_bits(),
- }
- })
-}
-
-fn null_id() -> rls_data::Id {
- rls_data::Id { krate: u32::MAX, index: u32::MAX }
-}
-
-fn lower_attributes(attrs: Vec<ast::Attribute>, scx: &SaveContext<'_>) -> Vec<rls_data::Attribute> {
- attrs
- .into_iter()
- // Only retain real attributes. Doc comments are lowered separately.
- .filter(|attr| !attr.has_name(sym::doc))
- .map(|mut attr| {
- // Remove the surrounding '#[..]' or '#![..]' of the pretty printed
- // attribute. First normalize all inner attribute (#![..]) to outer
- // ones (#[..]), then remove the two leading and the one trailing character.
- attr.style = ast::AttrStyle::Outer;
- let value = attribute_to_string(&attr);
- // This str slicing works correctly, because the leading and trailing characters
- // are in the ASCII range and thus exactly one byte each.
- let value = value[2..value.len() - 1].to_string();
-
- rls_data::Attribute { value, span: scx.span_from_span(attr.span) }
- })
- .collect()
-}
diff --git a/compiler/rustc_save_analysis/src/sig.rs b/compiler/rustc_save_analysis/src/sig.rs
deleted file mode 100644
index 5a1bcb8fd..000000000
--- a/compiler/rustc_save_analysis/src/sig.rs
+++ /dev/null
@@ -1,923 +0,0 @@
-// A signature is a string representation of an item's type signature, excluding
-// any body. It also includes ids for any defs or refs in the signature. For
-// example:
-//
-// ```
-// fn foo(x: String) {
-// println!("{}", x);
-// }
-// ```
-// The signature string is something like "fn foo(x: String) {}" and the signature
-// will have defs for `foo` and `x` and a ref for `String`.
-//
-// All signature text should parse in the correct context (i.e., in a module or
-// impl, etc.). Clients may want to trim trailing `{}` or `;`. The text of a
-// signature is not guaranteed to be stable (it may improve or change as the
-// syntax changes, or whitespace or punctuation may change). It is also likely
-// not to be pretty - no attempt is made to prettify the text. It is recommended
-// that clients run the text through Rustfmt.
-//
-// This module generates Signatures for items by walking the AST and looking up
-// references.
-//
-// Signatures do not include visibility info. I'm not sure if this is a feature
-// or an omission (FIXME).
-//
-// FIXME where clauses need implementing, defs/refs in generics are mostly missing.
-
-use crate::{id_from_def_id, id_from_hir_id, SaveContext};
-
-use rls_data::{SigElement, Signature};
-
-use rustc_ast::Mutability;
-use rustc_hir as hir;
-use rustc_hir::def::{DefKind, Res};
-use rustc_hir_pretty::id_to_string;
-use rustc_hir_pretty::{bounds_to_string, path_segment_to_string, path_to_string, ty_to_string};
-use rustc_span::symbol::{Ident, Symbol};
-
-pub fn item_signature(item: &hir::Item<'_>, scx: &SaveContext<'_>) -> Option<Signature> {
- if !scx.config.signatures {
- return None;
- }
- item.make(0, None, scx).ok()
-}
-
-pub fn foreign_item_signature(
- item: &hir::ForeignItem<'_>,
- scx: &SaveContext<'_>,
-) -> Option<Signature> {
- if !scx.config.signatures {
- return None;
- }
- item.make(0, None, scx).ok()
-}
-
-/// Signature for a struct or tuple field declaration.
-/// Does not include a trailing comma.
-pub fn field_signature(field: &hir::FieldDef<'_>, scx: &SaveContext<'_>) -> Option<Signature> {
- if !scx.config.signatures {
- return None;
- }
- field.make(0, None, scx).ok()
-}
-
-/// Does not include a trailing comma.
-pub fn variant_signature(variant: &hir::Variant<'_>, scx: &SaveContext<'_>) -> Option<Signature> {
- if !scx.config.signatures {
- return None;
- }
- variant.make(0, None, scx).ok()
-}
-
-pub fn method_signature(
- id: hir::HirId,
- ident: Ident,
- generics: &hir::Generics<'_>,
- m: &hir::FnSig<'_>,
- scx: &SaveContext<'_>,
-) -> Option<Signature> {
- if !scx.config.signatures {
- return None;
- }
- make_method_signature(id, ident, generics, m, scx).ok()
-}
-
-pub fn assoc_const_signature(
- id: hir::HirId,
- ident: Symbol,
- ty: &hir::Ty<'_>,
- default: Option<&hir::Expr<'_>>,
- scx: &SaveContext<'_>,
-) -> Option<Signature> {
- if !scx.config.signatures {
- return None;
- }
- make_assoc_const_signature(id, ident, ty, default, scx).ok()
-}
-
-pub fn assoc_type_signature(
- id: hir::HirId,
- ident: Ident,
- bounds: Option<hir::GenericBounds<'_>>,
- default: Option<&hir::Ty<'_>>,
- scx: &SaveContext<'_>,
-) -> Option<Signature> {
- if !scx.config.signatures {
- return None;
- }
- make_assoc_type_signature(id, ident, bounds, default, scx).ok()
-}
-
-type Result = std::result::Result<Signature, &'static str>;
-
-trait Sig {
- fn make(&self, offset: usize, id: Option<hir::HirId>, scx: &SaveContext<'_>) -> Result;
-}
-
-fn extend_sig(
- mut sig: Signature,
- text: String,
- defs: Vec<SigElement>,
- refs: Vec<SigElement>,
-) -> Signature {
- sig.text = text;
- sig.defs.extend(defs.into_iter());
- sig.refs.extend(refs.into_iter());
- sig
-}
-
-fn replace_text(mut sig: Signature, text: String) -> Signature {
- sig.text = text;
- sig
-}
-
-fn merge_sigs(text: String, sigs: Vec<Signature>) -> Signature {
- let mut result = Signature { text, defs: vec![], refs: vec![] };
-
- let (defs, refs): (Vec<_>, Vec<_>) = sigs.into_iter().map(|s| (s.defs, s.refs)).unzip();
-
- result.defs.extend(defs.into_iter().flat_map(|ds| ds.into_iter()));
- result.refs.extend(refs.into_iter().flat_map(|rs| rs.into_iter()));
-
- result
-}
-
-fn text_sig(text: String) -> Signature {
- Signature { text, defs: vec![], refs: vec![] }
-}
-
-impl<'hir> Sig for hir::Ty<'hir> {
- fn make(&self, offset: usize, _parent_id: Option<hir::HirId>, scx: &SaveContext<'_>) -> Result {
- let id = Some(self.hir_id);
- match self.kind {
- hir::TyKind::Slice(ref ty) => {
- let nested = ty.make(offset + 1, id, scx)?;
- let text = format!("[{}]", nested.text);
- Ok(replace_text(nested, text))
- }
- hir::TyKind::Ptr(ref mt) => {
- let prefix = match mt.mutbl {
- hir::Mutability::Mut => "*mut ",
- hir::Mutability::Not => "*const ",
- };
- let nested = mt.ty.make(offset + prefix.len(), id, scx)?;
- let text = format!("{}{}", prefix, nested.text);
- Ok(replace_text(nested, text))
- }
- hir::TyKind::Ref(ref lifetime, ref mt) => {
- let mut prefix = "&".to_owned();
- prefix.push_str(&lifetime.ident.to_string());
- prefix.push(' ');
- if mt.mutbl.is_mut() {
- prefix.push_str("mut ");
- };
-
- let nested = mt.ty.make(offset + prefix.len(), id, scx)?;
- let text = format!("{}{}", prefix, nested.text);
- Ok(replace_text(nested, text))
- }
- hir::TyKind::Never => Ok(text_sig("!".to_owned())),
- hir::TyKind::Tup(ts) => {
- let mut text = "(".to_owned();
- let mut defs = vec![];
- let mut refs = vec![];
- for t in ts {
- let nested = t.make(offset + text.len(), id, scx)?;
- text.push_str(&nested.text);
- text.push(',');
- defs.extend(nested.defs.into_iter());
- refs.extend(nested.refs.into_iter());
- }
- text.push(')');
- Ok(Signature { text, defs, refs })
- }
- hir::TyKind::BareFn(ref f) => {
- let mut text = String::new();
- if !f.generic_params.is_empty() {
- // FIXME defs, bounds on lifetimes
- text.push_str("for<");
- text.push_str(
- &f.generic_params
- .iter()
- .filter_map(|param| match param.kind {
- hir::GenericParamKind::Lifetime { .. } => {
- Some(param.name.ident().to_string())
- }
- _ => None,
- })
- .collect::<Vec<_>>()
- .join(", "),
- );
- text.push('>');
- }
-
- if let hir::Unsafety::Unsafe = f.unsafety {
- text.push_str("unsafe ");
- }
- text.push_str("fn(");
-
- let mut defs = vec![];
- let mut refs = vec![];
- for i in f.decl.inputs {
- let nested = i.make(offset + text.len(), Some(i.hir_id), scx)?;
- text.push_str(&nested.text);
- text.push(',');
- defs.extend(nested.defs.into_iter());
- refs.extend(nested.refs.into_iter());
- }
- text.push(')');
- if let hir::FnRetTy::Return(ref t) = f.decl.output {
- text.push_str(" -> ");
- let nested = t.make(offset + text.len(), None, scx)?;
- text.push_str(&nested.text);
- text.push(',');
- defs.extend(nested.defs.into_iter());
- refs.extend(nested.refs.into_iter());
- }
-
- Ok(Signature { text, defs, refs })
- }
- hir::TyKind::Path(hir::QPath::Resolved(None, ref path)) => path.make(offset, id, scx),
- hir::TyKind::Path(hir::QPath::Resolved(Some(ref qself), ref path)) => {
- let nested_ty = qself.make(offset + 1, id, scx)?;
- let prefix = format!(
- "<{} as {}>::",
- nested_ty.text,
- path_segment_to_string(&path.segments[0])
- );
-
- let name = path_segment_to_string(path.segments.last().ok_or("Bad path")?);
- let res = scx.get_path_res(id.ok_or("Missing id for Path")?);
- let id = id_from_def_id(res.def_id());
- if path.segments.len() == 2 {
- let start = offset + prefix.len();
- let end = start + name.len();
-
- Ok(Signature {
- text: prefix + &name,
- defs: vec![],
- refs: vec![SigElement { id, start, end }],
- })
- } else {
- let start = offset + prefix.len() + 5;
- let end = start + name.len();
- // FIXME should put the proper path in there, not ellipsis.
- Ok(Signature {
- text: prefix + "...::" + &name,
- defs: vec![],
- refs: vec![SigElement { id, start, end }],
- })
- }
- }
- hir::TyKind::Path(hir::QPath::TypeRelative(ty, segment)) => {
- let nested_ty = ty.make(offset + 1, id, scx)?;
- let prefix = format!("<{}>::", nested_ty.text);
-
- let name = path_segment_to_string(segment);
- let res = scx.get_path_res(id.ok_or("Missing id for Path")?);
- let id = id_from_def_id(res.def_id());
-
- let start = offset + prefix.len();
- let end = start + name.len();
- Ok(Signature {
- text: prefix + &name,
- defs: vec![],
- refs: vec![SigElement { id, start, end }],
- })
- }
- hir::TyKind::Path(hir::QPath::LangItem(lang_item, _, _)) => {
- Ok(text_sig(format!("#[lang = \"{}\"]", lang_item.name())))
- }
- hir::TyKind::TraitObject(bounds, ..) => {
- // FIXME recurse into bounds
- let bounds: Vec<hir::GenericBound<'_>> = bounds
- .iter()
- .map(|hir::PolyTraitRef { bound_generic_params, trait_ref, span }| {
- hir::GenericBound::Trait(
- hir::PolyTraitRef {
- bound_generic_params,
- trait_ref: hir::TraitRef {
- path: trait_ref.path,
- hir_ref_id: trait_ref.hir_ref_id,
- },
- span: *span,
- },
- hir::TraitBoundModifier::None,
- )
- })
- .collect();
- let nested = bounds_to_string(&bounds);
- Ok(text_sig(nested))
- }
- hir::TyKind::Array(ref ty, ref length) => {
- let nested_ty = ty.make(offset + 1, id, scx)?;
- let expr = id_to_string(&scx.tcx.hir(), length.hir_id()).replace('\n', " ");
- let text = format!("[{}; {}]", nested_ty.text, expr);
- Ok(replace_text(nested_ty, text))
- }
- hir::TyKind::OpaqueDef(item_id, _, _) => {
- let item = scx.tcx.hir().item(item_id);
- item.make(offset, Some(item_id.hir_id()), scx)
- }
- hir::TyKind::Typeof(_) | hir::TyKind::Infer | hir::TyKind::Err => Err("Ty"),
- }
- }
-}
-
-impl<'hir> Sig for hir::Item<'hir> {
- fn make(&self, offset: usize, _parent_id: Option<hir::HirId>, scx: &SaveContext<'_>) -> Result {
- let id = Some(self.hir_id());
-
- match self.kind {
- hir::ItemKind::Static(ref ty, m, ref body) => {
- let mut text = "static ".to_owned();
- if m.is_mut() {
- text.push_str("mut ");
- }
- let name = self.ident.to_string();
- let defs = vec![SigElement {
- id: id_from_def_id(self.owner_id.to_def_id()),
- start: offset + text.len(),
- end: offset + text.len() + name.len(),
- }];
- text.push_str(&name);
- text.push_str(": ");
-
- let ty = ty.make(offset + text.len(), id, scx)?;
- text.push_str(&ty.text);
-
- text.push_str(" = ");
- let expr = id_to_string(&scx.tcx.hir(), body.hir_id).replace('\n', " ");
- text.push_str(&expr);
-
- text.push(';');
-
- Ok(extend_sig(ty, text, defs, vec![]))
- }
- hir::ItemKind::Const(ref ty, ref body) => {
- let mut text = "const ".to_owned();
- let name = self.ident.to_string();
- let defs = vec![SigElement {
- id: id_from_def_id(self.owner_id.to_def_id()),
- start: offset + text.len(),
- end: offset + text.len() + name.len(),
- }];
- text.push_str(&name);
- text.push_str(": ");
-
- let ty = ty.make(offset + text.len(), id, scx)?;
- text.push_str(&ty.text);
-
- text.push_str(" = ");
- let expr = id_to_string(&scx.tcx.hir(), body.hir_id).replace('\n', " ");
- text.push_str(&expr);
-
- text.push(';');
-
- Ok(extend_sig(ty, text, defs, vec![]))
- }
- hir::ItemKind::Fn(hir::FnSig { ref decl, header, span: _ }, ref generics, _) => {
- let mut text = String::new();
- if let hir::Constness::Const = header.constness {
- text.push_str("const ");
- }
- if hir::IsAsync::Async == header.asyncness {
- text.push_str("async ");
- }
- if let hir::Unsafety::Unsafe = header.unsafety {
- text.push_str("unsafe ");
- }
- text.push_str("fn ");
-
- let mut sig =
- name_and_generics(text, offset, generics, self.hir_id(), self.ident, scx)?;
-
- sig.text.push('(');
- for i in decl.inputs {
- // FIXME should descend into patterns to add defs.
- sig.text.push_str(": ");
- let nested = i.make(offset + sig.text.len(), Some(i.hir_id), scx)?;
- sig.text.push_str(&nested.text);
- sig.text.push(',');
- sig.defs.extend(nested.defs.into_iter());
- sig.refs.extend(nested.refs.into_iter());
- }
- sig.text.push(')');
-
- if let hir::FnRetTy::Return(ref t) = decl.output {
- sig.text.push_str(" -> ");
- let nested = t.make(offset + sig.text.len(), None, scx)?;
- sig.text.push_str(&nested.text);
- sig.defs.extend(nested.defs.into_iter());
- sig.refs.extend(nested.refs.into_iter());
- }
- sig.text.push_str(" {}");
-
- Ok(sig)
- }
- hir::ItemKind::Macro(..) => {
- let mut text = "macro".to_owned();
- let name = self.ident.to_string();
- text.push_str(&name);
- text.push_str(&"! {}");
-
- Ok(text_sig(text))
- }
- hir::ItemKind::Mod(ref _mod) => {
- let mut text = "mod ".to_owned();
- let name = self.ident.to_string();
- let defs = vec![SigElement {
- id: id_from_def_id(self.owner_id.to_def_id()),
- start: offset + text.len(),
- end: offset + text.len() + name.len(),
- }];
- text.push_str(&name);
- // Could be either `mod foo;` or `mod foo { ... }`, but we'll just pick one.
- text.push(';');
-
- Ok(Signature { text, defs, refs: vec![] })
- }
- hir::ItemKind::TyAlias(ref ty, ref generics) => {
- let text = "type ".to_owned();
- let mut sig =
- name_and_generics(text, offset, generics, self.hir_id(), self.ident, scx)?;
-
- sig.text.push_str(" = ");
- let ty = ty.make(offset + sig.text.len(), id, scx)?;
- sig.text.push_str(&ty.text);
- sig.text.push(';');
-
- Ok(merge_sigs(sig.text.clone(), vec![sig, ty]))
- }
- hir::ItemKind::Enum(_, ref generics) => {
- let text = "enum ".to_owned();
- let mut sig =
- name_and_generics(text, offset, generics, self.hir_id(), self.ident, scx)?;
- sig.text.push_str(" {}");
- Ok(sig)
- }
- hir::ItemKind::Struct(_, ref generics) => {
- let text = "struct ".to_owned();
- let mut sig =
- name_and_generics(text, offset, generics, self.hir_id(), self.ident, scx)?;
- sig.text.push_str(" {}");
- Ok(sig)
- }
- hir::ItemKind::Union(_, ref generics) => {
- let text = "union ".to_owned();
- let mut sig =
- name_and_generics(text, offset, generics, self.hir_id(), self.ident, scx)?;
- sig.text.push_str(" {}");
- Ok(sig)
- }
- hir::ItemKind::Trait(is_auto, unsafety, ref generics, bounds, _) => {
- let mut text = String::new();
-
- if is_auto == hir::IsAuto::Yes {
- text.push_str("auto ");
- }
-
- if let hir::Unsafety::Unsafe = unsafety {
- text.push_str("unsafe ");
- }
- text.push_str("trait ");
- let mut sig =
- name_and_generics(text, offset, generics, self.hir_id(), self.ident, scx)?;
-
- if !bounds.is_empty() {
- sig.text.push_str(": ");
- sig.text.push_str(&bounds_to_string(bounds));
- }
- // FIXME where clause
- sig.text.push_str(" {}");
-
- Ok(sig)
- }
- hir::ItemKind::TraitAlias(ref generics, bounds) => {
- let mut text = String::new();
- text.push_str("trait ");
- let mut sig =
- name_and_generics(text, offset, generics, self.hir_id(), self.ident, scx)?;
-
- if !bounds.is_empty() {
- sig.text.push_str(" = ");
- sig.text.push_str(&bounds_to_string(bounds));
- }
- // FIXME where clause
- sig.text.push(';');
-
- Ok(sig)
- }
- hir::ItemKind::Impl(hir::Impl {
- unsafety,
- polarity,
- defaultness,
- defaultness_span: _,
- constness,
- ref generics,
- ref of_trait,
- ref self_ty,
- items: _,
- }) => {
- let mut text = String::new();
- if let hir::Defaultness::Default { .. } = defaultness {
- text.push_str("default ");
- }
- if let hir::Unsafety::Unsafe = unsafety {
- text.push_str("unsafe ");
- }
- text.push_str("impl");
- if let hir::Constness::Const = constness {
- text.push_str(" const");
- }
-
- let generics_sig = generics.make(offset + text.len(), id, scx)?;
- text.push_str(&generics_sig.text);
-
- text.push(' ');
-
- let trait_sig = if let Some(ref t) = *of_trait {
- if let hir::ImplPolarity::Negative(_) = polarity {
- text.push('!');
- }
- let trait_sig = t.path.make(offset + text.len(), id, scx)?;
- text.push_str(&trait_sig.text);
- text.push_str(" for ");
- trait_sig
- } else {
- text_sig(String::new())
- };
-
- let ty_sig = self_ty.make(offset + text.len(), id, scx)?;
- text.push_str(&ty_sig.text);
-
- text.push_str(" {}");
-
- Ok(merge_sigs(text, vec![generics_sig, trait_sig, ty_sig]))
-
- // FIXME where clause
- }
- hir::ItemKind::ForeignMod { .. } => Err("extern mod"),
- hir::ItemKind::GlobalAsm(_) => Err("global asm"),
- hir::ItemKind::ExternCrate(_) => Err("extern crate"),
- hir::ItemKind::OpaqueTy(ref opaque) => {
- if opaque.in_trait {
- Err("opaque type in trait")
- } else {
- Err("opaque type")
- }
- }
- // FIXME should implement this (e.g., pub use).
- hir::ItemKind::Use(..) => Err("import"),
- }
- }
-}
-
-impl<'hir> Sig for hir::Path<'hir> {
- fn make(&self, offset: usize, id: Option<hir::HirId>, scx: &SaveContext<'_>) -> Result {
- let res = scx.get_path_res(id.ok_or("Missing id for Path")?);
-
- let (name, start, end) = match res {
- Res::PrimTy(..) | Res::SelfTyParam { .. } | Res::SelfTyAlias { .. } | Res::Err => {
- return Ok(Signature { text: path_to_string(self), defs: vec![], refs: vec![] });
- }
- Res::Def(DefKind::AssocConst | DefKind::Variant | DefKind::Ctor(..), _) => {
- let len = self.segments.len();
- if len < 2 {
- return Err("Bad path");
- }
- // FIXME: really we should descend into the generics here and add SigElements for
- // them.
- // FIXME: would be nice to have a def for the first path segment.
- let seg1 = path_segment_to_string(&self.segments[len - 2]);
- let seg2 = path_segment_to_string(&self.segments[len - 1]);
- let start = offset + seg1.len() + 2;
- (format!("{}::{}", seg1, seg2), start, start + seg2.len())
- }
- _ => {
- let name = path_segment_to_string(self.segments.last().ok_or("Bad path")?);
- let end = offset + name.len();
- (name, offset, end)
- }
- };
-
- let id = id_from_def_id(res.def_id());
- Ok(Signature { text: name, defs: vec![], refs: vec![SigElement { id, start, end }] })
- }
-}
-
-// This does not cover the where clause, which must be processed separately.
-impl<'hir> Sig for hir::Generics<'hir> {
- fn make(&self, offset: usize, _parent_id: Option<hir::HirId>, scx: &SaveContext<'_>) -> Result {
- if self.params.is_empty() {
- return Ok(text_sig(String::new()));
- }
-
- let mut text = "<".to_owned();
-
- let mut defs = Vec::with_capacity(self.params.len());
- for param in self.params {
- let mut param_text = String::new();
- if let hir::GenericParamKind::Const { .. } = param.kind {
- param_text.push_str("const ");
- }
- param_text.push_str(param.name.ident().as_str());
- defs.push(SigElement {
- id: id_from_hir_id(param.hir_id, scx),
- start: offset + text.len(),
- end: offset + text.len() + param_text.as_str().len(),
- });
- if let hir::GenericParamKind::Const { ref ty, default } = param.kind {
- param_text.push_str(": ");
- param_text.push_str(&ty_to_string(&ty));
- if let Some(default) = default {
- param_text.push_str(" = ");
- param_text.push_str(&id_to_string(&scx.tcx.hir(), default.hir_id));
- }
- }
- text.push_str(&param_text);
- text.push(',');
- }
-
- text.push('>');
- Ok(Signature { text, defs, refs: vec![] })
- }
-}
-
-impl<'hir> Sig for hir::FieldDef<'hir> {
- fn make(&self, offset: usize, _parent_id: Option<hir::HirId>, scx: &SaveContext<'_>) -> Result {
- let mut text = String::new();
-
- text.push_str(&self.ident.to_string());
- let defs = Some(SigElement {
- id: id_from_hir_id(self.hir_id, scx),
- start: offset,
- end: offset + text.len(),
- });
- text.push_str(": ");
-
- let mut ty_sig = self.ty.make(offset + text.len(), Some(self.hir_id), scx)?;
- text.push_str(&ty_sig.text);
- ty_sig.text = text;
- ty_sig.defs.extend(defs.into_iter());
- Ok(ty_sig)
- }
-}
-
-impl<'hir> Sig for hir::Variant<'hir> {
- fn make(&self, offset: usize, parent_id: Option<hir::HirId>, scx: &SaveContext<'_>) -> Result {
- let mut text = self.ident.to_string();
- match self.data {
- hir::VariantData::Struct(fields, r) => {
- let id = parent_id.ok_or("Missing id for Variant's parent")?;
- let name_def = SigElement {
- id: id_from_hir_id(id, scx),
- start: offset,
- end: offset + text.len(),
- };
- text.push_str(" { ");
- let mut defs = vec![name_def];
- let mut refs = vec![];
- if r {
- text.push_str("/* parse error */ ");
- } else {
- for f in fields {
- let field_sig = f.make(offset + text.len(), Some(id), scx)?;
- text.push_str(&field_sig.text);
- text.push_str(", ");
- defs.extend(field_sig.defs.into_iter());
- refs.extend(field_sig.refs.into_iter());
- }
- }
- text.push('}');
- Ok(Signature { text, defs, refs })
- }
- hir::VariantData::Tuple(fields, id, _) => {
- let name_def = SigElement {
- id: id_from_hir_id(id, scx),
- start: offset,
- end: offset + text.len(),
- };
- text.push('(');
- let mut defs = vec![name_def];
- let mut refs = vec![];
- for f in fields {
- let field_sig = f.make(offset + text.len(), Some(id), scx)?;
- text.push_str(&field_sig.text);
- text.push_str(", ");
- defs.extend(field_sig.defs.into_iter());
- refs.extend(field_sig.refs.into_iter());
- }
- text.push(')');
- Ok(Signature { text, defs, refs })
- }
- hir::VariantData::Unit(id, _) => {
- let name_def = SigElement {
- id: id_from_hir_id(id, scx),
- start: offset,
- end: offset + text.len(),
- };
- Ok(Signature { text, defs: vec![name_def], refs: vec![] })
- }
- }
- }
-}
-
-impl<'hir> Sig for hir::ForeignItem<'hir> {
- fn make(&self, offset: usize, _parent_id: Option<hir::HirId>, scx: &SaveContext<'_>) -> Result {
- let id = Some(self.hir_id());
- match self.kind {
- hir::ForeignItemKind::Fn(decl, _, ref generics) => {
- let mut text = String::new();
- text.push_str("fn ");
-
- let mut sig =
- name_and_generics(text, offset, generics, self.hir_id(), self.ident, scx)?;
-
- sig.text.push('(');
- for i in decl.inputs {
- sig.text.push_str(": ");
- let nested = i.make(offset + sig.text.len(), Some(i.hir_id), scx)?;
- sig.text.push_str(&nested.text);
- sig.text.push(',');
- sig.defs.extend(nested.defs.into_iter());
- sig.refs.extend(nested.refs.into_iter());
- }
- sig.text.push(')');
-
- if let hir::FnRetTy::Return(ref t) = decl.output {
- sig.text.push_str(" -> ");
- let nested = t.make(offset + sig.text.len(), None, scx)?;
- sig.text.push_str(&nested.text);
- sig.defs.extend(nested.defs.into_iter());
- sig.refs.extend(nested.refs.into_iter());
- }
- sig.text.push(';');
-
- Ok(sig)
- }
- hir::ForeignItemKind::Static(ref ty, m) => {
- let mut text = "static ".to_owned();
- if m == Mutability::Mut {
- text.push_str("mut ");
- }
- let name = self.ident.to_string();
- let defs = vec![SigElement {
- id: id_from_def_id(self.owner_id.to_def_id()),
- start: offset + text.len(),
- end: offset + text.len() + name.len(),
- }];
- text.push_str(&name);
- text.push_str(": ");
-
- let ty_sig = ty.make(offset + text.len(), id, scx)?;
- text.push(';');
-
- Ok(extend_sig(ty_sig, text, defs, vec![]))
- }
- hir::ForeignItemKind::Type => {
- let mut text = "type ".to_owned();
- let name = self.ident.to_string();
- let defs = vec![SigElement {
- id: id_from_def_id(self.owner_id.to_def_id()),
- start: offset + text.len(),
- end: offset + text.len() + name.len(),
- }];
- text.push_str(&name);
- text.push(';');
-
- Ok(Signature { text, defs, refs: vec![] })
- }
- }
- }
-}
-
-fn name_and_generics(
- mut text: String,
- offset: usize,
- generics: &hir::Generics<'_>,
- id: hir::HirId,
- name: Ident,
- scx: &SaveContext<'_>,
-) -> Result {
- let name = name.to_string();
- let def = SigElement {
- id: id_from_hir_id(id, scx),
- start: offset + text.len(),
- end: offset + text.len() + name.len(),
- };
- text.push_str(&name);
- let generics: Signature = generics.make(offset + text.len(), Some(id), scx)?;
- // FIXME where clause
- let text = format!("{}{}", text, generics.text);
- Ok(extend_sig(generics, text, vec![def], vec![]))
-}
-
-fn make_assoc_type_signature(
- id: hir::HirId,
- ident: Ident,
- bounds: Option<hir::GenericBounds<'_>>,
- default: Option<&hir::Ty<'_>>,
- scx: &SaveContext<'_>,
-) -> Result {
- let mut text = "type ".to_owned();
- let name = ident.to_string();
- let mut defs = vec![SigElement {
- id: id_from_hir_id(id, scx),
- start: text.len(),
- end: text.len() + name.len(),
- }];
- let mut refs = vec![];
- text.push_str(&name);
- if let Some(bounds) = bounds {
- text.push_str(": ");
- // FIXME should descend into bounds
- text.push_str(&bounds_to_string(bounds));
- }
- if let Some(default) = default {
- text.push_str(" = ");
- let ty_sig = default.make(text.len(), Some(id), scx)?;
- text.push_str(&ty_sig.text);
- defs.extend(ty_sig.defs.into_iter());
- refs.extend(ty_sig.refs.into_iter());
- }
- text.push(';');
- Ok(Signature { text, defs, refs })
-}
-
-fn make_assoc_const_signature(
- id: hir::HirId,
- ident: Symbol,
- ty: &hir::Ty<'_>,
- default: Option<&hir::Expr<'_>>,
- scx: &SaveContext<'_>,
-) -> Result {
- let mut text = "const ".to_owned();
- let name = ident.to_string();
- let mut defs = vec![SigElement {
- id: id_from_hir_id(id, scx),
- start: text.len(),
- end: text.len() + name.len(),
- }];
- let mut refs = vec![];
- text.push_str(&name);
- text.push_str(": ");
-
- let ty_sig = ty.make(text.len(), Some(id), scx)?;
- text.push_str(&ty_sig.text);
- defs.extend(ty_sig.defs.into_iter());
- refs.extend(ty_sig.refs.into_iter());
-
- if let Some(default) = default {
- text.push_str(" = ");
- text.push_str(&id_to_string(&scx.tcx.hir(), default.hir_id));
- }
- text.push(';');
- Ok(Signature { text, defs, refs })
-}
-
-fn make_method_signature(
- id: hir::HirId,
- ident: Ident,
- generics: &hir::Generics<'_>,
- m: &hir::FnSig<'_>,
- scx: &SaveContext<'_>,
-) -> Result {
- // FIXME code dup with function signature
- let mut text = String::new();
- if let hir::Constness::Const = m.header.constness {
- text.push_str("const ");
- }
- if hir::IsAsync::Async == m.header.asyncness {
- text.push_str("async ");
- }
- if let hir::Unsafety::Unsafe = m.header.unsafety {
- text.push_str("unsafe ");
- }
- text.push_str("fn ");
-
- let mut sig = name_and_generics(text, 0, generics, id, ident, scx)?;
-
- sig.text.push('(');
- for i in m.decl.inputs {
- sig.text.push_str(": ");
- let nested = i.make(sig.text.len(), Some(i.hir_id), scx)?;
- sig.text.push_str(&nested.text);
- sig.text.push(',');
- sig.defs.extend(nested.defs.into_iter());
- sig.refs.extend(nested.refs.into_iter());
- }
- sig.text.push(')');
-
- if let hir::FnRetTy::Return(ref t) = m.decl.output {
- sig.text.push_str(" -> ");
- let nested = t.make(sig.text.len(), None, scx)?;
- sig.text.push_str(&nested.text);
- sig.defs.extend(nested.defs.into_iter());
- sig.refs.extend(nested.refs.into_iter());
- }
- sig.text.push_str(" {}");
-
- Ok(sig)
-}
diff --git a/compiler/rustc_save_analysis/src/span_utils.rs b/compiler/rustc_save_analysis/src/span_utils.rs
deleted file mode 100644
index e65d57bb3..000000000
--- a/compiler/rustc_save_analysis/src/span_utils.rs
+++ /dev/null
@@ -1,96 +0,0 @@
-use crate::generated_code;
-use rustc_data_structures::sync::Lrc;
-use rustc_lexer::{tokenize, TokenKind};
-use rustc_session::Session;
-use rustc_span::*;
-
-#[derive(Clone)]
-pub struct SpanUtils<'a> {
- pub sess: &'a Session,
-}
-
-impl<'a> SpanUtils<'a> {
- pub fn new(sess: &'a Session) -> SpanUtils<'a> {
- SpanUtils { sess }
- }
-
- pub fn make_filename_string(&self, file: &SourceFile) -> String {
- match &file.name {
- FileName::Real(RealFileName::LocalPath(path)) => {
- if path.is_absolute() {
- self.sess.source_map().path_mapping().map_prefix(path).0.display().to_string()
- } else {
- self.sess
- .opts
- .working_dir
- .remapped_path_if_available()
- .join(&path)
- .display()
- .to_string()
- }
- }
- filename => filename.prefer_remapped().to_string(),
- }
- }
-
- pub fn snippet(&self, span: Span) -> String {
- match self.sess.source_map().span_to_snippet(span) {
- Ok(s) => s,
- Err(_) => String::new(),
- }
- }
-
- /// Finds the span of `*` token withing the larger `span`.
- pub fn sub_span_of_star(&self, mut span: Span) -> Option<Span> {
- let begin = self.sess.source_map().lookup_byte_offset(span.lo());
- let end = self.sess.source_map().lookup_byte_offset(span.hi());
- // Make the range zero-length if the span is invalid.
- if begin.sf.start_pos != end.sf.start_pos {
- span = span.shrink_to_lo();
- }
-
- let sf = Lrc::clone(&begin.sf);
-
- self.sess.source_map().ensure_source_file_source_present(Lrc::clone(&sf));
- let src =
- sf.src.clone().or_else(|| sf.external_src.borrow().get_source().map(Lrc::clone))?;
- let to_index = |pos: BytePos| -> usize { (pos - sf.start_pos).0 as usize };
- let text = &src[to_index(span.lo())..to_index(span.hi())];
- let start_pos = {
- let mut pos = 0;
- tokenize(text)
- .map(|token| {
- let start = pos;
- pos += token.len;
- (start, token)
- })
- .find(|(_pos, token)| token.kind == TokenKind::Star)?
- .0
- };
- let lo = span.lo() + BytePos(start_pos as u32);
- let hi = lo + BytePos(1);
- Some(span.with_lo(lo).with_hi(hi))
- }
-
- /// Return true if the span is generated code, and
- /// it is not a subspan of the root callsite.
- ///
- /// Used to filter out spans of minimal value,
- /// such as references to macro internal variables.
- pub fn filter_generated(&self, span: Span) -> bool {
- if generated_code(span) {
- return true;
- }
-
- //If the span comes from a fake source_file, filter it.
- !self.sess.source_map().lookup_char_pos(span.lo()).file.is_real_file()
- }
-}
-
-macro_rules! filter {
- ($util: expr, $parent: expr) => {
- if $util.filter_generated($parent) {
- return None;
- }
- };
-}
diff --git a/compiler/rustc_serialize/Cargo.toml b/compiler/rustc_serialize/Cargo.toml
index db0ef7354..c04465719 100644
--- a/compiler/rustc_serialize/Cargo.toml
+++ b/compiler/rustc_serialize/Cargo.toml
@@ -6,7 +6,7 @@ edition = "2021"
[dependencies]
indexmap = "1.9.1"
smallvec = { version = "1.8.1", features = ["union", "may_dangle"] }
-thin-vec = "0.2.9"
+thin-vec = "0.2.12"
[dev-dependencies]
rustc_macros = { path = "../rustc_macros" }
diff --git a/compiler/rustc_serialize/src/serialize.rs b/compiler/rustc_serialize/src/serialize.rs
index 751b209f1..567fe0610 100644
--- a/compiler/rustc_serialize/src/serialize.rs
+++ b/compiler/rustc_serialize/src/serialize.rs
@@ -43,7 +43,6 @@ pub trait Encoder {
fn emit_str(&mut self, v: &str);
fn emit_raw_bytes(&mut self, s: &[u8]);
- // Convenience for the derive macro:
fn emit_enum_variant<F>(&mut self, v_id: usize, f: F)
where
F: FnOnce(&mut Self),
@@ -51,17 +50,6 @@ pub trait Encoder {
self.emit_usize(v_id);
f(self);
}
-
- // We put the field index in a const generic to allow the emit_usize to be
- // compiled into a more efficient form. In practice, the variant index is
- // known at compile-time, and that knowledge allows much more efficient
- // codegen than we'd otherwise get. LLVM isn't always able to make the
- // optimization that would otherwise be necessary here, likely due to the
- // multiple levels of inlining and const-prop that are needed.
- #[inline]
- fn emit_fieldless_enum_variant<const ID: usize>(&mut self) {
- self.emit_usize(ID)
- }
}
// Note: all the methods in this trait are infallible, which may be surprising.
@@ -430,11 +418,6 @@ impl<D: Decoder, T: Decodable<D> + Copy> Decodable<D> for Cell<T> {
}
}
-// FIXME: #15036
-// Should use `try_borrow`, returning an
-// `encoder.error("attempting to Encode borrowed RefCell")`
-// from `encode` when `try_borrow` returns `None`.
-
impl<S: Encoder, T: Encodable<S>> Encodable<S> for RefCell<T> {
fn encode(&self, s: &mut S) {
self.borrow().encode(s);
diff --git a/compiler/rustc_error_messages/locales/en-US/session.ftl b/compiler/rustc_session/locales/en-US.ftl
index bc37d91a7..ff53f22d4 100644
--- a/compiler/rustc_error_messages/locales/en-US/session.ftl
+++ b/compiler/rustc_session/locales/en-US.ftl
@@ -5,7 +5,7 @@ session_incorrect_cgu_reuse_type =
}`{$expected_reuse}`
session_cgu_not_recorded =
- CGU-reuse for `{$cgu_user_name}` is (mangled: `{$cgu_name}`) was not recorded`
+ CGU-reuse for `{$cgu_user_name}` is (mangled: `{$cgu_name}`) was not recorded
session_feature_gate_error = {$explain}
@@ -25,6 +25,8 @@ session_profile_sample_use_file_does_not_exist = file `{$path}` passed to `-C pr
session_target_requires_unwind_tables = target requires unwind tables, they cannot be disabled with `-C force-unwind-tables=no`
+session_instrumentation_not_supported = {$us} instrumentation is not supported for this target
+
session_sanitizer_not_supported = {$us} sanitizer is not supported for this target
session_sanitizers_not_supported = {$us} sanitizers are not supported for this target
@@ -89,3 +91,5 @@ session_int_literal_too_large = integer literal is too large
session_invalid_int_literal_width = invalid width `{$width}` for integer literal
.help = valid widths are 8, 16, 32, 64 and 128
+
+session_optimization_fuel_exhausted = optimization-fuel-exhausted: {$msg}
diff --git a/compiler/rustc_session/src/code_stats.rs b/compiler/rustc_session/src/code_stats.rs
index 1085bce44..551782504 100644
--- a/compiler/rustc_session/src/code_stats.rs
+++ b/compiler/rustc_session/src/code_stats.rs
@@ -20,7 +20,25 @@ pub enum SizeKind {
}
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
+pub enum FieldKind {
+ AdtField,
+ Upvar,
+ GeneratorLocal,
+}
+
+impl std::fmt::Display for FieldKind {
+ fn fmt(&self, w: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ match self {
+ FieldKind::AdtField => write!(w, "field"),
+ FieldKind::Upvar => write!(w, "upvar"),
+ FieldKind::GeneratorLocal => write!(w, "local"),
+ }
+ }
+}
+
+#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
pub struct FieldInfo {
+ pub kind: FieldKind,
pub name: Symbol,
pub offset: u64,
pub size: u64,
@@ -66,7 +84,11 @@ impl CodeStats {
// Sort variants so the largest ones are shown first. A stable sort is
// used here so that source code order is preserved for all variants
// that have the same size.
- variants.sort_by(|info1, info2| info2.size.cmp(&info1.size));
+ // Except for Generators, whose variants are already sorted according to
+ // their yield points in `variant_info_for_generator`.
+ if kind != DataTypeKind::Generator {
+ variants.sort_by(|info1, info2| info2.size.cmp(&info1.size));
+ }
let info = TypeSizeInfo {
kind,
type_description: type_desc.to_string(),
@@ -145,7 +167,7 @@ impl CodeStats {
fields.sort_by_key(|f| (f.offset, f.size));
for field in fields {
- let FieldInfo { ref name, offset, size, align } = field;
+ let FieldInfo { kind, ref name, offset, size, align } = field;
if offset > min_offset {
let pad = offset - min_offset;
@@ -155,16 +177,16 @@ impl CodeStats {
if offset < min_offset {
// If this happens it's probably a union.
println!(
- "print-type-size {indent}field `.{name}`: {size} bytes, \
+ "print-type-size {indent}{kind} `.{name}`: {size} bytes, \
offset: {offset} bytes, \
alignment: {align} bytes"
);
} else if info.packed || offset == min_offset {
- println!("print-type-size {indent}field `.{name}`: {size} bytes");
+ println!("print-type-size {indent}{kind} `.{name}`: {size} bytes");
} else {
// Include field alignment in output only if it caused padding injection
println!(
- "print-type-size {indent}field `.{name}`: {size} bytes, \
+ "print-type-size {indent}{kind} `.{name}`: {size} bytes, \
alignment: {align} bytes"
);
}
diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs
index 586454f76..d4e4ace88 100644
--- a/compiler/rustc_session/src/config.rs
+++ b/compiler/rustc_session/src/config.rs
@@ -24,7 +24,7 @@ use rustc_span::RealFileName;
use rustc_span::SourceFileHashAlgorithm;
use rustc_errors::emitter::HumanReadableErrorType;
-use rustc_errors::{ColorConfig, HandlerFlags};
+use rustc_errors::{ColorConfig, DiagnosticArgValue, HandlerFlags, IntoDiagnosticArg};
use std::collections::btree_map::{
Iter as BTreeMapIter, Keys as BTreeMapKeysIter, Values as BTreeMapValuesIter,
@@ -174,6 +174,25 @@ pub enum InstrumentCoverage {
Off,
}
+/// Settings for `-Z instrument-xray` flag.
+#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
+pub struct InstrumentXRay {
+ /// `-Z instrument-xray=always`, force instrumentation
+ pub always: bool,
+ /// `-Z instrument-xray=never`, disable instrumentation
+ pub never: bool,
+ /// `-Z instrument-xray=ignore-loops`, ignore presence of loops,
+ /// instrument functions based only on instruction count
+ pub ignore_loops: bool,
+ /// `-Z instrument-xray=instruction-threshold=N`, explicitly set instruction threshold
+ /// for instrumentation, or `None` to use compiler's default
+ pub instruction_threshold: Option<usize>,
+ /// `-Z instrument-xray=skip-entry`, do not instrument function entry
+ pub skip_entry: bool,
+ /// `-Z instrument-xray=skip-exit`, do not instrument function exit
+ pub skip_exit: bool,
+}
+
#[derive(Clone, PartialEq, Hash, Debug)]
pub enum LinkerPluginLto {
LinkerPlugin(PathBuf),
@@ -400,6 +419,18 @@ pub enum TrimmedDefPaths {
GoodPath,
}
+#[derive(Clone, Hash)]
+pub enum ResolveDocLinks {
+ /// Do not resolve doc links.
+ None,
+ /// Resolve doc links on exported items only for crate types that have metadata.
+ ExportedMetadata,
+ /// Resolve doc links on exported items.
+ Exported,
+ /// Resolve doc links on all items.
+ All,
+}
+
/// Use tree-based collections to cheaply get a deterministic `Hash` implementation.
/// *Do not* switch `BTreeMap` out for an unsorted container type! That would break
/// dependency tracking for command-line arguments. Also only hash keys, since tracking
@@ -769,6 +800,7 @@ impl Default for Options {
unstable_features: UnstableFeatures::Disallow,
debug_assertions: true,
actually_rustdoc: false,
+ resolve_doc_links: ResolveDocLinks::None,
trimmed_def_paths: TrimmedDefPaths::default(),
cli_forced_codegen_units: None,
cli_forced_local_thinlto_off: false,
@@ -865,13 +897,10 @@ pub enum CrateType {
}
impl CrateType {
- /// When generated, is this crate type an archive?
- pub fn is_archive(&self) -> bool {
- match *self {
- CrateType::Rlib | CrateType::Staticlib => true,
- CrateType::Executable | CrateType::Dylib | CrateType::Cdylib | CrateType::ProcMacro => {
- false
- }
+ pub fn has_metadata(self) -> bool {
+ match self {
+ CrateType::Rlib | CrateType::Dylib | CrateType::ProcMacro => true,
+ CrateType::Executable | CrateType::Cdylib | CrateType::Staticlib => false,
}
}
}
@@ -957,6 +986,7 @@ fn default_configuration(sess: &Session) -> CrateConfig {
if sess.target.has_thread_local {
ret.insert((sym::target_thread_local, None));
}
+ let mut has_atomic = false;
for (i, align) in [
(8, layout.i8_align.abi),
(16, layout.i16_align.abi),
@@ -965,6 +995,7 @@ fn default_configuration(sess: &Session) -> CrateConfig {
(128, layout.i128_align.abi),
] {
if i >= min_atomic_width && i <= max_atomic_width {
+ has_atomic = true;
let mut insert_atomic = |s, align: Align| {
ret.insert((sym::target_has_atomic_load_store, Some(Symbol::intern(s))));
if atomic_cas {
@@ -981,11 +1012,23 @@ fn default_configuration(sess: &Session) -> CrateConfig {
}
}
}
+ if sess.is_nightly_build() && has_atomic {
+ ret.insert((sym::target_has_atomic_load_store, None));
+ if atomic_cas {
+ ret.insert((sym::target_has_atomic, None));
+ }
+ }
let panic_strategy = sess.panic_strategy();
ret.insert((sym::panic, Some(panic_strategy.desc_symbol())));
- for s in sess.opts.unstable_opts.sanitizer {
+ for mut s in sess.opts.unstable_opts.sanitizer {
+ // KASAN should use the same attribute name as ASAN, as it's still ASAN
+ // under the hood
+ if s == SanitizerSet::KERNELADDRESS {
+ s = SanitizerSet::ADDRESS;
+ }
+
let symbol = Symbol::intern(&s.to_string());
ret.insert((sym::sanitize, Some(symbol)));
}
@@ -2202,7 +2245,7 @@ pub fn parse_externs(
early_error(
error_format,
"the `-Z unstable-options` flag must also be passed to \
- enable `--extern options",
+ enable `--extern` options",
);
}
for opt in opts.split(',') {
@@ -2507,7 +2550,7 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options {
}
// Only use this directory if it has a file we can expect to always find.
- if candidate.join("library/std/src/lib.rs").is_file() { Some(candidate) } else { None }
+ candidate.join("library/std/src/lib.rs").is_file().then_some(candidate)
};
let working_dir = std::env::current_dir().unwrap_or_else(|e| {
@@ -2547,6 +2590,7 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options {
libs,
debug_assertions,
actually_rustdoc: false,
+ resolve_doc_links: ResolveDocLinks::ExportedMetadata,
trimmed_def_paths: TrimmedDefPaths::default(),
cli_forced_codegen_units: codegen_units,
cli_forced_local_thinlto_off: disable_local_thinlto,
@@ -2577,6 +2621,7 @@ fn parse_pretty(unstable_opts: &UnstableOptions, efmt: ErrorOutputType) -> Optio
"hir,typed" => Hir(PpHirMode::Typed),
"hir-tree" => HirTree,
"thir-tree" => ThirTree,
+ "thir-flat" => ThirFlat,
"mir" => Mir,
"mir-cfg" => MirCFG,
name => early_error(
@@ -2585,7 +2630,8 @@ fn parse_pretty(unstable_opts: &UnstableOptions, efmt: ErrorOutputType) -> Optio
"argument to `unpretty` must be one of `normal`, `identified`, \
`expanded`, `expanded,identified`, `expanded,hygiene`, \
`ast-tree`, `ast-tree,expanded`, `hir`, `hir,identified`, \
- `hir,typed`, `hir-tree`, `thir-tree`, `mir` or `mir-cfg`; got {name}"
+ `hir,typed`, `hir-tree`, `thir-tree`, `thir-flat`, `mir` or \
+ `mir-cfg`; got {name}"
),
),
};
@@ -2696,6 +2742,12 @@ impl fmt::Display for CrateType {
}
}
+impl IntoDiagnosticArg for CrateType {
+ fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
+ self.to_string().into_diagnostic_arg()
+ }
+}
+
#[derive(Copy, Clone, PartialEq, Debug)]
pub enum PpSourceMode {
/// `-Zunpretty=normal`
@@ -2740,6 +2792,8 @@ pub enum PpMode {
HirTree,
/// `-Zunpretty=thir-tree`
ThirTree,
+ /// `-Zunpretty=thir-flat`
+ ThirFlat,
/// `-Zunpretty=mir`
Mir,
/// `-Zunpretty=mir-cfg`
@@ -2758,6 +2812,7 @@ impl PpMode {
| Hir(_)
| HirTree
| ThirTree
+ | ThirFlat
| Mir
| MirCFG => true,
}
@@ -2767,13 +2822,13 @@ impl PpMode {
match *self {
Source(_) | AstTree(_) => false,
- Hir(_) | HirTree | ThirTree | Mir | MirCFG => true,
+ Hir(_) | HirTree | ThirTree | ThirFlat | Mir | MirCFG => true,
}
}
pub fn needs_analysis(&self) -> bool {
use PpMode::*;
- matches!(*self, Mir | MirCFG | ThirTree)
+ matches!(*self, Mir | MirCFG | ThirTree | ThirFlat)
}
}
@@ -2798,9 +2853,10 @@ impl PpMode {
pub(crate) mod dep_tracking {
use super::{
BranchProtection, CFGuard, CFProtection, CrateType, DebugInfo, ErrorOutputType,
- InstrumentCoverage, LdImpl, LinkerPluginLto, LocationDetail, LtoCli, OomStrategy, OptLevel,
- OutputType, OutputTypes, Passes, SourceFileHashAlgorithm, SplitDwarfKind,
- SwitchWithOptPath, SymbolManglingVersion, TraitSolver, TrimmedDefPaths,
+ InstrumentCoverage, InstrumentXRay, LdImpl, LinkerPluginLto, LocationDetail, LtoCli,
+ OomStrategy, OptLevel, OutputType, OutputTypes, Passes, ResolveDocLinks,
+ SourceFileHashAlgorithm, SplitDwarfKind, SwitchWithOptPath, SymbolManglingVersion,
+ TraitSolver, TrimmedDefPaths,
};
use crate::lint;
use crate::options::WasiExecModel;
@@ -2869,6 +2925,7 @@ pub(crate) mod dep_tracking {
CodeModel,
TlsModel,
InstrumentCoverage,
+ InstrumentXRay,
CrateType,
MergeFunctions,
PanicStrategy,
@@ -2886,6 +2943,7 @@ pub(crate) mod dep_tracking {
TargetTriple,
Edition,
LinkerPluginLto,
+ ResolveDocLinks,
SplitDebuginfo,
SplitDwarfKind,
StackProtector,
diff --git a/compiler/rustc_session/src/cstore.rs b/compiler/rustc_session/src/cstore.rs
index 4ae9a3fae..868ffdf0f 100644
--- a/compiler/rustc_session/src/cstore.rs
+++ b/compiler/rustc_session/src/cstore.rs
@@ -6,10 +6,9 @@ use crate::search_paths::PathKind;
use crate::utils::NativeLibKind;
use crate::Session;
use rustc_ast as ast;
-use rustc_data_structures::sync::{self, MetadataRef, RwLock};
+use rustc_data_structures::sync::{self, AppendOnlyVec, MetadataRef, RwLock};
use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, StableCrateId, LOCAL_CRATE};
use rustc_hir::definitions::{DefKey, DefPath, DefPathHash, Definitions};
-use rustc_index::vec::IndexVec;
use rustc_span::hygiene::{ExpnHash, ExpnId};
use rustc_span::symbol::Symbol;
use rustc_span::Span;
@@ -200,12 +199,12 @@ pub enum ExternCrateSource {
/// At the time of this writing, there is only one backend and one way to store
/// metadata in library -- this trait just serves to decouple rustc_metadata from
/// the archive reader, which depends on LLVM.
-pub trait MetadataLoader {
+pub trait MetadataLoader: std::fmt::Debug {
fn get_rlib_metadata(&self, target: &Target, filename: &Path) -> Result<MetadataRef, String>;
fn get_dylib_metadata(&self, target: &Target, filename: &Path) -> Result<MetadataRef, String>;
}
-pub type MetadataLoaderDyn = dyn MetadataLoader + Sync;
+pub type MetadataLoaderDyn = dyn MetadataLoader + Send + Sync;
/// A store of Rust crates, through which their metadata can be accessed.
///
@@ -250,12 +249,11 @@ pub trait CrateStore: std::fmt::Debug {
fn import_source_files(&self, sess: &Session, cnum: CrateNum);
}
-pub type CrateStoreDyn = dyn CrateStore + sync::Sync;
+pub type CrateStoreDyn = dyn CrateStore + sync::Sync + sync::Send;
-#[derive(Debug)]
pub struct Untracked {
- pub cstore: Box<CrateStoreDyn>,
+ pub cstore: RwLock<Box<CrateStoreDyn>>,
/// Reference span for definitions.
- pub source_span: IndexVec<LocalDefId, Span>,
+ pub source_span: AppendOnlyVec<LocalDefId, Span>,
pub definitions: RwLock<Definitions>,
}
diff --git a/compiler/rustc_session/src/errors.rs b/compiler/rustc_session/src/errors.rs
index f5a72573d..bd32adbbd 100644
--- a/compiler/rustc_session/src/errors.rs
+++ b/compiler/rustc_session/src/errors.rs
@@ -4,7 +4,7 @@ use crate::cgu_reuse_tracker::CguReuse;
use crate::parse::ParseSess;
use rustc_ast::token;
use rustc_ast::util::literal::LitError;
-use rustc_errors::MultiSpan;
+use rustc_errors::{error_code, DiagnosticMessage, EmissionGuarantee, IntoDiagnostic, MultiSpan};
use rustc_macros::Diagnostic;
use rustc_span::{Span, Symbol};
use rustc_target::spec::{SplitDebuginfo, StackProtector, TargetTriple};
@@ -27,12 +27,22 @@ pub struct CguNotRecorded<'a> {
pub cgu_name: &'a str,
}
-#[derive(Diagnostic)]
-#[diag(session_feature_gate_error, code = "E0658")]
-pub struct FeatureGateError<'a> {
- #[primary_span]
+pub struct FeatureGateError {
pub span: MultiSpan,
- pub explain: &'a str,
+ pub explain: DiagnosticMessage,
+}
+
+impl<'a, T: EmissionGuarantee> IntoDiagnostic<'a, T> for FeatureGateError {
+ #[track_caller]
+ fn into_diagnostic(
+ self,
+ handler: &'a rustc_errors::Handler,
+ ) -> rustc_errors::DiagnosticBuilder<'a, T> {
+ let mut diag = handler.struct_diagnostic(self.explain);
+ diag.set_span(self.span);
+ diag.code(error_code!(E0658));
+ diag
+ }
}
#[derive(Subdiagnostic)]
@@ -72,6 +82,12 @@ pub struct ProfileSampleUseFileDoesNotExist<'a> {
pub struct TargetRequiresUnwindTables;
#[derive(Diagnostic)]
+#[diag(session_instrumentation_not_supported)]
+pub struct InstrumentationNotSupported {
+ pub us: String,
+}
+
+#[derive(Diagnostic)]
#[diag(session_sanitizer_not_supported)]
pub struct SanitizerNotSupported {
pub us: String,
@@ -316,11 +332,7 @@ pub fn report_lit_error(sess: &ParseSess, err: LitError, lit: token::Lit, span:
.take_while(|c| *c != 'i' && *c != 'u')
.all(|c| c.to_digit(base).is_some());
- if valid {
- Some(format!("0{}{}", base_char.to_ascii_lowercase(), &suffix[1..]))
- } else {
- None
- }
+ valid.then(|| format!("0{}{}", base_char.to_ascii_lowercase(), &suffix[1..]))
}
let token::Lit { kind, symbol, suffix, .. } = lit;
@@ -375,3 +387,9 @@ pub fn report_lit_error(sess: &ParseSess, err: LitError, lit: token::Lit, span:
}
}
}
+
+#[derive(Diagnostic)]
+#[diag(session_optimization_fuel_exhausted)]
+pub struct OptimisationFuelExhausted {
+ pub msg: String,
+}
diff --git a/compiler/rustc_session/src/filesearch.rs b/compiler/rustc_session/src/filesearch.rs
index b6a328908..f1fbf3821 100644
--- a/compiler/rustc_session/src/filesearch.rs
+++ b/compiler/rustc_session/src/filesearch.rs
@@ -182,7 +182,17 @@ pub fn get_or_default_sysroot() -> Result<PathBuf, String> {
if dir.ends_with(crate::config::host_triple()) {
dir.parent() // chop off `$target`
.and_then(|p| p.parent()) // chop off `rustlib`
- .and_then(|p| p.parent()) // chop off `lib`
+ .and_then(|p| {
+ // chop off `lib` (this could be also $arch dir if the host sysroot uses a
+ // multi-arch layout like Debian or Ubuntu)
+ match p.parent() {
+ Some(p) => match p.file_name() {
+ Some(f) if f == "lib" => p.parent(), // first chop went for $arch, so chop again for `lib`
+ _ => Some(p),
+ },
+ None => None,
+ }
+ })
.map(|s| s.to_owned())
.ok_or(format!(
"Could not move 3 levels upper using `parent()` on {}",
@@ -217,7 +227,7 @@ pub fn get_or_default_sysroot() -> Result<PathBuf, String> {
// Look for the target rustlib directory in the suspected sysroot.
let mut rustlib_path = rustc_target::target_rustlib_path(&p, "dummy");
rustlib_path.pop(); // pop off the dummy target.
- if rustlib_path.exists() { Some(p) } else { None }
+ rustlib_path.exists().then_some(p)
}
None => None,
}
diff --git a/compiler/rustc_session/src/lib.rs b/compiler/rustc_session/src/lib.rs
index 39e871f53..e1f1a5f6d 100644
--- a/compiler/rustc_session/src/lib.rs
+++ b/compiler/rustc_session/src/lib.rs
@@ -18,6 +18,9 @@ pub mod errors;
#[macro_use]
extern crate tracing;
+use rustc_errors::{DiagnosticMessage, SubdiagnosticMessage};
+use rustc_macros::fluent_messages;
+
pub mod cgu_reuse_tracker;
pub mod utils;
pub use lint::{declare_lint, declare_lint_pass, declare_tool_lint, impl_lint_pass};
@@ -39,6 +42,8 @@ pub mod output;
pub use getopts;
+fluent_messages! { "../locales/en-US.ftl" }
+
/// 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`.
diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs
index 7b5fd6cc2..b466a3fcd 100644
--- a/compiler/rustc_session/src/options.rs
+++ b/compiler/rustc_session/src/options.rs
@@ -4,7 +4,7 @@ use crate::early_error;
use crate::lint;
use crate::search_paths::SearchPath;
use crate::utils::NativeLib;
-use rustc_errors::LanguageIdentifier;
+use rustc_errors::{LanguageIdentifier, TerminalUrl};
use rustc_target::spec::{CodeModel, LinkerFlavorCli, MergeFunctions, PanicStrategy, SanitizerSet};
use rustc_target::spec::{
RelocModel, RelroLevel, SplitDebuginfo, StackProtector, TargetTriple, TlsModel,
@@ -169,6 +169,8 @@ top_level_options!(
/// is currently just a hack and will be removed eventually, so please
/// try to not rely on this too much.
actually_rustdoc: bool [TRACKED],
+ /// Whether name resolver should resolve documentation links.
+ resolve_doc_links: ResolveDocLinks [TRACKED],
/// Control path trimming.
trimmed_def_paths: TrimmedDefPaths [TRACKED],
@@ -349,7 +351,7 @@ fn build_options<O: Default>(
#[allow(non_upper_case_globals)]
mod desc {
pub const parse_no_flag: &str = "no value";
- pub const parse_bool: &str = "one of: `y`, `yes`, `on`, `n`, `no`, or `off`";
+ pub const parse_bool: &str = "one of: `y`, `yes`, `on`, `true`, `n`, `no`, `off` or `false`";
pub const parse_opt_bool: &str = parse_bool;
pub const parse_string: &str = "a string";
pub const parse_opt_string: &str = parse_string;
@@ -368,7 +370,7 @@ mod desc {
pub const parse_opt_panic_strategy: &str = parse_panic_strategy;
pub const parse_oom_strategy: &str = "either `panic` or `abort`";
pub const parse_relro_level: &str = "one of: `full`, `partial`, or `off`";
- pub const parse_sanitizers: &str = "comma separated list of sanitizers: `address`, `cfi`, `hwaddress`, `kcfi`, `leak`, `memory`, `memtag`, `shadow-call-stack`, or `thread`";
+ pub const parse_sanitizers: &str = "comma separated list of sanitizers: `address`, `cfi`, `hwaddress`, `kcfi`, `kernel-address`, `leak`, `memory`, `memtag`, `shadow-call-stack`, or `thread`";
pub const parse_sanitizer_memory_track_origins: &str = "0, 1, or 2";
pub const parse_cfguard: &str =
"either a boolean (`yes`, `no`, `on`, `off`, etc), `checks`, or `nochecks`";
@@ -380,6 +382,7 @@ mod desc {
pub const parse_dump_mono_stats: &str = "`markdown` (default) or `json`";
pub const parse_instrument_coverage: &str =
"`all` (default), `except-unused-generics`, `except-unused-functions`, or `off`";
+ pub const parse_instrument_xray: &str = "either a boolean (`yes`, `no`, `on`, `off`, etc), or a comma separated list of settings: `always` or `never` (mutually exclusive), `ignore-loops`, `instruction-threshold=N`, `skip-entry`, `skip-exit`";
pub const parse_unpretty: &str = "`string` or `string=string`";
pub const parse_treat_err_as_bug: &str = "either no value or a number bigger than 0";
pub const parse_trait_solver: &str =
@@ -399,6 +402,8 @@ mod desc {
pub const parse_code_model: &str = "one of supported code models (`rustc --print code-models`)";
pub const parse_tls_model: &str = "one of supported TLS models (`rustc --print tls-models`)";
pub const parse_target_feature: &str = parse_string;
+ pub const parse_terminal_url: &str =
+ "either a boolean (`yes`, `no`, `on`, `off`, etc), or `auto`";
pub const parse_wasi_exec_model: &str = "either `command` or `reactor`";
pub const parse_split_debuginfo: &str =
"one of supported split-debuginfo modes (`off`, `packed`, or `unpacked`)";
@@ -432,11 +437,11 @@ mod parse {
/// Use this for any boolean option that has a static default.
pub(crate) fn parse_bool(slot: &mut bool, v: Option<&str>) -> bool {
match v {
- Some("y") | Some("yes") | Some("on") | None => {
+ Some("y") | Some("yes") | Some("on") | Some("true") | None => {
*slot = true;
true
}
- Some("n") | Some("no") | Some("off") => {
+ Some("n") | Some("no") | Some("off") | Some("false") => {
*slot = false;
true
}
@@ -449,11 +454,11 @@ mod parse {
/// other factors, such as other options, or target options.)
pub(crate) fn parse_opt_bool(slot: &mut Option<bool>, v: Option<&str>) -> bool {
match v {
- Some("y") | Some("yes") | Some("on") | None => {
+ Some("y") | Some("yes") | Some("on") | Some("true") | None => {
*slot = Some(true);
true
}
- Some("n") | Some("no") | Some("off") => {
+ Some("n") | Some("no") | Some("off") | Some("false") => {
*slot = Some(false);
true
}
@@ -679,6 +684,7 @@ mod parse {
"address" => SanitizerSet::ADDRESS,
"cfi" => SanitizerSet::CFI,
"kcfi" => SanitizerSet::KCFI,
+ "kernel-address" => SanitizerSet::KERNELADDRESS,
"leak" => SanitizerSet::LEAK,
"memory" => SanitizerSet::MEMORY,
"memtag" => SanitizerSet::MEMTAG,
@@ -804,7 +810,7 @@ mod parse {
if v.is_some() {
let mut bool_arg = None;
if parse_opt_bool(&mut bool_arg, v) {
- *slot = if bool_arg.unwrap() { Some(MirSpanview::Statement) } else { None };
+ *slot = bool_arg.unwrap().then_some(MirSpanview::Statement);
return true;
}
}
@@ -845,7 +851,7 @@ mod parse {
if v.is_some() {
let mut bool_arg = None;
if parse_opt_bool(&mut bool_arg, v) {
- *slot = if bool_arg.unwrap() { Some(InstrumentCoverage::All) } else { None };
+ *slot = bool_arg.unwrap().then_some(InstrumentCoverage::All);
return true;
}
}
@@ -869,6 +875,68 @@ mod parse {
true
}
+ pub(crate) fn parse_instrument_xray(
+ slot: &mut Option<InstrumentXRay>,
+ v: Option<&str>,
+ ) -> bool {
+ if v.is_some() {
+ let mut bool_arg = None;
+ if parse_opt_bool(&mut bool_arg, v) {
+ *slot = if bool_arg.unwrap() { Some(InstrumentXRay::default()) } else { None };
+ return true;
+ }
+ }
+
+ let mut options = slot.get_or_insert_default();
+ let mut seen_always = false;
+ let mut seen_never = false;
+ let mut seen_ignore_loops = false;
+ let mut seen_instruction_threshold = false;
+ let mut seen_skip_entry = false;
+ let mut seen_skip_exit = false;
+ for option in v.into_iter().map(|v| v.split(',')).flatten() {
+ match option {
+ "always" if !seen_always && !seen_never => {
+ options.always = true;
+ options.never = false;
+ seen_always = true;
+ }
+ "never" if !seen_never && !seen_always => {
+ options.never = true;
+ options.always = false;
+ seen_never = true;
+ }
+ "ignore-loops" if !seen_ignore_loops => {
+ options.ignore_loops = true;
+ seen_ignore_loops = true;
+ }
+ option
+ if option.starts_with("instruction-threshold")
+ && !seen_instruction_threshold =>
+ {
+ let Some(("instruction-threshold", n)) = option.split_once('=') else {
+ return false;
+ };
+ match n.parse() {
+ Ok(n) => options.instruction_threshold = Some(n),
+ Err(_) => return false,
+ }
+ seen_instruction_threshold = true;
+ }
+ "skip-entry" if !seen_skip_entry => {
+ options.skip_entry = true;
+ seen_skip_entry = true;
+ }
+ "skip-exit" if !seen_skip_exit => {
+ options.skip_exit = true;
+ seen_skip_exit = true;
+ }
+ _ => return false,
+ }
+ }
+ true
+ }
+
pub(crate) fn parse_treat_err_as_bug(slot: &mut Option<NonZeroUsize>, v: Option<&str>) -> bool {
match v {
Some(s) => {
@@ -979,6 +1047,16 @@ mod parse {
true
}
+ pub(crate) fn parse_terminal_url(slot: &mut TerminalUrl, v: Option<&str>) -> bool {
+ *slot = match v {
+ Some("on" | "" | "yes" | "y") | None => TerminalUrl::Yes,
+ Some("off" | "no" | "n") => TerminalUrl::No,
+ Some("auto") => TerminalUrl::Auto,
+ _ => return false,
+ };
+ true
+ }
+
pub(crate) fn parse_symbol_mangling_version(
slot: &mut Option<SymbolManglingVersion>,
v: Option<&str>,
@@ -1290,6 +1368,8 @@ options! {
(default: no)"),
drop_tracking: bool = (false, parse_bool, [TRACKED],
"enables drop tracking in generators (default: no)"),
+ drop_tracking_mir: bool = (false, parse_bool, [TRACKED],
+ "enables drop tracking on MIR in generators (default: no)"),
dual_proc_macros: bool = (false, parse_bool, [TRACKED],
"load proc macros for both target and host, but only link to the target (default: no)"),
dump_dep_graph: bool = (false, parse_bool, [UNTRACKED],
@@ -1395,10 +1475,22 @@ options! {
`=off` (default)"),
instrument_mcount: bool = (false, parse_bool, [TRACKED],
"insert function instrument code for mcount-based tracing (default: no)"),
+ instrument_xray: Option<InstrumentXRay> = (None, parse_instrument_xray, [TRACKED],
+ "insert function instrument code for XRay-based tracing (default: no)
+ Optional extra settings:
+ `=always`
+ `=never`
+ `=ignore-loops`
+ `=instruction-threshold=N`
+ `=skip-entry`
+ `=skip-exit`
+ Multiple options can be combined with commas."),
keep_hygiene_data: bool = (false, parse_bool, [UNTRACKED],
"keep hygiene data after analysis (default: no)"),
layout_seed: Option<u64> = (None, parse_opt_number, [TRACKED],
"seed layout randomization"),
+ link_directives: bool = (true, parse_bool, [TRACKED],
+ "honor #[link] directives in the compiled crate (default: yes)"),
link_native_libraries: bool = (true, parse_bool, [UNTRACKED],
"link native libraries in the linker invocation (default: yes)"),
link_only: bool = (false, parse_bool, [TRACKED],
@@ -1411,8 +1503,9 @@ options! {
"what location details should be tracked when using caller_location, either \
`none`, or a comma separated list of location details, for which \
valid options are `file`, `line`, and `column` (default: `file,line,column`)"),
- log_backtrace: Option<String> = (None, parse_opt_string, [TRACKED],
- "add a backtrace along with logging"),
+ lower_impl_trait_in_trait_to_assoc_ty: bool = (false, parse_bool, [TRACKED],
+ "modify the lowering strategy for `impl Trait` in traits so that they are lowered to \
+ generic associated types"),
ls: bool = (false, parse_bool, [UNTRACKED],
"list the symbols defined by a library crate (default: no)"),
macro_backtrace: bool = (false, parse_bool, [UNTRACKED],
@@ -1479,8 +1572,6 @@ options! {
"parse only; do not compile, assemble, or link (default: no)"),
perf_stats: bool = (false, parse_bool, [UNTRACKED],
"print some performance-related statistics (default: no)"),
- pick_stable_methods_before_any_unstable: bool = (true, parse_bool, [TRACKED],
- "try to pick stable methods first before picking any unstable methods (default: yes)"),
plt: Option<bool> = (None, parse_opt_bool, [TRACKED],
"whether to use the PLT when calling into shared libraries;
only has effect for PIC code on systems with ELF binaries
@@ -1542,9 +1633,6 @@ options! {
saturating_float_casts: Option<bool> = (None, parse_opt_bool, [TRACKED],
"make float->int casts UB-free: numbers outside the integer type's range are clipped to \
the max/min integer respectively, and NaN is mapped to 0 (default: yes)"),
- save_analysis: bool = (false, parse_bool, [UNTRACKED],
- "write syntax and type analysis (in JSON format) information, in \
- addition to normal output (default: no)"),
self_profile: SwitchWithOptPath = (SwitchWithOptPath::Disabled,
parse_switch_with_opt_path, [UNTRACKED],
"run the self profiler and output the raw event data"),
@@ -1600,6 +1688,8 @@ options! {
"show extended diagnostic help (default: no)"),
temps_dir: Option<String> = (None, parse_opt_string, [UNTRACKED],
"the directory the intermediate files are written to"),
+ terminal_urls: TerminalUrl = (TerminalUrl::No, parse_terminal_url, [UNTRACKED],
+ "use the OSC 8 hyperlink terminal specification to print hyperlinks in the compiler output"),
#[rustc_lint_opt_deny_field_access("use `Session::lto` instead of this field")]
thinlto: Option<bool> = (None, parse_opt_bool, [TRACKED],
"enable ThinLTO when possible"),
@@ -1616,6 +1706,8 @@ options! {
"measure time of each LLVM pass (default: no)"),
time_passes: bool = (false, parse_bool, [UNTRACKED],
"measure time of each rustc pass (default: no)"),
+ tiny_const_eval_limit: bool = (false, parse_bool, [TRACKED],
+ "sets a tiny, non-configurable limit for const eval; useful for compiler tests"),
#[rustc_lint_opt_deny_field_access("use `Session::tls_model` instead of this field")]
tls_model: Option<TlsModel> = (None, parse_tls_model, [TRACKED],
"choose the TLS model to use (`rustc --print tls-models` for details)"),
diff --git a/compiler/rustc_session/src/parse.rs b/compiler/rustc_session/src/parse.rs
index 2aa8ca9e4..4e8c3f73e 100644
--- a/compiler/rustc_session/src/parse.rs
+++ b/compiler/rustc_session/src/parse.rs
@@ -88,7 +88,7 @@ pub fn feature_err<'a>(
sess: &'a ParseSess,
feature: Symbol,
span: impl Into<MultiSpan>,
- explain: &str,
+ explain: impl Into<DiagnosticMessage>,
) -> DiagnosticBuilder<'a, ErrorGuaranteed> {
feature_err_issue(sess, feature, span, GateIssue::Language, explain)
}
@@ -103,7 +103,7 @@ pub fn feature_err_issue<'a>(
feature: Symbol,
span: impl Into<MultiSpan>,
issue: GateIssue,
- explain: &str,
+ explain: impl Into<DiagnosticMessage>,
) -> DiagnosticBuilder<'a, ErrorGuaranteed> {
let span = span.into();
@@ -114,7 +114,7 @@ pub fn feature_err_issue<'a>(
.map(|err| err.cancel());
}
- let mut err = sess.create_err(FeatureGateError { span, explain });
+ let mut err = sess.create_err(FeatureGateError { span, explain: explain.into() });
add_feature_diagnostics_for_issue(&mut err, sess, feature, issue);
err
}
@@ -226,8 +226,8 @@ pub struct ParseSess {
impl ParseSess {
/// Used for testing.
- pub fn new(file_path_mapping: FilePathMapping) -> Self {
- let fallback_bundle = fallback_fluent_bundle(rustc_errors::DEFAULT_LOCALE_RESOURCES, false);
+ pub fn new(locale_resources: Vec<&'static str>, file_path_mapping: FilePathMapping) -> Self {
+ let fallback_bundle = fallback_fluent_bundle(locale_resources, false);
let sm = Lrc::new(SourceMap::new(file_path_mapping));
let handler = Handler::with_tty_emitter(
ColorConfig::Auto,
@@ -265,7 +265,7 @@ impl ParseSess {
}
pub fn with_silent_emitter(fatal_note: Option<String>) -> Self {
- let fallback_bundle = fallback_fluent_bundle(rustc_errors::DEFAULT_LOCALE_RESOURCES, false);
+ let fallback_bundle = fallback_fluent_bundle(Vec::new(), false);
let sm = Lrc::new(SourceMap::new(FilePathMapping::empty()));
let fatal_handler =
Handler::with_tty_emitter(ColorConfig::Auto, false, None, None, None, fallback_bundle);
diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs
index 95f199de6..12634f671 100644
--- a/compiler/rustc_session/src/session.rs
+++ b/compiler/rustc_session/src/session.rs
@@ -1,16 +1,9 @@
use crate::cgu_reuse_tracker::CguReuseTracker;
use crate::code_stats::CodeStats;
-pub use crate::code_stats::{DataTypeKind, FieldInfo, SizeKind, VariantInfo};
+pub use crate::code_stats::{DataTypeKind, FieldInfo, FieldKind, SizeKind, VariantInfo};
use crate::config::Input;
use crate::config::{self, CrateType, InstrumentCoverage, OptLevel, OutputType, SwitchWithOptPath};
-use crate::errors::{
- BranchProtectionRequiresAArch64, CannotEnableCrtStaticLinux, CannotMixAndMatchSanitizers,
- LinkerPluginToWindowsNotSupported, NotCircumventFeature, ProfileSampleUseFileDoesNotExist,
- ProfileUseFileDoesNotExist, SanitizerCfiEnabled, SanitizerNotSupported, SanitizersNotSupported,
- SkippingConstChecks, SplitDebugInfoUnstablePlatform, StackProtectorNotSupportedForTarget,
- TargetRequiresUnwindTables, UnleashedFeatureHelp, UnstableVirtualFunctionElimination,
- UnsupportedDwarfVersion,
-};
+use crate::errors;
use crate::parse::{add_feature_diagnostics, ParseSess};
use crate::search_paths::{PathKind, SearchPath};
use crate::{filesearch, lint};
@@ -31,6 +24,7 @@ use rustc_errors::registry::Registry;
use rustc_errors::{
error_code, fallback_fluent_bundle, DiagnosticBuilder, DiagnosticId, DiagnosticMessage,
ErrorGuaranteed, FluentBundle, IntoDiagnostic, LazyFallbackBundle, MultiSpan, Noted,
+ TerminalUrl,
};
use rustc_macros::HashStable_Generic;
pub use rustc_span::def_id::StableCrateId;
@@ -163,7 +157,7 @@ pub struct Session {
/// `-C metadata` arguments passed to the compiler. Its value forms a unique
/// global identifier for the crate. It is used to allow multiple crates
/// with the same name to coexist. See the
- /// `rustc_codegen_llvm::back::symbol_names` module for more information.
+ /// `rustc_symbol_mangling` crate for more information.
pub stable_crate_id: OnceCell<StableCrateId>,
features: OnceCell<rustc_feature::Features>,
@@ -245,15 +239,15 @@ impl Session {
if !unleashed_features.is_empty() {
let mut must_err = false;
// Create a diagnostic pointing at where things got unleashed.
- self.emit_warning(SkippingConstChecks {
+ self.emit_warning(errors::SkippingConstChecks {
unleashed_features: unleashed_features
.iter()
.map(|(span, gate)| {
gate.map(|gate| {
must_err = true;
- UnleashedFeatureHelp::Named { span: *span, gate }
+ errors::UnleashedFeatureHelp::Named { span: *span, gate }
})
- .unwrap_or(UnleashedFeatureHelp::Unnamed { span: *span })
+ .unwrap_or(errors::UnleashedFeatureHelp::Unnamed { span: *span })
})
.collect(),
});
@@ -261,7 +255,7 @@ impl Session {
// If we should err, make sure we did.
if must_err && self.has_errors().is_none() {
// We have skipped a feature gate, and not run into other errors... reject.
- self.emit_err(NotCircumventFeature);
+ self.emit_err(errors::NotCircumventFeature);
}
}
}
@@ -483,6 +477,8 @@ impl Session {
self.diagnostic().span_err_with_code(sp, msg, code)
}
#[rustc_lint_diagnostics]
+ #[allow(rustc::untranslatable_diagnostic)]
+ #[allow(rustc::diagnostic_outside_of_impl)]
pub fn err(&self, msg: impl Into<DiagnosticMessage>) -> ErrorGuaranteed {
self.diagnostic().err(msg)
}
@@ -583,12 +579,16 @@ impl Session {
))
}
}
+
+ #[rustc_lint_diagnostics]
#[allow(rustc::untranslatable_diagnostic)]
#[allow(rustc::diagnostic_outside_of_impl)]
#[track_caller]
pub fn span_warn<S: Into<MultiSpan>>(&self, sp: S, msg: impl Into<DiagnosticMessage>) {
self.diagnostic().span_warn(sp, msg)
}
+
+ #[rustc_lint_diagnostics]
#[allow(rustc::untranslatable_diagnostic)]
#[allow(rustc::diagnostic_outside_of_impl)]
pub fn span_warn_with_code<S: Into<MultiSpan>>(
@@ -599,6 +599,10 @@ impl Session {
) {
self.diagnostic().span_warn_with_code(sp, msg, code)
}
+
+ #[rustc_lint_diagnostics]
+ #[allow(rustc::untranslatable_diagnostic)]
+ #[allow(rustc::diagnostic_outside_of_impl)]
pub fn warn(&self, msg: impl Into<DiagnosticMessage>) {
self.diagnostic().warn(msg)
}
@@ -641,11 +645,17 @@ impl Session {
self.diagnostic().delay_good_path_bug(msg)
}
+ #[rustc_lint_diagnostics]
+ #[allow(rustc::untranslatable_diagnostic)]
+ #[allow(rustc::diagnostic_outside_of_impl)]
pub fn note_without_error(&self, msg: impl Into<DiagnosticMessage>) {
self.diagnostic().note_without_error(msg)
}
#[track_caller]
+ #[rustc_lint_diagnostics]
+ #[allow(rustc::untranslatable_diagnostic)]
+ #[allow(rustc::diagnostic_outside_of_impl)]
pub fn span_note_without_error<S: Into<MultiSpan>>(
&self,
sp: S,
@@ -653,6 +663,8 @@ impl Session {
) {
self.diagnostic().span_note_without_error(sp, msg)
}
+
+ #[rustc_lint_diagnostics]
#[allow(rustc::untranslatable_diagnostic)]
#[allow(rustc::diagnostic_outside_of_impl)]
pub fn struct_note_without_error(
@@ -870,10 +882,14 @@ impl Session {
/// We want to know if we're allowed to do an optimization for crate foo from -z fuel=foo=n.
/// This expends fuel if applicable, and records fuel if applicable.
- pub fn consider_optimizing<T: Fn() -> String>(&self, crate_name: &str, msg: T) -> bool {
+ pub fn consider_optimizing(
+ &self,
+ get_crate_name: impl Fn() -> Symbol,
+ msg: impl Fn() -> String,
+ ) -> bool {
let mut ret = true;
if let Some((ref c, _)) = self.opts.unstable_opts.fuel {
- if c == crate_name {
+ if c == get_crate_name().as_str() {
assert_eq!(self.threads(), 1);
let mut fuel = self.optimization_fuel.lock();
ret = fuel.remaining != 0;
@@ -882,7 +898,7 @@ impl Session {
// 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()));
+ self.emit_warning(errors::OptimisationFuelExhausted { msg: msg() });
}
fuel.out_of_fuel = true;
} else if fuel.remaining > 0 {
@@ -891,7 +907,7 @@ impl Session {
}
}
if let Some(ref c) = self.opts.unstable_opts.print_fuel {
- if c == crate_name {
+ if c == get_crate_name().as_str() {
assert_eq!(self.threads(), 1);
self.print_fuel.fetch_add(1, SeqCst);
}
@@ -899,23 +915,24 @@ impl Session {
ret
}
- pub fn rust_2015(&self) -> bool {
- self.edition() == Edition::Edition2015
+ /// Is this edition 2015?
+ pub fn is_rust_2015(&self) -> bool {
+ self.edition().is_rust_2015()
}
/// Are we allowed to use features from the Rust 2018 edition?
pub fn rust_2018(&self) -> bool {
- self.edition() >= Edition::Edition2018
+ self.edition().rust_2018()
}
/// Are we allowed to use features from the Rust 2021 edition?
pub fn rust_2021(&self) -> bool {
- self.edition() >= Edition::Edition2021
+ self.edition().rust_2021()
}
/// Are we allowed to use features from the Rust 2024 edition?
pub fn rust_2024(&self) -> bool {
- self.edition() >= Edition::Edition2024
+ self.edition().rust_2024()
}
/// Returns `true` if we cannot skip the PLT for shared library calls.
@@ -941,10 +958,10 @@ impl Session {
/// Checks if LLVM lifetime markers should be emitted.
pub fn emit_lifetime_markers(&self) -> bool {
self.opts.optimize != config::OptLevel::No
- // AddressSanitizer uses lifetimes to detect use after scope bugs.
+ // AddressSanitizer and KernelAddressSanitizer uses lifetimes to detect use after scope bugs.
// MemorySanitizer uses lifetimes to detect use of uninitialized stack variables.
// HWAddressSanitizer will use lifetimes to detect use after scope bugs in the future.
- || self.opts.unstable_opts.sanitizer.intersects(SanitizerSet::ADDRESS | SanitizerSet::MEMORY | SanitizerSet::HWADDRESS)
+ || self.opts.unstable_opts.sanitizer.intersects(SanitizerSet::ADDRESS | SanitizerSet::KERNELADDRESS | SanitizerSet::MEMORY | SanitizerSet::HWADDRESS)
}
pub fn is_proc_macro_attr(&self, attr: &Attribute) -> bool {
@@ -1261,6 +1278,19 @@ fn default_emitter(
) -> Box<dyn Emitter + sync::Send> {
let macro_backtrace = sopts.unstable_opts.macro_backtrace;
let track_diagnostics = sopts.unstable_opts.track_diagnostics;
+ let terminal_url = match sopts.unstable_opts.terminal_urls {
+ TerminalUrl::Auto => {
+ match (std::env::var("COLORTERM").as_deref(), std::env::var("TERM").as_deref()) {
+ (Ok("truecolor"), Ok("xterm-256color"))
+ if sopts.unstable_features.is_nightly_build() =>
+ {
+ TerminalUrl::Yes
+ }
+ _ => TerminalUrl::No,
+ }
+ }
+ t => t,
+ };
match sopts.error_format {
config::ErrorOutputType::HumanReadable(kind) => {
let (short, color_config) = kind.unzip();
@@ -1285,6 +1315,7 @@ fn default_emitter(
sopts.diagnostic_width,
macro_backtrace,
track_diagnostics,
+ terminal_url,
);
Box::new(emitter.ui_testing(sopts.unstable_opts.ui_testing))
}
@@ -1300,6 +1331,7 @@ fn default_emitter(
sopts.diagnostic_width,
macro_backtrace,
track_diagnostics,
+ terminal_url,
)
.ui_testing(sopts.unstable_opts.ui_testing),
),
@@ -1313,6 +1345,7 @@ pub fn build_session(
io: CompilerIO,
bundle: Option<Lrc<rustc_errors::FluentBundle>>,
registry: rustc_errors::registry::Registry,
+ fluent_resources: Vec<&'static str>,
driver_lint_caps: FxHashMap<lint::LintId, lint::Level>,
file_loader: Option<Box<dyn FileLoader + Send + Sync + 'static>>,
target_override: Option<Target>,
@@ -1357,7 +1390,7 @@ pub fn build_session(
));
let fallback_bundle = fallback_fluent_bundle(
- rustc_errors::DEFAULT_LOCALE_RESOURCES,
+ fluent_resources,
sopts.unstable_opts.translate_directionality_markers,
);
let emitter = default_emitter(&sopts, registry, source_map.clone(), bundle, fallback_bundle);
@@ -1482,28 +1515,28 @@ fn validate_commandline_args_with_session_available(sess: &Session) {
&& sess.opts.cg.prefer_dynamic
&& sess.target.is_like_windows
{
- sess.emit_err(LinkerPluginToWindowsNotSupported);
+ sess.emit_err(errors::LinkerPluginToWindowsNotSupported);
}
// Make sure that any given profiling data actually exists so LLVM can't
// decide to silently skip PGO.
if let Some(ref path) = sess.opts.cg.profile_use {
if !path.exists() {
- sess.emit_err(ProfileUseFileDoesNotExist { path });
+ sess.emit_err(errors::ProfileUseFileDoesNotExist { path });
}
}
// Do the same for sample profile data.
if let Some(ref path) = sess.opts.unstable_opts.profile_sample_use {
if !path.exists() {
- sess.emit_err(ProfileSampleUseFileDoesNotExist { path });
+ sess.emit_err(errors::ProfileSampleUseFileDoesNotExist { path });
}
}
// 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 {
- sess.emit_err(TargetRequiresUnwindTables);
+ sess.emit_err(errors::TargetRequiresUnwindTables);
}
}
@@ -1513,16 +1546,18 @@ fn validate_commandline_args_with_session_available(sess: &Session) {
match unsupported_sanitizers.into_iter().count() {
0 => {}
1 => {
- sess.emit_err(SanitizerNotSupported { us: unsupported_sanitizers.to_string() });
+ sess.emit_err(errors::SanitizerNotSupported { us: unsupported_sanitizers.to_string() });
}
_ => {
- sess.emit_err(SanitizersNotSupported { us: unsupported_sanitizers.to_string() });
+ sess.emit_err(errors::SanitizersNotSupported {
+ us: unsupported_sanitizers.to_string(),
+ });
}
}
// Cannot mix and match sanitizers.
let mut sanitizer_iter = sess.opts.unstable_opts.sanitizer.into_iter();
if let (Some(first), Some(second)) = (sanitizer_iter.next(), sanitizer_iter.next()) {
- sess.emit_err(CannotMixAndMatchSanitizers {
+ sess.emit_err(errors::CannotMixAndMatchSanitizers {
first: first.to_string(),
second: second.to_string(),
});
@@ -1530,22 +1565,22 @@ fn validate_commandline_args_with_session_available(sess: &Session) {
// Cannot enable crt-static with sanitizers on Linux
if sess.crt_static(None) && !sess.opts.unstable_opts.sanitizer.is_empty() {
- sess.emit_err(CannotEnableCrtStaticLinux);
+ sess.emit_err(errors::CannotEnableCrtStaticLinux);
}
// LLVM CFI and VFE both require LTO.
if sess.lto() != config::Lto::Fat {
if sess.is_sanitizer_cfi_enabled() {
- sess.emit_err(SanitizerCfiEnabled);
+ sess.emit_err(errors::SanitizerCfiEnabled);
}
if sess.opts.unstable_opts.virtual_function_elimination {
- sess.emit_err(UnstableVirtualFunctionElimination);
+ sess.emit_err(errors::UnstableVirtualFunctionElimination);
}
}
// LLVM CFI and KCFI are mutually exclusive
if sess.is_sanitizer_cfi_enabled() && sess.is_sanitizer_kcfi_enabled() {
- sess.emit_err(CannotMixAndMatchSanitizers {
+ sess.emit_err(errors::CannotMixAndMatchSanitizers {
first: "cfi".to_string(),
second: "kcfi".to_string(),
});
@@ -1553,7 +1588,7 @@ fn validate_commandline_args_with_session_available(sess: &Session) {
if sess.opts.unstable_opts.stack_protector != StackProtector::None {
if !sess.target.options.supports_stack_protector {
- sess.emit_warning(StackProtectorNotSupportedForTarget {
+ sess.emit_warning(errors::StackProtectorNotSupportedForTarget {
stack_protector: sess.opts.unstable_opts.stack_protector,
target_triple: &sess.opts.target_triple,
});
@@ -1561,19 +1596,23 @@ fn validate_commandline_args_with_session_available(sess: &Session) {
}
if sess.opts.unstable_opts.branch_protection.is_some() && sess.target.arch != "aarch64" {
- sess.emit_err(BranchProtectionRequiresAArch64);
+ sess.emit_err(errors::BranchProtectionRequiresAArch64);
}
if let Some(dwarf_version) = sess.opts.unstable_opts.dwarf_version {
if dwarf_version > 5 {
- sess.emit_err(UnsupportedDwarfVersion { dwarf_version });
+ sess.emit_err(errors::UnsupportedDwarfVersion { dwarf_version });
}
}
if !sess.target.options.supported_split_debuginfo.contains(&sess.split_debuginfo())
&& !sess.opts.unstable_opts.unstable_options
{
- sess.emit_err(SplitDebugInfoUnstablePlatform { debuginfo: sess.split_debuginfo() });
+ sess.emit_err(errors::SplitDebugInfoUnstablePlatform { debuginfo: sess.split_debuginfo() });
+ }
+
+ if sess.opts.unstable_opts.instrument_xray.is_some() && !sess.target.options.supports_xray {
+ sess.emit_err(errors::InstrumentationNotSupported { us: "XRay".to_string() });
}
}
@@ -1596,7 +1635,10 @@ pub enum IncrCompSession {
}
fn early_error_handler(output: config::ErrorOutputType) -> rustc_errors::Handler {
- let fallback_bundle = fallback_fluent_bundle(rustc_errors::DEFAULT_LOCALE_RESOURCES, false);
+ // FIXME(#100717): early errors aren't translated at the moment, so this is fine, but it will
+ // need to reference every crate that might emit an early error for translation to work.
+ let fallback_bundle =
+ fallback_fluent_bundle(vec![rustc_errors::DEFAULT_LOCALE_RESOURCE], false);
let emitter: Box<dyn Emitter + sync::Send> = match output {
config::ErrorOutputType::HumanReadable(kind) => {
let (short, color_config) = kind.unzip();
@@ -1610,6 +1652,7 @@ fn early_error_handler(output: config::ErrorOutputType) -> rustc_errors::Handler
None,
false,
false,
+ TerminalUrl::No,
))
}
config::ErrorOutputType::Json { pretty, json_rendered } => Box::new(JsonEmitter::basic(
@@ -1620,6 +1663,7 @@ fn early_error_handler(output: config::ErrorOutputType) -> rustc_errors::Handler
None,
false,
false,
+ TerminalUrl::No,
)),
};
rustc_errors::Handler::with_emitter(true, None, emitter)
diff --git a/compiler/rustc_span/src/def_id.rs b/compiler/rustc_span/src/def_id.rs
index 7c5e1427d..162c15574 100644
--- a/compiler/rustc_span/src/def_id.rs
+++ b/compiler/rustc_span/src/def_id.rs
@@ -119,6 +119,12 @@ impl DefPathHash {
}
}
+impl Default for DefPathHash {
+ fn default() -> Self {
+ DefPathHash(Fingerprint::ZERO)
+ }
+}
+
impl Borrow<Fingerprint> for DefPathHash {
#[inline]
fn borrow(&self) -> &Fingerprint {
@@ -229,7 +235,7 @@ impl<D: Decoder> Decodable<D> for DefIndex {
pub struct DefId {
// cfg-ing the order of fields so that the `DefIndex` which is high entropy always ends up in
// the lower bits no matter the endianness. This allows the compiler to turn that `Hash` impl
- // into a direct call to 'u64::hash(_)`.
+ // into a direct call to `u64::hash(_)`.
#[cfg(not(all(target_pointer_width = "64", target_endian = "big")))]
pub index: DefIndex,
pub krate: CrateNum,
@@ -293,7 +299,7 @@ impl DefId {
#[inline]
pub fn as_local(self) -> Option<LocalDefId> {
- if self.is_local() { Some(LocalDefId { local_def_index: self.index }) } else { None }
+ self.is_local().then(|| LocalDefId { local_def_index: self.index })
}
#[inline]
@@ -314,7 +320,7 @@ impl DefId {
#[inline]
pub fn as_crate_root(self) -> Option<CrateNum> {
- if self.is_crate_root() { Some(self.krate) } else { None }
+ self.is_crate_root().then_some(self.krate)
}
#[inline]
diff --git a/compiler/rustc_span/src/edit_distance.rs b/compiler/rustc_span/src/edit_distance.rs
new file mode 100644
index 000000000..89f0386e3
--- /dev/null
+++ b/compiler/rustc_span/src/edit_distance.rs
@@ -0,0 +1,229 @@
+//! Edit distances.
+//!
+//! The [edit distance] is a metric for measuring the difference between two strings.
+//!
+//! [edit distance]: https://en.wikipedia.org/wiki/Edit_distance
+
+// The current implementation is the restricted Damerau-Levenshtein algorithm. It is restricted
+// because it does not permit modifying characters that have already been transposed. The specific
+// algorithm should not matter to the caller of the methods, which is why it is not noted in the
+// documentation.
+
+use crate::symbol::Symbol;
+use std::{cmp, mem};
+
+#[cfg(test)]
+mod tests;
+
+/// Finds the [edit distance] between two strings.
+///
+/// Returns `None` if the distance exceeds the limit.
+///
+/// [edit distance]: https://en.wikipedia.org/wiki/Edit_distance
+pub fn edit_distance(a: &str, b: &str, limit: usize) -> Option<usize> {
+ let mut a = &a.chars().collect::<Vec<_>>()[..];
+ let mut b = &b.chars().collect::<Vec<_>>()[..];
+
+ // Ensure that `b` is the shorter string, minimizing memory use.
+ if a.len() < b.len() {
+ mem::swap(&mut a, &mut b);
+ }
+
+ let min_dist = a.len() - b.len();
+ // If we know the limit will be exceeded, we can return early.
+ if min_dist > limit {
+ return None;
+ }
+
+ // Strip common prefix.
+ while let Some(((b_char, b_rest), (a_char, a_rest))) = b.split_first().zip(a.split_first())
+ && a_char == b_char
+ {
+ a = a_rest;
+ b = b_rest;
+ }
+ // Strip common suffix.
+ while let Some(((b_char, b_rest), (a_char, a_rest))) = b.split_last().zip(a.split_last())
+ && a_char == b_char
+ {
+ a = a_rest;
+ b = b_rest;
+ }
+
+ // If either string is empty, the distance is the length of the other.
+ // We know that `b` is the shorter string, so we don't need to check `a`.
+ if b.len() == 0 {
+ return Some(min_dist);
+ }
+
+ let mut prev_prev = vec![usize::MAX; b.len() + 1];
+ let mut prev = (0..=b.len()).collect::<Vec<_>>();
+ let mut current = vec![0; b.len() + 1];
+
+ // row by row
+ for i in 1..=a.len() {
+ current[0] = i;
+ let a_idx = i - 1;
+
+ // column by column
+ for j in 1..=b.len() {
+ let b_idx = j - 1;
+
+ // There is no cost to substitute a character with itself.
+ let substitution_cost = if a[a_idx] == b[b_idx] { 0 } else { 1 };
+
+ current[j] = cmp::min(
+ // deletion
+ prev[j] + 1,
+ cmp::min(
+ // insertion
+ current[j - 1] + 1,
+ // substitution
+ prev[j - 1] + substitution_cost,
+ ),
+ );
+
+ if (i > 1) && (j > 1) && (a[a_idx] == b[b_idx - 1]) && (a[a_idx - 1] == b[b_idx]) {
+ // transposition
+ current[j] = cmp::min(current[j], prev_prev[j - 2] + 1);
+ }
+ }
+
+ // Rotate the buffers, reusing the memory.
+ [prev_prev, prev, current] = [prev, current, prev_prev];
+ }
+
+ // `prev` because we already rotated the buffers.
+ let distance = prev[b.len()];
+ (distance <= limit).then_some(distance)
+}
+
+/// Provides a word similarity score between two words that accounts for substrings being more
+/// meaningful than a typical edit distance. The lower the score, the closer the match. 0 is an
+/// identical match.
+///
+/// Uses the edit distance between the two strings and removes the cost of the length difference.
+/// If this is 0 then it is either a substring match or a full word match, in the substring match
+/// case we detect this and return `1`. To prevent finding meaningless substrings, eg. "in" in
+/// "shrink", we only perform this subtraction of length difference if one of the words is not
+/// greater than twice the length of the other. For cases where the words are close in size but not
+/// an exact substring then the cost of the length difference is discounted by half.
+///
+/// Returns `None` if the distance exceeds the limit.
+pub fn edit_distance_with_substrings(a: &str, b: &str, limit: usize) -> Option<usize> {
+ let n = a.chars().count();
+ let m = b.chars().count();
+
+ // Check one isn't less than half the length of the other. If this is true then there is a
+ // big difference in length.
+ let big_len_diff = (n * 2) < m || (m * 2) < n;
+ let len_diff = if n < m { m - n } else { n - m };
+ let distance = edit_distance(a, b, limit + len_diff)?;
+
+ // This is the crux, subtracting length difference means exact substring matches will now be 0
+ let score = distance - len_diff;
+
+ // If the score is 0 but the words have different lengths then it's a substring match not a full
+ // word match
+ let score = if score == 0 && len_diff > 0 && !big_len_diff {
+ 1 // Exact substring match, but not a total word match so return non-zero
+ } else if !big_len_diff {
+ // Not a big difference in length, discount cost of length difference
+ score + (len_diff + 1) / 2
+ } else {
+ // A big difference in length, add back the difference in length to the score
+ score + len_diff
+ };
+
+ (score <= limit).then_some(score)
+}
+
+/// Finds the best match for given word in the given iterator where substrings are meaningful.
+///
+/// A version of [`find_best_match_for_name`] that uses [`edit_distance_with_substrings`] as the
+/// score for word similarity. This takes an optional distance limit which defaults to one-third of
+/// the given word.
+///
+/// We use case insensitive comparison to improve accuracy on an edge case with a lower(upper)case
+/// letters mismatch.
+pub fn find_best_match_for_name_with_substrings(
+ candidates: &[Symbol],
+ lookup: Symbol,
+ dist: Option<usize>,
+) -> Option<Symbol> {
+ find_best_match_for_name_impl(true, candidates, lookup, dist)
+}
+
+/// Finds the best match for a given word in the given iterator.
+///
+/// As a loose rule to avoid the obviously incorrect suggestions, it takes
+/// an optional limit for the maximum allowable edit distance, which defaults
+/// to one-third of the given word.
+///
+/// We use case insensitive comparison to improve accuracy on an edge case with a lower(upper)case
+/// letters mismatch.
+pub fn find_best_match_for_name(
+ candidates: &[Symbol],
+ lookup: Symbol,
+ dist: Option<usize>,
+) -> Option<Symbol> {
+ find_best_match_for_name_impl(false, candidates, lookup, dist)
+}
+
+#[cold]
+fn find_best_match_for_name_impl(
+ use_substring_score: bool,
+ candidates: &[Symbol],
+ lookup: Symbol,
+ dist: Option<usize>,
+) -> Option<Symbol> {
+ let lookup = lookup.as_str();
+ let lookup_uppercase = lookup.to_uppercase();
+
+ // Priority of matches:
+ // 1. Exact case insensitive match
+ // 2. Edit distance match
+ // 3. Sorted word match
+ if let Some(c) = candidates.iter().find(|c| c.as_str().to_uppercase() == lookup_uppercase) {
+ return Some(*c);
+ }
+
+ let mut dist = dist.unwrap_or_else(|| cmp::max(lookup.len(), 3) / 3);
+ let mut best = None;
+ for c in candidates {
+ match if use_substring_score {
+ edit_distance_with_substrings(lookup, c.as_str(), dist)
+ } else {
+ edit_distance(lookup, c.as_str(), dist)
+ } {
+ Some(0) => return Some(*c),
+ Some(d) => {
+ dist = d - 1;
+ best = Some(*c);
+ }
+ None => {}
+ }
+ }
+ if best.is_some() {
+ return best;
+ }
+
+ find_match_by_sorted_words(candidates, lookup)
+}
+
+fn find_match_by_sorted_words(iter_names: &[Symbol], lookup: &str) -> Option<Symbol> {
+ iter_names.iter().fold(None, |result, candidate| {
+ if sort_by_words(candidate.as_str()) == sort_by_words(lookup) {
+ Some(*candidate)
+ } else {
+ result
+ }
+ })
+}
+
+fn sort_by_words(name: &str) -> String {
+ let mut split_words: Vec<&str> = name.split('_').collect();
+ // We are sorting primitive &strs and can use unstable sort here.
+ split_words.sort_unstable();
+ split_words.join("_")
+}
diff --git a/compiler/rustc_span/src/edit_distance/tests.rs b/compiler/rustc_span/src/edit_distance/tests.rs
new file mode 100644
index 000000000..c9c7a1f1b
--- /dev/null
+++ b/compiler/rustc_span/src/edit_distance/tests.rs
@@ -0,0 +1,80 @@
+use super::*;
+
+#[test]
+fn test_edit_distance() {
+ // Test bytelength agnosticity
+ for c in (0..char::MAX as u32).filter_map(char::from_u32).map(|i| i.to_string()) {
+ assert_eq!(edit_distance(&c[..], &c[..], usize::MAX), Some(0));
+ }
+
+ let a = "\nMäry häd ä little lämb\n\nLittle lämb\n";
+ let b = "\nMary häd ä little lämb\n\nLittle lämb\n";
+ let c = "Mary häd ä little lämb\n\nLittle lämb\n";
+ assert_eq!(edit_distance(a, b, usize::MAX), Some(1));
+ assert_eq!(edit_distance(b, a, usize::MAX), Some(1));
+ assert_eq!(edit_distance(a, c, usize::MAX), Some(2));
+ assert_eq!(edit_distance(c, a, usize::MAX), Some(2));
+ assert_eq!(edit_distance(b, c, usize::MAX), Some(1));
+ assert_eq!(edit_distance(c, b, usize::MAX), Some(1));
+}
+
+#[test]
+fn test_edit_distance_limit() {
+ assert_eq!(edit_distance("abc", "abcd", 1), Some(1));
+ assert_eq!(edit_distance("abc", "abcd", 0), None);
+ assert_eq!(edit_distance("abc", "xyz", 3), Some(3));
+ assert_eq!(edit_distance("abc", "xyz", 2), None);
+}
+
+#[test]
+fn test_method_name_similarity_score() {
+ assert_eq!(edit_distance_with_substrings("empty", "is_empty", 1), Some(1));
+ assert_eq!(edit_distance_with_substrings("shrunk", "rchunks", 2), None);
+ assert_eq!(edit_distance_with_substrings("abc", "abcd", 1), Some(1));
+ assert_eq!(edit_distance_with_substrings("a", "abcd", 1), None);
+ assert_eq!(edit_distance_with_substrings("edf", "eq", 1), None);
+ assert_eq!(edit_distance_with_substrings("abc", "xyz", 3), Some(3));
+ assert_eq!(edit_distance_with_substrings("abcdef", "abcdef", 2), Some(0));
+}
+
+#[test]
+fn test_find_best_match_for_name() {
+ use crate::create_default_session_globals_then;
+ create_default_session_globals_then(|| {
+ let input = vec![Symbol::intern("aaab"), Symbol::intern("aaabc")];
+ assert_eq!(
+ find_best_match_for_name(&input, Symbol::intern("aaaa"), None),
+ Some(Symbol::intern("aaab"))
+ );
+
+ assert_eq!(find_best_match_for_name(&input, Symbol::intern("1111111111"), None), None);
+
+ let input = vec![Symbol::intern("AAAA")];
+ assert_eq!(
+ find_best_match_for_name(&input, Symbol::intern("aaaa"), None),
+ Some(Symbol::intern("AAAA"))
+ );
+
+ let input = vec![Symbol::intern("AAAA")];
+ assert_eq!(
+ find_best_match_for_name(&input, Symbol::intern("aaaa"), Some(4)),
+ Some(Symbol::intern("AAAA"))
+ );
+
+ let input = vec![Symbol::intern("a_longer_variable_name")];
+ assert_eq!(
+ find_best_match_for_name(&input, Symbol::intern("a_variable_longer_name"), None),
+ Some(Symbol::intern("a_longer_variable_name"))
+ );
+ })
+}
+
+#[test]
+fn test_precise_algorithm() {
+ // Not Levenshtein distance.
+ assert_ne!(edit_distance("ab", "ba", usize::MAX), Some(2));
+ // Not unrestricted Damerau-Levenshtein distance.
+ assert_ne!(edit_distance("abde", "bcaed", usize::MAX), Some(3));
+ // The current implementation is a restricted Damerau-Levenshtein distance.
+ assert_eq!(edit_distance("abde", "bcaed", usize::MAX), Some(4));
+}
diff --git a/compiler/rustc_span/src/edition.rs b/compiler/rustc_span/src/edition.rs
index b43183916..f16db69aa 100644
--- a/compiler/rustc_span/src/edition.rs
+++ b/compiler/rustc_span/src/edition.rs
@@ -49,8 +49,8 @@ impl fmt::Display for Edition {
}
impl Edition {
- pub fn lint_name(&self) -> &'static str {
- match *self {
+ pub fn lint_name(self) -> &'static str {
+ match self {
Edition::Edition2015 => "rust_2015_compatibility",
Edition::Edition2018 => "rust_2018_compatibility",
Edition::Edition2021 => "rust_2021_compatibility",
@@ -58,8 +58,8 @@ impl Edition {
}
}
- pub fn feature_name(&self) -> Symbol {
- match *self {
+ pub fn feature_name(self) -> Symbol {
+ match self {
Edition::Edition2015 => sym::rust_2015_preview,
Edition::Edition2018 => sym::rust_2018_preview,
Edition::Edition2021 => sym::rust_2021_preview,
@@ -67,8 +67,8 @@ impl Edition {
}
}
- pub fn is_stable(&self) -> bool {
- match *self {
+ pub fn is_stable(self) -> bool {
+ match self {
Edition::Edition2015 => true,
Edition::Edition2018 => true,
Edition::Edition2021 => true,
@@ -76,23 +76,24 @@ impl Edition {
}
}
- pub fn rust_2015(&self) -> bool {
- *self == Edition::Edition2015
+ /// Is this edition 2015?
+ pub fn is_rust_2015(self) -> bool {
+ self == Edition::Edition2015
}
/// Are we allowed to use features from the Rust 2018 edition?
- pub fn rust_2018(&self) -> bool {
- *self >= Edition::Edition2018
+ pub fn rust_2018(self) -> bool {
+ self >= Edition::Edition2018
}
/// Are we allowed to use features from the Rust 2021 edition?
- pub fn rust_2021(&self) -> bool {
- *self >= Edition::Edition2021
+ pub fn rust_2021(self) -> bool {
+ self >= Edition::Edition2021
}
/// Are we allowed to use features from the Rust 2024 edition?
- pub fn rust_2024(&self) -> bool {
- *self >= Edition::Edition2024
+ pub fn rust_2024(self) -> bool {
+ self >= Edition::Edition2024
}
}
diff --git a/compiler/rustc_span/src/lev_distance.rs b/compiler/rustc_span/src/lev_distance.rs
deleted file mode 100644
index 61e4b98a8..000000000
--- a/compiler/rustc_span/src/lev_distance.rs
+++ /dev/null
@@ -1,177 +0,0 @@
-//! Levenshtein distances.
-//!
-//! The [Levenshtein distance] is a metric for measuring the difference between two strings.
-//!
-//! [Levenshtein distance]: https://en.wikipedia.org/wiki/Levenshtein_distance
-
-use crate::symbol::Symbol;
-use std::cmp;
-
-#[cfg(test)]
-mod tests;
-
-/// Finds the Levenshtein distance between two strings.
-///
-/// Returns None if the distance exceeds the limit.
-pub fn lev_distance(a: &str, b: &str, limit: usize) -> Option<usize> {
- let n = a.chars().count();
- let m = b.chars().count();
- let min_dist = if n < m { m - n } else { n - m };
-
- if min_dist > limit {
- return None;
- }
- if n == 0 || m == 0 {
- return (min_dist <= limit).then_some(min_dist);
- }
-
- let mut dcol: Vec<_> = (0..=m).collect();
-
- for (i, sc) in a.chars().enumerate() {
- let mut current = i;
- dcol[0] = current + 1;
-
- for (j, tc) in b.chars().enumerate() {
- let next = dcol[j + 1];
- if sc == tc {
- dcol[j + 1] = current;
- } else {
- dcol[j + 1] = cmp::min(current, next);
- dcol[j + 1] = cmp::min(dcol[j + 1], dcol[j]) + 1;
- }
- current = next;
- }
- }
-
- (dcol[m] <= limit).then_some(dcol[m])
-}
-
-/// Provides a word similarity score between two words that accounts for substrings being more
-/// meaningful than a typical Levenshtein distance. The lower the score, the closer the match.
-/// 0 is an identical match.
-///
-/// Uses the Levenshtein distance between the two strings and removes the cost of the length
-/// difference. If this is 0 then it is either a substring match or a full word match, in the
-/// substring match case we detect this and return `1`. To prevent finding meaningless substrings,
-/// eg. "in" in "shrink", we only perform this subtraction of length difference if one of the words
-/// is not greater than twice the length of the other. For cases where the words are close in size
-/// but not an exact substring then the cost of the length difference is discounted by half.
-///
-/// Returns `None` if the distance exceeds the limit.
-pub fn lev_distance_with_substrings(a: &str, b: &str, limit: usize) -> Option<usize> {
- let n = a.chars().count();
- let m = b.chars().count();
-
- // Check one isn't less than half the length of the other. If this is true then there is a
- // big difference in length.
- let big_len_diff = (n * 2) < m || (m * 2) < n;
- let len_diff = if n < m { m - n } else { n - m };
- let lev = lev_distance(a, b, limit + len_diff)?;
-
- // This is the crux, subtracting length difference means exact substring matches will now be 0
- let score = lev - len_diff;
-
- // If the score is 0 but the words have different lengths then it's a substring match not a full
- // word match
- let score = if score == 0 && len_diff > 0 && !big_len_diff {
- 1 // Exact substring match, but not a total word match so return non-zero
- } else if !big_len_diff {
- // Not a big difference in length, discount cost of length difference
- score + (len_diff + 1) / 2
- } else {
- // A big difference in length, add back the difference in length to the score
- score + len_diff
- };
-
- (score <= limit).then_some(score)
-}
-
-/// Finds the best match for given word in the given iterator where substrings are meaningful.
-///
-/// A version of [`find_best_match_for_name`] that uses [`lev_distance_with_substrings`] as the score
-/// for word similarity. This takes an optional distance limit which defaults to one-third of the
-/// given word.
-///
-/// Besides the modified Levenshtein, we use case insensitive comparison to improve accuracy
-/// on an edge case with a lower(upper)case letters mismatch.
-pub fn find_best_match_for_name_with_substrings(
- candidates: &[Symbol],
- lookup: Symbol,
- dist: Option<usize>,
-) -> Option<Symbol> {
- find_best_match_for_name_impl(true, candidates, lookup, dist)
-}
-
-/// Finds the best match for a given word in the given iterator.
-///
-/// As a loose rule to avoid the obviously incorrect suggestions, it takes
-/// an optional limit for the maximum allowable edit distance, which defaults
-/// to one-third of the given word.
-///
-/// Besides Levenshtein, we use case insensitive comparison to improve accuracy
-/// on an edge case with a lower(upper)case letters mismatch.
-pub fn find_best_match_for_name(
- candidates: &[Symbol],
- lookup: Symbol,
- dist: Option<usize>,
-) -> Option<Symbol> {
- find_best_match_for_name_impl(false, candidates, lookup, dist)
-}
-
-#[cold]
-fn find_best_match_for_name_impl(
- use_substring_score: bool,
- candidates: &[Symbol],
- lookup: Symbol,
- dist: Option<usize>,
-) -> Option<Symbol> {
- let lookup = lookup.as_str();
- let lookup_uppercase = lookup.to_uppercase();
-
- // Priority of matches:
- // 1. Exact case insensitive match
- // 2. Levenshtein distance match
- // 3. Sorted word match
- if let Some(c) = candidates.iter().find(|c| c.as_str().to_uppercase() == lookup_uppercase) {
- return Some(*c);
- }
-
- let mut dist = dist.unwrap_or_else(|| cmp::max(lookup.len(), 3) / 3);
- let mut best = None;
- for c in candidates {
- match if use_substring_score {
- lev_distance_with_substrings(lookup, c.as_str(), dist)
- } else {
- lev_distance(lookup, c.as_str(), dist)
- } {
- Some(0) => return Some(*c),
- Some(d) => {
- dist = d - 1;
- best = Some(*c);
- }
- None => {}
- }
- }
- if best.is_some() {
- return best;
- }
-
- find_match_by_sorted_words(candidates, lookup)
-}
-
-fn find_match_by_sorted_words(iter_names: &[Symbol], lookup: &str) -> Option<Symbol> {
- iter_names.iter().fold(None, |result, candidate| {
- if sort_by_words(candidate.as_str()) == sort_by_words(lookup) {
- Some(*candidate)
- } else {
- result
- }
- })
-}
-
-fn sort_by_words(name: &str) -> String {
- let mut split_words: Vec<&str> = name.split('_').collect();
- // We are sorting primitive &strs and can use unstable sort here.
- split_words.sort_unstable();
- split_words.join("_")
-}
diff --git a/compiler/rustc_span/src/lev_distance/tests.rs b/compiler/rustc_span/src/lev_distance/tests.rs
deleted file mode 100644
index b17d6588c..000000000
--- a/compiler/rustc_span/src/lev_distance/tests.rs
+++ /dev/null
@@ -1,71 +0,0 @@
-use super::*;
-
-#[test]
-fn test_lev_distance() {
- use std::char::{from_u32, MAX};
- // Test bytelength agnosticity
- for c in (0..MAX as u32).filter_map(from_u32).map(|i| i.to_string()) {
- assert_eq!(lev_distance(&c[..], &c[..], usize::MAX), Some(0));
- }
-
- let a = "\nMäry häd ä little lämb\n\nLittle lämb\n";
- let b = "\nMary häd ä little lämb\n\nLittle lämb\n";
- let c = "Mary häd ä little lämb\n\nLittle lämb\n";
- assert_eq!(lev_distance(a, b, usize::MAX), Some(1));
- assert_eq!(lev_distance(b, a, usize::MAX), Some(1));
- assert_eq!(lev_distance(a, c, usize::MAX), Some(2));
- assert_eq!(lev_distance(c, a, usize::MAX), Some(2));
- assert_eq!(lev_distance(b, c, usize::MAX), Some(1));
- assert_eq!(lev_distance(c, b, usize::MAX), Some(1));
-}
-
-#[test]
-fn test_lev_distance_limit() {
- assert_eq!(lev_distance("abc", "abcd", 1), Some(1));
- assert_eq!(lev_distance("abc", "abcd", 0), None);
- assert_eq!(lev_distance("abc", "xyz", 3), Some(3));
- assert_eq!(lev_distance("abc", "xyz", 2), None);
-}
-
-#[test]
-fn test_method_name_similarity_score() {
- assert_eq!(lev_distance_with_substrings("empty", "is_empty", 1), Some(1));
- assert_eq!(lev_distance_with_substrings("shrunk", "rchunks", 2), None);
- assert_eq!(lev_distance_with_substrings("abc", "abcd", 1), Some(1));
- assert_eq!(lev_distance_with_substrings("a", "abcd", 1), None);
- assert_eq!(lev_distance_with_substrings("edf", "eq", 1), None);
- assert_eq!(lev_distance_with_substrings("abc", "xyz", 3), Some(3));
- assert_eq!(lev_distance_with_substrings("abcdef", "abcdef", 2), Some(0));
-}
-
-#[test]
-fn test_find_best_match_for_name() {
- use crate::create_default_session_globals_then;
- create_default_session_globals_then(|| {
- let input = vec![Symbol::intern("aaab"), Symbol::intern("aaabc")];
- assert_eq!(
- find_best_match_for_name(&input, Symbol::intern("aaaa"), None),
- Some(Symbol::intern("aaab"))
- );
-
- assert_eq!(find_best_match_for_name(&input, Symbol::intern("1111111111"), None), None);
-
- let input = vec![Symbol::intern("AAAA")];
- assert_eq!(
- find_best_match_for_name(&input, Symbol::intern("aaaa"), None),
- Some(Symbol::intern("AAAA"))
- );
-
- let input = vec![Symbol::intern("AAAA")];
- assert_eq!(
- find_best_match_for_name(&input, Symbol::intern("aaaa"), Some(4)),
- Some(Symbol::intern("AAAA"))
- );
-
- let input = vec![Symbol::intern("a_longer_variable_name")];
- assert_eq!(
- find_best_match_for_name(&input, Symbol::intern("a_variable_longer_name"), None),
- Some(Symbol::intern("a_longer_variable_name"))
- );
- })
-}
diff --git a/compiler/rustc_span/src/lib.rs b/compiler/rustc_span/src/lib.rs
index 7e61f2f9f..873cd33f6 100644
--- a/compiler/rustc_span/src/lib.rs
+++ b/compiler/rustc_span/src/lib.rs
@@ -19,6 +19,7 @@
#![feature(negative_impls)]
#![feature(min_specialization)]
#![feature(rustc_attrs)]
+#![feature(let_chains)]
#![deny(rustc::untranslatable_diagnostic)]
#![deny(rustc::diagnostic_outside_of_impl)]
@@ -46,7 +47,7 @@ pub use hygiene::{ExpnData, ExpnHash, ExpnId, LocalExpnId, SyntaxContext};
use rustc_data_structures::stable_hasher::HashingControls;
pub mod def_id;
use def_id::{CrateNum, DefId, DefPathHash, LocalDefId, LOCAL_CRATE};
-pub mod lev_distance;
+pub mod edit_distance;
mod span_encoding;
pub use span_encoding::{Span, DUMMY_SP};
@@ -705,23 +706,23 @@ impl Span {
}
#[inline]
- pub fn rust_2015(self) -> bool {
- self.edition() == edition::Edition::Edition2015
+ pub fn is_rust_2015(self) -> bool {
+ self.edition().is_rust_2015()
}
#[inline]
pub fn rust_2018(self) -> bool {
- self.edition() >= edition::Edition::Edition2018
+ self.edition().rust_2018()
}
#[inline]
pub fn rust_2021(self) -> bool {
- self.edition() >= edition::Edition::Edition2021
+ self.edition().rust_2021()
}
#[inline]
pub fn rust_2024(self) -> bool {
- self.edition() >= edition::Edition::Edition2024
+ self.edition().rust_2024()
}
/// Returns the source callee.
@@ -2148,3 +2149,17 @@ where
Hash::hash(&len, hasher);
}
}
+
+/// Useful type to use with `Result<>` indicate that an error has already
+/// been reported to the user, so no need to continue checking.
+#[derive(Clone, Copy, Debug, Encodable, Decodable, Hash, PartialEq, Eq, PartialOrd, Ord)]
+#[derive(HashStable_Generic)]
+pub struct ErrorGuaranteed(());
+
+impl ErrorGuaranteed {
+ /// To be used only if you really know what you are doing... ideally, we would find a way to
+ /// eliminate all calls to this method.
+ pub fn unchecked_claim_error_was_emitted() -> Self {
+ ErrorGuaranteed(())
+ }
+}
diff --git a/compiler/rustc_span/src/span_encoding.rs b/compiler/rustc_span/src/span_encoding.rs
index d48c4f7e5..c600298c5 100644
--- a/compiler/rustc_span/src/span_encoding.rs
+++ b/compiler/rustc_span/src/span_encoding.rs
@@ -110,11 +110,16 @@ impl Span {
// Inline format with parent.
let len_or_tag = len_or_tag | PARENT_MASK;
let parent2 = parent.local_def_index.as_u32();
- if ctxt2 == SyntaxContext::root().as_u32() && parent2 <= MAX_CTXT {
+ if ctxt2 == SyntaxContext::root().as_u32()
+ && parent2 <= MAX_CTXT
+ && len_or_tag < LEN_TAG
+ {
+ debug_assert_ne!(len_or_tag, LEN_TAG);
return Span { base_or_index: base, len_or_tag, ctxt_or_tag: parent2 as u16 };
}
} else {
// Inline format with ctxt.
+ debug_assert_ne!(len_or_tag, LEN_TAG);
return Span {
base_or_index: base,
len_or_tag: len as u16,
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index 7597b8d12..6272bf7f2 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -288,6 +288,7 @@ symbols! {
Target,
ToOwned,
ToString,
+ TokenStream,
Try,
TryCaptureGeneric,
TryCapturePrintable,
@@ -723,16 +724,23 @@ symbols! {
forbid,
forget,
format,
+ format_alignment,
format_args,
format_args_capture,
format_args_macro,
format_args_nl,
+ format_argument,
+ format_arguments,
+ format_count,
format_macro,
+ format_placeholder,
+ format_unsafe_arg,
freeze,
freg,
frem_fast,
from,
from_desugaring,
+ from_fn,
from_iter,
from_method,
from_output,
@@ -948,6 +956,7 @@ symbols! {
mul,
mul_assign,
mul_with_overflow,
+ multiple_supertrait_upcastable,
must_not_suspend,
must_use,
naked,
@@ -1008,6 +1017,7 @@ symbols! {
non_ascii_idents,
non_exhaustive,
non_exhaustive_omitted_patterns_lint,
+ non_lifetime_binders,
non_modrs_mods,
nontemporal_store,
noop_method_borrow,
@@ -1041,6 +1051,7 @@ symbols! {
overlapping_marker_traits,
owned_box,
packed,
+ packed_bundled_libs,
panic,
panic_2015,
panic_2021,
@@ -1076,7 +1087,7 @@ symbols! {
plugins,
pointee_trait,
pointer,
- pointer_sized,
+ pointer_like,
poll,
position,
post_dash_lto: "post-lto",
@@ -1215,6 +1226,7 @@ symbols! {
rustc_capture_analysis,
rustc_clean,
rustc_coherence_is_core,
+ rustc_coinductive,
rustc_const_stable,
rustc_const_unstable,
rustc_conversion_suggestion,
@@ -1942,7 +1954,7 @@ impl Interner {
let name = Symbol::new(inner.strings.len() as u32);
// SAFETY: we convert from `&str` to `&[u8]`, clone it into the arena,
- // and immediately convert the clone back to `&[u8], all because there
+ // and immediately convert the clone back to `&[u8]`, all because there
// is no `inner.arena.alloc_str()` method. This is clearly safe.
let string: &str =
unsafe { str::from_utf8_unchecked(inner.arena.alloc_slice(string.as_bytes())) };
diff --git a/compiler/rustc_error_messages/locales/en-US/symbol_mangling.ftl b/compiler/rustc_symbol_mangling/locales/en-US.ftl
index b7d48280f..b7d48280f 100644
--- a/compiler/rustc_error_messages/locales/en-US/symbol_mangling.ftl
+++ b/compiler/rustc_symbol_mangling/locales/en-US.ftl
diff --git a/compiler/rustc_symbol_mangling/src/legacy.rs b/compiler/rustc_symbol_mangling/src/legacy.rs
index 23ff6b333..2368468c8 100644
--- a/compiler/rustc_symbol_mangling/src/legacy.rs
+++ b/compiler/rustc_symbol_mangling/src/legacy.rs
@@ -3,7 +3,7 @@ use rustc_hir::def_id::CrateNum;
use rustc_hir::definitions::{DefPathData, DisambiguatedDefPathData};
use rustc_middle::ty::print::{PrettyPrinter, Print, Printer};
use rustc_middle::ty::subst::{GenericArg, GenericArgKind};
-use rustc_middle::ty::{self, Instance, Ty, TyCtxt, TypeVisitable};
+use rustc_middle::ty::{self, Instance, Ty, TyCtxt, TypeVisitableExt};
use rustc_middle::util::common::record_time;
use std::fmt::{self, Write};
@@ -26,7 +26,7 @@ pub(super) fn mangle<'tcx>(
let key = tcx.def_key(ty_def_id);
match key.disambiguated_data.data {
DefPathData::TypeNs(_) | DefPathData::ValueNs(_) => {
- instance_ty = tcx.type_of(ty_def_id);
+ instance_ty = tcx.type_of(ty_def_id).subst_identity();
debug!(?instance_ty);
break;
}
diff --git a/compiler/rustc_symbol_mangling/src/lib.rs b/compiler/rustc_symbol_mangling/src/lib.rs
index 547a59076..d9ce73734 100644
--- a/compiler/rustc_symbol_mangling/src/lib.rs
+++ b/compiler/rustc_symbol_mangling/src/lib.rs
@@ -100,8 +100,10 @@ extern crate rustc_middle;
#[macro_use]
extern crate tracing;
+use rustc_errors::{DiagnosticMessage, SubdiagnosticMessage};
use rustc_hir::def::DefKind;
use rustc_hir::def_id::{CrateNum, LOCAL_CRATE};
+use rustc_macros::fluent_messages;
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrs;
use rustc_middle::mir::mono::{InstantiationMode, MonoItem};
@@ -117,6 +119,8 @@ pub mod errors;
pub mod test;
pub mod typeid;
+fluent_messages! { "../locales/en-US.ftl" }
+
/// This function computes the symbol name for the given `instance` and the
/// given instantiating crate. That is, if you know that instance X is
/// instantiated in crate Y, this is the symbol name this instance would have.
@@ -244,8 +248,7 @@ fn compute_symbol_name<'tcx>(
// project.
let avoid_cross_crate_conflicts = is_generic(substs) || is_globally_shared_function;
- let instantiating_crate =
- if avoid_cross_crate_conflicts { Some(compute_instantiating_crate()) } else { None };
+ let instantiating_crate = avoid_cross_crate_conflicts.then(compute_instantiating_crate);
// Pick the crate responsible for the symbol mangling version, which has to:
// 1. be stable for each instance, whether it's being defined or imported
diff --git a/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs b/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs
index 0759b95bd..1a679f32c 100644
--- a/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs
+++ b/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs
@@ -299,6 +299,7 @@ fn encode_region<'tcx>(
RegionKind::ReEarlyBound(..)
| RegionKind::ReFree(..)
| RegionKind::ReStatic
+ | RegionKind::ReError(_)
| RegionKind::ReVar(..)
| RegionKind::RePlaceholder(..) => {
bug!("encode_region: unexpected `{:?}`", region.kind());
@@ -395,6 +396,7 @@ fn encode_ty_name(tcx: TyCtxt<'_>, def_id: DefId) -> String {
hir::definitions::DefPathData::CrateRoot
| hir::definitions::DefPathData::Use
| hir::definitions::DefPathData::GlobalAsm
+ | hir::definitions::DefPathData::ImplTraitAssocTy
| hir::definitions::DefPathData::MacroNs(..)
| hir::definitions::DefPathData::LifetimeNs(..) => {
bug!("encode_ty_name: unexpected `{:?}`", disambiguated_data.data);
@@ -640,6 +642,7 @@ fn encode_ty<'tcx>(
ty::Bound(..)
| ty::Error(..)
| ty::GeneratorWitness(..)
+ | ty::GeneratorWitnessMIR(..)
| ty::Infer(..)
| ty::Alias(..)
| ty::Param(..)
@@ -672,7 +675,7 @@ fn transform_ty<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, options: TransformTyOptio
_ if ty.is_unit() => {}
ty::Tuple(tys) => {
- ty = tcx.mk_tup(tys.iter().map(|ty| transform_ty(tcx, ty, options)));
+ ty = tcx.mk_tup_from_iter(tys.iter().map(|ty| transform_ty(tcx, ty, options)));
}
ty::Array(ty0, len) => {
@@ -694,13 +697,13 @@ fn transform_ty<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, options: TransformTyOptio
let variant = adt_def.non_enum_variant();
let param_env = tcx.param_env(variant.def_id);
let field = variant.fields.iter().find(|field| {
- let ty = tcx.type_of(field.did);
+ let ty = tcx.type_of(field.did).subst_identity();
let is_zst =
tcx.layout_of(param_env.and(ty)).map_or(false, |layout| layout.is_zst());
!is_zst
});
if let Some(field) = field {
- let ty0 = tcx.bound_type_of(field.did).subst(tcx, substs);
+ let ty0 = tcx.type_of(field.did).subst(tcx, substs);
// Generalize any repr(transparent) user-defined type that is either a pointer
// or reference, and either references itself or any other type that contains or
// references itself, to avoid a reference cycle.
@@ -779,8 +782,8 @@ fn transform_ty<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, options: TransformTyOptio
let output = transform_ty(tcx, fn_sig.skip_binder().output(), options);
ty = tcx.mk_fn_ptr(ty::Binder::bind_with_vars(
tcx.mk_fn_sig(
- parameters.iter(),
- &output,
+ parameters,
+ output,
fn_sig.c_variadic(),
fn_sig.unsafety(),
fn_sig.abi(),
@@ -793,6 +796,7 @@ fn transform_ty<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, options: TransformTyOptio
ty::Bound(..)
| ty::Error(..)
| ty::GeneratorWitness(..)
+ | ty::GeneratorWitnessMIR(..)
| ty::Infer(..)
| ty::Alias(..)
| ty::Param(..)
@@ -810,21 +814,18 @@ fn transform_substs<'tcx>(
substs: SubstsRef<'tcx>,
options: TransformTyOptions,
) -> SubstsRef<'tcx> {
- let substs: Vec<GenericArg<'tcx>> = substs
- .iter()
- .map(|subst| {
- if let GenericArgKind::Type(ty) = subst.unpack() {
- if is_c_void_ty(tcx, ty) {
- tcx.mk_unit().into()
- } else {
- transform_ty(tcx, ty, options).into()
- }
+ let substs = substs.iter().map(|subst| {
+ if let GenericArgKind::Type(ty) = subst.unpack() {
+ if is_c_void_ty(tcx, ty) {
+ tcx.mk_unit().into()
} else {
- subst
+ transform_ty(tcx, ty, options).into()
}
- })
- .collect();
- tcx.mk_substs(substs.iter())
+ } else {
+ subst
+ }
+ });
+ tcx.mk_substs_from_iter(substs)
}
/// Returns a type metadata identifier for the specified FnAbi using the Itanium C++ ABI with vendor
diff --git a/compiler/rustc_symbol_mangling/src/v0.rs b/compiler/rustc_symbol_mangling/src/v0.rs
index 0d446d654..2f20d4213 100644
--- a/compiler/rustc_symbol_mangling/src/v0.rs
+++ b/compiler/rustc_symbol_mangling/src/v0.rs
@@ -8,7 +8,8 @@ use rustc_hir::definitions::{DefPathData, DisambiguatedDefPathData};
use rustc_middle::ty::layout::IntegerExt;
use rustc_middle::ty::print::{Print, Printer};
use rustc_middle::ty::{
- self, EarlyBinder, FloatTy, Instance, IntTy, Ty, TyCtxt, TypeVisitable, UintTy,
+ self, EarlyBinder, FloatTy, Instance, IntTy, Ty, TyCtxt, TypeVisitable, TypeVisitableExt,
+ UintTy,
};
use rustc_middle::ty::{GenericArg, GenericArgKind};
use rustc_span::symbol::kw;
@@ -204,7 +205,7 @@ impl<'tcx> SymbolMangler<'tcx> {
print_value: impl FnOnce(&'a mut Self, &T) -> Result<&'a mut Self, !>,
) -> Result<&'a mut Self, !>
where
- T: TypeVisitable<'tcx>,
+ T: TypeVisitable<TyCtxt<'tcx>>,
{
// FIXME(non-lifetime-binders): What to do here?
let regions = if value.has_late_bound_regions() {
@@ -490,6 +491,7 @@ impl<'tcx> Printer<'tcx> for &mut SymbolMangler<'tcx> {
}
ty::GeneratorWitness(_) => bug!("symbol_names: unexpected `GeneratorWitness`"),
+ ty::GeneratorWitnessMIR(..) => bug!("symbol_names: unexpected `GeneratorWitnessMIR`"),
}
// Only cache types that do not refer to an enclosing
@@ -539,7 +541,7 @@ impl<'tcx> Printer<'tcx> for &mut SymbolMangler<'tcx> {
match predicate.as_ref().skip_binder() {
ty::ExistentialPredicate::Trait(trait_ref) => {
// Use a type that can't appear in defaults of type parameters.
- let dummy_self = cx.tcx.mk_ty_infer(ty::FreshTy(0));
+ let dummy_self = cx.tcx.mk_fresh_ty(0);
let trait_ref = trait_ref.with_self_ty(cx.tcx, dummy_self);
cx = cx.print_def_path(trait_ref.def_id, trait_ref.substs)?;
}
@@ -790,6 +792,7 @@ impl<'tcx> Printer<'tcx> for &mut SymbolMangler<'tcx> {
| DefPathData::Use
| DefPathData::GlobalAsm
| DefPathData::Impl
+ | DefPathData::ImplTraitAssocTy
| DefPathData::MacroNs(_)
| DefPathData::LifetimeNs(_) => {
bug!("symbol_names: unexpected DefPathData: {:?}", disambiguated_data.data)
diff --git a/compiler/rustc_target/src/abi/call/loongarch.rs b/compiler/rustc_target/src/abi/call/loongarch.rs
index 4a2d39cc7..247256f07 100644
--- a/compiler/rustc_target/src/abi/call/loongarch.rs
+++ b/compiler/rustc_target/src/abi/call/loongarch.rs
@@ -39,7 +39,7 @@ where
{
match arg_layout.abi {
Abi::Scalar(scalar) => match scalar.primitive() {
- abi::Int(..) | abi::Pointer => {
+ abi::Int(..) | abi::Pointer(_) => {
if arg_layout.size.bits() > xlen {
return Err(CannotUseFpConv);
}
diff --git a/compiler/rustc_target/src/abi/call/mod.rs b/compiler/rustc_target/src/abi/call/mod.rs
index 3b8c867d3..a0730fbb6 100644
--- a/compiler/rustc_target/src/abi/call/mod.rs
+++ b/compiler/rustc_target/src/abi/call/mod.rs
@@ -346,7 +346,7 @@ impl<'a, Ty> TyAndLayout<'a, Ty> {
// The primitive for this algorithm.
Abi::Scalar(scalar) => {
let kind = match scalar.primitive() {
- abi::Int(..) | abi::Pointer => RegKind::Integer,
+ abi::Int(..) | abi::Pointer(_) => RegKind::Integer,
abi::F32 | abi::F64 => RegKind::Float,
};
Ok(HomogeneousAggregate::Homogeneous(Reg { kind, size: self.size }))
diff --git a/compiler/rustc_target/src/abi/call/riscv.rs b/compiler/rustc_target/src/abi/call/riscv.rs
index 34280d38e..d90dce2a0 100644
--- a/compiler/rustc_target/src/abi/call/riscv.rs
+++ b/compiler/rustc_target/src/abi/call/riscv.rs
@@ -45,7 +45,7 @@ where
{
match arg_layout.abi {
Abi::Scalar(scalar) => match scalar.primitive() {
- abi::Int(..) | abi::Pointer => {
+ abi::Int(..) | abi::Pointer(_) => {
if arg_layout.size.bits() > xlen {
return Err(CannotUseFpConv);
}
diff --git a/compiler/rustc_target/src/abi/call/sparc64.rs b/compiler/rustc_target/src/abi/call/sparc64.rs
index c8b6ac5ae..cbed5b4af 100644
--- a/compiler/rustc_target/src/abi/call/sparc64.rs
+++ b/compiler/rustc_target/src/abi/call/sparc64.rs
@@ -20,7 +20,7 @@ where
{
let dl = cx.data_layout();
- if !scalar.primitive().is_float() {
+ if !matches!(scalar.primitive(), abi::F32 | abi::F64) {
return data;
}
@@ -83,11 +83,11 @@ where
(abi::F32, _) => offset += Reg::f32().size,
(_, abi::F64) => offset += Reg::f64().size,
(abi::Int(i, _signed), _) => offset += i.size(),
- (abi::Pointer, _) => offset += Reg::i64().size,
+ (abi::Pointer(_), _) => offset += Reg::i64().size,
_ => {}
}
- if (offset.bytes() % 4) != 0 && scalar2.primitive().is_float() {
+ if (offset.bytes() % 4) != 0 && matches!(scalar2.primitive(), abi::F32 | abi::F64) {
offset += Size::from_bytes(4 - (offset.bytes() % 4));
}
data = arg_scalar(cx, scalar2, offset, data);
diff --git a/compiler/rustc_target/src/abi/call/x86_64.rs b/compiler/rustc_target/src/abi/call/x86_64.rs
index c0c071a61..9427f27d1 100644
--- a/compiler/rustc_target/src/abi/call/x86_64.rs
+++ b/compiler/rustc_target/src/abi/call/x86_64.rs
@@ -50,7 +50,7 @@ where
Abi::Uninhabited => return Ok(()),
Abi::Scalar(scalar) => match scalar.primitive() {
- abi::Int(..) | abi::Pointer => Class::Int,
+ 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 88a0a1f8e..8d2e92cc7 100644
--- a/compiler/rustc_target/src/abi/mod.rs
+++ b/compiler/rustc_target/src/abi/mod.rs
@@ -3,10 +3,8 @@ pub use Primitive::*;
use crate::json::{Json, ToJson};
-use std::fmt;
use std::ops::Deref;
-use rustc_data_structures::intern::Interned;
use rustc_macros::HashStable_Generic;
pub mod call;
@@ -19,48 +17,6 @@ impl ToJson for Endian {
}
}
-rustc_index::newtype_index! {
- #[derive(HashStable_Generic)]
- pub struct VariantIdx {}
-}
-
-#[derive(Copy, Clone, PartialEq, Eq, Hash, HashStable_Generic)]
-#[rustc_pass_by_value]
-pub struct Layout<'a>(pub Interned<'a, LayoutS<VariantIdx>>);
-
-impl<'a> fmt::Debug for Layout<'a> {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- // See comment on `<LayoutS as Debug>::fmt` above.
- self.0.0.fmt(f)
- }
-}
-
-impl<'a> Layout<'a> {
- pub fn fields(self) -> &'a FieldsShape {
- &self.0.0.fields
- }
-
- pub fn variants(self) -> &'a Variants<VariantIdx> {
- &self.0.0.variants
- }
-
- pub fn abi(self) -> Abi {
- self.0.0.abi
- }
-
- pub fn largest_niche(self) -> Option<Niche> {
- self.0.0.largest_niche
- }
-
- pub fn align(self) -> AbiAndPrefAlign {
- self.0.0.align
- }
-
- pub fn size(self) -> Size {
- self.0.0.size
- }
-}
-
/// The layout of a type, alongside the type itself.
/// Provides various type traversal APIs (e.g., recursing into fields).
///
@@ -75,8 +31,8 @@ pub struct TyAndLayout<'a, Ty> {
}
impl<'a, Ty> Deref for TyAndLayout<'a, Ty> {
- type Target = &'a LayoutS<VariantIdx>;
- fn deref(&self) -> &&'a LayoutS<VariantIdx> {
+ type Target = &'a LayoutS;
+ fn deref(&self) -> &&'a LayoutS {
&self.layout.0.0
}
}
@@ -129,7 +85,7 @@ impl<'a, Ty> TyAndLayout<'a, Ty> {
C: HasDataLayout,
{
match self.abi {
- Abi::Scalar(scalar) => scalar.primitive().is_float(),
+ Abi::Scalar(scalar) => matches!(scalar.primitive(), F32 | F64),
Abi::Aggregate { .. } => {
if self.fields.count() == 1 && self.fields.offset(0).bytes() == 0 {
self.field(cx, 0).is_single_fp_element(cx)
diff --git a/compiler/rustc_target/src/spec/aarch64_apple_ios.rs b/compiler/rustc_target/src/spec/aarch64_apple_ios.rs
index b5f9eb125..e9edfd287 100644
--- a/compiler/rustc_target/src/spec/aarch64_apple_ios.rs
+++ b/compiler/rustc_target/src/spec/aarch64_apple_ios.rs
@@ -1,8 +1,11 @@
use super::apple_base::{ios_llvm_target, opts, Arch};
-use crate::spec::{FramePointer, Target, TargetOptions};
+use crate::spec::{FramePointer, SanitizerSet, Target, TargetOptions};
pub fn target() -> Target {
let arch = Arch::Arm64;
+ let mut base = opts("ios", arch);
+ base.supported_sanitizers = SanitizerSet::ADDRESS | SanitizerSet::THREAD;
+
Target {
// Clang automatically chooses a more specific target based on
// IPHONEOS_DEPLOYMENT_TARGET.
@@ -28,7 +31,7 @@ pub fn target() -> Target {
darwinpcs\0\
-Os\0"
.into(),
- ..opts("ios", arch)
+ ..base
},
}
}
diff --git a/compiler/rustc_target/src/spec/aarch64_apple_ios_macabi.rs b/compiler/rustc_target/src/spec/aarch64_apple_ios_macabi.rs
index 0009972cf..2b135b670 100644
--- a/compiler/rustc_target/src/spec/aarch64_apple_ios_macabi.rs
+++ b/compiler/rustc_target/src/spec/aarch64_apple_ios_macabi.rs
@@ -2,7 +2,7 @@ use super::apple_base::{opts, Arch};
use crate::spec::{Cc, FramePointer, LinkerFlavor, Lld, Target, TargetOptions};
pub fn target() -> Target {
- let llvm_target = "arm64-apple-ios14.0-macabi";
+ let llvm_target = "arm64-apple-ios-macabi";
let arch = Arch::Arm64_macabi;
let mut base = opts("ios", arch);
@@ -22,7 +22,7 @@ pub fn target() -> Target {
// These arguments are not actually invoked - they just have
// to look right to pass App Store validation.
bitcode_llvm_cmdline: "-triple\0\
- arm64-apple-ios14.0-macabi\0\
+ arm64-apple-ios-macabi\0\
-emit-obj\0\
-disable-llvm-passes\0\
-Os\0"
diff --git a/compiler/rustc_target/src/spec/aarch64_apple_ios_sim.rs b/compiler/rustc_target/src/spec/aarch64_apple_ios_sim.rs
index 3374755e2..6e2d62b6e 100644
--- a/compiler/rustc_target/src/spec/aarch64_apple_ios_sim.rs
+++ b/compiler/rustc_target/src/spec/aarch64_apple_ios_sim.rs
@@ -1,8 +1,11 @@
use super::apple_base::{ios_sim_llvm_target, opts, Arch};
-use crate::spec::{FramePointer, Target, TargetOptions};
+use crate::spec::{FramePointer, SanitizerSet, Target, TargetOptions};
pub fn target() -> Target {
let arch = Arch::Arm64_sim;
+ let mut base = opts("ios", arch);
+ base.supported_sanitizers = SanitizerSet::ADDRESS | SanitizerSet::THREAD;
+
Target {
// Clang automatically chooses a more specific target based on
// IPHONEOS_DEPLOYMENT_TARGET.
@@ -28,7 +31,7 @@ pub fn target() -> Target {
darwinpcs\0\
-Os\0"
.into(),
- ..opts("ios", arch)
+ ..base
},
}
}
diff --git a/compiler/rustc_target/src/spec/aarch64_be_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/aarch64_be_unknown_linux_gnu.rs
index 9bce82a19..b84783c0a 100644
--- a/compiler/rustc_target/src/spec/aarch64_be_unknown_linux_gnu.rs
+++ b/compiler/rustc_target/src/spec/aarch64_be_unknown_linux_gnu.rs
@@ -8,7 +8,7 @@ pub fn target() -> Target {
data_layout: "E-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".into(),
arch: "aarch64".into(),
options: TargetOptions {
- features: "+outline-atomics".into(),
+ features: "+v8a,+outline-atomics".into(),
max_atomic_width: Some(128),
mcount: "\u{1}_mcount".into(),
endian: Endian::Big,
diff --git a/compiler/rustc_target/src/spec/aarch64_be_unknown_linux_gnu_ilp32.rs b/compiler/rustc_target/src/spec/aarch64_be_unknown_linux_gnu_ilp32.rs
index c9ceb55dd..a24e0119f 100644
--- a/compiler/rustc_target/src/spec/aarch64_be_unknown_linux_gnu_ilp32.rs
+++ b/compiler/rustc_target/src/spec/aarch64_be_unknown_linux_gnu_ilp32.rs
@@ -12,7 +12,7 @@ pub fn target() -> Target {
arch: "aarch64".into(),
options: TargetOptions {
abi: "ilp32".into(),
- features: "+outline-atomics".into(),
+ features: "+v8a,+outline-atomics".into(),
mcount: "\u{1}_mcount".into(),
endian: Endian::Big,
..base
diff --git a/compiler/rustc_target/src/spec/aarch64_kmc_solid_asp3.rs b/compiler/rustc_target/src/spec/aarch64_kmc_solid_asp3.rs
index 6ea9ae266..437fd6015 100644
--- a/compiler/rustc_target/src/spec/aarch64_kmc_solid_asp3.rs
+++ b/compiler/rustc_target/src/spec/aarch64_kmc_solid_asp3.rs
@@ -9,7 +9,7 @@ pub fn target() -> Target {
arch: "aarch64".into(),
options: TargetOptions {
linker: Some("aarch64-kmc-elf-gcc".into()),
- features: "+neon,+fp-armv8".into(),
+ features: "+v8a,+neon,+fp-armv8".into(),
relocation_model: RelocModel::Static,
disable_redzone: true,
max_atomic_width: Some(128),
diff --git a/compiler/rustc_target/src/spec/aarch64_linux_android.rs b/compiler/rustc_target/src/spec/aarch64_linux_android.rs
index c85f7f62a..071b727b3 100644
--- a/compiler/rustc_target/src/spec/aarch64_linux_android.rs
+++ b/compiler/rustc_target/src/spec/aarch64_linux_android.rs
@@ -13,12 +13,13 @@ pub fn target() -> Target {
max_atomic_width: Some(128),
// As documented in https://developer.android.com/ndk/guides/cpu-features.html
// the neon (ASIMD) and FP must exist on all android aarch64 targets.
- features: "+neon,+fp-armv8".into(),
+ features: "+v8a,+neon,+fp-armv8".into(),
supported_sanitizers: SanitizerSet::CFI
| SanitizerSet::HWADDRESS
| SanitizerSet::MEMTAG
| SanitizerSet::SHADOWCALLSTACK
| SanitizerSet::ADDRESS,
+ supports_xray: true,
..super::android_base::opts()
},
}
diff --git a/compiler/rustc_target/src/spec/aarch64_nintendo_switch_freestanding.rs b/compiler/rustc_target/src/spec/aarch64_nintendo_switch_freestanding.rs
index 529e98d2c..e271bdc8a 100644
--- a/compiler/rustc_target/src/spec/aarch64_nintendo_switch_freestanding.rs
+++ b/compiler/rustc_target/src/spec/aarch64_nintendo_switch_freestanding.rs
@@ -10,6 +10,7 @@ pub fn target() -> Target {
data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".into(),
arch: "aarch64".into(),
options: TargetOptions {
+ features: "+v8a".into(),
linker_flavor: LinkerFlavor::Gnu(Cc::No, Lld::Yes),
linker: Some("rust-lld".into()),
link_script: Some(LINKER_SCRIPT.into()),
diff --git a/compiler/rustc_target/src/spec/aarch64_pc_windows_gnullvm.rs b/compiler/rustc_target/src/spec/aarch64_pc_windows_gnullvm.rs
index 98d3e79c8..cf1d7ca11 100644
--- a/compiler/rustc_target/src/spec/aarch64_pc_windows_gnullvm.rs
+++ b/compiler/rustc_target/src/spec/aarch64_pc_windows_gnullvm.rs
@@ -3,7 +3,7 @@ use crate::spec::Target;
pub fn target() -> Target {
let mut base = super::windows_gnullvm_base::opts();
base.max_atomic_width = Some(128);
- base.features = "+neon,+fp-armv8".into();
+ base.features = "+v8a,+neon,+fp-armv8".into();
base.linker = Some("aarch64-w64-mingw32-clang".into());
Target {
diff --git a/compiler/rustc_target/src/spec/aarch64_pc_windows_msvc.rs b/compiler/rustc_target/src/spec/aarch64_pc_windows_msvc.rs
index 7c4544b3f..56b76bc7a 100644
--- a/compiler/rustc_target/src/spec/aarch64_pc_windows_msvc.rs
+++ b/compiler/rustc_target/src/spec/aarch64_pc_windows_msvc.rs
@@ -3,7 +3,7 @@ use crate::spec::Target;
pub fn target() -> Target {
let mut base = super::windows_msvc_base::opts();
base.max_atomic_width = Some(128);
- base.features = "+neon,+fp-armv8".into();
+ base.features = "+v8a,+neon,+fp-armv8".into();
Target {
llvm_target: "aarch64-pc-windows-msvc".into(),
diff --git a/compiler/rustc_target/src/spec/aarch64_unknown_freebsd.rs b/compiler/rustc_target/src/spec/aarch64_unknown_freebsd.rs
index 2f39c4862..84fa9814b 100644
--- a/compiler/rustc_target/src/spec/aarch64_unknown_freebsd.rs
+++ b/compiler/rustc_target/src/spec/aarch64_unknown_freebsd.rs
@@ -7,6 +7,7 @@ pub fn target() -> Target {
data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".into(),
arch: "aarch64".into(),
options: TargetOptions {
+ features: "+v8a".into(),
max_atomic_width: Some(128),
supported_sanitizers: SanitizerSet::ADDRESS
| SanitizerSet::CFI
diff --git a/compiler/rustc_target/src/spec/aarch64_unknown_fuchsia.rs b/compiler/rustc_target/src/spec/aarch64_unknown_fuchsia.rs
index ef2ab304f..a5683fa73 100644
--- a/compiler/rustc_target/src/spec/aarch64_unknown_fuchsia.rs
+++ b/compiler/rustc_target/src/spec/aarch64_unknown_fuchsia.rs
@@ -7,6 +7,7 @@ pub fn target() -> Target {
data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".into(),
arch: "aarch64".into(),
options: TargetOptions {
+ features: "+v8a".into(),
max_atomic_width: Some(128),
supported_sanitizers: SanitizerSet::ADDRESS
| SanitizerSet::CFI
diff --git a/compiler/rustc_target/src/spec/aarch64_unknown_hermit.rs b/compiler/rustc_target/src/spec/aarch64_unknown_hermit.rs
index 1d7269c8d..87e8d6270 100644
--- a/compiler/rustc_target/src/spec/aarch64_unknown_hermit.rs
+++ b/compiler/rustc_target/src/spec/aarch64_unknown_hermit.rs
@@ -3,7 +3,7 @@ use crate::spec::Target;
pub fn target() -> Target {
let mut base = super::hermit_base::opts();
base.max_atomic_width = Some(128);
- base.features = "+strict-align,+neon,+fp-armv8".into();
+ base.features = "+v8a,+strict-align,+neon,+fp-armv8".into();
Target {
llvm_target: "aarch64-unknown-hermit".into(),
diff --git a/compiler/rustc_target/src/spec/aarch64_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/aarch64_unknown_linux_gnu.rs
index 3006044d5..da2460894 100644
--- a/compiler/rustc_target/src/spec/aarch64_unknown_linux_gnu.rs
+++ b/compiler/rustc_target/src/spec/aarch64_unknown_linux_gnu.rs
@@ -7,7 +7,7 @@ pub fn target() -> Target {
data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".into(),
arch: "aarch64".into(),
options: TargetOptions {
- features: "+outline-atomics".into(),
+ features: "+v8a,+outline-atomics".into(),
mcount: "\u{1}_mcount".into(),
max_atomic_width: Some(128),
supported_sanitizers: SanitizerSet::ADDRESS
@@ -17,6 +17,7 @@ pub fn target() -> Target {
| SanitizerSet::MEMTAG
| SanitizerSet::THREAD
| SanitizerSet::HWADDRESS,
+ supports_xray: true,
..super::linux_gnu_base::opts()
},
}
diff --git a/compiler/rustc_target/src/spec/aarch64_unknown_linux_gnu_ilp32.rs b/compiler/rustc_target/src/spec/aarch64_unknown_linux_gnu_ilp32.rs
index 63023df1d..ad9df53c2 100644
--- a/compiler/rustc_target/src/spec/aarch64_unknown_linux_gnu_ilp32.rs
+++ b/compiler/rustc_target/src/spec/aarch64_unknown_linux_gnu_ilp32.rs
@@ -8,7 +8,7 @@ pub fn target() -> Target {
arch: "aarch64".into(),
options: TargetOptions {
abi: "ilp32".into(),
- features: "+outline-atomics".into(),
+ features: "+v8a,+outline-atomics".into(),
max_atomic_width: Some(128),
mcount: "\u{1}_mcount".into(),
..super::linux_gnu_base::opts()
diff --git a/compiler/rustc_target/src/spec/aarch64_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/aarch64_unknown_linux_musl.rs
index 002d0dac2..d0c950c2e 100644
--- a/compiler/rustc_target/src/spec/aarch64_unknown_linux_musl.rs
+++ b/compiler/rustc_target/src/spec/aarch64_unknown_linux_musl.rs
@@ -3,6 +3,8 @@ use crate::spec::{Target, TargetOptions};
pub fn target() -> Target {
let mut base = super::linux_musl_base::opts();
base.max_atomic_width = Some(128);
+ base.supports_xray = true;
+ base.features = "+v8a".into();
Target {
llvm_target: "aarch64-unknown-linux-musl".into(),
diff --git a/compiler/rustc_target/src/spec/aarch64_unknown_netbsd.rs b/compiler/rustc_target/src/spec/aarch64_unknown_netbsd.rs
index 703f75022..a58b64d3d 100644
--- a/compiler/rustc_target/src/spec/aarch64_unknown_netbsd.rs
+++ b/compiler/rustc_target/src/spec/aarch64_unknown_netbsd.rs
@@ -7,6 +7,7 @@ pub fn target() -> Target {
data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".into(),
arch: "aarch64".into(),
options: TargetOptions {
+ features: "+v8a".into(),
mcount: "__mcount".into(),
max_atomic_width: Some(128),
..super::netbsd_base::opts()
diff --git a/compiler/rustc_target/src/spec/aarch64_unknown_none.rs b/compiler/rustc_target/src/spec/aarch64_unknown_none.rs
index aca52e147..be27302f7 100644
--- a/compiler/rustc_target/src/spec/aarch64_unknown_none.rs
+++ b/compiler/rustc_target/src/spec/aarch64_unknown_none.rs
@@ -14,8 +14,8 @@ pub fn target() -> Target {
let opts = TargetOptions {
linker_flavor: LinkerFlavor::Gnu(Cc::No, Lld::Yes),
linker: Some("rust-lld".into()),
- features: "+strict-align,+neon,+fp-armv8".into(),
- supported_sanitizers: SanitizerSet::KCFI,
+ features: "+v8a,+strict-align,+neon,+fp-armv8".into(),
+ supported_sanitizers: SanitizerSet::KCFI | SanitizerSet::KERNELADDRESS,
relocation_model: RelocModel::Static,
disable_redzone: true,
max_atomic_width: Some(128),
diff --git a/compiler/rustc_target/src/spec/aarch64_unknown_none_softfloat.rs b/compiler/rustc_target/src/spec/aarch64_unknown_none_softfloat.rs
index 2385cb69a..9dfa1f268 100644
--- a/compiler/rustc_target/src/spec/aarch64_unknown_none_softfloat.rs
+++ b/compiler/rustc_target/src/spec/aarch64_unknown_none_softfloat.rs
@@ -13,7 +13,7 @@ pub fn target() -> Target {
abi: "softfloat".into(),
linker_flavor: LinkerFlavor::Gnu(Cc::No, Lld::Yes),
linker: Some("rust-lld".into()),
- features: "+strict-align,-neon,-fp-armv8".into(),
+ features: "+v8a,+strict-align,-neon,-fp-armv8".into(),
relocation_model: RelocModel::Static,
disable_redzone: true,
max_atomic_width: Some(128),
diff --git a/compiler/rustc_target/src/spec/aarch64_unknown_nto_qnx_710.rs b/compiler/rustc_target/src/spec/aarch64_unknown_nto_qnx_710.rs
index 916b6137b..8c1126ae6 100644
--- a/compiler/rustc_target/src/spec/aarch64_unknown_nto_qnx_710.rs
+++ b/compiler/rustc_target/src/spec/aarch64_unknown_nto_qnx_710.rs
@@ -17,6 +17,7 @@ pub fn target() -> Target {
data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".into(),
arch: "aarch64".into(),
options: TargetOptions {
+ features: "+v8a".into(),
max_atomic_width: Some(128),
pre_link_args: TargetOptions::link_args(
LinkerFlavor::Gnu(Cc::Yes, Lld::No),
diff --git a/compiler/rustc_target/src/spec/aarch64_unknown_openbsd.rs b/compiler/rustc_target/src/spec/aarch64_unknown_openbsd.rs
index 3d99040f0..224e31af2 100644
--- a/compiler/rustc_target/src/spec/aarch64_unknown_openbsd.rs
+++ b/compiler/rustc_target/src/spec/aarch64_unknown_openbsd.rs
@@ -6,6 +6,10 @@ pub fn target() -> Target {
pointer_width: 64,
data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".into(),
arch: "aarch64".into(),
- options: TargetOptions { max_atomic_width: Some(128), ..super::openbsd_base::opts() },
+ options: TargetOptions {
+ features: "+v8a".into(),
+ max_atomic_width: Some(128),
+ ..super::openbsd_base::opts()
+ },
}
}
diff --git a/compiler/rustc_target/src/spec/aarch64_unknown_redox.rs b/compiler/rustc_target/src/spec/aarch64_unknown_redox.rs
index 6c9be4c8e..5650162cd 100644
--- a/compiler/rustc_target/src/spec/aarch64_unknown_redox.rs
+++ b/compiler/rustc_target/src/spec/aarch64_unknown_redox.rs
@@ -3,6 +3,7 @@ use crate::spec::Target;
pub fn target() -> Target {
let mut base = super::redox_base::opts();
base.max_atomic_width = Some(128);
+ base.features = "+v8a".into();
Target {
llvm_target: "aarch64-unknown-redox".into(),
diff --git a/compiler/rustc_target/src/spec/aarch64_unknown_uefi.rs b/compiler/rustc_target/src/spec/aarch64_unknown_uefi.rs
index 817ff2422..82fb01556 100644
--- a/compiler/rustc_target/src/spec/aarch64_unknown_uefi.rs
+++ b/compiler/rustc_target/src/spec/aarch64_unknown_uefi.rs
@@ -9,6 +9,7 @@ pub fn target() -> Target {
base.max_atomic_width = Some(128);
base.add_pre_link_args(LinkerFlavor::Msvc(Lld::No), &["/machine:arm64"]);
+ base.features = "+v8a".into();
Target {
llvm_target: "aarch64-unknown-windows".into(),
diff --git a/compiler/rustc_target/src/spec/aarch64_uwp_windows_msvc.rs b/compiler/rustc_target/src/spec/aarch64_uwp_windows_msvc.rs
index db4dbf817..d39442d91 100644
--- a/compiler/rustc_target/src/spec/aarch64_uwp_windows_msvc.rs
+++ b/compiler/rustc_target/src/spec/aarch64_uwp_windows_msvc.rs
@@ -3,6 +3,7 @@ use crate::spec::Target;
pub fn target() -> Target {
let mut base = super::windows_uwp_msvc_base::opts();
base.max_atomic_width = Some(128);
+ base.features = "+v8a".into();
Target {
llvm_target: "aarch64-pc-windows-msvc".into(),
diff --git a/compiler/rustc_target/src/spec/aarch64_wrs_vxworks.rs b/compiler/rustc_target/src/spec/aarch64_wrs_vxworks.rs
index e118553df..7e2af4c7a 100644
--- a/compiler/rustc_target/src/spec/aarch64_wrs_vxworks.rs
+++ b/compiler/rustc_target/src/spec/aarch64_wrs_vxworks.rs
@@ -6,6 +6,10 @@ pub fn target() -> Target {
pointer_width: 64,
data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".into(),
arch: "aarch64".into(),
- options: TargetOptions { max_atomic_width: Some(128), ..super::vxworks_base::opts() },
+ options: TargetOptions {
+ features: "+v8a".into(),
+ max_atomic_width: Some(128),
+ ..super::vxworks_base::opts()
+ },
}
}
diff --git a/compiler/rustc_target/src/spec/arm64_32_apple_watchos.rs b/compiler/rustc_target/src/spec/arm64_32_apple_watchos.rs
index 52ee68e75..c757ed45e 100644
--- a/compiler/rustc_target/src/spec/arm64_32_apple_watchos.rs
+++ b/compiler/rustc_target/src/spec/arm64_32_apple_watchos.rs
@@ -9,7 +9,7 @@ pub fn target() -> Target {
data_layout: "e-m:o-p:32:32-i64:64-i128:128-n32:64-S128".into(),
arch: "aarch64".into(),
options: TargetOptions {
- features: "+neon,+fp-armv8,+apple-a7".into(),
+ features: "+v8a,+neon,+fp-armv8,+apple-a7".into(),
max_atomic_width: Some(128),
forces_embed_bitcode: true,
dynamic_linking: false,
diff --git a/compiler/rustc_target/src/spec/armebv7r_none_eabi.rs b/compiler/rustc_target/src/spec/armebv7r_none_eabi.rs
index 8c65d6afc..f6f46aac4 100644
--- a/compiler/rustc_target/src/spec/armebv7r_none_eabi.rs
+++ b/compiler/rustc_target/src/spec/armebv7r_none_eabi.rs
@@ -19,7 +19,7 @@ pub fn target() -> Target {
max_atomic_width: Some(32),
emit_debug_gdb_scripts: false,
// GCC and Clang default to 8 for arm-none here
- c_enum_min_bits: 8,
+ c_enum_min_bits: Some(8),
..Default::default()
},
}
diff --git a/compiler/rustc_target/src/spec/armebv7r_none_eabihf.rs b/compiler/rustc_target/src/spec/armebv7r_none_eabihf.rs
index 7013bc60d..9608efe8b 100644
--- a/compiler/rustc_target/src/spec/armebv7r_none_eabihf.rs
+++ b/compiler/rustc_target/src/spec/armebv7r_none_eabihf.rs
@@ -20,7 +20,7 @@ pub fn target() -> Target {
max_atomic_width: Some(32),
emit_debug_gdb_scripts: false,
// GCC and Clang default to 8 for arm-none here
- c_enum_min_bits: 8,
+ c_enum_min_bits: Some(8),
..Default::default()
},
}
diff --git a/compiler/rustc_target/src/spec/armv4t_none_eabi.rs b/compiler/rustc_target/src/spec/armv4t_none_eabi.rs
index 7ac1aab3b..28b109889 100644
--- a/compiler/rustc_target/src/spec/armv4t_none_eabi.rs
+++ b/compiler/rustc_target/src/spec/armv4t_none_eabi.rs
@@ -49,7 +49,7 @@ pub fn target() -> Target {
// from thumb_base, rust-lang/rust#44993.
emit_debug_gdb_scripts: false,
// from thumb_base, apparently gcc/clang give enums a minimum of 8 bits on no-os targets
- c_enum_min_bits: 8,
+ c_enum_min_bits: Some(8),
..Default::default()
},
}
diff --git a/compiler/rustc_target/src/spec/armv6k_nintendo_3ds.rs b/compiler/rustc_target/src/spec/armv6k_nintendo_3ds.rs
index 40ec6f961..23f4a5abf 100644
--- a/compiler/rustc_target/src/spec/armv6k_nintendo_3ds.rs
+++ b/compiler/rustc_target/src/spec/armv6k_nintendo_3ds.rs
@@ -29,8 +29,7 @@ pub fn target() -> Target {
pre_link_args,
exe_suffix: ".elf".into(),
no_default_libraries: false,
- // There are some issues in debug builds with this enabled in certain programs.
- has_thread_local: false,
+ has_thread_local: true,
..Default::default()
},
}
diff --git a/compiler/rustc_target/src/spec/armv7a_none_eabi.rs b/compiler/rustc_target/src/spec/armv7a_none_eabi.rs
index 4e20fb325..d59de86a2 100644
--- a/compiler/rustc_target/src/spec/armv7a_none_eabi.rs
+++ b/compiler/rustc_target/src/spec/armv7a_none_eabi.rs
@@ -27,7 +27,7 @@ pub fn target() -> Target {
max_atomic_width: Some(64),
panic_strategy: PanicStrategy::Abort,
emit_debug_gdb_scripts: false,
- c_enum_min_bits: 8,
+ c_enum_min_bits: Some(8),
..Default::default()
};
Target {
diff --git a/compiler/rustc_target/src/spec/armv7a_none_eabihf.rs b/compiler/rustc_target/src/spec/armv7a_none_eabihf.rs
index ae70129ae..8cdf3c36b 100644
--- a/compiler/rustc_target/src/spec/armv7a_none_eabihf.rs
+++ b/compiler/rustc_target/src/spec/armv7a_none_eabihf.rs
@@ -19,7 +19,7 @@ pub fn target() -> Target {
panic_strategy: PanicStrategy::Abort,
emit_debug_gdb_scripts: false,
// GCC and Clang default to 8 for arm-none here
- c_enum_min_bits: 8,
+ c_enum_min_bits: Some(8),
..Default::default()
};
Target {
diff --git a/compiler/rustc_target/src/spec/armv7r_none_eabi.rs b/compiler/rustc_target/src/spec/armv7r_none_eabi.rs
index 25f301ccc..5225abf44 100644
--- a/compiler/rustc_target/src/spec/armv7r_none_eabi.rs
+++ b/compiler/rustc_target/src/spec/armv7r_none_eabi.rs
@@ -18,7 +18,7 @@ pub fn target() -> Target {
max_atomic_width: Some(32),
emit_debug_gdb_scripts: false,
// GCC and Clang default to 8 for arm-none here
- c_enum_min_bits: 8,
+ c_enum_min_bits: Some(8),
..Default::default()
},
}
diff --git a/compiler/rustc_target/src/spec/armv7r_none_eabihf.rs b/compiler/rustc_target/src/spec/armv7r_none_eabihf.rs
index 40449759d..9a35e0461 100644
--- a/compiler/rustc_target/src/spec/armv7r_none_eabihf.rs
+++ b/compiler/rustc_target/src/spec/armv7r_none_eabihf.rs
@@ -19,7 +19,7 @@ pub fn target() -> Target {
max_atomic_width: Some(32),
emit_debug_gdb_scripts: false,
// GCC and Clang default to 8 for arm-none here
- c_enum_min_bits: 8,
+ c_enum_min_bits: Some(8),
..Default::default()
},
}
diff --git a/compiler/rustc_target/src/spec/bpf_base.rs b/compiler/rustc_target/src/spec/bpf_base.rs
index 2b00cda44..4d03747d0 100644
--- a/compiler/rustc_target/src/spec/bpf_base.rs
+++ b/compiler/rustc_target/src/spec/bpf_base.rs
@@ -6,7 +6,7 @@ pub fn opts(endian: Endian) -> TargetOptions {
allow_asm: true,
endian,
linker_flavor: LinkerFlavor::Bpf,
- atomic_cas: true,
+ atomic_cas: false,
dynamic_linking: true,
no_builtins: true,
panic_strategy: PanicStrategy::Abort,
diff --git a/compiler/rustc_target/src/spec/hexagon_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/hexagon_unknown_linux_musl.rs
index 3aad05eb2..4c6ab5f5a 100644
--- a/compiler/rustc_target/src/spec/hexagon_unknown_linux_musl.rs
+++ b/compiler/rustc_target/src/spec/hexagon_unknown_linux_musl.rs
@@ -11,7 +11,7 @@ pub fn target() -> Target {
base.has_rpath = true;
base.linker_flavor = LinkerFlavor::Unix(Cc::Yes);
- base.c_enum_min_bits = 8;
+ base.c_enum_min_bits = Some(8);
Target {
llvm_target: "hexagon-unknown-linux-musl".into(),
diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs
index a094c2c54..0d86a3032 100644
--- a/compiler/rustc_target/src/spec/mod.rs
+++ b/compiler/rustc_target/src/spec/mod.rs
@@ -812,6 +812,7 @@ bitflags::bitflags! {
const MEMTAG = 1 << 6;
const SHADOWCALLSTACK = 1 << 7;
const KCFI = 1 << 8;
+ const KERNELADDRESS = 1 << 9;
}
}
@@ -824,6 +825,7 @@ impl SanitizerSet {
SanitizerSet::ADDRESS => "address",
SanitizerSet::CFI => "cfi",
SanitizerSet::KCFI => "kcfi",
+ SanitizerSet::KERNELADDRESS => "kernel-address",
SanitizerSet::LEAK => "leak",
SanitizerSet::MEMORY => "memory",
SanitizerSet::MEMTAG => "memtag",
@@ -866,6 +868,7 @@ impl IntoIterator for SanitizerSet {
SanitizerSet::SHADOWCALLSTACK,
SanitizerSet::THREAD,
SanitizerSet::HWADDRESS,
+ SanitizerSet::KERNELADDRESS,
]
.iter()
.copied()
@@ -1344,10 +1347,18 @@ impl Target {
});
}
- dl.c_enum_min_size = match Integer::from_size(Size::from_bits(self.c_enum_min_bits)) {
- Ok(bits) => bits,
- Err(err) => return Err(TargetDataLayoutErrors::InvalidBitsSize { err }),
- };
+ dl.c_enum_min_size = self
+ .c_enum_min_bits
+ .map_or_else(
+ || {
+ self.c_int_width
+ .parse()
+ .map_err(|_| String::from("failed to parse c_int_width"))
+ },
+ Ok,
+ )
+ .and_then(|i| Integer::from_size(Size::from_bits(i)))
+ .map_err(|err| TargetDataLayoutErrors::InvalidBitsSize { err })?;
Ok(dl)
}
@@ -1701,8 +1712,8 @@ pub struct TargetOptions {
/// If present it's a default value to use for adjusting the C ABI.
pub default_adjusted_cabi: Option<Abi>,
- /// Minimum number of bits in #[repr(C)] enum. Defaults to 32.
- pub c_enum_min_bits: u64,
+ /// Minimum number of bits in #[repr(C)] enum. Defaults to the size of c_int
+ pub c_enum_min_bits: Option<u64>,
/// Whether or not the DWARF `.debug_aranges` section should be generated.
pub generate_arange_section: bool,
@@ -1718,6 +1729,9 @@ pub struct TargetOptions {
/// The ABI of entry function.
/// Default value is `Conv::C`, i.e. C call convention
pub entry_abi: Conv,
+
+ /// Whether the target supports XRay instrumentation.
+ pub supports_xray: bool,
}
/// Add arguments for the given flavor and also for its "twin" flavors
@@ -1932,11 +1946,12 @@ impl Default for TargetOptions {
supported_split_debuginfo: Cow::Borrowed(&[SplitDebuginfo::Off]),
supported_sanitizers: SanitizerSet::empty(),
default_adjusted_cabi: None,
- c_enum_min_bits: 32,
+ c_enum_min_bits: None,
generate_arange_section: true,
supports_stack_protector: true,
entry_name: "main".into(),
entry_abi: Conv::C,
+ supports_xray: false,
}
}
}
@@ -2118,12 +2133,6 @@ impl Target {
base.$key_name = s;
}
} );
- ($key_name:ident, u64) => ( {
- let name = (stringify!($key_name)).replace("_", "-");
- if let Some(s) = obj.remove(&name).and_then(|j| Json::as_u64(&j)) {
- base.$key_name = s;
- }
- } );
($key_name:ident, u32) => ( {
let name = (stringify!($key_name)).replace("_", "-");
if let Some(s) = obj.remove(&name).and_then(|b| b.as_u64()) {
@@ -2335,6 +2344,7 @@ impl Target {
Some("address") => SanitizerSet::ADDRESS,
Some("cfi") => SanitizerSet::CFI,
Some("kcfi") => SanitizerSet::KCFI,
+ Some("kernel-address") => SanitizerSet::KERNELADDRESS,
Some("leak") => SanitizerSet::LEAK,
Some("memory") => SanitizerSet::MEMORY,
Some("memtag") => SanitizerSet::MEMTAG,
@@ -2492,6 +2502,7 @@ impl Target {
key!(is_builtin, bool);
key!(c_int_width = "target-c-int-width");
+ key!(c_enum_min_bits, Option<u64>); // if None, matches c_int_width
key!(os);
key!(env);
key!(abi);
@@ -2587,11 +2598,11 @@ impl Target {
key!(supported_split_debuginfo, falliable_list)?;
key!(supported_sanitizers, SanitizerSet)?;
key!(default_adjusted_cabi, Option<Abi>)?;
- key!(c_enum_min_bits, u64);
key!(generate_arange_section, bool);
key!(supports_stack_protector, bool);
key!(entry_name);
key!(entry_abi, Conv)?;
+ key!(supports_xray, bool);
if base.is_builtin {
// This can cause unfortunate ICEs later down the line.
@@ -2845,6 +2856,7 @@ impl ToJson for Target {
target_option_val!(supports_stack_protector);
target_option_val!(entry_name);
target_option_val!(entry_abi);
+ target_option_val!(supports_xray);
if let Some(abi) = self.default_adjusted_cabi {
d.insert("default-adjusted-cabi".into(), Abi::name(abi).to_json());
diff --git a/compiler/rustc_target/src/spec/riscv64gc_unknown_none_elf.rs b/compiler/rustc_target/src/spec/riscv64gc_unknown_none_elf.rs
index 409b0b269..ab3c14e3f 100644
--- a/compiler/rustc_target/src/spec/riscv64gc_unknown_none_elf.rs
+++ b/compiler/rustc_target/src/spec/riscv64gc_unknown_none_elf.rs
@@ -1,6 +1,8 @@
use crate::spec::{Cc, CodeModel, LinkerFlavor, Lld, PanicStrategy};
use crate::spec::{RelocModel, Target, TargetOptions};
+use super::SanitizerSet;
+
pub fn target() -> Target {
Target {
data_layout: "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128".into(),
@@ -20,6 +22,7 @@ pub fn target() -> Target {
code_model: Some(CodeModel::Medium),
emit_debug_gdb_scripts: false,
eh_frame_header: false,
+ supported_sanitizers: SanitizerSet::KERNELADDRESS,
..Default::default()
},
}
diff --git a/compiler/rustc_target/src/spec/riscv64imac_unknown_none_elf.rs b/compiler/rustc_target/src/spec/riscv64imac_unknown_none_elf.rs
index 87aba9171..0f1821c99 100644
--- a/compiler/rustc_target/src/spec/riscv64imac_unknown_none_elf.rs
+++ b/compiler/rustc_target/src/spec/riscv64imac_unknown_none_elf.rs
@@ -1,5 +1,5 @@
use crate::spec::{Cc, CodeModel, LinkerFlavor, Lld, PanicStrategy};
-use crate::spec::{RelocModel, Target, TargetOptions};
+use crate::spec::{RelocModel, SanitizerSet, Target, TargetOptions};
pub fn target() -> Target {
Target {
@@ -19,6 +19,7 @@ pub fn target() -> Target {
code_model: Some(CodeModel::Medium),
emit_debug_gdb_scripts: false,
eh_frame_header: false,
+ supported_sanitizers: SanitizerSet::KERNELADDRESS,
..Default::default()
},
}
diff --git a/compiler/rustc_target/src/spec/s390x_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/s390x_unknown_linux_gnu.rs
index cda88de0e..f2c722b9a 100644
--- a/compiler/rustc_target/src/spec/s390x_unknown_linux_gnu.rs
+++ b/compiler/rustc_target/src/spec/s390x_unknown_linux_gnu.rs
@@ -1,5 +1,5 @@
use crate::abi::Endian;
-use crate::spec::{StackProbeType, Target};
+use crate::spec::{SanitizerSet, StackProbeType, Target};
pub fn target() -> Target {
let mut base = super::linux_gnu_base::opts();
@@ -13,6 +13,8 @@ pub fn target() -> Target {
base.max_atomic_width = Some(64);
base.min_global_align = Some(16);
base.stack_probes = StackProbeType::Inline;
+ base.supported_sanitizers =
+ SanitizerSet::ADDRESS | SanitizerSet::LEAK | SanitizerSet::MEMORY | SanitizerSet::THREAD;
Target {
llvm_target: "s390x-unknown-linux-gnu".into(),
diff --git a/compiler/rustc_target/src/spec/s390x_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/s390x_unknown_linux_musl.rs
index 91e63aee5..8fe9d023c 100644
--- a/compiler/rustc_target/src/spec/s390x_unknown_linux_musl.rs
+++ b/compiler/rustc_target/src/spec/s390x_unknown_linux_musl.rs
@@ -1,5 +1,5 @@
use crate::abi::Endian;
-use crate::spec::{StackProbeType, Target};
+use crate::spec::{SanitizerSet, StackProbeType, Target};
pub fn target() -> Target {
let mut base = super::linux_musl_base::opts();
@@ -14,6 +14,8 @@ pub fn target() -> Target {
base.min_global_align = Some(16);
base.static_position_independent_executables = true;
base.stack_probes = StackProbeType::Inline;
+ base.supported_sanitizers =
+ SanitizerSet::ADDRESS | SanitizerSet::LEAK | SanitizerSet::MEMORY | SanitizerSet::THREAD;
Target {
llvm_target: "s390x-unknown-linux-musl".into(),
diff --git a/compiler/rustc_target/src/spec/thumb_base.rs b/compiler/rustc_target/src/spec/thumb_base.rs
index 000766c57..4dcf47fe4 100644
--- a/compiler/rustc_target/src/spec/thumb_base.rs
+++ b/compiler/rustc_target/src/spec/thumb_base.rs
@@ -53,7 +53,7 @@ pub fn opts() -> TargetOptions {
frame_pointer: FramePointer::Always,
// ARM supports multiple ABIs for enums, the linux one matches the default of 32 here
// but any arm-none or thumb-none target will be defaulted to 8 on GCC and clang
- c_enum_min_bits: 8,
+ c_enum_min_bits: Some(8),
..Default::default()
}
}
diff --git a/compiler/rustc_target/src/spec/thumbv4t_none_eabi.rs b/compiler/rustc_target/src/spec/thumbv4t_none_eabi.rs
index 5a3e4c88d..e3734932f 100644
--- a/compiler/rustc_target/src/spec/thumbv4t_none_eabi.rs
+++ b/compiler/rustc_target/src/spec/thumbv4t_none_eabi.rs
@@ -55,7 +55,7 @@ pub fn target() -> Target {
// suggested from thumb_base, rust-lang/rust#44993.
emit_debug_gdb_scripts: false,
// suggested from thumb_base, with no-os gcc/clang use 8-bit enums
- c_enum_min_bits: 8,
+ c_enum_min_bits: Some(8),
frame_pointer: FramePointer::MayOmit,
main_needs_argc_argv: false,
diff --git a/compiler/rustc_target/src/spec/x86_64_apple_ios.rs b/compiler/rustc_target/src/spec/x86_64_apple_ios.rs
index fbd3ebd4d..1dcb47056 100644
--- a/compiler/rustc_target/src/spec/x86_64_apple_ios.rs
+++ b/compiler/rustc_target/src/spec/x86_64_apple_ios.rs
@@ -1,8 +1,11 @@
use super::apple_base::{ios_sim_llvm_target, opts, Arch};
-use crate::spec::{StackProbeType, Target, TargetOptions};
+use crate::spec::{SanitizerSet, StackProbeType, Target, TargetOptions};
pub fn target() -> Target {
let arch = Arch::X86_64_sim;
+ let mut base = opts("ios", arch);
+ base.supported_sanitizers = SanitizerSet::ADDRESS | SanitizerSet::THREAD;
+
Target {
llvm_target: ios_sim_llvm_target(arch).into(),
pointer_width: 64,
@@ -12,7 +15,7 @@ pub fn target() -> Target {
options: TargetOptions {
max_atomic_width: Some(64),
stack_probes: StackProbeType::X86,
- ..opts("ios", arch)
+ ..base
},
}
}
diff --git a/compiler/rustc_target/src/spec/x86_64_apple_ios_macabi.rs b/compiler/rustc_target/src/spec/x86_64_apple_ios_macabi.rs
index 0f3f85199..5a3e2a79b 100644
--- a/compiler/rustc_target/src/spec/x86_64_apple_ios_macabi.rs
+++ b/compiler/rustc_target/src/spec/x86_64_apple_ios_macabi.rs
@@ -2,7 +2,7 @@ use super::apple_base::{opts, Arch};
use crate::spec::{Cc, LinkerFlavor, Lld, StackProbeType, Target, TargetOptions};
pub fn target() -> Target {
- let llvm_target = "x86_64-apple-ios13.0-macabi";
+ let llvm_target = "x86_64-apple-ios-macabi";
let arch = Arch::X86_64_macabi;
let mut base = opts("ios", arch);
diff --git a/compiler/rustc_target/src/spec/x86_64_linux_android.rs b/compiler/rustc_target/src/spec/x86_64_linux_android.rs
index 9c9137848..a3bdb5f54 100644
--- a/compiler/rustc_target/src/spec/x86_64_linux_android.rs
+++ b/compiler/rustc_target/src/spec/x86_64_linux_android.rs
@@ -8,6 +8,7 @@ pub fn target() -> Target {
base.max_atomic_width = Some(64);
base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m64"]);
base.stack_probes = StackProbeType::X86;
+ base.supports_xray = true;
Target {
llvm_target: "x86_64-linux-android".into(),
diff --git a/compiler/rustc_target/src/spec/x86_64_unknown_freebsd.rs b/compiler/rustc_target/src/spec/x86_64_unknown_freebsd.rs
index 98988ab35..b41e5842a 100644
--- a/compiler/rustc_target/src/spec/x86_64_unknown_freebsd.rs
+++ b/compiler/rustc_target/src/spec/x86_64_unknown_freebsd.rs
@@ -8,6 +8,7 @@ pub fn target() -> Target {
base.stack_probes = StackProbeType::X86;
base.supported_sanitizers =
SanitizerSet::ADDRESS | SanitizerSet::CFI | SanitizerSet::MEMORY | SanitizerSet::THREAD;
+ base.supports_xray = true;
Target {
llvm_target: "x86_64-unknown-freebsd".into(),
diff --git a/compiler/rustc_target/src/spec/x86_64_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/x86_64_unknown_linux_gnu.rs
index a91ab365b..9af1049b8 100644
--- a/compiler/rustc_target/src/spec/x86_64_unknown_linux_gnu.rs
+++ b/compiler/rustc_target/src/spec/x86_64_unknown_linux_gnu.rs
@@ -12,6 +12,7 @@ pub fn target() -> Target {
| SanitizerSet::LEAK
| SanitizerSet::MEMORY
| SanitizerSet::THREAD;
+ base.supports_xray = true;
Target {
llvm_target: "x86_64-unknown-linux-gnu".into(),
diff --git a/compiler/rustc_target/src/spec/x86_64_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/x86_64_unknown_linux_musl.rs
index 9087dc3df..bf4cf7d7b 100644
--- a/compiler/rustc_target/src/spec/x86_64_unknown_linux_musl.rs
+++ b/compiler/rustc_target/src/spec/x86_64_unknown_linux_musl.rs
@@ -12,6 +12,7 @@ pub fn target() -> Target {
| SanitizerSet::LEAK
| SanitizerSet::MEMORY
| SanitizerSet::THREAD;
+ base.supports_xray = true;
Target {
llvm_target: "x86_64-unknown-linux-musl".into(),
diff --git a/compiler/rustc_target/src/spec/x86_64_unknown_netbsd.rs b/compiler/rustc_target/src/spec/x86_64_unknown_netbsd.rs
index 64ae425d8..74c434935 100644
--- a/compiler/rustc_target/src/spec/x86_64_unknown_netbsd.rs
+++ b/compiler/rustc_target/src/spec/x86_64_unknown_netbsd.rs
@@ -11,6 +11,7 @@ pub fn target() -> Target {
| SanitizerSet::LEAK
| SanitizerSet::MEMORY
| SanitizerSet::THREAD;
+ base.supports_xray = true;
Target {
llvm_target: "x86_64-unknown-netbsd".into(),
diff --git a/compiler/rustc_target/src/spec/x86_64_unknown_none.rs b/compiler/rustc_target/src/spec/x86_64_unknown_none.rs
index 32060c35c..43c5ce78c 100644
--- a/compiler/rustc_target/src/spec/x86_64_unknown_none.rs
+++ b/compiler/rustc_target/src/spec/x86_64_unknown_none.rs
@@ -20,7 +20,7 @@ pub fn target() -> Target {
features:
"-mmx,-sse,-sse2,-sse3,-ssse3,-sse4.1,-sse4.2,-3dnow,-3dnowa,-avx,-avx2,+soft-float"
.into(),
- supported_sanitizers: SanitizerSet::KCFI,
+ supported_sanitizers: SanitizerSet::KCFI | SanitizerSet::KERNELADDRESS,
disable_redzone: true,
panic_strategy: PanicStrategy::Abort,
code_model: Some(CodeModel::Kernel),
diff --git a/compiler/rustc_target/src/spec/x86_64_unknown_openbsd.rs b/compiler/rustc_target/src/spec/x86_64_unknown_openbsd.rs
index 66b8e2022..8e4d42a0a 100644
--- a/compiler/rustc_target/src/spec/x86_64_unknown_openbsd.rs
+++ b/compiler/rustc_target/src/spec/x86_64_unknown_openbsd.rs
@@ -6,6 +6,7 @@ pub fn target() -> Target {
base.max_atomic_width = Some(64);
base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m64"]);
base.stack_probes = StackProbeType::X86;
+ base.supports_xray = true;
Target {
llvm_target: "x86_64-unknown-openbsd".into(),
diff --git a/compiler/rustc_trait_selection/Cargo.toml b/compiler/rustc_trait_selection/Cargo.toml
index 90d879976..d3eba43b4 100644
--- a/compiler/rustc_trait_selection/Cargo.toml
+++ b/compiler/rustc_trait_selection/Cargo.toml
@@ -16,7 +16,6 @@ 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_serialize = { path = "../rustc_serialize" }
@@ -25,3 +24,4 @@ rustc_span = { path = "../rustc_span" }
rustc_target = { path = "../rustc_target" }
rustc_transmute = { path = "../rustc_transmute", features = ["rustc"] }
smallvec = { version = "1.8.1", features = ["union", "may_dangle"] }
+itertools = "0.10.1"
diff --git a/compiler/rustc_error_messages/locales/en-US/trait_selection.ftl b/compiler/rustc_trait_selection/locales/en-US.ftl
index 14eb4a550..14eb4a550 100644
--- a/compiler/rustc_error_messages/locales/en-US/trait_selection.ftl
+++ b/compiler/rustc_trait_selection/locales/en-US.ftl
diff --git a/compiler/rustc_trait_selection/src/errors.rs b/compiler/rustc_trait_selection/src/errors.rs
index 4405537c6..df7c4df18 100644
--- a/compiler/rustc_trait_selection/src/errors.rs
+++ b/compiler/rustc_trait_selection/src/errors.rs
@@ -1,4 +1,5 @@
-use rustc_errors::{fluent, ErrorGuaranteed, Handler, IntoDiagnostic};
+use crate::fluent_generated as fluent;
+use rustc_errors::{ErrorGuaranteed, Handler, IntoDiagnostic};
use rustc_macros::Diagnostic;
use rustc_middle::ty::{self, PolyTraitRef, Ty};
use rustc_span::{Span, Symbol};
@@ -69,19 +70,19 @@ impl IntoDiagnostic<'_> for NegativePositiveConflict<'_> {
diag.code(rustc_errors::error_code!(E0751));
match self.negative_impl_span {
Ok(span) => {
- diag.span_label(span, fluent::negative_implementation_here);
+ diag.span_label(span, fluent::trait_selection_negative_implementation_here);
}
Err(cname) => {
- diag.note(fluent::negative_implementation_in_crate);
+ diag.note(fluent::trait_selection_negative_implementation_in_crate);
diag.set_arg("negative_impl_cname", cname.to_string());
}
}
match self.positive_impl_span {
Ok(span) => {
- diag.span_label(span, fluent::positive_implementation_here);
+ diag.span_label(span, fluent::trait_selection_positive_implementation_here);
}
Err(cname) => {
- diag.note(fluent::positive_implementation_in_crate);
+ diag.note(fluent::trait_selection_positive_implementation_in_crate);
diag.set_arg("positive_impl_cname", cname.to_string());
}
}
diff --git a/compiler/rustc_trait_selection/src/infer.rs b/compiler/rustc_trait_selection/src/infer.rs
index 50c1787ef..9b47c7299 100644
--- a/compiler/rustc_trait_selection/src/infer.rs
+++ b/compiler/rustc_trait_selection/src/infer.rs
@@ -6,7 +6,7 @@ use rustc_hir::lang_items::LangItem;
use rustc_middle::arena::ArenaAllocatable;
use rustc_middle::infer::canonical::{Canonical, CanonicalQueryResponse, QueryResponse};
use rustc_middle::traits::query::Fallible;
-use rustc_middle::ty::{self, Ty, TypeFoldable, TypeVisitable};
+use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable, TypeVisitableExt};
use rustc_middle::ty::{GenericArg, ToPredicate};
use rustc_span::{Span, DUMMY_SP};
@@ -42,7 +42,7 @@ pub trait InferCtxtExt<'tcx> {
fn type_implements_trait(
&self,
trait_def_id: DefId,
- params: impl IntoIterator<Item = impl Into<GenericArg<'tcx>>>,
+ params: impl IntoIterator<Item: Into<GenericArg<'tcx>>>,
param_env: ty::ParamEnv<'tcx>,
) -> traits::EvaluationResult;
}
@@ -82,7 +82,7 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> {
fn type_implements_trait(
&self,
trait_def_id: DefId,
- params: impl IntoIterator<Item = impl Into<GenericArg<'tcx>>>,
+ params: impl IntoIterator<Item: Into<GenericArg<'tcx>>>,
param_env: ty::ParamEnv<'tcx>,
) -> traits::EvaluationResult {
let trait_ref = self.tcx.mk_trait_ref(trait_def_id, params);
@@ -104,8 +104,8 @@ pub trait InferCtxtBuilderExt<'tcx> {
operation: impl FnOnce(&ObligationCtxt<'_, 'tcx>, K) -> Fallible<R>,
) -> Fallible<CanonicalQueryResponse<'tcx, R>>
where
- K: TypeFoldable<'tcx>,
- R: Debug + TypeFoldable<'tcx>,
+ K: TypeFoldable<TyCtxt<'tcx>>,
+ R: Debug + TypeFoldable<TyCtxt<'tcx>>,
Canonical<'tcx, QueryResponse<'tcx, R>>: ArenaAllocatable<'tcx>;
}
@@ -125,15 +125,15 @@ impl<'tcx> InferCtxtBuilderExt<'tcx> for InferCtxtBuilder<'tcx> {
/// In part because we would need a `for<'tcx>` sort of
/// bound for the closure and in part because it is convenient to
/// have `'tcx` be free on this function so that we can talk about
- /// `K: TypeFoldable<'tcx>`.)
+ /// `K: TypeFoldable<TyCtxt<'tcx>>`.)
fn enter_canonical_trait_query<K, R>(
&mut self,
canonical_key: &Canonical<'tcx, K>,
operation: impl FnOnce(&ObligationCtxt<'_, 'tcx>, K) -> Fallible<R>,
) -> Fallible<CanonicalQueryResponse<'tcx, R>>
where
- K: TypeFoldable<'tcx>,
- R: Debug + TypeFoldable<'tcx>,
+ K: TypeFoldable<TyCtxt<'tcx>>,
+ R: Debug + TypeFoldable<TyCtxt<'tcx>>,
Canonical<'tcx, QueryResponse<'tcx, R>>: ArenaAllocatable<'tcx>,
{
let (infcx, key, canonical_inference_vars) =
diff --git a/compiler/rustc_trait_selection/src/lib.rs b/compiler/rustc_trait_selection/src/lib.rs
index 6fa094103..548b42cef 100644
--- a/compiler/rustc_trait_selection/src/lib.rs
+++ b/compiler/rustc_trait_selection/src/lib.rs
@@ -36,7 +36,12 @@ extern crate rustc_middle;
#[macro_use]
extern crate smallvec;
+use rustc_errors::{DiagnosticMessage, SubdiagnosticMessage};
+use rustc_macros::fluent_messages;
+
pub mod errors;
pub mod infer;
pub mod solve;
pub mod traits;
+
+fluent_messages! { "../locales/en-US.ftl" }
diff --git a/compiler/rustc_trait_selection/src/solve/assembly.rs b/compiler/rustc_trait_selection/src/solve/assembly.rs
index 31c1bc9ec..dec9f8016 100644
--- a/compiler/rustc_trait_selection/src/solve/assembly.rs
+++ b/compiler/rustc_trait_selection/src/solve/assembly.rs
@@ -1,7 +1,9 @@
//! Code shared by trait and projection goals for candidate assembly.
-use super::infcx_ext::InferCtxtExt;
+#[cfg(doc)]
+use super::trait_goals::structural_traits::*;
use super::{CanonicalResponse, Certainty, EvalCtxt, Goal, MaybeCause, QueryResult};
+use itertools::Itertools;
use rustc_hir::def_id::DefId;
use rustc_infer::traits::query::NoSolution;
use rustc_infer::traits::util::elaborate_predicates;
@@ -76,63 +78,135 @@ pub(super) enum CandidateSource {
/// let _y = x.clone();
/// }
/// ```
- AliasBound(usize),
+ AliasBound,
}
-pub(super) trait GoalKind<'tcx>: TypeFoldable<'tcx> + Copy + Eq {
+/// Methods used to assemble candidates for either trait or projection goals.
+pub(super) trait GoalKind<'tcx>: TypeFoldable<TyCtxt<'tcx>> + Copy + Eq {
fn self_ty(self) -> Ty<'tcx>;
fn with_self_ty(self, tcx: TyCtxt<'tcx>, self_ty: Ty<'tcx>) -> Self;
fn trait_def_id(self, tcx: TyCtxt<'tcx>) -> DefId;
- fn consider_impl_candidate(
+ // Consider a clause, which consists of a "assumption" and some "requirements",
+ // to satisfy a goal. If the requirements hold, then attempt to satisfy our
+ // goal by equating it with the assumption.
+ fn consider_implied_clause(
ecx: &mut EvalCtxt<'_, 'tcx>,
goal: Goal<'tcx, Self>,
- impl_def_id: DefId,
+ assumption: ty::Predicate<'tcx>,
+ requirements: impl IntoIterator<Item = Goal<'tcx, ty::Predicate<'tcx>>>,
) -> QueryResult<'tcx>;
- fn consider_assumption(
+ // Consider a clause specifically for a `dyn Trait` self type. This requires
+ // additionally checking all of the supertraits and object bounds to hold,
+ // since they're not implied by the well-formedness of the object type.
+ fn consider_object_bound_candidate(
ecx: &mut EvalCtxt<'_, 'tcx>,
goal: Goal<'tcx, Self>,
assumption: ty::Predicate<'tcx>,
) -> QueryResult<'tcx>;
+ fn consider_impl_candidate(
+ ecx: &mut EvalCtxt<'_, 'tcx>,
+ goal: Goal<'tcx, Self>,
+ impl_def_id: DefId,
+ ) -> QueryResult<'tcx>;
+
+ // A type implements an `auto trait` if its components do as well. These components
+ // are given by built-in rules from [`instantiate_constituent_tys_for_auto_trait`].
fn consider_auto_trait_candidate(
ecx: &mut EvalCtxt<'_, 'tcx>,
goal: Goal<'tcx, Self>,
) -> QueryResult<'tcx>;
+ // A trait alias holds if the RHS traits and `where` clauses hold.
fn consider_trait_alias_candidate(
ecx: &mut EvalCtxt<'_, 'tcx>,
goal: Goal<'tcx, Self>,
) -> QueryResult<'tcx>;
+ // A type is `Copy` or `Clone` if its components are `Sized`. These components
+ // are given by built-in rules from [`instantiate_constituent_tys_for_sized_trait`].
fn consider_builtin_sized_candidate(
ecx: &mut EvalCtxt<'_, 'tcx>,
goal: Goal<'tcx, Self>,
) -> QueryResult<'tcx>;
+ // A type is `Copy` or `Clone` if its components are `Copy` or `Clone`. These
+ // components are given by built-in rules from [`instantiate_constituent_tys_for_copy_clone_trait`].
fn consider_builtin_copy_clone_candidate(
ecx: &mut EvalCtxt<'_, 'tcx>,
goal: Goal<'tcx, Self>,
) -> QueryResult<'tcx>;
- fn consider_builtin_pointer_sized_candidate(
+ // A type is `PointerLike` if we can compute its layout, and that layout
+ // matches the layout of `usize`.
+ fn consider_builtin_pointer_like_candidate(
ecx: &mut EvalCtxt<'_, 'tcx>,
goal: Goal<'tcx, Self>,
) -> QueryResult<'tcx>;
+ // A callable type (a closure, fn def, or fn ptr) is known to implement the `Fn<A>`
+ // family of traits where `A` is given by the signature of the type.
fn consider_builtin_fn_trait_candidates(
ecx: &mut EvalCtxt<'_, 'tcx>,
goal: Goal<'tcx, Self>,
kind: ty::ClosureKind,
) -> QueryResult<'tcx>;
+ // `Tuple` is implemented if the `Self` type is a tuple.
fn consider_builtin_tuple_candidate(
ecx: &mut EvalCtxt<'_, 'tcx>,
goal: Goal<'tcx, Self>,
) -> QueryResult<'tcx>;
+
+ // `Pointee` is always implemented.
+ //
+ // See the projection implementation for the `Metadata` types for all of
+ // the built-in types. For structs, the metadata type is given by the struct
+ // tail.
+ fn consider_builtin_pointee_candidate(
+ ecx: &mut EvalCtxt<'_, 'tcx>,
+ goal: Goal<'tcx, Self>,
+ ) -> QueryResult<'tcx>;
+
+ // A generator (that comes from an `async` desugaring) is known to implement
+ // `Future<Output = O>`, where `O` is given by the generator's return type
+ // that was computed during type-checking.
+ fn consider_builtin_future_candidate(
+ ecx: &mut EvalCtxt<'_, 'tcx>,
+ goal: Goal<'tcx, Self>,
+ ) -> QueryResult<'tcx>;
+
+ // A generator (that doesn't come from an `async` desugaring) is known to
+ // implement `Generator<R, Yield = Y, Return = O>`, given the resume, yield,
+ // and return types of the generator computed during type-checking.
+ fn consider_builtin_generator_candidate(
+ ecx: &mut EvalCtxt<'_, 'tcx>,
+ goal: Goal<'tcx, Self>,
+ ) -> QueryResult<'tcx>;
+
+ // The most common forms of unsizing are array to slice, and concrete (Sized)
+ // type into a `dyn Trait`. ADTs and Tuples can also have their final field
+ // unsized if it's generic.
+ fn consider_builtin_unsize_candidate(
+ ecx: &mut EvalCtxt<'_, 'tcx>,
+ goal: Goal<'tcx, Self>,
+ ) -> QueryResult<'tcx>;
+
+ // `dyn Trait1` can be unsized to `dyn Trait2` if they are the same trait, or
+ // if `Trait2` is a (transitive) supertrait of `Trait2`.
+ fn consider_builtin_dyn_upcast_candidates(
+ ecx: &mut EvalCtxt<'_, 'tcx>,
+ goal: Goal<'tcx, Self>,
+ ) -> Vec<CanonicalResponse<'tcx>>;
+
+ fn consider_builtin_discriminant_kind_candidate(
+ ecx: &mut EvalCtxt<'_, 'tcx>,
+ goal: Goal<'tcx, Self>,
+ ) -> QueryResult<'tcx>;
}
impl<'tcx> EvalCtxt<'_, 'tcx> {
@@ -140,7 +214,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
&mut self,
goal: Goal<'tcx, G>,
) -> Vec<Candidate<'tcx>> {
- debug_assert_eq!(goal, self.infcx.resolve_vars_if_possible(goal));
+ debug_assert_eq!(goal, self.resolve_vars_if_possible(goal));
// HACK: `_: Trait` is ambiguous, because it may be satisfied via a builtin rule,
// object bound, alias bound, etc. We are unable to determine this until we can at
@@ -148,9 +222,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
if goal.predicate.self_ty().is_ty_var() {
return vec![Candidate {
source: CandidateSource::BuiltinImpl,
- result: self
- .make_canonical_response(Certainty::Maybe(MaybeCause::Ambiguity))
- .unwrap(),
+ result: self.make_canonical_response(Certainty::AMBIGUOUS).unwrap(),
}];
}
@@ -186,8 +258,8 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
let &ty::Alias(ty::Projection, projection_ty) = goal.predicate.self_ty().kind() else {
return
};
- self.infcx.probe(|_| {
- let normalized_ty = self.infcx.next_ty_infer();
+ self.probe(|this| {
+ let normalized_ty = this.next_ty_infer();
let normalizes_to_goal = goal.with(
tcx,
ty::Binder::dummy(ty::ProjectionPredicate {
@@ -195,18 +267,16 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
term: normalized_ty.into(),
}),
);
- let normalization_certainty = match self.evaluate_goal(normalizes_to_goal) {
+ let normalization_certainty = match this.evaluate_goal(normalizes_to_goal) {
Ok((_, certainty)) => certainty,
Err(NoSolution) => return,
};
- let normalized_ty = self.infcx.resolve_vars_if_possible(normalized_ty);
+ let normalized_ty = this.resolve_vars_if_possible(normalized_ty);
// NOTE: Alternatively we could call `evaluate_goal` here and only have a `Normalized` candidate.
// This doesn't work as long as we use `CandidateSource` in winnowing.
let goal = goal.with(tcx, goal.predicate.with_self_ty(tcx, normalized_ty));
- // FIXME: This is broken if we care about the `usize` of `AliasBound` because the self type
- // could be normalized to yet another projection with different item bounds.
- let normalized_candidates = self.assemble_and_evaluate_candidates(goal);
+ let normalized_candidates = this.assemble_and_evaluate_candidates(goal);
for mut normalized_candidate in normalized_candidates {
normalized_candidate.result =
normalized_candidate.result.unchecked_map(|mut response| {
@@ -255,12 +325,22 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
|| lang_items.clone_trait() == Some(trait_def_id)
{
G::consider_builtin_copy_clone_candidate(self, goal)
- } else if lang_items.pointer_sized() == Some(trait_def_id) {
- G::consider_builtin_pointer_sized_candidate(self, goal)
+ } else if lang_items.pointer_like() == Some(trait_def_id) {
+ G::consider_builtin_pointer_like_candidate(self, goal)
} else if let Some(kind) = self.tcx().fn_trait_kind_from_def_id(trait_def_id) {
G::consider_builtin_fn_trait_candidates(self, goal, kind)
} else if lang_items.tuple_trait() == Some(trait_def_id) {
G::consider_builtin_tuple_candidate(self, goal)
+ } else if lang_items.pointee_trait() == Some(trait_def_id) {
+ G::consider_builtin_pointee_candidate(self, goal)
+ } else if lang_items.future_trait() == Some(trait_def_id) {
+ G::consider_builtin_future_candidate(self, goal)
+ } else if lang_items.gen_trait() == Some(trait_def_id) {
+ G::consider_builtin_generator_candidate(self, goal)
+ } else if lang_items.unsize_trait() == Some(trait_def_id) {
+ G::consider_builtin_unsize_candidate(self, goal)
+ } else if lang_items.discriminant_kind_trait() == Some(trait_def_id) {
+ G::consider_builtin_discriminant_kind_candidate(self, goal)
} else {
Err(NoSolution)
};
@@ -271,6 +351,14 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
}
Err(NoSolution) => (),
}
+
+ // There may be multiple unsize candidates for a trait with several supertraits:
+ // `trait Foo: Bar<A> + Bar<B>` and `dyn Foo: Unsize<dyn Bar<_>>`
+ if lang_items.unsize_trait() == Some(trait_def_id) {
+ for result in G::consider_builtin_dyn_upcast_candidates(self, goal) {
+ candidates.push(Candidate { source: CandidateSource::BuiltinImpl, result });
+ }
+ }
}
fn assemble_param_env_candidates<G: GoalKind<'tcx>>(
@@ -279,7 +367,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
candidates: &mut Vec<Candidate<'tcx>>,
) {
for (i, assumption) in goal.param_env.caller_bounds().iter().enumerate() {
- match G::consider_assumption(self, goal, assumption) {
+ match G::consider_implied_clause(self, goal, assumption, []) {
Ok(result) => {
candidates.push(Candidate { source: CandidateSource::ParamEnv(i), result })
}
@@ -312,25 +400,23 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
| ty::Closure(..)
| ty::Generator(..)
| ty::GeneratorWitness(_)
+ | ty::GeneratorWitnessMIR(..)
| ty::Never
| ty::Tuple(_)
| ty::Param(_)
| ty::Placeholder(..)
- | ty::Infer(_)
+ | ty::Infer(ty::IntVar(_) | ty::FloatVar(_))
| ty::Error(_) => return,
- ty::Bound(..) => bug!("unexpected bound type: {goal:?}"),
+ ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_))
+ | ty::Bound(..) => bug!("unexpected self type for `{goal:?}`"),
ty::Alias(_, alias_ty) => alias_ty,
};
- for (i, (assumption, _)) in self
- .tcx()
- .bound_explicit_item_bounds(alias_ty.def_id)
- .subst_iter_copied(self.tcx(), alias_ty.substs)
- .enumerate()
+ for assumption in self.tcx().item_bounds(alias_ty.def_id).subst(self.tcx(), alias_ty.substs)
{
- match G::consider_assumption(self, goal, assumption) {
+ match G::consider_implied_clause(self, goal, assumption, []) {
Ok(result) => {
- candidates.push(Candidate { source: CandidateSource::AliasBound(i), result })
+ candidates.push(Candidate { source: CandidateSource::AliasBound, result })
}
Err(NoSolution) => (),
}
@@ -362,13 +448,15 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
| ty::Closure(..)
| ty::Generator(..)
| ty::GeneratorWitness(_)
+ | ty::GeneratorWitnessMIR(..)
| ty::Never
| ty::Tuple(_)
| ty::Param(_)
| ty::Placeholder(..)
- | ty::Infer(_)
+ | ty::Infer(ty::IntVar(_) | ty::FloatVar(_))
| ty::Error(_) => return,
- ty::Bound(..) => bug!("unexpected bound type: {goal:?}"),
+ ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_))
+ | ty::Bound(..) => bug!("unexpected self type for `{goal:?}`"),
ty::Dynamic(bounds, ..) => bounds,
};
@@ -376,7 +464,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
for assumption in
elaborate_predicates(tcx, bounds.iter().map(|bound| bound.with_self_ty(tcx, self_ty)))
{
- match G::consider_assumption(self, goal, assumption.predicate) {
+ match G::consider_object_bound_candidate(self, goal, assumption.predicate) {
Ok(result) => {
candidates.push(Candidate { source: CandidateSource::BuiltinImpl, result })
}
@@ -384,4 +472,79 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
}
}
}
+
+ #[instrument(level = "debug", skip(self), ret)]
+ pub(super) fn merge_candidates_and_discard_reservation_impls(
+ &mut self,
+ mut candidates: Vec<Candidate<'tcx>>,
+ ) -> QueryResult<'tcx> {
+ match candidates.len() {
+ 0 => return Err(NoSolution),
+ 1 => return Ok(self.discard_reservation_impl(candidates.pop().unwrap()).result),
+ _ => {}
+ }
+
+ if candidates.len() > 1 {
+ let mut i = 0;
+ 'outer: while i < candidates.len() {
+ for j in (0..candidates.len()).filter(|&j| i != j) {
+ if self.trait_candidate_should_be_dropped_in_favor_of(
+ &candidates[i],
+ &candidates[j],
+ ) {
+ debug!(candidate = ?candidates[i], "Dropping candidate #{}/{}", i, candidates.len());
+ candidates.swap_remove(i);
+ continue 'outer;
+ }
+ }
+
+ debug!(candidate = ?candidates[i], "Retaining candidate #{}/{}", i, candidates.len());
+ i += 1;
+ }
+
+ // If there are *STILL* multiple candidates that have *different* response
+ // results, give up and report ambiguity.
+ if candidates.len() > 1 && !candidates.iter().map(|cand| cand.result).all_equal() {
+ let certainty = if candidates.iter().all(|x| {
+ matches!(x.result.value.certainty, Certainty::Maybe(MaybeCause::Overflow))
+ }) {
+ Certainty::Maybe(MaybeCause::Overflow)
+ } else {
+ Certainty::AMBIGUOUS
+ };
+ return self.make_canonical_response(certainty);
+ }
+ }
+
+ // FIXME: What if there are >1 candidates left with the same response, and one is a reservation impl?
+ Ok(self.discard_reservation_impl(candidates.pop().unwrap()).result)
+ }
+
+ fn trait_candidate_should_be_dropped_in_favor_of(
+ &self,
+ candidate: &Candidate<'tcx>,
+ other: &Candidate<'tcx>,
+ ) -> bool {
+ // FIXME: implement this
+ match (candidate.source, other.source) {
+ (CandidateSource::Impl(_), _)
+ | (CandidateSource::ParamEnv(_), _)
+ | (CandidateSource::AliasBound, _)
+ | (CandidateSource::BuiltinImpl, _) => false,
+ }
+ }
+
+ fn discard_reservation_impl(&self, mut candidate: Candidate<'tcx>) -> Candidate<'tcx> {
+ if let CandidateSource::Impl(def_id) = candidate.source {
+ if let ty::ImplPolarity::Reservation = self.tcx().impl_polarity(def_id) {
+ debug!("Selected reservation impl");
+ // We assemble all candidates inside of a probe so by
+ // making a new canonical response here our result will
+ // have no constraints.
+ candidate.result = self.make_canonical_response(Certainty::AMBIGUOUS).unwrap();
+ }
+ }
+
+ candidate
+ }
}
diff --git a/compiler/rustc_trait_selection/src/solve/canonical/canonicalize.rs b/compiler/rustc_trait_selection/src/solve/canonical/canonicalize.rs
new file mode 100644
index 000000000..c048d4a2a
--- /dev/null
+++ b/compiler/rustc_trait_selection/src/solve/canonical/canonicalize.rs
@@ -0,0 +1,390 @@
+use std::cmp::Ordering;
+
+use crate::infer::InferCtxt;
+use rustc_middle::infer::canonical::Canonical;
+use rustc_middle::infer::canonical::CanonicalTyVarKind;
+use rustc_middle::infer::canonical::CanonicalVarInfo;
+use rustc_middle::infer::canonical::CanonicalVarInfos;
+use rustc_middle::infer::canonical::CanonicalVarKind;
+use rustc_middle::ty::BoundRegionKind::BrAnon;
+use rustc_middle::ty::BoundTyKind;
+use rustc_middle::ty::TyCtxt;
+use rustc_middle::ty::TypeVisitableExt;
+use rustc_middle::ty::{self, Ty};
+use rustc_middle::ty::{TypeFoldable, TypeFolder, TypeSuperFoldable};
+
+/// Whether we're canonicalizing a query input or the query reponse.
+///
+/// When canonicalizing an input we're in the context of the caller
+/// while canonicalizing the response happens in the context of the
+/// query.
+#[derive(Debug, Clone, Copy)]
+pub enum CanonicalizeMode {
+ Input,
+ /// FIXME: We currently return region constraints refering to
+ /// placeholders and inference variables from a binder instantiated
+ /// inside of the query.
+ ///
+ /// In the long term we should eagerly deal with these constraints
+ /// inside of the query and only propagate constraints which are
+ /// actually nameable by the caller.
+ Response {
+ /// The highest universe nameable by the caller.
+ ///
+ /// All variables in a universe nameable by the caller get mapped
+ /// to the root universe in the response and then mapped back to
+ /// their correct universe when applying the query response in the
+ /// context of the caller.
+ ///
+ /// This doesn't work for universes created inside of the query so
+ /// we do remember their universe in the response.
+ max_input_universe: ty::UniverseIndex,
+ },
+}
+
+pub struct Canonicalizer<'a, 'tcx> {
+ infcx: &'a InferCtxt<'tcx>,
+ canonicalize_mode: CanonicalizeMode,
+
+ variables: &'a mut Vec<ty::GenericArg<'tcx>>,
+ primitive_var_infos: Vec<CanonicalVarInfo<'tcx>>,
+ binder_index: ty::DebruijnIndex,
+}
+
+impl<'a, 'tcx> Canonicalizer<'a, 'tcx> {
+ #[instrument(level = "debug", skip(infcx), ret)]
+ pub fn canonicalize<T: TypeFoldable<TyCtxt<'tcx>>>(
+ infcx: &'a InferCtxt<'tcx>,
+ canonicalize_mode: CanonicalizeMode,
+ variables: &'a mut Vec<ty::GenericArg<'tcx>>,
+ value: T,
+ ) -> Canonical<'tcx, T> {
+ let mut canonicalizer = Canonicalizer {
+ infcx,
+ canonicalize_mode,
+
+ variables,
+ primitive_var_infos: Vec::new(),
+ binder_index: ty::INNERMOST,
+ };
+
+ let value = value.fold_with(&mut canonicalizer);
+ assert!(!value.needs_infer());
+ assert!(!value.has_placeholders());
+
+ let (max_universe, variables) = canonicalizer.finalize();
+
+ Canonical { max_universe, variables, value }
+ }
+
+ fn finalize(self) -> (ty::UniverseIndex, CanonicalVarInfos<'tcx>) {
+ let mut var_infos = self.primitive_var_infos;
+ // See the rustc-dev-guide section about how we deal with universes
+ // during canonicalization in the new solver.
+ match self.canonicalize_mode {
+ // We try to deduplicate as many query calls as possible and hide
+ // all information which should not matter for the solver.
+ //
+ // For this we compress universes as much as possible.
+ CanonicalizeMode::Input => {}
+ // When canonicalizing a response we map a universes already entered
+ // by the caller to the root universe and only return useful universe
+ // information for placeholders and inference variables created inside
+ // of the query.
+ CanonicalizeMode::Response { max_input_universe } => {
+ for var in var_infos.iter_mut() {
+ let uv = var.universe();
+ let new_uv = ty::UniverseIndex::from(
+ uv.index().saturating_sub(max_input_universe.index()),
+ );
+ *var = var.with_updated_universe(new_uv);
+ }
+ let max_universe = var_infos
+ .iter()
+ .map(|info| info.universe())
+ .max()
+ .unwrap_or(ty::UniverseIndex::ROOT);
+
+ let var_infos = self.infcx.tcx.mk_canonical_var_infos(&var_infos);
+ return (max_universe, var_infos);
+ }
+ }
+
+ // Given a `var_infos` with existentials `En` and universals `Un` in
+ // universes `n`, this algorithm compresses them in place so that:
+ //
+ // - the new universe indices are as small as possible
+ // - we only create a new universe if we would otherwise put a placeholder in
+ // the same compressed universe as an existential which cannot name it
+ //
+ // Let's walk through an example:
+ // - var_infos: [E0, U1, E5, U2, E2, E6, U6], curr_compressed_uv: 0, next_orig_uv: 0
+ // - var_infos: [E0, U1, E5, U2, E2, E6, U6], curr_compressed_uv: 0, next_orig_uv: 1
+ // - var_infos: [E0, U1, E5, U2, E2, E6, U6], curr_compressed_uv: 1, next_orig_uv: 2
+ // - var_infos: [E0, U1, E5, U1, E1, E6, U6], curr_compressed_uv: 1, next_orig_uv: 5
+ // - var_infos: [E0, U1, E1, U1, E1, E6, U6], curr_compressed_uv: 1, next_orig_uv: 6
+ // - var_infos: [E0, U1, E1, U1, E1, E2, U2], curr_compressed_uv: 2, next_orig_uv: -
+ //
+ // This algorithm runs in `O(n²)` where `n` is the number of different universe
+ // indices in the input. This should be fine as `n` is expected to be small.
+ let mut curr_compressed_uv = ty::UniverseIndex::ROOT;
+ let mut existential_in_new_uv = false;
+ let mut next_orig_uv = Some(ty::UniverseIndex::ROOT);
+ while let Some(orig_uv) = next_orig_uv.take() {
+ let mut update_uv = |var: &mut CanonicalVarInfo<'tcx>, orig_uv, is_existential| {
+ let uv = var.universe();
+ match uv.cmp(&orig_uv) {
+ Ordering::Less => (), // Already updated
+ Ordering::Equal => {
+ if is_existential {
+ existential_in_new_uv = true;
+ } else if existential_in_new_uv {
+ // `var` is a placeholder from a universe which is not nameable
+ // by an existential which we already put into the compressed
+ // universe `curr_compressed_uv`. We therefore have to create a
+ // new universe for `var`.
+ curr_compressed_uv = curr_compressed_uv.next_universe();
+ existential_in_new_uv = false;
+ }
+
+ *var = var.with_updated_universe(curr_compressed_uv);
+ }
+ Ordering::Greater => {
+ // We can ignore this variable in this iteration. We only look at
+ // universes which actually occur in the input for performance.
+ //
+ // For this we set `next_orig_uv` to the next smallest, not yet compressed,
+ // universe of the input.
+ if next_orig_uv.map_or(true, |curr_next_uv| uv.cannot_name(curr_next_uv)) {
+ next_orig_uv = Some(uv);
+ }
+ }
+ }
+ };
+
+ // For each universe which occurs in the input, we first iterate over all
+ // placeholders and then over all inference variables.
+ //
+ // Whenever we compress the universe of a placeholder, no existential with
+ // an already compressed universe can name that placeholder.
+ for is_existential in [false, true] {
+ for var in var_infos.iter_mut() {
+ // We simply put all regions from the input into the highest
+ // compressed universe, so we only deal with them at the end.
+ if !var.is_region() {
+ if is_existential == var.is_existential() {
+ update_uv(var, orig_uv, is_existential)
+ }
+ }
+ }
+ }
+ }
+
+ for var in var_infos.iter_mut() {
+ if var.is_region() {
+ assert!(var.is_existential());
+ *var = var.with_updated_universe(curr_compressed_uv);
+ }
+ }
+
+ let var_infos = self.infcx.tcx.mk_canonical_var_infos(&var_infos);
+ (curr_compressed_uv, var_infos)
+ }
+}
+
+impl<'tcx> TypeFolder<TyCtxt<'tcx>> for Canonicalizer<'_, 'tcx> {
+ fn interner(&self) -> TyCtxt<'tcx> {
+ self.infcx.tcx
+ }
+
+ fn fold_binder<T>(&mut self, t: ty::Binder<'tcx, T>) -> ty::Binder<'tcx, T>
+ where
+ T: TypeFoldable<TyCtxt<'tcx>>,
+ {
+ self.binder_index.shift_in(1);
+ let t = t.super_fold_with(self);
+ self.binder_index.shift_out(1);
+ t
+ }
+
+ fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
+ let r = self.infcx.shallow_resolve(r);
+ let kind = match *r {
+ ty::ReLateBound(..) => return r,
+
+ ty::ReStatic => match self.canonicalize_mode {
+ CanonicalizeMode::Input => CanonicalVarKind::Region(ty::UniverseIndex::ROOT),
+ CanonicalizeMode::Response { .. } => return r,
+ },
+
+ ty::ReErased | ty::ReFree(_) | ty::ReEarlyBound(_) => match self.canonicalize_mode {
+ CanonicalizeMode::Input => CanonicalVarKind::Region(ty::UniverseIndex::ROOT),
+ CanonicalizeMode::Response { .. } => bug!("unexpected region in response: {r:?}"),
+ },
+
+ ty::RePlaceholder(placeholder) => match self.canonicalize_mode {
+ // We canonicalize placeholder regions as existentials in query inputs.
+ CanonicalizeMode::Input => CanonicalVarKind::Region(ty::UniverseIndex::ROOT),
+ CanonicalizeMode::Response { max_input_universe } => {
+ // If we have a placeholder region inside of a query, it must be from
+ // a new universe.
+ if max_input_universe.can_name(placeholder.universe) {
+ bug!("new placeholder in universe {max_input_universe:?}: {r:?}");
+ }
+ CanonicalVarKind::PlaceholderRegion(placeholder)
+ }
+ },
+
+ ty::ReVar(_) => match self.canonicalize_mode {
+ CanonicalizeMode::Input => CanonicalVarKind::Region(ty::UniverseIndex::ROOT),
+ CanonicalizeMode::Response { .. } => {
+ CanonicalVarKind::Region(self.infcx.universe_of_region(r))
+ }
+ },
+
+ ty::ReError(_) => return r,
+ };
+
+ let existing_bound_var = match self.canonicalize_mode {
+ CanonicalizeMode::Input => None,
+ CanonicalizeMode::Response { .. } => {
+ self.variables.iter().position(|&v| v == r.into()).map(ty::BoundVar::from)
+ }
+ };
+ let var = existing_bound_var.unwrap_or_else(|| {
+ let var = ty::BoundVar::from(self.variables.len());
+ self.variables.push(r.into());
+ self.primitive_var_infos.push(CanonicalVarInfo { kind });
+ var
+ });
+ let br = ty::BoundRegion { var, kind: BrAnon(var.as_u32(), None) };
+ self.interner().mk_re_late_bound(self.binder_index, br)
+ }
+
+ fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
+ let kind = match *t.kind() {
+ ty::Infer(ty::TyVar(vid)) => match self.infcx.probe_ty_var(vid) {
+ Ok(t) => return self.fold_ty(t),
+ Err(ui) => CanonicalVarKind::Ty(CanonicalTyVarKind::General(ui)),
+ },
+ ty::Infer(ty::IntVar(_)) => {
+ let nt = self.infcx.shallow_resolve(t);
+ if nt != t {
+ return self.fold_ty(nt);
+ } else {
+ CanonicalVarKind::Ty(CanonicalTyVarKind::Int)
+ }
+ }
+ ty::Infer(ty::FloatVar(_)) => {
+ let nt = self.infcx.shallow_resolve(t);
+ if nt != t {
+ return self.fold_ty(nt);
+ } else {
+ CanonicalVarKind::Ty(CanonicalTyVarKind::Int)
+ }
+ }
+ ty::Infer(ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => {
+ bug!("fresh var during canonicalization: {t:?}")
+ }
+ ty::Placeholder(placeholder) => match self.canonicalize_mode {
+ CanonicalizeMode::Input => CanonicalVarKind::PlaceholderTy(ty::Placeholder {
+ universe: placeholder.universe,
+ name: BoundTyKind::Anon(self.variables.len() as u32),
+ }),
+ CanonicalizeMode::Response { .. } => CanonicalVarKind::PlaceholderTy(placeholder),
+ },
+ ty::Param(_) => match self.canonicalize_mode {
+ CanonicalizeMode::Input => CanonicalVarKind::PlaceholderTy(ty::Placeholder {
+ universe: ty::UniverseIndex::ROOT,
+ name: ty::BoundTyKind::Anon(self.variables.len() as u32),
+ }),
+ CanonicalizeMode::Response { .. } => bug!("param ty in response: {t:?}"),
+ },
+ ty::Bool
+ | ty::Char
+ | ty::Int(_)
+ | ty::Uint(_)
+ | ty::Float(_)
+ | ty::Adt(_, _)
+ | ty::Foreign(_)
+ | ty::Str
+ | ty::Array(_, _)
+ | ty::Slice(_)
+ | ty::RawPtr(_)
+ | ty::Ref(_, _, _)
+ | ty::FnDef(_, _)
+ | ty::FnPtr(_)
+ | ty::Dynamic(_, _, _)
+ | ty::Closure(_, _)
+ | ty::Generator(_, _, _)
+ | ty::GeneratorWitness(_)
+ | ty::GeneratorWitnessMIR(..)
+ | ty::Never
+ | ty::Tuple(_)
+ | ty::Alias(_, _)
+ | ty::Bound(_, _)
+ | ty::Error(_) => return t.super_fold_with(self),
+ };
+
+ let var = ty::BoundVar::from(
+ self.variables.iter().position(|&v| v == t.into()).unwrap_or_else(|| {
+ let var = self.variables.len();
+ self.variables.push(t.into());
+ self.primitive_var_infos.push(CanonicalVarInfo { kind });
+ var
+ }),
+ );
+ let bt = ty::BoundTy { var, kind: BoundTyKind::Anon(var.index() as u32) };
+ self.interner().mk_bound(self.binder_index, bt)
+ }
+
+ fn fold_const(&mut self, c: ty::Const<'tcx>) -> ty::Const<'tcx> {
+ let kind = match c.kind() {
+ ty::ConstKind::Infer(ty::InferConst::Var(vid)) => match self.infcx.probe_const_var(vid)
+ {
+ Ok(c) => return self.fold_const(c),
+ Err(universe) => CanonicalVarKind::Const(universe, c.ty()),
+ },
+ ty::ConstKind::Infer(ty::InferConst::Fresh(_)) => {
+ bug!("fresh var during canonicalization: {c:?}")
+ }
+ ty::ConstKind::Placeholder(placeholder) => match self.canonicalize_mode {
+ CanonicalizeMode::Input => CanonicalVarKind::PlaceholderConst(
+ ty::Placeholder {
+ universe: placeholder.universe,
+ name: ty::BoundVar::from(self.variables.len()),
+ },
+ c.ty(),
+ ),
+ CanonicalizeMode::Response { .. } => {
+ CanonicalVarKind::PlaceholderConst(placeholder, c.ty())
+ }
+ },
+ ty::ConstKind::Param(_) => match self.canonicalize_mode {
+ CanonicalizeMode::Input => CanonicalVarKind::PlaceholderConst(
+ ty::Placeholder {
+ universe: ty::UniverseIndex::ROOT,
+ name: ty::BoundVar::from(self.variables.len()),
+ },
+ c.ty(),
+ ),
+ CanonicalizeMode::Response { .. } => bug!("param ty in response: {c:?}"),
+ },
+ ty::ConstKind::Bound(_, _)
+ | ty::ConstKind::Unevaluated(_)
+ | ty::ConstKind::Value(_)
+ | ty::ConstKind::Error(_)
+ | ty::ConstKind::Expr(_) => return c.super_fold_with(self),
+ };
+
+ let var = ty::BoundVar::from(
+ self.variables.iter().position(|&v| v == c.into()).unwrap_or_else(|| {
+ let var = self.variables.len();
+ self.variables.push(c.into());
+ self.primitive_var_infos.push(CanonicalVarInfo { kind });
+ var
+ }),
+ );
+ self.interner().mk_const(ty::ConstKind::Bound(self.binder_index, var), c.ty())
+ }
+}
diff --git a/compiler/rustc_trait_selection/src/solve/canonical/mod.rs b/compiler/rustc_trait_selection/src/solve/canonical/mod.rs
new file mode 100644
index 000000000..8c3be8da1
--- /dev/null
+++ b/compiler/rustc_trait_selection/src/solve/canonical/mod.rs
@@ -0,0 +1,240 @@
+/// Canonicalization is used to separate some goal from its context,
+/// throwing away unnecessary information in the process.
+///
+/// This is necessary to cache goals containing inference variables
+/// and placeholders without restricting them to the current `InferCtxt`.
+///
+/// Canonicalization is fairly involved, for more details see the relevant
+/// section of the [rustc-dev-guide][c].
+///
+/// [c]: https://rustc-dev-guide.rust-lang.org/solve/canonicalization.html
+use self::canonicalize::{CanonicalizeMode, Canonicalizer};
+use super::{CanonicalGoal, Certainty, EvalCtxt, Goal};
+use super::{CanonicalResponse, ExternalConstraints, QueryResult, Response};
+use rustc_infer::infer::canonical::query_response::make_query_region_constraints;
+use rustc_infer::infer::canonical::CanonicalVarValues;
+use rustc_infer::infer::canonical::{CanonicalExt, QueryRegionConstraints};
+use rustc_infer::traits::query::NoSolution;
+use rustc_infer::traits::solve::ExternalConstraintsData;
+use rustc_infer::traits::ObligationCause;
+use rustc_middle::ty::{self, GenericArgKind};
+use rustc_span::DUMMY_SP;
+use std::iter;
+use std::ops::Deref;
+
+mod canonicalize;
+
+impl<'tcx> EvalCtxt<'_, 'tcx> {
+ /// Canonicalizes the goal remembering the original values
+ /// for each bound variable.
+ pub(super) fn canonicalize_goal(
+ &self,
+ goal: Goal<'tcx, ty::Predicate<'tcx>>,
+ ) -> (Vec<ty::GenericArg<'tcx>>, CanonicalGoal<'tcx>) {
+ let mut orig_values = Default::default();
+ let canonical_goal = Canonicalizer::canonicalize(
+ self.infcx,
+ CanonicalizeMode::Input,
+ &mut orig_values,
+ goal,
+ );
+ (orig_values, canonical_goal)
+ }
+
+ /// To return the constraints of a canonical query to the caller, we canonicalize:
+ ///
+ /// - `var_values`: a map from bound variables in the canonical goal to
+ /// the values inferred while solving the instantiated goal.
+ /// - `external_constraints`: additional constraints which aren't expressable
+ /// using simple unification of inference variables.
+ #[instrument(level = "debug", skip(self))]
+ pub(super) fn make_canonical_response(&self, certainty: Certainty) -> QueryResult<'tcx> {
+ let external_constraints = self.compute_external_query_constraints()?;
+
+ let response = Response { var_values: self.var_values, external_constraints, certainty };
+ let canonical = Canonicalizer::canonicalize(
+ self.infcx,
+ CanonicalizeMode::Response { max_input_universe: self.max_input_universe },
+ &mut Default::default(),
+ response,
+ );
+ Ok(canonical)
+ }
+
+ #[instrument(level = "debug", skip(self), ret)]
+ fn compute_external_query_constraints(&self) -> Result<ExternalConstraints<'tcx>, NoSolution> {
+ // Cannot use `take_registered_region_obligations` as we may compute the response
+ // inside of a `probe` whenever we have multiple choices inside of the solver.
+ let region_obligations = self.infcx.inner.borrow().region_obligations().to_owned();
+ let region_constraints = self.infcx.with_region_constraints(|region_constraints| {
+ make_query_region_constraints(
+ self.tcx(),
+ region_obligations
+ .iter()
+ .map(|r_o| (r_o.sup_type, r_o.sub_region, r_o.origin.to_constraint_category())),
+ region_constraints,
+ )
+ });
+ let opaque_types = self.infcx.clone_opaque_types_for_query_response();
+ Ok(self
+ .tcx()
+ .mk_external_constraints(ExternalConstraintsData { region_constraints, opaque_types }))
+ }
+
+ /// After calling a canonical query, we apply the constraints returned
+ /// by the query using this function.
+ ///
+ /// This happens in three steps:
+ /// - we instantiate the bound variables of the query response
+ /// - we unify the `var_values` of the response with the `original_values`
+ /// - we apply the `external_constraints` returned by the query
+ pub(super) fn instantiate_and_apply_query_response(
+ &mut self,
+ param_env: ty::ParamEnv<'tcx>,
+ original_values: Vec<ty::GenericArg<'tcx>>,
+ response: CanonicalResponse<'tcx>,
+ ) -> Result<Certainty, NoSolution> {
+ let substitution = self.compute_query_response_substitution(&original_values, &response);
+
+ let Response { var_values, external_constraints, certainty } =
+ response.substitute(self.tcx(), &substitution);
+
+ self.unify_query_var_values(param_env, &original_values, var_values)?;
+
+ // FIXME: implement external constraints.
+ let ExternalConstraintsData { region_constraints, opaque_types: _ } =
+ external_constraints.deref();
+ self.register_region_constraints(region_constraints);
+
+ Ok(certainty)
+ }
+
+ /// This returns the substitutions to instantiate the bound variables of
+ /// the canonical reponse. This depends on the `original_values` for the
+ /// bound variables.
+ fn compute_query_response_substitution(
+ &self,
+ original_values: &[ty::GenericArg<'tcx>],
+ response: &CanonicalResponse<'tcx>,
+ ) -> CanonicalVarValues<'tcx> {
+ // FIXME: Longterm canonical queries should deal with all placeholders
+ // created inside of the query directly instead of returning them to the
+ // caller.
+ let prev_universe = self.infcx.universe();
+ let universes_created_in_query = response.max_universe.index() + 1;
+ for _ in 0..universes_created_in_query {
+ self.infcx.create_next_universe();
+ }
+
+ let var_values = response.value.var_values;
+ assert_eq!(original_values.len(), var_values.len());
+
+ // If the query did not make progress with constraining inference variables,
+ // we would normally create a new inference variables for bound existential variables
+ // only then unify this new inference variable with the inference variable from
+ // the input.
+ //
+ // We therefore instantiate the existential variable in the canonical response with the
+ // inference variable of the input right away, which is more performant.
+ let mut opt_values = vec![None; response.variables.len()];
+ for (original_value, result_value) in iter::zip(original_values, var_values.var_values) {
+ match result_value.unpack() {
+ GenericArgKind::Type(t) => {
+ if let &ty::Bound(debruijn, b) = t.kind() {
+ assert_eq!(debruijn, ty::INNERMOST);
+ opt_values[b.var.index()] = Some(*original_value);
+ }
+ }
+ GenericArgKind::Lifetime(r) => {
+ if let ty::ReLateBound(debruijn, br) = *r {
+ assert_eq!(debruijn, ty::INNERMOST);
+ opt_values[br.var.index()] = Some(*original_value);
+ }
+ }
+ GenericArgKind::Const(c) => {
+ if let ty::ConstKind::Bound(debrujin, b) = c.kind() {
+ assert_eq!(debrujin, ty::INNERMOST);
+ opt_values[b.index()] = Some(*original_value);
+ }
+ }
+ }
+ }
+
+ let var_values = self.tcx().mk_substs_from_iter(response.variables.iter().enumerate().map(
+ |(index, info)| {
+ if info.universe() != ty::UniverseIndex::ROOT {
+ // A variable from inside a binder of the query. While ideally these shouldn't
+ // exist at all (see the FIXME at the start of this method), we have to deal with
+ // them for now.
+ self.infcx.instantiate_canonical_var(DUMMY_SP, info, |idx| {
+ ty::UniverseIndex::from(prev_universe.index() + idx.index())
+ })
+ } else if info.is_existential() {
+ // As an optimization we sometimes avoid creating a new inference variable here.
+ //
+ // All new inference variables we create start out in the current universe of the caller.
+ // This is conceptionally wrong as these inference variables would be able to name
+ // more placeholders then they should be able to. However the inference variables have
+ // to "come from somewhere", so by equating them with the original values of the caller
+ // later on, we pull them down into their correct universe again.
+ if let Some(v) = opt_values[index] {
+ v
+ } else {
+ self.infcx.instantiate_canonical_var(DUMMY_SP, info, |_| prev_universe)
+ }
+ } else {
+ // For placeholders which were already part of the input, we simply map this
+ // universal bound variable back the placeholder of the input.
+ original_values[info.expect_anon_placeholder() as usize]
+ }
+ },
+ ));
+
+ CanonicalVarValues { var_values }
+ }
+
+ #[instrument(level = "debug", skip(self, param_env), ret)]
+ fn unify_query_var_values(
+ &self,
+ param_env: ty::ParamEnv<'tcx>,
+ original_values: &[ty::GenericArg<'tcx>],
+ var_values: CanonicalVarValues<'tcx>,
+ ) -> Result<(), NoSolution> {
+ assert_eq!(original_values.len(), var_values.len());
+ for (&orig, response) in iter::zip(original_values, var_values.var_values) {
+ // This can fail due to the occurs check, see
+ // `tests/ui/typeck/lazy-norm/equating-projection-cyclically.rs` for an example
+ // where that can happen.
+ //
+ // FIXME: To deal with #105787 I also expect us to emit nested obligations here at
+ // some point. We can figure out how to deal with this once we actually have
+ // an ICE.
+ let nested_goals = self.eq(param_env, orig, response)?;
+ assert!(nested_goals.is_empty(), "{nested_goals:?}");
+ }
+
+ Ok(())
+ }
+
+ fn register_region_constraints(&mut self, region_constraints: &QueryRegionConstraints<'tcx>) {
+ for &(ty::OutlivesPredicate(lhs, rhs), _) in &region_constraints.outlives {
+ match lhs.unpack() {
+ GenericArgKind::Lifetime(lhs) => self.infcx.region_outlives_predicate(
+ &ObligationCause::dummy(),
+ ty::Binder::dummy(ty::OutlivesPredicate(lhs, rhs)),
+ ),
+ GenericArgKind::Type(lhs) => self.infcx.register_region_obligation_with_cause(
+ lhs,
+ rhs,
+ &ObligationCause::dummy(),
+ ),
+ GenericArgKind::Const(_) => bug!("const outlives: {lhs:?}: {rhs:?}"),
+ }
+ }
+
+ for member_constraint in &region_constraints.member_constraints {
+ // FIXME: Deal with member constraints :<
+ let _ = member_constraint;
+ }
+ }
+}
diff --git a/compiler/rustc_trait_selection/src/solve/eval_ctxt.rs b/compiler/rustc_trait_selection/src/solve/eval_ctxt.rs
new file mode 100644
index 000000000..95612674e
--- /dev/null
+++ b/compiler/rustc_trait_selection/src/solve/eval_ctxt.rs
@@ -0,0 +1,184 @@
+use rustc_hir::def_id::DefId;
+use rustc_infer::infer::at::ToTrace;
+use rustc_infer::infer::canonical::CanonicalVarValues;
+use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
+use rustc_infer::infer::{InferCtxt, InferOk, LateBoundRegionConversionTime};
+use rustc_infer::traits::query::NoSolution;
+use rustc_infer::traits::ObligationCause;
+use rustc_middle::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind};
+use rustc_middle::ty::{
+ self, Ty, TyCtxt, TypeFoldable, TypeSuperVisitable, TypeVisitable, TypeVisitableExt,
+ TypeVisitor,
+};
+use rustc_span::DUMMY_SP;
+use std::ops::ControlFlow;
+
+use super::search_graph::SearchGraph;
+use super::Goal;
+
+pub struct EvalCtxt<'a, 'tcx> {
+ // FIXME: should be private.
+ pub(super) infcx: &'a InferCtxt<'tcx>,
+ pub(super) var_values: CanonicalVarValues<'tcx>,
+ /// The highest universe index nameable by the caller.
+ ///
+ /// When we enter a new binder inside of the query we create new universes
+ /// which the caller cannot name. We have to be careful with variables from
+ /// these new universes when creating the query response.
+ ///
+ /// Both because these new universes can prevent us from reaching a fixpoint
+ /// if we have a coinductive cycle and because that's the only way we can return
+ /// new placeholders to the caller.
+ pub(super) max_input_universe: ty::UniverseIndex,
+
+ pub(super) search_graph: &'a mut SearchGraph<'tcx>,
+
+ /// This field is used by a debug assertion in [`EvalCtxt::evaluate_goal`],
+ /// see the comment in that method for more details.
+ pub in_projection_eq_hack: bool,
+}
+
+impl<'tcx> EvalCtxt<'_, 'tcx> {
+ pub(super) fn probe<T>(&mut self, f: impl FnOnce(&mut EvalCtxt<'_, 'tcx>) -> T) -> T {
+ self.infcx.probe(|_| f(self))
+ }
+
+ pub(super) fn tcx(&self) -> TyCtxt<'tcx> {
+ self.infcx.tcx
+ }
+
+ pub(super) fn next_ty_infer(&self) -> Ty<'tcx> {
+ self.infcx.next_ty_var(TypeVariableOrigin {
+ kind: TypeVariableOriginKind::MiscVariable,
+ span: DUMMY_SP,
+ })
+ }
+
+ pub(super) fn next_const_infer(&self, ty: Ty<'tcx>) -> ty::Const<'tcx> {
+ self.infcx.next_const_var(
+ ty,
+ ConstVariableOrigin { kind: ConstVariableOriginKind::MiscVariable, span: DUMMY_SP },
+ )
+ }
+
+ /// Is the projection predicate is of the form `exists<T> <Ty as Trait>::Assoc = T`.
+ ///
+ /// This is the case if the `term` is an inference variable in the innermost universe
+ /// and does not occur in any other part of the predicate.
+ pub(super) fn term_is_fully_unconstrained(
+ &self,
+ goal: Goal<'tcx, ty::ProjectionPredicate<'tcx>>,
+ ) -> bool {
+ let term_is_infer = match goal.predicate.term.unpack() {
+ ty::TermKind::Ty(ty) => {
+ if let &ty::Infer(ty::TyVar(vid)) = ty.kind() {
+ match self.infcx.probe_ty_var(vid) {
+ Ok(value) => bug!("resolved var in query: {goal:?} {value:?}"),
+ Err(universe) => universe == self.universe(),
+ }
+ } else {
+ false
+ }
+ }
+ ty::TermKind::Const(ct) => {
+ if let ty::ConstKind::Infer(ty::InferConst::Var(vid)) = ct.kind() {
+ match self.infcx.probe_const_var(vid) {
+ Ok(value) => bug!("resolved var in query: {goal:?} {value:?}"),
+ Err(universe) => universe == self.universe(),
+ }
+ } else {
+ false
+ }
+ }
+ };
+
+ // Guard against `<T as Trait<?0>>::Assoc = ?0>`.
+ struct ContainsTerm<'tcx> {
+ term: ty::Term<'tcx>,
+ }
+ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for ContainsTerm<'tcx> {
+ type BreakTy = ();
+ fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
+ if t.needs_infer() {
+ if ty::Term::from(t) == self.term {
+ ControlFlow::Break(())
+ } else {
+ t.super_visit_with(self)
+ }
+ } else {
+ ControlFlow::Continue(())
+ }
+ }
+
+ fn visit_const(&mut self, c: ty::Const<'tcx>) -> ControlFlow<Self::BreakTy> {
+ if c.needs_infer() {
+ if ty::Term::from(c) == self.term {
+ ControlFlow::Break(())
+ } else {
+ c.super_visit_with(self)
+ }
+ } else {
+ ControlFlow::Continue(())
+ }
+ }
+ }
+
+ let mut visitor = ContainsTerm { term: goal.predicate.term };
+
+ term_is_infer
+ && goal.predicate.projection_ty.visit_with(&mut visitor).is_continue()
+ && goal.param_env.visit_with(&mut visitor).is_continue()
+ }
+
+ #[instrument(level = "debug", skip(self, param_env), ret)]
+ pub(super) fn eq<T: ToTrace<'tcx>>(
+ &self,
+ param_env: ty::ParamEnv<'tcx>,
+ lhs: T,
+ rhs: T,
+ ) -> Result<Vec<Goal<'tcx, ty::Predicate<'tcx>>>, NoSolution> {
+ self.infcx
+ .at(&ObligationCause::dummy(), param_env)
+ .eq(lhs, rhs)
+ .map(|InferOk { value: (), obligations }| {
+ obligations.into_iter().map(|o| o.into()).collect()
+ })
+ .map_err(|e| {
+ debug!(?e, "failed to equate");
+ NoSolution
+ })
+ }
+
+ pub(super) fn instantiate_binder_with_infer<T: TypeFoldable<TyCtxt<'tcx>> + Copy>(
+ &self,
+ value: ty::Binder<'tcx, T>,
+ ) -> T {
+ self.infcx.instantiate_binder_with_fresh_vars(
+ DUMMY_SP,
+ LateBoundRegionConversionTime::HigherRankedType,
+ value,
+ )
+ }
+
+ pub(super) fn instantiate_binder_with_placeholders<T: TypeFoldable<TyCtxt<'tcx>> + Copy>(
+ &self,
+ value: ty::Binder<'tcx, T>,
+ ) -> T {
+ self.infcx.instantiate_binder_with_placeholders(value)
+ }
+
+ pub(super) fn resolve_vars_if_possible<T>(&self, value: T) -> T
+ where
+ T: TypeFoldable<TyCtxt<'tcx>>,
+ {
+ self.infcx.resolve_vars_if_possible(value)
+ }
+
+ pub(super) fn fresh_substs_for_item(&self, def_id: DefId) -> ty::SubstsRef<'tcx> {
+ self.infcx.fresh_substs_for_item(DUMMY_SP, def_id)
+ }
+
+ pub(super) fn universe(&self) -> ty::UniverseIndex {
+ self.infcx.universe()
+ }
+}
diff --git a/compiler/rustc_trait_selection/src/solve/fulfill.rs b/compiler/rustc_trait_selection/src/solve/fulfill.rs
index a6240666e..a55b984fd 100644
--- a/compiler/rustc_trait_selection/src/solve/fulfill.rs
+++ b/compiler/rustc_trait_selection/src/solve/fulfill.rs
@@ -1,16 +1,14 @@
use std::mem;
-use rustc_data_structures::fx::FxHashMap;
-use rustc_infer::{
- infer::InferCtxt,
- traits::{
- query::NoSolution, FulfillmentError, FulfillmentErrorCode, PredicateObligation,
- SelectionError, TraitEngine,
- },
+use rustc_infer::infer::InferCtxt;
+use rustc_infer::traits::{
+ query::NoSolution, FulfillmentError, FulfillmentErrorCode, MismatchedProjectionTypes,
+ PredicateObligation, SelectionError, TraitEngine,
};
use rustc_middle::ty;
+use rustc_middle::ty::error::{ExpectedFound, TypeError};
-use super::{search_graph, Certainty, EvalCtxt};
+use super::{Certainty, InferCtxtEvalExt};
/// A trait engine using the new trait solver.
///
@@ -42,12 +40,7 @@ impl<'tcx> TraitEngine<'tcx> for FulfillmentCtxt<'tcx> {
self.obligations.push(obligation);
}
- fn select_all_or_error(&mut self, infcx: &InferCtxt<'tcx>) -> Vec<FulfillmentError<'tcx>> {
- let errors = self.select_where_possible(infcx);
- if !errors.is_empty() {
- return errors;
- }
-
+ fn collect_remaining_errors(&mut self) -> Vec<FulfillmentError<'tcx>> {
self.obligations
.drain(..)
.map(|obligation| FulfillmentError {
@@ -68,16 +61,65 @@ impl<'tcx> TraitEngine<'tcx> for FulfillmentCtxt<'tcx> {
let mut has_changed = false;
for obligation in mem::take(&mut self.obligations) {
let goal = obligation.clone().into();
- let search_graph = &mut search_graph::SearchGraph::new(infcx.tcx);
- let mut ecx = EvalCtxt::new_outside_solver(infcx, search_graph);
- let (changed, certainty) = match ecx.evaluate_goal(goal) {
+ let (changed, certainty) = match infcx.evaluate_root_goal(goal) {
Ok(result) => result,
Err(NoSolution) => {
errors.push(FulfillmentError {
obligation: obligation.clone(),
- code: FulfillmentErrorCode::CodeSelectionError(
- SelectionError::Unimplemented,
- ),
+ code: match goal.predicate.kind().skip_binder() {
+ ty::PredicateKind::Clause(ty::Clause::Projection(_)) => {
+ FulfillmentErrorCode::CodeProjectionError(
+ // FIXME: This could be a `Sorts` if the term is a type
+ MismatchedProjectionTypes { err: TypeError::Mismatch },
+ )
+ }
+ ty::PredicateKind::AliasEq(_, _) => {
+ FulfillmentErrorCode::CodeProjectionError(
+ MismatchedProjectionTypes { err: TypeError::Mismatch },
+ )
+ }
+ ty::PredicateKind::Subtype(pred) => {
+ let (a, b) = infcx.instantiate_binder_with_placeholders(
+ goal.predicate.kind().rebind((pred.a, pred.b)),
+ );
+ let expected_found = ExpectedFound::new(true, a, b);
+ FulfillmentErrorCode::CodeSubtypeError(
+ expected_found,
+ TypeError::Sorts(expected_found),
+ )
+ }
+ ty::PredicateKind::Coerce(pred) => {
+ let (a, b) = infcx.instantiate_binder_with_placeholders(
+ goal.predicate.kind().rebind((pred.a, pred.b)),
+ );
+ let expected_found = ExpectedFound::new(false, a, b);
+ FulfillmentErrorCode::CodeSubtypeError(
+ expected_found,
+ TypeError::Sorts(expected_found),
+ )
+ }
+ ty::PredicateKind::ConstEquate(a, b) => {
+ let (a, b) = infcx.instantiate_binder_with_placeholders(
+ goal.predicate.kind().rebind((a, b)),
+ );
+ let expected_found = ExpectedFound::new(true, a, b);
+ FulfillmentErrorCode::CodeConstEquateError(
+ expected_found,
+ TypeError::ConstMismatch(expected_found),
+ )
+ }
+ ty::PredicateKind::Clause(_)
+ | ty::PredicateKind::WellFormed(_)
+ | ty::PredicateKind::ObjectSafe(_)
+ | ty::PredicateKind::ClosureKind(_, _, _)
+ | ty::PredicateKind::ConstEvaluatable(_)
+ | ty::PredicateKind::TypeWellFormedFromEnv(_)
+ | ty::PredicateKind::Ambiguous => {
+ FulfillmentErrorCode::CodeSelectionError(
+ SelectionError::Unimplemented,
+ )
+ }
+ },
root_obligation: obligation,
});
continue;
@@ -103,7 +145,10 @@ impl<'tcx> TraitEngine<'tcx> for FulfillmentCtxt<'tcx> {
self.obligations.clone()
}
- fn relationships(&mut self) -> &mut FxHashMap<ty::TyVid, ty::FoundRelationships> {
- unimplemented!("Should be moved out of `TraitEngine`")
+ fn drain_unstalled_obligations(
+ &mut self,
+ _: &InferCtxt<'tcx>,
+ ) -> Vec<PredicateObligation<'tcx>> {
+ unimplemented!()
}
}
diff --git a/compiler/rustc_trait_selection/src/solve/infcx_ext.rs b/compiler/rustc_trait_selection/src/solve/infcx_ext.rs
deleted file mode 100644
index 42f597c78..000000000
--- a/compiler/rustc_trait_selection/src/solve/infcx_ext.rs
+++ /dev/null
@@ -1,78 +0,0 @@
-use rustc_infer::infer::at::ToTrace;
-use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
-use rustc_infer::infer::{InferCtxt, InferOk, LateBoundRegionConversionTime};
-use rustc_infer::traits::query::NoSolution;
-use rustc_infer::traits::ObligationCause;
-use rustc_middle::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind};
-use rustc_middle::ty::{self, Ty, TypeFoldable};
-use rustc_span::DUMMY_SP;
-
-use super::Goal;
-
-/// Methods used inside of the canonical queries of the solver.
-///
-/// Most notably these do not care about diagnostics information.
-/// If you find this while looking for methods to use outside of the
-/// solver, you may look at the implementation of these method for
-/// help.
-pub(super) trait InferCtxtExt<'tcx> {
- fn next_ty_infer(&self) -> Ty<'tcx>;
- fn next_const_infer(&self, ty: Ty<'tcx>) -> ty::Const<'tcx>;
-
- fn eq<T: ToTrace<'tcx>>(
- &self,
- param_env: ty::ParamEnv<'tcx>,
- lhs: T,
- rhs: T,
- ) -> Result<Vec<Goal<'tcx, ty::Predicate<'tcx>>>, NoSolution>;
-
- fn instantiate_bound_vars_with_infer<T: TypeFoldable<'tcx> + Copy>(
- &self,
- value: ty::Binder<'tcx, T>,
- ) -> T;
-}
-
-impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> {
- fn next_ty_infer(&self) -> Ty<'tcx> {
- self.next_ty_var(TypeVariableOrigin {
- kind: TypeVariableOriginKind::MiscVariable,
- span: DUMMY_SP,
- })
- }
- fn next_const_infer(&self, ty: Ty<'tcx>) -> ty::Const<'tcx> {
- self.next_const_var(
- ty,
- ConstVariableOrigin { kind: ConstVariableOriginKind::MiscVariable, span: DUMMY_SP },
- )
- }
-
- #[instrument(level = "debug", skip(self, param_env), ret)]
- fn eq<T: ToTrace<'tcx>>(
- &self,
- param_env: ty::ParamEnv<'tcx>,
- lhs: T,
- rhs: T,
- ) -> Result<Vec<Goal<'tcx, ty::Predicate<'tcx>>>, NoSolution> {
- self.at(&ObligationCause::dummy(), param_env)
- .define_opaque_types(false)
- .eq(lhs, rhs)
- .map(|InferOk { value: (), obligations }| {
- obligations.into_iter().map(|o| o.into()).collect()
- })
- .map_err(|e| {
- debug!(?e, "failed to equate");
- NoSolution
- })
- }
-
- fn instantiate_bound_vars_with_infer<T: TypeFoldable<'tcx> + Copy>(
- &self,
- value: ty::Binder<'tcx, T>,
- ) -> T {
- self.replace_bound_vars_with_fresh_vars(
- DUMMY_SP,
- LateBoundRegionConversionTime::HigherRankedType,
- value,
- )
- }
-}
diff --git a/compiler/rustc_trait_selection/src/solve/mod.rs b/compiler/rustc_trait_selection/src/solve/mod.rs
index 32eb84635..57b6a4527 100644
--- a/compiler/rustc_trait_selection/src/solve/mod.rs
+++ b/compiler/rustc_trait_selection/src/solve/mod.rs
@@ -13,31 +13,34 @@
// preserves universes and creates a unique var (in the highest universe) for each
// appearance of a region.
-// FIXME: `CanonicalVarValues` should be interned and `Copy`.
-
// FIXME: uses of `infcx.at` need to enable deferred projection equality once that's implemented.
use std::mem;
-use rustc_infer::infer::canonical::{Canonical, CanonicalVarKind, CanonicalVarValues};
-use rustc_infer::infer::canonical::{OriginalQueryValues, QueryRegionConstraints, QueryResponse};
+use rustc_hir::def_id::DefId;
+use rustc_infer::infer::canonical::{Canonical, CanonicalVarValues};
use rustc_infer::infer::{InferCtxt, InferOk, TyCtxtInferExt};
use rustc_infer::traits::query::NoSolution;
use rustc_infer::traits::Obligation;
-use rustc_middle::infer::canonical::Certainty as OldCertainty;
+use rustc_middle::traits::solve::{ExternalConstraints, ExternalConstraintsData};
use rustc_middle::ty::{self, Ty, TyCtxt};
-use rustc_middle::ty::{RegionOutlivesPredicate, ToPredicate, TypeOutlivesPredicate};
+use rustc_middle::ty::{
+ CoercePredicate, RegionOutlivesPredicate, SubtypePredicate, ToPredicate, TypeOutlivesPredicate,
+};
use rustc_span::DUMMY_SP;
+use crate::solve::search_graph::OverflowHandler;
use crate::traits::ObligationCause;
mod assembly;
+mod canonical;
+mod eval_ctxt;
mod fulfill;
-mod infcx_ext;
mod project_goals;
mod search_graph;
mod trait_goals;
+pub use eval_ctxt::EvalCtxt;
pub use fulfill::FulfillmentCtxt;
/// A goal is a statement, i.e. `predicate`, we want to prove
@@ -71,8 +74,7 @@ impl<'tcx, P> From<Obligation<'tcx, P>> for Goal<'tcx, P> {
Goal { param_env: obligation.param_env, predicate: obligation.predicate }
}
}
-
-#[derive(Debug, PartialEq, Eq, Clone, Hash, TypeFoldable, TypeVisitable)]
+#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash, TypeFoldable, TypeVisitable)]
pub struct Response<'tcx> {
pub var_values: CanonicalVarValues<'tcx>,
/// Additional constraints returned by this query.
@@ -80,6 +82,18 @@ pub struct Response<'tcx> {
pub certainty: Certainty,
}
+trait CanonicalResponseExt {
+ fn has_no_inference_or_external_constraints(&self) -> bool;
+}
+
+impl<'tcx> CanonicalResponseExt for Canonical<'tcx, Response<'tcx>> {
+ fn has_no_inference_or_external_constraints(&self) -> bool {
+ self.value.external_constraints.region_constraints.is_empty()
+ && self.value.var_values.is_identity()
+ && self.value.external_constraints.opaque_types.is_empty()
+ }
+}
+
#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash, TypeFoldable, TypeVisitable)]
pub enum Certainty {
Yes,
@@ -87,6 +101,8 @@ pub enum Certainty {
}
impl Certainty {
+ pub const AMBIGUOUS: Certainty = Certainty::Maybe(MaybeCause::Ambiguity);
+
/// When proving multiple goals using **AND**, e.g. nested obligations for an impl,
/// use this function to unify the certainty of these goals
pub fn unify_and(self, other: Certainty) -> Certainty {
@@ -118,14 +134,6 @@ pub enum MaybeCause {
Overflow,
}
-/// Additional constraints returned on success.
-#[derive(Debug, PartialEq, Eq, Clone, Hash, TypeFoldable, TypeVisitable, Default)]
-pub struct ExternalConstraints<'tcx> {
- // FIXME: implement this.
- regions: (),
- opaque_types: Vec<(Ty<'tcx>, Ty<'tcx>)>,
-}
-
type CanonicalGoal<'tcx, T = ty::Predicate<'tcx>> = Canonical<'tcx, Goal<'tcx, T>>;
type CanonicalResponse<'tcx> = Canonical<'tcx, Response<'tcx>>;
/// The result of evaluating a canonical query.
@@ -136,78 +144,70 @@ type CanonicalResponse<'tcx> = Canonical<'tcx, Response<'tcx>>;
/// solver, merge the two responses again.
pub type QueryResult<'tcx> = Result<CanonicalResponse<'tcx>, NoSolution>;
-pub trait TyCtxtExt<'tcx> {
- fn evaluate_goal(self, goal: CanonicalGoal<'tcx>) -> QueryResult<'tcx>;
-}
-
-impl<'tcx> TyCtxtExt<'tcx> for TyCtxt<'tcx> {
- fn evaluate_goal(self, goal: CanonicalGoal<'tcx>) -> QueryResult<'tcx> {
- let mut search_graph = search_graph::SearchGraph::new(self);
- EvalCtxt::evaluate_canonical_goal(self, &mut search_graph, goal)
- }
+pub trait InferCtxtEvalExt<'tcx> {
+ /// Evaluates a goal from **outside** of the trait solver.
+ ///
+ /// Using this while inside of the solver is wrong as it uses a new
+ /// search graph which would break cycle detection.
+ fn evaluate_root_goal(
+ &self,
+ goal: Goal<'tcx, ty::Predicate<'tcx>>,
+ ) -> Result<(bool, Certainty), NoSolution>;
}
-struct EvalCtxt<'a, 'tcx> {
- infcx: &'a InferCtxt<'tcx>,
- var_values: CanonicalVarValues<'tcx>,
+impl<'tcx> InferCtxtEvalExt<'tcx> for InferCtxt<'tcx> {
+ fn evaluate_root_goal(
+ &self,
+ goal: Goal<'tcx, ty::Predicate<'tcx>>,
+ ) -> Result<(bool, Certainty), NoSolution> {
+ let mut search_graph = search_graph::SearchGraph::new(self.tcx);
+
+ let result = EvalCtxt {
+ search_graph: &mut search_graph,
+ infcx: self,
+ // Only relevant when canonicalizing the response.
+ max_input_universe: ty::UniverseIndex::ROOT,
+ var_values: CanonicalVarValues::dummy(),
+ in_projection_eq_hack: false,
+ }
+ .evaluate_goal(goal);
- search_graph: &'a mut search_graph::SearchGraph<'tcx>,
+ assert!(search_graph.is_empty());
+ result
+ }
}
impl<'a, 'tcx> EvalCtxt<'a, 'tcx> {
- fn tcx(&self) -> TyCtxt<'tcx> {
- self.infcx.tcx
- }
-
- /// Creates a new evaluation context outside of the trait solver.
+ /// The entry point of the solver.
///
- /// With this solver making a canonical response doesn't make much sense.
- /// The `search_graph` for this solver has to be completely empty.
- fn new_outside_solver(
- infcx: &'a InferCtxt<'tcx>,
- search_graph: &'a mut search_graph::SearchGraph<'tcx>,
- ) -> EvalCtxt<'a, 'tcx> {
- assert!(search_graph.is_empty());
- EvalCtxt { infcx, var_values: CanonicalVarValues::dummy(), search_graph }
- }
-
+ /// This function deals with (coinductive) cycles, overflow, and caching
+ /// and then calls [`EvalCtxt::compute_goal`] which contains the actual
+ /// logic of the solver.
+ ///
+ /// Instead of calling this function directly, use either [EvalCtxt::evaluate_goal]
+ /// if you're inside of the solver or [InferCtxtEvalExt::evaluate_root_goal] if you're
+ /// outside of it.
#[instrument(level = "debug", skip(tcx, search_graph), ret)]
fn evaluate_canonical_goal(
tcx: TyCtxt<'tcx>,
search_graph: &'a mut search_graph::SearchGraph<'tcx>,
canonical_goal: CanonicalGoal<'tcx>,
) -> QueryResult<'tcx> {
- match search_graph.try_push_stack(tcx, canonical_goal) {
- Ok(()) => {}
- // Our goal is already on the stack, eager return.
- Err(response) => return response,
- }
-
- // We may have to repeatedly recompute the goal in case of coinductive cycles,
- // check out the `cache` module for more information.
+ // Deal with overflow, caching, and coinduction.
//
- // FIXME: Similar to `evaluate_all`, this has to check for overflow.
- loop {
+ // The actual solver logic happens in `ecx.compute_goal`.
+ search_graph.with_new_goal(tcx, canonical_goal, |search_graph| {
let (ref infcx, goal, var_values) =
tcx.infer_ctxt().build_with_canonical(DUMMY_SP, &canonical_goal);
- let mut ecx = EvalCtxt { infcx, var_values, search_graph };
- let result = ecx.compute_goal(goal);
-
- // FIXME: `Response` should be `Copy`
- if search_graph.try_finalize_goal(tcx, canonical_goal, result.clone()) {
- return result;
- }
- }
- }
-
- fn make_canonical_response(&self, certainty: Certainty) -> QueryResult<'tcx> {
- let external_constraints = take_external_constraints(self.infcx)?;
-
- Ok(self.infcx.canonicalize_response(Response {
- var_values: self.var_values.clone(),
- external_constraints,
- certainty,
- }))
+ let mut ecx = EvalCtxt {
+ infcx,
+ var_values,
+ max_input_universe: canonical_goal.max_universe,
+ search_graph,
+ in_projection_eq_hack: false,
+ };
+ ecx.compute_goal(goal)
+ })
}
/// Recursively evaluates `goal`, returning whether any inference vars have
@@ -216,14 +216,39 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> {
&mut self,
goal: Goal<'tcx, ty::Predicate<'tcx>>,
) -> Result<(bool, Certainty), NoSolution> {
- let mut orig_values = OriginalQueryValues::default();
- let canonical_goal = self.infcx.canonicalize_query(goal, &mut orig_values);
+ let (orig_values, canonical_goal) = self.canonicalize_goal(goal);
let canonical_response =
EvalCtxt::evaluate_canonical_goal(self.tcx(), self.search_graph, canonical_goal)?;
- Ok((
- !canonical_response.value.var_values.is_identity(),
- instantiate_canonical_query_response(self.infcx, &orig_values, canonical_response),
- ))
+
+ let has_changed = !canonical_response.value.var_values.is_identity();
+ let certainty = self.instantiate_and_apply_query_response(
+ goal.param_env,
+ orig_values,
+ canonical_response,
+ )?;
+
+ // Check that rerunning this query with its inference constraints applied
+ // doesn't result in new inference constraints and has the same result.
+ //
+ // If we have projection goals like `<T as Trait>::Assoc == u32` we recursively
+ // call `exists<U> <T as Trait>::Assoc == U` to enable better caching. This goal
+ // could constrain `U` to `u32` which would cause this check to result in a
+ // solver cycle.
+ if cfg!(debug_assertions)
+ && has_changed
+ && !self.in_projection_eq_hack
+ && !self.search_graph.in_cycle()
+ {
+ let (_orig_values, canonical_goal) = self.canonicalize_goal(goal);
+ let canonical_response =
+ EvalCtxt::evaluate_canonical_goal(self.tcx(), self.search_graph, canonical_goal)?;
+ if !canonical_response.value.var_values.is_identity() {
+ bug!("unstable result: {goal:?} {canonical_goal:?} {canonical_response:?}");
+ }
+ assert_eq!(certainty, canonical_response.value.certainty);
+ }
+
+ Ok((has_changed, certainty))
}
fn compute_goal(&mut self, goal: Goal<'tcx, ty::Predicate<'tcx>>) -> QueryResult<'tcx> {
@@ -243,19 +268,40 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> {
ty::PredicateKind::Clause(ty::Clause::RegionOutlives(predicate)) => {
self.compute_region_outlives_goal(Goal { param_env, predicate })
}
+ ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(ct, ty)) => {
+ self.compute_const_arg_has_type_goal(Goal { param_env, predicate: (ct, ty) })
+ }
+ ty::PredicateKind::Subtype(predicate) => {
+ self.compute_subtype_goal(Goal { param_env, predicate })
+ }
+ ty::PredicateKind::Coerce(predicate) => {
+ self.compute_coerce_goal(Goal { param_env, predicate })
+ }
+ ty::PredicateKind::ClosureKind(def_id, substs, kind) => self
+ .compute_closure_kind_goal(Goal {
+ param_env,
+ predicate: (def_id, substs, kind),
+ }),
+ ty::PredicateKind::ObjectSafe(trait_def_id) => {
+ self.compute_object_safe_goal(trait_def_id)
+ }
+ ty::PredicateKind::WellFormed(arg) => {
+ self.compute_well_formed_goal(Goal { param_env, predicate: arg })
+ }
+ ty::PredicateKind::Ambiguous => self.make_canonical_response(Certainty::AMBIGUOUS),
// FIXME: implement these predicates :)
- ty::PredicateKind::WellFormed(_)
- | ty::PredicateKind::ObjectSafe(_)
- | ty::PredicateKind::ClosureKind(_, _, _)
- | ty::PredicateKind::Subtype(_)
- | ty::PredicateKind::Coerce(_)
- | ty::PredicateKind::ConstEvaluatable(_)
- | ty::PredicateKind::ConstEquate(_, _)
- | ty::PredicateKind::TypeWellFormedFromEnv(_)
- | ty::PredicateKind::Ambiguous => self.make_canonical_response(Certainty::Yes),
+ ty::PredicateKind::ConstEvaluatable(_) | ty::PredicateKind::ConstEquate(_, _) => {
+ self.make_canonical_response(Certainty::Yes)
+ }
+ ty::PredicateKind::TypeWellFormedFromEnv(..) => {
+ bug!("TypeWellFormedFromEnv is only used for Chalk")
+ }
+ ty::PredicateKind::AliasEq(lhs, rhs) => {
+ self.compute_alias_eq_goal(Goal { param_env, predicate: (lhs, rhs) })
+ }
}
} else {
- let kind = self.infcx.replace_bound_vars_with_placeholders(kind);
+ let kind = self.infcx.instantiate_binder_with_placeholders(kind);
let goal = goal.with(self.tcx(), ty::Binder::dummy(kind));
let (_, certainty) = self.evaluate_goal(goal)?;
self.make_canonical_response(certainty)
@@ -264,102 +310,255 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> {
fn compute_type_outlives_goal(
&mut self,
- _goal: Goal<'tcx, TypeOutlivesPredicate<'tcx>>,
+ goal: Goal<'tcx, TypeOutlivesPredicate<'tcx>>,
) -> QueryResult<'tcx> {
+ let ty::OutlivesPredicate(ty, lt) = goal.predicate;
+ self.infcx.register_region_obligation_with_cause(ty, lt, &ObligationCause::dummy());
self.make_canonical_response(Certainty::Yes)
}
fn compute_region_outlives_goal(
&mut self,
- _goal: Goal<'tcx, RegionOutlivesPredicate<'tcx>>,
+ goal: Goal<'tcx, RegionOutlivesPredicate<'tcx>>,
) -> QueryResult<'tcx> {
+ self.infcx.region_outlives_predicate(
+ &ObligationCause::dummy(),
+ ty::Binder::dummy(goal.predicate),
+ );
self.make_canonical_response(Certainty::Yes)
}
+
+ fn compute_coerce_goal(
+ &mut self,
+ goal: Goal<'tcx, CoercePredicate<'tcx>>,
+ ) -> QueryResult<'tcx> {
+ self.compute_subtype_goal(Goal {
+ param_env: goal.param_env,
+ predicate: SubtypePredicate {
+ a_is_expected: false,
+ a: goal.predicate.a,
+ b: goal.predicate.b,
+ },
+ })
+ }
+
+ fn compute_subtype_goal(
+ &mut self,
+ goal: Goal<'tcx, SubtypePredicate<'tcx>>,
+ ) -> QueryResult<'tcx> {
+ if goal.predicate.a.is_ty_var() && goal.predicate.b.is_ty_var() {
+ // FIXME: Do we want to register a subtype relation between these vars?
+ // That won't actually reflect in the query response, so it seems moot.
+ self.make_canonical_response(Certainty::AMBIGUOUS)
+ } else {
+ let InferOk { value: (), obligations } = self
+ .infcx
+ .at(&ObligationCause::dummy(), goal.param_env)
+ .sub(goal.predicate.a, goal.predicate.b)?;
+ self.evaluate_all_and_make_canonical_response(
+ obligations.into_iter().map(|pred| pred.into()).collect(),
+ )
+ }
+ }
+
+ fn compute_closure_kind_goal(
+ &mut self,
+ goal: Goal<'tcx, (DefId, ty::SubstsRef<'tcx>, ty::ClosureKind)>,
+ ) -> QueryResult<'tcx> {
+ let (_, substs, expected_kind) = goal.predicate;
+ let found_kind = substs.as_closure().kind_ty().to_opt_closure_kind();
+
+ let Some(found_kind) = found_kind else {
+ return self.make_canonical_response(Certainty::AMBIGUOUS);
+ };
+ if found_kind.extends(expected_kind) {
+ self.make_canonical_response(Certainty::Yes)
+ } else {
+ Err(NoSolution)
+ }
+ }
+
+ fn compute_object_safe_goal(&mut self, trait_def_id: DefId) -> QueryResult<'tcx> {
+ if self.tcx().check_is_object_safe(trait_def_id) {
+ self.make_canonical_response(Certainty::Yes)
+ } else {
+ Err(NoSolution)
+ }
+ }
+
+ fn compute_well_formed_goal(
+ &mut self,
+ goal: Goal<'tcx, ty::GenericArg<'tcx>>,
+ ) -> QueryResult<'tcx> {
+ match crate::traits::wf::unnormalized_obligations(
+ self.infcx,
+ goal.param_env,
+ goal.predicate,
+ ) {
+ Some(obligations) => self.evaluate_all_and_make_canonical_response(
+ obligations.into_iter().map(|o| o.into()).collect(),
+ ),
+ None => self.make_canonical_response(Certainty::AMBIGUOUS),
+ }
+ }
+
+ #[instrument(level = "debug", skip(self), ret)]
+ fn compute_alias_eq_goal(
+ &mut self,
+ goal: Goal<'tcx, (ty::Term<'tcx>, ty::Term<'tcx>)>,
+ ) -> QueryResult<'tcx> {
+ let tcx = self.tcx();
+
+ let evaluate_normalizes_to = |ecx: &mut EvalCtxt<'_, 'tcx>, alias, other| {
+ debug!("evaluate_normalizes_to(alias={:?}, other={:?})", alias, other);
+ let r = ecx.probe(|ecx| {
+ let (_, certainty) = ecx.evaluate_goal(goal.with(
+ tcx,
+ ty::Binder::dummy(ty::ProjectionPredicate {
+ projection_ty: alias,
+ term: other,
+ }),
+ ))?;
+ ecx.make_canonical_response(certainty)
+ });
+ debug!("evaluate_normalizes_to(..) -> {:?}", r);
+ r
+ };
+
+ if goal.predicate.0.is_infer() || goal.predicate.1.is_infer() {
+ bug!(
+ "`AliasEq` goal with an infer var on lhs or rhs which should have been instantiated"
+ );
+ }
+
+ match (
+ goal.predicate.0.to_alias_term_no_opaque(tcx),
+ goal.predicate.1.to_alias_term_no_opaque(tcx),
+ ) {
+ (None, None) => bug!("`AliasEq` goal without an alias on either lhs or rhs"),
+ (Some(alias), None) => evaluate_normalizes_to(self, alias, goal.predicate.1),
+ (None, Some(alias)) => evaluate_normalizes_to(self, alias, goal.predicate.0),
+ (Some(alias_lhs), Some(alias_rhs)) => {
+ debug!("compute_alias_eq_goal: both sides are aliases");
+
+ let mut candidates = Vec::with_capacity(3);
+
+ // Evaluate all 3 potential candidates for the alias' being equal
+ candidates.push(evaluate_normalizes_to(self, alias_lhs, goal.predicate.1));
+ candidates.push(evaluate_normalizes_to(self, alias_rhs, goal.predicate.0));
+ candidates.push(self.probe(|this| {
+ debug!("compute_alias_eq_goal: alias defids are equal, equating substs");
+ let nested_goals = this.eq(goal.param_env, alias_lhs, alias_rhs)?;
+ this.evaluate_all_and_make_canonical_response(nested_goals)
+ }));
+
+ debug!(?candidates);
+
+ self.try_merge_responses(candidates.into_iter())
+ }
+ }
+ }
+
+ #[instrument(level = "debug", skip(self), ret)]
+ fn compute_const_arg_has_type_goal(
+ &mut self,
+ goal: Goal<'tcx, (ty::Const<'tcx>, Ty<'tcx>)>,
+ ) -> QueryResult<'tcx> {
+ let (ct, ty) = goal.predicate;
+ let nested_goals = self.eq(goal.param_env, ct.ty(), ty)?;
+ self.evaluate_all_and_make_canonical_response(nested_goals)
+ }
}
impl<'tcx> EvalCtxt<'_, 'tcx> {
+ // Recursively evaluates a list of goals to completion, returning the certainty
+ // of all of the goals.
fn evaluate_all(
&mut self,
mut goals: Vec<Goal<'tcx, ty::Predicate<'tcx>>>,
) -> Result<Certainty, NoSolution> {
let mut new_goals = Vec::new();
- self.repeat_while_none(|this| {
- let mut has_changed = Err(Certainty::Yes);
- for goal in goals.drain(..) {
- let (changed, certainty) = match this.evaluate_goal(goal) {
- Ok(result) => result,
- Err(NoSolution) => return Some(Err(NoSolution)),
- };
-
- if changed {
- has_changed = Ok(());
- }
+ self.repeat_while_none(
+ |_| Ok(Certainty::Maybe(MaybeCause::Overflow)),
+ |this| {
+ let mut has_changed = Err(Certainty::Yes);
+ for goal in goals.drain(..) {
+ let (changed, certainty) = match this.evaluate_goal(goal) {
+ Ok(result) => result,
+ Err(NoSolution) => return Some(Err(NoSolution)),
+ };
+
+ if changed {
+ has_changed = Ok(());
+ }
- match certainty {
- Certainty::Yes => {}
- Certainty::Maybe(_) => {
- new_goals.push(goal);
- has_changed = has_changed.map_err(|c| c.unify_and(certainty));
+ match certainty {
+ Certainty::Yes => {}
+ Certainty::Maybe(_) => {
+ new_goals.push(goal);
+ has_changed = has_changed.map_err(|c| c.unify_and(certainty));
+ }
}
}
- }
- match has_changed {
- Ok(()) => {
- mem::swap(&mut new_goals, &mut goals);
- None
+ match has_changed {
+ Ok(()) => {
+ mem::swap(&mut new_goals, &mut goals);
+ None
+ }
+ Err(certainty) => Some(Ok(certainty)),
}
- Err(certainty) => Some(Ok(certainty)),
- }
- })
+ },
+ )
}
+ // Recursively evaluates a list of goals to completion, making a query response.
+ //
+ // This is just a convenient way of calling [`EvalCtxt::evaluate_all`],
+ // then [`EvalCtxt::make_canonical_response`].
fn evaluate_all_and_make_canonical_response(
&mut self,
goals: Vec<Goal<'tcx, ty::Predicate<'tcx>>>,
) -> QueryResult<'tcx> {
self.evaluate_all(goals).and_then(|certainty| self.make_canonical_response(certainty))
}
-}
-#[instrument(level = "debug", skip(infcx), ret)]
-fn take_external_constraints<'tcx>(
- infcx: &InferCtxt<'tcx>,
-) -> Result<ExternalConstraints<'tcx>, NoSolution> {
- let region_obligations = infcx.take_registered_region_obligations();
- let opaque_types = infcx.take_opaque_types_for_query_response();
- Ok(ExternalConstraints {
- // FIXME: Now that's definitely wrong :)
- //
- // Should also do the leak check here I think
- regions: drop(region_obligations),
- opaque_types,
- })
-}
+ fn try_merge_responses(
+ &mut self,
+ responses: impl Iterator<Item = QueryResult<'tcx>>,
+ ) -> QueryResult<'tcx> {
+ let candidates = responses.into_iter().flatten().collect::<Box<[_]>>();
-fn instantiate_canonical_query_response<'tcx>(
- infcx: &InferCtxt<'tcx>,
- original_values: &OriginalQueryValues<'tcx>,
- response: CanonicalResponse<'tcx>,
-) -> Certainty {
- let Ok(InferOk { value, obligations }) = infcx
- .instantiate_query_response_and_region_obligations(
- &ObligationCause::dummy(),
- ty::ParamEnv::empty(),
- original_values,
- &response.unchecked_map(|resp| QueryResponse {
- var_values: resp.var_values,
- region_constraints: QueryRegionConstraints::default(),
- certainty: match resp.certainty {
- Certainty::Yes => OldCertainty::Proven,
- Certainty::Maybe(_) => OldCertainty::Ambiguous,
- },
- opaque_types: resp.external_constraints.opaque_types,
- value: resp.certainty,
- }),
- ) else { bug!(); };
- assert!(obligations.is_empty());
- value
+ if candidates.is_empty() {
+ return Err(NoSolution);
+ }
+
+ // FIXME(-Ztreat-solver=next): We should instead try to find a `Certainty::Yes` response with
+ // a subset of the constraints that all the other responses have.
+ let one = candidates[0];
+ if candidates[1..].iter().all(|resp| resp == &one) {
+ return Ok(one);
+ }
+
+ if let Some(response) = candidates.iter().find(|response| {
+ response.value.certainty == Certainty::Yes
+ && response.has_no_inference_or_external_constraints()
+ }) {
+ return Ok(*response);
+ }
+
+ let certainty = candidates.iter().fold(Certainty::AMBIGUOUS, |certainty, response| {
+ certainty.unify_and(response.value.certainty)
+ });
+ // FIXME(-Ztrait-solver=next): We should take the intersection of the constraints on all the
+ // responses and use that for the constraints of this ambiguous response.
+ let response = self.make_canonical_response(certainty);
+ if let Ok(response) = &response {
+ assert!(response.has_no_inference_or_external_constraints());
+ }
+
+ response
+ }
}
pub(super) fn response_no_constraints<'tcx>(
@@ -367,33 +566,14 @@ pub(super) fn response_no_constraints<'tcx>(
goal: Canonical<'tcx, impl Sized>,
certainty: Certainty,
) -> QueryResult<'tcx> {
- let var_values = goal
- .variables
- .iter()
- .enumerate()
- .map(|(i, info)| match info.kind {
- CanonicalVarKind::Ty(_) | CanonicalVarKind::PlaceholderTy(_) => {
- tcx.mk_ty(ty::Bound(ty::INNERMOST, ty::BoundVar::from_usize(i).into())).into()
- }
- CanonicalVarKind::Region(_) | CanonicalVarKind::PlaceholderRegion(_) => {
- let br = ty::BoundRegion {
- var: ty::BoundVar::from_usize(i),
- kind: ty::BrAnon(i as u32, None),
- };
- tcx.mk_region(ty::ReLateBound(ty::INNERMOST, br)).into()
- }
- CanonicalVarKind::Const(_, ty) | CanonicalVarKind::PlaceholderConst(_, ty) => tcx
- .mk_const(ty::ConstKind::Bound(ty::INNERMOST, ty::BoundVar::from_usize(i)), ty)
- .into(),
- })
- .collect();
-
Ok(Canonical {
max_universe: goal.max_universe,
variables: goal.variables,
value: Response {
- var_values: CanonicalVarValues { var_values },
- external_constraints: Default::default(),
+ var_values: CanonicalVarValues::make_identity(tcx, goal.variables),
+ // FIXME: maybe we should store the "no response" version in tcx, like
+ // we do for tcx.types and stuff.
+ external_constraints: tcx.mk_external_constraints(ExternalConstraintsData::default()),
certainty,
},
})
diff --git a/compiler/rustc_trait_selection/src/solve/project_goals.rs b/compiler/rustc_trait_selection/src/solve/project_goals.rs
index e39fa0533..33c66d072 100644
--- a/compiler/rustc_trait_selection/src/solve/project_goals.rs
+++ b/compiler/rustc_trait_selection/src/solve/project_goals.rs
@@ -1,23 +1,22 @@
use crate::traits::{specialization_graph, translate_substs};
-use super::assembly::{self, Candidate, CandidateSource};
-use super::infcx_ext::InferCtxtExt;
+use super::assembly;
use super::trait_goals::structural_traits;
-use super::{Certainty, EvalCtxt, Goal, MaybeCause, QueryResult};
+use super::{Certainty, EvalCtxt, Goal, QueryResult};
use rustc_errors::ErrorGuaranteed;
use rustc_hir::def::DefKind;
use rustc_hir::def_id::DefId;
+use rustc_hir::LangItem;
use rustc_infer::infer::InferCtxt;
use rustc_infer::traits::query::NoSolution;
use rustc_infer::traits::specialization_graph::LeafDef;
use rustc_infer::traits::Reveal;
use rustc_middle::ty::fast_reject::{DeepRejectCtxt, TreatParams};
+use rustc_middle::ty::ProjectionPredicate;
use rustc_middle::ty::{self, Ty, TyCtxt};
-use rustc_middle::ty::{ProjectionPredicate, TypeSuperVisitable, TypeVisitor};
-use rustc_middle::ty::{ToPredicate, TypeVisitable};
-use rustc_span::DUMMY_SP;
+use rustc_middle::ty::{ToPredicate, TypeVisitableExt};
+use rustc_span::{sym, DUMMY_SP};
use std::iter;
-use std::ops::ControlFlow;
impl<'tcx> EvalCtxt<'_, 'tcx> {
pub(super) fn compute_projection_goal(
@@ -27,151 +26,62 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
// To only compute normalization once for each projection we only
// normalize if the expected term is an unconstrained inference variable.
//
- // E.g. for `<T as Trait>::Assoc = u32` we recursively compute the goal
- // `exists<U> <T as Trait>::Assoc = U` and then take the resulting type for
+ // E.g. for `<T as Trait>::Assoc == u32` we recursively compute the goal
+ // `exists<U> <T as Trait>::Assoc == U` and then take the resulting type for
// `U` and equate it with `u32`. This means that we don't need a separate
// projection cache in the solver.
if self.term_is_fully_unconstrained(goal) {
let candidates = self.assemble_and_evaluate_candidates(goal);
- self.merge_project_candidates(candidates)
+ self.merge_candidates_and_discard_reservation_impls(candidates)
} else {
let predicate = goal.predicate;
let unconstrained_rhs = match predicate.term.unpack() {
- ty::TermKind::Ty(_) => self.infcx.next_ty_infer().into(),
- ty::TermKind::Const(ct) => self.infcx.next_const_infer(ct.ty()).into(),
+ ty::TermKind::Ty(_) => self.next_ty_infer().into(),
+ ty::TermKind::Const(ct) => self.next_const_infer(ct.ty()).into(),
};
let unconstrained_predicate = ty::Clause::Projection(ProjectionPredicate {
projection_ty: goal.predicate.projection_ty,
term: unconstrained_rhs,
});
- let (_has_changed, normalize_certainty) =
- self.evaluate_goal(goal.with(self.tcx(), unconstrained_predicate))?;
+ let (_has_changed, normalize_certainty) = self.in_projection_eq_hack(|this| {
+ this.evaluate_goal(goal.with(this.tcx(), unconstrained_predicate))
+ })?;
- let nested_eq_goals =
- self.infcx.eq(goal.param_env, unconstrained_rhs, predicate.term)?;
+ let nested_eq_goals = self.eq(goal.param_env, unconstrained_rhs, predicate.term)?;
let eval_certainty = self.evaluate_all(nested_eq_goals)?;
self.make_canonical_response(normalize_certainty.unify_and(eval_certainty))
}
}
- /// Is the projection predicate is of the form `exists<T> <Ty as Trait>::Assoc = T`.
- ///
- /// This is the case if the `term` is an inference variable in the innermost universe
- /// and does not occur in any other part of the predicate.
- fn term_is_fully_unconstrained(&self, goal: Goal<'tcx, ProjectionPredicate<'tcx>>) -> bool {
- let infcx = self.infcx;
- let term_is_infer = match goal.predicate.term.unpack() {
- ty::TermKind::Ty(ty) => {
- if let &ty::Infer(ty::TyVar(vid)) = ty.kind() {
- match infcx.probe_ty_var(vid) {
- Ok(value) => bug!("resolved var in query: {goal:?} {value:?}"),
- Err(universe) => universe == infcx.universe(),
- }
- } else {
- false
- }
- }
- ty::TermKind::Const(ct) => {
- if let ty::ConstKind::Infer(ty::InferConst::Var(vid)) = ct.kind() {
- match self.infcx.probe_const_var(vid) {
- Ok(value) => bug!("resolved var in query: {goal:?} {value:?}"),
- Err(universe) => universe == infcx.universe(),
- }
- } else {
- false
- }
- }
- };
-
- // Guard against `<T as Trait<?0>>::Assoc = ?0>`.
- struct ContainsTerm<'tcx> {
- term: ty::Term<'tcx>,
- }
- impl<'tcx> TypeVisitor<'tcx> for ContainsTerm<'tcx> {
- type BreakTy = ();
- fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
- if t.needs_infer() {
- if ty::Term::from(t) == self.term {
- ControlFlow::BREAK
- } else {
- t.super_visit_with(self)
- }
- } else {
- ControlFlow::CONTINUE
- }
- }
-
- fn visit_const(&mut self, c: ty::Const<'tcx>) -> ControlFlow<Self::BreakTy> {
- if c.needs_infer() {
- if ty::Term::from(c) == self.term {
- ControlFlow::BREAK
- } else {
- c.super_visit_with(self)
- }
- } else {
- ControlFlow::CONTINUE
- }
- }
- }
-
- let mut visitor = ContainsTerm { term: goal.predicate.term };
-
- term_is_infer
- && goal.predicate.projection_ty.visit_with(&mut visitor).is_continue()
- && goal.param_env.visit_with(&mut visitor).is_continue()
+ /// This sets a flag used by a debug assert in [`EvalCtxt::evaluate_goal`],
+ /// see the comment in that method for more details.
+ fn in_projection_eq_hack<T>(&mut self, f: impl FnOnce(&mut Self) -> T) -> T {
+ self.in_projection_eq_hack = true;
+ let result = f(self);
+ self.in_projection_eq_hack = false;
+ result
}
- fn merge_project_candidates(
+ /// After normalizing the projection to `normalized_alias` with the given
+ /// `normalization_certainty`, constrain the inference variable `term` to it
+ /// and return a query response.
+ fn eq_term_and_make_canonical_response(
&mut self,
- mut candidates: Vec<Candidate<'tcx>>,
+ goal: Goal<'tcx, ProjectionPredicate<'tcx>>,
+ normalization_certainty: Certainty,
+ normalized_alias: impl Into<ty::Term<'tcx>>,
) -> QueryResult<'tcx> {
- match candidates.len() {
- 0 => return Err(NoSolution),
- 1 => return Ok(candidates.pop().unwrap().result),
- _ => {}
- }
-
- if candidates.len() > 1 {
- let mut i = 0;
- 'outer: while i < candidates.len() {
- for j in (0..candidates.len()).filter(|&j| i != j) {
- if self.project_candidate_should_be_dropped_in_favor_of(
- &candidates[i],
- &candidates[j],
- ) {
- debug!(candidate = ?candidates[i], "Dropping candidate #{}/{}", i, candidates.len());
- candidates.swap_remove(i);
- continue 'outer;
- }
- }
+ // The term of our goal should be fully unconstrained, so this should never fail.
+ //
+ // It can however be ambiguous when the `normalized_alias` contains a projection.
+ let nested_goals = self
+ .eq(goal.param_env, goal.predicate.term, normalized_alias.into())
+ .expect("failed to unify with unconstrained term");
- debug!(candidate = ?candidates[i], "Retaining candidate #{}/{}", i, candidates.len());
- // If there are *STILL* multiple candidates, give up
- // and report ambiguity.
- i += 1;
- if i > 1 {
- debug!("multiple matches, ambig");
- // FIXME: return overflow if all candidates overflow, otherwise return ambiguity.
- unimplemented!();
- }
- }
- }
+ let unify_certainty =
+ self.evaluate_all(nested_goals).expect("failed to unify with unconstrained term");
- Ok(candidates.pop().unwrap().result)
- }
-
- fn project_candidate_should_be_dropped_in_favor_of(
- &self,
- candidate: &Candidate<'tcx>,
- other: &Candidate<'tcx>,
- ) -> bool {
- // FIXME: implement this
- match (candidate.source, other.source) {
- (CandidateSource::Impl(_), _)
- | (CandidateSource::ParamEnv(_), _)
- | (CandidateSource::BuiltinImpl, _)
- | (CandidateSource::AliasBound(_), _) => unimplemented!(),
- }
+ self.make_canonical_response(normalization_certainty.unify_and(unify_certainty))
}
}
@@ -188,6 +98,82 @@ impl<'tcx> assembly::GoalKind<'tcx> for ProjectionPredicate<'tcx> {
self.trait_def_id(tcx)
}
+ fn consider_implied_clause(
+ ecx: &mut EvalCtxt<'_, 'tcx>,
+ goal: Goal<'tcx, Self>,
+ assumption: ty::Predicate<'tcx>,
+ requirements: impl IntoIterator<Item = Goal<'tcx, ty::Predicate<'tcx>>>,
+ ) -> QueryResult<'tcx> {
+ if let Some(poly_projection_pred) = assumption.to_opt_poly_projection_pred()
+ && poly_projection_pred.projection_def_id() == goal.predicate.def_id()
+ {
+ ecx.probe(|ecx| {
+ let assumption_projection_pred =
+ ecx.instantiate_binder_with_infer(poly_projection_pred);
+ let mut nested_goals = ecx.eq(
+ goal.param_env,
+ goal.predicate.projection_ty,
+ assumption_projection_pred.projection_ty,
+ )?;
+ nested_goals.extend(requirements);
+ let subst_certainty = ecx.evaluate_all(nested_goals)?;
+
+ ecx.eq_term_and_make_canonical_response(
+ goal,
+ subst_certainty,
+ assumption_projection_pred.term,
+ )
+ })
+ } else {
+ Err(NoSolution)
+ }
+ }
+
+ fn consider_object_bound_candidate(
+ ecx: &mut EvalCtxt<'_, 'tcx>,
+ goal: Goal<'tcx, Self>,
+ assumption: ty::Predicate<'tcx>,
+ ) -> QueryResult<'tcx> {
+ if let Some(poly_projection_pred) = assumption.to_opt_poly_projection_pred()
+ && poly_projection_pred.projection_def_id() == goal.predicate.def_id()
+ {
+ ecx.probe(|ecx| {
+ let assumption_projection_pred =
+ ecx.instantiate_binder_with_infer(poly_projection_pred);
+ let mut nested_goals = ecx.eq(
+ goal.param_env,
+ goal.predicate.projection_ty,
+ assumption_projection_pred.projection_ty,
+ )?;
+
+ let tcx = ecx.tcx();
+ let ty::Dynamic(bounds, _, _) = *goal.predicate.self_ty().kind() else {
+ bug!("expected object type in `consider_object_bound_candidate`");
+ };
+ nested_goals.extend(
+ structural_traits::predicates_for_object_candidate(
+ ecx,
+ goal.param_env,
+ goal.predicate.projection_ty.trait_ref(tcx),
+ bounds,
+ )
+ .into_iter()
+ .map(|pred| goal.with(tcx, pred)),
+ );
+
+ let subst_certainty = ecx.evaluate_all(nested_goals)?;
+
+ ecx.eq_term_and_make_canonical_response(
+ goal,
+ subst_certainty,
+ assumption_projection_pred.term,
+ )
+ })
+ } else {
+ Err(NoSolution)
+ }
+ }
+
fn consider_impl_candidate(
ecx: &mut EvalCtxt<'_, 'tcx>,
goal: Goal<'tcx, ProjectionPredicate<'tcx>>,
@@ -204,11 +190,11 @@ impl<'tcx> assembly::GoalKind<'tcx> for ProjectionPredicate<'tcx> {
return Err(NoSolution);
}
- ecx.infcx.probe(|_| {
- let impl_substs = ecx.infcx.fresh_substs_for_item(DUMMY_SP, impl_def_id);
+ ecx.probe(|ecx| {
+ let impl_substs = ecx.fresh_substs_for_item(impl_def_id);
let impl_trait_ref = impl_trait_ref.subst(tcx, impl_substs);
- let mut nested_goals = ecx.infcx.eq(goal.param_env, goal_trait_ref, impl_trait_ref)?;
+ let mut nested_goals = ecx.eq(goal.param_env, goal_trait_ref, impl_trait_ref)?;
let where_clause_bounds = tcx
.predicates_of(impl_def_id)
.instantiate(tcx, impl_substs)
@@ -217,7 +203,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for ProjectionPredicate<'tcx> {
.map(|pred| goal.with(tcx, pred));
nested_goals.extend(where_clause_bounds);
- let trait_ref_certainty = ecx.evaluate_all(nested_goals)?;
+ let match_impl_certainty = ecx.evaluate_all(nested_goals)?;
// In case the associated item is hidden due to specialization, we have to
// return ambiguity this would otherwise be incomplete, resulting in
@@ -229,8 +215,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for ProjectionPredicate<'tcx> {
goal.predicate.def_id(),
impl_def_id
)? else {
- let certainty = Certainty::Maybe(MaybeCause::Ambiguity);
- return ecx.make_canonical_response(trait_ref_certainty.unify_and(certainty));
+ return ecx.make_canonical_response(match_impl_certainty.unify_and(Certainty::AMBIGUOUS));
};
if !assoc_def.item.defaultness(tcx).has_value() {
@@ -265,7 +250,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for ProjectionPredicate<'tcx> {
// Finally we construct the actual value of the associated type.
let is_const = matches!(tcx.def_kind(assoc_def.item.def_id), DefKind::AssocConst);
- let ty = tcx.bound_type_of(assoc_def.item.def_id);
+ let ty = tcx.type_of(assoc_def.item.def_id);
let term: ty::EarlyBinder<ty::Term<'tcx>> = if is_const {
let identity_substs =
ty::InternalSubsts::identity_for_item(tcx, assoc_def.item.def_id);
@@ -277,54 +262,10 @@ impl<'tcx> assembly::GoalKind<'tcx> for ProjectionPredicate<'tcx> {
ty.map_bound(|ty| ty.into())
};
- // The term of our goal should be fully unconstrained, so this should never fail.
- //
- // It can however be ambiguous when the resolved type is a projection.
- let nested_goals = ecx
- .infcx
- .eq(goal.param_env, goal.predicate.term, term.subst(tcx, substs))
- .expect("failed to unify with unconstrained term");
- let rhs_certainty =
- ecx.evaluate_all(nested_goals).expect("failed to unify with unconstrained term");
-
- ecx.make_canonical_response(trait_ref_certainty.unify_and(rhs_certainty))
+ ecx.eq_term_and_make_canonical_response(goal, match_impl_certainty, term.subst(tcx, substs))
})
}
- fn consider_assumption(
- ecx: &mut EvalCtxt<'_, 'tcx>,
- goal: Goal<'tcx, Self>,
- assumption: ty::Predicate<'tcx>,
- ) -> QueryResult<'tcx> {
- if let Some(poly_projection_pred) = assumption.to_opt_poly_projection_pred() {
- ecx.infcx.probe(|_| {
- let assumption_projection_pred =
- ecx.infcx.instantiate_bound_vars_with_infer(poly_projection_pred);
- let nested_goals = ecx.infcx.eq(
- goal.param_env,
- goal.predicate.projection_ty,
- assumption_projection_pred.projection_ty,
- )?;
- let subst_certainty = ecx.evaluate_all(nested_goals)?;
-
- // The term of our goal should be fully unconstrained, so this should never fail.
- //
- // It can however be ambiguous when the resolved type is a projection.
- let nested_goals = ecx
- .infcx
- .eq(goal.param_env, goal.predicate.term, assumption_projection_pred.term)
- .expect("failed to unify with unconstrained term");
- let rhs_certainty = ecx
- .evaluate_all(nested_goals)
- .expect("failed to unify with unconstrained term");
-
- ecx.make_canonical_response(subst_certainty.unify_and(rhs_certainty))
- })
- } else {
- Err(NoSolution)
- }
- }
-
fn consider_auto_trait_candidate(
_ecx: &mut EvalCtxt<'_, 'tcx>,
goal: Goal<'tcx, Self>,
@@ -353,11 +294,11 @@ impl<'tcx> assembly::GoalKind<'tcx> for ProjectionPredicate<'tcx> {
bug!("`Copy`/`Clone` does not have an associated type: {:?}", goal);
}
- fn consider_builtin_pointer_sized_candidate(
+ fn consider_builtin_pointer_like_candidate(
_ecx: &mut EvalCtxt<'_, 'tcx>,
goal: Goal<'tcx, Self>,
) -> QueryResult<'tcx> {
- bug!("`PointerSized` does not have an associated type: {:?}", goal);
+ bug!("`PointerLike` does not have an associated type: {:?}", goal);
}
fn consider_builtin_fn_trait_candidates(
@@ -365,25 +306,28 @@ impl<'tcx> assembly::GoalKind<'tcx> for ProjectionPredicate<'tcx> {
goal: Goal<'tcx, Self>,
goal_kind: ty::ClosureKind,
) -> QueryResult<'tcx> {
- if let Some(tupled_inputs_and_output) =
- structural_traits::extract_tupled_inputs_and_output_from_callable(
- ecx.tcx(),
- goal.predicate.self_ty(),
- goal_kind,
- )?
- {
- let pred = tupled_inputs_and_output
- .map_bound(|(inputs, output)| ty::ProjectionPredicate {
- projection_ty: ecx
- .tcx()
- .mk_alias_ty(goal.predicate.def_id(), [goal.predicate.self_ty(), inputs]),
- term: output.into(),
- })
- .to_predicate(ecx.tcx());
- Self::consider_assumption(ecx, goal, pred)
- } else {
- ecx.make_canonical_response(Certainty::Maybe(MaybeCause::Ambiguity))
- }
+ let tcx = ecx.tcx();
+ let Some(tupled_inputs_and_output) =
+ structural_traits::extract_tupled_inputs_and_output_from_callable(
+ tcx,
+ goal.predicate.self_ty(),
+ goal_kind,
+ )? else {
+ return ecx.make_canonical_response(Certainty::AMBIGUOUS);
+ };
+ let output_is_sized_pred = tupled_inputs_and_output
+ .map_bound(|(_, output)| tcx.at(DUMMY_SP).mk_trait_ref(LangItem::Sized, [output]));
+
+ let pred = tupled_inputs_and_output
+ .map_bound(|(inputs, output)| ty::ProjectionPredicate {
+ projection_ty: tcx
+ .mk_alias_ty(goal.predicate.def_id(), [goal.predicate.self_ty(), inputs]),
+ term: output.into(),
+ })
+ .to_predicate(tcx);
+ // A built-in `Fn` impl only holds if the output is sized.
+ // (FIXME: technically we only need to check this if the type is a fn ptr...)
+ Self::consider_implied_clause(ecx, goal, pred, [goal.with(tcx, output_is_sized_pred)])
}
fn consider_builtin_tuple_candidate(
@@ -392,6 +336,193 @@ impl<'tcx> assembly::GoalKind<'tcx> for ProjectionPredicate<'tcx> {
) -> QueryResult<'tcx> {
bug!("`Tuple` does not have an associated type: {:?}", goal);
}
+
+ fn consider_builtin_pointee_candidate(
+ ecx: &mut EvalCtxt<'_, 'tcx>,
+ goal: Goal<'tcx, Self>,
+ ) -> QueryResult<'tcx> {
+ let tcx = ecx.tcx();
+ ecx.probe(|ecx| {
+ let metadata_ty = match goal.predicate.self_ty().kind() {
+ ty::Bool
+ | ty::Char
+ | ty::Int(..)
+ | ty::Uint(..)
+ | ty::Float(..)
+ | ty::Array(..)
+ | ty::RawPtr(..)
+ | ty::Ref(..)
+ | ty::FnDef(..)
+ | ty::FnPtr(..)
+ | ty::Closure(..)
+ | ty::Infer(ty::IntVar(..) | ty::FloatVar(..))
+ | ty::Generator(..)
+ | ty::GeneratorWitness(..)
+ | ty::GeneratorWitnessMIR(..)
+ | ty::Never
+ | ty::Foreign(..) => tcx.types.unit,
+
+ ty::Error(e) => tcx.ty_error(*e),
+
+ ty::Str | ty::Slice(_) => tcx.types.usize,
+
+ ty::Dynamic(_, _, _) => {
+ let dyn_metadata = tcx.require_lang_item(LangItem::DynMetadata, None);
+ tcx.type_of(dyn_metadata)
+ .subst(tcx, &[ty::GenericArg::from(goal.predicate.self_ty())])
+ }
+
+ ty::Alias(_, _) | ty::Param(_) | ty::Placeholder(..) => {
+ // FIXME(ptr_metadata): It would also be possible to return a `Ok(Ambig)` with no constraints.
+ let sized_predicate = ty::Binder::dummy(tcx.at(DUMMY_SP).mk_trait_ref(
+ LangItem::Sized,
+ [ty::GenericArg::from(goal.predicate.self_ty())],
+ ));
+
+ let (_, is_sized_certainty) =
+ ecx.evaluate_goal(goal.with(tcx, sized_predicate))?;
+ return ecx.eq_term_and_make_canonical_response(
+ goal,
+ is_sized_certainty,
+ tcx.types.unit,
+ );
+ }
+
+ ty::Adt(def, substs) if def.is_struct() => {
+ match def.non_enum_variant().fields.last() {
+ None => tcx.types.unit,
+ Some(field_def) => {
+ let self_ty = field_def.ty(tcx, substs);
+ let new_goal = goal.with(
+ tcx,
+ ty::Binder::dummy(goal.predicate.with_self_ty(tcx, self_ty)),
+ );
+ let (_, certainty) = ecx.evaluate_goal(new_goal)?;
+ return ecx.make_canonical_response(certainty);
+ }
+ }
+ }
+ ty::Adt(_, _) => tcx.types.unit,
+
+ ty::Tuple(elements) => match elements.last() {
+ None => tcx.types.unit,
+ Some(&self_ty) => {
+ let new_goal = goal.with(
+ tcx,
+ ty::Binder::dummy(goal.predicate.with_self_ty(tcx, self_ty)),
+ );
+ let (_, certainty) = ecx.evaluate_goal(new_goal)?;
+ return ecx.make_canonical_response(certainty);
+ }
+ },
+
+ ty::Infer(
+ ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_),
+ )
+ | ty::Bound(..) => bug!(
+ "unexpected self ty `{:?}` when normalizing `<T as Pointee>::Metadata`",
+ goal.predicate.self_ty()
+ ),
+ };
+
+ ecx.eq_term_and_make_canonical_response(goal, Certainty::Yes, metadata_ty)
+ })
+ }
+
+ fn consider_builtin_future_candidate(
+ ecx: &mut EvalCtxt<'_, 'tcx>,
+ goal: Goal<'tcx, Self>,
+ ) -> QueryResult<'tcx> {
+ let self_ty = goal.predicate.self_ty();
+ let ty::Generator(def_id, substs, _) = *self_ty.kind() else {
+ return Err(NoSolution);
+ };
+
+ // Generators are not futures unless they come from `async` desugaring
+ let tcx = ecx.tcx();
+ if !tcx.generator_is_async(def_id) {
+ return Err(NoSolution);
+ }
+
+ let term = substs.as_generator().return_ty().into();
+
+ Self::consider_implied_clause(
+ ecx,
+ goal,
+ ty::Binder::dummy(ty::ProjectionPredicate {
+ projection_ty: ecx.tcx().mk_alias_ty(goal.predicate.def_id(), [self_ty]),
+ term,
+ })
+ .to_predicate(tcx),
+ // Technically, we need to check that the future type is Sized,
+ // but that's already proven by the generator being WF.
+ [],
+ )
+ }
+
+ fn consider_builtin_generator_candidate(
+ ecx: &mut EvalCtxt<'_, 'tcx>,
+ goal: Goal<'tcx, Self>,
+ ) -> QueryResult<'tcx> {
+ let self_ty = goal.predicate.self_ty();
+ let ty::Generator(def_id, substs, _) = *self_ty.kind() else {
+ return Err(NoSolution);
+ };
+
+ // `async`-desugared generators do not implement the generator trait
+ let tcx = ecx.tcx();
+ if tcx.generator_is_async(def_id) {
+ return Err(NoSolution);
+ }
+
+ let generator = substs.as_generator();
+
+ let name = tcx.associated_item(goal.predicate.def_id()).name;
+ let term = if name == sym::Return {
+ generator.return_ty().into()
+ } else if name == sym::Yield {
+ generator.yield_ty().into()
+ } else {
+ bug!("unexpected associated item `<{self_ty} as Generator>::{name}`")
+ };
+
+ Self::consider_implied_clause(
+ ecx,
+ goal,
+ ty::Binder::dummy(ty::ProjectionPredicate {
+ projection_ty: ecx
+ .tcx()
+ .mk_alias_ty(goal.predicate.def_id(), [self_ty, generator.resume_ty()]),
+ term,
+ })
+ .to_predicate(tcx),
+ // Technically, we need to check that the future type is Sized,
+ // but that's already proven by the generator being WF.
+ [],
+ )
+ }
+
+ fn consider_builtin_unsize_candidate(
+ _ecx: &mut EvalCtxt<'_, 'tcx>,
+ goal: Goal<'tcx, Self>,
+ ) -> QueryResult<'tcx> {
+ bug!("`Unsize` does not have an associated type: {:?}", goal);
+ }
+
+ fn consider_builtin_dyn_upcast_candidates(
+ _ecx: &mut EvalCtxt<'_, 'tcx>,
+ goal: Goal<'tcx, Self>,
+ ) -> Vec<super::CanonicalResponse<'tcx>> {
+ bug!("`Unsize` does not have an associated type: {:?}", goal);
+ }
+
+ fn consider_builtin_discriminant_kind_candidate(
+ ecx: &mut EvalCtxt<'_, 'tcx>,
+ goal: Goal<'tcx, Self>,
+ ) -> QueryResult<'tcx> {
+ let discriminant = goal.predicate.self_ty().discriminant_ty(ecx.tcx());
+ ecx.probe(|ecx| ecx.eq_term_and_make_canonical_response(goal, Certainty::Yes, discriminant))
+ }
}
/// This behavior is also implemented in `rustc_ty_utils` and in the old `project` code.
diff --git a/compiler/rustc_trait_selection/src/solve/search_graph/cache.rs b/compiler/rustc_trait_selection/src/solve/search_graph/cache.rs
index 730a8e612..86b13c05f 100644
--- a/compiler/rustc_trait_selection/src/solve/search_graph/cache.rs
+++ b/compiler/rustc_trait_selection/src/solve/search_graph/cache.rs
@@ -95,7 +95,7 @@ impl<'tcx> ProvisionalCache<'tcx> {
}
pub(super) fn provisional_result(&self, entry_index: EntryIndex) -> QueryResult<'tcx> {
- self.entries[entry_index].response.clone()
+ self.entries[entry_index].response
}
}
diff --git a/compiler/rustc_trait_selection/src/solve/search_graph/mod.rs b/compiler/rustc_trait_selection/src/solve/search_graph/mod.rs
index 0030e9aa3..c7eb8de65 100644
--- a/compiler/rustc_trait_selection/src/solve/search_graph/mod.rs
+++ b/compiler/rustc_trait_selection/src/solve/search_graph/mod.rs
@@ -3,11 +3,12 @@ mod overflow;
use self::cache::ProvisionalEntry;
use super::{CanonicalGoal, Certainty, MaybeCause, QueryResult};
+pub(super) use crate::solve::search_graph::overflow::OverflowHandler;
use cache::ProvisionalCache;
use overflow::OverflowData;
use rustc_index::vec::IndexVec;
use rustc_middle::ty::TyCtxt;
-use std::collections::hash_map::Entry;
+use std::{collections::hash_map::Entry, mem};
rustc_index::newtype_index! {
pub struct StackDepth {}
@@ -42,10 +43,29 @@ impl<'tcx> SearchGraph<'tcx> {
&& !self.overflow_data.did_overflow()
}
+ /// Whether we're currently in a cycle. This should only be used
+ /// for debug assertions.
+ pub(super) fn in_cycle(&self) -> bool {
+ if let Some(stack_depth) = self.stack.last() {
+ // Either the current goal on the stack is the root of a cycle...
+ if self.stack[stack_depth].has_been_used {
+ return true;
+ }
+
+ // ...or it depends on a goal with a lower depth.
+ let current_goal = self.stack[stack_depth].goal;
+ let entry_index = self.provisional_cache.lookup_table[&current_goal];
+ self.provisional_cache.entries[entry_index].depth != stack_depth
+ } else {
+ false
+ }
+ }
+
/// Tries putting the new goal on the stack, returning an error if it is already cached.
///
/// This correctly updates the provisional cache if there is a cycle.
- pub(super) fn try_push_stack(
+ #[instrument(level = "debug", skip(self, tcx), ret)]
+ fn try_push_stack(
&mut self,
tcx: TyCtxt<'tcx>,
goal: CanonicalGoal<'tcx>,
@@ -79,8 +99,10 @@ impl<'tcx> SearchGraph<'tcx> {
Entry::Occupied(entry_index) => {
let entry_index = *entry_index.get();
- cache.add_dependency_of_leaf_on(entry_index);
let stack_depth = cache.depth(entry_index);
+ debug!("encountered cycle with depth {stack_depth:?}");
+
+ cache.add_dependency_of_leaf_on(entry_index);
self.stack[stack_depth].has_been_used = true;
// NOTE: The goals on the stack aren't the only goals involved in this cycle.
@@ -117,25 +139,29 @@ impl<'tcx> SearchGraph<'tcx> {
/// updated the provisional cache and we have to recompute the current goal.
///
/// FIXME: Refer to the rustc-dev-guide entry once it exists.
- pub(super) fn try_finalize_goal(
+ #[instrument(level = "debug", skip(self, tcx, actual_goal), ret)]
+ fn try_finalize_goal(
&mut self,
tcx: TyCtxt<'tcx>,
actual_goal: CanonicalGoal<'tcx>,
response: QueryResult<'tcx>,
) -> bool {
- let StackElem { goal, has_been_used } = self.stack.pop().unwrap();
+ let stack_elem = self.stack.pop().unwrap();
+ let StackElem { goal, has_been_used } = stack_elem;
assert_eq!(goal, actual_goal);
let cache = &mut self.provisional_cache;
let provisional_entry_index = *cache.lookup_table.get(&goal).unwrap();
let provisional_entry = &mut cache.entries[provisional_entry_index];
- let depth = provisional_entry.depth;
+ // We eagerly update the response in the cache here. If we have to reevaluate
+ // this goal we use the new response when hitting a cycle, and we definitely
+ // want to access the final response whenever we look at the cache.
+ let prev_response = mem::replace(&mut provisional_entry.response, response);
+
// Was the current goal the root of a cycle and was the provisional response
// different from the final one.
- if has_been_used && provisional_entry.response != response {
- // If so, update the provisional reponse for this goal...
- provisional_entry.response = response;
- // ...remove all entries whose result depends on this goal
+ if has_been_used && prev_response != response {
+ // If so, remove all entries whose result depends on this goal
// from the provisional cache...
//
// That's not completely correct, as a nested goal can also
@@ -150,29 +176,72 @@ impl<'tcx> SearchGraph<'tcx> {
self.stack.push(StackElem { goal, has_been_used: false });
false
} else {
- // If not, we're done with this goal.
- //
- // Check whether that this goal doesn't depend on a goal deeper on the stack
- // and if so, move it and all nested goals to the global cache.
- //
- // Note that if any nested goal were to depend on something deeper on the stack,
- // this would have also updated the depth of the current goal.
- if depth == self.stack.next_index() {
- for (i, entry) in cache.entries.drain_enumerated(provisional_entry_index.index()..)
- {
- let actual_index = cache.lookup_table.remove(&entry.goal);
- debug_assert_eq!(Some(i), actual_index);
- debug_assert!(entry.depth == depth);
- cache::try_move_finished_goal_to_global_cache(
- tcx,
- &mut self.overflow_data,
- &self.stack,
- entry.goal,
- entry.response,
- );
- }
- }
+ self.try_move_finished_goal_to_global_cache(tcx, stack_elem);
true
}
}
+
+ fn try_move_finished_goal_to_global_cache(
+ &mut self,
+ tcx: TyCtxt<'tcx>,
+ stack_elem: StackElem<'tcx>,
+ ) {
+ let StackElem { goal, .. } = stack_elem;
+ let cache = &mut self.provisional_cache;
+ let provisional_entry_index = *cache.lookup_table.get(&goal).unwrap();
+ let provisional_entry = &mut cache.entries[provisional_entry_index];
+ let depth = provisional_entry.depth;
+
+ // If not, we're done with this goal.
+ //
+ // Check whether that this goal doesn't depend on a goal deeper on the stack
+ // and if so, move it and all nested goals to the global cache.
+ //
+ // Note that if any nested goal were to depend on something deeper on the stack,
+ // this would have also updated the depth of the current goal.
+ if depth == self.stack.next_index() {
+ for (i, entry) in cache.entries.drain_enumerated(provisional_entry_index.index()..) {
+ let actual_index = cache.lookup_table.remove(&entry.goal);
+ debug_assert_eq!(Some(i), actual_index);
+ debug_assert!(entry.depth == depth);
+ cache::try_move_finished_goal_to_global_cache(
+ tcx,
+ &mut self.overflow_data,
+ &self.stack,
+ entry.goal,
+ entry.response,
+ );
+ }
+ }
+ }
+
+ pub(super) fn with_new_goal(
+ &mut self,
+ tcx: TyCtxt<'tcx>,
+ canonical_goal: CanonicalGoal<'tcx>,
+ mut loop_body: impl FnMut(&mut Self) -> QueryResult<'tcx>,
+ ) -> QueryResult<'tcx> {
+ match self.try_push_stack(tcx, canonical_goal) {
+ Ok(()) => {}
+ // Our goal is already on the stack, eager return.
+ Err(response) => return response,
+ }
+
+ self.repeat_while_none(
+ |this| {
+ let result = this.deal_with_overflow(tcx, canonical_goal);
+ let stack_elem = this.stack.pop().unwrap();
+ this.try_move_finished_goal_to_global_cache(tcx, stack_elem);
+ result
+ },
+ |this| {
+ let result = loop_body(this);
+ if this.try_finalize_goal(tcx, canonical_goal, result) {
+ Some(result)
+ } else {
+ None
+ }
+ },
+ )
+ }
}
diff --git a/compiler/rustc_trait_selection/src/solve/search_graph/overflow.rs b/compiler/rustc_trait_selection/src/solve/search_graph/overflow.rs
index 1dd3894c9..56409b060 100644
--- a/compiler/rustc_trait_selection/src/solve/search_graph/overflow.rs
+++ b/compiler/rustc_trait_selection/src/solve/search_graph/overflow.rs
@@ -50,6 +50,42 @@ impl OverflowData {
}
}
+pub(in crate::solve) trait OverflowHandler<'tcx> {
+ fn search_graph(&mut self) -> &mut SearchGraph<'tcx>;
+
+ fn repeat_while_none<T>(
+ &mut self,
+ on_overflow: impl FnOnce(&mut Self) -> Result<T, NoSolution>,
+ mut loop_body: impl FnMut(&mut Self) -> Option<Result<T, NoSolution>>,
+ ) -> Result<T, NoSolution> {
+ let start_depth = self.search_graph().overflow_data.additional_depth;
+ let depth = self.search_graph().stack.len();
+ while !self.search_graph().overflow_data.has_overflow(depth) {
+ if let Some(result) = loop_body(self) {
+ self.search_graph().overflow_data.additional_depth = start_depth;
+ return result;
+ }
+
+ self.search_graph().overflow_data.additional_depth += 1;
+ }
+ self.search_graph().overflow_data.additional_depth = start_depth;
+ self.search_graph().overflow_data.deal_with_overflow();
+ on_overflow(self)
+ }
+}
+
+impl<'tcx> OverflowHandler<'tcx> for EvalCtxt<'_, 'tcx> {
+ fn search_graph(&mut self) -> &mut SearchGraph<'tcx> {
+ &mut self.search_graph
+ }
+}
+
+impl<'tcx> OverflowHandler<'tcx> for SearchGraph<'tcx> {
+ fn search_graph(&mut self) -> &mut SearchGraph<'tcx> {
+ self
+ }
+}
+
impl<'tcx> SearchGraph<'tcx> {
pub fn deal_with_overflow(
&mut self,
@@ -60,25 +96,3 @@ impl<'tcx> SearchGraph<'tcx> {
response_no_constraints(tcx, goal, Certainty::Maybe(MaybeCause::Overflow))
}
}
-
-impl<'tcx> EvalCtxt<'_, 'tcx> {
- /// A `while`-loop which tracks overflow.
- pub fn repeat_while_none(
- &mut self,
- mut loop_body: impl FnMut(&mut Self) -> Option<Result<Certainty, NoSolution>>,
- ) -> Result<Certainty, NoSolution> {
- let start_depth = self.search_graph.overflow_data.additional_depth;
- let depth = self.search_graph.stack.len();
- while !self.search_graph.overflow_data.has_overflow(depth) {
- if let Some(result) = loop_body(self) {
- self.search_graph.overflow_data.additional_depth = start_depth;
- return result;
- }
-
- self.search_graph.overflow_data.additional_depth += 1;
- }
- self.search_graph.overflow_data.additional_depth = start_depth;
- self.search_graph.overflow_data.deal_with_overflow();
- Ok(Certainty::Maybe(MaybeCause::Overflow))
- }
-}
diff --git a/compiler/rustc_trait_selection/src/solve/trait_goals.rs b/compiler/rustc_trait_selection/src/solve/trait_goals.rs
index 9985d7181..5c499c36e 100644
--- a/compiler/rustc_trait_selection/src/solve/trait_goals.rs
+++ b/compiler/rustc_trait_selection/src/solve/trait_goals.rs
@@ -2,15 +2,15 @@
use std::iter;
-use super::assembly::{self, Candidate, CandidateSource};
-use super::infcx_ext::InferCtxtExt;
-use super::{Certainty, EvalCtxt, Goal, MaybeCause, QueryResult};
+use super::assembly;
+use super::{CanonicalResponse, Certainty, EvalCtxt, Goal, QueryResult};
use rustc_hir::def_id::DefId;
-use rustc_infer::infer::InferCtxt;
+use rustc_hir::LangItem;
use rustc_infer::traits::query::NoSolution;
+use rustc_infer::traits::util::supertraits;
use rustc_middle::ty::fast_reject::{DeepRejectCtxt, TreatParams};
use rustc_middle::ty::{self, ToPredicate, Ty, TyCtxt};
-use rustc_middle::ty::{TraitPredicate, TypeVisitable};
+use rustc_middle::ty::{TraitPredicate, TypeVisitableExt};
use rustc_span::DUMMY_SP;
pub mod structural_traits;
@@ -43,12 +43,12 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
return Err(NoSolution);
}
- ecx.infcx.probe(|_| {
- let impl_substs = ecx.infcx.fresh_substs_for_item(DUMMY_SP, impl_def_id);
+ ecx.probe(|ecx| {
+ let impl_substs = ecx.fresh_substs_for_item(impl_def_id);
let impl_trait_ref = impl_trait_ref.subst(tcx, impl_substs);
let mut nested_goals =
- ecx.infcx.eq(goal.param_env, goal.predicate.trait_ref, impl_trait_ref)?;
+ ecx.eq(goal.param_env, goal.predicate.trait_ref, impl_trait_ref)?;
let where_clause_bounds = tcx
.predicates_of(impl_def_id)
.instantiate(tcx, impl_substs)
@@ -60,21 +60,65 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
})
}
- fn consider_assumption(
+ fn consider_implied_clause(
ecx: &mut EvalCtxt<'_, 'tcx>,
goal: Goal<'tcx, Self>,
assumption: ty::Predicate<'tcx>,
+ requirements: impl IntoIterator<Item = Goal<'tcx, ty::Predicate<'tcx>>>,
) -> QueryResult<'tcx> {
- if let Some(poly_trait_pred) = assumption.to_opt_poly_trait_pred() {
+ if let Some(poly_trait_pred) = assumption.to_opt_poly_trait_pred()
+ && poly_trait_pred.def_id() == goal.predicate.def_id()
+ {
// FIXME: Constness and polarity
- ecx.infcx.probe(|_| {
+ ecx.probe(|ecx| {
let assumption_trait_pred =
- ecx.infcx.instantiate_bound_vars_with_infer(poly_trait_pred);
- let nested_goals = ecx.infcx.eq(
+ ecx.instantiate_binder_with_infer(poly_trait_pred);
+ let mut nested_goals = ecx.eq(
goal.param_env,
goal.predicate.trait_ref,
assumption_trait_pred.trait_ref,
)?;
+ nested_goals.extend(requirements);
+ ecx.evaluate_all_and_make_canonical_response(nested_goals)
+ })
+ } else {
+ Err(NoSolution)
+ }
+ }
+
+ fn consider_object_bound_candidate(
+ ecx: &mut EvalCtxt<'_, 'tcx>,
+ goal: Goal<'tcx, Self>,
+ assumption: ty::Predicate<'tcx>,
+ ) -> QueryResult<'tcx> {
+ if let Some(poly_trait_pred) = assumption.to_opt_poly_trait_pred()
+ && poly_trait_pred.def_id() == goal.predicate.def_id()
+ {
+ // FIXME: Constness and polarity
+ ecx.probe(|ecx| {
+ let assumption_trait_pred =
+ ecx.instantiate_binder_with_infer(poly_trait_pred);
+ let mut nested_goals = ecx.eq(
+ goal.param_env,
+ goal.predicate.trait_ref,
+ assumption_trait_pred.trait_ref,
+ )?;
+
+ let tcx = ecx.tcx();
+ let ty::Dynamic(bounds, _, _) = *goal.predicate.self_ty().kind() else {
+ bug!("expected object type in `consider_object_bound_candidate`");
+ };
+ nested_goals.extend(
+ structural_traits::predicates_for_object_candidate(
+ ecx,
+ goal.param_env,
+ goal.predicate.trait_ref,
+ bounds,
+ )
+ .into_iter()
+ .map(|pred| goal.with(tcx, pred)),
+ );
+
ecx.evaluate_all_and_make_canonical_response(nested_goals)
})
} else {
@@ -86,6 +130,20 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
ecx: &mut EvalCtxt<'_, 'tcx>,
goal: Goal<'tcx, Self>,
) -> QueryResult<'tcx> {
+ // This differs from the current stable behavior and
+ // fixes #84857. Due to breakage found via crater, we
+ // currently instead lint patterns which can be used to
+ // exploit this unsoundness on stable, see #93367 for
+ // more details.
+ if let Some(def_id) = ecx.tcx().find_map_relevant_impl(
+ goal.predicate.def_id(),
+ goal.predicate.self_ty(),
+ Some,
+ ) {
+ debug!(?def_id, ?goal, "disqualified auto-trait implementation");
+ return Err(NoSolution);
+ }
+
ecx.probe_and_evaluate_goal_for_constituent_tys(
goal,
structural_traits::instantiate_constituent_tys_for_auto_trait,
@@ -98,7 +156,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
) -> QueryResult<'tcx> {
let tcx = ecx.tcx();
- ecx.infcx.probe(|_| {
+ ecx.probe(|ecx| {
let nested_obligations = tcx
.predicates_of(goal.predicate.def_id())
.instantiate(tcx, goal.predicate.trait_ref.substs);
@@ -128,12 +186,12 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
)
}
- fn consider_builtin_pointer_sized_candidate(
+ fn consider_builtin_pointer_like_candidate(
ecx: &mut EvalCtxt<'_, 'tcx>,
goal: Goal<'tcx, Self>,
) -> QueryResult<'tcx> {
if goal.predicate.self_ty().has_non_region_infer() {
- return ecx.make_canonical_response(Certainty::Maybe(MaybeCause::Ambiguity));
+ return ecx.make_canonical_response(Certainty::AMBIGUOUS);
}
let tcx = ecx.tcx();
@@ -156,23 +214,26 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
goal: Goal<'tcx, Self>,
goal_kind: ty::ClosureKind,
) -> QueryResult<'tcx> {
- if let Some(tupled_inputs_and_output) =
+ let tcx = ecx.tcx();
+ let Some(tupled_inputs_and_output) =
structural_traits::extract_tupled_inputs_and_output_from_callable(
- ecx.tcx(),
+ tcx,
goal.predicate.self_ty(),
goal_kind,
- )?
- {
- let pred = tupled_inputs_and_output
- .map_bound(|(inputs, _)| {
- ecx.tcx()
- .mk_trait_ref(goal.predicate.def_id(), [goal.predicate.self_ty(), inputs])
- })
- .to_predicate(ecx.tcx());
- Self::consider_assumption(ecx, goal, pred)
- } else {
- ecx.make_canonical_response(Certainty::Maybe(MaybeCause::Ambiguity))
- }
+ )? else {
+ return ecx.make_canonical_response(Certainty::AMBIGUOUS);
+ };
+ let output_is_sized_pred = tupled_inputs_and_output
+ .map_bound(|(_, output)| tcx.at(DUMMY_SP).mk_trait_ref(LangItem::Sized, [output]));
+
+ let pred = tupled_inputs_and_output
+ .map_bound(|(inputs, _)| {
+ tcx.mk_trait_ref(goal.predicate.def_id(), [goal.predicate.self_ty(), inputs])
+ })
+ .to_predicate(tcx);
+ // A built-in `Fn` impl only holds if the output is sized.
+ // (FIXME: technically we only need to check this if the type is a fn ptr...)
+ Self::consider_implied_clause(ecx, goal, pred, [goal.with(tcx, output_is_sized_pred)])
}
fn consider_builtin_tuple_candidate(
@@ -185,6 +246,272 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
Err(NoSolution)
}
}
+
+ fn consider_builtin_pointee_candidate(
+ ecx: &mut EvalCtxt<'_, 'tcx>,
+ _goal: Goal<'tcx, Self>,
+ ) -> QueryResult<'tcx> {
+ ecx.make_canonical_response(Certainty::Yes)
+ }
+
+ fn consider_builtin_future_candidate(
+ ecx: &mut EvalCtxt<'_, 'tcx>,
+ goal: Goal<'tcx, Self>,
+ ) -> QueryResult<'tcx> {
+ let ty::Generator(def_id, _, _) = *goal.predicate.self_ty().kind() else {
+ return Err(NoSolution);
+ };
+
+ // Generators are not futures unless they come from `async` desugaring
+ let tcx = ecx.tcx();
+ if !tcx.generator_is_async(def_id) {
+ return Err(NoSolution);
+ }
+
+ // Async generator unconditionally implement `Future`
+ // Technically, we need to check that the future output type is Sized,
+ // but that's already proven by the generator being WF.
+ ecx.make_canonical_response(Certainty::Yes)
+ }
+
+ fn consider_builtin_generator_candidate(
+ ecx: &mut EvalCtxt<'_, 'tcx>,
+ goal: Goal<'tcx, Self>,
+ ) -> QueryResult<'tcx> {
+ let self_ty = goal.predicate.self_ty();
+ let ty::Generator(def_id, substs, _) = *self_ty.kind() else {
+ return Err(NoSolution);
+ };
+
+ // `async`-desugared generators do not implement the generator trait
+ let tcx = ecx.tcx();
+ if tcx.generator_is_async(def_id) {
+ return Err(NoSolution);
+ }
+
+ let generator = substs.as_generator();
+ Self::consider_implied_clause(
+ ecx,
+ goal,
+ ty::Binder::dummy(
+ tcx.mk_trait_ref(goal.predicate.def_id(), [self_ty, generator.resume_ty()]),
+ )
+ .to_predicate(tcx),
+ // Technically, we need to check that the generator types are Sized,
+ // but that's already proven by the generator being WF.
+ [],
+ )
+ }
+
+ fn consider_builtin_unsize_candidate(
+ ecx: &mut EvalCtxt<'_, 'tcx>,
+ goal: Goal<'tcx, Self>,
+ ) -> QueryResult<'tcx> {
+ let tcx = ecx.tcx();
+ let a_ty = goal.predicate.self_ty();
+ let b_ty = goal.predicate.trait_ref.substs.type_at(1);
+ if b_ty.is_ty_var() {
+ return ecx.make_canonical_response(Certainty::AMBIGUOUS);
+ }
+ ecx.probe(|ecx| {
+ match (a_ty.kind(), b_ty.kind()) {
+ // Trait upcasting, or `dyn Trait + Auto + 'a` -> `dyn Trait + 'b`
+ (&ty::Dynamic(_, _, ty::Dyn), &ty::Dynamic(_, _, ty::Dyn)) => {
+ // Dyn upcasting is handled separately, since due to upcasting,
+ // when there are two supertraits that differ by substs, we
+ // may return more than one query response.
+ return Err(NoSolution);
+ }
+ // `T` -> `dyn Trait` unsizing
+ (_, &ty::Dynamic(data, region, ty::Dyn)) => {
+ // Can only unsize to an object-safe type
+ if data
+ .principal_def_id()
+ .map_or(false, |def_id| !tcx.check_is_object_safe(def_id))
+ {
+ return Err(NoSolution);
+ }
+
+ let Some(sized_def_id) = tcx.lang_items().sized_trait() else {
+ return Err(NoSolution);
+ };
+ let nested_goals: Vec<_> = data
+ .iter()
+ // Check that the type implements all of the predicates of the def-id.
+ // (i.e. the principal, all of the associated types match, and any auto traits)
+ .map(|pred| goal.with(tcx, pred.with_self_ty(tcx, a_ty)))
+ .chain([
+ // The type must be Sized to be unsized.
+ goal.with(
+ tcx,
+ ty::Binder::dummy(tcx.mk_trait_ref(sized_def_id, [a_ty])),
+ ),
+ // The type must outlive the lifetime of the `dyn` we're unsizing into.
+ goal.with(tcx, ty::Binder::dummy(ty::OutlivesPredicate(a_ty, region))),
+ ])
+ .collect();
+
+ ecx.evaluate_all_and_make_canonical_response(nested_goals)
+ }
+ // `[T; n]` -> `[T]` unsizing
+ (&ty::Array(a_elem_ty, ..), &ty::Slice(b_elem_ty)) => {
+ // We just require that the element type stays the same
+ let nested_goals = ecx.eq(goal.param_env, a_elem_ty, b_elem_ty)?;
+ ecx.evaluate_all_and_make_canonical_response(nested_goals)
+ }
+ // Struct unsizing `Struct<T>` -> `Struct<U>` where `T: Unsize<U>`
+ (&ty::Adt(a_def, a_substs), &ty::Adt(b_def, b_substs))
+ if a_def.is_struct() && a_def.did() == b_def.did() =>
+ {
+ let unsizing_params = tcx.unsizing_params_for_adt(a_def.did());
+ // We must be unsizing some type parameters. This also implies
+ // that the struct has a tail field.
+ if unsizing_params.is_empty() {
+ return Err(NoSolution);
+ }
+
+ let tail_field = a_def
+ .non_enum_variant()
+ .fields
+ .last()
+ .expect("expected unsized ADT to have a tail field");
+ let tail_field_ty = tcx.type_of(tail_field.did);
+
+ let a_tail_ty = tail_field_ty.subst(tcx, a_substs);
+ let b_tail_ty = tail_field_ty.subst(tcx, b_substs);
+
+ // Substitute just the unsizing params from B into A. The type after
+ // this substitution must be equal to B. This is so we don't unsize
+ // unrelated type parameters.
+ let new_a_substs =
+ tcx.mk_substs_from_iter(a_substs.iter().enumerate().map(|(i, a)| {
+ if unsizing_params.contains(i as u32) { b_substs[i] } else { a }
+ }));
+ let unsized_a_ty = tcx.mk_adt(a_def, new_a_substs);
+
+ // Finally, we require that `TailA: Unsize<TailB>` for the tail field
+ // types.
+ let mut nested_goals = ecx.eq(goal.param_env, unsized_a_ty, b_ty)?;
+ nested_goals.push(goal.with(
+ tcx,
+ ty::Binder::dummy(
+ tcx.mk_trait_ref(goal.predicate.def_id(), [a_tail_ty, b_tail_ty]),
+ ),
+ ));
+
+ ecx.evaluate_all_and_make_canonical_response(nested_goals)
+ }
+ // Tuple unsizing `(.., T)` -> `(.., U)` where `T: Unsize<U>`
+ (&ty::Tuple(a_tys), &ty::Tuple(b_tys))
+ if a_tys.len() == b_tys.len() && !a_tys.is_empty() =>
+ {
+ let (a_last_ty, a_rest_tys) = a_tys.split_last().unwrap();
+ let b_last_ty = b_tys.last().unwrap();
+
+ // Substitute just the tail field of B., and require that they're equal.
+ let unsized_a_ty =
+ tcx.mk_tup_from_iter(a_rest_tys.iter().chain([b_last_ty]).copied());
+ let mut nested_goals = ecx.eq(goal.param_env, unsized_a_ty, b_ty)?;
+
+ // Similar to ADTs, require that the rest of the fields are equal.
+ nested_goals.push(goal.with(
+ tcx,
+ ty::Binder::dummy(
+ tcx.mk_trait_ref(goal.predicate.def_id(), [*a_last_ty, *b_last_ty]),
+ ),
+ ));
+
+ ecx.evaluate_all_and_make_canonical_response(nested_goals)
+ }
+ _ => Err(NoSolution),
+ }
+ })
+ }
+
+ fn consider_builtin_dyn_upcast_candidates(
+ ecx: &mut EvalCtxt<'_, 'tcx>,
+ goal: Goal<'tcx, Self>,
+ ) -> Vec<CanonicalResponse<'tcx>> {
+ let tcx = ecx.tcx();
+
+ let a_ty = goal.predicate.self_ty();
+ let b_ty = goal.predicate.trait_ref.substs.type_at(1);
+ let ty::Dynamic(a_data, a_region, ty::Dyn) = *a_ty.kind() else {
+ return vec![];
+ };
+ let ty::Dynamic(b_data, b_region, ty::Dyn) = *b_ty.kind() else {
+ return vec![];
+ };
+
+ // All of a's auto traits need to be in b's auto traits.
+ let auto_traits_compatible =
+ b_data.auto_traits().all(|b| a_data.auto_traits().any(|a| a == b));
+ if !auto_traits_compatible {
+ return vec![];
+ }
+
+ let mut unsize_dyn_to_principal = |principal: Option<ty::PolyExistentialTraitRef<'tcx>>| {
+ ecx.probe(|ecx| -> Result<_, NoSolution> {
+ // Require that all of the trait predicates from A match B, except for
+ // the auto traits. We do this by constructing a new A type with B's
+ // auto traits, and equating these types.
+ let new_a_data = principal
+ .into_iter()
+ .map(|trait_ref| trait_ref.map_bound(ty::ExistentialPredicate::Trait))
+ .chain(a_data.iter().filter(|a| {
+ matches!(a.skip_binder(), ty::ExistentialPredicate::Projection(_))
+ }))
+ .chain(
+ b_data
+ .auto_traits()
+ .map(ty::ExistentialPredicate::AutoTrait)
+ .map(ty::Binder::dummy),
+ );
+ let new_a_data = tcx.mk_poly_existential_predicates_from_iter(new_a_data);
+ let new_a_ty = tcx.mk_dynamic(new_a_data, b_region, ty::Dyn);
+
+ // We also require that A's lifetime outlives B's lifetime.
+ let mut nested_obligations = ecx.eq(goal.param_env, new_a_ty, b_ty)?;
+ nested_obligations.push(
+ goal.with(tcx, ty::Binder::dummy(ty::OutlivesPredicate(a_region, b_region))),
+ );
+
+ ecx.evaluate_all_and_make_canonical_response(nested_obligations)
+ })
+ };
+
+ let mut responses = vec![];
+ // If the principal def ids match (or are both none), then we're not doing
+ // trait upcasting. We're just removing auto traits (or shortening the lifetime).
+ if a_data.principal_def_id() == b_data.principal_def_id() {
+ if let Ok(response) = unsize_dyn_to_principal(a_data.principal()) {
+ responses.push(response);
+ }
+ } else if let Some(a_principal) = a_data.principal()
+ && let Some(b_principal) = b_data.principal()
+ {
+ for super_trait_ref in supertraits(tcx, a_principal.with_self_ty(tcx, a_ty)) {
+ if super_trait_ref.def_id() != b_principal.def_id() {
+ continue;
+ }
+ let erased_trait_ref = super_trait_ref
+ .map_bound(|trait_ref| ty::ExistentialTraitRef::erase_self_ty(tcx, trait_ref));
+ if let Ok(response) = unsize_dyn_to_principal(Some(erased_trait_ref)) {
+ responses.push(response);
+ }
+ }
+ }
+
+ responses
+ }
+
+ fn consider_builtin_discriminant_kind_candidate(
+ ecx: &mut EvalCtxt<'_, 'tcx>,
+ _goal: Goal<'tcx, Self>,
+ ) -> QueryResult<'tcx> {
+ // `DiscriminantKind` is automatically implemented for every type.
+ ecx.make_canonical_response(Certainty::Yes)
+ }
}
impl<'tcx> EvalCtxt<'_, 'tcx> {
@@ -195,16 +522,16 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
fn probe_and_evaluate_goal_for_constituent_tys(
&mut self,
goal: Goal<'tcx, TraitPredicate<'tcx>>,
- constituent_tys: impl Fn(&InferCtxt<'tcx>, Ty<'tcx>) -> Result<Vec<Ty<'tcx>>, NoSolution>,
+ constituent_tys: impl Fn(&EvalCtxt<'_, 'tcx>, Ty<'tcx>) -> Result<Vec<Ty<'tcx>>, NoSolution>,
) -> QueryResult<'tcx> {
- self.infcx.probe(|_| {
- self.evaluate_all_and_make_canonical_response(
- constituent_tys(self.infcx, goal.predicate.self_ty())?
+ self.probe(|this| {
+ this.evaluate_all_and_make_canonical_response(
+ constituent_tys(this, goal.predicate.self_ty())?
.into_iter()
.map(|ty| {
goal.with(
- self.tcx(),
- ty::Binder::dummy(goal.predicate.with_self_ty(self.tcx(), ty)),
+ this.tcx(),
+ ty::Binder::dummy(goal.predicate.with_self_ty(this.tcx(), ty)),
)
})
.collect(),
@@ -217,73 +544,6 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
goal: Goal<'tcx, TraitPredicate<'tcx>>,
) -> QueryResult<'tcx> {
let candidates = self.assemble_and_evaluate_candidates(goal);
- self.merge_trait_candidates_discard_reservation_impls(candidates)
- }
-
- #[instrument(level = "debug", skip(self), ret)]
- pub(super) fn merge_trait_candidates_discard_reservation_impls(
- &mut self,
- mut candidates: Vec<Candidate<'tcx>>,
- ) -> QueryResult<'tcx> {
- match candidates.len() {
- 0 => return Err(NoSolution),
- 1 => return Ok(self.discard_reservation_impl(candidates.pop().unwrap()).result),
- _ => {}
- }
-
- if candidates.len() > 1 {
- let mut i = 0;
- 'outer: while i < candidates.len() {
- for j in (0..candidates.len()).filter(|&j| i != j) {
- if self.trait_candidate_should_be_dropped_in_favor_of(
- &candidates[i],
- &candidates[j],
- ) {
- debug!(candidate = ?candidates[i], "Dropping candidate #{}/{}", i, candidates.len());
- candidates.swap_remove(i);
- continue 'outer;
- }
- }
-
- debug!(candidate = ?candidates[i], "Retaining candidate #{}/{}", i, candidates.len());
- // If there are *STILL* multiple candidates, give up
- // and report ambiguity.
- i += 1;
- if i > 1 {
- debug!("multiple matches, ambig");
- // FIXME: return overflow if all candidates overflow, otherwise return ambiguity.
- unimplemented!();
- }
- }
- }
-
- Ok(self.discard_reservation_impl(candidates.pop().unwrap()).result)
- }
-
- fn trait_candidate_should_be_dropped_in_favor_of(
- &self,
- candidate: &Candidate<'tcx>,
- other: &Candidate<'tcx>,
- ) -> bool {
- // FIXME: implement this
- match (candidate.source, other.source) {
- (CandidateSource::Impl(_), _)
- | (CandidateSource::ParamEnv(_), _)
- | (CandidateSource::AliasBound(_), _)
- | (CandidateSource::BuiltinImpl, _) => unimplemented!(),
- }
- }
-
- fn discard_reservation_impl(&self, candidate: Candidate<'tcx>) -> Candidate<'tcx> {
- if let CandidateSource::Impl(def_id) = candidate.source {
- if let ty::ImplPolarity::Reservation = self.tcx().impl_polarity(def_id) {
- debug!("Selected reservation impl");
- // FIXME: reduce candidate to ambiguous
- // FIXME: replace `var_values` with identity, yeet external constraints.
- unimplemented!()
- }
- }
-
- candidate
+ self.merge_candidates_and_discard_reservation_impls(candidates)
}
}
diff --git a/compiler/rustc_trait_selection/src/solve/trait_goals/structural_traits.rs b/compiler/rustc_trait_selection/src/solve/trait_goals/structural_traits.rs
index a11cd13cb..d7d93377c 100644
--- a/compiler/rustc_trait_selection/src/solve/trait_goals/structural_traits.rs
+++ b/compiler/rustc_trait_selection/src/solve/trait_goals/structural_traits.rs
@@ -1,16 +1,19 @@
-use rustc_hir::{Movability, Mutability};
-use rustc_infer::{infer::InferCtxt, traits::query::NoSolution};
-use rustc_middle::ty::{self, Ty, TyCtxt};
+use rustc_data_structures::fx::FxHashMap;
+use rustc_hir::{def_id::DefId, Movability, Mutability};
+use rustc_infer::traits::query::NoSolution;
+use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable};
+
+use crate::solve::EvalCtxt;
// Calculates the constituent types of a type for `auto trait` purposes.
//
// For types with an "existential" binder, i.e. generator witnesses, we also
// instantiate the binder with placeholders eagerly.
pub(super) fn instantiate_constituent_tys_for_auto_trait<'tcx>(
- infcx: &InferCtxt<'tcx>,
+ ecx: &EvalCtxt<'_, 'tcx>,
ty: Ty<'tcx>,
) -> Result<Vec<Ty<'tcx>>, NoSolution> {
- let tcx = infcx.tcx;
+ let tcx = ecx.tcx();
match *ty.kind() {
ty::Uint(_)
| ty::Int(_)
@@ -18,21 +21,24 @@ pub(super) fn instantiate_constituent_tys_for_auto_trait<'tcx>(
| ty::Float(_)
| ty::FnDef(..)
| ty::FnPtr(_)
- | ty::Str
| ty::Error(_)
| ty::Infer(ty::IntVar(_) | ty::FloatVar(_))
| ty::Never
| ty::Char => Ok(vec![]),
- ty::Placeholder(..)
- | ty::Dynamic(..)
+ // Treat this like `struct str([u8]);`
+ ty::Str => Ok(vec![tcx.mk_slice(tcx.types.u8)]),
+
+ ty::Dynamic(..)
| ty::Param(..)
| ty::Foreign(..)
| ty::Alias(ty::Projection, ..)
- | ty::Bound(..)
- | ty::Infer(ty::TyVar(_)) => Err(NoSolution),
+ | ty::Placeholder(..) => Err(NoSolution),
- ty::Infer(ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => bug!(),
+ ty::Bound(..)
+ | ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => {
+ bug!("unexpected type `{ty}`")
+ }
ty::RawPtr(ty::TypeAndMut { ty: element_ty, .. }) | ty::Ref(_, element_ty, _) => {
Ok(vec![element_ty])
@@ -52,9 +58,9 @@ pub(super) fn instantiate_constituent_tys_for_auto_trait<'tcx>(
Ok(vec![generator_substs.tupled_upvars_ty(), generator_substs.witness()])
}
- ty::GeneratorWitness(types) => {
- Ok(infcx.replace_bound_vars_with_placeholders(types).to_vec())
- }
+ ty::GeneratorWitness(types) => Ok(ecx.instantiate_binder_with_placeholders(types).to_vec()),
+
+ ty::GeneratorWitnessMIR(..) => todo!(),
// For `PhantomData<T>`, we pass `T`.
ty::Adt(def, substs) if def.is_phantom_data() => Ok(vec![substs.type_at(0)]),
@@ -65,13 +71,13 @@ pub(super) fn instantiate_constituent_tys_for_auto_trait<'tcx>(
// We can resolve the `impl Trait` to its concrete type,
// which enforces a DAG between the functions requiring
// the auto trait bounds in question.
- Ok(vec![tcx.bound_type_of(def_id).subst(tcx, substs)])
+ Ok(vec![tcx.type_of(def_id).subst(tcx, substs)])
}
}
}
pub(super) fn instantiate_constituent_tys_for_sized_trait<'tcx>(
- infcx: &InferCtxt<'tcx>,
+ ecx: &EvalCtxt<'_, 'tcx>,
ty: Ty<'tcx>,
) -> Result<Vec<Ty<'tcx>>, NoSolution> {
match *ty.kind() {
@@ -87,6 +93,7 @@ pub(super) fn instantiate_constituent_tys_for_sized_trait<'tcx>(
| ty::Ref(..)
| ty::Generator(..)
| ty::GeneratorWitness(..)
+ | ty::GeneratorWitnessMIR(..)
| ty::Array(..)
| ty::Closure(..)
| ty::Never
@@ -99,27 +106,28 @@ pub(super) fn instantiate_constituent_tys_for_sized_trait<'tcx>(
| ty::Foreign(..)
| ty::Alias(..)
| ty::Param(_)
- | ty::Infer(ty::TyVar(_)) => Err(NoSolution),
+ | ty::Placeholder(..) => Err(NoSolution),
- ty::Placeholder(..)
- | ty::Bound(..)
- | ty::Infer(ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => bug!(),
+ ty::Bound(..)
+ | ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => {
+ bug!("unexpected type `{ty}`")
+ }
ty::Tuple(tys) => Ok(tys.to_vec()),
ty::Adt(def, substs) => {
- let sized_crit = def.sized_constraint(infcx.tcx);
+ let sized_crit = def.sized_constraint(ecx.tcx());
Ok(sized_crit
.0
.iter()
- .map(|ty| sized_crit.rebind(*ty).subst(infcx.tcx, substs))
+ .map(|ty| sized_crit.rebind(*ty).subst(ecx.tcx(), substs))
.collect())
}
}
}
pub(super) fn instantiate_constituent_tys_for_copy_clone_trait<'tcx>(
- infcx: &InferCtxt<'tcx>,
+ ecx: &EvalCtxt<'_, 'tcx>,
ty: Ty<'tcx>,
) -> Result<Vec<Ty<'tcx>>, NoSolution> {
match *ty.kind() {
@@ -148,18 +156,19 @@ pub(super) fn instantiate_constituent_tys_for_copy_clone_trait<'tcx>(
| ty::Adt(_, _)
| ty::Alias(_, _)
| ty::Param(_)
- | ty::Infer(ty::TyVar(_)) => Err(NoSolution),
+ | ty::Placeholder(..) => Err(NoSolution),
- ty::Placeholder(..)
- | ty::Bound(..)
- | ty::Infer(ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => bug!(),
+ ty::Bound(..)
+ | ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => {
+ bug!("unexpected type `{ty}`")
+ }
ty::Tuple(tys) => Ok(tys.to_vec()),
ty::Closure(_, substs) => Ok(vec![substs.as_closure().tupled_upvars_ty()]),
ty::Generator(_, substs, Movability::Movable) => {
- if infcx.tcx.features().generator_clone {
+ if ecx.tcx().features().generator_clone {
let generator = substs.as_generator();
Ok(vec![generator.tupled_upvars_ty(), generator.witness()])
} else {
@@ -167,12 +176,13 @@ pub(super) fn instantiate_constituent_tys_for_copy_clone_trait<'tcx>(
}
}
- ty::GeneratorWitness(types) => {
- Ok(infcx.replace_bound_vars_with_placeholders(types).to_vec())
- }
+ ty::GeneratorWitness(types) => Ok(ecx.instantiate_binder_with_placeholders(types).to_vec()),
+
+ ty::GeneratorWitnessMIR(..) => todo!(),
}
}
+// Returns a binder of the tupled inputs types and output type from a builtin callable type.
pub(crate) fn extract_tupled_inputs_and_output_from_callable<'tcx>(
tcx: TyCtxt<'tcx>,
self_ty: Ty<'tcx>,
@@ -180,13 +190,11 @@ pub(crate) fn extract_tupled_inputs_and_output_from_callable<'tcx>(
) -> Result<Option<ty::Binder<'tcx, (Ty<'tcx>, Ty<'tcx>)>>, NoSolution> {
match *self_ty.kind() {
ty::FnDef(def_id, substs) => Ok(Some(
- tcx.bound_fn_sig(def_id)
+ tcx.fn_sig(def_id)
.subst(tcx, substs)
- .map_bound(|sig| (tcx.mk_tup(sig.inputs().iter()), sig.output())),
+ .map_bound(|sig| (tcx.mk_tup(sig.inputs()), sig.output())),
)),
- ty::FnPtr(sig) => {
- Ok(Some(sig.map_bound(|sig| (tcx.mk_tup(sig.inputs().iter()), sig.output()))))
- }
+ ty::FnPtr(sig) => Ok(Some(sig.map_bound(|sig| (tcx.mk_tup(sig.inputs()), sig.output())))),
ty::Closure(_, substs) => {
let closure_substs = substs.as_closure();
match closure_substs.kind_ty().to_opt_closure_kind() {
@@ -211,13 +219,127 @@ pub(crate) fn extract_tupled_inputs_and_output_from_callable<'tcx>(
| ty::Dynamic(_, _, _)
| ty::Generator(_, _, _)
| ty::GeneratorWitness(_)
+ | ty::GeneratorWitnessMIR(..)
| ty::Never
| ty::Tuple(_)
| ty::Alias(_, _)
| ty::Param(_)
- | ty::Placeholder(_)
- | ty::Bound(_, _)
- | ty::Infer(_)
+ | ty::Placeholder(..)
+ | ty::Infer(ty::IntVar(_) | ty::FloatVar(_))
| ty::Error(_) => Err(NoSolution),
+
+ ty::Bound(..)
+ | ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => {
+ bug!("unexpected type `{self_ty}`")
+ }
+ }
+}
+
+/// Assemble a list of predicates that would be present on a theoretical
+/// user impl for an object type. These predicates must be checked any time
+/// we assemble a built-in object candidate for an object type, since they
+/// are not implied by the well-formedness of the type.
+///
+/// For example, given the following traits:
+///
+/// ```rust,ignore (theoretical code)
+/// trait Foo: Baz {
+/// type Bar: Copy;
+/// }
+///
+/// trait Baz {}
+/// ```
+///
+/// For the dyn type `dyn Foo<Item = Ty>`, we can imagine there being a
+/// pair of theoretical impls:
+///
+/// ```rust,ignore (theoretical code)
+/// impl Foo for dyn Foo<Item = Ty>
+/// where
+/// Self: Baz,
+/// <Self as Foo>::Bar: Copy,
+/// {
+/// type Bar = Ty;
+/// }
+///
+/// impl Baz for dyn Foo<Item = Ty> {}
+/// ```
+///
+/// However, in order to make such impls well-formed, we need to do an
+/// additional step of eagerly folding the associated types in the where
+/// clauses of the impl. In this example, that means replacing
+/// `<Self as Foo>::Bar` with `Ty` in the first impl.
+pub(crate) fn predicates_for_object_candidate<'tcx>(
+ ecx: &EvalCtxt<'_, 'tcx>,
+ param_env: ty::ParamEnv<'tcx>,
+ trait_ref: ty::TraitRef<'tcx>,
+ object_bound: &'tcx ty::List<ty::PolyExistentialPredicate<'tcx>>,
+) -> Vec<ty::Predicate<'tcx>> {
+ let tcx = ecx.tcx();
+ let mut requirements = vec![];
+ requirements.extend(
+ tcx.super_predicates_of(trait_ref.def_id).instantiate(tcx, trait_ref.substs).predicates,
+ );
+ for item in tcx.associated_items(trait_ref.def_id).in_definition_order() {
+ // FIXME(associated_const_equality): Also add associated consts to
+ // the requirements here.
+ if item.kind == ty::AssocKind::Type {
+ requirements.extend(tcx.item_bounds(item.def_id).subst(tcx, trait_ref.substs));
+ }
+ }
+
+ let mut replace_projection_with = FxHashMap::default();
+ for bound in object_bound {
+ if let ty::ExistentialPredicate::Projection(proj) = bound.skip_binder() {
+ let proj = proj.with_self_ty(tcx, trait_ref.self_ty());
+ let old_ty = replace_projection_with.insert(proj.def_id(), bound.rebind(proj));
+ assert_eq!(
+ old_ty,
+ None,
+ "{} has two substitutions: {} and {}",
+ proj.projection_ty,
+ proj.term,
+ old_ty.unwrap()
+ );
+ }
+ }
+
+ requirements.fold_with(&mut ReplaceProjectionWith {
+ ecx,
+ param_env,
+ mapping: replace_projection_with,
+ })
+}
+
+struct ReplaceProjectionWith<'a, 'tcx> {
+ ecx: &'a EvalCtxt<'a, 'tcx>,
+ param_env: ty::ParamEnv<'tcx>,
+ mapping: FxHashMap<DefId, ty::PolyProjectionPredicate<'tcx>>,
+}
+
+impl<'tcx> TypeFolder<TyCtxt<'tcx>> for ReplaceProjectionWith<'_, 'tcx> {
+ fn interner(&self) -> TyCtxt<'tcx> {
+ self.ecx.tcx()
+ }
+
+ fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
+ if let ty::Alias(ty::Projection, alias_ty) = *ty.kind()
+ && let Some(replacement) = self.mapping.get(&alias_ty.def_id)
+ {
+ // We may have a case where our object type's projection bound is higher-ranked,
+ // but the where clauses we instantiated are not. We can solve this by instantiating
+ // the binder at the usage site.
+ let proj = self.ecx.instantiate_binder_with_infer(*replacement);
+ // FIXME: Technically this folder could be fallible?
+ let nested = self
+ .ecx
+ .eq(self.param_env, alias_ty, proj.projection_ty)
+ .expect("expected to be able to unify goal projection with dyn's projection");
+ // FIXME: Technically we could register these too..
+ assert!(nested.is_empty(), "did not expect unification to have any nested goals");
+ proj.term.ty().unwrap()
+ } else {
+ ty.super_fold_with(self)
+ }
}
}
diff --git a/compiler/rustc_trait_selection/src/traits/auto_trait.rs b/compiler/rustc_trait_selection/src/traits/auto_trait.rs
index 948632ccc..1fb8659bb 100644
--- a/compiler/rustc_trait_selection/src/traits/auto_trait.rs
+++ b/compiler/rustc_trait_selection/src/traits/auto_trait.rs
@@ -9,7 +9,7 @@ use crate::infer::InferCtxt;
use crate::traits::project::ProjectAndUnifyResult;
use rustc_middle::mir::interpret::ErrorHandled;
use rustc_middle::ty::fold::{TypeFolder, TypeSuperFoldable};
-use rustc_middle::ty::visit::TypeVisitable;
+use rustc_middle::ty::visit::TypeVisitableExt;
use rustc_middle::ty::{ImplPolarity, Region, RegionVid};
use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexSet};
@@ -350,14 +350,14 @@ impl<'tcx> AutoTraitFinder<'tcx> {
)
.map(|o| o.predicate);
new_env = ty::ParamEnv::new(
- tcx.mk_predicates(normalized_preds),
+ tcx.mk_predicates_from_iter(normalized_preds),
param_env.reveal(),
param_env.constness(),
);
}
let final_user_env = ty::ParamEnv::new(
- tcx.mk_predicates(user_computed_preds.into_iter()),
+ tcx.mk_predicates_from_iter(user_computed_preds.into_iter()),
user_env.reveal(),
user_env.constness(),
);
@@ -823,14 +823,18 @@ impl<'tcx> AutoTraitFinder<'tcx> {
_ => return false,
}
}
+
// There's not really much we can do with these predicates -
// we start out with a `ParamEnv` with no inference variables,
// and these don't correspond to adding any new bounds to
// the `ParamEnv`.
ty::PredicateKind::WellFormed(..)
+ | ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(..))
+ | ty::PredicateKind::AliasEq(..)
| ty::PredicateKind::ObjectSafe(..)
| ty::PredicateKind::ClosureKind(..)
| ty::PredicateKind::Subtype(..)
+ // FIXME(generic_const_exprs): you can absolutely add this as a where clauses
| ty::PredicateKind::ConstEvaluatable(..)
| ty::PredicateKind::Coerce(..)
| ty::PredicateKind::TypeWellFormedFromEnv(..) => {}
@@ -855,8 +859,8 @@ pub struct RegionReplacer<'a, 'tcx> {
tcx: TyCtxt<'tcx>,
}
-impl<'a, 'tcx> TypeFolder<'tcx> for RegionReplacer<'a, 'tcx> {
- fn tcx<'b>(&'b self) -> TyCtxt<'tcx> {
+impl<'a, 'tcx> TypeFolder<TyCtxt<'tcx>> for RegionReplacer<'a, 'tcx> {
+ fn interner(&self) -> TyCtxt<'tcx> {
self.tcx
}
diff --git a/compiler/rustc_trait_selection/src/traits/chalk_fulfill.rs b/compiler/rustc_trait_selection/src/traits/chalk_fulfill.rs
index e88950523..b42a49eb4 100644
--- a/compiler/rustc_trait_selection/src/traits/chalk_fulfill.rs
+++ b/compiler/rustc_trait_selection/src/traits/chalk_fulfill.rs
@@ -7,24 +7,18 @@ use crate::traits::{
ChalkEnvironmentAndGoal, FulfillmentError, FulfillmentErrorCode, PredicateObligation,
SelectionError, TraitEngine,
};
-use rustc_data_structures::fx::{FxHashMap, FxIndexSet};
-use rustc_middle::ty::{self, TypeVisitable};
+use rustc_data_structures::fx::FxIndexSet;
+use rustc_middle::ty::TypeVisitableExt;
pub struct FulfillmentContext<'tcx> {
obligations: FxIndexSet<PredicateObligation<'tcx>>,
- relationships: FxHashMap<ty::TyVid, ty::FoundRelationships>,
-
usable_in_snapshot: bool,
}
impl FulfillmentContext<'_> {
pub(super) fn new() -> Self {
- FulfillmentContext {
- obligations: FxIndexSet::default(),
- relationships: FxHashMap::default(),
- usable_in_snapshot: false,
- }
+ FulfillmentContext { obligations: FxIndexSet::default(), usable_in_snapshot: false }
}
pub(crate) fn new_in_snapshot() -> Self {
@@ -43,20 +37,10 @@ impl<'tcx> TraitEngine<'tcx> for FulfillmentContext<'tcx> {
}
let obligation = infcx.resolve_vars_if_possible(obligation);
- super::relationships::update(self, infcx, &obligation);
-
self.obligations.insert(obligation);
}
- fn select_all_or_error(&mut self, infcx: &InferCtxt<'tcx>) -> Vec<FulfillmentError<'tcx>> {
- {
- let errors = self.select_where_possible(infcx);
-
- if !errors.is_empty() {
- return errors;
- }
- }
-
+ fn collect_remaining_errors(&mut self) -> Vec<FulfillmentError<'tcx>> {
// any remaining obligations are errors
self.obligations
.iter()
@@ -151,11 +135,14 @@ impl<'tcx> TraitEngine<'tcx> for FulfillmentContext<'tcx> {
errors
}
- fn pending_obligations(&self) -> Vec<PredicateObligation<'tcx>> {
- self.obligations.iter().cloned().collect()
+ fn drain_unstalled_obligations(
+ &mut self,
+ _: &InferCtxt<'tcx>,
+ ) -> Vec<PredicateObligation<'tcx>> {
+ unimplemented!()
}
- fn relationships(&mut self) -> &mut FxHashMap<ty::TyVid, ty::FoundRelationships> {
- &mut self.relationships
+ fn pending_obligations(&self) -> Vec<PredicateObligation<'tcx>> {
+ self.obligations.iter().cloned().collect()
}
}
diff --git a/compiler/rustc_trait_selection/src/traits/coherence.rs b/compiler/rustc_trait_selection/src/traits/coherence.rs
index 225c1050c..6b688c322 100644
--- a/compiler/rustc_trait_selection/src/traits/coherence.rs
+++ b/compiler/rustc_trait_selection/src/traits/coherence.rs
@@ -17,12 +17,11 @@ use crate::traits::{
use rustc_data_structures::fx::FxIndexSet;
use rustc_errors::Diagnostic;
use rustc_hir::def_id::{DefId, CRATE_DEF_ID, LOCAL_CRATE};
-use rustc_hir::CRATE_HIR_ID;
use rustc_infer::infer::{DefiningAnchor, InferCtxt, TyCtxtInferExt};
use rustc_infer::traits::util;
use rustc_middle::traits::specialization_graph::OverlapMode;
use rustc_middle::ty::fast_reject::{DeepRejectCtxt, TreatParams};
-use rustc_middle::ty::visit::TypeVisitable;
+use rustc_middle::ty::visit::{TypeVisitable, TypeVisitableExt};
use rustc_middle::ty::{self, ImplSubject, Ty, TyCtxt, TypeVisitor};
use rustc_span::symbol::sym;
use rustc_span::DUMMY_SP;
@@ -83,8 +82,8 @@ pub fn overlapping_impls(
(Some(a), Some(b)) => iter::zip(a.skip_binder().substs, b.skip_binder().substs)
.all(|(arg1, arg2)| drcx.generic_args_may_unify(arg1, arg2)),
(None, None) => {
- let self_ty1 = tcx.type_of(impl1_def_id);
- let self_ty2 = tcx.type_of(impl2_def_id);
+ let self_ty1 = tcx.type_of(impl1_def_id).skip_binder();
+ let self_ty2 = tcx.type_of(impl2_def_id).skip_binder();
drcx.types_may_unify(self_ty1, self_ty2)
}
_ => bug!("unexpected impls: {impl1_def_id:?} {impl2_def_id:?}"),
@@ -125,7 +124,7 @@ fn with_fresh_ty_vars<'cx, 'tcx>(
let header = ty::ImplHeader {
impl_def_id,
- self_ty: tcx.bound_type_of(impl_def_id).subst(tcx, impl_substs),
+ self_ty: tcx.type_of(impl_def_id).subst(tcx, impl_substs),
trait_ref: tcx.impl_trait_ref(impl_def_id).map(|i| i.subst(tcx, impl_substs)),
predicates: tcx.predicates_of(impl_def_id).instantiate(tcx, impl_substs).predicates,
};
@@ -218,6 +217,7 @@ fn equate_impl_headers<'cx, 'tcx>(
selcx
.infcx
.at(&ObligationCause::dummy(), ty::ParamEnv::empty())
+ .define_opaque_types(true)
.eq_impl_headers(impl1_header, impl2_header)
.map(|infer_ok| infer_ok.obligations)
.ok()
@@ -382,18 +382,14 @@ fn resolve_negative_obligation<'tcx>(
return false;
}
- let (body_id, body_def_id) = if let Some(body_def_id) = body_def_id.as_local() {
- (tcx.hir().local_def_id_to_hir_id(body_def_id), body_def_id)
- } else {
- (CRATE_HIR_ID, CRATE_DEF_ID)
- };
+ let body_def_id = body_def_id.as_local().unwrap_or(CRATE_DEF_ID);
let ocx = ObligationCtxt::new(&infcx);
let wf_tys = ocx.assumed_wf_types(param_env, DUMMY_SP, body_def_id);
let outlives_env = OutlivesEnvironment::with_bounds(
param_env,
Some(&infcx),
- infcx.implied_bounds_tys(param_env, body_id, wf_tys),
+ infcx.implied_bounds_tys(param_env, body_def_id, wf_tys),
);
infcx.process_registered_region_obligations(outlives_env.region_bound_pairs(), param_env);
@@ -632,7 +628,7 @@ enum OrphanCheckEarlyExit<'tcx> {
LocalTy(Ty<'tcx>),
}
-impl<'tcx> TypeVisitor<'tcx> for OrphanChecker<'tcx> {
+impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for OrphanChecker<'tcx> {
type BreakTy = OrphanCheckEarlyExit<'tcx>;
fn visit_region(&mut self, _r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> {
ControlFlow::Continue(())
@@ -701,7 +697,9 @@ impl<'tcx> TypeVisitor<'tcx> for OrphanChecker<'tcx> {
// This should only be created when checking whether we have to check whether some
// auto trait impl applies. There will never be multiple impls, so we can just
// act as if it were a local type here.
- ty::GeneratorWitness(_) => ControlFlow::Break(OrphanCheckEarlyExit::LocalTy(ty)),
+ ty::GeneratorWitness(_) | ty::GeneratorWitnessMIR(..) => {
+ ControlFlow::Break(OrphanCheckEarlyExit::LocalTy(ty))
+ }
ty::Alias(ty::Opaque, ..) => {
// This merits some explanation.
// Normally, opaque types are not involved when performing
diff --git a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs
index f779d9dd8..345e84990 100644
--- a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs
+++ b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs
@@ -14,7 +14,7 @@ use rustc_middle::mir::interpret::ErrorHandled;
use rustc_middle::traits::ObligationCause;
use rustc_middle::ty::abstract_const::NotConstEvaluatable;
-use rustc_middle::ty::{self, TyCtxt, TypeVisitable, TypeVisitor};
+use rustc_middle::ty::{self, TyCtxt, TypeVisitable, TypeVisitableExt, TypeVisitor};
use rustc_span::Span;
use std::ops::ControlFlow;
@@ -171,7 +171,7 @@ fn satisfied_from_param_env<'tcx>(
single_match: Option<Result<ty::Const<'tcx>, ()>>,
}
- impl<'a, 'tcx> TypeVisitor<'tcx> for Visitor<'a, 'tcx> {
+ impl<'a, 'tcx> TypeVisitor<TyCtxt<'tcx>> for Visitor<'a, 'tcx> {
type BreakTy = ();
fn visit_const(&mut self, c: ty::Const<'tcx>) -> ControlFlow<Self::BreakTy> {
debug!("is_const_evaluatable: candidate={:?}", c);
@@ -219,7 +219,7 @@ fn satisfied_from_param_env<'tcx>(
}
if let Some(Ok(c)) = single_match {
- let ocx = ObligationCtxt::new(infcx);
+ let ocx = ObligationCtxt::new_in_snapshot(infcx);
assert!(ocx.eq(&ObligationCause::dummy(), param_env, c.ty(), ct.ty()).is_ok());
assert!(ocx.eq(&ObligationCause::dummy(), param_env, c, ct).is_ok());
assert!(ocx.select_all_or_error().is_empty());
diff --git a/compiler/rustc_trait_selection/src/traits/engine.rs b/compiler/rustc_trait_selection/src/traits/engine.rs
index 369f80139..b20636174 100644
--- a/compiler/rustc_trait_selection/src/traits/engine.rs
+++ b/compiler/rustc_trait_selection/src/traits/engine.rs
@@ -104,7 +104,7 @@ impl<'a, 'tcx> ObligationCtxt<'a, 'tcx> {
});
}
- pub fn normalize<T: TypeFoldable<'tcx>>(
+ pub fn normalize<T: TypeFoldable<TyCtxt<'tcx>>>(
&self,
cause: &ObligationCause<'tcx>,
param_env: ty::ParamEnv<'tcx>,
@@ -128,6 +128,7 @@ impl<'a, 'tcx> ObligationCtxt<'a, 'tcx> {
{
self.infcx
.at(cause, param_env)
+ .define_opaque_types(true)
.eq_exp(a_is_expected, a, b)
.map(|infer_ok| self.register_infer_ok_obligations(infer_ok))
}
@@ -141,6 +142,7 @@ impl<'a, 'tcx> ObligationCtxt<'a, 'tcx> {
) -> Result<(), TypeError<'tcx>> {
self.infcx
.at(cause, param_env)
+ .define_opaque_types(true)
.eq(expected, actual)
.map(|infer_ok| self.register_infer_ok_obligations(infer_ok))
}
@@ -155,6 +157,7 @@ impl<'a, 'tcx> ObligationCtxt<'a, 'tcx> {
) -> Result<(), TypeError<'tcx>> {
self.infcx
.at(cause, param_env)
+ .define_opaque_types(true)
.sup(expected, actual)
.map(|infer_ok| self.register_infer_ok_obligations(infer_ok))
}
@@ -169,6 +172,7 @@ impl<'a, 'tcx> ObligationCtxt<'a, 'tcx> {
) -> Result<(), TypeError<'tcx>> {
self.infcx
.at(cause, param_env)
+ .define_opaque_types(true)
.sup(expected, actual)
.map(|infer_ok| self.register_infer_ok_obligations(infer_ok))
}
@@ -190,8 +194,7 @@ impl<'a, 'tcx> ObligationCtxt<'a, 'tcx> {
let tcx = self.infcx.tcx;
let assumed_wf_types = tcx.assumed_wf_types(def_id);
let mut implied_bounds = FxIndexSet::default();
- let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
- let cause = ObligationCause::misc(span, hir_id);
+ let cause = ObligationCause::misc(span, def_id);
for ty in assumed_wf_types {
// FIXME(@lcnr): rustc currently does not check wf for types
// pre-normalization, meaning that implied bounds are sometimes
@@ -217,7 +220,7 @@ impl<'a, 'tcx> ObligationCtxt<'a, 'tcx> {
answer: T,
) -> Fallible<CanonicalQueryResponse<'tcx, T>>
where
- T: Debug + TypeFoldable<'tcx>,
+ T: Debug + TypeFoldable<TyCtxt<'tcx>>,
Canonical<'tcx, QueryResponse<'tcx, T>>: ArenaAllocatable<'tcx>,
{
self.infcx.make_canonicalized_query_response(
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/ambiguity.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/ambiguity.rs
index 0419bb3f7..84045c4d0 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/ambiguity.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/ambiguity.rs
@@ -22,7 +22,7 @@ pub fn recompute_applicable_impls<'tcx>(
let impl_may_apply = |impl_def_id| {
let ocx = ObligationCtxt::new_in_snapshot(infcx);
let placeholder_obligation =
- infcx.replace_bound_vars_with_placeholders(obligation.predicate);
+ infcx.instantiate_binder_with_placeholders(obligation.predicate);
let obligation_trait_ref =
ocx.normalize(&ObligationCause::dummy(), param_env, placeholder_obligation.trait_ref);
@@ -47,11 +47,11 @@ pub fn recompute_applicable_impls<'tcx>(
let param_env_candidate_may_apply = |poly_trait_predicate: ty::PolyTraitPredicate<'tcx>| {
let ocx = ObligationCtxt::new_in_snapshot(infcx);
let placeholder_obligation =
- infcx.replace_bound_vars_with_placeholders(obligation.predicate);
+ infcx.instantiate_binder_with_placeholders(obligation.predicate);
let obligation_trait_ref =
ocx.normalize(&ObligationCause::dummy(), param_env, placeholder_obligation.trait_ref);
- let param_env_predicate = infcx.replace_bound_vars_with_fresh_vars(
+ let param_env_predicate = infcx.instantiate_binder_with_fresh_vars(
DUMMY_SP,
LateBoundRegionConversionTime::HigherRankedType,
poly_trait_predicate,
@@ -81,7 +81,7 @@ pub fn recompute_applicable_impls<'tcx>(
);
let predicates =
- tcx.predicates_of(obligation.cause.body_id.owner.to_def_id()).instantiate_identity(tcx);
+ tcx.predicates_of(obligation.cause.body_id.to_def_id()).instantiate_identity(tcx);
for obligation in elaborate_predicates_with_span(tcx, predicates.into_iter()) {
let kind = obligation.predicate.kind();
if let ty::PredicateKind::Clause(ty::Clause::Trait(trait_pred)) = kind.skip_binder()
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/method_chain.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/method_chain.rs
index ba9ee57d4..1174efdbf 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/method_chain.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/method_chain.rs
@@ -1,5 +1,7 @@
use crate::infer::InferCtxt;
+use rustc_infer::infer::ObligationEmittingRelation;
+use rustc_infer::traits::PredicateObligations;
use rustc_middle::ty::error::TypeError;
use rustc_middle::ty::relate::{self, Relate, RelateResult, TypeRelation};
use rustc_middle::ty::{self, Ty, TyCtxt};
@@ -88,3 +90,16 @@ impl<'a, 'tcx> TypeRelation<'tcx> for CollectAllMismatches<'a, 'tcx> {
Ok(a.rebind(self.relate(a.skip_binder(), b.skip_binder())?))
}
}
+
+impl<'tcx> ObligationEmittingRelation<'tcx> for CollectAllMismatches<'_, 'tcx> {
+ fn register_obligations(&mut self, _obligations: PredicateObligations<'tcx>) {
+ // FIXME(deferred_projection_equality)
+ }
+
+ fn register_predicates(
+ &mut self,
+ _obligations: impl IntoIterator<Item: ty::ToPredicate<'tcx>>,
+ ) {
+ // FIXME(deferred_projection_equality)
+ }
+}
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 52971486c..a844a1494 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
@@ -38,7 +38,7 @@ use rustc_middle::ty::fold::{TypeFolder, TypeSuperFoldable};
use rustc_middle::ty::print::{with_forced_trimmed_paths, FmtPrinter, Print};
use rustc_middle::ty::{
self, SubtypePredicate, ToPolyTraitRef, ToPredicate, TraitRef, Ty, TyCtxt, TypeFoldable,
- TypeVisitable,
+ TypeVisitable, TypeVisitableExt,
};
use rustc_session::config::TraitSolver;
use rustc_session::Limit;
@@ -101,6 +101,18 @@ pub trait InferCtxtExt<'tcx> {
}
pub trait TypeErrCtxtExt<'tcx> {
+ fn build_overflow_error<T>(
+ &self,
+ predicate: &T,
+ span: Span,
+ suggest_increasing_limit: bool,
+ ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed>
+ where
+ T: fmt::Display
+ + TypeFoldable<TyCtxt<'tcx>>
+ + Print<'tcx, FmtPrinter<'tcx, 'tcx>, Output = FmtPrinter<'tcx, 'tcx>>,
+ <T as Print<'tcx, FmtPrinter<'tcx, 'tcx>>>::Error: std::fmt::Debug;
+
fn report_overflow_error<T>(
&self,
predicate: &T,
@@ -110,7 +122,7 @@ pub trait TypeErrCtxtExt<'tcx> {
) -> !
where
T: fmt::Display
- + TypeFoldable<'tcx>
+ + TypeFoldable<TyCtxt<'tcx>>
+ Print<'tcx, FmtPrinter<'tcx, 'tcx>, Output = FmtPrinter<'tcx, 'tcx>>,
<T as Print<'tcx, FmtPrinter<'tcx, 'tcx>>>::Error: std::fmt::Debug;
@@ -480,7 +492,27 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
) -> !
where
T: fmt::Display
- + TypeFoldable<'tcx>
+ + TypeFoldable<TyCtxt<'tcx>>
+ + Print<'tcx, FmtPrinter<'tcx, 'tcx>, Output = FmtPrinter<'tcx, 'tcx>>,
+ <T as Print<'tcx, FmtPrinter<'tcx, 'tcx>>>::Error: std::fmt::Debug,
+ {
+ let mut err = self.build_overflow_error(predicate, span, suggest_increasing_limit);
+ mutate(&mut err);
+ err.emit();
+
+ self.tcx.sess.abort_if_errors();
+ bug!();
+ }
+
+ fn build_overflow_error<T>(
+ &self,
+ predicate: &T,
+ span: Span,
+ suggest_increasing_limit: bool,
+ ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed>
+ where
+ T: fmt::Display
+ + TypeFoldable<TyCtxt<'tcx>>
+ Print<'tcx, FmtPrinter<'tcx, 'tcx>, Output = FmtPrinter<'tcx, 'tcx>>,
<T as Print<'tcx, FmtPrinter<'tcx, 'tcx>>>::Error: std::fmt::Debug,
{
@@ -511,11 +543,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
self.suggest_new_overflow_limit(&mut err);
}
- mutate(&mut err);
-
- err.emit();
- self.tcx.sess.abort_if_errors();
- bug!();
+ err
}
/// Reports that an overflow has occurred and halts compilation. We
@@ -839,14 +867,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
err.note(s.as_str());
}
if let Some(ref s) = parent_label {
- let body = tcx
- .hir()
- .opt_local_def_id(obligation.cause.body_id)
- .unwrap_or_else(|| {
- tcx.hir().body_owner_def_id(hir::BodyId {
- hir_id: obligation.cause.body_id,
- })
- });
+ let body = obligation.cause.body_id;
err.span_label(tcx.def_span(body), s);
}
@@ -934,6 +955,8 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
);
}
+ let body_hir_id =
+ self.tcx.hir().local_def_id_to_hir_id(obligation.cause.body_id);
// Try to report a help message
if is_fn_trait
&& let Ok((implemented_kind, params)) = self.type_implements_fn_trait(
@@ -1014,7 +1037,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
if !self.report_similar_impl_candidates(
impl_candidates,
trait_ref,
- obligation.cause.body_id,
+ body_hir_id,
&mut err,
true,
) {
@@ -1050,7 +1073,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
self.report_similar_impl_candidates(
impl_candidates,
trait_ref,
- obligation.cause.body_id,
+ body_hir_id,
&mut err,
true,
);
@@ -1207,20 +1230,23 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
}
ty::PredicateKind::WellFormed(ty) => {
- if self.tcx.sess.opts.unstable_opts.trait_solver == TraitSolver::Classic {
- // WF predicates cannot themselves make
- // errors. They can only block due to
- // ambiguity; otherwise, they always
- // degenerate into other obligations
- // (which may fail).
- span_bug!(span, "WF predicate not satisfied for {:?}", ty);
- } else {
- // FIXME: we'll need a better message which takes into account
- // which bounds actually failed to hold.
- self.tcx.sess.struct_span_err(
- span,
- &format!("the type `{}` is not well-formed", ty),
- )
+ match self.tcx.sess.opts.unstable_opts.trait_solver {
+ TraitSolver::Classic => {
+ // WF predicates cannot themselves make
+ // errors. They can only block due to
+ // ambiguity; otherwise, they always
+ // degenerate into other obligations
+ // (which may fail).
+ span_bug!(span, "WF predicate not satisfied for {:?}", ty);
+ }
+ TraitSolver::Chalk | TraitSolver::Next => {
+ // FIXME: we'll need a better message which takes into account
+ // which bounds actually failed to hold.
+ self.tcx.sess.struct_span_err(
+ span,
+ &format!("the type `{}` is not well-formed", ty),
+ )
+ }
}
}
@@ -1252,6 +1278,18 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
span,
"TypeWellFormedFromEnv predicate should only exist in the environment"
),
+
+ ty::PredicateKind::AliasEq(..) => span_bug!(
+ span,
+ "AliasEq predicate should never be the predicate cause of a SelectionError"
+ ),
+
+ ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(ct, ty)) => {
+ self.tcx.sess.struct_span_err(
+ span,
+ &format!("the constant `{}` is not of type `{}`", ct, ty),
+ )
+ }
}
}
@@ -1598,7 +1636,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
// Eventually I'll need to implement param-env-aware
// `Γ₁ ⊦ φ₁ => Γ₂ ⊦ φ₂` logic.
let param_env = ty::ParamEnv::empty();
- if self.can_sub(param_env, error, implication).is_ok() {
+ if self.can_sub(param_env, error, implication) {
debug!("error_implies: {:?} -> {:?} -> {:?}", cond, error, implication);
return true;
}
@@ -1690,7 +1728,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
let (values, err) = if let ty::PredicateKind::Clause(ty::Clause::Projection(data)) =
bound_predicate.skip_binder()
{
- let data = self.replace_bound_vars_with_fresh_vars(
+ let data = self.instantiate_binder_with_fresh_vars(
obligation.cause.span,
infer::LateBoundRegionConversionTime::HigherRankedType,
bound_predicate.rebind(data),
@@ -1843,10 +1881,14 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
with_forced_trimmed_paths! {
if Some(pred.projection_ty.def_id) == self.tcx.lang_items().fn_once_output() {
+ let fn_kind = self_ty.prefix_string(self.tcx);
+ let item = match self_ty.kind() {
+ ty::FnDef(def, _) => self.tcx.item_name(*def).to_string(),
+ _ => self_ty.to_string(),
+ };
Some(format!(
- "expected `{self_ty}` to be a {fn_kind} that returns `{expected_ty}`, but it \
+ "expected `{item}` to be a {fn_kind} that returns `{expected_ty}`, but it \
returns `{normalized_ty}`",
- fn_kind = self_ty.prefix_string(self.tcx)
))
} else if Some(trait_def_id) == self.tcx.lang_items().future_trait() {
Some(format!(
@@ -1896,6 +1938,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
ty::Generator(..) => Some(16),
ty::Foreign(..) => Some(17),
ty::GeneratorWitness(..) => Some(18),
+ ty::GeneratorWitnessMIR(..) => Some(19),
ty::Placeholder(..) | ty::Bound(..) | ty::Infer(..) | ty::Error(_) => None,
}
}
@@ -2062,7 +2105,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
// Ignore automatically derived impls and `!Trait` impls.
.filter(|&def_id| {
self.tcx.impl_polarity(def_id) != ty::ImplPolarity::Negative
- || self.tcx.is_builtin_derive(def_id)
+ || self.tcx.is_automatically_derived(def_id)
})
.filter_map(|def_id| self.tcx.impl_trait_ref(def_id))
.map(ty::EarlyBinder::subst_identity)
@@ -2305,10 +2348,12 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
predicate.to_opt_poly_trait_pred().unwrap(),
);
if impl_candidates.len() < 10 {
+ let hir =
+ self.tcx.hir().local_def_id_to_hir_id(obligation.cause.body_id);
self.report_similar_impl_candidates(
impl_candidates,
trait_ref,
- body_id.map(|id| id.hir_id).unwrap_or(obligation.cause.body_id),
+ body_id.map(|id| id.hir_id).unwrap_or(hir),
&mut err,
false,
);
@@ -2395,7 +2440,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
};
let mut suggestions = vec![(
path.span.shrink_to_lo(),
- format!("<{} as ", self.tcx.type_of(impl_def_id))
+ format!("<{} as ", self.tcx.type_of(impl_def_id).subst_identity())
)];
if let Some(generic_arg) = trait_path_segment.args {
let between_span = trait_path_segment.ident.span.between(generic_arg.span_ext);
@@ -2637,8 +2682,8 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
var_map: FxHashMap<Ty<'tcx>, Ty<'tcx>>,
}
- impl<'a, 'tcx> TypeFolder<'tcx> for ParamToVarFolder<'a, 'tcx> {
- fn tcx<'b>(&'b self) -> TyCtxt<'tcx> {
+ impl<'a, 'tcx> TypeFolder<TyCtxt<'tcx>> for ParamToVarFolder<'a, 'tcx> {
+ fn interner(&self) -> TyCtxt<'tcx> {
self.infcx.tcx
}
@@ -2828,7 +2873,7 @@ pub struct FindExprBySpan<'hir> {
}
impl<'hir> FindExprBySpan<'hir> {
- fn new(span: Span) -> Self {
+ pub fn new(span: Span) -> Self {
Self { span, result: None, ty_result: None }
}
}
@@ -2926,7 +2971,7 @@ impl ArgKind {
struct HasNumericInferVisitor;
-impl<'tcx> ty::TypeVisitor<'tcx> for HasNumericInferVisitor {
+impl<'tcx> ty::TypeVisitor<TyCtxt<'tcx>> for HasNumericInferVisitor {
type BreakTy = ();
fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
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 18d308f71..b3bf9ad59 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
@@ -60,7 +60,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
) -> Option<(DefId, SubstsRef<'tcx>)> {
let tcx = self.tcx;
let param_env = obligation.param_env;
- let trait_ref = tcx.erase_late_bound_regions(trait_ref);
+ let trait_ref = self.instantiate_binder_with_placeholders(trait_ref);
let trait_self_ty = trait_ref.self_ty();
let mut self_match_impls = vec![];
@@ -72,7 +72,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
let impl_self_ty = impl_trait_ref.self_ty();
- if let Ok(..) = self.can_eq(param_env, trait_self_ty, impl_self_ty) {
+ if self.can_eq(param_env, trait_self_ty, impl_self_ty) {
self_match_impls.push((def_id, impl_substs));
if iter::zip(
@@ -149,10 +149,9 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
.unwrap_or_else(|| (trait_ref.def_id(), trait_ref.skip_binder().substs));
let trait_ref = trait_ref.skip_binder();
- let mut flags = vec![(
- sym::ItemContext,
- self.describe_enclosure(obligation.cause.body_id).map(|s| s.to_owned()),
- )];
+ let body_hir = self.tcx.hir().local_def_id_to_hir_id(obligation.cause.body_id);
+ let mut flags =
+ vec![(sym::ItemContext, self.describe_enclosure(body_hir).map(|s| s.to_owned()))];
match obligation.cause.code() {
ObligationCauseCode::BuiltinDerivedObligation(..)
@@ -201,7 +200,10 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
if let Some(def) = self_ty.ty_adt_def() {
// We also want to be able to select self's original
// signature with no type arguments resolved
- flags.push((sym::_Self, Some(self.tcx.type_of(def.did()).to_string())));
+ flags.push((
+ sym::_Self,
+ Some(self.tcx.type_of(def.did()).subst_identity().to_string()),
+ ));
}
for param in generics.params.iter() {
@@ -219,7 +221,10 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
if let Some(def) = param_ty.ty_adt_def() {
// We also want to be able to select the parameter's
// original signature with no type arguments resolved
- flags.push((name, Some(self.tcx.type_of(def.did()).to_string())));
+ flags.push((
+ name,
+ Some(self.tcx.type_of(def.did()).subst_identity().to_string()),
+ ));
}
}
}
@@ -252,7 +257,10 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
if let Some(def) = aty.ty_adt_def() {
// We also want to be able to select the slice's type's original
// signature with no type arguments resolved
- flags.push((sym::_Self, Some(format!("[{}]", self.tcx.type_of(def.did())))));
+ flags.push((
+ sym::_Self,
+ Some(format!("[{}]", self.tcx.type_of(def.did()).subst_identity())),
+ ));
}
if aty.is_integral() {
flags.push((sym::_Self, Some("[{integral}]".to_string())));
@@ -262,7 +270,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
// Arrays give us `[]`, `[{ty}; _]` and `[{ty}; N]`
if let ty::Array(aty, len) = self_ty.kind() {
flags.push((sym::_Self, Some("[]".to_string())));
- let len = len.kind().try_to_value().and_then(|v| v.try_to_machine_usize(self.tcx));
+ let len = len.kind().try_to_value().and_then(|v| v.try_to_target_usize(self.tcx));
flags.push((sym::_Self, Some(format!("[{}; _]", aty))));
if let Some(n) = len {
flags.push((sym::_Self, Some(format!("[{}; {}]", aty, n))));
@@ -270,7 +278,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
if let Some(def) = aty.ty_adt_def() {
// We also want to be able to select the array's type's original
// signature with no type arguments resolved
- let def_ty = self.tcx.type_of(def.did());
+ let def_ty = self.tcx.type_of(def.did()).subst_identity();
flags.push((sym::_Self, Some(format!("[{def_ty}; _]"))));
if let Some(n) = len {
flags.push((sym::_Self, Some(format!("[{def_ty}; {n}]"))));
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 39e50b2ac..66d74fd05 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,6 @@ use crate::infer::InferCtxt;
use crate::traits::{NormalizeExt, ObligationCtxt};
use hir::def::CtorOf;
-use hir::{Expr, HirId};
use rustc_data_structures::fx::FxHashSet;
use rustc_data_structures::stack::ensure_sufficient_stack;
use rustc_errors::{
@@ -20,8 +19,10 @@ use rustc_hir as hir;
use rustc_hir::def::DefKind;
use rustc_hir::def_id::DefId;
use rustc_hir::intravisit::Visitor;
+use rustc_hir::is_range_literal;
use rustc_hir::lang_items::LangItem;
use rustc_hir::{AsyncGeneratorKind, GeneratorKind, Node};
+use rustc_hir::{Expr, HirId};
use rustc_infer::infer::error_reporting::TypeErrCtxt;
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
use rustc_infer::infer::{InferOk, LateBoundRegionConversionTime};
@@ -32,8 +33,9 @@ use rustc_middle::ty::{
self, suggest_arbitrary_trait_bound, suggest_constraining_type_param, AdtKind, DefIdTree,
GeneratorDiagnosticData, GeneratorInteriorTypeCause, Infer, InferTy, InternalSubsts,
IsSuggestable, ToPredicate, Ty, TyCtxt, TypeAndMut, TypeFoldable, TypeFolder,
- TypeSuperFoldable, TypeVisitable, TypeckResults,
+ TypeSuperFoldable, TypeVisitableExt, TypeckResults,
};
+use rustc_span::def_id::LocalDefId;
use rustc_span::symbol::{sym, Ident, Symbol};
use rustc_span::{BytePos, DesugaringKind, ExpnKind, MacroKind, Span, DUMMY_SP};
use rustc_target::spec::abi;
@@ -80,11 +82,8 @@ impl<'tcx, 'a> GeneratorData<'tcx, 'a> {
upvars.iter().find_map(|(upvar_id, upvar)| {
let upvar_ty = typeck_results.node_type(*upvar_id);
let upvar_ty = infer_context.resolve_vars_if_possible(upvar_ty);
- if ty_matches(ty::Binder::dummy(upvar_ty)) {
- Some(GeneratorInteriorOrUpvar::Upvar(upvar.span))
- } else {
- None
- }
+ ty_matches(ty::Binder::dummy(upvar_ty))
+ .then(|| GeneratorInteriorOrUpvar::Upvar(upvar.span))
})
})
}
@@ -97,6 +96,7 @@ impl<'tcx, 'a> GeneratorData<'tcx, 'a> {
// obligation
fn get_from_await_ty<F>(
&self,
+ tcx: TyCtxt<'tcx>,
visitor: AwaitsVisitor,
hir: map::Map<'tcx>,
ty_matches: F,
@@ -132,10 +132,8 @@ impl<'tcx, 'a> GeneratorData<'tcx, 'a> {
.cloned()
.unwrap_or_else(|| {
bug!(
- "node_type: no type for node `{}`",
- ty::tls::with(|tcx| tcx
- .hir()
- .node_to_string(await_expr.hir_id))
+ "node_type: no type for node {}",
+ tcx.hir().node_to_string(await_expr.hir_id)
)
})
},
@@ -179,7 +177,7 @@ pub trait TypeErrCtxtExt<'tcx> {
err: &mut Diagnostic,
trait_pred: ty::PolyTraitPredicate<'tcx>,
associated_item: Option<(&'static str, Ty<'tcx>)>,
- body_id: hir::HirId,
+ body_id: LocalDefId,
);
fn suggest_dereferences(
@@ -398,7 +396,7 @@ fn predicate_constraint(generics: &hir::Generics<'_>, pred: ty::Predicate<'_>) -
/// param for cleaner code.
fn suggest_restriction<'tcx>(
tcx: TyCtxt<'tcx>,
- hir_id: HirId,
+ item_id: LocalDefId,
hir_generics: &hir::Generics<'tcx>,
msg: &str,
err: &mut Diagnostic,
@@ -417,7 +415,6 @@ fn suggest_restriction<'tcx>(
{
return;
}
- let Some(item_id) = hir_id.as_owner() else { return; };
let generics = tcx.generics_of(item_id);
// Given `fn foo(t: impl Trait)` where `Trait` requires assoc type `A`...
if let Some((param, bound_str, fn_sig)) =
@@ -522,7 +519,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
mut err: &mut Diagnostic,
trait_pred: ty::PolyTraitPredicate<'tcx>,
associated_ty: Option<(&'static str, Ty<'tcx>)>,
- body_id: hir::HirId,
+ mut body_id: LocalDefId,
) {
let trait_pred = self.resolve_numeric_literals_with_default(trait_pred);
@@ -535,8 +532,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
// FIXME: Add check for trait bound that is already present, particularly `?Sized` so we
// don't suggest `T: Sized + ?Sized`.
- let mut hir_id = body_id;
- while let Some(node) = self.tcx.hir().find(hir_id) {
+ while let Some(node) = self.tcx.hir().find_by_def_id(body_id) {
match node {
hir::Node::Item(hir::Item {
ident,
@@ -547,7 +543,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
// Restricting `Self` for a single method.
suggest_restriction(
self.tcx,
- hir_id,
+ body_id,
&generics,
"`Self`",
err,
@@ -567,7 +563,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
assert!(param_ty);
// Restricting `Self` for a single method.
suggest_restriction(
- self.tcx, hir_id, &generics, "`Self`", err, None, projection, trait_pred,
+ self.tcx, body_id, &generics, "`Self`", err, None, projection, trait_pred,
None,
);
return;
@@ -589,7 +585,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
// Missing restriction on associated type of type parameter (unmet projection).
suggest_restriction(
self.tcx,
- hir_id,
+ body_id,
&generics,
"the associated type",
err,
@@ -609,7 +605,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
// Missing restriction on associated type of type parameter (unmet projection).
suggest_restriction(
self.tcx,
- hir_id,
+ body_id,
&generics,
"the associated type",
err,
@@ -680,6 +676,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
&param_name,
&constraint,
Some(trait_pred.def_id()),
+ None,
) {
return;
}
@@ -713,8 +710,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
_ => {}
}
-
- hir_id = self.tcx.hir().get_parent_item(hir_id).into();
+ body_id = self.tcx.local_parent(body_id);
}
}
@@ -749,10 +745,11 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
let real_ty = real_trait_pred.self_ty();
// We `erase_late_bound_regions` here because `make_subregion` does not handle
// `ReLateBound`, and we don't particularly care about the regions.
- if self
- .can_eq(obligation.param_env, self.tcx.erase_late_bound_regions(real_ty), arg_ty)
- .is_err()
- {
+ if !self.can_eq(
+ obligation.param_env,
+ self.tcx.erase_late_bound_regions(real_ty),
+ arg_ty,
+ ) {
continue;
}
@@ -770,15 +767,13 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
obligation.param_env,
real_trait_pred_and_ty,
);
- if obligations
+ let may_hold = obligations
.iter()
.chain([&obligation])
.all(|obligation| self.predicate_may_hold(obligation))
- {
- Some(steps)
- } else {
- None
- }
+ .then_some(steps);
+
+ may_hold
})
{
if steps > 0 {
@@ -899,14 +894,15 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
return false;
}
- let self_ty = self.replace_bound_vars_with_fresh_vars(
+ let self_ty = self.instantiate_binder_with_fresh_vars(
DUMMY_SP,
LateBoundRegionConversionTime::FnCall,
trait_pred.self_ty(),
);
+ let body_hir_id = self.tcx.hir().local_def_id_to_hir_id(obligation.cause.body_id);
let Some((def_id_or_name, output, inputs)) = self.extract_callable_info(
- obligation.cause.body_id,
+ body_hir_id,
obligation.param_env,
self_ty,
) else { return false; };
@@ -931,7 +927,10 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
DefKind::Ctor(CtorOf::Variant, _) => {
"use parentheses to construct this tuple variant".to_string()
}
- kind => format!("use parentheses to call this {}", kind.descr(def_id)),
+ kind => format!(
+ "use parentheses to call this {}",
+ self.tcx.def_kind_descr(kind, def_id)
+ ),
},
DefIdOrName::Name(name) => format!("use parentheses to call this {name}"),
};
@@ -1004,8 +1003,9 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
span.remove_mark();
}
let mut expr_finder = FindExprBySpan::new(span);
- let Some(hir::Node::Expr(body)) = self.tcx.hir().find(obligation.cause.body_id) else { return; };
- expr_finder.visit_expr(&body);
+ let Some(body_id) = self.tcx.hir().maybe_body_owned_by(obligation.cause.body_id) else { return; };
+ let body = self.tcx.hir().body(body_id);
+ expr_finder.visit_expr(body.value);
let Some(expr) = expr_finder.result else { return; };
let Some(typeck) = &self.typeck_results else { return; };
let Some(ty) = typeck.expr_ty_adjusted_opt(expr) else { return; };
@@ -1059,9 +1059,8 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
trait_pred: ty::PolyTraitPredicate<'tcx>,
) -> bool {
let self_ty = self.resolve_vars_if_possible(trait_pred.self_ty());
- let ty = self.tcx.erase_late_bound_regions(self_ty);
- let owner = self.tcx.hir().get_parent_item(obligation.cause.body_id);
- let Some(generics) = self.tcx.hir().get_generics(owner.def_id) else { return false };
+ let ty = self.instantiate_binder_with_placeholders(self_ty);
+ let Some(generics) = self.tcx.hir().get_generics(obligation.cause.body_id) else { return false };
let ty::Ref(_, inner_ty, hir::Mutability::Not) = ty.kind() else { return false };
let ty::Param(param) = inner_ty.kind() else { return false };
let ObligationCauseCode::FunctionArgumentObligation { arg_hir_id, .. } = obligation.cause.code() else { return false };
@@ -1088,6 +1087,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
param.name.as_str(),
"Clone",
Some(clone_trait),
+ None,
);
}
err.span_suggestion_verbose(
@@ -1104,6 +1104,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
/// Extracts information about a callable type for diagnostics. This is a
/// heuristic -- it doesn't necessarily mean that a type is always callable,
/// because the callable type must also be well-formed to be called.
+ // FIXME(vincenzopalazzo): move the HirId to a LocalDefId
fn extract_callable_info(
&self,
hir_id: HirId,
@@ -1189,7 +1190,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
}
}) else { return None; };
- let output = self.replace_bound_vars_with_fresh_vars(
+ let output = self.instantiate_binder_with_fresh_vars(
DUMMY_SP,
LateBoundRegionConversionTime::FnCall,
output,
@@ -1198,7 +1199,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
.skip_binder()
.iter()
.map(|ty| {
- self.replace_bound_vars_with_fresh_vars(
+ self.instantiate_binder_with_fresh_vars(
DUMMY_SP,
LateBoundRegionConversionTime::FnCall,
inputs.rebind(*ty),
@@ -1348,14 +1349,41 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
Applicability::MaybeIncorrect,
);
} else {
+ // Issue #104961, we need to add parentheses properly for compond expressions
+ // for example, `x.starts_with("hi".to_string() + "you")`
+ // should be `x.starts_with(&("hi".to_string() + "you"))`
+ let Some(body_id) = self.tcx.hir().maybe_body_owned_by(obligation.cause.body_id) else { return false; };
+ let body = self.tcx.hir().body(body_id);
+ let mut expr_finder = FindExprBySpan::new(span);
+ expr_finder.visit_expr(body.value);
+ let Some(expr) = expr_finder.result else { return false; };
+ let needs_parens = match expr.kind {
+ // parenthesize if needed (Issue #46756)
+ hir::ExprKind::Cast(_, _) | hir::ExprKind::Binary(_, _, _) => true,
+ // parenthesize borrows of range literals (Issue #54505)
+ _ if is_range_literal(expr) => true,
+ _ => false,
+ };
+
let is_mut = mut_ref_self_ty_satisfies_pred || ref_inner_ty_mut;
- err.span_suggestion_verbose(
- span.shrink_to_lo(),
- &format!(
- "consider{} borrowing here",
- if is_mut { " mutably" } else { "" }
- ),
- format!("&{}", if is_mut { "mut " } else { "" }),
+ let span = if needs_parens { span } else { span.shrink_to_lo() };
+ let sugg_prefix = format!("&{}", if is_mut { "mut " } else { "" });
+ let sugg_msg = &format!(
+ "consider{} borrowing here",
+ if is_mut { " mutably" } else { "" }
+ );
+
+ let suggestions = if !needs_parens {
+ vec![(span.shrink_to_lo(), format!("{}", sugg_prefix))]
+ } else {
+ vec![
+ (span.shrink_to_lo(), format!("{}(", sugg_prefix)),
+ (span.shrink_to_hi(), ")".to_string()),
+ ]
+ };
+ err.multipart_suggestion_verbose(
+ sugg_msg,
+ suggestions,
Applicability::MaybeIncorrect,
);
}
@@ -1429,10 +1457,11 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
span.remove_mark();
}
let mut expr_finder = super::FindExprBySpan::new(span);
- let Some(hir::Node::Expr(body)) = self.tcx.hir().find(obligation.cause.body_id) else {
+ let Some(body_id) = self.tcx.hir().maybe_body_owned_by(obligation.cause.body_id) else {
return false;
};
- expr_finder.visit_expr(&body);
+ let body = self.tcx.hir().body(body_id);
+ expr_finder.visit_expr(body.value);
let mut maybe_suggest = |suggested_ty, count, suggestions| {
// Remapping bound vars here
let trait_pred_and_suggested_ty =
@@ -1670,8 +1699,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
trait_pred: ty::PolyTraitPredicate<'tcx>,
) -> bool {
let hir = self.tcx.hir();
- let parent_node = hir.parent_id(obligation.cause.body_id);
- let node = hir.find(parent_node);
+ let node = hir.find_by_def_id(obligation.cause.body_id);
if let Some(hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(sig, _, body_id), .. })) = node
&& let hir::ExprKind::Block(blk, _) = &hir.body(*body_id).value.kind
&& sig.decl.output.span().overlaps(span)
@@ -1707,8 +1735,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
fn return_type_span(&self, obligation: &PredicateObligation<'tcx>) -> Option<Span> {
let hir = self.tcx.hir();
- let parent_node = hir.parent_id(obligation.cause.body_id);
- let Some(hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(sig, ..), .. })) = hir.find(parent_node) else {
+ let Some(hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(sig, ..), .. })) = hir.find_by_def_id(obligation.cause.body_id) else {
return None;
};
@@ -1732,8 +1759,8 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
}
let hir = self.tcx.hir();
- let fn_hir_id = hir.parent_id(obligation.cause.body_id);
- let node = hir.find(fn_hir_id);
+ let fn_hir_id = hir.local_def_id_to_hir_id(obligation.cause.body_id);
+ let node = hir.find_by_def_id(obligation.cause.body_id);
let Some(hir::Node::Item(hir::Item {
kind: hir::ItemKind::Fn(sig, _, body_id),
..
@@ -1749,7 +1776,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
// If the `dyn Trait` is not object safe, do not suggest `Box<dyn Trait>`.
predicates
.principal_def_id()
- .map_or(true, |def_id| self.tcx.object_safety_violations(def_id).is_empty())
+ .map_or(true, |def_id| self.tcx.check_is_object_safe(def_id))
}
// We only want to suggest `impl Trait` to `dyn Trait`s.
// For example, `fn foo() -> str` needs to be filtered out.
@@ -1806,7 +1833,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
match liberated_sig.output().kind() {
ty::Dynamic(predicates, _, ty::Dyn) => {
- let cause = ObligationCause::misc(ret_ty.span, fn_hir_id);
+ let cause = ObligationCause::misc(ret_ty.span, obligation.cause.body_id);
let param_env = ty::ParamEnv::empty();
if !only_never_return {
@@ -1944,8 +1971,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
}
let hir = self.tcx.hir();
- let parent_node = hir.parent_id(obligation.cause.body_id);
- let node = hir.find(parent_node);
+ let node = hir.find_by_def_id(obligation.cause.body_id);
if let Some(hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(_, _, body_id), .. })) =
node
{
@@ -1989,7 +2015,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
let sig = match inputs.kind() {
ty::Tuple(inputs) if infcx.tcx.is_fn_trait(trait_ref.def_id()) => {
infcx.tcx.mk_fn_sig(
- inputs.iter(),
+ *inputs,
infcx.next_ty_var(TypeVariableOrigin {
span: DUMMY_SP,
kind: TypeVariableOriginKind::MiscVariable,
@@ -2000,7 +2026,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
)
}
_ => infcx.tcx.mk_fn_sig(
- std::iter::once(inputs),
+ [inputs],
infcx.next_ty_var(TypeVariableOrigin {
span: DUMMY_SP,
kind: TypeVariableOriginKind::MiscVariable,
@@ -2116,7 +2142,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
err.note(&format!(
"{}s cannot be accessed directly on a `trait`, they can only be \
accessed through a specific `impl`",
- assoc_item.kind.as_def_kind().descr(item_def_id)
+ self.tcx.def_kind_descr(assoc_item.kind.as_def_kind(), item_def_id)
));
err.span_suggestion(
span,
@@ -2225,7 +2251,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
);
match *ty.kind() {
- ty::Generator(did, ..) => {
+ ty::Generator(did, ..) | ty::GeneratorWitnessMIR(did, _) => {
generator = generator.or(Some(did));
outer_generator = Some(did);
}
@@ -2255,7 +2281,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
);
match *ty.kind() {
- ty::Generator(did, ..) => {
+ ty::Generator(did, ..) | ty::GeneratorWitnessMIR(did, ..) => {
generator = generator.or(Some(did));
outer_generator = Some(did);
}
@@ -2344,9 +2370,14 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
_ => return false,
};
+ let generator_within_in_progress_typeck = match &self.typeck_results {
+ Some(t) => t.hir_owner.to_def_id() == generator_did_root,
+ _ => false,
+ };
+
let mut interior_or_upvar_span = None;
- let from_awaited_ty = generator_data.get_from_await_ty(visitor, hir, ty_matches);
+ let from_awaited_ty = generator_data.get_from_await_ty(self.tcx, visitor, hir, ty_matches);
debug!(?from_awaited_ty);
// The generator interior types share the same binders
@@ -2363,6 +2394,35 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
*span,
Some((*scope_span, *yield_span, *expr, from_awaited_ty)),
));
+
+ if interior_or_upvar_span.is_none() && generator_data.is_foreign() {
+ interior_or_upvar_span = Some(GeneratorInteriorOrUpvar::Interior(*span, None));
+ }
+ } else if self.tcx.sess.opts.unstable_opts.drop_tracking_mir
+ // Avoid disclosing internal information to downstream crates.
+ && generator_did.is_local()
+ // Try to avoid cycles.
+ && !generator_within_in_progress_typeck
+ {
+ let generator_info = &self.tcx.mir_generator_witnesses(generator_did);
+ debug!(?generator_info);
+
+ 'find_source: for (variant, source_info) in
+ generator_info.variant_fields.iter().zip(&generator_info.variant_source_info)
+ {
+ debug!(?variant);
+ for &local in variant {
+ let decl = &generator_info.field_tys[local];
+ debug!(?decl);
+ if ty_matches(ty::Binder::dummy(decl.ty)) && !decl.ignore_for_traits {
+ interior_or_upvar_span = Some(GeneratorInteriorOrUpvar::Interior(
+ decl.source_info.span,
+ Some((None, source_info.span, None, from_awaited_ty)),
+ ));
+ break 'find_source;
+ }
+ }
+ }
}
if interior_or_upvar_span.is_none() {
@@ -2727,7 +2787,13 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
_ => true,
};
if ident.span.is_visible(sm) && !ident.span.overlaps(span) && !same_line {
- multispan.push_span_label(ident.span, "required by a bound in this");
+ multispan.push_span_label(
+ ident.span,
+ format!(
+ "required by a bound in this {}",
+ tcx.def_kind(item_def_id).descr(item_def_id)
+ ),
+ );
}
}
let descr = format!("required by a bound in `{item_name}`");
@@ -3011,6 +3077,20 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
}
err.note(msg.trim_end_matches(", "))
}
+ ty::GeneratorWitnessMIR(def_id, substs) => {
+ use std::fmt::Write;
+
+ // FIXME: this is kind of an unusual format for rustc, can we make it more clear?
+ // Maybe we should just remove this note altogether?
+ // FIXME: only print types which don't meet the trait requirement
+ let mut msg =
+ "required because it captures the following types: ".to_owned();
+ for bty in tcx.generator_hidden_types(*def_id) {
+ let ty = bty.subst(tcx, substs);
+ write!(msg, "`{}`, ", ty).unwrap();
+ }
+ err.note(msg.trim_end_matches(", "))
+ }
ty::Generator(def_id, _, _) => {
let sp = self.tcx.def_span(def_id);
@@ -3027,6 +3107,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
self.tcx.def_span(def_id),
"required because it's used within this closure",
),
+ ty::Str => err.note("`str` is considered to contain a `[u8]` slice for auto trait purposes"),
_ => err.note(&msg),
};
}
@@ -3072,7 +3153,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
parent_trait_pred.print_modifiers_and_trait_path()
);
let mut is_auto_trait = false;
- match self.tcx.hir().get_if_local(data.impl_def_id) {
+ match self.tcx.hir().get_if_local(data.impl_or_alias_def_id) {
Some(Node::Item(hir::Item {
kind: hir::ItemKind::Trait(is_auto, ..),
ident,
@@ -3283,12 +3364,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
trait_pred: ty::PolyTraitPredicate<'tcx>,
span: Span,
) {
- let body_hir_id = obligation.cause.body_id;
- let item_id = self.tcx.hir().parent_id(body_hir_id);
-
- if let Some(body_id) =
- self.tcx.hir().maybe_body_owned_by(self.tcx.hir().local_def_id(item_id))
- {
+ if let Some(body_id) = self.tcx.hir().maybe_body_owned_by(obligation.cause.body_id) {
let body = self.tcx.hir().body(body_id);
if let Some(hir::GeneratorKind::Async(_)) = body.generator_kind {
let future_trait = self.tcx.require_lang_item(LangItem::Future, None);
@@ -3459,7 +3535,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
{
if let hir::Expr { kind: hir::ExprKind::Block(..), .. } = expr {
let expr = expr.peel_blocks();
- let ty = typeck_results.expr_ty_adjusted_opt(expr).unwrap_or(tcx.ty_error());
+ let ty = typeck_results.expr_ty_adjusted_opt(expr).unwrap_or(tcx.ty_error_misc());
let span = expr.span;
if Some(span) != err.span.primary_span() {
err.span_label(
@@ -3502,7 +3578,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
{
type_diffs = vec![
Sorts(ty::error::ExpectedFound {
- expected: self.tcx.mk_ty(ty::Alias(ty::Projection, where_pred.skip_binder().projection_ty)),
+ expected: self.tcx.mk_alias(ty::Projection, where_pred.skip_binder().projection_ty),
found,
}),
];
@@ -3562,7 +3638,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
let mut assocs = vec![];
let mut expr = expr;
let mut prev_ty = self.resolve_vars_if_possible(
- typeck_results.expr_ty_adjusted_opt(expr).unwrap_or(tcx.ty_error()),
+ typeck_results.expr_ty_adjusted_opt(expr).unwrap_or(tcx.ty_error_misc()),
);
while let hir::ExprKind::MethodCall(_path_segment, rcvr_expr, _args, span) = expr.kind {
// Point at every method call in the chain with the resulting type.
@@ -3573,7 +3649,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
self.probe_assoc_types_at_expr(&type_diffs, span, prev_ty, expr.hir_id, param_env);
assocs.push(assocs_in_this_method);
prev_ty = self.resolve_vars_if_possible(
- typeck_results.expr_ty_adjusted_opt(expr).unwrap_or(tcx.ty_error()),
+ typeck_results.expr_ty_adjusted_opt(expr).unwrap_or(tcx.ty_error_misc()),
);
if let hir::ExprKind::Path(hir::QPath::Resolved(None, path)) = expr.kind
@@ -3591,7 +3667,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
if let hir::Node::Param(param) = parent {
// ...and it is a an fn argument.
let prev_ty = self.resolve_vars_if_possible(
- typeck_results.node_type_opt(param.hir_id).unwrap_or(tcx.ty_error()),
+ typeck_results.node_type_opt(param.hir_id).unwrap_or(tcx.ty_error_misc()),
);
let assocs_in_this_method = self.probe_assoc_types_at_expr(&type_diffs, param.ty_span, prev_ty, param.hir_id, param_env);
if assocs_in_this_method.iter().any(|a| a.is_some()) {
@@ -3620,7 +3696,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
let Some((span, (assoc, ty))) = entry else { continue; };
if primary_spans.is_empty() || type_diffs.iter().any(|diff| {
let Sorts(expected_found) = diff else { return false; };
- self.can_eq(param_env, expected_found.found, ty).is_ok()
+ self.can_eq(param_env, expected_found.found, ty)
}) {
// FIXME: this doesn't quite work for `Iterator::collect`
// because we have `Vec<i32>` and `()`, but we'd want `i32`
@@ -3647,10 +3723,10 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
let ty_str = with_forced_trimmed_paths!(self.ty_to_string(ty));
let assoc = with_forced_trimmed_paths!(self.tcx.def_path_str(assoc));
- if self.can_eq(param_env, ty, *prev_ty).is_err() {
+ if !self.can_eq(param_env, ty, *prev_ty) {
if type_diffs.iter().any(|diff| {
let Sorts(expected_found) = diff else { return false; };
- self.can_eq(param_env, expected_found.found, ty).is_ok()
+ self.can_eq(param_env, expected_found.found, ty)
}) {
primary_spans.push(span);
}
@@ -3727,9 +3803,14 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
term: ty_var.into(),
},
)));
+ let body_def_id = self.tcx.hir().enclosing_body_owner(body_id);
// Add `<ExprTy as Iterator>::Item = _` obligation.
ocx.register_obligation(Obligation::misc(
- self.tcx, span, body_id, param_env, projection,
+ self.tcx,
+ span,
+ body_def_id,
+ param_env,
+ projection,
));
if ocx.select_where_possible().is_empty() {
// `ty_var` now holds the type that `Item` is for `ExprTy`.
@@ -3758,13 +3839,13 @@ fn hint_missing_borrow<'tcx>(
err: &mut Diagnostic,
) {
let found_args = match found.kind() {
- ty::FnPtr(f) => f.inputs().skip_binder().iter(),
+ ty::FnPtr(f) => infcx.instantiate_binder_with_placeholders(*f).inputs().iter(),
kind => {
span_bug!(span, "found was converted to a FnPtr above but is now {:?}", kind)
}
};
let expected_args = match expected.kind() {
- ty::FnPtr(f) => f.inputs().skip_binder().iter(),
+ ty::FnPtr(f) => infcx.instantiate_binder_with_placeholders(*f).inputs().iter(),
kind => {
span_bug!(span, "expected was converted to a FnPtr above but is now {:?}", kind)
}
@@ -3775,12 +3856,12 @@ fn hint_missing_borrow<'tcx>(
let args = fn_decl.inputs.iter().map(|ty| ty);
- fn get_deref_type_and_refs(mut ty: Ty<'_>) -> (Ty<'_>, usize) {
- let mut refs = 0;
+ fn get_deref_type_and_refs(mut ty: Ty<'_>) -> (Ty<'_>, Vec<hir::Mutability>) {
+ let mut refs = vec![];
- while let ty::Ref(_, new_ty, _) = ty.kind() {
+ while let ty::Ref(_, new_ty, mutbl) = ty.kind() {
ty = *new_ty;
- refs += 1;
+ refs.push(*mutbl);
}
(ty, refs)
@@ -3793,12 +3874,22 @@ fn hint_missing_borrow<'tcx>(
let (found_ty, found_refs) = get_deref_type_and_refs(*found_arg);
let (expected_ty, expected_refs) = get_deref_type_and_refs(*expected_arg);
- if infcx.can_eq(param_env, found_ty, expected_ty).is_ok() {
- if found_refs < expected_refs {
- to_borrow.push((arg.span.shrink_to_lo(), "&".repeat(expected_refs - found_refs)));
- } else if found_refs > expected_refs {
+ if infcx.can_eq(param_env, found_ty, expected_ty) {
+ // FIXME: This could handle more exotic cases like mutability mismatches too!
+ if found_refs.len() < expected_refs.len()
+ && found_refs[..] == expected_refs[expected_refs.len() - found_refs.len()..]
+ {
+ to_borrow.push((
+ arg.span.shrink_to_lo(),
+ expected_refs[..expected_refs.len() - found_refs.len()]
+ .iter()
+ .map(|mutbl| format!("&{}", mutbl.prefix_str()))
+ .collect::<Vec<_>>()
+ .join(""),
+ ));
+ } else if found_refs.len() > expected_refs.len() {
let mut span = arg.span.shrink_to_lo();
- let mut left = found_refs - expected_refs;
+ let mut left = found_refs.len() - expected_refs.len();
let mut ty = arg;
while let hir::TyKind::Ref(_, mut_ty) = &ty.kind && left > 0 {
span = span.with_hi(mut_ty.ty.span.lo());
@@ -3996,7 +4087,7 @@ struct ReplaceImplTraitFolder<'tcx> {
replace_ty: Ty<'tcx>,
}
-impl<'tcx> TypeFolder<'tcx> for ReplaceImplTraitFolder<'tcx> {
+impl<'tcx> TypeFolder<TyCtxt<'tcx>> for ReplaceImplTraitFolder<'tcx> {
fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
if let ty::Param(ty::ParamTy { index, .. }) = t.kind() {
if self.param.index == *index {
@@ -4006,7 +4097,7 @@ impl<'tcx> TypeFolder<'tcx> for ReplaceImplTraitFolder<'tcx> {
t.super_fold_with(self)
}
- fn tcx(&self) -> TyCtxt<'tcx> {
+ fn interner(&self) -> TyCtxt<'tcx> {
self.tcx
}
}
diff --git a/compiler/rustc_trait_selection/src/traits/fulfill.rs b/compiler/rustc_trait_selection/src/traits/fulfill.rs
index 76a755ed9..944436ab8 100644
--- a/compiler/rustc_trait_selection/src/traits/fulfill.rs
+++ b/compiler/rustc_trait_selection/src/traits/fulfill.rs
@@ -1,5 +1,4 @@
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};
@@ -9,7 +8,7 @@ use rustc_middle::mir::interpret::ErrorHandled;
use rustc_middle::ty::abstract_const::NotConstEvaluatable;
use rustc_middle::ty::error::{ExpectedFound, TypeError};
use rustc_middle::ty::subst::SubstsRef;
-use rustc_middle::ty::{self, Binder, Const, TypeVisitable};
+use rustc_middle::ty::{self, Binder, Const, TypeVisitableExt};
use std::marker::PhantomData;
use super::const_evaluatable;
@@ -54,8 +53,6 @@ pub struct FulfillmentContext<'tcx> {
// fulfillment context.
predicates: ObligationForest<PendingPredicateObligation<'tcx>>,
- relationships: FxHashMap<ty::TyVid, ty::FoundRelationships>,
-
// Is it OK to register obligations into this infcx inside
// an infcx snapshot?
//
@@ -85,19 +82,11 @@ static_assert_size!(PendingPredicateObligation<'_>, 72);
impl<'a, 'tcx> FulfillmentContext<'tcx> {
/// Creates a new fulfillment context.
pub(super) fn new() -> FulfillmentContext<'tcx> {
- FulfillmentContext {
- predicates: ObligationForest::new(),
- relationships: FxHashMap::default(),
- usable_in_snapshot: false,
- }
+ FulfillmentContext { predicates: ObligationForest::new(), usable_in_snapshot: false }
}
pub(super) fn new_in_snapshot() -> FulfillmentContext<'tcx> {
- FulfillmentContext {
- predicates: ObligationForest::new(),
- relationships: FxHashMap::default(),
- usable_in_snapshot: true,
- }
+ FulfillmentContext { predicates: ObligationForest::new(), usable_in_snapshot: true }
}
/// Attempts to select obligations using `selcx`.
@@ -139,20 +128,11 @@ 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![] });
}
- fn select_all_or_error(&mut self, infcx: &InferCtxt<'tcx>) -> Vec<FulfillmentError<'tcx>> {
- {
- let errors = self.select_where_possible(infcx);
- if !errors.is_empty() {
- return errors;
- }
- }
-
+ fn collect_remaining_errors(&mut self) -> Vec<FulfillmentError<'tcx>> {
self.predicates.to_errors(CodeAmbiguity).into_iter().map(to_fulfillment_error).collect()
}
@@ -161,12 +141,57 @@ impl<'tcx> TraitEngine<'tcx> for FulfillmentContext<'tcx> {
self.select(selcx)
}
- fn pending_obligations(&self) -> Vec<PredicateObligation<'tcx>> {
- self.predicates.map_pending_obligations(|o| o.obligation.clone())
+ fn drain_unstalled_obligations(
+ &mut self,
+ infcx: &InferCtxt<'tcx>,
+ ) -> Vec<PredicateObligation<'tcx>> {
+ let mut processor = DrainProcessor { removed_predicates: Vec::new(), infcx };
+ let outcome: Outcome<_, _> = self.predicates.process_obligations(&mut processor);
+ assert!(outcome.errors.is_empty());
+ return processor.removed_predicates;
+
+ struct DrainProcessor<'a, 'tcx> {
+ infcx: &'a InferCtxt<'tcx>,
+ removed_predicates: Vec<PredicateObligation<'tcx>>,
+ }
+
+ impl<'tcx> ObligationProcessor for DrainProcessor<'_, 'tcx> {
+ type Obligation = PendingPredicateObligation<'tcx>;
+ type Error = !;
+ type OUT = Outcome<Self::Obligation, Self::Error>;
+
+ fn needs_process_obligation(&self, pending_obligation: &Self::Obligation) -> bool {
+ pending_obligation
+ .stalled_on
+ .iter()
+ .any(|&var| self.infcx.ty_or_const_infer_var_changed(var))
+ }
+
+ fn process_obligation(
+ &mut self,
+ pending_obligation: &mut PendingPredicateObligation<'tcx>,
+ ) -> ProcessResult<PendingPredicateObligation<'tcx>, !> {
+ assert!(self.needs_process_obligation(pending_obligation));
+ self.removed_predicates.push(pending_obligation.obligation.clone());
+ ProcessResult::Changed(vec![])
+ }
+
+ fn process_backedge<'c, I>(
+ &mut self,
+ cycle: I,
+ _marker: PhantomData<&'c PendingPredicateObligation<'tcx>>,
+ ) -> Result<(), !>
+ where
+ I: Clone + Iterator<Item = &'c PendingPredicateObligation<'tcx>>,
+ {
+ self.removed_predicates.extend(cycle.map(|c| c.obligation.clone()));
+ Ok(())
+ }
+ }
}
- fn relationships(&mut self) -> &mut FxHashMap<ty::TyVid, ty::FoundRelationships> {
- &mut self.relationships
+ fn pending_obligations(&self) -> Vec<PredicateObligation<'tcx>> {
+ self.predicates.map_pending_obligations(|o| o.obligation.clone())
}
}
@@ -187,36 +212,44 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> {
/// Identifies whether a predicate obligation needs processing.
///
- /// This is always inlined, despite its size, because it has a single
- /// callsite and it is called *very* frequently.
+ /// This is always inlined because it has a single callsite and it is
+ /// called *very* frequently. Be careful modifying this code! Several
+ /// compile-time benchmarks are very sensitive to even small changes.
#[inline(always)]
fn needs_process_obligation(&self, pending_obligation: &Self::Obligation) -> bool {
// If we were stalled on some unresolved variables, first check whether
// any of them have been resolved; if not, don't bother doing more work
// yet.
- match pending_obligation.stalled_on.len() {
- // Match arms are in order of frequency, which matters because this
- // code is so hot. 1 and 0 dominate; 2+ is fairly rare.
- 1 => {
- let infer_var = pending_obligation.stalled_on[0];
- self.selcx.infcx.ty_or_const_infer_var_changed(infer_var)
- }
- 0 => {
- // In this case we haven't changed, but wish to make a change.
- true
- }
- _ => {
- // This `for` loop was once a call to `all()`, but this lower-level
- // form was a perf win. See #64545 for details.
- (|| {
- for &infer_var in &pending_obligation.stalled_on {
- if self.selcx.infcx.ty_or_const_infer_var_changed(infer_var) {
- return true;
- }
+ let stalled_on = &pending_obligation.stalled_on;
+ match stalled_on.len() {
+ // This case is the hottest most of the time, being hit up to 99%
+ // of the time. `keccak` and `cranelift-codegen-0.82.1` are
+ // benchmarks that particularly stress this path.
+ 1 => self.selcx.infcx.ty_or_const_infer_var_changed(stalled_on[0]),
+
+ // In this case we haven't changed, but wish to make a change. Note
+ // that this is a special case, and is not equivalent to the `_`
+ // case below, which would return `false` for an empty `stalled_on`
+ // vector.
+ //
+ // This case is usually hit only 1% of the time or less, though it
+ // reaches 20% in `wasmparser-0.101.0`.
+ 0 => true,
+
+ // This case is usually hit only 1% of the time or less, though it
+ // reaches 95% in `mime-0.3.16`, 64% in `wast-54.0.0`, and 12% in
+ // `inflate-0.4.5`.
+ //
+ // The obvious way of writing this, with a call to `any()` and no
+ // closure, is currently slower than this version.
+ _ => (|| {
+ for &infer_var in stalled_on {
+ if self.selcx.infcx.ty_or_const_infer_var_changed(infer_var) {
+ return true;
}
- false
- })()
- }
+ }
+ false
+ })(),
}
}
@@ -288,6 +321,7 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> {
}
ty::PredicateKind::Clause(ty::Clause::RegionOutlives(_))
| ty::PredicateKind::Clause(ty::Clause::TypeOutlives(_))
+ | ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(..))
| ty::PredicateKind::WellFormed(_)
| ty::PredicateKind::ObjectSafe(_)
| ty::PredicateKind::ClosureKind(..)
@@ -296,13 +330,16 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> {
| ty::PredicateKind::ConstEvaluatable(..)
| ty::PredicateKind::ConstEquate(..) => {
let pred =
- ty::Binder::dummy(infcx.replace_bound_vars_with_placeholders(binder));
+ ty::Binder::dummy(infcx.instantiate_binder_with_placeholders(binder));
ProcessResult::Changed(mk_pending(vec![obligation.with(infcx.tcx, pred)]))
}
ty::PredicateKind::Ambiguous => ProcessResult::Unchanged,
ty::PredicateKind::TypeWellFormedFromEnv(..) => {
bug!("TypeWellFormedFromEnv is only used for Chalk")
}
+ ty::PredicateKind::AliasEq(..) => {
+ bug!("AliasEq is only used for new solver")
+ }
},
Some(pred) => match pred {
ty::PredicateKind::Clause(ty::Clause::Trait(data)) => {
@@ -344,7 +381,7 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> {
}
ty::PredicateKind::ObjectSafe(trait_def_id) => {
- if !self.selcx.tcx().is_object_safe(trait_def_id) {
+ if !self.selcx.tcx().check_is_object_safe(trait_def_id) {
ProcessResult::Error(CodeSelectionError(Unimplemented))
} else {
ProcessResult::Changed(vec![])
@@ -569,6 +606,22 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> {
ty::PredicateKind::TypeWellFormedFromEnv(..) => {
bug!("TypeWellFormedFromEnv is only used for Chalk")
}
+ ty::PredicateKind::AliasEq(..) => {
+ bug!("AliasEq is only used for new solver")
+ }
+ ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(ct, ty)) => {
+ match self
+ .selcx
+ .infcx
+ .at(&obligation.cause, obligation.param_env)
+ .eq(ct.ty(), ty)
+ {
+ Ok(inf_ok) => ProcessResult::Changed(mk_pending(inf_ok.into_obligations())),
+ Err(_) => ProcessResult::Error(FulfillmentErrorCode::CodeSelectionError(
+ SelectionError::Unimplemented,
+ )),
+ }
+ }
},
}
}
diff --git a/compiler/rustc_trait_selection/src/traits/misc.rs b/compiler/rustc_trait_selection/src/traits/misc.rs
index a41a601f2..b94346b09 100644
--- a/compiler/rustc_trait_selection/src/traits/misc.rs
+++ b/compiler/rustc_trait_selection/src/traits/misc.rs
@@ -1,12 +1,15 @@
//! Miscellaneous type-system utilities that are too small to deserve their own modules.
-use crate::traits::{self, ObligationCause};
+use crate::traits::{self, ObligationCause, ObligationCtxt};
use rustc_data_structures::fx::FxIndexSet;
use rustc_hir as hir;
+use rustc_infer::infer::canonical::Canonical;
use rustc_infer::infer::{RegionResolutionError, TyCtxtInferExt};
+use rustc_infer::traits::query::NoSolution;
use rustc_infer::{infer::outlives::env::OutlivesEnvironment, traits::FulfillmentError};
-use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitable};
+use rustc_middle::ty::{self, ParamEnv, Ty, TyCtxt, TypeVisitableExt};
+use rustc_span::DUMMY_SP;
use super::outlives_bounds::InferCtxtExt;
@@ -131,3 +134,19 @@ pub fn type_allowed_to_implement_copy<'tcx>(
Ok(())
}
+
+pub fn check_tys_might_be_eq<'tcx>(
+ tcx: TyCtxt<'tcx>,
+ canonical: Canonical<'tcx, (ParamEnv<'tcx>, Ty<'tcx>, Ty<'tcx>)>,
+) -> Result<(), NoSolution> {
+ let (infcx, (param_env, ty_a, ty_b), _) =
+ tcx.infer_ctxt().build_with_canonical(DUMMY_SP, &canonical);
+ let ocx = ObligationCtxt::new(&infcx);
+
+ let result = ocx.eq(&ObligationCause::dummy(), param_env, ty_a, ty_b);
+ // use `select_where_possible` instead of `select_all_or_error` so that
+ // we don't get errors from obligations being ambiguous.
+ let errors = ocx.select_where_possible();
+
+ if errors.len() > 0 || result.is_err() { Err(NoSolution) } else { Ok(()) }
+}
diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs
index f036a311d..4e30108be 100644
--- a/compiler/rustc_trait_selection/src/traits/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/mod.rs
@@ -14,7 +14,6 @@ mod object_safety;
pub mod outlives_bounds;
mod project;
pub mod query;
-pub(crate) mod relationships;
mod select;
mod specialize;
mod structural_match;
@@ -27,12 +26,11 @@ use crate::infer::{InferCtxt, TyCtxtInferExt};
use crate::traits::error_reporting::TypeErrCtxtExt as _;
use crate::traits::query::evaluate_obligation::InferCtxtExt as _;
use rustc_errors::ErrorGuaranteed;
-use rustc_hir as hir;
-use rustc_hir::def_id::DefId;
use rustc_middle::ty::fold::TypeFoldable;
-use rustc_middle::ty::visit::TypeVisitable;
+use rustc_middle::ty::visit::{TypeVisitable, TypeVisitableExt};
use rustc_middle::ty::{self, DefIdTree, ToPredicate, Ty, TyCtxt, TypeSuperVisitable};
use rustc_middle::ty::{InternalSubsts, SubstsRef};
+use rustc_span::def_id::{DefId, CRATE_DEF_ID};
use rustc_span::Span;
use std::fmt::Debug;
@@ -143,7 +141,7 @@ pub fn type_known_to_meet_bound_modulo_regions<'tcx>(
fn pred_known_to_hold_modulo_regions<'tcx>(
infcx: &InferCtxt<'tcx>,
param_env: ty::ParamEnv<'tcx>,
- pred: impl ToPredicate<'tcx> + TypeVisitable<'tcx>,
+ pred: impl ToPredicate<'tcx> + TypeVisitable<TyCtxt<'tcx>>,
span: Span,
) -> bool {
let has_non_region_infer = pred.has_non_region_infer();
@@ -152,29 +150,29 @@ fn pred_known_to_hold_modulo_regions<'tcx>(
// We can use a dummy node-id here because we won't pay any mind
// to region obligations that arise (there shouldn't really be any
// anyhow).
- cause: ObligationCause::misc(span, hir::CRATE_HIR_ID),
+ cause: ObligationCause::misc(span, CRATE_DEF_ID),
recursion_depth: 0,
predicate: pred.to_predicate(infcx.tcx),
};
- let result = infcx.predicate_must_hold_modulo_regions(&obligation);
+ let result = infcx.evaluate_obligation_no_overflow(&obligation);
debug!(?result);
- if result && has_non_region_infer {
+ if result.must_apply_modulo_regions() && !has_non_region_infer {
+ true
+ } else if result.may_apply() {
// Because of inference "guessing", selection can sometimes claim
// to succeed while the success requires a guess. To ensure
// this function's result remains infallible, we must confirm
// that guess. While imperfect, I believe this is sound.
// FIXME(@lcnr): this function doesn't seem right.
+ //
// The handling of regions in this area of the code is terrible,
// see issue #29149. We should be able to improve on this with
// NLL.
let errors = fully_solve_obligation(infcx, obligation);
- // Note: we only assume something is `Copy` if we can
- // *definitively* show that it implements `Copy`. Otherwise,
- // assume it is move; linear is always ok.
match &errors[..] {
[] => true,
errors => {
@@ -183,7 +181,7 @@ fn pred_known_to_hold_modulo_regions<'tcx>(
}
}
} else {
- result
+ false
}
}
@@ -285,7 +283,7 @@ pub fn normalize_param_env_or_error<'tcx>(
debug!("normalize_param_env_or_error: elaborated-predicates={:?}", predicates);
let elaborated_env = ty::ParamEnv::new(
- tcx.intern_predicates(&predicates),
+ tcx.mk_predicates(&predicates),
unnormalized_env.reveal(),
unnormalized_env.constness(),
);
@@ -337,10 +335,9 @@ pub fn normalize_param_env_or_error<'tcx>(
// Not sure whether it is better to include the unnormalized TypeOutlives predicates
// here. I believe they should not matter, because we are ignoring TypeOutlives param-env
// predicates here anyway. Keeping them here anyway because it seems safer.
- let outlives_env: Vec<_> =
- non_outlives_predicates.iter().chain(&outlives_predicates).cloned().collect();
+ let outlives_env = non_outlives_predicates.iter().chain(&outlives_predicates).cloned();
let outlives_env = ty::ParamEnv::new(
- tcx.intern_predicates(&outlives_env),
+ tcx.mk_predicates_from_iter(outlives_env),
unnormalized_env.reveal(),
unnormalized_env.constness(),
);
@@ -360,7 +357,7 @@ pub fn normalize_param_env_or_error<'tcx>(
predicates.extend(outlives_predicates);
debug!("normalize_param_env_or_error: final predicates={:?}", predicates);
ty::ParamEnv::new(
- tcx.intern_predicates(&predicates),
+ tcx.mk_predicates(&predicates),
unnormalized_env.reveal(),
unnormalized_env.constness(),
)
@@ -375,7 +372,7 @@ pub fn fully_normalize<'tcx, T>(
value: T,
) -> Result<T, Vec<FulfillmentError<'tcx>>>
where
- T: TypeFoldable<'tcx>,
+ T: TypeFoldable<TyCtxt<'tcx>>,
{
let ocx = ObligationCtxt::new(infcx);
debug!(?value);
@@ -485,7 +482,7 @@ fn is_impossible_method(tcx: TyCtxt<'_>, (impl_def_id, trait_item_def_id): (DefI
generics: &'tcx ty::Generics,
trait_item_def_id: DefId,
}
- impl<'tcx> ty::TypeVisitor<'tcx> for ReferencesOnlyParentGenerics<'tcx> {
+ impl<'tcx> ty::TypeVisitor<TyCtxt<'tcx>> for ReferencesOnlyParentGenerics<'tcx> {
type BreakTy = ();
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
// If this is a parameter from the trait item's own generics, then bail
@@ -527,16 +524,14 @@ fn is_impossible_method(tcx: TyCtxt<'_>, (impl_def_id, trait_item_def_id): (DefI
let mut visitor = ReferencesOnlyParentGenerics { tcx, generics, trait_item_def_id };
let predicates_for_trait = predicates.predicates.iter().filter_map(|(pred, span)| {
- if pred.visit_with(&mut visitor).is_continue() {
- Some(Obligation::new(
+ pred.visit_with(&mut visitor).is_continue().then(|| {
+ Obligation::new(
tcx,
ObligationCause::dummy_with_span(*span),
param_env,
ty::EarlyBinder(*pred).subst(tcx, impl_trait_ref.substs),
- ))
- } else {
- None
- }
+ )
+ })
});
let infcx = tcx.infer_ctxt().ignoring_regions().build();
@@ -558,6 +553,7 @@ pub fn provide(providers: &mut ty::query::Providers) {
specialization_graph_of: specialize::specialization_graph_provider,
specializes: specialize::specializes,
subst_and_check_impossible_predicates,
+ check_tys_might_be_eq: misc::check_tys_might_be_eq,
is_impossible_method,
..*providers
};
diff --git a/compiler/rustc_trait_selection/src/traits/object_safety.rs b/compiler/rustc_trait_selection/src/traits/object_safety.rs
index c9121212c..4eacb5211 100644
--- a/compiler/rustc_trait_selection/src/traits/object_safety.rs
+++ b/compiler/rustc_trait_selection/src/traits/object_safety.rs
@@ -18,10 +18,10 @@ use rustc_errors::{DelayDm, FatalError, MultiSpan};
use rustc_hir as hir;
use rustc_hir::def_id::DefId;
use rustc_middle::ty::subst::{GenericArg, InternalSubsts};
+use rustc_middle::ty::ToPredicate;
use rustc_middle::ty::{
self, EarlyBinder, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitor,
};
-use rustc_middle::ty::{Predicate, ToPredicate};
use rustc_session::lint::builtin::WHERE_CLAUSES_OBJECT_SAFETY;
use rustc_span::symbol::Symbol;
use rustc_span::Span;
@@ -62,11 +62,42 @@ fn object_safety_violations(tcx: TyCtxt<'_>, trait_def_id: DefId) -> &'_ [Object
)
}
+fn check_is_object_safe(tcx: TyCtxt<'_>, trait_def_id: DefId) -> bool {
+ let violations = tcx.object_safety_violations(trait_def_id);
+
+ if violations.is_empty() {
+ return true;
+ }
+
+ // If the trait contains any other violations, then let the error reporting path
+ // report it instead of emitting a warning here.
+ if violations.iter().all(|violation| {
+ matches!(
+ violation,
+ ObjectSafetyViolation::Method(_, MethodViolationCode::WhereClauseReferencesSelf, _)
+ )
+ }) {
+ for violation in violations {
+ if let ObjectSafetyViolation::Method(
+ _,
+ MethodViolationCode::WhereClauseReferencesSelf,
+ span,
+ ) = violation
+ {
+ lint_object_unsafe_trait(tcx, *span, trait_def_id, &violation);
+ }
+ }
+ return true;
+ }
+
+ false
+}
+
/// We say a method is *vtable safe* if it can be invoked on a trait
/// object. Note that object-safe traits can have some
/// non-vtable-safe methods, so long as they require `Self: Sized` or
/// otherwise ensure that they cannot be used when `Self = Trait`.
-pub fn is_vtable_safe_method(tcx: TyCtxt<'_>, trait_def_id: DefId, method: &ty::AssocItem) -> bool {
+pub fn is_vtable_safe_method(tcx: TyCtxt<'_>, trait_def_id: DefId, method: ty::AssocItem) -> bool {
debug_assert!(tcx.generics_of(trait_def_id).has_self);
debug!("is_vtable_safe_method({:?}, {:?})", trait_def_id, method);
// Any method that has a `Self: Sized` bound cannot be called.
@@ -89,23 +120,10 @@ fn object_safety_violations_for_trait(
.associated_items(trait_def_id)
.in_definition_order()
.filter(|item| item.kind == ty::AssocKind::Fn)
- .filter_map(|item| {
- object_safety_violation_for_method(tcx, trait_def_id, &item)
+ .filter_map(|&item| {
+ object_safety_violation_for_method(tcx, trait_def_id, item)
.map(|(code, span)| ObjectSafetyViolation::Method(item.name, code, span))
})
- .filter(|violation| {
- if let ObjectSafetyViolation::Method(
- _,
- MethodViolationCode::WhereClauseReferencesSelf,
- span,
- ) = violation
- {
- lint_object_unsafe_trait(tcx, *span, trait_def_id, &violation);
- false
- } else {
- true
- }
- })
.collect();
// Check the trait itself.
@@ -289,7 +307,7 @@ fn predicate_references_self<'tcx>(
match predicate.kind().skip_binder() {
ty::PredicateKind::Clause(ty::Clause::Trait(ref data)) => {
// In the case of a trait predicate, we can skip the "self" type.
- if data.trait_ref.substs[1..].iter().any(has_self_ty) { Some(sp) } else { None }
+ data.trait_ref.substs[1..].iter().any(has_self_ty).then_some(sp)
}
ty::PredicateKind::Clause(ty::Clause::Projection(ref data)) => {
// And similarly for projections. This should be redundant with
@@ -307,8 +325,14 @@ fn predicate_references_self<'tcx>(
//
// This is ALT2 in issue #56288, see that for discussion of the
// possible alternatives.
- if data.projection_ty.substs[1..].iter().any(has_self_ty) { Some(sp) } else { None }
+ data.projection_ty.substs[1..].iter().any(has_self_ty).then_some(sp)
+ }
+ ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(_ct, ty)) => {
+ has_self_ty(&ty.into()).then_some(sp)
}
+
+ ty::PredicateKind::AliasEq(..) => bug!("`AliasEq` not allowed as assumption"),
+
ty::PredicateKind::WellFormed(..)
| ty::PredicateKind::ObjectSafe(..)
| ty::PredicateKind::Clause(ty::Clause::TypeOutlives(..))
@@ -316,6 +340,7 @@ fn predicate_references_self<'tcx>(
| ty::PredicateKind::ClosureKind(..)
| ty::PredicateKind::Subtype(..)
| ty::PredicateKind::Coerce(..)
+ // FIXME(generic_const_exprs): this can mention `Self`
| ty::PredicateKind::ConstEvaluatable(..)
| ty::PredicateKind::ConstEquate(..)
| ty::PredicateKind::Ambiguous
@@ -341,6 +366,7 @@ fn generics_require_sized_self(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
trait_pred.def_id() == sized_def_id && trait_pred.self_ty().is_param(0)
}
ty::PredicateKind::Clause(ty::Clause::Projection(..))
+ | ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(..))
| ty::PredicateKind::Subtype(..)
| ty::PredicateKind::Coerce(..)
| ty::PredicateKind::Clause(ty::Clause::RegionOutlives(..))
@@ -350,6 +376,7 @@ fn generics_require_sized_self(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
| ty::PredicateKind::Clause(ty::Clause::TypeOutlives(..))
| ty::PredicateKind::ConstEvaluatable(..)
| ty::PredicateKind::ConstEquate(..)
+ | ty::PredicateKind::AliasEq(..)
| ty::PredicateKind::Ambiguous
| ty::PredicateKind::TypeWellFormedFromEnv(..) => false,
}
@@ -360,7 +387,7 @@ fn generics_require_sized_self(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
fn object_safety_violation_for_method(
tcx: TyCtxt<'_>,
trait_def_id: DefId,
- method: &ty::AssocItem,
+ method: ty::AssocItem,
) -> Option<(MethodViolationCode, Span)> {
debug!("object_safety_violation_for_method({:?}, {:?})", trait_def_id, method);
// Any method that has a `Self : Sized` requisite is otherwise
@@ -393,9 +420,9 @@ fn object_safety_violation_for_method(
fn virtual_call_violation_for_method<'tcx>(
tcx: TyCtxt<'tcx>,
trait_def_id: DefId,
- method: &ty::AssocItem,
+ method: ty::AssocItem,
) -> Option<MethodViolationCode> {
- let sig = tcx.fn_sig(method.def_id);
+ let sig = tcx.fn_sig(method.def_id).subst_identity();
// The method's first parameter must be named `self`
if !method.fn_has_self_parameter {
@@ -505,8 +532,7 @@ fn virtual_call_violation_for_method<'tcx>(
}
}
- let trait_object_ty =
- object_ty_for_trait(tcx, trait_def_id, tcx.mk_region(ty::ReStatic));
+ let trait_object_ty = object_ty_for_trait(tcx, trait_def_id, tcx.lifetimes.re_static);
// e.g., `Rc<dyn Trait>`
let trait_object_receiver =
@@ -529,16 +555,56 @@ fn virtual_call_violation_for_method<'tcx>(
// NOTE: This check happens last, because it results in a lint, and not a
// hard error.
- if tcx
- .predicates_of(method.def_id)
- .predicates
- .iter()
- // A trait object can't claim to live more than the concrete type,
- // so outlives predicates will always hold.
- .cloned()
- .filter(|(p, _)| p.to_opt_type_outlives().is_none())
- .any(|pred| contains_illegal_self_type_reference(tcx, trait_def_id, pred))
- {
+ if tcx.predicates_of(method.def_id).predicates.iter().any(|&(pred, span)| {
+ // dyn Trait is okay:
+ //
+ // trait Trait {
+ // fn f(&self) where Self: 'static;
+ // }
+ //
+ // because a trait object can't claim to live longer than the concrete
+ // type. If the lifetime bound holds on dyn Trait then it's guaranteed
+ // to hold as well on the concrete type.
+ if pred.to_opt_type_outlives().is_some() {
+ return false;
+ }
+
+ // dyn Trait is okay:
+ //
+ // auto trait AutoTrait {}
+ //
+ // trait Trait {
+ // fn f(&self) where Self: AutoTrait;
+ // }
+ //
+ // because `impl AutoTrait for dyn Trait` is disallowed by coherence.
+ // Traits with a default impl are implemented for a trait object if and
+ // only if the autotrait is one of the trait object's trait bounds, like
+ // in `dyn Trait + AutoTrait`. This guarantees that trait objects only
+ // implement auto traits if the underlying type does as well.
+ if let ty::PredicateKind::Clause(ty::Clause::Trait(ty::TraitPredicate {
+ trait_ref: pred_trait_ref,
+ constness: ty::BoundConstness::NotConst,
+ polarity: ty::ImplPolarity::Positive,
+ })) = pred.kind().skip_binder()
+ && pred_trait_ref.self_ty() == tcx.types.self_param
+ && tcx.trait_is_auto(pred_trait_ref.def_id)
+ {
+ // Consider bounds like `Self: Bound<Self>`. Auto traits are not
+ // allowed to have generic parameters so `auto trait Bound<T> {}`
+ // would already have reported an error at the definition of the
+ // auto trait.
+ if pred_trait_ref.substs.len() != 1 {
+ tcx.sess.diagnostic().delay_span_bug(
+ span,
+ "auto traits cannot have generic parameters",
+ );
+ }
+ return false;
+ }
+
+ contains_illegal_self_type_reference(tcx, trait_def_id, pred)
+ }) {
return Some(MethodViolationCode::WhereClauseReferencesSelf);
}
@@ -588,11 +654,9 @@ fn object_ty_for_trait<'tcx>(
debug!(?obligation);
let pred = obligation.predicate.to_opt_poly_projection_pred()?;
Some(pred.map_bound(|p| {
- ty::ExistentialPredicate::Projection(ty::ExistentialProjection {
- def_id: p.projection_ty.def_id,
- substs: p.projection_ty.substs,
- term: p.term,
- })
+ ty::ExistentialPredicate::Projection(ty::ExistentialProjection::erase_self_ty(
+ tcx, p,
+ ))
}))
})
.collect();
@@ -602,8 +666,9 @@ fn object_ty_for_trait<'tcx>(
elaborated_predicates.sort_by(|a, b| a.skip_binder().stable_cmp(tcx, &b.skip_binder()));
elaborated_predicates.dedup();
- let existential_predicates = tcx
- .mk_poly_existential_predicates(iter::once(trait_predicate).chain(elaborated_predicates));
+ let existential_predicates = tcx.mk_poly_existential_predicates_from_iter(
+ iter::once(trait_predicate).chain(elaborated_predicates),
+ );
debug!(?existential_predicates);
tcx.mk_dynamic(existential_predicates, lifetime, ty::Dyn)
@@ -658,7 +723,7 @@ fn object_ty_for_trait<'tcx>(
#[allow(dead_code)]
fn receiver_is_dispatchable<'tcx>(
tcx: TyCtxt<'tcx>,
- method: &ty::AssocItem,
+ method: ty::AssocItem,
receiver_ty: Ty<'tcx>,
) -> bool {
debug!("receiver_is_dispatchable: method = {:?}, receiver_ty = {:?}", method, receiver_ty);
@@ -702,11 +767,11 @@ fn receiver_is_dispatchable<'tcx>(
ty::Binder::dummy(tcx.mk_trait_ref(trait_def_id, substs)).to_predicate(tcx)
};
- let caller_bounds: Vec<Predicate<'tcx>> =
- param_env.caller_bounds().iter().chain([unsize_predicate, trait_predicate]).collect();
+ let caller_bounds =
+ param_env.caller_bounds().iter().chain([unsize_predicate, trait_predicate]);
ty::ParamEnv::new(
- tcx.intern_predicates(&caller_bounds),
+ tcx.mk_predicates_from_iter(caller_bounds),
param_env.reveal(),
param_env.constness(),
)
@@ -726,7 +791,7 @@ fn receiver_is_dispatchable<'tcx>(
infcx.predicate_must_hold_modulo_regions(&obligation)
}
-fn contains_illegal_self_type_reference<'tcx, T: TypeVisitable<'tcx>>(
+fn contains_illegal_self_type_reference<'tcx, T: TypeVisitable<TyCtxt<'tcx>>>(
tcx: TyCtxt<'tcx>,
trait_def_id: DefId,
value: T,
@@ -776,7 +841,7 @@ fn contains_illegal_self_type_reference<'tcx, T: TypeVisitable<'tcx>>(
supertraits: Option<Vec<DefId>>,
}
- impl<'tcx> TypeVisitor<'tcx> for IllegalSelfTypeVisitor<'tcx> {
+ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for IllegalSelfTypeVisitor<'tcx> {
type BreakTy = ();
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
@@ -866,5 +931,6 @@ pub fn contains_illegal_impl_trait_in_trait<'tcx>(
}
pub fn provide(providers: &mut ty::query::Providers) {
- *providers = ty::query::Providers { object_safety_violations, ..*providers };
+ *providers =
+ ty::query::Providers { object_safety_violations, check_is_object_safe, ..*providers };
}
diff --git a/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs b/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs
index f2c5f730b..6cb64ad57 100644
--- a/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs
+++ b/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs
@@ -3,9 +3,8 @@ use crate::traits::query::type_op::{self, TypeOp, TypeOpOutput};
use crate::traits::query::NoSolution;
use crate::traits::ObligationCause;
use rustc_data_structures::fx::FxIndexSet;
-use rustc_hir as hir;
-use rustc_hir::HirId;
use rustc_middle::ty::{self, ParamEnv, Ty};
+use rustc_span::def_id::LocalDefId;
pub use rustc_middle::traits::query::OutlivesBound;
@@ -14,14 +13,14 @@ pub trait InferCtxtExt<'a, 'tcx> {
fn implied_outlives_bounds(
&self,
param_env: ty::ParamEnv<'tcx>,
- body_id: hir::HirId,
+ body_id: LocalDefId,
ty: Ty<'tcx>,
) -> Vec<OutlivesBound<'tcx>>;
fn implied_bounds_tys(
&'a self,
param_env: ty::ParamEnv<'tcx>,
- body_id: hir::HirId,
+ body_id: LocalDefId,
tys: FxIndexSet<Ty<'tcx>>,
) -> Bounds<'a, 'tcx>;
}
@@ -50,10 +49,10 @@ impl<'a, 'tcx: 'a> InferCtxtExt<'a, 'tcx> for InferCtxt<'tcx> {
fn implied_outlives_bounds(
&self,
param_env: ty::ParamEnv<'tcx>,
- body_id: hir::HirId,
+ body_id: LocalDefId,
ty: Ty<'tcx>,
) -> Vec<OutlivesBound<'tcx>> {
- let span = self.tcx.hir().span(body_id);
+ let span = self.tcx.def_span(body_id);
let result = param_env
.and(type_op::implied_outlives_bounds::ImpliedOutlivesBounds { ty })
.fully_perform(self);
@@ -102,7 +101,7 @@ impl<'a, 'tcx: 'a> InferCtxtExt<'a, 'tcx> for InferCtxt<'tcx> {
fn implied_bounds_tys(
&'a self,
param_env: ParamEnv<'tcx>,
- body_id: HirId,
+ body_id: LocalDefId,
tys: FxIndexSet<Ty<'tcx>>,
) -> Bounds<'a, 'tcx> {
tys.into_iter()
diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs
index fbc7ecced..870ecc2a9 100644
--- a/compiler/rustc_trait_selection/src/traits/project.rs
+++ b/compiler/rustc_trait_selection/src/traits/project.rs
@@ -31,7 +31,7 @@ use rustc_infer::infer::resolve::OpportunisticRegionResolver;
use rustc_infer::traits::ImplSourceBuiltinData;
use rustc_middle::traits::select::OverflowError;
use rustc_middle::ty::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable};
-use rustc_middle::ty::visit::{MaxUniverse, TypeVisitable};
+use rustc_middle::ty::visit::{MaxUniverse, TypeVisitable, TypeVisitableExt};
use rustc_middle::ty::DefIdTree;
use rustc_middle::ty::{self, Term, ToPredicate, Ty, TyCtxt};
use rustc_span::symbol::sym;
@@ -53,11 +53,11 @@ pub trait NormalizeExt<'tcx> {
///
/// This normalization should be used when the type contains inference variables or the
/// projection may be fallible.
- fn normalize<T: TypeFoldable<'tcx>>(&self, t: T) -> InferOk<'tcx, T>;
+ fn normalize<T: TypeFoldable<TyCtxt<'tcx>>>(&self, t: T) -> InferOk<'tcx, T>;
}
impl<'tcx> NormalizeExt<'tcx> for At<'_, 'tcx> {
- fn normalize<T: TypeFoldable<'tcx>>(&self, value: T) -> InferOk<'tcx, T> {
+ fn normalize<T: TypeFoldable<TyCtxt<'tcx>>>(&self, value: T) -> InferOk<'tcx, T> {
let mut selcx = SelectionContext::new(self.infcx);
let Normalized { value, obligations } =
normalize_with_depth(&mut selcx, self.param_env, self.cause.clone(), 0, value);
@@ -90,15 +90,7 @@ enum ProjectionCandidate<'tcx> {
/// From an "impl" (or a "pseudo-impl" returned by select)
Select(Selection<'tcx>),
- ImplTraitInTrait(ImplTraitInTraitCandidate<'tcx>),
-}
-
-#[derive(PartialEq, Eq, Debug)]
-enum ImplTraitInTraitCandidate<'tcx> {
- // The `impl Trait` from a trait function's default body
- Trait,
- // A concrete type provided from a trait's `impl Trait` from an impl
- Impl(ImplSourceUserDefinedData<'tcx, PredicateObligation<'tcx>>),
+ ImplTraitInTrait(ImplSourceUserDefinedData<'tcx, PredicateObligation<'tcx>>),
}
enum ProjectionCandidateSet<'tcx> {
@@ -215,7 +207,7 @@ pub(super) fn poly_project_and_unify_type<'cx, 'tcx>(
let r = infcx.commit_if_ok(|_snapshot| {
let old_universe = infcx.universe();
let placeholder_predicate =
- infcx.replace_bound_vars_with_placeholders(obligation.predicate);
+ infcx.instantiate_binder_with_placeholders(obligation.predicate);
let new_universe = infcx.universe();
let placeholder_obligation = obligation.with(infcx.tcx, placeholder_predicate);
@@ -294,7 +286,12 @@ fn project_and_unify_type<'cx, 'tcx>(
);
obligations.extend(new);
- match infcx.at(&obligation.cause, obligation.param_env).eq(normalized, actual) {
+ match infcx
+ .at(&obligation.cause, obligation.param_env)
+ // This is needed to support nested opaque types like `impl Fn() -> impl Trait`
+ .define_opaque_types(true)
+ .eq(normalized, actual)
+ {
Ok(InferOk { obligations: inferred_obligations, value: () }) => {
obligations.extend(inferred_obligations);
ProjectAndUnifyResult::Holds(obligations)
@@ -315,7 +312,7 @@ pub(crate) fn normalize_with_depth<'a, 'b, 'tcx, T>(
value: T,
) -> Normalized<'tcx, T>
where
- T: TypeFoldable<'tcx>,
+ T: TypeFoldable<TyCtxt<'tcx>>,
{
let mut obligations = Vec::new();
let value = normalize_with_depth_to(selcx, param_env, cause, depth, value, &mut obligations);
@@ -332,7 +329,7 @@ pub(crate) fn normalize_with_depth_to<'a, 'b, 'tcx, T>(
obligations: &mut Vec<PredicateObligation<'tcx>>,
) -> T
where
- T: TypeFoldable<'tcx>,
+ T: TypeFoldable<TyCtxt<'tcx>>,
{
debug!(obligations.len = obligations.len());
let mut normalizer = AssocTypeNormalizer::new(selcx, param_env, cause, depth, obligations);
@@ -352,7 +349,7 @@ pub(crate) fn try_normalize_with_depth_to<'a, 'b, 'tcx, T>(
obligations: &mut Vec<PredicateObligation<'tcx>>,
) -> T
where
- T: TypeFoldable<'tcx>,
+ T: TypeFoldable<TyCtxt<'tcx>>,
{
debug!(obligations.len = obligations.len());
let mut normalizer = AssocTypeNormalizer::new_without_eager_inference_replacement(
@@ -368,7 +365,10 @@ where
result
}
-pub(crate) fn needs_normalization<'tcx, T: TypeVisitable<'tcx>>(value: &T, reveal: Reveal) -> bool {
+pub(crate) fn needs_normalization<'tcx, T: TypeVisitable<TyCtxt<'tcx>>>(
+ value: &T,
+ reveal: Reveal,
+) -> bool {
match reveal {
Reveal::UserFacing => value
.has_type_flags(ty::TypeFlags::HAS_TY_PROJECTION | ty::TypeFlags::HAS_CT_PROJECTION),
@@ -430,7 +430,7 @@ impl<'a, 'b, 'tcx> AssocTypeNormalizer<'a, 'b, 'tcx> {
}
}
- fn fold<T: TypeFoldable<'tcx>>(&mut self, value: T) -> T {
+ fn fold<T: TypeFoldable<TyCtxt<'tcx>>>(&mut self, value: T) -> T {
let value = self.selcx.infcx.resolve_vars_if_possible(value);
debug!(?value);
@@ -448,12 +448,12 @@ impl<'a, 'b, 'tcx> AssocTypeNormalizer<'a, 'b, 'tcx> {
}
}
-impl<'a, 'b, 'tcx> TypeFolder<'tcx> for AssocTypeNormalizer<'a, 'b, 'tcx> {
- fn tcx<'c>(&'c self) -> TyCtxt<'tcx> {
+impl<'a, 'b, 'tcx> TypeFolder<TyCtxt<'tcx>> for AssocTypeNormalizer<'a, 'b, 'tcx> {
+ fn interner(&self) -> TyCtxt<'tcx> {
self.selcx.tcx()
}
- fn fold_binder<T: TypeFoldable<'tcx>>(
+ fn fold_binder<T: TypeFoldable<TyCtxt<'tcx>>>(
&mut self,
t: ty::Binder<'tcx, T>,
) -> ty::Binder<'tcx, T> {
@@ -503,7 +503,7 @@ impl<'a, 'b, 'tcx> TypeFolder<'tcx> for AssocTypeNormalizer<'a, 'b, 'tcx> {
Reveal::UserFacing => ty.super_fold_with(self),
Reveal::All => {
- let recursion_limit = self.tcx().recursion_limit();
+ let recursion_limit = self.interner().recursion_limit();
if !recursion_limit.value_within_limit(self.depth) {
self.selcx.infcx.err_ctxt().report_overflow_error(
&ty,
@@ -514,8 +514,8 @@ impl<'a, 'b, 'tcx> TypeFolder<'tcx> for AssocTypeNormalizer<'a, 'b, 'tcx> {
}
let substs = substs.fold_with(self);
- let generic_ty = self.tcx().bound_type_of(def_id);
- let concrete_ty = generic_ty.subst(self.tcx(), substs);
+ let generic_ty = self.interner().type_of(def_id);
+ let concrete_ty = generic_ty.subst(self.interner(), substs);
self.depth += 1;
let folded_ty = self.fold_ty(concrete_ty);
self.depth -= 1;
@@ -672,7 +672,12 @@ pub struct BoundVarReplacer<'me, 'tcx> {
///
/// FIXME(@lcnr): We may even consider experimenting with eagerly replacing bound vars during
/// normalization as well, at which point this function will be unnecessary and can be removed.
-pub fn with_replaced_escaping_bound_vars<'a, 'tcx, T: TypeFoldable<'tcx>, R: TypeFoldable<'tcx>>(
+pub fn with_replaced_escaping_bound_vars<
+ 'a,
+ 'tcx,
+ T: TypeFoldable<TyCtxt<'tcx>>,
+ R: TypeFoldable<TyCtxt<'tcx>>,
+>(
infcx: &'a InferCtxt<'tcx>,
universe_indices: &'a mut Vec<Option<ty::UniverseIndex>>,
value: T,
@@ -698,7 +703,7 @@ pub fn with_replaced_escaping_bound_vars<'a, 'tcx, T: TypeFoldable<'tcx>, R: Typ
impl<'me, 'tcx> BoundVarReplacer<'me, 'tcx> {
/// Returns `Some` if we *were* able to replace bound vars. If there are any bound vars that
/// use a binding level above `universe_indices.len()`, we fail.
- pub fn replace_bound_vars<T: TypeFoldable<'tcx>>(
+ pub fn replace_bound_vars<T: TypeFoldable<TyCtxt<'tcx>>>(
infcx: &'me InferCtxt<'tcx>,
universe_indices: &'me mut Vec<Option<ty::UniverseIndex>>,
value: T,
@@ -740,12 +745,12 @@ impl<'me, 'tcx> BoundVarReplacer<'me, 'tcx> {
}
}
-impl<'tcx> TypeFolder<'tcx> for BoundVarReplacer<'_, 'tcx> {
- fn tcx<'b>(&'b self) -> TyCtxt<'tcx> {
+impl<'tcx> TypeFolder<TyCtxt<'tcx>> for BoundVarReplacer<'_, 'tcx> {
+ fn interner(&self) -> TyCtxt<'tcx> {
self.infcx.tcx
}
- fn fold_binder<T: TypeFoldable<'tcx>>(
+ fn fold_binder<T: TypeFoldable<TyCtxt<'tcx>>>(
&mut self,
t: ty::Binder<'tcx, T>,
) -> ty::Binder<'tcx, T> {
@@ -767,7 +772,7 @@ impl<'tcx> TypeFolder<'tcx> for BoundVarReplacer<'_, 'tcx> {
let universe = self.universe_for(debruijn);
let p = ty::PlaceholderRegion { universe, name: br.kind };
self.mapped_regions.insert(p, br);
- self.infcx.tcx.mk_region(ty::RePlaceholder(p))
+ self.infcx.tcx.mk_re_placeholder(p)
}
_ => r,
}
@@ -783,9 +788,9 @@ impl<'tcx> 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 };
+ let p = ty::PlaceholderType { universe, name: bound_ty.kind };
self.mapped_types.insert(p, bound_ty);
- self.infcx.tcx.mk_ty(ty::Placeholder(p))
+ self.infcx.tcx.mk_placeholder(p)
}
_ if t.has_vars_bound_at_or_above(self.current_index) => t.super_fold_with(self),
_ => t,
@@ -826,7 +831,7 @@ pub struct PlaceholderReplacer<'me, 'tcx> {
}
impl<'me, 'tcx> PlaceholderReplacer<'me, 'tcx> {
- pub fn replace_placeholders<T: TypeFoldable<'tcx>>(
+ pub fn replace_placeholders<T: TypeFoldable<TyCtxt<'tcx>>>(
infcx: &'me InferCtxt<'tcx>,
mapped_regions: BTreeMap<ty::PlaceholderRegion, ty::BoundRegion>,
mapped_types: BTreeMap<ty::PlaceholderType, ty::BoundTy>,
@@ -846,12 +851,12 @@ impl<'me, 'tcx> PlaceholderReplacer<'me, 'tcx> {
}
}
-impl<'tcx> TypeFolder<'tcx> for PlaceholderReplacer<'_, 'tcx> {
- fn tcx<'b>(&'b self) -> TyCtxt<'tcx> {
+impl<'tcx> TypeFolder<TyCtxt<'tcx>> for PlaceholderReplacer<'_, 'tcx> {
+ fn interner(&self) -> TyCtxt<'tcx> {
self.infcx.tcx
}
- fn fold_binder<T: TypeFoldable<'tcx>>(
+ fn fold_binder<T: TypeFoldable<TyCtxt<'tcx>>>(
&mut self,
t: ty::Binder<'tcx, T>,
) -> ty::Binder<'tcx, T> {
@@ -888,7 +893,7 @@ impl<'tcx> TypeFolder<'tcx> for PlaceholderReplacer<'_, 'tcx> {
let db = ty::DebruijnIndex::from_usize(
self.universe_indices.len() - index + self.current_index.as_usize() - 1,
);
- self.tcx().mk_region(ty::ReLateBound(db, *replace_var))
+ self.interner().mk_re_late_bound(db, *replace_var)
}
None => r1,
}
@@ -915,7 +920,7 @@ impl<'tcx> TypeFolder<'tcx> for PlaceholderReplacer<'_, 'tcx> {
let db = ty::DebruijnIndex::from_usize(
self.universe_indices.len() - index + self.current_index.as_usize() - 1,
);
- self.tcx().mk_ty(ty::Bound(db, *replace_var))
+ self.interner().mk_bound(db, *replace_var)
}
None => ty,
}
@@ -939,7 +944,7 @@ impl<'tcx> TypeFolder<'tcx> for PlaceholderReplacer<'_, 'tcx> {
let db = ty::DebruijnIndex::from_usize(
self.universe_indices.len() - index + self.current_index.as_usize() - 1,
);
- self.tcx().mk_const(ty::ConstKind::Bound(db, *replace_var), ct.ty())
+ self.interner().mk_const(ty::ConstKind::Bound(db, *replace_var), ct.ty())
}
None => ct,
}
@@ -1170,7 +1175,7 @@ fn opt_normalize_projection_type<'a, 'b, 'tcx>(
/// paths you want to take. To make things worse, it was possible for
/// cycles to arise, where you basically had a setup like `<MyType<$0>
/// as Trait>::Foo == $0`. Here, normalizing `<MyType<$0> as
-/// Trait>::Foo> to `[type error]` would lead to an obligation of
+/// Trait>::Foo>` to `[type error]` would lead to an obligation of
/// `<MyType<[type error]> as Trait>::Foo`. We are supposed to report
/// an error for this obligation, but we legitimately should not,
/// because it contains `[type error]`. Yuck! (See issue #29857 for
@@ -1208,8 +1213,8 @@ struct Progress<'tcx> {
}
impl<'tcx> Progress<'tcx> {
- fn error(tcx: TyCtxt<'tcx>) -> Self {
- Progress { term: tcx.ty_error().into(), obligations: vec![] }
+ fn error(tcx: TyCtxt<'tcx>, guar: ErrorGuaranteed) -> Self {
+ Progress { term: tcx.ty_error(guar).into(), obligations: vec![] }
}
fn with_addl_obligations(mut self, mut obligations: Vec<PredicateObligation<'tcx>>) -> Self {
@@ -1235,8 +1240,8 @@ fn project<'cx, 'tcx>(
)));
}
- if obligation.predicate.references_error() {
- return Ok(Projected::Progress(Progress::error(selcx.tcx())));
+ if let Err(guar) = obligation.predicate.error_reported() {
+ return Ok(Projected::Progress(Progress::error(selcx.tcx(), guar)));
}
let mut candidates = ProjectionCandidateSet::None;
@@ -1292,17 +1297,6 @@ fn assemble_candidate_for_impl_trait_in_trait<'cx, 'tcx>(
let tcx = selcx.tcx();
if tcx.def_kind(obligation.predicate.def_id) == DefKind::ImplTraitPlaceholder {
let trait_fn_def_id = tcx.impl_trait_in_trait_parent(obligation.predicate.def_id);
- // If we are trying to project an RPITIT with trait's default `Self` parameter,
- // then we must be within a default trait body.
- if obligation.predicate.self_ty()
- == ty::InternalSubsts::identity_for_item(tcx, obligation.predicate.def_id).type_at(0)
- && tcx.associated_item(trait_fn_def_id).defaultness(tcx).has_value()
- {
- candidate_set.push_candidate(ProjectionCandidate::ImplTraitInTrait(
- ImplTraitInTraitCandidate::Trait,
- ));
- return;
- }
let trait_def_id = tcx.parent(trait_fn_def_id);
let trait_substs =
@@ -1313,23 +1307,21 @@ fn assemble_candidate_for_impl_trait_in_trait<'cx, 'tcx>(
let _ = selcx.infcx.commit_if_ok(|_| {
match selcx.select(&obligation.with(tcx, trait_predicate)) {
Ok(Some(super::ImplSource::UserDefined(data))) => {
- candidate_set.push_candidate(ProjectionCandidate::ImplTraitInTrait(
- ImplTraitInTraitCandidate::Impl(data),
- ));
+ candidate_set.push_candidate(ProjectionCandidate::ImplTraitInTrait(data));
Ok(())
}
Ok(None) => {
candidate_set.mark_ambiguous();
- return Err(());
+ Err(())
}
Ok(Some(_)) => {
// Don't know enough about the impl to provide a useful signature
- return Err(());
+ Err(())
}
Err(e) => {
debug!(error = ?e, "selection error");
candidate_set.mark_error(e);
- return Err(());
+ Err(())
}
}
});
@@ -1605,6 +1597,7 @@ fn assemble_candidates_from_impls<'cx, 'tcx>(
| ty::Closure(..)
| ty::Generator(..)
| ty::GeneratorWitness(..)
+ | ty::GeneratorWitnessMIR(..)
| ty::Never
| ty::Tuple(..)
// Integers and floats always have `u8` as their discriminant.
@@ -1654,6 +1647,7 @@ fn assemble_candidates_from_impls<'cx, 'tcx>(
| ty::Closure(..)
| ty::Generator(..)
| ty::GeneratorWitness(..)
+ | ty::GeneratorWitnessMIR(..)
| ty::Never
// Extern types have unit metadata, according to RFC 2850
| ty::Foreign(_)
@@ -1775,18 +1769,9 @@ fn confirm_candidate<'cx, 'tcx>(
ProjectionCandidate::Select(impl_source) => {
confirm_select_candidate(selcx, obligation, impl_source)
}
- ProjectionCandidate::ImplTraitInTrait(ImplTraitInTraitCandidate::Impl(data)) => {
+ ProjectionCandidate::ImplTraitInTrait(data) => {
confirm_impl_trait_in_trait_candidate(selcx, obligation, data)
}
- // If we're projecting an RPITIT for a default trait body, that's just
- // the same def-id, but as an opaque type (with regular RPIT semantics).
- ProjectionCandidate::ImplTraitInTrait(ImplTraitInTraitCandidate::Trait) => Progress {
- term: selcx
- .tcx()
- .mk_opaque(obligation.predicate.def_id, obligation.predicate.substs)
- .into(),
- obligations: vec![],
- },
};
// When checking for cycle during evaluation, we compare predicates with
@@ -1921,7 +1906,7 @@ fn confirm_builtin_candidate<'cx, 'tcx>(
) -> Progress<'tcx> {
let tcx = selcx.tcx();
let self_ty = obligation.predicate.self_ty();
- let substs = tcx.mk_substs([self_ty.into()].iter());
+ let substs = tcx.mk_substs(&[self_ty.into()]);
let lang_items = tcx.lang_items();
let item_def_id = obligation.predicate.def_id;
let trait_def_id = tcx.trait_of_item(item_def_id).unwrap();
@@ -2044,7 +2029,7 @@ fn confirm_param_env_candidate<'cx, 'tcx>(
let cause = &obligation.cause;
let param_env = obligation.param_env;
- let cache_entry = infcx.replace_bound_vars_with_fresh_vars(
+ let cache_entry = infcx.instantiate_binder_with_fresh_vars(
cause.span,
LateBoundRegionConversionTime::HigherRankedType,
poly_cache_entry,
@@ -2112,8 +2097,9 @@ fn confirm_impl_candidate<'cx, 'tcx>(
let trait_def_id = tcx.trait_id_of_impl(impl_def_id).unwrap();
let param_env = obligation.param_env;
- let Ok(assoc_ty) = specialization_graph::assoc_def(tcx, impl_def_id, assoc_item_id) else {
- return Progress { term: tcx.ty_error().into(), obligations: nested };
+ let assoc_ty = match specialization_graph::assoc_def(tcx, impl_def_id, assoc_item_id) {
+ Ok(assoc_ty) => assoc_ty,
+ Err(guar) => return Progress::error(tcx, guar),
};
if !assoc_ty.item.defaultness(tcx).has_value() {
@@ -2125,7 +2111,7 @@ fn confirm_impl_candidate<'cx, 'tcx>(
"confirm_impl_candidate: no associated type {:?} for {:?}",
assoc_ty.item.name, obligation.predicate
);
- return Progress { term: tcx.ty_error().into(), obligations: nested };
+ return Progress { term: tcx.ty_error_misc().into(), obligations: nested };
}
// If we're trying to normalize `<Vec<u32> as X>::A<S>` using
//`impl<T> X for Vec<T> { type A<Y> = Box<Y>; }`, then:
@@ -2136,7 +2122,7 @@ fn confirm_impl_candidate<'cx, 'tcx>(
let substs = obligation.predicate.substs.rebase_onto(tcx, trait_def_id, substs);
let substs =
translate_substs(selcx.infcx, param_env, impl_def_id, substs, assoc_ty.defining_node);
- let ty = tcx.bound_type_of(assoc_ty.item.def_id);
+ let ty = tcx.type_of(assoc_ty.item.def_id);
let is_const = matches!(tcx.def_kind(assoc_ty.item.def_id), DefKind::AssocConst);
let term: ty::EarlyBinder<ty::Term<'tcx>> = if is_const {
let identity_substs =
@@ -2147,7 +2133,7 @@ fn confirm_impl_candidate<'cx, 'tcx>(
} else {
ty.map_bound(|ty| ty.into())
};
- if !check_substs_compatible(tcx, &assoc_ty.item, substs) {
+ if !check_substs_compatible(tcx, assoc_ty.item, substs) {
let err = tcx.ty_error_with_message(
obligation.cause.span,
"impl item and trait item have different parameters",
@@ -2162,7 +2148,7 @@ fn confirm_impl_candidate<'cx, 'tcx>(
// Verify that the trait item and its implementation have compatible substs lists
fn check_substs_compatible<'tcx>(
tcx: TyCtxt<'tcx>,
- assoc_item: &ty::AssocItem,
+ assoc_item: ty::AssocItem,
substs: ty::SubstsRef<'tcx>,
) -> bool {
fn check_substs_compatible_inner<'tcx>(
@@ -2209,11 +2195,13 @@ fn confirm_impl_trait_in_trait_candidate<'tcx>(
let mut obligations = data.nested;
let trait_fn_def_id = tcx.impl_trait_in_trait_parent(obligation.predicate.def_id);
- let Ok(leaf_def) = specialization_graph::assoc_def(tcx, data.impl_def_id, trait_fn_def_id) else {
- return Progress { term: tcx.ty_error().into(), obligations };
+ let leaf_def = match specialization_graph::assoc_def(tcx, data.impl_def_id, trait_fn_def_id) {
+ Ok(assoc_ty) => assoc_ty,
+ Err(guar) => return Progress::error(tcx, guar),
};
- if !leaf_def.item.defaultness(tcx).has_value() {
- return Progress { term: tcx.ty_error().into(), obligations };
+ // We don't support specialization for RPITITs anyways... yet.
+ if !leaf_def.is_final() {
+ return Progress { term: tcx.ty_error_misc().into(), obligations };
}
// Use the default `impl Trait` for the trait, e.g., for a default trait body
@@ -2236,7 +2224,7 @@ fn confirm_impl_trait_in_trait_candidate<'tcx>(
leaf_def.defining_node,
);
- if !check_substs_compatible(tcx, &leaf_def.item, impl_fn_substs) {
+ if !check_substs_compatible(tcx, leaf_def.item, impl_fn_substs) {
let err = tcx.ty_error_with_message(
obligation.cause.span,
"impl method and trait method have different parameters",
@@ -2284,7 +2272,7 @@ fn confirm_impl_trait_in_trait_candidate<'tcx>(
obligation.recursion_depth + 1,
tcx.bound_return_position_impl_trait_in_trait_tys(impl_fn_def_id)
.map_bound(|tys| {
- tys.map_or_else(|_| tcx.ty_error(), |tys| tys[&obligation.predicate.def_id])
+ tys.map_or_else(|guar| tcx.ty_error(guar), |tys| tys[&obligation.predicate.def_id])
})
.subst(tcx, impl_fn_substs),
&mut obligations,
diff --git a/compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs b/compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs
index 0f21813bc..455b53bfb 100644
--- a/compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs
+++ b/compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs
@@ -31,6 +31,7 @@ pub fn trivial_dropck_outlives<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> bool {
| ty::FnPtr(_)
| ty::Char
| ty::GeneratorWitness(..)
+ | ty::GeneratorWitnessMIR(..)
| ty::RawPtr(_)
| ty::Ref(..)
| ty::Str
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 09b58894d..f183248f2 100644
--- a/compiler/rustc_trait_selection/src/traits/query/evaluate_obligation.rs
+++ b/compiler/rustc_trait_selection/src/traits/query/evaluate_obligation.rs
@@ -1,7 +1,9 @@
use rustc_middle::ty;
+use rustc_session::config::TraitSolver;
use crate::infer::canonical::OriginalQueryValues;
use crate::infer::InferCtxt;
+use crate::solve::{Certainty, Goal, InferCtxtEvalExt, MaybeCause};
use crate::traits::{EvaluationResult, OverflowError, PredicateObligation, SelectionContext};
pub trait InferCtxtExt<'tcx> {
@@ -77,12 +79,38 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> {
_ => obligation.param_env.without_const(),
};
- let c_pred = self
- .canonicalize_query_keep_static(param_env.and(obligation.predicate), &mut _orig_values);
- // Run canonical query. If overflow occurs, rerun from scratch but this time
- // in standard trait query mode so that overflow is handled appropriately
- // within `SelectionContext`.
- self.tcx.at(obligation.cause.span()).evaluate_obligation(c_pred)
+ if self.tcx.sess.opts.unstable_opts.trait_solver != TraitSolver::Next {
+ let c_pred = self.canonicalize_query_keep_static(
+ param_env.and(obligation.predicate),
+ &mut _orig_values,
+ );
+ self.tcx.at(obligation.cause.span()).evaluate_obligation(c_pred)
+ } else {
+ self.probe(|snapshot| {
+ if let Ok((_, certainty)) =
+ self.evaluate_root_goal(Goal::new(self.tcx, param_env, obligation.predicate))
+ {
+ match certainty {
+ Certainty::Yes => {
+ if self.opaque_types_added_in_snapshot(snapshot) {
+ Ok(EvaluationResult::EvaluatedToOkModuloOpaqueTypes)
+ } else if self.region_constraints_added_in_snapshot(snapshot).is_some()
+ {
+ Ok(EvaluationResult::EvaluatedToOkModuloRegions)
+ } else {
+ Ok(EvaluationResult::EvaluatedToOk)
+ }
+ }
+ Certainty::Maybe(MaybeCause::Ambiguity) => {
+ Ok(EvaluationResult::EvaluatedToAmbig)
+ }
+ Certainty::Maybe(MaybeCause::Overflow) => Err(OverflowError::Canonical),
+ }
+ } else {
+ Ok(EvaluationResult::EvaluatedToErr)
+ }
+ })
+ }
}
// Helper function that canonicalizes and runs the query. If an
@@ -92,6 +120,9 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> {
&self,
obligation: &PredicateObligation<'tcx>,
) -> EvaluationResult {
+ // Run canonical query. If overflow occurs, rerun from scratch but this time
+ // in standard trait query mode so that overflow is handled appropriately
+ // within `SelectionContext`.
match self.evaluate_obligation(obligation) {
Ok(result) => result,
Err(OverflowError::Canonical) => {
diff --git a/compiler/rustc_trait_selection/src/traits/query/normalize.rs b/compiler/rustc_trait_selection/src/traits/query/normalize.rs
index 27247271d..b0cec3ce7 100644
--- a/compiler/rustc_trait_selection/src/traits/query/normalize.rs
+++ b/compiler/rustc_trait_selection/src/traits/query/normalize.rs
@@ -12,7 +12,7 @@ use rustc_data_structures::sso::SsoHashMap;
use rustc_data_structures::stack::ensure_sufficient_stack;
use rustc_infer::traits::Normalized;
use rustc_middle::ty::fold::{FallibleTypeFolder, TypeFoldable, TypeSuperFoldable};
-use rustc_middle::ty::visit::{TypeSuperVisitable, TypeVisitable};
+use rustc_middle::ty::visit::{TypeSuperVisitable, TypeVisitable, TypeVisitableExt};
use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitor};
use rustc_span::DUMMY_SP;
@@ -32,7 +32,7 @@ pub trait QueryNormalizeExt<'tcx> {
/// use [`TyCtxt::normalize_erasing_regions`], which wraps this procedure.
fn query_normalize<T>(&self, value: T) -> Result<Normalized<'tcx, T>, NoSolution>
where
- T: TypeFoldable<'tcx>;
+ T: TypeFoldable<TyCtxt<'tcx>>;
}
impl<'cx, 'tcx> QueryNormalizeExt<'tcx> for At<'cx, 'tcx> {
@@ -51,7 +51,7 @@ impl<'cx, 'tcx> QueryNormalizeExt<'tcx> for At<'cx, 'tcx> {
/// and other details are still "under development".
fn query_normalize<T>(&self, value: T) -> Result<Normalized<'tcx, T>, NoSolution>
where
- T: TypeFoldable<'tcx>,
+ T: TypeFoldable<TyCtxt<'tcx>>,
{
debug!(
"normalize::<{}>(value={:?}, param_env={:?}, cause={:?})",
@@ -115,8 +115,8 @@ struct MaxEscapingBoundVarVisitor {
escaping: usize,
}
-impl<'tcx> TypeVisitor<'tcx> for MaxEscapingBoundVarVisitor {
- fn visit_binder<T: TypeVisitable<'tcx>>(
+impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for MaxEscapingBoundVarVisitor {
+ fn visit_binder<T: TypeVisitable<TyCtxt<'tcx>>>(
&mut self,
t: &ty::Binder<'tcx, T>,
) -> ControlFlow<Self::BreakTy> {
@@ -170,14 +170,14 @@ struct QueryNormalizer<'cx, 'tcx> {
universes: Vec<Option<ty::UniverseIndex>>,
}
-impl<'cx, 'tcx> FallibleTypeFolder<'tcx> for QueryNormalizer<'cx, 'tcx> {
+impl<'cx, 'tcx> FallibleTypeFolder<TyCtxt<'tcx>> for QueryNormalizer<'cx, 'tcx> {
type Error = NoSolution;
- fn tcx<'c>(&'c self) -> TyCtxt<'tcx> {
+ fn interner(&self) -> TyCtxt<'tcx> {
self.infcx.tcx
}
- fn try_fold_binder<T: TypeFoldable<'tcx>>(
+ fn try_fold_binder<T: TypeFoldable<TyCtxt<'tcx>>>(
&mut self,
t: ty::Binder<'tcx, T>,
) -> Result<ty::Binder<'tcx, T>, Self::Error> {
@@ -214,18 +214,22 @@ impl<'cx, 'tcx> FallibleTypeFolder<'tcx> for QueryNormalizer<'cx, 'tcx> {
Reveal::All => {
let substs = substs.try_fold_with(self)?;
- let recursion_limit = self.tcx().recursion_limit();
+ let recursion_limit = self.interner().recursion_limit();
if !recursion_limit.value_within_limit(self.anon_depth) {
- self.infcx.err_ctxt().report_overflow_error(
- &ty,
- self.cause.span,
- true,
- |_| {},
- );
+ // A closure or generator may have itself as in its upvars.
+ // This should be checked handled by the recursion check for opaque
+ // types, but we may end up here before that check can happen.
+ // In that case, we delay a bug to mark the trip, and continue without
+ // revealing the opaque.
+ self.infcx
+ .err_ctxt()
+ .build_overflow_error(&ty, self.cause.span, true)
+ .delay_as_bug();
+ return ty.try_super_fold_with(self);
}
- let generic_ty = self.tcx().bound_type_of(def_id);
- let concrete_ty = generic_ty.subst(self.tcx(), substs);
+ let generic_ty = self.interner().type_of(def_id);
+ let concrete_ty = generic_ty.subst(self.interner(), substs);
self.anon_depth += 1;
if concrete_ty == ty {
bug!(
diff --git a/compiler/rustc_trait_selection/src/traits/query/type_op/mod.rs b/compiler/rustc_trait_selection/src/traits/query/type_op/mod.rs
index 97002b461..9e8bc8bce 100644
--- a/compiler/rustc_trait_selection/src/traits/query/type_op/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/query/type_op/mod.rs
@@ -54,8 +54,8 @@ pub struct TypeOpOutput<'tcx, Op: TypeOp<'tcx>> {
/// which produces the resulting query region constraints.
///
/// [c]: https://rust-lang.github.io/chalk/book/canonical_queries/canonicalization.html
-pub trait QueryTypeOp<'tcx>: fmt::Debug + Copy + TypeFoldable<'tcx> + 'tcx {
- type QueryResponse: TypeFoldable<'tcx>;
+pub trait QueryTypeOp<'tcx>: fmt::Debug + Copy + TypeFoldable<TyCtxt<'tcx>> + 'tcx {
+ type QueryResponse: TypeFoldable<TyCtxt<'tcx>>;
/// Give query the option for a simple fast path that never
/// actually hits the tcx cache lookup etc. Return `Some(r)` with
diff --git a/compiler/rustc_trait_selection/src/traits/query/type_op/normalize.rs b/compiler/rustc_trait_selection/src/traits/query/type_op/normalize.rs
index 8f0b4de31..5b216c076 100644
--- a/compiler/rustc_trait_selection/src/traits/query/type_op/normalize.rs
+++ b/compiler/rustc_trait_selection/src/traits/query/type_op/normalize.rs
@@ -1,7 +1,7 @@
use crate::infer::canonical::{Canonical, CanonicalQueryResponse};
use crate::traits::query::Fallible;
use rustc_middle::ty::fold::TypeFoldable;
-use rustc_middle::ty::{self, Lift, ParamEnvAnd, Ty, TyCtxt};
+use rustc_middle::ty::{self, Lift, ParamEnvAnd, Ty, TyCtxt, TypeVisitableExt};
use std::fmt;
pub use rustc_middle::traits::query::type_op::Normalize;
@@ -24,7 +24,7 @@ where
}
}
-pub trait Normalizable<'tcx>: fmt::Debug + TypeFoldable<'tcx> + Lift<'tcx> + Copy {
+pub trait Normalizable<'tcx>: fmt::Debug + TypeFoldable<TyCtxt<'tcx>> + Lift<'tcx> + Copy {
fn type_op_method(
tcx: TyCtxt<'tcx>,
canonicalized: Canonical<'tcx, ParamEnvAnd<'tcx, Normalize<Self>>>,
diff --git a/compiler/rustc_trait_selection/src/traits/query/type_op/outlives.rs b/compiler/rustc_trait_selection/src/traits/query/type_op/outlives.rs
index 0d42cd825..21ef4e24f 100644
--- a/compiler/rustc_trait_selection/src/traits/query/type_op/outlives.rs
+++ b/compiler/rustc_trait_selection/src/traits/query/type_op/outlives.rs
@@ -21,11 +21,7 @@ impl<'tcx> super::QueryTypeOp<'tcx> for DropckOutlives<'tcx> {
tcx: TyCtxt<'tcx>,
key: &ParamEnvAnd<'tcx, Self>,
) -> Option<Self::QueryResponse> {
- if trivial_dropck_outlives(tcx, key.value.dropped_ty) {
- Some(DropckOutlivesResult::default())
- } else {
- None
- }
+ trivial_dropck_outlives(tcx, key.value.dropped_ty).then(DropckOutlivesResult::default)
}
fn perform_query(
diff --git a/compiler/rustc_trait_selection/src/traits/relationships.rs b/compiler/rustc_trait_selection/src/traits/relationships.rs
deleted file mode 100644
index 34b5fc489..000000000
--- a/compiler/rustc_trait_selection/src/traits/relationships.rs
+++ /dev/null
@@ -1,48 +0,0 @@
-use crate::infer::InferCtxt;
-use crate::traits::query::evaluate_obligation::InferCtxtExt;
-use crate::traits::PredicateObligation;
-use rustc_infer::traits::TraitEngine;
-use rustc_middle::ty;
-
-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::Clause(ty::Clause::Trait(tpred)) = obligation.predicate.kind().skip_binder()
- && let Some(ty) = infcx.shallow_resolve(tpred.self_ty()).ty_vid().map(|t| infcx.root_var(t))
- && infcx.tcx.lang_items().sized_trait().map_or(false, |st| st != tpred.trait_ref.def_id)
- {
- let new_self_ty = infcx.tcx.types.unit;
-
- // Then construct a new obligation with Self = () added
- // to the ParamEnv, and see if it holds.
- let o = obligation.with(infcx.tcx,
- obligation
- .predicate
- .kind()
- .rebind(
- // (*) binder moved here
- ty::PredicateKind::Clause(ty::Clause::Trait(tpred.with_self_ty(infcx.tcx, new_self_ty)))
- ),
- );
- // Don't report overflow errors. Otherwise equivalent to may_hold.
- if let Ok(result) = infcx.probe(|_| infcx.evaluate_obligation(&o)) && result.may_apply() {
- engine.relationships().entry(ty).or_default().self_in_trait = true;
- }
- }
-
- if let ty::PredicateKind::Clause(ty::Clause::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.term.ty().and_then(|ty| 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 2733d9643..e91057356 100644
--- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
@@ -9,7 +9,7 @@ use hir::LangItem;
use rustc_hir as hir;
use rustc_infer::traits::ObligationCause;
use rustc_infer::traits::{Obligation, SelectionError, TraitObligation};
-use rustc_middle::ty::{self, Ty, TypeVisitable};
+use rustc_middle::ty::{self, Ty, TypeVisitableExt};
use rustc_target::spec::abi::Abi;
use crate::traits;
@@ -94,7 +94,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
self.assemble_candidates_for_transmutability(obligation, &mut candidates);
} else if lang_items.tuple_trait() == Some(def_id) {
self.assemble_candidate_for_tuple(obligation, &mut candidates);
- } else if lang_items.pointer_sized() == Some(def_id) {
+ } else if lang_items.pointer_like() == Some(def_id) {
self.assemble_candidate_for_ptr_sized(obligation, &mut candidates);
} else {
if lang_items.clone_trait() == Some(def_id) {
@@ -174,8 +174,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
.param_env
.caller_bounds()
.iter()
- .filter_map(|p| p.to_opt_poly_trait_pred())
- .filter(|p| !p.references_error());
+ .filter(|p| !p.references_error())
+ .filter_map(|p| p.to_opt_poly_trait_pred());
// Micro-optimization: filter out predicates relating to different traits.
let matching_bounds =
@@ -339,7 +339,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
// Essentially any user-written impl will match with an error type,
// so creating `ImplCandidates` isn't useful. However, we might
- // end up finding a candidate elsewhere (e.g. a `BuiltinCandidate` for `Sized)
+ // end up finding a candidate elsewhere (e.g. a `BuiltinCandidate` for `Sized`)
// This helps us avoid overflow: see issue #72839
// Since compilation is already guaranteed to fail, this is just
// to try to show the 'nicest' possible errors to the user.
@@ -396,7 +396,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
// still be provided by a manual implementation for
// this trait and type.
}
- ty::Param(..) | ty::Alias(ty::Projection, ..) => {
+ ty::Param(..)
+ | ty::Alias(ty::Projection, ..)
+ | ty::Placeholder(..)
+ | ty::Bound(..) => {
// In these cases, we don't know what the actual
// type is. Therefore, we cannot break it down
// into its constituent types. So we don't
@@ -448,6 +451,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
);
self.infcx.probe(|_snapshot| {
+ if obligation.has_non_region_late_bound() {
+ return;
+ }
+
// The code below doesn't care about regions, and the
// self-ty here doesn't escape this probe, so just erase
// any LBR.
@@ -466,7 +473,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
if let Some(principal) = data.principal() {
if !self.infcx.tcx.features().object_safe_for_dispatch {
principal.with_self_ty(self.tcx(), self_ty)
- } else if self.tcx().is_object_safe(principal.def_id()) {
+ } else if self.tcx().check_is_object_safe(principal.def_id()) {
principal.with_self_ty(self.tcx(), self_ty)
} else {
return;
@@ -488,7 +495,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
let poly_trait_predicate = self.infcx.resolve_vars_if_possible(obligation.predicate);
let placeholder_trait_predicate =
- self.infcx.replace_bound_vars_with_placeholders(poly_trait_predicate);
+ self.infcx.instantiate_binder_with_placeholders(poly_trait_predicate);
// Count only those upcast versions that match the trait-ref
// we are looking for. Specifically, do not only check for the
@@ -765,7 +772,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
| ty::Closure(..)
| ty::Generator(..)
| ty::Tuple(_)
- | ty::GeneratorWitness(_) => {
+ | ty::GeneratorWitness(_)
+ | ty::GeneratorWitnessMIR(..) => {
// These are built-in, and cannot have a custom `impl const Destruct`.
candidates.vec.push(ConstDestructCandidate(None));
}
@@ -826,6 +834,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
| ty::Closure(_, _)
| ty::Generator(_, _, _)
| ty::GeneratorWitness(_)
+ | ty::GeneratorWitnessMIR(..)
| ty::Never
| ty::Alias(..)
| ty::Param(_)
diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
index 82a59831b..21c158fd0 100644
--- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
@@ -8,12 +8,11 @@
//! https://rustc-dev-guide.rust-lang.org/traits/resolution.html#confirmation
use rustc_data_structures::stack::ensure_sufficient_stack;
use rustc_hir::lang_items::LangItem;
-use rustc_index::bit_set::GrowableBitSet;
use rustc_infer::infer::InferOk;
use rustc_infer::infer::LateBoundRegionConversionTime::HigherRankedType;
use rustc_middle::ty::{
- self, Binder, GenericArg, GenericArgKind, GenericParamDefKind, InternalSubsts, SubstsRef,
- ToPolyTraitRef, ToPredicate, TraitRef, Ty, TyCtxt,
+ self, Binder, GenericParamDefKind, InternalSubsts, SubstsRef, ToPolyTraitRef, ToPredicate,
+ TraitRef, Ty, TyCtxt, TypeVisitableExt,
};
use rustc_session::config::TraitSolver;
use rustc_span::def_id::DefId;
@@ -152,7 +151,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
let trait_predicate = self.infcx.shallow_resolve(obligation.predicate);
let placeholder_trait_predicate =
- self.infcx.replace_bound_vars_with_placeholders(trait_predicate).trait_ref;
+ self.infcx.instantiate_binder_with_placeholders(trait_predicate).trait_ref;
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() {
@@ -337,7 +336,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
let cause = obligation.derived_cause(BuiltinDerivedObligation);
let poly_trait_ref = obligation.predicate.to_poly_trait_ref();
- let trait_ref = self.infcx.replace_bound_vars_with_placeholders(poly_trait_ref);
+ let trait_ref = self.infcx.instantiate_binder_with_placeholders(poly_trait_ref);
let trait_obligations: Vec<PredicateObligation<'_>> = self.impl_or_trait_obligations(
&cause,
obligation.recursion_depth + 1,
@@ -428,7 +427,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
let tcx = self.tcx();
debug!(?obligation, ?index, "confirm_object_candidate");
- let trait_predicate = self.infcx.replace_bound_vars_with_placeholders(obligation.predicate);
+ let trait_predicate = self.infcx.instantiate_binder_with_placeholders(obligation.predicate);
let self_ty = self.infcx.shallow_resolve(trait_predicate.self_ty());
let obligation_trait_ref = ty::Binder::dummy(trait_predicate.trait_ref);
let ty::Dynamic(data, ..) = *self_ty.kind() else {
@@ -438,7 +437,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
let object_trait_ref = data.principal().unwrap_or_else(|| {
span_bug!(obligation.cause.span, "object candidate with no principal")
});
- let object_trait_ref = self.infcx.replace_bound_vars_with_fresh_vars(
+ let object_trait_ref = self.infcx.instantiate_binder_with_fresh_vars(
obligation.cause.span,
HigherRankedType,
object_trait_ref,
@@ -525,29 +524,29 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
.kind
{
GenericParamDefKind::Type { .. } => {
- let kind = ty::BoundTyKind::Param(param.name);
+ let kind = ty::BoundTyKind::Param(param.def_id, param.name);
let bound_var = ty::BoundVariableKind::Ty(kind);
bound_vars.push(bound_var);
- tcx.mk_ty(ty::Bound(
+ tcx.mk_bound(
ty::INNERMOST,
ty::BoundTy {
var: ty::BoundVar::from_usize(bound_vars.len() - 1),
kind,
},
- ))
+ )
.into()
}
GenericParamDefKind::Lifetime => {
let kind = ty::BoundRegionKind::BrNamed(param.def_id, param.name);
let bound_var = ty::BoundVariableKind::Region(kind);
bound_vars.push(bound_var);
- tcx.mk_region(ty::ReLateBound(
+ tcx.mk_re_late_bound(
ty::INNERMOST,
ty::BoundRegion {
var: ty::BoundVar::from_usize(bound_vars.len() - 1),
kind,
},
- ))
+ )
.into()
}
GenericParamDefKind::Const { .. } => {
@@ -558,15 +557,15 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
ty::INNERMOST,
ty::BoundVar::from_usize(bound_vars.len() - 1),
),
- tcx.type_of(param.def_id),
+ tcx.type_of(param.def_id)
+ .no_bound_vars()
+ .expect("const parameter types cannot be generic"),
)
.into()
}
});
- let bound_vars = tcx.mk_bound_variable_kinds(bound_vars.into_iter());
- let assoc_ty_substs = tcx.intern_substs(&substs);
-
- let bound_vars = tcx.mk_bound_variable_kinds(bound_vars.into_iter());
+ let bound_vars = tcx.mk_bound_variable_kinds(&bound_vars);
+ let assoc_ty_substs = tcx.mk_substs(&substs);
let bound =
bound.map_bound(|b| b.kind().skip_binder()).subst(tcx, assoc_ty_substs);
tcx.mk_predicate(ty::Binder::bind_with_vars(bound, bound_vars))
@@ -630,7 +629,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
}
// Confirm the `type Output: Sized;` bound that is present on `FnOnce`
- let output_ty = self.infcx.replace_bound_vars_with_placeholders(sig.output());
+ let output_ty = self.infcx.instantiate_binder_with_placeholders(sig.output());
let output_ty = normalize_with_depth_to(
self,
obligation.param_env,
@@ -653,7 +652,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
debug!(?obligation, "confirm_trait_alias_candidate");
let alias_def_id = obligation.predicate.def_id();
- let predicate = self.infcx.replace_bound_vars_with_placeholders(obligation.predicate);
+ let predicate = self.infcx.instantiate_binder_with_placeholders(obligation.predicate);
let trait_ref = predicate.trait_ref;
let trait_def_id = trait_ref.def_id;
let substs = trait_ref.substs;
@@ -822,6 +821,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
self.infcx
.at(&obligation.cause, obligation.param_env)
+ // needed for tests/ui/type-alias-impl-trait/assoc-projection-ice.rs
+ .define_opaque_types(true)
.sup(obligation_trait_ref, expected_trait_ref)
.map(|InferOk { mut obligations, .. }| {
obligations.extend(nested);
@@ -879,7 +880,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
.map(ty::ExistentialPredicate::AutoTrait)
.map(ty::Binder::dummy),
);
- let existential_predicates = tcx.mk_poly_existential_predicates(iter);
+ let existential_predicates = tcx.mk_poly_existential_predicates_from_iter(iter);
let source_trait = tcx.mk_dynamic(existential_predicates, r_b, repr_a);
// Require that the traits involved in this upcast are **equal**;
@@ -978,7 +979,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
.map(ty::ExistentialPredicate::AutoTrait)
.map(ty::Binder::dummy),
);
- let existential_predicates = tcx.mk_poly_existential_predicates(iter);
+ let existential_predicates = tcx.mk_poly_existential_predicates_from_iter(iter);
let source_trait = tcx.mk_dynamic(existential_predicates, r_b, dyn_a);
// Require that the traits involved in this upcast are **equal**;
@@ -1009,7 +1010,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
// `T` -> `Trait`
(_, &ty::Dynamic(ref data, r, ty::Dyn)) => {
let mut object_dids = data.auto_traits().chain(data.principal_def_id());
- if let Some(did) = object_dids.find(|did| !tcx.is_object_safe(*did)) {
+ if let Some(did) = object_dids.find(|did| !tcx.check_is_object_safe(*did)) {
return Err(TraitNotObjectSafe(did));
}
@@ -1064,51 +1065,18 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
// `Struct<T>` -> `Struct<U>`
(&ty::Adt(def, substs_a), &ty::Adt(_, substs_b)) => {
- let maybe_unsizing_param_idx = |arg: GenericArg<'tcx>| match arg.unpack() {
- GenericArgKind::Type(ty) => match ty.kind() {
- ty::Param(p) => Some(p.index),
- _ => None,
- },
-
- // Lifetimes aren't allowed to change during unsizing.
- GenericArgKind::Lifetime(_) => None,
-
- GenericArgKind::Const(ct) => match ct.kind() {
- ty::ConstKind::Param(p) => Some(p.index),
- _ => None,
- },
- };
-
- // FIXME(eddyb) cache this (including computing `unsizing_params`)
- // by putting it in a query; it would only need the `DefId` as it
- // looks at declared field types, not anything substituted.
-
- // The last field of the structure has to exist and contain type/const parameters.
- let (tail_field, prefix_fields) =
- def.non_enum_variant().fields.split_last().ok_or(Unimplemented)?;
- let tail_field_ty = tcx.bound_type_of(tail_field.did);
-
- let mut unsizing_params = GrowableBitSet::new_empty();
- for arg in tail_field_ty.0.walk() {
- if let Some(i) = maybe_unsizing_param_idx(arg) {
- unsizing_params.insert(i);
- }
- }
-
- // Ensure none of the other fields mention the parameters used
- // in unsizing.
- for field in prefix_fields {
- for arg in tcx.type_of(field.did).walk() {
- if let Some(i) = maybe_unsizing_param_idx(arg) {
- unsizing_params.remove(i);
- }
- }
- }
-
+ let unsizing_params = tcx.unsizing_params_for_adt(def.did());
if unsizing_params.is_empty() {
return Err(Unimplemented);
}
+ let tail_field = def
+ .non_enum_variant()
+ .fields
+ .last()
+ .expect("expected unsized ADT to have a tail field");
+ let tail_field_ty = tcx.type_of(tail_field.did);
+
// Extract `TailField<T>` and `TailField<U>` from `Struct<T>` and `Struct<U>`,
// normalizing in the process, since `type_of` returns something directly from
// astconv (which means it's un-normalized).
@@ -1131,7 +1099,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
// Check that the source struct with the target's
// unsizing parameters is equal to the target.
- let substs = tcx.mk_substs(substs_a.iter().enumerate().map(|(i, k)| {
+ let substs = tcx.mk_substs_from_iter(substs_a.iter().enumerate().map(|(i, k)| {
if unsizing_params.contains(i as u32) { substs_b[i] } else { k }
}));
let new_struct = tcx.mk_adt(def, substs);
@@ -1163,7 +1131,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
// Check that the source tuple with the target's
// last element is equal to the target.
- let new_tuple = tcx.mk_tup(a_mid.iter().copied().chain(iter::once(b_last)));
+ let new_tuple =
+ tcx.mk_tup_from_iter(a_mid.iter().copied().chain(iter::once(b_last)));
let InferOk { obligations, .. } = self
.infcx
.at(&obligation.cause, obligation.param_env)
@@ -1223,7 +1192,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
let cause = obligation.derived_cause(|derived| {
ImplDerivedObligation(Box::new(ImplDerivedObligationCause {
derived,
- impl_def_id,
+ impl_or_alias_def_id: impl_def_id,
+ impl_def_predicate_index: None,
span: obligation.cause.span,
}))
});
@@ -1285,6 +1255,14 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
ty::GeneratorWitness(tys) => {
stack.extend(tcx.erase_late_bound_regions(tys).to_vec());
}
+ ty::GeneratorWitnessMIR(def_id, substs) => {
+ let tcx = self.tcx();
+ stack.extend(tcx.generator_hidden_types(def_id).map(|bty| {
+ let ty = bty.subst(tcx, substs);
+ debug_assert!(!ty.has_late_bound_regions());
+ ty
+ }))
+ }
// If we have a projection type, make sure to normalize it so we replace it
// with a fresh infer variable
diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs
index f90da95d5..7f454fbb3 100644
--- a/compiler/rustc_trait_selection/src/traits/select/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs
@@ -27,6 +27,7 @@ use super::{
use crate::infer::{InferCtxt, InferOk, TypeFreshener};
use crate::traits::error_reporting::TypeErrCtxtExt;
+use crate::traits::project::try_normalize_with_depth_to;
use crate::traits::project::ProjectAndUnifyResult;
use crate::traits::project::ProjectionCacheKeyExt;
use crate::traits::ProjectionCacheKey;
@@ -38,6 +39,8 @@ use rustc_errors::Diagnostic;
use rustc_hir as hir;
use rustc_hir::def_id::DefId;
use rustc_infer::infer::LateBoundRegionConversionTime;
+use rustc_infer::traits::TraitEngine;
+use rustc_infer::traits::TraitEngineExt;
use rustc_middle::dep_graph::{DepKind, DepNodeIndex};
use rustc_middle::mir::interpret::ErrorHandled;
use rustc_middle::ty::abstract_const::NotConstEvaluatable;
@@ -46,7 +49,8 @@ use rustc_middle::ty::fold::BottomUpFolder;
use rustc_middle::ty::relate::TypeRelation;
use rustc_middle::ty::SubstsRef;
use rustc_middle::ty::{self, EarlyBinder, PolyProjectionPredicate, ToPolyTraitRef, ToPredicate};
-use rustc_middle::ty::{Ty, TyCtxt, TypeFoldable, TypeVisitable};
+use rustc_middle::ty::{Ty, TyCtxt, TypeFoldable, TypeVisitableExt};
+use rustc_session::config::TraitSolver;
use rustc_span::symbol::sym;
use std::cell::{Cell, RefCell};
@@ -147,7 +151,7 @@ struct TraitObligationStack<'prev, 'tcx> {
/// you don't want to cache that `B: AutoTrait` or `A: AutoTrait`
/// is `EvaluatedToOk`; this is because they were only considered
/// ok on the premise that if `A: AutoTrait` held, but we indeed
- /// encountered a problem (later on) with `A: AutoTrait. So we
+ /// encountered a problem (later on) with `A: AutoTrait`. So we
/// currently set a flag on the stack node for `B: AutoTrait` (as
/// well as the second instance of `A: AutoTrait`) to suppress
/// caching.
@@ -374,11 +378,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
let self_ty = trait_ref.self_ty();
let (trait_desc, self_desc) = with_no_trimmed_paths!({
let trait_desc = trait_ref.print_only_trait_path().to_string();
- let self_desc = if self_ty.has_concrete_skeleton() {
- Some(self_ty.to_string())
- } else {
- None
- };
+ let self_desc =
+ self_ty.has_concrete_skeleton().then(|| self_ty.to_string());
(trait_desc, self_desc)
});
let cause = if let Conflict::Upstream = conflict {
@@ -544,10 +545,14 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
obligation: &PredicateObligation<'tcx>,
) -> Result<EvaluationResult, OverflowError> {
self.evaluation_probe(|this| {
- this.evaluate_predicate_recursively(
- TraitObligationStackList::empty(&ProvisionalEvaluationCache::default()),
- obligation.clone(),
- )
+ if this.tcx().sess.opts.unstable_opts.trait_solver != TraitSolver::Next {
+ this.evaluate_predicate_recursively(
+ TraitObligationStackList::empty(&ProvisionalEvaluationCache::default()),
+ obligation.clone(),
+ )
+ } else {
+ this.evaluate_predicates_recursively_in_new_solver([obligation.clone()])
+ }
})
}
@@ -586,18 +591,40 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
where
I: IntoIterator<Item = PredicateObligation<'tcx>> + std::fmt::Debug,
{
- let mut result = EvaluatedToOk;
- for obligation in predicates {
- let eval = self.evaluate_predicate_recursively(stack, obligation.clone())?;
- if let EvaluatedToErr = eval {
- // fast-path - EvaluatedToErr is the top of the lattice,
- // so we don't need to look on the other predicates.
- return Ok(EvaluatedToErr);
- } else {
- result = cmp::max(result, eval);
+ if self.tcx().sess.opts.unstable_opts.trait_solver != TraitSolver::Next {
+ let mut result = EvaluatedToOk;
+ for obligation in predicates {
+ let eval = self.evaluate_predicate_recursively(stack, obligation.clone())?;
+ if let EvaluatedToErr = eval {
+ // fast-path - EvaluatedToErr is the top of the lattice,
+ // so we don't need to look on the other predicates.
+ return Ok(EvaluatedToErr);
+ } else {
+ result = cmp::max(result, eval);
+ }
}
+ Ok(result)
+ } else {
+ self.evaluate_predicates_recursively_in_new_solver(predicates)
}
- Ok(result)
+ }
+
+ /// Evaluates the predicates using the new solver when `-Ztrait-solver=next` is enabled
+ fn evaluate_predicates_recursively_in_new_solver(
+ &mut self,
+ predicates: impl IntoIterator<Item = PredicateObligation<'tcx>>,
+ ) -> Result<EvaluationResult, OverflowError> {
+ let mut fulfill_cx = crate::solve::FulfillmentCtxt::new();
+ fulfill_cx.register_predicate_obligations(self.infcx, predicates);
+ // True errors
+ if !fulfill_cx.select_where_possible(self.infcx).is_empty() {
+ return Ok(EvaluatedToErr);
+ }
+ if !fulfill_cx.select_all_or_error(self.infcx).is_empty() {
+ return Ok(EvaluatedToAmbig);
+ }
+ // Regions and opaques are handled in the `evaluation_probe` by looking at the snapshot
+ Ok(EvaluatedToOk)
}
#[instrument(
@@ -700,7 +727,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
// Otherwise, we can say that `T: NonAutoTrait` is
// true.
// Let's imagine we have a predicate stack like
- // `Foo: Bar -> WF(T) -> T: NonAutoTrait -> T: Auto
+ // `Foo: Bar -> WF(T) -> T: NonAutoTrait -> T: Auto`
// depth ^1 ^2 ^3
// and the current predicate is `WF(T)`. `wf_args`
// would contain `(T, 1)`. We want to check all
@@ -768,7 +795,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
}
ty::PredicateKind::ObjectSafe(trait_def_id) => {
- if self.tcx().is_object_safe(trait_def_id) {
+ if self.tcx().check_is_object_safe(trait_def_id) {
Ok(EvaluatedToOk)
} else {
Ok(EvaluatedToErr)
@@ -962,7 +989,19 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
ty::PredicateKind::TypeWellFormedFromEnv(..) => {
bug!("TypeWellFormedFromEnv is only used for chalk")
}
+ ty::PredicateKind::AliasEq(..) => {
+ bug!("AliasEq is only used for new solver")
+ }
ty::PredicateKind::Ambiguous => Ok(EvaluatedToAmbig),
+ ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(ct, ty)) => {
+ match self.infcx.at(&obligation.cause, obligation.param_env).eq(ct.ty(), ty) {
+ Ok(inf_ok) => self.evaluate_predicates_recursively(
+ previous_stack,
+ inf_ok.into_obligations(),
+ ),
+ Err(_) => Ok(EvaluatedToErr),
+ }
+ }
}
})
}
@@ -1017,7 +1056,51 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
return Ok(cycle_result);
}
- let (result, dep_node) = self.in_task(|this| this.evaluate_stack(&stack));
+ let (result, dep_node) = self.in_task(|this| {
+ let mut result = this.evaluate_stack(&stack)?;
+
+ // fix issue #103563, we don't normalize
+ // nested obligations which produced by `TraitDef` candidate
+ // (i.e. using bounds on assoc items as assumptions).
+ // because we don't have enough information to
+ // normalize these obligations before evaluating.
+ // so we will try to normalize the obligation and evaluate again.
+ // we will replace it with new solver in the future.
+ if EvaluationResult::EvaluatedToErr == result
+ && fresh_trait_pred.has_projections()
+ && fresh_trait_pred.is_global()
+ {
+ let mut nested_obligations = Vec::new();
+ let predicate = try_normalize_with_depth_to(
+ this,
+ param_env,
+ obligation.cause.clone(),
+ obligation.recursion_depth + 1,
+ obligation.predicate,
+ &mut nested_obligations,
+ );
+ if predicate != obligation.predicate {
+ let mut nested_result = EvaluationResult::EvaluatedToOk;
+ for obligation in nested_obligations {
+ nested_result = cmp::max(
+ this.evaluate_predicate_recursively(previous_stack, obligation)?,
+ nested_result,
+ );
+ }
+
+ if nested_result.must_apply_modulo_regions() {
+ let obligation = obligation.with(this.tcx(), predicate);
+ result = cmp::max(
+ nested_result,
+ this.evaluate_trait_predicate_recursively(previous_stack, obligation)?,
+ );
+ }
+ }
+ }
+
+ Ok::<_, OverflowError>(result)
+ });
+
let result = result?;
if !result.must_apply_modulo_regions() {
@@ -1323,7 +1406,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
/// 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<T: Display + TypeFoldable<'tcx>, V>(
+ fn check_recursion_limit<T: Display + TypeFoldable<TyCtxt<'tcx>>, V>(
&self,
obligation: &Obligation<'tcx, T>,
error_obligation: &Obligation<'tcx, V>,
@@ -1589,7 +1672,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
) -> smallvec::SmallVec<[(usize, ty::BoundConstness); 2]> {
let poly_trait_predicate = self.infcx.resolve_vars_if_possible(obligation.predicate);
let placeholder_trait_predicate =
- self.infcx.replace_bound_vars_with_placeholders(poly_trait_predicate);
+ self.infcx.instantiate_binder_with_placeholders(poly_trait_predicate);
debug!(?placeholder_trait_predicate);
let tcx = self.infcx.tcx;
@@ -1669,7 +1752,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
});
self.infcx
.at(&obligation.cause, obligation.param_env)
- .define_opaque_types(false)
.sup(ty::Binder::dummy(placeholder_trait_ref), trait_bound)
.map(|InferOk { obligations: _, value: () }| {
// This method is called within a probe, so we can't have
@@ -1709,7 +1791,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
potentially_unnormalized_candidates: bool,
) -> ProjectionMatchesProjection {
let mut nested_obligations = Vec::new();
- let infer_predicate = self.infcx.replace_bound_vars_with_fresh_vars(
+ let infer_predicate = self.infcx.instantiate_binder_with_fresh_vars(
obligation.cause.span,
LateBoundRegionConversionTime::HigherRankedType,
env_predicate,
@@ -1732,7 +1814,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
let is_match = self
.infcx
.at(&obligation.cause, obligation.param_env)
- .define_opaque_types(false)
.sup(obligation.predicate, infer_projection)
.map_or(false, |InferOk { obligations, value: () }| {
self.evaluate_predicates_recursively(
@@ -2037,6 +2118,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
| ty::Ref(..)
| ty::Generator(..)
| ty::GeneratorWitness(..)
+ | ty::GeneratorWitnessMIR(..)
| ty::Array(..)
| ty::Closure(..)
| ty::Never
@@ -2064,12 +2146,13 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
}))
}
- ty::Alias(..) | ty::Param(_) => None,
+ ty::Alias(..) | ty::Param(_) | ty::Placeholder(..) => None,
ty::Infer(ty::TyVar(_)) => Ambiguous,
- ty::Placeholder(..)
- | ty::Bound(..)
- | ty::Infer(ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => {
+ // We can make this an ICE if/once we actually instantiate the trait obligation.
+ ty::Bound(..) => None,
+
+ ty::Infer(ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => {
bug!("asked to assemble builtin bounds of unexpected type: {:?}", self_ty);
}
}
@@ -2147,12 +2230,22 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
}
}
// (*) binder moved here
- let all_vars = self.tcx().mk_bound_variable_kinds(
+ let all_vars = self.tcx().mk_bound_variable_kinds_from_iter(
obligation.predicate.bound_vars().iter().chain(binder.bound_vars().iter()),
);
Where(ty::Binder::bind_with_vars(witness_tys.to_vec(), all_vars))
}
+ ty::GeneratorWitnessMIR(def_id, ref substs) => {
+ let hidden_types = bind_generator_hidden_types_above(
+ self.infcx,
+ def_id,
+ substs,
+ obligation.predicate.bound_vars(),
+ );
+ Where(hidden_types)
+ }
+
ty::Closure(_, substs) => {
// (*) binder moved here
let ty = self.infcx.shallow_resolve(substs.as_closure().tupled_upvars_ty());
@@ -2207,12 +2300,14 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
| ty::Float(_)
| ty::FnDef(..)
| ty::FnPtr(_)
- | ty::Str
| ty::Error(_)
| ty::Infer(ty::IntVar(_) | ty::FloatVar(_))
| ty::Never
| ty::Char => ty::Binder::dummy(Vec::new()),
+ // Treat this like `struct str([u8]);`
+ ty::Str => ty::Binder::dummy(vec![self.tcx().mk_slice(self.tcx().types.u8)]),
+
ty::Placeholder(..)
| ty::Dynamic(..)
| ty::Param(..)
@@ -2250,6 +2345,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
types.map_bound(|types| types.to_vec())
}
+ ty::GeneratorWitnessMIR(def_id, ref substs) => {
+ bind_generator_hidden_types_above(self.infcx, def_id, substs, t.bound_vars())
+ }
+
// For `PhantomData<T>`, we pass `T`.
ty::Adt(def, substs) if def.is_phantom_data() => t.rebind(substs.types().collect()),
@@ -2261,7 +2360,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
// We can resolve the `impl Trait` to its concrete type,
// which enforces a DAG between the functions requiring
// the auto trait bounds in question.
- t.rebind(vec![self.tcx().bound_type_of(def_id).subst(self.tcx(), substs)])
+ t.rebind(vec![self.tcx().type_of(def_id).subst(self.tcx(), substs)])
}
}
}
@@ -2295,7 +2394,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
.flat_map(|ty| {
let ty: ty::Binder<'tcx, Ty<'tcx>> = types.rebind(*ty); // <----/
- let placeholder_ty = self.infcx.replace_bound_vars_with_placeholders(ty);
+ let placeholder_ty = self.infcx.instantiate_binder_with_placeholders(ty);
let Normalized { value: normalized_ty, mut obligations } =
ensure_sufficient_stack(|| {
project::normalize_with_depth(
@@ -2346,7 +2445,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
// the placeholder trait ref may fail due the Generalizer relation
// raising a CyclicalTy error due to a sub_root_var relation
// for a variable being generalized...
- self.infcx.tcx.sess.delay_span_bug(
+ let guar = self.infcx.tcx.sess.delay_span_bug(
obligation.cause.span,
&format!(
"Impl {:?} was matchable against {:?} but now is not",
@@ -2354,7 +2453,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
),
);
let value = self.infcx.fresh_substs_for_item(obligation.cause.span, impl_def_id);
- let err = self.tcx().ty_error();
+ let err = self.tcx().ty_error(guar);
let value = value.fold_with(&mut BottomUpFolder {
tcx: self.tcx(),
ty_op: |_| err,
@@ -2374,7 +2473,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
obligation: &TraitObligation<'tcx>,
) -> Result<Normalized<'tcx, SubstsRef<'tcx>>, ()> {
let placeholder_obligation =
- self.infcx.replace_bound_vars_with_placeholders(obligation.predicate);
+ self.infcx.instantiate_binder_with_placeholders(obligation.predicate);
let placeholder_obligation_trait_ref = placeholder_obligation.trait_ref;
let impl_substs = self.infcx.fresh_substs_for_item(obligation.cause.span, impl_def_id);
@@ -2408,9 +2507,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
let InferOk { obligations, .. } = self
.infcx
.at(&cause, obligation.param_env)
- .define_opaque_types(false)
.eq(placeholder_obligation_trait_ref, impl_trait_ref)
- .map_err(|e| debug!("match_impl: failed eq_trait_refs due to `{e}`"))?;
+ .map_err(|e| {
+ debug!("match_impl: failed eq_trait_refs due to `{}`", e.to_string(self.tcx()))
+ })?;
nested_obligations.extend(obligations);
if !self.is_intercrate()
@@ -2457,11 +2557,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
) -> Result<Vec<PredicateObligation<'tcx>>, ()> {
self.infcx
.at(&obligation.cause, obligation.param_env)
- // We don't want predicates for opaque types to just match all other types,
- // if there is an obligation on the opaque type, then that obligation must be met
- // opaquely. Otherwise we'd match any obligation to the opaque type and then error
- // out later.
- .define_opaque_types(false)
.sup(obligation.predicate.to_poly_trait_ref(), poly_trait_ref)
.map(|InferOk { obligations, .. }| obligations)
.map_err(|_| ())
@@ -2562,11 +2657,12 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
assert_eq!(predicates.parent, None);
let predicates = predicates.instantiate_own(tcx, substs);
let mut obligations = Vec::with_capacity(predicates.len());
- for (predicate, span) in predicates {
+ for (index, (predicate, span)) in predicates.into_iter().enumerate() {
let cause = cause.clone().derived_cause(parent_trait_pred, |derived| {
ImplDerivedObligation(Box::new(ImplDerivedObligationCause {
derived,
- impl_def_id: def_id,
+ impl_or_alias_def_id: def_id,
+ impl_def_predicate_index: Some(index),
span,
}))
});
@@ -2892,3 +2988,56 @@ pub enum ProjectionMatchesProjection {
Ambiguous,
No,
}
+
+/// Replace all regions inside the generator interior with late bound regions.
+/// Note that each region slot in the types gets a new fresh late bound region, which means that
+/// none of the regions inside relate to any other, even if typeck had previously found constraints
+/// that would cause them to be related.
+#[instrument(level = "trace", skip(infcx), ret)]
+fn bind_generator_hidden_types_above<'tcx>(
+ infcx: &InferCtxt<'tcx>,
+ def_id: DefId,
+ substs: ty::SubstsRef<'tcx>,
+ bound_vars: &ty::List<ty::BoundVariableKind>,
+) -> ty::Binder<'tcx, Vec<Ty<'tcx>>> {
+ let tcx = infcx.tcx;
+ let mut seen_tys = FxHashSet::default();
+
+ let considering_regions = infcx.considering_regions;
+
+ let num_bound_variables = bound_vars.len() as u32;
+ let mut counter = num_bound_variables;
+
+ let hidden_types: Vec<_> = tcx
+ .generator_hidden_types(def_id)
+ // Deduplicate tys to avoid repeated work.
+ .filter(|bty| seen_tys.insert(*bty))
+ .map(|bty| {
+ let mut ty = bty.subst(tcx, substs);
+
+ // Only remap erased regions if we use them.
+ if considering_regions {
+ ty = tcx.fold_regions(ty, |mut r, current_depth| {
+ if let ty::ReErased = r.kind() {
+ let br = ty::BoundRegion {
+ var: ty::BoundVar::from_u32(counter),
+ kind: ty::BrAnon(counter, None),
+ };
+ counter += 1;
+ r = tcx.mk_re_late_bound(current_depth, br);
+ }
+ r
+ })
+ }
+
+ ty
+ })
+ .collect();
+ if considering_regions {
+ debug_assert!(!hidden_types.has_erased_regions());
+ }
+ let bound_vars = tcx.mk_bound_variable_kinds_from_iter(bound_vars.iter().chain(
+ (num_bound_variables..counter).map(|i| ty::BoundVariableKind::Region(ty::BrAnon(i, None))),
+ ));
+ ty::Binder::bind_with_vars(hidden_types, bound_vars)
+}
diff --git a/compiler/rustc_trait_selection/src/traits/specialize/mod.rs b/compiler/rustc_trait_selection/src/traits/specialize/mod.rs
index 3b796c623..d1d6a7a90 100644
--- a/compiler/rustc_trait_selection/src/traits/specialize/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/specialize/mod.rs
@@ -455,7 +455,13 @@ pub(crate) fn to_pretty_impl_header(tcx: TyCtxt<'_>, impl_def_id: DefId) -> Opti
w.push('>');
}
- write!(w, " {} for {}", trait_ref.print_only_trait_path(), tcx.type_of(impl_def_id)).unwrap();
+ write!(
+ w,
+ " {} for {}",
+ trait_ref.print_only_trait_path(),
+ tcx.type_of(impl_def_id).subst_identity()
+ )
+ .unwrap();
// The predicates will contain default bounds like `T: Sized`. We need to
// remove these bounds, and add `T: ?Sized` to any untouched type parameters.
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 0f9196de4..61ed9ef2e 100644
--- a/compiler/rustc_trait_selection/src/traits/specialize/specialization_graph.rs
+++ b/compiler/rustc_trait_selection/src/traits/specialize/specialization_graph.rs
@@ -4,7 +4,7 @@ use crate::traits;
use rustc_errors::ErrorGuaranteed;
use rustc_hir::def_id::DefId;
use rustc_middle::ty::fast_reject::{self, SimplifiedType, TreatParams};
-use rustc_middle::ty::{self, TyCtxt, TypeVisitable};
+use rustc_middle::ty::{self, TyCtxt, TypeVisitableExt};
pub use rustc_middle::traits::specialization_graph::*;
@@ -113,7 +113,7 @@ impl<'tcx> ChildrenExt<'tcx> for Children {
// Only report the `Self` type if it has at least
// some outer concrete shell; otherwise, it's
// not adding much information.
- self_ty: if self_ty.has_concrete_skeleton() { Some(self_ty) } else { None },
+ self_ty: self_ty.has_concrete_skeleton().then_some(self_ty),
intercrate_ambiguity_causes: overlap.intercrate_ambiguity_causes,
involves_placeholder: overlap.involves_placeholder,
}
@@ -399,7 +399,7 @@ pub(crate) fn assoc_def(
// If there is no such item in that impl, this function will fail with a
// cycle error if the specialization graph is currently being built.
if let Some(&impl_item_id) = tcx.impl_item_implementor_ids(impl_def_id).get(&assoc_def_id) {
- let &item = tcx.associated_item(impl_item_id);
+ let item = tcx.associated_item(impl_item_id);
let impl_node = Node::Impl(impl_def_id);
return Ok(LeafDef {
item,
diff --git a/compiler/rustc_trait_selection/src/traits/structural_match.rs b/compiler/rustc_trait_selection/src/traits/structural_match.rs
index f398fb06c..e38ae9381 100644
--- a/compiler/rustc_trait_selection/src/traits/structural_match.rs
+++ b/compiler/rustc_trait_selection/src/traits/structural_match.rs
@@ -78,7 +78,7 @@ impl<'tcx> Search<'tcx> {
}
}
-impl<'tcx> TypeVisitor<'tcx> for Search<'tcx> {
+impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for Search<'tcx> {
type BreakTy = Ty<'tcx>;
fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
@@ -101,7 +101,7 @@ impl<'tcx> TypeVisitor<'tcx> for Search<'tcx> {
ty::Closure(..) => {
return ControlFlow::Break(ty);
}
- ty::Generator(..) | ty::GeneratorWitness(..) => {
+ ty::Generator(..) | ty::GeneratorWitness(..) | ty::GeneratorWitnessMIR(..) => {
return ControlFlow::Break(ty);
}
ty::FnDef(..) => {
@@ -110,7 +110,7 @@ impl<'tcx> TypeVisitor<'tcx> for Search<'tcx> {
return ControlFlow::Continue(());
}
ty::Array(_, n)
- if { n.try_eval_usize(self.tcx, ty::ParamEnv::reveal_all()) == Some(0) } =>
+ if { n.try_eval_target_usize(self.tcx, ty::ParamEnv::reveal_all()) == Some(0) } =>
{
// rust-lang/rust#62336: ignore type of contents
// for empty array.
diff --git a/compiler/rustc_trait_selection/src/traits/util.rs b/compiler/rustc_trait_selection/src/traits/util.rs
index b5df583e3..bcf63d5a6 100644
--- a/compiler/rustc_trait_selection/src/traits/util.rs
+++ b/compiler/rustc_trait_selection/src/traits/util.rs
@@ -4,7 +4,7 @@ use smallvec::SmallVec;
use rustc_data_structures::fx::FxHashSet;
use rustc_hir::def_id::DefId;
-use rustc_middle::ty::{self, ImplSubject, ToPredicate, Ty, TyCtxt, TypeVisitable};
+use rustc_middle::ty::{self, ImplSubject, ToPredicate, Ty, TyCtxt, TypeVisitableExt};
use rustc_middle::ty::{GenericArg, SubstsRef};
use super::NormalizeExt;
@@ -239,7 +239,7 @@ pub fn predicate_for_trait_def<'tcx>(
cause: ObligationCause<'tcx>,
trait_def_id: DefId,
recursion_depth: usize,
- params: impl IntoIterator<Item = impl Into<GenericArg<'tcx>>>,
+ params: impl IntoIterator<Item: Into<GenericArg<'tcx>>>,
) -> PredicateObligation<'tcx> {
let trait_ref = tcx.mk_trait_ref(trait_def_id, params);
predicate_for_trait_ref(tcx, cause, param_env, trait_ref, recursion_depth)
@@ -292,7 +292,7 @@ pub fn closure_trait_ref_and_return_type<'tcx>(
assert!(!self_ty.has_escaping_bound_vars());
let arguments_tuple = match tuple_arguments {
TupleArgumentsFlag::No => sig.skip_binder().inputs()[0],
- TupleArgumentsFlag::Yes => tcx.intern_tup(sig.skip_binder().inputs()),
+ TupleArgumentsFlag::Yes => tcx.mk_tup(sig.skip_binder().inputs()),
};
let trait_ref = tcx.mk_trait_ref(fn_trait_def_id, [self_ty, arguments_tuple]);
sig.map_bound(|sig| (trait_ref, sig.output()))
diff --git a/compiler/rustc_trait_selection/src/traits/vtable.rs b/compiler/rustc_trait_selection/src/traits/vtable.rs
index 64daca714..a4e9928f8 100644
--- a/compiler/rustc_trait_selection/src/traits/vtable.rs
+++ b/compiler/rustc_trait_selection/src/traits/vtable.rs
@@ -4,7 +4,7 @@ use rustc_hir::def_id::DefId;
use rustc_hir::lang_items::LangItem;
use rustc_infer::traits::util::PredicateSet;
use rustc_infer::traits::ImplSource;
-use rustc_middle::ty::visit::TypeVisitable;
+use rustc_middle::ty::visit::TypeVisitableExt;
use rustc_middle::ty::InternalSubsts;
use rustc_middle::ty::{self, GenericParamDefKind, ToPredicate, Ty, TyCtxt, VtblEntry};
use rustc_span::{sym, Span};
@@ -197,12 +197,12 @@ fn own_existential_vtable_entries(tcx: TyCtxt<'_>, trait_def_id: DefId) -> &[Def
.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| {
+ 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_def_id, &trait_method) {
+ if !is_vtable_safe_method(tcx, trait_def_id, trait_method) {
debug!("own_existential_vtable_entry: not vtable safe");
return None;
}
diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs
index 12d4cb4fc..d498af359 100644
--- a/compiler/rustc_trait_selection/src/traits/wf.rs
+++ b/compiler/rustc_trait_selection/src/traits/wf.rs
@@ -1,11 +1,11 @@
use crate::infer::InferCtxt;
use crate::traits;
use rustc_hir as hir;
-use rustc_hir::def_id::DefId;
use rustc_hir::lang_items::LangItem;
use rustc_middle::ty::subst::{GenericArg, GenericArgKind, SubstsRef};
-use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitable};
-use rustc_span::Span;
+use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt};
+use rustc_span::def_id::{DefId, LocalDefId, CRATE_DEF_ID};
+use rustc_span::{Span, DUMMY_SP};
use std::iter;
/// Returns the set of obligations needed to make `arg` well-formed.
@@ -17,7 +17,7 @@ use std::iter;
pub fn obligations<'tcx>(
infcx: &InferCtxt<'tcx>,
param_env: ty::ParamEnv<'tcx>,
- body_id: hir::HirId,
+ body_id: LocalDefId,
recursion_depth: usize,
arg: GenericArg<'tcx>,
span: Span,
@@ -75,6 +75,34 @@ pub fn obligations<'tcx>(
Some(result)
}
+/// Compute the predicates that are required for a type to be well-formed.
+///
+/// This is only intended to be used in the new solver, since it does not
+/// take into account recursion depth or proper error-reporting spans.
+pub fn unnormalized_obligations<'tcx>(
+ infcx: &InferCtxt<'tcx>,
+ param_env: ty::ParamEnv<'tcx>,
+ arg: GenericArg<'tcx>,
+) -> Option<Vec<traits::PredicateObligation<'tcx>>> {
+ if let ty::GenericArgKind::Lifetime(..) = arg.unpack() {
+ return Some(vec![]);
+ }
+
+ debug_assert_eq!(arg, infcx.resolve_vars_if_possible(arg));
+
+ let mut wf = WfPredicates {
+ tcx: infcx.tcx,
+ param_env,
+ body_id: CRATE_DEF_ID,
+ span: DUMMY_SP,
+ out: vec![],
+ recursion_depth: 0,
+ item: None,
+ };
+ wf.compute(arg);
+ Some(wf.out)
+}
+
/// Returns the obligations that make this trait reference
/// well-formed. For example, if there is a trait `Set` defined like
/// `trait Set<K:Eq>`, then the trait reference `Foo: Set<Bar>` is WF
@@ -82,7 +110,7 @@ pub fn obligations<'tcx>(
pub fn trait_obligations<'tcx>(
infcx: &InferCtxt<'tcx>,
param_env: ty::ParamEnv<'tcx>,
- body_id: hir::HirId,
+ body_id: LocalDefId,
trait_pred: &ty::TraitPredicate<'tcx>,
span: Span,
item: &'tcx hir::Item<'tcx>,
@@ -105,7 +133,7 @@ pub fn trait_obligations<'tcx>(
pub fn predicate_obligations<'tcx>(
infcx: &InferCtxt<'tcx>,
param_env: ty::ParamEnv<'tcx>,
- body_id: hir::HirId,
+ body_id: LocalDefId,
predicate: ty::Predicate<'tcx>,
span: Span,
) -> Vec<traits::PredicateObligation<'tcx>> {
@@ -135,6 +163,10 @@ pub fn predicate_obligations<'tcx>(
ty::TermKind::Const(c) => c.into(),
})
}
+ ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(ct, ty)) => {
+ wf.compute(ct.into());
+ wf.compute(ty.into());
+ }
ty::PredicateKind::WellFormed(arg) => {
wf.compute(arg);
}
@@ -159,6 +191,9 @@ pub fn predicate_obligations<'tcx>(
ty::PredicateKind::TypeWellFormedFromEnv(..) => {
bug!("TypeWellFormedFromEnv is only used for Chalk")
}
+ ty::PredicateKind::AliasEq(..) => {
+ bug!("We should only wf check where clauses and `AliasEq` is not a `Clause`")
+ }
}
wf.normalize(infcx)
@@ -167,7 +202,7 @@ pub fn predicate_obligations<'tcx>(
struct WfPredicates<'tcx> {
tcx: TyCtxt<'tcx>,
param_env: ty::ParamEnv<'tcx>,
- body_id: hir::HirId,
+ body_id: LocalDefId,
span: Span,
out: Vec<traits::PredicateObligation<'tcx>>,
recursion_depth: usize,
@@ -523,6 +558,7 @@ impl<'tcx> WfPredicates<'tcx> {
| ty::Error(_)
| ty::Str
| ty::GeneratorWitness(..)
+ | ty::GeneratorWitnessMIR(..)
| ty::Never
| ty::Param(_)
| ty::Bound(..)
@@ -847,7 +883,7 @@ pub fn object_region_bounds<'tcx>(
// Since we don't actually *know* the self type for an object,
// this "open(err)" serves as a kind of dummy standin -- basically
// a placeholder type.
- let open_ty = tcx.mk_ty_infer(ty::FreshTy(0));
+ let open_ty = tcx.mk_fresh_ty(0);
let predicates = existential_predicates.iter().filter_map(|predicate| {
if let ty::ExistentialPredicate::Projection(_) = predicate.skip_binder() {
@@ -890,6 +926,7 @@ pub(crate) fn required_region_bounds<'tcx>(
match obligation.predicate.kind().skip_binder() {
ty::PredicateKind::Clause(ty::Clause::Projection(..))
| ty::PredicateKind::Clause(ty::Clause::Trait(..))
+ | ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(..))
| ty::PredicateKind::Subtype(..)
| ty::PredicateKind::Coerce(..)
| ty::PredicateKind::WellFormed(..)
@@ -899,6 +936,7 @@ pub(crate) fn required_region_bounds<'tcx>(
| ty::PredicateKind::ConstEvaluatable(..)
| ty::PredicateKind::ConstEquate(..)
| ty::PredicateKind::Ambiguous
+ | ty::PredicateKind::AliasEq(..)
| ty::PredicateKind::TypeWellFormedFromEnv(..) => None,
ty::PredicateKind::Clause(ty::Clause::TypeOutlives(ty::OutlivesPredicate(
ref t,
diff --git a/compiler/rustc_traits/Cargo.toml b/compiler/rustc_traits/Cargo.toml
index a432498ab..eff6fb26d 100644
--- a/compiler/rustc_traits/Cargo.toml
+++ b/compiler/rustc_traits/Cargo.toml
@@ -5,7 +5,6 @@ edition = "2021"
[dependencies]
tracing = "0.1"
-rustc_attr = { path = "../rustc_attr" }
rustc_middle = { path = "../rustc_middle" }
rustc_data_structures = { path = "../rustc_data_structures" }
rustc_hir = { path = "../rustc_hir" }
diff --git a/compiler/rustc_traits/src/chalk/db.rs b/compiler/rustc_traits/src/chalk/db.rs
index f146de396..f8c8f744e 100644
--- a/compiler/rustc_traits/src/chalk/db.rs
+++ b/compiler/rustc_traits/src/chalk/db.rs
@@ -246,7 +246,7 @@ impl<'tcx> chalk_solve::RustIrDatabase<RustInterner<'tcx>> for RustIrDatabase<'t
// Grab the ADT and the param we might need to calculate its layout
let param_env = tcx.param_env(did);
- let adt_ty = tcx.type_of(did);
+ let adt_ty = tcx.type_of(did).subst_identity();
// The ADT is a 1-zst if it's a ZST and its alignment is 1.
// Mark the ADT as _not_ a 1-zst if there was a layout error.
@@ -269,7 +269,7 @@ impl<'tcx> chalk_solve::RustIrDatabase<RustInterner<'tcx>> for RustIrDatabase<'t
let where_clauses = self.where_clauses_for(def_id, bound_vars);
- let sig = self.interner.tcx.bound_fn_sig(def_id);
+ let sig = self.interner.tcx.fn_sig(def_id);
let (inputs_and_output, iobinders, _) = crate::chalk::lowering::collect_bound_vars(
self.interner,
self.interner.tcx,
@@ -468,7 +468,7 @@ impl<'tcx> chalk_solve::RustIrDatabase<RustInterner<'tcx>> for RustIrDatabase<'t
let ty = self
.interner
.tcx
- .bound_type_of(def_id)
+ .type_of(def_id)
.subst(self.interner.tcx, bound_vars)
.lower_into(self.interner);
@@ -580,7 +580,7 @@ impl<'tcx> chalk_solve::RustIrDatabase<RustInterner<'tcx>> for RustIrDatabase<'t
}
fn is_object_safe(&self, trait_id: chalk_ir::TraitId<RustInterner<'tcx>>) -> bool {
- self.interner.tcx.is_object_safe(trait_id.0)
+ self.interner.tcx.check_is_object_safe(trait_id.0)
}
fn hidden_opaque_type(
@@ -588,10 +588,7 @@ impl<'tcx> chalk_solve::RustIrDatabase<RustInterner<'tcx>> for RustIrDatabase<'t
_id: chalk_ir::OpaqueTyId<RustInterner<'tcx>>,
) -> chalk_ir::Ty<RustInterner<'tcx>> {
// FIXME(chalk): actually get hidden ty
- self.interner
- .tcx
- .mk_ty(ty::Tuple(self.interner.tcx.intern_type_list(&[])))
- .lower_into(self.interner)
+ self.interner.tcx.types.unit.lower_into(self.interner)
}
fn closure_kind(
@@ -721,13 +718,13 @@ impl<'tcx> chalk_ir::UnificationDatabase<RustInterner<'tcx>> for RustIrDatabase<
fn bound_vars_for_item(tcx: TyCtxt<'_>, def_id: DefId) -> SubstsRef<'_> {
InternalSubsts::for_item(tcx, def_id, |param, substs| match param.kind {
ty::GenericParamDefKind::Type { .. } => tcx
- .mk_ty(ty::Bound(
+ .mk_bound(
ty::INNERMOST,
ty::BoundTy {
var: ty::BoundVar::from(param.index),
- kind: ty::BoundTyKind::Param(param.name),
+ kind: ty::BoundTyKind::Param(param.def_id, param.name),
},
- ))
+ )
.into(),
ty::GenericParamDefKind::Lifetime => {
@@ -735,13 +732,13 @@ fn bound_vars_for_item(tcx: TyCtxt<'_>, def_id: DefId) -> SubstsRef<'_> {
var: ty::BoundVar::from_usize(substs.len()),
kind: ty::BrAnon(substs.len() as u32, None),
};
- tcx.mk_region(ty::ReLateBound(ty::INNERMOST, br)).into()
+ tcx.mk_re_late_bound(ty::INNERMOST, br).into()
}
ty::GenericParamDefKind::Const { .. } => tcx
.mk_const(
ty::ConstKind::Bound(ty::INNERMOST, ty::BoundVar::from(param.index)),
- tcx.type_of(param.def_id),
+ tcx.type_of(param.def_id).subst_identity(),
)
.into(),
})
@@ -772,12 +769,12 @@ struct ReplaceOpaqueTyFolder<'tcx> {
binder_index: ty::DebruijnIndex,
}
-impl<'tcx> ty::TypeFolder<'tcx> for ReplaceOpaqueTyFolder<'tcx> {
- fn tcx<'b>(&'b self) -> TyCtxt<'tcx> {
+impl<'tcx> ty::TypeFolder<TyCtxt<'tcx>> for ReplaceOpaqueTyFolder<'tcx> {
+ fn interner(&self) -> TyCtxt<'tcx> {
self.tcx
}
- fn fold_binder<T: TypeFoldable<'tcx>>(
+ fn fold_binder<T: TypeFoldable<TyCtxt<'tcx>>>(
&mut self,
t: ty::Binder<'tcx, T>,
) -> ty::Binder<'tcx, T> {
@@ -790,10 +787,9 @@ impl<'tcx> ty::TypeFolder<'tcx> for ReplaceOpaqueTyFolder<'tcx> {
fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
if let ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. }) = *ty.kind() {
if def_id == self.opaque_ty_id.0 && substs == self.identity_substs {
- return self.tcx.mk_ty(ty::Bound(
- self.binder_index,
- ty::BoundTy::from(ty::BoundVar::from_u32(0)),
- ));
+ return self
+ .tcx
+ .mk_bound(self.binder_index, ty::BoundTy::from(ty::BoundVar::from_u32(0)));
}
}
ty
diff --git a/compiler/rustc_traits/src/chalk/lowering.rs b/compiler/rustc_traits/src/chalk/lowering.rs
index 9712abb70..60e22d100 100644
--- a/compiler/rustc_traits/src/chalk/lowering.rs
+++ b/compiler/rustc_traits/src/chalk/lowering.rs
@@ -62,7 +62,9 @@ impl<'tcx> LowerInto<'tcx, chalk_ir::Substitution<RustInterner<'tcx>>> for Subst
impl<'tcx> LowerInto<'tcx, SubstsRef<'tcx>> for &chalk_ir::Substitution<RustInterner<'tcx>> {
fn lower_into(self, interner: RustInterner<'tcx>) -> SubstsRef<'tcx> {
- interner.tcx.mk_substs(self.iter(interner).map(|subst| subst.lower_into(interner)))
+ interner
+ .tcx
+ .mk_substs_from_iter(self.iter(interner).map(|subst| subst.lower_into(interner)))
}
}
@@ -116,6 +118,8 @@ impl<'tcx> LowerInto<'tcx, chalk_ir::InEnvironment<chalk_ir::Goal<RustInterner<'
)),
},
ty::PredicateKind::ObjectSafe(..)
+ | ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(..))
+ | ty::PredicateKind::AliasEq(..)
| ty::PredicateKind::ClosureKind(..)
| ty::PredicateKind::Subtype(..)
| ty::PredicateKind::Coerce(..)
@@ -210,6 +214,8 @@ impl<'tcx> LowerInto<'tcx, chalk_ir::GoalData<RustInterner<'tcx>>> for ty::Predi
// We can defer this, but ultimately we'll want to express
// some of these in terms of chalk operations.
ty::PredicateKind::ClosureKind(..)
+ | ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(..))
+ | ty::PredicateKind::AliasEq(..)
| ty::PredicateKind::Coerce(..)
| ty::PredicateKind::ConstEvaluatable(..)
| ty::PredicateKind::Ambiguous
@@ -343,6 +349,7 @@ impl<'tcx> LowerInto<'tcx, chalk_ir::Ty<RustInterner<'tcx>>> for Ty<'tcx> {
substs.lower_into(interner),
),
ty::GeneratorWitness(_) => unimplemented!(),
+ ty::GeneratorWitnessMIR(..) => unimplemented!(),
ty::Never => chalk_ir::TyKind::Never,
ty::Tuple(types) => {
chalk_ir::TyKind::Tuple(types.len(), types.as_substs().lower_into(interner))
@@ -369,7 +376,7 @@ impl<'tcx> LowerInto<'tcx, chalk_ir::Ty<RustInterner<'tcx>>> for Ty<'tcx> {
ty::Placeholder(_placeholder) => {
chalk_ir::TyKind::Placeholder(chalk_ir::PlaceholderIndex {
ui: chalk_ir::UniverseIndex { counter: _placeholder.universe.as_usize() },
- idx: _placeholder.name.as_usize(),
+ idx: _placeholder.name.expect_anon() as usize,
})
}
ty::Infer(_infer) => unimplemented!(),
@@ -450,11 +457,7 @@ impl<'tcx> LowerInto<'tcx, Ty<'tcx>> for &chalk_ir::Ty<RustInterner<'tcx>> {
interner.tcx.mk_alias_ty(assoc_ty.0, substitution.lower_into(interner)),
),
TyKind::Foreign(def_id) => ty::Foreign(def_id.0),
- TyKind::Error => return interner.tcx.ty_error(),
- TyKind::Placeholder(placeholder) => ty::Placeholder(ty::Placeholder {
- universe: ty::UniverseIndex::from_usize(placeholder.ui.counter),
- name: ty::BoundVar::from_usize(placeholder.idx),
- }),
+ TyKind::Error => return interner.tcx.ty_error_misc(),
TyKind::Alias(alias_ty) => match alias_ty {
chalk_ir::AliasTy::Projection(projection) => ty::Alias(
ty::Projection,
@@ -472,17 +475,21 @@ impl<'tcx> LowerInto<'tcx, Ty<'tcx>> for &chalk_ir::Ty<RustInterner<'tcx>> {
),
},
TyKind::Function(_quantified_ty) => unimplemented!(),
- TyKind::BoundVar(_bound) => ty::Bound(
- ty::DebruijnIndex::from_usize(_bound.debruijn.depth() as usize),
+ TyKind::BoundVar(bound) => ty::Bound(
+ ty::DebruijnIndex::from_usize(bound.debruijn.depth() as usize),
ty::BoundTy {
- var: ty::BoundVar::from_usize(_bound.index),
- kind: ty::BoundTyKind::Anon,
+ var: ty::BoundVar::from_usize(bound.index),
+ kind: ty::BoundTyKind::Anon(bound.index as u32),
},
),
+ TyKind::Placeholder(placeholder) => ty::Placeholder(ty::Placeholder {
+ universe: ty::UniverseIndex::from_usize(placeholder.ui.counter),
+ name: ty::BoundTyKind::Anon(placeholder.idx as u32),
+ }),
TyKind::InferenceVar(_, _) => unimplemented!(),
TyKind::Dyn(_) => unimplemented!(),
};
- interner.tcx.mk_ty(kind)
+ interner.tcx.mk_ty_from_kind(kind)
}
}
@@ -492,6 +499,9 @@ impl<'tcx> LowerInto<'tcx, chalk_ir::Lifetime<RustInterner<'tcx>>> for Region<'t
ty::ReEarlyBound(_) => {
panic!("Should have already been substituted.");
}
+ ty::ReError(_) => {
+ panic!("Error lifetime should not have already been lowered.");
+ }
ty::ReLateBound(db, br) => chalk_ir::LifetimeData::BoundVar(chalk_ir::BoundVar::new(
chalk_ir::DebruijnIndex::new(db.as_u32()),
br.var.as_usize(),
@@ -503,7 +513,7 @@ impl<'tcx> LowerInto<'tcx, chalk_ir::Lifetime<RustInterner<'tcx>>> for Region<'t
ty::RePlaceholder(placeholder_region) => {
chalk_ir::LifetimeData::Placeholder(chalk_ir::PlaceholderIndex {
ui: chalk_ir::UniverseIndex { counter: placeholder_region.universe.index() },
- idx: 0,
+ idx: 0, // FIXME: This `idx: 0` is sus.
})
.intern(interner)
}
@@ -514,8 +524,9 @@ impl<'tcx> LowerInto<'tcx, chalk_ir::Lifetime<RustInterner<'tcx>>> for Region<'t
impl<'tcx> LowerInto<'tcx, Region<'tcx>> for &chalk_ir::Lifetime<RustInterner<'tcx>> {
fn lower_into(self, interner: RustInterner<'tcx>) -> Region<'tcx> {
- let kind = match self.data(interner) {
- chalk_ir::LifetimeData::BoundVar(var) => ty::ReLateBound(
+ let tcx = interner.tcx;
+ match self.data(interner) {
+ chalk_ir::LifetimeData::BoundVar(var) => tcx.mk_re_late_bound(
ty::DebruijnIndex::from_u32(var.debruijn.depth()),
ty::BoundRegion {
var: ty::BoundVar::from_usize(var.index),
@@ -523,15 +534,14 @@ impl<'tcx> LowerInto<'tcx, Region<'tcx>> for &chalk_ir::Lifetime<RustInterner<'t
},
),
chalk_ir::LifetimeData::InferenceVar(_var) => unimplemented!(),
- chalk_ir::LifetimeData::Placeholder(p) => ty::RePlaceholder(ty::Placeholder {
+ chalk_ir::LifetimeData::Placeholder(p) => tcx.mk_re_placeholder(ty::Placeholder {
universe: ty::UniverseIndex::from_usize(p.ui.counter),
name: ty::BoundRegionKind::BrAnon(p.idx as u32, None),
}),
- chalk_ir::LifetimeData::Static => return interner.tcx.lifetimes.re_static,
- chalk_ir::LifetimeData::Erased => return interner.tcx.lifetimes.re_erased,
+ chalk_ir::LifetimeData::Static => tcx.lifetimes.re_static,
+ chalk_ir::LifetimeData::Erased => tcx.lifetimes.re_erased,
chalk_ir::LifetimeData::Phantom(void, _) => match *void {},
- };
- interner.tcx.mk_region(kind)
+ }
}
}
@@ -639,8 +649,10 @@ impl<'tcx> LowerInto<'tcx, Option<chalk_ir::QuantifiedWhereClause<RustInterner<'
Some(chalk_ir::WhereClause::AliasEq(predicate.lower_into(interner)))
}
ty::PredicateKind::WellFormed(_ty) => None,
+ ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(..)) => None,
ty::PredicateKind::ObjectSafe(..)
+ | ty::PredicateKind::AliasEq(..)
| ty::PredicateKind::ClosureKind(..)
| ty::PredicateKind::Subtype(..)
| ty::PredicateKind::Coerce(..)
@@ -670,11 +682,11 @@ impl<'tcx> LowerInto<'tcx, chalk_ir::Binders<chalk_ir::QuantifiedWhereClauses<Ru
// shifted in by one so that they are still escaping.
let predicates = ty::fold::shift_vars(interner.tcx, self, 1);
- let self_ty = interner.tcx.mk_ty(ty::Bound(
+ let self_ty = interner.tcx.mk_bound(
// This is going to be wrapped in a binder
ty::DebruijnIndex::from_usize(1),
- ty::BoundTy { var: ty::BoundVar::from_usize(0), kind: ty::BoundTyKind::Anon },
- ));
+ ty::BoundTy { var: ty::BoundVar::from_usize(0), kind: ty::BoundTyKind::Anon(0) },
+ );
let where_clauses = predicates.into_iter().map(|predicate| {
let (predicate, binders, _named_regions) =
collect_bound_vars(interner, interner.tcx, predicate);
@@ -772,8 +784,10 @@ impl<'tcx> LowerInto<'tcx, Option<chalk_solve::rust_ir::QuantifiedInlineBound<Ru
}
ty::PredicateKind::Clause(ty::Clause::TypeOutlives(_predicate)) => None,
ty::PredicateKind::WellFormed(_ty) => None,
+ ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(..)) => None,
ty::PredicateKind::Clause(ty::Clause::RegionOutlives(..))
+ | ty::PredicateKind::AliasEq(..)
| ty::PredicateKind::ObjectSafe(..)
| ty::PredicateKind::ClosureKind(..)
| ty::PredicateKind::Subtype(..)
@@ -867,7 +881,7 @@ impl<'tcx> LowerInto<'tcx, chalk_solve::rust_ir::AliasEqBound<RustInterner<'tcx>
/// It's important to note that because of prior substitution, we may have
/// late-bound regions, even outside of fn contexts, since this is the best way
/// to prep types for chalk lowering.
-pub(crate) fn collect_bound_vars<'tcx, T: TypeFoldable<'tcx>>(
+pub(crate) fn collect_bound_vars<'tcx, T: TypeFoldable<TyCtxt<'tcx>>>(
interner: RustInterner<'tcx>,
tcx: TyCtxt<'tcx>,
ty: Binder<'tcx, T>,
@@ -917,8 +931,8 @@ impl<'tcx> BoundVarsCollector<'tcx> {
}
}
-impl<'tcx> TypeVisitor<'tcx> for BoundVarsCollector<'tcx> {
- fn visit_binder<T: TypeVisitable<'tcx>>(
+impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for BoundVarsCollector<'tcx> {
+ fn visit_binder<T: TypeVisitable<TyCtxt<'tcx>>>(
&mut self,
t: &Binder<'tcx, T>,
) -> ControlFlow<Self::BreakTy> {
@@ -998,12 +1012,15 @@ impl<'a, 'tcx> NamedBoundVarSubstitutor<'a, 'tcx> {
}
}
-impl<'a, 'tcx> TypeFolder<'tcx> for NamedBoundVarSubstitutor<'a, 'tcx> {
- fn tcx<'b>(&'b self) -> TyCtxt<'tcx> {
+impl<'a, 'tcx> TypeFolder<TyCtxt<'tcx>> for NamedBoundVarSubstitutor<'a, 'tcx> {
+ fn interner(&self) -> TyCtxt<'tcx> {
self.tcx
}
- fn fold_binder<T: TypeFoldable<'tcx>>(&mut self, t: Binder<'tcx, T>) -> Binder<'tcx, T> {
+ fn fold_binder<T: TypeFoldable<TyCtxt<'tcx>>>(
+ &mut self,
+ t: Binder<'tcx, T>,
+ ) -> Binder<'tcx, T> {
self.binder_index.shift_in(1);
let result = t.super_fold_with(self);
self.binder_index.shift_out(1);
@@ -1016,7 +1033,7 @@ impl<'a, 'tcx> TypeFolder<'tcx> for NamedBoundVarSubstitutor<'a, 'tcx> {
ty::BrNamed(def_id, _name) => match self.named_parameters.get(&def_id) {
Some(idx) => {
let new_br = ty::BoundRegion { var: br.var, kind: ty::BrAnon(*idx, None) };
- return self.tcx.mk_region(ty::ReLateBound(index, new_br));
+ return self.tcx.mk_re_late_bound(index, new_br);
}
None => panic!("Missing `BrNamed`."),
},
@@ -1037,7 +1054,7 @@ pub(crate) struct ParamsSubstitutor<'tcx> {
binder_index: ty::DebruijnIndex,
list: Vec<rustc_middle::ty::ParamTy>,
next_ty_placeholder: usize,
- pub(crate) params: rustc_data_structures::fx::FxHashMap<usize, rustc_middle::ty::ParamTy>,
+ pub(crate) params: rustc_data_structures::fx::FxHashMap<u32, rustc_middle::ty::ParamTy>,
pub(crate) named_regions: BTreeMap<DefId, u32>,
}
@@ -1054,12 +1071,15 @@ impl<'tcx> ParamsSubstitutor<'tcx> {
}
}
-impl<'tcx> TypeFolder<'tcx> for ParamsSubstitutor<'tcx> {
- fn tcx<'b>(&'b self) -> TyCtxt<'tcx> {
+impl<'tcx> TypeFolder<TyCtxt<'tcx>> for ParamsSubstitutor<'tcx> {
+ fn interner(&self) -> TyCtxt<'tcx> {
self.tcx
}
- fn fold_binder<T: TypeFoldable<'tcx>>(&mut self, t: Binder<'tcx, T>) -> Binder<'tcx, T> {
+ fn fold_binder<T: TypeFoldable<TyCtxt<'tcx>>>(
+ &mut self,
+ t: Binder<'tcx, T>,
+ ) -> Binder<'tcx, T> {
self.binder_index.shift_in(1);
let result = t.super_fold_with(self);
self.binder_index.shift_out(1);
@@ -1069,18 +1089,18 @@ impl<'tcx> TypeFolder<'tcx> for ParamsSubstitutor<'tcx> {
fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
match *t.kind() {
ty::Param(param) => match self.list.iter().position(|r| r == &param) {
- Some(idx) => self.tcx.mk_ty(ty::Placeholder(ty::PlaceholderType {
+ Some(idx) => self.tcx.mk_placeholder(ty::PlaceholderType {
universe: ty::UniverseIndex::from_usize(0),
- name: ty::BoundVar::from_usize(idx),
- })),
+ name: ty::BoundTyKind::Anon(idx as u32),
+ }),
None => {
self.list.push(param);
let idx = self.list.len() - 1 + self.next_ty_placeholder;
- self.params.insert(idx, param);
- self.tcx.mk_ty(ty::Placeholder(ty::PlaceholderType {
+ self.params.insert(idx as u32, param);
+ self.tcx.mk_placeholder(ty::PlaceholderType {
universe: ty::UniverseIndex::from_usize(0),
- name: ty::BoundVar::from_usize(idx),
- }))
+ name: ty::BoundTyKind::Anon(idx as u32),
+ })
}
},
_ => t.super_fold_with(self),
@@ -1098,7 +1118,7 @@ impl<'tcx> TypeFolder<'tcx> for ParamsSubstitutor<'tcx> {
var: ty::BoundVar::from_u32(*idx),
kind: ty::BrAnon(*idx, None),
};
- self.tcx.mk_region(ty::ReLateBound(self.binder_index, br))
+ self.tcx.mk_re_late_bound(self.binder_index, br)
}
None => {
let idx = self.named_regions.len() as u32;
@@ -1107,7 +1127,7 @@ impl<'tcx> TypeFolder<'tcx> for ParamsSubstitutor<'tcx> {
kind: ty::BrAnon(idx, None),
};
self.named_regions.insert(_re.def_id, idx);
- self.tcx.mk_region(ty::ReLateBound(self.binder_index, br))
+ self.tcx.mk_re_late_bound(self.binder_index, br)
}
},
@@ -1118,28 +1138,28 @@ impl<'tcx> TypeFolder<'tcx> for ParamsSubstitutor<'tcx> {
pub(crate) struct ReverseParamsSubstitutor<'tcx> {
tcx: TyCtxt<'tcx>,
- params: rustc_data_structures::fx::FxHashMap<usize, rustc_middle::ty::ParamTy>,
+ params: rustc_data_structures::fx::FxHashMap<u32, rustc_middle::ty::ParamTy>,
}
impl<'tcx> ReverseParamsSubstitutor<'tcx> {
pub(crate) fn new(
tcx: TyCtxt<'tcx>,
- params: rustc_data_structures::fx::FxHashMap<usize, rustc_middle::ty::ParamTy>,
+ params: rustc_data_structures::fx::FxHashMap<u32, rustc_middle::ty::ParamTy>,
) -> Self {
Self { tcx, params }
}
}
-impl<'tcx> TypeFolder<'tcx> for ReverseParamsSubstitutor<'tcx> {
- fn tcx<'b>(&'b self) -> TyCtxt<'tcx> {
+impl<'tcx> TypeFolder<TyCtxt<'tcx>> for ReverseParamsSubstitutor<'tcx> {
+ fn interner(&self) -> TyCtxt<'tcx> {
self.tcx
}
fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
match *t.kind() {
ty::Placeholder(ty::PlaceholderType { universe: ty::UniverseIndex::ROOT, name }) => {
- match self.params.get(&name.as_usize()) {
- Some(param) => self.tcx.mk_ty(ty::Param(*param)),
+ match self.params.get(&name.expect_anon()) {
+ Some(&ty::ParamTy { index, name }) => self.tcx.mk_ty_param(index, name),
None => t,
}
}
@@ -1166,11 +1186,12 @@ impl PlaceholdersCollector {
}
}
-impl<'tcx> TypeVisitor<'tcx> for PlaceholdersCollector {
+impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for PlaceholdersCollector {
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
match t.kind() {
ty::Placeholder(p) if p.universe == self.universe_index => {
- self.next_ty_placeholder = self.next_ty_placeholder.max(p.name.as_usize() + 1);
+ self.next_ty_placeholder =
+ self.next_ty_placeholder.max(p.name.expect_anon() as usize + 1);
}
_ => (),
@@ -1185,6 +1206,7 @@ impl<'tcx> TypeVisitor<'tcx> for PlaceholdersCollector {
if let ty::BoundRegionKind::BrAnon(anon, _) = p.name {
self.next_anon_region_placeholder = self.next_anon_region_placeholder.max(anon);
}
+ // FIXME: This doesn't seem to handle BrNamed at all?
}
_ => (),
diff --git a/compiler/rustc_traits/src/chalk/mod.rs b/compiler/rustc_traits/src/chalk/mod.rs
index f76386fa7..a5ebc26a8 100644
--- a/compiler/rustc_traits/src/chalk/mod.rs
+++ b/compiler/rustc_traits/src/chalk/mod.rs
@@ -6,15 +6,10 @@
pub(crate) mod db;
pub(crate) mod lowering;
-use rustc_data_structures::fx::FxHashMap;
-
-use rustc_index::vec::IndexVec;
-
use rustc_middle::infer::canonical::{CanonicalTyVarKind, CanonicalVarKind};
use rustc_middle::traits::ChalkRustInterner;
use rustc_middle::ty::query::Providers;
-use rustc_middle::ty::subst::GenericArg;
-use rustc_middle::ty::{self, BoundVar, ParamTy, TyCtxt, TypeFoldable, TypeVisitable};
+use rustc_middle::ty::{self, TyCtxt, TypeFoldable, TypeVisitable};
use rustc_infer::infer::canonical::{
Canonical, CanonicalVarValues, Certainty, QueryRegionConstraints, QueryResponse,
@@ -44,7 +39,7 @@ pub(crate) fn evaluate_goal<'tcx>(
let mut params_substitutor =
ParamsSubstitutor::new(tcx, placeholders_collector.next_ty_placeholder);
let obligation = obligation.fold_with(&mut params_substitutor);
- let params: FxHashMap<usize, ParamTy> = params_substitutor.params;
+ let params = params_substitutor.params;
let max_universe = obligation.max_universe.index();
@@ -100,36 +95,35 @@ pub(crate) fn evaluate_goal<'tcx>(
binders: chalk_ir::CanonicalVarKinds<_>| {
use rustc_middle::infer::canonical::CanonicalVarInfo;
- let mut var_values: IndexVec<BoundVar, GenericArg<'tcx>> = IndexVec::new();
let mut reverse_param_substitutor = ReverseParamsSubstitutor::new(tcx, params);
- subst.as_slice(interner).iter().for_each(|p| {
- var_values.push(p.lower_into(interner).fold_with(&mut reverse_param_substitutor));
- });
- let variables: Vec<_> = binders
- .iter(interner)
- .map(|var| {
- let kind = match var.kind {
- chalk_ir::VariableKind::Ty(ty_kind) => CanonicalVarKind::Ty(match ty_kind {
- chalk_ir::TyVariableKind::General => CanonicalTyVarKind::General(
- ty::UniverseIndex::from_usize(var.skip_kind().counter),
- ),
- chalk_ir::TyVariableKind::Integer => CanonicalTyVarKind::Int,
- chalk_ir::TyVariableKind::Float => CanonicalTyVarKind::Float,
- }),
- chalk_ir::VariableKind::Lifetime => CanonicalVarKind::Region(
+ let var_values = tcx.mk_substs_from_iter(
+ subst
+ .as_slice(interner)
+ .iter()
+ .map(|p| p.lower_into(interner).fold_with(&mut reverse_param_substitutor)),
+ );
+ let variables = binders.iter(interner).map(|var| {
+ let kind = match var.kind {
+ chalk_ir::VariableKind::Ty(ty_kind) => CanonicalVarKind::Ty(match ty_kind {
+ chalk_ir::TyVariableKind::General => CanonicalTyVarKind::General(
ty::UniverseIndex::from_usize(var.skip_kind().counter),
),
- // FIXME(compiler-errors): We don't currently have a way of turning
- // a Chalk ty back into a rustc ty, right?
- chalk_ir::VariableKind::Const(_) => todo!(),
- };
- CanonicalVarInfo { kind }
- })
- .collect();
+ chalk_ir::TyVariableKind::Integer => CanonicalTyVarKind::Int,
+ chalk_ir::TyVariableKind::Float => CanonicalTyVarKind::Float,
+ }),
+ chalk_ir::VariableKind::Lifetime => {
+ CanonicalVarKind::Region(ty::UniverseIndex::from_usize(var.skip_kind().counter))
+ }
+ // FIXME(compiler-errors): We don't currently have a way of turning
+ // a Chalk ty back into a rustc ty, right?
+ chalk_ir::VariableKind::Const(_) => todo!(),
+ };
+ CanonicalVarInfo { kind }
+ });
let max_universe = binders.iter(interner).map(|v| v.skip_kind().counter).max().unwrap_or(0);
let sol = Canonical {
max_universe: ty::UniverseIndex::from_usize(max_universe),
- variables: tcx.intern_canonical_var_infos(&variables),
+ variables: tcx.mk_canonical_var_infos_from_iter(variables),
value: QueryResponse {
var_values: CanonicalVarValues { var_values },
region_constraints: QueryRegionConstraints::default(),
@@ -159,8 +153,7 @@ pub(crate) fn evaluate_goal<'tcx>(
max_universe: ty::UniverseIndex::from_usize(0),
variables: obligation.variables,
value: QueryResponse {
- var_values: CanonicalVarValues { var_values: IndexVec::new() }
- .make_identity(tcx),
+ var_values: CanonicalVarValues::dummy(),
region_constraints: QueryRegionConstraints::default(),
certainty: Certainty::Ambiguous,
opaque_types: vec![],
diff --git a/compiler/rustc_traits/src/codegen.rs b/compiler/rustc_traits/src/codegen.rs
index c0da8a816..6f81d343e 100644
--- a/compiler/rustc_traits/src/codegen.rs
+++ b/compiler/rustc_traits/src/codegen.rs
@@ -4,7 +4,7 @@
// general routines.
use rustc_infer::infer::{DefiningAnchor, TyCtxtInferExt};
-use rustc_infer::traits::FulfillmentErrorCode;
+use rustc_infer::traits::{FulfillmentErrorCode, TraitEngineExt as _};
use rustc_middle::traits::CodegenObligationError;
use rustc_middle::ty::{self, TyCtxt};
use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt;
diff --git a/compiler/rustc_traits/src/dropck_outlives.rs b/compiler/rustc_traits/src/dropck_outlives.rs
index 481b56e11..b5924e949 100644
--- a/compiler/rustc_traits/src/dropck_outlives.rs
+++ b/compiler/rustc_traits/src/dropck_outlives.rs
@@ -164,7 +164,8 @@ fn dtorck_constraint_for_ty<'tcx>(
| ty::Ref(..)
| ty::FnDef(..)
| ty::FnPtr(_)
- | ty::GeneratorWitness(..) => {
+ | ty::GeneratorWitness(..)
+ | ty::GeneratorWitnessMIR(..) => {
// these types never have a destructor
}
@@ -307,7 +308,7 @@ pub(crate) fn adt_dtorck_constraint(
let mut result = DropckConstraint::empty();
for field in def.all_fields() {
- let fty = tcx.type_of(field.did);
+ let fty = tcx.type_of(field.did).subst_identity();
dtorck_constraint_for_ty(tcx, span, fty, 0, fty, &mut result)?;
}
result.outlives.extend(tcx.destructor_constraints(def));
diff --git a/compiler/rustc_traits/src/implied_outlives_bounds.rs b/compiler/rustc_traits/src/implied_outlives_bounds.rs
index 7d2d8433c..ddd4ca143 100644
--- a/compiler/rustc_traits/src/implied_outlives_bounds.rs
+++ b/compiler/rustc_traits/src/implied_outlives_bounds.rs
@@ -2,13 +2,13 @@
//! Do not call this query directory. See
//! [`rustc_trait_selection::traits::query::type_op::implied_outlives_bounds`].
-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::TyCtxtInferExt;
use rustc_infer::traits::query::OutlivesBound;
use rustc_middle::ty::query::Providers;
-use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitable};
+use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt};
+use rustc_span::def_id::CRATE_DEF_ID;
use rustc_span::source_map::DUMMY_SP;
use rustc_trait_selection::infer::InferCtxtBuilderExt;
use rustc_trait_selection::traits::query::{CanonicalTyGoal, Fallible, NoSolution};
@@ -67,51 +67,69 @@ fn compute_implied_outlives_bounds<'tcx>(
// FIXME(@lcnr): It's not really "always fine", having fewer implied
// bounds can be backward incompatible, e.g. #101951 was caused by
// us not dealing with inference vars in `TypeOutlives` predicates.
- let obligations =
- wf::obligations(ocx.infcx, param_env, hir::CRATE_HIR_ID, 0, arg, DUMMY_SP)
- .unwrap_or_default();
-
- // While these predicates should all be implied by other parts of
- // the program, they are still relevant as they may constrain
- // inference variables, which is necessary to add the correct
- // implied bounds in some cases, mostly when dealing with projections.
- ocx.register_obligations(
- obligations.iter().filter(|o| o.predicate.has_non_region_infer()).cloned(),
- );
-
- // From the full set of obligations, just filter down to the
- // region relationships.
- outlives_bounds.extend(obligations.into_iter().filter_map(|obligation| {
+ let obligations = wf::obligations(ocx.infcx, param_env, CRATE_DEF_ID, 0, arg, DUMMY_SP)
+ .unwrap_or_default();
+
+ for obligation in obligations {
+ debug!(?obligation);
assert!(!obligation.has_escaping_bound_vars());
- match obligation.predicate.kind().no_bound_vars() {
- None => None,
- Some(pred) => match pred {
- ty::PredicateKind::Clause(ty::Clause::Trait(..))
- | ty::PredicateKind::Subtype(..)
- | ty::PredicateKind::Coerce(..)
- | ty::PredicateKind::Clause(ty::Clause::Projection(..))
- | ty::PredicateKind::ClosureKind(..)
- | ty::PredicateKind::ObjectSafe(..)
- | ty::PredicateKind::ConstEvaluatable(..)
- | ty::PredicateKind::ConstEquate(..)
- | ty::PredicateKind::Ambiguous
- | ty::PredicateKind::TypeWellFormedFromEnv(..) => None,
- ty::PredicateKind::WellFormed(arg) => {
- wf_args.push(arg);
- None
+
+ // While these predicates should all be implied by other parts of
+ // the program, they are still relevant as they may constrain
+ // inference variables, which is necessary to add the correct
+ // implied bounds in some cases, mostly when dealing with projections.
+ //
+ // Another important point here: we only register `Projection`
+ // predicates, since otherwise we might register outlives
+ // predicates containing inference variables, and we don't
+ // learn anything new from those.
+ if obligation.predicate.has_non_region_infer() {
+ match obligation.predicate.kind().skip_binder() {
+ ty::PredicateKind::Clause(ty::Clause::Projection(..))
+ | ty::PredicateKind::AliasEq(..) => {
+ ocx.register_obligation(obligation.clone());
}
+ _ => {}
+ }
+ }
- ty::PredicateKind::Clause(ty::Clause::RegionOutlives(
- ty::OutlivesPredicate(r_a, r_b),
- )) => Some(ty::OutlivesPredicate(r_a.into(), r_b)),
+ let pred = match obligation.predicate.kind().no_bound_vars() {
+ None => continue,
+ Some(pred) => pred,
+ };
+ match pred {
+ ty::PredicateKind::Clause(ty::Clause::Trait(..))
+ // FIXME(const_generics): Make sure that `<'a, 'b, const N: &'a &'b u32>` is sound
+ // if we ever support that
+ | ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(..))
+ | ty::PredicateKind::Subtype(..)
+ | ty::PredicateKind::Coerce(..)
+ | ty::PredicateKind::Clause(ty::Clause::Projection(..))
+ | ty::PredicateKind::ClosureKind(..)
+ | ty::PredicateKind::ObjectSafe(..)
+ | ty::PredicateKind::ConstEvaluatable(..)
+ | ty::PredicateKind::ConstEquate(..)
+ | ty::PredicateKind::Ambiguous
+ | ty::PredicateKind::AliasEq(..)
+ | ty::PredicateKind::TypeWellFormedFromEnv(..) => {}
+
+ // We need to search through *all* WellFormed predicates
+ ty::PredicateKind::WellFormed(arg) => {
+ wf_args.push(arg);
+ }
+
+ // We need to register region relationships
+ ty::PredicateKind::Clause(ty::Clause::RegionOutlives(ty::OutlivesPredicate(
+ r_a,
+ r_b,
+ ))) => outlives_bounds.push(ty::OutlivesPredicate(r_a.into(), r_b)),
- ty::PredicateKind::Clause(ty::Clause::TypeOutlives(ty::OutlivesPredicate(
- ty_a,
- r_b,
- ))) => Some(ty::OutlivesPredicate(ty_a.into(), r_b)),
- },
+ ty::PredicateKind::Clause(ty::Clause::TypeOutlives(ty::OutlivesPredicate(
+ ty_a,
+ r_b,
+ ))) => outlives_bounds.push(ty::OutlivesPredicate(ty_a.into(), r_b)),
}
- }));
+ }
}
// This call to `select_all_or_error` is necessary to constrain inference variables, which we
diff --git a/compiler/rustc_traits/src/lib.rs b/compiler/rustc_traits/src/lib.rs
index 9aa26667e..8bea5588a 100644
--- a/compiler/rustc_traits/src/lib.rs
+++ b/compiler/rustc_traits/src/lib.rs
@@ -4,6 +4,7 @@
#![deny(rustc::untranslatable_diagnostic)]
#![deny(rustc::diagnostic_outside_of_impl)]
#![feature(let_chains)]
+#![feature(drain_filter)]
#![recursion_limit = "256"]
#[macro_use]
diff --git a/compiler/rustc_traits/src/normalize_erasing_regions.rs b/compiler/rustc_traits/src/normalize_erasing_regions.rs
index 5cad2c2cc..f0597f192 100644
--- a/compiler/rustc_traits/src/normalize_erasing_regions.rs
+++ b/compiler/rustc_traits/src/normalize_erasing_regions.rs
@@ -1,7 +1,7 @@
use rustc_infer::infer::TyCtxtInferExt;
use rustc_middle::traits::query::NoSolution;
use rustc_middle::ty::query::Providers;
-use rustc_middle::ty::{self, ParamEnvAnd, TyCtxt, TypeFoldable};
+use rustc_middle::ty::{self, ParamEnvAnd, TyCtxt, TypeFoldable, TypeVisitableExt};
use rustc_trait_selection::traits::query::normalize::QueryNormalizeExt;
use rustc_trait_selection::traits::{Normalized, ObligationCause};
use std::sync::atomic::Ordering;
@@ -22,7 +22,7 @@ pub(crate) fn provide(p: &mut Providers) {
};
}
-fn try_normalize_after_erasing_regions<'tcx, T: TypeFoldable<'tcx> + PartialEq + Copy>(
+fn try_normalize_after_erasing_regions<'tcx, T: TypeFoldable<TyCtxt<'tcx>> + PartialEq + Copy>(
tcx: TyCtxt<'tcx>,
goal: ParamEnvAnd<'tcx, T>,
) -> Result<T, NoSolution> {
@@ -60,6 +60,8 @@ fn not_outlives_predicate(p: ty::Predicate<'_>) -> bool {
| ty::PredicateKind::Clause(ty::Clause::TypeOutlives(..)) => false,
ty::PredicateKind::Clause(ty::Clause::Trait(..))
| ty::PredicateKind::Clause(ty::Clause::Projection(..))
+ | ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(..))
+ | ty::PredicateKind::AliasEq(..)
| ty::PredicateKind::WellFormed(..)
| ty::PredicateKind::ObjectSafe(..)
| ty::PredicateKind::ClosureKind(..)
diff --git a/compiler/rustc_traits/src/type_op.rs b/compiler/rustc_traits/src/type_op.rs
index f35c5e448..e0fd487b3 100644
--- a/compiler/rustc_traits/src/type_op.rs
+++ b/compiler/rustc_traits/src/type_op.rs
@@ -6,6 +6,7 @@ use rustc_middle::ty::query::Providers;
use rustc_middle::ty::{self, FnSig, Lift, PolyFnSig, Ty, TyCtxt, TypeFoldable};
use rustc_middle::ty::{ParamEnvAnd, Predicate};
use rustc_middle::ty::{UserSelfTy, UserSubsts, UserType};
+use rustc_span::def_id::CRATE_DEF_ID;
use rustc_span::{Span, DUMMY_SP};
use rustc_trait_selection::infer::InferCtxtBuilderExt;
use rustc_trait_selection::traits::query::normalize::QueryNormalizeExt;
@@ -76,7 +77,6 @@ fn relate_mir_and_user_ty<'tcx>(
// FIXME(#104764): We should check well-formedness before normalization.
let predicate = ty::Binder::dummy(ty::PredicateKind::WellFormed(user_ty.into()));
ocx.register_obligation(Obligation::new(ocx.infcx.tcx, cause, param_env, predicate));
-
Ok(())
}
@@ -93,7 +93,7 @@ fn relate_mir_and_user_substs<'tcx>(
let tcx = ocx.infcx.tcx;
let cause = ObligationCause::dummy_with_span(span);
- let ty = tcx.bound_type_of(def_id).subst(tcx, substs);
+ let ty = tcx.type_of(def_id).subst(tcx, substs);
let ty = ocx.normalize(&cause, param_env, ty);
debug!("relate_type_and_user_type: ty of def-id is {:?}", ty);
@@ -111,7 +111,7 @@ fn relate_mir_and_user_substs<'tcx>(
let span = if span == DUMMY_SP { predicate_span } else { span };
let cause = ObligationCause::new(
span,
- hir::CRATE_HIR_ID,
+ CRATE_DEF_ID,
ObligationCauseCode::AscribeUserTypeProvePredicate(predicate_span),
);
let instantiated_predicate =
@@ -122,11 +122,10 @@ fn relate_mir_and_user_substs<'tcx>(
if let Some(UserSelfTy { impl_def_id, self_ty }) = user_self_ty {
let self_ty = ocx.normalize(&cause, param_env, self_ty);
- let impl_self_ty = tcx.bound_type_of(impl_def_id).subst(tcx, substs);
+ let impl_self_ty = tcx.type_of(impl_def_id).subst(tcx, substs);
let impl_self_ty = ocx.normalize(&cause, param_env, impl_self_ty);
ocx.eq(&cause, param_env, self_ty, impl_self_ty)?;
-
let predicate = ty::Binder::dummy(ty::PredicateKind::WellFormed(impl_self_ty.into()));
ocx.register_obligation(Obligation::new(tcx, cause.clone(), param_env, predicate));
}
@@ -162,7 +161,7 @@ fn type_op_normalize<'tcx, T>(
key: ParamEnvAnd<'tcx, Normalize<T>>,
) -> Fallible<T>
where
- T: fmt::Debug + TypeFoldable<'tcx> + Lift<'tcx>,
+ T: fmt::Debug + TypeFoldable<TyCtxt<'tcx>> + Lift<'tcx>,
{
let (param_env, Normalize { value }) = key.into_parts();
let Normalized { value, obligations } =
diff --git a/compiler/rustc_transmute/src/layout/tree.rs b/compiler/rustc_transmute/src/layout/tree.rs
index 30e20ba6f..295b65c2c 100644
--- a/compiler/rustc_transmute/src/layout/tree.rs
+++ b/compiler/rustc_transmute/src/layout/tree.rs
@@ -284,8 +284,9 @@ pub(crate) mod rustc {
}
ty::Array(ty, len) => {
- let len =
- len.try_eval_usize(tcx, ParamEnv::reveal_all()).ok_or(Err::Unspecified)?;
+ let len = len
+ .try_eval_target_usize(tcx, ParamEnv::reveal_all())
+ .ok_or(Err::Unspecified)?;
let elt = Tree::from_ty(*ty, tcx)?;
Ok(std::iter::repeat(elt)
.take(len as usize)
diff --git a/compiler/rustc_transmute/src/lib.rs b/compiler/rustc_transmute/src/lib.rs
index b3b9a67b2..4b4a8ebd0 100644
--- a/compiler/rustc_transmute/src/lib.rs
+++ b/compiler/rustc_transmute/src/lib.rs
@@ -117,7 +117,7 @@ mod rustc {
c: Const<'tcx>,
) -> Option<Self> {
use rustc_middle::ty::ScalarInt;
- use rustc_middle::ty::TypeVisitable;
+ use rustc_middle::ty::TypeVisitableExt;
use rustc_span::symbol::sym;
let c = c.eval(tcx, param_env);
diff --git a/compiler/rustc_error_messages/locales/en-US/ty_utils.ftl b/compiler/rustc_ty_utils/locales/en-US.ftl
index abe65a0e3..abe65a0e3 100644
--- a/compiler/rustc_error_messages/locales/en-US/ty_utils.ftl
+++ b/compiler/rustc_ty_utils/locales/en-US.ftl
diff --git a/compiler/rustc_ty_utils/src/abi.rs b/compiler/rustc_ty_utils/src/abi.rs
index 91a505a72..35c9f95eb 100644
--- a/compiler/rustc_ty_utils/src/abi.rs
+++ b/compiler/rustc_ty_utils/src/abi.rs
@@ -41,7 +41,7 @@ fn fn_sig_for_fn_abi<'tcx>(
// We normalize the `fn_sig` again after substituting at a later point.
let mut sig = match *ty.kind() {
ty::FnDef(def_id, substs) => tcx
- .bound_fn_sig(def_id)
+ .fn_sig(def_id)
.map_bound(|fn_sig| {
tcx.normalize_erasing_regions(tcx.param_env(def_id), fn_sig)
})
@@ -54,7 +54,7 @@ fn fn_sig_for_fn_abi<'tcx>(
sig = sig.map_bound(|mut sig| {
let mut inputs_and_output = sig.inputs_and_output.to_vec();
inputs_and_output[0] = tcx.mk_mut_ptr(inputs_and_output[0]);
- sig.inputs_and_output = tcx.intern_type_list(&inputs_and_output);
+ sig.inputs_and_output = tcx.mk_type_list(&inputs_and_output);
sig
});
}
@@ -63,14 +63,14 @@ fn fn_sig_for_fn_abi<'tcx>(
ty::Closure(def_id, substs) => {
let sig = substs.as_closure().sig();
- let bound_vars = tcx.mk_bound_variable_kinds(
+ let bound_vars = tcx.mk_bound_variable_kinds_from_iter(
sig.bound_vars().iter().chain(iter::once(ty::BoundVariableKind::Region(ty::BrEnv))),
);
let br = ty::BoundRegion {
var: ty::BoundVar::from_usize(bound_vars.len() - 1),
kind: ty::BoundRegionKind::BrEnv,
};
- let env_region = ty::ReLateBound(ty::INNERMOST, br);
+ let env_region = tcx.mk_re_late_bound(ty::INNERMOST, br);
let env_ty = tcx.closure_env_ty(def_id, substs, env_region).unwrap();
let sig = sig.skip_binder();
@@ -88,19 +88,18 @@ fn fn_sig_for_fn_abi<'tcx>(
ty::Generator(did, substs, _) => {
let sig = substs.as_generator().poly_sig();
- let bound_vars = tcx.mk_bound_variable_kinds(
+ let bound_vars = tcx.mk_bound_variable_kinds_from_iter(
sig.bound_vars().iter().chain(iter::once(ty::BoundVariableKind::Region(ty::BrEnv))),
);
let br = ty::BoundRegion {
var: ty::BoundVar::from_usize(bound_vars.len() - 1),
kind: ty::BoundRegionKind::BrEnv,
};
- let env_region = ty::ReLateBound(ty::INNERMOST, br);
- let env_ty = tcx.mk_mut_ref(tcx.mk_region(env_region), ty);
+ let env_ty = tcx.mk_mut_ref(tcx.mk_re_late_bound(ty::INNERMOST, br), ty);
let pin_did = tcx.require_lang_item(LangItem::Pin, None);
let pin_adt_ref = tcx.adt_def(pin_did);
- let pin_substs = tcx.intern_substs(&[env_ty.into()]);
+ let pin_substs = tcx.mk_substs(&[env_ty.into()]);
let env_ty = tcx.mk_adt(pin_adt_ref, pin_substs);
let sig = sig.skip_binder();
@@ -112,7 +111,7 @@ fn fn_sig_for_fn_abi<'tcx>(
// The signature should be `Future::poll(_, &mut Context<'_>) -> Poll<Output>`
let poll_did = tcx.require_lang_item(LangItem::Poll, None);
let poll_adt_ref = tcx.adt_def(poll_did);
- let poll_substs = tcx.intern_substs(&[sig.return_ty.into()]);
+ let poll_substs = tcx.mk_substs(&[sig.return_ty.into()]);
let ret_ty = tcx.mk_adt(poll_adt_ref, poll_substs);
// We have to replace the `ResumeTy` that is used for type and borrow checking
@@ -134,7 +133,7 @@ fn fn_sig_for_fn_abi<'tcx>(
// The signature should be `Generator::resume(_, Resume) -> GeneratorState<Yield, Return>`
let state_did = tcx.require_lang_item(LangItem::GeneratorState, None);
let state_adt_ref = tcx.adt_def(state_did);
- let state_substs = tcx.intern_substs(&[sig.yield_ty.into(), sig.return_ty.into()]);
+ let state_substs = tcx.mk_substs(&[sig.yield_ty.into(), sig.return_ty.into()]);
let ret_ty = tcx.mk_adt(state_adt_ref, state_substs);
(sig.resume_ty, ret_ty)
@@ -142,8 +141,8 @@ fn fn_sig_for_fn_abi<'tcx>(
ty::Binder::bind_with_vars(
tcx.mk_fn_sig(
- [env_ty, resume_ty].iter(),
- &ret_ty,
+ [env_ty, resume_ty],
+ ret_ty,
false,
hir::Unsafety::Normal,
rustc_target::spec::abi::Abi::Rust,
@@ -207,11 +206,8 @@ fn fn_abi_of_instance<'tcx>(
let sig = fn_sig_for_fn_abi(tcx, instance, param_env);
- let caller_location = if instance.def.requires_caller_location(tcx) {
- Some(tcx.caller_location_ty())
- } else {
- None
- };
+ let caller_location =
+ instance.def.requires_caller_location(tcx).then(|| tcx.caller_location_ty());
fn_abi_new_uncached(
&LayoutCx { tcx, param_env },
@@ -244,7 +240,7 @@ fn adjust_for_rust_scalar<'tcx>(
}
// Only pointer types handled below.
- let Scalar::Initialized { value: Pointer, valid_range} = scalar else { return };
+ let Scalar::Initialized { value: Pointer(_), valid_range} = scalar else { return };
if !valid_range.contains(0) {
attrs.set(ArgAttribute::NonNull);
@@ -254,15 +250,18 @@ fn adjust_for_rust_scalar<'tcx>(
if let Some(kind) = pointee.safe {
attrs.pointee_align = Some(pointee.align);
- // `Box` (`UniqueBorrowed`) are not necessarily dereferenceable
- // for the entire duration of the function as they can be deallocated
- // at any time. Same for shared mutable references. If LLVM had a
- // way to say "dereferenceable on entry" we could use it here.
+ // `Box` are not necessarily dereferenceable for the entire duration of the function as
+ // they can be deallocated at any time. Same for non-frozen shared references (see
+ // <https://github.com/rust-lang/rust/pull/98017>), and for mutable references to
+ // potentially self-referential types (see
+ // <https://github.com/rust-lang/unsafe-code-guidelines/issues/381>). If LLVM had a way
+ // to say "dereferenceable on entry" we could use it here.
attrs.pointee_size = match kind {
- PointerKind::UniqueBorrowed
- | PointerKind::UniqueBorrowedPinned
- | PointerKind::Frozen => pointee.size,
- PointerKind::SharedMutable | PointerKind::UniqueOwned => Size::ZERO,
+ PointerKind::Box { .. }
+ | PointerKind::SharedRef { frozen: false }
+ | PointerKind::MutableRef { unpin: false } => Size::ZERO,
+ PointerKind::SharedRef { frozen: true }
+ | PointerKind::MutableRef { unpin: true } => pointee.size,
};
// The aliasing rules for `Box<T>` are still not decided, but currently we emit
@@ -275,18 +274,16 @@ fn adjust_for_rust_scalar<'tcx>(
// versions at all anymore. We still support turning it off using -Zmutable-noalias.
let noalias_mut_ref = cx.tcx.sess.opts.unstable_opts.mutable_noalias;
- // `&mut` pointer parameters never alias other parameters,
- // or mutable global data
+ // `&T` where `T` contains no `UnsafeCell<U>` is immutable, and can be marked as both
+ // `readonly` and `noalias`, as LLVM's definition of `noalias` is based solely on memory
+ // dependencies rather than pointer equality. However this only applies to arguments,
+ // not return values.
//
- // `&T` where `T` contains no `UnsafeCell<U>` is immutable,
- // and can be marked as both `readonly` and `noalias`, as
- // LLVM's definition of `noalias` is based solely on memory
- // dependencies rather than pointer equality
+ // `&mut T` and `Box<T>` where `T: Unpin` are unique and hence `noalias`.
let no_alias = match kind {
- PointerKind::SharedMutable | PointerKind::UniqueBorrowedPinned => false,
- PointerKind::UniqueBorrowed => noalias_mut_ref,
- PointerKind::UniqueOwned => noalias_for_box,
- PointerKind::Frozen => true,
+ PointerKind::SharedRef { frozen } => frozen,
+ PointerKind::MutableRef { unpin } => unpin && noalias_mut_ref,
+ PointerKind::Box { unpin } => unpin && noalias_for_box,
};
// We can never add `noalias` in return position; that LLVM attribute has some very surprising semantics
// (see <https://github.com/rust-lang/unsafe-code-guidelines/issues/385#issuecomment-1368055745>).
@@ -294,7 +291,7 @@ fn adjust_for_rust_scalar<'tcx>(
attrs.set(ArgAttribute::NoAlias);
}
- if kind == PointerKind::Frozen && !is_return {
+ if matches!(kind, PointerKind::SharedRef { frozen: true }) && !is_return {
attrs.set(ArgAttribute::ReadOnly);
}
}
@@ -479,7 +476,7 @@ fn fn_abi_adjust_for_abi<'tcx>(
}
let size = arg.layout.size;
- if arg.layout.is_unsized() || size > Pointer.size(cx) {
+ if arg.layout.is_unsized() || size > Pointer(AddressSpace::DATA).size(cx) {
arg.make_indirect();
} else {
// We want to pass small aggregates as immediates, but using
diff --git a/compiler/rustc_ty_utils/src/assoc.rs b/compiler/rustc_ty_utils/src/assoc.rs
index 424b52309..0648784b2 100644
--- a/compiler/rustc_ty_utils/src/assoc.rs
+++ b/compiler/rustc_ty_utils/src/assoc.rs
@@ -1,13 +1,19 @@
use rustc_data_structures::fx::FxHashMap;
use rustc_hir as hir;
-use rustc_hir::def_id::DefId;
-use rustc_middle::ty::{self, TyCtxt};
+use rustc_hir::def::DefKind;
+use rustc_hir::def_id::{DefId, LocalDefId};
+use rustc_hir::definitions::DefPathData;
+use rustc_hir::intravisit::{self, Visitor};
+use rustc_middle::ty::{self, DefIdTree, ImplTraitInTraitData, InternalSubsts, TyCtxt};
+use rustc_span::symbol::kw;
pub fn provide(providers: &mut ty::query::Providers) {
*providers = ty::query::Providers {
associated_item,
associated_item_def_ids,
associated_items,
+ associated_items_for_impl_trait_in_trait,
+ associated_item_for_impl_trait_in_trait,
impl_item_implementor_ids,
..*providers
};
@@ -16,20 +22,79 @@ pub fn provide(providers: &mut ty::query::Providers) {
fn associated_item_def_ids(tcx: TyCtxt<'_>, def_id: DefId) -> &[DefId] {
let item = tcx.hir().expect_item(def_id.expect_local());
match item.kind {
- hir::ItemKind::Trait(.., ref trait_item_refs) => tcx.arena.alloc_from_iter(
- trait_item_refs.iter().map(|trait_item_ref| trait_item_ref.id.owner_id.to_def_id()),
- ),
- hir::ItemKind::Impl(ref impl_) => tcx.arena.alloc_from_iter(
- impl_.items.iter().map(|impl_item_ref| impl_item_ref.id.owner_id.to_def_id()),
- ),
- hir::ItemKind::TraitAlias(..) => &[],
+ hir::ItemKind::Trait(.., ref trait_item_refs) => {
+ if tcx.sess.opts.unstable_opts.lower_impl_trait_in_trait_to_assoc_ty {
+ // We collect RPITITs for each trait method's return type and create a
+ // corresponding associated item using associated_items_for_impl_trait_in_trait
+ // query.
+ tcx.arena.alloc_from_iter(
+ trait_item_refs
+ .iter()
+ .map(|trait_item_ref| trait_item_ref.id.owner_id.to_def_id())
+ .chain(
+ trait_item_refs
+ .iter()
+ .filter(|trait_item_ref| {
+ matches!(trait_item_ref.kind, hir::AssocItemKind::Fn { .. })
+ })
+ .flat_map(|trait_item_ref| {
+ let trait_fn_def_id =
+ trait_item_ref.id.owner_id.def_id.to_def_id();
+ tcx.associated_items_for_impl_trait_in_trait(trait_fn_def_id)
+ })
+ .map(|def_id| *def_id),
+ ),
+ )
+ } else {
+ tcx.arena.alloc_from_iter(
+ trait_item_refs
+ .iter()
+ .map(|trait_item_ref| trait_item_ref.id.owner_id.to_def_id()),
+ )
+ }
+ }
+ hir::ItemKind::Impl(ref impl_) => {
+ if tcx.sess.opts.unstable_opts.lower_impl_trait_in_trait_to_assoc_ty {
+ // We collect RPITITs for each trait method's return type, on the impl side too and
+ // create a corresponding associated item using
+ // associated_items_for_impl_trait_in_trait query.
+ tcx.arena.alloc_from_iter(
+ impl_
+ .items
+ .iter()
+ .map(|impl_item_ref| impl_item_ref.id.owner_id.to_def_id())
+ .chain(impl_.of_trait.iter().flat_map(|_| {
+ impl_
+ .items
+ .iter()
+ .filter(|impl_item_ref| {
+ matches!(impl_item_ref.kind, hir::AssocItemKind::Fn { .. })
+ })
+ .flat_map(|impl_item_ref| {
+ let impl_fn_def_id =
+ impl_item_ref.id.owner_id.def_id.to_def_id();
+ tcx.associated_items_for_impl_trait_in_trait(impl_fn_def_id)
+ })
+ .map(|def_id| *def_id)
+ })),
+ )
+ } else {
+ tcx.arena.alloc_from_iter(
+ impl_.items.iter().map(|impl_item_ref| impl_item_ref.id.owner_id.to_def_id()),
+ )
+ }
+ }
_ => span_bug!(item.span, "associated_item_def_ids: not impl or trait"),
}
}
-fn associated_items(tcx: TyCtxt<'_>, def_id: DefId) -> ty::AssocItems<'_> {
- let items = tcx.associated_item_def_ids(def_id).iter().map(|did| tcx.associated_item(*did));
- ty::AssocItems::new(items)
+fn associated_items(tcx: TyCtxt<'_>, def_id: DefId) -> ty::AssocItems {
+ if tcx.is_trait_alias(def_id) {
+ ty::AssocItems::new(Vec::new())
+ } else {
+ let items = tcx.associated_item_def_ids(def_id).iter().map(|did| tcx.associated_item(*did));
+ ty::AssocItems::new(items)
+ }
}
fn impl_item_implementor_ids(tcx: TyCtxt<'_>, impl_id: DefId) -> FxHashMap<DefId, DefId> {
@@ -109,3 +174,184 @@ fn associated_item_from_impl_item_ref(impl_item_ref: &hir::ImplItemRef) -> ty::A
fn_has_self_parameter: has_self,
}
}
+
+/// Given an `fn_def_id` of a trait or of an impl that implements a given trait:
+/// if `fn_def_id` is the def id of a function defined inside a trait, then it creates and returns
+/// the associated items that correspond to each impl trait in return position for that trait.
+/// if `fn_def_id` is the def id of a function defined inside an impl that implements a trait, then it
+/// creates and returns the associated items that correspond to each impl trait in return position
+/// of the implemented trait.
+fn associated_items_for_impl_trait_in_trait(tcx: TyCtxt<'_>, fn_def_id: DefId) -> &'_ [DefId] {
+ let parent_def_id = tcx.parent(fn_def_id);
+
+ match tcx.def_kind(parent_def_id) {
+ DefKind::Trait => {
+ struct RPITVisitor {
+ rpits: Vec<LocalDefId>,
+ }
+
+ impl<'v> Visitor<'v> for RPITVisitor {
+ fn visit_ty(&mut self, ty: &'v hir::Ty<'v>) {
+ if let hir::TyKind::OpaqueDef(item_id, _, _) = ty.kind {
+ self.rpits.push(item_id.owner_id.def_id)
+ }
+ intravisit::walk_ty(self, ty)
+ }
+ }
+
+ let mut visitor = RPITVisitor { rpits: Vec::new() };
+
+ if let Some(output) = tcx.hir().get_fn_output(fn_def_id.expect_local()) {
+ visitor.visit_fn_ret_ty(output);
+
+ tcx.arena.alloc_from_iter(visitor.rpits.iter().map(|opaque_ty_def_id| {
+ tcx.associated_item_for_impl_trait_in_trait(opaque_ty_def_id).to_def_id()
+ }))
+ } else {
+ &[]
+ }
+ }
+
+ DefKind::Impl { .. } => {
+ let Some(trait_fn_def_id) = tcx.associated_item(fn_def_id).trait_item_def_id else { return &[] };
+
+ tcx.arena.alloc_from_iter(
+ tcx.associated_items_for_impl_trait_in_trait(trait_fn_def_id).iter().map(
+ move |trait_assoc_def_id| {
+ impl_associated_item_for_impl_trait_in_trait(
+ tcx,
+ trait_assoc_def_id.expect_local(),
+ fn_def_id.expect_local(),
+ )
+ .to_def_id()
+ },
+ ),
+ )
+ }
+
+ def_kind => bug!(
+ "associated_items_for_impl_trait_in_trait: {:?} should be Trait or Impl but is {:?}",
+ parent_def_id,
+ def_kind
+ ),
+ }
+}
+
+/// Given an `opaque_ty_def_id` corresponding to an impl trait in trait, create and return the
+/// corresponding associated item.
+fn associated_item_for_impl_trait_in_trait(
+ tcx: TyCtxt<'_>,
+ opaque_ty_def_id: LocalDefId,
+) -> LocalDefId {
+ let fn_def_id = tcx.impl_trait_in_trait_parent(opaque_ty_def_id.to_def_id());
+ let trait_def_id = tcx.parent(fn_def_id);
+ assert_eq!(tcx.def_kind(trait_def_id), DefKind::Trait);
+
+ let span = tcx.def_span(opaque_ty_def_id);
+ let trait_assoc_ty =
+ tcx.at(span).create_def(trait_def_id.expect_local(), DefPathData::ImplTraitAssocTy);
+
+ let local_def_id = trait_assoc_ty.def_id();
+ let def_id = local_def_id.to_def_id();
+
+ trait_assoc_ty.opt_def_kind(Some(DefKind::AssocTy));
+
+ // There's no HIR associated with this new synthesized `def_id`, so feed
+ // `opt_local_def_id_to_hir_id` with `None`.
+ trait_assoc_ty.opt_local_def_id_to_hir_id(None);
+
+ // Copy span of the opaque.
+ trait_assoc_ty.def_ident_span(Some(span));
+
+ // Add the def_id of the function and opaque that generated this synthesized associated type.
+ trait_assoc_ty.opt_rpitit_info(Some(ImplTraitInTraitData::Trait {
+ fn_def_id,
+ opaque_def_id: opaque_ty_def_id.to_def_id(),
+ }));
+
+ trait_assoc_ty.associated_item(ty::AssocItem {
+ name: kw::Empty,
+ kind: ty::AssocKind::Type,
+ def_id,
+ trait_item_def_id: None,
+ container: ty::TraitContainer,
+ fn_has_self_parameter: false,
+ });
+
+ // Copy visility of the containing function.
+ trait_assoc_ty.visibility(tcx.visibility(fn_def_id));
+
+ // Copy impl_defaultness of the containing function.
+ trait_assoc_ty.impl_defaultness(tcx.impl_defaultness(fn_def_id));
+
+ // Copy type_of of the opaque.
+ trait_assoc_ty.type_of(ty::EarlyBinder(tcx.mk_opaque(
+ opaque_ty_def_id.to_def_id(),
+ InternalSubsts::identity_for_item(tcx, opaque_ty_def_id.to_def_id()),
+ )));
+
+ // Copy generics_of of the opaque.
+ trait_assoc_ty.generics_of(tcx.generics_of(opaque_ty_def_id).clone());
+
+ // There are no predicates for the synthesized associated type.
+ trait_assoc_ty.explicit_predicates_of(ty::GenericPredicates {
+ parent: Some(trait_def_id),
+ predicates: &[],
+ });
+
+ // There are no inferred outlives for the synthesized associated type.
+ trait_assoc_ty.inferred_outlives_of(&[]);
+
+ // FIXME implement this.
+ trait_assoc_ty.explicit_item_bounds(&[]);
+
+ local_def_id
+}
+
+/// Given an `trait_assoc_def_id` that corresponds to a previously synthesized impl trait in trait
+/// into an associated type and an `impl_def_id` corresponding to an impl block, create and return
+/// the corresponding associated item inside the impl block.
+fn impl_associated_item_for_impl_trait_in_trait(
+ tcx: TyCtxt<'_>,
+ trait_assoc_def_id: LocalDefId,
+ impl_fn_def_id: LocalDefId,
+) -> LocalDefId {
+ let impl_def_id = tcx.local_parent(impl_fn_def_id);
+
+ // FIXME fix the span, we probably want the def_id of the return type of the function
+ let span = tcx.def_span(impl_fn_def_id);
+ let impl_assoc_ty = tcx.at(span).create_def(impl_def_id, DefPathData::ImplTraitAssocTy);
+
+ let local_def_id = impl_assoc_ty.def_id();
+ let def_id = local_def_id.to_def_id();
+
+ impl_assoc_ty.opt_def_kind(Some(DefKind::AssocTy));
+
+ // There's no HIR associated with this new synthesized `def_id`, so feed
+ // `opt_local_def_id_to_hir_id` with `None`.
+ impl_assoc_ty.opt_local_def_id_to_hir_id(None);
+
+ // Add the def_id of the function that generated this synthesized associated type.
+ impl_assoc_ty.opt_rpitit_info(Some(ImplTraitInTraitData::Impl {
+ fn_def_id: impl_fn_def_id.to_def_id(),
+ }));
+
+ impl_assoc_ty.associated_item(ty::AssocItem {
+ name: kw::Empty,
+ kind: ty::AssocKind::Type,
+ def_id,
+ trait_item_def_id: Some(trait_assoc_def_id.to_def_id()),
+ container: ty::ImplContainer,
+ fn_has_self_parameter: false,
+ });
+
+ // Copy impl_defaultness of the containing function.
+ impl_assoc_ty.impl_defaultness(tcx.impl_defaultness(impl_fn_def_id));
+
+ // Copy generics_of the trait's associated item.
+ // FIXME: This is not correct, in particular the parent is going to be wrong. So we would need
+ // to copy from trait_assoc_def_id and adjust things.
+ impl_assoc_ty.generics_of(tcx.generics_of(trait_assoc_def_id).clone());
+
+ local_def_id
+}
diff --git a/compiler/rustc_ty_utils/src/consts.rs b/compiler/rustc_ty_utils/src/consts.rs
index a9fbad55d..f26352716 100644
--- a/compiler/rustc_ty_utils/src/consts.rs
+++ b/compiler/rustc_ty_utils/src/consts.rs
@@ -5,7 +5,7 @@ use rustc_middle::mir::interpret::{LitToConstError, LitToConstInput};
use rustc_middle::thir::visit;
use rustc_middle::thir::visit::Visitor;
use rustc_middle::ty::abstract_const::CastKind;
-use rustc_middle::ty::{self, Expr, TyCtxt, TypeVisitable};
+use rustc_middle::ty::{self, Expr, TyCtxt, TypeVisitableExt};
use rustc_middle::{mir, thir};
use rustc_span::Span;
use rustc_target::abi::VariantIdx;
@@ -144,7 +144,7 @@ fn recurse_build<'tcx>(
for &id in args.iter() {
new_args.push(recurse_build(tcx, body, id, root_span)?);
}
- let new_args = tcx.mk_const_list(new_args.iter());
+ let new_args = tcx.mk_const_list(&new_args);
tcx.mk_const(Expr::FunctionCall(fun, new_args), node.ty)
}
&ExprKind::Binary { op, lhs, rhs } if check_binop(op) => {
diff --git a/compiler/rustc_ty_utils/src/errors.rs b/compiler/rustc_ty_utils/src/errors.rs
index c05eeb353..ab3e62f04 100644
--- a/compiler/rustc_ty_utils/src/errors.rs
+++ b/compiler/rustc_ty_utils/src/errors.rs
@@ -16,7 +16,7 @@ pub struct NeedsDropOverflow<'tcx> {
pub struct GenericConstantTooComplex {
#[primary_span]
pub span: Span,
- #[note(maybe_supported)]
+ #[note(ty_utils_maybe_supported)]
pub maybe_supported: Option<()>,
#[subdiagnostic]
pub sub: GenericConstantTooComplexSub,
diff --git a/compiler/rustc_ty_utils/src/implied_bounds.rs b/compiler/rustc_ty_utils/src/implied_bounds.rs
index 7a2464580..7fecee2a3 100644
--- a/compiler/rustc_ty_utils/src/implied_bounds.rs
+++ b/compiler/rustc_ty_utils/src/implied_bounds.rs
@@ -9,26 +9,26 @@ pub fn provide(providers: &mut ty::query::Providers) {
fn assumed_wf_types(tcx: TyCtxt<'_>, def_id: DefId) -> &ty::List<Ty<'_>> {
match tcx.def_kind(def_id) {
DefKind::Fn => {
- let sig = tcx.fn_sig(def_id);
+ let sig = tcx.fn_sig(def_id).subst_identity();
let liberated_sig = tcx.liberate_late_bound_regions(def_id, sig);
liberated_sig.inputs_and_output
}
DefKind::AssocFn => {
- let sig = tcx.fn_sig(def_id);
+ let sig = tcx.fn_sig(def_id).subst_identity();
let liberated_sig = tcx.liberate_late_bound_regions(def_id, sig);
let mut assumed_wf_types: Vec<_> =
tcx.assumed_wf_types(tcx.parent(def_id)).as_slice().into();
assumed_wf_types.extend(liberated_sig.inputs_and_output);
- tcx.intern_type_list(&assumed_wf_types)
+ tcx.mk_type_list(&assumed_wf_types)
}
- DefKind::Impl => {
+ DefKind::Impl { .. } => {
match tcx.impl_trait_ref(def_id) {
Some(trait_ref) => {
let types: Vec<_> = trait_ref.skip_binder().substs.types().collect();
- tcx.intern_type_list(&types)
+ tcx.mk_type_list(&types)
}
// Only the impl self type
- None => tcx.intern_type_list(&[tcx.type_of(def_id)]),
+ None => tcx.mk_type_list(&[tcx.type_of(def_id).subst_identity()]),
}
}
DefKind::AssocConst | DefKind::AssocTy => tcx.assumed_wf_types(tcx.parent(def_id)),
diff --git a/compiler/rustc_ty_utils/src/instance.rs b/compiler/rustc_ty_utils/src/instance.rs
index 8d46ba320..2eaeca73d 100644
--- a/compiler/rustc_ty_utils/src/instance.rs
+++ b/compiler/rustc_ty_utils/src/instance.rs
@@ -3,7 +3,7 @@ use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_infer::infer::TyCtxtInferExt;
use rustc_middle::traits::CodegenObligationError;
use rustc_middle::ty::subst::SubstsRef;
-use rustc_middle::ty::{self, Instance, TyCtxt, TypeVisitable};
+use rustc_middle::ty::{self, Instance, TyCtxt, TypeVisitableExt};
use rustc_span::sym;
use rustc_trait_selection::traits;
use traits::{translate_substs, Reveal};
@@ -53,7 +53,8 @@ fn inner_resolve_instance<'tcx>(
)
} else {
let ty = tcx.type_of(def.def_id_for_type_of());
- let item_type = tcx.subst_and_normalize_erasing_regions(substs, param_env, ty);
+ let item_type =
+ tcx.subst_and_normalize_erasing_regions(substs, param_env, ty.skip_binder());
let def = match *item_type.kind() {
ty::FnDef(def_id, ..) if tcx.is_intrinsic(def_id) => {
diff --git a/compiler/rustc_ty_utils/src/layout.rs b/compiler/rustc_ty_utils/src/layout.rs
index 6aa016133..e3132fcc4 100644
--- a/compiler/rustc_ty_utils/src/layout.rs
+++ b/compiler/rustc_ty_utils/src/layout.rs
@@ -7,9 +7,9 @@ use rustc_middle::ty::layout::{
IntegerExt, LayoutCx, LayoutError, LayoutOf, TyAndLayout, MAX_SIMD_LANES,
};
use rustc_middle::ty::{
- self, subst::SubstsRef, AdtDef, EarlyBinder, ReprOptions, Ty, TyCtxt, TypeVisitable,
+ self, subst::SubstsRef, AdtDef, EarlyBinder, ReprOptions, Ty, TyCtxt, TypeVisitableExt,
};
-use rustc_session::{DataTypeKind, FieldInfo, SizeKind, VariantInfo};
+use rustc_session::{DataTypeKind, FieldInfo, FieldKind, SizeKind, VariantInfo};
use rustc_span::symbol::Symbol;
use rustc_span::DUMMY_SP;
use rustc_target::abi::*;
@@ -78,10 +78,10 @@ fn invert_mapping(map: &[u32]) -> Vec<u32> {
fn univariant_uninterned<'tcx>(
cx: &LayoutCx<'tcx, TyCtxt<'tcx>>,
ty: Ty<'tcx>,
- fields: &[TyAndLayout<'_>],
+ fields: &[Layout<'_>],
repr: &ReprOptions,
kind: StructKind,
-) -> Result<LayoutS<VariantIdx>, LayoutError<'tcx>> {
+) -> Result<LayoutS, LayoutError<'tcx>> {
let dl = cx.data_layout();
let pack = repr.pack;
if pack.is_some() && repr.align.is_some() {
@@ -104,23 +104,23 @@ fn layout_of_uncached<'tcx>(
assert!(size.bits() <= 128);
Scalar::Initialized { value, valid_range: WrappingRange::full(size) }
};
- let scalar = |value: Primitive| tcx.intern_layout(LayoutS::scalar(cx, scalar_unit(value)));
+ let scalar = |value: Primitive| tcx.mk_layout(LayoutS::scalar(cx, scalar_unit(value)));
- let univariant = |fields: &[TyAndLayout<'_>], repr: &ReprOptions, kind| {
- Ok(tcx.intern_layout(univariant_uninterned(cx, ty, fields, repr, kind)?))
+ let univariant = |fields: &[Layout<'_>], repr: &ReprOptions, kind| {
+ Ok(tcx.mk_layout(univariant_uninterned(cx, ty, fields, repr, kind)?))
};
debug_assert!(!ty.has_non_region_infer());
Ok(match *ty.kind() {
// Basic scalars.
- ty::Bool => tcx.intern_layout(LayoutS::scalar(
+ ty::Bool => tcx.mk_layout(LayoutS::scalar(
cx,
Scalar::Initialized {
value: Int(I8, false),
valid_range: WrappingRange { start: 0, end: 1 },
},
)),
- ty::Char => tcx.intern_layout(LayoutS::scalar(
+ ty::Char => tcx.mk_layout(LayoutS::scalar(
cx,
Scalar::Initialized {
value: Int(I32, false),
@@ -134,24 +134,24 @@ fn layout_of_uncached<'tcx>(
ty::FloatTy::F64 => F64,
}),
ty::FnPtr(_) => {
- let mut ptr = scalar_unit(Pointer);
+ let mut ptr = scalar_unit(Pointer(dl.instruction_address_space));
ptr.valid_range_mut().start = 1;
- tcx.intern_layout(LayoutS::scalar(cx, ptr))
+ tcx.mk_layout(LayoutS::scalar(cx, ptr))
}
// The never type.
- ty::Never => tcx.intern_layout(cx.layout_of_never_type()),
+ ty::Never => tcx.mk_layout(cx.layout_of_never_type()),
// Potentially-wide pointers.
ty::Ref(_, pointee, _) | ty::RawPtr(ty::TypeAndMut { ty: pointee, .. }) => {
- let mut data_ptr = scalar_unit(Pointer);
+ let mut data_ptr = scalar_unit(Pointer(AddressSpace::DATA));
if !ty.is_unsafe_ptr() {
data_ptr.valid_range_mut().start = 1;
}
let pointee = tcx.normalize_erasing_regions(param_env, pointee);
if pointee.is_sized(tcx, param_env) {
- return Ok(tcx.intern_layout(LayoutS::scalar(cx, data_ptr)));
+ return Ok(tcx.mk_layout(LayoutS::scalar(cx, data_ptr)));
}
let unsized_part = tcx.struct_tail_erasing_lifetimes(pointee, param_env);
@@ -164,7 +164,7 @@ fn layout_of_uncached<'tcx>(
let metadata_layout = cx.layout_of(metadata_ty)?;
// If the metadata is a 1-zst, then the pointer is thin.
if metadata_layout.is_zst() && metadata_layout.align.abi.bytes() == 1 {
- return Ok(tcx.intern_layout(LayoutS::scalar(cx, data_ptr)));
+ return Ok(tcx.mk_layout(LayoutS::scalar(cx, data_ptr)));
}
let Abi::Scalar(metadata) = metadata_layout.abi else {
@@ -174,11 +174,11 @@ fn layout_of_uncached<'tcx>(
} else {
match unsized_part.kind() {
ty::Foreign(..) => {
- return Ok(tcx.intern_layout(LayoutS::scalar(cx, data_ptr)));
+ return Ok(tcx.mk_layout(LayoutS::scalar(cx, data_ptr)));
}
ty::Slice(_) | ty::Str => scalar_unit(Int(dl.ptr_sized_integer(), false)),
ty::Dynamic(..) => {
- let mut vtable = scalar_unit(Pointer);
+ let mut vtable = scalar_unit(Pointer(AddressSpace::DATA));
vtable.valid_range_mut().start = 1;
vtable
}
@@ -189,15 +189,15 @@ fn layout_of_uncached<'tcx>(
};
// Effectively a (ptr, meta) tuple.
- tcx.intern_layout(cx.scalar_pair(data_ptr, metadata))
+ tcx.mk_layout(cx.scalar_pair(data_ptr, metadata))
}
ty::Dynamic(_, _, ty::DynStar) => {
- let mut data = scalar_unit(Int(dl.ptr_sized_integer(), false));
+ let mut data = scalar_unit(Pointer(AddressSpace::DATA));
data.valid_range_mut().start = 0;
- let mut vtable = scalar_unit(Pointer);
+ let mut vtable = scalar_unit(Pointer(AddressSpace::DATA));
vtable.valid_range_mut().start = 1;
- tcx.intern_layout(cx.scalar_pair(data, vtable))
+ tcx.mk_layout(cx.scalar_pair(data, vtable))
}
// Arrays and slices.
@@ -209,7 +209,8 @@ fn layout_of_uncached<'tcx>(
}
}
- let count = count.try_eval_usize(tcx, param_env).ok_or(LayoutError::Unknown(ty))?;
+ let count =
+ count.try_eval_target_usize(tcx, param_env).ok_or(LayoutError::Unknown(ty))?;
let element = cx.layout_of(element)?;
let size = element.size.checked_mul(count, dl).ok_or(LayoutError::SizeOverflow(ty))?;
@@ -221,7 +222,7 @@ fn layout_of_uncached<'tcx>(
let largest_niche = if count != 0 { element.largest_niche } else { None };
- tcx.intern_layout(LayoutS {
+ tcx.mk_layout(LayoutS {
variants: Variants::Single { index: VariantIdx::new(0) },
fields: FieldsShape::Array { stride: element.size, count },
abi,
@@ -232,7 +233,7 @@ fn layout_of_uncached<'tcx>(
}
ty::Slice(element) => {
let element = cx.layout_of(element)?;
- tcx.intern_layout(LayoutS {
+ tcx.mk_layout(LayoutS {
variants: Variants::Single { index: VariantIdx::new(0) },
fields: FieldsShape::Array { stride: element.size, count: 0 },
abi: Abi::Aggregate { sized: false },
@@ -241,7 +242,7 @@ fn layout_of_uncached<'tcx>(
size: Size::ZERO,
})
}
- ty::Str => tcx.intern_layout(LayoutS {
+ ty::Str => tcx.mk_layout(LayoutS {
variants: Variants::Single { index: VariantIdx::new(0) },
fields: FieldsShape::Array { stride: Size::from_bytes(1), count: 0 },
abi: Abi::Aggregate { sized: false },
@@ -264,7 +265,7 @@ fn layout_of_uncached<'tcx>(
Abi::Aggregate { ref mut sized } => *sized = false,
_ => bug!(),
}
- tcx.intern_layout(unit)
+ tcx.mk_layout(unit)
}
ty::Generator(def_id, substs, _) => generator_layout(cx, ty, def_id, substs)?,
@@ -272,7 +273,7 @@ fn layout_of_uncached<'tcx>(
ty::Closure(_, ref substs) => {
let tys = substs.as_closure().upvar_tys();
univariant(
- &tys.map(|ty| cx.layout_of(ty)).collect::<Result<Vec<_>, _>>()?,
+ &tys.map(|ty| Ok(cx.layout_of(ty)?.layout)).collect::<Result<Vec<_>, _>>()?,
&ReprOptions::default(),
StructKind::AlwaysSized,
)?
@@ -283,7 +284,7 @@ fn layout_of_uncached<'tcx>(
if tys.len() == 0 { StructKind::AlwaysSized } else { StructKind::MaybeUnsized };
univariant(
- &tys.iter().map(|k| cx.layout_of(k)).collect::<Result<Vec<_>, _>>()?,
+ &tys.iter().map(|k| Ok(cx.layout_of(k)?.layout)).collect::<Result<Vec<_>, _>>()?,
&ReprOptions::default(),
kind,
)?
@@ -393,7 +394,7 @@ fn layout_of_uncached<'tcx>(
FieldsShape::Array { stride: e_ly.size, count: e_len }
};
- tcx.intern_layout(LayoutS {
+ tcx.mk_layout(LayoutS {
variants: Variants::Single { index: VariantIdx::new(0) },
fields,
abi: Abi::Vector { element: e_abi, count: e_len },
@@ -412,7 +413,7 @@ fn layout_of_uncached<'tcx>(
.map(|v| {
v.fields
.iter()
- .map(|field| cx.layout_of(field.ty(tcx, substs)))
+ .map(|field| Ok(cx.layout_of(field.ty(tcx, substs))?.layout))
.collect::<Result<Vec<_>, _>>()
})
.collect::<Result<IndexVec<VariantIdx, _>, _>>()?;
@@ -426,12 +427,12 @@ fn layout_of_uncached<'tcx>(
return Err(LayoutError::Unknown(ty));
}
- return Ok(tcx.intern_layout(
+ return Ok(tcx.mk_layout(
cx.layout_of_union(&def.repr(), &variants).ok_or(LayoutError::Unknown(ty))?,
));
}
- tcx.intern_layout(
+ tcx.mk_layout(
cx.layout_of_struct_or_enum(
&def.repr(),
&variants,
@@ -452,9 +453,10 @@ fn layout_of_uncached<'tcx>(
let param_env = tcx.param_env(def.did());
def.is_struct()
&& match def.variants().iter().next().and_then(|x| x.fields.last()) {
- Some(last_field) => {
- tcx.type_of(last_field.did).is_sized(tcx, param_env)
- }
+ Some(last_field) => tcx
+ .type_of(last_field.did)
+ .subst_identity()
+ .is_sized(tcx, param_env),
None => false,
}
},
@@ -470,11 +472,11 @@ fn layout_of_uncached<'tcx>(
return Err(LayoutError::Unknown(ty));
}
- ty::Placeholder(..) | ty::GeneratorWitness(..) | ty::Infer(_) => {
+ ty::Bound(..) | ty::GeneratorWitness(..) | ty::GeneratorWitnessMIR(..) | ty::Infer(_) => {
bug!("Layout::compute: unexpected type `{}`", ty)
}
- ty::Bound(..) | ty::Param(_) | ty::Error(_) => {
+ ty::Placeholder(..) | ty::Param(_) | ty::Error(_) => {
return Err(LayoutError::Unknown(ty));
}
})
@@ -630,23 +632,21 @@ fn generator_layout<'tcx>(
// `info.variant_fields` already accounts for the reserved variants, so no need to add them.
let max_discr = (info.variant_fields.len() - 1) as u128;
let discr_int = Integer::fit_unsigned(max_discr);
- let discr_int_ty = discr_int.to_ty(tcx, false);
let tag = Scalar::Initialized {
value: Primitive::Int(discr_int, false),
valid_range: WrappingRange { start: 0, end: max_discr },
};
- let tag_layout = cx.tcx.intern_layout(LayoutS::scalar(cx, tag));
- let tag_layout = TyAndLayout { ty: discr_int_ty, layout: tag_layout };
+ let tag_layout = cx.tcx.mk_layout(LayoutS::scalar(cx, tag));
let promoted_layouts = ineligible_locals
.iter()
- .map(|local| subst_field(info.field_tys[local]))
+ .map(|local| subst_field(info.field_tys[local].ty))
.map(|ty| tcx.mk_maybe_uninit(ty))
- .map(|ty| cx.layout_of(ty));
+ .map(|ty| Ok(cx.layout_of(ty)?.layout));
let prefix_layouts = substs
.as_generator()
.prefix_tys()
- .map(|ty| cx.layout_of(ty))
+ .map(|ty| Ok(cx.layout_of(ty)?.layout))
.chain(iter::once(Ok(tag_layout)))
.chain(promoted_layouts)
.collect::<Result<Vec<_>, _>>()?;
@@ -710,12 +710,14 @@ fn generator_layout<'tcx>(
Assigned(_) => bug!("assignment does not match variant"),
Ineligible(_) => false,
})
- .map(|local| subst_field(info.field_tys[*local]));
+ .map(|local| subst_field(info.field_tys[*local].ty));
let mut variant = univariant_uninterned(
cx,
ty,
- &variant_only_tys.map(|ty| cx.layout_of(ty)).collect::<Result<Vec<_>, _>>()?,
+ &variant_only_tys
+ .map(|ty| Ok(cx.layout_of(ty)?.layout))
+ .collect::<Result<Vec<_>, _>>()?,
&ReprOptions::default(),
StructKind::Prefixed(prefix_size, prefix_align.abi),
)?;
@@ -782,7 +784,7 @@ fn generator_layout<'tcx>(
Abi::Aggregate { sized: true }
};
- let layout = tcx.intern_layout(LayoutS {
+ let layout = tcx.mk_layout(LayoutS {
variants: Variants::Multiple {
tag,
tag_encoding: TagEncoding::Direct,
@@ -878,6 +880,7 @@ fn variant_info_for_adt<'tcx>(
let offset = layout.fields.offset(i);
min_size = min_size.max(offset + field_layout.size);
FieldInfo {
+ kind: FieldKind::AdtField,
name,
offset: offset.bytes(),
size: field_layout.size.bytes(),
@@ -957,6 +960,7 @@ fn variant_info_for_generator<'tcx>(
let offset = layout.fields.offset(field_idx);
upvars_size = upvars_size.max(offset + field_layout.size);
FieldInfo {
+ kind: FieldKind::Upvar,
name: Symbol::intern(&name),
offset: offset.bytes(),
size: field_layout.size.bytes(),
@@ -965,7 +969,7 @@ fn variant_info_for_generator<'tcx>(
})
.collect();
- let variant_infos: Vec<_> = generator
+ let mut variant_infos: Vec<_> = generator
.variant_fields
.iter_enumerated()
.map(|(variant_idx, variant_def)| {
@@ -980,6 +984,7 @@ fn variant_info_for_generator<'tcx>(
// The struct is as large as the last field's end
variant_size = variant_size.max(offset + field_layout.size);
FieldInfo {
+ kind: FieldKind::GeneratorLocal,
name: state_specific_names.get(*local).copied().flatten().unwrap_or(
Symbol::intern(&format!(".generator_field{}", local.as_usize())),
),
@@ -1027,6 +1032,15 @@ fn variant_info_for_generator<'tcx>(
}
})
.collect();
+
+ // The first three variants are hardcoded to be `UNRESUMED`, `RETURNED` and `POISONED`.
+ // We will move the `RETURNED` and `POISONED` elements to the end so we
+ // are left with a sorting order according to the generators yield points:
+ // First `Unresumed`, then the `SuspendN` followed by `Returned` and `Panicked` (POISONED).
+ let end_states = variant_infos.drain(1..=2);
+ let end_states: Vec<_> = end_states.collect();
+ variant_infos.extend(end_states);
+
(
variant_infos,
match tag_encoding {
diff --git a/compiler/rustc_ty_utils/src/lib.rs b/compiler/rustc_ty_utils/src/lib.rs
index 0853de601..35f468aa9 100644
--- a/compiler/rustc_ty_utils/src/lib.rs
+++ b/compiler/rustc_ty_utils/src/lib.rs
@@ -15,6 +15,8 @@ extern crate rustc_middle;
#[macro_use]
extern crate tracing;
+use rustc_errors::{DiagnosticMessage, SubdiagnosticMessage};
+use rustc_macros::fluent_messages;
use rustc_middle::ty::query::Providers;
mod abi;
@@ -31,6 +33,8 @@ pub mod representability;
mod structural_match;
mod ty;
+fluent_messages! { "../locales/en-US.ftl" }
+
pub fn provide(providers: &mut Providers) {
abi::provide(providers);
assoc::provide(providers);
diff --git a/compiler/rustc_ty_utils/src/needs_drop.rs b/compiler/rustc_ty_utils/src/needs_drop.rs
index 0df060fc5..de7fd0031 100644
--- a/compiler/rustc_ty_utils/src/needs_drop.rs
+++ b/compiler/rustc_ty_utils/src/needs_drop.rs
@@ -109,6 +109,13 @@ where
for component in components {
match *component.kind() {
+ // The information required to determine whether a generator has drop is
+ // computed on MIR, while this very method is used to build MIR.
+ // To avoid cycles, we consider that generators always require drop.
+ ty::Generator(..) if tcx.sess.opts.unstable_opts.drop_tracking_mir => {
+ return Some(Err(AlwaysRequiresDrop));
+ }
+
_ if component.is_copy_modulo_regions(tcx, self.param_env) => (),
ty::Closure(_, substs) => {
@@ -235,7 +242,7 @@ fn drop_tys_helper<'tcx>(
Ok(Vec::new())
} else {
let field_tys = adt_def.all_fields().map(|field| {
- let r = tcx.bound_type_of(field.did).subst(tcx, substs);
+ let r = tcx.type_of(field.did).subst(tcx, substs);
debug!("drop_tys_helper: Subst into {:?} with {:?} gettng {:?}", field, substs, r);
r
});
@@ -288,9 +295,15 @@ fn adt_drop_tys<'tcx>(
let adt_has_dtor =
|adt_def: ty::AdtDef<'tcx>| adt_def.destructor(tcx).map(|_| DtorType::Significant);
// `tcx.type_of(def_id)` identical to `tcx.make_adt(def, identity_substs)`
- drop_tys_helper(tcx, tcx.type_of(def_id), tcx.param_env(def_id), adt_has_dtor, false)
- .collect::<Result<Vec<_>, _>>()
- .map(|components| tcx.intern_type_list(&components))
+ drop_tys_helper(
+ tcx,
+ tcx.type_of(def_id).subst_identity(),
+ tcx.param_env(def_id),
+ adt_has_dtor,
+ false,
+ )
+ .collect::<Result<Vec<_>, _>>()
+ .map(|components| tcx.mk_type_list(&components))
}
// If `def_id` refers to a generic ADT, the queries above and below act as if they had been handed
// a `tcx.make_ty(def, identity_substs)` and as such it is legal to substitute the generic parameters
@@ -301,13 +314,13 @@ fn adt_significant_drop_tys(
) -> Result<&ty::List<Ty<'_>>, AlwaysRequiresDrop> {
drop_tys_helper(
tcx,
- tcx.type_of(def_id), // identical to `tcx.make_adt(def, identity_substs)`
+ tcx.type_of(def_id).subst_identity(), // identical to `tcx.make_adt(def, identity_substs)`
tcx.param_env(def_id),
adt_consider_insignificant_dtor(tcx),
true,
)
.collect::<Result<Vec<_>, _>>()
- .map(|components| tcx.intern_type_list(&components))
+ .map(|components| tcx.mk_type_list(&components))
}
pub(crate) fn provide(providers: &mut ty::query::Providers) {
diff --git a/compiler/rustc_ty_utils/src/representability.rs b/compiler/rustc_ty_utils/src/representability.rs
index 7f48fb804..591017eec 100644
--- a/compiler/rustc_ty_utils/src/representability.rs
+++ b/compiler/rustc_ty_utils/src/representability.rs
@@ -31,7 +31,7 @@ fn representability(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Representability {
}
Representability::Representable
}
- DefKind::Field => representability_ty(tcx, tcx.type_of(def_id)),
+ DefKind::Field => representability_ty(tcx, tcx.type_of(def_id).subst_identity()),
def_kind => bug!("unexpected {def_kind:?}"),
}
}
@@ -91,7 +91,7 @@ fn params_in_repr(tcx: TyCtxt<'_>, def_id: DefId) -> BitSet<u32> {
let mut params_in_repr = BitSet::new_empty(generics.params.len());
for variant in adt_def.variants() {
for field in variant.fields.iter() {
- params_in_repr_ty(tcx, tcx.type_of(field.did), &mut params_in_repr);
+ params_in_repr_ty(tcx, tcx.type_of(field.did).subst_identity(), &mut params_in_repr);
}
}
params_in_repr
diff --git a/compiler/rustc_ty_utils/src/ty.rs b/compiler/rustc_ty_utils/src/ty.rs
index eb5454bf2..18159778a 100644
--- a/compiler/rustc_ty_utils/src/ty.rs
+++ b/compiler/rustc_ty_utils/src/ty.rs
@@ -1,8 +1,13 @@
-use rustc_data_structures::fx::FxIndexSet;
+use rustc_data_structures::fx::{FxHashSet, FxIndexSet};
use rustc_hir as hir;
-use rustc_hir::def_id::DefId;
-use rustc_middle::ty::{self, Binder, Predicate, PredicateKind, ToPredicate, Ty, TyCtxt};
+use rustc_hir::def::DefKind;
+use rustc_index::bit_set::BitSet;
+use rustc_middle::ty::{
+ self, Binder, EarlyBinder, Predicate, PredicateKind, ToPredicate, Ty, TyCtxt,
+ TypeSuperVisitable, TypeVisitable, TypeVisitor,
+};
use rustc_session::config::TraitSolver;
+use rustc_span::def_id::{DefId, CRATE_DEF_ID};
use rustc_trait_selection::traits;
fn sized_constraint_for_ty<'tcx>(
@@ -16,7 +21,13 @@ fn sized_constraint_for_ty<'tcx>(
Bool | Char | Int(..) | Uint(..) | Float(..) | RawPtr(..) | Ref(..) | FnDef(..)
| FnPtr(_) | Array(..) | Closure(..) | Generator(..) | Never => vec![],
- Str | Dynamic(..) | Slice(_) | Foreign(..) | Error(_) | GeneratorWitness(..) => {
+ Str
+ | Dynamic(..)
+ | Slice(_)
+ | Foreign(..)
+ | Error(_)
+ | GeneratorWitness(..)
+ | GeneratorWitnessMIR(..) => {
// these are never sized - return the target type
vec![ty]
}
@@ -87,16 +98,16 @@ fn impl_defaultness(tcx: TyCtxt<'_>, def_id: DefId) -> hir::Defaultness {
fn adt_sized_constraint(tcx: TyCtxt<'_>, def_id: DefId) -> &[Ty<'_>] {
if let Some(def_id) = def_id.as_local() {
if matches!(tcx.representability(def_id), ty::Representability::Infinite) {
- return tcx.intern_type_list(&[tcx.ty_error()]);
+ return tcx.mk_type_list(&[tcx.ty_error_misc()]);
}
}
let def = tcx.adt_def(def_id);
- let result = tcx.mk_type_list(
+ let result = tcx.mk_type_list_from_iter(
def.variants()
.iter()
.flat_map(|v| v.fields.last())
- .flat_map(|f| sized_constraint_for_ty(tcx, def, tcx.type_of(f.did))),
+ .flat_map(|f| sized_constraint_for_ty(tcx, def, tcx.type_of(f.did).subst_identity())),
);
debug!("adt_sized_constraint: {:?} => {:?}", def, result);
@@ -127,6 +138,19 @@ fn param_env(tcx: TyCtxt<'_>, def_id: DefId) -> ty::ParamEnv<'_> {
predicates.extend(environment);
}
+ if tcx.def_kind(def_id) == DefKind::AssocFn
+ && tcx.associated_item(def_id).container == ty::AssocItemContainer::TraitContainer
+ {
+ let sig = tcx.fn_sig(def_id).subst_identity();
+ sig.visit_with(&mut ImplTraitInTraitFinder {
+ tcx,
+ fn_def_id: def_id,
+ bound_vars: sig.bound_vars(),
+ predicates: &mut predicates,
+ seen: FxHashSet::default(),
+ });
+ }
+
let local_did = def_id.as_local();
let hir_id = local_did.map(|def_id| tcx.hir().local_def_id_to_hir_id(def_id));
@@ -202,24 +226,54 @@ fn param_env(tcx: TyCtxt<'_>, def_id: DefId) -> ty::ParamEnv<'_> {
None => hir::Constness::NotConst,
};
- let unnormalized_env = ty::ParamEnv::new(
- tcx.intern_predicates(&predicates),
- traits::Reveal::UserFacing,
- constness,
- );
-
- let body_id =
- local_did.and_then(|id| tcx.hir().maybe_body_owned_by(id).map(|body| body.hir_id));
- let body_id = match body_id {
- Some(id) => id,
- None if hir_id.is_some() => hir_id.unwrap(),
- _ => hir::CRATE_HIR_ID,
- };
+ let unnormalized_env =
+ ty::ParamEnv::new(tcx.mk_predicates(&predicates), traits::Reveal::UserFacing, constness);
+ let body_id = local_did.unwrap_or(CRATE_DEF_ID);
let cause = traits::ObligationCause::misc(tcx.def_span(def_id), body_id);
traits::normalize_param_env_or_error(tcx, unnormalized_env, cause)
}
+/// Walk through a function type, gathering all RPITITs and installing a
+/// `NormalizesTo(Projection(RPITIT) -> Opaque(RPITIT))` predicate into the
+/// predicates list. This allows us to observe that an RPITIT projects to
+/// its corresponding opaque within the body of a default-body trait method.
+struct ImplTraitInTraitFinder<'a, 'tcx> {
+ tcx: TyCtxt<'tcx>,
+ predicates: &'a mut Vec<Predicate<'tcx>>,
+ fn_def_id: DefId,
+ bound_vars: &'tcx ty::List<ty::BoundVariableKind>,
+ seen: FxHashSet<DefId>,
+}
+
+impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for ImplTraitInTraitFinder<'_, 'tcx> {
+ fn visit_ty(&mut self, ty: Ty<'tcx>) -> std::ops::ControlFlow<Self::BreakTy> {
+ if let ty::Alias(ty::Projection, alias_ty) = *ty.kind()
+ && self.tcx.def_kind(alias_ty.def_id) == DefKind::ImplTraitPlaceholder
+ && self.tcx.impl_trait_in_trait_parent(alias_ty.def_id) == self.fn_def_id
+ && self.seen.insert(alias_ty.def_id)
+ {
+ self.predicates.push(
+ ty::Binder::bind_with_vars(
+ ty::ProjectionPredicate {
+ projection_ty: alias_ty,
+ term: self.tcx.mk_alias(ty::Opaque, alias_ty).into(),
+ },
+ self.bound_vars,
+ )
+ .to_predicate(self.tcx),
+ );
+
+ for bound in self.tcx.item_bounds(alias_ty.def_id).subst_iter(self.tcx, alias_ty.substs)
+ {
+ bound.visit_with(self);
+ }
+ }
+
+ ty.super_visit_with(self)
+ }
+}
+
/// Elaborate the environment.
///
/// Collect a list of `Predicate`'s used for building the `ParamEnv`. Adds `TypeWellFormedFromEnv`'s
@@ -299,14 +353,14 @@ fn well_formed_types_in_env(tcx: TyCtxt<'_>, def_id: DefId) -> &ty::List<Predica
// In an inherent impl, we assume that the receiver type and all its
// constituents are well-formed.
NodeKind::InherentImpl => {
- let self_ty = tcx.type_of(def_id);
+ let self_ty = tcx.type_of(def_id).subst_identity();
inputs.extend(self_ty.walk());
}
// In an fn, we assume that the arguments and all their constituents are
// well-formed.
NodeKind::Fn => {
- let fn_sig = tcx.fn_sig(def_id);
+ let fn_sig = tcx.fn_sig(def_id).subst_identity();
let fn_sig = tcx.liberate_late_bound_regions(def_id, fn_sig);
inputs.extend(fn_sig.inputs().iter().flat_map(|ty| ty.walk()));
@@ -329,7 +383,7 @@ fn well_formed_types_in_env(tcx: TyCtxt<'_>, def_id: DefId) -> &ty::List<Predica
}
});
- tcx.mk_predicates(clauses.chain(input_clauses))
+ tcx.mk_predicates_from_iter(clauses.chain(input_clauses))
}
fn param_env_reveal_all_normalized(tcx: TyCtxt<'_>, def_id: DefId) -> ty::ParamEnv<'_> {
@@ -355,7 +409,7 @@ fn instance_def_size_estimate<'tcx>(
/// If `def_id` is an issue 33140 hack impl, returns its self type; otherwise, returns `None`.
///
/// See [`ty::ImplOverlapKind::Issue33140`] for more details.
-fn issue33140_self_ty(tcx: TyCtxt<'_>, def_id: DefId) -> Option<Ty<'_>> {
+fn issue33140_self_ty(tcx: TyCtxt<'_>, def_id: DefId) -> Option<EarlyBinder<Ty<'_>>> {
debug!("issue33140_self_ty({:?})", def_id);
let trait_ref = tcx
@@ -394,7 +448,7 @@ fn issue33140_self_ty(tcx: TyCtxt<'_>, def_id: DefId) -> Option<Ty<'_>> {
if self_ty_matches {
debug!("issue33140_self_ty - MATCHES!");
- Some(self_ty)
+ Some(EarlyBinder(self_ty))
} else {
debug!("issue33140_self_ty - non-matching self type");
None
@@ -407,6 +461,52 @@ fn asyncness(tcx: TyCtxt<'_>, def_id: DefId) -> hir::IsAsync {
node.fn_sig().map_or(hir::IsAsync::NotAsync, |sig| sig.header.asyncness)
}
+fn unsizing_params_for_adt<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> BitSet<u32> {
+ let def = tcx.adt_def(def_id);
+ let num_params = tcx.generics_of(def_id).count();
+
+ let maybe_unsizing_param_idx = |arg: ty::GenericArg<'tcx>| match arg.unpack() {
+ ty::GenericArgKind::Type(ty) => match ty.kind() {
+ ty::Param(p) => Some(p.index),
+ _ => None,
+ },
+
+ // We can't unsize a lifetime
+ ty::GenericArgKind::Lifetime(_) => None,
+
+ ty::GenericArgKind::Const(ct) => match ct.kind() {
+ ty::ConstKind::Param(p) => Some(p.index),
+ _ => None,
+ },
+ };
+
+ // The last field of the structure has to exist and contain type/const parameters.
+ let Some((tail_field, prefix_fields)) =
+ def.non_enum_variant().fields.split_last() else
+ {
+ return BitSet::new_empty(num_params);
+ };
+
+ let mut unsizing_params = BitSet::new_empty(num_params);
+ for arg in tcx.type_of(tail_field.did).subst_identity().walk() {
+ if let Some(i) = maybe_unsizing_param_idx(arg) {
+ unsizing_params.insert(i);
+ }
+ }
+
+ // Ensure none of the other fields mention the parameters used
+ // in unsizing.
+ for field in prefix_fields {
+ for arg in tcx.type_of(field.did).subst_identity().walk() {
+ if let Some(i) = maybe_unsizing_param_idx(arg) {
+ unsizing_params.remove(i);
+ }
+ }
+ }
+
+ unsizing_params
+}
+
pub fn provide(providers: &mut ty::query::Providers) {
*providers = ty::query::Providers {
asyncness,
@@ -416,6 +516,7 @@ pub fn provide(providers: &mut ty::query::Providers) {
instance_def_size_estimate,
issue33140_self_ty,
impl_defaultness,
+ unsizing_params_for_adt,
..*providers
};
}
diff --git a/compiler/rustc_type_ir/src/fold.rs b/compiler/rustc_type_ir/src/fold.rs
new file mode 100644
index 000000000..ee4ef57c3
--- /dev/null
+++ b/compiler/rustc_type_ir/src/fold.rs
@@ -0,0 +1,239 @@
+//! A folding traversal mechanism for complex data structures that contain type
+//! information.
+//!
+//! This is a modifying traversal. It consumes the data structure, producing a
+//! (possibly) modified version of it. Both fallible and infallible versions are
+//! available. The name is potentially confusing, because this traversal is more
+//! like `Iterator::map` than `Iterator::fold`.
+//!
+//! This traversal has limited flexibility. Only a small number of "types of
+//! interest" within the complex data structures can receive custom
+//! modification. These are the ones containing the most important type-related
+//! information, such as `Ty`, `Predicate`, `Region`, and `Const`.
+//!
+//! There are three groups of traits involved in each traversal.
+//! - `TypeFoldable`. This is implemented once for many types, including:
+//! - Types of interest, for which the methods delegate to the folder.
+//! - All other types, including generic containers like `Vec` and `Option`.
+//! It defines a "skeleton" of how they should be folded.
+//! - `TypeSuperFoldable`. This is implemented only for each type of interest,
+//! and defines the folding "skeleton" for these types.
+//! - `TypeFolder`/`FallibleTypeFolder. One of these is implemented for each
+//! folder. This defines how types of interest are folded.
+//!
+//! This means each fold is a mixture of (a) generic folding operations, and (b)
+//! custom fold operations that are specific to the folder.
+//! - The `TypeFoldable` impls handle most of the traversal, and call into
+//! `TypeFolder`/`FallibleTypeFolder` when they encounter a type of interest.
+//! - A `TypeFolder`/`FallibleTypeFolder` may call into another `TypeFoldable`
+//! impl, because some of the types of interest are recursive and can contain
+//! other types of interest.
+//! - A `TypeFolder`/`FallibleTypeFolder` may also call into a `TypeSuperFoldable`
+//! impl, because each folder might provide custom handling only for some types
+//! of interest, or only for some variants of each type of interest, and then
+//! use default traversal for the remaining cases.
+//!
+//! For example, if you have `struct S(Ty, U)` where `S: TypeFoldable` and `U:
+//! TypeFoldable`, and an instance `s = S(ty, u)`, it would be folded like so:
+//! ```text
+//! s.fold_with(folder) calls
+//! - ty.fold_with(folder) calls
+//! - folder.fold_ty(ty) may call
+//! - ty.super_fold_with(folder)
+//! - u.fold_with(folder)
+//! ```
+use crate::{visit::TypeVisitable, Interner};
+
+/// This trait is implemented for every type that can be folded,
+/// providing the skeleton of the traversal.
+///
+/// To implement this conveniently, use the derive macro located in
+/// `rustc_macros`.
+pub trait TypeFoldable<I: Interner>: TypeVisitable<I> {
+ /// The entry point for folding. To fold a value `t` with a folder `f`
+ /// call: `t.try_fold_with(f)`.
+ ///
+ /// For most types, this just traverses the value, calling `try_fold_with`
+ /// on each field/element.
+ ///
+ /// For types of interest (such as `Ty`), the implementation of method
+ /// calls a folder method specifically for that type (such as
+ /// `F::try_fold_ty`). This is where control transfers from `TypeFoldable`
+ /// to `TypeFolder`.
+ fn try_fold_with<F: FallibleTypeFolder<I>>(self, folder: &mut F) -> Result<Self, F::Error>;
+
+ /// A convenient alternative to `try_fold_with` for use with infallible
+ /// folders. Do not override this method, to ensure coherence with
+ /// `try_fold_with`.
+ fn fold_with<F: TypeFolder<I>>(self, folder: &mut F) -> Self {
+ self.try_fold_with(folder).into_ok()
+ }
+}
+
+// This trait is implemented for types of interest.
+pub trait TypeSuperFoldable<I: Interner>: TypeFoldable<I> {
+ /// Provides a default fold for a type of interest. This should only be
+ /// called within `TypeFolder` methods, when a non-custom traversal is
+ /// desired for the value of the type of interest passed to that method.
+ /// For example, in `MyFolder::try_fold_ty(ty)`, it is valid to call
+ /// `ty.try_super_fold_with(self)`, but any other folding should be done
+ /// with `xyz.try_fold_with(self)`.
+ fn try_super_fold_with<F: FallibleTypeFolder<I>>(
+ self,
+ folder: &mut F,
+ ) -> Result<Self, F::Error>;
+
+ /// A convenient alternative to `try_super_fold_with` for use with
+ /// infallible folders. Do not override this method, to ensure coherence
+ /// with `try_super_fold_with`.
+ fn super_fold_with<F: TypeFolder<I>>(self, folder: &mut F) -> Self {
+ self.try_super_fold_with(folder).into_ok()
+ }
+}
+
+/// This trait is implemented for every infallible folding traversal. There is
+/// a fold method defined for every type of interest. Each such method has a
+/// default that does an "identity" fold. Implementations of these methods
+/// often fall back to a `super_fold_with` method if the primary argument
+/// doesn't satisfy a particular condition.
+///
+/// A blanket implementation of [`FallibleTypeFolder`] will defer to
+/// the infallible methods of this trait to ensure that the two APIs
+/// are coherent.
+pub trait TypeFolder<I: Interner>: FallibleTypeFolder<I, Error = !> {
+ fn interner(&self) -> I;
+
+ fn fold_binder<T>(&mut self, t: I::Binder<T>) -> I::Binder<T>
+ where
+ T: TypeFoldable<I>,
+ I::Binder<T>: TypeSuperFoldable<I>,
+ {
+ t.super_fold_with(self)
+ }
+
+ fn fold_ty(&mut self, t: I::Ty) -> I::Ty
+ where
+ I::Ty: TypeSuperFoldable<I>,
+ {
+ t.super_fold_with(self)
+ }
+
+ fn fold_region(&mut self, r: I::Region) -> I::Region
+ where
+ I::Region: TypeSuperFoldable<I>,
+ {
+ r.super_fold_with(self)
+ }
+
+ fn fold_const(&mut self, c: I::Const) -> I::Const
+ where
+ I::Const: TypeSuperFoldable<I>,
+ {
+ c.super_fold_with(self)
+ }
+
+ fn fold_predicate(&mut self, p: I::Predicate) -> I::Predicate
+ where
+ I::Predicate: TypeSuperFoldable<I>,
+ {
+ p.super_fold_with(self)
+ }
+}
+
+/// This trait is implemented for every folding traversal. There is a fold
+/// method defined for every type of interest. Each such method has a default
+/// that does an "identity" fold.
+///
+/// A blanket implementation of this trait (that defers to the relevant
+/// method of [`TypeFolder`]) is provided for all infallible folders in
+/// order to ensure the two APIs are coherent.
+pub trait FallibleTypeFolder<I: Interner>: Sized {
+ type Error;
+
+ fn interner(&self) -> I;
+
+ fn try_fold_binder<T>(&mut self, t: I::Binder<T>) -> Result<I::Binder<T>, Self::Error>
+ where
+ T: TypeFoldable<I>,
+ I::Binder<T>: TypeSuperFoldable<I>,
+ {
+ t.try_super_fold_with(self)
+ }
+
+ fn try_fold_ty(&mut self, t: I::Ty) -> Result<I::Ty, Self::Error>
+ where
+ I::Ty: TypeSuperFoldable<I>,
+ {
+ t.try_super_fold_with(self)
+ }
+
+ fn try_fold_region(&mut self, r: I::Region) -> Result<I::Region, Self::Error>
+ where
+ I::Region: TypeSuperFoldable<I>,
+ {
+ r.try_super_fold_with(self)
+ }
+
+ fn try_fold_const(&mut self, c: I::Const) -> Result<I::Const, Self::Error>
+ where
+ I::Const: TypeSuperFoldable<I>,
+ {
+ c.try_super_fold_with(self)
+ }
+
+ fn try_fold_predicate(&mut self, p: I::Predicate) -> Result<I::Predicate, Self::Error>
+ where
+ I::Predicate: TypeSuperFoldable<I>,
+ {
+ p.try_super_fold_with(self)
+ }
+}
+
+// This blanket implementation of the fallible trait for infallible folders
+// delegates to infallible methods to ensure coherence.
+impl<I: Interner, F> FallibleTypeFolder<I> for F
+where
+ F: TypeFolder<I>,
+{
+ type Error = !;
+
+ fn interner(&self) -> I {
+ TypeFolder::interner(self)
+ }
+
+ fn try_fold_binder<T>(&mut self, t: I::Binder<T>) -> Result<I::Binder<T>, !>
+ where
+ T: TypeFoldable<I>,
+ I::Binder<T>: TypeSuperFoldable<I>,
+ {
+ Ok(self.fold_binder(t))
+ }
+
+ fn try_fold_ty(&mut self, t: I::Ty) -> Result<I::Ty, !>
+ where
+ I::Ty: TypeSuperFoldable<I>,
+ {
+ Ok(self.fold_ty(t))
+ }
+
+ fn try_fold_region(&mut self, r: I::Region) -> Result<I::Region, !>
+ where
+ I::Region: TypeSuperFoldable<I>,
+ {
+ Ok(self.fold_region(r))
+ }
+
+ fn try_fold_const(&mut self, c: I::Const) -> Result<I::Const, !>
+ where
+ I::Const: TypeSuperFoldable<I>,
+ {
+ Ok(self.fold_const(c))
+ }
+
+ fn try_fold_predicate(&mut self, p: I::Predicate) -> Result<I::Predicate, !>
+ where
+ I::Predicate: TypeSuperFoldable<I>,
+ {
+ Ok(self.fold_predicate(p))
+ }
+}
diff --git a/compiler/rustc_type_ir/src/lib.rs b/compiler/rustc_type_ir/src/lib.rs
index 44004cb0b..5a991e03d 100644
--- a/compiler/rustc_type_ir/src/lib.rs
+++ b/compiler/rustc_type_ir/src/lib.rs
@@ -1,6 +1,9 @@
+#![feature(associated_type_defaults)]
#![feature(fmt_helpers_for_derive)]
#![feature(min_specialization)]
+#![feature(never_type)]
#![feature(rustc_attrs)]
+#![feature(unwrap_infallible)]
#![deny(rustc::untranslatable_diagnostic)]
#![deny(rustc::diagnostic_outside_of_impl)]
@@ -18,8 +21,14 @@ use std::hash::Hash;
use std::mem::discriminant;
pub mod codec;
+pub mod fold;
pub mod sty;
pub mod ty_info;
+pub mod visit;
+
+#[macro_use]
+mod macros;
+mod structural_impls;
pub use codec::*;
pub use sty::*;
@@ -28,68 +37,69 @@ pub use ty_info::*;
/// Needed so we can use #[derive(HashStable_Generic)]
pub trait HashStableContext {}
-pub trait Interner {
- type AdtDef: Clone + Debug + Hash + PartialEq + Eq + PartialOrd + Ord;
- type SubstsRef: Clone + Debug + Hash + PartialEq + Eq + PartialOrd + Ord;
- type DefId: Clone + Debug + Hash + PartialEq + Eq + PartialOrd + Ord;
- type Ty: Clone + Debug + Hash + PartialEq + Eq + PartialOrd + Ord;
- type Const: Clone + Debug + Hash + PartialEq + Eq + PartialOrd + Ord;
- type Region: Clone + Debug + Hash + PartialEq + Eq + PartialOrd + Ord;
- type TypeAndMut: Clone + Debug + Hash + PartialEq + Eq + PartialOrd + Ord;
- type Mutability: Clone + Debug + Hash + PartialEq + Eq + PartialOrd + Ord;
- type Movability: Clone + Debug + Hash + PartialEq + Eq + PartialOrd + Ord;
- type PolyFnSig: Clone + Debug + Hash + PartialEq + Eq + PartialOrd + Ord;
- type ListBinderExistentialPredicate: Clone + Debug + Hash + PartialEq + Eq + PartialOrd + Ord;
- type BinderListTy: Clone + Debug + Hash + PartialEq + Eq + PartialOrd + Ord;
- type ListTy: Clone + Debug + Hash + PartialEq + Eq + PartialOrd + Ord;
- type AliasTy: Clone + Debug + Hash + PartialEq + Eq + PartialOrd + Ord;
- type ParamTy: Clone + Debug + Hash + PartialEq + Eq + PartialOrd + Ord;
- type BoundTy: Clone + Debug + Hash + PartialEq + Eq + PartialOrd + Ord;
- type PlaceholderType: Clone + Debug + Hash + PartialEq + Eq + PartialOrd + Ord;
- type InferTy: Clone + Debug + Hash + PartialEq + Eq + PartialOrd + Ord;
- type ErrorGuaranteed: Clone + Debug + Hash + PartialEq + Eq + PartialOrd + Ord;
+pub trait Interner: Sized {
+ type AdtDef: Clone + Debug + Hash + Ord;
+ type SubstsRef: Clone + Debug + Hash + Ord;
+ type DefId: Clone + Debug + Hash + Ord;
+ type Binder<T>;
+ type Ty: Clone + Debug + Hash + Ord;
+ type Const: Clone + Debug + Hash + Ord;
+ type Region: Clone + Debug + Hash + Ord;
+ type Predicate;
+ type TypeAndMut: Clone + Debug + Hash + Ord;
+ type Mutability: Clone + Debug + Hash + Ord;
+ type Movability: Clone + Debug + Hash + Ord;
+ type PolyFnSig: Clone + Debug + Hash + Ord;
+ type ListBinderExistentialPredicate: Clone + Debug + Hash + Ord;
+ type BinderListTy: Clone + Debug + Hash + Ord;
+ type ListTy: Clone + Debug + Hash + Ord;
+ type AliasTy: Clone + Debug + Hash + Ord;
+ type ParamTy: Clone + Debug + Hash + Ord;
+ type BoundTy: Clone + Debug + Hash + Ord;
+ type PlaceholderType: Clone + Debug + Hash + Ord;
+ type InferTy: Clone + Debug + Hash + Ord;
+ type ErrorGuaranteed: Clone + Debug + Hash + Ord;
type PredicateKind: Clone + Debug + Hash + PartialEq + Eq;
- type AllocId: Clone + Debug + Hash + PartialEq + Eq + PartialOrd + Ord;
+ type AllocId: Clone + Debug + Hash + Ord;
- type EarlyBoundRegion: Clone + Debug + Hash + PartialEq + Eq + PartialOrd + Ord;
- type BoundRegion: Clone + Debug + Hash + PartialEq + Eq + PartialOrd + Ord;
- type FreeRegion: Clone + Debug + Hash + PartialEq + Eq + PartialOrd + Ord;
- type RegionVid: Clone + Debug + Hash + PartialEq + Eq + PartialOrd + Ord;
- type PlaceholderRegion: Clone + Debug + Hash + PartialEq + Eq + PartialOrd + Ord;
+ type EarlyBoundRegion: Clone + Debug + Hash + Ord;
+ type BoundRegion: Clone + Debug + Hash + Ord;
+ type FreeRegion: Clone + Debug + Hash + Ord;
+ type RegionVid: Clone + Debug + Hash + Ord;
+ type PlaceholderRegion: Clone + Debug + Hash + Ord;
}
-pub trait InternAs<T: ?Sized, R> {
+/// Imagine you have a function `F: FnOnce(&[T]) -> R`, plus an iterator `iter`
+/// that produces `T` items. You could combine them with
+/// `f(&iter.collect::<Vec<_>>())`, but this requires allocating memory for the
+/// `Vec`.
+///
+/// This trait allows for faster implementations, intended for cases where the
+/// number of items produced by the iterator is small. There is a blanket impl
+/// for `T` items, but there is also a fallible impl for `Result<T, E>` items.
+pub trait CollectAndApply<T, R>: Sized {
type Output;
- fn intern_with<F>(self, f: F) -> Self::Output
+
+ /// Produce a result of type `Self::Output` from `iter`. The result will
+ /// typically be produced by applying `f` on the elements produced by
+ /// `iter`, though this may not happen in some impls, e.g. if an error
+ /// occured during iteration.
+ fn collect_and_apply<I, F>(iter: I, f: F) -> Self::Output
where
+ I: Iterator<Item = Self>,
F: FnOnce(&[T]) -> R;
}
-impl<I, T, R, E> InternAs<T, R> for I
-where
- E: InternIteratorElement<T, R>,
- I: Iterator<Item = E>,
-{
- type Output = E::Output;
- fn intern_with<F>(self, f: F) -> Self::Output
+/// The blanket impl that always collects all elements and applies `f`.
+impl<T, R> CollectAndApply<T, R> for T {
+ type Output = R;
+
+ /// Equivalent to `f(&iter.collect::<Vec<_>>())`.
+ fn collect_and_apply<I, F>(mut iter: I, f: F) -> R
where
+ I: Iterator<Item = T>,
F: FnOnce(&[T]) -> R,
{
- E::intern_with(self, f)
- }
-}
-
-pub trait InternIteratorElement<T, R>: Sized {
- type Output;
- fn intern_with<I: Iterator<Item = Self>, F: FnOnce(&[T]) -> R>(iter: I, f: F) -> Self::Output;
-}
-
-impl<T, R> InternIteratorElement<T, R> for T {
- type Output = R;
- fn intern_with<I: Iterator<Item = Self>, F: FnOnce(&[T]) -> R>(
- mut iter: I,
- f: F,
- ) -> Self::Output {
// This code is hot enough that it's worth specializing for the most
// common length lists, to avoid the overhead of `SmallVec` creation.
// Lengths 0, 1, and 2 typically account for ~95% of cases. If
@@ -116,23 +126,17 @@ impl<T, R> InternIteratorElement<T, R> for T {
}
}
-impl<'a, T, R> InternIteratorElement<T, R> for &'a T
-where
- T: Clone + 'a,
-{
- type Output = R;
- fn intern_with<I: Iterator<Item = Self>, F: FnOnce(&[T]) -> R>(iter: I, f: F) -> Self::Output {
- // This code isn't hot.
- f(&iter.cloned().collect::<SmallVec<[_; 8]>>())
- }
-}
-
-impl<T, R, E> InternIteratorElement<T, R> for Result<T, E> {
+/// A fallible impl that will fail, without calling `f`, if there are any
+/// errors during collection.
+impl<T, R, E> CollectAndApply<T, R> for Result<T, E> {
type Output = Result<R, E>;
- fn intern_with<I: Iterator<Item = Self>, F: FnOnce(&[T]) -> R>(
- mut iter: I,
- f: F,
- ) -> Self::Output {
+
+ /// Equivalent to `Ok(f(&iter.collect::<Result<Vec<_>>>()?))`.
+ fn collect_and_apply<I, F>(mut iter: I, f: F) -> Result<R, E>
+ where
+ I: Iterator<Item = Result<T, E>>,
+ F: FnOnce(&[T]) -> R,
+ {
// This code is hot enough that it's worth specializing for the most
// common length lists, to avoid the overhead of `SmallVec` creation.
// Lengths 0, 1, and 2 typically account for ~95% of cases. If
@@ -220,7 +224,8 @@ bitflags! {
// which is different from how types/const are freshened.
| TypeFlags::HAS_TY_FRESH.bits
| TypeFlags::HAS_CT_FRESH.bits
- | TypeFlags::HAS_FREE_LOCAL_REGIONS.bits;
+ | TypeFlags::HAS_FREE_LOCAL_REGIONS.bits
+ | TypeFlags::HAS_RE_ERASED.bits;
/// Does this have `Projection`?
const HAS_TY_PROJECTION = 1 << 10;
@@ -265,6 +270,9 @@ bitflags! {
/// Does this value have `InferConst::Fresh`?
const HAS_CT_FRESH = 1 << 21;
+
+ /// Does this have `Generator` or `GeneratorWitness`?
+ const HAS_TY_GENERATOR = 1 << 22;
}
}
diff --git a/compiler/rustc_type_ir/src/macros.rs b/compiler/rustc_type_ir/src/macros.rs
new file mode 100644
index 000000000..6c1810397
--- /dev/null
+++ b/compiler/rustc_type_ir/src/macros.rs
@@ -0,0 +1,176 @@
+/// Used for types that are `Copy` and which **do not care arena
+/// allocated data** (i.e., don't need to be folded).
+macro_rules! TrivialTypeTraversalImpls {
+ ($($ty:ty,)+) => {
+ $(
+ impl<I: $crate::Interner> $crate::fold::TypeFoldable<I> for $ty {
+ fn try_fold_with<F: $crate::fold::FallibleTypeFolder<I>>(
+ self,
+ _: &mut F,
+ ) -> ::std::result::Result<Self, F::Error> {
+ Ok(self)
+ }
+
+ #[inline]
+ fn fold_with<F: $crate::fold::TypeFolder<I>>(
+ self,
+ _: &mut F,
+ ) -> Self {
+ self
+ }
+ }
+
+ impl<I: $crate::Interner> $crate::visit::TypeVisitable<I> for $ty {
+ #[inline]
+ fn visit_with<F: $crate::visit::TypeVisitor<I>>(
+ &self,
+ _: &mut F)
+ -> ::std::ops::ControlFlow<F::BreakTy>
+ {
+ ::std::ops::ControlFlow::Continue(())
+ }
+ }
+ )+
+ };
+}
+
+macro_rules! EnumTypeTraversalImpl {
+ (impl<$($p:tt),*> TypeFoldable<$tcx:tt> for $s:path {
+ $($variants:tt)*
+ } $(where $($wc:tt)*)*) => {
+ impl<$($p),*> $crate::fold::TypeFoldable<$tcx> for $s
+ $(where $($wc)*)*
+ {
+ fn try_fold_with<V: $crate::fold::FallibleTypeFolder<$tcx>>(
+ self,
+ folder: &mut V,
+ ) -> ::std::result::Result<Self, V::Error> {
+ EnumTypeTraversalImpl!(@FoldVariants(self, folder) input($($variants)*) output())
+ }
+ }
+ };
+
+ (impl<$($p:tt),*> TypeVisitable<$tcx:tt> for $s:path {
+ $($variants:tt)*
+ } $(where $($wc:tt)*)*) => {
+ impl<$($p),*> $crate::visit::TypeVisitable<$tcx> for $s
+ $(where $($wc)*)*
+ {
+ fn visit_with<V: $crate::visit::TypeVisitor<$tcx>>(
+ &self,
+ visitor: &mut V,
+ ) -> ::std::ops::ControlFlow<V::BreakTy> {
+ EnumTypeTraversalImpl!(@VisitVariants(self, visitor) input($($variants)*) output())
+ }
+ }
+ };
+
+ (@FoldVariants($this:expr, $folder:expr) input() output($($output:tt)*)) => {
+ Ok(match $this {
+ $($output)*
+ })
+ };
+
+ (@FoldVariants($this:expr, $folder:expr)
+ input( ($variant:path) ( $($variant_arg:ident),* ) , $($input:tt)*)
+ output( $($output:tt)*) ) => {
+ EnumTypeTraversalImpl!(
+ @FoldVariants($this, $folder)
+ input($($input)*)
+ output(
+ $variant ( $($variant_arg),* ) => {
+ $variant (
+ $($crate::fold::TypeFoldable::try_fold_with($variant_arg, $folder)?),*
+ )
+ }
+ $($output)*
+ )
+ )
+ };
+
+ (@FoldVariants($this:expr, $folder:expr)
+ input( ($variant:path) { $($variant_arg:ident),* $(,)? } , $($input:tt)*)
+ output( $($output:tt)*) ) => {
+ EnumTypeTraversalImpl!(
+ @FoldVariants($this, $folder)
+ input($($input)*)
+ output(
+ $variant { $($variant_arg),* } => {
+ $variant {
+ $($variant_arg: $crate::fold::TypeFoldable::fold_with(
+ $variant_arg, $folder
+ )?),* }
+ }
+ $($output)*
+ )
+ )
+ };
+
+ (@FoldVariants($this:expr, $folder:expr)
+ input( ($variant:path), $($input:tt)*)
+ output( $($output:tt)*) ) => {
+ EnumTypeTraversalImpl!(
+ @FoldVariants($this, $folder)
+ input($($input)*)
+ output(
+ $variant => { $variant }
+ $($output)*
+ )
+ )
+ };
+
+ (@VisitVariants($this:expr, $visitor:expr) input() output($($output:tt)*)) => {
+ match $this {
+ $($output)*
+ }
+ };
+
+ (@VisitVariants($this:expr, $visitor:expr)
+ input( ($variant:path) ( $($variant_arg:ident),* ) , $($input:tt)*)
+ output( $($output:tt)*) ) => {
+ EnumTypeTraversalImpl!(
+ @VisitVariants($this, $visitor)
+ input($($input)*)
+ output(
+ $variant ( $($variant_arg),* ) => {
+ $($crate::visit::TypeVisitable::visit_with(
+ $variant_arg, $visitor
+ )?;)*
+ ::std::ops::ControlFlow::Continue(())
+ }
+ $($output)*
+ )
+ )
+ };
+
+ (@VisitVariants($this:expr, $visitor:expr)
+ input( ($variant:path) { $($variant_arg:ident),* $(,)? } , $($input:tt)*)
+ output( $($output:tt)*) ) => {
+ EnumTypeTraversalImpl!(
+ @VisitVariants($this, $visitor)
+ input($($input)*)
+ output(
+ $variant { $($variant_arg),* } => {
+ $($crate::visit::TypeVisitable::visit_with(
+ $variant_arg, $visitor
+ )?;)*
+ ::std::ops::ControlFlow::Continue(())
+ }
+ $($output)*
+ )
+ )
+ };
+
+ (@VisitVariants($this:expr, $visitor:expr)
+ input( ($variant:path), $($input:tt)*)
+ output( $($output:tt)*) ) => {
+ EnumTypeTraversalImpl!(
+ @VisitVariants($this, $visitor)
+ input($($input)*)
+ output(
+ $variant => { ::std::ops::ControlFlow::Continue(()) }
+ $($output)*
+ )
+ )
+ };
+}
diff --git a/compiler/rustc_type_ir/src/structural_impls.rs b/compiler/rustc_type_ir/src/structural_impls.rs
new file mode 100644
index 000000000..3ebe24104
--- /dev/null
+++ b/compiler/rustc_type_ir/src/structural_impls.rs
@@ -0,0 +1,175 @@
+//! This module contains implementations of the `TypeFoldable` and `TypeVisitable`
+//! traits for various types in the Rust compiler. Most are written by hand, though
+//! we've recently added some macros and proc-macros to help with the tedium.
+
+use crate::fold::{FallibleTypeFolder, TypeFoldable};
+use crate::visit::{TypeVisitable, TypeVisitor};
+use crate::Interner;
+use rustc_data_structures::functor::IdFunctor;
+use rustc_index::vec::{Idx, IndexVec};
+
+use std::ops::ControlFlow;
+use std::rc::Rc;
+use std::sync::Arc;
+
+///////////////////////////////////////////////////////////////////////////
+// Atomic structs
+//
+// For things that don't carry any arena-allocated data (and are
+// copy...), just add them to this list.
+
+TrivialTypeTraversalImpls! {
+ (),
+ bool,
+ usize,
+ u16,
+ u32,
+ u64,
+ String,
+ crate::DebruijnIndex,
+}
+
+///////////////////////////////////////////////////////////////////////////
+// Traversal implementations.
+
+impl<I: Interner, T: TypeFoldable<I>, U: TypeFoldable<I>> TypeFoldable<I> for (T, U) {
+ fn try_fold_with<F: FallibleTypeFolder<I>>(self, folder: &mut F) -> Result<(T, U), F::Error> {
+ Ok((self.0.try_fold_with(folder)?, self.1.try_fold_with(folder)?))
+ }
+}
+
+impl<I: Interner, T: TypeVisitable<I>, U: TypeVisitable<I>> TypeVisitable<I> for (T, U) {
+ fn visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
+ self.0.visit_with(visitor)?;
+ self.1.visit_with(visitor)
+ }
+}
+
+impl<I: Interner, A: TypeFoldable<I>, B: TypeFoldable<I>, C: TypeFoldable<I>> TypeFoldable<I>
+ for (A, B, C)
+{
+ fn try_fold_with<F: FallibleTypeFolder<I>>(
+ self,
+ folder: &mut F,
+ ) -> Result<(A, B, C), F::Error> {
+ Ok((
+ self.0.try_fold_with(folder)?,
+ self.1.try_fold_with(folder)?,
+ self.2.try_fold_with(folder)?,
+ ))
+ }
+}
+
+impl<I: Interner, A: TypeVisitable<I>, B: TypeVisitable<I>, C: TypeVisitable<I>> TypeVisitable<I>
+ for (A, B, C)
+{
+ fn visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
+ self.0.visit_with(visitor)?;
+ self.1.visit_with(visitor)?;
+ self.2.visit_with(visitor)
+ }
+}
+
+EnumTypeTraversalImpl! {
+ impl<I, T> TypeFoldable<I> for Option<T> {
+ (Some)(a),
+ (None),
+ } where I: Interner, T: TypeFoldable<I>
+}
+EnumTypeTraversalImpl! {
+ impl<I, T> TypeVisitable<I> for Option<T> {
+ (Some)(a),
+ (None),
+ } where I: Interner, T: TypeVisitable<I>
+}
+
+EnumTypeTraversalImpl! {
+ impl<I, T, E> TypeFoldable<I> for Result<T, E> {
+ (Ok)(a),
+ (Err)(a),
+ } where I: Interner, T: TypeFoldable<I>, E: TypeFoldable<I>,
+}
+EnumTypeTraversalImpl! {
+ impl<I, T, E> TypeVisitable<I> for Result<T, E> {
+ (Ok)(a),
+ (Err)(a),
+ } where I: Interner, T: TypeVisitable<I>, E: TypeVisitable<I>,
+}
+
+impl<I: Interner, T: TypeFoldable<I>> TypeFoldable<I> for Rc<T> {
+ fn try_fold_with<F: FallibleTypeFolder<I>>(self, folder: &mut F) -> Result<Self, F::Error> {
+ self.try_map_id(|value| value.try_fold_with(folder))
+ }
+}
+
+impl<I: Interner, T: TypeVisitable<I>> TypeVisitable<I> for Rc<T> {
+ fn visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
+ (**self).visit_with(visitor)
+ }
+}
+
+impl<I: Interner, T: TypeFoldable<I>> TypeFoldable<I> for Arc<T> {
+ fn try_fold_with<F: FallibleTypeFolder<I>>(self, folder: &mut F) -> Result<Self, F::Error> {
+ self.try_map_id(|value| value.try_fold_with(folder))
+ }
+}
+
+impl<I: Interner, T: TypeVisitable<I>> TypeVisitable<I> for Arc<T> {
+ fn visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
+ (**self).visit_with(visitor)
+ }
+}
+
+impl<I: Interner, T: TypeFoldable<I>> TypeFoldable<I> for Box<T> {
+ fn try_fold_with<F: FallibleTypeFolder<I>>(self, folder: &mut F) -> Result<Self, F::Error> {
+ self.try_map_id(|value| value.try_fold_with(folder))
+ }
+}
+
+impl<I: Interner, T: TypeVisitable<I>> TypeVisitable<I> for Box<T> {
+ fn visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
+ (**self).visit_with(visitor)
+ }
+}
+
+impl<I: Interner, T: TypeFoldable<I>> TypeFoldable<I> for Vec<T> {
+ fn try_fold_with<F: FallibleTypeFolder<I>>(self, folder: &mut F) -> Result<Self, F::Error> {
+ self.try_map_id(|t| t.try_fold_with(folder))
+ }
+}
+
+impl<I: Interner, T: TypeVisitable<I>> TypeVisitable<I> for Vec<T> {
+ fn visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
+ self.iter().try_for_each(|t| t.visit_with(visitor))
+ }
+}
+
+impl<I: Interner, T: TypeVisitable<I>> TypeVisitable<I> for &[T] {
+ fn visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
+ self.iter().try_for_each(|t| t.visit_with(visitor))
+ }
+}
+
+impl<I: Interner, T: TypeFoldable<I>> TypeFoldable<I> for Box<[T]> {
+ fn try_fold_with<F: FallibleTypeFolder<I>>(self, folder: &mut F) -> Result<Self, F::Error> {
+ self.try_map_id(|t| t.try_fold_with(folder))
+ }
+}
+
+impl<I: Interner, T: TypeVisitable<I>> TypeVisitable<I> for Box<[T]> {
+ fn visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
+ self.iter().try_for_each(|t| t.visit_with(visitor))
+ }
+}
+
+impl<I: Interner, T: TypeFoldable<I>, Ix: Idx> TypeFoldable<I> for IndexVec<Ix, T> {
+ fn try_fold_with<F: FallibleTypeFolder<I>>(self, folder: &mut F) -> Result<Self, F::Error> {
+ self.try_map_id(|x| x.try_fold_with(folder))
+ }
+}
+
+impl<I: Interner, T: TypeVisitable<I>, Ix: Idx> TypeVisitable<I> for IndexVec<Ix, T> {
+ fn visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
+ self.iter().try_for_each(|t| t.visit_with(visitor))
+ }
+}
diff --git a/compiler/rustc_type_ir/src/sty.rs b/compiler/rustc_type_ir/src/sty.rs
index 5f29588ae..ebe2b76ae 100644
--- a/compiler/rustc_type_ir/src/sty.rs
+++ b/compiler/rustc_type_ir/src/sty.rs
@@ -26,11 +26,9 @@ pub enum DynKind {
Dyn,
/// A sized `dyn* Trait` object
///
- /// These objects are represented as a `(data, vtable)` pair where `data` is a ptr-sized value
- /// (often a pointer to the real object, but not necessarily) and `vtable` is a pointer to
- /// the vtable for `dyn* Trait`. The representation is essentially the same as `&dyn Trait`
- /// or similar, but the drop function included in the vtable is responsible for freeing the
- /// underlying storage if needed. This allows a `dyn*` object to be treated agnostically with
+ /// These objects are represented as a `(data, vtable)` pair where `data` is a value of some
+ /// ptr-sized and ptr-aligned dynamically determined type `T` and `vtable` is a pointer to the
+ /// vtable of `impl T for Trait`. This allows a `dyn*` object to be treated agnostically with
/// respect to whether it points to a `Box<T>`, `Rc<T>`, etc.
DynStar,
}
@@ -160,6 +158,32 @@ pub enum TyKind<I: Interner> {
/// ```
GeneratorWitness(I::BinderListTy),
+ /// A type representing the types stored inside a generator.
+ /// This should only appear as part of the `GeneratorSubsts`.
+ ///
+ /// Unlike upvars, the witness can reference lifetimes from
+ /// inside of the generator itself. To deal with them in
+ /// the type of the generator, we convert them to higher ranked
+ /// lifetimes bound by the witness itself.
+ ///
+ /// This variant is only using when `drop_tracking_mir` is set.
+ /// This contains the `DefId` and the `SubstRef` of the generator.
+ /// The actual witness types are computed on MIR by the `mir_generator_witnesses` query.
+ ///
+ /// Looking at the following example, the witness for this generator
+ /// may end up as something like `for<'a> [Vec<i32>, &'a Vec<i32>]`:
+ ///
+ /// ```ignore UNSOLVED (ask @compiler-errors, should this error? can we just swap the yields?)
+ /// #![feature(generators)]
+ /// |a| {
+ /// let x = &vec![3];
+ /// yield a;
+ /// yield x[0];
+ /// }
+ /// # ;
+ /// ```
+ GeneratorWitnessMIR(I::DefId, I::SubstsRef),
+
/// The never type `!`.
Never,
@@ -241,6 +265,7 @@ const fn tykind_discriminant<I: Interner>(value: &TyKind<I>) -> usize {
Placeholder(_) => 23,
Infer(_) => 24,
Error(_) => 25,
+ GeneratorWitnessMIR(_, _) => 26,
}
}
@@ -266,6 +291,7 @@ impl<I: Interner> Clone for TyKind<I> {
Closure(d, s) => Closure(d.clone(), s.clone()),
Generator(d, s, m) => Generator(d.clone(), s.clone(), m.clone()),
GeneratorWitness(g) => GeneratorWitness(g.clone()),
+ GeneratorWitnessMIR(d, s) => GeneratorWitnessMIR(d.clone(), s.clone()),
Never => Never,
Tuple(t) => Tuple(t.clone()),
Alias(k, p) => Alias(*k, p.clone()),
@@ -282,43 +308,51 @@ impl<I: Interner> Clone for TyKind<I> {
impl<I: Interner> PartialEq for TyKind<I> {
#[inline]
fn eq(&self, other: &TyKind<I>) -> bool {
- tykind_discriminant(self) == tykind_discriminant(other)
- && match (self, other) {
- (Int(a_i), Int(b_i)) => a_i == b_i,
- (Uint(a_u), Uint(b_u)) => a_u == b_u,
- (Float(a_f), Float(b_f)) => a_f == b_f,
- (Adt(a_d, a_s), Adt(b_d, b_s)) => a_d == b_d && a_s == b_s,
- (Foreign(a_d), Foreign(b_d)) => a_d == b_d,
- (Array(a_t, a_c), Array(b_t, b_c)) => a_t == b_t && a_c == b_c,
- (Slice(a_t), Slice(b_t)) => a_t == b_t,
- (RawPtr(a_t), RawPtr(b_t)) => a_t == b_t,
- (Ref(a_r, a_t, a_m), Ref(b_r, b_t, b_m)) => a_r == b_r && a_t == b_t && a_m == b_m,
- (FnDef(a_d, a_s), FnDef(b_d, b_s)) => a_d == b_d && a_s == b_s,
- (FnPtr(a_s), FnPtr(b_s)) => a_s == b_s,
- (Dynamic(a_p, a_r, a_repr), Dynamic(b_p, b_r, b_repr)) => {
- a_p == b_p && a_r == b_r && a_repr == b_repr
- }
- (Closure(a_d, a_s), Closure(b_d, b_s)) => a_d == b_d && a_s == b_s,
- (Generator(a_d, a_s, a_m), Generator(b_d, b_s, b_m)) => {
- a_d == b_d && a_s == b_s && a_m == b_m
- }
- (GeneratorWitness(a_g), GeneratorWitness(b_g)) => a_g == b_g,
- (Tuple(a_t), Tuple(b_t)) => a_t == b_t,
- (Alias(a_i, a_p), Alias(b_i, b_p)) => a_i == b_i && a_p == b_p,
- (Param(a_p), Param(b_p)) => a_p == b_p,
- (Bound(a_d, a_b), Bound(b_d, b_b)) => a_d == b_d && a_b == b_b,
- (Placeholder(a_p), Placeholder(b_p)) => a_p == b_p,
- (Infer(a_t), Infer(b_t)) => a_t == b_t,
- (Error(a_e), Error(b_e)) => a_e == b_e,
- (Bool, Bool) | (Char, Char) | (Str, Str) | (Never, Never) => true,
- _ => {
- debug_assert!(
- false,
- "This branch must be unreachable, maybe the match is missing an arm? self = self = {self:?}, other = {other:?}"
- );
- true
- }
+ // You might expect this `match` to be preceded with this:
+ //
+ // tykind_discriminant(self) == tykind_discriminant(other) &&
+ //
+ // but the data patterns in practice are such that a comparison
+ // succeeds 99%+ of the time, and it's faster to omit it.
+ match (self, other) {
+ (Int(a_i), Int(b_i)) => a_i == b_i,
+ (Uint(a_u), Uint(b_u)) => a_u == b_u,
+ (Float(a_f), Float(b_f)) => a_f == b_f,
+ (Adt(a_d, a_s), Adt(b_d, b_s)) => a_d == b_d && a_s == b_s,
+ (Foreign(a_d), Foreign(b_d)) => a_d == b_d,
+ (Array(a_t, a_c), Array(b_t, b_c)) => a_t == b_t && a_c == b_c,
+ (Slice(a_t), Slice(b_t)) => a_t == b_t,
+ (RawPtr(a_t), RawPtr(b_t)) => a_t == b_t,
+ (Ref(a_r, a_t, a_m), Ref(b_r, b_t, b_m)) => a_r == b_r && a_t == b_t && a_m == b_m,
+ (FnDef(a_d, a_s), FnDef(b_d, b_s)) => a_d == b_d && a_s == b_s,
+ (FnPtr(a_s), FnPtr(b_s)) => a_s == b_s,
+ (Dynamic(a_p, a_r, a_repr), Dynamic(b_p, b_r, b_repr)) => {
+ a_p == b_p && a_r == b_r && a_repr == b_repr
+ }
+ (Closure(a_d, a_s), Closure(b_d, b_s)) => a_d == b_d && a_s == b_s,
+ (Generator(a_d, a_s, a_m), Generator(b_d, b_s, b_m)) => {
+ a_d == b_d && a_s == b_s && a_m == b_m
+ }
+ (GeneratorWitness(a_g), GeneratorWitness(b_g)) => a_g == b_g,
+ (GeneratorWitnessMIR(a_d, a_s), GeneratorWitnessMIR(b_d, b_s)) => {
+ a_d == b_d && a_s == b_s
}
+ (Tuple(a_t), Tuple(b_t)) => a_t == b_t,
+ (Alias(a_i, a_p), Alias(b_i, b_p)) => a_i == b_i && a_p == b_p,
+ (Param(a_p), Param(b_p)) => a_p == b_p,
+ (Bound(a_d, a_b), Bound(b_d, b_b)) => a_d == b_d && a_b == b_b,
+ (Placeholder(a_p), Placeholder(b_p)) => a_p == b_p,
+ (Infer(a_t), Infer(b_t)) => a_t == b_t,
+ (Error(a_e), Error(b_e)) => a_e == b_e,
+ (Bool, Bool) | (Char, Char) | (Str, Str) | (Never, Never) => true,
+ _ => {
+ debug_assert!(
+ tykind_discriminant(self) != tykind_discriminant(other),
+ "This branch must be unreachable, maybe the match is missing an arm? self = self = {self:?}, other = {other:?}"
+ );
+ false
+ }
+ }
}
}
@@ -360,6 +394,13 @@ impl<I: Interner> Ord for TyKind<I> {
a_d.cmp(b_d).then_with(|| a_s.cmp(b_s).then_with(|| a_m.cmp(b_m)))
}
(GeneratorWitness(a_g), GeneratorWitness(b_g)) => a_g.cmp(b_g),
+ (
+ GeneratorWitnessMIR(a_d, a_s),
+ GeneratorWitnessMIR(b_d, b_s),
+ ) => match Ord::cmp(a_d, b_d) {
+ Ordering::Equal => Ord::cmp(a_s, b_s),
+ cmp => cmp,
+ },
(Tuple(a_t), Tuple(b_t)) => a_t.cmp(b_t),
(Alias(a_i, a_p), Alias(b_i, b_p)) => a_i.cmp(b_i).then_with(|| a_p.cmp(b_p)),
(Param(a_p), Param(b_p)) => a_p.cmp(b_p),
@@ -369,7 +410,7 @@ impl<I: Interner> Ord for TyKind<I> {
(Error(a_e), Error(b_e)) => a_e.cmp(b_e),
(Bool, Bool) | (Char, Char) | (Str, Str) | (Never, Never) => Ordering::Equal,
_ => {
- debug_assert!(false, "This branch must be unreachable, maybe the match is missing an arm? self = self = {self:?}, other = {other:?}");
+ debug_assert!(false, "This branch must be unreachable, maybe the match is missing an arm? self = {self:?}, other = {other:?}");
Ordering::Equal
}
}
@@ -421,6 +462,10 @@ impl<I: Interner> hash::Hash for TyKind<I> {
m.hash(state)
}
GeneratorWitness(g) => g.hash(state),
+ GeneratorWitnessMIR(d, s) => {
+ d.hash(state);
+ s.hash(state);
+ }
Tuple(t) => t.hash(state),
Alias(i, p) => {
i.hash(state);
@@ -461,6 +506,7 @@ impl<I: Interner> fmt::Debug for TyKind<I> {
Closure(d, s) => f.debug_tuple_field2_finish("Closure", d, s),
Generator(d, s, m) => f.debug_tuple_field3_finish("Generator", d, s, m),
GeneratorWitness(g) => f.debug_tuple_field1_finish("GeneratorWitness", g),
+ GeneratorWitnessMIR(d, s) => f.debug_tuple_field2_finish("GeneratorWitnessMIR", d, s),
Never => f.write_str("Never"),
Tuple(t) => f.debug_tuple_field1_finish("Tuple", t),
Alias(i, a) => f.debug_tuple_field2_finish("Alias", i, a),
@@ -559,6 +605,10 @@ where
GeneratorWitness(b) => e.emit_enum_variant(disc, |e| {
b.encode(e);
}),
+ GeneratorWitnessMIR(def_id, substs) => e.emit_enum_variant(disc, |e| {
+ def_id.encode(e);
+ substs.encode(e);
+ }),
Never => e.emit_enum_variant(disc, |_| {}),
Tuple(substs) => e.emit_enum_variant(disc, |e| {
substs.encode(e);
@@ -641,6 +691,7 @@ where
23 => Placeholder(Decodable::decode(d)),
24 => Infer(Decodable::decode(d)),
25 => Error(Decodable::decode(d)),
+ 26 => GeneratorWitnessMIR(Decodable::decode(d), Decodable::decode(d)),
_ => panic!(
"{}",
format!(
@@ -742,6 +793,10 @@ where
GeneratorWitness(b) => {
b.hash_stable(__hcx, __hasher);
}
+ GeneratorWitnessMIR(def_id, substs) => {
+ def_id.hash_stable(__hcx, __hasher);
+ substs.hash_stable(__hcx, __hasher);
+ }
Never => {}
Tuple(substs) => {
substs.hash_stable(__hcx, __hasher);
@@ -903,6 +958,9 @@ pub enum RegionKind<I: Interner> {
/// Erased region, used by trait selection, in MIR and during codegen.
ReErased,
+
+ /// A region that resulted from some other error. Used exclusively for diagnostics.
+ ReError(I::ErrorGuaranteed),
}
// This is manually implemented for `RegionKind` because `std::mem::discriminant`
@@ -917,6 +975,7 @@ const fn regionkind_discriminant<I: Interner>(value: &RegionKind<I>) -> usize {
ReVar(_) => 4,
RePlaceholder(_) => 5,
ReErased => 6,
+ ReError(_) => 7,
}
}
@@ -928,6 +987,7 @@ where
I::FreeRegion: Copy,
I::RegionVid: Copy,
I::PlaceholderRegion: Copy,
+ I::ErrorGuaranteed: Copy,
{
}
@@ -942,6 +1002,7 @@ impl<I: Interner> Clone for RegionKind<I> {
ReVar(r) => ReVar(r.clone()),
RePlaceholder(r) => RePlaceholder(r.clone()),
ReErased => ReErased,
+ ReError(r) => ReError(r.clone()),
}
}
}
@@ -959,10 +1020,11 @@ impl<I: Interner> PartialEq for RegionKind<I> {
(ReVar(a_r), ReVar(b_r)) => a_r == b_r,
(RePlaceholder(a_r), RePlaceholder(b_r)) => a_r == b_r,
(ReErased, ReErased) => true,
+ (ReError(_), ReError(_)) => true,
_ => {
debug_assert!(
false,
- "This branch must be unreachable, maybe the match is missing an arm? self = self = {self:?}, other = {other:?}"
+ "This branch must be unreachable, maybe the match is missing an arm? self = {self:?}, other = {other:?}"
);
true
}
@@ -1020,6 +1082,7 @@ impl<I: Interner> hash::Hash for RegionKind<I> {
ReVar(r) => r.hash(state),
RePlaceholder(r) => r.hash(state),
ReErased => (),
+ ReError(_) => (),
}
}
}
@@ -1043,6 +1106,8 @@ impl<I: Interner> fmt::Debug for RegionKind<I> {
RePlaceholder(placeholder) => write!(f, "RePlaceholder({placeholder:?})"),
ReErased => f.write_str("ReErased"),
+
+ ReError(_) => f.write_str("ReError"),
}
}
}
@@ -1077,6 +1142,7 @@ where
a.encode(e);
}),
ReErased => e.emit_enum_variant(disc, |_| {}),
+ ReError(_) => e.emit_enum_variant(disc, |_| {}),
}
}
}
@@ -1089,6 +1155,7 @@ where
I::FreeRegion: Decodable<D>,
I::RegionVid: Decodable<D>,
I::PlaceholderRegion: Decodable<D>,
+ I::ErrorGuaranteed: Decodable<D>,
{
fn decode(d: &mut D) -> Self {
match Decoder::read_usize(d) {
@@ -1099,6 +1166,7 @@ where
4 => ReVar(Decodable::decode(d)),
5 => RePlaceholder(Decodable::decode(d)),
6 => ReErased,
+ 7 => ReError(Decodable::decode(d)),
_ => panic!(
"{}",
format!(
@@ -1127,7 +1195,7 @@ where
) {
std::mem::discriminant(self).hash_stable(hcx, hasher);
match self {
- ReErased | ReStatic => {
+ ReErased | ReStatic | ReError(_) => {
// No variant fields to hash for these ...
}
ReLateBound(d, r) => {
diff --git a/compiler/rustc_type_ir/src/visit.rs b/compiler/rustc_type_ir/src/visit.rs
new file mode 100644
index 000000000..62239fd20
--- /dev/null
+++ b/compiler/rustc_type_ir/src/visit.rs
@@ -0,0 +1,115 @@
+//! A visiting traversal mechanism for complex data structures that contain type
+//! information.
+//!
+//! This is a read-only traversal of the data structure.
+//!
+//! This traversal has limited flexibility. Only a small number of "types of
+//! interest" within the complex data structures can receive custom
+//! visitation. These are the ones containing the most important type-related
+//! information, such as `Ty`, `Predicate`, `Region`, and `Const`.
+//!
+//! There are three groups of traits involved in each traversal.
+//! - `TypeVisitable`. This is implemented once for many types, including:
+//! - Types of interest, for which the methods delegate to the visitor.
+//! - All other types, including generic containers like `Vec` and `Option`.
+//! It defines a "skeleton" of how they should be visited.
+//! - `TypeSuperVisitable`. This is implemented only for each type of interest,
+//! and defines the visiting "skeleton" for these types.
+//! - `TypeVisitor`. This is implemented for each visitor. This defines how
+//! types of interest are visited.
+//!
+//! This means each visit is a mixture of (a) generic visiting operations, and (b)
+//! custom visit operations that are specific to the visitor.
+//! - The `TypeVisitable` impls handle most of the traversal, and call into
+//! `TypeVisitor` when they encounter a type of interest.
+//! - A `TypeVisitor` may call into another `TypeVisitable` impl, because some of
+//! the types of interest are recursive and can contain other types of interest.
+//! - A `TypeVisitor` may also call into a `TypeSuperVisitable` impl, because each
+//! visitor might provide custom handling only for some types of interest, or
+//! only for some variants of each type of interest, and then use default
+//! traversal for the remaining cases.
+//!
+//! For example, if you have `struct S(Ty, U)` where `S: TypeVisitable` and `U:
+//! TypeVisitable`, and an instance `s = S(ty, u)`, it would be visited like so:
+//! ```text
+//! s.visit_with(visitor) calls
+//! - ty.visit_with(visitor) calls
+//! - visitor.visit_ty(ty) may call
+//! - ty.super_visit_with(visitor)
+//! - u.visit_with(visitor)
+//! ```
+use crate::Interner;
+
+use std::fmt;
+use std::ops::ControlFlow;
+
+/// This trait is implemented for every type that can be visited,
+/// providing the skeleton of the traversal.
+///
+/// To implement this conveniently, use the derive macro located in
+/// `rustc_macros`.
+pub trait TypeVisitable<I: Interner>: fmt::Debug + Clone {
+ /// The entry point for visiting. To visit a value `t` with a visitor `v`
+ /// call: `t.visit_with(v)`.
+ ///
+ /// For most types, this just traverses the value, calling `visit_with` on
+ /// each field/element.
+ ///
+ /// For types of interest (such as `Ty`), the implementation of this method
+ /// that calls a visitor method specifically for that type (such as
+ /// `V::visit_ty`). This is where control transfers from `TypeFoldable` to
+ /// `TypeVisitor`.
+ fn visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy>;
+}
+
+pub trait TypeSuperVisitable<I: Interner>: TypeVisitable<I> {
+ /// Provides a default visit for a type of interest. This should only be
+ /// called within `TypeVisitor` methods, when a non-custom traversal is
+ /// desired for the value of the type of interest passed to that method.
+ /// For example, in `MyVisitor::visit_ty(ty)`, it is valid to call
+ /// `ty.super_visit_with(self)`, but any other visiting should be done
+ /// with `xyz.visit_with(self)`.
+ fn super_visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy>;
+}
+
+/// This trait is implemented for every visiting traversal. There is a visit
+/// method defined for every type of interest. Each such method has a default
+/// that recurses into the type's fields in a non-custom fashion.
+pub trait TypeVisitor<I: Interner>: Sized {
+ type BreakTy = !;
+
+ fn visit_binder<T: TypeVisitable<I>>(&mut self, t: &I::Binder<T>) -> ControlFlow<Self::BreakTy>
+ where
+ I::Binder<T>: TypeSuperVisitable<I>,
+ {
+ t.super_visit_with(self)
+ }
+
+ fn visit_ty(&mut self, t: I::Ty) -> ControlFlow<Self::BreakTy>
+ where
+ I::Ty: TypeSuperVisitable<I>,
+ {
+ t.super_visit_with(self)
+ }
+
+ fn visit_region(&mut self, r: I::Region) -> ControlFlow<Self::BreakTy>
+ where
+ I::Region: TypeSuperVisitable<I>,
+ {
+ r.super_visit_with(self)
+ }
+
+ fn visit_const(&mut self, c: I::Const) -> ControlFlow<Self::BreakTy>
+ where
+ I::Const: TypeSuperVisitable<I>,
+ {
+ c.super_visit_with(self)
+ }
+
+ fn visit_predicate(&mut self, p: I::Predicate) -> ControlFlow<Self::BreakTy>
+ where
+ I::Predicate: TypeSuperVisitable<I>,
+ {
+ p.super_visit_with(self)
+ }
+}
diff --git a/config.toml.example b/config.toml.example
index 5e1d2f2e3..69eb228a2 100644
--- a/config.toml.example
+++ b/config.toml.example
@@ -233,6 +233,9 @@ changelog-seen = 2
# and generated in already-minified form from the beginning.
#docs-minification = true
+# Flag to specify whether private items should be included in the library docs.
+#library-docs-private-items = false
+
# Indicate whether the compiler should be documented in addition to the standard
# library and facade crates.
#compiler-docs = false
@@ -285,11 +288,24 @@ changelog-seen = 2
# be built if `extended = true`.
#extended = false
-# Installs chosen set of extended tools if `extended = true`. By default builds
-# all extended tools except `rust-demangler`, unless the target is also being
-# built with `profiler = true`. If chosen tool failed to build the installation
-# fails. If `extended = false`, this option is ignored.
-#tools = ["cargo", "rls", "clippy", "rustfmt", "analysis", "src"] # + "rust-demangler" if `profiler`
+# Set of tools to be included in the installation.
+#
+# If `extended = false`, the only one of these built by default is rustdoc.
+#
+# If `extended = true`, they're all included, with the exception of
+# rust-demangler which additionally requires `profiler = true` to be set.
+#
+# If any enabled tool fails to build, the installation fails.
+#tools = [
+# "cargo",
+# "clippy",
+# "rustdoc",
+# "rustfmt",
+# "rust-analyzer",
+# "analysis",
+# "src",
+# "rust-demangler", # if profiler = true
+#]
# Verbosity level: 0 == not verbose, 1 == verbose, 2 == very verbose
#verbose = 0
@@ -646,9 +662,13 @@ changelog-seen = 2
# Select LTO mode that will be used for compiling rustc. By default, thin local LTO
# (LTO within a single crate) is used (like for any Rust crate). You can also select
-# "thin" or "fat" to apply Thin/Fat LTO to the `rustc_driver` dylib.
+# "thin" or "fat" to apply Thin/Fat LTO to the `rustc_driver` dylib, or "off" to disable
+# LTO entirely.
#lto = "thin-local"
+# Build compiler with the optimization enabled and -Zvalidate-mir, currently only for `std`
+#validate-mir-opts = 3
+
# =============================================================================
# Options for specific targets
#
diff --git a/git-commit-hash b/git-commit-hash
index e85873fe4..f0e235983 100644
--- a/git-commit-hash
+++ b/git-commit-hash
@@ -1 +1 @@
-9eb3afe9ebe9c7d2b84b71002d44f4a0edac95e0 \ No newline at end of file
+84c898d65adf2f39a5a98507f1fe0ce10a2b8dbc \ No newline at end of file
diff --git a/git-commit-info b/git-commit-info
index 9d8d5eadb..3bb794e51 100644
--- a/git-commit-info
+++ b/git-commit-info
@@ -1,3 +1,3 @@
-9eb3afe9ebe9c7d2b84b71002d44f4a0edac95e0
-9eb3afe9e
-2023-03-27
+84c898d65adf2f39a5a98507f1fe0ce10a2b8dbc
+84c898d65
+2023-04-16
diff --git a/library/alloc/benches/vec_deque.rs b/library/alloc/benches/vec_deque.rs
index 7c78561eb..313a97ed1 100644
--- a/library/alloc/benches/vec_deque.rs
+++ b/library/alloc/benches/vec_deque.rs
@@ -1,4 +1,8 @@
-use std::collections::VecDeque;
+use core::iter::Iterator;
+use std::{
+ collections::{vec_deque, VecDeque},
+ mem,
+};
use test::{black_box, Bencher};
#[bench]
@@ -53,6 +57,146 @@ fn bench_try_fold(b: &mut Bencher) {
b.iter(|| black_box(ring.iter().try_fold(0, |a, b| Some(a + b))))
}
+/// does the memory bookkeeping to reuse the buffer of the Vec between iterations.
+/// `setup` must not modify its argument's length or capacity. `g` must not move out of its argument.
+fn into_iter_helper<
+ T: Copy,
+ F: FnOnce(&mut VecDeque<T>),
+ G: FnOnce(&mut vec_deque::IntoIter<T>),
+>(
+ v: &mut Vec<T>,
+ setup: F,
+ g: G,
+) {
+ let ptr = v.as_mut_ptr();
+ let len = v.len();
+ // ensure that the vec is full, to make sure that any wrapping from the deque doesn't
+ // access uninitialized memory.
+ assert_eq!(v.len(), v.capacity());
+
+ let mut deque = VecDeque::from(mem::take(v));
+ setup(&mut deque);
+
+ let mut it = deque.into_iter();
+ g(&mut it);
+
+ mem::forget(it);
+
+ // SAFETY: the provided functions are not allowed to modify the allocation, so the buffer is still alive.
+ // len and capacity are accurate due to the above assertion.
+ // All the elements in the buffer are still valid, because of `T: Copy` which implies `T: !Drop`.
+ mem::forget(mem::replace(v, unsafe { Vec::from_raw_parts(ptr, len, len) }));
+}
+
+#[bench]
+fn bench_into_iter(b: &mut Bencher) {
+ let len = 1024;
+ // we reuse this allocation for every run
+ let mut vec: Vec<usize> = (0..len).collect();
+ vec.shrink_to_fit();
+
+ b.iter(|| {
+ let mut sum = 0;
+ into_iter_helper(
+ &mut vec,
+ |_| {},
+ |it| {
+ for i in it {
+ sum += i;
+ }
+ },
+ );
+ black_box(sum);
+
+ let mut sum = 0;
+ // rotating a full deque doesn't move any memory.
+ into_iter_helper(
+ &mut vec,
+ |d| d.rotate_left(len / 2),
+ |it| {
+ for i in it {
+ sum += i;
+ }
+ },
+ );
+ black_box(sum);
+ });
+}
+
+#[bench]
+fn bench_into_iter_fold(b: &mut Bencher) {
+ let len = 1024;
+
+ // because `fold` takes ownership of the iterator,
+ // we can't prevent it from dropping the memory,
+ // so we have to bite the bullet and reallocate
+ // for every iteration.
+ b.iter(|| {
+ let deque: VecDeque<usize> = (0..len).collect();
+ assert_eq!(deque.len(), deque.capacity());
+ let sum = deque.into_iter().fold(0, |a, b| a + b);
+ black_box(sum);
+
+ // rotating a full deque doesn't move any memory.
+ let mut deque: VecDeque<usize> = (0..len).collect();
+ assert_eq!(deque.len(), deque.capacity());
+ deque.rotate_left(len / 2);
+ let sum = deque.into_iter().fold(0, |a, b| a + b);
+ black_box(sum);
+ });
+}
+
+#[bench]
+fn bench_into_iter_try_fold(b: &mut Bencher) {
+ let len = 1024;
+ // we reuse this allocation for every run
+ let mut vec: Vec<usize> = (0..len).collect();
+ vec.shrink_to_fit();
+
+ // Iterator::any uses Iterator::try_fold under the hood
+ b.iter(|| {
+ let mut b = false;
+ into_iter_helper(&mut vec, |_| {}, |it| b = it.any(|i| i == len - 1));
+ black_box(b);
+
+ into_iter_helper(&mut vec, |d| d.rotate_left(len / 2), |it| b = it.any(|i| i == len - 1));
+ black_box(b);
+ });
+}
+
+#[bench]
+fn bench_into_iter_next_chunk(b: &mut Bencher) {
+ let len = 1024;
+ // we reuse this allocation for every run
+ let mut vec: Vec<usize> = (0..len).collect();
+ vec.shrink_to_fit();
+
+ b.iter(|| {
+ let mut buf = [0; 64];
+ into_iter_helper(
+ &mut vec,
+ |_| {},
+ |it| {
+ while let Ok(a) = it.next_chunk() {
+ buf = a;
+ }
+ },
+ );
+ black_box(buf);
+
+ into_iter_helper(
+ &mut vec,
+ |d| d.rotate_left(len / 2),
+ |it| {
+ while let Ok(a) = it.next_chunk() {
+ buf = a;
+ }
+ },
+ );
+ black_box(buf);
+ });
+}
+
#[bench]
fn bench_from_array_1000(b: &mut Bencher) {
const N: usize = 1000;
diff --git a/library/alloc/src/boxed.rs b/library/alloc/src/boxed.rs
index a563b2587..44a378990 100644
--- a/library/alloc/src/boxed.rs
+++ b/library/alloc/src/boxed.rs
@@ -283,9 +283,7 @@ impl<T> Box<T> {
#[must_use]
#[inline(always)]
pub fn pin(x: T) -> Pin<Box<T>> {
- (#[rustc_box]
- Box::new(x))
- .into()
+ Box::new(x).into()
}
/// Allocates memory on the heap then places `x` into it,
@@ -1242,8 +1240,8 @@ unsafe impl<#[may_dangle] T: ?Sized, A: Allocator> Drop for Box<T, A> {
#[stable(feature = "rust1", since = "1.0.0")]
impl<T: Default> Default for Box<T> {
/// Creates a `Box<T>`, with the `Default` value for T.
+ #[inline]
fn default() -> Self {
- #[rustc_box]
Box::new(T::default())
}
}
@@ -1252,6 +1250,7 @@ impl<T: Default> Default for Box<T> {
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_const_unstable(feature = "const_default_impls", issue = "87864")]
impl<T> const Default for Box<[T]> {
+ #[inline]
fn default() -> Self {
let ptr: Unique<[T]> = Unique::<[T; 0]>::dangling();
Box(ptr, Global)
@@ -1262,6 +1261,7 @@ impl<T> const Default for Box<[T]> {
#[stable(feature = "default_box_extra", since = "1.17.0")]
#[rustc_const_unstable(feature = "const_default_impls", issue = "87864")]
impl const Default for Box<str> {
+ #[inline]
fn default() -> Self {
// SAFETY: This is the same as `Unique::cast<U>` but with an unsized `U = str`.
let ptr: Unique<str> = unsafe {
@@ -1616,7 +1616,6 @@ impl<T, const N: usize> From<[T; N]> for Box<[T]> {
/// println!("{boxed:?}");
/// ```
fn from(array: [T; N]) -> Box<[T]> {
- #[rustc_box]
Box::new(array)
}
}
diff --git a/library/alloc/src/boxed/thin.rs b/library/alloc/src/boxed/thin.rs
index c1a82e452..ad48315fd 100644
--- a/library/alloc/src/boxed/thin.rs
+++ b/library/alloc/src/boxed/thin.rs
@@ -48,7 +48,7 @@ unsafe impl<T: ?Sized + Sync> Sync for ThinBox<T> {}
#[unstable(feature = "thin_box", issue = "92791")]
impl<T> ThinBox<T> {
- /// Moves a type to the heap with its `Metadata` stored in the heap allocation instead of on
+ /// Moves a type to the heap with its [`Metadata`] stored in the heap allocation instead of on
/// the stack.
///
/// # Examples
@@ -59,6 +59,8 @@ impl<T> ThinBox<T> {
///
/// let five = ThinBox::new(5);
/// ```
+ ///
+ /// [`Metadata`]: core::ptr::Pointee::Metadata
#[cfg(not(no_global_oom_handling))]
pub fn new(value: T) -> Self {
let meta = ptr::metadata(&value);
@@ -69,7 +71,7 @@ impl<T> ThinBox<T> {
#[unstable(feature = "thin_box", issue = "92791")]
impl<Dyn: ?Sized> ThinBox<Dyn> {
- /// Moves a type to the heap with its `Metadata` stored in the heap allocation instead of on
+ /// Moves a type to the heap with its [`Metadata`] stored in the heap allocation instead of on
/// the stack.
///
/// # Examples
@@ -80,6 +82,8 @@ impl<Dyn: ?Sized> ThinBox<Dyn> {
///
/// let thin_slice = ThinBox::<[i32]>::new_unsize([1, 2, 3, 4]);
/// ```
+ ///
+ /// [`Metadata`]: core::ptr::Pointee::Metadata
#[cfg(not(no_global_oom_handling))]
pub fn new_unsize<T>(value: T) -> Self
where
diff --git a/library/alloc/src/collections/binary_heap/mod.rs b/library/alloc/src/collections/binary_heap/mod.rs
index 0b73b1af4..f1d0a305d 100644
--- a/library/alloc/src/collections/binary_heap/mod.rs
+++ b/library/alloc/src/collections/binary_heap/mod.rs
@@ -851,18 +851,30 @@ impl<T: Ord> BinaryHeap<T> {
where
F: FnMut(&T) -> bool,
{
- let mut first_removed = self.len();
+ struct RebuildOnDrop<'a, T: Ord> {
+ heap: &'a mut BinaryHeap<T>,
+ first_removed: usize,
+ }
+
+ let mut guard = RebuildOnDrop { first_removed: self.len(), heap: self };
+
let mut i = 0;
- self.data.retain(|e| {
+ guard.heap.data.retain(|e| {
let keep = f(e);
- if !keep && i < first_removed {
- first_removed = i;
+ if !keep && i < guard.first_removed {
+ guard.first_removed = i;
}
i += 1;
keep
});
- // data[0..first_removed] is untouched, so we only need to rebuild the tail:
- self.rebuild_tail(first_removed);
+
+ impl<'a, T: Ord> Drop for RebuildOnDrop<'a, T> {
+ fn drop(&mut self) {
+ // data[..first_removed] is untouched, so we only need to
+ // rebuild the tail:
+ self.heap.rebuild_tail(self.first_removed);
+ }
+ }
}
}
diff --git a/library/alloc/src/collections/binary_heap/tests.rs b/library/alloc/src/collections/binary_heap/tests.rs
index ffbb6c80a..500caa356 100644
--- a/library/alloc/src/collections/binary_heap/tests.rs
+++ b/library/alloc/src/collections/binary_heap/tests.rs
@@ -474,6 +474,25 @@ fn test_retain() {
assert!(a.is_empty());
}
+#[test]
+fn test_retain_catch_unwind() {
+ let mut heap = BinaryHeap::from(vec![3, 1, 2]);
+
+ // Removes the 3, then unwinds out of retain.
+ let _ = catch_unwind(AssertUnwindSafe(|| {
+ heap.retain(|e| {
+ if *e == 1 {
+ panic!();
+ }
+ false
+ });
+ }));
+
+ // Naively this would be [1, 2] (an invalid heap) if BinaryHeap delegates to
+ // Vec's retain impl and then does not rebuild the heap after that unwinds.
+ assert_eq!(heap.into_vec(), [2, 1]);
+}
+
// old binaryheap failed this test
//
// Integrity means that all elements are present after a comparison panics,
diff --git a/library/alloc/src/collections/btree/borrow.rs b/library/alloc/src/collections/btree/borrow.rs
index 016f139a5..000b9bd0f 100644
--- a/library/alloc/src/collections/btree/borrow.rs
+++ b/library/alloc/src/collections/btree/borrow.rs
@@ -41,6 +41,28 @@ impl<'a, T> DormantMutRef<'a, T> {
// SAFETY: our own safety conditions imply this reference is again unique.
unsafe { &mut *self.ptr.as_ptr() }
}
+
+ /// Borrows a new mutable reference from the unique borrow initially captured.
+ ///
+ /// # Safety
+ ///
+ /// The reborrow must have ended, i.e., the reference returned by `new` and
+ /// all pointers and references derived from it, must not be used anymore.
+ pub unsafe fn reborrow(&mut self) -> &'a mut T {
+ // SAFETY: our own safety conditions imply this reference is again unique.
+ unsafe { &mut *self.ptr.as_ptr() }
+ }
+
+ /// Borrows a new shared reference from the unique borrow initially captured.
+ ///
+ /// # Safety
+ ///
+ /// The reborrow must have ended, i.e., the reference returned by `new` and
+ /// all pointers and references derived from it, must not be used anymore.
+ pub unsafe fn reborrow_shared(&self) -> &'a T {
+ // SAFETY: our own safety conditions imply this reference is again unique.
+ unsafe { &*self.ptr.as_ptr() }
+ }
}
#[cfg(test)]
diff --git a/library/alloc/src/collections/btree/map.rs b/library/alloc/src/collections/btree/map.rs
index 1d9c4460e..386cd1a16 100644
--- a/library/alloc/src/collections/btree/map.rs
+++ b/library/alloc/src/collections/btree/map.rs
@@ -6,7 +6,7 @@ use core::hash::{Hash, Hasher};
use core::iter::{FromIterator, FusedIterator};
use core::marker::PhantomData;
use core::mem::{self, ManuallyDrop};
-use core::ops::{Index, RangeBounds};
+use core::ops::{Bound, Index, RangeBounds};
use core::ptr;
use crate::alloc::{Allocator, Global};
@@ -15,7 +15,7 @@ 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::*;
+use super::search::{SearchBound, SearchResult::*};
use super::set_val::SetValZST;
mod entry;
@@ -2422,6 +2422,732 @@ impl<K, V, A: Allocator + Clone> BTreeMap<K, V, A> {
pub const fn is_empty(&self) -> bool {
self.len() == 0
}
+
+ /// Returns a [`Cursor`] pointing at the first element that is above the
+ /// given bound.
+ ///
+ /// If no such element exists then a cursor pointing at the "ghost"
+ /// non-element is returned.
+ ///
+ /// Passing [`Bound::Unbounded`] will return a cursor pointing at the first
+ /// element of the map.
+ ///
+ /// # Examples
+ ///
+ /// Basic usage:
+ ///
+ /// ```
+ /// #![feature(btree_cursors)]
+ ///
+ /// use std::collections::BTreeMap;
+ /// use std::ops::Bound;
+ ///
+ /// let mut a = BTreeMap::new();
+ /// a.insert(1, "a");
+ /// a.insert(2, "b");
+ /// a.insert(3, "c");
+ /// a.insert(4, "c");
+ /// let cursor = a.lower_bound(Bound::Excluded(&2));
+ /// assert_eq!(cursor.key(), Some(&3));
+ /// ```
+ #[unstable(feature = "btree_cursors", issue = "107540")]
+ pub fn lower_bound<Q>(&self, bound: Bound<&Q>) -> Cursor<'_, K, V>
+ where
+ K: Borrow<Q> + Ord,
+ Q: Ord,
+ {
+ let root_node = match self.root.as_ref() {
+ None => return Cursor { current: None, root: None },
+ Some(root) => root.reborrow(),
+ };
+ let edge = root_node.lower_bound(SearchBound::from_range(bound));
+ Cursor { current: edge.next_kv().ok(), root: self.root.as_ref() }
+ }
+
+ /// Returns a [`CursorMut`] pointing at the first element that is above the
+ /// given bound.
+ ///
+ /// If no such element exists then a cursor pointing at the "ghost"
+ /// non-element is returned.
+ ///
+ /// Passing [`Bound::Unbounded`] will return a cursor pointing at the first
+ /// element of the map.
+ ///
+ /// # Examples
+ ///
+ /// Basic usage:
+ ///
+ /// ```
+ /// #![feature(btree_cursors)]
+ ///
+ /// use std::collections::BTreeMap;
+ /// use std::ops::Bound;
+ ///
+ /// let mut a = BTreeMap::new();
+ /// a.insert(1, "a");
+ /// a.insert(2, "b");
+ /// a.insert(3, "c");
+ /// a.insert(4, "c");
+ /// let cursor = a.lower_bound_mut(Bound::Excluded(&2));
+ /// assert_eq!(cursor.key(), Some(&3));
+ /// ```
+ #[unstable(feature = "btree_cursors", issue = "107540")]
+ pub fn lower_bound_mut<Q>(&mut self, bound: Bound<&Q>) -> CursorMut<'_, K, V, A>
+ where
+ K: Borrow<Q> + Ord,
+ Q: Ord,
+ {
+ let (root, dormant_root) = DormantMutRef::new(&mut self.root);
+ let root_node = match root.as_mut() {
+ None => {
+ return CursorMut {
+ current: None,
+ root: dormant_root,
+ length: &mut self.length,
+ alloc: &mut *self.alloc,
+ };
+ }
+ Some(root) => root.borrow_mut(),
+ };
+ let edge = root_node.lower_bound(SearchBound::from_range(bound));
+ CursorMut {
+ current: edge.next_kv().ok(),
+ root: dormant_root,
+ length: &mut self.length,
+ alloc: &mut *self.alloc,
+ }
+ }
+
+ /// Returns a [`Cursor`] pointing at the last element that is below the
+ /// given bound.
+ ///
+ /// If no such element exists then a cursor pointing at the "ghost"
+ /// non-element is returned.
+ ///
+ /// Passing [`Bound::Unbounded`] will return a cursor pointing at the last
+ /// element of the map.
+ ///
+ /// # Examples
+ ///
+ /// Basic usage:
+ ///
+ /// ```
+ /// #![feature(btree_cursors)]
+ ///
+ /// use std::collections::BTreeMap;
+ /// use std::ops::Bound;
+ ///
+ /// let mut a = BTreeMap::new();
+ /// a.insert(1, "a");
+ /// a.insert(2, "b");
+ /// a.insert(3, "c");
+ /// a.insert(4, "c");
+ /// let cursor = a.upper_bound(Bound::Excluded(&3));
+ /// assert_eq!(cursor.key(), Some(&2));
+ /// ```
+ #[unstable(feature = "btree_cursors", issue = "107540")]
+ pub fn upper_bound<Q>(&self, bound: Bound<&Q>) -> Cursor<'_, K, V>
+ where
+ K: Borrow<Q> + Ord,
+ Q: Ord,
+ {
+ let root_node = match self.root.as_ref() {
+ None => return Cursor { current: None, root: None },
+ Some(root) => root.reborrow(),
+ };
+ let edge = root_node.upper_bound(SearchBound::from_range(bound));
+ Cursor { current: edge.next_back_kv().ok(), root: self.root.as_ref() }
+ }
+
+ /// Returns a [`CursorMut`] pointing at the last element that is below the
+ /// given bound.
+ ///
+ /// If no such element exists then a cursor pointing at the "ghost"
+ /// non-element is returned.
+ ///
+ /// Passing [`Bound::Unbounded`] will return a cursor pointing at the last
+ /// element of the map.
+ ///
+ /// # Examples
+ ///
+ /// Basic usage:
+ ///
+ /// ```
+ /// #![feature(btree_cursors)]
+ ///
+ /// use std::collections::BTreeMap;
+ /// use std::ops::Bound;
+ ///
+ /// let mut a = BTreeMap::new();
+ /// a.insert(1, "a");
+ /// a.insert(2, "b");
+ /// a.insert(3, "c");
+ /// a.insert(4, "c");
+ /// let cursor = a.upper_bound_mut(Bound::Excluded(&3));
+ /// assert_eq!(cursor.key(), Some(&2));
+ /// ```
+ #[unstable(feature = "btree_cursors", issue = "107540")]
+ pub fn upper_bound_mut<Q>(&mut self, bound: Bound<&Q>) -> CursorMut<'_, K, V, A>
+ where
+ K: Borrow<Q> + Ord,
+ Q: Ord,
+ {
+ let (root, dormant_root) = DormantMutRef::new(&mut self.root);
+ let root_node = match root.as_mut() {
+ None => {
+ return CursorMut {
+ current: None,
+ root: dormant_root,
+ length: &mut self.length,
+ alloc: &mut *self.alloc,
+ };
+ }
+ Some(root) => root.borrow_mut(),
+ };
+ let edge = root_node.upper_bound(SearchBound::from_range(bound));
+ CursorMut {
+ current: edge.next_back_kv().ok(),
+ root: dormant_root,
+ length: &mut self.length,
+ alloc: &mut *self.alloc,
+ }
+ }
+}
+
+/// A cursor over a `BTreeMap`.
+///
+/// A `Cursor` is like an iterator, except that it can freely seek back-and-forth.
+///
+/// Cursors always point to an element in the tree, and index in a logically circular way.
+/// To accommodate this, there is a "ghost" non-element that yields `None` between the last and
+/// first elements of the tree.
+///
+/// A `Cursor` is created with the [`BTreeMap::lower_bound`] and [`BTreeMap::upper_bound`] methods.
+#[unstable(feature = "btree_cursors", issue = "107540")]
+pub struct Cursor<'a, K: 'a, V: 'a> {
+ current: Option<Handle<NodeRef<marker::Immut<'a>, K, V, marker::LeafOrInternal>, marker::KV>>,
+ root: Option<&'a node::Root<K, V>>,
+}
+
+#[unstable(feature = "btree_cursors", issue = "107540")]
+impl<K, V> Clone for Cursor<'_, K, V> {
+ fn clone(&self) -> Self {
+ let Cursor { current, root } = *self;
+ Cursor { current, root }
+ }
+}
+
+#[unstable(feature = "btree_cursors", issue = "107540")]
+impl<K: Debug, V: Debug> Debug for Cursor<'_, K, V> {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ f.debug_tuple("Cursor").field(&self.key_value()).finish()
+ }
+}
+
+/// A cursor over a `BTreeMap` with editing operations.
+///
+/// A `Cursor` is like an iterator, except that it can freely seek back-and-forth, and can
+/// safely mutate the tree during iteration. This is because the lifetime of its yielded
+/// references is tied to its own lifetime, instead of just the underlying tree. This means
+/// cursors cannot yield multiple elements at once.
+///
+/// Cursors always point to an element in the tree, and index in a logically circular way.
+/// To accommodate this, there is a "ghost" non-element that yields `None` between the last and
+/// first elements of the tree.
+///
+/// A `Cursor` is created with the [`BTreeMap::lower_bound_mut`] and [`BTreeMap::upper_bound_mut`]
+/// methods.
+#[unstable(feature = "btree_cursors", issue = "107540")]
+pub struct CursorMut<
+ 'a,
+ K: 'a,
+ V: 'a,
+ #[unstable(feature = "allocator_api", issue = "32838")] A = Global,
+> {
+ current: Option<Handle<NodeRef<marker::Mut<'a>, K, V, marker::LeafOrInternal>, marker::KV>>,
+ root: DormantMutRef<'a, Option<node::Root<K, V>>>,
+ length: &'a mut usize,
+ alloc: &'a mut A,
+}
+
+#[unstable(feature = "btree_cursors", issue = "107540")]
+impl<K: Debug, V: Debug, A> Debug for CursorMut<'_, K, V, A> {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ f.debug_tuple("CursorMut").field(&self.key_value()).finish()
+ }
+}
+
+impl<'a, K, V> Cursor<'a, K, V> {
+ /// Moves the cursor to the next element of the `BTreeMap`.
+ ///
+ /// If the cursor is pointing to the "ghost" non-element then this will move it to
+ /// the first element of the `BTreeMap`. If it is pointing to the last
+ /// element of the `BTreeMap` then this will move it to the "ghost" non-element.
+ #[unstable(feature = "btree_cursors", issue = "107540")]
+ pub fn move_next(&mut self) {
+ match self.current.take() {
+ None => {
+ self.current = self.root.and_then(|root| {
+ root.reborrow().first_leaf_edge().forget_node_type().right_kv().ok()
+ });
+ }
+ Some(current) => {
+ self.current = current.next_leaf_edge().next_kv().ok();
+ }
+ }
+ }
+
+ /// Moves the cursor to the previous element of the `BTreeMap`.
+ ///
+ /// If the cursor is pointing to the "ghost" non-element then this will move it to
+ /// the last element of the `BTreeMap`. If it is pointing to the first
+ /// element of the `BTreeMap` then this will move it to the "ghost" non-element.
+ #[unstable(feature = "btree_cursors", issue = "107540")]
+ pub fn move_prev(&mut self) {
+ match self.current.take() {
+ None => {
+ self.current = self.root.and_then(|root| {
+ root.reborrow().last_leaf_edge().forget_node_type().left_kv().ok()
+ });
+ }
+ Some(current) => {
+ self.current = current.next_back_leaf_edge().next_back_kv().ok();
+ }
+ }
+ }
+
+ /// Returns a reference to the key of the element that the cursor is
+ /// currently pointing to.
+ ///
+ /// This returns `None` if the cursor is currently pointing to the
+ /// "ghost" non-element.
+ #[unstable(feature = "btree_cursors", issue = "107540")]
+ pub fn key(&self) -> Option<&'a K> {
+ self.current.as_ref().map(|current| current.into_kv().0)
+ }
+
+ /// Returns a reference to the value of the element that the cursor is
+ /// currently pointing to.
+ ///
+ /// This returns `None` if the cursor is currently pointing to the
+ /// "ghost" non-element.
+ #[unstable(feature = "btree_cursors", issue = "107540")]
+ pub fn value(&self) -> Option<&'a V> {
+ self.current.as_ref().map(|current| current.into_kv().1)
+ }
+
+ /// Returns a reference to the key and value of the element that the cursor
+ /// is currently pointing to.
+ ///
+ /// This returns `None` if the cursor is currently pointing to the
+ /// "ghost" non-element.
+ #[unstable(feature = "btree_cursors", issue = "107540")]
+ pub fn key_value(&self) -> Option<(&'a K, &'a V)> {
+ self.current.as_ref().map(|current| current.into_kv())
+ }
+
+ /// Returns a reference to the next element.
+ ///
+ /// If the cursor is pointing to the "ghost" non-element then this returns
+ /// the first element of the `BTreeMap`. If it is pointing to the last
+ /// element of the `BTreeMap` then this returns `None`.
+ #[unstable(feature = "btree_cursors", issue = "107540")]
+ pub fn peek_next(&self) -> Option<(&'a K, &'a V)> {
+ let mut next = self.clone();
+ next.move_next();
+ next.current.as_ref().map(|current| current.into_kv())
+ }
+
+ /// Returns a reference to the previous element.
+ ///
+ /// If the cursor is pointing to the "ghost" non-element then this returns
+ /// the last element of the `BTreeMap`. If it is pointing to the first
+ /// element of the `BTreeMap` then this returns `None`.
+ #[unstable(feature = "btree_cursors", issue = "107540")]
+ pub fn peek_prev(&self) -> Option<(&'a K, &'a V)> {
+ let mut prev = self.clone();
+ prev.move_prev();
+ prev.current.as_ref().map(|current| current.into_kv())
+ }
+}
+
+impl<'a, K, V, A> CursorMut<'a, K, V, A> {
+ /// Moves the cursor to the next element of the `BTreeMap`.
+ ///
+ /// If the cursor is pointing to the "ghost" non-element then this will move it to
+ /// the first element of the `BTreeMap`. If it is pointing to the last
+ /// element of the `BTreeMap` then this will move it to the "ghost" non-element.
+ #[unstable(feature = "btree_cursors", issue = "107540")]
+ pub fn move_next(&mut self) {
+ match self.current.take() {
+ None => {
+ // SAFETY: The previous borrow of root has ended.
+ self.current = unsafe { self.root.reborrow() }.as_mut().and_then(|root| {
+ root.borrow_mut().first_leaf_edge().forget_node_type().right_kv().ok()
+ });
+ }
+ Some(current) => {
+ self.current = current.next_leaf_edge().next_kv().ok();
+ }
+ }
+ }
+
+ /// Moves the cursor to the previous element of the `BTreeMap`.
+ ///
+ /// If the cursor is pointing to the "ghost" non-element then this will move it to
+ /// the last element of the `BTreeMap`. If it is pointing to the first
+ /// element of the `BTreeMap` then this will move it to the "ghost" non-element.
+ #[unstable(feature = "btree_cursors", issue = "107540")]
+ pub fn move_prev(&mut self) {
+ match self.current.take() {
+ None => {
+ // SAFETY: The previous borrow of root has ended.
+ self.current = unsafe { self.root.reborrow() }.as_mut().and_then(|root| {
+ root.borrow_mut().last_leaf_edge().forget_node_type().left_kv().ok()
+ });
+ }
+ Some(current) => {
+ self.current = current.next_back_leaf_edge().next_back_kv().ok();
+ }
+ }
+ }
+
+ /// Returns a reference to the key of the element that the cursor is
+ /// currently pointing to.
+ ///
+ /// This returns `None` if the cursor is currently pointing to the
+ /// "ghost" non-element.
+ #[unstable(feature = "btree_cursors", issue = "107540")]
+ pub fn key(&self) -> Option<&K> {
+ self.current.as_ref().map(|current| current.reborrow().into_kv().0)
+ }
+
+ /// Returns a reference to the value of the element that the cursor is
+ /// currently pointing to.
+ ///
+ /// This returns `None` if the cursor is currently pointing to the
+ /// "ghost" non-element.
+ #[unstable(feature = "btree_cursors", issue = "107540")]
+ pub fn value(&self) -> Option<&V> {
+ self.current.as_ref().map(|current| current.reborrow().into_kv().1)
+ }
+
+ /// Returns a reference to the key and value of the element that the cursor
+ /// is currently pointing to.
+ ///
+ /// This returns `None` if the cursor is currently pointing to the
+ /// "ghost" non-element.
+ #[unstable(feature = "btree_cursors", issue = "107540")]
+ pub fn key_value(&self) -> Option<(&K, &V)> {
+ self.current.as_ref().map(|current| current.reborrow().into_kv())
+ }
+
+ /// Returns a mutable reference to the value of the element that the cursor
+ /// is currently pointing to.
+ ///
+ /// This returns `None` if the cursor is currently pointing to the
+ /// "ghost" non-element.
+ #[unstable(feature = "btree_cursors", issue = "107540")]
+ pub fn value_mut(&mut self) -> Option<&mut V> {
+ self.current.as_mut().map(|current| current.kv_mut().1)
+ }
+
+ /// Returns a reference to the key and mutable reference to the value of the
+ /// element that the cursor is currently pointing to.
+ ///
+ /// This returns `None` if the cursor is currently pointing to the
+ /// "ghost" non-element.
+ #[unstable(feature = "btree_cursors", issue = "107540")]
+ pub fn key_value_mut(&mut self) -> Option<(&K, &mut V)> {
+ self.current.as_mut().map(|current| {
+ let (k, v) = current.kv_mut();
+ (&*k, v)
+ })
+ }
+
+ /// Returns a mutable reference to the of the element that the cursor is
+ /// currently pointing to.
+ ///
+ /// This returns `None` if the cursor is currently pointing to the
+ /// "ghost" non-element.
+ ///
+ /// # Safety
+ ///
+ /// This can be used to modify the key, but you must ensure that the
+ /// `BTreeMap` invariants are maintained. Specifically:
+ ///
+ /// * The key must remain unique within the tree.
+ /// * The key must remain in sorted order with regards to other elements in
+ /// the tree.
+ #[unstable(feature = "btree_cursors", issue = "107540")]
+ pub unsafe fn key_mut_unchecked(&mut self) -> Option<&mut K> {
+ self.current.as_mut().map(|current| current.kv_mut().0)
+ }
+
+ /// Returns a reference to the key and value of the next element.
+ ///
+ /// If the cursor is pointing to the "ghost" non-element then this returns
+ /// the first element of the `BTreeMap`. If it is pointing to the last
+ /// element of the `BTreeMap` then this returns `None`.
+ #[unstable(feature = "btree_cursors", issue = "107540")]
+ pub fn peek_next(&mut self) -> Option<(&K, &mut V)> {
+ let (k, v) = match self.current {
+ None => {
+ // SAFETY: The previous borrow of root has ended.
+ unsafe { self.root.reborrow() }
+ .as_mut()?
+ .borrow_mut()
+ .first_leaf_edge()
+ .next_kv()
+ .ok()?
+ .into_kv_valmut()
+ }
+ // SAFETY: We're not using this to mutate the tree.
+ Some(ref mut current) => {
+ unsafe { current.reborrow_mut() }.next_leaf_edge().next_kv().ok()?.into_kv_valmut()
+ }
+ };
+ Some((k, v))
+ }
+
+ /// Returns a reference to the key and value of the previous element.
+ ///
+ /// If the cursor is pointing to the "ghost" non-element then this returns
+ /// the last element of the `BTreeMap`. If it is pointing to the first
+ /// element of the `BTreeMap` then this returns `None`.
+ #[unstable(feature = "btree_cursors", issue = "107540")]
+ pub fn peek_prev(&mut self) -> Option<(&K, &mut V)> {
+ let (k, v) = match self.current.as_mut() {
+ None => {
+ // SAFETY: The previous borrow of root has ended.
+ unsafe { self.root.reborrow() }
+ .as_mut()?
+ .borrow_mut()
+ .first_leaf_edge()
+ .next_kv()
+ .ok()?
+ .into_kv_valmut()
+ }
+ Some(current) => {
+ // SAFETY: We're not using this to mutate the tree.
+ unsafe { current.reborrow_mut() }
+ .next_back_leaf_edge()
+ .next_back_kv()
+ .ok()?
+ .into_kv_valmut()
+ }
+ };
+ Some((k, v))
+ }
+
+ /// Returns a read-only cursor pointing to the current element.
+ ///
+ /// 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`.
+ #[unstable(feature = "btree_cursors", issue = "107540")]
+ pub fn as_cursor(&self) -> Cursor<'_, K, V> {
+ Cursor {
+ // SAFETY: The tree is immutable while the cursor exists.
+ root: unsafe { self.root.reborrow_shared().as_ref() },
+ current: self.current.as_ref().map(|current| current.reborrow()),
+ }
+ }
+}
+
+// Now the tree editing operations
+impl<'a, K: Ord, V, A: Allocator + Clone> CursorMut<'a, K, V, A> {
+ /// Inserts a new element into the `BTreeMap` after the current one.
+ ///
+ /// If the cursor is pointing at the "ghost" non-element then the new element is
+ /// inserted at the front of the `BTreeMap`.
+ ///
+ /// # Safety
+ ///
+ /// You must ensure that the `BTreeMap` invariants are maintained.
+ /// Specifically:
+ ///
+ /// * The key of the newly inserted element must be unique in the tree.
+ /// * All keys in the tree must remain in sorted order.
+ #[unstable(feature = "btree_cursors", issue = "107540")]
+ pub unsafe fn insert_after_unchecked(&mut self, key: K, value: V) {
+ let edge = match self.current.take() {
+ None => {
+ // SAFETY: We have no other reference to the tree.
+ match unsafe { self.root.reborrow() } {
+ root @ None => {
+ // Tree is empty, allocate a new root.
+ let mut node = NodeRef::new_leaf(self.alloc.clone());
+ node.borrow_mut().push(key, value);
+ *root = Some(node.forget_type());
+ *self.length += 1;
+ return;
+ }
+ Some(root) => root.borrow_mut().first_leaf_edge(),
+ }
+ }
+ Some(current) => current.next_leaf_edge(),
+ };
+
+ let handle = edge.insert_recursing(key, value, self.alloc.clone(), |ins| {
+ drop(ins.left);
+ // SAFETY: The handle to the newly inserted value is always on a
+ // leaf node, so adding a new root node doesn't invalidate it.
+ let root = unsafe { self.root.reborrow().as_mut().unwrap() };
+ root.push_internal_level(self.alloc.clone()).push(ins.kv.0, ins.kv.1, ins.right)
+ });
+ self.current = handle.left_edge().next_back_kv().ok();
+ *self.length += 1;
+ }
+
+ /// Inserts a new element into the `BTreeMap` before the current one.
+ ///
+ /// If the cursor is pointing at the "ghost" non-element then the new element is
+ /// inserted at the end of the `BTreeMap`.
+ ///
+ /// # Safety
+ ///
+ /// You must ensure that the `BTreeMap` invariants are maintained.
+ /// Specifically:
+ ///
+ /// * The key of the newly inserted element must be unique in the tree.
+ /// * All keys in the tree must remain in sorted order.
+ #[unstable(feature = "btree_cursors", issue = "107540")]
+ pub unsafe fn insert_before_unchecked(&mut self, key: K, value: V) {
+ let edge = match self.current.take() {
+ None => {
+ // SAFETY: We have no other reference to the tree.
+ match unsafe { self.root.reborrow() } {
+ root @ None => {
+ // Tree is empty, allocate a new root.
+ let mut node = NodeRef::new_leaf(self.alloc.clone());
+ node.borrow_mut().push(key, value);
+ *root = Some(node.forget_type());
+ *self.length += 1;
+ return;
+ }
+ Some(root) => root.borrow_mut().last_leaf_edge(),
+ }
+ }
+ Some(current) => current.next_back_leaf_edge(),
+ };
+
+ let handle = edge.insert_recursing(key, value, self.alloc.clone(), |ins| {
+ drop(ins.left);
+ // SAFETY: The handle to the newly inserted value is always on a
+ // leaf node, so adding a new root node doesn't invalidate it.
+ let root = unsafe { self.root.reborrow().as_mut().unwrap() };
+ root.push_internal_level(self.alloc.clone()).push(ins.kv.0, ins.kv.1, ins.right)
+ });
+ self.current = handle.right_edge().next_kv().ok();
+ *self.length += 1;
+ }
+
+ /// Inserts a new element into the `BTreeMap` after the current one.
+ ///
+ /// If the cursor is pointing at the "ghost" non-element then the new element is
+ /// inserted at the front of the `BTreeMap`.
+ ///
+ /// # Panics
+ ///
+ /// This function panics if:
+ /// - the given key compares less than or equal to the current element (if
+ /// any).
+ /// - the given key compares greater than or equal to the next element (if
+ /// any).
+ #[unstable(feature = "btree_cursors", issue = "107540")]
+ pub fn insert_after(&mut self, key: K, value: V) {
+ if let Some(current) = self.key() {
+ if &key <= current {
+ panic!("key must be ordered above the current element");
+ }
+ }
+ if let Some((next, _)) = self.peek_prev() {
+ if &key >= next {
+ panic!("key must be ordered below the next element");
+ }
+ }
+ unsafe {
+ self.insert_after_unchecked(key, value);
+ }
+ }
+
+ /// Inserts a new element into the `BTreeMap` before the current one.
+ ///
+ /// If the cursor is pointing at the "ghost" non-element then the new element is
+ /// inserted at the end of the `BTreeMap`.
+ ///
+ /// # Panics
+ ///
+ /// This function panics if:
+ /// - the given key compares greater than or equal to the current element
+ /// (if any).
+ /// - the given key compares less than or equal to the previous element (if
+ /// any).
+ #[unstable(feature = "btree_cursors", issue = "107540")]
+ pub fn insert_before(&mut self, key: K, value: V) {
+ if let Some(current) = self.key() {
+ if &key >= current {
+ panic!("key must be ordered below the current element");
+ }
+ }
+ if let Some((prev, _)) = self.peek_prev() {
+ if &key <= prev {
+ panic!("key must be ordered above the previous element");
+ }
+ }
+ unsafe {
+ self.insert_before_unchecked(key, value);
+ }
+ }
+
+ /// Removes the current element from the `BTreeMap`.
+ ///
+ /// The element that was removed is returned, and the cursor is
+ /// moved to point to the next element in the `BTreeMap`.
+ ///
+ /// If the cursor is currently pointing to the "ghost" non-element then no element
+ /// is removed and `None` is returned. The cursor is not moved in this case.
+ #[unstable(feature = "btree_cursors", issue = "107540")]
+ pub fn remove_current(&mut self) -> Option<(K, V)> {
+ let current = self.current.take()?;
+ let mut emptied_internal_root = false;
+ let (kv, pos) =
+ current.remove_kv_tracking(|| emptied_internal_root = true, self.alloc.clone());
+ self.current = pos.next_kv().ok();
+ *self.length -= 1;
+ if emptied_internal_root {
+ // SAFETY: This is safe since current does not point within the now
+ // empty root node.
+ let root = unsafe { self.root.reborrow().as_mut().unwrap() };
+ root.pop_internal_level(self.alloc.clone());
+ }
+ Some(kv)
+ }
+
+ /// Removes the current element from the `BTreeMap`.
+ ///
+ /// The element that was removed is returned, and the cursor is
+ /// moved to point to the previous element in the `BTreeMap`.
+ ///
+ /// If the cursor is currently pointing to the "ghost" non-element then no element
+ /// is removed and `None` is returned. The cursor is not moved in this case.
+ #[unstable(feature = "btree_cursors", issue = "107540")]
+ pub fn remove_current_and_move_back(&mut self) -> Option<(K, V)> {
+ let current = self.current.take()?;
+ let mut emptied_internal_root = false;
+ let (kv, pos) =
+ current.remove_kv_tracking(|| emptied_internal_root = true, self.alloc.clone());
+ self.current = pos.next_back_kv().ok();
+ *self.length -= 1;
+ if emptied_internal_root {
+ // SAFETY: This is safe since current does not point within the now
+ // empty root node.
+ let root = unsafe { self.root.reborrow().as_mut().unwrap() };
+ root.pop_internal_level(self.alloc.clone());
+ }
+ Some(kv)
+ }
}
#[cfg(test)]
diff --git a/library/alloc/src/collections/btree/map/entry.rs b/library/alloc/src/collections/btree/map/entry.rs
index 370b58864..e9366eec9 100644
--- a/library/alloc/src/collections/btree/map/entry.rs
+++ b/library/alloc/src/collections/btree/map/entry.rs
@@ -347,7 +347,7 @@ impl<'a, K: Ord, V, A: Allocator + Clone> VacantEntry<'a, K, V, A> {
/// assert_eq!(map["poneyland"], 37);
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
- pub fn insert(self, value: V) -> &'a mut V {
+ pub fn insert(mut self, value: V) -> &'a mut V {
let out_ptr = match self.handle {
None => {
// SAFETY: There is no tree yet so no reference to it exists.
@@ -358,25 +358,27 @@ impl<'a, K: Ord, V, A: Allocator + Clone> VacantEntry<'a, K, V, A> {
map.length = 1;
val_ptr
}
- Some(handle) => match handle.insert_recursing(self.key, value, self.alloc.clone()) {
- (None, val_ptr) => {
- // SAFETY: We have consumed self.handle.
- let map = unsafe { self.dormant_map.awaken() };
- map.length += 1;
- val_ptr
- }
- (Some(ins), val_ptr) => {
- drop(ins.left);
- // SAFETY: We have consumed self.handle and dropped the
- // remaining reference to the tree, ins.left.
- let map = unsafe { self.dormant_map.awaken() };
- let root = map.root.as_mut().unwrap(); // same as ins.left
- root.push_internal_level(self.alloc).push(ins.kv.0, ins.kv.1, ins.right);
- map.length += 1;
- val_ptr
- }
- },
+ Some(handle) => {
+ let new_handle =
+ handle.insert_recursing(self.key, value, self.alloc.clone(), |ins| {
+ drop(ins.left);
+ // SAFETY: Pushing a new root node doesn't invalidate
+ // handles to existing nodes.
+ let map = unsafe { self.dormant_map.reborrow() };
+ let root = map.root.as_mut().unwrap(); // same as ins.left
+ root.push_internal_level(self.alloc).push(ins.kv.0, ins.kv.1, ins.right)
+ });
+
+ // Get the pointer to the value
+ let val_ptr = new_handle.into_val_mut();
+
+ // SAFETY: We have consumed self.handle.
+ let map = unsafe { self.dormant_map.awaken() };
+ map.length += 1;
+ val_ptr
+ }
};
+
// Now that we have finished growing the tree using borrowed references,
// dereference the pointer to a part of it, that we picked up along the way.
unsafe { &mut *out_ptr }
diff --git a/library/alloc/src/collections/btree/map/tests.rs b/library/alloc/src/collections/btree/map/tests.rs
index 700b1463b..76c2f27b4 100644
--- a/library/alloc/src/collections/btree/map/tests.rs
+++ b/library/alloc/src/collections/btree/map/tests.rs
@@ -2336,3 +2336,52 @@ fn from_array() {
let unordered_duplicates = BTreeMap::from([(3, 4), (1, 2), (1, 2)]);
assert_eq!(map, unordered_duplicates);
}
+
+#[test]
+fn test_cursor() {
+ let map = BTreeMap::from([(1, 'a'), (2, 'b'), (3, 'c')]);
+
+ let mut cur = map.lower_bound(Bound::Unbounded);
+ assert_eq!(cur.key(), Some(&1));
+ cur.move_next();
+ assert_eq!(cur.key(), Some(&2));
+ assert_eq!(cur.peek_next(), Some((&3, &'c')));
+ cur.move_prev();
+ assert_eq!(cur.key(), Some(&1));
+ assert_eq!(cur.peek_prev(), None);
+
+ let mut cur = map.upper_bound(Bound::Excluded(&1));
+ assert_eq!(cur.key(), None);
+ cur.move_next();
+ assert_eq!(cur.key(), Some(&1));
+ cur.move_prev();
+ assert_eq!(cur.key(), None);
+ assert_eq!(cur.peek_prev(), Some((&3, &'c')));
+}
+
+#[test]
+fn test_cursor_mut() {
+ let mut map = BTreeMap::from([(1, 'a'), (3, 'c'), (5, 'e')]);
+ let mut cur = map.lower_bound_mut(Bound::Excluded(&3));
+ assert_eq!(cur.key(), Some(&5));
+ cur.insert_before(4, 'd');
+ assert_eq!(cur.key(), Some(&5));
+ assert_eq!(cur.peek_prev(), Some((&4, &mut 'd')));
+ cur.move_next();
+ assert_eq!(cur.key(), None);
+ cur.insert_before(6, 'f');
+ assert_eq!(cur.key(), None);
+ assert_eq!(cur.remove_current(), None);
+ assert_eq!(cur.key(), None);
+ cur.insert_after(0, '?');
+ assert_eq!(cur.key(), None);
+ assert_eq!(map, BTreeMap::from([(0, '?'), (1, 'a'), (3, 'c'), (4, 'd'), (5, 'e'), (6, 'f')]));
+
+ let mut cur = map.upper_bound_mut(Bound::Included(&5));
+ assert_eq!(cur.key(), Some(&5));
+ assert_eq!(cur.remove_current(), Some((5, 'e')));
+ assert_eq!(cur.key(), Some(&6));
+ assert_eq!(cur.remove_current_and_move_back(), Some((6, 'f')));
+ assert_eq!(cur.key(), Some(&4));
+ assert_eq!(map, BTreeMap::from([(0, '?'), (1, 'a'), (3, 'c'), (4, 'd')]));
+}
diff --git a/library/alloc/src/collections/btree/navigate.rs b/library/alloc/src/collections/btree/navigate.rs
index 1e33c1e64..b890717e5 100644
--- a/library/alloc/src/collections/btree/navigate.rs
+++ b/library/alloc/src/collections/btree/navigate.rs
@@ -4,6 +4,7 @@ use core::ops::RangeBounds;
use core::ptr;
use super::node::{marker, ForceResult::*, Handle, NodeRef};
+use super::search::SearchBound;
use crate::alloc::Allocator;
// `front` and `back` are always both `None` or both `Some`.
@@ -386,7 +387,7 @@ impl<BorrowType: marker::BorrowType, K, V>
/// Given a leaf edge handle, returns [`Result::Ok`] with a handle to the neighboring KV
/// on the left side, which is either in the same leaf node or in an ancestor node.
/// If the leaf edge is the first one in the tree, returns [`Result::Err`] with the root node.
- fn next_back_kv(
+ pub fn next_back_kv(
self,
) -> Result<
Handle<NodeRef<BorrowType, K, V, marker::LeafOrInternal>, marker::KV>,
@@ -707,7 +708,9 @@ impl<BorrowType: marker::BorrowType, K, V>
}
/// Returns the leaf edge closest to a KV for backward navigation.
- fn next_back_leaf_edge(self) -> Handle<NodeRef<BorrowType, K, V, marker::Leaf>, marker::Edge> {
+ pub fn next_back_leaf_edge(
+ self,
+ ) -> Handle<NodeRef<BorrowType, K, V, marker::Leaf>, marker::Edge> {
match self.force() {
Leaf(leaf_kv) => leaf_kv.left_edge(),
Internal(internal_kv) => {
@@ -717,3 +720,51 @@ impl<BorrowType: marker::BorrowType, K, V>
}
}
}
+
+impl<BorrowType: marker::BorrowType, K, V> NodeRef<BorrowType, K, V, marker::LeafOrInternal> {
+ /// Returns the leaf edge corresponding to the first point at which the
+ /// given bound is true.
+ pub fn lower_bound<Q: ?Sized>(
+ self,
+ mut bound: SearchBound<&Q>,
+ ) -> Handle<NodeRef<BorrowType, K, V, marker::Leaf>, marker::Edge>
+ where
+ Q: Ord,
+ K: Borrow<Q>,
+ {
+ let mut node = self;
+ loop {
+ let (edge, new_bound) = node.find_lower_bound_edge(bound);
+ match edge.force() {
+ Leaf(edge) => return edge,
+ Internal(edge) => {
+ node = edge.descend();
+ bound = new_bound;
+ }
+ }
+ }
+ }
+
+ /// Returns the leaf edge corresponding to the last point at which the
+ /// given bound is true.
+ pub fn upper_bound<Q: ?Sized>(
+ self,
+ mut bound: SearchBound<&Q>,
+ ) -> Handle<NodeRef<BorrowType, K, V, marker::Leaf>, marker::Edge>
+ where
+ Q: Ord,
+ K: Borrow<Q>,
+ {
+ let mut node = self;
+ loop {
+ let (edge, new_bound) = node.find_upper_bound_edge(bound);
+ match edge.force() {
+ Leaf(edge) => return edge,
+ Internal(edge) => {
+ node = edge.descend();
+ bound = new_bound;
+ }
+ }
+ }
+ }
+}
diff --git a/library/alloc/src/collections/btree/node.rs b/library/alloc/src/collections/btree/node.rs
index 691246644..3233a575e 100644
--- a/library/alloc/src/collections/btree/node.rs
+++ b/library/alloc/src/collections/btree/node.rs
@@ -442,6 +442,24 @@ impl<'a, K, V, Type> NodeRef<marker::Mut<'a>, K, V, Type> {
// SAFETY: we have exclusive access to the entire node.
unsafe { &mut *ptr }
}
+
+ /// Returns a dormant copy of this node with its lifetime erased which can
+ /// be reawakened later.
+ pub fn dormant(&self) -> NodeRef<marker::DormantMut, K, V, Type> {
+ NodeRef { height: self.height, node: self.node, _marker: PhantomData }
+ }
+}
+
+impl<K, V, Type> NodeRef<marker::DormantMut, K, V, Type> {
+ /// Revert to the unique borrow initially captured.
+ ///
+ /// # Safety
+ ///
+ /// The reborrow must have ended, i.e., the reference returned by `new` and
+ /// all pointers and references derived from it, must not be used anymore.
+ pub unsafe fn awaken<'a>(self) -> NodeRef<marker::Mut<'a>, K, V, Type> {
+ NodeRef { height: self.height, node: self.node, _marker: PhantomData }
+ }
}
impl<K, V, Type> NodeRef<marker::Dying, K, V, Type> {
@@ -798,6 +816,25 @@ impl<'a, K, V, NodeType, HandleType> Handle<NodeRef<marker::Mut<'a>, K, V, NodeT
// We can't use Handle::new_kv or Handle::new_edge because we don't know our type
Handle { node: unsafe { self.node.reborrow_mut() }, idx: self.idx, _marker: PhantomData }
}
+
+ /// Returns a dormant copy of this handle which can be reawakened later.
+ ///
+ /// See `DormantMutRef` for more details.
+ pub fn dormant(&self) -> Handle<NodeRef<marker::DormantMut, K, V, NodeType>, HandleType> {
+ Handle { node: self.node.dormant(), idx: self.idx, _marker: PhantomData }
+ }
+}
+
+impl<K, V, NodeType, HandleType> Handle<NodeRef<marker::DormantMut, K, V, NodeType>, HandleType> {
+ /// Revert to the unique borrow initially captured.
+ ///
+ /// # Safety
+ ///
+ /// The reborrow must have ended, i.e., the reference returned by `new` and
+ /// all pointers and references derived from it, must not be used anymore.
+ pub unsafe fn awaken<'a>(self) -> Handle<NodeRef<marker::Mut<'a>, K, V, NodeType>, HandleType> {
+ Handle { node: unsafe { self.node.awaken() }, idx: self.idx, _marker: PhantomData }
+ }
}
impl<BorrowType, K, V, NodeType> Handle<NodeRef<BorrowType, K, V, NodeType>, marker::Edge> {
@@ -851,9 +888,11 @@ impl<'a, K: 'a, V: 'a> Handle<NodeRef<marker::Mut<'a>, K, V, marker::Leaf>, mark
/// Inserts a new key-value pair between the key-value pairs to the right and left of
/// this edge. This method assumes that there is enough space in the node for the new
/// pair to fit.
- ///
- /// The returned pointer points to the inserted value.
- fn insert_fit(&mut self, key: K, val: V) -> *mut V {
+ unsafe fn insert_fit(
+ mut self,
+ key: K,
+ val: V,
+ ) -> Handle<NodeRef<marker::Mut<'a>, K, V, marker::Leaf>, marker::KV> {
debug_assert!(self.node.len() < CAPACITY);
let new_len = self.node.len() + 1;
@@ -862,7 +901,7 @@ impl<'a, K: 'a, V: 'a> Handle<NodeRef<marker::Mut<'a>, K, V, marker::Leaf>, mark
slice_insert(self.node.val_area_mut(..new_len), self.idx, val);
*self.node.len_mut() = new_len as u16;
- self.node.val_area_mut(self.idx).assume_init_mut()
+ Handle::new_kv(self.node, self.idx)
}
}
}
@@ -871,21 +910,26 @@ impl<'a, K: 'a, V: 'a> Handle<NodeRef<marker::Mut<'a>, K, V, marker::Leaf>, mark
/// Inserts a new key-value pair between the key-value pairs to the right and left of
/// this edge. This method splits the node if there isn't enough room.
///
- /// The returned pointer points to the inserted value.
+ /// Returns a dormant handle to the inserted node which can be reawakened
+ /// once splitting is complete.
fn insert<A: Allocator + Clone>(
- mut self,
+ self,
key: K,
val: V,
alloc: A,
- ) -> (Option<SplitResult<'a, K, V, marker::Leaf>>, *mut V) {
+ ) -> (
+ Option<SplitResult<'a, K, V, marker::Leaf>>,
+ Handle<NodeRef<marker::DormantMut, K, V, marker::Leaf>, marker::KV>,
+ ) {
if self.node.len() < CAPACITY {
- let val_ptr = self.insert_fit(key, val);
- (None, val_ptr)
+ // SAFETY: There is enough space in the node for insertion.
+ let handle = unsafe { self.insert_fit(key, val) };
+ (None, handle.dormant())
} else {
let (middle_kv_idx, insertion) = splitpoint(self.idx);
let middle = unsafe { Handle::new_kv(self.node, middle_kv_idx) };
let mut result = middle.split(alloc);
- let mut insertion_edge = match insertion {
+ let insertion_edge = match insertion {
LeftOrRight::Left(insert_idx) => unsafe {
Handle::new_edge(result.left.reborrow_mut(), insert_idx)
},
@@ -893,8 +937,10 @@ impl<'a, K: 'a, V: 'a> Handle<NodeRef<marker::Mut<'a>, K, V, marker::Leaf>, mark
Handle::new_edge(result.right.borrow_mut(), insert_idx)
},
};
- let val_ptr = insertion_edge.insert_fit(key, val);
- (Some(result), val_ptr)
+ // SAFETY: We just split the node, so there is enough space for
+ // insertion.
+ let handle = unsafe { insertion_edge.insert_fit(key, val).dormant() };
+ (Some(result), handle)
}
}
}
@@ -976,21 +1022,31 @@ impl<'a, K: 'a, V: 'a> Handle<NodeRef<marker::Mut<'a>, K, V, marker::Leaf>, mark
key: K,
value: V,
alloc: A,
- ) -> (Option<SplitResult<'a, K, V, marker::LeafOrInternal>>, *mut V) {
- let (mut split, val_ptr) = match self.insert(key, value, alloc.clone()) {
- (None, val_ptr) => return (None, val_ptr),
- (Some(split), val_ptr) => (split.forget_node_type(), val_ptr),
+ split_root: impl FnOnce(SplitResult<'a, K, V, marker::LeafOrInternal>),
+ ) -> Handle<NodeRef<marker::Mut<'a>, K, V, marker::Leaf>, marker::KV> {
+ let (mut split, handle) = match self.insert(key, value, alloc.clone()) {
+ // SAFETY: we have finished splitting and can now re-awaken the
+ // handle to the inserted element.
+ (None, handle) => return unsafe { handle.awaken() },
+ (Some(split), handle) => (split.forget_node_type(), handle),
};
loop {
split = match split.left.ascend() {
Ok(parent) => {
match parent.insert(split.kv.0, split.kv.1, split.right, alloc.clone()) {
- None => return (None, val_ptr),
+ // SAFETY: we have finished splitting and can now re-awaken the
+ // handle to the inserted element.
+ None => return unsafe { handle.awaken() },
Some(split) => split.forget_node_type(),
}
}
- Err(root) => return (Some(SplitResult { left: root, ..split }), val_ptr),
+ Err(root) => {
+ split_root(SplitResult { left: root, ..split });
+ // SAFETY: we have finished splitting and can now re-awaken the
+ // handle to the inserted element.
+ return unsafe { handle.awaken() };
+ }
};
}
}
@@ -1043,6 +1099,14 @@ impl<'a, K: 'a, V: 'a, NodeType> Handle<NodeRef<marker::Mut<'a>, K, V, NodeType>
let leaf = self.node.into_leaf_mut();
unsafe { leaf.vals.get_unchecked_mut(self.idx).assume_init_mut() }
}
+
+ pub fn into_kv_valmut(self) -> (&'a K, &'a mut V) {
+ debug_assert!(self.idx < self.node.len());
+ let leaf = self.node.into_leaf_mut();
+ let k = unsafe { leaf.keys.get_unchecked(self.idx).assume_init_ref() };
+ let v = unsafe { leaf.vals.get_unchecked_mut(self.idx).assume_init_mut() };
+ (k, v)
+ }
}
impl<'a, K, V, NodeType> Handle<NodeRef<marker::ValMut<'a>, K, V, NodeType>, marker::KV> {
@@ -1667,6 +1731,7 @@ pub mod marker {
pub enum Owned {}
pub enum Dying {}
+ pub enum DormantMut {}
pub struct Immut<'a>(PhantomData<&'a ()>);
pub struct Mut<'a>(PhantomData<&'a mut ()>);
pub struct ValMut<'a>(PhantomData<&'a mut ()>);
@@ -1688,6 +1753,7 @@ pub mod marker {
impl<'a> BorrowType for Immut<'a> {}
impl<'a> BorrowType for Mut<'a> {}
impl<'a> BorrowType for ValMut<'a> {}
+ impl BorrowType for DormantMut {}
pub enum KV {}
pub enum Edge {}
diff --git a/library/alloc/src/collections/vec_deque/into_iter.rs b/library/alloc/src/collections/vec_deque/into_iter.rs
index e54880e86..34bc0ce91 100644
--- a/library/alloc/src/collections/vec_deque/into_iter.rs
+++ b/library/alloc/src/collections/vec_deque/into_iter.rs
@@ -1,5 +1,5 @@
-use core::fmt;
use core::iter::{FusedIterator, TrustedLen};
+use core::{array, fmt, mem::MaybeUninit, ops::Try, ptr};
use crate::alloc::{Allocator, Global};
@@ -52,6 +52,126 @@ impl<T, A: Allocator> Iterator for IntoIter<T, A> {
let len = self.inner.len();
(len, Some(len))
}
+
+ #[inline]
+ fn advance_by(&mut self, n: usize) -> Result<(), usize> {
+ if self.inner.len < n {
+ let len = self.inner.len;
+ self.inner.clear();
+ Err(len)
+ } else {
+ self.inner.drain(..n);
+ Ok(())
+ }
+ }
+
+ #[inline]
+ fn count(self) -> usize {
+ self.inner.len
+ }
+
+ fn try_fold<B, F, R>(&mut self, mut init: B, mut f: F) -> R
+ where
+ F: FnMut(B, Self::Item) -> R,
+ R: Try<Output = B>,
+ {
+ struct Guard<'a, T, A: Allocator> {
+ deque: &'a mut VecDeque<T, A>,
+ // `consumed <= deque.len` always holds.
+ consumed: usize,
+ }
+
+ impl<'a, T, A: Allocator> Drop for Guard<'a, T, A> {
+ fn drop(&mut self) {
+ self.deque.len -= self.consumed;
+ self.deque.head = self.deque.to_physical_idx(self.consumed);
+ }
+ }
+
+ let mut guard = Guard { deque: &mut self.inner, consumed: 0 };
+
+ let (head, tail) = guard.deque.as_slices();
+
+ init = head
+ .iter()
+ .map(|elem| {
+ guard.consumed += 1;
+ // SAFETY: Because we incremented `guard.consumed`, the
+ // deque effectively forgot the element, so we can take
+ // ownership
+ unsafe { ptr::read(elem) }
+ })
+ .try_fold(init, &mut f)?;
+
+ tail.iter()
+ .map(|elem| {
+ guard.consumed += 1;
+ // SAFETY: Same as above.
+ unsafe { ptr::read(elem) }
+ })
+ .try_fold(init, &mut f)
+ }
+
+ #[inline]
+ fn fold<B, F>(mut self, init: B, mut f: F) -> B
+ where
+ F: FnMut(B, Self::Item) -> B,
+ {
+ match self.try_fold(init, |b, item| Ok::<B, !>(f(b, item))) {
+ Ok(b) => b,
+ Err(e) => match e {},
+ }
+ }
+
+ #[inline]
+ fn last(mut self) -> Option<Self::Item> {
+ self.inner.pop_back()
+ }
+
+ fn next_chunk<const N: usize>(
+ &mut self,
+ ) -> Result<[Self::Item; N], array::IntoIter<Self::Item, N>> {
+ let mut raw_arr = MaybeUninit::uninit_array();
+ let raw_arr_ptr = raw_arr.as_mut_ptr().cast();
+ let (head, tail) = self.inner.as_slices();
+
+ if head.len() >= N {
+ // SAFETY: By manually adjusting the head and length of the deque, we effectively
+ // make it forget the first `N` elements, so taking ownership of them is safe.
+ unsafe { ptr::copy_nonoverlapping(head.as_ptr(), raw_arr_ptr, N) };
+ self.inner.head = self.inner.to_physical_idx(N);
+ self.inner.len -= N;
+ // SAFETY: We initialized the entire array with items from `head`
+ return Ok(unsafe { raw_arr.transpose().assume_init() });
+ }
+
+ // SAFETY: Same argument as above.
+ unsafe { ptr::copy_nonoverlapping(head.as_ptr(), raw_arr_ptr, head.len()) };
+ let remaining = N - head.len();
+
+ if tail.len() >= remaining {
+ // SAFETY: Same argument as above.
+ unsafe {
+ ptr::copy_nonoverlapping(tail.as_ptr(), raw_arr_ptr.add(head.len()), remaining)
+ };
+ self.inner.head = self.inner.to_physical_idx(N);
+ self.inner.len -= N;
+ // SAFETY: We initialized the entire array with items from `head` and `tail`
+ Ok(unsafe { raw_arr.transpose().assume_init() })
+ } else {
+ // SAFETY: Same argument as above.
+ unsafe {
+ ptr::copy_nonoverlapping(tail.as_ptr(), raw_arr_ptr.add(head.len()), tail.len())
+ };
+ let init = head.len() + tail.len();
+ // We completely drained all the deques elements.
+ self.inner.head = 0;
+ self.inner.len = 0;
+ // SAFETY: We copied all elements from both slices to the beginning of the array, so
+ // the given range is initialized.
+ Err(unsafe { array::IntoIter::new_unchecked(raw_arr, 0..init) })
+ }
+ }
}
#[stable(feature = "rust1", since = "1.0.0")]
@@ -60,10 +180,73 @@ impl<T, A: Allocator> DoubleEndedIterator for IntoIter<T, A> {
fn next_back(&mut self) -> Option<T> {
self.inner.pop_back()
}
+
+ #[inline]
+ fn advance_back_by(&mut self, n: usize) -> Result<(), usize> {
+ let len = self.inner.len;
+ if len >= n {
+ self.inner.truncate(len - n);
+ Ok(())
+ } else {
+ self.inner.clear();
+ Err(len)
+ }
+ }
+
+ fn try_rfold<B, F, R>(&mut self, mut init: B, mut f: F) -> R
+ where
+ F: FnMut(B, Self::Item) -> R,
+ R: Try<Output = B>,
+ {
+ struct Guard<'a, T, A: Allocator> {
+ deque: &'a mut VecDeque<T, A>,
+ // `consumed <= deque.len` always holds.
+ consumed: usize,
+ }
+
+ impl<'a, T, A: Allocator> Drop for Guard<'a, T, A> {
+ fn drop(&mut self) {
+ self.deque.len -= self.consumed;
+ }
+ }
+
+ let mut guard = Guard { deque: &mut self.inner, consumed: 0 };
+
+ let (head, tail) = guard.deque.as_slices();
+
+ init = tail
+ .iter()
+ .map(|elem| {
+ guard.consumed += 1;
+ // SAFETY: See `try_fold`'s safety comment.
+ unsafe { ptr::read(elem) }
+ })
+ .try_rfold(init, &mut f)?;
+
+ head.iter()
+ .map(|elem| {
+ guard.consumed += 1;
+ // SAFETY: Same as above.
+ unsafe { ptr::read(elem) }
+ })
+ .try_rfold(init, &mut f)
+ }
+
+ #[inline]
+ fn rfold<B, F>(mut self, init: B, mut f: F) -> B
+ where
+ F: FnMut(B, Self::Item) -> B,
+ {
+ match self.try_rfold(init, |b, item| Ok::<B, !>(f(b, item))) {
+ Ok(b) => b,
+ Err(e) => match e {},
+ }
+ }
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<T, A: Allocator> ExactSizeIterator for IntoIter<T, A> {
+ #[inline]
fn is_empty(&self) -> bool {
self.inner.is_empty()
}
diff --git a/library/alloc/src/ffi/c_str.rs b/library/alloc/src/ffi/c_str.rs
index 11bd4c4dc..f99395c72 100644
--- a/library/alloc/src/ffi/c_str.rs
+++ b/library/alloc/src/ffi/c_str.rs
@@ -991,12 +991,6 @@ impl IntoStringError {
pub fn utf8_error(&self) -> Utf8Error {
self.error
}
-
- #[doc(hidden)]
- #[unstable(feature = "cstr_internals", issue = "none")]
- pub fn __source(&self) -> &Utf8Error {
- &self.error
- }
}
impl IntoStringError {
@@ -1141,6 +1135,6 @@ impl core::error::Error for IntoStringError {
}
fn source(&self) -> Option<&(dyn core::error::Error + 'static)> {
- Some(self.__source())
+ Some(&self.error)
}
}
diff --git a/library/alloc/src/fmt.rs b/library/alloc/src/fmt.rs
index eadb35cb9..1da86e1a4 100644
--- a/library/alloc/src/fmt.rs
+++ b/library/alloc/src/fmt.rs
@@ -558,7 +558,7 @@ pub use core::fmt::Alignment;
#[stable(feature = "rust1", since = "1.0.0")]
pub use core::fmt::Error;
#[stable(feature = "rust1", since = "1.0.0")]
-pub use core::fmt::{write, ArgumentV1, Arguments};
+pub use core::fmt::{write, Arguments};
#[stable(feature = "rust1", since = "1.0.0")]
pub use core::fmt::{Binary, Octal};
#[stable(feature = "rust1", since = "1.0.0")]
diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs
index ca75c3895..e9cc3875f 100644
--- a/library/alloc/src/lib.rs
+++ b/library/alloc/src/lib.rs
@@ -87,6 +87,7 @@
#![warn(missing_debug_implementations)]
#![warn(missing_docs)]
#![allow(explicit_outlives_requirements)]
+#![cfg_attr(not(bootstrap), warn(multiple_supertrait_upcastable))]
//
// Library features:
#![feature(alloc_layout_extra)]
@@ -115,7 +116,6 @@
#![feature(const_eval_select)]
#![feature(const_pin)]
#![feature(const_waker)]
-#![feature(cstr_from_bytes_until_nul)]
#![feature(dispatch_from_dyn)]
#![feature(error_generic_member_access)]
#![feature(error_in_core)]
@@ -195,6 +195,7 @@
#![feature(c_unwind)]
#![feature(with_negative_coherence)]
#![cfg_attr(test, feature(panic_update_hook))]
+#![cfg_attr(not(bootstrap), feature(multiple_supertrait_upcastable))]
//
// Rustdoc features:
#![feature(doc_cfg)]
diff --git a/library/alloc/src/macros.rs b/library/alloc/src/macros.rs
index 5198bf297..4c6ae8f25 100644
--- a/library/alloc/src/macros.rs
+++ b/library/alloc/src/macros.rs
@@ -48,6 +48,8 @@ macro_rules! vec {
);
($($x:expr),+ $(,)?) => (
$crate::__rust_force_expr!(<[_]>::into_vec(
+ // This rustc_box is not required, but it produces a dramatic improvement in compile
+ // time when constructing arrays with many elements.
#[rustc_box]
$crate::boxed::Box::new([$($x),+])
))
diff --git a/library/alloc/src/raw_vec.rs b/library/alloc/src/raw_vec.rs
index 5a10121bb..3751f2a24 100644
--- a/library/alloc/src/raw_vec.rs
+++ b/library/alloc/src/raw_vec.rs
@@ -241,10 +241,15 @@ impl<T, A: Allocator> RawVec<T, A> {
if T::IS_ZST || self.cap == 0 {
None
} else {
- // We have an allocated chunk of memory, so we can bypass runtime
- // checks to get our current layout.
+ // We could use Layout::array here which ensures the absence of isize and usize overflows
+ // and could hypothetically handle differences between stride and size, but this memory
+ // has already been allocated so we know it can't overflow and currently rust does not
+ // support such types. So we can do better by skipping some checks and avoid an unwrap.
+ let _: () = const { assert!(mem::size_of::<T>() % mem::align_of::<T>() == 0) };
unsafe {
- let layout = Layout::array::<T>(self.cap).unwrap_unchecked();
+ let align = mem::align_of::<T>();
+ let size = mem::size_of::<T>().unchecked_mul(self.cap);
+ let layout = Layout::from_size_align_unchecked(size, align);
Some((self.ptr.cast().into(), layout))
}
}
@@ -426,11 +431,13 @@ impl<T, A: Allocator> RawVec<T, A> {
assert!(cap <= self.capacity(), "Tried to shrink to a larger capacity");
let (ptr, layout) = if let Some(mem) = self.current_memory() { mem } else { return Ok(()) };
-
+ // See current_memory() why this assert is here
+ let _: () = const { assert!(mem::size_of::<T>() % mem::align_of::<T>() == 0) };
let ptr = unsafe {
// `Layout::array` cannot overflow here because it would have
// overflowed earlier when capacity was larger.
- let new_layout = Layout::array::<T>(cap).unwrap_unchecked();
+ let new_size = mem::size_of::<T>().unchecked_mul(cap);
+ let new_layout = Layout::from_size_align_unchecked(new_size, layout.align());
self.alloc
.shrink(ptr, layout, new_layout)
.map_err(|_| AllocError { layout: new_layout, non_exhaustive: () })?
diff --git a/library/alloc/src/rc.rs b/library/alloc/src/rc.rs
index c9aa23fc4..932a537c5 100644
--- a/library/alloc/src/rc.rs
+++ b/library/alloc/src/rc.rs
@@ -1092,7 +1092,7 @@ impl<T: ?Sized> Rc<T> {
/// # Safety
///
/// If any other `Rc` or [`Weak`] pointers to the same allocation exist, then
- /// they must be must not be dereferenced or have active borrows for the duration
+ /// they must not be dereferenced or have active borrows for the duration
/// of the returned borrow, and their inner type must be exactly the same as the
/// inner type of this Rc (including lifetimes). This is trivially the case if no
/// such pointers exist, for example immediately after `Rc::new`.
@@ -2145,7 +2145,7 @@ impl<T, I: iter::TrustedLen<Item = T>> ToRcSlice<T> for I {
Rc::from_iter_exact(self, low)
}
} else {
- // TrustedLen contract guarantees that `upper_bound == `None` implies an iterator
+ // TrustedLen contract guarantees that `upper_bound == None` implies an iterator
// length exceeding `usize::MAX`.
// The default implementation would collect into a vec which would panic.
// Thus we panic here immediately without invoking `Vec` code.
diff --git a/library/alloc/src/slice.rs b/library/alloc/src/slice.rs
index fecacc2bb..093dcbbe8 100644
--- a/library/alloc/src/slice.rs
+++ b/library/alloc/src/slice.rs
@@ -782,6 +782,38 @@ impl<T, A: Allocator> BorrowMut<[T]> for Vec<T, A> {
}
}
+// Specializable trait for implementing ToOwned::clone_into. This is
+// public in the crate and has the Allocator parameter so that
+// vec::clone_from use it too.
+#[cfg(not(no_global_oom_handling))]
+pub(crate) trait SpecCloneIntoVec<T, A: Allocator> {
+ fn clone_into(&self, target: &mut Vec<T, A>);
+}
+
+#[cfg(not(no_global_oom_handling))]
+impl<T: Clone, A: Allocator> SpecCloneIntoVec<T, A> for [T] {
+ default fn clone_into(&self, target: &mut Vec<T, A>) {
+ // drop anything in target that will not be overwritten
+ target.truncate(self.len());
+
+ // target.len <= self.len due to the truncate above, so the
+ // slices here are always in-bounds.
+ let (init, tail) = self.split_at(target.len());
+
+ // reuse the contained values' allocations/resources.
+ target.clone_from_slice(init);
+ target.extend_from_slice(tail);
+ }
+}
+
+#[cfg(not(no_global_oom_handling))]
+impl<T: Copy, A: Allocator> SpecCloneIntoVec<T, A> for [T] {
+ fn clone_into(&self, target: &mut Vec<T, A>) {
+ target.clear();
+ target.extend_from_slice(self);
+ }
+}
+
#[cfg(not(no_global_oom_handling))]
#[stable(feature = "rust1", since = "1.0.0")]
impl<T: Clone> ToOwned for [T] {
@@ -797,16 +829,7 @@ impl<T: Clone> ToOwned for [T] {
}
fn clone_into(&self, target: &mut Vec<T>) {
- // drop anything in target that will not be overwritten
- target.truncate(self.len());
-
- // target.len <= self.len due to the truncate above, so the
- // slices here are always in-bounds.
- let (init, tail) = self.split_at(target.len());
-
- // reuse the contained values' allocations/resources.
- target.clone_from_slice(init);
- target.extend_from_slice(tail);
+ SpecCloneIntoVec::clone_into(self, target);
}
}
diff --git a/library/alloc/src/string.rs b/library/alloc/src/string.rs
index ca182c810..c7e7ed3e9 100644
--- a/library/alloc/src/string.rs
+++ b/library/alloc/src/string.rs
@@ -42,8 +42,6 @@
#![stable(feature = "rust1", since = "1.0.0")]
-#[cfg(not(no_global_oom_handling))]
-use core::char::{decode_utf16, REPLACEMENT_CHARACTER};
use core::error::Error;
use core::fmt;
use core::hash;
@@ -683,7 +681,7 @@ impl String {
// This isn't done via collect::<Result<_, _>>() for performance reasons.
// FIXME: the function can be simplified again when #48994 is closed.
let mut ret = String::with_capacity(v.len());
- for c in decode_utf16(v.iter().cloned()) {
+ for c in char::decode_utf16(v.iter().cloned()) {
if let Ok(c) = c {
ret.push(c);
} else {
@@ -722,7 +720,9 @@ impl String {
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
pub fn from_utf16_lossy(v: &[u16]) -> String {
- decode_utf16(v.iter().cloned()).map(|r| r.unwrap_or(REPLACEMENT_CHARACTER)).collect()
+ char::decode_utf16(v.iter().cloned())
+ .map(|r| r.unwrap_or(char::REPLACEMENT_CHARACTER))
+ .collect()
}
/// Decomposes a `String` into its raw components.
@@ -928,12 +928,12 @@ impl String {
/// Copies elements from `src` range to the end of the string.
///
- /// ## Panics
+ /// # Panics
///
/// Panics if the starting point or end point do not lie on a [`char`]
/// boundary, or if they're out of bounds.
///
- /// ## Examples
+ /// # Examples
///
/// ```
/// #![feature(string_extend_from_within)]
@@ -2213,10 +2213,6 @@ impl PartialEq for String {
fn eq(&self, other: &String) -> bool {
PartialEq::eq(&self[..], &other[..])
}
- #[inline]
- fn ne(&self, other: &String) -> bool {
- PartialEq::ne(&self[..], &other[..])
- }
}
macro_rules! impl_eq {
diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs
index bab7f5f53..fdd341a06 100644
--- a/library/alloc/src/sync.rs
+++ b/library/alloc/src/sync.rs
@@ -654,6 +654,20 @@ impl<T> Arc<T> {
///
/// This will succeed even if there are outstanding weak references.
///
+ // FIXME: when `Arc::into_inner` is stabilized, add this paragraph:
+ /*
+ /// It is strongly recommended to use [`Arc::into_inner`] instead if you don't
+ /// want to keep the `Arc` in the [`Err`] case.
+ /// Immediately dropping the [`Err`] payload, like in the expression
+ /// `Arc::try_unwrap(this).ok()`, can still cause the strong count to
+ /// drop to zero and the inner value of the `Arc` to be dropped:
+ /// For instance if two threads execute this expression in parallel, then
+ /// there is a race condition. The threads could first both check whether they
+ /// have the last clone of their `Arc` via `Arc::try_unwrap`, and then
+ /// both drop their `Arc` in the call to [`ok`][`Result::ok`],
+ /// taking the strong count from two down to zero.
+ ///
+ */
/// # Examples
///
/// ```
@@ -685,6 +699,137 @@ impl<T> Arc<T> {
Ok(elem)
}
}
+
+ /// Returns the inner value, if the `Arc` has exactly one strong reference.
+ ///
+ /// Otherwise, [`None`] is returned and the `Arc` is dropped.
+ ///
+ /// This will succeed even if there are outstanding weak references.
+ ///
+ /// If `Arc::into_inner` is called on every clone of this `Arc`,
+ /// it is guaranteed that exactly one of the calls returns the inner value.
+ /// This means in particular that the inner value is not dropped.
+ ///
+ /// The similar expression `Arc::try_unwrap(this).ok()` does not
+ /// offer such a guarantee. See the last example below.
+ //
+ // FIXME: when `Arc::into_inner` is stabilized, add this to end
+ // of the previous sentence:
+ /*
+ /// and the documentation of [`Arc::try_unwrap`].
+ */
+ ///
+ /// # Examples
+ ///
+ /// Minimal example demonstrating the guarantee that `Arc::into_inner` gives.
+ /// ```
+ /// #![feature(arc_into_inner)]
+ ///
+ /// use std::sync::Arc;
+ ///
+ /// let x = Arc::new(3);
+ /// let y = Arc::clone(&x);
+ ///
+ /// // Two threads calling `Arc::into_inner` on both clones of an `Arc`:
+ /// let x_thread = std::thread::spawn(|| Arc::into_inner(x));
+ /// let y_thread = std::thread::spawn(|| Arc::into_inner(y));
+ ///
+ /// let x_inner_value = x_thread.join().unwrap();
+ /// let y_inner_value = y_thread.join().unwrap();
+ ///
+ /// // One of the threads is guaranteed to receive the inner value:
+ /// assert!(matches!(
+ /// (x_inner_value, y_inner_value),
+ /// (None, Some(3)) | (Some(3), None)
+ /// ));
+ /// // The result could also be `(None, None)` if the threads called
+ /// // `Arc::try_unwrap(x).ok()` and `Arc::try_unwrap(y).ok()` instead.
+ /// ```
+ ///
+ /// A more practical example demonstrating the need for `Arc::into_inner`:
+ /// ```
+ /// #![feature(arc_into_inner)]
+ ///
+ /// use std::sync::Arc;
+ ///
+ /// // Definition of a simple singly linked list using `Arc`:
+ /// #[derive(Clone)]
+ /// struct LinkedList<T>(Option<Arc<Node<T>>>);
+ /// struct Node<T>(T, Option<Arc<Node<T>>>);
+ ///
+ /// // Dropping a long `LinkedList<T>` relying on the destructor of `Arc`
+ /// // can cause a stack overflow. To prevent this, we can provide a
+ /// // manual `Drop` implementation that does the destruction in a loop:
+ /// impl<T> Drop for LinkedList<T> {
+ /// fn drop(&mut self) {
+ /// let mut link = self.0.take();
+ /// while let Some(arc_node) = link.take() {
+ /// if let Some(Node(_value, next)) = Arc::into_inner(arc_node) {
+ /// link = next;
+ /// }
+ /// }
+ /// }
+ /// }
+ ///
+ /// // Implementation of `new` and `push` omitted
+ /// impl<T> LinkedList<T> {
+ /// /* ... */
+ /// # fn new() -> Self {
+ /// # LinkedList(None)
+ /// # }
+ /// # fn push(&mut self, x: T) {
+ /// # self.0 = Some(Arc::new(Node(x, self.0.take())));
+ /// # }
+ /// }
+ ///
+ /// // The following code could have still caused a stack overflow
+ /// // despite the manual `Drop` impl if that `Drop` impl had used
+ /// // `Arc::try_unwrap(arc).ok()` instead of `Arc::into_inner(arc)`.
+ ///
+ /// // Create a long list and clone it
+ /// let mut x = LinkedList::new();
+ /// for i in 0..100000 {
+ /// x.push(i); // Adds i to the front of x
+ /// }
+ /// let y = x.clone();
+ ///
+ /// // Drop the clones in parallel
+ /// let x_thread = std::thread::spawn(|| drop(x));
+ /// let y_thread = std::thread::spawn(|| drop(y));
+ /// x_thread.join().unwrap();
+ /// y_thread.join().unwrap();
+ /// ```
+
+ // FIXME: when `Arc::into_inner` is stabilized, adjust above documentation
+ // and the documentation of `Arc::try_unwrap` according to the `FIXME`s. Also
+ // open an issue on rust-lang/rust-clippy, asking for a lint against
+ // `Arc::try_unwrap(...).ok()`.
+ #[inline]
+ #[unstable(feature = "arc_into_inner", issue = "106894")]
+ pub fn into_inner(this: Self) -> Option<T> {
+ // Make sure that the ordinary `Drop` implementation isn’t called as well
+ let mut this = mem::ManuallyDrop::new(this);
+
+ // Following the implementation of `drop` and `drop_slow`
+ if this.inner().strong.fetch_sub(1, Release) != 1 {
+ return None;
+ }
+
+ acquire!(this.inner().strong);
+
+ // SAFETY: This mirrors the line
+ //
+ // unsafe { ptr::drop_in_place(Self::get_mut_unchecked(self)) };
+ //
+ // in `drop_slow`. Instead of dropping the value behind the pointer,
+ // it is read and eventually returned; `ptr::read` has the same
+ // safety conditions as `ptr::drop_in_place`.
+ let inner = unsafe { ptr::read(Self::get_mut_unchecked(&mut this)) };
+
+ drop(Weak { ptr: this.ptr });
+
+ Some(inner)
+ }
}
impl<T> Arc<[T]> {
@@ -1588,7 +1733,7 @@ impl<T: ?Sized> Arc<T> {
/// # Safety
///
/// If any other `Arc` or [`Weak`] pointers to the same allocation exist, then
- /// they must be must not be dereferenced or have active borrows for the duration
+ /// they must not be dereferenced or have active borrows for the duration
/// of the returned borrow, and their inner type must be exactly the same as the
/// inner type of this Rc (including lifetimes). This is trivially the case if no
/// such pointers exist, for example immediately after `Arc::new`.
@@ -2750,7 +2895,7 @@ impl<T, I: iter::TrustedLen<Item = T>> ToArcSlice<T> for I {
Arc::from_iter_exact(self, low)
}
} else {
- // TrustedLen contract guarantees that `upper_bound == `None` implies an iterator
+ // TrustedLen contract guarantees that `upper_bound == None` implies an iterator
// length exceeding `usize::MAX`.
// The default implementation would collect into a vec which would panic.
// Thus we panic here immediately without invoking `Vec` code.
diff --git a/library/alloc/src/sync/tests.rs b/library/alloc/src/sync/tests.rs
index 0fae8953a..863d58bdf 100644
--- a/library/alloc/src/sync/tests.rs
+++ b/library/alloc/src/sync/tests.rs
@@ -102,6 +102,38 @@ fn try_unwrap() {
}
#[test]
+fn into_inner() {
+ for _ in 0..100
+ // ^ Increase chances of hitting potential race conditions
+ {
+ let x = Arc::new(3);
+ let y = Arc::clone(&x);
+ let r_thread = std::thread::spawn(|| Arc::into_inner(x));
+ let s_thread = std::thread::spawn(|| Arc::into_inner(y));
+ let r = r_thread.join().expect("r_thread panicked");
+ let s = s_thread.join().expect("s_thread panicked");
+ assert!(
+ matches!((r, s), (None, Some(3)) | (Some(3), None)),
+ "assertion failed: unexpected result `{:?}`\
+ \n expected `(None, Some(3))` or `(Some(3), None)`",
+ (r, s),
+ );
+ }
+
+ let x = Arc::new(3);
+ assert_eq!(Arc::into_inner(x), Some(3));
+
+ let x = Arc::new(4);
+ let y = Arc::clone(&x);
+ assert_eq!(Arc::into_inner(x), None);
+ assert_eq!(Arc::into_inner(y), Some(4));
+
+ let x = Arc::new(5);
+ let _w = Arc::downgrade(&x);
+ assert_eq!(Arc::into_inner(x), Some(5));
+}
+
+#[test]
fn into_from_raw() {
let x = Arc::new(Box::new("hello"));
let y = x.clone();
diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs
index 36b0b3c9e..f2aa30f18 100644
--- a/library/alloc/src/vec/mod.rs
+++ b/library/alloc/src/vec/mod.rs
@@ -378,8 +378,8 @@ mod spec_extend;
/// Currently, `Vec` does not guarantee the order in which elements are dropped.
/// The order has changed in the past and may change again.
///
-/// [`get`]: ../../std/vec/struct.Vec.html#method.get
-/// [`get_mut`]: ../../std/vec/struct.Vec.html#method.get_mut
+/// [`get`]: slice::get
+/// [`get_mut`]: slice::get_mut
/// [`String`]: crate::string::String
/// [`&str`]: type@str
/// [`shrink_to_fit`]: Vec::shrink_to_fit
@@ -2647,35 +2647,6 @@ impl<T, A: Allocator> ops::DerefMut for Vec<T, A> {
}
#[cfg(not(no_global_oom_handling))]
-trait SpecCloneFrom {
- fn clone_from(this: &mut Self, other: &Self);
-}
-
-#[cfg(not(no_global_oom_handling))]
-impl<T: Clone, A: Allocator> SpecCloneFrom for Vec<T, A> {
- default fn clone_from(this: &mut Self, other: &Self) {
- // drop anything that will not be overwritten
- this.truncate(other.len());
-
- // self.len <= other.len due to the truncate above, so the
- // slices here are always in-bounds.
- let (init, tail) = other.split_at(this.len());
-
- // reuse the contained values' allocations/resources.
- this.clone_from_slice(init);
- this.extend_from_slice(tail);
- }
-}
-
-#[cfg(not(no_global_oom_handling))]
-impl<T: Copy, A: Allocator> SpecCloneFrom for Vec<T, A> {
- fn clone_from(this: &mut Self, other: &Self) {
- this.clear();
- this.extend_from_slice(other);
- }
-}
-
-#[cfg(not(no_global_oom_handling))]
#[stable(feature = "rust1", since = "1.0.0")]
impl<T: Clone, A: Allocator + Clone> Clone for Vec<T, A> {
#[cfg(not(test))]
@@ -2695,7 +2666,7 @@ impl<T: Clone, A: Allocator + Clone> Clone for Vec<T, A> {
}
fn clone_from(&mut self, other: &Self) {
- SpecCloneFrom::clone_from(self, other)
+ crate::slice::SpecCloneIntoVec::clone_into(other.as_slice(), self);
}
}
@@ -3160,10 +3131,7 @@ impl<T, const N: usize> From<[T; N]> for Vec<T> {
/// ```
#[cfg(not(test))]
fn from(s: [T; N]) -> Vec<T> {
- <[T]>::into_vec(
- #[rustc_box]
- Box::new(s),
- )
+ <[T]>::into_vec(Box::new(s))
}
#[cfg(test)]
diff --git a/library/core/benches/array.rs b/library/core/benches/array.rs
new file mode 100644
index 000000000..d8cc44d05
--- /dev/null
+++ b/library/core/benches/array.rs
@@ -0,0 +1,19 @@
+use test::black_box;
+use test::Bencher;
+
+macro_rules! map_array {
+ ($func_name:ident, $start_item: expr, $map_item: expr, $arr_size: expr) => {
+ #[bench]
+ fn $func_name(b: &mut Bencher) {
+ let arr = [$start_item; $arr_size];
+ b.iter(|| black_box(arr).map(|_| black_box($map_item)));
+ }
+ };
+}
+
+map_array!(map_8byte_8byte_8, 0u64, 1u64, 80);
+map_array!(map_8byte_8byte_64, 0u64, 1u64, 640);
+map_array!(map_8byte_8byte_256, 0u64, 1u64, 2560);
+
+map_array!(map_8byte_256byte_256, 0u64, [0u64; 4], 2560);
+map_array!(map_256byte_8byte_256, [0u64; 4], 0u64, 2560);
diff --git a/library/core/benches/char/methods.rs b/library/core/benches/char/methods.rs
index 9408f83c3..5d4df1ac8 100644
--- a/library/core/benches/char/methods.rs
+++ b/library/core/benches/char/methods.rs
@@ -1,26 +1,26 @@
-use test::Bencher;
+use test::{black_box, Bencher};
const CHARS: [char; 9] = ['0', 'x', '2', '5', 'A', 'f', '7', '8', '9'];
const RADIX: [u32; 5] = [2, 8, 10, 16, 32];
#[bench]
fn bench_to_digit_radix_2(b: &mut Bencher) {
- b.iter(|| CHARS.iter().cycle().take(10_000).map(|c| c.to_digit(2)).min())
+ b.iter(|| CHARS.iter().cycle().take(10_000).map(|c| black_box(c).to_digit(2)).min())
}
#[bench]
fn bench_to_digit_radix_10(b: &mut Bencher) {
- b.iter(|| CHARS.iter().cycle().take(10_000).map(|c| c.to_digit(10)).min())
+ b.iter(|| CHARS.iter().cycle().take(10_000).map(|c| black_box(c).to_digit(10)).min())
}
#[bench]
fn bench_to_digit_radix_16(b: &mut Bencher) {
- b.iter(|| CHARS.iter().cycle().take(10_000).map(|c| c.to_digit(16)).min())
+ b.iter(|| CHARS.iter().cycle().take(10_000).map(|c| black_box(c).to_digit(16)).min())
}
#[bench]
fn bench_to_digit_radix_36(b: &mut Bencher) {
- b.iter(|| CHARS.iter().cycle().take(10_000).map(|c| c.to_digit(36)).min())
+ b.iter(|| CHARS.iter().cycle().take(10_000).map(|c| black_box(c).to_digit(36)).min())
}
#[bench]
@@ -31,47 +31,59 @@ fn bench_to_digit_radix_var(b: &mut Bencher) {
.cycle()
.zip(RADIX.iter().cycle())
.take(10_000)
- .map(|(c, radix)| c.to_digit(*radix))
+ .map(|(c, radix)| black_box(c).to_digit(*radix))
.min()
})
}
#[bench]
fn bench_to_ascii_uppercase(b: &mut Bencher) {
- b.iter(|| CHARS.iter().cycle().take(10_000).map(|c| c.to_ascii_uppercase()).min())
+ b.iter(|| CHARS.iter().cycle().take(10_000).map(|c| black_box(c).to_ascii_uppercase()).min())
}
#[bench]
fn bench_to_ascii_lowercase(b: &mut Bencher) {
- b.iter(|| CHARS.iter().cycle().take(10_000).map(|c| c.to_ascii_lowercase()).min())
+ b.iter(|| CHARS.iter().cycle().take(10_000).map(|c| black_box(c).to_ascii_lowercase()).min())
}
#[bench]
fn bench_ascii_mix_to_uppercase(b: &mut Bencher) {
- b.iter(|| (0..=255).cycle().take(10_000).map(|b| char::from(b).to_uppercase()).count())
+ b.iter(|| {
+ (0..=255).cycle().take(10_000).map(|b| black_box(char::from(b)).to_uppercase()).count()
+ })
}
#[bench]
fn bench_ascii_mix_to_lowercase(b: &mut Bencher) {
- b.iter(|| (0..=255).cycle().take(10_000).map(|b| char::from(b).to_lowercase()).count())
+ b.iter(|| {
+ (0..=255).cycle().take(10_000).map(|b| black_box(char::from(b)).to_lowercase()).count()
+ })
}
#[bench]
fn bench_ascii_char_to_uppercase(b: &mut Bencher) {
- b.iter(|| (0..=127).cycle().take(10_000).map(|b| char::from(b).to_uppercase()).count())
+ b.iter(|| {
+ (0..=127).cycle().take(10_000).map(|b| black_box(char::from(b)).to_uppercase()).count()
+ })
}
#[bench]
fn bench_ascii_char_to_lowercase(b: &mut Bencher) {
- b.iter(|| (0..=127).cycle().take(10_000).map(|b| char::from(b).to_lowercase()).count())
+ b.iter(|| {
+ (0..=127).cycle().take(10_000).map(|b| black_box(char::from(b)).to_lowercase()).count()
+ })
}
#[bench]
fn bench_non_ascii_char_to_uppercase(b: &mut Bencher) {
- b.iter(|| (128..=255).cycle().take(10_000).map(|b| char::from(b).to_uppercase()).count())
+ b.iter(|| {
+ (128..=255).cycle().take(10_000).map(|b| black_box(char::from(b)).to_uppercase()).count()
+ })
}
#[bench]
fn bench_non_ascii_char_to_lowercase(b: &mut Bencher) {
- b.iter(|| (128..=255).cycle().take(10_000).map(|b| char::from(b).to_lowercase()).count())
+ b.iter(|| {
+ (128..=255).cycle().take(10_000).map(|b| black_box(char::from(b)).to_lowercase()).count()
+ })
}
diff --git a/library/core/benches/lib.rs b/library/core/benches/lib.rs
index f1244d932..e4100120d 100644
--- a/library/core/benches/lib.rs
+++ b/library/core/benches/lib.rs
@@ -9,6 +9,7 @@
extern crate test;
mod any;
+mod array;
mod ascii;
mod char;
mod fmt;
diff --git a/library/core/benches/num/flt2dec/strategy/dragon.rs b/library/core/benches/num/flt2dec/strategy/dragon.rs
index 319b9773e..377c99eff 100644
--- a/library/core/benches/num/flt2dec/strategy/dragon.rs
+++ b/library/core/benches/num/flt2dec/strategy/dragon.rs
@@ -1,14 +1,14 @@
use super::super::*;
use core::num::flt2dec::strategy::dragon::*;
use std::mem::MaybeUninit;
-use test::Bencher;
+use test::{black_box, Bencher};
#[bench]
fn bench_small_shortest(b: &mut Bencher) {
let decoded = decode_finite(3.141592f64);
let mut buf = [MaybeUninit::new(0); MAX_SIG_DIGITS];
b.iter(|| {
- format_shortest(&decoded, &mut buf);
+ format_shortest(black_box(&decoded), &mut buf);
});
}
@@ -17,7 +17,7 @@ fn bench_big_shortest(b: &mut Bencher) {
let decoded = decode_finite(f64::MAX);
let mut buf = [MaybeUninit::new(0); MAX_SIG_DIGITS];
b.iter(|| {
- format_shortest(&decoded, &mut buf);
+ format_shortest(black_box(&decoded), &mut buf);
});
}
@@ -26,7 +26,7 @@ fn bench_small_exact_3(b: &mut Bencher) {
let decoded = decode_finite(3.141592f64);
let mut buf = [MaybeUninit::new(0); 3];
b.iter(|| {
- format_exact(&decoded, &mut buf, i16::MIN);
+ format_exact(black_box(&decoded), &mut buf, i16::MIN);
});
}
@@ -35,7 +35,7 @@ fn bench_big_exact_3(b: &mut Bencher) {
let decoded = decode_finite(f64::MAX);
let mut buf = [MaybeUninit::new(0); 3];
b.iter(|| {
- format_exact(&decoded, &mut buf, i16::MIN);
+ format_exact(black_box(&decoded), &mut buf, i16::MIN);
});
}
@@ -44,7 +44,7 @@ fn bench_small_exact_12(b: &mut Bencher) {
let decoded = decode_finite(3.141592f64);
let mut buf = [MaybeUninit::new(0); 12];
b.iter(|| {
- format_exact(&decoded, &mut buf, i16::MIN);
+ format_exact(black_box(&decoded), &mut buf, i16::MIN);
});
}
@@ -53,7 +53,7 @@ fn bench_big_exact_12(b: &mut Bencher) {
let decoded = decode_finite(f64::MAX);
let mut buf = [MaybeUninit::new(0); 12];
b.iter(|| {
- format_exact(&decoded, &mut buf, i16::MIN);
+ format_exact(black_box(&decoded), &mut buf, i16::MIN);
});
}
@@ -62,7 +62,7 @@ fn bench_small_exact_inf(b: &mut Bencher) {
let decoded = decode_finite(3.141592f64);
let mut buf = [MaybeUninit::new(0); 1024];
b.iter(|| {
- format_exact(&decoded, &mut buf, i16::MIN);
+ format_exact(black_box(&decoded), &mut buf, i16::MIN);
});
}
@@ -71,6 +71,6 @@ fn bench_big_exact_inf(b: &mut Bencher) {
let decoded = decode_finite(f64::MAX);
let mut buf = [MaybeUninit::new(0); 1024];
b.iter(|| {
- format_exact(&decoded, &mut buf, i16::MIN);
+ format_exact(black_box(&decoded), &mut buf, i16::MIN);
});
}
diff --git a/library/core/benches/num/flt2dec/strategy/grisu.rs b/library/core/benches/num/flt2dec/strategy/grisu.rs
index 8e47a046c..6bea5e55d 100644
--- a/library/core/benches/num/flt2dec/strategy/grisu.rs
+++ b/library/core/benches/num/flt2dec/strategy/grisu.rs
@@ -1,7 +1,7 @@
use super::super::*;
use core::num::flt2dec::strategy::grisu::*;
use std::mem::MaybeUninit;
-use test::Bencher;
+use test::{black_box, Bencher};
pub fn decode_finite<T: DecodableFloat>(v: T) -> Decoded {
match decode(v).1 {
@@ -15,7 +15,7 @@ fn bench_small_shortest(b: &mut Bencher) {
let decoded = decode_finite(3.141592f64);
let mut buf = [MaybeUninit::new(0); MAX_SIG_DIGITS];
b.iter(|| {
- format_shortest(&decoded, &mut buf);
+ format_shortest(black_box(&decoded), &mut buf);
});
}
@@ -24,7 +24,7 @@ fn bench_big_shortest(b: &mut Bencher) {
let decoded = decode_finite(f64::MAX);
let mut buf = [MaybeUninit::new(0); MAX_SIG_DIGITS];
b.iter(|| {
- format_shortest(&decoded, &mut buf);
+ format_shortest(black_box(&decoded), &mut buf);
});
}
@@ -33,7 +33,7 @@ fn bench_small_exact_3(b: &mut Bencher) {
let decoded = decode_finite(3.141592f64);
let mut buf = [MaybeUninit::new(0); 3];
b.iter(|| {
- format_exact(&decoded, &mut buf, i16::MIN);
+ format_exact(black_box(&decoded), &mut buf, i16::MIN);
});
}
@@ -42,7 +42,7 @@ fn bench_big_exact_3(b: &mut Bencher) {
let decoded = decode_finite(f64::MAX);
let mut buf = [MaybeUninit::new(0); 3];
b.iter(|| {
- format_exact(&decoded, &mut buf, i16::MIN);
+ format_exact(black_box(&decoded), &mut buf, i16::MIN);
});
}
@@ -51,7 +51,7 @@ fn bench_small_exact_12(b: &mut Bencher) {
let decoded = decode_finite(3.141592f64);
let mut buf = [MaybeUninit::new(0); 12];
b.iter(|| {
- format_exact(&decoded, &mut buf, i16::MIN);
+ format_exact(black_box(&decoded), &mut buf, i16::MIN);
});
}
@@ -60,7 +60,7 @@ fn bench_big_exact_12(b: &mut Bencher) {
let decoded = decode_finite(f64::MAX);
let mut buf = [MaybeUninit::new(0); 12];
b.iter(|| {
- format_exact(&decoded, &mut buf, i16::MIN);
+ format_exact(black_box(&decoded), &mut buf, i16::MIN);
});
}
@@ -69,7 +69,7 @@ fn bench_small_exact_inf(b: &mut Bencher) {
let decoded = decode_finite(3.141592f64);
let mut buf = [MaybeUninit::new(0); 1024];
b.iter(|| {
- format_exact(&decoded, &mut buf, i16::MIN);
+ format_exact(black_box(&decoded), &mut buf, i16::MIN);
});
}
@@ -78,6 +78,6 @@ fn bench_big_exact_inf(b: &mut Bencher) {
let decoded = decode_finite(f64::MAX);
let mut buf = [MaybeUninit::new(0); 1024];
b.iter(|| {
- format_exact(&decoded, &mut buf, i16::MIN);
+ format_exact(black_box(&decoded), &mut buf, i16::MIN);
});
}
diff --git a/library/core/src/alloc/global.rs b/library/core/src/alloc/global.rs
index 1d80b8bf9..18da70451 100644
--- a/library/core/src/alloc/global.rs
+++ b/library/core/src/alloc/global.rs
@@ -203,7 +203,7 @@ pub unsafe trait GlobalAlloc {
ptr
}
- /// Shrink or grow a block of memory to the given `new_size`.
+ /// Shrink or grow a block of memory to the given `new_size` in bytes.
/// The block is described by the given `ptr` pointer and `layout`.
///
/// If this returns a non-null pointer, then ownership of the memory block
@@ -211,10 +211,11 @@ pub unsafe trait GlobalAlloc {
/// Any access to the old `ptr` is Undefined Behavior, even if the
/// allocation remained in-place. The newly returned pointer is the only valid pointer
/// for accessing this memory now.
+ ///
/// The new memory block is allocated with `layout`,
- /// but with the `size` updated to `new_size`. This new layout must be
- /// used when deallocating the new memory block with `dealloc`. The range
- /// `0..min(layout.size(), new_size)` of the new memory block is
+ /// but with the `size` updated to `new_size` in bytes.
+ /// This new layout must be used when deallocating the new memory block with `dealloc`.
+ /// The range `0..min(layout.size(), new_size)` of the new memory block is
/// guaranteed to have the same values as the original block.
///
/// If this method returns null, then ownership of the memory
diff --git a/library/core/src/any.rs b/library/core/src/any.rs
index c0fb0d993..c27646b8f 100644
--- a/library/core/src/any.rs
+++ b/library/core/src/any.rs
@@ -56,7 +56,7 @@
//! let value_any = value as &dyn Any;
//!
//! // Try to convert our value to a `String`. If successful, we want to
-//! // output the String`'s length as well as its value. If not, it's a
+//! // output the `String`'s length as well as its value. If not, it's a
//! // different type: just print it out unadorned.
//! match value_any.downcast_ref::<String>() {
//! Some(as_string) => {
diff --git a/library/core/src/array/drain.rs b/library/core/src/array/drain.rs
new file mode 100644
index 000000000..5fadf907b
--- /dev/null
+++ b/library/core/src/array/drain.rs
@@ -0,0 +1,76 @@
+use crate::iter::{TrustedLen, UncheckedIterator};
+use crate::mem::ManuallyDrop;
+use crate::ptr::drop_in_place;
+use crate::slice;
+
+/// A situationally-optimized version of `array.into_iter().for_each(func)`.
+///
+/// [`crate::array::IntoIter`]s are great when you need an owned iterator, but
+/// storing the entire array *inside* the iterator like that can sometimes
+/// pessimize code. Notable, it can be more bytes than you really want to move
+/// around, and because the array accesses index into it SRoA has a harder time
+/// optimizing away the type than it does iterators that just hold a couple pointers.
+///
+/// Thus this function exists, which gives a way to get *moved* access to the
+/// elements of an array using a small iterator -- no bigger than a slice iterator.
+///
+/// The function-taking-a-closure structure makes it safe, as it keeps callers
+/// from looking at already-dropped elements.
+pub(crate) fn drain_array_with<T, R, const N: usize>(
+ array: [T; N],
+ func: impl for<'a> FnOnce(Drain<'a, T>) -> R,
+) -> R {
+ let mut array = ManuallyDrop::new(array);
+ // SAFETY: Now that the local won't drop it, it's ok to construct the `Drain` which will.
+ let drain = Drain(array.iter_mut());
+ func(drain)
+}
+
+/// See [`drain_array_with`] -- this is `pub(crate)` only so it's allowed to be
+/// mentioned in the signature of that method. (Otherwise it hits `E0446`.)
+// INVARIANT: It's ok to drop the remainder of the inner iterator.
+pub(crate) struct Drain<'a, T>(slice::IterMut<'a, T>);
+
+impl<T> Drop for Drain<'_, T> {
+ fn drop(&mut self) {
+ // SAFETY: By the type invariant, we're allowed to drop all these.
+ unsafe { drop_in_place(self.0.as_mut_slice()) }
+ }
+}
+
+impl<T> Iterator for Drain<'_, T> {
+ type Item = T;
+
+ #[inline]
+ fn next(&mut self) -> Option<T> {
+ let p: *const T = self.0.next()?;
+ // SAFETY: The iterator was already advanced, so we won't drop this later.
+ Some(unsafe { p.read() })
+ }
+
+ #[inline]
+ fn size_hint(&self) -> (usize, Option<usize>) {
+ let n = self.len();
+ (n, Some(n))
+ }
+}
+
+impl<T> ExactSizeIterator for Drain<'_, T> {
+ #[inline]
+ fn len(&self) -> usize {
+ self.0.len()
+ }
+}
+
+// SAFETY: This is a 1:1 wrapper for a slice iterator, which is also `TrustedLen`.
+unsafe impl<T> TrustedLen for Drain<'_, T> {}
+
+impl<T> UncheckedIterator for Drain<'_, T> {
+ unsafe fn next_unchecked(&mut self) -> T {
+ // SAFETY: `Drain` is 1:1 with the inner iterator, so if the caller promised
+ // that there's an element left, the inner iterator has one too.
+ let p: *const T = unsafe { self.0.next_unchecked() };
+ // SAFETY: The iterator was already advanced, so we won't drop this later.
+ unsafe { p.read() }
+ }
+}
diff --git a/library/core/src/array/equality.rs b/library/core/src/array/equality.rs
index b2c895f88..d749865f7 100644
--- a/library/core/src/array/equality.rs
+++ b/library/core/src/array/equality.rs
@@ -1,6 +1,5 @@
+use crate::cmp::BytewiseEq;
use crate::convert::TryInto;
-use crate::num::{NonZeroI128, NonZeroI16, NonZeroI32, NonZeroI64, NonZeroI8, NonZeroIsize};
-use crate::num::{NonZeroU128, NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU8, NonZeroUsize};
#[stable(feature = "rust1", since = "1.0.0")]
impl<A, B, const N: usize> PartialEq<[B; N]> for [A; N]
@@ -144,74 +143,14 @@ impl<T: PartialEq<Other>, Other, const N: usize> SpecArrayEq<Other, N> for T {
}
}
-impl<T: IsRawEqComparable<U>, U, const N: usize> SpecArrayEq<U, N> for T {
+impl<T: BytewiseEq<U>, U, const N: usize> SpecArrayEq<U, N> for T {
fn spec_eq(a: &[T; N], b: &[U; N]) -> bool {
- // SAFETY: This is why `IsRawEqComparable` is an `unsafe trait`.
- unsafe {
- let b = &*b.as_ptr().cast::<[T; N]>();
- crate::intrinsics::raw_eq(a, b)
- }
+ // SAFETY: Arrays are compared element-wise, and don't add any padding
+ // between elements, so when the elements are `BytewiseEq`, we can
+ // compare the entire array at once.
+ unsafe { crate::intrinsics::raw_eq(a, crate::mem::transmute(b)) }
}
fn spec_ne(a: &[T; N], b: &[U; N]) -> bool {
!Self::spec_eq(a, b)
}
}
-
-/// `U` exists on here mostly because `min_specialization` didn't let me
-/// repeat the `T` type parameter in the above specialization, so instead
-/// the `T == U` constraint comes from the impls on this.
-/// # Safety
-/// - Neither `Self` nor `U` has any padding.
-/// - `Self` and `U` have the same layout.
-/// - `Self: PartialEq<U>` is byte-wise (this means no floats, among other things)
-#[rustc_specialization_trait]
-unsafe trait IsRawEqComparable<U>: PartialEq<U> {}
-
-macro_rules! is_raw_eq_comparable {
- ($($t:ty),+ $(,)?) => {$(
- unsafe impl IsRawEqComparable<$t> for $t {}
- )+};
-}
-
-// SAFETY: All the ordinary integer types have no padding, and are not pointers.
-is_raw_eq_comparable!(u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize);
-
-// SAFETY: bool and char have *niches*, but no *padding* (and these are not pointer types), so this
-// is sound
-is_raw_eq_comparable!(bool, char);
-
-// SAFETY: Similarly, the non-zero types have a niche, but no undef and no pointers,
-// and they compare like their underlying numeric type.
-is_raw_eq_comparable!(
- NonZeroU8,
- NonZeroU16,
- NonZeroU32,
- NonZeroU64,
- NonZeroU128,
- NonZeroUsize,
- NonZeroI8,
- NonZeroI16,
- NonZeroI32,
- NonZeroI64,
- NonZeroI128,
- NonZeroIsize,
-);
-
-// SAFETY: The NonZero types have the "null" optimization guaranteed, and thus
-// are also safe to equality-compare bitwise inside an `Option`.
-// The way `PartialOrd` is defined for `Option` means that this wouldn't work
-// for `<` or `>` on the signed types, but since we only do `==` it's fine.
-is_raw_eq_comparable!(
- Option<NonZeroU8>,
- Option<NonZeroU16>,
- Option<NonZeroU32>,
- Option<NonZeroU64>,
- Option<NonZeroU128>,
- Option<NonZeroUsize>,
- Option<NonZeroI8>,
- Option<NonZeroI16>,
- Option<NonZeroI32>,
- Option<NonZeroI64>,
- Option<NonZeroI128>,
- Option<NonZeroIsize>,
-);
diff --git a/library/core/src/array/mod.rs b/library/core/src/array/mod.rs
index 2825e0bbb..1643842d6 100644
--- a/library/core/src/array/mod.rs
+++ b/library/core/src/array/mod.rs
@@ -10,16 +10,19 @@ use crate::convert::{Infallible, TryFrom};
use crate::error::Error;
use crate::fmt;
use crate::hash::{self, Hash};
-use crate::iter::TrustedLen;
+use crate::iter::UncheckedIterator;
use crate::mem::{self, MaybeUninit};
use crate::ops::{
ChangeOutputType, ControlFlow, FromResidual, Index, IndexMut, NeverShortCircuit, Residual, Try,
};
use crate::slice::{Iter, IterMut};
+mod drain;
mod equality;
mod iter;
+pub(crate) use drain::drain_array_with;
+
#[stable(feature = "array_value_iter", since = "1.51.0")]
pub use iter::IntoIter;
@@ -52,16 +55,11 @@ pub use iter::IntoIter;
/// ```
#[inline]
#[stable(feature = "array_from_fn", since = "1.63.0")]
-pub fn from_fn<T, const N: usize, F>(mut cb: F) -> [T; N]
+pub fn from_fn<T, const N: usize, F>(cb: F) -> [T; N]
where
F: FnMut(usize) -> T,
{
- let mut idx = 0;
- [(); N].map(|_| {
- let res = cb(idx);
- idx += 1;
- res
- })
+ try_from_fn(NeverShortCircuit::wrap_mut_1(cb)).0
}
/// Creates an array `[T; N]` where each fallible array element `T` is returned by the `cb` call.
@@ -101,9 +99,14 @@ where
R: Try,
R::Residual: Residual<[R::Output; N]>,
{
- // SAFETY: we know for certain that this iterator will yield exactly `N`
- // items.
- unsafe { try_collect_into_array_unchecked(&mut (0..N).map(cb)) }
+ let mut array = MaybeUninit::uninit_array::<N>();
+ match try_from_fn_erased(&mut array, cb) {
+ ControlFlow::Break(r) => FromResidual::from_residual(r),
+ ControlFlow::Continue(()) => {
+ // SAFETY: All elements of the array were populated.
+ try { unsafe { MaybeUninit::array_assume_init(array) } }
+ }
+ }
}
/// Converts a reference to `T` into a reference to an array of length 1 (without copying).
@@ -131,7 +134,8 @@ pub struct TryFromSliceError(());
impl fmt::Display for TryFromSliceError {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- fmt::Display::fmt(self.__description(), f)
+ #[allow(deprecated)]
+ self.description().fmt(f)
}
}
@@ -139,20 +143,6 @@ impl fmt::Display for TryFromSliceError {
impl Error for TryFromSliceError {
#[allow(deprecated)]
fn description(&self) -> &str {
- self.__description()
- }
-}
-
-impl TryFromSliceError {
- #[unstable(
- feature = "array_error_internals",
- reason = "available through Error trait and this method should not \
- be exposed publicly",
- issue = "none"
- )]
- #[inline]
- #[doc(hidden)]
- pub fn __description(&self) -> &str {
"could not convert slice to array"
}
}
@@ -427,9 +417,7 @@ trait SpecArrayClone: Clone {
impl<T: Clone> SpecArrayClone for T {
#[inline]
default fn clone<const N: usize>(array: &[T; N]) -> [T; N] {
- // SAFETY: we know for certain that this iterator will yield exactly `N`
- // items.
- unsafe { collect_into_array_unchecked(&mut array.iter().cloned()) }
+ from_trusted_iterator(array.iter().cloned())
}
}
@@ -513,9 +501,7 @@ impl<T, const N: usize> [T; N] {
where
F: FnMut(T) -> U,
{
- // SAFETY: we know for certain that this iterator will yield exactly `N`
- // items.
- unsafe { collect_into_array_unchecked(&mut IntoIterator::into_iter(self).map(f)) }
+ self.try_map(NeverShortCircuit::wrap_mut_1(f)).0
}
/// A fallible function `f` applied to each element on array `self` in order to
@@ -552,9 +538,7 @@ impl<T, const N: usize> [T; N] {
R: Try,
R::Residual: Residual<[R::Output; N]>,
{
- // SAFETY: we know for certain that this iterator will yield exactly `N`
- // items.
- unsafe { try_collect_into_array_unchecked(&mut IntoIterator::into_iter(self).map(f)) }
+ drain_array_with(self, |iter| try_from_trusted_iterator(iter.map(f)))
}
/// 'Zips up' two arrays into a single array of pairs.
@@ -575,11 +559,9 @@ impl<T, const N: usize> [T; N] {
/// ```
#[unstable(feature = "array_zip", issue = "80094")]
pub fn zip<U>(self, rhs: [U; N]) -> [(T, U); N] {
- let mut iter = IntoIterator::into_iter(self).zip(rhs);
-
- // SAFETY: we know for certain that this iterator will yield exactly `N`
- // items.
- unsafe { collect_into_array_unchecked(&mut iter) }
+ drain_array_with(self, |lhs| {
+ drain_array_with(rhs, |rhs| from_trusted_iterator(crate::iter::zip(lhs, rhs)))
+ })
}
/// Returns a slice containing the entire array. Equivalent to `&s[..]`.
@@ -626,9 +608,7 @@ impl<T, const N: usize> [T; N] {
/// ```
#[unstable(feature = "array_methods", issue = "76118")]
pub fn each_ref(&self) -> [&T; N] {
- // SAFETY: we know for certain that this iterator will yield exactly `N`
- // items.
- unsafe { collect_into_array_unchecked(&mut self.iter()) }
+ from_trusted_iterator(self.iter())
}
/// Borrows each element mutably and returns an array of mutable references
@@ -648,9 +628,7 @@ impl<T, const N: usize> [T; N] {
/// ```
#[unstable(feature = "array_methods", issue = "76118")]
pub fn each_mut(&mut self) -> [&mut T; N] {
- // SAFETY: we know for certain that this iterator will yield exactly `N`
- // items.
- unsafe { collect_into_array_unchecked(&mut self.iter_mut()) }
+ from_trusted_iterator(self.iter_mut())
}
/// Divides one array reference into two at an index.
@@ -810,105 +788,71 @@ impl<T, const N: usize> [T; N] {
}
}
-/// Pulls `N` items from `iter` and returns them as an array. If the iterator
-/// yields fewer than `N` items, this function exhibits undefined behavior.
+/// Populate an array from the first `N` elements of `iter`
///
-/// See [`try_collect_into_array`] for more information.
+/// # Panics
///
+/// If the iterator doesn't actually have enough items.
///
-/// # Safety
-///
-/// It is up to the caller to guarantee that `iter` yields at least `N` items.
-/// Violating this condition causes undefined behavior.
-unsafe fn try_collect_into_array_unchecked<I, T, R, const N: usize>(iter: &mut I) -> R::TryType
-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::Item: Try<Output = T, Residual = R>,
- R: Residual<[T; N]>,
-{
- debug_assert!(N <= iter.size_hint().1.unwrap_or(usize::MAX));
- debug_assert!(N <= iter.size_hint().0);
-
- // SAFETY: covered by the function contract.
- unsafe { try_collect_into_array(iter).unwrap_unchecked() }
+/// By depending on `TrustedLen`, however, we can do that check up-front (where
+/// it easily optimizes away) so it doesn't impact the loop that fills the array.
+#[inline]
+fn from_trusted_iterator<T, const N: usize>(iter: impl UncheckedIterator<Item = T>) -> [T; N] {
+ try_from_trusted_iterator(iter.map(NeverShortCircuit)).0
}
-// Infallible version of `try_collect_into_array_unchecked`.
-unsafe fn collect_into_array_unchecked<I, const N: usize>(iter: &mut I) -> [I::Item; N]
+#[inline]
+fn try_from_trusted_iterator<T, R, const N: usize>(
+ iter: impl UncheckedIterator<Item = R>,
+) -> ChangeOutputType<R, [T; N]>
where
- I: Iterator + TrustedLen,
+ R: Try<Output = T>,
+ R::Residual: Residual<[T; N]>,
{
- let mut map = iter.map(NeverShortCircuit);
-
- // SAFETY: The same safety considerations w.r.t. the iterator length
- // apply for `try_collect_into_array_unchecked` as for
- // `collect_into_array_unchecked`
- match unsafe { try_collect_into_array_unchecked(&mut map) } {
- NeverShortCircuit(array) => array,
+ assert!(iter.size_hint().0 >= N);
+ fn next<T>(mut iter: impl UncheckedIterator<Item = T>) -> impl FnMut(usize) -> T {
+ move |_| {
+ // SAFETY: We know that `from_fn` will call this at most N times,
+ // and we checked to ensure that we have at least that many items.
+ unsafe { iter.next_unchecked() }
+ }
}
+
+ try_from_fn(next(iter))
}
-/// Pulls `N` items from `iter` and returns them as an array. If the iterator
-/// yields fewer than `N` items, `Err` is returned containing an iterator over
-/// the already yielded items.
+/// Version of [`try_from_fn`] using a passed-in slice in order to avoid
+/// needing to monomorphize for every array length.
///
-/// Since the iterator is passed as a mutable reference and this function calls
-/// `next` at most `N` times, the iterator can still be used afterwards to
-/// retrieve the remaining items.
+/// This takes a generator rather than an iterator so that *at the type level*
+/// it never needs to worry about running out of items. When combined with
+/// an infallible `Try` type, that means the loop canonicalizes easily, allowing
+/// it to optimize well.
///
-/// If `iter.next()` panicks, all items already yielded by the iterator are
-/// dropped.
+/// It would be *possible* to unify this and [`iter_next_chunk_erased`] into one
+/// function that does the union of both things, but last time it was that way
+/// it resulted in poor codegen from the "are there enough source items?" checks
+/// not optimizing away. So if you give it a shot, make sure to watch what
+/// happens in the codegen tests.
#[inline]
-fn try_collect_into_array<I, T, R, const N: usize>(
- iter: &mut I,
-) -> Result<R::TryType, IntoIter<T, N>>
+fn try_from_fn_erased<T, R>(
+ buffer: &mut [MaybeUninit<T>],
+ mut generator: impl FnMut(usize) -> R,
+) -> ControlFlow<R::Residual>
where
- I: Iterator,
- I::Item: Try<Output = T, Residual = R>,
- R: Residual<[T; N]>,
+ R: Try<Output = T>,
{
- if N == 0 {
- // SAFETY: An empty array is always inhabited and has no validity invariants.
- return Ok(Try::from_output(unsafe { mem::zeroed() }));
- }
+ let mut guard = Guard { array_mut: buffer, initialized: 0 };
- let mut array = MaybeUninit::uninit_array::<N>();
- let mut guard = Guard { array_mut: &mut array, initialized: 0 };
-
- for _ in 0..N {
- match iter.next() {
- Some(item_rslt) => {
- let item = match item_rslt.branch() {
- ControlFlow::Break(r) => {
- return Ok(FromResidual::from_residual(r));
- }
- ControlFlow::Continue(elem) => elem,
- };
-
- // SAFETY: `guard.initialized` starts at 0, which means push can be called
- // at most N times, which this loop does.
- unsafe {
- guard.push_unchecked(item);
- }
- }
- None => {
- let alive = 0..guard.initialized;
- mem::forget(guard);
- // SAFETY: `array` was initialized with exactly `initialized`
- // number of elements.
- return Err(unsafe { IntoIter::new_unchecked(array, alive) });
- }
- }
+ while guard.initialized < guard.array_mut.len() {
+ let item = generator(guard.initialized).branch()?;
+
+ // SAFETY: The loop condition ensures we have space to push the item
+ unsafe { guard.push_unchecked(item) };
}
mem::forget(guard);
- // SAFETY: All elements of the array were populated in the loop above.
- let output = unsafe { array.transpose().assume_init() };
- Ok(Try::from_output(output))
+ ControlFlow::Continue(())
}
/// Panic guard for incremental initialization of arrays.
@@ -922,14 +866,14 @@ where
///
/// To minimize indirection fields are still pub but callers should at least use
/// `push_unchecked` to signal that something unsafe is going on.
-pub(crate) struct Guard<'a, T, const N: usize> {
+struct Guard<'a, T> {
/// The array to be initialized.
- pub array_mut: &'a mut [MaybeUninit<T>; N],
+ pub array_mut: &'a mut [MaybeUninit<T>],
/// The number of items that have been initialized so far.
pub initialized: usize,
}
-impl<T, const N: usize> Guard<'_, T, N> {
+impl<T> Guard<'_, T> {
/// Adds an item to the array and updates the initialized item counter.
///
/// # Safety
@@ -947,28 +891,73 @@ impl<T, const N: usize> Guard<'_, T, N> {
}
}
-impl<T, const N: usize> Drop for Guard<'_, T, N> {
+impl<T> Drop for Guard<'_, T> {
fn drop(&mut self) {
- debug_assert!(self.initialized <= N);
+ debug_assert!(self.initialized <= self.array_mut.len());
// SAFETY: this slice will contain only initialized objects.
unsafe {
crate::ptr::drop_in_place(MaybeUninit::slice_assume_init_mut(
- &mut self.array_mut.get_unchecked_mut(..self.initialized),
+ self.array_mut.get_unchecked_mut(..self.initialized),
));
}
}
}
-/// Returns the next chunk of `N` items from the iterator or errors with an
-/// iterator over the remainder. Used for `Iterator::next_chunk`.
+/// Pulls `N` items from `iter` and returns them as an array. If the iterator
+/// yields fewer than `N` items, `Err` is returned containing an iterator over
+/// the already yielded items.
+///
+/// Since the iterator is passed as a mutable reference and this function calls
+/// `next` at most `N` times, the iterator can still be used afterwards to
+/// retrieve the remaining items.
+///
+/// If `iter.next()` panicks, all items already yielded by the iterator are
+/// dropped.
+///
+/// Used for [`Iterator::next_chunk`].
+#[inline]
+pub(crate) fn iter_next_chunk<T, const N: usize>(
+ iter: &mut impl Iterator<Item = T>,
+) -> Result<[T; N], IntoIter<T, N>> {
+ let mut array = MaybeUninit::uninit_array::<N>();
+ let r = iter_next_chunk_erased(&mut array, iter);
+ match r {
+ Ok(()) => {
+ // SAFETY: All elements of `array` were populated.
+ Ok(unsafe { MaybeUninit::array_assume_init(array) })
+ }
+ Err(initialized) => {
+ // SAFETY: Only the first `initialized` elements were populated
+ Err(unsafe { IntoIter::new_unchecked(array, 0..initialized) })
+ }
+ }
+}
+
+/// Version of [`iter_next_chunk`] using a passed-in slice in order to avoid
+/// needing to monomorphize for every array length.
+///
+/// Unfortunately this loop has two exit conditions, the buffer filling up
+/// or the iterator running out of items, making it tend to optimize poorly.
#[inline]
-pub(crate) fn iter_next_chunk<I, const N: usize>(
- iter: &mut I,
-) -> Result<[I::Item; N], IntoIter<I::Item, N>>
-where
- I: Iterator,
-{
- let mut map = iter.map(NeverShortCircuit);
- try_collect_into_array(&mut map).map(|NeverShortCircuit(arr)| arr)
+fn iter_next_chunk_erased<T>(
+ buffer: &mut [MaybeUninit<T>],
+ iter: &mut impl Iterator<Item = T>,
+) -> Result<(), usize> {
+ let mut guard = Guard { array_mut: buffer, initialized: 0 };
+ while guard.initialized < guard.array_mut.len() {
+ let Some(item) = iter.next() else {
+ // Unlike `try_from_fn_erased`, we want to keep the partial results,
+ // so we need to defuse the guard instead of using `?`.
+ let initialized = guard.initialized;
+ mem::forget(guard);
+ return Err(initialized)
+ };
+
+ // SAFETY: The loop condition ensures we have space to push the item
+ unsafe { guard.push_unchecked(item) };
+ }
+
+ mem::forget(guard);
+ Ok(())
}
diff --git a/library/core/src/cell.rs b/library/core/src/cell.rs
index 129213fde..897d03595 100644
--- a/library/core/src/cell.rs
+++ b/library/core/src/cell.rs
@@ -196,7 +196,7 @@ use crate::cmp::Ordering;
use crate::fmt::{self, Debug, Display};
use crate::marker::{PhantomData, Unsize};
use crate::mem;
-use crate::ops::{CoerceUnsized, Deref, DerefMut};
+use crate::ops::{CoerceUnsized, Deref, DerefMut, DispatchFromDyn};
use crate::ptr::{self, NonNull};
mod lazy;
@@ -571,6 +571,16 @@ impl<T: Default> Cell<T> {
#[unstable(feature = "coerce_unsized", issue = "18598")]
impl<T: CoerceUnsized<U>, U> CoerceUnsized<Cell<U>> for Cell<T> {}
+// Allow types that wrap `Cell` to also implement `DispatchFromDyn`
+// and become object safe method receivers.
+// Note that currently `Cell` itself cannot be a method receiver
+// because it does not implement Deref.
+// In other words:
+// `self: Cell<&Self>` won't work
+// `self: CellWrapper<Self>` becomes possible
+#[unstable(feature = "dispatch_from_dyn", issue = "none")]
+impl<T: DispatchFromDyn<U>, U> DispatchFromDyn<Cell<U>> for Cell<T> {}
+
impl<T> Cell<[T]> {
/// Returns a `&[Cell<T>]` from a `&Cell<[T]>`
///
@@ -622,7 +632,7 @@ pub struct RefCell<T: ?Sized> {
// Stores the location of the earliest currently active borrow.
// This gets updated whenever we go from having zero borrows
// to having a single borrow. When a borrow occurs, this gets included
- // in the generated `BorrowError/`BorrowMutError`
+ // in the generated `BorrowError`/`BorrowMutError`
#[cfg(feature = "debug_refcell")]
borrowed_at: Cell<Option<&'static crate::panic::Location<'static>>>,
value: UnsafeCell<T>,
@@ -2078,6 +2088,16 @@ impl<T> const From<T> for UnsafeCell<T> {
#[unstable(feature = "coerce_unsized", issue = "18598")]
impl<T: CoerceUnsized<U>, U> CoerceUnsized<UnsafeCell<U>> for UnsafeCell<T> {}
+// Allow types that wrap `UnsafeCell` to also implement `DispatchFromDyn`
+// and become object safe method receivers.
+// Note that currently `UnsafeCell` itself cannot be a method receiver
+// because it does not implement Deref.
+// In other words:
+// `self: UnsafeCell<&Self>` won't work
+// `self: UnsafeCellWrapper<Self>` becomes possible
+#[unstable(feature = "dispatch_from_dyn", issue = "none")]
+impl<T: DispatchFromDyn<U>, U> DispatchFromDyn<UnsafeCell<U>> for UnsafeCell<T> {}
+
/// [`UnsafeCell`], but [`Sync`].
///
/// This is just an `UnsafeCell`, except it implements `Sync`
@@ -2169,6 +2189,17 @@ impl<T> const From<T> for SyncUnsafeCell<T> {
//#[unstable(feature = "sync_unsafe_cell", issue = "95439")]
impl<T: CoerceUnsized<U>, U> CoerceUnsized<SyncUnsafeCell<U>> for SyncUnsafeCell<T> {}
+// Allow types that wrap `SyncUnsafeCell` to also implement `DispatchFromDyn`
+// and become object safe method receivers.
+// Note that currently `SyncUnsafeCell` itself cannot be a method receiver
+// because it does not implement Deref.
+// In other words:
+// `self: SyncUnsafeCell<&Self>` won't work
+// `self: SyncUnsafeCellWrapper<Self>` becomes possible
+#[unstable(feature = "dispatch_from_dyn", issue = "none")]
+//#[unstable(feature = "sync_unsafe_cell", issue = "95439")]
+impl<T: DispatchFromDyn<U>, U> DispatchFromDyn<SyncUnsafeCell<U>> for SyncUnsafeCell<T> {}
+
#[allow(unused)]
fn assert_coerce_unsized(
a: UnsafeCell<&i32>,
diff --git a/library/core/src/cell/once.rs b/library/core/src/cell/once.rs
index 7757068a4..f74e563f1 100644
--- a/library/core/src/cell/once.rs
+++ b/library/core/src/cell/once.rs
@@ -298,3 +298,7 @@ impl<T> const From<T> for OnceCell<T> {
OnceCell { inner: UnsafeCell::new(Some(value)) }
}
}
+
+// Just like for `Cell<T>` this isn't needed, but results in nicer error messages.
+#[unstable(feature = "once_cell", issue = "74465")]
+impl<T> !Sync for OnceCell<T> {}
diff --git a/library/core/src/char/convert.rs b/library/core/src/char/convert.rs
index f1a51a550..136bbcb8b 100644
--- a/library/core/src/char/convert.rs
+++ b/library/core/src/char/convert.rs
@@ -2,6 +2,7 @@
use crate::char::TryFromCharError;
use crate::convert::TryFrom;
+use crate::error::Error;
use crate::fmt;
use crate::mem::transmute;
use crate::str::FromStr;
@@ -150,14 +151,16 @@ pub struct ParseCharError {
kind: CharErrorKind,
}
-impl ParseCharError {
- #[unstable(
- feature = "char_error_internals",
- reason = "this method should not be available publicly",
- issue = "none"
- )]
- #[doc(hidden)]
- pub fn __description(&self) -> &str {
+#[derive(Copy, Clone, Debug, PartialEq, Eq)]
+enum CharErrorKind {
+ EmptyString,
+ TooManyChars,
+}
+
+#[stable(feature = "char_from_str", since = "1.20.0")]
+impl Error for ParseCharError {
+ #[allow(deprecated)]
+ fn description(&self) -> &str {
match self.kind {
CharErrorKind::EmptyString => "cannot parse char from empty string",
CharErrorKind::TooManyChars => "too many characters in string",
@@ -165,16 +168,11 @@ impl ParseCharError {
}
}
-#[derive(Copy, Clone, Debug, PartialEq, Eq)]
-enum CharErrorKind {
- EmptyString,
- TooManyChars,
-}
-
#[stable(feature = "char_from_str", since = "1.20.0")]
impl fmt::Display for ParseCharError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- self.__description().fmt(f)
+ #[allow(deprecated)]
+ self.description().fmt(f)
}
}
diff --git a/library/core/src/char/decode.rs b/library/core/src/char/decode.rs
index eeb088030..dbfe251f2 100644
--- a/library/core/src/char/decode.rs
+++ b/library/core/src/char/decode.rs
@@ -3,8 +3,6 @@
use crate::error::Error;
use crate::fmt;
-use super::from_u32_unchecked;
-
/// An iterator that decodes UTF-16 encoded code points from an iterator of `u16`s.
///
/// This `struct` is created by the [`decode_utf16`] method on [`char`]. See its
@@ -49,7 +47,7 @@ impl<I: Iterator<Item = u16>> Iterator for DecodeUtf16<I> {
if !u.is_utf16_surrogate() {
// SAFETY: not a surrogate
- Some(Ok(unsafe { from_u32_unchecked(u as u32) }))
+ Some(Ok(unsafe { char::from_u32_unchecked(u as u32) }))
} else if u >= 0xDC00 {
// a trailing surrogate
Some(Err(DecodeUtf16Error { code: u }))
@@ -69,7 +67,7 @@ impl<I: Iterator<Item = u16>> Iterator for DecodeUtf16<I> {
// all ok, so lets decode it.
let c = (((u & 0x3ff) as u32) << 10 | (u2 & 0x3ff) as u32) + 0x1_0000;
// SAFETY: we checked that it's a legal unicode value
- Some(Ok(unsafe { from_u32_unchecked(c) }))
+ Some(Ok(unsafe { char::from_u32_unchecked(c) }))
}
}
diff --git a/library/core/src/char/methods.rs b/library/core/src/char/methods.rs
index 3e7383b4c..9bc97ea0b 100644
--- a/library/core/src/char/methods.rs
+++ b/library/core/src/char/methods.rs
@@ -53,15 +53,13 @@ impl char {
/// Basic usage:
///
/// ```
- /// use std::char::decode_utf16;
- ///
/// // 𝄞mus<invalid>ic<invalid>
/// let v = [
/// 0xD834, 0xDD1E, 0x006d, 0x0075, 0x0073, 0xDD1E, 0x0069, 0x0063, 0xD834,
/// ];
///
/// assert_eq!(
- /// decode_utf16(v)
+ /// char::decode_utf16(v)
/// .map(|r| r.map_err(|e| e.unpaired_surrogate()))
/// .collect::<Vec<_>>(),
/// vec![
@@ -77,16 +75,14 @@ impl char {
/// A lossy decoder can be obtained by replacing `Err` results with the replacement character:
///
/// ```
- /// use std::char::{decode_utf16, REPLACEMENT_CHARACTER};
- ///
/// // 𝄞mus<invalid>ic<invalid>
/// let v = [
/// 0xD834, 0xDD1E, 0x006d, 0x0075, 0x0073, 0xDD1E, 0x0069, 0x0063, 0xD834,
/// ];
///
/// assert_eq!(
- /// decode_utf16(v)
- /// .map(|r| r.unwrap_or(REPLACEMENT_CHARACTER))
+ /// char::decode_utf16(v)
+ /// .map(|r| r.unwrap_or(char::REPLACEMENT_CHARACTER))
/// .collect::<String>(),
/// "𝄞mus�ic�"
/// );
@@ -123,8 +119,6 @@ impl char {
/// Basic usage:
///
/// ```
- /// use std::char;
- ///
/// let c = char::from_u32(0x2764);
///
/// assert_eq!(Some('❤'), c);
@@ -133,8 +127,6 @@ impl char {
/// Returning `None` when the input is not a valid `char`:
///
/// ```
- /// use std::char;
- ///
/// let c = char::from_u32(0x110000);
///
/// assert_eq!(None, c);
@@ -176,8 +168,6 @@ impl char {
/// Basic usage:
///
/// ```
- /// use std::char;
- ///
/// let c = unsafe { char::from_u32_unchecked(0x2764) };
///
/// assert_eq!('❤', c);
@@ -210,8 +200,6 @@ impl char {
/// Basic usage:
///
/// ```
- /// use std::char;
- ///
/// let c = char::from_digit(4, 10);
///
/// assert_eq!(Some('4'), c);
@@ -225,8 +213,6 @@ impl char {
/// Returning `None` when the input is not a digit:
///
/// ```
- /// use std::char;
- ///
/// let c = char::from_digit(20, 10);
///
/// assert_eq!(None, c);
@@ -235,8 +221,6 @@ impl char {
/// Passing a large radix, causing a panic:
///
/// ```should_panic
- /// use std::char;
- ///
/// // this panics
/// let _c = char::from_digit(1, 37);
/// ```
@@ -1786,7 +1770,7 @@ pub fn encode_utf16_raw(mut code: u32, dst: &mut [u16]) -> &mut [u16] {
} else {
panic!(
"encode_utf16: need {} units to encode U+{:X}, but the buffer has {}",
- from_u32_unchecked(code).len_utf16(),
+ char::from_u32_unchecked(code).len_utf16(),
code,
dst.len(),
)
diff --git a/library/core/src/char/mod.rs b/library/core/src/char/mod.rs
index af98059cf..8ec78e887 100644
--- a/library/core/src/char/mod.rs
+++ b/library/core/src/char/mod.rs
@@ -189,7 +189,7 @@ impl Iterator for EscapeUnicode {
}
EscapeUnicodeState::Value => {
let hex_digit = ((self.c as u32) >> (self.hex_digit_idx * 4)) & 0xf;
- let c = from_digit(hex_digit, 16).unwrap();
+ let c = char::from_digit(hex_digit, 16).unwrap();
if self.hex_digit_idx == 0 {
self.state = EscapeUnicodeState::RightBrace;
} else {
diff --git a/library/core/src/cmp.rs b/library/core/src/cmp.rs
index a7d6fec7d..068637d1a 100644
--- a/library/core/src/cmp.rs
+++ b/library/core/src/cmp.rs
@@ -22,7 +22,9 @@
#![stable(feature = "rust1", since = "1.0.0")]
-use crate::const_closure::ConstFnMutClosure;
+mod bytewise;
+pub(crate) use bytewise::BytewiseEq;
+
use crate::marker::Destruct;
use self::Ordering::*;
@@ -798,12 +800,6 @@ pub trait Ord: Eq + PartialOrd<Self> {
Self: Sized,
Self: ~const Destruct,
{
- #[cfg(not(bootstrap))]
- {
- max_by(self, other, Ord::cmp)
- }
-
- #[cfg(bootstrap)]
match self.cmp(&other) {
Ordering::Less | Ordering::Equal => other,
Ordering::Greater => self,
@@ -828,12 +824,6 @@ pub trait Ord: Eq + PartialOrd<Self> {
Self: Sized,
Self: ~const Destruct,
{
- #[cfg(not(bootstrap))]
- {
- min_by(self, other, Ord::cmp)
- }
-
- #[cfg(bootstrap)]
match self.cmp(&other) {
Ordering::Less | Ordering::Equal => self,
Ordering::Greater => other,
@@ -1200,12 +1190,7 @@ pub const fn min<T: ~const Ord + ~const Destruct>(v1: T, v2: T) -> T {
#[inline]
#[must_use]
#[stable(feature = "cmp_min_max_by", since = "1.53.0")]
-#[rustc_const_unstable(feature = "const_cmp", issue = "92391")]
-pub const fn min_by<T, F: ~const FnOnce(&T, &T) -> Ordering>(v1: T, v2: T, compare: F) -> T
-where
- T: ~const Destruct,
- F: ~const Destruct,
-{
+pub fn min_by<T, F: FnOnce(&T, &T) -> Ordering>(v1: T, v2: T, compare: F) -> T {
match compare(&v1, &v2) {
Ordering::Less | Ordering::Equal => v1,
Ordering::Greater => v2,
@@ -1227,30 +1212,8 @@ where
#[inline]
#[must_use]
#[stable(feature = "cmp_min_max_by", since = "1.53.0")]
-#[rustc_const_unstable(feature = "const_cmp", issue = "92391")]
-pub const fn min_by_key<T, F: ~const FnMut(&T) -> K, K: ~const Ord>(v1: T, v2: T, mut f: F) -> T
-where
- T: ~const Destruct,
- F: ~const Destruct,
- K: ~const Destruct,
-{
- cfg_if! {
- if #[cfg(bootstrap)] {
- const fn imp<T, F: ~const FnMut(&T) -> K, K: ~const Ord>(
- f: &mut F,
- (v1, v2): (&T, &T),
- ) -> Ordering
- where
- T: ~const Destruct,
- K: ~const Destruct,
- {
- f(v1).cmp(&f(v2))
- }
- min_by(v1, v2, ConstFnMutClosure::new(&mut f, imp))
- } else {
- min_by(v1, v2, const |v1, v2| f(v1).cmp(&f(v2)))
- }
- }
+pub fn min_by_key<T, F: FnMut(&T) -> K, K: Ord>(v1: T, v2: T, mut f: F) -> T {
+ min_by(v1, v2, |v1, v2| f(v1).cmp(&f(v2)))
}
/// Compares and returns the maximum of two values.
@@ -1291,12 +1254,7 @@ pub const fn max<T: ~const Ord + ~const Destruct>(v1: T, v2: T) -> T {
#[inline]
#[must_use]
#[stable(feature = "cmp_min_max_by", since = "1.53.0")]
-#[rustc_const_unstable(feature = "const_cmp", issue = "92391")]
-pub const fn max_by<T, F: ~const FnOnce(&T, &T) -> Ordering>(v1: T, v2: T, compare: F) -> T
-where
- T: ~const Destruct,
- F: ~const Destruct,
-{
+pub fn max_by<T, F: FnOnce(&T, &T) -> Ordering>(v1: T, v2: T, compare: F) -> T {
match compare(&v1, &v2) {
Ordering::Less | Ordering::Equal => v2,
Ordering::Greater => v1,
@@ -1318,24 +1276,8 @@ where
#[inline]
#[must_use]
#[stable(feature = "cmp_min_max_by", since = "1.53.0")]
-#[rustc_const_unstable(feature = "const_cmp", issue = "92391")]
-pub const fn max_by_key<T, F: ~const FnMut(&T) -> K, K: ~const Ord>(v1: T, v2: T, mut f: F) -> T
-where
- T: ~const Destruct,
- F: ~const Destruct,
- K: ~const Destruct,
-{
- const fn imp<T, F: ~const FnMut(&T) -> K, K: ~const Ord>(
- f: &mut F,
- (v1, v2): (&T, &T),
- ) -> Ordering
- where
- T: ~const Destruct,
- K: ~const Destruct,
- {
- f(v1).cmp(&f(v2))
- }
- max_by(v1, v2, ConstFnMutClosure::new(&mut f, imp))
+pub fn max_by_key<T, F: FnMut(&T) -> K, K: Ord>(v1: T, v2: T, mut f: F) -> T {
+ max_by(v1, v2, |v1, v2| f(v1).cmp(&f(v2)))
}
// Implementation of PartialEq, Eq, PartialOrd and Ord for primitive types
@@ -1536,9 +1478,10 @@ mod impls {
}
}
#[stable(feature = "rust1", since = "1.0.0")]
- impl<A: ?Sized, B: ?Sized> PartialOrd<&B> for &A
+ #[rustc_const_unstable(feature = "const_cmp", issue = "92391")]
+ impl<A: ?Sized, B: ?Sized> const PartialOrd<&B> for &A
where
- A: PartialOrd<B>,
+ A: ~const PartialOrd<B>,
{
#[inline]
fn partial_cmp(&self, other: &&B) -> Option<Ordering> {
diff --git a/library/core/src/cmp/bytewise.rs b/library/core/src/cmp/bytewise.rs
new file mode 100644
index 000000000..2548d9e24
--- /dev/null
+++ b/library/core/src/cmp/bytewise.rs
@@ -0,0 +1,83 @@
+use crate::num::{NonZeroI128, NonZeroI16, NonZeroI32, NonZeroI64, NonZeroI8, NonZeroIsize};
+use crate::num::{NonZeroU128, NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU8, NonZeroUsize};
+
+/// Types where `==` & `!=` are equivalent to comparing their underlying bytes.
+///
+/// Importantly, this means no floating-point types, as those have different
+/// byte representations (like `-0` and `+0`) which compare as the same.
+/// Since byte arrays are `Eq`, that implies that these types are probably also
+/// `Eq`, but that's not technically required to use this trait.
+///
+/// `Rhs` is *de facto* always `Self`, but the separate parameter is important
+/// to avoid the `specializing impl repeats parameter` error when consuming this.
+///
+/// # Safety
+///
+/// - `Self` and `Rhs` have no padding.
+/// - `Self` and `Rhs` have the same layout (size and alignment).
+/// - Neither `Self` nor `Rhs` have provenance, so integer comparisons are correct.
+/// - `<Self as PartialEq<Rhs>>::{eq,ne}` are equivalent to comparing the bytes.
+#[rustc_specialization_trait]
+pub(crate) unsafe trait BytewiseEq<Rhs = Self>: PartialEq<Rhs> + Sized {}
+
+macro_rules! is_bytewise_comparable {
+ ($($t:ty),+ $(,)?) => {$(
+ unsafe impl BytewiseEq for $t {}
+ )+};
+}
+
+// SAFETY: All the ordinary integer types have no padding, and are not pointers.
+is_bytewise_comparable!(u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize);
+
+// SAFETY: These have *niches*, but no *padding* and no *provenance*,
+// so we can compare them directly.
+is_bytewise_comparable!(bool, char, super::Ordering);
+
+// SAFETY: Similarly, the non-zero types have a niche, but no undef and no pointers,
+// and they compare like their underlying numeric type.
+is_bytewise_comparable!(
+ NonZeroU8,
+ NonZeroU16,
+ NonZeroU32,
+ NonZeroU64,
+ NonZeroU128,
+ NonZeroUsize,
+ NonZeroI8,
+ NonZeroI16,
+ NonZeroI32,
+ NonZeroI64,
+ NonZeroI128,
+ NonZeroIsize,
+);
+
+// SAFETY: The NonZero types have the "null" optimization guaranteed, and thus
+// are also safe to equality-compare bitwise inside an `Option`.
+// The way `PartialOrd` is defined for `Option` means that this wouldn't work
+// for `<` or `>` on the signed types, but since we only do `==` it's fine.
+is_bytewise_comparable!(
+ Option<NonZeroU8>,
+ Option<NonZeroU16>,
+ Option<NonZeroU32>,
+ Option<NonZeroU64>,
+ Option<NonZeroU128>,
+ Option<NonZeroUsize>,
+ Option<NonZeroI8>,
+ Option<NonZeroI16>,
+ Option<NonZeroI32>,
+ Option<NonZeroI64>,
+ Option<NonZeroI128>,
+ Option<NonZeroIsize>,
+);
+
+macro_rules! is_bytewise_comparable_array_length {
+ ($($n:literal),+ $(,)?) => {$(
+ // SAFETY: Arrays have no padding between elements, so if the elements are
+ // `BytewiseEq`, then the whole array can be too.
+ unsafe impl<T: BytewiseEq<U>, U> BytewiseEq<[U; $n]> for [T; $n] {}
+ )+};
+}
+
+// Frustratingly, this can't be made const-generic as it gets
+// error: specializing impl repeats parameter `N`
+// so just do it for a couple of plausibly-common ones.
+is_bytewise_comparable_array_length!(0, 1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64);
diff --git a/library/core/src/const_closure.rs b/library/core/src/const_closure.rs
deleted file mode 100644
index 97900a486..000000000
--- a/library/core/src/const_closure.rs
+++ /dev/null
@@ -1,78 +0,0 @@
-use crate::marker::Destruct;
-use crate::marker::Tuple;
-
-/// Struct representing a closure with mutably borrowed data.
-///
-/// Example:
-/// ```no_build
-/// #![feature(const_mut_refs)]
-/// use crate::const_closure::ConstFnMutClosure;
-/// const fn imp(state: &mut i32, (arg,): (i32,)) -> i32 {
-/// *state += arg;
-/// *state
-/// }
-/// let mut i = 5;
-/// let mut cl = ConstFnMutClosure::new(&mut i, imp);
-///
-/// assert!(7 == cl(2));
-/// assert!(8 == cl(1));
-/// ```
-pub(crate) struct ConstFnMutClosure<CapturedData, Function> {
- /// The Data captured by the Closure.
- /// Must be either a (mutable) reference or a tuple of (mutable) references.
- pub data: CapturedData,
- /// The Function of the Closure, must be: Fn(CapturedData, ClosureArgs) -> ClosureReturn
- pub func: Function,
-}
-impl<'a, CapturedData: ?Sized, Function> ConstFnMutClosure<&'a mut CapturedData, Function> {
- /// Function for creating a new closure.
- ///
- /// `data` is the a mutable borrow of data that is captured from the environment.
- /// If you want Data to be a tuple of mutable Borrows, the struct must be constructed manually.
- ///
- /// `func` is the function of the closure, it gets the data and a tuple of the arguments closure
- /// and return the return value of the closure.
- pub(crate) const fn new<ClosureArguments, ClosureReturnValue>(
- data: &'a mut CapturedData,
- func: Function,
- ) -> Self
- where
- Function: ~const Fn(&mut CapturedData, ClosureArguments) -> ClosureReturnValue,
- {
- Self { data, func }
- }
-}
-
-macro_rules! impl_fn_mut_tuple {
- ($($var:ident)*) => {
- #[allow(unused_parens)]
- impl<'a, $($var,)* ClosureArguments: Tuple, Function, ClosureReturnValue> const
- FnOnce<ClosureArguments> for ConstFnMutClosure<($(&'a mut $var),*), Function>
- where
- Function: ~const Fn(($(&mut $var),*), ClosureArguments) -> ClosureReturnValue+ ~const Destruct,
- {
- type Output = ClosureReturnValue;
-
- extern "rust-call" fn call_once(mut self, args: ClosureArguments) -> Self::Output {
- self.call_mut(args)
- }
- }
- #[allow(unused_parens)]
- impl<'a, $($var,)* ClosureArguments: Tuple, Function, ClosureReturnValue> const
- FnMut<ClosureArguments> for ConstFnMutClosure<($(&'a mut $var),*), Function>
- where
- Function: ~const Fn(($(&mut $var),*), ClosureArguments)-> ClosureReturnValue,
- {
- extern "rust-call" fn call_mut(&mut self, args: ClosureArguments) -> Self::Output {
- #[allow(non_snake_case)]
- let ($($var),*) = &mut self.data;
- (self.func)(($($var),*), args)
- }
- }
- };
-}
-impl_fn_mut_tuple!(A);
-impl_fn_mut_tuple!(A B);
-impl_fn_mut_tuple!(A B C);
-impl_fn_mut_tuple!(A B C D);
-impl_fn_mut_tuple!(A B C D E);
diff --git a/library/core/src/convert/mod.rs b/library/core/src/convert/mod.rs
index f95b880df..805354be0 100644
--- a/library/core/src/convert/mod.rs
+++ b/library/core/src/convert/mod.rs
@@ -542,7 +542,7 @@ pub trait Into<T>: Sized {
#[const_trait]
pub trait From<T>: Sized {
/// Converts to this type from the input type.
- #[lang = "from"]
+ #[rustc_diagnostic_item = "from_fn"]
#[must_use]
#[stable(feature = "rust1", since = "1.0.0")]
fn from(value: T) -> Self;
diff --git a/library/core/src/error.rs b/library/core/src/error.rs
index 7152300ab..d4103183c 100644
--- a/library/core/src/error.rs
+++ b/library/core/src/error.rs
@@ -28,6 +28,7 @@ use crate::fmt::{Debug, Display};
#[stable(feature = "rust1", since = "1.0.0")]
#[cfg_attr(not(test), rustc_diagnostic_item = "Error")]
#[rustc_has_incoherent_inherent_impls]
+#[cfg_attr(not(bootstrap), allow(multiple_supertrait_upcastable))]
pub trait Error: Debug + Display {
/// The lower-level source of this error, if any.
///
@@ -485,26 +486,10 @@ impl Error for crate::char::CharTryFromError {
}
}
-#[stable(feature = "char_from_str", since = "1.20.0")]
-impl Error for crate::char::ParseCharError {
- #[allow(deprecated)]
- fn description(&self) -> &str {
- self.__description()
- }
-}
-
#[stable(feature = "duration_checked_float", since = "1.66.0")]
impl Error for crate::time::TryFromFloatSecsError {}
-#[stable(feature = "frombyteswithnulerror_impls", since = "1.17.0")]
-impl Error for crate::ffi::FromBytesWithNulError {
- #[allow(deprecated)]
- fn description(&self) -> &str {
- self.__description()
- }
-}
-
-#[unstable(feature = "cstr_from_bytes_until_nul", issue = "95027")]
+#[stable(feature = "cstr_from_bytes_until_nul", since = "1.69.0")]
impl Error for crate::ffi::FromBytesUntilNulError {}
#[unstable(feature = "get_many_mut", issue = "104642")]
diff --git a/library/core/src/ffi/c_str.rs b/library/core/src/ffi/c_str.rs
index 15dd9ea7e..fe8abdf7f 100644
--- a/library/core/src/ffi/c_str.rs
+++ b/library/core/src/ffi/c_str.rs
@@ -1,4 +1,5 @@
use crate::cmp::Ordering;
+use crate::error::Error;
use crate::ffi::c_char;
use crate::fmt;
use crate::intrinsics;
@@ -129,10 +130,12 @@ impl FromBytesWithNulError {
const fn not_nul_terminated() -> FromBytesWithNulError {
FromBytesWithNulError { kind: FromBytesWithNulErrorKind::NotNulTerminated }
}
+}
- #[doc(hidden)]
- #[unstable(feature = "cstr_internals", issue = "none")]
- pub fn __description(&self) -> &str {
+#[stable(feature = "frombyteswithnulerror_impls", since = "1.17.0")]
+impl Error for FromBytesWithNulError {
+ #[allow(deprecated)]
+ fn description(&self) -> &str {
match self.kind {
FromBytesWithNulErrorKind::InteriorNul(..) => {
"data provided contains an interior nul byte"
@@ -150,10 +153,10 @@ impl FromBytesWithNulError {
/// This error is created by the [`CStr::from_bytes_until_nul`] method.
///
#[derive(Clone, PartialEq, Eq, Debug)]
-#[unstable(feature = "cstr_from_bytes_until_nul", issue = "95027")]
+#[stable(feature = "cstr_from_bytes_until_nul", since = "1.69.0")]
pub struct FromBytesUntilNulError(());
-#[unstable(feature = "cstr_from_bytes_until_nul", issue = "95027")]
+#[stable(feature = "cstr_from_bytes_until_nul", since = "1.69.0")]
impl fmt::Display for FromBytesUntilNulError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "data provided does not contain a nul")
@@ -180,7 +183,7 @@ impl Default for &CStr {
impl fmt::Display for FromBytesWithNulError {
#[allow(deprecated, deprecated_in_future)]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- f.write_str(self.__description())?;
+ f.write_str(self.description())?;
if let FromBytesWithNulErrorKind::InteriorNul(pos) = self.kind {
write!(f, " at byte pos {pos}")?;
}
@@ -306,8 +309,6 @@ impl CStr {
///
/// # Examples
/// ```
- /// #![feature(cstr_from_bytes_until_nul)]
- ///
/// use std::ffi::CStr;
///
/// let mut buffer = [0u8; 16];
@@ -322,8 +323,9 @@ impl CStr {
/// assert_eq!(c_str.to_str().unwrap(), "AAAAAAAA");
/// ```
///
- #[unstable(feature = "cstr_from_bytes_until_nul", issue = "95027")]
- #[rustc_const_unstable(feature = "cstr_from_bytes_until_nul", issue = "95027")]
+ #[rustc_allow_const_fn_unstable(const_slice_index)]
+ #[stable(feature = "cstr_from_bytes_until_nul", since = "1.69.0")]
+ #[rustc_const_stable(feature = "cstr_from_bytes_until_nul", since = "1.69.0")]
pub const fn from_bytes_until_nul(bytes: &[u8]) -> Result<&CStr, FromBytesUntilNulError> {
let nul_pos = memchr::memchr(0, bytes);
match nul_pos {
@@ -455,6 +457,10 @@ impl CStr {
/// to a contiguous region of memory terminated with a 0 byte to represent
/// the end of the string.
///
+ /// The type of the returned pointer is
+ /// [`*const c_char`][crate::ffi::c_char], and whether it's
+ /// an alias for `*const i8` or `*const u8` is platform-specific.
+ ///
/// **WARNING**
///
/// The returned pointer is read-only; writing to it (including passing it
@@ -468,6 +474,7 @@ impl CStr {
/// # #![allow(unused_must_use)] #![allow(temporary_cstring_as_ptr)]
/// use std::ffi::CString;
///
+ /// // Do not do this:
/// let ptr = CString::new("Hello").expect("CString::new failed").as_ptr();
/// unsafe {
/// // `ptr` is dangling
diff --git a/library/core/src/ffi/mod.rs b/library/core/src/ffi/mod.rs
index 76daceecd..27f665904 100644
--- a/library/core/src/ffi/mod.rs
+++ b/library/core/src/ffi/mod.rs
@@ -144,6 +144,7 @@ mod c_char_definition {
)
),
all(target_os = "fuchsia", target_arch = "aarch64"),
+ all(target_os = "nto", target_arch = "aarch64"),
target_os = "horizon"
))] {
pub type c_char = u8;
diff --git a/library/core/src/fmt/mod.rs b/library/core/src/fmt/mod.rs
index fa5073e33..c9821bf81 100644
--- a/library/core/src/fmt/mod.rs
+++ b/library/core/src/fmt/mod.rs
@@ -267,6 +267,7 @@ extern "C" {
/// family of functions. It contains a function to format the given value. At
/// compile time it is ensured that the function and the value have the correct
/// types, and then this struct is used to canonicalize arguments to one type.
+#[cfg_attr(not(bootstrap), lang = "format_argument")]
#[derive(Copy, Clone)]
#[allow(missing_debug_implementations)]
#[unstable(feature = "fmt_internals", reason = "internal to format_args!", issue = "none")]
@@ -279,6 +280,7 @@ pub struct ArgumentV1<'a> {
/// 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.
+#[cfg_attr(not(bootstrap), lang = "format_unsafe_arg")]
#[allow(missing_debug_implementations)]
#[doc(hidden)]
#[unstable(feature = "fmt_internals", reason = "internal to format_args!", issue = "none")]
@@ -473,8 +475,8 @@ impl<'a> Arguments<'a> {
/// ```
///
/// [`format()`]: ../../std/fmt/fn.format.html
+#[cfg_attr(not(bootstrap), lang = "format_arguments")]
#[stable(feature = "rust1", since = "1.0.0")]
-#[cfg_attr(not(test), rustc_diagnostic_item = "Arguments")]
#[derive(Copy, Clone)]
pub struct Arguments<'a> {
// Format string pieces to print.
@@ -489,9 +491,26 @@ pub struct Arguments<'a> {
}
impl<'a> Arguments<'a> {
- /// Get the formatted string, if it has no arguments to be formatted.
+ /// Get the formatted string, if it has no arguments to be formatted at runtime.
///
- /// This can be used to avoid allocations in the most trivial case.
+ /// This can be used to avoid allocations in some cases.
+ ///
+ /// # Guarantees
+ ///
+ /// For `format_args!("just a literal")`, this function is guaranteed to
+ /// return `Some("just a literal")`.
+ ///
+ /// For most cases with placeholders, this function will return `None`.
+ ///
+ /// However, the compiler may perform optimizations that can cause this
+ /// function to return `Some(_)` even if the format string contains
+ /// placeholders. For example, `format_args!("Hello, {}!", "world")` may be
+ /// optimized to `format_args!("Hello, world!")`, such that `as_str()`
+ /// returns `Some("Hello, world!")`.
+ ///
+ /// The behavior for anything but the trivial case (without placeholders)
+ /// is not guaranteed, and should not be relied upon for anything other
+ /// than optimization.
///
/// # Examples
///
@@ -512,7 +531,7 @@ impl<'a> Arguments<'a> {
/// ```rust
/// assert_eq!(format_args!("hello").as_str(), Some("hello"));
/// assert_eq!(format_args!("").as_str(), Some(""));
- /// assert_eq!(format_args!("{}", 1).as_str(), None);
+ /// assert_eq!(format_args!("{:?}", std::env::current_dir()).as_str(), None);
/// ```
#[stable(feature = "fmt_as_str", since = "1.52.0")]
#[rustc_const_unstable(feature = "const_arguments_as_str", issue = "103900")]
@@ -1355,11 +1374,11 @@ impl<'a> Formatter<'a> {
/// }
/// }
///
- /// assert_eq!(&format!("{}", Foo::new(2)), "2");
- /// assert_eq!(&format!("{}", Foo::new(-1)), "-1");
- /// assert_eq!(&format!("{}", Foo::new(0)), "0");
- /// assert_eq!(&format!("{:#}", Foo::new(-1)), "-Foo 1");
- /// assert_eq!(&format!("{:0>#8}", Foo::new(-1)), "00-Foo 1");
+ /// assert_eq!(format!("{}", Foo::new(2)), "2");
+ /// assert_eq!(format!("{}", Foo::new(-1)), "-1");
+ /// assert_eq!(format!("{}", Foo::new(0)), "0");
+ /// assert_eq!(format!("{:#}", Foo::new(-1)), "-Foo 1");
+ /// assert_eq!(format!("{:0>#8}", Foo::new(-1)), "00-Foo 1");
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn pad_integral(&mut self, is_nonnegative: bool, prefix: &str, buf: &str) -> Result {
@@ -1452,8 +1471,8 @@ impl<'a> Formatter<'a> {
/// }
/// }
///
- /// assert_eq!(&format!("{Foo:<4}"), "Foo ");
- /// assert_eq!(&format!("{Foo:0>4}"), "0Foo");
+ /// assert_eq!(format!("{Foo:<4}"), "Foo ");
+ /// assert_eq!(format!("{Foo:0>4}"), "0Foo");
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn pad(&mut self, s: &str) -> Result {
@@ -1636,8 +1655,8 @@ impl<'a> Formatter<'a> {
/// }
/// }
///
- /// assert_eq!(&format!("{Foo}"), "Foo");
- /// assert_eq!(&format!("{Foo:0>8}"), "Foo");
+ /// assert_eq!(format!("{Foo}"), "Foo");
+ /// assert_eq!(format!("{Foo:0>8}"), "Foo");
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn write_str(&mut self, data: &str) -> Result {
@@ -1659,8 +1678,8 @@ impl<'a> Formatter<'a> {
/// }
/// }
///
- /// assert_eq!(&format!("{}", Foo(-1)), "Foo -1");
- /// assert_eq!(&format!("{:0>8}", Foo(2)), "Foo 2");
+ /// assert_eq!(format!("{}", Foo(-1)), "Foo -1");
+ /// assert_eq!(format!("{:0>8}", Foo(2)), "Foo 2");
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn write_fmt(&mut self, fmt: Arguments<'_>) -> Result {
@@ -1703,8 +1722,8 @@ impl<'a> Formatter<'a> {
/// }
///
/// // We set alignment to the right with ">".
- /// assert_eq!(&format!("{Foo:G>3}"), "GGG");
- /// assert_eq!(&format!("{Foo:t>6}"), "tttttt");
+ /// assert_eq!(format!("{Foo:G>3}"), "GGG");
+ /// assert_eq!(format!("{Foo:t>6}"), "tttttt");
/// ```
#[must_use]
#[stable(feature = "fmt_flags", since = "1.5.0")]
@@ -1738,10 +1757,10 @@ impl<'a> Formatter<'a> {
/// }
/// }
///
- /// assert_eq!(&format!("{Foo:<}"), "left");
- /// assert_eq!(&format!("{Foo:>}"), "right");
- /// assert_eq!(&format!("{Foo:^}"), "center");
- /// assert_eq!(&format!("{Foo}"), "into the void");
+ /// assert_eq!(format!("{Foo:<}"), "left");
+ /// assert_eq!(format!("{Foo:>}"), "right");
+ /// assert_eq!(format!("{Foo:^}"), "center");
+ /// assert_eq!(format!("{Foo}"), "into the void");
/// ```
#[must_use]
#[stable(feature = "fmt_flags_align", since = "1.28.0")]
@@ -1767,7 +1786,7 @@ impl<'a> Formatter<'a> {
/// fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
/// if let Some(width) = formatter.width() {
/// // If we received a width, we use it
- /// write!(formatter, "{:width$}", &format!("Foo({})", self.0), width = width)
+ /// write!(formatter, "{:width$}", format!("Foo({})", self.0), width = width)
/// } else {
/// // Otherwise we do nothing special
/// write!(formatter, "Foo({})", self.0)
@@ -1775,8 +1794,8 @@ impl<'a> Formatter<'a> {
/// }
/// }
///
- /// assert_eq!(&format!("{:10}", Foo(23)), "Foo(23) ");
- /// assert_eq!(&format!("{}", Foo(23)), "Foo(23)");
+ /// assert_eq!(format!("{:10}", Foo(23)), "Foo(23) ");
+ /// assert_eq!(format!("{}", Foo(23)), "Foo(23)");
/// ```
#[must_use]
#[stable(feature = "fmt_flags", since = "1.5.0")]
@@ -1806,8 +1825,8 @@ impl<'a> Formatter<'a> {
/// }
/// }
///
- /// assert_eq!(&format!("{:.4}", Foo(23.2)), "Foo(23.2000)");
- /// assert_eq!(&format!("{}", Foo(23.2)), "Foo(23.20)");
+ /// assert_eq!(format!("{:.4}", Foo(23.2)), "Foo(23.2000)");
+ /// assert_eq!(format!("{}", Foo(23.2)), "Foo(23.20)");
/// ```
#[must_use]
#[stable(feature = "fmt_flags", since = "1.5.0")]
@@ -1837,9 +1856,9 @@ impl<'a> Formatter<'a> {
/// }
/// }
///
- /// assert_eq!(&format!("{:+}", Foo(23)), "Foo(+23)");
- /// assert_eq!(&format!("{:+}", Foo(-23)), "Foo(-23)");
- /// assert_eq!(&format!("{}", Foo(23)), "Foo(23)");
+ /// assert_eq!(format!("{:+}", Foo(23)), "Foo(+23)");
+ /// assert_eq!(format!("{:+}", Foo(-23)), "Foo(-23)");
+ /// assert_eq!(format!("{}", Foo(23)), "Foo(23)");
/// ```
#[must_use]
#[stable(feature = "fmt_flags", since = "1.5.0")]
@@ -1867,8 +1886,8 @@ impl<'a> Formatter<'a> {
/// }
/// }
///
- /// assert_eq!(&format!("{:-}", Foo(23)), "-Foo(23)");
- /// assert_eq!(&format!("{}", Foo(23)), "Foo(23)");
+ /// assert_eq!(format!("{:-}", Foo(23)), "-Foo(23)");
+ /// assert_eq!(format!("{}", Foo(23)), "Foo(23)");
/// ```
#[must_use]
#[stable(feature = "fmt_flags", since = "1.5.0")]
@@ -1895,8 +1914,8 @@ impl<'a> Formatter<'a> {
/// }
/// }
///
- /// assert_eq!(&format!("{:#}", Foo(23)), "Foo(23)");
- /// assert_eq!(&format!("{}", Foo(23)), "23");
+ /// assert_eq!(format!("{:#}", Foo(23)), "Foo(23)");
+ /// assert_eq!(format!("{}", Foo(23)), "23");
/// ```
#[must_use]
#[stable(feature = "fmt_flags", since = "1.5.0")]
@@ -1922,7 +1941,7 @@ impl<'a> Formatter<'a> {
/// }
/// }
///
- /// assert_eq!(&format!("{:04}", Foo(23)), "23");
+ /// assert_eq!(format!("{:04}", Foo(23)), "23");
/// ```
#[must_use]
#[stable(feature = "fmt_flags", since = "1.5.0")]
diff --git a/library/core/src/fmt/rt/v1.rs b/library/core/src/fmt/rt/v1.rs
index 37202b277..11a50951a 100644
--- a/library/core/src/fmt/rt/v1.rs
+++ b/library/core/src/fmt/rt/v1.rs
@@ -5,7 +5,9 @@
//! these can be statically allocated and are slightly optimized for the runtime
#![allow(missing_debug_implementations)]
+#[cfg_attr(not(bootstrap), lang = "format_placeholder")]
#[derive(Copy, Clone)]
+// FIXME: Rename this to Placeholder
pub struct Argument {
pub position: usize,
pub format: FormatSpec,
@@ -20,7 +22,22 @@ pub struct FormatSpec {
pub width: Count,
}
+impl Argument {
+ #[inline(always)]
+ pub const fn new(
+ position: usize,
+ fill: char,
+ align: Alignment,
+ flags: u32,
+ precision: Count,
+ width: Count,
+ ) -> Self {
+ Self { position, format: FormatSpec { fill, align, flags, precision, width } }
+ }
+}
+
/// Possible alignments that can be requested as part of a formatting directive.
+#[cfg_attr(not(bootstrap), lang = "format_alignment")]
#[derive(Copy, Clone, PartialEq, Eq)]
pub enum Alignment {
/// Indication that contents should be left-aligned.
@@ -34,6 +51,7 @@ pub enum Alignment {
}
/// Used by [width](https://doc.rust-lang.org/std/fmt/#width) and [precision](https://doc.rust-lang.org/std/fmt/#precision) specifiers.
+#[cfg_attr(not(bootstrap), lang = "format_count")]
#[derive(Copy, Clone)]
pub enum Count {
/// Specified with a literal number, stores the value
diff --git a/library/core/src/future/mod.rs b/library/core/src/future/mod.rs
index c4fb36209..46cbcd435 100644
--- a/library/core/src/future/mod.rs
+++ b/library/core/src/future/mod.rs
@@ -56,51 +56,6 @@ unsafe impl Send for ResumeTy {}
#[unstable(feature = "gen_future", issue = "50547")]
unsafe impl Sync for ResumeTy {}
-/// Wrap a generator in a future.
-///
-/// This function returns a `GenFuture` underneath, but hides it in `impl Trait` to give
-/// better error messages (`impl Future` rather than `GenFuture<[closure.....]>`).
-// This is `const` to avoid extra errors after we recover from `const async fn`
-#[doc(hidden)]
-#[unstable(feature = "gen_future", issue = "50547")]
-#[rustc_const_unstable(feature = "gen_future", issue = "50547")]
-#[inline]
-pub const fn from_generator<T>(gen: T) -> impl Future<Output = T::Return>
-where
- T: crate::ops::Generator<ResumeTy, Yield = ()>,
-{
- use crate::{
- ops::{Generator, GeneratorState},
- pin::Pin,
- task::Poll,
- };
-
- #[rustc_diagnostic_item = "gen_future"]
- struct GenFuture<T: Generator<ResumeTy, Yield = ()>>(T);
-
- // We rely on the fact that async/await futures are immovable in order to create
- // self-referential borrows in the underlying generator.
- impl<T: Generator<ResumeTy, Yield = ()>> !Unpin for GenFuture<T> {}
-
- impl<T: Generator<ResumeTy, Yield = ()>> Future for GenFuture<T> {
- type Output = T::Return;
- #[track_caller]
- fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
- // SAFETY: Safe because we're !Unpin + !Drop, and this is just a field projection.
- let gen = unsafe { Pin::map_unchecked_mut(self, |s| &mut s.0) };
-
- // Resume the generator, turning the `&mut Context` into a `NonNull` raw pointer. The
- // `.await` lowering will safely cast that back to a `&mut Context`.
- match gen.resume(ResumeTy(NonNull::from(cx).cast::<Context<'static>>())) {
- GeneratorState::Yielded(()) => Poll::Pending,
- GeneratorState::Complete(x) => Poll::Ready(x),
- }
- }
- }
-
- GenFuture(gen)
-}
-
#[lang = "get_context"]
#[doc(hidden)]
#[unstable(feature = "gen_future", issue = "50547")]
diff --git a/library/core/src/hint.rs b/library/core/src/hint.rs
index 5a76e8669..ee13dae60 100644
--- a/library/core/src/hint.rs
+++ b/library/core/src/hint.rs
@@ -216,7 +216,8 @@ pub fn spin_loop() {
///
/// Note however, that `black_box` is only (and can only be) provided on a "best-effort" basis. The
/// extent to which it can block optimisations may vary depending upon the platform and code-gen
-/// backend used. Programs cannot rely on `black_box` for *correctness* in any way.
+/// backend used. Programs cannot rely on `black_box` for *correctness*, beyond it behaving as the
+/// identity function.
///
/// [`std::convert::identity`]: crate::convert::identity
///
diff --git a/library/core/src/intrinsics.rs b/library/core/src/intrinsics.rs
index a315a28fb..18a90599c 100644
--- a/library/core/src/intrinsics.rs
+++ b/library/core/src/intrinsics.rs
@@ -58,7 +58,6 @@ use crate::marker::DiscriminantKind;
use crate::marker::Tuple;
use crate::mem;
-#[cfg(not(bootstrap))]
pub mod mir;
// These imports are used for simplifying intra-doc links
@@ -963,7 +962,6 @@ extern "rust-intrinsic" {
/// This intrinsic does not have a stable counterpart.
#[rustc_const_unstable(feature = "const_assert_type2", issue = "none")]
#[rustc_safe_intrinsic]
- #[cfg(not(bootstrap))]
pub fn assert_mem_uninitialized_valid<T>();
/// Gets a reference to a static `Location` indicating where it was called.
@@ -2095,6 +2093,10 @@ extern "rust-intrinsic" {
/// Above some backend-decided threshold this will emit calls to `memcmp`,
/// like slice equality does, instead of causing massive code size.
///
+ /// Since this works by comparing the underlying bytes, the actual `T` is
+ /// not particularly important. It will be used for its size and alignment,
+ /// but any validity restrictions will be ignored, not enforced.
+ ///
/// # Safety
///
/// It's UB to call this if any of the *bytes* in `*a` or `*b` are uninitialized or carry a
diff --git a/library/core/src/intrinsics/mir.rs b/library/core/src/intrinsics/mir.rs
index e3157b669..72db1d87c 100644
--- a/library/core/src/intrinsics/mir.rs
+++ b/library/core/src/intrinsics/mir.rs
@@ -42,7 +42,7 @@
//! another function. The `dialect` and `phase` parameters indicate which [version of MIR][dialect
//! docs] you are inserting here. Generally you'll want to use `#![custom_mir(dialect = "built")]`
//! if you want your MIR to be modified by the full MIR pipeline, or `#![custom_mir(dialect =
-//! "runtime", phase = "optimized")] if you don't.
+//! "runtime", phase = "optimized")]` if you don't.
//!
//! [dialect docs]:
//! https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/mir/enum.MirPhase.html
@@ -60,8 +60,7 @@
//!
//! # Examples
//!
-#![cfg_attr(bootstrap, doc = "```rust,compile_fail")]
-#![cfg_attr(not(bootstrap), doc = "```rust")]
+//! ```rust
//! #![feature(core_intrinsics, custom_mir)]
//!
//! extern crate core;
@@ -211,13 +210,16 @@
//!
//! #### Statements
//! - Assign statements work via normal Rust assignment.
-//! - [`Retag`] statements have an associated function.
+//! - [`Retag`], [`StorageLive`], [`StorageDead`], [`Deinit`] statements have an associated function.
//!
//! #### Rvalues
//!
//! - Operands implicitly convert to `Use` rvalues.
//! - `&`, `&mut`, `addr_of!`, and `addr_of_mut!` all work to create their associated rvalue.
-//! - [`Discriminant`] has an associated function.
+//! - [`Discriminant`] and [`Len`] have associated functions.
+//! - Unary and binary operations use their normal Rust syntax - `a * b`, `!c`, etc.
+//! - Checked binary operations are represented by wrapping the associated binop in [`Checked`].
+//! - Array repetition syntax (`[foo; 10]`) creates the associated rvalue.
//!
//! #### Terminators
//!
@@ -261,6 +263,9 @@ define!("mir_drop_and_replace", fn DropAndReplace<T>(place: T, value: T, goto: B
define!("mir_call", fn Call<T>(place: T, goto: BasicBlock, call: T));
define!("mir_storage_live", fn StorageLive<T>(local: T));
define!("mir_storage_dead", fn StorageDead<T>(local: T));
+define!("mir_deinit", fn Deinit<T>(place: T));
+define!("mir_checked", fn Checked<T>(binop: T) -> (T, bool));
+define!("mir_len", fn Len<T>(place: T) -> usize);
define!("mir_retag", fn Retag<T>(place: T));
define!("mir_move", fn Move<T>(place: T) -> T);
define!("mir_static", fn Static<T>(s: T) -> &'static T);
@@ -294,8 +299,7 @@ define!(
///
/// # Examples
///
- #[cfg_attr(bootstrap, doc = "```rust,compile_fail")]
- #[cfg_attr(not(bootstrap), doc = "```rust")]
+ /// ```rust
/// #![feature(custom_mir, core_intrinsics)]
///
/// extern crate core;
diff --git a/library/core/src/iter/adapters/array_chunks.rs b/library/core/src/iter/adapters/array_chunks.rs
index 5e4211058..13719c727 100644
--- a/library/core/src/iter/adapters/array_chunks.rs
+++ b/library/core/src/iter/adapters/array_chunks.rs
@@ -1,7 +1,5 @@
use crate::array;
-use crate::const_closure::ConstFnMutClosure;
use crate::iter::{ByRefSized, FusedIterator, Iterator, TrustedRandomAccessNoCoerce};
-use crate::mem::{self, MaybeUninit};
use crate::ops::{ControlFlow, NeverShortCircuit, Try};
/// An iterator over `N` elements of the iterator at a time.
@@ -189,13 +187,12 @@ where
I: Iterator,
{
#[inline]
- default fn fold<B, F>(mut self, init: B, mut f: F) -> B
+ default fn fold<B, F>(mut self, init: B, f: F) -> B
where
Self: Sized,
F: FnMut(B, Self::Item) -> B,
{
- let fold = ConstFnMutClosure::new(&mut f, NeverShortCircuit::wrap_mut_2_imp);
- self.try_fold(init, fold).0
+ self.try_fold(init, NeverShortCircuit::wrap_mut_2(f)).0
}
}
@@ -214,19 +211,14 @@ where
let mut i = 0;
// Use a while loop because (0..len).step_by(N) doesn't optimize well.
while inner_len - i >= N {
- let mut chunk = MaybeUninit::uninit_array();
- let mut guard = array::Guard { array_mut: &mut chunk, initialized: 0 };
- while guard.initialized < N {
+ let chunk = crate::array::from_fn(|local| {
// SAFETY: The method consumes the iterator and the loop condition ensures that
// all accesses are in bounds and only happen once.
unsafe {
- let idx = i + guard.initialized;
- guard.push_unchecked(self.iter.__iterator_get_unchecked(idx));
+ let idx = i + local;
+ self.iter.__iterator_get_unchecked(idx)
}
- }
- mem::forget(guard);
- // SAFETY: The loop above initialized all elements
- let chunk = unsafe { MaybeUninit::array_assume_init(chunk) };
+ });
accum = f(accum, chunk);
i += N;
}
diff --git a/library/core/src/iter/adapters/by_ref_sized.rs b/library/core/src/iter/adapters/by_ref_sized.rs
index 1945e402f..477e7117c 100644
--- a/library/core/src/iter/adapters/by_ref_sized.rs
+++ b/library/core/src/iter/adapters/by_ref_sized.rs
@@ -1,7 +1,4 @@
-use crate::{
- const_closure::ConstFnMutClosure,
- ops::{NeverShortCircuit, Try},
-};
+use crate::ops::{NeverShortCircuit, Try};
/// Like `Iterator::by_ref`, but requiring `Sized` so it can forward generics.
///
@@ -39,13 +36,12 @@ impl<I: Iterator> Iterator for ByRefSized<'_, I> {
}
#[inline]
- fn fold<B, F>(self, init: B, mut f: F) -> B
+ fn fold<B, F>(self, init: B, f: F) -> B
where
F: FnMut(B, Self::Item) -> B,
{
// `fold` needs ownership, so this can't forward directly.
- I::try_fold(self.0, init, ConstFnMutClosure::new(&mut f, NeverShortCircuit::wrap_mut_2_imp))
- .0
+ I::try_fold(self.0, init, NeverShortCircuit::wrap_mut_2(f)).0
}
#[inline]
@@ -76,17 +72,12 @@ impl<I: DoubleEndedIterator> DoubleEndedIterator for ByRefSized<'_, I> {
}
#[inline]
- fn rfold<B, F>(self, init: B, mut f: F) -> B
+ fn rfold<B, F>(self, init: B, f: F) -> B
where
F: FnMut(B, Self::Item) -> B,
{
// `rfold` needs ownership, so this can't forward directly.
- I::try_rfold(
- self.0,
- init,
- ConstFnMutClosure::new(&mut f, NeverShortCircuit::wrap_mut_2_imp),
- )
- .0
+ I::try_rfold(self.0, init, NeverShortCircuit::wrap_mut_2(f)).0
}
#[inline]
diff --git a/library/core/src/iter/adapters/cloned.rs b/library/core/src/iter/adapters/cloned.rs
index aba24a79d..914ff86c1 100644
--- a/library/core/src/iter/adapters/cloned.rs
+++ b/library/core/src/iter/adapters/cloned.rs
@@ -1,7 +1,7 @@
use crate::iter::adapters::{
zip::try_get_unchecked, TrustedRandomAccess, TrustedRandomAccessNoCoerce,
};
-use crate::iter::{FusedIterator, TrustedLen};
+use crate::iter::{FusedIterator, TrustedLen, UncheckedIterator};
use crate::ops::Try;
/// An iterator that clones the elements of an underlying iterator.
@@ -140,3 +140,16 @@ where
T: Clone,
{
}
+
+impl<'a, I, T: 'a> UncheckedIterator for Cloned<I>
+where
+ I: UncheckedIterator<Item = &'a T>,
+ T: Clone,
+{
+ unsafe fn next_unchecked(&mut self) -> T {
+ // SAFETY: `Cloned` is 1:1 with the inner iterator, so if the caller promised
+ // that there's an element left, the inner iterator has one too.
+ let item = unsafe { self.it.next_unchecked() };
+ item.clone()
+ }
+}
diff --git a/library/core/src/iter/adapters/filter_map.rs b/library/core/src/iter/adapters/filter_map.rs
index e0d665c9e..6bdf53f7f 100644
--- a/library/core/src/iter/adapters/filter_map.rs
+++ b/library/core/src/iter/adapters/filter_map.rs
@@ -99,7 +99,7 @@ where
) -> impl FnMut((), T) -> ControlFlow<B> + '_ {
move |(), x| match f(x) {
Some(x) => ControlFlow::Break(x),
- None => ControlFlow::CONTINUE,
+ None => ControlFlow::Continue(()),
}
}
diff --git a/library/core/src/iter/adapters/flatten.rs b/library/core/src/iter/adapters/flatten.rs
index 307016c26..b040a0ea9 100644
--- a/library/core/src/iter/adapters/flatten.rs
+++ b/library/core/src/iter/adapters/flatten.rs
@@ -539,7 +539,7 @@ where
#[rustc_inherit_overflow_checks]
fn advance<U: Iterator>(n: usize, iter: &mut U) -> ControlFlow<(), usize> {
match iter.advance_by(n) {
- Ok(()) => ControlFlow::BREAK,
+ Ok(()) => ControlFlow::Break(()),
Err(advanced) => ControlFlow::Continue(n - advanced),
}
}
@@ -629,7 +629,7 @@ where
#[rustc_inherit_overflow_checks]
fn advance<U: DoubleEndedIterator>(n: usize, iter: &mut U) -> ControlFlow<(), usize> {
match iter.advance_back_by(n) {
- Ok(()) => ControlFlow::BREAK,
+ Ok(()) => ControlFlow::Break(()),
Err(advanced) => ControlFlow::Continue(n - advanced),
}
}
diff --git a/library/core/src/iter/adapters/map.rs b/library/core/src/iter/adapters/map.rs
index 9e25dbe46..31d02a4da 100644
--- a/library/core/src/iter/adapters/map.rs
+++ b/library/core/src/iter/adapters/map.rs
@@ -2,7 +2,7 @@ use crate::fmt;
use crate::iter::adapters::{
zip::try_get_unchecked, SourceIter, TrustedRandomAccess, TrustedRandomAccessNoCoerce,
};
-use crate::iter::{FusedIterator, InPlaceIterable, TrustedLen};
+use crate::iter::{FusedIterator, InPlaceIterable, TrustedLen, UncheckedIterator};
use crate::ops::Try;
/// An iterator that maps the values of `iter` with `f`.
@@ -187,6 +187,19 @@ where
{
}
+impl<B, I, F> UncheckedIterator for Map<I, F>
+where
+ I: UncheckedIterator,
+ F: FnMut(I::Item) -> B,
+{
+ unsafe fn next_unchecked(&mut self) -> B {
+ // SAFETY: `Map` is 1:1 with the inner iterator, so if the caller promised
+ // that there's an element left, the inner iterator has one too.
+ let item = unsafe { self.iter.next_unchecked() };
+ (self.f)(item)
+ }
+}
+
#[doc(hidden)]
#[unstable(feature = "trusted_random_access", issue = "none")]
unsafe impl<I, F> TrustedRandomAccess for Map<I, F> where I: TrustedRandomAccess {}
diff --git a/library/core/src/iter/adapters/zip.rs b/library/core/src/iter/adapters/zip.rs
index 8153c8cfe..b6b0c90cb 100644
--- a/library/core/src/iter/adapters/zip.rs
+++ b/library/core/src/iter/adapters/zip.rs
@@ -1,7 +1,7 @@
use crate::cmp;
use crate::fmt::{self, Debug};
use crate::iter::{DoubleEndedIterator, ExactSizeIterator, FusedIterator, Iterator};
-use crate::iter::{InPlaceIterable, SourceIter, TrustedLen};
+use crate::iter::{InPlaceIterable, SourceIter, TrustedLen, UncheckedIterator};
/// An iterator that iterates two other iterators simultaneously.
///
@@ -417,6 +417,13 @@ where
{
}
+impl<A, B> UncheckedIterator for Zip<A, B>
+where
+ A: UncheckedIterator,
+ B: UncheckedIterator,
+{
+}
+
// 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")]
diff --git a/library/core/src/iter/mod.rs b/library/core/src/iter/mod.rs
index bb35d50b4..ae00232c1 100644
--- a/library/core/src/iter/mod.rs
+++ b/library/core/src/iter/mod.rs
@@ -278,6 +278,7 @@
//!
//! ```
//! # #![allow(unused_must_use)]
+//! # #![cfg_attr(not(bootstrap), allow(map_unit_fn))]
//! let v = vec![1, 2, 3, 4, 5];
//! v.iter().map(|x| println!("{x}"));
//! ```
@@ -362,15 +363,13 @@ macro_rules! impl_fold_via_try_fold {
};
(@internal $fold:ident -> $try_fold:ident) => {
#[inline]
- fn $fold<AAA, FFF>(mut self, init: AAA, mut fold: FFF) -> AAA
+ fn $fold<AAA, FFF>(mut self, init: AAA, fold: FFF) -> AAA
where
FFF: FnMut(AAA, Self::Item) -> AAA,
{
- use crate::const_closure::ConstFnMutClosure;
use crate::ops::NeverShortCircuit;
- let fold = ConstFnMutClosure::new(&mut fold, NeverShortCircuit::wrap_mut_2_imp);
- self.$try_fold(init, fold).0
+ self.$try_fold(init, NeverShortCircuit::wrap_mut_2(fold)).0
}
};
}
@@ -452,6 +451,7 @@ pub use self::adapters::{
pub use self::adapters::{Intersperse, IntersperseWith};
pub(crate) use self::adapters::try_process;
+pub(crate) use self::traits::UncheckedIterator;
mod adapters;
mod range;
diff --git a/library/core/src/iter/range.rs b/library/core/src/iter/range.rs
index b5739f2f3..78e27d730 100644
--- a/library/core/src/iter/range.rs
+++ b/library/core/src/iter/range.rs
@@ -1,4 +1,3 @@
-use crate::char;
use crate::convert::TryFrom;
use crate::mem;
use crate::ops::{self, Try};
diff --git a/library/core/src/iter/traits/double_ended.rs b/library/core/src/iter/traits/double_ended.rs
index bdf94c792..ed23873cd 100644
--- a/library/core/src/iter/traits/double_ended.rs
+++ b/library/core/src/iter/traits/double_ended.rs
@@ -352,7 +352,7 @@ pub trait DoubleEndedIterator: Iterator {
#[inline]
fn check<T>(mut predicate: impl FnMut(&T) -> bool) -> impl FnMut((), T) -> ControlFlow<T> {
move |(), x| {
- if predicate(&x) { ControlFlow::Break(x) } else { ControlFlow::CONTINUE }
+ if predicate(&x) { ControlFlow::Break(x) } else { ControlFlow::Continue(()) }
}
}
diff --git a/library/core/src/iter/traits/exact_size.rs b/library/core/src/iter/traits/exact_size.rs
index 1757e37ec..908830d8a 100644
--- a/library/core/src/iter/traits/exact_size.rs
+++ b/library/core/src/iter/traits/exact_size.rs
@@ -21,6 +21,16 @@
///
/// [`len`]: ExactSizeIterator::len
///
+/// # When *shouldn't* an adapter be `ExactSizeIterator`?
+///
+/// If an adapter makes an iterator *longer*, then it's usually incorrect for
+/// that adapter to implement `ExactSizeIterator`. The inner exact-sized
+/// iterator might already be `usize::MAX`-long, and thus the length of the
+/// longer adapted iterator would no longer be exactly representable in `usize`.
+///
+/// This is why [`Chain<A, B>`](crate::iter::Chain) isn't `ExactSizeIterator`,
+/// even when `A` and `B` are both `ExactSizeIterator`.
+///
/// # Examples
///
/// Basic usage:
diff --git a/library/core/src/iter/traits/iterator.rs b/library/core/src/iter/traits/iterator.rs
index a4a665d48..b8e7d0a68 100644
--- a/library/core/src/iter/traits/iterator.rs
+++ b/library/core/src/iter/traits/iterator.rs
@@ -69,6 +69,7 @@ fn _assert_is_object_safe(_: &dyn Iterator<Item = ()>) {}
#[doc(notable_trait)]
#[rustc_diagnostic_item = "Iterator"]
#[must_use = "iterators are lazy and do nothing unless consumed"]
+#[cfg_attr(not(bootstrap), const_trait)]
pub trait Iterator {
/// The type of the elements being iterated over.
#[rustc_diagnostic_item = "IteratorItem"]
@@ -141,6 +142,7 @@ pub trait Iterator {
/// ```
#[inline]
#[unstable(feature = "iter_next_chunk", reason = "recently added", issue = "98326")]
+ #[rustc_do_not_const_check]
fn next_chunk<const N: usize>(
&mut self,
) -> Result<[Self::Item; N], array::IntoIter<Self::Item, N>>
@@ -218,6 +220,7 @@ pub trait Iterator {
/// ```
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
+ #[rustc_do_not_const_check]
fn size_hint(&self) -> (usize, Option<usize>) {
(0, None)
}
@@ -255,6 +258,7 @@ pub trait Iterator {
/// ```
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
+ #[rustc_do_not_const_check]
fn count(self) -> usize
where
Self: Sized,
@@ -285,6 +289,7 @@ pub trait Iterator {
/// ```
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
+ #[rustc_do_not_const_check]
fn last(self) -> Option<Self::Item>
where
Self: Sized,
@@ -331,6 +336,7 @@ pub trait Iterator {
/// ```
#[inline]
#[unstable(feature = "iter_advance_by", reason = "recently added", issue = "77404")]
+ #[rustc_do_not_const_check]
fn advance_by(&mut self, n: usize) -> Result<(), usize> {
for i in 0..n {
self.next().ok_or(i)?;
@@ -379,6 +385,7 @@ pub trait Iterator {
/// ```
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
+ #[rustc_do_not_const_check]
fn nth(&mut self, n: usize) -> Option<Self::Item> {
self.advance_by(n).ok()?;
self.next()
@@ -431,6 +438,7 @@ pub trait Iterator {
/// ```
#[inline]
#[stable(feature = "iterator_step_by", since = "1.28.0")]
+ #[rustc_do_not_const_check]
fn step_by(self, step: usize) -> StepBy<Self>
where
Self: Sized,
@@ -502,6 +510,7 @@ pub trait Iterator {
/// [`OsStr`]: ../../std/ffi/struct.OsStr.html
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
+ #[rustc_do_not_const_check]
fn chain<U>(self, other: U) -> Chain<Self, U::IntoIter>
where
Self: Sized,
@@ -620,6 +629,7 @@ pub trait Iterator {
/// [`zip`]: crate::iter::zip
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
+ #[rustc_do_not_const_check]
fn zip<U>(self, other: U) -> Zip<Self, U::IntoIter>
where
Self: Sized,
@@ -662,6 +672,7 @@ pub trait Iterator {
/// [`intersperse_with`]: Iterator::intersperse_with
#[inline]
#[unstable(feature = "iter_intersperse", reason = "recently added", issue = "79524")]
+ #[rustc_do_not_const_check]
fn intersperse(self, separator: Self::Item) -> Intersperse<Self>
where
Self: Sized,
@@ -720,6 +731,7 @@ pub trait Iterator {
/// [`intersperse`]: Iterator::intersperse
#[inline]
#[unstable(feature = "iter_intersperse", reason = "recently added", issue = "79524")]
+ #[rustc_do_not_const_check]
fn intersperse_with<G>(self, separator: G) -> IntersperseWith<Self, G>
where
Self: Sized,
@@ -777,8 +789,10 @@ pub trait Iterator {
/// println!("{x}");
/// }
/// ```
+ #[rustc_diagnostic_item = "IteratorMap"]
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
+ #[rustc_do_not_const_check]
fn map<B, F>(self, f: F) -> Map<Self, F>
where
Self: Sized,
@@ -824,6 +838,7 @@ pub trait Iterator {
/// ```
#[inline]
#[stable(feature = "iterator_for_each", since = "1.21.0")]
+ #[rustc_do_not_const_check]
fn for_each<F>(self, f: F)
where
Self: Sized,
@@ -899,6 +914,7 @@ pub trait Iterator {
/// Note that `iter.filter(f).next()` is equivalent to `iter.find(f)`.
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
+ #[rustc_do_not_const_check]
fn filter<P>(self, predicate: P) -> Filter<Self, P>
where
Self: Sized,
@@ -944,6 +960,7 @@ pub trait Iterator {
/// ```
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
+ #[rustc_do_not_const_check]
fn filter_map<B, F>(self, f: F) -> FilterMap<Self, F>
where
Self: Sized,
@@ -990,6 +1007,7 @@ pub trait Iterator {
/// ```
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
+ #[rustc_do_not_const_check]
fn enumerate(self) -> Enumerate<Self>
where
Self: Sized,
@@ -1061,6 +1079,7 @@ pub trait Iterator {
/// [`next`]: Iterator::next
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
+ #[rustc_do_not_const_check]
fn peekable(self) -> Peekable<Self>
where
Self: Sized,
@@ -1126,6 +1145,7 @@ pub trait Iterator {
#[inline]
#[doc(alias = "drop_while")]
#[stable(feature = "rust1", since = "1.0.0")]
+ #[rustc_do_not_const_check]
fn skip_while<P>(self, predicate: P) -> SkipWhile<Self, P>
where
Self: Sized,
@@ -1207,6 +1227,7 @@ pub trait Iterator {
/// the iteration should stop, but wasn't placed back into the iterator.
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
+ #[rustc_do_not_const_check]
fn take_while<P>(self, predicate: P) -> TakeWhile<Self, P>
where
Self: Sized,
@@ -1295,6 +1316,7 @@ pub trait Iterator {
/// [`fuse`]: Iterator::fuse
#[inline]
#[stable(feature = "iter_map_while", since = "1.57.0")]
+ #[rustc_do_not_const_check]
fn map_while<B, P>(self, predicate: P) -> MapWhile<Self, P>
where
Self: Sized,
@@ -1326,6 +1348,7 @@ pub trait Iterator {
/// ```
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
+ #[rustc_do_not_const_check]
fn skip(self, n: usize) -> Skip<Self>
where
Self: Sized,
@@ -1379,6 +1402,7 @@ pub trait Iterator {
/// ```
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
+ #[rustc_do_not_const_check]
fn take(self, n: usize) -> Take<Self>
where
Self: Sized,
@@ -1428,6 +1452,7 @@ pub trait Iterator {
/// ```
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
+ #[rustc_do_not_const_check]
fn scan<St, B, F>(self, initial_state: St, f: F) -> Scan<Self, St, F>
where
Self: Sized,
@@ -1468,6 +1493,7 @@ pub trait Iterator {
/// ```
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
+ #[rustc_do_not_const_check]
fn flat_map<U, F>(self, f: F) -> FlatMap<Self, U, F>
where
Self: Sized,
@@ -1552,6 +1578,7 @@ pub trait Iterator {
/// [`flat_map()`]: Iterator::flat_map
#[inline]
#[stable(feature = "iterator_flatten", since = "1.29.0")]
+ #[rustc_do_not_const_check]
fn flatten(self) -> Flatten<Self>
where
Self: Sized,
@@ -1620,6 +1647,7 @@ pub trait Iterator {
/// ```
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
+ #[rustc_do_not_const_check]
fn fuse(self) -> Fuse<Self>
where
Self: Sized,
@@ -1704,6 +1732,7 @@ pub trait Iterator {
/// ```
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
+ #[rustc_do_not_const_check]
fn inspect<F>(self, f: F) -> Inspect<Self, F>
where
Self: Sized,
@@ -1734,6 +1763,7 @@ pub trait Iterator {
/// assert_eq!(of_rust, vec!["of", "Rust"]);
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
+ #[rustc_do_not_const_check]
fn by_ref(&mut self) -> &mut Self
where
Self: Sized,
@@ -1853,6 +1883,7 @@ pub trait Iterator {
#[stable(feature = "rust1", since = "1.0.0")]
#[must_use = "if you really need to exhaust the iterator, consider `.for_each(drop)` instead"]
#[cfg_attr(not(test), rustc_diagnostic_item = "iterator_collect_fn")]
+ #[rustc_do_not_const_check]
fn collect<B: FromIterator<Self::Item>>(self) -> B
where
Self: Sized,
@@ -1931,6 +1962,7 @@ pub trait Iterator {
/// [`collect`]: Iterator::collect
#[inline]
#[unstable(feature = "iterator_try_collect", issue = "94047")]
+ #[rustc_do_not_const_check]
fn try_collect<B>(&mut self) -> ChangeOutputType<Self::Item, B>
where
Self: Sized,
@@ -2004,6 +2036,7 @@ pub trait Iterator {
/// ```
#[inline]
#[unstable(feature = "iter_collect_into", reason = "new API", issue = "94780")]
+ #[rustc_do_not_const_check]
fn collect_into<E: Extend<Self::Item>>(self, collection: &mut E) -> &mut E
where
Self: Sized,
@@ -2038,6 +2071,7 @@ pub trait Iterator {
/// assert_eq!(odd, vec![1, 3]);
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
+ #[rustc_do_not_const_check]
fn partition<B, F>(self, f: F) -> (B, B)
where
Self: Sized,
@@ -2100,6 +2134,7 @@ pub trait Iterator {
/// assert!(a[i..].iter().all(|&n| n % 2 == 1)); // odds
/// ```
#[unstable(feature = "iter_partition_in_place", reason = "new API", issue = "62543")]
+ #[rustc_do_not_const_check]
fn partition_in_place<'a, T: 'a, P>(mut self, ref mut predicate: P) -> usize
where
Self: Sized + DoubleEndedIterator<Item = &'a mut T>,
@@ -2157,6 +2192,7 @@ pub trait Iterator {
/// assert!(!"IntoIterator".chars().is_partitioned(char::is_uppercase));
/// ```
#[unstable(feature = "iter_is_partitioned", reason = "new API", issue = "62544")]
+ #[rustc_do_not_const_check]
fn is_partitioned<P>(mut self, mut predicate: P) -> bool
where
Self: Sized,
@@ -2251,6 +2287,7 @@ pub trait Iterator {
/// ```
#[inline]
#[stable(feature = "iterator_try_fold", since = "1.27.0")]
+ #[rustc_do_not_const_check]
fn try_fold<B, F, R>(&mut self, init: B, mut f: F) -> R
where
Self: Sized,
@@ -2309,6 +2346,7 @@ pub trait Iterator {
/// ```
#[inline]
#[stable(feature = "iterator_try_fold", since = "1.27.0")]
+ #[rustc_do_not_const_check]
fn try_for_each<F, R>(&mut self, f: F) -> R
where
Self: Sized,
@@ -2428,6 +2466,7 @@ pub trait Iterator {
#[doc(alias = "inject", alias = "foldl")]
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
+ #[rustc_do_not_const_check]
fn fold<B, F>(mut self, init: B, mut f: F) -> B
where
Self: Sized,
@@ -2465,6 +2504,7 @@ pub trait Iterator {
/// ```
#[inline]
#[stable(feature = "iterator_fold_self", since = "1.51.0")]
+ #[rustc_do_not_const_check]
fn reduce<F>(mut self, f: F) -> Option<Self::Item>
where
Self: Sized,
@@ -2536,6 +2576,7 @@ pub trait Iterator {
/// ```
#[inline]
#[unstable(feature = "iterator_try_reduce", reason = "new API", issue = "87053")]
+ #[rustc_do_not_const_check]
fn try_reduce<F, R>(&mut self, f: F) -> ChangeOutputType<R, Option<R::Output>>
where
Self: Sized,
@@ -2593,6 +2634,7 @@ pub trait Iterator {
/// ```
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
+ #[rustc_do_not_const_check]
fn all<F>(&mut self, f: F) -> bool
where
Self: Sized,
@@ -2601,10 +2643,10 @@ pub trait Iterator {
#[inline]
fn check<T>(mut f: impl FnMut(T) -> bool) -> impl FnMut((), T) -> ControlFlow<()> {
move |(), x| {
- if f(x) { ControlFlow::CONTINUE } else { ControlFlow::BREAK }
+ if f(x) { ControlFlow::Continue(()) } else { ControlFlow::Break(()) }
}
}
- self.try_fold((), check(f)) == ControlFlow::CONTINUE
+ self.try_fold((), check(f)) == ControlFlow::Continue(())
}
/// Tests if any element of the iterator matches a predicate.
@@ -2646,6 +2688,7 @@ pub trait Iterator {
/// ```
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
+ #[rustc_do_not_const_check]
fn any<F>(&mut self, f: F) -> bool
where
Self: Sized,
@@ -2654,11 +2697,11 @@ pub trait Iterator {
#[inline]
fn check<T>(mut f: impl FnMut(T) -> bool) -> impl FnMut((), T) -> ControlFlow<()> {
move |(), x| {
- if f(x) { ControlFlow::BREAK } else { ControlFlow::CONTINUE }
+ if f(x) { ControlFlow::Break(()) } else { ControlFlow::Continue(()) }
}
}
- self.try_fold((), check(f)) == ControlFlow::BREAK
+ self.try_fold((), check(f)) == ControlFlow::Break(())
}
/// Searches for an element of an iterator that satisfies a predicate.
@@ -2709,6 +2752,7 @@ pub trait Iterator {
/// Note that `iter.find(f)` is equivalent to `iter.filter(f).next()`.
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
+ #[rustc_do_not_const_check]
fn find<P>(&mut self, predicate: P) -> Option<Self::Item>
where
Self: Sized,
@@ -2717,7 +2761,7 @@ pub trait Iterator {
#[inline]
fn check<T>(mut predicate: impl FnMut(&T) -> bool) -> impl FnMut((), T) -> ControlFlow<T> {
move |(), x| {
- if predicate(&x) { ControlFlow::Break(x) } else { ControlFlow::CONTINUE }
+ if predicate(&x) { ControlFlow::Break(x) } else { ControlFlow::Continue(()) }
}
}
@@ -2740,6 +2784,7 @@ pub trait Iterator {
/// ```
#[inline]
#[stable(feature = "iterator_find_map", since = "1.30.0")]
+ #[rustc_do_not_const_check]
fn find_map<B, F>(&mut self, f: F) -> Option<B>
where
Self: Sized,
@@ -2749,7 +2794,7 @@ pub trait Iterator {
fn check<T, B>(mut f: impl FnMut(T) -> Option<B>) -> impl FnMut((), T) -> ControlFlow<B> {
move |(), x| match f(x) {
Some(x) => ControlFlow::Break(x),
- None => ControlFlow::CONTINUE,
+ None => ControlFlow::Continue(()),
}
}
@@ -2796,6 +2841,7 @@ pub trait Iterator {
/// ```
#[inline]
#[unstable(feature = "try_find", reason = "new API", issue = "63178")]
+ #[rustc_do_not_const_check]
fn try_find<F, R>(&mut self, f: F) -> ChangeOutputType<R, Option<Self::Item>>
where
Self: Sized,
@@ -2812,7 +2858,7 @@ pub trait Iterator {
R: Residual<Option<I>>,
{
move |(), x| match f(&x).branch() {
- ControlFlow::Continue(false) => ControlFlow::CONTINUE,
+ ControlFlow::Continue(false) => ControlFlow::Continue(()),
ControlFlow::Continue(true) => ControlFlow::Break(Try::from_output(Some(x))),
ControlFlow::Break(r) => ControlFlow::Break(FromResidual::from_residual(r)),
}
@@ -2878,6 +2924,7 @@ pub trait Iterator {
/// ```
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
+ #[rustc_do_not_const_check]
fn position<P>(&mut self, predicate: P) -> Option<usize>
where
Self: Sized,
@@ -2935,6 +2982,7 @@ pub trait Iterator {
/// ```
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
+ #[rustc_do_not_const_check]
fn rposition<P>(&mut self, predicate: P) -> Option<usize>
where
P: FnMut(Self::Item) -> bool,
@@ -2986,6 +3034,7 @@ pub trait Iterator {
/// ```
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
+ #[rustc_do_not_const_check]
fn max(self) -> Option<Self::Item>
where
Self: Sized,
@@ -3024,6 +3073,7 @@ pub trait Iterator {
/// ```
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
+ #[rustc_do_not_const_check]
fn min(self) -> Option<Self::Item>
where
Self: Sized,
@@ -3046,6 +3096,7 @@ pub trait Iterator {
/// ```
#[inline]
#[stable(feature = "iter_cmp_by_key", since = "1.6.0")]
+ #[rustc_do_not_const_check]
fn max_by_key<B: Ord, F>(self, f: F) -> Option<Self::Item>
where
Self: Sized,
@@ -3079,6 +3130,7 @@ pub trait Iterator {
/// ```
#[inline]
#[stable(feature = "iter_max_by", since = "1.15.0")]
+ #[rustc_do_not_const_check]
fn max_by<F>(self, compare: F) -> Option<Self::Item>
where
Self: Sized,
@@ -3106,6 +3158,7 @@ pub trait Iterator {
/// ```
#[inline]
#[stable(feature = "iter_cmp_by_key", since = "1.6.0")]
+ #[rustc_do_not_const_check]
fn min_by_key<B: Ord, F>(self, f: F) -> Option<Self::Item>
where
Self: Sized,
@@ -3139,6 +3192,7 @@ pub trait Iterator {
/// ```
#[inline]
#[stable(feature = "iter_min_by", since = "1.15.0")]
+ #[rustc_do_not_const_check]
fn min_by<F>(self, compare: F) -> Option<Self::Item>
where
Self: Sized,
@@ -3176,6 +3230,7 @@ pub trait Iterator {
#[inline]
#[doc(alias = "reverse")]
#[stable(feature = "rust1", since = "1.0.0")]
+ #[rustc_do_not_const_check]
fn rev(self) -> Rev<Self>
where
Self: Sized + DoubleEndedIterator,
@@ -3214,6 +3269,7 @@ pub trait Iterator {
/// assert_eq!(z, [3, 6]);
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
+ #[rustc_do_not_const_check]
fn unzip<A, B, FromA, FromB>(self) -> (FromA, FromB)
where
FromA: Default + Extend<A>,
@@ -3246,6 +3302,7 @@ pub trait Iterator {
/// assert_eq!(v_map, vec![1, 2, 3]);
/// ```
#[stable(feature = "iter_copied", since = "1.36.0")]
+ #[rustc_do_not_const_check]
fn copied<'a, T: 'a>(self) -> Copied<Self>
where
Self: Sized + Iterator<Item = &'a T>,
@@ -3293,6 +3350,7 @@ pub trait Iterator {
/// assert_eq!(&[vec![23]], &faster[..]);
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
+ #[rustc_do_not_const_check]
fn cloned<'a, T: 'a>(self) -> Cloned<Self>
where
Self: Sized + Iterator<Item = &'a T>,
@@ -3327,6 +3385,7 @@ pub trait Iterator {
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
+ #[rustc_do_not_const_check]
fn cycle(self) -> Cycle<Self>
where
Self: Sized + Clone,
@@ -3370,6 +3429,7 @@ pub trait Iterator {
/// ```
#[track_caller]
#[unstable(feature = "iter_array_chunks", reason = "recently added", issue = "100450")]
+ #[rustc_do_not_const_check]
fn array_chunks<const N: usize>(self) -> ArrayChunks<Self, N>
where
Self: Sized,
@@ -3400,6 +3460,7 @@ pub trait Iterator {
/// assert_eq!(sum, 6);
/// ```
#[stable(feature = "iter_arith", since = "1.11.0")]
+ #[rustc_do_not_const_check]
fn sum<S>(self) -> S
where
Self: Sized,
@@ -3429,6 +3490,7 @@ pub trait Iterator {
/// assert_eq!(factorial(5), 120);
/// ```
#[stable(feature = "iter_arith", since = "1.11.0")]
+ #[rustc_do_not_const_check]
fn product<P>(self) -> P
where
Self: Sized,
@@ -3450,6 +3512,7 @@ pub trait Iterator {
/// assert_eq!([1, 2].iter().cmp([1].iter()), Ordering::Greater);
/// ```
#[stable(feature = "iter_order", since = "1.5.0")]
+ #[rustc_do_not_const_check]
fn cmp<I>(self, other: I) -> Ordering
where
I: IntoIterator<Item = Self::Item>,
@@ -3479,6 +3542,7 @@ pub trait Iterator {
/// assert_eq!(xs.iter().cmp_by(&ys, |&x, &y| (2 * x).cmp(&y)), Ordering::Greater);
/// ```
#[unstable(feature = "iter_order_by", issue = "64295")]
+ #[rustc_do_not_const_check]
fn cmp_by<I, F>(self, other: I, cmp: F) -> Ordering
where
Self: Sized,
@@ -3491,7 +3555,7 @@ pub trait Iterator {
F: FnMut(X, Y) -> Ordering,
{
move |x, y| match cmp(x, y) {
- Ordering::Equal => ControlFlow::CONTINUE,
+ Ordering::Equal => ControlFlow::Continue(()),
non_eq => ControlFlow::Break(non_eq),
}
}
@@ -3502,8 +3566,10 @@ pub trait Iterator {
}
}
- /// [Lexicographically](Ord#lexicographical-comparison) compares the elements of this [`Iterator`] with those
- /// of another.
+ /// [Lexicographically](Ord#lexicographical-comparison) compares the [`PartialOrd`] elements of
+ /// this [`Iterator`] with those of another. The comparison works like short-circuit
+ /// evaluation, returning a result without comparing the remaining elements.
+ /// As soon as an order can be determined, the evaluation stops and a result is returned.
///
/// # Examples
///
@@ -3513,10 +3579,27 @@ pub trait Iterator {
/// assert_eq!([1.].iter().partial_cmp([1.].iter()), Some(Ordering::Equal));
/// assert_eq!([1.].iter().partial_cmp([1., 2.].iter()), Some(Ordering::Less));
/// assert_eq!([1., 2.].iter().partial_cmp([1.].iter()), Some(Ordering::Greater));
+ /// ```
///
+ /// For floating-point numbers, NaN does not have a total order and will result
+ /// in `None` when compared:
+ ///
+ /// ```
/// assert_eq!([f64::NAN].iter().partial_cmp([1.].iter()), None);
/// ```
+ ///
+ /// The results are determined by the order of evaluation.
+ ///
+ /// ```
+ /// use std::cmp::Ordering;
+ ///
+ /// assert_eq!([1.0, f64::NAN].iter().partial_cmp([2.0, f64::NAN].iter()), Some(Ordering::Less));
+ /// assert_eq!([2.0, f64::NAN].iter().partial_cmp([1.0, f64::NAN].iter()), Some(Ordering::Greater));
+ /// assert_eq!([f64::NAN, 1.0].iter().partial_cmp([f64::NAN, 2.0].iter()), None);
+ /// ```
+ ///
#[stable(feature = "iter_order", since = "1.5.0")]
+ #[rustc_do_not_const_check]
fn partial_cmp<I>(self, other: I) -> Option<Ordering>
where
I: IntoIterator,
@@ -3555,6 +3638,7 @@ pub trait Iterator {
/// );
/// ```
#[unstable(feature = "iter_order_by", issue = "64295")]
+ #[rustc_do_not_const_check]
fn partial_cmp_by<I, F>(self, other: I, partial_cmp: F) -> Option<Ordering>
where
Self: Sized,
@@ -3567,7 +3651,7 @@ pub trait Iterator {
F: FnMut(X, Y) -> Option<Ordering>,
{
move |x, y| match partial_cmp(x, y) {
- Some(Ordering::Equal) => ControlFlow::CONTINUE,
+ Some(Ordering::Equal) => ControlFlow::Continue(()),
non_eq => ControlFlow::Break(non_eq),
}
}
@@ -3588,6 +3672,7 @@ pub trait Iterator {
/// assert_eq!([1].iter().eq([1, 2].iter()), false);
/// ```
#[stable(feature = "iter_order", since = "1.5.0")]
+ #[rustc_do_not_const_check]
fn eq<I>(self, other: I) -> bool
where
I: IntoIterator,
@@ -3613,6 +3698,7 @@ pub trait Iterator {
/// assert!(xs.iter().eq_by(&ys, |&x, &y| x * x == y));
/// ```
#[unstable(feature = "iter_order_by", issue = "64295")]
+ #[rustc_do_not_const_check]
fn eq_by<I, F>(self, other: I, eq: F) -> bool
where
Self: Sized,
@@ -3625,7 +3711,7 @@ pub trait Iterator {
F: FnMut(X, Y) -> bool,
{
move |x, y| {
- if eq(x, y) { ControlFlow::CONTINUE } else { ControlFlow::BREAK }
+ if eq(x, y) { ControlFlow::Continue(()) } else { ControlFlow::Break(()) }
}
}
@@ -3645,6 +3731,7 @@ pub trait Iterator {
/// assert_eq!([1].iter().ne([1, 2].iter()), true);
/// ```
#[stable(feature = "iter_order", since = "1.5.0")]
+ #[rustc_do_not_const_check]
fn ne<I>(self, other: I) -> bool
where
I: IntoIterator,
@@ -3666,6 +3753,7 @@ pub trait Iterator {
/// assert_eq!([1, 2].iter().lt([1, 2].iter()), false);
/// ```
#[stable(feature = "iter_order", since = "1.5.0")]
+ #[rustc_do_not_const_check]
fn lt<I>(self, other: I) -> bool
where
I: IntoIterator,
@@ -3687,6 +3775,7 @@ pub trait Iterator {
/// assert_eq!([1, 2].iter().le([1, 2].iter()), true);
/// ```
#[stable(feature = "iter_order", since = "1.5.0")]
+ #[rustc_do_not_const_check]
fn le<I>(self, other: I) -> bool
where
I: IntoIterator,
@@ -3708,6 +3797,7 @@ pub trait Iterator {
/// assert_eq!([1, 2].iter().gt([1, 2].iter()), false);
/// ```
#[stable(feature = "iter_order", since = "1.5.0")]
+ #[rustc_do_not_const_check]
fn gt<I>(self, other: I) -> bool
where
I: IntoIterator,
@@ -3729,6 +3819,7 @@ pub trait Iterator {
/// assert_eq!([1, 2].iter().ge([1, 2].iter()), true);
/// ```
#[stable(feature = "iter_order", since = "1.5.0")]
+ #[rustc_do_not_const_check]
fn ge<I>(self, other: I) -> bool
where
I: IntoIterator,
@@ -3760,6 +3851,7 @@ pub trait Iterator {
/// ```
#[inline]
#[unstable(feature = "is_sorted", reason = "new API", issue = "53485")]
+ #[rustc_do_not_const_check]
fn is_sorted(self) -> bool
where
Self: Sized,
@@ -3788,6 +3880,7 @@ pub trait Iterator {
///
/// [`is_sorted`]: Iterator::is_sorted
#[unstable(feature = "is_sorted", reason = "new API", issue = "53485")]
+ #[rustc_do_not_const_check]
fn is_sorted_by<F>(mut self, compare: F) -> bool
where
Self: Sized,
@@ -3834,6 +3927,7 @@ pub trait Iterator {
/// ```
#[inline]
#[unstable(feature = "is_sorted", reason = "new API", issue = "53485")]
+ #[rustc_do_not_const_check]
fn is_sorted_by_key<F, K>(self, f: F) -> bool
where
Self: Sized,
@@ -3849,6 +3943,7 @@ pub trait Iterator {
#[inline]
#[doc(hidden)]
#[unstable(feature = "trusted_random_access", issue = "none")]
+ #[rustc_do_not_const_check]
unsafe fn __iterator_get_unchecked(&mut self, _idx: usize) -> Self::Item
where
Self: TrustedRandomAccessNoCoerce,
@@ -3859,7 +3954,7 @@ pub trait Iterator {
/// Compares two iterators element-wise using the given function.
///
-/// If `ControlFlow::CONTINUE` is returned from the function, the comparison moves on to the next
+/// If `ControlFlow::Continue(())` is returned from the function, the comparison moves on to the next
/// elements of both iterators. Returning `ControlFlow::Break(x)` short-circuits the iteration and
/// returns `ControlFlow::Break(x)`. If one of the iterators runs out of elements,
/// `ControlFlow::Continue(ord)` is returned where `ord` is the result of comparing the lengths of
diff --git a/library/core/src/iter/traits/marker.rs b/library/core/src/iter/traits/marker.rs
index da7537457..af0284823 100644
--- a/library/core/src/iter/traits/marker.rs
+++ b/library/core/src/iter/traits/marker.rs
@@ -31,6 +31,17 @@ impl<I: FusedIterator + ?Sized> FusedIterator for &mut I {}
/// The iterator must produce exactly the number of elements it reported
/// or diverge before reaching the end.
///
+/// # When *shouldn't* an adapter be `TrustedLen`?
+///
+/// If an adapter makes an iterator *shorter* by a given amount, then it's
+/// usually incorrect for that adapter to implement `TrustedLen`. The inner
+/// iterator might return more than `usize::MAX` items, but there's no way to
+/// know what `k` elements less than that will be, since the `size_hint` from
+/// the inner iterator has already saturated and lost that information.
+///
+/// This is why [`Skip<I>`](crate::iter::Skip) isn't `TrustedLen`, even when
+/// `I` implements `TrustedLen`.
+///
/// # Safety
///
/// This trait must only be implemented when the contract is upheld. Consumers
diff --git a/library/core/src/iter/traits/mod.rs b/library/core/src/iter/traits/mod.rs
index ed0fb634d..41ea29e6a 100644
--- a/library/core/src/iter/traits/mod.rs
+++ b/library/core/src/iter/traits/mod.rs
@@ -4,6 +4,7 @@ mod double_ended;
mod exact_size;
mod iterator;
mod marker;
+mod unchecked_iterator;
#[stable(feature = "rust1", since = "1.0.0")]
pub use self::{
@@ -19,3 +20,5 @@ pub use self::{
pub use self::marker::InPlaceIterable;
#[unstable(feature = "trusted_step", issue = "85731")]
pub use self::marker::TrustedStep;
+
+pub(crate) use self::unchecked_iterator::UncheckedIterator;
diff --git a/library/core/src/iter/traits/unchecked_iterator.rs b/library/core/src/iter/traits/unchecked_iterator.rs
new file mode 100644
index 000000000..ae4bfcad4
--- /dev/null
+++ b/library/core/src/iter/traits/unchecked_iterator.rs
@@ -0,0 +1,36 @@
+use crate::iter::TrustedLen;
+
+/// [`TrustedLen`] cannot have methods, so this allows augmenting it.
+///
+/// It currently requires `TrustedLen` because it's unclear whether it's
+/// reasonably possible to depend on the `size_hint` of anything else.
+pub(crate) trait UncheckedIterator: TrustedLen {
+ /// Gets the next item from a non-empty iterator.
+ ///
+ /// Because there's always a value to return, that means it can return
+ /// the `Item` type directly, without wrapping it in an `Option`.
+ ///
+ /// # Safety
+ ///
+ /// This can only be called if `size_hint().0 != 0`, guaranteeing that
+ /// there's at least one item available.
+ ///
+ /// Otherwise (aka when `size_hint().1 == Some(0)`), this is UB.
+ ///
+ /// # Note to Implementers
+ ///
+ /// This has a default implementation using [`Option::unwrap_unchecked`].
+ /// That's probably sufficient if your `next` *always* returns `Some`,
+ /// such as for infinite iterators. In more complicated situations, however,
+ /// sometimes there can still be `insertvalue`/`assume`/`extractvalue`
+ /// instructions remaining in the IR from the `Option` handling, at which
+ /// point you might want to implement this manually instead.
+ #[unstable(feature = "trusted_len_next_unchecked", issue = "37572")]
+ #[inline]
+ unsafe fn next_unchecked(&mut self) -> Self::Item {
+ let opt = self.next();
+ // SAFETY: The caller promised that we're not empty, and
+ // `Self: TrustedLen` so we can actually trust the `size_hint`.
+ unsafe { opt.unwrap_unchecked() }
+ }
+}
diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs
index 8790649ab..24bad799f 100644
--- a/library/core/src/lib.rs
+++ b/library/core/src/lib.rs
@@ -95,6 +95,7 @@
#![warn(missing_docs)]
#![allow(explicit_outlives_requirements)]
#![allow(incomplete_features)]
+#![cfg_attr(not(bootstrap), warn(multiple_supertrait_upcastable))]
//
// Library features:
#![feature(const_align_offset)]
@@ -123,6 +124,8 @@
#![feature(const_inherent_unchecked_arith)]
#![feature(const_int_unchecked_arith)]
#![feature(const_intrinsic_forget)]
+#![feature(const_ipv4)]
+#![feature(const_ipv6)]
#![feature(const_likely)]
#![feature(const_maybe_uninit_uninit_array)]
#![feature(const_maybe_uninit_as_mut_ptr)]
@@ -133,6 +136,7 @@
#![feature(const_option)]
#![feature(const_option_ext)]
#![feature(const_pin)]
+#![feature(const_pointer_byte_offsets)]
#![feature(const_pointer_is_aligned)]
#![feature(const_ptr_sub_ptr)]
#![feature(const_replace)]
@@ -178,6 +182,7 @@
#![feature(const_slice_index)]
#![feature(const_is_char_boundary)]
#![feature(const_cstr_methods)]
+#![feature(ip)]
#![feature(is_ascii_octdigit)]
//
// Language features:
@@ -191,8 +196,9 @@
#![feature(cfg_sanitize)]
#![feature(cfg_target_has_atomic)]
#![feature(cfg_target_has_atomic_equal_alignment)]
-#![cfg_attr(not(bootstrap), feature(const_closures))]
+#![feature(const_closures)]
#![feature(const_fn_floating_point_arithmetic)]
+#![feature(const_for)]
#![feature(const_mut_refs)]
#![feature(const_precise_live_drops)]
#![feature(const_refs_to_cell)]
@@ -235,11 +241,11 @@
#![feature(unsized_fn_params)]
#![feature(asm_const)]
#![feature(const_transmute_copy)]
+#![cfg_attr(not(bootstrap), feature(multiple_supertrait_upcastable))]
//
// Target features:
#![feature(arm_target_feature)]
#![feature(avx512_target_feature)]
-#![feature(cmpxchg16b_target_feature)]
#![feature(hexagon_target_feature)]
#![feature(mips_target_feature)]
#![feature(powerpc_target_feature)]
@@ -248,7 +254,7 @@
#![feature(sse4a_target_feature)]
#![feature(tbm_target_feature)]
#![feature(wasm_target_feature)]
-#![cfg_attr(bootstrap, feature(f16c_target_feature))]
+#![cfg_attr(bootstrap, feature(cmpxchg16b_target_feature))]
// allow using `core::` in intra-doc links
#[allow(unused_extern_crates)]
@@ -347,6 +353,7 @@ pub mod cell;
pub mod char;
pub mod ffi;
pub mod iter;
+pub mod net;
pub mod option;
pub mod panic;
pub mod panicking;
@@ -375,8 +382,6 @@ mod bool;
mod tuple;
mod unit;
-mod const_closure;
-
#[stable(feature = "core_primitive", since = "1.43.0")]
pub mod primitive;
diff --git a/library/core/src/marker.rs b/library/core/src/marker.rs
index 1326fc9ab..520ae0edb 100644
--- a/library/core/src/marker.rs
+++ b/library/core/src/marker.rs
@@ -97,6 +97,7 @@ unsafe impl<T: Sync + ?Sized> Send for &T {}
#[fundamental] // for Default, for example, which requires that `[T]: !Default` be evaluatable
#[rustc_specialization_trait]
#[rustc_deny_explicit_impl]
+#[cfg_attr(not(bootstrap), rustc_coinductive)]
pub trait Sized {
// Empty.
}
@@ -469,6 +470,62 @@ pub macro Copy($item:item) {
#[cfg_attr(not(test), rustc_diagnostic_item = "Sync")]
#[lang = "sync"]
#[rustc_on_unimplemented(
+ on(
+ _Self = "std::cell::OnceCell<T>",
+ note = "if you want to do aliasing and mutation between multiple threads, use `std::sync::OnceLock` instead"
+ ),
+ on(
+ _Self = "std::cell::Cell<u8>",
+ note = "if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` or `std::sync::atomic::AtomicU8` instead",
+ ),
+ on(
+ _Self = "std::cell::Cell<u16>",
+ note = "if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` or `std::sync::atomic::AtomicU16` instead",
+ ),
+ on(
+ _Self = "std::cell::Cell<u32>",
+ note = "if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` or `std::sync::atomic::AtomicU32` instead",
+ ),
+ on(
+ _Self = "std::cell::Cell<u64>",
+ note = "if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` or `std::sync::atomic::AtomicU64` instead",
+ ),
+ on(
+ _Self = "std::cell::Cell<usize>",
+ note = "if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` or `std::sync::atomic::AtomicUsize` instead",
+ ),
+ on(
+ _Self = "std::cell::Cell<i8>",
+ note = "if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` or `std::sync::atomic::AtomicI8` instead",
+ ),
+ on(
+ _Self = "std::cell::Cell<i16>",
+ note = "if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` or `std::sync::atomic::AtomicI16` instead",
+ ),
+ on(
+ _Self = "std::cell::Cell<i32>",
+ note = "if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` or `std::sync::atomic::AtomicI32` instead",
+ ),
+ on(
+ _Self = "std::cell::Cell<i64>",
+ note = "if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` or `std::sync::atomic::AtomicI64` instead",
+ ),
+ on(
+ _Self = "std::cell::Cell<isize>",
+ note = "if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` or `std::sync::atomic::AtomicIsize` instead",
+ ),
+ on(
+ _Self = "std::cell::Cell<bool>",
+ note = "if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` or `std::sync::atomic::AtomicBool` instead",
+ ),
+ on(
+ _Self = "std::cell::Cell<T>",
+ note = "if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock`",
+ ),
+ on(
+ _Self = "std::cell::RefCell<T>",
+ note = "if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` instead",
+ ),
message = "`{Self}` cannot be shared between threads safely",
label = "`{Self}` cannot be shared between threads safely"
)]
@@ -815,14 +872,18 @@ pub trait Destruct {}
#[rustc_deny_explicit_impl]
pub trait Tuple {}
-/// A marker for things
-#[unstable(feature = "pointer_sized_trait", issue = "none")]
-#[lang = "pointer_sized"]
+/// A marker for pointer-like types.
+///
+/// All types that have the same size and alignment as a `usize` or
+/// `*const ()` automatically implement this trait.
+#[unstable(feature = "pointer_like_trait", issue = "none")]
+#[cfg_attr(bootstrap, lang = "pointer_sized")]
+#[cfg_attr(not(bootstrap), lang = "pointer_like")]
#[rustc_on_unimplemented(
- message = "`{Self}` needs to be a pointer-sized type",
- label = "`{Self}` needs to be a pointer-sized type"
+ message = "`{Self}` needs to have the same alignment and size as a pointer",
+ label = "`{Self}` needs to be a pointer-like type"
)]
-pub trait PointerSized {}
+pub trait PointerLike {}
/// Implementations of `Copy` for primitive types.
///
diff --git a/library/core/src/mem/mod.rs b/library/core/src/mem/mod.rs
index 5e01ccc07..a67df7ed5 100644
--- a/library/core/src/mem/mod.rs
+++ b/library/core/src/mem/mod.rs
@@ -682,7 +682,6 @@ pub unsafe fn zeroed<T>() -> T {
pub unsafe fn uninitialized<T>() -> T {
// SAFETY: the caller must guarantee that an uninitialized value is valid for `T`.
unsafe {
- #[cfg(not(bootstrap))] // If the compiler hits this itself then it deserves the UB.
intrinsics::assert_mem_uninitialized_valid::<T>();
let mut val = MaybeUninit::<T>::uninit();
diff --git a/library/std/src/net/display_buffer.rs b/library/core/src/net/display_buffer.rs
index 7aadf06e9..7aadf06e9 100644
--- a/library/std/src/net/display_buffer.rs
+++ b/library/core/src/net/display_buffer.rs
diff --git a/library/core/src/net/ip_addr.rs b/library/core/src/net/ip_addr.rs
new file mode 100644
index 000000000..954d88d54
--- /dev/null
+++ b/library/core/src/net/ip_addr.rs
@@ -0,0 +1,2070 @@
+use crate::cmp::Ordering;
+use crate::fmt::{self, Write};
+use crate::mem::transmute;
+
+use super::display_buffer::DisplayBuffer;
+
+/// An IP address, either IPv4 or IPv6.
+///
+/// This enum can contain either an [`Ipv4Addr`] or an [`Ipv6Addr`], see their
+/// respective documentation for more details.
+///
+/// # Examples
+///
+/// ```
+/// use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
+///
+/// let localhost_v4 = IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1));
+/// let localhost_v6 = IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1));
+///
+/// assert_eq!("127.0.0.1".parse(), Ok(localhost_v4));
+/// assert_eq!("::1".parse(), Ok(localhost_v6));
+///
+/// assert_eq!(localhost_v4.is_ipv6(), false);
+/// assert_eq!(localhost_v4.is_ipv4(), true);
+/// ```
+#[cfg_attr(not(test), rustc_diagnostic_item = "IpAddr")]
+#[stable(feature = "ip_addr", since = "1.7.0")]
+#[derive(Copy, Clone, Eq, PartialEq, Hash, PartialOrd, Ord)]
+pub enum IpAddr {
+ /// An IPv4 address.
+ #[stable(feature = "ip_addr", since = "1.7.0")]
+ V4(#[stable(feature = "ip_addr", since = "1.7.0")] Ipv4Addr),
+ /// An IPv6 address.
+ #[stable(feature = "ip_addr", since = "1.7.0")]
+ V6(#[stable(feature = "ip_addr", since = "1.7.0")] Ipv6Addr),
+}
+
+/// An IPv4 address.
+///
+/// IPv4 addresses are defined as 32-bit integers in [IETF RFC 791].
+/// They are usually represented as four octets.
+///
+/// See [`IpAddr`] for a type encompassing both IPv4 and IPv6 addresses.
+///
+/// [IETF RFC 791]: https://tools.ietf.org/html/rfc791
+///
+/// # Textual representation
+///
+/// `Ipv4Addr` provides a [`FromStr`] implementation. The four octets are in decimal
+/// notation, divided by `.` (this is called "dot-decimal notation").
+/// Notably, octal numbers (which are indicated with a leading `0`) and hexadecimal numbers (which
+/// are indicated with a leading `0x`) are not allowed per [IETF RFC 6943].
+///
+/// [IETF RFC 6943]: https://tools.ietf.org/html/rfc6943#section-3.1.1
+/// [`FromStr`]: crate::str::FromStr
+///
+/// # Examples
+///
+/// ```
+/// use std::net::Ipv4Addr;
+///
+/// let localhost = Ipv4Addr::new(127, 0, 0, 1);
+/// assert_eq!("127.0.0.1".parse(), Ok(localhost));
+/// assert_eq!(localhost.is_loopback(), true);
+/// assert!("012.004.002.000".parse::<Ipv4Addr>().is_err()); // all octets are in octal
+/// assert!("0000000.0.0.0".parse::<Ipv4Addr>().is_err()); // first octet is a zero in octal
+/// assert!("0xcb.0x0.0x71.0x00".parse::<Ipv4Addr>().is_err()); // all octets are in hex
+/// ```
+#[derive(Copy, Clone, PartialEq, Eq, Hash)]
+#[stable(feature = "rust1", since = "1.0.0")]
+pub struct Ipv4Addr {
+ octets: [u8; 4],
+}
+
+/// An IPv6 address.
+///
+/// IPv6 addresses are defined as 128-bit integers in [IETF RFC 4291].
+/// They are usually represented as eight 16-bit segments.
+///
+/// [IETF RFC 4291]: https://tools.ietf.org/html/rfc4291
+///
+/// # Embedding IPv4 Addresses
+///
+/// See [`IpAddr`] for a type encompassing both IPv4 and IPv6 addresses.
+///
+/// To assist in the transition from IPv4 to IPv6 two types of IPv6 addresses that embed an IPv4 address were defined:
+/// IPv4-compatible and IPv4-mapped addresses. Of these IPv4-compatible addresses have been officially deprecated.
+///
+/// Both types of addresses are not assigned any special meaning by this implementation,
+/// other than what the relevant standards prescribe. This means that an address like `::ffff:127.0.0.1`,
+/// while representing an IPv4 loopback address, is not itself an IPv6 loopback address; only `::1` is.
+/// To handle these so called "IPv4-in-IPv6" addresses, they have to first be converted to their canonical IPv4 address.
+///
+/// ### IPv4-Compatible IPv6 Addresses
+///
+/// IPv4-compatible IPv6 addresses are defined in [IETF RFC 4291 Section 2.5.5.1], and have been officially deprecated.
+/// The RFC describes the format of an "IPv4-Compatible IPv6 address" as follows:
+///
+/// ```text
+/// | 80 bits | 16 | 32 bits |
+/// +--------------------------------------+--------------------------+
+/// |0000..............................0000|0000| IPv4 address |
+/// +--------------------------------------+----+---------------------+
+/// ```
+/// So `::a.b.c.d` would be an IPv4-compatible IPv6 address representing the IPv4 address `a.b.c.d`.
+///
+/// To convert from an IPv4 address to an IPv4-compatible IPv6 address, use [`Ipv4Addr::to_ipv6_compatible`].
+/// Use [`Ipv6Addr::to_ipv4`] to convert an IPv4-compatible IPv6 address to the canonical IPv4 address.
+///
+/// [IETF RFC 4291 Section 2.5.5.1]: https://datatracker.ietf.org/doc/html/rfc4291#section-2.5.5.1
+///
+/// ### IPv4-Mapped IPv6 Addresses
+///
+/// IPv4-mapped IPv6 addresses are defined in [IETF RFC 4291 Section 2.5.5.2].
+/// The RFC describes the format of an "IPv4-Mapped IPv6 address" as follows:
+///
+/// ```text
+/// | 80 bits | 16 | 32 bits |
+/// +--------------------------------------+--------------------------+
+/// |0000..............................0000|FFFF| IPv4 address |
+/// +--------------------------------------+----+---------------------+
+/// ```
+/// So `::ffff:a.b.c.d` would be an IPv4-mapped IPv6 address representing the IPv4 address `a.b.c.d`.
+///
+/// To convert from an IPv4 address to an IPv4-mapped IPv6 address, use [`Ipv4Addr::to_ipv6_mapped`].
+/// Use [`Ipv6Addr::to_ipv4`] to convert an IPv4-mapped IPv6 address to the canonical IPv4 address.
+/// Note that this will also convert the IPv6 loopback address `::1` to `0.0.0.1`. Use
+/// [`Ipv6Addr::to_ipv4_mapped`] to avoid this.
+///
+/// [IETF RFC 4291 Section 2.5.5.2]: https://datatracker.ietf.org/doc/html/rfc4291#section-2.5.5.2
+///
+/// # Textual representation
+///
+/// `Ipv6Addr` provides a [`FromStr`] implementation. There are many ways to represent
+/// an IPv6 address in text, but in general, each segments is written in hexadecimal
+/// notation, and segments are separated by `:`. For more information, see
+/// [IETF RFC 5952].
+///
+/// [`FromStr`]: crate::str::FromStr
+/// [IETF RFC 5952]: https://tools.ietf.org/html/rfc5952
+///
+/// # Examples
+///
+/// ```
+/// use std::net::Ipv6Addr;
+///
+/// let localhost = Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1);
+/// assert_eq!("::1".parse(), Ok(localhost));
+/// assert_eq!(localhost.is_loopback(), true);
+/// ```
+#[derive(Copy, Clone, PartialEq, Eq, Hash)]
+#[stable(feature = "rust1", since = "1.0.0")]
+pub struct Ipv6Addr {
+ octets: [u8; 16],
+}
+
+/// Scope of an [IPv6 multicast address] as defined in [IETF RFC 7346 section 2].
+///
+/// # Stability Guarantees
+///
+/// Not all possible values for a multicast scope have been assigned.
+/// Future RFCs may introduce new scopes, which will be added as variants to this enum;
+/// because of this the enum is marked as `#[non_exhaustive]`.
+///
+/// # Examples
+/// ```
+/// #![feature(ip)]
+///
+/// use std::net::Ipv6Addr;
+/// use std::net::Ipv6MulticastScope::*;
+///
+/// // An IPv6 multicast address with global scope (`ff0e::`).
+/// let address = Ipv6Addr::new(0xff0e, 0, 0, 0, 0, 0, 0, 0);
+///
+/// // Will print "Global scope".
+/// match address.multicast_scope() {
+/// Some(InterfaceLocal) => println!("Interface-Local scope"),
+/// Some(LinkLocal) => println!("Link-Local scope"),
+/// Some(RealmLocal) => println!("Realm-Local scope"),
+/// Some(AdminLocal) => println!("Admin-Local scope"),
+/// Some(SiteLocal) => println!("Site-Local scope"),
+/// Some(OrganizationLocal) => println!("Organization-Local scope"),
+/// Some(Global) => println!("Global scope"),
+/// Some(_) => println!("Unknown scope"),
+/// None => println!("Not a multicast address!")
+/// }
+///
+/// ```
+///
+/// [IPv6 multicast address]: Ipv6Addr
+/// [IETF RFC 7346 section 2]: https://tools.ietf.org/html/rfc7346#section-2
+#[derive(Copy, PartialEq, Eq, Clone, Hash, Debug)]
+#[unstable(feature = "ip", issue = "27709")]
+#[non_exhaustive]
+pub enum Ipv6MulticastScope {
+ /// Interface-Local scope.
+ InterfaceLocal,
+ /// Link-Local scope.
+ LinkLocal,
+ /// Realm-Local scope.
+ RealmLocal,
+ /// Admin-Local scope.
+ AdminLocal,
+ /// Site-Local scope.
+ SiteLocal,
+ /// Organization-Local scope.
+ OrganizationLocal,
+ /// Global scope.
+ Global,
+}
+
+impl IpAddr {
+ /// Returns [`true`] for the special 'unspecified' address.
+ ///
+ /// See the documentation for [`Ipv4Addr::is_unspecified()`] and
+ /// [`Ipv6Addr::is_unspecified()`] for more details.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
+ ///
+ /// assert_eq!(IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0)).is_unspecified(), true);
+ /// assert_eq!(IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0)).is_unspecified(), true);
+ /// ```
+ #[rustc_const_stable(feature = "const_ip_50", since = "1.50.0")]
+ #[stable(feature = "ip_shared", since = "1.12.0")]
+ #[must_use]
+ #[inline]
+ pub const fn is_unspecified(&self) -> bool {
+ match self {
+ IpAddr::V4(ip) => ip.is_unspecified(),
+ IpAddr::V6(ip) => ip.is_unspecified(),
+ }
+ }
+
+ /// Returns [`true`] if this is a loopback address.
+ ///
+ /// See the documentation for [`Ipv4Addr::is_loopback()`] and
+ /// [`Ipv6Addr::is_loopback()`] for more details.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
+ ///
+ /// assert_eq!(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)).is_loopback(), true);
+ /// assert_eq!(IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0x1)).is_loopback(), true);
+ /// ```
+ #[rustc_const_stable(feature = "const_ip_50", since = "1.50.0")]
+ #[stable(feature = "ip_shared", since = "1.12.0")]
+ #[must_use]
+ #[inline]
+ pub const fn is_loopback(&self) -> bool {
+ match self {
+ IpAddr::V4(ip) => ip.is_loopback(),
+ IpAddr::V6(ip) => ip.is_loopback(),
+ }
+ }
+
+ /// Returns [`true`] if the address appears to be globally routable.
+ ///
+ /// See the documentation for [`Ipv4Addr::is_global()`] and
+ /// [`Ipv6Addr::is_global()`] for more details.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(ip)]
+ ///
+ /// use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
+ ///
+ /// assert_eq!(IpAddr::V4(Ipv4Addr::new(80, 9, 12, 3)).is_global(), true);
+ /// assert_eq!(IpAddr::V6(Ipv6Addr::new(0, 0, 0x1c9, 0, 0, 0xafc8, 0, 0x1)).is_global(), true);
+ /// ```
+ #[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 {
+ IpAddr::V4(ip) => ip.is_global(),
+ IpAddr::V6(ip) => ip.is_global(),
+ }
+ }
+
+ /// Returns [`true`] if this is a multicast address.
+ ///
+ /// See the documentation for [`Ipv4Addr::is_multicast()`] and
+ /// [`Ipv6Addr::is_multicast()`] for more details.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
+ ///
+ /// assert_eq!(IpAddr::V4(Ipv4Addr::new(224, 254, 0, 0)).is_multicast(), true);
+ /// assert_eq!(IpAddr::V6(Ipv6Addr::new(0xff00, 0, 0, 0, 0, 0, 0, 0)).is_multicast(), true);
+ /// ```
+ #[rustc_const_stable(feature = "const_ip_50", since = "1.50.0")]
+ #[stable(feature = "ip_shared", since = "1.12.0")]
+ #[must_use]
+ #[inline]
+ pub const fn is_multicast(&self) -> bool {
+ match self {
+ IpAddr::V4(ip) => ip.is_multicast(),
+ IpAddr::V6(ip) => ip.is_multicast(),
+ }
+ }
+
+ /// Returns [`true`] if this address is in a range designated for documentation.
+ ///
+ /// See the documentation for [`Ipv4Addr::is_documentation()`] and
+ /// [`Ipv6Addr::is_documentation()`] for more details.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(ip)]
+ ///
+ /// use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
+ ///
+ /// assert_eq!(IpAddr::V4(Ipv4Addr::new(203, 0, 113, 6)).is_documentation(), true);
+ /// assert_eq!(
+ /// IpAddr::V6(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0)).is_documentation(),
+ /// true
+ /// );
+ /// ```
+ #[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 {
+ IpAddr::V4(ip) => ip.is_documentation(),
+ IpAddr::V6(ip) => ip.is_documentation(),
+ }
+ }
+
+ /// 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.
+ ///
+ /// [`IPv4` address]: IpAddr::V4
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
+ ///
+ /// assert_eq!(IpAddr::V4(Ipv4Addr::new(203, 0, 113, 6)).is_ipv4(), true);
+ /// assert_eq!(IpAddr::V6(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0)).is_ipv4(), false);
+ /// ```
+ #[rustc_const_stable(feature = "const_ip_50", 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(_))
+ }
+
+ /// Returns [`true`] if this address is an [`IPv6` address], and [`false`]
+ /// otherwise.
+ ///
+ /// [`IPv6` address]: IpAddr::V6
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
+ ///
+ /// assert_eq!(IpAddr::V4(Ipv4Addr::new(203, 0, 113, 6)).is_ipv6(), false);
+ /// assert_eq!(IpAddr::V6(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0)).is_ipv6(), true);
+ /// ```
+ #[rustc_const_stable(feature = "const_ip_50", 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(_))
+ }
+
+ /// Converts this address to an `IpAddr::V4` if it is an IPv4-mapped IPv6 addresses, otherwise it
+ /// return `self` as-is.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(ip)]
+ /// use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
+ ///
+ /// assert_eq!(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)).to_canonical().is_loopback(), true);
+ /// assert_eq!(IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0x7f00, 0x1)).is_loopback(), false);
+ /// 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 {
+ match self {
+ &v4 @ IpAddr::V4(_) => v4,
+ IpAddr::V6(v6) => v6.to_canonical(),
+ }
+ }
+}
+
+impl Ipv4Addr {
+ /// Creates a new IPv4 address from four eight-bit octets.
+ ///
+ /// The result will represent the IP address `a`.`b`.`c`.`d`.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::net::Ipv4Addr;
+ ///
+ /// let addr = Ipv4Addr::new(127, 0, 0, 1);
+ /// ```
+ #[rustc_const_stable(feature = "const_ip_32", 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 {
+ Ipv4Addr { octets: [a, b, c, d] }
+ }
+
+ /// An IPv4 address with the address pointing to localhost: `127.0.0.1`
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::net::Ipv4Addr;
+ ///
+ /// let addr = Ipv4Addr::LOCALHOST;
+ /// assert_eq!(addr, Ipv4Addr::new(127, 0, 0, 1));
+ /// ```
+ #[stable(feature = "ip_constructors", since = "1.30.0")]
+ pub const LOCALHOST: Self = Ipv4Addr::new(127, 0, 0, 1);
+
+ /// An IPv4 address representing an unspecified address: `0.0.0.0`
+ ///
+ /// This corresponds to the constant `INADDR_ANY` in other languages.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::net::Ipv4Addr;
+ ///
+ /// let addr = Ipv4Addr::UNSPECIFIED;
+ /// assert_eq!(addr, Ipv4Addr::new(0, 0, 0, 0));
+ /// ```
+ #[doc(alias = "INADDR_ANY")]
+ #[stable(feature = "ip_constructors", since = "1.30.0")]
+ pub const UNSPECIFIED: Self = Ipv4Addr::new(0, 0, 0, 0);
+
+ /// An IPv4 address representing the broadcast address: `255.255.255.255`
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::net::Ipv4Addr;
+ ///
+ /// let addr = Ipv4Addr::BROADCAST;
+ /// assert_eq!(addr, Ipv4Addr::new(255, 255, 255, 255));
+ /// ```
+ #[stable(feature = "ip_constructors", since = "1.30.0")]
+ pub const BROADCAST: Self = Ipv4Addr::new(255, 255, 255, 255);
+
+ /// Returns the four eight-bit integers that make up this address.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::net::Ipv4Addr;
+ ///
+ /// let addr = Ipv4Addr::new(127, 0, 0, 1);
+ /// assert_eq!(addr.octets(), [127, 0, 0, 1]);
+ /// ```
+ #[rustc_const_stable(feature = "const_ip_50", since = "1.50.0")]
+ #[stable(feature = "rust1", since = "1.0.0")]
+ #[must_use]
+ #[inline]
+ pub const fn octets(&self) -> [u8; 4] {
+ self.octets
+ }
+
+ /// Returns [`true`] for the special 'unspecified' address (`0.0.0.0`).
+ ///
+ /// This property is defined in _UNIX Network Programming, Second Edition_,
+ /// W. Richard Stevens, p. 891; see also [ip7].
+ ///
+ /// [ip7]: https://man7.org/linux/man-pages/man7/ip.7.html
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::net::Ipv4Addr;
+ ///
+ /// assert_eq!(Ipv4Addr::new(0, 0, 0, 0).is_unspecified(), true);
+ /// assert_eq!(Ipv4Addr::new(45, 22, 13, 197).is_unspecified(), false);
+ /// ```
+ #[rustc_const_stable(feature = "const_ip_32", since = "1.32.0")]
+ #[stable(feature = "ip_shared", since = "1.12.0")]
+ #[must_use]
+ #[inline]
+ pub const fn is_unspecified(&self) -> bool {
+ u32::from_be_bytes(self.octets) == 0
+ }
+
+ /// Returns [`true`] if this is a loopback address (`127.0.0.0/8`).
+ ///
+ /// This property is defined by [IETF RFC 1122].
+ ///
+ /// [IETF RFC 1122]: https://tools.ietf.org/html/rfc1122
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::net::Ipv4Addr;
+ ///
+ /// assert_eq!(Ipv4Addr::new(127, 0, 0, 1).is_loopback(), true);
+ /// assert_eq!(Ipv4Addr::new(45, 22, 13, 197).is_loopback(), false);
+ /// ```
+ #[rustc_const_stable(feature = "const_ip_50", 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
+ }
+
+ /// Returns [`true`] if this is a private address.
+ ///
+ /// The private address ranges are defined in [IETF RFC 1918] and include:
+ ///
+ /// - `10.0.0.0/8`
+ /// - `172.16.0.0/12`
+ /// - `192.168.0.0/16`
+ ///
+ /// [IETF RFC 1918]: https://tools.ietf.org/html/rfc1918
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::net::Ipv4Addr;
+ ///
+ /// assert_eq!(Ipv4Addr::new(10, 0, 0, 1).is_private(), true);
+ /// assert_eq!(Ipv4Addr::new(10, 10, 10, 10).is_private(), true);
+ /// assert_eq!(Ipv4Addr::new(172, 16, 10, 10).is_private(), true);
+ /// assert_eq!(Ipv4Addr::new(172, 29, 45, 14).is_private(), true);
+ /// assert_eq!(Ipv4Addr::new(172, 32, 0, 2).is_private(), false);
+ /// assert_eq!(Ipv4Addr::new(192, 168, 0, 2).is_private(), true);
+ /// assert_eq!(Ipv4Addr::new(192, 169, 0, 2).is_private(), false);
+ /// ```
+ #[rustc_const_stable(feature = "const_ip_50", 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() {
+ [10, ..] => true,
+ [172, b, ..] if b >= 16 && b <= 31 => true,
+ [192, 168, ..] => true,
+ _ => false,
+ }
+ }
+
+ /// Returns [`true`] if the address is link-local (`169.254.0.0/16`).
+ ///
+ /// This property is defined by [IETF RFC 3927].
+ ///
+ /// [IETF RFC 3927]: https://tools.ietf.org/html/rfc3927
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::net::Ipv4Addr;
+ ///
+ /// assert_eq!(Ipv4Addr::new(169, 254, 0, 0).is_link_local(), true);
+ /// assert_eq!(Ipv4Addr::new(169, 254, 10, 65).is_link_local(), true);
+ /// assert_eq!(Ipv4Addr::new(16, 89, 10, 65).is_link_local(), false);
+ /// ```
+ #[rustc_const_stable(feature = "const_ip_50", 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, ..])
+ }
+
+ /// Returns [`true`] if the address appears to be globally reachable
+ /// as specified by the [IANA IPv4 Special-Purpose Address Registry].
+ /// Whether or not an address is practically reachable will depend on your network configuration.
+ ///
+ /// Most IPv4 addresses are globally reachable;
+ /// unless they are specifically defined as *not* globally reachable.
+ ///
+ /// Non-exhaustive list of notable addresses that are not globally reachable:
+ ///
+ /// - The [unspecified address] ([`is_unspecified`](Ipv4Addr::is_unspecified))
+ /// - Addresses reserved for private use ([`is_private`](Ipv4Addr::is_private))
+ /// - Addresses in the shared address space ([`is_shared`](Ipv4Addr::is_shared))
+ /// - Loopback addresses ([`is_loopback`](Ipv4Addr::is_loopback))
+ /// - Link-local addresses ([`is_link_local`](Ipv4Addr::is_link_local))
+ /// - Addresses reserved for documentation ([`is_documentation`](Ipv4Addr::is_documentation))
+ /// - Addresses reserved for benchmarking ([`is_benchmarking`](Ipv4Addr::is_benchmarking))
+ /// - Reserved addresses ([`is_reserved`](Ipv4Addr::is_reserved))
+ /// - The [broadcast address] ([`is_broadcast`](Ipv4Addr::is_broadcast))
+ ///
+ /// For the complete overview of which addresses are globally reachable, see the table at the [IANA IPv4 Special-Purpose Address Registry].
+ ///
+ /// [IANA IPv4 Special-Purpose Address Registry]: https://www.iana.org/assignments/iana-ipv4-special-registry/iana-ipv4-special-registry.xhtml
+ /// [unspecified address]: Ipv4Addr::UNSPECIFIED
+ /// [broadcast address]: Ipv4Addr::BROADCAST
+
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(ip)]
+ ///
+ /// use std::net::Ipv4Addr;
+ ///
+ /// // Most IPv4 addresses are globally reachable:
+ /// assert_eq!(Ipv4Addr::new(80, 9, 12, 3).is_global(), true);
+ ///
+ /// // However some addresses have been assigned a special meaning
+ /// // that makes them not globally reachable. Some examples are:
+ ///
+ /// // The unspecified address (`0.0.0.0`)
+ /// assert_eq!(Ipv4Addr::UNSPECIFIED.is_global(), false);
+ ///
+ /// // Addresses reserved for private use (`10.0.0.0/8`, `172.16.0.0/12`, 192.168.0.0/16)
+ /// assert_eq!(Ipv4Addr::new(10, 254, 0, 0).is_global(), false);
+ /// assert_eq!(Ipv4Addr::new(192, 168, 10, 65).is_global(), false);
+ /// assert_eq!(Ipv4Addr::new(172, 16, 10, 65).is_global(), false);
+ ///
+ /// // Addresses in the shared address space (`100.64.0.0/10`)
+ /// assert_eq!(Ipv4Addr::new(100, 100, 0, 0).is_global(), false);
+ ///
+ /// // The loopback addresses (`127.0.0.0/8`)
+ /// assert_eq!(Ipv4Addr::LOCALHOST.is_global(), false);
+ ///
+ /// // Link-local addresses (`169.254.0.0/16`)
+ /// assert_eq!(Ipv4Addr::new(169, 254, 45, 1).is_global(), false);
+ ///
+ /// // Addresses reserved for documentation (`192.0.2.0/24`, `198.51.100.0/24`, `203.0.113.0/24`)
+ /// assert_eq!(Ipv4Addr::new(192, 0, 2, 255).is_global(), false);
+ /// assert_eq!(Ipv4Addr::new(198, 51, 100, 65).is_global(), false);
+ /// assert_eq!(Ipv4Addr::new(203, 0, 113, 6).is_global(), false);
+ ///
+ /// // Addresses reserved for benchmarking (`198.18.0.0/15`)
+ /// assert_eq!(Ipv4Addr::new(198, 18, 0, 0).is_global(), false);
+ ///
+ /// // Reserved addresses (`240.0.0.0/4`)
+ /// assert_eq!(Ipv4Addr::new(250, 10, 20, 30).is_global(), false);
+ ///
+ /// // The broadcast address (`255.255.255.255`)
+ /// assert_eq!(Ipv4Addr::BROADCAST.is_global(), false);
+ ///
+ /// // For a complete overview see the IANA IPv4 Special-Purpose Address Registry.
+ /// ```
+ #[rustc_const_unstable(feature = "const_ipv4", issue = "76205")]
+ #[unstable(feature = "ip", issue = "27709")]
+ #[must_use]
+ #[inline]
+ pub const fn is_global(&self) -> bool {
+ !(self.octets()[0] == 0 // "This network"
+ || self.is_private()
+ || self.is_shared()
+ || self.is_loopback()
+ || self.is_link_local()
+ // addresses reserved for future protocols (`192.0.0.0/24`)
+ ||(self.octets()[0] == 192 && self.octets()[1] == 0 && self.octets()[2] == 0)
+ || self.is_documentation()
+ || self.is_benchmarking()
+ || self.is_reserved()
+ || self.is_broadcast())
+ }
+
+ /// Returns [`true`] if this address is part of the Shared Address Space defined in
+ /// [IETF RFC 6598] (`100.64.0.0/10`).
+ ///
+ /// [IETF RFC 6598]: https://tools.ietf.org/html/rfc6598
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(ip)]
+ /// use std::net::Ipv4Addr;
+ ///
+ /// assert_eq!(Ipv4Addr::new(100, 64, 0, 0).is_shared(), true);
+ /// assert_eq!(Ipv4Addr::new(100, 127, 255, 255).is_shared(), true);
+ /// assert_eq!(Ipv4Addr::new(100, 128, 0, 0).is_shared(), false);
+ /// ```
+ #[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)
+ }
+
+ /// Returns [`true`] if this address part of the `198.18.0.0/15` range, which is reserved for
+ /// network devices benchmarking. This range is defined in [IETF RFC 2544] as `192.18.0.0`
+ /// through `198.19.255.255` but [errata 423] corrects it to `198.18.0.0/15`.
+ ///
+ /// [IETF RFC 2544]: https://tools.ietf.org/html/rfc2544
+ /// [errata 423]: https://www.rfc-editor.org/errata/eid423
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(ip)]
+ /// use std::net::Ipv4Addr;
+ ///
+ /// assert_eq!(Ipv4Addr::new(198, 17, 255, 255).is_benchmarking(), false);
+ /// assert_eq!(Ipv4Addr::new(198, 18, 0, 0).is_benchmarking(), true);
+ /// assert_eq!(Ipv4Addr::new(198, 19, 255, 255).is_benchmarking(), true);
+ /// assert_eq!(Ipv4Addr::new(198, 20, 0, 0).is_benchmarking(), false);
+ /// ```
+ #[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
+ }
+
+ /// Returns [`true`] if this address is reserved by IANA for future use. [IETF RFC 1112]
+ /// defines the block of reserved addresses as `240.0.0.0/4`. This range normally includes the
+ /// broadcast address `255.255.255.255`, but this implementation explicitly excludes it, since
+ /// it is obviously not reserved for future use.
+ ///
+ /// [IETF RFC 1112]: https://tools.ietf.org/html/rfc1112
+ ///
+ /// # Warning
+ ///
+ /// As IANA assigns new addresses, this method will be
+ /// updated. This may result in non-reserved addresses being
+ /// treated as reserved in code that relies on an outdated version
+ /// of this method.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(ip)]
+ /// use std::net::Ipv4Addr;
+ ///
+ /// assert_eq!(Ipv4Addr::new(240, 0, 0, 0).is_reserved(), true);
+ /// assert_eq!(Ipv4Addr::new(255, 255, 255, 254).is_reserved(), true);
+ ///
+ /// assert_eq!(Ipv4Addr::new(239, 255, 255, 255).is_reserved(), false);
+ /// // The broadcast address is not considered as reserved for future use by this implementation
+ /// assert_eq!(Ipv4Addr::new(255, 255, 255, 255).is_reserved(), false);
+ /// ```
+ #[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()
+ }
+
+ /// Returns [`true`] if this is a multicast address (`224.0.0.0/4`).
+ ///
+ /// Multicast addresses have a most significant octet between `224` and `239`,
+ /// and is defined by [IETF RFC 5771].
+ ///
+ /// [IETF RFC 5771]: https://tools.ietf.org/html/rfc5771
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::net::Ipv4Addr;
+ ///
+ /// assert_eq!(Ipv4Addr::new(224, 254, 0, 0).is_multicast(), true);
+ /// assert_eq!(Ipv4Addr::new(236, 168, 10, 65).is_multicast(), true);
+ /// assert_eq!(Ipv4Addr::new(172, 16, 10, 65).is_multicast(), false);
+ /// ```
+ #[rustc_const_stable(feature = "const_ip_50", 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
+ }
+
+ /// Returns [`true`] if this is a broadcast address (`255.255.255.255`).
+ ///
+ /// A broadcast address has all octets set to `255` as defined in [IETF RFC 919].
+ ///
+ /// [IETF RFC 919]: https://tools.ietf.org/html/rfc919
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::net::Ipv4Addr;
+ ///
+ /// assert_eq!(Ipv4Addr::new(255, 255, 255, 255).is_broadcast(), true);
+ /// assert_eq!(Ipv4Addr::new(236, 168, 10, 65).is_broadcast(), false);
+ /// ```
+ #[rustc_const_stable(feature = "const_ip_50", 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())
+ }
+
+ /// Returns [`true`] if this address is in a range designated for documentation.
+ ///
+ /// This is defined in [IETF RFC 5737]:
+ ///
+ /// - `192.0.2.0/24` (TEST-NET-1)
+ /// - `198.51.100.0/24` (TEST-NET-2)
+ /// - `203.0.113.0/24` (TEST-NET-3)
+ ///
+ /// [IETF RFC 5737]: https://tools.ietf.org/html/rfc5737
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::net::Ipv4Addr;
+ ///
+ /// assert_eq!(Ipv4Addr::new(192, 0, 2, 255).is_documentation(), true);
+ /// assert_eq!(Ipv4Addr::new(198, 51, 100, 65).is_documentation(), true);
+ /// assert_eq!(Ipv4Addr::new(203, 0, 113, 6).is_documentation(), true);
+ /// assert_eq!(Ipv4Addr::new(193, 34, 17, 19).is_documentation(), false);
+ /// ```
+ #[rustc_const_stable(feature = "const_ip_50", since = "1.50.0")]
+ #[stable(since = "1.7.0", feature = "ip_17")]
+ #[must_use]
+ #[inline]
+ pub const fn is_documentation(&self) -> bool {
+ matches!(self.octets(), [192, 0, 2, _] | [198, 51, 100, _] | [203, 0, 113, _])
+ }
+
+ /// Converts this address to an [IPv4-compatible] [`IPv6` address].
+ ///
+ /// `a.b.c.d` becomes `::a.b.c.d`
+ ///
+ /// Note that IPv4-compatible addresses have been officially deprecated.
+ /// If you don't explicitly need an IPv4-compatible address for legacy reasons, consider using `to_ipv6_mapped` instead.
+ ///
+ /// [IPv4-compatible]: Ipv6Addr#ipv4-compatible-ipv6-addresses
+ /// [`IPv6` address]: Ipv6Addr
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::net::{Ipv4Addr, Ipv6Addr};
+ ///
+ /// assert_eq!(
+ /// Ipv4Addr::new(192, 0, 2, 255).to_ipv6_compatible(),
+ /// Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0xc000, 0x2ff)
+ /// );
+ /// ```
+ #[rustc_const_stable(feature = "const_ip_50", 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();
+ Ipv6Addr { octets: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, a, b, c, d] }
+ }
+
+ /// Converts this address to an [IPv4-mapped] [`IPv6` address].
+ ///
+ /// `a.b.c.d` becomes `::ffff:a.b.c.d`
+ ///
+ /// [IPv4-mapped]: Ipv6Addr#ipv4-mapped-ipv6-addresses
+ /// [`IPv6` address]: Ipv6Addr
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::net::{Ipv4Addr, Ipv6Addr};
+ ///
+ /// assert_eq!(Ipv4Addr::new(192, 0, 2, 255).to_ipv6_mapped(),
+ /// Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc000, 0x2ff));
+ /// ```
+ #[rustc_const_stable(feature = "const_ip_50", 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();
+ Ipv6Addr { octets: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF, a, b, c, d] }
+ }
+}
+
+#[stable(feature = "ip_addr", since = "1.7.0")]
+impl fmt::Display for IpAddr {
+ fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
+ match self {
+ IpAddr::V4(ip) => ip.fmt(fmt),
+ IpAddr::V6(ip) => ip.fmt(fmt),
+ }
+ }
+}
+
+#[stable(feature = "ip_addr", since = "1.7.0")]
+impl fmt::Debug for IpAddr {
+ fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
+ fmt::Display::fmt(self, fmt)
+ }
+}
+
+#[stable(feature = "ip_from_ip", since = "1.16.0")]
+impl From<Ipv4Addr> for IpAddr {
+ /// Copies this address to a new `IpAddr::V4`.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::net::{IpAddr, Ipv4Addr};
+ ///
+ /// let addr = Ipv4Addr::new(127, 0, 0, 1);
+ ///
+ /// assert_eq!(
+ /// IpAddr::V4(addr),
+ /// IpAddr::from(addr)
+ /// )
+ /// ```
+ #[inline]
+ fn from(ipv4: Ipv4Addr) -> IpAddr {
+ IpAddr::V4(ipv4)
+ }
+}
+
+#[stable(feature = "ip_from_ip", since = "1.16.0")]
+impl From<Ipv6Addr> for IpAddr {
+ /// Copies this address to a new `IpAddr::V6`.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::net::{IpAddr, Ipv6Addr};
+ ///
+ /// let addr = Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff);
+ ///
+ /// assert_eq!(
+ /// IpAddr::V6(addr),
+ /// IpAddr::from(addr)
+ /// );
+ /// ```
+ #[inline]
+ fn from(ipv6: Ipv6Addr) -> IpAddr {
+ IpAddr::V6(ipv6)
+ }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl fmt::Display for Ipv4Addr {
+ fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
+ let octets = self.octets();
+
+ // If there are no alignment requirements, write the IP address directly to `f`.
+ // Otherwise, write it to a local buffer and then use `f.pad`.
+ if fmt.precision().is_none() && fmt.width().is_none() {
+ write!(fmt, "{}.{}.{}.{}", octets[0], octets[1], octets[2], octets[3])
+ } else {
+ const LONGEST_IPV4_ADDR: &str = "255.255.255.255";
+
+ let mut buf = DisplayBuffer::<{ LONGEST_IPV4_ADDR.len() }>::new();
+ // Buffer is long enough for the longest possible IPv4 address, so this should never fail.
+ write!(buf, "{}.{}.{}.{}", octets[0], octets[1], octets[2], octets[3]).unwrap();
+
+ fmt.pad(buf.as_str())
+ }
+ }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl fmt::Debug for Ipv4Addr {
+ fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
+ fmt::Display::fmt(self, fmt)
+ }
+}
+
+#[stable(feature = "ip_cmp", since = "1.16.0")]
+impl PartialEq<Ipv4Addr> for IpAddr {
+ #[inline]
+ fn eq(&self, other: &Ipv4Addr) -> bool {
+ match self {
+ IpAddr::V4(v4) => v4 == other,
+ IpAddr::V6(_) => false,
+ }
+ }
+}
+
+#[stable(feature = "ip_cmp", since = "1.16.0")]
+impl PartialEq<IpAddr> for Ipv4Addr {
+ #[inline]
+ fn eq(&self, other: &IpAddr) -> bool {
+ match other {
+ IpAddr::V4(v4) => self == v4,
+ IpAddr::V6(_) => false,
+ }
+ }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl PartialOrd for Ipv4Addr {
+ #[inline]
+ fn partial_cmp(&self, other: &Ipv4Addr) -> Option<Ordering> {
+ Some(self.cmp(other))
+ }
+}
+
+#[stable(feature = "ip_cmp", since = "1.16.0")]
+impl PartialOrd<Ipv4Addr> for IpAddr {
+ #[inline]
+ fn partial_cmp(&self, other: &Ipv4Addr) -> Option<Ordering> {
+ match self {
+ IpAddr::V4(v4) => v4.partial_cmp(other),
+ IpAddr::V6(_) => Some(Ordering::Greater),
+ }
+ }
+}
+
+#[stable(feature = "ip_cmp", since = "1.16.0")]
+impl PartialOrd<IpAddr> for Ipv4Addr {
+ #[inline]
+ fn partial_cmp(&self, other: &IpAddr) -> Option<Ordering> {
+ match other {
+ IpAddr::V4(v4) => self.partial_cmp(v4),
+ IpAddr::V6(_) => Some(Ordering::Less),
+ }
+ }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl Ord for Ipv4Addr {
+ #[inline]
+ fn cmp(&self, other: &Ipv4Addr) -> Ordering {
+ self.octets.cmp(&other.octets)
+ }
+}
+
+#[stable(feature = "ip_u32", since = "1.1.0")]
+impl From<Ipv4Addr> for u32 {
+ /// Converts an `Ipv4Addr` into a host byte order `u32`.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::net::Ipv4Addr;
+ ///
+ /// let addr = Ipv4Addr::new(0x12, 0x34, 0x56, 0x78);
+ /// assert_eq!(0x12345678, u32::from(addr));
+ /// ```
+ #[inline]
+ fn from(ip: Ipv4Addr) -> u32 {
+ u32::from_be_bytes(ip.octets)
+ }
+}
+
+#[stable(feature = "ip_u32", since = "1.1.0")]
+impl From<u32> for Ipv4Addr {
+ /// Converts a host byte order `u32` into an `Ipv4Addr`.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::net::Ipv4Addr;
+ ///
+ /// let addr = Ipv4Addr::from(0x12345678);
+ /// assert_eq!(Ipv4Addr::new(0x12, 0x34, 0x56, 0x78), addr);
+ /// ```
+ #[inline]
+ fn from(ip: u32) -> Ipv4Addr {
+ Ipv4Addr { octets: ip.to_be_bytes() }
+ }
+}
+
+#[stable(feature = "from_slice_v4", since = "1.9.0")]
+impl From<[u8; 4]> for Ipv4Addr {
+ /// Creates an `Ipv4Addr` from a four element byte array.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::net::Ipv4Addr;
+ ///
+ /// let addr = Ipv4Addr::from([13u8, 12u8, 11u8, 10u8]);
+ /// assert_eq!(Ipv4Addr::new(13, 12, 11, 10), addr);
+ /// ```
+ #[inline]
+ fn from(octets: [u8; 4]) -> Ipv4Addr {
+ Ipv4Addr { octets }
+ }
+}
+
+#[stable(feature = "ip_from_slice", since = "1.17.0")]
+impl From<[u8; 4]> for IpAddr {
+ /// Creates an `IpAddr::V4` from a four element byte array.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::net::{IpAddr, Ipv4Addr};
+ ///
+ /// let addr = IpAddr::from([13u8, 12u8, 11u8, 10u8]);
+ /// assert_eq!(IpAddr::V4(Ipv4Addr::new(13, 12, 11, 10)), addr);
+ /// ```
+ #[inline]
+ fn from(octets: [u8; 4]) -> IpAddr {
+ IpAddr::V4(Ipv4Addr::from(octets))
+ }
+}
+
+impl Ipv6Addr {
+ /// Creates a new IPv6 address from eight 16-bit segments.
+ ///
+ /// The result will represent the IP address `a:b:c:d:e:f:g:h`.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::net::Ipv6Addr;
+ ///
+ /// let addr = Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff);
+ /// ```
+ #[rustc_const_stable(feature = "const_ip_32", 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 = [
+ a.to_be(),
+ b.to_be(),
+ c.to_be(),
+ d.to_be(),
+ e.to_be(),
+ f.to_be(),
+ g.to_be(),
+ h.to_be(),
+ ];
+ Ipv6Addr {
+ // All elements in `addr16` are big endian.
+ // SAFETY: `[u16; 8]` is always safe to transmute to `[u8; 16]`.
+ octets: unsafe { transmute::<_, [u8; 16]>(addr16) },
+ }
+ }
+
+ /// An IPv6 address representing localhost: `::1`.
+ ///
+ /// This corresponds to constant `IN6ADDR_LOOPBACK_INIT` or `in6addr_loopback` in other
+ /// languages.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::net::Ipv6Addr;
+ ///
+ /// let addr = Ipv6Addr::LOCALHOST;
+ /// assert_eq!(addr, Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1));
+ /// ```
+ #[doc(alias = "IN6ADDR_LOOPBACK_INIT")]
+ #[doc(alias = "in6addr_loopback")]
+ #[stable(feature = "ip_constructors", since = "1.30.0")]
+ pub const LOCALHOST: Self = Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1);
+
+ /// An IPv6 address representing the unspecified address: `::`
+ ///
+ /// This corresponds to constant `IN6ADDR_ANY_INIT` or `in6addr_any` in other languages.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::net::Ipv6Addr;
+ ///
+ /// let addr = Ipv6Addr::UNSPECIFIED;
+ /// assert_eq!(addr, Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0));
+ /// ```
+ #[doc(alias = "IN6ADDR_ANY_INIT")]
+ #[doc(alias = "in6addr_any")]
+ #[stable(feature = "ip_constructors", since = "1.30.0")]
+ pub const UNSPECIFIED: Self = Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0);
+
+ /// Returns the eight 16-bit segments that make up this address.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::net::Ipv6Addr;
+ ///
+ /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).segments(),
+ /// [0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff]);
+ /// ```
+ #[rustc_const_stable(feature = "const_ip_50", since = "1.50.0")]
+ #[stable(feature = "rust1", since = "1.0.0")]
+ #[must_use]
+ #[inline]
+ pub const fn segments(&self) -> [u16; 8] {
+ // All elements in `self.octets` must be big endian.
+ // SAFETY: `[u8; 16]` is always safe to transmute to `[u16; 8]`.
+ let [a, b, c, d, e, f, g, h] = unsafe { transmute::<_, [u16; 8]>(self.octets) };
+ // We want native endian u16
+ [
+ u16::from_be(a),
+ u16::from_be(b),
+ u16::from_be(c),
+ u16::from_be(d),
+ u16::from_be(e),
+ u16::from_be(f),
+ u16::from_be(g),
+ u16::from_be(h),
+ ]
+ }
+
+ /// Returns [`true`] for the special 'unspecified' address (`::`).
+ ///
+ /// This property is defined in [IETF RFC 4291].
+ ///
+ /// [IETF RFC 4291]: https://tools.ietf.org/html/rfc4291
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::net::Ipv6Addr;
+ ///
+ /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_unspecified(), false);
+ /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0).is_unspecified(), true);
+ /// ```
+ #[rustc_const_stable(feature = "const_ip_50", 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())
+ }
+
+ /// Returns [`true`] if this is the [loopback address] (`::1`),
+ /// as defined in [IETF RFC 4291 section 2.5.3].
+ ///
+ /// Contrary to IPv4, in IPv6 there is only one loopback address.
+ ///
+ /// [loopback address]: Ipv6Addr::LOCALHOST
+ /// [IETF RFC 4291 section 2.5.3]: https://tools.ietf.org/html/rfc4291#section-2.5.3
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::net::Ipv6Addr;
+ ///
+ /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_loopback(), false);
+ /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0x1).is_loopback(), true);
+ /// ```
+ #[rustc_const_stable(feature = "const_ip_50", 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())
+ }
+
+ /// Returns [`true`] if the address appears to be globally reachable
+ /// as specified by the [IANA IPv6 Special-Purpose Address Registry].
+ /// Whether or not an address is practically reachable will depend on your network configuration.
+ ///
+ /// Most IPv6 addresses are globally reachable;
+ /// unless they are specifically defined as *not* globally reachable.
+ ///
+ /// Non-exhaustive list of notable addresses that are not globally reachable:
+ /// - The [unspecified address] ([`is_unspecified`](Ipv6Addr::is_unspecified))
+ /// - The [loopback address] ([`is_loopback`](Ipv6Addr::is_loopback))
+ /// - IPv4-mapped addresses
+ /// - Addresses reserved for benchmarking
+ /// - Addresses reserved for documentation ([`is_documentation`](Ipv6Addr::is_documentation))
+ /// - Unique local addresses ([`is_unique_local`](Ipv6Addr::is_unique_local))
+ /// - Unicast addresses with link-local scope ([`is_unicast_link_local`](Ipv6Addr::is_unicast_link_local))
+ ///
+ /// For the complete overview of which addresses are globally reachable, see the table at the [IANA IPv6 Special-Purpose Address Registry].
+ ///
+ /// Note that an address having global scope is not the same as being globally reachable,
+ /// and there is no direct relation between the two concepts: There exist addresses with global scope
+ /// that are not globally reachable (for example unique local addresses),
+ /// and addresses that are globally reachable without having global scope
+ /// (multicast addresses with non-global scope).
+ ///
+ /// [IANA IPv6 Special-Purpose Address Registry]: https://www.iana.org/assignments/iana-ipv6-special-registry/iana-ipv6-special-registry.xhtml
+ /// [unspecified address]: Ipv6Addr::UNSPECIFIED
+ /// [loopback address]: Ipv6Addr::LOCALHOST
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(ip)]
+ ///
+ /// use std::net::Ipv6Addr;
+ ///
+ /// // Most IPv6 addresses are globally reachable:
+ /// assert_eq!(Ipv6Addr::new(0x26, 0, 0x1c9, 0, 0, 0xafc8, 0x10, 0x1).is_global(), true);
+ ///
+ /// // However some addresses have been assigned a special meaning
+ /// // that makes them not globally reachable. Some examples are:
+ ///
+ /// // The unspecified address (`::`)
+ /// assert_eq!(Ipv6Addr::UNSPECIFIED.is_global(), false);
+ ///
+ /// // The loopback address (`::1`)
+ /// assert_eq!(Ipv6Addr::LOCALHOST.is_global(), false);
+ ///
+ /// // IPv4-mapped addresses (`::ffff:0:0/96`)
+ /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_global(), false);
+ ///
+ /// // Addresses reserved for benchmarking (`2001:2::/48`)
+ /// assert_eq!(Ipv6Addr::new(0x2001, 2, 0, 0, 0, 0, 0, 1,).is_global(), false);
+ ///
+ /// // Addresses reserved for documentation (`2001:db8::/32`)
+ /// assert_eq!(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 1).is_global(), false);
+ ///
+ /// // Unique local addresses (`fc00::/7`)
+ /// assert_eq!(Ipv6Addr::new(0xfc02, 0, 0, 0, 0, 0, 0, 1).is_global(), false);
+ ///
+ /// // Unicast addresses with link-local scope (`fe80::/10`)
+ /// assert_eq!(Ipv6Addr::new(0xfe81, 0, 0, 0, 0, 0, 0, 1).is_global(), false);
+ ///
+ /// // For a complete overview see the IANA IPv6 Special-Purpose Address Registry.
+ /// ```
+ #[rustc_const_unstable(feature = "const_ipv6", issue = "76205")]
+ #[unstable(feature = "ip", issue = "27709")]
+ #[must_use]
+ #[inline]
+ pub const fn is_global(&self) -> bool {
+ !(self.is_unspecified()
+ || self.is_loopback()
+ // IPv4-mapped Address (`::ffff:0:0/96`)
+ || matches!(self.segments(), [0, 0, 0, 0, 0, 0xffff, _, _])
+ // IPv4-IPv6 Translat. (`64:ff9b:1::/48`)
+ || matches!(self.segments(), [0x64, 0xff9b, 1, _, _, _, _, _])
+ // Discard-Only Address Block (`100::/64`)
+ || matches!(self.segments(), [0x100, 0, 0, 0, _, _, _, _])
+ // IETF Protocol Assignments (`2001::/23`)
+ || (matches!(self.segments(), [0x2001, b, _, _, _, _, _, _] if b < 0x200)
+ && !(
+ // Port Control Protocol Anycast (`2001:1::1`)
+ u128::from_be_bytes(self.octets()) == 0x2001_0001_0000_0000_0000_0000_0000_0001
+ // Traversal Using Relays around NAT Anycast (`2001:1::2`)
+ || u128::from_be_bytes(self.octets()) == 0x2001_0001_0000_0000_0000_0000_0000_0002
+ // AMT (`2001:3::/32`)
+ || matches!(self.segments(), [0x2001, 3, _, _, _, _, _, _])
+ // AS112-v6 (`2001:4:112::/48`)
+ || matches!(self.segments(), [0x2001, 4, 0x112, _, _, _, _, _])
+ // ORCHIDv2 (`2001:20::/28`)
+ || matches!(self.segments(), [0x2001, b, _, _, _, _, _, _] if b >= 0x20 && b <= 0x2F)
+ ))
+ || self.is_documentation()
+ || self.is_unique_local()
+ || self.is_unicast_link_local())
+ }
+
+ /// Returns [`true`] if this is a unique local address (`fc00::/7`).
+ ///
+ /// This property is defined in [IETF RFC 4193].
+ ///
+ /// [IETF RFC 4193]: https://tools.ietf.org/html/rfc4193
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(ip)]
+ ///
+ /// use std::net::Ipv6Addr;
+ ///
+ /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_unique_local(), false);
+ /// assert_eq!(Ipv6Addr::new(0xfc02, 0, 0, 0, 0, 0, 0, 0).is_unique_local(), true);
+ /// ```
+ #[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
+ }
+
+ /// Returns [`true`] if this is a unicast address, as defined by [IETF RFC 4291].
+ /// Any address that is not a [multicast address] (`ff00::/8`) is unicast.
+ ///
+ /// [IETF RFC 4291]: https://tools.ietf.org/html/rfc4291
+ /// [multicast address]: Ipv6Addr::is_multicast
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(ip)]
+ ///
+ /// use std::net::Ipv6Addr;
+ ///
+ /// // The unspecified and loopback addresses are unicast.
+ /// assert_eq!(Ipv6Addr::UNSPECIFIED.is_unicast(), true);
+ /// assert_eq!(Ipv6Addr::LOCALHOST.is_unicast(), true);
+ ///
+ /// // Any address that is not a multicast address (`ff00::/8`) is unicast.
+ /// assert_eq!(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0).is_unicast(), true);
+ /// assert_eq!(Ipv6Addr::new(0xff00, 0, 0, 0, 0, 0, 0, 0).is_unicast(), false);
+ /// ```
+ #[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()
+ }
+
+ /// Returns `true` if the address is a unicast address with link-local scope,
+ /// as defined in [RFC 4291].
+ ///
+ /// A unicast address has link-local scope if it has the prefix `fe80::/10`, as per [RFC 4291 section 2.4].
+ /// Note that this encompasses more addresses than those defined in [RFC 4291 section 2.5.6],
+ /// which describes "Link-Local IPv6 Unicast Addresses" as having the following stricter format:
+ ///
+ /// ```text
+ /// | 10 bits | 54 bits | 64 bits |
+ /// +----------+-------------------------+----------------------------+
+ /// |1111111010| 0 | interface ID |
+ /// +----------+-------------------------+----------------------------+
+ /// ```
+ /// So while currently the only addresses with link-local scope an application will encounter are all in `fe80::/64`,
+ /// this might change in the future with the publication of new standards. More addresses in `fe80::/10` could be allocated,
+ /// and those addresses will have link-local scope.
+ ///
+ /// Also note that while [RFC 4291 section 2.5.3] mentions about the [loopback address] (`::1`) that "it is treated as having Link-Local scope",
+ /// this does not mean that the loopback address actually has link-local scope and this method will return `false` on it.
+ ///
+ /// [RFC 4291]: https://tools.ietf.org/html/rfc4291
+ /// [RFC 4291 section 2.4]: https://tools.ietf.org/html/rfc4291#section-2.4
+ /// [RFC 4291 section 2.5.3]: https://tools.ietf.org/html/rfc4291#section-2.5.3
+ /// [RFC 4291 section 2.5.6]: https://tools.ietf.org/html/rfc4291#section-2.5.6
+ /// [loopback address]: Ipv6Addr::LOCALHOST
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(ip)]
+ ///
+ /// use std::net::Ipv6Addr;
+ ///
+ /// // The loopback address (`::1`) does not actually have link-local scope.
+ /// assert_eq!(Ipv6Addr::LOCALHOST.is_unicast_link_local(), false);
+ ///
+ /// // Only addresses in `fe80::/10` have link-local scope.
+ /// assert_eq!(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0).is_unicast_link_local(), false);
+ /// assert_eq!(Ipv6Addr::new(0xfe80, 0, 0, 0, 0, 0, 0, 0).is_unicast_link_local(), true);
+ ///
+ /// // Addresses outside the stricter `fe80::/64` also have link-local scope.
+ /// assert_eq!(Ipv6Addr::new(0xfe80, 0, 0, 1, 0, 0, 0, 0).is_unicast_link_local(), true);
+ /// assert_eq!(Ipv6Addr::new(0xfe81, 0, 0, 0, 0, 0, 0, 0).is_unicast_link_local(), true);
+ /// ```
+ #[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
+ }
+
+ /// Returns [`true`] if this is an address reserved for documentation
+ /// (`2001:db8::/32`).
+ ///
+ /// This property is defined in [IETF RFC 3849].
+ ///
+ /// [IETF RFC 3849]: https://tools.ietf.org/html/rfc3849
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(ip)]
+ ///
+ /// use std::net::Ipv6Addr;
+ ///
+ /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_documentation(), false);
+ /// assert_eq!(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0).is_documentation(), true);
+ /// ```
+ #[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:
+ ///
+ /// - the loopback address
+ /// - the link-local addresses
+ /// - unique local addresses
+ /// - the unspecified address
+ /// - the address range reserved for documentation
+ ///
+ /// This method returns [`true`] for site-local addresses as per [RFC 4291 section 2.5.7]
+ ///
+ /// ```no_rust
+ /// The special behavior of [the site-local unicast] prefix defined in [RFC3513] must no longer
+ /// be supported in new implementations (i.e., new implementations must treat this prefix as
+ /// Global Unicast).
+ /// ```
+ ///
+ /// [RFC 4291 section 2.5.7]: https://tools.ietf.org/html/rfc4291#section-2.5.7
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(ip)]
+ ///
+ /// use std::net::Ipv6Addr;
+ ///
+ /// assert_eq!(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0).is_unicast_global(), false);
+ /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_unicast_global(), true);
+ /// ```
+ #[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()
+ && !self.is_loopback()
+ && !self.is_unicast_link_local()
+ && !self.is_unique_local()
+ && !self.is_unspecified()
+ && !self.is_documentation()
+ && !self.is_benchmarking()
+ }
+
+ /// Returns the address's multicast scope if the address is multicast.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(ip)]
+ ///
+ /// use std::net::{Ipv6Addr, Ipv6MulticastScope};
+ ///
+ /// assert_eq!(
+ /// Ipv6Addr::new(0xff0e, 0, 0, 0, 0, 0, 0, 0).multicast_scope(),
+ /// Some(Ipv6MulticastScope::Global)
+ /// );
+ /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).multicast_scope(), None);
+ /// ```
+ #[rustc_const_unstable(feature = "const_ipv6", issue = "76205")]
+ #[unstable(feature = "ip", issue = "27709")]
+ #[must_use]
+ #[inline]
+ pub const fn multicast_scope(&self) -> Option<Ipv6MulticastScope> {
+ if self.is_multicast() {
+ match self.segments()[0] & 0x000f {
+ 1 => Some(Ipv6MulticastScope::InterfaceLocal),
+ 2 => Some(Ipv6MulticastScope::LinkLocal),
+ 3 => Some(Ipv6MulticastScope::RealmLocal),
+ 4 => Some(Ipv6MulticastScope::AdminLocal),
+ 5 => Some(Ipv6MulticastScope::SiteLocal),
+ 8 => Some(Ipv6MulticastScope::OrganizationLocal),
+ 14 => Some(Ipv6MulticastScope::Global),
+ _ => None,
+ }
+ } else {
+ None
+ }
+ }
+
+ /// Returns [`true`] if this is a multicast address (`ff00::/8`).
+ ///
+ /// This property is defined by [IETF RFC 4291].
+ ///
+ /// [IETF RFC 4291]: https://tools.ietf.org/html/rfc4291
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::net::Ipv6Addr;
+ ///
+ /// assert_eq!(Ipv6Addr::new(0xff00, 0, 0, 0, 0, 0, 0, 0).is_multicast(), true);
+ /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_multicast(), false);
+ /// ```
+ #[rustc_const_stable(feature = "const_ip_50", 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
+ }
+
+ /// Converts this address to an [`IPv4` address] if it's an [IPv4-mapped] address,
+ /// as defined in [IETF RFC 4291 section 2.5.5.2], otherwise returns [`None`].
+ ///
+ /// `::ffff:a.b.c.d` becomes `a.b.c.d`.
+ /// All addresses *not* starting with `::ffff` will return `None`.
+ ///
+ /// [`IPv4` address]: Ipv4Addr
+ /// [IPv4-mapped]: Ipv6Addr
+ /// [IETF RFC 4291 section 2.5.5.2]: https://tools.ietf.org/html/rfc4291#section-2.5.5.2
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::net::{Ipv4Addr, Ipv6Addr};
+ ///
+ /// assert_eq!(Ipv6Addr::new(0xff00, 0, 0, 0, 0, 0, 0, 0).to_ipv4_mapped(), None);
+ /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).to_ipv4_mapped(),
+ /// Some(Ipv4Addr::new(192, 10, 2, 255)));
+ /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1).to_ipv4_mapped(), None);
+ /// ```
+ #[rustc_const_unstable(feature = "const_ipv6", issue = "76205")]
+ #[stable(feature = "ipv6_to_ipv4_mapped", since = "1.63.0")]
+ #[must_use = "this returns the result of the operation, \
+ without modifying the original"]
+ #[inline]
+ pub const fn to_ipv4_mapped(&self) -> Option<Ipv4Addr> {
+ match self.octets() {
+ [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff, a, b, c, d] => {
+ Some(Ipv4Addr::new(a, b, c, d))
+ }
+ _ => None,
+ }
+ }
+
+ /// Converts this address to an [`IPv4` address] if it is either
+ /// an [IPv4-compatible] address as defined in [IETF RFC 4291 section 2.5.5.1],
+ /// or an [IPv4-mapped] address as defined in [IETF RFC 4291 section 2.5.5.2],
+ /// otherwise returns [`None`].
+ ///
+ /// Note that this will return an [`IPv4` address] for the IPv6 loopback address `::1`. Use
+ /// [`Ipv6Addr::to_ipv4_mapped`] to avoid this.
+ ///
+ /// `::a.b.c.d` and `::ffff:a.b.c.d` become `a.b.c.d`. `::1` becomes `0.0.0.1`.
+ /// All addresses *not* starting with either all zeroes or `::ffff` will return `None`.
+ ///
+ /// [`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
+ /// [IETF RFC 4291 section 2.5.5.2]: https://tools.ietf.org/html/rfc4291#section-2.5.5.2
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::net::{Ipv4Addr, Ipv6Addr};
+ ///
+ /// assert_eq!(Ipv6Addr::new(0xff00, 0, 0, 0, 0, 0, 0, 0).to_ipv4(), None);
+ /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).to_ipv4(),
+ /// Some(Ipv4Addr::new(192, 10, 2, 255)));
+ /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1).to_ipv4(),
+ /// Some(Ipv4Addr::new(0, 0, 0, 1)));
+ /// ```
+ #[rustc_const_stable(feature = "const_ip_50", 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<Ipv4Addr> {
+ if let [0, 0, 0, 0, 0, 0 | 0xffff, ab, cd] = self.segments() {
+ let [a, b] = ab.to_be_bytes();
+ let [c, d] = cd.to_be_bytes();
+ Some(Ipv4Addr::new(a, b, c, d))
+ } else {
+ None
+ }
+ }
+
+ /// Converts this address to an `IpAddr::V4` if it is an IPv4-mapped addresses, otherwise it
+ /// returns self wrapped in an `IpAddr::V6`.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(ip)]
+ /// use std::net::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);
+ /// ```
+ #[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);
+ }
+ IpAddr::V6(*self)
+ }
+
+ /// Returns the sixteen eight-bit integers the IPv6 address consists of.
+ ///
+ /// ```
+ /// use std::net::Ipv6Addr;
+ ///
+ /// assert_eq!(Ipv6Addr::new(0xff00, 0, 0, 0, 0, 0, 0, 0).octets(),
+ /// [255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
+ /// ```
+ #[rustc_const_stable(feature = "const_ip_32", since = "1.32.0")]
+ #[stable(feature = "ipv6_to_octets", since = "1.12.0")]
+ #[must_use]
+ #[inline]
+ pub const fn octets(&self) -> [u8; 16] {
+ self.octets
+ }
+}
+
+/// Write an Ipv6Addr, conforming to the canonical style described by
+/// [RFC 5952](https://tools.ietf.org/html/rfc5952).
+#[stable(feature = "rust1", since = "1.0.0")]
+impl fmt::Display for Ipv6Addr {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ // If there are no alignment requirements, write the IP address directly to `f`.
+ // Otherwise, write it to a local buffer and then use `f.pad`.
+ if f.precision().is_none() && f.width().is_none() {
+ let segments = self.segments();
+
+ // Special case for :: and ::1; otherwise they get written with the
+ // IPv4 formatter
+ if self.is_unspecified() {
+ f.write_str("::")
+ } else if self.is_loopback() {
+ f.write_str("::1")
+ } else if let Some(ipv4) = self.to_ipv4() {
+ match segments[5] {
+ // IPv4 Compatible address
+ 0 => write!(f, "::{}", ipv4),
+ // IPv4 Mapped address
+ 0xffff => write!(f, "::ffff:{}", ipv4),
+ _ => unreachable!(),
+ }
+ } else {
+ #[derive(Copy, Clone, Default)]
+ struct Span {
+ start: usize,
+ len: usize,
+ }
+
+ // Find the inner 0 span
+ let zeroes = {
+ let mut longest = Span::default();
+ let mut current = Span::default();
+
+ for (i, &segment) in segments.iter().enumerate() {
+ if segment == 0 {
+ if current.len == 0 {
+ current.start = i;
+ }
+
+ current.len += 1;
+
+ if current.len > longest.len {
+ longest = current;
+ }
+ } else {
+ current = Span::default();
+ }
+ }
+
+ longest
+ };
+
+ /// Write a colon-separated part of the address
+ #[inline]
+ fn fmt_subslice(f: &mut fmt::Formatter<'_>, chunk: &[u16]) -> fmt::Result {
+ if let Some((first, tail)) = chunk.split_first() {
+ write!(f, "{:x}", first)?;
+ for segment in tail {
+ f.write_char(':')?;
+ write!(f, "{:x}", segment)?;
+ }
+ }
+ Ok(())
+ }
+
+ if zeroes.len > 1 {
+ fmt_subslice(f, &segments[..zeroes.start])?;
+ f.write_str("::")?;
+ fmt_subslice(f, &segments[zeroes.start + zeroes.len..])
+ } else {
+ fmt_subslice(f, &segments)
+ }
+ }
+ } else {
+ const LONGEST_IPV6_ADDR: &str = "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff";
+
+ let mut buf = DisplayBuffer::<{ LONGEST_IPV6_ADDR.len() }>::new();
+ // Buffer is long enough for the longest possible IPv6 address, so this should never fail.
+ write!(buf, "{}", self).unwrap();
+
+ f.pad(buf.as_str())
+ }
+ }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl fmt::Debug for Ipv6Addr {
+ fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
+ fmt::Display::fmt(self, fmt)
+ }
+}
+
+#[stable(feature = "ip_cmp", since = "1.16.0")]
+impl PartialEq<IpAddr> for Ipv6Addr {
+ #[inline]
+ fn eq(&self, other: &IpAddr) -> bool {
+ match other {
+ IpAddr::V4(_) => false,
+ IpAddr::V6(v6) => self == v6,
+ }
+ }
+}
+
+#[stable(feature = "ip_cmp", since = "1.16.0")]
+impl PartialEq<Ipv6Addr> for IpAddr {
+ #[inline]
+ fn eq(&self, other: &Ipv6Addr) -> bool {
+ match self {
+ IpAddr::V4(_) => false,
+ IpAddr::V6(v6) => v6 == other,
+ }
+ }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl PartialOrd for Ipv6Addr {
+ #[inline]
+ fn partial_cmp(&self, other: &Ipv6Addr) -> Option<Ordering> {
+ Some(self.cmp(other))
+ }
+}
+
+#[stable(feature = "ip_cmp", since = "1.16.0")]
+impl PartialOrd<Ipv6Addr> for IpAddr {
+ #[inline]
+ fn partial_cmp(&self, other: &Ipv6Addr) -> Option<Ordering> {
+ match self {
+ IpAddr::V4(_) => Some(Ordering::Less),
+ IpAddr::V6(v6) => v6.partial_cmp(other),
+ }
+ }
+}
+
+#[stable(feature = "ip_cmp", since = "1.16.0")]
+impl PartialOrd<IpAddr> for Ipv6Addr {
+ #[inline]
+ fn partial_cmp(&self, other: &IpAddr) -> Option<Ordering> {
+ match other {
+ IpAddr::V4(_) => Some(Ordering::Greater),
+ IpAddr::V6(v6) => self.partial_cmp(v6),
+ }
+ }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl Ord for Ipv6Addr {
+ #[inline]
+ fn cmp(&self, other: &Ipv6Addr) -> Ordering {
+ self.segments().cmp(&other.segments())
+ }
+}
+
+#[stable(feature = "i128", since = "1.26.0")]
+impl From<Ipv6Addr> for u128 {
+ /// Convert an `Ipv6Addr` into a host byte order `u128`.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::net::Ipv6Addr;
+ ///
+ /// let addr = Ipv6Addr::new(
+ /// 0x1020, 0x3040, 0x5060, 0x7080,
+ /// 0x90A0, 0xB0C0, 0xD0E0, 0xF00D,
+ /// );
+ /// assert_eq!(0x102030405060708090A0B0C0D0E0F00D_u128, u128::from(addr));
+ /// ```
+ #[inline]
+ fn from(ip: Ipv6Addr) -> u128 {
+ u128::from_be_bytes(ip.octets)
+ }
+}
+#[stable(feature = "i128", since = "1.26.0")]
+impl From<u128> for Ipv6Addr {
+ /// Convert a host byte order `u128` into an `Ipv6Addr`.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::net::Ipv6Addr;
+ ///
+ /// let addr = Ipv6Addr::from(0x102030405060708090A0B0C0D0E0F00D_u128);
+ /// assert_eq!(
+ /// Ipv6Addr::new(
+ /// 0x1020, 0x3040, 0x5060, 0x7080,
+ /// 0x90A0, 0xB0C0, 0xD0E0, 0xF00D,
+ /// ),
+ /// addr);
+ /// ```
+ #[inline]
+ fn from(ip: u128) -> Ipv6Addr {
+ Ipv6Addr::from(ip.to_be_bytes())
+ }
+}
+
+#[stable(feature = "ipv6_from_octets", since = "1.9.0")]
+impl From<[u8; 16]> for Ipv6Addr {
+ /// Creates an `Ipv6Addr` from a sixteen element byte array.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::net::Ipv6Addr;
+ ///
+ /// let addr = Ipv6Addr::from([
+ /// 25u8, 24u8, 23u8, 22u8, 21u8, 20u8, 19u8, 18u8,
+ /// 17u8, 16u8, 15u8, 14u8, 13u8, 12u8, 11u8, 10u8,
+ /// ]);
+ /// assert_eq!(
+ /// Ipv6Addr::new(
+ /// 0x1918, 0x1716,
+ /// 0x1514, 0x1312,
+ /// 0x1110, 0x0f0e,
+ /// 0x0d0c, 0x0b0a
+ /// ),
+ /// addr
+ /// );
+ /// ```
+ #[inline]
+ fn from(octets: [u8; 16]) -> Ipv6Addr {
+ Ipv6Addr { octets }
+ }
+}
+
+#[stable(feature = "ipv6_from_segments", since = "1.16.0")]
+impl From<[u16; 8]> for Ipv6Addr {
+ /// Creates an `Ipv6Addr` from an eight element 16-bit array.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::net::Ipv6Addr;
+ ///
+ /// let addr = Ipv6Addr::from([
+ /// 525u16, 524u16, 523u16, 522u16,
+ /// 521u16, 520u16, 519u16, 518u16,
+ /// ]);
+ /// assert_eq!(
+ /// Ipv6Addr::new(
+ /// 0x20d, 0x20c,
+ /// 0x20b, 0x20a,
+ /// 0x209, 0x208,
+ /// 0x207, 0x206
+ /// ),
+ /// addr
+ /// );
+ /// ```
+ #[inline]
+ fn from(segments: [u16; 8]) -> Ipv6Addr {
+ let [a, b, c, d, e, f, g, h] = segments;
+ Ipv6Addr::new(a, b, c, d, e, f, g, h)
+ }
+}
+
+#[stable(feature = "ip_from_slice", since = "1.17.0")]
+impl From<[u8; 16]> for IpAddr {
+ /// Creates an `IpAddr::V6` from a sixteen element byte array.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::net::{IpAddr, Ipv6Addr};
+ ///
+ /// let addr = IpAddr::from([
+ /// 25u8, 24u8, 23u8, 22u8, 21u8, 20u8, 19u8, 18u8,
+ /// 17u8, 16u8, 15u8, 14u8, 13u8, 12u8, 11u8, 10u8,
+ /// ]);
+ /// assert_eq!(
+ /// IpAddr::V6(Ipv6Addr::new(
+ /// 0x1918, 0x1716,
+ /// 0x1514, 0x1312,
+ /// 0x1110, 0x0f0e,
+ /// 0x0d0c, 0x0b0a
+ /// )),
+ /// addr
+ /// );
+ /// ```
+ #[inline]
+ fn from(octets: [u8; 16]) -> IpAddr {
+ IpAddr::V6(Ipv6Addr::from(octets))
+ }
+}
+
+#[stable(feature = "ip_from_slice", since = "1.17.0")]
+impl From<[u16; 8]> for IpAddr {
+ /// Creates an `IpAddr::V6` from an eight element 16-bit array.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::net::{IpAddr, Ipv6Addr};
+ ///
+ /// let addr = IpAddr::from([
+ /// 525u16, 524u16, 523u16, 522u16,
+ /// 521u16, 520u16, 519u16, 518u16,
+ /// ]);
+ /// assert_eq!(
+ /// IpAddr::V6(Ipv6Addr::new(
+ /// 0x20d, 0x20c,
+ /// 0x20b, 0x20a,
+ /// 0x209, 0x208,
+ /// 0x207, 0x206
+ /// )),
+ /// addr
+ /// );
+ /// ```
+ #[inline]
+ fn from(segments: [u16; 8]) -> IpAddr {
+ IpAddr::V6(Ipv6Addr::from(segments))
+ }
+}
diff --git a/library/core/src/net/mod.rs b/library/core/src/net/mod.rs
new file mode 100644
index 000000000..31f5f5d3c
--- /dev/null
+++ b/library/core/src/net/mod.rs
@@ -0,0 +1,24 @@
+//! Networking primitives for IP communication.
+//!
+//! This module provides types for IP and socket addresses.
+//!
+//! # Organization
+//!
+//! * [`IpAddr`] represents IP addresses of either IPv4 or IPv6; [`Ipv4Addr`] and
+//! [`Ipv6Addr`] are respectively IPv4 and IPv6 addresses
+//! * [`SocketAddr`] represents socket addresses of either IPv4 or IPv6; [`SocketAddrV4`]
+//! and [`SocketAddrV6`] are respectively IPv4 and IPv6 socket addresses
+
+#![unstable(feature = "ip_in_core", issue = "108443")]
+
+#[stable(feature = "rust1", since = "1.0.0")]
+pub use self::ip_addr::{IpAddr, Ipv4Addr, Ipv6Addr, Ipv6MulticastScope};
+#[stable(feature = "rust1", since = "1.0.0")]
+pub use self::parser::AddrParseError;
+#[stable(feature = "rust1", since = "1.0.0")]
+pub use self::socket_addr::{SocketAddr, SocketAddrV4, SocketAddrV6};
+
+mod display_buffer;
+mod ip_addr;
+mod parser;
+mod socket_addr;
diff --git a/library/std/src/net/parser.rs b/library/core/src/net/parser.rs
index a38031c48..a08d2792d 100644
--- a/library/std/src/net/parser.rs
+++ b/library/core/src/net/parser.rs
@@ -3,9 +3,7 @@
//! This module is "publicly exported" through the `FromStr` implementations
//! below.
-#[cfg(test)]
-mod tests;
-
+use crate::convert::TryInto;
use crate::error::Error;
use crate::fmt;
use crate::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6};
diff --git a/library/core/src/net/socket_addr.rs b/library/core/src/net/socket_addr.rs
new file mode 100644
index 000000000..2d48e2715
--- /dev/null
+++ b/library/core/src/net/socket_addr.rs
@@ -0,0 +1,664 @@
+use crate::cmp::Ordering;
+use crate::fmt::{self, Write};
+use crate::hash;
+use crate::net::{IpAddr, Ipv4Addr, Ipv6Addr};
+
+use super::display_buffer::DisplayBuffer;
+
+/// An internet socket address, either IPv4 or IPv6.
+///
+/// Internet socket addresses consist of an [IP address], a 16-bit port number, as well
+/// as possibly some version-dependent additional information. See [`SocketAddrV4`]'s and
+/// [`SocketAddrV6`]'s respective documentation for more details.
+///
+/// The size of a `SocketAddr` instance may vary depending on the target operating
+/// system.
+///
+/// [IP address]: IpAddr
+///
+/// # Examples
+///
+/// ```
+/// use std::net::{IpAddr, Ipv4Addr, SocketAddr};
+///
+/// let socket = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8080);
+///
+/// assert_eq!("127.0.0.1:8080".parse(), Ok(socket));
+/// assert_eq!(socket.port(), 8080);
+/// assert_eq!(socket.is_ipv4(), true);
+/// ```
+#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[stable(feature = "rust1", since = "1.0.0")]
+pub enum SocketAddr {
+ /// An IPv4 socket address.
+ #[stable(feature = "rust1", since = "1.0.0")]
+ V4(#[stable(feature = "rust1", since = "1.0.0")] SocketAddrV4),
+ /// An IPv6 socket address.
+ #[stable(feature = "rust1", since = "1.0.0")]
+ V6(#[stable(feature = "rust1", since = "1.0.0")] SocketAddrV6),
+}
+
+/// An IPv4 socket address.
+///
+/// IPv4 socket addresses consist of an [`IPv4` address] and a 16-bit port number, as
+/// stated in [IETF RFC 793].
+///
+/// See [`SocketAddr`] for a type encompassing both IPv4 and IPv6 socket addresses.
+///
+/// The size of a `SocketAddrV4` struct may vary depending on the target operating
+/// system. Do not assume that this type has the same memory layout as the underlying
+/// system representation.
+///
+/// [IETF RFC 793]: https://tools.ietf.org/html/rfc793
+/// [`IPv4` address]: Ipv4Addr
+///
+/// # Examples
+///
+/// ```
+/// use std::net::{Ipv4Addr, SocketAddrV4};
+///
+/// let socket = SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), 8080);
+///
+/// assert_eq!("127.0.0.1:8080".parse(), Ok(socket));
+/// assert_eq!(socket.ip(), &Ipv4Addr::new(127, 0, 0, 1));
+/// assert_eq!(socket.port(), 8080);
+/// ```
+#[derive(Copy, Clone, Eq, PartialEq)]
+#[stable(feature = "rust1", since = "1.0.0")]
+pub struct SocketAddrV4 {
+ ip: Ipv4Addr,
+ port: u16,
+}
+
+/// An IPv6 socket address.
+///
+/// IPv6 socket addresses consist of an [`IPv6` address], a 16-bit port number, as well
+/// as fields containing the traffic class, the flow label, and a scope identifier
+/// (see [IETF RFC 2553, Section 3.3] for more details).
+///
+/// See [`SocketAddr`] for a type encompassing both IPv4 and IPv6 socket addresses.
+///
+/// The size of a `SocketAddrV6` struct may vary depending on the target operating
+/// system. Do not assume that this type has the same memory layout as the underlying
+/// system representation.
+///
+/// [IETF RFC 2553, Section 3.3]: https://tools.ietf.org/html/rfc2553#section-3.3
+/// [`IPv6` address]: Ipv6Addr
+///
+/// # Examples
+///
+/// ```
+/// use std::net::{Ipv6Addr, SocketAddrV6};
+///
+/// let socket = SocketAddrV6::new(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 1), 8080, 0, 0);
+///
+/// assert_eq!("[2001:db8::1]:8080".parse(), Ok(socket));
+/// assert_eq!(socket.ip(), &Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 1));
+/// assert_eq!(socket.port(), 8080);
+/// ```
+#[derive(Copy, Clone, Eq, PartialEq)]
+#[stable(feature = "rust1", since = "1.0.0")]
+pub struct SocketAddrV6 {
+ ip: Ipv6Addr,
+ port: u16,
+ flowinfo: u32,
+ scope_id: u32,
+}
+
+impl SocketAddr {
+ /// Creates a new socket address from an [IP address] and a port number.
+ ///
+ /// [IP address]: IpAddr
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::net::{IpAddr, Ipv4Addr, SocketAddr};
+ ///
+ /// let socket = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8080);
+ /// assert_eq!(socket.ip(), IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)));
+ /// assert_eq!(socket.port(), 8080);
+ /// ```
+ #[stable(feature = "ip_addr", since = "1.7.0")]
+ #[must_use]
+ #[rustc_const_stable(feature = "const_socketaddr", since = "1.69.0")]
+ pub const fn new(ip: IpAddr, port: u16) -> SocketAddr {
+ match ip {
+ IpAddr::V4(a) => SocketAddr::V4(SocketAddrV4::new(a, port)),
+ IpAddr::V6(a) => SocketAddr::V6(SocketAddrV6::new(a, port, 0, 0)),
+ }
+ }
+
+ /// Returns the IP address associated with this socket address.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::net::{IpAddr, Ipv4Addr, SocketAddr};
+ ///
+ /// let socket = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8080);
+ /// assert_eq!(socket.ip(), IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)));
+ /// ```
+ #[must_use]
+ #[stable(feature = "ip_addr", since = "1.7.0")]
+ #[rustc_const_stable(feature = "const_socketaddr", since = "1.69.0")]
+ pub const fn ip(&self) -> IpAddr {
+ match *self {
+ SocketAddr::V4(ref a) => IpAddr::V4(*a.ip()),
+ SocketAddr::V6(ref a) => IpAddr::V6(*a.ip()),
+ }
+ }
+
+ /// Changes the IP address associated with this socket address.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::net::{IpAddr, Ipv4Addr, SocketAddr};
+ ///
+ /// let mut socket = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8080);
+ /// socket.set_ip(IpAddr::V4(Ipv4Addr::new(10, 10, 0, 1)));
+ /// assert_eq!(socket.ip(), IpAddr::V4(Ipv4Addr::new(10, 10, 0, 1)));
+ /// ```
+ #[stable(feature = "sockaddr_setters", since = "1.9.0")]
+ pub fn set_ip(&mut self, new_ip: IpAddr) {
+ // `match (*self, new_ip)` would have us mutate a copy of self only to throw it away.
+ match (self, new_ip) {
+ (&mut SocketAddr::V4(ref mut a), IpAddr::V4(new_ip)) => a.set_ip(new_ip),
+ (&mut SocketAddr::V6(ref mut a), IpAddr::V6(new_ip)) => a.set_ip(new_ip),
+ (self_, new_ip) => *self_ = Self::new(new_ip, self_.port()),
+ }
+ }
+
+ /// Returns the port number associated with this socket address.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::net::{IpAddr, Ipv4Addr, SocketAddr};
+ ///
+ /// let socket = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8080);
+ /// assert_eq!(socket.port(), 8080);
+ /// ```
+ #[must_use]
+ #[stable(feature = "rust1", since = "1.0.0")]
+ #[rustc_const_stable(feature = "const_socketaddr", since = "1.69.0")]
+ pub const fn port(&self) -> u16 {
+ match *self {
+ SocketAddr::V4(ref a) => a.port(),
+ SocketAddr::V6(ref a) => a.port(),
+ }
+ }
+
+ /// Changes the port number associated with this socket address.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::net::{IpAddr, Ipv4Addr, SocketAddr};
+ ///
+ /// let mut socket = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8080);
+ /// socket.set_port(1025);
+ /// assert_eq!(socket.port(), 1025);
+ /// ```
+ #[stable(feature = "sockaddr_setters", since = "1.9.0")]
+ pub fn set_port(&mut self, new_port: u16) {
+ match *self {
+ SocketAddr::V4(ref mut a) => a.set_port(new_port),
+ SocketAddr::V6(ref mut a) => a.set_port(new_port),
+ }
+ }
+
+ /// Returns [`true`] if the [IP address] in this `SocketAddr` is an
+ /// [`IPv4` address], and [`false`] otherwise.
+ ///
+ /// [IP address]: IpAddr
+ /// [`IPv4` address]: IpAddr::V4
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::net::{IpAddr, Ipv4Addr, SocketAddr};
+ ///
+ /// let socket = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8080);
+ /// assert_eq!(socket.is_ipv4(), true);
+ /// assert_eq!(socket.is_ipv6(), false);
+ /// ```
+ #[must_use]
+ #[stable(feature = "sockaddr_checker", since = "1.16.0")]
+ #[rustc_const_stable(feature = "const_socketaddr", since = "1.69.0")]
+ pub const fn is_ipv4(&self) -> bool {
+ matches!(*self, SocketAddr::V4(_))
+ }
+
+ /// Returns [`true`] if the [IP address] in this `SocketAddr` is an
+ /// [`IPv6` address], and [`false`] otherwise.
+ ///
+ /// [IP address]: IpAddr
+ /// [`IPv6` address]: IpAddr::V6
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::net::{IpAddr, Ipv6Addr, SocketAddr};
+ ///
+ /// let socket = SocketAddr::new(IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 65535, 0, 1)), 8080);
+ /// assert_eq!(socket.is_ipv4(), false);
+ /// assert_eq!(socket.is_ipv6(), true);
+ /// ```
+ #[must_use]
+ #[stable(feature = "sockaddr_checker", since = "1.16.0")]
+ #[rustc_const_stable(feature = "const_socketaddr", since = "1.69.0")]
+ pub const fn is_ipv6(&self) -> bool {
+ matches!(*self, SocketAddr::V6(_))
+ }
+}
+
+impl SocketAddrV4 {
+ /// Creates a new socket address from an [`IPv4` address] and a port number.
+ ///
+ /// [`IPv4` address]: Ipv4Addr
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::net::{SocketAddrV4, Ipv4Addr};
+ ///
+ /// let socket = SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), 8080);
+ /// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
+ #[must_use]
+ #[rustc_const_stable(feature = "const_socketaddr", since = "1.69.0")]
+ pub const fn new(ip: Ipv4Addr, port: u16) -> SocketAddrV4 {
+ SocketAddrV4 { ip, port }
+ }
+
+ /// Returns the IP address associated with this socket address.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::net::{SocketAddrV4, Ipv4Addr};
+ ///
+ /// let socket = SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), 8080);
+ /// assert_eq!(socket.ip(), &Ipv4Addr::new(127, 0, 0, 1));
+ /// ```
+ #[must_use]
+ #[stable(feature = "rust1", since = "1.0.0")]
+ #[rustc_const_stable(feature = "const_socketaddr", since = "1.69.0")]
+ pub const fn ip(&self) -> &Ipv4Addr {
+ &self.ip
+ }
+
+ /// Changes the IP address associated with this socket address.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::net::{SocketAddrV4, Ipv4Addr};
+ ///
+ /// let mut socket = SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), 8080);
+ /// socket.set_ip(Ipv4Addr::new(192, 168, 0, 1));
+ /// assert_eq!(socket.ip(), &Ipv4Addr::new(192, 168, 0, 1));
+ /// ```
+ #[stable(feature = "sockaddr_setters", since = "1.9.0")]
+ pub fn set_ip(&mut self, new_ip: Ipv4Addr) {
+ self.ip = new_ip;
+ }
+
+ /// Returns the port number associated with this socket address.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::net::{SocketAddrV4, Ipv4Addr};
+ ///
+ /// let socket = SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), 8080);
+ /// assert_eq!(socket.port(), 8080);
+ /// ```
+ #[must_use]
+ #[stable(feature = "rust1", since = "1.0.0")]
+ #[rustc_const_stable(feature = "const_socketaddr", since = "1.69.0")]
+ pub const fn port(&self) -> u16 {
+ self.port
+ }
+
+ /// Changes the port number associated with this socket address.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::net::{SocketAddrV4, Ipv4Addr};
+ ///
+ /// let mut socket = SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), 8080);
+ /// socket.set_port(4242);
+ /// assert_eq!(socket.port(), 4242);
+ /// ```
+ #[stable(feature = "sockaddr_setters", since = "1.9.0")]
+ pub fn set_port(&mut self, new_port: u16) {
+ self.port = new_port;
+ }
+}
+
+impl SocketAddrV6 {
+ /// Creates a new socket address from an [`IPv6` address], a 16-bit port number,
+ /// and the `flowinfo` and `scope_id` fields.
+ ///
+ /// For more information on the meaning and layout of the `flowinfo` and `scope_id`
+ /// parameters, see [IETF RFC 2553, Section 3.3].
+ ///
+ /// [IETF RFC 2553, Section 3.3]: https://tools.ietf.org/html/rfc2553#section-3.3
+ /// [`IPv6` address]: Ipv6Addr
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::net::{SocketAddrV6, Ipv6Addr};
+ ///
+ /// 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]
+ #[rustc_const_stable(feature = "const_socketaddr", since = "1.69.0")]
+ pub const fn new(ip: Ipv6Addr, port: u16, flowinfo: u32, scope_id: u32) -> SocketAddrV6 {
+ SocketAddrV6 { ip, port, flowinfo, scope_id }
+ }
+
+ /// Returns the IP address associated with this socket address.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::net::{SocketAddrV6, Ipv6Addr};
+ ///
+ /// let socket = SocketAddrV6::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1), 8080, 0, 0);
+ /// assert_eq!(socket.ip(), &Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1));
+ /// ```
+ #[must_use]
+ #[stable(feature = "rust1", since = "1.0.0")]
+ #[rustc_const_stable(feature = "const_socketaddr", since = "1.69.0")]
+ pub const fn ip(&self) -> &Ipv6Addr {
+ &self.ip
+ }
+
+ /// Changes the IP address associated with this socket address.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::net::{SocketAddrV6, Ipv6Addr};
+ ///
+ /// let mut socket = SocketAddrV6::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1), 8080, 0, 0);
+ /// socket.set_ip(Ipv6Addr::new(76, 45, 0, 0, 0, 0, 0, 0));
+ /// assert_eq!(socket.ip(), &Ipv6Addr::new(76, 45, 0, 0, 0, 0, 0, 0));
+ /// ```
+ #[stable(feature = "sockaddr_setters", since = "1.9.0")]
+ pub fn set_ip(&mut self, new_ip: Ipv6Addr) {
+ self.ip = new_ip;
+ }
+
+ /// Returns the port number associated with this socket address.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::net::{SocketAddrV6, Ipv6Addr};
+ ///
+ /// let socket = SocketAddrV6::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1), 8080, 0, 0);
+ /// assert_eq!(socket.port(), 8080);
+ /// ```
+ #[must_use]
+ #[stable(feature = "rust1", since = "1.0.0")]
+ #[rustc_const_stable(feature = "const_socketaddr", since = "1.69.0")]
+ pub const fn port(&self) -> u16 {
+ self.port
+ }
+
+ /// Changes the port number associated with this socket address.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::net::{SocketAddrV6, Ipv6Addr};
+ ///
+ /// let mut socket = SocketAddrV6::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1), 8080, 0, 0);
+ /// socket.set_port(4242);
+ /// assert_eq!(socket.port(), 4242);
+ /// ```
+ #[stable(feature = "sockaddr_setters", since = "1.9.0")]
+ pub fn set_port(&mut self, new_port: u16) {
+ self.port = new_port;
+ }
+
+ /// Returns the flow information associated with this address.
+ ///
+ /// This information corresponds to the `sin6_flowinfo` field in C's `netinet/in.h`,
+ /// as specified in [IETF RFC 2553, Section 3.3].
+ /// It combines information about the flow label and the traffic class as specified
+ /// in [IETF RFC 2460], respectively [Section 6] and [Section 7].
+ ///
+ /// [IETF RFC 2553, Section 3.3]: https://tools.ietf.org/html/rfc2553#section-3.3
+ /// [IETF RFC 2460]: https://tools.ietf.org/html/rfc2460
+ /// [Section 6]: https://tools.ietf.org/html/rfc2460#section-6
+ /// [Section 7]: https://tools.ietf.org/html/rfc2460#section-7
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::net::{SocketAddrV6, Ipv6Addr};
+ ///
+ /// let socket = SocketAddrV6::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1), 8080, 10, 0);
+ /// assert_eq!(socket.flowinfo(), 10);
+ /// ```
+ #[must_use]
+ #[stable(feature = "rust1", since = "1.0.0")]
+ #[rustc_const_stable(feature = "const_socketaddr", since = "1.69.0")]
+ pub const fn flowinfo(&self) -> u32 {
+ self.flowinfo
+ }
+
+ /// Changes the flow information associated with this socket address.
+ ///
+ /// See [`SocketAddrV6::flowinfo`]'s documentation for more details.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::net::{SocketAddrV6, Ipv6Addr};
+ ///
+ /// let mut socket = SocketAddrV6::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1), 8080, 10, 0);
+ /// socket.set_flowinfo(56);
+ /// assert_eq!(socket.flowinfo(), 56);
+ /// ```
+ #[stable(feature = "sockaddr_setters", since = "1.9.0")]
+ pub fn set_flowinfo(&mut self, new_flowinfo: u32) {
+ self.flowinfo = new_flowinfo;
+ }
+
+ /// Returns the scope ID associated with this address.
+ ///
+ /// This information corresponds to the `sin6_scope_id` field in C's `netinet/in.h`,
+ /// as specified in [IETF RFC 2553, Section 3.3].
+ ///
+ /// [IETF RFC 2553, Section 3.3]: https://tools.ietf.org/html/rfc2553#section-3.3
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::net::{SocketAddrV6, Ipv6Addr};
+ ///
+ /// let socket = SocketAddrV6::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1), 8080, 0, 78);
+ /// assert_eq!(socket.scope_id(), 78);
+ /// ```
+ #[must_use]
+ #[stable(feature = "rust1", since = "1.0.0")]
+ #[rustc_const_stable(feature = "const_socketaddr", since = "1.69.0")]
+ pub const fn scope_id(&self) -> u32 {
+ self.scope_id
+ }
+
+ /// Changes the scope ID associated with this socket address.
+ ///
+ /// See [`SocketAddrV6::scope_id`]'s documentation for more details.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::net::{SocketAddrV6, Ipv6Addr};
+ ///
+ /// let mut socket = SocketAddrV6::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1), 8080, 0, 78);
+ /// socket.set_scope_id(42);
+ /// assert_eq!(socket.scope_id(), 42);
+ /// ```
+ #[stable(feature = "sockaddr_setters", since = "1.9.0")]
+ pub fn set_scope_id(&mut self, new_scope_id: u32) {
+ self.scope_id = new_scope_id;
+ }
+}
+
+#[stable(feature = "ip_from_ip", since = "1.16.0")]
+impl From<SocketAddrV4> for SocketAddr {
+ /// Converts a [`SocketAddrV4`] into a [`SocketAddr::V4`].
+ fn from(sock4: SocketAddrV4) -> SocketAddr {
+ SocketAddr::V4(sock4)
+ }
+}
+
+#[stable(feature = "ip_from_ip", since = "1.16.0")]
+impl From<SocketAddrV6> for SocketAddr {
+ /// Converts a [`SocketAddrV6`] into a [`SocketAddr::V6`].
+ fn from(sock6: SocketAddrV6) -> SocketAddr {
+ SocketAddr::V6(sock6)
+ }
+}
+
+#[stable(feature = "addr_from_into_ip", since = "1.17.0")]
+impl<I: Into<IpAddr>> From<(I, u16)> for SocketAddr {
+ /// Converts a tuple struct (Into<[`IpAddr`]>, `u16`) into a [`SocketAddr`].
+ ///
+ /// This conversion creates a [`SocketAddr::V4`] for an [`IpAddr::V4`]
+ /// and creates a [`SocketAddr::V6`] for an [`IpAddr::V6`].
+ ///
+ /// `u16` is treated as port of the newly created [`SocketAddr`].
+ fn from(pieces: (I, u16)) -> SocketAddr {
+ SocketAddr::new(pieces.0.into(), pieces.1)
+ }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl fmt::Display for SocketAddr {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ match *self {
+ SocketAddr::V4(ref a) => a.fmt(f),
+ SocketAddr::V6(ref a) => a.fmt(f),
+ }
+ }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl fmt::Debug for SocketAddr {
+ fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
+ fmt::Display::fmt(self, fmt)
+ }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl fmt::Display for SocketAddrV4 {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ // If there are no alignment requirements, write the socket address directly to `f`.
+ // Otherwise, write it to a local buffer and then use `f.pad`.
+ if f.precision().is_none() && f.width().is_none() {
+ write!(f, "{}:{}", self.ip(), self.port())
+ } else {
+ const LONGEST_IPV4_SOCKET_ADDR: &str = "255.255.255.255:65536";
+
+ let mut buf = DisplayBuffer::<{ LONGEST_IPV4_SOCKET_ADDR.len() }>::new();
+ // Buffer is long enough for the longest possible IPv4 socket address, so this should never fail.
+ write!(buf, "{}:{}", self.ip(), self.port()).unwrap();
+
+ f.pad(buf.as_str())
+ }
+ }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl fmt::Debug for SocketAddrV4 {
+ fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
+ fmt::Display::fmt(self, fmt)
+ }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl fmt::Display for SocketAddrV6 {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ // If there are no alignment requirements, write the socket address directly to `f`.
+ // Otherwise, write it to a local buffer and then use `f.pad`.
+ if f.precision().is_none() && f.width().is_none() {
+ match self.scope_id() {
+ 0 => write!(f, "[{}]:{}", self.ip(), self.port()),
+ scope_id => write!(f, "[{}%{}]:{}", self.ip(), scope_id, self.port()),
+ }
+ } else {
+ const LONGEST_IPV6_SOCKET_ADDR: &str =
+ "[ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff%4294967296]:65536";
+
+ let mut buf = DisplayBuffer::<{ LONGEST_IPV6_SOCKET_ADDR.len() }>::new();
+ match self.scope_id() {
+ 0 => write!(buf, "[{}]:{}", self.ip(), self.port()),
+ scope_id => write!(buf, "[{}%{}]:{}", self.ip(), scope_id, self.port()),
+ }
+ // Buffer is long enough for the longest possible IPv6 socket address, so this should never fail.
+ .unwrap();
+
+ f.pad(buf.as_str())
+ }
+ }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl fmt::Debug for SocketAddrV6 {
+ fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
+ fmt::Display::fmt(self, fmt)
+ }
+}
+
+#[stable(feature = "socketaddr_ordering", since = "1.45.0")]
+impl PartialOrd for SocketAddrV4 {
+ fn partial_cmp(&self, other: &SocketAddrV4) -> Option<Ordering> {
+ Some(self.cmp(other))
+ }
+}
+
+#[stable(feature = "socketaddr_ordering", since = "1.45.0")]
+impl PartialOrd for SocketAddrV6 {
+ fn partial_cmp(&self, other: &SocketAddrV6) -> Option<Ordering> {
+ Some(self.cmp(other))
+ }
+}
+
+#[stable(feature = "socketaddr_ordering", since = "1.45.0")]
+impl Ord for SocketAddrV4 {
+ fn cmp(&self, other: &SocketAddrV4) -> Ordering {
+ self.ip().cmp(other.ip()).then(self.port().cmp(&other.port()))
+ }
+}
+
+#[stable(feature = "socketaddr_ordering", since = "1.45.0")]
+impl Ord for SocketAddrV6 {
+ fn cmp(&self, other: &SocketAddrV6) -> Ordering {
+ self.ip().cmp(other.ip()).then(self.port().cmp(&other.port()))
+ }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl hash::Hash for SocketAddrV4 {
+ fn hash<H: hash::Hasher>(&self, s: &mut H) {
+ (self.port, self.ip).hash(s)
+ }
+}
+#[stable(feature = "rust1", since = "1.0.0")]
+impl hash::Hash for SocketAddrV6 {
+ fn hash<H: hash::Hasher>(&self, s: &mut H) {
+ (self.port, &self.ip, self.flowinfo, self.scope_id).hash(s)
+ }
+}
diff --git a/library/core/src/num/dec2flt/mod.rs b/library/core/src/num/dec2flt/mod.rs
index a888ced49..f8d493e8b 100644
--- a/library/core/src/num/dec2flt/mod.rs
+++ b/library/core/src/num/dec2flt/mod.rs
@@ -75,6 +75,7 @@
issue = "none"
)]
+use crate::error::Error;
use crate::fmt;
use crate::str::FromStr;
@@ -182,15 +183,10 @@ enum FloatErrorKind {
Invalid,
}
-impl ParseFloatError {
- #[unstable(
- feature = "int_error_internals",
- reason = "available through Error trait and this method should \
- not be exposed publicly",
- issue = "none"
- )]
- #[doc(hidden)]
- pub fn __description(&self) -> &str {
+#[stable(feature = "rust1", since = "1.0.0")]
+impl Error for ParseFloatError {
+ #[allow(deprecated)]
+ fn description(&self) -> &str {
match self.kind {
FloatErrorKind::Empty => "cannot parse float from empty string",
FloatErrorKind::Invalid => "invalid float literal",
@@ -201,7 +197,8 @@ impl ParseFloatError {
#[stable(feature = "rust1", since = "1.0.0")]
impl fmt::Display for ParseFloatError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- self.__description().fmt(f)
+ #[allow(deprecated)]
+ self.description().fmt(f)
}
}
diff --git a/library/core/src/num/error.rs b/library/core/src/num/error.rs
index 768dd8781..1bae4efe7 100644
--- a/library/core/src/num/error.rs
+++ b/library/core/src/num/error.rs
@@ -9,23 +9,19 @@ use crate::fmt;
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub struct TryFromIntError(pub(crate) ());
-impl TryFromIntError {
- #[unstable(
- feature = "int_error_internals",
- reason = "available through Error trait and this method should \
- not be exposed publicly",
- issue = "none"
- )]
- #[doc(hidden)]
- pub fn __description(&self) -> &str {
- "out of range integral type conversion attempted"
+#[stable(feature = "try_from", since = "1.34.0")]
+impl fmt::Display for TryFromIntError {
+ fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
+ #[allow(deprecated)]
+ self.description().fmt(fmt)
}
}
#[stable(feature = "try_from", since = "1.34.0")]
-impl fmt::Display for TryFromIntError {
- fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
- self.__description().fmt(fmt)
+impl Error for TryFromIntError {
+ #[allow(deprecated)]
+ fn description(&self) -> &str {
+ "out of range integral type conversion attempted"
}
}
@@ -121,28 +117,13 @@ impl ParseIntError {
pub fn kind(&self) -> &IntErrorKind {
&self.kind
}
- #[unstable(
- feature = "int_error_internals",
- reason = "available through Error trait and this method should \
- not be exposed publicly",
- issue = "none"
- )]
- #[doc(hidden)]
- pub fn __description(&self) -> &str {
- match self.kind {
- IntErrorKind::Empty => "cannot parse integer from empty string",
- IntErrorKind::InvalidDigit => "invalid digit found in string",
- IntErrorKind::PosOverflow => "number too large to fit in target type",
- IntErrorKind::NegOverflow => "number too small to fit in target type",
- IntErrorKind::Zero => "number would be zero for non-zero type",
- }
- }
}
#[stable(feature = "rust1", since = "1.0.0")]
impl fmt::Display for ParseIntError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- self.__description().fmt(f)
+ #[allow(deprecated)]
+ self.description().fmt(f)
}
}
@@ -150,14 +131,12 @@ impl fmt::Display for ParseIntError {
impl Error for ParseIntError {
#[allow(deprecated)]
fn description(&self) -> &str {
- self.__description()
- }
-}
-
-#[stable(feature = "try_from", since = "1.34.0")]
-impl Error for TryFromIntError {
- #[allow(deprecated)]
- fn description(&self) -> &str {
- self.__description()
+ match self.kind {
+ IntErrorKind::Empty => "cannot parse integer from empty string",
+ IntErrorKind::InvalidDigit => "invalid digit found in string",
+ IntErrorKind::PosOverflow => "number too large to fit in target type",
+ IntErrorKind::NegOverflow => "number too small to fit in target type",
+ IntErrorKind::Zero => "number would be zero for non-zero type",
+ }
}
}
diff --git a/library/core/src/num/int_log10.rs b/library/core/src/num/int_log10.rs
index 80472528f..0ce31b40a 100644
--- a/library/core/src/num/int_log10.rs
+++ b/library/core/src/num/int_log10.rs
@@ -138,3 +138,11 @@ pub const fn i64(val: i64) -> u32 {
pub const fn i128(val: i128) -> u32 {
u128(val as u128)
}
+
+/// Instantiate this panic logic once, rather than for all the ilog methods
+/// on every single primitive type.
+#[cold]
+#[track_caller]
+pub const fn panic_for_nonpositive_argument() -> ! {
+ panic!("argument of integer logarithm must be positive")
+}
diff --git a/library/core/src/num/int_macros.rs b/library/core/src/num/int_macros.rs
index 2cae98b8e..aec15212d 100644
--- a/library/core/src/num/int_macros.rs
+++ b/library/core/src/num/int_macros.rs
@@ -1,11 +1,31 @@
macro_rules! int_impl {
- ($SelfT:ty, $ActualT:ident, $UnsignedT:ty, $BITS:expr, $BITS_MINUS_ONE:expr, $Min:expr, $Max: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,
- $bound_condition:expr) => {
+ (
+ Self = $SelfT:ty,
+ ActualT = $ActualT:ident,
+ UnsignedT = $UnsignedT:ty,
+
+ // There are all for use *only* in doc comments.
+ // As such, they're all passed as literals -- passing them as a string
+ // literal is fine if they need to be multiple code tokens.
+ // In non-comments, use the associated constants rather than these.
+ BITS = $BITS:literal,
+ BITS_MINUS_ONE = $BITS_MINUS_ONE:literal,
+ Min = $Min:literal,
+ Max = $Max:literal,
+ rot = $rot:literal,
+ rot_op = $rot_op:literal,
+ rot_result = $rot_result:literal,
+ swap_op = $swap_op:literal,
+ swapped = $swapped:literal,
+ reversed = $reversed:literal,
+ le_bytes = $le_bytes:literal,
+ be_bytes = $be_bytes:literal,
+ to_xe_bytes_doc = $to_xe_bytes_doc:expr,
+ from_xe_bytes_doc = $from_xe_bytes_doc:expr,
+ bound_condition = $bound_condition:literal,
+ ) => {
/// The smallest value that can be represented by this integer type
- #[doc = concat!("(&minus;2<sup>", $BITS_MINUS_ONE, "</sup>", $bound_condition, ")")]
+ #[doc = concat!("(&minus;2<sup>", $BITS_MINUS_ONE, "</sup>", $bound_condition, ").")]
///
/// # Examples
///
@@ -15,10 +35,10 @@ macro_rules! int_impl {
#[doc = concat!("assert_eq!(", stringify!($SelfT), "::MIN, ", stringify!($Min), ");")]
/// ```
#[stable(feature = "assoc_int_consts", since = "1.43.0")]
- pub const MIN: Self = !0 ^ ((!0 as $UnsignedT) >> 1) as Self;
+ pub const MIN: Self = !Self::MAX;
/// The largest value that can be represented by this integer type
- #[doc = concat!("(2<sup>", $BITS_MINUS_ONE, "</sup> &minus; 1", $bound_condition, ")")]
+ #[doc = concat!("(2<sup>", $BITS_MINUS_ONE, "</sup> &minus; 1", $bound_condition, ").")]
///
/// # Examples
///
@@ -28,7 +48,7 @@ macro_rules! int_impl {
#[doc = concat!("assert_eq!(", stringify!($SelfT), "::MAX, ", stringify!($Max), ");")]
/// ```
#[stable(feature = "assoc_int_consts", since = "1.43.0")]
- pub const MAX: Self = !Self::MIN;
+ pub const MAX: Self = (<$UnsignedT>::MAX >> 1) as Self;
/// The size of this integer type in bits.
///
@@ -38,7 +58,7 @@ macro_rules! int_impl {
#[doc = concat!("assert_eq!(", stringify!($SelfT), "::BITS, ", stringify!($BITS), ");")]
/// ```
#[stable(feature = "int_bits_const", since = "1.53.0")]
- pub const BITS: u32 = $BITS;
+ pub const BITS: u32 = <$UnsignedT>::BITS;
/// Converts a string slice in a given base to an integer.
///
@@ -1365,7 +1385,7 @@ macro_rules! int_impl {
// SAFETY: the masking by the bitsize of the type ensures that we do not shift
// out of bounds
unsafe {
- self.unchecked_shl(rhs & ($BITS - 1))
+ self.unchecked_shl(rhs & (Self::BITS - 1))
}
}
@@ -1395,7 +1415,7 @@ macro_rules! int_impl {
// SAFETY: the masking by the bitsize of the type ensures that we do not shift
// out of bounds
unsafe {
- self.unchecked_shr(rhs & ($BITS - 1))
+ self.unchecked_shr(rhs & (Self::BITS - 1))
}
}
@@ -1901,7 +1921,7 @@ macro_rules! int_impl {
without modifying the original"]
#[inline]
pub const fn overflowing_shl(self, rhs: u32) -> (Self, bool) {
- (self.wrapping_shl(rhs), (rhs > ($BITS - 1)))
+ (self.wrapping_shl(rhs), rhs >= Self::BITS)
}
/// Shifts self right by `rhs` bits.
@@ -1924,7 +1944,7 @@ macro_rules! int_impl {
without modifying the original"]
#[inline]
pub const fn overflowing_shr(self, rhs: u32) -> (Self, bool) {
- (self.wrapping_shr(rhs), (rhs > ($BITS - 1)))
+ (self.wrapping_shr(rhs), rhs >= Self::BITS)
}
/// Computes the absolute value of `self`.
@@ -2331,14 +2351,17 @@ macro_rules! int_impl {
/// ```
#[stable(feature = "int_log", since = "1.67.0")]
#[rustc_const_stable(feature = "int_log", since = "1.67.0")]
- #[rustc_allow_const_fn_unstable(const_option)]
#[must_use = "this returns the result of the operation, \
without modifying the original"]
#[inline]
#[track_caller]
pub const fn ilog(self, base: Self) -> u32 {
assert!(base >= 2, "base of integer logarithm must be at least 2");
- self.checked_ilog(base).expect("argument of integer logarithm must be positive")
+ if let Some(log) = self.checked_ilog(base) {
+ log
+ } else {
+ int_log10::panic_for_nonpositive_argument()
+ }
}
/// Returns the base 2 logarithm of the number, rounded down.
@@ -2354,13 +2377,16 @@ macro_rules! int_impl {
/// ```
#[stable(feature = "int_log", since = "1.67.0")]
#[rustc_const_stable(feature = "int_log", since = "1.67.0")]
- #[rustc_allow_const_fn_unstable(const_option)]
#[must_use = "this returns the result of the operation, \
without modifying the original"]
#[inline]
#[track_caller]
pub const fn ilog2(self) -> u32 {
- self.checked_ilog2().expect("argument of integer logarithm must be positive")
+ if let Some(log) = self.checked_ilog2() {
+ log
+ } else {
+ int_log10::panic_for_nonpositive_argument()
+ }
}
/// Returns the base 10 logarithm of the number, rounded down.
@@ -2376,13 +2402,16 @@ macro_rules! int_impl {
/// ```
#[stable(feature = "int_log", since = "1.67.0")]
#[rustc_const_stable(feature = "int_log", since = "1.67.0")]
- #[rustc_allow_const_fn_unstable(const_option)]
#[must_use = "this returns the result of the operation, \
without modifying the original"]
#[inline]
#[track_caller]
pub const fn ilog10(self) -> u32 {
- self.checked_ilog10().expect("argument of integer logarithm must be positive")
+ if let Some(log) = self.checked_ilog10() {
+ log
+ } else {
+ int_log10::panic_for_nonpositive_argument()
+ }
}
/// Returns the logarithm of the number with respect to an arbitrary base,
@@ -2574,12 +2603,13 @@ macro_rules! int_impl {
#[must_use = "this returns the result of the operation, \
without modifying the original"]
#[inline(always)]
+ #[rustc_allow_const_fn_unstable(const_cmp)]
pub const fn signum(self) -> Self {
- match self {
- n if n > 0 => 1,
- 0 => 0,
- _ => -1,
- }
+ // Picking the right way to phrase this is complicated
+ // (<https://graphics.stanford.edu/~seander/bithacks.html#CopyIntegerSign>)
+ // so delegate it to `Ord` which is already producing -1/0/+1
+ // exactly like we need and can be the place to deal with the complexity.
+ self.cmp(&0) as _
}
/// Returns `true` if `self` is positive and `false` if the number is zero or
diff --git a/library/core/src/num/mod.rs b/library/core/src/num/mod.rs
index ac7f579eb..a50c91579 100644
--- a/library/core/src/num/mod.rs
+++ b/library/core/src/num/mod.rs
@@ -9,9 +9,6 @@ use crate::mem;
use crate::ops::{Add, Mul, Sub};
use crate::str::FromStr;
-#[cfg(not(no_fp_fmt_parse))]
-use crate::error::Error;
-
// Used because the `?` operator is not allowed in a const context.
macro_rules! try_opt {
($e:expr) => {
@@ -61,15 +58,6 @@ pub use wrapping::Wrapping;
#[cfg(not(no_fp_fmt_parse))]
pub use dec2flt::ParseFloatError;
-#[cfg(not(no_fp_fmt_parse))]
-#[stable(feature = "rust1", since = "1.0.0")]
-impl Error for ParseFloatError {
- #[allow(deprecated)]
- fn description(&self) -> &str {
- self.__description()
- }
-}
-
#[stable(feature = "rust1", since = "1.0.0")]
pub use error::ParseIntError;
@@ -238,72 +226,217 @@ macro_rules! widening_impl {
}
impl i8 {
- int_impl! { i8, i8, u8, 8, 7, -128, 127, 2, "-0x7e", "0xa", "0x12", "0x12", "0x48",
- "[0x12]", "[0x12]", "", "", "" }
+ int_impl! {
+ Self = i8,
+ ActualT = i8,
+ UnsignedT = u8,
+ BITS = 8,
+ BITS_MINUS_ONE = 7,
+ Min = -128,
+ Max = 127,
+ rot = 2,
+ rot_op = "-0x7e",
+ rot_result = "0xa",
+ swap_op = "0x12",
+ swapped = "0x12",
+ reversed = "0x48",
+ le_bytes = "[0x12]",
+ be_bytes = "[0x12]",
+ to_xe_bytes_doc = "",
+ from_xe_bytes_doc = "",
+ bound_condition = "",
+ }
}
impl i16 {
- int_impl! { i16, i16, u16, 16, 15, -32768, 32767, 4, "-0x5ffd", "0x3a", "0x1234", "0x3412",
- "0x2c48", "[0x34, 0x12]", "[0x12, 0x34]", "", "", "" }
+ int_impl! {
+ Self = i16,
+ ActualT = i16,
+ UnsignedT = u16,
+ BITS = 16,
+ BITS_MINUS_ONE = 15,
+ Min = -32768,
+ Max = 32767,
+ rot = 4,
+ rot_op = "-0x5ffd",
+ rot_result = "0x3a",
+ swap_op = "0x1234",
+ swapped = "0x3412",
+ reversed = "0x2c48",
+ le_bytes = "[0x34, 0x12]",
+ be_bytes = "[0x12, 0x34]",
+ to_xe_bytes_doc = "",
+ from_xe_bytes_doc = "",
+ bound_condition = "",
+ }
}
impl i32 {
- int_impl! { i32, i32, u32, 32, 31, -2147483648, 2147483647, 8, "0x10000b3", "0xb301",
- "0x12345678", "0x78563412", "0x1e6a2c48", "[0x78, 0x56, 0x34, 0x12]",
- "[0x12, 0x34, 0x56, 0x78]", "", "", "" }
+ int_impl! {
+ Self = i32,
+ ActualT = i32,
+ UnsignedT = u32,
+ BITS = 32,
+ BITS_MINUS_ONE = 31,
+ Min = -2147483648,
+ Max = 2147483647,
+ rot = 8,
+ rot_op = "0x10000b3",
+ rot_result = "0xb301",
+ swap_op = "0x12345678",
+ swapped = "0x78563412",
+ reversed = "0x1e6a2c48",
+ le_bytes = "[0x78, 0x56, 0x34, 0x12]",
+ be_bytes = "[0x12, 0x34, 0x56, 0x78]",
+ to_xe_bytes_doc = "",
+ from_xe_bytes_doc = "",
+ bound_condition = "",
+ }
}
impl i64 {
- int_impl! { i64, i64, u64, 64, 63, -9223372036854775808, 9223372036854775807, 12,
- "0xaa00000000006e1", "0x6e10aa", "0x1234567890123456", "0x5634129078563412",
- "0x6a2c48091e6a2c48", "[0x56, 0x34, 0x12, 0x90, 0x78, 0x56, 0x34, 0x12]",
- "[0x12, 0x34, 0x56, 0x78, 0x90, 0x12, 0x34, 0x56]", "", "", "" }
+ int_impl! {
+ Self = i64,
+ ActualT = i64,
+ UnsignedT = u64,
+ BITS = 64,
+ BITS_MINUS_ONE = 63,
+ Min = -9223372036854775808,
+ Max = 9223372036854775807,
+ rot = 12,
+ rot_op = "0xaa00000000006e1",
+ rot_result = "0x6e10aa",
+ swap_op = "0x1234567890123456",
+ swapped = "0x5634129078563412",
+ reversed = "0x6a2c48091e6a2c48",
+ le_bytes = "[0x56, 0x34, 0x12, 0x90, 0x78, 0x56, 0x34, 0x12]",
+ be_bytes = "[0x12, 0x34, 0x56, 0x78, 0x90, 0x12, 0x34, 0x56]",
+ to_xe_bytes_doc = "",
+ from_xe_bytes_doc = "",
+ bound_condition = "",
+ }
}
impl i128 {
- int_impl! { i128, i128, u128, 128, 127, -170141183460469231731687303715884105728,
- 170141183460469231731687303715884105727, 16,
- "0x13f40000000000000000000000004f76", "0x4f7613f4", "0x12345678901234567890123456789012",
- "0x12907856341290785634129078563412", "0x48091e6a2c48091e6a2c48091e6a2c48",
- "[0x12, 0x90, 0x78, 0x56, 0x34, 0x12, 0x90, 0x78, \
- 0x56, 0x34, 0x12, 0x90, 0x78, 0x56, 0x34, 0x12]",
- "[0x12, 0x34, 0x56, 0x78, 0x90, 0x12, 0x34, 0x56, \
- 0x78, 0x90, 0x12, 0x34, 0x56, 0x78, 0x90, 0x12]", "", "", "" }
+ int_impl! {
+ Self = i128,
+ ActualT = i128,
+ UnsignedT = u128,
+ BITS = 128,
+ BITS_MINUS_ONE = 127,
+ Min = -170141183460469231731687303715884105728,
+ Max = 170141183460469231731687303715884105727,
+ rot = 16,
+ rot_op = "0x13f40000000000000000000000004f76",
+ rot_result = "0x4f7613f4",
+ swap_op = "0x12345678901234567890123456789012",
+ swapped = "0x12907856341290785634129078563412",
+ reversed = "0x48091e6a2c48091e6a2c48091e6a2c48",
+ le_bytes = "[0x12, 0x90, 0x78, 0x56, 0x34, 0x12, 0x90, 0x78, \
+ 0x56, 0x34, 0x12, 0x90, 0x78, 0x56, 0x34, 0x12]",
+ be_bytes = "[0x12, 0x34, 0x56, 0x78, 0x90, 0x12, 0x34, 0x56, \
+ 0x78, 0x90, 0x12, 0x34, 0x56, 0x78, 0x90, 0x12]",
+ to_xe_bytes_doc = "",
+ from_xe_bytes_doc = "",
+ bound_condition = "",
+ }
}
#[cfg(target_pointer_width = "16")]
impl isize {
- int_impl! { isize, i16, usize, 16, 15, -32768, 32767, 4, "-0x5ffd", "0x3a", "0x1234",
- "0x3412", "0x2c48", "[0x34, 0x12]", "[0x12, 0x34]",
- usize_isize_to_xe_bytes_doc!(), usize_isize_from_xe_bytes_doc!(),
- " on 16-bit targets" }
+ int_impl! {
+ Self = isize,
+ ActualT = i16,
+ UnsignedT = usize,
+ BITS = 16,
+ BITS_MINUS_ONE = 15,
+ Min = -32768,
+ Max = 32767,
+ rot = 4,
+ rot_op = "-0x5ffd",
+ rot_result = "0x3a",
+ swap_op = "0x1234",
+ swapped = "0x3412",
+ reversed = "0x2c48",
+ le_bytes = "[0x34, 0x12]",
+ be_bytes = "[0x12, 0x34]",
+ to_xe_bytes_doc = usize_isize_to_xe_bytes_doc!(),
+ from_xe_bytes_doc = usize_isize_from_xe_bytes_doc!(),
+ bound_condition = " on 16-bit targets",
+ }
}
#[cfg(target_pointer_width = "32")]
impl isize {
- int_impl! { isize, i32, usize, 32, 31, -2147483648, 2147483647, 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!(),
- " on 32-bit targets" }
+ int_impl! {
+ Self = isize,
+ ActualT = i32,
+ UnsignedT = usize,
+ BITS = 32,
+ BITS_MINUS_ONE = 31,
+ Min = -2147483648,
+ Max = 2147483647,
+ rot = 8,
+ rot_op = "0x10000b3",
+ rot_result = "0xb301",
+ swap_op = "0x12345678",
+ swapped = "0x78563412",
+ reversed = "0x1e6a2c48",
+ le_bytes = "[0x78, 0x56, 0x34, 0x12]",
+ be_bytes = "[0x12, 0x34, 0x56, 0x78]",
+ to_xe_bytes_doc = usize_isize_to_xe_bytes_doc!(),
+ from_xe_bytes_doc = usize_isize_from_xe_bytes_doc!(),
+ bound_condition = " on 32-bit targets",
+ }
}
#[cfg(target_pointer_width = "64")]
impl isize {
- int_impl! { isize, i64, usize, 64, 63, -9223372036854775808, 9223372036854775807,
- 12, "0xaa00000000006e1", "0x6e10aa", "0x1234567890123456", "0x5634129078563412",
- "0x6a2c48091e6a2c48", "[0x56, 0x34, 0x12, 0x90, 0x78, 0x56, 0x34, 0x12]",
- "[0x12, 0x34, 0x56, 0x78, 0x90, 0x12, 0x34, 0x56]",
- usize_isize_to_xe_bytes_doc!(), usize_isize_from_xe_bytes_doc!(),
- " on 64-bit targets" }
+ int_impl! {
+ Self = isize,
+ ActualT = i64,
+ UnsignedT = usize,
+ BITS = 64,
+ BITS_MINUS_ONE = 63,
+ Min = -9223372036854775808,
+ Max = 9223372036854775807,
+ rot = 12,
+ rot_op = "0xaa00000000006e1",
+ rot_result = "0x6e10aa",
+ swap_op = "0x1234567890123456",
+ swapped = "0x5634129078563412",
+ reversed = "0x6a2c48091e6a2c48",
+ le_bytes = "[0x56, 0x34, 0x12, 0x90, 0x78, 0x56, 0x34, 0x12]",
+ be_bytes = "[0x12, 0x34, 0x56, 0x78, 0x90, 0x12, 0x34, 0x56]",
+ to_xe_bytes_doc = usize_isize_to_xe_bytes_doc!(),
+ from_xe_bytes_doc = usize_isize_from_xe_bytes_doc!(),
+ bound_condition = " on 64-bit targets",
+ }
}
/// If 6th bit set ascii is upper case.
const ASCII_CASE_MASK: u8 = 0b0010_0000;
impl u8 {
- uint_impl! { u8, u8, i8, NonZeroU8, 8, 255, 2, "0x82", "0xa", "0x12", "0x12", "0x48", "[0x12]",
- "[0x12]", "", "", "" }
+ uint_impl! {
+ Self = u8,
+ ActualT = u8,
+ SignedT = i8,
+ NonZeroT = NonZeroU8,
+ BITS = 8,
+ MAX = 255,
+ rot = 2,
+ rot_op = "0x82",
+ rot_result = "0xa",
+ swap_op = "0x12",
+ swapped = "0x12",
+ reversed = "0x48",
+ le_bytes = "[0x12]",
+ be_bytes = "[0x12]",
+ to_xe_bytes_doc = "",
+ from_xe_bytes_doc = "",
+ bound_condition = "",
+ }
widening_impl! { u8, u16, 8, unsigned }
/// Checks if the value is within the ASCII range.
@@ -887,8 +1020,25 @@ impl u8 {
}
impl u16 {
- uint_impl! { u16, u16, i16, NonZeroU16, 16, 65535, 4, "0xa003", "0x3a", "0x1234", "0x3412", "0x2c48",
- "[0x34, 0x12]", "[0x12, 0x34]", "", "", "" }
+ uint_impl! {
+ Self = u16,
+ ActualT = u16,
+ SignedT = i16,
+ NonZeroT = NonZeroU16,
+ BITS = 16,
+ MAX = 65535,
+ rot = 4,
+ rot_op = "0xa003",
+ rot_result = "0x3a",
+ swap_op = "0x1234",
+ swapped = "0x3412",
+ reversed = "0x2c48",
+ le_bytes = "[0x34, 0x12]",
+ be_bytes = "[0x12, 0x34]",
+ to_xe_bytes_doc = "",
+ from_xe_bytes_doc = "",
+ bound_condition = "",
+ }
widening_impl! { u16, u32, 16, unsigned }
/// Checks if the value is a Unicode surrogate code point, which are disallowed values for [`char`].
@@ -918,56 +1068,144 @@ impl u16 {
}
impl u32 {
- uint_impl! { u32, u32, i32, NonZeroU32, 32, 4294967295, 8, "0x10000b3", "0xb301", "0x12345678",
- "0x78563412", "0x1e6a2c48", "[0x78, 0x56, 0x34, 0x12]", "[0x12, 0x34, 0x56, 0x78]", "", "", "" }
+ uint_impl! {
+ Self = u32,
+ ActualT = u32,
+ SignedT = i32,
+ NonZeroT = NonZeroU32,
+ BITS = 32,
+ MAX = 4294967295,
+ rot = 8,
+ rot_op = "0x10000b3",
+ rot_result = "0xb301",
+ swap_op = "0x12345678",
+ swapped = "0x78563412",
+ reversed = "0x1e6a2c48",
+ le_bytes = "[0x78, 0x56, 0x34, 0x12]",
+ be_bytes = "[0x12, 0x34, 0x56, 0x78]",
+ to_xe_bytes_doc = "",
+ from_xe_bytes_doc = "",
+ bound_condition = "",
+ }
widening_impl! { u32, u64, 32, unsigned }
}
impl u64 {
- uint_impl! { u64, u64, i64, NonZeroU64, 64, 18446744073709551615, 12, "0xaa00000000006e1", "0x6e10aa",
- "0x1234567890123456", "0x5634129078563412", "0x6a2c48091e6a2c48",
- "[0x56, 0x34, 0x12, 0x90, 0x78, 0x56, 0x34, 0x12]",
- "[0x12, 0x34, 0x56, 0x78, 0x90, 0x12, 0x34, 0x56]",
- "", "", ""}
+ uint_impl! {
+ Self = u64,
+ ActualT = u64,
+ SignedT = i64,
+ NonZeroT = NonZeroU64,
+ BITS = 64,
+ MAX = 18446744073709551615,
+ rot = 12,
+ rot_op = "0xaa00000000006e1",
+ rot_result = "0x6e10aa",
+ swap_op = "0x1234567890123456",
+ swapped = "0x5634129078563412",
+ reversed = "0x6a2c48091e6a2c48",
+ le_bytes = "[0x56, 0x34, 0x12, 0x90, 0x78, 0x56, 0x34, 0x12]",
+ be_bytes = "[0x12, 0x34, 0x56, 0x78, 0x90, 0x12, 0x34, 0x56]",
+ to_xe_bytes_doc = "",
+ from_xe_bytes_doc = "",
+ bound_condition = "",
+ }
widening_impl! { u64, u128, 64, unsigned }
}
impl u128 {
- uint_impl! { u128, u128, i128, NonZeroU128, 128, 340282366920938463463374607431768211455, 16,
- "0x13f40000000000000000000000004f76", "0x4f7613f4", "0x12345678901234567890123456789012",
- "0x12907856341290785634129078563412", "0x48091e6a2c48091e6a2c48091e6a2c48",
- "[0x12, 0x90, 0x78, 0x56, 0x34, 0x12, 0x90, 0x78, \
- 0x56, 0x34, 0x12, 0x90, 0x78, 0x56, 0x34, 0x12]",
- "[0x12, 0x34, 0x56, 0x78, 0x90, 0x12, 0x34, 0x56, \
- 0x78, 0x90, 0x12, 0x34, 0x56, 0x78, 0x90, 0x12]",
- "", "", ""}
+ uint_impl! {
+ Self = u128,
+ ActualT = u128,
+ SignedT = i128,
+ NonZeroT = NonZeroU128,
+ BITS = 128,
+ MAX = 340282366920938463463374607431768211455,
+ rot = 16,
+ rot_op = "0x13f40000000000000000000000004f76",
+ rot_result = "0x4f7613f4",
+ swap_op = "0x12345678901234567890123456789012",
+ swapped = "0x12907856341290785634129078563412",
+ reversed = "0x48091e6a2c48091e6a2c48091e6a2c48",
+ le_bytes = "[0x12, 0x90, 0x78, 0x56, 0x34, 0x12, 0x90, 0x78, \
+ 0x56, 0x34, 0x12, 0x90, 0x78, 0x56, 0x34, 0x12]",
+ be_bytes = "[0x12, 0x34, 0x56, 0x78, 0x90, 0x12, 0x34, 0x56, \
+ 0x78, 0x90, 0x12, 0x34, 0x56, 0x78, 0x90, 0x12]",
+ to_xe_bytes_doc = "",
+ from_xe_bytes_doc = "",
+ bound_condition = "",
+ }
}
#[cfg(target_pointer_width = "16")]
impl usize {
- uint_impl! { usize, u16, isize, NonZeroUsize, 16, 65535, 4, "0xa003", "0x3a", "0x1234", "0x3412", "0x2c48",
- "[0x34, 0x12]", "[0x12, 0x34]",
- usize_isize_to_xe_bytes_doc!(), usize_isize_from_xe_bytes_doc!(),
- " on 16-bit targets" }
+ uint_impl! {
+ Self = usize,
+ ActualT = u16,
+ SignedT = isize,
+ NonZeroT = NonZeroUsize,
+ BITS = 16,
+ MAX = 65535,
+ rot = 4,
+ rot_op = "0xa003",
+ rot_result = "0x3a",
+ swap_op = "0x1234",
+ swapped = "0x3412",
+ reversed = "0x2c48",
+ le_bytes = "[0x34, 0x12]",
+ be_bytes = "[0x12, 0x34]",
+ to_xe_bytes_doc = usize_isize_to_xe_bytes_doc!(),
+ from_xe_bytes_doc = usize_isize_from_xe_bytes_doc!(),
+ bound_condition = " on 16-bit targets",
+ }
widening_impl! { usize, u32, 16, unsigned }
}
+
#[cfg(target_pointer_width = "32")]
impl usize {
- uint_impl! { usize, u32, isize, NonZeroUsize, 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!(),
- " on 32-bit targets" }
+ uint_impl! {
+ Self = usize,
+ ActualT = u32,
+ SignedT = isize,
+ NonZeroT = NonZeroUsize,
+ BITS = 32,
+ MAX = 4294967295,
+ rot = 8,
+ rot_op = "0x10000b3",
+ rot_result = "0xb301",
+ swap_op = "0x12345678",
+ swapped = "0x78563412",
+ reversed = "0x1e6a2c48",
+ le_bytes = "[0x78, 0x56, 0x34, 0x12]",
+ be_bytes = "[0x12, 0x34, 0x56, 0x78]",
+ to_xe_bytes_doc = usize_isize_to_xe_bytes_doc!(),
+ from_xe_bytes_doc = usize_isize_from_xe_bytes_doc!(),
+ bound_condition = " on 32-bit targets",
+ }
widening_impl! { usize, u64, 32, unsigned }
}
#[cfg(target_pointer_width = "64")]
impl usize {
- uint_impl! { usize, u64, isize, NonZeroUsize, 64, 18446744073709551615, 12, "0xaa00000000006e1", "0x6e10aa",
- "0x1234567890123456", "0x5634129078563412", "0x6a2c48091e6a2c48",
- "[0x56, 0x34, 0x12, 0x90, 0x78, 0x56, 0x34, 0x12]",
- "[0x12, 0x34, 0x56, 0x78, 0x90, 0x12, 0x34, 0x56]",
- usize_isize_to_xe_bytes_doc!(), usize_isize_from_xe_bytes_doc!(),
- " on 64-bit targets" }
+ uint_impl! {
+ Self = usize,
+ ActualT = u64,
+ SignedT = isize,
+ NonZeroT = NonZeroUsize,
+ BITS = 64,
+ MAX = 18446744073709551615,
+ rot = 12,
+ rot_op = "0xaa00000000006e1",
+ rot_result = "0x6e10aa",
+ swap_op = "0x1234567890123456",
+ swapped = "0x5634129078563412",
+ reversed = "0x6a2c48091e6a2c48",
+ le_bytes = "[0x56, 0x34, 0x12, 0x90, 0x78, 0x56, 0x34, 0x12]",
+ be_bytes = "[0x12, 0x34, 0x56, 0x78, 0x90, 0x12, 0x34, 0x56]",
+ to_xe_bytes_doc = usize_isize_to_xe_bytes_doc!(),
+ from_xe_bytes_doc = usize_isize_from_xe_bytes_doc!(),
+ bound_condition = " on 64-bit targets",
+ }
widening_impl! { usize, u128, 64, unsigned }
}
diff --git a/library/core/src/num/shells/i128.rs b/library/core/src/num/shells/i128.rs
index 7b048dc52..b3b3d3b48 100644
--- a/library/core/src/num/shells/i128.rs
+++ b/library/core/src/num/shells/i128.rs
@@ -1,6 +1,4 @@
-//! Constants for the 128-bit signed integer type.
-//!
-//! *[See also the `i128` primitive type][i128].*
+//! Redundant constants module for the [`i128` primitive type][i128].
//!
//! New code should use the associated constants directly on the primitive type.
diff --git a/library/core/src/num/shells/i16.rs b/library/core/src/num/shells/i16.rs
index 5c5812d5c..70a452e19 100644
--- a/library/core/src/num/shells/i16.rs
+++ b/library/core/src/num/shells/i16.rs
@@ -1,6 +1,4 @@
-//! Constants for the 16-bit signed integer type.
-//!
-//! *[See also the `i16` primitive type][i16].*
+//! Redundant constants module for the [`i16` primitive type][i16].
//!
//! New code should use the associated constants directly on the primitive type.
diff --git a/library/core/src/num/shells/i32.rs b/library/core/src/num/shells/i32.rs
index b283ac644..c30849e25 100644
--- a/library/core/src/num/shells/i32.rs
+++ b/library/core/src/num/shells/i32.rs
@@ -1,6 +1,4 @@
-//! Constants for the 32-bit signed integer type.
-//!
-//! *[See also the `i32` primitive type][i32].*
+//! Redundant constants module for the [`i32` primitive type][i32].
//!
//! New code should use the associated constants directly on the primitive type.
diff --git a/library/core/src/num/shells/i64.rs b/library/core/src/num/shells/i64.rs
index a416fa7e9..77d95d712 100644
--- a/library/core/src/num/shells/i64.rs
+++ b/library/core/src/num/shells/i64.rs
@@ -1,6 +1,4 @@
-//! Constants for the 64-bit signed integer type.
-//!
-//! *[See also the `i64` primitive type][i64].*
+//! Redundant constants module for the [`i64` primitive type][i64].
//!
//! New code should use the associated constants directly on the primitive type.
diff --git a/library/core/src/num/shells/i8.rs b/library/core/src/num/shells/i8.rs
index 02465013a..516ba8cde 100644
--- a/library/core/src/num/shells/i8.rs
+++ b/library/core/src/num/shells/i8.rs
@@ -1,6 +1,4 @@
-//! Constants for the 8-bit signed integer type.
-//!
-//! *[See also the `i8` primitive type][i8].*
+//! Redundant constants module for the [`i8` primitive type][i8].
//!
//! New code should use the associated constants directly on the primitive type.
diff --git a/library/core/src/num/shells/isize.rs b/library/core/src/num/shells/isize.rs
index 1579fbab6..828f7345b 100644
--- a/library/core/src/num/shells/isize.rs
+++ b/library/core/src/num/shells/isize.rs
@@ -1,6 +1,4 @@
-//! Constants for the pointer-sized signed integer type.
-//!
-//! *[See also the `isize` primitive type][isize].*
+//! Redundant constants module for the [`isize` primitive type][isize].
//!
//! New code should use the associated constants directly on the primitive type.
diff --git a/library/core/src/num/shells/u128.rs b/library/core/src/num/shells/u128.rs
index fe08cee58..b1e30e384 100644
--- a/library/core/src/num/shells/u128.rs
+++ b/library/core/src/num/shells/u128.rs
@@ -1,6 +1,4 @@
-//! Constants for the 128-bit unsigned integer type.
-//!
-//! *[See also the `u128` primitive type][u128].*
+//! Redundant constants module for the [`u128` primitive type][u128].
//!
//! New code should use the associated constants directly on the primitive type.
diff --git a/library/core/src/num/shells/u16.rs b/library/core/src/num/shells/u16.rs
index 36f8c6978..b203806f4 100644
--- a/library/core/src/num/shells/u16.rs
+++ b/library/core/src/num/shells/u16.rs
@@ -1,6 +1,4 @@
-//! Constants for the 16-bit unsigned integer type.
-//!
-//! *[See also the `u16` primitive type][u16].*
+//! Redundant constants module for the [`i16` primitive type][i16].
//!
//! New code should use the associated constants directly on the primitive type.
diff --git a/library/core/src/num/shells/u32.rs b/library/core/src/num/shells/u32.rs
index 1c369097d..4c84274e7 100644
--- a/library/core/src/num/shells/u32.rs
+++ b/library/core/src/num/shells/u32.rs
@@ -1,6 +1,4 @@
-//! Constants for the 32-bit unsigned integer type.
-//!
-//! *[See also the `u32` primitive type][u32].*
+//! Redundant constants module for the [`u32` primitive type][u32].
//!
//! New code should use the associated constants directly on the primitive type.
diff --git a/library/core/src/num/shells/u64.rs b/library/core/src/num/shells/u64.rs
index e8b691d15..47a95c682 100644
--- a/library/core/src/num/shells/u64.rs
+++ b/library/core/src/num/shells/u64.rs
@@ -1,6 +1,4 @@
-//! Constants for the 64-bit unsigned integer type.
-//!
-//! *[See also the `u64` primitive type][u64].*
+//! Redundant constants module for the [`u64` primitive type][u64].
//!
//! New code should use the associated constants directly on the primitive type.
diff --git a/library/core/src/num/shells/u8.rs b/library/core/src/num/shells/u8.rs
index 817c6a18a..360baef72 100644
--- a/library/core/src/num/shells/u8.rs
+++ b/library/core/src/num/shells/u8.rs
@@ -1,6 +1,4 @@
-//! Constants for the 8-bit unsigned integer type.
-//!
-//! *[See also the `u8` primitive type][u8].*
+//! Redundant constants module for the [`u8` primitive type][u8].
//!
//! New code should use the associated constants directly on the primitive type.
diff --git a/library/core/src/num/shells/usize.rs b/library/core/src/num/shells/usize.rs
index 3e1bec5ec..44c24dfc2 100644
--- a/library/core/src/num/shells/usize.rs
+++ b/library/core/src/num/shells/usize.rs
@@ -1,6 +1,4 @@
-//! Constants for the pointer-sized unsigned integer type.
-//!
-//! *[See also the `usize` primitive type][usize].*
+//! Redundant constants module for the [`usize` primitive type][usize].
//!
//! New code should use the associated constants directly on the primitive type.
diff --git a/library/core/src/num/uint_macros.rs b/library/core/src/num/uint_macros.rs
index 1c97c4686..932038a0b 100644
--- a/library/core/src/num/uint_macros.rs
+++ b/library/core/src/num/uint_macros.rs
@@ -1,10 +1,28 @@
macro_rules! uint_impl {
- ($SelfT:ty, $ActualT:ident, $SignedT:ident, $NonZeroT: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,
- $bound_condition:expr) => {
+ (
+ Self = $SelfT:ty,
+ ActualT = $ActualT:ident,
+ SignedT = $SignedT:ident,
+ NonZeroT = $NonZeroT:ident,
+
+ // There are all for use *only* in doc comments.
+ // As such, they're all passed as literals -- passing them as a string
+ // literal is fine if they need to be multiple code tokens.
+ // In non-comments, use the associated constants rather than these.
+ BITS = $BITS:literal,
+ MAX = $MaxV:literal,
+ rot = $rot:literal,
+ rot_op = $rot_op:literal,
+ rot_result = $rot_result:literal,
+ swap_op = $swap_op:literal,
+ swapped = $swapped:literal,
+ reversed = $reversed:literal,
+ le_bytes = $le_bytes:literal,
+ be_bytes = $be_bytes:literal,
+ to_xe_bytes_doc = $to_xe_bytes_doc:expr,
+ from_xe_bytes_doc = $from_xe_bytes_doc:expr,
+ bound_condition = $bound_condition:literal,
+ ) => {
/// The smallest value that can be represented by this integer type.
///
/// # Examples
@@ -18,7 +36,7 @@ macro_rules! uint_impl {
pub const MIN: Self = 0;
/// The largest value that can be represented by this integer type
- #[doc = concat!("(2<sup>", $BITS, "</sup> &minus; 1", $bound_condition, ")")]
+ #[doc = concat!("(2<sup>", $BITS, "</sup> &minus; 1", $bound_condition, ").")]
///
/// # Examples
///
@@ -38,7 +56,7 @@ macro_rules! uint_impl {
#[doc = concat!("assert_eq!(", stringify!($SelfT), "::BITS, ", stringify!($BITS), ");")]
/// ```
#[stable(feature = "int_bits_const", since = "1.53.0")]
- pub const BITS: u32 = $BITS;
+ pub const BITS: u32 = Self::MAX.count_ones();
/// Converts a string slice in a given base to an integer.
///
@@ -705,14 +723,17 @@ macro_rules! uint_impl {
/// ```
#[stable(feature = "int_log", since = "1.67.0")]
#[rustc_const_stable(feature = "int_log", since = "1.67.0")]
- #[rustc_allow_const_fn_unstable(const_option)]
#[must_use = "this returns the result of the operation, \
without modifying the original"]
#[inline]
#[track_caller]
pub const fn ilog(self, base: Self) -> u32 {
assert!(base >= 2, "base of integer logarithm must be at least 2");
- self.checked_ilog(base).expect("argument of integer logarithm must be positive")
+ if let Some(log) = self.checked_ilog(base) {
+ log
+ } else {
+ int_log10::panic_for_nonpositive_argument()
+ }
}
/// Returns the base 2 logarithm of the number, rounded down.
@@ -728,13 +749,16 @@ macro_rules! uint_impl {
/// ```
#[stable(feature = "int_log", since = "1.67.0")]
#[rustc_const_stable(feature = "int_log", since = "1.67.0")]
- #[rustc_allow_const_fn_unstable(const_option)]
#[must_use = "this returns the result of the operation, \
without modifying the original"]
#[inline]
#[track_caller]
pub const fn ilog2(self) -> u32 {
- self.checked_ilog2().expect("argument of integer logarithm must be positive")
+ if let Some(log) = self.checked_ilog2() {
+ log
+ } else {
+ int_log10::panic_for_nonpositive_argument()
+ }
}
/// Returns the base 10 logarithm of the number, rounded down.
@@ -750,13 +774,16 @@ macro_rules! uint_impl {
/// ```
#[stable(feature = "int_log", since = "1.67.0")]
#[rustc_const_stable(feature = "int_log", since = "1.67.0")]
- #[rustc_allow_const_fn_unstable(const_option)]
#[must_use = "this returns the result of the operation, \
without modifying the original"]
#[inline]
#[track_caller]
pub const fn ilog10(self) -> u32 {
- self.checked_ilog10().expect("argument of integer logarithm must be positive")
+ if let Some(log) = self.checked_ilog10() {
+ log
+ } else {
+ int_log10::panic_for_nonpositive_argument()
+ }
}
/// Returns the logarithm of the number with respect to an arbitrary base,
@@ -1381,7 +1408,7 @@ macro_rules! uint_impl {
// SAFETY: the masking by the bitsize of the type ensures that we do not shift
// out of bounds
unsafe {
- self.unchecked_shl(rhs & ($BITS - 1))
+ self.unchecked_shl(rhs & (Self::BITS - 1))
}
}
@@ -1414,7 +1441,7 @@ macro_rules! uint_impl {
// SAFETY: the masking by the bitsize of the type ensures that we do not shift
// out of bounds
unsafe {
- self.unchecked_shr(rhs & ($BITS - 1))
+ self.unchecked_shr(rhs & (Self::BITS - 1))
}
}
@@ -1838,7 +1865,7 @@ macro_rules! uint_impl {
without modifying the original"]
#[inline(always)]
pub const fn overflowing_shl(self, rhs: u32) -> (Self, bool) {
- (self.wrapping_shl(rhs), (rhs > ($BITS - 1)))
+ (self.wrapping_shl(rhs), rhs >= Self::BITS)
}
/// Shifts self right by `rhs` bits.
@@ -1863,7 +1890,7 @@ macro_rules! uint_impl {
without modifying the original"]
#[inline(always)]
pub const fn overflowing_shr(self, rhs: u32) -> (Self, bool) {
- (self.wrapping_shr(rhs), (rhs > ($BITS - 1)))
+ (self.wrapping_shr(rhs), rhs >= Self::BITS)
}
/// Raises self to the power of `exp`, using exponentiation by squaring.
diff --git a/library/core/src/ops/arith.rs b/library/core/src/ops/arith.rs
index 75c52d3ec..0c7ee9630 100644
--- a/library/core/src/ops/arith.rs
+++ b/library/core/src/ops/arith.rs
@@ -86,7 +86,8 @@ pub trait Add<Rhs = Self> {
/// ```
/// assert_eq!(12 + 1, 13);
/// ```
- #[must_use]
+ #[must_use = "this returns the result of the operation, without modifying the original"]
+ #[rustc_diagnostic_item = "add"]
#[stable(feature = "rust1", since = "1.0.0")]
fn add(self, rhs: Rhs) -> Self::Output;
}
@@ -195,7 +196,8 @@ pub trait Sub<Rhs = Self> {
/// ```
/// assert_eq!(12 - 1, 11);
/// ```
- #[must_use]
+ #[must_use = "this returns the result of the operation, without modifying the original"]
+ #[rustc_diagnostic_item = "sub"]
#[stable(feature = "rust1", since = "1.0.0")]
fn sub(self, rhs: Rhs) -> Self::Output;
}
@@ -325,7 +327,8 @@ pub trait Mul<Rhs = Self> {
/// ```
/// assert_eq!(12 * 2, 24);
/// ```
- #[must_use]
+ #[must_use = "this returns the result of the operation, without modifying the original"]
+ #[rustc_diagnostic_item = "mul"]
#[stable(feature = "rust1", since = "1.0.0")]
fn mul(self, rhs: Rhs) -> Self::Output;
}
@@ -459,7 +462,8 @@ pub trait Div<Rhs = Self> {
/// ```
/// assert_eq!(12 / 2, 6);
/// ```
- #[must_use]
+ #[must_use = "this returns the result of the operation, without modifying the original"]
+ #[rustc_diagnostic_item = "div"]
#[stable(feature = "rust1", since = "1.0.0")]
fn div(self, rhs: Rhs) -> Self::Output;
}
@@ -545,7 +549,7 @@ div_impl_float! { f32 f64 }
#[lang = "rem"]
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_on_unimplemented(
- message = "cannot mod `{Self}` by `{Rhs}`",
+ message = "cannot calculate the remainder of `{Self}` divided by `{Rhs}`",
label = "no implementation for `{Self} % {Rhs}`"
)]
#[doc(alias = "%")]
@@ -562,7 +566,8 @@ pub trait Rem<Rhs = Self> {
/// ```
/// assert_eq!(12 % 10, 2);
/// ```
- #[must_use]
+ #[must_use = "this returns the result of the operation, without modifying the original"]
+ #[rustc_diagnostic_item = "rem"]
#[stable(feature = "rust1", since = "1.0.0")]
fn rem(self, rhs: Rhs) -> Self::Output;
}
@@ -678,7 +683,8 @@ pub trait Neg {
/// let x: i32 = 12;
/// assert_eq!(-x, -12);
/// ```
- #[must_use]
+ #[must_use = "this returns the result of the operation, without modifying the original"]
+ #[rustc_diagnostic_item = "neg"]
#[stable(feature = "rust1", since = "1.0.0")]
fn neg(self) -> Self::Output;
}
@@ -981,7 +987,7 @@ div_assign_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 }
#[lang = "rem_assign"]
#[stable(feature = "op_assign_traits", since = "1.8.0")]
#[rustc_on_unimplemented(
- message = "cannot mod-assign `{Self}` by `{Rhs}``",
+ message = "cannot calculate and assign the remainder of `{Self}` divided by `{Rhs}`",
label = "no implementation for `{Self} %= {Rhs}`"
)]
#[doc(alias = "%")]
diff --git a/library/core/src/ops/control_flow.rs b/library/core/src/ops/control_flow.rs
index cd183540c..117706fb4 100644
--- a/library/core/src/ops/control_flow.rs
+++ b/library/core/src/ops/control_flow.rs
@@ -259,46 +259,3 @@ impl<R: ops::Try> ControlFlow<R, R::Output> {
}
}
}
-
-impl<B> ControlFlow<B, ()> {
- /// It's frequently the case that there's no value needed with `Continue`,
- /// so this provides a way to avoid typing `(())`, if you prefer it.
- ///
- /// # Examples
- ///
- /// ```
- /// #![feature(control_flow_enum)]
- /// use std::ops::ControlFlow;
- ///
- /// let mut partial_sum = 0;
- /// let last_used = (1..10).chain(20..25).try_for_each(|x| {
- /// partial_sum += x;
- /// if partial_sum > 100 { ControlFlow::Break(x) }
- /// else { ControlFlow::CONTINUE }
- /// });
- /// assert_eq!(last_used.break_value(), Some(22));
- /// ```
- #[unstable(feature = "control_flow_enum", reason = "new API", issue = "75744")]
- pub const CONTINUE: Self = ControlFlow::Continue(());
-}
-
-impl<C> ControlFlow<(), C> {
- /// APIs like `try_for_each` don't need values with `Break`,
- /// so this provides a way to avoid typing `(())`, if you prefer it.
- ///
- /// # Examples
- ///
- /// ```
- /// #![feature(control_flow_enum)]
- /// use std::ops::ControlFlow;
- ///
- /// let mut partial_sum = 0;
- /// (1..10).chain(20..25).try_for_each(|x| {
- /// if partial_sum > 100 { ControlFlow::BREAK }
- /// else { partial_sum += x; ControlFlow::CONTINUE }
- /// });
- /// assert_eq!(partial_sum, 108);
- /// ```
- #[unstable(feature = "control_flow_enum", reason = "new API", issue = "75744")]
- pub const BREAK: Self = ControlFlow::Break(());
-}
diff --git a/library/core/src/ops/range.rs b/library/core/src/ops/range.rs
index d29ae3561..b8ab26564 100644
--- a/library/core/src/ops/range.rs
+++ b/library/core/src/ops/range.rs
@@ -96,7 +96,7 @@ impl<Idx: fmt::Debug> fmt::Debug for Range<Idx> {
}
}
-impl<Idx: PartialOrd<Idx>> Range<Idx> {
+impl<Idx: ~const PartialOrd<Idx>> Range<Idx> {
/// Returns `true` if `item` is contained in the range.
///
/// # Examples
@@ -116,10 +116,11 @@ impl<Idx: PartialOrd<Idx>> Range<Idx> {
/// assert!(!(f32::NAN..1.0).contains(&0.5));
/// ```
#[stable(feature = "range_contains", since = "1.35.0")]
- pub fn contains<U>(&self, item: &U) -> bool
+ #[rustc_const_unstable(feature = "const_range_bounds", issue = "108082")]
+ pub const fn contains<U>(&self, item: &U) -> bool
where
- Idx: PartialOrd<U>,
- U: ?Sized + PartialOrd<Idx>,
+ Idx: ~const PartialOrd<U>,
+ U: ?Sized + ~const PartialOrd<Idx>,
{
<Self as RangeBounds<Idx>>::contains(self, item)
}
@@ -142,7 +143,8 @@ impl<Idx: PartialOrd<Idx>> Range<Idx> {
/// assert!( (f32::NAN..5.0).is_empty());
/// ```
#[stable(feature = "range_is_empty", since = "1.47.0")]
- pub fn is_empty(&self) -> bool {
+ #[rustc_const_unstable(feature = "const_range_bounds", issue = "108082")]
+ pub const fn is_empty(&self) -> bool {
!(self.start < self.end)
}
}
@@ -199,7 +201,7 @@ impl<Idx: fmt::Debug> fmt::Debug for RangeFrom<Idx> {
}
}
-impl<Idx: PartialOrd<Idx>> RangeFrom<Idx> {
+impl<Idx: ~const PartialOrd<Idx>> RangeFrom<Idx> {
/// Returns `true` if `item` is contained in the range.
///
/// # Examples
@@ -214,10 +216,11 @@ impl<Idx: PartialOrd<Idx>> RangeFrom<Idx> {
/// assert!(!(f32::NAN..).contains(&0.5));
/// ```
#[stable(feature = "range_contains", since = "1.35.0")]
- pub fn contains<U>(&self, item: &U) -> bool
+ #[rustc_const_unstable(feature = "const_range_bounds", issue = "108082")]
+ pub const fn contains<U>(&self, item: &U) -> bool
where
- Idx: PartialOrd<U>,
- U: ?Sized + PartialOrd<Idx>,
+ Idx: ~const PartialOrd<U>,
+ U: ?Sized + ~const PartialOrd<Idx>,
{
<Self as RangeBounds<Idx>>::contains(self, item)
}
@@ -280,7 +283,7 @@ impl<Idx: fmt::Debug> fmt::Debug for RangeTo<Idx> {
}
}
-impl<Idx: PartialOrd<Idx>> RangeTo<Idx> {
+impl<Idx: ~const PartialOrd<Idx>> RangeTo<Idx> {
/// Returns `true` if `item` is contained in the range.
///
/// # Examples
@@ -295,10 +298,11 @@ impl<Idx: PartialOrd<Idx>> RangeTo<Idx> {
/// assert!(!(..f32::NAN).contains(&0.5));
/// ```
#[stable(feature = "range_contains", since = "1.35.0")]
- pub fn contains<U>(&self, item: &U) -> bool
+ #[rustc_const_unstable(feature = "const_range_bounds", issue = "108082")]
+ pub const fn contains<U>(&self, item: &U) -> bool
where
- Idx: PartialOrd<U>,
- U: ?Sized + PartialOrd<Idx>,
+ Idx: ~const PartialOrd<U>,
+ U: ?Sized + ~const PartialOrd<Idx>,
{
<Self as RangeBounds<Idx>>::contains(self, item)
}
@@ -437,7 +441,8 @@ impl<Idx> RangeInclusive<Idx> {
/// ```
#[stable(feature = "inclusive_range_methods", since = "1.27.0")]
#[inline]
- pub fn into_inner(self) -> (Idx, Idx) {
+ #[rustc_const_unstable(feature = "const_range_bounds", issue = "108082")]
+ pub const fn into_inner(self) -> (Idx, Idx) {
(self.start, self.end)
}
}
@@ -469,7 +474,7 @@ impl<Idx: fmt::Debug> fmt::Debug for RangeInclusive<Idx> {
}
}
-impl<Idx: PartialOrd<Idx>> RangeInclusive<Idx> {
+impl<Idx: ~const PartialOrd<Idx>> RangeInclusive<Idx> {
/// Returns `true` if `item` is contained in the range.
///
/// # Examples
@@ -500,10 +505,11 @@ impl<Idx: PartialOrd<Idx>> RangeInclusive<Idx> {
/// assert!(!r.contains(&3) && !r.contains(&5));
/// ```
#[stable(feature = "range_contains", since = "1.35.0")]
- pub fn contains<U>(&self, item: &U) -> bool
+ #[rustc_const_unstable(feature = "const_range_bounds", issue = "108082")]
+ pub const fn contains<U>(&self, item: &U) -> bool
where
- Idx: PartialOrd<U>,
- U: ?Sized + PartialOrd<Idx>,
+ Idx: ~const PartialOrd<U>,
+ U: ?Sized + ~const PartialOrd<Idx>,
{
<Self as RangeBounds<Idx>>::contains(self, item)
}
@@ -535,8 +541,9 @@ impl<Idx: PartialOrd<Idx>> RangeInclusive<Idx> {
/// assert!(r.is_empty());
/// ```
#[stable(feature = "range_is_empty", since = "1.47.0")]
+ #[rustc_const_unstable(feature = "const_range_bounds", issue = "108082")]
#[inline]
- pub fn is_empty(&self) -> bool {
+ pub const fn is_empty(&self) -> bool {
self.exhausted || !(self.start <= self.end)
}
}
@@ -598,7 +605,7 @@ impl<Idx: fmt::Debug> fmt::Debug for RangeToInclusive<Idx> {
}
}
-impl<Idx: PartialOrd<Idx>> RangeToInclusive<Idx> {
+impl<Idx: ~const PartialOrd<Idx>> RangeToInclusive<Idx> {
/// Returns `true` if `item` is contained in the range.
///
/// # Examples
@@ -613,10 +620,11 @@ impl<Idx: PartialOrd<Idx>> RangeToInclusive<Idx> {
/// assert!(!(..=f32::NAN).contains(&0.5));
/// ```
#[stable(feature = "range_contains", since = "1.35.0")]
- pub fn contains<U>(&self, item: &U) -> bool
+ #[rustc_const_unstable(feature = "const_range_bounds", issue = "108082")]
+ pub const fn contains<U>(&self, item: &U) -> bool
where
- Idx: PartialOrd<U>,
- U: ?Sized + PartialOrd<Idx>,
+ Idx: ~const PartialOrd<U>,
+ U: ?Sized + ~const PartialOrd<Idx>,
{
<Self as RangeBounds<Idx>>::contains(self, item)
}
@@ -757,6 +765,7 @@ impl<T: Clone> Bound<&T> {
/// `RangeBounds` is implemented by Rust's built-in range types, produced
/// by range syntax like `..`, `a..`, `..b`, `..=c`, `d..e`, or `f..=g`.
#[stable(feature = "collections_range", since = "1.28.0")]
+#[const_trait]
pub trait RangeBounds<T: ?Sized> {
/// Start index bound.
///
@@ -809,8 +818,8 @@ pub trait RangeBounds<T: ?Sized> {
#[stable(feature = "range_contains", since = "1.35.0")]
fn contains<U>(&self, item: &U) -> bool
where
- T: PartialOrd<U>,
- U: ?Sized + PartialOrd<T>,
+ T: ~const PartialOrd<U>,
+ U: ?Sized + ~const PartialOrd<T>,
{
(match self.start_bound() {
Included(start) => start <= item,
@@ -827,7 +836,8 @@ pub trait RangeBounds<T: ?Sized> {
use self::Bound::{Excluded, Included, Unbounded};
#[stable(feature = "collections_range", since = "1.28.0")]
-impl<T: ?Sized> RangeBounds<T> for RangeFull {
+#[rustc_const_unstable(feature = "const_range_bounds", issue = "108082")]
+impl<T: ?Sized> const RangeBounds<T> for RangeFull {
fn start_bound(&self) -> Bound<&T> {
Unbounded
}
@@ -837,7 +847,8 @@ impl<T: ?Sized> RangeBounds<T> for RangeFull {
}
#[stable(feature = "collections_range", since = "1.28.0")]
-impl<T> RangeBounds<T> for RangeFrom<T> {
+#[rustc_const_unstable(feature = "const_range_bounds", issue = "108082")]
+impl<T> const RangeBounds<T> for RangeFrom<T> {
fn start_bound(&self) -> Bound<&T> {
Included(&self.start)
}
@@ -847,7 +858,8 @@ impl<T> RangeBounds<T> for RangeFrom<T> {
}
#[stable(feature = "collections_range", since = "1.28.0")]
-impl<T> RangeBounds<T> for RangeTo<T> {
+#[rustc_const_unstable(feature = "const_range_bounds", issue = "108082")]
+impl<T> const RangeBounds<T> for RangeTo<T> {
fn start_bound(&self) -> Bound<&T> {
Unbounded
}
@@ -857,7 +869,8 @@ impl<T> RangeBounds<T> for RangeTo<T> {
}
#[stable(feature = "collections_range", since = "1.28.0")]
-impl<T> RangeBounds<T> for Range<T> {
+#[rustc_const_unstable(feature = "const_range_bounds", issue = "108082")]
+impl<T> const RangeBounds<T> for Range<T> {
fn start_bound(&self) -> Bound<&T> {
Included(&self.start)
}
@@ -867,7 +880,8 @@ impl<T> RangeBounds<T> for Range<T> {
}
#[stable(feature = "collections_range", since = "1.28.0")]
-impl<T> RangeBounds<T> for RangeInclusive<T> {
+#[rustc_const_unstable(feature = "const_range_bounds", issue = "108082")]
+impl<T> const RangeBounds<T> for RangeInclusive<T> {
fn start_bound(&self) -> Bound<&T> {
Included(&self.start)
}
@@ -883,7 +897,8 @@ impl<T> RangeBounds<T> for RangeInclusive<T> {
}
#[stable(feature = "collections_range", since = "1.28.0")]
-impl<T> RangeBounds<T> for RangeToInclusive<T> {
+#[rustc_const_unstable(feature = "const_range_bounds", issue = "108082")]
+impl<T> const RangeBounds<T> for RangeToInclusive<T> {
fn start_bound(&self) -> Bound<&T> {
Unbounded
}
@@ -893,7 +908,8 @@ impl<T> RangeBounds<T> for RangeToInclusive<T> {
}
#[stable(feature = "collections_range", since = "1.28.0")]
-impl<T> RangeBounds<T> for (Bound<T>, Bound<T>) {
+#[rustc_const_unstable(feature = "const_range_bounds", issue = "108082")]
+impl<T> const RangeBounds<T> for (Bound<T>, Bound<T>) {
fn start_bound(&self) -> Bound<&T> {
match *self {
(Included(ref start), _) => Included(start),
@@ -912,7 +928,8 @@ impl<T> RangeBounds<T> for (Bound<T>, Bound<T>) {
}
#[stable(feature = "collections_range", since = "1.28.0")]
-impl<'a, T: ?Sized + 'a> RangeBounds<T> for (Bound<&'a T>, Bound<&'a T>) {
+#[rustc_const_unstable(feature = "const_range_bounds", issue = "108082")]
+impl<'a, T: ?Sized + 'a> const RangeBounds<T> for (Bound<&'a T>, Bound<&'a T>) {
fn start_bound(&self) -> Bound<&T> {
self.0
}
@@ -923,7 +940,8 @@ impl<'a, T: ?Sized + 'a> RangeBounds<T> for (Bound<&'a T>, Bound<&'a T>) {
}
#[stable(feature = "collections_range", since = "1.28.0")]
-impl<T> RangeBounds<T> for RangeFrom<&T> {
+#[rustc_const_unstable(feature = "const_range_bounds", issue = "108082")]
+impl<T> const RangeBounds<T> for RangeFrom<&T> {
fn start_bound(&self) -> Bound<&T> {
Included(self.start)
}
@@ -933,7 +951,8 @@ impl<T> RangeBounds<T> for RangeFrom<&T> {
}
#[stable(feature = "collections_range", since = "1.28.0")]
-impl<T> RangeBounds<T> for RangeTo<&T> {
+#[rustc_const_unstable(feature = "const_range_bounds", issue = "108082")]
+impl<T> const RangeBounds<T> for RangeTo<&T> {
fn start_bound(&self) -> Bound<&T> {
Unbounded
}
@@ -943,7 +962,8 @@ impl<T> RangeBounds<T> for RangeTo<&T> {
}
#[stable(feature = "collections_range", since = "1.28.0")]
-impl<T> RangeBounds<T> for Range<&T> {
+#[rustc_const_unstable(feature = "const_range_bounds", issue = "108082")]
+impl<T> const RangeBounds<T> for Range<&T> {
fn start_bound(&self) -> Bound<&T> {
Included(self.start)
}
@@ -953,7 +973,8 @@ impl<T> RangeBounds<T> for Range<&T> {
}
#[stable(feature = "collections_range", since = "1.28.0")]
-impl<T> RangeBounds<T> for RangeInclusive<&T> {
+#[rustc_const_unstable(feature = "const_range_bounds", issue = "108082")]
+impl<T> const RangeBounds<T> for RangeInclusive<&T> {
fn start_bound(&self) -> Bound<&T> {
Included(self.start)
}
@@ -963,7 +984,8 @@ impl<T> RangeBounds<T> for RangeInclusive<&T> {
}
#[stable(feature = "collections_range", since = "1.28.0")]
-impl<T> RangeBounds<T> for RangeToInclusive<&T> {
+#[rustc_const_unstable(feature = "const_range_bounds", issue = "108082")]
+impl<T> const RangeBounds<T> for RangeToInclusive<&T> {
fn start_bound(&self) -> Bound<&T> {
Unbounded
}
diff --git a/library/core/src/ops/try_trait.rs b/library/core/src/ops/try_trait.rs
index 84a690468..86aa1e4fd 100644
--- a/library/core/src/ops/try_trait.rs
+++ b/library/core/src/ops/try_trait.rs
@@ -379,13 +379,27 @@ pub(crate) type ChangeOutputType<T, V> = <<T as Try>::Residual as Residual<V>>::
pub(crate) struct NeverShortCircuit<T>(pub T);
impl<T> NeverShortCircuit<T> {
- /// Implementation for building `ConstFnMutClosure` for wrapping the output of a ~const FnMut in a `NeverShortCircuit`.
+ /// Wraps a unary function to produce one that wraps the output into a `NeverShortCircuit`.
+ ///
+ /// This is useful for implementing infallible functions in terms of the `try_` ones,
+ /// without accidentally capturing extra generic parameters in a closure.
+ #[inline]
+ pub fn wrap_mut_1<A>(mut f: impl FnMut(A) -> T) -> impl FnMut(A) -> NeverShortCircuit<T> {
+ move |a| NeverShortCircuit(f(a))
+ }
+
#[inline]
- pub const fn wrap_mut_2_imp<A, B, F: ~const FnMut(A, B) -> T>(
- f: &mut F,
- (a, b): (A, B),
- ) -> NeverShortCircuit<T> {
- NeverShortCircuit(f(a, b))
+ pub fn wrap_mut_2<A, B>(
+ mut f: impl ~const FnMut(A, B) -> T,
+ ) -> impl ~const FnMut(A, B) -> Self {
+ cfg_if! {
+ if #[cfg(bootstrap)] {
+ #[allow(unused_parens)]
+ (const move |a, b| NeverShortCircuit(f(a, b)))
+ } else {
+ const move |a, b| NeverShortCircuit(f(a, b))
+ }
+ }
}
}
diff --git a/library/core/src/option.rs b/library/core/src/option.rs
index 7cc00e3f8..994c08d1f 100644
--- a/library/core/src/option.rs
+++ b/library/core/src/option.rs
@@ -551,8 +551,9 @@ use crate::marker::Destruct;
use crate::panicking::{panic, panic_str};
use crate::pin::Pin;
use crate::{
- convert, hint, mem,
+ cmp, convert, hint, mem,
ops::{self, ControlFlow, Deref, DerefMut},
+ slice,
};
/// The `Option` type. See [the module level documentation](self) for more.
@@ -734,6 +735,124 @@ impl<T> Option<T> {
}
}
+ const fn get_some_offset() -> isize {
+ if mem::size_of::<Option<T>>() == mem::size_of::<T>() {
+ // niche optimization means the `T` is always stored at the same position as the Option.
+ 0
+ } else {
+ assert!(mem::size_of::<Option<T>>() == mem::size_of::<Option<mem::MaybeUninit<T>>>());
+ let some_uninit = Some(mem::MaybeUninit::<T>::uninit());
+ // SAFETY: This gets the byte offset of the `Some(_)` value following the fact that
+ // niche optimization is not active, and thus Option<T> and Option<MaybeUninit<t>> share
+ // the same layout.
+ unsafe {
+ (some_uninit.as_ref().unwrap() as *const mem::MaybeUninit<T>)
+ .byte_offset_from(&some_uninit as *const Option<mem::MaybeUninit<T>>)
+ }
+ }
+ }
+
+ /// Returns a slice of the contained value, if any. If this is `None`, an
+ /// empty slice is returned. This can be useful to have a single type of
+ /// iterator over an `Option` or slice.
+ ///
+ /// Note: Should you have an `Option<&T>` and wish to get a slice of `T`,
+ /// you can unpack it via `opt.map_or(&[], std::slice::from_ref)`.
+ ///
+ /// # Examples
+ ///
+ /// ```rust
+ /// #![feature(option_as_slice)]
+ ///
+ /// assert_eq!(
+ /// [Some(1234).as_slice(), None.as_slice()],
+ /// [&[1234][..], &[][..]],
+ /// );
+ /// ```
+ ///
+ /// The inverse of this function is (discounting
+ /// borrowing) [`[_]::first`](slice::first):
+ ///
+ /// ```rust
+ /// #![feature(option_as_slice)]
+ ///
+ /// for i in [Some(1234_u16), None] {
+ /// assert_eq!(i.as_ref(), i.as_slice().first());
+ /// }
+ /// ```
+ #[inline]
+ #[must_use]
+ #[unstable(feature = "option_as_slice", issue = "108545")]
+ pub fn as_slice(&self) -> &[T] {
+ // SAFETY: This is sound as long as `get_some_offset` returns the
+ // correct offset. Though in the `None` case, the slice may be located
+ // at a pointer pointing into padding, the fact that the slice is
+ // empty, and the padding is at a properly aligned position for a
+ // value of that type makes it sound.
+ unsafe {
+ slice::from_raw_parts(
+ (self as *const Option<T>).wrapping_byte_offset(Self::get_some_offset())
+ as *const T,
+ self.is_some() as usize,
+ )
+ }
+ }
+
+ /// Returns a mutable slice of the contained value, if any. If this is
+ /// `None`, an empty slice is returned. This can be useful to have a
+ /// single type of iterator over an `Option` or slice.
+ ///
+ /// Note: Should you have an `Option<&mut T>` instead of a
+ /// `&mut Option<T>`, which this method takes, you can obtain a mutable
+ /// slice via `opt.map_or(&mut [], std::slice::from_mut)`.
+ ///
+ /// # Examples
+ ///
+ /// ```rust
+ /// #![feature(option_as_slice)]
+ ///
+ /// assert_eq!(
+ /// [Some(1234).as_mut_slice(), None.as_mut_slice()],
+ /// [&mut [1234][..], &mut [][..]],
+ /// );
+ /// ```
+ ///
+ /// The result is a mutable slice of zero or one items that points into
+ /// our original `Option`:
+ ///
+ /// ```rust
+ /// #![feature(option_as_slice)]
+ ///
+ /// let mut x = Some(1234);
+ /// x.as_mut_slice()[0] += 1;
+ /// assert_eq!(x, Some(1235));
+ /// ```
+ ///
+ /// The inverse of this method (discounting borrowing)
+ /// is [`[_]::first_mut`](slice::first_mut):
+ ///
+ /// ```rust
+ /// #![feature(option_as_slice)]
+ ///
+ /// assert_eq!(Some(123).as_mut_slice().first_mut(), Some(&mut 123))
+ /// ```
+ #[inline]
+ #[must_use]
+ #[unstable(feature = "option_as_slice", issue = "108545")]
+ pub fn as_mut_slice(&mut self) -> &mut [T] {
+ // SAFETY: This is sound as long as `get_some_offset` returns the
+ // correct offset. Though in the `None` case, the slice may be located
+ // at a pointer pointing into padding, the fact that the slice is
+ // empty, and the padding is at a properly aligned position for a
+ // value of that type makes it sound.
+ unsafe {
+ slice::from_raw_parts_mut(
+ (self as *mut Option<T>).wrapping_byte_offset(Self::get_some_offset()) as *mut T,
+ self.is_some() as usize,
+ )
+ }
+ }
+
/////////////////////////////////////////////////////////////////////////
// Getting to contained values
/////////////////////////////////////////////////////////////////////////
@@ -943,7 +1062,7 @@ impl<T> Option<T> {
// Transforming contained values
/////////////////////////////////////////////////////////////////////////
- /// Maps an `Option<T>` to `Option<U>` by applying a function to a contained value.
+ /// Maps an `Option<T>` to `Option<U>` by applying a function to a contained value (if `Some`) or returns `None` (if `None`).
///
/// # Examples
///
@@ -955,8 +1074,10 @@ impl<T> Option<T> {
/// let maybe_some_string = Some(String::from("Hello, World!"));
/// // `Option::map` takes self *by value*, consuming `maybe_some_string`
/// let maybe_some_len = maybe_some_string.map(|s| s.len());
- ///
/// assert_eq!(maybe_some_len, Some(13));
+ ///
+ /// let x: Option<&str> = None;
+ /// assert_eq!(x.map(|s| s.len()), None);
/// ```
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
@@ -2090,6 +2211,12 @@ impl<T: PartialEq> PartialEq for Option<T> {
}
}
+/// This specialization trait is a workaround for LLVM not currently (2023-01)
+/// being able to optimize this itself, even though Alive confirms that it would
+/// be legal to do so: <https://github.com/llvm/llvm-project/issues/52622>
+///
+/// Once that's fixed, `Option` should go back to deriving `PartialEq`, as
+/// it used to do before <https://github.com/rust-lang/rust/pull/103556>.
#[unstable(feature = "spec_option_partial_eq", issue = "none", reason = "exposed only for rustc")]
#[doc(hidden)]
pub trait SpecOptionPartialEq: Sized {
@@ -2146,6 +2273,14 @@ impl<T> SpecOptionPartialEq for crate::ptr::NonNull<T> {
}
}
+#[stable(feature = "rust1", since = "1.0.0")]
+impl SpecOptionPartialEq for cmp::Ordering {
+ #[inline]
+ fn eq(l: &Option<Self>, r: &Option<Self>) -> bool {
+ l.map_or(2, |x| x as i8) == r.map_or(2, |x| x as i8)
+ }
+}
+
/////////////////////////////////////////////////////////////////////////////
// The Option Iterators
/////////////////////////////////////////////////////////////////////////////
diff --git a/library/core/src/panicking.rs b/library/core/src/panicking.rs
index 48e90e6d7..805a1e51a 100644
--- a/library/core/src/panicking.rs
+++ b/library/core/src/panicking.rs
@@ -117,7 +117,7 @@ pub const fn panic(expr: &'static str) -> ! {
/// Like `panic`, but without unwinding and track_caller to reduce the impact on codesize.
#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never), cold)]
#[cfg_attr(feature = "panic_immediate_abort", inline)]
-#[cfg_attr(not(bootstrap), lang = "panic_nounwind")] // needed by codegen for non-unwinding panics
+#[lang = "panic_nounwind"] // needed by codegen for non-unwinding panics
#[rustc_nounwind]
pub fn panic_nounwind(expr: &'static str) -> ! {
panic_nounwind_fmt(fmt::Arguments::new_v1(&[expr], &[]));
@@ -165,8 +165,7 @@ fn panic_bounds_check(index: usize, len: usize) -> ! {
/// any extra arguments (including those synthesized by track_caller).
#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never), cold)]
#[cfg_attr(feature = "panic_immediate_abort", inline)]
-#[cfg_attr(bootstrap, lang = "panic_no_unwind")] // needed by codegen for panic in nounwind function
-#[cfg_attr(not(bootstrap), lang = "panic_cannot_unwind")] // needed by codegen for panic in nounwind function
+#[lang = "panic_cannot_unwind"] // needed by codegen for panic in nounwind function
#[rustc_nounwind]
fn panic_cannot_unwind() -> ! {
panic_nounwind("panic in a function that cannot unwind")
diff --git a/library/core/src/primitive_docs.rs b/library/core/src/primitive_docs.rs
index d6e9da187..6f78811a1 100644
--- a/library/core/src/primitive_docs.rs
+++ b/library/core/src/primitive_docs.rs
@@ -587,8 +587,10 @@ mod prim_pointer {}
/// 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`].
+/// * A repeat expression `[expr; N]` where `N` is how many times to repeat `expr` in the array. `expr` must either be:
+///
+/// * A value of a type implementing the [`Copy`] trait
+/// * A `const` value
///
/// Note that `[expr; 0]` is allowed, and produces an empty array.
/// This will still evaluate `expr`, however, and immediately drop the resulting value, so
diff --git a/library/core/src/ptr/alignment.rs b/library/core/src/ptr/alignment.rs
index 2123147c7..efe6d4183 100644
--- a/library/core/src/ptr/alignment.rs
+++ b/library/core/src/ptr/alignment.rs
@@ -41,7 +41,7 @@ impl Alignment {
/// Returns the alignment for a type.
///
/// This provides the same numerical value as [`mem::align_of`],
- /// but in an `Alignment` instead of a `usize.
+ /// but in an `Alignment` instead of a `usize`.
#[unstable(feature = "ptr_alignment_type", issue = "102070")]
#[inline]
pub const fn of<T>() -> Self {
diff --git a/library/core/src/ptr/const_ptr.rs b/library/core/src/ptr/const_ptr.rs
index 7b1cb5488..57e2ffe5d 100644
--- a/library/core/src/ptr/const_ptr.rs
+++ b/library/core/src/ptr/const_ptr.rs
@@ -23,8 +23,6 @@ impl<T: ?Sized> *const T {
///
/// # Examples
///
- /// Basic usage:
- ///
/// ```
/// let s: &str = "Follow the rabbit";
/// let ptr: *const u8 = s.as_ptr();
@@ -323,8 +321,6 @@ impl<T: ?Sized> *const T {
///
/// # Examples
///
- /// Basic usage:
- ///
/// ```
/// let ptr: *const u8 = &10u8 as *const u8;
///
@@ -384,8 +380,6 @@ impl<T: ?Sized> *const T {
///
/// # Examples
///
- /// Basic usage:
- ///
/// ```
/// #![feature(ptr_as_uninit)]
///
@@ -449,8 +443,6 @@ impl<T: ?Sized> *const T {
///
/// # Examples
///
- /// Basic usage:
- ///
/// ```
/// let s: &str = "123";
/// let ptr: *const u8 = s.as_ptr();
@@ -526,8 +518,6 @@ impl<T: ?Sized> *const T {
///
/// # Examples
///
- /// Basic usage:
- ///
/// ```
/// // Iterate using a raw pointer in increments of two elements
/// let data = [1u8, 2, 3, 4, 5];
@@ -731,7 +721,7 @@ impl<T: ?Sized> *const T {
/// This computes the same value that [`offset_from`](#method.offset_from)
/// would compute, but with the added precondition that the offset is
/// guaranteed to be non-negative. This method is equivalent to
- /// `usize::from(self.offset_from(origin)).unwrap_unchecked()`,
+ /// `usize::try_from(self.offset_from(origin)).unwrap_unchecked()`,
/// but it provides slightly more information to the optimizer, which can
/// sometimes allow it to optimize slightly better with some backends.
///
@@ -908,8 +898,6 @@ impl<T: ?Sized> *const T {
///
/// # Examples
///
- /// Basic usage:
- ///
/// ```
/// let s: &str = "123";
/// let ptr: *const u8 = s.as_ptr();
@@ -993,8 +981,6 @@ impl<T: ?Sized> *const T {
///
/// # Examples
///
- /// Basic usage:
- ///
/// ```
/// let s: &str = "123";
///
@@ -1072,8 +1058,6 @@ impl<T: ?Sized> *const T {
///
/// # Examples
///
- /// Basic usage:
- ///
/// ```
/// // Iterate using a raw pointer in increments of two elements
/// let data = [1u8, 2, 3, 4, 5];
@@ -1152,8 +1136,6 @@ impl<T: ?Sized> *const T {
///
/// # Examples
///
- /// Basic usage:
- ///
/// ```
/// // Iterate using a raw pointer in increments of two elements (backwards)
/// let data = [1u8, 2, 3, 4, 5];
@@ -1359,7 +1341,6 @@ impl<T: ?Sized> *const T {
///
/// # Examples
///
- /// Basic usage:
/// ```
/// #![feature(pointer_is_aligned)]
/// #![feature(pointer_byte_offsets)]
@@ -1482,7 +1463,6 @@ impl<T: ?Sized> *const T {
///
/// # Examples
///
- /// Basic usage:
/// ```
/// #![feature(pointer_is_aligned)]
/// #![feature(pointer_byte_offsets)]
diff --git a/library/core/src/ptr/mut_ptr.rs b/library/core/src/ptr/mut_ptr.rs
index ed1e3bd48..422d0f2b8 100644
--- a/library/core/src/ptr/mut_ptr.rs
+++ b/library/core/src/ptr/mut_ptr.rs
@@ -22,8 +22,6 @@ impl<T: ?Sized> *mut T {
///
/// # Examples
///
- /// Basic usage:
- ///
/// ```
/// let mut s = [1, 2, 3];
/// let ptr: *mut u32 = s.as_mut_ptr();
@@ -332,8 +330,6 @@ impl<T: ?Sized> *mut T {
///
/// # Examples
///
- /// Basic usage:
- ///
/// ```
/// let ptr: *mut u8 = &mut 10u8 as *mut u8;
///
@@ -396,8 +392,6 @@ impl<T: ?Sized> *mut T {
///
/// # Examples
///
- /// Basic usage:
- ///
/// ```
/// #![feature(ptr_as_uninit)]
///
@@ -461,8 +455,6 @@ impl<T: ?Sized> *mut T {
///
/// # Examples
///
- /// Basic usage:
- ///
/// ```
/// let mut s = [1, 2, 3];
/// let ptr: *mut u32 = s.as_mut_ptr();
@@ -539,8 +531,6 @@ impl<T: ?Sized> *mut T {
///
/// # Examples
///
- /// Basic usage:
- ///
/// ```
/// // Iterate using a raw pointer in increments of two elements
/// let mut data = [1u8, 2, 3, 4, 5];
@@ -660,8 +650,6 @@ impl<T: ?Sized> *mut T {
///
/// # Examples
///
- /// Basic usage:
- ///
/// ```
/// let mut s = [1, 2, 3];
/// let ptr: *mut u32 = s.as_mut_ptr();
@@ -904,7 +892,7 @@ impl<T: ?Sized> *mut T {
/// This computes the same value that [`offset_from`](#method.offset_from)
/// would compute, but with the added precondition that the offset is
/// guaranteed to be non-negative. This method is equivalent to
- /// `usize::from(self.offset_from(origin)).unwrap_unchecked()`,
+ /// `usize::try_from(self.offset_from(origin)).unwrap_unchecked()`,
/// but it provides slightly more information to the optimizer, which can
/// sometimes allow it to optimize slightly better with some backends.
///
@@ -1010,8 +998,6 @@ impl<T: ?Sized> *mut T {
///
/// # Examples
///
- /// Basic usage:
- ///
/// ```
/// let s: &str = "123";
/// let ptr: *const u8 = s.as_ptr();
@@ -1095,8 +1081,6 @@ impl<T: ?Sized> *mut T {
///
/// # Examples
///
- /// Basic usage:
- ///
/// ```
/// let s: &str = "123";
///
@@ -1174,8 +1158,6 @@ impl<T: ?Sized> *mut T {
///
/// # Examples
///
- /// Basic usage:
- ///
/// ```
/// // Iterate using a raw pointer in increments of two elements
/// let data = [1u8, 2, 3, 4, 5];
@@ -1254,8 +1236,6 @@ impl<T: ?Sized> *mut T {
///
/// # Examples
///
- /// Basic usage:
- ///
/// ```
/// // Iterate using a raw pointer in increments of two elements (backwards)
/// let data = [1u8, 2, 3, 4, 5];
@@ -1627,7 +1607,6 @@ impl<T: ?Sized> *mut T {
///
/// # Examples
///
- /// Basic usage:
/// ```
/// #![feature(pointer_is_aligned)]
/// #![feature(pointer_byte_offsets)]
@@ -1752,7 +1731,6 @@ impl<T: ?Sized> *mut T {
///
/// # Examples
///
- /// Basic usage:
/// ```
/// #![feature(pointer_is_aligned)]
/// #![feature(pointer_byte_offsets)]
diff --git a/library/core/src/result.rs b/library/core/src/result.rs
index f00c40f35..208b220c2 100644
--- a/library/core/src/result.rs
+++ b/library/core/src/result.rs
@@ -458,7 +458,7 @@
//! [`Result`] of a collection of each contained value of the original
//! [`Result`] values, or [`Err`] if any of the elements was [`Err`].
//!
-//! [impl-FromIterator]: Result#impl-FromIterator%3CResult%3CA%2C%20E%3E%3E-for-Result%3CV%2C%20E%3E
+//! [impl-FromIterator]: Result#impl-FromIterator%3CResult%3CA,+E%3E%3E-for-Result%3CV,+E%3E
//!
//! ```
//! let v = [Ok(2), Ok(4), Err("err!"), Ok(8)];
@@ -474,8 +474,8 @@
//! to provide the [`product`][Iterator::product] and
//! [`sum`][Iterator::sum] methods.
//!
-//! [impl-Product]: Result#impl-Product%3CResult%3CU%2C%20E%3E%3E-for-Result%3CT%2C%20E%3E
-//! [impl-Sum]: Result#impl-Sum%3CResult%3CU%2C%20E%3E%3E-for-Result%3CT%2C%20E%3E
+//! [impl-Product]: Result#impl-Product%3CResult%3CU,+E%3E%3E-for-Result%3CT,+E%3E
+//! [impl-Sum]: Result#impl-Sum%3CResult%3CU,+E%3E%3E-for-Result%3CT,+E%3E
//!
//! ```
//! let v = [Err("error!"), Ok(1), Ok(2), Ok(3), Err("foo")];
@@ -525,8 +525,6 @@ impl<T, E> Result<T, E> {
///
/// # Examples
///
- /// Basic usage:
- ///
/// ```
/// let x: Result<i32, &str> = Ok(-3);
/// assert_eq!(x.is_ok(), true);
@@ -572,8 +570,6 @@ impl<T, E> Result<T, E> {
///
/// # Examples
///
- /// Basic usage:
- ///
/// ```
/// let x: Result<i32, &str> = Ok(-3);
/// assert_eq!(x.is_err(), false);
@@ -627,8 +623,6 @@ impl<T, E> Result<T, E> {
///
/// # Examples
///
- /// Basic usage:
- ///
/// ```
/// let x: Result<u32, &str> = Ok(2);
/// assert_eq!(x.ok(), Some(2));
@@ -658,8 +652,6 @@ impl<T, E> Result<T, E> {
///
/// # Examples
///
- /// Basic usage:
- ///
/// ```
/// let x: Result<u32, &str> = Ok(2);
/// assert_eq!(x.err(), None);
@@ -693,8 +685,6 @@ impl<T, E> Result<T, E> {
///
/// # Examples
///
- /// Basic usage:
- ///
/// ```
/// let x: Result<u32, &str> = Ok(2);
/// assert_eq!(x.as_ref(), Ok(&2));
@@ -716,8 +706,6 @@ impl<T, E> Result<T, E> {
///
/// # Examples
///
- /// Basic usage:
- ///
/// ```
/// fn mutate(r: &mut Result<i32, i32>) {
/// match r.as_mut() {
@@ -812,8 +800,6 @@ impl<T, E> Result<T, E> {
///
/// # Examples
///
- /// Basic usage:
- ///
/// ```
/// let k = 21;
///
@@ -841,8 +827,6 @@ impl<T, E> Result<T, E> {
///
/// # Examples
///
- /// Basic usage:
- ///
/// ```
/// fn stringify(x: u32) -> String { format!("error code: {x}") }
///
@@ -968,8 +952,6 @@ impl<T, E> Result<T, E> {
///
/// # Examples
///
- /// Basic usage:
- ///
/// ```
/// let x: Result<u32, &str> = Ok(7);
/// assert_eq!(x.iter().next(), Some(&7));
@@ -989,8 +971,6 @@ impl<T, E> Result<T, E> {
///
/// # Examples
///
- /// Basic usage:
- ///
/// ```
/// let mut x: Result<u32, &str> = Ok(7);
/// match x.iter_mut().next() {
@@ -1031,8 +1011,6 @@ impl<T, E> Result<T, E> {
///
/// # Examples
///
- /// Basic usage:
- ///
/// ```should_panic
/// let x: Result<u32, &str> = Err("emergency failure");
/// x.expect("Testing expect"); // panics with `Testing expect: emergency failure`
@@ -1160,8 +1138,6 @@ impl<T, E> Result<T, E> {
///
/// # Examples
///
- /// Basic usage:
- ///
/// ```should_panic
/// let x: Result<u32, &str> = Ok(10);
/// x.expect_err("Testing expect_err"); // panics with `Testing expect_err: 10`
@@ -1222,8 +1198,6 @@ impl<T, E> Result<T, E> {
///
/// # Examples
///
- /// Basic usage:
- ///
/// ```
/// # #![feature(never_type)]
/// # #![feature(unwrap_infallible)]
@@ -1259,8 +1233,6 @@ impl<T, E> Result<T, E> {
///
/// # Examples
///
- /// Basic usage:
- ///
/// ```
/// # #![feature(never_type)]
/// # #![feature(unwrap_infallible)]
@@ -1298,8 +1270,6 @@ impl<T, E> Result<T, E> {
///
/// # Examples
///
- /// Basic usage:
- ///
/// ```
/// let x: Result<u32, &str> = Ok(2);
/// let y: Result<&str, &str> = Err("late error");
@@ -1383,8 +1353,6 @@ impl<T, E> Result<T, E> {
///
/// # Examples
///
- /// Basic usage:
- ///
/// ```
/// let x: Result<u32, &str> = Ok(2);
/// let y: Result<u32, &str> = Err("late error");
@@ -1426,8 +1394,6 @@ impl<T, E> Result<T, E> {
///
/// # Examples
///
- /// Basic usage:
- ///
/// ```
/// fn sq(x: u32) -> Result<u32, u32> { Ok(x * x) }
/// fn err(x: u32) -> Result<u32, u32> { Err(x) }
@@ -1456,8 +1422,6 @@ impl<T, E> Result<T, E> {
///
/// # Examples
///
- /// Basic usage:
- ///
/// ```
/// let default = 2;
/// let x: Result<u32, &str> = Ok(9);
@@ -1487,8 +1451,6 @@ impl<T, E> Result<T, E> {
///
/// # Examples
///
- /// Basic usage:
- ///
/// ```
/// fn count(x: &str) -> usize { x.len() }
///
@@ -1752,8 +1714,6 @@ impl<T, E> Result<Result<T, E>, E> {
///
/// # Examples
///
- /// Basic usage:
- ///
/// ```
/// #![feature(result_flattening)]
/// let x: Result<Result<&'static str, u32>, u32> = Ok(Ok("hello"));
@@ -1842,8 +1802,6 @@ impl<T, E> IntoIterator for Result<T, E> {
///
/// # Examples
///
- /// Basic usage:
- ///
/// ```
/// let x: Result<u32, &str> = Ok(5);
/// let v: Vec<u32> = x.into_iter().collect();
diff --git a/library/core/src/slice/cmp.rs b/library/core/src/slice/cmp.rs
index 5e1b218e5..7601dd3c7 100644
--- a/library/core/src/slice/cmp.rs
+++ b/library/core/src/slice/cmp.rs
@@ -1,6 +1,6 @@
//! Comparison traits for `[T]`.
-use crate::cmp::{self, Ordering};
+use crate::cmp::{self, BytewiseEq, Ordering};
use crate::ffi;
use crate::mem;
@@ -77,7 +77,7 @@ where
// Use memcmp for bytewise equality when the types allow
impl<A, B> SlicePartialEq<B> for [A]
where
- A: BytewiseEquality<B>,
+ A: BytewiseEq<B>,
{
fn equal(&self, other: &[B]) -> bool {
if self.len() != other.len() {
@@ -203,29 +203,6 @@ impl SliceOrd for u8 {
}
}
-// Hack to allow specializing on `Eq` even though `Eq` has a method.
-#[rustc_unsafe_specialization_marker]
-trait MarkerEq<T>: PartialEq<T> {}
-
-impl<T: Eq> MarkerEq<T> for T {}
-
-#[doc(hidden)]
-/// Trait implemented for types that can be compared for equality using
-/// their bytewise representation
-#[rustc_specialization_trait]
-trait BytewiseEquality<T>: MarkerEq<T> + Copy {}
-
-macro_rules! impl_marker_for {
- ($traitname:ident, $($ty:ty)*) => {
- $(
- impl $traitname<$ty> for $ty { }
- )*
- }
-}
-
-impl_marker_for!(BytewiseEquality,
- u8 i8 u16 i16 u32 i32 u64 i64 u128 i128 usize isize char bool);
-
pub(super) trait SliceContains: Sized {
fn slice_contains(&self, x: &[Self]) -> bool;
}
diff --git a/library/core/src/slice/iter.rs b/library/core/src/slice/iter.rs
index 90ab43d12..c4317799b 100644
--- a/library/core/src/slice/iter.rs
+++ b/library/core/src/slice/iter.rs
@@ -7,7 +7,9 @@ use crate::cmp;
use crate::cmp::Ordering;
use crate::fmt;
use crate::intrinsics::assume;
-use crate::iter::{FusedIterator, TrustedLen, TrustedRandomAccess, TrustedRandomAccessNoCoerce};
+use crate::iter::{
+ FusedIterator, TrustedLen, TrustedRandomAccess, TrustedRandomAccessNoCoerce, UncheckedIterator,
+};
use crate::marker::{PhantomData, Send, Sized, Sync};
use crate::mem::{self, SizedTypeProperties};
use crate::num::NonZeroUsize;
diff --git a/library/core/src/slice/iter/macros.rs b/library/core/src/slice/iter/macros.rs
index 0fd57b197..89b92a7d5 100644
--- a/library/core/src/slice/iter/macros.rs
+++ b/library/core/src/slice/iter/macros.rs
@@ -384,6 +384,15 @@ macro_rules! iterator {
#[unstable(feature = "trusted_len", issue = "37572")]
unsafe impl<T> TrustedLen for $name<'_, T> {}
+
+ impl<'a, T> UncheckedIterator for $name<'a, T> {
+ unsafe fn next_unchecked(&mut self) -> $elem {
+ // SAFETY: The caller promised there's at least one more item.
+ unsafe {
+ next_unchecked!(self)
+ }
+ }
+ }
}
}
diff --git a/library/core/src/slice/memchr.rs b/library/core/src/slice/memchr.rs
index c848c2e18..98c8349eb 100644
--- a/library/core/src/slice/memchr.rs
+++ b/library/core/src/slice/memchr.rs
@@ -16,25 +16,29 @@ const USIZE_BYTES: usize = mem::size_of::<usize>();
/// bytes where the borrow propagated all the way to the most significant
/// bit."
#[inline]
+#[rustc_const_stable(feature = "const_memchr", since = "1.65.0")]
const fn contains_zero_byte(x: usize) -> bool {
x.wrapping_sub(LO_USIZE) & !x & HI_USIZE != 0
}
-#[cfg(target_pointer_width = "16")]
#[inline]
+#[cfg(target_pointer_width = "16")]
+#[rustc_const_stable(feature = "const_memchr", since = "1.65.0")]
const fn repeat_byte(b: u8) -> usize {
(b as usize) << 8 | b as usize
}
-#[cfg(not(target_pointer_width = "16"))]
#[inline]
+#[cfg(not(target_pointer_width = "16"))]
+#[rustc_const_stable(feature = "const_memchr", since = "1.65.0")]
const fn repeat_byte(b: u8) -> usize {
(b as usize) * (usize::MAX / 255)
}
/// Returns the first index matching the byte `x` in `text`.
-#[must_use]
#[inline]
+#[must_use]
+#[rustc_const_stable(feature = "const_memchr", since = "1.65.0")]
pub const fn memchr(x: u8, text: &[u8]) -> Option<usize> {
// Fast path for small slices.
if text.len() < 2 * USIZE_BYTES {
@@ -45,6 +49,7 @@ pub const fn memchr(x: u8, text: &[u8]) -> Option<usize> {
}
#[inline]
+#[rustc_const_stable(feature = "const_memchr", since = "1.65.0")]
const fn memchr_naive(x: u8, text: &[u8]) -> Option<usize> {
let mut i = 0;
@@ -60,6 +65,10 @@ const fn memchr_naive(x: u8, text: &[u8]) -> Option<usize> {
None
}
+#[rustc_allow_const_fn_unstable(const_cmp)]
+#[rustc_allow_const_fn_unstable(const_slice_index)]
+#[rustc_allow_const_fn_unstable(const_align_offset)]
+#[rustc_const_stable(feature = "const_memchr", since = "1.65.0")]
const fn memchr_aligned(x: u8, text: &[u8]) -> Option<usize> {
// Scan for a single byte value by reading two `usize` words at a time.
//
diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs
index d93a3a57e..1cd86b445 100644
--- a/library/core/src/slice/mod.rs
+++ b/library/core/src/slice/mod.rs
@@ -805,8 +805,9 @@ impl<T> [T] {
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
+ #[track_caller]
pub fn windows(&self, size: usize) -> Windows<'_, T> {
- let size = NonZeroUsize::new(size).expect("size is zero");
+ let size = NonZeroUsize::new(size).expect("window size must be non-zero");
Windows::new(self, size)
}
@@ -839,8 +840,9 @@ impl<T> [T] {
/// [`rchunks`]: slice::rchunks
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
+ #[track_caller]
pub fn chunks(&self, chunk_size: usize) -> Chunks<'_, T> {
- assert_ne!(chunk_size, 0, "chunks cannot have a size of zero");
+ assert!(chunk_size != 0, "chunk size must be non-zero");
Chunks::new(self, chunk_size)
}
@@ -877,8 +879,9 @@ impl<T> [T] {
/// [`rchunks_mut`]: slice::rchunks_mut
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
+ #[track_caller]
pub fn chunks_mut(&mut self, chunk_size: usize) -> ChunksMut<'_, T> {
- assert_ne!(chunk_size, 0, "chunks cannot have a size of zero");
+ assert!(chunk_size != 0, "chunk size must be non-zero");
ChunksMut::new(self, chunk_size)
}
@@ -914,8 +917,9 @@ impl<T> [T] {
/// [`rchunks_exact`]: slice::rchunks_exact
#[stable(feature = "chunks_exact", since = "1.31.0")]
#[inline]
+ #[track_caller]
pub fn chunks_exact(&self, chunk_size: usize) -> ChunksExact<'_, T> {
- assert_ne!(chunk_size, 0, "chunks cannot have a size of zero");
+ assert!(chunk_size != 0, "chunk size must be non-zero");
ChunksExact::new(self, chunk_size)
}
@@ -956,8 +960,9 @@ impl<T> [T] {
/// [`rchunks_exact_mut`]: slice::rchunks_exact_mut
#[stable(feature = "chunks_exact", since = "1.31.0")]
#[inline]
+ #[track_caller]
pub fn chunks_exact_mut(&mut self, chunk_size: usize) -> ChunksExactMut<'_, T> {
- assert_ne!(chunk_size, 0, "chunks cannot have a size of zero");
+ assert!(chunk_size != 0, "chunk size must be non-zero");
ChunksExactMut::new(self, chunk_size)
}
@@ -1037,9 +1042,10 @@ impl<T> [T] {
/// ```
#[unstable(feature = "slice_as_chunks", issue = "74985")]
#[inline]
+ #[track_caller]
#[must_use]
pub fn as_chunks<const N: usize>(&self) -> (&[[T; N]], &[T]) {
- assert_ne!(N, 0, "chunks cannot have a size of zero");
+ assert!(N != 0, "chunk size must be non-zero");
let len = self.len() / N;
let (multiple_of_n, remainder) = self.split_at(len * N);
// SAFETY: We already panicked for zero, and ensured by construction
@@ -1068,9 +1074,10 @@ impl<T> [T] {
/// ```
#[unstable(feature = "slice_as_chunks", issue = "74985")]
#[inline]
+ #[track_caller]
#[must_use]
pub fn as_rchunks<const N: usize>(&self) -> (&[T], &[[T; N]]) {
- assert_ne!(N, 0, "chunks cannot have a size of zero");
+ assert!(N != 0, "chunk size must be non-zero");
let len = self.len() / N;
let (remainder, multiple_of_n) = self.split_at(self.len() - len * N);
// SAFETY: We already panicked for zero, and ensured by construction
@@ -1108,8 +1115,9 @@ impl<T> [T] {
/// [`chunks_exact`]: slice::chunks_exact
#[unstable(feature = "array_chunks", issue = "74985")]
#[inline]
+ #[track_caller]
pub fn array_chunks<const N: usize>(&self) -> ArrayChunks<'_, T, N> {
- assert_ne!(N, 0, "chunks cannot have a size of zero");
+ assert!(N != 0, "chunk size must be non-zero");
ArrayChunks::new(self)
}
@@ -1186,9 +1194,10 @@ impl<T> [T] {
/// ```
#[unstable(feature = "slice_as_chunks", issue = "74985")]
#[inline]
+ #[track_caller]
#[must_use]
pub fn as_chunks_mut<const N: usize>(&mut self) -> (&mut [[T; N]], &mut [T]) {
- assert_ne!(N, 0, "chunks cannot have a size of zero");
+ assert!(N != 0, "chunk size must be non-zero");
let len = self.len() / N;
let (multiple_of_n, remainder) = self.split_at_mut(len * N);
// SAFETY: We already panicked for zero, and ensured by construction
@@ -1223,9 +1232,10 @@ impl<T> [T] {
/// ```
#[unstable(feature = "slice_as_chunks", issue = "74985")]
#[inline]
+ #[track_caller]
#[must_use]
pub fn as_rchunks_mut<const N: usize>(&mut self) -> (&mut [T], &mut [[T; N]]) {
- assert_ne!(N, 0, "chunks cannot have a size of zero");
+ assert!(N != 0, "chunk size must be non-zero");
let len = self.len() / N;
let (remainder, multiple_of_n) = self.split_at_mut(self.len() - len * N);
// SAFETY: We already panicked for zero, and ensured by construction
@@ -1265,8 +1275,9 @@ impl<T> [T] {
/// [`chunks_exact_mut`]: slice::chunks_exact_mut
#[unstable(feature = "array_chunks", issue = "74985")]
#[inline]
+ #[track_caller]
pub fn array_chunks_mut<const N: usize>(&mut self) -> ArrayChunksMut<'_, T, N> {
- assert_ne!(N, 0, "chunks cannot have a size of zero");
+ assert!(N != 0, "chunk size must be non-zero");
ArrayChunksMut::new(self)
}
@@ -1297,8 +1308,9 @@ impl<T> [T] {
/// [`windows`]: slice::windows
#[unstable(feature = "array_windows", issue = "75027")]
#[inline]
+ #[track_caller]
pub fn array_windows<const N: usize>(&self) -> ArrayWindows<'_, T, N> {
- assert_ne!(N, 0, "windows cannot have a size of zero");
+ assert!(N != 0, "window size must be non-zero");
ArrayWindows::new(self)
}
@@ -1331,8 +1343,9 @@ impl<T> [T] {
/// [`chunks`]: slice::chunks
#[stable(feature = "rchunks", since = "1.31.0")]
#[inline]
+ #[track_caller]
pub fn rchunks(&self, chunk_size: usize) -> RChunks<'_, T> {
- assert!(chunk_size != 0);
+ assert!(chunk_size != 0, "chunk size must be non-zero");
RChunks::new(self, chunk_size)
}
@@ -1369,8 +1382,9 @@ impl<T> [T] {
/// [`chunks_mut`]: slice::chunks_mut
#[stable(feature = "rchunks", since = "1.31.0")]
#[inline]
+ #[track_caller]
pub fn rchunks_mut(&mut self, chunk_size: usize) -> RChunksMut<'_, T> {
- assert!(chunk_size != 0);
+ assert!(chunk_size != 0, "chunk size must be non-zero");
RChunksMut::new(self, chunk_size)
}
@@ -1408,8 +1422,9 @@ impl<T> [T] {
/// [`chunks_exact`]: slice::chunks_exact
#[stable(feature = "rchunks", since = "1.31.0")]
#[inline]
+ #[track_caller]
pub fn rchunks_exact(&self, chunk_size: usize) -> RChunksExact<'_, T> {
- assert!(chunk_size != 0);
+ assert!(chunk_size != 0, "chunk size must be non-zero");
RChunksExact::new(self, chunk_size)
}
@@ -1451,8 +1466,9 @@ impl<T> [T] {
/// [`chunks_exact_mut`]: slice::chunks_exact_mut
#[stable(feature = "rchunks", since = "1.31.0")]
#[inline]
+ #[track_caller]
pub fn rchunks_exact_mut(&mut self, chunk_size: usize) -> RChunksExactMut<'_, T> {
- assert!(chunk_size != 0);
+ assert!(chunk_size != 0, "chunk size must be non-zero");
RChunksExactMut::new(self, chunk_size)
}
@@ -2714,8 +2730,10 @@ impl<T> [T] {
/// This reordering has the additional property that any value at position `i < index` will be
/// less than or equal to any value at a position `j > index`. Additionally, this reordering is
/// unstable (i.e. any number of equal elements may end up at position `index`), in-place
- /// (i.e. does not allocate), and *O*(*n*) worst-case. This function is also/ known as "kth
- /// element" in other libraries. It returns a triplet of the following from the reordered slice:
+ /// (i.e. does not allocate), and *O*(*n*) on average. The worst-case performance is *O*(*n* log *n*).
+ /// This function is also known as "kth element" in other libraries.
+ ///
+ /// It returns a triplet of the following from the reordered slice:
/// the subslice prior to `index`, the element at `index`, and the subslice after `index`;
/// accordingly, the values in those two subslices will respectively all be less-than-or-equal-to
/// and greater-than-or-equal-to the value of the element at `index`.
@@ -2761,8 +2779,11 @@ impl<T> [T] {
/// This reordering has the additional property that any value at position `i < index` will be
/// less than or equal to any value at a position `j > index` using the comparator function.
/// Additionally, this reordering is unstable (i.e. any number of equal elements may end up at
- /// position `index`), in-place (i.e. does not allocate), and *O*(*n*) worst-case. This function
- /// is also known as "kth element" in other libraries. It returns a triplet of the following from
+ /// position `index`), in-place (i.e. does not allocate), and *O*(*n*) on average.
+ /// The worst-case performance is *O*(*n* log *n*). This function is also known as
+ /// "kth element" in other libraries.
+ ///
+ /// It returns a triplet of the following from
/// the slice reordered according to the provided comparator function: the subslice prior to
/// `index`, the element at `index`, and the subslice after `index`; accordingly, the values in
/// those two subslices will respectively all be less-than-or-equal-to and greater-than-or-equal-to
@@ -2813,8 +2834,11 @@ impl<T> [T] {
/// This reordering has the additional property that any value at position `i < index` will be
/// less than or equal to any value at a position `j > index` using the key extraction function.
/// Additionally, this reordering is unstable (i.e. any number of equal elements may end up at
- /// position `index`), in-place (i.e. does not allocate), and *O*(*n*) worst-case. This function
- /// is also known as "kth element" in other libraries. It returns a triplet of the following from
+ /// position `index`), in-place (i.e. does not allocate), and *O*(*n*) on average.
+ /// The worst-case performance is *O*(*n* log *n*).
+ /// This function is also known as "kth element" in other libraries.
+ ///
+ /// It returns a triplet of the following from
/// the slice reordered according to the provided key extraction function: the subslice prior to
/// `index`, the element at `index`, and the subslice after `index`; accordingly, the values in
/// those two subslices will respectively all be less-than-or-equal-to and greater-than-or-equal-to
@@ -2931,7 +2955,7 @@ impl<T> [T] {
// This operation is still `O(n)`.
//
// Example: We start in this state, where `r` represents "next
- // read" and `w` represents "next_write`.
+ // read" and `w` represents "next_write".
//
// r
// +---+---+---+---+---+---+
diff --git a/library/core/src/slice/sort.rs b/library/core/src/slice/sort.rs
index 2181f9a81..2333f60a8 100644
--- a/library/core/src/slice/sort.rs
+++ b/library/core/src/slice/sort.rs
@@ -13,115 +13,184 @@ use crate::cmp;
use crate::mem::{self, MaybeUninit, SizedTypeProperties};
use crate::ptr;
-/// When dropped, copies from `src` into `dest`.
-struct CopyOnDrop<T> {
+// When dropped, copies from `src` into `dest`.
+struct InsertionHole<T> {
src: *const T,
dest: *mut T,
}
-impl<T> Drop for CopyOnDrop<T> {
+impl<T> Drop for InsertionHole<T> {
fn drop(&mut self) {
- // SAFETY: This is a helper class.
- // Please refer to its usage for correctness.
- // Namely, one must be sure that `src` and `dst` does not overlap as required by `ptr::copy_nonoverlapping`.
+ // SAFETY: This is a helper class. Please refer to its usage for correctness. Namely, one
+ // must be sure that `src` and `dst` does not overlap as required by
+ // `ptr::copy_nonoverlapping` and are both valid for writes.
unsafe {
ptr::copy_nonoverlapping(self.src, self.dest, 1);
}
}
}
-/// Shifts the first element to the right until it encounters a greater or equal element.
-fn shift_head<T, F>(v: &mut [T], is_less: &mut F)
+/// Inserts `v[v.len() - 1]` into pre-sorted sequence `v[..v.len() - 1]` so that whole `v[..]`
+/// becomes sorted.
+unsafe fn insert_tail<T, F>(v: &mut [T], is_less: &mut F)
where
F: FnMut(&T, &T) -> bool,
{
- let len = v.len();
- // SAFETY: The unsafe operations below involves indexing without a bounds check (by offsetting a
- // pointer) and copying memory (`ptr::copy_nonoverlapping`).
- //
- // a. Indexing:
- // 1. We checked the size of the array to >=2.
- // 2. All the indexing that we will do is always between {0 <= index < len} at most.
- //
- // b. Memory copying
- // 1. We are obtaining pointers to references which are guaranteed to be valid.
- // 2. They cannot overlap because we obtain pointers to difference indices of the slice.
- // Namely, `i` and `i-1`.
- // 3. If the slice is properly aligned, the elements are properly aligned.
- // It is the caller's responsibility to make sure the slice is properly aligned.
- //
- // See comments below for further detail.
+ debug_assert!(v.len() >= 2);
+
+ let arr_ptr = v.as_mut_ptr();
+ let i = v.len() - 1;
+
+ // SAFETY: caller must ensure v is at least len 2.
unsafe {
- // If the first two elements are out-of-order...
- if len >= 2 && is_less(v.get_unchecked(1), v.get_unchecked(0)) {
- // Read the first element into a stack-allocated variable. If a following comparison
- // operation panics, `hole` will get dropped and automatically write the element back
- // into the slice.
- let tmp = mem::ManuallyDrop::new(ptr::read(v.get_unchecked(0)));
- let v = v.as_mut_ptr();
- let mut hole = CopyOnDrop { src: &*tmp, dest: v.add(1) };
- ptr::copy_nonoverlapping(v.add(1), v.add(0), 1);
-
- for i in 2..len {
- if !is_less(&*v.add(i), &*tmp) {
+ // See insert_head which talks about why this approach is beneficial.
+ let i_ptr = arr_ptr.add(i);
+
+ // It's important that we use i_ptr here. If this check is positive and we continue,
+ // We want to make sure that no other copy of the value was seen by is_less.
+ // Otherwise we would have to copy it back.
+ if is_less(&*i_ptr, &*i_ptr.sub(1)) {
+ // It's important, that we use tmp for comparison from now on. As it is the value that
+ // will be copied back. And notionally we could have created a divergence if we copy
+ // back the wrong value.
+ let tmp = mem::ManuallyDrop::new(ptr::read(i_ptr));
+ // Intermediate state of the insertion process is always tracked by `hole`, which
+ // serves two purposes:
+ // 1. Protects integrity of `v` from panics in `is_less`.
+ // 2. Fills the remaining hole in `v` in the end.
+ //
+ // Panic safety:
+ //
+ // If `is_less` panics at any point during the process, `hole` will get dropped and
+ // fill the hole in `v` with `tmp`, thus ensuring that `v` still holds every object it
+ // initially held exactly once.
+ let mut hole = InsertionHole { src: &*tmp, dest: i_ptr.sub(1) };
+ ptr::copy_nonoverlapping(hole.dest, i_ptr, 1);
+
+ // SAFETY: We know i is at least 1.
+ for j in (0..(i - 1)).rev() {
+ let j_ptr = arr_ptr.add(j);
+ if !is_less(&*tmp, &*j_ptr) {
break;
}
- // Move `i`-th element one place to the left, thus shifting the hole to the right.
- ptr::copy_nonoverlapping(v.add(i), v.add(i - 1), 1);
- hole.dest = v.add(i);
+ ptr::copy_nonoverlapping(j_ptr, hole.dest, 1);
+ hole.dest = j_ptr;
}
// `hole` gets dropped and thus copies `tmp` into the remaining hole in `v`.
}
}
}
-/// Shifts the last element to the left until it encounters a smaller or equal element.
-fn shift_tail<T, F>(v: &mut [T], is_less: &mut F)
+/// Inserts `v[0]` into pre-sorted sequence `v[1..]` so that whole `v[..]` becomes sorted.
+///
+/// This is the integral subroutine of insertion sort.
+unsafe fn insert_head<T, F>(v: &mut [T], is_less: &mut F)
where
F: FnMut(&T, &T) -> bool,
{
- let len = v.len();
- // SAFETY: The unsafe operations below involves indexing without a bound check (by offsetting a
- // pointer) and copying memory (`ptr::copy_nonoverlapping`).
- //
- // a. Indexing:
- // 1. We checked the size of the array to >= 2.
- // 2. All the indexing that we will do is always between `0 <= index < len-1` at most.
- //
- // b. Memory copying
- // 1. We are obtaining pointers to references which are guaranteed to be valid.
- // 2. They cannot overlap because we obtain pointers to difference indices of the slice.
- // Namely, `i` and `i+1`.
- // 3. If the slice is properly aligned, the elements are properly aligned.
- // It is the caller's responsibility to make sure the slice is properly aligned.
- //
- // See comments below for further detail.
+ debug_assert!(v.len() >= 2);
+
+ // SAFETY: caller must ensure v is at least len 2.
unsafe {
- // If the last two elements are out-of-order...
- if len >= 2 && is_less(v.get_unchecked(len - 1), v.get_unchecked(len - 2)) {
- // Read the last element into a stack-allocated variable. If a following comparison
- // operation panics, `hole` will get dropped and automatically write the element back
- // into the slice.
- let tmp = mem::ManuallyDrop::new(ptr::read(v.get_unchecked(len - 1)));
- let v = v.as_mut_ptr();
- let mut hole = CopyOnDrop { src: &*tmp, dest: v.add(len - 2) };
- ptr::copy_nonoverlapping(v.add(len - 2), v.add(len - 1), 1);
-
- for i in (0..len - 2).rev() {
- if !is_less(&*tmp, &*v.add(i)) {
+ if is_less(v.get_unchecked(1), v.get_unchecked(0)) {
+ let arr_ptr = v.as_mut_ptr();
+
+ // There are three ways to implement insertion here:
+ //
+ // 1. Swap adjacent elements until the first one gets to its final destination.
+ // However, this way we copy data around more than is necessary. If elements are big
+ // structures (costly to copy), this method will be slow.
+ //
+ // 2. Iterate until the right place for the first element is found. Then shift the
+ // elements succeeding it to make room for it and finally place it into the
+ // remaining hole. This is a good method.
+ //
+ // 3. Copy the first element into a temporary variable. Iterate until the right place
+ // for it is found. As we go along, copy every traversed element into the slot
+ // preceding it. Finally, copy data from the temporary variable into the remaining
+ // hole. This method is very good. Benchmarks demonstrated slightly better
+ // performance than with the 2nd method.
+ //
+ // All methods were benchmarked, and the 3rd showed best results. So we chose that one.
+ let tmp = mem::ManuallyDrop::new(ptr::read(arr_ptr));
+
+ // Intermediate state of the insertion process is always tracked by `hole`, which
+ // serves two purposes:
+ // 1. Protects integrity of `v` from panics in `is_less`.
+ // 2. Fills the remaining hole in `v` in the end.
+ //
+ // Panic safety:
+ //
+ // If `is_less` panics at any point during the process, `hole` will get dropped and
+ // fill the hole in `v` with `tmp`, thus ensuring that `v` still holds every object it
+ // initially held exactly once.
+ let mut hole = InsertionHole { src: &*tmp, dest: arr_ptr.add(1) };
+ ptr::copy_nonoverlapping(arr_ptr.add(1), arr_ptr.add(0), 1);
+
+ for i in 2..v.len() {
+ if !is_less(&v.get_unchecked(i), &*tmp) {
break;
}
-
- // Move `i`-th element one place to the right, thus shifting the hole to the left.
- ptr::copy_nonoverlapping(v.add(i), v.add(i + 1), 1);
- hole.dest = v.add(i);
+ ptr::copy_nonoverlapping(arr_ptr.add(i), arr_ptr.add(i - 1), 1);
+ hole.dest = arr_ptr.add(i);
}
// `hole` gets dropped and thus copies `tmp` into the remaining hole in `v`.
}
}
}
+/// Sort `v` assuming `v[..offset]` is already sorted.
+///
+/// Never inline this function to avoid code bloat. It still optimizes nicely and has practically no
+/// performance impact. Even improving performance in some cases.
+#[inline(never)]
+fn insertion_sort_shift_left<T, F>(v: &mut [T], offset: usize, is_less: &mut F)
+where
+ F: FnMut(&T, &T) -> bool,
+{
+ let len = v.len();
+
+ // Using assert here improves performance.
+ assert!(offset != 0 && offset <= len);
+
+ // Shift each element of the unsorted region v[i..] as far left as is needed to make v sorted.
+ for i in offset..len {
+ // SAFETY: we tested that `offset` must be at least 1, so this loop is only entered if len
+ // >= 2. The range is exclusive and we know `i` must be at least 1 so this slice has at
+ // >least len 2.
+ unsafe {
+ insert_tail(&mut v[..=i], is_less);
+ }
+ }
+}
+
+/// Sort `v` assuming `v[offset..]` is already sorted.
+///
+/// Never inline this function to avoid code bloat. It still optimizes nicely and has practically no
+/// performance impact. Even improving performance in some cases.
+#[inline(never)]
+fn insertion_sort_shift_right<T, F>(v: &mut [T], offset: usize, is_less: &mut F)
+where
+ F: FnMut(&T, &T) -> bool,
+{
+ let len = v.len();
+
+ // Using assert here improves performance.
+ assert!(offset != 0 && offset <= len && len >= 2);
+
+ // Shift each element of the unsorted region v[..i] as far left as is needed to make v sorted.
+ for i in (0..offset).rev() {
+ // SAFETY: we tested that `offset` must be at least 1, so this loop is only entered if len
+ // >= 2.We ensured that the slice length is always at least 2 long. We know that start_found
+ // will be at least one less than end, and the range is exclusive. Which gives us i always
+ // <= (end - 2).
+ unsafe {
+ insert_head(&mut v[i..len], is_less);
+ }
+ }
+}
+
/// Partially sorts a slice by shifting several out-of-order elements around.
///
/// Returns `true` if the slice is sorted at the end. This function is *O*(*n*) worst-case.
@@ -161,26 +230,19 @@ where
// Swap the found pair of elements. This puts them in correct order.
v.swap(i - 1, i);
- // Shift the smaller element to the left.
- shift_tail(&mut v[..i], is_less);
- // Shift the greater element to the right.
- shift_head(&mut v[i..], is_less);
+ if i >= 2 {
+ // Shift the smaller element to the left.
+ insertion_sort_shift_left(&mut v[..i], i - 1, is_less);
+
+ // Shift the greater element to the right.
+ insertion_sort_shift_right(&mut v[..i], 1, is_less);
+ }
}
// Didn't manage to sort the slice in the limited number of steps.
false
}
-/// Sorts a slice using insertion sort, which is *O*(*n*^2) worst-case.
-fn insertion_sort<T, F>(v: &mut [T], is_less: &mut F)
-where
- F: FnMut(&T, &T) -> bool,
-{
- for i in 1..v.len() {
- shift_tail(&mut v[..i + 1], is_less);
- }
-}
-
/// Sorts `v` using heapsort, which guarantees *O*(*n* \* log(*n*)) worst-case.
#[cold]
#[unstable(feature = "sort_internals", reason = "internal to sort module", issue = "none")]
@@ -198,8 +260,11 @@ where
}
// Choose the greater child.
- if child + 1 < v.len() && is_less(&v[child], &v[child + 1]) {
- child += 1;
+ if child + 1 < v.len() {
+ // We need a branch to be sure not to out-of-bounds index,
+ // but it's highly predictable. The comparison, however,
+ // is better done branchless, especially for primitives.
+ child += is_less(&v[child], &v[child + 1]) as usize;
}
// Stop if the invariant holds at `node`.
@@ -252,7 +317,7 @@ where
// 1. `block` - Number of elements in the block.
// 2. `start` - Start pointer into the `offsets` array.
// 3. `end` - End pointer into the `offsets` array.
- // 4. `offsets - Indices of out-of-order elements within the block.
+ // 4. `offsets` - Indices of out-of-order elements within the block.
// The current block on the left side (from `l` to `l.add(block_l)`).
let mut l = v.as_mut_ptr();
@@ -262,7 +327,7 @@ where
let mut offsets_l = [MaybeUninit::<u8>::uninit(); BLOCK];
// The current block on the right side (from `r.sub(block_r)` to `r`).
- // SAFETY: The documentation for .add() specifically mention that `vec.as_ptr().add(vec.len())` is always safe`
+ // SAFETY: The documentation for .add() specifically mention that `vec.as_ptr().add(vec.len())` is always safe
let mut r = unsafe { l.add(v.len()) };
let mut block_r = BLOCK;
let mut start_r = ptr::null_mut();
@@ -507,7 +572,7 @@ where
// SAFETY: `pivot` is a reference to the first element of `v`, so `ptr::read` is safe.
let tmp = mem::ManuallyDrop::new(unsafe { ptr::read(pivot) });
- let _pivot_guard = CopyOnDrop { src: &*tmp, dest: pivot };
+ let _pivot_guard = InsertionHole { src: &*tmp, dest: pivot };
let pivot = &*tmp;
// Find the first pair of out-of-order elements.
@@ -560,7 +625,7 @@ where
// operation panics, the pivot will be automatically written back into the slice.
// SAFETY: The pointer here is valid because it is obtained from a reference to a slice.
let tmp = mem::ManuallyDrop::new(unsafe { ptr::read(pivot) });
- let _pivot_guard = CopyOnDrop { src: &*tmp, dest: pivot };
+ let _pivot_guard = InsertionHole { src: &*tmp, dest: pivot };
let pivot = &*tmp;
// Now partition the slice.
@@ -608,19 +673,23 @@ where
fn break_patterns<T>(v: &mut [T]) {
let len = v.len();
if len >= 8 {
- // Pseudorandom number generator from the "Xorshift RNGs" paper by George Marsaglia.
- let mut random = len as u32;
- let mut gen_u32 = || {
- random ^= random << 13;
- random ^= random >> 17;
- random ^= random << 5;
- random
- };
+ let mut seed = len;
let mut gen_usize = || {
+ // Pseudorandom number generator from the "Xorshift RNGs" paper by George Marsaglia.
if usize::BITS <= 32 {
- gen_u32() as usize
+ let mut r = seed as u32;
+ r ^= r << 13;
+ r ^= r >> 17;
+ r ^= r << 5;
+ seed = r as usize;
+ seed
} else {
- (((gen_u32() as u64) << 32) | (gen_u32() as u64)) as usize
+ let mut r = seed as u64;
+ r ^= r << 13;
+ r ^= r >> 7;
+ r ^= r << 17;
+ seed = r as usize;
+ seed
}
};
@@ -742,7 +811,9 @@ where
// Very short slices get sorted using insertion sort.
if len <= MAX_INSERTION {
- insertion_sort(v, is_less);
+ if len >= 2 {
+ insertion_sort_shift_left(v, 1, is_less);
+ }
return;
}
@@ -844,10 +915,14 @@ fn partition_at_index_loop<'a, T, F>(
let mut was_balanced = true;
loop {
+ let len = v.len();
+
// For slices of up to this length it's probably faster to simply sort them.
const MAX_INSERTION: usize = 10;
- if v.len() <= MAX_INSERTION {
- insertion_sort(v, is_less);
+ if len <= MAX_INSERTION {
+ if len >= 2 {
+ insertion_sort_shift_left(v, 1, is_less);
+ }
return;
}
@@ -887,7 +962,7 @@ fn partition_at_index_loop<'a, T, F>(
}
let (mid, _) = partition(v, pivot, is_less);
- was_balanced = cmp::min(mid, v.len() - mid) >= v.len() / 8;
+ was_balanced = cmp::min(mid, len - mid) >= len / 8;
// Split the slice into `left`, `pivot`, and `right`.
let (left, right) = v.split_at_mut(mid);
@@ -954,75 +1029,6 @@ where
(left, pivot, right)
}
-/// Inserts `v[0]` into pre-sorted sequence `v[1..]` so that whole `v[..]` becomes sorted.
-///
-/// This is the integral subroutine of insertion sort.
-fn insert_head<T, F>(v: &mut [T], is_less: &mut F)
-where
- F: FnMut(&T, &T) -> bool,
-{
- if v.len() >= 2 && is_less(&v[1], &v[0]) {
- // SAFETY: Copy tmp back even if panic, and ensure unique observation.
- unsafe {
- // There are three ways to implement insertion here:
- //
- // 1. Swap adjacent elements until the first one gets to its final destination.
- // However, this way we copy data around more than is necessary. If elements are big
- // structures (costly to copy), this method will be slow.
- //
- // 2. Iterate until the right place for the first element is found. Then shift the
- // elements succeeding it to make room for it and finally place it into the
- // remaining hole. This is a good method.
- //
- // 3. Copy the first element into a temporary variable. Iterate until the right place
- // for it is found. As we go along, copy every traversed element into the slot
- // preceding it. Finally, copy data from the temporary variable into the remaining
- // hole. This method is very good. Benchmarks demonstrated slightly better
- // performance than with the 2nd method.
- //
- // All methods were benchmarked, and the 3rd showed best results. So we chose that one.
- let tmp = mem::ManuallyDrop::new(ptr::read(&v[0]));
-
- // Intermediate state of the insertion process is always tracked by `hole`, which
- // serves two purposes:
- // 1. Protects integrity of `v` from panics in `is_less`.
- // 2. Fills the remaining hole in `v` in the end.
- //
- // Panic safety:
- //
- // If `is_less` panics at any point during the process, `hole` will get dropped and
- // fill the hole in `v` with `tmp`, thus ensuring that `v` still holds every object it
- // initially held exactly once.
- let mut hole = InsertionHole { src: &*tmp, dest: &mut v[1] };
- ptr::copy_nonoverlapping(&v[1], &mut v[0], 1);
-
- for i in 2..v.len() {
- if !is_less(&v[i], &*tmp) {
- break;
- }
- ptr::copy_nonoverlapping(&v[i], &mut v[i - 1], 1);
- hole.dest = &mut v[i];
- }
- // `hole` gets dropped and thus copies `tmp` into the remaining hole in `v`.
- }
- }
-
- // When dropped, copies from `src` into `dest`.
- struct InsertionHole<T> {
- src: *const T,
- dest: *mut T,
- }
-
- impl<T> Drop for InsertionHole<T> {
- fn drop(&mut self) {
- // SAFETY: The caller must ensure that src and dest are correctly set.
- unsafe {
- ptr::copy_nonoverlapping(self.src, self.dest, 1);
- }
- }
- }
-}
-
/// Merges non-decreasing runs `v[..mid]` and `v[mid..]` using `buf` as temporary storage, and
/// stores the result into `v[..]`.
///
@@ -1180,8 +1186,6 @@ pub fn merge_sort<T, CmpF, ElemAllocF, ElemDeallocF, RunAllocF, RunDeallocF>(
{
// Slices of up to this length get sorted using insertion sort.
const MAX_INSERTION: usize = 20;
- // Very short runs are extended using insertion sort to span at least this many elements.
- const MIN_RUN: usize = 10;
// The caller should have already checked that.
debug_assert!(!T::IS_ZST);
@@ -1191,9 +1195,7 @@ pub fn merge_sort<T, CmpF, ElemAllocF, ElemDeallocF, RunAllocF, RunDeallocF>(
// Short arrays get sorted in-place via insertion sort to avoid allocations.
if len <= MAX_INSERTION {
if len >= 2 {
- for i in (0..len - 1).rev() {
- insert_head(&mut v[i..], is_less);
- }
+ insertion_sort_shift_left(v, 1, is_less);
}
return;
}
@@ -1203,59 +1205,43 @@ pub fn merge_sort<T, CmpF, ElemAllocF, ElemDeallocF, RunAllocF, RunDeallocF>(
// `is_less` panics. When merging two sorted runs, this buffer holds a copy of the shorter run,
// which will always have length at most `len / 2`.
let buf = BufGuard::new(len / 2, elem_alloc_fn, elem_dealloc_fn);
- let buf_ptr = buf.buf_ptr;
+ let buf_ptr = buf.buf_ptr.as_ptr();
let mut runs = RunVec::new(run_alloc_fn, run_dealloc_fn);
- // In order to identify natural runs in `v`, we traverse it backwards. That might seem like a
- // strange decision, but consider the fact that merges more often go in the opposite direction
- // (forwards). According to benchmarks, merging forwards is slightly faster than merging
- // backwards. To conclude, identifying runs by traversing backwards improves performance.
- let mut end = len;
- while end > 0 {
- // Find the next natural run, and reverse it if it's strictly descending.
- let mut start = end - 1;
- if start > 0 {
- start -= 1;
-
- // SAFETY: The v.get_unchecked must be fed with correct inbound indicies.
- unsafe {
- if is_less(v.get_unchecked(start + 1), v.get_unchecked(start)) {
- while start > 0 && is_less(v.get_unchecked(start), v.get_unchecked(start - 1)) {
- start -= 1;
- }
- v[start..end].reverse();
- } else {
- while start > 0 && !is_less(v.get_unchecked(start), v.get_unchecked(start - 1))
- {
- start -= 1;
- }
- }
- }
+ let mut end = 0;
+ let mut start = 0;
+
+ // Scan forward. Memory pre-fetching prefers forward scanning vs backwards scanning, and the
+ // code-gen is usually better. For the most sensitive types such as integers, these are merged
+ // bidirectionally at once. So there is no benefit in scanning backwards.
+ while end < len {
+ let (streak_end, was_reversed) = find_streak(&v[start..], is_less);
+ end += streak_end;
+ if was_reversed {
+ v[start..end].reverse();
}
// Insert some more elements into the run if it's too short. Insertion sort is faster than
// merge sort on short sequences, so this significantly improves performance.
- while start > 0 && end - start < MIN_RUN {
- start -= 1;
- insert_head(&mut v[start..end], is_less);
- }
+ end = provide_sorted_batch(v, start, end, is_less);
// Push this run onto the stack.
runs.push(TimSortRun { start, len: end - start });
- end = start;
+ start = end;
// Merge some pairs of adjacent runs to satisfy the invariants.
- while let Some(r) = collapse(runs.as_slice()) {
- let left = runs[r + 1];
- let right = runs[r];
+ while let Some(r) = collapse(runs.as_slice(), len) {
+ let left = runs[r];
+ let right = runs[r + 1];
+ let merge_slice = &mut v[left.start..right.start + right.len];
// SAFETY: `buf_ptr` must hold enough capacity for the shorter of the two sides, and
// neither side may be on length 0.
unsafe {
- merge(&mut v[left.start..right.start + right.len], left.len, buf_ptr, is_less);
+ merge(merge_slice, left.len, buf_ptr, is_less);
}
- runs[r] = TimSortRun { start: left.start, len: left.len + right.len };
- runs.remove(r + 1);
+ runs[r + 1] = TimSortRun { start: left.start, len: left.len + right.len };
+ runs.remove(r);
}
}
@@ -1277,10 +1263,10 @@ pub fn merge_sort<T, CmpF, ElemAllocF, ElemDeallocF, RunAllocF, RunDeallocF>(
// run starts at index 0, it will always demand a merge operation until the stack is fully
// collapsed, in order to complete the sort.
#[inline]
- fn collapse(runs: &[TimSortRun]) -> Option<usize> {
+ fn collapse(runs: &[TimSortRun], stop: usize) -> Option<usize> {
let n = runs.len();
if n >= 2
- && (runs[n - 1].start == 0
+ && (runs[n - 1].start + runs[n - 1].len == stop
|| runs[n - 2].len <= runs[n - 1].len
|| (n >= 3 && runs[n - 3].len <= runs[n - 2].len + runs[n - 1].len)
|| (n >= 4 && runs[n - 4].len <= runs[n - 3].len + runs[n - 2].len))
@@ -1298,7 +1284,7 @@ pub fn merge_sort<T, CmpF, ElemAllocF, ElemDeallocF, RunAllocF, RunDeallocF>(
where
ElemDeallocF: Fn(*mut T, usize),
{
- buf_ptr: *mut T,
+ buf_ptr: ptr::NonNull<T>,
capacity: usize,
elem_dealloc_fn: ElemDeallocF,
}
@@ -1315,7 +1301,11 @@ pub fn merge_sort<T, CmpF, ElemAllocF, ElemDeallocF, RunAllocF, RunDeallocF>(
where
ElemAllocF: Fn(usize) -> *mut T,
{
- Self { buf_ptr: elem_alloc_fn(len), capacity: len, elem_dealloc_fn }
+ Self {
+ buf_ptr: ptr::NonNull::new(elem_alloc_fn(len)).unwrap(),
+ capacity: len,
+ elem_dealloc_fn,
+ }
}
}
@@ -1324,7 +1314,7 @@ pub fn merge_sort<T, CmpF, ElemAllocF, ElemDeallocF, RunAllocF, RunDeallocF>(
ElemDeallocF: Fn(*mut T, usize),
{
fn drop(&mut self) {
- (self.elem_dealloc_fn)(self.buf_ptr, self.capacity);
+ (self.elem_dealloc_fn)(self.buf_ptr.as_ptr(), self.capacity);
}
}
@@ -1333,7 +1323,7 @@ pub fn merge_sort<T, CmpF, ElemAllocF, ElemDeallocF, RunAllocF, RunDeallocF>(
RunAllocF: Fn(usize) -> *mut TimSortRun,
RunDeallocF: Fn(*mut TimSortRun, usize),
{
- buf_ptr: *mut TimSortRun,
+ buf_ptr: ptr::NonNull<TimSortRun>,
capacity: usize,
len: usize,
run_alloc_fn: RunAllocF,
@@ -1350,7 +1340,7 @@ pub fn merge_sort<T, CmpF, ElemAllocF, ElemDeallocF, RunAllocF, RunDeallocF>(
const START_RUN_CAPACITY: usize = 16;
Self {
- buf_ptr: run_alloc_fn(START_RUN_CAPACITY),
+ buf_ptr: ptr::NonNull::new(run_alloc_fn(START_RUN_CAPACITY)).unwrap(),
capacity: START_RUN_CAPACITY,
len: 0,
run_alloc_fn,
@@ -1361,15 +1351,15 @@ pub fn merge_sort<T, CmpF, ElemAllocF, ElemDeallocF, RunAllocF, RunDeallocF>(
fn push(&mut self, val: TimSortRun) {
if self.len == self.capacity {
let old_capacity = self.capacity;
- let old_buf_ptr = self.buf_ptr;
+ let old_buf_ptr = self.buf_ptr.as_ptr();
self.capacity = self.capacity * 2;
- self.buf_ptr = (self.run_alloc_fn)(self.capacity);
+ self.buf_ptr = ptr::NonNull::new((self.run_alloc_fn)(self.capacity)).unwrap();
// SAFETY: buf_ptr new and old were correctly allocated and old_buf_ptr has
// old_capacity valid elements.
unsafe {
- ptr::copy_nonoverlapping(old_buf_ptr, self.buf_ptr, old_capacity);
+ ptr::copy_nonoverlapping(old_buf_ptr, self.buf_ptr.as_ptr(), old_capacity);
}
(self.run_dealloc_fn)(old_buf_ptr, old_capacity);
@@ -1377,7 +1367,7 @@ pub fn merge_sort<T, CmpF, ElemAllocF, ElemDeallocF, RunAllocF, RunDeallocF>(
// SAFETY: The invariant was just checked.
unsafe {
- self.buf_ptr.add(self.len).write(val);
+ self.buf_ptr.as_ptr().add(self.len).write(val);
}
self.len += 1;
}
@@ -1390,7 +1380,7 @@ pub fn merge_sort<T, CmpF, ElemAllocF, ElemDeallocF, RunAllocF, RunDeallocF>(
// SAFETY: buf_ptr needs to be valid and len invariant upheld.
unsafe {
// the place we are taking from.
- let ptr = self.buf_ptr.add(index);
+ let ptr = self.buf_ptr.as_ptr().add(index);
// Shift everything down to fill in that spot.
ptr::copy(ptr.add(1), ptr, self.len - index - 1);
@@ -1400,7 +1390,7 @@ pub fn merge_sort<T, CmpF, ElemAllocF, ElemDeallocF, RunAllocF, RunDeallocF>(
fn as_slice(&self) -> &[TimSortRun] {
// SAFETY: Safe as long as buf_ptr is valid and len invariant was upheld.
- unsafe { &*ptr::slice_from_raw_parts(self.buf_ptr, self.len) }
+ unsafe { &*ptr::slice_from_raw_parts(self.buf_ptr.as_ptr(), self.len) }
}
fn len(&self) -> usize {
@@ -1419,7 +1409,7 @@ pub fn merge_sort<T, CmpF, ElemAllocF, ElemDeallocF, RunAllocF, RunDeallocF>(
if index < self.len {
// SAFETY: buf_ptr and len invariant must be upheld.
unsafe {
- return &*(self.buf_ptr.add(index));
+ return &*(self.buf_ptr.as_ptr().add(index));
}
}
@@ -1436,7 +1426,7 @@ pub fn merge_sort<T, CmpF, ElemAllocF, ElemDeallocF, RunAllocF, RunDeallocF>(
if index < self.len {
// SAFETY: buf_ptr and len invariant must be upheld.
unsafe {
- return &mut *(self.buf_ptr.add(index));
+ return &mut *(self.buf_ptr.as_ptr().add(index));
}
}
@@ -1452,7 +1442,7 @@ pub fn merge_sort<T, CmpF, ElemAllocF, ElemDeallocF, RunAllocF, RunDeallocF>(
fn drop(&mut self) {
// As long as TimSortRun is Copy we don't need to drop them individually but just the
// whole allocation.
- (self.run_dealloc_fn)(self.buf_ptr, self.capacity);
+ (self.run_dealloc_fn)(self.buf_ptr.as_ptr(), self.capacity);
}
}
}
@@ -1463,3 +1453,71 @@ pub struct TimSortRun {
len: usize,
start: usize,
}
+
+/// Takes a range as denoted by start and end, that is already sorted and extends it to the right if
+/// necessary with sorts optimized for smaller ranges such as insertion sort.
+#[cfg(not(no_global_oom_handling))]
+fn provide_sorted_batch<T, F>(v: &mut [T], start: usize, mut end: usize, is_less: &mut F) -> usize
+where
+ F: FnMut(&T, &T) -> bool,
+{
+ let len = v.len();
+ assert!(end >= start && end <= len);
+
+ // This value is a balance between least comparisons and best performance, as
+ // influenced by for example cache locality.
+ const MIN_INSERTION_RUN: usize = 10;
+
+ // Insert some more elements into the run if it's too short. Insertion sort is faster than
+ // merge sort on short sequences, so this significantly improves performance.
+ let start_end_diff = end - start;
+
+ if start_end_diff < MIN_INSERTION_RUN && end < len {
+ // v[start_found..end] are elements that are already sorted in the input. We want to extend
+ // the sorted region to the left, so we push up MIN_INSERTION_RUN - 1 to the right. Which is
+ // more efficient that trying to push those already sorted elements to the left.
+ end = cmp::min(start + MIN_INSERTION_RUN, len);
+ let presorted_start = cmp::max(start_end_diff, 1);
+
+ insertion_sort_shift_left(&mut v[start..end], presorted_start, is_less);
+ }
+
+ end
+}
+
+/// Finds a streak of presorted elements starting at the beginning of the slice. Returns the first
+/// value that is not part of said streak, and a bool denoting wether the streak was reversed.
+/// Streaks can be increasing or decreasing.
+fn find_streak<T, F>(v: &[T], is_less: &mut F) -> (usize, bool)
+where
+ F: FnMut(&T, &T) -> bool,
+{
+ let len = v.len();
+
+ if len < 2 {
+ return (len, false);
+ }
+
+ let mut end = 2;
+
+ // SAFETY: See below specific.
+ unsafe {
+ // SAFETY: We checked that len >= 2, so 0 and 1 are valid indices.
+ let assume_reverse = is_less(v.get_unchecked(1), v.get_unchecked(0));
+
+ // SAFETY: We know end >= 2 and check end < len.
+ // From that follows that accessing v at end and end - 1 is safe.
+ if assume_reverse {
+ while end < len && is_less(v.get_unchecked(end), v.get_unchecked(end - 1)) {
+ end += 1;
+ }
+
+ (end, true)
+ } else {
+ while end < len && !is_less(v.get_unchecked(end), v.get_unchecked(end - 1)) {
+ end += 1;
+ }
+ (end, false)
+ }
+ }
+}
diff --git a/library/core/src/str/iter.rs b/library/core/src/str/iter.rs
index d969475aa..95c682f42 100644
--- a/library/core/src/str/iter.rs
+++ b/library/core/src/str/iter.rs
@@ -1,6 +1,6 @@
//! Iterators for `str` methods.
-use crate::char;
+use crate::char as char_mod;
use crate::fmt::{self, Write};
use crate::iter::{Chain, FlatMap, Flatten};
use crate::iter::{Copied, Filter, FusedIterator, Map, TrustedLen};
@@ -1455,8 +1455,8 @@ impl FusedIterator for EncodeUtf16<'_> {}
#[derive(Clone, Debug)]
pub struct EscapeDebug<'a> {
pub(super) inner: Chain<
- Flatten<option::IntoIter<char::EscapeDebug>>,
- FlatMap<Chars<'a>, char::EscapeDebug, CharEscapeDebugContinue>,
+ Flatten<option::IntoIter<char_mod::EscapeDebug>>,
+ FlatMap<Chars<'a>, char_mod::EscapeDebug, CharEscapeDebugContinue>,
>,
}
@@ -1464,14 +1464,14 @@ pub struct EscapeDebug<'a> {
#[stable(feature = "str_escape", since = "1.34.0")]
#[derive(Clone, Debug)]
pub struct EscapeDefault<'a> {
- pub(super) inner: FlatMap<Chars<'a>, char::EscapeDefault, CharEscapeDefault>,
+ pub(super) inner: FlatMap<Chars<'a>, char_mod::EscapeDefault, CharEscapeDefault>,
}
/// The return type of [`str::escape_unicode`].
#[stable(feature = "str_escape", since = "1.34.0")]
#[derive(Clone, Debug)]
pub struct EscapeUnicode<'a> {
- pub(super) inner: FlatMap<Chars<'a>, char::EscapeUnicode, CharEscapeUnicode>,
+ pub(super) inner: FlatMap<Chars<'a>, char_mod::EscapeUnicode, CharEscapeUnicode>,
}
macro_rules! escape_types_impls {
diff --git a/library/core/src/str/traits.rs b/library/core/src/str/traits.rs
index d3ed811b1..68f62ce8b 100644
--- a/library/core/src/str/traits.rs
+++ b/library/core/src/str/traits.rs
@@ -28,10 +28,6 @@ impl PartialEq for str {
fn eq(&self, other: &str) -> bool {
self.as_bytes() == other.as_bytes()
}
- #[inline]
- fn ne(&self, other: &str) -> bool {
- !(*self).eq(other)
- }
}
#[stable(feature = "rust1", since = "1.0.0")]
diff --git a/library/core/src/sync/atomic.rs b/library/core/src/sync/atomic.rs
index 14367eb09..040a59184 100644
--- a/library/core/src/sync/atomic.rs
+++ b/library/core/src/sync/atomic.rs
@@ -305,6 +305,50 @@ impl AtomicBool {
AtomicBool { v: UnsafeCell::new(v as u8) }
}
+ /// Creates a new `AtomicBool` from a pointer.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(atomic_from_ptr, pointer_is_aligned)]
+ /// use std::sync::atomic::{self, AtomicBool};
+ /// use std::mem::align_of;
+ ///
+ /// // Get a pointer to an allocated value
+ /// let ptr: *mut bool = Box::into_raw(Box::new(false));
+ ///
+ /// assert!(ptr.is_aligned_to(align_of::<AtomicBool>()));
+ ///
+ /// {
+ /// // Create an atomic view of the allocated value
+ /// let atomic = unsafe { AtomicBool::from_ptr(ptr) };
+ ///
+ /// // Use `atomic` for atomic operations, possibly share it with other threads
+ /// atomic.store(true, atomic::Ordering::Relaxed);
+ /// }
+ ///
+ /// // It's ok to non-atomically access the value behind `ptr`,
+ /// // since the reference to the atomic ended its lifetime in the block above
+ /// assert_eq!(unsafe { *ptr }, true);
+ ///
+ /// // Deallocate the value
+ /// unsafe { drop(Box::from_raw(ptr)) }
+ /// ```
+ ///
+ /// # Safety
+ ///
+ /// * `ptr` must be aligned to `align_of::<AtomicBool>()` (note that on some platforms this can be bigger than `align_of::<bool>()`).
+ /// * `ptr` must be [valid] for both reads and writes for the whole lifetime `'a`.
+ /// * The value behind `ptr` must not be accessed through non-atomic operations for the whole lifetime `'a`.
+ ///
+ /// [valid]: crate::ptr#safety
+ #[unstable(feature = "atomic_from_ptr", issue = "108652")]
+ #[rustc_const_unstable(feature = "atomic_from_ptr", issue = "108652")]
+ pub const unsafe fn from_ptr<'a>(ptr: *mut bool) -> &'a AtomicBool {
+ // SAFETY: guaranteed by the caller
+ unsafe { &*ptr.cast() }
+ }
+
/// Returns a mutable reference to the underlying [`bool`].
///
/// This is safe because the mutable reference guarantees that no other threads are
@@ -922,14 +966,14 @@ impl AtomicBool {
///
/// let mut atomic = AtomicBool::new(true);
/// unsafe {
- /// my_atomic_op(atomic.as_mut_ptr());
+ /// my_atomic_op(atomic.as_ptr());
/// }
/// # }
/// ```
#[inline]
#[unstable(feature = "atomic_mut_ptr", reason = "recently added", issue = "66893")]
- pub fn as_mut_ptr(&self) -> *mut bool {
- self.v.get() as *mut bool
+ pub const fn as_ptr(&self) -> *mut bool {
+ self.v.get().cast()
}
/// Fetches the value, and applies a function to it that returns an optional
@@ -1017,6 +1061,50 @@ impl<T> AtomicPtr<T> {
AtomicPtr { p: UnsafeCell::new(p) }
}
+ /// Creates a new `AtomicPtr` from a pointer.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(atomic_from_ptr, pointer_is_aligned)]
+ /// use std::sync::atomic::{self, AtomicPtr};
+ /// use std::mem::align_of;
+ ///
+ /// // Get a pointer to an allocated value
+ /// let ptr: *mut *mut u8 = Box::into_raw(Box::new(std::ptr::null_mut()));
+ ///
+ /// assert!(ptr.is_aligned_to(align_of::<AtomicPtr<u8>>()));
+ ///
+ /// {
+ /// // Create an atomic view of the allocated value
+ /// let atomic = unsafe { AtomicPtr::from_ptr(ptr) };
+ ///
+ /// // Use `atomic` for atomic operations, possibly share it with other threads
+ /// atomic.store(std::ptr::NonNull::dangling().as_ptr(), atomic::Ordering::Relaxed);
+ /// }
+ ///
+ /// // It's ok to non-atomically access the value behind `ptr`,
+ /// // since the reference to the atomic ended its lifetime in the block above
+ /// assert!(!unsafe { *ptr }.is_null());
+ ///
+ /// // Deallocate the value
+ /// unsafe { drop(Box::from_raw(ptr)) }
+ /// ```
+ ///
+ /// # Safety
+ ///
+ /// * `ptr` must be aligned to `align_of::<AtomicPtr<T>>()` (note that on some platforms this can be bigger than `align_of::<*mut T>()`).
+ /// * `ptr` must be [valid] for both reads and writes for the whole lifetime `'a`.
+ /// * The value behind `ptr` must not be accessed through non-atomic operations for the whole lifetime `'a`.
+ ///
+ /// [valid]: crate::ptr#safety
+ #[unstable(feature = "atomic_from_ptr", issue = "108652")]
+ #[rustc_const_unstable(feature = "atomic_from_ptr", issue = "108652")]
+ pub const unsafe fn from_ptr<'a>(ptr: *mut *mut T) -> &'a AtomicPtr<T> {
+ // SAFETY: guaranteed by the caller
+ unsafe { &*ptr.cast() }
+ }
+
/// Returns a mutable reference to the underlying pointer.
///
/// This is safe because the mutable reference guarantees that no other threads are
@@ -1803,7 +1891,7 @@ impl<T> AtomicPtr<T> {
///
/// ```ignore (extern-declaration)
/// #![feature(atomic_mut_ptr)]
- //// use std::sync::atomic::AtomicPtr;
+ /// use std::sync::atomic::AtomicPtr;
///
/// extern "C" {
/// fn my_atomic_op(arg: *mut *mut u32);
@@ -1814,12 +1902,12 @@ impl<T> AtomicPtr<T> {
///
/// // SAFETY: Safe as long as `my_atomic_op` is atomic.
/// unsafe {
- /// my_atomic_op(atomic.as_mut_ptr());
+ /// my_atomic_op(atomic.as_ptr());
/// }
/// ```
#[inline]
#[unstable(feature = "atomic_mut_ptr", reason = "recently added", issue = "66893")]
- pub fn as_mut_ptr(&self) -> *mut *mut T {
+ pub const fn as_ptr(&self) -> *mut *mut T {
self.p.get()
}
}
@@ -1861,7 +1949,8 @@ macro_rules! if_not_8_bit {
($_:ident, $($tt:tt)*) => { $($tt)* };
}
-#[cfg(target_has_atomic_load_store = "8")]
+#[cfg_attr(not(bootstrap), cfg(target_has_atomic_load_store))]
+#[cfg_attr(bootstrap, cfg(target_has_atomic_load_store = "8"))]
macro_rules! atomic_int {
($cfg_cas:meta,
$cfg_align:meta,
@@ -1957,6 +2046,53 @@ macro_rules! atomic_int {
Self {v: UnsafeCell::new(v)}
}
+ /// Creates a new reference to an atomic integer from a pointer.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(atomic_from_ptr, pointer_is_aligned)]
+ #[doc = concat!($extra_feature, "use std::sync::atomic::{self, ", stringify!($atomic_type), "};")]
+ /// use std::mem::align_of;
+ ///
+ /// // Get a pointer to an allocated value
+ #[doc = concat!("let ptr: *mut ", stringify!($int_type), " = Box::into_raw(Box::new(0));")]
+ ///
+ #[doc = concat!("assert!(ptr.is_aligned_to(align_of::<", stringify!($atomic_type), ">()));")]
+ ///
+ /// {
+ /// // Create an atomic view of the allocated value
+ // SAFETY: this is a doc comment, tidy, it can't hurt you (also guaranteed by the construction of `ptr` and the assert above)
+ #[doc = concat!(" let atomic = unsafe {", stringify!($atomic_type), "::from_ptr(ptr) };")]
+ ///
+ /// // Use `atomic` for atomic operations, possibly share it with other threads
+ /// atomic.store(1, atomic::Ordering::Relaxed);
+ /// }
+ ///
+ /// // It's ok to non-atomically access the value behind `ptr`,
+ /// // since the reference to the atomic ended its lifetime in the block above
+ /// assert_eq!(unsafe { *ptr }, 1);
+ ///
+ /// // Deallocate the value
+ /// unsafe { drop(Box::from_raw(ptr)) }
+ /// ```
+ ///
+ /// # Safety
+ ///
+ /// * `ptr` must be aligned to `align_of::<AtomicBool>()` (note that on some platforms this can be bigger than `align_of::<bool>()`).
+ #[doc = concat!(" * `ptr` must be aligned to `align_of::<", stringify!($atomic_type), ">()` (note that on some platforms this can be bigger than `align_of::<", stringify!($int_type), ">()`).")]
+ /// * `ptr` must be [valid] for both reads and writes for the whole lifetime `'a`.
+ /// * The value behind `ptr` must not be accessed through non-atomic operations for the whole lifetime `'a`.
+ ///
+ /// [valid]: crate::ptr#safety
+ #[unstable(feature = "atomic_from_ptr", issue = "108652")]
+ #[rustc_const_unstable(feature = "atomic_from_ptr", issue = "108652")]
+ pub const unsafe fn from_ptr<'a>(ptr: *mut $int_type) -> &'a $atomic_type {
+ // SAFETY: guaranteed by the caller
+ unsafe { &*ptr.cast() }
+ }
+
+
/// Returns a mutable reference to the underlying integer.
///
/// This is safe because the mutable reference guarantees that no other threads are
@@ -2718,7 +2854,7 @@ macro_rules! atomic_int {
///
/// // SAFETY: Safe as long as `my_atomic_op` is atomic.
/// unsafe {
- /// my_atomic_op(atomic.as_mut_ptr());
+ /// my_atomic_op(atomic.as_ptr());
/// }
/// # }
/// ```
@@ -2726,7 +2862,7 @@ macro_rules! atomic_int {
#[unstable(feature = "atomic_mut_ptr",
reason = "recently added",
issue = "66893")]
- pub fn as_mut_ptr(&self) -> *mut $int_type {
+ pub const fn as_ptr(&self) -> *mut $int_type {
self.v.get()
}
}
@@ -2988,7 +3124,8 @@ atomic_int_ptr_sized! {
}
#[inline]
-#[cfg(target_has_atomic = "8")]
+#[cfg_attr(not(bootstrap), cfg(target_has_atomic))]
+#[cfg_attr(bootstrap, cfg(target_has_atomic = "8"))]
fn strongest_failure_ordering(order: Ordering) -> Ordering {
match order {
Release => Relaxed,
@@ -3030,7 +3167,8 @@ unsafe fn atomic_load<T: Copy>(dst: *const T, order: Ordering) -> T {
}
#[inline]
-#[cfg(target_has_atomic = "8")]
+#[cfg_attr(not(bootstrap), cfg(target_has_atomic))]
+#[cfg_attr(bootstrap, cfg(target_has_atomic = "8"))]
#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
unsafe fn atomic_swap<T: Copy>(dst: *mut T, val: T, order: Ordering) -> T {
// SAFETY: the caller must uphold the safety contract for `atomic_swap`.
@@ -3047,7 +3185,8 @@ unsafe fn atomic_swap<T: Copy>(dst: *mut T, val: T, order: Ordering) -> T {
/// Returns the previous value (like __sync_fetch_and_add).
#[inline]
-#[cfg(target_has_atomic = "8")]
+#[cfg_attr(not(bootstrap), cfg(target_has_atomic))]
+#[cfg_attr(bootstrap, cfg(target_has_atomic = "8"))]
#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
unsafe fn atomic_add<T: Copy>(dst: *mut T, val: T, order: Ordering) -> T {
// SAFETY: the caller must uphold the safety contract for `atomic_add`.
@@ -3064,7 +3203,8 @@ unsafe fn atomic_add<T: Copy>(dst: *mut T, val: T, order: Ordering) -> T {
/// Returns the previous value (like __sync_fetch_and_sub).
#[inline]
-#[cfg(target_has_atomic = "8")]
+#[cfg_attr(not(bootstrap), cfg(target_has_atomic))]
+#[cfg_attr(bootstrap, cfg(target_has_atomic = "8"))]
#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
unsafe fn atomic_sub<T: Copy>(dst: *mut T, val: T, order: Ordering) -> T {
// SAFETY: the caller must uphold the safety contract for `atomic_sub`.
@@ -3080,7 +3220,8 @@ unsafe fn atomic_sub<T: Copy>(dst: *mut T, val: T, order: Ordering) -> T {
}
#[inline]
-#[cfg(target_has_atomic = "8")]
+#[cfg_attr(not(bootstrap), cfg(target_has_atomic))]
+#[cfg_attr(bootstrap, cfg(target_has_atomic = "8"))]
#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
unsafe fn atomic_compare_exchange<T: Copy>(
dst: *mut T,
@@ -3115,7 +3256,8 @@ unsafe fn atomic_compare_exchange<T: Copy>(
}
#[inline]
-#[cfg(target_has_atomic = "8")]
+#[cfg_attr(not(bootstrap), cfg(target_has_atomic))]
+#[cfg_attr(bootstrap, cfg(target_has_atomic = "8"))]
#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
unsafe fn atomic_compare_exchange_weak<T: Copy>(
dst: *mut T,
@@ -3150,7 +3292,8 @@ unsafe fn atomic_compare_exchange_weak<T: Copy>(
}
#[inline]
-#[cfg(target_has_atomic = "8")]
+#[cfg_attr(not(bootstrap), cfg(target_has_atomic))]
+#[cfg_attr(bootstrap, cfg(target_has_atomic = "8"))]
#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
unsafe fn atomic_and<T: Copy>(dst: *mut T, val: T, order: Ordering) -> T {
// SAFETY: the caller must uphold the safety contract for `atomic_and`
@@ -3166,7 +3309,8 @@ unsafe fn atomic_and<T: Copy>(dst: *mut T, val: T, order: Ordering) -> T {
}
#[inline]
-#[cfg(target_has_atomic = "8")]
+#[cfg_attr(not(bootstrap), cfg(target_has_atomic))]
+#[cfg_attr(bootstrap, cfg(target_has_atomic = "8"))]
#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
unsafe fn atomic_nand<T: Copy>(dst: *mut T, val: T, order: Ordering) -> T {
// SAFETY: the caller must uphold the safety contract for `atomic_nand`
@@ -3182,7 +3326,8 @@ unsafe fn atomic_nand<T: Copy>(dst: *mut T, val: T, order: Ordering) -> T {
}
#[inline]
-#[cfg(target_has_atomic = "8")]
+#[cfg_attr(not(bootstrap), cfg(target_has_atomic))]
+#[cfg_attr(bootstrap, cfg(target_has_atomic = "8"))]
#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
unsafe fn atomic_or<T: Copy>(dst: *mut T, val: T, order: Ordering) -> T {
// SAFETY: the caller must uphold the safety contract for `atomic_or`
@@ -3198,7 +3343,8 @@ unsafe fn atomic_or<T: Copy>(dst: *mut T, val: T, order: Ordering) -> T {
}
#[inline]
-#[cfg(target_has_atomic = "8")]
+#[cfg_attr(not(bootstrap), cfg(target_has_atomic))]
+#[cfg_attr(bootstrap, cfg(target_has_atomic = "8"))]
#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
unsafe fn atomic_xor<T: Copy>(dst: *mut T, val: T, order: Ordering) -> T {
// SAFETY: the caller must uphold the safety contract for `atomic_xor`
@@ -3215,7 +3361,8 @@ unsafe fn atomic_xor<T: Copy>(dst: *mut T, val: T, order: Ordering) -> T {
/// returns the max value (signed comparison)
#[inline]
-#[cfg(target_has_atomic = "8")]
+#[cfg_attr(not(bootstrap), cfg(target_has_atomic))]
+#[cfg_attr(bootstrap, cfg(target_has_atomic = "8"))]
#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
unsafe fn atomic_max<T: Copy>(dst: *mut T, val: T, order: Ordering) -> T {
// SAFETY: the caller must uphold the safety contract for `atomic_max`
@@ -3232,7 +3379,8 @@ unsafe fn atomic_max<T: Copy>(dst: *mut T, val: T, order: Ordering) -> T {
/// returns the min value (signed comparison)
#[inline]
-#[cfg(target_has_atomic = "8")]
+#[cfg_attr(not(bootstrap), cfg(target_has_atomic))]
+#[cfg_attr(bootstrap, cfg(target_has_atomic = "8"))]
#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
unsafe fn atomic_min<T: Copy>(dst: *mut T, val: T, order: Ordering) -> T {
// SAFETY: the caller must uphold the safety contract for `atomic_min`
@@ -3249,7 +3397,8 @@ unsafe fn atomic_min<T: Copy>(dst: *mut T, val: T, order: Ordering) -> T {
/// returns the max value (unsigned comparison)
#[inline]
-#[cfg(target_has_atomic = "8")]
+#[cfg_attr(not(bootstrap), cfg(target_has_atomic))]
+#[cfg_attr(bootstrap, cfg(target_has_atomic = "8"))]
#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
unsafe fn atomic_umax<T: Copy>(dst: *mut T, val: T, order: Ordering) -> T {
// SAFETY: the caller must uphold the safety contract for `atomic_umax`
@@ -3266,7 +3415,8 @@ unsafe fn atomic_umax<T: Copy>(dst: *mut T, val: T, order: Ordering) -> T {
/// returns the min value (unsigned comparison)
#[inline]
-#[cfg(target_has_atomic = "8")]
+#[cfg_attr(not(bootstrap), cfg(target_has_atomic))]
+#[cfg_attr(bootstrap, cfg(target_has_atomic = "8"))]
#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
unsafe fn atomic_umin<T: Copy>(dst: *mut T, val: T, order: Ordering) -> T {
// SAFETY: the caller must uphold the safety contract for `atomic_umin`
diff --git a/library/core/src/task/poll.rs b/library/core/src/task/poll.rs
index 25b61c0e6..af5bf441b 100644
--- a/library/core/src/task/poll.rs
+++ b/library/core/src/task/poll.rs
@@ -45,6 +45,7 @@ impl<T> Poll<T> {
/// assert_eq!(poll_some_len, Poll::Ready(13));
/// ```
#[stable(feature = "futures_api", since = "1.36.0")]
+ #[inline]
pub fn map<U, F>(self, f: F) -> Poll<U>
where
F: FnOnce(T) -> U,
@@ -144,6 +145,7 @@ impl<T, E> Poll<Result<T, E>> {
/// assert_eq!(squared, Poll::Ready(Ok(144)));
/// ```
#[stable(feature = "futures_api", since = "1.36.0")]
+ #[inline]
pub fn map_ok<U, F>(self, f: F) -> Poll<Result<U, E>>
where
F: FnOnce(T) -> U,
@@ -171,6 +173,7 @@ impl<T, E> Poll<Result<T, E>> {
/// assert_eq!(res, Poll::Ready(Err(0)));
/// ```
#[stable(feature = "futures_api", since = "1.36.0")]
+ #[inline]
pub fn map_err<U, F>(self, f: F) -> Poll<Result<T, U>>
where
F: FnOnce(E) -> U,
@@ -199,6 +202,7 @@ impl<T, E> Poll<Option<Result<T, E>>> {
/// assert_eq!(squared, Poll::Ready(Some(Ok(144))));
/// ```
#[stable(feature = "poll_map", since = "1.51.0")]
+ #[inline]
pub fn map_ok<U, F>(self, f: F) -> Poll<Option<Result<U, E>>>
where
F: FnOnce(T) -> U,
@@ -228,6 +232,7 @@ impl<T, E> Poll<Option<Result<T, E>>> {
/// assert_eq!(res, Poll::Ready(Some(Err(0))));
/// ```
#[stable(feature = "poll_map", since = "1.51.0")]
+ #[inline]
pub fn map_err<U, F>(self, f: F) -> Poll<Option<Result<T, U>>>
where
F: FnOnce(E) -> U,
diff --git a/library/core/src/task/wake.rs b/library/core/src/task/wake.rs
index 89adfccd9..808825326 100644
--- a/library/core/src/task/wake.rs
+++ b/library/core/src/task/wake.rs
@@ -174,7 +174,7 @@ impl RawWakerVTable {
/// Currently, `Context` only serves to provide access to a [`&Waker`](Waker)
/// which can be used to wake the current task.
#[stable(feature = "futures_api", since = "1.36.0")]
-#[cfg_attr(not(bootstrap), lang = "Context")]
+#[lang = "Context"]
pub struct Context<'a> {
waker: &'a Waker,
// Ensure we future-proof against variance changes by forcing
diff --git a/library/core/tests/array.rs b/library/core/tests/array.rs
index f268fe3ae..5327e4f81 100644
--- a/library/core/tests/array.rs
+++ b/library/core/tests/array.rs
@@ -700,3 +700,28 @@ fn array_into_iter_rfold() {
let s = it.rfold(10, |a, b| 10 * a + b);
assert_eq!(s, 10432);
}
+
+#[cfg(not(panic = "abort"))]
+#[test]
+fn array_map_drops_unmapped_elements_on_panic() {
+ struct DropCounter<'a>(usize, &'a AtomicUsize);
+ impl Drop for DropCounter<'_> {
+ fn drop(&mut self) {
+ self.1.fetch_add(1, Ordering::SeqCst);
+ }
+ }
+
+ const MAX: usize = 11;
+ for panic_after in 0..MAX {
+ let counter = AtomicUsize::new(0);
+ let a = array::from_fn::<_, 11, _>(|i| DropCounter(i, &counter));
+ let success = std::panic::catch_unwind(|| {
+ let _ = a.map(|x| {
+ assert!(x.0 < panic_after);
+ assert_eq!(counter.load(Ordering::SeqCst), x.0);
+ });
+ });
+ assert!(success.is_err());
+ assert_eq!(counter.load(Ordering::SeqCst), MAX);
+ }
+}
diff --git a/library/core/tests/iter/adapters/mod.rs b/library/core/tests/iter/adapters/mod.rs
index ffd5f3857..ca3463aa7 100644
--- a/library/core/tests/iter/adapters/mod.rs
+++ b/library/core/tests/iter/adapters/mod.rs
@@ -24,7 +24,7 @@ mod zip;
use core::cell::Cell;
-/// An iterator that panics whenever `next` or next_back` is called
+/// An iterator that panics whenever `next` or `next_back` is called
/// after `None` has already been returned. This does not violate
/// `Iterator`'s contract. Used to test that iterator adapters don't
/// poll their inner iterators after exhausting them.
diff --git a/library/core/tests/iter/range.rs b/library/core/tests/iter/range.rs
index 84498a8ea..0f91ffe2d 100644
--- a/library/core/tests/iter/range.rs
+++ b/library/core/tests/iter/range.rs
@@ -26,7 +26,6 @@ fn test_range() {
#[test]
fn test_char_range() {
- use std::char;
// Miri is too slow
let from = if cfg!(miri) { char::from_u32(0xD800 - 10).unwrap() } else { '\0' };
let to = if cfg!(miri) { char::from_u32(0xDFFF + 10).unwrap() } else { char::MAX };
diff --git a/library/core/tests/iter/traits/iterator.rs b/library/core/tests/iter/traits/iterator.rs
index 37345c1d3..62566a950 100644
--- a/library/core/tests/iter/traits/iterator.rs
+++ b/library/core/tests/iter/traits/iterator.rs
@@ -582,6 +582,9 @@ fn test_next_chunk() {
assert_eq!(it.next_chunk().unwrap(), []);
assert_eq!(it.next_chunk().unwrap(), [4, 5, 6, 7, 8, 9]);
assert_eq!(it.next_chunk::<4>().unwrap_err().as_slice(), &[10, 11]);
+
+ let mut it = std::iter::repeat_with(|| panic!());
+ assert_eq!(it.next_chunk::<0>().unwrap(), []);
}
// just tests by whether or not this compiles
diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs
index 42a26ae16..ccb7be68e 100644
--- a/library/core/tests/lib.rs
+++ b/library/core/tests/lib.rs
@@ -66,6 +66,8 @@
#![feature(try_trait_v2)]
#![feature(slice_internals)]
#![feature(slice_partition_dedup)]
+#![feature(ip)]
+#![feature(ip_in_core)]
#![feature(iter_advance_by)]
#![feature(iter_array_chunks)]
#![feature(iter_collect_into)]
@@ -77,6 +79,9 @@
#![feature(iter_repeat_n)]
#![feature(iterator_try_collect)]
#![feature(iterator_try_reduce)]
+#![feature(const_ip)]
+#![feature(const_ipv4)]
+#![feature(const_ipv6)]
#![feature(const_mut_refs)]
#![feature(const_pin)]
#![feature(const_waker)]
@@ -135,6 +140,7 @@ mod lazy;
mod macros;
mod manually_drop;
mod mem;
+mod net;
mod nonzero;
mod num;
mod ops;
diff --git a/library/core/tests/net/ip_addr.rs b/library/core/tests/net/ip_addr.rs
new file mode 100644
index 000000000..5a6ac08c0
--- /dev/null
+++ b/library/core/tests/net/ip_addr.rs
@@ -0,0 +1,1035 @@
+use super::{sa4, sa6};
+use core::net::{
+ IpAddr, Ipv4Addr, Ipv6Addr, Ipv6MulticastScope, SocketAddr, SocketAddrV4, SocketAddrV6,
+};
+use core::str::FromStr;
+
+#[test]
+fn test_from_str_ipv4() {
+ assert_eq!(Ok(Ipv4Addr::new(127, 0, 0, 1)), "127.0.0.1".parse());
+ assert_eq!(Ok(Ipv4Addr::new(255, 255, 255, 255)), "255.255.255.255".parse());
+ assert_eq!(Ok(Ipv4Addr::new(0, 0, 0, 0)), "0.0.0.0".parse());
+
+ // out of range
+ let none: Option<Ipv4Addr> = "256.0.0.1".parse().ok();
+ assert_eq!(None, none);
+ // too short
+ let none: Option<Ipv4Addr> = "255.0.0".parse().ok();
+ assert_eq!(None, none);
+ // too long
+ let none: Option<Ipv4Addr> = "255.0.0.1.2".parse().ok();
+ assert_eq!(None, none);
+ // no number between dots
+ let none: Option<Ipv4Addr> = "255.0..1".parse().ok();
+ assert_eq!(None, none);
+ // octal
+ let none: Option<Ipv4Addr> = "255.0.0.01".parse().ok();
+ assert_eq!(None, none);
+ // octal zero
+ let none: Option<Ipv4Addr> = "255.0.0.00".parse().ok();
+ assert_eq!(None, none);
+ let none: Option<Ipv4Addr> = "255.0.00.0".parse().ok();
+ assert_eq!(None, none);
+}
+
+#[test]
+fn test_from_str_ipv6() {
+ assert_eq!(Ok(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0)), "0:0:0:0:0:0:0:0".parse());
+ assert_eq!(Ok(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1)), "0:0:0:0:0:0:0:1".parse());
+
+ assert_eq!(Ok(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1)), "::1".parse());
+ assert_eq!(Ok(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0)), "::".parse());
+
+ assert_eq!(Ok(Ipv6Addr::new(0x2a02, 0x6b8, 0, 0, 0, 0, 0x11, 0x11)), "2a02:6b8::11:11".parse());
+
+ // too long group
+ let none: Option<Ipv6Addr> = "::00000".parse().ok();
+ assert_eq!(None, none);
+ // too short
+ let none: Option<Ipv6Addr> = "1:2:3:4:5:6:7".parse().ok();
+ assert_eq!(None, none);
+ // too long
+ let none: Option<Ipv6Addr> = "1:2:3:4:5:6:7:8:9".parse().ok();
+ assert_eq!(None, none);
+ // triple colon
+ let none: Option<Ipv6Addr> = "1:2:::6:7:8".parse().ok();
+ assert_eq!(None, none);
+ // two double colons
+ let none: Option<Ipv6Addr> = "1:2::6::8".parse().ok();
+ assert_eq!(None, none);
+ // `::` indicating zero groups of zeros
+ let none: Option<Ipv6Addr> = "1:2:3:4::5:6:7:8".parse().ok();
+ assert_eq!(None, none);
+}
+
+#[test]
+fn test_from_str_ipv4_in_ipv6() {
+ assert_eq!(Ok(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 49152, 545)), "::192.0.2.33".parse());
+ assert_eq!(Ok(Ipv6Addr::new(0, 0, 0, 0, 0, 0xFFFF, 49152, 545)), "::FFFF:192.0.2.33".parse());
+ assert_eq!(
+ Ok(Ipv6Addr::new(0x64, 0xff9b, 0, 0, 0, 0, 49152, 545)),
+ "64:ff9b::192.0.2.33".parse()
+ );
+ assert_eq!(
+ Ok(Ipv6Addr::new(0x2001, 0xdb8, 0x122, 0xc000, 0x2, 0x2100, 49152, 545)),
+ "2001:db8:122:c000:2:2100:192.0.2.33".parse()
+ );
+
+ // colon after v4
+ let none: Option<Ipv4Addr> = "::127.0.0.1:".parse().ok();
+ assert_eq!(None, none);
+ // not enough groups
+ let none: Option<Ipv6Addr> = "1:2:3:4:5:127.0.0.1".parse().ok();
+ assert_eq!(None, none);
+ // too many groups
+ let none: Option<Ipv6Addr> = "1:2:3:4:5:6:7:127.0.0.1".parse().ok();
+ assert_eq!(None, none);
+}
+
+#[test]
+fn test_from_str_socket_addr() {
+ assert_eq!(Ok(sa4(Ipv4Addr::new(77, 88, 21, 11), 80)), "77.88.21.11:80".parse());
+ assert_eq!(Ok(SocketAddrV4::new(Ipv4Addr::new(77, 88, 21, 11), 80)), "77.88.21.11:80".parse());
+ assert_eq!(
+ Ok(sa6(Ipv6Addr::new(0x2a02, 0x6b8, 0, 1, 0, 0, 0, 1), 53)),
+ "[2a02:6b8:0:1::1]:53".parse()
+ );
+ assert_eq!(
+ Ok(SocketAddrV6::new(Ipv6Addr::new(0x2a02, 0x6b8, 0, 1, 0, 0, 0, 1), 53, 0, 0)),
+ "[2a02:6b8:0:1::1]:53".parse()
+ );
+ assert_eq!(Ok(sa6(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0x7F00, 1), 22)), "[::127.0.0.1]:22".parse());
+ assert_eq!(
+ Ok(SocketAddrV6::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0x7F00, 1), 22, 0, 0)),
+ "[::127.0.0.1]:22".parse()
+ );
+
+ // without port
+ let none: Option<SocketAddr> = "127.0.0.1".parse().ok();
+ assert_eq!(None, none);
+ // without port
+ let none: Option<SocketAddr> = "127.0.0.1:".parse().ok();
+ assert_eq!(None, none);
+ // wrong brackets around v4
+ let none: Option<SocketAddr> = "[127.0.0.1]:22".parse().ok();
+ assert_eq!(None, none);
+ // port out of range
+ let none: Option<SocketAddr> = "127.0.0.1:123456".parse().ok();
+ assert_eq!(None, none);
+}
+
+#[test]
+fn ipv4_addr_to_string() {
+ assert_eq!(Ipv4Addr::new(127, 0, 0, 1).to_string(), "127.0.0.1");
+ // Short address
+ assert_eq!(Ipv4Addr::new(1, 1, 1, 1).to_string(), "1.1.1.1");
+ // Long address
+ assert_eq!(Ipv4Addr::new(127, 127, 127, 127).to_string(), "127.127.127.127");
+
+ // Test padding
+ assert_eq!(format!("{:16}", Ipv4Addr::new(1, 1, 1, 1)), "1.1.1.1 ");
+ assert_eq!(format!("{:>16}", Ipv4Addr::new(1, 1, 1, 1)), " 1.1.1.1");
+}
+
+#[test]
+fn ipv6_addr_to_string() {
+ // ipv4-mapped address
+ let a1 = Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc000, 0x280);
+ assert_eq!(a1.to_string(), "::ffff:192.0.2.128");
+
+ // ipv4-compatible address
+ let a1 = Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0xc000, 0x280);
+ assert_eq!(a1.to_string(), "::192.0.2.128");
+
+ // v6 address with no zero segments
+ assert_eq!(Ipv6Addr::new(8, 9, 10, 11, 12, 13, 14, 15).to_string(), "8:9:a:b:c:d:e:f");
+
+ // longest possible IPv6 length
+ assert_eq!(
+ Ipv6Addr::new(0x1111, 0x2222, 0x3333, 0x4444, 0x5555, 0x6666, 0x7777, 0x8888).to_string(),
+ "1111:2222:3333:4444:5555:6666:7777:8888"
+ );
+ // padding
+ assert_eq!(format!("{:20}", Ipv6Addr::new(1, 2, 3, 4, 5, 6, 7, 8)), "1:2:3:4:5:6:7:8 ");
+ assert_eq!(format!("{:>20}", Ipv6Addr::new(1, 2, 3, 4, 5, 6, 7, 8)), " 1:2:3:4:5:6:7:8");
+
+ // reduce a single run of zeros
+ assert_eq!(
+ "ae::ffff:102:304",
+ Ipv6Addr::new(0xae, 0, 0, 0, 0, 0xffff, 0x0102, 0x0304).to_string()
+ );
+
+ // don't reduce just a single zero segment
+ assert_eq!("1:2:3:4:5:6:0:8", Ipv6Addr::new(1, 2, 3, 4, 5, 6, 0, 8).to_string());
+
+ // 'any' address
+ assert_eq!("::", Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0).to_string());
+
+ // loopback address
+ assert_eq!("::1", Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1).to_string());
+
+ // ends in zeros
+ assert_eq!("1::", Ipv6Addr::new(1, 0, 0, 0, 0, 0, 0, 0).to_string());
+
+ // two runs of zeros, second one is longer
+ assert_eq!("1:0:0:4::8", Ipv6Addr::new(1, 0, 0, 4, 0, 0, 0, 8).to_string());
+
+ // two runs of zeros, equal length
+ assert_eq!("1::4:5:0:0:8", Ipv6Addr::new(1, 0, 0, 4, 5, 0, 0, 8).to_string());
+
+ // don't prefix `0x` to each segment in `dbg!`.
+ assert_eq!("1::4:5:0:0:8", &format!("{:#?}", Ipv6Addr::new(1, 0, 0, 4, 5, 0, 0, 8)));
+}
+
+#[test]
+fn ipv4_to_ipv6() {
+ assert_eq!(
+ Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0x1234, 0x5678),
+ Ipv4Addr::new(0x12, 0x34, 0x56, 0x78).to_ipv6_mapped()
+ );
+ assert_eq!(
+ Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0x1234, 0x5678),
+ Ipv4Addr::new(0x12, 0x34, 0x56, 0x78).to_ipv6_compatible()
+ );
+}
+
+#[test]
+fn ipv6_to_ipv4_mapped() {
+ assert_eq!(
+ Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0x1234, 0x5678).to_ipv4_mapped(),
+ Some(Ipv4Addr::new(0x12, 0x34, 0x56, 0x78))
+ );
+ assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0x1234, 0x5678).to_ipv4_mapped(), None);
+}
+
+#[test]
+fn ipv6_to_ipv4() {
+ assert_eq!(
+ Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0x1234, 0x5678).to_ipv4(),
+ Some(Ipv4Addr::new(0x12, 0x34, 0x56, 0x78))
+ );
+ assert_eq!(
+ Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0x1234, 0x5678).to_ipv4(),
+ Some(Ipv4Addr::new(0x12, 0x34, 0x56, 0x78))
+ );
+ assert_eq!(Ipv6Addr::new(0, 0, 1, 0, 0, 0, 0x1234, 0x5678).to_ipv4(), None);
+}
+
+#[test]
+fn ip_properties() {
+ macro_rules! ip {
+ ($s:expr) => {
+ IpAddr::from_str($s).unwrap()
+ };
+ }
+
+ macro_rules! check {
+ ($s:expr) => {
+ check!($s, 0);
+ };
+
+ ($s:expr, $mask:expr) => {{
+ let unspec: u8 = 1 << 0;
+ let loopback: u8 = 1 << 1;
+ 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());
+ } else {
+ assert!(!ip!($s).is_unspecified());
+ }
+
+ if ($mask & loopback) == loopback {
+ assert!(ip!($s).is_loopback());
+ } else {
+ assert!(!ip!($s).is_loopback());
+ }
+
+ if ($mask & global) == global {
+ assert!(ip!($s).is_global());
+ } else {
+ assert!(!ip!($s).is_global());
+ }
+
+ if ($mask & multicast) == multicast {
+ assert!(ip!($s).is_multicast());
+ } else {
+ assert!(!ip!($s).is_multicast());
+ }
+
+ if ($mask & doc) == doc {
+ assert!(ip!($s).is_documentation());
+ } else {
+ assert!(!ip!($s).is_documentation());
+ }
+
+ if ($mask & benchmarking) == benchmarking {
+ assert!(ip!($s).is_benchmarking());
+ } else {
+ assert!(!ip!($s).is_benchmarking());
+ }
+ }};
+ }
+
+ let unspec: u8 = 1 << 0;
+ let loopback: u8 = 1 << 1;
+ 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");
+ check!("0.1.0.0");
+ check!("10.9.8.7");
+ check!("127.1.2.3", loopback);
+ check!("172.31.254.253");
+ check!("169.254.253.242");
+ check!("192.0.2.183", doc);
+ check!("192.1.2.183", global);
+ check!("192.168.254.253");
+ check!("198.51.100.0", doc);
+ check!("203.0.113.0", doc);
+ check!("203.2.113.0", global);
+ check!("224.0.0.0", global | multicast);
+ check!("239.255.255.255", global | multicast);
+ check!("255.255.255.255");
+ // make sure benchmarking addresses are not global
+ 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");
+ check!("192.0.0.100");
+ // make sure reserved addresses are not global
+ check!("240.0.0.0");
+ check!("251.54.1.76");
+ check!("254.255.255.255");
+ // make sure shared addresses are not global
+ check!("100.64.0.0");
+ check!("100.127.255.255");
+ check!("100.100.100.0");
+
+ check!("::", unspec);
+ check!("::1", loopback);
+ check!("::0.0.0.2", global);
+ check!("1::", global);
+ check!("fc00::");
+ check!("fdff:ffff::");
+ check!("fe80:ffff::");
+ check!("febf:ffff::");
+ check!("fec0::", global);
+ check!("ff01::", global | multicast);
+ check!("ff02::", global | multicast);
+ check!("ff03::", global | multicast);
+ check!("ff04::", global | multicast);
+ check!("ff05::", global | multicast);
+ check!("ff08::", global | multicast);
+ check!("ff0e::", global | multicast);
+ check!("2001:db8:85a3::8a2e:370:7334", doc);
+ check!("2001:2::ac32:23ff:21", benchmarking);
+ check!("102:304:506:708:90a:b0c:d0e:f10", global);
+}
+
+#[test]
+fn ipv4_properties() {
+ macro_rules! ip {
+ ($s:expr) => {
+ Ipv4Addr::from_str($s).unwrap()
+ };
+ }
+
+ macro_rules! check {
+ ($s:expr) => {
+ check!($s, 0);
+ };
+
+ ($s:expr, $mask:expr) => {{
+ let unspec: u16 = 1 << 0;
+ let loopback: u16 = 1 << 1;
+ let private: u16 = 1 << 2;
+ let link_local: u16 = 1 << 3;
+ let global: u16 = 1 << 4;
+ let multicast: u16 = 1 << 5;
+ let broadcast: u16 = 1 << 6;
+ let documentation: u16 = 1 << 7;
+ let benchmarking: u16 = 1 << 8;
+ let reserved: u16 = 1 << 10;
+ let shared: u16 = 1 << 11;
+
+ if ($mask & unspec) == unspec {
+ assert!(ip!($s).is_unspecified());
+ } else {
+ assert!(!ip!($s).is_unspecified());
+ }
+
+ if ($mask & loopback) == loopback {
+ assert!(ip!($s).is_loopback());
+ } else {
+ assert!(!ip!($s).is_loopback());
+ }
+
+ if ($mask & private) == private {
+ assert!(ip!($s).is_private());
+ } else {
+ assert!(!ip!($s).is_private());
+ }
+
+ if ($mask & link_local) == link_local {
+ assert!(ip!($s).is_link_local());
+ } else {
+ assert!(!ip!($s).is_link_local());
+ }
+
+ if ($mask & global) == global {
+ assert!(ip!($s).is_global());
+ } else {
+ assert!(!ip!($s).is_global());
+ }
+
+ if ($mask & multicast) == multicast {
+ assert!(ip!($s).is_multicast());
+ } else {
+ assert!(!ip!($s).is_multicast());
+ }
+
+ if ($mask & broadcast) == broadcast {
+ assert!(ip!($s).is_broadcast());
+ } else {
+ assert!(!ip!($s).is_broadcast());
+ }
+
+ if ($mask & documentation) == documentation {
+ assert!(ip!($s).is_documentation());
+ } else {
+ assert!(!ip!($s).is_documentation());
+ }
+
+ if ($mask & benchmarking) == benchmarking {
+ assert!(ip!($s).is_benchmarking());
+ } else {
+ assert!(!ip!($s).is_benchmarking());
+ }
+
+ if ($mask & reserved) == reserved {
+ assert!(ip!($s).is_reserved());
+ } else {
+ assert!(!ip!($s).is_reserved());
+ }
+
+ if ($mask & shared) == shared {
+ assert!(ip!($s).is_shared());
+ } else {
+ assert!(!ip!($s).is_shared());
+ }
+ }};
+ }
+
+ let unspec: u16 = 1 << 0;
+ let loopback: u16 = 1 << 1;
+ let private: u16 = 1 << 2;
+ let link_local: u16 = 1 << 3;
+ let global: u16 = 1 << 4;
+ let multicast: u16 = 1 << 5;
+ let broadcast: u16 = 1 << 6;
+ let documentation: u16 = 1 << 7;
+ let benchmarking: u16 = 1 << 8;
+ let reserved: u16 = 1 << 10;
+ let shared: u16 = 1 << 11;
+
+ check!("0.0.0.0", unspec);
+ check!("0.0.0.1");
+ check!("0.1.0.0");
+ check!("10.9.8.7", private);
+ check!("127.1.2.3", loopback);
+ check!("172.31.254.253", private);
+ check!("169.254.253.242", link_local);
+ check!("192.0.2.183", documentation);
+ check!("192.1.2.183", global);
+ check!("192.168.254.253", private);
+ check!("198.51.100.0", documentation);
+ check!("203.0.113.0", documentation);
+ check!("203.2.113.0", global);
+ check!("224.0.0.0", global | multicast);
+ check!("239.255.255.255", global | multicast);
+ check!("255.255.255.255", broadcast);
+ check!("198.18.0.0", benchmarking);
+ check!("198.18.54.2", benchmarking);
+ check!("198.19.255.255", benchmarking);
+ check!("192.0.0.0");
+ check!("192.0.0.255");
+ check!("192.0.0.100");
+ check!("240.0.0.0", reserved);
+ check!("251.54.1.76", reserved);
+ check!("254.255.255.255", reserved);
+ check!("100.64.0.0", shared);
+ check!("100.127.255.255", shared);
+ check!("100.100.100.0", shared);
+}
+
+#[test]
+fn ipv6_properties() {
+ macro_rules! ip {
+ ($s:expr) => {
+ Ipv6Addr::from_str($s).unwrap()
+ };
+ }
+
+ macro_rules! check {
+ ($s:expr, &[$($octet:expr),*], $mask:expr) => {
+ assert_eq!($s, ip!($s).to_string());
+ let octets = &[$($octet),*];
+ assert_eq!(&ip!($s).octets(), octets);
+ assert_eq!(Ipv6Addr::from(*octets), ip!($s));
+
+ 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
+ | multicast_realm_local
+ | multicast_site_local
+ | multicast_organization_local;
+
+ if ($mask & unspecified) == unspecified {
+ assert!(ip!($s).is_unspecified());
+ } else {
+ assert!(!ip!($s).is_unspecified());
+ }
+ if ($mask & loopback) == loopback {
+ assert!(ip!($s).is_loopback());
+ } else {
+ assert!(!ip!($s).is_loopback());
+ }
+ if ($mask & unique_local) == unique_local {
+ assert!(ip!($s).is_unique_local());
+ } else {
+ assert!(!ip!($s).is_unique_local());
+ }
+ if ($mask & global) == global {
+ assert!(ip!($s).is_global());
+ } else {
+ assert!(!ip!($s).is_global());
+ }
+ if ($mask & unicast_link_local) == unicast_link_local {
+ assert!(ip!($s).is_unicast_link_local());
+ } else {
+ assert!(!ip!($s).is_unicast_link_local());
+ }
+ if ($mask & unicast_global) == unicast_global {
+ assert!(ip!($s).is_unicast_global());
+ } else {
+ assert!(!ip!($s).is_unicast_global());
+ }
+ if ($mask & documentation) == documentation {
+ assert!(ip!($s).is_documentation());
+ } 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());
+ } else {
+ assert!(ip!($s).multicast_scope().is_none());
+ assert!(!ip!($s).is_multicast());
+ }
+ if ($mask & multicast_interface_local) == multicast_interface_local {
+ assert_eq!(ip!($s).multicast_scope().unwrap(),
+ Ipv6MulticastScope::InterfaceLocal);
+ }
+ if ($mask & multicast_link_local) == multicast_link_local {
+ assert_eq!(ip!($s).multicast_scope().unwrap(),
+ Ipv6MulticastScope::LinkLocal);
+ }
+ if ($mask & multicast_realm_local) == multicast_realm_local {
+ assert_eq!(ip!($s).multicast_scope().unwrap(),
+ Ipv6MulticastScope::RealmLocal);
+ }
+ if ($mask & multicast_admin_local) == multicast_admin_local {
+ assert_eq!(ip!($s).multicast_scope().unwrap(),
+ Ipv6MulticastScope::AdminLocal);
+ }
+ if ($mask & multicast_site_local) == multicast_site_local {
+ assert_eq!(ip!($s).multicast_scope().unwrap(),
+ Ipv6MulticastScope::SiteLocal);
+ }
+ if ($mask & multicast_organization_local) == multicast_organization_local {
+ assert_eq!(ip!($s).multicast_scope().unwrap(),
+ Ipv6MulticastScope::OrganizationLocal);
+ }
+ if ($mask & multicast_global) == multicast_global {
+ assert_eq!(ip!($s).multicast_scope().unwrap(),
+ Ipv6MulticastScope::Global);
+ }
+ }
+ }
+
+ 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);
+
+ check!("::1", &[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], loopback);
+
+ check!("::0.0.0.2", &[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2], global | unicast_global);
+
+ check!("1::", &[0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], global | unicast_global);
+
+ check!(
+ "::ffff:127.0.0.1",
+ &[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff, 0x7f, 0, 0, 1],
+ unicast_global
+ );
+
+ check!(
+ "64:ff9b:1::",
+ &[0, 0x64, 0xff, 0x9b, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+ unicast_global
+ );
+
+ check!("100::", &[0x01, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], unicast_global);
+
+ check!("2001::", &[0x20, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], unicast_global);
+
+ check!(
+ "2001:1::1",
+ &[0x20, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
+ global | unicast_global
+ );
+
+ check!(
+ "2001:1::2",
+ &[0x20, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2],
+ global | unicast_global
+ );
+
+ check!(
+ "2001:3::",
+ &[0x20, 1, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+ global | unicast_global
+ );
+
+ check!(
+ "2001:4:112::",
+ &[0x20, 1, 0, 4, 1, 0x12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+ global | unicast_global
+ );
+
+ check!(
+ "2001:20::",
+ &[0x20, 1, 0, 0x20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+ global | unicast_global
+ );
+
+ check!("2001:30::", &[0x20, 1, 0, 0x30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], unicast_global);
+
+ check!(
+ "2001:200::",
+ &[0x20, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+ global | unicast_global
+ );
+
+ check!("fc00::", &[0xfc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], unique_local);
+
+ check!(
+ "fdff:ffff::",
+ &[0xfd, 0xff, 0xff, 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+ unique_local
+ );
+
+ check!(
+ "fe80:ffff::",
+ &[0xfe, 0x80, 0xff, 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+ unicast_link_local
+ );
+
+ check!("fe80::", &[0xfe, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], unicast_link_local);
+
+ check!(
+ "febf:ffff::",
+ &[0xfe, 0xbf, 0xff, 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+ unicast_link_local
+ );
+
+ check!("febf::", &[0xfe, 0xbf, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], unicast_link_local);
+
+ check!(
+ "febf:ffff:ffff:ffff:ffff:ffff:ffff:ffff",
+ &[
+ 0xfe, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff
+ ],
+ unicast_link_local
+ );
+
+ check!(
+ "fe80::ffff:ffff:ffff:ffff",
+ &[
+ 0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff
+ ],
+ unicast_link_local
+ );
+
+ check!(
+ "fe80:0:0:1::",
+ &[0xfe, 0x80, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0],
+ unicast_link_local
+ );
+
+ check!(
+ "fec0::",
+ &[0xfe, 0xc0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+ unicast_global | global
+ );
+
+ check!(
+ "ff01::",
+ &[0xff, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+ multicast_interface_local | global
+ );
+
+ check!(
+ "ff02::",
+ &[0xff, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+ multicast_link_local | global
+ );
+
+ check!(
+ "ff03::",
+ &[0xff, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+ multicast_realm_local | global
+ );
+
+ check!(
+ "ff04::",
+ &[0xff, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+ multicast_admin_local | global
+ );
+
+ check!(
+ "ff05::",
+ &[0xff, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+ multicast_site_local | global
+ );
+
+ check!(
+ "ff08::",
+ &[0xff, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+ multicast_organization_local | global
+ );
+
+ check!(
+ "ff0e::",
+ &[0xff, 0xe, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+ multicast_global | global
+ );
+
+ check!(
+ "2001:db8:85a3::8a2e:370:7334",
+ &[0x20, 1, 0xd, 0xb8, 0x85, 0xa3, 0, 0, 0, 0, 0x8a, 0x2e, 3, 0x70, 0x73, 0x34],
+ documentation
+ );
+
+ check!(
+ "2001:2::ac32:23ff:21",
+ &[0x20, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0xac, 0x32, 0x23, 0xff, 0, 0x21],
+ 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],
+ global | unicast_global
+ );
+}
+
+#[test]
+fn test_ipv4_to_int() {
+ let a = Ipv4Addr::new(0x11, 0x22, 0x33, 0x44);
+ assert_eq!(u32::from(a), 0x11223344);
+}
+
+#[test]
+fn test_int_to_ipv4() {
+ let a = Ipv4Addr::new(0x11, 0x22, 0x33, 0x44);
+ assert_eq!(Ipv4Addr::from(0x11223344), a);
+}
+
+#[test]
+fn test_ipv6_to_int() {
+ let a = Ipv6Addr::new(0x1122, 0x3344, 0x5566, 0x7788, 0x99aa, 0xbbcc, 0xddee, 0xff11);
+ assert_eq!(u128::from(a), 0x112233445566778899aabbccddeeff11u128);
+}
+
+#[test]
+fn test_int_to_ipv6() {
+ let a = Ipv6Addr::new(0x1122, 0x3344, 0x5566, 0x7788, 0x99aa, 0xbbcc, 0xddee, 0xff11);
+ assert_eq!(Ipv6Addr::from(0x112233445566778899aabbccddeeff11u128), a);
+}
+
+#[test]
+fn ipv4_from_constructors() {
+ assert_eq!(Ipv4Addr::LOCALHOST, Ipv4Addr::new(127, 0, 0, 1));
+ assert!(Ipv4Addr::LOCALHOST.is_loopback());
+ assert_eq!(Ipv4Addr::UNSPECIFIED, Ipv4Addr::new(0, 0, 0, 0));
+ assert!(Ipv4Addr::UNSPECIFIED.is_unspecified());
+ assert_eq!(Ipv4Addr::BROADCAST, Ipv4Addr::new(255, 255, 255, 255));
+ assert!(Ipv4Addr::BROADCAST.is_broadcast());
+}
+
+#[test]
+fn ipv6_from_constructors() {
+ assert_eq!(Ipv6Addr::LOCALHOST, Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1));
+ assert!(Ipv6Addr::LOCALHOST.is_loopback());
+ assert_eq!(Ipv6Addr::UNSPECIFIED, Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0));
+ assert!(Ipv6Addr::UNSPECIFIED.is_unspecified());
+}
+
+#[test]
+fn ipv4_from_octets() {
+ assert_eq!(Ipv4Addr::from([127, 0, 0, 1]), Ipv4Addr::new(127, 0, 0, 1))
+}
+
+#[test]
+fn ipv6_from_segments() {
+ let from_u16s =
+ Ipv6Addr::from([0x0011, 0x2233, 0x4455, 0x6677, 0x8899, 0xaabb, 0xccdd, 0xeeff]);
+ let new = Ipv6Addr::new(0x0011, 0x2233, 0x4455, 0x6677, 0x8899, 0xaabb, 0xccdd, 0xeeff);
+ assert_eq!(new, from_u16s);
+}
+
+#[test]
+fn ipv6_from_octets() {
+ let from_u16s =
+ Ipv6Addr::from([0x0011, 0x2233, 0x4455, 0x6677, 0x8899, 0xaabb, 0xccdd, 0xeeff]);
+ let from_u8s = Ipv6Addr::from([
+ 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee,
+ 0xff,
+ ]);
+ assert_eq!(from_u16s, from_u8s);
+}
+
+#[test]
+fn cmp() {
+ let v41 = Ipv4Addr::new(100, 64, 3, 3);
+ let v42 = Ipv4Addr::new(192, 0, 2, 2);
+ let v61 = "2001:db8:f00::1002".parse::<Ipv6Addr>().unwrap();
+ let v62 = "2001:db8:f00::2001".parse::<Ipv6Addr>().unwrap();
+ assert!(v41 < v42);
+ assert!(v61 < v62);
+
+ assert_eq!(v41, IpAddr::V4(v41));
+ assert_eq!(v61, IpAddr::V6(v61));
+ assert!(v41 != IpAddr::V4(v42));
+ assert!(v61 != IpAddr::V6(v62));
+
+ assert!(v41 < IpAddr::V4(v42));
+ assert!(v61 < IpAddr::V6(v62));
+ assert!(IpAddr::V4(v41) < v42);
+ assert!(IpAddr::V6(v61) < v62);
+
+ assert!(v41 < IpAddr::V6(v61));
+ assert!(IpAddr::V4(v41) < v61);
+}
+
+#[test]
+fn is_v4() {
+ let ip = IpAddr::V4(Ipv4Addr::new(100, 64, 3, 3));
+ assert!(ip.is_ipv4());
+ assert!(!ip.is_ipv6());
+}
+
+#[test]
+fn is_v6() {
+ let ip = IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0x1234, 0x5678));
+ assert!(!ip.is_ipv4());
+ assert!(ip.is_ipv6());
+}
+
+#[test]
+fn ipv4_const() {
+ // test that the methods of `Ipv4Addr` are usable in a const context
+
+ const IP_ADDRESS: Ipv4Addr = Ipv4Addr::new(127, 0, 0, 1);
+ assert_eq!(IP_ADDRESS, Ipv4Addr::LOCALHOST);
+
+ const OCTETS: [u8; 4] = IP_ADDRESS.octets();
+ assert_eq!(OCTETS, [127, 0, 0, 1]);
+
+ const IS_UNSPECIFIED: bool = IP_ADDRESS.is_unspecified();
+ assert!(!IS_UNSPECIFIED);
+
+ const IS_LOOPBACK: bool = IP_ADDRESS.is_loopback();
+ assert!(IS_LOOPBACK);
+
+ const IS_PRIVATE: bool = IP_ADDRESS.is_private();
+ assert!(!IS_PRIVATE);
+
+ const IS_LINK_LOCAL: bool = IP_ADDRESS.is_link_local();
+ assert!(!IS_LINK_LOCAL);
+
+ const IS_GLOBAL: bool = IP_ADDRESS.is_global();
+ assert!(!IS_GLOBAL);
+
+ const IS_SHARED: bool = IP_ADDRESS.is_shared();
+ assert!(!IS_SHARED);
+
+ const IS_BENCHMARKING: bool = IP_ADDRESS.is_benchmarking();
+ assert!(!IS_BENCHMARKING);
+
+ const IS_RESERVED: bool = IP_ADDRESS.is_reserved();
+ assert!(!IS_RESERVED);
+
+ const IS_MULTICAST: bool = IP_ADDRESS.is_multicast();
+ assert!(!IS_MULTICAST);
+
+ const IS_BROADCAST: bool = IP_ADDRESS.is_broadcast();
+ assert!(!IS_BROADCAST);
+
+ const IS_DOCUMENTATION: bool = IP_ADDRESS.is_documentation();
+ assert!(!IS_DOCUMENTATION);
+
+ const IP_V6_COMPATIBLE: Ipv6Addr = IP_ADDRESS.to_ipv6_compatible();
+ assert_eq!(
+ IP_V6_COMPATIBLE,
+ Ipv6Addr::from([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 127, 0, 0, 1])
+ );
+
+ const IP_V6_MAPPED: Ipv6Addr = IP_ADDRESS.to_ipv6_mapped();
+ assert_eq!(
+ IP_V6_MAPPED,
+ Ipv6Addr::from([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 127, 0, 0, 1])
+ );
+}
+
+#[test]
+fn ipv6_const() {
+ // test that the methods of `Ipv6Addr` are usable in a const context
+
+ const IP_ADDRESS: Ipv6Addr = Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1);
+ assert_eq!(IP_ADDRESS, Ipv6Addr::LOCALHOST);
+
+ const SEGMENTS: [u16; 8] = IP_ADDRESS.segments();
+ assert_eq!(SEGMENTS, [0, 0, 0, 0, 0, 0, 0, 1]);
+
+ const OCTETS: [u8; 16] = IP_ADDRESS.octets();
+ assert_eq!(OCTETS, [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]);
+
+ const IS_UNSPECIFIED: bool = IP_ADDRESS.is_unspecified();
+ assert!(!IS_UNSPECIFIED);
+
+ const IS_LOOPBACK: bool = IP_ADDRESS.is_loopback();
+ assert!(IS_LOOPBACK);
+
+ const IS_GLOBAL: bool = IP_ADDRESS.is_global();
+ assert!(!IS_GLOBAL);
+
+ const IS_UNIQUE_LOCAL: bool = IP_ADDRESS.is_unique_local();
+ assert!(!IS_UNIQUE_LOCAL);
+
+ const IS_UNICAST_LINK_LOCAL: bool = IP_ADDRESS.is_unicast_link_local();
+ assert!(!IS_UNICAST_LINK_LOCAL);
+
+ 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);
+
+ const MULTICAST_SCOPE: Option<Ipv6MulticastScope> = IP_ADDRESS.multicast_scope();
+ assert_eq!(MULTICAST_SCOPE, None);
+
+ const IS_MULTICAST: bool = IP_ADDRESS.is_multicast();
+ assert!(!IS_MULTICAST);
+
+ const IP_V4: Option<Ipv4Addr> = IP_ADDRESS.to_ipv4();
+ assert_eq!(IP_V4.unwrap(), Ipv4Addr::new(0, 0, 0, 1));
+}
+
+#[test]
+fn ip_const() {
+ // test that the methods of `IpAddr` are usable in a const context
+
+ const IP_ADDRESS: IpAddr = IpAddr::V4(Ipv4Addr::LOCALHOST);
+
+ const IS_UNSPECIFIED: bool = IP_ADDRESS.is_unspecified();
+ assert!(!IS_UNSPECIFIED);
+
+ const IS_LOOPBACK: bool = IP_ADDRESS.is_loopback();
+ assert!(IS_LOOPBACK);
+
+ const IS_GLOBAL: bool = IP_ADDRESS.is_global();
+ assert!(!IS_GLOBAL);
+
+ const IS_MULTICAST: bool = IP_ADDRESS.is_multicast();
+ assert!(!IS_MULTICAST);
+
+ const IS_IP_V4: bool = IP_ADDRESS.is_ipv4();
+ assert!(IS_IP_V4);
+
+ const IS_IP_V6: bool = IP_ADDRESS.is_ipv6();
+ assert!(!IS_IP_V6);
+}
+
+#[test]
+fn structural_match() {
+ // test that all IP types can be structurally matched upon
+
+ const IPV4: Ipv4Addr = Ipv4Addr::LOCALHOST;
+ match IPV4 {
+ Ipv4Addr::LOCALHOST => {}
+ _ => unreachable!(),
+ }
+
+ const IPV6: Ipv6Addr = Ipv6Addr::LOCALHOST;
+ match IPV6 {
+ Ipv6Addr::LOCALHOST => {}
+ _ => unreachable!(),
+ }
+
+ const IP: IpAddr = IpAddr::V4(Ipv4Addr::LOCALHOST);
+ match IP {
+ IpAddr::V4(Ipv4Addr::LOCALHOST) => {}
+ _ => unreachable!(),
+ }
+}
diff --git a/library/core/tests/net/mod.rs b/library/core/tests/net/mod.rs
new file mode 100644
index 000000000..8f17bbe55
--- /dev/null
+++ b/library/core/tests/net/mod.rs
@@ -0,0 +1,13 @@
+use core::net::{Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6};
+
+mod ip_addr;
+mod parser;
+mod socket_addr;
+
+pub fn sa4(a: Ipv4Addr, p: u16) -> SocketAddr {
+ SocketAddr::V4(SocketAddrV4::new(a, p))
+}
+
+pub fn sa6(a: Ipv6Addr, p: u16) -> SocketAddr {
+ SocketAddr::V6(SocketAddrV6::new(a, p, 0, 0))
+}
diff --git a/library/std/src/net/parser/tests.rs b/library/core/tests/net/parser.rs
index 6d2d48eca..36b87d7c1 100644
--- a/library/std/src/net/parser/tests.rs
+++ b/library/core/tests/net/parser.rs
@@ -1,6 +1,6 @@
// FIXME: These tests are all excellent candidates for AFL fuzz testing
-use crate::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6};
-use crate::str::FromStr;
+use core::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6};
+use core::str::FromStr;
const PORT: u16 = 8080;
const SCOPE_ID: u32 = 1337;
diff --git a/library/core/tests/net/socket_addr.rs b/library/core/tests/net/socket_addr.rs
new file mode 100644
index 000000000..68c7cd94d
--- /dev/null
+++ b/library/core/tests/net/socket_addr.rs
@@ -0,0 +1,233 @@
+use core::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6};
+
+#[test]
+fn ipv4_socket_addr_to_string() {
+ // Shortest possible IPv4 length.
+ assert_eq!(SocketAddrV4::new(Ipv4Addr::new(0, 0, 0, 0), 0).to_string(), "0.0.0.0:0");
+
+ // Longest possible IPv4 length.
+ assert_eq!(
+ SocketAddrV4::new(Ipv4Addr::new(255, 255, 255, 255), u16::MAX).to_string(),
+ "255.255.255.255:65535"
+ );
+
+ // Test padding.
+ assert_eq!(
+ &format!("{:16}", SocketAddrV4::new(Ipv4Addr::new(1, 1, 1, 1), 53)),
+ "1.1.1.1:53 "
+ );
+ assert_eq!(
+ &format!("{:>16}", SocketAddrV4::new(Ipv4Addr::new(1, 1, 1, 1), 53)),
+ " 1.1.1.1:53"
+ );
+}
+
+#[test]
+fn ipv6_socket_addr_to_string() {
+ // IPv4-mapped address.
+ assert_eq!(
+ SocketAddrV6::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc000, 0x280), 8080, 0, 0)
+ .to_string(),
+ "[::ffff:192.0.2.128]:8080"
+ );
+
+ // IPv4-compatible address.
+ assert_eq!(
+ SocketAddrV6::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0xc000, 0x280), 8080, 0, 0).to_string(),
+ "[::192.0.2.128]:8080"
+ );
+
+ // IPv6 address with no zero segments.
+ assert_eq!(
+ SocketAddrV6::new(Ipv6Addr::new(8, 9, 10, 11, 12, 13, 14, 15), 80, 0, 0).to_string(),
+ "[8:9:a:b:c:d:e:f]:80"
+ );
+
+ // Shortest possible IPv6 length.
+ assert_eq!(SocketAddrV6::new(Ipv6Addr::UNSPECIFIED, 0, 0, 0).to_string(), "[::]:0");
+
+ // Longest possible IPv6 length.
+ assert_eq!(
+ SocketAddrV6::new(
+ Ipv6Addr::new(0x1111, 0x2222, 0x3333, 0x4444, 0x5555, 0x6666, 0x7777, 0x8888),
+ u16::MAX,
+ u32::MAX,
+ u32::MAX,
+ )
+ .to_string(),
+ "[1111:2222:3333:4444:5555:6666:7777:8888%4294967295]:65535"
+ );
+
+ // Test padding.
+ assert_eq!(
+ &format!("{:22}", SocketAddrV6::new(Ipv6Addr::new(1, 2, 3, 4, 5, 6, 7, 8), 9, 0, 0)),
+ "[1:2:3:4:5:6:7:8]:9 "
+ );
+ assert_eq!(
+ &format!("{:>22}", SocketAddrV6::new(Ipv6Addr::new(1, 2, 3, 4, 5, 6, 7, 8), 9, 0, 0)),
+ " [1:2:3:4:5:6:7:8]:9"
+ );
+}
+
+#[test]
+fn set_ip() {
+ fn ip4(low: u8) -> Ipv4Addr {
+ Ipv4Addr::new(77, 88, 21, low)
+ }
+ fn ip6(low: u16) -> Ipv6Addr {
+ Ipv6Addr::new(0x2a02, 0x6b8, 0, 1, 0, 0, 0, low)
+ }
+
+ let mut v4 = SocketAddrV4::new(ip4(11), 80);
+ assert_eq!(v4.ip(), &ip4(11));
+ v4.set_ip(ip4(12));
+ assert_eq!(v4.ip(), &ip4(12));
+
+ let mut addr = SocketAddr::V4(v4);
+ assert_eq!(addr.ip(), IpAddr::V4(ip4(12)));
+ addr.set_ip(IpAddr::V4(ip4(13)));
+ assert_eq!(addr.ip(), IpAddr::V4(ip4(13)));
+ addr.set_ip(IpAddr::V6(ip6(14)));
+ assert_eq!(addr.ip(), IpAddr::V6(ip6(14)));
+
+ let mut v6 = SocketAddrV6::new(ip6(1), 80, 0, 0);
+ assert_eq!(v6.ip(), &ip6(1));
+ v6.set_ip(ip6(2));
+ assert_eq!(v6.ip(), &ip6(2));
+
+ let mut addr = SocketAddr::V6(v6);
+ assert_eq!(addr.ip(), IpAddr::V6(ip6(2)));
+ addr.set_ip(IpAddr::V6(ip6(3)));
+ assert_eq!(addr.ip(), IpAddr::V6(ip6(3)));
+ addr.set_ip(IpAddr::V4(ip4(4)));
+ assert_eq!(addr.ip(), IpAddr::V4(ip4(4)));
+}
+
+#[test]
+fn set_port() {
+ let mut v4 = SocketAddrV4::new(Ipv4Addr::new(77, 88, 21, 11), 80);
+ assert_eq!(v4.port(), 80);
+ v4.set_port(443);
+ assert_eq!(v4.port(), 443);
+
+ let mut addr = SocketAddr::V4(v4);
+ assert_eq!(addr.port(), 443);
+ addr.set_port(8080);
+ assert_eq!(addr.port(), 8080);
+
+ let mut v6 = SocketAddrV6::new(Ipv6Addr::new(0x2a02, 0x6b8, 0, 1, 0, 0, 0, 1), 80, 0, 0);
+ assert_eq!(v6.port(), 80);
+ v6.set_port(443);
+ assert_eq!(v6.port(), 443);
+
+ let mut addr = SocketAddr::V6(v6);
+ assert_eq!(addr.port(), 443);
+ addr.set_port(8080);
+ assert_eq!(addr.port(), 8080);
+}
+
+#[test]
+fn set_flowinfo() {
+ let mut v6 = SocketAddrV6::new(Ipv6Addr::new(0x2a02, 0x6b8, 0, 1, 0, 0, 0, 1), 80, 10, 0);
+ assert_eq!(v6.flowinfo(), 10);
+ v6.set_flowinfo(20);
+ assert_eq!(v6.flowinfo(), 20);
+}
+
+#[test]
+fn set_scope_id() {
+ let mut v6 = SocketAddrV6::new(Ipv6Addr::new(0x2a02, 0x6b8, 0, 1, 0, 0, 0, 1), 80, 0, 10);
+ assert_eq!(v6.scope_id(), 10);
+ v6.set_scope_id(20);
+ assert_eq!(v6.scope_id(), 20);
+}
+
+#[test]
+fn is_v4() {
+ let v4 = SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::new(77, 88, 21, 11), 80));
+ assert!(v4.is_ipv4());
+ assert!(!v4.is_ipv6());
+}
+
+#[test]
+fn is_v6() {
+ let v6 = SocketAddr::V6(SocketAddrV6::new(
+ Ipv6Addr::new(0x2a02, 0x6b8, 0, 1, 0, 0, 0, 1),
+ 80,
+ 10,
+ 0,
+ ));
+ assert!(!v6.is_ipv4());
+ assert!(v6.is_ipv6());
+}
+
+#[test]
+fn socket_v4_to_str() {
+ let socket = SocketAddrV4::new(Ipv4Addr::new(192, 168, 0, 1), 8080);
+
+ assert_eq!(format!("{socket}"), "192.168.0.1:8080");
+ assert_eq!(format!("{socket:<20}"), "192.168.0.1:8080 ");
+ assert_eq!(format!("{socket:>20}"), " 192.168.0.1:8080");
+ assert_eq!(format!("{socket:^20}"), " 192.168.0.1:8080 ");
+ assert_eq!(format!("{socket:.10}"), "192.168.0.");
+}
+
+#[test]
+fn socket_v6_to_str() {
+ let mut socket = SocketAddrV6::new(Ipv6Addr::new(0x2a02, 0x6b8, 0, 1, 0, 0, 0, 1), 53, 0, 0);
+
+ assert_eq!(format!("{socket}"), "[2a02:6b8:0:1::1]:53");
+ assert_eq!(format!("{socket:<24}"), "[2a02:6b8:0:1::1]:53 ");
+ assert_eq!(format!("{socket:>24}"), " [2a02:6b8:0:1::1]:53");
+ assert_eq!(format!("{socket:^24}"), " [2a02:6b8:0:1::1]:53 ");
+ assert_eq!(format!("{socket:.15}"), "[2a02:6b8:0:1::");
+
+ socket.set_scope_id(5);
+
+ assert_eq!(format!("{socket}"), "[2a02:6b8:0:1::1%5]:53");
+ assert_eq!(format!("{socket:<24}"), "[2a02:6b8:0:1::1%5]:53 ");
+ assert_eq!(format!("{socket:>24}"), " [2a02:6b8:0:1::1%5]:53");
+ assert_eq!(format!("{socket:^24}"), " [2a02:6b8:0:1::1%5]:53 ");
+ assert_eq!(format!("{socket:.18}"), "[2a02:6b8:0:1::1%5");
+}
+
+#[test]
+fn compare() {
+ let v4_1 = "224.120.45.1:23456".parse::<SocketAddrV4>().unwrap();
+ let v4_2 = "224.210.103.5:12345".parse::<SocketAddrV4>().unwrap();
+ let v4_3 = "224.210.103.5:23456".parse::<SocketAddrV4>().unwrap();
+ let v6_1 = "[2001:db8:f00::1002]:23456".parse::<SocketAddrV6>().unwrap();
+ let v6_2 = "[2001:db8:f00::2001]:12345".parse::<SocketAddrV6>().unwrap();
+ let v6_3 = "[2001:db8:f00::2001]:23456".parse::<SocketAddrV6>().unwrap();
+
+ // equality
+ assert_eq!(v4_1, v4_1);
+ assert_eq!(v6_1, v6_1);
+ assert_eq!(SocketAddr::V4(v4_1), SocketAddr::V4(v4_1));
+ assert_eq!(SocketAddr::V6(v6_1), SocketAddr::V6(v6_1));
+ assert!(v4_1 != v4_2);
+ assert!(v6_1 != v6_2);
+
+ // compare different addresses
+ assert!(v4_1 < v4_2);
+ assert!(v6_1 < v6_2);
+ assert!(v4_2 > v4_1);
+ assert!(v6_2 > v6_1);
+
+ // compare the same address with different ports
+ assert!(v4_2 < v4_3);
+ assert!(v6_2 < v6_3);
+ assert!(v4_3 > v4_2);
+ assert!(v6_3 > v6_2);
+
+ // compare different addresses with the same port
+ assert!(v4_1 < v4_3);
+ assert!(v6_1 < v6_3);
+ assert!(v4_3 > v4_1);
+ assert!(v6_3 > v6_1);
+
+ // compare with an inferred right-hand side
+ assert_eq!(v4_1, "224.120.45.1:23456".parse().unwrap());
+ assert_eq!(v6_1, "[2001:db8:f00::1002]:23456".parse().unwrap());
+ assert_eq!(SocketAddr::V4(v4_1), "224.120.45.1:23456".parse().unwrap());
+}
diff --git a/library/core/tests/num/dec2flt/mod.rs b/library/core/tests/num/dec2flt/mod.rs
index c4e105cba..a2b9bb551 100644
--- a/library/core/tests/num/dec2flt/mod.rs
+++ b/library/core/tests/num/dec2flt/mod.rs
@@ -15,7 +15,7 @@ macro_rules! test_literal {
for input in inputs {
assert_eq!(input.parse(), Ok(x64));
assert_eq!(input.parse(), Ok(x32));
- let neg_input = &format!("-{input}");
+ let neg_input = format!("-{input}");
assert_eq!(neg_input.parse(), Ok(-x64));
assert_eq!(neg_input.parse(), Ok(-x32));
}
diff --git a/library/core/tests/ptr.rs b/library/core/tests/ptr.rs
index 80d30f14c..c02cd99cc 100644
--- a/library/core/tests/ptr.rs
+++ b/library/core/tests/ptr.rs
@@ -25,7 +25,7 @@ fn test() {
snd: isize,
}
let mut p = Pair { fst: 10, snd: 20 };
- let pptr: *mut Pair = &mut p;
+ let pptr: *mut Pair = addr_of_mut!(p);
let iptr: *mut isize = pptr as *mut isize;
assert_eq!(*iptr, 10);
*iptr = 30;
@@ -1070,8 +1070,8 @@ fn swap_copy_untyped() {
let mut x = 5u8;
let mut y = 6u8;
- let ptr1 = &mut x as *mut u8 as *mut bool;
- let ptr2 = &mut y as *mut u8 as *mut bool;
+ let ptr1 = addr_of_mut!(x).cast::<bool>();
+ let ptr2 = addr_of_mut!(y).cast::<bool>();
unsafe {
ptr::swap(ptr1, ptr2);
diff --git a/library/portable-simd/crates/core_simd/examples/spectral_norm.rs b/library/portable-simd/crates/core_simd/examples/spectral_norm.rs
index 012182e09..d576bd0cc 100644
--- a/library/portable-simd/crates/core_simd/examples/spectral_norm.rs
+++ b/library/portable-simd/crates/core_simd/examples/spectral_norm.rs
@@ -69,7 +69,7 @@ fn dot(x: &[f64], y: &[f64]) -> f64 {
#[cfg(test)]
#[test]
fn test() {
- assert_eq!(&format!("{:.9}", spectral_norm(100)), "1.274219991");
+ assert_eq!(format!("{:.9}", spectral_norm(100)), "1.274219991");
}
fn main() {
diff --git a/library/portable-simd/crates/core_simd/src/vector.rs b/library/portable-simd/crates/core_simd/src/vector.rs
index 78f56402e..d52d1ac4d 100644
--- a/library/portable-simd/crates/core_simd/src/vector.rs
+++ b/library/portable-simd/crates/core_simd/src/vector.rs
@@ -28,7 +28,7 @@ use crate::simd::{
/// let zm_add = a0.zip(a1).map(|(lhs, rhs)| lhs + rhs);
/// let zm_mul = a0.zip(a1).map(|(lhs, rhs)| lhs * rhs);
///
-/// // `Simd<T, N>` implements `From<[T; N]>
+/// // `Simd<T, N>` implements `From<[T; N]>`
/// let (v0, v1) = (Simd::from(a0), Simd::from(a1));
/// // Which means arrays implement `Into<Simd<T, N>>`.
/// assert_eq!(v0 + v1, zm_add.into());
diff --git a/library/proc_macro/src/bridge/rpc.rs b/library/proc_macro/src/bridge/rpc.rs
index e9d7a46c0..5b1bfb309 100644
--- a/library/proc_macro/src/bridge/rpc.rs
+++ b/library/proc_macro/src/bridge/rpc.rs
@@ -1,7 +1,6 @@
//! Serialization for client-server communication.
use std::any::Any;
-use std::char;
use std::io::Write;
use std::num::NonZeroU32;
use std::str;
diff --git a/library/proc_macro/src/lib.rs b/library/proc_macro/src/lib.rs
index f0e4f5d8a..938935771 100644
--- a/library/proc_macro/src/lib.rs
+++ b/library/proc_macro/src/lib.rs
@@ -74,6 +74,7 @@ pub fn is_available() -> bool {
///
/// This is both the input and output of `#[proc_macro]`, `#[proc_macro_attribute]`
/// and `#[proc_macro_derive]` definitions.
+#[rustc_diagnostic_item = "TokenStream"]
#[stable(feature = "proc_macro_lib", since = "1.15.0")]
#[derive(Clone)]
pub struct TokenStream(Option<bridge::client::TokenStream>);
@@ -581,7 +582,7 @@ impl fmt::Debug for Span {
/// A line-column pair representing the start or end of a `Span`.
#[unstable(feature = "proc_macro_span", issue = "54725")]
-#[derive(Copy, Clone, Debug, PartialEq, Eq)]
+#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
pub struct LineColumn {
/// The 1-indexed line in the source file on which the span starts or ends (inclusive).
#[unstable(feature = "proc_macro_span", issue = "54725")]
diff --git a/library/std/Cargo.toml b/library/std/Cargo.toml
index adf521d9b..598a4bf92 100644
--- a/library/std/Cargo.toml
+++ b/library/std/Cargo.toml
@@ -15,8 +15,8 @@ cfg-if = { version = "1.0", features = ['rustc-dep-of-std'] }
panic_unwind = { path = "../panic_unwind", optional = true }
panic_abort = { path = "../panic_abort" }
core = { path = "../core" }
-libc = { version = "0.2.138", default-features = false, features = ['rustc-dep-of-std'] }
-compiler_builtins = { version = "0.1.85" }
+libc = { version = "0.2.139", default-features = false, features = ['rustc-dep-of-std'] }
+compiler_builtins = { version = "0.1.87" }
profiler_builtins = { path = "../profiler_builtins", optional = true }
unwind = { path = "../unwind" }
hashbrown = { version = "0.12", default-features = false, features = ['rustc-dep-of-std'] }
@@ -43,7 +43,7 @@ dlmalloc = { version = "0.2.3", features = ['rustc-dep-of-std'] }
fortanix-sgx-abi = { version = "0.5.0", features = ['rustc-dep-of-std'] }
[target.'cfg(target_os = "hermit")'.dependencies]
-hermit-abi = { version = "0.2.6", features = ['rustc-dep-of-std'] }
+hermit-abi = { version = "0.3.0", features = ['rustc-dep-of-std'] }
[target.wasm32-wasi.dependencies]
wasi = { version = "0.11.0", features = ['rustc-dep-of-std'], default-features = false }
diff --git a/library/std/build.rs b/library/std/build.rs
index 8b1a06ee7..ea8796675 100644
--- a/library/std/build.rs
+++ b/library/std/build.rs
@@ -31,6 +31,7 @@ fn main() {
|| target.contains("espidf")
|| target.contains("solid")
|| target.contains("nintendo-3ds")
+ || target.contains("nto")
{
// These platforms don't have any special requirements.
} else {
diff --git a/library/std/src/collections/hash/map.rs b/library/std/src/collections/hash/map.rs
index df4903588..742c4cc7c 100644
--- a/library/std/src/collections/hash/map.rs
+++ b/library/std/src/collections/hash/map.rs
@@ -238,7 +238,7 @@ impl<K, V> HashMap<K, V, RandomState> {
///
/// The hash map will be able to hold at least `capacity` elements without
/// reallocating. This method is allowed to allocate for more elements than
- /// `capacity`. If `capacity` is 0, the hash set will not allocate.
+ /// `capacity`. If `capacity` is 0, the hash map will not allocate.
///
/// # Examples
///
diff --git a/library/std/src/f32.rs b/library/std/src/f32.rs
index 4e3007624..6b1f0cba8 100644
--- a/library/std/src/f32.rs
+++ b/library/std/src/f32.rs
@@ -69,8 +69,8 @@ impl f32 {
unsafe { intrinsics::ceilf32(self) }
}
- /// Returns the nearest integer to `self`. Round half-way cases away from
- /// `0.0`.
+ /// Returns the nearest integer to `self`. If a value is half-way between two
+ /// integers, round away from `0.0`.
///
/// # Examples
///
diff --git a/library/std/src/f64.rs b/library/std/src/f64.rs
index ec67fdad4..16359766b 100644
--- a/library/std/src/f64.rs
+++ b/library/std/src/f64.rs
@@ -69,8 +69,8 @@ impl f64 {
unsafe { intrinsics::ceilf64(self) }
}
- /// Returns the nearest integer to `self`. Round half-way cases away from
- /// `0.0`.
+ /// Returns the nearest integer to `self`. If a value is half-way between two
+ /// integers, round away from `0.0`.
///
/// # Examples
///
diff --git a/library/std/src/fs.rs b/library/std/src/fs.rs
index 286ad68fd..c550378e7 100644
--- a/library/std/src/fs.rs
+++ b/library/std/src/fs.rs
@@ -334,6 +334,10 @@ impl File {
///
/// See the [`OpenOptions::open`] method for more details.
///
+ /// If you only need to read the entire file contents,
+ /// consider [`std::fs::read()`][self::read] or
+ /// [`std::fs::read_to_string()`][self::read_to_string] instead.
+ ///
/// # Errors
///
/// This function will return an error if `path` does not already exist.
@@ -343,9 +347,12 @@ impl File {
///
/// ```no_run
/// use std::fs::File;
+ /// use std::io::Read;
///
/// fn main() -> std::io::Result<()> {
/// let mut f = File::open("foo.txt")?;
+ /// let mut data = vec![];
+ /// f.read_to_end(&mut data)?;
/// Ok(())
/// }
/// ```
@@ -361,16 +368,20 @@ impl File {
///
/// Depending on the platform, this function may fail if the
/// full directory path does not exist.
- ///
/// See the [`OpenOptions::open`] function for more details.
///
+ /// See also [`std::fs::write()`][self::write] for a simple function to
+ /// create a file with a given data.
+ ///
/// # Examples
///
/// ```no_run
/// use std::fs::File;
+ /// use std::io::Write;
///
/// fn main() -> std::io::Result<()> {
/// let mut f = File::create("foo.txt")?;
+ /// f.write_all(&1234_u32.to_be_bytes())?;
/// Ok(())
/// }
/// ```
@@ -397,9 +408,11 @@ impl File {
/// #![feature(file_create_new)]
///
/// use std::fs::File;
+ /// use std::io::Write;
///
/// fn main() -> std::io::Result<()> {
/// let mut f = File::create_new("foo.txt")?;
+ /// f.write_all("Hello, world!".as_bytes())?;
/// Ok(())
/// }
/// ```
@@ -426,9 +439,11 @@ impl File {
///
/// ```no_run
/// use std::fs::File;
+ /// use std::io::Write;
///
/// fn main() -> std::io::Result<()> {
/// let mut f = File::options().append(true).open("example.log")?;
+ /// writeln!(&mut f, "new line")?;
/// Ok(())
/// }
/// ```
@@ -966,6 +981,9 @@ impl OpenOptions {
/// In order for the file to be created, [`OpenOptions::write`] or
/// [`OpenOptions::append`] access must be used.
///
+ /// See also [`std::fs::write()`][self::write] for a simple function to
+ /// create a file with a given data.
+ ///
/// # Examples
///
/// ```no_run
diff --git a/library/std/src/fs/tests.rs b/library/std/src/fs/tests.rs
index eb582be01..909d9bf40 100644
--- a/library/std/src/fs/tests.rs
+++ b/library/std/src/fs/tests.rs
@@ -12,6 +12,8 @@ use crate::time::{Duration, Instant};
use rand::RngCore;
+#[cfg(target_os = "macos")]
+use crate::ffi::{c_char, c_int};
#[cfg(unix)]
use crate::os::unix::fs::symlink as symlink_dir;
#[cfg(unix)]
@@ -24,8 +26,6 @@ use crate::os::windows::fs::{symlink_dir, symlink_file};
use crate::sys::fs::symlink_junction;
#[cfg(target_os = "macos")]
use crate::sys::weak::weak;
-#[cfg(target_os = "macos")]
-use libc::{c_char, c_int};
macro_rules! check {
($e:expr) => {
@@ -1595,3 +1595,19 @@ fn test_read_dir_infinite_loop() {
// Check for duplicate errors
assert!(dir.filter(|e| e.is_err()).take(2).count() < 2);
}
+
+#[test]
+fn rename_directory() {
+ let tmpdir = tmpdir();
+ let old_path = tmpdir.join("foo/bar/baz");
+ fs::create_dir_all(&old_path).unwrap();
+ let test_file = &old_path.join("temp.txt");
+
+ File::create(test_file).unwrap();
+
+ let new_path = tmpdir.join("quux/blat");
+ fs::create_dir_all(&new_path).unwrap();
+ fs::rename(&old_path, &new_path.join("newdir")).unwrap();
+ assert!(new_path.join("newdir").is_dir());
+ assert!(new_path.join("newdir/temp.txt").exists());
+}
diff --git a/library/std/src/io/error.rs b/library/std/src/io/error.rs
index 3cabf2449..7f07e4fdd 100644
--- a/library/std/src/io/error.rs
+++ b/library/std/src/io/error.rs
@@ -88,12 +88,23 @@ impl From<alloc::ffi::NulError> for Error {
// doesn't accidentally get printed.
#[cfg_attr(test, derive(Debug))]
enum ErrorData<C> {
- Os(i32),
+ Os(RawOsError),
Simple(ErrorKind),
SimpleMessage(&'static SimpleMessage),
Custom(C),
}
+/// The type of raw OS error codes returned by [`Error::raw_os_error`].
+///
+/// This is an [`i32`] on all currently supported platforms, but platforms
+/// added in the future (such as UEFI) may use a different primitive type like
+/// [`usize`]. Use `as`or [`into`] conversions where applicable to ensure maximum
+/// portability.
+///
+/// [`into`]: Into::into
+#[unstable(feature = "raw_os_error_ty", issue = "107792")]
+pub type RawOsError = i32;
+
// `#[repr(align(4))]` is probably redundant, it should have that value or
// higher already. We include it just because repr_bitpacked.rs's encoding
// requires an alignment >= 4 (note that `#[repr(align)]` will not reduce the
@@ -579,7 +590,7 @@ impl Error {
#[must_use]
#[inline]
pub fn last_os_error() -> Error {
- Error::from_raw_os_error(sys::os::errno() as i32)
+ Error::from_raw_os_error(sys::os::errno())
}
/// Creates a new instance of an [`Error`] from a particular OS error code.
@@ -610,7 +621,7 @@ impl Error {
#[stable(feature = "rust1", since = "1.0.0")]
#[must_use]
#[inline]
- pub fn from_raw_os_error(code: i32) -> Error {
+ pub fn from_raw_os_error(code: RawOsError) -> Error {
Error { repr: Repr::new_os(code) }
}
@@ -646,7 +657,7 @@ impl Error {
#[stable(feature = "rust1", since = "1.0.0")]
#[must_use]
#[inline]
- pub fn raw_os_error(&self) -> Option<i32> {
+ pub fn raw_os_error(&self) -> Option<RawOsError> {
match self.repr.data() {
ErrorData::Os(i) => Some(i),
ErrorData::Custom(..) => None,
diff --git a/library/std/src/io/error/repr_bitpacked.rs b/library/std/src/io/error/repr_bitpacked.rs
index 358148405..f94f88bac 100644
--- a/library/std/src/io/error/repr_bitpacked.rs
+++ b/library/std/src/io/error/repr_bitpacked.rs
@@ -102,7 +102,7 @@
//! to use a pointer type to store something that may hold an integer, some of
//! the time.
-use super::{Custom, ErrorData, ErrorKind, SimpleMessage};
+use super::{Custom, ErrorData, ErrorKind, RawOsError, SimpleMessage};
use alloc::boxed::Box;
use core::marker::PhantomData;
use core::mem::{align_of, size_of};
@@ -172,7 +172,7 @@ impl Repr {
}
#[inline]
- pub(super) fn new_os(code: i32) -> Self {
+ pub(super) fn new_os(code: RawOsError) -> Self {
let utagged = ((code as usize) << 32) | TAG_OS;
// Safety: `TAG_OS` is not zero, so the result of the `|` is not 0.
let res = Self(unsafe { NonNull::new_unchecked(ptr::invalid_mut(utagged)) }, PhantomData);
@@ -250,7 +250,7 @@ where
let bits = ptr.as_ptr().addr();
match bits & TAG_MASK {
TAG_OS => {
- let code = ((bits as i64) >> 32) as i32;
+ let code = ((bits as i64) >> 32) as RawOsError;
ErrorData::Os(code)
}
TAG_SIMPLE => {
@@ -374,6 +374,9 @@ static_assert!((TAG_MASK + 1).is_power_of_two());
static_assert!(align_of::<SimpleMessage>() >= TAG_MASK + 1);
static_assert!(align_of::<Custom>() >= TAG_MASK + 1);
+// `RawOsError` must be an alias for `i32`.
+const _: fn(RawOsError) -> i32 = |os| os;
+
static_assert!(@usize_eq: TAG_MASK & TAG_SIMPLE_MESSAGE, TAG_SIMPLE_MESSAGE);
static_assert!(@usize_eq: TAG_MASK & TAG_CUSTOM, TAG_CUSTOM);
static_assert!(@usize_eq: TAG_MASK & TAG_OS, TAG_OS);
diff --git a/library/std/src/io/error/repr_unpacked.rs b/library/std/src/io/error/repr_unpacked.rs
index d6ad55b99..093fde337 100644
--- a/library/std/src/io/error/repr_unpacked.rs
+++ b/library/std/src/io/error/repr_unpacked.rs
@@ -2,7 +2,7 @@
//! non-64bit targets, where the packed 64 bit representation wouldn't work, and
//! would have no benefit.
-use super::{Custom, ErrorData, ErrorKind, SimpleMessage};
+use super::{Custom, ErrorData, ErrorKind, RawOsError, SimpleMessage};
use alloc::boxed::Box;
type Inner = ErrorData<Box<Custom>>;
@@ -18,7 +18,7 @@ impl Repr {
Self(Inner::Custom(b))
}
#[inline]
- pub(super) fn new_os(code: i32) -> Self {
+ pub(super) fn new_os(code: RawOsError) -> Self {
Self(Inner::Os(code))
}
#[inline]
diff --git a/library/std/src/io/error/tests.rs b/library/std/src/io/error/tests.rs
index 16c634e9a..36d52aef0 100644
--- a/library/std/src/io/error/tests.rs
+++ b/library/std/src/io/error/tests.rs
@@ -71,7 +71,7 @@ fn test_const() {
#[test]
fn test_os_packing() {
- for code in -20i32..20i32 {
+ for code in -20..20 {
let e = Error::from_raw_os_error(code);
assert_eq!(e.raw_os_error(), Some(code));
assert_matches!(
@@ -190,5 +190,5 @@ fn test_std_io_error_downcast() {
let io_error = io_error.downcast::<E>().unwrap_err();
assert_eq!(SIMPLE_MESSAGE.kind, io_error.kind());
- assert_eq!(SIMPLE_MESSAGE.message, &*format!("{io_error}"));
+ assert_eq!(SIMPLE_MESSAGE.message, format!("{io_error}"));
}
diff --git a/library/std/src/io/mod.rs b/library/std/src/io/mod.rs
index de528e853..b2b6d8613 100644
--- a/library/std/src/io/mod.rs
+++ b/library/std/src/io/mod.rs
@@ -262,6 +262,8 @@ use crate::sys_common::memchr;
#[stable(feature = "bufwriter_into_parts", since = "1.56.0")]
pub use self::buffered::WriterPanicked;
+#[unstable(feature = "raw_os_error_ty", issue = "107792")]
+pub use self::error::RawOsError;
pub(crate) use self::stdio::attempt_print_to_stderr;
#[unstable(feature = "internal_output_capture", issue = "none")]
#[doc(no_inline, hidden)]
diff --git a/library/std/src/keyword_docs.rs b/library/std/src/keyword_docs.rs
index e35145c4a..203c490fa 100644
--- a/library/std/src/keyword_docs.rs
+++ b/library/std/src/keyword_docs.rs
@@ -1568,7 +1568,7 @@ mod static_keyword {}
///
/// # Style conventions
///
-/// Structs are always written in CamelCase, with few exceptions. While the trailing comma on a
+/// Structs are always written in UpperCamelCase, with few exceptions. While the trailing comma on a
/// struct's list of fields can be omitted, it's usually kept for convenience in adding and
/// removing fields down the line.
///
diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs
index a7e13f5b8..b62f3ad29 100644
--- a/library/std/src/lib.rs
+++ b/library/std/src/lib.rs
@@ -232,13 +232,13 @@
all(target_vendor = "fortanix", target_env = "sgx"),
feature(slice_index_methods, coerce_unsized, sgx_platform)
)]
+#![cfg_attr(windows, feature(round_char_boundary))]
//
// Language features:
#![feature(alloc_error_handler)]
#![feature(allocator_internals)]
#![feature(allow_internal_unsafe)]
#![feature(allow_internal_unstable)]
-#![feature(box_syntax)]
#![feature(c_unwind)]
#![feature(cfg_target_thread_local)]
#![feature(concat_idents)]
@@ -274,13 +274,9 @@
#![feature(utf8_chunks)]
//
// Library features (core):
-#![feature(array_error_internals)]
#![feature(atomic_mut_ptr)]
-#![feature(char_error_internals)]
#![feature(char_internals)]
#![feature(core_intrinsics)]
-#![feature(cstr_from_bytes_until_nul)]
-#![feature(cstr_internals)]
#![feature(duration_constants)]
#![feature(error_generic_member_access)]
#![feature(error_in_core)]
@@ -292,7 +288,8 @@
#![feature(float_next_up_down)]
#![feature(hasher_prefixfree_extras)]
#![feature(hashmap_internals)]
-#![feature(int_error_internals)]
+#![feature(ip)]
+#![feature(ip_in_core)]
#![feature(is_some_and)]
#![feature(maybe_uninit_slice)]
#![feature(maybe_uninit_write_slice)]
@@ -359,7 +356,6 @@
#![feature(const_ip)]
#![feature(const_ipv4)]
#![feature(const_ipv6)]
-#![feature(const_socketaddr)]
#![feature(thread_local_internals)]
//
#![default_lib_allocator]
diff --git a/library/std/src/net/ip_addr.rs b/library/std/src/net/ip_addr.rs
index 07f08c1b5..e167fbd1b 100644
--- a/library/std/src/net/ip_addr.rs
+++ b/library/std/src/net/ip_addr.rs
@@ -2,2101 +2,40 @@
#[cfg(all(test, not(target_os = "emscripten")))]
mod tests;
-use crate::cmp::Ordering;
-use crate::fmt::{self, Write};
-use crate::mem::transmute;
use crate::sys::net::netc as c;
use crate::sys_common::{FromInner, IntoInner};
-use super::display_buffer::DisplayBuffer;
-
-/// An IP address, either IPv4 or IPv6.
-///
-/// This enum can contain either an [`Ipv4Addr`] or an [`Ipv6Addr`], see their
-/// respective documentation for more details.
-///
-/// # Examples
-///
-/// ```
-/// use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
-///
-/// let localhost_v4 = IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1));
-/// let localhost_v6 = IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1));
-///
-/// assert_eq!("127.0.0.1".parse(), Ok(localhost_v4));
-/// assert_eq!("::1".parse(), Ok(localhost_v6));
-///
-/// assert_eq!(localhost_v4.is_ipv6(), false);
-/// assert_eq!(localhost_v4.is_ipv4(), true);
-/// ```
-#[cfg_attr(not(test), rustc_diagnostic_item = "IpAddr")]
#[stable(feature = "ip_addr", since = "1.7.0")]
-#[derive(Copy, Clone, Eq, PartialEq, Hash, PartialOrd, Ord)]
-pub enum IpAddr {
- /// An IPv4 address.
- #[stable(feature = "ip_addr", since = "1.7.0")]
- V4(#[stable(feature = "ip_addr", since = "1.7.0")] Ipv4Addr),
- /// An IPv6 address.
- #[stable(feature = "ip_addr", since = "1.7.0")]
- V6(#[stable(feature = "ip_addr", since = "1.7.0")] Ipv6Addr),
-}
+pub use core::net::IpAddr;
-/// An IPv4 address.
-///
-/// IPv4 addresses are defined as 32-bit integers in [IETF RFC 791].
-/// They are usually represented as four octets.
-///
-/// See [`IpAddr`] for a type encompassing both IPv4 and IPv6 addresses.
-///
-/// [IETF RFC 791]: https://tools.ietf.org/html/rfc791
-///
-/// # Textual representation
-///
-/// `Ipv4Addr` provides a [`FromStr`] implementation. The four octets are in decimal
-/// notation, divided by `.` (this is called "dot-decimal notation").
-/// Notably, octal numbers (which are indicated with a leading `0`) and hexadecimal numbers (which
-/// are indicated with a leading `0x`) are not allowed per [IETF RFC 6943].
-///
-/// [IETF RFC 6943]: https://tools.ietf.org/html/rfc6943#section-3.1.1
-/// [`FromStr`]: crate::str::FromStr
-///
-/// # Examples
-///
-/// ```
-/// use std::net::Ipv4Addr;
-///
-/// let localhost = Ipv4Addr::new(127, 0, 0, 1);
-/// assert_eq!("127.0.0.1".parse(), Ok(localhost));
-/// assert_eq!(localhost.is_loopback(), true);
-/// assert!("012.004.002.000".parse::<Ipv4Addr>().is_err()); // all octets are in octal
-/// assert!("0000000.0.0.0".parse::<Ipv4Addr>().is_err()); // first octet is a zero in octal
-/// assert!("0xcb.0x0.0x71.0x00".parse::<Ipv4Addr>().is_err()); // all octets are in hex
-/// ```
-#[derive(Copy, Clone, PartialEq, Eq, Hash)]
#[stable(feature = "rust1", since = "1.0.0")]
-pub struct Ipv4Addr {
- octets: [u8; 4],
-}
+pub use core::net::{Ipv4Addr, Ipv6Addr};
-/// An IPv6 address.
-///
-/// IPv6 addresses are defined as 128-bit integers in [IETF RFC 4291].
-/// They are usually represented as eight 16-bit segments.
-///
-/// [IETF RFC 4291]: https://tools.ietf.org/html/rfc4291
-///
-/// # Embedding IPv4 Addresses
-///
-/// See [`IpAddr`] for a type encompassing both IPv4 and IPv6 addresses.
-///
-/// To assist in the transition from IPv4 to IPv6 two types of IPv6 addresses that embed an IPv4 address were defined:
-/// IPv4-compatible and IPv4-mapped addresses. Of these IPv4-compatible addresses have been officially deprecated.
-///
-/// Both types of addresses are not assigned any special meaning by this implementation,
-/// other than what the relevant standards prescribe. This means that an address like `::ffff:127.0.0.1`,
-/// while representing an IPv4 loopback address, is not itself an IPv6 loopback address; only `::1` is.
-/// To handle these so called "IPv4-in-IPv6" addresses, they have to first be converted to their canonical IPv4 address.
-///
-/// ### IPv4-Compatible IPv6 Addresses
-///
-/// IPv4-compatible IPv6 addresses are defined in [IETF RFC 4291 Section 2.5.5.1], and have been officially deprecated.
-/// The RFC describes the format of an "IPv4-Compatible IPv6 address" as follows:
-///
-/// ```text
-/// | 80 bits | 16 | 32 bits |
-/// +--------------------------------------+--------------------------+
-/// |0000..............................0000|0000| IPv4 address |
-/// +--------------------------------------+----+---------------------+
-/// ```
-/// So `::a.b.c.d` would be an IPv4-compatible IPv6 address representing the IPv4 address `a.b.c.d`.
-///
-/// To convert from an IPv4 address to an IPv4-compatible IPv6 address, use [`Ipv4Addr::to_ipv6_compatible`].
-/// Use [`Ipv6Addr::to_ipv4`] to convert an IPv4-compatible IPv6 address to the canonical IPv4 address.
-///
-/// [IETF RFC 4291 Section 2.5.5.1]: https://datatracker.ietf.org/doc/html/rfc4291#section-2.5.5.1
-///
-/// ### IPv4-Mapped IPv6 Addresses
-///
-/// IPv4-mapped IPv6 addresses are defined in [IETF RFC 4291 Section 2.5.5.2].
-/// The RFC describes the format of an "IPv4-Mapped IPv6 address" as follows:
-///
-/// ```text
-/// | 80 bits | 16 | 32 bits |
-/// +--------------------------------------+--------------------------+
-/// |0000..............................0000|FFFF| IPv4 address |
-/// +--------------------------------------+----+---------------------+
-/// ```
-/// So `::ffff:a.b.c.d` would be an IPv4-mapped IPv6 address representing the IPv4 address `a.b.c.d`.
-///
-/// To convert from an IPv4 address to an IPv4-mapped IPv6 address, use [`Ipv4Addr::to_ipv6_mapped`].
-/// Use [`Ipv6Addr::to_ipv4`] to convert an IPv4-mapped IPv6 address to the canonical IPv4 address.
-/// Note that this will also convert the IPv6 loopback address `::1` to `0.0.0.1`. Use
-/// [`Ipv6Addr::to_ipv4_mapped`] to avoid this.
-///
-/// [IETF RFC 4291 Section 2.5.5.2]: https://datatracker.ietf.org/doc/html/rfc4291#section-2.5.5.2
-///
-/// # Textual representation
-///
-/// `Ipv6Addr` provides a [`FromStr`] implementation. There are many ways to represent
-/// an IPv6 address in text, but in general, each segments is written in hexadecimal
-/// notation, and segments are separated by `:`. For more information, see
-/// [IETF RFC 5952].
-///
-/// [`FromStr`]: crate::str::FromStr
-/// [IETF RFC 5952]: https://tools.ietf.org/html/rfc5952
-///
-/// # Examples
-///
-/// ```
-/// use std::net::Ipv6Addr;
-///
-/// let localhost = Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1);
-/// assert_eq!("::1".parse(), Ok(localhost));
-/// assert_eq!(localhost.is_loopback(), true);
-/// ```
-#[derive(Copy, Clone, PartialEq, Eq, Hash)]
-#[stable(feature = "rust1", since = "1.0.0")]
-pub struct Ipv6Addr {
- octets: [u8; 16],
-}
-
-/// Scope of an [IPv6 multicast address] as defined in [IETF RFC 7346 section 2].
-///
-/// # Stability Guarantees
-///
-/// Not all possible values for a multicast scope have been assigned.
-/// Future RFCs may introduce new scopes, which will be added as variants to this enum;
-/// because of this the enum is marked as `#[non_exhaustive]`.
-///
-/// # Examples
-/// ```
-/// #![feature(ip)]
-///
-/// use std::net::Ipv6Addr;
-/// use std::net::Ipv6MulticastScope::*;
-///
-/// // An IPv6 multicast address with global scope (`ff0e::`).
-/// let address = Ipv6Addr::new(0xff0e, 0, 0, 0, 0, 0, 0, 0);
-///
-/// // Will print "Global scope".
-/// match address.multicast_scope() {
-/// Some(InterfaceLocal) => println!("Interface-Local scope"),
-/// Some(LinkLocal) => println!("Link-Local scope"),
-/// Some(RealmLocal) => println!("Realm-Local scope"),
-/// Some(AdminLocal) => println!("Admin-Local scope"),
-/// Some(SiteLocal) => println!("Site-Local scope"),
-/// Some(OrganizationLocal) => println!("Organization-Local scope"),
-/// Some(Global) => println!("Global scope"),
-/// Some(_) => println!("Unknown scope"),
-/// None => println!("Not a multicast address!")
-/// }
-///
-/// ```
-///
-/// [IPv6 multicast address]: Ipv6Addr
-/// [IETF RFC 7346 section 2]: https://tools.ietf.org/html/rfc7346#section-2
-#[derive(Copy, PartialEq, Eq, Clone, Hash, Debug)]
#[unstable(feature = "ip", issue = "27709")]
-#[non_exhaustive]
-pub enum Ipv6MulticastScope {
- /// Interface-Local scope.
- InterfaceLocal,
- /// Link-Local scope.
- LinkLocal,
- /// Realm-Local scope.
- RealmLocal,
- /// Admin-Local scope.
- AdminLocal,
- /// Site-Local scope.
- SiteLocal,
- /// Organization-Local scope.
- OrganizationLocal,
- /// Global scope.
- Global,
-}
-
-impl IpAddr {
- /// Returns [`true`] for the special 'unspecified' address.
- ///
- /// See the documentation for [`Ipv4Addr::is_unspecified()`] and
- /// [`Ipv6Addr::is_unspecified()`] for more details.
- ///
- /// # Examples
- ///
- /// ```
- /// use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
- ///
- /// assert_eq!(IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0)).is_unspecified(), true);
- /// assert_eq!(IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0)).is_unspecified(), true);
- /// ```
- #[rustc_const_stable(feature = "const_ip_50", since = "1.50.0")]
- #[stable(feature = "ip_shared", since = "1.12.0")]
- #[must_use]
- #[inline]
- pub const fn is_unspecified(&self) -> bool {
- match self {
- IpAddr::V4(ip) => ip.is_unspecified(),
- IpAddr::V6(ip) => ip.is_unspecified(),
- }
- }
-
- /// Returns [`true`] if this is a loopback address.
- ///
- /// See the documentation for [`Ipv4Addr::is_loopback()`] and
- /// [`Ipv6Addr::is_loopback()`] for more details.
- ///
- /// # Examples
- ///
- /// ```
- /// use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
- ///
- /// assert_eq!(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)).is_loopback(), true);
- /// assert_eq!(IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0x1)).is_loopback(), true);
- /// ```
- #[rustc_const_stable(feature = "const_ip_50", since = "1.50.0")]
- #[stable(feature = "ip_shared", since = "1.12.0")]
- #[must_use]
- #[inline]
- pub const fn is_loopback(&self) -> bool {
- match self {
- IpAddr::V4(ip) => ip.is_loopback(),
- IpAddr::V6(ip) => ip.is_loopback(),
- }
- }
-
- /// Returns [`true`] if the address appears to be globally routable.
- ///
- /// See the documentation for [`Ipv4Addr::is_global()`] and
- /// [`Ipv6Addr::is_global()`] for more details.
- ///
- /// # Examples
- ///
- /// ```
- /// #![feature(ip)]
- ///
- /// use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
- ///
- /// assert_eq!(IpAddr::V4(Ipv4Addr::new(80, 9, 12, 3)).is_global(), true);
- /// assert_eq!(IpAddr::V6(Ipv6Addr::new(0, 0, 0x1c9, 0, 0, 0xafc8, 0, 0x1)).is_global(), true);
- /// ```
- #[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 {
- IpAddr::V4(ip) => ip.is_global(),
- IpAddr::V6(ip) => ip.is_global(),
- }
- }
-
- /// Returns [`true`] if this is a multicast address.
- ///
- /// See the documentation for [`Ipv4Addr::is_multicast()`] and
- /// [`Ipv6Addr::is_multicast()`] for more details.
- ///
- /// # Examples
- ///
- /// ```
- /// use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
- ///
- /// assert_eq!(IpAddr::V4(Ipv4Addr::new(224, 254, 0, 0)).is_multicast(), true);
- /// assert_eq!(IpAddr::V6(Ipv6Addr::new(0xff00, 0, 0, 0, 0, 0, 0, 0)).is_multicast(), true);
- /// ```
- #[rustc_const_stable(feature = "const_ip_50", since = "1.50.0")]
- #[stable(feature = "ip_shared", since = "1.12.0")]
- #[must_use]
- #[inline]
- pub const fn is_multicast(&self) -> bool {
- match self {
- IpAddr::V4(ip) => ip.is_multicast(),
- IpAddr::V6(ip) => ip.is_multicast(),
- }
- }
-
- /// Returns [`true`] if this address is in a range designated for documentation.
- ///
- /// See the documentation for [`Ipv4Addr::is_documentation()`] and
- /// [`Ipv6Addr::is_documentation()`] for more details.
- ///
- /// # Examples
- ///
- /// ```
- /// #![feature(ip)]
- ///
- /// use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
- ///
- /// assert_eq!(IpAddr::V4(Ipv4Addr::new(203, 0, 113, 6)).is_documentation(), true);
- /// assert_eq!(
- /// IpAddr::V6(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0)).is_documentation(),
- /// true
- /// );
- /// ```
- #[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 {
- IpAddr::V4(ip) => ip.is_documentation(),
- IpAddr::V6(ip) => ip.is_documentation(),
- }
- }
-
- /// 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.
- ///
- /// [`IPv4` address]: IpAddr::V4
- ///
- /// # Examples
- ///
- /// ```
- /// use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
- ///
- /// assert_eq!(IpAddr::V4(Ipv4Addr::new(203, 0, 113, 6)).is_ipv4(), true);
- /// assert_eq!(IpAddr::V6(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0)).is_ipv4(), false);
- /// ```
- #[rustc_const_stable(feature = "const_ip_50", 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(_))
- }
-
- /// Returns [`true`] if this address is an [`IPv6` address], and [`false`]
- /// otherwise.
- ///
- /// [`IPv6` address]: IpAddr::V6
- ///
- /// # Examples
- ///
- /// ```
- /// use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
- ///
- /// assert_eq!(IpAddr::V4(Ipv4Addr::new(203, 0, 113, 6)).is_ipv6(), false);
- /// assert_eq!(IpAddr::V6(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0)).is_ipv6(), true);
- /// ```
- #[rustc_const_stable(feature = "const_ip_50", 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(_))
- }
-
- /// Converts this address to an `IpAddr::V4` if it is an IPv4-mapped IPv6 addresses, otherwise it
- /// return `self` as-is.
- ///
- /// # Examples
- ///
- /// ```
- /// #![feature(ip)]
- /// use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
- ///
- /// assert_eq!(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)).to_canonical().is_loopback(), true);
- /// assert_eq!(IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0x7f00, 0x1)).is_loopback(), false);
- /// 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 {
- match self {
- &v4 @ IpAddr::V4(_) => v4,
- IpAddr::V6(v6) => v6.to_canonical(),
- }
- }
-}
-
-impl Ipv4Addr {
- /// Creates a new IPv4 address from four eight-bit octets.
- ///
- /// The result will represent the IP address `a`.`b`.`c`.`d`.
- ///
- /// # Examples
- ///
- /// ```
- /// use std::net::Ipv4Addr;
- ///
- /// let addr = Ipv4Addr::new(127, 0, 0, 1);
- /// ```
- #[rustc_const_stable(feature = "const_ip_32", 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 {
- Ipv4Addr { octets: [a, b, c, d] }
- }
-
- /// An IPv4 address with the address pointing to localhost: `127.0.0.1`
- ///
- /// # Examples
- ///
- /// ```
- /// use std::net::Ipv4Addr;
- ///
- /// let addr = Ipv4Addr::LOCALHOST;
- /// assert_eq!(addr, Ipv4Addr::new(127, 0, 0, 1));
- /// ```
- #[stable(feature = "ip_constructors", since = "1.30.0")]
- pub const LOCALHOST: Self = Ipv4Addr::new(127, 0, 0, 1);
-
- /// An IPv4 address representing an unspecified address: `0.0.0.0`
- ///
- /// This corresponds to the constant `INADDR_ANY` in other languages.
- ///
- /// # Examples
- ///
- /// ```
- /// use std::net::Ipv4Addr;
- ///
- /// let addr = Ipv4Addr::UNSPECIFIED;
- /// assert_eq!(addr, Ipv4Addr::new(0, 0, 0, 0));
- /// ```
- #[doc(alias = "INADDR_ANY")]
- #[stable(feature = "ip_constructors", since = "1.30.0")]
- pub const UNSPECIFIED: Self = Ipv4Addr::new(0, 0, 0, 0);
-
- /// An IPv4 address representing the broadcast address: `255.255.255.255`
- ///
- /// # Examples
- ///
- /// ```
- /// use std::net::Ipv4Addr;
- ///
- /// let addr = Ipv4Addr::BROADCAST;
- /// assert_eq!(addr, Ipv4Addr::new(255, 255, 255, 255));
- /// ```
- #[stable(feature = "ip_constructors", since = "1.30.0")]
- pub const BROADCAST: Self = Ipv4Addr::new(255, 255, 255, 255);
-
- /// Returns the four eight-bit integers that make up this address.
- ///
- /// # Examples
- ///
- /// ```
- /// use std::net::Ipv4Addr;
- ///
- /// let addr = Ipv4Addr::new(127, 0, 0, 1);
- /// assert_eq!(addr.octets(), [127, 0, 0, 1]);
- /// ```
- #[rustc_const_stable(feature = "const_ip_50", since = "1.50.0")]
- #[stable(feature = "rust1", since = "1.0.0")]
- #[must_use]
- #[inline]
- pub const fn octets(&self) -> [u8; 4] {
- self.octets
- }
-
- /// Returns [`true`] for the special 'unspecified' address (`0.0.0.0`).
- ///
- /// This property is defined in _UNIX Network Programming, Second Edition_,
- /// W. Richard Stevens, p. 891; see also [ip7].
- ///
- /// [ip7]: https://man7.org/linux/man-pages/man7/ip.7.html
- ///
- /// # Examples
- ///
- /// ```
- /// use std::net::Ipv4Addr;
- ///
- /// assert_eq!(Ipv4Addr::new(0, 0, 0, 0).is_unspecified(), true);
- /// assert_eq!(Ipv4Addr::new(45, 22, 13, 197).is_unspecified(), false);
- /// ```
- #[rustc_const_stable(feature = "const_ip_32", since = "1.32.0")]
- #[stable(feature = "ip_shared", since = "1.12.0")]
- #[must_use]
- #[inline]
- pub const fn is_unspecified(&self) -> bool {
- u32::from_be_bytes(self.octets) == 0
- }
-
- /// Returns [`true`] if this is a loopback address (`127.0.0.0/8`).
- ///
- /// This property is defined by [IETF RFC 1122].
- ///
- /// [IETF RFC 1122]: https://tools.ietf.org/html/rfc1122
- ///
- /// # Examples
- ///
- /// ```
- /// use std::net::Ipv4Addr;
- ///
- /// assert_eq!(Ipv4Addr::new(127, 0, 0, 1).is_loopback(), true);
- /// assert_eq!(Ipv4Addr::new(45, 22, 13, 197).is_loopback(), false);
- /// ```
- #[rustc_const_stable(feature = "const_ip_50", 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
- }
-
- /// Returns [`true`] if this is a private address.
- ///
- /// The private address ranges are defined in [IETF RFC 1918] and include:
- ///
- /// - `10.0.0.0/8`
- /// - `172.16.0.0/12`
- /// - `192.168.0.0/16`
- ///
- /// [IETF RFC 1918]: https://tools.ietf.org/html/rfc1918
- ///
- /// # Examples
- ///
- /// ```
- /// use std::net::Ipv4Addr;
- ///
- /// assert_eq!(Ipv4Addr::new(10, 0, 0, 1).is_private(), true);
- /// assert_eq!(Ipv4Addr::new(10, 10, 10, 10).is_private(), true);
- /// assert_eq!(Ipv4Addr::new(172, 16, 10, 10).is_private(), true);
- /// assert_eq!(Ipv4Addr::new(172, 29, 45, 14).is_private(), true);
- /// assert_eq!(Ipv4Addr::new(172, 32, 0, 2).is_private(), false);
- /// assert_eq!(Ipv4Addr::new(192, 168, 0, 2).is_private(), true);
- /// assert_eq!(Ipv4Addr::new(192, 169, 0, 2).is_private(), false);
- /// ```
- #[rustc_const_stable(feature = "const_ip_50", 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() {
- [10, ..] => true,
- [172, b, ..] if b >= 16 && b <= 31 => true,
- [192, 168, ..] => true,
- _ => false,
- }
- }
-
- /// Returns [`true`] if the address is link-local (`169.254.0.0/16`).
- ///
- /// This property is defined by [IETF RFC 3927].
- ///
- /// [IETF RFC 3927]: https://tools.ietf.org/html/rfc3927
- ///
- /// # Examples
- ///
- /// ```
- /// use std::net::Ipv4Addr;
- ///
- /// assert_eq!(Ipv4Addr::new(169, 254, 0, 0).is_link_local(), true);
- /// assert_eq!(Ipv4Addr::new(169, 254, 10, 65).is_link_local(), true);
- /// assert_eq!(Ipv4Addr::new(16, 89, 10, 65).is_link_local(), false);
- /// ```
- #[rustc_const_stable(feature = "const_ip_50", 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, ..])
- }
-
- /// Returns [`true`] if the address appears to be globally reachable
- /// as specified by the [IANA IPv4 Special-Purpose Address Registry].
- /// Whether or not an address is practically reachable will depend on your network configuration.
- ///
- /// Most IPv4 addresses are globally reachable;
- /// unless they are specifically defined as *not* globally reachable.
- ///
- /// Non-exhaustive list of notable addresses that are not globally reachable:
- ///
- /// - The [unspecified address] ([`is_unspecified`](Ipv4Addr::is_unspecified))
- /// - Addresses reserved for private use ([`is_private`](Ipv4Addr::is_private))
- /// - Addresses in the shared address space ([`is_shared`](Ipv4Addr::is_shared))
- /// - Loopback addresses ([`is_loopback`](Ipv4Addr::is_loopback))
- /// - Link-local addresses ([`is_link_local`](Ipv4Addr::is_link_local))
- /// - Addresses reserved for documentation ([`is_documentation`](Ipv4Addr::is_documentation))
- /// - Addresses reserved for benchmarking ([`is_benchmarking`](Ipv4Addr::is_benchmarking))
- /// - Reserved addresses ([`is_reserved`](Ipv4Addr::is_reserved))
- /// - The [broadcast address] ([`is_broadcast`](Ipv4Addr::is_broadcast))
- ///
- /// For the complete overview of which addresses are globally reachable, see the table at the [IANA IPv4 Special-Purpose Address Registry].
- ///
- /// [IANA IPv4 Special-Purpose Address Registry]: https://www.iana.org/assignments/iana-ipv4-special-registry/iana-ipv4-special-registry.xhtml
- /// [unspecified address]: Ipv4Addr::UNSPECIFIED
- /// [broadcast address]: Ipv4Addr::BROADCAST
-
- ///
- /// # Examples
- ///
- /// ```
- /// #![feature(ip)]
- ///
- /// use std::net::Ipv4Addr;
- ///
- /// // Most IPv4 addresses are globally reachable:
- /// assert_eq!(Ipv4Addr::new(80, 9, 12, 3).is_global(), true);
- ///
- /// // However some addresses have been assigned a special meaning
- /// // that makes them not globally reachable. Some examples are:
- ///
- /// // The unspecified address (`0.0.0.0`)
- /// assert_eq!(Ipv4Addr::UNSPECIFIED.is_global(), false);
- ///
- /// // Addresses reserved for private use (`10.0.0.0/8`, `172.16.0.0/12`, 192.168.0.0/16)
- /// assert_eq!(Ipv4Addr::new(10, 254, 0, 0).is_global(), false);
- /// assert_eq!(Ipv4Addr::new(192, 168, 10, 65).is_global(), false);
- /// assert_eq!(Ipv4Addr::new(172, 16, 10, 65).is_global(), false);
- ///
- /// // Addresses in the shared address space (`100.64.0.0/10`)
- /// assert_eq!(Ipv4Addr::new(100, 100, 0, 0).is_global(), false);
- ///
- /// // The loopback addresses (`127.0.0.0/8`)
- /// assert_eq!(Ipv4Addr::LOCALHOST.is_global(), false);
- ///
- /// // Link-local addresses (`169.254.0.0/16`)
- /// assert_eq!(Ipv4Addr::new(169, 254, 45, 1).is_global(), false);
- ///
- /// // Addresses reserved for documentation (`192.0.2.0/24`, `198.51.100.0/24`, `203.0.113.0/24`)
- /// assert_eq!(Ipv4Addr::new(192, 0, 2, 255).is_global(), false);
- /// assert_eq!(Ipv4Addr::new(198, 51, 100, 65).is_global(), false);
- /// assert_eq!(Ipv4Addr::new(203, 0, 113, 6).is_global(), false);
- ///
- /// // Addresses reserved for benchmarking (`198.18.0.0/15`)
- /// assert_eq!(Ipv4Addr::new(198, 18, 0, 0).is_global(), false);
- ///
- /// // Reserved addresses (`240.0.0.0/4`)
- /// assert_eq!(Ipv4Addr::new(250, 10, 20, 30).is_global(), false);
- ///
- /// // The broadcast address (`255.255.255.255`)
- /// assert_eq!(Ipv4Addr::BROADCAST.is_global(), false);
- ///
- /// // For a complete overview see the IANA IPv4 Special-Purpose Address Registry.
- /// ```
- #[rustc_const_unstable(feature = "const_ipv4", issue = "76205")]
- #[unstable(feature = "ip", issue = "27709")]
- #[must_use]
- #[inline]
- pub const fn is_global(&self) -> bool {
- !(self.octets()[0] == 0 // "This network"
- || self.is_private()
- || self.is_shared()
- || self.is_loopback()
- || self.is_link_local()
- // addresses reserved for future protocols (`192.0.0.0/24`)
- ||(self.octets()[0] == 192 && self.octets()[1] == 0 && self.octets()[2] == 0)
- || self.is_documentation()
- || self.is_benchmarking()
- || self.is_reserved()
- || self.is_broadcast())
- }
-
- /// Returns [`true`] if this address is part of the Shared Address Space defined in
- /// [IETF RFC 6598] (`100.64.0.0/10`).
- ///
- /// [IETF RFC 6598]: https://tools.ietf.org/html/rfc6598
- ///
- /// # Examples
- ///
- /// ```
- /// #![feature(ip)]
- /// use std::net::Ipv4Addr;
- ///
- /// assert_eq!(Ipv4Addr::new(100, 64, 0, 0).is_shared(), true);
- /// assert_eq!(Ipv4Addr::new(100, 127, 255, 255).is_shared(), true);
- /// assert_eq!(Ipv4Addr::new(100, 128, 0, 0).is_shared(), false);
- /// ```
- #[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)
- }
-
- /// Returns [`true`] if this address part of the `198.18.0.0/15` range, which is reserved for
- /// network devices benchmarking. This range is defined in [IETF RFC 2544] as `192.18.0.0`
- /// through `198.19.255.255` but [errata 423] corrects it to `198.18.0.0/15`.
- ///
- /// [IETF RFC 2544]: https://tools.ietf.org/html/rfc2544
- /// [errata 423]: https://www.rfc-editor.org/errata/eid423
- ///
- /// # Examples
- ///
- /// ```
- /// #![feature(ip)]
- /// use std::net::Ipv4Addr;
- ///
- /// assert_eq!(Ipv4Addr::new(198, 17, 255, 255).is_benchmarking(), false);
- /// assert_eq!(Ipv4Addr::new(198, 18, 0, 0).is_benchmarking(), true);
- /// assert_eq!(Ipv4Addr::new(198, 19, 255, 255).is_benchmarking(), true);
- /// assert_eq!(Ipv4Addr::new(198, 20, 0, 0).is_benchmarking(), false);
- /// ```
- #[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
- }
-
- /// Returns [`true`] if this address is reserved by IANA for future use. [IETF RFC 1112]
- /// defines the block of reserved addresses as `240.0.0.0/4`. This range normally includes the
- /// broadcast address `255.255.255.255`, but this implementation explicitly excludes it, since
- /// it is obviously not reserved for future use.
- ///
- /// [IETF RFC 1112]: https://tools.ietf.org/html/rfc1112
- ///
- /// # Warning
- ///
- /// As IANA assigns new addresses, this method will be
- /// updated. This may result in non-reserved addresses being
- /// treated as reserved in code that relies on an outdated version
- /// of this method.
- ///
- /// # Examples
- ///
- /// ```
- /// #![feature(ip)]
- /// use std::net::Ipv4Addr;
- ///
- /// assert_eq!(Ipv4Addr::new(240, 0, 0, 0).is_reserved(), true);
- /// assert_eq!(Ipv4Addr::new(255, 255, 255, 254).is_reserved(), true);
- ///
- /// assert_eq!(Ipv4Addr::new(239, 255, 255, 255).is_reserved(), false);
- /// // The broadcast address is not considered as reserved for future use by this implementation
- /// assert_eq!(Ipv4Addr::new(255, 255, 255, 255).is_reserved(), false);
- /// ```
- #[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()
- }
-
- /// Returns [`true`] if this is a multicast address (`224.0.0.0/4`).
- ///
- /// Multicast addresses have a most significant octet between `224` and `239`,
- /// and is defined by [IETF RFC 5771].
- ///
- /// [IETF RFC 5771]: https://tools.ietf.org/html/rfc5771
- ///
- /// # Examples
- ///
- /// ```
- /// use std::net::Ipv4Addr;
- ///
- /// assert_eq!(Ipv4Addr::new(224, 254, 0, 0).is_multicast(), true);
- /// assert_eq!(Ipv4Addr::new(236, 168, 10, 65).is_multicast(), true);
- /// assert_eq!(Ipv4Addr::new(172, 16, 10, 65).is_multicast(), false);
- /// ```
- #[rustc_const_stable(feature = "const_ip_50", 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
- }
-
- /// Returns [`true`] if this is a broadcast address (`255.255.255.255`).
- ///
- /// A broadcast address has all octets set to `255` as defined in [IETF RFC 919].
- ///
- /// [IETF RFC 919]: https://tools.ietf.org/html/rfc919
- ///
- /// # Examples
- ///
- /// ```
- /// use std::net::Ipv4Addr;
- ///
- /// assert_eq!(Ipv4Addr::new(255, 255, 255, 255).is_broadcast(), true);
- /// assert_eq!(Ipv4Addr::new(236, 168, 10, 65).is_broadcast(), false);
- /// ```
- #[rustc_const_stable(feature = "const_ip_50", 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())
- }
-
- /// Returns [`true`] if this address is in a range designated for documentation.
- ///
- /// This is defined in [IETF RFC 5737]:
- ///
- /// - `192.0.2.0/24` (TEST-NET-1)
- /// - `198.51.100.0/24` (TEST-NET-2)
- /// - `203.0.113.0/24` (TEST-NET-3)
- ///
- /// [IETF RFC 5737]: https://tools.ietf.org/html/rfc5737
- ///
- /// # Examples
- ///
- /// ```
- /// use std::net::Ipv4Addr;
- ///
- /// assert_eq!(Ipv4Addr::new(192, 0, 2, 255).is_documentation(), true);
- /// assert_eq!(Ipv4Addr::new(198, 51, 100, 65).is_documentation(), true);
- /// assert_eq!(Ipv4Addr::new(203, 0, 113, 6).is_documentation(), true);
- /// assert_eq!(Ipv4Addr::new(193, 34, 17, 19).is_documentation(), false);
- /// ```
- #[rustc_const_stable(feature = "const_ip_50", since = "1.50.0")]
- #[stable(since = "1.7.0", feature = "ip_17")]
- #[must_use]
- #[inline]
- pub const fn is_documentation(&self) -> bool {
- matches!(self.octets(), [192, 0, 2, _] | [198, 51, 100, _] | [203, 0, 113, _])
- }
-
- /// Converts this address to an [IPv4-compatible] [`IPv6` address].
- ///
- /// `a.b.c.d` becomes `::a.b.c.d`
- ///
- /// Note that IPv4-compatible addresses have been officially deprecated.
- /// If you don't explicitly need an IPv4-compatible address for legacy reasons, consider using `to_ipv6_mapped` instead.
- ///
- /// [IPv4-compatible]: Ipv6Addr#ipv4-compatible-ipv6-addresses
- /// [`IPv6` address]: Ipv6Addr
- ///
- /// # Examples
- ///
- /// ```
- /// use std::net::{Ipv4Addr, Ipv6Addr};
- ///
- /// assert_eq!(
- /// Ipv4Addr::new(192, 0, 2, 255).to_ipv6_compatible(),
- /// Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0xc000, 0x2ff)
- /// );
- /// ```
- #[rustc_const_stable(feature = "const_ip_50", 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();
- Ipv6Addr { octets: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, a, b, c, d] }
- }
-
- /// Converts this address to an [IPv4-mapped] [`IPv6` address].
- ///
- /// `a.b.c.d` becomes `::ffff:a.b.c.d`
- ///
- /// [IPv4-mapped]: Ipv6Addr#ipv4-mapped-ipv6-addresses
- /// [`IPv6` address]: Ipv6Addr
- ///
- /// # Examples
- ///
- /// ```
- /// use std::net::{Ipv4Addr, Ipv6Addr};
- ///
- /// assert_eq!(Ipv4Addr::new(192, 0, 2, 255).to_ipv6_mapped(),
- /// Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc000, 0x2ff));
- /// ```
- #[rustc_const_stable(feature = "const_ip_50", 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();
- Ipv6Addr { octets: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF, a, b, c, d] }
- }
-}
-
-#[stable(feature = "ip_addr", since = "1.7.0")]
-impl fmt::Display for IpAddr {
- fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
- match self {
- IpAddr::V4(ip) => ip.fmt(fmt),
- IpAddr::V6(ip) => ip.fmt(fmt),
- }
- }
-}
-
-#[stable(feature = "ip_addr", since = "1.7.0")]
-impl fmt::Debug for IpAddr {
- fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
- fmt::Display::fmt(self, fmt)
- }
-}
-
-#[stable(feature = "ip_from_ip", since = "1.16.0")]
-impl From<Ipv4Addr> for IpAddr {
- /// Copies this address to a new `IpAddr::V4`.
- ///
- /// # Examples
- ///
- /// ```
- /// use std::net::{IpAddr, Ipv4Addr};
- ///
- /// let addr = Ipv4Addr::new(127, 0, 0, 1);
- ///
- /// assert_eq!(
- /// IpAddr::V4(addr),
- /// IpAddr::from(addr)
- /// )
- /// ```
- #[inline]
- fn from(ipv4: Ipv4Addr) -> IpAddr {
- IpAddr::V4(ipv4)
- }
-}
-
-#[stable(feature = "ip_from_ip", since = "1.16.0")]
-impl From<Ipv6Addr> for IpAddr {
- /// Copies this address to a new `IpAddr::V6`.
- ///
- /// # Examples
- ///
- /// ```
- /// use std::net::{IpAddr, Ipv6Addr};
- ///
- /// let addr = Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff);
- ///
- /// assert_eq!(
- /// IpAddr::V6(addr),
- /// IpAddr::from(addr)
- /// );
- /// ```
- #[inline]
- fn from(ipv6: Ipv6Addr) -> IpAddr {
- IpAddr::V6(ipv6)
- }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl fmt::Display for Ipv4Addr {
- fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
- let octets = self.octets();
-
- // If there are no alignment requirements, write the IP address directly to `f`.
- // Otherwise, write it to a local buffer and then use `f.pad`.
- if fmt.precision().is_none() && fmt.width().is_none() {
- write!(fmt, "{}.{}.{}.{}", octets[0], octets[1], octets[2], octets[3])
- } else {
- const LONGEST_IPV4_ADDR: &str = "255.255.255.255";
-
- let mut buf = DisplayBuffer::<{ LONGEST_IPV4_ADDR.len() }>::new();
- // Buffer is long enough for the longest possible IPv4 address, so this should never fail.
- write!(buf, "{}.{}.{}.{}", octets[0], octets[1], octets[2], octets[3]).unwrap();
-
- fmt.pad(buf.as_str())
- }
- }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl fmt::Debug for Ipv4Addr {
- fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
- fmt::Display::fmt(self, fmt)
- }
-}
-
-#[stable(feature = "ip_cmp", since = "1.16.0")]
-impl PartialEq<Ipv4Addr> for IpAddr {
- #[inline]
- fn eq(&self, other: &Ipv4Addr) -> bool {
- match self {
- IpAddr::V4(v4) => v4 == other,
- IpAddr::V6(_) => false,
- }
- }
-}
-
-#[stable(feature = "ip_cmp", since = "1.16.0")]
-impl PartialEq<IpAddr> for Ipv4Addr {
- #[inline]
- fn eq(&self, other: &IpAddr) -> bool {
- match other {
- IpAddr::V4(v4) => self == v4,
- IpAddr::V6(_) => false,
- }
- }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl PartialOrd for Ipv4Addr {
- #[inline]
- fn partial_cmp(&self, other: &Ipv4Addr) -> Option<Ordering> {
- Some(self.cmp(other))
- }
-}
-
-#[stable(feature = "ip_cmp", since = "1.16.0")]
-impl PartialOrd<Ipv4Addr> for IpAddr {
- #[inline]
- fn partial_cmp(&self, other: &Ipv4Addr) -> Option<Ordering> {
- match self {
- IpAddr::V4(v4) => v4.partial_cmp(other),
- IpAddr::V6(_) => Some(Ordering::Greater),
- }
- }
-}
-
-#[stable(feature = "ip_cmp", since = "1.16.0")]
-impl PartialOrd<IpAddr> for Ipv4Addr {
- #[inline]
- fn partial_cmp(&self, other: &IpAddr) -> Option<Ordering> {
- match other {
- IpAddr::V4(v4) => self.partial_cmp(v4),
- IpAddr::V6(_) => Some(Ordering::Less),
- }
- }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl Ord for Ipv4Addr {
- #[inline]
- fn cmp(&self, other: &Ipv4Addr) -> Ordering {
- self.octets.cmp(&other.octets)
- }
-}
+pub use core::net::Ipv6MulticastScope;
impl IntoInner<c::in_addr> for Ipv4Addr {
#[inline]
fn into_inner(self) -> c::in_addr {
// `s_addr` is stored as BE on all machines and the array is in BE order.
// So the native endian conversion method is used so that it's never swapped.
- c::in_addr { s_addr: u32::from_ne_bytes(self.octets) }
+ c::in_addr { s_addr: u32::from_ne_bytes(self.octets()) }
}
}
impl FromInner<c::in_addr> for Ipv4Addr {
fn from_inner(addr: c::in_addr) -> Ipv4Addr {
- Ipv4Addr { octets: addr.s_addr.to_ne_bytes() }
- }
-}
-
-#[stable(feature = "ip_u32", since = "1.1.0")]
-impl From<Ipv4Addr> for u32 {
- /// Converts an `Ipv4Addr` into a host byte order `u32`.
- ///
- /// # Examples
- ///
- /// ```
- /// use std::net::Ipv4Addr;
- ///
- /// let addr = Ipv4Addr::new(0x12, 0x34, 0x56, 0x78);
- /// assert_eq!(0x12345678, u32::from(addr));
- /// ```
- #[inline]
- fn from(ip: Ipv4Addr) -> u32 {
- u32::from_be_bytes(ip.octets)
- }
-}
-
-#[stable(feature = "ip_u32", since = "1.1.0")]
-impl From<u32> for Ipv4Addr {
- /// Converts a host byte order `u32` into an `Ipv4Addr`.
- ///
- /// # Examples
- ///
- /// ```
- /// use std::net::Ipv4Addr;
- ///
- /// let addr = Ipv4Addr::from(0x12345678);
- /// assert_eq!(Ipv4Addr::new(0x12, 0x34, 0x56, 0x78), addr);
- /// ```
- #[inline]
- fn from(ip: u32) -> Ipv4Addr {
- Ipv4Addr { octets: ip.to_be_bytes() }
- }
-}
-
-#[stable(feature = "from_slice_v4", since = "1.9.0")]
-impl From<[u8; 4]> for Ipv4Addr {
- /// Creates an `Ipv4Addr` from a four element byte array.
- ///
- /// # Examples
- ///
- /// ```
- /// use std::net::Ipv4Addr;
- ///
- /// let addr = Ipv4Addr::from([13u8, 12u8, 11u8, 10u8]);
- /// assert_eq!(Ipv4Addr::new(13, 12, 11, 10), addr);
- /// ```
- #[inline]
- fn from(octets: [u8; 4]) -> Ipv4Addr {
- Ipv4Addr { octets }
- }
-}
-
-#[stable(feature = "ip_from_slice", since = "1.17.0")]
-impl From<[u8; 4]> for IpAddr {
- /// Creates an `IpAddr::V4` from a four element byte array.
- ///
- /// # Examples
- ///
- /// ```
- /// use std::net::{IpAddr, Ipv4Addr};
- ///
- /// let addr = IpAddr::from([13u8, 12u8, 11u8, 10u8]);
- /// assert_eq!(IpAddr::V4(Ipv4Addr::new(13, 12, 11, 10)), addr);
- /// ```
- #[inline]
- fn from(octets: [u8; 4]) -> IpAddr {
- IpAddr::V4(Ipv4Addr::from(octets))
- }
-}
-
-impl Ipv6Addr {
- /// Creates a new IPv6 address from eight 16-bit segments.
- ///
- /// The result will represent the IP address `a:b:c:d:e:f:g:h`.
- ///
- /// # Examples
- ///
- /// ```
- /// use std::net::Ipv6Addr;
- ///
- /// let addr = Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff);
- /// ```
- #[rustc_const_stable(feature = "const_ip_32", 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 = [
- a.to_be(),
- b.to_be(),
- c.to_be(),
- d.to_be(),
- e.to_be(),
- f.to_be(),
- g.to_be(),
- h.to_be(),
- ];
- Ipv6Addr {
- // All elements in `addr16` are big endian.
- // SAFETY: `[u16; 8]` is always safe to transmute to `[u8; 16]`.
- octets: unsafe { transmute::<_, [u8; 16]>(addr16) },
- }
- }
-
- /// An IPv6 address representing localhost: `::1`.
- ///
- /// This corresponds to constant `IN6ADDR_LOOPBACK_INIT` or `in6addr_loopback` in other
- /// languages.
- ///
- /// # Examples
- ///
- /// ```
- /// use std::net::Ipv6Addr;
- ///
- /// let addr = Ipv6Addr::LOCALHOST;
- /// assert_eq!(addr, Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1));
- /// ```
- #[doc(alias = "IN6ADDR_LOOPBACK_INIT")]
- #[doc(alias = "in6addr_loopback")]
- #[stable(feature = "ip_constructors", since = "1.30.0")]
- pub const LOCALHOST: Self = Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1);
-
- /// An IPv6 address representing the unspecified address: `::`
- ///
- /// This corresponds to constant `IN6ADDR_ANY_INIT` or `in6addr_any` in other languages.
- ///
- /// # Examples
- ///
- /// ```
- /// use std::net::Ipv6Addr;
- ///
- /// let addr = Ipv6Addr::UNSPECIFIED;
- /// assert_eq!(addr, Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0));
- /// ```
- #[doc(alias = "IN6ADDR_ANY_INIT")]
- #[doc(alias = "in6addr_any")]
- #[stable(feature = "ip_constructors", since = "1.30.0")]
- pub const UNSPECIFIED: Self = Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0);
-
- /// Returns the eight 16-bit segments that make up this address.
- ///
- /// # Examples
- ///
- /// ```
- /// use std::net::Ipv6Addr;
- ///
- /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).segments(),
- /// [0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff]);
- /// ```
- #[rustc_const_stable(feature = "const_ip_50", since = "1.50.0")]
- #[stable(feature = "rust1", since = "1.0.0")]
- #[must_use]
- #[inline]
- pub const fn segments(&self) -> [u16; 8] {
- // All elements in `self.octets` must be big endian.
- // SAFETY: `[u8; 16]` is always safe to transmute to `[u16; 8]`.
- let [a, b, c, d, e, f, g, h] = unsafe { transmute::<_, [u16; 8]>(self.octets) };
- // We want native endian u16
- [
- u16::from_be(a),
- u16::from_be(b),
- u16::from_be(c),
- u16::from_be(d),
- u16::from_be(e),
- u16::from_be(f),
- u16::from_be(g),
- u16::from_be(h),
- ]
- }
-
- /// Returns [`true`] for the special 'unspecified' address (`::`).
- ///
- /// This property is defined in [IETF RFC 4291].
- ///
- /// [IETF RFC 4291]: https://tools.ietf.org/html/rfc4291
- ///
- /// # Examples
- ///
- /// ```
- /// use std::net::Ipv6Addr;
- ///
- /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_unspecified(), false);
- /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0).is_unspecified(), true);
- /// ```
- #[rustc_const_stable(feature = "const_ip_50", 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())
- }
-
- /// Returns [`true`] if this is the [loopback address] (`::1`),
- /// as defined in [IETF RFC 4291 section 2.5.3].
- ///
- /// Contrary to IPv4, in IPv6 there is only one loopback address.
- ///
- /// [loopback address]: Ipv6Addr::LOCALHOST
- /// [IETF RFC 4291 section 2.5.3]: https://tools.ietf.org/html/rfc4291#section-2.5.3
- ///
- /// # Examples
- ///
- /// ```
- /// use std::net::Ipv6Addr;
- ///
- /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_loopback(), false);
- /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0x1).is_loopback(), true);
- /// ```
- #[rustc_const_stable(feature = "const_ip_50", 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())
- }
-
- /// Returns [`true`] if the address appears to be globally reachable
- /// as specified by the [IANA IPv6 Special-Purpose Address Registry].
- /// Whether or not an address is practically reachable will depend on your network configuration.
- ///
- /// Most IPv6 addresses are globally reachable;
- /// unless they are specifically defined as *not* globally reachable.
- ///
- /// Non-exhaustive list of notable addresses that are not globally reachable:
- /// - The [unspecified address] ([`is_unspecified`](Ipv6Addr::is_unspecified))
- /// - The [loopback address] ([`is_loopback`](Ipv6Addr::is_loopback))
- /// - IPv4-mapped addresses
- /// - Addresses reserved for benchmarking
- /// - Addresses reserved for documentation ([`is_documentation`](Ipv6Addr::is_documentation))
- /// - Unique local addresses ([`is_unique_local`](Ipv6Addr::is_unique_local))
- /// - Unicast addresses with link-local scope ([`is_unicast_link_local`](Ipv6Addr::is_unicast_link_local))
- ///
- /// For the complete overview of which addresses are globally reachable, see the table at the [IANA IPv6 Special-Purpose Address Registry].
- ///
- /// Note that an address having global scope is not the same as being globally reachable,
- /// and there is no direct relation between the two concepts: There exist addresses with global scope
- /// that are not globally reachable (for example unique local addresses),
- /// and addresses that are globally reachable without having global scope
- /// (multicast addresses with non-global scope).
- ///
- /// [IANA IPv6 Special-Purpose Address Registry]: https://www.iana.org/assignments/iana-ipv6-special-registry/iana-ipv6-special-registry.xhtml
- /// [unspecified address]: Ipv6Addr::UNSPECIFIED
- /// [loopback address]: Ipv6Addr::LOCALHOST
- ///
- /// # Examples
- ///
- /// ```
- /// #![feature(ip)]
- ///
- /// use std::net::Ipv6Addr;
- ///
- /// // Most IPv6 addresses are globally reachable:
- /// assert_eq!(Ipv6Addr::new(0x26, 0, 0x1c9, 0, 0, 0xafc8, 0x10, 0x1).is_global(), true);
- ///
- /// // However some addresses have been assigned a special meaning
- /// // that makes them not globally reachable. Some examples are:
- ///
- /// // The unspecified address (`::`)
- /// assert_eq!(Ipv6Addr::UNSPECIFIED.is_global(), false);
- ///
- /// // The loopback address (`::1`)
- /// assert_eq!(Ipv6Addr::LOCALHOST.is_global(), false);
- ///
- /// // IPv4-mapped addresses (`::ffff:0:0/96`)
- /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_global(), false);
- ///
- /// // Addresses reserved for benchmarking (`2001:2::/48`)
- /// assert_eq!(Ipv6Addr::new(0x2001, 2, 0, 0, 0, 0, 0, 1,).is_global(), false);
- ///
- /// // Addresses reserved for documentation (`2001:db8::/32`)
- /// assert_eq!(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 1).is_global(), false);
- ///
- /// // Unique local addresses (`fc00::/7`)
- /// assert_eq!(Ipv6Addr::new(0xfc02, 0, 0, 0, 0, 0, 0, 1).is_global(), false);
- ///
- /// // Unicast addresses with link-local scope (`fe80::/10`)
- /// assert_eq!(Ipv6Addr::new(0xfe81, 0, 0, 0, 0, 0, 0, 1).is_global(), false);
- ///
- /// // For a complete overview see the IANA IPv6 Special-Purpose Address Registry.
- /// ```
- #[rustc_const_unstable(feature = "const_ipv6", issue = "76205")]
- #[unstable(feature = "ip", issue = "27709")]
- #[must_use]
- #[inline]
- pub const fn is_global(&self) -> bool {
- !(self.is_unspecified()
- || self.is_loopback()
- // IPv4-mapped Address (`::ffff:0:0/96`)
- || matches!(self.segments(), [0, 0, 0, 0, 0, 0xffff, _, _])
- // IPv4-IPv6 Translat. (`64:ff9b:1::/48`)
- || matches!(self.segments(), [0x64, 0xff9b, 1, _, _, _, _, _])
- // Discard-Only Address Block (`100::/64`)
- || matches!(self.segments(), [0x100, 0, 0, 0, _, _, _, _])
- // IETF Protocol Assignments (`2001::/23`)
- || (matches!(self.segments(), [0x2001, b, _, _, _, _, _, _] if b < 0x200)
- && !(
- // Port Control Protocol Anycast (`2001:1::1`)
- u128::from_be_bytes(self.octets()) == 0x2001_0001_0000_0000_0000_0000_0000_0001
- // Traversal Using Relays around NAT Anycast (`2001:1::2`)
- || u128::from_be_bytes(self.octets()) == 0x2001_0001_0000_0000_0000_0000_0000_0002
- // AMT (`2001:3::/32`)
- || matches!(self.segments(), [0x2001, 3, _, _, _, _, _, _])
- // AS112-v6 (`2001:4:112::/48`)
- || matches!(self.segments(), [0x2001, 4, 0x112, _, _, _, _, _])
- // ORCHIDv2 (`2001:20::/28`)
- || matches!(self.segments(), [0x2001, b, _, _, _, _, _, _] if b >= 0x20 && b <= 0x2F)
- ))
- || self.is_documentation()
- || self.is_unique_local()
- || self.is_unicast_link_local())
- }
-
- /// Returns [`true`] if this is a unique local address (`fc00::/7`).
- ///
- /// This property is defined in [IETF RFC 4193].
- ///
- /// [IETF RFC 4193]: https://tools.ietf.org/html/rfc4193
- ///
- /// # Examples
- ///
- /// ```
- /// #![feature(ip)]
- ///
- /// use std::net::Ipv6Addr;
- ///
- /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_unique_local(), false);
- /// assert_eq!(Ipv6Addr::new(0xfc02, 0, 0, 0, 0, 0, 0, 0).is_unique_local(), true);
- /// ```
- #[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
- }
-
- /// Returns [`true`] if this is a unicast address, as defined by [IETF RFC 4291].
- /// Any address that is not a [multicast address] (`ff00::/8`) is unicast.
- ///
- /// [IETF RFC 4291]: https://tools.ietf.org/html/rfc4291
- /// [multicast address]: Ipv6Addr::is_multicast
- ///
- /// # Examples
- ///
- /// ```
- /// #![feature(ip)]
- ///
- /// use std::net::Ipv6Addr;
- ///
- /// // The unspecified and loopback addresses are unicast.
- /// assert_eq!(Ipv6Addr::UNSPECIFIED.is_unicast(), true);
- /// assert_eq!(Ipv6Addr::LOCALHOST.is_unicast(), true);
- ///
- /// // Any address that is not a multicast address (`ff00::/8`) is unicast.
- /// assert_eq!(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0).is_unicast(), true);
- /// assert_eq!(Ipv6Addr::new(0xff00, 0, 0, 0, 0, 0, 0, 0).is_unicast(), false);
- /// ```
- #[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()
- }
-
- /// Returns `true` if the address is a unicast address with link-local scope,
- /// as defined in [RFC 4291].
- ///
- /// A unicast address has link-local scope if it has the prefix `fe80::/10`, as per [RFC 4291 section 2.4].
- /// Note that this encompasses more addresses than those defined in [RFC 4291 section 2.5.6],
- /// which describes "Link-Local IPv6 Unicast Addresses" as having the following stricter format:
- ///
- /// ```text
- /// | 10 bits | 54 bits | 64 bits |
- /// +----------+-------------------------+----------------------------+
- /// |1111111010| 0 | interface ID |
- /// +----------+-------------------------+----------------------------+
- /// ```
- /// So while currently the only addresses with link-local scope an application will encounter are all in `fe80::/64`,
- /// this might change in the future with the publication of new standards. More addresses in `fe80::/10` could be allocated,
- /// and those addresses will have link-local scope.
- ///
- /// Also note that while [RFC 4291 section 2.5.3] mentions about the [loopback address] (`::1`) that "it is treated as having Link-Local scope",
- /// this does not mean that the loopback address actually has link-local scope and this method will return `false` on it.
- ///
- /// [RFC 4291]: https://tools.ietf.org/html/rfc4291
- /// [RFC 4291 section 2.4]: https://tools.ietf.org/html/rfc4291#section-2.4
- /// [RFC 4291 section 2.5.3]: https://tools.ietf.org/html/rfc4291#section-2.5.3
- /// [RFC 4291 section 2.5.6]: https://tools.ietf.org/html/rfc4291#section-2.5.6
- /// [loopback address]: Ipv6Addr::LOCALHOST
- ///
- /// # Examples
- ///
- /// ```
- /// #![feature(ip)]
- ///
- /// use std::net::Ipv6Addr;
- ///
- /// // The loopback address (`::1`) does not actually have link-local scope.
- /// assert_eq!(Ipv6Addr::LOCALHOST.is_unicast_link_local(), false);
- ///
- /// // Only addresses in `fe80::/10` have link-local scope.
- /// assert_eq!(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0).is_unicast_link_local(), false);
- /// assert_eq!(Ipv6Addr::new(0xfe80, 0, 0, 0, 0, 0, 0, 0).is_unicast_link_local(), true);
- ///
- /// // Addresses outside the stricter `fe80::/64` also have link-local scope.
- /// assert_eq!(Ipv6Addr::new(0xfe80, 0, 0, 1, 0, 0, 0, 0).is_unicast_link_local(), true);
- /// assert_eq!(Ipv6Addr::new(0xfe81, 0, 0, 0, 0, 0, 0, 0).is_unicast_link_local(), true);
- /// ```
- #[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
- }
-
- /// Returns [`true`] if this is an address reserved for documentation
- /// (`2001:db8::/32`).
- ///
- /// This property is defined in [IETF RFC 3849].
- ///
- /// [IETF RFC 3849]: https://tools.ietf.org/html/rfc3849
- ///
- /// # Examples
- ///
- /// ```
- /// #![feature(ip)]
- ///
- /// use std::net::Ipv6Addr;
- ///
- /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_documentation(), false);
- /// assert_eq!(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0).is_documentation(), true);
- /// ```
- #[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:
- ///
- /// - the loopback address
- /// - the link-local addresses
- /// - unique local addresses
- /// - the unspecified address
- /// - the address range reserved for documentation
- ///
- /// This method returns [`true`] for site-local addresses as per [RFC 4291 section 2.5.7]
- ///
- /// ```no_rust
- /// The special behavior of [the site-local unicast] prefix defined in [RFC3513] must no longer
- /// be supported in new implementations (i.e., new implementations must treat this prefix as
- /// Global Unicast).
- /// ```
- ///
- /// [RFC 4291 section 2.5.7]: https://tools.ietf.org/html/rfc4291#section-2.5.7
- ///
- /// # Examples
- ///
- /// ```
- /// #![feature(ip)]
- ///
- /// use std::net::Ipv6Addr;
- ///
- /// assert_eq!(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0).is_unicast_global(), false);
- /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_unicast_global(), true);
- /// ```
- #[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()
- && !self.is_loopback()
- && !self.is_unicast_link_local()
- && !self.is_unique_local()
- && !self.is_unspecified()
- && !self.is_documentation()
- && !self.is_benchmarking()
- }
-
- /// Returns the address's multicast scope if the address is multicast.
- ///
- /// # Examples
- ///
- /// ```
- /// #![feature(ip)]
- ///
- /// use std::net::{Ipv6Addr, Ipv6MulticastScope};
- ///
- /// assert_eq!(
- /// Ipv6Addr::new(0xff0e, 0, 0, 0, 0, 0, 0, 0).multicast_scope(),
- /// Some(Ipv6MulticastScope::Global)
- /// );
- /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).multicast_scope(), None);
- /// ```
- #[rustc_const_unstable(feature = "const_ipv6", issue = "76205")]
- #[unstable(feature = "ip", issue = "27709")]
- #[must_use]
- #[inline]
- pub const fn multicast_scope(&self) -> Option<Ipv6MulticastScope> {
- if self.is_multicast() {
- match self.segments()[0] & 0x000f {
- 1 => Some(Ipv6MulticastScope::InterfaceLocal),
- 2 => Some(Ipv6MulticastScope::LinkLocal),
- 3 => Some(Ipv6MulticastScope::RealmLocal),
- 4 => Some(Ipv6MulticastScope::AdminLocal),
- 5 => Some(Ipv6MulticastScope::SiteLocal),
- 8 => Some(Ipv6MulticastScope::OrganizationLocal),
- 14 => Some(Ipv6MulticastScope::Global),
- _ => None,
- }
- } else {
- None
- }
- }
-
- /// Returns [`true`] if this is a multicast address (`ff00::/8`).
- ///
- /// This property is defined by [IETF RFC 4291].
- ///
- /// [IETF RFC 4291]: https://tools.ietf.org/html/rfc4291
- ///
- /// # Examples
- ///
- /// ```
- /// use std::net::Ipv6Addr;
- ///
- /// assert_eq!(Ipv6Addr::new(0xff00, 0, 0, 0, 0, 0, 0, 0).is_multicast(), true);
- /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_multicast(), false);
- /// ```
- #[rustc_const_stable(feature = "const_ip_50", 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
- }
-
- /// Converts this address to an [`IPv4` address] if it's an [IPv4-mapped] address,
- /// as defined in [IETF RFC 4291 section 2.5.5.2], otherwise returns [`None`].
- ///
- /// `::ffff:a.b.c.d` becomes `a.b.c.d`.
- /// All addresses *not* starting with `::ffff` will return `None`.
- ///
- /// [`IPv4` address]: Ipv4Addr
- /// [IPv4-mapped]: Ipv6Addr
- /// [IETF RFC 4291 section 2.5.5.2]: https://tools.ietf.org/html/rfc4291#section-2.5.5.2
- ///
- /// # Examples
- ///
- /// ```
- /// use std::net::{Ipv4Addr, Ipv6Addr};
- ///
- /// assert_eq!(Ipv6Addr::new(0xff00, 0, 0, 0, 0, 0, 0, 0).to_ipv4_mapped(), None);
- /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).to_ipv4_mapped(),
- /// Some(Ipv4Addr::new(192, 10, 2, 255)));
- /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1).to_ipv4_mapped(), None);
- /// ```
- #[rustc_const_unstable(feature = "const_ipv6", issue = "76205")]
- #[stable(feature = "ipv6_to_ipv4_mapped", since = "1.63.0")]
- #[must_use = "this returns the result of the operation, \
- without modifying the original"]
- #[inline]
- pub const fn to_ipv4_mapped(&self) -> Option<Ipv4Addr> {
- match self.octets() {
- [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff, a, b, c, d] => {
- Some(Ipv4Addr::new(a, b, c, d))
- }
- _ => None,
- }
- }
-
- /// Converts this address to an [`IPv4` address] if it is either
- /// an [IPv4-compatible] address as defined in [IETF RFC 4291 section 2.5.5.1],
- /// or an [IPv4-mapped] address as defined in [IETF RFC 4291 section 2.5.5.2],
- /// otherwise returns [`None`].
- ///
- /// Note that this will return an [`IPv4` address] for the IPv6 loopback address `::1`. Use
- /// [`Ipv6Addr::to_ipv4_mapped`] to avoid this.
- ///
- /// `::a.b.c.d` and `::ffff:a.b.c.d` become `a.b.c.d`. `::1` becomes `0.0.0.1`.
- /// All addresses *not* starting with either all zeroes or `::ffff` will return `None`.
- ///
- /// [`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
- /// [IETF RFC 4291 section 2.5.5.2]: https://tools.ietf.org/html/rfc4291#section-2.5.5.2
- ///
- /// # Examples
- ///
- /// ```
- /// use std::net::{Ipv4Addr, Ipv6Addr};
- ///
- /// assert_eq!(Ipv6Addr::new(0xff00, 0, 0, 0, 0, 0, 0, 0).to_ipv4(), None);
- /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).to_ipv4(),
- /// Some(Ipv4Addr::new(192, 10, 2, 255)));
- /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1).to_ipv4(),
- /// Some(Ipv4Addr::new(0, 0, 0, 1)));
- /// ```
- #[rustc_const_stable(feature = "const_ip_50", 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<Ipv4Addr> {
- if let [0, 0, 0, 0, 0, 0 | 0xffff, ab, cd] = self.segments() {
- let [a, b] = ab.to_be_bytes();
- let [c, d] = cd.to_be_bytes();
- Some(Ipv4Addr::new(a, b, c, d))
- } else {
- None
- }
- }
-
- /// Converts this address to an `IpAddr::V4` if it is an IPv4-mapped addresses, otherwise it
- /// returns self wrapped in an `IpAddr::V6`.
- ///
- /// # Examples
- ///
- /// ```
- /// #![feature(ip)]
- /// use std::net::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);
- /// ```
- #[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);
- }
- IpAddr::V6(*self)
- }
-
- /// Returns the sixteen eight-bit integers the IPv6 address consists of.
- ///
- /// ```
- /// use std::net::Ipv6Addr;
- ///
- /// assert_eq!(Ipv6Addr::new(0xff00, 0, 0, 0, 0, 0, 0, 0).octets(),
- /// [255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
- /// ```
- #[rustc_const_stable(feature = "const_ip_32", since = "1.32.0")]
- #[stable(feature = "ipv6_to_octets", since = "1.12.0")]
- #[must_use]
- #[inline]
- pub const fn octets(&self) -> [u8; 16] {
- self.octets
- }
-}
-
-/// Write an Ipv6Addr, conforming to the canonical style described by
-/// [RFC 5952](https://tools.ietf.org/html/rfc5952).
-#[stable(feature = "rust1", since = "1.0.0")]
-impl fmt::Display for Ipv6Addr {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- // If there are no alignment requirements, write the IP address directly to `f`.
- // Otherwise, write it to a local buffer and then use `f.pad`.
- if f.precision().is_none() && f.width().is_none() {
- let segments = self.segments();
-
- // Special case for :: and ::1; otherwise they get written with the
- // IPv4 formatter
- if self.is_unspecified() {
- f.write_str("::")
- } else if self.is_loopback() {
- f.write_str("::1")
- } else if let Some(ipv4) = self.to_ipv4() {
- match segments[5] {
- // IPv4 Compatible address
- 0 => write!(f, "::{}", ipv4),
- // IPv4 Mapped address
- 0xffff => write!(f, "::ffff:{}", ipv4),
- _ => unreachable!(),
- }
- } else {
- #[derive(Copy, Clone, Default)]
- struct Span {
- start: usize,
- len: usize,
- }
-
- // Find the inner 0 span
- let zeroes = {
- let mut longest = Span::default();
- let mut current = Span::default();
-
- for (i, &segment) in segments.iter().enumerate() {
- if segment == 0 {
- if current.len == 0 {
- current.start = i;
- }
-
- current.len += 1;
-
- if current.len > longest.len {
- longest = current;
- }
- } else {
- current = Span::default();
- }
- }
-
- longest
- };
-
- /// Write a colon-separated part of the address
- #[inline]
- fn fmt_subslice(f: &mut fmt::Formatter<'_>, chunk: &[u16]) -> fmt::Result {
- if let Some((first, tail)) = chunk.split_first() {
- write!(f, "{:x}", first)?;
- for segment in tail {
- f.write_char(':')?;
- write!(f, "{:x}", segment)?;
- }
- }
- Ok(())
- }
-
- if zeroes.len > 1 {
- fmt_subslice(f, &segments[..zeroes.start])?;
- f.write_str("::")?;
- fmt_subslice(f, &segments[zeroes.start + zeroes.len..])
- } else {
- fmt_subslice(f, &segments)
- }
- }
- } else {
- const LONGEST_IPV6_ADDR: &str = "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff";
-
- let mut buf = DisplayBuffer::<{ LONGEST_IPV6_ADDR.len() }>::new();
- // Buffer is long enough for the longest possible IPv6 address, so this should never fail.
- write!(buf, "{}", self).unwrap();
-
- f.pad(buf.as_str())
- }
- }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl fmt::Debug for Ipv6Addr {
- fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
- fmt::Display::fmt(self, fmt)
- }
-}
-
-#[stable(feature = "ip_cmp", since = "1.16.0")]
-impl PartialEq<IpAddr> for Ipv6Addr {
- #[inline]
- fn eq(&self, other: &IpAddr) -> bool {
- match other {
- IpAddr::V4(_) => false,
- IpAddr::V6(v6) => self == v6,
- }
- }
-}
-
-#[stable(feature = "ip_cmp", since = "1.16.0")]
-impl PartialEq<Ipv6Addr> for IpAddr {
- #[inline]
- fn eq(&self, other: &Ipv6Addr) -> bool {
- match self {
- IpAddr::V4(_) => false,
- IpAddr::V6(v6) => v6 == other,
- }
- }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl PartialOrd for Ipv6Addr {
- #[inline]
- fn partial_cmp(&self, other: &Ipv6Addr) -> Option<Ordering> {
- Some(self.cmp(other))
- }
-}
-
-#[stable(feature = "ip_cmp", since = "1.16.0")]
-impl PartialOrd<Ipv6Addr> for IpAddr {
- #[inline]
- fn partial_cmp(&self, other: &Ipv6Addr) -> Option<Ordering> {
- match self {
- IpAddr::V4(_) => Some(Ordering::Less),
- IpAddr::V6(v6) => v6.partial_cmp(other),
- }
- }
-}
-
-#[stable(feature = "ip_cmp", since = "1.16.0")]
-impl PartialOrd<IpAddr> for Ipv6Addr {
- #[inline]
- fn partial_cmp(&self, other: &IpAddr) -> Option<Ordering> {
- match other {
- IpAddr::V4(_) => Some(Ordering::Greater),
- IpAddr::V6(v6) => self.partial_cmp(v6),
- }
- }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl Ord for Ipv6Addr {
- #[inline]
- fn cmp(&self, other: &Ipv6Addr) -> Ordering {
- self.segments().cmp(&other.segments())
+ Ipv4Addr::from(addr.s_addr.to_ne_bytes())
}
}
impl IntoInner<c::in6_addr> for Ipv6Addr {
fn into_inner(self) -> c::in6_addr {
- c::in6_addr { s6_addr: self.octets }
+ c::in6_addr { s6_addr: self.octets() }
}
}
impl FromInner<c::in6_addr> for Ipv6Addr {
#[inline]
fn from_inner(addr: c::in6_addr) -> Ipv6Addr {
- Ipv6Addr { octets: addr.s6_addr }
- }
-}
-
-#[stable(feature = "i128", since = "1.26.0")]
-impl From<Ipv6Addr> for u128 {
- /// Convert an `Ipv6Addr` into a host byte order `u128`.
- ///
- /// # Examples
- ///
- /// ```
- /// use std::net::Ipv6Addr;
- ///
- /// let addr = Ipv6Addr::new(
- /// 0x1020, 0x3040, 0x5060, 0x7080,
- /// 0x90A0, 0xB0C0, 0xD0E0, 0xF00D,
- /// );
- /// assert_eq!(0x102030405060708090A0B0C0D0E0F00D_u128, u128::from(addr));
- /// ```
- #[inline]
- fn from(ip: Ipv6Addr) -> u128 {
- u128::from_be_bytes(ip.octets)
- }
-}
-#[stable(feature = "i128", since = "1.26.0")]
-impl From<u128> for Ipv6Addr {
- /// Convert a host byte order `u128` into an `Ipv6Addr`.
- ///
- /// # Examples
- ///
- /// ```
- /// use std::net::Ipv6Addr;
- ///
- /// let addr = Ipv6Addr::from(0x102030405060708090A0B0C0D0E0F00D_u128);
- /// assert_eq!(
- /// Ipv6Addr::new(
- /// 0x1020, 0x3040, 0x5060, 0x7080,
- /// 0x90A0, 0xB0C0, 0xD0E0, 0xF00D,
- /// ),
- /// addr);
- /// ```
- #[inline]
- fn from(ip: u128) -> Ipv6Addr {
- Ipv6Addr::from(ip.to_be_bytes())
- }
-}
-
-#[stable(feature = "ipv6_from_octets", since = "1.9.0")]
-impl From<[u8; 16]> for Ipv6Addr {
- /// Creates an `Ipv6Addr` from a sixteen element byte array.
- ///
- /// # Examples
- ///
- /// ```
- /// use std::net::Ipv6Addr;
- ///
- /// let addr = Ipv6Addr::from([
- /// 25u8, 24u8, 23u8, 22u8, 21u8, 20u8, 19u8, 18u8,
- /// 17u8, 16u8, 15u8, 14u8, 13u8, 12u8, 11u8, 10u8,
- /// ]);
- /// assert_eq!(
- /// Ipv6Addr::new(
- /// 0x1918, 0x1716,
- /// 0x1514, 0x1312,
- /// 0x1110, 0x0f0e,
- /// 0x0d0c, 0x0b0a
- /// ),
- /// addr
- /// );
- /// ```
- #[inline]
- fn from(octets: [u8; 16]) -> Ipv6Addr {
- Ipv6Addr { octets }
- }
-}
-
-#[stable(feature = "ipv6_from_segments", since = "1.16.0")]
-impl From<[u16; 8]> for Ipv6Addr {
- /// Creates an `Ipv6Addr` from an eight element 16-bit array.
- ///
- /// # Examples
- ///
- /// ```
- /// use std::net::Ipv6Addr;
- ///
- /// let addr = Ipv6Addr::from([
- /// 525u16, 524u16, 523u16, 522u16,
- /// 521u16, 520u16, 519u16, 518u16,
- /// ]);
- /// assert_eq!(
- /// Ipv6Addr::new(
- /// 0x20d, 0x20c,
- /// 0x20b, 0x20a,
- /// 0x209, 0x208,
- /// 0x207, 0x206
- /// ),
- /// addr
- /// );
- /// ```
- #[inline]
- fn from(segments: [u16; 8]) -> Ipv6Addr {
- let [a, b, c, d, e, f, g, h] = segments;
- Ipv6Addr::new(a, b, c, d, e, f, g, h)
- }
-}
-
-#[stable(feature = "ip_from_slice", since = "1.17.0")]
-impl From<[u8; 16]> for IpAddr {
- /// Creates an `IpAddr::V6` from a sixteen element byte array.
- ///
- /// # Examples
- ///
- /// ```
- /// use std::net::{IpAddr, Ipv6Addr};
- ///
- /// let addr = IpAddr::from([
- /// 25u8, 24u8, 23u8, 22u8, 21u8, 20u8, 19u8, 18u8,
- /// 17u8, 16u8, 15u8, 14u8, 13u8, 12u8, 11u8, 10u8,
- /// ]);
- /// assert_eq!(
- /// IpAddr::V6(Ipv6Addr::new(
- /// 0x1918, 0x1716,
- /// 0x1514, 0x1312,
- /// 0x1110, 0x0f0e,
- /// 0x0d0c, 0x0b0a
- /// )),
- /// addr
- /// );
- /// ```
- #[inline]
- fn from(octets: [u8; 16]) -> IpAddr {
- IpAddr::V6(Ipv6Addr::from(octets))
- }
-}
-
-#[stable(feature = "ip_from_slice", since = "1.17.0")]
-impl From<[u16; 8]> for IpAddr {
- /// Creates an `IpAddr::V6` from an eight element 16-bit array.
- ///
- /// # Examples
- ///
- /// ```
- /// use std::net::{IpAddr, Ipv6Addr};
- ///
- /// let addr = IpAddr::from([
- /// 525u16, 524u16, 523u16, 522u16,
- /// 521u16, 520u16, 519u16, 518u16,
- /// ]);
- /// assert_eq!(
- /// IpAddr::V6(Ipv6Addr::new(
- /// 0x20d, 0x20c,
- /// 0x20b, 0x20a,
- /// 0x209, 0x208,
- /// 0x207, 0x206
- /// )),
- /// addr
- /// );
- /// ```
- #[inline]
- fn from(segments: [u16; 8]) -> IpAddr {
- IpAddr::V6(Ipv6Addr::from(segments))
+ Ipv6Addr::from(addr.s6_addr)
}
}
diff --git a/library/std/src/net/ip_addr/tests.rs b/library/std/src/net/ip_addr/tests.rs
index 7c3430b2b..ab99c0c2f 100644
--- a/library/std/src/net/ip_addr/tests.rs
+++ b/library/std/src/net/ip_addr/tests.rs
@@ -1,1039 +1,8 @@
-use crate::net::test::{sa4, sa6, tsa};
-use crate::net::*;
-use crate::str::FromStr;
-
-#[test]
-fn test_from_str_ipv4() {
- assert_eq!(Ok(Ipv4Addr::new(127, 0, 0, 1)), "127.0.0.1".parse());
- assert_eq!(Ok(Ipv4Addr::new(255, 255, 255, 255)), "255.255.255.255".parse());
- assert_eq!(Ok(Ipv4Addr::new(0, 0, 0, 0)), "0.0.0.0".parse());
-
- // out of range
- let none: Option<Ipv4Addr> = "256.0.0.1".parse().ok();
- assert_eq!(None, none);
- // too short
- let none: Option<Ipv4Addr> = "255.0.0".parse().ok();
- assert_eq!(None, none);
- // too long
- let none: Option<Ipv4Addr> = "255.0.0.1.2".parse().ok();
- assert_eq!(None, none);
- // no number between dots
- let none: Option<Ipv4Addr> = "255.0..1".parse().ok();
- assert_eq!(None, none);
- // octal
- let none: Option<Ipv4Addr> = "255.0.0.01".parse().ok();
- assert_eq!(None, none);
- // octal zero
- let none: Option<Ipv4Addr> = "255.0.0.00".parse().ok();
- assert_eq!(None, none);
- let none: Option<Ipv4Addr> = "255.0.00.0".parse().ok();
- assert_eq!(None, none);
-}
-
-#[test]
-fn test_from_str_ipv6() {
- assert_eq!(Ok(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0)), "0:0:0:0:0:0:0:0".parse());
- assert_eq!(Ok(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1)), "0:0:0:0:0:0:0:1".parse());
-
- assert_eq!(Ok(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1)), "::1".parse());
- assert_eq!(Ok(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0)), "::".parse());
-
- assert_eq!(Ok(Ipv6Addr::new(0x2a02, 0x6b8, 0, 0, 0, 0, 0x11, 0x11)), "2a02:6b8::11:11".parse());
-
- // too long group
- let none: Option<Ipv6Addr> = "::00000".parse().ok();
- assert_eq!(None, none);
- // too short
- let none: Option<Ipv6Addr> = "1:2:3:4:5:6:7".parse().ok();
- assert_eq!(None, none);
- // too long
- let none: Option<Ipv6Addr> = "1:2:3:4:5:6:7:8:9".parse().ok();
- assert_eq!(None, none);
- // triple colon
- let none: Option<Ipv6Addr> = "1:2:::6:7:8".parse().ok();
- assert_eq!(None, none);
- // two double colons
- let none: Option<Ipv6Addr> = "1:2::6::8".parse().ok();
- assert_eq!(None, none);
- // `::` indicating zero groups of zeros
- let none: Option<Ipv6Addr> = "1:2:3:4::5:6:7:8".parse().ok();
- assert_eq!(None, none);
-}
-
-#[test]
-fn test_from_str_ipv4_in_ipv6() {
- assert_eq!(Ok(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 49152, 545)), "::192.0.2.33".parse());
- assert_eq!(Ok(Ipv6Addr::new(0, 0, 0, 0, 0, 0xFFFF, 49152, 545)), "::FFFF:192.0.2.33".parse());
- assert_eq!(
- Ok(Ipv6Addr::new(0x64, 0xff9b, 0, 0, 0, 0, 49152, 545)),
- "64:ff9b::192.0.2.33".parse()
- );
- assert_eq!(
- Ok(Ipv6Addr::new(0x2001, 0xdb8, 0x122, 0xc000, 0x2, 0x2100, 49152, 545)),
- "2001:db8:122:c000:2:2100:192.0.2.33".parse()
- );
-
- // colon after v4
- let none: Option<Ipv4Addr> = "::127.0.0.1:".parse().ok();
- assert_eq!(None, none);
- // not enough groups
- let none: Option<Ipv6Addr> = "1:2:3:4:5:127.0.0.1".parse().ok();
- assert_eq!(None, none);
- // too many groups
- let none: Option<Ipv6Addr> = "1:2:3:4:5:6:7:127.0.0.1".parse().ok();
- assert_eq!(None, none);
-}
-
-#[test]
-fn test_from_str_socket_addr() {
- assert_eq!(Ok(sa4(Ipv4Addr::new(77, 88, 21, 11), 80)), "77.88.21.11:80".parse());
- assert_eq!(Ok(SocketAddrV4::new(Ipv4Addr::new(77, 88, 21, 11), 80)), "77.88.21.11:80".parse());
- assert_eq!(
- Ok(sa6(Ipv6Addr::new(0x2a02, 0x6b8, 0, 1, 0, 0, 0, 1), 53)),
- "[2a02:6b8:0:1::1]:53".parse()
- );
- assert_eq!(
- Ok(SocketAddrV6::new(Ipv6Addr::new(0x2a02, 0x6b8, 0, 1, 0, 0, 0, 1), 53, 0, 0)),
- "[2a02:6b8:0:1::1]:53".parse()
- );
- assert_eq!(Ok(sa6(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0x7F00, 1), 22)), "[::127.0.0.1]:22".parse());
- assert_eq!(
- Ok(SocketAddrV6::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0x7F00, 1), 22, 0, 0)),
- "[::127.0.0.1]:22".parse()
- );
-
- // without port
- let none: Option<SocketAddr> = "127.0.0.1".parse().ok();
- assert_eq!(None, none);
- // without port
- let none: Option<SocketAddr> = "127.0.0.1:".parse().ok();
- assert_eq!(None, none);
- // wrong brackets around v4
- let none: Option<SocketAddr> = "[127.0.0.1]:22".parse().ok();
- assert_eq!(None, none);
- // port out of range
- let none: Option<SocketAddr> = "127.0.0.1:123456".parse().ok();
- assert_eq!(None, none);
-}
-
-#[test]
-fn ipv4_addr_to_string() {
- assert_eq!(Ipv4Addr::new(127, 0, 0, 1).to_string(), "127.0.0.1");
- // Short address
- assert_eq!(Ipv4Addr::new(1, 1, 1, 1).to_string(), "1.1.1.1");
- // Long address
- assert_eq!(Ipv4Addr::new(127, 127, 127, 127).to_string(), "127.127.127.127");
-
- // Test padding
- assert_eq!(&format!("{:16}", Ipv4Addr::new(1, 1, 1, 1)), "1.1.1.1 ");
- assert_eq!(&format!("{:>16}", Ipv4Addr::new(1, 1, 1, 1)), " 1.1.1.1");
-}
-
-#[test]
-fn ipv6_addr_to_string() {
- // ipv4-mapped address
- let a1 = Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc000, 0x280);
- assert_eq!(a1.to_string(), "::ffff:192.0.2.128");
-
- // ipv4-compatible address
- let a1 = Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0xc000, 0x280);
- assert_eq!(a1.to_string(), "::192.0.2.128");
-
- // v6 address with no zero segments
- assert_eq!(Ipv6Addr::new(8, 9, 10, 11, 12, 13, 14, 15).to_string(), "8:9:a:b:c:d:e:f");
-
- // longest possible IPv6 length
- assert_eq!(
- Ipv6Addr::new(0x1111, 0x2222, 0x3333, 0x4444, 0x5555, 0x6666, 0x7777, 0x8888).to_string(),
- "1111:2222:3333:4444:5555:6666:7777:8888"
- );
- // padding
- assert_eq!(&format!("{:20}", Ipv6Addr::new(1, 2, 3, 4, 5, 6, 7, 8)), "1:2:3:4:5:6:7:8 ");
- assert_eq!(&format!("{:>20}", Ipv6Addr::new(1, 2, 3, 4, 5, 6, 7, 8)), " 1:2:3:4:5:6:7:8");
-
- // reduce a single run of zeros
- assert_eq!(
- "ae::ffff:102:304",
- Ipv6Addr::new(0xae, 0, 0, 0, 0, 0xffff, 0x0102, 0x0304).to_string()
- );
-
- // don't reduce just a single zero segment
- assert_eq!("1:2:3:4:5:6:0:8", Ipv6Addr::new(1, 2, 3, 4, 5, 6, 0, 8).to_string());
-
- // 'any' address
- assert_eq!("::", Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0).to_string());
-
- // loopback address
- assert_eq!("::1", Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1).to_string());
-
- // ends in zeros
- assert_eq!("1::", Ipv6Addr::new(1, 0, 0, 0, 0, 0, 0, 0).to_string());
-
- // two runs of zeros, second one is longer
- assert_eq!("1:0:0:4::8", Ipv6Addr::new(1, 0, 0, 4, 0, 0, 0, 8).to_string());
-
- // two runs of zeros, equal length
- assert_eq!("1::4:5:0:0:8", Ipv6Addr::new(1, 0, 0, 4, 5, 0, 0, 8).to_string());
-
- // don't prefix `0x` to each segment in `dbg!`.
- assert_eq!("1::4:5:0:0:8", &format!("{:#?}", Ipv6Addr::new(1, 0, 0, 4, 5, 0, 0, 8)));
-}
-
-#[test]
-fn ipv4_to_ipv6() {
- assert_eq!(
- Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0x1234, 0x5678),
- Ipv4Addr::new(0x12, 0x34, 0x56, 0x78).to_ipv6_mapped()
- );
- assert_eq!(
- Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0x1234, 0x5678),
- Ipv4Addr::new(0x12, 0x34, 0x56, 0x78).to_ipv6_compatible()
- );
-}
-
-#[test]
-fn ipv6_to_ipv4_mapped() {
- assert_eq!(
- Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0x1234, 0x5678).to_ipv4_mapped(),
- Some(Ipv4Addr::new(0x12, 0x34, 0x56, 0x78))
- );
- assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0x1234, 0x5678).to_ipv4_mapped(), None);
-}
-
-#[test]
-fn ipv6_to_ipv4() {
- assert_eq!(
- Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0x1234, 0x5678).to_ipv4(),
- Some(Ipv4Addr::new(0x12, 0x34, 0x56, 0x78))
- );
- assert_eq!(
- Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0x1234, 0x5678).to_ipv4(),
- Some(Ipv4Addr::new(0x12, 0x34, 0x56, 0x78))
- );
- assert_eq!(Ipv6Addr::new(0, 0, 1, 0, 0, 0, 0x1234, 0x5678).to_ipv4(), None);
-}
-
-#[test]
-fn ip_properties() {
- macro_rules! ip {
- ($s:expr) => {
- IpAddr::from_str($s).unwrap()
- };
- }
-
- macro_rules! check {
- ($s:expr) => {
- check!($s, 0);
- };
-
- ($s:expr, $mask:expr) => {{
- let unspec: u8 = 1 << 0;
- let loopback: u8 = 1 << 1;
- 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());
- } else {
- assert!(!ip!($s).is_unspecified());
- }
-
- if ($mask & loopback) == loopback {
- assert!(ip!($s).is_loopback());
- } else {
- assert!(!ip!($s).is_loopback());
- }
-
- if ($mask & global) == global {
- assert!(ip!($s).is_global());
- } else {
- assert!(!ip!($s).is_global());
- }
-
- if ($mask & multicast) == multicast {
- assert!(ip!($s).is_multicast());
- } else {
- assert!(!ip!($s).is_multicast());
- }
-
- if ($mask & doc) == doc {
- assert!(ip!($s).is_documentation());
- } else {
- assert!(!ip!($s).is_documentation());
- }
-
- if ($mask & benchmarking) == benchmarking {
- assert!(ip!($s).is_benchmarking());
- } else {
- assert!(!ip!($s).is_benchmarking());
- }
- }};
- }
-
- let unspec: u8 = 1 << 0;
- let loopback: u8 = 1 << 1;
- 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");
- check!("0.1.0.0");
- check!("10.9.8.7");
- check!("127.1.2.3", loopback);
- check!("172.31.254.253");
- check!("169.254.253.242");
- check!("192.0.2.183", doc);
- check!("192.1.2.183", global);
- check!("192.168.254.253");
- check!("198.51.100.0", doc);
- check!("203.0.113.0", doc);
- check!("203.2.113.0", global);
- check!("224.0.0.0", global | multicast);
- check!("239.255.255.255", global | multicast);
- check!("255.255.255.255");
- // make sure benchmarking addresses are not global
- 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");
- check!("192.0.0.100");
- // make sure reserved addresses are not global
- check!("240.0.0.0");
- check!("251.54.1.76");
- check!("254.255.255.255");
- // make sure shared addresses are not global
- check!("100.64.0.0");
- check!("100.127.255.255");
- check!("100.100.100.0");
-
- check!("::", unspec);
- check!("::1", loopback);
- check!("::0.0.0.2", global);
- check!("1::", global);
- check!("fc00::");
- check!("fdff:ffff::");
- check!("fe80:ffff::");
- check!("febf:ffff::");
- check!("fec0::", global);
- check!("ff01::", global | multicast);
- check!("ff02::", global | multicast);
- check!("ff03::", global | multicast);
- check!("ff04::", global | multicast);
- check!("ff05::", global | multicast);
- check!("ff08::", global | multicast);
- check!("ff0e::", global | multicast);
- check!("2001:db8:85a3::8a2e:370:7334", doc);
- check!("2001:2::ac32:23ff:21", benchmarking);
- check!("102:304:506:708:90a:b0c:d0e:f10", global);
-}
-
-#[test]
-fn ipv4_properties() {
- macro_rules! ip {
- ($s:expr) => {
- Ipv4Addr::from_str($s).unwrap()
- };
- }
-
- macro_rules! check {
- ($s:expr) => {
- check!($s, 0);
- };
-
- ($s:expr, $mask:expr) => {{
- let unspec: u16 = 1 << 0;
- let loopback: u16 = 1 << 1;
- let private: u16 = 1 << 2;
- let link_local: u16 = 1 << 3;
- let global: u16 = 1 << 4;
- let multicast: u16 = 1 << 5;
- let broadcast: u16 = 1 << 6;
- let documentation: u16 = 1 << 7;
- let benchmarking: u16 = 1 << 8;
- let reserved: u16 = 1 << 10;
- let shared: u16 = 1 << 11;
-
- if ($mask & unspec) == unspec {
- assert!(ip!($s).is_unspecified());
- } else {
- assert!(!ip!($s).is_unspecified());
- }
-
- if ($mask & loopback) == loopback {
- assert!(ip!($s).is_loopback());
- } else {
- assert!(!ip!($s).is_loopback());
- }
-
- if ($mask & private) == private {
- assert!(ip!($s).is_private());
- } else {
- assert!(!ip!($s).is_private());
- }
-
- if ($mask & link_local) == link_local {
- assert!(ip!($s).is_link_local());
- } else {
- assert!(!ip!($s).is_link_local());
- }
-
- if ($mask & global) == global {
- assert!(ip!($s).is_global());
- } else {
- assert!(!ip!($s).is_global());
- }
-
- if ($mask & multicast) == multicast {
- assert!(ip!($s).is_multicast());
- } else {
- assert!(!ip!($s).is_multicast());
- }
-
- if ($mask & broadcast) == broadcast {
- assert!(ip!($s).is_broadcast());
- } else {
- assert!(!ip!($s).is_broadcast());
- }
-
- if ($mask & documentation) == documentation {
- assert!(ip!($s).is_documentation());
- } else {
- assert!(!ip!($s).is_documentation());
- }
-
- if ($mask & benchmarking) == benchmarking {
- assert!(ip!($s).is_benchmarking());
- } else {
- assert!(!ip!($s).is_benchmarking());
- }
-
- if ($mask & reserved) == reserved {
- assert!(ip!($s).is_reserved());
- } else {
- assert!(!ip!($s).is_reserved());
- }
-
- if ($mask & shared) == shared {
- assert!(ip!($s).is_shared());
- } else {
- assert!(!ip!($s).is_shared());
- }
- }};
- }
-
- let unspec: u16 = 1 << 0;
- let loopback: u16 = 1 << 1;
- let private: u16 = 1 << 2;
- let link_local: u16 = 1 << 3;
- let global: u16 = 1 << 4;
- let multicast: u16 = 1 << 5;
- let broadcast: u16 = 1 << 6;
- let documentation: u16 = 1 << 7;
- let benchmarking: u16 = 1 << 8;
- let reserved: u16 = 1 << 10;
- let shared: u16 = 1 << 11;
-
- check!("0.0.0.0", unspec);
- check!("0.0.0.1");
- check!("0.1.0.0");
- check!("10.9.8.7", private);
- check!("127.1.2.3", loopback);
- check!("172.31.254.253", private);
- check!("169.254.253.242", link_local);
- check!("192.0.2.183", documentation);
- check!("192.1.2.183", global);
- check!("192.168.254.253", private);
- check!("198.51.100.0", documentation);
- check!("203.0.113.0", documentation);
- check!("203.2.113.0", global);
- check!("224.0.0.0", global | multicast);
- check!("239.255.255.255", global | multicast);
- check!("255.255.255.255", broadcast);
- check!("198.18.0.0", benchmarking);
- check!("198.18.54.2", benchmarking);
- check!("198.19.255.255", benchmarking);
- check!("192.0.0.0");
- check!("192.0.0.255");
- check!("192.0.0.100");
- check!("240.0.0.0", reserved);
- check!("251.54.1.76", reserved);
- check!("254.255.255.255", reserved);
- check!("100.64.0.0", shared);
- check!("100.127.255.255", shared);
- check!("100.100.100.0", shared);
-}
-
-#[test]
-fn ipv6_properties() {
- macro_rules! ip {
- ($s:expr) => {
- Ipv6Addr::from_str($s).unwrap()
- };
- }
-
- macro_rules! check {
- ($s:expr, &[$($octet:expr),*], $mask:expr) => {
- assert_eq!($s, ip!($s).to_string());
- let octets = &[$($octet),*];
- assert_eq!(&ip!($s).octets(), octets);
- assert_eq!(Ipv6Addr::from(*octets), ip!($s));
-
- 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
- | multicast_realm_local
- | multicast_site_local
- | multicast_organization_local;
-
- if ($mask & unspecified) == unspecified {
- assert!(ip!($s).is_unspecified());
- } else {
- assert!(!ip!($s).is_unspecified());
- }
- if ($mask & loopback) == loopback {
- assert!(ip!($s).is_loopback());
- } else {
- assert!(!ip!($s).is_loopback());
- }
- if ($mask & unique_local) == unique_local {
- assert!(ip!($s).is_unique_local());
- } else {
- assert!(!ip!($s).is_unique_local());
- }
- if ($mask & global) == global {
- assert!(ip!($s).is_global());
- } else {
- assert!(!ip!($s).is_global());
- }
- if ($mask & unicast_link_local) == unicast_link_local {
- assert!(ip!($s).is_unicast_link_local());
- } else {
- assert!(!ip!($s).is_unicast_link_local());
- }
- if ($mask & unicast_global) == unicast_global {
- assert!(ip!($s).is_unicast_global());
- } else {
- assert!(!ip!($s).is_unicast_global());
- }
- if ($mask & documentation) == documentation {
- assert!(ip!($s).is_documentation());
- } 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());
- } else {
- assert!(ip!($s).multicast_scope().is_none());
- assert!(!ip!($s).is_multicast());
- }
- if ($mask & multicast_interface_local) == multicast_interface_local {
- assert_eq!(ip!($s).multicast_scope().unwrap(),
- Ipv6MulticastScope::InterfaceLocal);
- }
- if ($mask & multicast_link_local) == multicast_link_local {
- assert_eq!(ip!($s).multicast_scope().unwrap(),
- Ipv6MulticastScope::LinkLocal);
- }
- if ($mask & multicast_realm_local) == multicast_realm_local {
- assert_eq!(ip!($s).multicast_scope().unwrap(),
- Ipv6MulticastScope::RealmLocal);
- }
- if ($mask & multicast_admin_local) == multicast_admin_local {
- assert_eq!(ip!($s).multicast_scope().unwrap(),
- Ipv6MulticastScope::AdminLocal);
- }
- if ($mask & multicast_site_local) == multicast_site_local {
- assert_eq!(ip!($s).multicast_scope().unwrap(),
- Ipv6MulticastScope::SiteLocal);
- }
- if ($mask & multicast_organization_local) == multicast_organization_local {
- assert_eq!(ip!($s).multicast_scope().unwrap(),
- Ipv6MulticastScope::OrganizationLocal);
- }
- if ($mask & multicast_global) == multicast_global {
- assert_eq!(ip!($s).multicast_scope().unwrap(),
- Ipv6MulticastScope::Global);
- }
- }
- }
-
- 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);
-
- check!("::1", &[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], loopback);
-
- check!("::0.0.0.2", &[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2], global | unicast_global);
-
- check!("1::", &[0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], global | unicast_global);
-
- check!(
- "::ffff:127.0.0.1",
- &[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff, 0x7f, 0, 0, 1],
- unicast_global
- );
-
- check!(
- "64:ff9b:1::",
- &[0, 0x64, 0xff, 0x9b, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
- unicast_global
- );
-
- check!("100::", &[0x01, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], unicast_global);
-
- check!("2001::", &[0x20, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], unicast_global);
-
- check!(
- "2001:1::1",
- &[0x20, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
- global | unicast_global
- );
-
- check!(
- "2001:1::2",
- &[0x20, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2],
- global | unicast_global
- );
-
- check!(
- "2001:3::",
- &[0x20, 1, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
- global | unicast_global
- );
-
- check!(
- "2001:4:112::",
- &[0x20, 1, 0, 4, 1, 0x12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
- global | unicast_global
- );
-
- check!(
- "2001:20::",
- &[0x20, 1, 0, 0x20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
- global | unicast_global
- );
-
- check!("2001:30::", &[0x20, 1, 0, 0x30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], unicast_global);
-
- check!(
- "2001:200::",
- &[0x20, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
- global | unicast_global
- );
-
- check!("fc00::", &[0xfc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], unique_local);
-
- check!(
- "fdff:ffff::",
- &[0xfd, 0xff, 0xff, 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
- unique_local
- );
-
- check!(
- "fe80:ffff::",
- &[0xfe, 0x80, 0xff, 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
- unicast_link_local
- );
-
- check!("fe80::", &[0xfe, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], unicast_link_local);
-
- check!(
- "febf:ffff::",
- &[0xfe, 0xbf, 0xff, 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
- unicast_link_local
- );
-
- check!("febf::", &[0xfe, 0xbf, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], unicast_link_local);
-
- check!(
- "febf:ffff:ffff:ffff:ffff:ffff:ffff:ffff",
- &[
- 0xfe, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff
- ],
- unicast_link_local
- );
-
- check!(
- "fe80::ffff:ffff:ffff:ffff",
- &[
- 0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff
- ],
- unicast_link_local
- );
-
- check!(
- "fe80:0:0:1::",
- &[0xfe, 0x80, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0],
- unicast_link_local
- );
-
- check!(
- "fec0::",
- &[0xfe, 0xc0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
- unicast_global | global
- );
-
- check!(
- "ff01::",
- &[0xff, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
- multicast_interface_local | global
- );
-
- check!(
- "ff02::",
- &[0xff, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
- multicast_link_local | global
- );
-
- check!(
- "ff03::",
- &[0xff, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
- multicast_realm_local | global
- );
-
- check!(
- "ff04::",
- &[0xff, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
- multicast_admin_local | global
- );
-
- check!(
- "ff05::",
- &[0xff, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
- multicast_site_local | global
- );
-
- check!(
- "ff08::",
- &[0xff, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
- multicast_organization_local | global
- );
-
- check!(
- "ff0e::",
- &[0xff, 0xe, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
- multicast_global | global
- );
-
- check!(
- "2001:db8:85a3::8a2e:370:7334",
- &[0x20, 1, 0xd, 0xb8, 0x85, 0xa3, 0, 0, 0, 0, 0x8a, 0x2e, 3, 0x70, 0x73, 0x34],
- documentation
- );
-
- check!(
- "2001:2::ac32:23ff:21",
- &[0x20, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0xac, 0x32, 0x23, 0xff, 0, 0x21],
- 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],
- global | unicast_global
- );
-}
+use crate::net::test::{sa4, tsa};
+use crate::net::Ipv4Addr;
#[test]
fn to_socket_addr_socketaddr() {
let a = sa4(Ipv4Addr::new(77, 88, 21, 11), 12345);
assert_eq!(Ok(vec![a]), tsa(a));
}
-
-#[test]
-fn test_ipv4_to_int() {
- let a = Ipv4Addr::new(0x11, 0x22, 0x33, 0x44);
- assert_eq!(u32::from(a), 0x11223344);
-}
-
-#[test]
-fn test_int_to_ipv4() {
- let a = Ipv4Addr::new(0x11, 0x22, 0x33, 0x44);
- assert_eq!(Ipv4Addr::from(0x11223344), a);
-}
-
-#[test]
-fn test_ipv6_to_int() {
- let a = Ipv6Addr::new(0x1122, 0x3344, 0x5566, 0x7788, 0x99aa, 0xbbcc, 0xddee, 0xff11);
- assert_eq!(u128::from(a), 0x112233445566778899aabbccddeeff11u128);
-}
-
-#[test]
-fn test_int_to_ipv6() {
- let a = Ipv6Addr::new(0x1122, 0x3344, 0x5566, 0x7788, 0x99aa, 0xbbcc, 0xddee, 0xff11);
- assert_eq!(Ipv6Addr::from(0x112233445566778899aabbccddeeff11u128), a);
-}
-
-#[test]
-fn ipv4_from_constructors() {
- assert_eq!(Ipv4Addr::LOCALHOST, Ipv4Addr::new(127, 0, 0, 1));
- assert!(Ipv4Addr::LOCALHOST.is_loopback());
- assert_eq!(Ipv4Addr::UNSPECIFIED, Ipv4Addr::new(0, 0, 0, 0));
- assert!(Ipv4Addr::UNSPECIFIED.is_unspecified());
- assert_eq!(Ipv4Addr::BROADCAST, Ipv4Addr::new(255, 255, 255, 255));
- assert!(Ipv4Addr::BROADCAST.is_broadcast());
-}
-
-#[test]
-fn ipv6_from_constructors() {
- assert_eq!(Ipv6Addr::LOCALHOST, Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1));
- assert!(Ipv6Addr::LOCALHOST.is_loopback());
- assert_eq!(Ipv6Addr::UNSPECIFIED, Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0));
- assert!(Ipv6Addr::UNSPECIFIED.is_unspecified());
-}
-
-#[test]
-fn ipv4_from_octets() {
- assert_eq!(Ipv4Addr::from([127, 0, 0, 1]), Ipv4Addr::new(127, 0, 0, 1))
-}
-
-#[test]
-fn ipv6_from_segments() {
- let from_u16s =
- Ipv6Addr::from([0x0011, 0x2233, 0x4455, 0x6677, 0x8899, 0xaabb, 0xccdd, 0xeeff]);
- let new = Ipv6Addr::new(0x0011, 0x2233, 0x4455, 0x6677, 0x8899, 0xaabb, 0xccdd, 0xeeff);
- assert_eq!(new, from_u16s);
-}
-
-#[test]
-fn ipv6_from_octets() {
- let from_u16s =
- Ipv6Addr::from([0x0011, 0x2233, 0x4455, 0x6677, 0x8899, 0xaabb, 0xccdd, 0xeeff]);
- let from_u8s = Ipv6Addr::from([
- 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee,
- 0xff,
- ]);
- assert_eq!(from_u16s, from_u8s);
-}
-
-#[test]
-fn cmp() {
- let v41 = Ipv4Addr::new(100, 64, 3, 3);
- let v42 = Ipv4Addr::new(192, 0, 2, 2);
- let v61 = "2001:db8:f00::1002".parse::<Ipv6Addr>().unwrap();
- let v62 = "2001:db8:f00::2001".parse::<Ipv6Addr>().unwrap();
- assert!(v41 < v42);
- assert!(v61 < v62);
-
- assert_eq!(v41, IpAddr::V4(v41));
- assert_eq!(v61, IpAddr::V6(v61));
- assert!(v41 != IpAddr::V4(v42));
- assert!(v61 != IpAddr::V6(v62));
-
- assert!(v41 < IpAddr::V4(v42));
- assert!(v61 < IpAddr::V6(v62));
- assert!(IpAddr::V4(v41) < v42);
- assert!(IpAddr::V6(v61) < v62);
-
- assert!(v41 < IpAddr::V6(v61));
- assert!(IpAddr::V4(v41) < v61);
-}
-
-#[test]
-fn is_v4() {
- let ip = IpAddr::V4(Ipv4Addr::new(100, 64, 3, 3));
- assert!(ip.is_ipv4());
- assert!(!ip.is_ipv6());
-}
-
-#[test]
-fn is_v6() {
- let ip = IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0x1234, 0x5678));
- assert!(!ip.is_ipv4());
- assert!(ip.is_ipv6());
-}
-
-#[test]
-fn ipv4_const() {
- // test that the methods of `Ipv4Addr` are usable in a const context
-
- const IP_ADDRESS: Ipv4Addr = Ipv4Addr::new(127, 0, 0, 1);
- assert_eq!(IP_ADDRESS, Ipv4Addr::LOCALHOST);
-
- const OCTETS: [u8; 4] = IP_ADDRESS.octets();
- assert_eq!(OCTETS, [127, 0, 0, 1]);
-
- const IS_UNSPECIFIED: bool = IP_ADDRESS.is_unspecified();
- assert!(!IS_UNSPECIFIED);
-
- const IS_LOOPBACK: bool = IP_ADDRESS.is_loopback();
- assert!(IS_LOOPBACK);
-
- const IS_PRIVATE: bool = IP_ADDRESS.is_private();
- assert!(!IS_PRIVATE);
-
- const IS_LINK_LOCAL: bool = IP_ADDRESS.is_link_local();
- assert!(!IS_LINK_LOCAL);
-
- const IS_GLOBAL: bool = IP_ADDRESS.is_global();
- assert!(!IS_GLOBAL);
-
- const IS_SHARED: bool = IP_ADDRESS.is_shared();
- assert!(!IS_SHARED);
-
- const IS_BENCHMARKING: bool = IP_ADDRESS.is_benchmarking();
- assert!(!IS_BENCHMARKING);
-
- const IS_RESERVED: bool = IP_ADDRESS.is_reserved();
- assert!(!IS_RESERVED);
-
- const IS_MULTICAST: bool = IP_ADDRESS.is_multicast();
- assert!(!IS_MULTICAST);
-
- const IS_BROADCAST: bool = IP_ADDRESS.is_broadcast();
- assert!(!IS_BROADCAST);
-
- const IS_DOCUMENTATION: bool = IP_ADDRESS.is_documentation();
- assert!(!IS_DOCUMENTATION);
-
- const IP_V6_COMPATIBLE: Ipv6Addr = IP_ADDRESS.to_ipv6_compatible();
- assert_eq!(
- IP_V6_COMPATIBLE,
- Ipv6Addr::from([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 127, 0, 0, 1])
- );
-
- const IP_V6_MAPPED: Ipv6Addr = IP_ADDRESS.to_ipv6_mapped();
- assert_eq!(
- IP_V6_MAPPED,
- Ipv6Addr::from([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 127, 0, 0, 1])
- );
-}
-
-#[test]
-fn ipv6_const() {
- // test that the methods of `Ipv6Addr` are usable in a const context
-
- const IP_ADDRESS: Ipv6Addr = Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1);
- assert_eq!(IP_ADDRESS, Ipv6Addr::LOCALHOST);
-
- const SEGMENTS: [u16; 8] = IP_ADDRESS.segments();
- assert_eq!(SEGMENTS, [0, 0, 0, 0, 0, 0, 0, 1]);
-
- const OCTETS: [u8; 16] = IP_ADDRESS.octets();
- assert_eq!(OCTETS, [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]);
-
- const IS_UNSPECIFIED: bool = IP_ADDRESS.is_unspecified();
- assert!(!IS_UNSPECIFIED);
-
- const IS_LOOPBACK: bool = IP_ADDRESS.is_loopback();
- assert!(IS_LOOPBACK);
-
- const IS_GLOBAL: bool = IP_ADDRESS.is_global();
- assert!(!IS_GLOBAL);
-
- const IS_UNIQUE_LOCAL: bool = IP_ADDRESS.is_unique_local();
- assert!(!IS_UNIQUE_LOCAL);
-
- const IS_UNICAST_LINK_LOCAL: bool = IP_ADDRESS.is_unicast_link_local();
- assert!(!IS_UNICAST_LINK_LOCAL);
-
- 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);
-
- const MULTICAST_SCOPE: Option<Ipv6MulticastScope> = IP_ADDRESS.multicast_scope();
- assert_eq!(MULTICAST_SCOPE, None);
-
- const IS_MULTICAST: bool = IP_ADDRESS.is_multicast();
- assert!(!IS_MULTICAST);
-
- const IP_V4: Option<Ipv4Addr> = IP_ADDRESS.to_ipv4();
- assert_eq!(IP_V4.unwrap(), Ipv4Addr::new(0, 0, 0, 1));
-}
-
-#[test]
-fn ip_const() {
- // test that the methods of `IpAddr` are usable in a const context
-
- const IP_ADDRESS: IpAddr = IpAddr::V4(Ipv4Addr::LOCALHOST);
-
- const IS_UNSPECIFIED: bool = IP_ADDRESS.is_unspecified();
- assert!(!IS_UNSPECIFIED);
-
- const IS_LOOPBACK: bool = IP_ADDRESS.is_loopback();
- assert!(IS_LOOPBACK);
-
- const IS_GLOBAL: bool = IP_ADDRESS.is_global();
- assert!(!IS_GLOBAL);
-
- const IS_MULTICAST: bool = IP_ADDRESS.is_multicast();
- assert!(!IS_MULTICAST);
-
- const IS_IP_V4: bool = IP_ADDRESS.is_ipv4();
- assert!(IS_IP_V4);
-
- const IS_IP_V6: bool = IP_ADDRESS.is_ipv6();
- assert!(!IS_IP_V6);
-}
-
-#[test]
-fn structural_match() {
- // test that all IP types can be structurally matched upon
-
- const IPV4: Ipv4Addr = Ipv4Addr::LOCALHOST;
- match IPV4 {
- Ipv4Addr::LOCALHOST => {}
- _ => unreachable!(),
- }
-
- const IPV6: Ipv6Addr = Ipv6Addr::LOCALHOST;
- match IPV6 {
- Ipv6Addr::LOCALHOST => {}
- _ => unreachable!(),
- }
-
- const IP: IpAddr = IpAddr::V4(Ipv4Addr::LOCALHOST);
- match IP {
- IpAddr::V4(Ipv4Addr::LOCALHOST) => {}
- _ => unreachable!(),
- }
-}
diff --git a/library/std/src/net/mod.rs b/library/std/src/net/mod.rs
index 19d90e7ec..bcab15db3 100644
--- a/library/std/src/net/mod.rs
+++ b/library/std/src/net/mod.rs
@@ -26,8 +26,6 @@ use crate::io::{self, ErrorKind};
#[stable(feature = "rust1", since = "1.0.0")]
pub use self::ip_addr::{IpAddr, Ipv4Addr, Ipv6Addr, Ipv6MulticastScope};
#[stable(feature = "rust1", since = "1.0.0")]
-pub use self::parser::AddrParseError;
-#[stable(feature = "rust1", since = "1.0.0")]
pub use self::socket_addr::{SocketAddr, SocketAddrV4, SocketAddrV6, ToSocketAddrs};
#[unstable(feature = "tcplistener_into_incoming", issue = "88339")]
pub use self::tcp::IntoIncoming;
@@ -35,10 +33,10 @@ pub use self::tcp::IntoIncoming;
pub use self::tcp::{Incoming, TcpListener, TcpStream};
#[stable(feature = "rust1", since = "1.0.0")]
pub use self::udp::UdpSocket;
+#[stable(feature = "rust1", since = "1.0.0")]
+pub use core::net::AddrParseError;
-mod display_buffer;
mod ip_addr;
-mod parser;
mod socket_addr;
mod tcp;
#[cfg(test)]
diff --git a/library/std/src/net/socket_addr.rs b/library/std/src/net/socket_addr.rs
index 33b0dfa03..421fed907 100644
--- a/library/std/src/net/socket_addr.rs
+++ b/library/std/src/net/socket_addr.rs
@@ -1,9 +1,7 @@
+// Tests for this module
#[cfg(all(test, not(target_os = "emscripten")))]
mod tests;
-use crate::cmp::Ordering;
-use crate::fmt::{self, Write};
-use crate::hash;
use crate::io;
use crate::iter;
use crate::mem;
@@ -15,533 +13,23 @@ use crate::sys_common::net::LookupHost;
use crate::sys_common::{FromInner, IntoInner};
use crate::vec;
-use super::display_buffer::DisplayBuffer;
-
-/// An internet socket address, either IPv4 or IPv6.
-///
-/// Internet socket addresses consist of an [IP address], a 16-bit port number, as well
-/// as possibly some version-dependent additional information. See [`SocketAddrV4`]'s and
-/// [`SocketAddrV6`]'s respective documentation for more details.
-///
-/// The size of a `SocketAddr` instance may vary depending on the target operating
-/// system.
-///
-/// [IP address]: IpAddr
-///
-/// # Examples
-///
-/// ```
-/// use std::net::{IpAddr, Ipv4Addr, SocketAddr};
-///
-/// let socket = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8080);
-///
-/// assert_eq!("127.0.0.1:8080".parse(), Ok(socket));
-/// assert_eq!(socket.port(), 8080);
-/// assert_eq!(socket.is_ipv4(), true);
-/// ```
-#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
-#[stable(feature = "rust1", since = "1.0.0")]
-pub enum SocketAddr {
- /// An IPv4 socket address.
- #[stable(feature = "rust1", since = "1.0.0")]
- V4(#[stable(feature = "rust1", since = "1.0.0")] SocketAddrV4),
- /// An IPv6 socket address.
- #[stable(feature = "rust1", since = "1.0.0")]
- V6(#[stable(feature = "rust1", since = "1.0.0")] SocketAddrV6),
-}
-
-/// An IPv4 socket address.
-///
-/// IPv4 socket addresses consist of an [`IPv4` address] and a 16-bit port number, as
-/// stated in [IETF RFC 793].
-///
-/// See [`SocketAddr`] for a type encompassing both IPv4 and IPv6 socket addresses.
-///
-/// The size of a `SocketAddrV4` struct may vary depending on the target operating
-/// system. Do not assume that this type has the same memory layout as the underlying
-/// system representation.
-///
-/// [IETF RFC 793]: https://tools.ietf.org/html/rfc793
-/// [`IPv4` address]: Ipv4Addr
-///
-/// # Examples
-///
-/// ```
-/// use std::net::{Ipv4Addr, SocketAddrV4};
-///
-/// let socket = SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), 8080);
-///
-/// assert_eq!("127.0.0.1:8080".parse(), Ok(socket));
-/// assert_eq!(socket.ip(), &Ipv4Addr::new(127, 0, 0, 1));
-/// assert_eq!(socket.port(), 8080);
-/// ```
-#[derive(Copy, Clone, Eq, PartialEq)]
-#[stable(feature = "rust1", since = "1.0.0")]
-pub struct SocketAddrV4 {
- ip: Ipv4Addr,
- port: u16,
-}
-
-/// An IPv6 socket address.
-///
-/// IPv6 socket addresses consist of an [`IPv6` address], a 16-bit port number, as well
-/// as fields containing the traffic class, the flow label, and a scope identifier
-/// (see [IETF RFC 2553, Section 3.3] for more details).
-///
-/// See [`SocketAddr`] for a type encompassing both IPv4 and IPv6 socket addresses.
-///
-/// The size of a `SocketAddrV6` struct may vary depending on the target operating
-/// system. Do not assume that this type has the same memory layout as the underlying
-/// system representation.
-///
-/// [IETF RFC 2553, Section 3.3]: https://tools.ietf.org/html/rfc2553#section-3.3
-/// [`IPv6` address]: Ipv6Addr
-///
-/// # Examples
-///
-/// ```
-/// use std::net::{Ipv6Addr, SocketAddrV6};
-///
-/// let socket = SocketAddrV6::new(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 1), 8080, 0, 0);
-///
-/// assert_eq!("[2001:db8::1]:8080".parse(), Ok(socket));
-/// assert_eq!(socket.ip(), &Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 1));
-/// assert_eq!(socket.port(), 8080);
-/// ```
-#[derive(Copy, Clone, Eq, PartialEq)]
#[stable(feature = "rust1", since = "1.0.0")]
-pub struct SocketAddrV6 {
- ip: Ipv6Addr,
- port: u16,
- flowinfo: u32,
- scope_id: u32,
-}
-
-impl SocketAddr {
- /// Creates a new socket address from an [IP address] and a port number.
- ///
- /// [IP address]: IpAddr
- ///
- /// # Examples
- ///
- /// ```
- /// use std::net::{IpAddr, Ipv4Addr, SocketAddr};
- ///
- /// let socket = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8080);
- /// assert_eq!(socket.ip(), IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)));
- /// assert_eq!(socket.port(), 8080);
- /// ```
- #[stable(feature = "ip_addr", since = "1.7.0")]
- #[must_use]
- #[rustc_const_unstable(feature = "const_socketaddr", issue = "82485")]
- pub const fn new(ip: IpAddr, port: u16) -> SocketAddr {
- match ip {
- IpAddr::V4(a) => SocketAddr::V4(SocketAddrV4::new(a, port)),
- IpAddr::V6(a) => SocketAddr::V6(SocketAddrV6::new(a, port, 0, 0)),
- }
- }
-
- /// Returns the IP address associated with this socket address.
- ///
- /// # Examples
- ///
- /// ```
- /// use std::net::{IpAddr, Ipv4Addr, SocketAddr};
- ///
- /// let socket = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8080);
- /// assert_eq!(socket.ip(), IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)));
- /// ```
- #[must_use]
- #[stable(feature = "ip_addr", since = "1.7.0")]
- #[rustc_const_unstable(feature = "const_socketaddr", issue = "82485")]
- pub const fn ip(&self) -> IpAddr {
- match *self {
- SocketAddr::V4(ref a) => IpAddr::V4(*a.ip()),
- SocketAddr::V6(ref a) => IpAddr::V6(*a.ip()),
- }
- }
-
- /// Changes the IP address associated with this socket address.
- ///
- /// # Examples
- ///
- /// ```
- /// use std::net::{IpAddr, Ipv4Addr, SocketAddr};
- ///
- /// let mut socket = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8080);
- /// socket.set_ip(IpAddr::V4(Ipv4Addr::new(10, 10, 0, 1)));
- /// assert_eq!(socket.ip(), IpAddr::V4(Ipv4Addr::new(10, 10, 0, 1)));
- /// ```
- #[stable(feature = "sockaddr_setters", since = "1.9.0")]
- pub fn set_ip(&mut self, new_ip: IpAddr) {
- // `match (*self, new_ip)` would have us mutate a copy of self only to throw it away.
- match (self, new_ip) {
- (&mut SocketAddr::V4(ref mut a), IpAddr::V4(new_ip)) => a.set_ip(new_ip),
- (&mut SocketAddr::V6(ref mut a), IpAddr::V6(new_ip)) => a.set_ip(new_ip),
- (self_, new_ip) => *self_ = Self::new(new_ip, self_.port()),
- }
- }
-
- /// Returns the port number associated with this socket address.
- ///
- /// # Examples
- ///
- /// ```
- /// use std::net::{IpAddr, Ipv4Addr, SocketAddr};
- ///
- /// let socket = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8080);
- /// assert_eq!(socket.port(), 8080);
- /// ```
- #[must_use]
- #[stable(feature = "rust1", since = "1.0.0")]
- #[rustc_const_unstable(feature = "const_socketaddr", issue = "82485")]
- pub const fn port(&self) -> u16 {
- match *self {
- SocketAddr::V4(ref a) => a.port(),
- SocketAddr::V6(ref a) => a.port(),
- }
- }
-
- /// Changes the port number associated with this socket address.
- ///
- /// # Examples
- ///
- /// ```
- /// use std::net::{IpAddr, Ipv4Addr, SocketAddr};
- ///
- /// let mut socket = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8080);
- /// socket.set_port(1025);
- /// assert_eq!(socket.port(), 1025);
- /// ```
- #[stable(feature = "sockaddr_setters", since = "1.9.0")]
- pub fn set_port(&mut self, new_port: u16) {
- match *self {
- SocketAddr::V4(ref mut a) => a.set_port(new_port),
- SocketAddr::V6(ref mut a) => a.set_port(new_port),
- }
- }
-
- /// Returns [`true`] if the [IP address] in this `SocketAddr` is an
- /// [`IPv4` address], and [`false`] otherwise.
- ///
- /// [IP address]: IpAddr
- /// [`IPv4` address]: IpAddr::V4
- ///
- /// # Examples
- ///
- /// ```
- /// use std::net::{IpAddr, Ipv4Addr, SocketAddr};
- ///
- /// let socket = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8080);
- /// 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 {
- matches!(*self, SocketAddr::V4(_))
- }
-
- /// Returns [`true`] if the [IP address] in this `SocketAddr` is an
- /// [`IPv6` address], and [`false`] otherwise.
- ///
- /// [IP address]: IpAddr
- /// [`IPv6` address]: IpAddr::V6
- ///
- /// # Examples
- ///
- /// ```
- /// use std::net::{IpAddr, Ipv6Addr, SocketAddr};
- ///
- /// let socket = SocketAddr::new(IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 65535, 0, 1)), 8080);
- /// 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 {
- matches!(*self, SocketAddr::V6(_))
- }
-}
-
-impl SocketAddrV4 {
- /// Creates a new socket address from an [`IPv4` address] and a port number.
- ///
- /// [`IPv4` address]: Ipv4Addr
- ///
- /// # Examples
- ///
- /// ```
- /// use std::net::{SocketAddrV4, Ipv4Addr};
- ///
- /// let socket = SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), 8080);
- /// ```
- #[stable(feature = "rust1", since = "1.0.0")]
- #[must_use]
- #[rustc_const_unstable(feature = "const_socketaddr", issue = "82485")]
- pub const fn new(ip: Ipv4Addr, port: u16) -> SocketAddrV4 {
- SocketAddrV4 { ip, port }
- }
-
- /// Returns the IP address associated with this socket address.
- ///
- /// # Examples
- ///
- /// ```
- /// use std::net::{SocketAddrV4, Ipv4Addr};
- ///
- /// let socket = SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), 8080);
- /// assert_eq!(socket.ip(), &Ipv4Addr::new(127, 0, 0, 1));
- /// ```
- #[must_use]
- #[stable(feature = "rust1", since = "1.0.0")]
- #[rustc_const_unstable(feature = "const_socketaddr", issue = "82485")]
- pub const fn ip(&self) -> &Ipv4Addr {
- &self.ip
- }
-
- /// Changes the IP address associated with this socket address.
- ///
- /// # Examples
- ///
- /// ```
- /// use std::net::{SocketAddrV4, Ipv4Addr};
- ///
- /// let mut socket = SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), 8080);
- /// socket.set_ip(Ipv4Addr::new(192, 168, 0, 1));
- /// assert_eq!(socket.ip(), &Ipv4Addr::new(192, 168, 0, 1));
- /// ```
- #[stable(feature = "sockaddr_setters", since = "1.9.0")]
- pub fn set_ip(&mut self, new_ip: Ipv4Addr) {
- self.ip = new_ip;
- }
-
- /// Returns the port number associated with this socket address.
- ///
- /// # Examples
- ///
- /// ```
- /// use std::net::{SocketAddrV4, Ipv4Addr};
- ///
- /// let socket = SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), 8080);
- /// assert_eq!(socket.port(), 8080);
- /// ```
- #[must_use]
- #[stable(feature = "rust1", since = "1.0.0")]
- #[rustc_const_unstable(feature = "const_socketaddr", issue = "82485")]
- pub const fn port(&self) -> u16 {
- self.port
- }
-
- /// Changes the port number associated with this socket address.
- ///
- /// # Examples
- ///
- /// ```
- /// use std::net::{SocketAddrV4, Ipv4Addr};
- ///
- /// let mut socket = SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), 8080);
- /// socket.set_port(4242);
- /// assert_eq!(socket.port(), 4242);
- /// ```
- #[stable(feature = "sockaddr_setters", since = "1.9.0")]
- pub fn set_port(&mut self, new_port: u16) {
- self.port = new_port;
- }
-}
-
-impl SocketAddrV6 {
- /// Creates a new socket address from an [`IPv6` address], a 16-bit port number,
- /// and the `flowinfo` and `scope_id` fields.
- ///
- /// For more information on the meaning and layout of the `flowinfo` and `scope_id`
- /// parameters, see [IETF RFC 2553, Section 3.3].
- ///
- /// [IETF RFC 2553, Section 3.3]: https://tools.ietf.org/html/rfc2553#section-3.3
- /// [`IPv6` address]: Ipv6Addr
- ///
- /// # Examples
- ///
- /// ```
- /// use std::net::{SocketAddrV6, Ipv6Addr};
- ///
- /// 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]
- #[rustc_const_unstable(feature = "const_socketaddr", issue = "82485")]
- pub const fn new(ip: Ipv6Addr, port: u16, flowinfo: u32, scope_id: u32) -> SocketAddrV6 {
- SocketAddrV6 { ip, port, flowinfo, scope_id }
- }
-
- /// Returns the IP address associated with this socket address.
- ///
- /// # Examples
- ///
- /// ```
- /// use std::net::{SocketAddrV6, Ipv6Addr};
- ///
- /// let socket = SocketAddrV6::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1), 8080, 0, 0);
- /// assert_eq!(socket.ip(), &Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1));
- /// ```
- #[must_use]
- #[stable(feature = "rust1", since = "1.0.0")]
- #[rustc_const_unstable(feature = "const_socketaddr", issue = "82485")]
- pub const fn ip(&self) -> &Ipv6Addr {
- &self.ip
- }
-
- /// Changes the IP address associated with this socket address.
- ///
- /// # Examples
- ///
- /// ```
- /// use std::net::{SocketAddrV6, Ipv6Addr};
- ///
- /// let mut socket = SocketAddrV6::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1), 8080, 0, 0);
- /// socket.set_ip(Ipv6Addr::new(76, 45, 0, 0, 0, 0, 0, 0));
- /// assert_eq!(socket.ip(), &Ipv6Addr::new(76, 45, 0, 0, 0, 0, 0, 0));
- /// ```
- #[stable(feature = "sockaddr_setters", since = "1.9.0")]
- pub fn set_ip(&mut self, new_ip: Ipv6Addr) {
- self.ip = new_ip;
- }
-
- /// Returns the port number associated with this socket address.
- ///
- /// # Examples
- ///
- /// ```
- /// use std::net::{SocketAddrV6, Ipv6Addr};
- ///
- /// let socket = SocketAddrV6::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1), 8080, 0, 0);
- /// assert_eq!(socket.port(), 8080);
- /// ```
- #[must_use]
- #[stable(feature = "rust1", since = "1.0.0")]
- #[rustc_const_unstable(feature = "const_socketaddr", issue = "82485")]
- pub const fn port(&self) -> u16 {
- self.port
- }
-
- /// Changes the port number associated with this socket address.
- ///
- /// # Examples
- ///
- /// ```
- /// use std::net::{SocketAddrV6, Ipv6Addr};
- ///
- /// let mut socket = SocketAddrV6::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1), 8080, 0, 0);
- /// socket.set_port(4242);
- /// assert_eq!(socket.port(), 4242);
- /// ```
- #[stable(feature = "sockaddr_setters", since = "1.9.0")]
- pub fn set_port(&mut self, new_port: u16) {
- self.port = new_port;
- }
-
- /// Returns the flow information associated with this address.
- ///
- /// This information corresponds to the `sin6_flowinfo` field in C's `netinet/in.h`,
- /// as specified in [IETF RFC 2553, Section 3.3].
- /// It combines information about the flow label and the traffic class as specified
- /// in [IETF RFC 2460], respectively [Section 6] and [Section 7].
- ///
- /// [IETF RFC 2553, Section 3.3]: https://tools.ietf.org/html/rfc2553#section-3.3
- /// [IETF RFC 2460]: https://tools.ietf.org/html/rfc2460
- /// [Section 6]: https://tools.ietf.org/html/rfc2460#section-6
- /// [Section 7]: https://tools.ietf.org/html/rfc2460#section-7
- ///
- /// # Examples
- ///
- /// ```
- /// use std::net::{SocketAddrV6, Ipv6Addr};
- ///
- /// let socket = SocketAddrV6::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1), 8080, 10, 0);
- /// assert_eq!(socket.flowinfo(), 10);
- /// ```
- #[must_use]
- #[stable(feature = "rust1", since = "1.0.0")]
- #[rustc_const_unstable(feature = "const_socketaddr", issue = "82485")]
- pub const fn flowinfo(&self) -> u32 {
- self.flowinfo
- }
-
- /// Changes the flow information associated with this socket address.
- ///
- /// See [`SocketAddrV6::flowinfo`]'s documentation for more details.
- ///
- /// # Examples
- ///
- /// ```
- /// use std::net::{SocketAddrV6, Ipv6Addr};
- ///
- /// let mut socket = SocketAddrV6::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1), 8080, 10, 0);
- /// socket.set_flowinfo(56);
- /// assert_eq!(socket.flowinfo(), 56);
- /// ```
- #[stable(feature = "sockaddr_setters", since = "1.9.0")]
- pub fn set_flowinfo(&mut self, new_flowinfo: u32) {
- self.flowinfo = new_flowinfo;
- }
-
- /// Returns the scope ID associated with this address.
- ///
- /// This information corresponds to the `sin6_scope_id` field in C's `netinet/in.h`,
- /// as specified in [IETF RFC 2553, Section 3.3].
- ///
- /// [IETF RFC 2553, Section 3.3]: https://tools.ietf.org/html/rfc2553#section-3.3
- ///
- /// # Examples
- ///
- /// ```
- /// use std::net::{SocketAddrV6, Ipv6Addr};
- ///
- /// let socket = SocketAddrV6::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1), 8080, 0, 78);
- /// assert_eq!(socket.scope_id(), 78);
- /// ```
- #[must_use]
- #[stable(feature = "rust1", since = "1.0.0")]
- #[rustc_const_unstable(feature = "const_socketaddr", issue = "82485")]
- pub const fn scope_id(&self) -> u32 {
- self.scope_id
- }
-
- /// Changes the scope ID associated with this socket address.
- ///
- /// See [`SocketAddrV6::scope_id`]'s documentation for more details.
- ///
- /// # Examples
- ///
- /// ```
- /// use std::net::{SocketAddrV6, Ipv6Addr};
- ///
- /// let mut socket = SocketAddrV6::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1), 8080, 0, 78);
- /// socket.set_scope_id(42);
- /// assert_eq!(socket.scope_id(), 42);
- /// ```
- #[stable(feature = "sockaddr_setters", since = "1.9.0")]
- pub fn set_scope_id(&mut self, new_scope_id: u32) {
- self.scope_id = new_scope_id;
- }
-}
+pub use core::net::{SocketAddr, SocketAddrV4, SocketAddrV6};
impl FromInner<c::sockaddr_in> for SocketAddrV4 {
fn from_inner(addr: c::sockaddr_in) -> SocketAddrV4 {
- SocketAddrV4 { ip: Ipv4Addr::from_inner(addr.sin_addr), port: u16::from_be(addr.sin_port) }
+ SocketAddrV4::new(Ipv4Addr::from_inner(addr.sin_addr), u16::from_be(addr.sin_port))
}
}
impl FromInner<c::sockaddr_in6> for SocketAddrV6 {
fn from_inner(addr: c::sockaddr_in6) -> SocketAddrV6 {
- SocketAddrV6 {
- ip: Ipv6Addr::from_inner(addr.sin6_addr),
- port: u16::from_be(addr.sin6_port),
- flowinfo: addr.sin6_flowinfo,
- scope_id: addr.sin6_scope_id,
- }
+ SocketAddrV6::new(
+ Ipv6Addr::from_inner(addr.sin6_addr),
+ u16::from_be(addr.sin6_port),
+ addr.sin6_flowinfo,
+ addr.sin6_scope_id,
+ )
}
}
@@ -549,8 +37,8 @@ impl IntoInner<c::sockaddr_in> for SocketAddrV4 {
fn into_inner(self) -> c::sockaddr_in {
c::sockaddr_in {
sin_family: c::AF_INET as c::sa_family_t,
- sin_port: self.port.to_be(),
- sin_addr: self.ip.into_inner(),
+ sin_port: self.port().to_be(),
+ sin_addr: self.ip().into_inner(),
..unsafe { mem::zeroed() }
}
}
@@ -560,162 +48,15 @@ impl IntoInner<c::sockaddr_in6> for SocketAddrV6 {
fn into_inner(self) -> c::sockaddr_in6 {
c::sockaddr_in6 {
sin6_family: c::AF_INET6 as c::sa_family_t,
- sin6_port: self.port.to_be(),
- sin6_addr: self.ip.into_inner(),
- sin6_flowinfo: self.flowinfo,
- sin6_scope_id: self.scope_id,
+ sin6_port: self.port().to_be(),
+ sin6_addr: self.ip().into_inner(),
+ sin6_flowinfo: self.flowinfo(),
+ sin6_scope_id: self.scope_id(),
..unsafe { mem::zeroed() }
}
}
}
-#[stable(feature = "ip_from_ip", since = "1.16.0")]
-impl From<SocketAddrV4> for SocketAddr {
- /// Converts a [`SocketAddrV4`] into a [`SocketAddr::V4`].
- fn from(sock4: SocketAddrV4) -> SocketAddr {
- SocketAddr::V4(sock4)
- }
-}
-
-#[stable(feature = "ip_from_ip", since = "1.16.0")]
-impl From<SocketAddrV6> for SocketAddr {
- /// Converts a [`SocketAddrV6`] into a [`SocketAddr::V6`].
- fn from(sock6: SocketAddrV6) -> SocketAddr {
- SocketAddr::V6(sock6)
- }
-}
-
-#[stable(feature = "addr_from_into_ip", since = "1.17.0")]
-impl<I: Into<IpAddr>> From<(I, u16)> for SocketAddr {
- /// Converts a tuple struct (Into<[`IpAddr`]>, `u16`) into a [`SocketAddr`].
- ///
- /// This conversion creates a [`SocketAddr::V4`] for an [`IpAddr::V4`]
- /// and creates a [`SocketAddr::V6`] for an [`IpAddr::V6`].
- ///
- /// `u16` is treated as port of the newly created [`SocketAddr`].
- fn from(pieces: (I, u16)) -> SocketAddr {
- SocketAddr::new(pieces.0.into(), pieces.1)
- }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl fmt::Display for SocketAddr {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- match *self {
- SocketAddr::V4(ref a) => a.fmt(f),
- SocketAddr::V6(ref a) => a.fmt(f),
- }
- }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl fmt::Debug for SocketAddr {
- fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
- fmt::Display::fmt(self, fmt)
- }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl fmt::Display for SocketAddrV4 {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- // If there are no alignment requirements, write the socket address directly to `f`.
- // Otherwise, write it to a local buffer and then use `f.pad`.
- if f.precision().is_none() && f.width().is_none() {
- write!(f, "{}:{}", self.ip(), self.port())
- } else {
- const LONGEST_IPV4_SOCKET_ADDR: &str = "255.255.255.255:65536";
-
- let mut buf = DisplayBuffer::<{ LONGEST_IPV4_SOCKET_ADDR.len() }>::new();
- // Buffer is long enough for the longest possible IPv4 socket address, so this should never fail.
- write!(buf, "{}:{}", self.ip(), self.port()).unwrap();
-
- f.pad(buf.as_str())
- }
- }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl fmt::Debug for SocketAddrV4 {
- fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
- fmt::Display::fmt(self, fmt)
- }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl fmt::Display for SocketAddrV6 {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- // If there are no alignment requirements, write the socket address directly to `f`.
- // Otherwise, write it to a local buffer and then use `f.pad`.
- if f.precision().is_none() && f.width().is_none() {
- match self.scope_id() {
- 0 => write!(f, "[{}]:{}", self.ip(), self.port()),
- scope_id => write!(f, "[{}%{}]:{}", self.ip(), scope_id, self.port()),
- }
- } else {
- const LONGEST_IPV6_SOCKET_ADDR: &str =
- "[ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff%4294967296]:65536";
-
- let mut buf = DisplayBuffer::<{ LONGEST_IPV6_SOCKET_ADDR.len() }>::new();
- match self.scope_id() {
- 0 => write!(buf, "[{}]:{}", self.ip(), self.port()),
- scope_id => write!(buf, "[{}%{}]:{}", self.ip(), scope_id, self.port()),
- }
- // Buffer is long enough for the longest possible IPv6 socket address, so this should never fail.
- .unwrap();
-
- f.pad(buf.as_str())
- }
- }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl fmt::Debug for SocketAddrV6 {
- fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
- fmt::Display::fmt(self, fmt)
- }
-}
-
-#[stable(feature = "socketaddr_ordering", since = "1.45.0")]
-impl PartialOrd for SocketAddrV4 {
- fn partial_cmp(&self, other: &SocketAddrV4) -> Option<Ordering> {
- Some(self.cmp(other))
- }
-}
-
-#[stable(feature = "socketaddr_ordering", since = "1.45.0")]
-impl PartialOrd for SocketAddrV6 {
- fn partial_cmp(&self, other: &SocketAddrV6) -> Option<Ordering> {
- Some(self.cmp(other))
- }
-}
-
-#[stable(feature = "socketaddr_ordering", since = "1.45.0")]
-impl Ord for SocketAddrV4 {
- fn cmp(&self, other: &SocketAddrV4) -> Ordering {
- self.ip().cmp(other.ip()).then(self.port().cmp(&other.port()))
- }
-}
-
-#[stable(feature = "socketaddr_ordering", since = "1.45.0")]
-impl Ord for SocketAddrV6 {
- fn cmp(&self, other: &SocketAddrV6) -> Ordering {
- self.ip().cmp(other.ip()).then(self.port().cmp(&other.port()))
- }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl hash::Hash for SocketAddrV4 {
- fn hash<H: hash::Hasher>(&self, s: &mut H) {
- (self.port, self.ip).hash(s)
- }
-}
-#[stable(feature = "rust1", since = "1.0.0")]
-impl hash::Hash for SocketAddrV6 {
- fn hash<H: hash::Hasher>(&self, s: &mut H) {
- (self.port, &self.ip, self.flowinfo, self.scope_id).hash(s)
- }
-}
-
/// A trait for objects which can be converted or resolved to one or more
/// [`SocketAddr`] values.
///
diff --git a/library/std/src/net/socket_addr/tests.rs b/library/std/src/net/socket_addr/tests.rs
index 15211f819..dfc6dabbe 100644
--- a/library/std/src/net/socket_addr/tests.rs
+++ b/library/std/src/net/socket_addr/tests.rs
@@ -64,11 +64,11 @@ fn ipv4_socket_addr_to_string() {
// Test padding.
assert_eq!(
- &format!("{:16}", SocketAddrV4::new(Ipv4Addr::new(1, 1, 1, 1), 53)),
+ format!("{:16}", SocketAddrV4::new(Ipv4Addr::new(1, 1, 1, 1), 53)),
"1.1.1.1:53 "
);
assert_eq!(
- &format!("{:>16}", SocketAddrV4::new(Ipv4Addr::new(1, 1, 1, 1), 53)),
+ format!("{:>16}", SocketAddrV4::new(Ipv4Addr::new(1, 1, 1, 1), 53)),
" 1.1.1.1:53"
);
}
@@ -111,11 +111,11 @@ fn ipv6_socket_addr_to_string() {
// Test padding.
assert_eq!(
- &format!("{:22}", SocketAddrV6::new(Ipv6Addr::new(1, 2, 3, 4, 5, 6, 7, 8), 9, 0, 0)),
+ format!("{:22}", SocketAddrV6::new(Ipv6Addr::new(1, 2, 3, 4, 5, 6, 7, 8), 9, 0, 0)),
"[1:2:3:4:5:6:7:8]:9 "
);
assert_eq!(
- &format!("{:>22}", SocketAddrV6::new(Ipv6Addr::new(1, 2, 3, 4, 5, 6, 7, 8), 9, 0, 0)),
+ format!("{:>22}", SocketAddrV6::new(Ipv6Addr::new(1, 2, 3, 4, 5, 6, 7, 8), 9, 0, 0)),
" [1:2:3:4:5:6:7:8]:9"
);
}
diff --git a/library/std/src/net/tcp.rs b/library/std/src/net/tcp.rs
index 69b72a81c..ac09a8059 100644
--- a/library/std/src/net/tcp.rs
+++ b/library/std/src/net/tcp.rs
@@ -829,7 +829,7 @@ impl TcpListener {
/// }
///
/// fn main() -> std::io::Result<()> {
- /// let listener = TcpListener::bind("127.0.0.1:80").unwrap();
+ /// let listener = TcpListener::bind("127.0.0.1:80")?;
///
/// for stream in listener.incoming() {
/// match stream {
diff --git a/library/std/src/net/tcp/tests.rs b/library/std/src/net/tcp/tests.rs
index 8c0adcfb0..e019bc0b6 100644
--- a/library/std/src/net/tcp/tests.rs
+++ b/library/std/src/net/tcp/tests.rs
@@ -670,7 +670,10 @@ fn debug() {
// FIXME: re-enabled openbsd tests once their socket timeout code
// no longer has rounding errors.
// VxWorks ignores SO_SNDTIMEO.
-#[cfg_attr(any(target_os = "netbsd", target_os = "openbsd", target_os = "vxworks"), ignore)]
+#[cfg_attr(
+ any(target_os = "netbsd", target_os = "openbsd", target_os = "vxworks", target_os = "nto"),
+ ignore
+)]
#[cfg_attr(target_env = "sgx", ignore)] // FIXME: https://github.com/fortanix/rust-sgx/issues/31
#[test]
fn timeouts() {
diff --git a/library/std/src/net/udp/tests.rs b/library/std/src/net/udp/tests.rs
index f82904ffb..892fe2ba8 100644
--- a/library/std/src/net/udp/tests.rs
+++ b/library/std/src/net/udp/tests.rs
@@ -180,7 +180,10 @@ fn debug() {
// FIXME: re-enabled openbsd/netbsd tests once their socket timeout code
// no longer has rounding errors.
// VxWorks ignores SO_SNDTIMEO.
-#[cfg_attr(any(target_os = "netbsd", target_os = "openbsd", target_os = "vxworks"), ignore)]
+#[cfg_attr(
+ any(target_os = "netbsd", target_os = "openbsd", target_os = "vxworks", target_os = "nto"),
+ ignore
+)]
#[test]
fn timeouts() {
let addr = next_test_ip4();
diff --git a/library/std/src/os/fd/owned.rs b/library/std/src/os/fd/owned.rs
index c41e093a7..99a4e0b51 100644
--- a/library/std/src/os/fd/owned.rs
+++ b/library/std/src/os/fd/owned.rs
@@ -9,7 +9,7 @@ use crate::fs;
use crate::io;
use crate::marker::PhantomData;
use crate::mem::forget;
-#[cfg(not(any(target_arch = "wasm32", target_env = "sgx")))]
+#[cfg(not(any(target_arch = "wasm32", target_env = "sgx", target_os = "hermit")))]
use crate::sys::cvt;
use crate::sys_common::{AsInner, FromInner, IntoInner};
@@ -89,7 +89,7 @@ impl OwnedFd {
impl BorrowedFd<'_> {
/// Creates a new `OwnedFd` instance that shares the same underlying file
/// description as the existing `BorrowedFd` instance.
- #[cfg(not(target_arch = "wasm32"))]
+ #[cfg(not(any(target_arch = "wasm32", target_os = "hermit")))]
#[stable(feature = "io_safety", since = "1.63.0")]
pub fn try_clone_to_owned(&self) -> crate::io::Result<OwnedFd> {
// We want to atomically duplicate this file descriptor and set the
@@ -112,7 +112,7 @@ impl BorrowedFd<'_> {
/// Creates a new `OwnedFd` instance that shares the same underlying file
/// description as the existing `BorrowedFd` instance.
- #[cfg(target_arch = "wasm32")]
+ #[cfg(any(target_arch = "wasm32", target_os = "hermit"))]
#[stable(feature = "io_safety", since = "1.63.0")]
pub fn try_clone_to_owned(&self) -> crate::io::Result<OwnedFd> {
Err(crate::io::const_io_error!(
@@ -174,7 +174,10 @@ impl Drop for OwnedFd {
// the file descriptor was closed or not, and if we retried (for
// something like EINTR), we might close another valid file descriptor
// opened after we closed ours.
+ #[cfg(not(target_os = "hermit"))]
let _ = libc::close(self.fd);
+ #[cfg(target_os = "hermit")]
+ let _ = hermit_abi::close(self.fd);
}
}
}
@@ -396,6 +399,14 @@ impl<T: AsFd> AsFd for crate::sync::Arc<T> {
}
}
+#[stable(feature = "asfd_rc", since = "1.69.0")]
+impl<T: AsFd> AsFd for crate::rc::Rc<T> {
+ #[inline]
+ fn as_fd(&self) -> BorrowedFd<'_> {
+ (**self).as_fd()
+ }
+}
+
#[stable(feature = "asfd_ptrs", since = "1.64.0")]
impl<T: AsFd> AsFd for Box<T> {
#[inline]
diff --git a/library/std/src/os/fd/raw.rs b/library/std/src/os/fd/raw.rs
index f92a05066..592e072ad 100644
--- a/library/std/src/os/fd/raw.rs
+++ b/library/std/src/os/fd/raw.rs
@@ -4,6 +4,9 @@
use crate::fs;
use crate::io;
+#[cfg(target_os = "hermit")]
+use crate::os::hermit::io::OwnedFd;
+#[cfg(not(target_os = "hermit"))]
use crate::os::raw;
#[cfg(all(doc, not(target_arch = "wasm32")))]
use crate::os::unix::io::AsFd;
@@ -12,11 +15,18 @@ use crate::os::unix::io::OwnedFd;
#[cfg(target_os = "wasi")]
use crate::os::wasi::io::OwnedFd;
use crate::sys_common::{AsInner, IntoInner};
+#[cfg(target_os = "hermit")]
+use hermit_abi as libc;
/// Raw file descriptors.
#[rustc_allowed_through_unstable_modules]
#[stable(feature = "rust1", since = "1.0.0")]
+#[cfg(not(target_os = "hermit"))]
pub type RawFd = raw::c_int;
+#[rustc_allowed_through_unstable_modules]
+#[stable(feature = "rust1", since = "1.0.0")]
+#[cfg(target_os = "hermit")]
+pub type RawFd = i32;
/// A trait to extract the raw file descriptor from an underlying object.
///
@@ -244,6 +254,14 @@ impl<T: AsRawFd> AsRawFd for crate::sync::Arc<T> {
}
}
+#[stable(feature = "asfd_rc", since = "1.69.0")]
+impl<T: AsRawFd> AsRawFd for crate::rc::Rc<T> {
+ #[inline]
+ fn as_raw_fd(&self) -> RawFd {
+ (**self).as_raw_fd()
+ }
+}
+
#[stable(feature = "asrawfd_ptrs", since = "1.63.0")]
impl<T: AsRawFd> AsRawFd for Box<T> {
#[inline]
diff --git a/library/std/src/os/fuchsia/raw.rs b/library/std/src/os/fuchsia/raw.rs
index 060d6e86b..ea6b94f2f 100644
--- a/library/std/src/os/fuchsia/raw.rs
+++ b/library/std/src/os/fuchsia/raw.rs
@@ -24,12 +24,7 @@ pub type pthread_t = c_ulong;
#[stable(feature = "raw_ext", since = "1.1.0")]
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 = "powerpc",
- target_arch = "arm"
-))]
+#[cfg(any(target_arch = "x86", target_arch = "powerpc", target_arch = "arm"))]
mod arch {
use crate::os::raw::{c_long, c_short, c_uint};
diff --git a/library/std/src/os/hermit/io/mod.rs b/library/std/src/os/hermit/io/mod.rs
new file mode 100644
index 000000000..524dfae0d
--- /dev/null
+++ b/library/std/src/os/hermit/io/mod.rs
@@ -0,0 +1,13 @@
+#![stable(feature = "os_fd", since = "1.66.0")]
+
+mod net;
+#[path = "../../fd/owned.rs"]
+mod owned;
+#[path = "../../fd/raw.rs"]
+mod raw;
+
+// Export the types and traits for the public API.
+#[stable(feature = "os_fd", since = "1.66.0")]
+pub use owned::*;
+#[stable(feature = "os_fd", since = "1.66.0")]
+pub use raw::*;
diff --git a/library/std/src/os/hermit/io/net.rs b/library/std/src/os/hermit/io/net.rs
new file mode 100644
index 000000000..8f3802d78
--- /dev/null
+++ b/library/std/src/os/hermit/io/net.rs
@@ -0,0 +1,46 @@
+use crate::os::hermit::io::OwnedFd;
+use crate::os::hermit::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd};
+use crate::sys_common::{self, AsInner, FromInner, IntoInner};
+use crate::{net, sys};
+
+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_raw_fd()
+ }
+ }
+ )*};
+}
+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 {
+ unsafe {
+ let socket = sys::net::Socket::from_inner(FromInner::from_inner(OwnedFd::from_raw_fd(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().into_inner().into_raw_fd()
+ }
+ }
+ )*};
+}
+impl_into_raw_fd! { TcpStream TcpListener UdpSocket }
diff --git a/library/std/src/os/hermit/mod.rs b/library/std/src/os/hermit/mod.rs
index 4657b545a..89b1b8319 100644
--- a/library/std/src/os/hermit/mod.rs
+++ b/library/std/src/os/hermit/mod.rs
@@ -1,6 +1,11 @@
#![stable(feature = "rust1", since = "1.0.0")]
+#[allow(unused_extern_crates)]
+#[stable(feature = "rust1", since = "1.0.0")]
+pub extern crate hermit_abi as abi;
+
pub mod ffi;
+pub mod io;
/// A prelude for conveniently writing platform-specific code.
///
diff --git a/library/std/src/os/l4re/raw.rs b/library/std/src/os/l4re/raw.rs
index 699e8be33..b3f7439f8 100644
--- a/library/std/src/os/l4re/raw.rs
+++ b/library/std/src/os/l4re/raw.rs
@@ -26,7 +26,6 @@ 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",
diff --git a/library/std/src/os/linux/raw.rs b/library/std/src/os/linux/raw.rs
index c73791d14..f46028c3a 100644
--- a/library/std/src/os/linux/raw.rs
+++ b/library/std/src/os/linux/raw.rs
@@ -26,7 +26,6 @@ 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",
diff --git a/library/std/src/os/mod.rs b/library/std/src/os/mod.rs
index 42773805c..b148d8a00 100644
--- a/library/std/src/os/mod.rs
+++ b/library/std/src/os/mod.rs
@@ -60,16 +60,6 @@ pub mod windows {}
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;
@@ -123,6 +113,8 @@ pub mod freebsd;
pub mod fuchsia;
#[cfg(target_os = "haiku")]
pub mod haiku;
+#[cfg(target_os = "hermit")]
+pub mod hermit;
#[cfg(target_os = "horizon")]
pub mod horizon;
#[cfg(target_os = "illumos")]
@@ -135,6 +127,8 @@ pub mod l4re;
pub mod macos;
#[cfg(target_os = "netbsd")]
pub mod netbsd;
+#[cfg(target_os = "nto")]
+pub mod nto;
#[cfg(target_os = "openbsd")]
pub mod openbsd;
#[cfg(target_os = "redox")]
diff --git a/library/std/src/os/net/mod.rs b/library/std/src/os/net/mod.rs
index 5ec267c41..b7046dd7c 100644
--- a/library/std/src/os/net/mod.rs
+++ b/library/std/src/os/net/mod.rs
@@ -1,4 +1,13 @@
//! OS-specific networking functionality.
+// See cfg macros in `library/std/src/os/mod.rs` for why these platforms must
+// be special-cased during rustdoc generation.
+#[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 = "android", doc))]
pub(super) mod linux_ext;
diff --git a/library/std/src/os/nto/fs.rs b/library/std/src/os/nto/fs.rs
new file mode 100644
index 000000000..8f915b08c
--- /dev/null
+++ b/library/std/src/os/nto/fs.rs
@@ -0,0 +1,92 @@
+#![stable(feature = "metadata_ext", since = "1.1.0")]
+
+use crate::fs::Metadata;
+use crate::sys_common::AsInner;
+
+#[stable(feature = "metadata_ext", since = "1.1.0")]
+pub trait MetadataExt {
+ #[stable(feature = "metadata_ext2", since = "1.8.0")]
+ fn st_dev(&self) -> u64;
+ #[stable(feature = "metadata_ext2", since = "1.8.0")]
+ fn st_ino(&self) -> u64;
+ #[stable(feature = "metadata_ext2", since = "1.8.0")]
+ fn st_mode(&self) -> u32;
+ #[stable(feature = "metadata_ext2", since = "1.8.0")]
+ fn st_nlink(&self) -> u64;
+ #[stable(feature = "metadata_ext2", since = "1.8.0")]
+ fn st_uid(&self) -> u32;
+ #[stable(feature = "metadata_ext2", since = "1.8.0")]
+ fn st_gid(&self) -> u32;
+ #[stable(feature = "metadata_ext2", since = "1.8.0")]
+ fn st_rdev(&self) -> u64;
+ #[stable(feature = "metadata_ext2", since = "1.8.0")]
+ fn st_size(&self) -> u64;
+ #[stable(feature = "metadata_ext2", since = "1.8.0")]
+ fn st_atime(&self) -> i64;
+ #[stable(feature = "metadata_ext2", since = "1.8.0")]
+ fn st_atime_nsec(&self) -> i64;
+ #[stable(feature = "metadata_ext2", since = "1.8.0")]
+ fn st_mtime(&self) -> i64;
+ #[stable(feature = "metadata_ext2", since = "1.8.0")]
+ fn st_mtime_nsec(&self) -> i64;
+ #[stable(feature = "metadata_ext2", since = "1.8.0")]
+ fn st_ctime(&self) -> i64;
+ #[stable(feature = "metadata_ext2", since = "1.8.0")]
+ fn st_ctime_nsec(&self) -> i64;
+ #[stable(feature = "metadata_ext2", since = "1.8.0")]
+ fn st_blksize(&self) -> u64;
+ #[stable(feature = "metadata_ext2", since = "1.8.0")]
+ fn st_blocks(&self) -> u64;
+}
+
+#[stable(feature = "metadata_ext", since = "1.1.0")]
+impl MetadataExt for Metadata {
+ fn st_dev(&self) -> u64 {
+ self.as_inner().as_inner().st_dev as u64
+ }
+ fn st_ino(&self) -> u64 {
+ self.as_inner().as_inner().st_ino as u64
+ }
+ fn st_mode(&self) -> u32 {
+ self.as_inner().as_inner().st_mode as u32
+ }
+ fn st_nlink(&self) -> u64 {
+ self.as_inner().as_inner().st_nlink as u64
+ }
+ fn st_uid(&self) -> u32 {
+ self.as_inner().as_inner().st_uid as u32
+ }
+ fn st_gid(&self) -> u32 {
+ self.as_inner().as_inner().st_gid as u32
+ }
+ fn st_rdev(&self) -> u64 {
+ self.as_inner().as_inner().st_rdev as u64
+ }
+ fn st_size(&self) -> u64 {
+ self.as_inner().as_inner().st_size as u64
+ }
+ fn st_atime(&self) -> i64 {
+ self.as_inner().as_inner().st_atim.tv_sec as i64
+ }
+ fn st_atime_nsec(&self) -> i64 {
+ self.as_inner().as_inner().st_atim.tv_nsec as i64
+ }
+ fn st_mtime(&self) -> i64 {
+ self.as_inner().as_inner().st_mtim.tv_sec as i64
+ }
+ fn st_mtime_nsec(&self) -> i64 {
+ self.as_inner().as_inner().st_mtim.tv_nsec as i64
+ }
+ fn st_ctime(&self) -> i64 {
+ self.as_inner().as_inner().st_ctim.tv_sec as i64
+ }
+ fn st_ctime_nsec(&self) -> i64 {
+ self.as_inner().as_inner().st_ctim.tv_nsec as i64
+ }
+ fn st_blksize(&self) -> u64 {
+ self.as_inner().as_inner().st_blksize as u64
+ }
+ fn st_blocks(&self) -> u64 {
+ self.as_inner().as_inner().st_blocks as u64
+ }
+}
diff --git a/library/std/src/os/nto/mod.rs b/library/std/src/os/nto/mod.rs
new file mode 100644
index 000000000..3e591dace
--- /dev/null
+++ b/library/std/src/os/nto/mod.rs
@@ -0,0 +1,4 @@
+#![stable(feature = "raw_ext", since = "1.1.0")]
+
+pub mod fs;
+pub(super) mod raw;
diff --git a/library/std/src/os/nto/raw.rs b/library/std/src/os/nto/raw.rs
new file mode 100644
index 000000000..90e9ad546
--- /dev/null
+++ b/library/std/src/os/nto/raw.rs
@@ -0,0 +1,40 @@
+#![stable(feature = "raw_ext", since = "1.1.0")]
+#![deprecated(
+ since = "1.8.0",
+ note = "these type aliases are no longer supported by \
+ the standard library, the `libc` crate on \
+ crates.io should be used instead for the correct \
+ definitions"
+)]
+#![allow(deprecated)]
+
+use crate::os::raw::c_int;
+
+#[stable(feature = "raw_ext", since = "1.1.0")]
+pub type dev_t = u32;
+#[stable(feature = "raw_ext", since = "1.1.0")]
+pub type mode_t = u32;
+
+#[stable(feature = "pthread_t", since = "1.8.0")]
+pub type pthread_t = c_int;
+
+#[doc(inline)]
+#[stable(feature = "raw_ext", since = "1.1.0")]
+pub use self::arch::{blkcnt_t, blksize_t, ino_t, nlink_t, off_t, time_t};
+
+mod arch {
+ use crate::os::raw::c_long;
+
+ #[stable(feature = "raw_ext", since = "1.1.0")]
+ pub type blkcnt_t = i64;
+ #[stable(feature = "raw_ext", since = "1.1.0")]
+ pub type blksize_t = i32;
+ #[stable(feature = "raw_ext", since = "1.1.0")]
+ pub type ino_t = u64;
+ #[stable(feature = "raw_ext", since = "1.1.0")]
+ pub type nlink_t = u32;
+ #[stable(feature = "raw_ext", since = "1.1.0")]
+ pub type off_t = i64;
+ #[stable(feature = "raw_ext", since = "1.1.0")]
+ pub type time_t = c_long;
+}
diff --git a/library/std/src/os/unix/fs.rs b/library/std/src/os/unix/fs.rs
index 3fc6cc44c..a0e664acd 100644
--- a/library/std/src/os/unix/fs.rs
+++ b/library/std/src/os/unix/fs.rs
@@ -17,6 +17,10 @@ use crate::sealed::Sealed;
#[allow(unused_imports)]
use io::{Read, Write};
+// Tests for this module
+#[cfg(test)]
+mod tests;
+
/// Unix-specific extensions to [`fs::File`].
#[stable(feature = "file_offset", since = "1.15.0")]
pub trait FileExt {
@@ -54,6 +58,16 @@ pub trait FileExt {
#[stable(feature = "file_offset", since = "1.15.0")]
fn read_at(&self, buf: &mut [u8], offset: u64) -> io::Result<usize>;
+ /// Like `read_at`, except that it reads into a slice of buffers.
+ ///
+ /// Data is copied to fill each buffer in order, with the final buffer
+ /// written to possibly being only partially filled. This method must behave
+ /// equivalently to a single call to read with concatenated buffers.
+ #[unstable(feature = "unix_file_vectored_at", issue = "89517")]
+ fn read_vectored_at(&self, bufs: &mut [io::IoSliceMut<'_>], offset: u64) -> io::Result<usize> {
+ io::default_read_vectored(|b| self.read_at(b, offset), bufs)
+ }
+
/// Reads the exact number of byte required to fill `buf` from the given offset.
///
/// The offset is relative to the start of the file and thus independent
@@ -155,6 +169,16 @@ pub trait FileExt {
#[stable(feature = "file_offset", since = "1.15.0")]
fn write_at(&self, buf: &[u8], offset: u64) -> io::Result<usize>;
+ /// Like `write_at`, except that it writes from a slice of buffers.
+ ///
+ /// Data is copied from each buffer in order, with the final buffer read
+ /// from possibly being only partially consumed. This method must behave as
+ /// a call to `write_at` with the buffers concatenated would.
+ #[unstable(feature = "unix_file_vectored_at", issue = "89517")]
+ fn write_vectored_at(&self, bufs: &[io::IoSlice<'_>], offset: u64) -> io::Result<usize> {
+ io::default_write_vectored(|b| self.write_at(b, offset), bufs)
+ }
+
/// Attempts to write an entire buffer starting from a given offset.
///
/// The offset is relative to the start of the file and thus independent
@@ -218,9 +242,15 @@ impl FileExt for fs::File {
fn read_at(&self, buf: &mut [u8], offset: u64) -> io::Result<usize> {
self.as_inner().read_at(buf, offset)
}
+ fn read_vectored_at(&self, bufs: &mut [io::IoSliceMut<'_>], offset: u64) -> io::Result<usize> {
+ self.as_inner().read_vectored_at(bufs, offset)
+ }
fn write_at(&self, buf: &[u8], offset: u64) -> io::Result<usize> {
self.as_inner().write_at(buf, offset)
}
+ fn write_vectored_at(&self, bufs: &[io::IoSlice<'_>], offset: u64) -> io::Result<usize> {
+ self.as_inner().write_vectored_at(bufs, offset)
+ }
}
/// Unix-specific extensions to [`fs::Permissions`].
diff --git a/library/std/src/os/unix/fs/tests.rs b/library/std/src/os/unix/fs/tests.rs
new file mode 100644
index 000000000..67f607bd4
--- /dev/null
+++ b/library/std/src/os/unix/fs/tests.rs
@@ -0,0 +1,57 @@
+use super::*;
+
+#[test]
+fn read_vectored_at() {
+ let msg = b"preadv is working!";
+ let dir = crate::sys_common::io::test::tmpdir();
+
+ let filename = dir.join("preadv.txt");
+ {
+ let mut file = fs::File::create(&filename).unwrap();
+ file.write_all(msg).unwrap();
+ }
+ {
+ let file = fs::File::open(&filename).unwrap();
+ let mut buf0 = [0; 4];
+ let mut buf1 = [0; 3];
+
+ let mut iovec = [io::IoSliceMut::new(&mut buf0), io::IoSliceMut::new(&mut buf1)];
+
+ let n = file.read_vectored_at(&mut iovec, 4).unwrap();
+
+ assert!(n == 4 || n == 7);
+ assert_eq!(&buf0, b"dv i");
+
+ if n == 7 {
+ assert_eq!(&buf1, b"s w");
+ }
+ }
+}
+
+#[test]
+fn write_vectored_at() {
+ let msg = b"pwritev is not working!";
+ let dir = crate::sys_common::io::test::tmpdir();
+
+ let filename = dir.join("preadv.txt");
+ {
+ let mut file = fs::File::create(&filename).unwrap();
+ file.write_all(msg).unwrap();
+ }
+ let expected = {
+ let file = fs::File::options().write(true).open(&filename).unwrap();
+ let buf0 = b" ";
+ let buf1 = b"great ";
+
+ let iovec = [io::IoSlice::new(buf0), io::IoSlice::new(buf1)];
+
+ let n = file.write_vectored_at(&iovec, 11).unwrap();
+
+ assert!(n == 4 || n == 11);
+
+ if n == 4 { b"pwritev is working!" } else { b"pwritev is great !" }
+ };
+
+ let content = fs::read(&filename).unwrap();
+ assert_eq!(&content, expected);
+}
diff --git a/library/std/src/os/unix/mod.rs b/library/std/src/os/unix/mod.rs
index f97fa0fb0..eb2d7ce11 100644
--- a/library/std/src/os/unix/mod.rs
+++ b/library/std/src/os/unix/mod.rs
@@ -65,6 +65,8 @@ mod platform {
pub use crate::os::macos::*;
#[cfg(target_os = "netbsd")]
pub use crate::os::netbsd::*;
+ #[cfg(target_os = "nto")]
+ pub use crate::os::nto::*;
#[cfg(target_os = "openbsd")]
pub use crate::os::openbsd::*;
#[cfg(target_os = "redox")]
@@ -95,7 +97,8 @@ pub mod thread;
target_os = "watchos",
target_os = "macos",
target_os = "netbsd",
- target_os = "openbsd"
+ target_os = "openbsd",
+ target_os = "nto",
))]
pub mod ucred;
diff --git a/library/std/src/os/unix/net/datagram.rs b/library/std/src/os/unix/net/datagram.rs
index f758f88d0..272b4f5dc 100644
--- a/library/std/src/os/unix/net/datagram.rs
+++ b/library/std/src/os/unix/net/datagram.rs
@@ -19,7 +19,8 @@ use crate::{fmt, io};
target_os = "freebsd",
target_os = "openbsd",
target_os = "netbsd",
- target_os = "haiku"
+ target_os = "haiku",
+ target_os = "nto",
))]
use libc::MSG_NOSIGNAL;
#[cfg(not(any(
@@ -29,7 +30,8 @@ use libc::MSG_NOSIGNAL;
target_os = "freebsd",
target_os = "openbsd",
target_os = "netbsd",
- target_os = "haiku"
+ target_os = "haiku",
+ target_os = "nto",
)))]
const MSG_NOSIGNAL: libc::c_int = 0x0;
diff --git a/library/std/src/os/unix/net/tests.rs b/library/std/src/os/unix/net/tests.rs
index 37fcfa844..f8c29a6d3 100644
--- a/library/std/src/os/unix/net/tests.rs
+++ b/library/std/src/os/unix/net/tests.rs
@@ -167,6 +167,7 @@ fn long_path() {
}
#[test]
+#[cfg(not(target_os = "nto"))]
fn timeouts() {
let dir = tmpdir();
let socket_path = dir.path().join("sock");
diff --git a/library/std/src/os/unix/process.rs b/library/std/src/os/unix/process.rs
index 09b2bfe39..729c63d18 100644
--- a/library/std/src/os/unix/process.rs
+++ b/library/std/src/os/unix/process.rs
@@ -12,15 +12,23 @@ use crate::sealed::Sealed;
use crate::sys;
use crate::sys_common::{AsInner, AsInnerMut, FromInner, IntoInner};
-#[cfg(not(any(target_os = "vxworks", target_os = "espidf", target_os = "horizon")))]
-type UserId = u32;
-#[cfg(not(any(target_os = "vxworks", target_os = "espidf", target_os = "horizon")))]
-type GroupId = u32;
-
-#[cfg(any(target_os = "vxworks", target_os = "espidf", target_os = "horizon"))]
-type UserId = u16;
-#[cfg(any(target_os = "vxworks", target_os = "espidf", target_os = "horizon"))]
-type GroupId = u16;
+use cfg_if::cfg_if;
+
+cfg_if! {
+ if #[cfg(any(target_os = "vxworks", target_os = "espidf", target_os = "horizon"))] {
+ type UserId = u16;
+ type GroupId = u16;
+ } else if #[cfg(target_os = "nto")] {
+ // Both IDs are signed, see `sys/target_nto.h` of the QNX Neutrino SDP.
+ // Only positive values should be used, see e.g.
+ // https://www.qnx.com/developers/docs/7.1/#com.qnx.doc.neutrino.lib_ref/topic/s/setuid.html
+ type UserId = i32;
+ type GroupId = i32;
+ } else {
+ type UserId = u32;
+ type GroupId = u32;
+ }
+}
/// Unix-specific extensions to the [`process::Command`] builder.
///
diff --git a/library/std/src/os/unix/ucred.rs b/library/std/src/os/unix/ucred.rs
index ae4faf27b..95967eac2 100644
--- a/library/std/src/os/unix/ucred.rs
+++ b/library/std/src/os/unix/ucred.rs
@@ -79,7 +79,8 @@ pub mod impl_linux {
target_os = "dragonfly",
target_os = "freebsd",
target_os = "openbsd",
- target_os = "netbsd"
+ target_os = "netbsd",
+ target_os = "nto",
))]
pub mod impl_bsd {
use super::UCred;
diff --git a/library/std/src/panicking.rs b/library/std/src/panicking.rs
index b0db3112e..e59f32af7 100644
--- a/library/std/src/panicking.rs
+++ b/library/std/src/panicking.rs
@@ -95,13 +95,16 @@ impl Default for Hook {
static HOOK: RwLock<Hook> = RwLock::new(Hook::Default);
-/// Registers a custom panic hook, replacing any that was previously registered.
+/// Registers a custom panic hook, replacing the previously registered hook.
///
/// The panic hook is invoked when a thread panics, but before the panic runtime
/// is invoked. As such, the hook will run with both the aborting and unwinding
-/// runtimes. The default hook prints a message to standard error and generates
-/// a backtrace if requested, but this behavior can be customized with the
-/// `set_hook` and [`take_hook`] functions.
+/// runtimes.
+///
+/// The default hook, which is registered at startup, prints a message to standard error and
+/// generates a backtrace if requested. This behavior can be customized using the `set_hook` function.
+/// The current hook can be retrieved while reinstating the default hook with the [`take_hook`]
+/// function.
///
/// [`take_hook`]: ./fn.take_hook.html
///
@@ -143,13 +146,14 @@ pub fn set_hook(hook: Box<dyn Fn(&PanicInfo<'_>) + 'static + Sync + Send>) {
drop(old);
}
-/// Unregisters the current panic hook, returning it.
+/// Unregisters the current panic hook and returns it, registering the default hook
+/// in its place.
///
/// *See also the function [`set_hook`].*
///
/// [`set_hook`]: ./fn.set_hook.html
///
-/// If no custom hook is registered, the default hook will be returned.
+/// If the default hook is registered it will be returned, but remain registered.
///
/// # Panics
///
diff --git a/library/std/src/path.rs b/library/std/src/path.rs
index 4778114b4..cd6b393a2 100644
--- a/library/std/src/path.rs
+++ b/library/std/src/path.rs
@@ -2531,6 +2531,8 @@ impl Path {
/// Creates an owned [`PathBuf`] with `path` adjoined to `self`.
///
+ /// If `path` is absolute, it replaces the current path.
+ ///
/// See [`PathBuf::push`] for more details on what it means to adjoin a path.
///
/// # Examples
@@ -2539,6 +2541,7 @@ impl Path {
/// use std::path::{Path, PathBuf};
///
/// assert_eq!(Path::new("/etc").join("passwd"), PathBuf::from("/etc/passwd"));
+ /// assert_eq!(Path::new("/etc").join("/bin/sh"), PathBuf::from("/bin/sh"));
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[must_use]
@@ -2685,6 +2688,7 @@ impl Path {
/// escapes the path please use [`Debug`] instead.
///
/// [`Display`]: fmt::Display
+ /// [`Debug`]: fmt::Debug
///
/// # Examples
///
diff --git a/library/std/src/personality/emcc.rs b/library/std/src/personality/emcc.rs
index f942bdf18..cb52ae89b 100644
--- a/library/std/src/personality/emcc.rs
+++ b/library/std/src/personality/emcc.rs
@@ -1,7 +1,7 @@
//! On Emscripten Rust panics are wrapped in C++ exceptions, so we just forward
//! to `__gxx_personality_v0` which is provided by Emscripten.
-use libc::c_int;
+use crate::ffi::c_int;
use unwind as uw;
// This is required by the compiler to exist (e.g., it's a lang item), but it's
diff --git a/library/std/src/personality/gcc.rs b/library/std/src/personality/gcc.rs
index 5fc1b91a1..41c0fe725 100644
--- a/library/std/src/personality/gcc.rs
+++ b/library/std/src/personality/gcc.rs
@@ -37,7 +37,8 @@
//! and the last personality routine transfers control to the catch block.
use super::dwarf::eh::{self, EHAction, EHContext};
-use libc::{c_int, uintptr_t};
+use crate::ffi::c_int;
+use libc::uintptr_t;
use unwind as uw;
// Register ids were lifted from LLVM's TargetLowering::getExceptionPointerRegister()
diff --git a/library/std/src/primitive_docs.rs b/library/std/src/primitive_docs.rs
index d6e9da187..6f78811a1 100644
--- a/library/std/src/primitive_docs.rs
+++ b/library/std/src/primitive_docs.rs
@@ -587,8 +587,10 @@ mod prim_pointer {}
/// 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`].
+/// * A repeat expression `[expr; N]` where `N` is how many times to repeat `expr` in the array. `expr` must either be:
+///
+/// * A value of a type implementing the [`Copy`] trait
+/// * A `const` value
///
/// Note that `[expr; 0]` is allowed, and produces an empty array.
/// This will still evaluate `expr`, however, and immediately drop the resulting value, so
diff --git a/library/std/src/process.rs b/library/std/src/process.rs
index 62ce2cb33..1952e19e6 100644
--- a/library/std/src/process.rs
+++ b/library/std/src/process.rs
@@ -1416,7 +1416,7 @@ impl From<fs::File> for Stdio {
/// use std::fs::File;
/// use std::process::Command;
///
- /// // With the `foo.txt` file containing `Hello, world!"
+ /// // With the `foo.txt` file containing "Hello, world!"
/// let file = File::open("foo.txt").unwrap();
///
/// let reverse = Command::new("rev")
diff --git a/library/std/src/sync/lazy_lock.rs b/library/std/src/sync/lazy_lock.rs
index 4a1530530..7e85d6a06 100644
--- a/library/std/src/sync/lazy_lock.rs
+++ b/library/std/src/sync/lazy_lock.rs
@@ -1,8 +1,21 @@
-use crate::cell::Cell;
+use crate::cell::UnsafeCell;
use crate::fmt;
+use crate::mem::ManuallyDrop;
use crate::ops::Deref;
use crate::panic::{RefUnwindSafe, UnwindSafe};
-use crate::sync::OnceLock;
+use crate::sync::Once;
+
+use super::once::ExclusiveState;
+
+// We use the state of a Once as discriminant value. Upon creation, the state is
+// "incomplete" and `f` contains the initialization closure. In the first call to
+// `call_once`, `f` is taken and run. If it succeeds, `value` is set and the state
+// is changed to "complete". If it panics, the Once is poisoned, so none of the
+// two fields is initialized.
+union Data<T, F> {
+ value: ManuallyDrop<T>,
+ f: ManuallyDrop<F>,
+}
/// A value which is initialized on the first access.
///
@@ -43,16 +56,17 @@ use crate::sync::OnceLock;
/// ```
#[unstable(feature = "once_cell", issue = "74465")]
pub struct LazyLock<T, F = fn() -> T> {
- cell: OnceLock<T>,
- init: Cell<Option<F>>,
+ once: Once,
+ data: UnsafeCell<Data<T, F>>,
}
+
impl<T, F: FnOnce() -> T> LazyLock<T, F> {
/// Creates a new lazy value with the given initializing
/// function.
#[inline]
#[unstable(feature = "once_cell", issue = "74465")]
pub const fn new(f: F) -> LazyLock<T, F> {
- LazyLock { cell: OnceLock::new(), init: Cell::new(Some(f)) }
+ LazyLock { once: Once::new(), data: UnsafeCell::new(Data { f: ManuallyDrop::new(f) }) }
}
/// Forces the evaluation of this lazy value and
@@ -74,10 +88,50 @@ impl<T, F: FnOnce() -> T> LazyLock<T, F> {
#[inline]
#[unstable(feature = "once_cell", issue = "74465")]
pub fn force(this: &LazyLock<T, F>) -> &T {
- this.cell.get_or_init(|| match this.init.take() {
- Some(f) => f(),
- None => panic!("Lazy instance has previously been poisoned"),
- })
+ this.once.call_once(|| {
+ // SAFETY: `call_once` only runs this closure once, ever.
+ let data = unsafe { &mut *this.data.get() };
+ let f = unsafe { ManuallyDrop::take(&mut data.f) };
+ let value = f();
+ data.value = ManuallyDrop::new(value);
+ });
+
+ // SAFETY:
+ // There are four possible scenarios:
+ // * the closure was called and initialized `value`.
+ // * the closure was called and panicked, so this point is never reached.
+ // * the closure was not called, but a previous call initialized `value`.
+ // * the closure was not called because the Once is poisoned, so this point
+ // is never reached.
+ // So `value` has definitely been initialized and will not be modified again.
+ unsafe { &*(*this.data.get()).value }
+ }
+}
+
+impl<T, F> LazyLock<T, F> {
+ /// Get the inner value if it has already been initialized.
+ fn get(&self) -> Option<&T> {
+ if self.once.is_completed() {
+ // SAFETY:
+ // The closure has been run successfully, so `value` has been initialized
+ // and will not be modified again.
+ Some(unsafe { &*(*self.data.get()).value })
+ } else {
+ None
+ }
+ }
+}
+
+#[unstable(feature = "once_cell", issue = "74465")]
+impl<T, F> Drop for LazyLock<T, F> {
+ fn drop(&mut self) {
+ match self.once.state() {
+ ExclusiveState::Incomplete => unsafe { ManuallyDrop::drop(&mut self.data.get_mut().f) },
+ ExclusiveState::Complete => unsafe {
+ ManuallyDrop::drop(&mut self.data.get_mut().value)
+ },
+ ExclusiveState::Poisoned => {}
+ }
}
}
@@ -103,23 +157,23 @@ impl<T: Default> Default for LazyLock<T> {
#[unstable(feature = "once_cell", issue = "74465")]
impl<T: fmt::Debug, F> fmt::Debug for LazyLock<T, F> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- f.debug_struct("Lazy").field("cell", &self.cell).finish_non_exhaustive()
+ match self.get() {
+ Some(v) => f.debug_tuple("LazyLock").field(v).finish(),
+ None => f.write_str("LazyLock(Uninit)"),
+ }
}
}
// We never create a `&F` from a `&LazyLock<T, F>` so it is fine
// to not impl `Sync` for `F`
-// we do create a `&mut Option<F>` in `force`, but this is
-// properly synchronized, so it only happens once
-// so it also does not contribute to this impl.
#[unstable(feature = "once_cell", issue = "74465")]
-unsafe impl<T, F: Send> Sync for LazyLock<T, F> where OnceLock<T>: Sync {}
+unsafe impl<T: Sync + Send, F: Send> Sync for LazyLock<T, F> {}
// auto-derived `Send` impl is OK.
#[unstable(feature = "once_cell", issue = "74465")]
-impl<T, F: UnwindSafe> RefUnwindSafe for LazyLock<T, F> where OnceLock<T>: RefUnwindSafe {}
+impl<T: RefUnwindSafe + UnwindSafe, F: UnwindSafe> RefUnwindSafe for LazyLock<T, F> {}
#[unstable(feature = "once_cell", issue = "74465")]
-impl<T, F: UnwindSafe> UnwindSafe for LazyLock<T, F> where OnceLock<T>: UnwindSafe {}
+impl<T: UnwindSafe, F: UnwindSafe> UnwindSafe for LazyLock<T, F> {}
#[cfg(test)]
mod tests;
diff --git a/library/std/src/sync/mod.rs b/library/std/src/sync/mod.rs
index ba20bab87..4edc95617 100644
--- a/library/std/src/sync/mod.rs
+++ b/library/std/src/sync/mod.rs
@@ -186,7 +186,7 @@ mod condvar;
mod lazy_lock;
mod mpmc;
mod mutex;
-mod once;
+pub(crate) mod once;
mod once_lock;
mod poison;
mod remutex;
diff --git a/library/std/src/sync/mpmc/array.rs b/library/std/src/sync/mpmc/array.rs
index c1e3e48b0..c6bb09b04 100644
--- a/library/std/src/sync/mpmc/array.rs
+++ b/library/std/src/sync/mpmc/array.rs
@@ -319,19 +319,10 @@ impl<T> Channel<T> {
) -> Result<(), SendTimeoutError<T>> {
let token = &mut Token::default();
loop {
- // Try sending a message several times.
- let backoff = Backoff::new();
- loop {
- if self.start_send(token) {
- let res = unsafe { self.write(token, msg) };
- return res.map_err(SendTimeoutError::Disconnected);
- }
-
- if backoff.is_completed() {
- break;
- } else {
- backoff.spin_light();
- }
+ // Try sending a message.
+ if self.start_send(token) {
+ let res = unsafe { self.write(token, msg) };
+ return res.map_err(SendTimeoutError::Disconnected);
}
if let Some(d) = deadline {
@@ -379,6 +370,7 @@ impl<T> Channel<T> {
pub(crate) fn recv(&self, deadline: Option<Instant>) -> Result<T, RecvTimeoutError> {
let token = &mut Token::default();
loop {
+ // Try receiving a message.
if self.start_recv(token) {
let res = unsafe { self.read(token) };
return res.map_err(|_| RecvTimeoutError::Disconnected);
diff --git a/library/std/src/sync/mpmc/utils.rs b/library/std/src/sync/mpmc/utils.rs
index cfe42750d..d053d69e2 100644
--- a/library/std/src/sync/mpmc/utils.rs
+++ b/library/std/src/sync/mpmc/utils.rs
@@ -105,10 +105,8 @@ impl Backoff {
/// Backs off using lightweight spinning.
///
- /// This method should be used for:
- /// - Retrying an operation because another thread made progress. i.e. on CAS failure.
- /// - Waiting for an operation to complete by spinning optimistically for a few iterations
- /// before falling back to parking the thread (see `Backoff::is_completed`).
+ /// This method should be used for retrying an operation because another thread made
+ /// progress. i.e. on CAS failure.
#[inline]
pub fn spin_light(&self) {
let step = self.step.get().min(SPIN_LIMIT);
@@ -134,10 +132,4 @@ impl Backoff {
self.step.set(self.step.get() + 1);
}
-
- /// Returns `true` if quadratic backoff has completed and parking the thread is advised.
- #[inline]
- pub fn is_completed(&self) -> bool {
- self.step.get() > SPIN_LIMIT
- }
}
diff --git a/library/std/src/sync/once.rs b/library/std/src/sync/once.rs
index 0f25417d6..1b17c3108 100644
--- a/library/std/src/sync/once.rs
+++ b/library/std/src/sync/once.rs
@@ -43,6 +43,12 @@ pub struct OnceState {
pub(crate) inner: sys::OnceState,
}
+pub(crate) enum ExclusiveState {
+ Incomplete,
+ Poisoned,
+ Complete,
+}
+
/// Initialization value for static [`Once`] values.
///
/// # Examples
@@ -248,6 +254,16 @@ impl Once {
pub fn is_completed(&self) -> bool {
self.inner.is_completed()
}
+
+ /// Returns the current state of the `Once` instance.
+ ///
+ /// Since this takes a mutable reference, no initialization can currently
+ /// be running, so the state must be either "incomplete", "poisoned" or
+ /// "complete".
+ #[inline]
+ pub(crate) fn state(&mut self) -> ExclusiveState {
+ self.inner.state()
+ }
}
#[stable(feature = "std_debug", since = "1.16.0")]
diff --git a/library/std/src/sys/common/alloc.rs b/library/std/src/sys/common/alloc.rs
index 3edbe7280..403a5e627 100644
--- a/library/std/src/sys/common/alloc.rs
+++ b/library/std/src/sys/common/alloc.rs
@@ -7,6 +7,7 @@ use crate::ptr;
#[cfg(any(
target_arch = "x86",
target_arch = "arm",
+ target_arch = "m68k",
target_arch = "mips",
target_arch = "powerpc",
target_arch = "powerpc64",
diff --git a/library/std/src/sys/hermit/args.rs b/library/std/src/sys/hermit/args.rs
index afcae6c90..220a76e4b 100644
--- a/library/std/src/sys/hermit/args.rs
+++ b/library/std/src/sys/hermit/args.rs
@@ -1,6 +1,6 @@
use crate::ffi::{c_char, CStr, OsString};
use crate::fmt;
-use crate::os::unix::ffi::OsStringExt;
+use crate::os::hermit::ffi::OsStringExt;
use crate::ptr;
use crate::sync::atomic::{
AtomicIsize, AtomicPtr,
diff --git a/library/std/src/sys/hermit/fd.rs b/library/std/src/sys/hermit/fd.rs
index c400f5f2c..3a2cdd301 100644
--- a/library/std/src/sys/hermit/fd.rs
+++ b/library/std/src/sys/hermit/fd.rs
@@ -1,36 +1,23 @@
#![unstable(reason = "not public", issue = "none", feature = "fd")]
use crate::io::{self, Read};
-use crate::mem;
+use crate::os::hermit::io::{FromRawFd, OwnedFd, RawFd};
use crate::sys::cvt;
use crate::sys::hermit::abi;
use crate::sys::unsupported;
-use crate::sys_common::AsInner;
+use crate::sys_common::{AsInner, FromInner, IntoInner};
+
+use crate::os::hermit::io::*;
#[derive(Debug)]
pub struct FileDesc {
- fd: i32,
+ fd: OwnedFd,
}
impl FileDesc {
- pub fn new(fd: i32) -> FileDesc {
- FileDesc { fd }
- }
-
- pub fn raw(&self) -> i32 {
- self.fd
- }
-
- /// Extracts the actual file descriptor without closing it.
- pub fn into_raw(self) -> i32 {
- let fd = self.fd;
- mem::forget(self);
- fd
- }
-
pub fn read(&self, buf: &mut [u8]) -> io::Result<usize> {
- let result = unsafe { abi::read(self.fd, buf.as_mut_ptr(), buf.len()) };
- cvt(result as i32)
+ let result = cvt(unsafe { abi::read(self.fd.as_raw_fd(), buf.as_mut_ptr(), buf.len()) })?;
+ Ok(result as usize)
}
pub fn read_to_end(&self, buf: &mut Vec<u8>) -> io::Result<usize> {
@@ -39,8 +26,8 @@ impl FileDesc {
}
pub fn write(&self, buf: &[u8]) -> io::Result<usize> {
- let result = unsafe { abi::write(self.fd, buf.as_ptr(), buf.len()) };
- cvt(result as i32)
+ let result = cvt(unsafe { abi::write(self.fd.as_raw_fd(), buf.as_ptr(), buf.len()) })?;
+ Ok(result as usize)
}
pub fn duplicate(&self) -> io::Result<FileDesc> {
@@ -69,19 +56,45 @@ impl<'a> Read for &'a FileDesc {
}
}
-impl AsInner<i32> for FileDesc {
- fn as_inner(&self) -> &i32 {
+impl IntoInner<OwnedFd> for FileDesc {
+ fn into_inner(self) -> OwnedFd {
+ self.fd
+ }
+}
+
+impl FromInner<OwnedFd> for FileDesc {
+ fn from_inner(owned_fd: OwnedFd) -> Self {
+ Self { fd: owned_fd }
+ }
+}
+
+impl FromRawFd for FileDesc {
+ unsafe fn from_raw_fd(raw_fd: RawFd) -> Self {
+ Self { fd: FromRawFd::from_raw_fd(raw_fd) }
+ }
+}
+
+impl AsInner<OwnedFd> for FileDesc {
+ fn as_inner(&self) -> &OwnedFd {
&self.fd
}
}
-impl Drop for FileDesc {
- fn drop(&mut self) {
- // Note that errors are ignored when closing a file descriptor. The
- // reason for this is that if an error occurs we don't actually know if
- // the file descriptor was closed or not, and if we retried (for
- // something like EINTR), we might close another valid file descriptor
- // (opened after we closed ours.
- let _ = unsafe { abi::close(self.fd) };
+impl AsFd for FileDesc {
+ fn as_fd(&self) -> BorrowedFd<'_> {
+ self.fd.as_fd()
+ }
+}
+
+impl AsRawFd for FileDesc {
+ #[inline]
+ fn as_raw_fd(&self) -> RawFd {
+ self.fd.as_raw_fd()
+ }
+}
+
+impl IntoRawFd for FileDesc {
+ fn into_raw_fd(self) -> RawFd {
+ self.fd.into_raw_fd()
}
}
diff --git a/library/std/src/sys/hermit/fs.rs b/library/std/src/sys/hermit/fs.rs
index 6fb92c037..c966f2177 100644
--- a/library/std/src/sys/hermit/fs.rs
+++ b/library/std/src/sys/hermit/fs.rs
@@ -3,14 +3,17 @@ use crate::fmt;
use crate::hash::{Hash, Hasher};
use crate::io::{self, Error, ErrorKind};
use crate::io::{BorrowedCursor, IoSlice, IoSliceMut, SeekFrom};
+use crate::os::hermit::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, RawFd};
use crate::path::{Path, PathBuf};
use crate::sys::common::small_c_string::run_path_with_cstr;
use crate::sys::cvt;
-use crate::sys::hermit::abi;
-use crate::sys::hermit::abi::{O_APPEND, O_CREAT, O_EXCL, O_RDONLY, O_RDWR, O_TRUNC, O_WRONLY};
+use crate::sys::hermit::abi::{
+ self, O_APPEND, O_CREAT, O_EXCL, O_RDONLY, O_RDWR, O_TRUNC, O_WRONLY,
+};
use crate::sys::hermit::fd::FileDesc;
use crate::sys::time::SystemTime;
use crate::sys::unsupported;
+use crate::sys_common::{AsInner, AsInnerMut, FromInner, IntoInner};
pub use crate::sys_common::fs::{copy, try_exists};
//pub use crate::sys_common::fs::remove_dir_all;
@@ -283,7 +286,7 @@ impl File {
}
let fd = unsafe { cvt(abi::open(path.as_ptr(), flags, mode))? };
- Ok(File(FileDesc::new(fd as i32)))
+ Ok(File(unsafe { FileDesc::from_raw_fd(fd as i32) }))
}
pub fn file_attr(&self) -> io::Result<FileAttr> {
@@ -363,6 +366,54 @@ impl DirBuilder {
}
}
+impl AsInner<FileDesc> for File {
+ fn as_inner(&self) -> &FileDesc {
+ &self.0
+ }
+}
+
+impl AsInnerMut<FileDesc> for File {
+ fn as_inner_mut(&mut self) -> &mut FileDesc {
+ &mut self.0
+ }
+}
+
+impl IntoInner<FileDesc> for File {
+ fn into_inner(self) -> FileDesc {
+ self.0
+ }
+}
+
+impl FromInner<FileDesc> for File {
+ fn from_inner(file_desc: FileDesc) -> Self {
+ Self(file_desc)
+ }
+}
+
+impl AsFd for File {
+ fn as_fd(&self) -> BorrowedFd<'_> {
+ self.0.as_fd()
+ }
+}
+
+impl AsRawFd for File {
+ fn as_raw_fd(&self) -> RawFd {
+ self.0.as_raw_fd()
+ }
+}
+
+impl IntoRawFd for File {
+ fn into_raw_fd(self) -> RawFd {
+ self.0.into_raw_fd()
+ }
+}
+
+impl FromRawFd for File {
+ unsafe fn from_raw_fd(raw_fd: RawFd) -> Self {
+ Self(FromRawFd::from_raw_fd(raw_fd))
+ }
+}
+
pub fn readdir(_p: &Path) -> io::Result<ReadDir> {
unsupported()
}
diff --git a/library/std/src/sys/hermit/mod.rs b/library/std/src/sys/hermit/mod.rs
index 6811fadb0..d34a4cfed 100644
--- a/library/std/src/sys/hermit/mod.rs
+++ b/library/std/src/sys/hermit/mod.rs
@@ -13,7 +13,7 @@
//! compiling for wasm. That way it's a compile time error for something that's
//! guaranteed to be a runtime error!
-#![allow(unsafe_op_in_unsafe_fn)]
+#![allow(missing_docs, nonstandard_style, unsafe_op_in_unsafe_fn)]
use crate::intrinsics;
use crate::os::raw::c_char;
@@ -57,9 +57,7 @@ pub mod locks {
}
use crate::io::ErrorKind;
-
-#[allow(unused_extern_crates)]
-pub extern crate hermit_abi as abi;
+use crate::os::hermit::abi;
pub fn unsupported<T>() -> crate::io::Result<T> {
Err(unsupported_err())
@@ -72,11 +70,6 @@ pub fn unsupported_err() -> crate::io::Error {
)
}
-#[no_mangle]
-pub extern "C" fn floor(x: f64) -> f64 {
- unsafe { intrinsics::floorf64(x) }
-}
-
pub fn abort_internal() -> ! {
unsafe {
abi::abort();
@@ -131,25 +124,72 @@ pub unsafe extern "C" fn runtime_entry(
pub fn decode_error_kind(errno: i32) -> ErrorKind {
match errno {
- x if x == 13 as i32 => ErrorKind::PermissionDenied,
- x if x == 98 as i32 => ErrorKind::AddrInUse,
- x if x == 99 as i32 => ErrorKind::AddrNotAvailable,
- x if x == 11 as i32 => ErrorKind::WouldBlock,
- x if x == 103 as i32 => ErrorKind::ConnectionAborted,
- x if x == 111 as i32 => ErrorKind::ConnectionRefused,
- x if x == 104 as i32 => ErrorKind::ConnectionReset,
- x if x == 17 as i32 => ErrorKind::AlreadyExists,
- x if x == 4 as i32 => ErrorKind::Interrupted,
- x if x == 22 as i32 => ErrorKind::InvalidInput,
- x if x == 2 as i32 => ErrorKind::NotFound,
- x if x == 107 as i32 => ErrorKind::NotConnected,
- x if x == 1 as i32 => ErrorKind::PermissionDenied,
- x if x == 32 as i32 => ErrorKind::BrokenPipe,
- x if x == 110 as i32 => ErrorKind::TimedOut,
+ abi::errno::EACCES => ErrorKind::PermissionDenied,
+ abi::errno::EADDRINUSE => ErrorKind::AddrInUse,
+ abi::errno::EADDRNOTAVAIL => ErrorKind::AddrNotAvailable,
+ abi::errno::EAGAIN => ErrorKind::WouldBlock,
+ abi::errno::ECONNABORTED => ErrorKind::ConnectionAborted,
+ abi::errno::ECONNREFUSED => ErrorKind::ConnectionRefused,
+ abi::errno::ECONNRESET => ErrorKind::ConnectionReset,
+ abi::errno::EEXIST => ErrorKind::AlreadyExists,
+ abi::errno::EINTR => ErrorKind::Interrupted,
+ abi::errno::EINVAL => ErrorKind::InvalidInput,
+ abi::errno::ENOENT => ErrorKind::NotFound,
+ abi::errno::ENOTCONN => ErrorKind::NotConnected,
+ abi::errno::EPERM => ErrorKind::PermissionDenied,
+ abi::errno::EPIPE => ErrorKind::BrokenPipe,
+ abi::errno::ETIMEDOUT => ErrorKind::TimedOut,
_ => ErrorKind::Uncategorized,
}
}
-pub fn cvt(result: i32) -> crate::io::Result<usize> {
- if result < 0 { Err(crate::io::Error::from_raw_os_error(-result)) } else { Ok(result as usize) }
+#[doc(hidden)]
+pub trait IsNegative {
+ fn is_negative(&self) -> bool;
+ fn negate(&self) -> i32;
+}
+
+macro_rules! impl_is_negative {
+ ($($t:ident)*) => ($(impl IsNegative for $t {
+ fn is_negative(&self) -> bool {
+ *self < 0
+ }
+
+ fn negate(&self) -> i32 {
+ i32::try_from(-(*self)).unwrap()
+ }
+ })*)
+}
+
+impl IsNegative for i32 {
+ fn is_negative(&self) -> bool {
+ *self < 0
+ }
+
+ fn negate(&self) -> i32 {
+ -(*self)
+ }
+}
+impl_is_negative! { i8 i16 i64 isize }
+
+pub fn cvt<T: IsNegative>(t: T) -> crate::io::Result<T> {
+ if t.is_negative() {
+ let e = decode_error_kind(t.negate());
+ Err(crate::io::Error::from(e))
+ } else {
+ Ok(t)
+ }
+}
+
+pub fn cvt_r<T, F>(mut f: F) -> crate::io::Result<T>
+where
+ T: IsNegative,
+ F: FnMut() -> T,
+{
+ loop {
+ match cvt(f()) {
+ Err(ref e) if e.kind() == ErrorKind::Interrupted => {}
+ other => return other,
+ }
+ }
}
diff --git a/library/std/src/sys/hermit/net.rs b/library/std/src/sys/hermit/net.rs
index 8a13879d8..5fb6281aa 100644
--- a/library/std/src/sys/hermit/net.rs
+++ b/library/std/src/sys/hermit/net.rs
@@ -1,490 +1,353 @@
-use crate::fmt;
-use crate::io::{self, ErrorKind, IoSlice, IoSliceMut};
-use crate::net::{IpAddr, Ipv4Addr, Ipv6Addr, Shutdown, SocketAddr};
-use crate::str;
-use crate::sync::Arc;
-use crate::sys::hermit::abi;
-use crate::sys::hermit::abi::IpAddress::{Ipv4, Ipv6};
-use crate::sys::unsupported;
-use crate::sys_common::AsInner;
+#![allow(dead_code)]
+
+use crate::cmp;
+use crate::io::{self, IoSlice, IoSliceMut};
+use crate::mem;
+use crate::net::{Shutdown, SocketAddr};
+use crate::os::hermit::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, RawFd};
+use crate::sys::hermit::fd::FileDesc;
+use crate::sys::time::Instant;
+use crate::sys_common::net::{getsockopt, setsockopt, sockaddr_to_addr};
+use crate::sys_common::{AsInner, FromInner, IntoInner};
use crate::time::Duration;
-/// Checks whether the HermitCore's socket interface has been started already, and
-/// if not, starts it.
-pub fn init() -> io::Result<()> {
- if abi::network_init() < 0 {
- return Err(io::const_io_error!(
- ErrorKind::Uncategorized,
- "Unable to initialize network interface",
- ));
- }
-
- Ok(())
-}
-
-#[derive(Debug, Clone)]
-pub struct Socket(abi::Handle);
-
-impl AsInner<abi::Handle> for Socket {
- fn as_inner(&self) -> &abi::Handle {
- &self.0
- }
-}
+use core::ffi::c_int;
-impl Drop for Socket {
- fn drop(&mut self) {
- let _ = abi::tcpstream::close(self.0);
- }
-}
+#[allow(unused_extern_crates)]
+pub extern crate hermit_abi as netc;
-// Arc is used to count the number of used sockets.
-// Only if all sockets are released, the drop
-// method will close the socket.
-#[derive(Clone)]
-pub struct TcpStream(Arc<Socket>);
-
-impl TcpStream {
- pub fn connect(addr: io::Result<&SocketAddr>) -> io::Result<TcpStream> {
- let addr = addr?;
-
- match abi::tcpstream::connect(addr.ip().to_string().as_bytes(), addr.port(), None) {
- Ok(handle) => Ok(TcpStream(Arc::new(Socket(handle)))),
- _ => Err(io::const_io_error!(
- ErrorKind::Uncategorized,
- "Unable to initiate a connection on a socket",
- )),
- }
- }
+pub use crate::sys::{cvt, cvt_r};
- pub fn connect_timeout(saddr: &SocketAddr, duration: Duration) -> io::Result<TcpStream> {
- match abi::tcpstream::connect(
- saddr.ip().to_string().as_bytes(),
- saddr.port(),
- Some(duration.as_millis() as u64),
- ) {
- Ok(handle) => Ok(TcpStream(Arc::new(Socket(handle)))),
- _ => Err(io::const_io_error!(
- ErrorKind::Uncategorized,
- "Unable to initiate a connection on a socket",
- )),
- }
- }
+pub type wrlen_t = usize;
- pub fn set_read_timeout(&self, duration: Option<Duration>) -> io::Result<()> {
- abi::tcpstream::set_read_timeout(*self.0.as_inner(), duration.map(|d| d.as_millis() as u64))
- .map_err(|_| {
- io::const_io_error!(ErrorKind::Uncategorized, "Unable to set timeout value")
- })
+pub fn cvt_gai(err: i32) -> io::Result<()> {
+ if err == 0 {
+ return Ok(());
}
- pub fn set_write_timeout(&self, duration: Option<Duration>) -> io::Result<()> {
- abi::tcpstream::set_write_timeout(
- *self.0.as_inner(),
- duration.map(|d| d.as_millis() as u64),
- )
- .map_err(|_| io::const_io_error!(ErrorKind::Uncategorized, "Unable to set timeout value"))
- }
+ let detail = "";
- pub fn read_timeout(&self) -> io::Result<Option<Duration>> {
- let duration = abi::tcpstream::get_read_timeout(*self.0.as_inner()).map_err(|_| {
- io::const_io_error!(ErrorKind::Uncategorized, "Unable to determine timeout value")
- })?;
+ Err(io::Error::new(
+ io::ErrorKind::Uncategorized,
+ &format!("failed to lookup address information: {detail}")[..],
+ ))
+}
- Ok(duration.map(|d| Duration::from_millis(d)))
+/// Checks whether the HermitCore's socket interface has been started already, and
+/// if not, starts it.
+pub fn init() {
+ if unsafe { netc::network_init() } < 0 {
+ panic!("Unable to initialize network interface");
}
+}
- pub fn write_timeout(&self) -> io::Result<Option<Duration>> {
- let duration = abi::tcpstream::get_write_timeout(*self.0.as_inner()).map_err(|_| {
- io::const_io_error!(ErrorKind::Uncategorized, "Unable to determine timeout value")
- })?;
+#[derive(Debug)]
+pub struct Socket(FileDesc);
- Ok(duration.map(|d| Duration::from_millis(d)))
+impl Socket {
+ pub fn new(addr: &SocketAddr, ty: i32) -> io::Result<Socket> {
+ let fam = match *addr {
+ SocketAddr::V4(..) => netc::AF_INET,
+ SocketAddr::V6(..) => netc::AF_INET6,
+ };
+ Socket::new_raw(fam, ty)
}
- pub fn peek(&self, buf: &mut [u8]) -> io::Result<usize> {
- abi::tcpstream::peek(*self.0.as_inner(), buf)
- .map_err(|_| io::const_io_error!(ErrorKind::Uncategorized, "peek failed"))
+ pub fn new_raw(fam: i32, ty: i32) -> io::Result<Socket> {
+ let fd = cvt(unsafe { netc::socket(fam, ty, 0) })?;
+ Ok(Socket(unsafe { FileDesc::from_raw_fd(fd) }))
}
- pub fn read(&self, buffer: &mut [u8]) -> io::Result<usize> {
- self.read_vectored(&mut [IoSliceMut::new(buffer)])
+ pub fn new_pair(_fam: i32, _ty: i32) -> io::Result<(Socket, Socket)> {
+ unimplemented!()
}
- pub fn read_vectored(&self, ioslice: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
- let mut size: usize = 0;
-
- for i in ioslice.iter_mut() {
- let ret = abi::tcpstream::read(*self.0.as_inner(), &mut i[0..]).map_err(|_| {
- io::const_io_error!(ErrorKind::Uncategorized, "Unable to read on socket")
- })?;
+ pub fn connect_timeout(&self, addr: &SocketAddr, timeout: Duration) -> io::Result<()> {
+ self.set_nonblocking(true)?;
+ let r = unsafe {
+ let (addr, len) = addr.into_inner();
+ cvt(netc::connect(self.as_raw_fd(), addr.as_ptr(), len))
+ };
+ self.set_nonblocking(false)?;
- if ret != 0 {
- size += ret;
- }
+ match r {
+ Ok(_) => return Ok(()),
+ // there's no ErrorKind for EINPROGRESS :(
+ Err(ref e) if e.raw_os_error() == Some(netc::errno::EINPROGRESS) => {}
+ Err(e) => return Err(e),
}
- Ok(size)
- }
-
- #[inline]
- pub fn is_read_vectored(&self) -> bool {
- true
- }
-
- pub fn write(&self, buffer: &[u8]) -> io::Result<usize> {
- self.write_vectored(&[IoSlice::new(buffer)])
- }
+ let mut pollfd = netc::pollfd { fd: self.as_raw_fd(), events: netc::POLLOUT, revents: 0 };
- pub fn write_vectored(&self, ioslice: &[IoSlice<'_>]) -> io::Result<usize> {
- let mut size: usize = 0;
-
- for i in ioslice.iter() {
- size += abi::tcpstream::write(*self.0.as_inner(), i).map_err(|_| {
- io::const_io_error!(ErrorKind::Uncategorized, "Unable to write on socket")
- })?;
+ if timeout.as_secs() == 0 && timeout.subsec_nanos() == 0 {
+ return Err(io::const_io_error!(
+ io::ErrorKind::InvalidInput,
+ "cannot set a 0 duration timeout",
+ ));
}
- Ok(size)
- }
-
- #[inline]
- pub fn is_write_vectored(&self) -> bool {
- true
- }
-
- pub fn peer_addr(&self) -> io::Result<SocketAddr> {
- let (ipaddr, port) = abi::tcpstream::peer_addr(*self.0.as_inner())
- .map_err(|_| io::const_io_error!(ErrorKind::Uncategorized, "peer_addr failed"))?;
+ let start = Instant::now();
- let saddr = match ipaddr {
- Ipv4(ref addr) => SocketAddr::new(IpAddr::V4(Ipv4Addr::from(addr.0)), port),
- Ipv6(ref addr) => SocketAddr::new(IpAddr::V6(Ipv6Addr::from(addr.0)), port),
- _ => {
- return Err(io::const_io_error!(ErrorKind::Uncategorized, "peer_addr failed"));
+ loop {
+ let elapsed = start.elapsed();
+ if elapsed >= timeout {
+ return Err(io::const_io_error!(io::ErrorKind::TimedOut, "connection timed out"));
}
- };
-
- Ok(saddr)
- }
-
- pub fn socket_addr(&self) -> io::Result<SocketAddr> {
- unsupported()
- }
-
- pub fn shutdown(&self, how: Shutdown) -> io::Result<()> {
- abi::tcpstream::shutdown(*self.0.as_inner(), how as i32)
- .map_err(|_| io::const_io_error!(ErrorKind::Uncategorized, "unable to shutdown socket"))
- }
-
- pub fn duplicate(&self) -> io::Result<TcpStream> {
- Ok(self.clone())
- }
-
- pub fn set_linger(&self, _linger: Option<Duration>) -> io::Result<()> {
- unsupported()
- }
-
- pub fn linger(&self) -> io::Result<Option<Duration>> {
- unsupported()
- }
-
- pub fn set_nodelay(&self, mode: bool) -> io::Result<()> {
- abi::tcpstream::set_nodelay(*self.0.as_inner(), mode)
- .map_err(|_| io::const_io_error!(ErrorKind::Uncategorized, "set_nodelay failed"))
- }
-
- pub fn nodelay(&self) -> io::Result<bool> {
- abi::tcpstream::nodelay(*self.0.as_inner())
- .map_err(|_| io::const_io_error!(ErrorKind::Uncategorized, "nodelay failed"))
- }
-
- pub fn set_ttl(&self, tll: u32) -> io::Result<()> {
- abi::tcpstream::set_tll(*self.0.as_inner(), tll)
- .map_err(|_| io::const_io_error!(ErrorKind::Uncategorized, "unable to set TTL"))
- }
-
- pub fn ttl(&self) -> io::Result<u32> {
- abi::tcpstream::get_tll(*self.0.as_inner())
- .map_err(|_| io::const_io_error!(ErrorKind::Uncategorized, "unable to get TTL"))
- }
- pub fn take_error(&self) -> io::Result<Option<io::Error>> {
- unsupported()
- }
-
- pub fn set_nonblocking(&self, mode: bool) -> io::Result<()> {
- abi::tcpstream::set_nonblocking(*self.0.as_inner(), mode).map_err(|_| {
- io::const_io_error!(ErrorKind::Uncategorized, "unable to set blocking mode")
- })
- }
-}
-
-impl fmt::Debug for TcpStream {
- fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
- Ok(())
- }
-}
-
-#[derive(Clone)]
-pub struct TcpListener(SocketAddr);
-
-impl TcpListener {
- pub fn bind(addr: io::Result<&SocketAddr>) -> io::Result<TcpListener> {
- let addr = addr?;
-
- Ok(TcpListener(*addr))
- }
-
- pub fn socket_addr(&self) -> io::Result<SocketAddr> {
- Ok(self.0)
- }
-
- pub fn accept(&self) -> io::Result<(TcpStream, SocketAddr)> {
- let (handle, ipaddr, port) = abi::tcplistener::accept(self.0.port())
- .map_err(|_| io::const_io_error!(ErrorKind::Uncategorized, "accept failed"))?;
- let saddr = match ipaddr {
- Ipv4(ref addr) => SocketAddr::new(IpAddr::V4(Ipv4Addr::from(addr.0)), port),
- Ipv6(ref addr) => SocketAddr::new(IpAddr::V6(Ipv6Addr::from(addr.0)), port),
- _ => {
- return Err(io::const_io_error!(ErrorKind::Uncategorized, "accept failed"));
+ let timeout = timeout - elapsed;
+ let mut timeout = timeout
+ .as_secs()
+ .saturating_mul(1_000)
+ .saturating_add(timeout.subsec_nanos() as u64 / 1_000_000);
+ if timeout == 0 {
+ timeout = 1;
}
- };
-
- Ok((TcpStream(Arc::new(Socket(handle))), saddr))
- }
- pub fn duplicate(&self) -> io::Result<TcpListener> {
- Ok(self.clone())
- }
-
- pub fn set_ttl(&self, _: u32) -> io::Result<()> {
- unsupported()
- }
-
- pub fn ttl(&self) -> io::Result<u32> {
- unsupported()
- }
-
- pub fn set_only_v6(&self, _: bool) -> io::Result<()> {
- unsupported()
+ let timeout = cmp::min(timeout, c_int::MAX as u64) as c_int;
+
+ match unsafe { netc::poll(&mut pollfd, 1, timeout) } {
+ -1 => {
+ let err = io::Error::last_os_error();
+ if err.kind() != io::ErrorKind::Interrupted {
+ return Err(err);
+ }
+ }
+ 0 => {}
+ _ => {
+ // linux returns POLLOUT|POLLERR|POLLHUP for refused connections (!), so look
+ // for POLLHUP rather than read readiness
+ if pollfd.revents & netc::POLLHUP != 0 {
+ let e = self.take_error()?.unwrap_or_else(|| {
+ io::const_io_error!(
+ io::ErrorKind::Uncategorized,
+ "no error set after POLLHUP",
+ )
+ });
+ return Err(e);
+ }
+
+ return Ok(());
+ }
+ }
+ }
}
- pub fn only_v6(&self) -> io::Result<bool> {
- unsupported()
+ pub fn accept(
+ &self,
+ storage: *mut netc::sockaddr,
+ len: *mut netc::socklen_t,
+ ) -> io::Result<Socket> {
+ let fd = cvt(unsafe { netc::accept(self.0.as_raw_fd(), storage, len) })?;
+ Ok(Socket(unsafe { FileDesc::from_raw_fd(fd) }))
}
- pub fn take_error(&self) -> io::Result<Option<io::Error>> {
- unsupported()
+ pub fn duplicate(&self) -> io::Result<Socket> {
+ let fd = cvt(unsafe { netc::dup(self.0.as_raw_fd()) })?;
+ Ok(Socket(unsafe { FileDesc::from_raw_fd(fd) }))
}
- pub fn set_nonblocking(&self, _: bool) -> io::Result<()> {
- unsupported()
+ fn recv_with_flags(&self, buf: &mut [u8], flags: i32) -> io::Result<usize> {
+ let ret =
+ cvt(unsafe { netc::recv(self.0.as_raw_fd(), buf.as_mut_ptr(), buf.len(), flags) })?;
+ Ok(ret as usize)
}
-}
-impl fmt::Debug for TcpListener {
- fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
- Ok(())
+ pub fn read(&self, buf: &mut [u8]) -> io::Result<usize> {
+ self.recv_with_flags(buf, 0)
}
-}
-
-pub struct UdpSocket(abi::Handle);
-impl UdpSocket {
- pub fn bind(_: io::Result<&SocketAddr>) -> io::Result<UdpSocket> {
- unsupported()
+ pub fn peek(&self, buf: &mut [u8]) -> io::Result<usize> {
+ self.recv_with_flags(buf, netc::MSG_PEEK)
}
- pub fn peer_addr(&self) -> io::Result<SocketAddr> {
- unsupported()
- }
+ pub fn read_vectored(&self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
+ let mut size: isize = 0;
- pub fn socket_addr(&self) -> io::Result<SocketAddr> {
- unsupported()
- }
+ for i in bufs.iter_mut() {
+ let ret: isize =
+ cvt(unsafe { netc::read(self.0.as_raw_fd(), i.as_mut_ptr(), i.len()) })?;
- pub fn recv_from(&self, _: &mut [u8]) -> io::Result<(usize, SocketAddr)> {
- unsupported()
- }
+ if ret != 0 {
+ size += ret;
+ }
+ }
- pub fn peek_from(&self, _: &mut [u8]) -> io::Result<(usize, SocketAddr)> {
- unsupported()
+ Ok(size.try_into().unwrap())
}
- pub fn send_to(&self, _: &[u8], _: &SocketAddr) -> io::Result<usize> {
- unsupported()
+ #[inline]
+ pub fn is_read_vectored(&self) -> bool {
+ true
}
- pub fn duplicate(&self) -> io::Result<UdpSocket> {
- unsupported()
- }
+ fn recv_from_with_flags(&self, buf: &mut [u8], flags: i32) -> 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;
- pub fn set_read_timeout(&self, _: Option<Duration>) -> io::Result<()> {
- unsupported()
+ let n = cvt(unsafe {
+ netc::recvfrom(
+ self.as_raw_fd(),
+ buf.as_mut_ptr(),
+ buf.len(),
+ flags,
+ &mut storage as *mut _ as *mut _,
+ &mut addrlen,
+ )
+ })?;
+ Ok((n as usize, sockaddr_to_addr(&storage, addrlen as usize)?))
}
- pub fn set_write_timeout(&self, _: Option<Duration>) -> io::Result<()> {
- unsupported()
+ pub fn recv_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> {
+ self.recv_from_with_flags(buf, 0)
}
- pub fn read_timeout(&self) -> io::Result<Option<Duration>> {
- unsupported()
+ pub fn peek_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> {
+ self.recv_from_with_flags(buf, netc::MSG_PEEK)
}
- pub fn write_timeout(&self) -> io::Result<Option<Duration>> {
- unsupported()
+ pub fn write(&self, buf: &[u8]) -> io::Result<usize> {
+ let sz = cvt(unsafe { netc::write(self.0.as_raw_fd(), buf.as_ptr(), buf.len()) })?;
+ Ok(sz.try_into().unwrap())
}
- pub fn set_broadcast(&self, _: bool) -> io::Result<()> {
- unsupported()
- }
+ pub fn write_vectored(&self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
+ let mut size: isize = 0;
- pub fn broadcast(&self) -> io::Result<bool> {
- unsupported()
- }
+ for i in bufs.iter() {
+ size += cvt(unsafe { netc::write(self.0.as_raw_fd(), i.as_ptr(), i.len()) })?;
+ }
- pub fn set_multicast_loop_v4(&self, _: bool) -> io::Result<()> {
- unsupported()
+ Ok(size.try_into().unwrap())
}
- pub fn multicast_loop_v4(&self) -> io::Result<bool> {
- unsupported()
+ pub fn is_write_vectored(&self) -> bool {
+ true
}
- pub fn set_multicast_ttl_v4(&self, _: u32) -> io::Result<()> {
- unsupported()
- }
+ pub fn set_timeout(&self, dur: Option<Duration>, kind: i32) -> io::Result<()> {
+ let timeout = match dur {
+ Some(dur) => {
+ if dur.as_secs() == 0 && dur.subsec_nanos() == 0 {
+ return Err(io::const_io_error!(
+ io::ErrorKind::InvalidInput,
+ "cannot set a 0 duration timeout",
+ ));
+ }
+
+ let secs = if dur.as_secs() > netc::time_t::MAX as u64 {
+ netc::time_t::MAX
+ } else {
+ dur.as_secs() as netc::time_t
+ };
+ let mut timeout = netc::timeval {
+ tv_sec: secs,
+ tv_usec: dur.subsec_micros() as netc::suseconds_t,
+ };
+ if timeout.tv_sec == 0 && timeout.tv_usec == 0 {
+ timeout.tv_usec = 1;
+ }
+ timeout
+ }
+ None => netc::timeval { tv_sec: 0, tv_usec: 0 },
+ };
- pub fn multicast_ttl_v4(&self) -> io::Result<u32> {
- unsupported()
+ setsockopt(self, netc::SOL_SOCKET, kind, timeout)
}
- pub fn set_multicast_loop_v6(&self, _: bool) -> io::Result<()> {
- unsupported()
+ pub fn timeout(&self, kind: i32) -> io::Result<Option<Duration>> {
+ 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 multicast_loop_v6(&self) -> io::Result<bool> {
- unsupported()
+ 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_socket(self.as_raw_fd(), how) })?;
+ Ok(())
}
- pub fn join_multicast_v4(&self, _: &Ipv4Addr, _: &Ipv4Addr) -> io::Result<()> {
- unsupported()
- }
+ pub fn set_linger(&self, linger: Option<Duration>) -> io::Result<()> {
+ let linger = netc::linger {
+ l_onoff: linger.is_some() as i32,
+ l_linger: linger.unwrap_or_default().as_secs() as libc::c_int,
+ };
- pub fn join_multicast_v6(&self, _: &Ipv6Addr, _: u32) -> io::Result<()> {
- unsupported()
+ setsockopt(self, netc::SOL_SOCKET, netc::SO_LINGER, linger)
}
- pub fn leave_multicast_v4(&self, _: &Ipv4Addr, _: &Ipv4Addr) -> io::Result<()> {
- unsupported()
- }
+ pub fn linger(&self) -> io::Result<Option<Duration>> {
+ let val: netc::linger = getsockopt(self, netc::SOL_SOCKET, netc::SO_LINGER)?;
- pub fn leave_multicast_v6(&self, _: &Ipv6Addr, _: u32) -> io::Result<()> {
- unsupported()
+ Ok((val.l_onoff != 0).then(|| Duration::from_secs(val.l_linger as u64)))
}
- pub fn set_ttl(&self, _: u32) -> io::Result<()> {
- unsupported()
+ pub fn set_nodelay(&self, nodelay: bool) -> io::Result<()> {
+ let value: i32 = if nodelay { 1 } else { 0 };
+ setsockopt(self, netc::IPPROTO_TCP, netc::TCP_NODELAY, value)
}
- pub fn ttl(&self) -> io::Result<u32> {
- unsupported()
+ pub fn nodelay(&self) -> io::Result<bool> {
+ let raw: i32 = getsockopt(self, netc::IPPROTO_TCP, netc::TCP_NODELAY)?;
+ Ok(raw != 0)
+ }
+
+ pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> {
+ let mut nonblocking: i32 = if nonblocking { 1 } else { 0 };
+ cvt(unsafe {
+ netc::ioctl(
+ self.as_raw_fd(),
+ netc::FIONBIO,
+ &mut nonblocking as *mut _ as *mut core::ffi::c_void,
+ )
+ })
+ .map(drop)
}
pub fn take_error(&self) -> io::Result<Option<io::Error>> {
- unsupported()
- }
-
- pub fn set_nonblocking(&self, _: bool) -> io::Result<()> {
- unsupported()
- }
-
- pub fn recv(&self, _: &mut [u8]) -> io::Result<usize> {
- unsupported()
- }
-
- pub fn peek(&self, _: &mut [u8]) -> io::Result<usize> {
- unsupported()
+ unimplemented!()
}
- pub fn send(&self, _: &[u8]) -> io::Result<usize> {
- unsupported()
- }
-
- pub fn connect(&self, _: io::Result<&SocketAddr>) -> io::Result<()> {
- unsupported()
+ // This is used by sys_common code to abstract over Windows and Unix.
+ pub fn as_raw(&self) -> RawFd {
+ self.0.as_raw_fd()
}
}
-impl fmt::Debug for UdpSocket {
- fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
- Ok(())
+impl AsInner<FileDesc> for Socket {
+ fn as_inner(&self) -> &FileDesc {
+ &self.0
}
}
-pub struct LookupHost(!);
-
-impl LookupHost {
- pub fn port(&self) -> u16 {
+impl IntoInner<FileDesc> for Socket {
+ fn into_inner(self) -> FileDesc {
self.0
}
}
-impl Iterator for LookupHost {
- type Item = SocketAddr;
- fn next(&mut self) -> Option<SocketAddr> {
- self.0
+impl FromInner<FileDesc> for Socket {
+ fn from_inner(file_desc: FileDesc) -> Self {
+ Self(file_desc)
}
}
-impl TryFrom<&str> for LookupHost {
- type Error = io::Error;
-
- fn try_from(_v: &str) -> io::Result<LookupHost> {
- unsupported()
+impl AsFd for Socket {
+ fn as_fd(&self) -> BorrowedFd<'_> {
+ self.0.as_fd()
}
}
-impl<'a> TryFrom<(&'a str, u16)> for LookupHost {
- type Error = io::Error;
-
- fn try_from(_v: (&'a str, u16)) -> io::Result<LookupHost> {
- unsupported()
+impl AsRawFd for Socket {
+ fn as_raw_fd(&self) -> RawFd {
+ self.0.as_raw_fd()
}
}
-
-#[allow(nonstandard_style)]
-pub mod netc {
- pub const AF_INET: u8 = 0;
- pub const AF_INET6: u8 = 1;
- pub type sa_family_t = u8;
-
- #[derive(Copy, Clone)]
- pub struct in_addr {
- pub s_addr: u32,
- }
-
- #[derive(Copy, Clone)]
- pub struct sockaddr_in {
- pub sin_family: sa_family_t,
- pub sin_port: u16,
- pub sin_addr: in_addr,
- }
-
- #[derive(Copy, Clone)]
- pub struct in6_addr {
- pub s6_addr: [u8; 16],
- }
-
- #[derive(Copy, Clone)]
- pub struct sockaddr_in6 {
- pub sin6_family: sa_family_t,
- pub sin6_port: u16,
- pub sin6_addr: in6_addr,
- pub sin6_flowinfo: u32,
- pub sin6_scope_id: u32,
- }
-
- #[derive(Copy, Clone)]
- pub struct sockaddr {}
-}
diff --git a/library/std/src/sys/hermit/os.rs b/library/std/src/sys/hermit/os.rs
index 8f927df85..e53dbae61 100644
--- a/library/std/src/sys/hermit/os.rs
+++ b/library/std/src/sys/hermit/os.rs
@@ -4,7 +4,7 @@ use crate::ffi::{CStr, OsStr, OsString};
use crate::fmt;
use crate::io;
use crate::marker::PhantomData;
-use crate::os::unix::ffi::OsStringExt;
+use crate::os::hermit::ffi::OsStringExt;
use crate::path::{self, PathBuf};
use crate::str;
use crate::sync::Mutex;
diff --git a/library/std/src/sys/hermit/thread.rs b/library/std/src/sys/hermit/thread.rs
index 8f65544a9..2507f7069 100644
--- a/library/std/src/sys/hermit/thread.rs
+++ b/library/std/src/sys/hermit/thread.rs
@@ -27,10 +27,10 @@ impl Thread {
p: Box<dyn FnOnce()>,
core_id: isize,
) -> io::Result<Thread> {
- let p = Box::into_raw(box p);
+ let p = Box::into_raw(Box::new(p));
let tid = abi::spawn2(
thread_start,
- p as usize,
+ p.expose_addr(),
abi::Priority::into(abi::NORMAL_PRIO),
stack,
core_id,
diff --git a/library/std/src/sys/hermit/thread_local_dtor.rs b/library/std/src/sys/hermit/thread_local_dtor.rs
index 9b683fce1..613266b95 100644
--- a/library/std/src/sys/hermit/thread_local_dtor.rs
+++ b/library/std/src/sys/hermit/thread_local_dtor.rs
@@ -5,32 +5,23 @@
// The this solution works like the implementation of macOS and
// doesn't additional OS support
-use crate::cell::Cell;
-use crate::ptr;
+use crate::mem;
#[thread_local]
-static DTORS: Cell<*mut List> = Cell::new(ptr::null_mut());
-
-type List = Vec<(*mut u8, unsafe extern "C" fn(*mut u8))>;
+static mut DTORS: Vec<(*mut u8, unsafe extern "C" fn(*mut u8))> = Vec::new();
pub unsafe fn register_dtor(t: *mut u8, dtor: unsafe extern "C" fn(*mut u8)) {
- if DTORS.get().is_null() {
- let v: Box<List> = box Vec::new();
- DTORS.set(Box::into_raw(v));
- }
-
- let list: &mut List = &mut *DTORS.get();
+ let list = &mut DTORS;
list.push((t, dtor));
}
// every thread call this function to run through all possible destructors
pub unsafe fn run_dtors() {
- let mut ptr = DTORS.replace(ptr::null_mut());
- while !ptr.is_null() {
- let list = Box::from_raw(ptr);
- for (ptr, dtor) in list.into_iter() {
+ let mut list = mem::take(&mut DTORS);
+ while !list.is_empty() {
+ for (ptr, dtor) in list {
dtor(ptr);
}
- ptr = DTORS.replace(ptr::null_mut());
+ list = mem::take(&mut DTORS);
}
}
diff --git a/library/std/src/sys/hermit/time.rs b/library/std/src/sys/hermit/time.rs
index c17e6c8af..32ddc4346 100644
--- a/library/std/src/sys/hermit/time.rs
+++ b/library/std/src/sys/hermit/time.rs
@@ -1,6 +1,7 @@
#![allow(dead_code)]
use crate::cmp::Ordering;
+use crate::ops::{Add, AddAssign, Sub, SubAssign};
use crate::sys::hermit::abi;
use crate::sys::hermit::abi::timespec;
use crate::sys::hermit::abi::{CLOCK_MONOTONIC, CLOCK_REALTIME, NSEC_PER_SEC};
@@ -102,55 +103,122 @@ impl Hash for Timespec {
}
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)]
-pub struct Instant {
- t: Timespec,
-}
+pub struct Instant(Timespec);
impl Instant {
pub fn now() -> Instant {
let mut time: Timespec = Timespec::zero();
let _ = unsafe { abi::clock_gettime(CLOCK_MONOTONIC, &mut time.t as *mut timespec) };
- Instant { t: time }
+ Instant(time)
+ }
+
+ #[stable(feature = "time2", since = "1.8.0")]
+ pub fn elapsed(&self) -> Duration {
+ Instant::now() - *self
+ }
+
+ pub fn duration_since(&self, earlier: Instant) -> Duration {
+ self.checked_duration_since(earlier).unwrap_or_default()
+ }
+
+ pub fn checked_duration_since(&self, earlier: Instant) -> Option<Duration> {
+ self.checked_sub_instant(&earlier)
}
pub fn checked_sub_instant(&self, other: &Instant) -> Option<Duration> {
- self.t.sub_timespec(&other.t).ok()
+ self.0.sub_timespec(&other.0).ok()
}
pub fn checked_add_duration(&self, other: &Duration) -> Option<Instant> {
- Some(Instant { t: self.t.checked_add_duration(other)? })
+ Some(Instant(self.0.checked_add_duration(other)?))
}
pub fn checked_sub_duration(&self, other: &Duration) -> Option<Instant> {
- Some(Instant { t: self.t.checked_sub_duration(other)? })
+ Some(Instant(self.0.checked_sub_duration(other)?))
+ }
+
+ pub fn checked_add(&self, duration: Duration) -> Option<Instant> {
+ self.0.checked_add_duration(&duration).map(Instant)
+ }
+
+ pub fn checked_sub(&self, duration: Duration) -> Option<Instant> {
+ self.0.checked_sub_duration(&duration).map(Instant)
}
}
-#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
-pub struct SystemTime {
- t: Timespec,
+impl Add<Duration> for Instant {
+ type Output = Instant;
+
+ /// # Panics
+ ///
+ /// This function may panic if the resulting point in time cannot be represented by the
+ /// underlying data structure. See [`Instant::checked_add`] for a version without panic.
+ fn add(self, other: Duration) -> Instant {
+ self.checked_add(other).expect("overflow when adding duration to instant")
+ }
}
-pub const UNIX_EPOCH: SystemTime = SystemTime { t: Timespec::zero() };
+impl AddAssign<Duration> for Instant {
+ fn add_assign(&mut self, other: Duration) {
+ *self = *self + other;
+ }
+}
+
+impl Sub<Duration> for Instant {
+ type Output = Instant;
+
+ fn sub(self, other: Duration) -> Instant {
+ self.checked_sub(other).expect("overflow when subtracting duration from instant")
+ }
+}
+
+impl SubAssign<Duration> for Instant {
+ fn sub_assign(&mut self, other: Duration) {
+ *self = *self - other;
+ }
+}
+
+impl Sub<Instant> for Instant {
+ type Output = Duration;
+
+ /// Returns the amount of time elapsed from another instant to this one,
+ /// or zero duration if that instant is later than this one.
+ ///
+ /// # Panics
+ ///
+ /// Previous rust versions panicked when `other` was later than `self`. Currently this
+ /// method saturates. Future versions may reintroduce the panic in some circumstances.
+ /// See [Monotonicity].
+ ///
+ /// [Monotonicity]: Instant#monotonicity
+ fn sub(self, other: Instant) -> Duration {
+ self.duration_since(other)
+ }
+}
+
+#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
+pub struct SystemTime(Timespec);
+
+pub const UNIX_EPOCH: SystemTime = SystemTime(Timespec::zero());
impl SystemTime {
pub fn now() -> SystemTime {
let mut time: Timespec = Timespec::zero();
let _ = unsafe { abi::clock_gettime(CLOCK_REALTIME, &mut time.t as *mut timespec) };
- SystemTime { t: time }
+ SystemTime(time)
}
pub fn sub_time(&self, other: &SystemTime) -> Result<Duration, Duration> {
- self.t.sub_timespec(&other.t)
+ self.0.sub_timespec(&other.0)
}
pub fn checked_add_duration(&self, other: &Duration) -> Option<SystemTime> {
- Some(SystemTime { t: self.t.checked_add_duration(other)? })
+ Some(SystemTime(self.0.checked_add_duration(other)?))
}
pub fn checked_sub_duration(&self, other: &Duration) -> Option<SystemTime> {
- Some(SystemTime { t: self.t.checked_sub_duration(other)? })
+ Some(SystemTime(self.0.checked_sub_duration(other)?))
}
}
diff --git a/library/std/src/sys/itron/thread.rs b/library/std/src/sys/itron/thread.rs
index 19350b83f..ae0f71853 100644
--- a/library/std/src/sys/itron/thread.rs
+++ b/library/std/src/sys/itron/thread.rs
@@ -247,7 +247,7 @@ impl Thread {
// [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`.
+ // `Ordering::Acquire` must be used for the above `swap` call.
}
_ => unsafe { hint::unreachable_unchecked() },
}
diff --git a/library/std/src/sys/itron/thread_parking.rs b/library/std/src/sys/itron/thread_parking.rs
new file mode 100644
index 000000000..fe9934439
--- /dev/null
+++ b/library/std/src/sys/itron/thread_parking.rs
@@ -0,0 +1,37 @@
+use super::abi;
+use super::error::expect_success_aborting;
+use super::time::with_tmos;
+use crate::time::Duration;
+
+pub type ThreadId = abi::ID;
+
+pub use super::task::current_task_id_aborting as current;
+
+pub fn park(_hint: usize) {
+ match unsafe { abi::slp_tsk() } {
+ abi::E_OK | abi::E_RLWAI => {}
+ err => {
+ expect_success_aborting(err, &"slp_tsk");
+ }
+ }
+}
+
+pub fn park_timeout(dur: Duration, _hint: usize) {
+ match with_tmos(dur, |tmo| unsafe { abi::tslp_tsk(tmo) }) {
+ abi::E_OK | abi::E_RLWAI | abi::E_TMOUT => {}
+ err => {
+ expect_success_aborting(err, &"tslp_tsk");
+ }
+ }
+}
+
+pub fn unpark(id: ThreadId, _hint: usize) {
+ match unsafe { abi::wup_tsk(id) } {
+ // It is allowed to try to wake up a destroyed or unrelated task, so we ignore all
+ // errors that could result from that situation.
+ abi::E_OK | abi::E_NOEXS | abi::E_OBJ | abi::E_QOVR => {}
+ err => {
+ expect_success_aborting(err, &"wup_tsk");
+ }
+ }
+}
diff --git a/library/std/src/sys/itron/wait_flag.rs b/library/std/src/sys/itron/wait_flag.rs
deleted file mode 100644
index e432edd20..000000000
--- a/library/std/src/sys/itron/wait_flag.rs
+++ /dev/null
@@ -1,72 +0,0 @@
-use crate::mem::MaybeUninit;
-use crate::time::Duration;
-
-use super::{
- abi,
- error::{expect_success, fail},
- time::with_tmos,
-};
-
-const CLEAR: abi::FLGPTN = 0;
-const RAISED: abi::FLGPTN = 1;
-
-/// A thread parking primitive that is not susceptible to race conditions,
-/// but provides no atomic ordering guarantees and allows only one `raise` per wait.
-pub struct WaitFlag {
- flag: abi::ID,
-}
-
-impl WaitFlag {
- /// Creates a new wait flag.
- pub fn new() -> WaitFlag {
- let flag = expect_success(
- unsafe {
- abi::acre_flg(&abi::T_CFLG {
- flgatr: abi::TA_FIFO | abi::TA_WSGL | abi::TA_CLR,
- iflgptn: CLEAR,
- })
- },
- &"acre_flg",
- );
-
- WaitFlag { flag }
- }
-
- /// Wait for the wait flag to be raised.
- pub fn wait(&self) {
- let mut token = MaybeUninit::uninit();
- expect_success(
- unsafe { abi::wai_flg(self.flag, RAISED, abi::TWF_ORW, token.as_mut_ptr()) },
- &"wai_flg",
- );
- }
-
- /// Wait for the wait flag to be raised or the timeout to occur.
- ///
- /// Returns whether the flag was raised (`true`) or the operation timed out (`false`).
- pub fn wait_timeout(&self, dur: Duration) -> bool {
- let mut token = MaybeUninit::uninit();
- let res = with_tmos(dur, |tmout| unsafe {
- abi::twai_flg(self.flag, RAISED, abi::TWF_ORW, token.as_mut_ptr(), tmout)
- });
-
- match res {
- abi::E_OK => true,
- abi::E_TMOUT => false,
- error => fail(error, &"twai_flg"),
- }
- }
-
- /// Raise the wait flag.
- ///
- /// Calls to this function should be balanced with the number of successful waits.
- pub fn raise(&self) {
- expect_success(unsafe { abi::set_flg(self.flag, RAISED) }, &"set_flg");
- }
-}
-
-impl Drop for WaitFlag {
- fn drop(&mut self) {
- expect_success(unsafe { abi::del_flg(self.flag) }, &"del_flg");
- }
-}
diff --git a/library/std/src/sys/solid/mod.rs b/library/std/src/sys/solid/mod.rs
index 5867979a2..923d27fd9 100644
--- a/library/std/src/sys/solid/mod.rs
+++ b/library/std/src/sys/solid/mod.rs
@@ -13,9 +13,9 @@ mod itron {
pub(super) mod spin;
pub(super) mod task;
pub mod thread;
+ pub mod thread_parking;
pub(super) mod time;
use super::unsupported;
- pub mod wait_flag;
}
pub mod alloc;
@@ -43,8 +43,8 @@ pub use self::itron::thread;
pub mod memchr;
pub mod thread_local_dtor;
pub mod thread_local_key;
+pub use self::itron::thread_parking;
pub mod time;
-pub use self::itron::wait_flag;
mod rwlock;
diff --git a/library/std/src/sys/solid/thread_local_dtor.rs b/library/std/src/sys/solid/thread_local_dtor.rs
index 973564570..bad14bb37 100644
--- a/library/std/src/sys/solid/thread_local_dtor.rs
+++ b/library/std/src/sys/solid/thread_local_dtor.rs
@@ -5,43 +5,35 @@
use super::{abi, itron::task};
use crate::cell::Cell;
-use crate::ptr;
+use crate::mem;
#[thread_local]
-static DTORS: Cell<*mut List> = Cell::new(ptr::null_mut());
+static REGISTERED: Cell<bool> = Cell::new(false);
-type List = Vec<(*mut u8, unsafe extern "C" fn(*mut u8))>;
+#[thread_local]
+static mut DTORS: Vec<(*mut u8, unsafe extern "C" fn(*mut u8))> = Vec::new();
pub unsafe fn register_dtor(t: *mut u8, dtor: unsafe extern "C" fn(*mut u8)) {
- if DTORS.get().is_null() {
+ if !REGISTERED.get() {
let tid = task::current_task_id_aborting();
- let v: Box<List> = 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) };
+ REGISTERED.set(true);
}
- let list: &mut List = unsafe { &mut *DTORS.get() };
+ let list = unsafe { &mut DTORS };
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) };
- }
+ let mut list = mem::take(unsafe { &mut DTORS });
+ while !list.is_empty() {
+ for (ptr, dtor) in list {
+ unsafe { dtor(ptr) };
}
- // Drop the destructor list
- unsafe { Box::from_raw(DTORS.replace(ptr::null_mut())) };
+ list = mem::take(unsafe { &mut DTORS });
}
}
diff --git a/library/std/src/sys/unix/args.rs b/library/std/src/sys/unix/args.rs
index a342f0f5e..3d79058b3 100644
--- a/library/std/src/sys/unix/args.rs
+++ b/library/std/src/sys/unix/args.rs
@@ -69,7 +69,8 @@ impl DoubleEndedIterator for Args {
target_os = "fuchsia",
target_os = "redox",
target_os = "vxworks",
- target_os = "horizon"
+ target_os = "horizon",
+ target_os = "nto",
))]
mod imp {
use super::Args;
@@ -141,12 +142,28 @@ mod imp {
// list.
let argv = ARGV.load(Ordering::Relaxed);
let argc = if argv.is_null() { 0 } else { ARGC.load(Ordering::Relaxed) };
- (0..argc)
- .map(|i| {
- let cstr = CStr::from_ptr(*argv.offset(i) as *const libc::c_char);
- OsStringExt::from_vec(cstr.to_bytes().to_vec())
- })
- .collect()
+ let mut args = Vec::with_capacity(argc as usize);
+ for i in 0..argc {
+ let ptr = *argv.offset(i) as *const libc::c_char;
+
+ // Some C commandline parsers (e.g. GLib and Qt) are replacing already
+ // handled arguments in `argv` with `NULL` and move them to the end. That
+ // means that `argc` might be bigger than the actual number of non-`NULL`
+ // pointers in `argv` at this point.
+ //
+ // To handle this we simply stop iterating at the first `NULL` argument.
+ //
+ // `argv` is also guaranteed to be `NULL`-terminated so any non-`NULL` arguments
+ // after the first `NULL` can safely be ignored.
+ if ptr.is_null() {
+ break;
+ }
+
+ let cstr = CStr::from_ptr(ptr);
+ args.push(OsStringExt::from_vec(cstr.to_bytes().to_vec()));
+ }
+
+ args
}
}
}
diff --git a/library/std/src/sys/unix/env.rs b/library/std/src/sys/unix/env.rs
index c9ba661c8..1a9276f11 100644
--- a/library/std/src/sys/unix/env.rs
+++ b/library/std/src/sys/unix/env.rs
@@ -185,6 +185,17 @@ pub mod os {
pub const EXE_EXTENSION: &str = "";
}
+#[cfg(target_os = "nto")]
+pub mod os {
+ pub const FAMILY: &str = "unix";
+ pub const OS: &str = "nto";
+ pub const DLL_PREFIX: &str = "lib";
+ pub const DLL_SUFFIX: &str = ".so";
+ pub const DLL_EXTENSION: &str = "so";
+ pub const EXE_SUFFIX: &str = "";
+ pub const EXE_EXTENSION: &str = "";
+}
+
#[cfg(target_os = "redox")]
pub mod os {
pub const FAMILY: &str = "unix";
diff --git a/library/std/src/sys/unix/fd.rs b/library/std/src/sys/unix/fd.rs
index dbaa3c33e..9874af4d3 100644
--- a/library/std/src/sys/unix/fd.rs
+++ b/library/std/src/sys/unix/fd.rs
@@ -53,7 +53,12 @@ const fn max_iov() -> usize {
libc::IOV_MAX as usize
}
-#[cfg(any(target_os = "android", target_os = "emscripten", target_os = "linux"))]
+#[cfg(any(
+ target_os = "android",
+ target_os = "emscripten",
+ target_os = "linux",
+ target_os = "nto",
+))]
const fn max_iov() -> usize {
libc::UIO_MAXIOV as usize
}
@@ -67,6 +72,7 @@ const fn max_iov() -> usize {
target_os = "linux",
target_os = "macos",
target_os = "netbsd",
+ target_os = "nto",
target_os = "openbsd",
target_os = "horizon",
target_os = "watchos",
@@ -92,7 +98,7 @@ impl FileDesc {
let ret = cvt(unsafe {
libc::readv(
self.as_raw_fd(),
- bufs.as_ptr() as *const libc::iovec,
+ bufs.as_mut_ptr() as *mut libc::iovec as *const libc::iovec,
cmp::min(bufs.len(), max_iov()) as libc::c_int,
)
})?;
@@ -101,7 +107,7 @@ impl FileDesc {
#[cfg(any(target_os = "espidf", target_os = "horizon"))]
pub fn read_vectored(&self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
- return crate::io::default_read_vectored(|b| self.read(b), bufs);
+ io::default_read_vectored(|b| self.read(b), bufs)
}
#[inline]
@@ -147,6 +153,95 @@ impl FileDesc {
Ok(())
}
+ #[cfg(any(
+ target_os = "emscripten",
+ target_os = "freebsd",
+ target_os = "fuchsia",
+ target_os = "illumos",
+ target_os = "linux",
+ target_os = "netbsd",
+ ))]
+ pub fn read_vectored_at(&self, bufs: &mut [IoSliceMut<'_>], offset: u64) -> io::Result<usize> {
+ let ret = cvt(unsafe {
+ libc::preadv(
+ self.as_raw_fd(),
+ bufs.as_mut_ptr() as *mut libc::iovec as *const libc::iovec,
+ cmp::min(bufs.len(), max_iov()) as libc::c_int,
+ offset as _,
+ )
+ })?;
+ Ok(ret as usize)
+ }
+
+ #[cfg(not(any(
+ target_os = "android",
+ target_os = "emscripten",
+ target_os = "freebsd",
+ target_os = "fuchsia",
+ target_os = "illumos",
+ target_os = "ios",
+ target_os = "linux",
+ target_os = "macos",
+ target_os = "netbsd",
+ )))]
+ pub fn read_vectored_at(&self, bufs: &mut [IoSliceMut<'_>], offset: u64) -> io::Result<usize> {
+ io::default_read_vectored(|b| self.read_at(b, offset), bufs)
+ }
+
+ // We support some old Android versions that do not have `preadv` in libc,
+ // so we use weak linkage and fallback to a direct syscall if not available.
+ //
+ // On 32-bit targets, we don't want to deal with weird ABI issues around
+ // passing 64-bits parameters to syscalls, so we fallback to the default
+ // implementation if `preadv` is not available.
+ #[cfg(all(target_os = "android", target_pointer_width = "64"))]
+ pub fn read_vectored_at(&self, bufs: &mut [IoSliceMut<'_>], offset: u64) -> io::Result<usize> {
+ super::weak::syscall! {
+ fn preadv(
+ fd: libc::c_int,
+ iovec: *const libc::iovec,
+ n_iovec: libc::c_int,
+ offset: off64_t
+ ) -> isize
+ }
+
+ let ret = cvt(unsafe {
+ preadv(
+ self.as_raw_fd(),
+ bufs.as_mut_ptr() as *mut libc::iovec as *const libc::iovec,
+ cmp::min(bufs.len(), max_iov()) as libc::c_int,
+ offset as _,
+ )
+ })?;
+ Ok(ret as usize)
+ }
+
+ // We support old MacOS and iOS versions that do not have `preadv`. There is
+ // no `syscall` possible in these platform.
+ #[cfg(any(
+ all(target_os = "android", target_pointer_width = "32"),
+ target_os = "ios",
+ target_os = "macos",
+ ))]
+ pub fn read_vectored_at(&self, bufs: &mut [IoSliceMut<'_>], offset: u64) -> io::Result<usize> {
+ super::weak::weak!(fn preadv64(libc::c_int, *const libc::iovec, libc::c_int, off64_t) -> isize);
+
+ match preadv64.get() {
+ Some(preadv) => {
+ let ret = cvt(unsafe {
+ preadv(
+ self.as_raw_fd(),
+ bufs.as_mut_ptr() as *mut libc::iovec as *const libc::iovec,
+ cmp::min(bufs.len(), max_iov()) as libc::c_int,
+ offset as _,
+ )
+ })?;
+ Ok(ret as usize)
+ }
+ None => io::default_read_vectored(|b| self.read_at(b, offset), bufs),
+ }
+ }
+
pub fn write(&self, buf: &[u8]) -> io::Result<usize> {
let ret = cvt(unsafe {
libc::write(
@@ -172,7 +267,7 @@ impl FileDesc {
#[cfg(any(target_os = "espidf", target_os = "horizon"))]
pub fn write_vectored(&self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
- return crate::io::default_write_vectored(|b| self.write(b), bufs);
+ io::default_write_vectored(|b| self.write(b), bufs)
}
#[inline]
@@ -197,9 +292,93 @@ impl FileDesc {
}
}
- #[cfg(target_os = "linux")]
- pub fn get_cloexec(&self) -> io::Result<bool> {
- unsafe { Ok((cvt(libc::fcntl(self.as_raw_fd(), libc::F_GETFD))? & libc::FD_CLOEXEC) != 0) }
+ #[cfg(any(
+ target_os = "emscripten",
+ target_os = "freebsd",
+ target_os = "fuchsia",
+ target_os = "illumos",
+ target_os = "linux",
+ target_os = "netbsd",
+ ))]
+ pub fn write_vectored_at(&self, bufs: &[IoSlice<'_>], offset: u64) -> io::Result<usize> {
+ let ret = cvt(unsafe {
+ libc::pwritev(
+ self.as_raw_fd(),
+ bufs.as_ptr() as *const libc::iovec,
+ cmp::min(bufs.len(), max_iov()) as libc::c_int,
+ offset as _,
+ )
+ })?;
+ Ok(ret as usize)
+ }
+
+ #[cfg(not(any(
+ target_os = "android",
+ target_os = "emscripten",
+ target_os = "freebsd",
+ target_os = "fuchsia",
+ target_os = "illumos",
+ target_os = "ios",
+ target_os = "linux",
+ target_os = "macos",
+ target_os = "netbsd",
+ )))]
+ pub fn write_vectored_at(&self, bufs: &[IoSlice<'_>], offset: u64) -> io::Result<usize> {
+ io::default_write_vectored(|b| self.write_at(b, offset), bufs)
+ }
+
+ // We support some old Android versions that do not have `pwritev` in libc,
+ // so we use weak linkage and fallback to a direct syscall if not available.
+ //
+ // On 32-bit targets, we don't want to deal with weird ABI issues around
+ // passing 64-bits parameters to syscalls, so we fallback to the default
+ // implementation if `pwritev` is not available.
+ #[cfg(all(target_os = "android", target_pointer_width = "64"))]
+ pub fn write_vectored_at(&self, bufs: &[IoSlice<'_>], offset: u64) -> io::Result<usize> {
+ super::weak::syscall! {
+ fn pwritev(
+ fd: libc::c_int,
+ iovec: *const libc::iovec,
+ n_iovec: libc::c_int,
+ offset: off64_t
+ ) -> isize
+ }
+
+ let ret = cvt(unsafe {
+ pwritev(
+ self.as_raw_fd(),
+ bufs.as_ptr() as *const libc::iovec,
+ cmp::min(bufs.len(), max_iov()) as libc::c_int,
+ offset as _,
+ )
+ })?;
+ Ok(ret as usize)
+ }
+
+ // We support old MacOS and iOS versions that do not have `pwritev`. There is
+ // no `syscall` possible in these platform.
+ #[cfg(any(
+ all(target_os = "android", target_pointer_width = "32"),
+ target_os = "ios",
+ target_os = "macos",
+ ))]
+ pub fn write_vectored_at(&self, bufs: &[IoSlice<'_>], offset: u64) -> io::Result<usize> {
+ super::weak::weak!(fn pwritev64(libc::c_int, *const libc::iovec, libc::c_int, off64_t) -> isize);
+
+ match pwritev64.get() {
+ Some(pwritev) => {
+ let ret = cvt(unsafe {
+ pwritev(
+ self.as_raw_fd(),
+ bufs.as_ptr() as *const libc::iovec,
+ cmp::min(bufs.len(), max_iov()) as libc::c_int,
+ offset as _,
+ )
+ })?;
+ Ok(ret as usize)
+ }
+ None => io::default_write_vectored(|b| self.write_at(b, offset), bufs),
+ }
}
#[cfg(not(any(
@@ -212,7 +391,8 @@ impl FileDesc {
target_os = "linux",
target_os = "haiku",
target_os = "redox",
- target_os = "vxworks"
+ target_os = "vxworks",
+ target_os = "nto",
)))]
pub fn set_cloexec(&self) -> io::Result<()> {
unsafe {
@@ -230,7 +410,8 @@ impl FileDesc {
target_os = "linux",
target_os = "haiku",
target_os = "redox",
- target_os = "vxworks"
+ target_os = "vxworks",
+ target_os = "nto",
))]
pub fn set_cloexec(&self) -> io::Result<()> {
unsafe {
@@ -284,6 +465,10 @@ impl<'a> Read for &'a FileDesc {
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
(**self).read(buf)
}
+
+ fn read_buf(&mut self, cursor: BorrowedCursor<'_>) -> io::Result<()> {
+ (**self).read_buf(cursor)
+ }
}
impl AsInner<OwnedFd> for FileDesc {
diff --git a/library/std/src/sys/unix/fs.rs b/library/std/src/sys/unix/fs.rs
index 8e1f35d6c..7566fafda 100644
--- a/library/std/src/sys/unix/fs.rs
+++ b/library/std/src/sys/unix/fs.rs
@@ -13,7 +13,8 @@ use crate::mem;
target_os = "solaris",
target_os = "fuchsia",
target_os = "redox",
- target_os = "illumos"
+ target_os = "illumos",
+ target_os = "nto",
))]
use crate::mem::MaybeUninit;
use crate::os::unix::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd};
@@ -54,7 +55,8 @@ use libc::fstatat64;
target_os = "solaris",
target_os = "fuchsia",
target_os = "redox",
- target_os = "illumos"
+ target_os = "illumos",
+ target_os = "nto",
))]
use libc::readdir as readdir64;
#[cfg(target_os = "linux")]
@@ -69,7 +71,8 @@ use libc::readdir64_r;
target_os = "illumos",
target_os = "l4re",
target_os = "fuchsia",
- target_os = "redox"
+ target_os = "redox",
+ target_os = "nto",
)))]
use libc::readdir_r as readdir64_r;
#[cfg(target_os = "android")]
@@ -277,7 +280,8 @@ unsafe impl Sync for Dir {}
target_os = "solaris",
target_os = "illumos",
target_os = "fuchsia",
- target_os = "redox"
+ target_os = "redox",
+ target_os = "nto",
))]
pub struct DirEntry {
dir: Arc<InnerReadDir>,
@@ -297,11 +301,12 @@ pub struct DirEntry {
target_os = "solaris",
target_os = "illumos",
target_os = "fuchsia",
- target_os = "redox"
+ target_os = "redox",
+ target_os = "nto",
))]
struct dirent64_min {
d_ino: u64,
- #[cfg(not(any(target_os = "solaris", target_os = "illumos")))]
+ #[cfg(not(any(target_os = "solaris", target_os = "illumos", target_os = "nto")))]
d_type: u8,
}
@@ -311,7 +316,8 @@ struct dirent64_min {
target_os = "solaris",
target_os = "illumos",
target_os = "fuchsia",
- target_os = "redox"
+ target_os = "redox",
+ target_os = "nto",
)))]
pub struct DirEntry {
dir: Arc<InnerReadDir>,
@@ -438,7 +444,7 @@ impl FileAttr {
}
}
-#[cfg(not(target_os = "netbsd"))]
+#[cfg(not(any(target_os = "netbsd", target_os = "nto")))]
impl FileAttr {
#[cfg(not(any(target_os = "vxworks", target_os = "espidf", target_os = "horizon")))]
pub fn modified(&self) -> io::Result<SystemTime> {
@@ -524,6 +530,21 @@ impl FileAttr {
}
}
+#[cfg(target_os = "nto")]
+impl FileAttr {
+ pub fn modified(&self) -> io::Result<SystemTime> {
+ Ok(SystemTime::new(self.stat.st_mtim.tv_sec, self.stat.st_mtim.tv_nsec))
+ }
+
+ pub fn accessed(&self) -> io::Result<SystemTime> {
+ Ok(SystemTime::new(self.stat.st_atim.tv_sec, self.stat.st_atim.tv_nsec))
+ }
+
+ pub fn created(&self) -> io::Result<SystemTime> {
+ Ok(SystemTime::new(self.stat.st_ctim.tv_sec, self.stat.st_ctim.tv_nsec))
+ }
+}
+
impl AsInner<stat64> for FileAttr {
fn as_inner(&self) -> &stat64 {
&self.stat
@@ -603,7 +624,8 @@ impl Iterator for ReadDir {
target_os = "solaris",
target_os = "fuchsia",
target_os = "redox",
- target_os = "illumos"
+ target_os = "illumos",
+ target_os = "nto",
))]
fn next(&mut self) -> Option<io::Result<DirEntry>> {
if self.end_of_stream {
@@ -686,7 +708,11 @@ impl Iterator for ReadDir {
let entry = dirent64_min {
d_ino: *offset_ptr!(entry_ptr, d_ino) as u64,
- #[cfg(not(any(target_os = "solaris", target_os = "illumos")))]
+ #[cfg(not(any(
+ target_os = "solaris",
+ target_os = "illumos",
+ target_os = "nto",
+ )))]
d_type: *offset_ptr!(entry_ptr, d_type) as u8,
};
@@ -705,7 +731,8 @@ impl Iterator for ReadDir {
target_os = "solaris",
target_os = "fuchsia",
target_os = "redox",
- target_os = "illumos"
+ target_os = "illumos",
+ target_os = "nto",
)))]
fn next(&mut self) -> Option<io::Result<DirEntry>> {
if self.end_of_stream {
@@ -794,7 +821,8 @@ impl DirEntry {
target_os = "solaris",
target_os = "illumos",
target_os = "haiku",
- target_os = "vxworks"
+ target_os = "vxworks",
+ target_os = "nto",
))]
pub fn file_type(&self) -> io::Result<FileType> {
self.metadata().map(|m| m.file_type())
@@ -804,7 +832,8 @@ impl DirEntry {
target_os = "solaris",
target_os = "illumos",
target_os = "haiku",
- target_os = "vxworks"
+ target_os = "vxworks",
+ target_os = "nto",
)))]
pub fn file_type(&self) -> io::Result<FileType> {
match self.entry.d_type {
@@ -834,7 +863,8 @@ impl DirEntry {
target_os = "redox",
target_os = "vxworks",
target_os = "espidf",
- target_os = "horizon"
+ target_os = "horizon",
+ target_os = "nto",
))]
pub fn ino(&self) -> u64 {
self.entry.d_ino as u64
@@ -887,7 +917,8 @@ impl DirEntry {
target_os = "solaris",
target_os = "illumos",
target_os = "fuchsia",
- target_os = "redox"
+ target_os = "redox",
+ target_os = "nto",
)))]
fn name_cstr(&self) -> &CStr {
unsafe { CStr::from_ptr(self.entry.d_name.as_ptr()) }
@@ -898,7 +929,8 @@ impl DirEntry {
target_os = "solaris",
target_os = "illumos",
target_os = "fuchsia",
- target_os = "redox"
+ target_os = "redox",
+ target_os = "nto",
))]
fn name_cstr(&self) -> &CStr {
&self.name
@@ -1051,7 +1083,8 @@ impl File {
target_os = "linux",
target_os = "android",
target_os = "netbsd",
- target_os = "openbsd"
+ target_os = "openbsd",
+ target_os = "nto",
))]
unsafe fn os_datasync(fd: c_int) -> c_int {
libc::fdatasync(fd)
@@ -1065,6 +1098,7 @@ impl File {
target_os = "netbsd",
target_os = "openbsd",
target_os = "watchos",
+ target_os = "nto",
)))]
unsafe fn os_datasync(fd: c_int) -> c_int {
libc::fsync(fd)
@@ -1098,6 +1132,10 @@ impl File {
self.0.read_buf(cursor)
}
+ pub fn read_vectored_at(&self, bufs: &mut [IoSliceMut<'_>], offset: u64) -> io::Result<usize> {
+ self.0.read_vectored_at(bufs, offset)
+ }
+
pub fn write(&self, buf: &[u8]) -> io::Result<usize> {
self.0.write(buf)
}
@@ -1115,6 +1153,10 @@ impl File {
self.0.write_at(buf, offset)
}
+ pub fn write_vectored_at(&self, bufs: &[IoSlice<'_>], offset: u64) -> io::Result<usize> {
+ self.0.write_vectored_at(bufs, offset)
+ }
+
pub fn flush(&self) -> io::Result<()> {
Ok(())
}
@@ -1750,13 +1792,25 @@ pub fn chroot(dir: &Path) -> io::Result<()> {
pub use remove_dir_impl::remove_dir_all;
// Fallback for REDOX, ESP-ID, Horizon, and Miri
-#[cfg(any(target_os = "redox", target_os = "espidf", target_os = "horizon", miri))]
+#[cfg(any(
+ target_os = "redox",
+ target_os = "espidf",
+ target_os = "horizon",
+ target_os = "nto",
+ miri
+))]
mod remove_dir_impl {
pub use crate::sys_common::fs::remove_dir_all;
}
// Modern implementation using openat(), unlinkat() and fdopendir()
-#[cfg(not(any(target_os = "redox", target_os = "espidf", target_os = "horizon", miri)))]
+#[cfg(not(any(
+ target_os = "redox",
+ target_os = "espidf",
+ target_os = "horizon",
+ target_os = "nto",
+ miri
+)))]
mod remove_dir_impl {
use super::{lstat, Dir, DirEntry, InnerReadDir, ReadDir};
use crate::ffi::CStr;
diff --git a/library/std/src/sys/unix/locks/pthread_condvar.rs b/library/std/src/sys/unix/locks/pthread_condvar.rs
index 6be1abc2b..192fa216d 100644
--- a/library/std/src/sys/unix/locks/pthread_condvar.rs
+++ b/library/std/src/sys/unix/locks/pthread_condvar.rs
@@ -2,7 +2,10 @@ use crate::cell::UnsafeCell;
use crate::ptr;
use crate::sync::atomic::{AtomicPtr, Ordering::Relaxed};
use crate::sys::locks::{pthread_mutex, Mutex};
+#[cfg(not(target_os = "nto"))]
use crate::sys::time::TIMESPEC_MAX;
+#[cfg(target_os = "nto")]
+use crate::sys::time::TIMESPEC_MAX_CAPPED;
use crate::sys_common::lazy_box::{LazyBox, LazyInit};
use crate::time::Duration;
@@ -132,10 +135,18 @@ impl Condvar {
let mutex = pthread_mutex::raw(mutex);
self.verify(mutex);
+ #[cfg(not(target_os = "nto"))]
let timeout = Timespec::now(libc::CLOCK_MONOTONIC)
.checked_add_duration(&dur)
.and_then(|t| t.to_timespec())
.unwrap_or(TIMESPEC_MAX);
+
+ #[cfg(target_os = "nto")]
+ let timeout = Timespec::now(libc::CLOCK_MONOTONIC)
+ .checked_add_duration(&dur)
+ .and_then(|t| t.to_timespec_capped())
+ .unwrap_or(TIMESPEC_MAX_CAPPED);
+
let r = libc::pthread_cond_timedwait(raw(self), mutex, &timeout);
assert!(r == libc::ETIMEDOUT || r == 0);
r == 0
diff --git a/library/std/src/sys/unix/mod.rs b/library/std/src/sys/unix/mod.rs
index 30a96be14..68c9520cc 100644
--- a/library/std/src/sys/unix/mod.rs
+++ b/library/std/src/sys/unix/mod.rs
@@ -329,7 +329,7 @@ pub fn cvt_nz(error: libc::c_int) -> crate::io::Result<()> {
// do so. In 1003.1-2004 this was fixed.
//
// glibc's implementation did the flush, unsafely, before glibc commit
-// 91e7cf982d01 `abort: Do not flush stdio streams [BZ #15436]' by Florian
+// 91e7cf982d01 `abort: Do not flush stdio streams [BZ #15436]` by Florian
// Weimer. According to glibc's NEWS:
//
// The abort function terminates the process immediately, without flushing
diff --git a/library/std/src/sys/unix/net.rs b/library/std/src/sys/unix/net.rs
index c86f80972..8e05b618d 100644
--- a/library/std/src/sys/unix/net.rs
+++ b/library/std/src/sys/unix/net.rs
@@ -78,6 +78,7 @@ impl Socket {
target_os = "linux",
target_os = "netbsd",
target_os = "openbsd",
+ target_os = "nto",
))] {
// On platforms that support it we pass the SOCK_CLOEXEC
// flag to atomically create the socket and set it as
@@ -115,6 +116,7 @@ impl Socket {
target_os = "linux",
target_os = "netbsd",
target_os = "openbsd",
+ target_os = "nto",
))] {
// Like above, set cloexec atomically
cvt(libc::socketpair(fam, ty | libc::SOCK_CLOEXEC, 0, fds.as_mut_ptr()))?;
diff --git a/library/std/src/sys/unix/os.rs b/library/std/src/sys/unix/os.rs
index 2f2663db6..21b035fb3 100644
--- a/library/std/src/sys/unix/os.rs
+++ b/library/std/src/sys/unix/os.rs
@@ -62,6 +62,7 @@ extern "C" {
link_name = "__errno"
)]
#[cfg_attr(any(target_os = "solaris", target_os = "illumos"), link_name = "___errno")]
+ #[cfg_attr(target_os = "nto", link_name = "__get_errno_ptr")]
#[cfg_attr(
any(target_os = "macos", target_os = "ios", target_os = "freebsd", target_os = "watchos"),
link_name = "__error"
@@ -361,6 +362,17 @@ pub fn current_exe() -> io::Result<PathBuf> {
}
}
+#[cfg(target_os = "nto")]
+pub fn current_exe() -> io::Result<PathBuf> {
+ let mut e = crate::fs::read("/proc/self/exefile")?;
+ // Current versions of QNX Neutrino provide a null-terminated path.
+ // Ensure the trailing null byte is not returned here.
+ if let Some(0) = e.last() {
+ e.pop();
+ }
+ Ok(PathBuf::from(OsString::from_vec(e)))
+}
+
#[cfg(any(target_os = "macos", target_os = "ios", target_os = "watchos"))]
pub fn current_exe() -> io::Result<PathBuf> {
unsafe {
diff --git a/library/std/src/sys/unix/process/process_unix.rs b/library/std/src/sys/unix/process/process_unix.rs
index 3bc17b775..ceaff5966 100644
--- a/library/std/src/sys/unix/process/process_unix.rs
+++ b/library/std/src/sys/unix/process/process_unix.rs
@@ -18,6 +18,7 @@ use crate::sys::weak::raw_syscall;
target_os = "freebsd",
all(target_os = "linux", target_env = "gnu"),
all(target_os = "linux", target_env = "musl"),
+ target_os = "nto",
))]
use crate::sys::weak::weak;
@@ -30,6 +31,15 @@ use libc::{c_int, pid_t};
#[cfg(not(any(target_os = "vxworks", target_os = "l4re")))]
use libc::{gid_t, uid_t};
+cfg_if::cfg_if! {
+ if #[cfg(all(target_os = "nto", target_env = "nto71"))] {
+ use crate::thread;
+ use libc::{c_char, posix_spawn_file_actions_t, posix_spawnattr_t};
+ // arbitrary number of tries:
+ const MAX_FORKSPAWN_TRIES: u32 = 4;
+ }
+}
+
////////////////////////////////////////////////////////////////////////////////
// Command
////////////////////////////////////////////////////////////////////////////////
@@ -140,11 +150,31 @@ impl Command {
// Attempts to fork the process. If successful, returns Ok((0, -1))
// in the child, and Ok((child_pid, -1)) in the parent.
- #[cfg(not(target_os = "linux"))]
+ #[cfg(not(any(target_os = "linux", all(target_os = "nto", target_env = "nto71"))))]
unsafe fn do_fork(&mut self) -> Result<(pid_t, pid_t), io::Error> {
cvt(libc::fork()).map(|res| (res, -1))
}
+ // On QNX Neutrino, fork can fail with EBADF in case "another thread might have opened
+ // or closed a file descriptor while the fork() was occurring".
+ // Documentation says "... or try calling fork() again". This is what we do here.
+ // See also https://www.qnx.com/developers/docs/7.1/#com.qnx.doc.neutrino.lib_ref/topic/f/fork.html
+ #[cfg(all(target_os = "nto", target_env = "nto71"))]
+ unsafe fn do_fork(&mut self) -> Result<(pid_t, pid_t), io::Error> {
+ use crate::sys::os::errno;
+
+ let mut tries_left = MAX_FORKSPAWN_TRIES;
+ loop {
+ let r = libc::fork();
+ if r == -1 as libc::pid_t && tries_left > 0 && errno() as libc::c_int == libc::EBADF {
+ thread::yield_now();
+ tries_left -= 1;
+ } else {
+ return cvt(r).map(|res| (res, -1));
+ }
+ }
+ }
+
// Attempts to fork the process. If successful, returns Ok((0, -1))
// in the child, and Ok((child_pid, child_pidfd)) in the parent.
#[cfg(target_os = "linux")]
@@ -389,6 +419,7 @@ impl Command {
target_os = "freebsd",
all(target_os = "linux", target_env = "gnu"),
all(target_os = "linux", target_env = "musl"),
+ target_os = "nto",
)))]
fn posix_spawn(
&mut self,
@@ -405,6 +436,7 @@ impl Command {
target_os = "freebsd",
all(target_os = "linux", target_env = "gnu"),
all(target_os = "linux", target_env = "musl"),
+ target_os = "nto",
))]
fn posix_spawn(
&mut self,
@@ -436,6 +468,34 @@ impl Command {
}
}
+ // On QNX Neutrino, posix_spawnp can fail with EBADF in case "another thread might have opened
+ // or closed a file descriptor while the posix_spawn() was occurring".
+ // Documentation says "... or try calling posix_spawn() again". This is what we do here.
+ // See also http://www.qnx.com/developers/docs/7.1/#com.qnx.doc.neutrino.lib_ref/topic/p/posix_spawn.html
+ #[cfg(all(target_os = "nto", target_env = "nto71"))]
+ unsafe fn retrying_libc_posix_spawnp(
+ pid: *mut pid_t,
+ file: *const c_char,
+ file_actions: *const posix_spawn_file_actions_t,
+ attrp: *const posix_spawnattr_t,
+ argv: *const *mut c_char,
+ envp: *const *mut c_char,
+ ) -> i32 {
+ let mut tries_left = MAX_FORKSPAWN_TRIES;
+ loop {
+ match libc::posix_spawnp(pid, file, file_actions, attrp, argv, envp) {
+ libc::EBADF if tries_left > 0 => {
+ thread::yield_now();
+ tries_left -= 1;
+ continue;
+ }
+ r => {
+ return r;
+ }
+ }
+ }
+ }
+
// Solaris, glibc 2.29+, and musl 1.24+ can set a new working directory,
// and maybe others will gain this non-POSIX function too. We'll check
// for this weak symbol as soon as it's needed, so we can return early
@@ -555,7 +615,12 @@ impl Command {
// Make sure we synchronize access to the global `environ` resource
let _env_lock = sys::os::env_read_lock();
let envp = envp.map(|c| c.as_ptr()).unwrap_or_else(|| *sys::os::environ() as *const _);
- cvt_nz(libc::posix_spawnp(
+
+ #[cfg(not(target_os = "nto"))]
+ let spawn_fn = libc::posix_spawnp;
+ #[cfg(target_os = "nto")]
+ let spawn_fn = retrying_libc_posix_spawnp;
+ cvt_nz(spawn_fn(
&mut p.pid,
self.get_program_cstr().as_ptr(),
file_actions.0.as_ptr(),
@@ -760,7 +825,7 @@ fn signal_string(signal: i32) -> &'static str {
)
))]
libc::SIGSTKFLT => " (SIGSTKFLT)",
- #[cfg(target_os = "linux")]
+ #[cfg(any(target_os = "linux", target_os = "nto"))]
libc::SIGPWR => " (SIGPWR)",
#[cfg(any(
target_os = "macos",
@@ -769,7 +834,8 @@ fn signal_string(signal: i32) -> &'static str {
target_os = "freebsd",
target_os = "netbsd",
target_os = "openbsd",
- target_os = "dragonfly"
+ target_os = "dragonfly",
+ target_os = "nto",
))]
libc::SIGEMT => " (SIGEMT)",
#[cfg(any(
diff --git a/library/std/src/sys/unix/thread.rs b/library/std/src/sys/unix/thread.rs
index 2a1830d06..15070b1f6 100644
--- a/library/std/src/sys/unix/thread.rs
+++ b/library/std/src/sys/unix/thread.rs
@@ -9,7 +9,7 @@ use crate::time::Duration;
#[cfg(all(target_os = "linux", target_env = "gnu"))]
use crate::sys::weak::dlsym;
-#[cfg(any(target_os = "solaris", target_os = "illumos"))]
+#[cfg(any(target_os = "solaris", target_os = "illumos", target_os = "nto"))]
use crate::sys::weak::weak;
#[cfg(not(any(target_os = "l4re", target_os = "vxworks", target_os = "espidf")))]
pub const DEFAULT_MIN_STACK_SIZE: usize = 2 * 1024 * 1024;
@@ -49,7 +49,7 @@ unsafe impl Sync for Thread {}
impl Thread {
// unsafe: see thread::Builder::spawn_unchecked for safety requirements
pub unsafe fn new(stack: usize, p: Box<dyn FnOnce()>) -> io::Result<Thread> {
- let p = Box::into_raw(box p);
+ let p = Box::into_raw(Box::new(p));
let mut native: libc::pthread_t = mem::zeroed();
let mut attr: libc::pthread_attr_t = mem::zeroed();
assert_eq!(libc::pthread_attr_init(&mut attr), 0);
@@ -173,7 +173,7 @@ impl Thread {
}
}
- #[cfg(any(target_os = "solaris", target_os = "illumos"))]
+ #[cfg(any(target_os = "solaris", target_os = "illumos", target_os = "nto"))]
pub fn set_name(name: &CStr) {
weak! {
fn pthread_setname_np(
@@ -381,6 +381,17 @@ pub fn available_parallelism() -> io::Result<NonZeroUsize> {
}
Ok(unsafe { NonZeroUsize::new_unchecked(cpus as usize) })
+ } else if #[cfg(target_os = "nto")] {
+ unsafe {
+ use libc::_syspage_ptr;
+ if _syspage_ptr.is_null() {
+ Err(io::const_io_error!(io::ErrorKind::NotFound, "No syspage available"))
+ } else {
+ let cpus = (*_syspage_ptr).num_cpu;
+ NonZeroUsize::new(cpus as usize)
+ .ok_or(io::const_io_error!(io::ErrorKind::NotFound, "The number of hardware threads is not known for the target platform"))
+ }
+ }
} 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`
diff --git a/library/std/src/sys/unix/thread_local_dtor.rs b/library/std/src/sys/unix/thread_local_dtor.rs
index d7fd2130f..236d2f2ee 100644
--- a/library/std/src/sys/unix/thread_local_dtor.rs
+++ b/library/std/src/sys/unix/thread_local_dtor.rs
@@ -11,13 +11,7 @@
// Note, however, that we run on lots older linuxes, as well as cross
// compiling from a newer linux to an older linux, so we also have a
// fallback implementation to use as well.
-#[cfg(any(
- target_os = "linux",
- target_os = "fuchsia",
- target_os = "redox",
- target_os = "emscripten"
-))]
-#[cfg_attr(target_family = "wasm", allow(unused))] // might remain unused depending on target details (e.g. wasm32-unknown-emscripten)
+#[cfg(any(target_os = "linux", target_os = "fuchsia", target_os = "redox"))]
pub unsafe fn register_dtor(t: *mut u8, dtor: unsafe extern "C" fn(*mut u8)) {
use crate::mem;
use crate::sys_common::thread_local_dtor::register_dtor_fallback;
@@ -57,44 +51,40 @@ pub unsafe fn register_dtor(t: *mut u8, dtor: unsafe extern "C" fn(*mut u8)) {
#[cfg(target_os = "macos")]
pub unsafe fn register_dtor(t: *mut u8, dtor: unsafe extern "C" fn(*mut u8)) {
use crate::cell::Cell;
+ use crate::mem;
use crate::ptr;
#[thread_local]
static REGISTERED: Cell<bool> = Cell::new(false);
+
+ #[thread_local]
+ static mut DTORS: Vec<(*mut u8, unsafe extern "C" fn(*mut u8))> = Vec::new();
+
if !REGISTERED.get() {
_tlv_atexit(run_dtors, ptr::null_mut());
REGISTERED.set(true);
}
- type List = Vec<(*mut u8, unsafe extern "C" fn(*mut u8))>;
-
- #[thread_local]
- static DTORS: Cell<*mut List> = Cell::new(ptr::null_mut());
- if DTORS.get().is_null() {
- let v: Box<List> = box Vec::new();
- DTORS.set(Box::into_raw(v));
- }
-
extern "C" {
fn _tlv_atexit(dtor: unsafe extern "C" fn(*mut u8), arg: *mut u8);
}
- let list: &mut List = &mut *DTORS.get();
+ let list = &mut DTORS;
list.push((t, dtor));
unsafe extern "C" fn run_dtors(_: *mut u8) {
- let mut ptr = DTORS.replace(ptr::null_mut());
- while !ptr.is_null() {
- let list = Box::from_raw(ptr);
- for (ptr, dtor) in list.into_iter() {
+ let mut list = mem::take(&mut DTORS);
+ while !list.is_empty() {
+ for (ptr, dtor) in list {
dtor(ptr);
}
- ptr = DTORS.replace(ptr::null_mut());
+ list = mem::take(&mut DTORS);
}
}
}
-#[cfg(any(target_os = "vxworks", target_os = "horizon"))]
+#[cfg(any(target_os = "vxworks", target_os = "horizon", target_os = "emscripten"))]
+#[cfg_attr(target_family = "wasm", allow(unused))] // might remain unused depending on target details (e.g. wasm32-unknown-emscripten)
pub unsafe fn register_dtor(t: *mut u8, dtor: unsafe extern "C" fn(*mut u8)) {
use crate::sys_common::thread_local_dtor::register_dtor_fallback;
register_dtor_fallback(t, dtor);
diff --git a/library/std/src/sys/unix/thread_parking/pthread.rs b/library/std/src/sys/unix/thread_parking/pthread.rs
index 082d25e68..43046ed07 100644
--- a/library/std/src/sys/unix/thread_parking/pthread.rs
+++ b/library/std/src/sys/unix/thread_parking/pthread.rs
@@ -6,7 +6,10 @@ use crate::pin::Pin;
use crate::ptr::addr_of_mut;
use crate::sync::atomic::AtomicUsize;
use crate::sync::atomic::Ordering::SeqCst;
+#[cfg(not(target_os = "nto"))]
use crate::sys::time::TIMESPEC_MAX;
+#[cfg(target_os = "nto")]
+use crate::sys::time::TIMESPEC_MAX_CAPPED;
use crate::time::Duration;
const EMPTY: usize = 0;
@@ -80,8 +83,14 @@ unsafe fn wait_timeout(
(Timespec::now(libc::CLOCK_MONOTONIC), dur)
};
+ #[cfg(not(target_os = "nto"))]
let timeout =
now.checked_add_duration(&dur).and_then(|t| t.to_timespec()).unwrap_or(TIMESPEC_MAX);
+ #[cfg(target_os = "nto")]
+ let timeout = now
+ .checked_add_duration(&dur)
+ .and_then(|t| t.to_timespec_capped())
+ .unwrap_or(TIMESPEC_MAX_CAPPED);
let r = libc::pthread_cond_timedwait(cond, lock, &timeout);
debug_assert!(r == libc::ETIMEDOUT || r == 0);
}
diff --git a/library/std/src/sys/unix/time.rs b/library/std/src/sys/unix/time.rs
index 2daad981b..0f11de8f5 100644
--- a/library/std/src/sys/unix/time.rs
+++ b/library/std/src/sys/unix/time.rs
@@ -9,6 +9,14 @@ pub const UNIX_EPOCH: SystemTime = SystemTime { t: Timespec::zero() };
pub const TIMESPEC_MAX: libc::timespec =
libc::timespec { tv_sec: <libc::time_t>::MAX, tv_nsec: 1_000_000_000 - 1 };
+// This additional constant is only used when calling
+// `libc::pthread_cond_timedwait`.
+#[cfg(target_os = "nto")]
+pub(super) const TIMESPEC_MAX_CAPPED: libc::timespec = libc::timespec {
+ tv_sec: (u64::MAX / NSEC_PER_SEC) as i64,
+ tv_nsec: (u64::MAX % NSEC_PER_SEC) as i64,
+};
+
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[repr(transparent)]
#[rustc_layout_scalar_valid_range_start(0)]
@@ -144,6 +152,20 @@ impl Timespec {
tv_nsec: self.tv_nsec.0.try_into().ok()?,
})
}
+
+ // On QNX Neutrino, the maximum timespec for e.g. pthread_cond_timedwait
+ // is 2^64 nanoseconds
+ #[cfg(target_os = "nto")]
+ pub(super) fn to_timespec_capped(&self) -> Option<libc::timespec> {
+ // Check if timeout in nanoseconds would fit into an u64
+ if (self.tv_nsec.0 as u64)
+ .checked_add((self.tv_sec as u64).checked_mul(NSEC_PER_SEC)?)
+ .is_none()
+ {
+ return None;
+ }
+ self.to_timespec()
+ }
}
impl From<libc::timespec> for Timespec {
diff --git a/library/std/src/sys/unsupported/once.rs b/library/std/src/sys/unsupported/once.rs
index b4bb4975f..11fde1888 100644
--- a/library/std/src/sys/unsupported/once.rs
+++ b/library/std/src/sys/unsupported/once.rs
@@ -1,5 +1,6 @@
use crate::cell::Cell;
use crate::sync as public;
+use crate::sync::once::ExclusiveState;
pub struct Once {
state: Cell<State>,
@@ -44,6 +45,16 @@ impl Once {
self.state.get() == State::Complete
}
+ #[inline]
+ pub(crate) fn state(&mut self) -> ExclusiveState {
+ match self.state.get() {
+ State::Incomplete => ExclusiveState::Incomplete,
+ State::Poisoned => ExclusiveState::Poisoned,
+ State::Complete => ExclusiveState::Complete,
+ _ => unreachable!("invalid Once state"),
+ }
+ }
+
#[cold]
#[track_caller]
pub fn call(&self, ignore_poisoning: bool, f: &mut impl FnMut(&public::OnceState)) {
diff --git a/library/std/src/sys/wasi/os.rs b/library/std/src/sys/wasi/os.rs
index f5513e999..9919dc708 100644
--- a/library/std/src/sys/wasi/os.rs
+++ b/library/std/src/sys/wasi/os.rs
@@ -21,6 +21,7 @@ mod libc {
extern "C" {
pub fn getcwd(buf: *mut c_char, size: size_t) -> *mut c_char;
pub fn chdir(dir: *const c_char) -> c_int;
+ pub fn __wasilibc_get_environ() -> *mut *mut c_char;
}
}
@@ -161,7 +162,12 @@ impl Iterator for Env {
pub fn env() -> Env {
unsafe {
let _guard = env_read_lock();
- let mut environ = libc::environ;
+
+ // Use `__wasilibc_get_environ` instead of `environ` here so that we
+ // don't require wasi-libc to eagerly initialize the environment
+ // variables.
+ let mut environ = libc::__wasilibc_get_environ();
+
let mut result = Vec::new();
if !environ.is_null() {
while !(*environ).is_null() {
diff --git a/library/std/src/sys/windows/args.rs b/library/std/src/sys/windows/args.rs
index 6741ae46d..30356fa85 100644
--- a/library/std/src/sys/windows/args.rs
+++ b/library/std/src/sys/windows/args.rs
@@ -270,7 +270,7 @@ pub(crate) fn make_bat_command_line(
// It is necessary to surround the command in an extra pair of quotes,
// hence the trailing quote here. It will be closed after all arguments
// have been added.
- let mut cmd: Vec<u16> = "cmd.exe /c \"".encode_utf16().collect();
+ let mut cmd: Vec<u16> = "cmd.exe /d /c \"".encode_utf16().collect();
// Push the script name surrounded by its quote pair.
cmd.push(b'"' as u16);
@@ -290,6 +290,15 @@ pub(crate) fn make_bat_command_line(
// reconstructed by the batch script by default.
for arg in args {
cmd.push(' ' as u16);
+ // Make sure to always quote special command prompt characters, including:
+ // * Characters `cmd /?` says require quotes.
+ // * `%` for environment variables, as in `%TMP%`.
+ // * `|<>` pipe/redirect characters.
+ const SPECIAL: &[u8] = b"\t &()[]{}^=;!'+,`~%|<>";
+ let force_quotes = match arg {
+ Arg::Regular(arg) if !force_quotes => arg.bytes().iter().any(|c| SPECIAL.contains(c)),
+ _ => force_quotes,
+ };
append_arg(&mut cmd, arg, force_quotes)?;
}
diff --git a/library/std/src/sys/windows/c.rs b/library/std/src/sys/windows/c.rs
index f58dcf128..5d150eca0 100644
--- a/library/std/src/sys/windows/c.rs
+++ b/library/std/src/sys/windows/c.rs
@@ -6,13 +6,15 @@
use crate::ffi::CStr;
use crate::mem;
-use crate::os::raw::{c_char, c_int, c_long, c_longlong, c_uint, c_ulong, c_ushort};
+use crate::os::raw::{c_char, c_long, c_longlong, c_uint, c_ulong, c_ushort};
use crate::os::windows::io::{BorrowedHandle, HandleOrInvalid, HandleOrNull};
use crate::ptr;
use core::ffi::NonZero_c_ulong;
use libc::{c_void, size_t, wchar_t};
+pub use crate::os::raw::c_int;
+
#[path = "c/errors.rs"] // c.rs is included from two places so we need to specify this
mod errors;
pub use errors::*;
@@ -47,16 +49,19 @@ pub type ACCESS_MASK = DWORD;
pub type LPBOOL = *mut BOOL;
pub type LPBYTE = *mut BYTE;
+pub type LPCCH = *const CHAR;
pub type LPCSTR = *const CHAR;
+pub type LPCWCH = *const WCHAR;
pub type LPCWSTR = *const WCHAR;
+pub type LPCVOID = *const c_void;
pub type LPDWORD = *mut DWORD;
pub type LPHANDLE = *mut HANDLE;
pub type LPOVERLAPPED = *mut OVERLAPPED;
pub type LPPROCESS_INFORMATION = *mut PROCESS_INFORMATION;
pub type LPSECURITY_ATTRIBUTES = *mut SECURITY_ATTRIBUTES;
pub type LPSTARTUPINFO = *mut STARTUPINFO;
+pub type LPSTR = *mut CHAR;
pub type LPVOID = *mut c_void;
-pub type LPCVOID = *const c_void;
pub type LPWCH = *mut WCHAR;
pub type LPWIN32_FIND_DATAW = *mut WIN32_FIND_DATAW;
pub type LPWSADATA = *mut WSADATA;
@@ -132,6 +137,10 @@ pub const MAX_PATH: usize = 260;
pub const FILE_TYPE_PIPE: u32 = 3;
+pub const CP_UTF8: DWORD = 65001;
+pub const MB_ERR_INVALID_CHARS: DWORD = 0x08;
+pub const WC_ERR_INVALID_CHARS: DWORD = 0x80;
+
#[repr(C)]
#[derive(Copy)]
pub struct WIN32_FIND_DATAW {
@@ -539,14 +548,6 @@ pub struct SYMBOLIC_LINK_REPARSE_BUFFER {
pub PathBuffer: WCHAR,
}
-/// NB: Use carefully! In general using this as a reference is likely to get the
-/// provenance wrong for the `PathBuffer` field!
-#[repr(C)]
-pub struct FILE_NAME_INFO {
- pub FileNameLength: DWORD,
- pub FileName: [WCHAR; 1],
-}
-
#[repr(C)]
pub struct MOUNT_POINT_REPARSE_BUFFER {
pub SubstituteNameOffset: c_ushort,
@@ -1155,6 +1156,25 @@ extern "system" {
lpFilePart: *mut LPWSTR,
) -> DWORD;
pub fn GetFileAttributesW(lpFileName: LPCWSTR) -> DWORD;
+
+ pub fn MultiByteToWideChar(
+ CodePage: UINT,
+ dwFlags: DWORD,
+ lpMultiByteStr: LPCCH,
+ cbMultiByte: c_int,
+ lpWideCharStr: LPWSTR,
+ cchWideChar: c_int,
+ ) -> c_int;
+ pub fn WideCharToMultiByte(
+ CodePage: UINT,
+ dwFlags: DWORD,
+ lpWideCharStr: LPCWCH,
+ cchWideChar: c_int,
+ lpMultiByteStr: LPSTR,
+ cbMultiByte: c_int,
+ lpDefaultChar: LPCCH,
+ lpUsedDefaultChar: LPBOOL,
+ ) -> c_int;
}
#[link(name = "ws2_32")]
diff --git a/library/std/src/sys/windows/fs.rs b/library/std/src/sys/windows/fs.rs
index 378098038..d2c597664 100644
--- a/library/std/src/sys/windows/fs.rs
+++ b/library/std/src/sys/windows/fs.rs
@@ -1266,7 +1266,12 @@ fn metadata(path: &Path, reparse: ReparsePoint) -> io::Result<FileAttr> {
// If the fallback fails for any reason we return the original error.
match File::open(path, &opts) {
Ok(file) => file.file_attr(),
- Err(e) if e.raw_os_error() == Some(c::ERROR_SHARING_VIOLATION as _) => {
+ Err(e)
+ if [Some(c::ERROR_SHARING_VIOLATION as _), Some(c::ERROR_ACCESS_DENIED as _)]
+ .contains(&e.raw_os_error()) =>
+ {
+ // `ERROR_ACCESS_DENIED` is returned when the user doesn't have permission for the resource.
+ // One such example is `System Volume Information` as default but can be created as well
// `ERROR_SHARING_VIOLATION` will almost never be returned.
// Usually if a file is locked you can still read some metadata.
// However, there are special system files, such as
@@ -1393,6 +1398,8 @@ fn symlink_junction_inner(original: &Path, junction: &Path) -> io::Result<()> {
let mut data = Align8([MaybeUninit::<u8>::uninit(); c::MAXIMUM_REPARSE_DATA_BUFFER_SIZE]);
let data_ptr = data.0.as_mut_ptr();
let db = data_ptr.cast::<c::REPARSE_MOUNTPOINT_DATA_BUFFER>();
+ // Zero the header to ensure it's fully initialized, including reserved parameters.
+ *db = mem::zeroed();
let buf = ptr::addr_of_mut!((*db).ReparseTarget).cast::<c::WCHAR>();
let mut i = 0;
// FIXME: this conversion is very hacky
diff --git a/library/std/src/sys/windows/io.rs b/library/std/src/sys/windows/io.rs
index 2cc34c986..7fdd1f702 100644
--- a/library/std/src/sys/windows/io.rs
+++ b/library/std/src/sys/windows/io.rs
@@ -2,8 +2,7 @@ use crate::marker::PhantomData;
use crate::mem::size_of;
use crate::os::windows::io::{AsHandle, AsRawHandle, BorrowedHandle};
use crate::slice;
-use crate::sys::{c, Align8};
-use core;
+use crate::sys::c;
use libc;
#[derive(Copy, Clone)]
@@ -125,22 +124,33 @@ unsafe fn msys_tty_on(handle: c::HANDLE) -> bool {
return false;
}
- const SIZE: usize = size_of::<c::FILE_NAME_INFO>() + c::MAX_PATH * size_of::<c::WCHAR>();
- let mut name_info_bytes = Align8([0u8; SIZE]);
+ /// Mirrors [`FILE_NAME_INFO`], giving it a fixed length that we can stack
+ /// allocate
+ ///
+ /// [`FILE_NAME_INFO`]: https://learn.microsoft.com/en-us/windows/win32/api/winbase/ns-winbase-file_name_info
+ #[repr(C)]
+ #[allow(non_snake_case)]
+ struct FILE_NAME_INFO {
+ FileNameLength: u32,
+ FileName: [u16; c::MAX_PATH as usize],
+ }
+ let mut name_info = FILE_NAME_INFO { FileNameLength: 0, FileName: [0; c::MAX_PATH as usize] };
+ // Safety: buffer length is fixed.
let res = c::GetFileInformationByHandleEx(
handle,
c::FileNameInfo,
- name_info_bytes.0.as_mut_ptr() as *mut libc::c_void,
- SIZE as u32,
+ &mut name_info as *mut _ as *mut libc::c_void,
+ size_of::<FILE_NAME_INFO>() as u32,
);
if res == 0 {
return false;
}
- let name_info: &c::FILE_NAME_INFO = &*(name_info_bytes.0.as_ptr() as *const c::FILE_NAME_INFO);
- let name_len = name_info.FileNameLength as usize / 2;
- // Offset to get the `FileName` field.
- let name_ptr = name_info_bytes.0.as_ptr().offset(size_of::<c::DWORD>() as isize).cast::<u16>();
- let s = core::slice::from_raw_parts(name_ptr, name_len);
+
+ // Use `get` because `FileNameLength` can be out of range.
+ let s = match name_info.FileName.get(..name_info.FileNameLength as usize / 2) {
+ None => return false,
+ Some(s) => s,
+ };
let name = String::from_utf16_lossy(s);
// Get the file name only.
let name = name.rsplit('\\').next().unwrap_or(&name);
diff --git a/library/std/src/sys/windows/stdio.rs b/library/std/src/sys/windows/stdio.rs
index 70c9b14a0..32c6ccffb 100644
--- a/library/std/src/sys/windows/stdio.rs
+++ b/library/std/src/sys/windows/stdio.rs
@@ -1,6 +1,5 @@
#![unstable(issue = "none", feature = "windows_stdio")]
-use crate::char::decode_utf16;
use crate::cmp;
use crate::io;
use crate::mem::MaybeUninit;
@@ -170,14 +169,27 @@ fn write(
}
fn write_valid_utf8_to_console(handle: c::HANDLE, utf8: &str) -> io::Result<usize> {
+ debug_assert!(!utf8.is_empty());
+
let mut utf16 = [MaybeUninit::<u16>::uninit(); MAX_BUFFER_SIZE / 2];
- let mut len_utf16 = 0;
- for (chr, dest) in utf8.encode_utf16().zip(utf16.iter_mut()) {
- *dest = MaybeUninit::new(chr);
- len_utf16 += 1;
- }
- // Safety: We've initialized `len_utf16` values.
- let utf16: &[u16] = unsafe { MaybeUninit::slice_assume_init_ref(&utf16[..len_utf16]) };
+ let utf8 = &utf8[..utf8.floor_char_boundary(utf16.len())];
+
+ let utf16: &[u16] = unsafe {
+ // Note that this theoretically checks validity twice in the (most common) case
+ // where the underlying byte sequence is valid utf-8 (given the check in `write()`).
+ let result = c::MultiByteToWideChar(
+ c::CP_UTF8, // CodePage
+ c::MB_ERR_INVALID_CHARS, // dwFlags
+ utf8.as_ptr() as c::LPCCH, // lpMultiByteStr
+ utf8.len() as c::c_int, // cbMultiByte
+ utf16.as_mut_ptr() as c::LPWSTR, // lpWideCharStr
+ utf16.len() as c::c_int, // cchWideChar
+ );
+ assert!(result != 0, "Unexpected error in MultiByteToWideChar");
+
+ // Safety: MultiByteToWideChar initializes `result` values.
+ MaybeUninit::slice_assume_init_ref(&utf16[..result as usize])
+ };
let mut written = write_u16s(handle, &utf16)?;
@@ -190,8 +202,8 @@ fn write_valid_utf8_to_console(handle: c::HANDLE, utf8: &str) -> io::Result<usiz
// a missing surrogate can be produced (and also because of the UTF-8 validation above),
// write the missing surrogate out now.
// Buffering it would mean we have to lie about the number of bytes written.
- let first_char_remaining = utf16[written];
- if first_char_remaining >= 0xDCEE && first_char_remaining <= 0xDFFF {
+ let first_code_unit_remaining = utf16[written];
+ if first_code_unit_remaining >= 0xDCEE && first_code_unit_remaining <= 0xDFFF {
// low surrogate
// We just hope this works, and give up otherwise
let _ = write_u16s(handle, &utf16[written..written + 1]);
@@ -213,6 +225,7 @@ fn write_valid_utf8_to_console(handle: c::HANDLE, utf8: &str) -> io::Result<usiz
}
fn write_u16s(handle: c::HANDLE, data: &[u16]) -> io::Result<usize> {
+ debug_assert!(data.len() < u32::MAX as usize);
let mut written = 0;
cvt(unsafe {
c::WriteConsoleW(
@@ -366,26 +379,32 @@ fn read_u16s(handle: c::HANDLE, buf: &mut [MaybeUninit<u16>]) -> io::Result<usiz
Ok(amount as usize)
}
-#[allow(unused)]
fn utf16_to_utf8(utf16: &[u16], utf8: &mut [u8]) -> io::Result<usize> {
- let mut written = 0;
- for chr in decode_utf16(utf16.iter().cloned()) {
- match chr {
- Ok(chr) => {
- chr.encode_utf8(&mut utf8[written..]);
- written += chr.len_utf8();
- }
- Err(_) => {
- // We can't really do any better than forget all data and return an error.
- return Err(io::const_io_error!(
- io::ErrorKind::InvalidData,
- "Windows stdin in console mode does not support non-UTF-16 input; \
- encountered unpaired surrogate",
- ));
- }
- }
+ debug_assert!(utf16.len() <= c::c_int::MAX as usize);
+ debug_assert!(utf8.len() <= c::c_int::MAX as usize);
+
+ let result = unsafe {
+ c::WideCharToMultiByte(
+ c::CP_UTF8, // CodePage
+ c::WC_ERR_INVALID_CHARS, // dwFlags
+ utf16.as_ptr(), // lpWideCharStr
+ utf16.len() as c::c_int, // cchWideChar
+ utf8.as_mut_ptr() as c::LPSTR, // lpMultiByteStr
+ utf8.len() as c::c_int, // cbMultiByte
+ ptr::null(), // lpDefaultChar
+ ptr::null_mut(), // lpUsedDefaultChar
+ )
+ };
+ if result == 0 {
+ // We can't really do any better than forget all data and return an error.
+ Err(io::const_io_error!(
+ io::ErrorKind::InvalidData,
+ "Windows stdin in console mode does not support non-UTF-16 input; \
+ encountered unpaired surrogate",
+ ))
+ } else {
+ Ok(result as usize)
}
- Ok(written)
}
impl IncompleteUtf8 {
diff --git a/library/std/src/sys/windows/thread.rs b/library/std/src/sys/windows/thread.rs
index 1cb576c95..ed58c47e0 100644
--- a/library/std/src/sys/windows/thread.rs
+++ b/library/std/src/sys/windows/thread.rs
@@ -22,7 +22,7 @@ pub struct Thread {
impl Thread {
// unsafe: see thread::Builder::spawn_unchecked for safety requirements
pub unsafe fn new(stack: usize, p: Box<dyn FnOnce()>) -> io::Result<Thread> {
- let p = Box::into_raw(box p);
+ let p = Box::into_raw(Box::new(p));
// FIXME On UNIX, we guard against stack sizes that are too small but
// that's because pthreads enforces that stacks are at least
diff --git a/library/std/src/sys/windows/thread_parking.rs b/library/std/src/sys/windows/thread_parking.rs
index 5d43676ad..eb9167cd8 100644
--- a/library/std/src/sys/windows/thread_parking.rs
+++ b/library/std/src/sys/windows/thread_parking.rs
@@ -221,7 +221,7 @@ impl Parker {
fn keyed_event_handle() -> c::HANDLE {
const INVALID: c::HANDLE = ptr::invalid_mut(!0);
- static HANDLE: AtomicPtr<libc::c_void> = AtomicPtr::new(INVALID);
+ static HANDLE: AtomicPtr<crate::ffi::c_void> = AtomicPtr::new(INVALID);
match HANDLE.load(Relaxed) {
INVALID => {
let mut handle = c::INVALID_HANDLE_VALUE;
diff --git a/library/std/src/sys_common/backtrace.rs b/library/std/src/sys_common/backtrace.rs
index f1d804ef4..8752f46ff 100644
--- a/library/std/src/sys_common/backtrace.rs
+++ b/library/std/src/sys_common/backtrace.rs
@@ -91,6 +91,19 @@ unsafe fn _print_fmt(fmt: &mut fmt::Formatter<'_>, print_fmt: PrintFmt) -> fmt::
if stop {
return false;
}
+ #[cfg(target_os = "nto")]
+ if libc::__my_thread_exit as *mut libc::c_void == frame.ip() {
+ if !hit && start {
+ use crate::backtrace_rs::SymbolName;
+ res = bt_fmt.frame().print_raw(
+ frame.ip(),
+ Some(SymbolName::new("__my_thread_exit".as_bytes())),
+ None,
+ None,
+ );
+ }
+ return false;
+ }
if !hit && start {
res = bt_fmt.frame().print_raw(frame.ip(), None, None, None);
}
diff --git a/library/std/src/sys_common/mod.rs b/library/std/src/sys_common/mod.rs
index 6b24b0e9a..e9c727cbb 100644
--- a/library/std/src/sys_common/mod.rs
+++ b/library/std/src/sys_common/mod.rs
@@ -44,7 +44,6 @@ cfg_if::cfg_if! {
cfg_if::cfg_if! {
if #[cfg(any(target_os = "l4re",
- target_os = "hermit",
feature = "restricted-std",
all(target_family = "wasm", not(target_os = "emscripten")),
all(target_vendor = "fortanix", target_env = "sgx")))] {
diff --git a/library/std/src/sys_common/net.rs b/library/std/src/sys_common/net.rs
index fad4a6333..85ecc1def 100644
--- a/library/std/src/sys_common/net.rs
+++ b/library/std/src/sys_common/net.rs
@@ -14,14 +14,14 @@ use crate::sys::net::{cvt, cvt_gai, cvt_r, init, wrlen_t, Socket};
use crate::sys_common::{AsInner, FromInner, IntoInner};
use crate::time::Duration;
-use libc::{c_int, c_void};
+use crate::ffi::{c_int, c_void};
cfg_if::cfg_if! {
if #[cfg(any(
target_os = "dragonfly", target_os = "freebsd",
target_os = "ios", target_os = "macos", target_os = "watchos",
target_os = "openbsd", target_os = "netbsd", target_os = "illumos",
- target_os = "solaris", target_os = "haiku", target_os = "l4re"))] {
+ target_os = "solaris", target_os = "haiku", target_os = "l4re", target_os = "nto"))] {
use crate::sys::net::netc::IPV6_JOIN_GROUP as IPV6_ADD_MEMBERSHIP;
use crate::sys::net::netc::IPV6_LEAVE_GROUP as IPV6_DROP_MEMBERSHIP;
} else {
@@ -35,7 +35,7 @@ cfg_if::cfg_if! {
target_os = "linux", target_os = "android",
target_os = "dragonfly", target_os = "freebsd",
target_os = "openbsd", target_os = "netbsd",
- target_os = "haiku"))] {
+ target_os = "haiku", target_os = "nto"))] {
use libc::MSG_NOSIGNAL;
} else {
const MSG_NOSIGNAL: c_int = 0x0;
@@ -46,8 +46,9 @@ cfg_if::cfg_if! {
if #[cfg(any(
target_os = "dragonfly", target_os = "freebsd",
target_os = "openbsd", target_os = "netbsd",
- target_os = "solaris", target_os = "illumos"))] {
- use libc::c_uchar;
+ target_os = "solaris", target_os = "illumos",
+ target_os = "nto"))] {
+ use crate::ffi::c_uchar;
type IpV4MultiCastType = c_uchar;
} else {
type IpV4MultiCastType = c_int;
@@ -127,8 +128,8 @@ fn to_ipv6mr_interface(value: u32) -> c_int {
}
#[cfg(not(target_os = "android"))]
-fn to_ipv6mr_interface(value: u32) -> libc::c_uint {
- value as libc::c_uint
+fn to_ipv6mr_interface(value: u32) -> crate::ffi::c_uint {
+ value as crate::ffi::c_uint
}
////////////////////////////////////////////////////////////////////////////////
diff --git a/library/std/src/sys_common/net/tests.rs b/library/std/src/sys_common/net/tests.rs
index ac75d9ebf..fc236b802 100644
--- a/library/std/src/sys_common/net/tests.rs
+++ b/library/std/src/sys_common/net/tests.rs
@@ -6,7 +6,7 @@ fn no_lookup_host_duplicates() {
let mut addrs = HashMap::new();
let lh = match LookupHost::try_from(("localhost", 0)) {
Ok(lh) => lh,
- Err(e) => panic!("couldn't resolve `localhost': {e}"),
+ Err(e) => panic!("couldn't resolve `localhost`: {e}"),
};
for sa in lh {
*addrs.entry(sa).or_insert(0) += 1;
diff --git a/library/std/src/sys_common/once/futex.rs b/library/std/src/sys_common/once/futex.rs
index 5c7e6c013..42db5fad4 100644
--- a/library/std/src/sys_common/once/futex.rs
+++ b/library/std/src/sys_common/once/futex.rs
@@ -4,6 +4,7 @@ use crate::sync::atomic::{
AtomicU32,
Ordering::{Acquire, Relaxed, Release},
};
+use crate::sync::once::ExclusiveState;
use crate::sys::futex::{futex_wait, futex_wake_all};
// On some platforms, the OS is very nice and handles the waiter queue for us.
@@ -78,6 +79,16 @@ impl Once {
self.state.load(Acquire) == COMPLETE
}
+ #[inline]
+ pub(crate) fn state(&mut self) -> ExclusiveState {
+ match *self.state.get_mut() {
+ INCOMPLETE => ExclusiveState::Incomplete,
+ POISONED => ExclusiveState::Poisoned,
+ COMPLETE => ExclusiveState::Complete,
+ _ => unreachable!("invalid Once state"),
+ }
+ }
+
// This uses FnMut to match the API of the generic implementation. As this
// implementation is quite light-weight, it is generic over the closure and
// so avoids the cost of dynamic dispatch.
diff --git a/library/std/src/sys_common/once/queue.rs b/library/std/src/sys_common/once/queue.rs
index d953a6745..def0bcd6f 100644
--- a/library/std/src/sys_common/once/queue.rs
+++ b/library/std/src/sys_common/once/queue.rs
@@ -60,6 +60,7 @@ use crate::fmt;
use crate::ptr;
use crate::sync as public;
use crate::sync::atomic::{AtomicBool, AtomicPtr, Ordering};
+use crate::sync::once::ExclusiveState;
use crate::thread::{self, Thread};
type Masked = ();
@@ -121,6 +122,16 @@ impl Once {
self.state_and_queue.load(Ordering::Acquire).addr() == COMPLETE
}
+ #[inline]
+ pub(crate) fn state(&mut self) -> ExclusiveState {
+ match self.state_and_queue.get_mut().addr() {
+ INCOMPLETE => ExclusiveState::Incomplete,
+ POISONED => ExclusiveState::Poisoned,
+ COMPLETE => ExclusiveState::Complete,
+ _ => unreachable!("invalid Once state"),
+ }
+ }
+
// This is a non-generic function to reduce the monomorphization cost of
// using `call_once` (this isn't exactly a trivial or small implementation).
//
diff --git a/library/std/src/sys_common/thread_local_dtor.rs b/library/std/src/sys_common/thread_local_dtor.rs
index 1d13a7171..844946eda 100644
--- a/library/std/src/sys_common/thread_local_dtor.rs
+++ b/library/std/src/sys_common/thread_local_dtor.rs
@@ -30,7 +30,7 @@ pub unsafe fn register_dtor_fallback(t: *mut u8, dtor: unsafe extern "C" fn(*mut
static DTORS: StaticKey = StaticKey::new(Some(run_dtors));
type List = Vec<(*mut u8, unsafe extern "C" fn(*mut u8))>;
if DTORS.get().is_null() {
- let v: Box<List> = box Vec::new();
+ let v: Box<List> = Box::new(Vec::new());
DTORS.set(Box::into_raw(v) as *mut u8);
}
let list: &mut List = &mut *(DTORS.get() as *mut List);
diff --git a/library/std/src/sys_common/thread_local_key.rs b/library/std/src/sys_common/thread_local_key.rs
index 2672a2a75..89360e456 100644
--- a/library/std/src/sys_common/thread_local_key.rs
+++ b/library/std/src/sys_common/thread_local_key.rs
@@ -117,9 +117,15 @@ pub struct Key {
/// This value specifies no destructor by default.
pub const INIT: StaticKey = StaticKey::new(None);
-// Define a sentinel value that is unlikely to be returned
-// as a TLS key (but it may be returned).
+// Define a sentinel value that is likely not to be returned
+// as a TLS key.
+#[cfg(not(target_os = "nto"))]
const KEY_SENTVAL: usize = 0;
+// On QNX Neutrino, 0 is always returned when currently not in use.
+// Using 0 would mean to always create two keys and remote the first
+// one (with value of 0) immediately afterwards.
+#[cfg(target_os = "nto")]
+const KEY_SENTVAL: usize = libc::PTHREAD_KEYS_MAX + 1;
impl StaticKey {
#[rustc_const_unstable(feature = "thread_local_internals", issue = "none")]
diff --git a/library/std/src/sys_common/thread_parking/id.rs b/library/std/src/sys_common/thread_parking/id.rs
index e98169597..575988ec7 100644
--- a/library/std/src/sys_common/thread_parking/id.rs
+++ b/library/std/src/sys_common/thread_parking/id.rs
@@ -60,7 +60,7 @@ impl Parker {
if state == PARKED {
// Loop to guard against spurious wakeups.
while state == PARKED {
- park(self.state.as_mut_ptr().addr());
+ park(self.state.as_ptr().addr());
state = self.state.load(Acquire);
}
@@ -76,7 +76,7 @@ impl Parker {
let state = self.state.fetch_sub(1, Acquire).wrapping_sub(1);
if state == PARKED {
- park_timeout(dur, self.state.as_mut_ptr().addr());
+ park_timeout(dur, self.state.as_ptr().addr());
// Swap to ensure that we observe all state changes with acquire
// ordering, even if the state has been changed after the timeout
// occured.
@@ -99,7 +99,7 @@ impl Parker {
// and terminated before this call is made. This call then returns an
// error or wakes up an unrelated thread. The platform API and
// environment does allow this, however.
- unpark(tid, self.state.as_mut_ptr().addr());
+ unpark(tid, self.state.as_ptr().addr());
}
}
}
diff --git a/library/std/src/sys_common/thread_parking/mod.rs b/library/std/src/sys_common/thread_parking/mod.rs
index 0ead6633c..e8e028bb3 100644
--- a/library/std/src/sys_common/thread_parking/mod.rs
+++ b/library/std/src/sys_common/thread_parking/mod.rs
@@ -14,12 +14,10 @@ cfg_if::cfg_if! {
} else if #[cfg(any(
target_os = "netbsd",
all(target_vendor = "fortanix", target_env = "sgx"),
+ target_os = "solid_asp3",
))] {
mod id;
pub use id::Parker;
- } else if #[cfg(target_os = "solid_asp3")] {
- mod wait_flag;
- pub use wait_flag::Parker;
} else if #[cfg(any(windows, target_family = "unix"))] {
pub use crate::sys::thread_parking::Parker;
} else {
diff --git a/library/std/src/sys_common/thread_parking/wait_flag.rs b/library/std/src/sys_common/thread_parking/wait_flag.rs
deleted file mode 100644
index d0f8899a9..000000000
--- a/library/std/src/sys_common/thread_parking/wait_flag.rs
+++ /dev/null
@@ -1,102 +0,0 @@
-//! A wait-flag-based thread parker.
-//!
-//! Some operating systems provide low-level parking primitives like wait counts,
-//! event flags or semaphores which are not susceptible to race conditions (meaning
-//! the wakeup can occur before the wait operation). To implement the `std` thread
-//! parker on top of these primitives, we only have to ensure that parking is fast
-//! when the thread token is available, the atomic ordering guarantees are maintained
-//! and spurious wakeups are minimized.
-//!
-//! To achieve this, this parker uses an atomic variable with three states: `EMPTY`,
-//! `PARKED` and `NOTIFIED`:
-//! * `EMPTY` means the token has not been made available, but the thread is not
-//! currently waiting on it.
-//! * `PARKED` means the token is not available and the thread is parked.
-//! * `NOTIFIED` means the token is available.
-//!
-//! `park` and `park_timeout` change the state from `EMPTY` to `PARKED` and from
-//! `NOTIFIED` to `EMPTY`. If the state was `NOTIFIED`, the thread was unparked and
-//! execution can continue without calling into the OS. If the state was `EMPTY`,
-//! the token is not available and the thread waits on the primitive (here called
-//! "wait flag").
-//!
-//! `unpark` changes the state to `NOTIFIED`. If the state was `PARKED`, the thread
-//! is or will be sleeping on the wait flag, so we raise it.
-
-use crate::pin::Pin;
-use crate::sync::atomic::AtomicI8;
-use crate::sync::atomic::Ordering::{Acquire, Relaxed, Release};
-use crate::sys::wait_flag::WaitFlag;
-use crate::time::Duration;
-
-const EMPTY: i8 = 0;
-const PARKED: i8 = -1;
-const NOTIFIED: i8 = 1;
-
-pub struct Parker {
- state: AtomicI8,
- wait_flag: WaitFlag,
-}
-
-impl Parker {
- /// Construct a parker for the current thread. The UNIX parker
- /// implementation requires this to happen in-place.
- pub unsafe fn new_in_place(parker: *mut Parker) {
- parker.write(Parker { state: AtomicI8::new(EMPTY), wait_flag: WaitFlag::new() })
- }
-
- // This implementation doesn't require `unsafe` and `Pin`, but other implementations do.
- pub unsafe fn park(self: Pin<&Self>) {
- match self.state.fetch_sub(1, Acquire) {
- // NOTIFIED => EMPTY
- NOTIFIED => return,
- // EMPTY => PARKED
- EMPTY => (),
- _ => panic!("inconsistent park state"),
- }
-
- // Avoid waking up from spurious wakeups (these are quite likely, see below).
- loop {
- self.wait_flag.wait();
-
- match self.state.compare_exchange(NOTIFIED, EMPTY, Acquire, Relaxed) {
- Ok(_) => return,
- Err(PARKED) => (),
- Err(_) => panic!("inconsistent park state"),
- }
- }
- }
-
- // This implementation doesn't require `unsafe` and `Pin`, but other implementations do.
- pub unsafe fn park_timeout(self: Pin<&Self>, dur: Duration) {
- match self.state.fetch_sub(1, Acquire) {
- NOTIFIED => return,
- EMPTY => (),
- _ => panic!("inconsistent park state"),
- }
-
- self.wait_flag.wait_timeout(dur);
-
- // Either a wakeup or a timeout occurred. Wakeups may be spurious, as there can be
- // a race condition when `unpark` is performed between receiving the timeout and
- // resetting the state, resulting in the eventflag being set unnecessarily. `park`
- // is protected against this by looping until the token is actually given, but
- // here we cannot easily tell.
-
- // Use `swap` to provide acquire ordering.
- match self.state.swap(EMPTY, Acquire) {
- NOTIFIED => (),
- PARKED => (),
- _ => panic!("inconsistent park state"),
- }
- }
-
- // This implementation doesn't require `Pin`, but other implementations do.
- pub fn unpark(self: Pin<&Self>) {
- let state = self.state.swap(NOTIFIED, Release);
-
- if state == PARKED {
- self.wait_flag.raise();
- }
- }
-}
diff --git a/library/std/src/sys_common/wtf8.rs b/library/std/src/sys_common/wtf8.rs
index dd53767d4..bc588bdbb 100644
--- a/library/std/src/sys_common/wtf8.rs
+++ b/library/std/src/sys_common/wtf8.rs
@@ -18,10 +18,10 @@
#[cfg(test)]
mod tests;
+use core::char::{encode_utf16_raw, encode_utf8_raw};
use core::str::next_code_point;
use crate::borrow::Cow;
-use crate::char;
use crate::collections::TryReserveError;
use crate::fmt;
use crate::hash::{Hash, Hasher};
@@ -235,7 +235,7 @@ impl Wtf8Buf {
/// This does **not** include the WTF-8 concatenation check or `is_known_utf8` check.
fn push_code_point_unchecked(&mut self, code_point: CodePoint) {
let mut bytes = [0; 4];
- let bytes = char::encode_utf8_raw(code_point.value, &mut bytes);
+ let bytes = encode_utf8_raw(code_point.value, &mut bytes);
self.bytes.extend_from_slice(bytes)
}
@@ -594,7 +594,7 @@ impl Wtf8 {
}
/// Returns the code point at `position` if it is in the ASCII range,
- /// or `b'\xFF' otherwise.
+ /// or `b'\xFF'` otherwise.
///
/// # Panics
///
@@ -939,7 +939,7 @@ impl<'a> Iterator for EncodeWide<'a> {
let mut buf = [0; 2];
self.code_points.next().map(|code_point| {
- let n = char::encode_utf16_raw(code_point.value, &mut buf).len();
+ let n = encode_utf16_raw(code_point.value, &mut buf).len();
if n == 2 {
self.extra = buf[1];
}
diff --git a/library/std/src/thread/local.rs b/library/std/src/thread/local.rs
index b30bb7b77..cf7c2e05a 100644
--- a/library/std/src/thread/local.rs
+++ b/library/std/src/thread/local.rs
@@ -1110,8 +1110,7 @@ pub mod os {
let ptr = if ptr.is_null() {
// If the lookup returned null, we haven't initialized our own
// local copy, so do that now.
- let ptr: Box<Value<T>> = box Value { inner: LazyKeyInner::new(), key: self };
- let ptr = Box::into_raw(ptr);
+ let ptr = Box::into_raw(Box::new(Value { inner: LazyKeyInner::new(), key: self }));
// SAFETY: At this point we are sure there is no value inside
// ptr so setting it will not affect anyone else.
unsafe {
diff --git a/library/std/src/thread/mod.rs b/library/std/src/thread/mod.rs
index 692ff0cbc..489af7767 100644
--- a/library/std/src/thread/mod.rs
+++ b/library/std/src/thread/mod.rs
@@ -124,8 +124,10 @@
//!
//! ## Stack size
//!
-//! The default stack size is platform-dependent and subject to change. Currently it is 2MB on all
-//! Tier-1 platforms. There are two ways to manually specify the stack size for spawned threads:
+//! The default stack size is platform-dependent and subject to change.
+//! Currently, it is 2 MiB on all Tier-1 platforms.
+//!
+//! There are two ways to manually specify the stack size for spawned threads:
//!
//! * Build the thread with [`Builder`] and pass the desired stack size to [`Builder::stack_size`].
//! * Set the `RUST_MIN_STACK` environment variable to an integer representing the desired stack
diff --git a/library/std/src/time.rs b/library/std/src/time.rs
index ecd06ebf7..5c2e9da70 100644
--- a/library/std/src/time.rs
+++ b/library/std/src/time.rs
@@ -1,6 +1,6 @@
//! Temporal quantification.
//!
-//! # Examples:
+//! # Examples
//!
//! There are multiple ways to create a new [`Duration`]:
//!
@@ -352,7 +352,7 @@ impl Instant {
self.checked_duration_since(earlier).unwrap_or_default()
}
- /// Returns the amount of time elapsed since this instant was created.
+ /// Returns the amount of time elapsed since this instant.
///
/// # Panics
///
@@ -525,8 +525,8 @@ impl SystemTime {
self.0.sub_time(&earlier.0).map_err(SystemTimeError)
}
- /// Returns the difference between the clock time when this
- /// system time was created, and the current clock time.
+ /// Returns the difference from this system time to the
+ /// current clock time.
///
/// 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
diff --git a/library/std/tests/common/mod.rs b/library/std/tests/common/mod.rs
new file mode 100644
index 000000000..fce220223
--- /dev/null
+++ b/library/std/tests/common/mod.rs
@@ -0,0 +1,58 @@
+#![allow(unused)]
+
+use std::env;
+use std::fs;
+use std::path::{Path, PathBuf};
+use std::thread;
+use rand::RngCore;
+
+/// Copied from `std::test_helpers::test_rng`, since these tests rely on the
+/// seed not being the same for every RNG invocation too.
+#[track_caller]
+pub(crate) fn test_rng() -> rand_xorshift::XorShiftRng {
+ use core::hash::{BuildHasher, Hash, Hasher};
+ let mut hasher = std::collections::hash_map::RandomState::new().build_hasher();
+ core::panic::Location::caller().hash(&mut hasher);
+ let hc64 = hasher.finish();
+ let seed_vec = hc64.to_le_bytes().into_iter().chain(0u8..8).collect::<Vec<u8>>();
+ let seed: [u8; 16] = seed_vec.as_slice().try_into().unwrap();
+ rand::SeedableRng::from_seed(seed)
+}
+
+// Copied from std::sys_common::io
+pub struct TempDir(PathBuf);
+
+impl TempDir {
+ pub fn join(&self, path: &str) -> PathBuf {
+ let TempDir(ref p) = *self;
+ p.join(path)
+ }
+
+ pub fn path(&self) -> &Path {
+ let TempDir(ref p) = *self;
+ p
+ }
+}
+
+impl Drop for TempDir {
+ fn drop(&mut self) {
+ // Gee, seeing how we're testing the fs module I sure hope that we
+ // at least implement this correctly!
+ let TempDir(ref p) = *self;
+ let result = fs::remove_dir_all(p);
+ // Avoid panicking while panicking as this causes the process to
+ // immediately abort, without displaying test results.
+ if !thread::panicking() {
+ result.unwrap();
+ }
+ }
+}
+
+#[track_caller] // for `test_rng`
+pub fn tmpdir() -> TempDir {
+ let p = env::temp_dir();
+ let mut r = test_rng();
+ let ret = p.join(&format!("rust-{}", r.next_u32()));
+ fs::create_dir(&ret).unwrap();
+ TempDir(ret)
+}
diff --git a/library/std/tests/create_dir_all_bare.rs b/library/std/tests/create_dir_all_bare.rs
new file mode 100644
index 000000000..fe789323f
--- /dev/null
+++ b/library/std/tests/create_dir_all_bare.rs
@@ -0,0 +1,39 @@
+#![cfg(all(test, not(any(target_os = "emscripten", target_env = "sgx"))))]
+
+//! Note that this test changes the current directory so
+//! should not be in the same process as other tests.
+use std::env;
+use std::fs;
+use std::path::{Path, PathBuf};
+
+mod common;
+
+// On some platforms, setting the current directory will prevent deleting it.
+// So this helper ensures the current directory is reset.
+struct CurrentDir(PathBuf);
+impl CurrentDir {
+ fn new() -> Self {
+ Self(env::current_dir().unwrap())
+ }
+ fn set(&self, path: &Path) {
+ env::set_current_dir(path).unwrap();
+ }
+ fn with(path: &Path, f: impl FnOnce()) {
+ let current_dir = Self::new();
+ current_dir.set(path);
+ f();
+ }
+}
+impl Drop for CurrentDir {
+ fn drop(&mut self) {
+ env::set_current_dir(&self.0).unwrap();
+ }
+}
+
+#[test]
+fn create_dir_all_bare() {
+ let tmpdir = common::tmpdir();
+ CurrentDir::with(tmpdir.path(), || {
+ fs::create_dir_all("create-dir-all-bare").unwrap();
+ });
+}
diff --git a/library/std/tests/env.rs b/library/std/tests/env.rs
index aae2c49d8..96b4f372b 100644
--- a/library/std/tests/env.rs
+++ b/library/std/tests/env.rs
@@ -3,18 +3,8 @@ use std::ffi::{OsStr, OsString};
use rand::distributions::{Alphanumeric, DistString};
-/// Copied from `std::test_helpers::test_rng`, since these tests rely on the
-/// seed not being the same for every RNG invocation too.
-#[track_caller]
-pub(crate) fn test_rng() -> rand_xorshift::XorShiftRng {
- use core::hash::{BuildHasher, Hash, Hasher};
- let mut hasher = std::collections::hash_map::RandomState::new().build_hasher();
- core::panic::Location::caller().hash(&mut hasher);
- let hc64 = hasher.finish();
- let seed_vec = hc64.to_le_bytes().into_iter().chain(0u8..8).collect::<Vec<u8>>();
- let seed: [u8; 16] = seed_vec.as_slice().try_into().unwrap();
- rand::SeedableRng::from_seed(seed)
-}
+mod common;
+use common::test_rng;
#[track_caller]
fn make_rand_name() -> OsString {
diff --git a/library/std/tests/run-time-detect.rs b/library/std/tests/run-time-detect.rs
index 1a2c12556..bf3c81fcc 100644
--- a/library/std/tests/run-time-detect.rs
+++ b/library/std/tests/run-time-detect.rs
@@ -120,16 +120,13 @@ fn x86_all() {
println!("avx512dq: {:?}", is_x86_feature_detected!("avx512dq"));
println!("avx512er: {:?}", is_x86_feature_detected!("avx512er"));
println!("avx512f: {:?}", is_x86_feature_detected!("avx512f"));
- println!("avx512gfni: {:?}", is_x86_feature_detected!("avx512gfni"));
println!("avx512ifma: {:?}", is_x86_feature_detected!("avx512ifma"));
println!("avx512pf: {:?}", is_x86_feature_detected!("avx512pf"));
- println!("avx512vaes: {:?}", is_x86_feature_detected!("avx512vaes"));
println!("avx512vbmi2: {:?}", is_x86_feature_detected!("avx512vbmi2"));
println!("avx512vbmi: {:?}", is_x86_feature_detected!("avx512vbmi"));
println!("avx512vl: {:?}", is_x86_feature_detected!("avx512vl"));
println!("avx512vnni: {:?}", is_x86_feature_detected!("avx512vnni"));
println!("avx512vp2intersect: {:?}", is_x86_feature_detected!("avx512vp2intersect"));
- println!("avx512vpclmulqdq: {:?}", is_x86_feature_detected!("avx512vpclmulqdq"));
println!("avx512vpopcntdq: {:?}", is_x86_feature_detected!("avx512vpopcntdq"));
println!("avx: {:?}", is_x86_feature_detected!("avx"));
println!("bmi1: {:?}", is_x86_feature_detected!("bmi1"));
@@ -138,6 +135,7 @@ fn x86_all() {
println!("f16c: {:?}", is_x86_feature_detected!("f16c"));
println!("fma: {:?}", is_x86_feature_detected!("fma"));
println!("fxsr: {:?}", is_x86_feature_detected!("fxsr"));
+ println!("gfni: {:?}", is_x86_feature_detected!("gfni"));
println!("lzcnt: {:?}", is_x86_feature_detected!("lzcnt"));
//println!("movbe: {:?}", is_x86_feature_detected!("movbe")); // movbe is unsupported as a target feature
println!("pclmulqdq: {:?}", is_x86_feature_detected!("pclmulqdq"));
@@ -154,6 +152,8 @@ fn x86_all() {
println!("sse: {:?}", is_x86_feature_detected!("sse"));
println!("ssse3: {:?}", is_x86_feature_detected!("ssse3"));
println!("tbm: {:?}", is_x86_feature_detected!("tbm"));
+ println!("vaes: {:?}", is_x86_feature_detected!("vaes"));
+ println!("vpclmulqdq: {:?}", is_x86_feature_detected!("vpclmulqdq"));
println!("xsave: {:?}", is_x86_feature_detected!("xsave"));
println!("xsavec: {:?}", is_x86_feature_detected!("xsavec"));
println!("xsaveopt: {:?}", is_x86_feature_detected!("xsaveopt"));
diff --git a/library/stdarch/.github/workflows/main.yml b/library/stdarch/.github/workflows/main.yml
index fd8713ff8..7d4085334 100644
--- a/library/stdarch/.github/workflows/main.yml
+++ b/library/stdarch/.github/workflows/main.yml
@@ -80,10 +80,7 @@ jobs:
- s390x-unknown-linux-gnu
- wasm32-wasi
- i586-unknown-linux-gnu
- - x86_64-linux-android
- - arm-linux-androideabi
- mipsel-unknown-linux-musl
- - aarch64-linux-android
- nvptx64-nvidia-cuda
- thumbv6m-none-eabi
- thumbv7m-none-eabi
@@ -146,18 +143,9 @@ jobs:
os: windows-latest
- target: i586-unknown-linux-gnu
os: ubuntu-latest
- - target: x86_64-linux-android
- os: ubuntu-latest
- disable_assert_instr: 1
- - target: arm-linux-androideabi
- os: ubuntu-latest
- disable_assert_instr: 1
- target: mipsel-unknown-linux-musl
os: ubuntu-latest
norun: 1
- - target: aarch64-linux-android
- os: ubuntu-latest
- disable_assert_instr: 1
- target: nvptx64-nvidia-cuda
os: ubuntu-latest
- target: thumbv6m-none-eabi
diff --git a/library/stdarch/ci/android-install-ndk.sh b/library/stdarch/ci/android-install-ndk.sh
deleted file mode 100644
index 944a8389a..000000000
--- a/library/stdarch/ci/android-install-ndk.sh
+++ /dev/null
@@ -1,38 +0,0 @@
-#!/usr/bin/env sh
-# Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-# file at the top-level directory of this distribution and at
-# http://rust-lang.org/COPYRIGHT.
-#
-# Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-# http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-# <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-# option. This file may not be copied, modified, or distributed
-# except according to those terms.
-
-set -ex
-
-curl --retry 5 -O \
- https://dl.google.com/android/repository/android-ndk-r15b-linux-x86_64.zip
-unzip -q android-ndk-r15b-linux-x86_64.zip
-
-case "${1}" in
- aarch64)
- arch=arm64
- ;;
-
- i686)
- arch=x86
- ;;
-
- *)
- arch="${1}"
- ;;
-esac;
-
-android-ndk-r15b/build/tools/make_standalone_toolchain.py \
- --unified-headers \
- --install-dir "/android/ndk-${1}" \
- --arch "${arch}" \
- --api 24
-
-rm -rf ./android-ndk-r15b-linux-x86_64.zip ./android-ndk-r15b
diff --git a/library/stdarch/ci/android-install-sdk.sh b/library/stdarch/ci/android-install-sdk.sh
deleted file mode 100644
index 3383dcb7f..000000000
--- a/library/stdarch/ci/android-install-sdk.sh
+++ /dev/null
@@ -1,60 +0,0 @@
-#!/usr/bin/env sh
-# Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-# file at the top-level directory of this distribution and at
-# http://rust-lang.org/COPYRIGHT.
-#
-# Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-# http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-# <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-# option. This file may not be copied, modified, or distributed
-# except according to those terms.
-
-set -ex
-
-# Prep the SDK and emulator
-#
-# Note that the update process requires that we accept a bunch of licenses, and
-# we can't just pipe `yes` into it for some reason, so we take the same strategy
-# located in https://github.com/appunite/docker by just wrapping it in a script
-# which apparently magically accepts the licenses.
-
-mkdir sdk
-curl --retry 5 https://dl.google.com/android/repository/sdk-tools-linux-4333796.zip -O
-unzip -d sdk sdk-tools-linux-4333796.zip
-
-case "$1" in
- arm | armv7)
- abi=armeabi-v7a
- ;;
-
- aarch64)
- abi=arm64-v8a
- ;;
-
- i686)
- abi=x86
- ;;
-
- x86_64)
- abi=x86_64
- ;;
-
- *)
- echo "invalid arch: $1"
- exit 1
- ;;
-esac;
-
-# --no_https avoids
-# javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: No trusted certificate found
-yes | ./sdk/tools/bin/sdkmanager --licenses --no_https
-yes | ./sdk/tools/bin/sdkmanager --no_https \
- "emulator" \
- "platform-tools" \
- "platforms;android-24" \
- "system-images;android-24;default;$abi"
-
-echo "no" |
- ./sdk/tools/bin/avdmanager create avd \
- --name "${1}" \
- --package "system-images;android-24;default;$abi"
diff --git a/library/stdarch/ci/android-sysimage.sh b/library/stdarch/ci/android-sysimage.sh
deleted file mode 100644
index 31a6762cb..000000000
--- a/library/stdarch/ci/android-sysimage.sh
+++ /dev/null
@@ -1,56 +0,0 @@
-#!/usr/bin/env bash
-
-# Copyright 2017 The Rust Project Developers. See the COPYRIGHT
-# file at the top-level directory of this distribution and at
-# http://rust-lang.org/COPYRIGHT.
-#
-# Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-# http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-# <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-# option. This file may not be copied, modified, or distributed
-# except according to those terms.
-
-set -ex
-
-URL=https://dl.google.com/android/repository/sys-img/android
-
-main() {
- local arch="${1}"
- local name="${2}"
- local dest=/system
- local td
- td="$(mktemp -d)"
-
- apt-get install --no-install-recommends e2tools
-
- pushd "$td"
- curl --retry 5 -O "${URL}/${name}"
- unzip -q "${name}"
-
- local system
- system=$(find . -name system.img)
- mkdir -p $dest/{bin,lib,lib64}
-
- # Extract android linker and libraries to /system
- # This allows android executables to be run directly (or with qemu)
- if [ "${arch}" = "x86_64" ] || [ "${arch}" = "arm64" ]; then
- e2cp -p "${system}:/bin/linker64" "${dest}/bin/"
- e2cp -p "${system}:/lib64/libdl.so" "${dest}/lib64/"
- e2cp -p "${system}:/lib64/libc.so" "${dest}/lib64/"
- e2cp -p "${system}:/lib64/libm.so" "${dest}/lib64/"
- else
- e2cp -p "${system}:/bin/linker" "${dest}/bin/"
- e2cp -p "${system}:/lib/libdl.so" "${dest}/lib/"
- e2cp -p "${system}:/lib/libc.so" "${dest}/lib/"
- e2cp -p "${system}:/lib/libm.so" "${dest}/lib/"
- fi
-
- # clean up
- apt-get purge --auto-remove -y e2tools
-
- popd
-
- rm -rf "${td}"
-}
-
-main "${@}"
diff --git a/library/stdarch/ci/docker/aarch64-linux-android/Dockerfile b/library/stdarch/ci/docker/aarch64-linux-android/Dockerfile
deleted file mode 100644
index 6cf9b5061..000000000
--- a/library/stdarch/ci/docker/aarch64-linux-android/Dockerfile
+++ /dev/null
@@ -1,46 +0,0 @@
-FROM ubuntu:22.04
-
-RUN apt-get update && \
- apt-get install -y --no-install-recommends \
- file \
- make \
- curl \
- ca-certificates \
- python-is-python3 \
- unzip \
- expect \
- openjdk-8-jre \
- libstdc++6-i386-cross \
- libpulse0 \
- gcc \
- libc6-dev
-
-WORKDIR /android/
-COPY android* /android/
-
-ENV ANDROID_ARCH=aarch64
-ENV PATH=$PATH:/android/ndk-$ANDROID_ARCH/bin:/android/sdk/tools:/android/sdk/platform-tools
-
-RUN sh /android/android-install-ndk.sh $ANDROID_ARCH
-RUN sh /android/android-install-sdk.sh $ANDROID_ARCH
-RUN mv /root/.android /tmp
-RUN chmod 777 -R /tmp/.android
-RUN chmod 755 /android/sdk/tools/* /android/sdk/emulator/qemu/linux-x86_64/*
-
-ENV PATH=$PATH:/rust/bin \
- CARGO_TARGET_AARCH64_LINUX_ANDROID_LINKER=aarch64-linux-android-gcc \
- CARGO_TARGET_AARCH64_LINUX_ANDROID_RUNNER=/tmp/runtest \
- OBJDUMP=aarch64-linux-android-objdump \
- HOME=/tmp
-
-ADD runtest-android.rs /tmp/runtest.rs
-ENTRYPOINT [ \
- "bash", \
- "-c", \
- # set SHELL so android can detect a 64bits system, see
- # http://stackoverflow.com/a/41789144
- "SHELL=/bin/dash /android/sdk/emulator/emulator @aarch64 -no-window & \
- rustc /tmp/runtest.rs -o /tmp/runtest && \
- exec \"$@\"", \
- "--" \
-]
diff --git a/library/stdarch/ci/docker/arm-linux-androideabi/Dockerfile b/library/stdarch/ci/docker/arm-linux-androideabi/Dockerfile
deleted file mode 100644
index fb1a0cecf..000000000
--- a/library/stdarch/ci/docker/arm-linux-androideabi/Dockerfile
+++ /dev/null
@@ -1,46 +0,0 @@
-FROM ubuntu:22.04
-
-RUN apt-get update && \
- apt-get install -y --no-install-recommends \
- file \
- make \
- curl \
- ca-certificates \
- python-is-python3 \
- unzip \
- expect \
- openjdk-8-jre \
- libstdc++6-i386-cross \
- libpulse0 \
- gcc \
- libc6-dev
-
-WORKDIR /android/
-COPY android* /android/
-
-ENV ANDROID_ARCH=arm
-ENV PATH=$PATH:/android/ndk-$ANDROID_ARCH/bin:/android/sdk/tools:/android/sdk/platform-tools
-
-RUN sh /android/android-install-ndk.sh $ANDROID_ARCH
-RUN sh /android/android-install-sdk.sh $ANDROID_ARCH
-RUN mv /root/.android /tmp
-RUN chmod 777 -R /tmp/.android
-RUN chmod 755 /android/sdk/tools/* /android/sdk/emulator/qemu/linux-x86_64/*
-
-ENV PATH=$PATH:/rust/bin \
- CARGO_TARGET_ARM_LINUX_ANDROIDEABI_LINKER=arm-linux-androideabi-gcc \
- CARGO_TARGET_ARM_LINUX_ANDROIDEABI_RUNNER=/tmp/runtest \
- OBJDUMP=arm-linux-androideabi-objdump \
- HOME=/tmp
-
-ADD runtest-android.rs /tmp/runtest.rs
-ENTRYPOINT [ \
- "bash", \
- "-c", \
- # set SHELL so android can detect a 64bits system, see
- # http://stackoverflow.com/a/41789144
- "SHELL=/bin/dash /android/sdk/emulator/emulator @arm -no-window & \
- rustc /tmp/runtest.rs -o /tmp/runtest && \
- exec \"$@\"", \
- "--" \
-]
diff --git a/library/stdarch/ci/docker/x86_64-linux-android/Dockerfile b/library/stdarch/ci/docker/x86_64-linux-android/Dockerfile
deleted file mode 100644
index 82119be74..000000000
--- a/library/stdarch/ci/docker/x86_64-linux-android/Dockerfile
+++ /dev/null
@@ -1,29 +0,0 @@
-FROM ubuntu:22.04
-
-RUN apt-get update && \
- apt-get install -y --no-install-recommends \
- ca-certificates \
- curl \
- gcc \
- libc-dev \
- python-is-python3 \
- unzip \
- file \
- make
-
-WORKDIR /android/
-ENV ANDROID_ARCH=x86_64
-COPY android-install-ndk.sh /android/
-RUN sh /android/android-install-ndk.sh $ANDROID_ARCH
-
-# We do not run x86_64-linux-android tests on an android emulator.
-# See ci/android-sysimage.sh for information about how tests are run.
-COPY android-sysimage.sh /android/
-RUN bash /android/android-sysimage.sh x86_64 x86_64-24_r07.zip
-
-ENV PATH=$PATH:/rust/bin:/android/ndk-$ANDROID_ARCH/bin \
- CARGO_TARGET_X86_64_LINUX_ANDROID_LINKER=x86_64-linux-android-gcc \
- CC_x86_64_linux_android=x86_64-linux-android-gcc \
- CXX_x86_64_linux_android=x86_64-linux-android-g++ \
- OBJDUMP=x86_64-linux-android-objdump \
- HOME=/tmp
diff --git a/library/stdarch/ci/runtest-android.rs b/library/stdarch/ci/runtest-android.rs
deleted file mode 100644
index ed1cd80c8..000000000
--- a/library/stdarch/ci/runtest-android.rs
+++ /dev/null
@@ -1,45 +0,0 @@
-use std::env;
-use std::process::Command;
-use std::path::{Path, PathBuf};
-
-fn main() {
- let args = env::args_os()
- .skip(1)
- .filter(|arg| arg != "--quiet")
- .collect::<Vec<_>>();
- assert_eq!(args.len(), 1);
- let test = PathBuf::from(&args[0]);
- let dst = Path::new("/data/local/tmp").join(test.file_name().unwrap());
-
- let status = Command::new("adb")
- .arg("wait-for-device")
- .status()
- .expect("failed to run: adb wait-for-device");
- assert!(status.success());
-
- let status = Command::new("adb")
- .arg("push")
- .arg(&test)
- .arg(&dst)
- .status()
- .expect("failed to run: adb pushr");
- assert!(status.success());
-
- let output = Command::new("adb")
- .arg("shell")
- .arg(&dst)
- .output()
- .expect("failed to run: adb shell");
- assert!(status.success());
-
- println!("status: {}\nstdout ---\n{}\nstderr ---\n{}",
- output.status,
- String::from_utf8_lossy(&output.stdout),
- String::from_utf8_lossy(&output.stderr));
-
- let stdout = String::from_utf8_lossy(&output.stdout);
- let mut lines = stdout.lines().filter(|l| l.starts_with("test result"));
- if !lines.all(|l| l.contains("test result: ok") && l.contains("0 failed")) {
- panic!("failed to find successful test run");
- }
-}
diff --git a/library/stdarch/crates/assert-instr-macro/Cargo.toml b/library/stdarch/crates/assert-instr-macro/Cargo.toml
index 3d9b32067..4ad654e69 100644
--- a/library/stdarch/crates/assert-instr-macro/Cargo.toml
+++ b/library/stdarch/crates/assert-instr-macro/Cargo.toml
@@ -2,7 +2,7 @@
name = "assert-instr-macro"
version = "0.1.0"
authors = ["Alex Crichton <alex@alexcrichton.com>"]
-edition = "2018"
+edition = "2021"
[lib]
proc-macro = true
diff --git a/library/stdarch/crates/assert-instr-macro/src/lib.rs b/library/stdarch/crates/assert-instr-macro/src/lib.rs
index 9fa411df3..99e37c910 100644
--- a/library/stdarch/crates/assert-instr-macro/src/lib.rs
+++ b/library/stdarch/crates/assert-instr-macro/src/lib.rs
@@ -56,14 +56,14 @@ pub fn assert_instr(
.replace('/', "_")
.replace(':', "_")
.replace(char::is_whitespace, "");
- let assert_name = syn::Ident::new(&format!("assert_{}_{}", name, instr_str), name.span());
+ let assert_name = syn::Ident::new(&format!("assert_{name}_{instr_str}"), name.span());
// These name has to be unique enough for us to find it in the disassembly later on:
let shim_name = syn::Ident::new(
- &format!("stdarch_test_shim_{}_{}", name, instr_str),
+ &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(),
+ &format!("stdarch_test_shim_{name}_{instr_str}_ptr").to_ascii_uppercase(),
name.span(),
);
let mut inputs = Vec::new();
@@ -131,7 +131,7 @@ pub fn assert_instr(
} else {
syn::LitStr::new("C", proc_macro2::Span::call_site())
};
- let shim_name_str = format!("{}{}", shim_name, assert_name);
+ let shim_name_str = format!("{shim_name}{assert_name}");
let to_test = if disable_dedup_guard {
quote! {
#attrs
diff --git a/library/stdarch/crates/core_arch/Cargo.toml b/library/stdarch/crates/core_arch/Cargo.toml
index e2b332af2..a1bb168ee 100644
--- a/library/stdarch/crates/core_arch/Cargo.toml
+++ b/library/stdarch/crates/core_arch/Cargo.toml
@@ -13,7 +13,7 @@ readme = "README.md"
keywords = ["core", "simd", "arch", "intrinsics"]
categories = ["hardware-support", "no-std"]
license = "MIT OR Apache-2.0"
-edition = "2018"
+edition = "2021"
[badges]
is-it-maintained-issue-resolution = { repository = "rust-lang/stdarch" }
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 9d9946b4f..7ff26ac21 100644
--- a/library/stdarch/crates/core_arch/src/aarch64/neon/mod.rs
+++ b/library/stdarch/crates/core_arch/src/aarch64/neon/mod.rs
@@ -162,7 +162,7 @@ extern "unadjusted" {
#[link_name = "llvm.aarch64.neon.smaxv.i8.v8i8"]
fn vmaxv_s8_(a: int8x8_t) -> i8;
- #[link_name = "llvm.aarch64.neon.smaxv.i8.6i8"]
+ #[link_name = "llvm.aarch64.neon.smaxv.i8.v16i8"]
fn vmaxvq_s8_(a: int8x16_t) -> i8;
#[link_name = "llvm.aarch64.neon.smaxv.i16.v4i16"]
fn vmaxv_s16_(a: int16x4_t) -> i16;
@@ -175,7 +175,7 @@ extern "unadjusted" {
#[link_name = "llvm.aarch64.neon.umaxv.i8.v8i8"]
fn vmaxv_u8_(a: uint8x8_t) -> u8;
- #[link_name = "llvm.aarch64.neon.umaxv.i8.6i8"]
+ #[link_name = "llvm.aarch64.neon.umaxv.i8.v16i8"]
fn vmaxvq_u8_(a: uint8x16_t) -> u8;
#[link_name = "llvm.aarch64.neon.umaxv.i16.v4i16"]
fn vmaxv_u16_(a: uint16x4_t) -> u16;
@@ -195,7 +195,7 @@ extern "unadjusted" {
#[link_name = "llvm.aarch64.neon.sminv.i8.v8i8"]
fn vminv_s8_(a: int8x8_t) -> i8;
- #[link_name = "llvm.aarch64.neon.sminv.i8.6i8"]
+ #[link_name = "llvm.aarch64.neon.sminv.i8.v16i8"]
fn vminvq_s8_(a: int8x16_t) -> i8;
#[link_name = "llvm.aarch64.neon.sminv.i16.v4i16"]
fn vminv_s16_(a: int16x4_t) -> i16;
@@ -208,7 +208,7 @@ extern "unadjusted" {
#[link_name = "llvm.aarch64.neon.uminv.i8.v8i8"]
fn vminv_u8_(a: uint8x8_t) -> u8;
- #[link_name = "llvm.aarch64.neon.uminv.i8.6i8"]
+ #[link_name = "llvm.aarch64.neon.uminv.i8.v16i8"]
fn vminvq_u8_(a: uint8x16_t) -> u8;
#[link_name = "llvm.aarch64.neon.uminv.i16.v4i16"]
fn vminv_u16_(a: uint16x4_t) -> u16;
@@ -1964,94 +1964,6 @@ pub unsafe fn vext_f64<const N: i32>(a: float64x1_t, _b: float64x1_t) -> float64
static_assert!(N : i32 where N == 0);
a
}
-/// Vector combine
-#[inline]
-#[target_feature(enable = "neon")]
-#[cfg_attr(test, assert_instr(mov))]
-#[stable(feature = "neon_intrinsics", since = "1.59.0")]
-pub unsafe fn vcombine_s8(low: int8x8_t, high: int8x8_t) -> int8x16_t {
- simd_shuffle16!(
- low,
- high,
- [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15],
- )
-}
-
-/// Vector combine
-#[inline]
-#[target_feature(enable = "neon")]
-#[cfg_attr(test, assert_instr(mov))]
-#[stable(feature = "neon_intrinsics", since = "1.59.0")]
-pub unsafe fn vcombine_s16(low: int16x4_t, high: int16x4_t) -> int16x8_t {
- simd_shuffle8!(low, high, [0, 1, 2, 3, 4, 5, 6, 7])
-}
-
-/// Vector combine
-#[inline]
-#[target_feature(enable = "neon")]
-#[cfg_attr(test, assert_instr(mov))]
-#[stable(feature = "neon_intrinsics", since = "1.59.0")]
-pub unsafe fn vcombine_s32(low: int32x2_t, high: int32x2_t) -> int32x4_t {
- simd_shuffle4!(low, high, [0, 1, 2, 3])
-}
-
-/// Vector combine
-#[inline]
-#[target_feature(enable = "neon")]
-#[cfg_attr(test, assert_instr(mov))]
-#[stable(feature = "neon_intrinsics", since = "1.59.0")]
-pub unsafe fn vcombine_s64(low: int64x1_t, high: int64x1_t) -> int64x2_t {
- simd_shuffle2!(low, high, [0, 1])
-}
-
-/// Vector combine
-#[inline]
-#[target_feature(enable = "neon")]
-#[cfg_attr(test, assert_instr(mov))]
-#[stable(feature = "neon_intrinsics", since = "1.59.0")]
-pub unsafe fn vcombine_u8(low: uint8x8_t, high: uint8x8_t) -> uint8x16_t {
- simd_shuffle16!(
- low,
- high,
- [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15],
- )
-}
-
-/// Vector combine
-#[inline]
-#[target_feature(enable = "neon")]
-#[cfg_attr(test, assert_instr(mov))]
-#[stable(feature = "neon_intrinsics", since = "1.59.0")]
-pub unsafe fn vcombine_u16(low: uint16x4_t, high: uint16x4_t) -> uint16x8_t {
- simd_shuffle8!(low, high, [0, 1, 2, 3, 4, 5, 6, 7])
-}
-
-/// Vector combine
-#[inline]
-#[target_feature(enable = "neon")]
-#[cfg_attr(test, assert_instr(mov))]
-#[stable(feature = "neon_intrinsics", since = "1.59.0")]
-pub unsafe fn vcombine_u32(low: uint32x2_t, high: uint32x2_t) -> uint32x4_t {
- simd_shuffle4!(low, high, [0, 1, 2, 3])
-}
-
-/// Vector combine
-#[inline]
-#[target_feature(enable = "neon")]
-#[cfg_attr(test, assert_instr(mov))]
-#[stable(feature = "neon_intrinsics", since = "1.59.0")]
-pub unsafe fn vcombine_u64(low: uint64x1_t, high: uint64x1_t) -> uint64x2_t {
- simd_shuffle2!(low, high, [0, 1])
-}
-
-/// Vector combine
-#[inline]
-#[target_feature(enable = "neon")]
-#[cfg_attr(test, assert_instr(mov))]
-#[stable(feature = "neon_intrinsics", since = "1.59.0")]
-pub unsafe fn vcombine_p64(low: poly64x1_t, high: poly64x1_t) -> poly64x2_t {
- simd_shuffle2!(low, high, [0, 1])
-}
/// Duplicate vector element to vector or scalar
#[inline]
@@ -2183,47 +2095,6 @@ pub unsafe fn vgetq_lane_f64<const IMM5: i32>(v: float64x2_t) -> f64 {
simd_extract(v, IMM5 as u32)
}
-/* FIXME: 16-bit float
-/// Vector combine
-#[inline]
-#[target_feature(enable = "neon")]
-#[cfg_attr(test, assert_instr(mov))]
-pub unsafe fn vcombine_f16 ( low: float16x4_t, high: float16x4_t) -> float16x8_t {
- simd_shuffle8!(low, high, [0, 1, 2, 3, 4, 5, 6, 7])
-}
-*/
-
-/// Vector combine
-#[inline]
-#[target_feature(enable = "neon")]
-#[cfg_attr(test, assert_instr(mov))]
-#[stable(feature = "neon_intrinsics", since = "1.59.0")]
-pub unsafe fn vcombine_f32(low: float32x2_t, high: float32x2_t) -> float32x4_t {
- simd_shuffle4!(low, high, [0, 1, 2, 3])
-}
-
-/// Vector combine
-#[inline]
-#[target_feature(enable = "neon")]
-#[cfg_attr(test, assert_instr(mov))]
-#[stable(feature = "neon_intrinsics", since = "1.59.0")]
-pub unsafe fn vcombine_p8(low: poly8x8_t, high: poly8x8_t) -> poly8x16_t {
- simd_shuffle16!(
- low,
- high,
- [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15],
- )
-}
-
-/// Vector combine
-#[inline]
-#[target_feature(enable = "neon")]
-#[cfg_attr(test, assert_instr(mov))]
-#[stable(feature = "neon_intrinsics", since = "1.59.0")]
-pub unsafe fn vcombine_p16(low: poly16x4_t, high: poly16x4_t) -> poly16x8_t {
- simd_shuffle8!(low, high, [0, 1, 2, 3, 4, 5, 6, 7])
-}
-
/// Vector combine
#[inline]
#[target_feature(enable = "neon")]
@@ -4478,43 +4349,6 @@ mod tests {
assert_eq!(r, e);
}
- macro_rules! test_vcombine {
- ($test_id:ident => $fn_id:ident ([$($a:expr),*], [$($b:expr),*])) => {
- #[allow(unused_assignments)]
- #[simd_test(enable = "neon")]
- unsafe fn $test_id() {
- let a = [$($a),*];
- let b = [$($b),*];
- let e = [$($a),* $(, $b)*];
- let c = $fn_id(transmute(a), transmute(b));
- let mut d = e;
- d = transmute(c);
- assert_eq!(d, e);
- }
- }
- }
-
- test_vcombine!(test_vcombine_s8 => vcombine_s8([3_i8, -4, 5, -6, 7, 8, 9, 10], [13_i8, -14, 15, -16, 17, 18, 19, 110]));
- test_vcombine!(test_vcombine_u8 => vcombine_u8([3_u8, 4, 5, 6, 7, 8, 9, 10], [13_u8, 14, 15, 16, 17, 18, 19, 110]));
- test_vcombine!(test_vcombine_p8 => vcombine_p8([3_u8, 4, 5, 6, 7, 8, 9, 10], [13_u8, 14, 15, 16, 17, 18, 19, 110]));
-
- test_vcombine!(test_vcombine_s16 => vcombine_s16([3_i16, -4, 5, -6], [13_i16, -14, 15, -16]));
- test_vcombine!(test_vcombine_u16 => vcombine_u16([3_u16, 4, 5, 6], [13_u16, 14, 15, 16]));
- test_vcombine!(test_vcombine_p16 => vcombine_p16([3_u16, 4, 5, 6], [13_u16, 14, 15, 16]));
- // FIXME: 16-bit floats
- // test_vcombine!(test_vcombine_f16 => vcombine_f16([3_f16, 4., 5., 6.],
- // [13_f16, 14., 15., 16.]));
-
- test_vcombine!(test_vcombine_s32 => vcombine_s32([3_i32, -4], [13_i32, -14]));
- test_vcombine!(test_vcombine_u32 => vcombine_u32([3_u32, 4], [13_u32, 14]));
- // note: poly32x4 does not exist, and neither does vcombine_p32
- test_vcombine!(test_vcombine_f32 => vcombine_f32([3_f32, -4.], [13_f32, -14.]));
-
- test_vcombine!(test_vcombine_s64 => vcombine_s64([-3_i64], [13_i64]));
- test_vcombine!(test_vcombine_u64 => vcombine_u64([3_u64], [13_u64]));
- test_vcombine!(test_vcombine_p64 => vcombine_p64([3_u64], [13_u64]));
- test_vcombine!(test_vcombine_f64 => vcombine_f64([-3_f64], [13_f64]));
-
#[simd_test(enable = "neon")]
unsafe fn test_vdup_n_f64() {
let a: f64 = 3.3;
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 ac2709744..fe473c51e 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
@@ -17,7 +17,7 @@ use stdarch_test::assert_instr;
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vand))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(and))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vand_s8(a: int8x8_t, b: int8x8_t) -> int8x8_t {
simd_and(a, b)
}
@@ -30,7 +30,7 @@ pub unsafe fn vand_s8(a: int8x8_t, b: int8x8_t) -> int8x8_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vand))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(and))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vandq_s8(a: int8x16_t, b: int8x16_t) -> int8x16_t {
simd_and(a, b)
}
@@ -43,7 +43,7 @@ pub unsafe fn vandq_s8(a: int8x16_t, b: int8x16_t) -> int8x16_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vand))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(and))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vand_s16(a: int16x4_t, b: int16x4_t) -> int16x4_t {
simd_and(a, b)
}
@@ -56,7 +56,7 @@ pub unsafe fn vand_s16(a: int16x4_t, b: int16x4_t) -> int16x4_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vand))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(and))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vandq_s16(a: int16x8_t, b: int16x8_t) -> int16x8_t {
simd_and(a, b)
}
@@ -69,7 +69,7 @@ pub unsafe fn vandq_s16(a: int16x8_t, b: int16x8_t) -> int16x8_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vand))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(and))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vand_s32(a: int32x2_t, b: int32x2_t) -> int32x2_t {
simd_and(a, b)
}
@@ -82,7 +82,7 @@ pub unsafe fn vand_s32(a: int32x2_t, b: int32x2_t) -> int32x2_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vand))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(and))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vandq_s32(a: int32x4_t, b: int32x4_t) -> int32x4_t {
simd_and(a, b)
}
@@ -95,7 +95,7 @@ pub unsafe fn vandq_s32(a: int32x4_t, b: int32x4_t) -> int32x4_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vand))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(and))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vand_u8(a: uint8x8_t, b: uint8x8_t) -> uint8x8_t {
simd_and(a, b)
}
@@ -108,7 +108,7 @@ pub unsafe fn vand_u8(a: uint8x8_t, b: uint8x8_t) -> uint8x8_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vand))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(and))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vandq_u8(a: uint8x16_t, b: uint8x16_t) -> uint8x16_t {
simd_and(a, b)
}
@@ -121,7 +121,7 @@ pub unsafe fn vandq_u8(a: uint8x16_t, b: uint8x16_t) -> uint8x16_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vand))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(and))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vand_u16(a: uint16x4_t, b: uint16x4_t) -> uint16x4_t {
simd_and(a, b)
}
@@ -134,7 +134,7 @@ pub unsafe fn vand_u16(a: uint16x4_t, b: uint16x4_t) -> uint16x4_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vand))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(and))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vandq_u16(a: uint16x8_t, b: uint16x8_t) -> uint16x8_t {
simd_and(a, b)
}
@@ -147,7 +147,7 @@ pub unsafe fn vandq_u16(a: uint16x8_t, b: uint16x8_t) -> uint16x8_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vand))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(and))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vand_u32(a: uint32x2_t, b: uint32x2_t) -> uint32x2_t {
simd_and(a, b)
}
@@ -160,7 +160,7 @@ pub unsafe fn vand_u32(a: uint32x2_t, b: uint32x2_t) -> uint32x2_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vand))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(and))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vandq_u32(a: uint32x4_t, b: uint32x4_t) -> uint32x4_t {
simd_and(a, b)
}
@@ -173,7 +173,7 @@ pub unsafe fn vandq_u32(a: uint32x4_t, b: uint32x4_t) -> uint32x4_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vand))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(and))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vand_s64(a: int64x1_t, b: int64x1_t) -> int64x1_t {
simd_and(a, b)
}
@@ -186,7 +186,7 @@ pub unsafe fn vand_s64(a: int64x1_t, b: int64x1_t) -> int64x1_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vand))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(and))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vandq_s64(a: int64x2_t, b: int64x2_t) -> int64x2_t {
simd_and(a, b)
}
@@ -199,7 +199,7 @@ pub unsafe fn vandq_s64(a: int64x2_t, b: int64x2_t) -> int64x2_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vand))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(and))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vand_u64(a: uint64x1_t, b: uint64x1_t) -> uint64x1_t {
simd_and(a, b)
}
@@ -212,7 +212,7 @@ pub unsafe fn vand_u64(a: uint64x1_t, b: uint64x1_t) -> uint64x1_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vand))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(and))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vandq_u64(a: uint64x2_t, b: uint64x2_t) -> uint64x2_t {
simd_and(a, b)
}
@@ -225,7 +225,7 @@ pub unsafe fn vandq_u64(a: uint64x2_t, b: uint64x2_t) -> uint64x2_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vorr))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(orr))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vorr_s8(a: int8x8_t, b: int8x8_t) -> int8x8_t {
simd_or(a, b)
}
@@ -238,7 +238,7 @@ pub unsafe fn vorr_s8(a: int8x8_t, b: int8x8_t) -> int8x8_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vorr))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(orr))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vorrq_s8(a: int8x16_t, b: int8x16_t) -> int8x16_t {
simd_or(a, b)
}
@@ -251,7 +251,7 @@ pub unsafe fn vorrq_s8(a: int8x16_t, b: int8x16_t) -> int8x16_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vorr))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(orr))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vorr_s16(a: int16x4_t, b: int16x4_t) -> int16x4_t {
simd_or(a, b)
}
@@ -264,7 +264,7 @@ pub unsafe fn vorr_s16(a: int16x4_t, b: int16x4_t) -> int16x4_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vorr))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(orr))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vorrq_s16(a: int16x8_t, b: int16x8_t) -> int16x8_t {
simd_or(a, b)
}
@@ -277,7 +277,7 @@ pub unsafe fn vorrq_s16(a: int16x8_t, b: int16x8_t) -> int16x8_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vorr))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(orr))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vorr_s32(a: int32x2_t, b: int32x2_t) -> int32x2_t {
simd_or(a, b)
}
@@ -290,7 +290,7 @@ pub unsafe fn vorr_s32(a: int32x2_t, b: int32x2_t) -> int32x2_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vorr))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(orr))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vorrq_s32(a: int32x4_t, b: int32x4_t) -> int32x4_t {
simd_or(a, b)
}
@@ -303,7 +303,7 @@ pub unsafe fn vorrq_s32(a: int32x4_t, b: int32x4_t) -> int32x4_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vorr))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(orr))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vorr_u8(a: uint8x8_t, b: uint8x8_t) -> uint8x8_t {
simd_or(a, b)
}
@@ -316,7 +316,7 @@ pub unsafe fn vorr_u8(a: uint8x8_t, b: uint8x8_t) -> uint8x8_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vorr))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(orr))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vorrq_u8(a: uint8x16_t, b: uint8x16_t) -> uint8x16_t {
simd_or(a, b)
}
@@ -329,7 +329,7 @@ pub unsafe fn vorrq_u8(a: uint8x16_t, b: uint8x16_t) -> uint8x16_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vorr))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(orr))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vorr_u16(a: uint16x4_t, b: uint16x4_t) -> uint16x4_t {
simd_or(a, b)
}
@@ -342,7 +342,7 @@ pub unsafe fn vorr_u16(a: uint16x4_t, b: uint16x4_t) -> uint16x4_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vorr))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(orr))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vorrq_u16(a: uint16x8_t, b: uint16x8_t) -> uint16x8_t {
simd_or(a, b)
}
@@ -355,7 +355,7 @@ pub unsafe fn vorrq_u16(a: uint16x8_t, b: uint16x8_t) -> uint16x8_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vorr))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(orr))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vorr_u32(a: uint32x2_t, b: uint32x2_t) -> uint32x2_t {
simd_or(a, b)
}
@@ -368,7 +368,7 @@ pub unsafe fn vorr_u32(a: uint32x2_t, b: uint32x2_t) -> uint32x2_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vorr))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(orr))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vorrq_u32(a: uint32x4_t, b: uint32x4_t) -> uint32x4_t {
simd_or(a, b)
}
@@ -381,7 +381,7 @@ pub unsafe fn vorrq_u32(a: uint32x4_t, b: uint32x4_t) -> uint32x4_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vorr))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(orr))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vorr_s64(a: int64x1_t, b: int64x1_t) -> int64x1_t {
simd_or(a, b)
}
@@ -394,7 +394,7 @@ pub unsafe fn vorr_s64(a: int64x1_t, b: int64x1_t) -> int64x1_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vorr))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(orr))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vorrq_s64(a: int64x2_t, b: int64x2_t) -> int64x2_t {
simd_or(a, b)
}
@@ -407,7 +407,7 @@ pub unsafe fn vorrq_s64(a: int64x2_t, b: int64x2_t) -> int64x2_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vorr))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(orr))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vorr_u64(a: uint64x1_t, b: uint64x1_t) -> uint64x1_t {
simd_or(a, b)
}
@@ -420,7 +420,7 @@ pub unsafe fn vorr_u64(a: uint64x1_t, b: uint64x1_t) -> uint64x1_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vorr))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(orr))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vorrq_u64(a: uint64x2_t, b: uint64x2_t) -> uint64x2_t {
simd_or(a, b)
}
@@ -433,7 +433,7 @@ pub unsafe fn vorrq_u64(a: uint64x2_t, b: uint64x2_t) -> uint64x2_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(veor))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(eor))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn veor_s8(a: int8x8_t, b: int8x8_t) -> int8x8_t {
simd_xor(a, b)
}
@@ -446,7 +446,7 @@ pub unsafe fn veor_s8(a: int8x8_t, b: int8x8_t) -> int8x8_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(veor))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(eor))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn veorq_s8(a: int8x16_t, b: int8x16_t) -> int8x16_t {
simd_xor(a, b)
}
@@ -459,7 +459,7 @@ pub unsafe fn veorq_s8(a: int8x16_t, b: int8x16_t) -> int8x16_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(veor))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(eor))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn veor_s16(a: int16x4_t, b: int16x4_t) -> int16x4_t {
simd_xor(a, b)
}
@@ -472,7 +472,7 @@ pub unsafe fn veor_s16(a: int16x4_t, b: int16x4_t) -> int16x4_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(veor))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(eor))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn veorq_s16(a: int16x8_t, b: int16x8_t) -> int16x8_t {
simd_xor(a, b)
}
@@ -485,7 +485,7 @@ pub unsafe fn veorq_s16(a: int16x8_t, b: int16x8_t) -> int16x8_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(veor))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(eor))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn veor_s32(a: int32x2_t, b: int32x2_t) -> int32x2_t {
simd_xor(a, b)
}
@@ -498,7 +498,7 @@ pub unsafe fn veor_s32(a: int32x2_t, b: int32x2_t) -> int32x2_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(veor))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(eor))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn veorq_s32(a: int32x4_t, b: int32x4_t) -> int32x4_t {
simd_xor(a, b)
}
@@ -511,7 +511,7 @@ pub unsafe fn veorq_s32(a: int32x4_t, b: int32x4_t) -> int32x4_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(veor))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(eor))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn veor_u8(a: uint8x8_t, b: uint8x8_t) -> uint8x8_t {
simd_xor(a, b)
}
@@ -524,7 +524,7 @@ pub unsafe fn veor_u8(a: uint8x8_t, b: uint8x8_t) -> uint8x8_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(veor))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(eor))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn veorq_u8(a: uint8x16_t, b: uint8x16_t) -> uint8x16_t {
simd_xor(a, b)
}
@@ -537,7 +537,7 @@ pub unsafe fn veorq_u8(a: uint8x16_t, b: uint8x16_t) -> uint8x16_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(veor))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(eor))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn veor_u16(a: uint16x4_t, b: uint16x4_t) -> uint16x4_t {
simd_xor(a, b)
}
@@ -550,7 +550,7 @@ pub unsafe fn veor_u16(a: uint16x4_t, b: uint16x4_t) -> uint16x4_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(veor))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(eor))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn veorq_u16(a: uint16x8_t, b: uint16x8_t) -> uint16x8_t {
simd_xor(a, b)
}
@@ -563,7 +563,7 @@ pub unsafe fn veorq_u16(a: uint16x8_t, b: uint16x8_t) -> uint16x8_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(veor))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(eor))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn veor_u32(a: uint32x2_t, b: uint32x2_t) -> uint32x2_t {
simd_xor(a, b)
}
@@ -576,7 +576,7 @@ pub unsafe fn veor_u32(a: uint32x2_t, b: uint32x2_t) -> uint32x2_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(veor))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(eor))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn veorq_u32(a: uint32x4_t, b: uint32x4_t) -> uint32x4_t {
simd_xor(a, b)
}
@@ -589,7 +589,7 @@ pub unsafe fn veorq_u32(a: uint32x4_t, b: uint32x4_t) -> uint32x4_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(veor))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(eor))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn veor_s64(a: int64x1_t, b: int64x1_t) -> int64x1_t {
simd_xor(a, b)
}
@@ -602,7 +602,7 @@ pub unsafe fn veor_s64(a: int64x1_t, b: int64x1_t) -> int64x1_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(veor))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(eor))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn veorq_s64(a: int64x2_t, b: int64x2_t) -> int64x2_t {
simd_xor(a, b)
}
@@ -615,7 +615,7 @@ pub unsafe fn veorq_s64(a: int64x2_t, b: int64x2_t) -> int64x2_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(veor))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(eor))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn veor_u64(a: uint64x1_t, b: uint64x1_t) -> uint64x1_t {
simd_xor(a, b)
}
@@ -628,7 +628,7 @@ pub unsafe fn veor_u64(a: uint64x1_t, b: uint64x1_t) -> uint64x1_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(veor))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(eor))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn veorq_u64(a: uint64x2_t, b: uint64x2_t) -> uint64x2_t {
simd_xor(a, b)
}
@@ -641,7 +641,7 @@ pub unsafe fn veorq_u64(a: uint64x2_t, b: uint64x2_t) -> uint64x2_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vabd.s8"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sabd))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vabd_s8(a: int8x8_t, b: int8x8_t) -> int8x8_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -660,7 +660,7 @@ vabd_s8_(a, b)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vabd.s8"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sabd))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vabdq_s8(a: int8x16_t, b: int8x16_t) -> int8x16_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -679,7 +679,7 @@ vabdq_s8_(a, b)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vabd.s16"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sabd))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vabd_s16(a: int16x4_t, b: int16x4_t) -> int16x4_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -698,7 +698,7 @@ vabd_s16_(a, b)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vabd.s16"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sabd))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vabdq_s16(a: int16x8_t, b: int16x8_t) -> int16x8_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -717,7 +717,7 @@ vabdq_s16_(a, b)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vabd.s32"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sabd))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vabd_s32(a: int32x2_t, b: int32x2_t) -> int32x2_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -736,7 +736,7 @@ vabd_s32_(a, b)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vabd.s32"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sabd))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vabdq_s32(a: int32x4_t, b: int32x4_t) -> int32x4_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -755,7 +755,7 @@ vabdq_s32_(a, b)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vabd.u8"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uabd))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vabd_u8(a: uint8x8_t, b: uint8x8_t) -> uint8x8_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -774,7 +774,7 @@ vabd_u8_(a, b)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vabd.u8"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uabd))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vabdq_u8(a: uint8x16_t, b: uint8x16_t) -> uint8x16_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -793,7 +793,7 @@ vabdq_u8_(a, b)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vabd.u16"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uabd))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vabd_u16(a: uint16x4_t, b: uint16x4_t) -> uint16x4_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -812,7 +812,7 @@ vabd_u16_(a, b)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vabd.u16"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uabd))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vabdq_u16(a: uint16x8_t, b: uint16x8_t) -> uint16x8_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -831,7 +831,7 @@ vabdq_u16_(a, b)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vabd.u32"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uabd))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vabd_u32(a: uint32x2_t, b: uint32x2_t) -> uint32x2_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -850,7 +850,7 @@ vabd_u32_(a, b)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vabd.u32"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uabd))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vabdq_u32(a: uint32x4_t, b: uint32x4_t) -> uint32x4_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -869,7 +869,7 @@ vabdq_u32_(a, b)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vabd.f32"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(fabd))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vabd_f32(a: float32x2_t, b: float32x2_t) -> float32x2_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -888,7 +888,7 @@ vabd_f32_(a, b)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vabd.f32"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(fabd))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vabdq_f32(a: float32x4_t, b: float32x4_t) -> float32x4_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -907,7 +907,7 @@ vabdq_f32_(a, b)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vabdl.u8"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uabdl))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vabdl_u8(a: uint8x8_t, b: uint8x8_t) -> uint16x8_t {
simd_cast(vabd_u8(a, b))
}
@@ -920,7 +920,7 @@ pub unsafe fn vabdl_u8(a: uint8x8_t, b: uint8x8_t) -> uint16x8_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vabdl.u16"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uabdl))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vabdl_u16(a: uint16x4_t, b: uint16x4_t) -> uint32x4_t {
simd_cast(vabd_u16(a, b))
}
@@ -933,7 +933,7 @@ pub unsafe fn vabdl_u16(a: uint16x4_t, b: uint16x4_t) -> uint32x4_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vabdl.u32"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uabdl))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vabdl_u32(a: uint32x2_t, b: uint32x2_t) -> uint64x2_t {
simd_cast(vabd_u32(a, b))
}
@@ -946,7 +946,7 @@ pub unsafe fn vabdl_u32(a: uint32x2_t, b: uint32x2_t) -> uint64x2_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vabdl.s8"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sabdl))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vabdl_s8(a: int8x8_t, b: int8x8_t) -> int16x8_t {
let c: uint8x8_t = simd_cast(vabd_s8(a, b));
simd_cast(c)
@@ -960,7 +960,7 @@ pub unsafe fn vabdl_s8(a: int8x8_t, b: int8x8_t) -> int16x8_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vabdl.s16"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sabdl))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vabdl_s16(a: int16x4_t, b: int16x4_t) -> int32x4_t {
let c: uint16x4_t = simd_cast(vabd_s16(a, b));
simd_cast(c)
@@ -974,7 +974,7 @@ pub unsafe fn vabdl_s16(a: int16x4_t, b: int16x4_t) -> int32x4_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vabdl.s32"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sabdl))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vabdl_s32(a: int32x2_t, b: int32x2_t) -> int64x2_t {
let c: uint32x2_t = simd_cast(vabd_s32(a, b));
simd_cast(c)
@@ -988,7 +988,7 @@ pub unsafe fn vabdl_s32(a: int32x2_t, b: int32x2_t) -> int64x2_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vceq.i8"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(cmeq))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vceq_u8(a: uint8x8_t, b: uint8x8_t) -> uint8x8_t {
simd_eq(a, b)
}
@@ -1001,7 +1001,7 @@ pub unsafe fn vceq_u8(a: uint8x8_t, b: uint8x8_t) -> uint8x8_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vceq.i8"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(cmeq))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vceqq_u8(a: uint8x16_t, b: uint8x16_t) -> uint8x16_t {
simd_eq(a, b)
}
@@ -1014,7 +1014,7 @@ pub unsafe fn vceqq_u8(a: uint8x16_t, b: uint8x16_t) -> uint8x16_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vceq.i16"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(cmeq))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vceq_u16(a: uint16x4_t, b: uint16x4_t) -> uint16x4_t {
simd_eq(a, b)
}
@@ -1027,7 +1027,7 @@ pub unsafe fn vceq_u16(a: uint16x4_t, b: uint16x4_t) -> uint16x4_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vceq.i16"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(cmeq))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vceqq_u16(a: uint16x8_t, b: uint16x8_t) -> uint16x8_t {
simd_eq(a, b)
}
@@ -1040,7 +1040,7 @@ pub unsafe fn vceqq_u16(a: uint16x8_t, b: uint16x8_t) -> uint16x8_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vceq.i32"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(cmeq))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vceq_u32(a: uint32x2_t, b: uint32x2_t) -> uint32x2_t {
simd_eq(a, b)
}
@@ -1053,7 +1053,7 @@ pub unsafe fn vceq_u32(a: uint32x2_t, b: uint32x2_t) -> uint32x2_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vceq.i32"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(cmeq))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vceqq_u32(a: uint32x4_t, b: uint32x4_t) -> uint32x4_t {
simd_eq(a, b)
}
@@ -1066,7 +1066,7 @@ pub unsafe fn vceqq_u32(a: uint32x4_t, b: uint32x4_t) -> uint32x4_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vceq.i8"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(cmeq))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vceq_s8(a: int8x8_t, b: int8x8_t) -> uint8x8_t {
simd_eq(a, b)
}
@@ -1079,7 +1079,7 @@ pub unsafe fn vceq_s8(a: int8x8_t, b: int8x8_t) -> uint8x8_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vceq.i8"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(cmeq))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vceqq_s8(a: int8x16_t, b: int8x16_t) -> uint8x16_t {
simd_eq(a, b)
}
@@ -1092,7 +1092,7 @@ pub unsafe fn vceqq_s8(a: int8x16_t, b: int8x16_t) -> uint8x16_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vceq.i16"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(cmeq))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vceq_s16(a: int16x4_t, b: int16x4_t) -> uint16x4_t {
simd_eq(a, b)
}
@@ -1105,7 +1105,7 @@ pub unsafe fn vceq_s16(a: int16x4_t, b: int16x4_t) -> uint16x4_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vceq.i16"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(cmeq))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vceqq_s16(a: int16x8_t, b: int16x8_t) -> uint16x8_t {
simd_eq(a, b)
}
@@ -1118,7 +1118,7 @@ pub unsafe fn vceqq_s16(a: int16x8_t, b: int16x8_t) -> uint16x8_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vceq.i32"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(cmeq))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vceq_s32(a: int32x2_t, b: int32x2_t) -> uint32x2_t {
simd_eq(a, b)
}
@@ -1131,7 +1131,7 @@ pub unsafe fn vceq_s32(a: int32x2_t, b: int32x2_t) -> uint32x2_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vceq.i32"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(cmeq))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vceqq_s32(a: int32x4_t, b: int32x4_t) -> uint32x4_t {
simd_eq(a, b)
}
@@ -1144,7 +1144,7 @@ pub unsafe fn vceqq_s32(a: int32x4_t, b: int32x4_t) -> uint32x4_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vceq.i8"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(cmeq))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vceq_p8(a: poly8x8_t, b: poly8x8_t) -> uint8x8_t {
simd_eq(a, b)
}
@@ -1157,7 +1157,7 @@ pub unsafe fn vceq_p8(a: poly8x8_t, b: poly8x8_t) -> uint8x8_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vceq.i8"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(cmeq))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vceqq_p8(a: poly8x16_t, b: poly8x16_t) -> uint8x16_t {
simd_eq(a, b)
}
@@ -1170,7 +1170,7 @@ pub unsafe fn vceqq_p8(a: poly8x16_t, b: poly8x16_t) -> uint8x16_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vceq.f32"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(fcmeq))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vceq_f32(a: float32x2_t, b: float32x2_t) -> uint32x2_t {
simd_eq(a, b)
}
@@ -1183,7 +1183,7 @@ pub unsafe fn vceq_f32(a: float32x2_t, b: float32x2_t) -> uint32x2_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vceq.f32"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(fcmeq))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vceqq_f32(a: float32x4_t, b: float32x4_t) -> uint32x4_t {
simd_eq(a, b)
}
@@ -1196,7 +1196,7 @@ pub unsafe fn vceqq_f32(a: float32x4_t, b: float32x4_t) -> uint32x4_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vtst))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(cmtst))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vtst_s8(a: int8x8_t, b: int8x8_t) -> uint8x8_t {
let c: int8x8_t = simd_and(a, b);
let d: i8x8 = i8x8::new(0, 0, 0, 0, 0, 0, 0, 0);
@@ -1211,7 +1211,7 @@ pub unsafe fn vtst_s8(a: int8x8_t, b: int8x8_t) -> uint8x8_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vtst))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(cmtst))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vtstq_s8(a: int8x16_t, b: int8x16_t) -> uint8x16_t {
let c: int8x16_t = simd_and(a, b);
let d: i8x16 = i8x16::new(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
@@ -1226,7 +1226,7 @@ pub unsafe fn vtstq_s8(a: int8x16_t, b: int8x16_t) -> uint8x16_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vtst))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(cmtst))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vtst_s16(a: int16x4_t, b: int16x4_t) -> uint16x4_t {
let c: int16x4_t = simd_and(a, b);
let d: i16x4 = i16x4::new(0, 0, 0, 0);
@@ -1241,7 +1241,7 @@ pub unsafe fn vtst_s16(a: int16x4_t, b: int16x4_t) -> uint16x4_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vtst))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(cmtst))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vtstq_s16(a: int16x8_t, b: int16x8_t) -> uint16x8_t {
let c: int16x8_t = simd_and(a, b);
let d: i16x8 = i16x8::new(0, 0, 0, 0, 0, 0, 0, 0);
@@ -1256,7 +1256,7 @@ pub unsafe fn vtstq_s16(a: int16x8_t, b: int16x8_t) -> uint16x8_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vtst))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(cmtst))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vtst_s32(a: int32x2_t, b: int32x2_t) -> uint32x2_t {
let c: int32x2_t = simd_and(a, b);
let d: i32x2 = i32x2::new(0, 0);
@@ -1271,7 +1271,7 @@ pub unsafe fn vtst_s32(a: int32x2_t, b: int32x2_t) -> uint32x2_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vtst))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(cmtst))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vtstq_s32(a: int32x4_t, b: int32x4_t) -> uint32x4_t {
let c: int32x4_t = simd_and(a, b);
let d: i32x4 = i32x4::new(0, 0, 0, 0);
@@ -1286,7 +1286,7 @@ pub unsafe fn vtstq_s32(a: int32x4_t, b: int32x4_t) -> uint32x4_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vtst))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(cmtst))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vtst_p8(a: poly8x8_t, b: poly8x8_t) -> uint8x8_t {
let c: poly8x8_t = simd_and(a, b);
let d: i8x8 = i8x8::new(0, 0, 0, 0, 0, 0, 0, 0);
@@ -1301,7 +1301,7 @@ pub unsafe fn vtst_p8(a: poly8x8_t, b: poly8x8_t) -> uint8x8_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vtst))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(cmtst))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vtstq_p8(a: poly8x16_t, b: poly8x16_t) -> uint8x16_t {
let c: poly8x16_t = simd_and(a, b);
let d: i8x16 = i8x16::new(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
@@ -1316,7 +1316,7 @@ pub unsafe fn vtstq_p8(a: poly8x16_t, b: poly8x16_t) -> uint8x16_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vtst))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(cmtst))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vtst_p16(a: poly16x4_t, b: poly16x4_t) -> uint16x4_t {
let c: poly16x4_t = simd_and(a, b);
let d: i16x4 = i16x4::new(0, 0, 0, 0);
@@ -1331,7 +1331,7 @@ pub unsafe fn vtst_p16(a: poly16x4_t, b: poly16x4_t) -> uint16x4_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vtst))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(cmtst))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vtstq_p16(a: poly16x8_t, b: poly16x8_t) -> uint16x8_t {
let c: poly16x8_t = simd_and(a, b);
let d: i16x8 = i16x8::new(0, 0, 0, 0, 0, 0, 0, 0);
@@ -1346,7 +1346,7 @@ pub unsafe fn vtstq_p16(a: poly16x8_t, b: poly16x8_t) -> uint16x8_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vtst))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(cmtst))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vtst_u8(a: uint8x8_t, b: uint8x8_t) -> uint8x8_t {
let c: uint8x8_t = simd_and(a, b);
let d: u8x8 = u8x8::new(0, 0, 0, 0, 0, 0, 0, 0);
@@ -1361,7 +1361,7 @@ pub unsafe fn vtst_u8(a: uint8x8_t, b: uint8x8_t) -> uint8x8_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vtst))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(cmtst))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vtstq_u8(a: uint8x16_t, b: uint8x16_t) -> uint8x16_t {
let c: uint8x16_t = simd_and(a, b);
let d: u8x16 = u8x16::new(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
@@ -1376,7 +1376,7 @@ pub unsafe fn vtstq_u8(a: uint8x16_t, b: uint8x16_t) -> uint8x16_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vtst))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(cmtst))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vtst_u16(a: uint16x4_t, b: uint16x4_t) -> uint16x4_t {
let c: uint16x4_t = simd_and(a, b);
let d: u16x4 = u16x4::new(0, 0, 0, 0);
@@ -1391,7 +1391,7 @@ pub unsafe fn vtst_u16(a: uint16x4_t, b: uint16x4_t) -> uint16x4_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vtst))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(cmtst))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vtstq_u16(a: uint16x8_t, b: uint16x8_t) -> uint16x8_t {
let c: uint16x8_t = simd_and(a, b);
let d: u16x8 = u16x8::new(0, 0, 0, 0, 0, 0, 0, 0);
@@ -1406,7 +1406,7 @@ pub unsafe fn vtstq_u16(a: uint16x8_t, b: uint16x8_t) -> uint16x8_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vtst))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(cmtst))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vtst_u32(a: uint32x2_t, b: uint32x2_t) -> uint32x2_t {
let c: uint32x2_t = simd_and(a, b);
let d: u32x2 = u32x2::new(0, 0);
@@ -1421,7 +1421,7 @@ pub unsafe fn vtst_u32(a: uint32x2_t, b: uint32x2_t) -> uint32x2_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vtst))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(cmtst))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vtstq_u32(a: uint32x4_t, b: uint32x4_t) -> uint32x4_t {
let c: uint32x4_t = simd_and(a, b);
let d: u32x4 = u32x4::new(0, 0, 0, 0);
@@ -1436,7 +1436,7 @@ pub unsafe fn vtstq_u32(a: uint32x4_t, b: uint32x4_t) -> uint32x4_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vabs))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(fabs))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vabs_f32(a: float32x2_t) -> float32x2_t {
simd_fabs(a)
}
@@ -1449,7 +1449,7 @@ pub unsafe fn vabs_f32(a: float32x2_t) -> float32x2_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vabs))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(fabs))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vabsq_f32(a: float32x4_t) -> float32x4_t {
simd_fabs(a)
}
@@ -1462,7 +1462,7 @@ pub unsafe fn vabsq_f32(a: float32x4_t) -> float32x4_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vcgt.s8"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(cmgt))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vcgt_s8(a: int8x8_t, b: int8x8_t) -> uint8x8_t {
simd_gt(a, b)
}
@@ -1475,7 +1475,7 @@ pub unsafe fn vcgt_s8(a: int8x8_t, b: int8x8_t) -> uint8x8_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vcgt.s8"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(cmgt))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vcgtq_s8(a: int8x16_t, b: int8x16_t) -> uint8x16_t {
simd_gt(a, b)
}
@@ -1488,7 +1488,7 @@ pub unsafe fn vcgtq_s8(a: int8x16_t, b: int8x16_t) -> uint8x16_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vcgt.s16"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(cmgt))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vcgt_s16(a: int16x4_t, b: int16x4_t) -> uint16x4_t {
simd_gt(a, b)
}
@@ -1501,7 +1501,7 @@ pub unsafe fn vcgt_s16(a: int16x4_t, b: int16x4_t) -> uint16x4_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vcgt.s16"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(cmgt))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vcgtq_s16(a: int16x8_t, b: int16x8_t) -> uint16x8_t {
simd_gt(a, b)
}
@@ -1514,7 +1514,7 @@ pub unsafe fn vcgtq_s16(a: int16x8_t, b: int16x8_t) -> uint16x8_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vcgt.s32"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(cmgt))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vcgt_s32(a: int32x2_t, b: int32x2_t) -> uint32x2_t {
simd_gt(a, b)
}
@@ -1527,7 +1527,7 @@ pub unsafe fn vcgt_s32(a: int32x2_t, b: int32x2_t) -> uint32x2_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vcgt.s32"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(cmgt))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vcgtq_s32(a: int32x4_t, b: int32x4_t) -> uint32x4_t {
simd_gt(a, b)
}
@@ -1540,7 +1540,7 @@ pub unsafe fn vcgtq_s32(a: int32x4_t, b: int32x4_t) -> uint32x4_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vcgt.u8"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(cmhi))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vcgt_u8(a: uint8x8_t, b: uint8x8_t) -> uint8x8_t {
simd_gt(a, b)
}
@@ -1553,7 +1553,7 @@ pub unsafe fn vcgt_u8(a: uint8x8_t, b: uint8x8_t) -> uint8x8_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vcgt.u8"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(cmhi))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vcgtq_u8(a: uint8x16_t, b: uint8x16_t) -> uint8x16_t {
simd_gt(a, b)
}
@@ -1566,7 +1566,7 @@ pub unsafe fn vcgtq_u8(a: uint8x16_t, b: uint8x16_t) -> uint8x16_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vcgt.u16"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(cmhi))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vcgt_u16(a: uint16x4_t, b: uint16x4_t) -> uint16x4_t {
simd_gt(a, b)
}
@@ -1579,7 +1579,7 @@ pub unsafe fn vcgt_u16(a: uint16x4_t, b: uint16x4_t) -> uint16x4_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vcgt.u16"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(cmhi))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vcgtq_u16(a: uint16x8_t, b: uint16x8_t) -> uint16x8_t {
simd_gt(a, b)
}
@@ -1592,7 +1592,7 @@ pub unsafe fn vcgtq_u16(a: uint16x8_t, b: uint16x8_t) -> uint16x8_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vcgt.u32"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(cmhi))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vcgt_u32(a: uint32x2_t, b: uint32x2_t) -> uint32x2_t {
simd_gt(a, b)
}
@@ -1605,7 +1605,7 @@ pub unsafe fn vcgt_u32(a: uint32x2_t, b: uint32x2_t) -> uint32x2_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vcgt.u32"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(cmhi))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vcgtq_u32(a: uint32x4_t, b: uint32x4_t) -> uint32x4_t {
simd_gt(a, b)
}
@@ -1618,7 +1618,7 @@ pub unsafe fn vcgtq_u32(a: uint32x4_t, b: uint32x4_t) -> uint32x4_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vcgt.f32"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(fcmgt))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vcgt_f32(a: float32x2_t, b: float32x2_t) -> uint32x2_t {
simd_gt(a, b)
}
@@ -1631,7 +1631,7 @@ pub unsafe fn vcgt_f32(a: float32x2_t, b: float32x2_t) -> uint32x2_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vcgt.f32"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(fcmgt))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vcgtq_f32(a: float32x4_t, b: float32x4_t) -> uint32x4_t {
simd_gt(a, b)
}
@@ -1644,7 +1644,7 @@ pub unsafe fn vcgtq_f32(a: float32x4_t, b: float32x4_t) -> uint32x4_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vcgt.s8"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(cmgt))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vclt_s8(a: int8x8_t, b: int8x8_t) -> uint8x8_t {
simd_lt(a, b)
}
@@ -1657,7 +1657,7 @@ pub unsafe fn vclt_s8(a: int8x8_t, b: int8x8_t) -> uint8x8_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vcgt.s8"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(cmgt))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vcltq_s8(a: int8x16_t, b: int8x16_t) -> uint8x16_t {
simd_lt(a, b)
}
@@ -1670,7 +1670,7 @@ pub unsafe fn vcltq_s8(a: int8x16_t, b: int8x16_t) -> uint8x16_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vcgt.s16"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(cmgt))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vclt_s16(a: int16x4_t, b: int16x4_t) -> uint16x4_t {
simd_lt(a, b)
}
@@ -1683,7 +1683,7 @@ pub unsafe fn vclt_s16(a: int16x4_t, b: int16x4_t) -> uint16x4_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vcgt.s16"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(cmgt))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vcltq_s16(a: int16x8_t, b: int16x8_t) -> uint16x8_t {
simd_lt(a, b)
}
@@ -1696,7 +1696,7 @@ pub unsafe fn vcltq_s16(a: int16x8_t, b: int16x8_t) -> uint16x8_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vcgt.s32"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(cmgt))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vclt_s32(a: int32x2_t, b: int32x2_t) -> uint32x2_t {
simd_lt(a, b)
}
@@ -1709,7 +1709,7 @@ pub unsafe fn vclt_s32(a: int32x2_t, b: int32x2_t) -> uint32x2_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vcgt.s32"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(cmgt))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vcltq_s32(a: int32x4_t, b: int32x4_t) -> uint32x4_t {
simd_lt(a, b)
}
@@ -1722,7 +1722,7 @@ pub unsafe fn vcltq_s32(a: int32x4_t, b: int32x4_t) -> uint32x4_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vcgt.u8"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(cmhi))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vclt_u8(a: uint8x8_t, b: uint8x8_t) -> uint8x8_t {
simd_lt(a, b)
}
@@ -1735,7 +1735,7 @@ pub unsafe fn vclt_u8(a: uint8x8_t, b: uint8x8_t) -> uint8x8_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vcgt.u8"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(cmhi))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vcltq_u8(a: uint8x16_t, b: uint8x16_t) -> uint8x16_t {
simd_lt(a, b)
}
@@ -1748,7 +1748,7 @@ pub unsafe fn vcltq_u8(a: uint8x16_t, b: uint8x16_t) -> uint8x16_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vcgt.u16"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(cmhi))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vclt_u16(a: uint16x4_t, b: uint16x4_t) -> uint16x4_t {
simd_lt(a, b)
}
@@ -1761,7 +1761,7 @@ pub unsafe fn vclt_u16(a: uint16x4_t, b: uint16x4_t) -> uint16x4_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vcgt.u16"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(cmhi))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vcltq_u16(a: uint16x8_t, b: uint16x8_t) -> uint16x8_t {
simd_lt(a, b)
}
@@ -1774,7 +1774,7 @@ pub unsafe fn vcltq_u16(a: uint16x8_t, b: uint16x8_t) -> uint16x8_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vcgt.u32"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(cmhi))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vclt_u32(a: uint32x2_t, b: uint32x2_t) -> uint32x2_t {
simd_lt(a, b)
}
@@ -1787,7 +1787,7 @@ pub unsafe fn vclt_u32(a: uint32x2_t, b: uint32x2_t) -> uint32x2_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vcgt.u32"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(cmhi))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vcltq_u32(a: uint32x4_t, b: uint32x4_t) -> uint32x4_t {
simd_lt(a, b)
}
@@ -1800,7 +1800,7 @@ pub unsafe fn vcltq_u32(a: uint32x4_t, b: uint32x4_t) -> uint32x4_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vcgt.f32"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(fcmgt))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vclt_f32(a: float32x2_t, b: float32x2_t) -> uint32x2_t {
simd_lt(a, b)
}
@@ -1813,7 +1813,7 @@ pub unsafe fn vclt_f32(a: float32x2_t, b: float32x2_t) -> uint32x2_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vcgt.f32"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(fcmgt))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vcltq_f32(a: float32x4_t, b: float32x4_t) -> uint32x4_t {
simd_lt(a, b)
}
@@ -1826,7 +1826,7 @@ pub unsafe fn vcltq_f32(a: float32x4_t, b: float32x4_t) -> uint32x4_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vcge.s8"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(cmge))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vcle_s8(a: int8x8_t, b: int8x8_t) -> uint8x8_t {
simd_le(a, b)
}
@@ -1839,7 +1839,7 @@ pub unsafe fn vcle_s8(a: int8x8_t, b: int8x8_t) -> uint8x8_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vcge.s8"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(cmge))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vcleq_s8(a: int8x16_t, b: int8x16_t) -> uint8x16_t {
simd_le(a, b)
}
@@ -1852,7 +1852,7 @@ pub unsafe fn vcleq_s8(a: int8x16_t, b: int8x16_t) -> uint8x16_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vcge.s16"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(cmge))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vcle_s16(a: int16x4_t, b: int16x4_t) -> uint16x4_t {
simd_le(a, b)
}
@@ -1865,7 +1865,7 @@ pub unsafe fn vcle_s16(a: int16x4_t, b: int16x4_t) -> uint16x4_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vcge.s16"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(cmge))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vcleq_s16(a: int16x8_t, b: int16x8_t) -> uint16x8_t {
simd_le(a, b)
}
@@ -1878,7 +1878,7 @@ pub unsafe fn vcleq_s16(a: int16x8_t, b: int16x8_t) -> uint16x8_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vcge.s32"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(cmge))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vcle_s32(a: int32x2_t, b: int32x2_t) -> uint32x2_t {
simd_le(a, b)
}
@@ -1891,7 +1891,7 @@ pub unsafe fn vcle_s32(a: int32x2_t, b: int32x2_t) -> uint32x2_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vcge.s32"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(cmge))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vcleq_s32(a: int32x4_t, b: int32x4_t) -> uint32x4_t {
simd_le(a, b)
}
@@ -1904,7 +1904,7 @@ pub unsafe fn vcleq_s32(a: int32x4_t, b: int32x4_t) -> uint32x4_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vcge.u8"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(cmhs))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vcle_u8(a: uint8x8_t, b: uint8x8_t) -> uint8x8_t {
simd_le(a, b)
}
@@ -1917,7 +1917,7 @@ pub unsafe fn vcle_u8(a: uint8x8_t, b: uint8x8_t) -> uint8x8_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vcge.u8"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(cmhs))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vcleq_u8(a: uint8x16_t, b: uint8x16_t) -> uint8x16_t {
simd_le(a, b)
}
@@ -1930,7 +1930,7 @@ pub unsafe fn vcleq_u8(a: uint8x16_t, b: uint8x16_t) -> uint8x16_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vcge.u16"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(cmhs))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vcle_u16(a: uint16x4_t, b: uint16x4_t) -> uint16x4_t {
simd_le(a, b)
}
@@ -1943,7 +1943,7 @@ pub unsafe fn vcle_u16(a: uint16x4_t, b: uint16x4_t) -> uint16x4_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vcge.u16"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(cmhs))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vcleq_u16(a: uint16x8_t, b: uint16x8_t) -> uint16x8_t {
simd_le(a, b)
}
@@ -1956,7 +1956,7 @@ pub unsafe fn vcleq_u16(a: uint16x8_t, b: uint16x8_t) -> uint16x8_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vcge.u32"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(cmhs))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vcle_u32(a: uint32x2_t, b: uint32x2_t) -> uint32x2_t {
simd_le(a, b)
}
@@ -1969,7 +1969,7 @@ pub unsafe fn vcle_u32(a: uint32x2_t, b: uint32x2_t) -> uint32x2_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vcge.u32"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(cmhs))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vcleq_u32(a: uint32x4_t, b: uint32x4_t) -> uint32x4_t {
simd_le(a, b)
}
@@ -1982,7 +1982,7 @@ pub unsafe fn vcleq_u32(a: uint32x4_t, b: uint32x4_t) -> uint32x4_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vcge.f32"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(fcmge))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vcle_f32(a: float32x2_t, b: float32x2_t) -> uint32x2_t {
simd_le(a, b)
}
@@ -1995,7 +1995,7 @@ pub unsafe fn vcle_f32(a: float32x2_t, b: float32x2_t) -> uint32x2_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vcge.f32"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(fcmge))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vcleq_f32(a: float32x4_t, b: float32x4_t) -> uint32x4_t {
simd_le(a, b)
}
@@ -2008,7 +2008,7 @@ pub unsafe fn vcleq_f32(a: float32x4_t, b: float32x4_t) -> uint32x4_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vcge.s8"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(cmge))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vcge_s8(a: int8x8_t, b: int8x8_t) -> uint8x8_t {
simd_ge(a, b)
}
@@ -2021,7 +2021,7 @@ pub unsafe fn vcge_s8(a: int8x8_t, b: int8x8_t) -> uint8x8_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vcge.s8"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(cmge))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vcgeq_s8(a: int8x16_t, b: int8x16_t) -> uint8x16_t {
simd_ge(a, b)
}
@@ -2034,7 +2034,7 @@ pub unsafe fn vcgeq_s8(a: int8x16_t, b: int8x16_t) -> uint8x16_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vcge.s16"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(cmge))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vcge_s16(a: int16x4_t, b: int16x4_t) -> uint16x4_t {
simd_ge(a, b)
}
@@ -2047,7 +2047,7 @@ pub unsafe fn vcge_s16(a: int16x4_t, b: int16x4_t) -> uint16x4_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vcge.s16"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(cmge))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vcgeq_s16(a: int16x8_t, b: int16x8_t) -> uint16x8_t {
simd_ge(a, b)
}
@@ -2060,7 +2060,7 @@ pub unsafe fn vcgeq_s16(a: int16x8_t, b: int16x8_t) -> uint16x8_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vcge.s32"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(cmge))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vcge_s32(a: int32x2_t, b: int32x2_t) -> uint32x2_t {
simd_ge(a, b)
}
@@ -2073,7 +2073,7 @@ pub unsafe fn vcge_s32(a: int32x2_t, b: int32x2_t) -> uint32x2_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vcge.s32"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(cmge))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vcgeq_s32(a: int32x4_t, b: int32x4_t) -> uint32x4_t {
simd_ge(a, b)
}
@@ -2086,7 +2086,7 @@ pub unsafe fn vcgeq_s32(a: int32x4_t, b: int32x4_t) -> uint32x4_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vcge.u8"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(cmhs))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vcge_u8(a: uint8x8_t, b: uint8x8_t) -> uint8x8_t {
simd_ge(a, b)
}
@@ -2099,7 +2099,7 @@ pub unsafe fn vcge_u8(a: uint8x8_t, b: uint8x8_t) -> uint8x8_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vcge.u8"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(cmhs))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vcgeq_u8(a: uint8x16_t, b: uint8x16_t) -> uint8x16_t {
simd_ge(a, b)
}
@@ -2112,7 +2112,7 @@ pub unsafe fn vcgeq_u8(a: uint8x16_t, b: uint8x16_t) -> uint8x16_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vcge.u16"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(cmhs))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vcge_u16(a: uint16x4_t, b: uint16x4_t) -> uint16x4_t {
simd_ge(a, b)
}
@@ -2125,7 +2125,7 @@ pub unsafe fn vcge_u16(a: uint16x4_t, b: uint16x4_t) -> uint16x4_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vcge.u16"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(cmhs))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vcgeq_u16(a: uint16x8_t, b: uint16x8_t) -> uint16x8_t {
simd_ge(a, b)
}
@@ -2138,7 +2138,7 @@ pub unsafe fn vcgeq_u16(a: uint16x8_t, b: uint16x8_t) -> uint16x8_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vcge.u32"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(cmhs))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vcge_u32(a: uint32x2_t, b: uint32x2_t) -> uint32x2_t {
simd_ge(a, b)
}
@@ -2151,7 +2151,7 @@ pub unsafe fn vcge_u32(a: uint32x2_t, b: uint32x2_t) -> uint32x2_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vcge.u32"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(cmhs))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vcgeq_u32(a: uint32x4_t, b: uint32x4_t) -> uint32x4_t {
simd_ge(a, b)
}
@@ -2164,7 +2164,7 @@ pub unsafe fn vcgeq_u32(a: uint32x4_t, b: uint32x4_t) -> uint32x4_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vcge.f32"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(fcmge))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vcge_f32(a: float32x2_t, b: float32x2_t) -> uint32x2_t {
simd_ge(a, b)
}
@@ -2177,7 +2177,7 @@ pub unsafe fn vcge_f32(a: float32x2_t, b: float32x2_t) -> uint32x2_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vcge.f32"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(fcmge))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vcgeq_f32(a: float32x4_t, b: float32x4_t) -> uint32x4_t {
simd_ge(a, b)
}
@@ -2190,7 +2190,7 @@ pub unsafe fn vcgeq_f32(a: float32x4_t, b: float32x4_t) -> uint32x4_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vcls.s8"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(cls))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vcls_s8(a: int8x8_t) -> int8x8_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -2209,7 +2209,7 @@ vcls_s8_(a)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vcls.s8"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(cls))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vclsq_s8(a: int8x16_t) -> int8x16_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -2228,7 +2228,7 @@ vclsq_s8_(a)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vcls.s16"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(cls))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vcls_s16(a: int16x4_t) -> int16x4_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -2247,7 +2247,7 @@ vcls_s16_(a)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vcls.s16"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(cls))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vclsq_s16(a: int16x8_t) -> int16x8_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -2266,7 +2266,7 @@ vclsq_s16_(a)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vcls.s32"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(cls))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vcls_s32(a: int32x2_t) -> int32x2_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -2285,7 +2285,7 @@ vcls_s32_(a)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vcls.s32"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(cls))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vclsq_s32(a: int32x4_t) -> int32x4_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -2304,7 +2304,7 @@ vclsq_s32_(a)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vcls))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(cls))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vcls_u8(a: uint8x8_t) -> int8x8_t {
transmute(vcls_s8(transmute(a)))
}
@@ -2317,7 +2317,7 @@ pub unsafe fn vcls_u8(a: uint8x8_t) -> int8x8_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vcls))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(cls))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vclsq_u8(a: uint8x16_t) -> int8x16_t {
transmute(vclsq_s8(transmute(a)))
}
@@ -2330,7 +2330,7 @@ pub unsafe fn vclsq_u8(a: uint8x16_t) -> int8x16_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vcls))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(cls))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vcls_u16(a: uint16x4_t) -> int16x4_t {
transmute(vcls_s16(transmute(a)))
}
@@ -2343,7 +2343,7 @@ pub unsafe fn vcls_u16(a: uint16x4_t) -> int16x4_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vcls))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(cls))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vclsq_u16(a: uint16x8_t) -> int16x8_t {
transmute(vclsq_s16(transmute(a)))
}
@@ -2356,7 +2356,7 @@ pub unsafe fn vclsq_u16(a: uint16x8_t) -> int16x8_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vcls))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(cls))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vcls_u32(a: uint32x2_t) -> int32x2_t {
transmute(vcls_s32(transmute(a)))
}
@@ -2369,7 +2369,7 @@ pub unsafe fn vcls_u32(a: uint32x2_t) -> int32x2_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vcls))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(cls))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vclsq_u32(a: uint32x4_t) -> int32x4_t {
transmute(vclsq_s32(transmute(a)))
}
@@ -2382,7 +2382,7 @@ pub unsafe fn vclsq_u32(a: uint32x4_t) -> int32x4_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vclz.i8"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(clz))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vclz_s8(a: int8x8_t) -> int8x8_t {
vclz_s8_(a)
}
@@ -2395,7 +2395,7 @@ pub unsafe fn vclz_s8(a: int8x8_t) -> int8x8_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vclz.i8"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(clz))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vclzq_s8(a: int8x16_t) -> int8x16_t {
vclzq_s8_(a)
}
@@ -2408,7 +2408,7 @@ pub unsafe fn vclzq_s8(a: int8x16_t) -> int8x16_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vclz.i16"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(clz))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vclz_s16(a: int16x4_t) -> int16x4_t {
vclz_s16_(a)
}
@@ -2421,7 +2421,7 @@ pub unsafe fn vclz_s16(a: int16x4_t) -> int16x4_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vclz.i16"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(clz))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vclzq_s16(a: int16x8_t) -> int16x8_t {
vclzq_s16_(a)
}
@@ -2434,7 +2434,7 @@ pub unsafe fn vclzq_s16(a: int16x8_t) -> int16x8_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vclz.i32"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(clz))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vclz_s32(a: int32x2_t) -> int32x2_t {
vclz_s32_(a)
}
@@ -2447,7 +2447,7 @@ pub unsafe fn vclz_s32(a: int32x2_t) -> int32x2_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vclz.i32"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(clz))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vclzq_s32(a: int32x4_t) -> int32x4_t {
vclzq_s32_(a)
}
@@ -2460,7 +2460,7 @@ pub unsafe fn vclzq_s32(a: int32x4_t) -> int32x4_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vclz.i8"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(clz))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vclz_u8(a: uint8x8_t) -> uint8x8_t {
transmute(vclz_s8_(transmute(a)))
}
@@ -2473,7 +2473,7 @@ pub unsafe fn vclz_u8(a: uint8x8_t) -> uint8x8_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vclz.i8"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(clz))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vclzq_u8(a: uint8x16_t) -> uint8x16_t {
transmute(vclzq_s8_(transmute(a)))
}
@@ -2486,7 +2486,7 @@ pub unsafe fn vclzq_u8(a: uint8x16_t) -> uint8x16_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vclz.i16"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(clz))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vclz_u16(a: uint16x4_t) -> uint16x4_t {
transmute(vclz_s16_(transmute(a)))
}
@@ -2499,7 +2499,7 @@ pub unsafe fn vclz_u16(a: uint16x4_t) -> uint16x4_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vclz.i16"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(clz))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vclzq_u16(a: uint16x8_t) -> uint16x8_t {
transmute(vclzq_s16_(transmute(a)))
}
@@ -2512,7 +2512,7 @@ pub unsafe fn vclzq_u16(a: uint16x8_t) -> uint16x8_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vclz.i32"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(clz))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vclz_u32(a: uint32x2_t) -> uint32x2_t {
transmute(vclz_s32_(transmute(a)))
}
@@ -2525,7 +2525,7 @@ pub unsafe fn vclz_u32(a: uint32x2_t) -> uint32x2_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vclz.i32"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(clz))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vclzq_u32(a: uint32x4_t) -> uint32x4_t {
transmute(vclzq_s32_(transmute(a)))
}
@@ -2538,7 +2538,7 @@ pub unsafe fn vclzq_u32(a: uint32x4_t) -> uint32x4_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vacgt.f32"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(facgt))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vcagt_f32(a: float32x2_t, b: float32x2_t) -> uint32x2_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -2557,7 +2557,7 @@ vcagt_f32_(a, b)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vacgt.f32"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(facgt))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vcagtq_f32(a: float32x4_t, b: float32x4_t) -> uint32x4_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -2576,7 +2576,7 @@ vcagtq_f32_(a, b)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vacge.f32"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(facge))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vcage_f32(a: float32x2_t, b: float32x2_t) -> uint32x2_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -2595,7 +2595,7 @@ vcage_f32_(a, b)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vacge.f32"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(facge))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vcageq_f32(a: float32x4_t, b: float32x4_t) -> uint32x4_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -2614,7 +2614,7 @@ vcageq_f32_(a, b)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vacgt.f32"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(facgt))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vcalt_f32(a: float32x2_t, b: float32x2_t) -> uint32x2_t {
vcagt_f32(b, a)
}
@@ -2627,7 +2627,7 @@ pub unsafe fn vcalt_f32(a: float32x2_t, b: float32x2_t) -> uint32x2_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vacgt.f32"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(facgt))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vcaltq_f32(a: float32x4_t, b: float32x4_t) -> uint32x4_t {
vcagtq_f32(b, a)
}
@@ -2640,7 +2640,7 @@ pub unsafe fn vcaltq_f32(a: float32x4_t, b: float32x4_t) -> uint32x4_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vacge.f32"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(facge))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vcale_f32(a: float32x2_t, b: float32x2_t) -> uint32x2_t {
vcage_f32(b, a)
}
@@ -2653,7 +2653,7 @@ pub unsafe fn vcale_f32(a: float32x2_t, b: float32x2_t) -> uint32x2_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vacge.f32"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(facge))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vcaleq_f32(a: float32x4_t, b: float32x4_t) -> uint32x4_t {
vcageq_f32(b, a)
}
@@ -2666,7 +2666,7 @@ pub unsafe fn vcaleq_f32(a: float32x4_t, b: float32x4_t) -> uint32x4_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vcreate_s8(a: u64) -> int8x8_t {
transmute(a)
}
@@ -2679,7 +2679,7 @@ pub unsafe fn vcreate_s8(a: u64) -> int8x8_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vcreate_s16(a: u64) -> int16x4_t {
transmute(a)
}
@@ -2692,7 +2692,7 @@ pub unsafe fn vcreate_s16(a: u64) -> int16x4_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vcreate_s32(a: u64) -> int32x2_t {
transmute(a)
}
@@ -2705,7 +2705,7 @@ pub unsafe fn vcreate_s32(a: u64) -> int32x2_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vcreate_s64(a: u64) -> int64x1_t {
transmute(a)
}
@@ -2718,7 +2718,7 @@ pub unsafe fn vcreate_s64(a: u64) -> int64x1_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vcreate_u8(a: u64) -> uint8x8_t {
transmute(a)
}
@@ -2731,7 +2731,7 @@ pub unsafe fn vcreate_u8(a: u64) -> uint8x8_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vcreate_u16(a: u64) -> uint16x4_t {
transmute(a)
}
@@ -2744,7 +2744,7 @@ pub unsafe fn vcreate_u16(a: u64) -> uint16x4_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vcreate_u32(a: u64) -> uint32x2_t {
transmute(a)
}
@@ -2757,7 +2757,7 @@ pub unsafe fn vcreate_u32(a: u64) -> uint32x2_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vcreate_u64(a: u64) -> uint64x1_t {
transmute(a)
}
@@ -2770,7 +2770,7 @@ pub unsafe fn vcreate_u64(a: u64) -> uint64x1_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vcreate_p8(a: u64) -> poly8x8_t {
transmute(a)
}
@@ -2783,7 +2783,7 @@ pub unsafe fn vcreate_p8(a: u64) -> poly8x8_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vcreate_p16(a: u64) -> poly16x4_t {
transmute(a)
}
@@ -2796,7 +2796,7 @@ pub unsafe fn vcreate_p16(a: u64) -> poly16x4_t {
#[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))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vcreate_p64(a: u64) -> poly64x1_t {
transmute(a)
}
@@ -2809,7 +2809,7 @@ pub unsafe fn vcreate_p64(a: u64) -> poly64x1_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vcreate_f32(a: u64) -> float32x2_t {
transmute(a)
}
@@ -2822,7 +2822,7 @@ pub unsafe fn vcreate_f32(a: u64) -> float32x2_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vcvt))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(scvtf))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vcvt_f32_s32(a: int32x2_t) -> float32x2_t {
simd_cast(a)
}
@@ -2835,7 +2835,7 @@ pub unsafe fn vcvt_f32_s32(a: int32x2_t) -> float32x2_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vcvt))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(scvtf))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vcvtq_f32_s32(a: int32x4_t) -> float32x4_t {
simd_cast(a)
}
@@ -2848,7 +2848,7 @@ pub unsafe fn vcvtq_f32_s32(a: int32x4_t) -> float32x4_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vcvt))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ucvtf))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vcvt_f32_u32(a: uint32x2_t) -> float32x2_t {
simd_cast(a)
}
@@ -2861,7 +2861,7 @@ pub unsafe fn vcvt_f32_u32(a: uint32x2_t) -> float32x2_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vcvt))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ucvtf))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vcvtq_f32_u32(a: uint32x4_t) -> float32x4_t {
simd_cast(a)
}
@@ -3170,7 +3170,7 @@ vcvtq_n_u32_f32_(a, N)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vcvt))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(fcvtzs))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vcvt_s32_f32(a: float32x2_t) -> int32x2_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -3189,7 +3189,7 @@ vcvt_s32_f32_(a)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vcvt))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(fcvtzs))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vcvtq_s32_f32(a: float32x4_t) -> int32x4_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -3208,7 +3208,7 @@ vcvtq_s32_f32_(a)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vcvt))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(fcvtzu))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vcvt_u32_f32(a: float32x2_t) -> uint32x2_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -3227,7 +3227,7 @@ vcvt_u32_f32_(a)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vcvt))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(fcvtzu))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vcvtq_u32_f32(a: float32x4_t) -> uint32x4_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -3247,7 +3247,7 @@ vcvtq_u32_f32_(a)
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vdup.8", N = 4))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(dup, N = 4))]
#[rustc_legacy_const_generics(1)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vdup_lane_s8<const N: i32>(a: int8x8_t) -> int8x8_t {
static_assert_imm3!(N);
simd_shuffle8!(a, a, <const N: i32> [N as u32, N as u32, N as u32, N as u32, N as u32, N as u32, N as u32, N as u32])
@@ -3262,7 +3262,7 @@ pub unsafe fn vdup_lane_s8<const N: i32>(a: int8x8_t) -> int8x8_t {
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vdup.8", N = 8))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(dup, N = 8))]
#[rustc_legacy_const_generics(1)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vdupq_laneq_s8<const N: i32>(a: int8x16_t) -> int8x16_t {
static_assert_imm4!(N);
simd_shuffle16!(a, a, <const N: i32> [N as u32, N as u32, N as u32, N as u32, N as u32, N as u32, N as u32, N as u32, N as u32, N as u32, N as u32, N as u32, N as u32, N as u32, N as u32, N as u32])
@@ -3277,7 +3277,7 @@ pub unsafe fn vdupq_laneq_s8<const N: i32>(a: int8x16_t) -> int8x16_t {
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vdup.16", N = 2))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(dup, N = 2))]
#[rustc_legacy_const_generics(1)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vdup_lane_s16<const N: i32>(a: int16x4_t) -> int16x4_t {
static_assert_imm2!(N);
simd_shuffle4!(a, a, <const N: i32> [N as u32, N as u32, N as u32, N as u32])
@@ -3292,7 +3292,7 @@ pub unsafe fn vdup_lane_s16<const N: i32>(a: int16x4_t) -> int16x4_t {
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vdup.16", N = 4))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(dup, N = 4))]
#[rustc_legacy_const_generics(1)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vdupq_laneq_s16<const N: i32>(a: int16x8_t) -> int16x8_t {
static_assert_imm3!(N);
simd_shuffle8!(a, a, <const N: i32> [N as u32, N as u32, N as u32, N as u32, N as u32, N as u32, N as u32, N as u32])
@@ -3307,7 +3307,7 @@ pub unsafe fn vdupq_laneq_s16<const N: i32>(a: int16x8_t) -> int16x8_t {
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vdup.32", N = 1))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(dup, N = 1))]
#[rustc_legacy_const_generics(1)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vdup_lane_s32<const N: i32>(a: int32x2_t) -> int32x2_t {
static_assert_imm1!(N);
simd_shuffle2!(a, a, <const N: i32> [N as u32, N as u32])
@@ -3322,7 +3322,7 @@ pub unsafe fn vdup_lane_s32<const N: i32>(a: int32x2_t) -> int32x2_t {
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vdup.32", N = 2))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(dup, N = 2))]
#[rustc_legacy_const_generics(1)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vdupq_laneq_s32<const N: i32>(a: int32x4_t) -> int32x4_t {
static_assert_imm2!(N);
simd_shuffle4!(a, a, <const N: i32> [N as u32, N as u32, N as u32, N as u32])
@@ -3337,7 +3337,7 @@ pub unsafe fn vdupq_laneq_s32<const N: i32>(a: int32x4_t) -> int32x4_t {
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vdup.8", N = 8))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(dup, N = 8))]
#[rustc_legacy_const_generics(1)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vdup_laneq_s8<const N: i32>(a: int8x16_t) -> int8x8_t {
static_assert_imm4!(N);
simd_shuffle8!(a, a, <const N: i32> [N as u32, N as u32, N as u32, N as u32, N as u32, N as u32, N as u32, N as u32])
@@ -3352,7 +3352,7 @@ pub unsafe fn vdup_laneq_s8<const N: i32>(a: int8x16_t) -> int8x8_t {
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vdup.16", N = 4))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(dup, N = 4))]
#[rustc_legacy_const_generics(1)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vdup_laneq_s16<const N: i32>(a: int16x8_t) -> int16x4_t {
static_assert_imm3!(N);
simd_shuffle4!(a, a, <const N: i32> [N as u32, N as u32, N as u32, N as u32])
@@ -3367,7 +3367,7 @@ pub unsafe fn vdup_laneq_s16<const N: i32>(a: int16x8_t) -> int16x4_t {
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vdup.32", N = 2))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(dup, N = 2))]
#[rustc_legacy_const_generics(1)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vdup_laneq_s32<const N: i32>(a: int32x4_t) -> int32x2_t {
static_assert_imm2!(N);
simd_shuffle2!(a, a, <const N: i32> [N as u32, N as u32])
@@ -3382,7 +3382,7 @@ pub unsafe fn vdup_laneq_s32<const N: i32>(a: int32x4_t) -> int32x2_t {
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vdup.8", N = 4))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(dup, N = 4))]
#[rustc_legacy_const_generics(1)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vdupq_lane_s8<const N: i32>(a: int8x8_t) -> int8x16_t {
static_assert_imm3!(N);
simd_shuffle16!(a, a, <const N: i32> [N as u32, N as u32, N as u32, N as u32, N as u32, N as u32, N as u32, N as u32, N as u32, N as u32, N as u32, N as u32, N as u32, N as u32, N as u32, N as u32])
@@ -3397,7 +3397,7 @@ pub unsafe fn vdupq_lane_s8<const N: i32>(a: int8x8_t) -> int8x16_t {
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vdup.16", N = 2))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(dup, N = 2))]
#[rustc_legacy_const_generics(1)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vdupq_lane_s16<const N: i32>(a: int16x4_t) -> int16x8_t {
static_assert_imm2!(N);
simd_shuffle8!(a, a, <const N: i32> [N as u32, N as u32, N as u32, N as u32, N as u32, N as u32, N as u32, N as u32])
@@ -3412,7 +3412,7 @@ pub unsafe fn vdupq_lane_s16<const N: i32>(a: int16x4_t) -> int16x8_t {
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vdup.32", N = 1))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(dup, N = 1))]
#[rustc_legacy_const_generics(1)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vdupq_lane_s32<const N: i32>(a: int32x2_t) -> int32x4_t {
static_assert_imm1!(N);
simd_shuffle4!(a, a, <const N: i32> [N as u32, N as u32, N as u32, N as u32])
@@ -3427,7 +3427,7 @@ pub unsafe fn vdupq_lane_s32<const N: i32>(a: int32x2_t) -> int32x4_t {
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vdup.8", N = 4))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(dup, N = 4))]
#[rustc_legacy_const_generics(1)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vdup_lane_u8<const N: i32>(a: uint8x8_t) -> uint8x8_t {
static_assert_imm3!(N);
simd_shuffle8!(a, a, <const N: i32> [N as u32, N as u32, N as u32, N as u32, N as u32, N as u32, N as u32, N as u32])
@@ -3442,7 +3442,7 @@ pub unsafe fn vdup_lane_u8<const N: i32>(a: uint8x8_t) -> uint8x8_t {
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vdup.8", N = 8))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(dup, N = 8))]
#[rustc_legacy_const_generics(1)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vdupq_laneq_u8<const N: i32>(a: uint8x16_t) -> uint8x16_t {
static_assert_imm4!(N);
simd_shuffle16!(a, a, <const N: i32> [N as u32, N as u32, N as u32, N as u32, N as u32, N as u32, N as u32, N as u32, N as u32, N as u32, N as u32, N as u32, N as u32, N as u32, N as u32, N as u32])
@@ -3457,7 +3457,7 @@ pub unsafe fn vdupq_laneq_u8<const N: i32>(a: uint8x16_t) -> uint8x16_t {
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vdup.16", N = 2))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(dup, N = 2))]
#[rustc_legacy_const_generics(1)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vdup_lane_u16<const N: i32>(a: uint16x4_t) -> uint16x4_t {
static_assert_imm2!(N);
simd_shuffle4!(a, a, <const N: i32> [N as u32, N as u32, N as u32, N as u32])
@@ -3472,7 +3472,7 @@ pub unsafe fn vdup_lane_u16<const N: i32>(a: uint16x4_t) -> uint16x4_t {
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vdup.16", N = 4))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(dup, N = 4))]
#[rustc_legacy_const_generics(1)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vdupq_laneq_u16<const N: i32>(a: uint16x8_t) -> uint16x8_t {
static_assert_imm3!(N);
simd_shuffle8!(a, a, <const N: i32> [N as u32, N as u32, N as u32, N as u32, N as u32, N as u32, N as u32, N as u32])
@@ -3487,7 +3487,7 @@ pub unsafe fn vdupq_laneq_u16<const N: i32>(a: uint16x8_t) -> uint16x8_t {
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vdup.32", N = 1))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(dup, N = 1))]
#[rustc_legacy_const_generics(1)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vdup_lane_u32<const N: i32>(a: uint32x2_t) -> uint32x2_t {
static_assert_imm1!(N);
simd_shuffle2!(a, a, <const N: i32> [N as u32, N as u32])
@@ -3502,7 +3502,7 @@ pub unsafe fn vdup_lane_u32<const N: i32>(a: uint32x2_t) -> uint32x2_t {
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vdup.32", N = 2))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(dup, N = 2))]
#[rustc_legacy_const_generics(1)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vdupq_laneq_u32<const N: i32>(a: uint32x4_t) -> uint32x4_t {
static_assert_imm2!(N);
simd_shuffle4!(a, a, <const N: i32> [N as u32, N as u32, N as u32, N as u32])
@@ -3517,7 +3517,7 @@ pub unsafe fn vdupq_laneq_u32<const N: i32>(a: uint32x4_t) -> uint32x4_t {
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vdup.8", N = 8))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(dup, N = 8))]
#[rustc_legacy_const_generics(1)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vdup_laneq_u8<const N: i32>(a: uint8x16_t) -> uint8x8_t {
static_assert_imm4!(N);
simd_shuffle8!(a, a, <const N: i32> [N as u32, N as u32, N as u32, N as u32, N as u32, N as u32, N as u32, N as u32])
@@ -3532,7 +3532,7 @@ pub unsafe fn vdup_laneq_u8<const N: i32>(a: uint8x16_t) -> uint8x8_t {
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vdup.16", N = 4))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(dup, N = 4))]
#[rustc_legacy_const_generics(1)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vdup_laneq_u16<const N: i32>(a: uint16x8_t) -> uint16x4_t {
static_assert_imm3!(N);
simd_shuffle4!(a, a, <const N: i32> [N as u32, N as u32, N as u32, N as u32])
@@ -3547,7 +3547,7 @@ pub unsafe fn vdup_laneq_u16<const N: i32>(a: uint16x8_t) -> uint16x4_t {
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vdup.32", N = 2))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(dup, N = 2))]
#[rustc_legacy_const_generics(1)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vdup_laneq_u32<const N: i32>(a: uint32x4_t) -> uint32x2_t {
static_assert_imm2!(N);
simd_shuffle2!(a, a, <const N: i32> [N as u32, N as u32])
@@ -3562,7 +3562,7 @@ pub unsafe fn vdup_laneq_u32<const N: i32>(a: uint32x4_t) -> uint32x2_t {
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vdup.8", N = 4))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(dup, N = 4))]
#[rustc_legacy_const_generics(1)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vdupq_lane_u8<const N: i32>(a: uint8x8_t) -> uint8x16_t {
static_assert_imm3!(N);
simd_shuffle16!(a, a, <const N: i32> [N as u32, N as u32, N as u32, N as u32, N as u32, N as u32, N as u32, N as u32, N as u32, N as u32, N as u32, N as u32, N as u32, N as u32, N as u32, N as u32])
@@ -3577,7 +3577,7 @@ pub unsafe fn vdupq_lane_u8<const N: i32>(a: uint8x8_t) -> uint8x16_t {
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vdup.16", N = 2))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(dup, N = 2))]
#[rustc_legacy_const_generics(1)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vdupq_lane_u16<const N: i32>(a: uint16x4_t) -> uint16x8_t {
static_assert_imm2!(N);
simd_shuffle8!(a, a, <const N: i32> [N as u32, N as u32, N as u32, N as u32, N as u32, N as u32, N as u32, N as u32])
@@ -3592,7 +3592,7 @@ pub unsafe fn vdupq_lane_u16<const N: i32>(a: uint16x4_t) -> uint16x8_t {
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vdup.32", N = 1))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(dup, N = 1))]
#[rustc_legacy_const_generics(1)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vdupq_lane_u32<const N: i32>(a: uint32x2_t) -> uint32x4_t {
static_assert_imm1!(N);
simd_shuffle4!(a, a, <const N: i32> [N as u32, N as u32, N as u32, N as u32])
@@ -3607,7 +3607,7 @@ pub unsafe fn vdupq_lane_u32<const N: i32>(a: uint32x2_t) -> uint32x4_t {
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vdup.8", N = 4))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(dup, N = 4))]
#[rustc_legacy_const_generics(1)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vdup_lane_p8<const N: i32>(a: poly8x8_t) -> poly8x8_t {
static_assert_imm3!(N);
simd_shuffle8!(a, a, <const N: i32> [N as u32, N as u32, N as u32, N as u32, N as u32, N as u32, N as u32, N as u32])
@@ -3622,7 +3622,7 @@ pub unsafe fn vdup_lane_p8<const N: i32>(a: poly8x8_t) -> poly8x8_t {
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vdup.8", N = 8))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(dup, N = 8))]
#[rustc_legacy_const_generics(1)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vdupq_laneq_p8<const N: i32>(a: poly8x16_t) -> poly8x16_t {
static_assert_imm4!(N);
simd_shuffle16!(a, a, <const N: i32> [N as u32, N as u32, N as u32, N as u32, N as u32, N as u32, N as u32, N as u32, N as u32, N as u32, N as u32, N as u32, N as u32, N as u32, N as u32, N as u32])
@@ -3637,7 +3637,7 @@ pub unsafe fn vdupq_laneq_p8<const N: i32>(a: poly8x16_t) -> poly8x16_t {
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vdup.16", N = 2))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(dup, N = 2))]
#[rustc_legacy_const_generics(1)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vdup_lane_p16<const N: i32>(a: poly16x4_t) -> poly16x4_t {
static_assert_imm2!(N);
simd_shuffle4!(a, a, <const N: i32> [N as u32, N as u32, N as u32, N as u32])
@@ -3652,7 +3652,7 @@ pub unsafe fn vdup_lane_p16<const N: i32>(a: poly16x4_t) -> poly16x4_t {
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vdup.16", N = 4))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(dup, N = 4))]
#[rustc_legacy_const_generics(1)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vdupq_laneq_p16<const N: i32>(a: poly16x8_t) -> poly16x8_t {
static_assert_imm3!(N);
simd_shuffle8!(a, a, <const N: i32> [N as u32, N as u32, N as u32, N as u32, N as u32, N as u32, N as u32, N as u32])
@@ -3667,7 +3667,7 @@ pub unsafe fn vdupq_laneq_p16<const N: i32>(a: poly16x8_t) -> poly16x8_t {
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vdup.8", N = 8))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(dup, N = 8))]
#[rustc_legacy_const_generics(1)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vdup_laneq_p8<const N: i32>(a: poly8x16_t) -> poly8x8_t {
static_assert_imm4!(N);
simd_shuffle8!(a, a, <const N: i32> [N as u32, N as u32, N as u32, N as u32, N as u32, N as u32, N as u32, N as u32])
@@ -3682,7 +3682,7 @@ pub unsafe fn vdup_laneq_p8<const N: i32>(a: poly8x16_t) -> poly8x8_t {
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vdup.16", N = 4))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(dup, N = 4))]
#[rustc_legacy_const_generics(1)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vdup_laneq_p16<const N: i32>(a: poly16x8_t) -> poly16x4_t {
static_assert_imm3!(N);
simd_shuffle4!(a, a, <const N: i32> [N as u32, N as u32, N as u32, N as u32])
@@ -3697,7 +3697,7 @@ pub unsafe fn vdup_laneq_p16<const N: i32>(a: poly16x8_t) -> poly16x4_t {
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vdup.8", N = 4))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(dup, N = 4))]
#[rustc_legacy_const_generics(1)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vdupq_lane_p8<const N: i32>(a: poly8x8_t) -> poly8x16_t {
static_assert_imm3!(N);
simd_shuffle16!(a, a, <const N: i32> [N as u32, N as u32, N as u32, N as u32, N as u32, N as u32, N as u32, N as u32, N as u32, N as u32, N as u32, N as u32, N as u32, N as u32, N as u32, N as u32])
@@ -3712,7 +3712,7 @@ pub unsafe fn vdupq_lane_p8<const N: i32>(a: poly8x8_t) -> poly8x16_t {
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vdup.16", N = 2))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(dup, N = 2))]
#[rustc_legacy_const_generics(1)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vdupq_lane_p16<const N: i32>(a: poly16x4_t) -> poly16x8_t {
static_assert_imm2!(N);
simd_shuffle8!(a, a, <const N: i32> [N as u32, N as u32, N as u32, N as u32, N as u32, N as u32, N as u32, N as u32])
@@ -3727,7 +3727,7 @@ pub unsafe fn vdupq_lane_p16<const N: i32>(a: poly16x4_t) -> poly16x8_t {
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmov, N = 1))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(dup, N = 1))]
#[rustc_legacy_const_generics(1)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vdupq_laneq_s64<const N: i32>(a: int64x2_t) -> int64x2_t {
static_assert_imm1!(N);
simd_shuffle2!(a, a, <const N: i32> [N as u32, N as u32])
@@ -3742,7 +3742,7 @@ pub unsafe fn vdupq_laneq_s64<const N: i32>(a: int64x2_t) -> int64x2_t {
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmov, N = 0))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(dup, N = 0))]
#[rustc_legacy_const_generics(1)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vdupq_lane_s64<const N: i32>(a: int64x1_t) -> int64x2_t {
static_assert!(N : i32 where N == 0);
simd_shuffle2!(a, a, <const N: i32> [N as u32, N as u32])
@@ -3757,7 +3757,7 @@ pub unsafe fn vdupq_lane_s64<const N: i32>(a: int64x1_t) -> int64x2_t {
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmov, N = 1))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(dup, N = 1))]
#[rustc_legacy_const_generics(1)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vdupq_laneq_u64<const N: i32>(a: uint64x2_t) -> uint64x2_t {
static_assert_imm1!(N);
simd_shuffle2!(a, a, <const N: i32> [N as u32, N as u32])
@@ -3772,7 +3772,7 @@ pub unsafe fn vdupq_laneq_u64<const N: i32>(a: uint64x2_t) -> uint64x2_t {
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmov, N = 0))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(dup, N = 0))]
#[rustc_legacy_const_generics(1)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vdupq_lane_u64<const N: i32>(a: uint64x1_t) -> uint64x2_t {
static_assert!(N : i32 where N == 0);
simd_shuffle2!(a, a, <const N: i32> [N as u32, N as u32])
@@ -3787,7 +3787,7 @@ pub unsafe fn vdupq_lane_u64<const N: i32>(a: uint64x1_t) -> uint64x2_t {
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vdup.32", N = 1))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(dup, N = 1))]
#[rustc_legacy_const_generics(1)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vdup_lane_f32<const N: i32>(a: float32x2_t) -> float32x2_t {
static_assert_imm1!(N);
simd_shuffle2!(a, a, <const N: i32> [N as u32, N as u32])
@@ -3802,7 +3802,7 @@ pub unsafe fn vdup_lane_f32<const N: i32>(a: float32x2_t) -> float32x2_t {
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vdup.32", N = 2))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(dup, N = 2))]
#[rustc_legacy_const_generics(1)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vdupq_laneq_f32<const N: i32>(a: float32x4_t) -> float32x4_t {
static_assert_imm2!(N);
simd_shuffle4!(a, a, <const N: i32> [N as u32, N as u32, N as u32, N as u32])
@@ -3817,7 +3817,7 @@ pub unsafe fn vdupq_laneq_f32<const N: i32>(a: float32x4_t) -> float32x4_t {
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vdup.32", N = 2))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(dup, N = 2))]
#[rustc_legacy_const_generics(1)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vdup_laneq_f32<const N: i32>(a: float32x4_t) -> float32x2_t {
static_assert_imm2!(N);
simd_shuffle2!(a, a, <const N: i32> [N as u32, N as u32])
@@ -3832,7 +3832,7 @@ pub unsafe fn vdup_laneq_f32<const N: i32>(a: float32x4_t) -> float32x2_t {
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vdup.32", N = 1))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(dup, N = 1))]
#[rustc_legacy_const_generics(1)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vdupq_lane_f32<const N: i32>(a: float32x2_t) -> float32x4_t {
static_assert_imm1!(N);
simd_shuffle4!(a, a, <const N: i32> [N as u32, N as u32, N as u32, N as u32])
@@ -3847,7 +3847,7 @@ pub unsafe fn vdupq_lane_f32<const N: i32>(a: float32x2_t) -> float32x4_t {
#[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(1)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vdup_lane_s64<const N: i32>(a: int64x1_t) -> int64x1_t {
static_assert!(N : i32 where N == 0);
a
@@ -3862,7 +3862,7 @@ pub unsafe fn vdup_lane_s64<const N: i32>(a: int64x1_t) -> int64x1_t {
#[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(1)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vdup_lane_u64<const N: i32>(a: uint64x1_t) -> uint64x1_t {
static_assert!(N : i32 where N == 0);
a
@@ -3877,7 +3877,7 @@ pub unsafe fn vdup_lane_u64<const N: i32>(a: uint64x1_t) -> uint64x1_t {
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmov, N = 1))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop, N = 1))]
#[rustc_legacy_const_generics(1)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vdup_laneq_s64<const N: i32>(a: int64x2_t) -> int64x1_t {
static_assert_imm1!(N);
transmute::<i64, _>(simd_extract(a, N as u32))
@@ -3892,7 +3892,7 @@ pub unsafe fn vdup_laneq_s64<const N: i32>(a: int64x2_t) -> int64x1_t {
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmov, N = 1))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop, N = 1))]
#[rustc_legacy_const_generics(1)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vdup_laneq_u64<const N: i32>(a: uint64x2_t) -> uint64x1_t {
static_assert_imm1!(N);
transmute::<u64, _>(simd_extract(a, N as u32))
@@ -3907,7 +3907,7 @@ pub unsafe fn vdup_laneq_u64<const N: i32>(a: uint64x2_t) -> uint64x1_t {
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vext.8", N = 7))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ext, N = 7))]
#[rustc_legacy_const_generics(2)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vext_s8<const N: i32>(a: int8x8_t, b: int8x8_t) -> int8x8_t {
static_assert_imm3!(N);
match N & 0b111 {
@@ -3932,7 +3932,7 @@ pub unsafe fn vext_s8<const N: i32>(a: int8x8_t, b: int8x8_t) -> int8x8_t {
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vext.8", N = 15))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ext, N = 15))]
#[rustc_legacy_const_generics(2)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vextq_s8<const N: i32>(a: int8x16_t, b: int8x16_t) -> int8x16_t {
static_assert_imm4!(N);
match N & 0b1111 {
@@ -3965,7 +3965,7 @@ pub unsafe fn vextq_s8<const N: i32>(a: int8x16_t, b: int8x16_t) -> int8x16_t {
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vext.8", N = 3))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ext, N = 3))]
#[rustc_legacy_const_generics(2)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vext_s16<const N: i32>(a: int16x4_t, b: int16x4_t) -> int16x4_t {
static_assert_imm2!(N);
match N & 0b11 {
@@ -3986,7 +3986,7 @@ pub unsafe fn vext_s16<const N: i32>(a: int16x4_t, b: int16x4_t) -> int16x4_t {
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vext.8", N = 7))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ext, N = 7))]
#[rustc_legacy_const_generics(2)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vextq_s16<const N: i32>(a: int16x8_t, b: int16x8_t) -> int16x8_t {
static_assert_imm3!(N);
match N & 0b111 {
@@ -4011,7 +4011,7 @@ pub unsafe fn vextq_s16<const N: i32>(a: int16x8_t, b: int16x8_t) -> int16x8_t {
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vext.8", N = 1))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ext, N = 1))]
#[rustc_legacy_const_generics(2)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vext_s32<const N: i32>(a: int32x2_t, b: int32x2_t) -> int32x2_t {
static_assert_imm1!(N);
match N & 0b1 {
@@ -4030,7 +4030,7 @@ pub unsafe fn vext_s32<const N: i32>(a: int32x2_t, b: int32x2_t) -> int32x2_t {
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vext.8", N = 3))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ext, N = 3))]
#[rustc_legacy_const_generics(2)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vextq_s32<const N: i32>(a: int32x4_t, b: int32x4_t) -> int32x4_t {
static_assert_imm2!(N);
match N & 0b11 {
@@ -4051,7 +4051,7 @@ pub unsafe fn vextq_s32<const N: i32>(a: int32x4_t, b: int32x4_t) -> int32x4_t {
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vext.8", N = 7))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ext, N = 7))]
#[rustc_legacy_const_generics(2)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vext_u8<const N: i32>(a: uint8x8_t, b: uint8x8_t) -> uint8x8_t {
static_assert_imm3!(N);
match N & 0b111 {
@@ -4076,7 +4076,7 @@ pub unsafe fn vext_u8<const N: i32>(a: uint8x8_t, b: uint8x8_t) -> uint8x8_t {
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vext.8", N = 15))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ext, N = 15))]
#[rustc_legacy_const_generics(2)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vextq_u8<const N: i32>(a: uint8x16_t, b: uint8x16_t) -> uint8x16_t {
static_assert_imm4!(N);
match N & 0b1111 {
@@ -4109,7 +4109,7 @@ pub unsafe fn vextq_u8<const N: i32>(a: uint8x16_t, b: uint8x16_t) -> uint8x16_t
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vext.8", N = 3))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ext, N = 3))]
#[rustc_legacy_const_generics(2)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vext_u16<const N: i32>(a: uint16x4_t, b: uint16x4_t) -> uint16x4_t {
static_assert_imm2!(N);
match N & 0b11 {
@@ -4130,7 +4130,7 @@ pub unsafe fn vext_u16<const N: i32>(a: uint16x4_t, b: uint16x4_t) -> uint16x4_t
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vext.8", N = 7))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ext, N = 7))]
#[rustc_legacy_const_generics(2)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vextq_u16<const N: i32>(a: uint16x8_t, b: uint16x8_t) -> uint16x8_t {
static_assert_imm3!(N);
match N & 0b111 {
@@ -4155,7 +4155,7 @@ pub unsafe fn vextq_u16<const N: i32>(a: uint16x8_t, b: uint16x8_t) -> uint16x8_
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vext.8", N = 1))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ext, N = 1))]
#[rustc_legacy_const_generics(2)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vext_u32<const N: i32>(a: uint32x2_t, b: uint32x2_t) -> uint32x2_t {
static_assert_imm1!(N);
match N & 0b1 {
@@ -4174,7 +4174,7 @@ pub unsafe fn vext_u32<const N: i32>(a: uint32x2_t, b: uint32x2_t) -> uint32x2_t
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vext.8", N = 3))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ext, N = 3))]
#[rustc_legacy_const_generics(2)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vextq_u32<const N: i32>(a: uint32x4_t, b: uint32x4_t) -> uint32x4_t {
static_assert_imm2!(N);
match N & 0b11 {
@@ -4195,7 +4195,7 @@ pub unsafe fn vextq_u32<const N: i32>(a: uint32x4_t, b: uint32x4_t) -> uint32x4_
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vext.8", N = 7))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ext, N = 7))]
#[rustc_legacy_const_generics(2)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vext_p8<const N: i32>(a: poly8x8_t, b: poly8x8_t) -> poly8x8_t {
static_assert_imm3!(N);
match N & 0b111 {
@@ -4220,7 +4220,7 @@ pub unsafe fn vext_p8<const N: i32>(a: poly8x8_t, b: poly8x8_t) -> poly8x8_t {
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vext.8", N = 15))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ext, N = 15))]
#[rustc_legacy_const_generics(2)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vextq_p8<const N: i32>(a: poly8x16_t, b: poly8x16_t) -> poly8x16_t {
static_assert_imm4!(N);
match N & 0b1111 {
@@ -4253,7 +4253,7 @@ pub unsafe fn vextq_p8<const N: i32>(a: poly8x16_t, b: poly8x16_t) -> poly8x16_t
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vext.8", N = 3))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ext, N = 3))]
#[rustc_legacy_const_generics(2)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vext_p16<const N: i32>(a: poly16x4_t, b: poly16x4_t) -> poly16x4_t {
static_assert_imm2!(N);
match N & 0b11 {
@@ -4274,7 +4274,7 @@ pub unsafe fn vext_p16<const N: i32>(a: poly16x4_t, b: poly16x4_t) -> poly16x4_t
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vext.8", N = 7))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ext, N = 7))]
#[rustc_legacy_const_generics(2)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vextq_p16<const N: i32>(a: poly16x8_t, b: poly16x8_t) -> poly16x8_t {
static_assert_imm3!(N);
match N & 0b111 {
@@ -4299,7 +4299,7 @@ pub unsafe fn vextq_p16<const N: i32>(a: poly16x8_t, b: poly16x8_t) -> poly16x8_
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmov, N = 1))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ext, N = 1))]
#[rustc_legacy_const_generics(2)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vextq_s64<const N: i32>(a: int64x2_t, b: int64x2_t) -> int64x2_t {
static_assert_imm1!(N);
match N & 0b1 {
@@ -4318,7 +4318,7 @@ pub unsafe fn vextq_s64<const N: i32>(a: int64x2_t, b: int64x2_t) -> int64x2_t {
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmov, N = 1))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ext, N = 1))]
#[rustc_legacy_const_generics(2)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vextq_u64<const N: i32>(a: uint64x2_t, b: uint64x2_t) -> uint64x2_t {
static_assert_imm1!(N);
match N & 0b1 {
@@ -4337,7 +4337,7 @@ pub unsafe fn vextq_u64<const N: i32>(a: uint64x2_t, b: uint64x2_t) -> uint64x2_
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vext.8", N = 1))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ext, N = 1))]
#[rustc_legacy_const_generics(2)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vext_f32<const N: i32>(a: float32x2_t, b: float32x2_t) -> float32x2_t {
static_assert_imm1!(N);
match N & 0b1 {
@@ -4356,7 +4356,7 @@ pub unsafe fn vext_f32<const N: i32>(a: float32x2_t, b: float32x2_t) -> float32x
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vext.8", N = 3))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ext, N = 3))]
#[rustc_legacy_const_generics(2)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vextq_f32<const N: i32>(a: float32x4_t, b: float32x4_t) -> float32x4_t {
static_assert_imm2!(N);
match N & 0b11 {
@@ -4376,7 +4376,7 @@ pub unsafe fn vextq_f32<const N: i32>(a: float32x4_t, b: float32x4_t) -> float32
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmla.i8"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mla))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmla_s8(a: int8x8_t, b: int8x8_t, c: int8x8_t) -> int8x8_t {
simd_add(a, simd_mul(b, c))
}
@@ -4389,7 +4389,7 @@ pub unsafe fn vmla_s8(a: int8x8_t, b: int8x8_t, c: int8x8_t) -> int8x8_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmla.i8"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mla))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmlaq_s8(a: int8x16_t, b: int8x16_t, c: int8x16_t) -> int8x16_t {
simd_add(a, simd_mul(b, c))
}
@@ -4402,7 +4402,7 @@ pub unsafe fn vmlaq_s8(a: int8x16_t, b: int8x16_t, c: int8x16_t) -> int8x16_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmla.i16"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mla))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmla_s16(a: int16x4_t, b: int16x4_t, c: int16x4_t) -> int16x4_t {
simd_add(a, simd_mul(b, c))
}
@@ -4415,7 +4415,7 @@ pub unsafe fn vmla_s16(a: int16x4_t, b: int16x4_t, c: int16x4_t) -> int16x4_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmla.i16"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mla))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmlaq_s16(a: int16x8_t, b: int16x8_t, c: int16x8_t) -> int16x8_t {
simd_add(a, simd_mul(b, c))
}
@@ -4428,7 +4428,7 @@ pub unsafe fn vmlaq_s16(a: int16x8_t, b: int16x8_t, c: int16x8_t) -> int16x8_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmla.i32"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mla))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmla_s32(a: int32x2_t, b: int32x2_t, c: int32x2_t) -> int32x2_t {
simd_add(a, simd_mul(b, c))
}
@@ -4441,7 +4441,7 @@ pub unsafe fn vmla_s32(a: int32x2_t, b: int32x2_t, c: int32x2_t) -> int32x2_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmla.i32"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mla))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmlaq_s32(a: int32x4_t, b: int32x4_t, c: int32x4_t) -> int32x4_t {
simd_add(a, simd_mul(b, c))
}
@@ -4454,7 +4454,7 @@ pub unsafe fn vmlaq_s32(a: int32x4_t, b: int32x4_t, c: int32x4_t) -> int32x4_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmla.i8"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mla))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmla_u8(a: uint8x8_t, b: uint8x8_t, c: uint8x8_t) -> uint8x8_t {
simd_add(a, simd_mul(b, c))
}
@@ -4467,7 +4467,7 @@ pub unsafe fn vmla_u8(a: uint8x8_t, b: uint8x8_t, c: uint8x8_t) -> uint8x8_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmla.i8"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mla))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmlaq_u8(a: uint8x16_t, b: uint8x16_t, c: uint8x16_t) -> uint8x16_t {
simd_add(a, simd_mul(b, c))
}
@@ -4480,7 +4480,7 @@ pub unsafe fn vmlaq_u8(a: uint8x16_t, b: uint8x16_t, c: uint8x16_t) -> uint8x16_
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmla.i16"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mla))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmla_u16(a: uint16x4_t, b: uint16x4_t, c: uint16x4_t) -> uint16x4_t {
simd_add(a, simd_mul(b, c))
}
@@ -4493,7 +4493,7 @@ pub unsafe fn vmla_u16(a: uint16x4_t, b: uint16x4_t, c: uint16x4_t) -> uint16x4_
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmla.i16"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mla))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmlaq_u16(a: uint16x8_t, b: uint16x8_t, c: uint16x8_t) -> uint16x8_t {
simd_add(a, simd_mul(b, c))
}
@@ -4506,7 +4506,7 @@ pub unsafe fn vmlaq_u16(a: uint16x8_t, b: uint16x8_t, c: uint16x8_t) -> uint16x8
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmla.i32"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mla))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmla_u32(a: uint32x2_t, b: uint32x2_t, c: uint32x2_t) -> uint32x2_t {
simd_add(a, simd_mul(b, c))
}
@@ -4519,7 +4519,7 @@ pub unsafe fn vmla_u32(a: uint32x2_t, b: uint32x2_t, c: uint32x2_t) -> uint32x2_
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmla.i32"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mla))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmlaq_u32(a: uint32x4_t, b: uint32x4_t, c: uint32x4_t) -> uint32x4_t {
simd_add(a, simd_mul(b, c))
}
@@ -4532,7 +4532,7 @@ pub unsafe fn vmlaq_u32(a: uint32x4_t, b: uint32x4_t, c: uint32x4_t) -> uint32x4
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmla.f32"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(fmul))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmla_f32(a: float32x2_t, b: float32x2_t, c: float32x2_t) -> float32x2_t {
simd_add(a, simd_mul(b, c))
}
@@ -4545,7 +4545,7 @@ pub unsafe fn vmla_f32(a: float32x2_t, b: float32x2_t, c: float32x2_t) -> float3
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmla.f32"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(fmul))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmlaq_f32(a: float32x4_t, b: float32x4_t, c: float32x4_t) -> float32x4_t {
simd_add(a, simd_mul(b, c))
}
@@ -4558,7 +4558,7 @@ pub unsafe fn vmlaq_f32(a: float32x4_t, b: float32x4_t, c: float32x4_t) -> float
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmla.i16"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mla))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmla_n_s16(a: int16x4_t, b: int16x4_t, c: i16) -> int16x4_t {
vmla_s16(a, b, vdup_n_s16(c))
}
@@ -4571,7 +4571,7 @@ pub unsafe fn vmla_n_s16(a: int16x4_t, b: int16x4_t, c: i16) -> int16x4_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmla.i16"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mla))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmlaq_n_s16(a: int16x8_t, b: int16x8_t, c: i16) -> int16x8_t {
vmlaq_s16(a, b, vdupq_n_s16(c))
}
@@ -4584,7 +4584,7 @@ pub unsafe fn vmlaq_n_s16(a: int16x8_t, b: int16x8_t, c: i16) -> int16x8_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmla.i32"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mla))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmla_n_s32(a: int32x2_t, b: int32x2_t, c: i32) -> int32x2_t {
vmla_s32(a, b, vdup_n_s32(c))
}
@@ -4597,7 +4597,7 @@ pub unsafe fn vmla_n_s32(a: int32x2_t, b: int32x2_t, c: i32) -> int32x2_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmla.i32"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mla))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmlaq_n_s32(a: int32x4_t, b: int32x4_t, c: i32) -> int32x4_t {
vmlaq_s32(a, b, vdupq_n_s32(c))
}
@@ -4610,7 +4610,7 @@ pub unsafe fn vmlaq_n_s32(a: int32x4_t, b: int32x4_t, c: i32) -> int32x4_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmla.i16"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mla))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmla_n_u16(a: uint16x4_t, b: uint16x4_t, c: u16) -> uint16x4_t {
vmla_u16(a, b, vdup_n_u16(c))
}
@@ -4623,7 +4623,7 @@ pub unsafe fn vmla_n_u16(a: uint16x4_t, b: uint16x4_t, c: u16) -> uint16x4_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmla.i16"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mla))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmlaq_n_u16(a: uint16x8_t, b: uint16x8_t, c: u16) -> uint16x8_t {
vmlaq_u16(a, b, vdupq_n_u16(c))
}
@@ -4636,7 +4636,7 @@ pub unsafe fn vmlaq_n_u16(a: uint16x8_t, b: uint16x8_t, c: u16) -> uint16x8_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmla.i32"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mla))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmla_n_u32(a: uint32x2_t, b: uint32x2_t, c: u32) -> uint32x2_t {
vmla_u32(a, b, vdup_n_u32(c))
}
@@ -4649,7 +4649,7 @@ pub unsafe fn vmla_n_u32(a: uint32x2_t, b: uint32x2_t, c: u32) -> uint32x2_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmla.i32"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mla))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmlaq_n_u32(a: uint32x4_t, b: uint32x4_t, c: u32) -> uint32x4_t {
vmlaq_u32(a, b, vdupq_n_u32(c))
}
@@ -4662,7 +4662,7 @@ pub unsafe fn vmlaq_n_u32(a: uint32x4_t, b: uint32x4_t, c: u32) -> uint32x4_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmla.f32"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(fmul))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmla_n_f32(a: float32x2_t, b: float32x2_t, c: f32) -> float32x2_t {
vmla_f32(a, b, vdup_n_f32(c))
}
@@ -4675,7 +4675,7 @@ pub unsafe fn vmla_n_f32(a: float32x2_t, b: float32x2_t, c: f32) -> float32x2_t
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmla.f32"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(fmul))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmlaq_n_f32(a: float32x4_t, b: float32x4_t, c: f32) -> float32x4_t {
vmlaq_f32(a, b, vdupq_n_f32(c))
}
@@ -4689,7 +4689,7 @@ pub unsafe fn vmlaq_n_f32(a: float32x4_t, b: float32x4_t, c: f32) -> float32x4_t
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmla.i16", LANE = 1))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mla, LANE = 1))]
#[rustc_legacy_const_generics(3)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmla_lane_s16<const LANE: i32>(a: int16x4_t, b: int16x4_t, c: int16x4_t) -> int16x4_t {
static_assert_imm2!(LANE);
vmla_s16(a, b, simd_shuffle4!(c, c, <const LANE: i32> [LANE as u32, LANE as u32, LANE as u32, LANE as u32]))
@@ -4704,7 +4704,7 @@ pub unsafe fn vmla_lane_s16<const LANE: i32>(a: int16x4_t, b: int16x4_t, c: int1
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmla.i16", LANE = 1))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mla, LANE = 1))]
#[rustc_legacy_const_generics(3)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmla_laneq_s16<const LANE: i32>(a: int16x4_t, b: int16x4_t, c: int16x8_t) -> int16x4_t {
static_assert_imm3!(LANE);
vmla_s16(a, b, simd_shuffle4!(c, c, <const LANE: i32> [LANE as u32, LANE as u32, LANE as u32, LANE as u32]))
@@ -4719,7 +4719,7 @@ pub unsafe fn vmla_laneq_s16<const LANE: i32>(a: int16x4_t, b: int16x4_t, c: int
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmla.i16", LANE = 1))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mla, LANE = 1))]
#[rustc_legacy_const_generics(3)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmlaq_lane_s16<const LANE: i32>(a: int16x8_t, b: int16x8_t, c: int16x4_t) -> int16x8_t {
static_assert_imm2!(LANE);
vmlaq_s16(a, b, simd_shuffle8!(c, c, <const LANE: i32> [LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32]))
@@ -4734,7 +4734,7 @@ pub unsafe fn vmlaq_lane_s16<const LANE: i32>(a: int16x8_t, b: int16x8_t, c: int
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmla.i16", LANE = 1))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mla, LANE = 1))]
#[rustc_legacy_const_generics(3)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmlaq_laneq_s16<const LANE: i32>(a: int16x8_t, b: int16x8_t, c: int16x8_t) -> int16x8_t {
static_assert_imm3!(LANE);
vmlaq_s16(a, b, simd_shuffle8!(c, c, <const LANE: i32> [LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32]))
@@ -4749,7 +4749,7 @@ pub unsafe fn vmlaq_laneq_s16<const LANE: i32>(a: int16x8_t, b: int16x8_t, c: in
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmla.i32", LANE = 1))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mla, LANE = 1))]
#[rustc_legacy_const_generics(3)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmla_lane_s32<const LANE: i32>(a: int32x2_t, b: int32x2_t, c: int32x2_t) -> int32x2_t {
static_assert_imm1!(LANE);
vmla_s32(a, b, simd_shuffle2!(c, c, <const LANE: i32> [LANE as u32, LANE as u32]))
@@ -4764,7 +4764,7 @@ pub unsafe fn vmla_lane_s32<const LANE: i32>(a: int32x2_t, b: int32x2_t, c: int3
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmla.i32", LANE = 1))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mla, LANE = 1))]
#[rustc_legacy_const_generics(3)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmla_laneq_s32<const LANE: i32>(a: int32x2_t, b: int32x2_t, c: int32x4_t) -> int32x2_t {
static_assert_imm2!(LANE);
vmla_s32(a, b, simd_shuffle2!(c, c, <const LANE: i32> [LANE as u32, LANE as u32]))
@@ -4779,7 +4779,7 @@ pub unsafe fn vmla_laneq_s32<const LANE: i32>(a: int32x2_t, b: int32x2_t, c: int
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmla.i32", LANE = 1))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mla, LANE = 1))]
#[rustc_legacy_const_generics(3)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmlaq_lane_s32<const LANE: i32>(a: int32x4_t, b: int32x4_t, c: int32x2_t) -> int32x4_t {
static_assert_imm1!(LANE);
vmlaq_s32(a, b, simd_shuffle4!(c, c, <const LANE: i32> [LANE as u32, LANE as u32, LANE as u32, LANE as u32]))
@@ -4794,7 +4794,7 @@ pub unsafe fn vmlaq_lane_s32<const LANE: i32>(a: int32x4_t, b: int32x4_t, c: int
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmla.i32", LANE = 1))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mla, LANE = 1))]
#[rustc_legacy_const_generics(3)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmlaq_laneq_s32<const LANE: i32>(a: int32x4_t, b: int32x4_t, c: int32x4_t) -> int32x4_t {
static_assert_imm2!(LANE);
vmlaq_s32(a, b, simd_shuffle4!(c, c, <const LANE: i32> [LANE as u32, LANE as u32, LANE as u32, LANE as u32]))
@@ -4809,7 +4809,7 @@ pub unsafe fn vmlaq_laneq_s32<const LANE: i32>(a: int32x4_t, b: int32x4_t, c: in
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmla.i16", LANE = 1))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mla, LANE = 1))]
#[rustc_legacy_const_generics(3)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmla_lane_u16<const LANE: i32>(a: uint16x4_t, b: uint16x4_t, c: uint16x4_t) -> uint16x4_t {
static_assert_imm2!(LANE);
vmla_u16(a, b, simd_shuffle4!(c, c, <const LANE: i32> [LANE as u32, LANE as u32, LANE as u32, LANE as u32]))
@@ -4824,7 +4824,7 @@ pub unsafe fn vmla_lane_u16<const LANE: i32>(a: uint16x4_t, b: uint16x4_t, c: ui
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmla.i16", LANE = 1))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mla, LANE = 1))]
#[rustc_legacy_const_generics(3)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmla_laneq_u16<const LANE: i32>(a: uint16x4_t, b: uint16x4_t, c: uint16x8_t) -> uint16x4_t {
static_assert_imm3!(LANE);
vmla_u16(a, b, simd_shuffle4!(c, c, <const LANE: i32> [LANE as u32, LANE as u32, LANE as u32, LANE as u32]))
@@ -4839,7 +4839,7 @@ pub unsafe fn vmla_laneq_u16<const LANE: i32>(a: uint16x4_t, b: uint16x4_t, c: u
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmla.i16", LANE = 1))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mla, LANE = 1))]
#[rustc_legacy_const_generics(3)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmlaq_lane_u16<const LANE: i32>(a: uint16x8_t, b: uint16x8_t, c: uint16x4_t) -> uint16x8_t {
static_assert_imm2!(LANE);
vmlaq_u16(a, b, simd_shuffle8!(c, c, <const LANE: i32> [LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32]))
@@ -4854,7 +4854,7 @@ pub unsafe fn vmlaq_lane_u16<const LANE: i32>(a: uint16x8_t, b: uint16x8_t, c: u
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmla.i16", LANE = 1))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mla, LANE = 1))]
#[rustc_legacy_const_generics(3)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmlaq_laneq_u16<const LANE: i32>(a: uint16x8_t, b: uint16x8_t, c: uint16x8_t) -> uint16x8_t {
static_assert_imm3!(LANE);
vmlaq_u16(a, b, simd_shuffle8!(c, c, <const LANE: i32> [LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32]))
@@ -4869,7 +4869,7 @@ pub unsafe fn vmlaq_laneq_u16<const LANE: i32>(a: uint16x8_t, b: uint16x8_t, c:
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmla.i32", LANE = 1))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mla, LANE = 1))]
#[rustc_legacy_const_generics(3)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmla_lane_u32<const LANE: i32>(a: uint32x2_t, b: uint32x2_t, c: uint32x2_t) -> uint32x2_t {
static_assert_imm1!(LANE);
vmla_u32(a, b, simd_shuffle2!(c, c, <const LANE: i32> [LANE as u32, LANE as u32]))
@@ -4884,7 +4884,7 @@ pub unsafe fn vmla_lane_u32<const LANE: i32>(a: uint32x2_t, b: uint32x2_t, c: ui
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmla.i32", LANE = 1))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mla, LANE = 1))]
#[rustc_legacy_const_generics(3)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmla_laneq_u32<const LANE: i32>(a: uint32x2_t, b: uint32x2_t, c: uint32x4_t) -> uint32x2_t {
static_assert_imm2!(LANE);
vmla_u32(a, b, simd_shuffle2!(c, c, <const LANE: i32> [LANE as u32, LANE as u32]))
@@ -4899,7 +4899,7 @@ pub unsafe fn vmla_laneq_u32<const LANE: i32>(a: uint32x2_t, b: uint32x2_t, c: u
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmla.i32", LANE = 1))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mla, LANE = 1))]
#[rustc_legacy_const_generics(3)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmlaq_lane_u32<const LANE: i32>(a: uint32x4_t, b: uint32x4_t, c: uint32x2_t) -> uint32x4_t {
static_assert_imm1!(LANE);
vmlaq_u32(a, b, simd_shuffle4!(c, c, <const LANE: i32> [LANE as u32, LANE as u32, LANE as u32, LANE as u32]))
@@ -4914,7 +4914,7 @@ pub unsafe fn vmlaq_lane_u32<const LANE: i32>(a: uint32x4_t, b: uint32x4_t, c: u
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmla.i32", LANE = 1))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mla, LANE = 1))]
#[rustc_legacy_const_generics(3)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmlaq_laneq_u32<const LANE: i32>(a: uint32x4_t, b: uint32x4_t, c: uint32x4_t) -> uint32x4_t {
static_assert_imm2!(LANE);
vmlaq_u32(a, b, simd_shuffle4!(c, c, <const LANE: i32> [LANE as u32, LANE as u32, LANE as u32, LANE as u32]))
@@ -4929,7 +4929,7 @@ pub unsafe fn vmlaq_laneq_u32<const LANE: i32>(a: uint32x4_t, b: uint32x4_t, c:
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmla.f32", LANE = 1))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(fmul, LANE = 1))]
#[rustc_legacy_const_generics(3)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmla_lane_f32<const LANE: i32>(a: float32x2_t, b: float32x2_t, c: float32x2_t) -> float32x2_t {
static_assert_imm1!(LANE);
vmla_f32(a, b, simd_shuffle2!(c, c, <const LANE: i32> [LANE as u32, LANE as u32]))
@@ -4944,7 +4944,7 @@ pub unsafe fn vmla_lane_f32<const LANE: i32>(a: float32x2_t, b: float32x2_t, c:
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmla.f32", LANE = 1))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(fmul, LANE = 1))]
#[rustc_legacy_const_generics(3)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmla_laneq_f32<const LANE: i32>(a: float32x2_t, b: float32x2_t, c: float32x4_t) -> float32x2_t {
static_assert_imm2!(LANE);
vmla_f32(a, b, simd_shuffle2!(c, c, <const LANE: i32> [LANE as u32, LANE as u32]))
@@ -4959,7 +4959,7 @@ pub unsafe fn vmla_laneq_f32<const LANE: i32>(a: float32x2_t, b: float32x2_t, c:
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmla.f32", LANE = 1))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(fmul, LANE = 1))]
#[rustc_legacy_const_generics(3)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmlaq_lane_f32<const LANE: i32>(a: float32x4_t, b: float32x4_t, c: float32x2_t) -> float32x4_t {
static_assert_imm1!(LANE);
vmlaq_f32(a, b, simd_shuffle4!(c, c, <const LANE: i32> [LANE as u32, LANE as u32, LANE as u32, LANE as u32]))
@@ -4974,7 +4974,7 @@ pub unsafe fn vmlaq_lane_f32<const LANE: i32>(a: float32x4_t, b: float32x4_t, c:
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmla.f32", LANE = 1))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(fmul, LANE = 1))]
#[rustc_legacy_const_generics(3)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmlaq_laneq_f32<const LANE: i32>(a: float32x4_t, b: float32x4_t, c: float32x4_t) -> float32x4_t {
static_assert_imm2!(LANE);
vmlaq_f32(a, b, simd_shuffle4!(c, c, <const LANE: i32> [LANE as u32, LANE as u32, LANE as u32, LANE as u32]))
@@ -4988,7 +4988,7 @@ pub unsafe fn vmlaq_laneq_f32<const LANE: i32>(a: float32x4_t, b: float32x4_t, c
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmlal.s8"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(smlal))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmlal_s8(a: int16x8_t, b: int8x8_t, c: int8x8_t) -> int16x8_t {
simd_add(a, vmull_s8(b, c))
}
@@ -5001,7 +5001,7 @@ pub unsafe fn vmlal_s8(a: int16x8_t, b: int8x8_t, c: int8x8_t) -> int16x8_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmlal.s16"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(smlal))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmlal_s16(a: int32x4_t, b: int16x4_t, c: int16x4_t) -> int32x4_t {
simd_add(a, vmull_s16(b, c))
}
@@ -5014,7 +5014,7 @@ pub unsafe fn vmlal_s16(a: int32x4_t, b: int16x4_t, c: int16x4_t) -> int32x4_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmlal.s32"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(smlal))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmlal_s32(a: int64x2_t, b: int32x2_t, c: int32x2_t) -> int64x2_t {
simd_add(a, vmull_s32(b, c))
}
@@ -5027,7 +5027,7 @@ pub unsafe fn vmlal_s32(a: int64x2_t, b: int32x2_t, c: int32x2_t) -> int64x2_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmlal.u8"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(umlal))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmlal_u8(a: uint16x8_t, b: uint8x8_t, c: uint8x8_t) -> uint16x8_t {
simd_add(a, vmull_u8(b, c))
}
@@ -5040,7 +5040,7 @@ pub unsafe fn vmlal_u8(a: uint16x8_t, b: uint8x8_t, c: uint8x8_t) -> uint16x8_t
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmlal.u16"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(umlal))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmlal_u16(a: uint32x4_t, b: uint16x4_t, c: uint16x4_t) -> uint32x4_t {
simd_add(a, vmull_u16(b, c))
}
@@ -5053,7 +5053,7 @@ pub unsafe fn vmlal_u16(a: uint32x4_t, b: uint16x4_t, c: uint16x4_t) -> uint32x4
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmlal.u32"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(umlal))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmlal_u32(a: uint64x2_t, b: uint32x2_t, c: uint32x2_t) -> uint64x2_t {
simd_add(a, vmull_u32(b, c))
}
@@ -5066,7 +5066,7 @@ pub unsafe fn vmlal_u32(a: uint64x2_t, b: uint32x2_t, c: uint32x2_t) -> uint64x2
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmlal.s16"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(smlal))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmlal_n_s16(a: int32x4_t, b: int16x4_t, c: i16) -> int32x4_t {
vmlal_s16(a, b, vdup_n_s16(c))
}
@@ -5079,7 +5079,7 @@ pub unsafe fn vmlal_n_s16(a: int32x4_t, b: int16x4_t, c: i16) -> int32x4_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmlal.s32"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(smlal))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmlal_n_s32(a: int64x2_t, b: int32x2_t, c: i32) -> int64x2_t {
vmlal_s32(a, b, vdup_n_s32(c))
}
@@ -5092,7 +5092,7 @@ pub unsafe fn vmlal_n_s32(a: int64x2_t, b: int32x2_t, c: i32) -> int64x2_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmlal.u16"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(umlal))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmlal_n_u16(a: uint32x4_t, b: uint16x4_t, c: u16) -> uint32x4_t {
vmlal_u16(a, b, vdup_n_u16(c))
}
@@ -5105,7 +5105,7 @@ pub unsafe fn vmlal_n_u16(a: uint32x4_t, b: uint16x4_t, c: u16) -> uint32x4_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmlal.u32"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(umlal))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmlal_n_u32(a: uint64x2_t, b: uint32x2_t, c: u32) -> uint64x2_t {
vmlal_u32(a, b, vdup_n_u32(c))
}
@@ -5119,7 +5119,7 @@ pub unsafe fn vmlal_n_u32(a: uint64x2_t, b: uint32x2_t, c: u32) -> uint64x2_t {
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmlal.s16", LANE = 1))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(smlal, LANE = 1))]
#[rustc_legacy_const_generics(3)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmlal_lane_s16<const LANE: i32>(a: int32x4_t, b: int16x4_t, c: int16x4_t) -> int32x4_t {
static_assert_imm2!(LANE);
vmlal_s16(a, b, simd_shuffle4!(c, c, <const LANE: i32> [LANE as u32, LANE as u32, LANE as u32, LANE as u32]))
@@ -5134,7 +5134,7 @@ pub unsafe fn vmlal_lane_s16<const LANE: i32>(a: int32x4_t, b: int16x4_t, c: int
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmlal.s16", LANE = 1))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(smlal, LANE = 1))]
#[rustc_legacy_const_generics(3)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmlal_laneq_s16<const LANE: i32>(a: int32x4_t, b: int16x4_t, c: int16x8_t) -> int32x4_t {
static_assert_imm3!(LANE);
vmlal_s16(a, b, simd_shuffle4!(c, c, <const LANE: i32> [LANE as u32, LANE as u32, LANE as u32, LANE as u32]))
@@ -5149,7 +5149,7 @@ pub unsafe fn vmlal_laneq_s16<const LANE: i32>(a: int32x4_t, b: int16x4_t, c: in
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmlal.s32", LANE = 1))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(smlal, LANE = 1))]
#[rustc_legacy_const_generics(3)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmlal_lane_s32<const LANE: i32>(a: int64x2_t, b: int32x2_t, c: int32x2_t) -> int64x2_t {
static_assert_imm1!(LANE);
vmlal_s32(a, b, simd_shuffle2!(c, c, <const LANE: i32> [LANE as u32, LANE as u32]))
@@ -5164,7 +5164,7 @@ pub unsafe fn vmlal_lane_s32<const LANE: i32>(a: int64x2_t, b: int32x2_t, c: int
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmlal.s32", LANE = 1))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(smlal, LANE = 1))]
#[rustc_legacy_const_generics(3)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmlal_laneq_s32<const LANE: i32>(a: int64x2_t, b: int32x2_t, c: int32x4_t) -> int64x2_t {
static_assert_imm2!(LANE);
vmlal_s32(a, b, simd_shuffle2!(c, c, <const LANE: i32> [LANE as u32, LANE as u32]))
@@ -5179,7 +5179,7 @@ pub unsafe fn vmlal_laneq_s32<const LANE: i32>(a: int64x2_t, b: int32x2_t, c: in
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmlal.u16", LANE = 1))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(umlal, LANE = 1))]
#[rustc_legacy_const_generics(3)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmlal_lane_u16<const LANE: i32>(a: uint32x4_t, b: uint16x4_t, c: uint16x4_t) -> uint32x4_t {
static_assert_imm2!(LANE);
vmlal_u16(a, b, simd_shuffle4!(c, c, <const LANE: i32> [LANE as u32, LANE as u32, LANE as u32, LANE as u32]))
@@ -5194,7 +5194,7 @@ pub unsafe fn vmlal_lane_u16<const LANE: i32>(a: uint32x4_t, b: uint16x4_t, c: u
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmlal.u16", LANE = 1))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(umlal, LANE = 1))]
#[rustc_legacy_const_generics(3)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmlal_laneq_u16<const LANE: i32>(a: uint32x4_t, b: uint16x4_t, c: uint16x8_t) -> uint32x4_t {
static_assert_imm3!(LANE);
vmlal_u16(a, b, simd_shuffle4!(c, c, <const LANE: i32> [LANE as u32, LANE as u32, LANE as u32, LANE as u32]))
@@ -5209,7 +5209,7 @@ pub unsafe fn vmlal_laneq_u16<const LANE: i32>(a: uint32x4_t, b: uint16x4_t, c:
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmlal.u32", LANE = 1))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(umlal, LANE = 1))]
#[rustc_legacy_const_generics(3)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmlal_lane_u32<const LANE: i32>(a: uint64x2_t, b: uint32x2_t, c: uint32x2_t) -> uint64x2_t {
static_assert_imm1!(LANE);
vmlal_u32(a, b, simd_shuffle2!(c, c, <const LANE: i32> [LANE as u32, LANE as u32]))
@@ -5224,7 +5224,7 @@ pub unsafe fn vmlal_lane_u32<const LANE: i32>(a: uint64x2_t, b: uint32x2_t, c: u
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmlal.u32", LANE = 1))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(umlal, LANE = 1))]
#[rustc_legacy_const_generics(3)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmlal_laneq_u32<const LANE: i32>(a: uint64x2_t, b: uint32x2_t, c: uint32x4_t) -> uint64x2_t {
static_assert_imm2!(LANE);
vmlal_u32(a, b, simd_shuffle2!(c, c, <const LANE: i32> [LANE as u32, LANE as u32]))
@@ -5238,7 +5238,7 @@ pub unsafe fn vmlal_laneq_u32<const LANE: i32>(a: uint64x2_t, b: uint32x2_t, c:
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmls.i8"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mls))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmls_s8(a: int8x8_t, b: int8x8_t, c: int8x8_t) -> int8x8_t {
simd_sub(a, simd_mul(b, c))
}
@@ -5251,7 +5251,7 @@ pub unsafe fn vmls_s8(a: int8x8_t, b: int8x8_t, c: int8x8_t) -> int8x8_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmls.i8"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mls))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmlsq_s8(a: int8x16_t, b: int8x16_t, c: int8x16_t) -> int8x16_t {
simd_sub(a, simd_mul(b, c))
}
@@ -5264,7 +5264,7 @@ pub unsafe fn vmlsq_s8(a: int8x16_t, b: int8x16_t, c: int8x16_t) -> int8x16_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmls.i16"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mls))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmls_s16(a: int16x4_t, b: int16x4_t, c: int16x4_t) -> int16x4_t {
simd_sub(a, simd_mul(b, c))
}
@@ -5277,7 +5277,7 @@ pub unsafe fn vmls_s16(a: int16x4_t, b: int16x4_t, c: int16x4_t) -> int16x4_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmls.i16"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mls))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmlsq_s16(a: int16x8_t, b: int16x8_t, c: int16x8_t) -> int16x8_t {
simd_sub(a, simd_mul(b, c))
}
@@ -5290,7 +5290,7 @@ pub unsafe fn vmlsq_s16(a: int16x8_t, b: int16x8_t, c: int16x8_t) -> int16x8_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmls.i32"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mls))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmls_s32(a: int32x2_t, b: int32x2_t, c: int32x2_t) -> int32x2_t {
simd_sub(a, simd_mul(b, c))
}
@@ -5303,7 +5303,7 @@ pub unsafe fn vmls_s32(a: int32x2_t, b: int32x2_t, c: int32x2_t) -> int32x2_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmls.i32"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mls))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmlsq_s32(a: int32x4_t, b: int32x4_t, c: int32x4_t) -> int32x4_t {
simd_sub(a, simd_mul(b, c))
}
@@ -5316,7 +5316,7 @@ pub unsafe fn vmlsq_s32(a: int32x4_t, b: int32x4_t, c: int32x4_t) -> int32x4_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmls.i8"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mls))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmls_u8(a: uint8x8_t, b: uint8x8_t, c: uint8x8_t) -> uint8x8_t {
simd_sub(a, simd_mul(b, c))
}
@@ -5329,7 +5329,7 @@ pub unsafe fn vmls_u8(a: uint8x8_t, b: uint8x8_t, c: uint8x8_t) -> uint8x8_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmls.i8"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mls))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmlsq_u8(a: uint8x16_t, b: uint8x16_t, c: uint8x16_t) -> uint8x16_t {
simd_sub(a, simd_mul(b, c))
}
@@ -5342,7 +5342,7 @@ pub unsafe fn vmlsq_u8(a: uint8x16_t, b: uint8x16_t, c: uint8x16_t) -> uint8x16_
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmls.i16"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mls))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmls_u16(a: uint16x4_t, b: uint16x4_t, c: uint16x4_t) -> uint16x4_t {
simd_sub(a, simd_mul(b, c))
}
@@ -5355,7 +5355,7 @@ pub unsafe fn vmls_u16(a: uint16x4_t, b: uint16x4_t, c: uint16x4_t) -> uint16x4_
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmls.i16"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mls))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmlsq_u16(a: uint16x8_t, b: uint16x8_t, c: uint16x8_t) -> uint16x8_t {
simd_sub(a, simd_mul(b, c))
}
@@ -5368,7 +5368,7 @@ pub unsafe fn vmlsq_u16(a: uint16x8_t, b: uint16x8_t, c: uint16x8_t) -> uint16x8
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmls.i32"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mls))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmls_u32(a: uint32x2_t, b: uint32x2_t, c: uint32x2_t) -> uint32x2_t {
simd_sub(a, simd_mul(b, c))
}
@@ -5381,7 +5381,7 @@ pub unsafe fn vmls_u32(a: uint32x2_t, b: uint32x2_t, c: uint32x2_t) -> uint32x2_
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmls.i32"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mls))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmlsq_u32(a: uint32x4_t, b: uint32x4_t, c: uint32x4_t) -> uint32x4_t {
simd_sub(a, simd_mul(b, c))
}
@@ -5394,7 +5394,7 @@ pub unsafe fn vmlsq_u32(a: uint32x4_t, b: uint32x4_t, c: uint32x4_t) -> uint32x4
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmls.f32"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(fmul))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmls_f32(a: float32x2_t, b: float32x2_t, c: float32x2_t) -> float32x2_t {
simd_sub(a, simd_mul(b, c))
}
@@ -5407,7 +5407,7 @@ pub unsafe fn vmls_f32(a: float32x2_t, b: float32x2_t, c: float32x2_t) -> float3
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmls.f32"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(fmul))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmlsq_f32(a: float32x4_t, b: float32x4_t, c: float32x4_t) -> float32x4_t {
simd_sub(a, simd_mul(b, c))
}
@@ -5420,7 +5420,7 @@ pub unsafe fn vmlsq_f32(a: float32x4_t, b: float32x4_t, c: float32x4_t) -> float
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmls.i16"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mls))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmls_n_s16(a: int16x4_t, b: int16x4_t, c: i16) -> int16x4_t {
vmls_s16(a, b, vdup_n_s16(c))
}
@@ -5433,7 +5433,7 @@ pub unsafe fn vmls_n_s16(a: int16x4_t, b: int16x4_t, c: i16) -> int16x4_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmls.i16"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mls))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmlsq_n_s16(a: int16x8_t, b: int16x8_t, c: i16) -> int16x8_t {
vmlsq_s16(a, b, vdupq_n_s16(c))
}
@@ -5446,7 +5446,7 @@ pub unsafe fn vmlsq_n_s16(a: int16x8_t, b: int16x8_t, c: i16) -> int16x8_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmls.i32"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mls))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmls_n_s32(a: int32x2_t, b: int32x2_t, c: i32) -> int32x2_t {
vmls_s32(a, b, vdup_n_s32(c))
}
@@ -5459,7 +5459,7 @@ pub unsafe fn vmls_n_s32(a: int32x2_t, b: int32x2_t, c: i32) -> int32x2_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmls.i32"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mls))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmlsq_n_s32(a: int32x4_t, b: int32x4_t, c: i32) -> int32x4_t {
vmlsq_s32(a, b, vdupq_n_s32(c))
}
@@ -5472,7 +5472,7 @@ pub unsafe fn vmlsq_n_s32(a: int32x4_t, b: int32x4_t, c: i32) -> int32x4_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmls.i16"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mls))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmls_n_u16(a: uint16x4_t, b: uint16x4_t, c: u16) -> uint16x4_t {
vmls_u16(a, b, vdup_n_u16(c))
}
@@ -5485,7 +5485,7 @@ pub unsafe fn vmls_n_u16(a: uint16x4_t, b: uint16x4_t, c: u16) -> uint16x4_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmls.i16"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mls))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmlsq_n_u16(a: uint16x8_t, b: uint16x8_t, c: u16) -> uint16x8_t {
vmlsq_u16(a, b, vdupq_n_u16(c))
}
@@ -5498,7 +5498,7 @@ pub unsafe fn vmlsq_n_u16(a: uint16x8_t, b: uint16x8_t, c: u16) -> uint16x8_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmls.i32"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mls))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmls_n_u32(a: uint32x2_t, b: uint32x2_t, c: u32) -> uint32x2_t {
vmls_u32(a, b, vdup_n_u32(c))
}
@@ -5511,7 +5511,7 @@ pub unsafe fn vmls_n_u32(a: uint32x2_t, b: uint32x2_t, c: u32) -> uint32x2_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmls.i32"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mls))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmlsq_n_u32(a: uint32x4_t, b: uint32x4_t, c: u32) -> uint32x4_t {
vmlsq_u32(a, b, vdupq_n_u32(c))
}
@@ -5524,7 +5524,7 @@ pub unsafe fn vmlsq_n_u32(a: uint32x4_t, b: uint32x4_t, c: u32) -> uint32x4_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmls.f32"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(fmul))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmls_n_f32(a: float32x2_t, b: float32x2_t, c: f32) -> float32x2_t {
vmls_f32(a, b, vdup_n_f32(c))
}
@@ -5537,7 +5537,7 @@ pub unsafe fn vmls_n_f32(a: float32x2_t, b: float32x2_t, c: f32) -> float32x2_t
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmls.f32"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(fmul))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmlsq_n_f32(a: float32x4_t, b: float32x4_t, c: f32) -> float32x4_t {
vmlsq_f32(a, b, vdupq_n_f32(c))
}
@@ -5551,7 +5551,7 @@ pub unsafe fn vmlsq_n_f32(a: float32x4_t, b: float32x4_t, c: f32) -> float32x4_t
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmls.i16", LANE = 1))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mls, LANE = 1))]
#[rustc_legacy_const_generics(3)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmls_lane_s16<const LANE: i32>(a: int16x4_t, b: int16x4_t, c: int16x4_t) -> int16x4_t {
static_assert_imm2!(LANE);
vmls_s16(a, b, simd_shuffle4!(c, c, <const LANE: i32> [LANE as u32, LANE as u32, LANE as u32, LANE as u32]))
@@ -5566,7 +5566,7 @@ pub unsafe fn vmls_lane_s16<const LANE: i32>(a: int16x4_t, b: int16x4_t, c: int1
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmls.i16", LANE = 1))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mls, LANE = 1))]
#[rustc_legacy_const_generics(3)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmls_laneq_s16<const LANE: i32>(a: int16x4_t, b: int16x4_t, c: int16x8_t) -> int16x4_t {
static_assert_imm3!(LANE);
vmls_s16(a, b, simd_shuffle4!(c, c, <const LANE: i32> [LANE as u32, LANE as u32, LANE as u32, LANE as u32]))
@@ -5581,7 +5581,7 @@ pub unsafe fn vmls_laneq_s16<const LANE: i32>(a: int16x4_t, b: int16x4_t, c: int
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmls.i16", LANE = 1))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mls, LANE = 1))]
#[rustc_legacy_const_generics(3)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmlsq_lane_s16<const LANE: i32>(a: int16x8_t, b: int16x8_t, c: int16x4_t) -> int16x8_t {
static_assert_imm2!(LANE);
vmlsq_s16(a, b, simd_shuffle8!(c, c, <const LANE: i32> [LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32]))
@@ -5596,7 +5596,7 @@ pub unsafe fn vmlsq_lane_s16<const LANE: i32>(a: int16x8_t, b: int16x8_t, c: int
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmls.i16", LANE = 1))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mls, LANE = 1))]
#[rustc_legacy_const_generics(3)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmlsq_laneq_s16<const LANE: i32>(a: int16x8_t, b: int16x8_t, c: int16x8_t) -> int16x8_t {
static_assert_imm3!(LANE);
vmlsq_s16(a, b, simd_shuffle8!(c, c, <const LANE: i32> [LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32]))
@@ -5611,7 +5611,7 @@ pub unsafe fn vmlsq_laneq_s16<const LANE: i32>(a: int16x8_t, b: int16x8_t, c: in
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmls.i32", LANE = 1))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mls, LANE = 1))]
#[rustc_legacy_const_generics(3)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmls_lane_s32<const LANE: i32>(a: int32x2_t, b: int32x2_t, c: int32x2_t) -> int32x2_t {
static_assert_imm1!(LANE);
vmls_s32(a, b, simd_shuffle2!(c, c, <const LANE: i32> [LANE as u32, LANE as u32]))
@@ -5626,7 +5626,7 @@ pub unsafe fn vmls_lane_s32<const LANE: i32>(a: int32x2_t, b: int32x2_t, c: int3
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmls.i32", LANE = 1))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mls, LANE = 1))]
#[rustc_legacy_const_generics(3)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmls_laneq_s32<const LANE: i32>(a: int32x2_t, b: int32x2_t, c: int32x4_t) -> int32x2_t {
static_assert_imm2!(LANE);
vmls_s32(a, b, simd_shuffle2!(c, c, <const LANE: i32> [LANE as u32, LANE as u32]))
@@ -5641,7 +5641,7 @@ pub unsafe fn vmls_laneq_s32<const LANE: i32>(a: int32x2_t, b: int32x2_t, c: int
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmls.i32", LANE = 1))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mls, LANE = 1))]
#[rustc_legacy_const_generics(3)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmlsq_lane_s32<const LANE: i32>(a: int32x4_t, b: int32x4_t, c: int32x2_t) -> int32x4_t {
static_assert_imm1!(LANE);
vmlsq_s32(a, b, simd_shuffle4!(c, c, <const LANE: i32> [LANE as u32, LANE as u32, LANE as u32, LANE as u32]))
@@ -5656,7 +5656,7 @@ pub unsafe fn vmlsq_lane_s32<const LANE: i32>(a: int32x4_t, b: int32x4_t, c: int
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmls.i32", LANE = 1))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mls, LANE = 1))]
#[rustc_legacy_const_generics(3)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmlsq_laneq_s32<const LANE: i32>(a: int32x4_t, b: int32x4_t, c: int32x4_t) -> int32x4_t {
static_assert_imm2!(LANE);
vmlsq_s32(a, b, simd_shuffle4!(c, c, <const LANE: i32> [LANE as u32, LANE as u32, LANE as u32, LANE as u32]))
@@ -5671,7 +5671,7 @@ pub unsafe fn vmlsq_laneq_s32<const LANE: i32>(a: int32x4_t, b: int32x4_t, c: in
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmls.i16", LANE = 1))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mls, LANE = 1))]
#[rustc_legacy_const_generics(3)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmls_lane_u16<const LANE: i32>(a: uint16x4_t, b: uint16x4_t, c: uint16x4_t) -> uint16x4_t {
static_assert_imm2!(LANE);
vmls_u16(a, b, simd_shuffle4!(c, c, <const LANE: i32> [LANE as u32, LANE as u32, LANE as u32, LANE as u32]))
@@ -5686,7 +5686,7 @@ pub unsafe fn vmls_lane_u16<const LANE: i32>(a: uint16x4_t, b: uint16x4_t, c: ui
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmls.i16", LANE = 1))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mls, LANE = 1))]
#[rustc_legacy_const_generics(3)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmls_laneq_u16<const LANE: i32>(a: uint16x4_t, b: uint16x4_t, c: uint16x8_t) -> uint16x4_t {
static_assert_imm3!(LANE);
vmls_u16(a, b, simd_shuffle4!(c, c, <const LANE: i32> [LANE as u32, LANE as u32, LANE as u32, LANE as u32]))
@@ -5701,7 +5701,7 @@ pub unsafe fn vmls_laneq_u16<const LANE: i32>(a: uint16x4_t, b: uint16x4_t, c: u
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmls.i16", LANE = 1))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mls, LANE = 1))]
#[rustc_legacy_const_generics(3)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmlsq_lane_u16<const LANE: i32>(a: uint16x8_t, b: uint16x8_t, c: uint16x4_t) -> uint16x8_t {
static_assert_imm2!(LANE);
vmlsq_u16(a, b, simd_shuffle8!(c, c, <const LANE: i32> [LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32]))
@@ -5716,7 +5716,7 @@ pub unsafe fn vmlsq_lane_u16<const LANE: i32>(a: uint16x8_t, b: uint16x8_t, c: u
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmls.i16", LANE = 1))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mls, LANE = 1))]
#[rustc_legacy_const_generics(3)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmlsq_laneq_u16<const LANE: i32>(a: uint16x8_t, b: uint16x8_t, c: uint16x8_t) -> uint16x8_t {
static_assert_imm3!(LANE);
vmlsq_u16(a, b, simd_shuffle8!(c, c, <const LANE: i32> [LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32]))
@@ -5731,7 +5731,7 @@ pub unsafe fn vmlsq_laneq_u16<const LANE: i32>(a: uint16x8_t, b: uint16x8_t, c:
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmls.i32", LANE = 1))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mls, LANE = 1))]
#[rustc_legacy_const_generics(3)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmls_lane_u32<const LANE: i32>(a: uint32x2_t, b: uint32x2_t, c: uint32x2_t) -> uint32x2_t {
static_assert_imm1!(LANE);
vmls_u32(a, b, simd_shuffle2!(c, c, <const LANE: i32> [LANE as u32, LANE as u32]))
@@ -5746,7 +5746,7 @@ pub unsafe fn vmls_lane_u32<const LANE: i32>(a: uint32x2_t, b: uint32x2_t, c: ui
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmls.i32", LANE = 1))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mls, LANE = 1))]
#[rustc_legacy_const_generics(3)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmls_laneq_u32<const LANE: i32>(a: uint32x2_t, b: uint32x2_t, c: uint32x4_t) -> uint32x2_t {
static_assert_imm2!(LANE);
vmls_u32(a, b, simd_shuffle2!(c, c, <const LANE: i32> [LANE as u32, LANE as u32]))
@@ -5761,7 +5761,7 @@ pub unsafe fn vmls_laneq_u32<const LANE: i32>(a: uint32x2_t, b: uint32x2_t, c: u
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmls.i32", LANE = 1))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mls, LANE = 1))]
#[rustc_legacy_const_generics(3)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmlsq_lane_u32<const LANE: i32>(a: uint32x4_t, b: uint32x4_t, c: uint32x2_t) -> uint32x4_t {
static_assert_imm1!(LANE);
vmlsq_u32(a, b, simd_shuffle4!(c, c, <const LANE: i32> [LANE as u32, LANE as u32, LANE as u32, LANE as u32]))
@@ -5776,7 +5776,7 @@ pub unsafe fn vmlsq_lane_u32<const LANE: i32>(a: uint32x4_t, b: uint32x4_t, c: u
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmls.i32", LANE = 1))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mls, LANE = 1))]
#[rustc_legacy_const_generics(3)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmlsq_laneq_u32<const LANE: i32>(a: uint32x4_t, b: uint32x4_t, c: uint32x4_t) -> uint32x4_t {
static_assert_imm2!(LANE);
vmlsq_u32(a, b, simd_shuffle4!(c, c, <const LANE: i32> [LANE as u32, LANE as u32, LANE as u32, LANE as u32]))
@@ -5791,7 +5791,7 @@ pub unsafe fn vmlsq_laneq_u32<const LANE: i32>(a: uint32x4_t, b: uint32x4_t, c:
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmls.f32", LANE = 1))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(fmul, LANE = 1))]
#[rustc_legacy_const_generics(3)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmls_lane_f32<const LANE: i32>(a: float32x2_t, b: float32x2_t, c: float32x2_t) -> float32x2_t {
static_assert_imm1!(LANE);
vmls_f32(a, b, simd_shuffle2!(c, c, <const LANE: i32> [LANE as u32, LANE as u32]))
@@ -5806,7 +5806,7 @@ pub unsafe fn vmls_lane_f32<const LANE: i32>(a: float32x2_t, b: float32x2_t, c:
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmls.f32", LANE = 1))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(fmul, LANE = 1))]
#[rustc_legacy_const_generics(3)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmls_laneq_f32<const LANE: i32>(a: float32x2_t, b: float32x2_t, c: float32x4_t) -> float32x2_t {
static_assert_imm2!(LANE);
vmls_f32(a, b, simd_shuffle2!(c, c, <const LANE: i32> [LANE as u32, LANE as u32]))
@@ -5821,7 +5821,7 @@ pub unsafe fn vmls_laneq_f32<const LANE: i32>(a: float32x2_t, b: float32x2_t, c:
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmls.f32", LANE = 1))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(fmul, LANE = 1))]
#[rustc_legacy_const_generics(3)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmlsq_lane_f32<const LANE: i32>(a: float32x4_t, b: float32x4_t, c: float32x2_t) -> float32x4_t {
static_assert_imm1!(LANE);
vmlsq_f32(a, b, simd_shuffle4!(c, c, <const LANE: i32> [LANE as u32, LANE as u32, LANE as u32, LANE as u32]))
@@ -5836,7 +5836,7 @@ pub unsafe fn vmlsq_lane_f32<const LANE: i32>(a: float32x4_t, b: float32x4_t, c:
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmls.f32", LANE = 1))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(fmul, LANE = 1))]
#[rustc_legacy_const_generics(3)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmlsq_laneq_f32<const LANE: i32>(a: float32x4_t, b: float32x4_t, c: float32x4_t) -> float32x4_t {
static_assert_imm2!(LANE);
vmlsq_f32(a, b, simd_shuffle4!(c, c, <const LANE: i32> [LANE as u32, LANE as u32, LANE as u32, LANE as u32]))
@@ -5850,7 +5850,7 @@ pub unsafe fn vmlsq_laneq_f32<const LANE: i32>(a: float32x4_t, b: float32x4_t, c
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmlsl.s8"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(smlsl))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmlsl_s8(a: int16x8_t, b: int8x8_t, c: int8x8_t) -> int16x8_t {
simd_sub(a, vmull_s8(b, c))
}
@@ -5863,7 +5863,7 @@ pub unsafe fn vmlsl_s8(a: int16x8_t, b: int8x8_t, c: int8x8_t) -> int16x8_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmlsl.s16"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(smlsl))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmlsl_s16(a: int32x4_t, b: int16x4_t, c: int16x4_t) -> int32x4_t {
simd_sub(a, vmull_s16(b, c))
}
@@ -5876,7 +5876,7 @@ pub unsafe fn vmlsl_s16(a: int32x4_t, b: int16x4_t, c: int16x4_t) -> int32x4_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmlsl.s32"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(smlsl))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmlsl_s32(a: int64x2_t, b: int32x2_t, c: int32x2_t) -> int64x2_t {
simd_sub(a, vmull_s32(b, c))
}
@@ -5889,7 +5889,7 @@ pub unsafe fn vmlsl_s32(a: int64x2_t, b: int32x2_t, c: int32x2_t) -> int64x2_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmlsl.u8"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(umlsl))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmlsl_u8(a: uint16x8_t, b: uint8x8_t, c: uint8x8_t) -> uint16x8_t {
simd_sub(a, vmull_u8(b, c))
}
@@ -5902,7 +5902,7 @@ pub unsafe fn vmlsl_u8(a: uint16x8_t, b: uint8x8_t, c: uint8x8_t) -> uint16x8_t
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmlsl.u16"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(umlsl))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmlsl_u16(a: uint32x4_t, b: uint16x4_t, c: uint16x4_t) -> uint32x4_t {
simd_sub(a, vmull_u16(b, c))
}
@@ -5915,7 +5915,7 @@ pub unsafe fn vmlsl_u16(a: uint32x4_t, b: uint16x4_t, c: uint16x4_t) -> uint32x4
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmlsl.u32"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(umlsl))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmlsl_u32(a: uint64x2_t, b: uint32x2_t, c: uint32x2_t) -> uint64x2_t {
simd_sub(a, vmull_u32(b, c))
}
@@ -5928,7 +5928,7 @@ pub unsafe fn vmlsl_u32(a: uint64x2_t, b: uint32x2_t, c: uint32x2_t) -> uint64x2
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmlsl.s16"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(smlsl))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmlsl_n_s16(a: int32x4_t, b: int16x4_t, c: i16) -> int32x4_t {
vmlsl_s16(a, b, vdup_n_s16(c))
}
@@ -5941,7 +5941,7 @@ pub unsafe fn vmlsl_n_s16(a: int32x4_t, b: int16x4_t, c: i16) -> int32x4_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmlsl.s32"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(smlsl))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmlsl_n_s32(a: int64x2_t, b: int32x2_t, c: i32) -> int64x2_t {
vmlsl_s32(a, b, vdup_n_s32(c))
}
@@ -5954,7 +5954,7 @@ pub unsafe fn vmlsl_n_s32(a: int64x2_t, b: int32x2_t, c: i32) -> int64x2_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmlsl.u16"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(umlsl))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmlsl_n_u16(a: uint32x4_t, b: uint16x4_t, c: u16) -> uint32x4_t {
vmlsl_u16(a, b, vdup_n_u16(c))
}
@@ -5967,7 +5967,7 @@ pub unsafe fn vmlsl_n_u16(a: uint32x4_t, b: uint16x4_t, c: u16) -> uint32x4_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmlsl.u32"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(umlsl))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmlsl_n_u32(a: uint64x2_t, b: uint32x2_t, c: u32) -> uint64x2_t {
vmlsl_u32(a, b, vdup_n_u32(c))
}
@@ -5981,7 +5981,7 @@ pub unsafe fn vmlsl_n_u32(a: uint64x2_t, b: uint32x2_t, c: u32) -> uint64x2_t {
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmlsl.s16", LANE = 1))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(smlsl, LANE = 1))]
#[rustc_legacy_const_generics(3)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmlsl_lane_s16<const LANE: i32>(a: int32x4_t, b: int16x4_t, c: int16x4_t) -> int32x4_t {
static_assert_imm2!(LANE);
vmlsl_s16(a, b, simd_shuffle4!(c, c, <const LANE: i32> [LANE as u32, LANE as u32, LANE as u32, LANE as u32]))
@@ -5996,7 +5996,7 @@ pub unsafe fn vmlsl_lane_s16<const LANE: i32>(a: int32x4_t, b: int16x4_t, c: int
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmlsl.s16", LANE = 1))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(smlsl, LANE = 1))]
#[rustc_legacy_const_generics(3)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmlsl_laneq_s16<const LANE: i32>(a: int32x4_t, b: int16x4_t, c: int16x8_t) -> int32x4_t {
static_assert_imm3!(LANE);
vmlsl_s16(a, b, simd_shuffle4!(c, c, <const LANE: i32> [LANE as u32, LANE as u32, LANE as u32, LANE as u32]))
@@ -6011,7 +6011,7 @@ pub unsafe fn vmlsl_laneq_s16<const LANE: i32>(a: int32x4_t, b: int16x4_t, c: in
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmlsl.s32", LANE = 1))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(smlsl, LANE = 1))]
#[rustc_legacy_const_generics(3)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmlsl_lane_s32<const LANE: i32>(a: int64x2_t, b: int32x2_t, c: int32x2_t) -> int64x2_t {
static_assert_imm1!(LANE);
vmlsl_s32(a, b, simd_shuffle2!(c, c, <const LANE: i32> [LANE as u32, LANE as u32]))
@@ -6026,7 +6026,7 @@ pub unsafe fn vmlsl_lane_s32<const LANE: i32>(a: int64x2_t, b: int32x2_t, c: int
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmlsl.s32", LANE = 1))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(smlsl, LANE = 1))]
#[rustc_legacy_const_generics(3)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmlsl_laneq_s32<const LANE: i32>(a: int64x2_t, b: int32x2_t, c: int32x4_t) -> int64x2_t {
static_assert_imm2!(LANE);
vmlsl_s32(a, b, simd_shuffle2!(c, c, <const LANE: i32> [LANE as u32, LANE as u32]))
@@ -6041,7 +6041,7 @@ pub unsafe fn vmlsl_laneq_s32<const LANE: i32>(a: int64x2_t, b: int32x2_t, c: in
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmlsl.u16", LANE = 1))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(umlsl, LANE = 1))]
#[rustc_legacy_const_generics(3)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmlsl_lane_u16<const LANE: i32>(a: uint32x4_t, b: uint16x4_t, c: uint16x4_t) -> uint32x4_t {
static_assert_imm2!(LANE);
vmlsl_u16(a, b, simd_shuffle4!(c, c, <const LANE: i32> [LANE as u32, LANE as u32, LANE as u32, LANE as u32]))
@@ -6056,7 +6056,7 @@ pub unsafe fn vmlsl_lane_u16<const LANE: i32>(a: uint32x4_t, b: uint16x4_t, c: u
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmlsl.u16", LANE = 1))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(umlsl, LANE = 1))]
#[rustc_legacy_const_generics(3)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmlsl_laneq_u16<const LANE: i32>(a: uint32x4_t, b: uint16x4_t, c: uint16x8_t) -> uint32x4_t {
static_assert_imm3!(LANE);
vmlsl_u16(a, b, simd_shuffle4!(c, c, <const LANE: i32> [LANE as u32, LANE as u32, LANE as u32, LANE as u32]))
@@ -6071,7 +6071,7 @@ pub unsafe fn vmlsl_laneq_u16<const LANE: i32>(a: uint32x4_t, b: uint16x4_t, c:
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmlsl.u32", LANE = 1))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(umlsl, LANE = 1))]
#[rustc_legacy_const_generics(3)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmlsl_lane_u32<const LANE: i32>(a: uint64x2_t, b: uint32x2_t, c: uint32x2_t) -> uint64x2_t {
static_assert_imm1!(LANE);
vmlsl_u32(a, b, simd_shuffle2!(c, c, <const LANE: i32> [LANE as u32, LANE as u32]))
@@ -6086,7 +6086,7 @@ pub unsafe fn vmlsl_lane_u32<const LANE: i32>(a: uint64x2_t, b: uint32x2_t, c: u
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmlsl.u32", LANE = 1))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(umlsl, LANE = 1))]
#[rustc_legacy_const_generics(3)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmlsl_laneq_u32<const LANE: i32>(a: uint64x2_t, b: uint32x2_t, c: uint32x4_t) -> uint64x2_t {
static_assert_imm2!(LANE);
vmlsl_u32(a, b, simd_shuffle2!(c, c, <const LANE: i32> [LANE as u32, LANE as u32]))
@@ -6100,7 +6100,7 @@ pub unsafe fn vmlsl_laneq_u32<const LANE: i32>(a: uint64x2_t, b: uint32x2_t, c:
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vneg.s8"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(neg))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vneg_s8(a: int8x8_t) -> int8x8_t {
simd_neg(a)
}
@@ -6113,7 +6113,7 @@ pub unsafe fn vneg_s8(a: int8x8_t) -> int8x8_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vneg.s8"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(neg))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vnegq_s8(a: int8x16_t) -> int8x16_t {
simd_neg(a)
}
@@ -6126,7 +6126,7 @@ pub unsafe fn vnegq_s8(a: int8x16_t) -> int8x16_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vneg.s16"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(neg))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vneg_s16(a: int16x4_t) -> int16x4_t {
simd_neg(a)
}
@@ -6139,7 +6139,7 @@ pub unsafe fn vneg_s16(a: int16x4_t) -> int16x4_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vneg.s16"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(neg))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vnegq_s16(a: int16x8_t) -> int16x8_t {
simd_neg(a)
}
@@ -6152,7 +6152,7 @@ pub unsafe fn vnegq_s16(a: int16x8_t) -> int16x8_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vneg.s32"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(neg))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vneg_s32(a: int32x2_t) -> int32x2_t {
simd_neg(a)
}
@@ -6165,7 +6165,7 @@ pub unsafe fn vneg_s32(a: int32x2_t) -> int32x2_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vneg.s32"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(neg))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vnegq_s32(a: int32x4_t) -> int32x4_t {
simd_neg(a)
}
@@ -6178,7 +6178,7 @@ pub unsafe fn vnegq_s32(a: int32x4_t) -> int32x4_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vneg.f32"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(fneg))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vneg_f32(a: float32x2_t) -> float32x2_t {
simd_neg(a)
}
@@ -6191,7 +6191,7 @@ pub unsafe fn vneg_f32(a: float32x2_t) -> float32x2_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vneg.f32"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(fneg))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vnegq_f32(a: float32x4_t) -> float32x4_t {
simd_neg(a)
}
@@ -6204,7 +6204,7 @@ pub unsafe fn vnegq_f32(a: float32x4_t) -> float32x4_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vqneg.s8"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqneg))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vqneg_s8(a: int8x8_t) -> int8x8_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -6223,7 +6223,7 @@ vqneg_s8_(a)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vqneg.s8"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqneg))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vqnegq_s8(a: int8x16_t) -> int8x16_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -6242,7 +6242,7 @@ vqnegq_s8_(a)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vqneg.s16"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqneg))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vqneg_s16(a: int16x4_t) -> int16x4_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -6261,7 +6261,7 @@ vqneg_s16_(a)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vqneg.s16"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqneg))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vqnegq_s16(a: int16x8_t) -> int16x8_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -6280,7 +6280,7 @@ vqnegq_s16_(a)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vqneg.s32"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqneg))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vqneg_s32(a: int32x2_t) -> int32x2_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -6299,7 +6299,7 @@ vqneg_s32_(a)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vqneg.s32"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqneg))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vqnegq_s32(a: int32x4_t) -> int32x4_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -6318,7 +6318,7 @@ vqnegq_s32_(a)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vqsub.u8"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uqsub))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vqsub_u8(a: uint8x8_t, b: uint8x8_t) -> uint8x8_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -6337,7 +6337,7 @@ vqsub_u8_(a, b)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vqsub.u8"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uqsub))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vqsubq_u8(a: uint8x16_t, b: uint8x16_t) -> uint8x16_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -6356,7 +6356,7 @@ vqsubq_u8_(a, b)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vqsub.u16"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uqsub))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vqsub_u16(a: uint16x4_t, b: uint16x4_t) -> uint16x4_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -6375,7 +6375,7 @@ vqsub_u16_(a, b)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vqsub.u16"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uqsub))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vqsubq_u16(a: uint16x8_t, b: uint16x8_t) -> uint16x8_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -6394,7 +6394,7 @@ vqsubq_u16_(a, b)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vqsub.u32"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uqsub))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vqsub_u32(a: uint32x2_t, b: uint32x2_t) -> uint32x2_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -6413,7 +6413,7 @@ vqsub_u32_(a, b)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vqsub.u32"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uqsub))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vqsubq_u32(a: uint32x4_t, b: uint32x4_t) -> uint32x4_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -6432,7 +6432,7 @@ vqsubq_u32_(a, b)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vqsub.u64"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uqsub))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vqsub_u64(a: uint64x1_t, b: uint64x1_t) -> uint64x1_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -6451,7 +6451,7 @@ vqsub_u64_(a, b)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vqsub.u64"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uqsub))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vqsubq_u64(a: uint64x2_t, b: uint64x2_t) -> uint64x2_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -6470,7 +6470,7 @@ vqsubq_u64_(a, b)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vqsub.s8"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqsub))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vqsub_s8(a: int8x8_t, b: int8x8_t) -> int8x8_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -6489,7 +6489,7 @@ vqsub_s8_(a, b)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vqsub.s8"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqsub))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vqsubq_s8(a: int8x16_t, b: int8x16_t) -> int8x16_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -6508,7 +6508,7 @@ vqsubq_s8_(a, b)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vqsub.s16"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqsub))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vqsub_s16(a: int16x4_t, b: int16x4_t) -> int16x4_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -6527,7 +6527,7 @@ vqsub_s16_(a, b)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vqsub.s16"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqsub))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vqsubq_s16(a: int16x8_t, b: int16x8_t) -> int16x8_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -6546,7 +6546,7 @@ vqsubq_s16_(a, b)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vqsub.s32"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqsub))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vqsub_s32(a: int32x2_t, b: int32x2_t) -> int32x2_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -6565,7 +6565,7 @@ vqsub_s32_(a, b)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vqsub.s32"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqsub))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vqsubq_s32(a: int32x4_t, b: int32x4_t) -> int32x4_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -6584,7 +6584,7 @@ vqsubq_s32_(a, b)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vqsub.s64"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqsub))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vqsub_s64(a: int64x1_t, b: int64x1_t) -> int64x1_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -6603,7 +6603,7 @@ vqsub_s64_(a, b)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vqsub.s64"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqsub))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vqsubq_s64(a: int64x2_t, b: int64x2_t) -> int64x2_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -6622,7 +6622,7 @@ vqsubq_s64_(a, b)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vhadd.u8"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uhadd))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vhadd_u8(a: uint8x8_t, b: uint8x8_t) -> uint8x8_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -6641,7 +6641,7 @@ vhadd_u8_(a, b)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vhadd.u8"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uhadd))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vhaddq_u8(a: uint8x16_t, b: uint8x16_t) -> uint8x16_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -6660,7 +6660,7 @@ vhaddq_u8_(a, b)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vhadd.u16"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uhadd))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vhadd_u16(a: uint16x4_t, b: uint16x4_t) -> uint16x4_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -6679,7 +6679,7 @@ vhadd_u16_(a, b)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vhadd.u16"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uhadd))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vhaddq_u16(a: uint16x8_t, b: uint16x8_t) -> uint16x8_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -6698,7 +6698,7 @@ vhaddq_u16_(a, b)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vhadd.u32"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uhadd))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vhadd_u32(a: uint32x2_t, b: uint32x2_t) -> uint32x2_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -6717,7 +6717,7 @@ vhadd_u32_(a, b)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vhadd.u32"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uhadd))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vhaddq_u32(a: uint32x4_t, b: uint32x4_t) -> uint32x4_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -6736,7 +6736,7 @@ vhaddq_u32_(a, b)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vhadd.s8"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(shadd))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vhadd_s8(a: int8x8_t, b: int8x8_t) -> int8x8_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -6755,7 +6755,7 @@ vhadd_s8_(a, b)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vhadd.s8"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(shadd))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vhaddq_s8(a: int8x16_t, b: int8x16_t) -> int8x16_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -6774,7 +6774,7 @@ vhaddq_s8_(a, b)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vhadd.s16"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(shadd))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vhadd_s16(a: int16x4_t, b: int16x4_t) -> int16x4_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -6793,7 +6793,7 @@ vhadd_s16_(a, b)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vhadd.s16"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(shadd))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vhaddq_s16(a: int16x8_t, b: int16x8_t) -> int16x8_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -6812,7 +6812,7 @@ vhaddq_s16_(a, b)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vhadd.s32"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(shadd))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vhadd_s32(a: int32x2_t, b: int32x2_t) -> int32x2_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -6831,7 +6831,7 @@ vhadd_s32_(a, b)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vhadd.s32"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(shadd))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vhaddq_s32(a: int32x4_t, b: int32x4_t) -> int32x4_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -6850,7 +6850,7 @@ vhaddq_s32_(a, b)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vrhadd.u8"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(urhadd))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vrhadd_u8(a: uint8x8_t, b: uint8x8_t) -> uint8x8_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -6869,7 +6869,7 @@ vrhadd_u8_(a, b)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vrhadd.u8"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(urhadd))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vrhaddq_u8(a: uint8x16_t, b: uint8x16_t) -> uint8x16_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -6888,7 +6888,7 @@ vrhaddq_u8_(a, b)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vrhadd.u16"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(urhadd))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vrhadd_u16(a: uint16x4_t, b: uint16x4_t) -> uint16x4_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -6907,7 +6907,7 @@ vrhadd_u16_(a, b)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vrhadd.u16"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(urhadd))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vrhaddq_u16(a: uint16x8_t, b: uint16x8_t) -> uint16x8_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -6926,7 +6926,7 @@ vrhaddq_u16_(a, b)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vrhadd.u32"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(urhadd))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vrhadd_u32(a: uint32x2_t, b: uint32x2_t) -> uint32x2_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -6945,7 +6945,7 @@ vrhadd_u32_(a, b)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vrhadd.u32"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(urhadd))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vrhaddq_u32(a: uint32x4_t, b: uint32x4_t) -> uint32x4_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -6964,7 +6964,7 @@ vrhaddq_u32_(a, b)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vrhadd.s8"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(srhadd))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vrhadd_s8(a: int8x8_t, b: int8x8_t) -> int8x8_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -6983,7 +6983,7 @@ vrhadd_s8_(a, b)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vrhadd.s8"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(srhadd))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vrhaddq_s8(a: int8x16_t, b: int8x16_t) -> int8x16_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -7002,7 +7002,7 @@ vrhaddq_s8_(a, b)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vrhadd.s16"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(srhadd))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vrhadd_s16(a: int16x4_t, b: int16x4_t) -> int16x4_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -7021,7 +7021,7 @@ vrhadd_s16_(a, b)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vrhadd.s16"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(srhadd))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vrhaddq_s16(a: int16x8_t, b: int16x8_t) -> int16x8_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -7040,7 +7040,7 @@ vrhaddq_s16_(a, b)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vrhadd.s32"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(srhadd))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vrhadd_s32(a: int32x2_t, b: int32x2_t) -> int32x2_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -7059,7 +7059,7 @@ vrhadd_s32_(a, b)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vrhadd.s32"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(srhadd))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vrhaddq_s32(a: int32x4_t, b: int32x4_t) -> int32x4_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -7078,7 +7078,7 @@ vrhaddq_s32_(a, b)
#[cfg_attr(target_arch = "arm", target_feature(enable = "fp-armv8,v8"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrintn))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(frintn))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vrndn_f32(a: float32x2_t) -> float32x2_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -7097,7 +7097,7 @@ vrndn_f32_(a)
#[cfg_attr(target_arch = "arm", target_feature(enable = "fp-armv8,v8"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrintn))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(frintn))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vrndnq_f32(a: float32x4_t) -> float32x4_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -7116,7 +7116,7 @@ vrndnq_f32_(a)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vqadd.u8"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uqadd))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vqadd_u8(a: uint8x8_t, b: uint8x8_t) -> uint8x8_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -7135,7 +7135,7 @@ vqadd_u8_(a, b)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vqadd.u8"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uqadd))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vqaddq_u8(a: uint8x16_t, b: uint8x16_t) -> uint8x16_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -7154,7 +7154,7 @@ vqaddq_u8_(a, b)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vqadd.u16"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uqadd))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vqadd_u16(a: uint16x4_t, b: uint16x4_t) -> uint16x4_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -7173,7 +7173,7 @@ vqadd_u16_(a, b)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vqadd.u16"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uqadd))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vqaddq_u16(a: uint16x8_t, b: uint16x8_t) -> uint16x8_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -7192,7 +7192,7 @@ vqaddq_u16_(a, b)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vqadd.u32"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uqadd))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vqadd_u32(a: uint32x2_t, b: uint32x2_t) -> uint32x2_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -7211,7 +7211,7 @@ vqadd_u32_(a, b)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vqadd.u32"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uqadd))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vqaddq_u32(a: uint32x4_t, b: uint32x4_t) -> uint32x4_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -7230,7 +7230,7 @@ vqaddq_u32_(a, b)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vqadd.u64"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uqadd))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vqadd_u64(a: uint64x1_t, b: uint64x1_t) -> uint64x1_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -7249,7 +7249,7 @@ vqadd_u64_(a, b)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vqadd.u64"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uqadd))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vqaddq_u64(a: uint64x2_t, b: uint64x2_t) -> uint64x2_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -7268,7 +7268,7 @@ vqaddq_u64_(a, b)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vqadd.s8"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqadd))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vqadd_s8(a: int8x8_t, b: int8x8_t) -> int8x8_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -7287,7 +7287,7 @@ vqadd_s8_(a, b)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vqadd.s8"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqadd))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vqaddq_s8(a: int8x16_t, b: int8x16_t) -> int8x16_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -7306,7 +7306,7 @@ vqaddq_s8_(a, b)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vqadd.s16"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqadd))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vqadd_s16(a: int16x4_t, b: int16x4_t) -> int16x4_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -7325,7 +7325,7 @@ vqadd_s16_(a, b)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vqadd.s16"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqadd))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vqaddq_s16(a: int16x8_t, b: int16x8_t) -> int16x8_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -7344,7 +7344,7 @@ vqaddq_s16_(a, b)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vqadd.s32"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqadd))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vqadd_s32(a: int32x2_t, b: int32x2_t) -> int32x2_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -7363,7 +7363,7 @@ vqadd_s32_(a, b)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vqadd.s32"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqadd))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vqaddq_s32(a: int32x4_t, b: int32x4_t) -> int32x4_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -7382,7 +7382,7 @@ vqaddq_s32_(a, b)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vqadd.s64"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqadd))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vqadd_s64(a: int64x1_t, b: int64x1_t) -> int64x1_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -7401,7 +7401,7 @@ vqadd_s64_(a, b)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vqadd.s64"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqadd))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vqaddq_s64(a: int64x2_t, b: int64x2_t) -> int64x2_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -7420,7 +7420,7 @@ vqaddq_s64_(a, b)
#[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))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vld1_s8_x2(a: *const i8) -> int8x8x2_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -7439,7 +7439,7 @@ vld1_s8_x2_(a)
#[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))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vld1_s16_x2(a: *const i16) -> int16x4x2_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -7458,7 +7458,7 @@ vld1_s16_x2_(a)
#[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))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vld1_s32_x2(a: *const i32) -> int32x2x2_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -7477,7 +7477,7 @@ vld1_s32_x2_(a)
#[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))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vld1_s64_x2(a: *const i64) -> int64x1x2_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -7496,7 +7496,7 @@ vld1_s64_x2_(a)
#[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))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vld1q_s8_x2(a: *const i8) -> int8x16x2_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -7515,7 +7515,7 @@ vld1q_s8_x2_(a)
#[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))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vld1q_s16_x2(a: *const i16) -> int16x8x2_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -7534,7 +7534,7 @@ vld1q_s16_x2_(a)
#[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))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vld1q_s32_x2(a: *const i32) -> int32x4x2_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -7553,7 +7553,7 @@ vld1q_s32_x2_(a)
#[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))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vld1q_s64_x2(a: *const i64) -> int64x2x2_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -7572,7 +7572,7 @@ vld1q_s64_x2_(a)
#[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))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vld1_s8_x3(a: *const i8) -> int8x8x3_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -7591,7 +7591,7 @@ vld1_s8_x3_(a)
#[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))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vld1_s16_x3(a: *const i16) -> int16x4x3_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -7610,7 +7610,7 @@ vld1_s16_x3_(a)
#[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))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vld1_s32_x3(a: *const i32) -> int32x2x3_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -7629,7 +7629,7 @@ vld1_s32_x3_(a)
#[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))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vld1_s64_x3(a: *const i64) -> int64x1x3_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -7648,7 +7648,7 @@ vld1_s64_x3_(a)
#[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))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vld1q_s8_x3(a: *const i8) -> int8x16x3_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -7667,7 +7667,7 @@ vld1q_s8_x3_(a)
#[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))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vld1q_s16_x3(a: *const i16) -> int16x8x3_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -7686,7 +7686,7 @@ vld1q_s16_x3_(a)
#[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))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vld1q_s32_x3(a: *const i32) -> int32x4x3_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -7705,7 +7705,7 @@ vld1q_s32_x3_(a)
#[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))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vld1q_s64_x3(a: *const i64) -> int64x2x3_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -7724,7 +7724,7 @@ vld1q_s64_x3_(a)
#[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))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vld1_s8_x4(a: *const i8) -> int8x8x4_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -7743,7 +7743,7 @@ vld1_s8_x4_(a)
#[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))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vld1_s16_x4(a: *const i16) -> int16x4x4_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -7762,7 +7762,7 @@ vld1_s16_x4_(a)
#[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))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vld1_s32_x4(a: *const i32) -> int32x2x4_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -7781,7 +7781,7 @@ vld1_s32_x4_(a)
#[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))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vld1_s64_x4(a: *const i64) -> int64x1x4_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -7800,7 +7800,7 @@ vld1_s64_x4_(a)
#[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))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vld1q_s8_x4(a: *const i8) -> int8x16x4_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -7819,7 +7819,7 @@ vld1q_s8_x4_(a)
#[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))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vld1q_s16_x4(a: *const i16) -> int16x8x4_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -7838,7 +7838,7 @@ vld1q_s16_x4_(a)
#[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))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vld1q_s32_x4(a: *const i32) -> int32x4x4_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -7857,7 +7857,7 @@ vld1q_s32_x4_(a)
#[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))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vld1q_s64_x4(a: *const i64) -> int64x2x4_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -7876,7 +7876,7 @@ vld1q_s64_x4_(a)
#[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))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vld1_u8_x2(a: *const u8) -> uint8x8x2_t {
transmute(vld1_s8_x2(transmute(a)))
}
@@ -7889,7 +7889,7 @@ pub unsafe fn vld1_u8_x2(a: *const u8) -> uint8x8x2_t {
#[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))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vld1_u16_x2(a: *const u16) -> uint16x4x2_t {
transmute(vld1_s16_x2(transmute(a)))
}
@@ -7902,7 +7902,7 @@ pub unsafe fn vld1_u16_x2(a: *const u16) -> uint16x4x2_t {
#[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))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vld1_u32_x2(a: *const u32) -> uint32x2x2_t {
transmute(vld1_s32_x2(transmute(a)))
}
@@ -7915,7 +7915,7 @@ pub unsafe fn vld1_u32_x2(a: *const u32) -> uint32x2x2_t {
#[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))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vld1_u64_x2(a: *const u64) -> uint64x1x2_t {
transmute(vld1_s64_x2(transmute(a)))
}
@@ -7928,7 +7928,7 @@ pub unsafe fn vld1_u64_x2(a: *const u64) -> uint64x1x2_t {
#[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))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vld1q_u8_x2(a: *const u8) -> uint8x16x2_t {
transmute(vld1q_s8_x2(transmute(a)))
}
@@ -7941,7 +7941,7 @@ pub unsafe fn vld1q_u8_x2(a: *const u8) -> uint8x16x2_t {
#[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))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vld1q_u16_x2(a: *const u16) -> uint16x8x2_t {
transmute(vld1q_s16_x2(transmute(a)))
}
@@ -7954,7 +7954,7 @@ pub unsafe fn vld1q_u16_x2(a: *const u16) -> uint16x8x2_t {
#[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))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vld1q_u32_x2(a: *const u32) -> uint32x4x2_t {
transmute(vld1q_s32_x2(transmute(a)))
}
@@ -7967,7 +7967,7 @@ pub unsafe fn vld1q_u32_x2(a: *const u32) -> uint32x4x2_t {
#[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))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vld1q_u64_x2(a: *const u64) -> uint64x2x2_t {
transmute(vld1q_s64_x2(transmute(a)))
}
@@ -7980,7 +7980,7 @@ pub unsafe fn vld1q_u64_x2(a: *const u64) -> uint64x2x2_t {
#[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))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vld1_u8_x3(a: *const u8) -> uint8x8x3_t {
transmute(vld1_s8_x3(transmute(a)))
}
@@ -7993,7 +7993,7 @@ pub unsafe fn vld1_u8_x3(a: *const u8) -> uint8x8x3_t {
#[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))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vld1_u16_x3(a: *const u16) -> uint16x4x3_t {
transmute(vld1_s16_x3(transmute(a)))
}
@@ -8006,7 +8006,7 @@ pub unsafe fn vld1_u16_x3(a: *const u16) -> uint16x4x3_t {
#[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))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vld1_u32_x3(a: *const u32) -> uint32x2x3_t {
transmute(vld1_s32_x3(transmute(a)))
}
@@ -8019,7 +8019,7 @@ pub unsafe fn vld1_u32_x3(a: *const u32) -> uint32x2x3_t {
#[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))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vld1_u64_x3(a: *const u64) -> uint64x1x3_t {
transmute(vld1_s64_x3(transmute(a)))
}
@@ -8032,7 +8032,7 @@ pub unsafe fn vld1_u64_x3(a: *const u64) -> uint64x1x3_t {
#[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))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vld1q_u8_x3(a: *const u8) -> uint8x16x3_t {
transmute(vld1q_s8_x3(transmute(a)))
}
@@ -8045,7 +8045,7 @@ pub unsafe fn vld1q_u8_x3(a: *const u8) -> uint8x16x3_t {
#[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))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vld1q_u16_x3(a: *const u16) -> uint16x8x3_t {
transmute(vld1q_s16_x3(transmute(a)))
}
@@ -8058,7 +8058,7 @@ pub unsafe fn vld1q_u16_x3(a: *const u16) -> uint16x8x3_t {
#[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))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vld1q_u32_x3(a: *const u32) -> uint32x4x3_t {
transmute(vld1q_s32_x3(transmute(a)))
}
@@ -8071,7 +8071,7 @@ pub unsafe fn vld1q_u32_x3(a: *const u32) -> uint32x4x3_t {
#[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))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vld1q_u64_x3(a: *const u64) -> uint64x2x3_t {
transmute(vld1q_s64_x3(transmute(a)))
}
@@ -8084,7 +8084,7 @@ pub unsafe fn vld1q_u64_x3(a: *const u64) -> uint64x2x3_t {
#[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))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vld1_u8_x4(a: *const u8) -> uint8x8x4_t {
transmute(vld1_s8_x4(transmute(a)))
}
@@ -8097,7 +8097,7 @@ pub unsafe fn vld1_u8_x4(a: *const u8) -> uint8x8x4_t {
#[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))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vld1_u16_x4(a: *const u16) -> uint16x4x4_t {
transmute(vld1_s16_x4(transmute(a)))
}
@@ -8110,7 +8110,7 @@ pub unsafe fn vld1_u16_x4(a: *const u16) -> uint16x4x4_t {
#[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))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vld1_u32_x4(a: *const u32) -> uint32x2x4_t {
transmute(vld1_s32_x4(transmute(a)))
}
@@ -8123,7 +8123,7 @@ pub unsafe fn vld1_u32_x4(a: *const u32) -> uint32x2x4_t {
#[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))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vld1_u64_x4(a: *const u64) -> uint64x1x4_t {
transmute(vld1_s64_x4(transmute(a)))
}
@@ -8136,7 +8136,7 @@ pub unsafe fn vld1_u64_x4(a: *const u64) -> uint64x1x4_t {
#[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))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vld1q_u8_x4(a: *const u8) -> uint8x16x4_t {
transmute(vld1q_s8_x4(transmute(a)))
}
@@ -8149,7 +8149,7 @@ pub unsafe fn vld1q_u8_x4(a: *const u8) -> uint8x16x4_t {
#[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))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vld1q_u16_x4(a: *const u16) -> uint16x8x4_t {
transmute(vld1q_s16_x4(transmute(a)))
}
@@ -8162,7 +8162,7 @@ pub unsafe fn vld1q_u16_x4(a: *const u16) -> uint16x8x4_t {
#[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))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vld1q_u32_x4(a: *const u32) -> uint32x4x4_t {
transmute(vld1q_s32_x4(transmute(a)))
}
@@ -8175,7 +8175,7 @@ pub unsafe fn vld1q_u32_x4(a: *const u32) -> uint32x4x4_t {
#[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))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vld1q_u64_x4(a: *const u64) -> uint64x2x4_t {
transmute(vld1q_s64_x4(transmute(a)))
}
@@ -8188,7 +8188,7 @@ pub unsafe fn vld1q_u64_x4(a: *const u64) -> uint64x2x4_t {
#[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))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vld1_p8_x2(a: *const p8) -> poly8x8x2_t {
transmute(vld1_s8_x2(transmute(a)))
}
@@ -8201,7 +8201,7 @@ pub unsafe fn vld1_p8_x2(a: *const p8) -> poly8x8x2_t {
#[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))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vld1_p8_x3(a: *const p8) -> poly8x8x3_t {
transmute(vld1_s8_x3(transmute(a)))
}
@@ -8214,7 +8214,7 @@ pub unsafe fn vld1_p8_x3(a: *const p8) -> poly8x8x3_t {
#[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))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vld1_p8_x4(a: *const p8) -> poly8x8x4_t {
transmute(vld1_s8_x4(transmute(a)))
}
@@ -8227,7 +8227,7 @@ pub unsafe fn vld1_p8_x4(a: *const p8) -> poly8x8x4_t {
#[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))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vld1q_p8_x2(a: *const p8) -> poly8x16x2_t {
transmute(vld1q_s8_x2(transmute(a)))
}
@@ -8240,7 +8240,7 @@ pub unsafe fn vld1q_p8_x2(a: *const p8) -> poly8x16x2_t {
#[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))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vld1q_p8_x3(a: *const p8) -> poly8x16x3_t {
transmute(vld1q_s8_x3(transmute(a)))
}
@@ -8253,7 +8253,7 @@ pub unsafe fn vld1q_p8_x3(a: *const p8) -> poly8x16x3_t {
#[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))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vld1q_p8_x4(a: *const p8) -> poly8x16x4_t {
transmute(vld1q_s8_x4(transmute(a)))
}
@@ -8266,7 +8266,7 @@ pub unsafe fn vld1q_p8_x4(a: *const p8) -> poly8x16x4_t {
#[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))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vld1_p16_x2(a: *const p16) -> poly16x4x2_t {
transmute(vld1_s16_x2(transmute(a)))
}
@@ -8279,7 +8279,7 @@ pub unsafe fn vld1_p16_x2(a: *const p16) -> poly16x4x2_t {
#[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))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vld1_p16_x3(a: *const p16) -> poly16x4x3_t {
transmute(vld1_s16_x3(transmute(a)))
}
@@ -8292,7 +8292,7 @@ pub unsafe fn vld1_p16_x3(a: *const p16) -> poly16x4x3_t {
#[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))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vld1_p16_x4(a: *const p16) -> poly16x4x4_t {
transmute(vld1_s16_x4(transmute(a)))
}
@@ -8305,7 +8305,7 @@ pub unsafe fn vld1_p16_x4(a: *const p16) -> poly16x4x4_t {
#[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))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vld1q_p16_x2(a: *const p16) -> poly16x8x2_t {
transmute(vld1q_s16_x2(transmute(a)))
}
@@ -8318,7 +8318,7 @@ pub unsafe fn vld1q_p16_x2(a: *const p16) -> poly16x8x2_t {
#[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))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vld1q_p16_x3(a: *const p16) -> poly16x8x3_t {
transmute(vld1q_s16_x3(transmute(a)))
}
@@ -8331,7 +8331,7 @@ pub unsafe fn vld1q_p16_x3(a: *const p16) -> poly16x8x3_t {
#[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))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vld1q_p16_x4(a: *const p16) -> poly16x8x4_t {
transmute(vld1q_s16_x4(transmute(a)))
}
@@ -8344,7 +8344,7 @@ pub unsafe fn vld1q_p16_x4(a: *const p16) -> poly16x8x4_t {
#[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))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vld1_p64_x2(a: *const p64) -> poly64x1x2_t {
transmute(vld1_s64_x2(transmute(a)))
}
@@ -8357,7 +8357,7 @@ pub unsafe fn vld1_p64_x2(a: *const p64) -> poly64x1x2_t {
#[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(ld1))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vld1_p64_x3(a: *const p64) -> poly64x1x3_t {
transmute(vld1_s64_x3(transmute(a)))
}
@@ -8370,7 +8370,7 @@ pub unsafe fn vld1_p64_x3(a: *const p64) -> poly64x1x3_t {
#[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(ld1))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vld1_p64_x4(a: *const p64) -> poly64x1x4_t {
transmute(vld1_s64_x4(transmute(a)))
}
@@ -8383,7 +8383,7 @@ pub unsafe fn vld1_p64_x4(a: *const p64) -> poly64x1x4_t {
#[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(ld1))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vld1q_p64_x2(a: *const p64) -> poly64x2x2_t {
transmute(vld1q_s64_x2(transmute(a)))
}
@@ -8396,7 +8396,7 @@ pub unsafe fn vld1q_p64_x2(a: *const p64) -> poly64x2x2_t {
#[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(ld1))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vld1q_p64_x3(a: *const p64) -> poly64x2x3_t {
transmute(vld1q_s64_x3(transmute(a)))
}
@@ -8409,7 +8409,7 @@ pub unsafe fn vld1q_p64_x3(a: *const p64) -> poly64x2x3_t {
#[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(ld1))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vld1q_p64_x4(a: *const p64) -> poly64x2x4_t {
transmute(vld1q_s64_x4(transmute(a)))
}
@@ -8422,7 +8422,7 @@ pub unsafe fn vld1q_p64_x4(a: *const p64) -> poly64x2x4_t {
#[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))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vld1_f32_x2(a: *const f32) -> float32x2x2_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -8441,7 +8441,7 @@ vld1_f32_x2_(a)
#[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))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vld1q_f32_x2(a: *const f32) -> float32x4x2_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -8460,7 +8460,7 @@ vld1q_f32_x2_(a)
#[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))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vld1_f32_x3(a: *const f32) -> float32x2x3_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -8479,7 +8479,7 @@ vld1_f32_x3_(a)
#[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))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vld1q_f32_x3(a: *const f32) -> float32x4x3_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -8498,7 +8498,7 @@ vld1q_f32_x3_(a)
#[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))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vld1_f32_x4(a: *const f32) -> float32x2x4_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -8517,7 +8517,7 @@ vld1_f32_x4_(a)
#[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))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vld1q_f32_x4(a: *const f32) -> float32x4x4_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -8767,7 +8767,7 @@ vld2_s64_(a as _)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld2))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld2))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vld2_u8(a: *const u8) -> uint8x8x2_t {
transmute(vld2_s8(transmute(a)))
}
@@ -8780,7 +8780,7 @@ pub unsafe fn vld2_u8(a: *const u8) -> uint8x8x2_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld2))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld2))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vld2_u16(a: *const u16) -> uint16x4x2_t {
transmute(vld2_s16(transmute(a)))
}
@@ -8793,7 +8793,7 @@ pub unsafe fn vld2_u16(a: *const u16) -> uint16x4x2_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld2))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld2))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vld2_u32(a: *const u32) -> uint32x2x2_t {
transmute(vld2_s32(transmute(a)))
}
@@ -8806,7 +8806,7 @@ pub unsafe fn vld2_u32(a: *const u32) -> uint32x2x2_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld2))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld2))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vld2q_u8(a: *const u8) -> uint8x16x2_t {
transmute(vld2q_s8(transmute(a)))
}
@@ -8819,7 +8819,7 @@ pub unsafe fn vld2q_u8(a: *const u8) -> uint8x16x2_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld2))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld2))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vld2q_u16(a: *const u16) -> uint16x8x2_t {
transmute(vld2q_s16(transmute(a)))
}
@@ -8832,7 +8832,7 @@ pub unsafe fn vld2q_u16(a: *const u16) -> uint16x8x2_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld2))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld2))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vld2q_u32(a: *const u32) -> uint32x4x2_t {
transmute(vld2q_s32(transmute(a)))
}
@@ -8845,7 +8845,7 @@ pub unsafe fn vld2q_u32(a: *const u32) -> uint32x4x2_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld2))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld2))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vld2_p8(a: *const p8) -> poly8x8x2_t {
transmute(vld2_s8(transmute(a)))
}
@@ -8858,7 +8858,7 @@ pub unsafe fn vld2_p8(a: *const p8) -> poly8x8x2_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld2))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld2))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vld2_p16(a: *const p16) -> poly16x4x2_t {
transmute(vld2_s16(transmute(a)))
}
@@ -8871,7 +8871,7 @@ pub unsafe fn vld2_p16(a: *const p16) -> poly16x4x2_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld2))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld2))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vld2q_p8(a: *const p8) -> poly8x16x2_t {
transmute(vld2q_s8(transmute(a)))
}
@@ -8884,7 +8884,7 @@ pub unsafe fn vld2q_p8(a: *const p8) -> poly8x16x2_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld2))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld2))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vld2q_p16(a: *const p16) -> poly16x8x2_t {
transmute(vld2q_s16(transmute(a)))
}
@@ -8897,7 +8897,7 @@ pub unsafe fn vld2q_p16(a: *const p16) -> poly16x8x2_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vld2_u64(a: *const u64) -> uint64x1x2_t {
transmute(vld2_s64(transmute(a)))
}
@@ -8910,7 +8910,7 @@ pub unsafe fn vld2_u64(a: *const u64) -> uint64x1x2_t {
#[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))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vld2_p64(a: *const p64) -> poly64x1x2_t {
transmute(vld2_s64(transmute(a)))
}
@@ -9220,7 +9220,7 @@ vld2_dup_s64_(a as _)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld2))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld2r))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vld2_dup_u8(a: *const u8) -> uint8x8x2_t {
transmute(vld2_dup_s8(transmute(a)))
}
@@ -9233,7 +9233,7 @@ pub unsafe fn vld2_dup_u8(a: *const u8) -> uint8x8x2_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld2))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld2r))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vld2_dup_u16(a: *const u16) -> uint16x4x2_t {
transmute(vld2_dup_s16(transmute(a)))
}
@@ -9246,7 +9246,7 @@ pub unsafe fn vld2_dup_u16(a: *const u16) -> uint16x4x2_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld2))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld2r))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vld2_dup_u32(a: *const u32) -> uint32x2x2_t {
transmute(vld2_dup_s32(transmute(a)))
}
@@ -9259,7 +9259,7 @@ pub unsafe fn vld2_dup_u32(a: *const u32) -> uint32x2x2_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld2))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld2r))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vld2q_dup_u8(a: *const u8) -> uint8x16x2_t {
transmute(vld2q_dup_s8(transmute(a)))
}
@@ -9272,7 +9272,7 @@ pub unsafe fn vld2q_dup_u8(a: *const u8) -> uint8x16x2_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld2))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld2r))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vld2q_dup_u16(a: *const u16) -> uint16x8x2_t {
transmute(vld2q_dup_s16(transmute(a)))
}
@@ -9285,7 +9285,7 @@ pub unsafe fn vld2q_dup_u16(a: *const u16) -> uint16x8x2_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld2))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld2r))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vld2q_dup_u32(a: *const u32) -> uint32x4x2_t {
transmute(vld2q_dup_s32(transmute(a)))
}
@@ -9298,7 +9298,7 @@ pub unsafe fn vld2q_dup_u32(a: *const u32) -> uint32x4x2_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld2))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld2r))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vld2_dup_p8(a: *const p8) -> poly8x8x2_t {
transmute(vld2_dup_s8(transmute(a)))
}
@@ -9311,7 +9311,7 @@ pub unsafe fn vld2_dup_p8(a: *const p8) -> poly8x8x2_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld2))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld2r))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vld2_dup_p16(a: *const p16) -> poly16x4x2_t {
transmute(vld2_dup_s16(transmute(a)))
}
@@ -9324,7 +9324,7 @@ pub unsafe fn vld2_dup_p16(a: *const p16) -> poly16x4x2_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld2))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld2r))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vld2q_dup_p8(a: *const p8) -> poly8x16x2_t {
transmute(vld2q_dup_s8(transmute(a)))
}
@@ -9337,7 +9337,7 @@ pub unsafe fn vld2q_dup_p8(a: *const p8) -> poly8x16x2_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld2))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld2r))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vld2q_dup_p16(a: *const p16) -> poly16x8x2_t {
transmute(vld2q_dup_s16(transmute(a)))
}
@@ -9350,7 +9350,7 @@ pub unsafe fn vld2q_dup_p16(a: *const p16) -> poly16x8x2_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld2r))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vld2_dup_u64(a: *const u64) -> uint64x1x2_t {
transmute(vld2_dup_s64(transmute(a)))
}
@@ -9363,7 +9363,7 @@ pub unsafe fn vld2_dup_u64(a: *const u64) -> uint64x1x2_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "aes,v8"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld2r))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vld2_dup_p64(a: *const p64) -> poly64x1x2_t {
transmute(vld2_dup_s64(transmute(a)))
}
@@ -9628,7 +9628,7 @@ vld2q_lane_s32_(b.0, b.1, LANE as i64, a as _)
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld2, LANE = 0))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld2, LANE = 0))]
#[rustc_legacy_const_generics(2)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vld2_lane_u8<const LANE: i32>(a: *const u8, b: uint8x8x2_t) -> uint8x8x2_t {
static_assert_imm3!(LANE);
transmute(vld2_lane_s8::<LANE>(transmute(a), transmute(b)))
@@ -9643,7 +9643,7 @@ pub unsafe fn vld2_lane_u8<const LANE: i32>(a: *const u8, b: uint8x8x2_t) -> uin
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld2, LANE = 0))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld2, LANE = 0))]
#[rustc_legacy_const_generics(2)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vld2_lane_u16<const LANE: i32>(a: *const u16, b: uint16x4x2_t) -> uint16x4x2_t {
static_assert_imm2!(LANE);
transmute(vld2_lane_s16::<LANE>(transmute(a), transmute(b)))
@@ -9658,7 +9658,7 @@ pub unsafe fn vld2_lane_u16<const LANE: i32>(a: *const u16, b: uint16x4x2_t) ->
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld2, LANE = 0))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld2, LANE = 0))]
#[rustc_legacy_const_generics(2)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vld2_lane_u32<const LANE: i32>(a: *const u32, b: uint32x2x2_t) -> uint32x2x2_t {
static_assert_imm1!(LANE);
transmute(vld2_lane_s32::<LANE>(transmute(a), transmute(b)))
@@ -9673,7 +9673,7 @@ pub unsafe fn vld2_lane_u32<const LANE: i32>(a: *const u32, b: uint32x2x2_t) ->
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld2, LANE = 0))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld2, LANE = 0))]
#[rustc_legacy_const_generics(2)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vld2q_lane_u16<const LANE: i32>(a: *const u16, b: uint16x8x2_t) -> uint16x8x2_t {
static_assert_imm3!(LANE);
transmute(vld2q_lane_s16::<LANE>(transmute(a), transmute(b)))
@@ -9688,7 +9688,7 @@ pub unsafe fn vld2q_lane_u16<const LANE: i32>(a: *const u16, b: uint16x8x2_t) ->
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld2, LANE = 0))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld2, LANE = 0))]
#[rustc_legacy_const_generics(2)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vld2q_lane_u32<const LANE: i32>(a: *const u32, b: uint32x4x2_t) -> uint32x4x2_t {
static_assert_imm2!(LANE);
transmute(vld2q_lane_s32::<LANE>(transmute(a), transmute(b)))
@@ -9703,7 +9703,7 @@ pub unsafe fn vld2q_lane_u32<const LANE: i32>(a: *const u32, b: uint32x4x2_t) ->
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld2, LANE = 0))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld2, LANE = 0))]
#[rustc_legacy_const_generics(2)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vld2_lane_p8<const LANE: i32>(a: *const p8, b: poly8x8x2_t) -> poly8x8x2_t {
static_assert_imm3!(LANE);
transmute(vld2_lane_s8::<LANE>(transmute(a), transmute(b)))
@@ -9718,7 +9718,7 @@ pub unsafe fn vld2_lane_p8<const LANE: i32>(a: *const p8, b: poly8x8x2_t) -> pol
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld2, LANE = 0))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld2, LANE = 0))]
#[rustc_legacy_const_generics(2)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vld2_lane_p16<const LANE: i32>(a: *const p16, b: poly16x4x2_t) -> poly16x4x2_t {
static_assert_imm2!(LANE);
transmute(vld2_lane_s16::<LANE>(transmute(a), transmute(b)))
@@ -9733,7 +9733,7 @@ pub unsafe fn vld2_lane_p16<const LANE: i32>(a: *const p16, b: poly16x4x2_t) ->
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld2, LANE = 0))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld2, LANE = 0))]
#[rustc_legacy_const_generics(2)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vld2q_lane_p16<const LANE: i32>(a: *const p16, b: poly16x8x2_t) -> poly16x8x2_t {
static_assert_imm3!(LANE);
transmute(vld2q_lane_s16::<LANE>(transmute(a), transmute(b)))
@@ -10052,7 +10052,7 @@ vld3_s64_(a as _)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld3))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld3))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vld3_u8(a: *const u8) -> uint8x8x3_t {
transmute(vld3_s8(transmute(a)))
}
@@ -10065,7 +10065,7 @@ pub unsafe fn vld3_u8(a: *const u8) -> uint8x8x3_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld3))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld3))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vld3_u16(a: *const u16) -> uint16x4x3_t {
transmute(vld3_s16(transmute(a)))
}
@@ -10078,7 +10078,7 @@ pub unsafe fn vld3_u16(a: *const u16) -> uint16x4x3_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld3))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld3))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vld3_u32(a: *const u32) -> uint32x2x3_t {
transmute(vld3_s32(transmute(a)))
}
@@ -10091,7 +10091,7 @@ pub unsafe fn vld3_u32(a: *const u32) -> uint32x2x3_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld3))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld3))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vld3q_u8(a: *const u8) -> uint8x16x3_t {
transmute(vld3q_s8(transmute(a)))
}
@@ -10104,7 +10104,7 @@ pub unsafe fn vld3q_u8(a: *const u8) -> uint8x16x3_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld3))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld3))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vld3q_u16(a: *const u16) -> uint16x8x3_t {
transmute(vld3q_s16(transmute(a)))
}
@@ -10117,7 +10117,7 @@ pub unsafe fn vld3q_u16(a: *const u16) -> uint16x8x3_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld3))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld3))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vld3q_u32(a: *const u32) -> uint32x4x3_t {
transmute(vld3q_s32(transmute(a)))
}
@@ -10130,7 +10130,7 @@ pub unsafe fn vld3q_u32(a: *const u32) -> uint32x4x3_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld3))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld3))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vld3_p8(a: *const p8) -> poly8x8x3_t {
transmute(vld3_s8(transmute(a)))
}
@@ -10143,7 +10143,7 @@ pub unsafe fn vld3_p8(a: *const p8) -> poly8x8x3_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld3))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld3))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vld3_p16(a: *const p16) -> poly16x4x3_t {
transmute(vld3_s16(transmute(a)))
}
@@ -10156,7 +10156,7 @@ pub unsafe fn vld3_p16(a: *const p16) -> poly16x4x3_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld3))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld3))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vld3q_p8(a: *const p8) -> poly8x16x3_t {
transmute(vld3q_s8(transmute(a)))
}
@@ -10169,7 +10169,7 @@ pub unsafe fn vld3q_p8(a: *const p8) -> poly8x16x3_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld3))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld3))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vld3q_p16(a: *const p16) -> poly16x8x3_t {
transmute(vld3q_s16(transmute(a)))
}
@@ -10182,7 +10182,7 @@ pub unsafe fn vld3q_p16(a: *const p16) -> poly16x8x3_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vld3_u64(a: *const u64) -> uint64x1x3_t {
transmute(vld3_s64(transmute(a)))
}
@@ -10195,7 +10195,7 @@ pub unsafe fn vld3_u64(a: *const u64) -> uint64x1x3_t {
#[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))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vld3_p64(a: *const p64) -> poly64x1x3_t {
transmute(vld3_s64(transmute(a)))
}
@@ -10505,7 +10505,7 @@ vld3_dup_s64_(a as _)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld3))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld3r))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vld3_dup_u8(a: *const u8) -> uint8x8x3_t {
transmute(vld3_dup_s8(transmute(a)))
}
@@ -10518,7 +10518,7 @@ pub unsafe fn vld3_dup_u8(a: *const u8) -> uint8x8x3_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld3))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld3r))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vld3_dup_u16(a: *const u16) -> uint16x4x3_t {
transmute(vld3_dup_s16(transmute(a)))
}
@@ -10531,7 +10531,7 @@ pub unsafe fn vld3_dup_u16(a: *const u16) -> uint16x4x3_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld3))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld3r))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vld3_dup_u32(a: *const u32) -> uint32x2x3_t {
transmute(vld3_dup_s32(transmute(a)))
}
@@ -10544,7 +10544,7 @@ pub unsafe fn vld3_dup_u32(a: *const u32) -> uint32x2x3_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld3))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld3r))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vld3q_dup_u8(a: *const u8) -> uint8x16x3_t {
transmute(vld3q_dup_s8(transmute(a)))
}
@@ -10557,7 +10557,7 @@ pub unsafe fn vld3q_dup_u8(a: *const u8) -> uint8x16x3_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld3))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld3r))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vld3q_dup_u16(a: *const u16) -> uint16x8x3_t {
transmute(vld3q_dup_s16(transmute(a)))
}
@@ -10570,7 +10570,7 @@ pub unsafe fn vld3q_dup_u16(a: *const u16) -> uint16x8x3_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld3))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld3r))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vld3q_dup_u32(a: *const u32) -> uint32x4x3_t {
transmute(vld3q_dup_s32(transmute(a)))
}
@@ -10583,7 +10583,7 @@ pub unsafe fn vld3q_dup_u32(a: *const u32) -> uint32x4x3_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld3))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld3r))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vld3_dup_p8(a: *const p8) -> poly8x8x3_t {
transmute(vld3_dup_s8(transmute(a)))
}
@@ -10596,7 +10596,7 @@ pub unsafe fn vld3_dup_p8(a: *const p8) -> poly8x8x3_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld3))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld3r))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vld3_dup_p16(a: *const p16) -> poly16x4x3_t {
transmute(vld3_dup_s16(transmute(a)))
}
@@ -10609,7 +10609,7 @@ pub unsafe fn vld3_dup_p16(a: *const p16) -> poly16x4x3_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld3))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld3r))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vld3q_dup_p8(a: *const p8) -> poly8x16x3_t {
transmute(vld3q_dup_s8(transmute(a)))
}
@@ -10622,7 +10622,7 @@ pub unsafe fn vld3q_dup_p8(a: *const p8) -> poly8x16x3_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld3))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld3r))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vld3q_dup_p16(a: *const p16) -> poly16x8x3_t {
transmute(vld3q_dup_s16(transmute(a)))
}
@@ -10635,7 +10635,7 @@ pub unsafe fn vld3q_dup_p16(a: *const p16) -> poly16x8x3_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld3r))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vld3_dup_u64(a: *const u64) -> uint64x1x3_t {
transmute(vld3_dup_s64(transmute(a)))
}
@@ -10648,7 +10648,7 @@ pub unsafe fn vld3_dup_u64(a: *const u64) -> uint64x1x3_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "aes,v8"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld3r))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vld3_dup_p64(a: *const p64) -> poly64x1x3_t {
transmute(vld3_dup_s64(transmute(a)))
}
@@ -10913,7 +10913,7 @@ vld3q_lane_s32_(b.0, b.1, b.2, LANE as i64, a as _)
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld3, LANE = 0))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld3, LANE = 0))]
#[rustc_legacy_const_generics(2)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vld3_lane_u8<const LANE: i32>(a: *const u8, b: uint8x8x3_t) -> uint8x8x3_t {
static_assert_imm3!(LANE);
transmute(vld3_lane_s8::<LANE>(transmute(a), transmute(b)))
@@ -10928,7 +10928,7 @@ pub unsafe fn vld3_lane_u8<const LANE: i32>(a: *const u8, b: uint8x8x3_t) -> uin
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld3, LANE = 0))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld3, LANE = 0))]
#[rustc_legacy_const_generics(2)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vld3_lane_u16<const LANE: i32>(a: *const u16, b: uint16x4x3_t) -> uint16x4x3_t {
static_assert_imm2!(LANE);
transmute(vld3_lane_s16::<LANE>(transmute(a), transmute(b)))
@@ -10943,7 +10943,7 @@ pub unsafe fn vld3_lane_u16<const LANE: i32>(a: *const u16, b: uint16x4x3_t) ->
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld3, LANE = 0))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld3, LANE = 0))]
#[rustc_legacy_const_generics(2)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vld3_lane_u32<const LANE: i32>(a: *const u32, b: uint32x2x3_t) -> uint32x2x3_t {
static_assert_imm1!(LANE);
transmute(vld3_lane_s32::<LANE>(transmute(a), transmute(b)))
@@ -10958,7 +10958,7 @@ pub unsafe fn vld3_lane_u32<const LANE: i32>(a: *const u32, b: uint32x2x3_t) ->
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld3, LANE = 0))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld3, LANE = 0))]
#[rustc_legacy_const_generics(2)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vld3q_lane_u16<const LANE: i32>(a: *const u16, b: uint16x8x3_t) -> uint16x8x3_t {
static_assert_imm3!(LANE);
transmute(vld3q_lane_s16::<LANE>(transmute(a), transmute(b)))
@@ -10973,7 +10973,7 @@ pub unsafe fn vld3q_lane_u16<const LANE: i32>(a: *const u16, b: uint16x8x3_t) ->
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld3, LANE = 0))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld3, LANE = 0))]
#[rustc_legacy_const_generics(2)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vld3q_lane_u32<const LANE: i32>(a: *const u32, b: uint32x4x3_t) -> uint32x4x3_t {
static_assert_imm2!(LANE);
transmute(vld3q_lane_s32::<LANE>(transmute(a), transmute(b)))
@@ -10988,7 +10988,7 @@ pub unsafe fn vld3q_lane_u32<const LANE: i32>(a: *const u32, b: uint32x4x3_t) ->
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld3, LANE = 0))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld3, LANE = 0))]
#[rustc_legacy_const_generics(2)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vld3_lane_p8<const LANE: i32>(a: *const p8, b: poly8x8x3_t) -> poly8x8x3_t {
static_assert_imm3!(LANE);
transmute(vld3_lane_s8::<LANE>(transmute(a), transmute(b)))
@@ -11003,7 +11003,7 @@ pub unsafe fn vld3_lane_p8<const LANE: i32>(a: *const p8, b: poly8x8x3_t) -> pol
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld3, LANE = 0))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld3, LANE = 0))]
#[rustc_legacy_const_generics(2)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vld3_lane_p16<const LANE: i32>(a: *const p16, b: poly16x4x3_t) -> poly16x4x3_t {
static_assert_imm2!(LANE);
transmute(vld3_lane_s16::<LANE>(transmute(a), transmute(b)))
@@ -11018,7 +11018,7 @@ pub unsafe fn vld3_lane_p16<const LANE: i32>(a: *const p16, b: poly16x4x3_t) ->
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld3, LANE = 0))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld3, LANE = 0))]
#[rustc_legacy_const_generics(2)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vld3q_lane_p16<const LANE: i32>(a: *const p16, b: poly16x8x3_t) -> poly16x8x3_t {
static_assert_imm3!(LANE);
transmute(vld3q_lane_s16::<LANE>(transmute(a), transmute(b)))
@@ -11337,7 +11337,7 @@ vld4_s64_(a as _)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld4))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld4))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vld4_u8(a: *const u8) -> uint8x8x4_t {
transmute(vld4_s8(transmute(a)))
}
@@ -11350,7 +11350,7 @@ pub unsafe fn vld4_u8(a: *const u8) -> uint8x8x4_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld4))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld4))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vld4_u16(a: *const u16) -> uint16x4x4_t {
transmute(vld4_s16(transmute(a)))
}
@@ -11363,7 +11363,7 @@ pub unsafe fn vld4_u16(a: *const u16) -> uint16x4x4_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld4))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld4))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vld4_u32(a: *const u32) -> uint32x2x4_t {
transmute(vld4_s32(transmute(a)))
}
@@ -11376,7 +11376,7 @@ pub unsafe fn vld4_u32(a: *const u32) -> uint32x2x4_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld4))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld4))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vld4q_u8(a: *const u8) -> uint8x16x4_t {
transmute(vld4q_s8(transmute(a)))
}
@@ -11389,7 +11389,7 @@ pub unsafe fn vld4q_u8(a: *const u8) -> uint8x16x4_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld4))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld4))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vld4q_u16(a: *const u16) -> uint16x8x4_t {
transmute(vld4q_s16(transmute(a)))
}
@@ -11402,7 +11402,7 @@ pub unsafe fn vld4q_u16(a: *const u16) -> uint16x8x4_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld4))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld4))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vld4q_u32(a: *const u32) -> uint32x4x4_t {
transmute(vld4q_s32(transmute(a)))
}
@@ -11415,7 +11415,7 @@ pub unsafe fn vld4q_u32(a: *const u32) -> uint32x4x4_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld4))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld4))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vld4_p8(a: *const p8) -> poly8x8x4_t {
transmute(vld4_s8(transmute(a)))
}
@@ -11428,7 +11428,7 @@ pub unsafe fn vld4_p8(a: *const p8) -> poly8x8x4_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld4))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld4))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vld4_p16(a: *const p16) -> poly16x4x4_t {
transmute(vld4_s16(transmute(a)))
}
@@ -11441,7 +11441,7 @@ pub unsafe fn vld4_p16(a: *const p16) -> poly16x4x4_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld4))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld4))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vld4q_p8(a: *const p8) -> poly8x16x4_t {
transmute(vld4q_s8(transmute(a)))
}
@@ -11454,7 +11454,7 @@ pub unsafe fn vld4q_p8(a: *const p8) -> poly8x16x4_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld4))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld4))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vld4q_p16(a: *const p16) -> poly16x8x4_t {
transmute(vld4q_s16(transmute(a)))
}
@@ -11467,7 +11467,7 @@ pub unsafe fn vld4q_p16(a: *const p16) -> poly16x8x4_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vld4_u64(a: *const u64) -> uint64x1x4_t {
transmute(vld4_s64(transmute(a)))
}
@@ -11480,7 +11480,7 @@ pub unsafe fn vld4_u64(a: *const u64) -> uint64x1x4_t {
#[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))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vld4_p64(a: *const p64) -> poly64x1x4_t {
transmute(vld4_s64(transmute(a)))
}
@@ -11790,7 +11790,7 @@ vld4_dup_s64_(a as _)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld4))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld4r))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vld4_dup_u8(a: *const u8) -> uint8x8x4_t {
transmute(vld4_dup_s8(transmute(a)))
}
@@ -11803,7 +11803,7 @@ pub unsafe fn vld4_dup_u8(a: *const u8) -> uint8x8x4_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld4))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld4r))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vld4_dup_u16(a: *const u16) -> uint16x4x4_t {
transmute(vld4_dup_s16(transmute(a)))
}
@@ -11816,7 +11816,7 @@ pub unsafe fn vld4_dup_u16(a: *const u16) -> uint16x4x4_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld4))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld4r))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vld4_dup_u32(a: *const u32) -> uint32x2x4_t {
transmute(vld4_dup_s32(transmute(a)))
}
@@ -11829,7 +11829,7 @@ pub unsafe fn vld4_dup_u32(a: *const u32) -> uint32x2x4_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld4))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld4r))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vld4q_dup_u8(a: *const u8) -> uint8x16x4_t {
transmute(vld4q_dup_s8(transmute(a)))
}
@@ -11842,7 +11842,7 @@ pub unsafe fn vld4q_dup_u8(a: *const u8) -> uint8x16x4_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld4))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld4r))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vld4q_dup_u16(a: *const u16) -> uint16x8x4_t {
transmute(vld4q_dup_s16(transmute(a)))
}
@@ -11855,7 +11855,7 @@ pub unsafe fn vld4q_dup_u16(a: *const u16) -> uint16x8x4_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld4))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld4r))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vld4q_dup_u32(a: *const u32) -> uint32x4x4_t {
transmute(vld4q_dup_s32(transmute(a)))
}
@@ -11868,7 +11868,7 @@ pub unsafe fn vld4q_dup_u32(a: *const u32) -> uint32x4x4_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld4))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld4r))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vld4_dup_p8(a: *const p8) -> poly8x8x4_t {
transmute(vld4_dup_s8(transmute(a)))
}
@@ -11881,7 +11881,7 @@ pub unsafe fn vld4_dup_p8(a: *const p8) -> poly8x8x4_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld4))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld4r))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vld4_dup_p16(a: *const p16) -> poly16x4x4_t {
transmute(vld4_dup_s16(transmute(a)))
}
@@ -11894,7 +11894,7 @@ pub unsafe fn vld4_dup_p16(a: *const p16) -> poly16x4x4_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld4))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld4r))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vld4q_dup_p8(a: *const p8) -> poly8x16x4_t {
transmute(vld4q_dup_s8(transmute(a)))
}
@@ -11907,7 +11907,7 @@ pub unsafe fn vld4q_dup_p8(a: *const p8) -> poly8x16x4_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld4))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld4r))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vld4q_dup_p16(a: *const p16) -> poly16x8x4_t {
transmute(vld4q_dup_s16(transmute(a)))
}
@@ -11920,7 +11920,7 @@ pub unsafe fn vld4q_dup_p16(a: *const p16) -> poly16x8x4_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld4r))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vld4_dup_u64(a: *const u64) -> uint64x1x4_t {
transmute(vld4_dup_s64(transmute(a)))
}
@@ -11933,7 +11933,7 @@ pub unsafe fn vld4_dup_u64(a: *const u64) -> uint64x1x4_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "aes,v8"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld4r))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vld4_dup_p64(a: *const p64) -> poly64x1x4_t {
transmute(vld4_dup_s64(transmute(a)))
}
@@ -12198,7 +12198,7 @@ vld4q_lane_s32_(b.0, b.1, b.2, b.3, LANE as i64, a as _)
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld4, LANE = 0))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld4, LANE = 0))]
#[rustc_legacy_const_generics(2)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vld4_lane_u8<const LANE: i32>(a: *const u8, b: uint8x8x4_t) -> uint8x8x4_t {
static_assert_imm3!(LANE);
transmute(vld4_lane_s8::<LANE>(transmute(a), transmute(b)))
@@ -12213,7 +12213,7 @@ pub unsafe fn vld4_lane_u8<const LANE: i32>(a: *const u8, b: uint8x8x4_t) -> uin
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld4, LANE = 0))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld4, LANE = 0))]
#[rustc_legacy_const_generics(2)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vld4_lane_u16<const LANE: i32>(a: *const u16, b: uint16x4x4_t) -> uint16x4x4_t {
static_assert_imm2!(LANE);
transmute(vld4_lane_s16::<LANE>(transmute(a), transmute(b)))
@@ -12228,7 +12228,7 @@ pub unsafe fn vld4_lane_u16<const LANE: i32>(a: *const u16, b: uint16x4x4_t) ->
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld4, LANE = 0))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld4, LANE = 0))]
#[rustc_legacy_const_generics(2)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vld4_lane_u32<const LANE: i32>(a: *const u32, b: uint32x2x4_t) -> uint32x2x4_t {
static_assert_imm1!(LANE);
transmute(vld4_lane_s32::<LANE>(transmute(a), transmute(b)))
@@ -12243,7 +12243,7 @@ pub unsafe fn vld4_lane_u32<const LANE: i32>(a: *const u32, b: uint32x2x4_t) ->
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld4, LANE = 0))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld4, LANE = 0))]
#[rustc_legacy_const_generics(2)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vld4q_lane_u16<const LANE: i32>(a: *const u16, b: uint16x8x4_t) -> uint16x8x4_t {
static_assert_imm3!(LANE);
transmute(vld4q_lane_s16::<LANE>(transmute(a), transmute(b)))
@@ -12258,7 +12258,7 @@ pub unsafe fn vld4q_lane_u16<const LANE: i32>(a: *const u16, b: uint16x8x4_t) ->
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld4, LANE = 0))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld4, LANE = 0))]
#[rustc_legacy_const_generics(2)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vld4q_lane_u32<const LANE: i32>(a: *const u32, b: uint32x4x4_t) -> uint32x4x4_t {
static_assert_imm2!(LANE);
transmute(vld4q_lane_s32::<LANE>(transmute(a), transmute(b)))
@@ -12273,7 +12273,7 @@ pub unsafe fn vld4q_lane_u32<const LANE: i32>(a: *const u32, b: uint32x4x4_t) ->
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld4, LANE = 0))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld4, LANE = 0))]
#[rustc_legacy_const_generics(2)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vld4_lane_p8<const LANE: i32>(a: *const p8, b: poly8x8x4_t) -> poly8x8x4_t {
static_assert_imm3!(LANE);
transmute(vld4_lane_s8::<LANE>(transmute(a), transmute(b)))
@@ -12288,7 +12288,7 @@ pub unsafe fn vld4_lane_p8<const LANE: i32>(a: *const p8, b: poly8x8x4_t) -> pol
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld4, LANE = 0))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld4, LANE = 0))]
#[rustc_legacy_const_generics(2)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vld4_lane_p16<const LANE: i32>(a: *const p16, b: poly16x4x4_t) -> poly16x4x4_t {
static_assert_imm2!(LANE);
transmute(vld4_lane_s16::<LANE>(transmute(a), transmute(b)))
@@ -12303,7 +12303,7 @@ pub unsafe fn vld4_lane_p16<const LANE: i32>(a: *const p16, b: poly16x4x4_t) ->
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld4, LANE = 0))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld4, LANE = 0))]
#[rustc_legacy_const_generics(2)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vld4q_lane_p16<const LANE: i32>(a: *const p16, b: poly16x8x4_t) -> poly16x8x4_t {
static_assert_imm3!(LANE);
transmute(vld4q_lane_s16::<LANE>(transmute(a), transmute(b)))
@@ -12392,7 +12392,7 @@ vld4q_lane_f32_(b.0, b.1, b.2, b.3, LANE as i64, a as _)
#[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)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vst1_lane_s8<const LANE: i32>(a: *mut i8, b: int8x8_t) {
static_assert_imm3!(LANE);
*a = simd_extract(b, LANE as u32);
@@ -12407,7 +12407,7 @@ pub unsafe fn vst1_lane_s8<const LANE: i32>(a: *mut i8, b: int8x8_t) {
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop, LANE = 0))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop, LANE = 0))]
#[rustc_legacy_const_generics(2)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vst1_lane_s16<const LANE: i32>(a: *mut i16, b: int16x4_t) {
static_assert_imm2!(LANE);
*a = simd_extract(b, LANE as u32);
@@ -12422,7 +12422,7 @@ pub unsafe fn vst1_lane_s16<const LANE: i32>(a: *mut i16, b: int16x4_t) {
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop, LANE = 0))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop, LANE = 0))]
#[rustc_legacy_const_generics(2)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vst1_lane_s32<const LANE: i32>(a: *mut i32, b: int32x2_t) {
static_assert_imm1!(LANE);
*a = simd_extract(b, LANE as u32);
@@ -12437,7 +12437,7 @@ pub unsafe fn vst1_lane_s32<const LANE: i32>(a: *mut i32, b: int32x2_t) {
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop, LANE = 0))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop, LANE = 0))]
#[rustc_legacy_const_generics(2)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vst1_lane_s64<const LANE: i32>(a: *mut i64, b: int64x1_t) {
static_assert!(LANE : i32 where LANE == 0);
*a = simd_extract(b, LANE as u32);
@@ -12452,7 +12452,7 @@ pub unsafe fn vst1_lane_s64<const LANE: i32>(a: *mut i64, b: int64x1_t) {
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop, LANE = 0))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop, LANE = 0))]
#[rustc_legacy_const_generics(2)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vst1q_lane_s8<const LANE: i32>(a: *mut i8, b: int8x16_t) {
static_assert_imm4!(LANE);
*a = simd_extract(b, LANE as u32);
@@ -12467,7 +12467,7 @@ pub unsafe fn vst1q_lane_s8<const LANE: i32>(a: *mut i8, b: int8x16_t) {
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop, LANE = 0))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop, LANE = 0))]
#[rustc_legacy_const_generics(2)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vst1q_lane_s16<const LANE: i32>(a: *mut i16, b: int16x8_t) {
static_assert_imm3!(LANE);
*a = simd_extract(b, LANE as u32);
@@ -12482,7 +12482,7 @@ pub unsafe fn vst1q_lane_s16<const LANE: i32>(a: *mut i16, b: int16x8_t) {
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop, LANE = 0))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop, LANE = 0))]
#[rustc_legacy_const_generics(2)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vst1q_lane_s32<const LANE: i32>(a: *mut i32, b: int32x4_t) {
static_assert_imm2!(LANE);
*a = simd_extract(b, LANE as u32);
@@ -12497,7 +12497,7 @@ pub unsafe fn vst1q_lane_s32<const LANE: i32>(a: *mut i32, b: int32x4_t) {
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop, LANE = 0))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop, LANE = 0))]
#[rustc_legacy_const_generics(2)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vst1q_lane_s64<const LANE: i32>(a: *mut i64, b: int64x2_t) {
static_assert_imm1!(LANE);
*a = simd_extract(b, LANE as u32);
@@ -12512,7 +12512,7 @@ pub unsafe fn vst1q_lane_s64<const LANE: i32>(a: *mut i64, b: int64x2_t) {
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop, LANE = 0))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop, LANE = 0))]
#[rustc_legacy_const_generics(2)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vst1_lane_u8<const LANE: i32>(a: *mut u8, b: uint8x8_t) {
static_assert_imm3!(LANE);
*a = simd_extract(b, LANE as u32);
@@ -12527,7 +12527,7 @@ pub unsafe fn vst1_lane_u8<const LANE: i32>(a: *mut u8, b: uint8x8_t) {
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop, LANE = 0))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop, LANE = 0))]
#[rustc_legacy_const_generics(2)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vst1_lane_u16<const LANE: i32>(a: *mut u16, b: uint16x4_t) {
static_assert_imm2!(LANE);
*a = simd_extract(b, LANE as u32);
@@ -12542,7 +12542,7 @@ pub unsafe fn vst1_lane_u16<const LANE: i32>(a: *mut u16, b: uint16x4_t) {
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop, LANE = 0))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop, LANE = 0))]
#[rustc_legacy_const_generics(2)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vst1_lane_u32<const LANE: i32>(a: *mut u32, b: uint32x2_t) {
static_assert_imm1!(LANE);
*a = simd_extract(b, LANE as u32);
@@ -12557,7 +12557,7 @@ pub unsafe fn vst1_lane_u32<const LANE: i32>(a: *mut u32, b: uint32x2_t) {
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop, LANE = 0))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop, LANE = 0))]
#[rustc_legacy_const_generics(2)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vst1_lane_u64<const LANE: i32>(a: *mut u64, b: uint64x1_t) {
static_assert!(LANE : i32 where LANE == 0);
*a = simd_extract(b, LANE as u32);
@@ -12572,7 +12572,7 @@ pub unsafe fn vst1_lane_u64<const LANE: i32>(a: *mut u64, b: uint64x1_t) {
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop, LANE = 0))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop, LANE = 0))]
#[rustc_legacy_const_generics(2)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vst1q_lane_u8<const LANE: i32>(a: *mut u8, b: uint8x16_t) {
static_assert_imm4!(LANE);
*a = simd_extract(b, LANE as u32);
@@ -12587,7 +12587,7 @@ pub unsafe fn vst1q_lane_u8<const LANE: i32>(a: *mut u8, b: uint8x16_t) {
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop, LANE = 0))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop, LANE = 0))]
#[rustc_legacy_const_generics(2)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vst1q_lane_u16<const LANE: i32>(a: *mut u16, b: uint16x8_t) {
static_assert_imm3!(LANE);
*a = simd_extract(b, LANE as u32);
@@ -12602,7 +12602,7 @@ pub unsafe fn vst1q_lane_u16<const LANE: i32>(a: *mut u16, b: uint16x8_t) {
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop, LANE = 0))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop, LANE = 0))]
#[rustc_legacy_const_generics(2)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vst1q_lane_u32<const LANE: i32>(a: *mut u32, b: uint32x4_t) {
static_assert_imm2!(LANE);
*a = simd_extract(b, LANE as u32);
@@ -12617,7 +12617,7 @@ pub unsafe fn vst1q_lane_u32<const LANE: i32>(a: *mut u32, b: uint32x4_t) {
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop, LANE = 0))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop, LANE = 0))]
#[rustc_legacy_const_generics(2)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vst1q_lane_u64<const LANE: i32>(a: *mut u64, b: uint64x2_t) {
static_assert_imm1!(LANE);
*a = simd_extract(b, LANE as u32);
@@ -12632,7 +12632,7 @@ pub unsafe fn vst1q_lane_u64<const LANE: i32>(a: *mut u64, b: uint64x2_t) {
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop, LANE = 0))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop, LANE = 0))]
#[rustc_legacy_const_generics(2)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vst1_lane_p8<const LANE: i32>(a: *mut p8, b: poly8x8_t) {
static_assert_imm3!(LANE);
*a = simd_extract(b, LANE as u32);
@@ -12647,7 +12647,7 @@ pub unsafe fn vst1_lane_p8<const LANE: i32>(a: *mut p8, b: poly8x8_t) {
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop, LANE = 0))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop, LANE = 0))]
#[rustc_legacy_const_generics(2)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vst1_lane_p16<const LANE: i32>(a: *mut p16, b: poly16x4_t) {
static_assert_imm2!(LANE);
*a = simd_extract(b, LANE as u32);
@@ -12662,7 +12662,7 @@ pub unsafe fn vst1_lane_p16<const LANE: i32>(a: *mut p16, b: poly16x4_t) {
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop, LANE = 0))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop, LANE = 0))]
#[rustc_legacy_const_generics(2)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vst1q_lane_p8<const LANE: i32>(a: *mut p8, b: poly8x16_t) {
static_assert_imm4!(LANE);
*a = simd_extract(b, LANE as u32);
@@ -12677,7 +12677,7 @@ pub unsafe fn vst1q_lane_p8<const LANE: i32>(a: *mut p8, b: poly8x16_t) {
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop, LANE = 0))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop, LANE = 0))]
#[rustc_legacy_const_generics(2)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vst1q_lane_p16<const LANE: i32>(a: *mut p16, b: poly16x8_t) {
static_assert_imm3!(LANE);
*a = simd_extract(b, LANE as u32);
@@ -12692,7 +12692,7 @@ pub unsafe fn vst1q_lane_p16<const LANE: i32>(a: *mut p16, b: poly16x8_t) {
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop, LANE = 0))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop, LANE = 0))]
#[rustc_legacy_const_generics(2)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vst1_lane_p64<const LANE: i32>(a: *mut p64, b: poly64x1_t) {
static_assert!(LANE : i32 where LANE == 0);
*a = simd_extract(b, LANE as u32);
@@ -12707,7 +12707,7 @@ pub unsafe fn vst1_lane_p64<const LANE: i32>(a: *mut p64, b: poly64x1_t) {
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop, LANE = 0))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop, LANE = 0))]
#[rustc_legacy_const_generics(2)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vst1q_lane_p64<const LANE: i32>(a: *mut p64, b: poly64x2_t) {
static_assert_imm1!(LANE);
*a = simd_extract(b, LANE as u32);
@@ -12722,7 +12722,7 @@ pub unsafe fn vst1q_lane_p64<const LANE: i32>(a: *mut p64, b: poly64x2_t) {
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop, LANE = 0))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop, LANE = 0))]
#[rustc_legacy_const_generics(2)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vst1_lane_f32<const LANE: i32>(a: *mut f32, b: float32x2_t) {
static_assert_imm1!(LANE);
*a = simd_extract(b, LANE as u32);
@@ -12737,7 +12737,7 @@ pub unsafe fn vst1_lane_f32<const LANE: i32>(a: *mut f32, b: float32x2_t) {
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop, LANE = 0))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop, LANE = 0))]
#[rustc_legacy_const_generics(2)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vst1q_lane_f32<const LANE: i32>(a: *mut f32, b: float32x4_t) {
static_assert_imm2!(LANE);
*a = simd_extract(b, LANE as u32);
@@ -13543,7 +13543,7 @@ vst1q_s64_x4_(b.0, b.1, b.2, b.3, a)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst1))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vst1_u8_x2(a: *mut u8, b: uint8x8x2_t) {
vst1_s8_x2(transmute(a), transmute(b))
}
@@ -13556,7 +13556,7 @@ pub unsafe fn vst1_u8_x2(a: *mut u8, b: uint8x8x2_t) {
#[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))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vst1_u16_x2(a: *mut u16, b: uint16x4x2_t) {
vst1_s16_x2(transmute(a), transmute(b))
}
@@ -13569,7 +13569,7 @@ pub unsafe fn vst1_u16_x2(a: *mut u16, b: uint16x4x2_t) {
#[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))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vst1_u32_x2(a: *mut u32, b: uint32x2x2_t) {
vst1_s32_x2(transmute(a), transmute(b))
}
@@ -13582,7 +13582,7 @@ pub unsafe fn vst1_u32_x2(a: *mut u32, b: uint32x2x2_t) {
#[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))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vst1_u64_x2(a: *mut u64, b: uint64x1x2_t) {
vst1_s64_x2(transmute(a), transmute(b))
}
@@ -13595,7 +13595,7 @@ pub unsafe fn vst1_u64_x2(a: *mut u64, b: uint64x1x2_t) {
#[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))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vst1q_u8_x2(a: *mut u8, b: uint8x16x2_t) {
vst1q_s8_x2(transmute(a), transmute(b))
}
@@ -13608,7 +13608,7 @@ pub unsafe fn vst1q_u8_x2(a: *mut u8, b: uint8x16x2_t) {
#[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))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vst1q_u16_x2(a: *mut u16, b: uint16x8x2_t) {
vst1q_s16_x2(transmute(a), transmute(b))
}
@@ -13621,7 +13621,7 @@ pub unsafe fn vst1q_u16_x2(a: *mut u16, b: uint16x8x2_t) {
#[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))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vst1q_u32_x2(a: *mut u32, b: uint32x4x2_t) {
vst1q_s32_x2(transmute(a), transmute(b))
}
@@ -13634,7 +13634,7 @@ pub unsafe fn vst1q_u32_x2(a: *mut u32, b: uint32x4x2_t) {
#[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))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vst1q_u64_x2(a: *mut u64, b: uint64x2x2_t) {
vst1q_s64_x2(transmute(a), transmute(b))
}
@@ -13647,7 +13647,7 @@ pub unsafe fn vst1q_u64_x2(a: *mut u64, b: uint64x2x2_t) {
#[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))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vst1_u8_x3(a: *mut u8, b: uint8x8x3_t) {
vst1_s8_x3(transmute(a), transmute(b))
}
@@ -13660,7 +13660,7 @@ pub unsafe fn vst1_u8_x3(a: *mut u8, b: uint8x8x3_t) {
#[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))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vst1_u16_x3(a: *mut u16, b: uint16x4x3_t) {
vst1_s16_x3(transmute(a), transmute(b))
}
@@ -13673,7 +13673,7 @@ pub unsafe fn vst1_u16_x3(a: *mut u16, b: uint16x4x3_t) {
#[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))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vst1_u32_x3(a: *mut u32, b: uint32x2x3_t) {
vst1_s32_x3(transmute(a), transmute(b))
}
@@ -13686,7 +13686,7 @@ pub unsafe fn vst1_u32_x3(a: *mut u32, b: uint32x2x3_t) {
#[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))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vst1_u64_x3(a: *mut u64, b: uint64x1x3_t) {
vst1_s64_x3(transmute(a), transmute(b))
}
@@ -13699,7 +13699,7 @@ pub unsafe fn vst1_u64_x3(a: *mut u64, b: uint64x1x3_t) {
#[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))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vst1q_u8_x3(a: *mut u8, b: uint8x16x3_t) {
vst1q_s8_x3(transmute(a), transmute(b))
}
@@ -13712,7 +13712,7 @@ pub unsafe fn vst1q_u8_x3(a: *mut u8, b: uint8x16x3_t) {
#[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))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vst1q_u16_x3(a: *mut u16, b: uint16x8x3_t) {
vst1q_s16_x3(transmute(a), transmute(b))
}
@@ -13725,7 +13725,7 @@ pub unsafe fn vst1q_u16_x3(a: *mut u16, b: uint16x8x3_t) {
#[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))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vst1q_u32_x3(a: *mut u32, b: uint32x4x3_t) {
vst1q_s32_x3(transmute(a), transmute(b))
}
@@ -13738,7 +13738,7 @@ pub unsafe fn vst1q_u32_x3(a: *mut u32, b: uint32x4x3_t) {
#[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))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vst1q_u64_x3(a: *mut u64, b: uint64x2x3_t) {
vst1q_s64_x3(transmute(a), transmute(b))
}
@@ -13751,7 +13751,7 @@ pub unsafe fn vst1q_u64_x3(a: *mut u64, b: uint64x2x3_t) {
#[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))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vst1_u8_x4(a: *mut u8, b: uint8x8x4_t) {
vst1_s8_x4(transmute(a), transmute(b))
}
@@ -13764,7 +13764,7 @@ pub unsafe fn vst1_u8_x4(a: *mut u8, b: uint8x8x4_t) {
#[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))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vst1_u16_x4(a: *mut u16, b: uint16x4x4_t) {
vst1_s16_x4(transmute(a), transmute(b))
}
@@ -13777,7 +13777,7 @@ pub unsafe fn vst1_u16_x4(a: *mut u16, b: uint16x4x4_t) {
#[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))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vst1_u32_x4(a: *mut u32, b: uint32x2x4_t) {
vst1_s32_x4(transmute(a), transmute(b))
}
@@ -13790,7 +13790,7 @@ pub unsafe fn vst1_u32_x4(a: *mut u32, b: uint32x2x4_t) {
#[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))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vst1_u64_x4(a: *mut u64, b: uint64x1x4_t) {
vst1_s64_x4(transmute(a), transmute(b))
}
@@ -13803,7 +13803,7 @@ pub unsafe fn vst1_u64_x4(a: *mut u64, b: uint64x1x4_t) {
#[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))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vst1q_u8_x4(a: *mut u8, b: uint8x16x4_t) {
vst1q_s8_x4(transmute(a), transmute(b))
}
@@ -13816,7 +13816,7 @@ pub unsafe fn vst1q_u8_x4(a: *mut u8, b: uint8x16x4_t) {
#[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))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vst1q_u16_x4(a: *mut u16, b: uint16x8x4_t) {
vst1q_s16_x4(transmute(a), transmute(b))
}
@@ -13829,7 +13829,7 @@ pub unsafe fn vst1q_u16_x4(a: *mut u16, b: uint16x8x4_t) {
#[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))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vst1q_u32_x4(a: *mut u32, b: uint32x4x4_t) {
vst1q_s32_x4(transmute(a), transmute(b))
}
@@ -13842,7 +13842,7 @@ pub unsafe fn vst1q_u32_x4(a: *mut u32, b: uint32x4x4_t) {
#[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))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vst1q_u64_x4(a: *mut u64, b: uint64x2x4_t) {
vst1q_s64_x4(transmute(a), transmute(b))
}
@@ -13855,7 +13855,7 @@ pub unsafe fn vst1q_u64_x4(a: *mut u64, b: uint64x2x4_t) {
#[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))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vst1_p8_x2(a: *mut p8, b: poly8x8x2_t) {
vst1_s8_x2(transmute(a), transmute(b))
}
@@ -13868,7 +13868,7 @@ pub unsafe fn vst1_p8_x2(a: *mut p8, b: poly8x8x2_t) {
#[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))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vst1_p8_x3(a: *mut p8, b: poly8x8x3_t) {
vst1_s8_x3(transmute(a), transmute(b))
}
@@ -13881,7 +13881,7 @@ pub unsafe fn vst1_p8_x3(a: *mut p8, b: poly8x8x3_t) {
#[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))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vst1_p8_x4(a: *mut p8, b: poly8x8x4_t) {
vst1_s8_x4(transmute(a), transmute(b))
}
@@ -13894,7 +13894,7 @@ pub unsafe fn vst1_p8_x4(a: *mut p8, b: poly8x8x4_t) {
#[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))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vst1q_p8_x2(a: *mut p8, b: poly8x16x2_t) {
vst1q_s8_x2(transmute(a), transmute(b))
}
@@ -13907,7 +13907,7 @@ pub unsafe fn vst1q_p8_x2(a: *mut p8, b: poly8x16x2_t) {
#[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))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vst1q_p8_x3(a: *mut p8, b: poly8x16x3_t) {
vst1q_s8_x3(transmute(a), transmute(b))
}
@@ -13920,7 +13920,7 @@ pub unsafe fn vst1q_p8_x3(a: *mut p8, b: poly8x16x3_t) {
#[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))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vst1q_p8_x4(a: *mut p8, b: poly8x16x4_t) {
vst1q_s8_x4(transmute(a), transmute(b))
}
@@ -13933,7 +13933,7 @@ pub unsafe fn vst1q_p8_x4(a: *mut p8, b: poly8x16x4_t) {
#[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))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vst1_p16_x2(a: *mut p16, b: poly16x4x2_t) {
vst1_s16_x2(transmute(a), transmute(b))
}
@@ -13946,7 +13946,7 @@ pub unsafe fn vst1_p16_x2(a: *mut p16, b: poly16x4x2_t) {
#[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))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vst1_p16_x3(a: *mut p16, b: poly16x4x3_t) {
vst1_s16_x3(transmute(a), transmute(b))
}
@@ -13959,7 +13959,7 @@ pub unsafe fn vst1_p16_x3(a: *mut p16, b: poly16x4x3_t) {
#[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))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vst1_p16_x4(a: *mut p16, b: poly16x4x4_t) {
vst1_s16_x4(transmute(a), transmute(b))
}
@@ -13972,7 +13972,7 @@ pub unsafe fn vst1_p16_x4(a: *mut p16, b: poly16x4x4_t) {
#[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))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vst1q_p16_x2(a: *mut p16, b: poly16x8x2_t) {
vst1q_s16_x2(transmute(a), transmute(b))
}
@@ -13985,7 +13985,7 @@ pub unsafe fn vst1q_p16_x2(a: *mut p16, b: poly16x8x2_t) {
#[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))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vst1q_p16_x3(a: *mut p16, b: poly16x8x3_t) {
vst1q_s16_x3(transmute(a), transmute(b))
}
@@ -13998,7 +13998,7 @@ pub unsafe fn vst1q_p16_x3(a: *mut p16, b: poly16x8x3_t) {
#[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))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vst1q_p16_x4(a: *mut p16, b: poly16x8x4_t) {
vst1q_s16_x4(transmute(a), transmute(b))
}
@@ -14011,7 +14011,7 @@ pub unsafe fn vst1q_p16_x4(a: *mut p16, b: poly16x8x4_t) {
#[cfg_attr(target_arch = "arm", target_feature(enable = "aes,v8"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst1))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vst1_p64_x2(a: *mut p64, b: poly64x1x2_t) {
vst1_s64_x2(transmute(a), transmute(b))
}
@@ -14024,7 +14024,7 @@ pub unsafe fn vst1_p64_x2(a: *mut p64, b: poly64x1x2_t) {
#[cfg_attr(target_arch = "arm", target_feature(enable = "aes,v8"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vst1_p64_x3(a: *mut p64, b: poly64x1x3_t) {
vst1_s64_x3(transmute(a), transmute(b))
}
@@ -14037,7 +14037,7 @@ pub unsafe fn vst1_p64_x3(a: *mut p64, b: poly64x1x3_t) {
#[cfg_attr(target_arch = "arm", target_feature(enable = "aes,v8"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vst1_p64_x4(a: *mut p64, b: poly64x1x4_t) {
vst1_s64_x4(transmute(a), transmute(b))
}
@@ -14050,7 +14050,7 @@ pub unsafe fn vst1_p64_x4(a: *mut p64, b: poly64x1x4_t) {
#[cfg_attr(target_arch = "arm", target_feature(enable = "aes,v8"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vst1q_p64_x2(a: *mut p64, b: poly64x2x2_t) {
vst1q_s64_x2(transmute(a), transmute(b))
}
@@ -14063,7 +14063,7 @@ pub unsafe fn vst1q_p64_x2(a: *mut p64, b: poly64x2x2_t) {
#[cfg_attr(target_arch = "arm", target_feature(enable = "aes,v8"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vst1q_p64_x3(a: *mut p64, b: poly64x2x3_t) {
vst1q_s64_x3(transmute(a), transmute(b))
}
@@ -14076,7 +14076,7 @@ pub unsafe fn vst1q_p64_x3(a: *mut p64, b: poly64x2x3_t) {
#[cfg_attr(target_arch = "arm", target_feature(enable = "aes,v8"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vst1q_p64_x4(a: *mut p64, b: poly64x2x4_t) {
vst1q_s64_x4(transmute(a), transmute(b))
}
@@ -14518,7 +14518,7 @@ vst2_s64_(b.0, b.1, a as _)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst2))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st2))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vst2_u8(a: *mut u8, b: uint8x8x2_t) {
transmute(vst2_s8(transmute(a), transmute(b)))
}
@@ -14531,7 +14531,7 @@ pub unsafe fn vst2_u8(a: *mut u8, b: uint8x8x2_t) {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst2))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st2))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vst2_u16(a: *mut u16, b: uint16x4x2_t) {
transmute(vst2_s16(transmute(a), transmute(b)))
}
@@ -14544,7 +14544,7 @@ pub unsafe fn vst2_u16(a: *mut u16, b: uint16x4x2_t) {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst2))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st2))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vst2_u32(a: *mut u32, b: uint32x2x2_t) {
transmute(vst2_s32(transmute(a), transmute(b)))
}
@@ -14557,7 +14557,7 @@ pub unsafe fn vst2_u32(a: *mut u32, b: uint32x2x2_t) {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst2))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st2))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vst2q_u8(a: *mut u8, b: uint8x16x2_t) {
transmute(vst2q_s8(transmute(a), transmute(b)))
}
@@ -14570,7 +14570,7 @@ pub unsafe fn vst2q_u8(a: *mut u8, b: uint8x16x2_t) {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst2))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st2))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vst2q_u16(a: *mut u16, b: uint16x8x2_t) {
transmute(vst2q_s16(transmute(a), transmute(b)))
}
@@ -14583,7 +14583,7 @@ pub unsafe fn vst2q_u16(a: *mut u16, b: uint16x8x2_t) {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst2))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st2))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vst2q_u32(a: *mut u32, b: uint32x4x2_t) {
transmute(vst2q_s32(transmute(a), transmute(b)))
}
@@ -14596,7 +14596,7 @@ pub unsafe fn vst2q_u32(a: *mut u32, b: uint32x4x2_t) {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst2))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st2))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vst2_p8(a: *mut p8, b: poly8x8x2_t) {
transmute(vst2_s8(transmute(a), transmute(b)))
}
@@ -14609,7 +14609,7 @@ pub unsafe fn vst2_p8(a: *mut p8, b: poly8x8x2_t) {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst2))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st2))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vst2_p16(a: *mut p16, b: poly16x4x2_t) {
transmute(vst2_s16(transmute(a), transmute(b)))
}
@@ -14622,7 +14622,7 @@ pub unsafe fn vst2_p16(a: *mut p16, b: poly16x4x2_t) {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst2))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st2))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vst2q_p8(a: *mut p8, b: poly8x16x2_t) {
transmute(vst2q_s8(transmute(a), transmute(b)))
}
@@ -14635,7 +14635,7 @@ pub unsafe fn vst2q_p8(a: *mut p8, b: poly8x16x2_t) {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst2))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st2))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vst2q_p16(a: *mut p16, b: poly16x8x2_t) {
transmute(vst2q_s16(transmute(a), transmute(b)))
}
@@ -14648,7 +14648,7 @@ pub unsafe fn vst2q_p16(a: *mut p16, b: poly16x8x2_t) {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vst2_u64(a: *mut u64, b: uint64x1x2_t) {
transmute(vst2_s64(transmute(a), transmute(b)))
}
@@ -14661,7 +14661,7 @@ pub unsafe fn vst2_u64(a: *mut u64, b: uint64x1x2_t) {
#[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))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vst2_p64(a: *mut p64, b: poly64x1x2_t) {
transmute(vst2_s64(transmute(a), transmute(b)))
}
@@ -14926,7 +14926,7 @@ vst2q_lane_s32_(b.0, b.1, LANE as i64, a as _)
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst2, LANE = 0))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st2, LANE = 0))]
#[rustc_legacy_const_generics(2)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vst2_lane_u8<const LANE: i32>(a: *mut u8, b: uint8x8x2_t) {
static_assert_imm3!(LANE);
transmute(vst2_lane_s8::<LANE>(transmute(a), transmute(b)))
@@ -14941,7 +14941,7 @@ pub unsafe fn vst2_lane_u8<const LANE: i32>(a: *mut u8, b: uint8x8x2_t) {
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst2, LANE = 0))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st2, LANE = 0))]
#[rustc_legacy_const_generics(2)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vst2_lane_u16<const LANE: i32>(a: *mut u16, b: uint16x4x2_t) {
static_assert_imm2!(LANE);
transmute(vst2_lane_s16::<LANE>(transmute(a), transmute(b)))
@@ -14956,7 +14956,7 @@ pub unsafe fn vst2_lane_u16<const LANE: i32>(a: *mut u16, b: uint16x4x2_t) {
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst2, LANE = 0))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st2, LANE = 0))]
#[rustc_legacy_const_generics(2)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vst2_lane_u32<const LANE: i32>(a: *mut u32, b: uint32x2x2_t) {
static_assert_imm1!(LANE);
transmute(vst2_lane_s32::<LANE>(transmute(a), transmute(b)))
@@ -14971,7 +14971,7 @@ pub unsafe fn vst2_lane_u32<const LANE: i32>(a: *mut u32, b: uint32x2x2_t) {
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst2, LANE = 0))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st2, LANE = 0))]
#[rustc_legacy_const_generics(2)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vst2q_lane_u16<const LANE: i32>(a: *mut u16, b: uint16x8x2_t) {
static_assert_imm3!(LANE);
transmute(vst2q_lane_s16::<LANE>(transmute(a), transmute(b)))
@@ -14986,7 +14986,7 @@ pub unsafe fn vst2q_lane_u16<const LANE: i32>(a: *mut u16, b: uint16x8x2_t) {
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst2, LANE = 0))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st2, LANE = 0))]
#[rustc_legacy_const_generics(2)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vst2q_lane_u32<const LANE: i32>(a: *mut u32, b: uint32x4x2_t) {
static_assert_imm2!(LANE);
transmute(vst2q_lane_s32::<LANE>(transmute(a), transmute(b)))
@@ -15001,7 +15001,7 @@ pub unsafe fn vst2q_lane_u32<const LANE: i32>(a: *mut u32, b: uint32x4x2_t) {
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst2, LANE = 0))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st2, LANE = 0))]
#[rustc_legacy_const_generics(2)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vst2_lane_p8<const LANE: i32>(a: *mut p8, b: poly8x8x2_t) {
static_assert_imm3!(LANE);
transmute(vst2_lane_s8::<LANE>(transmute(a), transmute(b)))
@@ -15016,7 +15016,7 @@ pub unsafe fn vst2_lane_p8<const LANE: i32>(a: *mut p8, b: poly8x8x2_t) {
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst2, LANE = 0))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st2, LANE = 0))]
#[rustc_legacy_const_generics(2)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vst2_lane_p16<const LANE: i32>(a: *mut p16, b: poly16x4x2_t) {
static_assert_imm2!(LANE);
transmute(vst2_lane_s16::<LANE>(transmute(a), transmute(b)))
@@ -15031,7 +15031,7 @@ pub unsafe fn vst2_lane_p16<const LANE: i32>(a: *mut p16, b: poly16x4x2_t) {
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst2, LANE = 0))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st2, LANE = 0))]
#[rustc_legacy_const_generics(2)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vst2q_lane_p16<const LANE: i32>(a: *mut p16, b: poly16x8x2_t) {
static_assert_imm3!(LANE);
transmute(vst2q_lane_s16::<LANE>(transmute(a), transmute(b)))
@@ -15350,7 +15350,7 @@ vst3_s64_(b.0, b.1, b.2, a as _)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst3))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st3))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vst3_u8(a: *mut u8, b: uint8x8x3_t) {
transmute(vst3_s8(transmute(a), transmute(b)))
}
@@ -15363,7 +15363,7 @@ pub unsafe fn vst3_u8(a: *mut u8, b: uint8x8x3_t) {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst3))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st3))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vst3_u16(a: *mut u16, b: uint16x4x3_t) {
transmute(vst3_s16(transmute(a), transmute(b)))
}
@@ -15376,7 +15376,7 @@ pub unsafe fn vst3_u16(a: *mut u16, b: uint16x4x3_t) {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst3))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st3))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vst3_u32(a: *mut u32, b: uint32x2x3_t) {
transmute(vst3_s32(transmute(a), transmute(b)))
}
@@ -15389,7 +15389,7 @@ pub unsafe fn vst3_u32(a: *mut u32, b: uint32x2x3_t) {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst3))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st3))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vst3q_u8(a: *mut u8, b: uint8x16x3_t) {
transmute(vst3q_s8(transmute(a), transmute(b)))
}
@@ -15402,7 +15402,7 @@ pub unsafe fn vst3q_u8(a: *mut u8, b: uint8x16x3_t) {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst3))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st3))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vst3q_u16(a: *mut u16, b: uint16x8x3_t) {
transmute(vst3q_s16(transmute(a), transmute(b)))
}
@@ -15415,7 +15415,7 @@ pub unsafe fn vst3q_u16(a: *mut u16, b: uint16x8x3_t) {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst3))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st3))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vst3q_u32(a: *mut u32, b: uint32x4x3_t) {
transmute(vst3q_s32(transmute(a), transmute(b)))
}
@@ -15428,7 +15428,7 @@ pub unsafe fn vst3q_u32(a: *mut u32, b: uint32x4x3_t) {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst3))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st3))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vst3_p8(a: *mut p8, b: poly8x8x3_t) {
transmute(vst3_s8(transmute(a), transmute(b)))
}
@@ -15441,7 +15441,7 @@ pub unsafe fn vst3_p8(a: *mut p8, b: poly8x8x3_t) {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst3))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st3))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vst3_p16(a: *mut p16, b: poly16x4x3_t) {
transmute(vst3_s16(transmute(a), transmute(b)))
}
@@ -15454,7 +15454,7 @@ pub unsafe fn vst3_p16(a: *mut p16, b: poly16x4x3_t) {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst3))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st3))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vst3q_p8(a: *mut p8, b: poly8x16x3_t) {
transmute(vst3q_s8(transmute(a), transmute(b)))
}
@@ -15467,7 +15467,7 @@ pub unsafe fn vst3q_p8(a: *mut p8, b: poly8x16x3_t) {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst3))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st3))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vst3q_p16(a: *mut p16, b: poly16x8x3_t) {
transmute(vst3q_s16(transmute(a), transmute(b)))
}
@@ -15480,7 +15480,7 @@ pub unsafe fn vst3q_p16(a: *mut p16, b: poly16x8x3_t) {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vst3_u64(a: *mut u64, b: uint64x1x3_t) {
transmute(vst3_s64(transmute(a), transmute(b)))
}
@@ -15493,7 +15493,7 @@ pub unsafe fn vst3_u64(a: *mut u64, b: uint64x1x3_t) {
#[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))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vst3_p64(a: *mut p64, b: poly64x1x3_t) {
transmute(vst3_s64(transmute(a), transmute(b)))
}
@@ -15758,7 +15758,7 @@ vst3q_lane_s32_(b.0, b.1, b.2, LANE as i64, a as _)
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst3, LANE = 0))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st3, LANE = 0))]
#[rustc_legacy_const_generics(2)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vst3_lane_u8<const LANE: i32>(a: *mut u8, b: uint8x8x3_t) {
static_assert_imm3!(LANE);
transmute(vst3_lane_s8::<LANE>(transmute(a), transmute(b)))
@@ -15773,7 +15773,7 @@ pub unsafe fn vst3_lane_u8<const LANE: i32>(a: *mut u8, b: uint8x8x3_t) {
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst3, LANE = 0))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st3, LANE = 0))]
#[rustc_legacy_const_generics(2)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vst3_lane_u16<const LANE: i32>(a: *mut u16, b: uint16x4x3_t) {
static_assert_imm2!(LANE);
transmute(vst3_lane_s16::<LANE>(transmute(a), transmute(b)))
@@ -15788,7 +15788,7 @@ pub unsafe fn vst3_lane_u16<const LANE: i32>(a: *mut u16, b: uint16x4x3_t) {
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst3, LANE = 0))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st3, LANE = 0))]
#[rustc_legacy_const_generics(2)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vst3_lane_u32<const LANE: i32>(a: *mut u32, b: uint32x2x3_t) {
static_assert_imm1!(LANE);
transmute(vst3_lane_s32::<LANE>(transmute(a), transmute(b)))
@@ -15803,7 +15803,7 @@ pub unsafe fn vst3_lane_u32<const LANE: i32>(a: *mut u32, b: uint32x2x3_t) {
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst3, LANE = 0))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st3, LANE = 0))]
#[rustc_legacy_const_generics(2)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vst3q_lane_u16<const LANE: i32>(a: *mut u16, b: uint16x8x3_t) {
static_assert_imm3!(LANE);
transmute(vst3q_lane_s16::<LANE>(transmute(a), transmute(b)))
@@ -15818,7 +15818,7 @@ pub unsafe fn vst3q_lane_u16<const LANE: i32>(a: *mut u16, b: uint16x8x3_t) {
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst3, LANE = 0))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st3, LANE = 0))]
#[rustc_legacy_const_generics(2)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vst3q_lane_u32<const LANE: i32>(a: *mut u32, b: uint32x4x3_t) {
static_assert_imm2!(LANE);
transmute(vst3q_lane_s32::<LANE>(transmute(a), transmute(b)))
@@ -15833,7 +15833,7 @@ pub unsafe fn vst3q_lane_u32<const LANE: i32>(a: *mut u32, b: uint32x4x3_t) {
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst3, LANE = 0))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st3, LANE = 0))]
#[rustc_legacy_const_generics(2)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vst3_lane_p8<const LANE: i32>(a: *mut p8, b: poly8x8x3_t) {
static_assert_imm3!(LANE);
transmute(vst3_lane_s8::<LANE>(transmute(a), transmute(b)))
@@ -15848,7 +15848,7 @@ pub unsafe fn vst3_lane_p8<const LANE: i32>(a: *mut p8, b: poly8x8x3_t) {
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst3, LANE = 0))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st3, LANE = 0))]
#[rustc_legacy_const_generics(2)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vst3_lane_p16<const LANE: i32>(a: *mut p16, b: poly16x4x3_t) {
static_assert_imm2!(LANE);
transmute(vst3_lane_s16::<LANE>(transmute(a), transmute(b)))
@@ -15863,7 +15863,7 @@ pub unsafe fn vst3_lane_p16<const LANE: i32>(a: *mut p16, b: poly16x4x3_t) {
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst3, LANE = 0))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st3, LANE = 0))]
#[rustc_legacy_const_generics(2)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vst3q_lane_p16<const LANE: i32>(a: *mut p16, b: poly16x8x3_t) {
static_assert_imm3!(LANE);
transmute(vst3q_lane_s16::<LANE>(transmute(a), transmute(b)))
@@ -16182,7 +16182,7 @@ vst4_s64_(b.0, b.1, b.2, b.3, a as _)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst4))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st4))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vst4_u8(a: *mut u8, b: uint8x8x4_t) {
transmute(vst4_s8(transmute(a), transmute(b)))
}
@@ -16195,7 +16195,7 @@ pub unsafe fn vst4_u8(a: *mut u8, b: uint8x8x4_t) {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst4))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st4))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vst4_u16(a: *mut u16, b: uint16x4x4_t) {
transmute(vst4_s16(transmute(a), transmute(b)))
}
@@ -16208,7 +16208,7 @@ pub unsafe fn vst4_u16(a: *mut u16, b: uint16x4x4_t) {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst4))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st4))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vst4_u32(a: *mut u32, b: uint32x2x4_t) {
transmute(vst4_s32(transmute(a), transmute(b)))
}
@@ -16221,7 +16221,7 @@ pub unsafe fn vst4_u32(a: *mut u32, b: uint32x2x4_t) {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst4))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st4))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vst4q_u8(a: *mut u8, b: uint8x16x4_t) {
transmute(vst4q_s8(transmute(a), transmute(b)))
}
@@ -16234,7 +16234,7 @@ pub unsafe fn vst4q_u8(a: *mut u8, b: uint8x16x4_t) {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst4))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st4))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vst4q_u16(a: *mut u16, b: uint16x8x4_t) {
transmute(vst4q_s16(transmute(a), transmute(b)))
}
@@ -16247,7 +16247,7 @@ pub unsafe fn vst4q_u16(a: *mut u16, b: uint16x8x4_t) {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst4))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st4))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vst4q_u32(a: *mut u32, b: uint32x4x4_t) {
transmute(vst4q_s32(transmute(a), transmute(b)))
}
@@ -16260,7 +16260,7 @@ pub unsafe fn vst4q_u32(a: *mut u32, b: uint32x4x4_t) {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst4))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st4))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vst4_p8(a: *mut p8, b: poly8x8x4_t) {
transmute(vst4_s8(transmute(a), transmute(b)))
}
@@ -16273,7 +16273,7 @@ pub unsafe fn vst4_p8(a: *mut p8, b: poly8x8x4_t) {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst4))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st4))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vst4_p16(a: *mut p16, b: poly16x4x4_t) {
transmute(vst4_s16(transmute(a), transmute(b)))
}
@@ -16286,7 +16286,7 @@ pub unsafe fn vst4_p16(a: *mut p16, b: poly16x4x4_t) {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst4))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st4))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vst4q_p8(a: *mut p8, b: poly8x16x4_t) {
transmute(vst4q_s8(transmute(a), transmute(b)))
}
@@ -16299,7 +16299,7 @@ pub unsafe fn vst4q_p8(a: *mut p8, b: poly8x16x4_t) {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst4))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st4))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vst4q_p16(a: *mut p16, b: poly16x8x4_t) {
transmute(vst4q_s16(transmute(a), transmute(b)))
}
@@ -16312,7 +16312,7 @@ pub unsafe fn vst4q_p16(a: *mut p16, b: poly16x8x4_t) {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vst4_u64(a: *mut u64, b: uint64x1x4_t) {
transmute(vst4_s64(transmute(a), transmute(b)))
}
@@ -16325,7 +16325,7 @@ pub unsafe fn vst4_u64(a: *mut u64, b: uint64x1x4_t) {
#[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))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vst4_p64(a: *mut p64, b: poly64x1x4_t) {
transmute(vst4_s64(transmute(a), transmute(b)))
}
@@ -16590,7 +16590,7 @@ vst4q_lane_s32_(b.0, b.1, b.2, b.3, LANE as i64, a as _)
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst4, LANE = 0))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st4, LANE = 0))]
#[rustc_legacy_const_generics(2)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vst4_lane_u8<const LANE: i32>(a: *mut u8, b: uint8x8x4_t) {
static_assert_imm3!(LANE);
transmute(vst4_lane_s8::<LANE>(transmute(a), transmute(b)))
@@ -16605,7 +16605,7 @@ pub unsafe fn vst4_lane_u8<const LANE: i32>(a: *mut u8, b: uint8x8x4_t) {
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst4, LANE = 0))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st4, LANE = 0))]
#[rustc_legacy_const_generics(2)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vst4_lane_u16<const LANE: i32>(a: *mut u16, b: uint16x4x4_t) {
static_assert_imm2!(LANE);
transmute(vst4_lane_s16::<LANE>(transmute(a), transmute(b)))
@@ -16620,7 +16620,7 @@ pub unsafe fn vst4_lane_u16<const LANE: i32>(a: *mut u16, b: uint16x4x4_t) {
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst4, LANE = 0))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st4, LANE = 0))]
#[rustc_legacy_const_generics(2)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vst4_lane_u32<const LANE: i32>(a: *mut u32, b: uint32x2x4_t) {
static_assert_imm1!(LANE);
transmute(vst4_lane_s32::<LANE>(transmute(a), transmute(b)))
@@ -16635,7 +16635,7 @@ pub unsafe fn vst4_lane_u32<const LANE: i32>(a: *mut u32, b: uint32x2x4_t) {
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst4, LANE = 0))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st4, LANE = 0))]
#[rustc_legacy_const_generics(2)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vst4q_lane_u16<const LANE: i32>(a: *mut u16, b: uint16x8x4_t) {
static_assert_imm3!(LANE);
transmute(vst4q_lane_s16::<LANE>(transmute(a), transmute(b)))
@@ -16650,7 +16650,7 @@ pub unsafe fn vst4q_lane_u16<const LANE: i32>(a: *mut u16, b: uint16x8x4_t) {
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst4, LANE = 0))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st4, LANE = 0))]
#[rustc_legacy_const_generics(2)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vst4q_lane_u32<const LANE: i32>(a: *mut u32, b: uint32x4x4_t) {
static_assert_imm2!(LANE);
transmute(vst4q_lane_s32::<LANE>(transmute(a), transmute(b)))
@@ -16665,7 +16665,7 @@ pub unsafe fn vst4q_lane_u32<const LANE: i32>(a: *mut u32, b: uint32x4x4_t) {
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst4, LANE = 0))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st4, LANE = 0))]
#[rustc_legacy_const_generics(2)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vst4_lane_p8<const LANE: i32>(a: *mut p8, b: poly8x8x4_t) {
static_assert_imm3!(LANE);
transmute(vst4_lane_s8::<LANE>(transmute(a), transmute(b)))
@@ -16680,7 +16680,7 @@ pub unsafe fn vst4_lane_p8<const LANE: i32>(a: *mut p8, b: poly8x8x4_t) {
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst4, LANE = 0))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st4, LANE = 0))]
#[rustc_legacy_const_generics(2)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vst4_lane_p16<const LANE: i32>(a: *mut p16, b: poly16x4x4_t) {
static_assert_imm2!(LANE);
transmute(vst4_lane_s16::<LANE>(transmute(a), transmute(b)))
@@ -16695,7 +16695,7 @@ pub unsafe fn vst4_lane_p16<const LANE: i32>(a: *mut p16, b: poly16x4x4_t) {
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst4, LANE = 0))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st4, LANE = 0))]
#[rustc_legacy_const_generics(2)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vst4q_lane_p16<const LANE: i32>(a: *mut p16, b: poly16x8x4_t) {
static_assert_imm3!(LANE);
transmute(vst4q_lane_s16::<LANE>(transmute(a), transmute(b)))
@@ -16783,7 +16783,7 @@ vst4q_lane_f32_(b.0, b.1, b.2, b.3, LANE as i64, a as _)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmul.i8"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mul))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmul_s8(a: int8x8_t, b: int8x8_t) -> int8x8_t {
simd_mul(a, b)
}
@@ -16796,7 +16796,7 @@ pub unsafe fn vmul_s8(a: int8x8_t, b: int8x8_t) -> int8x8_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmul.i8"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mul))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmulq_s8(a: int8x16_t, b: int8x16_t) -> int8x16_t {
simd_mul(a, b)
}
@@ -16809,7 +16809,7 @@ pub unsafe fn vmulq_s8(a: int8x16_t, b: int8x16_t) -> int8x16_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmul.i16"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mul))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmul_s16(a: int16x4_t, b: int16x4_t) -> int16x4_t {
simd_mul(a, b)
}
@@ -16822,7 +16822,7 @@ pub unsafe fn vmul_s16(a: int16x4_t, b: int16x4_t) -> int16x4_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmul.i16"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mul))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmulq_s16(a: int16x8_t, b: int16x8_t) -> int16x8_t {
simd_mul(a, b)
}
@@ -16835,7 +16835,7 @@ pub unsafe fn vmulq_s16(a: int16x8_t, b: int16x8_t) -> int16x8_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmul.i32"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mul))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmul_s32(a: int32x2_t, b: int32x2_t) -> int32x2_t {
simd_mul(a, b)
}
@@ -16848,7 +16848,7 @@ pub unsafe fn vmul_s32(a: int32x2_t, b: int32x2_t) -> int32x2_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmul.i32"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mul))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmulq_s32(a: int32x4_t, b: int32x4_t) -> int32x4_t {
simd_mul(a, b)
}
@@ -16861,7 +16861,7 @@ pub unsafe fn vmulq_s32(a: int32x4_t, b: int32x4_t) -> int32x4_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmul.i8"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mul))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmul_u8(a: uint8x8_t, b: uint8x8_t) -> uint8x8_t {
simd_mul(a, b)
}
@@ -16874,7 +16874,7 @@ pub unsafe fn vmul_u8(a: uint8x8_t, b: uint8x8_t) -> uint8x8_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmul.i8"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mul))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmulq_u8(a: uint8x16_t, b: uint8x16_t) -> uint8x16_t {
simd_mul(a, b)
}
@@ -16887,7 +16887,7 @@ pub unsafe fn vmulq_u8(a: uint8x16_t, b: uint8x16_t) -> uint8x16_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmul.i16"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mul))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmul_u16(a: uint16x4_t, b: uint16x4_t) -> uint16x4_t {
simd_mul(a, b)
}
@@ -16900,7 +16900,7 @@ pub unsafe fn vmul_u16(a: uint16x4_t, b: uint16x4_t) -> uint16x4_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmul.i16"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mul))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmulq_u16(a: uint16x8_t, b: uint16x8_t) -> uint16x8_t {
simd_mul(a, b)
}
@@ -16913,7 +16913,7 @@ pub unsafe fn vmulq_u16(a: uint16x8_t, b: uint16x8_t) -> uint16x8_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmul.i32"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mul))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmul_u32(a: uint32x2_t, b: uint32x2_t) -> uint32x2_t {
simd_mul(a, b)
}
@@ -16926,7 +16926,7 @@ pub unsafe fn vmul_u32(a: uint32x2_t, b: uint32x2_t) -> uint32x2_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmul.i32"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mul))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmulq_u32(a: uint32x4_t, b: uint32x4_t) -> uint32x4_t {
simd_mul(a, b)
}
@@ -16939,7 +16939,7 @@ pub unsafe fn vmulq_u32(a: uint32x4_t, b: uint32x4_t) -> uint32x4_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmul))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(pmul))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmul_p8(a: poly8x8_t, b: poly8x8_t) -> poly8x8_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -16958,7 +16958,7 @@ vmul_p8_(a, b)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmul))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(pmul))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmulq_p8(a: poly8x16_t, b: poly8x16_t) -> poly8x16_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -16977,7 +16977,7 @@ vmulq_p8_(a, b)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmul.f32"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(fmul))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmul_f32(a: float32x2_t, b: float32x2_t) -> float32x2_t {
simd_mul(a, b)
}
@@ -16990,7 +16990,7 @@ pub unsafe fn vmul_f32(a: float32x2_t, b: float32x2_t) -> float32x2_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmul.f32"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(fmul))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmulq_f32(a: float32x4_t, b: float32x4_t) -> float32x4_t {
simd_mul(a, b)
}
@@ -17003,7 +17003,7 @@ pub unsafe fn vmulq_f32(a: float32x4_t, b: float32x4_t) -> float32x4_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmul))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mul))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmul_n_s16(a: int16x4_t, b: i16) -> int16x4_t {
simd_mul(a, vdup_n_s16(b))
}
@@ -17016,7 +17016,7 @@ pub unsafe fn vmul_n_s16(a: int16x4_t, b: i16) -> int16x4_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmul))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mul))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmulq_n_s16(a: int16x8_t, b: i16) -> int16x8_t {
simd_mul(a, vdupq_n_s16(b))
}
@@ -17029,7 +17029,7 @@ pub unsafe fn vmulq_n_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(vmul))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mul))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmul_n_s32(a: int32x2_t, b: i32) -> int32x2_t {
simd_mul(a, vdup_n_s32(b))
}
@@ -17042,7 +17042,7 @@ pub unsafe fn vmul_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(vmul))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mul))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmulq_n_s32(a: int32x4_t, b: i32) -> int32x4_t {
simd_mul(a, vdupq_n_s32(b))
}
@@ -17055,7 +17055,7 @@ pub unsafe fn vmulq_n_s32(a: int32x4_t, b: i32) -> int32x4_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmul))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mul))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmul_n_u16(a: uint16x4_t, b: u16) -> uint16x4_t {
simd_mul(a, vdup_n_u16(b))
}
@@ -17068,7 +17068,7 @@ pub unsafe fn vmul_n_u16(a: uint16x4_t, b: u16) -> uint16x4_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmul))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mul))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmulq_n_u16(a: uint16x8_t, b: u16) -> uint16x8_t {
simd_mul(a, vdupq_n_u16(b))
}
@@ -17081,7 +17081,7 @@ pub unsafe fn vmulq_n_u16(a: uint16x8_t, b: u16) -> uint16x8_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmul))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mul))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmul_n_u32(a: uint32x2_t, b: u32) -> uint32x2_t {
simd_mul(a, vdup_n_u32(b))
}
@@ -17094,7 +17094,7 @@ pub unsafe fn vmul_n_u32(a: uint32x2_t, b: u32) -> uint32x2_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmul))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mul))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmulq_n_u32(a: uint32x4_t, b: u32) -> uint32x4_t {
simd_mul(a, vdupq_n_u32(b))
}
@@ -17107,7 +17107,7 @@ pub unsafe fn vmulq_n_u32(a: uint32x4_t, b: u32) -> uint32x4_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmul))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(fmul))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmul_n_f32(a: float32x2_t, b: f32) -> float32x2_t {
simd_mul(a, vdup_n_f32(b))
}
@@ -17120,7 +17120,7 @@ pub unsafe fn vmul_n_f32(a: float32x2_t, b: f32) -> float32x2_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmul))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(fmul))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmulq_n_f32(a: float32x4_t, b: f32) -> float32x4_t {
simd_mul(a, vdupq_n_f32(b))
}
@@ -17134,7 +17134,7 @@ pub unsafe fn vmulq_n_f32(a: float32x4_t, b: f32) -> float32x4_t {
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmul, LANE = 1))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mul, LANE = 1))]
#[rustc_legacy_const_generics(2)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmul_lane_s16<const LANE: i32>(a: int16x4_t, b: int16x4_t) -> int16x4_t {
static_assert_imm2!(LANE);
simd_mul(a, simd_shuffle4!(b, b, <const LANE: i32> [LANE as u32, LANE as u32, LANE as u32, LANE as u32]))
@@ -17149,7 +17149,7 @@ pub unsafe fn vmul_lane_s16<const LANE: i32>(a: int16x4_t, b: int16x4_t) -> int1
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmul, LANE = 1))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mul, LANE = 1))]
#[rustc_legacy_const_generics(2)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmul_laneq_s16<const LANE: i32>(a: int16x4_t, b: int16x8_t) -> int16x4_t {
static_assert_imm3!(LANE);
simd_mul(a, simd_shuffle4!(b, b, <const LANE: i32> [LANE as u32, LANE as u32, LANE as u32, LANE as u32]))
@@ -17164,7 +17164,7 @@ pub unsafe fn vmul_laneq_s16<const LANE: i32>(a: int16x4_t, b: int16x8_t) -> int
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmul, LANE = 1))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mul, LANE = 1))]
#[rustc_legacy_const_generics(2)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmulq_lane_s16<const LANE: i32>(a: int16x8_t, b: int16x4_t) -> int16x8_t {
static_assert_imm2!(LANE);
simd_mul(a, simd_shuffle8!(b, b, <const LANE: i32> [LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32]))
@@ -17179,7 +17179,7 @@ pub unsafe fn vmulq_lane_s16<const LANE: i32>(a: int16x8_t, b: int16x4_t) -> int
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmul, LANE = 1))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mul, LANE = 1))]
#[rustc_legacy_const_generics(2)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmulq_laneq_s16<const LANE: i32>(a: int16x8_t, b: int16x8_t) -> int16x8_t {
static_assert_imm3!(LANE);
simd_mul(a, simd_shuffle8!(b, b, <const LANE: i32> [LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32]))
@@ -17194,7 +17194,7 @@ pub unsafe fn vmulq_laneq_s16<const LANE: i32>(a: int16x8_t, b: int16x8_t) -> in
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmul, LANE = 1))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mul, LANE = 1))]
#[rustc_legacy_const_generics(2)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmul_lane_s32<const LANE: i32>(a: int32x2_t, b: int32x2_t) -> int32x2_t {
static_assert_imm1!(LANE);
simd_mul(a, simd_shuffle2!(b, b, <const LANE: i32> [LANE as u32, LANE as u32]))
@@ -17209,7 +17209,7 @@ pub unsafe fn vmul_lane_s32<const LANE: i32>(a: int32x2_t, b: int32x2_t) -> int3
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmul, LANE = 1))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mul, LANE = 1))]
#[rustc_legacy_const_generics(2)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmul_laneq_s32<const LANE: i32>(a: int32x2_t, b: int32x4_t) -> int32x2_t {
static_assert_imm2!(LANE);
simd_mul(a, simd_shuffle2!(b, b, <const LANE: i32> [LANE as u32, LANE as u32]))
@@ -17224,7 +17224,7 @@ pub unsafe fn vmul_laneq_s32<const LANE: i32>(a: int32x2_t, b: int32x4_t) -> int
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmul, LANE = 1))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mul, LANE = 1))]
#[rustc_legacy_const_generics(2)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmulq_lane_s32<const LANE: i32>(a: int32x4_t, b: int32x2_t) -> int32x4_t {
static_assert_imm1!(LANE);
simd_mul(a, simd_shuffle4!(b, b, <const LANE: i32> [LANE as u32, LANE as u32, LANE as u32, LANE as u32]))
@@ -17239,7 +17239,7 @@ pub unsafe fn vmulq_lane_s32<const LANE: i32>(a: int32x4_t, b: int32x2_t) -> int
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmul, LANE = 1))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mul, LANE = 1))]
#[rustc_legacy_const_generics(2)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmulq_laneq_s32<const LANE: i32>(a: int32x4_t, b: int32x4_t) -> int32x4_t {
static_assert_imm2!(LANE);
simd_mul(a, simd_shuffle4!(b, b, <const LANE: i32> [LANE as u32, LANE as u32, LANE as u32, LANE as u32]))
@@ -17254,7 +17254,7 @@ pub unsafe fn vmulq_laneq_s32<const LANE: i32>(a: int32x4_t, b: int32x4_t) -> in
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmul, LANE = 1))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mul, LANE = 1))]
#[rustc_legacy_const_generics(2)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmul_lane_u16<const LANE: i32>(a: uint16x4_t, b: uint16x4_t) -> uint16x4_t {
static_assert_imm2!(LANE);
simd_mul(a, simd_shuffle4!(b, b, <const LANE: i32> [LANE as u32, LANE as u32, LANE as u32, LANE as u32]))
@@ -17269,7 +17269,7 @@ pub unsafe fn vmul_lane_u16<const LANE: i32>(a: uint16x4_t, b: uint16x4_t) -> ui
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmul, LANE = 1))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mul, LANE = 1))]
#[rustc_legacy_const_generics(2)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmul_laneq_u16<const LANE: i32>(a: uint16x4_t, b: uint16x8_t) -> uint16x4_t {
static_assert_imm3!(LANE);
simd_mul(a, simd_shuffle4!(b, b, <const LANE: i32> [LANE as u32, LANE as u32, LANE as u32, LANE as u32]))
@@ -17284,7 +17284,7 @@ pub unsafe fn vmul_laneq_u16<const LANE: i32>(a: uint16x4_t, b: uint16x8_t) -> u
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmul, LANE = 1))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mul, LANE = 1))]
#[rustc_legacy_const_generics(2)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmulq_lane_u16<const LANE: i32>(a: uint16x8_t, b: uint16x4_t) -> uint16x8_t {
static_assert_imm2!(LANE);
simd_mul(a, simd_shuffle8!(b, b, <const LANE: i32> [LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32]))
@@ -17299,7 +17299,7 @@ pub unsafe fn vmulq_lane_u16<const LANE: i32>(a: uint16x8_t, b: uint16x4_t) -> u
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmul, LANE = 1))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mul, LANE = 1))]
#[rustc_legacy_const_generics(2)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmulq_laneq_u16<const LANE: i32>(a: uint16x8_t, b: uint16x8_t) -> uint16x8_t {
static_assert_imm3!(LANE);
simd_mul(a, simd_shuffle8!(b, b, <const LANE: i32> [LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32]))
@@ -17314,7 +17314,7 @@ pub unsafe fn vmulq_laneq_u16<const LANE: i32>(a: uint16x8_t, b: uint16x8_t) ->
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmul, LANE = 1))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mul, LANE = 1))]
#[rustc_legacy_const_generics(2)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmul_lane_u32<const LANE: i32>(a: uint32x2_t, b: uint32x2_t) -> uint32x2_t {
static_assert_imm1!(LANE);
simd_mul(a, simd_shuffle2!(b, b, <const LANE: i32> [LANE as u32, LANE as u32]))
@@ -17329,7 +17329,7 @@ pub unsafe fn vmul_lane_u32<const LANE: i32>(a: uint32x2_t, b: uint32x2_t) -> ui
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmul, LANE = 1))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mul, LANE = 1))]
#[rustc_legacy_const_generics(2)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmul_laneq_u32<const LANE: i32>(a: uint32x2_t, b: uint32x4_t) -> uint32x2_t {
static_assert_imm2!(LANE);
simd_mul(a, simd_shuffle2!(b, b, <const LANE: i32> [LANE as u32, LANE as u32]))
@@ -17344,7 +17344,7 @@ pub unsafe fn vmul_laneq_u32<const LANE: i32>(a: uint32x2_t, b: uint32x4_t) -> u
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmul, LANE = 1))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mul, LANE = 1))]
#[rustc_legacy_const_generics(2)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmulq_lane_u32<const LANE: i32>(a: uint32x4_t, b: uint32x2_t) -> uint32x4_t {
static_assert_imm1!(LANE);
simd_mul(a, simd_shuffle4!(b, b, <const LANE: i32> [LANE as u32, LANE as u32, LANE as u32, LANE as u32]))
@@ -17359,7 +17359,7 @@ pub unsafe fn vmulq_lane_u32<const LANE: i32>(a: uint32x4_t, b: uint32x2_t) -> u
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmul, LANE = 1))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mul, LANE = 1))]
#[rustc_legacy_const_generics(2)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmulq_laneq_u32<const LANE: i32>(a: uint32x4_t, b: uint32x4_t) -> uint32x4_t {
static_assert_imm2!(LANE);
simd_mul(a, simd_shuffle4!(b, b, <const LANE: i32> [LANE as u32, LANE as u32, LANE as u32, LANE as u32]))
@@ -17374,7 +17374,7 @@ pub unsafe fn vmulq_laneq_u32<const LANE: i32>(a: uint32x4_t, b: uint32x4_t) ->
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmul, LANE = 0))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(fmul, LANE = 0))]
#[rustc_legacy_const_generics(2)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmul_lane_f32<const LANE: i32>(a: float32x2_t, b: float32x2_t) -> float32x2_t {
static_assert_imm1!(LANE);
simd_mul(a, simd_shuffle2!(b, b, <const LANE: i32> [LANE as u32, LANE as u32]))
@@ -17389,7 +17389,7 @@ pub unsafe fn vmul_lane_f32<const LANE: i32>(a: float32x2_t, b: float32x2_t) ->
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmul, LANE = 0))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(fmul, LANE = 0))]
#[rustc_legacy_const_generics(2)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmul_laneq_f32<const LANE: i32>(a: float32x2_t, b: float32x4_t) -> float32x2_t {
static_assert_imm2!(LANE);
simd_mul(a, simd_shuffle2!(b, b, <const LANE: i32> [LANE as u32, LANE as u32]))
@@ -17404,7 +17404,7 @@ pub unsafe fn vmul_laneq_f32<const LANE: i32>(a: float32x2_t, b: float32x4_t) ->
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmul, LANE = 0))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(fmul, LANE = 0))]
#[rustc_legacy_const_generics(2)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmulq_lane_f32<const LANE: i32>(a: float32x4_t, b: float32x2_t) -> float32x4_t {
static_assert_imm1!(LANE);
simd_mul(a, simd_shuffle4!(b, b, <const LANE: i32> [LANE as u32, LANE as u32, LANE as u32, LANE as u32]))
@@ -17419,7 +17419,7 @@ pub unsafe fn vmulq_lane_f32<const LANE: i32>(a: float32x4_t, b: float32x2_t) ->
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmul, LANE = 0))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(fmul, LANE = 0))]
#[rustc_legacy_const_generics(2)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmulq_laneq_f32<const LANE: i32>(a: float32x4_t, b: float32x4_t) -> float32x4_t {
static_assert_imm2!(LANE);
simd_mul(a, simd_shuffle4!(b, b, <const LANE: i32> [LANE as u32, LANE as u32, LANE as u32, LANE as u32]))
@@ -17433,7 +17433,7 @@ pub unsafe fn vmulq_laneq_f32<const LANE: i32>(a: float32x4_t, b: float32x4_t) -
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmull.s8"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(smull))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmull_s8(a: int8x8_t, b: int8x8_t) -> int16x8_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -17452,7 +17452,7 @@ vmull_s8_(a, b)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmull.s16"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(smull))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmull_s16(a: int16x4_t, b: int16x4_t) -> int32x4_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -17471,7 +17471,7 @@ vmull_s16_(a, b)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmull.s32"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(smull))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmull_s32(a: int32x2_t, b: int32x2_t) -> int64x2_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -17490,7 +17490,7 @@ vmull_s32_(a, b)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmull.u8"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(umull))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmull_u8(a: uint8x8_t, b: uint8x8_t) -> uint16x8_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -17509,7 +17509,7 @@ vmull_u8_(a, b)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmull.u16"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(umull))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmull_u16(a: uint16x4_t, b: uint16x4_t) -> uint32x4_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -17528,7 +17528,7 @@ vmull_u16_(a, b)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmull.u32"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(umull))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmull_u32(a: uint32x2_t, b: uint32x2_t) -> uint64x2_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -17547,7 +17547,7 @@ vmull_u32_(a, b)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmull.p8"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(pmull))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmull_p8(a: poly8x8_t, b: poly8x8_t) -> poly16x8_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -17566,7 +17566,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))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmull_n_s16(a: int16x4_t, b: i16) -> int32x4_t {
vmull_s16(a, vdup_n_s16(b))
}
@@ -17579,7 +17579,7 @@ pub unsafe fn vmull_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))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmull_n_s32(a: int32x2_t, b: i32) -> int64x2_t {
vmull_s32(a, vdup_n_s32(b))
}
@@ -17592,7 +17592,7 @@ pub unsafe fn vmull_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))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmull_n_u16(a: uint16x4_t, b: u16) -> uint32x4_t {
vmull_u16(a, vdup_n_u16(b))
}
@@ -17605,7 +17605,7 @@ pub unsafe fn vmull_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))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmull_n_u32(a: uint32x2_t, b: u32) -> uint64x2_t {
vmull_u32(a, vdup_n_u32(b))
}
@@ -17619,7 +17619,7 @@ pub unsafe fn vmull_n_u32(a: uint32x2_t, b: u32) -> uint64x2_t {
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmull, LANE = 1))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(smull, LANE = 1))]
#[rustc_legacy_const_generics(2)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmull_lane_s16<const LANE: i32>(a: int16x4_t, b: int16x4_t) -> int32x4_t {
static_assert_imm2!(LANE);
vmull_s16(a, simd_shuffle4!(b, b, <const LANE: i32> [LANE as u32, LANE as u32, LANE as u32, LANE as u32]))
@@ -17634,7 +17634,7 @@ pub unsafe fn vmull_lane_s16<const LANE: i32>(a: int16x4_t, b: int16x4_t) -> int
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmull, LANE = 1))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(smull, LANE = 1))]
#[rustc_legacy_const_generics(2)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmull_laneq_s16<const LANE: i32>(a: int16x4_t, b: int16x8_t) -> int32x4_t {
static_assert_imm3!(LANE);
vmull_s16(a, simd_shuffle4!(b, b, <const LANE: i32> [LANE as u32, LANE as u32, LANE as u32, LANE as u32]))
@@ -17649,7 +17649,7 @@ pub unsafe fn vmull_laneq_s16<const LANE: i32>(a: int16x4_t, b: int16x8_t) -> in
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmull, LANE = 1))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(smull, LANE = 1))]
#[rustc_legacy_const_generics(2)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmull_lane_s32<const LANE: i32>(a: int32x2_t, b: int32x2_t) -> int64x2_t {
static_assert_imm1!(LANE);
vmull_s32(a, simd_shuffle2!(b, b, <const LANE: i32> [LANE as u32, LANE as u32]))
@@ -17664,7 +17664,7 @@ pub unsafe fn vmull_lane_s32<const LANE: i32>(a: int32x2_t, b: int32x2_t) -> int
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmull, LANE = 1))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(smull, LANE = 1))]
#[rustc_legacy_const_generics(2)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmull_laneq_s32<const LANE: i32>(a: int32x2_t, b: int32x4_t) -> int64x2_t {
static_assert_imm2!(LANE);
vmull_s32(a, simd_shuffle2!(b, b, <const LANE: i32> [LANE as u32, LANE as u32]))
@@ -17679,7 +17679,7 @@ pub unsafe fn vmull_laneq_s32<const LANE: i32>(a: int32x2_t, b: int32x4_t) -> in
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmull, LANE = 1))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(umull, LANE = 1))]
#[rustc_legacy_const_generics(2)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmull_lane_u16<const LANE: i32>(a: uint16x4_t, b: uint16x4_t) -> uint32x4_t {
static_assert_imm2!(LANE);
vmull_u16(a, simd_shuffle4!(b, b, <const LANE: i32> [LANE as u32, LANE as u32, LANE as u32, LANE as u32]))
@@ -17694,7 +17694,7 @@ pub unsafe fn vmull_lane_u16<const LANE: i32>(a: uint16x4_t, b: uint16x4_t) -> u
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmull, LANE = 1))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(umull, LANE = 1))]
#[rustc_legacy_const_generics(2)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmull_laneq_u16<const LANE: i32>(a: uint16x4_t, b: uint16x8_t) -> uint32x4_t {
static_assert_imm3!(LANE);
vmull_u16(a, simd_shuffle4!(b, b, <const LANE: i32> [LANE as u32, LANE as u32, LANE as u32, LANE as u32]))
@@ -17709,7 +17709,7 @@ pub unsafe fn vmull_laneq_u16<const LANE: i32>(a: uint16x4_t, b: uint16x8_t) ->
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmull, LANE = 1))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(umull, LANE = 1))]
#[rustc_legacy_const_generics(2)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmull_lane_u32<const LANE: i32>(a: uint32x2_t, b: uint32x2_t) -> uint64x2_t {
static_assert_imm1!(LANE);
vmull_u32(a, simd_shuffle2!(b, b, <const LANE: i32> [LANE as u32, LANE as u32]))
@@ -17724,7 +17724,7 @@ pub unsafe fn vmull_lane_u32<const LANE: i32>(a: uint32x2_t, b: uint32x2_t) -> u
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmull, LANE = 1))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(umull, LANE = 1))]
#[rustc_legacy_const_generics(2)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmull_laneq_u32<const LANE: i32>(a: uint32x2_t, b: uint32x4_t) -> uint64x2_t {
static_assert_imm2!(LANE);
vmull_u32(a, simd_shuffle2!(b, b, <const LANE: i32> [LANE as u32, LANE as u32]))
@@ -17738,7 +17738,7 @@ pub unsafe fn vmull_laneq_u32<const LANE: i32>(a: uint32x2_t, b: uint32x4_t) ->
#[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))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vfma_f32(a: float32x2_t, b: float32x2_t, c: float32x2_t) -> float32x2_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -17757,7 +17757,7 @@ vfma_f32_(b, c, a)
#[cfg_attr(target_arch = "arm", target_feature(enable = "vfp4"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vfma))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(fmla))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vfmaq_f32(a: float32x4_t, b: float32x4_t, c: float32x4_t) -> float32x4_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -17776,7 +17776,7 @@ vfmaq_f32_(b, c, a)
#[cfg_attr(target_arch = "arm", target_feature(enable = "vfp4"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vfma))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(fmla))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vfma_n_f32(a: float32x2_t, b: float32x2_t, c: f32) -> float32x2_t {
vfma_f32(a, b, vdup_n_f32_vfp4(c))
}
@@ -17789,7 +17789,7 @@ pub unsafe fn vfma_n_f32(a: float32x2_t, b: float32x2_t, c: f32) -> float32x2_t
#[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))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vfmaq_n_f32(a: float32x4_t, b: float32x4_t, c: f32) -> float32x4_t {
vfmaq_f32(a, b, vdupq_n_f32_vfp4(c))
}
@@ -17802,7 +17802,7 @@ pub unsafe fn vfmaq_n_f32(a: float32x4_t, b: float32x4_t, c: f32) -> float32x4_t
#[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))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vfms_f32(a: float32x2_t, b: float32x2_t, c: float32x2_t) -> float32x2_t {
let b: float32x2_t = simd_neg(b);
vfma_f32(a, b, c)
@@ -17816,7 +17816,7 @@ pub unsafe fn vfms_f32(a: float32x2_t, b: float32x2_t, c: float32x2_t) -> float3
#[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))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vfmsq_f32(a: float32x4_t, b: float32x4_t, c: float32x4_t) -> float32x4_t {
let b: float32x4_t = simd_neg(b);
vfmaq_f32(a, b, c)
@@ -17830,7 +17830,7 @@ pub unsafe fn vfmsq_f32(a: float32x4_t, b: float32x4_t, c: float32x4_t) -> float
#[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))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vfms_n_f32(a: float32x2_t, b: float32x2_t, c: f32) -> float32x2_t {
vfms_f32(a, b, vdup_n_f32_vfp4(c))
}
@@ -17843,7 +17843,7 @@ pub unsafe fn vfms_n_f32(a: float32x2_t, b: float32x2_t, c: f32) -> float32x2_t
#[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))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vfmsq_n_f32(a: float32x4_t, b: float32x4_t, c: f32) -> float32x4_t {
vfmsq_f32(a, b, vdupq_n_f32_vfp4(c))
}
@@ -17856,7 +17856,7 @@ pub unsafe fn vfmsq_n_f32(a: float32x4_t, b: float32x4_t, c: f32) -> float32x4_t
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vsub.i8"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sub))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vsub_s8(a: int8x8_t, b: int8x8_t) -> int8x8_t {
simd_sub(a, b)
}
@@ -17869,7 +17869,7 @@ pub unsafe fn vsub_s8(a: int8x8_t, b: int8x8_t) -> int8x8_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vsub.i8"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sub))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vsubq_s8(a: int8x16_t, b: int8x16_t) -> int8x16_t {
simd_sub(a, b)
}
@@ -17882,7 +17882,7 @@ pub unsafe fn vsubq_s8(a: int8x16_t, b: int8x16_t) -> int8x16_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vsub.i16"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sub))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vsub_s16(a: int16x4_t, b: int16x4_t) -> int16x4_t {
simd_sub(a, b)
}
@@ -17895,7 +17895,7 @@ pub unsafe fn vsub_s16(a: int16x4_t, b: int16x4_t) -> int16x4_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vsub.i16"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sub))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vsubq_s16(a: int16x8_t, b: int16x8_t) -> int16x8_t {
simd_sub(a, b)
}
@@ -17908,7 +17908,7 @@ pub unsafe fn vsubq_s16(a: int16x8_t, b: int16x8_t) -> int16x8_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vsub.i32"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sub))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vsub_s32(a: int32x2_t, b: int32x2_t) -> int32x2_t {
simd_sub(a, b)
}
@@ -17921,7 +17921,7 @@ pub unsafe fn vsub_s32(a: int32x2_t, b: int32x2_t) -> int32x2_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vsub.i32"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sub))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vsubq_s32(a: int32x4_t, b: int32x4_t) -> int32x4_t {
simd_sub(a, b)
}
@@ -17934,7 +17934,7 @@ pub unsafe fn vsubq_s32(a: int32x4_t, b: int32x4_t) -> int32x4_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vsub.i8"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sub))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vsub_u8(a: uint8x8_t, b: uint8x8_t) -> uint8x8_t {
simd_sub(a, b)
}
@@ -17947,7 +17947,7 @@ pub unsafe fn vsub_u8(a: uint8x8_t, b: uint8x8_t) -> uint8x8_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vsub.i8"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sub))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vsubq_u8(a: uint8x16_t, b: uint8x16_t) -> uint8x16_t {
simd_sub(a, b)
}
@@ -17960,7 +17960,7 @@ pub unsafe fn vsubq_u8(a: uint8x16_t, b: uint8x16_t) -> uint8x16_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vsub.i16"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sub))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vsub_u16(a: uint16x4_t, b: uint16x4_t) -> uint16x4_t {
simd_sub(a, b)
}
@@ -17973,7 +17973,7 @@ pub unsafe fn vsub_u16(a: uint16x4_t, b: uint16x4_t) -> uint16x4_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vsub.i16"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sub))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vsubq_u16(a: uint16x8_t, b: uint16x8_t) -> uint16x8_t {
simd_sub(a, b)
}
@@ -17986,7 +17986,7 @@ pub unsafe fn vsubq_u16(a: uint16x8_t, b: uint16x8_t) -> uint16x8_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vsub.i32"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sub))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vsub_u32(a: uint32x2_t, b: uint32x2_t) -> uint32x2_t {
simd_sub(a, b)
}
@@ -17999,7 +17999,7 @@ pub unsafe fn vsub_u32(a: uint32x2_t, b: uint32x2_t) -> uint32x2_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vsub.i32"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sub))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vsubq_u32(a: uint32x4_t, b: uint32x4_t) -> uint32x4_t {
simd_sub(a, b)
}
@@ -18012,7 +18012,7 @@ pub unsafe fn vsubq_u32(a: uint32x4_t, b: uint32x4_t) -> uint32x4_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vsub.i64"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sub))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vsub_s64(a: int64x1_t, b: int64x1_t) -> int64x1_t {
simd_sub(a, b)
}
@@ -18025,7 +18025,7 @@ pub unsafe fn vsub_s64(a: int64x1_t, b: int64x1_t) -> int64x1_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vsub.i64"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sub))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vsubq_s64(a: int64x2_t, b: int64x2_t) -> int64x2_t {
simd_sub(a, b)
}
@@ -18038,7 +18038,7 @@ pub unsafe fn vsubq_s64(a: int64x2_t, b: int64x2_t) -> int64x2_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vsub.i64"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sub))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vsub_u64(a: uint64x1_t, b: uint64x1_t) -> uint64x1_t {
simd_sub(a, b)
}
@@ -18051,7 +18051,7 @@ pub unsafe fn vsub_u64(a: uint64x1_t, b: uint64x1_t) -> uint64x1_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vsub.i64"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sub))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vsubq_u64(a: uint64x2_t, b: uint64x2_t) -> uint64x2_t {
simd_sub(a, b)
}
@@ -18064,7 +18064,7 @@ pub unsafe fn vsubq_u64(a: uint64x2_t, b: uint64x2_t) -> uint64x2_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vsub.f32"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(fsub))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vsub_f32(a: float32x2_t, b: float32x2_t) -> float32x2_t {
simd_sub(a, b)
}
@@ -18077,7 +18077,7 @@ pub unsafe fn vsub_f32(a: float32x2_t, b: float32x2_t) -> float32x2_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vsub.f32"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(fsub))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vsubq_f32(a: float32x4_t, b: float32x4_t) -> float32x4_t {
simd_sub(a, b)
}
@@ -18090,7 +18090,7 @@ pub unsafe fn vsubq_f32(a: float32x4_t, b: float32x4_t) -> float32x4_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vadd_p8(a: poly8x8_t, b: poly8x8_t) -> poly8x8_t {
simd_xor(a, b)
}
@@ -18103,7 +18103,7 @@ pub unsafe fn vadd_p8(a: poly8x8_t, b: poly8x8_t) -> poly8x8_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vadd_p16(a: poly16x4_t, b: poly16x4_t) -> poly16x4_t {
simd_xor(a, b)
}
@@ -18116,7 +18116,7 @@ pub unsafe fn vadd_p16(a: poly16x4_t, b: poly16x4_t) -> poly16x4_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vaddq_p8(a: poly8x16_t, b: poly8x16_t) -> poly8x16_t {
simd_xor(a, b)
}
@@ -18129,7 +18129,7 @@ pub unsafe fn vaddq_p8(a: poly8x16_t, b: poly8x16_t) -> poly8x16_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vaddq_p16(a: poly16x8_t, b: poly16x8_t) -> poly16x8_t {
simd_xor(a, b)
}
@@ -18142,7 +18142,7 @@ pub unsafe fn vaddq_p16(a: poly16x8_t, b: poly16x8_t) -> poly16x8_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vadd_p64(a: poly64x1_t, b: poly64x1_t) -> poly64x1_t {
simd_xor(a, b)
}
@@ -18155,7 +18155,7 @@ pub unsafe fn vadd_p64(a: poly64x1_t, b: poly64x1_t) -> poly64x1_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vaddq_p64(a: poly64x2_t, b: poly64x2_t) -> poly64x2_t {
simd_xor(a, b)
}
@@ -18168,7 +18168,7 @@ pub unsafe fn vaddq_p64(a: poly64x2_t, b: poly64x2_t) -> poly64x2_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vaddq_p128(a: p128, b: p128) -> p128 {
a ^ b
}
@@ -18181,7 +18181,7 @@ pub unsafe fn vaddq_p128(a: p128, b: p128) -> p128 {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vsubhn))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(subhn))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vsubhn_s16(a: int16x8_t, b: int16x8_t) -> int8x8_t {
let c: i16x8 = i16x8::new(8, 8, 8, 8, 8, 8, 8, 8);
simd_cast(simd_shr(simd_sub(a, b), transmute(c)))
@@ -18195,7 +18195,7 @@ pub unsafe fn vsubhn_s16(a: int16x8_t, b: int16x8_t) -> int8x8_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vsubhn))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(subhn))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vsubhn_s32(a: int32x4_t, b: int32x4_t) -> int16x4_t {
let c: i32x4 = i32x4::new(16, 16, 16, 16);
simd_cast(simd_shr(simd_sub(a, b), transmute(c)))
@@ -18209,7 +18209,7 @@ pub unsafe fn vsubhn_s32(a: int32x4_t, b: int32x4_t) -> int16x4_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vsubhn))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(subhn))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vsubhn_s64(a: int64x2_t, b: int64x2_t) -> int32x2_t {
let c: i64x2 = i64x2::new(32, 32);
simd_cast(simd_shr(simd_sub(a, b), transmute(c)))
@@ -18223,7 +18223,7 @@ pub unsafe fn vsubhn_s64(a: int64x2_t, b: int64x2_t) -> int32x2_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vsubhn))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(subhn))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vsubhn_u16(a: uint16x8_t, b: uint16x8_t) -> uint8x8_t {
let c: u16x8 = u16x8::new(8, 8, 8, 8, 8, 8, 8, 8);
simd_cast(simd_shr(simd_sub(a, b), transmute(c)))
@@ -18237,7 +18237,7 @@ pub unsafe fn vsubhn_u16(a: uint16x8_t, b: uint16x8_t) -> uint8x8_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vsubhn))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(subhn))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vsubhn_u32(a: uint32x4_t, b: uint32x4_t) -> uint16x4_t {
let c: u32x4 = u32x4::new(16, 16, 16, 16);
simd_cast(simd_shr(simd_sub(a, b), transmute(c)))
@@ -18251,7 +18251,7 @@ pub unsafe fn vsubhn_u32(a: uint32x4_t, b: uint32x4_t) -> uint16x4_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vsubhn))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(subhn))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vsubhn_u64(a: uint64x2_t, b: uint64x2_t) -> uint32x2_t {
let c: u64x2 = u64x2::new(32, 32);
simd_cast(simd_shr(simd_sub(a, b), transmute(c)))
@@ -18265,7 +18265,7 @@ pub unsafe fn vsubhn_u64(a: uint64x2_t, b: uint64x2_t) -> uint32x2_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vsubhn))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(subhn2))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vsubhn_high_s16(a: int8x8_t, b: int16x8_t, c: int16x8_t) -> int8x16_t {
let d: int8x8_t = vsubhn_s16(b, c);
simd_shuffle16!(a, d, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15])
@@ -18279,7 +18279,7 @@ pub unsafe fn vsubhn_high_s16(a: int8x8_t, b: int16x8_t, c: int16x8_t) -> int8x1
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vsubhn))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(subhn2))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vsubhn_high_s32(a: int16x4_t, b: int32x4_t, c: int32x4_t) -> int16x8_t {
let d: int16x4_t = vsubhn_s32(b, c);
simd_shuffle8!(a, d, [0, 1, 2, 3, 4, 5, 6, 7])
@@ -18293,7 +18293,7 @@ pub unsafe fn vsubhn_high_s32(a: int16x4_t, b: int32x4_t, c: int32x4_t) -> int16
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vsubhn))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(subhn2))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vsubhn_high_s64(a: int32x2_t, b: int64x2_t, c: int64x2_t) -> int32x4_t {
let d: int32x2_t = vsubhn_s64(b, c);
simd_shuffle4!(a, d, [0, 1, 2, 3])
@@ -18307,7 +18307,7 @@ pub unsafe fn vsubhn_high_s64(a: int32x2_t, b: int64x2_t, c: int64x2_t) -> int32
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vsubhn))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(subhn2))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vsubhn_high_u16(a: uint8x8_t, b: uint16x8_t, c: uint16x8_t) -> uint8x16_t {
let d: uint8x8_t = vsubhn_u16(b, c);
simd_shuffle16!(a, d, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15])
@@ -18321,7 +18321,7 @@ pub unsafe fn vsubhn_high_u16(a: uint8x8_t, b: uint16x8_t, c: uint16x8_t) -> uin
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vsubhn))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(subhn2))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vsubhn_high_u32(a: uint16x4_t, b: uint32x4_t, c: uint32x4_t) -> uint16x8_t {
let d: uint16x4_t = vsubhn_u32(b, c);
simd_shuffle8!(a, d, [0, 1, 2, 3, 4, 5, 6, 7])
@@ -18335,7 +18335,7 @@ pub unsafe fn vsubhn_high_u32(a: uint16x4_t, b: uint32x4_t, c: uint32x4_t) -> ui
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vsubhn))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(subhn2))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vsubhn_high_u64(a: uint32x2_t, b: uint64x2_t, c: uint64x2_t) -> uint32x4_t {
let d: uint32x2_t = vsubhn_u64(b, c);
simd_shuffle4!(a, d, [0, 1, 2, 3])
@@ -18349,7 +18349,7 @@ pub unsafe fn vsubhn_high_u64(a: uint32x2_t, b: uint64x2_t, c: uint64x2_t) -> ui
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vhsub.u8"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uhsub))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vhsub_u8(a: uint8x8_t, b: uint8x8_t) -> uint8x8_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -18368,7 +18368,7 @@ vhsub_u8_(a, b)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vhsub.u8"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uhsub))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vhsubq_u8(a: uint8x16_t, b: uint8x16_t) -> uint8x16_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -18387,7 +18387,7 @@ vhsubq_u8_(a, b)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vhsub.u16"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uhsub))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vhsub_u16(a: uint16x4_t, b: uint16x4_t) -> uint16x4_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -18406,7 +18406,7 @@ vhsub_u16_(a, b)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vhsub.u16"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uhsub))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vhsubq_u16(a: uint16x8_t, b: uint16x8_t) -> uint16x8_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -18425,7 +18425,7 @@ vhsubq_u16_(a, b)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vhsub.u32"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uhsub))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vhsub_u32(a: uint32x2_t, b: uint32x2_t) -> uint32x2_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -18444,7 +18444,7 @@ vhsub_u32_(a, b)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vhsub.u32"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uhsub))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vhsubq_u32(a: uint32x4_t, b: uint32x4_t) -> uint32x4_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -18463,7 +18463,7 @@ vhsubq_u32_(a, b)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vhsub.s8"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(shsub))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vhsub_s8(a: int8x8_t, b: int8x8_t) -> int8x8_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -18482,7 +18482,7 @@ vhsub_s8_(a, b)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vhsub.s8"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(shsub))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vhsubq_s8(a: int8x16_t, b: int8x16_t) -> int8x16_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -18501,7 +18501,7 @@ vhsubq_s8_(a, b)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vhsub.s16"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(shsub))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vhsub_s16(a: int16x4_t, b: int16x4_t) -> int16x4_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -18520,7 +18520,7 @@ vhsub_s16_(a, b)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vhsub.s16"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(shsub))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vhsubq_s16(a: int16x8_t, b: int16x8_t) -> int16x8_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -18539,7 +18539,7 @@ vhsubq_s16_(a, b)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vhsub.s32"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(shsub))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vhsub_s32(a: int32x2_t, b: int32x2_t) -> int32x2_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -18558,7 +18558,7 @@ vhsub_s32_(a, b)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vhsub.s32"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(shsub))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vhsubq_s32(a: int32x4_t, b: int32x4_t) -> int32x4_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -18577,7 +18577,7 @@ vhsubq_s32_(a, b)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vsubw))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ssubw))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vsubw_s8(a: int16x8_t, b: int8x8_t) -> int16x8_t {
simd_sub(a, simd_cast(b))
}
@@ -18590,7 +18590,7 @@ pub unsafe fn vsubw_s8(a: int16x8_t, b: int8x8_t) -> int16x8_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vsubw))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ssubw))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vsubw_s16(a: int32x4_t, b: int16x4_t) -> int32x4_t {
simd_sub(a, simd_cast(b))
}
@@ -18603,7 +18603,7 @@ pub unsafe fn vsubw_s16(a: int32x4_t, b: int16x4_t) -> int32x4_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vsubw))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ssubw))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vsubw_s32(a: int64x2_t, b: int32x2_t) -> int64x2_t {
simd_sub(a, simd_cast(b))
}
@@ -18616,7 +18616,7 @@ pub unsafe fn vsubw_s32(a: int64x2_t, b: int32x2_t) -> int64x2_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vsubw))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(usubw))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vsubw_u8(a: uint16x8_t, b: uint8x8_t) -> uint16x8_t {
simd_sub(a, simd_cast(b))
}
@@ -18629,7 +18629,7 @@ pub unsafe fn vsubw_u8(a: uint16x8_t, b: uint8x8_t) -> uint16x8_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vsubw))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(usubw))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vsubw_u16(a: uint32x4_t, b: uint16x4_t) -> uint32x4_t {
simd_sub(a, simd_cast(b))
}
@@ -18642,7 +18642,7 @@ pub unsafe fn vsubw_u16(a: uint32x4_t, b: uint16x4_t) -> uint32x4_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vsubw))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(usubw))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vsubw_u32(a: uint64x2_t, b: uint32x2_t) -> uint64x2_t {
simd_sub(a, simd_cast(b))
}
@@ -18655,7 +18655,7 @@ pub unsafe fn vsubw_u32(a: uint64x2_t, b: uint32x2_t) -> uint64x2_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vsubl))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ssubl))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vsubl_s8(a: int8x8_t, b: int8x8_t) -> int16x8_t {
let c: int16x8_t = simd_cast(a);
let d: int16x8_t = simd_cast(b);
@@ -18670,7 +18670,7 @@ pub unsafe fn vsubl_s8(a: int8x8_t, b: int8x8_t) -> int16x8_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vsubl))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ssubl))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vsubl_s16(a: int16x4_t, b: int16x4_t) -> int32x4_t {
let c: int32x4_t = simd_cast(a);
let d: int32x4_t = simd_cast(b);
@@ -18685,7 +18685,7 @@ pub unsafe fn vsubl_s16(a: int16x4_t, b: int16x4_t) -> int32x4_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vsubl))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ssubl))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vsubl_s32(a: int32x2_t, b: int32x2_t) -> int64x2_t {
let c: int64x2_t = simd_cast(a);
let d: int64x2_t = simd_cast(b);
@@ -18700,7 +18700,7 @@ pub unsafe fn vsubl_s32(a: int32x2_t, b: int32x2_t) -> int64x2_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vsubl))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(usubl))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vsubl_u8(a: uint8x8_t, b: uint8x8_t) -> uint16x8_t {
let c: uint16x8_t = simd_cast(a);
let d: uint16x8_t = simd_cast(b);
@@ -18715,7 +18715,7 @@ pub unsafe fn vsubl_u8(a: uint8x8_t, b: uint8x8_t) -> uint16x8_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vsubl))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(usubl))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vsubl_u16(a: uint16x4_t, b: uint16x4_t) -> uint32x4_t {
let c: uint32x4_t = simd_cast(a);
let d: uint32x4_t = simd_cast(b);
@@ -18730,7 +18730,7 @@ pub unsafe fn vsubl_u16(a: uint16x4_t, b: uint16x4_t) -> uint32x4_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vsubl))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(usubl))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vsubl_u32(a: uint32x2_t, b: uint32x2_t) -> uint64x2_t {
let c: uint64x2_t = simd_cast(a);
let d: uint64x2_t = simd_cast(b);
@@ -18745,7 +18745,7 @@ pub unsafe fn vsubl_u32(a: uint32x2_t, b: uint32x2_t) -> uint64x2_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmax))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(smax))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmax_s8(a: int8x8_t, b: int8x8_t) -> int8x8_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -18764,7 +18764,7 @@ vmax_s8_(a, b)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmax))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(smax))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmaxq_s8(a: int8x16_t, b: int8x16_t) -> int8x16_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -18783,7 +18783,7 @@ vmaxq_s8_(a, b)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmax))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(smax))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmax_s16(a: int16x4_t, b: int16x4_t) -> int16x4_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -18802,7 +18802,7 @@ vmax_s16_(a, b)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmax))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(smax))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmaxq_s16(a: int16x8_t, b: int16x8_t) -> int16x8_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -18821,7 +18821,7 @@ vmaxq_s16_(a, b)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmax))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(smax))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmax_s32(a: int32x2_t, b: int32x2_t) -> int32x2_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -18840,7 +18840,7 @@ vmax_s32_(a, b)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmax))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(smax))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmaxq_s32(a: int32x4_t, b: int32x4_t) -> int32x4_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -18859,7 +18859,7 @@ vmaxq_s32_(a, b)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmax))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(umax))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmax_u8(a: uint8x8_t, b: uint8x8_t) -> uint8x8_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -18878,7 +18878,7 @@ vmax_u8_(a, b)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmax))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(umax))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmaxq_u8(a: uint8x16_t, b: uint8x16_t) -> uint8x16_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -18897,7 +18897,7 @@ vmaxq_u8_(a, b)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmax))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(umax))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmax_u16(a: uint16x4_t, b: uint16x4_t) -> uint16x4_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -18916,7 +18916,7 @@ vmax_u16_(a, b)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmax))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(umax))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmaxq_u16(a: uint16x8_t, b: uint16x8_t) -> uint16x8_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -18935,7 +18935,7 @@ vmaxq_u16_(a, b)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmax))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(umax))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmax_u32(a: uint32x2_t, b: uint32x2_t) -> uint32x2_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -18954,7 +18954,7 @@ vmax_u32_(a, b)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmax))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(umax))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmaxq_u32(a: uint32x4_t, b: uint32x4_t) -> uint32x4_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -18973,7 +18973,7 @@ vmaxq_u32_(a, b)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmax))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(fmax))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmax_f32(a: float32x2_t, b: float32x2_t) -> float32x2_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -18992,7 +18992,7 @@ vmax_f32_(a, b)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmax))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(fmax))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmaxq_f32(a: float32x4_t, b: float32x4_t) -> float32x4_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -19011,7 +19011,7 @@ vmaxq_f32_(a, b)
#[cfg_attr(target_arch = "arm", target_feature(enable = "fp-armv8,v8"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmaxnm))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(fmaxnm))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmaxnm_f32(a: float32x2_t, b: float32x2_t) -> float32x2_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -19030,7 +19030,7 @@ vmaxnm_f32_(a, b)
#[cfg_attr(target_arch = "arm", target_feature(enable = "fp-armv8,v8"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmaxnm))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(fmaxnm))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmaxnmq_f32(a: float32x4_t, b: float32x4_t) -> float32x4_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -19049,7 +19049,7 @@ vmaxnmq_f32_(a, b)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmin))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(smin))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmin_s8(a: int8x8_t, b: int8x8_t) -> int8x8_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -19068,7 +19068,7 @@ vmin_s8_(a, b)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmin))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(smin))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vminq_s8(a: int8x16_t, b: int8x16_t) -> int8x16_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -19087,7 +19087,7 @@ vminq_s8_(a, b)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmin))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(smin))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmin_s16(a: int16x4_t, b: int16x4_t) -> int16x4_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -19106,7 +19106,7 @@ vmin_s16_(a, b)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmin))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(smin))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vminq_s16(a: int16x8_t, b: int16x8_t) -> int16x8_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -19125,7 +19125,7 @@ vminq_s16_(a, b)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmin))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(smin))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmin_s32(a: int32x2_t, b: int32x2_t) -> int32x2_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -19144,7 +19144,7 @@ vmin_s32_(a, b)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmin))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(smin))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vminq_s32(a: int32x4_t, b: int32x4_t) -> int32x4_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -19163,7 +19163,7 @@ vminq_s32_(a, b)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmin))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(umin))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmin_u8(a: uint8x8_t, b: uint8x8_t) -> uint8x8_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -19182,7 +19182,7 @@ vmin_u8_(a, b)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmin))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(umin))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vminq_u8(a: uint8x16_t, b: uint8x16_t) -> uint8x16_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -19201,7 +19201,7 @@ vminq_u8_(a, b)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmin))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(umin))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmin_u16(a: uint16x4_t, b: uint16x4_t) -> uint16x4_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -19220,7 +19220,7 @@ vmin_u16_(a, b)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmin))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(umin))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vminq_u16(a: uint16x8_t, b: uint16x8_t) -> uint16x8_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -19239,7 +19239,7 @@ vminq_u16_(a, b)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmin))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(umin))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmin_u32(a: uint32x2_t, b: uint32x2_t) -> uint32x2_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -19258,7 +19258,7 @@ vmin_u32_(a, b)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmin))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(umin))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vminq_u32(a: uint32x4_t, b: uint32x4_t) -> uint32x4_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -19277,7 +19277,7 @@ vminq_u32_(a, b)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmin))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(fmin))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vmin_f32(a: float32x2_t, b: float32x2_t) -> float32x2_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -19296,7 +19296,7 @@ vmin_f32_(a, b)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmin))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(fmin))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vminq_f32(a: float32x4_t, b: float32x4_t) -> float32x4_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -19315,7 +19315,7 @@ vminq_f32_(a, b)
#[cfg_attr(target_arch = "arm", target_feature(enable = "fp-armv8,v8"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vminnm))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(fminnm))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vminnm_f32(a: float32x2_t, b: float32x2_t) -> float32x2_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -19334,7 +19334,7 @@ vminnm_f32_(a, b)
#[cfg_attr(target_arch = "arm", target_feature(enable = "fp-armv8,v8"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vminnm))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(fminnm))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vminnmq_f32(a: float32x4_t, b: float32x4_t) -> float32x4_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -19353,7 +19353,7 @@ vminnmq_f32_(a, b)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vpadd))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(faddp))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vpadd_f32(a: float32x2_t, b: float32x2_t) -> float32x2_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -19372,7 +19372,7 @@ vpadd_f32_(a, b)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqdmull))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqdmull))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vqdmull_s16(a: int16x4_t, b: int16x4_t) -> int32x4_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -19391,7 +19391,7 @@ vqdmull_s16_(a, b)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqdmull))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqdmull))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vqdmull_s32(a: int32x2_t, b: int32x2_t) -> int64x2_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -19410,7 +19410,7 @@ vqdmull_s32_(a, b)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqdmull))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqdmull))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vqdmull_n_s16(a: int16x4_t, b: i16) -> int32x4_t {
vqdmull_s16(a, vdup_n_s16(b))
}
@@ -19423,7 +19423,7 @@ pub unsafe fn vqdmull_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(vqdmull))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqdmull))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vqdmull_n_s32(a: int32x2_t, b: i32) -> int64x2_t {
vqdmull_s32(a, vdup_n_s32(b))
}
@@ -19437,7 +19437,7 @@ pub unsafe fn vqdmull_n_s32(a: int32x2_t, b: i32) -> int64x2_t {
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqdmull, N = 2))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqdmull, N = 2))]
#[rustc_legacy_const_generics(2)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vqdmull_lane_s16<const N: i32>(a: int16x4_t, b: int16x4_t) -> int32x4_t {
static_assert_imm2!(N);
let b: int16x4_t = simd_shuffle4!(b, b, <const N: i32> [N as u32, N as u32, N as u32, N as u32]);
@@ -19453,7 +19453,7 @@ pub unsafe fn vqdmull_lane_s16<const N: i32>(a: int16x4_t, b: int16x4_t) -> int3
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqdmull, N = 1))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqdmull, N = 1))]
#[rustc_legacy_const_generics(2)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vqdmull_lane_s32<const N: i32>(a: int32x2_t, b: int32x2_t) -> int64x2_t {
static_assert_imm1!(N);
let b: int32x2_t = simd_shuffle2!(b, b, <const N: i32> [N as u32, N as u32]);
@@ -19468,7 +19468,7 @@ pub unsafe fn vqdmull_lane_s32<const N: i32>(a: int32x2_t, b: int32x2_t) -> int6
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqdmlal))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqdmlal))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vqdmlal_s16(a: int32x4_t, b: int16x4_t, c: int16x4_t) -> int32x4_t {
vqaddq_s32(a, vqdmull_s16(b, c))
}
@@ -19481,7 +19481,7 @@ pub unsafe fn vqdmlal_s16(a: int32x4_t, b: int16x4_t, c: int16x4_t) -> int32x4_t
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqdmlal))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqdmlal))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vqdmlal_s32(a: int64x2_t, b: int32x2_t, c: int32x2_t) -> int64x2_t {
vqaddq_s64(a, vqdmull_s32(b, c))
}
@@ -19494,7 +19494,7 @@ pub unsafe fn vqdmlal_s32(a: int64x2_t, b: int32x2_t, c: int32x2_t) -> int64x2_t
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqdmlal))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqdmlal))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vqdmlal_n_s16(a: int32x4_t, b: int16x4_t, c: i16) -> int32x4_t {
vqaddq_s32(a, vqdmull_n_s16(b, c))
}
@@ -19507,7 +19507,7 @@ pub unsafe fn vqdmlal_n_s16(a: int32x4_t, b: int16x4_t, c: i16) -> int32x4_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqdmlal))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqdmlal))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vqdmlal_n_s32(a: int64x2_t, b: int32x2_t, c: i32) -> int64x2_t {
vqaddq_s64(a, vqdmull_n_s32(b, c))
}
@@ -19521,7 +19521,7 @@ pub unsafe fn vqdmlal_n_s32(a: int64x2_t, b: int32x2_t, c: i32) -> int64x2_t {
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqdmlal, N = 2))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqdmlal, N = 2))]
#[rustc_legacy_const_generics(3)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vqdmlal_lane_s16<const N: i32>(a: int32x4_t, b: int16x4_t, c: int16x4_t) -> int32x4_t {
static_assert_imm2!(N);
vqaddq_s32(a, vqdmull_lane_s16::<N>(b, c))
@@ -19536,7 +19536,7 @@ pub unsafe fn vqdmlal_lane_s16<const N: i32>(a: int32x4_t, b: int16x4_t, c: int1
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqdmlal, N = 1))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqdmlal, N = 1))]
#[rustc_legacy_const_generics(3)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vqdmlal_lane_s32<const N: i32>(a: int64x2_t, b: int32x2_t, c: int32x2_t) -> int64x2_t {
static_assert_imm1!(N);
vqaddq_s64(a, vqdmull_lane_s32::<N>(b, c))
@@ -19550,7 +19550,7 @@ pub unsafe fn vqdmlal_lane_s32<const N: i32>(a: int64x2_t, b: int32x2_t, c: int3
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqdmlsl))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqdmlsl))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vqdmlsl_s16(a: int32x4_t, b: int16x4_t, c: int16x4_t) -> int32x4_t {
vqsubq_s32(a, vqdmull_s16(b, c))
}
@@ -19563,7 +19563,7 @@ pub unsafe fn vqdmlsl_s16(a: int32x4_t, b: int16x4_t, c: int16x4_t) -> int32x4_t
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqdmlsl))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqdmlsl))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vqdmlsl_s32(a: int64x2_t, b: int32x2_t, c: int32x2_t) -> int64x2_t {
vqsubq_s64(a, vqdmull_s32(b, c))
}
@@ -19576,7 +19576,7 @@ pub unsafe fn vqdmlsl_s32(a: int64x2_t, b: int32x2_t, c: int32x2_t) -> int64x2_t
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqdmlsl))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqdmlsl))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vqdmlsl_n_s16(a: int32x4_t, b: int16x4_t, c: i16) -> int32x4_t {
vqsubq_s32(a, vqdmull_n_s16(b, c))
}
@@ -19589,7 +19589,7 @@ pub unsafe fn vqdmlsl_n_s16(a: int32x4_t, b: int16x4_t, c: i16) -> int32x4_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqdmlsl))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqdmlsl))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vqdmlsl_n_s32(a: int64x2_t, b: int32x2_t, c: i32) -> int64x2_t {
vqsubq_s64(a, vqdmull_n_s32(b, c))
}
@@ -19603,7 +19603,7 @@ pub unsafe fn vqdmlsl_n_s32(a: int64x2_t, b: int32x2_t, c: i32) -> int64x2_t {
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqdmlsl, N = 2))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqdmlsl, N = 2))]
#[rustc_legacy_const_generics(3)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vqdmlsl_lane_s16<const N: i32>(a: int32x4_t, b: int16x4_t, c: int16x4_t) -> int32x4_t {
static_assert_imm2!(N);
vqsubq_s32(a, vqdmull_lane_s16::<N>(b, c))
@@ -19618,7 +19618,7 @@ pub unsafe fn vqdmlsl_lane_s16<const N: i32>(a: int32x4_t, b: int16x4_t, c: int1
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqdmlsl, N = 1))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqdmlsl, N = 1))]
#[rustc_legacy_const_generics(3)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vqdmlsl_lane_s32<const N: i32>(a: int64x2_t, b: int32x2_t, c: int32x2_t) -> int64x2_t {
static_assert_imm1!(N);
vqsubq_s64(a, vqdmull_lane_s32::<N>(b, c))
@@ -19632,7 +19632,7 @@ pub unsafe fn vqdmlsl_lane_s32<const N: i32>(a: int64x2_t, b: int32x2_t, c: int3
#[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))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vqdmulh_s16(a: int16x4_t, b: int16x4_t) -> int16x4_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -19651,7 +19651,7 @@ vqdmulh_s16_(a, b)
#[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))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vqdmulhq_s16(a: int16x8_t, b: int16x8_t) -> int16x8_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -19670,7 +19670,7 @@ vqdmulhq_s16_(a, b)
#[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))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vqdmulh_s32(a: int32x2_t, b: int32x2_t) -> int32x2_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -19689,7 +19689,7 @@ vqdmulh_s32_(a, b)
#[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))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vqdmulhq_s32(a: int32x4_t, b: int32x4_t) -> int32x4_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -19708,7 +19708,7 @@ vqdmulhq_s32_(a, b)
#[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))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vqdmulh_n_s16(a: int16x4_t, b: i16) -> int16x4_t {
let b: int16x4_t = vdup_n_s16(b);
vqdmulh_s16(a, b)
@@ -19722,7 +19722,7 @@ pub unsafe fn vqdmulh_n_s16(a: int16x4_t, b: i16) -> int16x4_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))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vqdmulh_n_s32(a: int32x2_t, b: i32) -> int32x2_t {
let b: int32x2_t = vdup_n_s32(b);
vqdmulh_s32(a, b)
@@ -19736,7 +19736,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))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
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)
@@ -19750,7 +19750,7 @@ pub unsafe fn vqdmulhq_n_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))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
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)
@@ -19765,7 +19765,7 @@ pub unsafe fn vqdmulhq_n_s32(a: int32x4_t, b: i32) -> int32x4_t {
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqdmulh, LANE = 0))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqdmulh, LANE = 0))]
#[rustc_legacy_const_generics(2)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vqdmulhq_laneq_s16<const LANE: i32>(a: int16x8_t, b: int16x8_t) -> int16x8_t {
static_assert_imm3!(LANE);
vqdmulhq_s16(a, vdupq_n_s16(simd_extract(b, LANE as u32)))
@@ -19780,7 +19780,7 @@ pub unsafe fn vqdmulhq_laneq_s16<const LANE: i32>(a: int16x8_t, b: int16x8_t) ->
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqdmulh, LANE = 0))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqdmulh, LANE = 0))]
#[rustc_legacy_const_generics(2)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vqdmulh_laneq_s16<const LANE: i32>(a: int16x4_t, b: int16x8_t) -> int16x4_t {
static_assert_imm3!(LANE);
vqdmulh_s16(a, vdup_n_s16(simd_extract(b, LANE as u32)))
@@ -19795,7 +19795,7 @@ pub unsafe fn vqdmulh_laneq_s16<const LANE: i32>(a: int16x4_t, b: int16x8_t) ->
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqdmulh, LANE = 0))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqdmulh, LANE = 0))]
#[rustc_legacy_const_generics(2)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vqdmulhq_laneq_s32<const LANE: i32>(a: int32x4_t, b: int32x4_t) -> int32x4_t {
static_assert_imm2!(LANE);
vqdmulhq_s32(a, vdupq_n_s32(simd_extract(b, LANE as u32)))
@@ -19810,7 +19810,7 @@ pub unsafe fn vqdmulhq_laneq_s32<const LANE: i32>(a: int32x4_t, b: int32x4_t) ->
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqdmulh, LANE = 0))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqdmulh, LANE = 0))]
#[rustc_legacy_const_generics(2)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vqdmulh_laneq_s32<const LANE: i32>(a: int32x2_t, b: int32x4_t) -> int32x2_t {
static_assert_imm2!(LANE);
vqdmulh_s32(a, vdup_n_s32(simd_extract(b, LANE as u32)))
@@ -19824,7 +19824,7 @@ pub unsafe fn vqdmulh_laneq_s32<const LANE: i32>(a: int32x2_t, b: int32x4_t) ->
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqmovn))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqxtn))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vqmovn_s16(a: int16x8_t) -> int8x8_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -19843,7 +19843,7 @@ vqmovn_s16_(a)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqmovn))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqxtn))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vqmovn_s32(a: int32x4_t) -> int16x4_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -19862,7 +19862,7 @@ vqmovn_s32_(a)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqmovn))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqxtn))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vqmovn_s64(a: int64x2_t) -> int32x2_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -19881,7 +19881,7 @@ vqmovn_s64_(a)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqmovn))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uqxtn))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vqmovn_u16(a: uint16x8_t) -> uint8x8_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -19900,7 +19900,7 @@ vqmovn_u16_(a)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqmovn))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uqxtn))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vqmovn_u32(a: uint32x4_t) -> uint16x4_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -19919,7 +19919,7 @@ vqmovn_u32_(a)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqmovn))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uqxtn))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vqmovn_u64(a: uint64x2_t) -> uint32x2_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -19938,7 +19938,7 @@ vqmovn_u64_(a)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqmovun))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqxtun))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vqmovun_s16(a: int16x8_t) -> uint8x8_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -19957,7 +19957,7 @@ vqmovun_s16_(a)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqmovun))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqxtun))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vqmovun_s32(a: int32x4_t) -> uint16x4_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -19976,7 +19976,7 @@ vqmovun_s32_(a)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqmovun))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqxtun))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vqmovun_s64(a: int64x2_t) -> uint32x2_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -19995,7 +19995,7 @@ vqmovun_s64_(a)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqrdmulh))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqrdmulh))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vqrdmulh_s16(a: int16x4_t, b: int16x4_t) -> int16x4_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -20014,7 +20014,7 @@ vqrdmulh_s16_(a, b)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqrdmulh))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqrdmulh))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vqrdmulhq_s16(a: int16x8_t, b: int16x8_t) -> int16x8_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -20033,7 +20033,7 @@ vqrdmulhq_s16_(a, b)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqrdmulh))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqrdmulh))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vqrdmulh_s32(a: int32x2_t, b: int32x2_t) -> int32x2_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -20052,7 +20052,7 @@ vqrdmulh_s32_(a, b)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqrdmulh))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqrdmulh))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vqrdmulhq_s32(a: int32x4_t, b: int32x4_t) -> int32x4_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -20071,7 +20071,7 @@ vqrdmulhq_s32_(a, b)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqrdmulh))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqrdmulh))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vqrdmulh_n_s16(a: int16x4_t, b: i16) -> int16x4_t {
vqrdmulh_s16(a, vdup_n_s16(b))
}
@@ -20084,7 +20084,7 @@ pub unsafe fn vqrdmulh_n_s16(a: int16x4_t, b: i16) -> int16x4_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqrdmulh))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqrdmulh))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vqrdmulhq_n_s16(a: int16x8_t, b: i16) -> int16x8_t {
vqrdmulhq_s16(a, vdupq_n_s16(b))
}
@@ -20097,7 +20097,7 @@ pub unsafe fn vqrdmulhq_n_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(vqrdmulh))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqrdmulh))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vqrdmulh_n_s32(a: int32x2_t, b: i32) -> int32x2_t {
vqrdmulh_s32(a, vdup_n_s32(b))
}
@@ -20110,7 +20110,7 @@ pub unsafe fn vqrdmulh_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(vqrdmulh))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqrdmulh))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vqrdmulhq_n_s32(a: int32x4_t, b: i32) -> int32x4_t {
vqrdmulhq_s32(a, vdupq_n_s32(b))
}
@@ -20124,7 +20124,7 @@ pub unsafe fn vqrdmulhq_n_s32(a: int32x4_t, b: i32) -> int32x4_t {
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqrdmulh, LANE = 1))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqrdmulh, LANE = 1))]
#[rustc_legacy_const_generics(2)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vqrdmulh_lane_s16<const LANE: i32>(a: int16x4_t, b: int16x4_t) -> int16x4_t {
static_assert_imm2!(LANE);
let b: int16x4_t = simd_shuffle4!(b, b, <const LANE: i32> [LANE as u32, LANE as u32, LANE as u32, LANE as u32]);
@@ -20140,7 +20140,7 @@ pub unsafe fn vqrdmulh_lane_s16<const LANE: i32>(a: int16x4_t, b: int16x4_t) ->
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqrdmulh, LANE = 1))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqrdmulh, LANE = 1))]
#[rustc_legacy_const_generics(2)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vqrdmulh_laneq_s16<const LANE: i32>(a: int16x4_t, b: int16x8_t) -> int16x4_t {
static_assert_imm3!(LANE);
let b: int16x4_t = simd_shuffle4!(b, b, <const LANE: i32> [LANE as u32, LANE as u32, LANE as u32, LANE as u32]);
@@ -20156,7 +20156,7 @@ pub unsafe fn vqrdmulh_laneq_s16<const LANE: i32>(a: int16x4_t, b: int16x8_t) ->
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqrdmulh, LANE = 1))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqrdmulh, LANE = 1))]
#[rustc_legacy_const_generics(2)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vqrdmulhq_lane_s16<const LANE: i32>(a: int16x8_t, b: int16x4_t) -> int16x8_t {
static_assert_imm2!(LANE);
let b: int16x8_t = simd_shuffle8!(b, b, <const LANE: i32> [LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32]);
@@ -20172,7 +20172,7 @@ pub unsafe fn vqrdmulhq_lane_s16<const LANE: i32>(a: int16x8_t, b: int16x4_t) ->
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqrdmulh, LANE = 1))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqrdmulh, LANE = 1))]
#[rustc_legacy_const_generics(2)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vqrdmulhq_laneq_s16<const LANE: i32>(a: int16x8_t, b: int16x8_t) -> int16x8_t {
static_assert_imm3!(LANE);
let b: int16x8_t = simd_shuffle8!(b, b, <const LANE: i32> [LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32]);
@@ -20188,7 +20188,7 @@ pub unsafe fn vqrdmulhq_laneq_s16<const LANE: i32>(a: int16x8_t, b: int16x8_t) -
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqrdmulh, LANE = 1))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqrdmulh, LANE = 1))]
#[rustc_legacy_const_generics(2)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vqrdmulh_lane_s32<const LANE: i32>(a: int32x2_t, b: int32x2_t) -> int32x2_t {
static_assert_imm1!(LANE);
let b: int32x2_t = simd_shuffle2!(b, b, <const LANE: i32> [LANE as u32, LANE as u32]);
@@ -20204,7 +20204,7 @@ pub unsafe fn vqrdmulh_lane_s32<const LANE: i32>(a: int32x2_t, b: int32x2_t) ->
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqrdmulh, LANE = 1))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqrdmulh, LANE = 1))]
#[rustc_legacy_const_generics(2)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vqrdmulh_laneq_s32<const LANE: i32>(a: int32x2_t, b: int32x4_t) -> int32x2_t {
static_assert_imm2!(LANE);
let b: int32x2_t = simd_shuffle2!(b, b, <const LANE: i32> [LANE as u32, LANE as u32]);
@@ -20220,7 +20220,7 @@ pub unsafe fn vqrdmulh_laneq_s32<const LANE: i32>(a: int32x2_t, b: int32x4_t) ->
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqrdmulh, LANE = 1))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqrdmulh, LANE = 1))]
#[rustc_legacy_const_generics(2)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vqrdmulhq_lane_s32<const LANE: i32>(a: int32x4_t, b: int32x2_t) -> int32x4_t {
static_assert_imm1!(LANE);
let b: int32x4_t = simd_shuffle4!(b, b, <const LANE: i32> [LANE as u32, LANE as u32, LANE as u32, LANE as u32]);
@@ -20236,7 +20236,7 @@ pub unsafe fn vqrdmulhq_lane_s32<const LANE: i32>(a: int32x4_t, b: int32x2_t) ->
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqrdmulh, LANE = 1))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqrdmulh, LANE = 1))]
#[rustc_legacy_const_generics(2)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vqrdmulhq_laneq_s32<const LANE: i32>(a: int32x4_t, b: int32x4_t) -> int32x4_t {
static_assert_imm2!(LANE);
let b: int32x4_t = simd_shuffle4!(b, b, <const LANE: i32> [LANE as u32, LANE as u32, LANE as u32, LANE as u32]);
@@ -20251,7 +20251,7 @@ pub unsafe fn vqrdmulhq_laneq_s32<const LANE: i32>(a: int32x4_t, b: int32x4_t) -
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqrshl))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqrshl))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vqrshl_s8(a: int8x8_t, b: int8x8_t) -> int8x8_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -20270,7 +20270,7 @@ vqrshl_s8_(a, b)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqrshl))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqrshl))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vqrshlq_s8(a: int8x16_t, b: int8x16_t) -> int8x16_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -20289,7 +20289,7 @@ vqrshlq_s8_(a, b)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqrshl))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqrshl))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vqrshl_s16(a: int16x4_t, b: int16x4_t) -> int16x4_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -20308,7 +20308,7 @@ vqrshl_s16_(a, b)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqrshl))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqrshl))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vqrshlq_s16(a: int16x8_t, b: int16x8_t) -> int16x8_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -20327,7 +20327,7 @@ vqrshlq_s16_(a, b)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqrshl))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqrshl))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vqrshl_s32(a: int32x2_t, b: int32x2_t) -> int32x2_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -20346,7 +20346,7 @@ vqrshl_s32_(a, b)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqrshl))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqrshl))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vqrshlq_s32(a: int32x4_t, b: int32x4_t) -> int32x4_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -20365,7 +20365,7 @@ vqrshlq_s32_(a, b)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqrshl))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqrshl))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vqrshl_s64(a: int64x1_t, b: int64x1_t) -> int64x1_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -20384,7 +20384,7 @@ vqrshl_s64_(a, b)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqrshl))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqrshl))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vqrshlq_s64(a: int64x2_t, b: int64x2_t) -> int64x2_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -20403,7 +20403,7 @@ vqrshlq_s64_(a, b)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqrshl))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uqrshl))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vqrshl_u8(a: uint8x8_t, b: int8x8_t) -> uint8x8_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -20422,7 +20422,7 @@ vqrshl_u8_(a, b)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqrshl))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uqrshl))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vqrshlq_u8(a: uint8x16_t, b: int8x16_t) -> uint8x16_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -20441,7 +20441,7 @@ vqrshlq_u8_(a, b)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqrshl))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uqrshl))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vqrshl_u16(a: uint16x4_t, b: int16x4_t) -> uint16x4_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -20460,7 +20460,7 @@ vqrshl_u16_(a, b)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqrshl))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uqrshl))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vqrshlq_u16(a: uint16x8_t, b: int16x8_t) -> uint16x8_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -20479,7 +20479,7 @@ vqrshlq_u16_(a, b)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqrshl))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uqrshl))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vqrshl_u32(a: uint32x2_t, b: int32x2_t) -> uint32x2_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -20498,7 +20498,7 @@ vqrshl_u32_(a, b)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqrshl))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uqrshl))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vqrshlq_u32(a: uint32x4_t, b: int32x4_t) -> uint32x4_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -20517,7 +20517,7 @@ vqrshlq_u32_(a, b)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqrshl))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uqrshl))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vqrshl_u64(a: uint64x1_t, b: int64x1_t) -> uint64x1_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -20536,7 +20536,7 @@ vqrshl_u64_(a, b)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqrshl))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uqrshl))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vqrshlq_u64(a: uint64x2_t, b: int64x2_t) -> uint64x2_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -20888,7 +20888,7 @@ vqrshrun_n_s64_(a, N)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqshl))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqshl))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vqshl_s8(a: int8x8_t, b: int8x8_t) -> int8x8_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -20907,7 +20907,7 @@ vqshl_s8_(a, b)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqshl))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqshl))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vqshlq_s8(a: int8x16_t, b: int8x16_t) -> int8x16_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -20926,7 +20926,7 @@ vqshlq_s8_(a, b)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqshl))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqshl))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vqshl_s16(a: int16x4_t, b: int16x4_t) -> int16x4_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -20945,7 +20945,7 @@ vqshl_s16_(a, b)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqshl))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqshl))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vqshlq_s16(a: int16x8_t, b: int16x8_t) -> int16x8_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -20964,7 +20964,7 @@ vqshlq_s16_(a, b)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqshl))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqshl))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vqshl_s32(a: int32x2_t, b: int32x2_t) -> int32x2_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -20983,7 +20983,7 @@ vqshl_s32_(a, b)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqshl))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqshl))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vqshlq_s32(a: int32x4_t, b: int32x4_t) -> int32x4_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -21002,7 +21002,7 @@ vqshlq_s32_(a, b)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqshl))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqshl))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vqshl_s64(a: int64x1_t, b: int64x1_t) -> int64x1_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -21021,7 +21021,7 @@ vqshl_s64_(a, b)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqshl))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqshl))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vqshlq_s64(a: int64x2_t, b: int64x2_t) -> int64x2_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -21040,7 +21040,7 @@ vqshlq_s64_(a, b)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqshl))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uqshl))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vqshl_u8(a: uint8x8_t, b: int8x8_t) -> uint8x8_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -21059,7 +21059,7 @@ vqshl_u8_(a, b)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqshl))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uqshl))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vqshlq_u8(a: uint8x16_t, b: int8x16_t) -> uint8x16_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -21078,7 +21078,7 @@ vqshlq_u8_(a, b)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqshl))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uqshl))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vqshl_u16(a: uint16x4_t, b: int16x4_t) -> uint16x4_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -21097,7 +21097,7 @@ vqshl_u16_(a, b)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqshl))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uqshl))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vqshlq_u16(a: uint16x8_t, b: int16x8_t) -> uint16x8_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -21116,7 +21116,7 @@ vqshlq_u16_(a, b)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqshl))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uqshl))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vqshl_u32(a: uint32x2_t, b: int32x2_t) -> uint32x2_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -21135,7 +21135,7 @@ vqshl_u32_(a, b)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqshl))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uqshl))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vqshlq_u32(a: uint32x4_t, b: int32x4_t) -> uint32x4_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -21154,7 +21154,7 @@ vqshlq_u32_(a, b)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqshl))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uqshl))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vqshl_u64(a: uint64x1_t, b: int64x1_t) -> uint64x1_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -21173,7 +21173,7 @@ vqshl_u64_(a, b)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqshl))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uqshl))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vqshlq_u64(a: uint64x2_t, b: int64x2_t) -> uint64x2_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -21193,7 +21193,7 @@ vqshlq_u64_(a, b)
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqshl, N = 2))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqshl, N = 2))]
#[rustc_legacy_const_generics(1)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vqshl_n_s8<const N: i32>(a: int8x8_t) -> int8x8_t {
static_assert_imm3!(N);
vqshl_s8(a, vdup_n_s8(N as _))
@@ -21208,7 +21208,7 @@ pub unsafe fn vqshl_n_s8<const N: i32>(a: int8x8_t) -> int8x8_t {
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqshl, N = 2))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqshl, N = 2))]
#[rustc_legacy_const_generics(1)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vqshlq_n_s8<const N: i32>(a: int8x16_t) -> int8x16_t {
static_assert_imm3!(N);
vqshlq_s8(a, vdupq_n_s8(N as _))
@@ -21223,7 +21223,7 @@ pub unsafe fn vqshlq_n_s8<const N: i32>(a: int8x16_t) -> int8x16_t {
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqshl, N = 2))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqshl, N = 2))]
#[rustc_legacy_const_generics(1)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vqshl_n_s16<const N: i32>(a: int16x4_t) -> int16x4_t {
static_assert_imm4!(N);
vqshl_s16(a, vdup_n_s16(N as _))
@@ -21238,7 +21238,7 @@ pub unsafe fn vqshl_n_s16<const N: i32>(a: int16x4_t) -> int16x4_t {
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqshl, N = 2))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqshl, N = 2))]
#[rustc_legacy_const_generics(1)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vqshlq_n_s16<const N: i32>(a: int16x8_t) -> int16x8_t {
static_assert_imm4!(N);
vqshlq_s16(a, vdupq_n_s16(N as _))
@@ -21253,7 +21253,7 @@ pub unsafe fn vqshlq_n_s16<const N: i32>(a: int16x8_t) -> int16x8_t {
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqshl, N = 2))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqshl, N = 2))]
#[rustc_legacy_const_generics(1)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vqshl_n_s32<const N: i32>(a: int32x2_t) -> int32x2_t {
static_assert_imm5!(N);
vqshl_s32(a, vdup_n_s32(N as _))
@@ -21268,7 +21268,7 @@ pub unsafe fn vqshl_n_s32<const N: i32>(a: int32x2_t) -> int32x2_t {
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqshl, N = 2))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqshl, N = 2))]
#[rustc_legacy_const_generics(1)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vqshlq_n_s32<const N: i32>(a: int32x4_t) -> int32x4_t {
static_assert_imm5!(N);
vqshlq_s32(a, vdupq_n_s32(N as _))
@@ -21283,7 +21283,7 @@ pub unsafe fn vqshlq_n_s32<const N: i32>(a: int32x4_t) -> int32x4_t {
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqshl, N = 2))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqshl, N = 2))]
#[rustc_legacy_const_generics(1)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vqshl_n_s64<const N: i32>(a: int64x1_t) -> int64x1_t {
static_assert_imm6!(N);
vqshl_s64(a, vdup_n_s64(N as _))
@@ -21298,7 +21298,7 @@ pub unsafe fn vqshl_n_s64<const N: i32>(a: int64x1_t) -> int64x1_t {
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqshl, N = 2))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqshl, N = 2))]
#[rustc_legacy_const_generics(1)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vqshlq_n_s64<const N: i32>(a: int64x2_t) -> int64x2_t {
static_assert_imm6!(N);
vqshlq_s64(a, vdupq_n_s64(N as _))
@@ -21313,7 +21313,7 @@ pub unsafe fn vqshlq_n_s64<const N: i32>(a: int64x2_t) -> int64x2_t {
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqshl, N = 2))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uqshl, N = 2))]
#[rustc_legacy_const_generics(1)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vqshl_n_u8<const N: i32>(a: uint8x8_t) -> uint8x8_t {
static_assert_imm3!(N);
vqshl_u8(a, vdup_n_s8(N as _))
@@ -21328,7 +21328,7 @@ pub unsafe fn vqshl_n_u8<const N: i32>(a: uint8x8_t) -> uint8x8_t {
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqshl, N = 2))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uqshl, N = 2))]
#[rustc_legacy_const_generics(1)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vqshlq_n_u8<const N: i32>(a: uint8x16_t) -> uint8x16_t {
static_assert_imm3!(N);
vqshlq_u8(a, vdupq_n_s8(N as _))
@@ -21343,7 +21343,7 @@ pub unsafe fn vqshlq_n_u8<const N: i32>(a: uint8x16_t) -> uint8x16_t {
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqshl, N = 2))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uqshl, N = 2))]
#[rustc_legacy_const_generics(1)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vqshl_n_u16<const N: i32>(a: uint16x4_t) -> uint16x4_t {
static_assert_imm4!(N);
vqshl_u16(a, vdup_n_s16(N as _))
@@ -21358,7 +21358,7 @@ pub unsafe fn vqshl_n_u16<const N: i32>(a: uint16x4_t) -> uint16x4_t {
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqshl, N = 2))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uqshl, N = 2))]
#[rustc_legacy_const_generics(1)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vqshlq_n_u16<const N: i32>(a: uint16x8_t) -> uint16x8_t {
static_assert_imm4!(N);
vqshlq_u16(a, vdupq_n_s16(N as _))
@@ -21373,7 +21373,7 @@ pub unsafe fn vqshlq_n_u16<const N: i32>(a: uint16x8_t) -> uint16x8_t {
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqshl, N = 2))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uqshl, N = 2))]
#[rustc_legacy_const_generics(1)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vqshl_n_u32<const N: i32>(a: uint32x2_t) -> uint32x2_t {
static_assert_imm5!(N);
vqshl_u32(a, vdup_n_s32(N as _))
@@ -21388,7 +21388,7 @@ pub unsafe fn vqshl_n_u32<const N: i32>(a: uint32x2_t) -> uint32x2_t {
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqshl, N = 2))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uqshl, N = 2))]
#[rustc_legacy_const_generics(1)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vqshlq_n_u32<const N: i32>(a: uint32x4_t) -> uint32x4_t {
static_assert_imm5!(N);
vqshlq_u32(a, vdupq_n_s32(N as _))
@@ -21403,7 +21403,7 @@ pub unsafe fn vqshlq_n_u32<const N: i32>(a: uint32x4_t) -> uint32x4_t {
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqshl, N = 2))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uqshl, N = 2))]
#[rustc_legacy_const_generics(1)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vqshl_n_u64<const N: i32>(a: uint64x1_t) -> uint64x1_t {
static_assert_imm6!(N);
vqshl_u64(a, vdup_n_s64(N as _))
@@ -21418,7 +21418,7 @@ pub unsafe fn vqshl_n_u64<const N: i32>(a: uint64x1_t) -> uint64x1_t {
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqshl, N = 2))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uqshl, N = 2))]
#[rustc_legacy_const_generics(1)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vqshlq_n_u64<const N: i32>(a: uint64x2_t) -> uint64x2_t {
static_assert_imm6!(N);
vqshlq_u64(a, vdupq_n_s64(N as _))
@@ -22061,7 +22061,7 @@ vqshrun_n_s64_(a, N)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrsqrte))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(frsqrte))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vrsqrte_f32(a: float32x2_t) -> float32x2_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -22080,7 +22080,7 @@ vrsqrte_f32_(a)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrsqrte))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(frsqrte))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vrsqrteq_f32(a: float32x4_t) -> float32x4_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -22099,7 +22099,7 @@ vrsqrteq_f32_(a)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrsqrte))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ursqrte))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vrsqrte_u32(a: uint32x2_t) -> uint32x2_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -22118,7 +22118,7 @@ vrsqrte_u32_(a)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrsqrte))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ursqrte))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vrsqrteq_u32(a: uint32x4_t) -> uint32x4_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -22137,7 +22137,7 @@ vrsqrteq_u32_(a)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrsqrts))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(frsqrts))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vrsqrts_f32(a: float32x2_t, b: float32x2_t) -> float32x2_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -22156,7 +22156,7 @@ vrsqrts_f32_(a, b)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrsqrts))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(frsqrts))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vrsqrtsq_f32(a: float32x4_t, b: float32x4_t) -> float32x4_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -22175,7 +22175,7 @@ vrsqrtsq_f32_(a, b)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrecpe))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(frecpe))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vrecpe_f32(a: float32x2_t) -> float32x2_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -22194,7 +22194,7 @@ vrecpe_f32_(a)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrecpe))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(frecpe))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vrecpeq_f32(a: float32x4_t) -> float32x4_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -22213,7 +22213,7 @@ vrecpeq_f32_(a)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrecpe))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(urecpe))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vrecpe_u32(a: uint32x2_t) -> uint32x2_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -22232,7 +22232,7 @@ vrecpe_u32_(a)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrecpe))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(urecpe))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vrecpeq_u32(a: uint32x4_t) -> uint32x4_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -22251,7 +22251,7 @@ vrecpeq_u32_(a)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrecps))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(frecps))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vrecps_f32(a: float32x2_t, b: float32x2_t) -> float32x2_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -22270,7 +22270,7 @@ vrecps_f32_(a, b)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrecps))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(frecps))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vrecpsq_f32(a: float32x4_t, b: float32x4_t) -> float32x4_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -22289,7 +22289,7 @@ vrecpsq_f32_(a, b)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpret_s8_u8(a: uint8x8_t) -> int8x8_t {
transmute(a)
}
@@ -22302,7 +22302,7 @@ pub unsafe fn vreinterpret_s8_u8(a: uint8x8_t) -> int8x8_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpret_s8_p8(a: poly8x8_t) -> int8x8_t {
transmute(a)
}
@@ -22315,7 +22315,7 @@ pub unsafe fn vreinterpret_s8_p8(a: poly8x8_t) -> int8x8_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpret_s16_p16(a: poly16x4_t) -> int16x4_t {
transmute(a)
}
@@ -22328,7 +22328,7 @@ pub unsafe fn vreinterpret_s16_p16(a: poly16x4_t) -> int16x4_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpret_s16_u16(a: uint16x4_t) -> int16x4_t {
transmute(a)
}
@@ -22341,7 +22341,7 @@ pub unsafe fn vreinterpret_s16_u16(a: uint16x4_t) -> int16x4_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpret_s32_u32(a: uint32x2_t) -> int32x2_t {
transmute(a)
}
@@ -22354,7 +22354,7 @@ pub unsafe fn vreinterpret_s32_u32(a: uint32x2_t) -> int32x2_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpret_s64_u64(a: uint64x1_t) -> int64x1_t {
transmute(a)
}
@@ -22367,7 +22367,7 @@ pub unsafe fn vreinterpret_s64_u64(a: uint64x1_t) -> int64x1_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpretq_s8_u8(a: uint8x16_t) -> int8x16_t {
transmute(a)
}
@@ -22380,7 +22380,7 @@ pub unsafe fn vreinterpretq_s8_u8(a: uint8x16_t) -> int8x16_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpretq_s8_p8(a: poly8x16_t) -> int8x16_t {
transmute(a)
}
@@ -22393,7 +22393,7 @@ pub unsafe fn vreinterpretq_s8_p8(a: poly8x16_t) -> int8x16_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpretq_s16_p16(a: poly16x8_t) -> int16x8_t {
transmute(a)
}
@@ -22406,7 +22406,7 @@ pub unsafe fn vreinterpretq_s16_p16(a: poly16x8_t) -> int16x8_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpretq_s16_u16(a: uint16x8_t) -> int16x8_t {
transmute(a)
}
@@ -22419,7 +22419,7 @@ pub unsafe fn vreinterpretq_s16_u16(a: uint16x8_t) -> int16x8_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpretq_s32_u32(a: uint32x4_t) -> int32x4_t {
transmute(a)
}
@@ -22432,7 +22432,7 @@ pub unsafe fn vreinterpretq_s32_u32(a: uint32x4_t) -> int32x4_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpretq_s64_u64(a: uint64x2_t) -> int64x2_t {
transmute(a)
}
@@ -22445,7 +22445,7 @@ pub unsafe fn vreinterpretq_s64_u64(a: uint64x2_t) -> int64x2_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpret_u8_p8(a: poly8x8_t) -> uint8x8_t {
transmute(a)
}
@@ -22458,7 +22458,7 @@ pub unsafe fn vreinterpret_u8_p8(a: poly8x8_t) -> uint8x8_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpret_u8_s8(a: int8x8_t) -> uint8x8_t {
transmute(a)
}
@@ -22471,7 +22471,7 @@ pub unsafe fn vreinterpret_u8_s8(a: int8x8_t) -> uint8x8_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpret_u16_p16(a: poly16x4_t) -> uint16x4_t {
transmute(a)
}
@@ -22484,7 +22484,7 @@ pub unsafe fn vreinterpret_u16_p16(a: poly16x4_t) -> uint16x4_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpret_u16_s16(a: int16x4_t) -> uint16x4_t {
transmute(a)
}
@@ -22497,7 +22497,7 @@ pub unsafe fn vreinterpret_u16_s16(a: int16x4_t) -> uint16x4_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpret_u32_s32(a: int32x2_t) -> uint32x2_t {
transmute(a)
}
@@ -22510,7 +22510,7 @@ pub unsafe fn vreinterpret_u32_s32(a: int32x2_t) -> uint32x2_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpret_u64_s64(a: int64x1_t) -> uint64x1_t {
transmute(a)
}
@@ -22523,7 +22523,7 @@ pub unsafe fn vreinterpret_u64_s64(a: int64x1_t) -> uint64x1_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpretq_u8_p8(a: poly8x16_t) -> uint8x16_t {
transmute(a)
}
@@ -22536,7 +22536,7 @@ pub unsafe fn vreinterpretq_u8_p8(a: poly8x16_t) -> uint8x16_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpretq_u8_s8(a: int8x16_t) -> uint8x16_t {
transmute(a)
}
@@ -22549,7 +22549,7 @@ pub unsafe fn vreinterpretq_u8_s8(a: int8x16_t) -> uint8x16_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpretq_u16_p16(a: poly16x8_t) -> uint16x8_t {
transmute(a)
}
@@ -22562,7 +22562,7 @@ pub unsafe fn vreinterpretq_u16_p16(a: poly16x8_t) -> uint16x8_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpretq_u16_s16(a: int16x8_t) -> uint16x8_t {
transmute(a)
}
@@ -22575,7 +22575,7 @@ pub unsafe fn vreinterpretq_u16_s16(a: int16x8_t) -> uint16x8_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpretq_u32_s32(a: int32x4_t) -> uint32x4_t {
transmute(a)
}
@@ -22588,7 +22588,7 @@ pub unsafe fn vreinterpretq_u32_s32(a: int32x4_t) -> uint32x4_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpretq_u64_s64(a: int64x2_t) -> uint64x2_t {
transmute(a)
}
@@ -22601,7 +22601,7 @@ pub unsafe fn vreinterpretq_u64_s64(a: int64x2_t) -> uint64x2_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpret_p8_s8(a: int8x8_t) -> poly8x8_t {
transmute(a)
}
@@ -22614,7 +22614,7 @@ pub unsafe fn vreinterpret_p8_s8(a: int8x8_t) -> poly8x8_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpret_p8_u8(a: uint8x8_t) -> poly8x8_t {
transmute(a)
}
@@ -22627,7 +22627,7 @@ pub unsafe fn vreinterpret_p8_u8(a: uint8x8_t) -> poly8x8_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpret_p16_s16(a: int16x4_t) -> poly16x4_t {
transmute(a)
}
@@ -22640,7 +22640,7 @@ pub unsafe fn vreinterpret_p16_s16(a: int16x4_t) -> poly16x4_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpret_p16_u16(a: uint16x4_t) -> poly16x4_t {
transmute(a)
}
@@ -22653,7 +22653,7 @@ pub unsafe fn vreinterpret_p16_u16(a: uint16x4_t) -> poly16x4_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpretq_p8_s8(a: int8x16_t) -> poly8x16_t {
transmute(a)
}
@@ -22666,7 +22666,7 @@ pub unsafe fn vreinterpretq_p8_s8(a: int8x16_t) -> poly8x16_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpretq_p8_u8(a: uint8x16_t) -> poly8x16_t {
transmute(a)
}
@@ -22679,7 +22679,7 @@ pub unsafe fn vreinterpretq_p8_u8(a: uint8x16_t) -> poly8x16_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpretq_p16_s16(a: int16x8_t) -> poly16x8_t {
transmute(a)
}
@@ -22692,7 +22692,7 @@ pub unsafe fn vreinterpretq_p16_s16(a: int16x8_t) -> poly16x8_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpretq_p16_u16(a: uint16x8_t) -> poly16x8_t {
transmute(a)
}
@@ -22705,7 +22705,7 @@ pub unsafe fn vreinterpretq_p16_u16(a: uint16x8_t) -> poly16x8_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpret_s8_s16(a: int16x4_t) -> int8x8_t {
transmute(a)
}
@@ -22718,7 +22718,7 @@ pub unsafe fn vreinterpret_s8_s16(a: int16x4_t) -> int8x8_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpret_s8_u16(a: uint16x4_t) -> int8x8_t {
transmute(a)
}
@@ -22731,7 +22731,7 @@ pub unsafe fn vreinterpret_s8_u16(a: uint16x4_t) -> int8x8_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpret_s8_p16(a: poly16x4_t) -> int8x8_t {
transmute(a)
}
@@ -22744,7 +22744,7 @@ pub unsafe fn vreinterpret_s8_p16(a: poly16x4_t) -> int8x8_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpret_s16_s32(a: int32x2_t) -> int16x4_t {
transmute(a)
}
@@ -22757,7 +22757,7 @@ pub unsafe fn vreinterpret_s16_s32(a: int32x2_t) -> int16x4_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpret_s16_u32(a: uint32x2_t) -> int16x4_t {
transmute(a)
}
@@ -22770,7 +22770,7 @@ pub unsafe fn vreinterpret_s16_u32(a: uint32x2_t) -> int16x4_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpret_s32_s64(a: int64x1_t) -> int32x2_t {
transmute(a)
}
@@ -22783,7 +22783,7 @@ pub unsafe fn vreinterpret_s32_s64(a: int64x1_t) -> int32x2_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpret_s32_u64(a: uint64x1_t) -> int32x2_t {
transmute(a)
}
@@ -22796,7 +22796,7 @@ pub unsafe fn vreinterpret_s32_u64(a: uint64x1_t) -> int32x2_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpretq_s8_s16(a: int16x8_t) -> int8x16_t {
transmute(a)
}
@@ -22809,7 +22809,7 @@ pub unsafe fn vreinterpretq_s8_s16(a: int16x8_t) -> int8x16_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpretq_s8_u16(a: uint16x8_t) -> int8x16_t {
transmute(a)
}
@@ -22822,7 +22822,7 @@ pub unsafe fn vreinterpretq_s8_u16(a: uint16x8_t) -> int8x16_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpretq_s8_p16(a: poly16x8_t) -> int8x16_t {
transmute(a)
}
@@ -22835,7 +22835,7 @@ pub unsafe fn vreinterpretq_s8_p16(a: poly16x8_t) -> int8x16_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpretq_s16_s32(a: int32x4_t) -> int16x8_t {
transmute(a)
}
@@ -22848,7 +22848,7 @@ pub unsafe fn vreinterpretq_s16_s32(a: int32x4_t) -> int16x8_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpretq_s16_u32(a: uint32x4_t) -> int16x8_t {
transmute(a)
}
@@ -22861,7 +22861,7 @@ pub unsafe fn vreinterpretq_s16_u32(a: uint32x4_t) -> int16x8_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpretq_s32_s64(a: int64x2_t) -> int32x4_t {
transmute(a)
}
@@ -22874,7 +22874,7 @@ pub unsafe fn vreinterpretq_s32_s64(a: int64x2_t) -> int32x4_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpretq_s32_u64(a: uint64x2_t) -> int32x4_t {
transmute(a)
}
@@ -22887,7 +22887,7 @@ pub unsafe fn vreinterpretq_s32_u64(a: uint64x2_t) -> int32x4_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpret_u8_p16(a: poly16x4_t) -> uint8x8_t {
transmute(a)
}
@@ -22900,7 +22900,7 @@ pub unsafe fn vreinterpret_u8_p16(a: poly16x4_t) -> uint8x8_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpret_u8_s16(a: int16x4_t) -> uint8x8_t {
transmute(a)
}
@@ -22913,7 +22913,7 @@ pub unsafe fn vreinterpret_u8_s16(a: int16x4_t) -> uint8x8_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpret_u8_u16(a: uint16x4_t) -> uint8x8_t {
transmute(a)
}
@@ -22926,7 +22926,7 @@ pub unsafe fn vreinterpret_u8_u16(a: uint16x4_t) -> uint8x8_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpret_u16_s32(a: int32x2_t) -> uint16x4_t {
transmute(a)
}
@@ -22939,7 +22939,7 @@ pub unsafe fn vreinterpret_u16_s32(a: int32x2_t) -> uint16x4_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpret_u16_u32(a: uint32x2_t) -> uint16x4_t {
transmute(a)
}
@@ -22952,7 +22952,7 @@ pub unsafe fn vreinterpret_u16_u32(a: uint32x2_t) -> uint16x4_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpret_u32_s64(a: int64x1_t) -> uint32x2_t {
transmute(a)
}
@@ -22965,7 +22965,7 @@ pub unsafe fn vreinterpret_u32_s64(a: int64x1_t) -> uint32x2_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpret_u32_u64(a: uint64x1_t) -> uint32x2_t {
transmute(a)
}
@@ -22978,7 +22978,7 @@ pub unsafe fn vreinterpret_u32_u64(a: uint64x1_t) -> uint32x2_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpretq_u8_p16(a: poly16x8_t) -> uint8x16_t {
transmute(a)
}
@@ -22991,7 +22991,7 @@ pub unsafe fn vreinterpretq_u8_p16(a: poly16x8_t) -> uint8x16_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpretq_u8_s16(a: int16x8_t) -> uint8x16_t {
transmute(a)
}
@@ -23004,7 +23004,7 @@ pub unsafe fn vreinterpretq_u8_s16(a: int16x8_t) -> uint8x16_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpretq_u8_u16(a: uint16x8_t) -> uint8x16_t {
transmute(a)
}
@@ -23017,7 +23017,7 @@ pub unsafe fn vreinterpretq_u8_u16(a: uint16x8_t) -> uint8x16_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpretq_u16_s32(a: int32x4_t) -> uint16x8_t {
transmute(a)
}
@@ -23030,7 +23030,7 @@ pub unsafe fn vreinterpretq_u16_s32(a: int32x4_t) -> uint16x8_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpretq_u16_u32(a: uint32x4_t) -> uint16x8_t {
transmute(a)
}
@@ -23043,7 +23043,7 @@ pub unsafe fn vreinterpretq_u16_u32(a: uint32x4_t) -> uint16x8_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpretq_u32_s64(a: int64x2_t) -> uint32x4_t {
transmute(a)
}
@@ -23056,7 +23056,7 @@ pub unsafe fn vreinterpretq_u32_s64(a: int64x2_t) -> uint32x4_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpretq_u32_u64(a: uint64x2_t) -> uint32x4_t {
transmute(a)
}
@@ -23069,7 +23069,7 @@ pub unsafe fn vreinterpretq_u32_u64(a: uint64x2_t) -> uint32x4_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpret_p8_p16(a: poly16x4_t) -> poly8x8_t {
transmute(a)
}
@@ -23082,7 +23082,7 @@ pub unsafe fn vreinterpret_p8_p16(a: poly16x4_t) -> poly8x8_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpret_p8_s16(a: int16x4_t) -> poly8x8_t {
transmute(a)
}
@@ -23095,7 +23095,7 @@ pub unsafe fn vreinterpret_p8_s16(a: int16x4_t) -> poly8x8_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpret_p8_u16(a: uint16x4_t) -> poly8x8_t {
transmute(a)
}
@@ -23108,7 +23108,7 @@ pub unsafe fn vreinterpret_p8_u16(a: uint16x4_t) -> poly8x8_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpret_p16_s32(a: int32x2_t) -> poly16x4_t {
transmute(a)
}
@@ -23121,7 +23121,7 @@ pub unsafe fn vreinterpret_p16_s32(a: int32x2_t) -> poly16x4_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpret_p16_u32(a: uint32x2_t) -> poly16x4_t {
transmute(a)
}
@@ -23134,7 +23134,7 @@ pub unsafe fn vreinterpret_p16_u32(a: uint32x2_t) -> poly16x4_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpretq_p8_p16(a: poly16x8_t) -> poly8x16_t {
transmute(a)
}
@@ -23147,7 +23147,7 @@ pub unsafe fn vreinterpretq_p8_p16(a: poly16x8_t) -> poly8x16_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpretq_p8_s16(a: int16x8_t) -> poly8x16_t {
transmute(a)
}
@@ -23160,7 +23160,7 @@ pub unsafe fn vreinterpretq_p8_s16(a: int16x8_t) -> poly8x16_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpretq_p8_u16(a: uint16x8_t) -> poly8x16_t {
transmute(a)
}
@@ -23173,7 +23173,7 @@ pub unsafe fn vreinterpretq_p8_u16(a: uint16x8_t) -> poly8x16_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpretq_p16_s32(a: int32x4_t) -> poly16x8_t {
transmute(a)
}
@@ -23186,7 +23186,7 @@ pub unsafe fn vreinterpretq_p16_s32(a: int32x4_t) -> poly16x8_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpretq_p16_u32(a: uint32x4_t) -> poly16x8_t {
transmute(a)
}
@@ -23199,7 +23199,7 @@ pub unsafe fn vreinterpretq_p16_u32(a: uint32x4_t) -> poly16x8_t {
#[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))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpret_s32_p64(a: poly64x1_t) -> int32x2_t {
transmute(a)
}
@@ -23212,7 +23212,7 @@ pub unsafe fn vreinterpret_s32_p64(a: poly64x1_t) -> int32x2_t {
#[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))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpret_u32_p64(a: poly64x1_t) -> uint32x2_t {
transmute(a)
}
@@ -23225,7 +23225,7 @@ pub unsafe fn vreinterpret_u32_p64(a: poly64x1_t) -> uint32x2_t {
#[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))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpretq_s32_p64(a: poly64x2_t) -> int32x4_t {
transmute(a)
}
@@ -23238,7 +23238,7 @@ pub unsafe fn vreinterpretq_s32_p64(a: poly64x2_t) -> int32x4_t {
#[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))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpretq_u32_p64(a: poly64x2_t) -> uint32x4_t {
transmute(a)
}
@@ -23251,7 +23251,7 @@ pub unsafe fn vreinterpretq_u32_p64(a: poly64x2_t) -> uint32x4_t {
#[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))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpretq_s64_p128(a: p128) -> int64x2_t {
transmute(a)
}
@@ -23264,7 +23264,7 @@ pub unsafe fn vreinterpretq_s64_p128(a: p128) -> int64x2_t {
#[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))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpretq_u64_p128(a: p128) -> uint64x2_t {
transmute(a)
}
@@ -23277,7 +23277,7 @@ pub unsafe fn vreinterpretq_u64_p128(a: p128) -> uint64x2_t {
#[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))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpretq_p64_p128(a: p128) -> poly64x2_t {
transmute(a)
}
@@ -23290,7 +23290,7 @@ pub unsafe fn vreinterpretq_p64_p128(a: p128) -> poly64x2_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpret_s16_p8(a: poly8x8_t) -> int16x4_t {
transmute(a)
}
@@ -23303,7 +23303,7 @@ pub unsafe fn vreinterpret_s16_p8(a: poly8x8_t) -> int16x4_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpret_s16_s8(a: int8x8_t) -> int16x4_t {
transmute(a)
}
@@ -23316,7 +23316,7 @@ pub unsafe fn vreinterpret_s16_s8(a: int8x8_t) -> int16x4_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpret_s16_u8(a: uint8x8_t) -> int16x4_t {
transmute(a)
}
@@ -23329,7 +23329,7 @@ pub unsafe fn vreinterpret_s16_u8(a: uint8x8_t) -> int16x4_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpret_s32_p16(a: poly16x4_t) -> int32x2_t {
transmute(a)
}
@@ -23342,7 +23342,7 @@ pub unsafe fn vreinterpret_s32_p16(a: poly16x4_t) -> int32x2_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpret_s32_s16(a: int16x4_t) -> int32x2_t {
transmute(a)
}
@@ -23355,7 +23355,7 @@ pub unsafe fn vreinterpret_s32_s16(a: int16x4_t) -> int32x2_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpret_s32_u16(a: uint16x4_t) -> int32x2_t {
transmute(a)
}
@@ -23368,7 +23368,7 @@ pub unsafe fn vreinterpret_s32_u16(a: uint16x4_t) -> int32x2_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpret_s64_s32(a: int32x2_t) -> int64x1_t {
transmute(a)
}
@@ -23381,7 +23381,7 @@ pub unsafe fn vreinterpret_s64_s32(a: int32x2_t) -> int64x1_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpret_s64_u32(a: uint32x2_t) -> int64x1_t {
transmute(a)
}
@@ -23394,7 +23394,7 @@ pub unsafe fn vreinterpret_s64_u32(a: uint32x2_t) -> int64x1_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpretq_s16_p8(a: poly8x16_t) -> int16x8_t {
transmute(a)
}
@@ -23407,7 +23407,7 @@ pub unsafe fn vreinterpretq_s16_p8(a: poly8x16_t) -> int16x8_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpretq_s16_s8(a: int8x16_t) -> int16x8_t {
transmute(a)
}
@@ -23420,7 +23420,7 @@ pub unsafe fn vreinterpretq_s16_s8(a: int8x16_t) -> int16x8_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpretq_s16_u8(a: uint8x16_t) -> int16x8_t {
transmute(a)
}
@@ -23433,7 +23433,7 @@ pub unsafe fn vreinterpretq_s16_u8(a: uint8x16_t) -> int16x8_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpretq_s32_p16(a: poly16x8_t) -> int32x4_t {
transmute(a)
}
@@ -23446,7 +23446,7 @@ pub unsafe fn vreinterpretq_s32_p16(a: poly16x8_t) -> int32x4_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpretq_s32_s16(a: int16x8_t) -> int32x4_t {
transmute(a)
}
@@ -23459,7 +23459,7 @@ pub unsafe fn vreinterpretq_s32_s16(a: int16x8_t) -> int32x4_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpretq_s32_u16(a: uint16x8_t) -> int32x4_t {
transmute(a)
}
@@ -23472,7 +23472,7 @@ pub unsafe fn vreinterpretq_s32_u16(a: uint16x8_t) -> int32x4_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpretq_s64_s32(a: int32x4_t) -> int64x2_t {
transmute(a)
}
@@ -23485,7 +23485,7 @@ pub unsafe fn vreinterpretq_s64_s32(a: int32x4_t) -> int64x2_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpretq_s64_u32(a: uint32x4_t) -> int64x2_t {
transmute(a)
}
@@ -23498,7 +23498,7 @@ pub unsafe fn vreinterpretq_s64_u32(a: uint32x4_t) -> int64x2_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpret_u16_p8(a: poly8x8_t) -> uint16x4_t {
transmute(a)
}
@@ -23511,7 +23511,7 @@ pub unsafe fn vreinterpret_u16_p8(a: poly8x8_t) -> uint16x4_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpret_u16_s8(a: int8x8_t) -> uint16x4_t {
transmute(a)
}
@@ -23524,7 +23524,7 @@ pub unsafe fn vreinterpret_u16_s8(a: int8x8_t) -> uint16x4_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpret_u16_u8(a: uint8x8_t) -> uint16x4_t {
transmute(a)
}
@@ -23537,7 +23537,7 @@ pub unsafe fn vreinterpret_u16_u8(a: uint8x8_t) -> uint16x4_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpret_u32_p16(a: poly16x4_t) -> uint32x2_t {
transmute(a)
}
@@ -23550,7 +23550,7 @@ pub unsafe fn vreinterpret_u32_p16(a: poly16x4_t) -> uint32x2_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpret_u32_s16(a: int16x4_t) -> uint32x2_t {
transmute(a)
}
@@ -23563,7 +23563,7 @@ pub unsafe fn vreinterpret_u32_s16(a: int16x4_t) -> uint32x2_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpret_u32_u16(a: uint16x4_t) -> uint32x2_t {
transmute(a)
}
@@ -23576,7 +23576,7 @@ pub unsafe fn vreinterpret_u32_u16(a: uint16x4_t) -> uint32x2_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpret_u64_s32(a: int32x2_t) -> uint64x1_t {
transmute(a)
}
@@ -23589,7 +23589,7 @@ pub unsafe fn vreinterpret_u64_s32(a: int32x2_t) -> uint64x1_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpret_u64_u32(a: uint32x2_t) -> uint64x1_t {
transmute(a)
}
@@ -23602,7 +23602,7 @@ pub unsafe fn vreinterpret_u64_u32(a: uint32x2_t) -> uint64x1_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpretq_u16_p8(a: poly8x16_t) -> uint16x8_t {
transmute(a)
}
@@ -23615,7 +23615,7 @@ pub unsafe fn vreinterpretq_u16_p8(a: poly8x16_t) -> uint16x8_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpretq_u16_s8(a: int8x16_t) -> uint16x8_t {
transmute(a)
}
@@ -23628,7 +23628,7 @@ pub unsafe fn vreinterpretq_u16_s8(a: int8x16_t) -> uint16x8_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpretq_u16_u8(a: uint8x16_t) -> uint16x8_t {
transmute(a)
}
@@ -23641,7 +23641,7 @@ pub unsafe fn vreinterpretq_u16_u8(a: uint8x16_t) -> uint16x8_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpretq_u32_p16(a: poly16x8_t) -> uint32x4_t {
transmute(a)
}
@@ -23654,7 +23654,7 @@ pub unsafe fn vreinterpretq_u32_p16(a: poly16x8_t) -> uint32x4_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpretq_u32_s16(a: int16x8_t) -> uint32x4_t {
transmute(a)
}
@@ -23667,7 +23667,7 @@ pub unsafe fn vreinterpretq_u32_s16(a: int16x8_t) -> uint32x4_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpretq_u32_u16(a: uint16x8_t) -> uint32x4_t {
transmute(a)
}
@@ -23680,7 +23680,7 @@ pub unsafe fn vreinterpretq_u32_u16(a: uint16x8_t) -> uint32x4_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpretq_u64_s32(a: int32x4_t) -> uint64x2_t {
transmute(a)
}
@@ -23693,7 +23693,7 @@ pub unsafe fn vreinterpretq_u64_s32(a: int32x4_t) -> uint64x2_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpretq_u64_u32(a: uint32x4_t) -> uint64x2_t {
transmute(a)
}
@@ -23706,7 +23706,7 @@ pub unsafe fn vreinterpretq_u64_u32(a: uint32x4_t) -> uint64x2_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpret_p16_p8(a: poly8x8_t) -> poly16x4_t {
transmute(a)
}
@@ -23719,7 +23719,7 @@ pub unsafe fn vreinterpret_p16_p8(a: poly8x8_t) -> poly16x4_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpret_p16_s8(a: int8x8_t) -> poly16x4_t {
transmute(a)
}
@@ -23732,7 +23732,7 @@ pub unsafe fn vreinterpret_p16_s8(a: int8x8_t) -> poly16x4_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpret_p16_u8(a: uint8x8_t) -> poly16x4_t {
transmute(a)
}
@@ -23745,7 +23745,7 @@ pub unsafe fn vreinterpret_p16_u8(a: uint8x8_t) -> poly16x4_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpretq_p16_p8(a: poly8x16_t) -> poly16x8_t {
transmute(a)
}
@@ -23758,7 +23758,7 @@ pub unsafe fn vreinterpretq_p16_p8(a: poly8x16_t) -> poly16x8_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpretq_p16_s8(a: int8x16_t) -> poly16x8_t {
transmute(a)
}
@@ -23771,7 +23771,7 @@ pub unsafe fn vreinterpretq_p16_s8(a: int8x16_t) -> poly16x8_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpretq_p16_u8(a: uint8x16_t) -> poly16x8_t {
transmute(a)
}
@@ -23784,7 +23784,7 @@ pub unsafe fn vreinterpretq_p16_u8(a: uint8x16_t) -> poly16x8_t {
#[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))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpret_p64_s32(a: int32x2_t) -> poly64x1_t {
transmute(a)
}
@@ -23797,7 +23797,7 @@ pub unsafe fn vreinterpret_p64_s32(a: int32x2_t) -> poly64x1_t {
#[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))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpret_p64_u32(a: uint32x2_t) -> poly64x1_t {
transmute(a)
}
@@ -23810,7 +23810,7 @@ pub unsafe fn vreinterpret_p64_u32(a: uint32x2_t) -> poly64x1_t {
#[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))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpretq_p64_s32(a: int32x4_t) -> poly64x2_t {
transmute(a)
}
@@ -23823,7 +23823,7 @@ pub unsafe fn vreinterpretq_p64_s32(a: int32x4_t) -> poly64x2_t {
#[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))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpretq_p64_u32(a: uint32x4_t) -> poly64x2_t {
transmute(a)
}
@@ -23836,7 +23836,7 @@ pub unsafe fn vreinterpretq_p64_u32(a: uint32x4_t) -> poly64x2_t {
#[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))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpretq_p128_s64(a: int64x2_t) -> p128 {
transmute(a)
}
@@ -23849,7 +23849,7 @@ pub unsafe fn vreinterpretq_p128_s64(a: int64x2_t) -> p128 {
#[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))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpretq_p128_u64(a: uint64x2_t) -> p128 {
transmute(a)
}
@@ -23862,7 +23862,7 @@ pub unsafe fn vreinterpretq_p128_u64(a: uint64x2_t) -> p128 {
#[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))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpretq_p128_p64(a: poly64x2_t) -> p128 {
transmute(a)
}
@@ -23875,7 +23875,7 @@ pub unsafe fn vreinterpretq_p128_p64(a: poly64x2_t) -> p128 {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpret_s8_s32(a: int32x2_t) -> int8x8_t {
transmute(a)
}
@@ -23888,7 +23888,7 @@ pub unsafe fn vreinterpret_s8_s32(a: int32x2_t) -> int8x8_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpret_s8_u32(a: uint32x2_t) -> int8x8_t {
transmute(a)
}
@@ -23901,7 +23901,7 @@ pub unsafe fn vreinterpret_s8_u32(a: uint32x2_t) -> int8x8_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpret_s16_s64(a: int64x1_t) -> int16x4_t {
transmute(a)
}
@@ -23914,7 +23914,7 @@ pub unsafe fn vreinterpret_s16_s64(a: int64x1_t) -> int16x4_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpret_s16_u64(a: uint64x1_t) -> int16x4_t {
transmute(a)
}
@@ -23927,7 +23927,7 @@ pub unsafe fn vreinterpret_s16_u64(a: uint64x1_t) -> int16x4_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpretq_s8_s32(a: int32x4_t) -> int8x16_t {
transmute(a)
}
@@ -23940,7 +23940,7 @@ pub unsafe fn vreinterpretq_s8_s32(a: int32x4_t) -> int8x16_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpretq_s8_u32(a: uint32x4_t) -> int8x16_t {
transmute(a)
}
@@ -23953,7 +23953,7 @@ pub unsafe fn vreinterpretq_s8_u32(a: uint32x4_t) -> int8x16_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpretq_s16_s64(a: int64x2_t) -> int16x8_t {
transmute(a)
}
@@ -23966,7 +23966,7 @@ pub unsafe fn vreinterpretq_s16_s64(a: int64x2_t) -> int16x8_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpretq_s16_u64(a: uint64x2_t) -> int16x8_t {
transmute(a)
}
@@ -23979,7 +23979,7 @@ pub unsafe fn vreinterpretq_s16_u64(a: uint64x2_t) -> int16x8_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpret_u8_s32(a: int32x2_t) -> uint8x8_t {
transmute(a)
}
@@ -23992,7 +23992,7 @@ pub unsafe fn vreinterpret_u8_s32(a: int32x2_t) -> uint8x8_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpret_u8_u32(a: uint32x2_t) -> uint8x8_t {
transmute(a)
}
@@ -24005,7 +24005,7 @@ pub unsafe fn vreinterpret_u8_u32(a: uint32x2_t) -> uint8x8_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpret_u16_s64(a: int64x1_t) -> uint16x4_t {
transmute(a)
}
@@ -24018,7 +24018,7 @@ pub unsafe fn vreinterpret_u16_s64(a: int64x1_t) -> uint16x4_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpret_u16_u64(a: uint64x1_t) -> uint16x4_t {
transmute(a)
}
@@ -24031,7 +24031,7 @@ pub unsafe fn vreinterpret_u16_u64(a: uint64x1_t) -> uint16x4_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpretq_u8_s32(a: int32x4_t) -> uint8x16_t {
transmute(a)
}
@@ -24044,7 +24044,7 @@ pub unsafe fn vreinterpretq_u8_s32(a: int32x4_t) -> uint8x16_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpretq_u8_u32(a: uint32x4_t) -> uint8x16_t {
transmute(a)
}
@@ -24057,7 +24057,7 @@ pub unsafe fn vreinterpretq_u8_u32(a: uint32x4_t) -> uint8x16_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpretq_u16_s64(a: int64x2_t) -> uint16x8_t {
transmute(a)
}
@@ -24070,7 +24070,7 @@ pub unsafe fn vreinterpretq_u16_s64(a: int64x2_t) -> uint16x8_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpretq_u16_u64(a: uint64x2_t) -> uint16x8_t {
transmute(a)
}
@@ -24083,7 +24083,7 @@ pub unsafe fn vreinterpretq_u16_u64(a: uint64x2_t) -> uint16x8_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpret_p8_s32(a: int32x2_t) -> poly8x8_t {
transmute(a)
}
@@ -24096,7 +24096,7 @@ pub unsafe fn vreinterpret_p8_s32(a: int32x2_t) -> poly8x8_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpret_p8_u32(a: uint32x2_t) -> poly8x8_t {
transmute(a)
}
@@ -24109,7 +24109,7 @@ pub unsafe fn vreinterpret_p8_u32(a: uint32x2_t) -> poly8x8_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpret_p16_s64(a: int64x1_t) -> poly16x4_t {
transmute(a)
}
@@ -24122,7 +24122,7 @@ pub unsafe fn vreinterpret_p16_s64(a: int64x1_t) -> poly16x4_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpret_p16_u64(a: uint64x1_t) -> poly16x4_t {
transmute(a)
}
@@ -24135,7 +24135,7 @@ pub unsafe fn vreinterpret_p16_u64(a: uint64x1_t) -> poly16x4_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpretq_p8_s32(a: int32x4_t) -> poly8x16_t {
transmute(a)
}
@@ -24148,7 +24148,7 @@ pub unsafe fn vreinterpretq_p8_s32(a: int32x4_t) -> poly8x16_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpretq_p8_u32(a: uint32x4_t) -> poly8x16_t {
transmute(a)
}
@@ -24161,7 +24161,7 @@ pub unsafe fn vreinterpretq_p8_u32(a: uint32x4_t) -> poly8x16_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpretq_p16_s64(a: int64x2_t) -> poly16x8_t {
transmute(a)
}
@@ -24174,7 +24174,7 @@ pub unsafe fn vreinterpretq_p16_s64(a: int64x2_t) -> poly16x8_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpretq_p16_u64(a: uint64x2_t) -> poly16x8_t {
transmute(a)
}
@@ -24187,7 +24187,7 @@ pub unsafe fn vreinterpretq_p16_u64(a: uint64x2_t) -> poly16x8_t {
#[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))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpret_s16_p64(a: poly64x1_t) -> int16x4_t {
transmute(a)
}
@@ -24200,7 +24200,7 @@ pub unsafe fn vreinterpret_s16_p64(a: poly64x1_t) -> int16x4_t {
#[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))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpret_u16_p64(a: poly64x1_t) -> uint16x4_t {
transmute(a)
}
@@ -24213,7 +24213,7 @@ pub unsafe fn vreinterpret_u16_p64(a: poly64x1_t) -> uint16x4_t {
#[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))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpret_p16_p64(a: poly64x1_t) -> poly16x4_t {
transmute(a)
}
@@ -24226,7 +24226,7 @@ pub unsafe fn vreinterpret_p16_p64(a: poly64x1_t) -> poly16x4_t {
#[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))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpretq_s16_p64(a: poly64x2_t) -> int16x8_t {
transmute(a)
}
@@ -24239,7 +24239,7 @@ pub unsafe fn vreinterpretq_s16_p64(a: poly64x2_t) -> int16x8_t {
#[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))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpretq_u16_p64(a: poly64x2_t) -> uint16x8_t {
transmute(a)
}
@@ -24252,7 +24252,7 @@ pub unsafe fn vreinterpretq_u16_p64(a: poly64x2_t) -> uint16x8_t {
#[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))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpretq_p16_p64(a: poly64x2_t) -> poly16x8_t {
transmute(a)
}
@@ -24265,7 +24265,7 @@ pub unsafe fn vreinterpretq_p16_p64(a: poly64x2_t) -> poly16x8_t {
#[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))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpretq_s32_p128(a: p128) -> int32x4_t {
transmute(a)
}
@@ -24278,7 +24278,7 @@ pub unsafe fn vreinterpretq_s32_p128(a: p128) -> int32x4_t {
#[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))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpretq_u32_p128(a: p128) -> uint32x4_t {
transmute(a)
}
@@ -24291,7 +24291,7 @@ pub unsafe fn vreinterpretq_u32_p128(a: p128) -> uint32x4_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpret_s32_p8(a: poly8x8_t) -> int32x2_t {
transmute(a)
}
@@ -24304,7 +24304,7 @@ pub unsafe fn vreinterpret_s32_p8(a: poly8x8_t) -> int32x2_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpret_s32_s8(a: int8x8_t) -> int32x2_t {
transmute(a)
}
@@ -24317,7 +24317,7 @@ pub unsafe fn vreinterpret_s32_s8(a: int8x8_t) -> int32x2_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpret_s32_u8(a: uint8x8_t) -> int32x2_t {
transmute(a)
}
@@ -24330,7 +24330,7 @@ pub unsafe fn vreinterpret_s32_u8(a: uint8x8_t) -> int32x2_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpret_s64_p16(a: poly16x4_t) -> int64x1_t {
transmute(a)
}
@@ -24343,7 +24343,7 @@ pub unsafe fn vreinterpret_s64_p16(a: poly16x4_t) -> int64x1_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpret_s64_s16(a: int16x4_t) -> int64x1_t {
transmute(a)
}
@@ -24356,7 +24356,7 @@ pub unsafe fn vreinterpret_s64_s16(a: int16x4_t) -> int64x1_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpret_s64_u16(a: uint16x4_t) -> int64x1_t {
transmute(a)
}
@@ -24369,7 +24369,7 @@ pub unsafe fn vreinterpret_s64_u16(a: uint16x4_t) -> int64x1_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpretq_s32_p8(a: poly8x16_t) -> int32x4_t {
transmute(a)
}
@@ -24382,7 +24382,7 @@ pub unsafe fn vreinterpretq_s32_p8(a: poly8x16_t) -> int32x4_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpretq_s32_s8(a: int8x16_t) -> int32x4_t {
transmute(a)
}
@@ -24395,7 +24395,7 @@ pub unsafe fn vreinterpretq_s32_s8(a: int8x16_t) -> int32x4_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpretq_s32_u8(a: uint8x16_t) -> int32x4_t {
transmute(a)
}
@@ -24408,7 +24408,7 @@ pub unsafe fn vreinterpretq_s32_u8(a: uint8x16_t) -> int32x4_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpretq_s64_p16(a: poly16x8_t) -> int64x2_t {
transmute(a)
}
@@ -24421,7 +24421,7 @@ pub unsafe fn vreinterpretq_s64_p16(a: poly16x8_t) -> int64x2_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpretq_s64_s16(a: int16x8_t) -> int64x2_t {
transmute(a)
}
@@ -24434,7 +24434,7 @@ pub unsafe fn vreinterpretq_s64_s16(a: int16x8_t) -> int64x2_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpretq_s64_u16(a: uint16x8_t) -> int64x2_t {
transmute(a)
}
@@ -24447,7 +24447,7 @@ pub unsafe fn vreinterpretq_s64_u16(a: uint16x8_t) -> int64x2_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpret_u32_p8(a: poly8x8_t) -> uint32x2_t {
transmute(a)
}
@@ -24460,7 +24460,7 @@ pub unsafe fn vreinterpret_u32_p8(a: poly8x8_t) -> uint32x2_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpret_u32_s8(a: int8x8_t) -> uint32x2_t {
transmute(a)
}
@@ -24473,7 +24473,7 @@ pub unsafe fn vreinterpret_u32_s8(a: int8x8_t) -> uint32x2_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpret_u32_u8(a: uint8x8_t) -> uint32x2_t {
transmute(a)
}
@@ -24486,7 +24486,7 @@ pub unsafe fn vreinterpret_u32_u8(a: uint8x8_t) -> uint32x2_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpret_u64_p16(a: poly16x4_t) -> uint64x1_t {
transmute(a)
}
@@ -24499,7 +24499,7 @@ pub unsafe fn vreinterpret_u64_p16(a: poly16x4_t) -> uint64x1_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpret_u64_s16(a: int16x4_t) -> uint64x1_t {
transmute(a)
}
@@ -24512,7 +24512,7 @@ pub unsafe fn vreinterpret_u64_s16(a: int16x4_t) -> uint64x1_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpret_u64_u16(a: uint16x4_t) -> uint64x1_t {
transmute(a)
}
@@ -24525,7 +24525,7 @@ pub unsafe fn vreinterpret_u64_u16(a: uint16x4_t) -> uint64x1_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpretq_u32_p8(a: poly8x16_t) -> uint32x4_t {
transmute(a)
}
@@ -24538,7 +24538,7 @@ pub unsafe fn vreinterpretq_u32_p8(a: poly8x16_t) -> uint32x4_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpretq_u32_s8(a: int8x16_t) -> uint32x4_t {
transmute(a)
}
@@ -24551,7 +24551,7 @@ pub unsafe fn vreinterpretq_u32_s8(a: int8x16_t) -> uint32x4_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpretq_u32_u8(a: uint8x16_t) -> uint32x4_t {
transmute(a)
}
@@ -24564,7 +24564,7 @@ pub unsafe fn vreinterpretq_u32_u8(a: uint8x16_t) -> uint32x4_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpretq_u64_p16(a: poly16x8_t) -> uint64x2_t {
transmute(a)
}
@@ -24577,7 +24577,7 @@ pub unsafe fn vreinterpretq_u64_p16(a: poly16x8_t) -> uint64x2_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpretq_u64_s16(a: int16x8_t) -> uint64x2_t {
transmute(a)
}
@@ -24590,7 +24590,7 @@ pub unsafe fn vreinterpretq_u64_s16(a: int16x8_t) -> uint64x2_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpretq_u64_u16(a: uint16x8_t) -> uint64x2_t {
transmute(a)
}
@@ -24603,7 +24603,7 @@ pub unsafe fn vreinterpretq_u64_u16(a: uint16x8_t) -> uint64x2_t {
#[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))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpret_p64_p16(a: poly16x4_t) -> poly64x1_t {
transmute(a)
}
@@ -24616,7 +24616,7 @@ pub unsafe fn vreinterpret_p64_p16(a: poly16x4_t) -> poly64x1_t {
#[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))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpret_p64_s16(a: int16x4_t) -> poly64x1_t {
transmute(a)
}
@@ -24629,7 +24629,7 @@ pub unsafe fn vreinterpret_p64_s16(a: int16x4_t) -> poly64x1_t {
#[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))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpret_p64_u16(a: uint16x4_t) -> poly64x1_t {
transmute(a)
}
@@ -24642,7 +24642,7 @@ pub unsafe fn vreinterpret_p64_u16(a: uint16x4_t) -> poly64x1_t {
#[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))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpretq_p64_p16(a: poly16x8_t) -> poly64x2_t {
transmute(a)
}
@@ -24655,7 +24655,7 @@ pub unsafe fn vreinterpretq_p64_p16(a: poly16x8_t) -> poly64x2_t {
#[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))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpretq_p64_s16(a: int16x8_t) -> poly64x2_t {
transmute(a)
}
@@ -24668,7 +24668,7 @@ pub unsafe fn vreinterpretq_p64_s16(a: int16x8_t) -> poly64x2_t {
#[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))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpretq_p64_u16(a: uint16x8_t) -> poly64x2_t {
transmute(a)
}
@@ -24681,7 +24681,7 @@ pub unsafe fn vreinterpretq_p64_u16(a: uint16x8_t) -> poly64x2_t {
#[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))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpretq_p128_s32(a: int32x4_t) -> p128 {
transmute(a)
}
@@ -24694,7 +24694,7 @@ pub unsafe fn vreinterpretq_p128_s32(a: int32x4_t) -> p128 {
#[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))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpretq_p128_u32(a: uint32x4_t) -> p128 {
transmute(a)
}
@@ -24707,7 +24707,7 @@ pub unsafe fn vreinterpretq_p128_u32(a: uint32x4_t) -> p128 {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpret_s8_s64(a: int64x1_t) -> int8x8_t {
transmute(a)
}
@@ -24720,7 +24720,7 @@ pub unsafe fn vreinterpret_s8_s64(a: int64x1_t) -> int8x8_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpret_s8_u64(a: uint64x1_t) -> int8x8_t {
transmute(a)
}
@@ -24733,7 +24733,7 @@ pub unsafe fn vreinterpret_s8_u64(a: uint64x1_t) -> int8x8_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpret_u8_s64(a: int64x1_t) -> uint8x8_t {
transmute(a)
}
@@ -24746,7 +24746,7 @@ pub unsafe fn vreinterpret_u8_s64(a: int64x1_t) -> uint8x8_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpret_u8_u64(a: uint64x1_t) -> uint8x8_t {
transmute(a)
}
@@ -24759,7 +24759,7 @@ pub unsafe fn vreinterpret_u8_u64(a: uint64x1_t) -> uint8x8_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpret_p8_s64(a: int64x1_t) -> poly8x8_t {
transmute(a)
}
@@ -24772,7 +24772,7 @@ pub unsafe fn vreinterpret_p8_s64(a: int64x1_t) -> poly8x8_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpret_p8_u64(a: uint64x1_t) -> poly8x8_t {
transmute(a)
}
@@ -24785,7 +24785,7 @@ pub unsafe fn vreinterpret_p8_u64(a: uint64x1_t) -> poly8x8_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpretq_s8_s64(a: int64x2_t) -> int8x16_t {
transmute(a)
}
@@ -24798,7 +24798,7 @@ pub unsafe fn vreinterpretq_s8_s64(a: int64x2_t) -> int8x16_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpretq_s8_u64(a: uint64x2_t) -> int8x16_t {
transmute(a)
}
@@ -24811,7 +24811,7 @@ pub unsafe fn vreinterpretq_s8_u64(a: uint64x2_t) -> int8x16_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpretq_u8_s64(a: int64x2_t) -> uint8x16_t {
transmute(a)
}
@@ -24824,7 +24824,7 @@ pub unsafe fn vreinterpretq_u8_s64(a: int64x2_t) -> uint8x16_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpretq_u8_u64(a: uint64x2_t) -> uint8x16_t {
transmute(a)
}
@@ -24837,7 +24837,7 @@ pub unsafe fn vreinterpretq_u8_u64(a: uint64x2_t) -> uint8x16_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpretq_p8_s64(a: int64x2_t) -> poly8x16_t {
transmute(a)
}
@@ -24850,7 +24850,7 @@ pub unsafe fn vreinterpretq_p8_s64(a: int64x2_t) -> poly8x16_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpretq_p8_u64(a: uint64x2_t) -> poly8x16_t {
transmute(a)
}
@@ -24863,7 +24863,7 @@ pub unsafe fn vreinterpretq_p8_u64(a: uint64x2_t) -> poly8x16_t {
#[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))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpret_s8_p64(a: poly64x1_t) -> int8x8_t {
transmute(a)
}
@@ -24876,7 +24876,7 @@ pub unsafe fn vreinterpret_s8_p64(a: poly64x1_t) -> int8x8_t {
#[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))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpret_u8_p64(a: poly64x1_t) -> uint8x8_t {
transmute(a)
}
@@ -24889,7 +24889,7 @@ pub unsafe fn vreinterpret_u8_p64(a: poly64x1_t) -> uint8x8_t {
#[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))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpret_p8_p64(a: poly64x1_t) -> poly8x8_t {
transmute(a)
}
@@ -24902,7 +24902,7 @@ pub unsafe fn vreinterpret_p8_p64(a: poly64x1_t) -> poly8x8_t {
#[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))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpretq_s8_p64(a: poly64x2_t) -> int8x16_t {
transmute(a)
}
@@ -24915,7 +24915,7 @@ pub unsafe fn vreinterpretq_s8_p64(a: poly64x2_t) -> int8x16_t {
#[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))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpretq_u8_p64(a: poly64x2_t) -> uint8x16_t {
transmute(a)
}
@@ -24928,7 +24928,7 @@ pub unsafe fn vreinterpretq_u8_p64(a: poly64x2_t) -> uint8x16_t {
#[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))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpretq_p8_p64(a: poly64x2_t) -> poly8x16_t {
transmute(a)
}
@@ -24941,7 +24941,7 @@ pub unsafe fn vreinterpretq_p8_p64(a: poly64x2_t) -> poly8x16_t {
#[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))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpretq_s16_p128(a: p128) -> int16x8_t {
transmute(a)
}
@@ -24954,7 +24954,7 @@ pub unsafe fn vreinterpretq_s16_p128(a: p128) -> int16x8_t {
#[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))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpretq_u16_p128(a: p128) -> uint16x8_t {
transmute(a)
}
@@ -24967,7 +24967,7 @@ pub unsafe fn vreinterpretq_u16_p128(a: p128) -> uint16x8_t {
#[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))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpretq_p16_p128(a: p128) -> poly16x8_t {
transmute(a)
}
@@ -24980,7 +24980,7 @@ pub unsafe fn vreinterpretq_p16_p128(a: p128) -> poly16x8_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpret_s64_p8(a: poly8x8_t) -> int64x1_t {
transmute(a)
}
@@ -24993,7 +24993,7 @@ pub unsafe fn vreinterpret_s64_p8(a: poly8x8_t) -> int64x1_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpret_s64_s8(a: int8x8_t) -> int64x1_t {
transmute(a)
}
@@ -25006,7 +25006,7 @@ pub unsafe fn vreinterpret_s64_s8(a: int8x8_t) -> int64x1_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpret_s64_u8(a: uint8x8_t) -> int64x1_t {
transmute(a)
}
@@ -25019,7 +25019,7 @@ pub unsafe fn vreinterpret_s64_u8(a: uint8x8_t) -> int64x1_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpret_u64_p8(a: poly8x8_t) -> uint64x1_t {
transmute(a)
}
@@ -25032,7 +25032,7 @@ pub unsafe fn vreinterpret_u64_p8(a: poly8x8_t) -> uint64x1_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpret_u64_s8(a: int8x8_t) -> uint64x1_t {
transmute(a)
}
@@ -25045,7 +25045,7 @@ pub unsafe fn vreinterpret_u64_s8(a: int8x8_t) -> uint64x1_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpret_u64_u8(a: uint8x8_t) -> uint64x1_t {
transmute(a)
}
@@ -25058,7 +25058,7 @@ pub unsafe fn vreinterpret_u64_u8(a: uint8x8_t) -> uint64x1_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpretq_s64_p8(a: poly8x16_t) -> int64x2_t {
transmute(a)
}
@@ -25071,7 +25071,7 @@ pub unsafe fn vreinterpretq_s64_p8(a: poly8x16_t) -> int64x2_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpretq_s64_s8(a: int8x16_t) -> int64x2_t {
transmute(a)
}
@@ -25084,7 +25084,7 @@ pub unsafe fn vreinterpretq_s64_s8(a: int8x16_t) -> int64x2_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpretq_s64_u8(a: uint8x16_t) -> int64x2_t {
transmute(a)
}
@@ -25097,7 +25097,7 @@ pub unsafe fn vreinterpretq_s64_u8(a: uint8x16_t) -> int64x2_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpretq_u64_p8(a: poly8x16_t) -> uint64x2_t {
transmute(a)
}
@@ -25110,7 +25110,7 @@ pub unsafe fn vreinterpretq_u64_p8(a: poly8x16_t) -> uint64x2_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpretq_u64_s8(a: int8x16_t) -> uint64x2_t {
transmute(a)
}
@@ -25123,7 +25123,7 @@ pub unsafe fn vreinterpretq_u64_s8(a: int8x16_t) -> uint64x2_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpretq_u64_u8(a: uint8x16_t) -> uint64x2_t {
transmute(a)
}
@@ -25136,7 +25136,7 @@ pub unsafe fn vreinterpretq_u64_u8(a: uint8x16_t) -> uint64x2_t {
#[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))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpret_p64_p8(a: poly8x8_t) -> poly64x1_t {
transmute(a)
}
@@ -25149,7 +25149,7 @@ pub unsafe fn vreinterpret_p64_p8(a: poly8x8_t) -> poly64x1_t {
#[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))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpret_p64_s8(a: int8x8_t) -> poly64x1_t {
transmute(a)
}
@@ -25162,7 +25162,7 @@ pub unsafe fn vreinterpret_p64_s8(a: int8x8_t) -> poly64x1_t {
#[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))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpret_p64_u8(a: uint8x8_t) -> poly64x1_t {
transmute(a)
}
@@ -25175,7 +25175,7 @@ pub unsafe fn vreinterpret_p64_u8(a: uint8x8_t) -> poly64x1_t {
#[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))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpretq_p64_p8(a: poly8x16_t) -> poly64x2_t {
transmute(a)
}
@@ -25188,7 +25188,7 @@ pub unsafe fn vreinterpretq_p64_p8(a: poly8x16_t) -> poly64x2_t {
#[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))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpretq_p64_s8(a: int8x16_t) -> poly64x2_t {
transmute(a)
}
@@ -25201,7 +25201,7 @@ pub unsafe fn vreinterpretq_p64_s8(a: int8x16_t) -> poly64x2_t {
#[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))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpretq_p64_u8(a: uint8x16_t) -> poly64x2_t {
transmute(a)
}
@@ -25214,7 +25214,7 @@ pub unsafe fn vreinterpretq_p64_u8(a: uint8x16_t) -> poly64x2_t {
#[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))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpretq_p128_s16(a: int16x8_t) -> p128 {
transmute(a)
}
@@ -25227,7 +25227,7 @@ pub unsafe fn vreinterpretq_p128_s16(a: int16x8_t) -> p128 {
#[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))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpretq_p128_u16(a: uint16x8_t) -> p128 {
transmute(a)
}
@@ -25240,7 +25240,7 @@ pub unsafe fn vreinterpretq_p128_u16(a: uint16x8_t) -> p128 {
#[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))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpretq_p128_p16(a: poly16x8_t) -> p128 {
transmute(a)
}
@@ -25253,7 +25253,7 @@ pub unsafe fn vreinterpretq_p128_p16(a: poly16x8_t) -> p128 {
#[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))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpretq_p128_s8(a: int8x16_t) -> p128 {
transmute(a)
}
@@ -25266,7 +25266,7 @@ pub unsafe fn vreinterpretq_p128_s8(a: int8x16_t) -> p128 {
#[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))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpretq_p128_u8(a: uint8x16_t) -> p128 {
transmute(a)
}
@@ -25279,7 +25279,7 @@ pub unsafe fn vreinterpretq_p128_u8(a: uint8x16_t) -> p128 {
#[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))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpretq_p128_p8(a: poly8x16_t) -> p128 {
transmute(a)
}
@@ -25292,7 +25292,7 @@ pub unsafe fn vreinterpretq_p128_p8(a: poly8x16_t) -> p128 {
#[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))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpretq_s8_p128(a: p128) -> int8x16_t {
transmute(a)
}
@@ -25305,7 +25305,7 @@ pub unsafe fn vreinterpretq_s8_p128(a: p128) -> int8x16_t {
#[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))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpretq_u8_p128(a: p128) -> uint8x16_t {
transmute(a)
}
@@ -25318,7 +25318,7 @@ pub unsafe fn vreinterpretq_u8_p128(a: p128) -> uint8x16_t {
#[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))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpretq_p8_p128(a: p128) -> poly8x16_t {
transmute(a)
}
@@ -25331,7 +25331,7 @@ pub unsafe fn vreinterpretq_p8_p128(a: p128) -> poly8x16_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpret_s8_f32(a: float32x2_t) -> int8x8_t {
transmute(a)
}
@@ -25344,7 +25344,7 @@ pub unsafe fn vreinterpret_s8_f32(a: float32x2_t) -> int8x8_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpret_s16_f32(a: float32x2_t) -> int16x4_t {
transmute(a)
}
@@ -25357,7 +25357,7 @@ pub unsafe fn vreinterpret_s16_f32(a: float32x2_t) -> int16x4_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpret_s32_f32(a: float32x2_t) -> int32x2_t {
transmute(a)
}
@@ -25370,7 +25370,7 @@ pub unsafe fn vreinterpret_s32_f32(a: float32x2_t) -> int32x2_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpret_s64_f32(a: float32x2_t) -> int64x1_t {
transmute(a)
}
@@ -25383,7 +25383,7 @@ pub unsafe fn vreinterpret_s64_f32(a: float32x2_t) -> int64x1_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpretq_s8_f32(a: float32x4_t) -> int8x16_t {
transmute(a)
}
@@ -25396,7 +25396,7 @@ pub unsafe fn vreinterpretq_s8_f32(a: float32x4_t) -> int8x16_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpretq_s16_f32(a: float32x4_t) -> int16x8_t {
transmute(a)
}
@@ -25409,7 +25409,7 @@ pub unsafe fn vreinterpretq_s16_f32(a: float32x4_t) -> int16x8_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpretq_s32_f32(a: float32x4_t) -> int32x4_t {
transmute(a)
}
@@ -25422,7 +25422,7 @@ pub unsafe fn vreinterpretq_s32_f32(a: float32x4_t) -> int32x4_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpretq_s64_f32(a: float32x4_t) -> int64x2_t {
transmute(a)
}
@@ -25435,7 +25435,7 @@ pub unsafe fn vreinterpretq_s64_f32(a: float32x4_t) -> int64x2_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpret_u8_f32(a: float32x2_t) -> uint8x8_t {
transmute(a)
}
@@ -25448,7 +25448,7 @@ pub unsafe fn vreinterpret_u8_f32(a: float32x2_t) -> uint8x8_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpret_u16_f32(a: float32x2_t) -> uint16x4_t {
transmute(a)
}
@@ -25461,7 +25461,7 @@ pub unsafe fn vreinterpret_u16_f32(a: float32x2_t) -> uint16x4_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpret_u32_f32(a: float32x2_t) -> uint32x2_t {
transmute(a)
}
@@ -25474,7 +25474,7 @@ pub unsafe fn vreinterpret_u32_f32(a: float32x2_t) -> uint32x2_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpret_u64_f32(a: float32x2_t) -> uint64x1_t {
transmute(a)
}
@@ -25487,7 +25487,7 @@ pub unsafe fn vreinterpret_u64_f32(a: float32x2_t) -> uint64x1_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpretq_u8_f32(a: float32x4_t) -> uint8x16_t {
transmute(a)
}
@@ -25500,7 +25500,7 @@ pub unsafe fn vreinterpretq_u8_f32(a: float32x4_t) -> uint8x16_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpretq_u16_f32(a: float32x4_t) -> uint16x8_t {
transmute(a)
}
@@ -25513,7 +25513,7 @@ pub unsafe fn vreinterpretq_u16_f32(a: float32x4_t) -> uint16x8_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpretq_u32_f32(a: float32x4_t) -> uint32x4_t {
transmute(a)
}
@@ -25526,7 +25526,7 @@ pub unsafe fn vreinterpretq_u32_f32(a: float32x4_t) -> uint32x4_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpretq_u64_f32(a: float32x4_t) -> uint64x2_t {
transmute(a)
}
@@ -25539,7 +25539,7 @@ pub unsafe fn vreinterpretq_u64_f32(a: float32x4_t) -> uint64x2_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpret_p8_f32(a: float32x2_t) -> poly8x8_t {
transmute(a)
}
@@ -25552,7 +25552,7 @@ pub unsafe fn vreinterpret_p8_f32(a: float32x2_t) -> poly8x8_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpret_p16_f32(a: float32x2_t) -> poly16x4_t {
transmute(a)
}
@@ -25565,7 +25565,7 @@ pub unsafe fn vreinterpret_p16_f32(a: float32x2_t) -> poly16x4_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpretq_p8_f32(a: float32x4_t) -> poly8x16_t {
transmute(a)
}
@@ -25578,7 +25578,7 @@ pub unsafe fn vreinterpretq_p8_f32(a: float32x4_t) -> poly8x16_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpretq_p16_f32(a: float32x4_t) -> poly16x8_t {
transmute(a)
}
@@ -25591,7 +25591,7 @@ pub unsafe fn vreinterpretq_p16_f32(a: float32x4_t) -> poly16x8_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpretq_p128_f32(a: float32x4_t) -> p128 {
transmute(a)
}
@@ -25604,7 +25604,7 @@ pub unsafe fn vreinterpretq_p128_f32(a: float32x4_t) -> p128 {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpret_f32_s8(a: int8x8_t) -> float32x2_t {
transmute(a)
}
@@ -25617,7 +25617,7 @@ pub unsafe fn vreinterpret_f32_s8(a: int8x8_t) -> float32x2_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpret_f32_s16(a: int16x4_t) -> float32x2_t {
transmute(a)
}
@@ -25630,7 +25630,7 @@ pub unsafe fn vreinterpret_f32_s16(a: int16x4_t) -> float32x2_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpret_f32_s32(a: int32x2_t) -> float32x2_t {
transmute(a)
}
@@ -25643,7 +25643,7 @@ pub unsafe fn vreinterpret_f32_s32(a: int32x2_t) -> float32x2_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpret_f32_s64(a: int64x1_t) -> float32x2_t {
transmute(a)
}
@@ -25656,7 +25656,7 @@ pub unsafe fn vreinterpret_f32_s64(a: int64x1_t) -> float32x2_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpretq_f32_s8(a: int8x16_t) -> float32x4_t {
transmute(a)
}
@@ -25669,7 +25669,7 @@ pub unsafe fn vreinterpretq_f32_s8(a: int8x16_t) -> float32x4_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpretq_f32_s16(a: int16x8_t) -> float32x4_t {
transmute(a)
}
@@ -25682,7 +25682,7 @@ pub unsafe fn vreinterpretq_f32_s16(a: int16x8_t) -> float32x4_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpretq_f32_s32(a: int32x4_t) -> float32x4_t {
transmute(a)
}
@@ -25695,7 +25695,7 @@ pub unsafe fn vreinterpretq_f32_s32(a: int32x4_t) -> float32x4_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpretq_f32_s64(a: int64x2_t) -> float32x4_t {
transmute(a)
}
@@ -25708,7 +25708,7 @@ pub unsafe fn vreinterpretq_f32_s64(a: int64x2_t) -> float32x4_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpret_f32_u8(a: uint8x8_t) -> float32x2_t {
transmute(a)
}
@@ -25721,7 +25721,7 @@ pub unsafe fn vreinterpret_f32_u8(a: uint8x8_t) -> float32x2_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpret_f32_u16(a: uint16x4_t) -> float32x2_t {
transmute(a)
}
@@ -25734,7 +25734,7 @@ pub unsafe fn vreinterpret_f32_u16(a: uint16x4_t) -> float32x2_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpret_f32_u32(a: uint32x2_t) -> float32x2_t {
transmute(a)
}
@@ -25747,7 +25747,7 @@ pub unsafe fn vreinterpret_f32_u32(a: uint32x2_t) -> float32x2_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpret_f32_u64(a: uint64x1_t) -> float32x2_t {
transmute(a)
}
@@ -25760,7 +25760,7 @@ pub unsafe fn vreinterpret_f32_u64(a: uint64x1_t) -> float32x2_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpretq_f32_u8(a: uint8x16_t) -> float32x4_t {
transmute(a)
}
@@ -25773,7 +25773,7 @@ pub unsafe fn vreinterpretq_f32_u8(a: uint8x16_t) -> float32x4_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpretq_f32_u16(a: uint16x8_t) -> float32x4_t {
transmute(a)
}
@@ -25786,7 +25786,7 @@ pub unsafe fn vreinterpretq_f32_u16(a: uint16x8_t) -> float32x4_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpretq_f32_u32(a: uint32x4_t) -> float32x4_t {
transmute(a)
}
@@ -25799,7 +25799,7 @@ pub unsafe fn vreinterpretq_f32_u32(a: uint32x4_t) -> float32x4_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpretq_f32_u64(a: uint64x2_t) -> float32x4_t {
transmute(a)
}
@@ -25812,7 +25812,7 @@ pub unsafe fn vreinterpretq_f32_u64(a: uint64x2_t) -> float32x4_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpret_f32_p8(a: poly8x8_t) -> float32x2_t {
transmute(a)
}
@@ -25825,7 +25825,7 @@ pub unsafe fn vreinterpret_f32_p8(a: poly8x8_t) -> float32x2_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpret_f32_p16(a: poly16x4_t) -> float32x2_t {
transmute(a)
}
@@ -25838,7 +25838,7 @@ pub unsafe fn vreinterpret_f32_p16(a: poly16x4_t) -> float32x2_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpretq_f32_p8(a: poly8x16_t) -> float32x4_t {
transmute(a)
}
@@ -25851,7 +25851,7 @@ pub unsafe fn vreinterpretq_f32_p8(a: poly8x16_t) -> float32x4_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpretq_f32_p16(a: poly16x8_t) -> float32x4_t {
transmute(a)
}
@@ -25864,7 +25864,7 @@ pub unsafe fn vreinterpretq_f32_p16(a: poly16x8_t) -> float32x4_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vreinterpretq_f32_p128(a: p128) -> float32x4_t {
transmute(a)
}
@@ -25877,7 +25877,7 @@ pub unsafe fn vreinterpretq_f32_p128(a: p128) -> float32x4_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrshl))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(srshl))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vrshl_s8(a: int8x8_t, b: int8x8_t) -> int8x8_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -25896,7 +25896,7 @@ vrshl_s8_(a, b)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrshl))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(srshl))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vrshlq_s8(a: int8x16_t, b: int8x16_t) -> int8x16_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -25915,7 +25915,7 @@ vrshlq_s8_(a, b)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrshl))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(srshl))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vrshl_s16(a: int16x4_t, b: int16x4_t) -> int16x4_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -25934,7 +25934,7 @@ vrshl_s16_(a, b)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrshl))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(srshl))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vrshlq_s16(a: int16x8_t, b: int16x8_t) -> int16x8_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -25953,7 +25953,7 @@ vrshlq_s16_(a, b)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrshl))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(srshl))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vrshl_s32(a: int32x2_t, b: int32x2_t) -> int32x2_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -25972,7 +25972,7 @@ vrshl_s32_(a, b)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrshl))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(srshl))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vrshlq_s32(a: int32x4_t, b: int32x4_t) -> int32x4_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -25991,7 +25991,7 @@ vrshlq_s32_(a, b)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrshl))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(srshl))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vrshl_s64(a: int64x1_t, b: int64x1_t) -> int64x1_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -26010,7 +26010,7 @@ vrshl_s64_(a, b)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrshl))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(srshl))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vrshlq_s64(a: int64x2_t, b: int64x2_t) -> int64x2_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -26029,7 +26029,7 @@ vrshlq_s64_(a, b)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrshl))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(urshl))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vrshl_u8(a: uint8x8_t, b: int8x8_t) -> uint8x8_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -26048,7 +26048,7 @@ vrshl_u8_(a, b)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrshl))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(urshl))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vrshlq_u8(a: uint8x16_t, b: int8x16_t) -> uint8x16_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -26067,7 +26067,7 @@ vrshlq_u8_(a, b)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrshl))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(urshl))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vrshl_u16(a: uint16x4_t, b: int16x4_t) -> uint16x4_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -26086,7 +26086,7 @@ vrshl_u16_(a, b)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrshl))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(urshl))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vrshlq_u16(a: uint16x8_t, b: int16x8_t) -> uint16x8_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -26105,7 +26105,7 @@ vrshlq_u16_(a, b)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrshl))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(urshl))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vrshl_u32(a: uint32x2_t, b: int32x2_t) -> uint32x2_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -26124,7 +26124,7 @@ vrshl_u32_(a, b)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrshl))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(urshl))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vrshlq_u32(a: uint32x4_t, b: int32x4_t) -> uint32x4_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -26143,7 +26143,7 @@ vrshlq_u32_(a, b)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrshl))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(urshl))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vrshl_u64(a: uint64x1_t, b: int64x1_t) -> uint64x1_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -26162,7 +26162,7 @@ vrshl_u64_(a, b)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrshl))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(urshl))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vrshlq_u64(a: uint64x2_t, b: int64x2_t) -> uint64x2_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -26182,7 +26182,7 @@ vrshlq_u64_(a, b)
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrshr, N = 2))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(srshr, N = 2))]
#[rustc_legacy_const_generics(1)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vrshr_n_s8<const N: i32>(a: int8x8_t) -> int8x8_t {
static_assert!(N : i32 where N >= 1 && N <= 8);
vrshl_s8(a, vdup_n_s8((-N) as _))
@@ -26197,7 +26197,7 @@ pub unsafe fn vrshr_n_s8<const N: i32>(a: int8x8_t) -> int8x8_t {
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrshr, N = 2))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(srshr, N = 2))]
#[rustc_legacy_const_generics(1)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vrshrq_n_s8<const N: i32>(a: int8x16_t) -> int8x16_t {
static_assert!(N : i32 where N >= 1 && N <= 8);
vrshlq_s8(a, vdupq_n_s8((-N) as _))
@@ -26212,7 +26212,7 @@ pub unsafe fn vrshrq_n_s8<const N: i32>(a: int8x16_t) -> int8x16_t {
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrshr, N = 2))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(srshr, N = 2))]
#[rustc_legacy_const_generics(1)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vrshr_n_s16<const N: i32>(a: int16x4_t) -> int16x4_t {
static_assert!(N : i32 where N >= 1 && N <= 16);
vrshl_s16(a, vdup_n_s16((-N) as _))
@@ -26227,7 +26227,7 @@ pub unsafe fn vrshr_n_s16<const N: i32>(a: int16x4_t) -> int16x4_t {
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrshr, N = 2))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(srshr, N = 2))]
#[rustc_legacy_const_generics(1)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vrshrq_n_s16<const N: i32>(a: int16x8_t) -> int16x8_t {
static_assert!(N : i32 where N >= 1 && N <= 16);
vrshlq_s16(a, vdupq_n_s16((-N) as _))
@@ -26242,7 +26242,7 @@ pub unsafe fn vrshrq_n_s16<const N: i32>(a: int16x8_t) -> int16x8_t {
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrshr, N = 2))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(srshr, N = 2))]
#[rustc_legacy_const_generics(1)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vrshr_n_s32<const N: i32>(a: int32x2_t) -> int32x2_t {
static_assert!(N : i32 where N >= 1 && N <= 32);
vrshl_s32(a, vdup_n_s32((-N) as _))
@@ -26257,7 +26257,7 @@ pub unsafe fn vrshr_n_s32<const N: i32>(a: int32x2_t) -> int32x2_t {
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrshr, N = 2))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(srshr, N = 2))]
#[rustc_legacy_const_generics(1)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vrshrq_n_s32<const N: i32>(a: int32x4_t) -> int32x4_t {
static_assert!(N : i32 where N >= 1 && N <= 32);
vrshlq_s32(a, vdupq_n_s32((-N) as _))
@@ -26272,7 +26272,7 @@ pub unsafe fn vrshrq_n_s32<const N: i32>(a: int32x4_t) -> int32x4_t {
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrshr, N = 2))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(srshr, N = 2))]
#[rustc_legacy_const_generics(1)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vrshr_n_s64<const N: i32>(a: int64x1_t) -> int64x1_t {
static_assert!(N : i32 where N >= 1 && N <= 64);
vrshl_s64(a, vdup_n_s64((-N) as _))
@@ -26287,7 +26287,7 @@ pub unsafe fn vrshr_n_s64<const N: i32>(a: int64x1_t) -> int64x1_t {
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrshr, N = 2))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(srshr, N = 2))]
#[rustc_legacy_const_generics(1)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vrshrq_n_s64<const N: i32>(a: int64x2_t) -> int64x2_t {
static_assert!(N : i32 where N >= 1 && N <= 64);
vrshlq_s64(a, vdupq_n_s64((-N) as _))
@@ -26302,7 +26302,7 @@ pub unsafe fn vrshrq_n_s64<const N: i32>(a: int64x2_t) -> int64x2_t {
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrshr, N = 2))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(urshr, N = 2))]
#[rustc_legacy_const_generics(1)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vrshr_n_u8<const N: i32>(a: uint8x8_t) -> uint8x8_t {
static_assert!(N : i32 where N >= 1 && N <= 8);
vrshl_u8(a, vdup_n_s8((-N) as _))
@@ -26317,7 +26317,7 @@ pub unsafe fn vrshr_n_u8<const N: i32>(a: uint8x8_t) -> uint8x8_t {
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrshr, N = 2))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(urshr, N = 2))]
#[rustc_legacy_const_generics(1)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vrshrq_n_u8<const N: i32>(a: uint8x16_t) -> uint8x16_t {
static_assert!(N : i32 where N >= 1 && N <= 8);
vrshlq_u8(a, vdupq_n_s8((-N) as _))
@@ -26332,7 +26332,7 @@ pub unsafe fn vrshrq_n_u8<const N: i32>(a: uint8x16_t) -> uint8x16_t {
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrshr, N = 2))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(urshr, N = 2))]
#[rustc_legacy_const_generics(1)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vrshr_n_u16<const N: i32>(a: uint16x4_t) -> uint16x4_t {
static_assert!(N : i32 where N >= 1 && N <= 16);
vrshl_u16(a, vdup_n_s16((-N) as _))
@@ -26347,7 +26347,7 @@ pub unsafe fn vrshr_n_u16<const N: i32>(a: uint16x4_t) -> uint16x4_t {
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrshr, N = 2))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(urshr, N = 2))]
#[rustc_legacy_const_generics(1)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vrshrq_n_u16<const N: i32>(a: uint16x8_t) -> uint16x8_t {
static_assert!(N : i32 where N >= 1 && N <= 16);
vrshlq_u16(a, vdupq_n_s16((-N) as _))
@@ -26362,7 +26362,7 @@ pub unsafe fn vrshrq_n_u16<const N: i32>(a: uint16x8_t) -> uint16x8_t {
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrshr, N = 2))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(urshr, N = 2))]
#[rustc_legacy_const_generics(1)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vrshr_n_u32<const N: i32>(a: uint32x2_t) -> uint32x2_t {
static_assert!(N : i32 where N >= 1 && N <= 32);
vrshl_u32(a, vdup_n_s32((-N) as _))
@@ -26377,7 +26377,7 @@ pub unsafe fn vrshr_n_u32<const N: i32>(a: uint32x2_t) -> uint32x2_t {
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrshr, N = 2))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(urshr, N = 2))]
#[rustc_legacy_const_generics(1)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vrshrq_n_u32<const N: i32>(a: uint32x4_t) -> uint32x4_t {
static_assert!(N : i32 where N >= 1 && N <= 32);
vrshlq_u32(a, vdupq_n_s32((-N) as _))
@@ -26392,7 +26392,7 @@ pub unsafe fn vrshrq_n_u32<const N: i32>(a: uint32x4_t) -> uint32x4_t {
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrshr, N = 2))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(urshr, N = 2))]
#[rustc_legacy_const_generics(1)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vrshr_n_u64<const N: i32>(a: uint64x1_t) -> uint64x1_t {
static_assert!(N : i32 where N >= 1 && N <= 64);
vrshl_u64(a, vdup_n_s64((-N) as _))
@@ -26407,7 +26407,7 @@ pub unsafe fn vrshr_n_u64<const N: i32>(a: uint64x1_t) -> uint64x1_t {
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrshr, N = 2))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(urshr, N = 2))]
#[rustc_legacy_const_generics(1)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vrshrq_n_u64<const N: i32>(a: uint64x2_t) -> uint64x2_t {
static_assert!(N : i32 where N >= 1 && N <= 64);
vrshlq_u64(a, vdupq_n_s64((-N) as _))
@@ -26533,7 +26533,7 @@ vrshrn_n_s64_(a, N)
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrshrn, N = 2))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(rshrn, N = 2))]
#[rustc_legacy_const_generics(1)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vrshrn_n_u16<const N: i32>(a: uint16x8_t) -> uint8x8_t {
static_assert!(N : i32 where N >= 1 && N <= 8);
transmute(vrshrn_n_s16::<N>(transmute(a)))
@@ -26548,7 +26548,7 @@ pub unsafe fn vrshrn_n_u16<const N: i32>(a: uint16x8_t) -> uint8x8_t {
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrshrn, N = 2))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(rshrn, N = 2))]
#[rustc_legacy_const_generics(1)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vrshrn_n_u32<const N: i32>(a: uint32x4_t) -> uint16x4_t {
static_assert!(N : i32 where N >= 1 && N <= 16);
transmute(vrshrn_n_s32::<N>(transmute(a)))
@@ -26563,7 +26563,7 @@ pub unsafe fn vrshrn_n_u32<const N: i32>(a: uint32x4_t) -> uint16x4_t {
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrshrn, N = 2))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(rshrn, N = 2))]
#[rustc_legacy_const_generics(1)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vrshrn_n_u64<const N: i32>(a: uint64x2_t) -> uint32x2_t {
static_assert!(N : i32 where N >= 1 && N <= 32);
transmute(vrshrn_n_s64::<N>(transmute(a)))
@@ -26578,7 +26578,7 @@ pub unsafe fn vrshrn_n_u64<const N: i32>(a: uint64x2_t) -> uint32x2_t {
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrsra, N = 2))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(srsra, N = 2))]
#[rustc_legacy_const_generics(2)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vrsra_n_s8<const N: i32>(a: int8x8_t, b: int8x8_t) -> int8x8_t {
static_assert!(N : i32 where N >= 1 && N <= 8);
simd_add(a, vrshr_n_s8::<N>(b))
@@ -26593,7 +26593,7 @@ pub unsafe fn vrsra_n_s8<const N: i32>(a: int8x8_t, b: int8x8_t) -> int8x8_t {
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrsra, N = 2))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(srsra, N = 2))]
#[rustc_legacy_const_generics(2)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vrsraq_n_s8<const N: i32>(a: int8x16_t, b: int8x16_t) -> int8x16_t {
static_assert!(N : i32 where N >= 1 && N <= 8);
simd_add(a, vrshrq_n_s8::<N>(b))
@@ -26608,7 +26608,7 @@ pub unsafe fn vrsraq_n_s8<const N: i32>(a: int8x16_t, b: int8x16_t) -> int8x16_t
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrsra, N = 2))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(srsra, N = 2))]
#[rustc_legacy_const_generics(2)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vrsra_n_s16<const N: i32>(a: int16x4_t, b: int16x4_t) -> int16x4_t {
static_assert!(N : i32 where N >= 1 && N <= 16);
simd_add(a, vrshr_n_s16::<N>(b))
@@ -26623,7 +26623,7 @@ pub unsafe fn vrsra_n_s16<const N: i32>(a: int16x4_t, b: int16x4_t) -> int16x4_t
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrsra, N = 2))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(srsra, N = 2))]
#[rustc_legacy_const_generics(2)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vrsraq_n_s16<const N: i32>(a: int16x8_t, b: int16x8_t) -> int16x8_t {
static_assert!(N : i32 where N >= 1 && N <= 16);
simd_add(a, vrshrq_n_s16::<N>(b))
@@ -26638,7 +26638,7 @@ pub unsafe fn vrsraq_n_s16<const N: i32>(a: int16x8_t, b: int16x8_t) -> int16x8_
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrsra, N = 2))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(srsra, N = 2))]
#[rustc_legacy_const_generics(2)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vrsra_n_s32<const N: i32>(a: int32x2_t, b: int32x2_t) -> int32x2_t {
static_assert!(N : i32 where N >= 1 && N <= 32);
simd_add(a, vrshr_n_s32::<N>(b))
@@ -26653,7 +26653,7 @@ pub unsafe fn vrsra_n_s32<const N: i32>(a: int32x2_t, b: int32x2_t) -> int32x2_t
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrsra, N = 2))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(srsra, N = 2))]
#[rustc_legacy_const_generics(2)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vrsraq_n_s32<const N: i32>(a: int32x4_t, b: int32x4_t) -> int32x4_t {
static_assert!(N : i32 where N >= 1 && N <= 32);
simd_add(a, vrshrq_n_s32::<N>(b))
@@ -26668,7 +26668,7 @@ pub unsafe fn vrsraq_n_s32<const N: i32>(a: int32x4_t, b: int32x4_t) -> int32x4_
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrsra, N = 2))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(srsra, N = 2))]
#[rustc_legacy_const_generics(2)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vrsra_n_s64<const N: i32>(a: int64x1_t, b: int64x1_t) -> int64x1_t {
static_assert!(N : i32 where N >= 1 && N <= 64);
simd_add(a, vrshr_n_s64::<N>(b))
@@ -26683,7 +26683,7 @@ pub unsafe fn vrsra_n_s64<const N: i32>(a: int64x1_t, b: int64x1_t) -> int64x1_t
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrsra, N = 2))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(srsra, N = 2))]
#[rustc_legacy_const_generics(2)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vrsraq_n_s64<const N: i32>(a: int64x2_t, b: int64x2_t) -> int64x2_t {
static_assert!(N : i32 where N >= 1 && N <= 64);
simd_add(a, vrshrq_n_s64::<N>(b))
@@ -26698,7 +26698,7 @@ pub unsafe fn vrsraq_n_s64<const N: i32>(a: int64x2_t, b: int64x2_t) -> int64x2_
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrsra, N = 2))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ursra, N = 2))]
#[rustc_legacy_const_generics(2)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vrsra_n_u8<const N: i32>(a: uint8x8_t, b: uint8x8_t) -> uint8x8_t {
static_assert!(N : i32 where N >= 1 && N <= 8);
simd_add(a, vrshr_n_u8::<N>(b))
@@ -26713,7 +26713,7 @@ pub unsafe fn vrsra_n_u8<const N: i32>(a: uint8x8_t, b: uint8x8_t) -> uint8x8_t
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrsra, N = 2))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ursra, N = 2))]
#[rustc_legacy_const_generics(2)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vrsraq_n_u8<const N: i32>(a: uint8x16_t, b: uint8x16_t) -> uint8x16_t {
static_assert!(N : i32 where N >= 1 && N <= 8);
simd_add(a, vrshrq_n_u8::<N>(b))
@@ -26728,7 +26728,7 @@ pub unsafe fn vrsraq_n_u8<const N: i32>(a: uint8x16_t, b: uint8x16_t) -> uint8x1
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrsra, N = 2))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ursra, N = 2))]
#[rustc_legacy_const_generics(2)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vrsra_n_u16<const N: i32>(a: uint16x4_t, b: uint16x4_t) -> uint16x4_t {
static_assert!(N : i32 where N >= 1 && N <= 16);
simd_add(a, vrshr_n_u16::<N>(b))
@@ -26743,7 +26743,7 @@ pub unsafe fn vrsra_n_u16<const N: i32>(a: uint16x4_t, b: uint16x4_t) -> uint16x
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrsra, N = 2))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ursra, N = 2))]
#[rustc_legacy_const_generics(2)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vrsraq_n_u16<const N: i32>(a: uint16x8_t, b: uint16x8_t) -> uint16x8_t {
static_assert!(N : i32 where N >= 1 && N <= 16);
simd_add(a, vrshrq_n_u16::<N>(b))
@@ -26758,7 +26758,7 @@ pub unsafe fn vrsraq_n_u16<const N: i32>(a: uint16x8_t, b: uint16x8_t) -> uint16
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrsra, N = 2))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ursra, N = 2))]
#[rustc_legacy_const_generics(2)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vrsra_n_u32<const N: i32>(a: uint32x2_t, b: uint32x2_t) -> uint32x2_t {
static_assert!(N : i32 where N >= 1 && N <= 32);
simd_add(a, vrshr_n_u32::<N>(b))
@@ -26773,7 +26773,7 @@ pub unsafe fn vrsra_n_u32<const N: i32>(a: uint32x2_t, b: uint32x2_t) -> uint32x
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrsra, N = 2))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ursra, N = 2))]
#[rustc_legacy_const_generics(2)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vrsraq_n_u32<const N: i32>(a: uint32x4_t, b: uint32x4_t) -> uint32x4_t {
static_assert!(N : i32 where N >= 1 && N <= 32);
simd_add(a, vrshrq_n_u32::<N>(b))
@@ -26788,7 +26788,7 @@ pub unsafe fn vrsraq_n_u32<const N: i32>(a: uint32x4_t, b: uint32x4_t) -> uint32
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrsra, N = 2))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ursra, N = 2))]
#[rustc_legacy_const_generics(2)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vrsra_n_u64<const N: i32>(a: uint64x1_t, b: uint64x1_t) -> uint64x1_t {
static_assert!(N : i32 where N >= 1 && N <= 64);
simd_add(a, vrshr_n_u64::<N>(b))
@@ -26803,7 +26803,7 @@ pub unsafe fn vrsra_n_u64<const N: i32>(a: uint64x1_t, b: uint64x1_t) -> uint64x
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrsra, N = 2))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ursra, N = 2))]
#[rustc_legacy_const_generics(2)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vrsraq_n_u64<const N: i32>(a: uint64x2_t, b: uint64x2_t) -> uint64x2_t {
static_assert!(N : i32 where N >= 1 && N <= 64);
simd_add(a, vrshrq_n_u64::<N>(b))
@@ -26817,7 +26817,7 @@ pub unsafe fn vrsraq_n_u64<const N: i32>(a: uint64x2_t, b: uint64x2_t) -> uint64
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrsubhn))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(rsubhn))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vrsubhn_s16(a: int16x8_t, b: int16x8_t) -> int8x8_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -26836,7 +26836,7 @@ vrsubhn_s16_(a, b)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrsubhn))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(rsubhn))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vrsubhn_s32(a: int32x4_t, b: int32x4_t) -> int16x4_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -26855,7 +26855,7 @@ vrsubhn_s32_(a, b)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrsubhn))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(rsubhn))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vrsubhn_s64(a: int64x2_t, b: int64x2_t) -> int32x2_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -26874,7 +26874,7 @@ vrsubhn_s64_(a, b)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrsubhn))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(rsubhn))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vrsubhn_u16(a: uint16x8_t, b: uint16x8_t) -> uint8x8_t {
transmute(vrsubhn_s16(transmute(a), transmute(b)))
}
@@ -26887,7 +26887,7 @@ pub unsafe fn vrsubhn_u16(a: uint16x8_t, b: uint16x8_t) -> uint8x8_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrsubhn))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(rsubhn))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vrsubhn_u32(a: uint32x4_t, b: uint32x4_t) -> uint16x4_t {
transmute(vrsubhn_s32(transmute(a), transmute(b)))
}
@@ -26900,7 +26900,7 @@ pub unsafe fn vrsubhn_u32(a: uint32x4_t, b: uint32x4_t) -> uint16x4_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrsubhn))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(rsubhn))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vrsubhn_u64(a: uint64x2_t, b: uint64x2_t) -> uint32x2_t {
transmute(vrsubhn_s64(transmute(a), transmute(b)))
}
@@ -26914,7 +26914,7 @@ pub unsafe fn vrsubhn_u64(a: uint64x2_t, b: uint64x2_t) -> uint32x2_t {
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop, LANE = 0))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop, LANE = 0))]
#[rustc_legacy_const_generics(2)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vset_lane_s8<const LANE: i32>(a: i8, b: int8x8_t) -> int8x8_t {
static_assert_imm3!(LANE);
simd_insert(b, LANE as u32, a)
@@ -26929,7 +26929,7 @@ pub unsafe fn vset_lane_s8<const LANE: i32>(a: i8, b: int8x8_t) -> int8x8_t {
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop, LANE = 0))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop, LANE = 0))]
#[rustc_legacy_const_generics(2)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vset_lane_s16<const LANE: i32>(a: i16, b: int16x4_t) -> int16x4_t {
static_assert_imm2!(LANE);
simd_insert(b, LANE as u32, a)
@@ -26944,7 +26944,7 @@ pub unsafe fn vset_lane_s16<const LANE: i32>(a: i16, b: int16x4_t) -> int16x4_t
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop, LANE = 0))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop, LANE = 0))]
#[rustc_legacy_const_generics(2)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vset_lane_s32<const LANE: i32>(a: i32, b: int32x2_t) -> int32x2_t {
static_assert_imm1!(LANE);
simd_insert(b, LANE as u32, a)
@@ -26959,7 +26959,7 @@ pub unsafe fn vset_lane_s32<const LANE: i32>(a: i32, b: int32x2_t) -> int32x2_t
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop, LANE = 0))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop, LANE = 0))]
#[rustc_legacy_const_generics(2)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vset_lane_s64<const LANE: i32>(a: i64, b: int64x1_t) -> int64x1_t {
static_assert!(LANE : i32 where LANE == 0);
simd_insert(b, LANE as u32, a)
@@ -26974,7 +26974,7 @@ pub unsafe fn vset_lane_s64<const LANE: i32>(a: i64, b: int64x1_t) -> int64x1_t
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop, LANE = 0))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop, LANE = 0))]
#[rustc_legacy_const_generics(2)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vset_lane_u8<const LANE: i32>(a: u8, b: uint8x8_t) -> uint8x8_t {
static_assert_imm3!(LANE);
simd_insert(b, LANE as u32, a)
@@ -26989,7 +26989,7 @@ pub unsafe fn vset_lane_u8<const LANE: i32>(a: u8, b: uint8x8_t) -> uint8x8_t {
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop, LANE = 0))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop, LANE = 0))]
#[rustc_legacy_const_generics(2)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vset_lane_u16<const LANE: i32>(a: u16, b: uint16x4_t) -> uint16x4_t {
static_assert_imm2!(LANE);
simd_insert(b, LANE as u32, a)
@@ -27004,7 +27004,7 @@ pub unsafe fn vset_lane_u16<const LANE: i32>(a: u16, b: uint16x4_t) -> uint16x4_
#[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)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vset_lane_u32<const LANE: i32>(a: u32, b: uint32x2_t) -> uint32x2_t {
static_assert_imm1!(LANE);
simd_insert(b, LANE as u32, a)
@@ -27019,7 +27019,7 @@ pub unsafe fn vset_lane_u32<const LANE: i32>(a: u32, b: uint32x2_t) -> uint32x2_
#[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)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vset_lane_u64<const LANE: i32>(a: u64, b: uint64x1_t) -> uint64x1_t {
static_assert!(LANE : i32 where LANE == 0);
simd_insert(b, LANE as u32, a)
@@ -27034,7 +27034,7 @@ pub unsafe fn vset_lane_u64<const LANE: i32>(a: u64, b: uint64x1_t) -> uint64x1_
#[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)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vset_lane_p8<const LANE: i32>(a: p8, b: poly8x8_t) -> poly8x8_t {
static_assert_imm3!(LANE);
simd_insert(b, LANE as u32, a)
@@ -27049,7 +27049,7 @@ pub unsafe fn vset_lane_p8<const LANE: i32>(a: p8, b: poly8x8_t) -> poly8x8_t {
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop, LANE = 0))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop, LANE = 0))]
#[rustc_legacy_const_generics(2)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vset_lane_p16<const LANE: i32>(a: p16, b: poly16x4_t) -> poly16x4_t {
static_assert_imm2!(LANE);
simd_insert(b, LANE as u32, a)
@@ -27064,7 +27064,7 @@ pub unsafe fn vset_lane_p16<const LANE: i32>(a: p16, b: poly16x4_t) -> poly16x4_
#[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)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vset_lane_p64<const LANE: i32>(a: p64, b: poly64x1_t) -> poly64x1_t {
static_assert!(LANE : i32 where LANE == 0);
simd_insert(b, LANE as u32, a)
@@ -27079,7 +27079,7 @@ pub unsafe fn vset_lane_p64<const LANE: i32>(a: p64, b: poly64x1_t) -> poly64x1_
#[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)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vsetq_lane_s8<const LANE: i32>(a: i8, b: int8x16_t) -> int8x16_t {
static_assert_imm4!(LANE);
simd_insert(b, LANE as u32, a)
@@ -27094,7 +27094,7 @@ pub unsafe fn vsetq_lane_s8<const LANE: i32>(a: i8, b: int8x16_t) -> int8x16_t {
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop, LANE = 0))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop, LANE = 0))]
#[rustc_legacy_const_generics(2)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vsetq_lane_s16<const LANE: i32>(a: i16, b: int16x8_t) -> int16x8_t {
static_assert_imm3!(LANE);
simd_insert(b, LANE as u32, a)
@@ -27109,7 +27109,7 @@ pub unsafe fn vsetq_lane_s16<const LANE: i32>(a: i16, b: int16x8_t) -> int16x8_t
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop, LANE = 0))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop, LANE = 0))]
#[rustc_legacy_const_generics(2)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vsetq_lane_s32<const LANE: i32>(a: i32, b: int32x4_t) -> int32x4_t {
static_assert_imm2!(LANE);
simd_insert(b, LANE as u32, a)
@@ -27124,7 +27124,7 @@ pub unsafe fn vsetq_lane_s32<const LANE: i32>(a: i32, b: int32x4_t) -> int32x4_t
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop, LANE = 0))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop, LANE = 0))]
#[rustc_legacy_const_generics(2)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vsetq_lane_s64<const LANE: i32>(a: i64, b: int64x2_t) -> int64x2_t {
static_assert_imm1!(LANE);
simd_insert(b, LANE as u32, a)
@@ -27139,7 +27139,7 @@ pub unsafe fn vsetq_lane_s64<const LANE: i32>(a: i64, b: int64x2_t) -> int64x2_t
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop, LANE = 0))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop, LANE = 0))]
#[rustc_legacy_const_generics(2)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vsetq_lane_u8<const LANE: i32>(a: u8, b: uint8x16_t) -> uint8x16_t {
static_assert_imm4!(LANE);
simd_insert(b, LANE as u32, a)
@@ -27154,7 +27154,7 @@ pub unsafe fn vsetq_lane_u8<const LANE: i32>(a: u8, b: uint8x16_t) -> uint8x16_t
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop, LANE = 0))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop, LANE = 0))]
#[rustc_legacy_const_generics(2)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vsetq_lane_u16<const LANE: i32>(a: u16, b: uint16x8_t) -> uint16x8_t {
static_assert_imm3!(LANE);
simd_insert(b, LANE as u32, a)
@@ -27169,7 +27169,7 @@ pub unsafe fn vsetq_lane_u16<const LANE: i32>(a: u16, b: uint16x8_t) -> uint16x8
#[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)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vsetq_lane_u32<const LANE: i32>(a: u32, b: uint32x4_t) -> uint32x4_t {
static_assert_imm2!(LANE);
simd_insert(b, LANE as u32, a)
@@ -27184,7 +27184,7 @@ pub unsafe fn vsetq_lane_u32<const LANE: i32>(a: u32, b: uint32x4_t) -> uint32x4
#[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)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vsetq_lane_u64<const LANE: i32>(a: u64, b: uint64x2_t) -> uint64x2_t {
static_assert_imm1!(LANE);
simd_insert(b, LANE as u32, a)
@@ -27199,7 +27199,7 @@ pub unsafe fn vsetq_lane_u64<const LANE: i32>(a: u64, b: uint64x2_t) -> uint64x2
#[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)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vsetq_lane_p8<const LANE: i32>(a: p8, b: poly8x16_t) -> poly8x16_t {
static_assert_imm4!(LANE);
simd_insert(b, LANE as u32, a)
@@ -27214,7 +27214,7 @@ pub unsafe fn vsetq_lane_p8<const LANE: i32>(a: p8, b: poly8x16_t) -> poly8x16_t
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop, LANE = 0))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop, LANE = 0))]
#[rustc_legacy_const_generics(2)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vsetq_lane_p16<const LANE: i32>(a: p16, b: poly16x8_t) -> poly16x8_t {
static_assert_imm3!(LANE);
simd_insert(b, LANE as u32, a)
@@ -27229,7 +27229,7 @@ pub unsafe fn vsetq_lane_p16<const LANE: i32>(a: p16, b: poly16x8_t) -> poly16x8
#[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)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vsetq_lane_p64<const LANE: i32>(a: p64, b: poly64x2_t) -> poly64x2_t {
static_assert_imm1!(LANE);
simd_insert(b, LANE as u32, a)
@@ -27244,7 +27244,7 @@ pub unsafe fn vsetq_lane_p64<const LANE: i32>(a: p64, b: poly64x2_t) -> poly64x2
#[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)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vset_lane_f32<const LANE: i32>(a: f32, b: float32x2_t) -> float32x2_t {
static_assert_imm1!(LANE);
simd_insert(b, LANE as u32, a)
@@ -27259,7 +27259,7 @@ pub unsafe fn vset_lane_f32<const LANE: i32>(a: f32, b: float32x2_t) -> float32x
#[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)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vsetq_lane_f32<const LANE: i32>(a: f32, b: float32x4_t) -> float32x4_t {
static_assert_imm2!(LANE);
simd_insert(b, LANE as u32, a)
@@ -27273,7 +27273,7 @@ pub unsafe fn vsetq_lane_f32<const LANE: i32>(a: f32, b: float32x4_t) -> float32
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vshl))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sshl))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vshl_s8(a: int8x8_t, b: int8x8_t) -> int8x8_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -27292,7 +27292,7 @@ vshl_s8_(a, b)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vshl))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sshl))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vshlq_s8(a: int8x16_t, b: int8x16_t) -> int8x16_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -27311,7 +27311,7 @@ vshlq_s8_(a, b)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vshl))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sshl))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vshl_s16(a: int16x4_t, b: int16x4_t) -> int16x4_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -27330,7 +27330,7 @@ vshl_s16_(a, b)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vshl))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sshl))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vshlq_s16(a: int16x8_t, b: int16x8_t) -> int16x8_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -27349,7 +27349,7 @@ vshlq_s16_(a, b)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vshl))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sshl))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vshl_s32(a: int32x2_t, b: int32x2_t) -> int32x2_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -27368,7 +27368,7 @@ vshl_s32_(a, b)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vshl))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sshl))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vshlq_s32(a: int32x4_t, b: int32x4_t) -> int32x4_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -27387,7 +27387,7 @@ vshlq_s32_(a, b)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vshl))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sshl))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vshl_s64(a: int64x1_t, b: int64x1_t) -> int64x1_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -27406,7 +27406,7 @@ vshl_s64_(a, b)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vshl))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sshl))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vshlq_s64(a: int64x2_t, b: int64x2_t) -> int64x2_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -27425,7 +27425,7 @@ vshlq_s64_(a, b)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vshl))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ushl))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vshl_u8(a: uint8x8_t, b: int8x8_t) -> uint8x8_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -27444,7 +27444,7 @@ vshl_u8_(a, b)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vshl))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ushl))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vshlq_u8(a: uint8x16_t, b: int8x16_t) -> uint8x16_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -27463,7 +27463,7 @@ vshlq_u8_(a, b)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vshl))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ushl))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vshl_u16(a: uint16x4_t, b: int16x4_t) -> uint16x4_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -27482,7 +27482,7 @@ vshl_u16_(a, b)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vshl))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ushl))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vshlq_u16(a: uint16x8_t, b: int16x8_t) -> uint16x8_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -27501,7 +27501,7 @@ vshlq_u16_(a, b)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vshl))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ushl))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vshl_u32(a: uint32x2_t, b: int32x2_t) -> uint32x2_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -27520,7 +27520,7 @@ vshl_u32_(a, b)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vshl))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ushl))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vshlq_u32(a: uint32x4_t, b: int32x4_t) -> uint32x4_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -27539,7 +27539,7 @@ vshlq_u32_(a, b)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vshl))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ushl))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vshl_u64(a: uint64x1_t, b: int64x1_t) -> uint64x1_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -27558,7 +27558,7 @@ vshl_u64_(a, b)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vshl))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ushl))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vshlq_u64(a: uint64x2_t, b: int64x2_t) -> uint64x2_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -27578,7 +27578,7 @@ vshlq_u64_(a, b)
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vshl, N = 2))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(shl, N = 2))]
#[rustc_legacy_const_generics(1)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vshl_n_s8<const N: i32>(a: int8x8_t) -> int8x8_t {
static_assert_imm3!(N);
simd_shl(a, vdup_n_s8(N as _))
@@ -27593,7 +27593,7 @@ pub unsafe fn vshl_n_s8<const N: i32>(a: int8x8_t) -> int8x8_t {
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vshl, N = 2))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(shl, N = 2))]
#[rustc_legacy_const_generics(1)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vshlq_n_s8<const N: i32>(a: int8x16_t) -> int8x16_t {
static_assert_imm3!(N);
simd_shl(a, vdupq_n_s8(N as _))
@@ -27608,7 +27608,7 @@ pub unsafe fn vshlq_n_s8<const N: i32>(a: int8x16_t) -> int8x16_t {
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vshl, N = 2))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(shl, N = 2))]
#[rustc_legacy_const_generics(1)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vshl_n_s16<const N: i32>(a: int16x4_t) -> int16x4_t {
static_assert_imm4!(N);
simd_shl(a, vdup_n_s16(N as _))
@@ -27623,7 +27623,7 @@ pub unsafe fn vshl_n_s16<const N: i32>(a: int16x4_t) -> int16x4_t {
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vshl, N = 2))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(shl, N = 2))]
#[rustc_legacy_const_generics(1)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vshlq_n_s16<const N: i32>(a: int16x8_t) -> int16x8_t {
static_assert_imm4!(N);
simd_shl(a, vdupq_n_s16(N as _))
@@ -27638,7 +27638,7 @@ pub unsafe fn vshlq_n_s16<const N: i32>(a: int16x8_t) -> int16x8_t {
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vshl, N = 2))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(shl, N = 2))]
#[rustc_legacy_const_generics(1)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vshl_n_s32<const N: i32>(a: int32x2_t) -> int32x2_t {
static_assert_imm5!(N);
simd_shl(a, vdup_n_s32(N as _))
@@ -27653,7 +27653,7 @@ pub unsafe fn vshl_n_s32<const N: i32>(a: int32x2_t) -> int32x2_t {
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vshl, N = 2))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(shl, N = 2))]
#[rustc_legacy_const_generics(1)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vshlq_n_s32<const N: i32>(a: int32x4_t) -> int32x4_t {
static_assert_imm5!(N);
simd_shl(a, vdupq_n_s32(N as _))
@@ -27668,7 +27668,7 @@ pub unsafe fn vshlq_n_s32<const N: i32>(a: int32x4_t) -> int32x4_t {
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vshl, N = 2))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(shl, N = 2))]
#[rustc_legacy_const_generics(1)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vshl_n_u8<const N: i32>(a: uint8x8_t) -> uint8x8_t {
static_assert_imm3!(N);
simd_shl(a, vdup_n_u8(N as _))
@@ -27683,7 +27683,7 @@ pub unsafe fn vshl_n_u8<const N: i32>(a: uint8x8_t) -> uint8x8_t {
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vshl, N = 2))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(shl, N = 2))]
#[rustc_legacy_const_generics(1)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vshlq_n_u8<const N: i32>(a: uint8x16_t) -> uint8x16_t {
static_assert_imm3!(N);
simd_shl(a, vdupq_n_u8(N as _))
@@ -27698,7 +27698,7 @@ pub unsafe fn vshlq_n_u8<const N: i32>(a: uint8x16_t) -> uint8x16_t {
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vshl, N = 2))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(shl, N = 2))]
#[rustc_legacy_const_generics(1)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vshl_n_u16<const N: i32>(a: uint16x4_t) -> uint16x4_t {
static_assert_imm4!(N);
simd_shl(a, vdup_n_u16(N as _))
@@ -27713,7 +27713,7 @@ pub unsafe fn vshl_n_u16<const N: i32>(a: uint16x4_t) -> uint16x4_t {
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vshl, N = 2))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(shl, N = 2))]
#[rustc_legacy_const_generics(1)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vshlq_n_u16<const N: i32>(a: uint16x8_t) -> uint16x8_t {
static_assert_imm4!(N);
simd_shl(a, vdupq_n_u16(N as _))
@@ -27728,7 +27728,7 @@ pub unsafe fn vshlq_n_u16<const N: i32>(a: uint16x8_t) -> uint16x8_t {
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vshl, N = 2))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(shl, N = 2))]
#[rustc_legacy_const_generics(1)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vshl_n_u32<const N: i32>(a: uint32x2_t) -> uint32x2_t {
static_assert_imm5!(N);
simd_shl(a, vdup_n_u32(N as _))
@@ -27743,7 +27743,7 @@ pub unsafe fn vshl_n_u32<const N: i32>(a: uint32x2_t) -> uint32x2_t {
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vshl, N = 2))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(shl, N = 2))]
#[rustc_legacy_const_generics(1)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vshlq_n_u32<const N: i32>(a: uint32x4_t) -> uint32x4_t {
static_assert_imm5!(N);
simd_shl(a, vdupq_n_u32(N as _))
@@ -27758,7 +27758,7 @@ pub unsafe fn vshlq_n_u32<const N: i32>(a: uint32x4_t) -> uint32x4_t {
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vshl, N = 2))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(shl, N = 2))]
#[rustc_legacy_const_generics(1)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vshl_n_s64<const N: i32>(a: int64x1_t) -> int64x1_t {
static_assert_imm6!(N);
simd_shl(a, vdup_n_s64(N as _))
@@ -27773,7 +27773,7 @@ pub unsafe fn vshl_n_s64<const N: i32>(a: int64x1_t) -> int64x1_t {
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vshl, N = 2))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(shl, N = 2))]
#[rustc_legacy_const_generics(1)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vshlq_n_s64<const N: i32>(a: int64x2_t) -> int64x2_t {
static_assert_imm6!(N);
simd_shl(a, vdupq_n_s64(N as _))
@@ -27788,7 +27788,7 @@ pub unsafe fn vshlq_n_s64<const N: i32>(a: int64x2_t) -> int64x2_t {
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vshl, N = 2))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(shl, N = 2))]
#[rustc_legacy_const_generics(1)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vshl_n_u64<const N: i32>(a: uint64x1_t) -> uint64x1_t {
static_assert_imm6!(N);
simd_shl(a, vdup_n_u64(N as _))
@@ -27803,7 +27803,7 @@ pub unsafe fn vshl_n_u64<const N: i32>(a: uint64x1_t) -> uint64x1_t {
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vshl, N = 2))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(shl, N = 2))]
#[rustc_legacy_const_generics(1)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vshlq_n_u64<const N: i32>(a: uint64x2_t) -> uint64x2_t {
static_assert_imm6!(N);
simd_shl(a, vdupq_n_u64(N as _))
@@ -27818,7 +27818,7 @@ pub unsafe fn vshlq_n_u64<const N: i32>(a: uint64x2_t) -> uint64x2_t {
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vshll.s8", N = 2))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sshll, N = 2))]
#[rustc_legacy_const_generics(1)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vshll_n_s8<const N: i32>(a: int8x8_t) -> int16x8_t {
static_assert!(N : i32 where N >= 0 && N <= 8);
simd_shl(simd_cast(a), vdupq_n_s16(N as _))
@@ -27833,7 +27833,7 @@ pub unsafe fn vshll_n_s8<const N: i32>(a: int8x8_t) -> int16x8_t {
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vshll.s16", N = 2))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sshll, N = 2))]
#[rustc_legacy_const_generics(1)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vshll_n_s16<const N: i32>(a: int16x4_t) -> int32x4_t {
static_assert!(N : i32 where N >= 0 && N <= 16);
simd_shl(simd_cast(a), vdupq_n_s32(N as _))
@@ -27848,7 +27848,7 @@ pub unsafe fn vshll_n_s16<const N: i32>(a: int16x4_t) -> int32x4_t {
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vshll.s32", N = 2))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sshll, N = 2))]
#[rustc_legacy_const_generics(1)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vshll_n_s32<const N: i32>(a: int32x2_t) -> int64x2_t {
static_assert!(N : i32 where N >= 0 && N <= 32);
simd_shl(simd_cast(a), vdupq_n_s64(N as _))
@@ -27863,7 +27863,7 @@ pub unsafe fn vshll_n_s32<const N: i32>(a: int32x2_t) -> int64x2_t {
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vshll.u8", N = 2))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ushll, N = 2))]
#[rustc_legacy_const_generics(1)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vshll_n_u8<const N: i32>(a: uint8x8_t) -> uint16x8_t {
static_assert!(N : i32 where N >= 0 && N <= 8);
simd_shl(simd_cast(a), vdupq_n_u16(N as _))
@@ -27878,7 +27878,7 @@ pub unsafe fn vshll_n_u8<const N: i32>(a: uint8x8_t) -> uint16x8_t {
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vshll.u16", N = 2))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ushll, N = 2))]
#[rustc_legacy_const_generics(1)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vshll_n_u16<const N: i32>(a: uint16x4_t) -> uint32x4_t {
static_assert!(N : i32 where N >= 0 && N <= 16);
simd_shl(simd_cast(a), vdupq_n_u32(N as _))
@@ -27893,7 +27893,7 @@ pub unsafe fn vshll_n_u16<const N: i32>(a: uint16x4_t) -> uint32x4_t {
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vshll.u32", N = 2))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ushll, N = 2))]
#[rustc_legacy_const_generics(1)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vshll_n_u32<const N: i32>(a: uint32x2_t) -> uint64x2_t {
static_assert!(N : i32 where N >= 0 && N <= 32);
simd_shl(simd_cast(a), vdupq_n_u64(N as _))
@@ -27908,7 +27908,7 @@ pub unsafe fn vshll_n_u32<const N: i32>(a: uint32x2_t) -> uint64x2_t {
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vshr.s8", N = 2))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sshr, N = 2))]
#[rustc_legacy_const_generics(1)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vshr_n_s8<const N: i32>(a: int8x8_t) -> int8x8_t {
static_assert!(N : i32 where N >= 1 && N <= 8);
let n: i32 = if N == 8 { 7 } else { N };
@@ -27924,7 +27924,7 @@ pub unsafe fn vshr_n_s8<const N: i32>(a: int8x8_t) -> int8x8_t {
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vshr.s8", N = 2))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sshr, N = 2))]
#[rustc_legacy_const_generics(1)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vshrq_n_s8<const N: i32>(a: int8x16_t) -> int8x16_t {
static_assert!(N : i32 where N >= 1 && N <= 8);
let n: i32 = if N == 8 { 7 } else { N };
@@ -27940,7 +27940,7 @@ pub unsafe fn vshrq_n_s8<const N: i32>(a: int8x16_t) -> int8x16_t {
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vshr.s16", N = 2))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sshr, N = 2))]
#[rustc_legacy_const_generics(1)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vshr_n_s16<const N: i32>(a: int16x4_t) -> int16x4_t {
static_assert!(N : i32 where N >= 1 && N <= 16);
let n: i32 = if N == 16 { 15 } else { N };
@@ -27956,7 +27956,7 @@ pub unsafe fn vshr_n_s16<const N: i32>(a: int16x4_t) -> int16x4_t {
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vshr.s16", N = 2))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sshr, N = 2))]
#[rustc_legacy_const_generics(1)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vshrq_n_s16<const N: i32>(a: int16x8_t) -> int16x8_t {
static_assert!(N : i32 where N >= 1 && N <= 16);
let n: i32 = if N == 16 { 15 } else { N };
@@ -27972,7 +27972,7 @@ pub unsafe fn vshrq_n_s16<const N: i32>(a: int16x8_t) -> int16x8_t {
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vshr.s32", N = 2))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sshr, N = 2))]
#[rustc_legacy_const_generics(1)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vshr_n_s32<const N: i32>(a: int32x2_t) -> int32x2_t {
static_assert!(N : i32 where N >= 1 && N <= 32);
let n: i32 = if N == 32 { 31 } else { N };
@@ -27988,7 +27988,7 @@ pub unsafe fn vshr_n_s32<const N: i32>(a: int32x2_t) -> int32x2_t {
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vshr.s32", N = 2))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sshr, N = 2))]
#[rustc_legacy_const_generics(1)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vshrq_n_s32<const N: i32>(a: int32x4_t) -> int32x4_t {
static_assert!(N : i32 where N >= 1 && N <= 32);
let n: i32 = if N == 32 { 31 } else { N };
@@ -28004,7 +28004,7 @@ pub unsafe fn vshrq_n_s32<const N: i32>(a: int32x4_t) -> int32x4_t {
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vshr.s64", N = 2))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sshr, N = 2))]
#[rustc_legacy_const_generics(1)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vshr_n_s64<const N: i32>(a: int64x1_t) -> int64x1_t {
static_assert!(N : i32 where N >= 1 && N <= 64);
let n: i32 = if N == 64 { 63 } else { N };
@@ -28020,7 +28020,7 @@ pub unsafe fn vshr_n_s64<const N: i32>(a: int64x1_t) -> int64x1_t {
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vshr.s64", N = 2))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sshr, N = 2))]
#[rustc_legacy_const_generics(1)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vshrq_n_s64<const N: i32>(a: int64x2_t) -> int64x2_t {
static_assert!(N : i32 where N >= 1 && N <= 64);
let n: i32 = if N == 64 { 63 } else { N };
@@ -28036,7 +28036,7 @@ pub unsafe fn vshrq_n_s64<const N: i32>(a: int64x2_t) -> int64x2_t {
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vshr.u8", N = 2))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ushr, N = 2))]
#[rustc_legacy_const_generics(1)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vshr_n_u8<const N: i32>(a: uint8x8_t) -> uint8x8_t {
static_assert!(N : i32 where N >= 1 && N <= 8);
let n: i32 = if N == 8 { return vdup_n_u8(0); } else { N };
@@ -28052,7 +28052,7 @@ pub unsafe fn vshr_n_u8<const N: i32>(a: uint8x8_t) -> uint8x8_t {
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vshr.u8", N = 2))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ushr, N = 2))]
#[rustc_legacy_const_generics(1)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vshrq_n_u8<const N: i32>(a: uint8x16_t) -> uint8x16_t {
static_assert!(N : i32 where N >= 1 && N <= 8);
let n: i32 = if N == 8 { return vdupq_n_u8(0); } else { N };
@@ -28068,7 +28068,7 @@ pub unsafe fn vshrq_n_u8<const N: i32>(a: uint8x16_t) -> uint8x16_t {
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vshr.u16", N = 2))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ushr, N = 2))]
#[rustc_legacy_const_generics(1)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vshr_n_u16<const N: i32>(a: uint16x4_t) -> uint16x4_t {
static_assert!(N : i32 where N >= 1 && N <= 16);
let n: i32 = if N == 16 { return vdup_n_u16(0); } else { N };
@@ -28084,7 +28084,7 @@ pub unsafe fn vshr_n_u16<const N: i32>(a: uint16x4_t) -> uint16x4_t {
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vshr.u16", N = 2))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ushr, N = 2))]
#[rustc_legacy_const_generics(1)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vshrq_n_u16<const N: i32>(a: uint16x8_t) -> uint16x8_t {
static_assert!(N : i32 where N >= 1 && N <= 16);
let n: i32 = if N == 16 { return vdupq_n_u16(0); } else { N };
@@ -28100,7 +28100,7 @@ pub unsafe fn vshrq_n_u16<const N: i32>(a: uint16x8_t) -> uint16x8_t {
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vshr.u32", N = 2))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ushr, N = 2))]
#[rustc_legacy_const_generics(1)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vshr_n_u32<const N: i32>(a: uint32x2_t) -> uint32x2_t {
static_assert!(N : i32 where N >= 1 && N <= 32);
let n: i32 = if N == 32 { return vdup_n_u32(0); } else { N };
@@ -28116,7 +28116,7 @@ pub unsafe fn vshr_n_u32<const N: i32>(a: uint32x2_t) -> uint32x2_t {
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vshr.u32", N = 2))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ushr, N = 2))]
#[rustc_legacy_const_generics(1)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vshrq_n_u32<const N: i32>(a: uint32x4_t) -> uint32x4_t {
static_assert!(N : i32 where N >= 1 && N <= 32);
let n: i32 = if N == 32 { return vdupq_n_u32(0); } else { N };
@@ -28132,7 +28132,7 @@ pub unsafe fn vshrq_n_u32<const N: i32>(a: uint32x4_t) -> uint32x4_t {
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vshr.u64", N = 2))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ushr, N = 2))]
#[rustc_legacy_const_generics(1)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vshr_n_u64<const N: i32>(a: uint64x1_t) -> uint64x1_t {
static_assert!(N : i32 where N >= 1 && N <= 64);
let n: i32 = if N == 64 { return vdup_n_u64(0); } else { N };
@@ -28148,7 +28148,7 @@ pub unsafe fn vshr_n_u64<const N: i32>(a: uint64x1_t) -> uint64x1_t {
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vshr.u64", N = 2))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ushr, N = 2))]
#[rustc_legacy_const_generics(1)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vshrq_n_u64<const N: i32>(a: uint64x2_t) -> uint64x2_t {
static_assert!(N : i32 where N >= 1 && N <= 64);
let n: i32 = if N == 64 { return vdupq_n_u64(0); } else { N };
@@ -28164,7 +28164,7 @@ pub unsafe fn vshrq_n_u64<const N: i32>(a: uint64x2_t) -> uint64x2_t {
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vshrn.i16", N = 2))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(shrn, N = 2))]
#[rustc_legacy_const_generics(1)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vshrn_n_s16<const N: i32>(a: int16x8_t) -> int8x8_t {
static_assert!(N : i32 where N >= 1 && N <= 8);
simd_cast(simd_shr(a, vdupq_n_s16(N as _)))
@@ -28179,7 +28179,7 @@ pub unsafe fn vshrn_n_s16<const N: i32>(a: int16x8_t) -> int8x8_t {
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vshrn.i32", N = 2))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(shrn, N = 2))]
#[rustc_legacy_const_generics(1)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vshrn_n_s32<const N: i32>(a: int32x4_t) -> int16x4_t {
static_assert!(N : i32 where N >= 1 && N <= 16);
simd_cast(simd_shr(a, vdupq_n_s32(N as _)))
@@ -28194,7 +28194,7 @@ pub unsafe fn vshrn_n_s32<const N: i32>(a: int32x4_t) -> int16x4_t {
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vshrn.i64", N = 2))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(shrn, N = 2))]
#[rustc_legacy_const_generics(1)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vshrn_n_s64<const N: i32>(a: int64x2_t) -> int32x2_t {
static_assert!(N : i32 where N >= 1 && N <= 32);
simd_cast(simd_shr(a, vdupq_n_s64(N as _)))
@@ -28209,7 +28209,7 @@ pub unsafe fn vshrn_n_s64<const N: i32>(a: int64x2_t) -> int32x2_t {
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vshrn.i16", N = 2))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(shrn, N = 2))]
#[rustc_legacy_const_generics(1)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vshrn_n_u16<const N: i32>(a: uint16x8_t) -> uint8x8_t {
static_assert!(N : i32 where N >= 1 && N <= 8);
simd_cast(simd_shr(a, vdupq_n_u16(N as _)))
@@ -28224,7 +28224,7 @@ pub unsafe fn vshrn_n_u16<const N: i32>(a: uint16x8_t) -> uint8x8_t {
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vshrn.i32", N = 2))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(shrn, N = 2))]
#[rustc_legacy_const_generics(1)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vshrn_n_u32<const N: i32>(a: uint32x4_t) -> uint16x4_t {
static_assert!(N : i32 where N >= 1 && N <= 16);
simd_cast(simd_shr(a, vdupq_n_u32(N as _)))
@@ -28239,7 +28239,7 @@ pub unsafe fn vshrn_n_u32<const N: i32>(a: uint32x4_t) -> uint16x4_t {
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vshrn.i64", N = 2))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(shrn, N = 2))]
#[rustc_legacy_const_generics(1)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vshrn_n_u64<const N: i32>(a: uint64x2_t) -> uint32x2_t {
static_assert!(N : i32 where N >= 1 && N <= 32);
simd_cast(simd_shr(a, vdupq_n_u64(N as _)))
@@ -28254,7 +28254,7 @@ pub unsafe fn vshrn_n_u64<const N: i32>(a: uint64x2_t) -> uint32x2_t {
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vsra, N = 2))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ssra, N = 2))]
#[rustc_legacy_const_generics(2)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vsra_n_s8<const N: i32>(a: int8x8_t, b: int8x8_t) -> int8x8_t {
static_assert!(N : i32 where N >= 1 && N <= 8);
simd_add(a, vshr_n_s8::<N>(b))
@@ -28269,7 +28269,7 @@ pub unsafe fn vsra_n_s8<const N: i32>(a: int8x8_t, b: int8x8_t) -> int8x8_t {
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vsra, N = 2))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ssra, N = 2))]
#[rustc_legacy_const_generics(2)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vsraq_n_s8<const N: i32>(a: int8x16_t, b: int8x16_t) -> int8x16_t {
static_assert!(N : i32 where N >= 1 && N <= 8);
simd_add(a, vshrq_n_s8::<N>(b))
@@ -28284,7 +28284,7 @@ pub unsafe fn vsraq_n_s8<const N: i32>(a: int8x16_t, b: int8x16_t) -> int8x16_t
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vsra, N = 2))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ssra, N = 2))]
#[rustc_legacy_const_generics(2)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vsra_n_s16<const N: i32>(a: int16x4_t, b: int16x4_t) -> int16x4_t {
static_assert!(N : i32 where N >= 1 && N <= 16);
simd_add(a, vshr_n_s16::<N>(b))
@@ -28299,7 +28299,7 @@ pub unsafe fn vsra_n_s16<const N: i32>(a: int16x4_t, b: int16x4_t) -> int16x4_t
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vsra, N = 2))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ssra, N = 2))]
#[rustc_legacy_const_generics(2)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vsraq_n_s16<const N: i32>(a: int16x8_t, b: int16x8_t) -> int16x8_t {
static_assert!(N : i32 where N >= 1 && N <= 16);
simd_add(a, vshrq_n_s16::<N>(b))
@@ -28314,7 +28314,7 @@ pub unsafe fn vsraq_n_s16<const N: i32>(a: int16x8_t, b: int16x8_t) -> int16x8_t
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vsra, N = 2))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ssra, N = 2))]
#[rustc_legacy_const_generics(2)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vsra_n_s32<const N: i32>(a: int32x2_t, b: int32x2_t) -> int32x2_t {
static_assert!(N : i32 where N >= 1 && N <= 32);
simd_add(a, vshr_n_s32::<N>(b))
@@ -28329,7 +28329,7 @@ pub unsafe fn vsra_n_s32<const N: i32>(a: int32x2_t, b: int32x2_t) -> int32x2_t
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vsra, N = 2))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ssra, N = 2))]
#[rustc_legacy_const_generics(2)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vsraq_n_s32<const N: i32>(a: int32x4_t, b: int32x4_t) -> int32x4_t {
static_assert!(N : i32 where N >= 1 && N <= 32);
simd_add(a, vshrq_n_s32::<N>(b))
@@ -28344,7 +28344,7 @@ pub unsafe fn vsraq_n_s32<const N: i32>(a: int32x4_t, b: int32x4_t) -> int32x4_t
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vsra, N = 2))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ssra, N = 2))]
#[rustc_legacy_const_generics(2)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vsra_n_s64<const N: i32>(a: int64x1_t, b: int64x1_t) -> int64x1_t {
static_assert!(N : i32 where N >= 1 && N <= 64);
simd_add(a, vshr_n_s64::<N>(b))
@@ -28359,7 +28359,7 @@ pub unsafe fn vsra_n_s64<const N: i32>(a: int64x1_t, b: int64x1_t) -> int64x1_t
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vsra, N = 2))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ssra, N = 2))]
#[rustc_legacy_const_generics(2)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vsraq_n_s64<const N: i32>(a: int64x2_t, b: int64x2_t) -> int64x2_t {
static_assert!(N : i32 where N >= 1 && N <= 64);
simd_add(a, vshrq_n_s64::<N>(b))
@@ -28374,7 +28374,7 @@ pub unsafe fn vsraq_n_s64<const N: i32>(a: int64x2_t, b: int64x2_t) -> int64x2_t
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vsra, N = 2))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(usra, N = 2))]
#[rustc_legacy_const_generics(2)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vsra_n_u8<const N: i32>(a: uint8x8_t, b: uint8x8_t) -> uint8x8_t {
static_assert!(N : i32 where N >= 1 && N <= 8);
simd_add(a, vshr_n_u8::<N>(b))
@@ -28389,7 +28389,7 @@ pub unsafe fn vsra_n_u8<const N: i32>(a: uint8x8_t, b: uint8x8_t) -> uint8x8_t {
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vsra, N = 2))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(usra, N = 2))]
#[rustc_legacy_const_generics(2)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vsraq_n_u8<const N: i32>(a: uint8x16_t, b: uint8x16_t) -> uint8x16_t {
static_assert!(N : i32 where N >= 1 && N <= 8);
simd_add(a, vshrq_n_u8::<N>(b))
@@ -28404,7 +28404,7 @@ pub unsafe fn vsraq_n_u8<const N: i32>(a: uint8x16_t, b: uint8x16_t) -> uint8x16
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vsra, N = 2))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(usra, N = 2))]
#[rustc_legacy_const_generics(2)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vsra_n_u16<const N: i32>(a: uint16x4_t, b: uint16x4_t) -> uint16x4_t {
static_assert!(N : i32 where N >= 1 && N <= 16);
simd_add(a, vshr_n_u16::<N>(b))
@@ -28419,7 +28419,7 @@ pub unsafe fn vsra_n_u16<const N: i32>(a: uint16x4_t, b: uint16x4_t) -> uint16x4
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vsra, N = 2))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(usra, N = 2))]
#[rustc_legacy_const_generics(2)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vsraq_n_u16<const N: i32>(a: uint16x8_t, b: uint16x8_t) -> uint16x8_t {
static_assert!(N : i32 where N >= 1 && N <= 16);
simd_add(a, vshrq_n_u16::<N>(b))
@@ -28434,7 +28434,7 @@ pub unsafe fn vsraq_n_u16<const N: i32>(a: uint16x8_t, b: uint16x8_t) -> uint16x
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vsra, N = 2))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(usra, N = 2))]
#[rustc_legacy_const_generics(2)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vsra_n_u32<const N: i32>(a: uint32x2_t, b: uint32x2_t) -> uint32x2_t {
static_assert!(N : i32 where N >= 1 && N <= 32);
simd_add(a, vshr_n_u32::<N>(b))
@@ -28449,7 +28449,7 @@ pub unsafe fn vsra_n_u32<const N: i32>(a: uint32x2_t, b: uint32x2_t) -> uint32x2
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vsra, N = 2))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(usra, N = 2))]
#[rustc_legacy_const_generics(2)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vsraq_n_u32<const N: i32>(a: uint32x4_t, b: uint32x4_t) -> uint32x4_t {
static_assert!(N : i32 where N >= 1 && N <= 32);
simd_add(a, vshrq_n_u32::<N>(b))
@@ -28464,7 +28464,7 @@ pub unsafe fn vsraq_n_u32<const N: i32>(a: uint32x4_t, b: uint32x4_t) -> uint32x
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vsra, N = 2))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(usra, N = 2))]
#[rustc_legacy_const_generics(2)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vsra_n_u64<const N: i32>(a: uint64x1_t, b: uint64x1_t) -> uint64x1_t {
static_assert!(N : i32 where N >= 1 && N <= 64);
simd_add(a, vshr_n_u64::<N>(b))
@@ -28479,7 +28479,7 @@ pub unsafe fn vsra_n_u64<const N: i32>(a: uint64x1_t, b: uint64x1_t) -> uint64x1
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vsra, N = 2))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(usra, N = 2))]
#[rustc_legacy_const_generics(2)]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vsraq_n_u64<const N: i32>(a: uint64x2_t, b: uint64x2_t) -> uint64x2_t {
static_assert!(N : i32 where N >= 1 && N <= 64);
simd_add(a, vshrq_n_u64::<N>(b))
@@ -28493,7 +28493,7 @@ pub unsafe fn vsraq_n_u64<const N: i32>(a: uint64x2_t, b: uint64x2_t) -> uint64x
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vtrn))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(trn))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vtrn_s8(a: int8x8_t, b: int8x8_t) -> int8x8x2_t {
let a1: int8x8_t = simd_shuffle8!(a, b, [0, 8, 2, 10, 4, 12, 6, 14]);
let b1: int8x8_t = simd_shuffle8!(a, b, [1, 9, 3, 11, 5, 13, 7, 15]);
@@ -28508,7 +28508,7 @@ pub unsafe fn vtrn_s8(a: int8x8_t, b: int8x8_t) -> int8x8x2_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vtrn))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(trn))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vtrn_s16(a: int16x4_t, b: int16x4_t) -> int16x4x2_t {
let a1: int16x4_t = simd_shuffle4!(a, b, [0, 4, 2, 6]);
let b1: int16x4_t = simd_shuffle4!(a, b, [1, 5, 3, 7]);
@@ -28523,7 +28523,7 @@ pub unsafe fn vtrn_s16(a: int16x4_t, b: int16x4_t) -> int16x4x2_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vtrn))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(trn))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vtrnq_s8(a: int8x16_t, b: int8x16_t) -> int8x16x2_t {
let a1: int8x16_t = simd_shuffle16!(a, b, [0, 16, 2, 18, 4, 20, 6, 22, 8, 24, 10, 26, 12, 28, 14, 30]);
let b1: int8x16_t = simd_shuffle16!(a, b, [1, 17, 3, 19, 5, 21, 7, 23, 9, 25, 11, 27, 13, 29, 15, 31]);
@@ -28538,7 +28538,7 @@ pub unsafe fn vtrnq_s8(a: int8x16_t, b: int8x16_t) -> int8x16x2_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vtrn))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(trn))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vtrnq_s16(a: int16x8_t, b: int16x8_t) -> int16x8x2_t {
let a1: int16x8_t = simd_shuffle8!(a, b, [0, 8, 2, 10, 4, 12, 6, 14]);
let b1: int16x8_t = simd_shuffle8!(a, b, [1, 9, 3, 11, 5, 13, 7, 15]);
@@ -28553,7 +28553,7 @@ pub unsafe fn vtrnq_s16(a: int16x8_t, b: int16x8_t) -> int16x8x2_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vtrn))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(trn))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vtrnq_s32(a: int32x4_t, b: int32x4_t) -> int32x4x2_t {
let a1: int32x4_t = simd_shuffle4!(a, b, [0, 4, 2, 6]);
let b1: int32x4_t = simd_shuffle4!(a, b, [1, 5, 3, 7]);
@@ -28568,7 +28568,7 @@ pub unsafe fn vtrnq_s32(a: int32x4_t, b: int32x4_t) -> int32x4x2_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vtrn))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(trn))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vtrn_u8(a: uint8x8_t, b: uint8x8_t) -> uint8x8x2_t {
let a1: uint8x8_t = simd_shuffle8!(a, b, [0, 8, 2, 10, 4, 12, 6, 14]);
let b1: uint8x8_t = simd_shuffle8!(a, b, [1, 9, 3, 11, 5, 13, 7, 15]);
@@ -28583,7 +28583,7 @@ pub unsafe fn vtrn_u8(a: uint8x8_t, b: uint8x8_t) -> uint8x8x2_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vtrn))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(trn))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vtrn_u16(a: uint16x4_t, b: uint16x4_t) -> uint16x4x2_t {
let a1: uint16x4_t = simd_shuffle4!(a, b, [0, 4, 2, 6]);
let b1: uint16x4_t = simd_shuffle4!(a, b, [1, 5, 3, 7]);
@@ -28598,7 +28598,7 @@ pub unsafe fn vtrn_u16(a: uint16x4_t, b: uint16x4_t) -> uint16x4x2_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vtrn))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(trn))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vtrnq_u8(a: uint8x16_t, b: uint8x16_t) -> uint8x16x2_t {
let a1: uint8x16_t = simd_shuffle16!(a, b, [0, 16, 2, 18, 4, 20, 6, 22, 8, 24, 10, 26, 12, 28, 14, 30]);
let b1: uint8x16_t = simd_shuffle16!(a, b, [1, 17, 3, 19, 5, 21, 7, 23, 9, 25, 11, 27, 13, 29, 15, 31]);
@@ -28613,7 +28613,7 @@ pub unsafe fn vtrnq_u8(a: uint8x16_t, b: uint8x16_t) -> uint8x16x2_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vtrn))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(trn))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vtrnq_u16(a: uint16x8_t, b: uint16x8_t) -> uint16x8x2_t {
let a1: uint16x8_t = simd_shuffle8!(a, b, [0, 8, 2, 10, 4, 12, 6, 14]);
let b1: uint16x8_t = simd_shuffle8!(a, b, [1, 9, 3, 11, 5, 13, 7, 15]);
@@ -28628,7 +28628,7 @@ pub unsafe fn vtrnq_u16(a: uint16x8_t, b: uint16x8_t) -> uint16x8x2_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vtrn))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(trn))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vtrnq_u32(a: uint32x4_t, b: uint32x4_t) -> uint32x4x2_t {
let a1: uint32x4_t = simd_shuffle4!(a, b, [0, 4, 2, 6]);
let b1: uint32x4_t = simd_shuffle4!(a, b, [1, 5, 3, 7]);
@@ -28643,7 +28643,7 @@ pub unsafe fn vtrnq_u32(a: uint32x4_t, b: uint32x4_t) -> uint32x4x2_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vtrn))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(trn))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vtrn_p8(a: poly8x8_t, b: poly8x8_t) -> poly8x8x2_t {
let a1: poly8x8_t = simd_shuffle8!(a, b, [0, 8, 2, 10, 4, 12, 6, 14]);
let b1: poly8x8_t = simd_shuffle8!(a, b, [1, 9, 3, 11, 5, 13, 7, 15]);
@@ -28658,7 +28658,7 @@ pub unsafe fn vtrn_p8(a: poly8x8_t, b: poly8x8_t) -> poly8x8x2_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vtrn))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(trn))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vtrn_p16(a: poly16x4_t, b: poly16x4_t) -> poly16x4x2_t {
let a1: poly16x4_t = simd_shuffle4!(a, b, [0, 4, 2, 6]);
let b1: poly16x4_t = simd_shuffle4!(a, b, [1, 5, 3, 7]);
@@ -28673,7 +28673,7 @@ pub unsafe fn vtrn_p16(a: poly16x4_t, b: poly16x4_t) -> poly16x4x2_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vtrn))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(trn))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vtrnq_p8(a: poly8x16_t, b: poly8x16_t) -> poly8x16x2_t {
let a1: poly8x16_t = simd_shuffle16!(a, b, [0, 16, 2, 18, 4, 20, 6, 22, 8, 24, 10, 26, 12, 28, 14, 30]);
let b1: poly8x16_t = simd_shuffle16!(a, b, [1, 17, 3, 19, 5, 21, 7, 23, 9, 25, 11, 27, 13, 29, 15, 31]);
@@ -28688,7 +28688,7 @@ pub unsafe fn vtrnq_p8(a: poly8x16_t, b: poly8x16_t) -> poly8x16x2_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vtrn))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(trn))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vtrnq_p16(a: poly16x8_t, b: poly16x8_t) -> poly16x8x2_t {
let a1: poly16x8_t = simd_shuffle8!(a, b, [0, 8, 2, 10, 4, 12, 6, 14]);
let b1: poly16x8_t = simd_shuffle8!(a, b, [1, 9, 3, 11, 5, 13, 7, 15]);
@@ -28703,7 +28703,7 @@ pub unsafe fn vtrnq_p16(a: poly16x8_t, b: poly16x8_t) -> poly16x8x2_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vtrn))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(zip))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vtrn_s32(a: int32x2_t, b: int32x2_t) -> int32x2x2_t {
let a1: int32x2_t = simd_shuffle2!(a, b, [0, 2]);
let b1: int32x2_t = simd_shuffle2!(a, b, [1, 3]);
@@ -28718,7 +28718,7 @@ pub unsafe fn vtrn_s32(a: int32x2_t, b: int32x2_t) -> int32x2x2_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vtrn))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(zip))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vtrn_u32(a: uint32x2_t, b: uint32x2_t) -> uint32x2x2_t {
let a1: uint32x2_t = simd_shuffle2!(a, b, [0, 2]);
let b1: uint32x2_t = simd_shuffle2!(a, b, [1, 3]);
@@ -28733,7 +28733,7 @@ pub unsafe fn vtrn_u32(a: uint32x2_t, b: uint32x2_t) -> uint32x2x2_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vtrn))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(zip))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vtrn_f32(a: float32x2_t, b: float32x2_t) -> float32x2x2_t {
let a1: float32x2_t = simd_shuffle2!(a, b, [0, 2]);
let b1: float32x2_t = simd_shuffle2!(a, b, [1, 3]);
@@ -28748,7 +28748,7 @@ pub unsafe fn vtrn_f32(a: float32x2_t, b: float32x2_t) -> float32x2x2_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vtrn))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(trn))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vtrnq_f32(a: float32x4_t, b: float32x4_t) -> float32x4x2_t {
let a1: float32x4_t = simd_shuffle4!(a, b, [0, 4, 2, 6]);
let b1: float32x4_t = simd_shuffle4!(a, b, [1, 5, 3, 7]);
@@ -28763,7 +28763,7 @@ pub unsafe fn vtrnq_f32(a: float32x4_t, b: float32x4_t) -> float32x4x2_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vzip))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(zip))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vzip_s8(a: int8x8_t, b: int8x8_t) -> int8x8x2_t {
let a0: int8x8_t = simd_shuffle8!(a, b, [0, 8, 1, 9, 2, 10, 3, 11]);
let b0: int8x8_t = simd_shuffle8!(a, b, [4, 12, 5, 13, 6, 14, 7, 15]);
@@ -28778,7 +28778,7 @@ pub unsafe fn vzip_s8(a: int8x8_t, b: int8x8_t) -> int8x8x2_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vzip))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(zip))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vzip_s16(a: int16x4_t, b: int16x4_t) -> int16x4x2_t {
let a0: int16x4_t = simd_shuffle4!(a, b, [0, 4, 1, 5]);
let b0: int16x4_t = simd_shuffle4!(a, b, [2, 6, 3, 7]);
@@ -28793,7 +28793,7 @@ pub unsafe fn vzip_s16(a: int16x4_t, b: int16x4_t) -> int16x4x2_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vzip))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(zip))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vzip_u8(a: uint8x8_t, b: uint8x8_t) -> uint8x8x2_t {
let a0: uint8x8_t = simd_shuffle8!(a, b, [0, 8, 1, 9, 2, 10, 3, 11]);
let b0: uint8x8_t = simd_shuffle8!(a, b, [4, 12, 5, 13, 6, 14, 7, 15]);
@@ -28808,7 +28808,7 @@ pub unsafe fn vzip_u8(a: uint8x8_t, b: uint8x8_t) -> uint8x8x2_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vzip))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(zip))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vzip_u16(a: uint16x4_t, b: uint16x4_t) -> uint16x4x2_t {
let a0: uint16x4_t = simd_shuffle4!(a, b, [0, 4, 1, 5]);
let b0: uint16x4_t = simd_shuffle4!(a, b, [2, 6, 3, 7]);
@@ -28823,7 +28823,7 @@ pub unsafe fn vzip_u16(a: uint16x4_t, b: uint16x4_t) -> uint16x4x2_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vzip))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(zip))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vzip_p8(a: poly8x8_t, b: poly8x8_t) -> poly8x8x2_t {
let a0: poly8x8_t = simd_shuffle8!(a, b, [0, 8, 1, 9, 2, 10, 3, 11]);
let b0: poly8x8_t = simd_shuffle8!(a, b, [4, 12, 5, 13, 6, 14, 7, 15]);
@@ -28838,7 +28838,7 @@ pub unsafe fn vzip_p8(a: poly8x8_t, b: poly8x8_t) -> poly8x8x2_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vzip))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(zip))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vzip_p16(a: poly16x4_t, b: poly16x4_t) -> poly16x4x2_t {
let a0: poly16x4_t = simd_shuffle4!(a, b, [0, 4, 1, 5]);
let b0: poly16x4_t = simd_shuffle4!(a, b, [2, 6, 3, 7]);
@@ -28853,7 +28853,7 @@ pub unsafe fn vzip_p16(a: poly16x4_t, b: poly16x4_t) -> poly16x4x2_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vtrn))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(zip))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vzip_s32(a: int32x2_t, b: int32x2_t) -> int32x2x2_t {
let a0: int32x2_t = simd_shuffle2!(a, b, [0, 2]);
let b0: int32x2_t = simd_shuffle2!(a, b, [1, 3]);
@@ -28868,7 +28868,7 @@ pub unsafe fn vzip_s32(a: int32x2_t, b: int32x2_t) -> int32x2x2_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vtrn))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(zip))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vzip_u32(a: uint32x2_t, b: uint32x2_t) -> uint32x2x2_t {
let a0: uint32x2_t = simd_shuffle2!(a, b, [0, 2]);
let b0: uint32x2_t = simd_shuffle2!(a, b, [1, 3]);
@@ -28883,7 +28883,7 @@ pub unsafe fn vzip_u32(a: uint32x2_t, b: uint32x2_t) -> uint32x2x2_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vorr))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ext))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vzipq_s8(a: int8x16_t, b: int8x16_t) -> int8x16x2_t {
let a0: int8x16_t = simd_shuffle16!(a, b, [0, 16, 1, 17, 2, 18, 3, 19, 4, 20, 5, 21, 6, 22, 7, 23]);
let b0: int8x16_t = simd_shuffle16!(a, b, [8, 24, 9, 25, 10, 26, 11, 27, 12, 28, 13, 29, 14, 30, 15, 31]);
@@ -28898,7 +28898,7 @@ pub unsafe fn vzipq_s8(a: int8x16_t, b: int8x16_t) -> int8x16x2_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vorr))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ext))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vzipq_s16(a: int16x8_t, b: int16x8_t) -> int16x8x2_t {
let a0: int16x8_t = simd_shuffle8!(a, b, [0, 8, 1, 9, 2, 10, 3, 11]);
let b0: int16x8_t = simd_shuffle8!(a, b, [4, 12, 5, 13, 6, 14, 7, 15]);
@@ -28913,7 +28913,7 @@ pub unsafe fn vzipq_s16(a: int16x8_t, b: int16x8_t) -> int16x8x2_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vorr))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ext))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vzipq_s32(a: int32x4_t, b: int32x4_t) -> int32x4x2_t {
let a0: int32x4_t = simd_shuffle4!(a, b, [0, 4, 1, 5]);
let b0: int32x4_t = simd_shuffle4!(a, b, [2, 6, 3, 7]);
@@ -28928,7 +28928,7 @@ pub unsafe fn vzipq_s32(a: int32x4_t, b: int32x4_t) -> int32x4x2_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vorr))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ext))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vzipq_u8(a: uint8x16_t, b: uint8x16_t) -> uint8x16x2_t {
let a0: uint8x16_t = simd_shuffle16!(a, b, [0, 16, 1, 17, 2, 18, 3, 19, 4, 20, 5, 21, 6, 22, 7, 23]);
let b0: uint8x16_t = simd_shuffle16!(a, b, [8, 24, 9, 25, 10, 26, 11, 27, 12, 28, 13, 29, 14, 30, 15, 31]);
@@ -28943,7 +28943,7 @@ pub unsafe fn vzipq_u8(a: uint8x16_t, b: uint8x16_t) -> uint8x16x2_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vorr))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ext))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vzipq_u16(a: uint16x8_t, b: uint16x8_t) -> uint16x8x2_t {
let a0: uint16x8_t = simd_shuffle8!(a, b, [0, 8, 1, 9, 2, 10, 3, 11]);
let b0: uint16x8_t = simd_shuffle8!(a, b, [4, 12, 5, 13, 6, 14, 7, 15]);
@@ -28958,7 +28958,7 @@ pub unsafe fn vzipq_u16(a: uint16x8_t, b: uint16x8_t) -> uint16x8x2_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vorr))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ext))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vzipq_u32(a: uint32x4_t, b: uint32x4_t) -> uint32x4x2_t {
let a0: uint32x4_t = simd_shuffle4!(a, b, [0, 4, 1, 5]);
let b0: uint32x4_t = simd_shuffle4!(a, b, [2, 6, 3, 7]);
@@ -28973,7 +28973,7 @@ pub unsafe fn vzipq_u32(a: uint32x4_t, b: uint32x4_t) -> uint32x4x2_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vorr))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ext))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vzipq_p8(a: poly8x16_t, b: poly8x16_t) -> poly8x16x2_t {
let a0: poly8x16_t = simd_shuffle16!(a, b, [0, 16, 1, 17, 2, 18, 3, 19, 4, 20, 5, 21, 6, 22, 7, 23]);
let b0: poly8x16_t = simd_shuffle16!(a, b, [8, 24, 9, 25, 10, 26, 11, 27, 12, 28, 13, 29, 14, 30, 15, 31]);
@@ -28988,7 +28988,7 @@ pub unsafe fn vzipq_p8(a: poly8x16_t, b: poly8x16_t) -> poly8x16x2_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vorr))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ext))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vzipq_p16(a: poly16x8_t, b: poly16x8_t) -> poly16x8x2_t {
let a0: poly16x8_t = simd_shuffle8!(a, b, [0, 8, 1, 9, 2, 10, 3, 11]);
let b0: poly16x8_t = simd_shuffle8!(a, b, [4, 12, 5, 13, 6, 14, 7, 15]);
@@ -29003,7 +29003,7 @@ pub unsafe fn vzipq_p16(a: poly16x8_t, b: poly16x8_t) -> poly16x8x2_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vtrn))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(zip))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vzip_f32(a: float32x2_t, b: float32x2_t) -> float32x2x2_t {
let a0: float32x2_t = simd_shuffle2!(a, b, [0, 2]);
let b0: float32x2_t = simd_shuffle2!(a, b, [1, 3]);
@@ -29018,7 +29018,7 @@ pub unsafe fn vzip_f32(a: float32x2_t, b: float32x2_t) -> float32x2x2_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vorr))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ext))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vzipq_f32(a: float32x4_t, b: float32x4_t) -> float32x4x2_t {
let a0: float32x4_t = simd_shuffle4!(a, b, [0, 4, 1, 5]);
let b0: float32x4_t = simd_shuffle4!(a, b, [2, 6, 3, 7]);
@@ -29033,7 +29033,7 @@ pub unsafe fn vzipq_f32(a: float32x4_t, b: float32x4_t) -> float32x4x2_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vuzp))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uzp))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vuzp_s8(a: int8x8_t, b: int8x8_t) -> int8x8x2_t {
let a0: int8x8_t = simd_shuffle8!(a, b, [0, 2, 4, 6, 8, 10, 12, 14]);
let b0: int8x8_t = simd_shuffle8!(a, b, [1, 3, 5, 7, 9, 11, 13, 15]);
@@ -29048,7 +29048,7 @@ pub unsafe fn vuzp_s8(a: int8x8_t, b: int8x8_t) -> int8x8x2_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vuzp))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uzp))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vuzp_s16(a: int16x4_t, b: int16x4_t) -> int16x4x2_t {
let a0: int16x4_t = simd_shuffle4!(a, b, [0, 2, 4, 6]);
let b0: int16x4_t = simd_shuffle4!(a, b, [1, 3, 5, 7]);
@@ -29063,7 +29063,7 @@ pub unsafe fn vuzp_s16(a: int16x4_t, b: int16x4_t) -> int16x4x2_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vuzp))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uzp))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vuzpq_s8(a: int8x16_t, b: int8x16_t) -> int8x16x2_t {
let a0: int8x16_t = simd_shuffle16!(a, b, [0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30]);
let b0: int8x16_t = simd_shuffle16!(a, b, [1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31]);
@@ -29078,7 +29078,7 @@ pub unsafe fn vuzpq_s8(a: int8x16_t, b: int8x16_t) -> int8x16x2_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vuzp))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uzp))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vuzpq_s16(a: int16x8_t, b: int16x8_t) -> int16x8x2_t {
let a0: int16x8_t = simd_shuffle8!(a, b, [0, 2, 4, 6, 8, 10, 12, 14]);
let b0: int16x8_t = simd_shuffle8!(a, b, [1, 3, 5, 7, 9, 11, 13, 15]);
@@ -29093,7 +29093,7 @@ pub unsafe fn vuzpq_s16(a: int16x8_t, b: int16x8_t) -> int16x8x2_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vuzp))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uzp))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vuzpq_s32(a: int32x4_t, b: int32x4_t) -> int32x4x2_t {
let a0: int32x4_t = simd_shuffle4!(a, b, [0, 2, 4, 6]);
let b0: int32x4_t = simd_shuffle4!(a, b, [1, 3, 5, 7]);
@@ -29108,7 +29108,7 @@ pub unsafe fn vuzpq_s32(a: int32x4_t, b: int32x4_t) -> int32x4x2_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vuzp))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uzp))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vuzp_u8(a: uint8x8_t, b: uint8x8_t) -> uint8x8x2_t {
let a0: uint8x8_t = simd_shuffle8!(a, b, [0, 2, 4, 6, 8, 10, 12, 14]);
let b0: uint8x8_t = simd_shuffle8!(a, b, [1, 3, 5, 7, 9, 11, 13, 15]);
@@ -29123,7 +29123,7 @@ pub unsafe fn vuzp_u8(a: uint8x8_t, b: uint8x8_t) -> uint8x8x2_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vuzp))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uzp))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vuzp_u16(a: uint16x4_t, b: uint16x4_t) -> uint16x4x2_t {
let a0: uint16x4_t = simd_shuffle4!(a, b, [0, 2, 4, 6]);
let b0: uint16x4_t = simd_shuffle4!(a, b, [1, 3, 5, 7]);
@@ -29138,7 +29138,7 @@ pub unsafe fn vuzp_u16(a: uint16x4_t, b: uint16x4_t) -> uint16x4x2_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vuzp))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uzp))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vuzpq_u8(a: uint8x16_t, b: uint8x16_t) -> uint8x16x2_t {
let a0: uint8x16_t = simd_shuffle16!(a, b, [0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30]);
let b0: uint8x16_t = simd_shuffle16!(a, b, [1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31]);
@@ -29153,7 +29153,7 @@ pub unsafe fn vuzpq_u8(a: uint8x16_t, b: uint8x16_t) -> uint8x16x2_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vuzp))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uzp))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vuzpq_u16(a: uint16x8_t, b: uint16x8_t) -> uint16x8x2_t {
let a0: uint16x8_t = simd_shuffle8!(a, b, [0, 2, 4, 6, 8, 10, 12, 14]);
let b0: uint16x8_t = simd_shuffle8!(a, b, [1, 3, 5, 7, 9, 11, 13, 15]);
@@ -29168,7 +29168,7 @@ pub unsafe fn vuzpq_u16(a: uint16x8_t, b: uint16x8_t) -> uint16x8x2_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vuzp))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uzp))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vuzpq_u32(a: uint32x4_t, b: uint32x4_t) -> uint32x4x2_t {
let a0: uint32x4_t = simd_shuffle4!(a, b, [0, 2, 4, 6]);
let b0: uint32x4_t = simd_shuffle4!(a, b, [1, 3, 5, 7]);
@@ -29183,7 +29183,7 @@ pub unsafe fn vuzpq_u32(a: uint32x4_t, b: uint32x4_t) -> uint32x4x2_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vuzp))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uzp))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vuzp_p8(a: poly8x8_t, b: poly8x8_t) -> poly8x8x2_t {
let a0: poly8x8_t = simd_shuffle8!(a, b, [0, 2, 4, 6, 8, 10, 12, 14]);
let b0: poly8x8_t = simd_shuffle8!(a, b, [1, 3, 5, 7, 9, 11, 13, 15]);
@@ -29198,7 +29198,7 @@ pub unsafe fn vuzp_p8(a: poly8x8_t, b: poly8x8_t) -> poly8x8x2_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vuzp))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uzp))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vuzp_p16(a: poly16x4_t, b: poly16x4_t) -> poly16x4x2_t {
let a0: poly16x4_t = simd_shuffle4!(a, b, [0, 2, 4, 6]);
let b0: poly16x4_t = simd_shuffle4!(a, b, [1, 3, 5, 7]);
@@ -29213,7 +29213,7 @@ pub unsafe fn vuzp_p16(a: poly16x4_t, b: poly16x4_t) -> poly16x4x2_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vuzp))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uzp))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vuzpq_p8(a: poly8x16_t, b: poly8x16_t) -> poly8x16x2_t {
let a0: poly8x16_t = simd_shuffle16!(a, b, [0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30]);
let b0: poly8x16_t = simd_shuffle16!(a, b, [1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31]);
@@ -29228,7 +29228,7 @@ pub unsafe fn vuzpq_p8(a: poly8x16_t, b: poly8x16_t) -> poly8x16x2_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vuzp))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uzp))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vuzpq_p16(a: poly16x8_t, b: poly16x8_t) -> poly16x8x2_t {
let a0: poly16x8_t = simd_shuffle8!(a, b, [0, 2, 4, 6, 8, 10, 12, 14]);
let b0: poly16x8_t = simd_shuffle8!(a, b, [1, 3, 5, 7, 9, 11, 13, 15]);
@@ -29243,7 +29243,7 @@ pub unsafe fn vuzpq_p16(a: poly16x8_t, b: poly16x8_t) -> poly16x8x2_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vtrn))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(zip))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vuzp_s32(a: int32x2_t, b: int32x2_t) -> int32x2x2_t {
let a0: int32x2_t = simd_shuffle2!(a, b, [0, 2]);
let b0: int32x2_t = simd_shuffle2!(a, b, [1, 3]);
@@ -29258,7 +29258,7 @@ pub unsafe fn vuzp_s32(a: int32x2_t, b: int32x2_t) -> int32x2x2_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vtrn))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(zip))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vuzp_u32(a: uint32x2_t, b: uint32x2_t) -> uint32x2x2_t {
let a0: uint32x2_t = simd_shuffle2!(a, b, [0, 2]);
let b0: uint32x2_t = simd_shuffle2!(a, b, [1, 3]);
@@ -29273,7 +29273,7 @@ pub unsafe fn vuzp_u32(a: uint32x2_t, b: uint32x2_t) -> uint32x2x2_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vtrn))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(zip))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vuzp_f32(a: float32x2_t, b: float32x2_t) -> float32x2x2_t {
let a0: float32x2_t = simd_shuffle2!(a, b, [0, 2]);
let b0: float32x2_t = simd_shuffle2!(a, b, [1, 3]);
@@ -29288,7 +29288,7 @@ pub unsafe fn vuzp_f32(a: float32x2_t, b: float32x2_t) -> float32x2x2_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vuzp))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uzp))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vuzpq_f32(a: float32x4_t, b: float32x4_t) -> float32x4x2_t {
let a0: float32x4_t = simd_shuffle4!(a, b, [0, 2, 4, 6]);
let b0: float32x4_t = simd_shuffle4!(a, b, [1, 3, 5, 7]);
@@ -29303,7 +29303,7 @@ pub unsafe fn vuzpq_f32(a: float32x4_t, b: float32x4_t) -> float32x4x2_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vabal.u8"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uabal))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vabal_u8(a: uint16x8_t, b: uint8x8_t, c: uint8x8_t) -> uint16x8_t {
let d: uint8x8_t = vabd_u8(b, c);
simd_add(a, simd_cast(d))
@@ -29317,7 +29317,7 @@ pub unsafe fn vabal_u8(a: uint16x8_t, b: uint8x8_t, c: uint8x8_t) -> uint16x8_t
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vabal.u16"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uabal))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vabal_u16(a: uint32x4_t, b: uint16x4_t, c: uint16x4_t) -> uint32x4_t {
let d: uint16x4_t = vabd_u16(b, c);
simd_add(a, simd_cast(d))
@@ -29331,7 +29331,7 @@ pub unsafe fn vabal_u16(a: uint32x4_t, b: uint16x4_t, c: uint16x4_t) -> uint32x4
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vabal.u32"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uabal))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vabal_u32(a: uint64x2_t, b: uint32x2_t, c: uint32x2_t) -> uint64x2_t {
let d: uint32x2_t = vabd_u32(b, c);
simd_add(a, simd_cast(d))
@@ -29345,7 +29345,7 @@ pub unsafe fn vabal_u32(a: uint64x2_t, b: uint32x2_t, c: uint32x2_t) -> uint64x2
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vabal.s8"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sabal))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vabal_s8(a: int16x8_t, b: int8x8_t, c: int8x8_t) -> int16x8_t {
let d: int8x8_t = vabd_s8(b, c);
let e: uint8x8_t = simd_cast(d);
@@ -29360,7 +29360,7 @@ pub unsafe fn vabal_s8(a: int16x8_t, b: int8x8_t, c: int8x8_t) -> int16x8_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vabal.s16"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sabal))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vabal_s16(a: int32x4_t, b: int16x4_t, c: int16x4_t) -> int32x4_t {
let d: int16x4_t = vabd_s16(b, c);
let e: uint16x4_t = simd_cast(d);
@@ -29375,7 +29375,7 @@ pub unsafe fn vabal_s16(a: int32x4_t, b: int16x4_t, c: int16x4_t) -> int32x4_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vabal.s32"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sabal))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vabal_s32(a: int64x2_t, b: int32x2_t, c: int32x2_t) -> int64x2_t {
let d: int32x2_t = vabd_s32(b, c);
let e: uint32x2_t = simd_cast(d);
@@ -29390,7 +29390,7 @@ pub unsafe fn vabal_s32(a: int64x2_t, b: int32x2_t, c: int32x2_t) -> int64x2_t {
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vqabs.s8"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqabs))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vqabs_s8(a: int8x8_t) -> int8x8_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -29409,7 +29409,7 @@ vqabs_s8_(a)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vqabs.s8"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqabs))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vqabsq_s8(a: int8x16_t) -> int8x16_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -29428,7 +29428,7 @@ vqabsq_s8_(a)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vqabs.s16"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqabs))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vqabs_s16(a: int16x4_t) -> int16x4_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -29447,7 +29447,7 @@ vqabs_s16_(a)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vqabs.s16"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqabs))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vqabsq_s16(a: int16x8_t) -> int16x8_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -29466,7 +29466,7 @@ vqabsq_s16_(a)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vqabs.s32"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqabs))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vqabs_s32(a: int32x2_t) -> int32x2_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
@@ -29485,7 +29485,7 @@ vqabs_s32_(a)
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vqabs.s32"))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqabs))]
-#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+#[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub unsafe fn vqabsq_s32(a: int32x4_t) -> int32x4_t {
#[allow(improper_ctypes)]
extern "unadjusted" {
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 0559aea83..31e924b84 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
@@ -18,90 +18,90 @@ pub(crate) type p128 = u128;
types! {
/// ARM-specific 64-bit wide vector of eight packed `i8`.
- #[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+ #[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub struct int8x8_t(pub(crate) i8, pub(crate) i8, pub(crate) i8, pub(crate) i8, pub(crate) i8, pub(crate) i8, pub(crate) i8, pub(crate) i8);
/// ARM-specific 64-bit wide vector of eight packed `u8`.
- #[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+ #[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub struct uint8x8_t(pub(crate) u8, pub(crate) u8, pub(crate) u8, pub(crate) u8, pub(crate) u8, pub(crate) u8, pub(crate) u8, pub(crate) u8);
/// ARM-specific 64-bit wide polynomial vector of eight packed `p8`.
- #[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+ #[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub struct poly8x8_t(pub(crate) p8, pub(crate) p8, pub(crate) p8, pub(crate) p8, pub(crate) p8, pub(crate) p8, pub(crate) p8, pub(crate) p8);
/// ARM-specific 64-bit wide vector of four packed `i16`.
- #[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+ #[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub struct int16x4_t(pub(crate) i16, pub(crate) i16, pub(crate) i16, pub(crate) i16);
/// ARM-specific 64-bit wide vector of four packed `u16`.
- #[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+ #[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub struct uint16x4_t(pub(crate) u16, pub(crate) u16, pub(crate) u16, pub(crate) u16);
// FIXME: ARM-specific 64-bit wide vector of four packed `f16`.
// pub struct float16x4_t(f16, f16, f16, f16);
/// ARM-specific 64-bit wide vector of four packed `p16`.
- #[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+ #[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub struct poly16x4_t(pub(crate) p16, pub(crate) p16, pub(crate) p16, pub(crate) p16);
/// ARM-specific 64-bit wide vector of two packed `i32`.
- #[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+ #[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub struct int32x2_t(pub(crate) i32, pub(crate) i32);
/// ARM-specific 64-bit wide vector of two packed `u32`.
- #[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+ #[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub struct uint32x2_t(pub(crate) u32, pub(crate) u32);
/// ARM-specific 64-bit wide vector of two packed `f32`.
- #[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+ #[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub struct float32x2_t(pub(crate) f32, pub(crate) f32);
/// ARM-specific 64-bit wide vector of one packed `i64`.
- #[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+ #[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub struct int64x1_t(pub(crate) i64);
/// ARM-specific 64-bit wide vector of one packed `u64`.
- #[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+ #[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub struct uint64x1_t(pub(crate) u64);
/// ARM-specific 64-bit wide vector of one packed `p64`.
- #[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+ #[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub struct poly64x1_t(pub(crate) p64);
/// ARM-specific 128-bit wide vector of sixteen packed `i8`.
- #[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+ #[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub struct int8x16_t(
pub(crate) i8, pub(crate) i8, pub(crate) i8, pub(crate) i8, pub(crate) i8, pub(crate) i8 , pub(crate) i8, pub(crate) i8,
pub(crate) i8, pub(crate) i8, pub(crate) i8, pub(crate) i8, pub(crate) i8, pub(crate) i8 , pub(crate) i8, pub(crate) i8,
);
/// ARM-specific 128-bit wide vector of sixteen packed `u8`.
- #[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+ #[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub struct uint8x16_t(
pub(crate) u8, pub(crate) u8 , pub(crate) u8, pub(crate) u8, pub(crate) u8, pub(crate) u8 , pub(crate) u8, pub(crate) u8,
pub(crate) u8, pub(crate) u8 , pub(crate) u8, pub(crate) u8, pub(crate) u8, pub(crate) u8 , pub(crate) u8, pub(crate) u8,
);
/// ARM-specific 128-bit wide vector of sixteen packed `p8`.
- #[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+ #[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub struct poly8x16_t(
pub(crate) p8, pub(crate) p8, pub(crate) p8, pub(crate) p8, pub(crate) p8, pub(crate) p8, pub(crate) p8, pub(crate) p8,
pub(crate) p8, pub(crate) p8, pub(crate) p8, pub(crate) p8, pub(crate) p8, pub(crate) p8, pub(crate) p8, pub(crate) p8,
);
/// ARM-specific 128-bit wide vector of eight packed `i16`.
- #[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+ #[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub struct int16x8_t(pub(crate) i16, pub(crate) i16, pub(crate) i16, pub(crate) i16, pub(crate) i16, pub(crate) i16, pub(crate) i16, pub(crate) i16);
/// ARM-specific 128-bit wide vector of eight packed `u16`.
- #[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+ #[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub struct uint16x8_t(pub(crate) u16, pub(crate) u16, pub(crate) u16, pub(crate) u16, pub(crate) u16, pub(crate) u16, pub(crate) u16, pub(crate) u16);
// FIXME: ARM-specific 128-bit wide vector of eight packed `f16`.
// pub struct float16x8_t(f16, f16, f16, f16, f16, f16, f16);
/// ARM-specific 128-bit wide vector of eight packed `p16`.
- #[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+ #[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub struct poly16x8_t(pub(crate) p16, pub(crate) p16, pub(crate) p16, pub(crate) p16, pub(crate) p16, pub(crate) p16, pub(crate) p16, pub(crate) p16);
/// ARM-specific 128-bit wide vector of four packed `i32`.
- #[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+ #[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub struct int32x4_t(pub(crate) i32, pub(crate) i32, pub(crate) i32, pub(crate) i32);
/// ARM-specific 128-bit wide vector of four packed `u32`.
- #[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+ #[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub struct uint32x4_t(pub(crate) u32, pub(crate) u32, pub(crate) u32, pub(crate) u32);
/// ARM-specific 128-bit wide vector of four packed `f32`.
- #[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+ #[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub struct float32x4_t(pub(crate) f32, pub(crate) f32, pub(crate) f32, pub(crate) f32);
/// ARM-specific 128-bit wide vector of two packed `i64`.
- #[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+ #[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub struct int64x2_t(pub(crate) i64, pub(crate) i64);
/// ARM-specific 128-bit wide vector of two packed `u64`.
- #[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+ #[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub struct uint64x2_t(pub(crate) u64, pub(crate) u64);
/// ARM-specific 128-bit wide vector of two packed `p64`.
- #[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))]
+ #[cfg_attr(not(target_arch = "arm"), stable(feature = "neon_intrinsics", since = "1.59.0"))]
pub struct poly64x2_t(pub(crate) p64, pub(crate) p64);
}
@@ -6915,6 +6915,177 @@ pub unsafe fn vusmmlaq_s32(a: int32x4_t, b: uint8x16_t, c: int8x16_t) -> int32x4
vusmmlaq_s32_(a, b, c)
}
+/* FIXME: 16-bit float
+/// Vector combine
+#[inline]
+#[target_feature(enable = "neon")]
+#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
+#[cfg_attr(test, assert_instr(nop))]
+pub unsafe fn vcombine_f16 ( low: float16x4_t, high: float16x4_t) -> float16x8_t {
+ simd_shuffle8!(low, high, [0, 1, 2, 3, 4, 5, 6, 7])
+}
+*/
+
+/// Vector combine
+#[inline]
+#[target_feature(enable = "neon")]
+#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
+#[cfg_attr(test, assert_instr(nop))]
+#[stable(feature = "neon_intrinsics", since = "1.59.0")]
+pub unsafe fn vcombine_f32(low: float32x2_t, high: float32x2_t) -> float32x4_t {
+ simd_shuffle4!(low, high, [0, 1, 2, 3])
+}
+
+/// Vector combine
+#[inline]
+#[target_feature(enable = "neon")]
+#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
+#[cfg_attr(test, assert_instr(nop))]
+#[stable(feature = "neon_intrinsics", since = "1.59.0")]
+pub unsafe fn vcombine_p8(low: poly8x8_t, high: poly8x8_t) -> poly8x16_t {
+ simd_shuffle16!(
+ low,
+ high,
+ [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15],
+ )
+}
+
+/// Vector combine
+#[inline]
+#[target_feature(enable = "neon")]
+#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
+#[cfg_attr(test, assert_instr(nop))]
+#[stable(feature = "neon_intrinsics", since = "1.59.0")]
+pub unsafe fn vcombine_p16(low: poly16x4_t, high: poly16x4_t) -> poly16x8_t {
+ simd_shuffle8!(low, high, [0, 1, 2, 3, 4, 5, 6, 7])
+}
+
+/// Vector combine
+#[inline]
+#[target_feature(enable = "neon")]
+#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
+#[cfg_attr(test, assert_instr(nop))]
+#[cfg_attr(
+ target_arch = "aarch64",
+ stable(feature = "neon_intrinsics", since = "1.59.0")
+)]
+pub unsafe fn vcombine_s8(low: int8x8_t, high: int8x8_t) -> int8x16_t {
+ simd_shuffle16!(
+ low,
+ high,
+ [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15],
+ )
+}
+
+/// Vector combine
+#[inline]
+#[target_feature(enable = "neon")]
+#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
+#[cfg_attr(test, assert_instr(nop))]
+#[cfg_attr(
+ target_arch = "aarch64",
+ stable(feature = "neon_intrinsics", since = "1.59.0")
+)]
+pub unsafe fn vcombine_s16(low: int16x4_t, high: int16x4_t) -> int16x8_t {
+ simd_shuffle8!(low, high, [0, 1, 2, 3, 4, 5, 6, 7])
+}
+
+/// Vector combine
+#[inline]
+#[target_feature(enable = "neon")]
+#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
+#[cfg_attr(test, assert_instr(nop))]
+#[cfg_attr(
+ target_arch = "aarch64",
+ stable(feature = "neon_intrinsics", since = "1.59.0")
+)]
+pub unsafe fn vcombine_s32(low: int32x2_t, high: int32x2_t) -> int32x4_t {
+ simd_shuffle4!(low, high, [0, 1, 2, 3])
+}
+
+/// Vector combine
+#[inline]
+#[target_feature(enable = "neon")]
+#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
+#[cfg_attr(test, assert_instr(nop))]
+#[cfg_attr(
+ target_arch = "aarch64",
+ stable(feature = "neon_intrinsics", since = "1.59.0")
+)]
+pub unsafe fn vcombine_s64(low: int64x1_t, high: int64x1_t) -> int64x2_t {
+ simd_shuffle2!(low, high, [0, 1])
+}
+
+/// Vector combine
+#[inline]
+#[target_feature(enable = "neon")]
+#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
+#[cfg_attr(test, assert_instr(nop))]
+#[cfg_attr(
+ target_arch = "aarch64",
+ stable(feature = "neon_intrinsics", since = "1.59.0")
+)]
+pub unsafe fn vcombine_u8(low: uint8x8_t, high: uint8x8_t) -> uint8x16_t {
+ simd_shuffle16!(
+ low,
+ high,
+ [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15],
+ )
+}
+
+/// Vector combine
+#[inline]
+#[target_feature(enable = "neon")]
+#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
+#[cfg_attr(test, assert_instr(nop))]
+#[cfg_attr(
+ target_arch = "aarch64",
+ stable(feature = "neon_intrinsics", since = "1.59.0")
+)]
+pub unsafe fn vcombine_u16(low: uint16x4_t, high: uint16x4_t) -> uint16x8_t {
+ simd_shuffle8!(low, high, [0, 1, 2, 3, 4, 5, 6, 7])
+}
+
+/// Vector combine
+#[inline]
+#[target_feature(enable = "neon")]
+#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
+#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))]
+#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mov))]
+#[cfg_attr(
+ target_arch = "aarch64",
+ stable(feature = "neon_intrinsics", since = "1.59.0")
+)]
+pub unsafe fn vcombine_u32(low: uint32x2_t, high: uint32x2_t) -> uint32x4_t {
+ simd_shuffle4!(low, high, [0, 1, 2, 3])
+}
+
+/// Vector combine
+#[inline]
+#[target_feature(enable = "neon")]
+#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
+#[cfg_attr(test, assert_instr(nop))]
+#[cfg_attr(
+ target_arch = "aarch64",
+ stable(feature = "neon_intrinsics", since = "1.59.0")
+)]
+pub unsafe fn vcombine_u64(low: uint64x1_t, high: uint64x1_t) -> uint64x2_t {
+ simd_shuffle2!(low, high, [0, 1])
+}
+
+/// Vector combine
+#[inline]
+#[target_feature(enable = "neon")]
+#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
+#[cfg_attr(test, assert_instr(nop))]
+#[cfg_attr(
+ target_arch = "aarch64",
+ stable(feature = "neon_intrinsics", since = "1.59.0")
+)]
+pub unsafe fn vcombine_p64(low: poly64x1_t, high: poly64x1_t) -> poly64x2_t {
+ simd_shuffle2!(low, high, [0, 1])
+}
+
#[cfg(test)]
mod tests {
use super::*;
@@ -12488,6 +12659,44 @@ mod tests {
let r: i32x4 = transmute(vusmmlaq_s32(transmute(a), transmute(b), transmute(c)));
assert_eq!(r, e);
}
+
+ macro_rules! test_vcombine {
+ ($test_id:ident => $fn_id:ident ([$($a:expr),*], [$($b:expr),*])) => {
+ #[allow(unused_assignments)]
+ #[simd_test(enable = "neon")]
+ unsafe fn $test_id() {
+ let a = [$($a),*];
+ let b = [$($b),*];
+ let e = [$($a),* $(, $b)*];
+ let c = $fn_id(transmute(a), transmute(b));
+ let mut d = e;
+ d = transmute(c);
+ assert_eq!(d, e);
+ }
+ }
+ }
+
+ test_vcombine!(test_vcombine_s8 => vcombine_s8([3_i8, -4, 5, -6, 7, 8, 9, 10], [13_i8, -14, 15, -16, 17, 18, 19, 110]));
+ test_vcombine!(test_vcombine_u8 => vcombine_u8([3_u8, 4, 5, 6, 7, 8, 9, 10], [13_u8, 14, 15, 16, 17, 18, 19, 110]));
+ test_vcombine!(test_vcombine_p8 => vcombine_p8([3_u8, 4, 5, 6, 7, 8, 9, 10], [13_u8, 14, 15, 16, 17, 18, 19, 110]));
+
+ test_vcombine!(test_vcombine_s16 => vcombine_s16([3_i16, -4, 5, -6], [13_i16, -14, 15, -16]));
+ test_vcombine!(test_vcombine_u16 => vcombine_u16([3_u16, 4, 5, 6], [13_u16, 14, 15, 16]));
+ test_vcombine!(test_vcombine_p16 => vcombine_p16([3_u16, 4, 5, 6], [13_u16, 14, 15, 16]));
+ // FIXME: 16-bit floats
+ // test_vcombine!(test_vcombine_f16 => vcombine_f16([3_f16, 4., 5., 6.],
+ // [13_f16, 14., 15., 16.]));
+
+ test_vcombine!(test_vcombine_s32 => vcombine_s32([3_i32, -4], [13_i32, -14]));
+ test_vcombine!(test_vcombine_u32 => vcombine_u32([3_u32, 4], [13_u32, 14]));
+ // note: poly32x4 does not exist, and neither does vcombine_p32
+ test_vcombine!(test_vcombine_f32 => vcombine_f32([3_f32, -4.], [13_f32, -14.]));
+
+ test_vcombine!(test_vcombine_s64 => vcombine_s64([-3_i64], [13_i64]));
+ test_vcombine!(test_vcombine_u64 => vcombine_u64([3_u64], [13_u64]));
+ test_vcombine!(test_vcombine_p64 => vcombine_p64([3_u64], [13_u64]));
+ #[cfg(target_arch = "aarch64")]
+ test_vcombine!(test_vcombine_f64 => vcombine_f64([-3_f64], [13_f64]));
}
#[cfg(all(test, target_arch = "arm", target_endian = "little"))]
diff --git a/library/stdarch/crates/core_arch/src/mips/msa.rs b/library/stdarch/crates/core_arch/src/mips/msa.rs
index 85ed30d18..cded73a54 100644
--- a/library/stdarch/crates/core_arch/src/mips/msa.rs
+++ b/library/stdarch/crates/core_arch/src/mips/msa.rs
@@ -2208,7 +2208,7 @@ pub unsafe fn __msa_bmnz_v(a: v16u8, b: v16u8, c: v16u8) -> v16u8 {
/// Immediate Bit Move If Not Zero
///
/// Copy to destination vector `a` (sixteen unsigned 8-bit integer numbers) all bits from source vector
-/// `b` (sixteen unsigned 8-bit integer numbers) for which the corresponding bits from from immediate `imm8`
+/// `b` (sixteen unsigned 8-bit integer numbers) for which the corresponding bits from immediate `imm8`
/// are 1 and leaves unchanged all destination bits for which the corresponding target bits are 0.
///
#[inline]
@@ -2237,7 +2237,7 @@ pub unsafe fn __msa_bmz_v(a: v16u8, b: v16u8, c: v16u8) -> v16u8 {
/// Immediate Bit Move If Zero
///
/// Copy to destination vector `a` (sixteen unsigned 8-bit integer numbers) all bits from source vector
-/// `b` (sixteen unsigned 8-bit integer numbers) for which the corresponding bits from from immediate `imm8`
+/// `b` (sixteen unsigned 8-bit integer numbers) for which the corresponding bits from immediate `imm8`
/// are 0 and leaves unchanged all destination bits for which the corresponding immediate bits are 1.
///
#[inline]
diff --git a/library/stdarch/crates/core_arch/src/mod.rs b/library/stdarch/crates/core_arch/src/mod.rs
index 2f7af22cb..231d89e33 100644
--- a/library/stdarch/crates/core_arch/src/mod.rs
+++ b/library/stdarch/crates/core_arch/src/mod.rs
@@ -155,7 +155,7 @@ pub mod arch {
/// which support SIMD, or it will not have SIMD at all. For compatibility
/// the standard library itself does not use any SIMD internally.
/// Determining how best to ship your WebAssembly binary with SIMD is
- /// largely left up to you as it can can be pretty nuanced depending on
+ /// largely left up to you as it can be pretty nuanced depending on
/// your situation.
///
/// [condsections]: https://github.com/webassembly/conditional-sections
diff --git a/library/stdarch/crates/core_arch/src/x86/avx.rs b/library/stdarch/crates/core_arch/src/x86/avx.rs
index ad9e68db6..f8e83a35b 100644
--- a/library/stdarch/crates/core_arch/src/x86/avx.rs
+++ b/library/stdarch/crates/core_arch/src/x86/avx.rs
@@ -2450,7 +2450,7 @@ pub unsafe fn _mm256_set1_epi8(a: i8) -> __m256i {
)
}
-/// Broadcasts 16-bit integer `a` to all all elements of returned vector.
+/// Broadcasts 16-bit integer `a` to all elements of returned vector.
/// This intrinsic may generate the `vpbroadcastw`.
///
/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_set1_epi16)
diff --git a/library/stdarch/crates/core_arch/src/x86/avx2.rs b/library/stdarch/crates/core_arch/src/x86/avx2.rs
index 16add3dbb..8638b3136 100644
--- a/library/stdarch/crates/core_arch/src/x86/avx2.rs
+++ b/library/stdarch/crates/core_arch/src/x86/avx2.rs
@@ -1857,7 +1857,9 @@ pub unsafe fn _mm256_maskstore_epi64(mem_addr: *mut i64, mask: __m256i, a: __m25
#[cfg_attr(test, assert_instr(vpmaxsw))]
#[stable(feature = "simd_x86", since = "1.27.0")]
pub unsafe fn _mm256_max_epi16(a: __m256i, b: __m256i) -> __m256i {
- transmute(pmaxsw(a.as_i16x16(), b.as_i16x16()))
+ let a = a.as_i16x16();
+ let b = b.as_i16x16();
+ transmute(simd_select::<i16x16, _>(simd_gt(a, b), a, b))
}
/// Compares packed 32-bit integers in `a` and `b`, and returns the packed
@@ -1869,7 +1871,9 @@ pub unsafe fn _mm256_max_epi16(a: __m256i, b: __m256i) -> __m256i {
#[cfg_attr(test, assert_instr(vpmaxsd))]
#[stable(feature = "simd_x86", since = "1.27.0")]
pub unsafe fn _mm256_max_epi32(a: __m256i, b: __m256i) -> __m256i {
- transmute(pmaxsd(a.as_i32x8(), b.as_i32x8()))
+ let a = a.as_i32x8();
+ let b = b.as_i32x8();
+ transmute(simd_select::<i32x8, _>(simd_gt(a, b), a, b))
}
/// Compares packed 8-bit integers in `a` and `b`, and returns the packed
@@ -1881,7 +1885,9 @@ pub unsafe fn _mm256_max_epi32(a: __m256i, b: __m256i) -> __m256i {
#[cfg_attr(test, assert_instr(vpmaxsb))]
#[stable(feature = "simd_x86", since = "1.27.0")]
pub unsafe fn _mm256_max_epi8(a: __m256i, b: __m256i) -> __m256i {
- transmute(pmaxsb(a.as_i8x32(), b.as_i8x32()))
+ let a = a.as_i8x32();
+ let b = b.as_i8x32();
+ transmute(simd_select::<i8x32, _>(simd_gt(a, b), a, b))
}
/// Compares packed unsigned 16-bit integers in `a` and `b`, and returns
@@ -1893,7 +1899,9 @@ pub unsafe fn _mm256_max_epi8(a: __m256i, b: __m256i) -> __m256i {
#[cfg_attr(test, assert_instr(vpmaxuw))]
#[stable(feature = "simd_x86", since = "1.27.0")]
pub unsafe fn _mm256_max_epu16(a: __m256i, b: __m256i) -> __m256i {
- transmute(pmaxuw(a.as_u16x16(), b.as_u16x16()))
+ let a = a.as_u16x16();
+ let b = b.as_u16x16();
+ transmute(simd_select::<i16x16, _>(simd_gt(a, b), a, b))
}
/// Compares packed unsigned 32-bit integers in `a` and `b`, and returns
@@ -1905,7 +1913,9 @@ pub unsafe fn _mm256_max_epu16(a: __m256i, b: __m256i) -> __m256i {
#[cfg_attr(test, assert_instr(vpmaxud))]
#[stable(feature = "simd_x86", since = "1.27.0")]
pub unsafe fn _mm256_max_epu32(a: __m256i, b: __m256i) -> __m256i {
- transmute(pmaxud(a.as_u32x8(), b.as_u32x8()))
+ let a = a.as_u32x8();
+ let b = b.as_u32x8();
+ transmute(simd_select::<i32x8, _>(simd_gt(a, b), a, b))
}
/// Compares packed unsigned 8-bit integers in `a` and `b`, and returns
@@ -1917,7 +1927,9 @@ pub unsafe fn _mm256_max_epu32(a: __m256i, b: __m256i) -> __m256i {
#[cfg_attr(test, assert_instr(vpmaxub))]
#[stable(feature = "simd_x86", since = "1.27.0")]
pub unsafe fn _mm256_max_epu8(a: __m256i, b: __m256i) -> __m256i {
- transmute(pmaxub(a.as_u8x32(), b.as_u8x32()))
+ let a = a.as_u8x32();
+ let b = b.as_u8x32();
+ transmute(simd_select::<i8x32, _>(simd_gt(a, b), a, b))
}
/// Compares packed 16-bit integers in `a` and `b`, and returns the packed
@@ -1929,7 +1941,9 @@ pub unsafe fn _mm256_max_epu8(a: __m256i, b: __m256i) -> __m256i {
#[cfg_attr(test, assert_instr(vpminsw))]
#[stable(feature = "simd_x86", since = "1.27.0")]
pub unsafe fn _mm256_min_epi16(a: __m256i, b: __m256i) -> __m256i {
- transmute(pminsw(a.as_i16x16(), b.as_i16x16()))
+ let a = a.as_i16x16();
+ let b = b.as_i16x16();
+ transmute(simd_select::<i16x16, _>(simd_lt(a, b), a, b))
}
/// Compares packed 32-bit integers in `a` and `b`, and returns the packed
@@ -1941,7 +1955,9 @@ pub unsafe fn _mm256_min_epi16(a: __m256i, b: __m256i) -> __m256i {
#[cfg_attr(test, assert_instr(vpminsd))]
#[stable(feature = "simd_x86", since = "1.27.0")]
pub unsafe fn _mm256_min_epi32(a: __m256i, b: __m256i) -> __m256i {
- transmute(pminsd(a.as_i32x8(), b.as_i32x8()))
+ let a = a.as_i32x8();
+ let b = b.as_i32x8();
+ transmute(simd_select::<i32x8, _>(simd_lt(a, b), a, b))
}
/// Compares packed 8-bit integers in `a` and `b`, and returns the packed
@@ -1953,7 +1969,9 @@ pub unsafe fn _mm256_min_epi32(a: __m256i, b: __m256i) -> __m256i {
#[cfg_attr(test, assert_instr(vpminsb))]
#[stable(feature = "simd_x86", since = "1.27.0")]
pub unsafe fn _mm256_min_epi8(a: __m256i, b: __m256i) -> __m256i {
- transmute(pminsb(a.as_i8x32(), b.as_i8x32()))
+ let a = a.as_i8x32();
+ let b = b.as_i8x32();
+ transmute(simd_select::<i8x32, _>(simd_lt(a, b), a, b))
}
/// Compares packed unsigned 16-bit integers in `a` and `b`, and returns
@@ -1965,7 +1983,9 @@ pub unsafe fn _mm256_min_epi8(a: __m256i, b: __m256i) -> __m256i {
#[cfg_attr(test, assert_instr(vpminuw))]
#[stable(feature = "simd_x86", since = "1.27.0")]
pub unsafe fn _mm256_min_epu16(a: __m256i, b: __m256i) -> __m256i {
- transmute(pminuw(a.as_u16x16(), b.as_u16x16()))
+ let a = a.as_u16x16();
+ let b = b.as_u16x16();
+ transmute(simd_select::<i16x16, _>(simd_lt(a, b), a, b))
}
/// Compares packed unsigned 32-bit integers in `a` and `b`, and returns
@@ -1977,7 +1997,9 @@ pub unsafe fn _mm256_min_epu16(a: __m256i, b: __m256i) -> __m256i {
#[cfg_attr(test, assert_instr(vpminud))]
#[stable(feature = "simd_x86", since = "1.27.0")]
pub unsafe fn _mm256_min_epu32(a: __m256i, b: __m256i) -> __m256i {
- transmute(pminud(a.as_u32x8(), b.as_u32x8()))
+ let a = a.as_u32x8();
+ let b = b.as_u32x8();
+ transmute(simd_select::<i32x8, _>(simd_lt(a, b), a, b))
}
/// Compares packed unsigned 8-bit integers in `a` and `b`, and returns
@@ -1989,7 +2011,9 @@ pub unsafe fn _mm256_min_epu32(a: __m256i, b: __m256i) -> __m256i {
#[cfg_attr(test, assert_instr(vpminub))]
#[stable(feature = "simd_x86", since = "1.27.0")]
pub unsafe fn _mm256_min_epu8(a: __m256i, b: __m256i) -> __m256i {
- transmute(pminub(a.as_u8x32(), b.as_u8x32()))
+ let a = a.as_u8x32();
+ let b = b.as_u8x32();
+ transmute(simd_select::<i8x32, _>(simd_lt(a, b), a, b))
}
/// Creates mask from the most significant bit of each 8-bit element in `a`,
@@ -2001,7 +2025,9 @@ pub unsafe fn _mm256_min_epu8(a: __m256i, b: __m256i) -> __m256i {
#[cfg_attr(test, assert_instr(vpmovmskb))]
#[stable(feature = "simd_x86", since = "1.27.0")]
pub unsafe fn _mm256_movemask_epi8(a: __m256i) -> i32 {
- simd_bitmask::<_, u32>(a.as_i8x32()) as i32
+ let z = i8x32::splat(0);
+ let m: i8x32 = simd_lt(a.as_i8x32(), z);
+ simd_bitmask::<_, u32>(m) as i32
}
/// Computes the sum of absolute differences (SADs) of quadruplets of unsigned
@@ -3618,30 +3644,6 @@ extern "C" {
fn maskstoreq(mem_addr: *mut i8, mask: i64x2, a: i64x2);
#[link_name = "llvm.x86.avx2.maskstore.q.256"]
fn maskstoreq256(mem_addr: *mut i8, mask: i64x4, a: i64x4);
- #[link_name = "llvm.x86.avx2.pmaxs.w"]
- fn pmaxsw(a: i16x16, b: i16x16) -> i16x16;
- #[link_name = "llvm.x86.avx2.pmaxs.d"]
- fn pmaxsd(a: i32x8, b: i32x8) -> i32x8;
- #[link_name = "llvm.x86.avx2.pmaxs.b"]
- fn pmaxsb(a: i8x32, b: i8x32) -> i8x32;
- #[link_name = "llvm.x86.avx2.pmaxu.w"]
- fn pmaxuw(a: u16x16, b: u16x16) -> u16x16;
- #[link_name = "llvm.x86.avx2.pmaxu.d"]
- fn pmaxud(a: u32x8, b: u32x8) -> u32x8;
- #[link_name = "llvm.x86.avx2.pmaxu.b"]
- fn pmaxub(a: u8x32, b: u8x32) -> u8x32;
- #[link_name = "llvm.x86.avx2.pmins.w"]
- fn pminsw(a: i16x16, b: i16x16) -> i16x16;
- #[link_name = "llvm.x86.avx2.pmins.d"]
- fn pminsd(a: i32x8, b: i32x8) -> i32x8;
- #[link_name = "llvm.x86.avx2.pmins.b"]
- fn pminsb(a: i8x32, b: i8x32) -> i8x32;
- #[link_name = "llvm.x86.avx2.pminu.w"]
- fn pminuw(a: u16x16, b: u16x16) -> u16x16;
- #[link_name = "llvm.x86.avx2.pminu.d"]
- fn pminud(a: u32x8, b: u32x8) -> u32x8;
- #[link_name = "llvm.x86.avx2.pminu.b"]
- fn pminub(a: u8x32, b: u8x32) -> u8x32;
#[link_name = "llvm.x86.avx2.mpsadbw"]
fn mpsadbw(a: u8x32, b: u8x32, imm8: i32) -> u16x16;
#[link_name = "llvm.x86.avx2.pmulhu.w"]
diff --git a/library/stdarch/crates/core_arch/src/x86/avx512bf16.rs b/library/stdarch/crates/core_arch/src/x86/avx512bf16.rs
index e9977e018..b21ededab 100644
--- a/library/stdarch/crates/core_arch/src/x86/avx512bf16.rs
+++ b/library/stdarch/crates/core_arch/src/x86/avx512bf16.rs
@@ -80,7 +80,7 @@ pub unsafe fn _mm256_cvtne2ps_pbh(a: __m256, b: __m256) -> __m256bh {
}
/// Convert packed single-precision (32-bit) floating-point elements in two vectors a and b
-/// to packed BF16 (16-bit) floating-point elements and and store the results in single vector
+/// to packed BF16 (16-bit) floating-point elements and store the results in single vector
/// dst using writemask k (elements are copied from src when the corresponding mask bit is not set).
/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#expand=1769,1651,1654&avx512techs=AVX512_BF16&text=_mm256_mask_cvtne2ps_pbh)
#[inline]
diff --git a/library/stdarch/crates/core_arch/src/x86/avx512bitalg.rs b/library/stdarch/crates/core_arch/src/x86/avx512bitalg.rs
index 3c9df3912..1099ee2cb 100644
--- a/library/stdarch/crates/core_arch/src/x86/avx512bitalg.rs
+++ b/library/stdarch/crates/core_arch/src/x86/avx512bitalg.rs
@@ -303,7 +303,7 @@ pub unsafe fn _mm_mask_popcnt_epi8(src: __m128i, k: __mmask16, a: __m128i) -> __
}
/// Considers the input `b` as packed 64-bit integers and `c` as packed 8-bit integers.
-/// Then groups 8 8-bit values from `c`as indices into the the bits of the corresponding 64-bit integer.
+/// Then groups 8 8-bit values from `c`as indices into the bits of the corresponding 64-bit integer.
/// It then selects these bits and packs them into the output.
///
/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_bitshuffle_epi64_mask)
@@ -315,7 +315,7 @@ pub unsafe fn _mm512_bitshuffle_epi64_mask(b: __m512i, c: __m512i) -> __mmask64
}
/// Considers the input `b` as packed 64-bit integers and `c` as packed 8-bit integers.
-/// Then groups 8 8-bit values from `c`as indices into the the bits of the corresponding 64-bit integer.
+/// Then groups 8 8-bit values from `c`as indices into the bits of the corresponding 64-bit integer.
/// It then selects these bits and packs them into the output.
///
/// Uses the writemask in k - elements are zeroed in the result if the corresponding mask bit is not set.
@@ -330,7 +330,7 @@ pub unsafe fn _mm512_mask_bitshuffle_epi64_mask(k: __mmask64, b: __m512i, c: __m
}
/// Considers the input `b` as packed 64-bit integers and `c` as packed 8-bit integers.
-/// Then groups 8 8-bit values from `c`as indices into the the bits of the corresponding 64-bit integer.
+/// Then groups 8 8-bit values from `c`as indices into the bits of the corresponding 64-bit integer.
/// It then selects these bits and packs them into the output.
///
/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_bitshuffle_epi64_mask)
@@ -342,7 +342,7 @@ pub unsafe fn _mm256_bitshuffle_epi64_mask(b: __m256i, c: __m256i) -> __mmask32
}
/// Considers the input `b` as packed 64-bit integers and `c` as packed 8-bit integers.
-/// Then groups 8 8-bit values from `c`as indices into the the bits of the corresponding 64-bit integer.
+/// Then groups 8 8-bit values from `c`as indices into the bits of the corresponding 64-bit integer.
/// It then selects these bits and packs them into the output.
///
/// Uses the writemask in k - elements are zeroed in the result if the corresponding mask bit is not set.
@@ -357,7 +357,7 @@ pub unsafe fn _mm256_mask_bitshuffle_epi64_mask(k: __mmask32, b: __m256i, c: __m
}
/// Considers the input `b` as packed 64-bit integers and `c` as packed 8-bit integers.
-/// Then groups 8 8-bit values from `c`as indices into the the bits of the corresponding 64-bit integer.
+/// Then groups 8 8-bit values from `c`as indices into the bits of the corresponding 64-bit integer.
/// It then selects these bits and packs them into the output.
///
/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_bitshuffle_epi64_mask)
@@ -369,7 +369,7 @@ pub unsafe fn _mm_bitshuffle_epi64_mask(b: __m128i, c: __m128i) -> __mmask16 {
}
/// Considers the input `b` as packed 64-bit integers and `c` as packed 8-bit integers.
-/// Then groups 8 8-bit values from `c`as indices into the the bits of the corresponding 64-bit integer.
+/// Then groups 8 8-bit values from `c`as indices into the bits of the corresponding 64-bit integer.
/// It then selects these bits and packs them into the output.
///
/// Uses the writemask in k - elements are zeroed in the result if the corresponding mask bit is not set.
diff --git a/library/stdarch/crates/core_arch/src/x86/avx512bw.rs b/library/stdarch/crates/core_arch/src/x86/avx512bw.rs
index 49d78ed60..fbf71dfc4 100644
--- a/library/stdarch/crates/core_arch/src/x86/avx512bw.rs
+++ b/library/stdarch/crates/core_arch/src/x86/avx512bw.rs
@@ -7450,7 +7450,7 @@ pub unsafe fn _mm_maskz_set1_epi8(k: __mmask16, a: i8) -> __m128i {
transmute(simd_select_bitmask(k, r, zero))
}
-/// Shuffle 16-bit integers in the low 64 bits of 128-bit lanes of a using the control in imm8. Store the results in the low 64 bits of 128-bit lanes of dst, with the high 64 bits of 128-bit lanes being copied from from a to dst.
+/// Shuffle 16-bit integers in the low 64 bits of 128-bit lanes of a using the control in imm8. Store the results in the low 64 bits of 128-bit lanes of dst, with the high 64 bits of 128-bit lanes being copied from a to dst.
///
/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_shufflelo_epi16&expand=5221)
#[inline]
@@ -7501,7 +7501,7 @@ pub unsafe fn _mm512_shufflelo_epi16<const IMM8: i32>(a: __m512i) -> __m512i {
transmute(r)
}
-/// Shuffle 16-bit integers in the low 64 bits of 128-bit lanes of a using the control in imm8. Store the results in the low 64 bits of 128-bit lanes of dst, with the high 64 bits of 128-bit lanes being copied from from a to dst, using writemask k (elements are copied from src when the corresponding mask bit is not set).
+/// Shuffle 16-bit integers in the low 64 bits of 128-bit lanes of a using the control in imm8. Store the results in the low 64 bits of 128-bit lanes of dst, with the high 64 bits of 128-bit lanes being copied from a to dst, using writemask k (elements are copied from src when the corresponding mask bit is not set).
///
/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_shufflelo_epi16&expand=5219)
#[inline]
@@ -7518,7 +7518,7 @@ pub unsafe fn _mm512_mask_shufflelo_epi16<const IMM8: i32>(
transmute(simd_select_bitmask(k, r.as_i16x32(), src.as_i16x32()))
}
-/// Shuffle 16-bit integers in the low 64 bits of 128-bit lanes of a using the control in imm8. Store the results in the low 64 bits of 128-bit lanes of dst, with the high 64 bits of 128-bit lanes being copied from from a to dst, using zeromask k (elements are zeroed out when the corresponding mask bit is not set).
+/// Shuffle 16-bit integers in the low 64 bits of 128-bit lanes of a using the control in imm8. Store the results in the low 64 bits of 128-bit lanes of dst, with the high 64 bits of 128-bit lanes being copied from a to dst, using zeromask k (elements are zeroed out when the corresponding mask bit is not set).
///
/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_shufflelo_epi16&expand=5220)
#[inline]
@@ -7532,7 +7532,7 @@ pub unsafe fn _mm512_maskz_shufflelo_epi16<const IMM8: i32>(k: __mmask32, a: __m
transmute(simd_select_bitmask(k, r.as_i16x32(), zero))
}
-/// Shuffle 16-bit integers in the low 64 bits of 128-bit lanes of a using the control in imm8. Store the results in the low 64 bits of 128-bit lanes of dst, with the high 64 bits of 128-bit lanes being copied from from a to dst, using writemask k (elements are copied from src when the corresponding mask bit is not set).
+/// Shuffle 16-bit integers in the low 64 bits of 128-bit lanes of a using the control in imm8. Store the results in the low 64 bits of 128-bit lanes of dst, with the high 64 bits of 128-bit lanes being copied from a to dst, using writemask k (elements are copied from src when the corresponding mask bit is not set).
///
/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_shufflelo_epi16&expand=5216)
#[inline]
@@ -7549,7 +7549,7 @@ pub unsafe fn _mm256_mask_shufflelo_epi16<const IMM8: i32>(
transmute(simd_select_bitmask(k, shuffle.as_i16x16(), src.as_i16x16()))
}
-/// Shuffle 16-bit integers in the low 64 bits of 128-bit lanes of a using the control in imm8. Store the results in the low 64 bits of 128-bit lanes of dst, with the high 64 bits of 128-bit lanes being copied from from a to dst, using writemask k (elements are copied from src when the corresponding mask bit is not set).
+/// Shuffle 16-bit integers in the low 64 bits of 128-bit lanes of a using the control in imm8. Store the results in the low 64 bits of 128-bit lanes of dst, with the high 64 bits of 128-bit lanes being copied from a to dst, using writemask k (elements are copied from src when the corresponding mask bit is not set).
///
/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_shufflelo_epi16&expand=5217)
#[inline]
@@ -7563,7 +7563,7 @@ pub unsafe fn _mm256_maskz_shufflelo_epi16<const IMM8: i32>(k: __mmask16, a: __m
transmute(simd_select_bitmask(k, shuffle.as_i16x16(), zero))
}
-/// Shuffle 16-bit integers in the low 64 bits of 128-bit lanes of a using the control in imm8. Store the results in the low 64 bits of 128-bit lanes of dst, with the high 64 bits of 128-bit lanes being copied from from a to dst, using writemask k (elements are copied from src when the corresponding mask bit is not set).
+/// Shuffle 16-bit integers in the low 64 bits of 128-bit lanes of a using the control in imm8. Store the results in the low 64 bits of 128-bit lanes of dst, with the high 64 bits of 128-bit lanes being copied from a to dst, using writemask k (elements are copied from src when the corresponding mask bit is not set).
///
/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_shufflelo_epi16&expand=5213)
#[inline]
@@ -7580,7 +7580,7 @@ pub unsafe fn _mm_mask_shufflelo_epi16<const IMM8: i32>(
transmute(simd_select_bitmask(k, shuffle.as_i16x8(), src.as_i16x8()))
}
-/// Shuffle 16-bit integers in the low 64 bits of 128-bit lanes of a using the control in imm8. Store the results in the low 64 bits of 128-bit lanes of dst, with the high 64 bits of 128-bit lanes being copied from from a to dst, using writemask k (elements are copied from src when the corresponding mask bit is not set).
+/// Shuffle 16-bit integers in the low 64 bits of 128-bit lanes of a using the control in imm8. Store the results in the low 64 bits of 128-bit lanes of dst, with the high 64 bits of 128-bit lanes being copied from a to dst, using writemask k (elements are copied from src when the corresponding mask bit is not set).
///
/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_shufflelo_epi16&expand=5214)
#[inline]
@@ -7594,7 +7594,7 @@ pub unsafe fn _mm_maskz_shufflelo_epi16<const IMM8: i32>(k: __mmask8, a: __m128i
transmute(simd_select_bitmask(k, shuffle.as_i16x8(), zero))
}
-/// Shuffle 16-bit integers in the high 64 bits of 128-bit lanes of a using the control in imm8. Store the results in the high 64 bits of 128-bit lanes of dst, with the low 64 bits of 128-bit lanes being copied from from a to dst.
+/// Shuffle 16-bit integers in the high 64 bits of 128-bit lanes of a using the control in imm8. Store the results in the high 64 bits of 128-bit lanes of dst, with the low 64 bits of 128-bit lanes being copied from a to dst.
///
/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_shufflehi_epi16&expand=5212)
#[inline]
@@ -7645,7 +7645,7 @@ pub unsafe fn _mm512_shufflehi_epi16<const IMM8: i32>(a: __m512i) -> __m512i {
transmute(r)
}
-/// Shuffle 16-bit integers in the high 64 bits of 128-bit lanes of a using the control in imm8. Store the results in the high 64 bits of 128-bit lanes of dst, with the low 64 bits of 128-bit lanes being copied from from a to dst, using writemask k (elements are copied from src when the corresponding mask bit is not set).
+/// Shuffle 16-bit integers in the high 64 bits of 128-bit lanes of a using the control in imm8. Store the results in the high 64 bits of 128-bit lanes of dst, with the low 64 bits of 128-bit lanes being copied from a to dst, using writemask k (elements are copied from src when the corresponding mask bit is not set).
///
/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_shufflehi_epi16&expand=5210)
#[inline]
@@ -7662,7 +7662,7 @@ pub unsafe fn _mm512_mask_shufflehi_epi16<const IMM8: i32>(
transmute(simd_select_bitmask(k, r.as_i16x32(), src.as_i16x32()))
}
-/// Shuffle 16-bit integers in the high 64 bits of 128-bit lanes of a using the control in imm8. Store the results in the high 64 bits of 128-bit lanes of dst, with the low 64 bits of 128-bit lanes being copied from from a to dst, using zeromask k (elements are zeroed out when the corresponding mask bit is not set).
+/// Shuffle 16-bit integers in the high 64 bits of 128-bit lanes of a using the control in imm8. Store the results in the high 64 bits of 128-bit lanes of dst, with the low 64 bits of 128-bit lanes being copied from a to dst, using zeromask k (elements are zeroed out when the corresponding mask bit is not set).
///
/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_shufflehi_epi16&expand=5211)
#[inline]
@@ -7676,7 +7676,7 @@ pub unsafe fn _mm512_maskz_shufflehi_epi16<const IMM8: i32>(k: __mmask32, a: __m
transmute(simd_select_bitmask(k, r.as_i16x32(), zero))
}
-/// Shuffle 16-bit integers in the high 64 bits of 128-bit lanes of a using the control in imm8. Store the results in the high 64 bits of 128-bit lanes of dst, with the low 64 bits of 128-bit lanes being copied from from a to dst, using writemask k (elements are copied from src when the corresponding mask bit is not set).
+/// Shuffle 16-bit integers in the high 64 bits of 128-bit lanes of a using the control in imm8. Store the results in the high 64 bits of 128-bit lanes of dst, with the low 64 bits of 128-bit lanes being copied from a to dst, using writemask k (elements are copied from src when the corresponding mask bit is not set).
///
/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_shufflehi_epi16&expand=5207)
#[inline]
@@ -7693,7 +7693,7 @@ pub unsafe fn _mm256_mask_shufflehi_epi16<const IMM8: i32>(
transmute(simd_select_bitmask(k, shuffle.as_i16x16(), src.as_i16x16()))
}
-/// Shuffle 16-bit integers in the high 64 bits of 128-bit lanes of a using the control in imm8. Store the results in the high 64 bits of 128-bit lanes of dst, with the low 64 bits of 128-bit lanes being copied from from a to dst, using zeromask k (elements are zeroed out when the corresponding mask bit is not set).
+/// Shuffle 16-bit integers in the high 64 bits of 128-bit lanes of a using the control in imm8. Store the results in the high 64 bits of 128-bit lanes of dst, with the low 64 bits of 128-bit lanes being copied from a to dst, using zeromask k (elements are zeroed out when the corresponding mask bit is not set).
///
/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_shufflehi_epi16&expand=5208)
#[inline]
@@ -7707,7 +7707,7 @@ pub unsafe fn _mm256_maskz_shufflehi_epi16<const IMM8: i32>(k: __mmask16, a: __m
transmute(simd_select_bitmask(k, shuffle.as_i16x16(), zero))
}
-/// Shuffle 16-bit integers in the high 64 bits of 128-bit lanes of a using the control in imm8. Store the results in the high 64 bits of 128-bit lanes of dst, with the low 64 bits of 128-bit lanes being copied from from a to dst, using writemask k (elements are copied from src when the corresponding mask bit is not set).
+/// Shuffle 16-bit integers in the high 64 bits of 128-bit lanes of a using the control in imm8. Store the results in the high 64 bits of 128-bit lanes of dst, with the low 64 bits of 128-bit lanes being copied from a to dst, using writemask k (elements are copied from src when the corresponding mask bit is not set).
///
/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_shufflehi_epi16&expand=5204)
#[inline]
@@ -7724,7 +7724,7 @@ pub unsafe fn _mm_mask_shufflehi_epi16<const IMM8: i32>(
transmute(simd_select_bitmask(k, shuffle.as_i16x8(), src.as_i16x8()))
}
-/// Shuffle 16-bit integers in the high 64 bits of 128-bit lanes of a using the control in imm8. Store the results in the high 64 bits of 128-bit lanes of dst, with the low 64 bits of 128-bit lanes being copied from from a to dst, using zeromask k (elements are zeroed out when the corresponding mask bit is not set).
+/// Shuffle 16-bit integers in the high 64 bits of 128-bit lanes of a using the control in imm8. Store the results in the high 64 bits of 128-bit lanes of dst, with the low 64 bits of 128-bit lanes being copied from a to dst, using zeromask k (elements are zeroed out when the corresponding mask bit is not set).
///
/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_shufflehi_epi16&expand=5205)
#[inline]
diff --git a/library/stdarch/crates/core_arch/src/x86/avx512f.rs b/library/stdarch/crates/core_arch/src/x86/avx512f.rs
index f70a28466..0ddb51283 100644
--- a/library/stdarch/crates/core_arch/src/x86/avx512f.rs
+++ b/library/stdarch/crates/core_arch/src/x86/avx512f.rs
@@ -26268,7 +26268,7 @@ pub unsafe fn _mm512_set1_epi8(a: i8) -> __m512i {
transmute(i8x64::splat(a))
}
-/// Broadcast the low packed 16-bit integer from a to all all elements of dst.
+/// Broadcast the low packed 16-bit integer from a to all elements of dst.
///
/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_set1_epi16&expand=4944)
#[inline]
diff --git a/library/stdarch/crates/core_arch/src/x86/avx512gfni.rs b/library/stdarch/crates/core_arch/src/x86/gfni.rs
index 66fd1c2e1..679b2548a 100644
--- a/library/stdarch/crates/core_arch/src/x86/avx512gfni.rs
+++ b/library/stdarch/crates/core_arch/src/x86/gfni.rs
@@ -65,7 +65,7 @@ extern "C" {
///
/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_gf2p8mul_epi8)
#[inline]
-#[target_feature(enable = "avx512gfni,avx512bw,avx512f")]
+#[target_feature(enable = "gfni,avx512bw,avx512f")]
#[cfg_attr(test, assert_instr(vgf2p8mulb))]
pub unsafe fn _mm512_gf2p8mul_epi8(a: __m512i, b: __m512i) -> __m512i {
transmute(vgf2p8mulb_512(a.as_i8x64(), b.as_i8x64()))
@@ -80,7 +80,7 @@ pub unsafe fn _mm512_gf2p8mul_epi8(a: __m512i, b: __m512i) -> __m512i {
///
/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_gf2p8mul_epi8)
#[inline]
-#[target_feature(enable = "avx512gfni,avx512bw,avx512f")]
+#[target_feature(enable = "gfni,avx512bw,avx512f")]
#[cfg_attr(test, assert_instr(vgf2p8mulb))]
pub unsafe fn _mm512_mask_gf2p8mul_epi8(
src: __m512i,
@@ -104,7 +104,7 @@ pub unsafe fn _mm512_mask_gf2p8mul_epi8(
///
/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_gf2p8mul_epi8)
#[inline]
-#[target_feature(enable = "avx512gfni,avx512bw,avx512f")]
+#[target_feature(enable = "gfni,avx512bw,avx512f")]
#[cfg_attr(test, assert_instr(vgf2p8mulb))]
pub unsafe fn _mm512_maskz_gf2p8mul_epi8(k: __mmask64, a: __m512i, b: __m512i) -> __m512i {
let zero = _mm512_setzero_si512().as_i8x64();
@@ -121,7 +121,7 @@ pub unsafe fn _mm512_maskz_gf2p8mul_epi8(k: __mmask64, a: __m512i, b: __m512i) -
///
/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_gf2p8mul_epi8)
#[inline]
-#[target_feature(enable = "avx512gfni,avx512bw,avx512vl")]
+#[target_feature(enable = "gfni,avx")]
#[cfg_attr(test, assert_instr(vgf2p8mulb))]
pub unsafe fn _mm256_gf2p8mul_epi8(a: __m256i, b: __m256i) -> __m256i {
transmute(vgf2p8mulb_256(a.as_i8x32(), b.as_i8x32()))
@@ -136,7 +136,7 @@ pub unsafe fn _mm256_gf2p8mul_epi8(a: __m256i, b: __m256i) -> __m256i {
///
/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_gf2p8mul_epi8)
#[inline]
-#[target_feature(enable = "avx512gfni,avx512bw,avx512vl")]
+#[target_feature(enable = "gfni,avx512bw,avx512vl")]
#[cfg_attr(test, assert_instr(vgf2p8mulb))]
pub unsafe fn _mm256_mask_gf2p8mul_epi8(
src: __m256i,
@@ -160,7 +160,7 @@ pub unsafe fn _mm256_mask_gf2p8mul_epi8(
///
/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_gf2p8mul_epi8)
#[inline]
-#[target_feature(enable = "avx512gfni,avx512bw,avx512vl")]
+#[target_feature(enable = "gfni,avx512bw,avx512vl")]
#[cfg_attr(test, assert_instr(vgf2p8mulb))]
pub unsafe fn _mm256_maskz_gf2p8mul_epi8(k: __mmask32, a: __m256i, b: __m256i) -> __m256i {
let zero = _mm256_setzero_si256().as_i8x32();
@@ -177,8 +177,8 @@ pub unsafe fn _mm256_maskz_gf2p8mul_epi8(k: __mmask32, a: __m256i, b: __m256i) -
///
/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_gf2p8mul_epi8)
#[inline]
-#[target_feature(enable = "avx512gfni,avx512bw,avx512vl")]
-#[cfg_attr(test, assert_instr(vgf2p8mulb))]
+#[target_feature(enable = "gfni")]
+#[cfg_attr(test, assert_instr(gf2p8mulb))]
pub unsafe fn _mm_gf2p8mul_epi8(a: __m128i, b: __m128i) -> __m128i {
transmute(vgf2p8mulb_128(a.as_i8x16(), b.as_i8x16()))
}
@@ -192,7 +192,7 @@ pub unsafe fn _mm_gf2p8mul_epi8(a: __m128i, b: __m128i) -> __m128i {
///
/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_gf2p8mul_epi8)
#[inline]
-#[target_feature(enable = "avx512gfni,avx512bw,avx512vl")]
+#[target_feature(enable = "gfni,avx512bw,avx512vl")]
#[cfg_attr(test, assert_instr(vgf2p8mulb))]
pub unsafe fn _mm_mask_gf2p8mul_epi8(
src: __m128i,
@@ -216,7 +216,7 @@ pub unsafe fn _mm_mask_gf2p8mul_epi8(
///
/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_gf2p8mul_epi8)
#[inline]
-#[target_feature(enable = "avx512gfni,avx512bw,avx512vl")]
+#[target_feature(enable = "gfni,avx512bw,avx512vl")]
#[cfg_attr(test, assert_instr(vgf2p8mulb))]
pub unsafe fn _mm_maskz_gf2p8mul_epi8(k: __mmask16, a: __m128i, b: __m128i) -> __m128i {
let zero = _mm_setzero_si128().as_i8x16();
@@ -234,7 +234,7 @@ pub unsafe fn _mm_maskz_gf2p8mul_epi8(k: __mmask16, a: __m128i, b: __m128i) -> _
///
/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_gf2p8affine_epi8)
#[inline]
-#[target_feature(enable = "avx512gfni,avx512bw,avx512f")]
+#[target_feature(enable = "gfni,avx512bw,avx512f")]
#[cfg_attr(test, assert_instr(vgf2p8affineqb, B = 0))]
#[rustc_legacy_const_generics(2)]
pub unsafe fn _mm512_gf2p8affine_epi64_epi8<const B: i32>(x: __m512i, a: __m512i) -> __m512i {
@@ -256,7 +256,7 @@ pub unsafe fn _mm512_gf2p8affine_epi64_epi8<const B: i32>(x: __m512i, a: __m512i
///
/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_gf2p8affine_epi8)
#[inline]
-#[target_feature(enable = "avx512gfni,avx512bw,avx512f")]
+#[target_feature(enable = "gfni,avx512bw,avx512f")]
#[cfg_attr(test, assert_instr(vgf2p8affineqb, B = 0))]
#[rustc_legacy_const_generics(3)]
pub unsafe fn _mm512_maskz_gf2p8affine_epi64_epi8<const B: i32>(
@@ -283,7 +283,7 @@ pub unsafe fn _mm512_maskz_gf2p8affine_epi64_epi8<const B: i32>(
///
/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_gf2p8affine_epi8)
#[inline]
-#[target_feature(enable = "avx512gfni,avx512bw,avx512f")]
+#[target_feature(enable = "gfni,avx512bw,avx512f")]
#[cfg_attr(test, assert_instr(vgf2p8affineqb, B = 0))]
#[rustc_legacy_const_generics(4)]
pub unsafe fn _mm512_mask_gf2p8affine_epi64_epi8<const B: i32>(
@@ -307,7 +307,7 @@ pub unsafe fn _mm512_mask_gf2p8affine_epi64_epi8<const B: i32>(
///
/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_gf2p8affine_epi8)
#[inline]
-#[target_feature(enable = "avx512gfni,avx512bw,avx512vl")]
+#[target_feature(enable = "gfni,avx")]
#[cfg_attr(test, assert_instr(vgf2p8affineqb, B = 0))]
#[rustc_legacy_const_generics(2)]
pub unsafe fn _mm256_gf2p8affine_epi64_epi8<const B: i32>(x: __m256i, a: __m256i) -> __m256i {
@@ -329,7 +329,7 @@ pub unsafe fn _mm256_gf2p8affine_epi64_epi8<const B: i32>(x: __m256i, a: __m256i
///
/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_gf2p8affine_epi8)
#[inline]
-#[target_feature(enable = "avx512gfni,avx512bw,avx512vl")]
+#[target_feature(enable = "gfni,avx512bw,avx512vl")]
#[cfg_attr(test, assert_instr(vgf2p8affineqb, B = 0))]
#[rustc_legacy_const_generics(3)]
pub unsafe fn _mm256_maskz_gf2p8affine_epi64_epi8<const B: i32>(
@@ -356,7 +356,7 @@ pub unsafe fn _mm256_maskz_gf2p8affine_epi64_epi8<const B: i32>(
///
/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_gf2p8affine_epi8)
#[inline]
-#[target_feature(enable = "avx512gfni,avx512bw,avx512vl")]
+#[target_feature(enable = "gfni,avx512bw,avx512vl")]
#[cfg_attr(test, assert_instr(vgf2p8affineqb, B = 0))]
#[rustc_legacy_const_generics(4)]
pub unsafe fn _mm256_mask_gf2p8affine_epi64_epi8<const B: i32>(
@@ -380,8 +380,8 @@ pub unsafe fn _mm256_mask_gf2p8affine_epi64_epi8<const B: i32>(
///
/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_gf2p8affine_epi8)
#[inline]
-#[target_feature(enable = "avx512gfni,avx512bw,avx512vl")]
-#[cfg_attr(test, assert_instr(vgf2p8affineqb, B = 0))]
+#[target_feature(enable = "gfni")]
+#[cfg_attr(test, assert_instr(gf2p8affineqb, B = 0))]
#[rustc_legacy_const_generics(2)]
pub unsafe fn _mm_gf2p8affine_epi64_epi8<const B: i32>(x: __m128i, a: __m128i) -> __m128i {
static_assert_imm8!(B);
@@ -402,7 +402,7 @@ pub unsafe fn _mm_gf2p8affine_epi64_epi8<const B: i32>(x: __m128i, a: __m128i) -
///
/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_gf2p8affine_epi8)
#[inline]
-#[target_feature(enable = "avx512gfni,avx512bw,avx512vl")]
+#[target_feature(enable = "gfni,avx512bw,avx512vl")]
#[cfg_attr(test, assert_instr(vgf2p8affineqb, B = 0))]
#[rustc_legacy_const_generics(3)]
pub unsafe fn _mm_maskz_gf2p8affine_epi64_epi8<const B: i32>(
@@ -429,7 +429,7 @@ pub unsafe fn _mm_maskz_gf2p8affine_epi64_epi8<const B: i32>(
///
/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_gf2p8affine_epi8)
#[inline]
-#[target_feature(enable = "avx512gfni,avx512bw,avx512vl")]
+#[target_feature(enable = "gfni,avx512bw,avx512vl")]
#[cfg_attr(test, assert_instr(vgf2p8affineqb, B = 0))]
#[rustc_legacy_const_generics(4)]
pub unsafe fn _mm_mask_gf2p8affine_epi64_epi8<const B: i32>(
@@ -455,7 +455,7 @@ pub unsafe fn _mm_mask_gf2p8affine_epi64_epi8<const B: i32>(
///
/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_gf2p8affineinv_epi64_epi8)
#[inline]
-#[target_feature(enable = "avx512gfni,avx512bw,avx512f")]
+#[target_feature(enable = "gfni,avx512bw,avx512f")]
#[cfg_attr(test, assert_instr(vgf2p8affineinvqb, B = 0))]
#[rustc_legacy_const_generics(2)]
pub unsafe fn _mm512_gf2p8affineinv_epi64_epi8<const B: i32>(x: __m512i, a: __m512i) -> __m512i {
@@ -479,7 +479,7 @@ pub unsafe fn _mm512_gf2p8affineinv_epi64_epi8<const B: i32>(x: __m512i, a: __m5
///
/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_gf2p8affineinv_epi64_epi8)
#[inline]
-#[target_feature(enable = "avx512gfni,avx512bw,avx512f")]
+#[target_feature(enable = "gfni,avx512bw,avx512f")]
#[cfg_attr(test, assert_instr(vgf2p8affineinvqb, B = 0))]
#[rustc_legacy_const_generics(3)]
pub unsafe fn _mm512_maskz_gf2p8affineinv_epi64_epi8<const B: i32>(
@@ -508,7 +508,7 @@ pub unsafe fn _mm512_maskz_gf2p8affineinv_epi64_epi8<const B: i32>(
///
/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_gf2p8affineinv_epi64_epi8)
#[inline]
-#[target_feature(enable = "avx512gfni,avx512bw,avx512f")]
+#[target_feature(enable = "gfni,avx512bw,avx512f")]
#[cfg_attr(test, assert_instr(vgf2p8affineinvqb, B = 0))]
#[rustc_legacy_const_generics(4)]
pub unsafe fn _mm512_mask_gf2p8affineinv_epi64_epi8<const B: i32>(
@@ -534,7 +534,7 @@ pub unsafe fn _mm512_mask_gf2p8affineinv_epi64_epi8<const B: i32>(
///
/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_gf2p8affineinv_epi64_epi8)
#[inline]
-#[target_feature(enable = "avx512gfni,avx512bw,avx512vl")]
+#[target_feature(enable = "gfni,avx")]
#[cfg_attr(test, assert_instr(vgf2p8affineinvqb, B = 0))]
#[rustc_legacy_const_generics(2)]
pub unsafe fn _mm256_gf2p8affineinv_epi64_epi8<const B: i32>(x: __m256i, a: __m256i) -> __m256i {
@@ -558,7 +558,7 @@ pub unsafe fn _mm256_gf2p8affineinv_epi64_epi8<const B: i32>(x: __m256i, a: __m2
///
/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_gf2p8affineinv_epi64_epi8)
#[inline]
-#[target_feature(enable = "avx512gfni,avx512bw,avx512vl")]
+#[target_feature(enable = "gfni,avx512bw,avx512vl")]
#[cfg_attr(test, assert_instr(vgf2p8affineinvqb, B = 0))]
#[rustc_legacy_const_generics(3)]
pub unsafe fn _mm256_maskz_gf2p8affineinv_epi64_epi8<const B: i32>(
@@ -587,7 +587,7 @@ pub unsafe fn _mm256_maskz_gf2p8affineinv_epi64_epi8<const B: i32>(
///
/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_gf2p8affineinv_epi64_epi8)
#[inline]
-#[target_feature(enable = "avx512gfni,avx512bw,avx512vl")]
+#[target_feature(enable = "gfni,avx512bw,avx512vl")]
#[cfg_attr(test, assert_instr(vgf2p8affineinvqb, B = 0))]
#[rustc_legacy_const_generics(4)]
pub unsafe fn _mm256_mask_gf2p8affineinv_epi64_epi8<const B: i32>(
@@ -613,8 +613,8 @@ pub unsafe fn _mm256_mask_gf2p8affineinv_epi64_epi8<const B: i32>(
///
/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_gf2p8affineinv_epi64_epi8)
#[inline]
-#[target_feature(enable = "avx512gfni,avx512bw,avx512vl")]
-#[cfg_attr(test, assert_instr(vgf2p8affineinvqb, B = 0))]
+#[target_feature(enable = "gfni")]
+#[cfg_attr(test, assert_instr(gf2p8affineinvqb, B = 0))]
#[rustc_legacy_const_generics(2)]
pub unsafe fn _mm_gf2p8affineinv_epi64_epi8<const B: i32>(x: __m128i, a: __m128i) -> __m128i {
static_assert_imm8!(B);
@@ -637,7 +637,7 @@ pub unsafe fn _mm_gf2p8affineinv_epi64_epi8<const B: i32>(x: __m128i, a: __m128i
///
/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_gf2p8affineinv_epi64_epi8)
#[inline]
-#[target_feature(enable = "avx512gfni,avx512bw,avx512vl")]
+#[target_feature(enable = "gfni,avx512bw,avx512vl")]
#[cfg_attr(test, assert_instr(vgf2p8affineinvqb, B = 0))]
#[rustc_legacy_const_generics(3)]
pub unsafe fn _mm_maskz_gf2p8affineinv_epi64_epi8<const B: i32>(
@@ -666,7 +666,7 @@ pub unsafe fn _mm_maskz_gf2p8affineinv_epi64_epi8<const B: i32>(
///
/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_gf2p8affineinv_epi64_epi8)
#[inline]
-#[target_feature(enable = "avx512gfni,avx512bw,avx512vl")]
+#[target_feature(enable = "gfni,avx512bw,avx512vl")]
#[cfg_attr(test, assert_instr(vgf2p8affineinvqb, B = 0))]
#[rustc_legacy_const_generics(4)]
pub unsafe fn _mm_mask_gf2p8affineinv_epi64_epi8<const B: i32>(
@@ -847,7 +847,7 @@ mod tests {
_mm512_loadu_si512(black_box(pointer))
}
- #[simd_test(enable = "avx512gfni,avx512bw")]
+ #[simd_test(enable = "gfni,avx512bw")]
unsafe fn test_mm512_gf2p8mul_epi8() {
let (left, right, expected) = generate_byte_mul_test_data();
@@ -860,7 +860,7 @@ mod tests {
}
}
- #[simd_test(enable = "avx512gfni,avx512bw")]
+ #[simd_test(enable = "gfni,avx512bw")]
unsafe fn test_mm512_maskz_gf2p8mul_epi8() {
let (left, right, _expected) = generate_byte_mul_test_data();
@@ -879,7 +879,7 @@ mod tests {
}
}
- #[simd_test(enable = "avx512gfni,avx512bw")]
+ #[simd_test(enable = "gfni,avx512bw")]
unsafe fn test_mm512_mask_gf2p8mul_epi8() {
let (left, right, _expected) = generate_byte_mul_test_data();
@@ -897,7 +897,7 @@ mod tests {
}
}
- #[simd_test(enable = "avx512gfni,avx512bw,avx512vl")]
+ #[simd_test(enable = "gfni,avx512bw,avx512vl")]
unsafe fn test_mm256_gf2p8mul_epi8() {
let (left, right, expected) = generate_byte_mul_test_data();
@@ -910,7 +910,7 @@ mod tests {
}
}
- #[simd_test(enable = "avx512gfni,avx512bw,avx512vl")]
+ #[simd_test(enable = "gfni,avx512bw,avx512vl")]
unsafe fn test_mm256_maskz_gf2p8mul_epi8() {
let (left, right, _expected) = generate_byte_mul_test_data();
@@ -929,7 +929,7 @@ mod tests {
}
}
- #[simd_test(enable = "avx512gfni,avx512bw,avx512vl")]
+ #[simd_test(enable = "gfni,avx512bw,avx512vl")]
unsafe fn test_mm256_mask_gf2p8mul_epi8() {
let (left, right, _expected) = generate_byte_mul_test_data();
@@ -947,7 +947,7 @@ mod tests {
}
}
- #[simd_test(enable = "avx512gfni,avx512bw,avx512vl")]
+ #[simd_test(enable = "gfni,avx512bw,avx512vl")]
unsafe fn test_mm_gf2p8mul_epi8() {
let (left, right, expected) = generate_byte_mul_test_data();
@@ -960,7 +960,7 @@ mod tests {
}
}
- #[simd_test(enable = "avx512gfni,avx512bw,avx512vl")]
+ #[simd_test(enable = "gfni,avx512bw,avx512vl")]
unsafe fn test_mm_maskz_gf2p8mul_epi8() {
let (left, right, _expected) = generate_byte_mul_test_data();
@@ -979,7 +979,7 @@ mod tests {
}
}
- #[simd_test(enable = "avx512gfni,avx512bw,avx512vl")]
+ #[simd_test(enable = "gfni,avx512bw,avx512vl")]
unsafe fn test_mm_mask_gf2p8mul_epi8() {
let (left, right, _expected) = generate_byte_mul_test_data();
@@ -997,7 +997,7 @@ mod tests {
}
}
- #[simd_test(enable = "avx512gfni,avx512bw")]
+ #[simd_test(enable = "gfni,avx512bw")]
unsafe fn test_mm512_gf2p8affine_epi64_epi8() {
let identity: i64 = 0x01_02_04_08_10_20_40_80;
const IDENTITY_BYTE: i32 = 0;
@@ -1031,7 +1031,7 @@ mod tests {
}
}
- #[simd_test(enable = "avx512gfni,avx512bw")]
+ #[simd_test(enable = "gfni,avx512bw")]
unsafe fn test_mm512_maskz_gf2p8affine_epi64_epi8() {
const CONSTANT_BYTE: i32 = 0x63;
let (matrices, vectors, _expected) = generate_affine_mul_test_data(CONSTANT_BYTE as u8);
@@ -1053,7 +1053,7 @@ mod tests {
}
}
- #[simd_test(enable = "avx512gfni,avx512bw")]
+ #[simd_test(enable = "gfni,avx512bw")]
unsafe fn test_mm512_mask_gf2p8affine_epi64_epi8() {
const CONSTANT_BYTE: i32 = 0x63;
let (matrices, vectors, _expected) = generate_affine_mul_test_data(CONSTANT_BYTE as u8);
@@ -1074,7 +1074,7 @@ mod tests {
}
}
- #[simd_test(enable = "avx512gfni,avx512bw,avx512vl")]
+ #[simd_test(enable = "gfni,avx512bw,avx512vl")]
unsafe fn test_mm256_gf2p8affine_epi64_epi8() {
let identity: i64 = 0x01_02_04_08_10_20_40_80;
const IDENTITY_BYTE: i32 = 0;
@@ -1108,7 +1108,7 @@ mod tests {
}
}
- #[simd_test(enable = "avx512gfni,avx512bw,avx512vl")]
+ #[simd_test(enable = "gfni,avx512bw,avx512vl")]
unsafe fn test_mm256_maskz_gf2p8affine_epi64_epi8() {
const CONSTANT_BYTE: i32 = 0x63;
let (matrices, vectors, _expected) = generate_affine_mul_test_data(CONSTANT_BYTE as u8);
@@ -1130,7 +1130,7 @@ mod tests {
}
}
- #[simd_test(enable = "avx512gfni,avx512bw,avx512vl")]
+ #[simd_test(enable = "gfni,avx512bw,avx512vl")]
unsafe fn test_mm256_mask_gf2p8affine_epi64_epi8() {
const CONSTANT_BYTE: i32 = 0x63;
let (matrices, vectors, _expected) = generate_affine_mul_test_data(CONSTANT_BYTE as u8);
@@ -1151,7 +1151,7 @@ mod tests {
}
}
- #[simd_test(enable = "avx512gfni,avx512bw,avx512vl")]
+ #[simd_test(enable = "gfni,avx512bw,avx512vl")]
unsafe fn test_mm_gf2p8affine_epi64_epi8() {
let identity: i64 = 0x01_02_04_08_10_20_40_80;
const IDENTITY_BYTE: i32 = 0;
@@ -1185,7 +1185,7 @@ mod tests {
}
}
- #[simd_test(enable = "avx512gfni,avx512bw,avx512vl")]
+ #[simd_test(enable = "gfni,avx512bw,avx512vl")]
unsafe fn test_mm_maskz_gf2p8affine_epi64_epi8() {
const CONSTANT_BYTE: i32 = 0x63;
let (matrices, vectors, _expected) = generate_affine_mul_test_data(CONSTANT_BYTE as u8);
@@ -1206,7 +1206,7 @@ mod tests {
}
}
- #[simd_test(enable = "avx512gfni,avx512bw,avx512vl")]
+ #[simd_test(enable = "gfni,avx512bw,avx512vl")]
unsafe fn test_mm_mask_gf2p8affine_epi64_epi8() {
const CONSTANT_BYTE: i32 = 0x63;
let (matrices, vectors, _expected) = generate_affine_mul_test_data(CONSTANT_BYTE as u8);
@@ -1227,7 +1227,7 @@ mod tests {
}
}
- #[simd_test(enable = "avx512gfni,avx512bw")]
+ #[simd_test(enable = "gfni,avx512bw")]
unsafe fn test_mm512_gf2p8affineinv_epi64_epi8() {
let identity: i64 = 0x01_02_04_08_10_20_40_80;
const IDENTITY_BYTE: i32 = 0;
@@ -1271,7 +1271,7 @@ mod tests {
}
}
- #[simd_test(enable = "avx512gfni,avx512bw")]
+ #[simd_test(enable = "gfni,avx512bw")]
unsafe fn test_mm512_maskz_gf2p8affineinv_epi64_epi8() {
const CONSTANT_BYTE: i32 = 0x63;
let (matrices, vectors, _expected) = generate_affine_mul_test_data(CONSTANT_BYTE as u8);
@@ -1293,7 +1293,7 @@ mod tests {
}
}
- #[simd_test(enable = "avx512gfni,avx512bw")]
+ #[simd_test(enable = "gfni,avx512bw")]
unsafe fn test_mm512_mask_gf2p8affineinv_epi64_epi8() {
const CONSTANT_BYTE: i32 = 0x63;
let (matrices, vectors, _expected) = generate_affine_mul_test_data(CONSTANT_BYTE as u8);
@@ -1315,7 +1315,7 @@ mod tests {
}
}
- #[simd_test(enable = "avx512gfni,avx512bw,avx512vl")]
+ #[simd_test(enable = "gfni,avx512bw,avx512vl")]
unsafe fn test_mm256_gf2p8affineinv_epi64_epi8() {
let identity: i64 = 0x01_02_04_08_10_20_40_80;
const IDENTITY_BYTE: i32 = 0;
@@ -1359,7 +1359,7 @@ mod tests {
}
}
- #[simd_test(enable = "avx512gfni,avx512bw,avx512vl")]
+ #[simd_test(enable = "gfni,avx512bw,avx512vl")]
unsafe fn test_mm256_maskz_gf2p8affineinv_epi64_epi8() {
const CONSTANT_BYTE: i32 = 0x63;
let (matrices, vectors, _expected) = generate_affine_mul_test_data(CONSTANT_BYTE as u8);
@@ -1381,7 +1381,7 @@ mod tests {
}
}
- #[simd_test(enable = "avx512gfni,avx512bw,avx512vl")]
+ #[simd_test(enable = "gfni,avx512bw,avx512vl")]
unsafe fn test_mm256_mask_gf2p8affineinv_epi64_epi8() {
const CONSTANT_BYTE: i32 = 0x63;
let (matrices, vectors, _expected) = generate_affine_mul_test_data(CONSTANT_BYTE as u8);
@@ -1403,7 +1403,7 @@ mod tests {
}
}
- #[simd_test(enable = "avx512gfni,avx512bw,avx512vl")]
+ #[simd_test(enable = "gfni,avx512bw,avx512vl")]
unsafe fn test_mm_gf2p8affineinv_epi64_epi8() {
let identity: i64 = 0x01_02_04_08_10_20_40_80;
const IDENTITY_BYTE: i32 = 0;
@@ -1447,7 +1447,7 @@ mod tests {
}
}
- #[simd_test(enable = "avx512gfni,avx512bw,avx512vl")]
+ #[simd_test(enable = "gfni,avx512bw,avx512vl")]
unsafe fn test_mm_maskz_gf2p8affineinv_epi64_epi8() {
const CONSTANT_BYTE: i32 = 0x63;
let (matrices, vectors, _expected) = generate_affine_mul_test_data(CONSTANT_BYTE as u8);
@@ -1469,7 +1469,7 @@ mod tests {
}
}
- #[simd_test(enable = "avx512gfni,avx512bw,avx512vl")]
+ #[simd_test(enable = "gfni,avx512bw,avx512vl")]
unsafe fn test_mm_mask_gf2p8affineinv_epi64_epi8() {
const CONSTANT_BYTE: i32 = 0x63;
let (matrices, vectors, _expected) = generate_affine_mul_test_data(CONSTANT_BYTE as u8);
diff --git a/library/stdarch/crates/core_arch/src/x86/mod.rs b/library/stdarch/crates/core_arch/src/x86/mod.rs
index 6b50e95b2..37045e40e 100644
--- a/library/stdarch/crates/core_arch/src/x86/mod.rs
+++ b/library/stdarch/crates/core_arch/src/x86/mod.rs
@@ -835,17 +835,17 @@ pub use self::avx512vnni::*;
mod avx512bitalg;
pub use self::avx512bitalg::*;
-mod avx512gfni;
-pub use self::avx512gfni::*;
+mod gfni;
+pub use self::gfni::*;
mod avx512vpopcntdq;
pub use self::avx512vpopcntdq::*;
-mod avx512vaes;
-pub use self::avx512vaes::*;
+mod vaes;
+pub use self::vaes::*;
-mod avx512vpclmulqdq;
-pub use self::avx512vpclmulqdq::*;
+mod vpclmulqdq;
+pub use self::vpclmulqdq::*;
mod bt;
pub use self::bt::*;
diff --git a/library/stdarch/crates/core_arch/src/x86/sse.rs b/library/stdarch/crates/core_arch/src/x86/sse.rs
index 03c3a14a5..f21288970 100644
--- a/library/stdarch/crates/core_arch/src/x86/sse.rs
+++ b/library/stdarch/crates/core_arch/src/x86/sse.rs
@@ -1080,10 +1080,7 @@ pub unsafe fn _mm_movelh_ps(a: __m128, b: __m128) -> __m128 {
/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_movemask_ps)
#[inline]
#[target_feature(enable = "sse")]
-// FIXME: LLVM9 trunk has the following bug:
-// https://github.com/rust-lang/stdarch/issues/794
-// so we only temporarily test this on i686 and x86_64 but not on i586:
-#[cfg_attr(all(test, target_feature = "sse2"), assert_instr(movmskps))]
+#[cfg_attr(test, assert_instr(movmskps))]
#[stable(feature = "simd_x86", since = "1.27.0")]
pub unsafe fn _mm_movemask_ps(a: __m128) -> i32 {
movmskps(a)
diff --git a/library/stdarch/crates/core_arch/src/x86/sse2.rs b/library/stdarch/crates/core_arch/src/x86/sse2.rs
index 3e79b3539..cde4bc316 100644
--- a/library/stdarch/crates/core_arch/src/x86/sse2.rs
+++ b/library/stdarch/crates/core_arch/src/x86/sse2.rs
@@ -203,7 +203,9 @@ pub unsafe fn _mm_madd_epi16(a: __m128i, b: __m128i) -> __m128i {
#[cfg_attr(test, assert_instr(pmaxsw))]
#[stable(feature = "simd_x86", since = "1.27.0")]
pub unsafe fn _mm_max_epi16(a: __m128i, b: __m128i) -> __m128i {
- transmute(pmaxsw(a.as_i16x8(), b.as_i16x8()))
+ let a = a.as_i16x8();
+ let b = b.as_i16x8();
+ transmute(simd_select::<i16x8, _>(simd_gt(a, b), a, b))
}
/// Compares packed unsigned 8-bit integers in `a` and `b`, and returns the
@@ -215,7 +217,9 @@ pub unsafe fn _mm_max_epi16(a: __m128i, b: __m128i) -> __m128i {
#[cfg_attr(test, assert_instr(pmaxub))]
#[stable(feature = "simd_x86", since = "1.27.0")]
pub unsafe fn _mm_max_epu8(a: __m128i, b: __m128i) -> __m128i {
- transmute(pmaxub(a.as_u8x16(), b.as_u8x16()))
+ let a = a.as_u8x16();
+ let b = b.as_u8x16();
+ transmute(simd_select::<i8x16, _>(simd_gt(a, b), a, b))
}
/// Compares packed 16-bit integers in `a` and `b`, and returns the packed
@@ -227,7 +231,9 @@ pub unsafe fn _mm_max_epu8(a: __m128i, b: __m128i) -> __m128i {
#[cfg_attr(test, assert_instr(pminsw))]
#[stable(feature = "simd_x86", since = "1.27.0")]
pub unsafe fn _mm_min_epi16(a: __m128i, b: __m128i) -> __m128i {
- transmute(pminsw(a.as_i16x8(), b.as_i16x8()))
+ let a = a.as_i16x8();
+ let b = b.as_i16x8();
+ transmute(simd_select::<i16x8, _>(simd_lt(a, b), a, b))
}
/// Compares packed unsigned 8-bit integers in `a` and `b`, and returns the
@@ -239,7 +245,9 @@ pub unsafe fn _mm_min_epi16(a: __m128i, b: __m128i) -> __m128i {
#[cfg_attr(test, assert_instr(pminub))]
#[stable(feature = "simd_x86", since = "1.27.0")]
pub unsafe fn _mm_min_epu8(a: __m128i, b: __m128i) -> __m128i {
- transmute(pminub(a.as_u8x16(), b.as_u8x16()))
+ let a = a.as_u8x16();
+ let b = b.as_u8x16();
+ transmute(simd_select::<i8x16, _>(simd_lt(a, b), a, b))
}
/// Multiplies the packed 16-bit integers in `a` and `b`.
@@ -1378,7 +1386,9 @@ pub unsafe fn _mm_insert_epi16<const IMM8: i32>(a: __m128i, i: i32) -> __m128i {
#[cfg_attr(test, assert_instr(pmovmskb))]
#[stable(feature = "simd_x86", since = "1.27.0")]
pub unsafe fn _mm_movemask_epi8(a: __m128i) -> i32 {
- simd_bitmask::<_, u16>(a.as_i8x16()) as u32 as i32
+ let z = i8x16::splat(0);
+ let m: i8x16 = simd_lt(a.as_i8x16(), z);
+ simd_bitmask::<_, u16>(m) as u32 as i32
}
/// Shuffles 32-bit integers in `a` using the control in `IMM8`.
@@ -1409,7 +1419,7 @@ pub unsafe fn _mm_shuffle_epi32<const IMM8: i32>(a: __m128i) -> __m128i {
/// `IMM8`.
///
/// Put the results in the high 64 bits of the returned vector, with the low 64
-/// bits being copied from from `a`.
+/// bits being copied from `a`.
///
/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_shufflehi_epi16)
#[inline]
@@ -1441,7 +1451,7 @@ pub unsafe fn _mm_shufflehi_epi16<const IMM8: i32>(a: __m128i) -> __m128i {
/// `IMM8`.
///
/// Put the results in the low 64 bits of the returned vector, with the high 64
-/// bits being copied from from `a`.
+/// bits being copied from `a`.
///
/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_shufflelo_epi16)
#[inline]
@@ -2796,14 +2806,6 @@ extern "C" {
fn pavgw(a: u16x8, b: u16x8) -> u16x8;
#[link_name = "llvm.x86.sse2.pmadd.wd"]
fn pmaddwd(a: i16x8, b: i16x8) -> i32x4;
- #[link_name = "llvm.x86.sse2.pmaxs.w"]
- fn pmaxsw(a: i16x8, b: i16x8) -> i16x8;
- #[link_name = "llvm.x86.sse2.pmaxu.b"]
- fn pmaxub(a: u8x16, b: u8x16) -> u8x16;
- #[link_name = "llvm.x86.sse2.pmins.w"]
- fn pminsw(a: i16x8, b: i16x8) -> i16x8;
- #[link_name = "llvm.x86.sse2.pminu.b"]
- fn pminub(a: u8x16, b: u8x16) -> u8x16;
#[link_name = "llvm.x86.sse2.pmulh.w"]
fn pmulhw(a: i16x8, b: i16x8) -> i16x8;
#[link_name = "llvm.x86.sse2.pmulhu.w"]
diff --git a/library/stdarch/crates/core_arch/src/x86/sse41.rs b/library/stdarch/crates/core_arch/src/x86/sse41.rs
index 7c59f2702..3162ad7d9 100644
--- a/library/stdarch/crates/core_arch/src/x86/sse41.rs
+++ b/library/stdarch/crates/core_arch/src/x86/sse41.rs
@@ -281,7 +281,9 @@ pub unsafe fn _mm_insert_epi32<const IMM8: i32>(a: __m128i, i: i32) -> __m128i {
#[cfg_attr(test, assert_instr(pmaxsb))]
#[stable(feature = "simd_x86", since = "1.27.0")]
pub unsafe fn _mm_max_epi8(a: __m128i, b: __m128i) -> __m128i {
- transmute(pmaxsb(a.as_i8x16(), b.as_i8x16()))
+ let a = a.as_i8x16();
+ let b = b.as_i8x16();
+ transmute(simd_select::<i8x16, _>(simd_gt(a, b), a, b))
}
/// Compares packed unsigned 16-bit integers in `a` and `b`, and returns packed
@@ -293,7 +295,9 @@ pub unsafe fn _mm_max_epi8(a: __m128i, b: __m128i) -> __m128i {
#[cfg_attr(test, assert_instr(pmaxuw))]
#[stable(feature = "simd_x86", since = "1.27.0")]
pub unsafe fn _mm_max_epu16(a: __m128i, b: __m128i) -> __m128i {
- transmute(pmaxuw(a.as_u16x8(), b.as_u16x8()))
+ let a = a.as_u16x8();
+ let b = b.as_u16x8();
+ transmute(simd_select::<i16x8, _>(simd_gt(a, b), a, b))
}
/// Compares packed 32-bit integers in `a` and `b`, and returns packed maximum
@@ -305,7 +309,9 @@ pub unsafe fn _mm_max_epu16(a: __m128i, b: __m128i) -> __m128i {
#[cfg_attr(test, assert_instr(pmaxsd))]
#[stable(feature = "simd_x86", since = "1.27.0")]
pub unsafe fn _mm_max_epi32(a: __m128i, b: __m128i) -> __m128i {
- transmute(pmaxsd(a.as_i32x4(), b.as_i32x4()))
+ let a = a.as_i32x4();
+ let b = b.as_i32x4();
+ transmute(simd_select::<i32x4, _>(simd_gt(a, b), a, b))
}
/// Compares packed unsigned 32-bit integers in `a` and `b`, and returns packed
@@ -317,7 +323,9 @@ pub unsafe fn _mm_max_epi32(a: __m128i, b: __m128i) -> __m128i {
#[cfg_attr(test, assert_instr(pmaxud))]
#[stable(feature = "simd_x86", since = "1.27.0")]
pub unsafe fn _mm_max_epu32(a: __m128i, b: __m128i) -> __m128i {
- transmute(pmaxud(a.as_u32x4(), b.as_u32x4()))
+ let a = a.as_u32x4();
+ let b = b.as_u32x4();
+ transmute(simd_select::<i32x4, _>(simd_gt(a, b), a, b))
}
/// Compares packed 8-bit integers in `a` and `b` and returns packed minimum
@@ -329,7 +337,9 @@ pub unsafe fn _mm_max_epu32(a: __m128i, b: __m128i) -> __m128i {
#[cfg_attr(test, assert_instr(pminsb))]
#[stable(feature = "simd_x86", since = "1.27.0")]
pub unsafe fn _mm_min_epi8(a: __m128i, b: __m128i) -> __m128i {
- transmute(pminsb(a.as_i8x16(), b.as_i8x16()))
+ let a = a.as_i8x16();
+ let b = b.as_i8x16();
+ transmute(simd_select::<i8x16, _>(simd_lt(a, b), a, b))
}
/// Compares packed unsigned 16-bit integers in `a` and `b`, and returns packed
@@ -341,7 +351,9 @@ pub unsafe fn _mm_min_epi8(a: __m128i, b: __m128i) -> __m128i {
#[cfg_attr(test, assert_instr(pminuw))]
#[stable(feature = "simd_x86", since = "1.27.0")]
pub unsafe fn _mm_min_epu16(a: __m128i, b: __m128i) -> __m128i {
- transmute(pminuw(a.as_u16x8(), b.as_u16x8()))
+ let a = a.as_u16x8();
+ let b = b.as_u16x8();
+ transmute(simd_select::<i16x8, _>(simd_lt(a, b), a, b))
}
/// Compares packed 32-bit integers in `a` and `b`, and returns packed minimum
@@ -353,7 +365,9 @@ pub unsafe fn _mm_min_epu16(a: __m128i, b: __m128i) -> __m128i {
#[cfg_attr(test, assert_instr(pminsd))]
#[stable(feature = "simd_x86", since = "1.27.0")]
pub unsafe fn _mm_min_epi32(a: __m128i, b: __m128i) -> __m128i {
- transmute(pminsd(a.as_i32x4(), b.as_i32x4()))
+ let a = a.as_i32x4();
+ let b = b.as_i32x4();
+ transmute(simd_select::<i32x4, _>(simd_lt(a, b), a, b))
}
/// Compares packed unsigned 32-bit integers in `a` and `b`, and returns packed
@@ -365,7 +379,9 @@ pub unsafe fn _mm_min_epi32(a: __m128i, b: __m128i) -> __m128i {
#[cfg_attr(test, assert_instr(pminud))]
#[stable(feature = "simd_x86", since = "1.27.0")]
pub unsafe fn _mm_min_epu32(a: __m128i, b: __m128i) -> __m128i {
- transmute(pminud(a.as_u32x4(), b.as_u32x4()))
+ let a = a.as_u32x4();
+ let b = b.as_u32x4();
+ transmute(simd_select::<i32x4, _>(simd_lt(a, b), a, b))
}
/// Converts packed 32-bit integers from `a` and `b` to packed 16-bit integers
@@ -1122,22 +1138,6 @@ extern "C" {
fn pblendw(a: i16x8, b: i16x8, imm8: u8) -> i16x8;
#[link_name = "llvm.x86.sse41.insertps"]
fn insertps(a: __m128, b: __m128, imm8: u8) -> __m128;
- #[link_name = "llvm.x86.sse41.pmaxsb"]
- fn pmaxsb(a: i8x16, b: i8x16) -> i8x16;
- #[link_name = "llvm.x86.sse41.pmaxuw"]
- fn pmaxuw(a: u16x8, b: u16x8) -> u16x8;
- #[link_name = "llvm.x86.sse41.pmaxsd"]
- fn pmaxsd(a: i32x4, b: i32x4) -> i32x4;
- #[link_name = "llvm.x86.sse41.pmaxud"]
- fn pmaxud(a: u32x4, b: u32x4) -> u32x4;
- #[link_name = "llvm.x86.sse41.pminsb"]
- fn pminsb(a: i8x16, b: i8x16) -> i8x16;
- #[link_name = "llvm.x86.sse41.pminuw"]
- fn pminuw(a: u16x8, b: u16x8) -> u16x8;
- #[link_name = "llvm.x86.sse41.pminsd"]
- fn pminsd(a: i32x4, b: i32x4) -> i32x4;
- #[link_name = "llvm.x86.sse41.pminud"]
- fn pminud(a: u32x4, b: u32x4) -> u32x4;
#[link_name = "llvm.x86.sse41.packusdw"]
fn packusdw(a: i32x4, b: i32x4) -> u16x8;
#[link_name = "llvm.x86.sse41.dppd"]
diff --git a/library/stdarch/crates/core_arch/src/x86/sse42.rs b/library/stdarch/crates/core_arch/src/x86/sse42.rs
index f474b0671..4eb12480b 100644
--- a/library/stdarch/crates/core_arch/src/x86/sse42.rs
+++ b/library/stdarch/crates/core_arch/src/x86/sse42.rs
@@ -614,7 +614,7 @@ mod tests {
use crate::core_arch::x86::*;
use std::ptr;
- // Currently one cannot `load` a &[u8] that is is less than 16
+ // Currently one cannot `load` a &[u8] that is less than 16
// in length. This makes loading strings less than 16 in length
// a bit difficult. Rather than `load` and mutate the __m128i,
// it is easier to memcpy the given string to a local slice with
@@ -623,11 +623,7 @@ mod tests {
unsafe fn str_to_m128i(s: &[u8]) -> __m128i {
assert!(s.len() <= 16);
let slice = &mut [0u8; 16];
- ptr::copy_nonoverlapping(
- s.get_unchecked(0) as *const u8 as *const u8,
- slice.get_unchecked_mut(0) as *mut u8 as *mut u8,
- s.len(),
- );
+ ptr::copy_nonoverlapping(s.as_ptr(), slice.as_mut_ptr(), s.len());
_mm_loadu_si128(slice.as_ptr() as *const _)
}
diff --git a/library/stdarch/crates/core_arch/src/x86/avx512vaes.rs b/library/stdarch/crates/core_arch/src/x86/vaes.rs
index 676de312b..e09f8a113 100644
--- a/library/stdarch/crates/core_arch/src/x86/avx512vaes.rs
+++ b/library/stdarch/crates/core_arch/src/x86/vaes.rs
@@ -38,7 +38,7 @@ extern "C" {
///
/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_aesenc_epi128)
#[inline]
-#[target_feature(enable = "avx512vaes,avx512vl")]
+#[target_feature(enable = "vaes")]
#[cfg_attr(test, assert_instr(vaesenc))]
pub unsafe fn _mm256_aesenc_epi128(a: __m256i, round_key: __m256i) -> __m256i {
aesenc_256(a, round_key)
@@ -49,7 +49,7 @@ pub unsafe fn _mm256_aesenc_epi128(a: __m256i, round_key: __m256i) -> __m256i {
///
/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_aesenclast_epi128)
#[inline]
-#[target_feature(enable = "avx512vaes,avx512vl")]
+#[target_feature(enable = "vaes")]
#[cfg_attr(test, assert_instr(vaesenclast))]
pub unsafe fn _mm256_aesenclast_epi128(a: __m256i, round_key: __m256i) -> __m256i {
aesenclast_256(a, round_key)
@@ -60,7 +60,7 @@ pub unsafe fn _mm256_aesenclast_epi128(a: __m256i, round_key: __m256i) -> __m256
///
/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_aesdec_epi128)
#[inline]
-#[target_feature(enable = "avx512vaes,avx512vl")]
+#[target_feature(enable = "vaes")]
#[cfg_attr(test, assert_instr(vaesdec))]
pub unsafe fn _mm256_aesdec_epi128(a: __m256i, round_key: __m256i) -> __m256i {
aesdec_256(a, round_key)
@@ -71,7 +71,7 @@ pub unsafe fn _mm256_aesdec_epi128(a: __m256i, round_key: __m256i) -> __m256i {
///
/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_aesdeclast_epi128)
#[inline]
-#[target_feature(enable = "avx512vaes,avx512vl")]
+#[target_feature(enable = "vaes")]
#[cfg_attr(test, assert_instr(vaesdeclast))]
pub unsafe fn _mm256_aesdeclast_epi128(a: __m256i, round_key: __m256i) -> __m256i {
aesdeclast_256(a, round_key)
@@ -82,7 +82,7 @@ pub unsafe fn _mm256_aesdeclast_epi128(a: __m256i, round_key: __m256i) -> __m256
///
/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_aesenc_epi128)
#[inline]
-#[target_feature(enable = "avx512vaes,avx512f")]
+#[target_feature(enable = "vaes,avx512f")]
#[cfg_attr(test, assert_instr(vaesenc))]
pub unsafe fn _mm512_aesenc_epi128(a: __m512i, round_key: __m512i) -> __m512i {
aesenc_512(a, round_key)
@@ -93,7 +93,7 @@ pub unsafe fn _mm512_aesenc_epi128(a: __m512i, round_key: __m512i) -> __m512i {
///
/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_aesenclast_epi128)
#[inline]
-#[target_feature(enable = "avx512vaes,avx512f")]
+#[target_feature(enable = "vaes,avx512f")]
#[cfg_attr(test, assert_instr(vaesenclast))]
pub unsafe fn _mm512_aesenclast_epi128(a: __m512i, round_key: __m512i) -> __m512i {
aesenclast_512(a, round_key)
@@ -104,7 +104,7 @@ pub unsafe fn _mm512_aesenclast_epi128(a: __m512i, round_key: __m512i) -> __m512
///
/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_aesdec_epi128)
#[inline]
-#[target_feature(enable = "avx512vaes,avx512f")]
+#[target_feature(enable = "vaes,avx512f")]
#[cfg_attr(test, assert_instr(vaesdec))]
pub unsafe fn _mm512_aesdec_epi128(a: __m512i, round_key: __m512i) -> __m512i {
aesdec_512(a, round_key)
@@ -115,7 +115,7 @@ pub unsafe fn _mm512_aesdec_epi128(a: __m512i, round_key: __m512i) -> __m512i {
///
/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_aesdeclast_epi128)
#[inline]
-#[target_feature(enable = "avx512vaes,avx512f")]
+#[target_feature(enable = "vaes,avx512f")]
#[cfg_attr(test, assert_instr(vaesdeclast))]
pub unsafe fn _mm512_aesdeclast_epi128(a: __m512i, round_key: __m512i) -> __m512i {
aesdeclast_512(a, round_key)
@@ -138,7 +138,7 @@ mod tests {
// ideally we'd be using quickcheck here instead
#[target_feature(enable = "avx2")]
- unsafe fn helper_for_256_avx512vaes(
+ unsafe fn helper_for_256_vaes(
linear: unsafe fn(__m128i, __m128i) -> __m128i,
vectorized: unsafe fn(__m256i, __m256i) -> __m256i,
) {
@@ -187,7 +187,7 @@ mod tests {
setup_state_key(_mm512_broadcast_i32x4)
}
- #[simd_test(enable = "avx512vaes,avx512vl")]
+ #[simd_test(enable = "vaes,avx512vl")]
unsafe fn test_mm256_aesdec_epi128() {
// Constants taken from https://msdn.microsoft.com/en-us/library/cc664949.aspx.
let (a, k) = setup_state_key_256();
@@ -196,10 +196,10 @@ mod tests {
let r = _mm256_aesdec_epi128(a, k);
assert_eq_m256i(r, e);
- helper_for_256_avx512vaes(_mm_aesdec_si128, _mm256_aesdec_epi128);
+ helper_for_256_vaes(_mm_aesdec_si128, _mm256_aesdec_epi128);
}
- #[simd_test(enable = "avx512vaes,avx512vl")]
+ #[simd_test(enable = "vaes,avx512vl")]
unsafe fn test_mm256_aesdeclast_epi128() {
// Constants taken from https://msdn.microsoft.com/en-us/library/cc714178.aspx.
let (a, k) = setup_state_key_256();
@@ -208,10 +208,10 @@ mod tests {
let r = _mm256_aesdeclast_epi128(a, k);
assert_eq_m256i(r, e);
- helper_for_256_avx512vaes(_mm_aesdeclast_si128, _mm256_aesdeclast_epi128);
+ helper_for_256_vaes(_mm_aesdeclast_si128, _mm256_aesdeclast_epi128);
}
- #[simd_test(enable = "avx512vaes,avx512vl")]
+ #[simd_test(enable = "vaes,avx512vl")]
unsafe fn test_mm256_aesenc_epi128() {
// Constants taken from https://msdn.microsoft.com/en-us/library/cc664810.aspx.
// they are repeated appropriately
@@ -221,10 +221,10 @@ mod tests {
let r = _mm256_aesenc_epi128(a, k);
assert_eq_m256i(r, e);
- helper_for_256_avx512vaes(_mm_aesenc_si128, _mm256_aesenc_epi128);
+ helper_for_256_vaes(_mm_aesenc_si128, _mm256_aesenc_epi128);
}
- #[simd_test(enable = "avx512vaes,avx512vl")]
+ #[simd_test(enable = "vaes,avx512vl")]
unsafe fn test_mm256_aesenclast_epi128() {
// Constants taken from https://msdn.microsoft.com/en-us/library/cc714136.aspx.
let (a, k) = setup_state_key_256();
@@ -233,11 +233,11 @@ mod tests {
let r = _mm256_aesenclast_epi128(a, k);
assert_eq_m256i(r, e);
- helper_for_256_avx512vaes(_mm_aesenclast_si128, _mm256_aesenclast_epi128);
+ helper_for_256_vaes(_mm_aesenclast_si128, _mm256_aesenclast_epi128);
}
#[target_feature(enable = "avx512f")]
- unsafe fn helper_for_512_avx512vaes(
+ unsafe fn helper_for_512_vaes(
linear: unsafe fn(__m128i, __m128i) -> __m128i,
vectorized: unsafe fn(__m512i, __m512i) -> __m512i,
) {
@@ -282,7 +282,7 @@ mod tests {
assert_eq_m128i(_mm512_extracti32x4_epi32::<3>(r), e_decomp[3]);
}
- #[simd_test(enable = "avx512vaes,avx512f")]
+ #[simd_test(enable = "vaes,avx512f")]
unsafe fn test_mm512_aesdec_epi128() {
// Constants taken from https://msdn.microsoft.com/en-us/library/cc664949.aspx.
let (a, k) = setup_state_key_512();
@@ -291,10 +291,10 @@ mod tests {
let r = _mm512_aesdec_epi128(a, k);
assert_eq_m512i(r, e);
- helper_for_512_avx512vaes(_mm_aesdec_si128, _mm512_aesdec_epi128);
+ helper_for_512_vaes(_mm_aesdec_si128, _mm512_aesdec_epi128);
}
- #[simd_test(enable = "avx512vaes,avx512f")]
+ #[simd_test(enable = "vaes,avx512f")]
unsafe fn test_mm512_aesdeclast_epi128() {
// Constants taken from https://msdn.microsoft.com/en-us/library/cc714178.aspx.
let (a, k) = setup_state_key_512();
@@ -303,10 +303,10 @@ mod tests {
let r = _mm512_aesdeclast_epi128(a, k);
assert_eq_m512i(r, e);
- helper_for_512_avx512vaes(_mm_aesdeclast_si128, _mm512_aesdeclast_epi128);
+ helper_for_512_vaes(_mm_aesdeclast_si128, _mm512_aesdeclast_epi128);
}
- #[simd_test(enable = "avx512vaes,avx512f")]
+ #[simd_test(enable = "vaes,avx512f")]
unsafe fn test_mm512_aesenc_epi128() {
// Constants taken from https://msdn.microsoft.com/en-us/library/cc664810.aspx.
let (a, k) = setup_state_key_512();
@@ -315,10 +315,10 @@ mod tests {
let r = _mm512_aesenc_epi128(a, k);
assert_eq_m512i(r, e);
- helper_for_512_avx512vaes(_mm_aesenc_si128, _mm512_aesenc_epi128);
+ helper_for_512_vaes(_mm_aesenc_si128, _mm512_aesenc_epi128);
}
- #[simd_test(enable = "avx512vaes,avx512f")]
+ #[simd_test(enable = "vaes,avx512f")]
unsafe fn test_mm512_aesenclast_epi128() {
// Constants taken from https://msdn.microsoft.com/en-us/library/cc714136.aspx.
let (a, k) = setup_state_key_512();
@@ -327,6 +327,6 @@ mod tests {
let r = _mm512_aesenclast_epi128(a, k);
assert_eq_m512i(r, e);
- helper_for_512_avx512vaes(_mm_aesenclast_si128, _mm512_aesenclast_epi128);
+ helper_for_512_vaes(_mm_aesenclast_si128, _mm512_aesenclast_epi128);
}
}
diff --git a/library/stdarch/crates/core_arch/src/x86/avx512vpclmulqdq.rs b/library/stdarch/crates/core_arch/src/x86/vpclmulqdq.rs
index 9bfeb903a..ea76708b8 100644
--- a/library/stdarch/crates/core_arch/src/x86/avx512vpclmulqdq.rs
+++ b/library/stdarch/crates/core_arch/src/x86/vpclmulqdq.rs
@@ -32,7 +32,7 @@ extern "C" {
///
/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_clmulepi64_epi128)
#[inline]
-#[target_feature(enable = "avx512vpclmulqdq,avx512f")]
+#[target_feature(enable = "vpclmulqdq,avx512f")]
// technically according to Intel's documentation we don't need avx512f here, however LLVM gets confused otherwise
#[cfg_attr(test, assert_instr(vpclmul, IMM8 = 0))]
#[rustc_legacy_const_generics(2)]
@@ -50,7 +50,7 @@ pub unsafe fn _mm512_clmulepi64_epi128<const IMM8: i32>(a: __m512i, b: __m512i)
///
/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_clmulepi64_epi128)
#[inline]
-#[target_feature(enable = "avx512vpclmulqdq,avx512vl")]
+#[target_feature(enable = "vpclmulqdq")]
#[cfg_attr(test, assert_instr(vpclmul, IMM8 = 0))]
#[rustc_legacy_const_generics(2)]
pub unsafe fn _mm256_clmulepi64_epi128<const IMM8: i32>(a: __m256i, b: __m256i) -> __m256i {
@@ -121,7 +121,7 @@ mod tests {
// this function tests one of the possible 4 instances
// with different inputs across lanes
- #[target_feature(enable = "avx512vpclmulqdq,avx512f")]
+ #[target_feature(enable = "vpclmulqdq,avx512f")]
unsafe fn verify_512_helper(
linear: unsafe fn(__m128i, __m128i) -> __m128i,
vectorized: unsafe fn(__m512i, __m512i) -> __m512i,
@@ -162,7 +162,7 @@ mod tests {
// this function tests one of the possible 4 instances
// with different inputs across lanes for the VL version
- #[target_feature(enable = "avx512vpclmulqdq,avx512vl")]
+ #[target_feature(enable = "vpclmulqdq,avx512vl")]
unsafe fn verify_256_helper(
linear: unsafe fn(__m128i, __m128i) -> __m128i,
vectorized: unsafe fn(__m256i, __m256i) -> __m256i,
@@ -204,7 +204,7 @@ mod tests {
unroll! {assert_eq_m128i(_mm256_extracti128_si256::<2>(r),e_decomp[2]);}
}
- #[simd_test(enable = "avx512vpclmulqdq,avx512f")]
+ #[simd_test(enable = "vpclmulqdq,avx512f")]
unsafe fn test_mm512_clmulepi64_epi128() {
verify_kat_pclmul!(
_mm512_broadcast_i32x4,
@@ -230,7 +230,7 @@ mod tests {
);
}
- #[simd_test(enable = "avx512vpclmulqdq,avx512vl")]
+ #[simd_test(enable = "vpclmulqdq,avx512vl")]
unsafe fn test_mm256_clmulepi64_epi128() {
verify_kat_pclmul!(
_mm256_broadcastsi128_si256,
diff --git a/library/stdarch/crates/core_arch/tests/cpu-detection.rs b/library/stdarch/crates/core_arch/tests/cpu-detection.rs
index 61f5f0905..08caca738 100644
--- a/library/stdarch/crates/core_arch/tests/cpu-detection.rs
+++ b/library/stdarch/crates/core_arch/tests/cpu-detection.rs
@@ -31,12 +31,9 @@ fn x86_all() {
is_x86_feature_detected!("avx512vpopcntdq")
);
println!("avx512vbmi2 {:?}", is_x86_feature_detected!("avx512vbmi2"));
- println!("avx512gfni {:?}", is_x86_feature_detected!("avx512gfni"));
- println!("avx512vaes {:?}", is_x86_feature_detected!("avx512vaes"));
- println!(
- "avx512vpclmulqdq {:?}",
- is_x86_feature_detected!("avx512vpclmulqdq")
- );
+ println!("gfni {:?}", is_x86_feature_detected!("gfni"));
+ println!("vaes {:?}", is_x86_feature_detected!("vaes"));
+ println!("vpclmulqdq {:?}", is_x86_feature_detected!("vpclmulqdq"));
println!("avx512vnni {:?}", is_x86_feature_detected!("avx512vnni"));
println!(
"avx512bitalg {:?}",
@@ -61,3 +58,15 @@ fn x86_all() {
println!("xsaves: {:?}", is_x86_feature_detected!("xsaves"));
println!("xsavec: {:?}", is_x86_feature_detected!("xsavec"));
}
+
+#[test]
+#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
+#[allow(deprecated)]
+fn x86_deprecated() {
+ println!("avx512gfni {:?}", is_x86_feature_detected!("avx512gfni"));
+ println!("avx512vaes {:?}", is_x86_feature_detected!("avx512vaes"));
+ println!(
+ "avx512vpclmulqdq {:?}",
+ is_x86_feature_detected!("avx512vpclmulqdq")
+ );
+}
diff --git a/library/stdarch/crates/intrinsic-test/Cargo.toml b/library/stdarch/crates/intrinsic-test/Cargo.toml
index 5fde23c9e..7efbab755 100644
--- a/library/stdarch/crates/intrinsic-test/Cargo.toml
+++ b/library/stdarch/crates/intrinsic-test/Cargo.toml
@@ -2,7 +2,7 @@
name = "intrinsic-test"
version = "0.1.0"
authors = ["Jamie Cunliffe <Jamie.Cunliffe@arm.com>"]
-edition = "2018"
+edition = "2021"
[dependencies]
lazy_static = "1.4.0"
@@ -14,4 +14,4 @@ log = "0.4.11"
pretty_env_logger = "0.4.0"
rayon = "1.5.0"
diff = "0.1.12"
-itertools = "0.10.1" \ No newline at end of file
+itertools = "0.10.1"
diff --git a/library/stdarch/crates/intrinsic-test/missing_arm.txt b/library/stdarch/crates/intrinsic-test/missing_arm.txt
index bbc8de584..3d7ead062 100644
--- a/library/stdarch/crates/intrinsic-test/missing_arm.txt
+++ b/library/stdarch/crates/intrinsic-test/missing_arm.txt
@@ -163,17 +163,6 @@ vcaddq_rot270_f32
vcaddq_rot90_f32
vcadd_rot270_f32
vcadd_rot90_f32
-vcombine_f32
-vcombine_p16
-vcombine_p8
-vcombine_s16
-vcombine_s32
-vcombine_s64
-vcombine_s8
-vcombine_u16
-vcombine_u32
-vcombine_u64
-vcombine_u8
vcvtaq_s32_f32
vcvtaq_u32_f32
vcvta_s32_f32
diff --git a/library/stdarch/crates/intrinsic-test/src/acle_csv_parser.rs b/library/stdarch/crates/intrinsic-test/src/acle_csv_parser.rs
index d7b066485..7336c9e8b 100644
--- a/library/stdarch/crates/intrinsic-test/src/acle_csv_parser.rs
+++ b/library/stdarch/crates/intrinsic-test/src/acle_csv_parser.rs
@@ -59,8 +59,8 @@ impl Into<Intrinsic> for ACLEIntrinsicLine {
let signature = self.intrinsic;
let (ret_ty, remaining) = signature.split_once(' ').unwrap();
- let results = type_from_c(ret_ty)
- .unwrap_or_else(|_| panic!("Failed to parse return type: {}", ret_ty));
+ let results =
+ type_from_c(ret_ty).unwrap_or_else(|_| panic!("Failed to parse return type: {ret_ty}"));
let (name, args) = remaining.split_once('(').unwrap();
let args = args.trim_end_matches(')');
@@ -177,7 +177,7 @@ fn from_c(pos: usize, s: &str) -> Argument {
Argument {
pos,
name,
- ty: type_from_c(s).unwrap_or_else(|_| panic!("Failed to parse type: {}", s)),
+ ty: type_from_c(s).unwrap_or_else(|_| panic!("Failed to parse type: {s}")),
constraints: vec![],
}
}
diff --git a/library/stdarch/crates/intrinsic-test/src/intrinsic.rs b/library/stdarch/crates/intrinsic-test/src/intrinsic.rs
index e0645a36b..fb4eb4cb7 100644
--- a/library/stdarch/crates/intrinsic-test/src/intrinsic.rs
+++ b/library/stdarch/crates/intrinsic-test/src/intrinsic.rs
@@ -109,7 +109,7 @@ impl Intrinsic {
pub fn generate_loop_rust(&self, additional: &str, passes: u32) -> String {
let constraints = self.arguments.as_constraint_parameters_rust();
let constraints = if !constraints.is_empty() {
- format!("::<{}>", constraints)
+ format!("::<{constraints}>")
} else {
constraints
};
diff --git a/library/stdarch/crates/intrinsic-test/src/main.rs b/library/stdarch/crates/intrinsic-test/src/main.rs
index 43f2df08b..dac934574 100644
--- a/library/stdarch/crates/intrinsic-test/src/main.rs
+++ b/library/stdarch/crates/intrinsic-test/src/main.rs
@@ -58,7 +58,7 @@ fn gen_code_c(
pass = gen_code_c(
intrinsic,
constraints,
- format!("{}-{}", name, i),
+ format!("{name}-{i}"),
p64_armv7_workaround
)
)
@@ -117,7 +117,7 @@ int main(int argc, char **argv) {{
}}"#,
header_files = header_files
.iter()
- .map(|header| format!("#include <{}>", header))
+ .map(|header| format!("#include <{header}>"))
.collect::<Vec<_>>()
.join("\n"),
arglists = intrinsic.arguments.gen_arglists_c(PASSES),
@@ -148,7 +148,7 @@ fn gen_code_rust(intrinsic: &Intrinsic, constraints: &[&Argument], name: String)
name = current.name,
ty = current.ty.rust_type(),
val = i,
- pass = gen_code_rust(intrinsic, constraints, format!("{}-{}", name, i))
+ pass = gen_code_rust(intrinsic, constraints, format!("{name}-{i}"))
)
})
.collect()
@@ -237,7 +237,7 @@ fn build_rust(intrinsics: &Vec<Intrinsic>, toolchain: &str, a32: bool) -> 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 rust_filename = format!(r#"{rust_dir}/main.rs"#);
let mut file = File::create(&rust_filename).unwrap();
let c_code = generate_rust_program(&i, a32);
@@ -355,7 +355,7 @@ fn main() {
let filename = matches.value_of("INPUT").unwrap();
let toolchain = matches
.value_of("TOOLCHAIN")
- .map_or("".into(), |t| format!("+{}", t));
+ .map_or("".into(), |t| format!("+{t}"));
let cpp_compiler = matches.value_of("CPPCOMPILER").unwrap();
let c_runner = matches.value_of("RUNNER").unwrap_or("");
@@ -443,7 +443,7 @@ fn compare_outputs(intrinsics: &Vec<Intrinsic>, toolchain: &str, runner: &str, a
let (c, rust) = match (c, rust) {
(Ok(c), Ok(rust)) => (c, rust),
- a => panic!("{:#?}", a),
+ a => panic!("{a:#?}"),
};
if !c.status.success() {
@@ -480,20 +480,20 @@ fn compare_outputs(intrinsics: &Vec<Intrinsic>, toolchain: &str, runner: &str, a
intrinsics.iter().for_each(|reason| match reason {
FailureReason::Difference(intrinsic, c, rust) => {
- println!("Difference for intrinsic: {}", intrinsic);
+ 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::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)
+ println!("Failed to run C program for intrinsic {intrinsic}")
}
FailureReason::RunRust(intrinsic) => {
- println!("Failed to run rust program for intrinsic {}", intrinsic)
+ println!("Failed to run rust program for intrinsic {intrinsic}")
}
});
println!("{} differences found", intrinsics.len());
diff --git a/library/stdarch/crates/intrinsic-test/src/types.rs b/library/stdarch/crates/intrinsic-test/src/types.rs
index dd23586e7..7442ad5e6 100644
--- a/library/stdarch/crates/intrinsic-test/src/types.rs
+++ b/library/stdarch/crates/intrinsic-test/src/types.rs
@@ -25,7 +25,7 @@ impl FromStr for TypeKind {
"poly" => Ok(Self::Poly),
"uint" | "unsigned" => Ok(Self::UInt),
"void" => Ok(Self::Void),
- _ => Err(format!("Impossible to parse argument kind {}", s)),
+ _ => Err(format!("Impossible to parse argument kind {s}")),
}
}
}
@@ -199,14 +199,14 @@ impl IntrinsicType {
simd_len: Some(simd_len),
vec_len: None,
..
- } => format!("{}{}x{}_t", kind.c_prefix(), bit_len, simd_len),
+ } => format!("{}{bit_len}x{simd_len}_t", kind.c_prefix()),
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),
+ } => format!("{}{bit_len}x{simd_len}x{vec_len}_t", kind.c_prefix()),
_ => todo!("{:#?}", self),
}
}
@@ -220,7 +220,7 @@ impl IntrinsicType {
simd_len: Some(simd_len),
vec_len: Some(_),
..
- } => format!("{}{}x{}_t", kind.c_prefix(), bit_len, simd_len),
+ } => format!("{}{bit_len}x{simd_len}_t", kind.c_prefix()),
_ => unreachable!("Shouldn't be called on this type"),
}
}
@@ -234,21 +234,21 @@ impl IntrinsicType {
simd_len: None,
vec_len: None,
..
- } => format!("{}{}", kind.rust_prefix(), bit_len),
+ } => format!("{}{bit_len}", kind.rust_prefix()),
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),
+ } => format!("{}{bit_len}x{simd_len}_t", kind.c_prefix()),
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),
+ } => format!("{}{bit_len}x{simd_len}x{vec_len}_t", kind.c_prefix()),
_ => todo!("{:#?}", self),
}
}
diff --git a/library/stdarch/crates/intrinsic-test/src/values.rs b/library/stdarch/crates/intrinsic-test/src/values.rs
index 64b4d9fc9..68dd30d44 100644
--- a/library/stdarch/crates/intrinsic-test/src/values.rs
+++ b/library/stdarch/crates/intrinsic-test/src/values.rs
@@ -13,7 +13,7 @@ pub fn value_for_array(bits: u32, index: u32) -> String {
} else if bits == 64 {
format!("{:#X}", VALUES_64[index % VALUES_64.len()])
} else {
- panic!("Unknown size: {}", bits);
+ panic!("Unknown size: {bits}");
}
}
diff --git a/library/stdarch/crates/simd-test-macro/Cargo.toml b/library/stdarch/crates/simd-test-macro/Cargo.toml
index c3ecf981e..cd110c1d3 100644
--- a/library/stdarch/crates/simd-test-macro/Cargo.toml
+++ b/library/stdarch/crates/simd-test-macro/Cargo.toml
@@ -2,7 +2,7 @@
name = "simd-test-macro"
version = "0.1.0"
authors = ["Alex Crichton <alex@alexcrichton.com>"]
-edition = "2018"
+edition = "2021"
[lib]
proc-macro = true
diff --git a/library/stdarch/crates/simd-test-macro/src/lib.rs b/library/stdarch/crates/simd-test-macro/src/lib.rs
index 9d81a4c5e..2a31dd745 100644
--- a/library/stdarch/crates/simd-test-macro/src/lib.rs
+++ b/library/stdarch/crates/simd-test-macro/src/lib.rs
@@ -59,7 +59,7 @@ pub fn simd_test(
let macro_test = match target
.split('-')
.next()
- .unwrap_or_else(|| panic!("target triple contained no \"-\": {}", target))
+ .unwrap_or_else(|| panic!("target triple contained no \"-\": {target}"))
{
"i686" | "x86_64" | "i586" => "is_x86_feature_detected",
"arm" | "armv7" => "is_arm_feature_detected",
@@ -82,7 +82,7 @@ pub fn simd_test(
force_test = true;
"is_mips64_feature_detected"
}
- t => panic!("unknown target: {}", t),
+ t => panic!("unknown target: {t}"),
};
let macro_test = Ident::new(macro_test, Span::call_site());
diff --git a/library/stdarch/crates/std_detect/Cargo.toml b/library/stdarch/crates/std_detect/Cargo.toml
index 3a482564e..589a3900a 100644
--- a/library/stdarch/crates/std_detect/Cargo.toml
+++ b/library/stdarch/crates/std_detect/Cargo.toml
@@ -13,7 +13,7 @@ readme = "README.md"
keywords = ["std", "run-time", "feature", "detection"]
categories = ["hardware-support"]
license = "MIT OR Apache-2.0"
-edition = "2018"
+edition = "2021"
[badges]
is-it-maintained-issue-resolution = { repository = "rust-lang/stdarch" }
diff --git a/library/stdarch/crates/std_detect/src/detect/arch/x86.rs b/library/stdarch/crates/std_detect/src/detect/arch/x86.rs
index 893e1a887..d0bf92d3e 100644
--- a/library/stdarch/crates/std_detect/src/detect/arch/x86.rs
+++ b/library/stdarch/crates/std_detect/src/detect/arch/x86.rs
@@ -68,9 +68,9 @@ features! {
/// * `"avx512vbmi"`
/// * `"avx512vpopcntdq"`
/// * `"avx512vbmi2"`
- /// * `"avx512gfni"`
- /// * `"avx512vaes"`
- /// * `"avx512vpclmulqdq"`
+ /// * `"gfni"`
+ /// * `"vaes"`
+ /// * `"vpclmulqdq"`
/// * `"avx512vnni"`
/// * `"avx512bitalg"`
/// * `"avx512bf16"`
@@ -95,6 +95,9 @@ features! {
/// [docs]: https://software.intel.com/sites/landingpage/IntrinsicsGuide
#[stable(feature = "simd_x86", since = "1.27.0")]
@BIND_FEATURE_NAME: "abm"; "lzcnt"; // abm is a synonym for lzcnt
+ @BIND_FEATURE_NAME: "avx512gfni"; "gfni"; #[deprecated(since = "1.67.0", note = "the `avx512gfni` feature has been renamed to `gfni`")];
+ @BIND_FEATURE_NAME: "avx512vaes"; "vaes"; #[deprecated(since = "1.67.0", note = "the `avx512vaes` feature has been renamed to `vaes`")];
+ @BIND_FEATURE_NAME: "avx512vpclmulqdq"; "vpclmulqdq"; #[deprecated(since = "1.67.0", note = "the `avx512vpclmulqdq` feature has been renamed to `vpclmulqdq`")];
@FEATURE: #[stable(feature = "simd_x86", since = "1.27.0")] aes: "aes";
/// AES (Advanced Encryption Standard New Instructions AES-NI)
@FEATURE: #[stable(feature = "simd_x86", since = "1.27.0")] pclmulqdq: "pclmulqdq";
@@ -150,11 +153,11 @@ features! {
/// Quadword)
@FEATURE: #[stable(feature = "simd_x86", since = "1.27.0")] avx512vbmi2: "avx512vbmi2";
/// AVX-512 VBMI2 (Additional byte, word, dword and qword capabilities)
- @FEATURE: #[stable(feature = "simd_x86", since = "1.27.0")] avx512gfni: "avx512gfni";
+ @FEATURE: #[stable(feature = "simd_x86", since = "1.27.0")] gfni: "gfni";
/// AVX-512 GFNI (Galois Field New Instruction)
- @FEATURE: #[stable(feature = "simd_x86", since = "1.27.0")] avx512vaes: "avx512vaes";
+ @FEATURE: #[stable(feature = "simd_x86", since = "1.27.0")] vaes: "vaes";
/// AVX-512 VAES (Vector AES instruction)
- @FEATURE: #[stable(feature = "simd_x86", since = "1.27.0")] avx512vpclmulqdq: "avx512vpclmulqdq";
+ @FEATURE: #[stable(feature = "simd_x86", since = "1.27.0")] vpclmulqdq: "vpclmulqdq";
/// AVX-512 VPCLMULQDQ (Vector PCLMULQDQ instructions)
@FEATURE: #[stable(feature = "simd_x86", since = "1.27.0")] avx512vnni: "avx512vnni";
/// AVX-512 VNNI (Vector Neural Network Instructions)
diff --git a/library/stdarch/crates/std_detect/src/detect/cache.rs b/library/stdarch/crates/std_detect/src/detect/cache.rs
index d01a5ea24..a94c655c3 100644
--- a/library/stdarch/crates/std_detect/src/detect/cache.rs
+++ b/library/stdarch/crates/std_detect/src/detect/cache.rs
@@ -179,7 +179,7 @@ fn detect_and_initialize() -> Initializer {
/// the bit is set, the feature is enabled, and otherwise it is disabled.
///
/// If the feature `std_detect_env_override` is enabled looks for the env
-/// variable `RUST_STD_DETECT_UNSTABLE` and uses its its content to disable
+/// variable `RUST_STD_DETECT_UNSTABLE` and uses its content to disable
/// Features that would had been otherwise detected.
#[inline]
pub(crate) fn test(bit: u32) -> bool {
diff --git a/library/stdarch/crates/std_detect/src/detect/macros.rs b/library/stdarch/crates/std_detect/src/detect/macros.rs
index a467f9db6..45feec79f 100644
--- a/library/stdarch/crates/std_detect/src/detect/macros.rs
+++ b/library/stdarch/crates/std_detect/src/detect/macros.rs
@@ -17,7 +17,7 @@ macro_rules! features {
@CFG: $cfg:meta;
@MACRO_NAME: $macro_name:ident;
@MACRO_ATTRS: $(#[$macro_attrs:meta])*
- $(@BIND_FEATURE_NAME: $bind_feature:tt; $feature_impl:tt; )*
+ $(@BIND_FEATURE_NAME: $bind_feature:tt; $feature_impl:tt; $(#[$deprecate_attr:meta];)?)*
$(@NO_RUNTIME_DETECTION: $nort_feature:tt; )*
$(@FEATURE: #[$stability_attr:meta] $feature:ident: $feature_lit:tt;
$(implied by target_features: [$($target_feature_lit:tt),*];)?
@@ -35,7 +35,15 @@ macro_rules! features {
};
)*
$(
- ($bind_feature) => { $crate::$macro_name!($feature_impl) };
+ ($bind_feature) => {
+ {
+ $(
+ #[$deprecate_attr] macro_rules! deprecated_feature { {} => {}; }
+ deprecated_feature! {};
+ )?
+ $crate::$macro_name!($feature_impl)
+ }
+ };
)*
$(
($nort_feature) => {
diff --git a/library/stdarch/crates/std_detect/src/detect/mod.rs b/library/stdarch/crates/std_detect/src/detect/mod.rs
index 2bca84ca1..9a135c90a 100644
--- a/library/stdarch/crates/std_detect/src/detect/mod.rs
+++ b/library/stdarch/crates/std_detect/src/detect/mod.rs
@@ -47,7 +47,7 @@ cfg_if! {
// On x86/x86_64 no OS specific functionality is required.
#[path = "os/x86.rs"]
mod os;
- } else if #[cfg(all(target_os = "linux", feature = "libc"))] {
+ } else if #[cfg(all(any(target_os = "linux", target_os = "android"), feature = "libc"))] {
#[path = "os/linux/mod.rs"]
mod os;
} else if #[cfg(all(target_os = "freebsd", feature = "libc"))] {
diff --git a/library/stdarch/crates/std_detect/src/detect/os/linux/aarch64.rs b/library/stdarch/crates/std_detect/src/detect/os/linux/aarch64.rs
index 6c79ba86d..a75185d43 100644
--- a/library/stdarch/crates/std_detect/src/detect/os/linux/aarch64.rs
+++ b/library/stdarch/crates/std_detect/src/detect/os/linux/aarch64.rs
@@ -329,7 +329,7 @@ mod tests {
env!("CARGO_MANIFEST_DIR"),
"/src/detect/test_data/linux-empty-hwcap2-aarch64.auxv"
);
- println!("file: {}", file);
+ println!("file: {file}");
let v = auxv_from_file(file).unwrap();
println!("HWCAP : 0x{:0x}", v.hwcap);
println!("HWCAP2: 0x{:0x}", v.hwcap2);
@@ -341,7 +341,7 @@ mod tests {
env!("CARGO_MANIFEST_DIR"),
"/src/detect/test_data/linux-no-hwcap2-aarch64.auxv"
);
- println!("file: {}", file);
+ println!("file: {file}");
let v = auxv_from_file(file).unwrap();
println!("HWCAP : 0x{:0x}", v.hwcap);
println!("HWCAP2: 0x{:0x}", v.hwcap2);
@@ -353,7 +353,7 @@ mod tests {
env!("CARGO_MANIFEST_DIR"),
"/src/detect/test_data/linux-hwcap2-aarch64.auxv"
);
- println!("file: {}", file);
+ println!("file: {file}");
let v = auxv_from_file(file).unwrap();
println!("HWCAP : 0x{:0x}", v.hwcap);
println!("HWCAP2: 0x{:0x}", v.hwcap2);
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 c903903bd..d9e7b28ea 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
@@ -313,7 +313,7 @@ mod tests {
#[test]
fn linux_rpi3() {
let file = concat!(env!("CARGO_MANIFEST_DIR"), "/src/detect/test_data/linux-rpi3.auxv");
- println!("file: {}", file);
+ println!("file: {file}");
let v = auxv_from_file(file).unwrap();
assert_eq!(v.hwcap, 4174038);
assert_eq!(v.hwcap2, 16);
@@ -322,7 +322,7 @@ mod tests {
#[test]
fn linux_macos_vb() {
let file = concat!(env!("CARGO_MANIFEST_DIR"), "/src/detect/test_data/macos-virtualbox-linux-x86-4850HQ.auxv");
- println!("file: {}", file);
+ println!("file: {file}");
// The file contains HWCAP but not HWCAP2. In that case, we treat HWCAP2 as zero.
let v = auxv_from_file(file).unwrap();
assert_eq!(v.hwcap, 126614527);
@@ -332,7 +332,7 @@ mod tests {
#[test]
fn linux_artificial_aarch64() {
let file = concat!(env!("CARGO_MANIFEST_DIR"), "/src/detect/test_data/linux-artificial-aarch64.auxv");
- println!("file: {}", file);
+ println!("file: {file}");
let v = auxv_from_file(file).unwrap();
assert_eq!(v.hwcap, 0x0123456789abcdef);
assert_eq!(v.hwcap2, 0x02468ace13579bdf);
@@ -340,7 +340,7 @@ mod tests {
#[test]
fn linux_no_hwcap2_aarch64() {
let file = concat!(env!("CARGO_MANIFEST_DIR"), "/src/detect/test_data/linux-no-hwcap2-aarch64.auxv");
- println!("file: {}", file);
+ println!("file: {file}");
let v = auxv_from_file(file).unwrap();
// An absent HWCAP2 is treated as zero, and does not prevent acceptance of HWCAP.
assert_ne!(v.hwcap, 0);
diff --git a/library/stdarch/crates/std_detect/src/detect/os/linux/riscv.rs b/library/stdarch/crates/std_detect/src/detect/os/linux/riscv.rs
index 1ec06959a..91a85d58e 100644
--- a/library/stdarch/crates/std_detect/src/detect/os/linux/riscv.rs
+++ b/library/stdarch/crates/std_detect/src/detect/os/linux/riscv.rs
@@ -1,73 +1,73 @@
-//! Run-time feature detection for RISC-V on Linux.
-
-use super::auxvec;
-use crate::detect::{bit, cache, Feature};
-
-/// Read list of supported features from the auxiliary vector.
-pub(crate) fn detect_features() -> cache::Initializer {
- let mut value = cache::Initializer::default();
- let enable_feature = |value: &mut cache::Initializer, feature, enable| {
- if enable {
- value.set(feature as u32);
- }
- };
- let enable_features = |value: &mut cache::Initializer, feature_slice: &[Feature], enable| {
- if enable {
- for feature in feature_slice {
- value.set(*feature as u32);
- }
- }
- };
-
- // The values are part of the platform-specific [asm/hwcap.h][hwcap]
- //
- // [hwcap]: https://github.com/torvalds/linux/blob/master/arch/riscv/include/asm/hwcap.h
- let auxv = auxvec::auxv().expect("read auxvec"); // should not fail on RISC-V platform
- enable_feature(
- &mut value,
- Feature::a,
- bit::test(auxv.hwcap, (b'a' - b'a').into()),
- );
- enable_feature(
- &mut value,
- Feature::c,
- bit::test(auxv.hwcap, (b'c' - b'a').into()),
- );
- enable_features(
- &mut value,
- &[Feature::d, Feature::f, Feature::zicsr],
- bit::test(auxv.hwcap, (b'd' - b'a').into()),
- );
- enable_features(
- &mut value,
- &[Feature::f, Feature::zicsr],
- bit::test(auxv.hwcap, (b'f' - b'a').into()),
- );
- let has_i = bit::test(auxv.hwcap, (b'i' - b'a').into());
- // If future RV128I is supported, implement with `enable_feature` here
- #[cfg(target_pointer_width = "64")]
- enable_feature(&mut value, Feature::rv64i, has_i);
- #[cfg(target_pointer_width = "32")]
- enable_feature(&mut value, Feature::rv32i, has_i);
- #[cfg(target_pointer_width = "32")]
- enable_feature(
- &mut value,
- Feature::rv32e,
- bit::test(auxv.hwcap, (b'e' - b'a').into()),
- );
- enable_feature(
- &mut value,
- Feature::h,
- bit::test(auxv.hwcap, (b'h' - b'a').into()),
- );
- enable_feature(
- &mut value,
- Feature::m,
- bit::test(auxv.hwcap, (b'm' - b'a').into()),
- );
- // FIXME: Auxvec does not show supervisor feature support, but this mode may be useful
- // to detect when Rust is used to write Linux kernel modules.
- // These should be more than Auxvec way to detect supervisor features.
-
- value
-}
+//! Run-time feature detection for RISC-V on Linux.
+
+use super::auxvec;
+use crate::detect::{bit, cache, Feature};
+
+/// Read list of supported features from the auxiliary vector.
+pub(crate) fn detect_features() -> cache::Initializer {
+ let mut value = cache::Initializer::default();
+ let enable_feature = |value: &mut cache::Initializer, feature, enable| {
+ if enable {
+ value.set(feature as u32);
+ }
+ };
+ let enable_features = |value: &mut cache::Initializer, feature_slice: &[Feature], enable| {
+ if enable {
+ for feature in feature_slice {
+ value.set(*feature as u32);
+ }
+ }
+ };
+
+ // The values are part of the platform-specific [asm/hwcap.h][hwcap]
+ //
+ // [hwcap]: https://github.com/torvalds/linux/blob/master/arch/riscv/include/asm/hwcap.h
+ let auxv = auxvec::auxv().expect("read auxvec"); // should not fail on RISC-V platform
+ enable_feature(
+ &mut value,
+ Feature::a,
+ bit::test(auxv.hwcap, (b'a' - b'a').into()),
+ );
+ enable_feature(
+ &mut value,
+ Feature::c,
+ bit::test(auxv.hwcap, (b'c' - b'a').into()),
+ );
+ enable_features(
+ &mut value,
+ &[Feature::d, Feature::f, Feature::zicsr],
+ bit::test(auxv.hwcap, (b'd' - b'a').into()),
+ );
+ enable_features(
+ &mut value,
+ &[Feature::f, Feature::zicsr],
+ bit::test(auxv.hwcap, (b'f' - b'a').into()),
+ );
+ let has_i = bit::test(auxv.hwcap, (b'i' - b'a').into());
+ // If future RV128I is supported, implement with `enable_feature` here
+ #[cfg(target_pointer_width = "64")]
+ enable_feature(&mut value, Feature::rv64i, has_i);
+ #[cfg(target_pointer_width = "32")]
+ enable_feature(&mut value, Feature::rv32i, has_i);
+ #[cfg(target_pointer_width = "32")]
+ enable_feature(
+ &mut value,
+ Feature::rv32e,
+ bit::test(auxv.hwcap, (b'e' - b'a').into()),
+ );
+ enable_feature(
+ &mut value,
+ Feature::h,
+ bit::test(auxv.hwcap, (b'h' - b'a').into()),
+ );
+ enable_feature(
+ &mut value,
+ Feature::m,
+ bit::test(auxv.hwcap, (b'm' - b'a').into()),
+ );
+ // FIXME: Auxvec does not show supervisor feature support, but this mode may be useful
+ // to detect when Rust is used to write Linux kernel modules.
+ // These should be more than Auxvec way to detect supervisor features.
+
+ value
+}
diff --git a/library/stdarch/crates/std_detect/src/detect/os/x86.rs b/library/stdarch/crates/std_detect/src/detect/os/x86.rs
index ea5f595ec..08f48cd17 100644
--- a/library/stdarch/crates/std_detect/src/detect/os/x86.rs
+++ b/library/stdarch/crates/std_detect/src/detect/os/x86.rs
@@ -211,10 +211,10 @@ pub(crate) fn detect_features() -> cache::Initializer {
enable(extended_features_ecx, 1, Feature::avx512vbmi);
enable(extended_features_ecx, 5, Feature::avx512bf16);
enable(extended_features_ecx, 6, Feature::avx512vbmi2);
- enable(extended_features_ecx, 8, Feature::avx512gfni);
+ enable(extended_features_ecx, 8, Feature::gfni);
enable(extended_features_ecx, 8, Feature::avx512vp2intersect);
- enable(extended_features_ecx, 9, Feature::avx512vaes);
- enable(extended_features_ecx, 10, Feature::avx512vpclmulqdq);
+ enable(extended_features_ecx, 9, Feature::vaes);
+ enable(extended_features_ecx, 10, Feature::vpclmulqdq);
enable(extended_features_ecx, 11, Feature::avx512vnni);
enable(extended_features_ecx, 12, Feature::avx512bitalg);
enable(extended_features_ecx, 14, Feature::avx512vpopcntdq);
diff --git a/library/stdarch/crates/std_detect/tests/cpu-detection.rs b/library/stdarch/crates/std_detect/tests/cpu-detection.rs
index ca8bf28f4..02ad77a63 100644
--- a/library/stdarch/crates/std_detect/tests/cpu-detection.rs
+++ b/library/stdarch/crates/std_detect/tests/cpu-detection.rs
@@ -15,7 +15,7 @@ extern crate std_detect;
#[test]
fn all() {
for (f, e) in std_detect::detect::features() {
- println!("{}: {}", f, e);
+ println!("{f}: {e}");
}
}
@@ -132,12 +132,9 @@ fn x86_all() {
is_x86_feature_detected!("avx512vpopcntdq")
);
println!("avx512vbmi2 {:?}", is_x86_feature_detected!("avx512vbmi2"));
- println!("avx512gfni {:?}", is_x86_feature_detected!("avx512gfni"));
- println!("avx512vaes {:?}", is_x86_feature_detected!("avx512vaes"));
- println!(
- "avx512vpclmulqdq {:?}",
- is_x86_feature_detected!("avx512vpclmulqdq")
- );
+ println!("gfni {:?}", is_x86_feature_detected!("gfni"));
+ println!("vaes {:?}", is_x86_feature_detected!("vaes"));
+ println!("vpclmulqdq {:?}", is_x86_feature_detected!("vpclmulqdq"));
println!("avx512vnni {:?}", is_x86_feature_detected!("avx512vnni"));
println!(
"avx512bitalg {:?}",
diff --git a/library/stdarch/crates/std_detect/tests/x86-specific.rs b/library/stdarch/crates/std_detect/tests/x86-specific.rs
index 59e9a62fd..e481620c7 100644
--- a/library/stdarch/crates/std_detect/tests/x86-specific.rs
+++ b/library/stdarch/crates/std_detect/tests/x86-specific.rs
@@ -36,12 +36,9 @@ fn dump() {
is_x86_feature_detected!("avx512vpopcntdq")
);
println!("avx512vbmi2 {:?}", is_x86_feature_detected!("avx512vbmi2"));
- println!("avx512gfni {:?}", is_x86_feature_detected!("avx512gfni"));
- println!("avx512vaes {:?}", is_x86_feature_detected!("avx512vaes"));
- println!(
- "avx512vpclmulqdq {:?}",
- is_x86_feature_detected!("avx512vpclmulqdq")
- );
+ println!("gfni {:?}", is_x86_feature_detected!("gfni"));
+ println!("vaes {:?}", is_x86_feature_detected!("vaes"));
+ println!("vpclmulqdq {:?}", is_x86_feature_detected!("vpclmulqdq"));
println!("avx512vnni {:?}", is_x86_feature_detected!("avx512vnni"));
println!(
"avx512bitalg {:?}",
diff --git a/library/stdarch/crates/stdarch-gen/Cargo.toml b/library/stdarch/crates/stdarch-gen/Cargo.toml
index b339672f4..a5d19b199 100644
--- a/library/stdarch/crates/stdarch-gen/Cargo.toml
+++ b/library/stdarch/crates/stdarch-gen/Cargo.toml
@@ -2,7 +2,7 @@
name = "stdarch-gen"
version = "0.1.0"
authors = ["Heinz Gies <heinz@licenser.net>"]
-edition = "2018"
+edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
diff --git a/library/stdarch/crates/stdarch-gen/src/main.rs b/library/stdarch/crates/stdarch-gen/src/main.rs
index d2f865753..750e88091 100644
--- a/library/stdarch/crates/stdarch-gen/src/main.rs
+++ b/library/stdarch/crates/stdarch-gen/src/main.rs
@@ -59,7 +59,7 @@ fn type_len(t: &str) -> usize {
"4_" => 4,
"8_" => 8,
"16" => 16,
- _ => panic!("unknown type: {}", t),
+ _ => panic!("unknown type: {t}"),
}
} else if s.len() == 3 {
s[1].parse::<usize>().unwrap() * type_sub_len(t)
@@ -77,7 +77,7 @@ fn type_sub_len(t: &str) -> usize {
"2_t" => 2,
"3_t" => 3,
"4_t" => 4,
- _ => panic!("unknown type len: {}", t),
+ _ => panic!("unknown type len: {t}"),
}
}
}
@@ -92,7 +92,7 @@ fn type_bits(t: &str) -> usize {
| "float32x4_t" | "f32" => 32,
"int64x1_t" | "int64x2_t" | "uint64x1_t" | "uint64x2_t" | "poly64x1_t" | "poly64x2_t"
| "i64" | "u64" | "float64x1_t" | "float64x2_t" | "f64" => 64,
- _ => panic!("unknown type: {}", t),
+ _ => panic!("unknown type: {t}"),
}
}
@@ -105,7 +105,7 @@ fn type_exp_len(t: &str, base_len: usize) -> usize {
4 => 2,
8 => 3,
16 => 4,
- _ => panic!("unknown type: {}", t),
+ _ => panic!("unknown type: {t}"),
}
}
@@ -118,7 +118,7 @@ fn type_bits_exp_len(t: &str) -> usize {
"int32x2_t" | "int32x4_t" | "uint32x2_t" | "uint32x4_t" | "i32" | "u32" => 5,
"int64x1_t" | "int64x2_t" | "uint64x1_t" | "uint64x2_t" | "poly64x1_t" | "poly64x2_t"
| "i64" | "u64" => 6,
- _ => panic!("unknown type: {}", t),
+ _ => panic!("unknown type: {t}"),
}
}
@@ -243,7 +243,7 @@ fn type_to_suffix(t: &str) -> &str {
"p8" => "b_p8",
"p16" => "h_p16",
"p128" => "q_p128",
- _ => panic!("unknown type: {}", t),
+ _ => panic!("unknown type: {t}"),
}
}
@@ -297,7 +297,7 @@ fn type_to_n_suffix(t: &str) -> &str {
"u16" => "h_n_u16",
"u32" => "s_n_u32",
"u64" => "d_n_u64",
- _ => panic!("unknown type: {}", t),
+ _ => panic!("unknown type: {t}"),
}
}
@@ -325,7 +325,7 @@ fn type_to_noq_n_suffix(t: &str) -> &str {
"u16" => "h_n_u16",
"u32" => "s_n_u32",
"u64" => "d_n_u64",
- _ => panic!("unknown type: {}", t),
+ _ => panic!("unknown type: {t}"),
}
}
@@ -354,7 +354,7 @@ fn type_to_rot_suffix(c_name: &str, suf: &str) -> String {
if suf.starts_with("q") {
format!("{}q_{}{}", ns[0], ns[1], &suf[1..])
} else {
- format!("{}{}", c_name, suf)
+ format!("{c_name}{suf}")
}
}
@@ -426,7 +426,7 @@ fn type_to_noq_suffix(t: &str) -> &str {
"poly16x4_t" | "poly16x8_t" => "_p16",
"poly64x1_t" | "poly64x2_t" | "p64" => "_p64",
"p128" => "_p128",
- _ => panic!("unknown type: {}", t),
+ _ => panic!("unknown type: {t}"),
}
}
@@ -521,7 +521,7 @@ fn type_to_global_type(t: &str) -> &str {
"p16" => "p16",
"p64" => "p64",
"p128" => "p128",
- _ => panic!("unknown type: {}", t),
+ _ => panic!("unknown type: {t}"),
}
}
@@ -530,7 +530,7 @@ fn type_to_sub_type(t: &str) -> String {
match s.len() {
2 => String::from(t),
3 => format!("{}x{}_t", s[0], s[1]),
- _ => panic!("unknown type: {}", t),
+ _ => panic!("unknown type: {t}"),
}
}
@@ -547,9 +547,9 @@ fn type_to_native_type(t: &str) -> String {
"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}"),
},
- _ => panic!("unknown type: {}", t),
+ _ => panic!("unknown type: {t}"),
}
}
@@ -566,7 +566,7 @@ fn native_type_to_type(t: &str) -> &str {
"f16" => "float16x4_t",
"f32" => "float32x2_t",
"f64" => "float64x1_t",
- _ => panic!("unknown type: {}", t),
+ _ => panic!("unknown type: {t}"),
}
}
@@ -583,7 +583,7 @@ fn native_type_to_long_type(t: &str) -> &str {
"f16" => "float16x8_t",
"f32" => "float32x4_t",
"f64" => "float64x2_t",
- _ => panic!("unknown type: {}", t),
+ _ => panic!("unknown type: {t}"),
}
}
@@ -601,7 +601,7 @@ fn type_to_half(t: &str) -> &str {
"poly16x8_t" => "poly16x4_t",
"float32x4_t" => "float32x2_t",
"float64x2_t" => "float64x1_t",
- _ => panic!("unknown half type for {}", t),
+ _ => panic!("unknown half type for {t}"),
}
}
@@ -624,7 +624,7 @@ fn transpose1(x: usize) -> &'static str {
4 => "[0, 4, 2, 6]",
8 => "[0, 8, 2, 10, 4, 12, 6, 14]",
16 => "[0, 16, 2, 18, 4, 20, 6, 22, 8, 24, 10, 26, 12, 28, 14, 30]",
- _ => panic!("unknown transpose order of len {}", x),
+ _ => panic!("unknown transpose order of len {x}"),
}
}
@@ -634,7 +634,7 @@ fn transpose2(x: usize) -> &'static str {
4 => "[1, 5, 3, 7]",
8 => "[1, 9, 3, 11, 5, 13, 7, 15]",
16 => "[1, 17, 3, 19, 5, 21, 7, 23, 9, 25, 11, 27, 13, 29, 15, 31]",
- _ => panic!("unknown transpose order of len {}", x),
+ _ => panic!("unknown transpose order of len {x}"),
}
}
@@ -644,7 +644,7 @@ fn zip1(x: usize) -> &'static str {
4 => "[0, 4, 1, 5]",
8 => "[0, 8, 1, 9, 2, 10, 3, 11]",
16 => "[0, 16, 1, 17, 2, 18, 3, 19, 4, 20, 5, 21, 6, 22, 7, 23]",
- _ => panic!("unknown zip order of len {}", x),
+ _ => panic!("unknown zip order of len {x}"),
}
}
@@ -654,7 +654,7 @@ fn zip2(x: usize) -> &'static str {
4 => "[2, 6, 3, 7]",
8 => "[4, 12, 5, 13, 6, 14, 7, 15]",
16 => "[8, 24, 9, 25, 10, 26, 11, 27, 12, 28, 13, 29, 14, 30, 15, 31]",
- _ => panic!("unknown zip order of len {}", x),
+ _ => panic!("unknown zip order of len {x}"),
}
}
@@ -664,7 +664,7 @@ fn unzip1(x: usize) -> &'static str {
4 => "[0, 2, 4, 6]",
8 => "[0, 2, 4, 6, 8, 10, 12, 14]",
16 => "[0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30]",
- _ => panic!("unknown unzip order of len {}", x),
+ _ => panic!("unknown unzip order of len {x}"),
}
}
@@ -674,13 +674,13 @@ fn unzip2(x: usize) -> &'static str {
4 => "[1, 3, 5, 7]",
8 => "[1, 3, 5, 7, 9, 11, 13, 15]",
16 => "[1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31]",
- _ => panic!("unknown unzip order of len {}", x),
+ _ => panic!("unknown unzip order of len {x}"),
}
}
fn values(t: &str, vs: &[String]) -> String {
if vs.len() == 1 && !t.contains('x') {
- format!(": {} = {}", t, vs[0])
+ format!(": {t} = {}", vs[0])
} else if vs.len() == 1 && type_to_global_type(t) == "f64" {
format!(": {} = {}", type_to_global_type(t), vs[0])
} else {
@@ -723,7 +723,7 @@ fn max_val(t: &str) -> &'static str {
"i64" => "0x7F_FF_FF_FF_FF_FF_FF_FF",
"f32" => "3.40282347e+38",
"f64" => "1.7976931348623157e+308",
- _ => panic!("No TRUE for type {}", t),
+ _ => panic!("No TRUE for type {t}"),
}
}
@@ -739,7 +739,7 @@ fn min_val(t: &str) -> &'static str {
"i64" => "-9223372036854775808",
"f32" => "-3.40282347e+38",
"f64" => "-1.7976931348623157e+308",
- _ => panic!("No TRUE for type {}", t),
+ _ => panic!("No TRUE for type {t}"),
}
}
@@ -749,7 +749,7 @@ fn true_val(t: &str) -> &'static str {
"u16" => "0xFF_FF",
"u32" => "0xFF_FF_FF_FF",
"u64" => "0xFF_FF_FF_FF_FF_FF_FF_FF",
- _ => panic!("No TRUE for type {}", t),
+ _ => panic!("No TRUE for type {t}"),
}
}
@@ -763,7 +763,7 @@ fn ff_val(t: &str) -> &'static str {
"i16" => "0xFF_FF",
"i32" => "0xFF_FF_FF_FF",
"i64" => "0xFF_FF_FF_FF_FF_FF_FF_FF",
- _ => panic!("No TRUE for type {}", t),
+ _ => panic!("No TRUE for type {t}"),
}
}
@@ -784,7 +784,7 @@ fn bits(t: &str) -> &'static str {
"p8x" => "8",
"p16" => "16",
"p64" => "64",
- _ => panic!("Unknown bits for type {}", t),
+ _ => panic!("Unknown bits for type {t}"),
}
}
@@ -801,7 +801,7 @@ fn bits_minus_one(t: &str) -> &'static str {
"p8x" => "7",
"p16" => "15",
"p64" => "63",
- _ => panic!("Unknown bits for type {}", t),
+ _ => panic!("Unknown bits for type {t}"),
}
}
@@ -818,7 +818,7 @@ fn half_bits(t: &str) -> &'static str {
"p8x" => "4",
"p16" => "8",
"p64" => "32",
- _ => panic!("Unknown bits for type {}", t),
+ _ => panic!("Unknown bits for type {t}"),
}
}
@@ -852,7 +852,7 @@ fn type_len_str(t: &str) -> &'static str {
"poly16x8_t" => "8",
"poly64x1_t" => "1",
"poly64x2_t" => "2",
- _ => panic!("unknown type: {}", t),
+ _ => panic!("unknown type: {t}"),
}
}
@@ -886,7 +886,7 @@ fn type_len_minus_one_str(t: &str) -> &'static str {
"poly16x8_t" => "7",
"poly64x1_t" => "0",
"poly64x2_t" => "1",
- _ => panic!("unknown type: {}", t),
+ _ => panic!("unknown type: {t}"),
}
}
@@ -920,7 +920,7 @@ fn type_half_len_str(t: &str) -> &'static str {
"poly16x8_t" => "4",
"poly64x1_t" => "0",
"poly64x2_t" => "1",
- _ => panic!("unknown type: {}", t),
+ _ => panic!("unknown type: {t}"),
}
}
@@ -954,12 +954,12 @@ fn type_to_ext(t: &str, v: bool, r: bool, pi8: bool) -> String {
native
),
_ if pi8 => format!(".p0i8"),
- _ => format!(".p0{}", native),
+ _ => format!(".p0{native}"),
};
let sub_type = match &native[0..1] {
"i" | "f" => native,
"u" => native.replace("u", "i"),
- _ => panic!("unknown type: {}", t),
+ _ => panic!("unknown type: {t}"),
};
let ext = format!(
"v{}{}{}",
@@ -1041,8 +1041,8 @@ fn gen_aarch64(
fn_type: Fntype,
) -> (String, String) {
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])),
+ Normal => format!("{current_name}{}", type_to_suffix(in_t[1])),
+ NoQ => format!("{current_name}{}", type_to_noq_suffix(in_t[1])),
Double => format!(
"{}{}",
current_name,
@@ -1053,15 +1053,15 @@ fn gen_aarch64(
current_name,
type_to_noq_double_suffixes(out_t, in_t[1])
),
- NSuffix => format!("{}{}", current_name, type_to_n_suffix(in_t[1])),
+ NSuffix => format!("{current_name}{}", type_to_n_suffix(in_t[1])),
DoubleN => format!(
"{}{}",
current_name,
type_to_double_n_suffixes(out_t, in_t[1])
),
- 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)),
+ 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,
@@ -1092,7 +1092,7 @@ fn gen_aarch64(
current_name,
type_to_lane_suffixes(out_t, in_t[1], false)
),
- In2 => format!("{}{}", current_name, type_to_suffix(in_t[2])),
+ In2 => format!("{current_name}{}", type_to_suffix(in_t[2])),
In2Lane => format!(
"{}{}",
current_name,
@@ -1122,11 +1122,11 @@ fn gen_aarch64(
};
let current_fn = if let Some(current_fn) = current_fn.clone() {
if link_aarch64.is_some() {
- panic!("[{}] Can't specify link and fn at the same time.", name)
+ panic!("[{name}] Can't specify link and fn at the same time.")
}
current_fn
} else if link_aarch64.is_some() {
- format!("{}_", name)
+ format!("{name}_")
} else {
if multi_fn.is_empty() {
panic!(
@@ -1174,8 +1174,8 @@ fn gen_aarch64(
let sub = type_to_sub_type(in_t[1]);
(
match type_sub_len(in_t[1]) {
- 1 => format!("a: {}, n: i64, ptr: {}", sub, ptr_type),
- 2 => format!("a: {}, b: {}, n: i64, ptr: {}", sub, sub, ptr_type),
+ 1 => format!("a: {sub}, n: i64, ptr: {ptr_type}"),
+ 2 => format!("a: {sub}, b: {sub}, n: i64, ptr: {ptr_type}"),
3 => format!(
"a: {}, b: {}, c: {}, n: i64, ptr: {}",
sub, sub, sub, ptr_type
@@ -1187,7 +1187,7 @@ fn gen_aarch64(
_ => panic!("unsupported type: {}", in_t[1]),
},
if out_t != "void" {
- format!(" -> {}", out_t)
+ format!(" -> {out_t}")
} else {
String::new()
},
@@ -1200,7 +1200,7 @@ fn gen_aarch64(
3 => format!("a: {}, b: {}, c: {}, n: i32", in_t[0], in_t[1], in_t[2]),
_ => unimplemented!("unknown para_num"),
},
- format!(" -> {}", out_t),
+ format!(" -> {out_t}"),
)
}
} else if matches!(fn_type, Fntype::Store) {
@@ -1211,23 +1211,20 @@ fn gen_aarch64(
type_to_native_type(in_t[1])
};
let subs = match type_sub_len(in_t[1]) {
- 1 => format!("a: {}", sub),
- 2 => format!("a: {}, b: {}", sub, sub),
- 3 => format!("a: {}, b: {}, c: {}", sub, sub, sub),
- 4 => format!("a: {}, b: {}, c: {}, d: {}", sub, sub, sub, sub),
+ 1 => format!("a: {sub}"),
+ 2 => format!("a: {sub}, b: {sub}"),
+ 3 => format!("a: {sub}, b: {sub}, c: {sub}"),
+ 4 => format!("a: {sub}, b: {sub}, c: {sub}, d: {sub}"),
_ => panic!("unsupported type: {}", in_t[1]),
};
- (format!("{}, ptr: *mut {}", subs, ptr_type), String::new())
+ (format!("{subs}, ptr: *mut {ptr_type}"), String::new())
} else if is_vldx(&name) {
let ptr_type = if name.contains("dup") {
type_to_native_type(out_t)
} else {
type_to_sub_type(out_t)
};
- (
- format!("ptr: *const {}", ptr_type),
- format!(" -> {}", out_t),
- )
+ (format!("ptr: *const {ptr_type}"), format!(" -> {out_t}"))
} else {
(
match para_num {
@@ -1256,7 +1253,7 @@ fn gen_aarch64(
assert_eq!(constns.len(), 2);
format!(r#"<const {}: i32, const {}: i32>"#, constns[0], constns[1])
} else {
- format!(r#"<const {}: i32>"#, constn)
+ format!(r#"<const {constn}: i32>"#)
}
} else {
String::new()
@@ -1314,7 +1311,7 @@ fn gen_aarch64(
para_num + 1
)
} else {
- format!("\n#[rustc_legacy_const_generics({})]", para_num)
+ format!("\n#[rustc_legacy_const_generics({para_num})]")
}
} else {
String::new()
@@ -1323,7 +1320,7 @@ fn gen_aarch64(
let fn_output = if out_t == "void" {
String::new()
} else {
- format!("-> {} ", out_t)
+ format!("-> {out_t} ")
};
let fn_inputs = match para_num {
1 => format!("(a: {})", in_t[0]),
@@ -1373,14 +1370,14 @@ fn gen_aarch64(
} else if link_aarch64.is_some() && matches!(fn_type, Fntype::Store) {
let cast = if is_vstx(&name) { " as _" } else { "" };
match type_sub_len(in_t[1]) {
- 1 => format!(r#"{}{}(b, a{})"#, ext_c, current_fn, cast),
- 2 => format!(r#"{}{}(b.0, b.1, a{})"#, ext_c, current_fn, cast),
- 3 => format!(r#"{}{}(b.0, b.1, b.2, a{})"#, ext_c, current_fn, cast),
- 4 => format!(r#"{}{}(b.0, b.1, b.2, b.3, a{})"#, ext_c, current_fn, cast),
+ 1 => format!(r#"{ext_c}{current_fn}(b, a{cast})"#),
+ 2 => format!(r#"{ext_c}{current_fn}(b.0, b.1, a{cast})"#),
+ 3 => format!(r#"{ext_c}{current_fn}(b.0, b.1, b.2, a{cast})"#),
+ 4 => format!(r#"{ext_c}{current_fn}(b.0, b.1, b.2, b.3, a{cast})"#),
_ => panic!("unsupported type: {}", in_t[1]),
}
} else if link_aarch64.is_some() && is_vldx(&name) {
- format!(r#"{}{}(a as _)"#, ext_c, current_fn,)
+ format!(r#"{ext_c}{current_fn}(a as _)"#,)
} else {
let trans: [&str; 2] = if link_t[3] != out_t {
["transmute(", ")"]
@@ -1388,7 +1385,7 @@ fn gen_aarch64(
["", ""]
};
match (multi_calls.len(), para_num, fixed.len()) {
- (0, 1, 0) => format!(r#"{}{}{}(a){}"#, ext_c, trans[0], current_fn, trans[1]),
+ (0, 1, 0) => format!(r#"{ext_c}{}{current_fn}(a){}"#, trans[0], trans[1]),
(0, 1, _) => {
let fixed: Vec<String> =
fixed.iter().take(type_len(in_t[0])).cloned().collect();
@@ -1402,11 +1399,11 @@ fn gen_aarch64(
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,),
+ (0, 2, _) => format!(r#"{ext_c}{}{current_fn}(a, b){}"#, trans[0], trans[1],),
+ (0, 3, _) => format!(r#"{ext_c}{current_fn}(a, b, c)"#,),
+ (_, 1, _) => format!(r#"{ext_c}{multi_calls}"#,),
+ (_, 2, _) => format!(r#"{ext_c}{multi_calls}"#,),
+ (_, 3, _) => format!(r#"{ext_c}{multi_calls}"#,),
(_, _, _) => String::new(),
}
}
@@ -1768,8 +1765,8 @@ fn gen_arm(
separate: bool,
) -> (String, String) {
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])),
+ Normal => format!("{current_name}{}", type_to_suffix(in_t[1])),
+ NoQ => format!("{current_name}{}", type_to_noq_suffix(in_t[1])),
Double => format!(
"{}{}",
current_name,
@@ -1780,15 +1777,15 @@ fn gen_arm(
current_name,
type_to_noq_double_suffixes(out_t, in_t[1])
),
- NSuffix => format!("{}{}", current_name, type_to_n_suffix(in_t[1])),
+ NSuffix => format!("{current_name}{}", type_to_n_suffix(in_t[1])),
DoubleN => format!(
"{}{}",
current_name,
type_to_double_n_suffixes(out_t, in_t[1])
),
- 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)),
+ 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,
@@ -1819,7 +1816,7 @@ fn gen_arm(
current_name,
type_to_lane_suffixes(out_t, in_t[1], false)
),
- In2 => format!("{}{}", current_name, type_to_suffix(in_t[2])),
+ In2 => format!("{current_name}{}", type_to_suffix(in_t[2])),
In2Lane => format!(
"{}{}",
current_name,
@@ -1873,7 +1870,7 @@ fn gen_arm(
}
current_fn
} else if link_aarch64.is_some() || link_arm.is_some() {
- format!("{}_", name)
+ format!("{name}_")
} else {
if multi_fn.is_empty() {
panic!(
@@ -1980,9 +1977,9 @@ fn gen_arm(
};
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,),
+ 1 => format!("a: {sub_type}"),
+ 2 => format!("a: {sub_type}, b: {sub_type}",),
+ 3 => format!("a: {sub_type}, b: {sub_type}, c: {sub_type}",),
4 => format!(
"a: {}, b: {}, c: {}, d: {}",
sub_type, sub_type, sub_type, sub_type,
@@ -1992,12 +1989,9 @@ fn gen_arm(
let out = if out_t == "void" {
String::new()
} else {
- format!(" -> {}", out_t)
+ format!(" -> {out_t}")
};
- (
- format!("ptr: {}, {}, n: i32, size: i32", ptr_type, inputs),
- out,
- )
+ (format!("ptr: {ptr_type}, {inputs}, n: i32, size: i32"), out)
} else {
let (_, const_type) = if const_arm.contains(":") {
let consts: Vec<_> =
@@ -2011,15 +2005,15 @@ fn gen_arm(
};
(
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),
+ 1 => format!("a: {}, n: {const_type}", in_t[0]),
+ 2 => format!("a: {}, b: {}, n: {const_type}", in_t[0], in_t[1]),
3 => format!(
- "a: {}, b: {}, c: {}, n: {}",
- in_t[0], in_t[1], in_t[2], const_type
+ "a: {}, b: {}, c: {}, n: {const_type}",
+ in_t[0], in_t[1], in_t[2]
),
_ => unimplemented!("unknown para_num"),
},
- format!(" -> {}", out_t),
+ format!(" -> {out_t}"),
)
}
} else if out_t != link_arm_t[3] {
@@ -2038,9 +2032,9 @@ fn gen_arm(
} 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,),
+ 1 => format!("a: {sub_type}"),
+ 2 => format!("a: {sub_type}, b: {sub_type}",),
+ 3 => format!("a: {sub_type}, b: {sub_type}, c: {sub_type}",),
4 => format!(
"a: {}, b: {}, c: {}, d: {}",
sub_type, sub_type, sub_type, sub_type,
@@ -2053,14 +2047,11 @@ fn gen_arm(
(type_to_native_type(in_t[1]), "")
};
(
- format!("ptr: *mut {}, {}{}", ptr_type, inputs, size),
+ format!("ptr: *mut {ptr_type}, {inputs}{size}"),
String::new(),
)
} else if is_vldx(&name) {
- (
- format!("ptr: *const i8, size: i32"),
- format!(" -> {}", out_t),
- )
+ (format!("ptr: *const i8, size: i32"), format!(" -> {out_t}"))
} else {
(String::new(), String::new())
}
@@ -2084,20 +2075,20 @@ fn gen_arm(
};
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,),
+ 1 => format!("a: {sub_type}",),
+ 2 => format!("a: {sub_type}, b: {sub_type}",),
+ 3 => format!("a: {sub_type}, b: {sub_type}, c: {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: {}", ptr_type));
+ inputs.push_str(&format!(", n: i64, ptr: {ptr_type}"));
let out = if out_t == "void" {
String::new()
} else {
- format!(" -> {}", out_t)
+ format!(" -> {out_t}")
};
(inputs, out)
} else if const_aarch64.contains("dup-in_len-N as ttn") {
@@ -2111,7 +2102,7 @@ fn gen_arm(
),
_ => unimplemented!("unknown para_num"),
},
- format!(" -> {}", out_t),
+ format!(" -> {out_t}"),
)
} else {
(
@@ -2121,7 +2112,7 @@ fn gen_arm(
3 => format!("a: {}, b: {}, c: {}, n: i32", in_t[0], in_t[1], in_t[2]),
_ => unimplemented!("unknown para_num"),
},
- format!(" -> {}", out_t),
+ format!(" -> {out_t}"),
)
}
} else if out_t != link_aarch64_t[3] {
@@ -2140,9 +2131,9 @@ fn gen_arm(
} 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,),
+ 1 => format!("a: {sub_type}",),
+ 2 => format!("a: {sub_type}, b: {sub_type}",),
+ 3 => format!("a: {sub_type}, b: {sub_type}, c: {sub_type}",),
4 => format!(
"a: {}, b: {}, c: {}, d: {}",
sub_type, sub_type, sub_type, sub_type,
@@ -2154,7 +2145,7 @@ fn gen_arm(
} else {
type_to_native_type(in_t[1])
};
- inputs.push_str(&format!(", ptr: *mut {}", ptr_type));
+ inputs.push_str(&format!(", ptr: *mut {ptr_type}"));
(inputs, String::new())
} else if is_vldx(&name) {
let ptr_type = if name.contains("dup") {
@@ -2162,10 +2153,7 @@ fn gen_arm(
} else {
type_to_sub_type(out_t)
};
- (
- format!("ptr: *const {}", ptr_type),
- format!(" -> {}", out_t),
- )
+ (format!("ptr: *const {ptr_type}"), format!(" -> {out_t}"))
} else {
(String::new(), String::new())
}
@@ -2181,7 +2169,7 @@ fn gen_arm(
));
};
let const_declare = if let Some(constn) = constn {
- format!(r#"<const {}: i32>"#, constn)
+ format!(r#"<const {constn}: i32>"#)
} else {
String::new()
};
@@ -2216,7 +2204,7 @@ fn gen_arm(
String::new()
};
let const_legacy = if constn.is_some() {
- format!("\n#[rustc_legacy_const_generics({})]", para_num)
+ format!("\n#[rustc_legacy_const_generics({para_num})]")
} else {
String::new()
};
@@ -2224,7 +2212,7 @@ fn gen_arm(
let fn_output = if out_t == "void" {
String::new()
} else {
- format!("-> {} ", out_t)
+ format!("-> {out_t} ")
};
let fn_inputs = match para_num {
1 => format!("(a: {})", in_t[0]),
@@ -2274,15 +2262,15 @@ fn gen_arm(
cnt
};
match para_num {
- 1 => format!("{}(a, {})", current_fn, cnt),
- 2 => format!("{}(a, b, {})", current_fn, cnt),
+ 1 => format!("{current_fn}(a, {cnt})"),
+ 2 => format!("{current_fn}(a, b, {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,),
+ 1 => format!("transmute({current_fn}(a))",),
+ 2 => format!("transmute({current_fn}(transmute(a), transmute(b)))",),
_ => String::new(),
}
} else if matches!(fn_type, Fntype::Store) {
@@ -2295,10 +2283,10 @@ fn gen_arm(
("", String::new())
};
match type_sub_len(in_t[1]) {
- 1 => format!("{}(a{}, b{})", current_fn, cast, size),
- 2 => format!("{}(a{}, b.0, b.1{})", current_fn, cast, size),
- 3 => format!("{}(a{}, b.0, b.1, b.2{})", current_fn, cast, size),
- 4 => format!("{}(a{}, b.0, b.1, b.2, b.3{})", current_fn, cast, size),
+ 1 => format!("{current_fn}(a{cast}, b{size})"),
+ 2 => format!("{current_fn}(a{cast}, b.0, b.1{size})"),
+ 3 => format!("{current_fn}(a{cast}, b.0, b.1, b.2{size})"),
+ 4 => format!("{current_fn}(a{cast}, b.0, b.1, b.2, b.3{size})"),
_ => String::new(),
}
} else if link_arm.is_some() && is_vldx(&name) {
@@ -2345,31 +2333,31 @@ fn gen_arm(
cnt.push_str(&const_aarch64);
}
cnt.push_str(")");
- format!("{}(a, {})", current_fn, cnt)
+ format!("{current_fn}(a, {cnt})")
} else {
match para_num {
- 1 => format!("{}(a, {})", current_fn, const_aarch64),
- 2 => format!("{}(a, b, {})", current_fn, const_aarch64),
+ 1 => format!("{current_fn}(a, {const_aarch64})"),
+ 2 => format!("{current_fn}(a, b, {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,),
+ 1 => format!("transmute({current_fn}(a))",),
+ 2 => format!("transmute({current_fn}(a, b))",),
_ => String::new(),
}
} else if matches!(fn_type, Fntype::Store) {
let cast = if is_vstx(&name) { " as _" } else { "" };
match type_sub_len(in_t[1]) {
- 1 => format!("{}(b, a{})", current_fn, cast),
- 2 => format!("{}(b.0, b.1, a{})", current_fn, cast),
- 3 => format!("{}(b.0, b.1, b.2, a{})", current_fn, cast),
- 4 => format!("{}(b.0, b.1, b.2, b.3, a{})", current_fn, cast),
+ 1 => format!("{current_fn}(b, a{cast})"),
+ 2 => format!("{current_fn}(b.0, b.1, a{cast})"),
+ 3 => format!("{current_fn}(b.0, b.1, b.2, a{cast})"),
+ 4 => format!("{current_fn}(b.0, b.1, b.2, b.3, a{cast})"),
_ => String::new(),
}
} else if link_aarch64.is_some() && is_vldx(&name) {
- format!("{}(a as _)", current_fn)
+ format!("{current_fn}(a as _)")
} else {
String::new()
};
@@ -2421,7 +2409,7 @@ fn gen_arm(
} 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, 0) => format!(r#"{ext_c}{current_fn}(a)"#,),
(0, 1, _) => {
let fixed: Vec<String> =
fixed.iter().take(type_len(in_t[0])).cloned().collect();
@@ -2433,11 +2421,11 @@ fn gen_arm(
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,),
+ (0, 2, _) => format!(r#"{ext_c}{current_fn}(a, b)"#,),
+ (0, 3, _) => format!(r#"{ext_c}{current_fn}(a, b, c)"#,),
+ (_, 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() {
@@ -2452,8 +2440,8 @@ fn gen_arm(
}
};
let stable_aarch64 = match target {
- Default | ArmV7 | Vfp4 | FPArmV8 | AES => String::from("\n#[cfg_attr(target_arch = \"aarch64\", stable(feature = \"neon_intrinsics\", since = \"1.59.0\"))]"),
- RDM => String::from("\n#[cfg_attr(target_arch = \"aarch64\", stable(feature = \"rdm_intrinsics\", since = \"1.62.0\"))]"),
+ Default | ArmV7 | Vfp4 | FPArmV8 | AES => String::from("\n#[cfg_attr(not(target_arch = \"arm\"), stable(feature = \"neon_intrinsics\", since = \"1.59.0\"))]"),
+ RDM => String::from("\n#[cfg_attr(not(target_arch = \"arm\"), stable(feature = \"rdm_intrinsics\", since = \"1.62.0\"))]"),
_ => String::new(),
};
let function_doc = create_doc_string(current_comment, &name);
@@ -2536,9 +2524,9 @@ fn expand_intrinsic(intr: &str, t: &str) -> String {
"poly64x1_t" => "i64x1",
"poly64x2_t" => "i64x2",
*/
- _ => panic!("unknown type for extension: {}", t),
+ _ => panic!("unknown type for extension: {t}"),
};
- format!(r#""{}{}""#, intr, ext)
+ format!(r#""{intr}{ext}""#)
} else if intr.ends_with(".s") {
let ext = match t {
"int8x8_t" => "s8",
@@ -2571,9 +2559,9 @@ fn expand_intrinsic(intr: &str, t: &str) -> String {
"poly64x1_t" => "i64x1",
"poly64x2_t" => "i64x2",
*/
- _ => panic!("unknown type for extension: {}", t),
+ _ => panic!("unknown type for extension: {t}"),
};
- format!(r#""{}{}""#, &intr[..intr.len() - 1], ext)
+ format!(r#""{}{ext}""#, &intr[..intr.len() - 1])
} else if intr.ends_with(".l") {
let ext = match t {
"int8x8_t" => "8",
@@ -2604,9 +2592,9 @@ fn expand_intrinsic(intr: &str, t: &str) -> String {
"float64x2_t" => "64",
"poly64x1_t" => "64",
"poly64x2_t" => "64",
- _ => panic!("unknown type for extension: {}", t),
+ _ => panic!("unknown type for extension: {t}"),
};
- format!(r#""{}{}""#, &intr[..intr.len() - 1], ext)
+ format!(r#""{}{ext}""#, &intr[..intr.len() - 1])
} else {
intr.to_string()
}
@@ -2655,7 +2643,7 @@ fn get_call(
"halflen" => type_len(in_t[1]) / 2,
_ => 0,
};
- let mut s = format!("{} [", const_declare);
+ let mut s = format!("{const_declare} [");
for i in 0..len {
if i != 0 {
s.push_str(", ");
@@ -2693,9 +2681,9 @@ fn get_call(
if i != 0 || j != 0 {
s.push_str(", ");
}
- s.push_str(&format!("{} * {} as u32", base_len, &fn_format[2]));
+ s.push_str(&format!("{base_len} * {} as u32", &fn_format[2]));
if j != 0 {
- s.push_str(&format!(" + {}", j));
+ s.push_str(&format!(" + {j}"));
}
}
}
@@ -2709,7 +2697,7 @@ fn get_call(
"in_ttn" => type_to_native_type(in_t[1]),
_ => String::new(),
};
- return format!("{} as {}", &fn_format[1], t);
+ return format!("{} as {t}", &fn_format[1]);
}
if fn_name.starts_with("ins") {
let fn_format: Vec<_> = fn_name.split('-').map(|v| v.to_string()).collect();
@@ -2726,7 +2714,7 @@ fn get_call(
"in0_len" => type_len(in_t[0]),
_ => 0,
};
- let mut s = format!("{} [", const_declare);
+ let mut s = format!("{const_declare} [");
for i in 0..len {
if i != 0 {
s.push_str(", ");
@@ -2760,7 +2748,7 @@ fn get_call(
fn_format[2], fn_format[2]
);
} else {
- return format!(r#"static_assert_imm{}!({});"#, len, fn_format[2]);
+ return format!(r#"static_assert_imm{len}!({});"#, fn_format[2]);
}
}
if fn_name.starts_with("static_assert") {
@@ -2781,13 +2769,13 @@ fn get_call(
};
if lim1 == lim2 {
return format!(
- r#"static_assert!({} : i32 where {} == {});"#,
- fn_format[1], fn_format[1], lim1
+ r#"static_assert!({} : i32 where {} == {lim1});"#,
+ fn_format[1], fn_format[1]
);
} else {
return format!(
- r#"static_assert!({} : i32 where {} >= {} && {} <= {});"#,
- fn_format[1], fn_format[1], lim1, fn_format[1], lim2
+ r#"static_assert!({} : i32 where {} >= {lim1} && {} <= {lim2});"#,
+ fn_format[1], fn_format[1], fn_format[1]
);
}
}
@@ -2945,7 +2933,7 @@ fn get_call(
if fn_name == "fixed" {
let (re_name, re_type) = re.unwrap();
let fixed: Vec<String> = fixed.iter().take(type_len(in_t[1])).cloned().collect();
- return format!(r#"let {}{};"#, re_name, values(&re_type, &fixed));
+ return format!(r#"let {re_name}{};"#, values(&re_type, &fixed));
}
if fn_name == "fixed-half-right" {
let fixed: Vec<String> = fixed.iter().take(type_len(in_t[1])).cloned().collect();
@@ -3083,9 +3071,9 @@ fn get_call(
re_name, re_type, fn_name, param_str
)
} else if fn_name.starts_with("*") {
- format!(r#"{} = {};"#, fn_name, param_str)
+ format!(r#"{fn_name} = {param_str};"#)
} else {
- format!(r#"{}({})"#, fn_name, param_str)
+ format!(r#"{fn_name}({param_str})"#)
};
return fn_str;
}
@@ -3337,7 +3325,7 @@ mod test {
in_t = [spec[0], spec[1], spec[2]];
out_t = spec[3];
} else {
- panic!("Bad spec: {}", line)
+ panic!("Bad spec: {line}")
}
if b.len() == 0 {
if matches!(fn_type, Fntype::Store) {
@@ -3430,8 +3418,8 @@ mod test {
.arg(&arm_out_path)
.arg(&aarch64_out_path)
.status() {
- eprintln!("Could not format `{}`: {}", arm_out_path.to_str().unwrap(), e);
- eprintln!("Could not format `{}`: {}", aarch64_out_path.to_str().unwrap(), e);
+ eprintln!("Could not format `{}`: {e}", arm_out_path.to_str().unwrap());
+ eprintln!("Could not format `{}`: {e}", aarch64_out_path.to_str().unwrap());
};
*/
Ok(())
diff --git a/library/stdarch/crates/stdarch-test/Cargo.toml b/library/stdarch/crates/stdarch-test/Cargo.toml
index 012b4e959..23bddeda6 100644
--- a/library/stdarch/crates/stdarch-test/Cargo.toml
+++ b/library/stdarch/crates/stdarch-test/Cargo.toml
@@ -2,7 +2,7 @@
name = "stdarch-test"
version = "0.1.0"
authors = ["Alex Crichton <alex@alexcrichton.com>"]
-edition = "2018"
+edition = "2021"
[dependencies]
assert-instr-macro = { path = "../assert-instr-macro" }
diff --git a/library/stdarch/crates/stdarch-test/src/disassembly.rs b/library/stdarch/crates/stdarch-test/src/disassembly.rs
index 3ace6b20e..8e4d57d4e 100644
--- a/library/stdarch/crates/stdarch-test/src/disassembly.rs
+++ b/library/stdarch/crates/stdarch-test/src/disassembly.rs
@@ -81,7 +81,7 @@ pub(crate) fn disassemble_myself() -> HashSet<Function> {
.args(add_args)
.arg(&me)
.output()
- .unwrap_or_else(|_| panic!("failed to execute objdump. OBJDUMP={}", objdump));
+ .unwrap_or_else(|_| panic!("failed to execute objdump. OBJDUMP={objdump}"));
println!(
"{}\n{}",
output.status,
@@ -103,7 +103,7 @@ fn parse(output: &str) -> HashSet<Function> {
lines.clone().count()
);
for line in output.lines().take(100) {
- println!("{}", line);
+ println!("{line}");
}
let mut functions = HashSet::new();
@@ -112,9 +112,9 @@ fn parse(output: &str) -> HashSet<Function> {
if !header.ends_with(':') || !header.contains("stdarch_test_shim") {
continue;
}
- eprintln!("header: {}", header);
+ eprintln!("header: {header}");
let symbol = normalize(header);
- eprintln!("normalized symbol: {}", symbol);
+ eprintln!("normalized symbol: {symbol}");
let mut instructions = Vec::new();
while let Some(instruction) = lines.next() {
if instruction.ends_with(':') {
diff --git a/library/stdarch/crates/stdarch-test/src/lib.rs b/library/stdarch/crates/stdarch-test/src/lib.rs
index eba17771c..e0cf46cb4 100644
--- a/library/stdarch/crates/stdarch-test/src/lib.rs
+++ b/library/stdarch/crates/stdarch-test/src/lib.rs
@@ -64,10 +64,10 @@ pub fn assert(shim_addr: usize, fnname: &str, expected: &str) {
// Make sure that the shim is not removed
black_box(shim_addr);
- //eprintln!("shim name: {}", fnname);
+ //eprintln!("shim name: {fnname}");
let function = &DISASSEMBLY
.get(&Function::new(fnname))
- .unwrap_or_else(|| panic!("function \"{}\" not found in the disassembly", fnname));
+ .unwrap_or_else(|| panic!("function \"{fnname}\" not found in the disassembly"));
//eprintln!(" function: {:?}", function);
let mut instrs = &function.instrs[..];
@@ -165,9 +165,9 @@ pub fn assert(shim_addr: usize, fnname: &str, expected: &str) {
// Help debug by printing out the found disassembly, and then panic as we
// didn't find the instruction.
- println!("disassembly for {}: ", fnname,);
+ println!("disassembly for {fnname}: ",);
for (i, instr) in instrs.iter().enumerate() {
- println!("\t{:2}: {}", i, instr);
+ println!("\t{i:2}: {instr}");
}
if !found {
@@ -194,7 +194,7 @@ pub fn assert_skip_test_ok(name: &str) {
if env::var("STDARCH_TEST_EVERYTHING").is_err() {
return;
}
- panic!("skipped test `{}` when it shouldn't be skipped", name);
+ panic!("skipped test `{name}` when it shouldn't be skipped");
}
// See comment in `assert-instr-macro` crate for why this exists
diff --git a/library/stdarch/crates/stdarch-verify/Cargo.toml b/library/stdarch/crates/stdarch-verify/Cargo.toml
index 6362e3d57..56548fd08 100644
--- a/library/stdarch/crates/stdarch-verify/Cargo.toml
+++ b/library/stdarch/crates/stdarch-verify/Cargo.toml
@@ -2,7 +2,7 @@
name = "stdarch-verify"
version = "0.1.0"
authors = ["Alex Crichton <alex@alexcrichton.com>"]
-edition = "2018"
+edition = "2021"
[dependencies]
proc-macro2 = "1.0"
diff --git a/library/stdarch/crates/stdarch-verify/src/lib.rs b/library/stdarch/crates/stdarch-verify/src/lib.rs
index 22108d26a..9b66137ba 100644
--- a/library/stdarch/crates/stdarch-verify/src/lib.rs
+++ b/library/stdarch/crates/stdarch-verify/src/lib.rs
@@ -85,20 +85,20 @@ fn functions(input: TokenStream, dirs: &[&str]) -> TokenStream {
.iter()
.map(|&(ref f, path)| {
let name = &f.sig.ident;
- // println!("{}", name);
+ // println!("{name}");
let mut arguments = Vec::new();
let mut const_arguments = Vec::new();
for input in f.sig.inputs.iter() {
let ty = match *input {
syn::FnArg::Typed(ref c) => &c.ty,
- _ => panic!("invalid argument on {}", name),
+ _ => panic!("invalid argument on {name}"),
};
arguments.push(to_type(ty));
}
for generic in f.sig.generics.params.iter() {
let ty = match *generic {
syn::GenericParam::Const(ref c) => &c.ty,
- _ => panic!("invalid generic argument on {}", name),
+ _ => panic!("invalid generic argument on {name}"),
};
const_arguments.push(to_type(ty));
}
@@ -144,12 +144,12 @@ fn functions(input: TokenStream, dirs: &[&str]) -> TokenStream {
// strip leading underscore from fn name when building a test
// _mm_foo -> mm_foo such that the test name is test_mm_foo.
- let test_name_string = format!("{}", name);
+ let test_name_string = format!("{name}");
let mut test_name_id = test_name_string.as_str();
while test_name_id.starts_with('_') {
test_name_id = &test_name_id[1..];
}
- let has_test = tests.contains(&format!("test_{}", test_name_id));
+ let has_test = tests.contains(&format!("test_{test_name_id}"));
quote! {
Function {
@@ -167,7 +167,7 @@ fn functions(input: TokenStream, dirs: &[&str]) -> TokenStream {
.collect::<Vec<_>>();
let ret = quote! { #input: &[Function] = &[#(#functions),*]; };
- // println!("{}", ret);
+ // println!("{ret}");
ret.into()
}
@@ -336,7 +336,7 @@ fn to_type(t: &syn::Type) -> proc_macro2::TokenStream {
"v4f32" => quote! { &v4f32 },
"v2f64" => quote! { &v2f64 },
- s => panic!("unsupported type: \"{}\"", s),
+ s => panic!("unsupported type: \"{s}\""),
},
syn::Type::Ptr(syn::TypePtr {
ref elem,
diff --git a/library/stdarch/crates/stdarch-verify/tests/arm.rs b/library/stdarch/crates/stdarch-verify/tests/arm.rs
index 6ce5ce05f..dd6720ef0 100644
--- a/library/stdarch/crates/stdarch-verify/tests/arm.rs
+++ b/library/stdarch/crates/stdarch-verify/tests/arm.rs
@@ -628,7 +628,7 @@ fn verify_all_signatures() {
if let Err(e) = matches(rust, arm) {
println!("failed to verify `{}`", rust.name);
- println!(" * {}", e);
+ println!(" * {e}");
all_valid = false;
}
}
@@ -801,7 +801,7 @@ fn parse_intrinsic(node: &Rc<Node>) -> Intrinsic {
let instruction = match instruction {
Some(s) => s.trim().to_lowercase(),
- None => panic!("can't find instruction for `{}`", name),
+ None => panic!("can't find instruction for `{name}`"),
};
Intrinsic {
@@ -973,7 +973,7 @@ fn parse_ty_base(s: &str) -> &'static Type {
"uint8x8x3_t" => &U8X8X3,
"uint8x8x4_t" => &U8X8X4,
- _ => panic!("failed to parse html type {:?}", s),
+ _ => panic!("failed to parse html type {s:?}"),
}
}
diff --git a/library/stdarch/crates/stdarch-verify/tests/mips.rs b/library/stdarch/crates/stdarch-verify/tests/mips.rs
index 1eb86dc29..365057b1d 100644
--- a/library/stdarch/crates/stdarch-verify/tests/mips.rs
+++ b/library/stdarch/crates/stdarch-verify/tests/mips.rs
@@ -125,7 +125,7 @@ impl<'a> From<&'a str> for MsaTy {
"u64" => MsaTy::u64,
"void" => MsaTy::Void,
"void *" => MsaTy::MutVoidPtr,
- v => panic!("unknown ty: \"{}\"", v),
+ v => panic!("unknown ty: \"{v}\""),
}
}
}
@@ -198,8 +198,8 @@ fn verify_all_signatures() {
}
use std::convert::TryFrom;
- let intrinsic: MsaIntrinsic = TryFrom::try_from(line)
- .unwrap_or_else(|_| panic!("failed to parse line: \"{}\"", line));
+ let intrinsic: MsaIntrinsic =
+ TryFrom::try_from(line).unwrap_or_else(|_| panic!("failed to parse line: \"{line}\""));
assert!(!intrinsics.contains_key(&intrinsic.id));
intrinsics.insert(intrinsic.id.clone(), intrinsic);
}
@@ -253,7 +253,7 @@ fn verify_all_signatures() {
if let Err(e) = matches(rust, mips) {
println!("failed to verify `{}`", rust.name);
- println!(" * {}", e);
+ println!(" * {e}");
all_valid = false;
}
}
diff --git a/library/stdarch/crates/stdarch-verify/tests/x86-intel.rs b/library/stdarch/crates/stdarch-verify/tests/x86-intel.rs
index 89494bfd2..cd9bd18ea 100644
--- a/library/stdarch/crates/stdarch-verify/tests/x86-intel.rs
+++ b/library/stdarch/crates/stdarch-verify/tests/x86-intel.rs
@@ -367,7 +367,7 @@ fn verify_all_signatures() {
}
println!("failed to verify `{}`", rust.name);
for error in errors {
- println!(" * {}", error);
+ println!(" * {error}");
}
all_valid = false;
}
@@ -403,18 +403,18 @@ fn verify_all_signatures() {
if PRINT_MISSING_LISTS || PRINT_MISSING_LISTS_MARKDOWN {
for (k, v) in missing {
if PRINT_MISSING_LISTS_MARKDOWN {
- println!("\n<details><summary>{:?}</summary><p>\n", k);
+ println!("\n<details><summary>{k:?}</summary><p>\n");
for intel in v {
let url = format!(
"https://software.intel.com/sites/landingpage\
/IntrinsicsGuide/#text={}&expand=5236",
intel.name
);
- println!(" * [ ] [`{}`]({})", intel.name, url);
+ println!(" * [ ] [`{}`]({url})", intel.name);
}
println!("</p></details>\n");
} else {
- println!("\n{:?}\n", k);
+ println!("\n{k:?}\n");
for intel in v {
println!("\t{}", intel.name);
}
@@ -471,6 +471,18 @@ fn matches(rust: &Function, intel: &Intrinsic) -> Result<(), String> {
continue;
}
+ // Some CPUs support VAES/GFNI/VPCLMULQDQ without AVX512, even though
+ // the Intel documentation states that those instructions require
+ // AVX512VL.
+ if *cpuid == "AVX512VL"
+ && intel
+ .cpuid
+ .iter()
+ .any(|x| matches!(&**x, "VAES" | "GFNI" | "VPCLMULQDQ"))
+ {
+ continue;
+ }
+
let cpuid = cpuid
.chars()
.flat_map(|c| c.to_lowercase())
diff --git a/library/stdarch/examples/Cargo.toml b/library/stdarch/examples/Cargo.toml
index e2590ed9f..38f497fa6 100644
--- a/library/stdarch/examples/Cargo.toml
+++ b/library/stdarch/examples/Cargo.toml
@@ -7,7 +7,7 @@ authors = [
"Gonzalo Brito Gadeschi <gonzalobg88@gmail.com>",
]
description = "Examples of the stdarch crate."
-edition = "2018"
+edition = "2021"
default-run = "hex"
[dependencies]
diff --git a/library/stdarch/examples/connect5.rs b/library/stdarch/examples/connect5.rs
index 1b3325785..09e7e48a7 100644
--- a/library/stdarch/examples/connect5.rs
+++ b/library/stdarch/examples/connect5.rs
@@ -1256,7 +1256,7 @@ fn main() {
pos_disp(&test1);
if pos_is_end(&test1) {
- println!("Game over!!!!!! at Move {}", i);
+ println!("Game over!!!!!! at Move {i}");
count = i + 1;
break;
}
diff --git a/library/stdarch/examples/hex.rs b/library/stdarch/examples/hex.rs
index d982a71b9..a961793a0 100644
--- a/library/stdarch/examples/hex.rs
+++ b/library/stdarch/examples/hex.rs
@@ -40,7 +40,7 @@ fn main() {
io::stdin().read_to_end(&mut input).unwrap();
let mut dst = vec![0; 2 * input.len()];
let s = hex_encode(&input, &mut dst).unwrap();
- println!("{}", s);
+ println!("{s}");
}
fn hex_encode<'a>(src: &[u8], dst: &'a mut [u8]) -> Result<&'a str, usize> {
diff --git a/library/stdarch/triagebot.toml b/library/stdarch/triagebot.toml
index fa0824ac5..f946af7f6 100644
--- a/library/stdarch/triagebot.toml
+++ b/library/stdarch/triagebot.toml
@@ -1 +1,4 @@
[assign]
+
+[assign.owners]
+"*" = ["@Amanieu"]
diff --git a/library/test/Cargo.toml b/library/test/Cargo.toml
index 61b6f33bc..18cb023d2 100644
--- a/library/test/Cargo.toml
+++ b/library/test/Cargo.toml
@@ -7,11 +7,9 @@ edition = "2021"
crate-type = ["dylib", "rlib"]
[dependencies]
-cfg-if = { version = "1.0", features = ['rustc-dep-of-std'] }
getopts = { version = "0.2.21", features = ['rustc-dep-of-std'] }
std = { path = "../std" }
core = { path = "../core" }
-libc = { version = "0.2", default-features = false }
panic_unwind = { path = "../panic_unwind" }
panic_abort = { path = "../panic_abort" }
diff --git a/library/test/src/cli.rs b/library/test/src/cli.rs
index 796796e07..9d22ebbee 100644
--- a/library/test/src/cli.rs
+++ b/library/test/src/cli.rs
@@ -309,7 +309,8 @@ fn parse_opts_impl(matches: getopts::Matches) -> OptRes {
// FIXME: Copied from librustc_ast until linkage errors are resolved. Issue #47566
fn is_nightly() -> bool {
// Whether this is a feature-staged build, i.e., on the beta or stable channel
- let disable_unstable_features = option_env!("CFG_DISABLE_UNSTABLE_FEATURES").is_some();
+ let disable_unstable_features =
+ option_env!("CFG_DISABLE_UNSTABLE_FEATURES").map(|s| s != "0").unwrap_or(false);
// Whether we should enable unstable features for bootstrapping
let bootstrap = env::var("RUSTC_BOOTSTRAP").is_ok();
diff --git a/library/test/src/console.rs b/library/test/src/console.rs
index 24cbe035f..1ee68c854 100644
--- a/library/test/src/console.rs
+++ b/library/test/src/console.rs
@@ -53,6 +53,7 @@ pub struct ConsoleTestState {
pub metrics: MetricMap,
pub failures: Vec<(TestDesc, Vec<u8>)>,
pub not_failures: Vec<(TestDesc, Vec<u8>)>,
+ pub ignores: Vec<(TestDesc, Vec<u8>)>,
pub time_failures: Vec<(TestDesc, Vec<u8>)>,
pub options: Options,
}
@@ -76,6 +77,7 @@ impl ConsoleTestState {
metrics: MetricMap::new(),
failures: Vec::new(),
not_failures: Vec::new(),
+ ignores: Vec::new(),
time_failures: Vec::new(),
options: opts.options,
})
@@ -194,7 +196,10 @@ fn handle_test_result(st: &mut ConsoleTestState, completed_test: CompletedTest)
st.passed += 1;
st.not_failures.push((test, stdout));
}
- TestResult::TrIgnored => st.ignored += 1,
+ TestResult::TrIgnored => {
+ st.ignored += 1;
+ st.ignores.push((test, stdout));
+ }
TestResult::TrBench(bs) => {
st.metrics.insert_metric(
test.name.as_slice(),
diff --git a/library/test/src/formatters/terse.rs b/library/test/src/formatters/terse.rs
index 0837ab169..a431acfbc 100644
--- a/library/test/src/formatters/terse.rs
+++ b/library/test/src/formatters/terse.rs
@@ -254,6 +254,15 @@ impl<T: Write> OutputFormatter for TerseFormatter<T> {
self.write_plain("\n\n")?;
+ // Custom handling of cases where there is only 1 test to execute and that test was ignored.
+ // We want to show more detailed information(why was the test ignored) for investigation purposes.
+ if self.total_test_count == 1 && state.ignores.len() == 1 {
+ let test_desc = &state.ignores[0].0;
+ if let Some(im) = test_desc.ignore_message {
+ self.write_plain(format!("test: {}, ignore_message: {}\n\n", test_desc.name, im))?;
+ }
+ }
+
Ok(success)
}
}
diff --git a/library/test/src/lib.rs b/library/test/src/lib.rs
index 69fb529d7..88d8e5fe9 100644
--- a/library/test/src/lib.rs
+++ b/library/test/src/lib.rs
@@ -204,7 +204,7 @@ fn make_owned_test(test: &&TestDescAndFn) -> TestDescAndFn {
}
/// Invoked when unit tests terminate. Returns `Result::Err` if the test is
-/// considered a failure. By default, invokes `report() and checks for a `0`
+/// considered a failure. By default, invokes `report()` and checks for a `0`
/// result.
pub fn assert_test_result<T: Termination>(result: T) -> Result<(), String> {
let code = result.report().to_i32();
diff --git a/library/test/src/tests.rs b/library/test/src/tests.rs
index 3a0260f86..44776fb0a 100644
--- a/library/test/src/tests.rs
+++ b/library/test/src/tests.rs
@@ -790,6 +790,7 @@ fn should_sort_failures_before_printing_them() {
failures: vec![(test_b, Vec::new()), (test_a, Vec::new())],
options: Options::new(),
not_failures: Vec::new(),
+ ignores: Vec::new(),
time_failures: Vec::new(),
};
diff --git a/library/unwind/src/lib.rs b/library/unwind/src/lib.rs
index 3753071d5..edc10aa39 100644
--- a/library/unwind/src/lib.rs
+++ b/library/unwind/src/lib.rs
@@ -127,3 +127,7 @@ extern "C" {}
#[cfg(target_os = "haiku")]
#[link(name = "gcc_s")]
extern "C" {}
+
+#[cfg(target_os = "nto")]
+#[link(name = "gcc_s")]
+extern "C" {}
diff --git a/library/unwind/src/libunwind.rs b/library/unwind/src/libunwind.rs
index 036a35869..eeeed3afc 100644
--- a/library/unwind/src/libunwind.rs
+++ b/library/unwind/src/libunwind.rs
@@ -89,7 +89,7 @@ pub type _Unwind_Exception_Cleanup_Fn =
// FIXME: The `#[link]` attributes on `extern "C"` block marks those symbols declared in
// the block are reexported in dylib build of std. This is needed when build rustc with
-// feature `llvm-libunwind', as no other cdylib will provided those _Unwind_* symbols.
+// feature `llvm-libunwind`, as no other cdylib will provided those _Unwind_* symbols.
// However the `link` attribute is duplicated multiple times and does not just export symbol,
// a better way to manually export symbol would be another attribute like `#[export]`.
// See the logic in function rustc_codegen_ssa::src::back::exported_symbols, module
diff --git a/src/bootstrap/Cargo.lock b/src/bootstrap/Cargo.lock
index 4a0ba5925..e861d520c 100644
--- a/src/bootstrap/Cargo.lock
+++ b/src/bootstrap/Cargo.lock
@@ -50,6 +50,7 @@ dependencies = [
"opener",
"pretty_assertions",
"serde",
+ "serde_derive",
"serde_json",
"sha2",
"sysinfo",
@@ -564,9 +565,6 @@ name = "serde"
version = "1.0.137"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "61ea8d54c77f8315140a05f4c7237403bf38b72704d031543aa1d16abbf517d1"
-dependencies = [
- "serde_derive",
-]
[[package]]
name = "serde_derive"
diff --git a/src/bootstrap/Cargo.toml b/src/bootstrap/Cargo.toml
index 22ceeca94..663987f11 100644
--- a/src/bootstrap/Cargo.toml
+++ b/src/bootstrap/Cargo.toml
@@ -39,7 +39,10 @@ cc = "1.0.69"
libc = "0.2"
hex = "0.4"
object = { version = "0.29.0", default-features = false, features = ["archive", "coff", "read_core", "unaligned"] }
-serde = { version = "1.0.8", features = ["derive"] }
+serde = "1.0.137"
+# Directly use serde_derive rather than through the derive feature of serde to allow building both
+# in parallel and to allow serde_json and toml to start building as soon as serde has been built.
+serde_derive = "1.0.137"
serde_json = "1.0.2"
sha2 = "0.10"
tar = "0.4"
diff --git a/src/bootstrap/README.md b/src/bootstrap/README.md
index 8dce9e79e..71eee8968 100644
--- a/src/bootstrap/README.md
+++ b/src/bootstrap/README.md
@@ -4,105 +4,31 @@ This is an in-progress README which is targeted at helping to explain how Rust
is bootstrapped and in general, some of the technical details of the build
system.
-## Using rustbuild
+Note that this README only covers internal information, not how to use the tool.
+Please check [bootstrapping dev guide][bootstrapping-dev-guide] for further information.
-The rustbuild build system has a primary entry point, a top level `x.py` script:
+[bootstrapping-dev-guide]: https://rustc-dev-guide.rust-lang.org/building/bootstrapping.html
-```sh
-$ python ./x.py build
-```
-
-Note that if you're on Unix, you should be able to execute the script directly:
-
-```sh
-$ ./x.py build
-```
-
-The script accepts commands, flags, and arguments to determine what to do:
-
-* `build` - a general purpose command for compiling code. Alone, `build` will
- bootstrap the entire compiler, and otherwise, arguments passed indicate what to
- build. For example:
-
- ```
- # build the whole compiler
- ./x.py build --stage 2
-
- # build the stage1 compiler
- ./x.py build
-
- # build stage0 libstd
- ./x.py build --stage 0 library/std
-
- # build a particular crate in stage0
- ./x.py build --stage 0 library/test
- ```
-
- If files that would normally be rebuilt from stage 0 are dirty, the rebuild can be
- overridden using `--keep-stage 0`. Using `--keep-stage n` will skip all steps
- that belong to stage n or earlier:
-
- ```
- # build stage 1, keeping old build products for stage 0
- ./x.py build --keep-stage 0
- ```
-
-* `test` - a command for executing unit tests. Like the `build` command, this
- will execute the entire test suite by default, and otherwise, it can be used to
- select which test suite is run:
-
- ```
- # run all unit tests
- ./x.py test
-
- # execute tool tests
- ./x.py test tidy
-
- # execute the UI test suite
- ./x.py test tests/ui
-
- # execute only some tests in the UI test suite
- ./x.py test tests/ui --test-args substring-of-test-name
-
- # execute tests in the standard library in stage0
- ./x.py test --stage 0 library/std
-
- # execute tests in the core and standard library in stage0,
- # without running doc tests (thus avoid depending on building the compiler)
- ./x.py test --stage 0 --no-doc library/core library/std
+## Introduction
- # execute all doc tests
- ./x.py test src/doc
- ```
+The build system defers most of the complicated logic managing invocations
+of rustc and rustdoc to Cargo itself. However, moving through various stages
+and copying artifacts is still necessary for it to do. Each time rustbuild
+is invoked, it will iterate through the list of predefined steps and execute
+each serially in turn if it matches the paths passed or is a default rule.
+For each step rustbuild relies on the step internally being incremental and
+parallel. Note, though, that the `-j` parameter to rustbuild gets forwarded
+to appropriate test harnesses and such.
-* `doc` - a command for building documentation. Like above, can take arguments
- for what to document.
-
-## Configuring rustbuild
-
-rustbuild offers a TOML-based configuration system with a `config.toml`
-file. An example of this configuration can be found at `config.toml.example`,
-and the configuration file can also be passed as `--config path/to/config.toml`
-if the build system is being invoked manually (via the python script).
-
-You can generate a config.toml using `./configure` options if you want to automate creating the file without having to edit it.
-
-Finally, rustbuild makes use of the [cc-rs crate] which has [its own
-method][env-vars] of configuring C compilers and C flags via environment
-variables.
-
-[cc-rs crate]: https://github.com/alexcrichton/cc-rs
-[env-vars]: https://github.com/alexcrichton/cc-rs#external-configuration-via-environment-variables
-
-## Build stages
+## Build phases
The rustbuild build system goes through a few phases to actually build the
compiler. What actually happens when you invoke rustbuild is:
-1. The entry point script, `x.py` is run. This script is
- responsible for downloading the stage0 compiler/Cargo binaries, and it then
- compiles the build system itself (this folder). Finally, it then invokes the
- actual `bootstrap` binary build system.
+1. The entry point script(`x` for unix like systems, `x.ps1` for windows systems,
+ `x.py` cross-platform) is run. This script is responsible for downloading the stage0
+ compiler/Cargo binaries, and it then compiles the build system itself (this folder).
+ Finally, it then invokes the actual `bootstrap` binary build system.
2. In Rust, `bootstrap` will slurp up all configuration, perform a number of
sanity checks (whether compilers exist, for example), and then start building the
stage0 artifacts.
@@ -115,24 +41,6 @@ compiler. What actually happens when you invoke rustbuild is:
The goal of each stage is to (a) leverage Cargo as much as possible and failing
that (b) leverage Rust as much as possible!
-## Incremental builds
-
-You can configure rustbuild to use incremental compilation with the
-`--incremental` flag:
-
-```sh
-$ ./x.py build --incremental
-```
-
-The `--incremental` flag will store incremental compilation artifacts
-in `build/<host>/stage0-incremental`. Note that we only use incremental
-compilation for the stage0 -> stage1 compilation -- this is because
-the stage1 compiler is changing, and we don't try to cache and reuse
-incremental artifacts across different versions of the compiler.
-
-You can always drop the `--incremental` to build as normal (but you
-will still be using the local nightly as your bootstrap).
-
## Directory Layout
This build system houses all output under the `build` directory, which looks
@@ -236,63 +144,31 @@ build/
# system will link (using hard links) output from stageN-{std,rustc} into
# each of these directories.
#
- # In theory, there is no extra build output in these directories.
+ # In theory these are working rustc sysroot directories, meaning there is
+ # no extra build output in these directories.
stage1/
stage2/
stage3/
```
-## Cargo projects
-
-The current build is unfortunately not quite as simple as `cargo build` in a
-directory, but rather the compiler is split into three different Cargo projects:
-
-* `library/std` - the standard library
-* `library/test` - testing support, depends on libstd
-* `compiler/rustc` - the actual compiler itself
-
-Each "project" has a corresponding Cargo.lock file with all dependencies, and
-this means that building the compiler involves running Cargo three times. The
-structure here serves two goals:
-
-1. Facilitating dependencies coming from crates.io. These dependencies don't
- depend on `std`, so libstd is a separate project compiled ahead of time
- before the actual compiler builds.
-2. Splitting "host artifacts" from "target artifacts". That is, when building
- code for an arbitrary target, you don't need the entire compiler, but you'll
- end up needing libraries like libtest that depend on std but also want to use
- crates.io dependencies. Hence, libtest is split out as its own project that
- is sequenced after `std` but before `rustc`. This project is built for all
- targets.
-
-There is some loss in build parallelism here because libtest can be compiled in
-parallel with a number of rustc artifacts, but in theory, the loss isn't too bad!
-
-## Build tools
-
-We've actually got quite a few tools that we use in the compiler's build system
-and for testing. To organize these, each tool is a project in `src/tools` with a
-corresponding `Cargo.toml`. All tools are compiled with Cargo (currently having
-independent `Cargo.lock` files) and do not currently explicitly depend on the
-compiler or standard library. Compiling each tool is sequenced after the
-appropriate libstd/libtest/librustc compile above.
-
## Extending rustbuild
-So, you'd like to add a feature to the rustbuild build system or just fix a bug.
-Great! One of the major motivational factors for moving away from `make` is that
-Rust is in theory much easier to read, modify, and write. If you find anything
-excessively confusing, please open an issue on this, and we'll try to get it
-documented or simplified, pronto.
+When you use the bootstrap system, you'll call it through the entry point script
+(`x`, `x.ps1`, or `x.py`). However, most of the code lives in `src/bootstrap`.
+`bootstrap` has a difficult problem: it is written in Rust, but yet it is run
+before the Rust compiler is built! To work around this, there are two components
+of bootstrap: the main one written in rust, and `bootstrap.py`. `bootstrap.py`
+is what gets run by entry point script. It takes care of downloading the `stage0`
+compiler, which will then build the bootstrap binary written in Rust.
-First up, you'll probably want to read over the documentation above, as that'll
-give you a high level overview of what rustbuild is doing. You also probably
-want to play around a bit yourself by just getting it up and running before you
-dive too much into the actual build system itself.
+Because there are two separate codebases behind `x.py`, they need to
+be kept in sync. In particular, both `bootstrap.py` and the bootstrap binary
+parse `config.toml` and read the same command line arguments. `bootstrap.py`
+keeps these in sync by setting various environment variables, and the
+programs sometimes have to add arguments that are explicitly ignored, to be
+read by the other.
-After that, each module in rustbuild should have enough documentation to keep
-you up and running. Some general areas that you may be interested in modifying
-are:
+Some general areas that you may be interested in modifying are:
* Adding a new build tool? Take a look at `bootstrap/tool.rs` for examples of
other tools.
@@ -320,8 +196,9 @@ A 'major change' includes
Changes that do not affect contributors to the compiler or users
building rustc from source don't need an update to `VERSION`.
-If you have any questions, feel free to reach out on the `#t-infra` channel in
-the [Rust Zulip server][rust-zulip] or ask on internals.rust-lang.org. When
-you encounter bugs, please file issues on the rust-lang/rust issue tracker.
+If you have any questions, feel free to reach out on the `#t-infra/bootstrap` channel
+at [Rust Bootstrap Zulip server][rust-bootstrap-zulip]. When you encounter bugs,
+please file issues on the [Rust issue tracker][rust-issue-tracker].
-[rust-zulip]: https://rust-lang.zulipchat.com/#narrow/stream/242791-t-infra
+[rust-bootstrap-zulip]: https://rust-lang.zulipchat.com/#narrow/stream/t-infra.2Fbootstrap
+[rust-issue-tracker]: https://github.com/rust-lang/rust/issues
diff --git a/src/bootstrap/bin/main.rs b/src/bootstrap/bin/main.rs
index be69f819c..3856bb64f 100644
--- a/src/bootstrap/bin/main.rs
+++ b/src/bootstrap/bin/main.rs
@@ -16,12 +16,17 @@ fn main() {
let mut build_lock;
let _build_lock_guard;
if cfg!(any(unix, windows)) {
- build_lock = fd_lock::RwLock::new(t!(std::fs::File::create(config.out.join("lock"))));
+ let path = config.out.join("lock");
+ build_lock = fd_lock::RwLock::new(t!(std::fs::File::create(&path)));
_build_lock_guard = match build_lock.try_write() {
Ok(lock) => lock,
err => {
- println!("warning: build directory locked, waiting for lock");
drop(err);
+ if let Some(pid) = get_lock_owner(&path) {
+ println!("warning: build directory locked by process {pid}, waiting for lock");
+ } else {
+ println!("warning: build directory locked, waiting for lock");
+ }
t!(build_lock.write())
}
};
@@ -98,3 +103,30 @@ fn check_version(config: &Config) -> Option<String> {
Some(msg)
}
+
+/// Get the PID of the process which took the write lock by
+/// parsing `/proc/locks`.
+#[cfg(target_os = "linux")]
+fn get_lock_owner(f: &std::path::Path) -> Option<u64> {
+ use std::fs::File;
+ use std::io::{BufRead, BufReader};
+ use std::os::unix::fs::MetadataExt;
+
+ let lock_inode = std::fs::metadata(f).ok()?.ino();
+ let lockfile = File::open("/proc/locks").ok()?;
+ BufReader::new(lockfile).lines().find_map(|line| {
+ // pid--vvvvvv vvvvvvv--- inode
+ // 21: FLOCK ADVISORY WRITE 359238 08:02:3719774 0 EOF
+ let line = line.ok()?;
+ let parts = line.split_whitespace().collect::<Vec<_>>();
+ let (pid, inode) = (parts[4].parse::<u64>().ok()?, &parts[5]);
+ let inode = inode.rsplit_once(':')?.1.parse::<u64>().ok()?;
+ if inode == lock_inode { Some(pid) } else { None }
+ })
+}
+
+#[cfg(not(target_os = "linux"))]
+fn get_lock_owner(_: &std::path::Path) -> Option<u64> {
+ // FIXME: Implement on other OS's
+ None
+}
diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py
index 9cf43fc7a..013d1ab52 100644
--- a/src/bootstrap/bootstrap.py
+++ b/src/bootstrap/bootstrap.py
@@ -2,7 +2,6 @@ from __future__ import absolute_import, division, print_function
import argparse
import contextlib
import datetime
-import distutils.version
import hashlib
import json
import os
@@ -13,17 +12,17 @@ import sys
import tarfile
import tempfile
-from time import time, sleep
+from time import time
-def support_xz():
- try:
- with tempfile.NamedTemporaryFile(delete=False) as temp_file:
- temp_path = temp_file.name
- with tarfile.open(temp_path, "w:xz"):
- pass
- return True
- except tarfile.CompressionError:
- return False
+try:
+ import lzma
+except ImportError:
+ lzma = None
+
+if sys.platform == 'win32':
+ EXE_SUFFIX = ".exe"
+else:
+ EXE_SUFFIX = ""
def get(base, url, path, checksums, verbose=False):
with tempfile.NamedTemporaryFile(delete=False) as temp_file:
@@ -61,7 +60,7 @@ def get(base, url, path, checksums, verbose=False):
def download(path, url, probably_big, verbose):
- for _ in range(0, 4):
+ for _ in range(4):
try:
_download(path, url, probably_big, verbose, True)
return
@@ -88,14 +87,16 @@ def _download(path, url, probably_big, verbose, exception):
# If curl is not present on Win32, we should not sys.exit
# but raise `CalledProcessError` or `OSError` instead
require(["curl", "--version"], exception=platform_is_win32)
- run(["curl", option,
- "-L", # Follow redirect.
- "-y", "30", "-Y", "10", # timeout if speed is < 10 bytes/sec for > 30 seconds
- "--connect-timeout", "30", # timeout if cannot connect within 30 seconds
- "--retry", "3", "-Sf", "-o", path, url],
- verbose=verbose,
- exception=True, # Will raise RuntimeError on failure
- )
+ with open(path, "wb") as outfile:
+ run(["curl", option,
+ "-L", # Follow redirect.
+ "-y", "30", "-Y", "10", # timeout if speed is < 10 bytes/sec for > 30 seconds
+ "--connect-timeout", "30", # timeout if cannot connect within 30 seconds
+ "--retry", "3", "-Sf", url],
+ stdout=outfile, #Implements cli redirect operator '>'
+ verbose=verbose,
+ exception=True, # Will raise RuntimeError on failure
+ )
except (subprocess.CalledProcessError, OSError, RuntimeError):
# see http://serverfault.com/questions/301128/how-to-download
if platform_is_win32:
@@ -395,17 +396,18 @@ class RustBuild(object):
def __init__(self):
self.checksums_sha256 = {}
self.stage0_compiler = None
- self._download_url = ''
+ self.download_url = ''
self.build = ''
self.build_dir = ''
self.clean = False
self.config_toml = ''
self.rust_root = ''
- self.use_locked_deps = ''
- self.use_vendored_sources = ''
+ self.use_locked_deps = False
+ self.use_vendored_sources = False
self.verbose = False
self.git_version = None
self.nix_deps_dir = None
+ self._should_fix_bins_and_dylibs = None
def download_toolchain(self):
"""Fetch the build system for Rust, written in Rust
@@ -426,7 +428,7 @@ class RustBuild(object):
self.program_out_of_date(self.rustc_stamp(), key)):
if os.path.exists(bin_root):
shutil.rmtree(bin_root)
- tarball_suffix = '.tar.xz' if support_xz() else '.tar.gz'
+ tarball_suffix = '.tar.gz' if lzma is None else '.tar.xz'
filename = "rust-std-{}-{}{}".format(
rustc_channel, self.build, tarball_suffix)
pattern = "rust-std-{}".format(self.build)
@@ -437,15 +439,17 @@ class RustBuild(object):
filename = "cargo-{}-{}{}".format(rustc_channel, self.build,
tarball_suffix)
self._download_component_helper(filename, "cargo", tarball_suffix)
- self.fix_bin_or_dylib("{}/bin/cargo".format(bin_root))
-
- self.fix_bin_or_dylib("{}/bin/rustc".format(bin_root))
- self.fix_bin_or_dylib("{}/bin/rustdoc".format(bin_root))
- self.fix_bin_or_dylib("{}/libexec/rust-analyzer-proc-macro-srv".format(bin_root))
- lib_dir = "{}/lib".format(bin_root)
- for lib in os.listdir(lib_dir):
- if lib.endswith(".so"):
- self.fix_bin_or_dylib(os.path.join(lib_dir, lib))
+ if self.should_fix_bins_and_dylibs():
+ self.fix_bin_or_dylib("{}/bin/cargo".format(bin_root))
+
+ self.fix_bin_or_dylib("{}/bin/rustc".format(bin_root))
+ self.fix_bin_or_dylib("{}/bin/rustdoc".format(bin_root))
+ self.fix_bin_or_dylib("{}/libexec/rust-analyzer-proc-macro-srv".format(bin_root))
+ lib_dir = "{}/lib".format(bin_root)
+ for lib in os.listdir(lib_dir):
+ if lib.endswith(".so"):
+ self.fix_bin_or_dylib(os.path.join(lib_dir, lib))
+
with output(self.rustc_stamp()) as rust_stamp:
rust_stamp.write(key)
@@ -458,60 +462,73 @@ class RustBuild(object):
if not os.path.exists(rustc_cache):
os.makedirs(rustc_cache)
- base = self._download_url
- url = "dist/{}".format(key)
tarball = os.path.join(rustc_cache, filename)
if not os.path.exists(tarball):
get(
- base,
- "{}/{}".format(url, filename),
+ self.download_url,
+ "dist/{}/{}".format(key, filename),
tarball,
self.checksums_sha256,
verbose=self.verbose,
)
unpack(tarball, tarball_suffix, self.bin_root(), match=pattern, verbose=self.verbose)
- def fix_bin_or_dylib(self, fname):
- """Modifies the interpreter section of 'fname' to fix the dynamic linker,
- or the RPATH section, to fix the dynamic library search path
-
- This method is only required on NixOS and uses the PatchELF utility to
- change the interpreter/RPATH of ELF executables.
-
- Please see https://nixos.org/patchelf.html for more information
+ def should_fix_bins_and_dylibs(self):
+ """Whether or not `fix_bin_or_dylib` needs to be run; can only be True
+ on NixOS.
"""
- default_encoding = sys.getdefaultencoding()
- try:
- ostype = subprocess.check_output(
- ['uname', '-s']).strip().decode(default_encoding)
- except subprocess.CalledProcessError:
- return
- except OSError as reason:
- if getattr(reason, 'winerror', None) is not None:
- return
- raise reason
+ if self._should_fix_bins_and_dylibs is not None:
+ return self._should_fix_bins_and_dylibs
- if ostype != "Linux":
- return
+ def get_answer():
+ default_encoding = sys.getdefaultencoding()
+ try:
+ ostype = subprocess.check_output(
+ ['uname', '-s']).strip().decode(default_encoding)
+ except subprocess.CalledProcessError:
+ return False
+ except OSError as reason:
+ if getattr(reason, 'winerror', None) is not None:
+ return False
+ raise reason
+
+ if ostype != "Linux":
+ return False
+
+ # If the user has asked binaries to be patched for Nix, then
+ # don't check for NixOS or `/lib`.
+ if self.get_toml("patch-binaries-for-nix", "build") == "true":
+ return True
- # 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(l.strip() in ["ID=nixos", "ID='nixos'", 'ID="nixos"'] for l in f):
- return
+ if not any(l.strip() in ("ID=nixos", "ID='nixos'", 'ID="nixos"') for l in f):
+ return False
except FileNotFoundError:
- return
+ return False
if os.path.exists("/lib"):
- return
+ return False
+
+ return True
+
+ answer = self._should_fix_bins_and_dylibs = get_answer()
+ if answer:
+ print("info: You seem to be using Nix.")
+ return answer
- # 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)
+ def fix_bin_or_dylib(self, fname):
+ """Modifies the interpreter section of 'fname' to fix the dynamic linker,
+ or the RPATH section, to fix the dynamic library search path
+
+ This method is only required on NixOS and uses the PatchELF utility to
+ change the interpreter/RPATH of ELF executables.
+
+ Please see https://nixos.org/patchelf.html for more information
+ """
+ assert self._should_fix_bins_and_dylibs is True
+ print("attempting to patch", fname)
# Only build `.nix-deps` once.
nix_deps_dir = self.nix_deps_dir
@@ -666,8 +683,7 @@ class RustBuild(object):
config = self.get_toml(program)
if config:
return os.path.expanduser(config)
- return os.path.join(self.bin_root(), "bin", "{}{}".format(
- program, self.exe_suffix()))
+ return os.path.join(self.bin_root(), "bin", "{}{}".format(program, EXE_SUFFIX))
@staticmethod
def get_string(line):
@@ -692,13 +708,6 @@ class RustBuild(object):
return line[start + 1:end]
return None
- @staticmethod
- def exe_suffix():
- """Return a suffix for executables"""
- if sys.platform == 'win32':
- return '.exe'
- return ''
-
def bootstrap_binary(self):
"""Return the path of the bootstrap binary
@@ -710,9 +719,9 @@ class RustBuild(object):
"""
return os.path.join(self.build_dir, "bootstrap", "debug", "bootstrap")
- def build_bootstrap(self, color):
+ def build_bootstrap(self, color, verbose_count):
"""Build bootstrap"""
- print("Building rustbuild")
+ print("Building bootstrap")
build_dir = os.path.join(self.build_dir, "bootstrap")
if self.clean and os.path.exists(build_dir):
shutil.rmtree(build_dir)
@@ -757,7 +766,6 @@ class RustBuild(object):
if target_linker is not None:
env["RUSTFLAGS"] += " -C linker=" + target_linker
env["RUSTFLAGS"] += " -Wrust_2018_idioms -Wunused_lifetimes"
- env["RUSTFLAGS"] += " -Wsemicolon_in_expressions_from_macros"
if self.get_toml("deny-warnings", "rust") != "false":
env["RUSTFLAGS"] += " -Dwarnings"
@@ -768,8 +776,7 @@ class RustBuild(object):
self.cargo()))
args = [self.cargo(), "build", "--manifest-path",
os.path.join(self.rust_root, "src/bootstrap/Cargo.toml")]
- for _ in range(0, self.verbose):
- args.append("--verbose")
+ args.extend("--verbose" for _ in range(verbose_count))
if self.use_locked_deps:
args.append("--locked")
if self.use_vendored_sources:
@@ -777,6 +784,8 @@ class RustBuild(object):
if self.get_toml("metrics", "build"):
args.append("--features")
args.append("build-metrics")
+ if self.json_output:
+ args.append("--message-format=json")
if color == "always":
args.append("--color=always")
elif color == "never":
@@ -792,16 +801,7 @@ class RustBuild(object):
so use `self.build` where possible.
"""
config = self.get_toml('build')
- if config:
- return config
- return default_build_triple(self.verbose)
-
- 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 = url
+ return config or default_build_triple(self.verbose)
def check_vendored_status(self):
"""Check that vendoring is configured properly"""
@@ -834,32 +834,28 @@ class RustBuild(object):
if os.path.exists(cargo_dir):
shutil.rmtree(cargo_dir)
-def bootstrap(help_triggered):
- """Configure, fetch, build and run the initial bootstrap"""
-
- # If the user is asking for help, let them know that the whole download-and-build
- # process has to happen before anything is printed out.
- if help_triggered:
- print("info: Downloading and building bootstrap before processing --help")
- print(" command. See src/bootstrap/README.md for help with common")
- print(" commands.")
-
- parser = argparse.ArgumentParser(description='Build rust')
+def parse_args():
+ """Parse the command line arguments that the python script needs."""
+ parser = argparse.ArgumentParser(add_help=False)
+ parser.add_argument('-h', '--help', action='store_true')
parser.add_argument('--config')
parser.add_argument('--build-dir')
parser.add_argument('--build')
parser.add_argument('--color', choices=['always', 'never', 'auto'])
parser.add_argument('--clean', action='store_true')
+ parser.add_argument('--json-output', action='store_true')
parser.add_argument('-v', '--verbose', action='count', default=0)
- args = [a for a in sys.argv if a != '-h' and a != '--help']
- args, _ = parser.parse_known_args(args)
+ return parser.parse_known_args(sys.argv)[0]
+def bootstrap(args):
+ """Configure, fetch, build and run the initial bootstrap"""
# Configure initial bootstrap
build = RustBuild()
build.rust_root = os.path.abspath(os.path.join(__file__, '../../..'))
- build.verbose = args.verbose
+ build.verbose = args.verbose != 0
build.clean = args.clean
+ build.json_output = args.json_output
# Read from `--config`, then `RUST_BOOTSTRAP_CONFIG`, then `./config.toml`,
# then `config.toml` in the root directory.
@@ -886,12 +882,12 @@ def bootstrap(help_triggered):
with open(include_path) as included_toml:
build.config_toml += os.linesep + included_toml.read()
- config_verbose = build.get_toml('verbose', 'build')
- if config_verbose is not None:
- build.verbose = max(build.verbose, int(config_verbose))
+ verbose_count = args.verbose
+ config_verbose_count = build.get_toml('verbose', 'build')
+ if config_verbose_count is not None:
+ verbose_count = max(args.verbose, int(config_verbose_count))
build.use_vendored_sources = build.get_toml('vendor', 'build') == 'true'
-
build.use_locked_deps = build.get_toml('locked-deps', 'build') == 'true'
build.check_vendored_status()
@@ -903,8 +899,7 @@ def bootstrap(help_triggered):
data = json.load(f)
build.checksums_sha256 = data["checksums_sha256"]
build.stage0_compiler = Stage0Toolchain(data["compiler"])
-
- build.set_dist_environment(data["config"]["dist_server"])
+ build.download_url = os.getenv("RUSTUP_DIST_SERVER") or data["config"]["dist_server"]
build.build = args.build or build.build_triple()
@@ -914,7 +909,7 @@ def bootstrap(help_triggered):
# Fetch/build the bootstrap
build.download_toolchain()
sys.stdout.flush()
- build.build_bootstrap(args.color)
+ build.build_bootstrap(args.color, verbose_count)
sys.stdout.flush()
# Run the bootstrap
@@ -932,25 +927,34 @@ def main():
# x.py help <cmd> ...
if len(sys.argv) > 1 and sys.argv[1] == 'help':
- sys.argv = [sys.argv[0], '-h'] + sys.argv[2:]
+ sys.argv[1] = '-h'
+
+ args = parse_args()
+ help_triggered = args.help or len(sys.argv) == 1
- help_triggered = (
- '-h' in sys.argv) or ('--help' in sys.argv) or (len(sys.argv) == 1)
+ # If the user is asking for help, let them know that the whole download-and-build
+ # process has to happen before anything is printed out.
+ if help_triggered:
+ print(
+ "info: Downloading and building bootstrap before processing --help command.\n"
+ " See src/bootstrap/README.md for help with common commands."
+ )
+
+ exit_code = 0
+ success_word = "successfully"
try:
- bootstrap(help_triggered)
- if not help_triggered:
- print("Build completed successfully in {}".format(
- format_build_time(time() - start_time)))
+ bootstrap(args)
except (SystemExit, KeyboardInterrupt) as error:
if hasattr(error, 'code') and isinstance(error.code, int):
exit_code = error.code
else:
exit_code = 1
print(error)
- if not help_triggered:
- print("Build completed unsuccessfully in {}".format(
- format_build_time(time() - start_time)))
- sys.exit(exit_code)
+ success_word = "unsuccessfully"
+
+ if not help_triggered:
+ print("Build completed", success_word, "in", format_build_time(time() - start_time))
+ sys.exit(exit_code)
if __name__ == '__main__':
diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs
index b4fc1d4f2..b33fc02f4 100644
--- a/src/bootstrap/builder.rs
+++ b/src/bootstrap/builder.rs
@@ -780,7 +780,6 @@ impl<'a> Builder<'a> {
install::Clippy,
install::Miri,
install::LlvmTools,
- install::Analysis,
install::Src,
install::Rustc
),
@@ -793,7 +792,7 @@ impl<'a> Builder<'a> {
run::CollectLicenseMetadata,
run::GenerateCopyright,
),
- Kind::Setup => describe!(setup::Profile),
+ Kind::Setup => describe!(setup::Profile, setup::Hook, setup::Link, setup::Vscode),
Kind::Clean => describe!(clean::CleanAll, clean::Rustc, clean::Std),
// special-cased in Build::build()
Kind::Format => vec![],
@@ -1802,16 +1801,6 @@ impl<'a> Builder<'a> {
}
}
- if mode == Mode::Std && self.config.extended && compiler.is_final_stage(self) {
- rustflags.arg("-Zsave-analysis");
- cargo.env(
- "RUST_SAVE_ANALYSIS_CONFIG",
- "{\"output_file\": null,\"full_docs\": false,\
- \"pub_only\": true,\"reachable_only\": false,\
- \"distro_crate\": true,\"signatures\": false,\"borrow_data\": false}",
- );
- }
-
// If Control Flow Guard is enabled, pass the `control-flow-guard` flag to rustc
// when compiling the standard library, since this might be linked into the final outputs
// produced by rustc. Since this mitigation is only available on Windows, only enable it
@@ -1926,6 +1915,13 @@ impl<'a> Builder<'a> {
}
}
+ if matches!(mode, Mode::Std) {
+ if let Some(mir_opt_level) = self.config.rust_validate_mir_opts {
+ rustflags.arg("-Zvalidate-mir");
+ rustflags.arg(&format!("-Zmir-opt-level={}", mir_opt_level));
+ }
+ }
+
Cargo { command: cargo, rustflags, rustdocflags, allow_features }
}
diff --git a/src/bootstrap/builder/tests.rs b/src/bootstrap/builder/tests.rs
index d5fcd1075..3574f1118 100644
--- a/src/bootstrap/builder/tests.rs
+++ b/src/bootstrap/builder/tests.rs
@@ -557,6 +557,7 @@ mod dist {
rustfix_coverage: false,
pass: None,
run: None,
+ only_modified: false,
};
let build = Build::new(config);
@@ -627,6 +628,7 @@ mod dist {
rustfix_coverage: false,
pass: None,
run: None,
+ only_modified: false,
};
// Make sure rustfmt binary not being found isn't an error.
config.channel = "beta".to_string();
diff --git a/src/bootstrap/check.rs b/src/bootstrap/check.rs
index 4b8a58e87..cd1966713 100644
--- a/src/bootstrap/check.rs
+++ b/src/bootstrap/check.rs
@@ -58,9 +58,10 @@ fn args(builder: &Builder<'_>) -> Vec<String> {
clippy_lint_warn.iter().for_each(|v| clippy_lint_levels.push(format!("-W{}", v)));
clippy_lint_forbid.iter().for_each(|v| clippy_lint_levels.push(format!("-F{}", v)));
args.extend(clippy_lint_levels);
+ args.extend(builder.config.free_args.clone());
args
} else {
- vec![]
+ builder.config.free_args.clone()
}
}
@@ -99,11 +100,20 @@ impl Step for Std {
cargo_subcommand(builder.kind),
);
std_cargo(builder, target, compiler.stage, &mut cargo);
+ if matches!(builder.config.cmd, Subcommand::Fix { .. }) {
+ // By default, cargo tries to fix all targets. Tell it not to fix tests until we've added `test` to the sysroot.
+ cargo.arg("--lib");
+ }
- builder.info(&format!(
- "Checking stage{} library artifacts ({} -> {})",
- builder.top_stage, &compiler.host, target
- ));
+ let msg = if compiler.host == target {
+ format!("Checking stage{} library artifacts ({target})", builder.top_stage)
+ } else {
+ format!(
+ "Checking stage{} library artifacts ({} -> {})",
+ builder.top_stage, &compiler.host, target
+ )
+ };
+ builder.info(&msg);
run_cargo(
builder,
cargo,
@@ -157,10 +167,18 @@ impl Step for Std {
cargo.arg("-p").arg(krate.name);
}
- builder.info(&format!(
- "Checking stage{} library test/bench/example targets ({} -> {})",
- builder.top_stage, &compiler.host, target
- ));
+ let msg = if compiler.host == target {
+ format!(
+ "Checking stage{} library test/bench/example targets ({target})",
+ builder.top_stage
+ )
+ } else {
+ format!(
+ "Checking stage{} library test/bench/example targets ({} -> {})",
+ builder.top_stage, &compiler.host, target
+ )
+ };
+ builder.info(&msg);
run_cargo(
builder,
cargo,
@@ -234,10 +252,15 @@ impl Step for Rustc {
cargo.arg("-p").arg(krate.name);
}
- builder.info(&format!(
- "Checking stage{} compiler artifacts ({} -> {})",
- builder.top_stage, &compiler.host, target
- ));
+ let msg = if compiler.host == target {
+ format!("Checking stage{} compiler artifacts ({target})", builder.top_stage)
+ } else {
+ format!(
+ "Checking stage{} compiler artifacts ({} -> {})",
+ builder.top_stage, &compiler.host, target
+ )
+ };
+ builder.info(&msg);
run_cargo(
builder,
cargo,
@@ -294,10 +317,15 @@ impl Step for CodegenBackend {
.arg(builder.src.join(format!("compiler/rustc_codegen_{}/Cargo.toml", backend)));
rustc_cargo_env(builder, &mut cargo, target);
- builder.info(&format!(
- "Checking stage{} {} artifacts ({} -> {})",
- builder.top_stage, backend, &compiler.host.triple, target.triple
- ));
+ let msg = if compiler.host == target {
+ format!("Checking stage{} {} artifacts ({target})", builder.top_stage, backend)
+ } else {
+ format!(
+ "Checking stage{} {} library ({} -> {})",
+ builder.top_stage, backend, &compiler.host.triple, target.triple
+ )
+ };
+ builder.info(&msg);
run_cargo(
builder,
@@ -357,10 +385,15 @@ impl Step for RustAnalyzer {
cargo.arg("--benches");
}
- builder.info(&format!(
- "Checking stage{} {} artifacts ({} -> {})",
- compiler.stage, "rust-analyzer", &compiler.host.triple, target.triple
- ));
+ let msg = if compiler.host == target {
+ format!("Checking stage{} {} artifacts ({target})", compiler.stage, "rust-analyzer")
+ } else {
+ format!(
+ "Checking stage{} {} artifacts ({} -> {})",
+ compiler.stage, "rust-analyzer", &compiler.host.triple, target.triple
+ )
+ };
+ builder.info(&msg);
run_cargo(
builder,
cargo,
@@ -427,14 +460,18 @@ macro_rules! tool_check_step {
// NOTE: this doesn't enable lints for any other tools unless they explicitly add `#![warn(rustc::internal)]`
// See https://github.com/rust-lang/rust/pull/80573#issuecomment-754010776
cargo.rustflag("-Zunstable-options");
-
- builder.info(&format!(
- "Checking stage{} {} artifacts ({} -> {})",
- builder.top_stage,
- stringify!($name).to_lowercase(),
- &compiler.host.triple,
- target.triple
- ));
+ let msg = if compiler.host == target {
+ format!("Checking stage{} {} artifacts ({target})", builder.top_stage, stringify!($name).to_lowercase())
+ } else {
+ format!(
+ "Checking stage{} {} artifacts ({} -> {})",
+ builder.top_stage,
+ stringify!($name).to_lowercase(),
+ &compiler.host.triple,
+ target.triple
+ )
+ };
+ builder.info(&msg);
run_cargo(
builder,
cargo,
diff --git a/src/bootstrap/clean.rs b/src/bootstrap/clean.rs
index 468efc111..7ebd0a8f2 100644
--- a/src/bootstrap/clean.rs
+++ b/src/bootstrap/clean.rs
@@ -62,6 +62,7 @@ macro_rules! clean_crate_tree {
let target = compiler.host;
let mut cargo = builder.bare_cargo(compiler, $mode, target, "clean");
for krate in &*self.crates {
+ cargo.arg("-p");
cargo.arg(krate);
}
diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs
index 68d1db016..8b80dfc0f 100644
--- a/src/bootstrap/compile.rs
+++ b/src/bootstrap/compile.rs
@@ -16,7 +16,7 @@ use std::path::{Path, PathBuf};
use std::process::{Command, Stdio};
use std::str;
-use serde::Deserialize;
+use serde_derive::Deserialize;
use crate::builder::crate_description;
use crate::builder::Cargo;
@@ -111,10 +111,18 @@ impl Step for Std {
let compiler_to_use = builder.compiler_for(compiler.stage, compiler.host, target);
if compiler_to_use != compiler {
builder.ensure(Std::new(compiler_to_use, target));
- builder.info(&format!(
- "Uplifting stage1 library ({} -> {})",
- compiler_to_use.host, target
- ));
+ let msg = if compiler_to_use.host == target {
+ format!(
+ "Uplifting library (stage{} -> stage{})",
+ compiler_to_use.stage, compiler.stage
+ )
+ } else {
+ format!(
+ "Uplifting library (stage{}:{} -> stage{}:{})",
+ compiler_to_use.stage, compiler_to_use.host, compiler.stage, target
+ )
+ };
+ builder.info(&msg);
// Even if we're not building std this stage, the new sysroot must
// still contain the third party objects needed by various targets.
@@ -134,13 +142,23 @@ impl Step for Std {
cargo.arg("-p").arg(krate);
}
- builder.info(&format!(
- "Building{} stage{} library artifacts ({} -> {})",
- crate_description(&self.crates),
- compiler.stage,
- &compiler.host,
- target,
- ));
+ let msg = if compiler.host == target {
+ format!(
+ "Building{} stage{} library artifacts ({}) ",
+ crate_description(&self.crates),
+ compiler.stage,
+ compiler.host
+ )
+ } else {
+ format!(
+ "Building{} stage{} library artifacts ({} -> {})",
+ crate_description(&self.crates),
+ compiler.stage,
+ compiler.host,
+ target,
+ )
+ };
+ builder.info(&msg);
run_cargo(
builder,
cargo,
@@ -379,6 +397,9 @@ pub fn std_cargo(builder: &Builder<'_>, target: TargetSelection, stage: u32, car
if stage >= 1 {
cargo.rustflag("-Cembed-bitcode=yes");
}
+ if builder.config.rust_lto == RustcLto::Off {
+ cargo.rustflag("-Clto=off");
+ }
// By default, rustc does not include unwind tables unless they are required
// for a particular target. They are not required by RISC-V targets, but
@@ -435,10 +456,6 @@ impl Step for StdLink {
let compiler = self.compiler;
let target_compiler = self.target_compiler;
let target = self.target;
- builder.info(&format!(
- "Copying stage{} library from stage{} ({} -> {} / {})",
- target_compiler.stage, compiler.stage, &compiler.host, target_compiler.host, target
- ));
let libdir = builder.sysroot_libdir(target_compiler, target);
let hostdir = builder.sysroot_libdir(target_compiler, compiler.host);
add_to_sysroot(builder, &libdir, &hostdir, &libstd_stamp(builder, compiler, target));
@@ -464,7 +481,12 @@ fn copy_sanitizers(
let dst = libdir.join(&runtime.name);
builder.copy(&runtime.path, &dst);
- if target == "x86_64-apple-darwin" || target == "aarch64-apple-darwin" {
+ if target == "x86_64-apple-darwin"
+ || target == "aarch64-apple-darwin"
+ || target == "aarch64-apple-ios"
+ || target == "aarch64-apple-ios-sim"
+ || target == "x86_64-apple-ios"
+ {
// Update the library’s install name to reflect that it has been renamed.
apple_darwin_update_library_name(&dst, &format!("@rpath/{}", &runtime.name));
// Upon renaming the install name, the code signature of the file will invalidate,
@@ -641,8 +663,22 @@ impl Step for Rustc {
let compiler_to_use = builder.compiler_for(compiler.stage, compiler.host, target);
if compiler_to_use != compiler {
builder.ensure(Rustc::new(compiler_to_use, target));
- builder
- .info(&format!("Uplifting stage1 rustc ({} -> {})", builder.config.build, target));
+ let msg = if compiler_to_use.host == target {
+ format!(
+ "Uplifting rustc (stage{} -> stage{})",
+ compiler_to_use.stage,
+ compiler.stage + 1
+ )
+ } else {
+ format!(
+ "Uplifting rustc (stage{}:{} -> stage{}:{})",
+ compiler_to_use.stage,
+ compiler_to_use.host,
+ compiler.stage + 1,
+ target
+ )
+ };
+ builder.info(&msg);
builder.ensure(RustcLink::from_rustc(self, compiler_to_use));
return;
}
@@ -722,6 +758,13 @@ impl Step for Rustc {
cargo.rustflag("-Cembed-bitcode=yes");
}
RustcLto::ThinLocal => { /* Do nothing, this is the default */ }
+ RustcLto::Off => {
+ cargo.rustflag("-Clto=off");
+ }
+ }
+ } else {
+ if builder.config.rust_lto == RustcLto::Off {
+ cargo.rustflag("-Clto=off");
}
}
@@ -729,13 +772,24 @@ impl Step for Rustc {
cargo.arg("-p").arg(krate);
}
- builder.info(&format!(
- "Building{} stage{} compiler artifacts ({} -> {})",
- crate_description(&self.crates),
- compiler.stage,
- &compiler.host,
- target,
- ));
+ let msg = if compiler.host == target {
+ format!(
+ "Building{} compiler artifacts (stage{} -> stage{})",
+ crate_description(&self.crates),
+ compiler.stage,
+ compiler.stage + 1
+ )
+ } else {
+ format!(
+ "Building{} compiler artifacts (stage{}:{} -> stage{}:{})",
+ crate_description(&self.crates),
+ compiler.stage,
+ compiler.host,
+ compiler.stage + 1,
+ target,
+ )
+ };
+ builder.info(&msg);
run_cargo(
builder,
cargo,
@@ -919,10 +973,6 @@ impl Step for RustcLink {
let compiler = self.compiler;
let target_compiler = self.target_compiler;
let target = self.target;
- builder.info(&format!(
- "Copying stage{} rustc from stage{} ({} -> {} / {})",
- target_compiler.stage, compiler.stage, &compiler.host, target_compiler.host, target
- ));
add_to_sysroot(
builder,
&builder.sysroot_libdir(target_compiler, target),
@@ -996,10 +1046,15 @@ impl Step for CodegenBackend {
let tmp_stamp = out_dir.join(".tmp.stamp");
- builder.info(&format!(
- "Building stage{} codegen backend {} ({} -> {})",
- compiler.stage, backend, &compiler.host, target
- ));
+ let msg = if compiler.host == target {
+ format!("Building stage{} codegen backend {}", compiler.stage, backend)
+ } else {
+ format!(
+ "Building stage{} codegen backend {} ({} -> {})",
+ compiler.stage, backend, compiler.host, target
+ )
+ };
+ builder.info(&msg);
let files = run_cargo(builder, cargo, vec![], &tmp_stamp, vec![], false, false);
if builder.config.dry_run() {
return;
@@ -1305,7 +1360,12 @@ impl Step for Assemble {
let stage = target_compiler.stage;
let host = target_compiler.host;
- builder.info(&format!("Assembling stage{} compiler ({})", stage, host));
+ let msg = if build_compiler.host == host {
+ format!("Assembling stage{} compiler", stage)
+ } else {
+ format!("Assembling stage{} compiler ({})", stage, host)
+ };
+ builder.info(&msg);
// Link in all dylibs to the libdir
let stamp = librustc_stamp(builder, build_compiler, target_compiler.host);
diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs
index b41d60d51..05e742549 100644
--- a/src/bootstrap/config.rs
+++ b/src/bootstrap/config.rs
@@ -25,6 +25,7 @@ use crate::flags::{Color, Flags};
use crate::util::{exe, output, t};
use once_cell::sync::OnceCell;
use serde::{Deserialize, Deserializer};
+use serde_derive::Deserialize;
macro_rules! check_ci_llvm {
($name:expr) => {
@@ -65,6 +66,7 @@ pub struct Config {
pub verbose: usize,
pub submodules: Option<bool>,
pub compiler_docs: bool,
+ pub library_docs_private_items: bool,
pub docs_minification: bool,
pub docs: bool,
pub locked_deps: bool,
@@ -96,6 +98,10 @@ pub struct Config {
pub cmd: Subcommand,
pub incremental: bool,
pub dry_run: DryRun,
+ /// Arguments appearing after `--` to be forwarded to tools,
+ /// e.g. `--fix-broken` or test arguments.
+ pub free_args: Vec<String>,
+
/// `None` if we shouldn't download CI compiler artifacts, or the commit to download if we should.
#[cfg(not(test))]
download_rustc_commit: Option<String>,
@@ -168,6 +174,7 @@ pub struct Config {
pub rust_profile_use: Option<String>,
pub rust_profile_generate: Option<String>,
pub rust_lto: RustcLto,
+ pub rust_validate_mir_opts: Option<u32>,
pub llvm_profile_use: Option<String>,
pub llvm_profile_generate: bool,
pub llvm_libunwind_default: Option<LlvmLibunwind>,
@@ -332,8 +339,9 @@ impl SplitDebuginfo {
}
/// LTO mode used for compiling rustc itself.
-#[derive(Default, Clone)]
+#[derive(Default, Clone, PartialEq)]
pub enum RustcLto {
+ Off,
#[default]
ThinLocal,
Thin,
@@ -348,6 +356,7 @@ impl std::str::FromStr for RustcLto {
"thin-local" => Ok(RustcLto::ThinLocal),
"thin" => Ok(RustcLto::Thin),
"fat" => Ok(RustcLto::Fat),
+ "off" => Ok(RustcLto::Off),
_ => Err(format!("Invalid value for rustc LTO: {}", s)),
}
}
@@ -606,6 +615,7 @@ define_config! {
rustfmt: Option<PathBuf> = "rustfmt",
docs: Option<bool> = "docs",
compiler_docs: Option<bool> = "compiler-docs",
+ library_docs_private_items: Option<bool> = "library-docs-private-items",
docs_minification: Option<bool> = "docs-minification",
submodules: Option<bool> = "submodules",
gdb: Option<String> = "gdb",
@@ -762,6 +772,7 @@ define_config! {
// ignored; this is set from an env var set by bootstrap.py
download_rustc: Option<StringOrBool> = "download-rustc",
lto: Option<String> = "lto",
+ validate_mir_opts: Option<u32> = "validate-mir-opts",
}
}
@@ -862,6 +873,7 @@ impl Config {
config.keep_stage = flags.keep_stage;
config.keep_stage_std = flags.keep_stage_std;
config.color = flags.color;
+ config.free_args = flags.free_args.clone().unwrap_or_default();
if let Some(value) = flags.deny_warnings {
config.deny_warnings = value;
}
@@ -965,6 +977,9 @@ impl Config {
config.changelog_seen = toml.changelog_seen;
let build = toml.build.unwrap_or_default();
+ if let Some(file_build) = build.build {
+ config.build = TargetSelection::from_user(&file_build);
+ };
set(&mut config.out, flags.build_dir.or_else(|| build.build_dir.map(PathBuf::from)));
// NOTE: Bootstrap spawns various commands with different working directories.
@@ -1015,6 +1030,7 @@ impl Config {
config.submodules = build.submodules;
set(&mut config.low_priority, build.low_priority);
set(&mut config.compiler_docs, build.compiler_docs);
+ set(&mut config.library_docs_private_items, build.library_docs_private_items);
set(&mut config.docs_minification, build.docs_minification);
set(&mut config.docs, build.docs);
set(&mut config.locked_deps, build.locked_deps);
@@ -1136,6 +1152,7 @@ impl Config {
.as_deref()
.map(|value| RustcLto::from_str(value).unwrap())
.unwrap_or_default();
+ config.rust_validate_mir_opts = rust.validate_mir_opts;
} else {
config.rust_profile_use = flags.rust_profile_use;
config.rust_profile_generate = flags.rust_profile_generate;
@@ -1302,15 +1319,6 @@ impl Config {
} else {
RustfmtState::Unavailable
};
- } else {
- // If using a system toolchain for bootstrapping, see if that has rustfmt available.
- let host = config.build;
- let rustfmt_path = config.initial_rustc.with_file_name(exe("rustfmt", host));
- let bin_root = config.out.join(host.triple).join("stage0");
- if !rustfmt_path.starts_with(&bin_root) {
- // Using a system-provided toolchain; we shouldn't download rustfmt.
- *config.initial_rustfmt.borrow_mut() = RustfmtState::SystemToolchain(rustfmt_path);
- }
}
// Now that we've reached the end of our configuration, infer the
diff --git a/src/bootstrap/config/tests.rs b/src/bootstrap/config/tests.rs
index c30c91317..5a105007f 100644
--- a/src/bootstrap/config/tests.rs
+++ b/src/bootstrap/config/tests.rs
@@ -11,6 +11,11 @@ fn parse(config: &str) -> Config {
#[test]
fn download_ci_llvm() {
+ if crate::native::is_ci_llvm_modified(&parse("")) {
+ eprintln!("Detected LLVM as non-available: running in CI and modified LLVM in this change");
+ return;
+ }
+
let parse_llvm = |s| parse(s).llvm_from_ci;
let if_available = parse_llvm("llvm.download-ci-llvm = \"if-available\"");
@@ -19,6 +24,13 @@ fn download_ci_llvm() {
assert_eq!(parse_llvm(""), if_available);
assert_eq!(parse_llvm("rust.channel = \"dev\""), if_available);
assert!(!parse_llvm("rust.channel = \"stable\""));
+ assert!(parse_llvm("build.build = \"x86_64-unknown-linux-gnu\""));
+ assert!(parse_llvm(
+ "llvm.assertions = true \r\n build.build = \"x86_64-unknown-linux-gnu\" \r\n llvm.download-ci-llvm = \"if-available\""
+ ));
+ assert!(!parse_llvm(
+ "llvm.assertions = true \r\n build.build = \"aarch64-apple-darwin\" \r\n llvm.download-ci-llvm = \"if-available\""
+ ));
}
// FIXME: add test for detecting `src` and `out`
diff --git a/src/bootstrap/configure.py b/src/bootstrap/configure.py
index 0af329e70..ab3d08292 100755
--- a/src/bootstrap/configure.py
+++ b/src/bootstrap/configure.py
@@ -379,8 +379,14 @@ cur_section = None
sections[None] = []
section_order = [None]
targets = {}
+top_level_keys = []
for line in open(rust_dir + '/config.toml.example').read().split("\n"):
+ if cur_section == None:
+ if line.count('=') == 1:
+ top_level_key = line.split('=')[0]
+ top_level_key = top_level_key.strip(' #')
+ top_level_keys.append(top_level_key)
if line.startswith('['):
cur_section = line[1:-1]
if cur_section.startswith('target'):
@@ -436,6 +442,8 @@ def to_toml(value):
return value
else:
return "'" + value + "'"
+ elif isinstance(value, dict):
+ return "{" + ", ".join(map(lambda a: "{} = {}".format(to_toml(a[0]), to_toml(a[1])), value.items())) + "}"
else:
raise RuntimeError('no toml')
@@ -459,12 +467,22 @@ def configure_section(lines, config):
raise RuntimeError("failed to find config line for {}".format(key))
-for section_key in config:
- section_config = config[section_key]
- if section_key not in sections:
- raise RuntimeError("config key {} not in sections".format(section_key))
+def configure_top_level_key(lines, top_level_key, value):
+ for i, line in enumerate(lines):
+ if line.startswith('#' + top_level_key + ' = ') or line.startswith(top_level_key + ' = '):
+ lines[i] = "{} = {}".format(top_level_key, value)
+ return
- if section_key == 'target':
+ raise RuntimeError("failed to find config line for {}".format(top_level_key))
+
+
+for section_key, section_config in config.items():
+ if section_key not in sections and section_key not in top_level_keys:
+ raise RuntimeError("config key {} not in sections or top_level_keys".format(section_key))
+ if section_key in top_level_keys:
+ configure_top_level_key(sections[None], section_key, section_config)
+
+ elif section_key == 'target':
for target in section_config:
configure_section(targets[target], section_config[target])
else:
diff --git a/src/bootstrap/defaults/config.compiler.toml b/src/bootstrap/defaults/config.compiler.toml
index 2f4ccb825..b98b13119 100644
--- a/src/bootstrap/defaults/config.compiler.toml
+++ b/src/bootstrap/defaults/config.compiler.toml
@@ -12,6 +12,8 @@ debug-logging = true
incremental = true
# Print backtrace on internal compiler errors during bootstrap
backtrace-on-ice = true
+# Make the compiler and standard library faster to build, at the expense of a ~20% runtime slowdown.
+lto = "off"
[llvm]
# Will download LLVM from CI if available on your platform.
diff --git a/src/bootstrap/defaults/config.library.toml b/src/bootstrap/defaults/config.library.toml
index 7bc054d3a..f362c4111 100644
--- a/src/bootstrap/defaults/config.library.toml
+++ b/src/bootstrap/defaults/config.library.toml
@@ -8,6 +8,8 @@ bench-stage = 0
[rust]
# This greatly increases the speed of rebuilds, especially when there are only minor changes. However, it makes the initial build slightly slower.
incremental = true
+# Make the compiler and standard library faster to build, at the expense of a ~20% runtime slowdown.
+lto = "off"
[llvm]
# Will download LLVM from CI if available on your platform.
diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs
index 6594b23c5..9b2b54961 100644
--- a/src/bootstrap/dist.rs
+++ b/src/bootstrap/dist.rs
@@ -12,6 +12,7 @@ use std::collections::HashSet;
use std::env;
use std::ffi::OsStr;
use std::fs;
+use std::io::Write;
use std::path::{Path, PathBuf};
use std::process::Command;
@@ -392,19 +393,29 @@ impl Step for Rustc {
t!(fs::create_dir_all(image.join("bin")));
builder.cp_r(&src.join("bin"), &image.join("bin"));
- builder.install(&builder.rustdoc(compiler), &image.join("bin"), 0o755);
+ if builder
+ .config
+ .tools
+ .as_ref()
+ .map_or(true, |tools| tools.iter().any(|tool| tool == "rustdoc"))
+ {
+ let rustdoc = builder.rustdoc(compiler);
+ builder.install(&rustdoc, &image.join("bin"), 0o755);
+ }
- let ra_proc_macro_srv = builder
- .ensure(tool::RustAnalyzerProcMacroSrv {
+ if let Some(ra_proc_macro_srv) = builder.ensure_if_default(
+ tool::RustAnalyzerProcMacroSrv {
compiler: builder.compiler_for(
compiler.stage,
builder.config.build,
compiler.host,
),
target: compiler.host,
- })
- .expect("rust-analyzer-proc-macro-server always builds");
- builder.install(&ra_proc_macro_srv, &image.join("libexec"), 0o755);
+ },
+ builder.kind,
+ ) {
+ builder.install(&ra_proc_macro_srv, &image.join("libexec"), 0o755);
+ }
let libdir_relative = builder.libdir_relative(compiler);
@@ -743,7 +754,7 @@ impl Step for Analysis {
});
}
- /// Creates a tarball of save-analysis metadata, if available.
+ /// Creates a tarball of (degenerate) save-analysis metadata, if available.
fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
let compiler = self.compiler;
let target = self.target;
@@ -751,7 +762,6 @@ impl Step for Analysis {
return None;
}
- builder.ensure(compile::Std::new(compiler, target));
let src = builder
.stage_out(compiler, Mode::Std)
.join(target.triple)
@@ -759,6 +769,13 @@ impl Step for Analysis {
.join("deps")
.join("save-analysis");
+ // Write a file indicating that this component has been removed.
+ t!(std::fs::create_dir_all(&src));
+ let mut removed = src.clone();
+ removed.push("removed.json");
+ let mut f = t!(std::fs::File::create(removed));
+ t!(write!(f, r#"{{ "warning": "The `rust-analysis` component has been removed." }}"#));
+
let mut tarball = Tarball::new(builder, "rust-analysis", &target.triple);
tarball.include_target_in_component_name(true);
tarball.add_dir(src, format!("lib/rustlib/{}/analysis", target.triple));
diff --git a/src/bootstrap/doc.rs b/src/bootstrap/doc.rs
index 9bad9046e..cc80763ef 100644
--- a/src/bootstrap/doc.rs
+++ b/src/bootstrap/doc.rs
@@ -62,6 +62,7 @@ macro_rules! book {
target: self.target,
name: INTERNER.intern_str($book_name),
src: INTERNER.intern_path(builder.src.join($path)),
+ parent: Some(self),
})
}
}
@@ -119,18 +120,20 @@ impl Step for UnstableBook {
target: self.target,
name: INTERNER.intern_str("unstable-book"),
src: INTERNER.intern_path(builder.md_doc_out(self.target).join("unstable-book")),
+ parent: Some(self),
})
}
}
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
-struct RustbookSrc {
+struct RustbookSrc<P: Step> {
target: TargetSelection,
name: Interned<String>,
src: Interned<PathBuf>,
+ parent: Option<P>,
}
-impl Step for RustbookSrc {
+impl<P: Step> Step for RustbookSrc<P> {
type Output = ();
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
@@ -152,13 +155,18 @@ impl Step for RustbookSrc {
let index = out.join("index.html");
let rustbook = builder.tool_exe(Tool::Rustbook);
let mut rustbook_cmd = builder.tool_cmd(Tool::Rustbook);
- if builder.config.dry_run() || up_to_date(&src, &index) && up_to_date(&rustbook, &index) {
- return;
+
+ if !builder.config.dry_run() && !(up_to_date(&src, &index) || up_to_date(&rustbook, &index))
+ {
+ builder.info(&format!("Rustbook ({}) - {}", target, name));
+ let _ = fs::remove_dir_all(&out);
+
+ builder.run(rustbook_cmd.arg("build").arg(&src).arg("-d").arg(out));
}
- builder.info(&format!("Rustbook ({}) - {}", target, name));
- let _ = fs::remove_dir_all(&out);
- builder.run(rustbook_cmd.arg("build").arg(&src).arg("-d").arg(out));
+ if self.parent.is_some() {
+ builder.maybe_open_in_browser::<P>(index)
+ }
}
}
@@ -205,6 +213,7 @@ impl Step for TheBook {
target,
name: INTERNER.intern_str("book"),
src: INTERNER.intern_path(builder.src.join(&relative_path)),
+ parent: Some(self),
});
// building older edition redirects
@@ -213,6 +222,9 @@ impl Step for TheBook {
target,
name: INTERNER.intern_string(format!("book/{}", edition)),
src: INTERNER.intern_path(builder.src.join(&relative_path).join(edition)),
+ // There should only be one book that is marked as the parent for each target, so
+ // treat the other editions as not having a parent.
+ parent: Option::<Self>::None,
});
}
@@ -228,10 +240,6 @@ impl Step for TheBook {
invoke_rustdoc(builder, compiler, &shared_assets, target, path);
}
-
- let out = builder.doc_out(target);
- let index = out.join("book").join("index.html");
- builder.maybe_open_in_browser::<Self>(index);
}
}
@@ -597,6 +605,9 @@ fn doc_std(
.arg("--resource-suffix")
.arg(&builder.version)
.args(extra_args);
+ if builder.config.library_docs_private_items {
+ cargo.arg("--document-private-items").arg("--document-hidden-items");
+ }
builder.run(&mut cargo.into());
};
@@ -1029,10 +1040,7 @@ impl Step for RustcBook {
target: self.target,
name: INTERNER.intern_str("rustc"),
src: INTERNER.intern_path(out_base),
+ parent: Some(self),
});
-
- let out = builder.doc_out(self.target);
- let index = out.join("rustc").join("index.html");
- builder.maybe_open_in_browser::<Self>(index);
}
}
diff --git a/src/bootstrap/download.rs b/src/bootstrap/download.rs
index 6ae283f32..d1e2149d3 100644
--- a/src/bootstrap/download.rs
+++ b/src/bootstrap/download.rs
@@ -18,6 +18,8 @@ use crate::{
Config,
};
+static SHOULD_FIX_BINS_AND_DYLIBS: OnceCell<bool> = OnceCell::new();
+
/// Generic helpers that are useful anywhere in bootstrap.
impl Config {
pub fn is_verbose(&self) -> bool {
@@ -70,53 +72,61 @@ impl Config {
check_run(cmd, self.is_verbose())
}
- /// Modifies the interpreter section of 'fname' to fix the dynamic linker,
- /// or the RPATH section, to fix the dynamic library search path
- ///
- /// This is only required on NixOS and uses the PatchELF utility to
- /// change the interpreter/RPATH of ELF executables.
- ///
- /// Please see https://nixos.org/patchelf.html for more information
- fn fix_bin_or_dylib(&self, fname: &Path) {
- // FIXME: cache NixOS detection?
- match Command::new("uname").arg("-s").stderr(Stdio::inherit()).output() {
- Err(_) => return,
- Ok(output) if !output.status.success() => return,
- Ok(output) => {
- let mut s = output.stdout;
- if s.last() == Some(&b'\n') {
- s.pop();
- }
- if s != b"Linux" {
- return;
+ /// Whether or not `fix_bin_or_dylib` needs to be run; can only be true
+ /// on NixOS
+ fn should_fix_bins_and_dylibs(&self) -> bool {
+ let val = *SHOULD_FIX_BINS_AND_DYLIBS.get_or_init(|| {
+ match Command::new("uname").arg("-s").stderr(Stdio::inherit()).output() {
+ Err(_) => return false,
+ Ok(output) if !output.status.success() => return false,
+ Ok(output) => {
+ let mut os_name = output.stdout;
+ if os_name.last() == Some(&b'\n') {
+ os_name.pop();
+ }
+ if os_name != b"Linux" {
+ return false;
+ }
}
}
- }
- // If the user has asked binaries to be patched for Nix, then
- // don't check for NixOS or `/lib`, just continue to the patching.
- // NOTE: this intentionally comes after the Linux check:
- // - patchelf only works with ELF files, so no need to run it on Mac or Windows
- // - On other Unix systems, there is no stable syscall interface, so Nix doesn't manage the global libc.
- if !self.patch_binaries_for_nix {
+ // If the user has asked binaries to be patched for Nix, then
+ // don't check for NixOS or `/lib`.
+ // NOTE: this intentionally comes after the Linux check:
+ // - patchelf only works with ELF files, so no need to run it on Mac or Windows
+ // - On other Unix systems, there is no stable syscall interface, so Nix doesn't manage the global libc.
+ if self.patch_binaries_for_nix {
+ return true;
+ }
+
// Use `/etc/os-release` instead of `/etc/NIXOS`.
// The latter one does not exist on NixOS when using tmpfs as root.
- const NIX_IDS: &[&str] = &["ID=nixos", "ID='nixos'", "ID=\"nixos\""];
- let os_release = match File::open("/etc/os-release") {
- Err(e) if e.kind() == ErrorKind::NotFound => return,
+ let is_nixos = match File::open("/etc/os-release") {
+ Err(e) if e.kind() == ErrorKind::NotFound => false,
Err(e) => panic!("failed to access /etc/os-release: {}", e),
- Ok(f) => f,
+ Ok(os_release) => BufReader::new(os_release).lines().any(|l| {
+ let l = l.expect("reading /etc/os-release");
+ matches!(l.trim(), "ID=nixos" | "ID='nixos'" | "ID=\"nixos\"")
+ }),
};
- if !BufReader::new(os_release).lines().any(|l| NIX_IDS.contains(&t!(l).trim())) {
- return;
- }
- if Path::new("/lib").exists() {
- return;
- }
+ is_nixos && !Path::new("/lib").exists()
+ });
+ if val {
+ println!("info: You seem to be using Nix.");
}
+ val
+ }
- // At this point we're pretty sure the user is running NixOS or using Nix
- println!("info: you seem to be using Nix. Attempting to patch {}", fname.display());
+ /// Modifies the interpreter section of 'fname' to fix the dynamic linker,
+ /// or the RPATH section, to fix the dynamic library search path
+ ///
+ /// This is only required on NixOS and uses the PatchELF utility to
+ /// change the interpreter/RPATH of ELF executables.
+ ///
+ /// Please see https://nixos.org/patchelf.html for more information
+ fn fix_bin_or_dylib(&self, fname: &Path) {
+ assert_eq!(SHOULD_FIX_BINS_AND_DYLIBS.get(), Some(&true));
+ println!("attempting to patch {}", fname.display());
// Only build `.nix-deps` once.
static NIX_DEPS_DIR: OnceCell<PathBuf> = OnceCell::new();
@@ -163,8 +173,7 @@ impl Config {
// appear to have this (even when `../lib` is redundant).
// NOTE: there are only two paths here, delimited by a `:`
let mut entries = OsString::from("$ORIGIN/../lib:");
- entries.push(t!(fs::canonicalize(nix_deps_dir)));
- entries.push("/lib");
+ entries.push(t!(fs::canonicalize(nix_deps_dir)).join("lib"));
entries
};
patchelf.args(&[OsString::from("--set-rpath"), rpath_entries]);
@@ -211,10 +220,10 @@ impl Config {
"--retry",
"3",
"-Sf",
- "-o",
]);
- curl.arg(tempfile);
curl.arg(url);
+ let f = File::create(tempfile).unwrap();
+ curl.stdout(Stdio::from(f));
if !self.check_run(&mut curl) {
if self.build.contains("windows-msvc") {
println!("Fallback to PowerShell");
@@ -318,18 +327,39 @@ impl Config {
let channel = format!("{version}-{date}");
let host = self.build;
- let rustfmt_path = self.initial_rustc.with_file_name(exe("rustfmt", host));
- let bin_root = self.out.join(host.triple).join("stage0");
+ let bin_root = self.out.join(host.triple).join("rustfmt");
+ let rustfmt_path = bin_root.join("bin").join(exe("rustfmt", host));
let rustfmt_stamp = bin_root.join(".rustfmt-stamp");
if rustfmt_path.exists() && !program_out_of_date(&rustfmt_stamp, &channel) {
return Some(rustfmt_path);
}
- let filename = format!("rustfmt-{version}-{build}.tar.xz", build = host.triple);
- self.download_component(DownloadSource::Dist, filename, "rustfmt-preview", &date, "stage0");
-
- self.fix_bin_or_dylib(&bin_root.join("bin").join("rustfmt"));
- self.fix_bin_or_dylib(&bin_root.join("bin").join("cargo-fmt"));
+ self.download_component(
+ DownloadSource::Dist,
+ format!("rustfmt-{version}-{build}.tar.xz", build = host.triple),
+ "rustfmt-preview",
+ &date,
+ "rustfmt",
+ );
+ self.download_component(
+ DownloadSource::Dist,
+ format!("rustc-{version}-{build}.tar.xz", build = host.triple),
+ "rustc",
+ &date,
+ "rustfmt",
+ );
+
+ if self.should_fix_bins_and_dylibs() {
+ self.fix_bin_or_dylib(&bin_root.join("bin").join("rustfmt"));
+ self.fix_bin_or_dylib(&bin_root.join("bin").join("cargo-fmt"));
+ let lib_dir = bin_root.join("lib");
+ for lib in t!(fs::read_dir(&lib_dir), lib_dir.display().to_string()) {
+ let lib = t!(lib);
+ if lib.path().extension() == Some(OsStr::new("so")) {
+ self.fix_bin_or_dylib(&lib.path());
+ }
+ }
+ }
self.create(&rustfmt_stamp, &channel);
Some(rustfmt_path)
@@ -358,16 +388,21 @@ impl Config {
let filename = format!("rust-src-{version}.tar.xz");
self.download_ci_component(filename, "rust-src", commit);
- self.fix_bin_or_dylib(&bin_root.join("bin").join("rustc"));
- self.fix_bin_or_dylib(&bin_root.join("bin").join("rustdoc"));
- self.fix_bin_or_dylib(&bin_root.join("libexec").join("rust-analyzer-proc-macro-srv"));
- let lib_dir = bin_root.join("lib");
- for lib in t!(fs::read_dir(&lib_dir), lib_dir.display().to_string()) {
- let lib = t!(lib);
- if lib.path().extension() == Some(OsStr::new("so")) {
- self.fix_bin_or_dylib(&lib.path());
+ if self.should_fix_bins_and_dylibs() {
+ self.fix_bin_or_dylib(&bin_root.join("bin").join("rustc"));
+ self.fix_bin_or_dylib(&bin_root.join("bin").join("rustdoc"));
+ self.fix_bin_or_dylib(
+ &bin_root.join("libexec").join("rust-analyzer-proc-macro-srv"),
+ );
+ let lib_dir = bin_root.join("lib");
+ for lib in t!(fs::read_dir(&lib_dir), lib_dir.display().to_string()) {
+ let lib = t!(lib);
+ if lib.path().extension() == Some(OsStr::new("so")) {
+ self.fix_bin_or_dylib(&lib.path());
+ }
}
}
+
t!(fs::write(rustc_stamp, commit));
}
}
@@ -459,8 +494,10 @@ impl Config {
let key = format!("{}{}", llvm_sha, self.llvm_assertions);
if program_out_of_date(&llvm_stamp, &key) && !self.dry_run() {
self.download_ci_llvm(&llvm_sha);
- for entry in t!(fs::read_dir(llvm_root.join("bin"))) {
- self.fix_bin_or_dylib(&t!(entry).path());
+ if self.should_fix_bins_and_dylibs() {
+ for entry in t!(fs::read_dir(llvm_root.join("bin"))) {
+ self.fix_bin_or_dylib(&t!(entry).path());
+ }
}
// Update the timestamp of llvm-config to force rustc_llvm to be
@@ -475,13 +512,16 @@ impl Config {
let llvm_config = llvm_root.join("bin").join(exe("llvm-config", self.build));
t!(filetime::set_file_times(&llvm_config, now, now));
- let llvm_lib = llvm_root.join("lib");
- for entry in t!(fs::read_dir(&llvm_lib)) {
- let lib = t!(entry).path();
- if lib.extension().map_or(false, |ext| ext == "so") {
- self.fix_bin_or_dylib(&lib);
+ if self.should_fix_bins_and_dylibs() {
+ let llvm_lib = llvm_root.join("lib");
+ for entry in t!(fs::read_dir(&llvm_lib)) {
+ let lib = t!(entry).path();
+ if lib.extension().map_or(false, |ext| ext == "so") {
+ self.fix_bin_or_dylib(&lib);
+ }
}
}
+
t!(fs::write(llvm_stamp, key));
}
}
diff --git a/src/bootstrap/flags.rs b/src/bootstrap/flags.rs
index 52c3dc0bf..9d1504c34 100644
--- a/src/bootstrap/flags.rs
+++ b/src/bootstrap/flags.rs
@@ -80,6 +80,10 @@ pub struct Flags {
pub llvm_profile_generate: bool,
pub llvm_bolt_profile_generate: bool,
pub llvm_bolt_profile_use: Option<String>,
+
+ /// Arguments appearing after `--` to be forwarded to tools,
+ /// e.g. `--fix-broken` or test arguments.
+ pub free_args: Option<Vec<String>>,
}
#[derive(Debug)]
@@ -124,6 +128,7 @@ pub enum Subcommand {
fail_fast: bool,
doc_tests: DocTests,
rustfix_coverage: bool,
+ only_modified: bool,
},
Bench {
paths: Vec<PathBuf>,
@@ -156,6 +161,12 @@ impl Default for Subcommand {
impl Flags {
pub fn parse(args: &[String]) -> Flags {
+ let (args, free_args) = if let Some(pos) = args.iter().position(|s| s == "--") {
+ let (args, free) = args.split_at(pos);
+ (args, Some(free[1..].to_vec()))
+ } else {
+ (args, None)
+ };
let mut subcommand_help = String::from(
"\
Usage: x.py <subcommand> [options] [<paths>...]
@@ -301,6 +312,7 @@ To learn more about a subcommand, run `./x.py <subcommand> -h`",
opts.optflag("", "doc", "only run doc tests");
opts.optflag("", "bless", "update all stderr/stdout files of failing ui tests");
opts.optflag("", "force-rerun", "rerun tests even if the inputs are unchanged");
+ opts.optflag("", "only-modified", "only run tests that result has been changed");
opts.optopt(
"",
"compare-mode",
@@ -542,7 +554,8 @@ Arguments:
Kind::Setup => {
subcommand_help.push_str(&format!(
"\n
-x.py setup creates a `config.toml` which changes the defaults for x.py itself.
+x.py setup creates a `config.toml` which changes the defaults for x.py itself,
+as well as setting up a git pre-push hook, VS code config and toolchain link.
Arguments:
This subcommand accepts a 'profile' to use for builds. For example:
@@ -552,7 +565,13 @@ Arguments:
The profile is optional and you will be prompted interactively if it is not given.
The following profiles are available:
-{}",
+{}
+
+ To only set up the git hook, VS code or toolchain link, you may use
+ ./x.py setup hook
+ ./x.py setup vscode
+ ./x.py setup link
+",
Profile::all_for_help(" ").trim_end()
));
}
@@ -598,6 +617,7 @@ Arguments:
rustc_args: matches.opt_strs("rustc-args"),
fail_fast: !matches.opt_present("no-fail-fast"),
rustfix_coverage: matches.opt_present("rustfix-coverage"),
+ only_modified: matches.opt_present("only-modified"),
doc_tests: if matches.opt_present("doc") {
DocTests::Only
} else if matches.opt_present("no-doc") {
@@ -625,7 +645,7 @@ Arguments:
}
Kind::Setup => {
let profile = if paths.len() > 1 {
- eprintln!("\nerror: At most one profile can be passed to setup\n");
+ eprintln!("\nerror: At most one option can be passed to setup\n");
usage(1, &opts, verbose, &subcommand_help)
} else if let Some(path) = paths.pop() {
let profile_string = t!(path.into_os_string().into_string().map_err(
@@ -706,6 +726,7 @@ Arguments:
llvm_profile_generate: matches.opt_present("llvm-profile-generate"),
llvm_bolt_profile_generate: matches.opt_present("llvm-bolt-profile-generate"),
llvm_bolt_profile_use: matches.opt_str("llvm-bolt-profile-use"),
+ free_args,
}
}
}
@@ -777,6 +798,13 @@ impl Subcommand {
}
}
+ pub fn only_modified(&self) -> bool {
+ match *self {
+ Subcommand::Test { only_modified, .. } => only_modified,
+ _ => false,
+ }
+ }
+
pub fn force_rerun(&self) -> bool {
match *self {
Subcommand::Test { force_rerun, .. } => force_rerun,
diff --git a/src/bootstrap/format.rs b/src/bootstrap/format.rs
index bfc57a85c..6d5753e8a 100644
--- a/src/bootstrap/format.rs
+++ b/src/bootstrap/format.rs
@@ -1,8 +1,8 @@
//! Runs rustfmt on the repository.
use crate::builder::Builder;
-use crate::util::{output, output_result, program_out_of_date, t};
-use build_helper::git::updated_master_branch;
+use crate::util::{output, program_out_of_date, t};
+use build_helper::git::get_git_modified_files;
use ignore::WalkBuilder;
use std::collections::VecDeque;
use std::path::{Path, PathBuf};
@@ -80,26 +80,14 @@ fn update_rustfmt_version(build: &Builder<'_>) {
///
/// Returns `None` if all files should be formatted.
fn get_modified_rs_files(build: &Builder<'_>) -> Result<Option<Vec<String>>, String> {
- let Ok(updated_master) = updated_master_branch(Some(&build.config.src)) else { return Ok(None); };
-
if !verify_rustfmt_version(build) {
return Ok(None);
}
- let merge_base =
- output_result(build.config.git().arg("merge-base").arg(&updated_master).arg("HEAD"))?;
- Ok(Some(
- output_result(
- build.config.git().arg("diff-index").arg("--name-only").arg(merge_base.trim()),
- )?
- .lines()
- .map(|s| s.trim().to_owned())
- .filter(|f| Path::new(f).extension().map_or(false, |ext| ext == "rs"))
- .collect(),
- ))
+ get_git_modified_files(Some(&build.config.src), &vec!["rs"])
}
-#[derive(serde::Deserialize)]
+#[derive(serde_derive::Deserialize)]
struct RustfmtConfig {
ignore: Vec<String>,
}
@@ -205,10 +193,46 @@ pub fn format(build: &Builder<'_>, check: bool, paths: &[PathBuf]) {
let (tx, rx): (SyncSender<PathBuf>, _) = std::sync::mpsc::sync_channel(128);
let walker = match paths.get(0) {
Some(first) => {
- let mut walker = WalkBuilder::new(first);
+ let find_shortcut_candidates = |p: &PathBuf| {
+ let mut candidates = Vec::new();
+ for candidate in WalkBuilder::new(src.clone()).max_depth(Some(3)).build() {
+ if let Ok(entry) = candidate {
+ if let Some(dir_name) = p.file_name() {
+ if entry.path().is_dir() && entry.file_name() == dir_name {
+ candidates.push(entry.into_path());
+ }
+ }
+ }
+ }
+ candidates
+ };
+
+ // Only try to look for shortcut candidates for single component paths like
+ // `std` and not for e.g. relative paths like `../library/std`.
+ let should_look_for_shortcut_dir = |p: &PathBuf| p.components().count() == 1;
+
+ let mut walker = if should_look_for_shortcut_dir(first) {
+ if let [single_candidate] = &find_shortcut_candidates(first)[..] {
+ WalkBuilder::new(single_candidate)
+ } else {
+ WalkBuilder::new(first)
+ }
+ } else {
+ WalkBuilder::new(src.join(first))
+ };
+
for path in &paths[1..] {
- walker.add(path);
+ if should_look_for_shortcut_dir(path) {
+ if let [single_candidate] = &find_shortcut_candidates(path)[..] {
+ walker.add(single_candidate);
+ } else {
+ walker.add(path);
+ }
+ } else {
+ walker.add(src.join(path));
+ }
}
+
walker
}
None => WalkBuilder::new(src.clone()),
diff --git a/src/bootstrap/install.rs b/src/bootstrap/install.rs
index 1815a0973..ac3843c33 100644
--- a/src/bootstrap/install.rs
+++ b/src/bootstrap/install.rs
@@ -243,18 +243,6 @@ install!((self, builder, _config),
);
}
};
- Analysis, alias = "analysis", Self::should_build(_config), only_hosts: false, {
- // `expect` should be safe, only None with host != build, but this
- // only uses the `build` compiler
- let tarball = builder.ensure(dist::Analysis {
- // Find the actual compiler (handling the full bootstrap option) which
- // produced the save-analysis data because that data isn't copied
- // through the sysroot uplifting.
- compiler: builder.compiler_for(builder.top_stage, builder.config.build, self.target),
- target: self.target
- }).expect("missing analysis");
- install_sh(builder, "analysis", self.compiler.stage, Some(self.target), &tarball);
- };
Rustc, path = "compiler/rustc", true, only_hosts: true, {
let tarball = builder.ensure(dist::Rustc {
compiler: builder.compiler(builder.top_stage, self.target),
diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs
index 0474ab344..950f3b151 100644
--- a/src/bootstrap/lib.rs
+++ b/src/bootstrap/lib.rs
@@ -11,93 +11,6 @@
//! crates.io and Cargo.
//! * A standard interface to build across all platforms, including MSVC
//!
-//! ## Architecture
-//!
-//! The build system defers most of the complicated logic managing invocations
-//! of rustc and rustdoc to Cargo itself. However, moving through various stages
-//! and copying artifacts is still necessary for it to do. Each time rustbuild
-//! is invoked, it will iterate through the list of predefined steps and execute
-//! each serially in turn if it matches the paths passed or is a default rule.
-//! For each step rustbuild relies on the step internally being incremental and
-//! parallel. Note, though, that the `-j` parameter to rustbuild gets forwarded
-//! to appropriate test harnesses and such.
-//!
-//! Most of the "meaty" steps that matter are backed by Cargo, which does indeed
-//! have its own parallelism and incremental management. Later steps, like
-//! tests, aren't incremental and simply run the entire suite currently.
-//! However, compiletest itself tries to avoid running tests when the artifacts
-//! that are involved (mainly the compiler) haven't changed.
-//!
-//! 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.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.
-//!
-//! * Rustbuild takes over, performs sanity checks, probes the environment,
-//! reads configuration, and starts executing steps as it reads the command
-//! line arguments (paths) or going through the default rules.
-//!
-//! The build output will be something like the following:
-//!
-//! Building stage0 std artifacts
-//! Copying stage0 std
-//! Building stage0 test artifacts
-//! Copying stage0 test
-//! Building stage0 compiler artifacts
-//! Copying stage0 rustc
-//! Assembling stage1 compiler
-//! Building stage1 std artifacts
-//! Copying stage1 std
-//! Building stage1 test artifacts
-//! Copying stage1 test
-//! Building stage1 compiler artifacts
-//! Copying stage1 rustc
-//! Assembling stage2 compiler
-//! Uplifting stage1 std
-//! Uplifting stage1 test
-//! Uplifting stage1 rustc
-//!
-//! Let's disect that a little:
-//!
-//! ## Building stage0 {std,test,compiler} artifacts
-//!
-//! These steps use the provided (downloaded, usually) compiler to compile the
-//! local Rust source into libraries we can use.
-//!
-//! ## Copying stage0 {std,test,rustc}
-//!
-//! This copies the build output from Cargo into
-//! `build/$HOST/stage0-sysroot/lib/rustlib/$ARCH/lib`. FIXME: this step's
-//! documentation should be expanded -- the information already here may be
-//! incorrect.
-//!
-//! ## Assembling stage1 compiler
-//!
-//! This copies the libraries we built in "building stage0 ... artifacts" into
-//! the stage1 compiler's lib directory. These are the host libraries that the
-//! compiler itself uses to run. These aren't actually used by artifacts the new
-//! compiler generates. This step also copies the rustc and rustdoc binaries we
-//! generated into build/$HOST/stage/bin.
-//!
-//! The stage1/bin/rustc is a fully functional compiler, but it doesn't yet have
-//! any libraries to link built binaries or libraries to. The next 3 steps will
-//! provide those libraries for it; they are mostly equivalent to constructing
-//! the stage1/bin compiler so we don't go through them individually.
-//!
-//! ## Uplifting stage1 {std,test,rustc}
-//!
-//! This step copies the libraries from the stage1 compiler sysroot into the
-//! stage2 compiler. This is done to avoid rebuilding the compiler; libraries
-//! we'd build in this step should be identical (in function, if not necessarily
-//! identical on disk) so there's no need to recompile the compiler again. Note
-//! that if you want to, you can enable the full-bootstrap option to change this
-//! behavior.
-//!
-//! Each step is driven by a separate Cargo project and rustbuild orchestrates
-//! copying files between steps and otherwise preparing for Cargo to run.
-//!
//! ## Further information
//!
//! More documentation can be found in each respective module below, and you can
@@ -110,7 +23,7 @@ use std::fs::{self, File};
use std::io;
use std::io::ErrorKind;
use std::path::{Path, PathBuf};
-use std::process::Command;
+use std::process::{Command, Stdio};
use std::str;
use build_helper::ci::CiEnv;
@@ -203,7 +116,6 @@ const EXTRA_CHECK_CFGS: &[(Option<Mode>, &'static str, Option<&[&'static str]>)]
(None, "bootstrap", None),
(Some(Mode::Rustc), "parallel_compiler", None),
(Some(Mode::ToolRustc), "parallel_compiler", None),
- (Some(Mode::ToolRustc), "emulate_second_only_system", None),
(Some(Mode::Codegen), "parallel_compiler", None),
(Some(Mode::Std), "stdarch_intel_sde", None),
(Some(Mode::Std), "no_fp_fmt_parse", None),
@@ -214,18 +126,9 @@ const EXTRA_CHECK_CFGS: &[(Option<Mode>, &'static str, Option<&[&'static str]>)]
(Some(Mode::Std), "backtrace_in_libstd", None),
/* Extra values not defined in the built-in targets yet, but used in std */
(Some(Mode::Std), "target_env", Some(&["libnx"])),
- (Some(Mode::Std), "target_os", Some(&["watchos"])),
- (
- Some(Mode::Std),
- "target_arch",
- Some(&["asmjs", "spirv", "nvptx", "nvptx64", "le32", "xtensa"]),
- ),
+ // (Some(Mode::Std), "target_os", Some(&[])),
+ (Some(Mode::Std), "target_arch", Some(&["asmjs", "spirv", "nvptx", "xtensa"])),
/* Extra names used by dependencies */
- // FIXME: Used by rustfmt is their test but is invalid (neither cargo nor bootstrap ever set
- // this config) should probably by removed or use a allow attribute.
- (Some(Mode::ToolRustc), "release", None),
- // FIXME: Used by stdarch in their test, should use a allow attribute instead.
- (Some(Mode::Std), "dont_compile_me", None),
// FIXME: Used by serde_json, but we should not be triggering on external dependencies.
(Some(Mode::Rustc), "no_btreemap_remove_entry", None),
(Some(Mode::ToolRustc), "no_btreemap_remove_entry", None),
@@ -235,8 +138,12 @@ const EXTRA_CHECK_CFGS: &[(Option<Mode>, &'static str, Option<&[&'static str]>)]
// FIXME: Used by proc-macro2, but we should not be triggering on external dependencies.
(Some(Mode::Rustc), "span_locations", None),
(Some(Mode::ToolRustc), "span_locations", None),
- // Can be passed in RUSTFLAGS to prevent direct syscalls in rustix.
- (None, "rustix_use_libc", None),
+ // FIXME: Used by rustix, but we should not be triggering on external dependencies.
+ (Some(Mode::Rustc), "rustix_use_libc", None),
+ (Some(Mode::ToolRustc), "rustix_use_libc", None),
+ // FIXME: Used by filetime, but we should not be triggering on external dependencies.
+ (Some(Mode::Rustc), "emulate_second_only_system", None),
+ (Some(Mode::ToolRustc), "emulate_second_only_system", None),
];
/// A structure representing a Rust compiler.
@@ -663,12 +570,32 @@ impl Build {
// Try passing `--progress` to start, then run git again without if that fails.
let update = |progress: bool| {
- let mut git = Command::new("git");
+ // Git is buggy and will try to fetch submodules from the tracking branch for *this* repository,
+ // even though that has no relation to the upstream for the submodule.
+ let current_branch = {
+ let output = self
+ .config
+ .git()
+ .args(["symbolic-ref", "--short", "HEAD"])
+ .stderr(Stdio::inherit())
+ .output();
+ let output = t!(output);
+ if output.status.success() {
+ Some(String::from_utf8(output.stdout).unwrap().trim().to_owned())
+ } else {
+ None
+ }
+ };
+
+ let mut git = self.config.git();
+ if let Some(branch) = current_branch {
+ git.arg("-c").arg(format!("branch.{branch}.remote=origin"));
+ }
git.args(&["submodule", "update", "--init", "--recursive", "--depth=1"]);
if progress {
git.arg("--progress");
}
- git.arg(relative_path).current_dir(&self.config.src);
+ git.arg(relative_path);
git
};
// NOTE: doesn't use `try_run` because this shouldn't print an error if it fails.
@@ -1432,6 +1359,14 @@ impl Build {
return Vec::new();
}
+ if !stamp.exists() {
+ eprintln!(
+ "Error: Unable to find the stamp file {}, did you try to keep a nonexistent build stage?",
+ stamp.display()
+ );
+ crate::detail_exit(1);
+ }
+
let mut paths = Vec::new();
let contents = t!(fs::read(stamp), &stamp);
// This is the method we use for extracting paths from the stamp file passed to us. See
diff --git a/src/bootstrap/metadata.rs b/src/bootstrap/metadata.rs
index e193e70a0..bba4d65e8 100644
--- a/src/bootstrap/metadata.rs
+++ b/src/bootstrap/metadata.rs
@@ -1,7 +1,7 @@
use std::path::PathBuf;
use std::process::Command;
-use serde::Deserialize;
+use serde_derive::Deserialize;
use crate::cache::INTERNER;
use crate::util::output;
diff --git a/src/bootstrap/metrics.rs b/src/bootstrap/metrics.rs
index c823dc796..2e62c9507 100644
--- a/src/bootstrap/metrics.rs
+++ b/src/bootstrap/metrics.rs
@@ -7,7 +7,7 @@
use crate::builder::Step;
use crate::util::t;
use crate::Build;
-use serde::{Deserialize, Serialize};
+use serde_derive::{Deserialize, Serialize};
use std::cell::RefCell;
use std::fs::File;
use std::io::BufWriter;
diff --git a/src/bootstrap/native.rs b/src/bootstrap/native.rs
index e0d1504c9..5987b641b 100644
--- a/src/bootstrap/native.rs
+++ b/src/bootstrap/native.rs
@@ -180,60 +180,60 @@ pub(crate) fn is_ci_llvm_available(config: &Config, asserts: bool) -> bool {
// https://doc.rust-lang.org/rustc/platform-support.html#tier-1
let supported_platforms = [
// tier 1
- "aarch64-unknown-linux-gnu",
- "i686-pc-windows-gnu",
- "i686-pc-windows-msvc",
- "i686-unknown-linux-gnu",
- "x86_64-unknown-linux-gnu",
- "x86_64-apple-darwin",
- "x86_64-pc-windows-gnu",
- "x86_64-pc-windows-msvc",
+ ("aarch64-unknown-linux-gnu", false),
+ ("i686-pc-windows-gnu", false),
+ ("i686-pc-windows-msvc", false),
+ ("i686-unknown-linux-gnu", false),
+ ("x86_64-unknown-linux-gnu", true),
+ ("x86_64-apple-darwin", true),
+ ("x86_64-pc-windows-gnu", true),
+ ("x86_64-pc-windows-msvc", true),
// tier 2 with host tools
- "aarch64-apple-darwin",
- "aarch64-pc-windows-msvc",
- "aarch64-unknown-linux-musl",
- "arm-unknown-linux-gnueabi",
- "arm-unknown-linux-gnueabihf",
- "armv7-unknown-linux-gnueabihf",
- "mips-unknown-linux-gnu",
- "mips64-unknown-linux-gnuabi64",
- "mips64el-unknown-linux-gnuabi64",
- "mipsel-unknown-linux-gnu",
- "powerpc-unknown-linux-gnu",
- "powerpc64-unknown-linux-gnu",
- "powerpc64le-unknown-linux-gnu",
- "riscv64gc-unknown-linux-gnu",
- "s390x-unknown-linux-gnu",
- "x86_64-unknown-freebsd",
- "x86_64-unknown-illumos",
- "x86_64-unknown-linux-musl",
- "x86_64-unknown-netbsd",
+ ("aarch64-apple-darwin", false),
+ ("aarch64-pc-windows-msvc", false),
+ ("aarch64-unknown-linux-musl", false),
+ ("arm-unknown-linux-gnueabi", false),
+ ("arm-unknown-linux-gnueabihf", false),
+ ("armv7-unknown-linux-gnueabihf", false),
+ ("mips-unknown-linux-gnu", false),
+ ("mips64-unknown-linux-gnuabi64", false),
+ ("mips64el-unknown-linux-gnuabi64", false),
+ ("mipsel-unknown-linux-gnu", false),
+ ("powerpc-unknown-linux-gnu", false),
+ ("powerpc64-unknown-linux-gnu", false),
+ ("powerpc64le-unknown-linux-gnu", false),
+ ("riscv64gc-unknown-linux-gnu", false),
+ ("s390x-unknown-linux-gnu", false),
+ ("x86_64-unknown-freebsd", false),
+ ("x86_64-unknown-illumos", false),
+ ("x86_64-unknown-linux-musl", false),
+ ("x86_64-unknown-netbsd", false),
];
- if !supported_platforms.contains(&&*config.build.triple) {
- return false;
+
+ if !supported_platforms.contains(&(&*config.build.triple, asserts)) {
+ if asserts == true || !supported_platforms.contains(&(&*config.build.triple, true)) {
+ return false;
+ }
}
- let triple = &*config.build.triple;
- if (triple == "aarch64-unknown-linux-gnu" || triple.contains("i686")) && asserts {
- // No alt builder for aarch64-unknown-linux-gnu today.
+ if is_ci_llvm_modified(config) {
+ eprintln!("Detected LLVM as non-available: running in CI and modified LLVM in this change");
return false;
}
- if CiEnv::is_ci() {
+ true
+}
+
+/// Returns true if we're running in CI with modified LLVM (and thus can't download it)
+pub(crate) fn is_ci_llvm_modified(config: &Config) -> bool {
+ CiEnv::is_ci() && {
// We assume we have access to git, so it's okay to unconditionally pass
// `true` here.
let llvm_sha = detect_llvm_sha(config, true);
let head_sha = output(config.git().arg("rev-parse").arg("HEAD"));
let head_sha = head_sha.trim();
- if llvm_sha == head_sha {
- eprintln!(
- "Detected LLVM as non-available: running in CI and modified LLVM in this change"
- );
- return false;
- }
+ llvm_sha == head_sha
}
-
- true
}
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
@@ -486,7 +486,7 @@ impl Step for Llvm {
cfg.define("LLVM_VERSION_SUFFIX", suffix);
}
- configure_cmake(builder, target, &mut cfg, true, ldflags);
+ configure_cmake(builder, target, &mut cfg, true, ldflags, &[]);
configure_llvm(builder, target, &mut cfg);
for (key, val) in &builder.config.llvm_build_config {
@@ -564,11 +564,11 @@ fn check_llvm_version(builder: &Builder<'_>, llvm_config: &Path) {
let version = output(cmd.arg("--version"));
let mut parts = version.split('.').take(2).filter_map(|s| s.parse::<u32>().ok());
if let (Some(major), Some(_minor)) = (parts.next(), parts.next()) {
- if major >= 13 {
+ if major >= 14 {
return;
}
}
- panic!("\n\nbad LLVM version: {}, need >=13.0\n\n", version)
+ panic!("\n\nbad LLVM version: {}, need >=14.0\n\n", version)
}
fn configure_cmake(
@@ -577,6 +577,7 @@ fn configure_cmake(
cfg: &mut cmake::Config,
use_compiler_launcher: bool,
mut ldflags: LdFlags,
+ extra_compiler_flags: &[&str],
) {
// Do not print installation messages for up-to-date files.
// LLVM and LLD builds can produce a lot of those and hit CI limits on log size.
@@ -717,6 +718,9 @@ fn configure_cmake(
if builder.config.llvm_clang_cl.is_some() {
cflags.push(&format!(" --target={}", target));
}
+ for flag in extra_compiler_flags {
+ cflags.push(&format!(" {}", flag));
+ }
cfg.define("CMAKE_C_FLAGS", cflags);
let mut cxxflags: OsString = builder.cflags(target, GitRepo::Llvm, CLang::Cxx).join(" ").into();
if let Some(ref s) = builder.config.llvm_cxxflags {
@@ -726,6 +730,9 @@ fn configure_cmake(
if builder.config.llvm_clang_cl.is_some() {
cxxflags.push(&format!(" --target={}", target));
}
+ for flag in extra_compiler_flags {
+ cxxflags.push(&format!(" {}", flag));
+ }
cfg.define("CMAKE_CXX_FLAGS", cxxflags);
if let Some(ar) = builder.ar(target) {
if ar.is_absolute() {
@@ -867,7 +874,7 @@ impl Step for Lld {
}
}
- configure_cmake(builder, target, &mut cfg, true, ldflags);
+ configure_cmake(builder, target, &mut cfg, true, ldflags, &[]);
configure_llvm(builder, target, &mut cfg);
// Re-use the same flags as llvm to control the level of debug information
@@ -1031,7 +1038,16 @@ impl Step for Sanitizers {
// Unfortunately sccache currently lacks support to build them successfully.
// Disable compiler launcher on Darwin targets to avoid potential issues.
let use_compiler_launcher = !self.target.contains("apple-darwin");
- configure_cmake(builder, self.target, &mut cfg, use_compiler_launcher, LdFlags::default());
+ let extra_compiler_flags: &[&str] =
+ if self.target.contains("apple") { &["-fembed-bitcode=off"] } else { &[] };
+ configure_cmake(
+ builder,
+ self.target,
+ &mut cfg,
+ use_compiler_launcher,
+ LdFlags::default(),
+ extra_compiler_flags,
+ );
t!(fs::create_dir_all(&out_dir));
cfg.out_dir(out_dir);
@@ -1087,12 +1103,15 @@ fn supported_sanitizers(
match &*target.triple {
"aarch64-apple-darwin" => darwin_libs("osx", &["asan", "lsan", "tsan"]),
+ "aarch64-apple-ios" => darwin_libs("ios", &["asan", "tsan"]),
+ "aarch64-apple-ios-sim" => darwin_libs("iossim", &["asan", "tsan"]),
"aarch64-unknown-fuchsia" => common_libs("fuchsia", "aarch64", &["asan"]),
"aarch64-unknown-linux-gnu" => {
common_libs("linux", "aarch64", &["asan", "lsan", "msan", "tsan", "hwasan"])
}
"x86_64-apple-darwin" => darwin_libs("osx", &["asan", "lsan", "tsan"]),
"x86_64-unknown-fuchsia" => common_libs("fuchsia", "x86_64", &["asan"]),
+ "x86_64-apple-ios" => darwin_libs("iossim", &["asan", "tsan"]),
"x86_64-unknown-freebsd" => common_libs("freebsd", "x86_64", &["asan", "msan", "tsan"]),
"x86_64-unknown-netbsd" => {
common_libs("netbsd", "x86_64", &["asan", "lsan", "msan", "tsan"])
@@ -1105,6 +1124,12 @@ fn supported_sanitizers(
"x86_64-unknown-linux-musl" => {
common_libs("linux", "x86_64", &["asan", "lsan", "msan", "tsan"])
}
+ "s390x-unknown-linux-gnu" => {
+ common_libs("linux", "s390x", &["asan", "lsan", "msan", "tsan"])
+ }
+ "s390x-unknown-linux-musl" => {
+ common_libs("linux", "s390x", &["asan", "lsan", "msan", "tsan"])
+ }
_ => Vec::new(),
}
}
diff --git a/src/bootstrap/run.rs b/src/bootstrap/run.rs
index e02808545..e14440f57 100644
--- a/src/bootstrap/run.rs
+++ b/src/bootstrap/run.rs
@@ -183,6 +183,7 @@ impl Step for Miri {
// Forward arguments.
miri.arg("--").arg("--target").arg(target.rustc_target_arg());
miri.args(builder.config.cmd.args());
+ miri.args(&builder.config.free_args);
// miri tests need to know about the stage sysroot
miri.env("MIRI_SYSROOT", &miri_sysroot);
diff --git a/src/bootstrap/setup.rs b/src/bootstrap/setup.rs
index 004601cb6..4480bce99 100644
--- a/src/bootstrap/setup.rs
+++ b/src/bootstrap/setup.rs
@@ -1,6 +1,7 @@
use crate::builder::{Builder, RunConfig, ShouldRun, Step};
use crate::Config;
use crate::{t, VERSION};
+use sha2::Digest;
use std::env::consts::EXE_SUFFIX;
use std::fmt::Write as _;
use std::fs::File;
@@ -10,6 +11,9 @@ use std::process::Command;
use std::str::FromStr;
use std::{fmt, fs, io};
+#[cfg(test)]
+mod tests;
+
#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
pub enum Profile {
Compiler,
@@ -17,8 +21,19 @@ pub enum Profile {
Library,
Tools,
User,
+ None,
}
+/// A list of historical hashes of `src/etc/vscode_settings.json`.
+/// New entries should be appended whenever this is updated so we can detect
+/// outdated vs. user-modified settings files.
+static SETTINGS_HASHES: &[&str] = &[
+ "ea67e259dedf60d4429b6c349a564ffcd1563cf41c920a856d1f5b16b4701ac8",
+ "56e7bf011c71c5d81e0bf42e84938111847a810eee69d906bba494ea90b51922",
+ "af1b5efe196aed007577899db9dae15d6dbc923d6fa42fa0934e68617ba9bbe0",
+];
+static VSCODE_SETTINGS: &str = include_str!("../etc/vscode_settings.json");
+
impl Profile {
fn include_path(&self, src_path: &Path) -> PathBuf {
PathBuf::from(format!("{}/src/bootstrap/defaults/config.{}.toml", src_path.display(), self))
@@ -27,7 +42,7 @@ impl Profile {
pub fn all() -> impl Iterator<Item = Self> {
use Profile::*;
// N.B. these are ordered by how they are displayed, not alphabetically
- [Library, Compiler, Codegen, Tools, User].iter().copied()
+ [Library, Compiler, Codegen, Tools, User, None].iter().copied()
}
pub fn purpose(&self) -> String {
@@ -38,6 +53,7 @@ impl Profile {
Codegen => "Contribute to the compiler, and also modify LLVM or codegen",
Tools => "Contribute to tools which depend on the compiler, but do not modify it directly (e.g. rustdoc, clippy, miri)",
User => "Install Rust from source",
+ None => "Do not modify `config.toml`"
}
.to_string()
}
@@ -57,6 +73,7 @@ impl Profile {
Profile::Library => "library",
Profile::Tools => "tools",
Profile::User => "user",
+ Profile::None => "none",
}
}
}
@@ -73,6 +90,7 @@ impl FromStr for Profile {
"tools" | "tool" | "rustdoc" | "clippy" | "miri" | "rustfmt" | "rls" => {
Ok(Profile::Tools)
}
+ "none" => Ok(Profile::None),
_ => Err(format!("unknown profile: '{}'", s)),
}
}
@@ -130,17 +148,8 @@ impl Step for Profile {
}
pub fn setup(config: &Config, profile: Profile) {
- let stage_path =
- ["build", config.build.rustc_target_arg(), "stage1"].join(&MAIN_SEPARATOR.to_string());
-
- if !rustup_installed() && profile != Profile::User {
- eprintln!("`rustup` is not installed; cannot link `stage1` toolchain");
- } else if stage_dir_exists(&stage_path[..]) && !config.dry_run() {
- attempt_toolchain_link(&stage_path[..]);
- }
-
- let suggestions = match profile {
- Profile::Codegen | Profile::Compiler => &["check", "build", "test"][..],
+ let suggestions: &[&str] = match profile {
+ Profile::Codegen | Profile::Compiler | Profile::None => &["check", "build", "test"],
Profile::Tools => &[
"check",
"build",
@@ -153,10 +162,6 @@ pub fn setup(config: &Config, profile: Profile) {
Profile::User => &["dist", "build"],
};
- if !config.dry_run() {
- t!(install_git_hook_maybe(&config));
- }
-
println!();
println!("To get started, try one of the following commands:");
@@ -175,6 +180,9 @@ pub fn setup(config: &Config, profile: Profile) {
}
fn setup_config_toml(path: &PathBuf, profile: Profile, config: &Config) {
+ if profile == Profile::None {
+ return;
+ }
if path.exists() {
eprintln!();
eprintln!(
@@ -202,6 +210,41 @@ fn setup_config_toml(path: &PathBuf, profile: Profile, config: &Config) {
println!("`x.py` will now use the configuration at {}", include_path.display());
}
+/// Creates a toolchain link for stage1 using `rustup`
+#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
+pub struct Link;
+impl Step for Link {
+ type Output = ();
+ const DEFAULT: bool = true;
+ fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
+ run.alias("link")
+ }
+ fn make_run(run: RunConfig<'_>) {
+ if run.builder.config.dry_run() {
+ return;
+ }
+ if let [cmd] = &run.paths[..] {
+ if cmd.assert_single_path().path.as_path().as_os_str() == "link" {
+ run.builder.ensure(Link);
+ }
+ }
+ }
+ fn run(self, builder: &Builder<'_>) -> Self::Output {
+ let config = &builder.config;
+ if config.dry_run() {
+ return;
+ }
+ let stage_path =
+ ["build", config.build.rustc_target_arg(), "stage1"].join(&MAIN_SEPARATOR.to_string());
+
+ if !rustup_installed() {
+ eprintln!("`rustup` is not installed; cannot link `stage1` toolchain");
+ } else if stage_dir_exists(&stage_path[..]) && !config.dry_run() {
+ attempt_toolchain_link(&stage_path[..]);
+ }
+ }
+}
+
fn rustup_installed() -> bool {
Command::new("rustup")
.arg("--version")
@@ -351,6 +394,63 @@ pub fn interactive_path() -> io::Result<Profile> {
Ok(template)
}
+#[derive(PartialEq)]
+enum PromptResult {
+ Yes, // y/Y/yes
+ No, // n/N/no
+ Print, // p/P/print
+}
+
+/// Prompt a user for a answer, looping until they enter an accepted input or nothing
+fn prompt_user(prompt: &str) -> io::Result<Option<PromptResult>> {
+ let mut input = String::new();
+ loop {
+ print!("{prompt} ");
+ io::stdout().flush()?;
+ input.clear();
+ io::stdin().read_line(&mut input)?;
+ match input.trim().to_lowercase().as_str() {
+ "y" | "yes" => return Ok(Some(PromptResult::Yes)),
+ "n" | "no" => return Ok(Some(PromptResult::No)),
+ "p" | "print" => return Ok(Some(PromptResult::Print)),
+ "" => return Ok(None),
+ _ => {
+ eprintln!("error: unrecognized option '{}'", input.trim());
+ eprintln!("note: press Ctrl+C to exit");
+ }
+ };
+ }
+}
+
+/// Installs `src/etc/pre-push.sh` as a Git hook
+#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
+pub struct Hook;
+
+impl Step for Hook {
+ type Output = ();
+ const DEFAULT: bool = true;
+ fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
+ run.alias("hook")
+ }
+ fn make_run(run: RunConfig<'_>) {
+ if run.builder.config.dry_run() {
+ return;
+ }
+ if let [cmd] = &run.paths[..] {
+ if cmd.assert_single_path().path.as_path().as_os_str() == "hook" {
+ run.builder.ensure(Hook);
+ }
+ }
+ }
+ fn run(self, builder: &Builder<'_>) -> Self::Output {
+ let config = &builder.config;
+ if config.dry_run() {
+ return;
+ }
+ t!(install_git_hook_maybe(&config));
+ }
+}
+
// install a git hook to automatically run tidy, if they want
fn install_git_hook_maybe(config: &Config) -> io::Result<()> {
let git = t!(config.git().args(&["rev-parse", "--git-common-dir"]).output().map(|output| {
@@ -363,43 +463,127 @@ fn install_git_hook_maybe(config: &Config) -> io::Result<()> {
return Ok(());
}
- let mut input = String::new();
- println!();
println!(
- "Rust's CI will automatically fail if it doesn't pass `tidy`, the internal tool for ensuring code quality.
+ "\nRust's CI will automatically fail if it doesn't pass `tidy`, the internal tool for ensuring code quality.
If you'd like, x.py can install a git hook for you that will automatically run `test tidy` before
pushing your code to ensure your code is up to par. If you decide later that this behavior is
undesirable, simply delete the `pre-push` file from .git/hooks."
);
- let should_install = loop {
- print!("Would you like to install the git hook?: [y/N] ");
- io::stdout().flush()?;
- input.clear();
- io::stdin().read_line(&mut input)?;
- break match input.trim().to_lowercase().as_str() {
- "y" | "yes" => true,
- "n" | "no" | "" => false,
- _ => {
- eprintln!("error: unrecognized option '{}'", input.trim());
- eprintln!("note: press Ctrl+C to exit");
- continue;
- }
- };
- };
-
- if should_install {
- let src = config.src.join("src").join("etc").join("pre-push.sh");
- match fs::hard_link(src, &dst) {
- Err(e) => eprintln!(
+ if prompt_user("Would you like to install the git hook?: [y/N]")? != Some(PromptResult::Yes) {
+ println!("Ok, skipping installation!");
+ return Ok(());
+ }
+ let src = config.src.join("src").join("etc").join("pre-push.sh");
+ match fs::hard_link(src, &dst) {
+ Err(e) => {
+ eprintln!(
"error: could not create hook {}: do you already have the git hook installed?\n{}",
dst.display(),
e
- ),
- Ok(_) => println!("Linked `src/etc/pre-push.sh` to `.git/hooks/pre-push`"),
+ );
+ return Err(e);
+ }
+ Ok(_) => println!("Linked `src/etc/pre-push.sh` to `.git/hooks/pre-push`"),
+ };
+ Ok(())
+}
+
+/// Sets up or displays `src/etc/vscode_settings.json`
+#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
+pub struct Vscode;
+
+impl Step for Vscode {
+ type Output = ();
+ const DEFAULT: bool = true;
+ fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
+ run.alias("vscode")
+ }
+ fn make_run(run: RunConfig<'_>) {
+ if run.builder.config.dry_run() {
+ return;
+ }
+ if let [cmd] = &run.paths[..] {
+ if cmd.assert_single_path().path.as_path().as_os_str() == "vscode" {
+ run.builder.ensure(Vscode);
+ }
+ }
+ }
+ fn run(self, builder: &Builder<'_>) -> Self::Output {
+ let config = &builder.config;
+ if config.dry_run() {
+ return;
+ }
+ t!(create_vscode_settings_maybe(&config));
+ }
+}
+
+/// Create a `.vscode/settings.json` file for rustc development, or just print it
+fn create_vscode_settings_maybe(config: &Config) -> io::Result<()> {
+ let (current_hash, historical_hashes) = SETTINGS_HASHES.split_last().unwrap();
+ let vscode_settings = config.src.join(".vscode").join("settings.json");
+ // If None, no settings.json exists
+ // If Some(true), is a previous version of settings.json
+ // If Some(false), is not a previous version (i.e. user modified)
+ // If it's up to date we can just skip this
+ let mut mismatched_settings = None;
+ if let Ok(current) = fs::read_to_string(&vscode_settings) {
+ let mut hasher = sha2::Sha256::new();
+ hasher.update(&current);
+ let hash = hex::encode(hasher.finalize().as_slice());
+ if hash == *current_hash {
+ return Ok(());
+ } else if historical_hashes.contains(&hash.as_str()) {
+ mismatched_settings = Some(true);
+ } else {
+ mismatched_settings = Some(false);
+ }
+ }
+ println!(
+ "\nx.py can automatically install the recommended `.vscode/settings.json` file for rustc development"
+ );
+ match mismatched_settings {
+ Some(true) => eprintln!(
+ "warning: existing `.vscode/settings.json` is out of date, x.py will update it"
+ ),
+ Some(false) => eprintln!(
+ "warning: existing `.vscode/settings.json` has been modified by user, x.py will back it up and replace it"
+ ),
+ _ => (),
+ }
+ let should_create = match prompt_user(
+ "Would you like to create/update `settings.json`, or only print suggested settings?: [y/p/N]",
+ )? {
+ Some(PromptResult::Yes) => true,
+ Some(PromptResult::Print) => false,
+ _ => {
+ println!("Ok, skipping settings!");
+ return Ok(());
+ }
+ };
+ if should_create {
+ let path = config.src.join(".vscode");
+ if !path.exists() {
+ fs::create_dir(&path)?;
+ }
+ let verb = match mismatched_settings {
+ // exists but outdated, we can replace this
+ Some(true) => "Updated",
+ // exists but user modified, back it up
+ Some(false) => {
+ // exists and is not current version or outdated, so back it up
+ let mut backup = vscode_settings.clone();
+ backup.set_extension("bak");
+ eprintln!("warning: copying `settings.json` to `settings.json.bak`");
+ fs::copy(&vscode_settings, &backup)?;
+ "Updated"
+ }
+ _ => "Created",
};
+ fs::write(&vscode_settings, &VSCODE_SETTINGS)?;
+ println!("{verb} `.vscode/settings.json`");
} else {
- println!("Ok, skipping installation!");
+ println!("\n{VSCODE_SETTINGS}");
}
Ok(())
}
diff --git a/src/bootstrap/setup/tests.rs b/src/bootstrap/setup/tests.rs
new file mode 100644
index 000000000..dcf9d18e6
--- /dev/null
+++ b/src/bootstrap/setup/tests.rs
@@ -0,0 +1,14 @@
+use super::{SETTINGS_HASHES, VSCODE_SETTINGS};
+use sha2::Digest;
+
+#[test]
+fn check_matching_settings_hash() {
+ let mut hasher = sha2::Sha256::new();
+ hasher.update(&VSCODE_SETTINGS);
+ let hash = hex::encode(hasher.finalize().as_slice());
+ assert_eq!(
+ &hash,
+ SETTINGS_HASHES.last().unwrap(),
+ "Update `SETTINGS_HASHES` with the new hash of `src/etc/vscode_settings.json`"
+ );
+}
diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs
index 6078e39ac..b4f1506dc 100644
--- a/src/bootstrap/test.rs
+++ b/src/bootstrap/test.rs
@@ -435,6 +435,10 @@ impl Step for Rustfmt {
&[],
);
+ if !builder.fail_fast {
+ cargo.arg("--no-fail-fast");
+ }
+
let dir = testdir(builder, compiler.host);
t!(fs::create_dir_all(&dir));
cargo.env("RUSTFMT_TEST_DIR", dir);
@@ -615,6 +619,10 @@ impl Step for Miri {
);
cargo.add_rustc_lib_path(builder, compiler);
+ if !builder.fail_fast {
+ cargo.arg("--no-fail-fast");
+ }
+
// miri tests need to know about the stage sysroot
cargo.env("MIRI_SYSROOT", &miri_sysroot);
cargo.env("MIRI_HOST_SYSROOT", sysroot);
@@ -746,6 +754,10 @@ impl Step for Clippy {
&[],
);
+ if !builder.fail_fast {
+ cargo.arg("--no-fail-fast");
+ }
+
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());
@@ -1114,9 +1126,6 @@ impl Step for Tidy {
cmd.arg("--bless");
}
- builder.info("tidy check");
- try_run(builder, &mut cmd);
-
if builder.config.channel == "dev" || builder.config.channel == "nightly" {
builder.info("fmt check");
if builder.initial_rustfmt().is_none() {
@@ -1134,6 +1143,11 @@ help: to skip test's attempt to check tidiness, pass `--exclude src/tools/tidy`
}
crate::format::format(&builder, !builder.config.cmd.bless(), &[]);
}
+
+ builder.info("tidy check");
+ try_run(builder, &mut cmd);
+
+ builder.ensure(ExpandYamlAnchors {});
}
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
@@ -1508,6 +1522,10 @@ note: if you're sure you want to do this, please open an issue as to why. In the
if builder.config.rust_optimize_tests {
cmd.arg("--optimize-tests");
}
+ if builder.config.cmd.only_modified() {
+ cmd.arg("--only-modified");
+ }
+
let mut flags = if is_rustdoc { Vec::new() } else { vec!["-Crpath".to_string()] };
flags.push(format!("-Cdebuginfo={}", builder.config.rust_debuginfo_level_tests));
flags.extend(builder.config.cmd.rustc_args().iter().map(|s| s.to_string()));
@@ -1582,6 +1600,7 @@ note: if you're sure you want to do this, please open an issue as to why. In the
.collect();
test_args.append(&mut builder.config.cmd.test_args());
+ test_args.extend(builder.config.free_args.iter().map(|s| s.as_str()));
// On Windows, replace forward slashes in test-args by backslashes
// so the correct filters are passed to libtest
diff --git a/src/bootstrap/tool.rs b/src/bootstrap/tool.rs
index 9a2100c2f..3c9a154da 100644
--- a/src/bootstrap/tool.rs
+++ b/src/bootstrap/tool.rs
@@ -33,6 +33,44 @@ struct ToolBuild {
allow_features: &'static str,
}
+fn tooling_output(
+ mode: Mode,
+ tool: &str,
+ build_stage: u32,
+ host: &TargetSelection,
+ target: &TargetSelection,
+) -> String {
+ match mode {
+ // depends on compiler stage, different to host compiler
+ Mode::ToolRustc => {
+ if host == target {
+ format!("Building tool {} (stage{} -> stage{})", tool, build_stage, build_stage + 1)
+ } else {
+ format!(
+ "Building tool {} (stage{}:{} -> stage{}:{})",
+ tool,
+ build_stage,
+ host,
+ build_stage + 1,
+ target
+ )
+ }
+ }
+ // doesn't depend on compiler, same as host compiler
+ Mode::ToolStd => {
+ if host == target {
+ format!("Building tool {} (stage{})", tool, build_stage)
+ } else {
+ format!(
+ "Building tool {} (stage{}:{} -> stage{}:{})",
+ tool, build_stage, host, build_stage, target
+ )
+ }
+ }
+ _ => format!("Building tool {} (stage{})", tool, build_stage),
+ }
+}
+
impl Step for ToolBuild {
type Output = Option<PathBuf>;
@@ -74,8 +112,14 @@ impl Step for ToolBuild {
if !self.allow_features.is_empty() {
cargo.allow_features(self.allow_features);
}
-
- builder.info(&format!("Building stage{} tool {} ({})", compiler.stage, tool, target));
+ let msg = tooling_output(
+ self.mode,
+ self.tool,
+ self.compiler.stage,
+ &self.compiler.host,
+ &self.target,
+ );
+ builder.info(&msg);
let mut duplicates = Vec::new();
let is_expected = compile::stream_cargo(builder, cargo, vec![], &mut |msg| {
// Only care about big things like the RLS/Cargo for now
@@ -551,7 +595,7 @@ impl Step for Rustdoc {
features.push("jemalloc".to_string());
}
- let cargo = prepare_tool_cargo(
+ let mut cargo = prepare_tool_cargo(
builder,
build_compiler,
Mode::ToolRustc,
@@ -562,10 +606,18 @@ impl Step for Rustdoc {
features.as_slice(),
);
- builder.info(&format!(
- "Building rustdoc for stage{} ({})",
- target_compiler.stage, target_compiler.host
- ));
+ if builder.config.rustc_parallel {
+ cargo.rustflag("--cfg=parallel_compiler");
+ }
+
+ let msg = tooling_output(
+ Mode::ToolRustc,
+ "rustdoc",
+ build_compiler.stage,
+ &self.compiler.host,
+ &target,
+ );
+ builder.info(&msg);
builder.run(&mut cargo.into());
// Cargo adds a number of paths to the dylib search path on windows, which results in
@@ -765,9 +817,15 @@ impl Step for RustAnalyzerProcMacroSrv {
const ONLY_HOSTS: bool = true;
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
+ let builder = run.builder;
// Allow building `rust-analyzer-proc-macro-srv` both as part of the `rust-analyzer` and as a stand-alone tool.
run.path("src/tools/rust-analyzer")
.path("src/tools/rust-analyzer/crates/proc-macro-srv-cli")
+ .default_condition(builder.config.tools.as_ref().map_or(true, |tools| {
+ tools
+ .iter()
+ .any(|tool| tool == "rust-analyzer" || tool == "rust-analyzer-proc-macro-srv")
+ }))
}
fn make_run(run: RunConfig<'_>) {
diff --git a/src/bootstrap/toolstate.rs b/src/bootstrap/toolstate.rs
index 1969e0b6f..7aab88a1a 100644
--- a/src/bootstrap/toolstate.rs
+++ b/src/bootstrap/toolstate.rs
@@ -1,6 +1,6 @@
use crate::builder::{Builder, RunConfig, ShouldRun, Step};
use crate::util::t;
-use serde::{Deserialize, Serialize};
+use serde_derive::{Deserialize, Serialize};
use std::collections::HashMap;
use std::env;
use std::fmt;
diff --git a/src/ci/docker/host-x86_64/dist-s390x-linux/Dockerfile b/src/ci/docker/host-x86_64/dist-s390x-linux/Dockerfile
index 43a449b3a..adb98d7eb 100644
--- a/src/ci/docker/host-x86_64/dist-s390x-linux/Dockerfile
+++ b/src/ci/docker/host-x86_64/dist-s390x-linux/Dockerfile
@@ -28,5 +28,5 @@ ENV \
ENV HOSTS=s390x-unknown-linux-gnu
-ENV RUST_CONFIGURE_ARGS --enable-extended --enable-lld --enable-profiler --disable-docs
+ENV RUST_CONFIGURE_ARGS --enable-extended --enable-lld --enable-sanitizers --enable-profiler --disable-docs
ENV SCRIPT python3 ../x.py dist --host $HOSTS --target $HOSTS
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 6bdc88e18..5feba4e06 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
@@ -81,7 +81,7 @@ ENV RUST_CONFIGURE_ARGS \
--set rust.jemalloc \
--set rust.use-lld=true \
--set rust.lto=thin
-ENV SCRIPT ../src/ci/pgo.sh python3 ../x.py dist \
+ENV SCRIPT python3 ../src/ci/stage-build.py python3 ../x.py dist \
--host $HOSTS --target $HOSTS \
--include-default-paths \
build-manifest bootstrap
diff --git a/src/ci/docker/host-x86_64/mingw-check/Dockerfile b/src/ci/docker/host-x86_64/mingw-check/Dockerfile
index 4cc5d9f8a..98bd90210 100644
--- a/src/ci/docker/host-x86_64/mingw-check/Dockerfile
+++ b/src/ci/docker/host-x86_64/mingw-check/Dockerfile
@@ -23,6 +23,8 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
RUN curl -sL https://nodejs.org/dist/v16.9.0/node-v16.9.0-linux-x64.tar.xz | tar -xJ
ENV PATH="/node-v16.9.0-linux-x64/bin:${PATH}"
+ENV RUST_CONFIGURE_ARGS="--set rust.validate-mir-opts=3"
+
# Install es-check
# Pin its version to prevent unrelated CI failures due to future es-check versions.
RUN npm install es-check@6.1.1 eslint@8.6.0 -g
@@ -38,7 +40,7 @@ COPY host-x86_64/mingw-check/validate-error-codes.sh /scripts/
ENV RUN_CHECK_WITH_PARALLEL_QUERIES 1
ENV SCRIPT python3 ../x.py --stage 2 test src/tools/expand-yaml-anchors && \
- python3 ../x.py check --target=i686-pc-windows-gnu --host=i686-pc-windows-gnu --all-targets && \
+ python3 ../x.py check --target=i686-pc-windows-gnu --host=i686-pc-windows-gnu && \
python3 ../x.py build --stage 0 src/tools/build-manifest && \
python3 ../x.py test --stage 0 src/tools/compiletest && \
python3 ../x.py test --stage 0 core alloc std test proc_macro && \
diff --git a/src/ci/docker/host-x86_64/mingw-check/validate-toolstate.sh b/src/ci/docker/host-x86_64/mingw-check/validate-toolstate.sh
index c6d728eb8..0b06f5e36 100755
--- a/src/ci/docker/host-x86_64/mingw-check/validate-toolstate.sh
+++ b/src/ci/docker/host-x86_64/mingw-check/validate-toolstate.sh
@@ -9,11 +9,5 @@ git clone --depth=1 https://github.com/rust-lang-nursery/rust-toolstate.git
cd rust-toolstate
python3 "../../src/tools/publish_toolstate.py" "$(git rev-parse HEAD)" \
"$(git log --format=%s -n1 HEAD)" "" ""
-# Only check maintainers if this build is supposed to publish toolstate.
-# Builds that are not supposed to publish don't have the access token.
-if [ -n "${TOOLSTATE_PUBLISH+is_set}" ]; then
- TOOLSTATE_VALIDATE_MAINTAINERS_REPO=rust-lang/rust python3 \
- "../../src/tools/publish_toolstate.py"
-fi
cd ..
rm -rf rust-toolstate
diff --git a/src/ci/docker/host-x86_64/x86_64-gnu-llvm-13-stage1/Dockerfile b/src/ci/docker/host-x86_64/x86_64-gnu-llvm-13-stage1/Dockerfile
deleted file mode 100644
index bcbf58253..000000000
--- a/src/ci/docker/host-x86_64/x86_64-gnu-llvm-13-stage1/Dockerfile
+++ /dev/null
@@ -1,49 +0,0 @@
-FROM ubuntu:22.04
-
-ARG DEBIAN_FRONTEND=noninteractive
-RUN apt-get update && apt-get install -y --no-install-recommends \
- g++ \
- gcc-multilib \
- make \
- ninja-build \
- file \
- curl \
- ca-certificates \
- python2.7 \
- git \
- cmake \
- sudo \
- gdb \
- llvm-13-tools \
- llvm-13-dev \
- libedit-dev \
- libssl-dev \
- pkg-config \
- zlib1g-dev \
- xz-utils \
- nodejs \
- && rm -rf /var/lib/apt/lists/*
-
-COPY scripts/sccache.sh /scripts/
-RUN sh /scripts/sccache.sh
-
-# We are disabling CI LLVM since this builder is intentionally using a host
-# LLVM, rather than the typical src/llvm-project LLVM.
-ENV NO_DOWNLOAD_CI_LLVM 1
-
-# Using llvm-link-shared due to libffi issues -- see #34486
-ENV RUST_CONFIGURE_ARGS \
- --build=x86_64-unknown-linux-gnu \
- --llvm-root=/usr/lib/llvm-13 \
- --enable-llvm-link-shared \
- --set rust.thin-lto-import-instr-limit=10
-
-ENV SCRIPT python2.7 ../x.py --stage 1 test --exclude src/tools/tidy && \
- # Run the `mir-opt` tests again but this time for a 32-bit target.
- # This enforces that tests using `// EMIT_MIR_FOR_EACH_BIT_WIDTH` have
- # both 32-bit and 64-bit outputs updated by the PR author, before
- # the PR is approved and tested for merging.
- # It will also detect tests lacking `// EMIT_MIR_FOR_EACH_BIT_WIDTH`,
- # despite having different output on 32-bit vs 64-bit targets.
- python2.7 ../x.py --stage 1 test tests/mir-opt \
- --host='' --target=i686-unknown-linux-gnu
diff --git a/src/ci/docker/host-x86_64/x86_64-gnu-llvm-14-stage1/Dockerfile b/src/ci/docker/host-x86_64/x86_64-gnu-llvm-14-stage1/Dockerfile
new file mode 100644
index 000000000..b99a0886b
--- /dev/null
+++ b/src/ci/docker/host-x86_64/x86_64-gnu-llvm-14-stage1/Dockerfile
@@ -0,0 +1,49 @@
+FROM ubuntu:22.04
+
+ARG DEBIAN_FRONTEND=noninteractive
+RUN apt-get update && apt-get install -y --no-install-recommends \
+ g++ \
+ gcc-multilib \
+ make \
+ ninja-build \
+ file \
+ curl \
+ ca-certificates \
+ python3 \
+ git \
+ cmake \
+ sudo \
+ gdb \
+ llvm-14-tools \
+ llvm-14-dev \
+ libedit-dev \
+ libssl-dev \
+ pkg-config \
+ zlib1g-dev \
+ xz-utils \
+ nodejs \
+ && rm -rf /var/lib/apt/lists/*
+
+COPY scripts/sccache.sh /scripts/
+RUN sh /scripts/sccache.sh
+
+# We are disabling CI LLVM since this builder is intentionally using a host
+# LLVM, rather than the typical src/llvm-project LLVM.
+ENV NO_DOWNLOAD_CI_LLVM 1
+
+# Using llvm-link-shared due to libffi issues -- see #34486
+ENV RUST_CONFIGURE_ARGS \
+ --build=x86_64-unknown-linux-gnu \
+ --llvm-root=/usr/lib/llvm-14 \
+ --enable-llvm-link-shared \
+ --set rust.thin-lto-import-instr-limit=10
+
+ENV SCRIPT ../x.py --stage 1 test --exclude src/tools/tidy && \
+ # Run the `mir-opt` tests again but this time for a 32-bit target.
+ # This enforces that tests using `// EMIT_MIR_FOR_EACH_BIT_WIDTH` have
+ # both 32-bit and 64-bit outputs updated by the PR author, before
+ # the PR is approved and tested for merging.
+ # It will also detect tests lacking `// EMIT_MIR_FOR_EACH_BIT_WIDTH`,
+ # despite having different output on 32-bit vs 64-bit targets.
+ ../x.py --stage 1 test tests/mir-opt \
+ --host='' --target=i686-unknown-linux-gnu
diff --git a/src/ci/docker/host-x86_64/x86_64-gnu-llvm-13/Dockerfile b/src/ci/docker/host-x86_64/x86_64-gnu-llvm-14/Dockerfile
index 9fc9e9cbf..db6032f87 100644
--- a/src/ci/docker/host-x86_64/x86_64-gnu-llvm-13/Dockerfile
+++ b/src/ci/docker/host-x86_64/x86_64-gnu-llvm-14/Dockerfile
@@ -12,27 +12,25 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
curl \
ca-certificates \
python2.7 \
- python3.9 \
+ python3 \
git \
cmake \
sudo \
gdb \
- llvm-13-tools \
- llvm-13-dev \
+ llvm-14-tools \
+ llvm-14-dev \
libedit-dev \
libssl-dev \
pkg-config \
zlib1g-dev \
xz-utils \
nodejs \
- \
-# Install powershell so we can test x.ps1 on Linux
- apt-transport-https software-properties-common && \
- curl -s "https://packages.microsoft.com/config/ubuntu/$(lsb_release -rs)/packages-microsoft-prod.deb" > packages-microsoft-prod.deb && \
- dpkg -i packages-microsoft-prod.deb && \
- apt-get update && \
- apt-get install -y powershell \
- && rm -rf /var/lib/apt/lists/*
+ && rm -rf /var/lib/apt/lists/*
+
+# Install powershell (universal package) so we can test x.ps1 on Linux
+RUN curl -sL "https://github.com/PowerShell/PowerShell/releases/download/v7.3.1/powershell_7.3.1-1.deb_amd64.deb" > powershell.deb && \
+ dpkg -i powershell.deb && \
+ rm -f powershell.deb
COPY scripts/sccache.sh /scripts/
RUN sh /scripts/sccache.sh
@@ -44,7 +42,7 @@ ENV NO_DOWNLOAD_CI_LLVM 1
# Using llvm-link-shared due to libffi issues -- see #34486
ENV RUST_CONFIGURE_ARGS \
--build=x86_64-unknown-linux-gnu \
- --llvm-root=/usr/lib/llvm-13 \
+ --llvm-root=/usr/lib/llvm-14 \
--enable-llvm-link-shared \
--set rust.thin-lto-import-instr-limit=10
diff --git a/src/ci/docker/host-x86_64/x86_64-gnu-llvm-15/Dockerfile b/src/ci/docker/host-x86_64/x86_64-gnu-llvm-15/Dockerfile
new file mode 100644
index 000000000..5219247cc
--- /dev/null
+++ b/src/ci/docker/host-x86_64/x86_64-gnu-llvm-15/Dockerfile
@@ -0,0 +1,67 @@
+FROM ubuntu:22.10
+
+ARG DEBIAN_FRONTEND=noninteractive
+
+# NOTE: intentionally installs both python2 and python3 so we can test support for both.
+RUN apt-get update && apt-get install -y --no-install-recommends \
+ g++ \
+ gcc-multilib \
+ make \
+ ninja-build \
+ file \
+ curl \
+ ca-certificates \
+ python2.7 \
+ python3 \
+ git \
+ cmake \
+ sudo \
+ gdb \
+ llvm-15-tools \
+ llvm-15-dev \
+ libedit-dev \
+ libssl-dev \
+ pkg-config \
+ zlib1g-dev \
+ xz-utils \
+ nodejs \
+ && rm -rf /var/lib/apt/lists/*
+
+# Install powershell (universal package) so we can test x.ps1 on Linux
+RUN curl -sL "https://github.com/PowerShell/PowerShell/releases/download/v7.3.1/powershell_7.3.1-1.deb_amd64.deb" > powershell.deb && \
+ dpkg -i powershell.deb && \
+ rm -f powershell.deb
+
+COPY scripts/sccache.sh /scripts/
+RUN sh /scripts/sccache.sh
+
+# We are disabling CI LLVM since this builder is intentionally using a host
+# LLVM, rather than the typical src/llvm-project LLVM.
+ENV NO_DOWNLOAD_CI_LLVM 1
+
+# Using llvm-link-shared due to libffi issues -- see #34486
+ENV RUST_CONFIGURE_ARGS \
+ --build=x86_64-unknown-linux-gnu \
+ --llvm-root=/usr/lib/llvm-15 \
+ --enable-llvm-link-shared \
+ --set rust.thin-lto-import-instr-limit=10
+
+# NOTE: intentionally uses all of `x.py`, `x`, and `x.ps1` to make sure they all work on Linux.
+ENV SCRIPT ../x.py --stage 2 test --exclude src/tools/tidy && \
+ # Run the `mir-opt` tests again but this time for a 32-bit target.
+ # This enforces that tests using `// EMIT_MIR_FOR_EACH_BIT_WIDTH` have
+ # both 32-bit and 64-bit outputs updated by the PR author, before
+ # the PR is approved and tested for merging.
+ # It will also detect tests lacking `// EMIT_MIR_FOR_EACH_BIT_WIDTH`,
+ # despite having different output on 32-bit vs 64-bit targets.
+ ../x --stage 2 test tests/mir-opt \
+ --host='' --target=i686-unknown-linux-gnu && \
+ # Run the UI test suite again, but in `--pass=check` mode
+ #
+ # This is intended to make sure that both `--pass=check` continues to
+ # work.
+ #
+ ../x.ps1 --stage 2 test tests/ui --pass=check \
+ --host='' --target=i686-unknown-linux-gnu && \
+ # Run tidy at the very end, after all the other tests.
+ python2.7 ../x.py --stage 2 test src/tools/tidy
diff --git a/src/ci/docker/host-x86_64/x86_64-gnu-tools/browser-ui-test.version b/src/ci/docker/host-x86_64/x86_64-gnu-tools/browser-ui-test.version
index c39e9c5fb..9c550b2d7 100644
--- a/src/ci/docker/host-x86_64/x86_64-gnu-tools/browser-ui-test.version
+++ b/src/ci/docker/host-x86_64/x86_64-gnu-tools/browser-ui-test.version
@@ -1 +1 @@
-0.14.1 \ No newline at end of file
+0.14.4 \ No newline at end of file
diff --git a/src/ci/docker/scripts/fuchsia-test-runner.py b/src/ci/docker/scripts/fuchsia-test-runner.py
index c8d1ff9ae..e7d1d9781 100755
--- a/src/ci/docker/scripts/fuchsia-test-runner.py
+++ b/src/ci/docker/scripts/fuchsia-test-runner.py
@@ -9,6 +9,7 @@ https://doc.rust-lang.org/stable/rustc/platform-support/fuchsia.html#aarch64-unk
import argparse
from dataclasses import dataclass
+import fcntl
import glob
import hashlib
import json
@@ -19,18 +20,18 @@ import shutil
import signal
import subprocess
import sys
-from typing import ClassVar, List
+from typing import ClassVar, List, Optional
@dataclass
class TestEnvironment:
rust_dir: str
sdk_dir: str
- target_arch: str
- package_server_pid: int = None
- emu_addr: str = None
- libstd_name: str = None
- libtest_name: str = None
+ target: str
+ package_server_pid: Optional[int] = None
+ emu_addr: Optional[str] = None
+ libstd_name: Optional[str] = None
+ libtest_name: Optional[str] = None
verbose: bool = False
@staticmethod
@@ -40,6 +41,15 @@ class TestEnvironment:
return os.path.abspath(tmp_dir)
return os.path.join(os.path.dirname(__file__), "tmp~")
+ @staticmethod
+ def triple_to_arch(triple):
+ if "x86_64" in triple:
+ return "x64"
+ elif "aarch64" in triple:
+ return "arm64"
+ else:
+ raise Exception(f"Unrecognized target triple {triple}")
+
@classmethod
def env_file_path(cls):
return os.path.join(cls.tmp_dir(), "test_env.json")
@@ -49,7 +59,7 @@ class TestEnvironment:
return cls(
os.path.abspath(args.rust),
os.path.abspath(args.sdk),
- args.target_arch,
+ args.target,
verbose=args.verbose,
)
@@ -60,7 +70,7 @@ class TestEnvironment:
return cls(
test_env["rust_dir"],
test_env["sdk_dir"],
- test_env["target_arch"],
+ test_env["target"],
libstd_name=test_env["libstd_name"],
libtest_name=test_env["libtest_name"],
emu_addr=test_env["emu_addr"],
@@ -68,13 +78,6 @@ class TestEnvironment:
verbose=test_env["verbose"],
)
- def image_name(self):
- if self.target_arch == "x64":
- return "qemu-x64"
- if self.target_arch == "arm64":
- return "qemu-arm64"
- raise Exception(f"Unrecognized target architecture {self.target_arch}")
-
def write_to_file(self):
with open(self.env_file_path(), "w", encoding="utf-8") as f:
f.write(json.dumps(self.__dict__))
@@ -108,13 +111,6 @@ class TestEnvironment:
def repo_dir(self):
return os.path.join(self.tmp_dir(), self.TEST_REPO_NAME)
- def rustlib_dir(self):
- if self.target_arch == "x64":
- return "x86_64-unknown-fuchsia"
- if self.target_arch == "arm64":
- return "aarch64-unknown-fuchsia"
- raise Exception(f"Unrecognized target architecture {self.target_arch}")
-
def libs_dir(self):
return os.path.join(
self.rust_dir,
@@ -125,7 +121,7 @@ class TestEnvironment:
return os.path.join(
self.libs_dir(),
"rustlib",
- self.rustlib_dir(),
+ self.target,
"lib",
)
@@ -151,6 +147,9 @@ class TestEnvironment:
def zxdb_script_path(self):
return os.path.join(self.tmp_dir(), "zxdb_script")
+ def pm_lockfile_path(self):
+ return os.path.join(self.tmp_dir(), "pm.lock")
+
def log_info(self, msg):
print(msg)
@@ -384,7 +383,7 @@ class TestEnvironment:
"--emulator-log",
self.emulator_log_path(),
"--image-name",
- self.image_name(),
+ "qemu-" + self.triple_to_arch(self.target),
],
stdout=self.subprocess_output(),
stderr=self.subprocess_output(),
@@ -465,6 +464,9 @@ class TestEnvironment:
stderr=self.subprocess_output(),
)
+ # Create lockfiles
+ open(self.pm_lockfile_path(), 'a').close()
+
# Write to file
self.write_to_file()
@@ -512,9 +514,8 @@ class TestEnvironment:
bin/{exe_name}={bin_path}
lib/{libstd_name}={rust_dir}/lib/rustlib/{rustlib_dir}/lib/{libstd_name}
lib/{libtest_name}={rust_dir}/lib/rustlib/{rustlib_dir}/lib/{libtest_name}
- lib/ld.so.1={sdk_dir}/arch/{target_arch}/sysroot/lib/libc.so
- lib/libzircon.so={sdk_dir}/arch/{target_arch}/sysroot/lib/libzircon.so
- lib/libfdio.so={sdk_dir}/arch/{target_arch}/lib/libfdio.so
+ lib/ld.so.1={sdk_dir}/arch/{target_arch}/sysroot/dist/lib/ld.so.1
+ lib/libfdio.so={sdk_dir}/arch/{target_arch}/dist/libfdio.so
"""
TEST_ENV_VARS: ClassVar[List[str]] = [
@@ -642,11 +643,11 @@ class TestEnvironment:
package_dir=package_dir,
package_name=package_name,
rust_dir=self.rust_dir,
- rustlib_dir=self.rustlib_dir(),
+ rustlib_dir=self.target,
sdk_dir=self.sdk_dir,
libstd_name=self.libstd_name,
libtest_name=self.libtest_name,
- target_arch=self.target_arch,
+ target_arch=self.triple_to_arch(self.target),
)
)
for shared_lib in shared_libs:
@@ -682,19 +683,25 @@ class TestEnvironment:
log("Publishing package to repo...")
# Publish package to repo
- subprocess.check_call(
- [
- self.tool_path("pm"),
- "publish",
- "-a",
- "-repo",
- self.repo_dir(),
- "-f",
- far_path,
- ],
- stdout=log_file,
- stderr=log_file,
- )
+ with open(self.pm_lockfile_path(), 'w') as pm_lockfile:
+ fcntl.lockf(pm_lockfile.fileno(), fcntl.LOCK_EX)
+ subprocess.check_call(
+ [
+ self.tool_path("pm"),
+ "publish",
+ "-a",
+ "-repo",
+ self.repo_dir(),
+ "-f",
+ far_path,
+ ],
+ stdout=log_file,
+ stderr=log_file,
+ )
+ # This lock should be released automatically when the pm
+ # lockfile is closed, but we'll be polite and unlock it now
+ # since the spec leaves some wiggle room.
+ fcntl.lockf(pm_lockfile.fileno(), fcntl.LOCK_UN)
log("Running ffx test...")
@@ -849,23 +856,34 @@ class TestEnvironment:
"--",
"--build-id-dir",
os.path.join(self.sdk_dir, ".build-id"),
- "--build-id-dir",
- os.path.join(self.libs_dir(), ".build-id"),
]
- # Add rust source if it's available
- if args.rust_src is not None:
+ libs_build_id_path = os.path.join(self.libs_dir(), ".build-id")
+ if os.path.exists(libs_build_id_path):
+ # Add .build-id symbols if installed libs have been stripped into a
+ # .build-id directory
command += [
- "--build-dir",
- args.rust_src,
+ "--build-id-dir",
+ libs_build_id_path,
+ ]
+ else:
+ # If no .build-id directory is detected, then assume that the shared
+ # libs contain their debug symbols
+ command += [
+ f"--symbol-path={self.rust_dir}/lib/rustlib/{self.target}/lib",
]
+ # Add rust source if it's available
+ rust_src_map = None
+ if args.rust_src is not None:
+ # This matches the remapped prefix used by compiletest. There's no
+ # clear way that we can determine this, so it's hard coded.
+ rust_src_map = f"/rustc/FAKE_PREFIX={args.rust_src}"
+
# Add fuchsia source if it's available
+ fuchsia_src_map = None
if args.fuchsia_src is not None:
- command += [
- "--build-dir",
- os.path.join(args.fuchsia_src, "out", "default"),
- ]
+ fuchsia_src_map = f"./../..={args.fuchsia_src}"
# Load debug symbols for the test binary and automatically attach
if args.test is not None:
@@ -888,7 +906,28 @@ class TestEnvironment:
test_name,
)
+ # The fake-test-src-base directory maps to the suite directory
+ # e.g. tests/ui/foo.rs has a path of rust/fake-test-src-base/foo.rs
+ fake_test_src_base = os.path.join(
+ args.rust_src,
+ "fake-test-src-base",
+ )
+ real_test_src_base = os.path.join(
+ args.rust_src,
+ "tests",
+ args.test.split(os.path.sep)[0],
+ )
+ test_src_map = f"{fake_test_src_base}={real_test_src_base}"
+
with open(self.zxdb_script_path(), mode="w", encoding="utf-8") as f:
+ print(f"set source-map += {test_src_map}", file=f)
+
+ if rust_src_map is not None:
+ print(f"set source-map += {rust_src_map}", file=f)
+
+ if fuchsia_src_map is not None:
+ print(f"set source-map += {fuchsia_src_map}", file=f)
+
print(f"attach {test_name[:31]}", file=f)
command += [
@@ -905,6 +944,20 @@ class TestEnvironment:
# Connect to the running emulator with zxdb
subprocess.run(command, env=self.ffx_cmd_env(), check=False)
+ def syslog(self, args):
+ subprocess.run(
+ [
+ self.tool_path("ffx"),
+ "--config",
+ self.ffx_user_config_path(),
+ "log",
+ "--since",
+ "now",
+ ],
+ env=self.ffx_cmd_env(),
+ check=False,
+ )
+
def start(args):
test_env = TestEnvironment.from_args(args)
@@ -938,6 +991,12 @@ def debug(args):
return 0
+def syslog(args):
+ test_env = TestEnvironment.read_from_file()
+ test_env.syslog(args)
+ return 0
+
+
def main():
parser = argparse.ArgumentParser()
@@ -969,8 +1028,8 @@ def main():
action="store_true",
)
start_parser.add_argument(
- "--target-arch",
- help="the architecture of the image to test",
+ "--target",
+ help="the target platform to test",
required=True,
)
start_parser.set_defaults(func=start)
@@ -1033,6 +1092,11 @@ def main():
)
debug_parser.set_defaults(func=debug)
+ syslog_parser = subparsers.add_parser(
+ "syslog", help="prints the device syslog"
+ )
+ syslog_parser.set_defaults(func=syslog)
+
args = parser.parse_args()
return args.func(args)
diff --git a/src/ci/github-actions/ci.yml b/src/ci/github-actions/ci.yml
index 743b57ed4..c594288dc 100644
--- a/src/ci/github-actions/ci.yml
+++ b/src/ci/github-actions/ci.yml
@@ -33,6 +33,7 @@ x--expand-yaml-anchors--remove:
- &shared-ci-variables
CI_JOB_NAME: ${{ matrix.name }}
+ CARGO_REGISTRIES_CRATES_IO_PROTOCOL: sparse
- &public-variables
SCCACHE_BUCKET: rust-lang-ci-sccache2
@@ -73,15 +74,15 @@ x--expand-yaml-anchors--remove:
env: {}
- &job-linux-xl
- os: ubuntu-20.04-xl
+ os: ubuntu-20.04-16core-64gb
<<: *base-job
- &job-macos-xl
- os: macos-latest # We don't have an XL builder for this
+ os: macos-12-xl
<<: *base-job
- &job-windows-xl
- os: windows-latest-xl
+ os: windows-2019-8core-32gb
<<: *base-job
- &job-aarch64-linux
@@ -299,15 +300,13 @@ jobs:
<<: *job-linux-xl
tidy: true
- - name: x86_64-gnu-llvm-13
+ - name: x86_64-gnu-llvm-14
<<: *job-linux-xl
tidy: false
- name: x86_64-gnu-tools
<<: *job-linux-xl
tidy: false
- env:
- CI_ONLY_WHEN_SUBMODULES_CHANGED: 1
auto:
permissions:
@@ -450,12 +449,17 @@ jobs:
- name: x86_64-gnu-distcheck
<<: *job-linux-xl
- - name: x86_64-gnu-llvm-13
+ - name: x86_64-gnu-llvm-15
+ env:
+ RUST_BACKTRACE: 1
+ <<: *job-linux-xl
+
+ - name: x86_64-gnu-llvm-14
env:
RUST_BACKTRACE: 1
<<: *job-linux-xl
- - name: x86_64-gnu-llvm-13-stage1
+ - name: x86_64-gnu-llvm-14-stage1
env:
RUST_BACKTRACE: 1
<<: *job-linux-xl
@@ -619,9 +623,7 @@ jobs:
- name: i686-mingw-1
env:
- RUST_CONFIGURE_ARGS: >-
- --build=i686-pc-windows-gnu
- --set llvm.allow-old-toolchain
+ RUST_CONFIGURE_ARGS: --build=i686-pc-windows-gnu
SCRIPT: make ci-mingw-subset-1
# We are intentionally allowing an old toolchain on this builder (and that's
# incompatible with LLVM downloads today).
@@ -631,9 +633,7 @@ jobs:
- name: i686-mingw-2
env:
- RUST_CONFIGURE_ARGS: >-
- --build=i686-pc-windows-gnu
- --set llvm.allow-old-toolchain
+ RUST_CONFIGURE_ARGS: --build=i686-pc-windows-gnu
SCRIPT: make ci-mingw-subset-2
# We are intentionally allowing an old toolchain on this builder (and that's
# incompatible with LLVM downloads today).
@@ -647,7 +647,6 @@ jobs:
RUST_CONFIGURE_ARGS: >-
--build=x86_64-pc-windows-gnu
--enable-profiler
- --set llvm.allow-old-toolchain
# We are intentionally allowing an old toolchain on this builder (and that's
# incompatible with LLVM downloads today).
NO_DOWNLOAD_CI_LLVM: 1
@@ -660,7 +659,6 @@ jobs:
RUST_CONFIGURE_ARGS: >-
--build=x86_64-pc-windows-gnu
--enable-profiler
- --set llvm.allow-old-toolchain
# We are intentionally allowing an old toolchain on this builder (and that's
# incompatible with LLVM downloads today).
NO_DOWNLOAD_CI_LLVM: 1
@@ -675,7 +673,7 @@ jobs:
--target=x86_64-pc-windows-msvc
--enable-full-tools
--enable-profiler
- SCRIPT: PGO_HOST=x86_64-pc-windows-msvc src/ci/pgo.sh python x.py dist bootstrap --include-default-paths
+ SCRIPT: PGO_HOST=x86_64-pc-windows-msvc python src/ci/stage-build.py python x.py dist bootstrap --include-default-paths
DIST_REQUIRE_ALL_TOOLS: 1
<<: *job-windows-xl
@@ -711,7 +709,6 @@ jobs:
--build=i686-pc-windows-gnu
--enable-full-tools
--enable-profiler
- --set llvm.allow-old-toolchain
# We are intentionally allowing an old toolchain on this builder (and that's
# incompatible with LLVM downloads today).
NO_DOWNLOAD_CI_LLVM: 1
@@ -727,7 +724,6 @@ jobs:
--build=x86_64-pc-windows-gnu
--enable-full-tools
--enable-profiler
- --set llvm.allow-old-toolchain
# We are intentionally allowing an old toolchain on this builder (and that's
# incompatible with LLVM downloads today).
NO_DOWNLOAD_CI_LLVM: 1
diff --git a/src/ci/pgo.sh b/src/ci/pgo.sh
deleted file mode 100755
index cbe32920a..000000000
--- a/src/ci/pgo.sh
+++ /dev/null
@@ -1,230 +0,0 @@
-#!/bin/bash
-# ignore-tidy-linelength
-
-set -euxo pipefail
-
-ci_dir=`cd $(dirname $0) && pwd`
-source "$ci_dir/shared.sh"
-
-# The root checkout, where the source is located
-CHECKOUT=/checkout
-
-DOWNLOADED_LLVM=/rustroot
-
-# The main directory where the build occurs, which can be different between linux and windows
-BUILD_ROOT=$CHECKOUT/obj
-
-if isWindows; then
- CHECKOUT=$(pwd)
- DOWNLOADED_LLVM=$CHECKOUT/citools/clang-rust
- BUILD_ROOT=$CHECKOUT
-fi
-
-# The various build artifacts used in other commands: to launch rustc builds, build the perf
-# collector, and run benchmarks to gather profiling data
-BUILD_ARTIFACTS=$BUILD_ROOT/build/$PGO_HOST
-RUSTC_STAGE_0=$BUILD_ARTIFACTS/stage0/bin/rustc
-CARGO_STAGE_0=$BUILD_ARTIFACTS/stage0/bin/cargo
-RUSTC_STAGE_2=$BUILD_ARTIFACTS/stage2/bin/rustc
-
-# Windows needs these to have the .exe extension
-if isWindows; then
- RUSTC_STAGE_0="${RUSTC_STAGE_0}.exe"
- CARGO_STAGE_0="${CARGO_STAGE_0}.exe"
- RUSTC_STAGE_2="${RUSTC_STAGE_2}.exe"
-fi
-
-# Make sure we have a temporary PGO work folder
-PGO_TMP=/tmp/tmp-pgo
-mkdir -p $PGO_TMP
-rm -rf $PGO_TMP/*
-
-RUSTC_PERF=$PGO_TMP/rustc-perf
-
-# Compile several crates to gather execution PGO profiles.
-# Arg0 => profiles (Debug, Opt)
-# Arg1 => scenarios (Full, IncrFull, All)
-# Arg2 => crates (syn, cargo, ...)
-gather_profiles () {
- cd $BUILD_ROOT
-
- # Compile libcore, both in opt-level=0 and opt-level=3
- RUSTC_BOOTSTRAP=1 $RUSTC_STAGE_2 \
- --edition=2021 --crate-type=lib $CHECKOUT/library/core/src/lib.rs \
- --out-dir $PGO_TMP
- RUSTC_BOOTSTRAP=1 $RUSTC_STAGE_2 \
- --edition=2021 --crate-type=lib -Copt-level=3 $CHECKOUT/library/core/src/lib.rs \
- --out-dir $PGO_TMP
-
- cd $RUSTC_PERF
-
- # Run rustc-perf benchmarks
- # Benchmark using profile_local with eprintln, which essentially just means
- # don't actually benchmark -- just make sure we run rustc a bunch of times.
- RUST_LOG=collector=debug \
- RUSTC=$RUSTC_STAGE_0 \
- RUSTC_BOOTSTRAP=1 \
- $CARGO_STAGE_0 run -p collector --bin collector -- \
- profile_local \
- eprintln \
- $RUSTC_STAGE_2 \
- --id Test \
- --profiles $1 \
- --cargo $CARGO_STAGE_0 \
- --scenarios $2 \
- --include $3
-
- cd $BUILD_ROOT
-}
-
-# This path has to be absolute
-LLVM_PROFILE_DIRECTORY_ROOT=$PGO_TMP/llvm-pgo
-
-# We collect LLVM profiling information and rustc profiling information in
-# separate phases. This increases build time -- though not by a huge amount --
-# but prevents any problems from arising due to different profiling runtimes
-# being simultaneously linked in.
-# LLVM IR PGO does not respect LLVM_PROFILE_FILE, so we have to set the profiling file
-# path through our custom environment variable. We include the PID in the directory path
-# to avoid updates to profile files being lost because of race conditions.
-LLVM_PROFILE_DIR=${LLVM_PROFILE_DIRECTORY_ROOT}/prof-%p python3 $CHECKOUT/x.py build \
- --target=$PGO_HOST \
- --host=$PGO_HOST \
- --stage 2 library/std \
- --llvm-profile-generate
-
-# Compile rustc-perf:
-# - get the expected commit source code: on linux, the Dockerfile downloads a source archive before
-# running this script. On Windows, we do that here.
-if isLinux; then
- cp -r /tmp/rustc-perf $RUSTC_PERF
- chown -R $(whoami): $RUSTC_PERF
-else
- # rustc-perf version from 2022-07-22
- PERF_COMMIT=3c253134664fdcba862c539d37f0de18557a9a4c
- retry curl -LS -o $PGO_TMP/perf.zip \
- https://github.com/rust-lang/rustc-perf/archive/$PERF_COMMIT.zip && \
- cd $PGO_TMP && unzip -q perf.zip && \
- mv rustc-perf-$PERF_COMMIT $RUSTC_PERF && \
- rm perf.zip
-fi
-
-# - build rustc-perf's collector ahead of time, which is needed to make sure the rustc-fake binary
-# used by the collector is present.
-cd $RUSTC_PERF
-
-RUSTC=$RUSTC_STAGE_0 \
-RUSTC_BOOTSTRAP=1 \
-$CARGO_STAGE_0 build -p collector
-
-# Here we're profiling LLVM, so we only care about `Debug` and `Opt`, because we want to stress
-# codegen. We also profile some of the most prolific crates.
-gather_profiles "Debug,Opt" "Full" \
- "syn-1.0.89,cargo-0.60.0,serde-1.0.136,ripgrep-13.0.0,regex-1.5.5,clap-3.1.6,hyper-0.14.18"
-
-LLVM_PROFILE_MERGED_FILE=$PGO_TMP/llvm-pgo.profdata
-
-# Merge the profile data we gathered for LLVM
-# Note that this uses the profdata from the clang we used to build LLVM,
-# which likely has a different version than our in-tree clang.
-$DOWNLOADED_LLVM/bin/llvm-profdata merge -o ${LLVM_PROFILE_MERGED_FILE} ${LLVM_PROFILE_DIRECTORY_ROOT}
-
-echo "LLVM PGO statistics"
-du -sh ${LLVM_PROFILE_MERGED_FILE}
-du -sh ${LLVM_PROFILE_DIRECTORY_ROOT}
-echo "Profile file count"
-find ${LLVM_PROFILE_DIRECTORY_ROOT} -type f | wc -l
-
-# We don't need the individual .profraw files now that they have been merged into a final .profdata
-rm -r $LLVM_PROFILE_DIRECTORY_ROOT
-
-# Rustbuild currently doesn't support rebuilding LLVM when PGO options
-# change (or any other llvm-related options); so just clear out the relevant
-# directories ourselves.
-rm -r $BUILD_ARTIFACTS/llvm $BUILD_ARTIFACTS/lld
-
-# Okay, LLVM profiling is done, switch to rustc PGO.
-
-# The path has to be absolute
-RUSTC_PROFILE_DIRECTORY_ROOT=$PGO_TMP/rustc-pgo
-
-python3 $CHECKOUT/x.py build --target=$PGO_HOST --host=$PGO_HOST \
- --stage 2 library/std \
- --rust-profile-generate=${RUSTC_PROFILE_DIRECTORY_ROOT}
-
-# Here we're profiling the `rustc` frontend, so we also include `Check`.
-# The benchmark set includes various stress tests that put the frontend under pressure.
-if isLinux; then
- # The profile data is written into a single filepath that is being repeatedly merged when each
- # rustc invocation ends. Empirically, this can result in some profiling data being lost. That's
- # why we override the profile path to include the PID. This will produce many more profiling
- # files, but the resulting profile will produce a slightly faster rustc binary.
- LLVM_PROFILE_FILE=${RUSTC_PROFILE_DIRECTORY_ROOT}/default_%m_%p.profraw gather_profiles \
- "Check,Debug,Opt" "All" \
- "externs,ctfe-stress-5,cargo-0.60.0,token-stream-stress,match-stress,tuple-stress,diesel-1.4.8,bitmaps-3.1.0"
-else
- # On windows, we don't do that yet (because it generates a lot of data, hitting disk space
- # limits on the builder), and use the default profraw merging behavior.
- gather_profiles \
- "Check,Debug,Opt" "All" \
- "externs,ctfe-stress-5,cargo-0.60.0,token-stream-stress,match-stress,tuple-stress,diesel-1.4.8,bitmaps-3.1.0"
-fi
-
-RUSTC_PROFILE_MERGED_FILE=$PGO_TMP/rustc-pgo.profdata
-
-# Merge the profile data we gathered
-$BUILD_ARTIFACTS/llvm/bin/llvm-profdata \
- merge -o ${RUSTC_PROFILE_MERGED_FILE} ${RUSTC_PROFILE_DIRECTORY_ROOT}
-
-echo "Rustc PGO statistics"
-du -sh ${RUSTC_PROFILE_MERGED_FILE}
-du -sh ${RUSTC_PROFILE_DIRECTORY_ROOT}
-echo "Profile file count"
-find ${RUSTC_PROFILE_DIRECTORY_ROOT} -type f | wc -l
-
-# We don't need the individual .profraw files now that they have been merged into a final .profdata
-rm -r $RUSTC_PROFILE_DIRECTORY_ROOT
-
-# Rustbuild currently doesn't support rebuilding LLVM when PGO options
-# change (or any other llvm-related options); so just clear out the relevant
-# directories ourselves.
-rm -r $BUILD_ARTIFACTS/llvm $BUILD_ARTIFACTS/lld
-
-if isLinux; then
- # Gather BOLT profile (BOLT is currently only available on Linux)
- python3 ../x.py build --target=$PGO_HOST --host=$PGO_HOST \
- --stage 2 library/std \
- --llvm-profile-use=${LLVM_PROFILE_MERGED_FILE} \
- --llvm-bolt-profile-generate
-
- BOLT_PROFILE_MERGED_FILE=/tmp/bolt.profdata
-
- # Here we're profiling Bolt.
- gather_profiles "Check,Debug,Opt" "Full" \
- "syn-1.0.89,serde-1.0.136,ripgrep-13.0.0,regex-1.5.5,clap-3.1.6,hyper-0.14.18"
-
- merge-fdata /tmp/prof.fdata* > ${BOLT_PROFILE_MERGED_FILE}
-
- echo "BOLT statistics"
- du -sh /tmp/prof.fdata*
- du -sh ${BOLT_PROFILE_MERGED_FILE}
- echo "Profile file count"
- find /tmp/prof.fdata* -type f | wc -l
-
- rm -r $BUILD_ARTIFACTS/llvm $BUILD_ARTIFACTS/lld
-
- # This produces the actual final set of artifacts, using both the LLVM and rustc
- # collected profiling data.
- $@ \
- --rust-profile-use=${RUSTC_PROFILE_MERGED_FILE} \
- --llvm-profile-use=${LLVM_PROFILE_MERGED_FILE} \
- --llvm-bolt-profile-use=${BOLT_PROFILE_MERGED_FILE}
-else
- $@ \
- --rust-profile-use=${RUSTC_PROFILE_MERGED_FILE} \
- --llvm-profile-use=${LLVM_PROFILE_MERGED_FILE}
-fi
-
-echo "Rustc binary size"
-ls -la ./build/$PGO_HOST/stage2/bin
-ls -la ./build/$PGO_HOST/stage2/lib
diff --git a/src/ci/run.sh b/src/ci/run.sh
index 0db9c993e..efeb850cd 100755
--- a/src/ci/run.sh
+++ b/src/ci/run.sh
@@ -45,6 +45,8 @@ fi
ci_dir=`cd $(dirname $0) && pwd`
source "$ci_dir/shared.sh"
+export CARGO_REGISTRIES_CRATES_IO_PROTOCOL=sparse
+
if ! isCI || isCiBranch auto || isCiBranch beta || isCiBranch try || isCiBranch try-perf; then
RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --set build.print-step-timings --enable-verbose-tests"
RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --set build.metrics"
@@ -57,6 +59,14 @@ RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --enable-locked-deps"
RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --enable-cargo-native-static"
RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --set rust.codegen-units-std=1"
+# When building for mingw, limit the number of parallel linker jobs during
+# the LLVM build, as not to run out of memory.
+# This is an attempt to fix the spurious build error tracked by
+# https://github.com/rust-lang/rust/issues/108227.
+if isWindows && [[ ${CUSTOM_MINGW-0} -eq 1 ]]; then
+ RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --set llvm.link-jobs=1"
+fi
+
# Only produce xz tarballs on CI. gz tarballs will be generated by the release
# process by recompressing the existing xz ones. This decreases the storage
# space required for CI artifacts.
diff --git a/src/ci/scripts/install-mingw.sh b/src/ci/scripts/install-mingw.sh
index 1685fbbbb..7eccb9b86 100755
--- a/src/ci/scripts/install-mingw.sh
+++ b/src/ci/scripts/install-mingw.sh
@@ -2,24 +2,6 @@
# If we need to download a custom MinGW, do so here and set the path
# appropriately.
#
-# Here we also do a pretty heinous thing which is to mangle the MinGW
-# installation we just downloaded. Currently, as of this writing, we're using
-# MinGW-w64 builds of gcc, and that's currently at 6.3.0. We use 6.3.0 as it
-# appears to be the first version which contains a fix for #40546, builds
-# randomly failing during LLVM due to ar.exe/ranlib.exe failures.
-#
-# Unfortunately, though, 6.3.0 *also* is the first version of MinGW-w64 builds
-# to contain a regression in gdb (#40184). As a result if we were to use the
-# gdb provided (7.11.1) then we would fail all debuginfo tests.
-#
-# In order to fix spurious failures (pretty high priority) we use 6.3.0. To
-# avoid disabling gdb tests we download an *old* version of gdb, specifically
-# that found inside the 6.2.0 distribution. We then overwrite the 6.3.0 gdb
-# with the 6.2.0 gdb to get tests passing.
-#
-# Note that we don't literally overwrite the gdb.exe binary because it appears
-# to just use gdborig.exe, so that's the binary we deal with instead.
-#
# Otherwise install MinGW through `pacman`
set -euo pipefail
@@ -27,8 +9,8 @@ IFS=$'\n\t'
source "$(cd "$(dirname "$0")" && pwd)/../shared.sh"
-MINGW_ARCHIVE_32="i686-6.3.0-release-posix-dwarf-rt_v5-rev2.7z"
-MINGW_ARCHIVE_64="x86_64-6.3.0-release-posix-seh-rt_v5-rev2.7z"
+MINGW_ARCHIVE_32="i686-12.2.0-release-posix-dwarf-rt_v10-rev0.7z"
+MINGW_ARCHIVE_64="x86_64-12.2.0-release-posix-seh-rt_v10-rev0.7z"
if isWindows; then
case "${CI_JOB_NAME}" in
@@ -66,7 +48,6 @@ if isWindows; then
curl -o mingw.7z "${MIRRORS_BASE}/${mingw_archive}"
7z x -y mingw.7z > /dev/null
- curl -o "${mingw_dir}/bin/gdborig.exe" "${MIRRORS_BASE}/2017-04-20-${bits}bit-gdborig.exe"
ciCommandAddPath "$(pwd)/${mingw_dir}/bin"
fi
fi
diff --git a/src/ci/scripts/should-skip-this.sh b/src/ci/scripts/should-skip-this.sh
index 85d772253..48127166a 100755
--- a/src/ci/scripts/should-skip-this.sh
+++ b/src/ci/scripts/should-skip-this.sh
@@ -1,46 +1,11 @@
#!/bin/bash
-# Set the SKIP_JOB environment variable if this job is supposed to only run
-# when submodules are updated and they were not. The following time consuming
-# tasks will be skipped when the environment variable is present.
+# Set the SKIP_JOB environment variable if this job is not supposed to run on the current builder.
set -euo pipefail
IFS=$'\n\t'
source "$(cd "$(dirname "$0")" && pwd)/../shared.sh"
-if [[ -n "${CI_ONLY_WHEN_SUBMODULES_CHANGED-}" ]]; then
- git fetch "https://github.com/$GITHUB_REPOSITORY" "$GITHUB_BASE_REF"
- BASE_COMMIT="$(git merge-base FETCH_HEAD HEAD)"
-
- echo "Searching for toolstate changes between $BASE_COMMIT and $(git rev-parse HEAD)"
-
- if git diff "$BASE_COMMIT" | grep --quiet "^index .* 160000"; then
- # Submodules pseudo-files inside git have the 160000 permissions, so when
- # those files are present in the diff a submodule was updated.
- echo "Submodules were updated"
- elif ! (git diff --quiet "$BASE_COMMIT" -- \
- src/tools/clippy src/tools/rustfmt src/tools/miri \
- library/std/src/sys); then
- # There is not an easy blanket search for subtrees. For now, manually list
- # the subtrees.
- # Also run this when the platform-specific parts of std change, in case
- # that breaks Miri.
- echo "Tool subtrees were updated"
- elif ! (git diff --quiet "$BASE_COMMIT" -- \
- tests/rustdoc-gui \
- src/librustdoc \
- src/ci/docker/host-x86_64/x86_64-gnu-tools/Dockerfile \
- src/ci/docker/host-x86_64/x86_64-gnu-tools/browser-ui-test.version \
- src/tools/rustdoc-gui); then
- # There was a change in either rustdoc or in its GUI tests.
- echo "Rustdoc was updated"
- else
- echo "Not executing this job since no submodules nor subtrees were updated"
- ciCommandSetEnv SKIP_JOB 1
- exit 0
- fi
-fi
-
if [[ -n "${CI_ONLY_WHEN_CHANNEL-}" ]]; then
if [[ "${CI_ONLY_WHEN_CHANNEL}" = "$(cat src/ci/channel)" ]]; then
echo "The channel is the expected one"
diff --git a/src/ci/stage-build.py b/src/ci/stage-build.py
new file mode 100644
index 000000000..bd8fd524a
--- /dev/null
+++ b/src/ci/stage-build.py
@@ -0,0 +1,842 @@
+#!/usr/bin/env python3
+# ignore-tidy-linelength
+
+# Compatible with Python 3.6+
+
+import contextlib
+import getpass
+import glob
+import json
+import logging
+import os
+import pprint
+import shutil
+import subprocess
+import sys
+import time
+import traceback
+import urllib.request
+from io import StringIO
+from pathlib import Path
+from typing import Callable, ContextManager, Dict, Iterable, Iterator, List, Optional, \
+ Tuple, Union
+
+PGO_HOST = os.environ["PGO_HOST"]
+
+LOGGER = logging.getLogger("stage-build")
+
+LLVM_PGO_CRATES = [
+ "syn-1.0.89",
+ "cargo-0.60.0",
+ "serde-1.0.136",
+ "ripgrep-13.0.0",
+ "regex-1.5.5",
+ "clap-3.1.6",
+ "hyper-0.14.18"
+]
+
+RUSTC_PGO_CRATES = [
+ "externs",
+ "ctfe-stress-5",
+ "cargo-0.60.0",
+ "token-stream-stress",
+ "match-stress",
+ "tuple-stress",
+ "diesel-1.4.8",
+ "bitmaps-3.1.0"
+]
+
+LLVM_BOLT_CRATES = LLVM_PGO_CRATES
+
+
+class Pipeline:
+ # Paths
+ def checkout_path(self) -> Path:
+ """
+ The root checkout, where the source is located.
+ """
+ raise NotImplementedError
+
+ def downloaded_llvm_dir(self) -> Path:
+ """
+ Directory where the host LLVM is located.
+ """
+ raise NotImplementedError
+
+ def build_root(self) -> Path:
+ """
+ The main directory where the build occurs.
+ """
+ raise NotImplementedError
+
+ def build_artifacts(self) -> Path:
+ return self.build_root() / "build" / PGO_HOST
+
+ def rustc_stage_0(self) -> Path:
+ return self.build_artifacts() / "stage0" / "bin" / "rustc"
+
+ def cargo_stage_0(self) -> Path:
+ return self.build_artifacts() / "stage0" / "bin" / "cargo"
+
+ def rustc_stage_2(self) -> Path:
+ return self.build_artifacts() / "stage2" / "bin" / "rustc"
+
+ def opt_artifacts(self) -> Path:
+ raise NotImplementedError
+
+ def llvm_profile_dir_root(self) -> Path:
+ return self.opt_artifacts() / "llvm-pgo"
+
+ def llvm_profile_merged_file(self) -> Path:
+ return self.opt_artifacts() / "llvm-pgo.profdata"
+
+ def rustc_perf_dir(self) -> Path:
+ return self.opt_artifacts() / "rustc-perf"
+
+ def build_rustc_perf(self):
+ raise NotImplementedError()
+
+ def rustc_profile_dir_root(self) -> Path:
+ return self.opt_artifacts() / "rustc-pgo"
+
+ def rustc_profile_merged_file(self) -> Path:
+ return self.opt_artifacts() / "rustc-pgo.profdata"
+
+ def rustc_profile_template_path(self) -> Path:
+ """
+ The profile data is written into a single filepath that is being repeatedly merged when each
+ rustc invocation ends. Empirically, this can result in some profiling data being lost. That's
+ why we override the profile path to include the PID. This will produce many more profiling
+ files, but the resulting profile will produce a slightly faster rustc binary.
+ """
+ return self.rustc_profile_dir_root() / "default_%m_%p.profraw"
+
+ def supports_bolt(self) -> bool:
+ raise NotImplementedError
+
+ def llvm_bolt_profile_merged_file(self) -> Path:
+ return self.opt_artifacts() / "bolt.profdata"
+
+ def metrics_path(self) -> Path:
+ return self.build_root() / "build" / "metrics.json"
+
+
+class LinuxPipeline(Pipeline):
+ def checkout_path(self) -> Path:
+ return Path("/checkout")
+
+ def downloaded_llvm_dir(self) -> Path:
+ return Path("/rustroot")
+
+ def build_root(self) -> Path:
+ return self.checkout_path() / "obj"
+
+ def opt_artifacts(self) -> Path:
+ return Path("/tmp/tmp-multistage/opt-artifacts")
+
+ def build_rustc_perf(self):
+ # /tmp/rustc-perf comes from the Dockerfile
+ shutil.copytree("/tmp/rustc-perf", self.rustc_perf_dir())
+ cmd(["chown", "-R", f"{getpass.getuser()}:", self.rustc_perf_dir()])
+
+ with change_cwd(self.rustc_perf_dir()):
+ cmd([self.cargo_stage_0(), "build", "-p", "collector"], env=dict(
+ RUSTC=str(self.rustc_stage_0()),
+ RUSTC_BOOTSTRAP="1"
+ ))
+
+ def supports_bolt(self) -> bool:
+ return True
+
+
+class WindowsPipeline(Pipeline):
+ def __init__(self):
+ self.checkout_dir = Path(os.getcwd())
+
+ def checkout_path(self) -> Path:
+ return self.checkout_dir
+
+ def downloaded_llvm_dir(self) -> Path:
+ return self.checkout_path() / "citools" / "clang-rust"
+
+ def build_root(self) -> Path:
+ return self.checkout_path()
+
+ def opt_artifacts(self) -> Path:
+ return self.checkout_path() / "opt-artifacts"
+
+ def rustc_stage_0(self) -> Path:
+ return super().rustc_stage_0().with_suffix(".exe")
+
+ def cargo_stage_0(self) -> Path:
+ return super().cargo_stage_0().with_suffix(".exe")
+
+ def rustc_stage_2(self) -> Path:
+ return super().rustc_stage_2().with_suffix(".exe")
+
+ def build_rustc_perf(self):
+ # rustc-perf version from 2022-07-22
+ perf_commit = "3c253134664fdcba862c539d37f0de18557a9a4c"
+ rustc_perf_zip_path = self.opt_artifacts() / "perf.zip"
+
+ def download_rustc_perf():
+ download_file(
+ f"https://github.com/rust-lang/rustc-perf/archive/{perf_commit}.zip",
+ rustc_perf_zip_path
+ )
+ with change_cwd(self.opt_artifacts()):
+ unpack_archive(rustc_perf_zip_path)
+ move_path(Path(f"rustc-perf-{perf_commit}"), self.rustc_perf_dir())
+ delete_file(rustc_perf_zip_path)
+
+ retry_action(download_rustc_perf, "Download rustc-perf")
+
+ with change_cwd(self.rustc_perf_dir()):
+ cmd([self.cargo_stage_0(), "build", "-p", "collector"], env=dict(
+ RUSTC=str(self.rustc_stage_0()),
+ RUSTC_BOOTSTRAP="1"
+ ))
+
+ def rustc_profile_template_path(self) -> Path:
+ """
+ On Windows, we don't have enough space to use separate files for each rustc invocation.
+ Therefore, we use a single file for the generated profiles.
+ """
+ return self.rustc_profile_dir_root() / "default_%m.profraw"
+
+ def supports_bolt(self) -> bool:
+ return False
+
+
+def get_timestamp() -> float:
+ return time.time()
+
+
+Duration = float
+
+
+def iterate_timers(timer: "Timer", name: str, level: int = 0) -> Iterator[
+ Tuple[int, str, Duration]]:
+ """
+ Hierarchically iterate the children of a timer, in a depth-first order.
+ """
+ yield (level, name, timer.total_duration())
+ for (child_name, child_timer) in timer.children:
+ yield from iterate_timers(child_timer, child_name, level=level + 1)
+
+
+class Timer:
+ def __init__(self, parent_names: Tuple[str, ...] = ()):
+ self.children: List[Tuple[str, Timer]] = []
+ self.section_active = False
+ self.parent_names = parent_names
+ self.duration_excluding_children: Duration = 0
+
+ @contextlib.contextmanager
+ def section(self, name: str) -> ContextManager["Timer"]:
+ assert not self.section_active
+ self.section_active = True
+
+ start = get_timestamp()
+ exc = None
+
+ child_timer = Timer(parent_names=self.parent_names + (name,))
+ full_name = " > ".join(child_timer.parent_names)
+ try:
+ LOGGER.info(f"Section `{full_name}` starts")
+ yield child_timer
+ except BaseException as exception:
+ exc = exception
+ raise
+ finally:
+ end = get_timestamp()
+ duration = end - start
+
+ child_timer.duration_excluding_children = duration - child_timer.total_duration()
+ self.add_child(name, child_timer)
+ if exc is None:
+ LOGGER.info(f"Section `{full_name}` ended: OK ({duration:.2f}s)")
+ else:
+ LOGGER.info(f"Section `{full_name}` ended: FAIL ({duration:.2f}s)")
+ self.section_active = False
+
+ def total_duration(self) -> Duration:
+ return self.duration_excluding_children + sum(
+ c.total_duration() for (_, c) in self.children)
+
+ def has_children(self) -> bool:
+ return len(self.children) > 0
+
+ def print_stats(self):
+ rows = []
+ for (child_name, child_timer) in self.children:
+ for (level, name, duration) in iterate_timers(child_timer, child_name, level=0):
+ label = f"{' ' * level}{name}:"
+ rows.append((label, duration))
+
+ # Empty row
+ rows.append(("", ""))
+
+ total_duration_label = "Total duration:"
+ total_duration = self.total_duration()
+ rows.append((total_duration_label, humantime(total_duration)))
+
+ space_after_label = 2
+ max_label_length = max(16, max(len(label) for (label, _) in rows)) + space_after_label
+
+ table_width = max_label_length + 23
+ divider = "-" * table_width
+
+ with StringIO() as output:
+ print(divider, file=output)
+ for (label, duration) in rows:
+ if isinstance(duration, Duration):
+ pct = (duration / total_duration) * 100
+ value = f"{duration:>12.2f}s ({pct:>5.2f}%)"
+ else:
+ value = f"{duration:>{len(total_duration_label) + 7}}"
+ print(f"{label:<{max_label_length}} {value}", file=output)
+ print(divider, file=output, end="")
+ LOGGER.info(f"Timer results\n{output.getvalue()}")
+
+ def add_child(self, name: str, timer: "Timer"):
+ self.children.append((name, timer))
+
+ def add_duration(self, name: str, duration: Duration):
+ timer = Timer(parent_names=self.parent_names + (name,))
+ timer.duration_excluding_children = duration
+ self.add_child(name, timer)
+
+
+class BuildStep:
+ def __init__(self, type: str, children: List["BuildStep"], duration: float):
+ self.type = type
+ self.children = children
+ self.duration = duration
+
+ def find_all_by_type(self, type: str) -> Iterator["BuildStep"]:
+ if type == self.type:
+ yield self
+ for child in self.children:
+ yield from child.find_all_by_type(type)
+
+ def __repr__(self):
+ return f"BuildStep(type={self.type}, duration={self.duration}, children={len(self.children)})"
+
+
+def load_last_metrics(path: Path) -> BuildStep:
+ """
+ Loads the metrics of the most recent bootstrap execution from a metrics.json file.
+ """
+ with open(path, "r") as f:
+ metrics = json.load(f)
+ invocation = metrics["invocations"][-1]
+
+ def parse(entry) -> Optional[BuildStep]:
+ if "kind" not in entry or entry["kind"] != "rustbuild_step":
+ return None
+ type = entry.get("type", "")
+ duration = entry.get("duration_excluding_children_sec", 0)
+ children = []
+
+ for child in entry.get("children", ()):
+ step = parse(child)
+ if step is not None:
+ children.append(step)
+ duration += step.duration
+ return BuildStep(type=type, children=children, duration=duration)
+
+ children = [parse(child) for child in invocation.get("children", ())]
+ return BuildStep(
+ type="root",
+ children=children,
+ duration=invocation.get("duration_including_children_sec", 0)
+ )
+
+
+@contextlib.contextmanager
+def change_cwd(dir: Path):
+ """
+ Temporarily change working directory to `dir`.
+ """
+ cwd = os.getcwd()
+ LOGGER.debug(f"Changing working dir from `{cwd}` to `{dir}`")
+ os.chdir(dir)
+ try:
+ yield
+ finally:
+ LOGGER.debug(f"Reverting working dir to `{cwd}`")
+ os.chdir(cwd)
+
+
+def humantime(time_s: float) -> str:
+ hours = time_s // 3600
+ time_s = time_s % 3600
+ minutes = time_s // 60
+ seconds = time_s % 60
+
+ result = ""
+ if hours > 0:
+ result += f"{int(hours)}h "
+ if minutes > 0:
+ result += f"{int(minutes)}m "
+ result += f"{round(seconds)}s"
+ return result
+
+
+def move_path(src: Path, dst: Path):
+ LOGGER.info(f"Moving `{src}` to `{dst}`")
+ shutil.move(src, dst)
+
+
+def delete_file(path: Path):
+ LOGGER.info(f"Deleting file `{path}`")
+ os.unlink(path)
+
+
+def delete_directory(path: Path):
+ LOGGER.info(f"Deleting directory `{path}`")
+ shutil.rmtree(path)
+
+
+def unpack_archive(archive: Path):
+ LOGGER.info(f"Unpacking archive `{archive}`")
+ shutil.unpack_archive(archive)
+
+
+def download_file(src: str, target: Path):
+ LOGGER.info(f"Downloading `{src}` into `{target}`")
+ urllib.request.urlretrieve(src, str(target))
+
+
+def retry_action(action, name: str, max_fails: int = 5):
+ LOGGER.info(f"Attempting to perform action `{name}` with retry")
+ for iteration in range(max_fails):
+ LOGGER.info(f"Attempt {iteration + 1}/{max_fails}")
+ try:
+ action()
+ return
+ except:
+ LOGGER.error(f"Action `{name}` has failed\n{traceback.format_exc()}")
+
+ raise Exception(f"Action `{name}` has failed after {max_fails} attempts")
+
+
+def cmd(
+ args: List[Union[str, Path]],
+ env: Optional[Dict[str, str]] = None,
+ output_path: Optional[Path] = None
+):
+ args = [str(arg) for arg in args]
+
+ environment = os.environ.copy()
+
+ cmd_str = ""
+ if env is not None:
+ environment.update(env)
+ cmd_str += " ".join(f"{k}={v}" for (k, v) in (env or {}).items())
+ cmd_str += " "
+ cmd_str += " ".join(args)
+ if output_path is not None:
+ cmd_str += f" > {output_path}"
+ LOGGER.info(f"Executing `{cmd_str}`")
+
+ if output_path is not None:
+ with open(output_path, "w") as f:
+ return subprocess.run(
+ args,
+ env=environment,
+ check=True,
+ stdout=f
+ )
+ return subprocess.run(args, env=environment, check=True)
+
+
+def run_compiler_benchmarks(
+ pipeline: Pipeline,
+ profiles: List[str],
+ scenarios: List[str],
+ crates: List[str],
+ env: Optional[Dict[str, str]] = None
+):
+ env = env if env is not None else {}
+
+ # Compile libcore, both in opt-level=0 and opt-level=3
+ with change_cwd(pipeline.build_root()):
+ cmd([
+ pipeline.rustc_stage_2(),
+ "--edition", "2021",
+ "--crate-type", "lib",
+ str(pipeline.checkout_path() / "library/core/src/lib.rs"),
+ "--out-dir", pipeline.opt_artifacts()
+ ], env=dict(RUSTC_BOOTSTRAP="1", **env))
+
+ cmd([
+ pipeline.rustc_stage_2(),
+ "--edition", "2021",
+ "--crate-type", "lib",
+ "-Copt-level=3",
+ str(pipeline.checkout_path() / "library/core/src/lib.rs"),
+ "--out-dir", pipeline.opt_artifacts()
+ ], env=dict(RUSTC_BOOTSTRAP="1", **env))
+
+ # Run rustc-perf benchmarks
+ # Benchmark using profile_local with eprintln, which essentially just means
+ # don't actually benchmark -- just make sure we run rustc a bunch of times.
+ with change_cwd(pipeline.rustc_perf_dir()):
+ cmd([
+ pipeline.cargo_stage_0(),
+ "run",
+ "-p", "collector", "--bin", "collector", "--",
+ "profile_local", "eprintln",
+ pipeline.rustc_stage_2(),
+ "--id", "Test",
+ "--cargo", pipeline.cargo_stage_0(),
+ "--profiles", ",".join(profiles),
+ "--scenarios", ",".join(scenarios),
+ "--include", ",".join(crates)
+ ], env=dict(
+ RUST_LOG="collector=debug",
+ RUSTC=str(pipeline.rustc_stage_0()),
+ RUSTC_BOOTSTRAP="1",
+ **env
+ ))
+
+
+# https://stackoverflow.com/a/31631711/1107768
+def format_bytes(size: int) -> str:
+ """Return the given bytes as a human friendly KiB, MiB or GiB string."""
+ KB = 1024
+ MB = KB ** 2 # 1,048,576
+ GB = KB ** 3 # 1,073,741,824
+ TB = KB ** 4 # 1,099,511,627,776
+
+ if size < KB:
+ return f"{size} B"
+ elif KB <= size < MB:
+ return f"{size / KB:.2f} KiB"
+ elif MB <= size < GB:
+ return f"{size / MB:.2f} MiB"
+ elif GB <= size < TB:
+ return f"{size / GB:.2f} GiB"
+ else:
+ return str(size)
+
+
+# https://stackoverflow.com/a/63307131/1107768
+def count_files(path: Path) -> int:
+ return sum(1 for p in path.rglob("*") if p.is_file())
+
+
+def count_files_with_prefix(path: Path) -> int:
+ return sum(1 for p in glob.glob(f"{path}*") if Path(p).is_file())
+
+
+# https://stackoverflow.com/a/55659577/1107768
+def get_path_size(path: Path) -> int:
+ if path.is_dir():
+ return sum(p.stat().st_size for p in path.rglob("*"))
+ return path.stat().st_size
+
+
+def get_path_prefix_size(path: Path) -> int:
+ """
+ Get size of all files beginning with the prefix `path`.
+ Alternative to shell `du -sh <path>*`.
+ """
+ return sum(Path(p).stat().st_size for p in glob.glob(f"{path}*"))
+
+
+def get_files(directory: Path, filter: Optional[Callable[[Path], bool]] = None) -> Iterable[Path]:
+ for file in os.listdir(directory):
+ path = directory / file
+ if filter is None or filter(path):
+ yield path
+
+
+def build_rustc(
+ pipeline: Pipeline,
+ args: List[str],
+ env: Optional[Dict[str, str]] = None
+):
+ arguments = [
+ sys.executable,
+ pipeline.checkout_path() / "x.py",
+ "build",
+ "--target", PGO_HOST,
+ "--host", PGO_HOST,
+ "--stage", "2",
+ "library/std"
+ ] + args
+ cmd(arguments, env=env)
+
+
+def create_pipeline() -> Pipeline:
+ if sys.platform == "linux":
+ return LinuxPipeline()
+ elif sys.platform in ("cygwin", "win32"):
+ return WindowsPipeline()
+ else:
+ raise Exception(f"Optimized build is not supported for platform {sys.platform}")
+
+
+def gather_llvm_profiles(pipeline: Pipeline):
+ LOGGER.info("Running benchmarks with PGO instrumented LLVM")
+ run_compiler_benchmarks(
+ pipeline,
+ profiles=["Debug", "Opt"],
+ scenarios=["Full"],
+ crates=LLVM_PGO_CRATES
+ )
+
+ profile_path = pipeline.llvm_profile_merged_file()
+ LOGGER.info(f"Merging LLVM PGO profiles to {profile_path}")
+ cmd([
+ pipeline.downloaded_llvm_dir() / "bin" / "llvm-profdata",
+ "merge",
+ "-o", profile_path,
+ pipeline.llvm_profile_dir_root()
+ ])
+
+ LOGGER.info("LLVM PGO statistics")
+ LOGGER.info(f"{profile_path}: {format_bytes(get_path_size(profile_path))}")
+ LOGGER.info(
+ f"{pipeline.llvm_profile_dir_root()}: {format_bytes(get_path_size(pipeline.llvm_profile_dir_root()))}")
+ LOGGER.info(f"Profile file count: {count_files(pipeline.llvm_profile_dir_root())}")
+
+ # We don't need the individual .profraw files now that they have been merged
+ # into a final .profdata
+ delete_directory(pipeline.llvm_profile_dir_root())
+
+
+def gather_rustc_profiles(pipeline: Pipeline):
+ LOGGER.info("Running benchmarks with PGO instrumented rustc")
+
+ # Here we're profiling the `rustc` frontend, so we also include `Check`.
+ # The benchmark set includes various stress tests that put the frontend under pressure.
+ run_compiler_benchmarks(
+ pipeline,
+ profiles=["Check", "Debug", "Opt"],
+ scenarios=["All"],
+ crates=RUSTC_PGO_CRATES,
+ env=dict(
+ LLVM_PROFILE_FILE=str(pipeline.rustc_profile_template_path())
+ )
+ )
+
+ profile_path = pipeline.rustc_profile_merged_file()
+ LOGGER.info(f"Merging Rustc PGO profiles to {profile_path}")
+ cmd([
+ pipeline.build_artifacts() / "llvm" / "bin" / "llvm-profdata",
+ "merge",
+ "-o", profile_path,
+ pipeline.rustc_profile_dir_root()
+ ])
+
+ LOGGER.info("Rustc PGO statistics")
+ LOGGER.info(f"{profile_path}: {format_bytes(get_path_size(profile_path))}")
+ LOGGER.info(
+ f"{pipeline.rustc_profile_dir_root()}: {format_bytes(get_path_size(pipeline.rustc_profile_dir_root()))}")
+ LOGGER.info(f"Profile file count: {count_files(pipeline.rustc_profile_dir_root())}")
+
+ # We don't need the individual .profraw files now that they have been merged
+ # into a final .profdata
+ delete_directory(pipeline.rustc_profile_dir_root())
+
+
+def gather_llvm_bolt_profiles(pipeline: Pipeline):
+ LOGGER.info("Running benchmarks with BOLT instrumented LLVM")
+ run_compiler_benchmarks(
+ pipeline,
+ profiles=["Check", "Debug", "Opt"],
+ scenarios=["Full"],
+ crates=LLVM_BOLT_CRATES
+ )
+
+ merged_profile_path = pipeline.llvm_bolt_profile_merged_file()
+ profile_files_path = Path("/tmp/prof.fdata")
+ LOGGER.info(f"Merging LLVM BOLT profiles to {merged_profile_path}")
+
+ profile_files = sorted(glob.glob(f"{profile_files_path}*"))
+ cmd([
+ "merge-fdata",
+ *profile_files,
+ ], output_path=merged_profile_path)
+
+ LOGGER.info("LLVM BOLT statistics")
+ LOGGER.info(f"{merged_profile_path}: {format_bytes(get_path_size(merged_profile_path))}")
+ LOGGER.info(
+ f"{profile_files_path}: {format_bytes(get_path_prefix_size(profile_files_path))}")
+ LOGGER.info(f"Profile file count: {count_files_with_prefix(profile_files_path)}")
+
+
+def clear_llvm_files(pipeline: Pipeline):
+ """
+ Rustbuild currently doesn't support rebuilding LLVM when PGO options
+ change (or any other llvm-related options); so just clear out the relevant
+ directories ourselves.
+ """
+ LOGGER.info("Clearing LLVM build files")
+ delete_directory(pipeline.build_artifacts() / "llvm")
+ delete_directory(pipeline.build_artifacts() / "lld")
+
+
+def print_binary_sizes(pipeline: Pipeline):
+ bin_dir = pipeline.build_artifacts() / "stage2" / "bin"
+ binaries = get_files(bin_dir)
+
+ lib_dir = pipeline.build_artifacts() / "stage2" / "lib"
+ libraries = get_files(lib_dir, lambda p: p.suffix == ".so")
+
+ paths = sorted(binaries) + sorted(libraries)
+ with StringIO() as output:
+ for path in paths:
+ path_str = f"{path.name}:"
+ print(f"{path_str:<50}{format_bytes(path.stat().st_size):>14}", file=output)
+ LOGGER.info(f"Rustc binary size\n{output.getvalue()}")
+
+
+def print_free_disk_space(pipeline: Pipeline):
+ usage = shutil.disk_usage(pipeline.opt_artifacts())
+ total = usage.total
+ used = usage.used
+ free = usage.free
+
+ logging.info(
+ f"Free disk space: {format_bytes(free)} out of total {format_bytes(total)} ({(used / total) * 100:.2f}% used)")
+
+
+def log_metrics(step: BuildStep):
+ substeps: List[Tuple[int, BuildStep]] = []
+
+ def visit(step: BuildStep, level: int):
+ substeps.append((level, step))
+ for child in step.children:
+ visit(child, level=level + 1)
+
+ visit(step, 0)
+
+ output = StringIO()
+ for (level, step) in substeps:
+ label = f"{'.' * level}{step.type}"
+ print(f"{label:<65}{step.duration:>8.2f}s", file=output)
+ logging.info(f"Build step durations\n{output.getvalue()}")
+
+
+def record_metrics(pipeline: Pipeline, timer: Timer):
+ metrics = load_last_metrics(pipeline.metrics_path())
+ if metrics is None:
+ return
+ llvm_steps = tuple(metrics.find_all_by_type("bootstrap::native::Llvm"))
+ assert len(llvm_steps) > 0
+ llvm_duration = sum(step.duration for step in llvm_steps)
+
+ rustc_steps = tuple(metrics.find_all_by_type("bootstrap::compile::Rustc"))
+ assert len(rustc_steps) > 0
+ rustc_duration = sum(step.duration for step in rustc_steps)
+
+ # The LLVM step is part of the Rustc step
+ rustc_duration -= llvm_duration
+
+ timer.add_duration("LLVM", llvm_duration)
+ timer.add_duration("Rustc", rustc_duration)
+
+ log_metrics(metrics)
+
+
+def execute_build_pipeline(timer: Timer, pipeline: Pipeline, final_build_args: List[str]):
+ # Clear and prepare tmp directory
+ shutil.rmtree(pipeline.opt_artifacts(), ignore_errors=True)
+ os.makedirs(pipeline.opt_artifacts(), exist_ok=True)
+
+ pipeline.build_rustc_perf()
+
+ # Stage 1: Build rustc + PGO instrumented LLVM
+ with timer.section("Stage 1 (LLVM PGO)") as stage1:
+ with stage1.section("Build rustc and LLVM") as rustc_build:
+ build_rustc(pipeline, args=[
+ "--llvm-profile-generate"
+ ], env=dict(
+ LLVM_PROFILE_DIR=str(pipeline.llvm_profile_dir_root() / "prof-%p")
+ ))
+ record_metrics(pipeline, rustc_build)
+
+ with stage1.section("Gather profiles"):
+ gather_llvm_profiles(pipeline)
+ print_free_disk_space(pipeline)
+
+ clear_llvm_files(pipeline)
+ final_build_args += [
+ "--llvm-profile-use",
+ pipeline.llvm_profile_merged_file()
+ ]
+
+ # Stage 2: Build PGO instrumented rustc + LLVM
+ with timer.section("Stage 2 (rustc PGO)") as stage2:
+ with stage2.section("Build rustc and LLVM") as rustc_build:
+ build_rustc(pipeline, args=[
+ "--rust-profile-generate",
+ pipeline.rustc_profile_dir_root()
+ ])
+ record_metrics(pipeline, rustc_build)
+
+ with stage2.section("Gather profiles"):
+ gather_rustc_profiles(pipeline)
+ print_free_disk_space(pipeline)
+
+ clear_llvm_files(pipeline)
+ final_build_args += [
+ "--rust-profile-use",
+ pipeline.rustc_profile_merged_file()
+ ]
+
+ # Stage 3: Build rustc + BOLT instrumented LLVM
+ if pipeline.supports_bolt():
+ with timer.section("Stage 3 (LLVM BOLT)") as stage3:
+ with stage3.section("Build rustc and LLVM") as rustc_build:
+ build_rustc(pipeline, args=[
+ "--llvm-profile-use",
+ pipeline.llvm_profile_merged_file(),
+ "--llvm-bolt-profile-generate",
+ ])
+ record_metrics(pipeline, rustc_build)
+
+ with stage3.section("Gather profiles"):
+ gather_llvm_bolt_profiles(pipeline)
+
+ print_free_disk_space(pipeline)
+ clear_llvm_files(pipeline)
+ final_build_args += [
+ "--llvm-bolt-profile-use",
+ pipeline.llvm_bolt_profile_merged_file()
+ ]
+
+ # Stage 4: Build PGO optimized rustc + PGO/BOLT optimized LLVM
+ with timer.section("Stage 4 (final build)") as stage4:
+ cmd(final_build_args)
+ record_metrics(pipeline, stage4)
+
+
+if __name__ == "__main__":
+ logging.basicConfig(
+ level=logging.DEBUG,
+ format="%(name)s %(levelname)-4s: %(message)s",
+ )
+
+ LOGGER.info(f"Running multi-stage build using Python {sys.version}")
+ LOGGER.info(f"Environment values\n{pprint.pformat(dict(os.environ), indent=2)}")
+
+ build_args = sys.argv[1:]
+
+ timer = Timer()
+ pipeline = create_pipeline()
+ try:
+ execute_build_pipeline(timer, pipeline, build_args)
+ except BaseException as e:
+ LOGGER.error("The multi-stage build has failed")
+ raise e
+ finally:
+ timer.print_stats()
+ print_free_disk_space(pipeline)
+
+ print_binary_sizes(pipeline)
diff --git a/src/doc/book/.github/workflows/main.yml b/src/doc/book/.github/workflows/main.yml
index 64ab49c51..65574a070 100644
--- a/src/doc/book/.github/workflows/main.yml
+++ b/src/doc/book/.github/workflows/main.yml
@@ -12,8 +12,8 @@ jobs:
- name: Install Rust
run: |
rustup set profile minimal
- rustup toolchain install 1.65 -c rust-docs
- rustup default 1.65
+ rustup toolchain install 1.67 -c rust-docs
+ rustup default 1.67
- name: Install mdbook
run: |
mkdir bin
diff --git a/src/doc/book/CONTRIBUTING.md b/src/doc/book/CONTRIBUTING.md
index 3c9500687..a58ea4203 100644
--- a/src/doc/book/CONTRIBUTING.md
+++ b/src/doc/book/CONTRIBUTING.md
@@ -38,11 +38,13 @@ that governs all sub-projects, including this one. Please respect it!
## Expectations
-Because the book is [printed](https://nostarch.com/rust), and because we want
+Because the book is [printed][nostarch], and because we want
to keep the online version of the book close to the print version when
possible, it may take longer than you're used to for us to address your issue
or pull request.
+[nostarch]: https://nostarch.com/rust-programming-language-2nd-edition
+
So far, we've been doing a larger revision to coincide with [Rust
Editions](https://doc.rust-lang.org/edition-guide/). Between those larger
revisions, we will only be correcting errors. If your issue or pull request
diff --git a/src/doc/book/README.md b/src/doc/book/README.md
index 94e1a004a..f6341efc9 100644
--- a/src/doc/book/README.md
+++ b/src/doc/book/README.md
@@ -6,7 +6,7 @@ This repository contains the source of "The Rust Programming Language" book.
[The book is available in dead-tree form from No Starch Press][nostarch].
-[nostarch]: https://nostarch.com/rust
+[nostarch]: https://nostarch.com/rust-programming-language-2nd-edition
You can also read the book for free online. Please see the book as shipped with
the latest [stable], [beta], or [nightly] Rust releases. Be aware that issues
@@ -73,7 +73,7 @@ kinds of contributions we're looking for.
[contrib]: https://github.com/rust-lang/book/blob/main/CONTRIBUTING.md
-Because the book is [printed](https://nostarch.com/rust), and because we want
+Because the book is [printed][nostarch], and because we want
to keep the online version of the book close to the print version when
possible, it may take longer than you're used to for us to address your issue
or pull request.
diff --git a/src/doc/book/ci/dictionary.txt b/src/doc/book/ci/dictionary.txt
index 9eb695d5b..a91df4a03 100644
--- a/src/doc/book/ci/dictionary.txt
+++ b/src/doc/book/ci/dictionary.txt
@@ -546,6 +546,7 @@ unsafety
unsized
unsynchronized
Unyank
+UpperCamelCase
URIs
UsefulType
username
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 70a0c930c..3640c0694 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
@@ -18,6 +18,7 @@ error[E0308]: mismatched types
= note: expected reference `&String`
found reference `&{integer}`
note: associated function defined here
+ --> /rustc/d5a82bbd26e1ad8b7401f6a718a9c57c96905483/library/core/src/cmp.rs:783:8
For more information about this error, try `rustc --explain E0308`.
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 8095bbd8d..9517af95f 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
@@ -4,10 +4,10 @@ warning: unused `Result` that must be used
--> src/main.rs:10:5
|
10 | io::stdin().read_line(&mut guess);
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
- = note: `#[warn(unused_must_use)]` on by default
= note: this `Result` may be an `Err` variant, which should be handled
+ = note: `#[warn(unused_must_use)]` on by default
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-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 c0484ea1b..d27a7fae2 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
@@ -8,7 +8,7 @@ error[E0308]: mismatched types
| |
| implicitly returns `()` as its body has no tail or `return` expression
8 | x + 1;
- | - help: remove this semicolon
+ | - help: remove this semicolon to return this value
For more information about this error, try `rustc --explain E0308`.
error: could not compile `functions` 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 05987f7c8..4a5356701 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
@@ -12,6 +12,10 @@ error[E0382]: borrow of moved value: `s1`
| ^^ value borrowed here after move
|
= note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info)
+help: consider cloning the value if the performance cost is acceptable
+ |
+3 | let s2 = s1.clone();
+ | ++++++++
For more information about this error, try `rustc --explain E0382`.
error: could not compile `ownership` 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 d4a040e8e..a16dc0180 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,15 +8,10 @@ error[E0277]: cannot add `Option<i8>` to `i8`
|
= help: the trait `Add<Option<i8>>` is not implemented for `i8`
= help: the following other types implement trait `Add<Rhs>`:
- <&'a f32 as Add<f32>>
- <&'a f64 as Add<f64>>
- <&'a i128 as Add<i128>>
- <&'a i16 as Add<i16>>
- <&'a i32 as Add<i32>>
- <&'a i64 as Add<i64>>
<&'a i8 as Add<i8>>
- <&'a isize as Add<isize>>
- and 48 others
+ <&i8 as Add<&i8>>
+ <i8 as Add<&i8>>
+ <i8 as Add>
For more information about this error, try `rustc --explain E0277`.
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 bec72849a..75d056f84 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
@@ -7,6 +7,10 @@ error[E0004]: non-exhaustive patterns: `None` not covered
| ^ pattern `None` not covered
|
note: `Option<i32>` defined here
+ --> /rustc/d5a82bbd26e1ad8b7401f6a718a9c57c96905483/library/core/src/option.rs:518:1
+ |
+ = note:
+/rustc/d5a82bbd26e1ad8b7401f6a718a9c57c96905483/library/core/src/option.rs:522:5: not covered
= note: the matched value is of type `Option<i32>`
help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
|
diff --git a/src/doc/book/listings/ch07-managing-growing-projects/listing-07-12/output.txt b/src/doc/book/listings/ch07-managing-growing-projects/listing-07-12/output.txt
index 39b650540..1bc89bf32 100644
--- a/src/doc/book/listings/ch07-managing-growing-projects/listing-07-12/output.txt
+++ b/src/doc/book/listings/ch07-managing-growing-projects/listing-07-12/output.txt
@@ -1,11 +1,5 @@
$ cargo build
Compiling restaurant v0.1.0 (file:///projects/restaurant)
-error[E0433]: failed to resolve: use of undeclared crate or module `hosting`
- --> src/lib.rs:11:9
- |
-11 | hosting::add_to_waitlist();
- | ^^^^^^^ use of undeclared crate or module `hosting`
-
warning: unused import: `crate::front_of_house::hosting`
--> src/lib.rs:7:5
|
@@ -14,6 +8,12 @@ warning: unused import: `crate::front_of_house::hosting`
|
= note: `#[warn(unused_imports)]` on by default
+error[E0433]: failed to resolve: use of undeclared crate or module `hosting`
+ --> src/lib.rs:11:9
+ |
+11 | hosting::add_to_waitlist();
+ | ^^^^^^^ use of undeclared crate or module `hosting`
+
For more information about this error, try `rustc --explain E0433`.
warning: `restaurant` (lib) generated 1 warning
error: could not compile `restaurant` due to previous error; 1 warning emitted
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 95577772e..3a682457c 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
@@ -14,7 +14,6 @@ error[E0277]: the type `String` cannot be indexed by `{integer}`
<String as Index<RangeTo<usize>>>
<String as Index<RangeToInclusive<usize>>>
<String as Index<std::ops::Range<usize>>>
- <str as Index<I>>
For more information about this error, try `rustc --explain E0277`.
error: could not compile `collections` due to previous error
diff --git a/src/doc/book/listings/ch11-writing-automated-tests/listing-11-03/output.txt b/src/doc/book/listings/ch11-writing-automated-tests/listing-11-03/output.txt
index 2fa5cf077..e8c31e79e 100644
--- a/src/doc/book/listings/ch11-writing-automated-tests/listing-11-03/output.txt
+++ b/src/doc/book/listings/ch11-writing-automated-tests/listing-11-03/output.txt
@@ -10,7 +10,7 @@ test tests::exploration ... ok
failures:
---- tests::another stdout ----
-thread 'main' panicked at 'Make this test fail', src/lib.rs:10:9
+thread 'tests::another' panicked at 'Make this test fail', src/lib.rs:10:9
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
diff --git a/src/doc/book/listings/ch11-writing-automated-tests/listing-11-10/output.txt b/src/doc/book/listings/ch11-writing-automated-tests/listing-11-10/output.txt
index 681cfbb81..b0d10deaa 100644
--- a/src/doc/book/listings/ch11-writing-automated-tests/listing-11-10/output.txt
+++ b/src/doc/book/listings/ch11-writing-automated-tests/listing-11-10/output.txt
@@ -11,7 +11,7 @@ failures:
---- tests::this_test_will_fail stdout ----
I got the value 8
-thread 'main' panicked at 'assertion failed: `(left == right)`
+thread 'tests::this_test_will_fail' panicked at 'assertion failed: `(left == right)`
left: `5`,
right: `10`', src/lib.rs:19:9
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
diff --git a/src/doc/book/listings/ch11-writing-automated-tests/no-listing-03-introducing-a-bug/output.txt b/src/doc/book/listings/ch11-writing-automated-tests/no-listing-03-introducing-a-bug/output.txt
index 7c62822f7..6fbb5e496 100644
--- a/src/doc/book/listings/ch11-writing-automated-tests/no-listing-03-introducing-a-bug/output.txt
+++ b/src/doc/book/listings/ch11-writing-automated-tests/no-listing-03-introducing-a-bug/output.txt
@@ -10,7 +10,7 @@ test tests::smaller_cannot_hold_larger ... ok
failures:
---- tests::larger_can_hold_smaller stdout ----
-thread 'main' panicked at 'assertion failed: larger.can_hold(&smaller)', src/lib.rs:28:9
+thread 'tests::larger_can_hold_smaller' panicked at 'assertion failed: larger.can_hold(&smaller)', src/lib.rs:28:9
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
diff --git a/src/doc/book/listings/ch11-writing-automated-tests/no-listing-04-bug-in-add-two/output.txt b/src/doc/book/listings/ch11-writing-automated-tests/no-listing-04-bug-in-add-two/output.txt
index 28e2414be..00bf63fff 100644
--- a/src/doc/book/listings/ch11-writing-automated-tests/no-listing-04-bug-in-add-two/output.txt
+++ b/src/doc/book/listings/ch11-writing-automated-tests/no-listing-04-bug-in-add-two/output.txt
@@ -9,7 +9,7 @@ test tests::it_adds_two ... FAILED
failures:
---- tests::it_adds_two stdout ----
-thread 'main' panicked at 'assertion failed: `(left == right)`
+thread 'tests::it_adds_two' panicked at 'assertion failed: `(left == right)`
left: `4`,
right: `5`', src/lib.rs:11:9
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
diff --git a/src/doc/book/listings/ch11-writing-automated-tests/no-listing-06-greeter-with-bug/output.txt b/src/doc/book/listings/ch11-writing-automated-tests/no-listing-06-greeter-with-bug/output.txt
index 3366e3ace..68d724f11 100644
--- a/src/doc/book/listings/ch11-writing-automated-tests/no-listing-06-greeter-with-bug/output.txt
+++ b/src/doc/book/listings/ch11-writing-automated-tests/no-listing-06-greeter-with-bug/output.txt
@@ -9,7 +9,7 @@ test tests::greeting_contains_name ... FAILED
failures:
---- tests::greeting_contains_name stdout ----
-thread 'main' panicked at 'assertion failed: result.contains(\"Carol\")', src/lib.rs:12:9
+thread 'tests::greeting_contains_name' panicked at 'assertion failed: result.contains(\"Carol\")', src/lib.rs:12:9
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
diff --git a/src/doc/book/listings/ch11-writing-automated-tests/no-listing-07-custom-failure-message/output.txt b/src/doc/book/listings/ch11-writing-automated-tests/no-listing-07-custom-failure-message/output.txt
index cebebdaee..03d6ad7f1 100644
--- a/src/doc/book/listings/ch11-writing-automated-tests/no-listing-07-custom-failure-message/output.txt
+++ b/src/doc/book/listings/ch11-writing-automated-tests/no-listing-07-custom-failure-message/output.txt
@@ -9,7 +9,7 @@ test tests::greeting_contains_name ... FAILED
failures:
---- tests::greeting_contains_name stdout ----
-thread 'main' panicked at 'Greeting did not contain name, value was `Hello!`', src/lib.rs:12:9
+thread 'tests::greeting_contains_name' panicked at 'Greeting did not contain name, value was `Hello!`', src/lib.rs:12:9
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
diff --git a/src/doc/book/listings/ch11-writing-automated-tests/no-listing-09-guess-with-panic-msg-bug/output.txt b/src/doc/book/listings/ch11-writing-automated-tests/no-listing-09-guess-with-panic-msg-bug/output.txt
index c176e88b8..0b045e8be 100644
--- a/src/doc/book/listings/ch11-writing-automated-tests/no-listing-09-guess-with-panic-msg-bug/output.txt
+++ b/src/doc/book/listings/ch11-writing-automated-tests/no-listing-09-guess-with-panic-msg-bug/output.txt
@@ -9,7 +9,7 @@ test tests::greater_than_100 - should panic ... FAILED
failures:
---- tests::greater_than_100 stdout ----
-thread 'main' panicked at 'Guess value must be greater than or equal to 1, got 200.', src/lib.rs:13:13
+thread 'tests::greater_than_100' panicked at 'Guess value must be greater than or equal to 1, got 200.', src/lib.rs:13:13
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
note: panic did not contain expected string
panic message: `"Guess value must be greater than or equal to 1, got 200."`,
diff --git a/src/doc/book/listings/ch11-writing-automated-tests/output-only-01-show-output/output.txt b/src/doc/book/listings/ch11-writing-automated-tests/output-only-01-show-output/output.txt
index 4ececf245..bc03145a1 100644
--- a/src/doc/book/listings/ch11-writing-automated-tests/output-only-01-show-output/output.txt
+++ b/src/doc/book/listings/ch11-writing-automated-tests/output-only-01-show-output/output.txt
@@ -20,7 +20,7 @@ failures:
---- tests::this_test_will_fail stdout ----
I got the value 8
-thread 'main' panicked at 'assertion failed: `(left == right)`
+thread 'tests::this_test_will_fail' panicked at 'assertion failed: `(left == right)`
left: `5`,
right: `10`', src/lib.rs:19:9
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
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 c18902518..9870b2125 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
@@ -4,10 +4,10 @@ warning: unused `Result` that must be used
--> src/main.rs:19:5
|
19 | run(config);
- | ^^^^^^^^^^^^
+ | ^^^^^^^^^^^
|
- = note: `#[warn(unused_must_use)]` on by default
= note: this `Result` may be an `Err` variant, which should be handled
+ = note: `#[warn(unused_must_use)]` on by default
warning: `minigrep` (bin "minigrep") generated 1 warning
Finished dev [unoptimized + debuginfo] target(s) in 0.71s
diff --git a/src/doc/book/listings/ch12-an-io-project/listing-12-16/output.txt b/src/doc/book/listings/ch12-an-io-project/listing-12-16/output.txt
index 3c34e3945..be4a97eea 100644
--- a/src/doc/book/listings/ch12-an-io-project/listing-12-16/output.txt
+++ b/src/doc/book/listings/ch12-an-io-project/listing-12-16/output.txt
@@ -9,7 +9,7 @@ test tests::one_result ... FAILED
failures:
---- tests::one_result stdout ----
-thread 'main' panicked at 'assertion failed: `(left == right)`
+thread 'tests::one_result' panicked at 'assertion failed: `(left == right)`
left: `["safe, fast, productive."]`,
right: `[]`', src/lib.rs:44:9
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
diff --git a/src/doc/book/listings/ch13-functional-features/listing-13-14/output.txt b/src/doc/book/listings/ch13-functional-features/listing-13-14/output.txt
index 228c764ed..993037991 100644
--- a/src/doc/book/listings/ch13-functional-features/listing-13-14/output.txt
+++ b/src/doc/book/listings/ch13-functional-features/listing-13-14/output.txt
@@ -4,10 +4,10 @@ warning: unused `Map` that must be used
--> src/main.rs:4:5
|
4 | v1.iter().map(|x| x + 1);
- | ^^^^^^^^^^^^^^^^^^^^^^^^^
+ | ^^^^^^^^^^^^^^^^^^^^^^^^
|
- = note: `#[warn(unused_must_use)]` on by default
= note: iterators are lazy and do nothing unless consumed
+ = note: `#[warn(unused_must_use)]` on by default
warning: `iterators` (bin "iterators") generated 1 warning
Finished dev [unoptimized + debuginfo] target(s) in 0.47s
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 d5522cd53..04b6976fe 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
@@ -4,11 +4,11 @@ error[E0072]: recursive type `List` has infinite size
--> src/main.rs:1:1
|
1 | enum List {
- | ^^^^^^^^^ recursive type has infinite size
+ | ^^^^^^^^^
2 | Cons(i32, List),
| ---- recursive without indirection
|
-help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `List` representable
+help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to break the cycle
|
2 | Cons(i32, Box<List>),
| ++++ +
diff --git a/src/doc/book/listings/ch15-smart-pointers/listing-15-23/output.txt b/src/doc/book/listings/ch15-smart-pointers/listing-15-23/output.txt
index 3749c845c..0ffabf765 100644
--- a/src/doc/book/listings/ch15-smart-pointers/listing-15-23/output.txt
+++ b/src/doc/book/listings/ch15-smart-pointers/listing-15-23/output.txt
@@ -9,7 +9,7 @@ test tests::it_sends_an_over_75_percent_warning_message ... FAILED
failures:
---- tests::it_sends_an_over_75_percent_warning_message stdout ----
-thread 'main' panicked at 'already borrowed: BorrowMutError', src/lib.rs:60:53
+thread 'tests::it_sends_an_over_75_percent_warning_message' panicked at 'already borrowed: BorrowMutError', src/lib.rs:60:53
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
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 0634b86e5..e8cf21a73 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
@@ -22,6 +22,9 @@ note: required because it's used within this closure
11 | let handle = thread::spawn(move || {
| ^^^^^^^
note: required by a bound in `spawn`
+ --> /rustc/d5a82bbd26e1ad8b7401f6a718a9c57c96905483/library/std/src/thread/mod.rs:704:8
+ |
+ = note: required by this bound in `spawn`
For more information about this error, try `rustc --explain E0277`.
error: could not compile `shared-state` 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 0fd5373b8..52efabb5c 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
@@ -9,11 +9,19 @@ error[E0005]: refutable pattern in local binding: `None` not covered
= note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
= note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
note: `Option<i32>` defined here
+ --> /rustc/d5a82bbd26e1ad8b7401f6a718a9c57c96905483/library/core/src/option.rs:518:1
+ |
+ = note:
+/rustc/d5a82bbd26e1ad8b7401f6a718a9c57c96905483/library/core/src/option.rs:522:5: not covered
= note: the matched value is of type `Option<i32>`
help: you might want to use `if let` to ignore the variant that isn't matched
|
3 | let x = if let Some(x) = some_option_value { x } else { todo!() };
| ++++++++++ ++++++++++++++++++++++
+help: alternatively, you might want to use let else to handle the variant that isn't matched
+ |
+3 | let Some(x) = some_option_value else { todo!() };
+ | ++++++++++++++++
For more information about this error, try `rustc --explain E0005`.
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 702d10a23..6488fb29c 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
@@ -6,9 +6,9 @@ warning: irrefutable `if let` pattern
2 | if let x = 5 {
| ^^^^^^^^^
|
- = note: `#[warn(irrefutable_let_patterns)]` on by default
= note: this pattern will always match, so the `if let` is useless
= help: consider replacing the `if let` with a `let`
+ = note: `#[warn(irrefutable_let_patterns)]` on by default
warning: `patterns` (bin "patterns") generated 1 warning
Finished dev [unoptimized + debuginfo] target(s) in 0.39s
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 a3b281e3f..594287604 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
@@ -11,8 +11,8 @@ error[E0790]: cannot call associated function on trait without specifying the co
|
help: use the fully-qualified path to the only available implementation
|
-20 | println!("A baby dog is called a {}", <::Dog as Animal>::baby_name());
- | +++++++++ +
+20 | println!("A baby dog is called a {}", <Dog as Animal>::baby_name());
+ | +++++++ +
For more information about this error, try `rustc --explain E0790`.
error: could not compile `traits-example` 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 a6c9e8d3b..342bf9a16 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
@@ -9,6 +9,7 @@ error[E0507]: cannot move out of `worker.thread` which is behind a mutable refer
| move occurs because `worker.thread` has type `JoinHandle<()>`, which does not implement the `Copy` trait
|
note: this function takes ownership of the receiver `self`, which moves `worker.thread`
+ --> /rustc/d5a82bbd26e1ad8b7401f6a718a9c57c96905483/library/std/src/thread/mod.rs:1581:17
For more information about this error, try `rustc --explain E0507`.
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 e4c0eeb2a..fec2377dc 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
@@ -7,6 +7,7 @@ error[E0599]: no method named `join` found for enum `Option` in the current scop
| ^^^^ method not found in `Option<JoinHandle<()>>`
|
note: the method `join` exists on the type `JoinHandle<()>`
+ --> /rustc/d5a82bbd26e1ad8b7401f6a718a9c57c96905483/library/std/src/thread/mod.rs:1581:5
help: consider using `Option::expect` to unwrap the `JoinHandle<()>` value, panicking if the value is an `Option::None`
|
52 | worker.thread.expect("REASON").join().unwrap();
diff --git a/src/doc/book/rust-toolchain b/src/doc/book/rust-toolchain
index 5b6cd6b3c..9ebd7af32 100644
--- a/src/doc/book/rust-toolchain
+++ b/src/doc/book/rust-toolchain
@@ -1 +1 @@
-1.65
+1.67
diff --git a/src/doc/book/src/ch00-00-introduction.md b/src/doc/book/src/ch00-00-introduction.md
index 9df8e6c88..536988cb1 100644
--- a/src/doc/book/src/ch00-00-introduction.md
+++ b/src/doc/book/src/ch00-00-introduction.md
@@ -4,7 +4,7 @@
> Language][nsprust] available in print and ebook format from [No Starch
> Press][nsp].
-[nsprust]: https://nostarch.com/rust
+[nsprust]: https://nostarch.com/rust-programming-language-2nd-edition
[nsp]: https://nostarch.com/
Welcome to *The Rust Programming Language*, an introductory book about Rust.
diff --git a/src/doc/book/src/ch03-01-variables-and-mutability.md b/src/doc/book/src/ch03-01-variables-and-mutability.md
index 883a53050..058f7bb5c 100644
--- a/src/doc/book/src/ch03-01-variables-and-mutability.md
+++ b/src/doc/book/src/ch03-01-variables-and-mutability.md
@@ -82,7 +82,7 @@ First, you aren’t allowed to use `mut` with constants. Constants aren’t just
immutable by default—they’re always immutable. You declare constants using the
`const` keyword instead of the `let` keyword, and the type of the value *must*
be annotated. We’ll cover types and type annotations in the next section,
-[“Data Types,”][data-types]<!-- ignore -->, so don’t worry about the details
+[“Data Types”][data-types]<!-- ignore -->, so don’t worry about the details
right now. Just know that you must always annotate the type.
Constants can be declared in any scope, including the global scope, which makes
diff --git a/src/doc/book/src/ch10-01-syntax.md b/src/doc/book/src/ch10-01-syntax.md
index c22aef7c3..431dba966 100644
--- a/src/doc/book/src/ch10-01-syntax.md
+++ b/src/doc/book/src/ch10-01-syntax.md
@@ -33,9 +33,9 @@ the duplication by introducing a generic type parameter in a single function.
To parameterize the types in a new single function, we need to name the type
parameter, just as we do for the value parameters to a function. You can use
any identifier as a type parameter name. But we’ll use `T` because, by
-convention, type parameter names in Rust are short, often just a letter, and Rust’s
-type-naming convention is CamelCase. Short for “type,” `T` is the default
-choice of most Rust programmers.
+convention, type parameter names in Rust are short, often just a letter, and
+Rust’s type-naming convention is UpperCamelCase. Short for “type,” `T` is the
+default choice of most Rust programmers.
When we use a parameter in the body of the function, we have to declare the
parameter name in the signature so the compiler knows what that name means.
@@ -274,7 +274,7 @@ method.
### Performance of Code Using Generics
You might be wondering whether there is a runtime cost when using generic type
-parameters. The good news is that using generic types won't make your program run
+parameters. The good news is that using generic types won't make your program run
any slower than it would with concrete types.
Rust accomplishes this by performing monomorphization of the code using
diff --git a/src/doc/book/src/title-page.md b/src/doc/book/src/title-page.md
index 12d1a6598..5f7a7a680 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.65 (released 2022-11-03)
+This version of the text assumes you’re using Rust 1.67.1 (released 2023-02-09)
or later. See the [“Installation” section of Chapter 1][install]<!-- ignore -->
to install or update Rust.
@@ -18,7 +18,7 @@ Press][nsprust].
[install]: ch01-01-installation.html
[editions]: appendix-05-editions.html
-[nsprust]: https://nostarch.com/rust
+[nsprust]: https://nostarch.com/rust-programming-language-2nd-edition
[translations]: appendix-06-translation.html
> **🚨 Want a more interactive learning experience? Try out a different version
diff --git a/src/doc/embedded-book/src/assets/verify.jpeg b/src/doc/embedded-book/src/assets/verify.jpeg
index a6e9376c5..ed4664578 100644
--- a/src/doc/embedded-book/src/assets/verify.jpeg
+++ b/src/doc/embedded-book/src/assets/verify.jpeg
Binary files differ
diff --git a/src/doc/embedded-book/src/collections/index.md b/src/doc/embedded-book/src/collections/index.md
index 7319a397a..aa03666ac 100644
--- a/src/doc/embedded-book/src/collections/index.md
+++ b/src/doc/embedded-book/src/collections/index.md
@@ -49,9 +49,8 @@ in your program instead of this allocator.
``` rust,ignore
// Bump pointer allocator implementation
-extern crate cortex_m;
-
-use core::alloc::GlobalAlloc;
+use core::alloc::{GlobalAlloc, Layout};
+use core::cell::UnsafeCell;
use core::ptr;
use cortex_m::interrupt;
@@ -144,8 +143,7 @@ as they are exact same implementation.
allocator. Just `use` its collections and proceed to instantiate them:
```rust,ignore
-extern crate heapless; // v0.4.x
-
+// heapless version: v0.4.x
use heapless::Vec;
use heapless::consts::*;
@@ -155,6 +153,7 @@ fn main() -> ! {
xs.push(42).unwrap();
assert_eq!(xs.pop(), Some(42));
+ loop {}
}
```
diff --git a/src/doc/embedded-book/src/interoperability/c-with-rust.md b/src/doc/embedded-book/src/interoperability/c-with-rust.md
index d5d8db39b..6bec3bd87 100644
--- a/src/doc/embedded-book/src/interoperability/c-with-rust.md
+++ b/src/doc/embedded-book/src/interoperability/c-with-rust.md
@@ -125,8 +125,6 @@ For projects with limited dependencies or complexity, or for projects where it i
In the simplest case of compiling a single C file as a dependency to a static library, an example `build.rs` script using the [`cc` crate] would look like this:
```rust,ignore
-extern crate cc;
-
fn main() {
cc::Build::new()
.file("foo.c")
diff --git a/src/doc/embedded-book/src/intro/install/macos.md b/src/doc/embedded-book/src/intro/install/macos.md
index b3e51bcf1..9a797563a 100644
--- a/src/doc/embedded-book/src/intro/install/macos.md
+++ b/src/doc/embedded-book/src/intro/install/macos.md
@@ -1,8 +1,11 @@
# macOS
-All the tools can be install using [Homebrew]:
+All the tools can be installed using [Homebrew] or [MacPorts]:
[Homebrew]: http://brew.sh/
+[MacPorts]: https://www.macports.org/
+
+## Install tools with [Homebrew]
``` text
$ # GDB
@@ -20,6 +23,21 @@ $ brew install qemu
$ brew install --HEAD openocd
```
+## Install tools with [MacPorts]
+
+``` text
+$ # GDB
+$ sudo port install arm-none-eabi-gcc
+
+$ # OpenOCD
+$ sudo port install openocd
+
+$ # QEMU
+$ sudo port install qemu
+```
+
+
+
That's all! Go to the [next section].
[next section]: verify.md
diff --git a/src/doc/embedded-book/src/intro/install/verify.md b/src/doc/embedded-book/src/intro/install/verify.md
index 921db8cc7..e60911dc3 100644
--- a/src/doc/embedded-book/src/intro/install/verify.md
+++ b/src/doc/embedded-book/src/intro/install/verify.md
@@ -8,7 +8,7 @@ discovery board has two USB connectors; use the one labeled "USB ST-LINK" that
sits on the center of the edge of the board.
Also check that the ST-LINK header is populated. See the picture below; the
-ST-LINK header is circled in red.
+ST-LINK header is highlighted.
<p align="center">
<img title="Connected discovery board" src="../../assets/verify.jpeg">
diff --git a/src/doc/embedded-book/src/peripherals/singletons.md b/src/doc/embedded-book/src/peripherals/singletons.md
index 3f04aa170..1f3a556e8 100644
--- a/src/doc/embedded-book/src/peripherals/singletons.md
+++ b/src/doc/embedded-book/src/peripherals/singletons.md
@@ -61,8 +61,7 @@ This has a small runtime overhead because we must wrap the `SerialPort` structur
Although we created our own `Peripherals` structure above, it is not necessary to do this for your code. the `cortex_m` crate contains a macro called `singleton!()` that will perform this action for you.
```rust,ignore
-#[macro_use(singleton)]
-extern crate cortex_m;
+use cortex_m::singleton;
fn main() {
// OK if `main` is executed only once
diff --git a/src/doc/embedded-book/src/start/registers.md b/src/doc/embedded-book/src/start/registers.md
index d5bb3e0cc..fe184792c 100644
--- a/src/doc/embedded-book/src/start/registers.md
+++ b/src/doc/embedded-book/src/start/registers.md
@@ -24,7 +24,7 @@ You may well find that the code you need to access the peripherals in your micro
A board crate is the perfect starting point, if you're new to embedded Rust. They nicely abstract the HW details that might be overwhelming when starting studying this subject, and makes standard tasks easy, like turning a LED on or off. The functionality it exposes varies a lot between boards. Since this book aims at staying hardware agnostic, the board crates won't be covered by this book.
-If you want to experiment with the STM32F3DISCOVERY board, it is highly recommmand to take a look at the [stm32f3-discovery] board crate, which provides functionality to blink the board LEDs, access its compass, bluetooth and more. The [Discovery] book offers a great introduction to the use of a board crate.
+If you want to experiment with the STM32F3DISCOVERY board, it is highly recommended to take a look at the [stm32f3-discovery] board crate, which provides functionality to blink the board LEDs, access its compass, bluetooth and more. The [Discovery] book offers a great introduction to the use of a board crate.
But if you're working on a system that doesn't yet have dedicated board crate, or you need functionality not provided by existing crates, read on as we start from the bottom, with the micro-architecture crates.
diff --git a/src/doc/index.md b/src/doc/index.md
index bf08960f3..7c97c16c2 100644
--- a/src/doc/index.md
+++ b/src/doc/index.md
@@ -4,6 +4,20 @@
nav {
display: none;
}
+body {
+ font-family: serif;
+}
+h1, h2, h3, h4, h5, h6 {
+ font-family: sans-serif;
+}
+h3 {
+ font-size: 1.35rem;
+}
+h4 {
+ font-size: 1.1rem;
+}
+
+/* Formatting for docs search bar */
#search-input {
width: calc(100% - 58px);
}
@@ -21,53 +35,74 @@ nav {
#search-but:hover, #search-input:focus {
border-color: #55a9ff;
}
-h2 {
- font-size: 18px;
+
+/* Formatting for external link icon */
+svg.external-link {
+ display: inline-block;
+ position: relative;
+ vertical-align: super;
+ width: 0.7rem;
+ height: 0.7rem;
+ padding-left: 2px;
+ top: 3px;
}
</style>
-Welcome to an overview of the documentation provided by the [Rust project].
-All of these projects are managed by the Docs Team; there are other
-unofficial documentation resources as well!
+Welcome to an overview of the documentation provided by the [Rust
+project]. This page contains links to various helpful references,
+most of which are available offline (if opened with `rustup doc`). Many of these
+resources take the form of "books"; we collectively call these "The Rust
+Bookshelf." Some are large, some are small.
-Many of these resources take the form of "books"; we collectively call these
-"The Rust Bookshelf." Some are large, some are small.
+All of these books are managed by the Rust Organization, but other unofficial
+documentation resources are included here as well!
-# Learn Rust
+If you're just looking for the standard library reference, here it is:
+[Rust API documentation](std/index.html)
-If you'd like to learn Rust, this is the spot for you! All of these resources
+
+## Learning Rust
+
+If you'd like to learn Rust, this is the section for you! All of these resources
assume that you have programmed before, but not in any specific language:
-## The Rust Programming Language
+### The Rust Programming Language
-Affectionately nicknamed "the book," [The Rust Programming
-Language](book/index.html) will give you an overview of the language from
-first principles. You'll build a few projects along the way, and by the end,
-you'll have a solid grasp of the language.
+Affectionately nicknamed "the book," [The Rust Programming Language](book/index.html)
+will give you an overview of the language from first principles. You'll build a
+few projects along the way, and by the end, you'll have a solid grasp of how to
+use the language.
-## Rust By Example
+### Rust By Example
If reading multiple hundreds of pages about a language isn't your style, then
-[Rust By Example](rust-by-example/index.html) has you covered. While the book talks about code with
-a lot of words, RBE shows off a bunch of code, and keeps the talking to a
-minimum. It also includes exercises!
+[Rust By Example](rust-by-example/index.html) has you covered. RBE shows off a
+bunch of code without using a lot of words. It also includes exercises!
+
+### Rustlings
+
+[Rustlings](https://github.com/rust-lang/rustlings) guides you
+through downloading and setting up the Rust toolchain, then provides an
+interactive tool that teaches you how to solve coding challenges in Rust.
+
+### Rust Playground
-## Rustlings
+The [Rust Playground](https://play.rust-lang.org) is a great place
+to try out and share small bits of code, or experiment with some of the most
+popular crates.
-[Rustlings](https://github.com/rust-lang/rustlings) guides you through downloading and setting up the Rust toolchain,
-and teaches you the basics of reading and writing Rust syntax. It's an
-alternative to Rust by Example that works with your own environment.
-# Use Rust
+## Using Rust
-Once you've gotten familiar with the language, these resources can help you
-when you're actually using it day-to-day.
+Once you've gotten familiar with the language, these resources can help you put
+it to work.
-## The Standard Library
+### The Standard Library
-Rust's standard library has [extensive API documentation](std/index.html),
-with explanations of how to use various things, as well as example code for
-accomplishing various tasks.
+Rust's standard library has [extensive API documentation](std/index.html), with
+explanations of how to use various things, as well as example code for
+accomplishing various tasks. Code examples have a "Run" button on hover that
+opens the sample in the playground.
<div>
<form action="std/index.html" method="get">
@@ -77,76 +112,143 @@ accomplishing various tasks.
</form>
</div>
-## The Edition Guide
+### Your Personal Documentation
-[The Edition Guide](edition-guide/index.html) describes the Rust editions.
+Whenever you are working in a crate, `cargo doc --open` will generate
+documentation for your project _and_ all its dependencies in their correct
+version, and open it in your browser. Add the flag `--document-private-items` to
+also show items not marked `pub`.
-## The Rustc Book
+### The Edition Guide
-[The Rustc Book](rustc/index.html) describes the Rust compiler, `rustc`.
+[The Edition Guide](edition-guide/index.html) describes the Rust editions and
+their differences.
-## The Cargo Book
+### The `rustc` Book
-[The Cargo Book](cargo/index.html) is a guide to Cargo, Rust's build tool and dependency manager.
+[The `rustc` Book](rustc/index.html) describes the Rust compiler, `rustc`.
-## The Rustdoc Book
+### The Cargo Book
+
+[The Cargo Book](cargo/index.html) is a guide to Cargo, Rust's build tool and
+dependency manager.
+
+### The Rustdoc Book
[The Rustdoc Book](rustdoc/index.html) describes our documentation tool, `rustdoc`.
-## The Clippy Book
+### The Clippy Book
[The Clippy Book](clippy/index.html) describes our static analyzer, Clippy.
-## Extended Error Listing
+### Extended Error Listing
Many of Rust's errors come with error codes, and you can request extended
-diagnostics from the compiler on those errors. You can also [read them
-here](error_codes/index.html), if you prefer to read them that way.
+diagnostics from the compiler on those errors (with `rustc --explain`). You can
+also read them here if you prefer: [rustc error codes](error_codes/index.html)
+
-# Master Rust
+## Mastering Rust
Once you're quite familiar with the language, you may find these advanced
resources useful.
-## The Reference
+### The Reference
-[The Reference](reference/index.html) is not a formal spec, but is more detailed and
-comprehensive than the book.
+[The Reference](reference/index.html) is not a formal spec, but is more detailed
+and comprehensive than the book.
-## The Style Guide
+### The Style Guide
-[The Rust Style Guide](style-guide/index.html) describes the standard formatting of Rust
-code. Most developers use rustfmt to format their code, and rustfmt's default
-formatting matches this style guide.
+[The Rust Style Guide](style-guide/index.html) describes the standard formatting
+of Rust code. Most developers use `cargo fmt` to invoke `rustfmt` and format the
+code automatically (the result matches this style guide).
-## The Rustonomicon
+### The Rustonomicon
-[The Rustonomicon](nomicon/index.html) is your guidebook to the dark arts of unsafe
-Rust. It's also sometimes called "the 'nomicon."
+[The Rustonomicon](nomicon/index.html) is your guidebook to the dark arts of
+unsafe Rust. It's also sometimes called "the 'nomicon."
-## The Unstable Book
+### The Unstable Book
-[The Unstable Book](unstable-book/index.html) has documentation for unstable features.
+[The Unstable Book](unstable-book/index.html) has documentation for unstable
+features.
-## The `rustc` Contribution Guide
+### The `rustc` Contribution Guide
-[The `rustc` Guide](https://rustc-dev-guide.rust-lang.org/) documents how
-the compiler works and how to contribute to it. This is useful if you want to build
-or modify the Rust compiler from source (e.g. to target something non-standard).
+[The `rustc` Guide](https://rustc-dev-guide.rust-lang.org/)
+documents how the compiler works and how to contribute to it. This is useful if
+you want to build or modify the Rust compiler from source (e.g. to target
+something non-standard).
-# Specialize Rust
-When using Rust in specific domain areas, consider using the following resources tailored to each domain.
+## Specialized Rust
-## Embedded Systems
+When using Rust in specific domains, consider using the following resources
+tailored to each area.
-When developing for Bare Metal or Embedded Linux systems, you may find these resources maintained by the [Embedded Working Group] useful.
+### Embedded Systems
+
+When developing for Bare Metal or Embedded Linux systems, you may find these
+resources maintained by the [Embedded Working Group] useful.
[Embedded Working Group]: https://github.com/rust-embedded
-### The Embedded Rust Book
+#### The Embedded Rust Book
-[The Embedded Rust Book] is targeted at developers familiar with embedded development and familiar with Rust, but have not used Rust for embedded development.
+[The Embedded Rust Book] is targeted at developers familiar with embedded
+development and familiar with Rust, but have not used Rust for embedded
+development.
[The Embedded Rust Book]: embedded-book/index.html
[Rust project]: https://www.rust-lang.org
+
+<script>
+// check if a given link is external
+function isExternalLink(url) {
+ const tmp = document.createElement('a');
+ tmp.href = url;
+ return tmp.host !== window.location.host;
+}
+
+// Add the `external` class to all <a> tags with external links and append the external link SVG
+function updateExternalAnchors() {
+ /*
+ External link SVG from Font-Awesome
+ CC BY-SA 3.0 https://creativecommons.org/licenses/by-sa/3.0
+ via Wikimedia Commons
+ */
+ const svgText = `<svg
+ class='external-link'
+ xmlns='http://www.w3.org/2000/svg'
+ viewBox='0 -256 1850 1850'
+ width='100%'
+ height='100%'>
+ <g transform='matrix(1,0,0,-1,30,1427)'>
+ <path d='M 1408,608 V 288 Q 1408,169 1323.5,84.5 1239,0 1120,
+ 0 H 288 Q 169,0 84.5,84.5 0,169 0,288 v 832 Q 0,1239 84.5,1323.5 169,
+ 1408 288,1408 h 704 q 14,0 23,-9 9,-9 9,-23 v -64 q 0,-14 -9,-23 -9,
+ -9 -23,-9 H 288 q -66,0 -113,-47 -47,-47 -47,-113 V 288 q 0,-66 47,
+ -113 47,-47 113,-47 h 832 q 66,0 113,47 47,47 47,113 v 320 q 0,14 9,
+ 23 9,9 23,9 h 64 q 14,0 23,-9 9,-9 9,-23 z m 384,864 V 960 q 0,
+ -26 -19,-45 -19,-19 -45,-19 -26,0 -45,19 L 1507,1091 855,439 q -10,
+ -10 -23,-10 -13,0 -23,10 L 695,553 q -10,10 -10,23 0,13 10,23 l 652,
+ 652 -176,176 q -19,19 -19,45 0,26 19,45 19,19 45,19 h 512 q 26,0 45,
+ -19 19,-19 19,-45 z' style='fill:currentColor' />
+ </g>
+ </svg>`;
+ let allAnchors = document.getElementsByTagName("a");
+
+ for (var i = 0; i < allAnchors.length; ++i) {
+ let anchor = allAnchors[i];
+ if (isExternalLink(anchor.href)) {
+ anchor.classList.add("external");
+ anchor.innerHTML += svgText;
+ }
+ }
+}
+
+// on page load, update external anchors
+document.addEventListener("DOMContentLoaded", updateExternalAnchors);
+
+</script>
diff --git a/src/doc/nomicon/src/dropck.md b/src/doc/nomicon/src/dropck.md
index 75940219c..4063d5619 100644
--- a/src/doc/nomicon/src/dropck.md
+++ b/src/doc/nomicon/src/dropck.md
@@ -250,7 +250,7 @@ fn main() {
inspector: None,
days: Box::new(1),
};
- world.inspector = Some(Inspector(&world.days, "gatget"));
+ world.inspector = Some(Inspector(&world.days, "gadget"));
}
```
diff --git a/src/doc/nomicon/src/ffi.md b/src/doc/nomicon/src/ffi.md
index 8d1a882b3..684e7125b 100644
--- a/src/doc/nomicon/src/ffi.md
+++ b/src/doc/nomicon/src/ffi.md
@@ -721,17 +721,20 @@ No `transmute` required!
## FFI and unwinding
-It’s important to be mindful of unwinding when working with FFI. Each
-non-`Rust` ABI comes in two variants, one with `-unwind` suffix and one without. If
-you expect Rust `panic`s or foreign (e.g. C++) exceptions to cross an FFI
-boundary, that boundary must use the appropriate `-unwind` ABI string (note
-that compiling with `panic=abort` will still cause `panic!` to immediately
-abort the process, regardless of which ABI is specified by the function that
-`panic`s).
+It’s important to be mindful of unwinding when working with FFI. Most
+ABI strings come in two variants, one with an `-unwind` suffix and one without.
+The `Rust` ABI always permits unwinding, so there is no `Rust-unwind` ABI.
+If you expect Rust `panic`s or foreign (e.g. C++) exceptions to cross an FFI
+boundary, that boundary must use the appropriate `-unwind` ABI string.
Conversely, if you do not expect unwinding to cross an ABI boundary, use one of
-the non-`unwind` ABI strings (other than `Rust`, which always permits
-unwinding). If an unwinding operation does encounter an ABI boundary that is
+the non-`unwind` ABI strings.
+
+> Note: Compiling with `panic=abort` will still cause `panic!` to immediately
+abort the process, regardless of which ABI is specified by the function that
+`panic`s.
+
+If an unwinding operation does encounter an ABI boundary that is
not permitted to unwind, the behavior depends on the source of the unwinding
(Rust `panic` or a foreign exception):
diff --git a/src/doc/nomicon/src/send-and-sync.md b/src/doc/nomicon/src/send-and-sync.md
index 34539daa3..808a5c3ae 100644
--- a/src/doc/nomicon/src/send-and-sync.md
+++ b/src/doc/nomicon/src/send-and-sync.md
@@ -94,6 +94,7 @@ to the heap.
use std::{
mem::{align_of, size_of},
ptr,
+ cmp::max,
};
struct Carton<T>(ptr::NonNull<T>);
@@ -105,8 +106,8 @@ impl<T> Carton<T> {
let mut memptr: *mut T = ptr::null_mut();
unsafe {
let ret = libc::posix_memalign(
- (&mut memptr).cast(),
- align_of::<T>(),
+ (&mut memptr as *mut *mut T).cast(),
+ max(align_of::<T>(), size_of::<usize>()),
size_of::<T>()
);
assert_eq!(ret, 0, "Failed to allocate or invalid alignment");
diff --git a/src/doc/nomicon/src/subtyping.md b/src/doc/nomicon/src/subtyping.md
index 6f0c12db4..cc48a5970 100644
--- a/src/doc/nomicon/src/subtyping.md
+++ b/src/doc/nomicon/src/subtyping.md
@@ -339,7 +339,7 @@ lifetimes to be covariant: as soon as you try to stuff them in something like a
mutable reference, they inherit invariance and you're prevented from doing anything
bad.
-However Box makes it easier to focus on by-value aspect of references that we
+However, Box makes it easier to focus on the by-value aspect of references that we
partially glossed over.
Unlike a lot of languages which allow values to be freely aliased at all times,
diff --git a/src/doc/reference/src/behavior-considered-undefined.md b/src/doc/reference/src/behavior-considered-undefined.md
index f8bffd13e..31963d1e5 100644
--- a/src/doc/reference/src/behavior-considered-undefined.md
+++ b/src/doc/reference/src/behavior-considered-undefined.md
@@ -25,7 +25,7 @@ code.
* Data races.
* Evaluating a [dereference expression] (`*expr`) on a raw pointer that is
[dangling] or unaligned, even in [place expression context]
- (e.g. `addr_of!(&*expr)`).
+ (e.g. `addr_of!(*expr)`).
* Breaking the [pointer aliasing rules]. `Box<T>`, `&mut T` and `&T` follow
LLVM’s scoped [noalias] model, except if the `&T` contains an
[`UnsafeCell<U>`]. References and boxes must not be [dangling] while they are
diff --git a/src/doc/reference/src/destructors.md b/src/doc/reference/src/destructors.md
index f89fde157..84aac89d3 100644
--- a/src/doc/reference/src/destructors.md
+++ b/src/doc/reference/src/destructors.md
@@ -162,7 +162,7 @@ smallest scope that contains the expression and is one of the following:
* The `else` block of an `if` expression.
* The condition expression of an `if` or `while` expression, or a `match`
guard.
-* The expression for a match arm.
+* The body expression for a match arm.
* The second operand of a [lazy boolean expression].
> **Notes**:
diff --git a/src/doc/reference/src/expressions/if-expr.md b/src/doc/reference/src/expressions/if-expr.md
index 591437fc9..fe387c828 100644
--- a/src/doc/reference/src/expressions/if-expr.md
+++ b/src/doc/reference/src/expressions/if-expr.md
@@ -129,7 +129,7 @@ The expression cannot be a [lazy boolean operator expression][_LazyBooleanOperat
Use of a lazy boolean operator is ambiguous with a planned feature change of the language (the implementation of if-let chains - see [eRFC 2947][_eRFCIfLetChain_]).
When lazy boolean operator expression is desired, this can be achieved by using parenthesis as below:
-<!-- ignore: psuedo code -->
+<!-- ignore: pseudo code -->
```rust,ignore
// Before...
if let PAT = EXPR && EXPR { .. }
diff --git a/src/doc/reference/src/expressions/operator-expr.md b/src/doc/reference/src/expressions/operator-expr.md
index 9f7e8edac..691f801e8 100644
--- a/src/doc/reference/src/expressions/operator-expr.md
+++ b/src/doc/reference/src/expressions/operator-expr.md
@@ -600,7 +600,7 @@ It will then set the value of the assigned operand's place to the value of perfo
> **Note**: This is different than other expressions in that the right operand is evaluated before the left one.
-Otherwise, this expression is syntactic sugar for calling the function of the overloading compound assigment trait of the operator (see the table earlier in this chapter).
+Otherwise, this expression is syntactic sugar for calling the function of the overloading compound assignment trait of the operator (see the table earlier in this chapter).
A mutable borrow of the assigned operand is automatically taken.
For example, the following expression statements in `example` are equivalent:
diff --git a/src/doc/reference/src/items/external-blocks.md b/src/doc/reference/src/items/external-blocks.md
index d89536968..ce2190829 100644
--- a/src/doc/reference/src/items/external-blocks.md
+++ b/src/doc/reference/src/items/external-blocks.md
@@ -90,6 +90,7 @@ There are also some platform-specific ABI strings:
`__fastcall` and GCC and clang's `__attribute__((fastcall))`
* `extern "vectorcall"` -- The `vectorcall` ABI -- corresponds to MSVC's
`__vectorcall` and clang's `__attribute__((vectorcall))`
+* `extern "efiapi"` -- The ABI used for [UEFI] functions.
## Variadic functions
@@ -288,6 +289,7 @@ Attributes on extern function parameters follow the same rules and
restrictions as [regular function parameters].
[IDENTIFIER]: ../identifiers.md
+[UEFI]: https://uefi.org/specifications
[WebAssembly module]: https://webassembly.github.io/spec/core/syntax/modules.html
[functions]: functions.md
[statics]: static-items.md
diff --git a/src/doc/reference/src/linkage.md b/src/doc/reference/src/linkage.md
index b15200511..82864b004 100644
--- a/src/doc/reference/src/linkage.md
+++ b/src/doc/reference/src/linkage.md
@@ -73,7 +73,7 @@ be ignored in favor of only building the artifacts specified by command line.
being built for a different target.
Note that these outputs are stackable in the sense that if multiple are
-specified, then the compiler will produce each form of output at once without
+specified, then the compiler will produce each form of output without
having to recompile. However, this only applies for outputs specified by the
same method. If only `crate_type` attributes are specified, then they will all
be built, but if one or more `--crate-type` command line flags are specified,
diff --git a/src/doc/reference/src/patterns.md b/src/doc/reference/src/patterns.md
index 14bbac155..370e1990c 100644
--- a/src/doc/reference/src/patterns.md
+++ b/src/doc/reference/src/patterns.md
@@ -380,16 +380,19 @@ match tuple {
> **<sup>Syntax</sup>**\
> _RangePattern_ :\
-> &nbsp;&nbsp; &nbsp;&nbsp; _InclusiveRangePattern_\
-> &nbsp;&nbsp; | _HalfOpenRangePattern_\
+> &nbsp;&nbsp; &nbsp;&nbsp; _RangeInclusivePattern_\
+> &nbsp;&nbsp; | _RangeFromPattern_\
+> &nbsp;&nbsp; | _RangeToInclusivePattern_\
> &nbsp;&nbsp; | _ObsoleteRangePattern_
>
-> _InclusiveRangePattern_ :\
+> _RangeInclusivePattern_ :\
> &nbsp;&nbsp; &nbsp;&nbsp; _RangePatternBound_ `..=` _RangePatternBound_
>
-> _HalfOpenRangePattern_ :\
+> _RangeFromPattern_ :\
> &nbsp;&nbsp; &nbsp;&nbsp; _RangePatternBound_ `..`
-> &nbsp;&nbsp; | `..=` _RangePatternBound_
+>
+> _RangeToInclusivePattern_ :\
+> &nbsp;&nbsp; &nbsp;&nbsp; `..=` _RangePatternBound_
>
> _ObsoleteRangePattern_ :\
> &nbsp;&nbsp; _RangePatternBound_ `...` _RangePatternBound_
@@ -402,16 +405,13 @@ match tuple {
> &nbsp;&nbsp; | [_PathExpression_]
*Range patterns* match scalar values within the range defined by their bounds.
-A bound on the left of its sigils is a *lower bound*.
+They comprise a *sigil* (one of `..`, `..=`, or `...`) and a bound on one or both sides.
+A bound on the left of the sigil is a *lower bound*.
A bound on the right is an *upper bound*.
-A range pattern may be closed or half-open.
-
-A range pattern is *closed* if it has both a lower and an upper bound.
-The only closed ranged pattern is the inclusive range pattern.
-*Inclusive range patterns* match all the values between and including both of its bounds.
-It is written as its lower bounds, followed by `..=`, followed by its upper bounds.
-The type of it is the type unification of its upper and lower bounds.
+A range pattern with both a lower and upper bound will match all values between and including both of its bounds.
+It is written as its lower bound, followed by `..=`, followed by its upper bound.
+The type of the range pattern is the type unification of its upper and lower bounds.
For example, a pattern `'m'..='p'` will match only the values `'m'`, `'n'`, `'o'`, and `'p'`.
@@ -419,19 +419,15 @@ The lower bound cannot be greater than the upper bound.
That is, in `a..=b`, a &le; b must be the case.
For example, it is an error to have a range pattern `10..=0`.
-Range patterns are *half-open* if they have only an upper or lower bound.
-They have the same type as their upper or lower bound.
-
-A half open range with only a lower bound is written as its lower bound followed by `..`.
-These range patterns will match on any value greater than or equal to the lower bound.
+A range pattern with only a lower bound will match any value greater than or equal to the lower bound.
+It is written as its lower bound followed by `..`, and has the same type as its lower bound.
For example, `1..` will match 1, 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 with only an upper bound is written as `..=` followed by its upper bound.
-These range patterns will match on any value less than or equal to the upper bound.
-For example, `..=10` will match 10, 1, 0, and for signed interger types, all negative values.
+A range pattern with only an upper bound matches any value less than or equal to the upper bound.
+It is written as `..=` followed by its upper bound, and has the same type as its upper bound.
+For example, `..=10` will match 10, 1, 0, and for signed integer types, all negative values.
-Half-open range patterns cannot be used as the top-level pattern for subpatterns in [slice patterns](#slice-patterns).
+Range patterns with only one bound cannot be used as the top-level pattern for subpatterns in [slice patterns](#slice-patterns).
The bounds is written as one of:
@@ -529,7 +525,7 @@ The range of values for a `char` type are precisely those ranges containing all
Floating point range patterns are deprecated and may be removed in a future Rust release.
See [issue #41620](https://github.com/rust-lang/rust/issues/41620) for more information.
-> **Edition Differences**: Before the 2021 edition, closed range patterns may also be written using `...` as an alternative to `..=`, with the same meaning.
+> **Edition Differences**: Before the 2021 edition, range patterns with both a lower and upper bound may also be written using `...` in place of `..=`, with the same meaning.
> **Note**: Although range patterns use the same syntax as [range expressions], there are no exclusive range patterns.
> That is, neither `x .. y` nor `.. x` are valid range patterns.
@@ -747,7 +743,8 @@ match v[..] {
Slice patterns are irrefutable when matching an array as long as each element 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.
+Within a slice, a range pattern without both lower and upper bound must be enclosed in parentheses, as in `(a..)`, to clarify it is intended to match against a single slice element.
+A range pattern with both lower and upper bound, like `a..=b`, is not required to be enclosed in parentheses.
## Path patterns
diff --git a/src/doc/reference/src/trait-bounds.md b/src/doc/reference/src/trait-bounds.md
index c8dab3f1c..0a6731288 100644
--- a/src/doc/reference/src/trait-bounds.md
+++ b/src/doc/reference/src/trait-bounds.md
@@ -27,7 +27,7 @@ provided on any type in a [where clause]. There are also shorter forms for
certain common cases:
* Bounds written after declaring a [generic parameter][generic]:
- `fn f<A: Copy>() {}` is the same as `fn f<A> where A: Copy () {}`.
+ `fn f<A: Copy>() {}` is the same as `fn f<A>() where A: Copy {}`.
* In trait declarations as [supertraits]: `trait Circle : Shape {}` is
equivalent to `trait Circle where Self : Shape {}`.
* In trait declarations as bounds on [associated types]:
diff --git a/src/doc/rust-by-example/src/error/option_unwrap/and_then.md b/src/doc/rust-by-example/src/error/option_unwrap/and_then.md
index c065f2043..42a1f3ec0 100644
--- a/src/doc/rust-by-example/src/error/option_unwrap/and_then.md
+++ b/src/doc/rust-by-example/src/error/option_unwrap/and_then.md
@@ -39,10 +39,7 @@ fn have_recipe(food: Food) -> Option<Food> {
fn cookable_v1(food: Food) -> Option<Food> {
match have_recipe(food) {
None => None,
- Some(food) => match have_ingredients(food) {
- None => None,
- Some(food) => Some(food),
- },
+ Some(food) => have_ingredients(food),
}
}
diff --git a/src/doc/rust-by-example/src/error/result/result_map.md b/src/doc/rust-by-example/src/error/result/result_map.md
index 24537c318..c453d9fa9 100644
--- a/src/doc/rust-by-example/src/error/result/result_map.md
+++ b/src/doc/rust-by-example/src/error/result/result_map.md
@@ -56,7 +56,7 @@ use std::num::ParseIntError;
// As with `Option`, we can use combinators such as `map()`.
// This function is otherwise identical to the one above and reads:
-// Modify n if the value is valid, otherwise pass on the error.
+// Multiply if both values can be parsed from str, otherwise pass on the error.
fn multiply(first_number_str: &str, second_number_str: &str) -> Result<i32, ParseIntError> {
first_number_str.parse::<i32>().and_then(|first_number| {
second_number_str.parse::<i32>().map(|second_number| first_number * second_number)
diff --git a/src/doc/rust-by-example/src/generics/bounds.md b/src/doc/rust-by-example/src/generics/bounds.md
index 5d7e849a8..86e54e670 100644
--- a/src/doc/rust-by-example/src/generics/bounds.md
+++ b/src/doc/rust-by-example/src/generics/bounds.md
@@ -58,10 +58,10 @@ fn main() {
let _triangle = Triangle { length: 3.0, height: 4.0 };
print_debug(&rectangle);
- println!("Area: {}", rectangle.area());
+ println!("Area: {}", area(&rectangle));
//print_debug(&_triangle);
- //println!("Area: {}", _triangle.area());
+ //println!("Area: {}", area(&_triangle));
// ^ TODO: Try uncommenting these.
// | Error: Does not implement either `Debug` or `HasArea`.
}
diff --git a/src/doc/rust-by-example/src/hello/comment.md b/src/doc/rust-by-example/src/hello/comment.md
index 5027f0a22..4ea6dcd44 100644
--- a/src/doc/rust-by-example/src/hello/comment.md
+++ b/src/doc/rust-by-example/src/hello/comment.md
@@ -14,7 +14,7 @@ a few different varieties:
fn main() {
// This is an example of a line comment.
// There are two slashes at the beginning of the line.
- // And nothing written inside these will be read by the compiler.
+ // And nothing written after these will be read by the compiler.
// println!("Hello, world!");
diff --git a/src/doc/rust-by-example/src/index.md b/src/doc/rust-by-example/src/index.md
index fecc1906a..ecadff4cc 100644
--- a/src/doc/rust-by-example/src/index.md
+++ b/src/doc/rust-by-example/src/index.md
@@ -27,7 +27,7 @@ Now let's begin!
- [Flow of Control](flow_control.md) - `if`/`else`, `for`, and others.
-- [Functions](fn.md) - Learn about Methods, Closures and High Order Functions.
+- [Functions](fn.md) - Learn about Methods, Closures and Higher Order Functions.
- [Modules](mod.md) - Organize code using modules
diff --git a/src/doc/rust-by-example/src/primitives/tuples.md b/src/doc/rust-by-example/src/primitives/tuples.md
index e745d89be..75c265e75 100644
--- a/src/doc/rust-by-example/src/primitives/tuples.md
+++ b/src/doc/rust-by-example/src/primitives/tuples.md
@@ -43,7 +43,7 @@ fn main() {
let pair = (1, true);
println!("Pair is {:?}", pair);
- println!("Uhe reversed pair is {:?}", reverse(pair));
+ println!("The reversed pair is {:?}", reverse(pair));
// To create one element tuples, the comma is required to tell them apart
// from a literal surrounded by parentheses.
diff --git a/src/doc/rust-by-example/src/std_misc/file/create.md b/src/doc/rust-by-example/src/std_misc/file/create.md
index 709213c9d..4f113df88 100644
--- a/src/doc/rust-by-example/src/std_misc/file/create.md
+++ b/src/doc/rust-by-example/src/std_misc/file/create.md
@@ -53,6 +53,6 @@ proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
(As in the previous example, you are encouraged to test this example under
failure conditions.)
-There is [`OpenOptions`] struct that can be used to configure how a file is opened.
+The [`OpenOptions`] struct can be used to configure how a file is opened.
[`OpenOptions`]: https://doc.rust-lang.org/std/fs/struct.OpenOptions.html
diff --git a/src/doc/rustc-dev-guide/.github/workflows/ci.yml b/src/doc/rustc-dev-guide/.github/workflows/ci.yml
index a21e342cb..2346698d4 100644
--- a/src/doc/rustc-dev-guide/.github/workflows/ci.yml
+++ b/src/doc/rustc-dev-guide/.github/workflows/ci.yml
@@ -16,10 +16,11 @@ jobs:
env:
MDBOOK_VERSION: 0.4.21
MDBOOK_LINKCHECK_VERSION: 0.7.6
- MDBOOK_MERMAID_VERSION: 0.11.2
- MDBOOK_TOC_VERSION: 0.9.0
+ MDBOOK_MERMAID_VERSION: 0.12.6
+ MDBOOK_TOC_VERSION: 0.11.2
DEPLOY_DIR: book/html
BASE_SHA: ${{ github.event.pull_request.base.sha }}
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
steps:
- uses: actions/checkout@v3
with:
diff --git a/src/doc/rustc-dev-guide/CITATION.cff b/src/doc/rustc-dev-guide/CITATION.cff
new file mode 100644
index 000000000..fee82ad8c
--- /dev/null
+++ b/src/doc/rustc-dev-guide/CITATION.cff
@@ -0,0 +1,9 @@
+cff-version: 1.2.0
+message: If you use this guide, please cite it using these metadata.
+title: Rust Compiler Development Guide (rustc-dev-guide)
+abstract: A guide to developing the Rust compiler (rustc)
+authors:
+ - name: "The Rust Project Developers"
+date-released: "2018-01-16"
+license: "MIT OR Apache-2.0"
+repository-code: "https://github.com/rust-lang/rustc-dev-guide"
diff --git a/src/doc/rustc-dev-guide/README.md b/src/doc/rustc-dev-guide/README.md
index 006ea3231..e501c9161 100644
--- a/src/doc/rustc-dev-guide/README.md
+++ b/src/doc/rustc-dev-guide/README.md
@@ -43,7 +43,7 @@ rustdocs][rustdocs].
To build a local static HTML site, install [`mdbook`](https://github.com/rust-lang/mdBook) with:
```
-> cargo install mdbook mdbook-linkcheck mdbook-toc
+> cargo install mdbook mdbook-linkcheck mdbook-toc mdbook-mermaid
```
and execute the following command in the root of the repository:
diff --git a/src/doc/rustc-dev-guide/book.toml b/src/doc/rustc-dev-guide/book.toml
index dc216760e..a5d794b50 100644
--- a/src/doc/rustc-dev-guide/book.toml
+++ b/src/doc/rustc-dev-guide/book.toml
@@ -1,7 +1,7 @@
[book]
-title = "Guide to Rustc Development"
-author = "Rustc developers"
-description = "A guide to developing rustc"
+title = "Rust Compiler Development Guide"
+author = "The Rust Project Developers"
+description = "A guide to developing the Rust compiler (rustc)"
[build]
create-missing = false
@@ -18,6 +18,9 @@ git-repository-url = "https://github.com/rust-lang/rustc-dev-guide"
edit-url-template = "https://github.com/rust-lang/rustc-dev-guide/edit/master/{path}"
additional-js = ["mermaid.min.js", "mermaid-init.js"]
+[output.html.search]
+use-boolean-and = true
+
[output.html.fold]
enable = true
level = 0
@@ -40,6 +43,9 @@ exclude = [
cache-timeout = 86400
warning-policy = "error"
+[output.linkcheck.http-headers]
+'github\.com' = ["Authorization: Bearer $GITHUB_TOKEN"]
+
[output.html.redirect]
"/compiletest.html" = "tests/compiletest.html"
"/diagnostics/sessiondiagnostic.html" = "diagnostics/diagnostic-structs.html"
diff --git a/src/doc/rustc-dev-guide/ci/date-check/src/main.rs b/src/doc/rustc-dev-guide/ci/date-check/src/main.rs
index 70fce8b1c..d9e8145a3 100644
--- a/src/doc/rustc-dev-guide/ci/date-check/src/main.rs
+++ b/src/doc/rustc-dev-guide/ci/date-check/src/main.rs
@@ -170,7 +170,7 @@ fn main() {
for (path, dates) in dates_by_file {
println!(
- "- [ ] {}",
+ "- {}",
path.strip_prefix(&root_dir_path).unwrap_or(&path).display(),
);
for (line, date) in dates {
diff --git a/src/doc/rustc-dev-guide/examples/README b/src/doc/rustc-dev-guide/examples/README
new file mode 100644
index 000000000..ca49dd74d
--- /dev/null
+++ b/src/doc/rustc-dev-guide/examples/README
@@ -0,0 +1,11 @@
+For each example to compile, you will need to first run the following:
+
+ rustup component add rustc-dev llvm-tools
+
+To create an executable:
+
+ rustc rustc-driver-example.rs
+
+To run an executable:
+
+ rustup run nightly ./rustc-driver-example
diff --git a/src/doc/rustc-dev-guide/examples/rustc-driver-example.rs b/src/doc/rustc-dev-guide/examples/rustc-driver-example.rs
index 8d8b40cd7..9708ab01d 100644
--- a/src/doc/rustc-dev-guide/examples/rustc-driver-example.rs
+++ b/src/doc/rustc-dev-guide/examples/rustc-driver-example.rs
@@ -1,10 +1,6 @@
#![feature(rustc_private)]
-// NOTE: For the example to compile, you will need to first run the following:
-// rustup component add rustc-dev llvm-tools-preview
-
-// version: rustc 1.68.0-nightly (935dc0721 2022-12-19)
-
+extern crate rustc_driver;
extern crate rustc_error_codes;
extern crate rustc_errors;
extern crate rustc_hash;
@@ -46,10 +42,9 @@ fn main() {
"#
.into(),
},
- input_path: None, // Option<PathBuf>
- output_dir: None, // Option<PathBuf>
- output_file: None, // Option<PathBuf>
- file_loader: None, // Option<Box<dyn FileLoader + Send + Sync>>
+ output_dir: None, // Option<PathBuf>
+ output_file: None, // Option<PathBuf>
+ file_loader: None, // Option<Box<dyn FileLoader + Send + Sync>>
lint_caps: FxHashMap::default(), // FxHashMap<lint::LintId, lint::Level>
// This is a callback from the driver that is called when [`ParseSess`] is created.
parse_sess_created: None, //Option<Box<dyn FnOnce(&mut ParseSess) + Send>>
@@ -71,17 +66,17 @@ fn main() {
rustc_interface::run_compiler(config, |compiler| {
compiler.enter(|queries| {
// Parse the program and print the syntax tree.
- let parse = queries.parse().unwrap().take();
+ let parse = queries.parse().unwrap().get_mut().clone();
println!("{parse:?}");
// Analyze the program and inspect the types of definitions.
- queries.global_ctxt().unwrap().take().enter(|tcx| {
+ queries.global_ctxt().unwrap().enter(|tcx| {
for id in tcx.hir().items() {
let hir = tcx.hir();
let item = hir.item(id);
match item.kind {
rustc_hir::ItemKind::Static(_, _, _) | rustc_hir::ItemKind::Fn(_, _, _) => {
let name = item.ident;
- let ty = tcx.type_of(hir.local_def_id(item.hir_id()));
+ let ty = tcx.type_of(item.hir_id().owner.def_id);
println!("{name:?}:\t{ty:?}")
}
_ => (),
diff --git a/src/doc/rustc-dev-guide/examples/rustc-driver-getting-diagnostics.rs b/src/doc/rustc-dev-guide/examples/rustc-driver-getting-diagnostics.rs
index 49ee9ff44..5bc2312a2 100644
--- a/src/doc/rustc-dev-guide/examples/rustc-driver-getting-diagnostics.rs
+++ b/src/doc/rustc-dev-guide/examples/rustc-driver-getting-diagnostics.rs
@@ -1,10 +1,6 @@
#![feature(rustc_private)]
-// NOTE: For the example to compile, you will need to first run the following:
-// rustup component add rustc-dev llvm-tools-preview
-
-// version: rustc 1.68.0-nightly (935dc0721 2022-12-19)
-
+extern crate rustc_driver;
extern crate rustc_error_codes;
extern crate rustc_errors;
extern crate rustc_hash;
@@ -67,7 +63,6 @@ fn main() {
},
crate_cfg: rustc_hash::FxHashSet::default(),
crate_check_cfg: CheckCfg::default(),
- input_path: None,
output_dir: None,
output_file: None,
file_loader: None,
@@ -80,7 +75,7 @@ fn main() {
};
rustc_interface::run_compiler(config, |compiler| {
compiler.enter(|queries| {
- queries.global_ctxt().unwrap().take().enter(|tcx| {
+ queries.global_ctxt().unwrap().enter(|tcx| {
// Run the analysis phase on the local crate to trigger the type error.
let _ = tcx.analysis(());
});
diff --git a/src/doc/rustc-dev-guide/examples/rustc-driver-interacting-with-the-ast.rs b/src/doc/rustc-dev-guide/examples/rustc-driver-interacting-with-the-ast.rs
index 07b09e9df..53f8df81a 100644
--- a/src/doc/rustc-dev-guide/examples/rustc-driver-interacting-with-the-ast.rs
+++ b/src/doc/rustc-dev-guide/examples/rustc-driver-interacting-with-the-ast.rs
@@ -1,11 +1,7 @@
#![feature(rustc_private)]
-// NOTE: For the example to compile, you will need to first run the following:
-// rustup component add rustc-dev llvm-tools-preview
-
-// version: rustc 1.68.0-nightly (935dc0721 2022-12-19)
-
extern crate rustc_ast_pretty;
+extern crate rustc_driver;
extern crate rustc_error_codes;
extern crate rustc_errors;
extern crate rustc_hash;
@@ -45,7 +41,6 @@ fn main() {
},
crate_cfg: rustc_hash::FxHashSet::default(),
crate_check_cfg: CheckCfg::default(),
- input_path: None,
output_dir: None,
output_file: None,
file_loader: None,
@@ -59,13 +54,12 @@ fn main() {
rustc_interface::run_compiler(config, |compiler| {
compiler.enter(|queries| {
// TODO: add this to -Z unpretty
- let ast_krate = queries.parse().unwrap().take();
+ let ast_krate = queries.parse().unwrap().get_mut().clone();
for item in ast_krate.items {
println!("{}", item_to_string(&item));
}
-
// Analyze the crate and inspect the types under the cursor.
- queries.global_ctxt().unwrap().take().enter(|tcx| {
+ queries.global_ctxt().unwrap().enter(|tcx| {
// Every compilation contains a single crate.
let hir_krate = tcx.hir();
// Iterate over the top-level items in the crate, looking for the main function.
@@ -78,7 +72,7 @@ fn main() {
if let rustc_hir::StmtKind::Local(local) = block.stmts[0].kind {
if let Some(expr) = local.init {
let hir_id = expr.hir_id; // hir_id identifies the string "Hello, world!"
- let def_id = tcx.hir().local_def_id(item.hir_id()); // def_id identifies the main function
+ let def_id = item.hir_id().owner.def_id; // def_id identifies the main function
let ty = tcx.typeck(def_id).node_type(hir_id);
println!("{expr:#?}: {ty:?}");
}
diff --git a/src/doc/rustc-dev-guide/src/SUMMARY.md b/src/doc/rustc-dev-guide/src/SUMMARY.md
index 360265c0e..adc397fd8 100644
--- a/src/doc/rustc-dev-guide/src/SUMMARY.md
+++ b/src/doc/rustc-dev-guide/src/SUMMARY.md
@@ -8,7 +8,7 @@
# Building and debugging `rustc`
-- [How to Build and Run the Compiler](./building/how-to-build-and-run.md)
+- [How to build and run the compiler](./building/how-to-build-and-run.md)
- [Prerequisites](./building/prerequisites.md)
- [Suggested Workflows](./building/suggested.md)
- [Distribution artifacts](./building/build-install-distribution-artifacts.md)
@@ -25,7 +25,7 @@
- [Test headers](./tests/headers.md)
- [Performance testing](./tests/perf.md)
- [Crater](./tests/crater.md)
-- [Debugging the Compiler](./compiler-debugging.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)
@@ -57,7 +57,7 @@
# High-level Compiler Architecture
- [Prologue](./part-2-intro.md)
-- [Overview of the Compiler](./overview.md)
+- [Overview of the compiler](./overview.md)
- [The compiler source code](./compiler-src.md)
- [Bootstrapping](./building/bootstrapping.md)
- [Queries: demand-driven compilation](./query.md)
@@ -75,7 +75,7 @@
- [Prologue](./part-3-intro.md)
- [Command-line arguments](./cli.md)
-- [The Rustc Driver and Interface](./rustc-driver.md)
+- [rustc_driver and rustc_interface](./rustc-driver.md)
- [Example: Type checking](./rustc-driver-interacting-with-the-ast.md)
- [Example: Getting diagnostics](./rustc-driver-getting-diagnostics.md)
- [Syntax and the AST](./syntax-intro.md)
@@ -95,7 +95,7 @@
- [MIR construction](./mir/construction.md)
- [MIR visitor and traversal](./mir/visitor.md)
- [MIR passes: getting the MIR for a function](./mir/passes.md)
-- [Identifiers in the Compiler](./identifiers.md)
+- [Identifiers in the compiler](./identifiers.md)
- [Closure expansion](./closure.md)
- [Inline assembly](./asm.md)
@@ -117,6 +117,10 @@
- [Lowering to logic](./traits/lowering-to-logic.md)
- [Goals and clauses](./traits/goals-and-clauses.md)
- [Canonical queries](./traits/canonical-queries.md)
+ - [Next-gen trait solving](./solve/trait-solving.md)
+ - [The solver](./solve/the-solver.md)
+ - [Canonicalization](./solve/canonicalization.md)
+ - [Coinduction](./solve/coinduction.md)
- [Type checking](./type-checking.md)
- [Method Lookup](./method-lookup.md)
- [Variance](./variance.md)
@@ -164,7 +168,7 @@
- [Profile-guided Optimization](./profile-guided-optimization.md)
- [LLVM Source-Based Code Coverage](./llvm-coverage-instrumentation.md)
- [Sanitizers Support](./sanitizers.md)
-- [Debugging Support in the Rust Compiler](./debugging-support-in-rustc.md)
+- [Debugging support in the Rust compiler](./debugging-support-in-rustc.md)
---
diff --git a/src/doc/rustc-dev-guide/src/appendix/glossary.md b/src/doc/rustc-dev-guide/src/appendix/glossary.md
index 42306dc1c..019d31138 100644
--- a/src/doc/rustc-dev-guide/src/appendix/glossary.md
+++ b/src/doc/rustc-dev-guide/src/appendix/glossary.md
@@ -23,7 +23,7 @@ Term | Meaning
<span id="double-ptr">double pointer</span> &nbsp; | A pointer with additional metadata. See "fat pointer" for more.
<span id="drop-glue">drop glue</span> &nbsp; | (internal) compiler-generated instructions that handle calling the destructors (`Drop`) for data types.
<span id="dst">DST</span> &nbsp; | Short for Dynamically-Sized Type, this is a type for which the compiler cannot statically know the size in memory (e.g. `str` or `[u8]`). Such types don't implement `Sized` and cannot be allocated on the stack. They can only occur as the last field in a struct. They can only be used behind a pointer (e.g. `&str` or `&[u8]`).
-<span id="ebl">early-bound lifetime</span> &nbsp; | A lifetime region that is substituted at its definition site. Bound in an item's `Generics` and substituted using a `Substs`. Contrast with **late-bound lifetime**. ([see more](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/enum.RegionKind.html#bound-regions))
+<span id="ebl">early-bound lifetime</span> &nbsp; | A lifetime region that is substituted at its definition site. Bound in an item's `Generics` and substituted using a `Substs`. Contrast with **late-bound lifetime**. ([see more](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_type_ir/sty/enum.RegionKind.html#bound-regions))
<span id="empty-type">empty type</span> &nbsp; | see "uninhabited type".
<span id="fat-ptr">fat pointer</span> &nbsp; | A two word value carrying the address of some value, along with some further information necessary to put the value to use. Rust includes two kinds of "fat pointers": references to slices, and trait objects. A reference to a slice carries the starting address of the slice and its length. A trait object carries a value's address and a pointer to the trait's implementation appropriate to that value. "Fat pointers" are also known as "wide pointers", and "double pointers".
<span id="free-var">free variable</span> &nbsp; | A "free variable" is one that is not bound within an expression or term; see [the background chapter for more](./background.md#free-vs-bound)
@@ -42,7 +42,7 @@ Term | Meaning
<span id="irlo">IRLO</span> &nbsp; | `IRLO` or `irlo` is sometimes used as an abbreviation for [internals.rust-lang.org](https://internals.rust-lang.org).
<span id="item">item</span> &nbsp; | A kind of "definition" in the language, such as a static, const, use statement, module, struct, etc. Concretely, this corresponds to the `Item` type.
<span id="lang-item">lang item</span> &nbsp; | Items that represent concepts intrinsic to the language itself, such as special built-in traits like `Sync` and `Send`; or traits representing operations such as `Add`; or functions that are called by the compiler. ([see more](https://doc.rust-lang.org/1.9.0/book/lang-items.html))
-<span id="lbl">late-bound lifetime</span> &nbsp; | A lifetime region that is substituted at its call site. Bound in a HRTB and substituted by specific functions in the compiler, such as `liberate_late_bound_regions`. Contrast with **early-bound lifetime**. ([see more](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/enum.RegionKind.html#bound-regions))
+<span id="lbl">late-bound lifetime</span> &nbsp; | A lifetime region that is substituted at its call site. Bound in a HRTB and substituted by specific functions in the compiler, such as `liberate_late_bound_regions`. Contrast with **early-bound lifetime**. ([see more](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_type_ir/sty/enum.RegionKind.html#bound-regions))
<span id="local-crate">local crate</span> &nbsp; | The crate currently being compiled. This is in contrast to "upstream crates" which refer to dependencies of the local crate.
<span id="lto">LTO</span> &nbsp; | Short for Link-Time Optimizations, this is a set of optimizations offered by LLVM that occur just before the final binary is linked. These include optimizations like removing functions that are never used in the final program, for example. _ThinLTO_ is a variant of LTO that aims to be a bit more scalable and efficient, but possibly sacrifices some optimizations. You may also read issues in the Rust repo about "FatLTO", which is the loving nickname given to non-Thin LTO. LLVM documentation: [here][lto] and [here][thinlto].
<span id="llvm">[LLVM]</span> &nbsp; | (actually not an acronym :P) an open-source compiler backend. It accepts LLVM IR and outputs native binaries. Various languages (e.g. Rust) can then implement a compiler front-end that outputs LLVM IR and use LLVM to compile to all the platforms LLVM supports.
diff --git a/src/doc/rustc-dev-guide/src/asm.md b/src/doc/rustc-dev-guide/src/asm.md
index 3b6b5e093..b19f2ad46 100644
--- a/src/doc/rustc-dev-guide/src/asm.md
+++ b/src/doc/rustc-dev-guide/src/asm.md
@@ -277,7 +277,7 @@ pub enum InlineAsmOperand<'tcx> {
}
```
-As part of HAIR lowering, `InOut` and `SplitInOut` operands are lowered to a split form with a
+As part of THIR lowering, `InOut` and `SplitInOut` operands are lowered to a split form with a
separate `in_value` and `out_place`.
Semantically, the `InlineAsm` terminator is similar to the `Call` terminator except that it has
diff --git a/src/doc/rustc-dev-guide/src/ast-validation.md b/src/doc/rustc-dev-guide/src/ast-validation.md
index ff549ca62..f3ac35e8a 100644
--- a/src/doc/rustc-dev-guide/src/ast-validation.md
+++ b/src/doc/rustc-dev-guide/src/ast-validation.md
@@ -1,6 +1,36 @@
# AST Validation
-AST validation is the process of checking various correctness properties about
-the AST after macro expansion.
+<!-- toc -->
-**TODO**: write this chapter. [#656](https://github.com/rust-lang/rustc-dev-guide/issues/656)
+## About
+
+_AST validation_ is a separate AST pass that visits each
+item in the tree and performs simple checks. This pass
+doesn't perform any complex analysis, type checking or
+name resolution.
+
+Before performing any validation, the compiler first expands
+the macros. Then this pass performs validations to check
+that each AST item is in the correct state. And when this pass
+is done, the compiler runs the crate resolution pass.
+
+## Validations
+
+Validations are defined in `AstValidator` type, which
+itself is located in `rustc_ast_passes` crate. This
+type implements various simple checks which emit errors
+when certain language rules are broken.
+
+In addition, `AstValidator` implements `Visitor` trait
+that defines how to visit AST items (which can be functions,
+traits, enums, etc).
+
+For each item, visitor performs specific checks. For
+example, when visiting a function declaration,
+`AstValidator` checks that the function has:
+
+* no more than `u16::MAX` parameters;
+* c-variadic functions are declared with at least one named argument;
+* c-variadic argument goes the last in the declaration;
+* documentation comments aren't applied to function parameters;
+* and other validations.
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 ea50cd754..c5eb57e64 100644
--- a/src/doc/rustc-dev-guide/src/backend/backend-agnostic.md
+++ b/src/doc/rustc-dev-guide/src/backend/backend-agnostic.md
@@ -2,16 +2,21 @@
<!-- toc -->
-As of <!-- date-check --> Aug 2022, `rustc_codegen_ssa` provides an
-abstract interface for all backends to implement, to allow other codegen
-backends (e.g. [Cranelift]).
+[`rustc_codegen_ssa`]
+provides an abstract interface for all backends to implement,
+namely LLVM, [Cranelift], and [GCC].
-[Cranelift]: https://github.com/bytecodealliance/wasmtime/tree/HEAD/cranelift
+[Cranelift]: https://github.com/bjorn3/rustc_codegen_cranelift
+[GCC]: https://github.com/rust-lang/rustc_codegen_gcc
+[`rustc_codegen_ssa`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_codegen_ssa/index.html
-# Refactoring of `rustc_codegen_llvm`
+Below is some background information on the refactoring that created this
+abstract interface.
+
+## Refactoring of `rustc_codegen_llvm`
by Denis Merigoux, October 23rd 2018
-## State of the code before the refactoring
+### State of the code before the refactoring
All the code related to the compilation of MIR into LLVM IR was contained
inside the `rustc_codegen_llvm` crate. Here is the breakdown of the most
@@ -51,7 +56,7 @@ While the LLVM-specific code will be left in `rustc_codegen_llvm`, all the new
traits and backend-agnostic code will be moved in `rustc_codegen_ssa` (name
suggestion by @eddyb).
-## Generic types and structures
+### Generic types and structures
@irinagpopa started to parametrize the types of `rustc_codegen_llvm` by a
generic `Value` type, implemented in LLVM by a reference `&'ll Value`. This
@@ -103,7 +108,7 @@ of the backend and it makes more sense to leave their definition to the backend
implementor than to allow just a narrow spot via a generic field for the
backend's context.
-## Traits and interface
+### Traits and interface
Because they have to be defined by the backend, `CodegenCx` and `Builder` will
be the structures implementing all the traits defining the backend's interface.
@@ -170,7 +175,7 @@ called. However, when implementing a Rust backend for `rustc`, these methods
will need information from `CodegenCx`, hence the additional parameter (unused
in the LLVM implementation of the trait).
-## State of the code after the refactoring
+### State of the code after the refactoring
The traits offer an API which is very similar to the API of LLVM. This is not
the best solution since LLVM has a very special way of doing things: when
diff --git a/src/doc/rustc-dev-guide/src/backend/monomorph.md b/src/doc/rustc-dev-guide/src/backend/monomorph.md
index 4a0b55f62..cbc56acfc 100644
--- a/src/doc/rustc-dev-guide/src/backend/monomorph.md
+++ b/src/doc/rustc-dev-guide/src/backend/monomorph.md
@@ -133,7 +133,7 @@ the substitutions with the identity parameter before being added to the set
of collected items - thereby reducing the copies from two (`[u16, u32]` and
`[u64, u32]`) to one (`[A, u32]`).
-`unused_generic_params` will also invoked during code generation when the
+`unused_generic_params` will also be invoked during code generation when the
symbol name for `foo` is being computed for use in the callsites of `foo`
(which have the regular substitutions present, otherwise there would be a
symbol mismatch between the caller and the function).
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 38fbb2e44..a02011149 100644
--- a/src/doc/rustc-dev-guide/src/backend/updating-llvm.md
+++ b/src/doc/rustc-dev-guide/src/backend/updating-llvm.md
@@ -2,7 +2,7 @@
<!-- toc -->
-<!-- date-check: Aug 2022 -->
+<!-- date-check: Feb 2023 -->
There is no formal policy about when to update LLVM or what it can be updated to,
but a few guidelines are applied:
@@ -16,9 +16,9 @@ but a few guidelines are applied:
There are two reasons we would want to update LLVM:
-* A bug could have been fixed! Often we find bugs in the compiler and fix
- them upstream in LLVM. We'll want to pull fixes back to the compiler itself as
- they're merged upstream.
+* A bug could have been fixed!
+ Note that if we are the ones who fixed such a bug,
+ we prefer to upstream it, then pull it back for use by rustc.
* LLVM itself may have a new release.
@@ -172,9 +172,11 @@ so let's go through each in detail.
Ideally the above instructions are pretty smooth, but here's some caveats to
keep in mind while going through them:
-* LLVM bugs are hard to find, don't hesitate to ask for help! Bisection is
- definitely your friend here (yes LLVM takes forever to build, yet bisection is
- still your friend)
+* LLVM bugs are hard to find, don't hesitate to ask for help!
+ Bisection is definitely your friend here
+ (yes LLVM takes forever to build, yet bisection is still your friend).
+ Note that you can make use of [Dev Desktops],
+ which is an initiative to provide the contributors with remote access to powerful hardware.
* If you've got general questions, [wg-llvm] can help you out.
* Creating branches is a privileged operation on GitHub, so you'll need someone
with write access to create the branches for you most likely.
@@ -184,3 +186,4 @@ keep in mind while going through them:
[llvm/llvm-project repository]: https://github.com/llvm/llvm-project
[`llvm-wrapper`]: https://github.com/rust-lang/rust/tree/master/compiler/rustc_llvm/llvm-wrapper
[wg-llvm]: https://rust-lang.zulipchat.com/#narrow/stream/187780-t-compiler.2Fwg-llvm
+[Dev Desktops]: https://forge.rust-lang.org/infra/docs/dev-desktop.html
diff --git a/src/doc/rustc-dev-guide/src/borrow_check/region_inference/lifetime_parameters.md b/src/doc/rustc-dev-guide/src/borrow_check/region_inference/lifetime_parameters.md
index 2dbbc0c1e..bd8a07843 100644
--- a/src/doc/rustc-dev-guide/src/borrow_check/region_inference/lifetime_parameters.md
+++ b/src/doc/rustc-dev-guide/src/borrow_check/region_inference/lifetime_parameters.md
@@ -43,8 +43,8 @@ only variant of [`ty::RegionKind`] that we use is the [`ReVar`]
variant. These region variables are broken into two major categories,
based on their index:
-[`ty::RegionKind`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/enum.RegionKind.html
-[`ReVar`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/enum.RegionKind.html#variant.ReVar
+[`ty::RegionKind`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_type_ir/sty/enum.RegionKind.html
+[`ReVar`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_type_ir/sty/enum.RegionKind.html#variant.ReVar
- 0..N: universal regions -- the ones we are discussing here. In this
case, the code must be correct with respect to any value of those
diff --git a/src/doc/rustc-dev-guide/src/building/bootstrapping.md b/src/doc/rustc-dev-guide/src/building/bootstrapping.md
index 543c68c2e..fe34cb500 100644
--- a/src/doc/rustc-dev-guide/src/building/bootstrapping.md
+++ b/src/doc/rustc-dev-guide/src/building/bootstrapping.md
@@ -1,8 +1,7 @@
-# Bootstrapping the Compiler
+# Bootstrapping the compiler
<!-- toc -->
-
[*Bootstrapping*][boot] is the process of using a compiler to compile itself.
More accurately, it means using an older compiler to compile a newer version
of the same compiler.
@@ -16,6 +15,11 @@ version.
This is exactly how `x.py` works: it downloads the current beta release of
rustc, then uses it to compile the new compiler.
+Note that this documentation mostly covers user-facing information. See
+[bootstrap/README.md][bootstrap-internals] to read about bootstrap internals.
+
+[bootstrap-internals]: https://github.com/rust-lang/rust/blob/master/src/bootstrap/README.md
+
## Stages of bootstrapping
Compiling `rustc` is done in stages. Here's a diagram, adapted from Joshua Nelson's
@@ -86,7 +90,7 @@ because one must first build the new compiler with an older compiler
and then use that to build the new compiler with itself.
For development, you usually only want the `stage1` compiler,
which you can build with `./x.py build library`.
-See [Building the Compiler](./how-to-build-and-run.html#building-the-compiler).
+See [Building the compiler](./how-to-build-and-run.html#building-the-compiler).
### Stage 3
@@ -135,31 +139,6 @@ bootstrapping the compiler.
[intrinsics]: ../appendix/glossary.md#intrinsic
[ocaml-compiler]: https://github.com/rust-lang/rust/tree/ef75860a0a72f79f97216f8aaa5b388d98da6480/src/boot
-## Contributing to bootstrap
-
-When you use the bootstrap system, you'll call it through `x.py`.
-However, most of the code lives in `src/bootstrap`.
-`bootstrap` has a difficult problem: it is written in Rust, but yet it is run
-before the Rust compiler is built! To work around this, there are two
-components of bootstrap: the main one written in rust, and `bootstrap.py`.
-`bootstrap.py` is what gets run by `x.py`. It takes care of downloading the
-`stage0` compiler, which will then build the bootstrap binary written in
-Rust.
-
-Because there are two separate codebases behind `x.py`, they need to
-be kept in sync. In particular, both `bootstrap.py` and the bootstrap binary
-parse `config.toml` and read the same command line arguments. `bootstrap.py`
-keeps these in sync by setting various environment variables, and the
-programs sometimes have to add arguments that are explicitly ignored, to be
-read by the other.
-
-### Adding a setting to config.toml
-
-This section is a work in progress. In the meantime, you can see an example
-contribution [here][bootstrap-build].
-
-[bootstrap-build]: https://github.com/rust-lang/rust/pull/71994
-
## Understanding stages of bootstrap
### Overview
@@ -407,44 +386,51 @@ usually means something is quite wrong -- or you're trying to compile e.g.
the unlikely case that you actually need to invoke rustc in such a situation,
you can tell the bootstrap shim to print all env variables by adding `-vvv` to your `x.py` command.
-### Directories and artifacts generated by `bootstrap`
-
-This is an incomplete reference for the outputs generated by bootstrap:
-
-| Stage 0 Action | Output |
-|-----------------------------------------------------------|----------------------------------------------|
-| `beta` extracted | `build/HOST/stage0` |
-| `stage0` builds `bootstrap` | `build/bootstrap` |
-| `stage0` builds `test`/`std` | `build/HOST/stage0-std/TARGET` |
-| copy `stage0-std` (HOST only) | `build/HOST/stage0-sysroot/lib/rustlib/HOST` |
-| `stage0` builds `rustc` with `stage0-sysroot` | `build/HOST/stage0-rustc/HOST` |
-| copy `stage0-rustc` (except executable) | `build/HOST/stage0-sysroot/lib/rustlib/HOST` |
-| build `llvm` | `build/HOST/llvm` |
-| `stage0` builds `codegen` with `stage0-sysroot` | `build/HOST/stage0-codegen/HOST` |
-| `stage0` builds `rustdoc`, `clippy`, `miri`, with `stage0-sysroot` | `build/HOST/stage0-tools/HOST` |
-
-`--stage=0` stops here.
-
-| Stage 1 Action | Output |
-|-----------------------------------------------------|---------------------------------------|
-| copy (uplift) `stage0-rustc` executable to `stage1` | `build/HOST/stage1/bin` |
-| copy (uplift) `stage0-codegen` to `stage1` | `build/HOST/stage1/lib` |
-| copy (uplift) `stage0-sysroot` to `stage1` | `build/HOST/stage1/lib` |
-| `stage1` builds `test`/`std` | `build/HOST/stage1-std/TARGET` |
-| copy `stage1-std` (HOST only) | `build/HOST/stage1/lib/rustlib/HOST` |
-| `stage1` builds `rustc` | `build/HOST/stage1-rustc/HOST` |
-| copy `stage1-rustc` (except executable) | `build/HOST/stage1/lib/rustlib/HOST` |
-| `stage1` builds `codegen` | `build/HOST/stage1-codegen/HOST` |
-
-`--stage=1` stops here.
-
-| Stage 2 Action | Output |
-|--------------------------------------------------------|-----------------------------------------------------------------|
-| copy (uplift) `stage1-rustc` executable | `build/HOST/stage2/bin` |
-| copy (uplift) `stage1-sysroot` | `build/HOST/stage2/lib and build/HOST/stage2/lib/rustlib/HOST` |
-| `stage2` builds `test`/`std` (not HOST targets) | `build/HOST/stage2-std/TARGET` |
-| copy `stage2-std` (not HOST targets) | `build/HOST/stage2/lib/rustlib/TARGET` |
-| `stage2` builds `rustdoc`, `clippy`, `miri` | `build/HOST/stage2-tools/HOST` |
-| copy `rustdoc` | `build/HOST/stage2/bin` |
-
-`--stage=2` stops here.
+Finally, bootstrap makes use of the [cc-rs crate] which has [its own
+method][env-vars] of configuring C compilers and C flags via environment
+variables.
+
+[cc-rs crate]: https://github.com/rust-lang/cc-rs
+[env-vars]: https://github.com/rust-lang/cc-rs#external-configuration-via-environment-variables
+
+## Clarification of build command's stdout
+
+In this part, we will investigate the build command's stdout in an action
+(similar, but more detailed and complete documentation compare to topic above).
+When you execute `x.py build --dry-run` command, the build output will be something
+like the following:
+
+```text
+Building stage0 library artifacts (x86_64-unknown-linux-gnu -> x86_64-unknown-linux-gnu)
+Copying stage0 library from stage0 (x86_64-unknown-linux-gnu -> x86_64-unknown-linux-gnu / x86_64-unknown-linux-gnu)
+Building stage0 compiler artifacts (x86_64-unknown-linux-gnu -> x86_64-unknown-linux-gnu)
+Copying stage0 rustc from stage0 (x86_64-unknown-linux-gnu -> x86_64-unknown-linux-gnu / x86_64-unknown-linux-gnu)
+Assembling stage1 compiler (x86_64-unknown-linux-gnu)
+Building stage1 library artifacts (x86_64-unknown-linux-gnu -> x86_64-unknown-linux-gnu)
+Copying stage1 library from stage1 (x86_64-unknown-linux-gnu -> x86_64-unknown-linux-gnu / x86_64-unknown-linux-gnu)
+Building stage1 tool rust-analyzer-proc-macro-srv (x86_64-unknown-linux-gnu)
+Building rustdoc for stage1 (x86_64-unknown-linux-gnu)
+```
+
+### Building stage0 {std,compiler} artifacts
+
+These steps use the provided (downloaded, usually) compiler to compile the
+local Rust source into libraries we can use.
+
+### Copying stage0 {std,rustc}
+
+This copies the library and compiler artifacts from Cargo into
+`stage0-sysroot/lib/rustlib/{target-triple}/lib`
+
+### Assembling stage1 compiler
+
+This copies the libraries we built in "building stage0 ... artifacts" into
+the stage1 compiler's lib directory. These are the host libraries that the
+compiler itself uses to run. These aren't actually used by artifacts the new
+compiler generates. This step also copies the rustc and rustdoc binaries we
+generated into `build/$HOST/stage/bin`.
+
+The stage1/bin/rustc is a fully functional compiler, but it doesn't yet have
+any libraries to link built binaries or libraries to. The next 3 steps will
+provide those libraries for it; they are mostly equivalent to constructing
+the stage1/bin compiler so we don't go through them individually.
diff --git a/src/doc/rustc-dev-guide/src/building/how-to-build-and-run.md b/src/doc/rustc-dev-guide/src/building/how-to-build-and-run.md
index 24786c0c0..6651b3691 100644
--- a/src/doc/rustc-dev-guide/src/building/how-to-build-and-run.md
+++ b/src/doc/rustc-dev-guide/src/building/how-to-build-and-run.md
@@ -1,4 +1,4 @@
-# How to Build and Run the Compiler
+# How to build and run the compiler
The compiler is built using a tool called `x.py`. You will need to
have Python installed to run it.
@@ -52,7 +52,7 @@ If you have already built `rustc` and you change settings related to LLVM, then
execute `rm -rf build` for subsequent configuration changes to take effect. Note that `./x.py
clean` will not cause a rebuild of LLVM.
-## Building the Compiler
+## Building the compiler
Note that building will require a relatively large amount of storage space.
You may want to have upwards of 10 or 15 gigabytes available to build the compiler.
@@ -122,16 +122,11 @@ you will likely need to build at some point; for example, if you want
to run the entire test suite).
```bash
-rustup toolchain link stage1 build/<host-triple>/stage1
-rustup toolchain link stage2 build/<host-triple>/stage2
+rustup toolchain link stage0 build/host/stage0-sysroot # beta compiler + stage0 std
+rustup toolchain link stage1 build/host/stage1
+rustup toolchain link stage2 build/host/stage2
```
-The `<host-triple>` would typically be one of the following:
-
-- Linux: `x86_64-unknown-linux-gnu`
-- Mac: `x86_64-apple-darwin` or `aarch64-apple-darwin`
-- Windows: `x86_64-pc-windows-msvc`
-
Now you can run the `rustc` you built with. If you run with `-vV`, you
should see a version number ending in `-dev`, indicating a build from
your local environment:
diff --git a/src/doc/rustc-dev-guide/src/building/prerequisites.md b/src/doc/rustc-dev-guide/src/building/prerequisites.md
index 8fee0a4b5..3dc2ea934 100644
--- a/src/doc/rustc-dev-guide/src/building/prerequisites.md
+++ b/src/doc/rustc-dev-guide/src/building/prerequisites.md
@@ -29,7 +29,7 @@ laptop. We suggest downloading LLVM from CI so you don't have to build it from s
Like `cargo`, the build system will use as many cores as possible. Sometimes
this can cause you to run low on memory. You can use `-j` to adjust the number
-concurrent jobs. If a full build takes more than ~45 minutes to an hour, you
+of concurrent jobs. If a full build takes more than ~45 minutes to an hour, you
are probably spending most of the time swapping memory in and out; try using
`-j1`.
diff --git a/src/doc/rustc-dev-guide/src/building/suggested.md b/src/doc/rustc-dev-guide/src/building/suggested.md
index f81daa5bc..2e2592094 100644
--- a/src/doc/rustc-dev-guide/src/building/suggested.md
+++ b/src/doc/rustc-dev-guide/src/building/suggested.md
@@ -19,51 +19,25 @@ You can also install the hook as a step of running `./x.py setup`!
## Configuring `rust-analyzer` for `rustc`
+### Visual Studio Code
+
`rust-analyzer` can help you check and format your code whenever you save
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: <!-- date-check: nov 2022 --><!-- the date comment is for the edition below -->
-
-```JSON
-{
- "rust-analyzer.checkOnSave.overrideCommand": [
- "python3",
- "x.py",
- "check",
- "--json-output"
- ],
- "rust-analyzer.rustfmt.overrideCommand": [
- "./build/host/stage0/bin/rustfmt",
- "--edition=2021"
- ],
- "rust-analyzer.procMacro.server": "./build/host/stage0/libexec/rust-analyzer-proc-macro-srv",
- "rust-analyzer.procMacro.enable": true,
- "rust-analyzer.cargo.buildScripts.enable": true,
- "rust-analyzer.cargo.buildScripts.invocationLocation": "root",
- "rust-analyzer.cargo.buildScripts.invocationStrategy": "once",
- "rust-analyzer.cargo.buildScripts.overrideCommand": [
- "python3",
- "x.py",
- "check",
- "--json-output"
- ],
- "rust-analyzer.cargo.sysroot": "./build/host/stage0-sysroot",
- "rust-analyzer.rustc.source": "./Cargo.toml",
-}
-```
-
-in your `.vscode/settings.json` file. This will ask `rust-analyzer` to use
-`./x.py check` to check the sources, and the stage 0 rustfmt to format them.
+of these tools when hacking on `rustc`. For example, `x.py setup` will prompt
+you to create a `.vscode/settings.json` file which will configure Visual Studio code.
+This will ask `rust-analyzer` to use `./x.py check` to check the sources, and the
+stage 0 rustfmt to format them.
+The recommended `rust-analyzer` settings live at [`src/etc/vscode_settings.json`].
If you have enough free disk space and you would like to be able to run `x.py` commands while
rust-analyzer runs in the background, you can also add `--build-dir build-rust-analyzer` to the
`overrideCommand` to avoid x.py locking.
If you're running `coc.nvim`, you can use `:CocLocalConfig` to create a
-`.vim/coc-settings.json` and enter the same settings as above, but replacing
-`editor.formatOnSave: true,` with
-`"coc.preferences.formatOnSaveFiletypes": ["rust"],`.
+`.vim/coc-settings.json` and copy the settings from [`src/etc/vscode_settings.json`].
+
+[`src/etc/vscode_settings.json`]: https://github.com/rust-lang/rust/blob/master/src/etc/vscode_settings.json
If running `./x.py check` on save is inconvenient, in VS Code you can use a [Build
Task] instead:
@@ -87,6 +61,35 @@ Task] instead:
[Build Task]: https://code.visualstudio.com/docs/editor/tasks
+
+### Neovim
+
+For Neovim users there are several options for configuring for rustc. The easiest way is by using
+[neoconf.nvim](https://github.com/folke/neoconf.nvim/), which allows for project-local
+configuration files with the native LSP. The steps for how to use it are below. Note that requires
+Rust-Analyzer to already be configured with Neovim. Steps for this can be
+[found here](https://rust-analyzer.github.io/manual.html#nvim-lsp).
+
+1. First install the plugin. This can be done by following the steps in the README.
+2. Run `x.py setup`, which will have a prompt for it to create a `.vscode/settings.json` file.
+`neoconf` is able to read and update Rust-Analyzer settings automatically when the project is
+opened when this file is detected.
+
+If you're running `coc.nvim`, you can use `:CocLocalConfig` to create a
+`.vim/coc-settings.json` and copy the settings from
+[this file](https://github.com/rust-lang/rust/blob/master/src/etc/vscode_settings.json).
+
+Another way is without a plugin, and creating your own logic in your configuration. To do this you
+must translate the JSON to Lua yourself. The translation is 1:1 and fairly straight-forward. It
+must be put in the `["rust-analyzer"]` key of the setup table, which is
+[shown here](https://github.com/neovim/nvim-lspconfig/blob/master/doc/server_configurations.md#rust_analyzer)
+
+If you would like to use the build task that is described above, you may either make your own
+command in your config, or you can install a plugin such as
+[overseer.nvim](https://github.com/stevearc/overseer.nvim) that can [read VSCode's `task.json`
+files](https://github.com/stevearc/overseer.nvim/blob/master/doc/guides.md#vs-code-tasks), and
+follow the same instructions as above.
+
## Check, check, and check again
When doing simple refactorings, it can be useful to run `./x.py check`
@@ -175,6 +178,27 @@ You can also use `--keep-stage 1` when running tests. Something like this:
- Initial test run: `./x.py test tests/ui`
- Subsequent test run: `./x.py test tests/ui --keep-stage 1`
+## Using incremental compilation
+
+You can further enable the `--incremental` flag to save additional
+time in subsequent rebuilds:
+
+```bash
+./x.py test tests/ui --incremental --test-args issue-1234
+```
+
+If you don't want to include the flag with every command, you can
+enable it in the `config.toml`:
+
+```toml
+[rust]
+incremental = true
+```
+
+Note that incremental compilation will use more disk space than usual.
+If disk space is a concern for you, you might want to check the size
+of the `build` directory from time to time.
+
## Fine-tuning optimizations
Setting `optimize = false` makes the compiler too slow for tests. However, to
diff --git a/src/doc/rustc-dev-guide/src/closure.md b/src/doc/rustc-dev-guide/src/closure.md
index 5746fd4de..e356f415d 100644
--- a/src/doc/rustc-dev-guide/src/closure.md
+++ b/src/doc/rustc-dev-guide/src/closure.md
@@ -155,7 +155,7 @@ This uses the stage1 compiler and enables `debug!` logging for the
The other option is to step through the code using lldb or gdb.
-1. `rust-lldb build/x86_64-apple-darwin/stage1/bin/rustc test.rs`
+1. `rust-lldb build/host/stage1/bin/rustc test.rs`
2. In lldb:
1. `b upvar.rs:134` // Setting the breakpoint on a certain line in the upvar.rs file`
2. `r` // Run the program until it hits the breakpoint
diff --git a/src/doc/rustc-dev-guide/src/compiler-debugging.md b/src/doc/rustc-dev-guide/src/compiler-debugging.md
index eac9aeb6d..6052ea58a 100644
--- a/src/doc/rustc-dev-guide/src/compiler-debugging.md
+++ b/src/doc/rustc-dev-guide/src/compiler-debugging.md
@@ -1,5 +1,4 @@
# Debugging the compiler
-[debugging]: #debugging
<!-- toc -->
@@ -185,7 +184,7 @@ stack backtrace:
Cool, now I have a backtrace for the error!
-## Getting the the error creation location
+## Getting the error creation location
`-Z track-diagnostics` can help figure out where errors are emitted. It uses `#[track_caller]`
for this and prints its location alongside the error:
@@ -341,3 +340,37 @@ error: aborting due to previous error
```
[`Layout`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_target/abi/struct.Layout.html
+
+
+## Configuring CodeLLDB for debugging `rustc`
+
+If you are using VSCode, and have edited your `config.toml` to request debugging
+level 1 or 2 for the parts of the code you're interested in, then you should be
+able to use the [CodeLLDB] extension in VSCode to debug it.
+
+Here is a sample `launch.json` file, being used to run a stage 1 compiler direct
+from the directory where it is built (does not have to be "installed"):
+
+```javascript
+// .vscode/launch.json
+{
+ "version": "0.2.0",
+ "configurations": [
+ {
+ "type": "lldb",
+ "request": "launch",
+ "name": "Launch",
+ "args": [], // array of string command-line arguments to pass to compiler
+ "program": "${workspaceFolder}/build/host/stage1/bin/rustc",
+ "windows": { // applicable if using windows
+ "program": "${workspaceFolder}/build/host/stage1/bin/rustc.exe"
+ },
+ "cwd": "${workspaceFolder}", // current working directory at program start
+ "stopOnEntry": false,
+ "sourceLanguages": ["rust"]
+ }
+ ]
+ }
+```
+
+[CodeLLDB]: https://marketplace.visualstudio.com/items?itemName=vadimcn.vscode-lldb
diff --git a/src/doc/rustc-dev-guide/src/compiler-src.md b/src/doc/rustc-dev-guide/src/compiler-src.md
index 1f55a9d09..9c7d0bb2e 100644
--- a/src/doc/rustc-dev-guide/src/compiler-src.md
+++ b/src/doc/rustc-dev-guide/src/compiler-src.md
@@ -27,8 +27,10 @@ The repository consists of three main directories:
`proc_macro`, `test`), as well as the Rust runtime (`backtrace`, `rtstartup`,
`lang_start`).
+- `tests/` contains the compiler tests.
+
- `src/` contains the source code for rustdoc, clippy, cargo, the build system,
- compiler tests, language docs, etc.
+ language docs, etc.
## Compiler
diff --git a/src/doc/rustc-dev-guide/src/constants.md b/src/doc/rustc-dev-guide/src/constants.md
index a33a283f3..91d21bd32 100644
--- a/src/doc/rustc-dev-guide/src/constants.md
+++ b/src/doc/rustc-dev-guide/src/constants.md
@@ -78,5 +78,5 @@ the constant doesn't use them in any way. This can cause
[`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
+[`ty::TyKind`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_type_ir/sty/enum.TyKind.html
[pcg-unused-substs]: https://github.com/rust-lang/project-const-generics/issues/33
diff --git a/src/doc/rustc-dev-guide/src/contributing.md b/src/doc/rustc-dev-guide/src/contributing.md
index bc39508a4..383660fc1 100644
--- a/src/doc/rustc-dev-guide/src/contributing.md
+++ b/src/doc/rustc-dev-guide/src/contributing.md
@@ -202,7 +202,7 @@ Periodically the changes made to subtree based dependencies need to be synchroni
repository and the upstream tool repositories.
Subtree synchronizations are typically handled by the respective tool maintainers. Other users
-are welcome to submit synchronization PRs, however, in order to do so you you will need to modify
+are welcome to submit synchronization PRs, however, in order to do so you will need to modify
your local git installation and follow a very precise set of instructions.
These instructions are documented, along with several useful tips and tricks, in the
[syncing subtree changes][clippy-sync-docs] section in Clippy's Contributing guide.
@@ -320,7 +320,7 @@ Here are those same steps in detail:
merged because CI will be broken. You'll want to write a message on the PR referencing
your change, and how the PR should be merged once your change makes it into a nightly.
5. Wait for your PR to merge.
-6. Wait for a nightly
+6. Wait for a nightly.
7. (optional) Help land your PR on the upstream repository now that your changes are in nightly.
8. (optional) Send a PR to rust-lang/rust updating the submodule.
@@ -390,20 +390,20 @@ Just a few things to keep in mind:
add a special annotation before specifying the date:
```md
- <!-- date-check --> Jul 2022
+ <!-- date-check --> Jan 2023
```
Example:
```md
- As of <!-- date-check --> Jul 2022, the foo did the bar.
+ As of <!-- date-check --> Jan 2023, the foo did the bar.
```
For cases where the date should not be part of the visible rendered output,
use the following instead:
```md
- <!-- date-check: Jul 2022 -->
+ <!-- date-check: Jan 2023 -->
```
- A link to a relevant WG, tracking issue, `rustc` rustdoc page, or similar, that may provide
diff --git a/src/doc/rustc-dev-guide/src/crates-io.md b/src/doc/rustc-dev-guide/src/crates-io.md
index f012c5bb5..403d61a81 100644
--- a/src/doc/rustc-dev-guide/src/crates-io.md
+++ b/src/doc/rustc-dev-guide/src/crates-io.md
@@ -11,10 +11,9 @@ you should avoid adding dependencies to the compiler for several reasons:
- The dependency may have transitive dependencies that have one of the above
problems.
-As of <!-- date-check --> Aug 2022,
-there is no official policy for vetting new dependencies to the compiler.
-Decisions are made on a case-by-case basis,
-during code review.
+<!-- date-check: Feb 2023 -->
+Note that there is no official policy for vetting new dependencies to the compiler.
+Decisions are made on a case-by-case basis, during code review.
## Permitted dependencies
diff --git a/src/doc/rustc-dev-guide/src/diagnostics.md b/src/doc/rustc-dev-guide/src/diagnostics.md
index b50b7bd18..d32de068e 100644
--- a/src/doc/rustc-dev-guide/src/diagnostics.md
+++ b/src/doc/rustc-dev-guide/src/diagnostics.md
@@ -112,10 +112,11 @@ Here are a few examples:
- Dead code: this is a lint. While the user probably doesn't want dead code in
their crate, making this a hard error would make refactoring and development
very painful.
-- [safe_packed_borrows future compatibility warning][safe_packed_borrows]:
- this is a silencable lint related to safety. It was judged that the making
- this a hard (fixed) error would cause too much breakage, so instead a
- warning is emitted that eventually will be turned into a hard error.
+- [future-incompatible lints]:
+ these are silencable lints.
+ It was decided that making them fixed errors would cause too much breakage,
+ so warnings are instead emitted,
+ and will eventually be turned into fixed (hard) errors.
Hard-coded warnings (those using the `span_warn` methods) should be avoided
for normal code, preferring to use lints instead. Some cases, such as warnings
@@ -124,7 +125,7 @@ with CLI flags, will require the use of hard-coded warnings.
See the `deny` [lint level](#diagnostic-levels) below for guidelines when to
use an error-level lint instead of a fixed error.
-[safe_packed_borrows]: https://github.com/rust-lang/rust/issues/46043
+[future-incompatible lints]: #future-incompatible-lints
## Diagnostic output style guide
@@ -637,12 +638,12 @@ broader meaning than what rustc exposes to users of the compiler.
Inside rustc, future-incompatible lints are for signalling to the user that code they have
written may not compile in the future. In general, future-incompatible code
exists for two reasons:
-* the user has written unsound code that the compiler mistakenly accepted. While
+* The user has written unsound code that the compiler mistakenly accepted. While
it is within Rust's backwards compatibility guarantees to fix the soundness hole
(breaking the user's code), the lint is there to warn the user that this will happen
in some upcoming version of rustc *regardless of which edition the code uses*. This is the
meaning that rustc exclusively exposes to users as "future incompatible".
-* the user has written code that will either no longer compiler *or* will change
+* The user has written code that will either no longer compiler *or* will change
meaning in an upcoming *edition*. These are often called "edition lints" and can be
typically seen in the various "edition compatibility" lint groups (e.g., `rust_2021_compatibility`)
that are used to lint against code that will break if the user updates the crate's edition.
@@ -665,7 +666,7 @@ declare_lint! {
Notice the `reason` field which describes why the future incompatible change is happening.
This will change the diagnostic message the user receives as well as determine which
lint groups the lint is added to. In the example above, the lint is an "edition lint"
-(since it's "reason" is `EditionError`) signifying to the user that the use of anonymous
+(since its "reason" is `EditionError`), signifying to the user that the use of anonymous
parameters will no longer compile in Rust 2018 and beyond.
Inside [LintStore::register_lints][fi-lint-groupings], lints with `future_incompatible`
diff --git a/src/doc/rustc-dev-guide/src/diagnostics/diagnostic-items.md b/src/doc/rustc-dev-guide/src/diagnostics/diagnostic-items.md
index dcaba533e..78fdd032d 100644
--- a/src/doc/rustc-dev-guide/src/diagnostics/diagnostic-items.md
+++ b/src/doc/rustc-dev-guide/src/diagnostics/diagnostic-items.md
@@ -48,7 +48,7 @@ A new diagnostic item can be added with these two steps:
For the naming conventions of diagnostic items, please refer to
[*Naming Conventions*](#naming-conventions).
-2. <!-- date-check: Aug 2022 -->
+2. <!-- date-check: Feb 2023 -->
Diagnostic items in code are accessed via symbols in
[`rustc_span::symbol::sym`].
To add your newly-created diagnostic item,
diff --git a/src/doc/rustc-dev-guide/src/diagnostics/diagnostic-structs.md b/src/doc/rustc-dev-guide/src/diagnostics/diagnostic-structs.md
index e26ba5f34..790d74dcf 100644
--- a/src/doc/rustc-dev-guide/src/diagnostics/diagnostic-structs.md
+++ b/src/doc/rustc-dev-guide/src/diagnostics/diagnostic-structs.md
@@ -23,7 +23,7 @@ pub struct FieldAlreadyDeclared {
#[primary_span]
#[label]
pub span: Span,
- #[label(hir_analysis_previous_decl_label)]
+ #[label(previous_decl_label)]
pub prev_span: Span,
}
```
@@ -82,7 +82,7 @@ these attributes can also take a value that is the attribute name to look for
Other types have special behavior when used in a `Diagnostic` derive:
-- Any attribute applied to an `Option<T>` and will only emit a
+- Any attribute applied to an `Option<T>` will only emit a
subdiagnostic if the option is `Some(..)`.
- Any attribute applied to a `Vec<T>` will be repeated for each element of the
vector.
diff --git a/src/doc/rustc-dev-guide/src/diagnostics/translation.md b/src/doc/rustc-dev-guide/src/diagnostics/translation.md
index e36333039..e3ccec7d7 100644
--- a/src/doc/rustc-dev-guide/src/diagnostics/translation.md
+++ b/src/doc/rustc-dev-guide/src/diagnostics/translation.md
@@ -222,7 +222,7 @@ returned by `Emitter::fluent_bundle`. This bundle is used preferentially when
translating messages, the fallback bundle is only used if the primary bundle is
missing a message or not provided.
-As of <!-- date-check --> June 2022, there are no locale bundles
+As of <!-- date-check --> Jan 2023, there are no locale bundles
distributed with the compiler, but mechanisms are implemented for loading
bundles.
diff --git a/src/doc/rustc-dev-guide/src/getting-started.md b/src/doc/rustc-dev-guide/src/getting-started.md
index 4e1f520ff..bc294d1b3 100644
--- a/src/doc/rustc-dev-guide/src/getting-started.md
+++ b/src/doc/rustc-dev-guide/src/getting-started.md
@@ -81,7 +81,7 @@ normally used for: building, testing, creating releases, formatting, etc.
[bootstrapping]: ./building/bootstrapping.md
-### Configuring the Compiler
+### Configuring the compiler
In the top level of the repo:
@@ -114,6 +114,10 @@ serious development work. In particular, `./x.py build` and `./x.py test`
provide many ways to compile or test a subset of the code, which can save a lot
of time.
+Also, note that `x.py` supports all kinds of path suffixes for `compiler`, `library`,
+and `src/tools` directories. So, you can simply run `x.py test tidy` instead of
+`x.py test src/tools/tidy`. Or, `x.py build std` instead of `x.py build library/std`.
+
[rust-analyzer]: ./building/suggested.html#configuring-rust-analyzer-for-rustc
See the chapters on [building](./building/how-to-build-and-run.md),
diff --git a/src/doc/rustc-dev-guide/src/git.md b/src/doc/rustc-dev-guide/src/git.md
index cac3d6534..a426157a2 100644
--- a/src/doc/rustc-dev-guide/src/git.md
+++ b/src/doc/rustc-dev-guide/src/git.md
@@ -238,18 +238,22 @@ Changes not staged for commit:
no changes added to commit (use "git add" and/or "git commit -a")
```
-These changes are not changes to files: they are changes to submodules (more on
-this [later](#git-submodules)). To get rid of those, run `git submodule update`
-(or run any `x.py` command, which will automatically update the submodules).
-Note that,
-as of <!-- date-check --> Aug 2022,
+These changes are not changes to files: they are changes to submodules (more on this
+[later](#git-submodules)). To get rid of those, run `./x.py --help`, which will automatically update
+the submodules.
+
+Some submodules are not actually needed; for example, `src/llvm-project` doesn't need to be checked
+out if you're using `download-ci-llvm`. To avoid having to keep fetching its history, you can use
+`git submodule deinit -f src/llvm-project`, which will also avoid it showing as modified again.
+
+Note that, as of <!-- date-check --> Aug 2022,
there is a [bug][#77620] if you use worktrees,
submodules, and `x.py` in a commit hook.
If you run into an error like the following,
it's not anything you did wrong:
```
-error: failed to read `/home/joshua/rustc-worktree/src/tools/miri/cargo-miri/Cargo.toml`
+error: failed to read `/home/jyn/rustc-worktree/src/tools/cargo/Cargo.toml`
Caused by:
No such file or directory (os error 2)
@@ -260,8 +264,6 @@ There is a workaround in [the issue][#77620-workaround].
[#77620]: https://github.com/rust-lang/rust/issues/77620
[#77620-workaround]: https://github.com/rust-lang/rust/issues/77620#issuecomment-705228229
-(Note that as of Sept 2022 `miri` is a subtree and not a submodule.)
-
## Rebasing and Conflicts
When you edit your code locally, you are making changes to the version of
diff --git a/src/doc/rustc-dev-guide/src/hir.md b/src/doc/rustc-dev-guide/src/hir.md
index 8316f7ce3..160b47645 100644
--- a/src/doc/rustc-dev-guide/src/hir.md
+++ b/src/doc/rustc-dev-guide/src/hir.md
@@ -117,9 +117,9 @@ that `n` must be some HIR expression, you can do
[Expr]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir/struct.Expr.html
Finally, you can use the HIR map to find the parents of nodes, via
-calls like [`tcx.hir().get_parent_node(n)`][get_parent_node].
+calls like [`tcx.hir().get_parent(n)`][get_parent].
-[get_parent_node]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/hir/map/struct.Map.html#method.get_parent_node
+[get_parent]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/hir/map/struct.Map.html#method.get_parent
## HIR Bodies
diff --git a/src/doc/rustc-dev-guide/src/identifiers.md b/src/doc/rustc-dev-guide/src/identifiers.md
index 18a3efefc..1b60b3b0b 100644
--- a/src/doc/rustc-dev-guide/src/identifiers.md
+++ b/src/doc/rustc-dev-guide/src/identifiers.md
@@ -1,4 +1,4 @@
-# Identifiers in the Compiler
+# Identifiers in the compiler
If you have read the few previous chapters, you now know that `rustc` uses
many different intermediate representations to perform different kinds of analyses.
diff --git a/src/doc/rustc-dev-guide/src/implementing_new_features.md b/src/doc/rustc-dev-guide/src/implementing_new_features.md
index 9147c1b41..9bd853080 100644
--- a/src/doc/rustc-dev-guide/src/implementing_new_features.md
+++ b/src/doc/rustc-dev-guide/src/implementing_new_features.md
@@ -33,7 +33,7 @@ like this; for example, the compiler team recommends
filing a Major Change Proposal ([MCP][mcp]) as a lightweight way to
garner support and feedback without requiring full consensus.
-[mcp]: compiler/mcp.md#public-facing-changes-require-rfcbot-fcp
+[mcp]: https://forge.rust-lang.org/compiler/mcp.html#public-facing-changes-require-rfcbot-fcp
You don't need to have the implementation fully ready for r+ to propose an FCP,
but it is generally a good idea to have at least a proof
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 b29b32a62..8cd765011 100644
--- a/src/doc/rustc-dev-guide/src/llvm-coverage-instrumentation.md
+++ b/src/doc/rustc-dev-guide/src/llvm-coverage-instrumentation.md
@@ -222,13 +222,9 @@ properly-configured variables in LLVM IR, according to very specific
details of the [_LLVM Coverage Mapping Format_][coverage-mapping-format]
(Version 6).[^llvm-and-covmap-versions]
-[^llvm-and-covmap-versions]: The Rust compiler (as of <!-- date-check --> December 2021)
-supports _LLVM Coverage Mapping Format_ Version 5 or 6. Version 5
-was introduced in _LLVM 12_,
-which is (as of <!-- date-check: December 2021--> this writing) the minimum LLVM
-version supported by the current version of Rust. Version 6 was introduced in
-_LLVM 13_, which is currently the default LLVM version for Rust. The Rust
-compiler will automatically use the most up-to-date coverage mapping format
+[^llvm-and-covmap-versions]:
+The Rust compiler (as of <!-- date-check: --> Feb 2023) supports _LLVM Coverage Mapping Format_ 6.
+The Rust compiler will automatically use the most up-to-date coverage mapping format
version that is compatible with the compiler's built-in version of LLVM.
```rust
@@ -301,11 +297,10 @@ $ ./x.py test tests/run-make-fulldeps/coverage --bless
```
[mir-opt-test]: https://github.com/rust-lang/rust/blob/master/tests/mir-opt/instrument_coverage.rs
-[coverage-test-samples]: https://github.com/rust-lang/rust/tree/master/tests/run-make-fulldeps/coverage
-[`coverage-reports`]: https://github.com/rust-lang/rust/tree/master/tests/run-make-fulldeps/coverage-reports
-[`coverage-spanview`]: https://github.com/rust-lang/rust/tree/master/tests/run-make-fulldeps/coverage-spanview
+[coverage-test-samples]: https://github.com/rust-lang/rust/tree/master/tests/run-make/coverage
+[`coverage-reports`]: https://github.com/rust-lang/rust/tree/master/tests/run-make/coverage-reports
[spanview-debugging]: compiler-debugging.md#viewing-spanview-output
-[`coverage-llvmir`]: https://github.com/rust-lang/rust/tree/master/tests/run-make-fulldeps/coverage-llvmir
+[`coverage-llvmir`]: https://github.com/rust-lang/rust/tree/master/tests/run-make/coverage-llvmir
## Implementation Details of the `InstrumentCoverage` MIR Pass
diff --git a/src/doc/rustc-dev-guide/src/mir/debugging.md b/src/doc/rustc-dev-guide/src/mir/debugging.md
index 3da17785b..4e1d68938 100644
--- a/src/doc/rustc-dev-guide/src/mir/debugging.md
+++ b/src/doc/rustc-dev-guide/src/mir/debugging.md
@@ -14,10 +14,10 @@ elements obscured by overlaps, and tooltips to view the MIR statements).
This flag takes an optional value: `statement` (the default), `terminator`, or
`block`, to generate span highlights with different levels of granularity.
-`-Z dump-mir=F` is a handy compiler options that will let you view the MIR for
+`-Z dump-mir=F` is a handy compiler option that will let you view the MIR for
each function at each stage of compilation. `-Z dump-mir` takes a **filter** `F`
which allows you to control which functions and which passes you are
-interesting in. For example:
+interested in. For example:
```bash
> rustc -Z dump-mir=foo ...
diff --git a/src/doc/rustc-dev-guide/src/mir/visitor.md b/src/doc/rustc-dev-guide/src/mir/visitor.md
index 505b700b3..17186fe75 100644
--- a/src/doc/rustc-dev-guide/src/mir/visitor.md
+++ b/src/doc/rustc-dev-guide/src/mir/visitor.md
@@ -37,10 +37,10 @@ code that will execute whenever a `foo` is found. If you want to
recursively walk the contents of the `foo`, you then invoke the
`super_foo` method. (NB. You never want to override `super_foo`.)
-A very simple example of a visitor can be found in [`LocalUseCounter`].
-By implementing `visit_local` method, this visitor counts how many times each local is used.
+A very simple example of a visitor can be found in [`LocalUseVisitor`].
+By implementing `visit_local` method, this visitor counts how many times each local is mutably used.
-[`LocalUseCounter`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir_transform/simplify_try/struct.LocalUseCounter.html
+[`LocalUseVisitor`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir_transform/const_debuginfo/struct.LocalUseVisitor.html
## Traversal
diff --git a/src/doc/rustc-dev-guide/src/overview.md b/src/doc/rustc-dev-guide/src/overview.md
index ca37f94b2..de06c742b 100644
--- a/src/doc/rustc-dev-guide/src/overview.md
+++ b/src/doc/rustc-dev-guide/src/overview.md
@@ -1,4 +1,4 @@
-# Overview of the Compiler
+# Overview of the compiler
<!-- toc -->
diff --git a/src/doc/rustc-dev-guide/src/profiling/with_perf.md b/src/doc/rustc-dev-guide/src/profiling/with_perf.md
index af30b4732..c9bd88ecd 100644
--- a/src/doc/rustc-dev-guide/src/profiling/with_perf.md
+++ b/src/doc/rustc-dev-guide/src/profiling/with_perf.md
@@ -90,14 +90,15 @@ You can also use that same command to use cachegrind or other profiling tools.
If you prefer to run things manually, that is also possible. You first
need to find the source for the test you want. Sources for the tests
-are found in [the `collector/benchmarks` directory][dir]. So let's go
-into the directory of a specific test; we'll use `clap-rs` as an
-example:
+are found in [the `collector/compile-benchmarks` directory][compile-time dir]
+and [the `collector/runtime-benchmarks` directory][runtime dir]. So let's
+go into the directory of a specific test; we'll use `clap-rs` as an example:
-[dir]: https://github.com/rust-lang/rustc-perf/tree/master/collector/benchmarks
+[compile-time dir]: https://github.com/rust-lang/rustc-perf/tree/master/collector/compile-benchmarks
+[runtime dir]: https://github.com/rust-lang/rustc-perf/tree/master/collector/runtime-benchmarks
```bash
-cd collector/benchmarks/clap-rs
+cd collector/compile-benchmarks/clap-3.1.6
```
In this case, let's say we want to profile the `cargo check`
diff --git a/src/doc/rustc-dev-guide/src/rustc-driver-getting-diagnostics.md b/src/doc/rustc-dev-guide/src/rustc-driver-getting-diagnostics.md
index bb19ad9d3..3c2102a50 100644
--- a/src/doc/rustc-dev-guide/src/rustc-driver-getting-diagnostics.md
+++ b/src/doc/rustc-dev-guide/src/rustc-driver-getting-diagnostics.md
@@ -7,34 +7,8 @@
To get diagnostics from the compiler,
configure `rustc_interface::Config` to output diagnostic to a buffer,
and run `TyCtxt.analysis`. The following was tested
-with <!-- date-check: Jan 2023 --> `nightly-2022-12-19` (See [here][example]
-for the complete example):
-
-[example]: https://github.com/rust-lang/rustc-dev-guide/blob/master/examples/rustc-driver-getting-diagnostics.rs
+with <!-- date-check: Feb 2023 --> `nightly-2023-02-13`:
```rust
-let buffer = sync::Arc::new(sync::Mutex::new(Vec::new()));
-let config = rustc_interface::Config {
- opts: config::Options {
- // Configure the compiler to emit diagnostics in compact JSON format.
- error_format: config::ErrorOutputType::Json {
- pretty: false,
- json_rendered: rustc_errors::emitter::HumanReadableErrorType::Default(
- rustc_errors::emitter::ColorConfig::Never,
- ),
- },
- /* other config */
- },
- /* other config */
-};
-rustc_interface::run_compiler(config, |compiler| {
- compiler.enter(|queries| {
- queries.global_ctxt().unwrap().take().enter(|tcx| {
- // Run the analysis phase on the local crate to trigger the type error.
- let _ = tcx.analysis(());
- });
- });
-});
-// Read buffered diagnostics.
-let diagnostics = String::from_utf8(buffer.lock().unwrap().clone()).unwrap();
+{{#include ../examples/rustc-driver-getting-diagnostics.rs}}
```
diff --git a/src/doc/rustc-dev-guide/src/rustc-driver-interacting-with-the-ast.md b/src/doc/rustc-dev-guide/src/rustc-driver-interacting-with-the-ast.md
index 5b495b4fe..d058a5838 100644
--- a/src/doc/rustc-dev-guide/src/rustc-driver-interacting-with-the-ast.md
+++ b/src/doc/rustc-dev-guide/src/rustc-driver-interacting-with-the-ast.md
@@ -5,45 +5,8 @@
## Getting the type of an expression
To get the type of an expression, use the `global_ctxt` to get a `TyCtxt`.
-The following was tested with <!-- date-check: Jan 2023 --> `nightly-2022-12-19`
-(see [here][example] for the complete example):
-
-[example]: https://github.com/rust-lang/rustc-dev-guide/blob/master/examples/rustc-driver-interacting-with-the-ast.rs
+The following was tested with <!-- date-check: Feb 2023 --> `nightly-2023-02-13`:
```rust
-let config = rustc_interface::Config {
- input: config::Input::Str {
- name: source_map::FileName::Custom("main.rs".to_string()),
- input: "fn main() { let message = \"Hello, world!\"; println!(\"{}\", message); }"
- .to_string(),
- },
- /* other config */
-};
-rustc_interface::run_compiler(config, |compiler| {
- compiler.enter(|queries| {
- // Analyze the crate and inspect the types under the cursor.
- queries.global_ctxt().unwrap().take().enter(|tcx| {
- // Every compilation contains a single crate.
- let hir_krate = tcx.hir();
- // Iterate over the top-level items in the crate, looking for the main function.
- for id in hir_krate.items() {
- let item = hir_krate.item(id);
- // Use pattern-matching to find a specific node inside the main function.
- if let rustc_hir::ItemKind::Fn(_, _, body_id) = item.kind {
- let expr = &tcx.hir().body(body_id).value;
- if let rustc_hir::ExprKind::Block(block, _) = expr.kind {
- if let rustc_hir::StmtKind::Local(local) = block.stmts[0].kind {
- if let Some(expr) = local.init {
- let hir_id = expr.hir_id; // hir_id identifies the string "Hello, world!"
- let def_id = tcx.hir().local_def_id(item.hir_id()); // def_id identifies the main function
- let ty = tcx.typeck(def_id).node_type(hir_id);
- println!("{:?}: {:?}", expr, ty);
- }
- }
- }
- }
- }
- })
- });
-});
+{{#include ../examples/rustc-driver-interacting-with-the-ast.rs}}
```
diff --git a/src/doc/rustc-dev-guide/src/rustc-driver.md b/src/doc/rustc-dev-guide/src/rustc-driver.md
index cef50111d..192811da1 100644
--- a/src/doc/rustc-dev-guide/src/rustc-driver.md
+++ b/src/doc/rustc-dev-guide/src/rustc-driver.md
@@ -1,4 +1,4 @@
-# The Rustc Driver and Interface
+# `rustc_driver` and `rustc_interface`
The [`rustc_driver`] is essentially `rustc`'s `main()` function. It acts as
the glue for running the various phases of the compiler in the correct order,
diff --git a/src/doc/rustc-dev-guide/src/solve/canonicalization.md b/src/doc/rustc-dev-guide/src/solve/canonicalization.md
new file mode 100644
index 000000000..a14be5216
--- /dev/null
+++ b/src/doc/rustc-dev-guide/src/solve/canonicalization.md
@@ -0,0 +1,84 @@
+# Canonicalization
+
+Canonicalization is the process of *isolating* a value from its context and is necessary
+for global caching of goals which include inference variables.
+
+The idea is that given the goals `u32: Trait<?x>` and `u32: Trait<?y>`, where `?x` and `?y`
+are two different currently unconstrained inference variables, we should get the same result
+for both goals. We can therefore prove *the canonical query* `exists<T> u32: Trait<T>` once
+and reuse the result.
+
+Let's first go over the way canonical queries work and then dive into the specifics of
+how canonicalization works.
+
+## A walkthrough of canonical queries
+
+To make this a bit easier, let's use the trait goal `u32: Trait<?x>` as an example with the
+assumption that the only relevant impl is `impl<T> Trait<Vec<T>> for u32`.
+
+### Canonicalizing the input
+
+We start by *canonicalizing* the goal, replacing inference variables with existential and
+placeholders with universal bound variables. This would result in the *canonical goal*
+`exists<T> u32: Trait<T>`.
+
+We remember the original values of all bound variables in the original context. Here this would
+map `T` back to `?x`. These original values are used later on when dealing with the query
+response.
+
+We now call the canonical query with the canonical goal.
+
+### Instantiating the canonical goal inside of the query
+
+To actually try to prove the canonical goal we start by instantiating the bound variables with
+inference variables and placeholders again.
+
+This happens inside of the query in a completely separate `InferCtxt`. Inside of the query we
+now have a goal `u32: Trait<?0>`. We also remember which value we've used to instantiate the bound
+variables in the canonical goal, which maps `T` to `?0`.
+
+We now compute the goal `u32: Trait<?0>` and figure out that this holds, but we've constrained
+`?0` to `Vec<?1>`. We finally convert this result to something useful to the caller.
+
+### Canonicalizing the query response
+
+We have to return to the caller both whether the goal holds, and the inference constraints
+from inside of the query.
+
+To return the inference results to the caller we canonicalize the mapping from bound variables
+to the instantiated values in the query. This means that the query response is `Certainty::Yes`
+and a mapping from `T` to `exists<U> Vec<U>`.
+
+### Instantiating the query response
+
+The caller now has to apply the constraints returned by the query. For this they first
+instantiate the bound variables of the canonical response with inference variables and
+placeholders again, so the mapping in the response is now from `T` to `Vec<?z>`.
+
+It now equates the original value of `T` (`?x`) with the value for `T` in the
+response (`Vec<?z>`), which correctly constrains `?x` to `Vec<?z>`.
+
+## `ExternalConstraints`
+
+Computing a trait goal may not only constrain inference variables, it can also add region
+obligations, e.g. given a goal `(): AOutlivesB<'a, 'b>` we would like to return the fact that
+`'a: 'b` has to hold.
+
+This is done by not only returning the mapping from bound variables to the instantiated values
+from the query but also extracting additional `ExternalConstraints` from the `InferCtxt` context
+while building the response.
+
+## How exactly does canonicalization work
+
+TODO: link to code once the PR lands and elaborate
+
+- types and consts: infer to existentially bound var, placeholder to universally bound var,
+ considering universes
+- generic parameters in the input get treated as placeholders in the root universe
+- all regions in the input get all mapped to existentially bound vars and we "uniquify" them.
+ `&'a (): Trait<'a>` gets canonicalized to `exists<'0, '1> &'0 (): Trait<'1>`. We do not care
+ about their universes and simply put all regions into the highest universe of the input.
+- once we collected all canonical vars we compress their universes, see comment in `finalize`.
+- in the output everything in a universe of the caller gets put into the root universe and only
+ gets its correct universe when we unify the var values with the orig values of the caller
+- we do not uniquify regions in the response and don't canonicalize `'static` \ No newline at end of file
diff --git a/src/doc/rustc-dev-guide/src/solve/coinduction.md b/src/doc/rustc-dev-guide/src/solve/coinduction.md
new file mode 100644
index 000000000..c682e002d
--- /dev/null
+++ b/src/doc/rustc-dev-guide/src/solve/coinduction.md
@@ -0,0 +1,250 @@
+# Coinduction
+
+The trait solver may use coinduction when proving goals.
+Coinduction is fairly subtle so we're giving it its own chapter.
+
+## Coinduction and induction
+
+With induction, we recursively apply proofs until we end up with a finite proof tree.
+Consider the example of `Vec<Vec<Vec<u32>>>: Debug` which results in the following tree.
+
+- `Vec<Vec<Vec<u32>>>: Debug`
+ - `Vec<Vec<u32>>: Debug`
+ - `Vec<u32>: Debug`
+ - `u32: Debug`
+
+This tree is finite. But not all goals we would want to hold have finite proof trees,
+consider the following example:
+
+```rust
+struct List<T> {
+ value: T,
+ next: Option<Box<List<T>>>,
+}
+```
+
+For `List<T>: Send` to hold all its fields have to recursively implement `Send` as well.
+This would result in the following proof tree:
+
+- `List<T>: Send`
+ - `T: Send`
+ - `Option<Box<List<T>>>: Send`
+ - `Box<List<T>>: Send`
+ - `List<T>: Send`
+ - `T: Send`
+ - `Option<Box<List<T>>>: Send`
+ - `Box<List<T>>: Send`
+ - ...
+
+This tree would be infinitely large which is exactly what coinduction is about.
+
+> To **inductively** prove a goal you need to provide a finite proof tree for it.
+> To **coinductively** prove a goal the provided proof tree may be infinite.
+
+## Why is coinduction correct
+
+When checking whether some trait goals holds, we're asking "does there exist an `impl`
+which satisfies this bound". Even if are infinite chains of nested goals, we still have a
+unique `impl` which should be used.
+
+## How to implement coinduction
+
+While our implementation can not check for coinduction by trying to construct an infinite
+tree as that would take infinite resources, it still makes sense to think of coinduction
+from this perspective.
+
+As we cannot check for infinite trees, we instead search for patterns for which we know that
+they would result in an infinite proof tree. The currently pattern we detect are (canonical)
+cycles. If `T: Send` relies on `T: Send` then it's pretty clear that this will just go on forever.
+
+With cycles we have to be careful with caching. Because of canonicalization of regions and
+inference variables encountering a cycle doesn't mean that we would get an infinite proof tree.
+Looking at the following example:
+```rust
+trait Foo {}
+struct Wrapper<T>(T);
+
+impl<T> Foo for Wrapper<Wrapper<T>>
+where
+ Wrapper<T>: Foo
+{}
+```
+Proving `Wrapper<?0>: Foo` uses the impl `impl<T> Foo for Wrapper<Wrapper<T>>` which constrains
+`?0` to `Wrapper<?1>` and then requires `Wrapper<?1>: Foo`. Due to canonicalization this would be
+detected as a cycle.
+
+The idea to solve is to return a *provisional result* whenever we detect a cycle and repeatedly
+retry goals until the *provisional result* is equal to the final result of that goal. We
+start out by using `Yes` with no constraints as the result and then update it to the result of
+the previous iteration whenever we have to rerun.
+
+TODO: elaborate here. We use the same approach as chalk for coinductive cycles.
+Note that the treatment for inductive cycles currently differs by simply returning `Overflow`.
+See [the relevant chapters][chalk] in the chalk book.
+
+[chalk]: https://rust-lang.github.io/chalk/book/recursive/inductive_cycles.html
+
+
+## Future work
+
+We currently only consider auto-traits, `Sized`, and `WF`-goals to be coinductive.
+In the future we pretty much intend for all goals to be coinductive.
+Lets first elaborate on why allowing more coinductive proofs is even desirable.
+
+### Recursive data types already rely on coinduction...
+
+...they just tend to avoid them in the trait solver.
+
+```rust
+enum List<T> {
+ Nil,
+ Succ(T, Box<List<T>>),
+}
+
+impl<T: Clone> Clone for List<T> {
+ fn clone(&self) -> Self {
+ match self {
+ List::Nil => List::Nil,
+ List::Succ(head, tail) => List::Succ(head.clone(), tail.clone()),
+ }
+ }
+}
+```
+
+We are using `tail.clone()` in this impl. For this we have to prove `Box<List<T>>: Clone`
+which requires `List<T>: Clone` but that relies on the impl which we are currently checking.
+By adding that requirement to the `where`-clauses of the impl, which is what we would
+do with [perfect derive], we move that cycle into the trait solver and [get an error][ex1].
+
+### Recursive data types
+
+We also need coinduction to reason about recursive types containing projections,
+e.g. the following currently fails to compile even though it should be valid.
+```rust
+use std::borrow::Cow;
+pub struct Foo<'a>(Cow<'a, [Foo<'a>]>);
+```
+This issue has been known since at least 2015, see
+[#23714](https://github.com/rust-lang/rust/issues/23714) if you want to know more.
+
+### Explicitly checked implied bounds
+
+When checking an impl, we assume that the types in the impl headers are well-formed.
+This means that when using instantiating the impl we have to prove that's actually the case.
+[#100051](https://github.com/rust-lang/rust/issues/100051) shows that this is not the case.
+To fix this, we have to add `WF` predicates for the types in impl headers.
+Without coinduction for all traits, this even breaks `core`.
+
+```rust
+trait FromResidual<R> {}
+trait Try: FromResidual<<Self as Try>::Residual> {
+ type Residual;
+}
+
+struct Ready<T>(T);
+impl<T> Try for Ready<T> {
+ type Residual = Ready<()>;
+}
+impl<T> FromResidual<<Ready<T> as Try>::Residual> for Ready<T> {}
+```
+
+When checking that the impl of `FromResidual` is well formed we get the following cycle:
+
+The impl is well formed if `<Ready<T> as Try>::Residual` and `Ready<T>` are well formed.
+- `wf(<Ready<T> as Try>::Residual)` requires
+- `Ready<T>: Try`, which requires because of the super trait
+- `Ready<T>: FromResidual<Ready<T> as Try>::Residual>`, **because of implied bounds on impl**
+- `wf(<Ready<T> as Try>::Residual)` :tada: **cycle**
+
+### Issues when extending coinduction to more goals
+
+There are some additional issues to keep in mind when extending coinduction.
+The issues here are not relevant for the current solver.
+
+#### Implied super trait bounds
+
+Our trait system currently treats super traits, e.g. `trait Trait: SuperTrait`,
+by 1) requiring that `SuperTrait` has to hold for all types which implement `Trait`,
+and 2) assuming `SuperTrait` holds if `Trait` holds.
+
+Relying on 2) while proving 1) is unsound. This can only be observed in case of
+coinductive cycles. Without cycles, whenever we rely on 2) we must have also
+proven 1) without relying on 2) for the used impl of `Trait`.
+
+```rust
+trait Trait: SuperTrait {}
+
+impl<T: Trait> Trait for T {}
+
+// Keeping the current setup for coinduction
+// would allow this compile. Uff :<
+fn sup<T: SuperTrait>() {}
+fn requires_trait<T: Trait>() { sup::<T>() }
+fn generic<T>() { requires_trait::<T>() }
+```
+This is not really fundamental to coinduction but rather an existing property
+which is made unsound because of it.
+
+##### Possible solutions
+
+The easiest way to solve this would be to completely remove 2) and always elaborate
+`T: Trait` to `T: Trait` and `T: SuperTrait` outside of the trait solver.
+This would allow us to also remove 1), but as we still have to prove ordinary
+`where`-bounds on traits, that's just additional work.
+
+While one could imagine ways to disable cyclic uses of 2) when checking 1),
+at least the ideas of myself - @lcnr - are all far to complex to be reasonable.
+
+#### `normalizes_to` goals and progress
+
+A `normalizes_to` goal represents the requirement that `<T as Trait>::Assoc` normalizes
+to some `U`. This is achieved by defacto first normalizing `<T as Trait>::Assoc` and then
+equating the resulting type with `U`. It should be a mapping as each projection should normalize
+to exactly one type. By simply allowing infinite proof trees, we would get the following behavior:
+
+```rust
+trait Trait {
+ type Assoc;
+}
+
+impl Trait for () {
+ type Assoc = <() as Trait>::Assoc;
+}
+```
+
+If we now compute `normalizes_to(<() as Trait>::Assoc, Vec<u32>)`, we would resolve the impl
+and get the associated type `<() as Trait>::Assoc`. We then equate that with the expected type,
+causing us to check `normalizes_to(<() as Trait>::Assoc, Vec<u32>)` again.
+This just goes on forever, resulting in an infinite proof tree.
+
+This means that `<() as Trait>::Assoc` would be equal to any other type which is unsound.
+
+##### How to solve this
+
+**WARNING: THIS IS SUBTLE AND MIGHT BE WRONG**
+
+Unlike trait goals, `normalizes_to` has to be *productive*[^1]. A `normalizes_to` goal
+is productive once the projection normalizes to a rigid type constructor,
+so `<() as Trait>::Assoc` normalizing to `Vec<<() as Trait>::Assoc>` would be productive.
+
+A `normalizes_to` goal has two kinds of nested goals. Nested requirements needed to actually
+normalize the projection, and the equality between the normalized projection and the
+expected type. Only the equality has to be productive. A branch in the proof tree is productive
+if it is either finite, or contains at least one `normalizes_to` where the alias is resolved
+to a rigid type constructor.
+
+Alternatively, we could simply always treat the equate branch of `normalizes_to` as inductive.
+Any cycles should result in infinite types, which aren't supported anyways and would only
+result in overflow when deeply normalizing for codegen.
+
+experimentation and examples: https://hackmd.io/-8p0AHnzSq2VAE6HE_wX-w?view
+
+Another attempt at a summary.
+- in projection eq, we must make progress with constraining the rhs
+- a cycle is only ok if while equating we have a rigid ty on the lhs after norm at least once
+- cycles outside of the recursive `eq` call of `normalizes_to` are always fine
+
+[^1]: related: https://coq.inria.fr/refman/language/core/coinductive.html#top-level-definitions-of-corecursive-functions
+
+[perfect derive]: https://smallcultfollowing.com/babysteps/blog/2022/04/12/implied-bounds-and-perfect-derive
+[ex1]: https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=0a9c3830b93a2380e6978d6328df8f72
diff --git a/src/doc/rustc-dev-guide/src/solve/the-solver.md b/src/doc/rustc-dev-guide/src/solve/the-solver.md
new file mode 100644
index 000000000..61e6cad1c
--- /dev/null
+++ b/src/doc/rustc-dev-guide/src/solve/the-solver.md
@@ -0,0 +1,17 @@
+# The solver
+
+Also consider reading the documentation for [the recursive solver in chalk][chalk]
+as it is very similar to this implementation and also talks about limitations of this
+approach.
+
+[chalk]: https://rust-lang.github.io/chalk/book/recursive.html
+
+The basic structure of the solver is a pure function
+`fn evaluate_goal(goal: Goal<'tcx>) -> Response`.
+While the actual solver is not fully pure to deal with overflow and cycles, we are
+going to defer that for now.
+
+To deal with inference variables and to improve caching, we use
+[canonicalization](./canonicalization.md).
+
+TODO: write the remaining code for this as well.
diff --git a/src/doc/rustc-dev-guide/src/solve/trait-solving.md b/src/doc/rustc-dev-guide/src/solve/trait-solving.md
new file mode 100644
index 000000000..71f6581c2
--- /dev/null
+++ b/src/doc/rustc-dev-guide/src/solve/trait-solving.md
@@ -0,0 +1,114 @@
+# Trait solving (new)
+
+This chapter describes how trait solving works with the new WIP solver located in
+[`rustc_trait_selection/solve`][solve]. Feel free to also look at the docs for
+[the current solver](../traits/resolution.md) and [the chalk solver](../traits/chalk.md)
+can be found separately.
+
+## Core concepts
+
+The goal of the trait system is to check whether a given trait bound is satisfied.
+Most notably when typechecking the body of - potentially generic - functions.
+For example:
+
+```rust
+fn uses_vec_clone<T: Clone>(x: Vec<T>) -> (Vec<T>, Vec<T>) {
+ (x.clone(), x)
+}
+```
+Here the call to `x.clone()` requires us to prove that `Vec<T>` implements `Clone` given
+the assumption that `T: Clone` is true. We can assume `T: Clone` as that will be proven by
+callers of this function.
+
+The concept of "prove the `Vec<T>: Clone` with the assumption `T: Clone`" is called a [`Goal`].
+Both `Vec<T>: Clone` and `T: Clone` are represented using [`Predicate`]. There are other
+predicates, most notably equality bounds on associated items: `<Vec<T> as IntoIterator>::Item == T`.
+See the `PredicateKind` enum for an exhaustive list. A `Goal` is represented as the `predicate` we
+have to prove and the `param_env` in which this predicate has to hold.
+
+We prove goals by checking whether each possible [`Candidate`] applies for the given goal by
+recursively proving its nested goals. For a list of possible candidates with examples, look at
+[`CandidateSource`]. The most important candidates are `Impl` candidates, i.e. trait implementations
+written by the user, and `ParamEnv` candidates, i.e. assumptions in our current environment.
+
+Looking at the above example, to prove `Vec<T>: Clone` we first use
+`impl<T: Clone> Clone for Vec<T>`. To use this impl we have to prove the nested
+goal that `T: Clone` holds. This can use the assumption `T: Clone` from the `ParamEnv`
+which does not have any nested goals. Therefore `Vec<T>: Clone` holds.
+
+The trait solver can either return success, ambiguity or an error as a [`CanonicalResponse`].
+For success and ambiguity it also returns constraints inference and region constraints.
+
+## Requirements
+
+Before we dive into the new solver lets first take the time to go through all of our requirements
+on the trait system. We can then use these to guide our design later on.
+
+TODO: elaborate on these rules and get more precise about their meaning.
+Also add issues where each of these rules have been broken in the past
+(or still are).
+
+### 1. The trait solver has to be *sound*
+
+This means that we must never return *success* for goals for which no `impl` exists. That would
+simply be unsound by assuming a trait is implemented even though it is not. When using predicates
+from the `where`-bounds, the `impl` will be proved by the user of the item.
+
+### 2. If type checker solves generic goal concrete instantiations of that goal have the same result
+
+Pretty much: If we successfully typecheck a generic function concrete instantiations
+of that function should also typeck. We should not get errors post-monomorphization.
+We can however get overflow as in the following snippet:
+
+```rust
+fn foo<T: Trait>(x: )
+```
+
+### 3. Trait goals in empty environments are proven by a unique impl
+
+If a trait goal holds with an empty environment, there is a unique `impl`,
+either user-defined or builtin, which is used to prove that goal.
+
+This is necessary for codegen to select a unique method.
+An exception here are *marker traits* which are allowed to overlap.
+
+### 4. Normalization in empty environments results in a unique type
+
+Normalization for alias types/consts has a unique result. Otherwise we can easily implement
+transmute in safe code. Given the following function, we have to make sure that the input and
+output types always get normalized to the same concrete type.
+```rust
+fn foo<T: Trait>(
+ x: <T as Trait>::Assoc
+) -> <T as Trait>::Assoc {
+ x
+}
+```
+
+### 5. During coherence trait solving has to be complete
+
+During coherence we never return *error* for goals which can be proven. This allows overlapping
+impls which would break rule 3.
+
+### 6. Trait solving must be (free) lifetime agnostic
+
+Trait solving during codegen should have the same result as during typeck. As we erase
+all free regions during codegen we must not rely on them during typeck. A noteworthy example
+is special behavior for `'static`.
+
+### 7. Removing ambiguity makes strictly more things compile
+
+We *should* not rely on ambiguity for things to compile.
+Not doing that will cause future improvements to be breaking changes.
+
+### 8. semantic equality implies structural equality
+
+Two types being equal in the type system must mean that they have the same `TypeId`.
+
+
+[solve]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_trait_selection/solve/index.html
+[`Goal`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_trait_selection/solve/struct.Goal.html
+[`Predicate`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.Predicate.html
+[`Candidate`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_trait_selection/solve/assembly/struct.Candidate.html
+[`CandidateSource`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_trait_selection/solve/assembly/enum.CandidateSource.html
+[`CanonicalResponse`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_trait_selection/solve/type.CanonicalResponse.html
diff --git a/src/doc/rustc-dev-guide/src/tests/compiletest.md b/src/doc/rustc-dev-guide/src/tests/compiletest.md
index 9f0c56dc4..5fc6ba809 100644
--- a/src/doc/rustc-dev-guide/src/tests/compiletest.md
+++ b/src/doc/rustc-dev-guide/src/tests/compiletest.md
@@ -24,6 +24,11 @@ See the [Adding new tests](adding.md) chapter for a tutorial on creating a new
test, and the [Running tests](running.md) chapter on how to run the test
suite.
+Compiletest itself tries to avoid running tests when the artifacts
+that are involved (mainly the compiler) haven't changed. You can use
+`x test --test-args --force-rerun` to rerun a test even when none of the
+inputs have changed.
+
## Test suites
All of the tests are in the [`tests`] directory.
diff --git a/src/doc/rustc-dev-guide/src/tests/running.md b/src/doc/rustc-dev-guide/src/tests/running.md
index 96c869109..0a3de6f8b 100644
--- a/src/doc/rustc-dev-guide/src/tests/running.md
+++ b/src/doc/rustc-dev-guide/src/tests/running.md
@@ -175,27 +175,6 @@ By passing `--pass $mode`, you can reduce the testing time. For each
mode, please see [Controlling pass/fail
expectations](ui.md#controlling-passfail-expectations).
-## Using incremental compilation
-
-You can further enable the `--incremental` flag to save additional
-time in subsequent rebuilds:
-
-```bash
-./x.py test tests/ui --incremental --test-args issue-1234
-```
-
-If you don't want to include the flag with every command, you can
-enable it in the `config.toml`:
-
-```toml
-[rust]
-incremental = true
-```
-
-Note that incremental compilation will use more disk space than usual.
-If disk space is a concern for you, you might want to check the size
-of the `build` directory from time to time.
-
## Running tests with different "compare modes"
UI tests may have different output depending on certain "modes" that
diff --git a/src/doc/rustc-dev-guide/src/traits/resolution.md b/src/doc/rustc-dev-guide/src/traits/resolution.md
index 9cf753b19..639ebbdec 100644
--- a/src/doc/rustc-dev-guide/src/traits/resolution.md
+++ b/src/doc/rustc-dev-guide/src/traits/resolution.md
@@ -163,7 +163,7 @@ impl<T: Get> Get for Box<T> {
}
```
-What happens when we invoke `get_it(&Box::new(1_u16))`, for example? In this
+What happens when we invoke `get(&Box::new(1_u16))`, for example? In this
case, the `Self` type is `Box<u16>` – that unifies with both impls,
because the first applies to all types `T`, and the second to all
`Box<T>`. In order for this to be unambiguous, the compiler does a *winnowing*
@@ -248,7 +248,7 @@ because we know that each resolution will resolve to a particular impl.
One interesting twist has to do with nested obligations. In general, in codegen,
we only to figure out which candidate applies, we do not care about nested obligations,
-as these are already assumed to be true. Nonetheless, we *do* currently do fulfill all of them.
+as these are already assumed to be true. Nonetheless, we *do* currently fulfill all of them.
That is because it can sometimes inform the results of type inference.
That is, we do not have the full substitutions in terms of the type variables
of the impl available to us, so we must run trait selection to figure
diff --git a/src/doc/rustc-dev-guide/src/ty.md b/src/doc/rustc-dev-guide/src/ty.md
index 90e17e85f..4a6cdb7c7 100644
--- a/src/doc/rustc-dev-guide/src/ty.md
+++ b/src/doc/rustc-dev-guide/src/ty.md
@@ -133,7 +133,7 @@ the `ty::Ty` to be a thin pointer-like
type. This allows us to do cheap comparisons for equality, along with the other
benefits of interning.
-[tykind]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/enum.TyKind.html
+[tykind]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_type_ir/sty/enum.TyKind.html
## Allocating and working with types
@@ -148,18 +148,62 @@ These methods all return a `Ty<'tcx>` – note that the lifetime you get back is
arena that this `tcx` has access to. Types are always canonicalized and interned (so we never
allocate exactly the same type twice).
-> N.B.
-> Because types are interned, it is possible to compare them for equality efficiently using `==`
-> – however, this is almost never what you want to do unless you happen to be hashing and looking
-> for duplicates. This is because often in Rust there are multiple ways to represent the same type,
-> particularly once inference is involved. If you are going to be testing for type equality, you
-> probably need to start looking into the inference code to do it right.
-
You can also find various common types in the `tcx` itself by accessing its fields:
`tcx.types.bool`, `tcx.types.char`, etc. (See [`CommonTypes`] for more.)
[`CommonTypes`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/context/struct.CommonTypes.html
+<!-- N.B: This section is linked from the type comparison internal lint. -->
+## Comparing types
+
+Because types are interned, it is possible to compare them for equality efficiently using `==`
+– however, this is almost never what you want to do unless you happen to be hashing and looking
+for duplicates. This is because often in Rust there are multiple ways to represent the same type,
+particularly once inference is involved.
+
+For example, the type `{integer}` (`ty::Infer(ty::IntVar(..))` an integer inference variable,
+the type of an integer literal like `0`) and `u8` (`ty::UInt(..)`) should often be treated as
+equal when testing whether they can be assigned to each other (which is a common operation in
+diagnostics code). `==` on them will return `false` though, since they are different types.
+
+The simplest way to compare two types correctly requires an inference context (`infcx`).
+If you have one, you can use `infcx.can_eq(param_env, ty1, ty2)`
+to check whether the types can be made equal.
+This is typically what you want to check during diagnostics, which is concerned with questions such
+as whether two types can be assigned to each other, not whether they're represented identically in
+the compiler's type-checking layer.
+
+When working with an inference context, you have to be careful to ensure that potential inference
+variables inside the types actually belong to that inference context. If you are in a function
+that has access to an inference context already, this should be the case. Specifically, this is the
+case during HIR type checking or MIR borrow checking.
+
+Another consideration is normalization. Two types may actually be the same, but one is behind an
+associated type. To compare them correctly, you have to normalize the types first. This is
+primarily a concern during HIR type checking and with all types from a `TyCtxt` query
+(for example from `tcx.type_of()`).
+
+When a `FnCtxt` or an `ObligationCtxt` is available during type checking, `.normalize(ty)`
+should be used on them to normalize the type. After type checking, diagnostics code can use
+`tcx.normalize_erasing_regions(ty)`.
+
+There are also cases where using `==` on `Ty` is fine. This is for example the case in late lints
+or after monomorphization, since type checking has been completed, meaning all inference variables
+are resolved and all regions have been erased. In these cases, if you know that inference variables
+or normalization won't be a concern, `#[allow]` or `#[expect]`ing the lint is recommended.
+
+When diagnostics code does not have access to an inference context, it should be threaded through
+the function calls if one is available in some place (like during type checking).
+
+If no inference context is available at all, then one can be created as described in
+[type-inference]. But this is only useful when the involved types (for example, if
+they came from a query like `tcx.type_of()`) are actually substituted with fresh
+inference variables using [`fresh_substs_for_item`]. This can be used to answer questions
+like "can `Vec<T>` for any `T` be unified with `Vec<u32>`?".
+
+[type-inference]: ./type-inference.md#creating-an-inference-context
+[`fresh_substs_for_item`]: https://doc.rust-lang.org/beta/nightly-rustc/rustc_infer/infer/struct.InferCtxt.html#method.fresh_substs_for_item
+
## `ty::TyKind` Variants
Note: `TyKind` is **NOT** the functional programming concept of *Kind*.
@@ -207,16 +251,16 @@ There are many variants on the `TyKind` enum, which you can see by looking at it
- [**And many more**...][kindvars]
[wikiadt]: https://en.wikipedia.org/wiki/Algebraic_data_type
-[kindadt]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/enum.TyKind.html#variant.Adt
-[kindforeign]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/enum.TyKind.html#variant.Foreign
-[kindstr]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/enum.TyKind.html#variant.Str
-[kindslice]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/enum.TyKind.html#variant.Slice
-[kindarray]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/enum.TyKind.html#variant.Array
-[kindrawptr]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/enum.TyKind.html#variant.RawPtr
-[kindref]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/enum.TyKind.html#variant.Ref
-[kindparam]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/enum.TyKind.html#variant.Param
-[kinderr]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/enum.TyKind.html#variant.Error
-[kindvars]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/enum.TyKind.html#variants
+[kindadt]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_type_ir/sty/enum.TyKind.html#variant.Adt
+[kindforeign]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_type_ir/sty/enum.TyKind.html#variant.Foreign
+[kindstr]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_type_ir/sty/enum.TyKind.html#variant.Str
+[kindslice]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_type_ir/sty/enum.TyKind.html#variant.Slice
+[kindarray]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_type_ir/sty/enum.TyKind.html#variant.Array
+[kindrawptr]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_type_ir/sty/enum.TyKind.html#variant.RawPtr
+[kindref]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_type_ir/sty/enum.TyKind.html#variant.Ref
+[kindparam]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_type_ir/sty/enum.TyKind.html#variant.Param
+[kinderr]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_type_ir/sty/enum.TyKind.html#variant.Error
+[kindvars]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_type_ir/sty/enum.TyKind.html#variants
## Import conventions
diff --git a/src/doc/rustc-dev-guide/src/type-checking.md b/src/doc/rustc-dev-guide/src/type-checking.md
index 08f15e30b..b60694201 100644
--- a/src/doc/rustc-dev-guide/src/type-checking.md
+++ b/src/doc/rustc-dev-guide/src/type-checking.md
@@ -1,10 +1,12 @@
# Type checking
-The [`rustc_typeck`][typeck] crate contains the source for "type collection"
-and "type checking", as well as a few other bits of related functionality. (It
-draws heavily on the [type inference] and [trait solving].)
+The [`hir_analysis`] crate contains the source for "type collection" as well
+as a bunch of related functionality.
+Checking the bodies of functions is implemented in the [`hir_typeck`] crate.
+These crates draw heavily on the [type inference] and [trait solving].
-[typeck]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir_analysis/index.html
+[`hir_analysis`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir_analysis/index.html
+[`hir_typeck`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir_typeck/index.html
[type inference]: ./type-inference.md
[trait solving]: ./traits/resolution.md
diff --git a/src/doc/rustc-dev-guide/src/type-inference.md b/src/doc/rustc-dev-guide/src/type-inference.md
index ca88c1686..2bafeb247 100644
--- a/src/doc/rustc-dev-guide/src/type-inference.md
+++ b/src/doc/rustc-dev-guide/src/type-inference.md
@@ -36,18 +36,16 @@ signature, such as the `'a` in `for<'a> fn(&'a u32)`. A region is
## Creating an inference context
-You create and "enter" an inference context by doing something like
+You create an inference context by doing something like
the following:
```rust,ignore
-tcx.infer_ctxt().enter(|infcx| {
- // Use the inference context `infcx` here.
-})
+let infcx = tcx.infer_ctxt().build();
+// Use the inference context `infcx` here.
```
-Within the closure,
-`infcx` has the type `InferCtxt<'a, 'tcx>` for some fresh `'a`,
-while `'tcx` is the same as outside the inference context.
+`infcx` has the type `InferCtxt<'tcx>`, the same `'tcx` lifetime as on
+the `tcx` it was built from.
The `tcx.infer_ctxt` method actually returns a builder, which means
there are some kinds of configuration you can do before the `infcx` is
diff --git a/src/doc/rustc/book.toml b/src/doc/rustc/book.toml
index 372350403..cea6033ed 100644
--- a/src/doc/rustc/book.toml
+++ b/src/doc/rustc/book.toml
@@ -5,3 +5,4 @@ title = "The rustc book"
[output.html]
git-repository-url = "https://github.com/rust-lang/rust/tree/master/src/doc/rustc"
+edit-url-template = "https://github.com/rust-lang/rust/edit/master/src/doc/rustc/{path}"
diff --git a/src/doc/rustc/src/codegen-options/index.md b/src/doc/rustc/src/codegen-options/index.md
index 7e355b7fc..c7f120daf 100644
--- a/src/doc/rustc/src/codegen-options/index.md
+++ b/src/doc/rustc/src/codegen-options/index.md
@@ -49,10 +49,10 @@ Guard](https://docs.microsoft.com/en-us/windows/win32/secbp/control-flow-guard)
platform security feature. This flag is currently ignored for non-Windows targets.
It takes one of the following values:
-* `y`, `yes`, `on`, `checks`, or no value: enable Control Flow Guard.
+* `y`, `yes`, `on`, `true`, `checks`, or no value: enable Control Flow Guard.
* `nochecks`: emit Control Flow Guard metadata without runtime enforcement checks (this
should only be used for testing purposes as it does not provide security enforcement).
-* `n`, `no`, `off`: do not enable Control Flow Guard (the default).
+* `n`, `no`, `off`, `false`: do not enable Control Flow Guard (the default).
## debug-assertions
@@ -60,8 +60,8 @@ This flag lets you turn `cfg(debug_assertions)` [conditional
compilation](../../reference/conditional-compilation.md#debug_assertions) on
or off. It takes one of the following values:
-* `y`, `yes`, `on`, or no value: enable debug-assertions.
-* `n`, `no`, or `off`: disable debug-assertions.
+* `y`, `yes`, `on`, `true`, or no value: enable debug-assertions.
+* `n`, `no`, `off` or `false`: disable debug-assertions.
If not specified, debug assertions are automatically enabled only if the
[opt-level](#opt-level) is 0.
@@ -82,8 +82,8 @@ Note: The [`-g` flag][option-g-debug] is an alias for `-C debuginfo=2`.
This flag controls whether or not the linker includes its default libraries.
It takes one of the following values:
-* `y`, `yes`, `on`, or no value: include default libraries (the default).
-* `n`, `no`, or `off`: exclude default libraries.
+* `y`, `yes`, `on`, `true` or no value: include default libraries (the default).
+* `n`, `no`, `off` or `false`: exclude default libraries.
For example, for gcc flavor linkers, this issues the `-nodefaultlibs` flag to
the linker.
@@ -93,8 +93,8 @@ the linker.
This flag controls whether or not the compiler embeds LLVM bitcode into object
files. It takes one of the following values:
-* `y`, `yes`, `on`, or no value: put bitcode in rlibs (the default).
-* `n`, `no`, or `off`: omit bitcode from rlibs.
+* `y`, `yes`, `on`, `true` or no value: put bitcode in rlibs (the default).
+* `n`, `no`, `off` or `false`: omit bitcode from rlibs.
LLVM bitcode is required when rustc is performing link-time optimization (LTO).
It is also required on some targets like iOS ones where vendors look for LLVM
@@ -135,8 +135,8 @@ flag][option-emit] for more information.
This flag forces the use of frame pointers. It takes one of the following
values:
-* `y`, `yes`, `on`, or no value: force-enable frame pointers.
-* `n`, `no`, or `off`: do not force-enable frame pointers. This does
+* `y`, `yes`, `on`, `true` or no value: force-enable frame pointers.
+* `n`, `no`, `off` or `false`: do not force-enable frame pointers. This does
not necessarily mean frame pointers will be removed.
The default behaviour, if frame pointers are not force-enabled, depends on the
@@ -147,8 +147,8 @@ target.
This flag forces the generation of unwind tables. It takes one of the following
values:
-* `y`, `yes`, `on`, or no value: Unwind tables are forced to be generated.
-* `n`, `no`, or `off`: Unwind tables are not forced to be generated. If unwind
+* `y`, `yes`, `on`, `true` or no value: Unwind tables are forced to be generated.
+* `n`, `no`, `off` or `false`: Unwind tables are not forced to be generated. If unwind
tables are required by the target an error will be emitted.
The default if not specified depends on the target.
@@ -202,8 +202,8 @@ options should be separated by spaces.
This flag controls whether the linker will keep dead code. It takes one of
the following values:
-* `y`, `yes`, `on`, or no value: keep dead code.
-* `n`, `no`, or `off`: remove dead code (the default).
+* `y`, `yes`, `on`, `true` or no value: keep dead code.
+* `n`, `no`, `off` or `false`: remove dead code (the default).
An example of when this flag might be useful is when trying to construct code coverage
metrics.
@@ -215,8 +215,8 @@ linker will use libraries and objects shipped with Rust instead or those in the
It takes one of the following values:
* no value: rustc will use heuristic to disable self-contained mode if system has necessary tools.
-* `y`, `yes`, `on`: use only libraries/objects shipped with Rust.
-* `n`, `no`, or `off`: rely on the user or the linker to provide non-Rust libraries/objects.
+* `y`, `yes`, `on`, `true`: use only libraries/objects shipped with Rust.
+* `n`, `no`, `off` or `false`: rely on the user or the linker to provide non-Rust libraries/objects.
This allows overriding cases when detection fails or user wants to use shipped libraries.
@@ -261,8 +261,8 @@ This flag defers LTO optimizations to the linker. See
[linker-plugin-LTO](../linker-plugin-lto.md) for more details. It takes one of
the following values:
-* `y`, `yes`, `on`, or no value: enable linker plugin LTO.
-* `n`, `no`, or `off`: disable linker plugin LTO (the default).
+* `y`, `yes`, `on`, `true` or no value: enable linker plugin LTO.
+* `n`, `no`, `off` or `false`: disable linker plugin LTO (the default).
* A path to the linker plugin.
More specifically this flag will cause the compiler to replace its typical
@@ -292,9 +292,9 @@ optimizations](https://llvm.org/docs/LinkTimeOptimization.html) to produce
better optimized code, using whole-program analysis, at the cost of longer
linking time. It takes one of the following values:
-* `y`, `yes`, `on`, `fat`, or no value: perform "fat" LTO which attempts to
+* `y`, `yes`, `on`, `true`, `fat`, or no value: perform "fat" LTO which attempts to
perform optimizations across all crates within the dependency graph.
-* `n`, `no`, `off`: disables LTO.
+* `n`, `no`, `off`, `false`: disables LTO.
* `thin`: perform ["thin"
LTO](http://blog.llvm.org/2016/06/thinlto-scalable-and-incremental-lto.html).
This is similar to "fat", but takes substantially less time to run while
@@ -333,8 +333,8 @@ This flag allows you to disable [the
red zone](https://en.wikipedia.org/wiki/Red_zone_\(computing\)). It takes one
of the following values:
-* `y`, `yes`, `on`, or no value: disable the red zone.
-* `n`, `no`, or `off`: enable the red zone.
+* `y`, `yes`, `on`, `true` or no value: disable the red zone.
+* `n`, `no`, `off` or `false`: enable the red zone.
The default behaviour, if the flag is not specified, depends on the target.
@@ -376,8 +376,8 @@ overflow](../../reference/expressions/operator-expr.md#overflow). When
overflow-checks are enabled, a panic will occur on overflow. This flag takes
one of the following values:
-* `y`, `yes`, `on`, or no value: enable overflow checks.
-* `n`, `no`, or `off`: disable overflow checks.
+* `y`, `yes`, `on`, `true` or no value: enable overflow checks.
+* `n`, `no`, `off` or `false`: disable overflow checks.
If not specified, overflow checks are enabled if
[debug-assertions](#debug-assertions) are enabled, disabled otherwise.
@@ -409,8 +409,8 @@ for determining whether or not it is possible to statically or dynamically
link with a dependency. For example, `cdylib` crate types may only use static
linkage. This flag takes one of the following values:
-* `y`, `yes`, `on`, or no value: use dynamic linking.
-* `n`, `no`, or `off`: use static linking (the default).
+* `y`, `yes`, `on`, `true` or no value: use dynamic linking.
+* `n`, `no`, `off` or `false`: use static linking (the default).
## profile-generate
@@ -487,24 +487,24 @@ The list of passes should be separated by spaces.
This flag controls whether [`rpath`](https://en.wikipedia.org/wiki/Rpath) is
enabled. It takes one of the following values:
-* `y`, `yes`, `on`, or no value: enable rpath.
-* `n`, `no`, or `off`: disable rpath (the default).
+* `y`, `yes`, `on`, `true` or no value: enable rpath.
+* `n`, `no`, `off` or `false`: disable rpath (the default).
## save-temps
This flag controls whether temporary files generated during compilation are
deleted once compilation finishes. It takes one of the following values:
-* `y`, `yes`, `on`, or no value: save temporary files.
-* `n`, `no`, or `off`: delete temporary files (the default).
+* `y`, `yes`, `on`, `true` or no value: save temporary files.
+* `n`, `no`, `off` or `false`: delete temporary files (the default).
## soft-float
This option controls whether `rustc` generates code that emulates floating
point instructions in software. It takes one of the following values:
-* `y`, `yes`, `on`, or no value: use soft floats.
-* `n`, `no`, or `off`: use hardware floats (the default).
+* `y`, `yes`, `on`, `true` or no value: use soft floats.
+* `n`, `no`, `off` or `false`: use hardware floats (the default).
## split-debuginfo
@@ -562,7 +562,7 @@ Supported values for this option are:
* `v0` — The "v0" mangling scheme. The specific format is not specified at
this time.
-The default if not specified will use a compiler-chosen default which may
+The default, if not specified, will use a compiler-chosen default which may
change in the future.
[name mangling]: https://en.wikipedia.org/wiki/Name_mangling
diff --git a/src/doc/rustc/src/json.md b/src/doc/rustc/src/json.md
index efbf861ea..d8843280b 100644
--- a/src/doc/rustc/src/json.md
+++ b/src/doc/rustc/src/json.md
@@ -223,7 +223,6 @@ flag][option-emit] documentation.
- "link": The generated crate as specified by the crate-type.
- "dep-info": The `.d` file with dependency information in a Makefile-like syntax.
- "metadata": The Rust `.rmeta` file containing metadata about the crate.
- - "save-analysis": A JSON file emitted by the `-Zsave-analysis` feature.
*/
"emit": "link"
}
diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md
index 160570482..9eafa27e2 100644
--- a/src/doc/rustc/src/platform-support.md
+++ b/src/doc/rustc/src/platform-support.md
@@ -13,6 +13,8 @@ for targets at each tier, see the [Target Tier Policy](target-tier-policy.md).
Targets are identified by their "target triple" which is the string to inform
the compiler what kind of output should be produced.
+Component availability is tracked [here](https://rust-lang.github.io/rustup-components-history/).
+
## Tier 1 with Host Tools
Tier 1 targets can be thought of as "guaranteed to work". The Rust project
@@ -216,7 +218,7 @@ target | std | host | notes
[`aarch64-kmc-solid_asp3`](platform-support/kmc-solid.md) | ✓ | | ARM64 SOLID with TOPPERS/ASP3
[`aarch64-nintendo-switch-freestanding`](platform-support/aarch64-nintendo-switch-freestanding.md) | * | | ARM64 Nintendo Switch, Horizon
[`aarch64-pc-windows-gnullvm`](platform-support/pc-windows-gnullvm.md) | ✓ | ✓ |
-[`aarch64-unknown-nto-qnx710`](platform-support/nto-qnx.md) | ? | | ARM64 QNX Neutrino 7.1 RTOS |
+[`aarch64-unknown-nto-qnx710`](platform-support/nto-qnx.md) | ✓ | | ARM64 QNX Neutrino 7.1 RTOS |
`aarch64-unknown-freebsd` | ✓ | ✓ | ARM64 FreeBSD
`aarch64-unknown-hermit` | ✓ | | ARM64 HermitCore
`aarch64-unknown-linux-gnu_ilp32` | ✓ | ✓ | ARM64 Linux (ILP32 ABI)
@@ -308,7 +310,7 @@ target | std | host | notes
`x86_64-apple-ios-macabi` | ✓ | | Apple Catalyst on x86_64
`x86_64-apple-tvos` | * | | x86 64-bit tvOS
[`x86_64-apple-watchos-sim`](platform-support/apple-watchos.md) | ✓ | | x86 64-bit Apple WatchOS simulator
-[`x86_64-pc-nto-qnx710`](platform-support/nto-qnx.md) | ? | | x86 64-bit QNX Neutrino 7.1 RTOS |
+[`x86_64-pc-nto-qnx710`](platform-support/nto-qnx.md) | ✓ | | x86 64-bit QNX Neutrino 7.1 RTOS |
[`x86_64-pc-windows-gnullvm`](platform-support/pc-windows-gnullvm.md) | ✓ | ✓ |
`x86_64-pc-windows-msvc` | * | | 64-bit Windows XP support
`x86_64-sun-solaris` | ? | | Deprecated target for 64-bit Solaris 10/11, illumos
diff --git a/src/doc/rustc/src/platform-support/fuchsia.md b/src/doc/rustc/src/platform-support/fuchsia.md
index 29e70129a..4d97b8c6c 100644
--- a/src/doc/rustc/src/platform-support/fuchsia.md
+++ b/src/doc/rustc/src/platform-support/fuchsia.md
@@ -12,7 +12,6 @@ The [Fuchsia team]:
- Tyler Mandry ([@tmandry](https://github.com/tmandry))
- Dan Johnson ([@computerdruid](https://github.com/computerdruid))
- David Koloski ([@djkoloski](https://github.com/djkoloski))
-- Andrew Pollack ([@andrewpollack](https://github.com/andrewpollack))
- Joseph Ryan ([@P1n3appl3](https://github.com/P1n3appl3))
As the team evolves over time, the specific members listed here may differ from
@@ -687,7 +686,9 @@ Rust compiler locally. See "[Targeting Fuchsia with a compiler built from source
for the steps to build locally.
You'll also need to download a copy of the Fuchsia SDK. The current minimum
-supported SDK version is [9.20220726.1.1](https://chrome-infra-packages.appspot.com/p/fuchsia/sdk/core/linux-amd64/+/version:9.20220726.1.1).
+supported SDK version is [10.20221207.2.89][minimum_supported_sdk_version].
+
+[minimum_supported_sdk_version]: https://chrome-infra-packages.appspot.com/p/fuchsia/sdk/core/linux-amd64/+/version:10.20221207.2.89
Fuchsia's test runner interacts with the Fuchsia emulator and is located at
`src/ci/docker/scripts/fuchsia-test-runner.py`. We can use it to start our
@@ -697,7 +698,7 @@ test environment with:
src/ci/docker/scripts/fuchsia-test-runner.py start
--rust ${RUST_SRC_PATH}/install
--sdk ${SDK_PATH}
- --target-arch {x64,arm64}
+ --target {x86_64-unknown-fuchsia|aarch64-unknown-fuchsia}
```
Where `${RUST_SRC_PATH}/install` is the `prefix` set in `config.toml` and
@@ -715,28 +716,30 @@ run the full `tests/ui` test suite:
--stage=2 \
test tests/ui \
--target x86_64-unknown-fuchsia \
- --run=always --jobs 1 \
- --test-args --target-rustcflags \
- --test-args -L \
- --test-args --target-rustcflags \
- --test-args ${SDK_PATH}/arch/{x64|arm64}/sysroot/lib \
+ --run=always \
--test-args --target-rustcflags \
- --test-args -L \
+ --test-args -Lnative=${SDK_PATH}/arch/{x64|arm64}/sysroot/lib \
--test-args --target-rustcflags \
- --test-args ${SDK_PATH}/arch/{x64|arm64}/lib \
+ --test-args -Lnative=${SDK_PATH}/arch/{x64|arm64}/lib \
--test-args --target-rustcflags \
- --test-args -Cpanic=abort \
- --test-args --target-rustcflags \
- --test-args -Zpanic_abort_tests \
+ --test-args -Clink-arg=--undefined-version \
--test-args --remote-test-client \
--test-args src/ci/docker/scripts/fuchsia-test-runner.py \
)
```
-*Note: The test suite cannot be run in parallel at the moment, so `x.py`
-must be run with `--jobs 1` to ensure only one test runs at a time.*
+By default, `x.py` compiles test binaries with `panic=unwind`. If you built your
+Rust toolchain with `-Cpanic=abort`, you need to tell `x.py` to compile test
+binaries with `panic=abort` as well:
-When finished, the test runner can be used to stop the test environment:
+```sh
+ --test-args --target-rustcflags \
+ --test-args -Cpanic=abort \
+ --test-args --target-rustcflags \
+ --test-args -Zpanic_abort_tests \
+```
+
+When finished testing, the test runner can be used to stop the test environment:
```sh
src/ci/docker/scripts/fuchsia-test-runner.py stop
@@ -764,8 +767,9 @@ ${SDK_PATH}/tools/${ARCH}/ffx debug connect -- \
* `--symbol-path` gets required symbol paths, which are
necessary for stepping through your program.
-The "[displaying source code in `zxdb`](#displaying-source-code-in-zxdb)" section describes how you can
-display Rust and/or Fuchsia source code in your debugging session.
+The "[displaying source code in `zxdb`](#displaying-source-code-in-zxdb)"
+section describes how you can display Rust and/or Fuchsia source code in your
+debugging session.
### Using `zxdb`
@@ -866,6 +870,64 @@ ${SDK_PATH}/tools/${ARCH}/ffx debug connect -- \
Linking to a Fuchsia checkout can help with debugging Fuchsia libraries,
such as [fdio].
+### Debugging the compiler test suite
+
+Debugging the compiler test suite requires some special configuration:
+
+First, we have to properly configure zxdb so it will be able to find debug
+symbols and source information for our test. The test runner can do this for us
+with:
+
+```sh
+src/ci/docker/scripts/fuchsia-test-runner.py debug \
+ --rust-src ${RUST_SRC_PATH} \
+ --fuchsia-src ${FUCHSIA_SRC_PATH} \
+ --test ${TEST}
+```
+
+where `${TEST}` is relative to Rust's `tests` directory (e.g. `ui/abi/...`).
+
+This will start a zxdb session that is properly configured for the specific test
+being run. All three arguments are optional, so you can omit `--fuchsia-src` if
+you don't have it downloaded. Now is a good time to set any desired breakpoints,
+like `b main`.
+
+Next, we have to tell `x.py` not to optimize or strip debug symbols from our
+test suite binaries. We can do this by passing some new arguments to `rustc`
+through our `x.py` invocation. The full invocation is:
+
+```sh
+( \
+ source config-env.sh && \
+ ./x.py \
+ --config config.toml \
+ --stage=2 \
+ test tests/${TEST} \
+ --target x86_64-unknown-fuchsia \
+ --run=always \
+ --test-args --target-rustcflags \
+ --test-args -Lnative=${SDK_PATH}/arch/{x64|arm64}/sysroot/lib \
+ --test-args --target-rustcflags \
+ --test-args -Lnative=${SDK_PATH}/arch/{x64|arm64}/lib \
+ --test-args --target-rustcflags \
+ --test-args -Clink-arg=--undefined-version \
+ --test-args --target-rustcflags \
+ --test-args -Cdebuginfo=2 \
+ --test-args --target-rustcflags \
+ --test-args -Copt-level=0 \
+ --test-args --target-rustcflags \
+ --test-args -Cstrip=none \
+ --test-args --remote-test-client \
+ --test-args src/ci/docker/scripts/fuchsia-test-runner.py \
+)
+```
+
+*If you built your Rust toolchain with `panic=abort`, make sure to include the
+previous flags so your test binaries are also compiled with `panic=abort`.*
+
+Upon running this command, the test suite binary will be run and zxdb will
+attach and load any relevant debug symbols.
+
[Fuchsia team]: https://team-api.infra.rust-lang.org/v1/teams/fuchsia.json
[Fuchsia]: https://fuchsia.dev/
[source tree]: https://fuchsia.dev/fuchsia-src/get-started/learn/build
diff --git a/src/doc/rustc/src/platform-support/nto-qnx.md b/src/doc/rustc/src/platform-support/nto-qnx.md
index 37d0c3197..38198fe6c 100644
--- a/src/doc/rustc/src/platform-support/nto-qnx.md
+++ b/src/doc/rustc/src/platform-support/nto-qnx.md
@@ -2,9 +2,9 @@
**Tier: 3**
-[BlackBerry® QNX®][BlackBerry] Neutrino (nto) Real-time operating system.
+[QNX®][BlackBerry] Neutrino (nto) Real-time operating system.
The support has been implemented jointly by [Elektrobit Automotive GmbH][Elektrobit]
-and [BlackBerry][BlackBerry].
+and [Blackberry QNX][BlackBerry].
[BlackBerry]: https://blackberry.qnx.com
[Elektrobit]: https://www.elektrobit.com
@@ -19,19 +19,24 @@ and [BlackBerry][BlackBerry].
Currently, only cross-compilation for QNX Neutrino on AArch64 and x86_64 are supported (little endian).
Adding other architectures that are supported by QNX Neutrino is possible.
-The standard library does not yet support QNX Neutrino. Therefore, only `no_std` code can
-be compiled.
+The standard library, including `core` and `alloc` (with default allocator) are supported.
-`core` and `alloc` (with default allocator) are supported.
+For building or using the Rust toolchain for QNX Neutrino, the
+[QNX Software Development Platform (SDP)](https://blackberry.qnx.com/en/products/foundation-software/qnx-software-development-platform)
+must be installed and initialized.
+Initialization is usually done by sourcing `qnxsdp-env.sh` (this will be installed as part of the SDP, see also installation instruction provided with the SDP).
+Afterwards [`qcc`](https://www.qnx.com/developers/docs/7.1/#com.qnx.doc.neutrino.utilities/topic/q/qcc.html) (QNX C/C++ compiler)
+should be available (in the `$PATH` variable).
+`qcc` will be called e.g. for linking executables.
-Applications must link against `libc.so` (see example). This is required because applications
-always link against the `crt` library and `crt` depends on `libc.so`.
-
-The correct version of `qcc` must be available by setting the `$PATH` variable (e.g. by sourcing `qnxsdp-env.sh` of the
-QNX Neutrino toolchain).
+When linking `no_std` applications, they must link against `libc.so` (see example). This is
+required because applications always link against the `crt` library and `crt` depends on `libc.so`.
+This is done automatically when using the standard library.
### Small example application
+Small `no_std` example is shown below. Applications using the standard library work as well.
+
```rust,ignore (platform-specific)
#![no_std]
#![no_main]
@@ -89,30 +94,150 @@ changelog-seen = 2
2. Compile the Rust toolchain for an `x86_64-unknown-linux-gnu` host (for both `aarch64` and `x86_64` targets)
-Run the following:
+Compiling the Rust toolchain requires the same environment variables used for compiling C binaries.
+Refer to the [QNX developer manual](https://www.qnx.com/developers/docs/7.1/#com.qnx.doc.neutrino.prog/topic/devel_OS_version.html).
+
+To compile for QNX Neutrino (aarch64 and x86_64) and Linux (x86_64):
```bash
-env \
- CC_aarch64-unknown-nto-qnx710="qcc" \
- CFLAGS_aarch64-unknown-nto-qnx710="-Vgcc_ntoaarch64le_cxx" \
- CXX_aarch64-unknown-nto-qnx710="qcc" \
- AR_aarch64_unknown_nto_qnx710="ntoaarch64-ar" \
- CC_x86_64-pc-nto-qnx710="qcc" \
- CFLAGS_x86_64-pc-nto-qnx710="-Vgcc_ntox86_64_cxx" \
- CXX_x86_64-pc-nto-qnx710="qcc" \
- AR_x86_64_pc_nto_qnx710="ntox86_64-ar" \
- ./x.py build --target aarch64-unknown-nto-qnx710 --target x86_64-pc-nto-qnx710 --target x86_64-unknown-linux-gnu rustc library/core library/alloc/
+export build_env='
+ CC_aarch64-unknown-nto-qnx710=qcc
+ CFLAGS_aarch64-unknown-nto-qnx710=-Vgcc_ntoaarch64le_cxx
+ CXX_aarch64-unknown-nto-qnx710=qcc
+ AR_aarch64_unknown_nto_qnx710=ntoaarch64-ar
+ CC_x86_64-pc-nto-qnx710=qcc
+ CFLAGS_x86_64-pc-nto-qnx710=-Vgcc_ntox86_64_cxx
+ CXX_x86_64-pc-nto-qnx710=qcc
+ AR_x86_64_pc_nto_qnx710=ntox86_64-ar'
+
+env $build_env \
+ ./x.py build \
+ --target aarch64-unknown-nto-qnx710 \
+ --target x86_64-pc-nto-qnx710 \
+ --target x86_64-unknown-linux-gnu \
+ rustc library/core library/alloc
```
+## Running the Rust test suite
+
+The test suites of the Rust compiler and standard library can be executed much like other Rust targets.
+The environment for testing should match the one used during compiler compilation (refer to `build_env` and `qcc`/`PATH` above) with the
+addition of the TEST_DEVICE_ADDR environment variable.
+The TEST_DEVICE_ADDR variable controls the remote runner and should point to the target, despite localhost being shown in the following example.
+Note that some tests are failing which is why they are currently excluded by the target maintainers which can be seen in the following example.
+
+To run all tests on a x86_64 QNX Neutrino target:
+
+```bash
+export TEST_DEVICE_ADDR="localhost:12345" # must address the test target, can be a SSH tunnel
+export build_env='
+ CC_aarch64-unknown-nto-qnx710=qcc
+ CFLAGS_aarch64-unknown-nto-qnx710=-Vgcc_ntoaarch64le_cxx
+ CXX_aarch64-unknown-nto-qnx710=qcc
+ AR_aarch64_unknown_nto_qnx710=ntoaarch64-ar
+ CC_x86_64-pc-nto-qnx710=qcc
+ CFLAGS_x86_64-pc-nto-qnx710=-Vgcc_ntox86_64_cxx
+ CXX_x86_64-pc-nto-qnx710=qcc
+ AR_x86_64_pc_nto_qnx710=ntox86_64-ar'
+
+# Disable tests that only work on the host or don't make sense for this target.
+# See also:
+# - src/ci/docker/host-x86_64/i686-gnu/Dockerfile
+# - https://rust-lang.zulipchat.com/#narrow/stream/182449-t-compiler.2Fhelp/topic/Running.20tests.20on.20remote.20target
+# - .github/workflows/ci.yml
+export exclude_tests='
+ --exclude src/bootstrap
+ --exclude src/tools/error_index_generator
+ --exclude src/tools/linkchecker
+ --exclude tests/ui-fulldeps
+ --exclude rustc
+ --exclude rustdoc
+ --exclude tests/run-make-fulldeps'
+
+env $build_env \
+ ./x.py test -j 1 \
+ $exclude_tests \
+ --stage 1 \
+ --target x86_64-pc-nto-qnx710
+```
+
+Currently, only one thread can be used when testing due to limitations in `libc::fork` and `libc::posix_spawnp`.
+See [fork documentation](https://www.qnx.com/developers/docs/7.1/#com.qnx.doc.neutrino.lib_ref/topic/f/fork.html)
+(error section) for more information.
+This can be achieved by using the `-j 1` parameter in the `x.py` call.
+This issue is being researched and we will try to allow parallelism in the future.
+
## Building Rust programs
-Rust does not yet ship pre-compiled artifacts for this target. To compile for this target, you must either build Rust with the target enabled (see "Building the target" above), or build your own copy of `core` by using
-`build-std` or similar.
+Rust does not yet ship pre-compiled artifacts for this target.
+To compile for this target, you must either build Rust with the target enabled (see "Building the target" above),
+or build your own copy of `core` by using `build-std` or similar.
## Testing
-Compiled executables can directly be run on QNX Neutrino.
+Compiled executables can run directly on QNX Neutrino.
+
+### Rust std library test suite
+
+The target needs sufficient resources to execute all tests. The commands below assume that a QEMU image
+is used.
+
+* Ensure that the temporary directory used by `remote-test-server` has enough free space and inodes.
+ 5GB of free space and 40000 inodes are known to be sufficient (the test will create more than 32k files).
+ To create a QEMU image in an empty directory, run this command inside the directory:
+
+ ```bash
+ mkqnximage --type=qemu --ssh-ident=$HOME/.ssh/id_ed25519.pub --data-size=5000 --data-inodes=40000
+ ```
+
+ `/data` should have enough free resources.
+ Set the `TMPDIR` environment variable accordingly when running `remote-test-server`, e.g.:
+ ```bash
+ TMPDIR=/data/tmp/rust remote-test-server --bind 0.0.0.0:12345
+ ```
+
+* Ensure the TCP stack can handle enough parallel connections (default is 200, should be 300 or higher).
+ After creating an image (see above), edit the file `output/build/startup.sh`:
+ 1. Search for `io-pkt-v6-hc`
+ 2. Add the parameter `-ptcpip threads_max=300`, e.g.:
+ ```text
+ io-pkt-v6-hc -U 33:33 -d e1000 -ptcpip threads_max=300
+ ```
+ 3. Update the image by running `mkqnximage` again with the same parameters as above for creating it.
+
+* Running and stopping the virtual machine
+
+ To start the virtual machine, run inside the directory of the VM:
+
+ ```bash
+ mkqnximage --run=-h
+ ```
+
+ To stop the virtual machine, run inside the directory of the VM:
+
+ ```bash
+ mkqnximage --stop
+ ```
+
+* Ensure local networking
+
+ Ensure that 'localhost' is getting resolved to 127.0.0.1. If you can't ping the localhost, some tests may fail.
+ Ensure it's appended to /etc/hosts (if first `ping` command fails).
+ Commands have to be executed inside the virtual machine!
+
+ ```bash
+ $ ping localhost
+ ping: Cannot resolve "localhost" (Host name lookup failure)
+
+ $ echo "127.0.0.1 localhost" >> /etc/hosts
+
+ $ ping localhost
+ PING localhost (127.0.0.1): 56 data bytes
+ 64 bytes from 127.0.0.1: icmp_seq=0 ttl=255 time=1 ms
+ ```
## Cross-compilation toolchains and C code
-Compiling C code requires the same environment variables to be set as compiling the Rust toolchain (see above), to ensure `qcc` is used with proper arguments. To ensure compatibility, do not specify any further arguments that for example change calling conventions or memory layout.
+Compiling C code requires the same environment variables to be set as compiling the Rust toolchain (see above),
+to ensure `qcc` is used with proper arguments.
+To ensure compatibility, do not specify any further arguments that for example change calling conventions or memory layout.
diff --git a/src/doc/rustdoc/src/how-to-read-rustdoc.md b/src/doc/rustdoc/src/how-to-read-rustdoc.md
index d666d54b3..28a004a92 100644
--- a/src/doc/rustdoc/src/how-to-read-rustdoc.md
+++ b/src/doc/rustdoc/src/how-to-read-rustdoc.md
@@ -84,6 +84,9 @@ When typing in the search bar, you can prefix your search term with a type
followed by a colon (such as `mod:`) to restrict the results to just that
kind of item. (The available items are listed in the help popup.)
+Searching for `println!` will search for a macro named `println`, just like
+searching for `macro:println` does.
+
### Changing displayed theme
You can change the displayed theme by opening the settings menu (the gear
diff --git a/src/doc/style-guide/src/cargo.md b/src/doc/style-guide/src/cargo.md
index f4993ba06..13b96ca8c 100644
--- a/src/doc/style-guide/src/cargo.md
+++ b/src/doc/style-guide/src/cargo.md
@@ -17,8 +17,7 @@ followed by the `description` at the end of that section.
Don't use quotes around any standard key names; use bare keys. Only use quoted
keys for non-standard keys whose names require them, and avoid introducing such
key names when possible. See the [TOML
-specification](https://github.com/toml-lang/toml/blob/master/versions/en/toml-v0.4.0.md#table)
-for details.
+specification](https://toml.io/en/v1.0.0#keys) for details.
Put a single space both before and after the `=` between a key and value. Do
not indent any key names; start all key names at the start of a line.
diff --git a/src/doc/style-guide/src/statements.md b/src/doc/style-guide/src/statements.md
index 29b48bb1e..4ab1c36f9 100644
--- a/src/doc/style-guide/src/statements.md
+++ b/src/doc/style-guide/src/statements.md
@@ -99,6 +99,84 @@ let Foo {
);
```
+#### else blocks (let-else statements)
+
+If a let statement contains an `else` component, also known as a let-else statement,
+then the `else` component should be formatted according to the same rules as the `else` block
+in [control flow expressions (i.e. if-else, and if-let-else expressions)](./expressions.md#control-flow-expressions).
+Apply the same formatting rules to the components preceding
+the `else` block (i.e. the `let pattern: Type = initializer_expr ...` portion)
+as described [above](#let-statements)
+
+Similarly to if-else expressions, if the initializer
+expression is multi-lined, then the `else` keyword and opening brace of the block (i.e. `else {`)
+should be put on the same line as the end of the initializer
+expression with a preceding space if all the following are true:
+
+* The initializer expression ends with one or more closing
+ parentheses, square brackets, and/or braces
+* There is nothing else on that line
+* That line is not indented beyond the indent of the first line containing the `let` keyword
+
+For example:
+
+```rust
+let Some(x) = y.foo(
+ "abc",
+ fairly_long_identifier,
+ "def",
+ "123456",
+ "string",
+ "cheese",
+) else {
+ bar()
+}
+```
+
+Otherwise, the `else` keyword and opening brace should be placed on the next line after the end of the initializer expression, and should not be indented (the `else` keyword should be aligned with the `let` keyword).
+
+For example:
+
+```rust
+let Some(x) = abcdef()
+ .foo(
+ "abc",
+ some_really_really_really_long_ident,
+ "ident",
+ "123456",
+ )
+ .bar()
+ .baz()
+ .qux("fffffffffffffffff")
+else {
+ foo_bar()
+}
+```
+
+##### Single line let-else statements
+
+The entire let-else statement may be formatted on a single line if all the following are true:
+
+* the entire statement is *short*
+* the `else` block contains a single-line expression and no statements
+* the `else` block contains no comments
+* the let statement components preceding the `else` block can be formatted on a single line
+
+```rust
+let Some(1) = opt else { return };
+
+let Some(1) = opt else {
+ return;
+};
+
+let Some(1) = opt else {
+ // nope
+ return
+};
+```
+
+Formatters may allow users to configure the value of the threshold
+used to determine whether a let-else statement is *short*.
### Macros in statement position
diff --git a/src/doc/unstable-book/src/compiler-flags/export-executable-symbols.md b/src/doc/unstable-book/src/compiler-flags/export-executable-symbols.md
new file mode 100644
index 000000000..c7f10afac
--- /dev/null
+++ b/src/doc/unstable-book/src/compiler-flags/export-executable-symbols.md
@@ -0,0 +1,43 @@
+# `export-executable-symbols`
+
+The tracking issue for this feature is: [#84161](https://github.com/rust-lang/rust/issues/84161).
+
+------------------------
+
+The `-Zexport-executable-symbols` compiler flag makes `rustc` export symbols from executables. The resulting binary is runnable, but can also be used as a dynamic library. This is useful for interoperating with programs written in other languages, in particular languages with a runtime like Java or Lua.
+
+For example on windows:
+```rust
+#[no_mangle]
+fn my_function() -> usize {
+ return 42;
+}
+
+fn main() {
+ println!("Hello, world!");
+}
+```
+
+A standard `cargo build` will produce a `.exe` without an export directory. When the `export-executable-symbols` flag is added
+
+```Bash
+export RUSTFLAGS="-Zexport-executable-symbols"
+cargo build
+```
+
+the binary has an export directory with the functions:
+
+```plain
+The Export Tables (interpreted .edata section contents)
+
+...
+
+[Ordinal/Name Pointer] Table
+ [ 0] my_function
+ [ 1] main
+```
+(the output of `objdump -x` on the binary)
+
+Please note that the `#[no_mangle]` attribute is required. Without it, the symbol is not exported.
+
+The equivalent of this flag in C and C++ compilers is the `__declspec(dllexport)` annotation or the `-rdynamic` linker flag.
diff --git a/src/doc/unstable-book/src/compiler-flags/instrument-xray.md b/src/doc/unstable-book/src/compiler-flags/instrument-xray.md
new file mode 100644
index 000000000..7fb33cd68
--- /dev/null
+++ b/src/doc/unstable-book/src/compiler-flags/instrument-xray.md
@@ -0,0 +1,39 @@
+# `instrument-xray`
+
+The tracking issue for this feature is: [#102921](https://github.com/rust-lang/rust/issues/102921).
+
+------------------------
+
+Enable generation of NOP sleds for XRay function tracing instrumentation.
+For more information on XRay,
+read [LLVM documentation](https://llvm.org/docs/XRay.html),
+and/or the [XRay whitepaper](http://research.google.com/pubs/pub45287.html).
+
+Set the `-Z instrument-xray` compiler flag in order to enable XRay instrumentation.
+
+ - `-Z instrument-xray` – use the default settings
+ - `-Z instrument-xray=skip-exit` – configure a custom setting
+ - `-Z instrument-xray=ignore-loops,instruction-threshold=300` –
+ multiple settings separated by commas
+
+Supported options:
+
+ - `always` – force instrumentation of all functions
+ - `never` – do no instrument any functions
+ - `ignore-loops` – ignore presence of loops,
+ instrument functions based only on instruction count
+ - `instruction-threshold=10` – set a different instruction threshold for instrumentation
+ - `skip-entry` – do no instrument function entry
+ - `skip-exit` – do no instrument function exit
+
+The default settings are:
+
+ - instrument both entry & exit from functions
+ - instrument functions with at least 200 instructions,
+ or containing a non-trivial loop
+
+Note that `-Z instrument-xray` only enables generation of NOP sleds
+which on their own don't do anything useful.
+In order to actually trace the functions,
+you will need to link a separate runtime library of your choice,
+such as Clang's [XRay Runtime Library](https://www.llvm.org/docs/XRay.html#xray-runtime-library).
diff --git a/src/doc/unstable-book/src/compiler-flags/sanitizer.md b/src/doc/unstable-book/src/compiler-flags/sanitizer.md
index 70c3a445b..262cef345 100644
--- a/src/doc/unstable-book/src/compiler-flags/sanitizer.md
+++ b/src/doc/unstable-book/src/compiler-flags/sanitizer.md
@@ -531,6 +531,24 @@ LLVM KCFI is supported on the following targets:
See the [Clang KernelControlFlowIntegrity documentation][clang-kcfi] for more
details.
+# KernelAddressSanitizer
+
+KernelAddressSanitizer (KASAN) is a freestanding version of AddressSanitizer
+which is suitable for detecting memory errors in programs which do not have a
+runtime environment, such as operating system kernels. KernelAddressSanitizer
+requires manual implementation of the underlying functions used for tracking
+KernelAddressSanitizer state.
+
+KernelAddressSanitizer is supported on the following targets:
+
+* `aarch64-unknown-none`
+* `riscv64gc-unknown-none-elf`
+* `riscv64imac-unknown-none-elf`
+* `x86_64-unknown-none`
+
+See the [Linux Kernel's KernelAddressSanitizer documentation][linux-kasan] for
+more details.
+
# LeakSanitizer
LeakSanitizer is run-time memory leak detector.
@@ -714,6 +732,7 @@ Sanitizers produce symbolized stacktraces when llvm-symbolizer binary is in `PAT
* [AddressSanitizer in Clang][clang-asan]
* [ControlFlowIntegrity in Clang][clang-cfi]
* [HWAddressSanitizer in Clang][clang-hwasan]
+* [Linux Kernel's KernelAddressSanitizer documentation][linux-kasan]
* [LeakSanitizer in Clang][clang-lsan]
* [MemorySanitizer in Clang][clang-msan]
* [MemTagSanitizer in LLVM][llvm-memtag]
@@ -727,4 +746,5 @@ Sanitizers produce symbolized stacktraces when llvm-symbolizer binary is in `PAT
[clang-msan]: https://clang.llvm.org/docs/MemorySanitizer.html
[clang-scs]: https://clang.llvm.org/docs/ShadowCallStack.html
[clang-tsan]: https://clang.llvm.org/docs/ThreadSanitizer.html
+[linux-kasan]: https://www.kernel.org/doc/html/latest/dev-tools/kasan.html
[llvm-memtag]: https://llvm.org/docs/MemTagSanitizer.html
diff --git a/src/doc/unstable-book/src/compiler-flags/tiny-const-eval-limit.md b/src/doc/unstable-book/src/compiler-flags/tiny-const-eval-limit.md
new file mode 100644
index 000000000..51c5fd69c
--- /dev/null
+++ b/src/doc/unstable-book/src/compiler-flags/tiny-const-eval-limit.md
@@ -0,0 +1,6 @@
+# `tiny-const-eval-limit`
+
+--------------------
+
+The `-Ztiny-const-eval-limit` compiler flag sets a tiny, non-configurable limit for const eval.
+This flag should only be used by const eval tests in the rustc test suite.
diff --git a/src/doc/unstable-book/src/library-features/char-error-internals.md b/src/doc/unstable-book/src/library-features/char-error-internals.md
deleted file mode 100644
index 8013b4988..000000000
--- a/src/doc/unstable-book/src/library-features/char-error-internals.md
+++ /dev/null
@@ -1,5 +0,0 @@
-# `char_error_internals`
-
-This feature is internal to the Rust compiler and is not intended for general use.
-
-------------------------
diff --git a/src/doc/unstable-book/src/library-features/int-error-internals.md b/src/doc/unstable-book/src/library-features/int-error-internals.md
deleted file mode 100644
index 402e4fa5e..000000000
--- a/src/doc/unstable-book/src/library-features/int-error-internals.md
+++ /dev/null
@@ -1,5 +0,0 @@
-# `int_error_internals`
-
-This feature is internal to the Rust compiler and is not intended for general use.
-
-------------------------
diff --git a/src/etc/pre-push.sh b/src/etc/pre-push.sh
index 7a846d44a..ff1793111 100755
--- a/src/etc/pre-push.sh
+++ b/src/etc/pre-push.sh
@@ -14,4 +14,4 @@ ROOT_DIR="$(git rev-parse --show-toplevel)"
echo "Running pre-push script $ROOT_DIR/x test tidy"
cd "$ROOT_DIR"
-./x test tidy
+CARGOFLAGS="--locked" ./x test tidy
diff --git a/src/etc/vscode_settings.json b/src/etc/vscode_settings.json
new file mode 100644
index 000000000..dd01bfaa7
--- /dev/null
+++ b/src/etc/vscode_settings.json
@@ -0,0 +1,28 @@
+{
+ "rust-analyzer.check.invocationLocation": "root",
+ "rust-analyzer.check.invocationStrategy": "once",
+ "rust-analyzer.check.overrideCommand": [
+ "python3",
+ "x.py",
+ "check",
+ "--json-output"
+ ],
+ "rust-analyzer.linkedProjects": ["src/bootstrap/Cargo.toml", "Cargo.toml"],
+ "rust-analyzer.rustfmt.overrideCommand": [
+ "./build/host/rustfmt/bin/rustfmt",
+ "--edition=2021"
+ ],
+ "rust-analyzer.procMacro.server": "./build/host/stage0/libexec/rust-analyzer-proc-macro-srv",
+ "rust-analyzer.procMacro.enable": true,
+ "rust-analyzer.cargo.buildScripts.enable": true,
+ "rust-analyzer.cargo.buildScripts.invocationLocation": "root",
+ "rust-analyzer.cargo.buildScripts.invocationStrategy": "once",
+ "rust-analyzer.cargo.buildScripts.overrideCommand": [
+ "python3",
+ "x.py",
+ "check",
+ "--json-output"
+ ],
+ "rust-analyzer.cargo.sysrootSrc": "./library",
+ "rust-analyzer.rustc.source": "./Cargo.toml"
+}
diff --git a/src/librustdoc/Cargo.toml b/src/librustdoc/Cargo.toml
index 0271c27b4..c48f7998c 100644
--- a/src/librustdoc/Cargo.toml
+++ b/src/librustdoc/Cargo.toml
@@ -12,14 +12,12 @@ askama = { version = "0.11", default-features = false, features = ["config"] }
itertools = "0.10.1"
minifier = "0.2.2"
once_cell = "1.10.0"
-pulldown-cmark = { version = "0.9.2", default-features = false }
regex = "1"
rustdoc-json-types = { path = "../rustdoc-json-types" }
serde_json = "1.0"
serde = { version = "1.0", features = ["derive"] }
smallvec = "1.8.1"
tempfile = "3"
-thin-vec = "0.2.9"
tracing = "0.1"
tracing-tree = "0.2.0"
diff --git a/src/librustdoc/clean/auto_trait.rs b/src/librustdoc/clean/auto_trait.rs
index a302750aa..9479b3ee0 100644
--- a/src/librustdoc/clean/auto_trait.rs
+++ b/src/librustdoc/clean/auto_trait.rs
@@ -137,7 +137,7 @@ where
pub(crate) fn get_auto_trait_impls(&mut self, item_def_id: DefId) -> Vec<Item> {
let tcx = self.cx.tcx;
let param_env = tcx.param_env(item_def_id);
- let ty = tcx.type_of(item_def_id);
+ let ty = tcx.type_of(item_def_id).subst_identity();
let f = auto_trait::AutoTraitFinder::new(tcx);
debug!("get_auto_trait_impls({:?})", ty);
@@ -734,8 +734,8 @@ struct RegionReplacer<'a, 'tcx> {
tcx: TyCtxt<'tcx>,
}
-impl<'a, 'tcx> TypeFolder<'tcx> for RegionReplacer<'a, 'tcx> {
- fn tcx<'b>(&'b self) -> TyCtxt<'tcx> {
+impl<'a, 'tcx> TypeFolder<TyCtxt<'tcx>> for RegionReplacer<'a, 'tcx> {
+ fn interner(&self) -> TyCtxt<'tcx> {
self.tcx
}
diff --git a/src/librustdoc/clean/blanket_impl.rs b/src/librustdoc/clean/blanket_impl.rs
index e6b2b2349..bcdbbcacc 100644
--- a/src/librustdoc/clean/blanket_impl.rs
+++ b/src/librustdoc/clean/blanket_impl.rs
@@ -15,7 +15,7 @@ impl<'a, 'tcx> BlanketImplFinder<'a, 'tcx> {
pub(crate) fn get_blanket_impls(&mut self, item_def_id: DefId) -> Vec<Item> {
let cx = &mut self.cx;
let param_env = cx.tcx.param_env(item_def_id);
- let ty = cx.tcx.bound_type_of(item_def_id);
+ let ty = cx.tcx.type_of(item_def_id);
trace!("get_blanket_impls({:?})", ty);
let mut impls = Vec::new();
diff --git a/src/librustdoc/clean/cfg.rs b/src/librustdoc/clean/cfg.rs
index f1853f369..dd58a5b51 100644
--- a/src/librustdoc/clean/cfg.rs
+++ b/src/librustdoc/clean/cfg.rs
@@ -164,10 +164,10 @@ impl Cfg {
/// Renders the configuration for human display, as a short HTML description.
pub(crate) fn render_short_html(&self) -> String {
let mut msg = Display(self, Format::ShortHtml).to_string();
- if self.should_capitalize_first_letter() {
- if let Some(i) = msg.find(|c: char| c.is_ascii_alphanumeric()) {
- msg[i..i + 1].make_ascii_uppercase();
- }
+ if self.should_capitalize_first_letter() &&
+ let Some(i) = msg.find(|c: char| c.is_ascii_alphanumeric())
+ {
+ msg[i..i + 1].make_ascii_uppercase();
}
msg
}
diff --git a/src/librustdoc/clean/cfg/tests.rs b/src/librustdoc/clean/cfg/tests.rs
index 81f676724..bb62660e1 100644
--- a/src/librustdoc/clean/cfg/tests.rs
+++ b/src/librustdoc/clean/cfg/tests.rs
@@ -4,6 +4,7 @@ use rustc_ast::{LitKind, MetaItemLit, Path, StrStyle};
use rustc_span::create_default_session_globals_then;
use rustc_span::symbol::{kw, Ident, Symbol};
use rustc_span::DUMMY_SP;
+use thin_vec::thin_vec;
fn word_cfg(s: &str) -> Cfg {
Cfg::Cfg(Symbol::intern(s), None)
@@ -34,7 +35,7 @@ macro_rules! dummy_meta_item_list {
($name:ident, [$($list:ident),* $(,)?]) => {
MetaItem {
path: Path::from_ident(Ident::from_str(stringify!($name))),
- kind: MetaItemKind::List(vec![
+ kind: MetaItemKind::List(thin_vec![
$(
NestedMetaItem::MetaItem(
dummy_meta_item_word(stringify!($list)),
@@ -48,7 +49,7 @@ macro_rules! dummy_meta_item_list {
($name:ident, [$($list:expr),* $(,)?]) => {
MetaItem {
path: Path::from_ident(Ident::from_str(stringify!($name))),
- kind: MetaItemKind::List(vec![
+ kind: MetaItemKind::List(thin_vec![
$(
NestedMetaItem::MetaItem($list),
)*
diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs
index b3b093312..148243683 100644
--- a/src/librustdoc/clean/inline.rs
+++ b/src/librustdoc/clean/inline.rs
@@ -9,7 +9,7 @@ use rustc_ast as ast;
use rustc_data_structures::fx::FxHashSet;
use rustc_hir as hir;
use rustc_hir::def::{DefKind, Res};
-use rustc_hir::def_id::{DefId, LocalDefId};
+use rustc_hir::def_id::{DefId, DefIdSet, LocalDefId};
use rustc_hir::Mutability;
use rustc_metadata::creader::{CStore, LoadedMacro};
use rustc_middle::ty::{self, TyCtxt};
@@ -45,7 +45,7 @@ pub(crate) fn try_inline(
res: Res,
name: Symbol,
attrs: Option<&[ast::Attribute]>,
- visited: &mut FxHashSet<DefId>,
+ visited: &mut DefIdSet,
) -> Option<Vec<clean::Item>> {
let did = res.opt_def_id()?;
if did.is_local() {
@@ -163,7 +163,7 @@ pub(crate) fn try_inline_glob(
cx: &mut DocContext<'_>,
res: Res,
current_mod: LocalDefId,
- visited: &mut FxHashSet<DefId>,
+ visited: &mut DefIdSet,
inlined_names: &mut FxHashSet<(ItemType, Symbol)>,
) -> Option<Vec<clean::Item>> {
let did = res.opt_def_id()?;
@@ -251,7 +251,7 @@ pub(crate) fn build_external_trait(cx: &mut DocContext<'_>, did: DefId) -> clean
}
fn build_external_function<'tcx>(cx: &mut DocContext<'tcx>, did: DefId) -> Box<clean::Function> {
- let sig = cx.tcx.fn_sig(did);
+ let sig = cx.tcx.fn_sig(did).subst_identity();
let late_bound_regions = sig.bound_vars().into_iter().filter_map(|var| match var {
ty::BoundVariableKind::Region(ty::BrNamed(_, name)) if name != kw::UnderscoreLifetime => {
@@ -303,7 +303,8 @@ fn build_union(cx: &mut DocContext<'_>, did: DefId) -> clean::Union {
fn build_type_alias(cx: &mut DocContext<'_>, did: DefId) -> Box<clean::Typedef> {
let predicates = cx.tcx.explicit_predicates_of(did);
- let type_ = clean_middle_ty(ty::Binder::dummy(cx.tcx.type_of(did)), cx, Some(did));
+ let type_ =
+ clean_middle_ty(ty::Binder::dummy(cx.tcx.type_of(did).subst_identity()), cx, Some(did));
Box::new(clean::Typedef {
type_,
@@ -390,18 +391,17 @@ pub(crate) fn build_impl(
// Only inline impl if the implemented trait is
// reachable in rustdoc generated documentation
- if !did.is_local() {
- if let Some(traitref) = associated_trait {
- let did = traitref.def_id;
- if !cx.cache.effective_visibilities.is_directly_public(tcx, did) {
- return;
- }
+ if !did.is_local() && let Some(traitref) = associated_trait {
+ let did = traitref.def_id;
+ if !cx.cache.effective_visibilities.is_directly_public(tcx, did) {
+ return;
+ }
- if let Some(stab) = tcx.lookup_stability(did) {
- if stab.is_unstable() && stab.feature == sym::rustc_private {
- return;
- }
- }
+ if let Some(stab) = tcx.lookup_stability(did) &&
+ stab.is_unstable() &&
+ stab.feature == sym::rustc_private
+ {
+ return;
}
}
@@ -415,7 +415,9 @@ pub(crate) fn build_impl(
let for_ = match &impl_item {
Some(impl_) => clean_ty(impl_.self_ty, cx),
- None => clean_middle_ty(ty::Binder::dummy(tcx.type_of(did)), cx, Some(did)),
+ None => {
+ clean_middle_ty(ty::Binder::dummy(tcx.type_of(did).subst_identity()), cx, Some(did))
+ }
};
// Only inline impl if the implementing type is
@@ -525,10 +527,8 @@ pub(crate) fn build_impl(
}
while let Some(ty) = stack.pop() {
- if let Some(did) = ty.def_id(&cx.cache) {
- if tcx.is_doc_hidden(did) {
- return;
- }
+ if let Some(did) = ty.def_id(&cx.cache) && tcx.is_doc_hidden(did) {
+ return;
}
if let Some(generics) = ty.generics() {
stack.extend(generics);
@@ -568,11 +568,7 @@ pub(crate) fn build_impl(
));
}
-fn build_module(
- cx: &mut DocContext<'_>,
- did: DefId,
- visited: &mut FxHashSet<DefId>,
-) -> clean::Module {
+fn build_module(cx: &mut DocContext<'_>, did: DefId, visited: &mut DefIdSet) -> clean::Module {
let items = build_module_items(cx, did, visited, &mut FxHashSet::default(), None);
let span = clean::Span::new(cx.tcx.def_span(did));
@@ -582,9 +578,9 @@ fn build_module(
fn build_module_items(
cx: &mut DocContext<'_>,
did: DefId,
- visited: &mut FxHashSet<DefId>,
+ visited: &mut DefIdSet,
inlined_names: &mut FxHashSet<(ItemType, Symbol)>,
- allowed_def_ids: Option<&FxHashSet<DefId>>,
+ allowed_def_ids: Option<&DefIdSet>,
) -> Vec<clean::Item> {
let mut items = Vec::new();
@@ -659,14 +655,22 @@ pub(crate) fn print_inlined_const(tcx: TyCtxt<'_>, did: DefId) -> String {
fn build_const(cx: &mut DocContext<'_>, def_id: DefId) -> clean::Constant {
clean::Constant {
- type_: clean_middle_ty(ty::Binder::dummy(cx.tcx.type_of(def_id)), cx, Some(def_id)),
+ type_: clean_middle_ty(
+ ty::Binder::dummy(cx.tcx.type_of(def_id).subst_identity()),
+ cx,
+ Some(def_id),
+ ),
kind: clean::ConstantKind::Extern { def_id },
}
}
fn build_static(cx: &mut DocContext<'_>, did: DefId, mutable: bool) -> clean::Static {
clean::Static {
- type_: clean_middle_ty(ty::Binder::dummy(cx.tcx.type_of(did)), cx, Some(did)),
+ type_: clean_middle_ty(
+ ty::Binder::dummy(cx.tcx.type_of(did).subst_identity()),
+ cx,
+ Some(did),
+ ),
mutability: if mutable { Mutability::Mut } else { Mutability::Not },
expr: None,
}
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index 0f0e16265..3edc2cd2e 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -11,18 +11,20 @@ pub(crate) mod types;
pub(crate) mod utils;
use rustc_ast as ast;
+use rustc_ast::token::{Token, TokenKind};
+use rustc_ast::tokenstream::{TokenStream, TokenTree};
use rustc_attr as attr;
use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap, FxIndexSet, IndexEntry};
use rustc_hir as hir;
use rustc_hir::def::{CtorKind, DefKind, Res};
-use rustc_hir::def_id::{DefId, LOCAL_CRATE};
+use rustc_hir::def_id::{DefId, DefIdMap, DefIdSet, LocalDefId, LOCAL_CRATE};
use rustc_hir::PredicateOrigin;
use rustc_hir_analysis::hir_ty_to_ty;
use rustc_infer::infer::region_constraints::{Constraint, RegionConstraintData};
-use rustc_middle::middle::resolve_lifetime as rl;
+use rustc_middle::middle::resolve_bound_vars as rbv;
use rustc_middle::ty::fold::TypeFolder;
use rustc_middle::ty::InternalSubsts;
-use rustc_middle::ty::TypeVisitable;
+use rustc_middle::ty::TypeVisitableExt;
use rustc_middle::ty::{self, AdtKind, DefIdTree, EarlyBinder, Ty, TyCtxt};
use rustc_middle::{bug, span_bug};
use rustc_span::hygiene::{AstPass, MacroKind};
@@ -37,6 +39,7 @@ use std::hash::Hash;
use std::mem;
use thin_vec::ThinVec;
+use crate::clean::inline::merge_attrs;
use crate::core::{self, DocContext, ImplTraitParam};
use crate::formats::item_type::ItemType;
use crate::visit_ast::Module as DocModule;
@@ -75,7 +78,7 @@ pub(crate) fn clean_doc_module<'tcx>(doc: &DocModule<'tcx>, cx: &mut DocContext<
// This covers the case where somebody does an import which should pull in an item,
// but there's already an item with the same namespace and same name. Rust gives
// priority to the not-imported one, so we should, too.
- items.extend(doc.items.iter().flat_map(|(item, renamed, import_id)| {
+ items.extend(doc.items.values().flat_map(|(item, renamed, import_id)| {
// First, lower everything other than imports.
if matches!(item.kind, hir::ItemKind::Use(_, hir::UseKind::Glob)) {
return Vec::new();
@@ -88,7 +91,7 @@ pub(crate) fn clean_doc_module<'tcx>(doc: &DocModule<'tcx>, cx: &mut DocContext<
}
v
}));
- items.extend(doc.items.iter().flat_map(|(item, renamed, _)| {
+ items.extend(doc.items.values().flat_map(|(item, renamed, _)| {
// Now we actually lower the imports, skipping everything else.
if let hir::ItemKind::Use(path, hir::UseKind::Glob) = item.kind {
let name = renamed.unwrap_or_else(|| cx.tcx.hir().name(item.hir_id()));
@@ -116,7 +119,8 @@ pub(crate) fn clean_doc_module<'tcx>(doc: &DocModule<'tcx>, cx: &mut DocContext<
}
});
- Item::from_hir_id_and_parts(doc.id, Some(doc.name), ModuleItem(Module { items, span }), cx)
+ let kind = ModuleItem(Module { items, span });
+ Item::from_def_id_and_parts(doc.def_id.to_def_id(), Some(doc.name), kind, cx)
}
fn clean_generic_bound<'tcx>(
@@ -197,11 +201,11 @@ fn clean_poly_trait_ref_with_bindings<'tcx>(
}
fn clean_lifetime<'tcx>(lifetime: &hir::Lifetime, cx: &mut DocContext<'tcx>) -> Lifetime {
- let def = cx.tcx.named_region(lifetime.hir_id);
+ let def = cx.tcx.named_bound_var(lifetime.hir_id);
if let Some(
- rl::Region::EarlyBound(node_id)
- | rl::Region::LateBound(_, _, node_id)
- | rl::Region::Free(_, node_id),
+ rbv::ResolvedArg::EarlyBound(node_id)
+ | rbv::ResolvedArg::LateBound(_, _, node_id)
+ | rbv::ResolvedArg::Free(_, node_id),
) = def
{
if let Some(lt) = cx.substs.get(&node_id).and_then(|p| p.as_lt()).cloned() {
@@ -214,7 +218,11 @@ fn clean_lifetime<'tcx>(lifetime: &hir::Lifetime, cx: &mut DocContext<'tcx>) ->
pub(crate) fn clean_const<'tcx>(constant: &hir::ConstArg, cx: &mut DocContext<'tcx>) -> Constant {
let def_id = cx.tcx.hir().body_owner_def_id(constant.value.body).to_def_id();
Constant {
- type_: clean_middle_ty(ty::Binder::dummy(cx.tcx.type_of(def_id)), cx, Some(def_id)),
+ type_: clean_middle_ty(
+ ty::Binder::dummy(cx.tcx.type_of(def_id).subst_identity()),
+ cx,
+ Some(def_id),
+ ),
kind: ConstantKind::Anonymous { body: constant.value.body },
}
}
@@ -241,6 +249,7 @@ pub(crate) fn clean_middle_region<'tcx>(region: ty::Region<'tcx>) -> Option<Life
ty::ReLateBound(..)
| ty::ReFree(..)
| ty::ReVar(..)
+ | ty::ReError(_)
| ty::RePlaceholder(..)
| ty::ReErased => {
debug!("cannot clean region {:?}", region);
@@ -309,10 +318,13 @@ pub(crate) fn clean_predicate<'tcx>(
ty::PredicateKind::Clause(ty::Clause::Projection(pred)) => {
Some(clean_projection_predicate(bound_predicate.rebind(pred), cx))
}
+ // FIXME(generic_const_exprs): should this do something?
ty::PredicateKind::ConstEvaluatable(..) => None,
ty::PredicateKind::WellFormed(..) => None,
+ ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(..)) => None,
ty::PredicateKind::Subtype(..)
+ | ty::PredicateKind::AliasEq(..)
| ty::PredicateKind::Coerce(..)
| ty::PredicateKind::ObjectSafe(..)
| ty::PredicateKind::ClosureKind(..)
@@ -382,13 +394,10 @@ fn clean_middle_term<'tcx>(
fn clean_hir_term<'tcx>(term: &hir::Term<'tcx>, cx: &mut DocContext<'tcx>) -> Term {
match term {
hir::Term::Ty(ty) => Term::Type(clean_ty(ty, cx)),
- hir::Term::Const(c) => {
- let def_id = cx.tcx.hir().local_def_id(c.hir_id);
- Term::Constant(clean_middle_const(
- ty::Binder::dummy(ty::Const::from_anon_const(cx.tcx, def_id)),
- cx,
- ))
- }
+ hir::Term::Const(c) => Term::Constant(clean_middle_const(
+ ty::Binder::dummy(ty::Const::from_anon_const(cx.tcx, c.def_id)),
+ cx,
+ )),
}
}
@@ -479,7 +488,7 @@ fn clean_generic_param_def<'tcx>(
ty::GenericParamDefKind::Type { has_default, synthetic, .. } => {
let default = if has_default {
Some(clean_middle_ty(
- ty::Binder::dummy(cx.tcx.type_of(def.def_id)),
+ ty::Binder::dummy(cx.tcx.type_of(def.def_id).subst_identity()),
cx,
Some(def.def_id),
))
@@ -501,7 +510,12 @@ fn clean_generic_param_def<'tcx>(
GenericParamDefKind::Const {
did: def.def_id,
ty: Box::new(clean_middle_ty(
- ty::Binder::dummy(cx.tcx.type_of(def.def_id)),
+ ty::Binder::dummy(
+ cx.tcx
+ .type_of(def.def_id)
+ .no_bound_vars()
+ .expect("const parameter types cannot be generic"),
+ ),
cx,
Some(def.def_id),
)),
@@ -523,12 +537,11 @@ fn clean_generic_param<'tcx>(
generics: Option<&hir::Generics<'tcx>>,
param: &hir::GenericParam<'tcx>,
) -> GenericParamDef {
- let did = cx.tcx.hir().local_def_id(param.hir_id);
let (name, kind) = match param.kind {
hir::GenericParamKind::Lifetime { .. } => {
let outlives = if let Some(generics) = generics {
generics
- .outlives_for_param(did)
+ .outlives_for_param(param.def_id)
.filter(|bp| !bp.in_where_clause)
.flat_map(|bp| bp.bounds)
.map(|bound| match bound {
@@ -544,7 +557,7 @@ fn clean_generic_param<'tcx>(
hir::GenericParamKind::Type { ref default, synthetic } => {
let bounds = if let Some(generics) = generics {
generics
- .bounds_for_param(did)
+ .bounds_for_param(param.def_id)
.filter(|bp| bp.origin != PredicateOrigin::WhereClause)
.flat_map(|bp| bp.bounds)
.filter_map(|x| clean_generic_bound(x, cx))
@@ -555,7 +568,7 @@ fn clean_generic_param<'tcx>(
(
param.name.ident().name,
GenericParamDefKind::Type {
- did: did.to_def_id(),
+ did: param.def_id.to_def_id(),
bounds,
default: default.map(|t| clean_ty(t, cx)).map(Box::new),
synthetic,
@@ -565,12 +578,10 @@ fn clean_generic_param<'tcx>(
hir::GenericParamKind::Const { ty, default } => (
param.name.ident().name,
GenericParamDefKind::Const {
- did: did.to_def_id(),
+ did: param.def_id.to_def_id(),
ty: Box::new(clean_ty(ty, cx)),
- default: default.map(|ct| {
- let def_id = cx.tcx.hir().local_def_id(ct.hir_id);
- Box::new(ty::Const::from_anon_const(cx.tcx, def_id).to_string())
- }),
+ default: default
+ .map(|ct| Box::new(ty::Const::from_anon_const(cx.tcx, ct.def_id).to_string())),
},
),
};
@@ -789,43 +800,43 @@ fn clean_ty_generics<'tcx>(
None
})();
- if let Some(param_idx) = param_idx {
- if let Some(b) = impl_trait.get_mut(&param_idx.into()) {
- let p: WherePredicate = clean_predicate(*p, cx)?;
+ if let Some(param_idx) = param_idx
+ && let Some(b) = impl_trait.get_mut(&param_idx.into())
+ {
+ let p: WherePredicate = clean_predicate(*p, cx)?;
+
+ b.extend(
+ p.get_bounds()
+ .into_iter()
+ .flatten()
+ .cloned()
+ .filter(|b| !b.is_sized_bound(cx)),
+ );
- b.extend(
- p.get_bounds()
+ let proj = projection.map(|p| {
+ (
+ clean_projection(p.map_bound(|p| p.projection_ty), cx, None),
+ p.map_bound(|p| p.term),
+ )
+ });
+ if let Some(((_, trait_did, name), rhs)) = proj
+ .as_ref()
+ .and_then(|(lhs, rhs): &(Type, _)| Some((lhs.projection()?, rhs)))
+ {
+ // FIXME(...): Remove this unwrap()
+ impl_trait_proj.entry(param_idx).or_default().push((
+ trait_did,
+ name,
+ rhs.map_bound(|rhs| rhs.ty().unwrap()),
+ p.get_bound_params()
.into_iter()
.flatten()
- .cloned()
- .filter(|b| !b.is_sized_bound(cx)),
- );
-
- let proj = projection.map(|p| {
- (
- clean_projection(p.map_bound(|p| p.projection_ty), cx, None),
- p.map_bound(|p| p.term),
- )
- });
- if let Some(((_, trait_did, name), rhs)) = proj
- .as_ref()
- .and_then(|(lhs, rhs): &(Type, _)| Some((lhs.projection()?, rhs)))
- {
- // FIXME(...): Remove this unwrap()
- impl_trait_proj.entry(param_idx).or_default().push((
- trait_did,
- name,
- rhs.map_bound(|rhs| rhs.ty().unwrap()),
- p.get_bound_params()
- .into_iter()
- .flatten()
- .map(|param| GenericParamDef::lifetime(param.0))
- .collect(),
- ));
- }
-
- return None;
+ .map(|param| GenericParamDef::lifetime(param.0))
+ .collect(),
+ ));
}
+
+ return None;
}
Some(p)
@@ -888,7 +899,7 @@ fn clean_ty_generics<'tcx>(
// `?Sized` bound for each one we didn't find to be `Sized`.
for tp in &stripped_params {
if let types::GenericParamDefKind::Type { .. } = tp.kind
- && !sized_params.contains(&tp.name)
+ && !sized_params.contains(&tp.name)
{
where_predicates.push(WherePredicate::BoundPredicate {
ty: Type::Generic(tp.name),
@@ -1214,7 +1225,7 @@ pub(crate) fn clean_middle_assoc_item<'tcx>(
let kind = match assoc_item.kind {
ty::AssocKind::Const => {
let ty = clean_middle_ty(
- ty::Binder::dummy(tcx.type_of(assoc_item.def_id)),
+ ty::Binder::dummy(tcx.type_of(assoc_item.def_id).subst_identity()),
cx,
Some(assoc_item.def_id),
);
@@ -1230,7 +1241,7 @@ pub(crate) fn clean_middle_assoc_item<'tcx>(
}
}
ty::AssocKind::Fn => {
- let sig = tcx.fn_sig(assoc_item.def_id);
+ let sig = tcx.fn_sig(assoc_item.def_id).subst_identity();
let late_bound_regions = sig.bound_vars().into_iter().filter_map(|var| match var {
ty::BoundVariableKind::Region(ty::BrNamed(_, name))
@@ -1253,7 +1264,7 @@ pub(crate) fn clean_middle_assoc_item<'tcx>(
if assoc_item.fn_has_self_parameter {
let self_ty = match assoc_item.container {
- ty::ImplContainer => tcx.type_of(assoc_item.container_id(tcx)),
+ ty::ImplContainer => tcx.type_of(assoc_item.container_id(tcx)).subst_identity(),
ty::TraitContainer => tcx.types.self_param,
};
let self_arg_ty = sig.input(0).skip_binder();
@@ -1400,7 +1411,7 @@ pub(crate) fn clean_middle_assoc_item<'tcx>(
AssocTypeItem(
Box::new(Typedef {
type_: clean_middle_ty(
- ty::Binder::dummy(tcx.type_of(assoc_item.def_id)),
+ ty::Binder::dummy(tcx.type_of(assoc_item.def_id).subst_identity()),
cx,
Some(assoc_item.def_id),
),
@@ -1418,7 +1429,7 @@ pub(crate) fn clean_middle_assoc_item<'tcx>(
AssocTypeItem(
Box::new(Typedef {
type_: clean_middle_ty(
- ty::Binder::dummy(tcx.type_of(assoc_item.def_id)),
+ ty::Binder::dummy(tcx.type_of(assoc_item.def_id).subst_identity()),
cx,
Some(assoc_item.def_id),
),
@@ -1463,10 +1474,10 @@ fn clean_qpath<'tcx>(hir_ty: &hir::Ty<'tcx>, cx: &mut DocContext<'tcx>) -> Type
// Try to normalize `<X as Y>::T` to a type
let ty = hir_ty_to_ty(cx.tcx, hir_ty);
// `hir_to_ty` can return projection types with escaping vars for GATs, e.g. `<() as Trait>::Gat<'_>`
- if !ty.has_escaping_bound_vars() {
- if let Some(normalized_value) = normalize(cx, ty::Binder::dummy(ty)) {
- return clean_middle_ty(normalized_value, cx, None);
- }
+ if !ty.has_escaping_bound_vars()
+ && let Some(normalized_value) = normalize(cx, ty::Binder::dummy(ty))
+ {
+ return clean_middle_ty(normalized_value, cx, None);
}
let trait_segments = &p.segments[..p.segments.len() - 1];
@@ -1528,7 +1539,7 @@ fn maybe_expand_private_type_alias<'tcx>(
let hir::ItemKind::TyAlias(ty, generics) = alias else { return None };
let provided_params = &path.segments.last().expect("segments were empty");
- let mut substs = FxHashMap::default();
+ let mut substs = DefIdMap::default();
let generic_args = provided_params.args();
let mut indices: hir::GenericParamCount = Default::default();
@@ -1547,18 +1558,16 @@ fn maybe_expand_private_type_alias<'tcx>(
_ => None,
});
if let Some(lt) = lifetime {
- let lt_def_id = cx.tcx.hir().local_def_id(param.hir_id);
let cleaned = if !lt.is_anonymous() {
clean_lifetime(lt, cx)
} else {
Lifetime::elided()
};
- substs.insert(lt_def_id.to_def_id(), SubstParam::Lifetime(cleaned));
+ substs.insert(param.def_id.to_def_id(), SubstParam::Lifetime(cleaned));
}
indices.lifetimes += 1;
}
hir::GenericParamKind::Type { ref default, .. } => {
- let ty_param_def_id = cx.tcx.hir().local_def_id(param.hir_id);
let mut j = 0;
let type_ = generic_args.args.iter().find_map(|arg| match arg {
hir::GenericArg::Type(ty) => {
@@ -1571,17 +1580,14 @@ fn maybe_expand_private_type_alias<'tcx>(
_ => None,
});
if let Some(ty) = type_ {
- substs.insert(ty_param_def_id.to_def_id(), SubstParam::Type(clean_ty(ty, cx)));
+ substs.insert(param.def_id.to_def_id(), SubstParam::Type(clean_ty(ty, cx)));
} else if let Some(default) = *default {
- substs.insert(
- ty_param_def_id.to_def_id(),
- SubstParam::Type(clean_ty(default, cx)),
- );
+ substs
+ .insert(param.def_id.to_def_id(), SubstParam::Type(clean_ty(default, cx)));
}
indices.types += 1;
}
hir::GenericParamKind::Const { .. } => {
- let const_param_def_id = cx.tcx.hir().local_def_id(param.hir_id);
let mut j = 0;
let const_ = generic_args.args.iter().find_map(|arg| match arg {
hir::GenericArg::Const(ct) => {
@@ -1595,7 +1601,7 @@ fn maybe_expand_private_type_alias<'tcx>(
});
if let Some(ct) = const_ {
substs.insert(
- const_param_def_id.to_def_id(),
+ param.def_id.to_def_id(),
SubstParam::Constant(clean_const(ct, cx)),
);
}
@@ -1623,7 +1629,6 @@ pub(crate) fn clean_ty<'tcx>(ty: &hir::Ty<'tcx>, cx: &mut DocContext<'tcx>) -> T
let length = match length {
hir::ArrayLen::Infer(_, _) => "_".to_string(),
hir::ArrayLen::Body(anon_const) => {
- let def_id = cx.tcx.hir().local_def_id(anon_const.hir_id);
// NOTE(min_const_generics): We can't use `const_eval_poly` for constants
// as we currently do not supply the parent generics to anonymous constants
// but do allow `ConstKind::Param`.
@@ -1631,8 +1636,8 @@ pub(crate) fn clean_ty<'tcx>(ty: &hir::Ty<'tcx>, cx: &mut DocContext<'tcx>) -> T
// `const_eval_poly` tries to first substitute generic parameters which
// results in an ICE while manually constructing the constant and using `eval`
// does nothing for `ConstKind::Param`.
- let ct = ty::Const::from_anon_const(cx.tcx, def_id);
- let param_env = cx.tcx.param_env(def_id);
+ let ct = ty::Const::from_anon_const(cx.tcx, anon_const.def_id);
+ let param_env = cx.tcx.param_env(anon_const.def_id);
print_const(cx, ct.eval(cx.tcx, param_env))
}
};
@@ -1657,7 +1662,7 @@ pub(crate) fn clean_ty<'tcx>(ty: &hir::Ty<'tcx>, cx: &mut DocContext<'tcx>) -> T
}
TyKind::BareFn(barefn) => BareFunction(Box::new(clean_bare_fn_ty(barefn, cx))),
// Rustdoc handles `TyKind::Err`s by turning them into `Type::Infer`s.
- TyKind::Infer | TyKind::Err | TyKind::Typeof(..) => Infer,
+ TyKind::Infer | TyKind::Err(_) | TyKind::Typeof(..) => Infer,
}
}
@@ -1854,6 +1859,7 @@ pub(crate) fn clean_middle_ty<'tcx>(
ty::Bound(..) => panic!("Bound"),
ty::Placeholder(..) => panic!("Placeholder"),
ty::GeneratorWitness(..) => panic!("GeneratorWitness"),
+ ty::GeneratorWitnessMIR(..) => panic!("GeneratorWitnessMIR"),
ty::Infer(..) => panic!("Infer"),
ty::Error(_) => rustc_errors::FatalError.raise(),
}
@@ -1885,11 +1891,9 @@ fn clean_middle_opaque_bounds<'tcx>(
_ => return None,
};
- if let Some(sized) = cx.tcx.lang_items().sized_trait() {
- if trait_ref.def_id() == sized {
- has_sized = true;
- return None;
- }
+ if let Some(sized) = cx.tcx.lang_items().sized_trait() && trait_ref.def_id() == sized {
+ has_sized = true;
+ return None;
}
let bindings: ThinVec<_> = bounds
@@ -1928,15 +1932,18 @@ fn clean_middle_opaque_bounds<'tcx>(
}
pub(crate) fn clean_field<'tcx>(field: &hir::FieldDef<'tcx>, cx: &mut DocContext<'tcx>) -> Item {
- let def_id = cx.tcx.hir().local_def_id(field.hir_id).to_def_id();
- clean_field_with_def_id(def_id, field.ident.name, clean_ty(field.ty, cx), cx)
+ clean_field_with_def_id(field.def_id.to_def_id(), field.ident.name, clean_ty(field.ty, cx), cx)
}
pub(crate) fn clean_middle_field<'tcx>(field: &ty::FieldDef, cx: &mut DocContext<'tcx>) -> Item {
clean_field_with_def_id(
field.did,
field.name,
- clean_middle_ty(ty::Binder::dummy(cx.tcx.type_of(field.did)), cx, Some(field.did)),
+ clean_middle_ty(
+ ty::Binder::dummy(cx.tcx.type_of(field.did).subst_identity()),
+ cx,
+ Some(field.did),
+ ),
cx,
)
}
@@ -1979,10 +1986,8 @@ fn clean_variant_data<'tcx>(
disr_expr: &Option<hir::AnonConst>,
cx: &mut DocContext<'tcx>,
) -> Variant {
- let discriminant = disr_expr.map(|disr| Discriminant {
- expr: Some(disr.body),
- value: cx.tcx.hir().local_def_id(disr.hir_id).to_def_id(),
- });
+ let discriminant = disr_expr
+ .map(|disr| Discriminant { expr: Some(disr.body), value: disr.def_id.to_def_id() });
let kind = match variant {
hir::VariantData::Struct(..) => VariantKind::Struct(VariantStruct {
@@ -2067,12 +2072,12 @@ struct OneLevelVisitor<'hir> {
map: rustc_middle::hir::map::Map<'hir>,
item: Option<&'hir hir::Item<'hir>>,
looking_for: Ident,
- target_hir_id: hir::HirId,
+ target_def_id: LocalDefId,
}
impl<'hir> OneLevelVisitor<'hir> {
- fn new(map: rustc_middle::hir::map::Map<'hir>, target_hir_id: hir::HirId) -> Self {
- Self { map, item: None, looking_for: Ident::empty(), target_hir_id }
+ fn new(map: rustc_middle::hir::map::Map<'hir>, target_def_id: LocalDefId) -> Self {
+ Self { map, item: None, looking_for: Ident::empty(), target_def_id }
}
fn reset(&mut self, looking_for: Ident) {
@@ -2091,8 +2096,8 @@ impl<'hir> hir::intravisit::Visitor<'hir> for OneLevelVisitor<'hir> {
fn visit_item(&mut self, item: &'hir hir::Item<'hir>) {
if self.item.is_none()
&& item.ident == self.looking_for
- && matches!(item.kind, hir::ItemKind::Use(_, _))
- || item.hir_id() == self.target_hir_id
+ && (matches!(item.kind, hir::ItemKind::Use(_, _))
+ || item.owner_id.def_id == self.target_def_id)
{
self.item = Some(item);
}
@@ -2106,41 +2111,168 @@ impl<'hir> hir::intravisit::Visitor<'hir> for OneLevelVisitor<'hir> {
fn get_all_import_attributes<'hir>(
mut item: &hir::Item<'hir>,
tcx: TyCtxt<'hir>,
- target_hir_id: hir::HirId,
+ target_def_id: LocalDefId,
attributes: &mut Vec<ast::Attribute>,
+ is_inline: bool,
) {
+ let mut first = true;
let hir_map = tcx.hir();
- let mut visitor = OneLevelVisitor::new(hir_map, target_hir_id);
+ let mut visitor = OneLevelVisitor::new(hir_map, target_def_id);
let mut visited = FxHashSet::default();
+
// If the item is an import and has at least a path with two parts, we go into it.
- while let hir::ItemKind::Use(path, _) = item.kind &&
- path.segments.len() > 1 &&
- let hir::def::Res::Def(_, def_id) = path.segments[path.segments.len() - 2].res &&
- visited.insert(def_id)
- {
- if let Some(hir::Node::Item(parent_item)) = hir_map.get_if_local(def_id) {
- // We add the attributes from this import into the list.
+ while let hir::ItemKind::Use(path, _) = item.kind && visited.insert(item.hir_id()) {
+ if first {
+ // This is the "original" reexport so we get all its attributes without filtering them.
attributes.extend_from_slice(hir_map.attrs(item.hir_id()));
- // We get the `Ident` we will be looking for into `item`.
- let looking_for = path.segments[path.segments.len() - 1].ident;
- visitor.reset(looking_for);
- hir::intravisit::walk_item(&mut visitor, parent_item);
- if let Some(i) = visitor.item {
- item = i;
- } else {
- break;
+ first = false;
+ } else {
+ add_without_unwanted_attributes(attributes, hir_map.attrs(item.hir_id()), is_inline);
+ }
+
+ let def_id = if let [.., parent_segment, _] = &path.segments {
+ match parent_segment.res {
+ hir::def::Res::Def(_, def_id) => def_id,
+ _ if parent_segment.ident.name == kw::Crate => {
+ // In case the "parent" is the crate, it'll give `Res::Err` so we need to
+ // circumvent it this way.
+ tcx.parent(item.owner_id.def_id.to_def_id())
+ }
+ _ => break,
}
} else {
+ // If the path doesn't have a parent, then the parent is the current module.
+ tcx.parent(item.owner_id.def_id.to_def_id())
+ };
+
+ let Some(parent) = hir_map.get_if_local(def_id) else { break };
+
+ // We get the `Ident` we will be looking for into `item`.
+ let looking_for = path.segments[path.segments.len() - 1].ident;
+ visitor.reset(looking_for);
+
+ match parent {
+ hir::Node::Item(parent_item) => {
+ hir::intravisit::walk_item(&mut visitor, parent_item);
+ }
+ hir::Node::Crate(m) => {
+ hir::intravisit::walk_mod(
+ &mut visitor,
+ m,
+ tcx.local_def_id_to_hir_id(def_id.as_local().unwrap()),
+ );
+ }
+ _ => break,
+ }
+ if let Some(i) = visitor.item {
+ item = i;
+ } else {
break;
}
}
}
+fn filter_tokens_from_list(
+ args_tokens: TokenStream,
+ should_retain: impl Fn(&TokenTree) -> bool,
+) -> Vec<TokenTree> {
+ let mut tokens = Vec::with_capacity(args_tokens.len());
+ let mut skip_next_comma = false;
+ for token in args_tokens.into_trees() {
+ match token {
+ TokenTree::Token(Token { kind: TokenKind::Comma, .. }, _) if skip_next_comma => {
+ skip_next_comma = false;
+ }
+ token if should_retain(&token) => {
+ skip_next_comma = false;
+ tokens.push(token);
+ }
+ _ => {
+ skip_next_comma = true;
+ }
+ }
+ }
+ tokens
+}
+
+/// When inlining items, we merge its attributes (and all the reexports attributes too) with the
+/// final reexport. For example:
+///
+/// ```ignore (just an example)
+/// #[doc(hidden, cfg(feature = "foo"))]
+/// pub struct Foo;
+///
+/// #[doc(cfg(feature = "bar"))]
+/// #[doc(hidden, no_inline)]
+/// pub use Foo as Foo1;
+///
+/// #[doc(inline)]
+/// pub use Foo2 as Bar;
+/// ```
+///
+/// So `Bar` at the end will have both `cfg(feature = "...")`. However, we don't want to merge all
+/// attributes so we filter out the following ones:
+/// * `doc(inline)`
+/// * `doc(no_inline)`
+/// * `doc(hidden)`
+fn add_without_unwanted_attributes(
+ attrs: &mut Vec<ast::Attribute>,
+ new_attrs: &[ast::Attribute],
+ is_inline: bool,
+) {
+ // If it's `#[doc(inline)]`, we don't want all attributes, otherwise we keep everything.
+ if !is_inline {
+ attrs.extend_from_slice(new_attrs);
+ return;
+ }
+ for attr in new_attrs {
+ let mut attr = attr.clone();
+ match attr.kind {
+ ast::AttrKind::Normal(ref mut normal) => {
+ if let [ident] = &*normal.item.path.segments &&
+ let ident = ident.ident.name &&
+ ident == sym::doc
+ {
+ match normal.item.args {
+ ast::AttrArgs::Delimited(ref mut args) => {
+ let tokens =
+ filter_tokens_from_list(args.tokens.clone(), |token| {
+ !matches!(
+ token,
+ TokenTree::Token(
+ Token {
+ kind: TokenKind::Ident(
+ sym::hidden | sym::inline | sym::no_inline,
+ _,
+ ),
+ ..
+ },
+ _,
+ ),
+ )
+ });
+ args.tokens = TokenStream::new(tokens);
+ attrs.push(attr);
+ }
+ ast::AttrArgs::Empty | ast::AttrArgs::Eq(..) => {
+ attrs.push(attr);
+ continue;
+ }
+ }
+ }
+ }
+ ast::AttrKind::DocComment(..) => {
+ attrs.push(attr);
+ }
+ }
+ }
+}
+
fn clean_maybe_renamed_item<'tcx>(
cx: &mut DocContext<'tcx>,
item: &hir::Item<'tcx>,
renamed: Option<Symbol>,
- import_id: Option<hir::HirId>,
+ import_id: Option<LocalDefId>,
) -> Vec<Item> {
use hir::ItemKind;
@@ -2185,7 +2317,7 @@ fn clean_maybe_renamed_item<'tcx>(
generics: clean_generics(generics, cx),
fields: variant_data.fields().iter().map(|x| clean_field(x, cx)).collect(),
}),
- ItemKind::Impl(impl_) => return clean_impl(impl_, item.hir_id(), cx),
+ ItemKind::Impl(impl_) => return clean_impl(impl_, item.owner_id.def_id, cx),
// proc macros can have a name set by attributes
ItemKind::Fn(ref sig, generics, body_id) => {
clean_fn_or_proc_macro(item, sig, generics, body_id, &mut name, cx)
@@ -2218,40 +2350,38 @@ fn clean_maybe_renamed_item<'tcx>(
_ => unreachable!("not yet converted"),
};
- let mut extra_attrs = Vec::new();
- if let Some(hir::Node::Item(use_node)) =
- import_id.and_then(|hir_id| cx.tcx.hir().find(hir_id))
+ let mut import_attrs = Vec::new();
+ let mut target_attrs = Vec::new();
+ if let Some(import_id) = import_id &&
+ let Some(hir::Node::Item(use_node)) = cx.tcx.hir().find_by_def_id(import_id)
{
- // We get all the various imports' attributes.
- get_all_import_attributes(use_node, cx.tcx, item.hir_id(), &mut extra_attrs);
- }
-
- if !extra_attrs.is_empty() {
- extra_attrs.extend_from_slice(inline::load_attrs(cx, def_id));
- let attrs = Attributes::from_ast(&extra_attrs);
- let cfg = extra_attrs.cfg(cx.tcx, &cx.cache.hidden_cfg);
-
- vec![Item::from_def_id_and_attrs_and_parts(
- def_id,
- Some(name),
- kind,
- Box::new(attrs),
- cfg,
- )]
+ let is_inline = inline::load_attrs(cx, import_id.to_def_id()).lists(sym::doc).get_word_attr(sym::inline).is_some();
+ // Then we get all the various imports' attributes.
+ get_all_import_attributes(use_node, cx.tcx, item.owner_id.def_id, &mut import_attrs, is_inline);
+ add_without_unwanted_attributes(&mut target_attrs, inline::load_attrs(cx, def_id), is_inline);
} else {
- vec![Item::from_def_id_and_parts(def_id, Some(name), kind, cx)]
+ // We only keep the item's attributes.
+ target_attrs.extend_from_slice(inline::load_attrs(cx, def_id));
}
+
+ let import_parent = import_id.map(|import_id| cx.tcx.local_parent(import_id).to_def_id());
+ let (attrs, cfg) = merge_attrs(cx, import_parent, &target_attrs, Some(&import_attrs));
+
+ let mut item =
+ Item::from_def_id_and_attrs_and_parts(def_id, Some(name), kind, Box::new(attrs), cfg);
+ item.inline_stmt_id = import_id.map(|def_id| def_id.to_def_id());
+ vec![item]
})
}
fn clean_variant<'tcx>(variant: &hir::Variant<'tcx>, cx: &mut DocContext<'tcx>) -> Item {
let kind = VariantItem(clean_variant_data(&variant.data, &variant.disr_expr, cx));
- Item::from_hir_id_and_parts(variant.hir_id, Some(variant.ident.name), kind, cx)
+ Item::from_def_id_and_parts(variant.def_id.to_def_id(), Some(variant.ident.name), kind, cx)
}
fn clean_impl<'tcx>(
impl_: &hir::Impl<'tcx>,
- hir_id: hir::HirId,
+ def_id: LocalDefId,
cx: &mut DocContext<'tcx>,
) -> Vec<Item> {
let tcx = cx.tcx;
@@ -2262,7 +2392,6 @@ fn clean_impl<'tcx>(
.iter()
.map(|ii| clean_impl_item(tcx.hir().impl_item(ii.id), cx))
.collect::<Vec<_>>();
- let def_id = tcx.hir().local_def_id(hir_id);
// 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.
@@ -2272,9 +2401,11 @@ fn clean_impl<'tcx>(
let for_ = clean_ty(impl_.self_ty, cx);
let type_alias = for_.def_id(&cx.cache).and_then(|did| match tcx.def_kind(did) {
- DefKind::TyAlias => {
- Some(clean_middle_ty(ty::Binder::dummy(tcx.type_of(did)), cx, Some(did)))
- }
+ DefKind::TyAlias => Some(clean_middle_ty(
+ ty::Binder::dummy(tcx.type_of(did).subst_identity()),
+ cx,
+ Some(did),
+ )),
_ => None,
});
let mut make_item = |trait_: Option<Path>, for_: Type, items: Vec<Item>| {
@@ -2291,7 +2422,7 @@ fn clean_impl<'tcx>(
ImplKind::Normal
},
}));
- Item::from_hir_id_and_parts(hir_id, None, kind, cx)
+ Item::from_def_id_and_parts(def_id.to_def_id(), None, kind, cx)
};
if let Some(type_alias) = type_alias {
ret.push(make_item(trait_.clone(), type_alias, items.clone()));
@@ -2323,7 +2454,7 @@ fn clean_extern_crate<'tcx>(
let krate_owner_def_id = krate.owner_id.to_def_id();
if please_inline {
- let mut visited = FxHashSet::default();
+ let mut visited = DefIdSet::default();
let res = Res::Def(DefKind::Mod, crate_def_id);
@@ -2405,17 +2536,15 @@ fn clean_use_statement_inner<'tcx>(
let is_visible_from_parent_mod =
visibility.is_accessible_from(parent_mod, cx.tcx) && !current_mod.is_top_level_module();
- if pub_underscore {
- if let Some(ref inline) = inline_attr {
- rustc_errors::struct_span_err!(
- cx.tcx.sess,
- inline.span(),
- E0780,
- "anonymous imports cannot be inlined"
- )
- .span_label(import.span, "anonymous import")
- .emit();
- }
+ if pub_underscore && let Some(ref inline) = inline_attr {
+ rustc_errors::struct_span_err!(
+ cx.tcx.sess,
+ inline.span(),
+ E0780,
+ "anonymous imports cannot be inlined"
+ )
+ .span_label(import.span, "anonymous import")
+ .emit();
}
// We consider inlining the documentation of `pub use` statements, but we
@@ -2442,7 +2571,7 @@ fn clean_use_statement_inner<'tcx>(
let path = clean_path(path, cx);
let inner = if kind == hir::UseKind::Glob {
if !denied {
- let mut visited = FxHashSet::default();
+ let mut visited = DefIdSet::default();
if let Some(items) =
inline::try_inline_glob(cx, path.res, current_mod, &mut visited, inlined_names)
{
@@ -2451,17 +2580,16 @@ fn clean_use_statement_inner<'tcx>(
}
Import::new_glob(resolve_use_source(cx, path), true)
} else {
- if inline_attr.is_none() {
- if let Res::Def(DefKind::Mod, did) = path.res {
- if !did.is_local() && did.is_crate_root() {
- // if we're `pub use`ing an extern crate root, don't inline it unless we
- // were specifically asked for it
- denied = true;
- }
- }
+ if inline_attr.is_none()
+ && let Res::Def(DefKind::Mod, did) = path.res
+ && !did.is_local() && did.is_crate_root()
+ {
+ // if we're `pub use`ing an extern crate root, don't inline it unless we
+ // were specifically asked for it
+ denied = true;
}
if !denied {
- let mut visited = FxHashSet::default();
+ let mut visited = DefIdSet::default();
let import_def_id = import.owner_id.to_def_id();
if let Some(mut items) = inline::try_inline(
@@ -2512,8 +2640,8 @@ fn clean_maybe_renamed_foreign_item<'tcx>(
hir::ForeignItemKind::Type => ForeignTypeItem,
};
- Item::from_hir_id_and_parts(
- item.hir_id(),
+ Item::from_def_id_and_parts(
+ item.owner_id.def_id.to_def_id(),
Some(renamed.unwrap_or(item.ident.name)),
kind,
cx,
diff --git a/src/librustdoc/clean/render_macro_matchers.rs b/src/librustdoc/clean/render_macro_matchers.rs
index ed7683e36..ef38ca3c1 100644
--- a/src/librustdoc/clean/render_macro_matchers.rs
+++ b/src/librustdoc/clean/render_macro_matchers.rs
@@ -63,7 +63,8 @@ fn snippet_equal_to_token(tcx: TyCtxt<'_>, matcher: &TokenTree) -> Option<String
let snippet = source_map.span_to_snippet(span).ok()?;
// Create a Parser.
- let sess = ParseSess::new(FilePathMapping::empty());
+ let sess =
+ ParseSess::new(rustc_driver::DEFAULT_LOCALE_RESOURCES.to_vec(), FilePathMapping::empty());
let file_name = source_map.span_to_filename(span);
let mut parser =
match rustc_parse::maybe_new_parser_from_source_str(&sess, file_name, snippet.clone()) {
diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs
index 87de41fde..27d18aad7 100644
--- a/src/librustdoc/clean/types.rs
+++ b/src/librustdoc/clean/types.rs
@@ -5,13 +5,12 @@ use std::path::PathBuf;
use std::rc::Rc;
use std::sync::Arc;
use std::sync::OnceLock as OnceCell;
-use std::{cmp, fmt, iter};
+use std::{fmt, iter};
use arrayvec::ArrayVec;
use thin_vec::ThinVec;
-use rustc_ast::util::comments::beautify_doc_string;
-use rustc_ast::{self as ast, AttrStyle};
+use rustc_ast as ast;
use rustc_attr::{ConstStability, Deprecation, Stability, StabilityLevel};
use rustc_const_eval::const_eval::is_unstable_const_fn;
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
@@ -24,6 +23,7 @@ use rustc_hir_analysis::check::intrinsic::intrinsic_operation_unsafety;
use rustc_index::vec::IndexVec;
use rustc_middle::ty::fast_reject::SimplifiedType;
use rustc_middle::ty::{self, DefIdTree, TyCtxt, Visibility};
+use rustc_resolve::rustdoc::{add_doc_fragment, attrs_to_doc_fragments, inner_docs, DocFragment};
use rustc_session::Session;
use rustc_span::hygiene::MacroKind;
use rustc_span::symbol::{kw, sym, Ident, Symbol};
@@ -182,10 +182,8 @@ impl ExternalCrate {
return Local;
}
- if extern_url_takes_precedence {
- if let Some(url) = extern_url {
- return to_remote(url);
- }
+ if extern_url_takes_precedence && let Some(url) = extern_url {
+ return to_remote(url);
}
// Failing that, see if there's an attribute specifying where to find this
@@ -405,7 +403,7 @@ impl Item {
pub(crate) fn inner_docs(&self, tcx: TyCtxt<'_>) -> bool {
self.item_id
.as_def_id()
- .map(|did| tcx.get_attrs_unchecked(did).inner_docs())
+ .map(|did| inner_docs(tcx.get_attrs_unchecked(did)))
.unwrap_or(false)
}
@@ -439,17 +437,6 @@ impl Item {
self.attrs.doc_value()
}
- /// Convenience wrapper around [`Self::from_def_id_and_parts`] which converts
- /// `hir_id` to a [`DefId`]
- pub(crate) fn from_hir_id_and_parts(
- hir_id: hir::HirId,
- name: Option<Symbol>,
- kind: ItemKind,
- cx: &mut DocContext<'_>,
- ) -> Item {
- Item::from_def_id_and_parts(cx.tcx.hir().local_def_id(hir_id).to_def_id(), name, kind, cx)
- }
-
pub(crate) fn from_def_id_and_parts(
def_id: DefId,
name: Option<Symbol>,
@@ -493,16 +480,16 @@ impl Item {
}
pub(crate) fn links(&self, cx: &Context<'_>) -> Vec<RenderedLink> {
- use crate::html::format::href;
+ use crate::html::format::{href, link_tooltip};
cx.cache()
.intra_doc_links
.get(&self.item_id)
.map_or(&[][..], |v| v.as_slice())
.iter()
- .filter_map(|ItemLink { link: s, link_text, page_id: did, ref fragment }| {
- debug!(?did);
- if let Ok((mut href, ..)) = href(*did, cx) {
+ .filter_map(|ItemLink { link: s, link_text, page_id: id, ref fragment }| {
+ debug!(?id);
+ if let Ok((mut href, ..)) = href(*id, cx) {
debug!(?href);
if let Some(ref fragment) = *fragment {
fragment.render(&mut href, cx.tcx())
@@ -510,6 +497,7 @@ impl Item {
Some(RenderedLink {
original_text: s.clone(),
new_text: link_text.clone(),
+ tooltip: link_tooltip(*id, fragment, cx),
href,
})
} else {
@@ -534,6 +522,7 @@ impl Item {
original_text: s.clone(),
new_text: link_text.clone(),
href: String::new(),
+ tooltip: String::new(),
})
.collect()
}
@@ -665,7 +654,7 @@ impl Item {
tcx: TyCtxt<'_>,
asyncness: hir::IsAsync,
) -> hir::FnHeader {
- let sig = tcx.fn_sig(def_id);
+ let sig = tcx.fn_sig(def_id).skip_binder();
let constness =
if tcx.is_const_fn(def_id) && is_unstable_const_fn(tcx, def_id).is_none() {
hir::Constness::Const
@@ -677,7 +666,7 @@ impl Item {
let header = match *self.kind {
ItemKind::ForeignFunctionItem(_) => {
let def_id = self.item_id.as_def_id().unwrap();
- let abi = tcx.fn_sig(def_id).abi();
+ let abi = tcx.fn_sig(def_id).skip_binder().abi();
hir::FnHeader {
unsafety: if abi == Abi::RustIntrinsic {
intrinsic_operation_unsafety(tcx, self.item_id.as_def_id().unwrap())
@@ -885,8 +874,6 @@ pub(crate) trait AttributesExt {
fn span(&self) -> Option<rustc_span::Span>;
- fn inner_docs(&self) -> bool;
-
fn cfg(&self, tcx: TyCtxt<'_>, hidden_cfg: &FxHashSet<Cfg>) -> Option<Arc<Cfg>>;
}
@@ -905,14 +892,6 @@ impl AttributesExt for [ast::Attribute] {
self.iter().find(|attr| attr.doc_str().is_some()).map(|attr| attr.span)
}
- /// Returns whether the first doc-comment is an inner attribute.
- ///
- //// If there are no doc-comments, return true.
- /// FIXME(#78591): Support both inner and outer attributes on the same item.
- fn inner_docs(&self) -> bool {
- self.iter().find(|a| a.doc_str().is_some()).map_or(true, |a| a.style == AttrStyle::Inner)
- }
-
fn cfg(&self, tcx: TyCtxt<'_>, hidden_cfg: &FxHashSet<Cfg>) -> Option<Arc<Cfg>> {
let sess = tcx.sess;
let doc_cfg_active = tcx.features().doc_cfg;
@@ -1021,58 +1000,6 @@ impl<I: Iterator<Item = ast::NestedMetaItem>> NestedAttributesExt for I {
}
}
-/// A portion of documentation, extracted from a `#[doc]` attribute.
-///
-/// Each variant contains the line number within the complete doc-comment where the fragment
-/// starts, as well as the Span where the corresponding doc comment or attribute is located.
-///
-/// Included files are kept separate from inline doc comments so that proper line-number
-/// information can be given when a doctest fails. Sugared doc comments and "raw" doc comments are
-/// kept separate because of issue #42760.
-#[derive(Clone, PartialEq, Eq, Debug)]
-pub(crate) struct DocFragment {
- pub(crate) span: rustc_span::Span,
- /// The module this doc-comment came from.
- ///
- /// This allows distinguishing between the original documentation and a pub re-export.
- /// If it is `None`, the item was not re-exported.
- pub(crate) parent_module: Option<DefId>,
- pub(crate) doc: Symbol,
- pub(crate) kind: DocFragmentKind,
- pub(crate) indent: usize,
-}
-
-#[derive(Clone, Copy, PartialEq, Eq, Debug)]
-pub(crate) enum DocFragmentKind {
- /// A doc fragment created from a `///` or `//!` doc comment.
- SugaredDoc,
- /// A doc fragment created from a "raw" `#[doc=""]` attribute.
- RawDoc,
-}
-
-/// The goal of this function is to apply the `DocFragment` transformation that is required when
-/// transforming into the final Markdown, which is applying the computed indent to each line in
-/// each doc fragment (a `DocFragment` can contain multiple lines in case of `#[doc = ""]`).
-///
-/// Note: remove the trailing newline where appropriate
-fn add_doc_fragment(out: &mut String, frag: &DocFragment) {
- let s = frag.doc.as_str();
- let mut iter = s.lines();
- if s.is_empty() {
- out.push('\n');
- return;
- }
- while let Some(line) = iter.next() {
- if line.chars().any(|c| !c.is_whitespace()) {
- assert!(line.len() >= frag.indent);
- out.push_str(&line[frag.indent..]);
- } else {
- out.push_str(line);
- }
- out.push('\n');
- }
-}
-
/// Collapse a collection of [`DocFragment`]s into one string,
/// handling indentation and newlines as needed.
pub(crate) fn collapse_doc_fragments(doc_strings: &[DocFragment]) -> String {
@@ -1084,98 +1011,18 @@ pub(crate) fn collapse_doc_fragments(doc_strings: &[DocFragment]) -> String {
acc
}
-/// Removes excess indentation on comments in order for the Markdown
-/// to be parsed correctly. This is necessary because the convention for
-/// writing documentation is to provide a space between the /// or //! marker
-/// and the doc text, but Markdown is whitespace-sensitive. For example,
-/// a block of text with four-space indentation is parsed as a code block,
-/// so if we didn't unindent comments, these list items
-///
-/// /// A list:
-/// ///
-/// /// - Foo
-/// /// - Bar
-///
-/// would be parsed as if they were in a code block, which is likely not what the user intended.
-fn unindent_doc_fragments(docs: &mut Vec<DocFragment>) {
- // `add` is used in case the most common sugared doc syntax is used ("/// "). The other
- // fragments kind's lines are never starting with a whitespace unless they are using some
- // markdown formatting requiring it. Therefore, if the doc block have a mix between the two,
- // we need to take into account the fact that the minimum indent minus one (to take this
- // whitespace into account).
- //
- // For example:
- //
- // /// hello!
- // #[doc = "another"]
- //
- // In this case, you want "hello! another" and not "hello! another".
- let add = if docs.windows(2).any(|arr| arr[0].kind != arr[1].kind)
- && docs.iter().any(|d| d.kind == DocFragmentKind::SugaredDoc)
- {
- // In case we have a mix of sugared doc comments and "raw" ones, we want the sugared one to
- // "decide" how much the minimum indent will be.
- 1
- } else {
- 0
- };
-
- // `min_indent` is used to know how much whitespaces from the start of each lines must be
- // removed. Example:
- //
- // /// hello!
- // #[doc = "another"]
- //
- // In here, the `min_indent` is 1 (because non-sugared fragment are always counted with minimum
- // 1 whitespace), meaning that "hello!" will be considered a codeblock because it starts with 4
- // (5 - 1) whitespaces.
- let Some(min_indent) = docs
- .iter()
- .map(|fragment| {
- fragment.doc.as_str().lines().fold(usize::MAX, |min_indent, line| {
- if line.chars().all(|c| c.is_whitespace()) {
- min_indent
- } else {
- // Compare against either space or tab, ignoring whether they are
- // mixed or not.
- let whitespace = line.chars().take_while(|c| *c == ' ' || *c == '\t').count();
- cmp::min(min_indent, whitespace)
- + if fragment.kind == DocFragmentKind::SugaredDoc { 0 } else { add }
- }
- })
- })
- .min()
- else {
- return;
- };
-
- for fragment in docs {
- if fragment.doc == kw::Empty {
- continue;
- }
-
- let min_indent = if fragment.kind != DocFragmentKind::SugaredDoc && min_indent > 0 {
- min_indent - add
- } else {
- min_indent
- };
-
- fragment.indent = min_indent;
- }
-}
-
/// 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)]
pub(crate) struct ItemLink {
/// The original link written in the markdown
- pub(crate) link: String,
+ pub(crate) link: Box<str>,
/// The link text displayed in the HTML.
///
/// 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) link_text: Box<str>,
/// The `DefId` of the Item whose **HTML Page** contains the item being
/// linked to. This will be different to `item_id` on item's that don't
/// have their own page, such as struct fields and enum variants.
@@ -1188,11 +1035,13 @@ pub struct RenderedLink {
/// The text the link was original written as.
///
/// This could potentially include disambiguators and backticks.
- pub(crate) original_text: String,
+ pub(crate) original_text: Box<str>,
/// The text to display in the HTML
- pub(crate) new_text: String,
+ pub(crate) new_text: Box<str>,
/// The URL to put in the `href`
pub(crate) href: String,
+ /// The tooltip.
+ pub(crate) tooltip: String,
}
/// The attributes on an [`Item`], including attributes like `#[derive(...)]` and `#[inline]`,
@@ -1242,26 +1091,7 @@ impl Attributes {
attrs: impl Iterator<Item = (&'a ast::Attribute, Option<DefId>)>,
doc_only: bool,
) -> Attributes {
- let mut doc_strings = Vec::new();
- let mut other_attrs = ast::AttrVec::new();
- for (attr, parent_module) in attrs {
- if let Some((doc_str, comment_kind)) = attr.doc_str_and_comment_kind() {
- trace!("got doc_str={doc_str:?}");
- let doc = beautify_doc_string(doc_str, comment_kind);
- let kind = if attr.is_doc_comment() {
- DocFragmentKind::SugaredDoc
- } else {
- DocFragmentKind::RawDoc
- };
- let fragment = DocFragment { span: attr.span, doc, kind, parent_module, indent: 0 };
- doc_strings.push(fragment);
- } else if !doc_only {
- other_attrs.push(attr.clone());
- }
- }
-
- unindent_doc_fragments(&mut doc_strings);
-
+ let (doc_strings, other_attrs) = attrs_to_doc_fragments(attrs, doc_only);
Attributes { doc_strings, other_attrs }
}
@@ -1280,20 +1110,6 @@ impl Attributes {
if out.is_empty() { None } else { Some(out) }
}
- /// Return the doc-comments on this item, grouped by the module they came from.
- /// The module can be different if this is a re-export with added documentation.
- ///
- /// The last newline is not trimmed so the produced strings are reusable between
- /// early and late doc link resolution regardless of their position.
- pub(crate) fn prepare_to_doc_link_resolution(&self) -> FxHashMap<Option<DefId>, String> {
- let mut res = FxHashMap::default();
- for fragment in &self.doc_strings {
- let out_str = res.entry(fragment.parent_module).or_default();
- add_doc_fragment(out_str, fragment);
- }
- res
- }
-
/// Finds all `doc` attributes as NameValues and returns their corresponding values, joined
/// with newlines.
pub(crate) fn collapsed_doc_value(&self) -> Option<String> {
@@ -1358,10 +1174,10 @@ impl GenericBound {
pub(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 Some(trait_.def_id()) == cx.tcx.lang_items().sized_trait() {
- return true;
- }
+ if let GenericBound::TraitBound(PolyTrait { ref trait_, .. }, TBM::None) = *self &&
+ Some(trait_.def_id()) == cx.tcx.lang_items().sized_trait()
+ {
+ return true;
}
false
}
@@ -2416,10 +2232,7 @@ impl ConstantKind {
pub(crate) fn is_literal(&self, tcx: TyCtxt<'_>) -> bool {
match *self {
- ConstantKind::TyConst { .. } => false,
- ConstantKind::Extern { def_id } => def_id.as_local().map_or(false, |def_id| {
- is_literal_expr(tcx, tcx.hir().local_def_id_to_hir_id(def_id))
- }),
+ ConstantKind::TyConst { .. } | ConstantKind::Extern { .. } => false,
ConstantKind::Local { body, .. } | ConstantKind::Anonymous { body } => {
is_literal_expr(tcx, body.hir_id)
}
@@ -2498,14 +2311,7 @@ impl Import {
}
pub(crate) fn imported_item_is_doc_hidden(&self, tcx: TyCtxt<'_>) -> bool {
- match self.source.did {
- Some(did) => tcx
- .get_attrs(did, sym::doc)
- .filter_map(ast::Attribute::meta_item_list)
- .flatten()
- .has_word(sym::hidden),
- None => false,
- }
+ self.source.did.map_or(false, |did| tcx.is_doc_hidden(did))
}
}
diff --git a/src/librustdoc/clean/types/tests.rs b/src/librustdoc/clean/types/tests.rs
index 71eddf434..20627c2cf 100644
--- a/src/librustdoc/clean/types/tests.rs
+++ b/src/librustdoc/clean/types/tests.rs
@@ -2,6 +2,7 @@ use super::*;
use crate::clean::collapse_doc_fragments;
+use rustc_resolve::rustdoc::{unindent_doc_fragments, DocFragment, DocFragmentKind};
use rustc_span::create_default_session_globals_then;
use rustc_span::source_map::DUMMY_SP;
use rustc_span::symbol::Symbol;
diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs
index a12f764fa..c9c1c2c45 100644
--- a/src/librustdoc/clean/utils.rs
+++ b/src/librustdoc/clean/utils.rs
@@ -29,11 +29,6 @@ mod tests;
pub(crate) fn krate(cx: &mut DocContext<'_>) -> Crate {
let module = crate::visit_ast::RustdocVisitor::new(cx).visit();
- for &cnum in cx.tcx.crates(()) {
- // Analyze doc-reachability for extern items
- crate::visit_lib::lib_embargo_visit_item(cx, cnum.as_def_id());
- }
-
// Clean the crate, translating the entire librustc_ast AST to one that is
// understood by rustdoc.
let mut module = clean_doc_module(&module, cx);
@@ -134,7 +129,7 @@ fn external_generic_args<'tcx>(
});
GenericArgs::Parenthesized { inputs, output }
} else {
- GenericArgs::AngleBracketed { args: args.into(), bindings: bindings.into() }
+ GenericArgs::AngleBracketed { args: args.into(), bindings }
}
}
@@ -271,7 +266,7 @@ pub(crate) fn print_evaluated_const(
underscores_and_type: bool,
) -> Option<String> {
tcx.const_eval_poly(def_id).ok().and_then(|val| {
- let ty = tcx.type_of(def_id);
+ let ty = tcx.type_of(def_id).subst_identity();
match (val, ty.kind()) {
(_, &ty::Ref(..)) => None,
(ConstValue::Scalar(_), &ty::Adt(_, _)) => None,
@@ -350,10 +345,10 @@ pub(crate) fn is_literal_expr(tcx: TyCtxt<'_>, hir_id: hir::HirId) -> bool {
return true;
}
- if let hir::ExprKind::Unary(hir::UnOp::Neg, expr) = &expr.kind {
- if let hir::ExprKind::Lit(_) = &expr.kind {
- return true;
- }
+ if let hir::ExprKind::Unary(hir::UnOp::Neg, expr) = &expr.kind &&
+ let hir::ExprKind::Lit(_) = &expr.kind
+ {
+ return true;
}
}
@@ -475,6 +470,12 @@ pub(crate) fn get_auto_trait_and_blanket_impls(
cx: &mut DocContext<'_>,
item_def_id: DefId,
) -> impl Iterator<Item = Item> {
+ // FIXME: To be removed once `parallel_compiler` bugs are fixed!
+ // More information in <https://github.com/rust-lang/rust/pull/106930>.
+ if cfg!(parallel_compiler) {
+ return vec![].into_iter().chain(vec![].into_iter());
+ }
+
let auto_impls = cx
.sess()
.prof
diff --git a/src/librustdoc/config.rs b/src/librustdoc/config.rs
index 56b40d8c6..2c514a0c8 100644
--- a/src/librustdoc/config.rs
+++ b/src/librustdoc/config.rs
@@ -509,7 +509,7 @@ impl Options {
// these values up both in `dataset` and in the storage API, so it needs to be able
// to convert the names back and forth. Despite doing this kebab-case to
// StudlyCaps transformation automatically, the JS DOM API does not provide a
- // mechanism for doing the just transformation on a string. So we want to avoid
+ // mechanism for doing just the transformation on a string. So we want to avoid
// the StudlyCaps representation in the `dataset` property.
//
// We solve this by replacing all the `-`s with `_`s. We do that here, when we
diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs
index 2153e7d8c..fbfc58a43 100644
--- a/src/librustdoc/core.rs
+++ b/src/librustdoc/core.rs
@@ -1,23 +1,22 @@
-use rustc_ast::NodeId;
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_data_structures::sync::{self, Lrc};
use rustc_data_structures::unord::UnordSet;
use rustc_errors::emitter::{Emitter, EmitterWriter};
use rustc_errors::json::JsonEmitter;
+use rustc_errors::TerminalUrl;
use rustc_feature::UnstableFeatures;
-use rustc_hir::def::{Namespace, Res};
-use rustc_hir::def_id::{DefId, DefIdMap, LocalDefId};
+use rustc_hir::def::Res;
+use rustc_hir::def_id::{DefId, DefIdMap, DefIdSet, LocalDefId};
use rustc_hir::intravisit::{self, Visitor};
-use rustc_hir::{HirId, Path, TraitCandidate};
+use rustc_hir::{HirId, Path};
use rustc_interface::interface;
use rustc_middle::hir::nested_filter;
use rustc_middle::ty::{ParamEnv, Ty, TyCtxt};
-use rustc_resolve as resolve;
-use rustc_session::config::{self, CrateType, ErrorOutputType};
+use rustc_session::config::{self, CrateType, ErrorOutputType, ResolveDocLinks};
use rustc_session::lint;
use rustc_session::Session;
use rustc_span::symbol::sym;
-use rustc_span::{source_map, Span, Symbol};
+use rustc_span::{source_map, Span};
use std::cell::RefCell;
use std::mem;
@@ -28,30 +27,12 @@ use crate::clean::inline::build_external_trait;
use crate::clean::{self, ItemId};
use crate::config::{Options as RustdocOptions, OutputFormat, RenderOptions};
use crate::formats::cache::Cache;
-use crate::passes::collect_intra_doc_links::PreprocessedMarkdownLink;
use crate::passes::{self, Condition::*};
pub(crate) use rustc_session::config::{Input, Options, UnstableOptions};
-pub(crate) struct ResolverCaches {
- pub(crate) markdown_links: Option<FxHashMap<String, Vec<PreprocessedMarkdownLink>>>,
- pub(crate) doc_link_resolutions: FxHashMap<(Symbol, Namespace, DefId), Option<Res<NodeId>>>,
- /// Traits in scope for a given module.
- /// See `collect_intra_doc_links::traits_implemented_by` for more details.
- pub(crate) traits_in_scope: DefIdMap<Vec<TraitCandidate>>,
- pub(crate) all_trait_impls: Option<Vec<DefId>>,
- pub(crate) all_macro_rules: FxHashMap<Symbol, Res<NodeId>>,
-}
-
pub(crate) struct DocContext<'tcx> {
pub(crate) tcx: TyCtxt<'tcx>,
- /// Name resolver. Used for intra-doc links.
- ///
- /// The `Rc<RefCell<...>>` wrapping is needed because that is what's returned by
- /// [`rustc_interface::Queries::expansion()`].
- // FIXME: see if we can get rid of this RefCell somehow
- pub(crate) resolver: Rc<RefCell<interface::BoxedResolver>>,
- pub(crate) resolver_caches: ResolverCaches,
/// Used for normalization.
///
/// Most of this logic is copied from rustc_lint::late.
@@ -60,11 +41,11 @@ pub(crate) struct DocContext<'tcx> {
pub(crate) external_traits: Rc<RefCell<FxHashMap<DefId, clean::Trait>>>,
/// Used while populating `external_traits` to ensure we don't process the same trait twice at
/// the same time.
- pub(crate) active_extern_traits: FxHashSet<DefId>,
+ pub(crate) active_extern_traits: DefIdSet,
// The current set of parameter substitutions,
// for expanding type aliases at the HIR level:
/// Table `DefId` of type, lifetime, or const parameter -> substituted type, lifetime, or const
- pub(crate) substs: FxHashMap<DefId, clean::SubstParam>,
+ pub(crate) substs: DefIdMap<clean::SubstParam>,
/// Table synthetic type parameter for `impl Trait` in argument position -> bounds
pub(crate) impl_trait_bounds: FxHashMap<ImplTraitParam, Vec<clean::GenericBound>>,
/// Auto-trait or blanket impls processed so far, as `(self_ty, trait_def_id)`.
@@ -99,20 +80,9 @@ impl<'tcx> DocContext<'tcx> {
ret
}
- pub(crate) fn enter_resolver<F, R>(&self, f: F) -> R
- where
- F: FnOnce(&mut resolve::Resolver<'_>) -> R,
- {
- self.resolver.borrow_mut().access(f)
- }
-
/// Call the closure with the given parameters set as
/// the substitutions for a type alias' RHS.
- pub(crate) fn enter_alias<F, R>(
- &mut self,
- substs: FxHashMap<DefId, clean::SubstParam>,
- f: F,
- ) -> R
+ pub(crate) fn enter_alias<F, R>(&mut self, substs: DefIdMap<clean::SubstParam>, f: F) -> R
where
F: FnOnce(&mut Self) -> R,
{
@@ -133,12 +103,6 @@ impl<'tcx> DocContext<'tcx> {
_ => None,
}
}
-
- pub(crate) fn with_all_trait_impls(&mut self, f: impl FnOnce(&mut Self, &[DefId])) {
- let all_trait_impls = self.resolver_caches.all_trait_impls.take();
- f(self, all_trait_impls.as_ref().expect("`all_trait_impls` are already borrowed"));
- self.resolver_caches.all_trait_impls = all_trait_impls;
- }
}
/// Creates a new diagnostic `Handler` that can be used to emit warnings and errors.
@@ -151,8 +115,10 @@ pub(crate) fn new_handler(
diagnostic_width: Option<usize>,
unstable_opts: &UnstableOptions,
) -> rustc_errors::Handler {
- let fallback_bundle =
- rustc_errors::fallback_fluent_bundle(rustc_errors::DEFAULT_LOCALE_RESOURCES, false);
+ let fallback_bundle = rustc_errors::fallback_fluent_bundle(
+ rustc_driver::DEFAULT_LOCALE_RESOURCES.to_vec(),
+ false,
+ );
let emitter: Box<dyn Emitter + sync::Send> = match error_format {
ErrorOutputType::HumanReadable(kind) => {
let (short, color_config) = kind.unzip();
@@ -167,6 +133,7 @@ pub(crate) fn new_handler(
diagnostic_width,
false,
unstable_opts.track_diagnostics,
+ TerminalUrl::No,
)
.ui_testing(unstable_opts.ui_testing),
)
@@ -186,6 +153,7 @@ pub(crate) fn new_handler(
diagnostic_width,
false,
unstable_opts.track_diagnostics,
+ TerminalUrl::No,
)
.ui_testing(unstable_opts.ui_testing),
)
@@ -221,6 +189,7 @@ pub(crate) fn create_config(
scrape_examples_options,
..
}: RustdocOptions,
+ RenderOptions { document_private, .. }: &RenderOptions,
) -> rustc_interface::Config {
// Add the doc cfg into the doc build.
cfgs.push("doc".to_string());
@@ -248,6 +217,13 @@ pub(crate) fn create_config(
let crate_types =
if proc_macro_crate { vec![CrateType::ProcMacro] } else { vec![CrateType::Rlib] };
+ let resolve_doc_links = if *document_private {
+ ResolveDocLinks::All
+ } else {
+ // Should be `ResolveDocLinks::Exported` in theory, but for some reason rustdoc
+ // still tries to request resolutions for links on private items.
+ ResolveDocLinks::All
+ };
let test = scrape_examples_options.map(|opts| opts.scrape_tests).unwrap_or(false);
// plays with error output here!
let sessopts = config::Options {
@@ -261,6 +237,7 @@ pub(crate) fn create_config(
target_triple: target,
unstable_features: UnstableFeatures::from_environment(crate_name.as_deref()),
actually_rustdoc: true,
+ resolve_doc_links,
unstable_opts,
error_format,
diagnostic_width,
@@ -279,6 +256,7 @@ pub(crate) fn create_config(
output_file: None,
output_dir: None,
file_loader: None,
+ locale_resources: rustc_driver::DEFAULT_LOCALE_RESOURCES,
lint_caps,
parse_sess_created: None,
register_lints: Some(Box::new(crate::lint::register_lints)),
@@ -316,8 +294,6 @@ pub(crate) fn create_config(
pub(crate) fn run_global_ctxt(
tcx: TyCtxt<'_>,
- resolver: Rc<RefCell<interface::BoxedResolver>>,
- resolver_caches: ResolverCaches,
show_coverage: bool,
render_options: RenderOptions,
output_format: OutputFormat,
@@ -351,8 +327,6 @@ pub(crate) fn run_global_ctxt(
let mut ctxt = DocContext {
tcx,
- resolver,
- resolver_caches,
param_env: ParamEnv::empty(),
external_traits: Default::default(),
active_extern_traits: Default::default(),
@@ -367,6 +341,10 @@ pub(crate) fn run_global_ctxt(
show_coverage,
};
+ for cnum in tcx.crates(()) {
+ crate::visit_lib::lib_embargo_visit_item(&mut ctxt, cnum.as_def_id());
+ }
+
// Small hack to force the Sized trait to be present.
//
// Note that in case of `#![no_core]`, the trait is not available.
diff --git a/src/librustdoc/doctest.rs b/src/librustdoc/doctest.rs
index c1a652c75..9cf84acc7 100644
--- a/src/librustdoc/doctest.rs
+++ b/src/librustdoc/doctest.rs
@@ -1,11 +1,9 @@
use rustc_ast as ast;
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_data_structures::sync::Lrc;
-use rustc_errors::{ColorConfig, ErrorGuaranteed, FatalError};
-use rustc_hir as hir;
-use rustc_hir::def_id::LOCAL_CRATE;
-use rustc_hir::intravisit;
-use rustc_hir::{HirId, CRATE_HIR_ID};
+use rustc_errors::{ColorConfig, ErrorGuaranteed, FatalError, TerminalUrl};
+use rustc_hir::def_id::{LocalDefId, CRATE_DEF_ID, LOCAL_CRATE};
+use rustc_hir::{self as hir, intravisit, CRATE_HIR_ID};
use rustc_interface::interface;
use rustc_middle::hir::map::Map;
use rustc_middle::hir::nested_filter;
@@ -98,6 +96,7 @@ pub(crate) fn run(options: RustdocOptions) -> Result<(), ErrorGuaranteed> {
output_file: None,
output_dir: None,
file_loader: None,
+ locale_resources: rustc_driver::DEFAULT_LOCALE_RESOURCES,
lint_caps,
parse_sess_created: None,
register_lints: Some(Box::new(crate::lint::register_lints)),
@@ -140,7 +139,7 @@ pub(crate) fn run(options: RustdocOptions) -> Result<(), ErrorGuaranteed> {
};
hir_collector.visit_testable(
"".to_string(),
- CRATE_HIR_ID,
+ CRATE_DEF_ID,
tcx.hir().span(CRATE_HIR_ID),
|this| tcx.hir().walk_toplevel_module(this),
);
@@ -231,11 +230,11 @@ fn scrape_test_config(attrs: &[ast::Attribute]) -> GlobalTestOptions {
if attr.has_name(sym::no_crate_inject) {
opts.no_crate_inject = true;
}
- if attr.has_name(sym::attr) {
- if let Some(l) = attr.meta_item_list() {
- for item in l {
- opts.attrs.push(pprust::meta_list_item_to_string(item));
- }
+ if attr.has_name(sym::attr)
+ && let Some(l) = attr.meta_item_list()
+ {
+ for item in l {
+ opts.attrs.push(pprust::meta_list_item_to_string(item));
}
}
}
@@ -547,8 +546,10 @@ pub(crate) fn make_test(
// Any errors in parsing should also appear when the doctest is compiled for real, so just
// send all the errors that librustc_ast emits directly into a `Sink` instead of stderr.
let sm = Lrc::new(SourceMap::new(FilePathMapping::empty()));
- let fallback_bundle =
- rustc_errors::fallback_fluent_bundle(rustc_errors::DEFAULT_LOCALE_RESOURCES, false);
+ let fallback_bundle = rustc_errors::fallback_fluent_bundle(
+ rustc_driver::DEFAULT_LOCALE_RESOURCES.to_vec(),
+ false,
+ );
supports_color = EmitterWriter::stderr(
ColorConfig::Auto,
None,
@@ -559,6 +560,7 @@ pub(crate) fn make_test(
Some(80),
false,
false,
+ TerminalUrl::No,
)
.supports_color();
@@ -573,6 +575,7 @@ pub(crate) fn make_test(
None,
false,
false,
+ TerminalUrl::No,
);
// FIXME(misdreavus): pass `-Z treat-err-as-bug` to the doctest parser
@@ -594,31 +597,28 @@ pub(crate) fn make_test(
loop {
match parser.parse_item(ForceCollect::No) {
Ok(Some(item)) => {
- if !found_main {
- if let ast::ItemKind::Fn(..) = item.kind {
- if item.ident.name == sym::main {
- found_main = true;
- }
- }
+ if !found_main &&
+ let ast::ItemKind::Fn(..) = item.kind &&
+ item.ident.name == sym::main
+ {
+ found_main = true;
}
- if !found_extern_crate {
- if let ast::ItemKind::ExternCrate(original) = item.kind {
- // This code will never be reached if `crate_name` is none because
- // `found_extern_crate` is initialized to `true` if it is none.
- let crate_name = crate_name.unwrap();
+ if !found_extern_crate &&
+ let ast::ItemKind::ExternCrate(original) = item.kind
+ {
+ // This code will never be reached if `crate_name` is none because
+ // `found_extern_crate` is initialized to `true` if it is none.
+ let crate_name = crate_name.unwrap();
- match original {
- Some(name) => found_extern_crate = name.as_str() == crate_name,
- None => found_extern_crate = item.ident.as_str() == crate_name,
- }
+ match original {
+ Some(name) => found_extern_crate = name.as_str() == crate_name,
+ None => found_extern_crate = item.ident.as_str() == crate_name,
}
}
- if !found_macro {
- if let ast::ItemKind::MacCall(..) = item.kind {
- found_macro = true;
- }
+ if !found_macro && let ast::ItemKind::MacCall(..) = item.kind {
+ found_macro = true;
}
if found_main && found_extern_crate {
@@ -744,8 +744,10 @@ fn check_if_attr_is_complete(source: &str, edition: Edition) -> bool {
// Any errors in parsing should also appear when the doctest is compiled for real, so just
// send all the errors that librustc_ast emits directly into a `Sink` instead of stderr.
let sm = Lrc::new(SourceMap::new(FilePathMapping::empty()));
- let fallback_bundle =
- rustc_errors::fallback_fluent_bundle(rustc_errors::DEFAULT_LOCALE_RESOURCES, false);
+ let fallback_bundle = rustc_errors::fallback_fluent_bundle(
+ rustc_driver::DEFAULT_LOCALE_RESOURCES.to_vec(),
+ false,
+ );
let emitter = EmitterWriter::new(
Box::new(io::sink()),
@@ -758,6 +760,7 @@ fn check_if_attr_is_complete(source: &str, edition: Edition) -> bool {
None,
false,
false,
+ TerminalUrl::No,
);
let handler = Handler::with_emitter(false, None, Box::new(emitter));
@@ -766,8 +769,8 @@ fn check_if_attr_is_complete(source: &str, edition: Edition) -> bool {
match maybe_new_parser_from_source_str(&sess, filename, source.to_owned()) {
Ok(p) => p,
Err(_) => {
- debug!("Cannot build a parser to check mod attr so skipping...");
- return true;
+ // If there is an unclosed delimiter, an error will be returned by the tokentrees.
+ return false;
}
};
// If a parsing error happened, it's very likely that the attribute is incomplete.
@@ -775,15 +778,7 @@ fn check_if_attr_is_complete(source: &str, edition: Edition) -> bool {
e.cancel();
return false;
}
- // We now check if there is an unclosed delimiter for the attribute. To do so, we look at
- // the `unclosed_delims` and see if the opening square bracket was closed.
- parser
- .unclosed_delims()
- .get(0)
- .map(|unclosed| {
- unclosed.unclosed_span.map(|s| s.lo()).unwrap_or(BytePos(0)) != BytePos(2)
- })
- .unwrap_or(true)
+ true
})
})
.unwrap_or(false)
@@ -971,14 +966,12 @@ impl Collector {
fn get_filename(&self) -> FileName {
if let Some(ref source_map) = self.source_map {
let filename = source_map.span_to_filename(self.position);
- if let FileName::Real(ref filename) = filename {
- if let Ok(cur_dir) = env::current_dir() {
- if let Some(local_path) = filename.local_path() {
- if let Ok(path) = local_path.strip_prefix(&cur_dir) {
- return path.to_owned().into();
- }
- }
- }
+ if let FileName::Real(ref filename) = filename &&
+ let Ok(cur_dir) = env::current_dir() &&
+ let Some(local_path) = filename.local_path() &&
+ let Ok(path) = local_path.strip_prefix(&cur_dir)
+ {
+ return path.to_owned().into();
}
filename
} else if let Some(ref filename) = self.filename {
@@ -1214,11 +1207,11 @@ impl<'a, 'hir, 'tcx> HirCollector<'a, 'hir, 'tcx> {
fn visit_testable<F: FnOnce(&mut Self)>(
&mut self,
name: String,
- hir_id: HirId,
+ def_id: LocalDefId,
sp: Span,
nested: F,
) {
- let ast_attrs = self.tcx.hir().attrs(hir_id);
+ let ast_attrs = self.tcx.hir().attrs(self.tcx.hir().local_def_id_to_hir_id(def_id));
if let Some(ref cfg) = ast_attrs.cfg(self.tcx, &FxHashSet::default()) {
if !cfg.matches(&self.sess.parse_sess, Some(self.tcx.features())) {
return;
@@ -1247,7 +1240,7 @@ impl<'a, 'hir, 'tcx> HirCollector<'a, 'hir, 'tcx> {
self.collector.enable_per_target_ignores,
Some(&crate::html::markdown::ExtraInfo::new(
self.tcx,
- hir_id,
+ def_id.to_def_id(),
span_of_attrs(&attrs).unwrap_or(sp),
)),
);
@@ -1276,37 +1269,37 @@ impl<'a, 'hir, 'tcx> intravisit::Visitor<'hir> for HirCollector<'a, 'hir, 'tcx>
_ => item.ident.to_string(),
};
- self.visit_testable(name, item.hir_id(), item.span, |this| {
+ self.visit_testable(name, item.owner_id.def_id, item.span, |this| {
intravisit::walk_item(this, item);
});
}
fn visit_trait_item(&mut self, item: &'hir hir::TraitItem<'_>) {
- self.visit_testable(item.ident.to_string(), item.hir_id(), item.span, |this| {
+ self.visit_testable(item.ident.to_string(), item.owner_id.def_id, item.span, |this| {
intravisit::walk_trait_item(this, item);
});
}
fn visit_impl_item(&mut self, item: &'hir hir::ImplItem<'_>) {
- self.visit_testable(item.ident.to_string(), item.hir_id(), item.span, |this| {
+ self.visit_testable(item.ident.to_string(), item.owner_id.def_id, item.span, |this| {
intravisit::walk_impl_item(this, item);
});
}
fn visit_foreign_item(&mut self, item: &'hir hir::ForeignItem<'_>) {
- self.visit_testable(item.ident.to_string(), item.hir_id(), item.span, |this| {
+ self.visit_testable(item.ident.to_string(), item.owner_id.def_id, item.span, |this| {
intravisit::walk_foreign_item(this, item);
});
}
fn visit_variant(&mut self, v: &'hir hir::Variant<'_>) {
- self.visit_testable(v.ident.to_string(), v.hir_id, v.span, |this| {
+ self.visit_testable(v.ident.to_string(), v.def_id, v.span, |this| {
intravisit::walk_variant(this, v);
});
}
fn visit_field_def(&mut self, f: &'hir hir::FieldDef<'_>) {
- self.visit_testable(f.ident.to_string(), f.hir_id, f.span, |this| {
+ self.visit_testable(f.ident.to_string(), f.def_id, f.span, |this| {
intravisit::walk_field_def(this, f);
});
}
diff --git a/src/librustdoc/formats/cache.rs b/src/librustdoc/formats/cache.rs
index 1c78c5b8d..8dbfaf4bb 100644
--- a/src/librustdoc/formats/cache.rs
+++ b/src/librustdoc/formats/cache.rs
@@ -1,7 +1,7 @@
use std::mem;
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
-use rustc_hir::def_id::{CrateNum, DefId};
+use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, DefIdSet};
use rustc_middle::ty::{self, TyCtxt};
use rustc_span::Symbol;
@@ -33,7 +33,7 @@ pub(crate) struct Cache {
///
/// The values of the map are a list of implementations and documentation
/// found on that implementation.
- pub(crate) impls: FxHashMap<DefId, Vec<Impl>>,
+ pub(crate) impls: DefIdMap<Vec<Impl>>,
/// Maintains a mapping of local crate `DefId`s to the fully qualified name
/// and "short type description" of that node. This is used when generating
@@ -56,7 +56,7 @@ pub(crate) struct Cache {
/// to the path used if the corresponding type is inlined. By
/// doing this, we can detect duplicate impls on a trait page, and only display
/// the impl for the inlined type.
- pub(crate) exact_paths: FxHashMap<DefId, Vec<Symbol>>,
+ pub(crate) exact_paths: DefIdMap<Vec<Symbol>>,
/// This map contains information about all known traits of this crate.
/// Implementations of a crate should inherit the documentation of the
@@ -127,7 +127,7 @@ pub(crate) struct Cache {
struct CacheBuilder<'a, 'tcx> {
cache: &'a mut Cache,
/// This field is used to prevent duplicated impl blocks.
- impl_ids: FxHashMap<DefId, FxHashSet<DefId>>,
+ impl_ids: DefIdMap<DefIdSet>,
tcx: TyCtxt<'tcx>,
}
@@ -173,7 +173,7 @@ impl Cache {
let (krate, mut impl_ids) = {
let mut cache_builder =
- CacheBuilder { tcx, cache: &mut cx.cache, impl_ids: FxHashMap::default() };
+ CacheBuilder { tcx, cache: &mut cx.cache, impl_ids: Default::default() };
krate = cache_builder.fold_crate(krate);
(krate, cache_builder.impl_ids)
};
@@ -229,16 +229,15 @@ impl<'a, 'tcx> DocFolder for CacheBuilder<'a, 'tcx> {
}
// Collect all the implementors of traits.
- if let clean::ImplItem(ref i) = *item.kind {
- if let Some(trait_) = &i.trait_ {
- if !i.kind.is_blanket() {
- self.cache
- .implementors
- .entry(trait_.def_id())
- .or_default()
- .push(Impl { impl_item: item.clone() });
- }
- }
+ if let clean::ImplItem(ref i) = *item.kind &&
+ let Some(trait_) = &i.trait_ &&
+ !i.kind.is_blanket()
+ {
+ self.cache
+ .implementors
+ .entry(trait_.def_id())
+ .or_default()
+ .push(Impl { impl_item: item.clone() });
}
// Index this method for searching later on.
@@ -288,6 +287,16 @@ impl<'a, 'tcx> DocFolder for CacheBuilder<'a, 'tcx> {
} else {
let last = self.cache.parent_stack.last().expect("parent_stack is empty 2");
let did = match &*last {
+ ParentStackItem::Impl {
+ // impl Trait for &T { fn method(self); }
+ //
+ // When generating a function index with the above shape, we want it
+ // associated with `T`, not with the primitive reference type. It should
+ // show up as `T::method`, rather than `reference::method`, in the search
+ // results page.
+ for_: clean::Type::BorrowedRef { type_, .. },
+ ..
+ } => type_.def_id(&self.cache),
ParentStackItem::Impl { for_, .. } => for_.def_id(&self.cache),
ParentStackItem::Type(item_id) => item_id.as_def_id(),
};
@@ -454,7 +463,7 @@ impl<'a, 'tcx> DocFolder for CacheBuilder<'a, 'tcx> {
| clean::BorrowedRef { type_: box clean::Type::Path { ref path }, .. } => {
dids.insert(path.def_id());
if let Some(generics) = path.generics() &&
- let ty::Adt(adt, _) = self.tcx.type_of(path.def_id()).kind() &&
+ let ty::Adt(adt, _) = self.tcx.type_of(path.def_id()).subst_identity().kind() &&
adt.is_fundamental() {
for ty in generics {
if let Some(did) = ty.def_id(self.cache) {
diff --git a/src/librustdoc/formats/item_type.rs b/src/librustdoc/formats/item_type.rs
index 2f1f4cbf3..452e14918 100644
--- a/src/librustdoc/formats/item_type.rs
+++ b/src/librustdoc/formats/item_type.rs
@@ -21,6 +21,7 @@ use crate::clean;
/// a heading, edit the listing in `html/render.rs`, function `sidebar_module`. This uses an
/// ordering based on a helper function inside `item_module`, in the same file.
#[derive(Copy, PartialEq, Eq, Hash, Clone, Debug, PartialOrd, Ord)]
+#[repr(u8)]
pub(crate) enum ItemType {
Module = 0,
ExternCrate = 1,
@@ -139,7 +140,7 @@ impl From<DefKind> for ItemType {
| DefKind::Field
| DefKind::LifetimeParam
| DefKind::GlobalAsm
- | DefKind::Impl
+ | DefKind::Impl { .. }
| DefKind::Closure
| DefKind::Generator => Self::ForeignType,
}
diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs
index d3dc4065d..0e4c5ed68 100644
--- a/src/librustdoc/html/format.rs
+++ b/src/librustdoc/html/format.rs
@@ -34,6 +34,7 @@ use crate::clean::{
use crate::formats::item_type::ItemType;
use crate::html::escape::Escape;
use crate::html::render::Context;
+use crate::passes::collect_intra_doc_links::UrlFragment;
use super::url_parts_builder::estimate_item_path_byte_length;
use super::url_parts_builder::UrlPartsBuilder;
@@ -208,7 +209,7 @@ impl clean::GenericParamDef {
if f.alternate() {
write!(f, ": {:#}", print_generic_bounds(bounds, cx))?;
} else {
- write!(f, ":&nbsp;{}", print_generic_bounds(bounds, cx))?;
+ write!(f, ": {}", print_generic_bounds(bounds, cx))?;
}
}
@@ -216,7 +217,7 @@ impl clean::GenericParamDef {
if f.alternate() {
write!(f, " = {:#}", ty.print(cx))?;
} else {
- write!(f, "&nbsp;=&nbsp;{}", ty.print(cx))?;
+ write!(f, " = {}", ty.print(cx))?;
}
}
@@ -226,14 +227,14 @@ impl clean::GenericParamDef {
if f.alternate() {
write!(f, "const {}: {:#}", self.name, ty.print(cx))?;
} else {
- write!(f, "const {}:&nbsp;{}", self.name, ty.print(cx))?;
+ write!(f, "const {}: {}", self.name, ty.print(cx))?;
}
if let Some(default) = default {
if f.alternate() {
write!(f, " = {:#}", default)?;
} else {
- write!(f, "&nbsp;=&nbsp;{}", default)?;
+ write!(f, " = {}", default)?;
}
}
@@ -289,7 +290,7 @@ pub(crate) fn print_where_clause<'a, 'tcx: 'a>(
if f.alternate() {
f.write_str(" ")?;
} else {
- f.write_str("<br>")?;
+ f.write_str("\n")?;
}
match pred {
@@ -352,23 +353,31 @@ pub(crate) fn print_where_clause<'a, 'tcx: 'a>(
}
} else {
let mut br_with_padding = String::with_capacity(6 * indent + 28);
- br_with_padding.push_str("<br>");
- for _ in 0..indent + 4 {
- br_with_padding.push_str("&nbsp;");
+ br_with_padding.push_str("\n");
+
+ let padding_amout =
+ if ending == Ending::Newline { indent + 4 } else { indent + "fn where ".len() };
+
+ for _ in 0..padding_amout {
+ br_with_padding.push_str(" ");
}
- let where_preds = where_preds.to_string().replace("<br>", &br_with_padding);
+ let where_preds = where_preds.to_string().replace('\n', &br_with_padding);
if ending == Ending::Newline {
- let mut clause = "&nbsp;".repeat(indent.saturating_sub(1));
+ let mut clause = " ".repeat(indent.saturating_sub(1));
write!(clause, "<span class=\"where fmt-newline\">where{where_preds},</span>")?;
clause
} else {
- // insert a <br> tag after a single space but before multiple spaces at the start
+ // insert a newline after a single space but before multiple spaces at the start
if indent == 0 {
- format!("<br><span class=\"where\">where{where_preds}</span>")
+ format!("\n<span class=\"where\">where{where_preds}</span>")
} else {
+ // put the first one on the same line as the 'where' keyword
+ let where_preds = where_preds.replacen(&br_with_padding, " ", 1);
+
let mut clause = br_with_padding;
- clause.truncate(clause.len() - 4 * "&nbsp;".len());
+ clause.truncate(clause.len() - "where ".len());
+
write!(clause, "<span class=\"where\">where{where_preds}</span>")?;
clause
}
@@ -701,11 +710,9 @@ pub(crate) fn href_with_root_path(
}
}
};
- if !is_remote {
- if let Some(root_path) = root_path {
- let root = root_path.trim_end_matches('/');
- url_parts.push_front(root);
- }
+ if !is_remote && let Some(root_path) = root_path {
+ let root = root_path.trim_end_matches('/');
+ url_parts.push_front(root);
}
debug!(?url_parts);
match shortty {
@@ -760,6 +767,28 @@ pub(crate) fn href_relative_parts<'fqp>(
}
}
+pub(crate) fn link_tooltip(did: DefId, fragment: &Option<UrlFragment>, cx: &Context<'_>) -> String {
+ let cache = cx.cache();
+ let Some((fqp, shortty)) = cache.paths.get(&did)
+ .or_else(|| cache.external_paths.get(&did))
+ else { return String::new() };
+ let mut buf = Buffer::new();
+ if let &Some(UrlFragment::Item(id)) = fragment {
+ write!(buf, "{} ", cx.tcx().def_descr(id));
+ for component in fqp {
+ write!(buf, "{component}::");
+ }
+ write!(buf, "{}", cx.tcx().item_name(id));
+ } else if !fqp.is_empty() {
+ let mut fqp_it = fqp.into_iter();
+ write!(buf, "{shortty} {}", fqp_it.next().unwrap());
+ for component in fqp_it {
+ write!(buf, "::{component}");
+ }
+ }
+ buf.into_inner()
+}
+
/// Used to render a [`clean::Path`].
fn resolved_path<'cx>(
w: &mut fmt::Formatter<'_>,
@@ -1064,14 +1093,8 @@ fn fmt_type<'cx>(
fmt_type(ty, f, use_absolute, cx)?;
write!(f, ")")
}
- clean::Generic(..) => {
- primitive_link(
- f,
- PrimitiveType::Reference,
- &format!("{}{}{}", amp, lt, m),
- cx,
- )?;
- fmt_type(ty, f, use_absolute, cx)
+ clean::Generic(name) => {
+ primitive_link(f, PrimitiveType::Reference, &format!("{amp}{lt}{m}{name}"), cx)
}
_ => {
write!(f, "{}{}{}", amp, lt, m)?;
@@ -1313,7 +1336,8 @@ impl clean::FnDecl {
/// * `header_len`: The length of the function header and name. In other words, the number of
/// characters in the function declaration up to but not including the parentheses.
- /// <br>Used to determine line-wrapping.
+ /// This is expected to go into a `<pre>`/`code-header` block, so indentation and newlines
+ /// are preserved.
/// * `indent`: The number of spaces to indent each successive line with, if line-wrapping is
/// necessary.
pub(crate) fn full_print<'a, 'tcx: 'a>(
@@ -1361,7 +1385,7 @@ impl clean::FnDecl {
}
} else {
if i > 0 {
- args.push_str("<br>");
+ args.push_str("\n");
}
if input.is_const {
args.push_str("const ");
@@ -1387,7 +1411,7 @@ impl clean::FnDecl {
let mut args = args.into_inner();
if self.c_variadic {
- args.push_str(",<br> ...");
+ args.push_str(",\n ...");
args_plain.push_str(", ...");
}
@@ -1397,24 +1421,20 @@ impl clean::FnDecl {
let declaration_len = header_len + args_plain.len() + arrow_plain.len();
let output = if declaration_len > 80 {
- let full_pad = format!("<br>{}", "&nbsp;".repeat(indent + 4));
- let close_pad = format!("<br>{}", "&nbsp;".repeat(indent));
+ let full_pad = format!("\n{}", " ".repeat(indent + 4));
+ let close_pad = format!("\n{}", " ".repeat(indent));
format!(
"({pad}{args}{close}){arrow}",
pad = if self.inputs.values.is_empty() { "" } else { &full_pad },
- args = args.replace("<br>", &full_pad),
+ args = args.replace('\n', &full_pad),
close = close_pad,
arrow = arrow
)
} else {
- format!("({args}){arrow}", args = args.replace("<br>", " "), arrow = arrow)
+ format!("({args}){arrow}", args = args.replace('\n', " "), arrow = arrow)
};
- if f.alternate() {
- write!(f, "{}", output.replace("<br>", "\n"))
- } else {
- write!(f, "{}", output)
- }
+ write!(f, "{}", output)
}
}
@@ -1617,7 +1637,7 @@ impl clean::TypeBinding {
if f.alternate() {
write!(f, ": {:#}", print_generic_bounds(bounds, cx))?;
} else {
- write!(f, ":&nbsp;{}", print_generic_bounds(bounds, cx))?;
+ write!(f, ": {}", print_generic_bounds(bounds, cx))?;
}
}
}
diff --git a/src/librustdoc/html/highlight.rs b/src/librustdoc/html/highlight.rs
index 8a9e6caf6..2c9fc4e3c 100644
--- a/src/librustdoc/html/highlight.rs
+++ b/src/librustdoc/html/highlight.rs
@@ -58,11 +58,11 @@ pub(crate) fn render_example_with_highlighting(
write_footer(out, playground_button);
}
-/// Highlights `src` as a macro, returning the HTML output.
-pub(crate) fn render_macro_with_highlighting(src: &str, out: &mut Buffer) {
- write_header(out, "macro", None, Tooltip::None);
+/// Highlights `src` as an item-decl, returning the HTML output.
+pub(crate) fn render_item_decl_with_highlighting(src: &str, out: &mut Buffer) {
+ write!(out, "<pre class=\"rust item-decl\">");
write_code(out, src, None, None);
- write_footer(out, None);
+ write!(out, "</pre>");
}
/// Highlights `src` as a source code page, returning the HTML output.
@@ -96,13 +96,19 @@ fn write_header(out: &mut Buffer, class: &str, extra_content: Option<Buffer>, to
);
if tooltip != Tooltip::None {
+ let edition_code;
write!(
out,
- "<div class='tooltip'{}>ⓘ</div>",
- if let Tooltip::Edition(edition_info) = tooltip {
- format!(" data-edition=\"{}\"", edition_info)
- } else {
- String::new()
+ "<a href=\"#\" class=\"tooltip\" title=\"{}\">ⓘ</a>",
+ match tooltip {
+ Tooltip::Ignore => "This example is not tested",
+ Tooltip::CompileFail => "This example deliberately fails to compile",
+ Tooltip::ShouldPanic => "This example panics",
+ Tooltip::Edition(edition) => {
+ edition_code = format!("This example runs with edition {edition}");
+ &edition_code
+ }
+ Tooltip::None => unreachable!(),
},
);
}
@@ -460,10 +466,8 @@ impl<'a> PeekIter<'a> {
}
/// Returns the next item after the current one. It doesn't interfere 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);
- }
+ if self.stored.is_empty() && let Some(next) = self.iter.next() {
+ self.stored.push_back(next);
}
self.stored.front()
}
diff --git a/src/librustdoc/html/layout.rs b/src/librustdoc/html/layout.rs
index a60e7cb10..6ab849c92 100644
--- a/src/librustdoc/html/layout.rs
+++ b/src/librustdoc/html/layout.rs
@@ -30,7 +30,6 @@ pub(crate) struct Page<'a> {
pub(crate) root_path: &'a str,
pub(crate) static_root_path: Option<&'a str>,
pub(crate) description: &'a str,
- pub(crate) keywords: &'a str,
pub(crate) resource_suffix: &'a str,
}
diff --git a/src/librustdoc/html/length_limit.rs b/src/librustdoc/html/length_limit.rs
index bbdc91c8d..4c8db2c67 100644
--- a/src/librustdoc/html/length_limit.rs
+++ b/src/librustdoc/html/length_limit.rs
@@ -61,14 +61,14 @@ impl HtmlWithLimit {
/// and returns [`ControlFlow::Break`].
pub(super) fn push(&mut self, text: &str) -> ControlFlow<(), ()> {
if self.len + text.len() > self.limit {
- return ControlFlow::BREAK;
+ return ControlFlow::Break(());
}
self.flush_queue();
write!(self.buf, "{}", Escape(text)).unwrap();
self.len += text.len();
- ControlFlow::CONTINUE
+ ControlFlow::Continue(())
}
/// Open an HTML tag.
diff --git a/src/librustdoc/html/length_limit/tests.rs b/src/librustdoc/html/length_limit/tests.rs
index 2d02b8a16..2185c0348 100644
--- a/src/librustdoc/html/length_limit/tests.rs
+++ b/src/librustdoc/html/length_limit/tests.rs
@@ -83,7 +83,7 @@ fn past_the_limit() {
buf.push("word#")?;
buf.push(&n.to_string())?;
buf.close_tag();
- ControlFlow::CONTINUE
+ ControlFlow::Continue(())
});
buf.close_tag();
assert_eq!(
diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs
index 4ff67fe15..fe446ae3c 100644
--- a/src/librustdoc/html/markdown.rs
+++ b/src/librustdoc/html/markdown.rs
@@ -27,14 +27,14 @@
use rustc_data_structures::fx::FxHashMap;
use rustc_hir::def_id::DefId;
-use rustc_hir::HirId;
use rustc_middle::ty::TyCtxt;
+pub(crate) use rustc_resolve::rustdoc::main_body_opts;
+use rustc_resolve::rustdoc::may_be_doc_link;
use rustc_span::edition::Edition;
use rustc_span::{Span, Symbol};
use once_cell::sync::Lazy;
use std::borrow::Cow;
-use std::cell::RefCell;
use std::collections::VecDeque;
use std::default::Default;
use std::fmt::Write;
@@ -47,6 +47,7 @@ use crate::html::escape::Escape;
use crate::html::format::Buffer;
use crate::html::highlight;
use crate::html::length_limit::HtmlWithLimit;
+use crate::html::render::small_url_encode;
use crate::html::toc::TocBuilder;
use pulldown_cmark::{
@@ -58,15 +59,6 @@ mod tests;
const MAX_HEADER_LEVEL: u32 = 6;
-/// Options for rendering Markdown in the main body of documentation.
-pub(crate) fn main_body_opts() -> Options {
- Options::ENABLE_TABLES
- | Options::ENABLE_FOOTNOTES
- | Options::ENABLE_STRIKETHROUGH
- | Options::ENABLE_TASKLISTS
- | Options::ENABLE_SMART_PUNCTUATION
-}
-
/// Options for rendering Markdown in summaries (e.g., in search results).
pub(crate) fn summary_opts() -> Options {
Options::ENABLE_TABLES
@@ -103,14 +95,14 @@ pub struct Markdown<'a> {
/// E.g. if `heading_offset: HeadingOffset::H2`, then `# something` renders an `<h2>`.
pub heading_offset: HeadingOffset,
}
-/// A tuple struct like `Markdown` that renders the markdown with a table of contents.
-pub(crate) struct MarkdownWithToc<'a>(
- pub(crate) &'a str,
- pub(crate) &'a mut IdMap,
- pub(crate) ErrorCodes,
- pub(crate) Edition,
- pub(crate) &'a Option<Playground>,
-);
+/// A struct like `Markdown` that renders the markdown with a table of contents.
+pub(crate) struct MarkdownWithToc<'a> {
+ pub(crate) content: &'a str,
+ pub(crate) ids: &'a mut IdMap,
+ pub(crate) error_codes: ErrorCodes,
+ pub(crate) edition: Edition,
+ pub(crate) playground: &'a Option<Playground>,
+}
/// A tuple struct like `Markdown` that renders the markdown escaping HTML tags
/// and includes no paragraph tags.
pub(crate) struct MarkdownItemInfo<'a>(pub(crate) &'a str, pub(crate) &'a mut IdMap);
@@ -295,30 +287,7 @@ impl<'a, I: Iterator<Item = Event<'a>>> Iterator for CodeBlocks<'_, 'a, I> {
doctest::make_test(&test, krate, false, &Default::default(), edition, None);
let channel = if test.contains("#![feature(") { "&amp;version=nightly" } else { "" };
- // These characters don't need to be escaped in a URI.
- // FIXME: use a library function for percent encoding.
- fn dont_escape(c: u8) -> bool {
- (b'a' <= c && c <= b'z')
- || (b'A' <= c && c <= b'Z')
- || (b'0' <= c && c <= b'9')
- || c == b'-'
- || c == b'_'
- || c == b'.'
- || c == b'~'
- || c == b'!'
- || c == b'\''
- || c == b'('
- || c == b')'
- || c == b'*'
- }
- let mut test_escaped = String::new();
- for b in test.bytes() {
- if dont_escape(b) {
- test_escaped.push(char::from(b));
- } else {
- write!(test_escaped, "%{:02X}", b).unwrap();
- }
- }
+ let test_escaped = small_url_encode(test);
Some(format!(
r#"<a class="test-arrow" target="_blank" href="{}?code={}{}&amp;edition={}">Run</a>"#,
url, test_escaped, channel, edition,
@@ -391,6 +360,9 @@ impl<'a, I: Iterator<Item = Event<'a>>> Iterator for LinkReplacer<'a, I> {
trace!("it matched");
assert!(self.shortcut_link.is_none(), "shortcut links cannot be nested");
self.shortcut_link = Some(link);
+ if title.is_empty() && !link.tooltip.is_empty() {
+ *title = CowStr::Borrowed(link.tooltip.as_ref());
+ }
}
}
// Now that we're done with the shortcut link, don't replace any more text.
@@ -441,9 +413,12 @@ impl<'a, I: Iterator<Item = Event<'a>>> Iterator for LinkReplacer<'a, I> {
}
// If this is a link, but not a shortcut link,
// replace the URL, since the broken_link_callback was not called.
- Some(Event::Start(Tag::Link(_, dest, _))) => {
+ Some(Event::Start(Tag::Link(_, dest, title))) => {
if let Some(link) = self.links.iter().find(|&link| *link.original_text == **dest) {
*dest = CowStr::Borrowed(link.href.as_ref());
+ if title.is_empty() && !link.tooltip.is_empty() {
+ *title = CowStr::Borrowed(link.tooltip.as_ref());
+ }
}
}
// Anything else couldn't have been a valid Rust path, so no need to replace the text.
@@ -577,10 +552,7 @@ impl<'a, I: Iterator<Item = Event<'a>>> SummaryLine<'a, I> {
}
fn check_if_allowed_tag(t: &Tag<'_>) -> bool {
- matches!(
- t,
- Tag::Paragraph | Tag::Item | Tag::Emphasis | Tag::Strong | Tag::Link(..) | Tag::BlockQuote
- )
+ matches!(t, Tag::Paragraph | Tag::Emphasis | Tag::Strong | Tag::Link(..) | Tag::BlockQuote)
}
fn is_forbidden_tag(t: &Tag<'_>) -> bool {
@@ -771,11 +743,7 @@ pub(crate) fn find_testable_code<T: doctest::Tester>(
}
Event::Text(ref s) if register_header.is_some() => {
let level = register_header.unwrap();
- if s.is_empty() {
- tests.register_header("", level);
- } else {
- tests.register_header(s, level);
- }
+ tests.register_header(s, level);
register_header = None;
}
_ => {}
@@ -784,45 +752,26 @@ pub(crate) fn find_testable_code<T: doctest::Tester>(
}
pub(crate) struct ExtraInfo<'tcx> {
- id: ExtraInfoId,
+ def_id: DefId,
sp: Span,
tcx: TyCtxt<'tcx>,
}
-enum ExtraInfoId {
- Hir(HirId),
- Def(DefId),
-}
-
impl<'tcx> ExtraInfo<'tcx> {
- pub(crate) fn new(tcx: TyCtxt<'tcx>, hir_id: HirId, sp: Span) -> ExtraInfo<'tcx> {
- ExtraInfo { id: ExtraInfoId::Hir(hir_id), sp, tcx }
- }
-
- pub(crate) fn new_did(tcx: TyCtxt<'tcx>, did: DefId, sp: Span) -> ExtraInfo<'tcx> {
- ExtraInfo { id: ExtraInfoId::Def(did), sp, tcx }
+ pub(crate) fn new(tcx: TyCtxt<'tcx>, def_id: DefId, sp: Span) -> ExtraInfo<'tcx> {
+ ExtraInfo { def_id, sp, tcx }
}
fn error_invalid_codeblock_attr(&self, msg: &str, help: &str) {
- let hir_id = match self.id {
- ExtraInfoId::Hir(hir_id) => hir_id,
- ExtraInfoId::Def(item_did) => {
- match item_did.as_local() {
- Some(item_did) => self.tcx.hir().local_def_id_to_hir_id(item_did),
- None => {
- // If non-local, no need to check anything.
- return;
- }
- }
- }
- };
- self.tcx.struct_span_lint_hir(
- crate::lint::INVALID_CODEBLOCK_ATTRIBUTES,
- hir_id,
- self.sp,
- msg,
- |lint| lint.help(help),
- );
+ if let Some(def_id) = self.def_id.as_local() {
+ self.tcx.struct_span_lint_hir(
+ crate::lint::INVALID_CODEBLOCK_ATTRIBUTES,
+ self.tcx.hir().local_def_id_to_hir_id(def_id),
+ self.sp,
+ msg,
+ |lint| lint.help(help),
+ );
+ }
}
}
@@ -1029,8 +978,8 @@ impl Markdown<'_> {
let mut replacer = |broken_link: BrokenLink<'_>| {
links
.iter()
- .find(|link| link.original_text.as_str() == &*broken_link.reference)
- .map(|link| (link.href.as_str().into(), link.new_text.as_str().into()))
+ .find(|link| &*link.original_text == &*broken_link.reference)
+ .map(|link| (link.href.as_str().into(), link.tooltip.as_str().into()))
};
let p = Parser::new_with_broken_link_callback(md, main_body_opts(), Some(&mut replacer));
@@ -1051,7 +1000,7 @@ impl Markdown<'_> {
impl MarkdownWithToc<'_> {
pub(crate) fn into_string(self) -> String {
- let MarkdownWithToc(md, ids, codes, edition, playground) = self;
+ let MarkdownWithToc { content: md, ids, error_codes: codes, edition, playground } = self;
let p = Parser::new_ext(md, main_body_opts()).into_offset_iter();
@@ -1112,8 +1061,8 @@ impl MarkdownSummaryLine<'_> {
let mut replacer = |broken_link: BrokenLink<'_>| {
links
.iter()
- .find(|link| link.original_text.as_str() == &*broken_link.reference)
- .map(|link| (link.href.as_str().into(), link.new_text.as_str().into()))
+ .find(|link| &*link.original_text == &*broken_link.reference)
+ .map(|link| (link.href.as_str().into(), link.tooltip.as_str().into()))
};
let p = Parser::new_with_broken_link_callback(md, summary_opts(), Some(&mut replacer))
@@ -1159,8 +1108,8 @@ fn markdown_summary_with_limit(
let mut replacer = |broken_link: BrokenLink<'_>| {
link_names
.iter()
- .find(|link| link.original_text.as_str() == &*broken_link.reference)
- .map(|link| (link.href.as_str().into(), link.new_text.as_str().into()))
+ .find(|link| &*link.original_text == &*broken_link.reference)
+ .map(|link| (link.href.as_str().into(), link.tooltip.as_str().into()))
};
let p = Parser::new_with_broken_link_callback(md, summary_opts(), Some(&mut replacer));
@@ -1191,18 +1140,18 @@ fn markdown_summary_with_limit(
Event::Start(tag) => match tag {
Tag::Emphasis => buf.open_tag("em"),
Tag::Strong => buf.open_tag("strong"),
- Tag::CodeBlock(..) => return ControlFlow::BREAK,
+ Tag::CodeBlock(..) => return ControlFlow::Break(()),
_ => {}
},
Event::End(tag) => match tag {
Tag::Emphasis | Tag::Strong => buf.close_tag(),
- Tag::Paragraph | Tag::Heading(..) => return ControlFlow::BREAK,
+ Tag::Paragraph | Tag::Heading(..) => return ControlFlow::Break(()),
_ => {}
},
Event::HardBreak | Event::SoftBreak => buf.push(" ")?,
_ => {}
};
- ControlFlow::CONTINUE
+ ControlFlow::Continue(())
});
(buf.finish(), stopped_early)
@@ -1230,14 +1179,23 @@ pub(crate) fn short_markdown_summary(markdown: &str, link_names: &[RenderedLink]
/// - Headings, links, and formatting are stripped.
/// - Inline code is rendered as-is, surrounded by backticks.
/// - HTML and code blocks are ignored.
-pub(crate) fn plain_text_summary(md: &str) -> String {
+pub(crate) fn plain_text_summary(md: &str, link_names: &[RenderedLink]) -> String {
if md.is_empty() {
return String::new();
}
let mut s = String::with_capacity(md.len() * 3 / 2);
- for event in Parser::new_ext(md, summary_opts()) {
+ let mut replacer = |broken_link: BrokenLink<'_>| {
+ link_names
+ .iter()
+ .find(|link| &*link.original_text == &*broken_link.reference)
+ .map(|link| (link.href.as_str().into(), link.tooltip.as_str().into()))
+ };
+
+ let p = Parser::new_with_broken_link_callback(md, summary_opts(), Some(&mut replacer));
+
+ for event in p {
match &event {
Event::Text(text) => s.push_str(text),
Event::Code(code) => {
@@ -1265,14 +1223,12 @@ pub(crate) struct MarkdownLink {
pub(crate) fn markdown_links<R>(
md: &str,
- filter_map: impl Fn(MarkdownLink) -> Option<R>,
+ preprocess_link: impl Fn(MarkdownLink) -> Option<R>,
) -> Vec<R> {
if md.is_empty() {
return vec![];
}
- let links = RefCell::new(vec![]);
-
// FIXME: remove this function once pulldown_cmark can provide spans for link definitions.
let locate = |s: &str, fallback: Range<usize>| unsafe {
let s_start = s.as_ptr();
@@ -1304,46 +1260,23 @@ pub(crate) fn markdown_links<R>(
}
};
- let mut push = |link: BrokenLink<'_>| {
- let span = span_for_link(&link.reference, link.span);
- filter_map(MarkdownLink {
- kind: LinkType::ShortcutUnknown,
- link: link.reference.to_string(),
- range: span,
- })
- .map(|link| links.borrow_mut().push(link));
- None
- };
- 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, HeadingOffset::H1));
-
- for ev in iter {
- if let Event::Start(Tag::Link(
- // `<>` links cannot be intra-doc links so we skip them.
- kind @ (LinkType::Inline
- | LinkType::Reference
- | LinkType::ReferenceUnknown
- | LinkType::Collapsed
- | LinkType::CollapsedUnknown
- | LinkType::Shortcut
- | LinkType::ShortcutUnknown),
- dest,
- _,
- )) = ev.0
- {
- debug!("found link: {dest}");
- let span = span_for_link(&dest, ev.1);
- filter_map(MarkdownLink { kind, link: dest.into_string(), range: span })
- .map(|link| links.borrow_mut().push(link));
+ Parser::new_with_broken_link_callback(
+ md,
+ main_body_opts(),
+ Some(&mut |link: BrokenLink<'_>| Some((link.reference, "".into()))),
+ )
+ .into_offset_iter()
+ .filter_map(|(event, span)| match event {
+ Event::Start(Tag::Link(link_type, dest, _)) if may_be_doc_link(link_type) => {
+ preprocess_link(MarkdownLink {
+ kind: link_type,
+ range: span_for_link(&dest, span),
+ link: dest.into_string(),
+ })
}
- }
-
- links.into_inner()
+ _ => None,
+ })
+ .collect()
}
#[derive(Debug)]
diff --git a/src/librustdoc/html/markdown/tests.rs b/src/librustdoc/html/markdown/tests.rs
index 5878c5826..e05635a02 100644
--- a/src/librustdoc/html/markdown/tests.rs
+++ b/src/librustdoc/html/markdown/tests.rs
@@ -249,7 +249,7 @@ fn test_short_markdown_summary() {
#[test]
fn test_plain_text_summary() {
fn t(input: &str, expect: &str) {
- let output = plain_text_summary(input);
+ let output = plain_text_summary(input, &[]);
assert_eq!(output, expect, "original: {}", input);
}
diff --git a/src/librustdoc/html/render/context.rs b/src/librustdoc/html/render/context.rs
index 5cefe9475..5e4a59562 100644
--- a/src/librustdoc/html/render/context.rs
+++ b/src/librustdoc/html/render/context.rs
@@ -6,7 +6,7 @@ use std::rc::Rc;
use std::sync::mpsc::{channel, Receiver};
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
-use rustc_hir::def_id::{DefId, LOCAL_CRATE};
+use rustc_hir::def_id::{DefIdMap, LOCAL_CRATE};
use rustc_middle::ty::TyCtxt;
use rustc_session::Session;
use rustc_span::edition::Edition;
@@ -18,7 +18,7 @@ use super::search_index::build_index;
use super::write_shared::write_shared;
use super::{
collect_spans_and_sources, print_sidebar, scrape_examples_help, sidebar_module_like, AllTypes,
- LinkFromSrc, NameDoc, StylePath, BASIC_KEYWORDS,
+ LinkFromSrc, StylePath,
};
use crate::clean::{self, types::ExternalLocation, ExternalCrate};
@@ -56,7 +56,7 @@ pub(crate) struct Context<'tcx> {
pub(super) render_redirect_pages: bool,
/// Tracks section IDs for `Deref` targets so they match in both the main
/// body and the sidebar.
- pub(super) deref_id_map: FxHashMap<DefId, String>,
+ pub(super) deref_id_map: DefIdMap<String>,
/// The map used to ensure all generated 'id=' attributes are unique.
pub(super) id_map: IdMap,
/// Shared mutable state.
@@ -182,7 +182,10 @@ impl<'tcx> Context<'tcx> {
};
title.push_str(" - Rust");
let tyname = it.type_();
- let desc = it.doc_value().as_ref().map(|doc| plain_text_summary(doc));
+ let desc = it
+ .doc_value()
+ .as_ref()
+ .map(|doc| plain_text_summary(doc, &it.link_names(&self.cache())));
let desc = if let Some(desc) = desc {
desc
} else if it.is_crate() {
@@ -195,7 +198,6 @@ impl<'tcx> Context<'tcx> {
self.shared.layout.krate
)
};
- let keywords = make_item_keywords(it);
let name;
let tyname_s = if it.is_crate() {
name = format!("{} crate", tyname);
@@ -212,7 +214,6 @@ impl<'tcx> Context<'tcx> {
static_root_path: clone_shared.static_root_path.as_deref(),
title: &title,
description: &desc,
- keywords: &keywords,
resource_suffix: &clone_shared.resource_suffix,
};
let mut page_buffer = Buffer::html();
@@ -258,7 +259,7 @@ impl<'tcx> Context<'tcx> {
}
/// Construct a map of items shown in the sidebar to a plain-text summary of their docs.
- fn build_sidebar_items(&self, m: &clean::Module) -> BTreeMap<String, Vec<NameDoc>> {
+ fn build_sidebar_items(&self, m: &clean::Module) -> BTreeMap<String, Vec<String>> {
// BTreeMap instead of HashMap to get a sorted output
let mut map: BTreeMap<_, Vec<_>> = BTreeMap::new();
let mut inserted: FxHashMap<ItemType, FxHashSet<Symbol>> = FxHashMap::default();
@@ -276,10 +277,7 @@ impl<'tcx> Context<'tcx> {
if inserted.entry(short).or_default().insert(myname) {
let short = short.to_string();
let myname = myname.to_string();
- map.entry(short).or_default().push((
- myname,
- Some(item.doc_value().map_or_else(String::new, |s| plain_text_summary(&s))),
- ));
+ map.entry(short).or_default().push(myname);
}
}
@@ -544,7 +542,7 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> {
dst,
render_redirect_pages: false,
id_map,
- deref_id_map: FxHashMap::default(),
+ deref_id_map: Default::default(),
shared: Rc::new(scx),
include_sources,
types_with_notable_traits: FxHashSet::default(),
@@ -572,7 +570,7 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> {
current: self.current.clone(),
dst: self.dst.clone(),
render_redirect_pages: self.render_redirect_pages,
- deref_id_map: FxHashMap::default(),
+ deref_id_map: Default::default(),
id_map: IdMap::new(),
shared: Rc::clone(&self.shared),
include_sources: self.include_sources,
@@ -598,7 +596,6 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> {
root_path: "../",
static_root_path: shared.static_root_path.as_deref(),
description: "List of all items in this crate",
- keywords: BASIC_KEYWORDS,
resource_suffix: &shared.resource_suffix,
};
let all = shared.all.replace(AllTypes::new());
@@ -708,14 +705,12 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> {
shared.fs.write(scrape_examples_help_file, v)?;
}
- if let Some(ref redirections) = 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();
- shared.ensure_dir(&self.dst.join(crate_name.as_str()))?;
- shared.fs.write(redirect_map_path, paths)?;
- }
+ if let Some(ref redirections) = shared.redirections && !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();
+ shared.ensure_dir(&self.dst.join(crate_name.as_str()))?;
+ shared.fs.write(redirect_map_path, paths)?;
}
// No need for it anymore.
@@ -828,7 +823,3 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> {
&self.shared.cache
}
}
-
-fn make_item_keywords(it: &clean::Item) -> String {
- format!("{}, {}", BASIC_KEYWORDS, it.name.as_ref().unwrap())
-}
diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs
index 4fa33e890..e6a040d02 100644
--- a/src/librustdoc/html/render/mod.rs
+++ b/src/librustdoc/html/render/mod.rs
@@ -38,7 +38,7 @@ pub(crate) use self::span_map::{collect_spans_and_sources, LinkFromSrc};
use std::collections::VecDeque;
use std::default::Default;
-use std::fmt;
+use std::fmt::{self, Write};
use std::fs;
use std::iter::Peekable;
use std::path::PathBuf;
@@ -50,7 +50,7 @@ use rustc_ast_pretty::pprust;
use rustc_attr::{ConstStability, Deprecation, StabilityLevel};
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_hir::def::CtorKind;
-use rustc_hir::def_id::DefId;
+use rustc_hir::def_id::{DefId, DefIdSet};
use rustc_hir::Mutability;
use rustc_middle::middle::stability;
use rustc_middle::ty;
@@ -83,9 +83,6 @@ use crate::scrape_examples::{CallData, CallLocation};
use crate::try_none;
use crate::DOC_RUST_LANG_ORG_CHANNEL;
-/// A pair of name and its optional document.
-pub(crate) type NameDoc = (String, Option<String>);
-
pub(crate) fn ensure_trailing_slash(v: &str) -> impl fmt::Display + '_ {
crate::html::format::display_fn(move |f| {
if !v.ends_with('/') && !v.is_empty() { write!(f, "{}/", v) } else { f.write_str(v) }
@@ -1115,7 +1112,7 @@ fn render_assoc_items(
it: DefId,
what: AssocItemRender<'_>,
) {
- let mut derefs = FxHashSet::default();
+ let mut derefs = DefIdSet::default();
derefs.insert(it);
render_assoc_items_inner(w, cx, containing_item, it, what, &mut derefs)
}
@@ -1126,7 +1123,7 @@ fn render_assoc_items_inner(
containing_item: &clean::Item,
it: DefId,
what: AssocItemRender<'_>,
- derefs: &mut FxHashSet<DefId>,
+ derefs: &mut DefIdSet,
) {
info!("Documenting associated items of {:?}", containing_item.name);
let shared = Rc::clone(&cx.shared);
@@ -1215,7 +1212,7 @@ fn render_deref_methods(
impl_: &Impl,
container_item: &clean::Item,
deref_mut: bool,
- derefs: &mut FxHashSet<DefId>,
+ derefs: &mut DefIdSet,
) {
let cache = cx.cache();
let deref_type = impl_.inner_impl().trait_.as_ref().unwrap();
@@ -1313,7 +1310,7 @@ pub(crate) fn notable_traits_button(ty: &clean::Type, cx: &mut Context<'_>) -> O
if has_notable_trait {
cx.types_with_notable_traits.insert(ty.clone());
Some(format!(
- " <a href=\"#\" class=\"notable-traits\" data-ty=\"{ty}\">ⓘ</a>",
+ " <a href=\"#\" class=\"tooltip\" data-notable-ty=\"{ty}\">ⓘ</a>",
ty = Escape(&format!("{:#}", ty.print(cx))),
))
} else {
@@ -1528,11 +1525,7 @@ fn render_impl(
})
})
.map(|item| format!("{}.{}", item.type_(), name));
- write!(
- w,
- "<section id=\"{}\" class=\"{}{} has-srclink\">",
- id, item_type, in_trait_class,
- );
+ write!(w, "<section id=\"{}\" class=\"{}{}\">", id, item_type, in_trait_class,);
render_rightside(w, cx, item, containing_item, render_mode);
if trait_.is_some() {
// Anchors are only used on trait impls.
@@ -1554,11 +1547,7 @@ fn render_impl(
kind @ (clean::TyAssocConstItem(ty) | clean::AssocConstItem(ty, _)) => {
let source_id = format!("{}.{}", item_type, name);
let id = cx.derive_id(source_id.clone());
- write!(
- w,
- "<section id=\"{}\" class=\"{}{} has-srclink\">",
- id, item_type, in_trait_class
- );
+ write!(w, "<section id=\"{}\" class=\"{}{}\">", id, item_type, in_trait_class);
render_rightside(w, cx, item, containing_item, render_mode);
if trait_.is_some() {
// Anchors are only used on trait impls.
@@ -1606,11 +1595,7 @@ fn render_impl(
clean::AssocTypeItem(tydef, _bounds) => {
let source_id = format!("{}.{}", item_type, name);
let id = cx.derive_id(source_id.clone());
- write!(
- w,
- "<section id=\"{}\" class=\"{}{} has-srclink\">",
- id, item_type, in_trait_class
- );
+ write!(w, "<section id=\"{}\" class=\"{}{}\">", id, item_type, in_trait_class);
if trait_.is_some() {
// Anchors are only used on trait impls.
write!(w, "<a href=\"#{}\" class=\"anchor\">§</a>", id);
@@ -1844,7 +1829,7 @@ pub(crate) fn render_impl_summary(
} else {
format!(" data-aliases=\"{}\"", aliases.join(","))
};
- write!(w, "<section id=\"{}\" class=\"impl has-srclink\"{}>", id, aliases);
+ write!(w, "<section id=\"{}\" class=\"impl\"{}>", id, aliases);
render_rightside(w, cx, &i.impl_item, containing_item, RenderMode::Normal);
write!(w, "<a href=\"#{}\" class=\"anchor\">§</a>", id);
write!(w, "<h3 class=\"code-header\">");
@@ -2032,31 +2017,60 @@ fn get_associated_constants(
.collect::<Vec<_>>()
}
-// The point is to url encode any potential character from a type with genericity.
-fn small_url_encode(s: String) -> String {
+pub(crate) fn small_url_encode(s: String) -> String {
+ // These characters don't need to be escaped in a URI.
+ // See https://url.spec.whatwg.org/#query-percent-encode-set
+ // and https://url.spec.whatwg.org/#urlencoded-parsing
+ // and https://url.spec.whatwg.org/#url-code-points
+ fn dont_escape(c: u8) -> bool {
+ (b'a' <= c && c <= b'z')
+ || (b'A' <= c && c <= b'Z')
+ || (b'0' <= c && c <= b'9')
+ || c == b'-'
+ || c == b'_'
+ || c == b'.'
+ || c == b','
+ || c == b'~'
+ || c == b'!'
+ || c == b'\''
+ || c == b'('
+ || c == b')'
+ || c == b'*'
+ || c == b'/'
+ || c == b';'
+ || c == b':'
+ || c == b'?'
+ // As described in urlencoded-parsing, the
+ // first `=` is the one that separates key from
+ // value. Following `=`s are part of the value.
+ || c == b'='
+ }
let mut st = String::new();
let mut last_match = 0;
- for (idx, c) in s.char_indices() {
- let escaped = match c {
- '<' => "%3C",
- '>' => "%3E",
- ' ' => "%20",
- '?' => "%3F",
- '\'' => "%27",
- '&' => "%26",
- ',' => "%2C",
- ':' => "%3A",
- ';' => "%3B",
- '[' => "%5B",
- ']' => "%5D",
- '"' => "%22",
- _ => continue,
- };
+ for (idx, b) in s.bytes().enumerate() {
+ if dont_escape(b) {
+ continue;
+ }
- st += &s[last_match..idx];
- st += escaped;
- // NOTE: we only expect single byte characters here - which is fine as long as we
- // only match single byte characters
+ if last_match != idx {
+ // Invariant: `idx` must be the first byte in a character at this point.
+ st += &s[last_match..idx];
+ }
+ if b == b' ' {
+ // URL queries are decoded with + replaced with SP.
+ // While the same is not true for hashes, rustdoc only needs to be
+ // consistent with itself when encoding them.
+ st += "+";
+ } else if b == b'%' {
+ st += "%%";
+ } else {
+ write!(st, "%{:02X}", b).unwrap();
+ }
+ // Invariant: if the current byte is not at the start of a multi-byte character,
+ // we need to get down here so that when the next turn of the loop comes around,
+ // last_match winds up equalling idx.
+ //
+ // In other words, dont_escape must always return `false` in multi-byte character.
last_match = idx + 1;
}
@@ -2175,7 +2189,7 @@ fn sidebar_assoc_items(cx: &Context<'_>, out: &mut Buffer, it: &clean::Item) {
if let Some(impl_) =
v.iter().find(|i| i.trait_did() == cx.tcx().lang_items().deref_trait())
{
- let mut derefs = FxHashSet::default();
+ let mut derefs = DefIdSet::default();
derefs.insert(did);
sidebar_deref_methods(cx, out, impl_, v, &mut derefs, &mut used_links);
}
@@ -2195,7 +2209,7 @@ fn sidebar_deref_methods(
out: &mut Buffer,
impl_: &Impl,
v: &[Impl],
- derefs: &mut FxHashSet<DefId>,
+ derefs: &mut DefIdSet,
used_links: &mut FxHashSet<String>,
) {
let c = cx.cache();
@@ -2211,14 +2225,13 @@ fn sidebar_deref_methods(
})
{
debug!("found target, real_target: {:?} {:?}", target, real_target);
- if let Some(did) = target.def_id(c) {
- if let Some(type_did) = impl_.inner_impl().for_.def_id(c) {
- // `impl Deref<Target = S> for S`
- if did == type_did || !derefs.insert(did) {
- // Avoid infinite cycles
- return;
- }
- }
+ if let Some(did) = target.def_id(c) &&
+ let Some(type_did) = impl_.inner_impl().for_.def_id(c) &&
+ // `impl Deref<Target = S> for S`
+ (did == type_did || !derefs.insert(did))
+ {
+ // Avoid infinite cycles
+ return;
}
let deref_mut = v.iter().any(|i| i.trait_did() == cx.tcx().lang_items().deref_mut_trait());
let inner_impl = target
@@ -2252,25 +2265,24 @@ fn sidebar_deref_methods(
}
// Recurse into any further impls that might exist for `target`
- if let Some(target_did) = target.def_id(c) {
- if let Some(target_impls) = c.impls.get(&target_did) {
- if let Some(target_deref_impl) = target_impls.iter().find(|i| {
- i.inner_impl()
- .trait_
- .as_ref()
- .map(|t| Some(t.def_id()) == cx.tcx().lang_items().deref_trait())
- .unwrap_or(false)
- }) {
- sidebar_deref_methods(
- cx,
- out,
- target_deref_impl,
- target_impls,
- derefs,
- used_links,
- );
- }
- }
+ if let Some(target_did) = target.def_id(c) &&
+ let Some(target_impls) = c.impls.get(&target_did) &&
+ let Some(target_deref_impl) = target_impls.iter().find(|i| {
+ i.inner_impl()
+ .trait_
+ .as_ref()
+ .map(|t| Some(t.def_id()) == cx.tcx().lang_items().deref_trait())
+ .unwrap_or(false)
+ })
+ {
+ sidebar_deref_methods(
+ cx,
+ out,
+ target_deref_impl,
+ target_impls,
+ derefs,
+ used_links,
+ );
}
}
}
@@ -2755,8 +2767,6 @@ fn sidebar_foreign_type(cx: &Context<'_>, buf: &mut Buffer, it: &clean::Item) {
}
}
-pub(crate) const BASIC_KEYWORDS: &str = "rust, rustlang, rust-lang";
-
/// Returns a list of all paths used in the type.
/// This is used to help deduplicate imported impls
/// for reexported types. If any of the contained
diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs
index f824c9e3a..2869a3961 100644
--- a/src/librustdoc/html/render/print_item.rs
+++ b/src/librustdoc/html/render/print_item.rs
@@ -10,7 +10,7 @@ use rustc_middle::ty::layout::LayoutError;
use rustc_middle::ty::{self, Adt, TyCtxt};
use rustc_span::hygiene::MacroKind;
use rustc_span::symbol::{kw, sym, Symbol};
-use rustc_target::abi::{LayoutS, Primitive, TagEncoding, VariantIdx, Variants};
+use rustc_target::abi::{LayoutS, Primitive, TagEncoding, Variants};
use std::cmp::Ordering;
use std::fmt;
use std::rc::Rc;
@@ -39,10 +39,10 @@ use crate::html::{highlight, static_files};
use askama::Template;
use itertools::Itertools;
-const ITEM_TABLE_OPEN: &str = "<div class=\"item-table\">";
-const ITEM_TABLE_CLOSE: &str = "</div>";
-const ITEM_TABLE_ROW_OPEN: &str = "<div class=\"item-row\">";
-const ITEM_TABLE_ROW_CLOSE: &str = "</div>";
+const ITEM_TABLE_OPEN: &str = "<ul class=\"item-table\">";
+const ITEM_TABLE_CLOSE: &str = "</ul>";
+const ITEM_TABLE_ROW_OPEN: &str = "<li>";
+const ITEM_TABLE_ROW_CLOSE: &str = "</li>";
// A component in a `use` path, like `string` in std::string::ToString
struct PathComponent {
@@ -338,14 +338,14 @@ fn item_module(w: &mut Buffer, cx: &mut Context<'_>, item: &clean::Item, items:
match *src {
Some(src) => write!(
w,
- "<div class=\"item-left\"><code>{}extern crate {} as {};",
+ "<div class=\"item-name\"><code>{}extern crate {} as {};",
visibility_print_with_space(myitem.visibility(tcx), myitem.item_id, cx),
anchor(myitem.item_id.expect_def_id(), src, cx),
myitem.name.unwrap(),
),
None => write!(
w,
- "<div class=\"item-left\"><code>{}extern crate {};",
+ "<div class=\"item-name\"><code>{}extern crate {};",
visibility_print_with_space(myitem.visibility(tcx), myitem.item_id, cx),
anchor(myitem.item_id.expect_def_id(), myitem.name.unwrap(), cx),
),
@@ -355,7 +355,7 @@ fn item_module(w: &mut Buffer, cx: &mut Context<'_>, item: &clean::Item, items:
}
clean::ImportItem(ref import) => {
- let (stab, stab_tags) = if let Some(import_def_id) = import.source.did {
+ let stab_tags = if let Some(import_def_id) = import.source.did {
let ast_attrs = cx.tcx().get_attrs_unchecked(import_def_id);
let import_attrs = Box::new(clean::Attributes::from_ast(ast_attrs));
@@ -367,15 +367,12 @@ fn item_module(w: &mut Buffer, cx: &mut Context<'_>, item: &clean::Item, items:
..myitem.clone()
};
- let stab = import_item.stability_class(cx.tcx());
let stab_tags = Some(extra_info_tags(&import_item, item, cx.tcx()));
- (stab, stab_tags)
+ stab_tags
} else {
- (None, None)
+ None
};
- let add = if stab.is_some() { " " } else { "" };
-
w.write_str(ITEM_TABLE_ROW_OPEN);
let id = match import.kind {
clean::ImportKind::Simple(s) => {
@@ -387,15 +384,14 @@ fn item_module(w: &mut Buffer, cx: &mut Context<'_>, item: &clean::Item, items:
let (stab_tags_before, stab_tags_after) = if stab_tags.is_empty() {
("", "")
} else {
- ("<div class=\"item-right docblock-short\">", "</div>")
+ ("<div class=\"desc docblock-short\">", "</div>")
};
write!(
w,
- "<div class=\"item-left {stab}{add}import-item\"{id}>\
+ "<div class=\"item-name\"{id}>\
<code>{vis}{imp}</code>\
</div>\
{stab_tags_before}{stab_tags}{stab_tags_after}",
- stab = stab.unwrap_or_default(),
vis = visibility_print_with_space(myitem.visibility(tcx), myitem.item_id, cx),
imp = import.print(cx),
);
@@ -417,9 +413,6 @@ fn item_module(w: &mut Buffer, cx: &mut Context<'_>, item: &clean::Item, items:
_ => "",
};
- let stab = myitem.stability_class(cx.tcx());
- let add = if stab.is_some() { " " } else { "" };
-
let visibility_emoji = match myitem.visibility(tcx) {
Some(ty::Visibility::Restricted(_)) => {
"<span title=\"Restricted Visibility\">&nbsp;🔒</span> "
@@ -433,11 +426,11 @@ fn item_module(w: &mut Buffer, cx: &mut Context<'_>, item: &clean::Item, items:
let (docs_before, docs_after) = if docs.is_empty() {
("", "")
} else {
- ("<div class=\"item-right docblock-short\">", "</div>")
+ ("<div class=\"desc docblock-short\">", "</div>")
};
write!(
w,
- "<div class=\"item-left {stab}{add}module-item\">\
+ "<div class=\"item-name\">\
<a class=\"{class}\" href=\"{href}\" title=\"{title}\">{name}</a>\
{visibility_emoji}\
{unsafety_flag}\
@@ -448,11 +441,9 @@ fn item_module(w: &mut Buffer, cx: &mut Context<'_>, item: &clean::Item, items:
visibility_emoji = visibility_emoji,
stab_tags = extra_info_tags(myitem, item, cx.tcx()),
class = myitem.type_(),
- add = add,
- stab = stab.unwrap_or_default(),
unsafety_flag = unsafety_flag,
href = item_path(myitem.type_(), myitem.name.unwrap().as_str()),
- title = [full_path(cx, myitem), myitem.type_().to_string()]
+ title = [myitem.type_().to_string(), full_path(cx, myitem)]
.iter()
.filter_map(|s| if !s.is_empty() { Some(s.as_str()) } else { None })
.collect::<Vec<_>>()
@@ -530,26 +521,24 @@ fn item_function(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, f: &cle
let notable_traits =
f.decl.output.as_return().and_then(|output| notable_traits_button(output, cx));
- wrap_into_item_decl(w, |w| {
- wrap_item(w, |w| {
- render_attributes_in_pre(w, it, "");
- w.reserve(header_len);
- write!(
- w,
- "{vis}{constness}{asyncness}{unsafety}{abi}fn \
- {name}{generics}{decl}{notable_traits}{where_clause}",
- vis = visibility,
- constness = constness,
- asyncness = asyncness,
- unsafety = unsafety,
- abi = abi,
- name = name,
- generics = f.generics.print(cx),
- where_clause = print_where_clause(&f.generics, cx, 0, Ending::Newline),
- decl = f.decl.full_print(header_len, 0, cx),
- notable_traits = notable_traits.unwrap_or_default(),
- );
- });
+ wrap_item(w, |w| {
+ render_attributes_in_pre(w, it, "");
+ w.reserve(header_len);
+ write!(
+ w,
+ "{vis}{constness}{asyncness}{unsafety}{abi}fn \
+ {name}{generics}{decl}{notable_traits}{where_clause}",
+ vis = visibility,
+ constness = constness,
+ asyncness = asyncness,
+ unsafety = unsafety,
+ abi = abi,
+ name = name,
+ generics = f.generics.print(cx),
+ where_clause = print_where_clause(&f.generics, cx, 0, Ending::Newline),
+ decl = f.decl.full_print(header_len, 0, cx),
+ notable_traits = notable_traits.unwrap_or_default(),
+ );
});
document(w, cx, it, None, HeadingOffset::H2);
}
@@ -569,145 +558,140 @@ fn item_trait(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean:
let must_implement_one_of_functions = tcx.trait_def(t.def_id).must_implement_one_of.clone();
// Output the trait definition
- wrap_into_item_decl(w, |w| {
- wrap_item(w, |w| {
- render_attributes_in_pre(w, it, "");
- write!(
- w,
- "{}{}{}trait {}{}{}",
- visibility_print_with_space(it.visibility(tcx), it.item_id, cx),
- t.unsafety(tcx).print_with_space(),
- if t.is_auto(tcx) { "auto " } else { "" },
- it.name.unwrap(),
- t.generics.print(cx),
- bounds
- );
+ wrap_item(w, |w| {
+ render_attributes_in_pre(w, it, "");
+ write!(
+ w,
+ "{}{}{}trait {}{}{}",
+ visibility_print_with_space(it.visibility(tcx), it.item_id, cx),
+ t.unsafety(tcx).print_with_space(),
+ if t.is_auto(tcx) { "auto " } else { "" },
+ it.name.unwrap(),
+ t.generics.print(cx),
+ bounds
+ );
- if !t.generics.where_predicates.is_empty() {
- write!(w, "{}", print_where_clause(&t.generics, cx, 0, Ending::Newline));
- } else {
- w.write_str(" ");
- }
+ if !t.generics.where_predicates.is_empty() {
+ write!(w, "{}", print_where_clause(&t.generics, cx, 0, Ending::Newline));
+ } else {
+ w.write_str(" ");
+ }
- if t.items.is_empty() {
- w.write_str("{ }");
- } else {
- // FIXME: we should be using a derived_id for the Anchors here
- w.write_str("{\n");
- let mut toggle = false;
-
- // If there are too many associated types, hide _everything_
- if should_hide_fields(count_types) {
- toggle = true;
- toggle_open(
- w,
- format_args!(
- "{} associated items",
- count_types + count_consts + count_methods
- ),
- );
- }
- for types in [&required_types, &provided_types] {
- for t in types {
- render_assoc_item(
- w,
- t,
- AssocItemLink::Anchor(None),
- ItemType::Trait,
- cx,
- RenderMode::Normal,
- );
- w.write_str(";\n");
- }
- }
- // If there are too many associated constants, hide everything after them
- // We also do this if the types + consts is large because otherwise we could
- // render a bunch of types and _then_ a bunch of consts just because both were
- // _just_ under the limit
- if !toggle && should_hide_fields(count_types + count_consts) {
- toggle = true;
- toggle_open(
- w,
- format_args!(
- "{} associated constant{} and {} method{}",
- count_consts,
- pluralize(count_consts),
- count_methods,
- pluralize(count_methods),
- ),
- );
- }
- if count_types != 0 && (count_consts != 0 || count_methods != 0) {
- w.write_str("\n");
- }
- for consts in [&required_consts, &provided_consts] {
- for c in consts {
- render_assoc_item(
- w,
- c,
- AssocItemLink::Anchor(None),
- ItemType::Trait,
- cx,
- RenderMode::Normal,
- );
- w.write_str(";\n");
- }
- }
- if !toggle && should_hide_fields(count_methods) {
- toggle = true;
- toggle_open(w, format_args!("{} methods", count_methods));
- }
- if count_consts != 0 && count_methods != 0 {
- w.write_str("\n");
- }
- for (pos, m) in required_methods.iter().enumerate() {
+ if t.items.is_empty() {
+ w.write_str("{ }");
+ } else {
+ // FIXME: we should be using a derived_id for the Anchors here
+ w.write_str("{\n");
+ let mut toggle = false;
+
+ // If there are too many associated types, hide _everything_
+ if should_hide_fields(count_types) {
+ toggle = true;
+ toggle_open(
+ w,
+ format_args!("{} associated items", count_types + count_consts + count_methods),
+ );
+ }
+ for types in [&required_types, &provided_types] {
+ for t in types {
render_assoc_item(
w,
- m,
+ t,
AssocItemLink::Anchor(None),
ItemType::Trait,
cx,
RenderMode::Normal,
);
w.write_str(";\n");
-
- if pos < required_methods.len() - 1 {
- w.write_str("<span class=\"item-spacer\"></span>");
- }
- }
- if !required_methods.is_empty() && !provided_methods.is_empty() {
- w.write_str("\n");
}
- for (pos, m) in provided_methods.iter().enumerate() {
+ }
+ // If there are too many associated constants, hide everything after them
+ // We also do this if the types + consts is large because otherwise we could
+ // render a bunch of types and _then_ a bunch of consts just because both were
+ // _just_ under the limit
+ if !toggle && should_hide_fields(count_types + count_consts) {
+ toggle = true;
+ toggle_open(
+ w,
+ format_args!(
+ "{} associated constant{} and {} method{}",
+ count_consts,
+ pluralize(count_consts),
+ count_methods,
+ pluralize(count_methods),
+ ),
+ );
+ }
+ if count_types != 0 && (count_consts != 0 || count_methods != 0) {
+ w.write_str("\n");
+ }
+ for consts in [&required_consts, &provided_consts] {
+ for c in consts {
render_assoc_item(
w,
- m,
+ c,
AssocItemLink::Anchor(None),
ItemType::Trait,
cx,
RenderMode::Normal,
);
- match *m.kind {
- clean::MethodItem(ref inner, _)
- if !inner.generics.where_predicates.is_empty() =>
- {
- w.write_str(",\n { ... }\n");
- }
- _ => {
- w.write_str(" { ... }\n");
- }
- }
+ w.write_str(";\n");
+ }
+ }
+ if !toggle && should_hide_fields(count_methods) {
+ toggle = true;
+ toggle_open(w, format_args!("{} methods", count_methods));
+ }
+ if count_consts != 0 && count_methods != 0 {
+ w.write_str("\n");
+ }
- if pos < provided_methods.len() - 1 {
- w.write_str("<span class=\"item-spacer\"></span>");
- }
+ if !required_methods.is_empty() {
+ write!(w, " // Required method{}\n", pluralize(required_methods.len()));
+ }
+ for (pos, m) in required_methods.iter().enumerate() {
+ render_assoc_item(
+ w,
+ m,
+ AssocItemLink::Anchor(None),
+ ItemType::Trait,
+ cx,
+ RenderMode::Normal,
+ );
+ w.write_str(";\n");
+
+ if pos < required_methods.len() - 1 {
+ w.write_str("<span class=\"item-spacer\"></span>");
}
- if toggle {
- toggle_close(w);
+ }
+ if !required_methods.is_empty() && !provided_methods.is_empty() {
+ w.write_str("\n");
+ }
+
+ if !provided_methods.is_empty() {
+ write!(w, " // Provided method{}\n", pluralize(provided_methods.len()));
+ }
+ for (pos, m) in provided_methods.iter().enumerate() {
+ render_assoc_item(
+ w,
+ m,
+ AssocItemLink::Anchor(None),
+ ItemType::Trait,
+ cx,
+ RenderMode::Normal,
+ );
+
+ w.write_str(" { ... }\n");
+
+ if pos < provided_methods.len() - 1 {
+ w.write_str("<span class=\"item-spacer\"></span>");
}
- w.write_str("}");
}
- });
+ if toggle {
+ toggle_close(w);
+ }
+ w.write_str("}");
+ }
});
// Trait documentation
@@ -735,7 +719,7 @@ fn item_trait(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean:
let method_toggle_class = if item_type.is_method() { " method-toggle" } else { "" };
write!(w, "<details class=\"toggle{method_toggle_class}\" open><summary>");
}
- write!(w, "<section id=\"{}\" class=\"method has-srclink\">", id);
+ write!(w, "<section id=\"{}\" class=\"method\">", id);
render_rightside(w, cx, m, t, RenderMode::Normal);
write!(w, "<h4 class=\"code-header\">");
render_assoc_item(
@@ -1050,18 +1034,16 @@ fn item_trait(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean:
}
fn item_trait_alias(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean::TraitAlias) {
- wrap_into_item_decl(w, |w| {
- wrap_item(w, |w| {
- render_attributes_in_pre(w, it, "");
- write!(
- w,
- "trait {}{}{} = {};",
- it.name.unwrap(),
- t.generics.print(cx),
- print_where_clause(&t.generics, cx, 0, Ending::Newline),
- bounds(&t.bounds, true, cx)
- );
- });
+ wrap_item(w, |w| {
+ render_attributes_in_pre(w, it, "");
+ write!(
+ w,
+ "trait {}{}{} = {};",
+ it.name.unwrap(),
+ t.generics.print(cx),
+ print_where_clause(&t.generics, cx, 0, Ending::Newline),
+ bounds(&t.bounds, true, cx)
+ );
});
document(w, cx, it, None, HeadingOffset::H2);
@@ -1074,18 +1056,16 @@ fn item_trait_alias(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &
}
fn item_opaque_ty(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean::OpaqueTy) {
- wrap_into_item_decl(w, |w| {
- wrap_item(w, |w| {
- render_attributes_in_pre(w, it, "");
- write!(
- w,
- "type {}{}{where_clause} = impl {bounds};",
- it.name.unwrap(),
- t.generics.print(cx),
- where_clause = print_where_clause(&t.generics, cx, 0, Ending::Newline),
- bounds = bounds(&t.bounds, false, cx),
- );
- });
+ wrap_item(w, |w| {
+ render_attributes_in_pre(w, it, "");
+ write!(
+ w,
+ "type {}{}{where_clause} = impl {bounds};",
+ it.name.unwrap(),
+ t.generics.print(cx),
+ where_clause = print_where_clause(&t.generics, cx, 0, Ending::Newline),
+ bounds = bounds(&t.bounds, false, cx),
+ );
});
document(w, cx, it, None, HeadingOffset::H2);
@@ -1101,10 +1081,10 @@ fn item_typedef(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clea
fn write_content(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::Typedef) {
wrap_item(w, |w| {
render_attributes_in_pre(w, it, "");
- write!(w, "{}", visibility_print_with_space(it.visibility(cx.tcx()), it.item_id, cx));
write!(
w,
- "type {}{}{where_clause} = {type_};",
+ "{}type {}{}{where_clause} = {type_};",
+ visibility_print_with_space(it.visibility(cx.tcx()), it.item_id, cx),
it.name.unwrap(),
t.generics.print(cx),
where_clause = print_where_clause(&t.generics, cx, 0, Ending::Newline),
@@ -1113,7 +1093,7 @@ fn item_typedef(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clea
});
}
- wrap_into_item_decl(w, |w| write_content(w, cx, it, t));
+ write_content(w, cx, it, t);
document(w, cx, it, None, HeadingOffset::H2);
@@ -1127,11 +1107,9 @@ fn item_typedef(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clea
}
fn item_union(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, s: &clean::Union) {
- wrap_into_item_decl(w, |w| {
- wrap_item(w, |w| {
- render_attributes_in_pre(w, it, "");
- render_union(w, it, Some(&s.generics), &s.fields, "", cx);
- });
+ wrap_item(w, |w| {
+ render_attributes_in_pre(w, it, "");
+ render_union(w, it, Some(&s.generics), &s.fields, cx);
});
document(w, cx, it, None, HeadingOffset::H2);
@@ -1160,13 +1138,11 @@ fn item_union(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, s: &clean:
<a href=\"#{id}\" class=\"anchor field\">§</a>\
<code>{name}: {ty}</code>\
</span>",
- id = id,
- name = name,
shortty = ItemType::StructField,
ty = ty.print(cx),
);
if let Some(stability_class) = field.stability_class(cx.tcx()) {
- write!(w, "<span class=\"stab {stab}\"></span>", stab = stability_class);
+ write!(w, "<span class=\"stab {stability_class}\"></span>");
}
document(w, cx, field, Some(it), HeadingOffset::H3);
}
@@ -1179,7 +1155,7 @@ fn item_union(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, s: &clean:
fn print_tuple_struct_fields(w: &mut Buffer, cx: &Context<'_>, s: &[clean::Item]) {
for (i, ty) in s.iter().enumerate() {
if i > 0 {
- w.write_str(",&nbsp;");
+ w.write_str(", ");
}
match *ty.kind {
clean::StrippedItem(box clean::StructFieldItem(_)) => w.write_str("_"),
@@ -1192,60 +1168,58 @@ fn print_tuple_struct_fields(w: &mut Buffer, cx: &Context<'_>, s: &[clean::Item]
fn item_enum(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, e: &clean::Enum) {
let tcx = cx.tcx();
let count_variants = e.variants().count();
- wrap_into_item_decl(w, |w| {
- wrap_item(w, |w| {
- render_attributes_in_pre(w, it, "");
- write!(
- w,
- "{}enum {}{}",
- visibility_print_with_space(it.visibility(tcx), it.item_id, cx),
- it.name.unwrap(),
- e.generics.print(cx),
- );
- if !print_where_clause_and_check(w, &e.generics, cx) {
- // If there wasn't a `where` clause, we add a whitespace.
- w.write_str(" ");
- }
+ wrap_item(w, |w| {
+ render_attributes_in_pre(w, it, "");
+ write!(
+ w,
+ "{}enum {}{}",
+ visibility_print_with_space(it.visibility(tcx), it.item_id, cx),
+ it.name.unwrap(),
+ e.generics.print(cx),
+ );
+ if !print_where_clause_and_check(w, &e.generics, cx) {
+ // If there wasn't a `where` clause, we add a whitespace.
+ w.write_str(" ");
+ }
- let variants_stripped = e.has_stripped_entries();
- if count_variants == 0 && !variants_stripped {
- w.write_str("{}");
- } else {
- w.write_str("{\n");
- let toggle = should_hide_fields(count_variants);
- if toggle {
- toggle_open(w, format_args!("{} variants", count_variants));
- }
- for v in e.variants() {
- w.write_str(" ");
- let name = v.name.unwrap();
- match *v.kind {
- // FIXME(#101337): Show discriminant
- clean::VariantItem(ref var) => match var.kind {
- clean::VariantKind::CLike => write!(w, "{}", name),
- clean::VariantKind::Tuple(ref s) => {
- write!(w, "{}(", name);
- print_tuple_struct_fields(w, cx, s);
- w.write_str(")");
- }
- clean::VariantKind::Struct(ref s) => {
- render_struct(w, v, None, None, &s.fields, " ", false, cx);
- }
- },
- _ => unreachable!(),
- }
- w.write_str(",\n");
+ let variants_stripped = e.has_stripped_entries();
+ if count_variants == 0 && !variants_stripped {
+ w.write_str("{}");
+ } else {
+ w.write_str("{\n");
+ let toggle = should_hide_fields(count_variants);
+ if toggle {
+ toggle_open(w, format_args!("{} variants", count_variants));
+ }
+ for v in e.variants() {
+ w.write_str(" ");
+ let name = v.name.unwrap();
+ match *v.kind {
+ // FIXME(#101337): Show discriminant
+ clean::VariantItem(ref var) => match var.kind {
+ clean::VariantKind::CLike => write!(w, "{}", name),
+ clean::VariantKind::Tuple(ref s) => {
+ write!(w, "{}(", name);
+ print_tuple_struct_fields(w, cx, s);
+ w.write_str(")");
+ }
+ clean::VariantKind::Struct(ref s) => {
+ render_struct(w, v, None, None, &s.fields, " ", false, cx);
+ }
+ },
+ _ => unreachable!(),
}
+ w.write_str(",\n");
+ }
- if variants_stripped {
- w.write_str(" // some variants omitted\n");
- }
- if toggle {
- toggle_close(w);
- }
- w.write_str("}");
+ if variants_stripped {
+ w.write_str(" // some variants omitted\n");
}
- });
+ if toggle {
+ toggle_close(w);
+ }
+ w.write_str("}");
+ }
});
document(w, cx, it, None, HeadingOffset::H2);
@@ -1266,7 +1240,6 @@ fn item_enum(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, e: &clean::
w,
"<section id=\"{id}\" class=\"variant\">\
<a href=\"#{id}\" class=\"anchor\">§</a>",
- id = id,
);
render_stability_since_raw_with_extra(
w,
@@ -1304,8 +1277,11 @@ fn item_enum(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, e: &clean::
if let Some((heading, fields)) = heading_and_fields {
let variant_id =
cx.derive_id(format!("{}.{}.fields", ItemType::Variant, variant.name.unwrap()));
- write!(w, "<div class=\"sub-variant\" id=\"{id}\">", id = variant_id);
- write!(w, "<h4>{heading}</h4>", heading = heading);
+ write!(
+ w,
+ "<div class=\"sub-variant\" id=\"{variant_id}\">\
+ <h4>{heading}</h4>",
+ );
document_non_exhaustive(w, variant);
for field in fields {
match *field.kind {
@@ -1321,9 +1297,8 @@ fn item_enum(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, e: &clean::
"<div class=\"sub-variant-field\">\
<span id=\"{id}\" class=\"small-section-header\">\
<a href=\"#{id}\" class=\"anchor field\">§</a>\
- <code>{f}:&nbsp;{t}</code>\
+ <code>{f}: {t}</code>\
</span>",
- id = id,
f = field.name.unwrap(),
t = ty.print(cx)
);
@@ -1346,38 +1321,30 @@ fn item_enum(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, e: &clean::
}
fn item_macro(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean::Macro) {
- wrap_into_item_decl(w, |w| {
- highlight::render_macro_with_highlighting(&t.source, w);
- });
+ highlight::render_item_decl_with_highlighting(&t.source, w);
document(w, cx, it, None, HeadingOffset::H2)
}
fn item_proc_macro(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, m: &clean::ProcMacro) {
- wrap_into_item_decl(w, |w| {
+ wrap_item(w, |w| {
let name = it.name.expect("proc-macros always have names");
match m.kind {
MacroKind::Bang => {
- wrap_item(w, |w| {
- write!(w, "{}!() {{ /* proc-macro */ }}", name);
- });
+ write!(w, "{}!() {{ /* proc-macro */ }}", name);
}
MacroKind::Attr => {
- wrap_item(w, |w| {
- write!(w, "#[{}]", name);
- });
+ write!(w, "#[{}]", name);
}
MacroKind::Derive => {
- wrap_item(w, |w| {
- write!(w, "#[derive({})]", name);
- if !m.helpers.is_empty() {
- w.push_str("\n{\n");
- w.push_str(" // Attributes available to this derive:\n");
- for attr in &m.helpers {
- writeln!(w, " #[{}]", attr);
- }
- w.push_str("}\n");
+ write!(w, "#[derive({})]", name);
+ if !m.helpers.is_empty() {
+ w.push_str("\n{\n");
+ w.push_str(" // Attributes available to this derive:\n");
+ for attr in &m.helpers {
+ writeln!(w, " #[{}]", attr);
}
- });
+ w.push_str("}\n");
+ }
}
}
});
@@ -1400,61 +1367,57 @@ fn item_primitive(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item) {
}
fn item_constant(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, c: &clean::Constant) {
- wrap_into_item_decl(w, |w| {
- wrap_item(w, |w| {
- let tcx = cx.tcx();
- render_attributes_in_code(w, it);
+ wrap_item(w, |w| {
+ let tcx = cx.tcx();
+ render_attributes_in_code(w, it);
- write!(
- w,
- "{vis}const {name}: {typ}",
- vis = visibility_print_with_space(it.visibility(tcx), it.item_id, cx),
- name = it.name.unwrap(),
- typ = c.type_.print(cx),
- );
+ write!(
+ w,
+ "{vis}const {name}: {typ}",
+ vis = visibility_print_with_space(it.visibility(tcx), it.item_id, cx),
+ name = it.name.unwrap(),
+ typ = c.type_.print(cx),
+ );
- // FIXME: The code below now prints
- // ` = _; // 100i32`
- // if the expression is
- // `50 + 50`
- // which looks just wrong.
- // Should we print
- // ` = 100i32;`
- // instead?
-
- let value = c.value(tcx);
- let is_literal = c.is_literal(tcx);
- let expr = c.expr(tcx);
- if value.is_some() || is_literal {
- write!(w, " = {expr};", expr = Escape(&expr));
- } else {
- w.write_str(";");
- }
+ // FIXME: The code below now prints
+ // ` = _; // 100i32`
+ // if the expression is
+ // `50 + 50`
+ // which looks just wrong.
+ // Should we print
+ // ` = 100i32;`
+ // instead?
+
+ let value = c.value(tcx);
+ let is_literal = c.is_literal(tcx);
+ let expr = c.expr(tcx);
+ if value.is_some() || is_literal {
+ write!(w, " = {expr};", expr = Escape(&expr));
+ } else {
+ w.write_str(";");
+ }
- if !is_literal {
- if let Some(value) = &value {
- let value_lowercase = value.to_lowercase();
- let expr_lowercase = expr.to_lowercase();
+ if !is_literal {
+ if let Some(value) = &value {
+ let value_lowercase = value.to_lowercase();
+ let expr_lowercase = expr.to_lowercase();
- if value_lowercase != expr_lowercase
- && value_lowercase.trim_end_matches("i32") != expr_lowercase
- {
- write!(w, " // {value}", value = Escape(value));
- }
+ if value_lowercase != expr_lowercase
+ && value_lowercase.trim_end_matches("i32") != expr_lowercase
+ {
+ write!(w, " // {value}", value = Escape(value));
}
}
- });
+ }
});
document(w, cx, it, None, HeadingOffset::H2)
}
fn item_struct(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, s: &clean::Struct) {
- wrap_into_item_decl(w, |w| {
- wrap_item(w, |w| {
- render_attributes_in_code(w, it);
- render_struct(w, it, Some(&s.generics), s.ctor_kind, &s.fields, "", true, cx);
- });
+ wrap_item(w, |w| {
+ render_attributes_in_code(w, it);
+ render_struct(w, it, Some(&s.generics), s.ctor_kind, &s.fields, "", true, cx);
});
document(w, cx, it, None, HeadingOffset::H2);
@@ -1486,11 +1449,9 @@ fn item_struct(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, s: &clean
w,
"<span id=\"{id}\" class=\"{item_type} small-section-header\">\
<a href=\"#{id}\" class=\"anchor field\">§</a>\
- <code>{name}: {ty}</code>\
+ <code>{field_name}: {ty}</code>\
</span>",
item_type = ItemType::StructField,
- id = id,
- name = field_name,
ty = ty.print(cx)
);
document(w, cx, field, Some(it), HeadingOffset::H3);
@@ -1503,34 +1464,30 @@ fn item_struct(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, s: &clean
}
fn item_static(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, s: &clean::Static) {
- wrap_into_item_decl(w, |w| {
- wrap_item(w, |w| {
- render_attributes_in_code(w, it);
- write!(
- w,
- "{vis}static {mutability}{name}: {typ}",
- vis = visibility_print_with_space(it.visibility(cx.tcx()), it.item_id, cx),
- mutability = s.mutability.print_with_space(),
- name = it.name.unwrap(),
- typ = s.type_.print(cx)
- );
- });
+ wrap_item(w, |w| {
+ render_attributes_in_code(w, it);
+ write!(
+ w,
+ "{vis}static {mutability}{name}: {typ}",
+ vis = visibility_print_with_space(it.visibility(cx.tcx()), it.item_id, cx),
+ mutability = s.mutability.print_with_space(),
+ name = it.name.unwrap(),
+ typ = s.type_.print(cx)
+ );
});
document(w, cx, it, None, HeadingOffset::H2)
}
fn item_foreign_type(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item) {
- wrap_into_item_decl(w, |w| {
- wrap_item(w, |w| {
- w.write_str("extern {\n");
- render_attributes_in_code(w, it);
- write!(
- w,
- " {}type {};\n}}",
- visibility_print_with_space(it.visibility(cx.tcx()), it.item_id, cx),
- it.name.unwrap(),
- );
- });
+ wrap_item(w, |w| {
+ w.write_str("extern {\n");
+ render_attributes_in_code(w, it);
+ write!(
+ w,
+ " {}type {};\n}}",
+ visibility_print_with_space(it.visibility(cx.tcx()), it.item_id, cx),
+ it.name.unwrap(),
+ );
});
document(w, cx, it, None, HeadingOffset::H2);
@@ -1609,20 +1566,11 @@ fn bounds(t_bounds: &[clean::GenericBound], trait_alias: bool, cx: &Context<'_>)
bounds
}
-fn wrap_into_item_decl<F>(w: &mut Buffer, f: F)
-where
- F: FnOnce(&mut Buffer),
-{
- w.write_str("<div class=\"item-decl\">");
- f(w);
- w.write_str("</div>")
-}
-
fn wrap_item<F>(w: &mut Buffer, f: F)
where
F: FnOnce(&mut Buffer),
{
- w.write_str(r#"<pre class="rust"><code>"#);
+ w.write_str(r#"<pre class="rust item-decl"><code>"#);
f(w);
w.write_str("</code></pre>");
}
@@ -1677,7 +1625,6 @@ fn render_union(
it: &clean::Item,
g: Option<&clean::Generics>,
fields: &[clean::Item],
- tab: &str,
cx: &Context<'_>,
) {
let tcx = cx.tcx();
@@ -1700,7 +1647,7 @@ fn render_union(
w.write_str(" ");
}
- write!(w, "{{\n{}", tab);
+ write!(w, "{{\n");
let count_fields =
fields.iter().filter(|f| matches!(*f.kind, clean::StructFieldItem(..))).count();
let toggle = should_hide_fields(count_fields);
@@ -1712,17 +1659,16 @@ fn render_union(
if let clean::StructFieldItem(ref ty) = *field.kind {
write!(
w,
- " {}{}: {},\n{}",
+ " {}{}: {},\n",
visibility_print_with_space(field.visibility(tcx), field.item_id, cx),
field.name.unwrap(),
- ty.print(cx),
- tab
+ ty.print(cx)
);
}
}
if it.has_stripped_entries().unwrap() {
- write!(w, " /* private fields */\n{}", tab);
+ write!(w, " /* private fields */\n");
}
if toggle {
toggle_close(w);
@@ -1887,12 +1833,12 @@ 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: &LayoutS<VariantIdx>, tag_size: u64) {
+ fn write_size_of_layout(w: &mut Buffer, layout: &LayoutS, 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" },);
+ let size = layout.size.bytes() - tag_size;
+ write!(w, "{size} byte{pl}", pl = if size == 1 { "" } else { "s" },);
}
}
@@ -1909,7 +1855,7 @@ fn document_type_layout(w: &mut Buffer, cx: &Context<'_>, ty_def_id: DefId) {
let tcx = cx.tcx();
let param_env = tcx.param_env(ty_def_id);
- let ty = tcx.type_of(ty_def_id);
+ let ty = tcx.type_of(ty_def_id).subst_identity();
match tcx.layout_of(param_env.and(ty)) {
Ok(ty_layout) => {
writeln!(
@@ -1947,7 +1893,7 @@ fn document_type_layout(w: &mut Buffer, cx: &Context<'_>, ty_def_id: DefId) {
for (index, layout) in variants.iter_enumerated() {
let name = adt.variant(index).name;
- write!(w, "<li><code>{name}</code>: ", name = name);
+ write!(w, "<li><code>{name}</code>: ");
write_size_of_layout(w, layout, tag_size);
writeln!(w, "</li>");
}
diff --git a/src/librustdoc/html/render/search_index.rs b/src/librustdoc/html/render/search_index.rs
index 5b0caac09..090ea2cb1 100644
--- a/src/librustdoc/html/render/search_index.rs
+++ b/src/librustdoc/html/render/search_index.rs
@@ -236,7 +236,16 @@ pub(crate) fn build_index<'tcx>(
crate_data.serialize_field("doc", &self.doc)?;
crate_data.serialize_field(
"t",
- &self.items.iter().map(|item| &item.ty).collect::<Vec<_>>(),
+ &self
+ .items
+ .iter()
+ .map(|item| {
+ let n = item.ty as u8;
+ let c = char::try_from(n + b'A').expect("item types must fit in ASCII");
+ assert!(c <= 'z', "item types must fit within ASCII printables");
+ c
+ })
+ .collect::<String>(),
)?;
crate_data.serialize_field(
"n",
diff --git a/src/librustdoc/html/render/write_shared.rs b/src/librustdoc/html/render/write_shared.rs
index bc8badad3..54749e9a3 100644
--- a/src/librustdoc/html/render/write_shared.rs
+++ b/src/librustdoc/html/render/write_shared.rs
@@ -11,7 +11,7 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use serde::ser::SerializeSeq;
use serde::{Serialize, Serializer};
-use super::{collect_paths_for_type, ensure_trailing_slash, Context, BASIC_KEYWORDS};
+use super::{collect_paths_for_type, ensure_trailing_slash, Context};
use crate::clean::Crate;
use crate::config::{EmitType, RenderOptions};
use crate::docfs::PathError;
@@ -138,7 +138,7 @@ pub(super) fn write_shared(
Ok((ret, krates))
}
- /// Read a file and return all lines that match the <code>"{crate}":{data},\</code> format,
+ /// Read a file and return all lines that match the <code>"{crate}":{data},\ </code> format,
/// and return a tuple `(Vec<DataString>, Vec<CrateNameString>)`.
///
/// This forms the payload of files that look like this:
@@ -340,7 +340,6 @@ if (typeof exports !== 'undefined') {exports.searchIndex = searchIndex};
root_path: "./",
static_root_path: shared.static_root_path.as_deref(),
description: "List of crates",
- keywords: BASIC_KEYWORDS,
resource_suffix: &shared.resource_suffix,
};
diff --git a/src/librustdoc/html/sources.rs b/src/librustdoc/html/sources.rs
index 799c497d1..2c90bf4fa 100644
--- a/src/librustdoc/html/sources.rs
+++ b/src/librustdoc/html/sources.rs
@@ -4,7 +4,7 @@ use crate::error::Error;
use crate::html::format::Buffer;
use crate::html::highlight;
use crate::html::layout;
-use crate::html::render::{Context, BASIC_KEYWORDS};
+use crate::html::render::Context;
use crate::visit::DocVisitor;
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
@@ -228,7 +228,6 @@ impl SourceCollector<'_, '_> {
root_path: &root_path,
static_root_path: shared.static_root_path.as_deref(),
description: &desc,
- keywords: BASIC_KEYWORDS,
resource_suffix: &shared.resource_suffix,
};
let v = layout::render(
diff --git a/src/librustdoc/html/static/.eslintrc.js b/src/librustdoc/html/static/.eslintrc.js
index fcd925bb3..1a34530c2 100644
--- a/src/librustdoc/html/static/.eslintrc.js
+++ b/src/librustdoc/html/static/.eslintrc.js
@@ -90,7 +90,6 @@ module.exports = {
"no-return-assign": "error",
"no-script-url": "error",
"no-sequences": "error",
- "no-throw-literal": "error",
"no-div-regex": "error",
}
};
diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css
index a93f60da2..95528e70e 100644
--- a/src/librustdoc/html/static/css/rustdoc.css
+++ b/src/librustdoc/html/static/css/rustdoc.css
@@ -1,3 +1,11 @@
+/* When static files are updated, their suffixes need to be updated.
+ 1. In the top directory run:
+ ./x.py doc --stage 1 library/core
+ 2. Find the directory containing files named with updated suffixes:
+ find build -path '*'/stage1-std/'*'/static.files
+ 3. Copy the filenames with updated suffixes from the directory.
+*/
+
/* See FiraSans-LICENSE.txt for the Fira Sans license. */
@font-face {
font-family: 'Fira Sans';
@@ -22,7 +30,7 @@
font-style: normal;
font-weight: 400;
src: local('Source Serif 4'),
- url("SourceSerif4-Regular-1f7d512b176f0f72.ttf.woff2") format("woff2");
+ url("SourceSerif4-Regular-46f98efaafac5295.ttf.woff2") format("woff2");
font-display: swap;
}
@font-face {
@@ -30,7 +38,7 @@
font-style: italic;
font-weight: 400;
src: local('Source Serif 4 Italic'),
- url("SourceSerif4-It-d034fe4ef9d0fa00.ttf.woff2") format("woff2");
+ url("SourceSerif4-It-acdfaf1a8af734b1.ttf.woff2") format("woff2");
font-display: swap;
}
@font-face {
@@ -38,7 +46,7 @@
font-style: normal;
font-weight: 700;
src: local('Source Serif 4 Bold'),
- url("SourceSerif4-Bold-124a1ca42af929b6.ttf.woff2") format("woff2");
+ url("SourceSerif4-Bold-a2c9cd1067f8b328.ttf.woff2") format("woff2");
font-display: swap;
}
@@ -166,6 +174,14 @@ h1, h2, h3, h4 {
.top-doc .docblock > h4 {
border-bottom: 1px solid var(--headings-border-bottom-color);
}
+/* while line-height 1.5 is required for any "block of text",
+ which WCAG defines as more than one sentence, it looks weird for
+ very large main headers */
+h1, h2 {
+ line-height: 1.25;
+ padding-top: 3px;
+ padding-bottom: 9px;
+}
h3.code-header {
font-size: 1.125rem; /* 18px */
}
@@ -176,6 +192,7 @@ h4.code-header {
font-weight: 600;
margin: 0;
padding: 0;
+ white-space: pre-wrap;
}
#crate-search,
@@ -184,7 +201,7 @@ h1, h2, h3, h4, h5, h6,
.mobile-topbar,
.search-input,
.search-results .result-name,
-.item-left > a,
+.item-name > a,
.out-of-band,
span.since,
a.srclink,
@@ -335,7 +352,7 @@ pre {
padding: 14px;
line-height: 1.5; /* https://github.com/rust-lang/rust/issues/105906 */
}
-.item-decl pre {
+pre.item-decl {
overflow-x: auto;
}
/* This rule allows to have scrolling on the X axis. */
@@ -533,7 +550,7 @@ ul.block, .block li {
.rustdoc .example-wrap > pre {
margin: 0;
flex-grow: 1;
- overflow-x: auto;
+ overflow: auto hidden;
}
.rustdoc .example-wrap > pre.example-line-numbers,
@@ -634,6 +651,7 @@ pre, .rustdoc.source .example-wrap {
.fn .where,
.where.fmt-newline {
display: block;
+ white-space: pre-wrap;
font-size: 0.875rem;
}
@@ -697,8 +715,8 @@ h2.small-section-header > .anchor {
.main-heading a:hover,
.example-wrap > pre.rust a:hover,
.all-items a:hover,
-.docblock a:not(.test-arrow):not(.scrape-help):hover,
-.docblock-short a:not(.test-arrow):not(.scrape-help):hover,
+.docblock a:not(.test-arrow):not(.scrape-help):not(.tooltip):hover,
+.docblock-short a:not(.test-arrow):not(.scrape-help):not(.tooltip):hover,
.item-info a {
text-decoration: underline;
}
@@ -732,14 +750,16 @@ table,
.item-table {
display: table;
+ padding: 0;
+ margin: 0;
}
-.item-row {
+.item-table > li {
display: table-row;
}
-.item-left, .item-right {
+.item-table > li > div {
display: table-cell;
}
-.item-left {
+.item-table > li > .item-name {
padding-right: 1.25rem;
}
@@ -806,8 +826,11 @@ so that we can apply CSS-filters to change the arrow color in themes */
background-repeat: no-repeat;
background-size: 20px;
background-position: calc(100% - 2px) 56%;
- /* image is black color */
- background-image: url("down-arrow-927217e04c7463ac.svg");
+ /* down arrow (image is black color) */
+ background-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" \
+ width="128" height="128" viewBox="-30 -20 176 176"><path d="M111,40.5L64,87.499L17,40.5" \
+ fill="none" stroke="black" strike-linecap="square" stroke-miterlimit="10" stroke-width="12"/> \
+ </svg>');
/* changes the arrow image color */
filter: var(--crate-search-div-filter);
}
@@ -941,7 +964,7 @@ so that we can apply CSS-filters to change the arrow color in themes */
padding: 3px;
margin-bottom: 5px;
}
-.item-left .stab {
+.item-name .stab {
margin-left: 0.3125em;
}
.stab {
@@ -977,11 +1000,6 @@ so that we can apply CSS-filters to change the arrow color in themes */
0 -1px 0 black;
}
-.module-item.unstable,
-.import-item.unstable {
- opacity: 0.65;
-}
-
.since {
font-weight: normal;
font-size: initial;
@@ -1093,44 +1111,8 @@ pre.rust .doccomment {
display: block;
left: -25px;
top: 5px;
-}
-
-.example-wrap .tooltip:hover::after {
- padding: 5px 3px 3px 3px;
- border-radius: 6px;
- margin-left: 5px;
- font-size: 1rem;
- border: 1px solid var(--border-color);
- position: absolute;
- width: max-content;
- top: -2px;
- z-index: 1;
- background-color: var(--tooltip-background-color);
- color: var(--tooltip-color);
-}
-
-.example-wrap .tooltip:hover::before {
- content: " ";
- position: absolute;
- top: 50%;
- left: 16px;
- margin-top: -5px;
- z-index: 1;
- border: 5px solid transparent;
- border-right-color: var(--tooltip-background-color);
-}
-
-.example-wrap.ignore .tooltip:hover::after {
- content: "This example is not tested";
-}
-.example-wrap.compile_fail .tooltip:hover::after {
- content: "This example deliberately fails to compile";
-}
-.example-wrap.should_panic .tooltip:hover::after {
- content: "This example panics";
-}
-.example-wrap.edition .tooltip:hover::after {
- content: "This code runs with edition " attr(data-edition);
+ margin: 0;
+ line-height: 1;
}
.example-wrap.compile_fail .tooltip,
@@ -1168,6 +1150,7 @@ a.test-arrow:hover {
.item-spacer {
width: 100%;
height: 12px;
+ display: block;
}
.out-of-band > span.since {
@@ -1196,7 +1179,7 @@ a.test-arrow:hover {
border-right: 3px solid var(--target-border-color);
}
-.notable-traits {
+.code-header a.tooltip {
color: inherit;
margin-right: 15px;
position: relative;
@@ -1205,7 +1188,7 @@ a.test-arrow:hover {
/* placeholder thunk so that the mouse can easily travel from "(i)" to popover
the resulting "hover tunnel" is a stepped triangle, approximating
https://bjk5.com/post/44698559168/breaking-down-amazons-mega-dropdown */
-.notable-traits:hover::after {
+a.tooltip:hover::after {
position: absolute;
top: calc(100% - 10px);
left: -15px;
@@ -1214,11 +1197,11 @@ a.test-arrow:hover {
content: "\00a0";
}
-.notable .content {
+.popover.tooltip .content {
margin: 0.25em 0.5em;
}
-.notable .content pre, .notable .content code {
+.popover.tooltip .content pre, .popover.tooltip .content code {
background: transparent;
margin: 0;
padding: 0;
@@ -1226,7 +1209,7 @@ a.test-arrow:hover {
white-space: pre-wrap;
}
-.notable .content > h3:first-child {
+.popover.tooltip .content > h3:first-child {
margin: 0 0 5px 0;
}
@@ -1263,12 +1246,25 @@ a.test-arrow:hover {
line-height: 1.5;
color: inherit;
}
+#search-tabs button:not(.selected) {
+ background-color: var(--search-tab-button-not-selected-background);
+ border-top-color: var(--search-tab-button-not-selected-border-top-color);
+}
+#search-tabs button:hover, #search-tabs button.selected {
+ background-color: var(--search-tab-button-selected-background);
+ border-top-color: var(--search-tab-button-selected-border-top-color);
+}
#search-tabs .count {
font-size: 1rem;
color: var(--search-tab-title-count-color);
}
+#search .error code {
+ border-radius: 3px;
+ background-color: var(--search-error-code-background-color);
+}
+
#src-sidebar-toggle {
position: sticky;
top: 0;
@@ -1433,7 +1429,10 @@ details.toggle > summary.hideme > span {
}
details.toggle > summary::before {
- background: url("toggle-plus-1092eb4930d581b0.svg") no-repeat top left;
+ /* toggle plus */
+ background: url('data:image/svg+xml,<svg width="17" height="17" \
+shape-rendering="crispEdges" stroke="black" fill="none" xmlns="http://www.w3.org/2000/svg"><path \
+d="M5 2.5H2.5v12H5m7-12h2.5v12H12M5 8.5h7M8.5 12V8.625v0V5"/></svg>') no-repeat top left;
content: "";
cursor: pointer;
width: 16px;
@@ -1511,7 +1510,10 @@ details.toggle[open] > summary.hideme > span {
}
details.toggle[open] > summary::before {
- background: url("toggle-minus-31bbd6e4c77f5c96.svg") no-repeat top left;
+ /* toggle minus */
+ background: url('data:image/svg+xml,<svg width="17" height="17" \
+shape-rendering="crispEdges" stroke="black" fill="none" xmlns="http://www.w3.org/2000/svg"><path \
+d="M5 2.5H2.5v12H5m7-12h2.5v12H12M5 8.5h7"/></svg>') no-repeat top left;
}
details.toggle[open] > summary::after {
@@ -1700,7 +1702,7 @@ in storage.js
}
/* Display an alternating layout on tablets and phones */
- .item-table, .item-row, .item-left, .item-right,
+ .item-table, .item-row, .item-table > li, .item-table > li > div,
.search-results > a, .search-results > a > div {
display: block;
}
@@ -1709,7 +1711,7 @@ in storage.js
.search-results > a {
padding: 5px 0px;
}
- .search-results > a > div.desc, .item-right {
+ .search-results > a > div.desc, .item-table > li > div.desc {
padding-left: 2em;
}
@@ -1897,19 +1899,25 @@ in storage.js
right: 0.25em;
}
-.scraped-example:not(.expanded) .code-wrapper:before,
-.scraped-example:not(.expanded) .code-wrapper:after {
+.scraped-example:not(.expanded) .code-wrapper::before,
+.scraped-example:not(.expanded) .code-wrapper::after {
content: " ";
width: 100%;
height: 5px;
position: absolute;
z-index: 1;
}
-.scraped-example:not(.expanded) .code-wrapper:before {
+.scraped-example:not(.expanded) .code-wrapper::before {
top: 0;
+ background: linear-gradient(to bottom,
+ var(--scrape-example-code-wrapper-background-start),
+ var(--scrape-example-code-wrapper-background-end));
}
-.scraped-example:not(.expanded) .code-wrapper:after {
+.scraped-example:not(.expanded) .code-wrapper::after {
bottom: 0;
+ background: linear-gradient(to top,
+ var(--scrape-example-code-wrapper-background-start),
+ var(--scrape-example-code-wrapper-background-end));
}
.scraped-example .code-wrapper .example-wrap {
diff --git a/src/librustdoc/html/static/css/settings.css b/src/librustdoc/html/static/css/settings.css
index 4e9803fe2..920f45c4b 100644
--- a/src/librustdoc/html/static/css/settings.css
+++ b/src/librustdoc/html/static/css/settings.css
@@ -3,8 +3,7 @@
position: relative;
}
-.setting-line .radio-line input,
-.setting-line .settings-toggle input {
+.setting-radio input, .setting-check input {
margin-right: 0.3em;
height: 1.2rem;
width: 1.2rem;
@@ -14,21 +13,20 @@
-webkit-appearance: none;
cursor: pointer;
}
-.setting-line .radio-line input {
+.setting-radio input {
border-radius: 50%;
}
-.setting-line .settings-toggle input:checked {
+.setting-check input:checked {
content: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 40 40">\
<path d="M7,25L17,32L33,12" fill="none" stroke="black" stroke-width="5"/>\
<path d="M7,23L17,30L33,10" fill="none" stroke="white" stroke-width="5"/></svg>');
}
-.setting-line .radio-line input + span,
-.setting-line .settings-toggle span {
+.setting-radio span, .setting-check span {
padding-bottom: 1px;
}
-.radio-line .choice {
+.setting-radio {
margin-top: 0.1em;
margin-bottom: 0.1em;
min-width: 3.8em;
@@ -37,36 +35,32 @@
align-items: center;
cursor: pointer;
}
-.radio-line .choice + .choice {
+.setting-radio + .setting-radio {
margin-left: 0.5em;
}
-.settings-toggle {
- position: relative;
- width: 100%;
+.setting-check {
margin-right: 20px;
display: flex;
align-items: center;
cursor: pointer;
}
-.setting-line .radio-line input:checked {
+.setting-radio input:checked {
box-shadow: inset 0 0 0 3px var(--main-background-color);
background-color: var(--settings-input-color);
}
-.setting-line .settings-toggle input:checked {
+.setting-check input:checked {
background-color: var(--settings-input-color);
}
-.setting-line .radio-line input:focus,
-.setting-line .settings-toggle input:focus {
+.setting-radio input:focus, .setting-check input:focus {
box-shadow: 0 0 1px 1px var(--settings-input-color);
}
/* In here we combine both `:focus` and `:checked` properties. */
-.setting-line .radio-line input:checked:focus {
+.setting-radio input:checked:focus {
box-shadow: inset 0 0 0 3px var(--main-background-color),
0 0 2px 2px var(--settings-input-color);
}
-.setting-line .radio-line input:hover,
-.setting-line .settings-toggle input:hover {
+.setting-radio input:hover, .setting-check input:hover {
border-color: var(--settings-input-color) !important;
}
diff --git a/src/librustdoc/html/static/css/themes/ayu.css b/src/librustdoc/html/static/css/themes/ayu.css
index 979e7e0f9..90cf689ad 100644
--- a/src/librustdoc/html/static/css/themes/ayu.css
+++ b/src/librustdoc/html/static/css/themes/ayu.css
@@ -43,9 +43,14 @@ Original by Dempfi (https://github.com/dempfi/ayu)
--search-result-link-focus-background-color: #3c3c3c;
--search-result-border-color: #aaa3;
--search-color: #fff;
+ --search-error-code-background-color: #4f4c4c;
--search-results-alias-color: #c5c5c5;
--search-results-grey-color: #999;
--search-tab-title-count-color: #888;
+ --search-tab-button-not-selected-border-top-color: none;
+ --search-tab-button-not-selected-background: transparent !important;
+ --search-tab-button-selected-border-top-color: none;
+ --search-tab-button-selected-background: #141920 !important;
--stab-background-color: #314559;
--stab-code-color: #e6e1cf;
--code-highlight-kw-color: #ff7733;
@@ -70,8 +75,6 @@ Original by Dempfi (https://github.com/dempfi/ayu)
--test-arrow-hover-background-color: rgba(57, 175, 215, 0.368);
--target-background-color: rgba(255, 236, 164, 0.06);
--target-border-color: rgba(255, 180, 76, 0.85);
- --tooltip-background-color: #314559;
- --tooltip-color: #c5c5c5;
--kbd-color: #c5c5c5;
--kbd-background: #314559;
--kbd-box-shadow-color: #5c6773;
@@ -97,12 +100,13 @@ Original by Dempfi (https://github.com/dempfi/ayu)
--scrape-example-help-color: #eee;
--scrape-example-help-hover-border-color: #fff;
--scrape-example-help-hover-color: #fff;
+ --scrape-example-code-wrapper-background-start: rgba(15, 20, 25, 1);
+ --scrape-example-code-wrapper-background-end: rgba(15, 20, 25, 0);
}
-h1, h2, h3, h4 {
- color: white;
-}
-h1 a {
+h1, h2, h3, h4,
+h1 a, .sidebar h2 a, .sidebar h3 a,
+#source-sidebar > .title {
color: #fff;
}
h4 {
@@ -112,24 +116,22 @@ h4 {
.docblock code {
color: #ffb454;
}
-.code-header {
- color: #e6e1cf;
-}
-.docblock pre > code, pre > code {
- color: #e6e1cf;
-}
-.item-info code {
- color: #e6e1cf;
-}
.docblock a > code {
color: #39AFD7 !important;
}
-pre, .rustdoc.source .example-wrap {
+.code-header,
+.docblock pre > code,
+pre, pre > code,
+.item-info code,
+.rustdoc.source .example-wrap {
color: #e6e1cf;
}
.sidebar .current,
-.sidebar a:hover {
+.sidebar a:hover,
+#source-sidebar div.files > a:hover, details.dir-entry summary:hover,
+#source-sidebar div.files > a:focus, details.dir-entry summary:focus,
+#source-sidebar div.files > a.selected {
color: #ffb44c;
}
@@ -143,15 +145,12 @@ pre, .rustdoc.source .example-wrap {
border-right: 1px solid #ffb44c;
}
-.search-results a:hover {
- color: #fff !important;
- background-color: #3c3c3c;
-}
-
+.search-results a:hover,
.search-results a:focus {
color: #fff !important;
background-color: #3c3c3c;
}
+
.search-results a {
color: #0096cf;
}
@@ -159,54 +158,22 @@ pre, .rustdoc.source .example-wrap {
color: #c5c5c5;
}
-.sidebar h2 a,
-.sidebar h3 a {
- color: white;
-}
-
.result-name .primitive > i, .result-name .keyword > i {
color: #788797;
}
#search-tabs > button.selected {
- background-color: #141920 !important;
border-bottom: 1px solid #ffb44c !important;
border-top: none;
}
-
#search-tabs > button:not(.selected) {
- background-color: transparent !important;
border: none;
+ background-color: transparent !important;
}
-
#search-tabs > button:hover {
border-bottom: 1px solid rgba(242, 151, 24, 0.3);
}
-/* rules that this theme does not need to set, here to satisfy the rule checker */
-/* note that a lot of these are partially set in some way (meaning they are set
-individually rather than as a group) */
-/* FIXME: these rules should be at the bottom of the file but currently must be
-above the `@media (max-width: 700px)` rules due to a bug in the css checker */
-/* see https://github.com/rust-lang/rust/pull/71237#issuecomment-618170143 */
-#search-tabs > button:hover, #search-tabs > button.selected {}
-
#settings-menu > a img {
filter: invert(100);
}
-
-#source-sidebar > .title {
- color: #fff;
-}
-#source-sidebar div.files > a:hover, details.dir-entry summary:hover,
-#source-sidebar div.files > a:focus, details.dir-entry summary:focus,
-#source-sidebar div.files > a.selected {
- color: #ffb44c;
-}
-
-.scraped-example:not(.expanded) .code-wrapper::before {
- background: linear-gradient(to bottom, rgba(15, 20, 25, 1), rgba(15, 20, 25, 0));
-}
-.scraped-example:not(.expanded) .code-wrapper::after {
- background: linear-gradient(to top, rgba(15, 20, 25, 1), rgba(15, 20, 25, 0));
-}
diff --git a/src/librustdoc/html/static/css/themes/dark.css b/src/librustdoc/html/static/css/themes/dark.css
index fb15863b0..e8cd06931 100644
--- a/src/librustdoc/html/static/css/themes/dark.css
+++ b/src/librustdoc/html/static/css/themes/dark.css
@@ -38,9 +38,14 @@
--search-result-link-focus-background-color: #616161;
--search-result-border-color: #aaa3;
--search-color: #111;
+ --search-error-code-background-color: #484848;
--search-results-alias-color: #fff;
--search-results-grey-color: #ccc;
--search-tab-title-count-color: #888;
+ --search-tab-button-not-selected-border-top-color: #252525;
+ --search-tab-button-not-selected-background: #252525;
+ --search-tab-button-selected-border-top-color: #0089ff;
+ --search-tab-button-selected-background: #353535;
--stab-background-color: #314559;
--stab-code-color: #e6e1cf;
--code-highlight-kw-color: #ab8ac1;
@@ -65,8 +70,6 @@
--test-arrow-hover-background-color: #4e8bca;
--target-background-color: #494a3d;
--target-border-color: #bb7410;
- --tooltip-background-color: #000;
- --tooltip-color: #fff;
--kbd-color: #000;
--kbd-background: #fafbfc;
--kbd-box-shadow-color: #c6cbd1;
@@ -92,21 +95,6 @@
--scrape-example-help-color: #eee;
--scrape-example-help-hover-border-color: #fff;
--scrape-example-help-hover-color: #fff;
-}
-
-#search-tabs > button:not(.selected) {
- background-color: #252525;
- border-top-color: #252525;
-}
-
-#search-tabs > button:hover, #search-tabs > button.selected {
- border-top-color: #0089ff;
- background-color: #353535;
-}
-
-.scraped-example:not(.expanded) .code-wrapper::before {
- background: linear-gradient(to bottom, rgba(53, 53, 53, 1), rgba(53, 53, 53, 0));
-}
-.scraped-example:not(.expanded) .code-wrapper::after {
- background: linear-gradient(to top, rgba(53, 53, 53, 1), rgba(53, 53, 53, 0));
+ --scrape-example-code-wrapper-background-start: rgba(53, 53, 53, 1);
+ --scrape-example-code-wrapper-background-end: rgba(53, 53, 53, 0);
}
diff --git a/src/librustdoc/html/static/css/themes/light.css b/src/librustdoc/html/static/css/themes/light.css
index 053fa78d1..5e3f14e48 100644
--- a/src/librustdoc/html/static/css/themes/light.css
+++ b/src/librustdoc/html/static/css/themes/light.css
@@ -38,9 +38,14 @@
--search-result-link-focus-background-color: #ccc;
--search-result-border-color: #aaa3;
--search-color: #000;
+ --search-error-code-background-color: #d0cccc;
--search-results-alias-color: #000;
--search-results-grey-color: #999;
--search-tab-title-count-color: #888;
+ --search-tab-button-not-selected-border-top-color: #e6e6e6;
+ --search-tab-button-not-selected-background: #e6e6e6;
+ --search-tab-button-selected-border-top-color: #0089ff;
+ --search-tab-button-selected-background: #ffffff;
--stab-background-color: #fff5d6;
--stab-code-color: #000;
--code-highlight-kw-color: #8959a8;
@@ -65,8 +70,6 @@
--test-arrow-hover-background-color: #4e8bca;
--target-background-color: #fdffd3;
--target-border-color: #ad7c37;
- --tooltip-background-color: #000;
- --tooltip-color: #fff;
--kbd-color: #000;
--kbd-background: #fafbfc;
--kbd-box-shadow-color: #c6cbd1;
@@ -89,21 +92,6 @@
--scrape-example-help-color: #333;
--scrape-example-help-hover-border-color: #000;
--scrape-example-help-hover-color: #000;
-}
-
-#search-tabs > button:not(.selected) {
- background-color: #e6e6e6;
- border-top-color: #e6e6e6;
-}
-
-#search-tabs > button:hover, #search-tabs > button.selected {
- background-color: #ffffff;
- border-top-color: #0089ff;
-}
-
-.scraped-example:not(.expanded) .code-wrapper::before {
- background: linear-gradient(to bottom, rgba(255, 255, 255, 1), rgba(255, 255, 255, 0));
-}
-.scraped-example:not(.expanded) .code-wrapper::after {
- background: linear-gradient(to top, rgba(255, 255, 255, 1), rgba(255, 255, 255, 0));
+ --scrape-example-code-wrapper-background-start: rgba(255, 255, 255, 1);
+ --scrape-example-code-wrapper-background-end: rgba(255, 255, 255, 0);
}
diff --git a/src/librustdoc/html/static/fonts/SourceSerif4-Bold.ttf.woff2 b/src/librustdoc/html/static/fonts/SourceSerif4-Bold.ttf.woff2
index db57d2145..181a07f63 100644
--- a/src/librustdoc/html/static/fonts/SourceSerif4-Bold.ttf.woff2
+++ b/src/librustdoc/html/static/fonts/SourceSerif4-Bold.ttf.woff2
Binary files differ
diff --git a/src/librustdoc/html/static/fonts/SourceSerif4-It.ttf.woff2 b/src/librustdoc/html/static/fonts/SourceSerif4-It.ttf.woff2
index 1cbc021a3..2ae08a7be 100644
--- a/src/librustdoc/html/static/fonts/SourceSerif4-It.ttf.woff2
+++ b/src/librustdoc/html/static/fonts/SourceSerif4-It.ttf.woff2
Binary files differ
diff --git a/src/librustdoc/html/static/fonts/SourceSerif4-LICENSE.md b/src/librustdoc/html/static/fonts/SourceSerif4-LICENSE.md
index 68ea18924..5871e1f3d 100644
--- a/src/librustdoc/html/static/fonts/SourceSerif4-LICENSE.md
+++ b/src/librustdoc/html/static/fonts/SourceSerif4-LICENSE.md
@@ -1,4 +1,4 @@
-Copyright 2014-2021 Adobe (http://www.adobe.com/), with Reserved Font Name 'Source'. All Rights Reserved. Source is a trademark of Adobe in the United States and/or other countries.
+Copyright 2014 - 2023 Adobe (http://www.adobe.com/), with Reserved Font Name ‘Source’. All Rights Reserved. Source is a trademark of Adobe in the United States and/or other countries.
This Font Software is licensed under the SIL Open Font License, Version 1.1.
diff --git a/src/librustdoc/html/static/fonts/SourceSerif4-Regular.ttf.woff2 b/src/librustdoc/html/static/fonts/SourceSerif4-Regular.ttf.woff2
index 2db73fe2b..0263fc304 100644
--- a/src/librustdoc/html/static/fonts/SourceSerif4-Regular.ttf.woff2
+++ b/src/librustdoc/html/static/fonts/SourceSerif4-Regular.ttf.woff2
Binary files differ
diff --git a/src/librustdoc/html/static/images/down-arrow.svg b/src/librustdoc/html/static/images/down-arrow.svg
deleted file mode 100644
index 5d76a64e9..000000000
--- a/src/librustdoc/html/static/images/down-arrow.svg
+++ /dev/null
@@ -1 +0,0 @@
-<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" id="Layer_1" width="128" height="128" enable-background="new 0 0 128 128" version="1.1" viewBox="-30 -20 176 176" xml:space="preserve"><g><line x1="111" x2="64" y1="40.5" y2="87.499" fill="none" stroke="#000000" stroke-linecap="square" stroke-miterlimit="10" stroke-width="12"/><line x1="64" x2="17" y1="87.499" y2="40.5" fill="none" stroke="#000000" stroke-linecap="square" stroke-miterlimit="10" stroke-width="12"/></g></svg> \ No newline at end of file
diff --git a/src/librustdoc/html/static/images/toggle-minus.svg b/src/librustdoc/html/static/images/toggle-minus.svg
deleted file mode 100644
index 73154788a..000000000
--- a/src/librustdoc/html/static/images/toggle-minus.svg
+++ /dev/null
@@ -1 +0,0 @@
-<svg width="17" height="17" shape-rendering="crispEdges" stroke="#000" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M5 2.5H2.5v12H5m7-12h2.5v12H12M5 8.5h7"/></svg> \ No newline at end of file
diff --git a/src/librustdoc/html/static/images/toggle-plus.svg b/src/librustdoc/html/static/images/toggle-plus.svg
deleted file mode 100644
index 08b17033e..000000000
--- a/src/librustdoc/html/static/images/toggle-plus.svg
+++ /dev/null
@@ -1 +0,0 @@
-<svg width="17" height="17" shape-rendering="crispEdges" stroke="#000" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M5 2.5H2.5v12H5m7-12h2.5v12H12M5 8.5h7M8.5 12V8.625v0V5"/></svg> \ No newline at end of file
diff --git a/src/librustdoc/html/static/images/wheel.svg b/src/librustdoc/html/static/images/wheel.svg
index 01da3b24c..83c07f63d 100644
--- a/src/librustdoc/html/static/images/wheel.svg
+++ b/src/librustdoc/html/static/images/wheel.svg
@@ -1 +1 @@
-<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" id="Capa_1" width="27.434" height="29.5" enable-background="new 0 0 27.434 29.5" version="1.1" viewBox="0 0 27.434 29.5" xml:space="preserve"><g><path d="M27.315,18.389c-0.165-0.604-0.509-1.113-0.981-1.459c-0.042-0.144-0.083-0.429-0.015-0.761l0.037-0.177v-0.182V14.8 c0-1.247-0.006-1.277-0.048-1.472c-0.076-0.354-0.035-0.653,0.007-0.803c0.477-0.346,0.828-0.861,0.996-1.476 c0.261-0.956,0.076-2.091-0.508-3.114l-0.591-1.032c-0.746-1.307-1.965-2.119-3.182-2.119c-0.378,0-0.75,0.081-1.085,0.235 c-0.198-0.025-0.554-0.15-0.855-0.389l-0.103-0.082l-0.114-0.065l-1.857-1.067L18.92,3.36l-0.105-0.044 c-0.376-0.154-0.658-0.41-0.768-0.556C17.918,1.172,16.349,0,14.296,0H13.14c-2.043,0-3.608,1.154-3.749,2.721 C9.277,2.862,8.999,3.104,8.633,3.25l-0.1,0.039L8.439,3.341L6.495,4.406L6.363,4.479L6.245,4.573 C5.936,4.82,5.596,4.944,5.416,4.977c-0.314-0.139-0.66-0.21-1.011-0.21c-1.198,0-2.411,0.819-3.165,2.139L0.65,7.938 c-0.412,0.72-0.642,1.521-0.644,2.258c-0.003,0.952,0.362,1.756,1.013,2.256c0.034,0.155,0.061,0.448-0.016,0.786 c-0.038,0.168-0.062,0.28-0.062,1.563c0,1.148,0,1.148,0.015,1.262l0.009,0.073l0.017,0.073c0.073,0.346,0.045,0.643,0.011,0.802 C0.348,17.512-0.01,18.314,0,19.268c0.008,0.729,0.238,1.523,0.648,2.242l0.589,1.031c0.761,1.331,1.967,2.159,3.15,2.159 c0.324,0,0.645-0.064,0.938-0.187c0.167,0.038,0.492,0.156,0.813,0.416l0.11,0.088l0.124,0.07l2.045,1.156l0.102,0.057l0.107,0.043 c0.364,0.147,0.646,0.381,0.766,0.521c0.164,1.52,1.719,2.634,3.745,2.634h1.155c2.037,0,3.598-1.134,3.747-2.675 c0.117-0.145,0.401-0.393,0.774-0.549l0.111-0.047l0.105-0.062l1.96-1.159l0.105-0.062l0.097-0.075 c0.309-0.246,0.651-0.371,0.832-0.402c0.313,0.138,0.662,0.212,1.016,0.212c1.199,0,2.412-0.82,3.166-2.139l0.59-1.032 C27.387,20.48,27.575,19.342,27.315,18.389z M25.274,20.635l-0.59,1.032c-0.438,0.765-1.104,1.251-1.639,1.251 c-0.133,0-0.258-0.029-0.369-0.094c-0.15-0.086-0.346-0.127-0.566-0.127c-0.596,0-1.383,0.295-2.01,0.796l-1.96,1.157 c-1.016,0.425-1.846,1.291-1.846,1.929s-0.898,1.159-1.998,1.159H13.14c-1.1,0-1.998-0.514-1.998-1.141s-0.834-1.477-1.854-1.888 l-2.046-1.157c-0.636-0.511-1.425-0.814-2.006-0.814c-0.202,0-0.379,0.037-0.516,0.115c-0.101,0.057-0.214,0.084-0.333,0.084 c-0.518,0-1.179-0.498-1.62-1.271l-0.591-1.032c-0.545-0.954-0.556-1.983-0.024-2.286c0.532-0.305,0.78-1.432,0.551-2.506 c0,0,0-0.003,0-1.042c0-1.088,0.021-1.18,0.021-1.18c0.238-1.072-0.01-2.203-0.552-2.513C1.631,10.8,1.634,9.765,2.18,8.812 L2.769,7.78c0.438-0.766,1.103-1.251,1.636-1.251c0.131,0,0.255,0.029,0.365,0.092C4.92,6.707,5.114,6.747,5.334,6.747 c0.596,0,1.38-0.296,2.007-0.795l1.944-1.065c1.021-0.407,1.856-1.277,1.856-1.933c0-0.656,0.898-1.192,1.998-1.192h1.156V1.761 c1.1,0,1.998,0.545,1.998,1.211c0,0.667,0.832,1.554,1.849,1.973L20,6.013c0.618,0.489,1.401,0.775,2.012,0.775 c0.24,0,0.454-0.045,0.62-0.139c0.122-0.069,0.259-0.102,0.403-0.102c0.551,0,1.221,0.476,1.653,1.231l0.59,1.032 c0.544,0.953,0.518,2.004-0.062,2.334c-0.577,0.331-0.859,1.48-0.627,2.554c0,0,0.01,0.042,0.01,1.103c0,1.012,0,1.012,0,1.012 c-0.218,1.049,0.068,2.174,0.636,2.498C25.802,18.635,25.819,19.68,25.274,20.635z"/><path d="M13.61,7.611c-3.913,0-7.084,3.173-7.084,7.085c0,3.914,3.171,7.085,7.084,7.085s7.085-3.172,7.085-7.085 C20.695,10.784,17.523,7.611,13.61,7.611z M13.61,20.02c-2.936,0-5.323-2.388-5.323-5.323c0-2.935,2.388-5.323,5.323-5.323 s5.324,2.388,5.324,5.323C18.934,17.632,16.546,20.02,13.61,20.02z"/><path d="M13.682,9.908c-2.602,0-4.718,2.116-4.718,4.718c0,2.601,2.116,4.716,4.718,4.716c2.601,0,4.717-2.115,4.717-4.716 C18.399,12.024,16.283,9.908,13.682,9.908z M13.682,17.581c-1.633,0-2.956-1.323-2.956-2.955s1.323-2.956,2.956-2.956 c1.632,0,2.956,1.324,2.956,2.956S15.314,17.581,13.682,17.581z"/></g></svg> \ No newline at end of file
+<svg xmlns="http://www.w3.org/2000/svg" width="27.434" height="29.5" enable-background="new 0 0 27.434 29.5" viewBox="0 0 27.434 29.5"><path d="M27.316 18.39a2.696 2.696 0 0 0-.98-1.46 1.62 1.62 0 0 1-.016-.762l.035-.176v-1.191c0-1.246-.003-1.278-.046-1.473a1.717 1.717 0 0 1 .007-.805c.477-.343.829-.859.997-1.472.257-.957.074-2.094-.508-3.117l-.594-1.032c-.746-1.304-1.965-2.117-3.18-2.117-.379 0-.75.078-1.086.235a1.958 1.958 0 0 1-.855-.391l-.102-.082-.117-.063-1.855-1.07-.094-.055-.106-.043c-.378-.156-.66-.41-.77-.554C17.919 1.172 16.349 0 14.297 0h-1.155c-2.043 0-3.61 1.152-3.75 2.723-.114.14-.391.382-.758.527l-.102.04-.094.05-1.94 1.066-.134.074-.117.094a2.019 2.019 0 0 1-.832.403 2.518 2.518 0 0 0-1.008-.211c-1.199 0-2.414.82-3.168 2.14l-.59 1.032c-.41.718-.64 1.523-.64 2.257-.004.953.36 1.758 1.012 2.258.035.152.058.445-.016.785-.04.168-.063.282-.063 1.563 0 1.148 0 1.148.016 1.261l.008.075.015.074c.075.344.047.64.012.8-.644.5-1.004 1.302-.992 2.259.008.726.238 1.52.648 2.242l.59 1.027c.758 1.332 1.965 2.16 3.149 2.16.324 0 .644-.062.937-.187.168.039.492.156.813.418l.11.086.124.07 2.047 1.156.102.059.105.043c.363.144.648.379.766.52.164 1.519 1.718 2.632 3.746 2.632h1.156c2.035 0 3.598-1.133 3.746-2.672.117-.144.402-.394.773-.55l.114-.047.101-.063 1.961-1.156.106-.063.097-.078c.309-.246.653-.37.832-.398.313.136.66.21 1.016.21 1.2 0 2.41-.82 3.164-2.14l.594-1.031c.59-1.028.777-2.164.52-3.117Zm-2.043 2.247-.59 1.031c-.437.766-1.105 1.25-1.636 1.25a.7.7 0 0 1-.371-.094 1.146 1.146 0 0 0-.567-.129c-.593 0-1.382.297-2.007.797l-1.961 1.156c-1.016.426-1.848 1.293-1.848 1.93 0 .64-.898 1.16-1.996 1.16H13.14c-1.102 0-2-.515-2-1.14 0-.63-.832-1.477-1.852-1.887l-2.047-1.16c-.637-.512-1.426-.813-2.008-.813-.199 0-.379.035-.515.114a.648.648 0 0 1-.332.085c-.52 0-1.18-.5-1.621-1.273l-.59-1.031c-.543-.953-.555-1.98-.024-2.285.532-.305.782-1.434.551-2.504V14.8c0-1.09.02-1.18.02-1.18.238-1.074-.008-2.203-.551-2.516-.54-.304-.54-1.34.008-2.293l.59-1.03c.437-.766 1.101-1.255 1.636-1.255a.73.73 0 0 1 .364.094c.152.086.343.125.566.125.594 0 1.379-.297 2.004-.793l1.945-1.066c1.02-.407 1.856-1.278 1.856-1.934 0-.656.898-1.191 2-1.191h1.156c1.098 0 1.996.543 1.996 1.21 0 .669.832 1.555 1.848 1.973L20 6.012c.617.492 1.402.777 2.012.777.242 0 .453-.047.62-.14a.79.79 0 0 1 .403-.102c.55 0 1.223.476 1.652 1.23l.59 1.032c.543.953.52 2.004-.062 2.336-.574.332-.86 1.48-.625 2.554 0 0 .008.04.008 1.102v1.011c-.215 1.051.07 2.176.636 2.5.567.325.586 1.368.04 2.325Zm0 0"/><path d="M13.61 7.61a7.084 7.084 0 0 0-7.083 7.085 7.085 7.085 0 1 0 14.168 0A7.088 7.088 0 0 0 13.61 7.61Zm0 12.41a5.33 5.33 0 0 1-5.325-5.325 5.33 5.33 0 0 1 5.324-5.32 5.327 5.327 0 0 1 5.325 5.32 5.328 5.328 0 0 1-5.325 5.325Zm0 0"/><path d="M13.684 9.906a4.722 4.722 0 0 0-4.72 4.719 4.722 4.722 0 0 0 4.72 4.719 4.724 4.724 0 0 0 4.714-4.719 4.724 4.724 0 0 0-4.714-4.719Zm0 7.676a2.954 2.954 0 1 1 0-5.91 2.953 2.953 0 0 1 2.953 2.953 2.957 2.957 0 0 1-2.953 2.957Zm0 0"/></svg> \ No newline at end of file
diff --git a/src/librustdoc/html/static/js/main.js b/src/librustdoc/html/static/js/main.js
index 604ab147f..5e8c0e8d1 100644
--- a/src/librustdoc/html/static/js/main.js
+++ b/src/librustdoc/html/static/js/main.js
@@ -180,7 +180,6 @@ function browserSupportsHistoryApi() {
return window.history && typeof window.history.pushState === "function";
}
-// eslint-disable-next-line no-unused-vars
function loadCss(cssUrl) {
const link = document.createElement("link");
link.href = cssUrl;
@@ -379,7 +378,7 @@ function loadCss(cssUrl) {
}
ev.preventDefault();
searchState.defocus();
- window.hideAllModals(true); // true = reset focus for notable traits
+ window.hideAllModals(true); // true = reset focus for tooltips
}
function handleShortcut(ev) {
@@ -456,10 +455,7 @@ function loadCss(cssUrl) {
const ul = document.createElement("ul");
ul.className = "block " + shortty;
- for (const item of filtered) {
- const name = item[0];
- const desc = item[1]; // can be null
-
+ for (const name of filtered) {
let path;
if (shortty === "mod") {
path = name + "/index.html";
@@ -469,7 +465,6 @@ function loadCss(cssUrl) {
const current_page = document.location.href.split("/").pop();
const link = document.createElement("a");
link.href = path;
- link.title = desc;
if (path === current_page) {
link.className = "current";
}
@@ -789,17 +784,17 @@ function loadCss(cssUrl) {
// we need to switch away from mobile mode and make the main content area scrollable.
hideSidebar();
}
- if (window.CURRENT_NOTABLE_ELEMENT) {
- // As a workaround to the behavior of `contains: layout` used in doc togglers, the
- // notable traits popup is positioned using javascript.
+ if (window.CURRENT_TOOLTIP_ELEMENT) {
+ // As a workaround to the behavior of `contains: layout` used in doc togglers,
+ // tooltip popovers are positioned using javascript.
//
// This means when the window is resized, we need to redo the layout.
- const base = window.CURRENT_NOTABLE_ELEMENT.NOTABLE_BASE;
- const force_visible = base.NOTABLE_FORCE_VISIBLE;
- hideNotable(false);
+ const base = window.CURRENT_TOOLTIP_ELEMENT.TOOLTIP_BASE;
+ const force_visible = base.TOOLTIP_FORCE_VISIBLE;
+ hideTooltip(false);
if (force_visible) {
- showNotable(base);
- base.NOTABLE_FORCE_VISIBLE = true;
+ showTooltip(base);
+ base.TOOLTIP_FORCE_VISIBLE = true;
}
}
});
@@ -827,27 +822,35 @@ function loadCss(cssUrl) {
});
});
- function showNotable(e) {
- if (!window.NOTABLE_TRAITS) {
+ function showTooltip(e) {
+ const notable_ty = e.getAttribute("data-notable-ty");
+ if (!window.NOTABLE_TRAITS && notable_ty) {
const data = document.getElementById("notable-traits-data");
if (data) {
window.NOTABLE_TRAITS = JSON.parse(data.innerText);
} else {
- throw new Error("showNotable() called on page without any notable traits!");
+ throw new Error("showTooltip() called with notable without any notable traits!");
}
}
- if (window.CURRENT_NOTABLE_ELEMENT && window.CURRENT_NOTABLE_ELEMENT.NOTABLE_BASE === e) {
+ if (window.CURRENT_TOOLTIP_ELEMENT && window.CURRENT_TOOLTIP_ELEMENT.TOOLTIP_BASE === e) {
// Make this function idempotent.
return;
}
window.hideAllModals(false);
- const ty = e.getAttribute("data-ty");
const wrapper = document.createElement("div");
- wrapper.innerHTML = "<div class=\"content\">" + window.NOTABLE_TRAITS[ty] + "</div>";
- wrapper.className = "notable popover";
+ if (notable_ty) {
+ wrapper.innerHTML = "<div class=\"content\">" +
+ window.NOTABLE_TRAITS[notable_ty] + "</div>";
+ } else if (e.getAttribute("title") !== undefined) {
+ const titleContent = document.createElement("div");
+ titleContent.className = "content";
+ titleContent.appendChild(document.createTextNode(e.getAttribute("title")));
+ wrapper.appendChild(titleContent);
+ }
+ wrapper.className = "tooltip popover";
const focusCatcher = document.createElement("div");
focusCatcher.setAttribute("tabindex", "0");
- focusCatcher.onfocus = hideNotable;
+ focusCatcher.onfocus = hideTooltip;
wrapper.appendChild(focusCatcher);
const pos = e.getBoundingClientRect();
// 5px overlap so that the mouse can easily travel from place to place
@@ -869,62 +872,62 @@ function loadCss(cssUrl) {
);
}
wrapper.style.visibility = "";
- window.CURRENT_NOTABLE_ELEMENT = wrapper;
- window.CURRENT_NOTABLE_ELEMENT.NOTABLE_BASE = e;
+ window.CURRENT_TOOLTIP_ELEMENT = wrapper;
+ window.CURRENT_TOOLTIP_ELEMENT.TOOLTIP_BASE = e;
wrapper.onpointerleave = function(ev) {
// If this is a synthetic touch event, ignore it. A click event will be along shortly.
if (ev.pointerType !== "mouse") {
return;
}
- if (!e.NOTABLE_FORCE_VISIBLE && !elemIsInParent(event.relatedTarget, e)) {
- hideNotable(true);
+ if (!e.TOOLTIP_FORCE_VISIBLE && !elemIsInParent(event.relatedTarget, e)) {
+ hideTooltip(true);
}
};
}
- function notableBlurHandler(event) {
- if (window.CURRENT_NOTABLE_ELEMENT &&
- !elemIsInParent(document.activeElement, window.CURRENT_NOTABLE_ELEMENT) &&
- !elemIsInParent(event.relatedTarget, window.CURRENT_NOTABLE_ELEMENT) &&
- !elemIsInParent(document.activeElement, window.CURRENT_NOTABLE_ELEMENT.NOTABLE_BASE) &&
- !elemIsInParent(event.relatedTarget, window.CURRENT_NOTABLE_ELEMENT.NOTABLE_BASE)
+ function tooltipBlurHandler(event) {
+ if (window.CURRENT_TOOLTIP_ELEMENT &&
+ !elemIsInParent(document.activeElement, window.CURRENT_TOOLTIP_ELEMENT) &&
+ !elemIsInParent(event.relatedTarget, window.CURRENT_TOOLTIP_ELEMENT) &&
+ !elemIsInParent(document.activeElement, window.CURRENT_TOOLTIP_ELEMENT.TOOLTIP_BASE) &&
+ !elemIsInParent(event.relatedTarget, window.CURRENT_TOOLTIP_ELEMENT.TOOLTIP_BASE)
) {
// Work around a difference in the focus behaviour between Firefox, Chrome, and Safari.
- // When I click the button on an already-opened notable trait popover, Safari
+ // When I click the button on an already-opened tooltip popover, Safari
// hides the popover and then immediately shows it again, while everyone else hides it
// and it stays hidden.
//
// To work around this, make sure the click finishes being dispatched before
- // hiding the popover. Since `hideNotable()` is idempotent, this makes Safari behave
+ // hiding the popover. Since `hideTooltip()` is idempotent, this makes Safari behave
// consistently with the other two.
- setTimeout(() => hideNotable(false), 0);
+ setTimeout(() => hideTooltip(false), 0);
}
}
- function hideNotable(focus) {
- if (window.CURRENT_NOTABLE_ELEMENT) {
- if (window.CURRENT_NOTABLE_ELEMENT.NOTABLE_BASE.NOTABLE_FORCE_VISIBLE) {
+ function hideTooltip(focus) {
+ if (window.CURRENT_TOOLTIP_ELEMENT) {
+ if (window.CURRENT_TOOLTIP_ELEMENT.TOOLTIP_BASE.TOOLTIP_FORCE_VISIBLE) {
if (focus) {
- window.CURRENT_NOTABLE_ELEMENT.NOTABLE_BASE.focus();
+ window.CURRENT_TOOLTIP_ELEMENT.TOOLTIP_BASE.focus();
}
- window.CURRENT_NOTABLE_ELEMENT.NOTABLE_BASE.NOTABLE_FORCE_VISIBLE = false;
+ window.CURRENT_TOOLTIP_ELEMENT.TOOLTIP_BASE.TOOLTIP_FORCE_VISIBLE = false;
}
const body = document.getElementsByTagName("body")[0];
- body.removeChild(window.CURRENT_NOTABLE_ELEMENT);
- window.CURRENT_NOTABLE_ELEMENT = null;
+ body.removeChild(window.CURRENT_TOOLTIP_ELEMENT);
+ window.CURRENT_TOOLTIP_ELEMENT = null;
}
}
- onEachLazy(document.getElementsByClassName("notable-traits"), e => {
+ onEachLazy(document.getElementsByClassName("tooltip"), e => {
e.onclick = function() {
- this.NOTABLE_FORCE_VISIBLE = this.NOTABLE_FORCE_VISIBLE ? false : true;
- if (window.CURRENT_NOTABLE_ELEMENT && !this.NOTABLE_FORCE_VISIBLE) {
- hideNotable(true);
+ this.TOOLTIP_FORCE_VISIBLE = this.TOOLTIP_FORCE_VISIBLE ? false : true;
+ if (window.CURRENT_TOOLTIP_ELEMENT && !this.TOOLTIP_FORCE_VISIBLE) {
+ hideTooltip(true);
} else {
- showNotable(this);
- window.CURRENT_NOTABLE_ELEMENT.setAttribute("tabindex", "0");
- window.CURRENT_NOTABLE_ELEMENT.focus();
- window.CURRENT_NOTABLE_ELEMENT.onblur = notableBlurHandler;
+ showTooltip(this);
+ window.CURRENT_TOOLTIP_ELEMENT.setAttribute("tabindex", "0");
+ window.CURRENT_TOOLTIP_ELEMENT.focus();
+ window.CURRENT_TOOLTIP_ELEMENT.onblur = tooltipBlurHandler;
}
return false;
};
@@ -933,16 +936,16 @@ function loadCss(cssUrl) {
if (ev.pointerType !== "mouse") {
return;
}
- showNotable(this);
+ showTooltip(this);
};
e.onpointerleave = function(ev) {
// If this is a synthetic touch event, ignore it. A click event will be along shortly.
if (ev.pointerType !== "mouse") {
return;
}
- if (!this.NOTABLE_FORCE_VISIBLE &&
- !elemIsInParent(ev.relatedTarget, window.CURRENT_NOTABLE_ELEMENT)) {
- hideNotable(true);
+ if (!this.TOOLTIP_FORCE_VISIBLE &&
+ !elemIsInParent(ev.relatedTarget, window.CURRENT_TOOLTIP_ELEMENT)) {
+ hideTooltip(true);
}
};
});
@@ -1044,14 +1047,14 @@ function loadCss(cssUrl) {
}
/**
- * Hide popover menus, notable trait tooltips, and the sidebar (if applicable).
+ * Hide popover menus, clickable tooltips, and the sidebar (if applicable).
*
- * Pass "true" to reset focus for notable traits.
+ * Pass "true" to reset focus for tooltip popovers.
*/
window.hideAllModals = function(switchFocus) {
hideSidebar();
window.hidePopoverMenus();
- hideNotable(switchFocus);
+ hideTooltip(switchFocus);
};
/**
@@ -1142,7 +1145,11 @@ function loadCss(cssUrl) {
(function() {
let reset_button_timeout = null;
- window.copy_path = but => {
+ const but = document.getElementById("copy-path");
+ if (!but) {
+ return;
+ }
+ but.onclick = () => {
const parent = but.parentElement;
const path = [];
diff --git a/src/librustdoc/html/static/js/search.js b/src/librustdoc/html/static/js/search.js
index 88592fa0c..b98bced41 100644
--- a/src/librustdoc/html/static/js/search.js
+++ b/src/librustdoc/html/static/js/search.js
@@ -112,7 +112,6 @@ function levenshtein(s1, s2) {
}
function initSearch(rawSearchIndex) {
- const MAX_LEV_DISTANCE = 3;
const MAX_RESULTS = 200;
const NO_TYPE_FILTER = -1;
/**
@@ -143,13 +142,11 @@ function initSearch(rawSearchIndex) {
}
function itemTypeFromName(typename) {
- for (let i = 0, len = itemTypes.length; i < len; ++i) {
- if (itemTypes[i] === typename) {
- return i;
- }
+ const index = itemTypes.findIndex(i => i === typename);
+ if (index < 0) {
+ throw ["Unknown type filter ", typename];
}
-
- throw new Error("Unknown type filter `" + typename + "`");
+ return index;
}
/**
@@ -167,21 +164,21 @@ function initSearch(rawSearchIndex) {
*/
function getStringElem(query, parserState, isInGenerics) {
if (isInGenerics) {
- throw new Error("`\"` cannot be used in generics");
+ throw ["Unexpected ", "\"", " in generics"];
} else if (query.literalSearch) {
- throw new Error("Cannot have more than one literal search element");
+ throw ["Cannot have more than one literal search element"];
} else if (parserState.totalElems - parserState.genericsElems > 0) {
- throw new Error("Cannot use literal search when there is more than one element");
+ throw ["Cannot use literal search when there is more than one element"];
}
parserState.pos += 1;
const start = parserState.pos;
const end = getIdentEndPosition(parserState);
if (parserState.pos >= parserState.length) {
- throw new Error("Unclosed `\"`");
+ throw ["Unclosed ", "\""];
} else if (parserState.userQuery[end] !== "\"") {
- throw new Error(`Unexpected \`${parserState.userQuery[end]}\` in a string element`);
+ throw ["Unexpected ", parserState.userQuery[end], " in a string element"];
} else if (start === end) {
- throw new Error("Cannot have empty string element");
+ throw ["Cannot have empty string element"];
}
// To skip the quote at the end.
parserState.pos += 1;
@@ -260,7 +257,7 @@ function initSearch(rawSearchIndex) {
return;
}
if (query.literalSearch && parserState.totalElems - parserState.genericsElems > 0) {
- throw new Error("You cannot have more than one element if you use quotes");
+ throw ["You cannot have more than one element if you use quotes"];
}
const pathSegments = name.split("::");
if (pathSegments.length > 1) {
@@ -269,17 +266,17 @@ function initSearch(rawSearchIndex) {
if (pathSegment.length === 0) {
if (i === 0) {
- throw new Error("Paths cannot start with `::`");
+ throw ["Paths cannot start with ", "::"];
} else if (i + 1 === len) {
- throw new Error("Paths cannot end with `::`");
+ throw ["Paths cannot end with ", "::"];
}
- throw new Error("Unexpected `::::`");
+ throw ["Unexpected ", "::::"];
}
}
}
// In case we only have something like `<p>`, there is no name.
if (pathSegments.length === 0 || (pathSegments.length === 1 && pathSegments[0] === "")) {
- throw new Error("Found generics without a path");
+ throw ["Found generics without a path"];
}
parserState.totalElems += 1;
if (isInGenerics) {
@@ -303,22 +300,23 @@ function initSearch(rawSearchIndex) {
* @return {integer}
*/
function getIdentEndPosition(parserState) {
+ const start = parserState.pos;
let end = parserState.pos;
- let foundExclamation = false;
+ let foundExclamation = -1;
while (parserState.pos < parserState.length) {
const c = parserState.userQuery[parserState.pos];
if (!isIdentCharacter(c)) {
if (c === "!") {
- if (foundExclamation) {
- throw new Error("Cannot have more than one `!` in an ident");
+ if (foundExclamation !== -1) {
+ throw ["Cannot have more than one ", "!", " in an ident"];
} else if (parserState.pos + 1 < parserState.length &&
isIdentCharacter(parserState.userQuery[parserState.pos + 1])
) {
- throw new Error("`!` can only be at the end of an ident");
+ throw ["Unexpected ", "!", ": it can only be at the end of an ident"];
}
- foundExclamation = true;
+ foundExclamation = parserState.pos;
} else if (isErrorCharacter(c)) {
- throw new Error(`Unexpected \`${c}\``);
+ throw ["Unexpected ", c];
} else if (
isStopCharacter(c) ||
isSpecialStartCharacter(c) ||
@@ -329,16 +327,40 @@ function initSearch(rawSearchIndex) {
if (!isPathStart(parserState)) {
break;
}
+ if (foundExclamation !== -1) {
+ if (start <= (end - 2)) {
+ throw ["Cannot have associated items in macros"];
+ } else {
+ // if start == end - 1, we got the never type
+ // while the never type has no associated macros, we still
+ // can parse a path like that
+ foundExclamation = -1;
+ }
+ }
// Skip current ":".
parserState.pos += 1;
- foundExclamation = false;
} else {
- throw new Error(`Unexpected \`${c}\``);
+ throw ["Unexpected ", c];
}
}
parserState.pos += 1;
end = parserState.pos;
}
+ // if start == end - 1, we got the never type
+ if (foundExclamation !== -1 && start <= (end - 2)) {
+ if (parserState.typeFilter === null) {
+ parserState.typeFilter = "macro";
+ } else if (parserState.typeFilter !== "macro") {
+ throw [
+ "Invalid search type: macro ",
+ "!",
+ " and ",
+ parserState.typeFilter,
+ " both specified",
+ ];
+ }
+ end = foundExclamation;
+ }
return end;
}
@@ -365,9 +387,9 @@ function initSearch(rawSearchIndex) {
parserState.userQuery[parserState.pos] === "<"
) {
if (isInGenerics) {
- throw new Error("Unexpected `<` after `<`");
+ throw ["Unexpected ", "<", " after ", "<"];
} else if (start >= end) {
- throw new Error("Found generics without a path");
+ throw ["Found generics without a path"];
}
parserState.pos += 1;
getItemsBefore(query, parserState, generics, ">");
@@ -411,24 +433,51 @@ function initSearch(rawSearchIndex) {
foundStopChar = true;
continue;
} else if (c === ":" && isPathStart(parserState)) {
- throw new Error("Unexpected `::`: paths cannot start with `::`");
+ throw ["Unexpected ", "::", ": paths cannot start with ", "::"];
} else if (c === ":" || isEndCharacter(c)) {
let extra = "";
if (endChar === ">") {
- extra = "`<`";
+ extra = "<";
} else if (endChar === "") {
- extra = "`->`";
+ extra = "->";
+ } else {
+ extra = endChar;
}
- throw new Error("Unexpected `" + c + "` after " + extra);
+ throw ["Unexpected ", c, " after ", extra];
}
if (!foundStopChar) {
if (endChar !== "") {
- throw new Error(`Expected \`,\`, \` \` or \`${endChar}\`, found \`${c}\``);
+ throw [
+ "Expected ",
+ ",", // comma
+ ", ",
+ "&nbsp;", // whitespace
+ " or ",
+ endChar,
+ ", found ",
+ c,
+ ];
}
- throw new Error(`Expected \`,\` or \` \`, found \`${c}\``);
+ throw [
+ "Expected ",
+ ",", // comma
+ " or ",
+ "&nbsp;", // whitespace
+ ", found ",
+ c,
+ ];
}
const posBefore = parserState.pos;
getNextElem(query, parserState, elems, endChar === ">");
+ if (endChar !== "") {
+ if (parserState.pos >= parserState.length) {
+ throw ["Unclosed ", "<"];
+ }
+ const c2 = parserState.userQuery[parserState.pos];
+ if (!isSeparatorCharacter(c2) && c2 !== endChar) {
+ throw ["Expected ", endChar, ", found ", c2];
+ }
+ }
// This case can be encountered if `getNextElem` encountered a "stop character" right
// from the start. For example if you have `,,` or `<>`. In this case, we simply move up
// the current position to continue the parsing.
@@ -437,7 +486,10 @@ function initSearch(rawSearchIndex) {
}
foundStopChar = false;
}
- // We are either at the end of the string or on the `endChar`` character, let's move forward
+ if (parserState.pos >= parserState.length && endChar !== "") {
+ throw ["Unclosed ", "<"];
+ }
+ // We are either at the end of the string or on the `endChar` character, let's move forward
// in any case.
parserState.pos += 1;
}
@@ -453,7 +505,7 @@ function initSearch(rawSearchIndex) {
for (let pos = 0; pos < parserState.pos; ++pos) {
if (!isIdentCharacter(query[pos]) && !isWhitespaceCharacter(query[pos])) {
- throw new Error(`Unexpected \`${query[pos]}\` in type filter`);
+ throw ["Unexpected ", query[pos], " in type filter"];
}
}
}
@@ -466,11 +518,10 @@ function initSearch(rawSearchIndex) {
* @param {ParserState} parserState
*/
function parseInput(query, parserState) {
- let c, before;
let foundStopChar = true;
while (parserState.pos < parserState.length) {
- c = parserState.userQuery[parserState.pos];
+ const c = parserState.userQuery[parserState.pos];
if (isStopCharacter(c)) {
foundStopChar = true;
if (isSeparatorCharacter(c)) {
@@ -480,19 +531,19 @@ function initSearch(rawSearchIndex) {
if (isReturnArrow(parserState)) {
break;
}
- throw new Error(`Unexpected \`${c}\` (did you mean \`->\`?)`);
+ throw ["Unexpected ", c, " (did you mean ", "->", "?)"];
}
- throw new Error(`Unexpected \`${c}\``);
+ throw ["Unexpected ", c];
} else if (c === ":" && !isPathStart(parserState)) {
if (parserState.typeFilter !== null) {
- throw new Error("Unexpected `:`");
+ throw ["Unexpected ", ":"];
}
if (query.elems.length === 0) {
- throw new Error("Expected type filter before `:`");
+ throw ["Expected type filter before ", ":"];
} else if (query.elems.length !== 1 || parserState.totalElems !== 1) {
- throw new Error("Unexpected `:`");
+ throw ["Unexpected ", ":"];
} else if (query.literalSearch) {
- throw new Error("You cannot use quotes on type filter");
+ throw ["You cannot use quotes on type filter"];
}
checkExtraTypeFilterCharacters(parserState);
// The type filter doesn't count as an element since it's a modifier.
@@ -505,11 +556,31 @@ function initSearch(rawSearchIndex) {
}
if (!foundStopChar) {
if (parserState.typeFilter !== null) {
- throw new Error(`Expected \`,\`, \` \` or \`->\`, found \`${c}\``);
+ throw [
+ "Expected ",
+ ",", // comma
+ ", ",
+ "&nbsp;", // whitespace
+ " or ",
+ "->", // arrow
+ ", found ",
+ c,
+ ];
}
- throw new Error(`Expected \`,\`, \` \`, \`:\` or \`->\`, found \`${c}\``);
- }
- before = query.elems.length;
+ throw [
+ "Expected ",
+ ",", // comma
+ ", ",
+ "&nbsp;", // whitespace
+ ", ",
+ ":", // colon
+ " or ",
+ "->", // arrow
+ ", found ",
+ c,
+ ];
+ }
+ const before = query.elems.length;
getNextElem(query, parserState, query.elems, false);
if (query.elems.length === before) {
// Nothing was added, weird... Let's increase the position to not remain stuck.
@@ -518,14 +589,13 @@ function initSearch(rawSearchIndex) {
foundStopChar = false;
}
while (parserState.pos < parserState.length) {
- c = parserState.userQuery[parserState.pos];
if (isReturnArrow(parserState)) {
parserState.pos += 2;
// Get returned elements.
getItemsBefore(query, parserState, query.returned, "");
// Nothing can come afterward!
if (query.returned.length === 0) {
- throw new Error("Expected at least one item after `->`");
+ throw ["Expected at least one item after ", "->"];
}
break;
} else {
@@ -594,8 +664,8 @@ function initSearch(rawSearchIndex) {
*
* The supported syntax by this parser is as follow:
*
- * ident = *(ALPHA / DIGIT / "_") [!]
- * path = ident *(DOUBLE-COLON ident)
+ * ident = *(ALPHA / DIGIT / "_")
+ * path = ident *(DOUBLE-COLON ident) [!]
* arg = path [generics]
* arg-without-generic = path
* type-sep = COMMA/WS *(COMMA/WS)
@@ -679,7 +749,7 @@ function initSearch(rawSearchIndex) {
}
} catch (err) {
query = newParsedQuery(userQuery);
- query.error = err.message;
+ query.error = err;
query.typeFilter = -1;
return query;
}
@@ -897,13 +967,13 @@ function initSearch(rawSearchIndex) {
* @param {QueryElement} elem - The element from the parsed query.
* @param {integer} defaultLev - This is the value to return in case there are no generics.
*
- * @return {integer} - Returns the best match (if any) or `MAX_LEV_DISTANCE + 1`.
+ * @return {integer} - Returns the best match (if any) or `maxLevDistance + 1`.
*/
- function checkGenerics(row, elem, defaultLev) {
+ function checkGenerics(row, elem, defaultLev, maxLevDistance) {
if (row.generics.length === 0) {
- return elem.generics.length === 0 ? defaultLev : MAX_LEV_DISTANCE + 1;
+ return elem.generics.length === 0 ? defaultLev : maxLevDistance + 1;
} else if (row.generics.length > 0 && row.generics[0].name === null) {
- return checkGenerics(row.generics[0], elem, defaultLev);
+ return checkGenerics(row.generics[0], elem, defaultLev, maxLevDistance);
}
// The names match, but we need to be sure that all generics kinda
// match as well.
@@ -914,8 +984,8 @@ function initSearch(rawSearchIndex) {
elem_name = entry.name;
if (elem_name === "") {
// Pure generic, needs to check into it.
- if (checkGenerics(entry, elem, MAX_LEV_DISTANCE + 1) !== 0) {
- return MAX_LEV_DISTANCE + 1;
+ if (checkGenerics(entry, elem, maxLevDistance + 1, maxLevDistance) !== 0) {
+ return maxLevDistance + 1;
}
continue;
}
@@ -942,7 +1012,7 @@ function initSearch(rawSearchIndex) {
}
}
if (match === null) {
- return MAX_LEV_DISTANCE + 1;
+ return maxLevDistance + 1;
}
elems[match] -= 1;
if (elems[match] === 0) {
@@ -951,7 +1021,7 @@ function initSearch(rawSearchIndex) {
}
return 0;
}
- return MAX_LEV_DISTANCE + 1;
+ return maxLevDistance + 1;
}
/**
@@ -963,10 +1033,10 @@ function initSearch(rawSearchIndex) {
*
* @return {integer} - Returns a Levenshtein distance to the best match.
*/
- function checkIfInGenerics(row, elem) {
- let lev = MAX_LEV_DISTANCE + 1;
+ function checkIfInGenerics(row, elem, maxLevDistance) {
+ let lev = maxLevDistance + 1;
for (const entry of row.generics) {
- lev = Math.min(checkType(entry, elem, true), lev);
+ lev = Math.min(checkType(entry, elem, true, maxLevDistance), lev);
if (lev === 0) {
break;
}
@@ -983,15 +1053,15 @@ function initSearch(rawSearchIndex) {
* @param {boolean} literalSearch
*
* @return {integer} - Returns a Levenshtein distance to the best match. If there is
- * no match, returns `MAX_LEV_DISTANCE + 1`.
+ * no match, returns `maxLevDistance + 1`.
*/
- function checkType(row, elem, literalSearch) {
+ function checkType(row, elem, literalSearch, maxLevDistance) {
if (row.name === null) {
// This is a pure "generic" search, no need to run other checks.
if (row.generics.length > 0) {
- return checkIfInGenerics(row, elem);
+ return checkIfInGenerics(row, elem, maxLevDistance);
}
- return MAX_LEV_DISTANCE + 1;
+ return maxLevDistance + 1;
}
let lev = levenshtein(row.name, elem.name);
@@ -1005,9 +1075,9 @@ function initSearch(rawSearchIndex) {
return 0;
}
}
- return MAX_LEV_DISTANCE + 1;
+ return maxLevDistance + 1;
} else if (elem.generics.length > 0) {
- return checkGenerics(row, elem, MAX_LEV_DISTANCE + 1);
+ return checkGenerics(row, elem, maxLevDistance + 1, maxLevDistance);
}
return 0;
} else if (row.generics.length > 0) {
@@ -1017,22 +1087,20 @@ function initSearch(rawSearchIndex) {
}
// The name didn't match so we now check if the type we're looking for is inside
// the generics!
- lev = checkIfInGenerics(row, elem);
- // Now whatever happens, the returned distance is "less good" so we should mark
- // it as such, and so we add 0.5 to the distance to make it "less good".
- return lev + 0.5;
- } else if (lev > MAX_LEV_DISTANCE) {
+ lev = Math.min(lev, checkIfInGenerics(row, elem, maxLevDistance));
+ return lev;
+ } else if (lev > maxLevDistance) {
// So our item's name doesn't match at all and has generics.
//
// Maybe it's present in a sub generic? For example "f<A<B<C>>>()", if we're
// looking for "B<C>", we'll need to go down.
- return checkIfInGenerics(row, elem);
+ return checkIfInGenerics(row, elem, maxLevDistance);
} else {
// At this point, the name kinda match and we have generics to check, so
// let's go!
- const tmp_lev = checkGenerics(row, elem, lev);
- if (tmp_lev > MAX_LEV_DISTANCE) {
- return MAX_LEV_DISTANCE + 1;
+ const tmp_lev = checkGenerics(row, elem, lev, maxLevDistance);
+ if (tmp_lev > maxLevDistance) {
+ return maxLevDistance + 1;
}
// We compute the median value of both checks and return it.
return (tmp_lev + lev) / 2;
@@ -1040,7 +1108,7 @@ function initSearch(rawSearchIndex) {
} else if (elem.generics.length > 0) {
// In this case, we were expecting generics but there isn't so we simply reject this
// one.
- return MAX_LEV_DISTANCE + 1;
+ return maxLevDistance + 1;
}
// No generics on our query or on the target type so we can return without doing
// anything else.
@@ -1055,23 +1123,26 @@ function initSearch(rawSearchIndex) {
* @param {integer} typeFilter
*
* @return {integer} - Returns a Levenshtein distance to the best match. If there is no
- * match, returns `MAX_LEV_DISTANCE + 1`.
+ * match, returns `maxLevDistance + 1`.
*/
- function findArg(row, elem, typeFilter) {
- let lev = MAX_LEV_DISTANCE + 1;
+ function findArg(row, elem, typeFilter, maxLevDistance) {
+ let lev = maxLevDistance + 1;
if (row && row.type && row.type.inputs && row.type.inputs.length > 0) {
for (const input of row.type.inputs) {
if (!typePassesFilter(typeFilter, input.ty)) {
continue;
}
- lev = Math.min(lev, checkType(input, elem, parsedQuery.literalSearch));
+ lev = Math.min(
+ lev,
+ checkType(input, elem, parsedQuery.literalSearch, maxLevDistance)
+ );
if (lev === 0) {
return 0;
}
}
}
- return parsedQuery.literalSearch ? MAX_LEV_DISTANCE + 1 : lev;
+ return parsedQuery.literalSearch ? maxLevDistance + 1 : lev;
}
/**
@@ -1082,10 +1153,10 @@ function initSearch(rawSearchIndex) {
* @param {integer} typeFilter
*
* @return {integer} - Returns a Levenshtein distance to the best match. If there is no
- * match, returns `MAX_LEV_DISTANCE + 1`.
+ * match, returns `maxLevDistance + 1`.
*/
- function checkReturned(row, elem, typeFilter) {
- let lev = MAX_LEV_DISTANCE + 1;
+ function checkReturned(row, elem, typeFilter, maxLevDistance) {
+ let lev = maxLevDistance + 1;
if (row && row.type && row.type.output.length > 0) {
const ret = row.type.output;
@@ -1093,20 +1164,23 @@ function initSearch(rawSearchIndex) {
if (!typePassesFilter(typeFilter, ret_ty.ty)) {
continue;
}
- lev = Math.min(lev, checkType(ret_ty, elem, parsedQuery.literalSearch));
+ lev = Math.min(
+ lev,
+ checkType(ret_ty, elem, parsedQuery.literalSearch, maxLevDistance)
+ );
if (lev === 0) {
return 0;
}
}
}
- return parsedQuery.literalSearch ? MAX_LEV_DISTANCE + 1 : lev;
+ return parsedQuery.literalSearch ? maxLevDistance + 1 : lev;
}
- function checkPath(contains, ty) {
+ function checkPath(contains, ty, maxLevDistance) {
if (contains.length === 0) {
return 0;
}
- let ret_lev = MAX_LEV_DISTANCE + 1;
+ let ret_lev = maxLevDistance + 1;
const path = ty.path.split("::");
if (ty.parent && ty.parent.name) {
@@ -1116,7 +1190,7 @@ function initSearch(rawSearchIndex) {
const length = path.length;
const clength = contains.length;
if (clength > length) {
- return MAX_LEV_DISTANCE + 1;
+ return maxLevDistance + 1;
}
for (let i = 0; i < length; ++i) {
if (i + clength > length) {
@@ -1126,7 +1200,7 @@ function initSearch(rawSearchIndex) {
let aborted = false;
for (let x = 0; x < clength; ++x) {
const lev = levenshtein(path[i + x], contains[x]);
- if (lev > MAX_LEV_DISTANCE) {
+ if (lev > maxLevDistance) {
aborted = true;
break;
}
@@ -1231,7 +1305,7 @@ function initSearch(rawSearchIndex) {
* following condition:
*
* * If it is a "literal search" (`parsedQuery.literalSearch`), then `lev` must be 0.
- * * If it is not a "literal search", `lev` must be <= `MAX_LEV_DISTANCE`.
+ * * If it is not a "literal search", `lev` must be <= `maxLevDistance`.
*
* The `results` map contains information which will be used to sort the search results:
*
@@ -1249,8 +1323,8 @@ function initSearch(rawSearchIndex) {
* @param {integer} lev
* @param {integer} path_lev
*/
- function addIntoResults(results, fullId, id, index, lev, path_lev) {
- const inBounds = lev <= MAX_LEV_DISTANCE || index !== -1;
+ function addIntoResults(results, fullId, id, index, lev, path_lev, maxLevDistance) {
+ const inBounds = lev <= maxLevDistance || index !== -1;
if (lev === 0 || (!parsedQuery.literalSearch && inBounds)) {
if (results[fullId] !== undefined) {
const result = results[fullId];
@@ -1289,7 +1363,8 @@ function initSearch(rawSearchIndex) {
elem,
results_others,
results_in_args,
- results_returned
+ results_returned,
+ maxLevDistance
) {
if (!row || (filterCrates !== null && row.crate !== filterCrates)) {
return;
@@ -1298,13 +1373,13 @@ function initSearch(rawSearchIndex) {
const fullId = row.id;
const searchWord = searchWords[pos];
- const in_args = findArg(row, elem, parsedQuery.typeFilter);
- const returned = checkReturned(row, elem, parsedQuery.typeFilter);
+ const in_args = findArg(row, elem, parsedQuery.typeFilter, maxLevDistance);
+ const returned = checkReturned(row, elem, parsedQuery.typeFilter, maxLevDistance);
// path_lev is 0 because no parent path information is currently stored
// in the search index
- addIntoResults(results_in_args, fullId, pos, -1, in_args, 0);
- addIntoResults(results_returned, fullId, pos, -1, returned, 0);
+ addIntoResults(results_in_args, fullId, pos, -1, in_args, 0, maxLevDistance);
+ addIntoResults(results_returned, fullId, pos, -1, returned, 0, maxLevDistance);
if (!typePassesFilter(parsedQuery.typeFilter, row.ty)) {
return;
@@ -1328,16 +1403,16 @@ function initSearch(rawSearchIndex) {
// No need to check anything else if it's a "pure" generics search.
if (elem.name.length === 0) {
if (row.type !== null) {
- lev = checkGenerics(row.type, elem, MAX_LEV_DISTANCE + 1);
+ lev = checkGenerics(row.type, elem, maxLevDistance + 1, maxLevDistance);
// path_lev is 0 because we know it's empty
- addIntoResults(results_others, fullId, pos, index, lev, 0);
+ addIntoResults(results_others, fullId, pos, index, lev, 0, maxLevDistance);
}
return;
}
if (elem.fullPath.length > 1) {
- path_lev = checkPath(elem.pathWithoutLast, row);
- if (path_lev > MAX_LEV_DISTANCE) {
+ path_lev = checkPath(elem.pathWithoutLast, row, maxLevDistance);
+ if (path_lev > maxLevDistance) {
return;
}
}
@@ -1351,11 +1426,11 @@ function initSearch(rawSearchIndex) {
lev = levenshtein(searchWord, elem.pathLast);
- if (index === -1 && lev + path_lev > MAX_LEV_DISTANCE) {
+ if (index === -1 && lev + path_lev > maxLevDistance) {
return;
}
- addIntoResults(results_others, fullId, pos, index, lev, path_lev);
+ addIntoResults(results_others, fullId, pos, index, lev, path_lev, maxLevDistance);
}
/**
@@ -1367,7 +1442,7 @@ function initSearch(rawSearchIndex) {
* @param {integer} pos - Position in the `searchIndex`.
* @param {Object} results
*/
- function handleArgs(row, pos, results) {
+ function handleArgs(row, pos, results, maxLevDistance) {
if (!row || (filterCrates !== null && row.crate !== filterCrates)) {
return;
}
@@ -1379,7 +1454,7 @@ function initSearch(rawSearchIndex) {
function checkArgs(elems, callback) {
for (const elem of elems) {
// There is more than one parameter to the query so all checks should be "exact"
- const lev = callback(row, elem, NO_TYPE_FILTER);
+ const lev = callback(row, elem, NO_TYPE_FILTER, maxLevDistance);
if (lev <= 1) {
nbLev += 1;
totalLev += lev;
@@ -1400,12 +1475,21 @@ function initSearch(rawSearchIndex) {
return;
}
const lev = Math.round(totalLev / nbLev);
- addIntoResults(results, row.id, pos, 0, lev, 0);
+ addIntoResults(results, row.id, pos, 0, lev, 0, maxLevDistance);
}
function innerRunQuery() {
let elem, i, nSearchWords, in_returned, row;
+ let queryLen = 0;
+ for (const elem of parsedQuery.elems) {
+ queryLen += elem.name.length;
+ }
+ for (const elem of parsedQuery.returned) {
+ queryLen += elem.name.length;
+ }
+ const maxLevDistance = Math.floor(queryLen / 3);
+
if (parsedQuery.foundElems === 1) {
if (parsedQuery.elems.length === 1) {
elem = parsedQuery.elems[0];
@@ -1418,7 +1502,8 @@ function initSearch(rawSearchIndex) {
elem,
results_others,
results_in_args,
- results_returned
+ results_returned,
+ maxLevDistance
);
}
} else if (parsedQuery.returned.length === 1) {
@@ -1426,13 +1511,18 @@ function initSearch(rawSearchIndex) {
elem = parsedQuery.returned[0];
for (i = 0, nSearchWords = searchWords.length; i < nSearchWords; ++i) {
row = searchIndex[i];
- in_returned = checkReturned(row, elem, parsedQuery.typeFilter);
- addIntoResults(results_others, row.id, i, -1, in_returned);
+ in_returned = checkReturned(
+ row,
+ elem,
+ parsedQuery.typeFilter,
+ maxLevDistance
+ );
+ addIntoResults(results_others, row.id, i, -1, in_returned, maxLevDistance);
}
}
} else if (parsedQuery.foundElems > 0) {
for (i = 0, nSearchWords = searchWords.length; i < nSearchWords; ++i) {
- handleArgs(searchIndex[i], i, results_others);
+ handleArgs(searchIndex[i], i, results_others, maxLevDistance);
}
}
}
@@ -1470,7 +1560,7 @@ function initSearch(rawSearchIndex) {
*
* @return {boolean} - Whether the result is valid or not
*/
- function validateResult(name, path, keys, parent) {
+ function validateResult(name, path, keys, parent, maxLevDistance) {
if (!keys || !keys.length) {
return true;
}
@@ -1485,7 +1575,7 @@ function initSearch(rawSearchIndex) {
(parent !== undefined && parent.name !== undefined &&
parent.name.toLowerCase().indexOf(key) > -1) ||
// lastly check to see if the name was a levenshtein match
- levenshtein(name, key) <= MAX_LEV_DISTANCE)) {
+ levenshtein(name, key) <= maxLevDistance)) {
return false;
}
}
@@ -1725,7 +1815,16 @@ function initSearch(rawSearchIndex) {
let output = `<h1 class="search-results-title">Results${crates}</h1>`;
if (results.query.error !== null) {
- output += `<h3>Query parser error: "${results.query.error}".</h3>`;
+ const error = results.query.error;
+ error.forEach((value, index) => {
+ value = value.split("<").join("&lt;").split(">").join("&gt;");
+ if (index % 2 !== 0) {
+ error[index] = `<code>${value}</code>`;
+ } else {
+ error[index] = value;
+ }
+ });
+ output += `<h3 class="error">Query parser error: "${error.join("")}".</h3>`;
output += "<div id=\"search-tabs\">" +
makeTabHeader(0, "In Names", ret_others[1]) +
"</div>";
@@ -1922,7 +2021,7 @@ function initSearch(rawSearchIndex) {
* @type {Array<string>}
*/
const searchWords = [];
- let i, word;
+ const charA = "A".charCodeAt(0);
let currentIndex = 0;
let id = 0;
@@ -1936,7 +2035,7 @@ function initSearch(rawSearchIndex) {
/**
* The raw search data for a given crate. `n`, `t`, `d`, and `q`, `i`, and `f`
* are arrays with the same length. n[i] contains the name of an item.
- * t[i] contains the type of that item (as a small integer that represents an
+ * t[i] contains the type of that item (as a string of characters that represent an
* offset in `itemTypes`). d[i] contains the description of that item.
*
* q[i] contains the full path of the item, or an empty string indicating
@@ -1963,7 +2062,7 @@ function initSearch(rawSearchIndex) {
* doc: string,
* a: Object,
* n: Array<string>,
- * t: Array<Number>,
+ * t: String,
* d: Array<string>,
* q: Array<string>,
* i: Array<Number>,
@@ -1992,7 +2091,7 @@ function initSearch(rawSearchIndex) {
searchIndex.push(crateRow);
currentIndex += 1;
- // an array of (Number) item types
+ // a String of one character item type codes
const itemTypes = crateCorpus.t;
// an array of (String) item names
const itemNames = crateCorpus.n;
@@ -2017,7 +2116,7 @@ function initSearch(rawSearchIndex) {
// convert `rawPaths` entries into object form
// generate normalizedPaths for function search mode
let len = paths.length;
- for (i = 0; i < len; ++i) {
+ for (let i = 0; i < len; ++i) {
lowercasePaths.push({ty: paths[i][0], name: paths[i][1].toLowerCase()});
paths[i] = {ty: paths[i][0], name: paths[i][1]};
}
@@ -2031,19 +2130,17 @@ function initSearch(rawSearchIndex) {
// faster analysis operations
len = itemTypes.length;
let lastPath = "";
- for (i = 0; i < len; ++i) {
+ for (let i = 0; i < len; ++i) {
+ let word = "";
// This object should have exactly the same set of fields as the "crateRow"
// object defined above.
if (typeof itemNames[i] === "string") {
word = itemNames[i].toLowerCase();
- searchWords.push(word);
- } else {
- word = "";
- searchWords.push("");
}
+ searchWords.push(word);
const row = {
crate: crate,
- ty: itemTypes[i],
+ ty: itemTypes.charCodeAt(i) - charA,
name: itemNames[i],
path: itemPaths[i] ? itemPaths[i] : lastPath,
desc: itemDescs[i],
diff --git a/src/librustdoc/html/static/js/settings.js b/src/librustdoc/html/static/js/settings.js
index 84df1b7d3..1cd552e7f 100644
--- a/src/librustdoc/html/static/js/settings.js
+++ b/src/librustdoc/html/static/js/settings.js
@@ -1,5 +1,5 @@
// Local js definitions:
-/* global getSettingValue, getVirtualKey, updateLocalStorage, updateSystemTheme */
+/* global getSettingValue, getVirtualKey, updateLocalStorage, updateTheme */
/* global addClass, removeClass, onEach, onEachLazy, blurHandler, elemIsInParent */
/* global MAIN_ID, getVar, getSettingsButton */
@@ -19,7 +19,7 @@
case "theme":
case "preferred-dark-theme":
case "preferred-light-theme":
- updateSystemTheme();
+ updateTheme();
updateLightAndDark();
break;
case "line-numbers":
@@ -48,13 +48,13 @@
}
function showLightAndDark() {
- removeClass(document.getElementById("preferred-light-theme").parentElement, "hidden");
- removeClass(document.getElementById("preferred-dark-theme").parentElement, "hidden");
+ removeClass(document.getElementById("preferred-light-theme"), "hidden");
+ removeClass(document.getElementById("preferred-dark-theme"), "hidden");
}
function hideLightAndDark() {
- addClass(document.getElementById("preferred-light-theme").parentElement, "hidden");
- addClass(document.getElementById("preferred-dark-theme").parentElement, "hidden");
+ addClass(document.getElementById("preferred-light-theme"), "hidden");
+ addClass(document.getElementById("preferred-dark-theme"), "hidden");
}
function updateLightAndDark() {
@@ -80,17 +80,6 @@
toggle.onkeyup = handleKey;
toggle.onkeyrelease = handleKey;
});
- onEachLazy(settingsElement.getElementsByClassName("select-wrapper"), elem => {
- const select = elem.getElementsByTagName("select")[0];
- const settingId = select.id;
- const settingValue = getSettingValue(settingId);
- if (settingValue !== null) {
- select.value = settingValue;
- }
- select.onchange = function() {
- changeSetting(this.id, this.value);
- };
- });
onEachLazy(settingsElement.querySelectorAll("input[type=\"radio\"]"), elem => {
const settingId = elem.name;
let settingValue = getSettingValue(settingId);
@@ -127,38 +116,40 @@
let output = "";
for (const setting of settings) {
- output += "<div class=\"setting-line\">";
const js_data_name = setting["js_name"];
const setting_name = setting["name"];
if (setting["options"] !== undefined) {
// This is a select setting.
output += `\
-<div class="radio-line" id="${js_data_name}">
- <div class="setting-name">${setting_name}</div>
-<div class="choices">`;
+<div class="setting-line" id="${js_data_name}">
+ <div class="setting-radio-name">${setting_name}</div>
+ <div class="setting-radio-choices">`;
onEach(setting["options"], option => {
const checked = option === setting["default"] ? " checked" : "";
const full = `${js_data_name}-${option.replace(/ /g,"-")}`;
output += `\
-<label for="${full}" class="choice">
- <input type="radio" name="${js_data_name}"
- id="${full}" value="${option}"${checked}>
- <span>${option}</span>
-</label>`;
+ <label for="${full}" class="setting-radio">
+ <input type="radio" name="${js_data_name}"
+ id="${full}" value="${option}"${checked}>
+ <span>${option}</span>
+ </label>`;
});
- output += "</div></div>";
+ output += `\
+ </div>
+</div>`;
} else {
// This is a checkbox toggle.
const checked = setting["default"] === true ? " checked" : "";
output += `\
-<label class="settings-toggle">\
- <input type="checkbox" id="${js_data_name}"${checked}>\
- <span class="label">${setting_name}</span>\
-</label>`;
+<div class="setting-line">\
+ <label class="setting-check">\
+ <input type="checkbox" id="${js_data_name}"${checked}>\
+ <span>${setting_name}</span>\
+ </label>\
+</div>`;
}
- output += "</div>";
}
return output;
}
diff --git a/src/librustdoc/html/static/js/source-script.js b/src/librustdoc/html/static/js/source-script.js
index 0e1c864e6..6c0f03b5b 100644
--- a/src/librustdoc/html/static/js/source-script.js
+++ b/src/librustdoc/html/static/js/source-script.js
@@ -117,8 +117,7 @@ function createSourceSidebar() {
sidebar.appendChild(title);
Object.keys(sourcesIndex).forEach(key => {
sourcesIndex[key][NAME_OFFSET] = key;
- hasFoundFile = createDirEntry(sourcesIndex[key], sidebar, "",
- hasFoundFile);
+ hasFoundFile = createDirEntry(sourcesIndex[key], sidebar, "", hasFoundFile);
});
container.appendChild(sidebar);
diff --git a/src/librustdoc/html/static/js/storage.js b/src/librustdoc/html/static/js/storage.js
index db2db83ca..c72ac254f 100644
--- a/src/librustdoc/html/static/js/storage.js
+++ b/src/librustdoc/html/static/js/storage.js
@@ -51,7 +51,6 @@ function hasClass(elem, className) {
return elem && elem.classList && elem.classList.contains(className);
}
-// eslint-disable-next-line no-unused-vars
function addClass(elem, className) {
if (!elem || !elem.classList) {
return;
@@ -153,79 +152,74 @@ function switchTheme(styleElem, mainStyleElem, newThemeName, saveTheme) {
}
}
-// This function is called from "main.js".
-// eslint-disable-next-line no-unused-vars
-function useSystemTheme(value) {
- if (value === undefined) {
- value = true;
- }
-
- updateLocalStorage("use-system-theme", value);
-
- // update the toggle if we're on the settings page
- const toggle = document.getElementById("use-system-theme");
- if (toggle && toggle instanceof HTMLInputElement) {
- toggle.checked = value;
- }
-}
-
-const updateSystemTheme = (function() {
- if (!window.matchMedia) {
- // fallback to the CSS computed value
- return () => {
- const cssTheme = getComputedStyle(document.documentElement)
- .getPropertyValue("content");
-
- switchTheme(
- window.currentTheme,
- window.mainTheme,
- JSON.parse(cssTheme) || "light",
- true
- );
+const updateTheme = (function() {
+ /**
+ * Update the current theme to match whatever the current combination of
+ * * the preference for using the system theme
+ * (if this is the case, the value of preferred-light-theme, if the
+ * system theme is light, otherwise if dark, the value of
+ * preferred-dark-theme.)
+ * * the preferred theme
+ * … dictates that it should be.
+ */
+ function updateTheme() {
+ const use = (theme, saveTheme) => {
+ switchTheme(window.currentTheme, window.mainTheme, theme, saveTheme);
};
- }
-
- // only listen to (prefers-color-scheme: dark) because light is the default
- const mql = window.matchMedia("(prefers-color-scheme: dark)");
- function handlePreferenceChange(mql) {
- const use = theme => {
- switchTheme(window.currentTheme, window.mainTheme, theme, true);
- };
// maybe the user has disabled the setting in the meantime!
if (getSettingValue("use-system-theme") !== "false") {
const lightTheme = getSettingValue("preferred-light-theme") || "light";
const darkTheme = getSettingValue("preferred-dark-theme") || "dark";
- if (mql.matches) {
- use(darkTheme);
+ if (isDarkMode()) {
+ use(darkTheme, true);
} else {
// prefers a light theme, or has no preference
- use(lightTheme);
+ use(lightTheme, true);
}
// note: we save the theme so that it doesn't suddenly change when
// the user disables "use-system-theme" and reloads the page or
// navigates to another page
} else {
- use(getSettingValue("theme"));
+ use(getSettingValue("theme"), false);
}
}
- mql.addListener(handlePreferenceChange);
+ // This is always updated below to a function () => bool.
+ let isDarkMode;
- return () => {
- handlePreferenceChange(mql);
- };
-})();
+ // Determine the function for isDarkMode, and if we have
+ // `window.matchMedia`, set up an event listener on the preferred color
+ // scheme.
+ //
+ // Otherwise, fall back to the prefers-color-scheme value CSS captured in
+ // the "content" property.
+ if (window.matchMedia) {
+ // only listen to (prefers-color-scheme: dark) because light is the default
+ const mql = window.matchMedia("(prefers-color-scheme: dark)");
-function switchToSavedTheme() {
- switchTheme(
- window.currentTheme,
- window.mainTheme,
- getSettingValue("theme") || "light",
- false
- );
-}
+ isDarkMode = () => mql.matches;
+
+ if (mql.addEventListener) {
+ mql.addEventListener("change", updateTheme);
+ } else {
+ // This is deprecated, see:
+ // https://developer.mozilla.org/en-US/docs/Web/API/MediaQueryList/addListener
+ mql.addListener(updateTheme);
+ }
+ } else {
+ // fallback to the CSS computed value
+ const cssContent = getComputedStyle(document.documentElement)
+ .getPropertyValue("content");
+ // (Note: the double-quotes come from that this is a CSS value, which
+ // might be a length, string, etc.)
+ const cssColorScheme = cssContent || "\"light\"";
+ isDarkMode = () => (cssColorScheme === "\"dark\"");
+ }
+
+ return updateTheme;
+})();
if (getSettingValue("use-system-theme") !== "false" && window.matchMedia) {
// update the preferred dark theme if the user is already using a dark theme
@@ -235,13 +229,10 @@ if (getSettingValue("use-system-theme") !== "false" && window.matchMedia) {
&& darkThemes.indexOf(localStoredTheme) >= 0) {
updateLocalStorage("preferred-dark-theme", localStoredTheme);
}
-
- // call the function to initialize the theme at least once!
- updateSystemTheme();
-} else {
- switchToSavedTheme();
}
+updateTheme();
+
if (getSettingValue("source-sidebar-show") === "true") {
// At this point in page load, `document.body` is not available yet.
// Set a class on the `<html>` element instead.
@@ -259,6 +250,6 @@ if (getSettingValue("source-sidebar-show") === "true") {
// specifically when talking to a remote website with no caching.
window.addEventListener("pageshow", ev => {
if (ev.persisted) {
- setTimeout(switchToSavedTheme, 0);
+ setTimeout(updateTheme, 0);
}
});
diff --git a/src/librustdoc/html/static_files.rs b/src/librustdoc/html/static_files.rs
index b48b82307..767b974cc 100644
--- a/src/librustdoc/html/static_files.rs
+++ b/src/librustdoc/html/static_files.rs
@@ -102,9 +102,6 @@ static_files! {
scrape_examples_js => "static/js/scrape-examples.js",
wheel_svg => "static/images/wheel.svg",
clipboard_svg => "static/images/clipboard.svg",
- down_arrow_svg => "static/images/down-arrow.svg",
- toggle_minus_png => "static/images/toggle-minus.svg",
- toggle_plus_png => "static/images/toggle-plus.svg",
copyright => "static/COPYRIGHT.txt",
license_apache => "static/LICENSE-APACHE.txt",
license_mit => "static/LICENSE-MIT.txt",
diff --git a/src/librustdoc/html/templates/page.html b/src/librustdoc/html/templates/page.html
index fddda293b..7690d8f25 100644
--- a/src/librustdoc/html/templates/page.html
+++ b/src/librustdoc/html/templates/page.html
@@ -5,7 +5,6 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0"> {#- -#}
<meta name="generator" content="rustdoc"> {#- -#}
<meta name="description" content="{{page.description}}"> {#- -#}
- <meta name="keywords" content="{{page.keywords}}"> {#- -#}
<title>{{page.title}}</title> {#- -#}
<link rel="preload" as="font" type="font/woff2" crossorigin href="{{static_root_path|safe}}{{files.source_serif_4_regular}}"> {#- -#}
<link rel="preload" as="font" type="font/woff2" crossorigin href="{{static_root_path|safe}}{{files.fira_sans_regular}}"> {#- -#}
@@ -24,11 +23,13 @@
{%- for theme in themes -%}
<link rel="stylesheet" disabled href="{{page.root_path|safe}}{{theme}}{{page.resource_suffix}}.css"> {#- -#}
{%- endfor -%}
+ {%- if !layout.default_settings.is_empty() -%}
<script id="default-settings" {# -#}
{% for (k, v) in layout.default_settings %}
data-{{k}}="{{v}}"
{%- endfor -%}
></script> {#- -#}
+ {%- endif -%}
<script src="{{static_root_path|safe}}{{files.storage_js}}"></script> {#- -#}
{%- if page.css_class.contains("crate") -%}
<script defer src="{{page.root_path|safe}}crates{{page.resource_suffix}}.js"></script> {#- -#}
diff --git a/src/librustdoc/html/templates/print_item.html b/src/librustdoc/html/templates/print_item.html
index ee2880bf6..3a1867b7f 100644
--- a/src/librustdoc/html/templates/print_item.html
+++ b/src/librustdoc/html/templates/print_item.html
@@ -6,7 +6,7 @@
<a href="{{component.path|safe}}index.html">{{component.name}}</a>::<wbr>
{%- endfor -%}
<a class="{{item_type}}" href="#">{{name}}</a> {#- -#}
- <button id="copy-path" onclick="copy_path(this)" title="Copy item path to clipboard"> {#- -#}
+ <button id="copy-path" title="Copy item path to clipboard"> {#- -#}
<img src="{{static_root_path|safe}}{{clipboard_svg}}" {# -#}
width="19" height="18" {# -#}
alt="Copy item path"> {#- -#}
diff --git a/src/librustdoc/json/conversions.rs b/src/librustdoc/json/conversions.rs
index bd95ec186..18c45fd69 100644
--- a/src/librustdoc/json/conversions.rs
+++ b/src/librustdoc/json/conversions.rs
@@ -38,7 +38,7 @@ impl JsonRenderer<'_> {
Some(UrlFragment::UserWritten(_)) | None => *page_id,
};
- (link.clone(), from_item_id(id.into(), self.tcx))
+ (String::from(&**link), id_from_item_default(id.into(), self.tcx))
})
.collect();
let docs = item.attrs.collapsed_doc_value();
@@ -50,7 +50,8 @@ impl JsonRenderer<'_> {
.collect();
let span = item.span(self.tcx);
let visibility = item.visibility(self.tcx);
- let clean::Item { name, attrs: _, kind: _, item_id, cfg: _, .. } = item;
+ let clean::Item { name, item_id, .. } = item;
+ let id = id_from_item(&item, self.tcx);
let inner = match *item.kind {
clean::KeywordItem => return None,
clean::StrippedItem(ref inner) => {
@@ -69,7 +70,7 @@ impl JsonRenderer<'_> {
_ => from_clean_item(item, self.tcx),
};
Some(Item {
- id: from_item_id_with_name(item_id, self.tcx, name),
+ id,
crate_id: item_id.krate().as_u32(),
name: name.map(|sym| sym.to_string()),
span: span.and_then(|span| self.convert_span(span)),
@@ -107,7 +108,7 @@ impl JsonRenderer<'_> {
Some(ty::Visibility::Public) => Visibility::Public,
Some(ty::Visibility::Restricted(did)) if did.is_crate_root() => Visibility::Crate,
Some(ty::Visibility::Restricted(did)) => Visibility::Restricted {
- parent: from_item_id(did.into(), self.tcx),
+ parent: id_from_item_default(did.into(), self.tcx),
path: self.tcx.def_path(did).to_string_no_crate_verbose(),
},
}
@@ -204,21 +205,42 @@ impl FromWithTcx<clean::TypeBindingKind> for TypeBindingKind {
}
}
-/// It generates an ID as follows:
-///
-/// `CRATE_ID:ITEM_ID[:NAME_ID]` (if there is no name, NAME_ID is not generated).
-pub(crate) fn from_item_id(item_id: ItemId, tcx: TyCtxt<'_>) -> Id {
- from_item_id_with_name(item_id, tcx, None)
+#[inline]
+pub(crate) fn id_from_item_default(item_id: ItemId, tcx: TyCtxt<'_>) -> Id {
+ id_from_item_inner(item_id, tcx, None, None)
}
-// FIXME: this function (and appending the name at the end of the ID) should be removed when
-// reexports are not inlined anymore for json format. It should be done in #93518.
-pub(crate) fn from_item_id_with_name(item_id: ItemId, tcx: TyCtxt<'_>, name: Option<Symbol>) -> Id {
- struct DisplayDefId<'a>(DefId, TyCtxt<'a>, Option<Symbol>);
+/// It generates an ID as follows:
+///
+/// `CRATE_ID:ITEM_ID[:NAME_ID][-EXTRA]`:
+/// * If there is no `name`, `NAME_ID` is not generated.
+/// * If there is no `extra`, `EXTRA` is not generated.
+///
+/// * `name` is the item's name if available (it's not for impl blocks for example).
+/// * `extra` is used for reexports: it contains the ID of the reexported item. It is used to allow
+/// to have items with the same name but different types to both appear in the generated JSON.
+pub(crate) fn id_from_item_inner(
+ item_id: ItemId,
+ tcx: TyCtxt<'_>,
+ name: Option<Symbol>,
+ extra: Option<&Id>,
+) -> Id {
+ struct DisplayDefId<'a, 'b>(DefId, TyCtxt<'a>, Option<&'b Id>, Option<Symbol>);
- impl<'a> fmt::Display for DisplayDefId<'a> {
+ impl<'a, 'b> fmt::Display for DisplayDefId<'a, 'b> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- let DisplayDefId(def_id, tcx, name) = self;
+ let DisplayDefId(def_id, tcx, extra, name) = self;
+ // We need this workaround because primitive types' DefId actually refers to
+ // their parent module, which isn't present in the output JSON items. So
+ // instead, we directly get the primitive symbol and convert it to u32 to
+ // generate the ID.
+ let s;
+ let extra = if let Some(e) = extra {
+ s = format!("-{}", e.0);
+ &s
+ } else {
+ ""
+ };
let name = match name {
Some(name) => format!(":{}", name.as_u32()),
None => {
@@ -240,18 +262,33 @@ pub(crate) fn from_item_id_with_name(item_id: ItemId, tcx: TyCtxt<'_>, name: Opt
}
}
};
- write!(f, "{}:{}{}", self.0.krate.as_u32(), u32::from(self.0.index), name)
+ write!(f, "{}:{}{name}{extra}", def_id.krate.as_u32(), u32::from(def_id.index))
}
}
match item_id {
- ItemId::DefId(did) => Id(format!("{}", DisplayDefId(did, tcx, name))),
- ItemId::Blanket { for_, impl_id } => {
- Id(format!("b:{}-{}", DisplayDefId(impl_id, tcx, None), DisplayDefId(for_, tcx, name)))
- }
- ItemId::Auto { for_, trait_ } => {
- Id(format!("a:{}-{}", DisplayDefId(trait_, tcx, None), DisplayDefId(for_, tcx, name)))
+ ItemId::DefId(did) => Id(format!("{}", DisplayDefId(did, tcx, extra, name))),
+ ItemId::Blanket { for_, impl_id } => Id(format!(
+ "b:{}-{}",
+ DisplayDefId(impl_id, tcx, None, None),
+ DisplayDefId(for_, tcx, extra, name)
+ )),
+ ItemId::Auto { for_, trait_ } => Id(format!(
+ "a:{}-{}",
+ DisplayDefId(trait_, tcx, None, None),
+ DisplayDefId(for_, tcx, extra, name)
+ )),
+ }
+}
+
+pub(crate) fn id_from_item(item: &clean::Item, tcx: TyCtxt<'_>) -> Id {
+ match *item.kind {
+ clean::ItemKind::ImportItem(ref import) => {
+ let extra =
+ import.source.did.map(ItemId::from).map(|i| id_from_item_inner(i, tcx, None, None));
+ id_from_item_inner(item.item_id, tcx, item.name, extra.as_ref())
}
+ _ => id_from_item_inner(item.item_id, tcx, item.name, None),
}
}
@@ -525,7 +562,7 @@ impl FromWithTcx<clean::Path> for Path {
fn from_tcx(path: clean::Path, tcx: TyCtxt<'_>) -> Path {
Path {
name: path.whole_name(),
- id: from_item_id(path.def_id().into(), tcx),
+ id: id_from_item_default(path.def_id().into(), tcx),
args: path.segments.last().map(|args| Box::new(args.clone().args.into_tcx(tcx))),
}
}
@@ -702,7 +739,7 @@ impl FromWithTcx<clean::Import> for Import {
Import {
source: import.source.path.whole_name(),
name,
- id: import.source.did.map(ItemId::from).map(|i| from_item_id(i, tcx)),
+ id: import.source.did.map(ItemId::from).map(|i| id_from_item_default(i, tcx)),
glob,
}
}
@@ -791,7 +828,7 @@ fn ids(items: impl IntoIterator<Item = clean::Item>, tcx: TyCtxt<'_>) -> Vec<Id>
items
.into_iter()
.filter(|x| !x.is_stripped() && !x.is_keyword())
- .map(|i| from_item_id_with_name(i.item_id, tcx, i.name))
+ .map(|i| id_from_item(&i, tcx))
.collect()
}
@@ -801,12 +838,10 @@ fn ids_keeping_stripped(
) -> Vec<Option<Id>> {
items
.into_iter()
- .map(|i| {
- if !i.is_stripped() && !i.is_keyword() {
- Some(from_item_id_with_name(i.item_id, tcx, i.name))
- } else {
- None
- }
- })
+ .map(
+ |i| {
+ if !i.is_stripped() && !i.is_keyword() { Some(id_from_item(&i, tcx)) } else { None }
+ },
+ )
.collect()
}
diff --git a/src/librustdoc/json/import_finder.rs b/src/librustdoc/json/import_finder.rs
index c5c687df7..982370aa2 100644
--- a/src/librustdoc/json/import_finder.rs
+++ b/src/librustdoc/json/import_finder.rs
@@ -1,5 +1,4 @@
-use rustc_data_structures::fx::FxHashSet;
-use rustc_hir::def_id::DefId;
+use rustc_hir::def_id::DefIdSet;
use crate::{
clean::{self, Import, ImportSource, Item},
@@ -14,14 +13,15 @@ use crate::{
/// See [#100973](https://github.com/rust-lang/rust/issues/100973) and
/// [#101103](https://github.com/rust-lang/rust/issues/101103) for times when
/// this information is needed.
-pub(crate) fn get_imports(krate: clean::Crate) -> (clean::Crate, FxHashSet<DefId>) {
- let mut finder = ImportFinder { imported: FxHashSet::default() };
+pub(crate) fn get_imports(krate: clean::Crate) -> (clean::Crate, DefIdSet) {
+ let mut finder = ImportFinder::default();
let krate = finder.fold_crate(krate);
(krate, finder.imported)
}
+#[derive(Default)]
struct ImportFinder {
- imported: FxHashSet<DefId>,
+ imported: DefIdSet,
}
impl DocFolder for ImportFinder {
diff --git a/src/librustdoc/json/mod.rs b/src/librustdoc/json/mod.rs
index 1196f944f..08bceb59c 100644
--- a/src/librustdoc/json/mod.rs
+++ b/src/librustdoc/json/mod.rs
@@ -13,8 +13,8 @@ use std::io::{BufWriter, Write};
use std::path::PathBuf;
use std::rc::Rc;
-use rustc_data_structures::fx::{FxHashMap, FxHashSet};
-use rustc_hir::def_id::DefId;
+use rustc_data_structures::fx::FxHashMap;
+use rustc_hir::def_id::{DefId, DefIdSet};
use rustc_middle::ty::TyCtxt;
use rustc_session::Session;
use rustc_span::def_id::LOCAL_CRATE;
@@ -28,7 +28,7 @@ use crate::docfs::PathError;
use crate::error::Error;
use crate::formats::cache::Cache;
use crate::formats::FormatRenderer;
-use crate::json::conversions::{from_item_id, from_item_id_with_name, IntoWithTcx};
+use crate::json::conversions::{id_from_item, id_from_item_default, IntoWithTcx};
use crate::{clean, try_err};
#[derive(Clone)]
@@ -40,7 +40,7 @@ pub(crate) struct JsonRenderer<'tcx> {
/// The directory where the blob will be written to.
out_path: PathBuf,
cache: Rc<Cache>,
- imported_items: FxHashSet<DefId>,
+ imported_items: DefIdSet,
}
impl<'tcx> JsonRenderer<'tcx> {
@@ -58,7 +58,7 @@ impl<'tcx> JsonRenderer<'tcx> {
.map(|i| {
let item = &i.impl_item;
self.item(item.clone()).unwrap();
- from_item_id_with_name(item.item_id, self.tcx, item.name)
+ id_from_item(&item, self.tcx)
})
.collect()
})
@@ -80,17 +80,16 @@ impl<'tcx> JsonRenderer<'tcx> {
// 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 let clean::types::ItemKind::ImplItem(ref impl_) = *item.kind &&
+ impl_.trait_.is_none() &&
+ let clean::types::Type::Primitive(_) = impl_.for_
+ {
+ is_primitive_impl = true;
}
if item.item_id.is_local() || is_primitive_impl {
self.item(item.clone()).unwrap();
- Some(from_item_id_with_name(item.item_id, self.tcx, item.name))
+ Some(id_from_item(&item, self.tcx))
} else {
None
}
@@ -151,7 +150,6 @@ impl<'tcx> FormatRenderer<'tcx> for JsonRenderer<'tcx> {
// Flatten items that recursively store other items
item.kind.inner_items().for_each(|i| self.item(i.clone()).unwrap());
- let name = item.name;
let item_id = item.item_id;
if let Some(mut new_item) = self.convert_item(item) {
let can_be_ignored = match new_item.inner {
@@ -194,10 +192,7 @@ impl<'tcx> FormatRenderer<'tcx> for JsonRenderer<'tcx> {
| types::ItemEnum::Macro(_)
| types::ItemEnum::ProcMacro(_) => false,
};
- let removed = self
- .index
- .borrow_mut()
- .insert(from_item_id_with_name(item_id, self.tcx, name), new_item.clone());
+ let removed = self.index.borrow_mut().insert(new_item.id.clone(), new_item.clone());
// FIXME(adotinthevoid): Currently, the index is duplicated. This is a sanity check
// to make sure the items are unique. The main place this happens is when an item, is
@@ -208,6 +203,7 @@ impl<'tcx> FormatRenderer<'tcx> for JsonRenderer<'tcx> {
if !can_be_ignored {
assert_eq!(old_item, new_item);
}
+ trace!("replaced {:?}\nwith {:?}", old_item, new_item);
}
}
@@ -222,7 +218,7 @@ impl<'tcx> FormatRenderer<'tcx> for JsonRenderer<'tcx> {
fn after_krate(&mut self) -> Result<(), Error> {
debug!("Done with crate");
- debug!("Adding Primitve impls");
+ debug!("Adding Primitive impls");
for primitive in Rc::clone(&self.cache).primitive_locations.values() {
self.get_impls(*primitive);
}
@@ -247,7 +243,7 @@ impl<'tcx> FormatRenderer<'tcx> for JsonRenderer<'tcx> {
.chain(&self.cache.external_paths)
.map(|(&k, &(ref path, kind))| {
(
- from_item_id(k.into(), self.tcx),
+ id_from_item_default(k.into(), self.tcx),
types::ItemSummary {
crate_id: k.krate.as_u32(),
path: path.iter().map(|s| s.to_string()).collect(),
diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs
index 86454e1f2..4fcf08736 100644
--- a/src/librustdoc/lib.rs
+++ b/src/librustdoc/lib.rs
@@ -6,7 +6,6 @@
#![feature(array_methods)]
#![feature(assert_matches)]
#![feature(box_patterns)]
-#![feature(control_flow_enum)]
#![feature(drain_filter)]
#![feature(is_terminal)]
#![feature(let_chains)]
@@ -21,6 +20,7 @@
#![allow(clippy::collapsible_if, clippy::collapsible_else_if)]
#![allow(rustc::potential_query_instability)]
+extern crate thin_vec;
#[macro_use]
extern crate tracing;
@@ -32,6 +32,7 @@ extern crate tracing;
//
// Dependencies listed in Cargo.toml do not need `extern crate`.
+extern crate pulldown_cmark;
extern crate rustc_ast;
extern crate rustc_ast_pretty;
extern crate rustc_attr;
@@ -82,7 +83,6 @@ use rustc_session::getopts;
use rustc_session::{early_error, early_warn};
use crate::clean::utils::DOC_RUST_LANG_ORG_CHANNEL;
-use crate::passes::collect_intra_doc_links;
/// A macro to create a FxHashMap.
///
@@ -742,7 +742,7 @@ fn main_args(at_args: &[String]) -> MainResult {
(false, true) => {
let input = options.input.clone();
let edition = options.edition;
- let config = core::create_config(options);
+ let config = core::create_config(options, &render_options);
// `markdown::render` can invoke `doctest::make_test`, which
// requires session globals and a thread pool, so we use
@@ -775,7 +775,7 @@ fn main_args(at_args: &[String]) -> MainResult {
let scrape_examples_options = options.scrape_examples_options.clone();
let bin_crate = options.bin_crate;
- let config = core::create_config(options);
+ let config = core::create_config(options, &render_options);
interface::run_compiler(config, |compiler| {
let sess = compiler.session();
@@ -793,40 +793,14 @@ fn main_args(at_args: &[String]) -> MainResult {
}
compiler.enter(|queries| {
- // 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.
- // FIXME(#83761): Resolver cloning can lead to inconsistencies between data in the
- // two copies because one of the copies can be modified after `TyCtxt` construction.
- let (resolver, resolver_caches) = {
- let expansion = abort_on_err(queries.expansion(), sess);
- let (krate, resolver, _) = &*expansion.borrow();
- let resolver_caches = resolver.borrow_mut().access(|resolver| {
- collect_intra_doc_links::early_resolve_intra_doc_links(
- resolver,
- krate,
- render_options.document_private,
- )
- });
- (resolver.clone(), resolver_caches)
- };
-
+ let mut gcx = abort_on_err(queries.global_ctxt(), sess);
if sess.diagnostic().has_errors_or_lint_errors().is_some() {
sess.fatal("Compilation failed, aborting rustdoc");
}
- let global_ctxt = abort_on_err(queries.global_ctxt(), sess);
-
- global_ctxt.enter(|tcx| {
+ gcx.enter(|tcx| {
let (krate, render_opts, mut cache) = sess.time("run_global_ctxt", || {
- core::run_global_ctxt(
- tcx,
- resolver,
- resolver_caches,
- show_coverage,
- render_options,
- output_format,
- )
+ core::run_global_ctxt(tcx, show_coverage, render_options, output_format)
});
info!("finished with rustc");
diff --git a/src/librustdoc/lint.rs b/src/librustdoc/lint.rs
index 3aad97bc2..6d289eb99 100644
--- a/src/librustdoc/lint.rs
+++ b/src/librustdoc/lint.rs
@@ -194,7 +194,11 @@ pub(crate) fn register_lints(_sess: &Session, lint_store: &mut LintStore) {
true,
"rustdoc::all",
Some("rustdoc"),
- RUSTDOC_LINTS.iter().map(|&lint| LintId::of(lint)).collect(),
+ RUSTDOC_LINTS
+ .iter()
+ .filter(|lint| lint.feature_gate.is_none()) // only include stable lints
+ .map(|&lint| LintId::of(lint))
+ .collect(),
);
for lint in &*RUSTDOC_LINTS {
let name = lint.name_lower();
diff --git a/src/librustdoc/markdown.rs b/src/librustdoc/markdown.rs
index 5f4ad6d2a..4321d4aa3 100644
--- a/src/librustdoc/markdown.rs
+++ b/src/librustdoc/markdown.rs
@@ -72,7 +72,14 @@ pub(crate) fn render<P: AsRef<Path>>(
let mut ids = IdMap::new();
let error_codes = ErrorCodes::from(options.unstable_features.is_nightly_build());
let text = if !options.markdown_no_toc {
- MarkdownWithToc(text, &mut ids, error_codes, edition, &playground).into_string()
+ MarkdownWithToc {
+ content: text,
+ ids: &mut ids,
+ error_codes,
+ edition,
+ playground: &playground,
+ }
+ .into_string()
} else {
Markdown {
content: text,
diff --git a/src/librustdoc/passes/calculate_doc_coverage.rs b/src/librustdoc/passes/calculate_doc_coverage.rs
index 02b227896..0b22f943d 100644
--- a/src/librustdoc/passes/calculate_doc_coverage.rs
+++ b/src/librustdoc/passes/calculate_doc_coverage.rs
@@ -216,13 +216,7 @@ impl<'a, 'b> DocVisitor for CoverageCalculator<'a, 'b> {
);
let has_doc_example = tests.found_tests != 0;
- // The `expect_def_id()` should be okay because `local_def_id_to_hir_id`
- // would presumably panic if a fake `DefIndex` were passed.
- let hir_id = self
- .ctx
- .tcx
- .hir()
- .local_def_id_to_hir_id(i.item_id.expect_def_id().expect_local());
+ let hir_id = DocContext::as_local_hir_id(self.ctx.tcx, i.item_id).unwrap();
let (level, source) = self.ctx.tcx.lint_level_at_node(MISSING_DOCS, hir_id);
// In case we have:
diff --git a/src/librustdoc/passes/check_doc_test_visibility.rs b/src/librustdoc/passes/check_doc_test_visibility.rs
index 6aa2dda98..a39d57d42 100644
--- a/src/librustdoc/passes/check_doc_test_visibility.rs
+++ b/src/librustdoc/passes/check_doc_test_visibility.rs
@@ -14,8 +14,8 @@ use crate::visit::DocVisitor;
use crate::visit_ast::inherits_doc_hidden;
use rustc_hir as hir;
use rustc_middle::lint::LintLevelSource;
+use rustc_middle::ty::DefIdTree;
use rustc_session::lint;
-use rustc_span::symbol::sym;
pub(crate) const CHECK_DOC_TEST_VISIBILITY: Pass = Pass {
name: "check_doc_test_visibility",
@@ -79,30 +79,32 @@ pub(crate) fn should_have_doc_example(cx: &DocContext<'_>, item: &clean::Item) -
// 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.item_id.expect_def_id().expect_local());
+ let def_id = item.item_id.expect_def_id().expect_local();
// check if parent is trait impl
- if let Some(parent_hir_id) = cx.tcx.hir().opt_parent_id(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 let Some(parent_def_id) = cx.tcx.opt_local_parent(def_id) &&
+ let Some(parent_node) = cx.tcx.hir().find_by_def_id(parent_def_id) &&
+ 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()
+ if cx.tcx.is_doc_hidden(def_id.to_def_id())
+ || inherits_doc_hidden(cx.tcx, def_id)
+ || cx.tcx.def_span(def_id.to_def_id()).in_derive_expansion()
{
return false;
}
- let (level, source) = cx.tcx.lint_level_at_node(crate::lint::MISSING_DOC_CODE_EXAMPLES, hir_id);
+ let (level, source) = cx.tcx.lint_level_at_node(
+ crate::lint::MISSING_DOC_CODE_EXAMPLES,
+ cx.tcx.hir().local_def_id_to_hir_id(def_id),
+ );
level != lint::Level::Allow || matches!(source, LintLevelSource::Default)
}
diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs
index 075951312..cbfc58138 100644
--- a/src/librustdoc/passes/collect_intra_doc_links.rs
+++ b/src/librustdoc/passes/collect_intra_doc_links.rs
@@ -15,7 +15,8 @@ use rustc_hir::def_id::{DefId, CRATE_DEF_ID};
use rustc_hir::Mutability;
use rustc_middle::ty::{DefIdTree, Ty, TyCtxt};
use rustc_middle::{bug, ty};
-use rustc_resolve::ParentScope;
+use rustc_resolve::rustdoc::MalformedGenerics;
+use rustc_resolve::rustdoc::{prepare_to_doc_link_resolution, strip_generics_from_path};
use rustc_session::lint::Lint;
use rustc_span::hygiene::MacroKind;
use rustc_span::symbol::{sym, Ident, Symbol};
@@ -34,9 +35,6 @@ use crate::lint::{BROKEN_INTRA_DOC_LINKS, PRIVATE_INTRA_DOC_LINKS};
use crate::passes::Pass;
use crate::visit::DocVisitor;
-mod early;
-pub(crate) use early::early_resolve_intra_doc_links;
-
pub(crate) const COLLECT_INTRA_DOC_LINKS: Pass = Pass {
name: "collect-intra-doc-links",
run: collect_intra_doc_links,
@@ -179,47 +177,6 @@ enum ResolutionFailure<'a> {
NotResolved(UnresolvedPath<'a>),
}
-#[derive(Clone, Copy, Debug)]
-enum MalformedGenerics {
- /// This link has unbalanced angle brackets.
- ///
- /// For example, `Vec<T` should trigger this, as should `Vec<T>>`.
- UnbalancedAngleBrackets,
- /// The generics are not attached to a type.
- ///
- /// For example, `<T>` should trigger this.
- ///
- /// This is detected by checking if the path is empty after the generics are stripped.
- MissingType,
- /// The link uses fully-qualified syntax, which is currently unsupported.
- ///
- /// For example, `<Vec as IntoIterator>::into_iter` should trigger this.
- ///
- /// This is detected by checking if ` as ` (the keyword `as` with spaces around it) is inside
- /// angle brackets.
- HasFullyQualifiedSyntax,
- /// The link has an invalid path separator.
- ///
- /// For example, `Vec:<T>:new()` should trigger this. Note that `Vec:new()` will **not**
- /// trigger this because it has no generics and thus [`strip_generics_from_path`] will not be
- /// called.
- ///
- /// Note that this will also **not** be triggered if the invalid path separator is inside angle
- /// brackets because rustdoc mostly ignores what's inside angle brackets (except for
- /// [`HasFullyQualifiedSyntax`](MalformedGenerics::HasFullyQualifiedSyntax)).
- ///
- /// This is detected by checking if there is a colon followed by a non-colon in the link.
- InvalidPathSeparator,
- /// The link has too many angle brackets.
- ///
- /// For example, `Vec<<T>>` should trigger this.
- TooManyAngleBrackets,
- /// The link has empty angle brackets.
- ///
- /// For example, `Vec<>` should trigger this.
- EmptyAngleBrackets,
-}
-
#[derive(Clone, Debug, Hash, PartialEq, Eq)]
pub(crate) enum UrlFragment {
Item(DefId),
@@ -271,7 +228,7 @@ struct ResolutionInfo {
item_id: ItemId,
module_id: DefId,
dis: Option<Disambiguator>,
- path_str: String,
+ path_str: Box<str>,
extra_fragment: Option<String>,
}
@@ -336,9 +293,10 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
let ty_res = self.resolve_path(&path, TypeNS, item_id, module_id).ok_or_else(no_res)?;
match ty_res {
- Res::Def(DefKind::Enum, did) => match tcx.type_of(did).kind() {
+ Res::Def(DefKind::Enum, did) => match tcx.type_of(did).subst_identity().kind() {
ty::Adt(def, _) if def.is_enum() => {
- if let Some(field) = def.all_fields().find(|f| f.name == variant_field_name) {
+ if let Some(variant) = def.variants().iter().find(|v| v.name == variant_name)
+ && let Some(field) = variant.fields.iter().find(|f| f.name == variant_field_name) {
Ok((ty_res, field.did))
} else {
Err(UnresolvedPath {
@@ -401,16 +359,16 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
_ => def_id,
})
.and_then(|self_id| match tcx.def_kind(self_id) {
- DefKind::Impl => self.def_id_to_res(self_id),
+ DefKind::Impl { .. } => self.def_id_to_res(self_id),
DefKind::Use => None,
def_kind => Some(Res::Def(def_kind, self_id)),
})
}
- /// Convenience wrapper around `resolve_rustdoc_path`.
+ /// Convenience wrapper around `doc_link_resolutions`.
///
/// This also handles resolving `true` and `false` as booleans.
- /// NOTE: `resolve_rustdoc_path` knows only about paths, not about types.
+ /// NOTE: `doc_link_resolutions` knows only about paths, not about types.
/// Associated items will never be resolved by this function.
fn resolve_path(
&self,
@@ -426,17 +384,11 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
// Resolver doesn't know about true, false, and types that aren't paths (e.g. `()`).
let result = self
.cx
- .resolver_caches
- .doc_link_resolutions
- .get(&(Symbol::intern(path_str), ns, module_id))
+ .tcx
+ .doc_link_resolutions(module_id)
+ .get(&(Symbol::intern(path_str), ns))
.copied()
- .unwrap_or_else(|| {
- self.cx.enter_resolver(|resolver| {
- let parent_scope =
- ParentScope::module(resolver.expect_module(module_id), resolver);
- resolver.resolve_rustdoc_path(path_str, ns, parent_scope)
- })
- })
+ .unwrap_or_else(|| panic!("no resolution for {:?} {:?} {:?}", path_str, ns, module_id))
.and_then(|res| res.try_into().ok())
.or_else(|| resolve_primitive(path_str, ns));
debug!("{} resolved to {:?} in namespace {:?}", path_str, result, ns);
@@ -519,7 +471,7 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
/// This is used for resolving type aliases.
fn def_id_to_res(&self, ty_id: DefId) -> Option<Res> {
use PrimitiveType::*;
- Some(match *self.cx.tcx.type_of(ty_id).kind() {
+ Some(match *self.cx.tcx.type_of(ty_id).subst_identity().kind() {
ty::Bool => Res::Primitive(Bool),
ty::Char => Res::Primitive(Char),
ty::Int(ity) => Res::Primitive(ity.into()),
@@ -542,6 +494,7 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
| ty::Closure(..)
| ty::Generator(..)
| ty::GeneratorWitness(_)
+ | ty::GeneratorWitnessMIR(..)
| ty::Dynamic(..)
| ty::Param(_)
| ty::Bound(..)
@@ -561,27 +514,27 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
// FIXME: Only simple types are supported here, see if we can support
// other types such as Tuple, Array, Slice, etc.
// See https://github.com/rust-lang/rust/issues/90703#issuecomment-1004263455
- Some(tcx.mk_ty(match prim {
- Bool => ty::Bool,
- Str => ty::Str,
- Char => ty::Char,
- Never => ty::Never,
- I8 => ty::Int(ty::IntTy::I8),
- I16 => ty::Int(ty::IntTy::I16),
- I32 => ty::Int(ty::IntTy::I32),
- I64 => ty::Int(ty::IntTy::I64),
- I128 => ty::Int(ty::IntTy::I128),
- Isize => ty::Int(ty::IntTy::Isize),
- F32 => ty::Float(ty::FloatTy::F32),
- F64 => ty::Float(ty::FloatTy::F64),
- U8 => ty::Uint(ty::UintTy::U8),
- U16 => ty::Uint(ty::UintTy::U16),
- U32 => ty::Uint(ty::UintTy::U32),
- U64 => ty::Uint(ty::UintTy::U64),
- U128 => ty::Uint(ty::UintTy::U128),
- Usize => ty::Uint(ty::UintTy::Usize),
+ Some(match prim {
+ Bool => tcx.types.bool,
+ Str => tcx.types.str_,
+ Char => tcx.types.char,
+ Never => tcx.types.never,
+ I8 => tcx.types.i8,
+ I16 => tcx.types.i16,
+ I32 => tcx.types.i32,
+ I64 => tcx.types.i64,
+ I128 => tcx.types.i128,
+ Isize => tcx.types.isize,
+ F32 => tcx.types.f32,
+ F64 => tcx.types.f64,
+ U8 => tcx.types.u8,
+ U16 => tcx.types.u16,
+ U32 => tcx.types.u32,
+ U64 => tcx.types.u64,
+ U128 => tcx.types.u128,
+ Usize => tcx.types.usize,
_ => return None,
- }))
+ })
}
/// Resolve an associated item, returning its containing page's `Res`
@@ -619,7 +572,7 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
debug!("looking for associated item named {} for item {:?}", item_name, did);
// Checks if item_name is a variant of the `SomeItem` enum
if ns == TypeNS && def_kind == DefKind::Enum {
- match tcx.type_of(did).kind() {
+ match tcx.type_of(did).subst_identity().kind() {
ty::Adt(adt_def, _) => {
for variant in adt_def.variants() {
if variant.name == item_name {
@@ -653,7 +606,7 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
// something like [`ambi_fn`](<SomeStruct as SomeTrait>::ambi_fn)
.or_else(|| {
resolve_associated_trait_item(
- tcx.type_of(did),
+ tcx.type_of(did).subst_identity(),
module_id,
item_name,
ns,
@@ -686,7 +639,7 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
// they also look like associated items (`module::Type::Variant`),
// because they are real Rust syntax (unlike the intra-doc links
// field syntax) and are handled by the compiler's resolver.
- let def = match tcx.type_of(did).kind() {
+ let def = match tcx.type_of(did).subst_identity().kind() {
ty::Adt(def, _) if !def.is_enum() => def,
_ => return None,
};
@@ -736,12 +689,12 @@ fn resolve_associated_trait_item<'a>(
.find_by_name_and_namespace(cx.tcx, Ident::with_dummy_span(item_name), ns, trait_)
.map(|trait_assoc| {
trait_assoc_to_impl_assoc_item(cx.tcx, impl_, trait_assoc.def_id)
- .unwrap_or(trait_assoc)
+ .unwrap_or(*trait_assoc)
})
});
// FIXME(#74563): warn about ambiguity
debug!("the candidates were {:?}", candidates.clone().collect::<Vec<_>>());
- candidates.next().copied()
+ candidates.next()
}
/// Find the associated item in the impl `impl_id` that corresponds to the
@@ -758,7 +711,7 @@ fn trait_assoc_to_impl_assoc_item<'tcx>(
tcx: TyCtxt<'tcx>,
impl_id: DefId,
trait_assoc_id: DefId,
-) -> Option<&'tcx ty::AssocItem> {
+) -> Option<ty::AssocItem> {
let trait_to_impl_assoc_map = tcx.impl_item_implementor_ids(impl_id);
debug!(?trait_to_impl_assoc_map);
let impl_assoc_id = *trait_to_impl_assoc_map.get(&trait_assoc_id)?;
@@ -778,8 +731,7 @@ fn trait_impls_for<'a>(
module: DefId,
) -> FxHashSet<(DefId, DefId)> {
let tcx = cx.tcx;
- let iter = cx.resolver_caches.traits_in_scope[&module].iter().flat_map(|trait_candidate| {
- let trait_ = trait_candidate.def_id;
+ let iter = tcx.doc_link_traits_in_scope(module).iter().flat_map(|&trait_| {
trace!("considering explicit impl for trait {:?}", trait_);
// Look at each trait implementation to see if it's an impl for `did`
@@ -845,7 +797,7 @@ impl<'a, 'tcx> DocVisitor for LinkCollector<'a, 'tcx> {
// In the presence of re-exports, this is not the same as the module of the item.
// Rather than merging all documentation into one, resolve it one attribute at a time
// so we know which module it came from.
- for (parent_module, doc) in item.attrs.prepare_to_doc_link_resolution() {
+ for (parent_module, doc) in prepare_to_doc_link_resolution(&item.attrs.doc_strings) {
if !may_have_doc_links(&doc) {
continue;
}
@@ -853,22 +805,12 @@ impl<'a, 'tcx> DocVisitor for LinkCollector<'a, 'tcx> {
// NOTE: if there are links that start in one crate and end in another, this will not resolve them.
// This is a degenerate case and it's not supported by rustdoc.
let parent_node = parent_module.or(parent_node);
- let mut tmp_links = self
- .cx
- .resolver_caches
- .markdown_links
- .take()
- .expect("`markdown_links` are already borrowed");
- if !tmp_links.contains_key(&doc) {
- tmp_links.insert(doc.clone(), preprocessed_markdown_links(&doc));
- }
- for md_link in &tmp_links[&doc] {
- let link = self.resolve_link(item, &doc, parent_node, md_link);
+ for md_link in preprocessed_markdown_links(&doc) {
+ let link = self.resolve_link(item, &doc, parent_node, &md_link);
if let Some(link) = link {
self.cx.cache.intra_doc_links.entry(item.item_id).or_default().push(link);
}
}
- self.cx.resolver_caches.markdown_links = Some(tmp_links);
}
if item.is_mod() {
@@ -907,10 +849,10 @@ impl PreprocessingError {
#[derive(Clone)]
struct PreprocessingInfo {
- path_str: String,
+ path_str: Box<str>,
disambiguator: Option<Disambiguator>,
extra_fragment: Option<String>,
- link_text: String,
+ link_text: Box<str>,
}
// Not a typedef to avoid leaking several private structures from this module.
@@ -942,7 +884,8 @@ fn preprocess_link(
let mut parts = stripped.split('#');
let link = parts.next().unwrap();
- if link.trim().is_empty() {
+ let link = link.trim();
+ if link.is_empty() {
// This is an anchor to an element of the current page, nothing to do in here!
return None;
}
@@ -955,7 +898,7 @@ fn preprocess_link(
// Parse and strip the disambiguator from the link, if present.
let (disambiguator, path_str, link_text) = match Disambiguator::from_str(link) {
Ok(Some((d, path, link_text))) => (Some(d), path.trim(), link_text.trim()),
- Ok(None) => (None, link.trim(), link.trim()),
+ Ok(None) => (None, link, link),
Err((err_msg, relative_range)) => {
// Only report error if we would not have ignored this link. See issue #83859.
if !should_ignore_link_with_disambiguators(link) {
@@ -974,16 +917,12 @@ fn preprocess_link(
}
// Strip generics from the path.
- let path_str = if path_str.contains(['<', '>'].as_slice()) {
- match strip_generics_from_path(path_str) {
- Ok(path) => path,
- Err(err) => {
- debug!("link has malformed generics: {}", path_str);
- return Some(Err(PreprocessingError::MalformedGenerics(err, path_str.to_owned())));
- }
+ let path_str = match strip_generics_from_path(path_str) {
+ Ok(path) => path,
+ Err(err) => {
+ debug!("link has malformed generics: {}", path_str);
+ return Some(Err(PreprocessingError::MalformedGenerics(err, path_str.to_owned())));
}
- } else {
- path_str.to_owned()
};
// Sanity check to make sure we don't have any angle brackets after stripping generics.
@@ -998,7 +937,7 @@ fn preprocess_link(
path_str,
disambiguator,
extra_fragment: extra_fragment.map(|frag| frag.to_owned()),
- link_text: link_text.to_owned(),
+ link_text: Box::<str>::from(link_text),
}))
}
@@ -1054,7 +993,7 @@ impl LinkCollector<'_, '_> {
item_id: item.item_id,
module_id,
dis: disambiguator,
- path_str: path_str.to_owned(),
+ path_str: path_str.clone(),
extra_fragment: extra_fragment.clone(),
},
diag_info.clone(), // this struct should really be Copy, but Range is not :(
@@ -1128,7 +1067,7 @@ impl LinkCollector<'_, '_> {
}
res.def_id(self.cx.tcx).map(|page_id| ItemLink {
- link: ori_link.link.clone(),
+ link: Box::<str>::from(&*ori_link.link),
link_text: link_text.clone(),
page_id,
fragment,
@@ -1152,7 +1091,7 @@ impl LinkCollector<'_, '_> {
let page_id = clean::register_res(self.cx, rustc_hir::def::Res::Def(kind, id));
Some(ItemLink {
- link: ori_link.link.clone(),
+ link: Box::<str>::from(&*ori_link.link),
link_text: link_text.clone(),
page_id,
fragment,
@@ -1194,14 +1133,9 @@ impl LinkCollector<'_, '_> {
}
// item can be non-local e.g. when using #[doc(primitive = "pointer")]
- if let Some((src_id, dst_id)) = id
- .as_local()
- // The `expect_def_id()` should be okay because `local_def_id_to_hir_id`
- // would presumably panic if a fake `DefIndex` were passed.
- .and_then(|dst_id| {
- item.item_id.expect_def_id().as_local().map(|src_id| (src_id, dst_id))
- })
- {
+ if let Some((src_id, dst_id)) = id.as_local().and_then(|dst_id| {
+ item.item_id.expect_def_id().as_local().map(|src_id| (src_id, dst_id))
+ }) {
if self.cx.tcx.effective_visibilities(()).is_exported(src_id)
&& !self.cx.tcx.effective_visibilities(()).is_exported(dst_id)
{
@@ -1681,7 +1615,7 @@ fn resolution_failure(
// ignore duplicates
let mut variants_seen = SmallVec::<[_; 3]>::new();
for mut failure in kinds {
- let variant = std::mem::discriminant(&failure);
+ let variant = mem::discriminant(&failure);
if variants_seen.contains(&variant) {
continue;
}
@@ -1751,7 +1685,7 @@ fn resolution_failure(
if !path_str.contains("::") {
if disambiguator.map_or(true, |d| d.ns() == MacroNS)
- && let Some(&res) = collector.cx.resolver_caches.all_macro_rules
+ && let Some(&res) = collector.cx.tcx.resolutions(()).all_macro_rules
.get(&Symbol::intern(path_str))
{
diag.note(format!(
@@ -1772,15 +1706,35 @@ fn resolution_failure(
// Otherwise, it must be an associated item or variant
let res = partial_res.expect("None case was handled by `last_found_module`");
- let kind = match res {
- Res::Def(kind, _) => Some(kind),
+ let kind_did = match res {
+ Res::Def(kind, did) => Some((kind, did)),
Res::Primitive(_) => None,
};
- let path_description = if let Some(kind) = kind {
+ let is_struct_variant = |did| {
+ if let ty::Adt(def, _) = tcx.type_of(did).subst_identity().kind()
+ && def.is_enum()
+ && let Some(variant) = def.variants().iter().find(|v| v.name == res.name(tcx)) {
+ // ctor is `None` if variant is a struct
+ variant.ctor.is_none()
+ } else {
+ false
+ }
+ };
+ let path_description = if let Some((kind, did)) = kind_did {
match kind {
Mod | ForeignMod => "inner item",
Struct => "field or associated item",
Enum | Union => "variant or associated item",
+ Variant if is_struct_variant(did) => {
+ let variant = res.name(tcx);
+ let note = format!("variant `{variant}` has no such field");
+ if let Some(span) = sp {
+ diag.span_label(span, &note);
+ } else {
+ diag.note(&note);
+ }
+ return;
+ }
Variant
| Field
| Closure
@@ -1808,7 +1762,7 @@ fn resolution_failure(
}
Trait | TyAlias | ForeignTy | OpaqueTy | ImplTraitPlaceholder
| TraitAlias | TyParam | Static(_) => "associated item",
- Impl | GlobalAsm => unreachable!("not a path"),
+ Impl { .. } | GlobalAsm => unreachable!("not a path"),
}
} else {
"associated item"
@@ -2068,94 +2022,3 @@ fn resolve_primitive(path_str: &str, ns: Namespace) -> Option<Res> {
debug!("resolved primitives {:?}", prim);
Some(Res::Primitive(prim))
}
-
-fn strip_generics_from_path(path_str: &str) -> Result<String, MalformedGenerics> {
- let mut stripped_segments = vec![];
- let mut path = path_str.chars().peekable();
- let mut segment = Vec::new();
-
- while let Some(chr) = path.next() {
- match chr {
- ':' => {
- if path.next_if_eq(&':').is_some() {
- let stripped_segment =
- strip_generics_from_path_segment(mem::take(&mut segment))?;
- if !stripped_segment.is_empty() {
- stripped_segments.push(stripped_segment);
- }
- } else {
- return Err(MalformedGenerics::InvalidPathSeparator);
- }
- }
- '<' => {
- segment.push(chr);
-
- match path.next() {
- Some('<') => {
- return Err(MalformedGenerics::TooManyAngleBrackets);
- }
- Some('>') => {
- return Err(MalformedGenerics::EmptyAngleBrackets);
- }
- Some(chr) => {
- segment.push(chr);
-
- while let Some(chr) = path.next_if(|c| *c != '>') {
- segment.push(chr);
- }
- }
- None => break,
- }
- }
- _ => segment.push(chr),
- }
- trace!("raw segment: {:?}", segment);
- }
-
- if !segment.is_empty() {
- let stripped_segment = strip_generics_from_path_segment(segment)?;
- if !stripped_segment.is_empty() {
- stripped_segments.push(stripped_segment);
- }
- }
-
- debug!("path_str: {:?}\nstripped segments: {:?}", path_str, &stripped_segments);
-
- let stripped_path = stripped_segments.join("::");
-
- if !stripped_path.is_empty() { Ok(stripped_path) } else { Err(MalformedGenerics::MissingType) }
-}
-
-fn strip_generics_from_path_segment(segment: Vec<char>) -> Result<String, MalformedGenerics> {
- let mut stripped_segment = String::new();
- let mut param_depth = 0;
-
- let mut latest_generics_chunk = String::new();
-
- for c in segment {
- if c == '<' {
- param_depth += 1;
- latest_generics_chunk.clear();
- } else if c == '>' {
- param_depth -= 1;
- if latest_generics_chunk.contains(" as ") {
- // The segment tries to use fully-qualified syntax, which is currently unsupported.
- // Give a helpful error message instead of completely ignoring the angle brackets.
- return Err(MalformedGenerics::HasFullyQualifiedSyntax);
- }
- } else {
- if param_depth == 0 {
- stripped_segment.push(c);
- } else {
- latest_generics_chunk.push(c);
- }
- }
- }
-
- if param_depth == 0 {
- Ok(stripped_segment)
- } else {
- // The segment has unbalanced angle brackets, e.g. `Vec<T` or `Vec<T>>`
- Err(MalformedGenerics::UnbalancedAngleBrackets)
- }
-}
diff --git a/src/librustdoc/passes/collect_intra_doc_links/early.rs b/src/librustdoc/passes/collect_intra_doc_links/early.rs
deleted file mode 100644
index 42677bd84..000000000
--- a/src/librustdoc/passes/collect_intra_doc_links/early.rs
+++ /dev/null
@@ -1,407 +0,0 @@
-use crate::clean::Attributes;
-use crate::core::ResolverCaches;
-use crate::passes::collect_intra_doc_links::preprocessed_markdown_links;
-use crate::passes::collect_intra_doc_links::{Disambiguator, PreprocessedMarkdownLink};
-
-use rustc_ast::visit::{self, AssocCtxt, Visitor};
-use rustc_ast::{self as ast, ItemKind};
-use rustc_data_structures::fx::FxHashMap;
-use rustc_hir::def::Namespace::*;
-use rustc_hir::def::{DefKind, Namespace, Res};
-use rustc_hir::def_id::{DefId, DefIdMap, DefIdSet, CRATE_DEF_ID};
-use rustc_hir::TraitCandidate;
-use rustc_middle::ty::{DefIdTree, Visibility};
-use rustc_resolve::{ParentScope, Resolver};
-use rustc_span::symbol::sym;
-use rustc_span::{Symbol, SyntaxContext};
-
-use std::collections::hash_map::Entry;
-use std::mem;
-
-pub(crate) fn early_resolve_intra_doc_links(
- resolver: &mut Resolver<'_>,
- krate: &ast::Crate,
- document_private_items: bool,
-) -> ResolverCaches {
- let parent_scope =
- ParentScope::module(resolver.expect_module(CRATE_DEF_ID.to_def_id()), resolver);
- let mut link_resolver = EarlyDocLinkResolver {
- resolver,
- parent_scope,
- visited_mods: Default::default(),
- markdown_links: Default::default(),
- doc_link_resolutions: Default::default(),
- traits_in_scope: Default::default(),
- all_trait_impls: Default::default(),
- all_macro_rules: Default::default(),
- document_private_items,
- };
-
- // Overridden `visit_item` below doesn't apply to the crate root,
- // so we have to visit its attributes and reexports separately.
- link_resolver.resolve_doc_links_local(&krate.attrs);
- link_resolver.process_module_children_or_reexports(CRATE_DEF_ID.to_def_id());
- visit::walk_crate(&mut link_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
- for (extern_name, _) in
- link_resolver.resolver.sess().opts.externs.iter().filter(|(_, entry)| entry.add_prelude)
- {
- link_resolver.resolver.resolve_rustdoc_path(extern_name, TypeNS, parent_scope);
- }
-
- link_resolver.process_extern_impls();
-
- ResolverCaches {
- markdown_links: Some(link_resolver.markdown_links),
- doc_link_resolutions: link_resolver.doc_link_resolutions,
- traits_in_scope: link_resolver.traits_in_scope,
- all_trait_impls: Some(link_resolver.all_trait_impls),
- all_macro_rules: link_resolver.all_macro_rules,
- }
-}
-
-fn doc_attrs<'a>(attrs: impl Iterator<Item = &'a ast::Attribute>) -> Attributes {
- Attributes::from_ast_iter(attrs.map(|attr| (attr, None)), true)
-}
-
-struct EarlyDocLinkResolver<'r, 'ra> {
- resolver: &'r mut Resolver<'ra>,
- parent_scope: ParentScope<'ra>,
- visited_mods: DefIdSet,
- markdown_links: FxHashMap<String, Vec<PreprocessedMarkdownLink>>,
- doc_link_resolutions: FxHashMap<(Symbol, Namespace, DefId), Option<Res<ast::NodeId>>>,
- traits_in_scope: DefIdMap<Vec<TraitCandidate>>,
- all_trait_impls: Vec<DefId>,
- all_macro_rules: FxHashMap<Symbol, Res<ast::NodeId>>,
- document_private_items: bool,
-}
-
-impl<'ra> EarlyDocLinkResolver<'_, 'ra> {
- fn add_traits_in_scope(&mut self, def_id: DefId) {
- // Calls to `traits_in_scope` are expensive, so try to avoid them if only possible.
- // Keys in the `traits_in_scope` cache are always module IDs.
- if let Entry::Vacant(entry) = self.traits_in_scope.entry(def_id) {
- let module = self.resolver.get_nearest_non_block_module(def_id);
- let module_id = module.def_id();
- let entry = if module_id == def_id {
- Some(entry)
- } else if let Entry::Vacant(entry) = self.traits_in_scope.entry(module_id) {
- Some(entry)
- } else {
- None
- };
- if let Some(entry) = entry {
- entry.insert(self.resolver.traits_in_scope(
- None,
- &ParentScope::module(module, self.resolver),
- SyntaxContext::root(),
- None,
- ));
- }
- }
- }
-
- /// Add traits in scope for links in impls collected by the `collect-intra-doc-links` pass.
- /// That pass filters impls using type-based information, but we don't yet have such
- /// information here, so we just conservatively calculate traits in scope for *all* modules
- /// having impls in them.
- fn process_extern_impls(&mut self) {
- // Resolving links in already existing crates may trigger loading of new crates.
- let mut start_cnum = 0;
- loop {
- let crates = Vec::from_iter(self.resolver.cstore().crates_untracked());
- for &cnum in &crates[start_cnum..] {
- let all_trait_impls =
- Vec::from_iter(self.resolver.cstore().trait_impls_in_crate_untracked(cnum));
- let all_inherent_impls =
- Vec::from_iter(self.resolver.cstore().inherent_impls_in_crate_untracked(cnum));
- let all_incoherent_impls = Vec::from_iter(
- self.resolver.cstore().incoherent_impls_in_crate_untracked(cnum),
- );
-
- // Querying traits in scope is expensive so we try to prune the impl lists using
- // privacy, private traits and impls from other crates are never documented in
- // the current crate, and links in their doc comments are not resolved.
- for &(trait_def_id, impl_def_id, simplified_self_ty) in &all_trait_impls {
- if self.resolver.cstore().visibility_untracked(trait_def_id).is_public()
- && simplified_self_ty.and_then(|ty| ty.def()).map_or(true, |ty_def_id| {
- self.resolver.cstore().visibility_untracked(ty_def_id).is_public()
- })
- {
- if self.visited_mods.insert(trait_def_id) {
- self.resolve_doc_links_extern_impl(trait_def_id, false);
- }
- self.resolve_doc_links_extern_impl(impl_def_id, false);
- }
- }
- for (ty_def_id, impl_def_id) in all_inherent_impls {
- if self.resolver.cstore().visibility_untracked(ty_def_id).is_public() {
- self.resolve_doc_links_extern_impl(impl_def_id, true);
- }
- }
- for impl_def_id in all_incoherent_impls {
- self.resolve_doc_links_extern_impl(impl_def_id, true);
- }
-
- self.all_trait_impls
- .extend(all_trait_impls.into_iter().map(|(_, def_id, _)| def_id));
- }
-
- if crates.len() > start_cnum {
- start_cnum = crates.len();
- } else {
- break;
- }
- }
- }
-
- fn resolve_doc_links_extern_impl(&mut self, def_id: DefId, is_inherent: bool) {
- self.resolve_doc_links_extern_outer_fixme(def_id, def_id);
- let assoc_item_def_ids = Vec::from_iter(
- self.resolver.cstore().associated_item_def_ids_untracked(def_id, self.resolver.sess()),
- );
- for assoc_def_id in assoc_item_def_ids {
- if !is_inherent || self.resolver.cstore().visibility_untracked(assoc_def_id).is_public()
- {
- self.resolve_doc_links_extern_outer_fixme(assoc_def_id, def_id);
- }
- }
- }
-
- // FIXME: replace all uses with `resolve_doc_links_extern_outer` to actually resolve links, not
- // just add traits in scope. This may be expensive and require benchmarking and optimization.
- fn resolve_doc_links_extern_outer_fixme(&mut self, def_id: DefId, scope_id: DefId) {
- if !self.resolver.cstore().may_have_doc_links_untracked(def_id) {
- return;
- }
- if let Some(parent_id) = self.resolver.opt_parent(scope_id) {
- self.add_traits_in_scope(parent_id);
- }
- }
-
- fn resolve_doc_links_extern_outer(&mut self, def_id: DefId, scope_id: DefId) {
- if !self.resolver.cstore().may_have_doc_links_untracked(def_id) {
- return;
- }
- let attrs = Vec::from_iter(
- self.resolver.cstore().item_attrs_untracked(def_id, self.resolver.sess()),
- );
- let parent_scope = ParentScope::module(
- self.resolver.get_nearest_non_block_module(
- self.resolver.opt_parent(scope_id).unwrap_or(scope_id),
- ),
- self.resolver,
- );
- self.resolve_doc_links(doc_attrs(attrs.iter()), parent_scope);
- }
-
- fn resolve_doc_links_extern_inner(&mut self, def_id: DefId) {
- if !self.resolver.cstore().may_have_doc_links_untracked(def_id) {
- return;
- }
- let attrs = Vec::from_iter(
- self.resolver.cstore().item_attrs_untracked(def_id, self.resolver.sess()),
- );
- let parent_scope = ParentScope::module(self.resolver.expect_module(def_id), self.resolver);
- self.resolve_doc_links(doc_attrs(attrs.iter()), parent_scope);
- }
-
- fn resolve_doc_links_local(&mut self, attrs: &[ast::Attribute]) {
- if !attrs.iter().any(|attr| attr.may_have_doc_links()) {
- return;
- }
- self.resolve_doc_links(doc_attrs(attrs.iter()), self.parent_scope);
- }
-
- fn resolve_and_cache(
- &mut self,
- path_str: &str,
- ns: Namespace,
- parent_scope: &ParentScope<'ra>,
- ) -> bool {
- // FIXME: This caching may be incorrect in case of multiple `macro_rules`
- // items with the same name in the same module.
- self.doc_link_resolutions
- .entry((Symbol::intern(path_str), ns, parent_scope.module.def_id()))
- .or_insert_with_key(|(path, ns, _)| {
- self.resolver.resolve_rustdoc_path(path.as_str(), *ns, *parent_scope)
- })
- .is_some()
- }
-
- fn resolve_doc_links(&mut self, attrs: Attributes, parent_scope: ParentScope<'ra>) {
- let mut need_traits_in_scope = false;
- for (doc_module, doc) in attrs.prepare_to_doc_link_resolution() {
- assert_eq!(doc_module, None);
- let mut tmp_links = mem::take(&mut self.markdown_links);
- let links =
- tmp_links.entry(doc).or_insert_with_key(|doc| preprocessed_markdown_links(doc));
- for PreprocessedMarkdownLink(pp_link, _) in links {
- if let Ok(pinfo) = pp_link {
- // The logic here is a conservative approximation for path resolution in
- // `resolve_with_disambiguator`.
- if let Some(ns) = pinfo.disambiguator.map(Disambiguator::ns) {
- if self.resolve_and_cache(&pinfo.path_str, ns, &parent_scope) {
- continue;
- }
- }
-
- // Resolve all namespaces due to no disambiguator or for diagnostics.
- let mut any_resolved = false;
- let mut need_assoc = false;
- for ns in [TypeNS, ValueNS, MacroNS] {
- if self.resolve_and_cache(&pinfo.path_str, ns, &parent_scope) {
- any_resolved = true;
- } else if ns != MacroNS {
- need_assoc = true;
- }
- }
-
- // Resolve all prefixes for type-relative resolution or for diagnostics.
- if need_assoc || !any_resolved {
- let mut path = &pinfo.path_str[..];
- while let Some(idx) = path.rfind("::") {
- path = &path[..idx];
- need_traits_in_scope = true;
- for ns in [TypeNS, ValueNS, MacroNS] {
- self.resolve_and_cache(path, ns, &parent_scope);
- }
- }
- }
- }
- }
- self.markdown_links = tmp_links;
- }
-
- if need_traits_in_scope {
- self.add_traits_in_scope(parent_scope.module.def_id());
- }
- }
-
- /// When reexports are inlined, they are replaced with item which they refer to, those items
- /// may have links in their doc comments, those links are resolved at the item definition site,
- /// so we need to know traits in scope at that definition site.
- fn process_module_children_or_reexports(&mut self, module_id: DefId) {
- if !self.visited_mods.insert(module_id) {
- return; // avoid infinite recursion
- }
-
- for child in self.resolver.module_children_or_reexports(module_id) {
- // This condition should give a superset of `denied` from `fn clean_use_statement`.
- if child.vis.is_public()
- || self.document_private_items
- && child.vis != Visibility::Restricted(module_id)
- && module_id.is_local()
- {
- if let Some(def_id) = child.res.opt_def_id() && !def_id.is_local() {
- let scope_id = match child.res {
- Res::Def(
- DefKind::Variant
- | DefKind::AssocTy
- | DefKind::AssocFn
- | DefKind::AssocConst,
- ..,
- ) => self.resolver.parent(def_id),
- _ => def_id,
- };
- self.resolve_doc_links_extern_outer(def_id, scope_id); // Outer attribute scope
- if let Res::Def(DefKind::Mod, ..) = child.res {
- self.resolve_doc_links_extern_inner(def_id); // Inner attribute scope
- }
- if let Res::Def(DefKind::Mod | DefKind::Enum | DefKind::Trait, ..) = child.res {
- self.process_module_children_or_reexports(def_id);
- }
- if let Res::Def(DefKind::Struct | DefKind::Union | DefKind::Variant, _) =
- child.res
- {
- let field_def_ids = Vec::from_iter(
- self.resolver
- .cstore()
- .associated_item_def_ids_untracked(def_id, self.resolver.sess()),
- );
- for field_def_id in field_def_ids {
- self.resolve_doc_links_extern_outer(field_def_id, scope_id);
- }
- }
- }
- }
- }
- }
-}
-
-impl Visitor<'_> for EarlyDocLinkResolver<'_, '_> {
- fn visit_item(&mut self, item: &ast::Item) {
- self.resolve_doc_links_local(&item.attrs); // Outer attribute scope
- if let ItemKind::Mod(..) = item.kind {
- let module_def_id = self.resolver.local_def_id(item.id).to_def_id();
- let module = self.resolver.expect_module(module_def_id);
- let old_module = mem::replace(&mut self.parent_scope.module, module);
- let old_macro_rules = self.parent_scope.macro_rules;
- self.resolve_doc_links_local(&item.attrs); // Inner attribute scope
- self.process_module_children_or_reexports(module_def_id);
- visit::walk_item(self, item);
- if item
- .attrs
- .iter()
- .all(|attr| !attr.has_name(sym::macro_use) && !attr.has_name(sym::macro_escape))
- {
- self.parent_scope.macro_rules = old_macro_rules;
- }
- self.parent_scope.module = old_module;
- } else {
- match &item.kind {
- ItemKind::Impl(box ast::Impl { of_trait: Some(trait_ref), .. }) => {
- if let Some(partial_res) = self.resolver.get_partial_res(trait_ref.ref_id)
- && let Some(res) = partial_res.full_res()
- && let Some(trait_def_id) = res.opt_def_id()
- && !trait_def_id.is_local()
- && self.visited_mods.insert(trait_def_id) {
- self.resolve_doc_links_extern_impl(trait_def_id, false);
- }
- self.all_trait_impls.push(self.resolver.local_def_id(item.id).to_def_id());
- }
- ItemKind::MacroDef(macro_def) if macro_def.macro_rules => {
- let (macro_rules_scope, res) =
- self.resolver.macro_rules_scope(self.resolver.local_def_id(item.id));
- self.parent_scope.macro_rules = macro_rules_scope;
- self.all_macro_rules.insert(item.ident.name, res);
- }
- _ => {}
- }
- visit::walk_item(self, item);
- }
- }
-
- fn visit_assoc_item(&mut self, item: &ast::AssocItem, ctxt: AssocCtxt) {
- self.resolve_doc_links_local(&item.attrs);
- visit::walk_assoc_item(self, item, ctxt)
- }
-
- fn visit_foreign_item(&mut self, item: &ast::ForeignItem) {
- self.resolve_doc_links_local(&item.attrs);
- visit::walk_foreign_item(self, item)
- }
-
- fn visit_variant(&mut self, v: &ast::Variant) {
- self.resolve_doc_links_local(&v.attrs);
- visit::walk_variant(self, v)
- }
-
- fn visit_field_def(&mut self, field: &ast::FieldDef) {
- self.resolve_doc_links_local(&field.attrs);
- visit::walk_field_def(self, field)
- }
-
- fn visit_block(&mut self, block: &ast::Block) {
- let old_macro_rules = self.parent_scope.macro_rules;
- visit::walk_block(self, block);
- self.parent_scope.macro_rules = old_macro_rules;
- }
-
- // NOTE: if doc-comments are ever allowed on other nodes (e.g. function parameters),
- // then this will have to implement other visitor methods too.
-}
diff --git a/src/librustdoc/passes/collect_trait_impls.rs b/src/librustdoc/passes/collect_trait_impls.rs
index 79db3c6c3..01ed4a60b 100644
--- a/src/librustdoc/passes/collect_trait_impls.rs
+++ b/src/librustdoc/passes/collect_trait_impls.rs
@@ -7,8 +7,8 @@ use crate::core::DocContext;
use crate::formats::cache::Cache;
use crate::visit::DocVisitor;
-use rustc_data_structures::fx::{FxHashMap, FxHashSet};
-use rustc_hir::def_id::{DefId, LOCAL_CRATE};
+use rustc_data_structures::fx::FxHashSet;
+use rustc_hir::def_id::{DefId, DefIdMap, DefIdSet, LOCAL_CRATE};
use rustc_middle::ty::{self, DefIdTree};
use rustc_span::symbol::sym;
@@ -45,18 +45,20 @@ pub(crate) fn collect_trait_impls(mut krate: Crate, cx: &mut DocContext<'_>) ->
let mut new_items_local = Vec::new();
// External trait impls.
- cx.with_all_trait_impls(|cx, all_trait_impls| {
+ {
let _prof_timer = cx.tcx.sess.prof.generic_activity("build_extern_trait_impls");
- for &impl_def_id in all_trait_impls.iter().skip_while(|def_id| def_id.is_local()) {
- inline::build_impl(cx, None, impl_def_id, None, &mut new_items_external);
+ for &cnum in cx.tcx.crates(()) {
+ for &impl_def_id in cx.tcx.trait_impls_in_crate(cnum) {
+ inline::build_impl(cx, None, impl_def_id, None, &mut new_items_external);
+ }
}
- });
+ }
// Local trait impls.
- cx.with_all_trait_impls(|cx, all_trait_impls| {
+ {
let _prof_timer = cx.tcx.sess.prof.generic_activity("build_local_trait_impls");
let mut attr_buf = Vec::new();
- for &impl_def_id in all_trait_impls.iter().take_while(|def_id| def_id.is_local()) {
+ for &impl_def_id in cx.tcx.trait_impls_in_crate(LOCAL_CRATE) {
let mut parent = Some(cx.tcx.parent(impl_def_id));
while let Some(did) = parent {
attr_buf.extend(
@@ -76,7 +78,7 @@ pub(crate) fn collect_trait_impls(mut krate: Crate, cx: &mut DocContext<'_>) ->
inline::build_impl(cx, None, impl_def_id, Some(&attr_buf), &mut new_items_local);
attr_buf.clear();
}
- });
+ }
cx.tcx.sess.prof.generic_activity("build_primitive_trait_impls").run(|| {
for def_id in PrimitiveType::all_impls(cx.tcx) {
@@ -107,7 +109,7 @@ pub(crate) fn collect_trait_impls(mut krate: Crate, cx: &mut DocContext<'_>) ->
// `Generics`. To avoid relying on the `impl` block, these
// things would need to be created from wholecloth, in a
// form that is valid for use in type inference.
- let ty = tcx.type_of(def_id);
+ let ty = tcx.type_of(def_id).subst_identity();
match ty.kind() {
ty::Slice(ty)
| ty::Ref(_, ty, _)
@@ -126,14 +128,14 @@ pub(crate) fn collect_trait_impls(mut krate: Crate, cx: &mut DocContext<'_>) ->
});
let mut cleaner = BadImplStripper { prims, items: crate_items, cache: &cx.cache };
- let mut type_did_to_deref_target: FxHashMap<DefId, &Type> = FxHashMap::default();
+ let mut type_did_to_deref_target: DefIdMap<&Type> = DefIdMap::default();
// Follow all `Deref` targets of included items and recursively add them as valid
fn add_deref_target(
cx: &DocContext<'_>,
- map: &FxHashMap<DefId, &Type>,
+ map: &DefIdMap<&Type>,
cleaner: &mut BadImplStripper<'_>,
- targets: &mut FxHashSet<DefId>,
+ targets: &mut DefIdSet,
type_did: DefId,
) {
if let Some(target) = map.get(&type_did) {
@@ -154,39 +156,38 @@ pub(crate) fn collect_trait_impls(mut krate: Crate, cx: &mut DocContext<'_>) ->
// scan through included items ahead of time to splice in Deref targets to the "valid" sets
for it in new_items_external.iter().chain(new_items_local.iter()) {
- if let ImplItem(box Impl { ref for_, ref trait_, ref items, .. }) = *it.kind {
- if trait_.as_ref().map(|t| t.def_id()) == cx.tcx.lang_items().deref_trait()
- && cleaner.keep_impl(for_, true)
- {
- let target = items
- .iter()
- .find_map(|item| match *item.kind {
- AssocTypeItem(ref t, _) => Some(&t.type_),
- _ => None,
- })
- .expect("Deref impl without Target type");
+ if let ImplItem(box Impl { ref for_, ref trait_, ref items, .. }) = *it.kind &&
+ trait_.as_ref().map(|t| t.def_id()) == cx.tcx.lang_items().deref_trait() &&
+ cleaner.keep_impl(for_, true)
+ {
+ let target = items
+ .iter()
+ .find_map(|item| match *item.kind {
+ AssocTypeItem(ref t, _) => Some(&t.type_),
+ _ => None,
+ })
+ .expect("Deref impl without Target type");
- if let Some(prim) = target.primitive_type() {
- cleaner.prims.insert(prim);
- } else if let Some(did) = target.def_id(&cx.cache) {
- cleaner.items.insert(did.into());
- }
- if let Some(for_did) = for_.def_id(&cx.cache) {
- if type_did_to_deref_target.insert(for_did, target).is_none() {
- // Since only the `DefId` portion of the `Type` instances is known to be same for both the
- // `Deref` target type and the impl for type positions, this map of types is keyed by
- // `DefId` and for convenience uses a special cleaner that accepts `DefId`s directly.
- if cleaner.keep_impl_with_def_id(for_did.into()) {
- let mut targets = FxHashSet::default();
- targets.insert(for_did);
- add_deref_target(
- cx,
- &type_did_to_deref_target,
- &mut cleaner,
- &mut targets,
- for_did,
- );
- }
+ if let Some(prim) = target.primitive_type() {
+ cleaner.prims.insert(prim);
+ } else if let Some(did) = target.def_id(&cx.cache) {
+ cleaner.items.insert(did.into());
+ }
+ if let Some(for_did) = for_.def_id(&cx.cache) {
+ if type_did_to_deref_target.insert(for_did, target).is_none() {
+ // Since only the `DefId` portion of the `Type` instances is known to be same for both the
+ // `Deref` target type and the impl for type positions, this map of types is keyed by
+ // `DefId` and for convenience uses a special cleaner that accepts `DefId`s directly.
+ if cleaner.keep_impl_with_def_id(for_did.into()) {
+ let mut targets = DefIdSet::default();
+ targets.insert(for_did);
+ add_deref_target(
+ cx,
+ &type_did_to_deref_target,
+ &mut cleaner,
+ &mut targets,
+ for_did,
+ );
}
}
}
diff --git a/src/librustdoc/passes/lint/check_code_block_syntax.rs b/src/librustdoc/passes/lint/check_code_block_syntax.rs
index 7158355ff..26fbb03a4 100644
--- a/src/librustdoc/passes/lint/check_code_block_syntax.rs
+++ b/src/librustdoc/passes/lint/check_code_block_syntax.rs
@@ -19,8 +19,7 @@ use crate::passes::source_span_for_markdown_range;
pub(crate) fn visit_item(cx: &DocContext<'_>, item: &clean::Item) {
if let Some(dox) = &item.attrs.collapsed_doc_value() {
let sp = item.attr_span(cx.tcx);
- let extra =
- crate::html::markdown::ExtraInfo::new_did(cx.tcx, item.item_id.expect_def_id(), sp);
+ let extra = crate::html::markdown::ExtraInfo::new(cx.tcx, item.item_id.expect_def_id(), sp);
for code_block in markdown::rust_code_blocks(dox, &extra) {
check_rust_syntax(cx, item, dox, code_block);
}
@@ -34,8 +33,10 @@ fn check_rust_syntax(
code_block: RustCodeBlock,
) {
let buffer = Lrc::new(Lock::new(Buffer::default()));
- let fallback_bundle =
- rustc_errors::fallback_fluent_bundle(rustc_errors::DEFAULT_LOCALE_RESOURCES, false);
+ let fallback_bundle = rustc_errors::fallback_fluent_bundle(
+ rustc_driver::DEFAULT_LOCALE_RESOURCES.to_vec(),
+ false,
+ );
let emitter = BufferEmitter { buffer: Lrc::clone(&buffer), fallback_bundle };
let sm = Lrc::new(SourceMap::new(FilePathMapping::empty()));
@@ -73,7 +74,6 @@ fn check_rust_syntax(
return;
};
- let hir_id = cx.tcx.hir().local_def_id_to_hir_id(local_id);
let empty_block = code_block.lang_string == Default::default() && code_block.is_fenced;
let is_ignore = code_block.lang_string.ignore != markdown::Ignore::None;
@@ -93,6 +93,7 @@ fn check_rust_syntax(
// Finally build and emit the completed diagnostic.
// All points of divergence have been handled earlier so this can be
// done the same way whether the span is precise or not.
+ let hir_id = cx.tcx.hir().local_def_id_to_hir_id(local_id);
cx.tcx.struct_span_lint_hir(crate::lint::INVALID_RUST_CODEBLOCKS, hir_id, sp, msg, |lint| {
let explanation = if is_ignore {
"`ignore` code blocks require valid Rust code for syntax highlighting; \
diff --git a/src/librustdoc/passes/lint/html_tags.rs b/src/librustdoc/passes/lint/html_tags.rs
index 070c0aab5..4f72df5a5 100644
--- a/src/librustdoc/passes/lint/html_tags.rs
+++ b/src/librustdoc/passes/lint/html_tags.rs
@@ -113,7 +113,7 @@ pub(crate) fn visit_item(cx: &DocContext<'_>, item: &Item) {
if let Some(link) =
link_names.iter().find(|link| *link.original_text == *broken_link.reference)
{
- Some((link.href.as_str().into(), link.new_text.as_str().into()))
+ Some((link.href.as_str().into(), link.new_text.to_string().into()))
} else if matches!(
&broken_link.link_type,
LinkType::Reference | LinkType::ReferenceUnknown
@@ -210,11 +210,9 @@ fn extract_path_backwards(text: &str, end_pos: usize) -> Option<usize> {
.take_while(|(_, c)| is_id_start(*c) || is_id_continue(*c))
.reduce(|_accum, item| item)
.and_then(|(new_pos, c)| is_id_start(c).then_some(new_pos));
- if let Some(new_pos) = new_pos {
- if current_pos != new_pos {
- current_pos = new_pos;
- continue;
- }
+ if let Some(new_pos) = new_pos && current_pos != new_pos {
+ current_pos = new_pos;
+ continue;
}
break;
}
diff --git a/src/librustdoc/passes/mod.rs b/src/librustdoc/passes/mod.rs
index 634e70ec9..4b1ff68df 100644
--- a/src/librustdoc/passes/mod.rs
+++ b/src/librustdoc/passes/mod.rs
@@ -2,11 +2,12 @@
//! process.
use rustc_middle::ty::TyCtxt;
+use rustc_resolve::rustdoc::DocFragmentKind;
use rustc_span::{InnerSpan, Span, DUMMY_SP};
use std::ops::Range;
use self::Condition::*;
-use crate::clean::{self, DocFragmentKind};
+use crate::clean;
use crate::core::DocContext;
mod stripper;
diff --git a/src/librustdoc/passes/propagate_doc_cfg.rs b/src/librustdoc/passes/propagate_doc_cfg.rs
index de3a4b339..a4bc48690 100644
--- a/src/librustdoc/passes/propagate_doc_cfg.rs
+++ b/src/librustdoc/passes/propagate_doc_cfg.rs
@@ -9,6 +9,7 @@ use crate::fold::DocFolder;
use crate::passes::Pass;
use rustc_hir::def_id::LocalDefId;
+use rustc_middle::ty::DefIdTree;
pub(crate) const PROPAGATE_DOC_CFG: Pass = Pass {
name: "propagate-doc-cfg",
@@ -41,24 +42,22 @@ impl<'a, 'tcx> CfgPropagator<'a, 'tcx> {
let Some(def_id) = item.item_id.as_def_id().and_then(|def_id| def_id.as_local())
else { return };
- let hir = self.cx.tcx.hir();
- let hir_id = hir.local_def_id_to_hir_id(def_id);
-
if check_parent {
- let expected_parent = hir.get_parent_item(hir_id);
+ let expected_parent = self.cx.tcx.opt_local_parent(def_id);
// If parents are different, it means that `item` is a reexport and we need
// to compute the actual `cfg` by iterating through its "real" parents.
- if self.parent == Some(expected_parent.def_id) {
+ if self.parent.is_some() && self.parent == expected_parent {
return;
}
}
let mut attrs = Vec::new();
- for (parent_hir_id, _) in hir.parent_iter(hir_id) {
- if let Some(def_id) = hir.opt_local_def_id(parent_hir_id) {
- attrs.extend_from_slice(load_attrs(self.cx, def_id.to_def_id()));
- }
+ let mut next_def_id = def_id;
+ while let Some(parent_def_id) = self.cx.tcx.opt_local_parent(next_def_id) {
+ attrs.extend_from_slice(load_attrs(self.cx, parent_def_id.to_def_id()));
+ next_def_id = parent_def_id;
}
+
let (_, cfg) = merge_attrs(self.cx, None, item.attrs.other_attrs.as_slice(), Some(&attrs));
item.cfg = cfg;
}
diff --git a/src/librustdoc/passes/strip_hidden.rs b/src/librustdoc/passes/strip_hidden.rs
index e07a788a7..890b3e8d6 100644
--- a/src/librustdoc/passes/strip_hidden.rs
+++ b/src/librustdoc/passes/strip_hidden.rs
@@ -1,4 +1,6 @@
//! Strip all doc(hidden) items from the output.
+
+use rustc_middle::ty::TyCtxt;
use rustc_span::symbol::sym;
use std::mem;
@@ -7,6 +9,7 @@ use crate::clean::{Item, ItemIdSet, NestedAttributesExt};
use crate::core::DocContext;
use crate::fold::{strip_item, DocFolder};
use crate::passes::{ImplStripper, Pass};
+use crate::visit_ast::inherits_doc_hidden;
pub(crate) const STRIP_HIDDEN: Pass = Pass {
name: "strip-hidden",
@@ -21,7 +24,12 @@ pub(crate) fn strip_hidden(krate: clean::Crate, cx: &mut DocContext<'_>) -> clea
// strip all #[doc(hidden)] items
let krate = {
- let mut stripper = Stripper { retained: &mut retained, update_retained: true };
+ let mut stripper = Stripper {
+ retained: &mut retained,
+ update_retained: true,
+ tcx: cx.tcx,
+ is_in_hidden_item: false,
+ };
stripper.fold_crate(krate)
};
@@ -36,40 +44,97 @@ pub(crate) fn strip_hidden(krate: clean::Crate, cx: &mut DocContext<'_>) -> clea
stripper.fold_crate(krate)
}
-struct Stripper<'a> {
+struct Stripper<'a, 'tcx> {
retained: &'a mut ItemIdSet,
update_retained: bool,
+ tcx: TyCtxt<'tcx>,
+ is_in_hidden_item: bool,
}
-impl<'a> DocFolder for Stripper<'a> {
+impl<'a, 'tcx> Stripper<'a, 'tcx> {
+ fn set_is_in_hidden_item_and_fold(&mut self, is_in_hidden_item: bool, i: Item) -> Item {
+ let prev = self.is_in_hidden_item;
+ self.is_in_hidden_item |= is_in_hidden_item;
+ let ret = self.fold_item_recur(i);
+ self.is_in_hidden_item = prev;
+ ret
+ }
+
+ /// In case `i` is a non-hidden impl block, then we special-case it by changing the value
+ /// of `is_in_hidden_item` to `true` because the impl children inherit its visibility.
+ fn recurse_in_impl_or_exported_macro(&mut self, i: Item) -> Item {
+ let prev = mem::replace(&mut self.is_in_hidden_item, false);
+ let ret = self.fold_item_recur(i);
+ self.is_in_hidden_item = prev;
+ ret
+ }
+}
+
+impl<'a, 'tcx> DocFolder for Stripper<'a, 'tcx> {
fn fold_item(&mut self, i: Item) -> Option<Item> {
- if i.attrs.lists(sym::doc).has_word(sym::hidden) {
- debug!("strip_hidden: stripping {:?} {:?}", i.type_(), i.name);
- // Use a dedicated hidden item for fields, variants, and modules.
- // We need to keep private fields and variants, so that the docs
- // can show a placeholder "// some variants omitted". We need to keep
- // private modules, because they can contain impl blocks, and impl
- // block privacy is inherited from the type and trait, not from the
- // module it's defined in. Both of these are marked "stripped," and
- // not included in the final docs, but since they still have an effect
- // on the final doc, cannot be completely removed from the Clean IR.
- match *i.kind {
- clean::StructFieldItem(..) | clean::ModuleItem(..) | clean::VariantItem(..) => {
- // We need to recurse into stripped modules to
- // strip things like impl methods but when doing so
- // we must not add any items to the `retained` set.
- let old = mem::replace(&mut self.update_retained, false);
- let ret = strip_item(self.fold_item_recur(i));
- self.update_retained = old;
- return Some(ret);
- }
- _ => return None,
+ let has_doc_hidden = i.attrs.lists(sym::doc).has_word(sym::hidden);
+ let is_impl_or_exported_macro = match *i.kind {
+ clean::ImplItem(..) => true,
+ // If the macro has the `#[macro_export]` attribute, it means it's accessible at the
+ // crate level so it should be handled differently.
+ clean::MacroItem(..) => {
+ i.attrs.other_attrs.iter().any(|attr| attr.has_name(sym::macro_export))
}
- } else {
+ _ => false,
+ };
+ let mut is_hidden = has_doc_hidden;
+ if !is_impl_or_exported_macro {
+ is_hidden = self.is_in_hidden_item || has_doc_hidden;
+ if !is_hidden && i.inline_stmt_id.is_none() {
+ // We don't need to check if it's coming from a reexport since the reexport itself was
+ // already checked.
+ is_hidden = i
+ .item_id
+ .as_def_id()
+ .and_then(|def_id| def_id.as_local())
+ .map(|def_id| inherits_doc_hidden(self.tcx, def_id))
+ .unwrap_or(false);
+ }
+ }
+ if !is_hidden {
if self.update_retained {
self.retained.insert(i.item_id);
}
+ return Some(if is_impl_or_exported_macro {
+ self.recurse_in_impl_or_exported_macro(i)
+ } else {
+ self.set_is_in_hidden_item_and_fold(false, i)
+ });
+ }
+ debug!("strip_hidden: stripping {:?} {:?}", i.type_(), i.name);
+ // Use a dedicated hidden item for fields, variants, and modules.
+ // We need to keep private fields and variants, so that the docs
+ // can show a placeholder "// some variants omitted". We need to keep
+ // private modules, because they can contain impl blocks, and impl
+ // block privacy is inherited from the type and trait, not from the
+ // module it's defined in. Both of these are marked "stripped," and
+ // not included in the final docs, but since they still have an effect
+ // on the final doc, cannot be completely removed from the Clean IR.
+ match *i.kind {
+ clean::StructFieldItem(..) | clean::ModuleItem(..) | clean::VariantItem(..) => {
+ // We need to recurse into stripped modules to
+ // strip things like impl methods but when doing so
+ // we must not add any items to the `retained` set.
+ let old = mem::replace(&mut self.update_retained, false);
+ let ret = strip_item(self.set_is_in_hidden_item_and_fold(true, i));
+ self.update_retained = old;
+ Some(ret)
+ }
+ _ => {
+ let ret = self.set_is_in_hidden_item_and_fold(true, i);
+ if has_doc_hidden {
+ // If the item itself has `#[doc(hidden)]`, then we simply remove it.
+ None
+ } else {
+ // However if it's a "descendant" of a `#[doc(hidden)]` item, then we strip it.
+ Some(strip_item(ret))
+ }
+ }
}
- Some(self.fold_item_recur(i))
}
}
diff --git a/src/librustdoc/passes/stripper.rs b/src/librustdoc/passes/stripper.rs
index 048ed2646..cba55e5fe 100644
--- a/src/librustdoc/passes/stripper.rs
+++ b/src/librustdoc/passes/stripper.rs
@@ -201,27 +201,25 @@ impl<'a> DocFolder for ImplStripper<'a, '_> {
// Because we don't inline in `maybe_inline_local` if the output format is JSON,
// we need to make a special check for JSON output: we want to keep it unless it has
// a `#[doc(hidden)]` attribute if the `for_` type is exported.
- if let Some(did) = imp.for_.def_id(self.cache) {
- if !imp.for_.is_assoc_ty() && !self.should_keep_impl(&i, did) {
- debug!("ImplStripper: impl item for stripped type; removing");
- return None;
- }
+ if let Some(did) = imp.for_.def_id(self.cache) &&
+ !imp.for_.is_assoc_ty() && !self.should_keep_impl(&i, did)
+ {
+ debug!("ImplStripper: impl item for stripped type; removing");
+ return None;
}
- if let Some(did) = imp.trait_.as_ref().map(|t| t.def_id()) {
- if !self.should_keep_impl(&i, did) {
- debug!("ImplStripper: impl item for stripped trait; removing");
- return None;
- }
+ if let Some(did) = imp.trait_.as_ref().map(|t| t.def_id()) &&
+ !self.should_keep_impl(&i, did) {
+ debug!("ImplStripper: impl item for stripped trait; removing");
+ return None;
}
if let Some(generics) = imp.trait_.as_ref().and_then(|t| t.generics()) {
for typaram in generics {
- if let Some(did) = typaram.def_id(self.cache) {
- if !self.should_keep_impl(&i, did) {
- debug!(
- "ImplStripper: stripped item in trait's generics; removing impl"
- );
- return None;
- }
+ if let Some(did) = typaram.def_id(self.cache) && !self.should_keep_impl(&i, did)
+ {
+ debug!(
+ "ImplStripper: stripped item in trait's generics; removing impl"
+ );
+ return None;
}
}
}
diff --git a/src/librustdoc/scrape_examples.rs b/src/librustdoc/scrape_examples.rs
index f2ee99cd9..f28c164d6 100644
--- a/src/librustdoc/scrape_examples.rs
+++ b/src/librustdoc/scrape_examples.rs
@@ -169,7 +169,7 @@ where
};
let ident_span = path.ident.span;
- (tcx.type_of(def_id), call_span, ident_span)
+ (tcx.type_of(def_id).subst_identity(), call_span, ident_span)
}
_ => {
return;
diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs
index 22068ebe0..157e042e4 100644
--- a/src/librustdoc/visit_ast.rs
+++ b/src/librustdoc/visit_ast.rs
@@ -1,13 +1,14 @@
//! The Rust AST Visitor. Extracts useful information and massages it into a form
//! usable for `clean`.
-use rustc_data_structures::fx::{FxHashMap, FxHashSet};
+use rustc_data_structures::fx::{FxHashSet, FxIndexMap};
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::ty::TyCtxt;
+use rustc_hir::def_id::{DefId, DefIdMap, LocalDefId, LocalDefIdSet};
+use rustc_hir::intravisit::{walk_item, Visitor};
+use rustc_hir::{Node, CRATE_HIR_ID};
+use rustc_middle::hir::nested_filter;
+use rustc_middle::ty::{DefIdTree, TyCtxt};
use rustc_span::def_id::{CRATE_DEF_ID, LOCAL_CRATE};
use rustc_span::symbol::{kw, sym, Symbol};
use rustc_span::Span;
@@ -24,19 +25,30 @@ pub(crate) struct Module<'hir> {
pub(crate) name: Symbol,
pub(crate) where_inner: Span,
pub(crate) mods: Vec<Module<'hir>>,
- pub(crate) id: hir::HirId,
- // (item, renamed, import_id)
- pub(crate) items: Vec<(&'hir hir::Item<'hir>, Option<Symbol>, Option<hir::HirId>)>,
+ pub(crate) def_id: LocalDefId,
+ /// The key is the item `ItemId` and the value is: (item, renamed, import_id).
+ /// We use `FxIndexMap` to keep the insert order.
+ pub(crate) items: FxIndexMap<
+ (LocalDefId, Option<Symbol>),
+ (&'hir hir::Item<'hir>, Option<Symbol>, Option<LocalDefId>),
+ >,
pub(crate) foreigns: Vec<(&'hir hir::ForeignItem<'hir>, Option<Symbol>)>,
}
impl Module<'_> {
- pub(crate) fn new(name: Symbol, id: hir::HirId, where_inner: Span) -> Self {
- Module { name, id, where_inner, mods: Vec::new(), items: Vec::new(), foreigns: Vec::new() }
+ pub(crate) fn new(name: Symbol, def_id: LocalDefId, where_inner: Span) -> Self {
+ Module {
+ name,
+ def_id,
+ where_inner,
+ mods: Vec::new(),
+ items: FxIndexMap::default(),
+ foreigns: Vec::new(),
+ }
}
pub(crate) fn where_outer(&self, tcx: TyCtxt<'_>) -> Span {
- tcx.hir().span(self.id)
+ tcx.def_span(self.def_id)
}
}
@@ -47,39 +59,54 @@ fn def_id_to_path(tcx: TyCtxt<'_>, did: DefId) -> Vec<Symbol> {
std::iter::once(crate_name).chain(relative).collect()
}
-pub(crate) fn inherits_doc_hidden(tcx: TyCtxt<'_>, mut node: hir::HirId) -> bool {
- while let Some(id) = tcx.hir().get_enclosing_scope(node) {
- node = id;
- if tcx.hir().attrs(node).lists(sym::doc).has_word(sym::hidden) {
+pub(crate) fn inherits_doc_hidden(tcx: TyCtxt<'_>, mut def_id: LocalDefId) -> bool {
+ let hir = tcx.hir();
+ while let Some(id) = tcx.opt_local_parent(def_id) {
+ def_id = id;
+ if tcx.is_doc_hidden(def_id.to_def_id()) {
return true;
+ } else if let Some(node) = hir.find_by_def_id(def_id) &&
+ matches!(
+ node,
+ hir::Node::Item(hir::Item { kind: hir::ItemKind::Impl(_), .. }),
+ )
+ {
+ // `impl` blocks stand a bit on their own: unless they have `#[doc(hidden)]` directly
+ // on them, they don't inherit it from the parent context.
+ return false;
}
}
false
}
-// Also, is there some reason that this doesn't use the 'visit'
-// framework from syntax?.
-
pub(crate) struct RustdocVisitor<'a, 'tcx> {
cx: &'a mut core::DocContext<'tcx>,
- view_item_stack: FxHashSet<hir::HirId>,
+ view_item_stack: LocalDefIdSet,
inlining: bool,
/// Are the current module and all of its parents public?
inside_public_path: bool,
- exact_paths: FxHashMap<DefId, Vec<Symbol>>,
+ exact_paths: DefIdMap<Vec<Symbol>>,
+ modules: Vec<Module<'tcx>>,
}
impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
pub(crate) fn new(cx: &'a mut core::DocContext<'tcx>) -> RustdocVisitor<'a, 'tcx> {
// If the root is re-exported, terminate all recursion.
- let mut stack = FxHashSet::default();
- stack.insert(hir::CRATE_HIR_ID);
+ let mut stack = LocalDefIdSet::default();
+ stack.insert(CRATE_DEF_ID);
+ let om = Module::new(
+ cx.tcx.crate_name(LOCAL_CRATE),
+ CRATE_DEF_ID,
+ cx.tcx.hir().root_module().spans.inner_span,
+ );
+
RustdocVisitor {
cx,
view_item_stack: stack,
inlining: false,
inside_public_path: true,
- exact_paths: FxHashMap::default(),
+ exact_paths: Default::default(),
+ modules: vec![om],
}
}
@@ -89,12 +116,10 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
}
pub(crate) fn visit(mut self) -> Module<'tcx> {
- let mut top_level_module = self.visit_mod_contents(
- hir::CRATE_HIR_ID,
- self.cx.tcx.hir().root_module(),
- self.cx.tcx.crate_name(LOCAL_CRATE),
- None,
- );
+ let root_module = self.cx.tcx.hir().root_module();
+ self.visit_mod_contents(CRATE_DEF_ID, root_module);
+
+ let mut top_level_module = self.modules.pop().unwrap();
// `#[macro_export] macro_rules!` items are reexported at the top level of the
// crate, regardless of where they're defined. We want to document the
@@ -109,15 +134,13 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
// macro in the same module.
let mut inserted = FxHashSet::default();
for export in self.cx.tcx.module_reexports(CRATE_DEF_ID).unwrap_or(&[]) {
- if let Res::Def(DefKind::Macro(_), def_id) = export.res {
- if let Some(local_def_id) = def_id.as_local() {
- if self.cx.tcx.has_attr(def_id, sym::macro_export) {
- if inserted.insert(def_id) {
- let item = self.cx.tcx.hir().expect_item(local_def_id);
- top_level_module.items.push((item, None, None));
- }
- }
- }
+ if let Res::Def(DefKind::Macro(_), def_id) = export.res &&
+ let Some(local_def_id) = def_id.as_local() &&
+ self.cx.tcx.has_attr(def_id, sym::macro_export) &&
+ inserted.insert(def_id)
+ {
+ let item = self.cx.tcx.hir().expect_item(local_def_id);
+ top_level_module.items.insert((local_def_id, Some(item.ident.name)), (item, None, None));
}
}
@@ -151,24 +174,22 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
top_level_module
}
- fn visit_mod_contents(
- &mut self,
- id: hir::HirId,
- m: &'tcx hir::Mod<'tcx>,
- name: Symbol,
- parent_id: Option<hir::HirId>,
- ) -> Module<'tcx> {
- let mut om = Module::new(name, id, m.spans.inner_span);
- let def_id = self.cx.tcx.hir().local_def_id(id).to_def_id();
+ /// This method will go through the given module items in two passes:
+ /// 1. The items which are not glob imports/reexports.
+ /// 2. The glob imports/reexports.
+ fn visit_mod_contents(&mut self, def_id: LocalDefId, m: &'tcx hir::Mod<'tcx>) {
+ debug!("Going through module {:?}", m);
// Keep track of if there were any private modules in the path.
let orig_inside_public_path = self.inside_public_path;
- self.inside_public_path &= self.cx.tcx.visibility(def_id).is_public();
+ self.inside_public_path &= self.cx.tcx.local_visibility(def_id).is_public();
+
+ // Reimplementation of `walk_mod` because we need to do it in two passes (explanations in
+ // the second loop):
for &i in m.item_ids {
let item = self.cx.tcx.hir().item(i);
- if matches!(item.kind, hir::ItemKind::Use(_, hir::UseKind::Glob)) {
- continue;
+ if !matches!(item.kind, hir::ItemKind::Use(_, hir::UseKind::Glob)) {
+ self.visit_item(item);
}
- self.visit_item(item, None, &mut om, parent_id);
}
for &i in m.item_ids {
let item = self.cx.tcx.hir().item(i);
@@ -176,11 +197,11 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
// Later passes in rustdoc will de-duplicate by name and kind, so if glob-
// imported items appear last, then they'll be the ones that get discarded.
if matches!(item.kind, hir::ItemKind::Use(_, hir::UseKind::Glob)) {
- self.visit_item(item, None, &mut om, parent_id);
+ self.visit_item(item);
}
}
self.inside_public_path = orig_inside_public_path;
- om
+ debug!("Leaving module {:?}", m);
}
/// Tries to resolve the target of a `pub use` statement and inlines the
@@ -194,11 +215,10 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
/// Returns `true` if the target has been inlined.
fn maybe_inline_local(
&mut self,
- id: hir::HirId,
+ def_id: LocalDefId,
res: Res,
renamed: Option<Symbol>,
glob: bool,
- om: &mut Module<'tcx>,
please_inline: bool,
) -> bool {
debug!("maybe_inline_local res: {:?}", res);
@@ -208,11 +228,11 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
}
let tcx = self.cx.tcx;
- let Some(res_did) = res.opt_def_id() else {
+ let Some(ori_res_did) = res.opt_def_id() else {
return false;
};
- let use_attrs = tcx.hir().attrs(id);
+ let use_attrs = tcx.hir().attrs(tcx.hir().local_def_id_to_hir_id(def_id));
// Don't inline `doc(hidden)` imports so they can be stripped at a later stage.
let is_no_inline = use_attrs.lists(sym::doc).has_word(sym::no_inline)
|| use_attrs.lists(sym::doc).has_word(sym::hidden);
@@ -221,69 +241,82 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
// reachable in documentation -- a previously unreachable item can be
// made reachable by cross-crate inlining which we're checking here.
// (this is done here because we need to know this upfront).
- if !res_did.is_local() && !is_no_inline {
- crate::visit_lib::lib_embargo_visit_item(self.cx, res_did);
+ if !ori_res_did.is_local() && !is_no_inline {
+ crate::visit_lib::lib_embargo_visit_item(self.cx, ori_res_did);
return false;
}
- let res_hir_id = match res_did.as_local() {
- Some(n) => tcx.hir().local_def_id_to_hir_id(n),
- None => return false,
+ let Some(res_did) = ori_res_did.as_local() else {
+ return false;
};
let is_private =
- !self.cx.cache.effective_visibilities.is_directly_public(self.cx.tcx, res_did);
- let is_hidden = inherits_doc_hidden(self.cx.tcx, res_hir_id);
+ !self.cx.cache.effective_visibilities.is_directly_public(self.cx.tcx, ori_res_did);
+ let is_hidden = inherits_doc_hidden(self.cx.tcx, res_did);
// Only inline if requested or if the item would otherwise be stripped.
if (!please_inline && !is_private && !is_hidden) || is_no_inline {
return false;
}
- if !self.view_item_stack.insert(res_hir_id) {
+ if !self.view_item_stack.insert(res_did) {
return false;
}
- let ret = match tcx.hir().get(res_hir_id) {
+ let ret = match tcx.hir().get_by_def_id(res_did) {
Node::Item(&hir::Item { kind: hir::ItemKind::Mod(ref m), .. }) if glob => {
let prev = mem::replace(&mut self.inlining, true);
for &i in m.item_ids {
let i = self.cx.tcx.hir().item(i);
- self.visit_item(i, None, om, Some(id));
+ self.visit_item_inner(i, None, Some(def_id));
}
self.inlining = prev;
true
}
Node::Item(it) if !glob => {
let prev = mem::replace(&mut self.inlining, true);
- self.visit_item(it, renamed, om, Some(id));
+ self.visit_item_inner(it, renamed, Some(def_id));
self.inlining = prev;
true
}
Node::ForeignItem(it) if !glob => {
let prev = mem::replace(&mut self.inlining, true);
- self.visit_foreign_item(it, renamed, om);
+ self.visit_foreign_item_inner(it, renamed);
self.inlining = prev;
true
}
_ => false,
};
- self.view_item_stack.remove(&res_hir_id);
+ self.view_item_stack.remove(&res_did);
ret
}
- fn visit_item(
+ #[inline]
+ fn add_to_current_mod(
&mut self,
item: &'tcx hir::Item<'_>,
renamed: Option<Symbol>,
- om: &mut Module<'tcx>,
- parent_id: Option<hir::HirId>,
+ parent_id: Option<LocalDefId>,
) {
+ self.modules
+ .last_mut()
+ .unwrap()
+ .items
+ .insert((item.owner_id.def_id, renamed), (item, renamed, parent_id));
+ }
+
+ fn visit_item_inner(
+ &mut self,
+ item: &'tcx hir::Item<'_>,
+ renamed: Option<Symbol>,
+ import_id: Option<LocalDefId>,
+ ) -> bool {
debug!("visiting item {:?}", item);
let name = renamed.unwrap_or(item.ident.name);
+ let tcx = self.cx.tcx;
let def_id = item.owner_id.to_def_id();
- let is_pub = self.cx.tcx.visibility(def_id).is_public();
+ let is_pub = tcx.visibility(def_id).is_public();
if is_pub {
self.store_path(item.owner_id.to_def_id());
@@ -292,8 +325,8 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
match item.kind {
hir::ItemKind::ForeignMod { items, .. } => {
for item in items {
- let item = self.cx.tcx.hir().foreign_item(item.id);
- self.visit_foreign_item(item, None, om);
+ let item = tcx.hir().foreign_item(item.id);
+ self.visit_foreign_item_inner(item, None);
}
}
// If we're inlining, skip private items or item reexported as "_".
@@ -308,7 +341,8 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
continue;
}
- let attrs = self.cx.tcx.hir().attrs(item.hir_id());
+ let attrs =
+ tcx.hir().attrs(tcx.hir().local_def_id_to_hir_id(item.owner_id.def_id));
// If there was a private module in the current path then don't bother inlining
// anything as it will probably be stripped anyway.
@@ -322,18 +356,17 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
let is_glob = kind == hir::UseKind::Glob;
let ident = if is_glob { None } else { Some(name) };
if self.maybe_inline_local(
- item.hir_id(),
+ item.owner_id.def_id,
res,
ident,
is_glob,
- om,
please_inline,
) {
continue;
}
}
- om.items.push((item, renamed, parent_id))
+ self.add_to_current_mod(item, renamed, import_id);
}
}
hir::ItemKind::Macro(ref macro_def, _) => {
@@ -350,14 +383,14 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
let def_id = item.owner_id.to_def_id();
let is_macro_2_0 = !macro_def.macro_rules;
- let nonexported = !self.cx.tcx.has_attr(def_id, sym::macro_export);
+ let nonexported = !tcx.has_attr(def_id, sym::macro_export);
if is_macro_2_0 || nonexported || self.inlining {
- om.items.push((item, renamed, None));
+ self.add_to_current_mod(item, renamed, import_id);
}
}
hir::ItemKind::Mod(ref m) => {
- om.mods.push(self.visit_mod_contents(item.hir_id(), m, name, parent_id));
+ self.enter_mod(item.owner_id.def_id, m, name);
}
hir::ItemKind::Fn(..)
| hir::ItemKind::ExternCrate(..)
@@ -365,36 +398,98 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
| hir::ItemKind::Struct(..)
| hir::ItemKind::Union(..)
| hir::ItemKind::TyAlias(..)
- | hir::ItemKind::OpaqueTy(..)
+ | hir::ItemKind::OpaqueTy(hir::OpaqueTy {
+ origin: hir::OpaqueTyOrigin::TyAlias, ..
+ })
| hir::ItemKind::Static(..)
| hir::ItemKind::Trait(..)
- | hir::ItemKind::TraitAlias(..) => om.items.push((item, renamed, parent_id)),
+ | hir::ItemKind::TraitAlias(..) => {
+ self.add_to_current_mod(item, renamed, import_id);
+ }
+ hir::ItemKind::OpaqueTy(hir::OpaqueTy {
+ origin: hir::OpaqueTyOrigin::AsyncFn(_) | hir::OpaqueTyOrigin::FnReturn(_),
+ ..
+ }) => {
+ // return-position impl traits are never nameable, and should never be documented.
+ }
hir::ItemKind::Const(..) => {
// Underscore constants do not correspond to a nameable item and
// so are never useful in documentation.
if name != kw::Underscore {
- om.items.push((item, renamed, parent_id));
+ self.add_to_current_mod(item, renamed, import_id);
}
}
hir::ItemKind::Impl(impl_) => {
// Don't duplicate impls when inlining or if it's implementing a trait, we'll pick
// them up regardless of where they're located.
if !self.inlining && impl_.of_trait.is_none() {
- om.items.push((item, None, None));
+ self.add_to_current_mod(item, None, None);
}
}
}
+ true
}
- fn visit_foreign_item(
+ fn visit_foreign_item_inner(
&mut self,
item: &'tcx hir::ForeignItem<'_>,
renamed: Option<Symbol>,
- om: &mut Module<'tcx>,
) {
// If inlining we only want to include public functions.
if !self.inlining || self.cx.tcx.visibility(item.owner_id).is_public() {
- om.foreigns.push((item, renamed));
+ self.modules.last_mut().unwrap().foreigns.push((item, renamed));
+ }
+ }
+
+ /// This method will create a new module and push it onto the "modules stack" then call
+ /// `visit_mod_contents`. Once done, it'll remove it from the "modules stack" and instead
+ /// add into the list of modules of the current module.
+ fn enter_mod(&mut self, id: LocalDefId, m: &'tcx hir::Mod<'tcx>, name: Symbol) {
+ self.modules.push(Module::new(name, id, m.spans.inner_span));
+
+ self.visit_mod_contents(id, m);
+
+ let last = self.modules.pop().unwrap();
+ self.modules.last_mut().unwrap().mods.push(last);
+ }
+}
+
+// We need to implement this visitor so it'll go everywhere and retrieve items we're interested in
+// such as impl blocks in const blocks.
+impl<'a, 'tcx> Visitor<'tcx> for RustdocVisitor<'a, 'tcx> {
+ type NestedFilter = nested_filter::All;
+
+ fn nested_visit_map(&mut self) -> Self::Map {
+ self.cx.tcx.hir()
+ }
+
+ fn visit_item(&mut self, i: &'tcx hir::Item<'tcx>) {
+ if self.visit_item_inner(i, None, None) {
+ walk_item(self, i);
}
}
+
+ fn visit_mod(&mut self, _: &hir::Mod<'tcx>, _: Span, _: hir::HirId) {
+ // Handled in `visit_item_inner`
+ }
+
+ fn visit_use(&mut self, _: &hir::UsePath<'tcx>, _: hir::HirId) {
+ // Handled in `visit_item_inner`
+ }
+
+ fn visit_path(&mut self, _: &hir::Path<'tcx>, _: hir::HirId) {
+ // Handled in `visit_item_inner`
+ }
+
+ fn visit_label(&mut self, _: &rustc_ast::Label) {
+ // Unneeded.
+ }
+
+ fn visit_infer(&mut self, _: &hir::InferArg) {
+ // Unneeded.
+ }
+
+ fn visit_lifetime(&mut self, _: &hir::Lifetime) {
+ // Unneeded.
+ }
}
diff --git a/src/librustdoc/visit_lib.rs b/src/librustdoc/visit_lib.rs
index e490559b0..fd4f92541 100644
--- a/src/librustdoc/visit_lib.rs
+++ b/src/librustdoc/visit_lib.rs
@@ -1,14 +1,13 @@
use crate::core::DocContext;
-use rustc_data_structures::fx::FxHashSet;
use rustc_hir::def::DefKind;
-use rustc_hir::def_id::DefId;
+use rustc_hir::def_id::{DefId, DefIdSet};
use rustc_middle::ty::TyCtxt;
// FIXME: this may not be exhaustive, but is sufficient for rustdocs current uses
#[derive(Default)]
pub(crate) struct RustdocEffectiveVisibilities {
- extern_public: FxHashSet<DefId>,
+ extern_public: DefIdSet,
}
macro_rules! define_method {
@@ -43,9 +42,9 @@ pub(crate) fn lib_embargo_visit_item(cx: &mut DocContext<'_>, def_id: DefId) {
struct LibEmbargoVisitor<'a, 'tcx> {
tcx: TyCtxt<'tcx>,
// Effective visibilities for reachable nodes
- extern_public: &'a mut FxHashSet<DefId>,
+ extern_public: &'a mut DefIdSet,
// Keeps track of already visited modules, in case a module re-exports its parent
- visited_mods: FxHashSet<DefId>,
+ visited_mods: DefIdSet,
}
impl LibEmbargoVisitor<'_, '_> {
diff --git a/src/stage0.json b/src/stage0.json
index eb41e81e3..03cafd870 100644
--- a/src/stage0.json
+++ b/src/stage0.json
@@ -17,298 +17,298 @@
"tool is executed."
],
"compiler": {
- "date": "2023-02-09",
- "version": "1.67.1"
+ "date": "2023-03-28",
+ "version": "1.68.2"
},
"rustfmt": null,
"checksums_sha256": {
- "dist/2023-02-09/cargo-1.67.1-aarch64-apple-darwin.tar.gz": "1d5e7ca72fa4a75c1fbe0e2cd87c32e2e0e0d1321e18d3c2097e70ce33ce649a",
- "dist/2023-02-09/cargo-1.67.1-aarch64-apple-darwin.tar.xz": "4e13e3b4965b21892fa25d47e7cc4802a8c90394f5770c4d8e64bf1006f3a8ca",
- "dist/2023-02-09/cargo-1.67.1-aarch64-pc-windows-msvc.tar.gz": "5828d190595e4edc285b0d236797d9de096eea096a505b6e86a26d5ad129e061",
- "dist/2023-02-09/cargo-1.67.1-aarch64-pc-windows-msvc.tar.xz": "ebc5a5a032b40dd02632d688fd47d22b848e4e4d25b5fb8398d8c4fb4b965cf0",
- "dist/2023-02-09/cargo-1.67.1-aarch64-unknown-linux-gnu.tar.gz": "e1ab1452572cb78fc7ec88bcadb2fd3e230c72b84d990fd6fc4ec57a24abdb2f",
- "dist/2023-02-09/cargo-1.67.1-aarch64-unknown-linux-gnu.tar.xz": "b04e33d9beb3cd97501399c17ca297f0adc12a7c0ea16351b8821fc9228de477",
- "dist/2023-02-09/cargo-1.67.1-aarch64-unknown-linux-musl.tar.gz": "0e732cd55f579b68e854e83d92c6d1037590d7f7f0a9bbd89c6c4d2b7028c7f3",
- "dist/2023-02-09/cargo-1.67.1-aarch64-unknown-linux-musl.tar.xz": "fcf674b75fcb5eca8c3bf53aa1c914dabea43e81f6eac169802eaec59ca830aa",
- "dist/2023-02-09/cargo-1.67.1-arm-unknown-linux-gnueabi.tar.gz": "48e16568801f31e9299d38d15ec95aebe8f1b5b7d78bc98f06ccb912c9a10d41",
- "dist/2023-02-09/cargo-1.67.1-arm-unknown-linux-gnueabi.tar.xz": "aff66f91d24d68c9f4136fd38d4b26320d6eff2a51101f6594a0b2c82cab3651",
- "dist/2023-02-09/cargo-1.67.1-arm-unknown-linux-gnueabihf.tar.gz": "e3cb5ec5192f040124713c08c2cdf056c0f4be26c563a0b6e22a95c0a67e0d4a",
- "dist/2023-02-09/cargo-1.67.1-arm-unknown-linux-gnueabihf.tar.xz": "5560cef3c8122bd99640867f281f46974c37dc8f62369d70d032794c359141e3",
- "dist/2023-02-09/cargo-1.67.1-armv7-unknown-linux-gnueabihf.tar.gz": "8de3e98677f38a4498ade080dc3417a231fe63a88b6b0996fcd9161f9791d67a",
- "dist/2023-02-09/cargo-1.67.1-armv7-unknown-linux-gnueabihf.tar.xz": "653749b539c43de70423fa2924c8560f3ada77c660911448575660564c95ca41",
- "dist/2023-02-09/cargo-1.67.1-i686-pc-windows-gnu.tar.gz": "fe7d7c5317898440e069a306708188ea6cee980042aa3c4beba614151152c926",
- "dist/2023-02-09/cargo-1.67.1-i686-pc-windows-gnu.tar.xz": "944617e6c8ed5eb028177458d58aa276ea5746e5ef2fa1d65fff19026347fe8e",
- "dist/2023-02-09/cargo-1.67.1-i686-pc-windows-msvc.tar.gz": "007c18185d2d447e299c7bf9856643dca91e49a7d6f525a3e26300e962d377ac",
- "dist/2023-02-09/cargo-1.67.1-i686-pc-windows-msvc.tar.xz": "256ca9f2af7c9d021784ac03179ef0c8ed9add4e53ac245aaca655373ad659d6",
- "dist/2023-02-09/cargo-1.67.1-i686-unknown-linux-gnu.tar.gz": "3d0d7d1c02701babb65e276d6359847e91e8ebe5dfdb51fbcf90fe3e96f5487f",
- "dist/2023-02-09/cargo-1.67.1-i686-unknown-linux-gnu.tar.xz": "36db46e19e8573ea113c38d88f66def5fad848721b3c6dd69361f197b7a02f80",
- "dist/2023-02-09/cargo-1.67.1-mips-unknown-linux-gnu.tar.gz": "f9809cfc845f49ecd85c80930fd35993aceb37a4a28551744e0ac54dd09ec078",
- "dist/2023-02-09/cargo-1.67.1-mips-unknown-linux-gnu.tar.xz": "06778d8aedd8e7850f0175483efa015cc2eeb69e6027e3d94352d89d2a510fc5",
- "dist/2023-02-09/cargo-1.67.1-mips64-unknown-linux-gnuabi64.tar.gz": "588707c552fde6b7837cd5718765999bf24e55ac20c5d3fa33abc1a64f42b91d",
- "dist/2023-02-09/cargo-1.67.1-mips64-unknown-linux-gnuabi64.tar.xz": "f8a20543772ca5feb409e2cc359caaaf9bda1c71a10c4917acc484e7be4c5a05",
- "dist/2023-02-09/cargo-1.67.1-mips64el-unknown-linux-gnuabi64.tar.gz": "c9f104204af0df6e16e80f848927a452979f710e0ea0c2ab1142077bb3903758",
- "dist/2023-02-09/cargo-1.67.1-mips64el-unknown-linux-gnuabi64.tar.xz": "3688d9c02df999a1e219a4863faf159a23cf6dcfaf9c7842646178d60d525a21",
- "dist/2023-02-09/cargo-1.67.1-mipsel-unknown-linux-gnu.tar.gz": "f660223397cad69927cfb4ce0a3d6c77f145ca4cde9ba0e6e32c699e7636cafb",
- "dist/2023-02-09/cargo-1.67.1-mipsel-unknown-linux-gnu.tar.xz": "7bf800ddd0ee6b69bb66fb7cdf12ae045db025fdb866e00c62b63a1eb99f7d64",
- "dist/2023-02-09/cargo-1.67.1-powerpc-unknown-linux-gnu.tar.gz": "6e23ceb0dfbb80cbbbec3c61f316c8a075db5daead9da13cb4fd59ac5b9e2469",
- "dist/2023-02-09/cargo-1.67.1-powerpc-unknown-linux-gnu.tar.xz": "b134c63817805f59821024d377196f2821ae53f88d0a4a2ebdbd8152433984b0",
- "dist/2023-02-09/cargo-1.67.1-powerpc64-unknown-linux-gnu.tar.gz": "6366775b1a281a146357640ee78a06e277ffd716a05b27318e3e5215e34d9861",
- "dist/2023-02-09/cargo-1.67.1-powerpc64-unknown-linux-gnu.tar.xz": "2cd84deb15ed16fc4a1d8a9de45577ba4d9f245de4f7efb3dc6611eec437eef3",
- "dist/2023-02-09/cargo-1.67.1-powerpc64le-unknown-linux-gnu.tar.gz": "ee88956966044a530a60a97a2d90668fefea2fcde06e8cc148ea1b8533585172",
- "dist/2023-02-09/cargo-1.67.1-powerpc64le-unknown-linux-gnu.tar.xz": "fbad853a30437653f09001d0de797823dfa32d537163841bec1792c3267f5eab",
- "dist/2023-02-09/cargo-1.67.1-riscv64gc-unknown-linux-gnu.tar.gz": "412c0a205375c0b578843896ba55605cf34627d67ffd7bf224a83287dafba34e",
- "dist/2023-02-09/cargo-1.67.1-riscv64gc-unknown-linux-gnu.tar.xz": "3381af9ba39068b9c5e62536125a3abb582aef15932f63cd4f90df0cccb05ac7",
- "dist/2023-02-09/cargo-1.67.1-s390x-unknown-linux-gnu.tar.gz": "47d21091a86f3a8e792066db80b85660fcc25f0337a1df4e14ddae4d28394b9d",
- "dist/2023-02-09/cargo-1.67.1-s390x-unknown-linux-gnu.tar.xz": "78d7c2714015ecb7283b417cb265d4d604379d0720aab5f611ca1c113987c283",
- "dist/2023-02-09/cargo-1.67.1-x86_64-apple-darwin.tar.gz": "7404d9dccb0f6ae776e5ddea1413bcf42b24ff1415a08b1763575692ef0c397d",
- "dist/2023-02-09/cargo-1.67.1-x86_64-apple-darwin.tar.xz": "222604e473eaf888f05e032df6fd6451b81b319483cc1d0b26ca20e1f22e1637",
- "dist/2023-02-09/cargo-1.67.1-x86_64-pc-windows-gnu.tar.gz": "2ec3dbbfc96551b708d29d8e5cb629ecdc3e411547217bcc5e18dbd274d46661",
- "dist/2023-02-09/cargo-1.67.1-x86_64-pc-windows-gnu.tar.xz": "f4b349d936f75a066eddb5ea60892677d9455be7f5ead29e578ad63e79df717e",
- "dist/2023-02-09/cargo-1.67.1-x86_64-pc-windows-msvc.tar.gz": "44a751281faad20bc007c660c688555e4ecabe3da65b821d87dc1c3c195c8bc8",
- "dist/2023-02-09/cargo-1.67.1-x86_64-pc-windows-msvc.tar.xz": "0c8dcb748bc64b4d12b35f490d4bf3968667768c08024931b9d2ae0be3807318",
- "dist/2023-02-09/cargo-1.67.1-x86_64-unknown-freebsd.tar.gz": "042cb0af8b42f7ead9db92379988dc96ec56a1b7d3191be5d40323efa27a527d",
- "dist/2023-02-09/cargo-1.67.1-x86_64-unknown-freebsd.tar.xz": "03a4c8299f5cac4c01be458387dff736e627c5ebd4deade61d63e8594269f34f",
- "dist/2023-02-09/cargo-1.67.1-x86_64-unknown-illumos.tar.gz": "a5dfecb76d78d1a8a33e9cd3232e8737c5404a83190bddf660e7e86d95ef5b6d",
- "dist/2023-02-09/cargo-1.67.1-x86_64-unknown-illumos.tar.xz": "7062a2d6f40c7a69e6b095ea0d68e0c171f5bf13461233dc609c2aeecabfcd54",
- "dist/2023-02-09/cargo-1.67.1-x86_64-unknown-linux-gnu.tar.gz": "8d9310dc1e8d36ebd8d56ccaddb0c854daddb6b750c147c141be04f0ec6e89f0",
- "dist/2023-02-09/cargo-1.67.1-x86_64-unknown-linux-gnu.tar.xz": "e744dad75de8419e7fea530c29bd56cf931b4d4de62eb4bd442bfac7b54e61ed",
- "dist/2023-02-09/cargo-1.67.1-x86_64-unknown-linux-musl.tar.gz": "db2c722c7e2daa9db16bcede73f808d704215b6046a373d6d3ecf9cadaf07bdd",
- "dist/2023-02-09/cargo-1.67.1-x86_64-unknown-linux-musl.tar.xz": "e5097075b92c31002bf585831362fa08a15b073730323aaa50bb09ba2ea3646a",
- "dist/2023-02-09/cargo-1.67.1-x86_64-unknown-netbsd.tar.gz": "dd93dfe32780527cc29b9e3fc0be90d9015582504749245df073cc009b366ddb",
- "dist/2023-02-09/cargo-1.67.1-x86_64-unknown-netbsd.tar.xz": "fe92e6bbdc2ef457ac3c765b0b4e8deb114db4d599379dc640e1bfe9c5c66349",
- "dist/2023-02-09/rust-std-1.67.1-aarch64-apple-darwin.tar.gz": "d105694229e90fdc2dcd3897783d6da2f805e8c6233abf0cdbf34f0bb7dab55e",
- "dist/2023-02-09/rust-std-1.67.1-aarch64-apple-darwin.tar.xz": "3ddd33a321a062883652e24e30b8311908e609eb11ba208f8fa6e9f3b490bfb1",
- "dist/2023-02-09/rust-std-1.67.1-aarch64-apple-ios-sim.tar.gz": "1b77641592b2fb74ecdf9bc36fecd6b2f7aaaf1538284d3fc8b7633a82e01dd0",
- "dist/2023-02-09/rust-std-1.67.1-aarch64-apple-ios-sim.tar.xz": "709e4344211ae1647ba48f15bc71cf13b5a304cfe10616523ecf456be5cfc329",
- "dist/2023-02-09/rust-std-1.67.1-aarch64-apple-ios.tar.gz": "d61837407fec6ae6c9e4d9cc253b2dc6c336d6a6fb5d85119e4bbac49031521e",
- "dist/2023-02-09/rust-std-1.67.1-aarch64-apple-ios.tar.xz": "06029a931fbdaa31316187f33a0ab72bf586c9c5092a27858301e86f4c00b972",
- "dist/2023-02-09/rust-std-1.67.1-aarch64-fuchsia.tar.gz": "e142a9787df5c669d2cb172b7b2efaa42330e04f81cb8034c759acbd3a0efa42",
- "dist/2023-02-09/rust-std-1.67.1-aarch64-fuchsia.tar.xz": "d6cf6074da5879e14c1b1d406c2a038f7522cc0a303b34e2b282c52fa44ed9bf",
- "dist/2023-02-09/rust-std-1.67.1-aarch64-linux-android.tar.gz": "dd9daf3e2c61beb88520126a8f557ea3106a38de709f1a80c5b72633a11f9ff4",
- "dist/2023-02-09/rust-std-1.67.1-aarch64-linux-android.tar.xz": "fecfc191c01dd759585d09b71bb5d3e2b491f2343a5a0b1f322343ba808dd56c",
- "dist/2023-02-09/rust-std-1.67.1-aarch64-pc-windows-msvc.tar.gz": "5898d46667b398180ed595a8fd588b8b58bd8aa42659c34aada66ac83e2751e7",
- "dist/2023-02-09/rust-std-1.67.1-aarch64-pc-windows-msvc.tar.xz": "d4644516634bf90037fffb68ffbcbfc496d4363f6b0de973514545624f92e770",
- "dist/2023-02-09/rust-std-1.67.1-aarch64-unknown-linux-gnu.tar.gz": "19f3afbe43c7e041b8b5c0143101d3ede92f73f720709ef1578ad5d259ad6181",
- "dist/2023-02-09/rust-std-1.67.1-aarch64-unknown-linux-gnu.tar.xz": "35027409400faaaa38ea2855b92dea6b553b2e656dff735da730f67ac02e57e6",
- "dist/2023-02-09/rust-std-1.67.1-aarch64-unknown-linux-musl.tar.gz": "b34e7728ea06ffccee03ec2334a57cf2445d479bd46bb846992d5bb9c1d72873",
- "dist/2023-02-09/rust-std-1.67.1-aarch64-unknown-linux-musl.tar.xz": "dcd3926c151cdd33d4de2860f021c86a18556809c4d06cbddebc1b377638710a",
- "dist/2023-02-09/rust-std-1.67.1-aarch64-unknown-none-softfloat.tar.gz": "a922d23fd33ec363a49a79745817a7571fc46825b24d0af7bc48e31784cedcef",
- "dist/2023-02-09/rust-std-1.67.1-aarch64-unknown-none-softfloat.tar.xz": "c5648a80152dd2d6ecbadee880b00f5188f1493dd1aea985341fcbd72137bdbf",
- "dist/2023-02-09/rust-std-1.67.1-aarch64-unknown-none.tar.gz": "bcfa1cf05fdab15b5c5607678e62589d3da8227fb773f75396df861f85191999",
- "dist/2023-02-09/rust-std-1.67.1-aarch64-unknown-none.tar.xz": "98257c117463b439fc35c0ea2102bcb6cb488decb4ee9cebe43518177aaf0cc0",
- "dist/2023-02-09/rust-std-1.67.1-aarch64-unknown-uefi.tar.gz": "778a4d5013aecc99dadb75651a62aac3609a04b64fc0df9f660886712279fa30",
- "dist/2023-02-09/rust-std-1.67.1-aarch64-unknown-uefi.tar.xz": "86b3dc5454b89d3ce85c08af23f8214a093915a277f158a040ea3223f0f6803c",
- "dist/2023-02-09/rust-std-1.67.1-arm-linux-androideabi.tar.gz": "8fc7073e19bf9ecef1f0e3c45f051144ff98a768b970b4e11f7fe76f550f30dd",
- "dist/2023-02-09/rust-std-1.67.1-arm-linux-androideabi.tar.xz": "2df85c9684787e9afed4adbdd72942cb4fc179d1e9423f194da16eec1f24656a",
- "dist/2023-02-09/rust-std-1.67.1-arm-unknown-linux-gnueabi.tar.gz": "26e290910b2936bfc800f9f7e9ffd81c4733fdf52b117ee42ce7def70105b87e",
- "dist/2023-02-09/rust-std-1.67.1-arm-unknown-linux-gnueabi.tar.xz": "da42d5b07984dac9a41719511eeb47cbb6c5e70b32a6eacba96c9f860ced0307",
- "dist/2023-02-09/rust-std-1.67.1-arm-unknown-linux-gnueabihf.tar.gz": "6eb6f4b915caa058f0b1fd6485283215ab628b6bd415abc343ccce054bf66131",
- "dist/2023-02-09/rust-std-1.67.1-arm-unknown-linux-gnueabihf.tar.xz": "3b95c9595db3e10077c4eca8f63d80414bf3a50c1f0f6b2ac33f1992ee0940db",
- "dist/2023-02-09/rust-std-1.67.1-arm-unknown-linux-musleabi.tar.gz": "e28eda9fa7ba7f49a1def04f1918142227c90a4d72b9f25f24b85c90a898edb9",
- "dist/2023-02-09/rust-std-1.67.1-arm-unknown-linux-musleabi.tar.xz": "1e53306124de9f282452bd6085e86918e5e9f6f1940fc79809a1b284272e2d2b",
- "dist/2023-02-09/rust-std-1.67.1-arm-unknown-linux-musleabihf.tar.gz": "ea68b28aee8aa859deb76499442fe4b4e085c1c156e0b2f67e57b28c08acd208",
- "dist/2023-02-09/rust-std-1.67.1-arm-unknown-linux-musleabihf.tar.xz": "767761d99846174dfb7dfb579e2e2be63800478858a82f3f7050cc9555209a89",
- "dist/2023-02-09/rust-std-1.67.1-armebv7r-none-eabi.tar.gz": "2a4fb4fba0b72d03dd899c4818d5db19a239056b62e5e0d5ae3db37ecb75cdf0",
- "dist/2023-02-09/rust-std-1.67.1-armebv7r-none-eabi.tar.xz": "d555c7c3b03e5af802ec90bc216e3ff421fa2941bd04be0a7582c55410c92796",
- "dist/2023-02-09/rust-std-1.67.1-armebv7r-none-eabihf.tar.gz": "1a569f77a0a118e452e432df564bf2d5874e51a71a1edbf50177f47cabcdff31",
- "dist/2023-02-09/rust-std-1.67.1-armebv7r-none-eabihf.tar.xz": "ca9f3f3774ce5a9f985aa2342fb84407ecf162d5576d86c15f6f81c56ca43928",
- "dist/2023-02-09/rust-std-1.67.1-armv5te-unknown-linux-gnueabi.tar.gz": "c04a9cf0a41df4b170a1e29700597fb424ebbb33ff357e935bc361cc0fb88d98",
- "dist/2023-02-09/rust-std-1.67.1-armv5te-unknown-linux-gnueabi.tar.xz": "3e8bb4265c8c6d8984b69eeefe015131ea140148a58179b3abec5653d93bea7d",
- "dist/2023-02-09/rust-std-1.67.1-armv5te-unknown-linux-musleabi.tar.gz": "010020d3677e40aaacf3c624172e4a1615fada25556a43d3f648af4ad26f4c8c",
- "dist/2023-02-09/rust-std-1.67.1-armv5te-unknown-linux-musleabi.tar.xz": "cbfce327b623e341c1243f0d29ef2f60e5fb205d406c79eb8be1433652c3c9a5",
- "dist/2023-02-09/rust-std-1.67.1-armv7-linux-androideabi.tar.gz": "f0a3406f838496cbf2fa0a9e85f1dc942b96334f123ca65df7665de921e0edcc",
- "dist/2023-02-09/rust-std-1.67.1-armv7-linux-androideabi.tar.xz": "45bfd3c6d4f263feadbf0f1c15699eddd886b330cf5623b7d96556080c356f5d",
- "dist/2023-02-09/rust-std-1.67.1-armv7-unknown-linux-gnueabi.tar.gz": "1b808edc6abed36ef6d0955e4858ba5b109073d068aa69c9dcec3cde43b6995e",
- "dist/2023-02-09/rust-std-1.67.1-armv7-unknown-linux-gnueabi.tar.xz": "8a7e46b15adb0718b4e4ee33cd46529117411e8d73c29043778b05e7412c2b46",
- "dist/2023-02-09/rust-std-1.67.1-armv7-unknown-linux-gnueabihf.tar.gz": "711aba76f98f630b6b51ff4e72ad350382e325bf8c06a7f6a949f12c44dbe5ff",
- "dist/2023-02-09/rust-std-1.67.1-armv7-unknown-linux-gnueabihf.tar.xz": "b6d00c4e338744ce1bf5b314f1056472acf1eb416f65057a8b3ca0a992fb04df",
- "dist/2023-02-09/rust-std-1.67.1-armv7-unknown-linux-musleabi.tar.gz": "46daa453e0d2cc72fe1abc8693d4c7a146d28318b4917ab536851161811170e1",
- "dist/2023-02-09/rust-std-1.67.1-armv7-unknown-linux-musleabi.tar.xz": "720958bc039c9ff00e7e399adf45f044484c5695a71bde0d07e0c895a819fe74",
- "dist/2023-02-09/rust-std-1.67.1-armv7-unknown-linux-musleabihf.tar.gz": "420e1fbb2309b3083c892279b74d41f95462067a92b3e059e0cef0829b6edc6b",
- "dist/2023-02-09/rust-std-1.67.1-armv7-unknown-linux-musleabihf.tar.xz": "6102f98617dd37874f3d755d0a325b45d47c6e1715c39d5e9bc037992e4d3cd6",
- "dist/2023-02-09/rust-std-1.67.1-armv7a-none-eabi.tar.gz": "b9da920df2cac3ab788e2e8e5b1a4332fb1c232806e7f8c58e411d36ec4f7b93",
- "dist/2023-02-09/rust-std-1.67.1-armv7a-none-eabi.tar.xz": "92e2e63af7d92e283479c27232516e16158da1b1143328d4e7371952b744305b",
- "dist/2023-02-09/rust-std-1.67.1-armv7r-none-eabi.tar.gz": "84d4da26dfa2cb847616bbf5d3864389e6d57ac713dcb58c5bdc862006d7822e",
- "dist/2023-02-09/rust-std-1.67.1-armv7r-none-eabi.tar.xz": "e66a565db30b5083547b700619ef7709b44d4685088ee31fd6187a47c820cd62",
- "dist/2023-02-09/rust-std-1.67.1-armv7r-none-eabihf.tar.gz": "259569451d8f94d37f2bf6df81c3f47d05e74682f2a99dfbaa0fb18bc776d4b5",
- "dist/2023-02-09/rust-std-1.67.1-armv7r-none-eabihf.tar.xz": "1d5e8435297afcbb436588279ecc8428467cc38e4ae4a626f2231acfb868e3f4",
- "dist/2023-02-09/rust-std-1.67.1-asmjs-unknown-emscripten.tar.gz": "e1dd321d64ef8ebcce9c6592bc1185a5eb9be9627b3ab17b6c4fb826784ef473",
- "dist/2023-02-09/rust-std-1.67.1-asmjs-unknown-emscripten.tar.xz": "e78131476c0f802266423fed680c9eaed5c193827b4703e921a659c8e318d068",
- "dist/2023-02-09/rust-std-1.67.1-i586-pc-windows-msvc.tar.gz": "ead827b6f24d4c867d2b09e75eca3fea0ac5a40c24395d615742c914f4ab69b0",
- "dist/2023-02-09/rust-std-1.67.1-i586-pc-windows-msvc.tar.xz": "6031604db4f1ae49985cb877be4d0b38f3fb70d1e339e30763ee29e322615901",
- "dist/2023-02-09/rust-std-1.67.1-i586-unknown-linux-gnu.tar.gz": "438908fcc378614e2717ab31a44b6dd16e4d56ca10f153ae120553412112f3a7",
- "dist/2023-02-09/rust-std-1.67.1-i586-unknown-linux-gnu.tar.xz": "22cbbf0b22d9b0894cfbd6e1dd6b95b71c7ad02cee4e477d375dcf81af8d1337",
- "dist/2023-02-09/rust-std-1.67.1-i586-unknown-linux-musl.tar.gz": "64e76ba26b26d02fc599ef8313ae6d65cd52b349c34cd2ea70ff7025241b610a",
- "dist/2023-02-09/rust-std-1.67.1-i586-unknown-linux-musl.tar.xz": "49beb678732f34a0bfc22f94900c3d4a17ec05effdb7377864042df73b2a2819",
- "dist/2023-02-09/rust-std-1.67.1-i686-linux-android.tar.gz": "ce5b857737106831cacc3e82eba8b400e15baf2c7b58bab0898a9f9b9697ec51",
- "dist/2023-02-09/rust-std-1.67.1-i686-linux-android.tar.xz": "835beb127b3be66707135795b4fa64de11d366ab967d05bdd7308bbc48f7efb4",
- "dist/2023-02-09/rust-std-1.67.1-i686-pc-windows-gnu.tar.gz": "50986adaff784a4b40a3721f702f7836322b3666b58e9bf6fcff2002b7a2083b",
- "dist/2023-02-09/rust-std-1.67.1-i686-pc-windows-gnu.tar.xz": "c9826d44ee8bf71169985343b87d43e1a97c9b217fbbb73279e235e58945d016",
- "dist/2023-02-09/rust-std-1.67.1-i686-pc-windows-msvc.tar.gz": "a42185cb53f26cf41994377bcbeb58649d0d0453b8fdfa7e2486d2b9724288fb",
- "dist/2023-02-09/rust-std-1.67.1-i686-pc-windows-msvc.tar.xz": "adbd865a8ac5a378108280773dbff867e5fc5e71e64406d017cbad6107d8ed48",
- "dist/2023-02-09/rust-std-1.67.1-i686-unknown-freebsd.tar.gz": "3d3dc7dddd51822b8fe3181ef2cd777b05b5c68446786169c4aa4bbf7956f934",
- "dist/2023-02-09/rust-std-1.67.1-i686-unknown-freebsd.tar.xz": "2557ff10fcd11bcc227047040e5b499212216a7a871a59530c61e1e902dd50a3",
- "dist/2023-02-09/rust-std-1.67.1-i686-unknown-linux-gnu.tar.gz": "af9dabb8126b7dfaa00eefc2a04b304685109b33929c54b6f4ec0e523776a8ce",
- "dist/2023-02-09/rust-std-1.67.1-i686-unknown-linux-gnu.tar.xz": "aab2d7aa76793e78c9c8810e93ed8978f6422843b1277e9c60337b0f943a4409",
- "dist/2023-02-09/rust-std-1.67.1-i686-unknown-linux-musl.tar.gz": "707fa96134a7dd48465feef8c9859b52d026cf8d1aab8ac35c5db3b394a45919",
- "dist/2023-02-09/rust-std-1.67.1-i686-unknown-linux-musl.tar.xz": "a2c6e55a8a2987d0c306d2c164347a70ab7a6a18f6562039a772b33e25934972",
- "dist/2023-02-09/rust-std-1.67.1-i686-unknown-uefi.tar.gz": "a8266a38f6a9bb35be87bbb2d728258a02c207c30c6d39c9910233274ff2c0d3",
- "dist/2023-02-09/rust-std-1.67.1-i686-unknown-uefi.tar.xz": "0e3a3004cef135dd52419690d1e2eb38b8523b410023742f4e01bc9b81c2e6fa",
- "dist/2023-02-09/rust-std-1.67.1-mips-unknown-linux-gnu.tar.gz": "40fb4fca0af8fc3452fcd589e0c1b265f53816bc5e742a8033ca6545a5a69dab",
- "dist/2023-02-09/rust-std-1.67.1-mips-unknown-linux-gnu.tar.xz": "048b3da190212b742f7a052618b57683dc96ee2b6c25fc7f5ae751143cb79bad",
- "dist/2023-02-09/rust-std-1.67.1-mips-unknown-linux-musl.tar.gz": "7e9483001dc0d1633512268c95600fc3b39ed2212605c189711ebd0b80f0e803",
- "dist/2023-02-09/rust-std-1.67.1-mips-unknown-linux-musl.tar.xz": "b9ef413b764a92d42e07a2e588268ece09994d2cd1ab2a93858c27f85a250349",
- "dist/2023-02-09/rust-std-1.67.1-mips64-unknown-linux-gnuabi64.tar.gz": "fe74d46a7f0d12e1af6055fa77bdb69d08d97c1b458f66eafa1f173701019336",
- "dist/2023-02-09/rust-std-1.67.1-mips64-unknown-linux-gnuabi64.tar.xz": "ef7fe3160de629f0d38788f2c270f87b0631480e5b0d848595b460528de719e4",
- "dist/2023-02-09/rust-std-1.67.1-mips64-unknown-linux-muslabi64.tar.gz": "210eaf102ca280984d25c1fc652bee82f2d609697fc5c24b6cbc9ed67a8ac671",
- "dist/2023-02-09/rust-std-1.67.1-mips64-unknown-linux-muslabi64.tar.xz": "15fdb3e8b39c8a122e9beee0c4c909ee8ec356e57aaaaae5f2b9e94f58d73c87",
- "dist/2023-02-09/rust-std-1.67.1-mips64el-unknown-linux-gnuabi64.tar.gz": "61ed21c39f961df9c868aa259535dd67612b3f74eec7ed9fb031e426c192399d",
- "dist/2023-02-09/rust-std-1.67.1-mips64el-unknown-linux-gnuabi64.tar.xz": "6ccfd98fd920cc2f1199bcf9a842430c27f6fcd2cc46c18421e487309ff7811e",
- "dist/2023-02-09/rust-std-1.67.1-mips64el-unknown-linux-muslabi64.tar.gz": "06279f96fcbf965934c1820df065c0e05f399ca5e3a01b0176e9f43786281724",
- "dist/2023-02-09/rust-std-1.67.1-mips64el-unknown-linux-muslabi64.tar.xz": "78477c45f5b848b156adaf0e0f6f2954ae73e2903321d1636c155020175eaaf5",
- "dist/2023-02-09/rust-std-1.67.1-mipsel-unknown-linux-gnu.tar.gz": "940132da5f30f86a4cd87b1c9c37b4f9a6e0cebaaf5d74d187be72383f571a13",
- "dist/2023-02-09/rust-std-1.67.1-mipsel-unknown-linux-gnu.tar.xz": "94410897626546dde806a114299c3c32abb6b4b294af5daea5c4d136751fe063",
- "dist/2023-02-09/rust-std-1.67.1-mipsel-unknown-linux-musl.tar.gz": "1f902de77accab62175d56a640664738495a37b926f2accbbda3a296aa85bea4",
- "dist/2023-02-09/rust-std-1.67.1-mipsel-unknown-linux-musl.tar.xz": "b3f1a338e69428f1611f059c67b8afafa78ce5c7ed0799f8a90795390261d3a4",
- "dist/2023-02-09/rust-std-1.67.1-nvptx64-nvidia-cuda.tar.gz": "d7b0ae5a8cd1c8a8074d0263b3f0285922bf5afea1b3f9218f4995e596ef1b31",
- "dist/2023-02-09/rust-std-1.67.1-nvptx64-nvidia-cuda.tar.xz": "46a2b2e9f3d8a3646df5ea5aa6995599c821176466de182412608eabb1047d31",
- "dist/2023-02-09/rust-std-1.67.1-powerpc-unknown-linux-gnu.tar.gz": "61d376eca89cf0a1b103824862651f7ad5abd7d4bc0f604f8f2fbb261cea8a85",
- "dist/2023-02-09/rust-std-1.67.1-powerpc-unknown-linux-gnu.tar.xz": "26efe78c09ed36da34964c0d023cf9aa404766ab790a94d9becd373b8879cb5a",
- "dist/2023-02-09/rust-std-1.67.1-powerpc64-unknown-linux-gnu.tar.gz": "2699578307a32e49dcf1a43dcee02efbcfb2ff3c5d235ff0c419b337a9493b20",
- "dist/2023-02-09/rust-std-1.67.1-powerpc64-unknown-linux-gnu.tar.xz": "135f5e6ab6d8f077a14521d387d3f31831abdb840ca4e6a15b6f0d0d5b7dbc81",
- "dist/2023-02-09/rust-std-1.67.1-powerpc64le-unknown-linux-gnu.tar.gz": "51ce112d7fb479d7fd8b51432255e27b31ad5d03ae0ac36772931873f6801a8d",
- "dist/2023-02-09/rust-std-1.67.1-powerpc64le-unknown-linux-gnu.tar.xz": "364c47ed22e4268edf238d221c40007d7d8792a66ca325d3937596a9c911ea48",
- "dist/2023-02-09/rust-std-1.67.1-riscv32i-unknown-none-elf.tar.gz": "fdac53f5540659a3059c1b10fdf9836a143ac8f564e8f1f08e0c1cb69ca8a4a8",
- "dist/2023-02-09/rust-std-1.67.1-riscv32i-unknown-none-elf.tar.xz": "9f39e6e94d653711b0e4c2d9113cef418072c73070f606879a5613da95398d04",
- "dist/2023-02-09/rust-std-1.67.1-riscv32imac-unknown-none-elf.tar.gz": "ae1386a6038f1e393bf5bf0bdd540ac49e9ed97cfa92a52f7da95834a38c99d7",
- "dist/2023-02-09/rust-std-1.67.1-riscv32imac-unknown-none-elf.tar.xz": "64cad043d7d4f518ecdee7d90c752ddb2f478930688f8dc518d838c97b51d4b9",
- "dist/2023-02-09/rust-std-1.67.1-riscv32imc-unknown-none-elf.tar.gz": "c38885ec2d0650e680619d09b4a0635589d78b166669a26224bbbd07ce56d582",
- "dist/2023-02-09/rust-std-1.67.1-riscv32imc-unknown-none-elf.tar.xz": "d5f16dee8bcc61bcbf959a882a7c9df60d362616ea9d566f268e82d75fe5e253",
- "dist/2023-02-09/rust-std-1.67.1-riscv64gc-unknown-linux-gnu.tar.gz": "2eb7150a54d0efba20ad98def3b96a4cc7c9e7de88f72e1990a249e6241ee74d",
- "dist/2023-02-09/rust-std-1.67.1-riscv64gc-unknown-linux-gnu.tar.xz": "63a7e6a6c889a3d01bb3c66a3def3e41963511ea52e13906669da5b29b2fd9da",
- "dist/2023-02-09/rust-std-1.67.1-riscv64gc-unknown-none-elf.tar.gz": "62397db61627973245ada7935d33dd45d34ddfa56a4828cdc718942ca973846b",
- "dist/2023-02-09/rust-std-1.67.1-riscv64gc-unknown-none-elf.tar.xz": "c92b38eb727160ca1522e319153bfcf9c569574070905fda0063a62460de3a5f",
- "dist/2023-02-09/rust-std-1.67.1-riscv64imac-unknown-none-elf.tar.gz": "a2d03053b37af67ab58e9a10e728e047b453391720d024a19459402ea2c26b49",
- "dist/2023-02-09/rust-std-1.67.1-riscv64imac-unknown-none-elf.tar.xz": "c4e1c2dab142e6d4e25781ae659d12ff307c1346246dcf8308f007635c4e7d77",
- "dist/2023-02-09/rust-std-1.67.1-s390x-unknown-linux-gnu.tar.gz": "08da1165c14589e9d7a6d42c9c4b4af5c79ee14a2bcd303c4b1b93e29ff9e78d",
- "dist/2023-02-09/rust-std-1.67.1-s390x-unknown-linux-gnu.tar.xz": "04573298d9e815c1e8c47a2f9548ea55d4a2afc538eceaa6a704d44a5e1f7e3e",
- "dist/2023-02-09/rust-std-1.67.1-sparc64-unknown-linux-gnu.tar.gz": "1b1a1003b18edde8f345f135a1f2c0d455bc1adabe39335b0b6d4e15efba277b",
- "dist/2023-02-09/rust-std-1.67.1-sparc64-unknown-linux-gnu.tar.xz": "addf0b0beb1966787e599f32849f18c28d5cb65515272b7d9608d4a1dddee2e7",
- "dist/2023-02-09/rust-std-1.67.1-sparcv9-sun-solaris.tar.gz": "b927ac23fc283e3da93f70f8b717ae7ec7003b26c62ee725a280c9408713dd8b",
- "dist/2023-02-09/rust-std-1.67.1-sparcv9-sun-solaris.tar.xz": "c67d02157ad47d69ea66beeed80c8162caee6d983f69fd41eab31658bb9f8fb6",
- "dist/2023-02-09/rust-std-1.67.1-thumbv6m-none-eabi.tar.gz": "984cb70d2e8a8b000117a8c32b983a813c35b3c0946f4acaec2466ae93fcbd1f",
- "dist/2023-02-09/rust-std-1.67.1-thumbv6m-none-eabi.tar.xz": "b4f7d4dd069eef9254b8405c6032855d319ca06a02ccd617612147c42c48ee7a",
- "dist/2023-02-09/rust-std-1.67.1-thumbv7em-none-eabi.tar.gz": "e8b8f2d32ef4f2563d1ad371af6ad575854daa1c18d2ef65a29188c568cf9d1a",
- "dist/2023-02-09/rust-std-1.67.1-thumbv7em-none-eabi.tar.xz": "cab7138523b5865ee33f008c19774938d55974747f746ec14c3623212049b0c0",
- "dist/2023-02-09/rust-std-1.67.1-thumbv7em-none-eabihf.tar.gz": "ff25c49c3a9ae7faddec848b91d86049adbd771410f31b85442c53cfbb49a473",
- "dist/2023-02-09/rust-std-1.67.1-thumbv7em-none-eabihf.tar.xz": "f711a8934f5660552bf4552419f9db6a4e5433d9988b38e90ded39e0e316ec77",
- "dist/2023-02-09/rust-std-1.67.1-thumbv7m-none-eabi.tar.gz": "363e238d6a118b360781700293b224a0762fa6324e2bb95d3083b08f1922783c",
- "dist/2023-02-09/rust-std-1.67.1-thumbv7m-none-eabi.tar.xz": "beb1d5490ffd1568490f28f25b5324b0167cc128bf1f7b78310bba518a0a8b03",
- "dist/2023-02-09/rust-std-1.67.1-thumbv7neon-linux-androideabi.tar.gz": "132895b0ea5581c11a8d8bf702e60aeb68cbb8aaed791094acd43fefd1c17b48",
- "dist/2023-02-09/rust-std-1.67.1-thumbv7neon-linux-androideabi.tar.xz": "ecf824b093767cce36fde1c6e08f235d900b6edb2775c75028f12fa78abf6729",
- "dist/2023-02-09/rust-std-1.67.1-thumbv7neon-unknown-linux-gnueabihf.tar.gz": "d16d0fc9073a8af4da2bd621d1ccd9d50c293a958baa4ec8fb1821a6e6ecf1a2",
- "dist/2023-02-09/rust-std-1.67.1-thumbv7neon-unknown-linux-gnueabihf.tar.xz": "a328ba18c91fea4af81a046f05c4853251b16a0f2ecf632129050a780fa0e90f",
- "dist/2023-02-09/rust-std-1.67.1-thumbv8m.base-none-eabi.tar.gz": "268449d832faf514a1682e4dac6a7cb1487a241c66149098a3a4533de7b805ee",
- "dist/2023-02-09/rust-std-1.67.1-thumbv8m.base-none-eabi.tar.xz": "72f5b820a4d7aa5788531f7f38d8f753b210be1d56fde3bd1c83057a248e241f",
- "dist/2023-02-09/rust-std-1.67.1-thumbv8m.main-none-eabi.tar.gz": "9e166c823274637357b77f143f80cdb50502b4af923d177da04b311a2f8c318e",
- "dist/2023-02-09/rust-std-1.67.1-thumbv8m.main-none-eabi.tar.xz": "651dc316c83e6b1f4e9f414b21767ad1360513a2e6a3fd996e717e281ce80c43",
- "dist/2023-02-09/rust-std-1.67.1-thumbv8m.main-none-eabihf.tar.gz": "65e02e4f5589f9228f57b752f9c519f6991c0d8a8bc239bcf0d648a0f47285ae",
- "dist/2023-02-09/rust-std-1.67.1-thumbv8m.main-none-eabihf.tar.xz": "e125927e5c4253ca283f027c5b7c4153f3c2b201930704eacdde86064b7f840a",
- "dist/2023-02-09/rust-std-1.67.1-wasm32-unknown-emscripten.tar.gz": "dacd3ed03d3546dfddb733d91ed9b744e297b96276751306db6006b0f19ca372",
- "dist/2023-02-09/rust-std-1.67.1-wasm32-unknown-emscripten.tar.xz": "30de37156a42593d108008450b3d9350859dae5b7006803a3b8551bbad846911",
- "dist/2023-02-09/rust-std-1.67.1-wasm32-unknown-unknown.tar.gz": "2c112ddefbc5df8d2bd46b05ed3046169ed6a5ae081ba84cba2e0bd21ba70317",
- "dist/2023-02-09/rust-std-1.67.1-wasm32-unknown-unknown.tar.xz": "cfde7cdda580f5b13d181b252c2f7736a5f634840b65a516eaa25fb2ae791002",
- "dist/2023-02-09/rust-std-1.67.1-wasm32-wasi.tar.gz": "7b3fa1ea3b8346a57832beb87bb760c565dd9359e4ce2288307b50a22120fa4b",
- "dist/2023-02-09/rust-std-1.67.1-wasm32-wasi.tar.xz": "7f421a7e7addc14ea8eb021d9d48c9ffbd5901878a25d89f48fa6a2bcea8d578",
- "dist/2023-02-09/rust-std-1.67.1-x86_64-apple-darwin.tar.gz": "0d1e93cada608ee1b4474af417dea2ac06590ba4cc963a9b9f5c7164ddf42b87",
- "dist/2023-02-09/rust-std-1.67.1-x86_64-apple-darwin.tar.xz": "75d516c07e943c3346fbf638834f2d61efc6d8ca94e507d8874562ebe761a3ae",
- "dist/2023-02-09/rust-std-1.67.1-x86_64-apple-ios.tar.gz": "eeab853aa1e77f1f1932e18bee16e4134da79c74bc2bc0ae80150d4fe5e6a606",
- "dist/2023-02-09/rust-std-1.67.1-x86_64-apple-ios.tar.xz": "aae07c34e71e23b5f9c1624daa8741cf8190ee18e9091ceb7897c36e29484f1e",
- "dist/2023-02-09/rust-std-1.67.1-x86_64-fortanix-unknown-sgx.tar.gz": "e6093ddf40857d0d2e5da0edfdaca41a89850612dd61633397a3a4342c911884",
- "dist/2023-02-09/rust-std-1.67.1-x86_64-fortanix-unknown-sgx.tar.xz": "20093299c6e90a707f86d85dadee463e6cfa1edf4df903903289a56e1593b588",
- "dist/2023-02-09/rust-std-1.67.1-x86_64-fuchsia.tar.gz": "0ff5f8f02df74442dc21ba0ceaef27b98547ca155dca7ab5f0a974a031d96ff9",
- "dist/2023-02-09/rust-std-1.67.1-x86_64-fuchsia.tar.xz": "80065ad2cd71cb36156c91fd66d065a3395dd9b5a80e90c1267b4be3f6174f66",
- "dist/2023-02-09/rust-std-1.67.1-x86_64-linux-android.tar.gz": "47994e3dd9e4447b426f5006e45921cfe67d6958ceea2ba5d7b7dfed9324d1ea",
- "dist/2023-02-09/rust-std-1.67.1-x86_64-linux-android.tar.xz": "90700e9bc007948878c5756a5ab7cc8df0d882614d0a6b34c77c296e5b2d7ae5",
- "dist/2023-02-09/rust-std-1.67.1-x86_64-pc-solaris.tar.gz": "c93f29fe0d222cc62a28534134a564e7b46cd39ce721f06a7aa08e99e003369e",
- "dist/2023-02-09/rust-std-1.67.1-x86_64-pc-solaris.tar.xz": "8a21318d1098fd27c2947cf0bf774455760d1a240da1ddd902bd78009adc315a",
- "dist/2023-02-09/rust-std-1.67.1-x86_64-pc-windows-gnu.tar.gz": "5088bfaf1d4b316e71655fcefb084cfa07876bd2ce832eb1e4b705ff27b3ad8a",
- "dist/2023-02-09/rust-std-1.67.1-x86_64-pc-windows-gnu.tar.xz": "b2d29d33c49fae57c3e6ed29d6879285326466ee7246b95da64462dcb153462f",
- "dist/2023-02-09/rust-std-1.67.1-x86_64-pc-windows-msvc.tar.gz": "3b5243d44998d7b731667dcb071dfbbbbd3ab7c301ddd0eb64e679c55a6a4aaa",
- "dist/2023-02-09/rust-std-1.67.1-x86_64-pc-windows-msvc.tar.xz": "2498173ddd136c1f68c3f6b871f80dce111ff3f9fc283ed77e4073d009ff0691",
- "dist/2023-02-09/rust-std-1.67.1-x86_64-sun-solaris.tar.gz": "299dcd20d6e50f875a143656106e3fa090d97e76b0bc5059e6be808b9215251c",
- "dist/2023-02-09/rust-std-1.67.1-x86_64-sun-solaris.tar.xz": "b6068036cc13c327959ee5474b4c5102a722f3b7b5de1f34befda5b33749499d",
- "dist/2023-02-09/rust-std-1.67.1-x86_64-unknown-freebsd.tar.gz": "aa6ac1844b06143a7533e44d129083d2c28a1d34953dc432c8c3591886cc892c",
- "dist/2023-02-09/rust-std-1.67.1-x86_64-unknown-freebsd.tar.xz": "8138d9bb13bbd96f2883eb83366793f315c30b3e20e5563dc3f4f93940526cf6",
- "dist/2023-02-09/rust-std-1.67.1-x86_64-unknown-illumos.tar.gz": "8c5d3c81b6a9303aac8645947ea005552172a79678eeff3a2183890e377e8c5f",
- "dist/2023-02-09/rust-std-1.67.1-x86_64-unknown-illumos.tar.xz": "6d1a1c1f8e16ab36a3b25229a5ce48c82b1ac4eec860eb7cf8b320547bd9d305",
- "dist/2023-02-09/rust-std-1.67.1-x86_64-unknown-linux-gnu.tar.gz": "31dfc19ae5821c0542975111574aa8cc7e0b2e1a95204f6cff7572f183524626",
- "dist/2023-02-09/rust-std-1.67.1-x86_64-unknown-linux-gnu.tar.xz": "f4dc8468dfc1dbd86f865b10f06e0e4b4e76f5a3a1cc27317a520ab1660844e9",
- "dist/2023-02-09/rust-std-1.67.1-x86_64-unknown-linux-gnux32.tar.gz": "bd2e06c1f3b6fd0356e263f57312489f720f580a2681d0da50e483c3bbee780d",
- "dist/2023-02-09/rust-std-1.67.1-x86_64-unknown-linux-gnux32.tar.xz": "6df9158831234058bca3fbdc64ecb51826be088b41f8d2dc1cf017bde5ff82b0",
- "dist/2023-02-09/rust-std-1.67.1-x86_64-unknown-linux-musl.tar.gz": "0d722ae8568b72bce0d4db5d3b717c12aa7d541da3bfe93606c59030b769af2b",
- "dist/2023-02-09/rust-std-1.67.1-x86_64-unknown-linux-musl.tar.xz": "89741cd2ac00c3a3f565bcccdf442cc1f9ec58ea419f1f0d09e911be0ff86c87",
- "dist/2023-02-09/rust-std-1.67.1-x86_64-unknown-netbsd.tar.gz": "351e4f61be6cc6cfa870d9574c02b2653def405955095d65743788b791168b72",
- "dist/2023-02-09/rust-std-1.67.1-x86_64-unknown-netbsd.tar.xz": "e7bf99890f8a47d804affced179bb47181c911ae13ae2dce9d1c7b632ef9eeb9",
- "dist/2023-02-09/rust-std-1.67.1-x86_64-unknown-none.tar.gz": "70f15d877e70fe733ea1675c37d8708ede565d851863d33fb500d66e1b137042",
- "dist/2023-02-09/rust-std-1.67.1-x86_64-unknown-none.tar.xz": "26a0e758ffc28cc6aa493778ecec4f0715480bbd8bbaad1773b8c6686dfd5001",
- "dist/2023-02-09/rust-std-1.67.1-x86_64-unknown-redox.tar.gz": "ce66599c3fbe2e7af4cab66c3415d5cb928dce6a63b0453e5bb1b3600fbb146e",
- "dist/2023-02-09/rust-std-1.67.1-x86_64-unknown-redox.tar.xz": "fc2f921813911939d027fd5608142c6afa6e0f8b9c95fd5c770efaddd40eb531",
- "dist/2023-02-09/rust-std-1.67.1-x86_64-unknown-uefi.tar.gz": "79c57252d2e15a643728015483a228466650e4db206629c480319a0ca14d5073",
- "dist/2023-02-09/rust-std-1.67.1-x86_64-unknown-uefi.tar.xz": "5549b3642f4be29fec964a3ffaa64b7cdf52022a56e253448de0fbb8d8d5afd2",
- "dist/2023-02-09/rustc-1.67.1-aarch64-apple-darwin.tar.gz": "81fb8f8e913b4bb5c2b3fac7704829347f660fc8b311abd3c72a2f1ff78fbc2a",
- "dist/2023-02-09/rustc-1.67.1-aarch64-apple-darwin.tar.xz": "9d0342e38141d3f1e3f681d870ad89ce91b57f3bc35723131f3e6818cbcdcad3",
- "dist/2023-02-09/rustc-1.67.1-aarch64-pc-windows-msvc.tar.gz": "3f594027025dbe41fa6fac9c8bf013e2b2fe25055566549e7148d90e9af3b36f",
- "dist/2023-02-09/rustc-1.67.1-aarch64-pc-windows-msvc.tar.xz": "b2ff8fbea09f45db4d52d4fe28f7ebfd26b3bc4a7f3d599f0e7e88fe2affac8f",
- "dist/2023-02-09/rustc-1.67.1-aarch64-unknown-linux-gnu.tar.gz": "accb1afa2674730b69a762f79b4f71bbb5211c4f5b022b115d8e034775dba5ad",
- "dist/2023-02-09/rustc-1.67.1-aarch64-unknown-linux-gnu.tar.xz": "053ccc4ab81ea9c16906205c2b653a93b5b44fe4f67f9e45153a2687b7efb65a",
- "dist/2023-02-09/rustc-1.67.1-aarch64-unknown-linux-musl.tar.gz": "eec2f6c5e33bd951e3439bab45b11cfc6db2098c8749a46e4b1bd5674a4f8f41",
- "dist/2023-02-09/rustc-1.67.1-aarch64-unknown-linux-musl.tar.xz": "8505a1a19eb1b85d4bfae6ea836430a8e42317949f49659d6d57bedc216831c6",
- "dist/2023-02-09/rustc-1.67.1-arm-unknown-linux-gnueabi.tar.gz": "340e21d21078a91e411c98043d4b618f155ceff77f542e7d7b0b0a9e77d5740e",
- "dist/2023-02-09/rustc-1.67.1-arm-unknown-linux-gnueabi.tar.xz": "bd71789ad9437e54ff1ed712f0bfd778a3a014626e1eac8e2551657e24e8b6b9",
- "dist/2023-02-09/rustc-1.67.1-arm-unknown-linux-gnueabihf.tar.gz": "c764753baf1707a8f82489c0ccaecffbba1d7d0c57f5b21c546c3d08aa66da45",
- "dist/2023-02-09/rustc-1.67.1-arm-unknown-linux-gnueabihf.tar.xz": "b2c3855966c36dc6271af80b5c39387a5ee0d8d9d84d0a7226296cf5b18a7f53",
- "dist/2023-02-09/rustc-1.67.1-armv7-unknown-linux-gnueabihf.tar.gz": "db39bbfdc665a585c811d6235823b525d5b642803f4c66d7162e9bc22b79f1f1",
- "dist/2023-02-09/rustc-1.67.1-armv7-unknown-linux-gnueabihf.tar.xz": "0a4c844f44bb00dca6d8e457a496a7e12c1eeb2514f9400f75f310d3d389e952",
- "dist/2023-02-09/rustc-1.67.1-i686-pc-windows-gnu.tar.gz": "865c5706e97693c59a1542060a05ff7f75fd9ddee8b96a9643e007a871b22480",
- "dist/2023-02-09/rustc-1.67.1-i686-pc-windows-gnu.tar.xz": "e1dfa96b247fa6ebde7df70affda22bb0fdaa3e0c465eb96fae2db42885639c6",
- "dist/2023-02-09/rustc-1.67.1-i686-pc-windows-msvc.tar.gz": "e9ed849e4e8f7f7a2591b7de8b8324f92e4174052dcc1c9a24bee08b5f856ae1",
- "dist/2023-02-09/rustc-1.67.1-i686-pc-windows-msvc.tar.xz": "1450669a9c6cc83016b5e9f2eaf843d2660bc38baae9469536b0fb49f7ada603",
- "dist/2023-02-09/rustc-1.67.1-i686-unknown-linux-gnu.tar.gz": "4dd74d1fa7af449a4296f5308da95a5cce75142d0b79dd956bccba7ea2dc461b",
- "dist/2023-02-09/rustc-1.67.1-i686-unknown-linux-gnu.tar.xz": "0c77fde6daa80825f8cb81a5525c99db238a3ab4f0b226470964062e74603dd6",
- "dist/2023-02-09/rustc-1.67.1-mips-unknown-linux-gnu.tar.gz": "03e93c1881786484fc4913b3419133551a5002778a28e5fb35bc5ea483d5ed22",
- "dist/2023-02-09/rustc-1.67.1-mips-unknown-linux-gnu.tar.xz": "d3b7501acdfda6e4e9d8ee64d9de716579791d567c66f1273e601a55c2e23ca8",
- "dist/2023-02-09/rustc-1.67.1-mips64-unknown-linux-gnuabi64.tar.gz": "7db6cd3e7b3c2a56232c6b9719db9d62f29f3c82971150da556bbbebf84a7bad",
- "dist/2023-02-09/rustc-1.67.1-mips64-unknown-linux-gnuabi64.tar.xz": "7a78e50890b840099c7a090ade98aa2a05a5df4e7cb1c177d9cc2ed9c5993134",
- "dist/2023-02-09/rustc-1.67.1-mips64el-unknown-linux-gnuabi64.tar.gz": "a5351ae7e0a847bcd664f09494fc285d832c83cff0b56e53cec6a461ba79e5dd",
- "dist/2023-02-09/rustc-1.67.1-mips64el-unknown-linux-gnuabi64.tar.xz": "83d12f1c0ecef87e333071aafac1defea312b688897056fa8af6468ac4f6308e",
- "dist/2023-02-09/rustc-1.67.1-mipsel-unknown-linux-gnu.tar.gz": "fde8bb59dbc3d4b4db495aaa91d7dcdfe9674df741a043d3b91a4f250077ebcf",
- "dist/2023-02-09/rustc-1.67.1-mipsel-unknown-linux-gnu.tar.xz": "eb34b5d901807e1e47fb6ac686571f21b2a80ad831583485872c9e9c59291776",
- "dist/2023-02-09/rustc-1.67.1-powerpc-unknown-linux-gnu.tar.gz": "f781c526f1e6439e547859d5f0a2c479bb1dc3e371c034576908cde5adc83c30",
- "dist/2023-02-09/rustc-1.67.1-powerpc-unknown-linux-gnu.tar.xz": "8f6212756d152f6876a6456f4d3f93ef8b4b7e5c93b96fe515cb8183c0612d7b",
- "dist/2023-02-09/rustc-1.67.1-powerpc64-unknown-linux-gnu.tar.gz": "f820b24944f0bf63ebca3465acfcb49b7d12574551fc6554cb9eaa2ee91fcf35",
- "dist/2023-02-09/rustc-1.67.1-powerpc64-unknown-linux-gnu.tar.xz": "bdb08b549df5d7a421637efb0be00211b5ca9cf1e4214d66eb762b92e0f9b3fe",
- "dist/2023-02-09/rustc-1.67.1-powerpc64le-unknown-linux-gnu.tar.gz": "521f56d78849ccd693ceb8183770effc60630055ec91adb00415da8d569d8260",
- "dist/2023-02-09/rustc-1.67.1-powerpc64le-unknown-linux-gnu.tar.xz": "4a2368996acd1741200d720674101323fa951dfa580b64c8b2e9fdc09bb22534",
- "dist/2023-02-09/rustc-1.67.1-riscv64gc-unknown-linux-gnu.tar.gz": "efd112ccc3fbdb28b33f072aec22da6091655a5d97fda909444b86629d9e8dab",
- "dist/2023-02-09/rustc-1.67.1-riscv64gc-unknown-linux-gnu.tar.xz": "916d204d727f485abbadeef914ee881cf61fa3c167741a9ed29c9f4042c99e25",
- "dist/2023-02-09/rustc-1.67.1-s390x-unknown-linux-gnu.tar.gz": "0f909def335ff80df74f7cccf12bf4b8882eabffb5873dee8973a3f27267b59d",
- "dist/2023-02-09/rustc-1.67.1-s390x-unknown-linux-gnu.tar.xz": "e786d34e10069dc00774fe53bca092e537e96db6c9d5258a8b0221e4fa5a2caf",
- "dist/2023-02-09/rustc-1.67.1-x86_64-apple-darwin.tar.gz": "e052ff6c7a75e988ee20adde0e9f38635c8f530ee7ca0ddbdf0c8e53ccc431b7",
- "dist/2023-02-09/rustc-1.67.1-x86_64-apple-darwin.tar.xz": "4f00d3b67df405c7b8395e1ba014145e9ca9a3812bc5d4d1e5f0036b708ff890",
- "dist/2023-02-09/rustc-1.67.1-x86_64-pc-windows-gnu.tar.gz": "67d72f969df0676213b556db4f3617e3a2455b09adba6d918e4a1010423a8526",
- "dist/2023-02-09/rustc-1.67.1-x86_64-pc-windows-gnu.tar.xz": "5b0fac5f6575eed8209773661277aa7afe89ee3255d623a91c6613abe79bd594",
- "dist/2023-02-09/rustc-1.67.1-x86_64-pc-windows-msvc.tar.gz": "a554533b23a0a1cf50b03825e54b4cc4e69f5771022c6fdc3626d2619de7e74f",
- "dist/2023-02-09/rustc-1.67.1-x86_64-pc-windows-msvc.tar.xz": "e14befd441d07afd162da6d8a73844dcd9f4872b35e62f9d11f2843ffb5c96f3",
- "dist/2023-02-09/rustc-1.67.1-x86_64-unknown-freebsd.tar.gz": "bd03fa96a80a25162d1d2333a48ac31d58388f0aec52de5480eb83eb6208715d",
- "dist/2023-02-09/rustc-1.67.1-x86_64-unknown-freebsd.tar.xz": "554a0d2460b257c891c31097855493c15cca10b5a6faad4bdf54a14cef8f5b3a",
- "dist/2023-02-09/rustc-1.67.1-x86_64-unknown-illumos.tar.gz": "c2930a3abcc4824aae1e1b6bd12cd78f4e2c81b858ef6009c2e0b4eec1c75927",
- "dist/2023-02-09/rustc-1.67.1-x86_64-unknown-illumos.tar.xz": "91f76aac7c53bc04359fd0ae5f711c5a59bfd9e4e2ff2391dbc6cb27064c327d",
- "dist/2023-02-09/rustc-1.67.1-x86_64-unknown-linux-gnu.tar.gz": "11115542833004fff465fdc86994245b6446d988aebd42153203a6f9c3aeccef",
- "dist/2023-02-09/rustc-1.67.1-x86_64-unknown-linux-gnu.tar.xz": "e27ec0c6d1a2b2b38e5258904c3741ddb246bff5715aa95e595f818aa77f7bee",
- "dist/2023-02-09/rustc-1.67.1-x86_64-unknown-linux-musl.tar.gz": "3d986024f8589344dc2d9cfb6842d14b5223a5c4dfd5055a4e7b6e6c19f7d412",
- "dist/2023-02-09/rustc-1.67.1-x86_64-unknown-linux-musl.tar.xz": "55fa8c61c767d23357075162ebd8c2be7297f2127e683c40d5db53ebcf6a737f",
- "dist/2023-02-09/rustc-1.67.1-x86_64-unknown-netbsd.tar.gz": "373855f45b76123ca8dfae329c744314a2e5d839006e5cec97486f784ac23e7c",
- "dist/2023-02-09/rustc-1.67.1-x86_64-unknown-netbsd.tar.xz": "ac2ce0f3ce1359c15cc13b0ae42e55f6479c9bb1c8b4449b620415065bd3bb78"
+ "dist/2023-03-28/cargo-1.68.2-aarch64-apple-darwin.tar.gz": "7317f1a2823a78f531f433d55cf76baf8701d16268bded12e0501fc07e74c6f4",
+ "dist/2023-03-28/cargo-1.68.2-aarch64-apple-darwin.tar.xz": "00812cc56dfb8cb06ab997737279e6a3a46a8fca3ac7baf4f9a42b3f6e1d3a3f",
+ "dist/2023-03-28/cargo-1.68.2-aarch64-pc-windows-msvc.tar.gz": "c56dbd0fdfe9be73d076a6404d09d8480b4b624e277b87b4fd25d7da9382b979",
+ "dist/2023-03-28/cargo-1.68.2-aarch64-pc-windows-msvc.tar.xz": "860a4275795629fd9d9096a5aabab0f8f0a6c69ed61c23528f79a79f427ec756",
+ "dist/2023-03-28/cargo-1.68.2-aarch64-unknown-linux-gnu.tar.gz": "09119c8df515f3358dbbb23514a80deb5d9891a5fcd4323667dbc84f32a160da",
+ "dist/2023-03-28/cargo-1.68.2-aarch64-unknown-linux-gnu.tar.xz": "a1b1f8ffdd56747453cb9531f70474ddbe603533e7b06647a810e32fc7c3a8ba",
+ "dist/2023-03-28/cargo-1.68.2-aarch64-unknown-linux-musl.tar.gz": "d9db2875c301386a64c57339d0fe3560454fb487bec36e2c27a865ff5c9aa46c",
+ "dist/2023-03-28/cargo-1.68.2-aarch64-unknown-linux-musl.tar.xz": "8211b2472df3bfbf0a1eaeaec5dc51c5d8b657e192d35eaa4c6432f73d2f1818",
+ "dist/2023-03-28/cargo-1.68.2-arm-unknown-linux-gnueabi.tar.gz": "62e72f243e5b8e8d77bebe7e627ecaca6829c722fc26ce69a52e0d780f240dd8",
+ "dist/2023-03-28/cargo-1.68.2-arm-unknown-linux-gnueabi.tar.xz": "383cc67e1bb3159d48d2e054e03a3bf85719cd5f63af366f5c4893734018008e",
+ "dist/2023-03-28/cargo-1.68.2-arm-unknown-linux-gnueabihf.tar.gz": "b9573233b7a8897e178c1cedf0b23af9641f2d24d2507ba2f59c22d25430b724",
+ "dist/2023-03-28/cargo-1.68.2-arm-unknown-linux-gnueabihf.tar.xz": "38453a4c37bff2d7e579a60fcdccad7b0a1f1bd5decc64a811b6d10c009c52e6",
+ "dist/2023-03-28/cargo-1.68.2-armv7-unknown-linux-gnueabihf.tar.gz": "6dc62202328089b0ab9b7f743799ef8e0bbb81fb36e8a89509b1c100cf64211a",
+ "dist/2023-03-28/cargo-1.68.2-armv7-unknown-linux-gnueabihf.tar.xz": "14eb6b290c5613760e9a6194fba06eb4c4703766984b4b5793a474e811a64d9c",
+ "dist/2023-03-28/cargo-1.68.2-i686-pc-windows-gnu.tar.gz": "05ca31c43ba3cd9df4fb1c3d5c85694205fe13fded040d886be2a31a02f860d0",
+ "dist/2023-03-28/cargo-1.68.2-i686-pc-windows-gnu.tar.xz": "6ff3a6ff4d34d7d0d886802c656e8003cb8fc410be9165e3937ccb9c4149346a",
+ "dist/2023-03-28/cargo-1.68.2-i686-pc-windows-msvc.tar.gz": "52cc6639802e20fb097dee52917a45b3ae2df330c0ed29e3880bb48f33bee04b",
+ "dist/2023-03-28/cargo-1.68.2-i686-pc-windows-msvc.tar.xz": "604d47ee65a3b977d778a4d4a727241e80532d52a7a47a590007efafbd45461d",
+ "dist/2023-03-28/cargo-1.68.2-i686-unknown-linux-gnu.tar.gz": "f6dbeaaeaf4a755ef45ef006f517ba376f0e81f5c108fe8ec58034de0867e0ca",
+ "dist/2023-03-28/cargo-1.68.2-i686-unknown-linux-gnu.tar.xz": "aeee38c0cd35b531d9f00028f720358256e9f3b80b176467c6afc033a16c92aa",
+ "dist/2023-03-28/cargo-1.68.2-mips-unknown-linux-gnu.tar.gz": "dca2229faf1175a6c8505449d5218ac710ae05da524acabf20dd563157711031",
+ "dist/2023-03-28/cargo-1.68.2-mips-unknown-linux-gnu.tar.xz": "8d24614f31ba67fe10a642e9f49d64066b4ce6789a80a101ae10afcc2a194c97",
+ "dist/2023-03-28/cargo-1.68.2-mips64-unknown-linux-gnuabi64.tar.gz": "a10c27917c4739cdda446248ef1758d401cb76643a3e99777b5b0b38fbcf1360",
+ "dist/2023-03-28/cargo-1.68.2-mips64-unknown-linux-gnuabi64.tar.xz": "271b899caf65466fd4560649af3e7ec61601be34d943936e546622ae8b4f39a2",
+ "dist/2023-03-28/cargo-1.68.2-mips64el-unknown-linux-gnuabi64.tar.gz": "220109f11c4cf656553087b9f2f3bd08ad2714c8bd602586f56602e670d486c7",
+ "dist/2023-03-28/cargo-1.68.2-mips64el-unknown-linux-gnuabi64.tar.xz": "0809ff7f2ef910ac0b584ad1f184a0898e5e701b3c0e45b158b129efa50493dd",
+ "dist/2023-03-28/cargo-1.68.2-mipsel-unknown-linux-gnu.tar.gz": "c3f0e5a71736cc07d3527432eea945c3fa795ad4669b269615dad0ea5a20be1f",
+ "dist/2023-03-28/cargo-1.68.2-mipsel-unknown-linux-gnu.tar.xz": "8664ff821dfd8bb252c61c2b7473e355bd38cd8a6bc15a9ecc98af46f6a2b282",
+ "dist/2023-03-28/cargo-1.68.2-powerpc-unknown-linux-gnu.tar.gz": "5a9c71ce2f9930264e19cf7fe7241c68b2b20eafb9aa2461d51e0c769bd902c8",
+ "dist/2023-03-28/cargo-1.68.2-powerpc-unknown-linux-gnu.tar.xz": "13ad9e74376fc01d9d770447c141a18dd986dd60bbd4c6177ed80df4a28fc142",
+ "dist/2023-03-28/cargo-1.68.2-powerpc64-unknown-linux-gnu.tar.gz": "8fea8801334b48d64136f1eb32b90b84b44dccac7222b1d4147c171ef5609431",
+ "dist/2023-03-28/cargo-1.68.2-powerpc64-unknown-linux-gnu.tar.xz": "ad4eded41be32bb19a5f6224daacb9589947956f4be9f884f7ea06323b448088",
+ "dist/2023-03-28/cargo-1.68.2-powerpc64le-unknown-linux-gnu.tar.gz": "fd66f5fdbad088bbeb022dfef4bef8ff3744c70f1fed0a0455260b332a674cd6",
+ "dist/2023-03-28/cargo-1.68.2-powerpc64le-unknown-linux-gnu.tar.xz": "1eb1c330d281a9478d514724c5089225b3f66880f4a69e9e02b9d389f000adbb",
+ "dist/2023-03-28/cargo-1.68.2-riscv64gc-unknown-linux-gnu.tar.gz": "29e2b12210e32c7ef1dad89d2a231ce61497bd7a2462b8a7122cf7dff9f072ec",
+ "dist/2023-03-28/cargo-1.68.2-riscv64gc-unknown-linux-gnu.tar.xz": "d5a154406bc6ebc6d5cdd3198aa2b5167ceef130454c56bcf03e37fa6b290882",
+ "dist/2023-03-28/cargo-1.68.2-s390x-unknown-linux-gnu.tar.gz": "65c166fbb7fdb6a9d1d99e4ab77e08c8c2a8e38ab3319f7c3ce9a5caeb596d9d",
+ "dist/2023-03-28/cargo-1.68.2-s390x-unknown-linux-gnu.tar.xz": "26353406aba935e135e0527673bfd3805de88ff9a63187135e73b5788f385112",
+ "dist/2023-03-28/cargo-1.68.2-x86_64-apple-darwin.tar.gz": "c580e7dbf6bde9bf4246380ac1591682981dc7cbdb7b82a95eac8322d866e4bd",
+ "dist/2023-03-28/cargo-1.68.2-x86_64-apple-darwin.tar.xz": "f44907243f9f42b9505c692ff4ff0cbbcc9590b146db9491edbd950a443a5e24",
+ "dist/2023-03-28/cargo-1.68.2-x86_64-pc-windows-gnu.tar.gz": "f1b563a41a08312ca38c7b9e91d2b3a3461ce6d0b5a88593ffe42f4cfa610b60",
+ "dist/2023-03-28/cargo-1.68.2-x86_64-pc-windows-gnu.tar.xz": "9158f8ec0793bd5f993c99fcc656b860507a394a4fb4df17c5350096e045dadd",
+ "dist/2023-03-28/cargo-1.68.2-x86_64-pc-windows-msvc.tar.gz": "374b25dfb7ec5ca31e0da96be1e854e7024b9b52580e457065f844197130b2e4",
+ "dist/2023-03-28/cargo-1.68.2-x86_64-pc-windows-msvc.tar.xz": "5c071ff9295e6309da4c71214a5b47f16033138bb74b783ad94acf45ba83c884",
+ "dist/2023-03-28/cargo-1.68.2-x86_64-unknown-freebsd.tar.gz": "4cc87ec3298db3f5464ab989c50b0641bfa5b5499996a2ad34da92260f8db17f",
+ "dist/2023-03-28/cargo-1.68.2-x86_64-unknown-freebsd.tar.xz": "b0a113d7f2992e6aa8827fd095c3bb9507b27b27a83d7aa2c98931f0a4dca9e6",
+ "dist/2023-03-28/cargo-1.68.2-x86_64-unknown-illumos.tar.gz": "d1d29e55aa9b8ed2bb9764eff921af59254fd56e81083b136bf27de9bc1e4f4a",
+ "dist/2023-03-28/cargo-1.68.2-x86_64-unknown-illumos.tar.xz": "5a656c5932964bb7d243a8a03455c20df1dee9aafec0382a711d794324cf2a95",
+ "dist/2023-03-28/cargo-1.68.2-x86_64-unknown-linux-gnu.tar.gz": "cf4e6c9d1a61c1898ffa21353fc9eb4c1512fc6beb6cad433851fbed777f1ea6",
+ "dist/2023-03-28/cargo-1.68.2-x86_64-unknown-linux-gnu.tar.xz": "b25d6f88b93cb75868ff4bc9ca0103facd4622825cf53df67546cea6cb60da0f",
+ "dist/2023-03-28/cargo-1.68.2-x86_64-unknown-linux-musl.tar.gz": "cfc86423b17adcbcdb4eec35ebc17f20ba73d181349ae01b0e17530332d12cb1",
+ "dist/2023-03-28/cargo-1.68.2-x86_64-unknown-linux-musl.tar.xz": "3427b766797da0a1065a84b074b93a309763ca5b94575d0f8b70b1f4e50c159e",
+ "dist/2023-03-28/cargo-1.68.2-x86_64-unknown-netbsd.tar.gz": "d1c72bccba9b2b534715c3cd9d2f4ae83ceff312d8533c270d168e4b97ba74d0",
+ "dist/2023-03-28/cargo-1.68.2-x86_64-unknown-netbsd.tar.xz": "57a45f1dc54c5e39fdf8a61342d774820adc4f6bdc0ecb53d4ff9aa0c448a02a",
+ "dist/2023-03-28/rust-std-1.68.2-aarch64-apple-darwin.tar.gz": "db2be7e5d766799796a71e43f141a5082ac30240e276c8c9b56800ab4638af92",
+ "dist/2023-03-28/rust-std-1.68.2-aarch64-apple-darwin.tar.xz": "3c18e4f87fc69a6907d9a76db079f3e59a26764b001157c2fc9c4c8497d5448b",
+ "dist/2023-03-28/rust-std-1.68.2-aarch64-apple-ios-sim.tar.gz": "123a67f9f8de9c3a4d793a864e05c5d59c0fb630611b97dd36e26805e549e539",
+ "dist/2023-03-28/rust-std-1.68.2-aarch64-apple-ios-sim.tar.xz": "e0287fb4e98b375495923aeddbd71111a17b9ef92c597277f24b9de5bcbe0fa6",
+ "dist/2023-03-28/rust-std-1.68.2-aarch64-apple-ios.tar.gz": "71d943a0340fbb3b0aec6f3a61c421b3a600235e3111b2d76464f1cd17326300",
+ "dist/2023-03-28/rust-std-1.68.2-aarch64-apple-ios.tar.xz": "cab7d6262087d1bb17fc0163923d8f8c786b2ddbd896caf6a5d959b982e13e1c",
+ "dist/2023-03-28/rust-std-1.68.2-aarch64-linux-android.tar.gz": "03f42f35c6b1426983e4dc0af017c4d7953d079f650f783512c06a9b5d30805c",
+ "dist/2023-03-28/rust-std-1.68.2-aarch64-linux-android.tar.xz": "5ad8e087347ba337198e4464913f1cc6bf5525f81a6388450faec5b20676c8ab",
+ "dist/2023-03-28/rust-std-1.68.2-aarch64-pc-windows-msvc.tar.gz": "351f99049c211b6828aaa964a5ef999eeb2f6d470ad5173379a428db082b65f1",
+ "dist/2023-03-28/rust-std-1.68.2-aarch64-pc-windows-msvc.tar.xz": "4d5c76138f9d2ece590515e2dda8cd2b606a061bcfd2024bf147348070cdda88",
+ "dist/2023-03-28/rust-std-1.68.2-aarch64-unknown-fuchsia.tar.gz": "2e43837dc70ec0ddde4a5deeef18b61a33fce8873159c672c3ea3719b2c1d314",
+ "dist/2023-03-28/rust-std-1.68.2-aarch64-unknown-fuchsia.tar.xz": "b10838f356514d3d85bf9b4cac1971daa30c7a29af532602453115d3f037cc8f",
+ "dist/2023-03-28/rust-std-1.68.2-aarch64-unknown-linux-gnu.tar.gz": "74c2cca31e34cbc0913fc2445c4853acb20c52dba2d0c3012a007cc5decc3bb1",
+ "dist/2023-03-28/rust-std-1.68.2-aarch64-unknown-linux-gnu.tar.xz": "cbe60945af743804be6822704f986c812dd1fe1d167602aec5350a8f519f9861",
+ "dist/2023-03-28/rust-std-1.68.2-aarch64-unknown-linux-musl.tar.gz": "fe2558065f0c2f119ea36be2edd74b862899d01abf463baa0f128839c52e2021",
+ "dist/2023-03-28/rust-std-1.68.2-aarch64-unknown-linux-musl.tar.xz": "718c073d24f3627750049bb74420f90d1ac29843ca16933e11aa301a806a0b10",
+ "dist/2023-03-28/rust-std-1.68.2-aarch64-unknown-none-softfloat.tar.gz": "d556518078ff7f7f7c2eb7fbe192e15d794f4fc1e6f43939cb6d46e6aad6c655",
+ "dist/2023-03-28/rust-std-1.68.2-aarch64-unknown-none-softfloat.tar.xz": "9a3ef9df914cba6a96404a768158a5d068251c97e47e8b77bd1fe163b2e01d70",
+ "dist/2023-03-28/rust-std-1.68.2-aarch64-unknown-none.tar.gz": "ef7283c7c449d15b8801fd5a8f5f36beca3ed16666ce23ad5d215544a695dacb",
+ "dist/2023-03-28/rust-std-1.68.2-aarch64-unknown-none.tar.xz": "4f90feac2c0a0c940fbfee2f47ff99e2d9c0249a585e850e51d2c17e1a42d1fc",
+ "dist/2023-03-28/rust-std-1.68.2-aarch64-unknown-uefi.tar.gz": "7f92979d44a7c494cc67df648f9d55dcfed2a3b1451767810ff86ba64d8af680",
+ "dist/2023-03-28/rust-std-1.68.2-aarch64-unknown-uefi.tar.xz": "ee7b6e77b69e27a7e429fe33ed03e08f80e2c653429d3f3ea0eff81a16463566",
+ "dist/2023-03-28/rust-std-1.68.2-arm-linux-androideabi.tar.gz": "e6883b69e0d2be0973083e02a3ccac9868ff8d1105f22eb0be944dc981557267",
+ "dist/2023-03-28/rust-std-1.68.2-arm-linux-androideabi.tar.xz": "0cb2dbf9cc116848300498eecbdbb9979a3bd6e78a0d970095c7b4753c5f001b",
+ "dist/2023-03-28/rust-std-1.68.2-arm-unknown-linux-gnueabi.tar.gz": "6b80d044fe690084ca6fb0c6dc0d9d353fe8ec5fa09fc0d59a1d7eda322b3bb0",
+ "dist/2023-03-28/rust-std-1.68.2-arm-unknown-linux-gnueabi.tar.xz": "59da96890b0a2881799b21a3f49e51f730d67b8dc09b87602dd599e8f980e247",
+ "dist/2023-03-28/rust-std-1.68.2-arm-unknown-linux-gnueabihf.tar.gz": "5e662e9754fca1ca8e9ed18359b39b8bf0ec06c641f7b61174738347e3774324",
+ "dist/2023-03-28/rust-std-1.68.2-arm-unknown-linux-gnueabihf.tar.xz": "565730a2ba02357251f9805b5efe0423adf5411892e0d01cf441456234f81e70",
+ "dist/2023-03-28/rust-std-1.68.2-arm-unknown-linux-musleabi.tar.gz": "28a6750eb0bd4017ae16228ad10a3b7d913b11ae493c7fb948eb454b880ce78b",
+ "dist/2023-03-28/rust-std-1.68.2-arm-unknown-linux-musleabi.tar.xz": "fd065db4269b5131c2f52638b8f30d0159109850c74c87bdf4c623dc0b32d5c2",
+ "dist/2023-03-28/rust-std-1.68.2-arm-unknown-linux-musleabihf.tar.gz": "a033a94fd8bee6e4fea391b5750066b74a4c0b3a4191157632a55af9b8bb2d44",
+ "dist/2023-03-28/rust-std-1.68.2-arm-unknown-linux-musleabihf.tar.xz": "4ea9588934eec3d83bee2789f3a15b48aaea05fc8ec1bc175951ec1d0eb6ed22",
+ "dist/2023-03-28/rust-std-1.68.2-armebv7r-none-eabi.tar.gz": "ac809aa7b7e61d028d82a262c2e75cd3466468c15116b68fa011056110927cf9",
+ "dist/2023-03-28/rust-std-1.68.2-armebv7r-none-eabi.tar.xz": "f9667eff4ee8c8812f07ef3dd94389062236860f820be37cd08a96d472756ef4",
+ "dist/2023-03-28/rust-std-1.68.2-armebv7r-none-eabihf.tar.gz": "69e5787f778a82816662a54ae134a5873d9ad3699024b4f5c490f596336b24b4",
+ "dist/2023-03-28/rust-std-1.68.2-armebv7r-none-eabihf.tar.xz": "a14e4588c6af1bca6fb083c248e06999bb8c398d62bf557f93e5076bede8a5b1",
+ "dist/2023-03-28/rust-std-1.68.2-armv5te-unknown-linux-gnueabi.tar.gz": "897ec452cd656af3f0b9be53f8a48ad37f908f53ba5f694fcf2d30de3cc39cf1",
+ "dist/2023-03-28/rust-std-1.68.2-armv5te-unknown-linux-gnueabi.tar.xz": "a7e19b68c44efe52df159f89f8b37790ca613adaa3f77937eb460747552d1e59",
+ "dist/2023-03-28/rust-std-1.68.2-armv5te-unknown-linux-musleabi.tar.gz": "a14fe46481437b5647da8a82348245dedbae5069340ac7b61d6eeec71cf2245c",
+ "dist/2023-03-28/rust-std-1.68.2-armv5te-unknown-linux-musleabi.tar.xz": "74188e1a1f4f7418d946636b4280c03dc80933f6eedda75ece82b7034f32c6db",
+ "dist/2023-03-28/rust-std-1.68.2-armv7-linux-androideabi.tar.gz": "8256c9cc16a9e7dee7aef32b309dd72f9a6cdbb8017f6672c43a759392f1d5db",
+ "dist/2023-03-28/rust-std-1.68.2-armv7-linux-androideabi.tar.xz": "d68c72ee56cb0cebd24626f43db10b373d7bb64ffe3e6ccabd60faa648d06882",
+ "dist/2023-03-28/rust-std-1.68.2-armv7-unknown-linux-gnueabi.tar.gz": "0ccb53e521a02f778e2c086e7da19966cbcb4a9934475a41dd1540090d8e89c8",
+ "dist/2023-03-28/rust-std-1.68.2-armv7-unknown-linux-gnueabi.tar.xz": "39009be69f01e30714c657a5f55475ce9f9c6a591cae85b5d7386944a8e87a80",
+ "dist/2023-03-28/rust-std-1.68.2-armv7-unknown-linux-gnueabihf.tar.gz": "53de9bc49050bb15e0f01ac655c3b08610c59effdee7b5e50bcb9880170a14fe",
+ "dist/2023-03-28/rust-std-1.68.2-armv7-unknown-linux-gnueabihf.tar.xz": "2b9b98eaf7d18049e4c8625a4cf3c2d610d905c9478a377c6cc3d48f8b31db32",
+ "dist/2023-03-28/rust-std-1.68.2-armv7-unknown-linux-musleabi.tar.gz": "55d8e89d624eb8c34ca13207118d5e84e4144c7f1686bd26972b032c6b83a189",
+ "dist/2023-03-28/rust-std-1.68.2-armv7-unknown-linux-musleabi.tar.xz": "b9992ee3b16c7b3b2fcf15339ade26084936d6088f578f8b2fab9b0c5c5b085c",
+ "dist/2023-03-28/rust-std-1.68.2-armv7-unknown-linux-musleabihf.tar.gz": "3d3b06c29dda5b5bfcfea69a3cb5037d16119772191472826fbb3ec82018ac90",
+ "dist/2023-03-28/rust-std-1.68.2-armv7-unknown-linux-musleabihf.tar.xz": "05bef3f9e66537d9f1271dd6b6bf2261ba1db52672223712a8eb9178d036ae53",
+ "dist/2023-03-28/rust-std-1.68.2-armv7a-none-eabi.tar.gz": "a99f963a5b5f7605454334ce26b0f45a19d6fed98f575ac01c4266647c86dca0",
+ "dist/2023-03-28/rust-std-1.68.2-armv7a-none-eabi.tar.xz": "3bbc611787495173e95f2d9202c0292aca27e87c11bdd5da707236cb5b3c234a",
+ "dist/2023-03-28/rust-std-1.68.2-armv7r-none-eabi.tar.gz": "8c83571fb066c0d3a5cd7b29cffbbc2581207e7d927f83aa9542def079044142",
+ "dist/2023-03-28/rust-std-1.68.2-armv7r-none-eabi.tar.xz": "5292ee455628bc018766e2a2d2bf13308132d826f0acbe4785cf173583a284d6",
+ "dist/2023-03-28/rust-std-1.68.2-armv7r-none-eabihf.tar.gz": "2801d1f8fc3124a99fdaa23244a7435389f4f140aa53c77396691871eb52a5d7",
+ "dist/2023-03-28/rust-std-1.68.2-armv7r-none-eabihf.tar.xz": "e3f905cdfec9a9f57b386698d322f0e637f2be2f1e79bfa2e52b25aa6c06a2d9",
+ "dist/2023-03-28/rust-std-1.68.2-asmjs-unknown-emscripten.tar.gz": "8fe55fd760e815b97bbff2dd18cdd81865d601a03f3d84e878d32f48f11ee785",
+ "dist/2023-03-28/rust-std-1.68.2-asmjs-unknown-emscripten.tar.xz": "0fec97c490656741a82f85259900c5fdb86d947fa2970c39f8184571cb41f9b2",
+ "dist/2023-03-28/rust-std-1.68.2-i586-pc-windows-msvc.tar.gz": "ee398d855c8bc6154f4b70356c40a52af4c89c38ac83da6cca965248b9273137",
+ "dist/2023-03-28/rust-std-1.68.2-i586-pc-windows-msvc.tar.xz": "a91a1bb2956ff3b8dee5dedd4662eebb5dd98baa229f87deade34e415c639866",
+ "dist/2023-03-28/rust-std-1.68.2-i586-unknown-linux-gnu.tar.gz": "d24eb133b3c12b6cb9d8293dca63af9628db201fc4ad15e94d39bd636e0cafaf",
+ "dist/2023-03-28/rust-std-1.68.2-i586-unknown-linux-gnu.tar.xz": "07fc71adf63691ae5e103c57c295e665b6dfc096fe4bedfeb5e1d33c133bb9f4",
+ "dist/2023-03-28/rust-std-1.68.2-i586-unknown-linux-musl.tar.gz": "aac0678c9051e94a48f8014e5c0195907d5e26c1ad57b230e90fe86c9b8ef426",
+ "dist/2023-03-28/rust-std-1.68.2-i586-unknown-linux-musl.tar.xz": "884c3b6cbe8d38bb15943917df8bc87470566014ec50200ed70094c12abbb6bd",
+ "dist/2023-03-28/rust-std-1.68.2-i686-linux-android.tar.gz": "4c0c4ca237385caceeb7d198b6fe9cd79b78040cc9142bc38d553fa61271f62e",
+ "dist/2023-03-28/rust-std-1.68.2-i686-linux-android.tar.xz": "f594e57950ae46c27fe61421accae1f0feda4d231ce29fbc07bdc2b016bff52a",
+ "dist/2023-03-28/rust-std-1.68.2-i686-pc-windows-gnu.tar.gz": "7a0c8c30db0109a093af231c9290ba8553da01cac32fe297444e8398565a0fd7",
+ "dist/2023-03-28/rust-std-1.68.2-i686-pc-windows-gnu.tar.xz": "fdc9f2906131b64f3379da995db978d454ad06cb50acd17925bb65ae7c477639",
+ "dist/2023-03-28/rust-std-1.68.2-i686-pc-windows-msvc.tar.gz": "51bb5146439365a78a41fd674df23c9771d074fe0e43bcd020d54a0b1a8ec472",
+ "dist/2023-03-28/rust-std-1.68.2-i686-pc-windows-msvc.tar.xz": "070225d9f555bdc55c635491c923ec8246156b7af835c5c0d9866edbb448578e",
+ "dist/2023-03-28/rust-std-1.68.2-i686-unknown-freebsd.tar.gz": "38efed7b4f3c1ee3b3b7c26eedd0f5addafd36471dbf34146f6bb5293d970da8",
+ "dist/2023-03-28/rust-std-1.68.2-i686-unknown-freebsd.tar.xz": "6eec64c8a5ecc5129a21fee147f7d10f628177d07a6c4e0e42e4796ffe88c4f6",
+ "dist/2023-03-28/rust-std-1.68.2-i686-unknown-linux-gnu.tar.gz": "0de164eb5673978149a4c5d73371f56021dfe2a38bc7a2dd17226ce97ce4bf3e",
+ "dist/2023-03-28/rust-std-1.68.2-i686-unknown-linux-gnu.tar.xz": "695d4469c131b9993c939db0ce73a3866ab8e69dd657ec3137f3d594857f7812",
+ "dist/2023-03-28/rust-std-1.68.2-i686-unknown-linux-musl.tar.gz": "16ecbaabc95cd0c1db5e4a8e6c36bc3d74cef9cee3ed3585edcb253bfa336150",
+ "dist/2023-03-28/rust-std-1.68.2-i686-unknown-linux-musl.tar.xz": "216a647fb15ffce5271b82c2c016f01b3d69095ab4635d6a895f9b76b6c1c528",
+ "dist/2023-03-28/rust-std-1.68.2-i686-unknown-uefi.tar.gz": "f9b8ac7553102dee3075b63b74878c479c6509e908bb4e85bbbbb2df3f60d147",
+ "dist/2023-03-28/rust-std-1.68.2-i686-unknown-uefi.tar.xz": "3cec2ff84038d6fa3a0f84b27e0624057ba2894ecdaab9b06bf4e0e11c70aa56",
+ "dist/2023-03-28/rust-std-1.68.2-mips-unknown-linux-gnu.tar.gz": "da3efcb29495f1965a27c8c67b060459104762acbd8278a427cb1307bf8a431d",
+ "dist/2023-03-28/rust-std-1.68.2-mips-unknown-linux-gnu.tar.xz": "4ab007f223cf723f8f7adf26a6014f4f5aa444f88c19daccc5ac81ea30275c66",
+ "dist/2023-03-28/rust-std-1.68.2-mips-unknown-linux-musl.tar.gz": "411366b7cfa00cdb1da76dbd761d55f32d8780ef3b12c10edafe58dfec1286b0",
+ "dist/2023-03-28/rust-std-1.68.2-mips-unknown-linux-musl.tar.xz": "0c77f06f410091371b7f6f4952d759fcc0365025213f925afe80e04ab4b53540",
+ "dist/2023-03-28/rust-std-1.68.2-mips64-unknown-linux-gnuabi64.tar.gz": "747c57f7259ef1a157717ac8b17dcd031460f81d39a4ce9091dd4b5f2e76ce5f",
+ "dist/2023-03-28/rust-std-1.68.2-mips64-unknown-linux-gnuabi64.tar.xz": "b1b44819454c920980e66473112003212920136e4904113258566d130686de09",
+ "dist/2023-03-28/rust-std-1.68.2-mips64-unknown-linux-muslabi64.tar.gz": "0b509d1b36d4bdfaea974a359b08c93c326d81644066dd09a370f8f82ca724af",
+ "dist/2023-03-28/rust-std-1.68.2-mips64-unknown-linux-muslabi64.tar.xz": "af586b37cac123774addc78d8c4568f22d94cec622ca9de80631f33da2700a6e",
+ "dist/2023-03-28/rust-std-1.68.2-mips64el-unknown-linux-gnuabi64.tar.gz": "abd8ff476c603322438e3afdf10cdb9e8206f008ba2a86f7416e2079b41c9143",
+ "dist/2023-03-28/rust-std-1.68.2-mips64el-unknown-linux-gnuabi64.tar.xz": "24028147dd7733637cbfe58b7f7acc8e8131ebbb39969a6c3c61ce56203b4af3",
+ "dist/2023-03-28/rust-std-1.68.2-mips64el-unknown-linux-muslabi64.tar.gz": "0ad700c67e89f4072b1b75c4b31b92c53585d212f323247c382925e042ef19f0",
+ "dist/2023-03-28/rust-std-1.68.2-mips64el-unknown-linux-muslabi64.tar.xz": "a6ae7b9b1710100f52d96dab59c6e7c46a4b057b8ea3d25b8ea2f792aee2f006",
+ "dist/2023-03-28/rust-std-1.68.2-mipsel-unknown-linux-gnu.tar.gz": "8bbb2ba4b3d42602e2acf24fcfc9dcbb862e89e4cf46b4b24e1d984c5bd8ce45",
+ "dist/2023-03-28/rust-std-1.68.2-mipsel-unknown-linux-gnu.tar.xz": "c299d65b3594c309d092f6a0fe15c205ab489ffa50910fb8126e944a2727cbe5",
+ "dist/2023-03-28/rust-std-1.68.2-mipsel-unknown-linux-musl.tar.gz": "93c40a6f2c46e35fb2b4c101000a354ef4ecfb949f8dc6c17fc5566dbdc61cab",
+ "dist/2023-03-28/rust-std-1.68.2-mipsel-unknown-linux-musl.tar.xz": "a6bbd8949dc8514161de4e367c5255e8b83a3cf78c8426ffacbb6e8077d0e5e0",
+ "dist/2023-03-28/rust-std-1.68.2-nvptx64-nvidia-cuda.tar.gz": "74bfa32f412403f5d453be4c4aa1852a13fd76659f3a4f7f9fdee048c259a6f8",
+ "dist/2023-03-28/rust-std-1.68.2-nvptx64-nvidia-cuda.tar.xz": "c7ffadab1939d18864511d0f7d575a3c62ec2d2d43b7736c7650b30e5f08d908",
+ "dist/2023-03-28/rust-std-1.68.2-powerpc-unknown-linux-gnu.tar.gz": "e41bac22c22ce54b2becf072ffe790421e1c775723996eab4f578c181100e6ab",
+ "dist/2023-03-28/rust-std-1.68.2-powerpc-unknown-linux-gnu.tar.xz": "e75bdc8a6e3f00285a37606240862cdad69a986c3e3d47d6af1376613281233a",
+ "dist/2023-03-28/rust-std-1.68.2-powerpc64-unknown-linux-gnu.tar.gz": "0a367b83afae71be859a7063b26b83d35b090f84179f83b6a40a109f5ae16238",
+ "dist/2023-03-28/rust-std-1.68.2-powerpc64-unknown-linux-gnu.tar.xz": "354322352cd8b661b84f5e97729d5d7adb7df9cb9bfd43cac378271c40214d7f",
+ "dist/2023-03-28/rust-std-1.68.2-powerpc64le-unknown-linux-gnu.tar.gz": "5ff3de9d9549369614e90c58bc75d1f966097ff58fda9d668d197cba5f65be6c",
+ "dist/2023-03-28/rust-std-1.68.2-powerpc64le-unknown-linux-gnu.tar.xz": "e69c8c1b7b0df839b271a2c12985b1c56565a34f9b357631ed99fa9263f3d326",
+ "dist/2023-03-28/rust-std-1.68.2-riscv32i-unknown-none-elf.tar.gz": "0dc08ab79536b3d755a3f79fc75867aad8bde8c79cbaa427d9988576a4c9fe42",
+ "dist/2023-03-28/rust-std-1.68.2-riscv32i-unknown-none-elf.tar.xz": "5fd9c02ae9c6e61f8123c725c0e59bfc10c1f1b2022d6937b93983694333ef4a",
+ "dist/2023-03-28/rust-std-1.68.2-riscv32imac-unknown-none-elf.tar.gz": "e8151762c4c6cc24911ef37132c7df3541e25b848c46d008f4bf0d56cfcdfd0b",
+ "dist/2023-03-28/rust-std-1.68.2-riscv32imac-unknown-none-elf.tar.xz": "ae89f2342ff0095b6464bf21f6acfc8c22f5bfa463f0096944287572cc47ab5f",
+ "dist/2023-03-28/rust-std-1.68.2-riscv32imc-unknown-none-elf.tar.gz": "6b9f3465a22e3ccd1ae446ad90363e772dadf52f05c80fdeb5097d14d9ba4442",
+ "dist/2023-03-28/rust-std-1.68.2-riscv32imc-unknown-none-elf.tar.xz": "c79b774efb8ff05943dd5a426f9408894698b9a8b88e76396a82b751de6ffd24",
+ "dist/2023-03-28/rust-std-1.68.2-riscv64gc-unknown-linux-gnu.tar.gz": "8409cf5ef0772c042fc3ab902e41048e9f15f7362b185403393519efdea7e947",
+ "dist/2023-03-28/rust-std-1.68.2-riscv64gc-unknown-linux-gnu.tar.xz": "8388ac7a5f924d5d6aa441ae97c33c1abf11fd9516f2b9853f7edc0c5d6c453b",
+ "dist/2023-03-28/rust-std-1.68.2-riscv64gc-unknown-none-elf.tar.gz": "c271cc91e5c4f1912cb786f167f14e40f862de1ba1637252a984cd2fb767e0a2",
+ "dist/2023-03-28/rust-std-1.68.2-riscv64gc-unknown-none-elf.tar.xz": "19fb8778a165cc5bd8b7c8d96a5f2af1a11c4d000f6806ef239be4a1adb12b44",
+ "dist/2023-03-28/rust-std-1.68.2-riscv64imac-unknown-none-elf.tar.gz": "b3ce497a5de00dc5d7d95527fb15c708683154c28e0d3a80265415b0d7389f21",
+ "dist/2023-03-28/rust-std-1.68.2-riscv64imac-unknown-none-elf.tar.xz": "d72e9b88b7841ca55a939b8689c3f0a443e61942f5032e4122fe510066ff26ff",
+ "dist/2023-03-28/rust-std-1.68.2-s390x-unknown-linux-gnu.tar.gz": "cf05d65ef0aad4b35054e6b13a062c71f2ef1a30f7e951276b9986abbb4fb251",
+ "dist/2023-03-28/rust-std-1.68.2-s390x-unknown-linux-gnu.tar.xz": "7f909658496692a05dd241c15f79a02f80658d353013dace127fdc69dc5026b4",
+ "dist/2023-03-28/rust-std-1.68.2-sparc64-unknown-linux-gnu.tar.gz": "68689effcfa42b6450643b8663bbf940ce065bb878c3d4c5cd238a9c74240359",
+ "dist/2023-03-28/rust-std-1.68.2-sparc64-unknown-linux-gnu.tar.xz": "787f5cbbcec4e75b9beba3804ea05e36b7cb9b164c291cf7ce8f775d05634d61",
+ "dist/2023-03-28/rust-std-1.68.2-sparcv9-sun-solaris.tar.gz": "47decd5464092484ffee454126dbc6e53dbd71b4f4b67166df36c1d80f555b97",
+ "dist/2023-03-28/rust-std-1.68.2-sparcv9-sun-solaris.tar.xz": "f69c32e3dba525a5041d8d3282558c0407d675d47756363e2cf4e7a498b7795d",
+ "dist/2023-03-28/rust-std-1.68.2-thumbv6m-none-eabi.tar.gz": "ef4a147ceadb9df7f93b526b04c54357ca521073a4b68ec2257d80442761814d",
+ "dist/2023-03-28/rust-std-1.68.2-thumbv6m-none-eabi.tar.xz": "42e9f6c17faa25056b9b406687af8a979b4679e3e98e48e241565e6a2203c7c9",
+ "dist/2023-03-28/rust-std-1.68.2-thumbv7em-none-eabi.tar.gz": "48cf91b0d4de7d270e6d74a9531299314c227d92c6b259a02fff3ef1811d59cd",
+ "dist/2023-03-28/rust-std-1.68.2-thumbv7em-none-eabi.tar.xz": "e7437ea383aa8fd02ec1c280cd66ee27a3f42902741d8a1b70fb2a1737167a71",
+ "dist/2023-03-28/rust-std-1.68.2-thumbv7em-none-eabihf.tar.gz": "80fb0f3173b8c7abc4d47372784ff33f2a9f9806c5bf8c522edcc335f6b1dccb",
+ "dist/2023-03-28/rust-std-1.68.2-thumbv7em-none-eabihf.tar.xz": "5c9682e6dd3eddfbddf95bd1b3d9f1198699df6075ef72735a789ace7d271ca5",
+ "dist/2023-03-28/rust-std-1.68.2-thumbv7m-none-eabi.tar.gz": "5a07c263c50f99a3d394354b5752b7ae8990d5485353e4c2b5847961f7e2fade",
+ "dist/2023-03-28/rust-std-1.68.2-thumbv7m-none-eabi.tar.xz": "e73c7842c661bdcc61fd38b0c35f8bae31dc9a7bddea4f01a5ff3ce1e22ff58f",
+ "dist/2023-03-28/rust-std-1.68.2-thumbv7neon-linux-androideabi.tar.gz": "b28de19b62385fe083aa4f1a4d146e7400c14c1f62111a4296b76520488de948",
+ "dist/2023-03-28/rust-std-1.68.2-thumbv7neon-linux-androideabi.tar.xz": "017ad76fe9fdba994c1ec38785d1670343cdfea9483b9e90b3669944c4f4af3f",
+ "dist/2023-03-28/rust-std-1.68.2-thumbv7neon-unknown-linux-gnueabihf.tar.gz": "e39c3e612956620420d186156807ad69c7205004139f8f291eab9ba8fa33fa73",
+ "dist/2023-03-28/rust-std-1.68.2-thumbv7neon-unknown-linux-gnueabihf.tar.xz": "de7eea7ef4f288be803ec2d24e384be2bb80020bdcc4763405b947c9d7c0a2a0",
+ "dist/2023-03-28/rust-std-1.68.2-thumbv8m.base-none-eabi.tar.gz": "faedf1f0c86ef191f0659b0e6192f79a4f0a26c0b4104d3cc2d7c2792fa20866",
+ "dist/2023-03-28/rust-std-1.68.2-thumbv8m.base-none-eabi.tar.xz": "2b40dc3800897657946545646f933bd954d6d177c1170813e86bf5416c4fed84",
+ "dist/2023-03-28/rust-std-1.68.2-thumbv8m.main-none-eabi.tar.gz": "db95d00bea5c05ce7fbb80bcb344e245917b4189ce276a217c503edc28cdab17",
+ "dist/2023-03-28/rust-std-1.68.2-thumbv8m.main-none-eabi.tar.xz": "c7ce6676bb94a7dd4a50bba8635a34cebc6010bcd5f711c37fc42dff839e634f",
+ "dist/2023-03-28/rust-std-1.68.2-thumbv8m.main-none-eabihf.tar.gz": "7f308e66d78fa22d1563e093b77a358185d50938f467f9f849a884896516eb4f",
+ "dist/2023-03-28/rust-std-1.68.2-thumbv8m.main-none-eabihf.tar.xz": "03b47913fbe56d545e5566fa145a3bac6cdc4a1d8f17a25f9a52b2290b6745af",
+ "dist/2023-03-28/rust-std-1.68.2-wasm32-unknown-emscripten.tar.gz": "51aa09a286d840dbc74f785176ee4c58b9a92637995ed94627fcdbc91369b4f0",
+ "dist/2023-03-28/rust-std-1.68.2-wasm32-unknown-emscripten.tar.xz": "17ce08a1aea3c1143d701d77786b566dc85016b69d608938614629760983d3b8",
+ "dist/2023-03-28/rust-std-1.68.2-wasm32-unknown-unknown.tar.gz": "db3931196877c945dfba5890a6c7529f500cb0c2d202f3c69f950c7286b811ed",
+ "dist/2023-03-28/rust-std-1.68.2-wasm32-unknown-unknown.tar.xz": "aeffdd2f557e60ee7f82000d39dce8bc638c533ccb612ee60eea0dba04883f34",
+ "dist/2023-03-28/rust-std-1.68.2-wasm32-wasi.tar.gz": "c341b885d891b534638a4c68b3c93847512c23bd37f05d54708796d6446159ac",
+ "dist/2023-03-28/rust-std-1.68.2-wasm32-wasi.tar.xz": "fc5490235965127c4a1233522f2a96b58480848f9c28bc5f4989b269ed9524d5",
+ "dist/2023-03-28/rust-std-1.68.2-x86_64-apple-darwin.tar.gz": "5d6a7d62ae67c2f7aae6eabb782a3125cf9fed6bbc2993d59b3714f4f832e797",
+ "dist/2023-03-28/rust-std-1.68.2-x86_64-apple-darwin.tar.xz": "c3eb6fa219297b43a3436fbb9e1717e81c90f5a6f243b036c257520601787092",
+ "dist/2023-03-28/rust-std-1.68.2-x86_64-apple-ios.tar.gz": "8d7603bd3d678b4dca1ed6fda2ba1cf6312383b65fb1833a6b437b90eac03d4e",
+ "dist/2023-03-28/rust-std-1.68.2-x86_64-apple-ios.tar.xz": "e42fc4770f67ac4e7d9541170652eed13102888852d02f2a5f0d8b9d3b23720a",
+ "dist/2023-03-28/rust-std-1.68.2-x86_64-fortanix-unknown-sgx.tar.gz": "9d31af766ac437712d1e7fd5fe898a3b08157ae2379dbbeefcc254cddc7a056b",
+ "dist/2023-03-28/rust-std-1.68.2-x86_64-fortanix-unknown-sgx.tar.xz": "228e515261c206e622c7b685da134939f2c6ef59b1ddb57141461498ba3e19ec",
+ "dist/2023-03-28/rust-std-1.68.2-x86_64-linux-android.tar.gz": "d2ca68a7e98b90a6b4f1647a5ca3900a786c3ada0131c1877dc4c5f39da45455",
+ "dist/2023-03-28/rust-std-1.68.2-x86_64-linux-android.tar.xz": "875bae1e5bdd9901b68eeb14ce583cbb7d133435e5cd8bef60eb4521ef04b9d6",
+ "dist/2023-03-28/rust-std-1.68.2-x86_64-pc-solaris.tar.gz": "0017285c6aa16f13b71e80d7f36c1faeb7e2ba5cf902673697914a8fe76ca3d9",
+ "dist/2023-03-28/rust-std-1.68.2-x86_64-pc-solaris.tar.xz": "4eb37dc1f0b9d35a8b7660dc2d3d2c09b50ed23a4fd0cd29a7faa3f10b215b8c",
+ "dist/2023-03-28/rust-std-1.68.2-x86_64-pc-windows-gnu.tar.gz": "4598f3f44f84353dcf64aab9669b7c3982fccc1e7840f3ef1aa90cadc37864a4",
+ "dist/2023-03-28/rust-std-1.68.2-x86_64-pc-windows-gnu.tar.xz": "2a8a5117d358ebe7b7fe16e55fc85b4d4859758dec2b648503418006b94010dd",
+ "dist/2023-03-28/rust-std-1.68.2-x86_64-pc-windows-msvc.tar.gz": "a16e98dc5a12366b929d1329583065a374d5c0e3952193a0c506f43c1fd84930",
+ "dist/2023-03-28/rust-std-1.68.2-x86_64-pc-windows-msvc.tar.xz": "9f6c17fb1409925f27682d4ab2c783219f4912142865b97a0a15e1979c25320b",
+ "dist/2023-03-28/rust-std-1.68.2-x86_64-sun-solaris.tar.gz": "1ff12a55b723bbf2f867c6c9e94e6b1a17d31ffc21213aeec51d6413a72dbd16",
+ "dist/2023-03-28/rust-std-1.68.2-x86_64-sun-solaris.tar.xz": "65800cef0252de414cc665f77b90e17ba977cb9f4e29ccbfa727b38df34a797a",
+ "dist/2023-03-28/rust-std-1.68.2-x86_64-unknown-freebsd.tar.gz": "c94334345413a28669b271584b385ed0c0d6c410458103d7242353dd8fb9048d",
+ "dist/2023-03-28/rust-std-1.68.2-x86_64-unknown-freebsd.tar.xz": "edb8f095cef5b3e1ad04e63cd26e0d8af4732949fc130f08febec026096796bc",
+ "dist/2023-03-28/rust-std-1.68.2-x86_64-unknown-fuchsia.tar.gz": "bc15bb7f52589d81f577a5c1e2b17f8326ae229630f993796b41ca0d1ec2a2f8",
+ "dist/2023-03-28/rust-std-1.68.2-x86_64-unknown-fuchsia.tar.xz": "e8e27ccdbf4e3220b3e6730891b43273c5bb57ee1589d82101c2d197f5c157fa",
+ "dist/2023-03-28/rust-std-1.68.2-x86_64-unknown-illumos.tar.gz": "3c5f604498b267990c635562151e31ba770e36cfff1b9678d5a273c84f7bc433",
+ "dist/2023-03-28/rust-std-1.68.2-x86_64-unknown-illumos.tar.xz": "0340f081e7b7f4b272f505eaf0c535d620006b1023b4bf424a261ad7e2e3d2dc",
+ "dist/2023-03-28/rust-std-1.68.2-x86_64-unknown-linux-gnu.tar.gz": "92974d3b9d1343e597cf8f7b2dc516fcb8c97cea948cca0552223b928cd44ae7",
+ "dist/2023-03-28/rust-std-1.68.2-x86_64-unknown-linux-gnu.tar.xz": "c8a3eaf26b83f1926d86b4db99ca16cbbff8e746e4c63f25f4d75a02a34a3b16",
+ "dist/2023-03-28/rust-std-1.68.2-x86_64-unknown-linux-gnux32.tar.gz": "631e67da7ec1d25fc602759a7e348cba99101d780043dce01d187180650aa4fb",
+ "dist/2023-03-28/rust-std-1.68.2-x86_64-unknown-linux-gnux32.tar.xz": "f20b32d437a49d39abaee155b22373d0df912661fe6361551baac4d09b69f9ad",
+ "dist/2023-03-28/rust-std-1.68.2-x86_64-unknown-linux-musl.tar.gz": "1a6ab58aa4df56048926fa1accd77bba0d4747f5d2d71dfefaa2af9889483b17",
+ "dist/2023-03-28/rust-std-1.68.2-x86_64-unknown-linux-musl.tar.xz": "6c2a91e60f4be6538fdb0e4ff0344038f282c23808ca018f526ec586f4ba43ab",
+ "dist/2023-03-28/rust-std-1.68.2-x86_64-unknown-netbsd.tar.gz": "bcafa9884314daadb2a073599a1417ee79ca96a9fcdef0d2ea23afe3a0396bb6",
+ "dist/2023-03-28/rust-std-1.68.2-x86_64-unknown-netbsd.tar.xz": "31bdab595565233e5d1b9b83c073fb92b46780213c58f14938a4006edd001d49",
+ "dist/2023-03-28/rust-std-1.68.2-x86_64-unknown-none.tar.gz": "365c2cfbfc4624cb5ce3f426ac679cc8dea078ba69bf3a3112ede357034adb69",
+ "dist/2023-03-28/rust-std-1.68.2-x86_64-unknown-none.tar.xz": "c2d94086e2965a13db8d26b45eda286ef8ba91bac217acff95ca84462ba0b47a",
+ "dist/2023-03-28/rust-std-1.68.2-x86_64-unknown-redox.tar.gz": "b63b4f392c473a7681826fdc470e9863edcebe10a38aa5f49aec74affc336928",
+ "dist/2023-03-28/rust-std-1.68.2-x86_64-unknown-redox.tar.xz": "4387108878b3bfaea8849fcbb9b9444013434b1e05a9940afe5454717ae35eb2",
+ "dist/2023-03-28/rust-std-1.68.2-x86_64-unknown-uefi.tar.gz": "741e591ef0979caeae96c4d2c31994ff2d74b136a720302d45fae56045ac6c02",
+ "dist/2023-03-28/rust-std-1.68.2-x86_64-unknown-uefi.tar.xz": "fb03448de28a52b49aa8dfca8b465695035fed817c7d0e442967b152c05b6286",
+ "dist/2023-03-28/rustc-1.68.2-aarch64-apple-darwin.tar.gz": "9cbec5ea622b445e620743cabc723534fa6e4871a53cb4743e6b28ce8e3d5112",
+ "dist/2023-03-28/rustc-1.68.2-aarch64-apple-darwin.tar.xz": "ddea7da2f70db2ffaeed476494fca0d069541bae0576d83557685c4178c17dfa",
+ "dist/2023-03-28/rustc-1.68.2-aarch64-pc-windows-msvc.tar.gz": "96096f2086ea504c77d3d75e90fd2783a2ade7451dc1562386fb21d056eb6e3b",
+ "dist/2023-03-28/rustc-1.68.2-aarch64-pc-windows-msvc.tar.xz": "37a2d5d5b9e5650060234ceb0f6ac61ec0f24e85dbedb224e4db5bc3ac1f21e6",
+ "dist/2023-03-28/rustc-1.68.2-aarch64-unknown-linux-gnu.tar.gz": "9fd96b0ec4209f8ddd82b6055b49f13993d83488f6ed82e33c7ad577786a6f42",
+ "dist/2023-03-28/rustc-1.68.2-aarch64-unknown-linux-gnu.tar.xz": "d78579af4d4b98b3bf49b8a0b7848960e68254150ac517faeb9caf7b9f44ede2",
+ "dist/2023-03-28/rustc-1.68.2-aarch64-unknown-linux-musl.tar.gz": "e43c95a457cbda8d9e4b8a2ba65aaf7b2c05664b8ed501ee1c70706b8329a817",
+ "dist/2023-03-28/rustc-1.68.2-aarch64-unknown-linux-musl.tar.xz": "b88070e3cbe399122398a74db62fa5d03edb6a5a583ee79a174b2caa1eb27fc5",
+ "dist/2023-03-28/rustc-1.68.2-arm-unknown-linux-gnueabi.tar.gz": "ef3624048ef66b43661ce3bc60cdf8afe27d81b959f4fa43ad1c2e2d25ede652",
+ "dist/2023-03-28/rustc-1.68.2-arm-unknown-linux-gnueabi.tar.xz": "151efdd16a6c1f871a4ddd66e22f0f7ec39cae7929da348ce14c6435dc38d89c",
+ "dist/2023-03-28/rustc-1.68.2-arm-unknown-linux-gnueabihf.tar.gz": "fc9adb8289645c1e3f3e3d1f9a3bde875396b5863b349207cb2efdcc2132da56",
+ "dist/2023-03-28/rustc-1.68.2-arm-unknown-linux-gnueabihf.tar.xz": "8918007df327cf6629e00f5390b34204dc408624426e4a1cb823ab3c764c4c19",
+ "dist/2023-03-28/rustc-1.68.2-armv7-unknown-linux-gnueabihf.tar.gz": "c98308c066f1edb14967e1fb9db45620e0d03298be10fc643900a30b7b7a7c15",
+ "dist/2023-03-28/rustc-1.68.2-armv7-unknown-linux-gnueabihf.tar.xz": "f4d11a7aaa83aeb52c1fe95393939c049385de5956282f1732031961e2806927",
+ "dist/2023-03-28/rustc-1.68.2-i686-pc-windows-gnu.tar.gz": "c8da60ea1853846a6c727f00b1db68c783fbead23fe90a1d2080476baec05b98",
+ "dist/2023-03-28/rustc-1.68.2-i686-pc-windows-gnu.tar.xz": "a31c786a421f21dfd26e6b105135c39d3555981fe25c2ef5c14a3242d2a93283",
+ "dist/2023-03-28/rustc-1.68.2-i686-pc-windows-msvc.tar.gz": "29beba763a02cdcc205456f2d5ed205e0b2149dc47edf6fefae74c6006fa3838",
+ "dist/2023-03-28/rustc-1.68.2-i686-pc-windows-msvc.tar.xz": "e67516fbb3b1d3453f7806986770e26e5aab204fa0d97f3a785de7e62b364ac6",
+ "dist/2023-03-28/rustc-1.68.2-i686-unknown-linux-gnu.tar.gz": "0eb86af5a05080984c68ed6e445dcbde98c4f391e6a7ada3ebed53109515175d",
+ "dist/2023-03-28/rustc-1.68.2-i686-unknown-linux-gnu.tar.xz": "dc533e7d0f0349d92a98973e20b99d69b09a25b8675f28a38fa26b0160615fd4",
+ "dist/2023-03-28/rustc-1.68.2-mips-unknown-linux-gnu.tar.gz": "2fe7deb053138e8daa0a4d5fbede087451662f043421682de7e87cce03fdf86a",
+ "dist/2023-03-28/rustc-1.68.2-mips-unknown-linux-gnu.tar.xz": "68c6aac6e0e95588b65d6f937032b57ad2a09b2897990a3a930729763f728e12",
+ "dist/2023-03-28/rustc-1.68.2-mips64-unknown-linux-gnuabi64.tar.gz": "89378190223a4d1e2b7c9ec309cac8748b9efb0945151b7e5f4fd8c107d6dc0d",
+ "dist/2023-03-28/rustc-1.68.2-mips64-unknown-linux-gnuabi64.tar.xz": "894725021b34afdde5afb89686d794c029317df9195f49e0d9a065e1cb4cc9b8",
+ "dist/2023-03-28/rustc-1.68.2-mips64el-unknown-linux-gnuabi64.tar.gz": "b8a23eddb567402157cf07c1fc0f039e25af77f2276690bce9e4f4e1c811014a",
+ "dist/2023-03-28/rustc-1.68.2-mips64el-unknown-linux-gnuabi64.tar.xz": "3f45f5b63004b14a193ed57143299c81f62246fc40e4a0df2119494d9ee4fe66",
+ "dist/2023-03-28/rustc-1.68.2-mipsel-unknown-linux-gnu.tar.gz": "673a69690f0008b7dcbac7c851c81b3c91c6265180604adbfb867b1c69f96e0b",
+ "dist/2023-03-28/rustc-1.68.2-mipsel-unknown-linux-gnu.tar.xz": "de72245d5e6db0e4327ce105a7ce3d5597a3792e71b95578dd7ec62af56946fb",
+ "dist/2023-03-28/rustc-1.68.2-powerpc-unknown-linux-gnu.tar.gz": "98e0f7633ca880d9b39e270cbd3ac89818ca69925ec40823d00a7c638c35a629",
+ "dist/2023-03-28/rustc-1.68.2-powerpc-unknown-linux-gnu.tar.xz": "92b08b1ad69786f3bcc6fd7bb71411ad162dca478f9636027bf809b9de6eea72",
+ "dist/2023-03-28/rustc-1.68.2-powerpc64-unknown-linux-gnu.tar.gz": "054e2f567b5f7791425bbe81eb6011b6217e11d7c60f8706607469a099ae17f7",
+ "dist/2023-03-28/rustc-1.68.2-powerpc64-unknown-linux-gnu.tar.xz": "a23e71c7da172ece7ef760db043b010c84dd8a491cd9c00303e2c01ad521dec2",
+ "dist/2023-03-28/rustc-1.68.2-powerpc64le-unknown-linux-gnu.tar.gz": "dfc8c2d375dee373b02de888641bf071dc837aa3d7b53752785a65e1c534574c",
+ "dist/2023-03-28/rustc-1.68.2-powerpc64le-unknown-linux-gnu.tar.xz": "4d493bec7500dd3159c05ee8f2fef71241de575e1cb7a89bf128f01dc3e537cb",
+ "dist/2023-03-28/rustc-1.68.2-riscv64gc-unknown-linux-gnu.tar.gz": "b815c4f031db892cb2ac28c293056ce13a121707c1da71a8577e8c80875270bc",
+ "dist/2023-03-28/rustc-1.68.2-riscv64gc-unknown-linux-gnu.tar.xz": "de7ef61f6fa5f7ddddbddc0934beec58a3ce49cda96679dbf06895128f1fc228",
+ "dist/2023-03-28/rustc-1.68.2-s390x-unknown-linux-gnu.tar.gz": "28e665d1a5ebd73fc9a3d8677b8ad10f9998c137f1135837d42a4ffd121365cf",
+ "dist/2023-03-28/rustc-1.68.2-s390x-unknown-linux-gnu.tar.xz": "fbfb02fff83f4a9d7298c511a3ad4b9e73c4d9d0be558edbf7226af0f586517a",
+ "dist/2023-03-28/rustc-1.68.2-x86_64-apple-darwin.tar.gz": "e0ba4545a390303a1447417ec19be2ad26ae33ee1b9a7b2e3e970e8a87e30ba7",
+ "dist/2023-03-28/rustc-1.68.2-x86_64-apple-darwin.tar.xz": "37831c92a751f63de2dfcc9f9b57f9d7ce5d61748d0849b209a156b24f994f63",
+ "dist/2023-03-28/rustc-1.68.2-x86_64-pc-windows-gnu.tar.gz": "1e86ffe40a94f717d1114637eda2a44e0543cdffffb2ca8274a3f54686e4bb97",
+ "dist/2023-03-28/rustc-1.68.2-x86_64-pc-windows-gnu.tar.xz": "e1d4a0a444076d6eccadd6e08f4d204e8b45c3b954203a4bb0663affd4e9c5e0",
+ "dist/2023-03-28/rustc-1.68.2-x86_64-pc-windows-msvc.tar.gz": "f64bdaab8920a26b357e8849427d4adaf6f29f98deff45c935c7b66e4a246f8f",
+ "dist/2023-03-28/rustc-1.68.2-x86_64-pc-windows-msvc.tar.xz": "69b277735603d0c8f1f476e53b785a6072340ff10bfde03f4df55d89c12d9ce1",
+ "dist/2023-03-28/rustc-1.68.2-x86_64-unknown-freebsd.tar.gz": "a3bce6d0bdde3e59a982f1a1c7c68e99b3fcf199e1d45233cdcd250a9da9c0c3",
+ "dist/2023-03-28/rustc-1.68.2-x86_64-unknown-freebsd.tar.xz": "9ec0e03f6e8f7b4b52fe2e65cb8bb45edea4ab3677e8df9fe530a1d9a645e824",
+ "dist/2023-03-28/rustc-1.68.2-x86_64-unknown-illumos.tar.gz": "6adef91820350b81ab35e8e18005392f9a64213f0489bf35b70f6775376f2bf3",
+ "dist/2023-03-28/rustc-1.68.2-x86_64-unknown-illumos.tar.xz": "f47c91dd6abbdeb8a5afe9a339ad172ba5be011cf7be4ff124e4b909a25e77d3",
+ "dist/2023-03-28/rustc-1.68.2-x86_64-unknown-linux-gnu.tar.gz": "532b1b20c83a8a849249b792fb7f38210559d6803cc465699641f7c21fcca5ae",
+ "dist/2023-03-28/rustc-1.68.2-x86_64-unknown-linux-gnu.tar.xz": "d33d493381dd17a4b491d0e978cdb6700badb5905e831dd5f7fe75ffbf8e0584",
+ "dist/2023-03-28/rustc-1.68.2-x86_64-unknown-linux-musl.tar.gz": "ad5d833fd32803cfdafaf4e42ba96d08da94420d6ac05243348a9f6c9256b60c",
+ "dist/2023-03-28/rustc-1.68.2-x86_64-unknown-linux-musl.tar.xz": "9308f27bda32a02b1debe5fcc5ee633a234652037687c46f4e57d9dc29f90b3e",
+ "dist/2023-03-28/rustc-1.68.2-x86_64-unknown-netbsd.tar.gz": "7f2981c2f84093f740631022c10494dcf293eb15243d254c25b8a1d9f4348e1c",
+ "dist/2023-03-28/rustc-1.68.2-x86_64-unknown-netbsd.tar.xz": "19f87fefa64b6d26a11f7fdae020228e91bec71527abf3350663fe165a135aea"
}
}
diff --git a/src/tools/build_helper/src/git.rs b/src/tools/build_helper/src/git.rs
index dc62051cb..168633c8f 100644
--- a/src/tools/build_helper/src/git.rs
+++ b/src/tools/build_helper/src/git.rs
@@ -1,5 +1,24 @@
+use std::process::Stdio;
use std::{path::Path, process::Command};
+/// Runs a command and returns the output
+fn output_result(cmd: &mut Command) -> Result<String, String> {
+ let output = match cmd.stderr(Stdio::inherit()).output() {
+ Ok(status) => status,
+ Err(e) => return Err(format!("failed to run command: {:?}: {}", cmd, e)),
+ };
+ if !output.status.success() {
+ return Err(format!(
+ "command did not execute successfully: {:?}\n\
+ expected success, got: {}\n{}",
+ cmd,
+ output.status,
+ String::from_utf8(output.stderr).map_err(|err| format!("{err:?}"))?
+ ));
+ }
+ Ok(String::from_utf8(output.stdout).map_err(|err| format!("{err:?}"))?)
+}
+
/// Finds the remote for rust-lang/rust.
/// For example for these remotes it will return `upstream`.
/// ```text
@@ -14,13 +33,7 @@ pub fn get_rust_lang_rust_remote(git_dir: Option<&Path>) -> Result<String, Strin
git.current_dir(git_dir);
}
git.args(["config", "--local", "--get-regex", "remote\\..*\\.url"]);
-
- let output = git.output().map_err(|err| format!("{err:?}"))?;
- if !output.status.success() {
- return Err("failed to execute git config command".to_owned());
- }
-
- let stdout = String::from_utf8(output.stdout).map_err(|err| format!("{err:?}"))?;
+ let stdout = output_result(&mut git)?;
let rust_lang_remote = stdout
.lines()
@@ -73,3 +86,48 @@ pub fn updated_master_branch(git_dir: Option<&Path>) -> Result<String, String> {
// We could implement smarter logic here in the future.
Ok("origin/master".into())
}
+
+/// Returns the files that have been modified in the current branch compared to the master branch.
+/// The `extensions` parameter can be used to filter the files by their extension.
+/// If `extensions` is empty, all files will be returned.
+pub fn get_git_modified_files(
+ git_dir: Option<&Path>,
+ extensions: &Vec<&str>,
+) -> Result<Option<Vec<String>>, String> {
+ let Ok(updated_master) = updated_master_branch(git_dir) else { return Ok(None); };
+
+ let git = || {
+ let mut git = Command::new("git");
+ if let Some(git_dir) = git_dir {
+ git.current_dir(git_dir);
+ }
+ git
+ };
+
+ let merge_base = output_result(git().arg("merge-base").arg(&updated_master).arg("HEAD"))?;
+ let files = output_result(git().arg("diff-index").arg("--name-only").arg(merge_base.trim()))?
+ .lines()
+ .map(|s| s.trim().to_owned())
+ .filter(|f| {
+ Path::new(f).extension().map_or(false, |ext| {
+ extensions.is_empty() || extensions.contains(&ext.to_str().unwrap())
+ })
+ })
+ .collect();
+ Ok(Some(files))
+}
+
+/// Returns the files that haven't been added to git yet.
+pub fn get_git_untracked_files(git_dir: Option<&Path>) -> Result<Option<Vec<String>>, String> {
+ let Ok(_updated_master) = updated_master_branch(git_dir) else { return Ok(None); };
+ let mut git = Command::new("git");
+ if let Some(git_dir) = git_dir {
+ git.current_dir(git_dir);
+ }
+
+ let files = output_result(git.arg("ls-files").arg("--others").arg("--exclude-standard"))?
+ .lines()
+ .map(|s| s.trim().to_owned())
+ .collect();
+ Ok(Some(files))
+}
diff --git a/src/tools/bump-stage0/src/main.rs b/src/tools/bump-stage0/src/main.rs
index 530a80b1e..f530a4d73 100644
--- a/src/tools/bump-stage0/src/main.rs
+++ b/src/tools/bump-stage0/src/main.rs
@@ -6,7 +6,7 @@ use std::convert::TryInto;
const PATH: &str = "src/stage0.json";
const COMPILER_COMPONENTS: &[&str] = &["rustc", "rust-std", "cargo"];
-const RUSTFMT_COMPONENTS: &[&str] = &["rustfmt-preview"];
+const RUSTFMT_COMPONENTS: &[&str] = &["rustfmt-preview", "rustc"];
struct Tool {
config: Config,
diff --git a/src/tools/clippy/.github/workflows/clippy_bors.yml b/src/tools/clippy/.github/workflows/clippy_bors.yml
index 1bc457a94..24e677ce8 100644
--- a/src/tools/clippy/.github/workflows/clippy_bors.yml
+++ b/src/tools/clippy/.github/workflows/clippy_bors.yml
@@ -157,6 +157,11 @@ jobs:
- name: Test metadata collection
run: cargo collect-metadata
+ - name: Test lint_configuration.md is up-to-date
+ run: |
+ echo "run \`cargo collect-metadata\` if this fails"
+ git update-index --refresh
+
integration_build:
needs: changelog
runs-on: ubuntu-latest
diff --git a/src/tools/clippy/CHANGELOG.md b/src/tools/clippy/CHANGELOG.md
index 8e31e8f0d..765826ed8 100644
--- a/src/tools/clippy/CHANGELOG.md
+++ b/src/tools/clippy/CHANGELOG.md
@@ -6,11 +6,204 @@ document.
## Unreleased / Beta / In Rust Nightly
-[4f142aa1...master](https://github.com/rust-lang/rust-clippy/compare/4f142aa1...master)
+[d822110d...master](https://github.com/rust-lang/rust-clippy/compare/d822110d...master)
+
+## Rust 1.67
+
+Current stable, released 2023-01-26
+
+[4f142aa1...d822110d](https://github.com/rust-lang/rust-clippy/compare/4f142aa1...d822110d)
+
+### New Lints
+
+* [`seek_from_current`]
+ [#9681](https://github.com/rust-lang/rust-clippy/pull/9681)
+* [`from_raw_with_void_ptr`]
+ [#9690](https://github.com/rust-lang/rust-clippy/pull/9690)
+* [`misnamed_getters`]
+ [#9770](https://github.com/rust-lang/rust-clippy/pull/9770)
+* [`seek_to_start_instead_of_rewind`]
+ [#9667](https://github.com/rust-lang/rust-clippy/pull/9667)
+* [`suspicious_xor_used_as_pow`]
+ [#9506](https://github.com/rust-lang/rust-clippy/pull/9506)
+* [`unnecessary_safety_doc`]
+ [#9822](https://github.com/rust-lang/rust-clippy/pull/9822)
+* [`unchecked_duration_subtraction`]
+ [#9570](https://github.com/rust-lang/rust-clippy/pull/9570)
+* [`manual_is_ascii_check`]
+ [#9765](https://github.com/rust-lang/rust-clippy/pull/9765)
+* [`unnecessary_safety_comment`]
+ [#9851](https://github.com/rust-lang/rust-clippy/pull/9851)
+* [`let_underscore_future`]
+ [#9760](https://github.com/rust-lang/rust-clippy/pull/9760)
+* [`manual_let_else`]
+ [#8437](https://github.com/rust-lang/rust-clippy/pull/8437)
+
+### Moves and Deprecations
+
+* Moved [`uninlined_format_args`] to `style` (Now warn-by-default)
+ [#9865](https://github.com/rust-lang/rust-clippy/pull/9865)
+* Moved [`needless_collect`] to `nursery` (Now allow-by-default)
+ [#9705](https://github.com/rust-lang/rust-clippy/pull/9705)
+* Moved [`or_fun_call`] to `nursery` (Now allow-by-default)
+ [#9829](https://github.com/rust-lang/rust-clippy/pull/9829)
+* Uplifted [`let_underscore_lock`] into rustc
+ [#9697](https://github.com/rust-lang/rust-clippy/pull/9697)
+* Uplifted [`let_underscore_drop`] into rustc
+ [#9697](https://github.com/rust-lang/rust-clippy/pull/9697)
+* Moved [`bool_to_int_with_if`] to `pedantic` (Now allow-by-default)
+ [#9830](https://github.com/rust-lang/rust-clippy/pull/9830)
+* Move `index_refutable_slice` to `pedantic` (Now warn-by-default)
+ [#9975](https://github.com/rust-lang/rust-clippy/pull/9975)
+* Moved [`manual_clamp`] to `nursery` (Now allow-by-default)
+ [#10101](https://github.com/rust-lang/rust-clippy/pull/10101)
+
+### Enhancements
+
+* The scope of `#![clippy::msrv]` is now tracked correctly
+ [#9924](https://github.com/rust-lang/rust-clippy/pull/9924)
+* `#[clippy::msrv]` can now be used as an outer attribute
+ [#9860](https://github.com/rust-lang/rust-clippy/pull/9860)
+* Clippy will now avoid Cargo's cache, if `Cargo.toml` or `clippy.toml` have changed
+ [#9707](https://github.com/rust-lang/rust-clippy/pull/9707)
+* [`uninlined_format_args`]: Added a new config `allow-mixed-uninlined-format-args` to allow the
+ lint, if only some arguments can be inlined
+ [#9865](https://github.com/rust-lang/rust-clippy/pull/9865)
+* [`needless_lifetimes`]: Now provides suggests for individual lifetimes
+ [#9743](https://github.com/rust-lang/rust-clippy/pull/9743)
+* [`needless_collect`]: Now detects needless `is_empty` and `contains` calls
+ [#8744](https://github.com/rust-lang/rust-clippy/pull/8744)
+* [`blanket_clippy_restriction_lints`]: Now lints, if `clippy::restriction` is enabled via the
+ command line arguments
+ [#9755](https://github.com/rust-lang/rust-clippy/pull/9755)
+* [`mutable_key_type`]: Now has the `ignore-interior-mutability` configuration, to add types which
+ should be ignored by the lint
+ [#9692](https://github.com/rust-lang/rust-clippy/pull/9692)
+* [`uninlined_format_args`]: Now works for multiline `format!` expressions
+ [#9945](https://github.com/rust-lang/rust-clippy/pull/9945)
+* [`cognitive_complexity`]: Now works for async functions
+ [#9828](https://github.com/rust-lang/rust-clippy/pull/9828)
+ [#9836](https://github.com/rust-lang/rust-clippy/pull/9836)
+* [`vec_box`]: Now avoids an off-by-one error when using the `vec-box-size-threshold` configuration
+ [#9848](https://github.com/rust-lang/rust-clippy/pull/9848)
+* [`never_loop`]: Now correctly handles breaks in nested labeled blocks
+ [#9858](https://github.com/rust-lang/rust-clippy/pull/9858)
+ [#9837](https://github.com/rust-lang/rust-clippy/pull/9837)
+* [`disallowed_methods`], [`disallowed_types`], [`disallowed_macros`]: Now correctly resolve
+ paths, if a crate is used multiple times with different versions
+ [#9800](https://github.com/rust-lang/rust-clippy/pull/9800)
+* [`disallowed_methods`]: Can now be used for local methods
+ [#9800](https://github.com/rust-lang/rust-clippy/pull/9800)
+* [`print_stdout`], [`print_stderr`]: Can now be enabled in test with the `allow-print-in-tests`
+ config value
+ [#9797](https://github.com/rust-lang/rust-clippy/pull/9797)
+* [`from_raw_with_void_ptr`]: Now works for `Rc`, `Arc`, `alloc::rc::Weak` and
+ `alloc::sync::Weak` types.
+ [#9700](https://github.com/rust-lang/rust-clippy/pull/9700)
+* [`needless_borrowed_reference`]: Now works for struct and tuple patterns with wildcards
+ [#9855](https://github.com/rust-lang/rust-clippy/pull/9855)
+* [`or_fun_call`]: Now supports `map_or` methods
+ [#9689](https://github.com/rust-lang/rust-clippy/pull/9689)
+* [`unwrap_used`], [`expect_used`]: No longer lints in test code
+ [#9686](https://github.com/rust-lang/rust-clippy/pull/9686)
+* [`fn_params_excessive_bools`]: Is now emitted with the lint level at the linted function
+ [#9698](https://github.com/rust-lang/rust-clippy/pull/9698)
+
+### False Positive Fixes
+
+* [`new_ret_no_self`]: No longer lints when `impl Trait<Self>` is returned
+ [#9733](https://github.com/rust-lang/rust-clippy/pull/9733)
+* [`unnecessary_lazy_evaluations`]: No longer lints, if the type has a significant drop
+ [#9750](https://github.com/rust-lang/rust-clippy/pull/9750)
+* [`option_if_let_else`]: No longer lints, if any arm has guard
+ [#9747](https://github.com/rust-lang/rust-clippy/pull/9747)
+* [`explicit_auto_deref`]: No longer lints, if the target type is a projection with generic
+ arguments
+ [#9813](https://github.com/rust-lang/rust-clippy/pull/9813)
+* [`unnecessary_to_owned`]: No longer lints, if the suggestion effects types
+ [#9796](https://github.com/rust-lang/rust-clippy/pull/9796)
+* [`needless_borrow`]: No longer lints, if the suggestion is affected by `Deref`
+ [#9674](https://github.com/rust-lang/rust-clippy/pull/9674)
+* [`unused_unit`]: No longer lints, if lifetimes are bound to the return type
+ [#9849](https://github.com/rust-lang/rust-clippy/pull/9849)
+* [`mut_mut`]: No longer lints cases with unsized mutable references
+ [#9835](https://github.com/rust-lang/rust-clippy/pull/9835)
+* [`bool_to_int_with_if`]: No longer lints in const context
+ [#9738](https://github.com/rust-lang/rust-clippy/pull/9738)
+* [`use_self`]: No longer lints in macros
+ [#9704](https://github.com/rust-lang/rust-clippy/pull/9704)
+* [`unnecessary_operation`]: No longer lints, if multiple macros are involved
+ [#9981](https://github.com/rust-lang/rust-clippy/pull/9981)
+* [`allow_attributes_without_reason`]: No longer lints inside external macros
+ [#9630](https://github.com/rust-lang/rust-clippy/pull/9630)
+* [`question_mark`]: No longer lints for `if let Err()` with an `else` branch
+ [#9722](https://github.com/rust-lang/rust-clippy/pull/9722)
+* [`unnecessary_cast`]: No longer lints if the identifier and cast originate from different macros
+ [#9980](https://github.com/rust-lang/rust-clippy/pull/9980)
+* [`arithmetic_side_effects`]: Now detects operations with associated constants
+ [#9592](https://github.com/rust-lang/rust-clippy/pull/9592)
+* [`explicit_auto_deref`]: No longer lints, if the initial value is not a reference or reference
+ receiver
+ [#9997](https://github.com/rust-lang/rust-clippy/pull/9997)
+* [`module_name_repetitions`], [`single_component_path_imports`]: Now handle `#[allow]`
+ attributes correctly
+ [#9879](https://github.com/rust-lang/rust-clippy/pull/9879)
+* [`bool_to_int_with_if`]: No longer lints `if let` statements
+ [#9714](https://github.com/rust-lang/rust-clippy/pull/9714)
+* [`needless_borrow`]: No longer lints, `if`-`else`-statements that require the borrow
+ [#9791](https://github.com/rust-lang/rust-clippy/pull/9791)
+* [`needless_borrow`]: No longer lints borrows, if moves were illegal
+ [#9711](https://github.com/rust-lang/rust-clippy/pull/9711)
+* [`manual_swap`]: No longer lints in const context
+ [#9871](https://github.com/rust-lang/rust-clippy/pull/9871)
+
+### Suggestion Fixes/Improvements
+
+* [`missing_safety_doc`], [`missing_errors_doc`], [`missing_panics_doc`]: No longer show the
+ entire item in the lint emission.
+ [#9772](https://github.com/rust-lang/rust-clippy/pull/9772)
+* [`needless_lifetimes`]: Only suggests `'_` when it's applicable
+ [#9743](https://github.com/rust-lang/rust-clippy/pull/9743)
+* [`use_self`]: Now suggests full paths correctly
+ [#9726](https://github.com/rust-lang/rust-clippy/pull/9726)
+* [`redundant_closure_call`]: Now correctly deals with macros during suggestion creation
+ [#9987](https://github.com/rust-lang/rust-clippy/pull/9987)
+* [`unnecessary_cast`]: Suggestions now correctly deal with references
+ [#9996](https://github.com/rust-lang/rust-clippy/pull/9996)
+* [`unnecessary_join`]: Suggestions now correctly use [turbofish] operators
+ [#9779](https://github.com/rust-lang/rust-clippy/pull/9779)
+* [`equatable_if_let`]: Can now suggest `matches!` replacements
+ [#9368](https://github.com/rust-lang/rust-clippy/pull/9368)
+* [`string_extend_chars`]: Suggestions now correctly work for `str` slices
+ [#9741](https://github.com/rust-lang/rust-clippy/pull/9741)
+* [`redundant_closure_for_method_calls`]: Suggestions now include angle brackets and generic
+ arguments if needed
+ [#9745](https://github.com/rust-lang/rust-clippy/pull/9745)
+* [`manual_let_else`]: Suggestions no longer expand macro calls
+ [#9943](https://github.com/rust-lang/rust-clippy/pull/9943)
+* [`infallible_destructuring_match`]: Suggestions now preserve references
+ [#9850](https://github.com/rust-lang/rust-clippy/pull/9850)
+* [`result_large_err`]: The error now shows the largest enum variant
+ [#9662](https://github.com/rust-lang/rust-clippy/pull/9662)
+* [`needless_return`]: Suggestions are now formatted better
+ [#9967](https://github.com/rust-lang/rust-clippy/pull/9967)
+* [`unused_rounding`]: The suggestion now preserves the original float literal notation
+ [#9870](https://github.com/rust-lang/rust-clippy/pull/9870)
+
+[turbofish]: https://turbo.fish/::%3CClippy%3E
+
+### ICE Fixes
+
+* [`result_large_err`]: Fixed ICE for empty enums
+ [#10007](https://github.com/rust-lang/rust-clippy/pull/10007)
+* [`redundant_allocation`]: Fixed ICE for types with bounded variables
+ [#9773](https://github.com/rust-lang/rust-clippy/pull/9773)
+* [`unused_rounding`]: Fixed ICE, if `_` was used as a separator
+ [#10001](https://github.com/rust-lang/rust-clippy/pull/10001)
## Rust 1.66
-Current stable, released 2022-12-15
+Released 2022-12-15
[b52fb523...4f142aa1](https://github.com/rust-lang/rust-clippy/compare/b52fb523...4f142aa1)
@@ -166,6 +359,7 @@ Current stable, released 2022-12-15
* [`unnecessary_to_owned`]: Avoid ICEs in favor of false negatives if information is missing
[#9505](https://github.com/rust-lang/rust-clippy/pull/9505)
+ [#10027](https://github.com/rust-lang/rust-clippy/pull/10027)
* [`manual_range_contains`]: No longer ICEs on values behind references
[#9627](https://github.com/rust-lang/rust-clippy/pull/9627)
* [`needless_pass_by_value`]: No longer ICEs on unsized `dyn Fn` arguments
@@ -4189,6 +4383,7 @@ Released 2018-09-13
[`extend_from_slice`]: https://rust-lang.github.io/rust-clippy/master/index.html#extend_from_slice
[`extend_with_drain`]: https://rust-lang.github.io/rust-clippy/master/index.html#extend_with_drain
[`extra_unused_lifetimes`]: https://rust-lang.github.io/rust-clippy/master/index.html#extra_unused_lifetimes
+[`extra_unused_type_parameters`]: https://rust-lang.github.io/rust-clippy/master/index.html#extra_unused_type_parameters
[`fallible_impl_from`]: https://rust-lang.github.io/rust-clippy/master/index.html#fallible_impl_from
[`field_reassign_with_default`]: https://rust-lang.github.io/rust-clippy/master/index.html#field_reassign_with_default
[`filetype_is_file`]: https://rust-lang.github.io/rust-clippy/master/index.html#filetype_is_file
@@ -4235,6 +4430,7 @@ Released 2018-09-13
[`if_same_then_else`]: https://rust-lang.github.io/rust-clippy/master/index.html#if_same_then_else
[`if_then_some_else_none`]: https://rust-lang.github.io/rust-clippy/master/index.html#if_then_some_else_none
[`ifs_same_cond`]: https://rust-lang.github.io/rust-clippy/master/index.html#ifs_same_cond
+[`impl_trait_in_params`]: https://rust-lang.github.io/rust-clippy/master/index.html#impl_trait_in_params
[`implicit_clone`]: https://rust-lang.github.io/rust-clippy/master/index.html#implicit_clone
[`implicit_hasher`]: https://rust-lang.github.io/rust-clippy/master/index.html#implicit_hasher
[`implicit_return`]: https://rust-lang.github.io/rust-clippy/master/index.html#implicit_return
@@ -4299,6 +4495,7 @@ Released 2018-09-13
[`let_underscore_future`]: https://rust-lang.github.io/rust-clippy/master/index.html#let_underscore_future
[`let_underscore_lock`]: https://rust-lang.github.io/rust-clippy/master/index.html#let_underscore_lock
[`let_underscore_must_use`]: https://rust-lang.github.io/rust-clippy/master/index.html#let_underscore_must_use
+[`let_underscore_untyped`]: https://rust-lang.github.io/rust-clippy/master/index.html#let_underscore_untyped
[`let_unit_value`]: https://rust-lang.github.io/rust-clippy/master/index.html#let_unit_value
[`linkedlist`]: https://rust-lang.github.io/rust-clippy/master/index.html#linkedlist
[`logic_bug`]: https://rust-lang.github.io/rust-clippy/master/index.html#logic_bug
@@ -4383,6 +4580,7 @@ Released 2018-09-13
[`multi_assignments`]: https://rust-lang.github.io/rust-clippy/master/index.html#multi_assignments
[`multiple_crate_versions`]: https://rust-lang.github.io/rust-clippy/master/index.html#multiple_crate_versions
[`multiple_inherent_impl`]: https://rust-lang.github.io/rust-clippy/master/index.html#multiple_inherent_impl
+[`multiple_unsafe_ops_per_block`]: https://rust-lang.github.io/rust-clippy/master/index.html#multiple_unsafe_ops_per_block
[`must_use_candidate`]: https://rust-lang.github.io/rust-clippy/master/index.html#must_use_candidate
[`must_use_unit`]: https://rust-lang.github.io/rust-clippy/master/index.html#must_use_unit
[`mut_from_ref`]: https://rust-lang.github.io/rust-clippy/master/index.html#mut_from_ref
@@ -4424,6 +4622,7 @@ Released 2018-09-13
[`no_effect`]: https://rust-lang.github.io/rust-clippy/master/index.html#no_effect
[`no_effect_replace`]: https://rust-lang.github.io/rust-clippy/master/index.html#no_effect_replace
[`no_effect_underscore_binding`]: https://rust-lang.github.io/rust-clippy/master/index.html#no_effect_underscore_binding
+[`no_mangle_with_rust_abi`]: https://rust-lang.github.io/rust-clippy/master/index.html#no_mangle_with_rust_abi
[`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
@@ -4479,6 +4678,7 @@ Released 2018-09-13
[`pub_enum_variant_names`]: https://rust-lang.github.io/rust-clippy/master/index.html#pub_enum_variant_names
[`pub_use`]: https://rust-lang.github.io/rust-clippy/master/index.html#pub_use
[`question_mark`]: https://rust-lang.github.io/rust-clippy/master/index.html#question_mark
+[`question_mark_used`]: https://rust-lang.github.io/rust-clippy/master/index.html#question_mark_used
[`range_minus_one`]: https://rust-lang.github.io/rust-clippy/master/index.html#range_minus_one
[`range_plus_one`]: https://rust-lang.github.io/rust-clippy/master/index.html#range_plus_one
[`range_step_by_zero`]: https://rust-lang.github.io/rust-clippy/master/index.html#range_step_by_zero
@@ -4538,6 +4738,7 @@ Released 2018-09-13
[`should_assert_eq`]: https://rust-lang.github.io/rust-clippy/master/index.html#should_assert_eq
[`should_implement_trait`]: https://rust-lang.github.io/rust-clippy/master/index.html#should_implement_trait
[`significant_drop_in_scrutinee`]: https://rust-lang.github.io/rust-clippy/master/index.html#significant_drop_in_scrutinee
+[`significant_drop_tightening`]: https://rust-lang.github.io/rust-clippy/master/index.html#significant_drop_tightening
[`similar_names`]: https://rust-lang.github.io/rust-clippy/master/index.html#similar_names
[`single_char_add_str`]: https://rust-lang.github.io/rust-clippy/master/index.html#single_char_add_str
[`single_char_lifetime_names`]: https://rust-lang.github.io/rust-clippy/master/index.html#single_char_lifetime_names
@@ -4568,6 +4769,7 @@ Released 2018-09-13
[`suboptimal_flops`]: https://rust-lang.github.io/rust-clippy/master/index.html#suboptimal_flops
[`suspicious_arithmetic_impl`]: https://rust-lang.github.io/rust-clippy/master/index.html#suspicious_arithmetic_impl
[`suspicious_assignment_formatting`]: https://rust-lang.github.io/rust-clippy/master/index.html#suspicious_assignment_formatting
+[`suspicious_command_arg_space`]: https://rust-lang.github.io/rust-clippy/master/index.html#suspicious_command_arg_space
[`suspicious_else_formatting`]: https://rust-lang.github.io/rust-clippy/master/index.html#suspicious_else_formatting
[`suspicious_map`]: https://rust-lang.github.io/rust-clippy/master/index.html#suspicious_map
[`suspicious_op_assign_impl`]: https://rust-lang.github.io/rust-clippy/master/index.html#suspicious_op_assign_impl
@@ -4594,6 +4796,7 @@ Released 2018-09-13
[`transmute_int_to_bool`]: https://rust-lang.github.io/rust-clippy/master/index.html#transmute_int_to_bool
[`transmute_int_to_char`]: https://rust-lang.github.io/rust-clippy/master/index.html#transmute_int_to_char
[`transmute_int_to_float`]: https://rust-lang.github.io/rust-clippy/master/index.html#transmute_int_to_float
+[`transmute_int_to_non_zero`]: https://rust-lang.github.io/rust-clippy/master/index.html#transmute_int_to_non_zero
[`transmute_null_to_fn`]: https://rust-lang.github.io/rust-clippy/master/index.html#transmute_null_to_fn
[`transmute_num_to_bytes`]: https://rust-lang.github.io/rust-clippy/master/index.html#transmute_num_to_bytes
[`transmute_ptr_to_ptr`]: https://rust-lang.github.io/rust-clippy/master/index.html#transmute_ptr_to_ptr
diff --git a/src/tools/clippy/Cargo.toml b/src/tools/clippy/Cargo.toml
index f8cb4b721..70d126809 100644
--- a/src/tools/clippy/Cargo.toml
+++ b/src/tools/clippy/Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "clippy"
-version = "0.1.68"
+version = "0.1.69"
description = "A bunch of helpful lints to avoid common pitfalls in Rust"
repository = "https://github.com/rust-lang/rust-clippy"
readme = "README.md"
@@ -42,6 +42,7 @@ filetime = "0.2"
rustc-workspace-hack = "1.0"
# UI test dependencies
+clap = { version = "4.1.4", features = ["derive"] }
clippy_utils = { path = "clippy_utils" }
derive-new = "0.5"
if_chain = "1.0"
diff --git a/src/tools/clippy/README.md b/src/tools/clippy/README.md
index 81254ba8b..3e7379ace 100644
--- a/src/tools/clippy/README.md
+++ b/src/tools/clippy/README.md
@@ -5,7 +5,7 @@
A collection of lints to catch common mistakes and improve your [Rust](https://github.com/rust-lang/rust) code.
-[There are over 550 lints included in this crate!](https://rust-lang.github.io/rust-clippy/master/index.html)
+[There are over 600 lints included in this crate!](https://rust-lang.github.io/rust-clippy/master/index.html)
Lints are divided into categories, each with a default [lint level](https://doc.rust-lang.org/rustc/lints/levels.html).
You can choose how much Clippy is supposed to ~~annoy~~ help you by changing the lint level by category.
@@ -19,21 +19,35 @@ You can choose how much Clippy is supposed to ~~annoy~~ help you by changing the
| `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 have occasional false positives | allow |
+| `clippy::restriction` | lints which prevent the use of language and library features[^restrict] | allow |
| `clippy::nursery` | new lints that are still under development | allow |
| `clippy::cargo` | lints for the cargo manifest | allow |
More to come, please [file an issue](https://github.com/rust-lang/rust-clippy/issues) if you have ideas!
-The [lint list](https://rust-lang.github.io/rust-clippy/master/index.html) also contains "restriction lints", which are
-for things which are usually not considered "bad", but may be useful to turn on in specific cases. These should be used
-very selectively, if at all.
+The `restriction` category should, *emphatically*, not be enabled as a whole. The contained
+lints may lint against perfectly reasonable code, may not have an alternative suggestion,
+and may contradict any other lints (including other categories). Lints should be considered
+on a case-by-case basis before enabling.
+
+[^restrict]: Some use cases for `restriction` lints include:
+ - Strict coding styles (e.g. [`clippy::else_if_without_else`]).
+ - Additional restrictions on CI (e.g. [`clippy::todo`]).
+ - Preventing panicking in certain functions (e.g. [`clippy::unwrap_used`]).
+ - Running a lint only on a subset of code (e.g. `#[forbid(clippy::float_arithmetic)]` on a module).
+
+[`clippy::else_if_without_else`]: https://rust-lang.github.io/rust-clippy/master/index.html#else_if_without_else
+[`clippy::todo`]: https://rust-lang.github.io/rust-clippy/master/index.html#todo
+[`clippy::unwrap_used`]: https://rust-lang.github.io/rust-clippy/master/index.html#unwrap_used
+
+---
Table of contents:
-* [Usage instructions](#usage)
-* [Configuration](#configuration)
-* [Contributing](#contributing)
-* [License](#license)
+* [Usage instructions](#usage)
+* [Configuration](#configuration)
+* [Contributing](#contributing)
+* [License](#license)
## Usage
@@ -64,6 +78,7 @@ Once you have rustup and the latest stable release (at least Rust 1.29) installe
```terminal
rustup component add clippy
```
+
If it says that it can't find the `clippy` component, please run `rustup self update`.
#### Step 3: Run Clippy
@@ -143,16 +158,16 @@ line. (You can swap `clippy::all` with the specific lint category you are target
You can add options to your code to `allow`/`warn`/`deny` Clippy lints:
-* the whole set of `Warn` lints using the `clippy` lint group (`#![deny(clippy::all)]`).
+* the whole set of `Warn` lints using the `clippy` lint group (`#![deny(clippy::all)]`).
Note that `rustc` has additional [lint groups](https://doc.rust-lang.org/rustc/lints/groups.html).
-* all lints using both the `clippy` and `clippy::pedantic` lint groups (`#![deny(clippy::all)]`,
+* all lints using both the `clippy` and `clippy::pedantic` lint groups (`#![deny(clippy::all)]`,
`#![deny(clippy::pedantic)]`). Note that `clippy::pedantic` contains some very aggressive
lints prone to false positives.
-* only some lints (`#![deny(clippy::single_match, clippy::box_vec)]`, etc.)
+* only some lints (`#![deny(clippy::single_match, clippy::box_vec)]`, etc.)
-* `allow`/`warn`/`deny` can be limited to a single function or module using `#[allow(...)]`, etc.
+* `allow`/`warn`/`deny` can be limited to a single function or module using `#[allow(...)]`, etc.
Note: `allow` means to suppress the lint for your code. With `warn` the lint
will only emit a warning, while with `deny` the lint will emit an error, when
@@ -176,12 +191,14 @@ cargo clippy -- -W clippy::lint_name
This also works with lint groups. For example, you
can run Clippy with warnings for all lints enabled:
+
```terminal
cargo clippy -- -W clippy::pedantic
```
If you care only about a single lint, you can allow all others and then explicitly warn on
the lint(s) you are interested in:
+
```terminal
cargo clippy -- -A clippy::all -W clippy::useless_format -W clippy::...
```
@@ -194,11 +211,21 @@ value` mapping e.g.
```toml
avoid-breaking-exported-api = false
disallowed-names = ["toto", "tata", "titi"]
-cognitive-complexity-threshold = 30
```
-See the [list of configurable lints](https://rust-lang.github.io/rust-clippy/master/index.html#Configuration),
-the lint descriptions contain the names and meanings of these configuration variables.
+The [table of configurations](https://doc.rust-lang.org/nightly/clippy/lint_configuration.html)
+contains all config values, their default, and a list of lints they affect.
+Each [configurable lint](https://rust-lang.github.io/rust-clippy/master/index.html#Configuration)
+, also contains information about these values.
+
+For configurations that are a list type with default values such as
+[disallowed-names](https://rust-lang.github.io/rust-clippy/master/index.html#disallowed_names),
+you can use the unique value `".."` to extend the default values instead of replacing them.
+
+```toml
+# default of disallowed-names is ["foo", "baz", "quux"]
+disallowed-names = ["bar", ".."] # -> ["bar", "foo", "baz", "quux"]
+```
> **Note**
>
diff --git a/src/tools/clippy/book/src/README.md b/src/tools/clippy/book/src/README.md
index 23867df8e..df4a1f270 100644
--- a/src/tools/clippy/book/src/README.md
+++ b/src/tools/clippy/book/src/README.md
@@ -6,7 +6,7 @@
A collection of lints to catch common mistakes and improve your
[Rust](https://github.com/rust-lang/rust) code.
-[There are over 550 lints included in this crate!](https://rust-lang.github.io/rust-clippy/master/index.html)
+[There are over 600 lints included in this crate!](https://rust-lang.github.io/rust-clippy/master/index.html)
Lints are divided into categories, each with a default [lint
level](https://doc.rust-lang.org/rustc/lints/levels.html). You can choose how
diff --git a/src/tools/clippy/book/src/SUMMARY.md b/src/tools/clippy/book/src/SUMMARY.md
index 1f0b8db28..0649f7a63 100644
--- a/src/tools/clippy/book/src/SUMMARY.md
+++ b/src/tools/clippy/book/src/SUMMARY.md
@@ -5,6 +5,7 @@
- [Installation](installation.md)
- [Usage](usage.md)
- [Configuration](configuration.md)
+ - [Lint Configuration](lint_configuration.md)
- [Clippy's Lints](lints.md)
- [Continuous Integration](continuous_integration/README.md)
- [GitHub Actions](continuous_integration/github_actions.md)
diff --git a/src/tools/clippy/book/src/configuration.md b/src/tools/clippy/book/src/configuration.md
index 430ff8b73..87f4a697a 100644
--- a/src/tools/clippy/book/src/configuration.md
+++ b/src/tools/clippy/book/src/configuration.md
@@ -8,11 +8,21 @@ basic `variable = value` mapping eg.
```toml
avoid-breaking-exported-api = false
disallowed-names = ["toto", "tata", "titi"]
-cognitive-complexity-threshold = 30
```
-See the [list of configurable lints](https://rust-lang.github.io/rust-clippy/master/index.html#Configuration),
-the lint descriptions contain the names and meanings of these configuration variables.
+The [table of configurations](./lint_configuration.md)
+contains all config values, their default, and a list of lints they affect.
+Each [configurable lint](https://rust-lang.github.io/rust-clippy/master/index.html#Configuration)
+, also contains information about these values.
+
+For configurations that are a list type with default values such as
+[disallowed-names](https://rust-lang.github.io/rust-clippy/master/index.html#disallowed_names),
+you can use the unique value `".."` to extend the default values instead of replacing them.
+
+```toml
+# default of disallowed-names is ["foo", "baz", "quux"]
+disallowed-names = ["bar", ".."] # -> ["bar", "foo", "baz", "quux"]
+```
To deactivate the "for further information visit *lint-link*" message you can define the `CLIPPY_DISABLE_DOCS_LINKS`
environment variable.
diff --git a/src/tools/clippy/book/src/development/adding_lints.md b/src/tools/clippy/book/src/development/adding_lints.md
index 8b4eee8c9..f57dc627d 100644
--- a/src/tools/clippy/book/src/development/adding_lints.md
+++ b/src/tools/clippy/book/src/development/adding_lints.md
@@ -146,7 +146,8 @@ For cargo lints, the process of testing differs in that we are interested in the
manifest.
If our new lint is named e.g. `foo_categories`, after running `cargo dev
-new_lint` we will find by default two new crates, each with its manifest file:
+new_lint --name=foo_categories --type=cargo --category=cargo` we will find by
+default two new crates, each with its manifest file:
* `tests/ui-cargo/foo_categories/fail/Cargo.toml`: this file should cause the
new lint to raise an error.
@@ -699,6 +700,10 @@ for some users. Adding a configuration is done in the following steps:
`clippy.toml` file with the configuration value and a rust file that
should be linted by Clippy. The test can otherwise be written as usual.
+5. Update [Lint Configuration](../lint_configuration.md)
+
+ Run `cargo collect-metadata` to generate documentation changes for the book.
+
[`clippy_lints::utils::conf`]: https://github.com/rust-lang/rust-clippy/blob/master/clippy_lints/src/utils/conf.rs
[`clippy_lints` lib file]: https://github.com/rust-lang/rust-clippy/blob/master/clippy_lints/src/lib.rs
[`tests/ui`]: https://github.com/rust-lang/rust-clippy/blob/master/tests/ui
diff --git a/src/tools/clippy/book/src/development/infrastructure/backport.md b/src/tools/clippy/book/src/development/infrastructure/backport.md
index 15f3d1f08..6920c4e46 100644
--- a/src/tools/clippy/book/src/development/infrastructure/backport.md
+++ b/src/tools/clippy/book/src/development/infrastructure/backport.md
@@ -28,6 +28,7 @@ repository. You can do this with:
```bash
# Assuming the current directory corresponds to the Rust repository
$ git checkout beta
+# Make sure to change `your-github-name` to your github name in the following command
$ git subtree pull -p src/tools/clippy https://github.com/<your-github-name>/rust-clippy backport
$ ./x.py test src/tools/clippy
```
diff --git a/src/tools/clippy/book/src/development/infrastructure/book.md b/src/tools/clippy/book/src/development/infrastructure/book.md
index a48742191..dbd624ecd 100644
--- a/src/tools/clippy/book/src/development/infrastructure/book.md
+++ b/src/tools/clippy/book/src/development/infrastructure/book.md
@@ -3,15 +3,15 @@
This document explains how to make additions and changes to the Clippy book, the
guide to Clippy that you're reading right now. The Clippy book is formatted with
[Markdown](https://www.markdownguide.org) and generated by
-[mdbook](https://github.com/rust-lang/mdBook).
+[mdBook](https://github.com/rust-lang/mdBook).
-- [Get mdbook](#get-mdbook)
+- [Get mdBook](#get-mdbook)
- [Make changes](#make-changes)
-## Get mdbook
+## Get mdBook
While not strictly necessary since the book source is simply Markdown text
-files, having mdbook locally will allow you to build, test and serve the book
+files, having mdBook locally will allow you to build, test and serve the book
locally to view changes before you commit them to the repository. You likely
already have `cargo` installed, so the easiest option is to simply:
@@ -19,7 +19,7 @@ already have `cargo` installed, so the easiest option is to simply:
cargo install mdbook
```
-See the mdbook [installation](https://github.com/rust-lang/mdBook#installation)
+See the mdBook [installation](https://github.com/rust-lang/mdBook#installation)
instructions for other options.
## Make changes
@@ -27,7 +27,7 @@ instructions for other options.
The book's
[src](https://github.com/rust-lang/rust-clippy/tree/master/book/src)
directory contains all of the markdown files used to generate the book. If you
-want to see your changes in real time, you can use the mdbook `serve` command to
+want to see your changes in real time, you can use the mdBook `serve` command to
run a web server locally that will automatically update changes as they are
made. From the top level of your `rust-clippy` directory:
@@ -38,5 +38,5 @@ mdbook serve book --open
Then navigate to `http://localhost:3000` to see the generated book. While the
server is running, changes you make will automatically be updated.
-For more information, see the mdbook
+For more information, see the mdBook
[guide](https://rust-lang.github.io/mdBook/).
diff --git a/src/tools/clippy/book/src/development/infrastructure/changelog_update.md b/src/tools/clippy/book/src/development/infrastructure/changelog_update.md
index 80a47affe..d1ac7237b 100644
--- a/src/tools/clippy/book/src/development/infrastructure/changelog_update.md
+++ b/src/tools/clippy/book/src/development/infrastructure/changelog_update.md
@@ -95,11 +95,23 @@ As section headers, we use:
Please also be sure to update the Beta/Unreleased sections at the top with the
relevant commit ranges.
-If you have the time, it would be appreciated if you double-check, that the
-`#[clippy::version]` attributes for the added lints contains the correct version.
+#### 3.1 Include `beta-accepted` PRs
+
+Look for the [`beta-accepted`] label and make sure to also include the PRs with
+that label in the changelog. If you can, remove the `beta-accepted` labels
+**after** the changelog PR was merged.
+
+> _Note:_ Some of those PRs might even got backported to the previous `beta`.
+> Those have to be included in the changelog of the _previous_ release.
+
+### 4. Update `clippy::version` attributes
+
+Next, make sure to check that the `#[clippy::version]` attributes for the added
+lints contain the correct version.
[changelog]: https://github.com/rust-lang/rust-clippy/blob/master/CHANGELOG.md
[forge]: https://forge.rust-lang.org/
[rust_master_tools]: https://github.com/rust-lang/rust/tree/master/src/tools/clippy
[rust_beta_tools]: https://github.com/rust-lang/rust/tree/beta/src/tools/clippy
[rust_stable_tools]: https://github.com/rust-lang/rust/releases
+[`beta-accepted`]: https://github.com/rust-lang/rust-clippy/issues?q=label%3Abeta-accepted+
diff --git a/src/tools/clippy/book/src/development/infrastructure/sync.md b/src/tools/clippy/book/src/development/infrastructure/sync.md
index 5a0f7409a..02cfc11b5 100644
--- a/src/tools/clippy/book/src/development/infrastructure/sync.md
+++ b/src/tools/clippy/book/src/development/infrastructure/sync.md
@@ -79,8 +79,7 @@ to be run inside the `rust` directory):
`rustup check`.
3. Sync the changes to the rust-copy of Clippy to your Clippy fork:
```bash
- # Make sure to change `your-github-name` to your github name in the following command. Also be
- # sure to either use a net-new branch, e.g. `sync-from-rust`, or delete the branch beforehand
+ # Be sure to either use a net-new branch, e.g. `sync-from-rust`, or delete the branch beforehand
# because changes cannot be fast forwarded and you have to run this command again.
git subtree push -P src/tools/clippy clippy-local sync-from-rust
```
diff --git a/src/tools/clippy/book/src/lint_configuration.md b/src/tools/clippy/book/src/lint_configuration.md
new file mode 100644
index 000000000..995dd2f04
--- /dev/null
+++ b/src/tools/clippy/book/src/lint_configuration.md
@@ -0,0 +1,553 @@
+<!--
+This file is generated by `cargo collect-metadata`.
+Please use that command to update the file and do not edit it by hand.
+-->
+
+## Lint Configuration Options
+| <div style="width:290px">Option</div> | Default Value |
+|--|--|
+| [arithmetic-side-effects-allowed](#arithmetic-side-effects-allowed) | `{}` |
+| [arithmetic-side-effects-allowed-binary](#arithmetic-side-effects-allowed-binary) | `[]` |
+| [arithmetic-side-effects-allowed-unary](#arithmetic-side-effects-allowed-unary) | `{}` |
+| [avoid-breaking-exported-api](#avoid-breaking-exported-api) | `true` |
+| [msrv](#msrv) | `None` |
+| [cognitive-complexity-threshold](#cognitive-complexity-threshold) | `25` |
+| [disallowed-names](#disallowed-names) | `["foo", "baz", "quux"]` |
+| [doc-valid-idents](#doc-valid-idents) | `["KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "DirectX", "ECMAScript", "GPLv2", "GPLv3", "GitHub", "GitLab", "IPv4", "IPv6", "ClojureScript", "CoffeeScript", "JavaScript", "PureScript", "TypeScript", "NaN", "NaNs", "OAuth", "GraphQL", "OCaml", "OpenGL", "OpenMP", "OpenSSH", "OpenSSL", "OpenStreetMap", "OpenDNS", "WebGL", "TensorFlow", "TrueType", "iOS", "macOS", "FreeBSD", "TeX", "LaTeX", "BibTeX", "BibLaTeX", "MinGW", "CamelCase"]` |
+| [too-many-arguments-threshold](#too-many-arguments-threshold) | `7` |
+| [type-complexity-threshold](#type-complexity-threshold) | `250` |
+| [single-char-binding-names-threshold](#single-char-binding-names-threshold) | `4` |
+| [too-large-for-stack](#too-large-for-stack) | `200` |
+| [enum-variant-name-threshold](#enum-variant-name-threshold) | `3` |
+| [enum-variant-size-threshold](#enum-variant-size-threshold) | `200` |
+| [verbose-bit-mask-threshold](#verbose-bit-mask-threshold) | `1` |
+| [literal-representation-threshold](#literal-representation-threshold) | `16384` |
+| [trivial-copy-size-limit](#trivial-copy-size-limit) | `None` |
+| [pass-by-value-size-limit](#pass-by-value-size-limit) | `256` |
+| [too-many-lines-threshold](#too-many-lines-threshold) | `100` |
+| [array-size-threshold](#array-size-threshold) | `512000` |
+| [vec-box-size-threshold](#vec-box-size-threshold) | `4096` |
+| [max-trait-bounds](#max-trait-bounds) | `3` |
+| [max-struct-bools](#max-struct-bools) | `3` |
+| [max-fn-params-bools](#max-fn-params-bools) | `3` |
+| [warn-on-all-wildcard-imports](#warn-on-all-wildcard-imports) | `false` |
+| [disallowed-macros](#disallowed-macros) | `[]` |
+| [disallowed-methods](#disallowed-methods) | `[]` |
+| [disallowed-types](#disallowed-types) | `[]` |
+| [unreadable-literal-lint-fractions](#unreadable-literal-lint-fractions) | `true` |
+| [upper-case-acronyms-aggressive](#upper-case-acronyms-aggressive) | `false` |
+| [matches-for-let-else](#matches-for-let-else) | `WellKnownTypes` |
+| [cargo-ignore-publish](#cargo-ignore-publish) | `false` |
+| [standard-macro-braces](#standard-macro-braces) | `[]` |
+| [enforced-import-renames](#enforced-import-renames) | `[]` |
+| [allowed-scripts](#allowed-scripts) | `["Latin"]` |
+| [enable-raw-pointer-heuristic-for-send](#enable-raw-pointer-heuristic-for-send) | `true` |
+| [max-suggested-slice-pattern-length](#max-suggested-slice-pattern-length) | `3` |
+| [await-holding-invalid-types](#await-holding-invalid-types) | `[]` |
+| [max-include-file-size](#max-include-file-size) | `1000000` |
+| [allow-expect-in-tests](#allow-expect-in-tests) | `false` |
+| [allow-unwrap-in-tests](#allow-unwrap-in-tests) | `false` |
+| [allow-dbg-in-tests](#allow-dbg-in-tests) | `false` |
+| [allow-print-in-tests](#allow-print-in-tests) | `false` |
+| [large-error-threshold](#large-error-threshold) | `128` |
+| [ignore-interior-mutability](#ignore-interior-mutability) | `["bytes::Bytes"]` |
+| [allow-mixed-uninlined-format-args](#allow-mixed-uninlined-format-args) | `true` |
+| [suppress-restriction-lint-in-const](#suppress-restriction-lint-in-const) | `false` |
+| [missing-docs-in-crate-items](#missing-docs-in-crate-items) | `false` |
+
+### arithmetic-side-effects-allowed
+Suppress checking of the passed type names in all types of operations.
+
+If a specific operation is desired, consider using `arithmetic_side_effects_allowed_binary` or `arithmetic_side_effects_allowed_unary` instead.
+
+#### Example
+
+```toml
+arithmetic-side-effects-allowed = ["SomeType", "AnotherType"]
+```
+
+#### Noteworthy
+
+A type, say `SomeType`, listed in this configuration has the same behavior of
+`["SomeType" , "*"], ["*", "SomeType"]` in `arithmetic_side_effects_allowed_binary`.
+
+**Default Value:** `{}` (`rustc_data_structures::fx::FxHashSet<String>`)
+
+* [arithmetic_side_effects](https://rust-lang.github.io/rust-clippy/master/index.html#arithmetic_side_effects)
+
+
+### arithmetic-side-effects-allowed-binary
+Suppress checking of the passed type pair names in binary operations like addition or
+multiplication.
+
+Supports the "*" wildcard to indicate that a certain type won't trigger the lint regardless
+of the involved counterpart. For example, `["SomeType", "*"]` or `["*", "AnotherType"]`.
+
+Pairs are asymmetric, which means that `["SomeType", "AnotherType"]` is not the same as
+`["AnotherType", "SomeType"]`.
+
+#### Example
+
+```toml
+arithmetic-side-effects-allowed-binary = [["SomeType" , "f32"], ["AnotherType", "*"]]
+```
+
+**Default Value:** `[]` (`Vec<[String; 2]>`)
+
+* [arithmetic_side_effects](https://rust-lang.github.io/rust-clippy/master/index.html#arithmetic_side_effects)
+
+
+### arithmetic-side-effects-allowed-unary
+Suppress checking of the passed type names in unary operations like "negation" (`-`).
+
+#### Example
+
+```toml
+arithmetic-side-effects-allowed-unary = ["SomeType", "AnotherType"]
+```
+
+**Default Value:** `{}` (`rustc_data_structures::fx::FxHashSet<String>`)
+
+* [arithmetic_side_effects](https://rust-lang.github.io/rust-clippy/master/index.html#arithmetic_side_effects)
+
+
+### avoid-breaking-exported-api
+Suppress lints whenever the suggested change would cause breakage for other crates.
+
+**Default Value:** `true` (`bool`)
+
+* [enum_variant_names](https://rust-lang.github.io/rust-clippy/master/index.html#enum_variant_names)
+* [large_types_passed_by_value](https://rust-lang.github.io/rust-clippy/master/index.html#large_types_passed_by_value)
+* [trivially_copy_pass_by_ref](https://rust-lang.github.io/rust-clippy/master/index.html#trivially_copy_pass_by_ref)
+* [unnecessary_wraps](https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_wraps)
+* [unused_self](https://rust-lang.github.io/rust-clippy/master/index.html#unused_self)
+* [upper_case_acronyms](https://rust-lang.github.io/rust-clippy/master/index.html#upper_case_acronyms)
+* [wrong_self_convention](https://rust-lang.github.io/rust-clippy/master/index.html#wrong_self_convention)
+* [box_collection](https://rust-lang.github.io/rust-clippy/master/index.html#box_collection)
+* [redundant_allocation](https://rust-lang.github.io/rust-clippy/master/index.html#redundant_allocation)
+* [rc_buffer](https://rust-lang.github.io/rust-clippy/master/index.html#rc_buffer)
+* [vec_box](https://rust-lang.github.io/rust-clippy/master/index.html#vec_box)
+* [option_option](https://rust-lang.github.io/rust-clippy/master/index.html#option_option)
+* [linkedlist](https://rust-lang.github.io/rust-clippy/master/index.html#linkedlist)
+* [rc_mutex](https://rust-lang.github.io/rust-clippy/master/index.html#rc_mutex)
+
+
+### msrv
+The minimum rust version that the project supports
+
+**Default Value:** `None` (`Option<String>`)
+
+* [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)
+* [cloned_instead_of_copied](https://rust-lang.github.io/rust-clippy/master/index.html#cloned_instead_of_copied)
+* [redundant_field_names](https://rust-lang.github.io/rust-clippy/master/index.html#redundant_field_names)
+* [redundant_static_lifetimes](https://rust-lang.github.io/rust-clippy/master/index.html#redundant_static_lifetimes)
+* [filter_map_next](https://rust-lang.github.io/rust-clippy/master/index.html#filter_map_next)
+* [checked_conversions](https://rust-lang.github.io/rust-clippy/master/index.html#checked_conversions)
+* [manual_range_contains](https://rust-lang.github.io/rust-clippy/master/index.html#manual_range_contains)
+* [use_self](https://rust-lang.github.io/rust-clippy/master/index.html#use_self)
+* [mem_replace_with_default](https://rust-lang.github.io/rust-clippy/master/index.html#mem_replace_with_default)
+* [manual_non_exhaustive](https://rust-lang.github.io/rust-clippy/master/index.html#manual_non_exhaustive)
+* [option_as_ref_deref](https://rust-lang.github.io/rust-clippy/master/index.html#option_as_ref_deref)
+* [map_unwrap_or](https://rust-lang.github.io/rust-clippy/master/index.html#map_unwrap_or)
+* [match_like_matches_macro](https://rust-lang.github.io/rust-clippy/master/index.html#match_like_matches_macro)
+* [manual_strip](https://rust-lang.github.io/rust-clippy/master/index.html#manual_strip)
+* [missing_const_for_fn](https://rust-lang.github.io/rust-clippy/master/index.html#missing_const_for_fn)
+* [unnested_or_patterns](https://rust-lang.github.io/rust-clippy/master/index.html#unnested_or_patterns)
+* [from_over_into](https://rust-lang.github.io/rust-clippy/master/index.html#from_over_into)
+* [ptr_as_ptr](https://rust-lang.github.io/rust-clippy/master/index.html#ptr_as_ptr)
+* [if_then_some_else_none](https://rust-lang.github.io/rust-clippy/master/index.html#if_then_some_else_none)
+* [approx_constant](https://rust-lang.github.io/rust-clippy/master/index.html#approx_constant)
+* [deprecated_cfg_attr](https://rust-lang.github.io/rust-clippy/master/index.html#deprecated_cfg_attr)
+* [index_refutable_slice](https://rust-lang.github.io/rust-clippy/master/index.html#index_refutable_slice)
+* [map_clone](https://rust-lang.github.io/rust-clippy/master/index.html#map_clone)
+* [borrow_as_ptr](https://rust-lang.github.io/rust-clippy/master/index.html#borrow_as_ptr)
+* [manual_bits](https://rust-lang.github.io/rust-clippy/master/index.html#manual_bits)
+* [err_expect](https://rust-lang.github.io/rust-clippy/master/index.html#err_expect)
+* [cast_abs_to_unsigned](https://rust-lang.github.io/rust-clippy/master/index.html#cast_abs_to_unsigned)
+* [uninlined_format_args](https://rust-lang.github.io/rust-clippy/master/index.html#uninlined_format_args)
+* [manual_clamp](https://rust-lang.github.io/rust-clippy/master/index.html#manual_clamp)
+* [manual_let_else](https://rust-lang.github.io/rust-clippy/master/index.html#manual_let_else)
+* [unchecked_duration_subtraction](https://rust-lang.github.io/rust-clippy/master/index.html#unchecked_duration_subtraction)
+* [collapsible_str_replace](https://rust-lang.github.io/rust-clippy/master/index.html#collapsible_str_replace)
+* [seek_from_current](https://rust-lang.github.io/rust-clippy/master/index.html#seek_from_current)
+* [seek_rewind](https://rust-lang.github.io/rust-clippy/master/index.html#seek_rewind)
+* [unnecessary_lazy_evaluations](https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_lazy_evaluations)
+* [transmute_ptr_to_ref](https://rust-lang.github.io/rust-clippy/master/index.html#transmute_ptr_to_ref)
+* [almost_complete_range](https://rust-lang.github.io/rust-clippy/master/index.html#almost_complete_range)
+* [needless_borrow](https://rust-lang.github.io/rust-clippy/master/index.html#needless_borrow)
+* [derivable_impls](https://rust-lang.github.io/rust-clippy/master/index.html#derivable_impls)
+* [manual_is_ascii_check](https://rust-lang.github.io/rust-clippy/master/index.html#manual_is_ascii_check)
+* [manual_rem_euclid](https://rust-lang.github.io/rust-clippy/master/index.html#manual_rem_euclid)
+* [manual_retain](https://rust-lang.github.io/rust-clippy/master/index.html#manual_retain)
+
+
+### cognitive-complexity-threshold
+The maximum cognitive complexity a function can have
+
+**Default Value:** `25` (`u64`)
+
+* [cognitive_complexity](https://rust-lang.github.io/rust-clippy/master/index.html#cognitive_complexity)
+
+
+### disallowed-names
+The list of disallowed names to lint about. NB: `bar` is not here since it has legitimate uses. The value
+`".."` can be used as part of the list to indicate, that the configured values should be appended to the
+default configuration of Clippy. By default any configuration will replace the default value.
+
+**Default Value:** `["foo", "baz", "quux"]` (`Vec<String>`)
+
+* [disallowed_names](https://rust-lang.github.io/rust-clippy/master/index.html#disallowed_names)
+
+
+### doc-valid-idents
+The list of words this lint should not consider as identifiers needing ticks. The value
+`".."` can be used as part of the list to indicate, that the configured values should be appended to the
+default configuration of Clippy. By default any configuraction will replace the default value. For example:
+* `doc-valid-idents = ["ClipPy"]` would replace the default list with `["ClipPy"]`.
+* `doc-valid-idents = ["ClipPy", ".."]` would append `ClipPy` to the default list.
+
+Default list:
+
+**Default Value:** `["KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "DirectX", "ECMAScript", "GPLv2", "GPLv3", "GitHub", "GitLab", "IPv4", "IPv6", "ClojureScript", "CoffeeScript", "JavaScript", "PureScript", "TypeScript", "NaN", "NaNs", "OAuth", "GraphQL", "OCaml", "OpenGL", "OpenMP", "OpenSSH", "OpenSSL", "OpenStreetMap", "OpenDNS", "WebGL", "TensorFlow", "TrueType", "iOS", "macOS", "FreeBSD", "TeX", "LaTeX", "BibTeX", "BibLaTeX", "MinGW", "CamelCase"]` (`Vec<String>`)
+
+* [doc_markdown](https://rust-lang.github.io/rust-clippy/master/index.html#doc_markdown)
+
+
+### too-many-arguments-threshold
+The maximum number of argument a function or method can have
+
+**Default Value:** `7` (`u64`)
+
+* [too_many_arguments](https://rust-lang.github.io/rust-clippy/master/index.html#too_many_arguments)
+
+
+### type-complexity-threshold
+The maximum complexity a type can have
+
+**Default Value:** `250` (`u64`)
+
+* [type_complexity](https://rust-lang.github.io/rust-clippy/master/index.html#type_complexity)
+
+
+### single-char-binding-names-threshold
+The maximum number of single char bindings a scope may have
+
+**Default Value:** `4` (`u64`)
+
+* [many_single_char_names](https://rust-lang.github.io/rust-clippy/master/index.html#many_single_char_names)
+
+
+### too-large-for-stack
+The maximum size of objects (in bytes) that will be linted. Larger objects are ok on the heap
+
+**Default Value:** `200` (`u64`)
+
+* [boxed_local](https://rust-lang.github.io/rust-clippy/master/index.html#boxed_local)
+* [useless_vec](https://rust-lang.github.io/rust-clippy/master/index.html#useless_vec)
+
+
+### enum-variant-name-threshold
+The minimum number of enum variants for the lints about variant names to trigger
+
+**Default Value:** `3` (`u64`)
+
+* [enum_variant_names](https://rust-lang.github.io/rust-clippy/master/index.html#enum_variant_names)
+
+
+### enum-variant-size-threshold
+The maximum size of an enum's variant to avoid box suggestion
+
+**Default Value:** `200` (`u64`)
+
+* [large_enum_variant](https://rust-lang.github.io/rust-clippy/master/index.html#large_enum_variant)
+
+
+### verbose-bit-mask-threshold
+The maximum allowed size of a bit mask before suggesting to use 'trailing_zeros'
+
+**Default Value:** `1` (`u64`)
+
+* [verbose_bit_mask](https://rust-lang.github.io/rust-clippy/master/index.html#verbose_bit_mask)
+
+
+### literal-representation-threshold
+The lower bound for linting decimal literals
+
+**Default Value:** `16384` (`u64`)
+
+* [decimal_literal_representation](https://rust-lang.github.io/rust-clippy/master/index.html#decimal_literal_representation)
+
+
+### trivial-copy-size-limit
+The maximum size (in bytes) to consider a `Copy` type for passing by value instead of by reference.
+
+**Default Value:** `None` (`Option<u64>`)
+
+* [trivially_copy_pass_by_ref](https://rust-lang.github.io/rust-clippy/master/index.html#trivially_copy_pass_by_ref)
+
+
+### pass-by-value-size-limit
+The minimum size (in bytes) to consider a type for passing by reference instead of by value.
+
+**Default Value:** `256` (`u64`)
+
+* [large_types_passed_by_value](https://rust-lang.github.io/rust-clippy/master/index.html#large_types_passed_by_value)
+
+
+### too-many-lines-threshold
+The maximum number of lines a function or method can have
+
+**Default Value:** `100` (`u64`)
+
+* [too_many_lines](https://rust-lang.github.io/rust-clippy/master/index.html#too_many_lines)
+
+
+### array-size-threshold
+The maximum allowed size for arrays on the stack
+
+**Default Value:** `512000` (`u64`)
+
+* [large_stack_arrays](https://rust-lang.github.io/rust-clippy/master/index.html#large_stack_arrays)
+* [large_const_arrays](https://rust-lang.github.io/rust-clippy/master/index.html#large_const_arrays)
+
+
+### vec-box-size-threshold
+The size of the boxed type in bytes, where boxing in a `Vec` is allowed
+
+**Default Value:** `4096` (`u64`)
+
+* [vec_box](https://rust-lang.github.io/rust-clippy/master/index.html#vec_box)
+
+
+### max-trait-bounds
+The maximum number of bounds a trait can have to be linted
+
+**Default Value:** `3` (`u64`)
+
+* [type_repetition_in_bounds](https://rust-lang.github.io/rust-clippy/master/index.html#type_repetition_in_bounds)
+
+
+### max-struct-bools
+The maximum number of bool fields a struct can have
+
+**Default Value:** `3` (`u64`)
+
+* [struct_excessive_bools](https://rust-lang.github.io/rust-clippy/master/index.html#struct_excessive_bools)
+
+
+### max-fn-params-bools
+The maximum number of bool parameters a function can have
+
+**Default Value:** `3` (`u64`)
+
+* [fn_params_excessive_bools](https://rust-lang.github.io/rust-clippy/master/index.html#fn_params_excessive_bools)
+
+
+### warn-on-all-wildcard-imports
+Whether to allow certain wildcard imports (prelude, super in tests).
+
+**Default Value:** `false` (`bool`)
+
+* [wildcard_imports](https://rust-lang.github.io/rust-clippy/master/index.html#wildcard_imports)
+
+
+### disallowed-macros
+The list of disallowed macros, written as fully qualified paths.
+
+**Default Value:** `[]` (`Vec<crate::utils::conf::DisallowedPath>`)
+
+* [disallowed_macros](https://rust-lang.github.io/rust-clippy/master/index.html#disallowed_macros)
+
+
+### disallowed-methods
+The list of disallowed methods, written as fully qualified paths.
+
+**Default Value:** `[]` (`Vec<crate::utils::conf::DisallowedPath>`)
+
+* [disallowed_methods](https://rust-lang.github.io/rust-clippy/master/index.html#disallowed_methods)
+
+
+### disallowed-types
+The list of disallowed types, written as fully qualified paths.
+
+**Default Value:** `[]` (`Vec<crate::utils::conf::DisallowedPath>`)
+
+* [disallowed_types](https://rust-lang.github.io/rust-clippy/master/index.html#disallowed_types)
+
+
+### unreadable-literal-lint-fractions
+Should the fraction of a decimal be linted to include separators.
+
+**Default Value:** `true` (`bool`)
+
+* [unreadable_literal](https://rust-lang.github.io/rust-clippy/master/index.html#unreadable_literal)
+
+
+### upper-case-acronyms-aggressive
+Enables verbose mode. Triggers if there is more than one uppercase char next to each other
+
+**Default Value:** `false` (`bool`)
+
+* [upper_case_acronyms](https://rust-lang.github.io/rust-clippy/master/index.html#upper_case_acronyms)
+
+
+### matches-for-let-else
+Whether the matches should be considered by the lint, and whether there should
+be filtering for common types.
+
+**Default Value:** `WellKnownTypes` (`crate::manual_let_else::MatchLintBehaviour`)
+
+* [manual_let_else](https://rust-lang.github.io/rust-clippy/master/index.html#manual_let_else)
+
+
+### cargo-ignore-publish
+For internal testing only, ignores the current `publish` settings in the Cargo manifest.
+
+**Default Value:** `false` (`bool`)
+
+* [_cargo_common_metadata](https://rust-lang.github.io/rust-clippy/master/index.html#_cargo_common_metadata)
+
+
+### standard-macro-braces
+Enforce the named macros always use the braces specified.
+
+A `MacroMatcher` can be added like so `{ name = "macro_name", brace = "(" }`. If the macro
+is could be used with a full path two `MacroMatcher`s have to be added one with the full path
+`crate_name::macro_name` and one with just the macro name.
+
+**Default Value:** `[]` (`Vec<crate::nonstandard_macro_braces::MacroMatcher>`)
+
+* [nonstandard_macro_braces](https://rust-lang.github.io/rust-clippy/master/index.html#nonstandard_macro_braces)
+
+
+### enforced-import-renames
+The list of imports to always rename, a fully qualified path followed by the rename.
+
+**Default Value:** `[]` (`Vec<crate::utils::conf::Rename>`)
+
+* [missing_enforced_import_renames](https://rust-lang.github.io/rust-clippy/master/index.html#missing_enforced_import_renames)
+
+
+### allowed-scripts
+The list of unicode scripts allowed to be used in the scope.
+
+**Default Value:** `["Latin"]` (`Vec<String>`)
+
+* [disallowed_script_idents](https://rust-lang.github.io/rust-clippy/master/index.html#disallowed_script_idents)
+
+
+### enable-raw-pointer-heuristic-for-send
+Whether to apply the raw pointer heuristic to determine if a type is `Send`.
+
+**Default Value:** `true` (`bool`)
+
+* [non_send_fields_in_send_ty](https://rust-lang.github.io/rust-clippy/master/index.html#non_send_fields_in_send_ty)
+
+
+### max-suggested-slice-pattern-length
+When Clippy suggests using a slice pattern, this is the maximum number of elements allowed in
+the slice pattern that is suggested. If more elements would be necessary, the lint is suppressed.
+For example, `[_, _, _, e, ..]` is a slice pattern with 4 elements.
+
+**Default Value:** `3` (`u64`)
+
+* [index_refutable_slice](https://rust-lang.github.io/rust-clippy/master/index.html#index_refutable_slice)
+
+
+### await-holding-invalid-types
+
+
+**Default Value:** `[]` (`Vec<crate::utils::conf::DisallowedPath>`)
+
+* [await_holding_invalid_type](https://rust-lang.github.io/rust-clippy/master/index.html#await_holding_invalid_type)
+
+
+### max-include-file-size
+The maximum size of a file included via `include_bytes!()` or `include_str!()`, in bytes
+
+**Default Value:** `1000000` (`u64`)
+
+* [large_include_file](https://rust-lang.github.io/rust-clippy/master/index.html#large_include_file)
+
+
+### allow-expect-in-tests
+Whether `expect` should be allowed in test functions or `#[cfg(test)]`
+
+**Default Value:** `false` (`bool`)
+
+* [expect_used](https://rust-lang.github.io/rust-clippy/master/index.html#expect_used)
+
+
+### allow-unwrap-in-tests
+Whether `unwrap` should be allowed in test functions or `#[cfg(test)]`
+
+**Default Value:** `false` (`bool`)
+
+* [unwrap_used](https://rust-lang.github.io/rust-clippy/master/index.html#unwrap_used)
+
+
+### allow-dbg-in-tests
+Whether `dbg!` should be allowed in test functions or `#[cfg(test)]`
+
+**Default Value:** `false` (`bool`)
+
+* [dbg_macro](https://rust-lang.github.io/rust-clippy/master/index.html#dbg_macro)
+
+
+### allow-print-in-tests
+Whether print macros (ex. `println!`) should be allowed in test functions or `#[cfg(test)]`
+
+**Default Value:** `false` (`bool`)
+
+* [print_stdout](https://rust-lang.github.io/rust-clippy/master/index.html#print_stdout)
+* [print_stderr](https://rust-lang.github.io/rust-clippy/master/index.html#print_stderr)
+
+
+### large-error-threshold
+The maximum size of the `Err`-variant in a `Result` returned from a function
+
+**Default Value:** `128` (`u64`)
+
+* [result_large_err](https://rust-lang.github.io/rust-clippy/master/index.html#result_large_err)
+
+
+### ignore-interior-mutability
+A list of paths to types that should be treated like `Arc`, i.e. ignored but
+for the generic parameters for determining interior mutability
+
+**Default Value:** `["bytes::Bytes"]` (`Vec<String>`)
+
+* [mutable_key_type](https://rust-lang.github.io/rust-clippy/master/index.html#mutable_key_type)
+
+
+### allow-mixed-uninlined-format-args
+Whether to allow mixed uninlined format args, e.g. `format!("{} {}", a, foo.bar)`
+
+**Default Value:** `true` (`bool`)
+
+* [uninlined_format_args](https://rust-lang.github.io/rust-clippy/master/index.html#uninlined_format_args)
+
+
+### suppress-restriction-lint-in-const
+Whether to suppress a restriction lint in constant code. In same
+cases the restructured operation might not be unavoidable, as the
+suggested counterparts are unavailable in constant code. This
+configuration will cause restriction lints to trigger even
+if no suggestion can be made.
+
+**Default Value:** `false` (`bool`)
+
+* [indexing_slicing](https://rust-lang.github.io/rust-clippy/master/index.html#indexing_slicing)
+
+
+### missing-docs-in-crate-items
+Whether to **only** check for missing documentation in items visible within the current
+crate. For example, `pub(crate)` items.
+
+**Default Value:** `false` (`bool`)
+
+* [missing_docs_in_private_items](https://rust-lang.github.io/rust-clippy/master/index.html#missing_docs_in_private_items)
+
+
+
diff --git a/src/tools/clippy/clippy_dev/Cargo.toml b/src/tools/clippy/clippy_dev/Cargo.toml
index 510c7e852..c3f8a782d 100644
--- a/src/tools/clippy/clippy_dev/Cargo.toml
+++ b/src/tools/clippy/clippy_dev/Cargo.toml
@@ -5,7 +5,7 @@ edition = "2021"
[dependencies]
aho-corasick = "0.7"
-clap = "3.2"
+clap = "4.1.4"
indoc = "1.0"
itertools = "0.10.1"
opener = "0.5"
diff --git a/src/tools/clippy/clippy_dev/src/main.rs b/src/tools/clippy/clippy_dev/src/main.rs
index d3e036692..e2457e5a8 100644
--- a/src/tools/clippy/clippy_dev/src/main.rs
+++ b/src/tools/clippy/clippy_dev/src/main.rs
@@ -2,7 +2,7 @@
// warn on lints, that are included in `rust-lang/rust`s bootstrap
#![warn(rust_2018_idioms, unused_lifetimes)]
-use clap::{Arg, ArgAction, ArgMatches, Command, PossibleValue};
+use clap::{Arg, ArgAction, ArgMatches, Command};
use clippy_dev::{bless, dogfood, fmt, lint, new_lint, serve, setup, update_lints};
use indoc::indoc;
@@ -11,22 +11,22 @@ fn main() {
match matches.subcommand() {
Some(("bless", matches)) => {
- bless::bless(matches.contains_id("ignore-timestamp"));
+ bless::bless(matches.get_flag("ignore-timestamp"));
},
Some(("dogfood", matches)) => {
dogfood::dogfood(
- matches.contains_id("fix"),
- matches.contains_id("allow-dirty"),
- matches.contains_id("allow-staged"),
+ matches.get_flag("fix"),
+ matches.get_flag("allow-dirty"),
+ matches.get_flag("allow-staged"),
);
},
Some(("fmt", matches)) => {
- fmt::run(matches.contains_id("check"), matches.contains_id("verbose"));
+ fmt::run(matches.get_flag("check"), matches.get_flag("verbose"));
},
Some(("update_lints", matches)) => {
- if matches.contains_id("print-only") {
+ if matches.get_flag("print-only") {
update_lints::print_lints();
- } else if matches.contains_id("check") {
+ } else if matches.get_flag("check") {
update_lints::update(update_lints::UpdateMode::Check);
} else {
update_lints::update(update_lints::UpdateMode::Change);
@@ -38,7 +38,7 @@ fn main() {
matches.get_one::<String>("name"),
matches.get_one::<String>("category").map(String::as_str),
matches.get_one::<String>("type").map(String::as_str),
- matches.contains_id("msrv"),
+ matches.get_flag("msrv"),
) {
Ok(_) => update_lints::update(update_lints::UpdateMode::Change),
Err(e) => eprintln!("Unable to create lint: {e}"),
@@ -46,7 +46,7 @@ fn main() {
},
Some(("setup", sub_command)) => match sub_command.subcommand() {
Some(("intellij", matches)) => {
- if matches.contains_id("remove") {
+ if matches.get_flag("remove") {
setup::intellij::remove_rustc_src();
} else {
setup::intellij::setup_rustc_src(
@@ -57,17 +57,17 @@ fn main() {
}
},
Some(("git-hook", matches)) => {
- if matches.contains_id("remove") {
+ if matches.get_flag("remove") {
setup::git_hook::remove_hook();
} else {
- setup::git_hook::install_hook(matches.contains_id("force-override"));
+ setup::git_hook::install_hook(matches.get_flag("force-override"));
}
},
Some(("vscode-tasks", matches)) => {
- if matches.contains_id("remove") {
+ if matches.get_flag("remove") {
setup::vscode::remove_tasks();
} else {
- setup::vscode::install_tasks(matches.contains_id("force-override"));
+ setup::vscode::install_tasks(matches.get_flag("force-override"));
}
},
_ => {},
@@ -91,7 +91,7 @@ fn main() {
Some(("rename_lint", matches)) => {
let old_name = matches.get_one::<String>("old_name").unwrap();
let new_name = matches.get_one::<String>("new_name").unwrap_or(old_name);
- let uplift = matches.contains_id("uplift");
+ let uplift = matches.get_flag("uplift");
update_lints::rename(old_name, new_name, uplift);
},
Some(("deprecate", matches)) => {
@@ -110,24 +110,37 @@ fn get_clap_config() -> ArgMatches {
Command::new("bless").about("bless the test output changes").arg(
Arg::new("ignore-timestamp")
.long("ignore-timestamp")
+ .action(ArgAction::SetTrue)
.help("Include files updated before clippy was built"),
),
Command::new("dogfood").about("Runs the dogfood test").args([
- Arg::new("fix").long("fix").help("Apply the suggestions when possible"),
+ Arg::new("fix")
+ .long("fix")
+ .action(ArgAction::SetTrue)
+ .help("Apply the suggestions when possible"),
Arg::new("allow-dirty")
.long("allow-dirty")
+ .action(ArgAction::SetTrue)
.help("Fix code even if the working directory has changes")
.requires("fix"),
Arg::new("allow-staged")
.long("allow-staged")
+ .action(ArgAction::SetTrue)
.help("Fix code even if the working directory has staged changes")
.requires("fix"),
]),
Command::new("fmt")
.about("Run rustfmt on all projects and tests")
.args([
- Arg::new("check").long("check").help("Use the rustfmt --check option"),
- Arg::new("verbose").short('v').long("verbose").help("Echo commands run"),
+ Arg::new("check")
+ .long("check")
+ .action(ArgAction::SetTrue)
+ .help("Use the rustfmt --check option"),
+ Arg::new("verbose")
+ .short('v')
+ .long("verbose")
+ .action(ArgAction::SetTrue)
+ .help("Echo commands run"),
]),
Command::new("update_lints")
.about("Updates lint registration and information from the source code")
@@ -140,13 +153,17 @@ fn get_clap_config() -> ArgMatches {
* all lints are registered in the lint store",
)
.args([
- Arg::new("print-only").long("print-only").help(
- "Print a table of lints to STDOUT. \
- This does not include deprecated and internal lints. \
- (Does not modify any files)",
- ),
+ Arg::new("print-only")
+ .long("print-only")
+ .action(ArgAction::SetTrue)
+ .help(
+ "Print a table of lints to STDOUT. \
+ This does not include deprecated and internal lints. \
+ (Does not modify any files)",
+ ),
Arg::new("check")
.long("check")
+ .action(ArgAction::SetTrue)
.help("Checks that `cargo dev update_lints` has been run. Used on CI."),
]),
Command::new("new_lint")
@@ -156,15 +173,13 @@ fn get_clap_config() -> ArgMatches {
.short('p')
.long("pass")
.help("Specify whether the lint runs during the early or late pass")
- .takes_value(true)
- .value_parser([PossibleValue::new("early"), PossibleValue::new("late")])
+ .value_parser(["early", "late"])
.conflicts_with("type")
.required_unless_present("type"),
Arg::new("name")
.short('n')
.long("name")
.help("Name of the new lint in snake case, ex: fn_too_long")
- .takes_value(true)
.required(true),
Arg::new("category")
.short('c')
@@ -172,25 +187,23 @@ fn get_clap_config() -> ArgMatches {
.help("What category the lint belongs to")
.default_value("nursery")
.value_parser([
- PossibleValue::new("style"),
- PossibleValue::new("correctness"),
- PossibleValue::new("suspicious"),
- PossibleValue::new("complexity"),
- PossibleValue::new("perf"),
- PossibleValue::new("pedantic"),
- PossibleValue::new("restriction"),
- PossibleValue::new("cargo"),
- PossibleValue::new("nursery"),
- PossibleValue::new("internal"),
- PossibleValue::new("internal_warn"),
- ])
- .takes_value(true),
- Arg::new("type")
- .long("type")
- .help("What directory the lint belongs in")
- .takes_value(true)
- .required(false),
- Arg::new("msrv").long("msrv").help("Add MSRV config code to the lint"),
+ "style",
+ "correctness",
+ "suspicious",
+ "complexity",
+ "perf",
+ "pedantic",
+ "restriction",
+ "cargo",
+ "nursery",
+ "internal",
+ "internal_warn",
+ ]),
+ Arg::new("type").long("type").help("What directory the lint belongs in"),
+ Arg::new("msrv")
+ .long("msrv")
+ .action(ArgAction::SetTrue)
+ .help("Add MSRV config code to the lint"),
]),
Command::new("setup")
.about("Support for setting up your personal development environment")
@@ -201,13 +214,12 @@ fn get_clap_config() -> ArgMatches {
.args([
Arg::new("remove")
.long("remove")
- .help("Remove the dependencies added with 'cargo dev setup intellij'")
- .required(false),
+ .action(ArgAction::SetTrue)
+ .help("Remove the dependencies added with 'cargo dev setup intellij'"),
Arg::new("rustc-repo-path")
.long("repo-path")
.short('r')
.help("The path to a rustc repo that will be used for setting the dependencies")
- .takes_value(true)
.value_name("path")
.conflicts_with("remove")
.required(true),
@@ -217,26 +229,26 @@ fn get_clap_config() -> ArgMatches {
.args([
Arg::new("remove")
.long("remove")
- .help("Remove the pre-commit hook added with 'cargo dev setup git-hook'")
- .required(false),
+ .action(ArgAction::SetTrue)
+ .help("Remove the pre-commit hook added with 'cargo dev setup git-hook'"),
Arg::new("force-override")
.long("force-override")
.short('f')
- .help("Forces the override of an existing git pre-commit hook")
- .required(false),
+ .action(ArgAction::SetTrue)
+ .help("Forces the override of an existing git pre-commit hook"),
]),
Command::new("vscode-tasks")
.about("Add several tasks to vscode for formatting, validation and testing")
.args([
Arg::new("remove")
.long("remove")
- .help("Remove the tasks added with 'cargo dev setup vscode-tasks'")
- .required(false),
+ .action(ArgAction::SetTrue)
+ .help("Remove the tasks added with 'cargo dev setup vscode-tasks'"),
Arg::new("force-override")
.long("force-override")
.short('f')
- .help("Forces the override of existing vscode tasks")
- .required(false),
+ .action(ArgAction::SetTrue)
+ .help("Forces the override of existing vscode tasks"),
]),
]),
Command::new("remove")
@@ -295,6 +307,7 @@ fn get_clap_config() -> ArgMatches {
.help("The new name of the lint"),
Arg::new("uplift")
.long("uplift")
+ .action(ArgAction::SetTrue)
.help("This lint will be uplifted into rustc"),
]),
Command::new("deprecate").about("Deprecates the given lint").args([
@@ -305,8 +318,6 @@ fn get_clap_config() -> ArgMatches {
Arg::new("reason")
.long("reason")
.short('r')
- .required(false)
- .takes_value(true)
.help("The reason for deprecation"),
]),
])
diff --git a/src/tools/clippy/clippy_dev/src/new_lint.rs b/src/tools/clippy/clippy_dev/src/new_lint.rs
index ec7f1dd0d..420214d92 100644
--- a/src/tools/clippy/clippy_dev/src/new_lint.rs
+++ b/src/tools/clippy/clippy_dev/src/new_lint.rs
@@ -1,5 +1,6 @@
use crate::clippy_project_root;
use indoc::{formatdoc, writedoc};
+use std::fmt;
use std::fmt::Write as _;
use std::fs::{self, OpenOptions};
use std::io::prelude::*;
@@ -256,7 +257,7 @@ fn get_lint_file_contents(lint: &LintData<'_>, enable_msrv: bool) -> String {
)
});
- let _ = write!(result, "{}", get_lint_declaration(&name_upper, category));
+ let _: fmt::Result = write!(result, "{}", get_lint_declaration(&name_upper, category));
result.push_str(&if enable_msrv {
formatdoc!(
@@ -353,7 +354,7 @@ fn create_lint_for_ty(lint: &LintData<'_>, enable_msrv: bool, ty: &str) -> io::R
let mut lint_file_contents = String::new();
if enable_msrv {
- let _ = writedoc!(
+ let _: fmt::Result = writedoc!(
lint_file_contents,
r#"
use clippy_utils::msrvs::{{self, Msrv}};
@@ -373,7 +374,7 @@ fn create_lint_for_ty(lint: &LintData<'_>, enable_msrv: bool, ty: &str) -> io::R
name_upper = name_upper,
);
} else {
- let _ = writedoc!(
+ let _: fmt::Result = writedoc!(
lint_file_contents,
r#"
use rustc_lint::{{{context_import}, LintContext}};
@@ -521,7 +522,7 @@ fn setup_mod_file(path: &Path, lint: &LintData<'_>) -> io::Result<&'static str>
.chain(std::iter::once(&*lint_name_upper))
.filter(|s| !s.is_empty())
{
- let _ = write!(new_arr_content, "\n {ident},");
+ let _: fmt::Result = write!(new_arr_content, "\n {ident},");
}
new_arr_content.push('\n');
diff --git a/src/tools/clippy/clippy_dev/src/update_lints.rs b/src/tools/clippy/clippy_dev/src/update_lints.rs
index 837618c92..779e4d0e1 100644
--- a/src/tools/clippy/clippy_dev/src/update_lints.rs
+++ b/src/tools/clippy/clippy_dev/src/update_lints.rs
@@ -5,7 +5,7 @@ use itertools::Itertools;
use rustc_lexer::{tokenize, unescape, LiteralKind, TokenKind};
use std::collections::{HashMap, HashSet};
use std::ffi::OsStr;
-use std::fmt::Write;
+use std::fmt::{self, Write};
use std::fs::{self, OpenOptions};
use std::io::{self, Read, Seek, SeekFrom, Write as _};
use std::ops::Range;
@@ -691,7 +691,7 @@ fn gen_deprecated(lints: &[DeprecatedLint]) -> String {
let mut output = GENERATED_FILE_COMMENT.to_string();
output.push_str("{\n");
for lint in lints {
- let _ = write!(
+ let _: fmt::Result = write!(
output,
concat!(
" store.register_removed(\n",
@@ -726,7 +726,7 @@ fn gen_declared_lints<'a>(
if !is_public {
output.push_str(" #[cfg(feature = \"internal\")]\n");
}
- let _ = writeln!(output, " crate::{module_name}::{lint_name}_INFO,");
+ let _: fmt::Result = writeln!(output, " crate::{module_name}::{lint_name}_INFO,");
}
output.push_str("];\n");
diff --git a/src/tools/clippy/clippy_lints/Cargo.toml b/src/tools/clippy/clippy_lints/Cargo.toml
index a9f69b1ba..796f1ff16 100644
--- a/src/tools/clippy/clippy_lints/Cargo.toml
+++ b/src/tools/clippy/clippy_lints/Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "clippy_lints"
-version = "0.1.68"
+version = "0.1.69"
description = "A bunch of helpful lints to avoid common pitfalls in Rust"
repository = "https://github.com/rust-lang/rust-clippy"
readme = "README.md"
@@ -9,7 +9,7 @@ keywords = ["clippy", "lint", "plugin"]
edition = "2021"
[dependencies]
-cargo_metadata = "0.14"
+cargo_metadata = "0.15.3"
clippy_utils = { path = "../clippy_utils" }
declare_clippy_lint = { path = "../declare_clippy_lint" }
if_chain = "1.0"
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 82d368bb8..1d9096ea6 100644
--- a/src/tools/clippy/clippy_lints/src/bool_assert_comparison.rs
+++ b/src/tools/clippy/clippy_lints/src/bool_assert_comparison.rs
@@ -1,10 +1,12 @@
+use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::macros::{find_assert_eq_args, root_macro_call_first_node};
-use clippy_utils::{diagnostics::span_lint_and_sugg, ty::implements_trait};
+use clippy_utils::sugg::Sugg;
+use clippy_utils::ty::{implements_trait, is_copy};
use rustc_ast::ast::LitKind;
use rustc_errors::Applicability;
use rustc_hir::{Expr, ExprKind, Lit};
-use rustc_lint::{LateContext, LateLintPass};
-use rustc_middle::ty;
+use rustc_lint::{LateContext, LateLintPass, LintContext};
+use rustc_middle::ty::{self, Ty};
use rustc_session::{declare_lint_pass, declare_tool_lint};
use rustc_span::symbol::Ident;
@@ -33,19 +35,19 @@ declare_clippy_lint! {
declare_lint_pass!(BoolAssertComparison => [BOOL_ASSERT_COMPARISON]);
-fn is_bool_lit(e: &Expr<'_>) -> bool {
- matches!(
- e.kind,
- ExprKind::Lit(Lit {
- node: LitKind::Bool(_),
- ..
- })
- ) && !e.span.from_expansion()
+fn extract_bool_lit(e: &Expr<'_>) -> Option<bool> {
+ if let ExprKind::Lit(Lit {
+ node: LitKind::Bool(b), ..
+ }) = e.kind
+ && !e.span.from_expansion()
+ {
+ Some(b)
+ } else {
+ None
+ }
}
-fn is_impl_not_trait_with_bool_out(cx: &LateContext<'_>, e: &Expr<'_>) -> bool {
- let ty = cx.typeck_results().expr_ty(e);
-
+fn is_impl_not_trait_with_bool_out<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool {
cx.tcx
.lang_items()
.not_trait()
@@ -70,38 +72,70 @@ impl<'tcx> LateLintPass<'tcx> for BoolAssertComparison {
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
let Some(macro_call) = root_macro_call_first_node(cx, expr) else { return };
let macro_name = cx.tcx.item_name(macro_call.def_id);
- if !matches!(
- macro_name.as_str(),
- "assert_eq" | "debug_assert_eq" | "assert_ne" | "debug_assert_ne"
- ) {
- return;
- }
+ let eq_macro = match macro_name.as_str() {
+ "assert_eq" | "debug_assert_eq" => true,
+ "assert_ne" | "debug_assert_ne" => false,
+ _ => return,
+ };
let Some ((a, b, _)) = find_assert_eq_args(cx, expr, macro_call.expn) else { return };
- if !(is_bool_lit(a) ^ is_bool_lit(b)) {
+
+ let a_span = a.span.source_callsite();
+ let b_span = b.span.source_callsite();
+
+ let (lit_span, bool_value, non_lit_expr) = match (extract_bool_lit(a), extract_bool_lit(b)) {
+ // assert_eq!(true/false, b)
+ // ^^^^^^^^^^^^
+ (Some(bool_value), None) => (a_span.until(b_span), bool_value, b),
+ // assert_eq!(a, true/false)
+ // ^^^^^^^^^^^^
+ (None, Some(bool_value)) => (b_span.with_lo(a_span.hi()), bool_value, a),
// 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;
- }
+ _ => return,
+ };
+
+ let non_lit_ty = cx.typeck_results().expr_ty(non_lit_expr);
- if !is_impl_not_trait_with_bool_out(cx, a) || !is_impl_not_trait_with_bool_out(cx, b) {
+ if !is_impl_not_trait_with_bool_out(cx, non_lit_ty) {
// 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;
}
+ if !is_copy(cx, non_lit_ty) {
+ // Only lint with types that are `Copy` because `assert!(x)` takes
+ // ownership of `x` whereas `assert_eq(x, true)` does not
+ return;
+ }
+
let macro_name = macro_name.as_str();
let non_eq_mac = &macro_name[..macro_name.len() - 3];
- span_lint_and_sugg(
+ span_lint_and_then(
cx,
BOOL_ASSERT_COMPARISON,
macro_call.span,
&format!("used `{macro_name}!` with a literal bool"),
- "replace it with",
- format!("{non_eq_mac}!(..)"),
- Applicability::MaybeIncorrect,
+ |diag| {
+ // assert_eq!(...)
+ // ^^^^^^^^^
+ let name_span = cx.sess().source_map().span_until_char(macro_call.span, '!');
+
+ let mut suggestions = vec![(name_span, non_eq_mac.to_string()), (lit_span, String::new())];
+
+ if bool_value ^ eq_macro {
+ let Some(sugg) = Sugg::hir_opt(cx, non_lit_expr) else { return };
+ suggestions.push((non_lit_expr.span, (!sugg).to_string()));
+ }
+
+ diag.multipart_suggestion(
+ format!("replace it with `{non_eq_mac}!(..)`"),
+ suggestions,
+ Applicability::MachineApplicable,
+ );
+ },
);
}
}
diff --git a/src/tools/clippy/clippy_lints/src/booleans.rs b/src/tools/clippy/clippy_lints/src/booleans.rs
index 939bdbcdc..e8106beec 100644
--- a/src/tools/clippy/clippy_lints/src/booleans.rs
+++ b/src/tools/clippy/clippy_lints/src/booleans.rs
@@ -6,9 +6,10 @@ use if_chain::if_chain;
use rustc_ast::ast::LitKind;
use rustc_errors::Applicability;
use rustc_hir::intravisit::{walk_expr, FnKind, Visitor};
-use rustc_hir::{BinOpKind, Body, Expr, ExprKind, FnDecl, HirId, UnOp};
+use rustc_hir::{BinOpKind, Body, Expr, ExprKind, FnDecl, UnOp};
use rustc_lint::{LateContext, LateLintPass};
use rustc_session::{declare_lint_pass, declare_tool_lint};
+use rustc_span::def_id::LocalDefId;
use rustc_span::source_map::Span;
use rustc_span::sym;
@@ -82,7 +83,7 @@ impl<'tcx> LateLintPass<'tcx> for NonminimalBool {
_: &'tcx FnDecl<'_>,
body: &'tcx Body<'_>,
_: Span,
- _: HirId,
+ _: LocalDefId,
) {
NonminimalBoolVisitor { cx }.visit_body(body);
}
diff --git a/src/tools/clippy/clippy_lints/src/box_default.rs b/src/tools/clippy/clippy_lints/src/box_default.rs
index 9d98a6bab..dfa949d1a 100644
--- a/src/tools/clippy/clippy_lints/src/box_default.rs
+++ b/src/tools/clippy/clippy_lints/src/box_default.rs
@@ -117,7 +117,8 @@ fn given_type(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
) => {
if let Some(index) = args.iter().position(|arg| arg.hir_id == expr.hir_id) &&
let Some(sig) = expr_sig(cx, path) &&
- let Some(input) = sig.input(index)
+ let Some(input) = sig.input(index) &&
+ !cx.typeck_results().expr_ty_adjusted(expr).boxed_ty().is_trait()
{
input.no_bound_vars().is_some()
} else {
diff --git a/src/tools/clippy/clippy_lints/src/casts/as_ptr_cast_mut.rs b/src/tools/clippy/clippy_lints/src/casts/as_ptr_cast_mut.rs
index 9409f4844..1633ffd58 100644
--- a/src/tools/clippy/clippy_lints/src/casts/as_ptr_cast_mut.rs
+++ b/src/tools/clippy/clippy_lints/src/casts/as_ptr_cast_mut.rs
@@ -17,7 +17,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, cast_expr: &Expr<'_>,
&& let ExprKind::MethodCall(method_name, receiver, [], _) = cast_expr.peel_blocks().kind
&& method_name.ident.name == rustc_span::sym::as_ptr
&& let Some(as_ptr_did) = cx.typeck_results().type_dependent_def_id(cast_expr.peel_blocks().hir_id)
- && let as_ptr_sig = cx.tcx.fn_sig(as_ptr_did)
+ && let as_ptr_sig = cx.tcx.fn_sig(as_ptr_did).subst_identity()
&& let Some(first_param_ty) = as_ptr_sig.skip_binder().inputs().iter().next()
&& let ty::Ref(_, _, Mutability::Not) = first_param_ty.kind()
&& let Some(recv) = snippet_opt(cx, receiver.span)
diff --git a/src/tools/clippy/clippy_lints/src/casts/cast_possible_truncation.rs b/src/tools/clippy/clippy_lints/src/casts/cast_possible_truncation.rs
index a63764849..823970e35 100644
--- a/src/tools/clippy/clippy_lints/src/casts/cast_possible_truncation.rs
+++ b/src/tools/clippy/clippy_lints/src/casts/cast_possible_truncation.rs
@@ -1,11 +1,14 @@
use clippy_utils::consts::{constant, Constant};
-use clippy_utils::diagnostics::span_lint;
+use clippy_utils::diagnostics::{span_lint, span_lint_and_then};
use clippy_utils::expr_or_init;
+use clippy_utils::source::snippet;
use clippy_utils::ty::{get_discriminant_value, is_isize_or_usize};
+use rustc_errors::{Applicability, SuggestionStyle};
use rustc_hir::def::{DefKind, Res};
use rustc_hir::{BinOpKind, Expr, ExprKind};
use rustc_lint::LateContext;
use rustc_middle::ty::{self, FloatTy, Ty};
+use rustc_span::Span;
use rustc_target::abi::IntegerType;
use super::{utils, CAST_ENUM_TRUNCATION, CAST_POSSIBLE_TRUNCATION};
@@ -74,7 +77,14 @@ fn apply_reductions(cx: &LateContext<'_>, nbits: u64, expr: &Expr<'_>, signed: b
}
}
-pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, cast_expr: &Expr<'_>, cast_from: Ty<'_>, cast_to: Ty<'_>) {
+pub(super) fn check(
+ cx: &LateContext<'_>,
+ expr: &Expr<'_>,
+ cast_expr: &Expr<'_>,
+ cast_from: Ty<'_>,
+ cast_to: Ty<'_>,
+ cast_to_span: Span,
+) {
let msg = match (cast_from.kind(), cast_to.is_integral()) {
(ty::Int(_) | ty::Uint(_), true) => {
let from_nbits = apply_reductions(
@@ -139,7 +149,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, cast_expr: &Expr<'_>,
);
return;
}
- format!("casting `{cast_from}` to `{cast_to}` may truncate the value{suffix}",)
+ format!("casting `{cast_from}` to `{cast_to}` may truncate the value{suffix}")
},
(ty::Float(_), true) => {
@@ -153,5 +163,19 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, cast_expr: &Expr<'_>,
_ => return,
};
- span_lint(cx, CAST_POSSIBLE_TRUNCATION, expr.span, &msg);
+ let name_of_cast_from = snippet(cx, cast_expr.span, "..");
+ let cast_to_snip = snippet(cx, cast_to_span, "..");
+ let suggestion = format!("{cast_to_snip}::try_from({name_of_cast_from})");
+
+ span_lint_and_then(cx, CAST_POSSIBLE_TRUNCATION, expr.span, &msg, |diag| {
+ diag.help("if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ...");
+ diag.span_suggestion_with_style(
+ expr.span,
+ "... or use `try_from` and handle the error accordingly",
+ suggestion,
+ Applicability::Unspecified,
+ // always show the suggestion in a separate line
+ SuggestionStyle::ShowAlways,
+ );
+ });
}
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 97054a0d1..6c8ee296c 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
@@ -66,7 +66,7 @@ fn is_used_as_unaligned(cx: &LateContext<'_>, e: &Expr<'_>) -> bool {
if matches!(name.ident.as_str(), "read_unaligned" | "write_unaligned")
&& let Some(def_id) = cx.typeck_results().type_dependent_def_id(parent.hir_id)
&& let Some(def_id) = cx.tcx.impl_of_method(def_id)
- && cx.tcx.type_of(def_id).is_unsafe_ptr()
+ && cx.tcx.type_of(def_id).subst_identity().is_unsafe_ptr()
{
true
} else {
diff --git a/src/tools/clippy/clippy_lints/src/casts/mod.rs b/src/tools/clippy/clippy_lints/src/casts/mod.rs
index 161e3a698..362f70d12 100644
--- a/src/tools/clippy/clippy_lints/src/casts/mod.rs
+++ b/src/tools/clippy/clippy_lints/src/casts/mod.rs
@@ -80,7 +80,8 @@ declare_clippy_lint! {
/// ### What it does
/// Checks for casts between numerical types that may
/// truncate large values. This is expected behavior, so the cast is `Allow` by
- /// default.
+ /// default. It suggests user either explicitly ignore the lint,
+ /// or use `try_from()` and handle the truncation, default, or panic explicitly.
///
/// ### Why is this bad?
/// In some problem domains, it is good practice to avoid
@@ -93,6 +94,21 @@ declare_clippy_lint! {
/// x as u8
/// }
/// ```
+ /// Use instead:
+ /// ```
+ /// fn as_u8(x: u64) -> u8 {
+ /// if let Ok(x) = u8::try_from(x) {
+ /// x
+ /// } else {
+ /// todo!();
+ /// }
+ /// }
+ /// // Or
+ /// #[allow(clippy::cast_possible_truncation)]
+ /// fn as_u16(x: u64) -> u16 {
+ /// x as u16
+ /// }
+ /// ```
#[clippy::version = "pre 1.29.0"]
pub CAST_POSSIBLE_TRUNCATION,
pedantic,
@@ -712,7 +728,7 @@ impl<'tcx> LateLintPass<'tcx> for Casts {
fn_to_numeric_cast_with_truncation::check(cx, expr, cast_expr, cast_from, cast_to);
if cast_to.is_numeric() && !in_external_macro(cx.sess(), expr.span) {
- cast_possible_truncation::check(cx, expr, cast_expr, cast_from, cast_to);
+ cast_possible_truncation::check(cx, expr, cast_expr, cast_from, cast_to, cast_to_hir.span);
if cast_from.is_numeric() {
cast_possible_wrap::check(cx, expr, cast_from, cast_to);
cast_precision_loss::check(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 1c3a89a97..e8531157e 100644
--- a/src/tools/clippy/clippy_lints/src/cognitive_complexity.rs
+++ b/src/tools/clippy/clippy_lints/src/cognitive_complexity.rs
@@ -8,9 +8,10 @@ use clippy_utils::{get_async_fn_body, is_async_fn, LimitStack};
use core::ops::ControlFlow;
use rustc_ast::ast::Attribute;
use rustc_hir::intravisit::FnKind;
-use rustc_hir::{Body, Expr, ExprKind, FnDecl, HirId};
+use rustc_hir::{Body, Expr, ExprKind, FnDecl};
use rustc_lint::{LateContext, LateLintPass, LintContext};
use rustc_session::{declare_tool_lint, impl_lint_pass};
+use rustc_span::def_id::LocalDefId;
use rustc_span::source_map::Span;
use rustc_span::{sym, BytePos};
@@ -140,9 +141,8 @@ impl<'tcx> LateLintPass<'tcx> for CognitiveComplexity {
decl: &'tcx FnDecl<'_>,
body: &'tcx Body<'_>,
span: Span,
- hir_id: HirId,
+ def_id: LocalDefId,
) {
- let def_id = cx.tcx.hir().local_def_id(hir_id);
if !cx.tcx.has_attr(def_id.to_def_id(), sym::test) {
let expr = if is_async_fn(kind) {
match get_async_fn_body(cx.tcx, body) {
diff --git a/src/tools/clippy/clippy_lints/src/copy_iterator.rs b/src/tools/clippy/clippy_lints/src/copy_iterator.rs
index e38f77268..0fc115232 100644
--- a/src/tools/clippy/clippy_lints/src/copy_iterator.rs
+++ b/src/tools/clippy/clippy_lints/src/copy_iterator.rs
@@ -43,7 +43,7 @@ impl<'tcx> LateLintPass<'tcx> for CopyIterator {
of_trait: Some(ref trait_ref),
..
}) = item.kind;
- let ty = cx.tcx.type_of(item.owner_id);
+ let ty = cx.tcx.type_of(item.owner_id).subst_identity();
if is_copy(cx, ty);
if let Some(trait_id) = trait_ref.trait_def_id();
if cx.tcx.is_diagnostic_item(sym::Iterator, trait_id);
diff --git a/src/tools/clippy/clippy_lints/src/declared_lints.rs b/src/tools/clippy/clippy_lints/src/declared_lints.rs
index 91ca73633..cd5dd7a57 100644
--- a/src/tools/clippy/clippy_lints/src/declared_lints.rs
+++ b/src/tools/clippy/clippy_lints/src/declared_lints.rs
@@ -156,6 +156,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[
crate::exhaustive_items::EXHAUSTIVE_STRUCTS_INFO,
crate::exit::EXIT_INFO,
crate::explicit_write::EXPLICIT_WRITE_INFO,
+ crate::extra_unused_type_parameters::EXTRA_UNUSED_TYPE_PARAMETERS_INFO,
crate::fallible_impl_from::FALLIBLE_IMPL_FROM_INFO,
crate::float_literal::EXCESSIVE_PRECISION_INFO,
crate::float_literal::LOSSY_FLOAT_LITERAL_INFO,
@@ -178,6 +179,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[
crate::from_raw_with_void_ptr::FROM_RAW_WITH_VOID_PTR_INFO,
crate::from_str_radix_10::FROM_STR_RADIX_10_INFO,
crate::functions::DOUBLE_MUST_USE_INFO,
+ crate::functions::IMPL_TRAIT_IN_PARAMS_INFO,
crate::functions::MISNAMED_GETTERS_INFO,
crate::functions::MUST_USE_CANDIDATE_INFO,
crate::functions::MUST_USE_UNIT_INFO,
@@ -223,6 +225,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[
crate::let_underscore::LET_UNDERSCORE_FUTURE_INFO,
crate::let_underscore::LET_UNDERSCORE_LOCK_INFO,
crate::let_underscore::LET_UNDERSCORE_MUST_USE_INFO,
+ crate::let_underscore::LET_UNDERSCORE_UNTYPED_INFO,
crate::lifetimes::EXTRA_UNUSED_LIFETIMES_INFO,
crate::lifetimes::NEEDLESS_LIFETIMES_INFO,
crate::literal_representation::DECIMAL_LITERAL_REPRESENTATION_INFO,
@@ -377,6 +380,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[
crate::methods::SKIP_WHILE_NEXT_INFO,
crate::methods::STABLE_SORT_PRIMITIVE_INFO,
crate::methods::STRING_EXTEND_CHARS_INFO,
+ crate::methods::SUSPICIOUS_COMMAND_ARG_SPACE_INFO,
crate::methods::SUSPICIOUS_MAP_INFO,
crate::methods::SUSPICIOUS_SPLITN_INFO,
crate::methods::SUSPICIOUS_TO_OWNED_INFO,
@@ -422,6 +426,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[
crate::module_style::MOD_MODULE_FILES_INFO,
crate::module_style::SELF_NAMED_MODULE_FILES_INFO,
crate::multi_assignments::MULTI_ASSIGNMENTS_INFO,
+ crate::multiple_unsafe_ops_per_block::MULTIPLE_UNSAFE_OPS_PER_BLOCK_INFO,
crate::mut_key::MUTABLE_KEY_TYPE_INFO,
crate::mut_mut::MUT_MUT_INFO,
crate::mut_reference::UNNECESSARY_MUT_PASSED_INFO,
@@ -445,6 +450,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[
crate::no_effect::NO_EFFECT_INFO,
crate::no_effect::NO_EFFECT_UNDERSCORE_BINDING_INFO,
crate::no_effect::UNNECESSARY_OPERATION_INFO,
+ crate::no_mangle_with_rust_abi::NO_MANGLE_WITH_RUST_ABI_INFO,
crate::non_copy_const::BORROW_INTERIOR_MUTABLE_CONST_INFO,
crate::non_copy_const::DECLARE_INTERIOR_MUTABLE_CONST_INFO,
crate::non_expressive_names::JUST_UNDERSCORES_AND_DIGITS_INFO,
@@ -504,6 +510,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[
crate::ptr_offset_with_cast::PTR_OFFSET_WITH_CAST_INFO,
crate::pub_use::PUB_USE_INFO,
crate::question_mark::QUESTION_MARK_INFO,
+ crate::question_mark_used::QUESTION_MARK_USED_INFO,
crate::ranges::MANUAL_RANGE_CONTAINS_INFO,
crate::ranges::RANGE_MINUS_ONE_INFO,
crate::ranges::RANGE_PLUS_ONE_INFO,
@@ -534,6 +541,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[
crate::shadow::SHADOW_REUSE_INFO,
crate::shadow::SHADOW_SAME_INFO,
crate::shadow::SHADOW_UNRELATED_INFO,
+ crate::significant_drop_tightening::SIGNIFICANT_DROP_TIGHTENING_INFO,
crate::single_char_lifetime_names::SINGLE_CHAR_LIFETIME_NAMES_INFO,
crate::single_component_path_imports::SINGLE_COMPONENT_PATH_IMPORTS_INFO,
crate::size_of_in_element_count::SIZE_OF_IN_ELEMENT_COUNT_INFO,
@@ -571,6 +579,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[
crate::transmute::TRANSMUTE_INT_TO_BOOL_INFO,
crate::transmute::TRANSMUTE_INT_TO_CHAR_INFO,
crate::transmute::TRANSMUTE_INT_TO_FLOAT_INFO,
+ crate::transmute::TRANSMUTE_INT_TO_NON_ZERO_INFO,
crate::transmute::TRANSMUTE_NULL_TO_FN_INFO,
crate::transmute::TRANSMUTE_NUM_TO_BYTES_INFO,
crate::transmute::TRANSMUTE_PTR_TO_PTR_INFO,
diff --git a/src/tools/clippy/clippy_lints/src/default.rs b/src/tools/clippy/clippy_lints/src/default.rs
index a04693f46..080d44e63 100644
--- a/src/tools/clippy/clippy_lints/src/default.rs
+++ b/src/tools/clippy/clippy_lints/src/default.rs
@@ -150,7 +150,7 @@ impl<'tcx> LateLintPass<'tcx> for Default {
.fields
.iter()
.all(|field| {
- is_copy(cx, cx.tcx.type_of(field.did))
+ is_copy(cx, cx.tcx.type_of(field.did).subst_identity())
});
if !has_drop(cx, binding_type) || all_fields_are_copy;
then {
diff --git a/src/tools/clippy/clippy_lints/src/default_numeric_fallback.rs b/src/tools/clippy/clippy_lints/src/default_numeric_fallback.rs
index 03460689e..4e1a6cd4d 100644
--- a/src/tools/clippy/clippy_lints/src/default_numeric_fallback.rs
+++ b/src/tools/clippy/clippy_lints/src/default_numeric_fallback.rs
@@ -141,7 +141,7 @@ impl<'a, 'tcx> Visitor<'tcx> for NumericFallbackVisitor<'a, 'tcx> {
ExprKind::MethodCall(_, receiver, args, _) => {
if let Some(def_id) = self.cx.typeck_results().type_dependent_def_id(expr.hir_id) {
- let fn_sig = self.cx.tcx.fn_sig(def_id).skip_binder();
+ let fn_sig = self.cx.tcx.fn_sig(def_id).subst_identity().skip_binder();
for (expr, bound) in iter::zip(std::iter::once(*receiver).chain(args.iter()), fn_sig.inputs()) {
self.ty_bounds.push((*bound).into());
self.visit_expr(expr);
@@ -167,7 +167,7 @@ impl<'a, 'tcx> Visitor<'tcx> for NumericFallbackVisitor<'a, 'tcx> {
.iter()
.find_map(|f_def| {
if f_def.ident(self.cx.tcx) == field.ident
- { Some(self.cx.tcx.type_of(f_def.did)) }
+ { Some(self.cx.tcx.type_of(f_def.did).subst_identity()) }
else { None }
});
self.ty_bounds.push(bound.into());
@@ -215,7 +215,7 @@ fn fn_sig_opt<'tcx>(cx: &LateContext<'tcx>, hir_id: HirId) -> Option<PolyFnSig<'
let node_ty = cx.typeck_results().node_type_opt(hir_id)?;
// We can't use `Ty::fn_sig` because it automatically performs substs, this may result in FNs.
match node_ty.kind() {
- ty::FnDef(def_id, _) => Some(cx.tcx.fn_sig(*def_id)),
+ ty::FnDef(def_id, _) => Some(cx.tcx.fn_sig(*def_id).subst_identity()),
ty::FnPtr(fn_sig) => Some(*fn_sig),
_ => None,
}
diff --git a/src/tools/clippy/clippy_lints/src/dereference.rs b/src/tools/clippy/clippy_lints/src/dereference.rs
index 05f2b92c0..7f3f26bed 100644
--- a/src/tools/clippy/clippy_lints/src/dereference.rs
+++ b/src/tools/clippy/clippy_lints/src/dereference.rs
@@ -3,7 +3,7 @@ use clippy_utils::mir::{enclosing_mir, expr_local, local_assignments, used_exact
use clippy_utils::msrvs::{self, Msrv};
use clippy_utils::source::{snippet_with_applicability, snippet_with_context};
use clippy_utils::sugg::has_enclosing_paren;
-use clippy_utils::ty::{expr_sig, is_copy, peel_mid_ty_refs, ty_sig, variant_of_res};
+use clippy_utils::ty::{adt_and_variant_of_res, expr_sig, is_copy, peel_mid_ty_refs, ty_sig};
use clippy_utils::{
fn_def_id, get_parent_expr, get_parent_expr_for_hir, is_lint_allowed, path_to_local, walk_to_expr_usage,
};
@@ -26,8 +26,8 @@ use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::mir::{Rvalue, StatementKind};
use rustc_middle::ty::adjustment::{Adjust, Adjustment, AutoBorrow, AutoBorrowMutability};
use rustc_middle::ty::{
- self, Binder, BoundVariableKind, Clause, EarlyBinder, FnSig, GenericArgKind, List, ParamTy, PredicateKind,
- ProjectionPredicate, Ty, TyCtxt, TypeVisitable, TypeckResults,
+ self, Binder, BoundVariableKind, Clause, EarlyBinder, FnSig, GenericArgKind, List, ParamEnv, ParamTy,
+ PredicateKind, ProjectionPredicate, Ty, TyCtxt, TypeVisitableExt, TypeckResults,
};
use rustc_session::{declare_tool_lint, impl_lint_pass};
use rustc_span::{symbol::sym, Span, Symbol};
@@ -735,8 +735,8 @@ fn walk_parents<'tcx>(
span,
..
}) if span.ctxt() == ctxt => {
- let ty = cx.tcx.type_of(owner_id.def_id);
- Some(ty_auto_deref_stability(cx, ty, precedence).position_for_result(cx))
+ let ty = cx.tcx.type_of(owner_id.def_id).subst_identity();
+ Some(ty_auto_deref_stability(cx.tcx, cx.param_env, ty, precedence).position_for_result(cx))
},
Node::Item(&Item {
@@ -759,8 +759,8 @@ fn walk_parents<'tcx>(
}) if span.ctxt() == ctxt => {
let output = cx
.tcx
- .erase_late_bound_regions(cx.tcx.fn_sig(owner_id.to_def_id()).output());
- Some(ty_auto_deref_stability(cx, output, precedence).position_for_result(cx))
+ .erase_late_bound_regions(cx.tcx.fn_sig(owner_id).subst_identity().output());
+ Some(ty_auto_deref_stability(cx.tcx, cx.param_env, output, precedence).position_for_result(cx))
},
Node::ExprField(field) if field.span.ctxt() == ctxt => match get_parent_expr_for_hir(cx, field.hir_id) {
@@ -768,31 +768,44 @@ fn walk_parents<'tcx>(
hir_id,
kind: ExprKind::Struct(path, ..),
..
- }) => variant_of_res(cx, cx.qpath_res(path, *hir_id))
- .and_then(|variant| variant.fields.iter().find(|f| f.name == field.ident.name))
- .map(|field_def| {
- ty_auto_deref_stability(cx, cx.tcx.type_of(field_def.did), precedence).position_for_arg()
+ }) => adt_and_variant_of_res(cx, cx.qpath_res(path, *hir_id))
+ .and_then(|(adt, variant)| {
+ variant
+ .fields
+ .iter()
+ .find(|f| f.name == field.ident.name)
+ .map(|f| (adt, f))
+ })
+ .map(|(adt, field_def)| {
+ ty_auto_deref_stability(
+ cx.tcx,
+ // Use the param_env of the target type.
+ cx.tcx.param_env(adt.did()),
+ cx.tcx.type_of(field_def.did).subst_identity(),
+ precedence,
+ )
+ .position_for_arg()
}),
_ => None,
},
Node::Expr(parent) if parent.span.ctxt() == ctxt => match parent.kind {
ExprKind::Ret(_) => {
- let owner_id = cx.tcx.hir().body_owner(cx.enclosing_body.unwrap());
+ let owner_id = cx.tcx.hir().body_owner_def_id(cx.enclosing_body.unwrap());
Some(
if let Node::Expr(
closure_expr @ Expr {
kind: ExprKind::Closure(closure),
..
},
- ) = cx.tcx.hir().get(owner_id)
+ ) = cx.tcx.hir().get_by_def_id(owner_id)
{
closure_result_position(cx, closure, cx.typeck_results().expr_ty(closure_expr), precedence)
} else {
let output = cx
.tcx
- .erase_late_bound_regions(cx.tcx.fn_sig(cx.tcx.hir().local_def_id(owner_id)).output());
- ty_auto_deref_stability(cx, output, precedence).position_for_result(cx)
+ .erase_late_bound_regions(cx.tcx.fn_sig(owner_id).subst_identity().output());
+ ty_auto_deref_stability(cx.tcx, cx.param_env, output, precedence).position_for_result(cx)
},
)
},
@@ -835,15 +848,20 @@ fn walk_parents<'tcx>(
msrv,
)
} else {
- ty_auto_deref_stability(cx, cx.tcx.erase_late_bound_regions(ty), precedence)
- .position_for_arg()
+ ty_auto_deref_stability(
+ cx.tcx,
+ // Use the param_env of the target function.
+ sig.predicates_id().map_or(ParamEnv::empty(), |id| cx.tcx.param_env(id)),
+ cx.tcx.erase_late_bound_regions(ty),
+ precedence
+ ).position_for_arg()
}
},
}
})
}),
ExprKind::MethodCall(method, receiver, args, _) => {
- let id = cx.typeck_results().type_dependent_def_id(parent.hir_id).unwrap();
+ let fn_id = cx.typeck_results().type_dependent_def_id(parent.hir_id).unwrap();
if receiver.hir_id == child_id {
// Check for calls to trait methods where the trait is implemented on a reference.
// Two cases need to be handled:
@@ -852,13 +870,17 @@ fn walk_parents<'tcx>(
// priority.
if e.hir_id != child_id {
return Some(Position::ReborrowStable(precedence))
- } else if let Some(trait_id) = cx.tcx.trait_of_item(id)
+ } else if let Some(trait_id) = cx.tcx.trait_of_item(fn_id)
&& let arg_ty = cx.tcx.erase_regions(cx.typeck_results().expr_ty_adjusted(e))
&& let ty::Ref(_, sub_ty, _) = *arg_ty.kind()
&& let subs = cx
.typeck_results()
.node_substs_opt(parent.hir_id).map(|subs| &subs[1..]).unwrap_or_default()
- && let impl_ty = if cx.tcx.fn_sig(id).skip_binder().inputs()[0].is_ref() {
+ && let impl_ty = if cx.tcx.fn_sig(fn_id)
+ .subst_identity()
+ .skip_binder()
+ .inputs()[0].is_ref()
+ {
// Trait methods taking `&self`
sub_ty
} else {
@@ -879,10 +901,13 @@ fn walk_parents<'tcx>(
return Some(Position::MethodReceiver);
}
args.iter().position(|arg| arg.hir_id == child_id).map(|i| {
- let ty = cx.tcx.fn_sig(id).skip_binder().inputs()[i + 1];
+ let ty = cx.tcx.fn_sig(fn_id).subst_identity().input(i + 1);
// `e.hir_id == child_id` for https://github.com/rust-lang/rust-clippy/issues/9739
// `method.args.is_none()` for https://github.com/rust-lang/rust-clippy/issues/9782
- if e.hir_id == child_id && method.args.is_none() && let ty::Param(param_ty) = ty.kind() {
+ if e.hir_id == child_id
+ && method.args.is_none()
+ && let ty::Param(param_ty) = ty.skip_binder().kind()
+ {
needless_borrow_impl_arg_position(
cx,
possible_borrowers,
@@ -895,8 +920,10 @@ fn walk_parents<'tcx>(
)
} else {
ty_auto_deref_stability(
- cx,
- cx.tcx.erase_late_bound_regions(cx.tcx.fn_sig(id).input(i + 1)),
+ cx.tcx,
+ // Use the param_env of the target function.
+ cx.tcx.param_env(fn_id),
+ cx.tcx.erase_late_bound_regions(ty),
precedence,
)
.position_for_arg()
@@ -1022,7 +1049,7 @@ fn binding_ty_auto_deref_stability<'tcx>(
))
.is_sized(cx.tcx, cx.param_env.without_caller_bounds()),
),
- TyKind::OpaqueDef(..) | TyKind::Infer | TyKind::Typeof(..) | TyKind::TraitObject(..) | TyKind::Err => {
+ TyKind::OpaqueDef(..) | TyKind::Infer | TyKind::Typeof(..) | TyKind::TraitObject(..) | TyKind::Err(_) => {
Position::ReborrowStable(precedence)
},
};
@@ -1038,7 +1065,7 @@ fn ty_contains_infer(ty: &hir::Ty<'_>) -> bool {
if self.0
|| matches!(
ty.kind,
- TyKind::OpaqueDef(..) | TyKind::Infer | TyKind::Typeof(_) | TyKind::Err
+ TyKind::OpaqueDef(..) | TyKind::Infer | TyKind::Typeof(_) | TyKind::Err(_)
)
{
self.0 = true;
@@ -1093,7 +1120,7 @@ fn needless_borrow_impl_arg_position<'tcx>(
let sized_trait_def_id = cx.tcx.lang_items().sized_trait();
let Some(callee_def_id) = fn_def_id(cx, parent) else { return Position::Other(precedence) };
- let fn_sig = cx.tcx.fn_sig(callee_def_id).skip_binder();
+ let fn_sig = cx.tcx.fn_sig(callee_def_id).subst_identity().skip_binder();
let substs_with_expr_ty = cx
.typeck_results()
.node_substs(if let ExprKind::Call(callee, _) = parent.kind {
@@ -1221,7 +1248,7 @@ fn has_ref_mut_self_method(cx: &LateContext<'_>, trait_def_id: DefId) -> bool {
.in_definition_order()
.any(|assoc_item| {
if assoc_item.fn_has_self_parameter {
- let self_ty = cx.tcx.fn_sig(assoc_item.def_id).skip_binder().inputs()[0];
+ let self_ty = cx.tcx.fn_sig(assoc_item.def_id).subst_identity().skip_binder().inputs()[0];
matches!(self_ty.kind(), ty::Ref(_, _, Mutability::Mut))
} else {
false
@@ -1330,10 +1357,10 @@ fn replace_types<'tcx>(
&& let Some(term_ty) = projection_predicate.term.ty()
&& let ty::Param(term_param_ty) = term_ty.kind()
{
- let item_def_id = projection_predicate.projection_ty.def_id;
- let assoc_item = cx.tcx.associated_item(item_def_id);
- let projection = cx.tcx
- .mk_projection(assoc_item.def_id, cx.tcx.mk_substs_trait(new_ty, []));
+ let projection = cx.tcx.mk_ty_from_kind(ty::Alias(
+ ty::Projection,
+ projection_predicate.projection_ty.with_self_ty(cx.tcx, new_ty),
+ ));
if let Ok(projected_ty) = cx.tcx.try_normalize_erasing_regions(cx.param_env, projection)
&& substs[term_param_ty.index as usize] != ty::GenericArg::from(projected_ty)
@@ -1378,11 +1405,18 @@ impl<'tcx> TyPosition<'tcx> {
}
// Checks whether a type is stable when switching to auto dereferencing,
-fn ty_auto_deref_stability<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>, precedence: i8) -> TyPosition<'tcx> {
+fn ty_auto_deref_stability<'tcx>(
+ tcx: TyCtxt<'tcx>,
+ param_env: ParamEnv<'tcx>,
+ ty: Ty<'tcx>,
+ precedence: i8,
+) -> TyPosition<'tcx> {
let ty::Ref(_, mut ty, _) = *ty.kind() else {
return Position::Other(precedence).into();
};
+ ty = tcx.try_normalize_erasing_regions(param_env, ty).unwrap_or(ty);
+
loop {
break match *ty.kind() {
ty::Ref(_, ref_ty, _) => {
@@ -1419,12 +1453,11 @@ fn ty_auto_deref_stability<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>, precedenc
| ty::FnDef(..)
| ty::Generator(..)
| ty::GeneratorWitness(..)
+ | ty::GeneratorWitnessMIR(..)
| ty::Closure(..)
| ty::Never
| ty::Tuple(_)
- | ty::Alias(ty::Projection, _) => {
- Position::DerefStable(precedence, ty.is_sized(cx.tcx, cx.param_env.without_caller_bounds())).into()
- },
+ | ty::Alias(ty::Projection, _) => Position::DerefStable(precedence, ty.is_sized(tcx, param_env)).into(),
};
}
}
diff --git a/src/tools/clippy/clippy_lints/src/derivable_impls.rs b/src/tools/clippy/clippy_lints/src/derivable_impls.rs
index bc18e2e5e..f95b8ccf0 100644
--- a/src/tools/clippy/clippy_lints/src/derivable_impls.rs
+++ b/src/tools/clippy/clippy_lints/src/derivable_impls.rs
@@ -184,7 +184,7 @@ impl<'tcx> LateLintPass<'tcx> for DerivableImpls {
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.owner_id).ty_adt_def();
+ if let Some(adt_def) = cx.tcx.type_of(item.owner_id).subst_identity().ty_adt_def();
if let attrs = cx.tcx.hir().attrs(item.hir_id());
if !attrs.iter().any(|attr| attr.doc_str().is_some());
if let child_attrs = cx.tcx.hir().attrs(impl_item_hir);
diff --git a/src/tools/clippy/clippy_lints/src/derive.rs b/src/tools/clippy/clippy_lints/src/derive.rs
index 248d73884..b8428d66a 100644
--- a/src/tools/clippy/clippy_lints/src/derive.rs
+++ b/src/tools/clippy/clippy_lints/src/derive.rs
@@ -7,7 +7,7 @@ use rustc_errors::Applicability;
use rustc_hir::def_id::DefId;
use rustc_hir::intravisit::{walk_expr, walk_fn, walk_item, FnKind, Visitor};
use rustc_hir::{
- self as hir, BlockCheckMode, BodyId, Constness, Expr, ExprKind, FnDecl, HirId, Impl, Item, ItemKind, UnsafeSource,
+ self as hir, BlockCheckMode, BodyId, Constness, Expr, ExprKind, FnDecl, Impl, Item, ItemKind, UnsafeSource,
Unsafety,
};
use rustc_lint::{LateContext, LateLintPass};
@@ -18,6 +18,7 @@ use rustc_middle::ty::{
TraitPredicate, Ty, TyCtxt,
};
use rustc_session::{declare_lint_pass, declare_tool_lint};
+use rustc_span::def_id::LocalDefId;
use rustc_span::source_map::Span;
use rustc_span::sym;
@@ -210,7 +211,7 @@ impl<'tcx> LateLintPass<'tcx> for Derive {
..
}) = item.kind
{
- let ty = cx.tcx.type_of(item.owner_id);
+ let ty = cx.tcx.type_of(item.owner_id).subst_identity();
let is_automatically_derived = cx.tcx.has_attr(item.owner_id.to_def_id(), sym::automatically_derived);
check_hash_peq(cx, item.span, trait_ref, ty, is_automatically_derived);
@@ -346,7 +347,7 @@ fn check_copy_clone<'tcx>(cx: &LateContext<'tcx>, item: &Item<'_>, trait_ref: &h
let has_copy_impl = cx.tcx.all_local_trait_impls(()).get(&copy_id).map_or(false, |impls| {
impls
.iter()
- .any(|&id| matches!(cx.tcx.type_of(id).kind(), ty::Adt(adt, _) if ty_adt.did() == adt.did()))
+ .any(|&id| matches!(cx.tcx.type_of(id).subst_identity().kind(), ty::Adt(adt, _) if ty_adt.did() == adt.did()))
});
if !has_copy_impl {
return;
@@ -425,7 +426,7 @@ struct UnsafeVisitor<'a, 'tcx> {
impl<'tcx> Visitor<'tcx> for UnsafeVisitor<'_, 'tcx> {
type NestedFilter = nested_filter::All;
- fn visit_fn(&mut self, kind: FnKind<'tcx>, decl: &'tcx FnDecl<'_>, body_id: BodyId, _: Span, id: HirId) {
+ fn visit_fn(&mut self, kind: FnKind<'tcx>, decl: &'tcx FnDecl<'_>, body_id: BodyId, _: Span, id: LocalDefId) {
if self.has_unsafe {
return;
}
@@ -513,7 +514,7 @@ fn param_env_for_derived_eq(tcx: TyCtxt<'_>, did: DefId, eq_trait_id: DefId) ->
}
ParamEnv::new(
- tcx.mk_predicates(ty_predicates.iter().map(|&(p, _)| p).chain(
+ tcx.mk_predicates_from_iter(ty_predicates.iter().map(|&(p, _)| p).chain(
params.iter().filter(|&&(_, needs_eq)| needs_eq).map(|&(param, _)| {
tcx.mk_predicate(Binder::dummy(PredicateKind::Clause(Clause::Trait(TraitPredicate {
trait_ref: tcx.mk_trait_ref(eq_trait_id, [tcx.mk_param_from_def(param)]),
diff --git a/src/tools/clippy/clippy_lints/src/doc.rs b/src/tools/clippy/clippy_lints/src/doc.rs
index cdc23a4d2..384aca7fe 100644
--- a/src/tools/clippy/clippy_lints/src/doc.rs
+++ b/src/tools/clippy/clippy_lints/src/doc.rs
@@ -6,12 +6,17 @@ use clippy_utils::ty::{implements_trait, is_type_diagnostic_item};
use clippy_utils::{is_entrypoint_fn, method_chain_args, return_ty};
use if_chain::if_chain;
use itertools::Itertools;
+use pulldown_cmark::Event::{
+ Code, End, FootnoteReference, HardBreak, Html, Rule, SoftBreak, Start, TaskListMarker, Text,
+};
+use pulldown_cmark::Tag::{CodeBlock, Heading, Item, Link, Paragraph};
+use pulldown_cmark::{BrokenLink, CodeBlockKind, CowStr, Options};
use rustc_ast::ast::{Async, AttrKind, Attribute, Fn, FnRetTy, ItemKind};
use rustc_ast::token::CommentKind;
use rustc_data_structures::fx::FxHashSet;
use rustc_data_structures::sync::Lrc;
use rustc_errors::emitter::EmitterWriter;
-use rustc_errors::{Applicability, Handler, SuggestionStyle};
+use rustc_errors::{Applicability, Handler, SuggestionStyle, TerminalUrl};
use rustc_hir as hir;
use rustc_hir::intravisit::{self, Visitor};
use rustc_hir::{AnonConst, Expr};
@@ -23,7 +28,6 @@ use rustc_parse::maybe_new_parser_from_source_str;
use rustc_parse::parser::ForceCollect;
use rustc_session::parse::ParseSess;
use rustc_session::{declare_tool_lint, impl_lint_pass};
-use rustc_span::def_id::LocalDefId;
use rustc_span::edition::Edition;
use rustc_span::source_map::{BytePos, FilePathMapping, SourceMap, Span};
use rustc_span::{sym, FileName, Pos};
@@ -251,7 +255,7 @@ declare_clippy_lint! {
/// unimplemented!();
/// }
/// ```
- #[clippy::version = "1.66.0"]
+ #[clippy::version = "1.67.0"]
pub UNNECESSARY_SAFETY_DOC,
restriction,
"`pub fn` or `pub trait` with `# Safety` docs"
@@ -302,7 +306,7 @@ impl<'tcx> LateLintPass<'tcx> for DocMarkdown {
panic_span: None,
};
fpu.visit_expr(body.value);
- lint_for_missing_headers(cx, item.owner_id.def_id, sig, headers, Some(body_id), fpu.panic_span);
+ lint_for_missing_headers(cx, item.owner_id, sig, headers, Some(body_id), fpu.panic_span);
}
},
hir::ItemKind::Impl(impl_) => {
@@ -338,7 +342,7 @@ impl<'tcx> LateLintPass<'tcx> for DocMarkdown {
let Some(headers) = check_attrs(cx, &self.valid_idents, attrs) else { return };
if let hir::TraitItemKind::Fn(ref sig, ..) = item.kind {
if !in_external_macro(cx.tcx.sess, item.span) {
- lint_for_missing_headers(cx, item.owner_id.def_id, sig, headers, None, None);
+ lint_for_missing_headers(cx, item.owner_id, sig, headers, None, None);
}
}
}
@@ -357,20 +361,20 @@ impl<'tcx> LateLintPass<'tcx> for DocMarkdown {
panic_span: None,
};
fpu.visit_expr(body.value);
- lint_for_missing_headers(cx, item.owner_id.def_id, sig, headers, Some(body_id), fpu.panic_span);
+ lint_for_missing_headers(cx, item.owner_id, sig, headers, Some(body_id), fpu.panic_span);
}
}
}
fn lint_for_missing_headers(
cx: &LateContext<'_>,
- def_id: LocalDefId,
+ owner_id: hir::OwnerId,
sig: &hir::FnSig<'_>,
headers: DocHeaders,
body_id: Option<hir::BodyId>,
panic_span: Option<Span>,
) {
- if !cx.effective_visibilities.is_exported(def_id) {
+ if !cx.effective_visibilities.is_exported(owner_id.def_id) {
return; // Private functions do not require doc comments
}
@@ -378,13 +382,13 @@ fn lint_for_missing_headers(
if cx
.tcx
.hir()
- .parent_iter(cx.tcx.hir().local_def_id_to_hir_id(def_id))
+ .parent_iter(owner_id.into())
.any(|(id, _node)| is_doc_hidden(cx.tcx.hir().attrs(id)))
{
return;
}
- let span = cx.tcx.def_span(def_id);
+ let span = cx.tcx.def_span(owner_id);
match (headers.safety, sig.header.unsafety) {
(false, hir::Unsafety::Unsafe) => span_lint(
cx,
@@ -411,8 +415,7 @@ fn lint_for_missing_headers(
);
}
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) {
+ if is_type_diagnostic_item(cx, return_ty(cx, owner_id), sym::Result) {
span_lint(
cx,
MISSING_ERRORS_DOC,
@@ -499,7 +502,6 @@ struct DocHeaders {
}
fn check_attrs(cx: &LateContext<'_>, valid_idents: &FxHashSet<String>, attrs: &[Attribute]) -> Option<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.
@@ -540,8 +542,6 @@ fn check_attrs(cx: &LateContext<'_>, valid_idents: &FxHashSet<String>, attrs: &[
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;
-
let previous_range = previous.1;
let current_range = current.1;
@@ -566,12 +566,6 @@ fn check_doc<'a, Events: Iterator<Item = (pulldown_cmark::Event<'a>, Range<usize
spans: &[(usize, Span)],
) -> DocHeaders {
// true if a safety header was found
- use pulldown_cmark::Event::{
- Code, End, FootnoteReference, HardBreak, Html, Rule, SoftBreak, Start, TaskListMarker, Text,
- };
- use pulldown_cmark::Tag::{CodeBlock, Heading, Item, Link, Paragraph};
- use pulldown_cmark::{CodeBlockKind, CowStr};
-
let mut headers = DocHeaders::default();
let mut in_code = false;
let mut in_link = None;
@@ -662,6 +656,12 @@ fn check_doc<'a, Events: Iterator<Item = (pulldown_cmark::Event<'a>, Range<usize
check_link_quotes(cx, in_link.is_some(), trimmed_text, span, &range, begin, text.len());
// Adjust for the beginning of the current `Event`
let span = span.with_lo(span.lo() + BytePos::from_usize(range.start - begin));
+ if let Some(link) = in_link.as_ref()
+ && let Ok(url) = Url::parse(link)
+ && (url.scheme() == "https" || url.scheme() == "http") {
+ // Don't check the text associated with external URLs
+ continue;
+ }
text_to_check.push((text, span));
}
},
@@ -707,7 +707,7 @@ fn check_code(cx: &LateContext<'_>, text: &str, edition: Edition, span: Span) {
let sm = Lrc::new(SourceMap::new(FilePathMapping::empty()));
let fallback_bundle =
- rustc_errors::fallback_fluent_bundle(rustc_errors::DEFAULT_LOCALE_RESOURCES, false);
+ rustc_errors::fallback_fluent_bundle(rustc_driver::DEFAULT_LOCALE_RESOURCES.to_vec(), false);
let emitter = EmitterWriter::new(
Box::new(io::sink()),
None,
@@ -719,6 +719,7 @@ fn check_code(cx: &LateContext<'_>, text: &str, edition: Edition, span: Span) {
None,
false,
false,
+ TerminalUrl::No,
);
let handler = Handler::with_emitter(false, None, Box::new(emitter));
let sess = ParseSess::with_span_handler(handler, sm);
diff --git a/src/tools/clippy/clippy_lints/src/empty_enum.rs b/src/tools/clippy/clippy_lints/src/empty_enum.rs
index 0570c2a10..d94664daa 100644
--- a/src/tools/clippy/clippy_lints/src/empty_enum.rs
+++ b/src/tools/clippy/clippy_lints/src/empty_enum.rs
@@ -49,7 +49,7 @@ impl<'tcx> LateLintPass<'tcx> for EmptyEnum {
}
if let ItemKind::Enum(..) = item.kind {
- let ty = cx.tcx.type_of(item.owner_id);
+ let ty = cx.tcx.type_of(item.owner_id).subst_identity();
let adt = ty.ty_adt_def().expect("already checked whether this is an enum");
if adt.variants().is_empty() {
span_lint_and_help(
diff --git a/src/tools/clippy/clippy_lints/src/entry.rs b/src/tools/clippy/clippy_lints/src/entry.rs
index b44e62435..48a54f602 100644
--- a/src/tools/clippy/clippy_lints/src/entry.rs
+++ b/src/tools/clippy/clippy_lints/src/entry.rs
@@ -6,7 +6,7 @@ use clippy_utils::{
source::{reindent_multiline, snippet_indent, snippet_with_applicability, snippet_with_context},
SpanlessEq,
};
-use core::fmt::Write;
+use core::fmt::{self, Write};
use rustc_errors::Applicability;
use rustc_hir::{
hir_id::HirIdSet,
@@ -65,6 +65,10 @@ declare_lint_pass!(HashMapPass => [MAP_ENTRY]);
impl<'tcx> LateLintPass<'tcx> for HashMapPass {
#[expect(clippy::too_many_lines)]
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
+ if expr.span.from_expansion() {
+ return;
+ }
+
let Some(higher::If { cond: cond_expr, then: then_expr, r#else: else_expr }) = higher::If::hir(expr) else {
return
};
@@ -532,7 +536,7 @@ impl<'tcx> InsertSearchResults<'tcx> {
if is_expr_used_or_unified(cx.tcx, insertion.call) {
write_wrapped(&mut res, insertion, ctxt, app);
} else {
- let _ = write!(
+ let _: fmt::Result = write!(
res,
"e.insert({})",
snippet_with_context(cx, insertion.value.span, ctxt, "..", app).0
@@ -548,7 +552,7 @@ impl<'tcx> InsertSearchResults<'tcx> {
(
self.snippet(cx, span, app, |res, insertion, ctxt, app| {
// Insertion into a map would return `Some(&mut value)`, but the entry returns `&mut value`
- let _ = write!(
+ let _: fmt::Result = write!(
res,
"Some(e.insert({}))",
snippet_with_context(cx, insertion.value.span, ctxt, "..", app).0
@@ -562,7 +566,7 @@ impl<'tcx> InsertSearchResults<'tcx> {
(
self.snippet(cx, span, app, |res, insertion, ctxt, app| {
// Insertion into a map would return `None`, but the entry returns a mutable reference.
- let _ = if is_expr_final_block_expr(cx.tcx, insertion.call) {
+ let _: fmt::Result = if is_expr_final_block_expr(cx.tcx, insertion.call) {
write!(
res,
"e.insert({});\n{}None",
diff --git a/src/tools/clippy/clippy_lints/src/enum_clike.rs b/src/tools/clippy/clippy_lints/src/enum_clike.rs
index da6788882..e275efaba 100644
--- a/src/tools/clippy/clippy_lints/src/enum_clike.rs
+++ b/src/tools/clippy/clippy_lints/src/enum_clike.rs
@@ -45,7 +45,7 @@ impl<'tcx> LateLintPass<'tcx> for UnportableVariant {
for var in def.variants {
if let Some(anon_const) = &var.disr_expr {
let def_id = cx.tcx.hir().body_owner_def_id(anon_const.body);
- let mut ty = cx.tcx.type_of(def_id.to_def_id());
+ let mut ty = cx.tcx.type_of(def_id.to_def_id()).subst_identity();
let constant = cx
.tcx
.const_eval_poly(def_id.to_def_id())
diff --git a/src/tools/clippy/clippy_lints/src/enum_variants.rs b/src/tools/clippy/clippy_lints/src/enum_variants.rs
index b77b5621b..4c69dacf3 100644
--- a/src/tools/clippy/clippy_lints/src/enum_variants.rs
+++ b/src/tools/clippy/clippy_lints/src/enum_variants.rs
@@ -277,7 +277,7 @@ impl LateLintPass<'_> for EnumVariantNames {
Some(c) if is_word_beginning(c) => span_lint(
cx,
MODULE_NAME_REPETITIONS,
- item.span,
+ item.ident.span,
"item name starts with its containing module's name",
),
_ => (),
@@ -287,7 +287,7 @@ impl LateLintPass<'_> for EnumVariantNames {
span_lint(
cx,
MODULE_NAME_REPETITIONS,
- item.span,
+ item.ident.span,
"item name ends with its containing module's name",
);
}
diff --git a/src/tools/clippy/clippy_lints/src/escape.rs b/src/tools/clippy/clippy_lints/src/escape.rs
index dfb438933..d6ab4c25e 100644
--- a/src/tools/clippy/clippy_lints/src/escape.rs
+++ b/src/tools/clippy/clippy_lints/src/escape.rs
@@ -8,6 +8,7 @@ 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::def_id::LocalDefId;
use rustc_span::source_map::Span;
use rustc_span::symbol::kw;
use rustc_target::spec::abi::Abi;
@@ -63,7 +64,7 @@ impl<'tcx> LateLintPass<'tcx> for BoxedLocal {
_: &'tcx FnDecl<'_>,
body: &'tcx Body<'_>,
_: Span,
- hir_id: HirId,
+ fn_def_id: LocalDefId,
) {
if let Some(header) = fn_kind.header() {
if header.abi != Abi::Rust {
@@ -71,7 +72,11 @@ impl<'tcx> LateLintPass<'tcx> for BoxedLocal {
}
}
- let parent_id = cx.tcx.hir().get_parent_item(hir_id).def_id;
+ let parent_id = cx
+ .tcx
+ .hir()
+ .get_parent_item(cx.tcx.hir().local_def_id_to_hir_id(fn_def_id))
+ .def_id;
let parent_node = cx.tcx.hir().find_by_def_id(parent_id);
let mut trait_self_ty = None;
@@ -84,7 +89,7 @@ impl<'tcx> LateLintPass<'tcx> for BoxedLocal {
// find `self` ty for this trait if relevant
if let ItemKind::Trait(_, _, _, _, items) = item.kind {
for trait_item in items {
- if trait_item.id.hir_id() == hir_id {
+ if trait_item.id.owner_id.def_id == fn_def_id {
// be sure we have `self` parameter in this function
if trait_item.kind == (AssocItemKind::Fn { has_self: true }) {
trait_self_ty = Some(
@@ -105,7 +110,6 @@ impl<'tcx> LateLintPass<'tcx> for BoxedLocal {
too_large_for_stack: self.too_large_for_stack,
};
- let fn_def_id = cx.tcx.hir().local_def_id(hir_id);
let infcx = cx.tcx.infer_ctxt().build();
ExprUseVisitor::new(&mut v, &infcx, fn_def_id, cx.param_env, cx.typeck_results()).consume_body(body);
diff --git a/src/tools/clippy/clippy_lints/src/eta_reduction.rs b/src/tools/clippy/clippy_lints/src/eta_reduction.rs
index 3543910c3..b2071f4dc 100644
--- a/src/tools/clippy/clippy_lints/src/eta_reduction.rs
+++ b/src/tools/clippy/clippy_lints/src/eta_reduction.rs
@@ -11,7 +11,7 @@ use rustc_hir::{Closure, Expr, ExprKind, Param, PatKind, Unsafety};
use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::ty::adjustment::{Adjust, Adjustment, AutoBorrow};
use rustc_middle::ty::binding::BindingMode;
-use rustc_middle::ty::{self, EarlyBinder, SubstsRef, Ty, TypeVisitable};
+use rustc_middle::ty::{self, EarlyBinder, SubstsRef, Ty, TypeVisitableExt};
use rustc_session::{declare_lint_pass, declare_tool_lint};
use rustc_span::symbol::sym;
@@ -108,7 +108,7 @@ impl<'tcx> LateLintPass<'tcx> for EtaReduction {
if check_inputs(cx, body.params, None, 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));
+ .map_or(callee_ty, |id| cx.tcx.type_of(id).subst_identity());
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
@@ -153,7 +153,7 @@ impl<'tcx> LateLintPass<'tcx> for EtaReduction {
if check_inputs(cx, body.params, Some(receiver), 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.bound_type_of(method_def_id).subst(cx.tcx, substs);
+ 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_then(cx, REDUNDANT_CLOSURE_FOR_METHOD_CALLS, expr.span, "redundant closure", |diag| {
@@ -233,7 +233,7 @@ fn get_ufcs_type_name<'tcx>(cx: &LateContext<'tcx>, method_def_id: DefId, substs
match assoc_item.container {
ty::TraitContainer => cx.tcx.def_path_str(def_id),
ty::ImplContainer => {
- let ty = cx.tcx.type_of(def_id);
+ let ty = cx.tcx.type_of(def_id).skip_binder();
match ty.kind() {
ty::Adt(adt, _) => cx.tcx.def_path_str(adt.did()),
ty::Array(..)
diff --git a/src/tools/clippy/clippy_lints/src/excessive_bools.rs b/src/tools/clippy/clippy_lints/src/excessive_bools.rs
index fc2912f69..aef2db385 100644
--- a/src/tools/clippy/clippy_lints/src/excessive_bools.rs
+++ b/src/tools/clippy/clippy_lints/src/excessive_bools.rs
@@ -1,9 +1,10 @@
use clippy_utils::diagnostics::span_lint_and_help;
use clippy_utils::{get_parent_as_impl, has_repr_attr, is_bool};
use rustc_hir::intravisit::FnKind;
-use rustc_hir::{Body, FnDecl, HirId, Item, ItemKind, TraitFn, TraitItem, TraitItemKind, Ty};
+use rustc_hir::{Body, FnDecl, Item, ItemKind, TraitFn, TraitItem, TraitItemKind, Ty};
use rustc_lint::{LateContext, LateLintPass};
use rustc_session::{declare_tool_lint, impl_lint_pass};
+use rustc_span::def_id::LocalDefId;
use rustc_span::Span;
use rustc_target::spec::abi::Abi;
@@ -168,8 +169,9 @@ impl<'tcx> LateLintPass<'tcx> for ExcessiveBools {
fn_decl: &'tcx FnDecl<'tcx>,
_: &'tcx Body<'tcx>,
span: Span,
- hir_id: HirId,
+ def_id: LocalDefId,
) {
+ let hir_id = cx.tcx.hir().local_def_id_to_hir_id(def_id);
if let Some(fn_header) = fn_kind.header()
&& fn_header.abi == Abi::Rust
&& get_parent_as_impl(cx.tcx, hir_id)
diff --git a/src/tools/clippy/clippy_lints/src/exhaustive_items.rs b/src/tools/clippy/clippy_lints/src/exhaustive_items.rs
index 1fece5d1c..9fd13084d 100644
--- a/src/tools/clippy/clippy_lints/src/exhaustive_items.rs
+++ b/src/tools/clippy/clippy_lints/src/exhaustive_items.rs
@@ -79,8 +79,7 @@ impl LateLintPass<'_> for ExhaustiveItems {
then {
let (lint, msg) = if let ItemKind::Struct(ref v, ..) = item.kind {
if v.fields().iter().any(|f| {
- let def_id = cx.tcx.hir().local_def_id(f.hir_id);
- !cx.tcx.visibility(def_id).is_public()
+ !cx.tcx.visibility(f.def_id).is_public()
}) {
// skip structs with private fields
return;
diff --git a/src/tools/clippy/clippy_lints/src/extra_unused_type_parameters.rs b/src/tools/clippy/clippy_lints/src/extra_unused_type_parameters.rs
new file mode 100644
index 000000000..20565e1d2
--- /dev/null
+++ b/src/tools/clippy/clippy_lints/src/extra_unused_type_parameters.rs
@@ -0,0 +1,229 @@
+use clippy_utils::diagnostics::span_lint_and_help;
+use clippy_utils::trait_ref_of_method;
+use rustc_data_structures::fx::FxHashMap;
+use rustc_errors::MultiSpan;
+use rustc_hir::intravisit::{walk_impl_item, walk_item, walk_param_bound, walk_ty, Visitor};
+use rustc_hir::{
+ BodyId, ExprKind, GenericBound, GenericParamKind, Generics, ImplItem, ImplItemKind, Item, ItemKind,
+ PredicateOrigin, Ty, TyKind, WherePredicate,
+};
+use rustc_lint::{LateContext, LateLintPass, LintContext};
+use rustc_middle::hir::nested_filter;
+use rustc_middle::lint::in_external_macro;
+use rustc_session::{declare_tool_lint, impl_lint_pass};
+use rustc_span::{
+ def_id::{DefId, LocalDefId},
+ Span,
+};
+
+declare_clippy_lint! {
+ /// ### What it does
+ /// Checks for type parameters in generics that are never used anywhere else.
+ ///
+ /// ### Why is this bad?
+ /// Functions cannot infer the value of unused type parameters; therefore, calling them
+ /// requires using a turbofish, which serves no purpose but to satisfy the compiler.
+ ///
+ /// ### Example
+ /// ```rust
+ /// fn unused_ty<T>(x: u8) {
+ /// // ..
+ /// }
+ /// ```
+ /// Use instead:
+ /// ```rust
+ /// fn no_unused_ty(x: u8) {
+ /// // ..
+ /// }
+ /// ```
+ #[clippy::version = "1.69.0"]
+ pub EXTRA_UNUSED_TYPE_PARAMETERS,
+ complexity,
+ "unused type parameters in function definitions"
+}
+
+pub struct ExtraUnusedTypeParameters {
+ avoid_breaking_exported_api: bool,
+}
+
+impl ExtraUnusedTypeParameters {
+ pub fn new(avoid_breaking_exported_api: bool) -> Self {
+ Self {
+ avoid_breaking_exported_api,
+ }
+ }
+
+ /// Don't lint external macros or functions with empty bodies. Also, don't lint public items if
+ /// the `avoid_breaking_exported_api` config option is set.
+ fn check_false_positive(&self, cx: &LateContext<'_>, span: Span, def_id: LocalDefId, body_id: BodyId) -> bool {
+ let body = cx.tcx.hir().body(body_id).value;
+ let fn_empty = matches!(&body.kind, ExprKind::Block(blk, None) if blk.stmts.is_empty() && blk.expr.is_none());
+ let is_exported = cx.effective_visibilities.is_exported(def_id);
+ in_external_macro(cx.sess(), span) || (self.avoid_breaking_exported_api && is_exported) || fn_empty
+ }
+}
+
+impl_lint_pass!(ExtraUnusedTypeParameters => [EXTRA_UNUSED_TYPE_PARAMETERS]);
+
+/// A visitor struct that walks a given function and gathers generic type parameters, plus any
+/// trait bounds those parameters have.
+struct TypeWalker<'cx, 'tcx> {
+ cx: &'cx LateContext<'tcx>,
+ /// Collection of all the function's type parameters.
+ ty_params: FxHashMap<DefId, Span>,
+ /// Collection of any (inline) trait bounds corresponding to each type parameter.
+ bounds: FxHashMap<DefId, Span>,
+ /// The entire `Generics` object of the function, useful for querying purposes.
+ generics: &'tcx Generics<'tcx>,
+ /// The value of this will remain `true` if *every* parameter:
+ /// 1. Is a type parameter, and
+ /// 2. Goes unused in the function.
+ /// Otherwise, if any type parameters end up being used, or if any lifetime or const-generic
+ /// parameters are present, this will be set to `false`.
+ all_params_unused: bool,
+}
+
+impl<'cx, 'tcx> TypeWalker<'cx, 'tcx> {
+ fn new(cx: &'cx LateContext<'tcx>, generics: &'tcx Generics<'tcx>) -> Self {
+ let mut all_params_unused = true;
+ let ty_params = generics
+ .params
+ .iter()
+ .filter_map(|param| {
+ if let GenericParamKind::Type { synthetic, .. } = param.kind {
+ (!synthetic).then_some((param.def_id.into(), param.span))
+ } else {
+ if !param.is_elided_lifetime() {
+ all_params_unused = false;
+ }
+ None
+ }
+ })
+ .collect();
+
+ Self {
+ cx,
+ ty_params,
+ bounds: FxHashMap::default(),
+ generics,
+ all_params_unused,
+ }
+ }
+
+ fn mark_param_used(&mut self, def_id: DefId) {
+ if self.ty_params.remove(&def_id).is_some() {
+ self.all_params_unused = false;
+ }
+ }
+
+ fn emit_lint(&self) {
+ let (msg, help) = match self.ty_params.len() {
+ 0 => return,
+ 1 => (
+ "type parameter goes unused in function definition",
+ "consider removing the parameter",
+ ),
+ _ => (
+ "type parameters go unused in function definition",
+ "consider removing the parameters",
+ ),
+ };
+
+ let source_map = self.cx.sess().source_map();
+ let span = if self.all_params_unused {
+ self.generics.span.into() // Remove the entire list of generics
+ } else {
+ MultiSpan::from_spans(
+ self.ty_params
+ .iter()
+ .map(|(def_id, &span)| {
+ // Extend the span past any trait bounds, and include the comma at the end.
+ let span_to_extend = self.bounds.get(def_id).copied().map_or(span, Span::shrink_to_hi);
+ let comma_range = source_map.span_extend_to_next_char(span_to_extend, '>', false);
+ let comma_span = source_map.span_through_char(comma_range, ',');
+ span.with_hi(comma_span.hi())
+ })
+ .collect(),
+ )
+ };
+
+ span_lint_and_help(self.cx, EXTRA_UNUSED_TYPE_PARAMETERS, span, msg, None, help);
+ }
+}
+
+/// Given a generic bound, if the bound is for a trait that's not a `LangItem`, return the
+/// `LocalDefId` for that trait.
+fn bound_to_trait_def_id(bound: &GenericBound<'_>) -> Option<LocalDefId> {
+ bound.trait_ref()?.trait_def_id()?.as_local()
+}
+
+impl<'cx, 'tcx> Visitor<'tcx> for TypeWalker<'cx, 'tcx> {
+ type NestedFilter = nested_filter::OnlyBodies;
+
+ fn visit_ty(&mut self, t: &'tcx Ty<'tcx>) {
+ if let Some((def_id, _)) = t.peel_refs().as_generic_param() {
+ self.mark_param_used(def_id);
+ } else if let TyKind::OpaqueDef(id, _, _) = t.kind {
+ // Explicitly walk OpaqueDef. Normally `walk_ty` would do the job, but it calls
+ // `visit_nested_item`, which checks that `Self::NestedFilter::INTER` is set. We're
+ // using `OnlyBodies`, so the check ends up failing and the type isn't fully walked.
+ let item = self.nested_visit_map().item(id);
+ walk_item(self, item);
+ } else {
+ walk_ty(self, t);
+ }
+ }
+
+ fn visit_where_predicate(&mut self, predicate: &'tcx WherePredicate<'tcx>) {
+ if let WherePredicate::BoundPredicate(predicate) = predicate {
+ // Collect spans for any bounds on type parameters. We only keep bounds that appear in
+ // the list of generics (not in a where-clause).
+ if let Some((def_id, _)) = predicate.bounded_ty.peel_refs().as_generic_param() {
+ // If the bound contains non-public traits, err on the safe side and don't lint the
+ // corresponding parameter.
+ if !predicate
+ .bounds
+ .iter()
+ .filter_map(bound_to_trait_def_id)
+ .all(|id| self.cx.effective_visibilities.is_exported(id))
+ {
+ self.mark_param_used(def_id);
+ } else if let PredicateOrigin::GenericParam = predicate.origin {
+ self.bounds.insert(def_id, predicate.span);
+ }
+ }
+ // Only walk the right-hand side of where-bounds
+ for bound in predicate.bounds {
+ walk_param_bound(self, bound);
+ }
+ }
+ }
+
+ fn nested_visit_map(&mut self) -> Self::Map {
+ self.cx.tcx.hir()
+ }
+}
+
+impl<'tcx> LateLintPass<'tcx> for ExtraUnusedTypeParameters {
+ fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'tcx>) {
+ if let ItemKind::Fn(_, generics, body_id) = item.kind
+ && !self.check_false_positive(cx, item.span, item.owner_id.def_id, body_id)
+ {
+ let mut walker = TypeWalker::new(cx, generics);
+ walk_item(&mut walker, item);
+ walker.emit_lint();
+ }
+ }
+
+ fn check_impl_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx ImplItem<'tcx>) {
+ // Only lint on inherent methods, not trait methods.
+ if let ImplItemKind::Fn(.., body_id) = item.kind
+ && trait_ref_of_method(cx, item.owner_id.def_id).is_none()
+ && !self.check_false_positive(cx, item.span, item.owner_id.def_id, body_id)
+ {
+ let mut walker = TypeWalker::new(cx, item.generics);
+ walk_impl_item(&mut walker, item);
+ walker.emit_lint();
+ }
+ }
+}
diff --git a/src/tools/clippy/clippy_lints/src/format_args.rs b/src/tools/clippy/clippy_lints/src/format_args.rs
index 04e6949e1..c511d85e9 100644
--- a/src/tools/clippy/clippy_lints/src/format_args.rs
+++ b/src/tools/clippy/clippy_lints/src/format_args.rs
@@ -7,14 +7,14 @@ use clippy_utils::macros::{
};
use clippy_utils::msrvs::{self, Msrv};
use clippy_utils::source::snippet_opt;
-use clippy_utils::ty::{implements_trait, is_type_diagnostic_item};
+use clippy_utils::ty::{implements_trait, is_type_lang_item};
use if_chain::if_chain;
use itertools::Itertools;
use rustc_errors::{
Applicability,
SuggestionStyle::{CompletelyHidden, ShowCode},
};
-use rustc_hir::{Expr, ExprKind, HirId, QPath};
+use rustc_hir::{Expr, ExprKind, HirId, LangItem, QPath};
use rustc_lint::{LateContext, LateLintPass, LintContext};
use rustc_middle::ty::adjustment::{Adjust, Adjustment};
use rustc_middle::ty::Ty;
@@ -237,7 +237,7 @@ fn check_unused_format_specifier(cx: &LateContext<'_>, arg: &FormatArg<'_>) {
);
}
- if is_type_diagnostic_item(cx, param_ty, sym::Arguments) && !arg.format.is_default_for_trait() {
+ if is_type_lang_item(cx, param_ty, LangItem::FormatArguments) && !arg.format.is_default_for_trait() {
span_lint_and_then(
cx,
UNUSED_FORMAT_SPECS,
@@ -311,6 +311,10 @@ fn check_uninlined_args(
// in those cases, make the code suggestion hidden
let multiline_fix = fixes.iter().any(|(span, _)| cx.sess().source_map().is_multiline(*span));
+ // Suggest removing each argument only once, for example in `format!("{0} {0}", arg)`.
+ fixes.sort_unstable_by_key(|(span, _)| *span);
+ fixes.dedup_by_key(|(span, _)| *span);
+
span_lint_and_then(
cx,
UNINLINED_FORMAT_ARGS,
@@ -336,6 +340,7 @@ fn check_one_arg(
if matches!(param.kind, Implicit | Starred | Named(_) | Numbered)
&& let ExprKind::Path(QPath::Resolved(None, path)) = param.value.kind
&& let [segment] = path.segments
+ && segment.args.is_none()
&& let Some(arg_span) = args.value_with_prev_comma_span(param.value.hir_id)
{
let replacement = match param.usage {
diff --git a/src/tools/clippy/clippy_lints/src/from_raw_with_void_ptr.rs b/src/tools/clippy/clippy_lints/src/from_raw_with_void_ptr.rs
index 00f5ba564..096508dc4 100644
--- a/src/tools/clippy/clippy_lints/src/from_raw_with_void_ptr.rs
+++ b/src/tools/clippy/clippy_lints/src/from_raw_with_void_ptr.rs
@@ -31,7 +31,7 @@ declare_clippy_lint! {
/// let _ = unsafe { Box::from_raw(ptr as *mut usize) };
/// ```
///
- #[clippy::version = "1.66.0"]
+ #[clippy::version = "1.67.0"]
pub FROM_RAW_WITH_VOID_PTR,
suspicious,
"creating a `Box` from a void raw pointer"
diff --git a/src/tools/clippy/clippy_lints/src/functions/impl_trait_in_params.rs b/src/tools/clippy/clippy_lints/src/functions/impl_trait_in_params.rs
new file mode 100644
index 000000000..2811a73f6
--- /dev/null
+++ b/src/tools/clippy/clippy_lints/src/functions/impl_trait_in_params.rs
@@ -0,0 +1,50 @@
+use clippy_utils::{diagnostics::span_lint_and_then, is_in_test_function};
+
+use rustc_hir::{intravisit::FnKind, Body, HirId};
+use rustc_lint::LateContext;
+use rustc_span::Span;
+
+use super::IMPL_TRAIT_IN_PARAMS;
+
+pub(super) fn check_fn<'tcx>(cx: &LateContext<'_>, kind: &'tcx FnKind<'_>, body: &'tcx Body<'_>, hir_id: HirId) {
+ if cx.tcx.visibility(cx.tcx.hir().body_owner_def_id(body.id())).is_public() && !is_in_test_function(cx.tcx, hir_id)
+ {
+ if let FnKind::ItemFn(ident, generics, _) = kind {
+ for param in generics.params {
+ if param.is_impl_trait() {
+ // No generics with nested generics, and no generics like FnMut(x)
+ span_lint_and_then(
+ cx,
+ IMPL_TRAIT_IN_PARAMS,
+ param.span,
+ "'`impl Trait` used as a function parameter'",
+ |diag| {
+ if let Some(gen_span) = generics.span_for_param_suggestion() {
+ diag.span_suggestion_with_style(
+ gen_span,
+ "add a type paremeter",
+ format!(", {{ /* Generic name */ }}: {}", &param.name.ident().as_str()[5..]),
+ rustc_errors::Applicability::HasPlaceholders,
+ rustc_errors::SuggestionStyle::ShowAlways,
+ );
+ } else {
+ diag.span_suggestion_with_style(
+ Span::new(
+ body.params[0].span.lo() - rustc_span::BytePos(1),
+ ident.span.hi(),
+ ident.span.ctxt(),
+ ident.span.parent(),
+ ),
+ "add a type paremeter",
+ format!("<{{ /* Generic name */ }}: {}>", &param.name.ident().as_str()[5..]),
+ rustc_errors::Applicability::HasPlaceholders,
+ rustc_errors::SuggestionStyle::ShowAlways,
+ );
+ }
+ },
+ );
+ }
+ }
+ }
+ }
+}
diff --git a/src/tools/clippy/clippy_lints/src/functions/misnamed_getters.rs b/src/tools/clippy/clippy_lints/src/functions/misnamed_getters.rs
index 27acad45c..8b53ee68e 100644
--- a/src/tools/clippy/clippy_lints/src/functions/misnamed_getters.rs
+++ b/src/tools/clippy/clippy_lints/src/functions/misnamed_getters.rs
@@ -1,7 +1,7 @@
use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::source::snippet;
use rustc_errors::Applicability;
-use rustc_hir::{intravisit::FnKind, Body, ExprKind, FnDecl, HirId, ImplicitSelfKind, Unsafety};
+use rustc_hir::{intravisit::FnKind, Body, ExprKind, FnDecl, ImplicitSelfKind, Unsafety};
use rustc_lint::LateContext;
use rustc_middle::ty;
use rustc_span::Span;
@@ -10,14 +10,7 @@ use std::iter;
use super::MISNAMED_GETTERS;
-pub fn check_fn(
- cx: &LateContext<'_>,
- kind: FnKind<'_>,
- decl: &FnDecl<'_>,
- body: &Body<'_>,
- span: Span,
- _hir_id: HirId,
-) {
+pub fn check_fn(cx: &LateContext<'_>, kind: FnKind<'_>, decl: &FnDecl<'_>, body: &Body<'_>, span: Span) {
let FnKind::Method(ref ident, sig) = kind else {
return;
};
diff --git a/src/tools/clippy/clippy_lints/src/functions/mod.rs b/src/tools/clippy/clippy_lints/src/functions/mod.rs
index 9dbce3f88..d2852b4ac 100644
--- a/src/tools/clippy/clippy_lints/src/functions/mod.rs
+++ b/src/tools/clippy/clippy_lints/src/functions/mod.rs
@@ -1,3 +1,4 @@
+mod impl_trait_in_params;
mod misnamed_getters;
mod must_use;
mod not_unsafe_ptr_arg_deref;
@@ -9,6 +10,7 @@ use rustc_hir as hir;
use rustc_hir::intravisit;
use rustc_lint::{LateContext, LateLintPass};
use rustc_session::{declare_tool_lint, impl_lint_pass};
+use rustc_span::def_id::LocalDefId;
use rustc_span::Span;
declare_clippy_lint! {
@@ -326,6 +328,32 @@ declare_clippy_lint! {
"getter method returning the wrong field"
}
+declare_clippy_lint! {
+ /// ### What it does
+ /// Lints when `impl Trait` is being used in a function's paremeters.
+ /// ### Why is this bad?
+ /// Turbofish syntax (`::<>`) cannot be used when `impl Trait` is being used, making `impl Trait` less powerful. Readability may also be a factor.
+ ///
+ /// ### Example
+ /// ```rust
+ /// trait MyTrait {}
+ /// fn foo(a: impl MyTrait) {
+ /// // [...]
+ /// }
+ /// ```
+ /// Use instead:
+ /// ```rust
+ /// trait MyTrait {}
+ /// fn foo<T: MyTrait>(a: T) {
+ /// // [...]
+ /// }
+ /// ```
+ #[clippy::version = "1.68.0"]
+ pub IMPL_TRAIT_IN_PARAMS,
+ restriction,
+ "`impl Trait` is used in the function's parameters"
+}
+
#[derive(Copy, Clone)]
pub struct Functions {
too_many_arguments_threshold: u64,
@@ -353,6 +381,7 @@ impl_lint_pass!(Functions => [
RESULT_UNIT_ERR,
RESULT_LARGE_ERR,
MISNAMED_GETTERS,
+ IMPL_TRAIT_IN_PARAMS,
]);
impl<'tcx> LateLintPass<'tcx> for Functions {
@@ -363,12 +392,14 @@ impl<'tcx> LateLintPass<'tcx> for Functions {
decl: &'tcx hir::FnDecl<'_>,
body: &'tcx hir::Body<'_>,
span: Span,
- hir_id: hir::HirId,
+ def_id: LocalDefId,
) {
+ let hir_id = cx.tcx.hir().local_def_id_to_hir_id(def_id);
too_many_arguments::check_fn(cx, kind, decl, span, hir_id, self.too_many_arguments_threshold);
too_many_lines::check_fn(cx, kind, span, body, self.too_many_lines_threshold);
- not_unsafe_ptr_arg_deref::check_fn(cx, kind, decl, body, hir_id);
- misnamed_getters::check_fn(cx, kind, decl, body, span, hir_id);
+ not_unsafe_ptr_arg_deref::check_fn(cx, kind, decl, body, def_id);
+ misnamed_getters::check_fn(cx, kind, decl, body, span);
+ impl_trait_in_params::check_fn(cx, &kind, body, hir_id);
}
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'_>) {
diff --git a/src/tools/clippy/clippy_lints/src/functions/must_use.rs b/src/tools/clippy/clippy_lints/src/functions/must_use.rs
index d22bede36..29bdc46b6 100644
--- a/src/tools/clippy/clippy_lints/src/functions/must_use.rs
+++ b/src/tools/clippy/clippy_lints/src/functions/must_use.rs
@@ -1,6 +1,6 @@
use rustc_ast::ast::Attribute;
use rustc_errors::Applicability;
-use rustc_hir::def_id::{DefIdSet, LocalDefId};
+use rustc_hir::def_id::DefIdSet;
use rustc_hir::{self as hir, def::Res, QPath};
use rustc_lint::{LateContext, LintContext};
use rustc_middle::{
@@ -27,14 +27,14 @@ pub(super) fn check_item<'tcx>(cx: &LateContext<'tcx>, item: &'tcx hir::Item<'_>
let is_public = cx.effective_visibilities.is_exported(item.owner_id.def_id);
let fn_header_span = item.span.with_hi(sig.decl.output.span().hi());
if let Some(attr) = attr {
- check_needless_must_use(cx, sig.decl, item.hir_id(), item.span, fn_header_span, attr);
+ check_needless_must_use(cx, sig.decl, item.owner_id, item.span, fn_header_span, attr);
} else if is_public && !is_proc_macro(cx.sess(), attrs) && !attrs.iter().any(|a| a.has_name(sym::no_mangle)) {
check_must_use_candidate(
cx,
sig.decl,
cx.tcx.hir().body(*body_id),
item.span,
- item.owner_id.def_id,
+ item.owner_id,
item.span.with_hi(sig.decl.output.span().hi()),
"this function could have a `#[must_use]` attribute",
);
@@ -49,7 +49,7 @@ pub(super) fn check_impl_item<'tcx>(cx: &LateContext<'tcx>, item: &'tcx hir::Imp
let attrs = cx.tcx.hir().attrs(item.hir_id());
let attr = cx.tcx.get_attr(item.owner_id.to_def_id(), sym::must_use);
if let Some(attr) = attr {
- check_needless_must_use(cx, sig.decl, item.hir_id(), item.span, fn_header_span, attr);
+ check_needless_must_use(cx, sig.decl, item.owner_id, item.span, fn_header_span, attr);
} else if is_public
&& !is_proc_macro(cx.sess(), attrs)
&& trait_ref_of_method(cx, item.owner_id.def_id).is_none()
@@ -59,7 +59,7 @@ pub(super) fn check_impl_item<'tcx>(cx: &LateContext<'tcx>, item: &'tcx hir::Imp
sig.decl,
cx.tcx.hir().body(*body_id),
item.span,
- item.owner_id.def_id,
+ item.owner_id,
item.span.with_hi(sig.decl.output.span().hi()),
"this method could have a `#[must_use]` attribute",
);
@@ -75,7 +75,7 @@ pub(super) fn check_trait_item<'tcx>(cx: &LateContext<'tcx>, item: &'tcx hir::Tr
let attrs = cx.tcx.hir().attrs(item.hir_id());
let attr = cx.tcx.get_attr(item.owner_id.to_def_id(), sym::must_use);
if let Some(attr) = attr {
- check_needless_must_use(cx, sig.decl, item.hir_id(), item.span, fn_header_span, attr);
+ check_needless_must_use(cx, sig.decl, item.owner_id, item.span, fn_header_span, attr);
} else if let hir::TraitFn::Provided(eid) = *eid {
let body = cx.tcx.hir().body(eid);
if attr.is_none() && is_public && !is_proc_macro(cx.sess(), attrs) {
@@ -84,7 +84,7 @@ pub(super) fn check_trait_item<'tcx>(cx: &LateContext<'tcx>, item: &'tcx hir::Tr
sig.decl,
body,
item.span,
- item.owner_id.def_id,
+ item.owner_id,
item.span.with_hi(sig.decl.output.span().hi()),
"this method could have a `#[must_use]` attribute",
);
@@ -96,7 +96,7 @@ pub(super) fn check_trait_item<'tcx>(cx: &LateContext<'tcx>, item: &'tcx hir::Tr
fn check_needless_must_use(
cx: &LateContext<'_>,
decl: &hir::FnDecl<'_>,
- item_id: hir::HirId,
+ item_id: hir::OwnerId,
item_span: Span,
fn_header_span: Span,
attr: &Attribute,
@@ -131,7 +131,7 @@ fn check_must_use_candidate<'tcx>(
decl: &'tcx hir::FnDecl<'_>,
body: &'tcx hir::Body<'_>,
item_span: Span,
- item_id: LocalDefId,
+ item_id: hir::OwnerId,
fn_span: Span,
msg: &str,
) {
@@ -139,8 +139,8 @@ fn check_must_use_candidate<'tcx>(
|| mutates_static(cx, body)
|| in_external_macro(cx.sess(), item_span)
|| returns_unit(decl)
- || !cx.effective_visibilities.is_exported(item_id)
- || is_must_use_ty(cx, return_ty(cx, cx.tcx.hir().local_def_id_to_hir_id(item_id)))
+ || !cx.effective_visibilities.is_exported(item_id.def_id)
+ || is_must_use_ty(cx, return_ty(cx, item_id))
{
return;
}
diff --git a/src/tools/clippy/clippy_lints/src/functions/not_unsafe_ptr_arg_deref.rs b/src/tools/clippy/clippy_lints/src/functions/not_unsafe_ptr_arg_deref.rs
index 2c0bf551f..f2aa7b597 100644
--- a/src/tools/clippy/clippy_lints/src/functions/not_unsafe_ptr_arg_deref.rs
+++ b/src/tools/clippy/clippy_lints/src/functions/not_unsafe_ptr_arg_deref.rs
@@ -17,7 +17,7 @@ pub(super) fn check_fn<'tcx>(
kind: intravisit::FnKind<'tcx>,
decl: &'tcx hir::FnDecl<'tcx>,
body: &'tcx hir::Body<'tcx>,
- hir_id: hir::HirId,
+ def_id: LocalDefId,
) {
let unsafety = match kind {
intravisit::FnKind::ItemFn(_, _, hir::FnHeader { unsafety, .. }) => unsafety,
@@ -25,7 +25,7 @@ pub(super) fn check_fn<'tcx>(
intravisit::FnKind::Closure => return,
};
- check_raw_ptr(cx, unsafety, decl, body, cx.tcx.hir().local_def_id(hir_id));
+ check_raw_ptr(cx, unsafety, decl, body, def_id);
}
pub(super) fn check_trait_item<'tcx>(cx: &LateContext<'tcx>, item: &'tcx hir::TraitItem<'_>) {
@@ -58,7 +58,7 @@ fn check_raw_ptr<'tcx>(
},
hir::ExprKind::MethodCall(_, recv, args, _) => {
let def_id = typeck.type_dependent_def_id(e.hir_id).unwrap();
- if cx.tcx.fn_sig(def_id).skip_binder().unsafety == hir::Unsafety::Unsafe {
+ if cx.tcx.fn_sig(def_id).skip_binder().skip_binder().unsafety == hir::Unsafety::Unsafe {
check_arg(cx, &raw_ptrs, recv);
for arg in args {
check_arg(cx, &raw_ptrs, arg);
diff --git a/src/tools/clippy/clippy_lints/src/functions/result.rs b/src/tools/clippy/clippy_lints/src/functions/result.rs
index 23da145d0..fa2a9b30c 100644
--- a/src/tools/clippy/clippy_lints/src/functions/result.rs
+++ b/src/tools/clippy/clippy_lints/src/functions/result.rs
@@ -21,7 +21,7 @@ fn result_err_ty<'tcx>(
) -> Option<(&'tcx hir::Ty<'tcx>, Ty<'tcx>)> {
if !in_external_macro(cx.sess(), item_span)
&& let hir::FnRetTy::Return(hir_ty) = decl.output
- && let ty = cx.tcx.erase_late_bound_regions(cx.tcx.fn_sig(id).output())
+ && let ty = cx.tcx.erase_late_bound_regions(cx.tcx.fn_sig(id).subst_identity().output())
&& is_type_diagnostic_item(cx, ty, sym::Result)
&& let ty::Adt(_, substs) = ty.kind()
{
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 989f83cf8..9fb73a371 100644
--- a/src/tools/clippy/clippy_lints/src/future_not_send.rs
+++ b/src/tools/clippy/clippy_lints/src/future_not_send.rs
@@ -1,11 +1,12 @@
use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::return_ty;
use rustc_hir::intravisit::FnKind;
-use rustc_hir::{Body, FnDecl, HirId};
+use rustc_hir::{Body, FnDecl};
use rustc_infer::infer::TyCtxtInferExt;
use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::ty::{self, AliasTy, Clause, EarlyBinder, PredicateKind};
use rustc_session::{declare_lint_pass, declare_tool_lint};
+use rustc_span::def_id::LocalDefId;
use rustc_span::{sym, Span};
use rustc_trait_selection::traits::error_reporting::suggestions::TypeErrCtxtExt;
use rustc_trait_selection::traits::{self, FulfillmentError};
@@ -56,12 +57,12 @@ impl<'tcx> LateLintPass<'tcx> for FutureNotSend {
decl: &'tcx FnDecl<'tcx>,
_: &'tcx Body<'tcx>,
_: Span,
- hir_id: HirId,
+ fn_def_id: LocalDefId,
) {
if let FnKind::Closure = kind {
return;
}
- let ret_ty = return_ty(cx, hir_id);
+ let ret_ty = return_ty(cx, cx.tcx.hir().local_def_id_to_hir_id(fn_def_id).expect_owner());
if let ty::Alias(ty::Opaque, AliasTy { def_id, substs, .. }) = *ret_ty.kind() {
let preds = cx.tcx.explicit_item_bounds(def_id);
let mut is_future = false;
@@ -78,7 +79,7 @@ impl<'tcx> LateLintPass<'tcx> for FutureNotSend {
let send_trait = cx.tcx.get_diagnostic_item(sym::Send).unwrap();
let span = decl.output.span();
let infcx = cx.tcx.infer_ctxt().build();
- let cause = traits::ObligationCause::misc(span, hir_id);
+ let cause = traits::ObligationCause::misc(span, fn_def_id);
let send_errors = traits::fully_solve_bound(&infcx, cause, cx.param_env, ret_ty, send_trait);
if !send_errors.is_empty() {
span_lint_and_then(
diff --git a/src/tools/clippy/clippy_lints/src/implicit_return.rs b/src/tools/clippy/clippy_lints/src/implicit_return.rs
index 946d04eff..372b6ead3 100644
--- a/src/tools/clippy/clippy_lints/src/implicit_return.rs
+++ b/src/tools/clippy/clippy_lints/src/implicit_return.rs
@@ -11,6 +11,7 @@ use rustc_hir::{Block, Body, Expr, ExprKind, FnDecl, FnRetTy, HirId};
use rustc_lint::{LateContext, LateLintPass, LintContext};
use rustc_middle::lint::in_external_macro;
use rustc_session::{declare_lint_pass, declare_tool_lint};
+use rustc_span::def_id::LocalDefId;
use rustc_span::{Span, SyntaxContext};
declare_clippy_lint! {
@@ -223,7 +224,7 @@ impl<'tcx> LateLintPass<'tcx> for ImplicitReturn {
decl: &'tcx FnDecl<'_>,
body: &'tcx Body<'_>,
span: Span,
- _: HirId,
+ _: LocalDefId,
) {
if (!matches!(kind, FnKind::Closure) && matches!(decl.output, FnRetTy::DefaultReturn(_)))
|| span.ctxt() != body.value.span.ctxt()
diff --git a/src/tools/clippy/clippy_lints/src/implicit_saturating_sub.rs b/src/tools/clippy/clippy_lints/src/implicit_saturating_sub.rs
index 29d59c26d..0c7aea6da 100644
--- a/src/tools/clippy/clippy_lints/src/implicit_saturating_sub.rs
+++ b/src/tools/clippy/clippy_lints/src/implicit_saturating_sub.rs
@@ -102,7 +102,7 @@ impl<'tcx> LateLintPass<'tcx> for ImplicitSaturatingSub {
if let Some(const_id) = cx.typeck_results().type_dependent_def_id(cond_num_val.hir_id);
if let Some(impl_id) = cx.tcx.impl_of_method(const_id);
if let None = cx.tcx.impl_trait_ref(impl_id); // An inherent impl
- if cx.tcx.type_of(impl_id).is_integral();
+ if cx.tcx.type_of(impl_id).subst_identity().is_integral();
then {
print_lint_and_sugg(cx, var_name, expr)
}
@@ -115,7 +115,7 @@ impl<'tcx> LateLintPass<'tcx> for ImplicitSaturatingSub {
if let Some(func_id) = cx.typeck_results().type_dependent_def_id(func.hir_id);
if let Some(impl_id) = cx.tcx.impl_of_method(func_id);
if let None = cx.tcx.impl_trait_ref(impl_id); // An inherent impl
- if cx.tcx.type_of(impl_id).is_integral();
+ if cx.tcx.type_of(impl_id).subst_identity().is_integral();
then {
print_lint_and_sugg(cx, var_name, expr)
}
diff --git a/src/tools/clippy/clippy_lints/src/inconsistent_struct_constructor.rs b/src/tools/clippy/clippy_lints/src/inconsistent_struct_constructor.rs
index e2f2d3d42..1ad886f2c 100644
--- a/src/tools/clippy/clippy_lints/src/inconsistent_struct_constructor.rs
+++ b/src/tools/clippy/clippy_lints/src/inconsistent_struct_constructor.rs
@@ -7,7 +7,7 @@ use rustc_hir::{self as hir, ExprKind};
use rustc_lint::{LateContext, LateLintPass};
use rustc_session::{declare_lint_pass, declare_tool_lint};
use rustc_span::symbol::Symbol;
-use std::fmt::Write as _;
+use std::fmt::{self, Write as _};
declare_clippy_lint! {
/// ### What it does
@@ -90,7 +90,7 @@ impl<'tcx> LateLintPass<'tcx> for InconsistentStructConstructor {
let mut fields_snippet = String::new();
let (last_ident, idents) = ordered_fields.split_last().unwrap();
for ident in idents {
- let _ = write!(fields_snippet, "{ident}, ");
+ let _: fmt::Result = write!(fields_snippet, "{ident}, ");
}
fields_snippet.push_str(&last_ident.to_string());
diff --git a/src/tools/clippy/clippy_lints/src/indexing_slicing.rs b/src/tools/clippy/clippy_lints/src/indexing_slicing.rs
index eebfb753a..c384172fb 100644
--- a/src/tools/clippy/clippy_lints/src/indexing_slicing.rs
+++ b/src/tools/clippy/clippy_lints/src/indexing_slicing.rs
@@ -109,7 +109,7 @@ impl<'tcx> LateLintPass<'tcx> for IndexingSlicing {
if let Some(range) = higher::Range::hir(index) {
// Ranged indexes, i.e., &x[n..m], &x[n..], &x[..n] and &x[..]
if let ty::Array(_, s) = ty.kind() {
- let size: u128 = if let Some(size) = s.try_eval_usize(cx.tcx, cx.param_env) {
+ let size: u128 = if let Some(size) = s.try_eval_target_usize(cx.tcx, cx.param_env) {
size.into()
} else {
return;
diff --git a/src/tools/clippy/clippy_lints/src/inherent_impl.rs b/src/tools/clippy/clippy_lints/src/inherent_impl.rs
index e9b2e31a7..7c41699f3 100644
--- a/src/tools/clippy/clippy_lints/src/inherent_impl.rs
+++ b/src/tools/clippy/clippy_lints/src/inherent_impl.rs
@@ -66,7 +66,8 @@ impl<'tcx> LateLintPass<'tcx> for MultipleInherentImpl {
)
}) {
for impl_id in impl_ids.iter().map(|id| id.expect_local()) {
- match type_map.entry(cx.tcx.type_of(impl_id)) {
+ let impl_ty = cx.tcx.type_of(impl_id).subst_identity();
+ match type_map.entry(impl_ty) {
Entry::Vacant(e) => {
// Store the id for the first impl block of this type. The span is retrieved lazily.
e.insert(IdOrSpan::Id(impl_id));
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 aaecc4fa8..d43e5cc9b 100644
--- a/src/tools/clippy/clippy_lints/src/inherent_to_string.rs
+++ b/src/tools/clippy/clippy_lints/src/inherent_to_string.rs
@@ -105,7 +105,7 @@ impl<'tcx> LateLintPass<'tcx> for InherentToString {
if impl_item.generics.params.iter().all(|p| matches!(p.kind, GenericParamKind::Lifetime { .. }));
// Check if return type is String
- if is_type_lang_item(cx, return_ty(cx, impl_item.hir_id()), LangItem::String);
+ if is_type_lang_item(cx, return_ty(cx, impl_item.owner_id), LangItem::String);
// Filters instances of to_string which are required by a trait
if trait_ref_of_method(cx, impl_item.owner_id.def_id).is_none();
@@ -124,7 +124,7 @@ fn show_lint(cx: &LateContext<'_>, item: &ImplItem<'_>) {
.expect("Failed to get trait ID of `Display`!");
// Get the real type of 'self'
- let self_type = cx.tcx.fn_sig(item.owner_id).input(0);
+ let self_type = cx.tcx.fn_sig(item.owner_id).skip_binder().input(0);
let self_type = self_type.skip_binder().peel_refs();
// Emit either a warning or an error
diff --git a/src/tools/clippy/clippy_lints/src/instant_subtraction.rs b/src/tools/clippy/clippy_lints/src/instant_subtraction.rs
index 9f6e89405..668110c7c 100644
--- a/src/tools/clippy/clippy_lints/src/instant_subtraction.rs
+++ b/src/tools/clippy/clippy_lints/src/instant_subtraction.rs
@@ -59,7 +59,7 @@ declare_clippy_lint! {
///
/// [`Duration`]: std::time::Duration
/// [`Instant::now()`]: std::time::Instant::now;
- #[clippy::version = "1.65.0"]
+ #[clippy::version = "1.67.0"]
pub UNCHECKED_DURATION_SUBTRACTION,
pedantic,
"finds unchecked subtraction of a 'Duration' from an 'Instant'"
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
index e76de77f1..c924d7361 100644
--- a/src/tools/clippy/clippy_lints/src/iter_not_returning_iterator.rs
+++ b/src/tools/clippy/clippy_lints/src/iter_not_returning_iterator.rs
@@ -66,7 +66,9 @@ impl<'tcx> LateLintPass<'tcx> for IterNotReturningIterator {
fn check_sig(cx: &LateContext<'_>, name: &str, sig: &FnSig<'_>, fn_id: LocalDefId) {
if sig.decl.implicit_self.has_implicit_self() {
- let ret_ty = cx.tcx.erase_late_bound_regions(cx.tcx.fn_sig(fn_id).output());
+ let ret_ty = cx
+ .tcx
+ .erase_late_bound_regions(cx.tcx.fn_sig(fn_id).subst_identity().output());
let ret_ty = cx
.tcx
.try_normalize_erasing_regions(cx.param_env, ret_ty)
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 db637dfc0..4dc750c03 100644
--- a/src/tools/clippy/clippy_lints/src/large_const_arrays.rs
+++ b/src/tools/clippy/clippy_lints/src/large_const_arrays.rs
@@ -54,7 +54,7 @@ impl<'tcx> LateLintPass<'tcx> for LargeConstArrays {
let ty = hir_ty_to_ty(cx.tcx, hir_ty);
if let ty::Array(element_type, cst) = ty.kind();
if let ConstKind::Value(ty::ValTree::Leaf(element_count)) = cst.kind();
- if let Ok(element_count) = element_count.try_to_machine_usize(cx.tcx);
+ if let Ok(element_count) = element_count.try_to_target_usize(cx.tcx);
if let Ok(element_size) = cx.layout_of(*element_type).map(|l| l.size.bytes());
if self.maximum_allowed_size < u128::from(element_count) * u128::from(element_size);
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 b8d4abdbb..1c99bd2f3 100644
--- a/src/tools/clippy/clippy_lints/src/large_enum_variant.rs
+++ b/src/tools/clippy/clippy_lints/src/large_enum_variant.rs
@@ -83,7 +83,7 @@ impl<'tcx> LateLintPass<'tcx> for LargeEnumVariant {
return;
}
if let ItemKind::Enum(ref def, _) = item.kind {
- let ty = cx.tcx.type_of(item.owner_id);
+ let ty = cx.tcx.type_of(item.owner_id).subst_identity();
let Adt(adt, subst) = ty.kind() else {
panic!("already checked whether this is an enum")
};
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 89ae83d48..32c6312e0 100644
--- a/src/tools/clippy/clippy_lints/src/large_stack_arrays.rs
+++ b/src/tools/clippy/clippy_lints/src/large_stack_arrays.rs
@@ -41,7 +41,7 @@ impl<'tcx> LateLintPass<'tcx> for LargeStackArrays {
if let ExprKind::Repeat(_, _) = expr.kind
&& let ty::Array(element_type, cst) = cx.typeck_results().expr_ty(expr).kind()
&& let ConstKind::Value(ty::ValTree::Leaf(element_count)) = cst.kind()
- && let Ok(element_count) = element_count.try_to_machine_usize(cx.tcx)
+ && let Ok(element_count) = element_count.try_to_target_usize(cx.tcx)
&& let Ok(element_size) = cx.layout_of(*element_type).map(|l| l.size.bytes())
&& !cx.tcx.hir().parent_iter(expr.hir_id)
.any(|(_, node)| matches!(node, Node::Item(Item { kind: ItemKind::Static(..), .. })))
diff --git a/src/tools/clippy/clippy_lints/src/len_zero.rs b/src/tools/clippy/clippy_lints/src/len_zero.rs
index 3c70c9cf1..e13bc4797 100644
--- a/src/tools/clippy/clippy_lints/src/len_zero.rs
+++ b/src/tools/clippy/clippy_lints/src/len_zero.rs
@@ -135,6 +135,7 @@ impl<'tcx> LateLintPass<'tcx> for LenZero {
if item.ident.name == sym::len;
if let ImplItemKind::Fn(sig, _) = &item.kind;
if sig.decl.implicit_self.has_implicit_self();
+ if sig.decl.inputs.len() == 1;
if cx.effective_visibilities.is_exported(item.owner_id.def_id);
if matches!(sig.decl.output, FnRetTy::Return(_));
if let Some(imp) = get_parent_as_impl(cx.tcx, item.hir_id());
@@ -144,7 +145,7 @@ impl<'tcx> LateLintPass<'tcx> for LenZero {
if let Some(local_id) = ty_id.as_local();
let ty_hir_id = cx.tcx.hir().local_def_id_to_hir_id(local_id);
if !is_lint_allowed(cx, LEN_WITHOUT_IS_EMPTY, ty_hir_id);
- if let Some(output) = parse_len_output(cx, cx.tcx.fn_sig(item.owner_id).skip_binder());
+ if let Some(output) = parse_len_output(cx, cx.tcx.fn_sig(item.owner_id).subst_identity().skip_binder());
then {
let (name, kind) = match cx.tcx.hir().find(ty_hir_id) {
Some(Node::ForeignItem(x)) => (x.ident.name, "extern type"),
@@ -196,7 +197,15 @@ fn check_trait_items(cx: &LateContext<'_>, visited_trait: &Item<'_>, trait_items
fn is_named_self(cx: &LateContext<'_>, item: &TraitItemRef, name: Symbol) -> bool {
item.ident.name == name
&& if let AssocItemKind::Fn { has_self } = item.kind {
- has_self && { cx.tcx.fn_sig(item.id.owner_id).inputs().skip_binder().len() == 1 }
+ has_self && {
+ cx.tcx
+ .fn_sig(item.id.owner_id)
+ .skip_binder()
+ .inputs()
+ .skip_binder()
+ .len()
+ == 1
+ }
} else {
false
}
@@ -224,7 +233,7 @@ fn check_trait_items(cx: &LateContext<'_>, visited_trait: &Item<'_>, trait_items
.any(|i| {
i.kind == ty::AssocKind::Fn
&& i.fn_has_self_parameter
- && cx.tcx.fn_sig(i.def_id).inputs().skip_binder().len() == 1
+ && cx.tcx.fn_sig(i.def_id).skip_binder().inputs().skip_binder().len() == 1
});
if !is_empty_method_found {
@@ -342,7 +351,11 @@ fn check_for_is_empty<'tcx>(
),
Some(is_empty)
if !(is_empty.fn_has_self_parameter
- && check_is_empty_sig(cx.tcx.fn_sig(is_empty.def_id).skip_binder(), self_kind, output)) =>
+ && check_is_empty_sig(
+ cx.tcx.fn_sig(is_empty.def_id).subst_identity().skip_binder(),
+ self_kind,
+ output,
+ )) =>
{
(
format!(
@@ -473,7 +486,7 @@ 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 item.kind == ty::AssocKind::Fn {
- let sig = cx.tcx.fn_sig(item.def_id);
+ let sig = cx.tcx.fn_sig(item.def_id).skip_binder();
let ty = sig.skip_binder();
ty.inputs().len() == 1
} else {
diff --git a/src/tools/clippy/clippy_lints/src/let_underscore.rs b/src/tools/clippy/clippy_lints/src/let_underscore.rs
index 61f87b914..7600777fa 100644
--- a/src/tools/clippy/clippy_lints/src/let_underscore.rs
+++ b/src/tools/clippy/clippy_lints/src/let_underscore.rs
@@ -84,13 +84,51 @@ declare_clippy_lint! {
/// let _ = foo().await;
/// # }
/// ```
- #[clippy::version = "1.66"]
+ #[clippy::version = "1.67.0"]
pub LET_UNDERSCORE_FUTURE,
suspicious,
"non-binding `let` on a future"
}
-declare_lint_pass!(LetUnderscore => [LET_UNDERSCORE_MUST_USE, LET_UNDERSCORE_LOCK, LET_UNDERSCORE_FUTURE]);
+declare_clippy_lint! {
+ /// ### What it does
+ /// Checks for `let _ = <expr>` without a type annotation, and suggests to either provide one,
+ /// or remove the `let` keyword altogether.
+ ///
+ /// ### Why is this bad?
+ /// The `let _ = <expr>` expression ignores the value of `<expr>` but will remain doing so even
+ /// if the type were to change, thus potentially introducing subtle bugs. By supplying a type
+ /// annotation, one will be forced to re-visit the decision to ignore the value in such cases.
+ ///
+ /// ### Known problems
+ /// The `_ = <expr>` is not properly supported by some tools (e.g. IntelliJ) and may seem odd
+ /// to many developers. This lint also partially overlaps with the other `let_underscore_*`
+ /// lints.
+ ///
+ /// ### Example
+ /// ```rust
+ /// fn foo() -> Result<u32, ()> {
+ /// Ok(123)
+ /// }
+ /// let _ = foo();
+ /// ```
+ /// Use instead:
+ /// ```rust
+ /// fn foo() -> Result<u32, ()> {
+ /// Ok(123)
+ /// }
+ /// // Either provide a type annotation:
+ /// let _: Result<u32, ()> = foo();
+ /// // …or drop the let keyword:
+ /// _ = foo();
+ /// ```
+ #[clippy::version = "1.69.0"]
+ pub LET_UNDERSCORE_UNTYPED,
+ pedantic,
+ "non-binding `let` without a type annotation"
+}
+
+declare_lint_pass!(LetUnderscore => [LET_UNDERSCORE_MUST_USE, LET_UNDERSCORE_LOCK, LET_UNDERSCORE_FUTURE, LET_UNDERSCORE_UNTYPED]);
const SYNC_GUARD_PATHS: [&[&str]; 3] = [
&paths::PARKING_LOT_MUTEX_GUARD,
@@ -148,6 +186,18 @@ impl<'tcx> LateLintPass<'tcx> for LetUnderscore {
"consider explicitly using function result",
);
}
+
+ if local.pat.default_binding_modes && local.ty.is_none() {
+ // When `default_binding_modes` is true, the `let` keyword is present.
+ span_lint_and_help(
+ cx,
+ LET_UNDERSCORE_UNTYPED,
+ local.span,
+ "non-binding `let` without a type annotation",
+ None,
+ "consider adding a type annotation or removing the `let` keyword",
+ );
+ }
}
}
}
diff --git a/src/tools/clippy/clippy_lints/src/lib.rs b/src/tools/clippy/clippy_lints/src/lib.rs
index e93f27bee..c626e0bd9 100644
--- a/src/tools/clippy/clippy_lints/src/lib.rs
+++ b/src/tools/clippy/clippy_lints/src/lib.rs
@@ -1,8 +1,8 @@
#![feature(array_windows)]
#![feature(binary_heap_into_iter_sorted)]
#![feature(box_patterns)]
-#![feature(control_flow_enum)]
#![feature(drain_filter)]
+#![feature(if_let_guard)]
#![feature(iter_intersperse)]
#![feature(let_chains)]
#![feature(lint_reasons)]
@@ -43,6 +43,7 @@ extern crate rustc_session;
extern crate rustc_span;
extern crate rustc_target;
extern crate rustc_trait_selection;
+extern crate thin_vec;
#[macro_use]
extern crate clippy_utils;
@@ -122,6 +123,7 @@ mod excessive_bools;
mod exhaustive_items;
mod exit;
mod explicit_write;
+mod extra_unused_type_parameters;
mod fallible_impl_from;
mod float_literal;
mod floating_point_arithmetic;
@@ -198,6 +200,7 @@ mod missing_trait_methods;
mod mixed_read_write_in_expression;
mod module_style;
mod multi_assignments;
+mod multiple_unsafe_ops_per_block;
mod mut_key;
mod mut_mut;
mod mut_reference;
@@ -217,6 +220,7 @@ mod neg_cmp_op_on_partial_ord;
mod neg_multiply;
mod new_without_default;
mod no_effect;
+mod no_mangle_with_rust_abi;
mod non_copy_const;
mod non_expressive_names;
mod non_octal_unix_permissions;
@@ -241,6 +245,7 @@ mod ptr;
mod ptr_offset_with_cast;
mod pub_use;
mod question_mark;
+mod question_mark_used;
mod ranges;
mod rc_clone_in_vec_init;
mod read_zero_byte_vec;
@@ -262,6 +267,7 @@ mod semicolon_block;
mod semicolon_if_nothing_returned;
mod serde_api;
mod shadow;
+mod significant_drop_tightening;
mod single_char_lifetime_names;
mod single_component_path_imports;
mod size_of_in_element_count;
@@ -557,6 +563,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
store.register_late_pass(|_| Box::new(eta_reduction::EtaReduction));
store.register_late_pass(|_| Box::new(mut_mut::MutMut));
store.register_late_pass(|_| Box::new(mut_reference::UnnecessaryMutPassed));
+ store.register_late_pass(|_| Box::<significant_drop_tightening::SignificantDropTightening<'_>>::default());
store.register_late_pass(|_| Box::new(len_zero::LenZero));
store.register_late_pass(|_| Box::new(attrs::Attributes));
store.register_late_pass(|_| Box::new(blocks_in_if_conditions::BlocksInIfConditions));
@@ -663,12 +670,13 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
))
});
let doc_valid_idents = conf.doc_valid_idents.iter().cloned().collect::<FxHashSet<_>>();
+ let missing_docs_in_crate_items = conf.missing_docs_in_crate_items;
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_forget::MemForget));
store.register_late_pass(|_| Box::new(let_if_seq::LetIfSeq));
store.register_late_pass(|_| Box::new(mixed_read_write_in_expression::EvalOrderDependence));
- store.register_late_pass(|_| Box::new(missing_doc::MissingDoc::new()));
+ store.register_late_pass(move |_| Box::new(missing_doc::MissingDoc::new(missing_docs_in_crate_items)));
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(match_result_ok::MatchResultOk));
@@ -692,6 +700,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
store.register_late_pass(|_| Box::new(implicit_hasher::ImplicitHasher));
store.register_late_pass(|_| Box::new(fallible_impl_from::FallibleImplFrom));
store.register_late_pass(|_| Box::new(question_mark::QuestionMark));
+ store.register_late_pass(|_| Box::new(question_mark_used::QuestionMarkUsed));
store.register_early_pass(|| Box::new(suspicious_operation_groupings::SuspiciousOperationGroupings));
store.register_late_pass(|_| Box::new(suspicious_trait_impl::SuspiciousImpl));
store.register_late_pass(|_| Box::new(map_unit_fn::MapUnit));
@@ -908,6 +917,13 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
store.register_late_pass(|_| Box::new(fn_null_check::FnNullCheck));
store.register_late_pass(|_| Box::new(permissions_set_readonly_false::PermissionsSetReadonlyFalse));
store.register_late_pass(|_| Box::new(size_of_ref::SizeOfRef));
+ store.register_late_pass(|_| Box::new(multiple_unsafe_ops_per_block::MultipleUnsafeOpsPerBlock));
+ store.register_late_pass(move |_| {
+ Box::new(extra_unused_type_parameters::ExtraUnusedTypeParameters::new(
+ avoid_breaking_exported_api,
+ ))
+ });
+ store.register_late_pass(|_| Box::new(no_mangle_with_rust_abi::NoMangleWithRustAbi));
// add lints here, do not remove this comment, it's used in `new_lint`
}
diff --git a/src/tools/clippy/clippy_lints/src/lifetimes.rs b/src/tools/clippy/clippy_lints/src/lifetimes.rs
index 7cf1a6b80..986ffcad8 100644
--- a/src/tools/clippy/clippy_lints/src/lifetimes.rs
+++ b/src/tools/clippy/clippy_lints/src/lifetimes.rs
@@ -1,21 +1,21 @@
use clippy_utils::diagnostics::{span_lint, span_lint_and_then};
use clippy_utils::trait_ref_of_method;
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
+use rustc_errors::Applicability;
use rustc_hir::intravisit::nested_filter::{self as hir_nested_filter, NestedFilter};
use rustc_hir::intravisit::{
- walk_fn_decl, walk_generic_arg, walk_generic_param, walk_generics, walk_impl_item_ref, walk_item, walk_param_bound,
+ walk_fn_decl, walk_generic_param, walk_generics, walk_impl_item_ref, walk_item, walk_param_bound,
walk_poly_trait_ref, walk_trait_ref, walk_ty, Visitor,
};
-use rustc_hir::lang_items;
use rustc_hir::FnRetTy::Return;
use rustc_hir::{
- BareFnTy, BodyId, FnDecl, GenericArg, GenericBound, GenericParam, GenericParamKind, Generics, Impl, ImplItem,
- ImplItemKind, Item, ItemKind, Lifetime, LifetimeName, LifetimeParamKind, PolyTraitRef, PredicateOrigin, TraitFn,
- TraitItem, TraitItemKind, Ty, TyKind, WherePredicate,
+ lang_items, BareFnTy, BodyId, FnDecl, FnSig, GenericArg, GenericBound, GenericParam, GenericParamKind, Generics,
+ Impl, ImplItem, ImplItemKind, Item, ItemKind, Lifetime, LifetimeName, LifetimeParamKind, Node, PolyTraitRef,
+ PredicateOrigin, TraitFn, TraitItem, TraitItemKind, Ty, TyKind, WherePredicate,
};
-use rustc_lint::{LateContext, LateLintPass};
+use rustc_lint::{LateContext, LateLintPass, LintContext};
use rustc_middle::hir::nested_filter as middle_nested_filter;
-use rustc_middle::ty::TyCtxt;
+use rustc_middle::lint::in_external_macro;
use rustc_session::{declare_lint_pass, declare_tool_lint};
use rustc_span::def_id::LocalDefId;
use rustc_span::source_map::Span;
@@ -34,8 +34,6 @@ declare_clippy_lint! {
/// ### Known problems
/// - We bail out if the function has a `where` clause where lifetimes
/// are mentioned due to potential false positives.
- /// - Lifetime bounds such as `impl Foo + 'a` and `T: 'a` must be elided with the
- /// placeholder notation `'_` because the fully elided notation leaves the type bound to `'static`.
///
/// ### Example
/// ```rust
@@ -93,7 +91,7 @@ declare_lint_pass!(Lifetimes => [NEEDLESS_LIFETIMES, EXTRA_UNUSED_LIFETIMES]);
impl<'tcx> LateLintPass<'tcx> for Lifetimes {
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) {
if let ItemKind::Fn(ref sig, generics, id) = item.kind {
- check_fn_inner(cx, sig.decl, Some(id), None, generics, item.span, true);
+ check_fn_inner(cx, sig, Some(id), None, generics, item.span, true);
} else if let ItemKind::Impl(impl_) = item.kind {
if !item.span.from_expansion() {
report_extra_impl_lifetimes(cx, impl_);
@@ -106,7 +104,7 @@ impl<'tcx> LateLintPass<'tcx> for Lifetimes {
let report_extra_lifetimes = trait_ref_of_method(cx, item.owner_id.def_id).is_none();
check_fn_inner(
cx,
- sig.decl,
+ sig,
Some(id),
None,
item.generics,
@@ -122,29 +120,21 @@ impl<'tcx> LateLintPass<'tcx> for Lifetimes {
TraitFn::Required(sig) => (None, Some(sig)),
TraitFn::Provided(id) => (Some(id), None),
};
- check_fn_inner(cx, sig.decl, body, trait_sig, item.generics, item.span, true);
+ check_fn_inner(cx, sig, body, trait_sig, item.generics, item.span, true);
}
}
}
-/// The lifetime of a &-reference.
-#[derive(PartialEq, Eq, Hash, Debug, Clone)]
-enum RefLt {
- Unnamed,
- Static,
- Named(LocalDefId),
-}
-
fn check_fn_inner<'tcx>(
cx: &LateContext<'tcx>,
- decl: &'tcx FnDecl<'_>,
+ sig: &'tcx FnSig<'_>,
body: Option<BodyId>,
trait_sig: Option<&[Ident]>,
generics: &'tcx Generics<'_>,
span: Span,
report_extra_lifetimes: bool,
) {
- if span.from_expansion() || has_where_lifetimes(cx, generics) {
+ if in_external_macro(cx.sess(), span) || has_where_lifetimes(cx, generics) {
return;
}
@@ -154,7 +144,11 @@ fn check_fn_inner<'tcx>(
.filter(|param| matches!(param.kind, GenericParamKind::Type { .. }));
for typ in types {
- for pred in generics.bounds_for_param(cx.tcx.hir().local_def_id(typ.hir_id)) {
+ if !typ.span.eq_ctxt(span) {
+ return;
+ }
+
+ for pred in generics.bounds_for_param(typ.def_id) {
if pred.origin == PredicateOrigin::WhereClause {
// has_where_lifetimes checked that this predicate contains no lifetime.
continue;
@@ -163,7 +157,7 @@ fn check_fn_inner<'tcx>(
for bound in pred.bounds {
let mut visitor = RefVisitor::new(cx);
walk_param_bound(&mut visitor, bound);
- if visitor.lts.iter().any(|lt| matches!(lt, RefLt::Named(_))) {
+ if visitor.lts.iter().any(|lt| matches!(lt.res, LifetimeName::Param(_))) {
return;
}
if let GenericBound::Trait(ref trait_ref, _) = *bound {
@@ -190,12 +184,16 @@ fn check_fn_inner<'tcx>(
}
}
- if let Some(elidable_lts) = could_use_elision(cx, decl, body, trait_sig, generics.params) {
+ if let Some((elidable_lts, usages)) = could_use_elision(cx, sig.decl, body, trait_sig, generics.params) {
+ if usages.iter().any(|usage| !usage.ident.span.eq_ctxt(span)) {
+ return;
+ }
+
let lts = elidable_lts
.iter()
// In principle, the result of the call to `Node::ident` could be `unwrap`ped, as `DefId` should refer to a
// `Node::GenericParam`.
- .filter_map(|&(def_id, _)| cx.tcx.hir().get_by_def_id(def_id).ident())
+ .filter_map(|&def_id| cx.tcx.hir().get_by_def_id(def_id).ident())
.map(|ident| ident.to_string())
.collect::<Vec<_>>()
.join(", ");
@@ -203,21 +201,99 @@ fn check_fn_inner<'tcx>(
span_lint_and_then(
cx,
NEEDLESS_LIFETIMES,
- span.with_hi(decl.output.span().hi()),
+ span.with_hi(sig.decl.output.span().hi()),
&format!("the following explicit lifetimes could be elided: {lts}"),
|diag| {
- if let Some(span) = elidable_lts.iter().find_map(|&(_, span)| span) {
- diag.span_help(span, "replace with `'_` in generic arguments such as here");
+ if sig.header.is_async() {
+ // async functions have usages whose spans point at the lifetime declaration which messes up
+ // suggestions
+ return;
+ };
+
+ if let Some(suggestions) = elision_suggestions(cx, generics, &elidable_lts, &usages) {
+ diag.multipart_suggestion("elide the lifetimes", suggestions, Applicability::MachineApplicable);
}
},
);
}
if report_extra_lifetimes {
- self::report_extra_lifetimes(cx, decl, generics);
+ self::report_extra_lifetimes(cx, sig.decl, generics);
}
}
+fn elision_suggestions(
+ cx: &LateContext<'_>,
+ generics: &Generics<'_>,
+ elidable_lts: &[LocalDefId],
+ usages: &[Lifetime],
+) -> Option<Vec<(Span, String)>> {
+ let explicit_params = generics
+ .params
+ .iter()
+ .filter(|param| !param.is_elided_lifetime() && !param.is_impl_trait())
+ .collect::<Vec<_>>();
+
+ let mut suggestions = if elidable_lts.len() == explicit_params.len() {
+ // if all the params are elided remove the whole generic block
+ //
+ // fn x<'a>() {}
+ // ^^^^
+ vec![(generics.span, String::new())]
+ } else {
+ elidable_lts
+ .iter()
+ .map(|&id| {
+ let pos = explicit_params.iter().position(|param| param.def_id == id)?;
+ let param = explicit_params.get(pos)?;
+
+ let span = if let Some(next) = explicit_params.get(pos + 1) {
+ // fn x<'prev, 'a, 'next>() {}
+ // ^^^^
+ param.span.until(next.span)
+ } else {
+ // `pos` should be at least 1 here, because the param in position 0 would either have a `next`
+ // param or would have taken the `elidable_lts.len() == explicit_params.len()` branch.
+ let prev = explicit_params.get(pos - 1)?;
+
+ // fn x<'prev, 'a>() {}
+ // ^^^^
+ param.span.with_lo(prev.span.hi())
+ };
+
+ Some((span, String::new()))
+ })
+ .collect::<Option<Vec<_>>>()?
+ };
+
+ suggestions.extend(
+ usages
+ .iter()
+ .filter(|usage| named_lifetime(usage).map_or(false, |id| elidable_lts.contains(&id)))
+ .map(|usage| {
+ match cx.tcx.hir().get_parent(usage.hir_id) {
+ Node::Ty(Ty {
+ kind: TyKind::Ref(..), ..
+ }) => {
+ // expand `&'a T` to `&'a T`
+ // ^^ ^^^
+ let span = cx
+ .sess()
+ .source_map()
+ .span_extend_while(usage.ident.span, |ch| ch.is_ascii_whitespace())
+ .unwrap_or(usage.ident.span);
+
+ (span, String::new())
+ },
+ // `T<'a>` and `impl Foo + 'a` should be replaced by `'_`
+ _ => (usage.ident.span, String::from("'_")),
+ }
+ }),
+ );
+
+ Some(suggestions)
+}
+
// elision doesn't work for explicit self types, see rust-lang/rust#69064
fn explicit_self_type<'tcx>(cx: &LateContext<'tcx>, func: &FnDecl<'tcx>, ident: Option<Ident>) -> bool {
if_chain! {
@@ -237,13 +313,20 @@ fn explicit_self_type<'tcx>(cx: &LateContext<'tcx>, func: &FnDecl<'tcx>, ident:
}
}
+fn named_lifetime(lt: &Lifetime) -> Option<LocalDefId> {
+ match lt.res {
+ LifetimeName::Param(id) if !lt.is_anonymous() => Some(id),
+ _ => None,
+ }
+}
+
fn could_use_elision<'tcx>(
cx: &LateContext<'tcx>,
func: &'tcx FnDecl<'_>,
body: Option<BodyId>,
trait_sig: Option<&[Ident]>,
named_generics: &'tcx [GenericParam<'_>],
-) -> Option<Vec<(LocalDefId, Option<Span>)>> {
+) -> Option<(Vec<LocalDefId>, Vec<Lifetime>)> {
// There are two scenarios where elision works:
// * no output references, all input references have different LT
// * output references, exactly one input reference with same LT
@@ -251,7 +334,7 @@ fn could_use_elision<'tcx>(
// level of the current item.
// check named LTs
- let allowed_lts = allowed_lts_from(cx.tcx, named_generics);
+ let allowed_lts = allowed_lts_from(named_generics);
// these will collect all the lifetimes for references in arg/return types
let mut input_visitor = RefVisitor::new(cx);
@@ -301,32 +384,24 @@ fn could_use_elision<'tcx>(
// check for lifetimes from higher scopes
for lt in input_lts.iter().chain(output_lts.iter()) {
- if !allowed_lts.contains(lt) {
+ if let Some(id) = named_lifetime(lt)
+ && !allowed_lts.contains(&id)
+ {
return None;
}
}
// check for higher-ranked trait bounds
if !input_visitor.nested_elision_site_lts.is_empty() || !output_visitor.nested_elision_site_lts.is_empty() {
- let allowed_lts: FxHashSet<_> = allowed_lts
- .iter()
- .filter_map(|lt| match lt {
- RefLt::Named(def_id) => Some(cx.tcx.item_name(def_id.to_def_id())),
- _ => None,
- })
- .collect();
+ let allowed_lts: FxHashSet<_> = allowed_lts.iter().map(|id| cx.tcx.item_name(id.to_def_id())).collect();
for lt in input_visitor.nested_elision_site_lts {
- if let RefLt::Named(def_id) = lt {
- if allowed_lts.contains(&cx.tcx.item_name(def_id.to_def_id())) {
- return None;
- }
+ if allowed_lts.contains(&lt.ident.name) {
+ return None;
}
}
for lt in output_visitor.nested_elision_site_lts {
- if let RefLt::Named(def_id) = lt {
- if allowed_lts.contains(&cx.tcx.item_name(def_id.to_def_id())) {
- return None;
- }
+ if allowed_lts.contains(&lt.ident.name) {
+ return None;
}
}
}
@@ -338,15 +413,10 @@ fn could_use_elision<'tcx>(
let elidable_lts = named_lifetime_occurrences(&input_lts)
.into_iter()
.filter_map(|(def_id, occurrences)| {
- if occurrences == 1 && (input_lts.len() == 1 || !output_lts.contains(&RefLt::Named(def_id))) {
- Some((
- def_id,
- input_visitor
- .lifetime_generic_arg_spans
- .get(&def_id)
- .or_else(|| output_visitor.lifetime_generic_arg_spans.get(&def_id))
- .copied(),
- ))
+ if occurrences == 1
+ && (input_lts.len() == 1 || !output_lts.iter().any(|lt| named_lifetime(lt) == Some(def_id)))
+ {
+ Some(def_id)
} else {
None
}
@@ -354,31 +424,34 @@ fn could_use_elision<'tcx>(
.collect::<Vec<_>>();
if elidable_lts.is_empty() {
- None
- } else {
- Some(elidable_lts)
+ return None;
}
+
+ let usages = itertools::chain(input_lts, output_lts).collect();
+
+ Some((elidable_lts, usages))
}
-fn allowed_lts_from(tcx: TyCtxt<'_>, named_generics: &[GenericParam<'_>]) -> FxHashSet<RefLt> {
- let mut allowed_lts = FxHashSet::default();
- for par in named_generics.iter() {
- if let GenericParamKind::Lifetime { .. } = par.kind {
- allowed_lts.insert(RefLt::Named(tcx.hir().local_def_id(par.hir_id)));
- }
- }
- allowed_lts.insert(RefLt::Unnamed);
- allowed_lts.insert(RefLt::Static);
- allowed_lts
+fn allowed_lts_from(named_generics: &[GenericParam<'_>]) -> FxHashSet<LocalDefId> {
+ named_generics
+ .iter()
+ .filter_map(|par| {
+ if let GenericParamKind::Lifetime { .. } = par.kind {
+ Some(par.def_id)
+ } else {
+ None
+ }
+ })
+ .collect()
}
/// Number of times each named lifetime occurs in the given slice. Returns a vector to preserve
/// relative order.
#[must_use]
-fn named_lifetime_occurrences(lts: &[RefLt]) -> Vec<(LocalDefId, usize)> {
+fn named_lifetime_occurrences(lts: &[Lifetime]) -> Vec<(LocalDefId, usize)> {
let mut occurrences = Vec::new();
for lt in lts {
- if let &RefLt::Named(curr_def_id) = lt {
+ if let Some(curr_def_id) = named_lifetime(lt) {
if let Some(pair) = occurrences
.iter_mut()
.find(|(prev_def_id, _)| *prev_def_id == curr_def_id)
@@ -392,12 +465,10 @@ fn named_lifetime_occurrences(lts: &[RefLt]) -> Vec<(LocalDefId, usize)> {
occurrences
}
-/// A visitor usable for `rustc_front::visit::walk_ty()`.
struct RefVisitor<'a, 'tcx> {
cx: &'a LateContext<'tcx>,
- lts: Vec<RefLt>,
- lifetime_generic_arg_spans: FxHashMap<LocalDefId, Span>,
- nested_elision_site_lts: Vec<RefLt>,
+ lts: Vec<Lifetime>,
+ nested_elision_site_lts: Vec<Lifetime>,
unelided_trait_object_lifetime: bool,
}
@@ -406,32 +477,16 @@ impl<'a, 'tcx> RefVisitor<'a, 'tcx> {
Self {
cx,
lts: Vec::new(),
- lifetime_generic_arg_spans: FxHashMap::default(),
nested_elision_site_lts: Vec::new(),
unelided_trait_object_lifetime: false,
}
}
- fn record(&mut self, lifetime: &Option<Lifetime>) {
- if let Some(ref lt) = *lifetime {
- if lt.is_static() {
- self.lts.push(RefLt::Static);
- } else if lt.is_anonymous() {
- // Fresh lifetimes generated should be ignored.
- self.lts.push(RefLt::Unnamed);
- } else if let LifetimeName::Param(def_id) = lt.res {
- self.lts.push(RefLt::Named(def_id));
- }
- } else {
- self.lts.push(RefLt::Unnamed);
- }
- }
-
- fn all_lts(&self) -> Vec<RefLt> {
+ fn all_lts(&self) -> Vec<Lifetime> {
self.lts
.iter()
.chain(self.nested_elision_site_lts.iter())
- .cloned()
+ .copied()
.collect::<Vec<_>>()
}
@@ -443,7 +498,7 @@ impl<'a, 'tcx> RefVisitor<'a, 'tcx> {
impl<'a, 'tcx> Visitor<'tcx> for RefVisitor<'a, 'tcx> {
// for lifetimes as parameters of generics
fn visit_lifetime(&mut self, lifetime: &'tcx Lifetime) {
- self.record(&Some(*lifetime));
+ self.lts.push(*lifetime);
}
fn visit_poly_trait_ref(&mut self, poly_tref: &'tcx PolyTraitRef<'tcx>) {
@@ -468,11 +523,7 @@ impl<'a, 'tcx> Visitor<'tcx> for RefVisitor<'a, 'tcx> {
walk_item(self, item);
self.lts.truncate(len);
self.lts.extend(bounds.iter().filter_map(|bound| match bound {
- GenericArg::Lifetime(l) => Some(if let LifetimeName::Param(def_id) = l.res {
- RefLt::Named(def_id)
- } else {
- RefLt::Unnamed
- }),
+ GenericArg::Lifetime(&l) => Some(l),
_ => None,
}));
},
@@ -492,13 +543,6 @@ impl<'a, 'tcx> Visitor<'tcx> for RefVisitor<'a, 'tcx> {
_ => walk_ty(self, ty),
}
}
-
- fn visit_generic_arg(&mut self, generic_arg: &'tcx GenericArg<'tcx>) {
- if let GenericArg::Lifetime(l) = generic_arg && let LifetimeName::Param(def_id) = l.res {
- self.lifetime_generic_arg_spans.entry(def_id).or_insert(l.ident.span);
- }
- walk_generic_arg(self, generic_arg);
- }
}
/// Are any lifetimes mentioned in the `where` clause? If so, we don't try to
@@ -516,14 +560,18 @@ fn has_where_lifetimes<'tcx>(cx: &LateContext<'tcx>, generics: &'tcx Generics<'_
return true;
}
// if the bounds define new lifetimes, they are fine to occur
- let allowed_lts = allowed_lts_from(cx.tcx, pred.bound_generic_params);
+ let allowed_lts = allowed_lts_from(pred.bound_generic_params);
// now walk the bounds
for bound in pred.bounds.iter() {
walk_param_bound(&mut visitor, bound);
}
// and check that all lifetimes are allowed
- if visitor.all_lts().iter().any(|it| !allowed_lts.contains(it)) {
- return true;
+ for lt in visitor.all_lts() {
+ if let Some(id) = named_lifetime(&lt)
+ && !allowed_lts.contains(&id)
+ {
+ return true;
+ }
}
},
WherePredicate::EqPredicate(ref pred) => {
diff --git a/src/tools/clippy/clippy_lints/src/literal_representation.rs b/src/tools/clippy/clippy_lints/src/literal_representation.rs
index 3a7b7835c..dadcd9c51 100644
--- a/src/tools/clippy/clippy_lints/src/literal_representation.rs
+++ b/src/tools/clippy/clippy_lints/src/literal_representation.rs
@@ -210,7 +210,7 @@ impl WarningType {
cx,
UNUSUAL_BYTE_GROUPINGS,
span,
- "digits of hex or binary literal not grouped by four",
+ "digits of hex, binary or octal literal not in groups of equal size",
"consider",
suggested_format,
Applicability::MachineApplicable,
@@ -427,8 +427,12 @@ impl LiteralDigitGrouping {
let first = groups.next().expect("At least one group");
- if (radix == Radix::Binary || radix == Radix::Hexadecimal) && groups.any(|i| i != 4 && i != 2) {
- return Err(WarningType::UnusualByteGroupings);
+ if radix == Radix::Binary || radix == Radix::Octal || radix == Radix::Hexadecimal {
+ if let Some(second_size) = groups.next() {
+ if !groups.all(|i| i == second_size) || first > second_size {
+ return Err(WarningType::UnusualByteGroupings);
+ }
+ }
}
if let Some(second) = groups.next() {
@@ -484,7 +488,7 @@ impl DecimalLiteralRepresentation {
then {
let hex = format!("{val:#X}");
let num_lit = NumericLiteral::new(&hex, num_lit.suffix, false);
- let _ = Self::do_lint(num_lit.integer).map_err(|warning_type| {
+ let _: Result<(), ()> = Self::do_lint(num_lit.integer).map_err(|warning_type| {
warning_type.display(num_lit.format(), cx, span);
});
}
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 b1f294162..151c7f1d5 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
@@ -68,7 +68,7 @@ fn is_iterable_array<'tcx>(ty: Ty<'tcx>, cx: &LateContext<'tcx>) -> bool {
// IntoIterator is currently only implemented for array sizes <= 32 in rustc
match ty.kind() {
ty::Array(_, n) => n
- .try_eval_usize(cx.tcx, cx.param_env)
+ .try_eval_target_usize(cx.tcx, cx.param_env)
.map_or(false, |val| (0..=32).contains(&val)),
_ => false,
}
diff --git a/src/tools/clippy/clippy_lints/src/loops/mod.rs b/src/tools/clippy/clippy_lints/src/loops/mod.rs
index 8e52cac43..610a0233e 100644
--- a/src/tools/clippy/clippy_lints/src/loops/mod.rs
+++ b/src/tools/clippy/clippy_lints/src/loops/mod.rs
@@ -61,7 +61,8 @@ declare_clippy_lint! {
///
/// ### Why is this bad?
/// Just iterating the collection itself makes the intent
- /// more clear and is probably faster.
+ /// more clear and is probably faster because it eliminates
+ /// the bounds check that is done when indexing.
///
/// ### Example
/// ```rust
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 3bca93d80..5c317c2a5 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
@@ -149,7 +149,7 @@ pub(super) fn check<'tcx>(
|diag| {
multispan_sugg(
diag,
- "consider using an iterator",
+ "consider using an iterator and enumerate()",
vec![
(pat.span, format!("({}, <item>)", ident.name)),
(
@@ -211,7 +211,7 @@ fn is_end_eq_array_len<'tcx>(
if let ExprKind::Lit(ref lit) = end.kind;
if let ast::LitKind::Int(end_int, _) = lit.node;
if let ty::Array(_, arr_len_const) = indexed_ty.kind();
- if let Some(arr_len) = arr_len_const.try_eval_usize(cx.tcx, cx.param_env);
+ if let Some(arr_len) = arr_len_const.try_eval_target_usize(cx.tcx, cx.param_env);
then {
return match limits {
ast::RangeLimits::Closed => end_int + 1 >= arr_len.into(),
@@ -370,7 +370,7 @@ impl<'a, 'tcx> Visitor<'tcx> for VarVisitor<'a, 'tcx> {
ExprKind::MethodCall(_, receiver, args, _) => {
let def_id = self.cx.typeck_results().type_dependent_def_id(expr.hir_id).unwrap();
for (ty, expr) in iter::zip(
- self.cx.tcx.fn_sig(def_id).inputs().skip_binder(),
+ self.cx.tcx.fn_sig(def_id).subst_identity().inputs().skip_binder(),
std::iter::once(receiver).chain(args.iter()),
) {
self.prefer_mutable = false;
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 14f161f51..b1bc10802 100644
--- a/src/tools/clippy/clippy_lints/src/loops/never_loop.rs
+++ b/src/tools/clippy/clippy_lints/src/loops/never_loop.rs
@@ -39,6 +39,7 @@ pub(super) fn check(
});
},
NeverLoopResult::MayContinueMainLoop | NeverLoopResult::Otherwise => (),
+ NeverLoopResult::IgnoreUntilEnd(_) => unreachable!(),
}
}
@@ -48,6 +49,8 @@ enum NeverLoopResult {
AlwaysBreak,
// A continue may occur for the main loop.
MayContinueMainLoop,
+ // Ignore everything until the end of the block with this id
+ IgnoreUntilEnd(HirId),
Otherwise,
}
@@ -56,6 +59,7 @@ fn absorb_break(arg: NeverLoopResult) -> NeverLoopResult {
match arg {
NeverLoopResult::AlwaysBreak | NeverLoopResult::Otherwise => NeverLoopResult::Otherwise,
NeverLoopResult::MayContinueMainLoop => NeverLoopResult::MayContinueMainLoop,
+ NeverLoopResult::IgnoreUntilEnd(id) => NeverLoopResult::IgnoreUntilEnd(id),
}
}
@@ -63,27 +67,26 @@ fn absorb_break(arg: NeverLoopResult) -> NeverLoopResult {
#[must_use]
fn combine_seq(first: NeverLoopResult, second: NeverLoopResult) -> NeverLoopResult {
match first {
- NeverLoopResult::AlwaysBreak | NeverLoopResult::MayContinueMainLoop => first,
- NeverLoopResult::Otherwise => second,
- }
-}
-
-// Combine two results where both parts are called but not necessarily in order.
-#[must_use]
-fn combine_both(left: NeverLoopResult, right: NeverLoopResult) -> NeverLoopResult {
- match (left, right) {
- (NeverLoopResult::MayContinueMainLoop, _) | (_, NeverLoopResult::MayContinueMainLoop) => {
- NeverLoopResult::MayContinueMainLoop
+ NeverLoopResult::AlwaysBreak | NeverLoopResult::MayContinueMainLoop | NeverLoopResult::IgnoreUntilEnd(_) => {
+ first
},
- (NeverLoopResult::AlwaysBreak, _) | (_, NeverLoopResult::AlwaysBreak) => NeverLoopResult::AlwaysBreak,
- (NeverLoopResult::Otherwise, NeverLoopResult::Otherwise) => NeverLoopResult::Otherwise,
+ NeverLoopResult::Otherwise => second,
}
}
// Combine two results where only one of the part may have been executed.
#[must_use]
-fn combine_branches(b1: NeverLoopResult, b2: NeverLoopResult) -> NeverLoopResult {
+fn combine_branches(b1: NeverLoopResult, b2: NeverLoopResult, ignore_ids: &[HirId]) -> NeverLoopResult {
match (b1, b2) {
+ (NeverLoopResult::IgnoreUntilEnd(a), NeverLoopResult::IgnoreUntilEnd(b)) => {
+ if ignore_ids.iter().find(|&e| e == &a || e == &b).unwrap() == &a {
+ NeverLoopResult::IgnoreUntilEnd(b)
+ } else {
+ NeverLoopResult::IgnoreUntilEnd(a)
+ }
+ },
+ (i @ NeverLoopResult::IgnoreUntilEnd(_), NeverLoopResult::AlwaysBreak)
+ | (NeverLoopResult::AlwaysBreak, i @ NeverLoopResult::IgnoreUntilEnd(_)) => i,
(NeverLoopResult::AlwaysBreak, NeverLoopResult::AlwaysBreak) => NeverLoopResult::AlwaysBreak,
(NeverLoopResult::MayContinueMainLoop, _) | (_, NeverLoopResult::MayContinueMainLoop) => {
NeverLoopResult::MayContinueMainLoop
@@ -103,7 +106,7 @@ fn never_loop_block(block: &Block<'_>, ignore_ids: &mut Vec<HirId>, main_loop_id
let e = never_loop_expr(e, ignore_ids, main_loop_id);
// els is an else block in a let...else binding
els.map_or(e, |els| {
- combine_branches(e, never_loop_block(els, ignore_ids, main_loop_id))
+ combine_branches(e, never_loop_block(els, ignore_ids, main_loop_id), ignore_ids)
})
})
.fold(NeverLoopResult::Otherwise, combine_seq)
@@ -139,7 +142,7 @@ fn never_loop_expr(expr: &Expr<'_>, ignore_ids: &mut Vec<HirId>, main_loop_id: H
ExprKind::Struct(_, fields, base) => {
let fields = never_loop_expr_all(&mut fields.iter().map(|f| f.expr), ignore_ids, main_loop_id);
if let Some(base) = base {
- combine_both(fields, never_loop_expr(base, ignore_ids, main_loop_id))
+ combine_seq(fields, never_loop_expr(base, ignore_ids, main_loop_id))
} else {
fields
}
@@ -159,7 +162,7 @@ fn never_loop_expr(expr: &Expr<'_>, ignore_ids: &mut Vec<HirId>, main_loop_id: H
let e3 = e3.as_ref().map_or(NeverLoopResult::Otherwise, |e| {
never_loop_expr(e, ignore_ids, main_loop_id)
});
- combine_seq(e1, combine_branches(e2, e3))
+ combine_seq(e1, combine_branches(e2, e3, ignore_ids))
},
ExprKind::Match(e, arms, _) => {
let e = never_loop_expr(e, ignore_ids, main_loop_id);
@@ -175,8 +178,13 @@ fn never_loop_expr(expr: &Expr<'_>, ignore_ids: &mut Vec<HirId>, main_loop_id: H
ignore_ids.push(b.hir_id);
}
let ret = never_loop_block(b, ignore_ids, main_loop_id);
- ignore_ids.pop();
- ret
+ if l.is_some() {
+ ignore_ids.pop();
+ }
+ match ret {
+ NeverLoopResult::IgnoreUntilEnd(a) if a == b.hir_id => NeverLoopResult::Otherwise,
+ _ => ret,
+ }
},
ExprKind::Continue(d) => {
let id = d
@@ -190,8 +198,8 @@ fn never_loop_expr(expr: &Expr<'_>, ignore_ids: &mut Vec<HirId>, main_loop_id: H
},
// checks if break targets a block instead of a loop
ExprKind::Break(Destination { target_id: Ok(t), .. }, e) if ignore_ids.contains(&t) => e
- .map_or(NeverLoopResult::Otherwise, |e| {
- combine_seq(never_loop_expr(e, ignore_ids, main_loop_id), NeverLoopResult::Otherwise)
+ .map_or(NeverLoopResult::IgnoreUntilEnd(t), |e| {
+ never_loop_expr(e, ignore_ids, main_loop_id)
}),
ExprKind::Break(_, e) | ExprKind::Ret(e) => e.as_ref().map_or(NeverLoopResult::AlwaysBreak, |e| {
combine_seq(
@@ -218,13 +226,13 @@ fn never_loop_expr(expr: &Expr<'_>, ignore_ids: &mut Vec<HirId>, main_loop_id: H
| InlineAsmOperand::SymFn { .. }
| InlineAsmOperand::SymStatic { .. } => NeverLoopResult::Otherwise,
})
- .fold(NeverLoopResult::Otherwise, combine_both),
+ .fold(NeverLoopResult::Otherwise, combine_seq),
ExprKind::Yield(_, _)
| ExprKind::Closure { .. }
| ExprKind::Path(_)
| ExprKind::ConstBlock(_)
| ExprKind::Lit(_)
- | ExprKind::Err => NeverLoopResult::Otherwise,
+ | ExprKind::Err(_) => NeverLoopResult::Otherwise,
}
}
@@ -234,7 +242,7 @@ fn never_loop_expr_all<'a, T: Iterator<Item = &'a Expr<'a>>>(
main_loop_id: HirId,
) -> NeverLoopResult {
es.map(|e| never_loop_expr(e, ignore_ids, main_loop_id))
- .fold(NeverLoopResult::Otherwise, combine_both)
+ .fold(NeverLoopResult::Otherwise, combine_seq)
}
fn never_loop_expr_branch<'a, T: Iterator<Item = &'a Expr<'a>>>(
@@ -242,8 +250,9 @@ fn never_loop_expr_branch<'a, T: Iterator<Item = &'a Expr<'a>>>(
ignore_ids: &mut Vec<HirId>,
main_loop_id: HirId,
) -> NeverLoopResult {
- e.map(|e| never_loop_expr(e, ignore_ids, main_loop_id))
- .fold(NeverLoopResult::AlwaysBreak, combine_branches)
+ e.fold(NeverLoopResult::AlwaysBreak, |a, b| {
+ combine_branches(a, never_loop_expr(b, ignore_ids, main_loop_id), ignore_ids)
+ })
}
fn for_to_if_let_sugg(cx: &LateContext<'_>, iterator: &Expr<'_>, pat: &Pat<'_>) -> String {
diff --git a/src/tools/clippy/clippy_lints/src/manual_assert.rs b/src/tools/clippy/clippy_lints/src/manual_assert.rs
index 4277455a3..ce5d657bc 100644
--- a/src/tools/clippy/clippy_lints/src/manual_assert.rs
+++ b/src/tools/clippy/clippy_lints/src/manual_assert.rs
@@ -1,7 +1,6 @@
use crate::rustc_lint::LintContext;
use clippy_utils::diagnostics::span_lint_and_then;
-use clippy_utils::macros::{root_macro_call, FormatArgsExpn};
-use clippy_utils::source::snippet_with_applicability;
+use clippy_utils::macros::root_macro_call;
use clippy_utils::{is_else_clause, peel_blocks_with_stmt, span_extract_comment, sugg};
use rustc_errors::Applicability;
use rustc_hir::{Expr, ExprKind, UnOp};
@@ -38,57 +37,57 @@ declare_lint_pass!(ManualAssert => [MANUAL_ASSERT]);
impl<'tcx> LateLintPass<'tcx> for ManualAssert {
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &Expr<'tcx>) {
- if_chain! {
- if let ExprKind::If(cond, then, None) = expr.kind;
- if !matches!(cond.kind, ExprKind::Let(_));
- if !expr.span.from_expansion();
- let then = peel_blocks_with_stmt(then);
- if let Some(macro_call) = root_macro_call(then.span);
- if cx.tcx.item_name(macro_call.def_id) == sym::panic;
- if !cx.tcx.sess.source_map().is_multiline(cond.span);
- if let Some(format_args) = FormatArgsExpn::find_nested(cx, then, macro_call.expn);
+ if let ExprKind::If(cond, then, None) = expr.kind
+ && !matches!(cond.kind, ExprKind::Let(_))
+ && !expr.span.from_expansion()
+ && let then = peel_blocks_with_stmt(then)
+ && let Some(macro_call) = root_macro_call(then.span)
+ && cx.tcx.item_name(macro_call.def_id) == sym::panic
+ && !cx.tcx.sess.source_map().is_multiline(cond.span)
+ && let Ok(panic_snippet) = cx.sess().source_map().span_to_snippet(macro_call.span)
+ && let Some(panic_snippet) = panic_snippet.strip_suffix(')')
+ && let Some((_, format_args_snip)) = panic_snippet.split_once('(')
// Don't change `else if foo { panic!(..) }` to `else { assert!(foo, ..) }` as it just
// shuffles the condition around.
// Should this have a config value?
- if !is_else_clause(cx.tcx, expr);
- then {
- let mut applicability = Applicability::MachineApplicable;
- let format_args_snip = snippet_with_applicability(cx, format_args.inputs_span(), "..", &mut applicability);
- let cond = cond.peel_drop_temps();
- let mut comments = span_extract_comment(cx.sess().source_map(), expr.span);
- if !comments.is_empty() {
- comments += "\n";
- }
- let (cond, not) = match cond.kind {
- ExprKind::Unary(UnOp::Not, e) => (e, ""),
- _ => (cond, "!"),
- };
- let cond_sugg = sugg::Sugg::hir_with_applicability(cx, cond, "..", &mut applicability).maybe_par();
- let sugg = format!("assert!({not}{cond_sugg}, {format_args_snip});");
- // we show to the user the suggestion without the comments, but when applicating the fix, include the comments in the block
- span_lint_and_then(
- cx,
- MANUAL_ASSERT,
- expr.span,
- "only a `panic!` in `if`-then statement",
- |diag| {
- // comments can be noisy, do not show them to the user
- if !comments.is_empty() {
- diag.tool_only_span_suggestion(
- expr.span.shrink_to_lo(),
- "add comments back",
- comments,
- applicability);
- }
- diag.span_suggestion(
- expr.span,
- "try instead",
- sugg,
- applicability);
- }
-
- );
+ && !is_else_clause(cx.tcx, expr)
+ {
+ let mut applicability = Applicability::MachineApplicable;
+ let cond = cond.peel_drop_temps();
+ let mut comments = span_extract_comment(cx.sess().source_map(), expr.span);
+ if !comments.is_empty() {
+ comments += "\n";
}
+ let (cond, not) = match cond.kind {
+ ExprKind::Unary(UnOp::Not, e) => (e, ""),
+ _ => (cond, "!"),
+ };
+ let cond_sugg = sugg::Sugg::hir_with_applicability(cx, cond, "..", &mut applicability).maybe_par();
+ let sugg = format!("assert!({not}{cond_sugg}, {format_args_snip});");
+ // we show to the user the suggestion without the comments, but when applicating the fix, include the comments in the block
+ span_lint_and_then(
+ cx,
+ MANUAL_ASSERT,
+ expr.span,
+ "only a `panic!` in `if`-then statement",
+ |diag| {
+ // comments can be noisy, do not show them to the user
+ if !comments.is_empty() {
+ diag.tool_only_span_suggestion(
+ expr.span.shrink_to_lo(),
+ "add comments back",
+ comments,
+ applicability
+ );
+ }
+ diag.span_suggestion(
+ expr.span,
+ "try instead",
+ sugg,
+ applicability
+ );
+ }
+ );
}
}
}
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 63212beaa..3778eb4c7 100644
--- a/src/tools/clippy/clippy_lints/src/manual_async_fn.rs
+++ b/src/tools/clippy/clippy_lints/src/manual_async_fn.rs
@@ -6,10 +6,11 @@ use rustc_errors::Applicability;
use rustc_hir::intravisit::FnKind;
use rustc_hir::{
AsyncGeneratorKind, Block, Body, Closure, Expr, ExprKind, FnDecl, FnRetTy, GeneratorKind, GenericArg, GenericBound,
- HirId, ItemKind, LifetimeName, Term, TraitRef, Ty, TyKind, TypeBindingKind,
+ ItemKind, LifetimeName, Term, TraitRef, Ty, TyKind, TypeBindingKind,
};
use rustc_lint::{LateContext, LateLintPass};
use rustc_session::{declare_lint_pass, declare_tool_lint};
+use rustc_span::def_id::LocalDefId;
use rustc_span::{sym, Span};
declare_clippy_lint! {
@@ -45,7 +46,7 @@ impl<'tcx> LateLintPass<'tcx> for ManualAsyncFn {
decl: &'tcx FnDecl<'_>,
body: &'tcx Body<'_>,
span: Span,
- _: HirId,
+ _: LocalDefId,
) {
if_chain! {
if let Some(header) = kind.header();
diff --git a/src/tools/clippy/clippy_lints/src/manual_is_ascii_check.rs b/src/tools/clippy/clippy_lints/src/manual_is_ascii_check.rs
index d9ef7dffa..2fd32c009 100644
--- a/src/tools/clippy/clippy_lints/src/manual_is_ascii_check.rs
+++ b/src/tools/clippy/clippy_lints/src/manual_is_ascii_check.rs
@@ -43,7 +43,7 @@ declare_clippy_lint! {
/// 'A'.is_ascii_uppercase();
/// }
/// ```
- #[clippy::version = "1.66.0"]
+ #[clippy::version = "1.67.0"]
pub MANUAL_IS_ASCII_CHECK,
style,
"use dedicated method to check ascii range"
diff --git a/src/tools/clippy/clippy_lints/src/manual_let_else.rs b/src/tools/clippy/clippy_lints/src/manual_let_else.rs
index 9c6f8b43c..98e698c6c 100644
--- a/src/tools/clippy/clippy_lints/src/manual_let_else.rs
+++ b/src/tools/clippy/clippy_lints/src/manual_let_else.rs
@@ -4,11 +4,12 @@ use clippy_utils::msrvs::{self, Msrv};
use clippy_utils::peel_blocks;
use clippy_utils::source::snippet_with_context;
use clippy_utils::ty::is_type_diagnostic_item;
-use clippy_utils::visitors::{for_each_expr, Descend};
+use clippy_utils::visitors::{Descend, Visitable};
use if_chain::if_chain;
use rustc_data_structures::fx::FxHashSet;
use rustc_errors::Applicability;
-use rustc_hir::{Expr, ExprKind, MatchSource, Pat, PatKind, QPath, Stmt, StmtKind};
+use rustc_hir::intravisit::{walk_expr, Visitor};
+use rustc_hir::{Expr, ExprKind, HirId, ItemId, Local, MatchSource, Pat, PatKind, QPath, Stmt, StmtKind, Ty};
use rustc_lint::{LateContext, LateLintPass, LintContext};
use rustc_middle::lint::in_external_macro;
use rustc_session::{declare_tool_lint, impl_lint_pass};
@@ -115,6 +116,13 @@ impl<'tcx> LateLintPass<'tcx> for ManualLetElse {
.enumerate()
.find(|(_, arm)| expr_diverges(cx, arm.body) && pat_allowed_for_else(cx, arm.pat, check_types));
let Some((idx, diverging_arm)) = diverging_arm_opt else { return; };
+ // If the non-diverging arm is the first one, its pattern can be reused in a let/else statement.
+ // However, if it arrives in second position, its pattern may cover some cases already covered
+ // by the diverging one.
+ // TODO: accept the non-diverging arm as a second position if patterns are disjointed.
+ if idx == 0 {
+ return;
+ }
let pat_arm = &arms[1 - idx];
if !expr_is_simple_identity(pat_arm.pat, pat_arm.body) {
return;
@@ -162,61 +170,102 @@ fn emit_manual_let_else(cx: &LateContext<'_>, span: Span, expr: &Expr<'_>, pat:
);
}
-fn expr_diverges(cx: &LateContext<'_>, expr: &'_ Expr<'_>) -> bool {
- fn is_never(cx: &LateContext<'_>, expr: &'_ Expr<'_>) -> bool {
- if let Some(ty) = cx.typeck_results().expr_ty_opt(expr) {
- return ty.is_never();
- }
- false
+/// Check whether an expression is divergent. May give false negatives.
+fn expr_diverges(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
+ struct V<'cx, 'tcx> {
+ cx: &'cx LateContext<'tcx>,
+ res: ControlFlow<(), Descend>,
}
- // We can't just call is_never on expr and be done, because the type system
- // sometimes coerces the ! type to something different before we can get
- // our hands on it. So instead, we do a manual search. We do fall back to
- // is_never in some places when there is no better alternative.
- for_each_expr(expr, |ex| {
- match ex.kind {
- ExprKind::Continue(_) | ExprKind::Break(_, _) | ExprKind::Ret(_) => ControlFlow::Break(()),
- ExprKind::Call(call, _) => {
- if is_never(cx, ex) || is_never(cx, call) {
- return ControlFlow::Break(());
- }
- ControlFlow::Continue(Descend::Yes)
- },
- ExprKind::MethodCall(..) => {
- if is_never(cx, ex) {
- return ControlFlow::Break(());
- }
- ControlFlow::Continue(Descend::Yes)
- },
- ExprKind::If(if_expr, if_then, if_else) => {
- let else_diverges = if_else.map_or(false, |ex| expr_diverges(cx, ex));
- let diverges = expr_diverges(cx, if_expr) || (else_diverges && expr_diverges(cx, if_then));
- if diverges {
- return ControlFlow::Break(());
+ impl<'tcx> Visitor<'tcx> for V<'_, '_> {
+ fn visit_expr(&mut self, e: &'tcx Expr<'tcx>) {
+ fn is_never(cx: &LateContext<'_>, expr: &'_ Expr<'_>) -> bool {
+ if let Some(ty) = cx.typeck_results().expr_ty_opt(expr) {
+ return ty.is_never();
}
- ControlFlow::Continue(Descend::No)
- },
- ExprKind::Match(match_expr, match_arms, _) => {
- let diverges = expr_diverges(cx, match_expr)
- || match_arms.iter().all(|arm| {
- let guard_diverges = arm.guard.as_ref().map_or(false, |g| expr_diverges(cx, g.body()));
- guard_diverges || expr_diverges(cx, arm.body)
- });
- if diverges {
- return ControlFlow::Break(());
- }
- ControlFlow::Continue(Descend::No)
- },
+ false
+ }
- // Don't continue into loops or labeled blocks, as they are breakable,
- // and we'd have to start checking labels.
- ExprKind::Block(_, Some(_)) | ExprKind::Loop(..) => ControlFlow::Continue(Descend::No),
+ if self.res.is_break() {
+ return;
+ }
- // Default: descend
- _ => ControlFlow::Continue(Descend::Yes),
+ // We can't just call is_never on expr and be done, because the type system
+ // sometimes coerces the ! type to something different before we can get
+ // our hands on it. So instead, we do a manual search. We do fall back to
+ // is_never in some places when there is no better alternative.
+ self.res = match e.kind {
+ ExprKind::Continue(_) | ExprKind::Break(_, _) | ExprKind::Ret(_) => ControlFlow::Break(()),
+ ExprKind::Call(call, _) => {
+ if is_never(self.cx, e) || is_never(self.cx, call) {
+ ControlFlow::Break(())
+ } else {
+ ControlFlow::Continue(Descend::Yes)
+ }
+ },
+ ExprKind::MethodCall(..) => {
+ if is_never(self.cx, e) {
+ ControlFlow::Break(())
+ } else {
+ ControlFlow::Continue(Descend::Yes)
+ }
+ },
+ ExprKind::If(if_expr, if_then, if_else) => {
+ let else_diverges = if_else.map_or(false, |ex| expr_diverges(self.cx, ex));
+ let diverges =
+ expr_diverges(self.cx, if_expr) || (else_diverges && expr_diverges(self.cx, if_then));
+ if diverges {
+ ControlFlow::Break(())
+ } else {
+ ControlFlow::Continue(Descend::No)
+ }
+ },
+ ExprKind::Match(match_expr, match_arms, _) => {
+ let diverges = expr_diverges(self.cx, match_expr)
+ || match_arms.iter().all(|arm| {
+ let guard_diverges = arm.guard.as_ref().map_or(false, |g| expr_diverges(self.cx, g.body()));
+ guard_diverges || expr_diverges(self.cx, arm.body)
+ });
+ if diverges {
+ ControlFlow::Break(())
+ } else {
+ ControlFlow::Continue(Descend::No)
+ }
+ },
+
+ // Don't continue into loops or labeled blocks, as they are breakable,
+ // and we'd have to start checking labels.
+ ExprKind::Block(_, Some(_)) | ExprKind::Loop(..) => ControlFlow::Continue(Descend::No),
+
+ // Default: descend
+ _ => ControlFlow::Continue(Descend::Yes),
+ };
+ if let ControlFlow::Continue(Descend::Yes) = self.res {
+ walk_expr(self, e);
+ }
+ }
+
+ fn visit_local(&mut self, local: &'tcx Local<'_>) {
+ // Don't visit the else block of a let/else statement as it will not make
+ // the statement divergent even though the else block is divergent.
+ if let Some(init) = local.init {
+ self.visit_expr(init);
+ }
}
- })
- .is_some()
+
+ // Avoid unnecessary `walk_*` calls.
+ fn visit_ty(&mut self, _: &'tcx Ty<'tcx>) {}
+ fn visit_pat(&mut self, _: &'tcx Pat<'tcx>) {}
+ fn visit_qpath(&mut self, _: &'tcx QPath<'tcx>, _: HirId, _: Span) {}
+ // Avoid monomorphising all `visit_*` functions.
+ fn visit_nested_item(&mut self, _: ItemId) {}
+ }
+
+ let mut v = V {
+ cx,
+ res: ControlFlow::Continue(Descend::Yes),
+ };
+ expr.visit(&mut v);
+ v.res.is_break()
}
fn pat_allowed_for_else(cx: &LateContext<'_>, pat: &'_ Pat<'_>, check_types: bool) -> bool {
diff --git a/src/tools/clippy/clippy_lints/src/manual_non_exhaustive.rs b/src/tools/clippy/clippy_lints/src/manual_non_exhaustive.rs
index bca193be9..9a84068d4 100644
--- a/src/tools/clippy/clippy_lints/src/manual_non_exhaustive.rs
+++ b/src/tools/clippy/clippy_lints/src/manual_non_exhaustive.rs
@@ -157,11 +157,10 @@ impl<'tcx> LateLintPass<'tcx> for ManualNonExhaustiveEnum {
&& def.variants.len() > 1
{
let mut iter = def.variants.iter().filter_map(|v| {
- let id = cx.tcx.hir().local_def_id(v.hir_id);
- (matches!(v.data, hir::VariantData::Unit(..))
+ (matches!(v.data, hir::VariantData::Unit(_, _))
&& v.ident.as_str().starts_with('_')
&& is_doc_hidden(cx.tcx.hir().attrs(v.hir_id)))
- .then_some((id, v.span))
+ .then_some((v.def_id, v.span))
});
if let Some((id, span)) = iter.next()
&& iter.next().is_none()
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 59195d1ae..edcab6968 100644
--- a/src/tools/clippy/clippy_lints/src/map_unit_fn.rs
+++ b/src/tools/clippy/clippy_lints/src/map_unit_fn.rs
@@ -104,7 +104,7 @@ fn is_unit_function(cx: &LateContext<'_>, expr: &hir::Expr<'_>) -> bool {
let ty = cx.typeck_results().expr_ty(expr);
if let ty::FnDef(id, _) = *ty.kind() {
- if let Some(fn_type) = cx.tcx.fn_sig(id).no_bound_vars() {
+ if let Some(fn_type) = cx.tcx.fn_sig(id).subst_identity().no_bound_vars() {
return is_unit_type(fn_type.output());
}
}
diff --git a/src/tools/clippy/clippy_lints/src/matches/match_wild_enum.rs b/src/tools/clippy/clippy_lints/src/matches/match_wild_enum.rs
index 59de8c038..3126b5901 100644
--- a/src/tools/clippy/clippy_lints/src/matches/match_wild_enum.rs
+++ b/src/tools/clippy/clippy_lints/src/matches/match_wild_enum.rs
@@ -45,8 +45,13 @@ pub(crate) fn check(cx: &LateContext<'_>, ex: &Expr<'_>, arms: &[Arm<'_>]) {
// Accumulate the variants which should be put in place of the wildcard because they're not
// already covered.
- let has_hidden = adt_def.variants().iter().any(|x| is_hidden(cx, x));
- let mut missing_variants: Vec<_> = adt_def.variants().iter().filter(|x| !is_hidden(cx, x)).collect();
+ let is_external = adt_def.did().as_local().is_none();
+ let has_external_hidden = is_external && adt_def.variants().iter().any(|x| is_hidden(cx, x));
+ let mut missing_variants: Vec<_> = adt_def
+ .variants()
+ .iter()
+ .filter(|x| !(is_external && is_hidden(cx, x)))
+ .collect();
let mut path_prefix = CommonPrefixSearcher::None;
for arm in arms {
@@ -133,7 +138,7 @@ pub(crate) fn check(cx: &LateContext<'_>, ex: &Expr<'_>, arms: &[Arm<'_>]) {
match missing_variants.as_slice() {
[] => (),
- [x] if !adt_def.is_variant_list_non_exhaustive() && !has_hidden => span_lint_and_sugg(
+ [x] if !adt_def.is_variant_list_non_exhaustive() && !has_external_hidden => span_lint_and_sugg(
cx,
MATCH_WILDCARD_FOR_SINGLE_VARIANTS,
wildcard_span,
@@ -144,7 +149,7 @@ pub(crate) fn check(cx: &LateContext<'_>, ex: &Expr<'_>, arms: &[Arm<'_>]) {
),
variants => {
let mut suggestions: Vec<_> = variants.iter().copied().map(format_suggestion).collect();
- let message = if adt_def.is_variant_list_non_exhaustive() || has_hidden {
+ let message = if adt_def.is_variant_list_non_exhaustive() || has_external_hidden {
suggestions.push("_".into());
"wildcard matches known variants and will also match future added variants"
} else {
diff --git a/src/tools/clippy/clippy_lints/src/matches/rest_pat_in_fully_bound_struct.rs b/src/tools/clippy/clippy_lints/src/matches/rest_pat_in_fully_bound_struct.rs
index 0aadb482a..d06bcdaa2 100644
--- a/src/tools/clippy/clippy_lints/src/matches/rest_pat_in_fully_bound_struct.rs
+++ b/src/tools/clippy/clippy_lints/src/matches/rest_pat_in_fully_bound_struct.rs
@@ -10,7 +10,7 @@ pub(crate) fn check(cx: &LateContext<'_>, pat: &Pat<'_>) {
if !pat.span.from_expansion();
if let PatKind::Struct(QPath::Resolved(_, path), fields, true) = pat.kind;
if let Some(def_id) = path.res.opt_def_id();
- let ty = cx.tcx.type_of(def_id);
+ let ty = cx.tcx.type_of(def_id).subst_identity();
if let ty::Adt(def, _) = ty.kind();
if def.is_struct() || def.is_union();
if fields.len() == def.non_enum_variant().fields.len();
diff --git a/src/tools/clippy/clippy_lints/src/matches/significant_drop_in_scrutinee.rs b/src/tools/clippy/clippy_lints/src/matches/significant_drop_in_scrutinee.rs
index f587c69f7..b33a24781 100644
--- a/src/tools/clippy/clippy_lints/src/matches/significant_drop_in_scrutinee.rs
+++ b/src/tools/clippy/clippy_lints/src/matches/significant_drop_in_scrutinee.rs
@@ -341,7 +341,7 @@ impl<'a, 'tcx> Visitor<'tcx> for SigDropHelper<'a, 'tcx> {
ExprKind::ConstBlock(_) |
ExprKind::Continue(_) |
ExprKind::DropTemps(_) |
- ExprKind::Err |
+ ExprKind::Err(_) |
ExprKind::InlineAsm(_) |
ExprKind::Let(_) |
ExprKind::Lit(_) |
diff --git a/src/tools/clippy/clippy_lints/src/methods/bytes_count_to_len.rs b/src/tools/clippy/clippy_lints/src/methods/bytes_count_to_len.rs
index 89aaad359..46a20ad41 100644
--- a/src/tools/clippy/clippy_lints/src/methods/bytes_count_to_len.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/bytes_count_to_len.rs
@@ -17,7 +17,7 @@ pub(super) fn check<'tcx>(
if_chain! {
if let Some(bytes_id) = cx.typeck_results().type_dependent_def_id(count_recv.hir_id);
if let Some(impl_id) = cx.tcx.impl_of_method(bytes_id);
- if cx.tcx.type_of(impl_id).is_str();
+ if cx.tcx.type_of(impl_id).subst_identity().is_str();
let ty = cx.typeck_results().expr_ty(bytes_recv).peel_refs();
if ty.is_str() || is_type_lang_item(cx, ty, hir::LangItem::String);
then {
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 d512cc4ee..c5fc145b2 100644
--- a/src/tools/clippy/clippy_lints/src/methods/bytes_nth.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/bytes_nth.rs
@@ -5,6 +5,8 @@ use rustc_errors::Applicability;
use rustc_hir::{Expr, LangItem};
use rustc_lint::LateContext;
+use crate::methods::method_call;
+
use super::BYTES_NTH;
pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'_>, recv: &'tcx Expr<'tcx>, n_arg: &'tcx Expr<'tcx>) {
@@ -16,18 +18,32 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'_>, recv: &'tcx E
} else {
return;
};
+
let mut applicability = Applicability::MachineApplicable;
- span_lint_and_sugg(
- cx,
- BYTES_NTH,
- expr.span,
- &format!("called `.bytes().nth()` on a `{caller_type}`"),
- "try",
- format!(
- "{}.as_bytes().get({})",
- snippet_with_applicability(cx, recv.span, "..", &mut applicability),
- snippet_with_applicability(cx, n_arg.span, "..", &mut applicability)
- ),
- applicability,
- );
+ let receiver = snippet_with_applicability(cx, recv.span, "..", &mut applicability);
+ let n = snippet_with_applicability(cx, n_arg.span, "..", &mut applicability);
+
+ if let Some(parent) = clippy_utils::get_parent_expr(cx, expr)
+ && let Some((name, _, _, _, _)) = method_call(parent)
+ && name == "unwrap" {
+ span_lint_and_sugg(
+ cx,
+ BYTES_NTH,
+ parent.span,
+ &format!("called `.bytes().nth().unwrap()` on a `{caller_type}`"),
+ "try",
+ format!("{receiver}.as_bytes()[{n}]",),
+ applicability
+ );
+ } else {
+ span_lint_and_sugg(
+ cx,
+ BYTES_NTH,
+ expr.span,
+ &format!("called `.bytes().nth()` on a `{caller_type}`"),
+ "try",
+ format!("{receiver}.as_bytes().get({n}).copied()"),
+ applicability
+ );
+ };
}
diff --git a/src/tools/clippy/clippy_lints/src/methods/case_sensitive_file_extension_comparisons.rs b/src/tools/clippy/clippy_lints/src/methods/case_sensitive_file_extension_comparisons.rs
index 0b3bf2274..7711aa78b 100644
--- a/src/tools/clippy/clippy_lints/src/methods/case_sensitive_file_extension_comparisons.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/case_sensitive_file_extension_comparisons.rs
@@ -30,7 +30,7 @@ pub(super) fn check<'tcx>(
if_chain! {
if let Some(method_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id);
if let Some(impl_id) = cx.tcx.impl_of_method(method_id);
- if cx.tcx.type_of(impl_id).is_str();
+ if cx.tcx.type_of(impl_id).subst_identity().is_str();
if let ExprKind::Lit(Spanned { node: LitKind::Str(ext_literal, ..), ..}) = arg.kind;
if (2..=6).contains(&ext_literal.as_str().len());
let ext_str = ext_literal.as_str();
diff --git a/src/tools/clippy/clippy_lints/src/methods/collapsible_str_replace.rs b/src/tools/clippy/clippy_lints/src/methods/collapsible_str_replace.rs
index ac61b4377..5e01ed90f 100644
--- a/src/tools/clippy/clippy_lints/src/methods/collapsible_str_replace.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/collapsible_str_replace.rs
@@ -54,7 +54,7 @@ fn collect_replace_calls<'tcx>(
from_args.push_front(from);
ControlFlow::Continue(())
} else {
- ControlFlow::BREAK
+ ControlFlow::Break(())
}
} else {
ControlFlow::Continue(())
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 a9189b31c..a22285058 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
@@ -33,7 +33,7 @@ pub(super) fn check<'tcx>(
if (method_name.ident.name == sym::as_str || method_name.ident.name == sym::as_ref) && {
let arg_type = cx.typeck_results().expr_ty(receiver);
let base_type = arg_type.peel_refs();
- *base_type.kind() == ty::Str || is_type_lang_item(cx, base_type, hir::LangItem::String)
+ base_type.is_str() || is_type_lang_item(cx, base_type, hir::LangItem::String)
} {
receiver
} else {
@@ -54,7 +54,7 @@ pub(super) fn check<'tcx>(
return false;
}
if let ty::Ref(_, ty, ..) = arg_ty.kind() {
- if *ty.kind() == ty::Str && can_be_static_str(cx, arg) {
+ if ty.is_str() && can_be_static_str(cx, arg) {
return false;
}
};
@@ -70,7 +70,7 @@ pub(super) fn check<'tcx>(
if let hir::ExprKind::Path(ref p) = fun.kind {
match cx.qpath_res(p, fun.hir_id) {
hir::def::Res::Def(hir::def::DefKind::Fn | hir::def::DefKind::AssocFn, def_id) => matches!(
- cx.tcx.fn_sig(def_id).output().skip_binder().kind(),
+ cx.tcx.fn_sig(def_id).subst_identity().output().skip_binder().kind(),
ty::Ref(re, ..) if re.is_static(),
),
_ => false,
@@ -84,7 +84,7 @@ pub(super) fn check<'tcx>(
.type_dependent_def_id(arg.hir_id)
.map_or(false, |method_id| {
matches!(
- cx.tcx.fn_sig(method_id).output().skip_binder().kind(),
+ cx.tcx.fn_sig(method_id).subst_identity().output().skip_binder().kind(),
ty::Ref(re, ..) if re.is_static()
)
})
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 cce8f797e..614610335 100644
--- a/src/tools/clippy/clippy_lints/src/methods/expect_used.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/expect_used.rs
@@ -1,6 +1,6 @@
use clippy_utils::diagnostics::span_lint_and_help;
-use clippy_utils::is_in_cfg_test;
use clippy_utils::ty::is_type_diagnostic_item;
+use clippy_utils::{is_in_cfg_test, is_in_test_function};
use rustc_hir as hir;
use rustc_lint::LateContext;
use rustc_span::sym;
@@ -27,7 +27,7 @@ pub(super) fn check(
let method = if is_err { "expect_err" } else { "expect" };
- if allow_expect_in_tests && is_in_cfg_test(cx.tcx, expr.hir_id) {
+ if allow_expect_in_tests && (is_in_test_function(cx.tcx, expr.hir_id) || is_in_cfg_test(cx.tcx, expr.hir_id)) {
return;
}
diff --git a/src/tools/clippy/clippy_lints/src/methods/get_first.rs b/src/tools/clippy/clippy_lints/src/methods/get_first.rs
index cb17af608..945bbf53b 100644
--- a/src/tools/clippy/clippy_lints/src/methods/get_first.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/get_first.rs
@@ -19,7 +19,7 @@ pub(super) fn check<'tcx>(
if_chain! {
if let Some(method_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id);
if let Some(impl_id) = cx.tcx.impl_of_method(method_id);
- if cx.tcx.type_of(impl_id).is_slice();
+ if cx.tcx.type_of(impl_id).subst_identity().is_slice();
if let Some(_) = is_slice_of_primitives(cx, recv);
if let hir::ExprKind::Lit(Spanned { node: LitKind::Int(0, _), .. }) = arg.kind;
then {
diff --git a/src/tools/clippy/clippy_lints/src/methods/implicit_clone.rs b/src/tools/clippy/clippy_lints/src/methods/implicit_clone.rs
index 06ecbce4e..5a78a4168 100644
--- a/src/tools/clippy/clippy_lints/src/methods/implicit_clone.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/implicit_clone.rs
@@ -53,7 +53,9 @@ pub fn is_clone_like(cx: &LateContext<'_>, method_name: &str, method_def_id: hir
"to_vec" => cx
.tcx
.impl_of_method(method_def_id)
- .filter(|&impl_did| cx.tcx.type_of(impl_did).is_slice() && cx.tcx.impl_trait_ref(impl_did).is_none())
+ .filter(|&impl_did| {
+ cx.tcx.type_of(impl_did).subst_identity().is_slice() && cx.tcx.impl_trait_ref(impl_did).is_none()
+ })
.is_some(),
_ => false,
}
diff --git a/src/tools/clippy/clippy_lints/src/methods/manual_ok_or.rs b/src/tools/clippy/clippy_lints/src/methods/manual_ok_or.rs
index 5b758f1e6..b9a0ec779 100644
--- a/src/tools/clippy/clippy_lints/src/methods/manual_ok_or.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/manual_ok_or.rs
@@ -21,7 +21,7 @@ pub(super) fn check<'tcx>(
if_chain! {
if let Some(method_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id);
if let Some(impl_id) = cx.tcx.impl_of_method(method_id);
- if is_type_diagnostic_item(cx, cx.tcx.type_of(impl_id), sym::Option);
+ if is_type_diagnostic_item(cx, cx.tcx.type_of(impl_id).subst_identity(), sym::Option);
if let ExprKind::Call(err_path, [err_arg]) = or_expr.kind;
if is_res_lang_ctor(cx, path_res(cx, err_path), ResultErr);
if is_ok_wrapping(cx, map_expr);
diff --git a/src/tools/clippy/clippy_lints/src/methods/map_clone.rs b/src/tools/clippy/clippy_lints/src/methods/map_clone.rs
index 52cc1e046..2b26ef014 100644
--- a/src/tools/clippy/clippy_lints/src/methods/map_clone.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/map_clone.rs
@@ -19,7 +19,7 @@ pub(super) fn check(cx: &LateContext<'_>, e: &hir::Expr<'_>, recv: &hir::Expr<'_
if_chain! {
if let Some(method_id) = cx.typeck_results().type_dependent_def_id(e.hir_id);
if cx.tcx.impl_of_method(method_id)
- .map_or(false, |id| is_type_diagnostic_item(cx, cx.tcx.type_of(id), sym::Option))
+ .map_or(false, |id| is_type_diagnostic_item(cx, cx.tcx.type_of(id).subst_identity(), sym::Option))
|| is_diag_trait_item(cx, method_id, sym::Iterator);
if let hir::ExprKind::Closure(&hir::Closure{ body, .. }) = arg.kind;
then {
diff --git a/src/tools/clippy/clippy_lints/src/methods/map_err_ignore.rs b/src/tools/clippy/clippy_lints/src/methods/map_err_ignore.rs
index b773b3e42..a5beb291f 100644
--- a/src/tools/clippy/clippy_lints/src/methods/map_err_ignore.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/map_err_ignore.rs
@@ -9,7 +9,7 @@ use super::MAP_ERR_IGNORE;
pub(super) fn check(cx: &LateContext<'_>, e: &Expr<'_>, arg: &Expr<'_>) {
if let Some(method_id) = cx.typeck_results().type_dependent_def_id(e.hir_id)
&& let Some(impl_id) = cx.tcx.impl_of_method(method_id)
- && is_type_diagnostic_item(cx, cx.tcx.type_of(impl_id), sym::Result)
+ && is_type_diagnostic_item(cx, cx.tcx.type_of(impl_id).subst_identity(), sym::Result)
&& let ExprKind::Closure(&Closure {
capture_clause: CaptureBy::Ref,
body,
diff --git a/src/tools/clippy/clippy_lints/src/methods/mod.rs b/src/tools/clippy/clippy_lints/src/methods/mod.rs
index 77be61b47..702df4b28 100644
--- a/src/tools/clippy/clippy_lints/src/methods/mod.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/mod.rs
@@ -80,6 +80,7 @@ mod skip_while_next;
mod stable_sort_primitive;
mod str_splitn;
mod string_extend_chars;
+mod suspicious_command_arg_space;
mod suspicious_map;
mod suspicious_splitn;
mod suspicious_to_owned;
@@ -1818,6 +1819,7 @@ declare_clippy_lint! {
/// - `or_else` to `or`
/// - `get_or_insert_with` to `get_or_insert`
/// - `ok_or_else` to `ok_or`
+ /// - `then` to `then_some` (for msrv >= 1.62.0)
///
/// ### Why is this bad?
/// Using eager evaluation is shorter and simpler in some cases.
@@ -3102,7 +3104,7 @@ declare_clippy_lint! {
/// Ok(())
/// }
/// ```
- #[clippy::version = "1.66.0"]
+ #[clippy::version = "1.67.0"]
pub SEEK_FROM_CURRENT,
complexity,
"use dedicated method for seek from current position"
@@ -3133,7 +3135,7 @@ declare_clippy_lint! {
/// t.rewind();
/// }
/// ```
- #[clippy::version = "1.66.0"]
+ #[clippy::version = "1.67.0"]
pub SEEK_TO_START_INSTEAD_OF_REWIND,
complexity,
"jumping to the start of stream using `seek` method"
@@ -3161,6 +3163,32 @@ declare_clippy_lint! {
"collecting an iterator when collect is not needed"
}
+declare_clippy_lint! {
+ /// ### What it does
+ ///
+ /// Checks for `Command::arg()` invocations that look like they
+ /// should be multiple arguments instead, such as `arg("-t ext2")`.
+ ///
+ /// ### Why is this bad?
+ ///
+ /// `Command::arg()` does not split arguments by space. An argument like `arg("-t ext2")`
+ /// will be passed as a single argument to the command,
+ /// which is likely not what was intended.
+ ///
+ /// ### Example
+ /// ```rust
+ /// std::process::Command::new("echo").arg("-n hello").spawn().unwrap();
+ /// ```
+ /// Use instead:
+ /// ```rust
+ /// std::process::Command::new("echo").args(["-n", "hello"]).spawn().unwrap();
+ /// ```
+ #[clippy::version = "1.67.0"]
+ pub SUSPICIOUS_COMMAND_ARG_SPACE,
+ suspicious,
+ "single command line argument that looks like it should be multiple arguments"
+}
+
pub struct Methods {
avoid_breaking_exported_api: bool,
msrv: Msrv,
@@ -3288,6 +3316,7 @@ impl_lint_pass!(Methods => [
SEEK_FROM_CURRENT,
SEEK_TO_START_INSTEAD_OF_REWIND,
NEEDLESS_COLLECT,
+ SUSPICIOUS_COMMAND_ARG_SPACE,
]);
/// Extracts a method call name, args, and `Span` of the method name.
@@ -3348,11 +3377,11 @@ impl<'tcx> LateLintPass<'tcx> for Methods {
let name = impl_item.ident.name.as_str();
let parent = cx.tcx.hir().get_parent_item(impl_item.hir_id()).def_id;
let item = cx.tcx.hir().expect_item(parent);
- let self_ty = cx.tcx.type_of(item.owner_id);
+ let self_ty = cx.tcx.type_of(item.owner_id).subst_identity();
let implements_trait = matches!(item.kind, hir::ItemKind::Impl(hir::Impl { of_trait: Some(_), .. }));
if let hir::ImplItemKind::Fn(ref sig, id) = impl_item.kind {
- let method_sig = cx.tcx.fn_sig(impl_item.owner_id);
+ let method_sig = cx.tcx.fn_sig(impl_item.owner_id).subst_identity();
let method_sig = cx.tcx.erase_late_bound_regions(method_sig);
let first_arg_ty_opt = method_sig.inputs().iter().next().copied();
// if this impl block implements a trait, lint in trait definition instead
@@ -3412,7 +3441,7 @@ impl<'tcx> LateLintPass<'tcx> for Methods {
}
if let hir::ImplItemKind::Fn(_, _) = impl_item.kind {
- let ret_ty = return_ty(cx, impl_item.hir_id());
+ let ret_ty = return_ty(cx, impl_item.owner_id);
if contains_ty_adt_constructor_opaque(cx, ret_ty, self_ty) {
return;
@@ -3460,7 +3489,7 @@ impl<'tcx> LateLintPass<'tcx> for Methods {
if_chain! {
if item.ident.name == sym::new;
if let TraitItemKind::Fn(_, _) = item.kind;
- let ret_ty = return_ty(cx, item.hir_id());
+ let ret_ty = return_ty(cx, item.owner_id);
let self_ty = TraitRef::identity(cx.tcx, item.owner_id.to_def_id())
.self_ty()
.skip_binder();
@@ -3495,6 +3524,9 @@ impl Methods {
unnecessary_lazy_eval::check(cx, expr, recv, arg, "and");
}
},
+ ("arg", [arg]) => {
+ suspicious_command_arg_space::check(cx, recv, arg, span);
+ }
("as_deref" | "as_deref_mut", []) => {
needless_option_as_deref::check(cx, expr, recv, name);
},
diff --git a/src/tools/clippy/clippy_lints/src/methods/mut_mutex_lock.rs b/src/tools/clippy/clippy_lints/src/methods/mut_mutex_lock.rs
index b9593b368..d0aa39d06 100644
--- a/src/tools/clippy/clippy_lints/src/methods/mut_mutex_lock.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/mut_mutex_lock.rs
@@ -15,7 +15,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, ex: &'tcx Expr<'tcx>, recv: &'
if let ty::Ref(_, _, Mutability::Mut) = cx.typeck_results().expr_ty(recv).kind();
if let Some(method_id) = cx.typeck_results().type_dependent_def_id(ex.hir_id);
if let Some(impl_id) = cx.tcx.impl_of_method(method_id);
- if is_type_diagnostic_item(cx, cx.tcx.type_of(impl_id), sym::Mutex);
+ if is_type_diagnostic_item(cx, cx.tcx.type_of(impl_id).subst_identity(), sym::Mutex);
then {
span_lint_and_sugg(
cx,
diff --git a/src/tools/clippy/clippy_lints/src/methods/needless_collect.rs b/src/tools/clippy/clippy_lints/src/methods/needless_collect.rs
index f4d3ef3b7..0b0c6adc5 100644
--- a/src/tools/clippy/clippy_lints/src/methods/needless_collect.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/needless_collect.rs
@@ -137,7 +137,7 @@ pub(super) fn check<'tcx>(
/// Checks if the given method call matches the expected signature of `([&[mut]] self) -> bool`
fn is_is_empty_sig(cx: &LateContext<'_>, call_id: HirId) -> bool {
cx.typeck_results().type_dependent_def_id(call_id).map_or(false, |id| {
- let sig = cx.tcx.fn_sig(id).skip_binder();
+ let sig = cx.tcx.fn_sig(id).subst_identity().skip_binder();
sig.inputs().len() == 1 && sig.output().is_bool()
})
}
@@ -165,7 +165,7 @@ fn iterates_same_ty<'tcx>(cx: &LateContext<'tcx>, iter_ty: Ty<'tcx>, collect_ty:
fn is_contains_sig(cx: &LateContext<'_>, call_id: HirId, iter_expr: &Expr<'_>) -> bool {
let typeck = cx.typeck_results();
if let Some(id) = typeck.type_dependent_def_id(call_id)
- && let sig = cx.tcx.fn_sig(id)
+ && let sig = cx.tcx.fn_sig(id).subst_identity()
&& sig.skip_binder().output().is_bool()
&& let [_, search_ty] = *sig.skip_binder().inputs()
&& let ty::Ref(_, search_ty, Mutability::Not) = *cx.tcx.erase_late_bound_regions(sig.rebind(search_ty)).kind()
@@ -173,7 +173,7 @@ fn is_contains_sig(cx: &LateContext<'_>, call_id: HirId, iter_expr: &Expr<'_>) -
&& let Some(iter_item) = cx.tcx
.associated_items(iter_trait)
.find_by_name_and_kind(cx.tcx, Ident::with_dummy_span(Symbol::intern("Item")), AssocKind::Type, iter_trait)
- && let substs = cx.tcx.mk_substs([GenericArg::from(typeck.expr_ty_adjusted(iter_expr))].into_iter())
+ && let substs = cx.tcx.mk_substs(&[GenericArg::from(typeck.expr_ty_adjusted(iter_expr))])
&& let proj_ty = cx.tcx.mk_projection(iter_item.def_id, substs)
&& let Ok(item_ty) = cx.tcx.try_normalize_erasing_regions(cx.param_env, proj_ty)
{
diff --git a/src/tools/clippy/clippy_lints/src/methods/open_options.rs b/src/tools/clippy/clippy_lints/src/methods/open_options.rs
index 597af853d..c6a27cdd6 100644
--- a/src/tools/clippy/clippy_lints/src/methods/open_options.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/open_options.rs
@@ -11,7 +11,7 @@ use super::NONSENSICAL_OPEN_OPTIONS;
pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>, recv: &'tcx Expr<'_>) {
if let Some(method_id) = cx.typeck_results().type_dependent_def_id(e.hir_id)
&& let Some(impl_id) = cx.tcx.impl_of_method(method_id)
- && match_type(cx, cx.tcx.type_of(impl_id), &paths::OPEN_OPTIONS)
+ && match_type(cx, cx.tcx.type_of(impl_id).subst_identity(), &paths::OPEN_OPTIONS)
{
let mut options = Vec::new();
get_open_options(cx, recv, &mut options);
diff --git a/src/tools/clippy/clippy_lints/src/methods/path_buf_push_overwrite.rs b/src/tools/clippy/clippy_lints/src/methods/path_buf_push_overwrite.rs
index 0cc28c0dc..e3f2de3cd 100644
--- a/src/tools/clippy/clippy_lints/src/methods/path_buf_push_overwrite.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/path_buf_push_overwrite.rs
@@ -14,7 +14,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, arg: &'t
if_chain! {
if let Some(method_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id);
if let Some(impl_id) = cx.tcx.impl_of_method(method_id);
- if is_type_diagnostic_item(cx, cx.tcx.type_of(impl_id), sym::PathBuf);
+ if is_type_diagnostic_item(cx, cx.tcx.type_of(impl_id).subst_identity(), sym::PathBuf);
if let ExprKind::Lit(ref lit) = arg.kind;
if let LitKind::Str(ref path_lit, _) = lit.node;
if let pushed_path = Path::new(path_lit.as_str());
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 1c031ad6a..afdb8ce94 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
@@ -8,7 +8,6 @@ use rustc_errors::Applicability;
use rustc_hir as hir;
use rustc_hir::PatKind;
use rustc_lint::LateContext;
-use rustc_middle::ty;
use rustc_span::source_map::Span;
use rustc_span::symbol::sym;
@@ -108,7 +107,7 @@ pub(super) fn check<'tcx>(
if is_type_lang_item(cx, self_ty, hir::LangItem::String) {
true
} else {
- *self_ty.kind() == ty::Str
+ self_ty.is_str()
}
};
if_chain! {
diff --git a/src/tools/clippy/clippy_lints/src/methods/single_char_pattern.rs b/src/tools/clippy/clippy_lints/src/methods/single_char_pattern.rs
index 4221c52d5..4d704ec39 100644
--- a/src/tools/clippy/clippy_lints/src/methods/single_char_pattern.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/single_char_pattern.rs
@@ -47,7 +47,7 @@ pub(super) fn check(
for &(method, pos) in &PATTERN_METHODS {
if_chain! {
if let ty::Ref(_, ty, _) = cx.typeck_results().expr_ty_adjusted(receiver).kind();
- if *ty.kind() == ty::Str;
+ if ty.is_str();
if method_name.as_str() == method && args.len() > pos;
let arg = &args[pos];
let mut applicability = Applicability::MachineApplicable;
diff --git a/src/tools/clippy/clippy_lints/src/methods/stable_sort_primitive.rs b/src/tools/clippy/clippy_lints/src/methods/stable_sort_primitive.rs
index 09c8ca4cb..b5fd0ad8c 100644
--- a/src/tools/clippy/clippy_lints/src/methods/stable_sort_primitive.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/stable_sort_primitive.rs
@@ -10,7 +10,7 @@ use super::STABLE_SORT_PRIMITIVE;
pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>, recv: &'tcx Expr<'_>) {
if let Some(method_id) = cx.typeck_results().type_dependent_def_id(e.hir_id)
&& let Some(impl_id) = cx.tcx.impl_of_method(method_id)
- && cx.tcx.type_of(impl_id).is_slice()
+ && cx.tcx.type_of(impl_id).subst_identity().is_slice()
&& let Some(slice_type) = is_slice_of_primitives(cx, recv)
{
span_lint_and_then(
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 f35d81cee..2c20c6d75 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
@@ -5,7 +5,6 @@ use clippy_utils::ty::is_type_lang_item;
use rustc_errors::Applicability;
use rustc_hir as hir;
use rustc_lint::LateContext;
-use rustc_middle::ty;
use super::STRING_EXTEND_CHARS;
@@ -17,7 +16,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, recv: &hir::Expr
if let Some(arglists) = method_chain_args(arg, &["chars"]) {
let target = &arglists[0].0;
let self_ty = cx.typeck_results().expr_ty(target).peel_refs();
- let ref_str = if *self_ty.kind() == ty::Str {
+ let ref_str = if self_ty.is_str() {
if matches!(target.kind, hir::ExprKind::Index(..)) {
"&"
} else {
diff --git a/src/tools/clippy/clippy_lints/src/methods/suspicious_command_arg_space.rs b/src/tools/clippy/clippy_lints/src/methods/suspicious_command_arg_space.rs
new file mode 100644
index 000000000..73632c5a3
--- /dev/null
+++ b/src/tools/clippy/clippy_lints/src/methods/suspicious_command_arg_space.rs
@@ -0,0 +1,39 @@
+use clippy_utils::diagnostics::span_lint_and_then;
+use clippy_utils::paths;
+use clippy_utils::ty::match_type;
+use rustc_ast as ast;
+use rustc_errors::{Applicability, Diagnostic};
+use rustc_hir as hir;
+use rustc_lint::LateContext;
+use rustc_span::Span;
+
+use super::SUSPICIOUS_COMMAND_ARG_SPACE;
+
+pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, recv: &'tcx hir::Expr<'_>, arg: &'tcx hir::Expr<'_>, span: Span) {
+ let ty = cx.typeck_results().expr_ty(recv).peel_refs();
+
+ if match_type(cx, ty, &paths::STD_PROCESS_COMMAND)
+ && let hir::ExprKind::Lit(lit) = &arg.kind
+ && let ast::LitKind::Str(s, _) = &lit.node
+ && let Some((arg1, arg2)) = s.as_str().split_once(' ')
+ && arg1.starts_with('-')
+ && arg1.chars().all(|c| c.is_ascii_alphanumeric() || c == '_' || c == '-')
+ {
+ span_lint_and_then(
+ cx,
+ SUSPICIOUS_COMMAND_ARG_SPACE,
+ arg.span,
+ "single argument that looks like it should be multiple arguments",
+ |diag: &mut Diagnostic| {
+ diag.multipart_suggestion_verbose(
+ "consider splitting the argument",
+ vec![
+ (span, "args".to_string()),
+ (arg.span, format!("[{arg1:?}, {arg2:?}]")),
+ ],
+ Applicability::MaybeIncorrect,
+ );
+ }
+ );
+ }
+}
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 2ac0786b3..0dc7fe2a2 100644
--- a/src/tools/clippy/clippy_lints/src/methods/suspicious_map.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/suspicious_map.rs
@@ -11,10 +11,8 @@ use super::SUSPICIOUS_MAP;
pub fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, count_recv: &hir::Expr<'_>, map_arg: &hir::Expr<'_>) {
if_chain! {
if is_trait_method(cx, count_recv, sym::Iterator);
- let closure = expr_or_init(cx, map_arg);
- if let Some(def_id) = cx.tcx.hir().opt_local_def_id(closure.hir_id);
- if let Some(body_id) = cx.tcx.hir().maybe_body_owned_by(def_id);
- let closure_body = cx.tcx.hir().body(body_id);
+ if let hir::ExprKind::Closure(closure) = expr_or_init(cx, map_arg).kind;
+ let closure_body = cx.tcx.hir().body(closure.body);
if !cx.typeck_results().expr_ty(closure_body.value).is_unit();
then {
if let Some(map_mutated_vars) = mutated_variables(closure_body.value, cx) {
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 219a9edd6..90ca66bd7 100644
--- a/src/tools/clippy/clippy_lints/src/methods/suspicious_splitn.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/suspicious_splitn.rs
@@ -13,7 +13,7 @@ pub(super) fn check(cx: &LateContext<'_>, method_name: &str, expr: &Expr<'_>, se
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);
if cx.tcx.impl_trait_ref(impl_id).is_none();
- let self_ty = cx.tcx.type_of(impl_id);
+ let self_ty = cx.tcx.type_of(impl_id).subst_identity();
if self_ty.is_slice() || self_ty.is_str();
then {
// Ignore empty slice and string literals when used with a literal count.
diff --git a/src/tools/clippy/clippy_lints/src/methods/suspicious_to_owned.rs b/src/tools/clippy/clippy_lints/src/methods/suspicious_to_owned.rs
index fe88fa41f..e818f1892 100644
--- a/src/tools/clippy/clippy_lints/src/methods/suspicious_to_owned.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/suspicious_to_owned.rs
@@ -1,4 +1,4 @@
-use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::is_diag_trait_item;
use clippy_utils::source::snippet_with_context;
use if_chain::if_chain;
@@ -17,19 +17,31 @@ pub fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, recv: &hir::Expr<'_>) -
let input_type = cx.typeck_results().expr_ty(expr);
if let ty::Adt(adt, _) = cx.typeck_results().expr_ty(expr).kind();
if cx.tcx.is_diagnostic_item(sym::Cow, adt.did());
+
then {
let mut app = Applicability::MaybeIncorrect;
let recv_snip = snippet_with_context(cx, recv.span, expr.span.ctxt(), "..", &mut app).0;
- span_lint_and_sugg(
+ span_lint_and_then(
cx,
SUSPICIOUS_TO_OWNED,
expr.span,
&with_forced_trimmed_paths!(format!(
"this `to_owned` call clones the {input_type} itself and does not cause the {input_type} contents to become owned"
)),
- "consider using, depending on intent",
- format!("{recv_snip}.clone()` or `{recv_snip}.into_owned()"),
- app,
+ |diag| {
+ diag.span_suggestion(
+ expr.span,
+ "depending on intent, either make the Cow an Owned variant",
+ format!("{recv_snip}.into_owned()"),
+ app
+ );
+ diag.span_suggestion(
+ expr.span,
+ "or clone the Cow itself",
+ format!("{recv_snip}.clone()"),
+ app
+ );
+ }
);
return true;
}
diff --git a/src/tools/clippy/clippy_lints/src/methods/unnecessary_sort_by.rs b/src/tools/clippy/clippy_lints/src/methods/unnecessary_sort_by.rs
index ed5a75b0f..5201da52b 100644
--- a/src/tools/clippy/clippy_lints/src/methods/unnecessary_sort_by.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/unnecessary_sort_by.rs
@@ -122,7 +122,7 @@ fn detect_lint(cx: &LateContext<'_>, expr: &Expr<'_>, recv: &Expr<'_>, arg: &Exp
if_chain! {
if let Some(method_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id);
if let Some(impl_id) = cx.tcx.impl_of_method(method_id);
- if cx.tcx.type_of(impl_id).is_slice();
+ if cx.tcx.type_of(impl_id).subst_identity().is_slice();
if let ExprKind::Closure(&Closure { body, .. }) = arg.kind;
if let closure_body = cx.tcx.hir().body(body);
if let &[
diff --git a/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs b/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs
index 9263f0519..df26b36b7 100644
--- a/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs
@@ -246,7 +246,7 @@ fn check_other_call_arg<'tcx>(
if_chain! {
if let Some((maybe_call, maybe_arg)) = skip_addr_of_ancestors(cx, expr);
if let Some((callee_def_id, _, recv, call_args)) = get_callee_substs_and_args(cx, maybe_call);
- let fn_sig = cx.tcx.fn_sig(callee_def_id).skip_binder();
+ let fn_sig = cx.tcx.fn_sig(callee_def_id).subst_identity().skip_binder();
if let Some(i) = recv.into_iter().chain(call_args).position(|arg| arg.hir_id == maybe_arg.hir_id);
if let Some(input) = fn_sig.inputs().get(i);
let (input, n_refs) = peel_mid_ty_refs(*input);
@@ -368,10 +368,9 @@ fn can_change_type<'a>(cx: &LateContext<'a>, mut expr: &'a Expr<'a>, mut ty: Ty<
Node::Block(..) => continue,
Node::Item(item) => {
if let ItemKind::Fn(_, _, body_id) = &item.kind
- && let output_ty = return_ty(cx, item.hir_id())
- && let local_def_id = cx.tcx.hir().local_def_id(item.hir_id())
- && Inherited::build(cx.tcx, local_def_id).enter(|inherited| {
- let fn_ctxt = FnCtxt::new(inherited, cx.param_env, item.hir_id());
+ && let output_ty = return_ty(cx, item.owner_id)
+ && Inherited::build(cx.tcx, item.owner_id.def_id).enter(|inherited| {
+ let fn_ctxt = FnCtxt::new(inherited, cx.param_env, item.owner_id.def_id);
fn_ctxt.can_coerce(ty, output_ty)
}) {
if has_lifetime(output_ty) && has_lifetime(ty) {
@@ -386,7 +385,7 @@ fn can_change_type<'a>(cx: &LateContext<'a>, mut expr: &'a Expr<'a>, mut ty: Ty<
Node::Expr(parent_expr) => {
if let Some((callee_def_id, call_substs, recv, call_args)) = get_callee_substs_and_args(cx, parent_expr)
{
- let fn_sig = cx.tcx.fn_sig(callee_def_id).skip_binder();
+ let fn_sig = cx.tcx.fn_sig(callee_def_id).subst_identity().skip_binder();
if let Some(arg_index) = recv.into_iter().chain(call_args).position(|arg| arg.hir_id == expr.hir_id)
&& let Some(param_ty) = fn_sig.inputs().get(arg_index)
&& let ty::Param(ParamTy { index: param_index , ..}) = param_ty.kind()
@@ -415,7 +414,7 @@ fn can_change_type<'a>(cx: &LateContext<'a>, mut expr: &'a Expr<'a>, mut ty: Ty<
}
});
- let new_subst = cx.tcx.mk_substs(
+ let new_subst = cx.tcx.mk_substs_from_iter(
call_substs.iter()
.enumerate()
.map(|(i, t)|
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 90983f249..5e4c3daee 100644
--- a/src/tools/clippy/clippy_lints/src/methods/unwrap_used.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/unwrap_used.rs
@@ -1,6 +1,6 @@
use clippy_utils::diagnostics::span_lint_and_help;
use clippy_utils::ty::is_type_diagnostic_item;
-use clippy_utils::{is_in_cfg_test, is_lint_allowed};
+use clippy_utils::{is_in_cfg_test, is_in_test_function, is_lint_allowed};
use rustc_hir as hir;
use rustc_lint::LateContext;
use rustc_span::sym;
@@ -27,7 +27,7 @@ pub(super) fn check(
let method_suffix = if is_err { "_err" } else { "" };
- if allow_unwrap_in_tests && is_in_cfg_test(cx.tcx, expr.hir_id) {
+ if allow_unwrap_in_tests && (is_in_test_function(cx.tcx, expr.hir_id) || is_in_cfg_test(cx.tcx, expr.hir_id)) {
return;
}
diff --git a/src/tools/clippy/clippy_lints/src/methods/utils.rs b/src/tools/clippy/clippy_lints/src/methods/utils.rs
index ae6b165fd..c96d69226 100644
--- a/src/tools/clippy/clippy_lints/src/methods/utils.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/utils.rs
@@ -22,7 +22,7 @@ pub(super) fn derefs_to_slice<'tcx>(
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),
- ty::Array(_, size) => size.try_eval_usize(cx.tcx, cx.param_env).is_some(),
+ ty::Array(_, size) => size.try_eval_target_usize(cx.tcx, cx.param_env).is_some(),
ty::Ref(_, inner, _) => may_slice(cx, *inner),
_ => false,
}
@@ -143,7 +143,7 @@ impl<'cx, 'tcx> Visitor<'tcx> for CloneOrCopyVisitor<'cx, 'tcx> {
if_chain! {
if args.iter().all(|arg| !self.is_binding(arg));
if let Some(method_def_id) = self.cx.typeck_results().type_dependent_def_id(parent.hir_id);
- let method_ty = self.cx.tcx.type_of(method_def_id);
+ let method_ty = self.cx.tcx.type_of(method_def_id).subst_identity();
let self_ty = method_ty.fn_sig(self.cx.tcx).input(0).skip_binder();
if matches!(self_ty.kind(), ty::Ref(_, _, Mutability::Not));
then {
diff --git a/src/tools/clippy/clippy_lints/src/methods/vec_resize_to_zero.rs b/src/tools/clippy/clippy_lints/src/methods/vec_resize_to_zero.rs
index 02d8364cb..b0cfc163f 100644
--- a/src/tools/clippy/clippy_lints/src/methods/vec_resize_to_zero.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/vec_resize_to_zero.rs
@@ -20,7 +20,7 @@ pub(super) fn check<'tcx>(
if_chain! {
if let Some(method_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id);
if let Some(impl_id) = cx.tcx.impl_of_method(method_id);
- if is_type_diagnostic_item(cx, cx.tcx.type_of(impl_id), sym::Vec);
+ if is_type_diagnostic_item(cx, cx.tcx.type_of(impl_id).subst_identity(), sym::Vec);
if let ExprKind::Lit(Spanned { node: LitKind::Int(0, _), .. }) = count_arg.kind;
if let ExprKind::Lit(Spanned { node: LitKind::Int(..), .. }) = default_arg.kind;
then {
diff --git a/src/tools/clippy/clippy_lints/src/misc.rs b/src/tools/clippy/clippy_lints/src/misc.rs
index 9f4beb92b..0705029a6 100644
--- a/src/tools/clippy/clippy_lints/src/misc.rs
+++ b/src/tools/clippy/clippy_lints/src/misc.rs
@@ -4,12 +4,13 @@ use if_chain::if_chain;
use rustc_errors::Applicability;
use rustc_hir::intravisit::FnKind;
use rustc_hir::{
- self as hir, def, BinOpKind, BindingAnnotation, Body, ByRef, Expr, ExprKind, FnDecl, HirId, Mutability, PatKind,
- Stmt, StmtKind, TyKind,
+ self as hir, def, BinOpKind, BindingAnnotation, Body, ByRef, Expr, ExprKind, FnDecl, Mutability, PatKind, Stmt,
+ StmtKind, TyKind,
};
use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::lint::in_external_macro;
use rustc_session::{declare_tool_lint, impl_lint_pass};
+use rustc_span::def_id::LocalDefId;
use rustc_span::hygiene::DesugaringKind;
use rustc_span::source_map::{ExpnKind, Span};
@@ -151,7 +152,7 @@ impl<'tcx> LateLintPass<'tcx> for LintPass {
decl: &'tcx FnDecl<'_>,
body: &'tcx Body<'_>,
span: Span,
- _: HirId,
+ _: LocalDefId,
) {
if let FnKind::Closure = k {
// Does not apply to closures
diff --git a/src/tools/clippy/clippy_lints/src/missing_const_for_fn.rs b/src/tools/clippy/clippy_lints/src/missing_const_for_fn.rs
index 5bc04bc17..87bd007a2 100644
--- a/src/tools/clippy/clippy_lints/src/missing_const_for_fn.rs
+++ b/src/tools/clippy/clippy_lints/src/missing_const_for_fn.rs
@@ -6,11 +6,12 @@ use clippy_utils::{fn_has_unsatisfiable_preds, is_entrypoint_fn, is_from_proc_ma
use rustc_hir as hir;
use rustc_hir::def_id::CRATE_DEF_ID;
use rustc_hir::intravisit::FnKind;
-use rustc_hir::{Body, Constness, FnDecl, GenericParamKind, HirId};
+use rustc_hir::{Body, Constness, FnDecl, GenericParamKind};
use rustc_hir_analysis::hir_ty_to_ty;
use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::lint::in_external_macro;
use rustc_session::{declare_tool_lint, impl_lint_pass};
+use rustc_span::def_id::LocalDefId;
use rustc_span::Span;
declare_clippy_lint! {
@@ -91,14 +92,12 @@ impl<'tcx> LateLintPass<'tcx> for MissingConstForFn {
_: &FnDecl<'_>,
body: &Body<'tcx>,
span: Span,
- hir_id: HirId,
+ def_id: LocalDefId,
) {
if !self.msrv.meets(msrvs::CONST_IF_MATCH) {
return;
}
- let def_id = cx.tcx.hir().local_def_id(hir_id);
-
if in_external_macro(cx.tcx.sess, span) || is_entrypoint_fn(cx, def_id.to_def_id()) {
return;
}
@@ -132,6 +131,8 @@ impl<'tcx> LateLintPass<'tcx> for MissingConstForFn {
FnKind::Closure => return,
}
+ let hir_id = cx.tcx.hir().local_def_id_to_hir_id(def_id);
+
// Const fns are not allowed as methods in a trait.
{
let parent = cx.tcx.hir().get_parent_item(hir_id).def_id;
diff --git a/src/tools/clippy/clippy_lints/src/missing_doc.rs b/src/tools/clippy/clippy_lints/src/missing_doc.rs
index 6fd100762..9659ca8ce 100644
--- a/src/tools/clippy/clippy_lints/src/missing_doc.rs
+++ b/src/tools/clippy/clippy_lints/src/missing_doc.rs
@@ -8,10 +8,12 @@
use clippy_utils::attrs::is_doc_hidden;
use clippy_utils::diagnostics::span_lint;
use clippy_utils::is_from_proc_macro;
+use hir::def_id::LocalDefId;
+use if_chain::if_chain;
use rustc_ast::ast::{self, MetaItem, MetaItemKind};
use rustc_hir as hir;
use rustc_lint::{LateContext, LateLintPass, LintContext};
-use rustc_middle::ty::DefIdTree;
+use rustc_middle::ty::{DefIdTree, Visibility};
use rustc_session::{declare_tool_lint, impl_lint_pass};
use rustc_span::def_id::CRATE_DEF_ID;
use rustc_span::source_map::Span;
@@ -34,6 +36,9 @@ declare_clippy_lint! {
}
pub struct MissingDoc {
+ /// Whether to **only** check for missing documentation in items visible within the current
+ /// crate. For example, `pub(crate)` items.
+ crate_items_only: bool,
/// Stack of whether #[doc(hidden)] is set
/// at each level which has lint attributes.
doc_hidden_stack: Vec<bool>,
@@ -42,14 +47,15 @@ pub struct MissingDoc {
impl Default for MissingDoc {
#[must_use]
fn default() -> Self {
- Self::new()
+ Self::new(false)
}
}
impl MissingDoc {
#[must_use]
- pub fn new() -> Self {
+ pub fn new(crate_items_only: bool) -> Self {
Self {
+ crate_items_only,
doc_hidden_stack: vec![false],
}
}
@@ -75,6 +81,7 @@ impl MissingDoc {
fn check_missing_docs_attrs(
&self,
cx: &LateContext<'_>,
+ def_id: LocalDefId,
attrs: &[ast::Attribute],
sp: Span,
article: &'static str,
@@ -95,6 +102,13 @@ impl MissingDoc {
return;
}
+ if self.crate_items_only && def_id != CRATE_DEF_ID {
+ let vis = cx.tcx.visibility(def_id);
+ if vis == Visibility::Public || vis != Visibility::Restricted(CRATE_DEF_ID.into()) {
+ return;
+ }
+ }
+
let has_doc = attrs
.iter()
.any(|a| a.doc_str().is_some() || Self::has_include(a.meta()));
@@ -123,7 +137,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingDoc {
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, cx.tcx.def_span(CRATE_DEF_ID), "the", "crate");
+ self.check_missing_docs_attrs(cx, CRATE_DEF_ID, attrs, cx.tcx.def_span(CRATE_DEF_ID), "the", "crate");
}
fn check_item(&mut self, cx: &LateContext<'tcx>, it: &'tcx hir::Item<'_>) {
@@ -159,7 +173,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingDoc {
let attrs = cx.tcx.hir().attrs(it.hir_id());
if !is_from_proc_macro(cx, it) {
- self.check_missing_docs_attrs(cx, attrs, it.span, article, desc);
+ self.check_missing_docs_attrs(cx, it.owner_id.def_id, attrs, it.span, article, desc);
}
}
@@ -168,7 +182,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingDoc {
let attrs = cx.tcx.hir().attrs(trait_item.hir_id());
if !is_from_proc_macro(cx, trait_item) {
- self.check_missing_docs_attrs(cx, attrs, trait_item.span, article, desc);
+ self.check_missing_docs_attrs(cx, trait_item.owner_id.def_id, attrs, trait_item.span, article, desc);
}
}
@@ -185,7 +199,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingDoc {
let (article, desc) = cx.tcx.article_and_description(impl_item.owner_id.to_def_id());
let attrs = cx.tcx.hir().attrs(impl_item.hir_id());
if !is_from_proc_macro(cx, impl_item) {
- self.check_missing_docs_attrs(cx, attrs, impl_item.span, article, desc);
+ self.check_missing_docs_attrs(cx, impl_item.owner_id.def_id, attrs, impl_item.span, article, desc);
}
}
@@ -193,7 +207,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingDoc {
if !sf.is_positional() {
let attrs = cx.tcx.hir().attrs(sf.hir_id);
if !is_from_proc_macro(cx, sf) {
- self.check_missing_docs_attrs(cx, attrs, sf.span, "a", "struct field");
+ self.check_missing_docs_attrs(cx, sf.def_id, attrs, sf.span, "a", "struct field");
}
}
}
@@ -201,7 +215,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingDoc {
fn check_variant(&mut self, cx: &LateContext<'tcx>, v: &'tcx hir::Variant<'_>) {
let attrs = cx.tcx.hir().attrs(v.hir_id);
if !is_from_proc_macro(cx, v) {
- self.check_missing_docs_attrs(cx, attrs, v.span, "a", "variant");
+ self.check_missing_docs_attrs(cx, v.def_id, attrs, v.span, "a", "variant");
}
}
}
diff --git a/src/tools/clippy/clippy_lints/src/missing_trait_methods.rs b/src/tools/clippy/clippy_lints/src/missing_trait_methods.rs
index 3371b4cce..e99081ad0 100644
--- a/src/tools/clippy/clippy_lints/src/missing_trait_methods.rs
+++ b/src/tools/clippy/clippy_lints/src/missing_trait_methods.rs
@@ -94,7 +94,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingTraitMethods {
"implement the method",
);
}
- })
+ });
}
}
}
diff --git a/src/tools/clippy/clippy_lints/src/module_style.rs b/src/tools/clippy/clippy_lints/src/module_style.rs
index 0742943df..349fcd227 100644
--- a/src/tools/clippy/clippy_lints/src/module_style.rs
+++ b/src/tools/clippy/clippy_lints/src/module_style.rs
@@ -134,7 +134,7 @@ fn process_paths_for_mod_files<'a>(
mod_folders: &mut FxHashSet<&'a OsStr>,
) {
let mut comp = path.components().rev().peekable();
- let _ = comp.next();
+ let _: Option<_> = comp.next();
if path.ends_with("mod.rs") {
mod_folders.insert(comp.peek().map(|c| c.as_os_str()).unwrap_or_default());
}
diff --git a/src/tools/clippy/clippy_lints/src/multiple_unsafe_ops_per_block.rs b/src/tools/clippy/clippy_lints/src/multiple_unsafe_ops_per_block.rs
new file mode 100644
index 000000000..63c575fca
--- /dev/null
+++ b/src/tools/clippy/clippy_lints/src/multiple_unsafe_ops_per_block.rs
@@ -0,0 +1,186 @@
+use clippy_utils::{
+ diagnostics::span_lint_and_then,
+ visitors::{for_each_expr_with_closures, Descend, Visitable},
+};
+use core::ops::ControlFlow::Continue;
+use hir::{
+ def::{DefKind, Res},
+ BlockCheckMode, ExprKind, QPath, UnOp, Unsafety,
+};
+use rustc_ast::Mutability;
+use rustc_hir as hir;
+use rustc_lint::{LateContext, LateLintPass};
+use rustc_middle::lint::in_external_macro;
+use rustc_session::{declare_lint_pass, declare_tool_lint};
+use rustc_span::Span;
+
+declare_clippy_lint! {
+ /// ### What it does
+ /// Checks for `unsafe` blocks that contain more than one unsafe operation.
+ ///
+ /// ### Why is this bad?
+ /// Combined with `undocumented_unsafe_blocks`,
+ /// this lint ensures that each unsafe operation must be independently justified.
+ /// Combined with `unused_unsafe`, this lint also ensures
+ /// elimination of unnecessary unsafe blocks through refactoring.
+ ///
+ /// ### Example
+ /// ```rust
+ /// /// Reads a `char` from the given pointer.
+ /// ///
+ /// /// # Safety
+ /// ///
+ /// /// `ptr` must point to four consecutive, initialized bytes which
+ /// /// form a valid `char` when interpreted in the native byte order.
+ /// fn read_char(ptr: *const u8) -> char {
+ /// // SAFETY: The caller has guaranteed that the value pointed
+ /// // to by `bytes` is a valid `char`.
+ /// unsafe { char::from_u32_unchecked(*ptr.cast::<u32>()) }
+ /// }
+ /// ```
+ /// Use instead:
+ /// ```rust
+ /// /// Reads a `char` from the given pointer.
+ /// ///
+ /// /// # Safety
+ /// ///
+ /// /// - `ptr` must be 4-byte aligned, point to four consecutive
+ /// /// initialized bytes, and be valid for reads of 4 bytes.
+ /// /// - The bytes pointed to by `ptr` must represent a valid
+ /// /// `char` when interpreted in the native byte order.
+ /// fn read_char(ptr: *const u8) -> char {
+ /// // SAFETY: `ptr` is 4-byte aligned, points to four consecutive
+ /// // initialized bytes, and is valid for reads of 4 bytes.
+ /// let int_value = unsafe { *ptr.cast::<u32>() };
+ ///
+ /// // SAFETY: The caller has guaranteed that the four bytes
+ /// // pointed to by `bytes` represent a valid `char`.
+ /// unsafe { char::from_u32_unchecked(int_value) }
+ /// }
+ /// ```
+ #[clippy::version = "1.68.0"]
+ pub MULTIPLE_UNSAFE_OPS_PER_BLOCK,
+ restriction,
+ "more than one unsafe operation per `unsafe` block"
+}
+declare_lint_pass!(MultipleUnsafeOpsPerBlock => [MULTIPLE_UNSAFE_OPS_PER_BLOCK]);
+
+impl<'tcx> LateLintPass<'tcx> for MultipleUnsafeOpsPerBlock {
+ fn check_block(&mut self, cx: &LateContext<'tcx>, block: &'tcx hir::Block<'_>) {
+ if !matches!(block.rules, BlockCheckMode::UnsafeBlock(_)) || in_external_macro(cx.tcx.sess, block.span) {
+ return;
+ }
+ let mut unsafe_ops = vec![];
+ collect_unsafe_exprs(cx, block, &mut unsafe_ops);
+ if unsafe_ops.len() > 1 {
+ span_lint_and_then(
+ cx,
+ MULTIPLE_UNSAFE_OPS_PER_BLOCK,
+ block.span,
+ &format!(
+ "this `unsafe` block contains {} unsafe operations, expected only one",
+ unsafe_ops.len()
+ ),
+ |diag| {
+ for (msg, span) in unsafe_ops {
+ diag.span_note(span, msg);
+ }
+ },
+ );
+ }
+ }
+}
+
+fn collect_unsafe_exprs<'tcx>(
+ cx: &LateContext<'tcx>,
+ node: impl Visitable<'tcx>,
+ unsafe_ops: &mut Vec<(&'static str, Span)>,
+) {
+ for_each_expr_with_closures(cx, node, |expr| {
+ match expr.kind {
+ ExprKind::InlineAsm(_) => unsafe_ops.push(("inline assembly used here", expr.span)),
+
+ ExprKind::Field(e, _) => {
+ if cx.typeck_results().expr_ty(e).is_union() {
+ unsafe_ops.push(("union field access occurs here", expr.span));
+ }
+ },
+
+ ExprKind::Path(QPath::Resolved(
+ _,
+ hir::Path {
+ res: Res::Def(DefKind::Static(Mutability::Mut), _),
+ ..
+ },
+ )) => {
+ unsafe_ops.push(("access of a mutable static occurs here", expr.span));
+ },
+
+ ExprKind::Unary(UnOp::Deref, e) if cx.typeck_results().expr_ty_adjusted(e).is_unsafe_ptr() => {
+ unsafe_ops.push(("raw pointer dereference occurs here", expr.span));
+ },
+
+ ExprKind::Call(path_expr, _) => match path_expr.kind {
+ ExprKind::Path(QPath::Resolved(
+ _,
+ hir::Path {
+ res: Res::Def(kind, def_id),
+ ..
+ },
+ )) if kind.is_fn_like() => {
+ let sig = cx.tcx.fn_sig(*def_id);
+ if sig.0.unsafety() == Unsafety::Unsafe {
+ unsafe_ops.push(("unsafe function call occurs here", expr.span));
+ }
+ },
+
+ ExprKind::Path(QPath::TypeRelative(..)) => {
+ if let Some(sig) = cx
+ .typeck_results()
+ .type_dependent_def_id(path_expr.hir_id)
+ .map(|def_id| cx.tcx.fn_sig(def_id))
+ {
+ if sig.0.unsafety() == Unsafety::Unsafe {
+ unsafe_ops.push(("unsafe function call occurs here", expr.span));
+ }
+ }
+ },
+
+ _ => {},
+ },
+
+ ExprKind::MethodCall(..) => {
+ if let Some(sig) = cx
+ .typeck_results()
+ .type_dependent_def_id(expr.hir_id)
+ .map(|def_id| cx.tcx.fn_sig(def_id))
+ {
+ if sig.0.unsafety() == Unsafety::Unsafe {
+ unsafe_ops.push(("unsafe method call occurs here", expr.span));
+ }
+ }
+ },
+
+ ExprKind::AssignOp(_, lhs, rhs) | ExprKind::Assign(lhs, rhs, _) => {
+ if matches!(
+ lhs.kind,
+ ExprKind::Path(QPath::Resolved(
+ _,
+ hir::Path {
+ res: Res::Def(DefKind::Static(Mutability::Mut), _),
+ ..
+ }
+ ))
+ ) {
+ unsafe_ops.push(("modification of a mutable static occurs here", expr.span));
+ collect_unsafe_exprs(cx, rhs, unsafe_ops);
+ return Continue(Descend::No);
+ }
+ },
+
+ _ => {},
+ };
+
+ Continue::<(), _>(Descend::Yes)
+ });
+}
diff --git a/src/tools/clippy/clippy_lints/src/mut_key.rs b/src/tools/clippy/clippy_lints/src/mut_key.rs
index a651020ca..8aa814b74 100644
--- a/src/tools/clippy/clippy_lints/src/mut_key.rs
+++ b/src/tools/clippy/clippy_lints/src/mut_key.rs
@@ -3,9 +3,10 @@ use clippy_utils::{def_path_def_ids, trait_ref_of_method};
use rustc_data_structures::fx::FxHashSet;
use rustc_hir as hir;
use rustc_lint::{LateContext, LateLintPass};
-use rustc_middle::ty::TypeVisitable;
+use rustc_middle::ty::TypeVisitableExt;
use rustc_middle::ty::{Adt, Array, Ref, Slice, Tuple, Ty};
use rustc_session::{declare_tool_lint, impl_lint_pass};
+use rustc_span::def_id::LocalDefId;
use rustc_span::source_map::Span;
use rustc_span::symbol::sym;
use std::iter;
@@ -102,21 +103,21 @@ impl<'tcx> LateLintPass<'tcx> for MutableKeyType {
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'tcx>) {
if let hir::ItemKind::Fn(ref sig, ..) = item.kind {
- self.check_sig(cx, item.hir_id(), sig.decl);
+ self.check_sig(cx, item.owner_id.def_id, sig.decl);
}
}
fn check_impl_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::ImplItem<'tcx>) {
if let hir::ImplItemKind::Fn(ref sig, ..) = item.kind {
if trait_ref_of_method(cx, item.owner_id.def_id).is_none() {
- self.check_sig(cx, item.hir_id(), sig.decl);
+ self.check_sig(cx, item.owner_id.def_id, sig.decl);
}
}
}
fn check_trait_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::TraitItem<'tcx>) {
if let hir::TraitItemKind::Fn(ref sig, ..) = item.kind {
- self.check_sig(cx, item.hir_id(), sig.decl);
+ self.check_sig(cx, item.owner_id.def_id, sig.decl);
}
}
@@ -136,9 +137,8 @@ impl MutableKeyType {
}
}
- fn check_sig(&self, cx: &LateContext<'_>, item_hir_id: hir::HirId, decl: &hir::FnDecl<'_>) {
- let fn_def_id = cx.tcx.hir().local_def_id(item_hir_id);
- let fn_sig = cx.tcx.fn_sig(fn_def_id);
+ fn check_sig(&self, cx: &LateContext<'_>, fn_def_id: LocalDefId, decl: &hir::FnDecl<'_>) {
+ let fn_sig = cx.tcx.fn_sig(fn_def_id).subst_identity();
for (hir_ty, ty) in iter::zip(decl.inputs, fn_sig.inputs().skip_binder()) {
self.check_ty_(cx, hir_ty.span, *ty);
}
@@ -166,7 +166,8 @@ impl MutableKeyType {
Ref(_, inner_ty, mutbl) => mutbl == hir::Mutability::Mut || self.is_interior_mutable_type(cx, inner_ty),
Slice(inner_ty) => self.is_interior_mutable_type(cx, inner_ty),
Array(inner_ty, size) => {
- size.try_eval_usize(cx.tcx, cx.param_env).map_or(true, |u| u != 0)
+ size.try_eval_target_usize(cx.tcx, cx.param_env)
+ .map_or(true, |u| u != 0)
&& self.is_interior_mutable_type(cx, inner_ty)
},
Tuple(fields) => fields.iter().any(|ty| self.is_interior_mutable_type(cx, ty)),
diff --git a/src/tools/clippy/clippy_lints/src/mut_reference.rs b/src/tools/clippy/clippy_lints/src/mut_reference.rs
index 4547ed7ea..e91aac41b 100644
--- a/src/tools/clippy/clippy_lints/src/mut_reference.rs
+++ b/src/tools/clippy/clippy_lints/src/mut_reference.rs
@@ -52,7 +52,7 @@ impl<'tcx> LateLintPass<'tcx> for UnnecessaryMutPassed {
ExprKind::MethodCall(path, receiver, arguments, _) => {
let def_id = cx.typeck_results().type_dependent_def_id(e.hir_id).unwrap();
let substs = cx.typeck_results().node_substs(e.hir_id);
- let method_type = cx.tcx.bound_type_of(def_id).subst(cx.tcx, substs);
+ let method_type = cx.tcx.type_of(def_id).subst(cx.tcx, substs);
check_arguments(
cx,
std::iter::once(receiver).chain(arguments.iter()).collect(),
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 8c9d4c5cf..1ab81aee7 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
@@ -18,8 +18,9 @@ use rustc_hir_typeck::expr_use_visitor as euv;
use rustc_infer::infer::TyCtxtInferExt;
use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::mir::FakeReadCause;
-use rustc_middle::ty::{self, TypeVisitable};
+use rustc_middle::ty::{self, TypeVisitableExt};
use rustc_session::{declare_lint_pass, declare_tool_lint};
+use rustc_span::def_id::LocalDefId;
use rustc_span::symbol::kw;
use rustc_span::{sym, Span};
use rustc_target::spec::abi::Abi;
@@ -82,12 +83,14 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessPassByValue {
decl: &'tcx FnDecl<'_>,
body: &'tcx Body<'_>,
span: Span,
- hir_id: HirId,
+ fn_def_id: LocalDefId,
) {
if span.from_expansion() {
return;
}
+ let hir_id = cx.tcx.hir().local_def_id_to_hir_id(fn_def_id);
+
match kind {
FnKind::ItemFn(.., header) => {
let attrs = cx.tcx.hir().attrs(hir_id);
@@ -119,8 +122,6 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessPassByValue {
let sized_trait = need!(cx.tcx.lang_items().sized_trait());
- let fn_def_id = cx.tcx.hir().local_def_id(hir_id);
-
let preds = traits::elaborate_predicates(cx.tcx, cx.param_env.caller_bounds().iter())
.filter(|p| !p.is_global())
.filter_map(|obligation| {
@@ -147,8 +148,8 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessPassByValue {
ctx
};
- let fn_sig = cx.tcx.fn_sig(fn_def_id);
- let fn_sig = cx.tcx.erase_late_bound_regions(fn_sig);
+ let fn_sig = cx.tcx.fn_sig(fn_def_id).subst_identity();
+ let fn_sig = cx.tcx.liberate_late_bound_regions(fn_def_id.to_def_id(), fn_sig);
for (idx, ((input, &ty), arg)) in decl.inputs.iter().zip(fn_sig.inputs()).zip(body.params).enumerate() {
// All spans generated from a proc-macro invocation are the same...
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 54a3c82b7..653b1a8a0 100644
--- a/src/tools/clippy/clippy_lints/src/new_without_default.rs
+++ b/src/tools/clippy/clippy_lints/src/new_without_default.rs
@@ -75,7 +75,7 @@ impl<'tcx> LateLintPass<'tcx> for NewWithoutDefault {
}
if let hir::ImplItemKind::Fn(ref sig, _) = impl_item.kind {
let name = impl_item.ident.name;
- let id = impl_item.hir_id();
+ let id = impl_item.owner_id;
if sig.header.constness == hir::Constness::Const {
// can't be implemented by default
return;
@@ -97,15 +97,16 @@ impl<'tcx> LateLintPass<'tcx> for NewWithoutDefault {
if sig.decl.inputs.is_empty();
if name == sym::new;
if cx.effective_visibilities.is_reachable(impl_item.owner_id.def_id);
- let self_def_id = cx.tcx.hir().get_parent_item(id);
- let self_ty = cx.tcx.type_of(self_def_id);
+ let self_def_id = cx.tcx.hir().get_parent_item(id.into());
+ let self_ty = cx.tcx.type_of(self_def_id).subst_identity();
if self_ty == return_ty(cx, id);
if let Some(default_trait_id) = cx.tcx.get_diagnostic_item(sym::Default);
then {
if self.impling_types.is_none() {
let mut impls = HirIdSet::default();
cx.tcx.for_each_impl(default_trait_id, |d| {
- if let Some(ty_def) = cx.tcx.type_of(d).ty_adt_def() {
+ let ty = cx.tcx.type_of(d).subst_identity();
+ if let Some(ty_def) = ty.ty_adt_def() {
if let Some(local_def_id) = ty_def.did().as_local() {
impls.insert(cx.tcx.hir().local_def_id_to_hir_id(local_def_id));
}
@@ -118,7 +119,8 @@ impl<'tcx> LateLintPass<'tcx> for NewWithoutDefault {
// generics
if_chain! {
if let Some(ref impling_types) = self.impling_types;
- if let Some(self_def) = cx.tcx.type_of(self_def_id).ty_adt_def();
+ let self_def = cx.tcx.type_of(self_def_id).subst_identity();
+ if let Some(self_def) = self_def.ty_adt_def();
if let Some(self_local_did) = self_def.did().as_local();
let self_id = cx.tcx.hir().local_def_id_to_hir_id(self_local_did);
if impling_types.contains(&self_id);
@@ -133,7 +135,7 @@ impl<'tcx> LateLintPass<'tcx> for NewWithoutDefault {
span_lint_hir_and_then(
cx,
NEW_WITHOUT_DEFAULT,
- id,
+ id.into(),
impl_item.span,
&format!(
"you should consider adding a `Default` implementation for `{self_type_snip}`"
diff --git a/src/tools/clippy/clippy_lints/src/no_mangle_with_rust_abi.rs b/src/tools/clippy/clippy_lints/src/no_mangle_with_rust_abi.rs
new file mode 100644
index 000000000..bc64ccb29
--- /dev/null
+++ b/src/tools/clippy/clippy_lints/src/no_mangle_with_rust_abi.rs
@@ -0,0 +1,65 @@
+use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::source::snippet_with_applicability;
+use rustc_errors::Applicability;
+use rustc_hir::{Item, ItemKind};
+use rustc_lint::{LateContext, LateLintPass};
+use rustc_session::{declare_lint_pass, declare_tool_lint};
+use rustc_target::spec::abi::Abi;
+
+declare_clippy_lint! {
+ /// ### What it does
+ /// Checks for Rust ABI functions with the `#[no_mangle]` attribute.
+ ///
+ /// ### Why is this bad?
+ /// The Rust ABI is not stable, but in many simple cases matches
+ /// enough with the C ABI that it is possible to forget to add
+ /// `extern "C"` to a function called from C. Changes to the
+ /// Rust ABI can break this at any point.
+ ///
+ /// ### Example
+ /// ```rust
+ /// #[no_mangle]
+ /// fn example(arg_one: u32, arg_two: usize) {}
+ /// ```
+ ///
+ /// Use instead:
+ /// ```rust
+ /// #[no_mangle]
+ /// extern "C" fn example(arg_one: u32, arg_two: usize) {}
+ /// ```
+ #[clippy::version = "1.69.0"]
+ pub NO_MANGLE_WITH_RUST_ABI,
+ pedantic,
+ "convert Rust ABI functions to C ABI"
+}
+declare_lint_pass!(NoMangleWithRustAbi => [NO_MANGLE_WITH_RUST_ABI]);
+
+impl<'tcx> LateLintPass<'tcx> for NoMangleWithRustAbi {
+ fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'tcx>) {
+ if let ItemKind::Fn(fn_sig, _, _) = &item.kind {
+ let attrs = cx.tcx.hir().attrs(item.hir_id());
+ let mut applicability = Applicability::MachineApplicable;
+ let snippet = snippet_with_applicability(cx, fn_sig.span, "..", &mut applicability);
+ for attr in attrs {
+ if let Some(ident) = attr.ident()
+ && ident.name == rustc_span::sym::no_mangle
+ && fn_sig.header.abi == Abi::Rust
+ && !snippet.contains("extern") {
+
+ let suggestion = snippet.split_once("fn")
+ .map_or(String::new(), |(first, second)| format!(r#"{first}extern "C" fn{second}"#));
+
+ span_lint_and_sugg(
+ cx,
+ NO_MANGLE_WITH_RUST_ABI,
+ fn_sig.span,
+ "attribute #[no_mangle] set on a Rust ABI function",
+ "try",
+ suggestion,
+ applicability
+ );
+ }
+ }
+ }
+ }
+}
diff --git a/src/tools/clippy/clippy_lints/src/non_copy_const.rs b/src/tools/clippy/clippy_lints/src/non_copy_const.rs
index 07fd321d6..0bedab05e 100644
--- a/src/tools/clippy/clippy_lints/src/non_copy_const.rs
+++ b/src/tools/clippy/clippy_lints/src/non_copy_const.rs
@@ -313,7 +313,7 @@ impl<'tcx> LateLintPass<'tcx> for NonCopyConst {
// and, in that case, the definition is *not* generic.
cx.tcx.normalize_erasing_regions(
cx.tcx.param_env(of_trait_def_id),
- cx.tcx.type_of(of_assoc_item),
+ cx.tcx.type_of(of_assoc_item).subst_identity(),
),
))
.is_err();
diff --git a/src/tools/clippy/clippy_lints/src/only_used_in_recursion.rs b/src/tools/clippy/clippy_lints/src/only_used_in_recursion.rs
index 7b1d974f2..8b77a5c99 100644
--- a/src/tools/clippy/clippy_lints/src/only_used_in_recursion.rs
+++ b/src/tools/clippy/clippy_lints/src/only_used_in_recursion.rs
@@ -7,7 +7,7 @@ use rustc_hir::def_id::DefId;
use rustc_hir::hir_id::HirIdMap;
use rustc_hir::{Body, Expr, ExprKind, HirId, ImplItem, ImplItemKind, Node, PatKind, TraitItem, TraitItemKind};
use rustc_lint::{LateContext, LateLintPass};
-use rustc_middle::ty::subst::{GenericArgKind, SubstsRef};
+use rustc_middle::ty::subst::{EarlyBinder, GenericArgKind, SubstsRef};
use rustc_middle::ty::{self, ConstKind};
use rustc_session::{declare_tool_lint, impl_lint_pass};
use rustc_span::symbol::{kw, Ident};
@@ -244,7 +244,7 @@ impl<'tcx> LateLintPass<'tcx> for OnlyUsedInRecursion {
})) => {
#[allow(trivial_casts)]
if let Some(Node::Item(item)) = get_parent_node(cx.tcx, owner_id.into())
- && let Some(trait_ref) = cx.tcx.impl_trait_ref(item.owner_id).map(|t| t.subst_identity())
+ && let Some(trait_ref) = cx.tcx.impl_trait_ref(item.owner_id).map(EarlyBinder::subst_identity)
&& let Some(trait_item_id) = cx.tcx.associated_item(owner_id).trait_item_def_id
{
(
diff --git a/src/tools/clippy/clippy_lints/src/operators/arithmetic_side_effects.rs b/src/tools/clippy/clippy_lints/src/operators/arithmetic_side_effects.rs
index cff82b875..87a8a2ed1 100644
--- a/src/tools/clippy/clippy_lints/src/operators/arithmetic_side_effects.rs
+++ b/src/tools/clippy/clippy_lints/src/operators/arithmetic_side_effects.rs
@@ -1,8 +1,8 @@
use super::ARITHMETIC_SIDE_EFFECTS;
use clippy_utils::{
- consts::{constant, constant_simple},
+ consts::{constant, constant_simple, Constant},
diagnostics::span_lint,
- peel_hir_expr_refs, peel_hir_expr_unary,
+ is_lint_allowed, peel_hir_expr_refs, peel_hir_expr_unary,
};
use rustc_ast as ast;
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
@@ -97,17 +97,19 @@ impl ArithmeticSideEffects {
self.expr_span = Some(expr.span);
}
- /// If `expr` is not a literal integer like `1`, returns `None`.
+ /// Returns the numeric value of a literal integer originated from `expr`, if any.
///
- /// Returns the absolute value of the expression, if this is an integer literal.
- fn literal_integer(expr: &hir::Expr<'_>) -> Option<u128> {
+ /// Literal integers can be originated from adhoc declarations like `1`, associated constants
+ /// like `i32::MAX` or constant references like `N` from `const N: i32 = 1;`,
+ fn literal_integer(cx: &LateContext<'_>, expr: &hir::Expr<'_>) -> Option<u128> {
let actual = peel_hir_expr_unary(expr).0;
if let hir::ExprKind::Lit(ref lit) = actual.kind && let ast::LitKind::Int(n, _) = lit.node {
- Some(n)
+ return Some(n)
}
- else {
- None
+ if let Some((Constant::Int(n), _)) = constant(cx, cx.typeck_results(), expr) {
+ return Some(n);
}
+ None
}
/// Manages when the lint should be triggered. Operations in constant environments, hard coded
@@ -143,7 +145,10 @@ impl ArithmeticSideEffects {
let has_valid_op = if Self::is_integral(lhs_ty) && Self::is_integral(rhs_ty) {
let (actual_lhs, lhs_ref_counter) = peel_hir_expr_refs(lhs);
let (actual_rhs, rhs_ref_counter) = peel_hir_expr_refs(rhs);
- match (Self::literal_integer(actual_lhs), Self::literal_integer(actual_rhs)) {
+ match (
+ Self::literal_integer(cx, actual_lhs),
+ Self::literal_integer(cx, actual_rhs),
+ ) {
(None, None) => false,
(None, Some(n)) | (Some(n), None) => match (&op.node, n) {
(hir::BinOpKind::Div | hir::BinOpKind::Rem, 0) => false,
@@ -180,20 +185,22 @@ impl ArithmeticSideEffects {
return;
}
let actual_un_expr = peel_hir_expr_refs(un_expr).0;
- if Self::literal_integer(actual_un_expr).is_some() {
+ if Self::literal_integer(cx, actual_un_expr).is_some() {
return;
}
self.issue_lint(cx, expr);
}
- fn should_skip_expr(&mut self, expr: &hir::Expr<'_>) -> bool {
- self.expr_span.is_some() || self.const_span.map_or(false, |sp| sp.contains(expr.span))
+ fn should_skip_expr(&mut self, cx: &LateContext<'_>, expr: &hir::Expr<'_>) -> bool {
+ is_lint_allowed(cx, ARITHMETIC_SIDE_EFFECTS, expr.hir_id)
+ || self.expr_span.is_some()
+ || self.const_span.map_or(false, |sp| sp.contains(expr.span))
}
}
impl<'tcx> LateLintPass<'tcx> for ArithmeticSideEffects {
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &hir::Expr<'tcx>) {
- if self.should_skip_expr(expr) {
+ if self.should_skip_expr(cx, expr) {
return;
}
match &expr.kind {
@@ -209,7 +216,8 @@ impl<'tcx> LateLintPass<'tcx> for ArithmeticSideEffects {
fn check_body(&mut self, cx: &LateContext<'_>, body: &hir::Body<'_>) {
let body_owner = cx.tcx.hir().body_owner(body.id());
- let body_owner_def_id = cx.tcx.hir().local_def_id(body_owner);
+ let body_owner_def_id = cx.tcx.hir().body_owner_def_id(body.id());
+
let body_owner_kind = cx.tcx.hir().body_owner_kind(body_owner_def_id);
if let hir::BodyOwnerKind::Const | hir::BodyOwnerKind::Static(_) = body_owner_kind {
let body_span = cx.tcx.hir().span_with_body(body_owner);
diff --git a/src/tools/clippy/clippy_lints/src/operators/cmp_owned.rs b/src/tools/clippy/clippy_lints/src/operators/cmp_owned.rs
index 24aeb82a3..d3de9699f 100644
--- a/src/tools/clippy/clippy_lints/src/operators/cmp_owned.rs
+++ b/src/tools/clippy/clippy_lints/src/operators/cmp_owned.rs
@@ -49,10 +49,10 @@ fn check_op(cx: &LateContext<'_>, expr: &Expr<'_>, other: &Expr<'_>, left: bool)
(arg, arg.span)
},
ExprKind::Call(path, [arg])
- if path_def_id(cx, path).map_or(false, |id| {
- if match_def_path(cx, id, &paths::FROM_STR_METHOD) {
+ if path_def_id(cx, path).map_or(false, |did| {
+ if match_def_path(cx, did, &paths::FROM_STR_METHOD) {
true
- } else if cx.tcx.lang_items().from_fn() == Some(id) {
+ } else if cx.tcx.is_diagnostic_item(sym::from_fn, did) {
!is_copy(cx, typeck.expr_ty(expr))
} else {
false
diff --git a/src/tools/clippy/clippy_lints/src/operators/numeric_arithmetic.rs b/src/tools/clippy/clippy_lints/src/operators/numeric_arithmetic.rs
index 0830a106f..777395f45 100644
--- a/src/tools/clippy/clippy_lints/src/operators/numeric_arithmetic.rs
+++ b/src/tools/clippy/clippy_lints/src/operators/numeric_arithmetic.rs
@@ -96,7 +96,7 @@ impl Context {
pub fn enter_body(&mut self, cx: &LateContext<'_>, body: &hir::Body<'_>) {
let body_owner = cx.tcx.hir().body_owner(body.id());
- let body_owner_def_id = cx.tcx.hir().local_def_id(body_owner);
+ let body_owner_def_id = cx.tcx.hir().body_owner_def_id(body.id());
match cx.tcx.hir().body_owner_kind(body_owner_def_id) {
hir::BodyOwnerKind::Static(_) | hir::BodyOwnerKind::Const => {
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 472f52380..c5ea09590 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
@@ -25,11 +25,11 @@ declare_clippy_lint! {
/// Using the dedicated functions of the `Option` type is clearer and
/// more concise than an `if let` expression.
///
- /// ### Known problems
- /// This lint uses a deliberately conservative metric for checking
- /// if the inside of either body contains breaks or continues which will
- /// cause it to not suggest a fix if either block contains a loop with
- /// continues or breaks contained within the loop.
+ /// ### Notes
+ /// This lint uses a deliberately conservative metric for checking if the
+ /// inside of either body contains loop control expressions `break` or
+ /// `continue` (which cannot be used within closures). If these are found,
+ /// this lint will not be raised.
///
/// ### Example
/// ```rust
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 efec12489..849cd03dd 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
@@ -8,6 +8,7 @@ use rustc_hir as hir;
use rustc_hir::intravisit::FnKind;
use rustc_lint::{LateContext, LateLintPass};
use rustc_session::{declare_lint_pass, declare_tool_lint};
+use rustc_span::def_id::LocalDefId;
use rustc_span::{sym, Span};
declare_clippy_lint! {
@@ -49,9 +50,13 @@ impl<'tcx> LateLintPass<'tcx> for PanicInResultFn {
_: &'tcx hir::FnDecl<'tcx>,
body: &'tcx hir::Body<'tcx>,
span: Span,
- hir_id: hir::HirId,
+ def_id: LocalDefId,
) {
- if !matches!(fn_kind, FnKind::Closure) && is_type_diagnostic_item(cx, return_ty(cx, hir_id), sym::Result) {
+ if matches!(fn_kind, FnKind::Closure) {
+ return;
+ }
+ let owner = cx.tcx.hir().local_def_id_to_hir_id(def_id).expect_owner();
+ if is_type_diagnostic_item(cx, return_ty(cx, owner), 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 2d21aaa4f..0d78c3048 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
@@ -12,7 +12,7 @@ use rustc_data_structures::fx::FxHashSet;
use rustc_errors::Applicability;
use rustc_hir as hir;
use rustc_hir::intravisit::FnKind;
-use rustc_hir::{BindingAnnotation, Body, FnDecl, HirId, Impl, ItemKind, MutTy, Mutability, Node, PatKind};
+use rustc_hir::{BindingAnnotation, Body, FnDecl, Impl, ItemKind, MutTy, Mutability, Node, PatKind};
use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::ty::adjustment::{Adjust, PointerCast};
use rustc_middle::ty::layout::LayoutOf;
@@ -143,7 +143,7 @@ impl<'tcx> PassByRefOrValue {
return;
}
- let fn_sig = cx.tcx.fn_sig(def_id);
+ let fn_sig = cx.tcx.fn_sig(def_id).subst_identity();
let fn_body = cx.enclosing_body.map(|id| cx.tcx.hir().body(id));
// Gather all the lifetimes found in the output type which may affect whether
@@ -272,12 +272,13 @@ impl<'tcx> LateLintPass<'tcx> for PassByRefOrValue {
decl: &'tcx FnDecl<'_>,
_body: &'tcx Body<'_>,
span: Span,
- hir_id: HirId,
+ def_id: LocalDefId,
) {
if span.from_expansion() {
return;
}
+ let hir_id = cx.tcx.hir().local_def_id_to_hir_id(def_id);
match kind {
FnKind::ItemFn(.., header) => {
if header.abi != Abi::Rust {
@@ -308,6 +309,6 @@ impl<'tcx> LateLintPass<'tcx> for PassByRefOrValue {
}
}
- self.check_poly_fn(cx, cx.tcx.hir().local_def_id(hir_id), decl, Some(span));
+ self.check_poly_fn(cx, def_id, decl, Some(span));
}
}
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 97b5a4ce3..9f98195d3 100644
--- a/src/tools/clippy/clippy_lints/src/pattern_type_mismatch.rs
+++ b/src/tools/clippy/clippy_lints/src/pattern_type_mismatch.rs
@@ -1,11 +1,10 @@
use clippy_utils::diagnostics::span_lint_and_help;
-use rustc_hir::{
- intravisit, Body, Expr, ExprKind, FnDecl, HirId, Let, LocalSource, Mutability, Pat, PatKind, Stmt, StmtKind,
-};
+use rustc_hir::{intravisit, Body, Expr, ExprKind, FnDecl, Let, LocalSource, Mutability, Pat, PatKind, Stmt, StmtKind};
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::def_id::LocalDefId;
use rustc_span::source_map::Span;
declare_clippy_lint! {
@@ -116,7 +115,7 @@ impl<'tcx> LateLintPass<'tcx> for PatternTypeMismatch {
_: &'tcx FnDecl<'_>,
body: &'tcx Body<'_>,
_: Span,
- _: HirId,
+ _: LocalDefId,
) {
for param in body.params {
apply_lint(cx, param.pat, DerefPossible::Impossible);
diff --git a/src/tools/clippy/clippy_lints/src/ptr.rs b/src/tools/clippy/clippy_lints/src/ptr.rs
index 262953042..fc5509361 100644
--- a/src/tools/clippy/clippy_lints/src/ptr.rs
+++ b/src/tools/clippy/clippy_lints/src/ptr.rs
@@ -164,7 +164,7 @@ impl<'tcx> LateLintPass<'tcx> for Ptr {
check_mut_from_ref(cx, sig, None);
for arg in check_fn_args(
cx,
- cx.tcx.fn_sig(item.owner_id).skip_binder().inputs(),
+ cx.tcx.fn_sig(item.owner_id).subst_identity().skip_binder().inputs(),
sig.decl.inputs,
&[],
)
@@ -217,7 +217,7 @@ impl<'tcx> LateLintPass<'tcx> for Ptr {
check_mut_from_ref(cx, sig, Some(body));
let decl = sig.decl;
- let sig = cx.tcx.fn_sig(item_id).skip_binder();
+ let sig = cx.tcx.fn_sig(item_id).subst_identity().skip_binder();
let lint_args: Vec<_> = check_fn_args(cx, sig.inputs(), decl.inputs, body.params)
.filter(|arg| !is_trait_item || arg.mutability() == Mutability::Not)
.collect();
@@ -505,13 +505,13 @@ fn check_mut_from_ref<'tcx>(cx: &LateContext<'tcx>, sig: &FnSig<'_>, body: Optio
if let FnRetTy::Return(ty) = sig.decl.output
&& let Some((out, Mutability::Mut, _)) = get_ref_lm(ty)
{
- let out_region = cx.tcx.named_region(out.hir_id);
+ let out_region = cx.tcx.named_bound_var(out.hir_id);
let args: Option<Vec<_>> = sig
.decl
.inputs
.iter()
.filter_map(get_ref_lm)
- .filter(|&(lt, _, _)| cx.tcx.named_region(lt.hir_id) == out_region)
+ .filter(|&(lt, _, _)| cx.tcx.named_bound_var(lt.hir_id) == out_region)
.map(|(_, mutability, span)| (mutability == Mutability::Not).then_some(span))
.collect();
if let Some(args) = args
@@ -624,7 +624,10 @@ fn check_ptr_arg_usage<'tcx>(cx: &LateContext<'tcx>, body: &'tcx Body<'_>, args:
return;
};
- match *self.cx.tcx.fn_sig(id).skip_binder().inputs()[i].peel_refs().kind() {
+ match *self.cx.tcx.fn_sig(id).subst_identity().skip_binder().inputs()[i]
+ .peel_refs()
+ .kind()
+ {
ty::Dynamic(preds, _, _) if !matches_preds(self.cx, args.deref_ty.ty(self.cx), preds) => {
set_skip_flag();
},
diff --git a/src/tools/clippy/clippy_lints/src/question_mark_used.rs b/src/tools/clippy/clippy_lints/src/question_mark_used.rs
new file mode 100644
index 000000000..9b678e8d7
--- /dev/null
+++ b/src/tools/clippy/clippy_lints/src/question_mark_used.rs
@@ -0,0 +1,52 @@
+use clippy_utils::diagnostics::span_lint_and_help;
+
+use clippy_utils::macros::span_is_local;
+use rustc_hir::{Expr, ExprKind, MatchSource};
+use rustc_lint::{LateContext, LateLintPass};
+use rustc_session::{declare_lint_pass, declare_tool_lint};
+
+declare_clippy_lint! {
+ /// ### What it does
+ /// Checks for expressions that use the question mark operator and rejects them.
+ ///
+ /// ### Why is this bad?
+ /// Sometimes code wants to avoid the question mark operator because for instance a local
+ /// block requires a macro to re-throw errors to attach additional information to the
+ /// error.
+ ///
+ /// ### Example
+ /// ```ignore
+ /// let result = expr?;
+ /// ```
+ ///
+ /// Could be written:
+ ///
+ /// ```ignore
+ /// utility_macro!(expr);
+ /// ```
+ #[clippy::version = "pre 1.29.0"]
+ pub QUESTION_MARK_USED,
+ restriction,
+ "complains if the question mark operator is used"
+}
+
+declare_lint_pass!(QuestionMarkUsed => [QUESTION_MARK_USED]);
+
+impl<'tcx> LateLintPass<'tcx> for QuestionMarkUsed {
+ fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
+ if let ExprKind::Match(_, _, MatchSource::TryDesugar) = expr.kind {
+ if !span_is_local(expr.span) {
+ return;
+ }
+
+ span_lint_and_help(
+ cx,
+ QUESTION_MARK_USED,
+ expr.span,
+ "question mark operator was used",
+ None,
+ "consider using a custom macro or match expression",
+ );
+ }
+ }
+}
diff --git a/src/tools/clippy/clippy_lints/src/redundant_clone.rs b/src/tools/clippy/clippy_lints/src/redundant_clone.rs
index c1677fb3d..944a33cc3 100644
--- a/src/tools/clippy/clippy_lints/src/redundant_clone.rs
+++ b/src/tools/clippy/clippy_lints/src/redundant_clone.rs
@@ -6,11 +6,12 @@ use clippy_utils::{fn_has_unsatisfiable_preds, match_def_path, paths};
use if_chain::if_chain;
use rustc_errors::Applicability;
use rustc_hir::intravisit::FnKind;
-use rustc_hir::{def_id, Body, FnDecl, HirId, LangItem};
+use rustc_hir::{def_id, Body, FnDecl, LangItem};
use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::mir;
use rustc_middle::ty::{self, Ty};
use rustc_session::{declare_lint_pass, declare_tool_lint};
+use rustc_span::def_id::LocalDefId;
use rustc_span::source_map::{BytePos, Span};
use rustc_span::sym;
@@ -69,12 +70,10 @@ impl<'tcx> LateLintPass<'tcx> for RedundantClone {
cx: &LateContext<'tcx>,
_: FnKind<'tcx>,
_: &'tcx FnDecl<'_>,
- body: &'tcx Body<'_>,
+ _: &'tcx Body<'_>,
_: Span,
- _: HirId,
+ def_id: LocalDefId,
) {
- let def_id = cx.tcx.hir().body_owner_def_id(body.id());
-
// Building MIR for `fn`s with unsatisfiable preds results in ICE.
if fn_has_unsatisfiable_preds(cx, def_id.to_def_id()) {
return;
diff --git a/src/tools/clippy/clippy_lints/src/redundant_slicing.rs b/src/tools/clippy/clippy_lints/src/redundant_slicing.rs
index 245a02ea2..2fdd775ad 100644
--- a/src/tools/clippy/clippy_lints/src/redundant_slicing.rs
+++ b/src/tools/clippy/clippy_lints/src/redundant_slicing.rs
@@ -11,8 +11,6 @@ use rustc_middle::ty::adjustment::{Adjust, AutoBorrow, AutoBorrowMutability};
use rustc_middle::ty::subst::GenericArg;
use rustc_session::{declare_lint_pass, declare_tool_lint};
-use std::iter;
-
declare_clippy_lint! {
/// ### What it does
/// Checks for redundant slicing expressions which use the full range, and
@@ -136,7 +134,7 @@ impl<'tcx> LateLintPass<'tcx> for RedundantSlicing {
} else if let Some(target_id) = cx.tcx.lang_items().deref_target() {
if let Ok(deref_ty) = cx.tcx.try_normalize_erasing_regions(
cx.param_env,
- cx.tcx.mk_projection(target_id, cx.tcx.mk_substs(iter::once(GenericArg::from(indexed_ty)))),
+ cx.tcx.mk_projection(target_id, cx.tcx.mk_substs(&[GenericArg::from(indexed_ty)])),
) {
if deref_ty == expr_ty {
let snip = snippet_with_context(cx, indexed.span, ctxt, "..", &mut app).0;
diff --git a/src/tools/clippy/clippy_lints/src/regex.rs b/src/tools/clippy/clippy_lints/src/regex.rs
index 1fda58fa5..9e6c6c73d 100644
--- a/src/tools/clippy/clippy_lints/src/regex.rs
+++ b/src/tools/clippy/clippy_lints/src/regex.rs
@@ -1,5 +1,8 @@
+use std::fmt::Display;
+
use clippy_utils::consts::{constant, Constant};
use clippy_utils::diagnostics::{span_lint, span_lint_and_help};
+use clippy_utils::source::snippet_opt;
use clippy_utils::{match_def_path, paths};
use if_chain::if_chain;
use rustc_ast::ast::{LitKind, StrStyle};
@@ -77,13 +80,45 @@ impl<'tcx> LateLintPass<'tcx> for Regex {
}
}
-#[must_use]
-fn str_span(base: Span, c: regex_syntax::ast::Span, offset: u8) -> Span {
- let offset = u32::from(offset);
- 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(), base.parent())
+fn lint_syntax_error(cx: &LateContext<'_>, error: &regex_syntax::Error, unescaped: &str, base: Span, offset: u8) {
+ let parts: Option<(_, _, &dyn Display)> = match &error {
+ regex_syntax::Error::Parse(e) => Some((e.span(), e.auxiliary_span(), e.kind())),
+ regex_syntax::Error::Translate(e) => Some((e.span(), None, e.kind())),
+ _ => None,
+ };
+
+ let convert_span = |regex_span: &regex_syntax::ast::Span| {
+ let offset = u32::from(offset);
+ let start = base.lo() + BytePos(u32::try_from(regex_span.start.offset).expect("offset too large") + offset);
+ let end = base.lo() + BytePos(u32::try_from(regex_span.end.offset).expect("offset too large") + offset);
+
+ Span::new(start, end, base.ctxt(), base.parent())
+ };
+
+ if let Some((primary, auxiliary, kind)) = parts
+ && let Some(literal_snippet) = snippet_opt(cx, base)
+ && let Some(inner) = literal_snippet.get(offset as usize..)
+ // Only convert to native rustc spans if the parsed regex matches the
+ // source snippet exactly, to ensure the span offsets are correct
+ && inner.get(..unescaped.len()) == Some(unescaped)
+ {
+ let spans = if let Some(auxiliary) = auxiliary {
+ vec![convert_span(primary), convert_span(auxiliary)]
+ } else {
+ vec![convert_span(primary)]
+ };
+
+ span_lint(cx, INVALID_REGEX, spans, &format!("regex syntax error: {kind}"));
+ } else {
+ span_lint_and_help(
+ cx,
+ INVALID_REGEX,
+ base,
+ &error.to_string(),
+ None,
+ "consider using a raw string literal: `r\"..\"`",
+ );
+ }
}
fn const_str<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) -> Option<String> {
@@ -155,25 +190,7 @@ fn check_regex<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, utf8: bool) {
span_lint_and_help(cx, TRIVIAL_REGEX, expr.span, "trivial regex", None, repl);
}
},
- Err(regex_syntax::Error::Parse(e)) => {
- span_lint(
- cx,
- INVALID_REGEX,
- str_span(expr.span, *e.span(), offset),
- &format!("regex syntax error: {}", e.kind()),
- );
- },
- Err(regex_syntax::Error::Translate(e)) => {
- span_lint(
- cx,
- INVALID_REGEX,
- str_span(expr.span, *e.span(), offset),
- &format!("regex syntax error: {}", e.kind()),
- );
- },
- Err(e) => {
- span_lint(cx, INVALID_REGEX, expr.span, &format!("regex syntax error: {e}"));
- },
+ Err(e) => lint_syntax_error(cx, &e, r, expr.span, offset),
}
}
} else if let Some(r) = const_str(cx, expr) {
@@ -183,25 +200,7 @@ fn check_regex<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, utf8: bool) {
span_lint_and_help(cx, TRIVIAL_REGEX, expr.span, "trivial regex", None, repl);
}
},
- Err(regex_syntax::Error::Parse(e)) => {
- span_lint(
- cx,
- INVALID_REGEX,
- expr.span,
- &format!("regex syntax error on position {}: {}", e.span().start.offset, e.kind()),
- );
- },
- Err(regex_syntax::Error::Translate(e)) => {
- span_lint(
- cx,
- INVALID_REGEX,
- expr.span,
- &format!("regex syntax error on position {}: {}", e.span().start.offset, e.kind()),
- );
- },
- Err(e) => {
- span_lint(cx, INVALID_REGEX, expr.span, &format!("regex syntax error: {e}"));
- },
+ Err(e) => span_lint(cx, INVALID_REGEX, expr.span, &e.to_string()),
}
}
}
diff --git a/src/tools/clippy/clippy_lints/src/return_self_not_must_use.rs b/src/tools/clippy/clippy_lints/src/return_self_not_must_use.rs
index b77faf732..bccf421e8 100644
--- a/src/tools/clippy/clippy_lints/src/return_self_not_must_use.rs
+++ b/src/tools/clippy/clippy_lints/src/return_self_not_must_use.rs
@@ -3,7 +3,7 @@ use clippy_utils::ty::is_must_use_ty;
use clippy_utils::{nth_arg, return_ty};
use rustc_hir::def_id::LocalDefId;
use rustc_hir::intravisit::FnKind;
-use rustc_hir::{Body, FnDecl, HirId, TraitItem, TraitItemKind};
+use rustc_hir::{Body, FnDecl, OwnerId, TraitItem, TraitItemKind};
use rustc_lint::{LateContext, LateLintPass, LintContext};
use rustc_middle::lint::in_external_macro;
use rustc_session::{declare_lint_pass, declare_tool_lint};
@@ -68,7 +68,7 @@ declare_clippy_lint! {
declare_lint_pass!(ReturnSelfNotMustUse => [RETURN_SELF_NOT_MUST_USE]);
-fn check_method(cx: &LateContext<'_>, decl: &FnDecl<'_>, fn_def: LocalDefId, span: Span, hir_id: HirId) {
+fn check_method(cx: &LateContext<'_>, decl: &FnDecl<'_>, fn_def: LocalDefId, span: Span, owner_id: OwnerId) {
if_chain! {
// If it comes from an external macro, better ignore it.
if !in_external_macro(cx.sess(), span);
@@ -76,10 +76,10 @@ fn check_method(cx: &LateContext<'_>, decl: &FnDecl<'_>, fn_def: LocalDefId, spa
// We only show this warning for public exported methods.
if cx.effective_visibilities.is_exported(fn_def);
// We don't want to emit this lint if the `#[must_use]` attribute is already there.
- if !cx.tcx.hir().attrs(hir_id).iter().any(|attr| attr.has_name(sym::must_use));
+ if !cx.tcx.hir().attrs(owner_id.into()).iter().any(|attr| attr.has_name(sym::must_use));
if cx.tcx.visibility(fn_def.to_def_id()).is_public();
- let ret_ty = return_ty(cx, hir_id);
- let self_arg = nth_arg(cx, hir_id, 0);
+ let ret_ty = return_ty(cx, owner_id);
+ let self_arg = nth_arg(cx, owner_id, 0);
// If `Self` has the same type as the returned type, then we want to warn.
//
// For this check, we don't want to remove the reference on the returned type because if
@@ -109,26 +109,26 @@ impl<'tcx> LateLintPass<'tcx> for ReturnSelfNotMustUse {
decl: &'tcx FnDecl<'tcx>,
_: &'tcx Body<'tcx>,
span: Span,
- hir_id: HirId,
+ fn_def: LocalDefId,
) {
if_chain! {
// We are only interested in methods, not in functions or associated functions.
if matches!(kind, FnKind::Method(_, _));
- if let Some(fn_def) = cx.tcx.hir().opt_local_def_id(hir_id);
if let Some(impl_def) = cx.tcx.impl_of_method(fn_def.to_def_id());
// We don't want this method to be te implementation of a trait because the
// `#[must_use]` should be put on the trait definition directly.
if cx.tcx.trait_id_of_impl(impl_def).is_none();
then {
- check_method(cx, decl, fn_def, span, hir_id);
+ let hir_id = cx.tcx.hir().local_def_id_to_hir_id(fn_def);
+ check_method(cx, decl, fn_def, span, hir_id.expect_owner());
}
}
}
fn check_trait_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx TraitItem<'tcx>) {
if let TraitItemKind::Fn(ref sig, _) = item.kind {
- check_method(cx, sig.decl, item.owner_id.def_id, item.span, item.hir_id());
+ check_method(cx, sig.decl, item.owner_id.def_id, item.span, item.owner_id);
}
}
}
diff --git a/src/tools/clippy/clippy_lints/src/returns.rs b/src/tools/clippy/clippy_lints/src/returns.rs
index bbbd9e498..f0d7dd23a 100644
--- a/src/tools/clippy/clippy_lints/src/returns.rs
+++ b/src/tools/clippy/clippy_lints/src/returns.rs
@@ -1,18 +1,20 @@
use clippy_utils::diagnostics::{span_lint_and_then, span_lint_hir_and_then};
use clippy_utils::source::{snippet_opt, snippet_with_context};
use clippy_utils::visitors::{for_each_expr, Descend};
-use clippy_utils::{fn_def_id, path_to_local_id};
+use clippy_utils::{fn_def_id, path_to_local_id, span_find_starting_semi};
use core::ops::ControlFlow;
use if_chain::if_chain;
use rustc_errors::Applicability;
use rustc_hir::intravisit::FnKind;
-use rustc_hir::{Block, Body, Expr, ExprKind, FnDecl, HirId, LangItem, MatchSource, PatKind, QPath, StmtKind};
+use rustc_hir::{Block, Body, Expr, ExprKind, FnDecl, LangItem, MatchSource, PatKind, QPath, StmtKind};
use rustc_lint::{LateContext, LateLintPass, LintContext};
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::def_id::LocalDefId;
use rustc_span::source_map::Span;
use rustc_span::{BytePos, Pos};
+use std::borrow::Cow;
declare_clippy_lint! {
/// ### What it does
@@ -68,31 +70,41 @@ declare_clippy_lint! {
"using a return statement like `return expr;` where an expression would suffice"
}
-#[derive(PartialEq, Eq, Copy, Clone)]
-enum RetReplacement {
+#[derive(PartialEq, Eq, Clone)]
+enum RetReplacement<'tcx> {
Empty,
Block,
Unit,
+ IfSequence(Cow<'tcx, str>, Applicability),
+ Expr(Cow<'tcx, str>, Applicability),
}
-impl RetReplacement {
+impl<'tcx> RetReplacement<'tcx> {
fn sugg_help(self) -> &'static str {
match self {
- Self::Empty => "remove `return`",
+ Self::Empty | Self::Expr(..) => "remove `return`",
Self::Block => "replace `return` with an empty block",
Self::Unit => "replace `return` with a unit value",
+ Self::IfSequence(..) => "remove `return` and wrap the sequence with parentheses",
+ }
+ }
+ fn applicability(&self) -> Option<Applicability> {
+ match self {
+ Self::Expr(_, ap) | Self::IfSequence(_, ap) => Some(*ap),
+ _ => None,
}
}
}
-impl ToString for RetReplacement {
+impl<'tcx> ToString for RetReplacement<'tcx> {
fn to_string(&self) -> String {
- match *self {
- Self::Empty => "",
- Self::Block => "{}",
- Self::Unit => "()",
+ match self {
+ Self::Empty => String::new(),
+ Self::Block => "{}".to_string(),
+ Self::Unit => "()".to_string(),
+ Self::IfSequence(inner, _) => format!("({inner})"),
+ Self::Expr(inner, _) => inner.to_string(),
}
- .to_string()
}
}
@@ -151,8 +163,8 @@ impl<'tcx> LateLintPass<'tcx> for Return {
kind: FnKind<'tcx>,
_: &'tcx FnDecl<'tcx>,
body: &'tcx Body<'tcx>,
- _: Span,
- _: HirId,
+ sp: Span,
+ _: LocalDefId,
) {
match kind {
FnKind::Closure => {
@@ -166,14 +178,14 @@ impl<'tcx> LateLintPass<'tcx> for Return {
check_final_expr(cx, body.value, vec![], replacement);
},
FnKind::ItemFn(..) | FnKind::Method(..) => {
- check_block_return(cx, &body.value.kind, vec![]);
+ check_block_return(cx, &body.value.kind, sp, vec![]);
},
}
}
}
// if `expr` is a block, check if there are needless returns in it
-fn check_block_return<'tcx>(cx: &LateContext<'tcx>, expr_kind: &ExprKind<'tcx>, semi_spans: Vec<Span>) {
+fn check_block_return<'tcx>(cx: &LateContext<'tcx>, expr_kind: &ExprKind<'tcx>, sp: Span, mut semi_spans: Vec<Span>) {
if let ExprKind::Block(block, _) = expr_kind {
if let Some(block_expr) = block.expr {
check_final_expr(cx, block_expr, semi_spans, RetReplacement::Empty);
@@ -183,12 +195,14 @@ fn check_block_return<'tcx>(cx: &LateContext<'tcx>, expr_kind: &ExprKind<'tcx>,
check_final_expr(cx, expr, semi_spans, RetReplacement::Empty);
},
StmtKind::Semi(semi_expr) => {
- let mut semi_spans_and_this_one = semi_spans;
- // we only want the span containing the semicolon so we can remove it later. From `entry.rs:382`
- if let Some(semicolon_span) = stmt.span.trim_start(semi_expr.span) {
- semi_spans_and_this_one.push(semicolon_span);
- check_final_expr(cx, semi_expr, semi_spans_and_this_one, RetReplacement::Empty);
+ // Remove ending semicolons and any whitespace ' ' in between.
+ // Without `return`, the suggestion might not compile if the semicolon is retained
+ if let Some(semi_span) = stmt.span.trim_start(semi_expr.span) {
+ let semi_span_to_remove =
+ span_find_starting_semi(cx.sess().source_map(), semi_span.with_hi(sp.hi()));
+ semi_spans.push(semi_span_to_remove);
}
+ check_final_expr(cx, semi_expr, semi_spans, RetReplacement::Empty);
},
_ => (),
}
@@ -201,19 +215,38 @@ fn check_final_expr<'tcx>(
expr: &'tcx Expr<'tcx>,
semi_spans: Vec<Span>, /* containing all the places where we would need to remove semicolons if finding an
* needless return */
- replacement: RetReplacement,
+ replacement: RetReplacement<'tcx>,
) {
let peeled_drop_expr = expr.peel_drop_temps();
match &peeled_drop_expr.kind {
// simple return is always "bad"
ExprKind::Ret(ref inner) => {
- // if desugar of `do yeet`, don't lint
- if let Some(inner_expr) = inner
- && let ExprKind::Call(path_expr, _) = inner_expr.kind
- && let ExprKind::Path(QPath::LangItem(LangItem::TryTraitFromYeet, _, _)) = path_expr.kind
- {
- return;
- }
+ // check if expr return nothing
+ let ret_span = if inner.is_none() && replacement == RetReplacement::Empty {
+ extend_span_to_previous_non_ws(cx, peeled_drop_expr.span)
+ } else {
+ peeled_drop_expr.span
+ };
+
+ let replacement = if let Some(inner_expr) = inner {
+ // if desugar of `do yeet`, don't lint
+ if let ExprKind::Call(path_expr, _) = inner_expr.kind
+ && let ExprKind::Path(QPath::LangItem(LangItem::TryTraitFromYeet, _, _)) = path_expr.kind
+ {
+ return;
+ }
+
+ let mut applicability = Applicability::MachineApplicable;
+ let (snippet, _) = snippet_with_context(cx, inner_expr.span, ret_span.ctxt(), "..", &mut applicability);
+ if expr_contains_conjunctive_ifs(inner_expr) {
+ RetReplacement::IfSequence(snippet, applicability)
+ } else {
+ RetReplacement::Expr(snippet, applicability)
+ }
+ } else {
+ replacement
+ };
+
if !cx.tcx.hir().attrs(expr.hir_id).is_empty() {
return;
}
@@ -221,19 +254,13 @@ fn check_final_expr<'tcx>(
if borrows {
return;
}
- // check if expr return nothing
- let ret_span = if inner.is_none() && replacement == RetReplacement::Empty {
- extend_span_to_previous_non_ws(cx, peeled_drop_expr.span)
- } else {
- peeled_drop_expr.span
- };
- emit_return_lint(cx, ret_span, semi_spans, inner.as_ref().map(|i| i.span), replacement);
+ emit_return_lint(cx, ret_span, semi_spans, replacement);
},
ExprKind::If(_, then, else_clause_opt) => {
- check_block_return(cx, &then.kind, semi_spans.clone());
+ check_block_return(cx, &then.kind, peeled_drop_expr.span, semi_spans.clone());
if let Some(else_clause) = else_clause_opt {
- check_block_return(cx, &else_clause.kind, semi_spans);
+ check_block_return(cx, &else_clause.kind, peeled_drop_expr.span, semi_spans);
}
},
// a match expr, check all arms
@@ -246,33 +273,29 @@ fn check_final_expr<'tcx>(
}
},
// if it's a whole block, check it
- other_expr_kind => check_block_return(cx, other_expr_kind, semi_spans),
+ other_expr_kind => check_block_return(cx, other_expr_kind, peeled_drop_expr.span, semi_spans),
}
}
-fn emit_return_lint(
- cx: &LateContext<'_>,
- ret_span: Span,
- semi_spans: Vec<Span>,
- inner_span: Option<Span>,
- replacement: RetReplacement,
-) {
+fn expr_contains_conjunctive_ifs<'tcx>(expr: &'tcx Expr<'tcx>) -> bool {
+ fn contains_if(expr: &Expr<'_>, on_if: bool) -> bool {
+ match expr.kind {
+ ExprKind::If(..) => on_if,
+ ExprKind::Binary(_, left, right) => contains_if(left, true) || contains_if(right, true),
+ _ => false,
+ }
+ }
+
+ contains_if(expr, false)
+}
+
+fn emit_return_lint(cx: &LateContext<'_>, ret_span: Span, semi_spans: Vec<Span>, replacement: RetReplacement<'_>) {
if ret_span.from_expansion() {
return;
}
- let mut applicability = Applicability::MachineApplicable;
- let return_replacement = inner_span.map_or_else(
- || replacement.to_string(),
- |inner_span| {
- let (snippet, _) = snippet_with_context(cx, inner_span, ret_span.ctxt(), "..", &mut applicability);
- snippet.to_string()
- },
- );
- let sugg_help = if inner_span.is_some() {
- "remove `return`"
- } else {
- replacement.sugg_help()
- };
+ let applicability = replacement.applicability().unwrap_or(Applicability::MachineApplicable);
+ let return_replacement = replacement.to_string();
+ let sugg_help = replacement.sugg_help();
span_lint_and_then(cx, NEEDLESS_RETURN, ret_span, "unneeded `return` statement", |diag| {
diag.span_suggestion_hidden(ret_span, sugg_help, return_replacement, applicability);
// for each parent statement, we need to remove the semicolon
@@ -288,6 +311,7 @@ fn last_statement_borrows<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>)
&& cx
.tcx
.fn_sig(def_id)
+ .subst_identity()
.skip_binder()
.output()
.walk()
diff --git a/src/tools/clippy/clippy_lints/src/same_name_method.rs b/src/tools/clippy/clippy_lints/src/same_name_method.rs
index 17763128c..a37e2772d 100644
--- a/src/tools/clippy/clippy_lints/src/same_name_method.rs
+++ b/src/tools/clippy/clippy_lints/src/same_name_method.rs
@@ -52,7 +52,7 @@ impl<'tcx> LateLintPass<'tcx> for SameNameMethod {
let mut map = FxHashMap::<Res, ExistingName>::default();
for id in cx.tcx.hir().items() {
- if matches!(cx.tcx.def_kind(id.owner_id), DefKind::Impl)
+ if matches!(cx.tcx.def_kind(id.owner_id), DefKind::Impl { .. })
&& let item = cx.tcx.hir().item(id)
&& let ItemKind::Impl(Impl {
items,
diff --git a/src/tools/clippy/clippy_lints/src/self_named_constructors.rs b/src/tools/clippy/clippy_lints/src/self_named_constructors.rs
index 71b387c66..beca203c8 100644
--- a/src/tools/clippy/clippy_lints/src/self_named_constructors.rs
+++ b/src/tools/clippy/clippy_lints/src/self_named_constructors.rs
@@ -53,8 +53,8 @@ impl<'tcx> LateLintPass<'tcx> for SelfNamedConstructors {
let parent = cx.tcx.hir().get_parent_item(impl_item.hir_id()).def_id;
let item = cx.tcx.hir().expect_item(parent);
- let self_ty = cx.tcx.type_of(item.owner_id);
- let ret_ty = return_ty(cx, impl_item.hir_id());
+ let self_ty = cx.tcx.type_of(item.owner_id).subst_identity();
+ let ret_ty = return_ty(cx, impl_item.owner_id);
// Do not check trait impls
if matches!(item.kind, ItemKind::Impl(Impl { of_trait: Some(_), .. })) {
diff --git a/src/tools/clippy/clippy_lints/src/semicolon_block.rs b/src/tools/clippy/clippy_lints/src/semicolon_block.rs
index 8f1d1490e..34a3e5ddf 100644
--- a/src/tools/clippy/clippy_lints/src/semicolon_block.rs
+++ b/src/tools/clippy/clippy_lints/src/semicolon_block.rs
@@ -30,7 +30,7 @@ declare_clippy_lint! {
/// # let x = 0;
/// unsafe { f(x); }
/// ```
- #[clippy::version = "1.66.0"]
+ #[clippy::version = "1.68.0"]
pub SEMICOLON_INSIDE_BLOCK,
restriction,
"add a semicolon inside the block"
@@ -59,7 +59,7 @@ declare_clippy_lint! {
/// # let x = 0;
/// unsafe { f(x) };
/// ```
- #[clippy::version = "1.66.0"]
+ #[clippy::version = "1.68.0"]
pub SEMICOLON_OUTSIDE_BLOCK,
restriction,
"add a semicolon outside the block"
diff --git a/src/tools/clippy/clippy_lints/src/significant_drop_tightening.rs b/src/tools/clippy/clippy_lints/src/significant_drop_tightening.rs
new file mode 100644
index 000000000..c3e99aa00
--- /dev/null
+++ b/src/tools/clippy/clippy_lints/src/significant_drop_tightening.rs
@@ -0,0 +1,423 @@
+use clippy_utils::{
+ diagnostics::span_lint_and_then,
+ get_attr,
+ source::{indent_of, snippet},
+};
+use rustc_data_structures::fx::{FxHashMap, FxHashSet};
+use rustc_errors::{Applicability, Diagnostic};
+use rustc_hir::{
+ self as hir,
+ intravisit::{walk_expr, Visitor},
+};
+use rustc_lint::{LateContext, LateLintPass, LintContext};
+use rustc_middle::ty::{subst::GenericArgKind, Ty, TypeAndMut};
+use rustc_session::{declare_tool_lint, impl_lint_pass};
+use rustc_span::{symbol::Ident, Span, DUMMY_SP};
+
+declare_clippy_lint! {
+ /// ### What it does
+ ///
+ /// Searches for elements marked with `#[clippy::significant_drop]` that could be early
+ /// dropped but are in fact dropped at the end of their scopes. In other words, enforces the
+ /// "tightening" of their possible lifetimes.
+ ///
+ /// ### Why is this bad?
+ ///
+ /// Elements marked with `#[clippy::has_significant_drop]` are generally synchronizing
+ /// primitives that manage shared resources, as such, it is desired to release them as soon as
+ /// possible to avoid unnecessary resource contention.
+ ///
+ /// ### Example
+ ///
+ /// ```rust,ignore
+ /// fn main() {
+ /// let lock = some_sync_resource.lock();
+ /// let owned_rslt = lock.do_stuff_with_resource();
+ /// // Only `owned_rslt` is needed but `lock` is still held.
+ /// do_heavy_computation_that_takes_time(owned_rslt);
+ /// }
+ /// ```
+ ///
+ /// Use instead:
+ ///
+ /// ```rust,ignore
+ /// fn main() {
+ /// let owned_rslt = some_sync_resource.lock().do_stuff_with_resource();
+ /// do_heavy_computation_that_takes_time(owned_rslt);
+ /// }
+ /// ```
+ #[clippy::version = "1.67.0"]
+ pub SIGNIFICANT_DROP_TIGHTENING,
+ nursery,
+ "Searches for elements marked with `#[clippy::has_significant_drop]` that could be early dropped but are in fact dropped at the end of their scopes"
+}
+
+impl_lint_pass!(SignificantDropTightening<'_> => [SIGNIFICANT_DROP_TIGHTENING]);
+
+#[derive(Default)]
+pub struct SignificantDropTightening<'tcx> {
+ /// Auxiliary structure used to avoid having to verify the same type multiple times.
+ seen_types: FxHashSet<Ty<'tcx>>,
+ type_cache: FxHashMap<Ty<'tcx>, bool>,
+}
+
+impl<'tcx> SignificantDropTightening<'tcx> {
+ /// Unifies the statements of a block with its return expression.
+ fn all_block_stmts<'ret, 'rslt, 'stmts>(
+ block_stmts: &'stmts [hir::Stmt<'tcx>],
+ dummy_ret_stmt: Option<&'ret hir::Stmt<'tcx>>,
+ ) -> impl Iterator<Item = &'rslt hir::Stmt<'tcx>>
+ where
+ 'ret: 'rslt,
+ 'stmts: 'rslt,
+ {
+ block_stmts.iter().chain(dummy_ret_stmt)
+ }
+
+ /// Searches for at least one statement that could slow down the release of a significant drop.
+ fn at_least_one_stmt_is_expensive<'stmt>(stmts: impl Iterator<Item = &'stmt hir::Stmt<'tcx>>) -> bool
+ where
+ 'tcx: 'stmt,
+ {
+ for stmt in stmts {
+ match stmt.kind {
+ hir::StmtKind::Expr(expr) if let hir::ExprKind::Path(_) = expr.kind => {}
+ hir::StmtKind::Local(local) if let Some(expr) = local.init
+ && let hir::ExprKind::Path(_) = expr.kind => {},
+ _ => return true
+ };
+ }
+ false
+ }
+
+ /// Verifies if the expression is of type `drop(some_lock_path)` to assert that the temporary
+ /// is already being dropped before the end of its scope.
+ fn has_drop(expr: &'tcx hir::Expr<'_>, init_bind_ident: Ident) -> bool {
+ if let hir::ExprKind::Call(fun, args) = expr.kind
+ && let hir::ExprKind::Path(hir::QPath::Resolved(_, fun_path)) = &fun.kind
+ && let [fun_ident, ..] = fun_path.segments
+ && fun_ident.ident.name == rustc_span::sym::drop
+ && let [first_arg, ..] = args
+ && let hir::ExprKind::Path(hir::QPath::Resolved(_, arg_path)) = &first_arg.kind
+ && let [first_arg_ps, .. ] = arg_path.segments
+ {
+ first_arg_ps.ident == init_bind_ident
+ }
+ else {
+ false
+ }
+ }
+
+ /// Tries to find types marked with `#[has_significant_drop]` of an expression `expr` that is
+ /// originated from `stmt` and then performs common logic on `sdap`.
+ fn modify_sdap_if_sig_drop_exists(
+ &mut self,
+ cx: &LateContext<'tcx>,
+ expr: &'tcx hir::Expr<'_>,
+ idx: usize,
+ sdap: &mut SigDropAuxParams,
+ stmt: &hir::Stmt<'_>,
+ cb: impl Fn(&mut SigDropAuxParams),
+ ) {
+ let mut sig_drop_finder = SigDropFinder::new(cx, &mut self.seen_types, &mut self.type_cache);
+ sig_drop_finder.visit_expr(expr);
+ if sig_drop_finder.has_sig_drop {
+ cb(sdap);
+ if sdap.number_of_stmts > 0 {
+ sdap.last_use_stmt_idx = idx;
+ sdap.last_use_stmt_span = stmt.span;
+ if let hir::ExprKind::MethodCall(_, _, _, span) = expr.kind {
+ sdap.last_use_method_span = span;
+ }
+ }
+ sdap.number_of_stmts = sdap.number_of_stmts.wrapping_add(1);
+ }
+ }
+
+ /// Shows generic overall messages as well as specialized messages depending on the usage.
+ fn set_suggestions(cx: &LateContext<'tcx>, block_span: Span, diag: &mut Diagnostic, sdap: &SigDropAuxParams) {
+ match sdap.number_of_stmts {
+ 0 | 1 => {},
+ 2 => {
+ let indent = " ".repeat(indent_of(cx, sdap.last_use_stmt_span).unwrap_or(0));
+ let init_method = snippet(cx, sdap.init_method_span, "..");
+ let usage_method = snippet(cx, sdap.last_use_method_span, "..");
+ let stmt = if let Some(last_use_bind_span) = sdap.last_use_bind_span {
+ format!(
+ "\n{indent}let {} = {init_method}.{usage_method};",
+ snippet(cx, last_use_bind_span, ".."),
+ )
+ } else {
+ format!("\n{indent}{init_method}.{usage_method};")
+ };
+ diag.span_suggestion_verbose(
+ sdap.init_stmt_span,
+ "merge the temporary construction with its single usage",
+ stmt,
+ Applicability::MaybeIncorrect,
+ );
+ diag.span_suggestion(
+ sdap.last_use_stmt_span,
+ "remove separated single usage",
+ "",
+ Applicability::MaybeIncorrect,
+ );
+ },
+ _ => {
+ diag.span_suggestion(
+ sdap.last_use_stmt_span.shrink_to_hi(),
+ "drop the temporary after the end of its last usage",
+ format!(
+ "\n{}drop({});",
+ " ".repeat(indent_of(cx, sdap.last_use_stmt_span).unwrap_or(0)),
+ sdap.init_bind_ident
+ ),
+ Applicability::MaybeIncorrect,
+ );
+ },
+ }
+ diag.note("this might lead to unnecessary resource contention");
+ diag.span_label(
+ block_span,
+ format!(
+ "temporary `{}` is currently being dropped at the end of its contained scope",
+ sdap.init_bind_ident
+ ),
+ );
+ }
+}
+
+impl<'tcx> LateLintPass<'tcx> for SignificantDropTightening<'tcx> {
+ fn check_block(&mut self, cx: &LateContext<'tcx>, block: &'tcx hir::Block<'_>) {
+ let dummy_ret_stmt = block.expr.map(|expr| hir::Stmt {
+ hir_id: hir::HirId::INVALID,
+ kind: hir::StmtKind::Expr(expr),
+ span: DUMMY_SP,
+ });
+ let mut sdap = SigDropAuxParams::default();
+ for (idx, stmt) in Self::all_block_stmts(block.stmts, dummy_ret_stmt.as_ref()).enumerate() {
+ match stmt.kind {
+ hir::StmtKind::Expr(expr) => self.modify_sdap_if_sig_drop_exists(
+ cx,
+ expr,
+ idx,
+ &mut sdap,
+ stmt,
+ |_| {}
+ ),
+ hir::StmtKind::Local(local) if let Some(expr) = local.init => self.modify_sdap_if_sig_drop_exists(
+ cx,
+ expr,
+ idx,
+ &mut sdap,
+ stmt,
+ |local_sdap| {
+ if local_sdap.number_of_stmts == 0 {
+ if let hir::PatKind::Binding(_, _, ident, _) = local.pat.kind {
+ local_sdap.init_bind_ident = ident;
+ }
+ if let hir::ExprKind::MethodCall(_, local_expr, _, span) = expr.kind {
+ local_sdap.init_method_span = local_expr.span.to(span);
+ }
+ local_sdap.init_stmt_span = stmt.span;
+ }
+ else if let hir::PatKind::Binding(_, _, ident, _) = local.pat.kind {
+ local_sdap.last_use_bind_span = Some(ident.span);
+ }
+ }
+ ),
+ hir::StmtKind::Semi(expr) => {
+ if Self::has_drop(expr, sdap.init_bind_ident) {
+ return;
+ }
+ self.modify_sdap_if_sig_drop_exists(cx, expr, idx, &mut sdap, stmt, |_| {});
+ },
+ _ => {}
+ };
+ }
+
+ let idx = sdap.last_use_stmt_idx.wrapping_add(1);
+ let stmts_after_last_use = Self::all_block_stmts(block.stmts, dummy_ret_stmt.as_ref()).skip(idx);
+ if sdap.number_of_stmts > 1 && Self::at_least_one_stmt_is_expensive(stmts_after_last_use) {
+ span_lint_and_then(
+ cx,
+ SIGNIFICANT_DROP_TIGHTENING,
+ sdap.init_bind_ident.span,
+ "temporary with significant `Drop` can be early dropped",
+ |diag| {
+ Self::set_suggestions(cx, block.span, diag, &sdap);
+ },
+ );
+ }
+ }
+}
+
+/// Auxiliary parameters used on each block check.
+struct SigDropAuxParams {
+ /// The binding or variable that references the initial construction of the type marked with
+ /// `#[has_significant_drop]`.
+ init_bind_ident: Ident,
+ /// Similar to `init_bind_ident` but encompasses the right-hand method call.
+ init_method_span: Span,
+ /// Similar to `init_bind_ident` but encompasses the whole contained statement.
+ init_stmt_span: Span,
+
+ /// The last visited binding or variable span within a block that had any referenced inner type
+ /// marked with `#[has_significant_drop]`.
+ last_use_bind_span: Option<Span>,
+ /// Index of the last visited statement within a block that had any referenced inner type
+ /// marked with `#[has_significant_drop]`.
+ last_use_stmt_idx: usize,
+ /// Similar to `last_use_bind_span` but encompasses the whole contained statement.
+ last_use_stmt_span: Span,
+ /// Similar to `last_use_bind_span` but encompasses the right-hand method call.
+ last_use_method_span: Span,
+
+ /// Total number of statements within a block that have any referenced inner type marked with
+ /// `#[has_significant_drop]`.
+ number_of_stmts: usize,
+}
+
+impl Default for SigDropAuxParams {
+ fn default() -> Self {
+ Self {
+ init_bind_ident: Ident::empty(),
+ init_method_span: DUMMY_SP,
+ init_stmt_span: DUMMY_SP,
+ last_use_bind_span: None,
+ last_use_method_span: DUMMY_SP,
+ last_use_stmt_idx: 0,
+ last_use_stmt_span: DUMMY_SP,
+ number_of_stmts: 0,
+ }
+ }
+}
+
+/// Checks the existence of the `#[has_significant_drop]` attribute
+struct SigDropChecker<'cx, 'sdt, 'tcx> {
+ cx: &'cx LateContext<'tcx>,
+ seen_types: &'sdt mut FxHashSet<Ty<'tcx>>,
+ type_cache: &'sdt mut FxHashMap<Ty<'tcx>, bool>,
+}
+
+impl<'cx, 'sdt, 'tcx> SigDropChecker<'cx, 'sdt, 'tcx> {
+ pub(crate) fn new(
+ cx: &'cx LateContext<'tcx>,
+ seen_types: &'sdt mut FxHashSet<Ty<'tcx>>,
+ type_cache: &'sdt mut FxHashMap<Ty<'tcx>, bool>,
+ ) -> Self {
+ seen_types.clear();
+ Self {
+ cx,
+ seen_types,
+ type_cache,
+ }
+ }
+
+ pub(crate) fn has_sig_drop_attr_uncached(&mut self, ty: Ty<'tcx>) -> bool {
+ if let Some(adt) = ty.ty_adt_def() {
+ let mut iter = get_attr(
+ self.cx.sess(),
+ self.cx.tcx.get_attrs_unchecked(adt.did()),
+ "has_significant_drop",
+ );
+ if iter.next().is_some() {
+ return true;
+ }
+ }
+ match ty.kind() {
+ rustc_middle::ty::Adt(a, b) => {
+ for f in a.all_fields() {
+ let ty = f.ty(self.cx.tcx, b);
+ if !self.has_seen_ty(ty) && self.has_sig_drop_attr(ty) {
+ return true;
+ }
+ }
+ for generic_arg in b.iter() {
+ if let GenericArgKind::Type(ty) = generic_arg.unpack() {
+ if self.has_sig_drop_attr(ty) {
+ return true;
+ }
+ }
+ }
+ false
+ },
+ rustc_middle::ty::Array(ty, _)
+ | rustc_middle::ty::RawPtr(TypeAndMut { ty, .. })
+ | rustc_middle::ty::Ref(_, ty, _)
+ | rustc_middle::ty::Slice(ty) => self.has_sig_drop_attr(*ty),
+ _ => false,
+ }
+ }
+
+ pub(crate) fn has_sig_drop_attr(&mut self, ty: Ty<'tcx>) -> bool {
+ // The borrow checker prevents us from using something fancier like or_insert_with.
+ if let Some(ty) = self.type_cache.get(&ty) {
+ return *ty;
+ }
+ let value = self.has_sig_drop_attr_uncached(ty);
+ self.type_cache.insert(ty, value);
+ value
+ }
+
+ fn has_seen_ty(&mut self, ty: Ty<'tcx>) -> bool {
+ !self.seen_types.insert(ty)
+ }
+}
+
+/// Performs recursive calls to find any inner type marked with `#[has_significant_drop]`.
+struct SigDropFinder<'cx, 'sdt, 'tcx> {
+ cx: &'cx LateContext<'tcx>,
+ has_sig_drop: bool,
+ sig_drop_checker: SigDropChecker<'cx, 'sdt, 'tcx>,
+}
+
+impl<'cx, 'sdt, 'tcx> SigDropFinder<'cx, 'sdt, 'tcx> {
+ fn new(
+ cx: &'cx LateContext<'tcx>,
+ seen_types: &'sdt mut FxHashSet<Ty<'tcx>>,
+ type_cache: &'sdt mut FxHashMap<Ty<'tcx>, bool>,
+ ) -> Self {
+ Self {
+ cx,
+ has_sig_drop: false,
+ sig_drop_checker: SigDropChecker::new(cx, seen_types, type_cache),
+ }
+ }
+}
+
+impl<'cx, 'sdt, 'tcx> Visitor<'tcx> for SigDropFinder<'cx, 'sdt, 'tcx> {
+ fn visit_expr(&mut self, ex: &'tcx hir::Expr<'_>) {
+ if self
+ .sig_drop_checker
+ .has_sig_drop_attr(self.cx.typeck_results().expr_ty(ex))
+ {
+ self.has_sig_drop = true;
+ return;
+ }
+
+ match ex.kind {
+ hir::ExprKind::MethodCall(_, expr, ..) => {
+ self.visit_expr(expr);
+ },
+ hir::ExprKind::Array(..)
+ | hir::ExprKind::Assign(..)
+ | hir::ExprKind::AssignOp(..)
+ | hir::ExprKind::Binary(..)
+ | hir::ExprKind::Box(..)
+ | hir::ExprKind::Call(..)
+ | hir::ExprKind::Field(..)
+ | hir::ExprKind::If(..)
+ | hir::ExprKind::Index(..)
+ | hir::ExprKind::Match(..)
+ | hir::ExprKind::Repeat(..)
+ | hir::ExprKind::Ret(..)
+ | hir::ExprKind::Tup(..)
+ | hir::ExprKind::Unary(..)
+ | hir::ExprKind::Yield(..) => {
+ walk_expr(self, ex);
+ },
+ _ => {},
+ }
+ }
+}
diff --git a/src/tools/clippy/clippy_lints/src/strings.rs b/src/tools/clippy/clippy_lints/src/strings.rs
index bc18cad6d..b2f4b3109 100644
--- a/src/tools/clippy/clippy_lints/src/strings.rs
+++ b/src/tools/clippy/clippy_lints/src/strings.rs
@@ -190,7 +190,7 @@ impl<'tcx> LateLintPass<'tcx> for StringAdd {
},
ExprKind::Index(target, _idx) => {
let e_ty = cx.typeck_results().expr_ty(target).peel_refs();
- if matches!(e_ty.kind(), ty::Str) || is_type_lang_item(cx, e_ty, LangItem::String) {
+ if e_ty.is_str() || is_type_lang_item(cx, e_ty, LangItem::String) {
span_lint(
cx,
STRING_SLICE,
@@ -407,7 +407,7 @@ impl<'tcx> LateLintPass<'tcx> for StrToString {
if path.ident.name == sym::to_string;
let ty = cx.typeck_results().expr_ty(self_arg);
if let ty::Ref(_, ty, ..) = ty.kind();
- if *ty.kind() == ty::Str;
+ if ty.is_str();
then {
span_lint_and_help(
cx,
diff --git a/src/tools/clippy/clippy_lints/src/suspicious_xor_used_as_pow.rs b/src/tools/clippy/clippy_lints/src/suspicious_xor_used_as_pow.rs
index 301aa5798..9c0dc8096 100644
--- a/src/tools/clippy/clippy_lints/src/suspicious_xor_used_as_pow.rs
+++ b/src/tools/clippy/clippy_lints/src/suspicious_xor_used_as_pow.rs
@@ -9,7 +9,7 @@ declare_clippy_lint! {
/// ### What it does
/// Warns for a Bitwise XOR (`^`) operator being probably confused as a powering. It will not trigger if any of the numbers are not in decimal.
/// ### Why is this bad?
- /// It's most probably a typo and may lead to unexpected behaviours.
+ /// It's most probably a typo and may lead to unexpected behaviours.
/// ### Example
/// ```rust
/// let x = 3_i32 ^ 4_i32;
@@ -18,7 +18,7 @@ declare_clippy_lint! {
/// ```rust
/// let x = 3_i32.pow(4);
/// ```
- #[clippy::version = "1.66.0"]
+ #[clippy::version = "1.67.0"]
pub SUSPICIOUS_XOR_USED_AS_POW,
restriction,
"XOR (`^`) operator possibly used as exponentiation operator"
diff --git a/src/tools/clippy/clippy_lints/src/swap.rs b/src/tools/clippy/clippy_lints/src/swap.rs
index 17e9cc5f6..0f062cecf 100644
--- a/src/tools/clippy/clippy_lints/src/swap.rs
+++ b/src/tools/clippy/clippy_lints/src/swap.rs
@@ -10,7 +10,7 @@ use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::ty;
use rustc_session::{declare_lint_pass, declare_tool_lint};
use rustc_span::source_map::Spanned;
-use rustc_span::{sym, Span};
+use rustc_span::{sym, symbol::Ident, Span};
declare_clippy_lint! {
/// ### What it does
@@ -174,53 +174,74 @@ fn check_manual_swap(cx: &LateContext<'_>, block: &Block<'_>) {
/// Implementation of the `ALMOST_SWAPPED` lint.
fn check_suspicious_swap(cx: &LateContext<'_>, block: &Block<'_>) {
- for w in block.stmts.windows(2) {
- if_chain! {
- if let StmtKind::Semi(first) = w[0].kind;
- if let StmtKind::Semi(second) = w[1].kind;
- if first.span.ctxt() == second.span.ctxt();
- if let ExprKind::Assign(lhs0, rhs0, _) = first.kind;
- if let ExprKind::Assign(lhs1, rhs1, _) = second.kind;
- if eq_expr_value(cx, lhs0, rhs1);
- if eq_expr_value(cx, lhs1, rhs0);
- then {
- let lhs0 = Sugg::hir_opt(cx, lhs0);
- let rhs0 = Sugg::hir_opt(cx, rhs0);
- let (what, lhs, rhs) = if let (Some(first), Some(second)) = (lhs0, rhs0) {
- (
- format!(" `{first}` and `{second}`"),
- first.mut_addr().to_string(),
- second.mut_addr().to_string(),
- )
- } else {
- (String::new(), String::new(), String::new())
- };
+ for [first, second] in block.stmts.array_windows() {
+ if let Some((lhs0, rhs0)) = parse(first)
+ && let Some((lhs1, rhs1)) = parse(second)
+ && first.span.eq_ctxt(second.span)
+ && is_same(cx, lhs0, rhs1)
+ && is_same(cx, lhs1, rhs0)
+ && let Some(lhs_sugg) = match &lhs0 {
+ ExprOrIdent::Expr(expr) => Sugg::hir_opt(cx, expr),
+ ExprOrIdent::Ident(ident) => Some(Sugg::NonParen(ident.as_str().into())),
+ }
+ && let Some(rhs_sugg) = Sugg::hir_opt(cx, rhs0)
+ {
+ let span = first.span.to(rhs1.span);
+ let Some(sugg) = std_or_core(cx) else { return };
+ span_lint_and_then(
+ cx,
+ ALMOST_SWAPPED,
+ span,
+ &format!("this looks like you are trying to swap `{lhs_sugg}` and `{rhs_sugg}`"),
+ |diag| {
+ diag.span_suggestion(
+ span,
+ "try",
+ format!("{sugg}::mem::swap({}, {})", lhs_sugg.mut_addr(), rhs_sugg.mut_addr()),
+ Applicability::MaybeIncorrect,
+ );
+ diag.note(format!("or maybe you should use `{sugg}::mem::replace`?"));
+ },
+ );
+ }
+ }
+}
+
+fn is_same(cx: &LateContext<'_>, lhs: ExprOrIdent<'_>, rhs: &Expr<'_>) -> bool {
+ match lhs {
+ ExprOrIdent::Expr(expr) => eq_expr_value(cx, expr, rhs),
+ ExprOrIdent::Ident(ident) => {
+ if let ExprKind::Path(QPath::Resolved(None, path)) = rhs.kind
+ && let [segment] = &path.segments
+ && segment.ident == ident
+ {
+ true
+ } else {
+ false
+ }
+ }
+ }
+}
- let span = first.span.to(second.span);
- let Some(sugg) = std_or_core(cx) else { return };
+#[derive(Debug, Clone, Copy)]
+enum ExprOrIdent<'a> {
+ Expr(&'a Expr<'a>),
+ Ident(Ident),
+}
- span_lint_and_then(cx,
- ALMOST_SWAPPED,
- span,
- &format!("this looks like you are trying to swap{what}"),
- |diag| {
- if !what.is_empty() {
- diag.span_suggestion(
- span,
- "try",
- format!(
- "{sugg}::mem::swap({lhs}, {rhs})",
- ),
- Applicability::MaybeIncorrect,
- );
- diag.note(
- format!("or maybe you should use `{sugg}::mem::replace`?")
- );
- }
- });
+fn parse<'a, 'hir>(stmt: &'a Stmt<'hir>) -> Option<(ExprOrIdent<'hir>, &'a Expr<'hir>)> {
+ if let StmtKind::Semi(expr) = stmt.kind {
+ if let ExprKind::Assign(lhs, rhs, _) = expr.kind {
+ return Some((ExprOrIdent::Expr(lhs), rhs));
+ }
+ } else if let StmtKind::Local(expr) = stmt.kind {
+ if let Some(rhs) = expr.init {
+ if let PatKind::Binding(_, _, ident_l, _) = expr.pat.kind {
+ return Some((ExprOrIdent::Ident(ident_l), rhs));
}
}
}
+ None
}
/// Implementation of the xor case for `MANUAL_SWAP` lint.
diff --git a/src/tools/clippy/clippy_lints/src/trailing_empty_array.rs b/src/tools/clippy/clippy_lints/src/trailing_empty_array.rs
index 63b326048..1382c1a40 100644
--- a/src/tools/clippy/clippy_lints/src/trailing_empty_array.rs
+++ b/src/tools/clippy/clippy_lints/src/trailing_empty_array.rs
@@ -61,9 +61,8 @@ fn is_struct_with_trailing_zero_sized_array(cx: &LateContext<'_>, item: &Item<'_
if let rustc_hir::TyKind::Array(_, rustc_hir::ArrayLen::Body(length)) = last_field.ty.kind;
// Then check if that that array zero-sized
- let length_ldid = cx.tcx.hir().local_def_id(length.hir_id);
- let length = Const::from_anon_const(cx.tcx, length_ldid);
- let length = length.try_eval_usize(cx.tcx, cx.param_env);
+ let length = Const::from_anon_const(cx.tcx, length.def_id);
+ let length = length.try_eval_target_usize(cx.tcx, cx.param_env);
if let Some(length) = length;
then {
length == 0
diff --git a/src/tools/clippy/clippy_lints/src/transmute/mod.rs b/src/tools/clippy/clippy_lints/src/transmute/mod.rs
index 691d759d7..c01cbe509 100644
--- a/src/tools/clippy/clippy_lints/src/transmute/mod.rs
+++ b/src/tools/clippy/clippy_lints/src/transmute/mod.rs
@@ -3,6 +3,7 @@ mod transmute_float_to_int;
mod transmute_int_to_bool;
mod transmute_int_to_char;
mod transmute_int_to_float;
+mod transmute_int_to_non_zero;
mod transmute_null_to_fn;
mod transmute_num_to_bytes;
mod transmute_ptr_to_ptr;
@@ -255,6 +256,31 @@ declare_clippy_lint! {
declare_clippy_lint! {
/// ### What it does
+ /// Checks for transmutes from integers to `NonZero*` types, and suggests their `new_unchecked`
+ /// method instead.
+ ///
+ /// ### Why is this bad?
+ /// Transmutes work on any types and thus might cause unsoundness when those types change
+ /// elsewhere. `new_unchecked` only works for the appropriate types instead.
+ ///
+ /// ### Example
+ /// ```rust
+ /// # use core::num::NonZeroU32;
+ /// let _non_zero: NonZeroU32 = unsafe { std::mem::transmute(123) };
+ /// ```
+ /// Use instead:
+ /// ```rust
+ /// # use core::num::NonZeroU32;
+ /// let _non_zero = unsafe { NonZeroU32::new_unchecked(123) };
+ /// ```
+ #[clippy::version = "1.69.0"]
+ pub TRANSMUTE_INT_TO_NON_ZERO,
+ complexity,
+ "transmutes from an integer to a non-zero wrapper"
+}
+
+declare_clippy_lint! {
+ /// ### What it does
/// Checks for transmutes from a float to an integer.
///
/// ### Why is this bad?
@@ -451,6 +477,7 @@ impl_lint_pass!(Transmute => [
TRANSMUTE_BYTES_TO_STR,
TRANSMUTE_INT_TO_BOOL,
TRANSMUTE_INT_TO_FLOAT,
+ TRANSMUTE_INT_TO_NON_ZERO,
TRANSMUTE_FLOAT_TO_INT,
TRANSMUTE_NUM_TO_BYTES,
UNSOUND_COLLECTION_TRANSMUTE,
@@ -479,7 +506,10 @@ impl<'tcx> LateLintPass<'tcx> for Transmute {
// - char conversions (https://github.com/rust-lang/rust/issues/89259)
let const_context = in_constant(cx, e.hir_id);
- let from_ty = cx.typeck_results().expr_ty_adjusted(arg);
+ let (from_ty, from_ty_adjusted) = match cx.typeck_results().expr_adjustments(arg) {
+ [] => (cx.typeck_results().expr_ty(arg), false),
+ [.., a] => (a.target, true),
+ };
// Adjustments for `to_ty` happen after the call to `transmute`, so don't use them.
let to_ty = cx.typeck_results().expr_ty(e);
@@ -498,6 +528,7 @@ impl<'tcx> LateLintPass<'tcx> for Transmute {
| transmute_ptr_to_ptr::check(cx, e, from_ty, to_ty, arg)
| transmute_int_to_bool::check(cx, e, from_ty, to_ty, arg)
| transmute_int_to_float::check(cx, e, from_ty, to_ty, arg, const_context)
+ | transmute_int_to_non_zero::check(cx, e, from_ty, to_ty, arg)
| transmute_float_to_int::check(cx, e, from_ty, to_ty, arg, const_context)
| transmute_num_to_bytes::check(cx, e, from_ty, to_ty, arg, const_context)
| (
@@ -506,7 +537,7 @@ impl<'tcx> LateLintPass<'tcx> for Transmute {
);
if !linted {
- transmutes_expressible_as_ptr_casts::check(cx, e, from_ty, to_ty, arg);
+ transmutes_expressible_as_ptr_casts::check(cx, e, from_ty, from_ty_adjusted, to_ty, arg);
}
}
}
diff --git a/src/tools/clippy/clippy_lints/src/transmute/transmute_int_to_non_zero.rs b/src/tools/clippy/clippy_lints/src/transmute/transmute_int_to_non_zero.rs
new file mode 100644
index 000000000..550365325
--- /dev/null
+++ b/src/tools/clippy/clippy_lints/src/transmute/transmute_int_to_non_zero.rs
@@ -0,0 +1,61 @@
+use super::TRANSMUTE_INT_TO_NON_ZERO;
+use clippy_utils::diagnostics::span_lint_and_then;
+use clippy_utils::sugg;
+use rustc_errors::Applicability;
+use rustc_hir::Expr;
+use rustc_lint::LateContext;
+use rustc_middle::{
+ query::Key,
+ ty::{self, Ty},
+};
+use rustc_span::symbol::sym;
+
+/// Checks for `transmute_int_to_non_zero` lint.
+/// Returns `true` if it's triggered, otherwise returns `false`.
+pub(super) fn check<'tcx>(
+ cx: &LateContext<'tcx>,
+ e: &'tcx Expr<'_>,
+ from_ty: Ty<'tcx>,
+ to_ty: Ty<'tcx>,
+ arg: &'tcx Expr<'_>,
+) -> bool {
+ let (ty::Int(_) | ty::Uint(_), Some(to_ty_id)) = (&from_ty.kind(), to_ty.ty_adt_id()) else {
+ return false;
+ };
+ let Some(to_type_sym) = cx.tcx.get_diagnostic_name(to_ty_id) else {
+ return false;
+ };
+
+ if !matches!(
+ to_type_sym,
+ sym::NonZeroU8
+ | sym::NonZeroU16
+ | sym::NonZeroU32
+ | sym::NonZeroU64
+ | sym::NonZeroU128
+ | sym::NonZeroI8
+ | sym::NonZeroI16
+ | sym::NonZeroI32
+ | sym::NonZeroI64
+ | sym::NonZeroI128
+ ) {
+ return false;
+ }
+
+ span_lint_and_then(
+ cx,
+ TRANSMUTE_INT_TO_NON_ZERO,
+ e.span,
+ &format!("transmute from a `{from_ty}` to a `{to_type_sym}`"),
+ |diag| {
+ let arg = sugg::Sugg::hir(cx, arg, "..");
+ diag.span_suggestion(
+ e.span,
+ "consider using",
+ format!("{to_type_sym}::{}({arg})", sym::new_unchecked),
+ Applicability::Unspecified,
+ );
+ },
+ );
+ true
+}
diff --git a/src/tools/clippy/clippy_lints/src/transmute/transmute_ptr_to_ref.rs b/src/tools/clippy/clippy_lints/src/transmute/transmute_ptr_to_ref.rs
index 54ac04df1..6bdb9aa5a 100644
--- a/src/tools/clippy/clippy_lints/src/transmute/transmute_ptr_to_ref.rs
+++ b/src/tools/clippy/clippy_lints/src/transmute/transmute_ptr_to_ref.rs
@@ -6,7 +6,7 @@ use clippy_utils::sugg;
use rustc_errors::Applicability;
use rustc_hir::{self as hir, Expr, GenericArg, Mutability, Path, TyKind};
use rustc_lint::LateContext;
-use rustc_middle::ty::{self, Ty, TypeVisitable};
+use rustc_middle::ty::{self, Ty, TypeVisitableExt};
/// Checks for `transmute_ptr_to_ref` lint.
/// Returns `true` if it's triggered, otherwise returns `false`.
diff --git a/src/tools/clippy/clippy_lints/src/transmute/transmute_ref_to_ref.rs b/src/tools/clippy/clippy_lints/src/transmute/transmute_ref_to_ref.rs
index afb7f2e13..426c72538 100644
--- a/src/tools/clippy/clippy_lints/src/transmute/transmute_ref_to_ref.rs
+++ b/src/tools/clippy/clippy_lints/src/transmute/transmute_ref_to_ref.rs
@@ -22,7 +22,8 @@ pub(super) fn check<'tcx>(
if let (ty::Ref(_, ty_from, from_mutbl), ty::Ref(_, ty_to, to_mutbl)) = (&from_ty.kind(), &to_ty.kind()) {
if_chain! {
- if let (&ty::Slice(slice_ty), &ty::Str) = (&ty_from.kind(), &ty_to.kind());
+ if let ty::Slice(slice_ty) = *ty_from.kind();
+ if ty_to.is_str();
if let ty::Uint(ty::UintTy::U8) = slice_ty.kind();
if from_mutbl == to_mutbl;
then {
diff --git a/src/tools/clippy/clippy_lints/src/transmute/transmute_undefined_repr.rs b/src/tools/clippy/clippy_lints/src/transmute/transmute_undefined_repr.rs
index af0242348..5e24213d0 100644
--- a/src/tools/clippy/clippy_lints/src/transmute/transmute_undefined_repr.rs
+++ b/src/tools/clippy/clippy_lints/src/transmute/transmute_undefined_repr.rs
@@ -273,7 +273,7 @@ fn reduce_ty<'tcx>(cx: &LateContext<'tcx>, mut ty: Ty<'tcx>) -> ReducedTy<'tcx>
.non_enum_variant()
.fields
.iter()
- .map(|f| cx.tcx.bound_type_of(f.did).subst(cx.tcx, substs));
+ .map(|f| cx.tcx.type_of(f.did).subst(cx.tcx, substs));
let Some(sized_ty) = iter.find(|&ty| !is_zero_sized_ty(cx, ty)) else {
return ReducedTy::TypeErasure { raw_ptr_only: false };
};
diff --git a/src/tools/clippy/clippy_lints/src/transmute/transmutes_expressible_as_ptr_casts.rs b/src/tools/clippy/clippy_lints/src/transmute/transmutes_expressible_as_ptr_casts.rs
index b79d4e915..8530b4324 100644
--- a/src/tools/clippy/clippy_lints/src/transmute/transmutes_expressible_as_ptr_casts.rs
+++ b/src/tools/clippy/clippy_lints/src/transmute/transmutes_expressible_as_ptr_casts.rs
@@ -1,11 +1,11 @@
-use super::utils::can_be_expressed_as_pointer_cast;
+use super::utils::check_cast;
use super::TRANSMUTES_EXPRESSIBLE_AS_PTR_CASTS;
-use clippy_utils::diagnostics::span_lint_and_then;
-use clippy_utils::sugg;
+use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::sugg::Sugg;
use rustc_errors::Applicability;
use rustc_hir::Expr;
use rustc_lint::LateContext;
-use rustc_middle::ty::Ty;
+use rustc_middle::ty::{cast::CastKind, Ty};
/// Checks for `transmutes_expressible_as_ptr_casts` lint.
/// Returns `true` if it's triggered, otherwise returns `false`.
@@ -13,24 +13,40 @@ pub(super) fn check<'tcx>(
cx: &LateContext<'tcx>,
e: &'tcx Expr<'_>,
from_ty: Ty<'tcx>,
+ from_ty_adjusted: bool,
to_ty: Ty<'tcx>,
arg: &'tcx Expr<'_>,
) -> bool {
- if can_be_expressed_as_pointer_cast(cx, e, from_ty, to_ty) {
- span_lint_and_then(
- cx,
- TRANSMUTES_EXPRESSIBLE_AS_PTR_CASTS,
- e.span,
- &format!("transmute from `{from_ty}` to `{to_ty}` which could be expressed as a pointer cast instead"),
- |diag| {
- if let Some(arg) = sugg::Sugg::hir_opt(cx, arg) {
- let sugg = arg.as_ty(to_ty.to_string()).to_string();
- diag.span_suggestion(e.span, "try", sugg, Applicability::MachineApplicable);
- }
- },
- );
- true
- } else {
- false
- }
+ use CastKind::{AddrPtrCast, ArrayPtrCast, FnPtrAddrCast, FnPtrPtrCast, PtrAddrCast, PtrPtrCast};
+ let mut app = Applicability::MachineApplicable;
+ let sugg = match check_cast(cx, e, from_ty, to_ty) {
+ Some(PtrPtrCast | AddrPtrCast | ArrayPtrCast | FnPtrPtrCast | FnPtrAddrCast) => {
+ Sugg::hir_with_context(cx, arg, e.span.ctxt(), "..", &mut app)
+ .as_ty(to_ty.to_string())
+ .to_string()
+ },
+ Some(PtrAddrCast) if !from_ty_adjusted => Sugg::hir_with_context(cx, arg, e.span.ctxt(), "..", &mut app)
+ .as_ty(to_ty.to_string())
+ .to_string(),
+
+ // The only adjustments here would be ref-to-ptr and unsize coercions. The result of an unsize coercions can't
+ // be transmuted to a usize. For ref-to-ptr coercions, borrows need to be cast to a pointer before being cast to
+ // a usize.
+ Some(PtrAddrCast) => format!(
+ "{} as {to_ty}",
+ Sugg::hir_with_context(cx, arg, e.span.ctxt(), "..", &mut app).as_ty(from_ty)
+ ),
+ _ => return false,
+ };
+
+ span_lint_and_sugg(
+ cx,
+ TRANSMUTES_EXPRESSIBLE_AS_PTR_CASTS,
+ e.span,
+ &format!("transmute from `{from_ty}` to `{to_ty}` which could be expressed as a pointer cast instead"),
+ "try",
+ sugg,
+ app,
+ );
+ true
}
diff --git a/src/tools/clippy/clippy_lints/src/transmute/useless_transmute.rs b/src/tools/clippy/clippy_lints/src/transmute/useless_transmute.rs
index 871c3fadb..56207fe76 100644
--- a/src/tools/clippy/clippy_lints/src/transmute/useless_transmute.rs
+++ b/src/tools/clippy/clippy_lints/src/transmute/useless_transmute.rs
@@ -4,7 +4,7 @@ use clippy_utils::sugg;
use rustc_errors::Applicability;
use rustc_hir::Expr;
use rustc_lint::LateContext;
-use rustc_middle::ty::{self, Ty, TypeVisitable};
+use rustc_middle::ty::{self, Ty, TypeVisitableExt};
/// Checks for `useless_transmute` lint.
/// Returns `true` if it's triggered, otherwise returns `false`.
diff --git a/src/tools/clippy/clippy_lints/src/transmute/utils.rs b/src/tools/clippy/clippy_lints/src/transmute/utils.rs
index 49d863ec0..cddaf9450 100644
--- a/src/tools/clippy/clippy_lints/src/transmute/utils.rs
+++ b/src/tools/clippy/clippy_lints/src/transmute/utils.rs
@@ -20,33 +20,21 @@ pub(super) fn is_layout_incompatible<'tcx>(cx: &LateContext<'tcx>, from: Ty<'tcx
}
}
-/// Check if the type conversion can be expressed as a pointer cast, instead of
-/// a transmute. In certain cases, including some invalid casts from array
-/// references to pointers, this may cause additional errors to be emitted and/or
-/// ICE error messages. This function will panic if that occurs.
-pub(super) fn can_be_expressed_as_pointer_cast<'tcx>(
- cx: &LateContext<'tcx>,
- e: &'tcx Expr<'_>,
- from_ty: Ty<'tcx>,
- to_ty: Ty<'tcx>,
-) -> bool {
- use CastKind::{AddrPtrCast, ArrayPtrCast, FnPtrAddrCast, FnPtrPtrCast, PtrAddrCast, PtrPtrCast};
- matches!(
- check_cast(cx, e, from_ty, to_ty),
- Some(PtrPtrCast | PtrAddrCast | AddrPtrCast | ArrayPtrCast | FnPtrPtrCast | FnPtrAddrCast)
- )
-}
-
/// If a cast from `from_ty` to `to_ty` is valid, returns an Ok containing the kind of
/// the cast. In certain cases, including some invalid casts from array references
/// to pointers, this may cause additional errors to be emitted and/or ICE error
/// messages. This function will panic if that occurs.
-fn check_cast<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>, from_ty: Ty<'tcx>, to_ty: Ty<'tcx>) -> Option<CastKind> {
+pub(super) fn check_cast<'tcx>(
+ cx: &LateContext<'tcx>,
+ e: &'tcx Expr<'_>,
+ from_ty: Ty<'tcx>,
+ to_ty: Ty<'tcx>,
+) -> Option<CastKind> {
let hir_id = e.hir_id;
let local_def_id = hir_id.owner.def_id;
Inherited::build(cx.tcx, local_def_id).enter(|inherited| {
- let fn_ctxt = FnCtxt::new(inherited, cx.param_env, hir_id);
+ let fn_ctxt = FnCtxt::new(inherited, cx.param_env, local_def_id);
// If we already have errors, we can't be sure we can pointer cast.
assert!(
diff --git a/src/tools/clippy/clippy_lints/src/types/mod.rs b/src/tools/clippy/clippy_lints/src/types/mod.rs
index 229478b7c..c1f228d5f 100644
--- a/src/tools/clippy/clippy_lints/src/types/mod.rs
+++ b/src/tools/clippy/clippy_lints/src/types/mod.rs
@@ -12,11 +12,12 @@ mod vec_box;
use rustc_hir as hir;
use rustc_hir::intravisit::FnKind;
use rustc_hir::{
- Body, FnDecl, FnRetTy, GenericArg, HirId, ImplItem, ImplItemKind, Item, ItemKind, Local, MutTy, QPath, TraitItem,
+ Body, FnDecl, FnRetTy, GenericArg, ImplItem, ImplItemKind, Item, ItemKind, Local, MutTy, QPath, TraitItem,
TraitItemKind, TyKind,
};
use rustc_lint::{LateContext, LateLintPass};
use rustc_session::{declare_tool_lint, impl_lint_pass};
+use rustc_span::def_id::LocalDefId;
use rustc_span::source_map::Span;
declare_clippy_lint! {
@@ -311,15 +312,27 @@ pub struct Types {
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) {
- let is_in_trait_impl =
- if let Some(hir::Node::Item(item)) = cx.tcx.hir().find_by_def_id(cx.tcx.hir().get_parent_item(id).def_id) {
- matches!(item.kind, ItemKind::Impl(hir::Impl { of_trait: Some(_), .. }))
- } else {
- false
- };
+ fn check_fn(
+ &mut self,
+ cx: &LateContext<'_>,
+ _: FnKind<'_>,
+ decl: &FnDecl<'_>,
+ _: &Body<'_>,
+ _: Span,
+ def_id: LocalDefId,
+ ) {
+ let is_in_trait_impl = if let Some(hir::Node::Item(item)) = cx.tcx.hir().find_by_def_id(
+ cx.tcx
+ .hir()
+ .get_parent_item(cx.tcx.hir().local_def_id_to_hir_id(def_id))
+ .def_id,
+ ) {
+ matches!(item.kind, ItemKind::Impl(hir::Impl { of_trait: Some(_), .. }))
+ } else {
+ false
+ };
- let is_exported = cx.effective_visibilities.is_exported(cx.tcx.hir().local_def_id(id));
+ let is_exported = cx.effective_visibilities.is_exported(def_id);
self.check_fn_decl(
cx,
@@ -379,9 +392,7 @@ impl<'tcx> LateLintPass<'tcx> for Types {
}
fn check_field_def(&mut self, cx: &LateContext<'_>, field: &hir::FieldDef<'_>) {
- let is_exported = cx
- .effective_visibilities
- .is_exported(cx.tcx.hir().local_def_id(field.hir_id));
+ let is_exported = cx.effective_visibilities.is_exported(field.def_id);
self.check_ty(
cx,
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 f9b9a66b5..f7adc9d35 100644
--- a/src/tools/clippy/clippy_lints/src/types/redundant_allocation.rs
+++ b/src/tools/clippy/clippy_lints/src/types/redundant_allocation.rs
@@ -5,7 +5,7 @@ use rustc_errors::Applicability;
use rustc_hir::{self as hir, def_id::DefId, QPath, TyKind};
use rustc_hir_analysis::hir_ty_to_ty;
use rustc_lint::LateContext;
-use rustc_middle::ty::TypeVisitable;
+use rustc_middle::ty::TypeVisitableExt;
use rustc_span::symbol::sym;
use super::{utils, REDUNDANT_ALLOCATION};
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 7a3c7cd8a..d3062f3d2 100644
--- a/src/tools/clippy/clippy_lints/src/types/vec_box.rs
+++ b/src/tools/clippy/clippy_lints/src/types/vec_box.rs
@@ -7,7 +7,7 @@ use rustc_hir::{self as hir, def_id::DefId, GenericArg, QPath, TyKind};
use rustc_hir_analysis::hir_ty_to_ty;
use rustc_lint::LateContext;
use rustc_middle::ty::layout::LayoutOf;
-use rustc_middle::ty::TypeVisitable;
+use rustc_middle::ty::TypeVisitableExt;
use rustc_span::symbol::sym;
use super::VEC_BOX;
diff --git a/src/tools/clippy/clippy_lints/src/undocumented_unsafe_blocks.rs b/src/tools/clippy/clippy_lints/src/undocumented_unsafe_blocks.rs
index 2e1b6d8d4..2920684ad 100644
--- a/src/tools/clippy/clippy_lints/src/undocumented_unsafe_blocks.rs
+++ b/src/tools/clippy/clippy_lints/src/undocumented_unsafe_blocks.rs
@@ -263,6 +263,18 @@ fn expr_has_unnecessary_safety_comment<'tcx>(
expr: &'tcx hir::Expr<'tcx>,
comment_pos: BytePos,
) -> Option<Span> {
+ if cx.tcx.hir().parent_iter(expr.hir_id).any(|(_, ref node)| {
+ matches!(
+ node,
+ Node::Block(&Block {
+ rules: BlockCheckMode::UnsafeBlock(UnsafeSource::UserProvided),
+ ..
+ }),
+ )
+ }) {
+ return None;
+ }
+
// this should roughly be the reverse of `block_parents_have_safety_comment`
if for_each_expr_with_closures(cx, expr, |expr| match expr.kind {
hir::ExprKind::Block(
diff --git a/src/tools/clippy/clippy_lints/src/unit_return_expecting_ord.rs b/src/tools/clippy/clippy_lints/src/unit_return_expecting_ord.rs
index a138a4baa..289ca4e9b 100644
--- a/src/tools/clippy/clippy_lints/src/unit_return_expecting_ord.rs
+++ b/src/tools/clippy/clippy_lints/src/unit_return_expecting_ord.rs
@@ -76,7 +76,7 @@ fn get_projection_pred<'tcx>(
fn get_args_to_check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) -> Vec<(usize, String)> {
let mut args_to_check = Vec::new();
if let Some(def_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id) {
- let fn_sig = cx.tcx.fn_sig(def_id);
+ let fn_sig = cx.tcx.fn_sig(def_id).subst_identity();
let generics = cx.tcx.predicates_of(def_id);
let fn_mut_preds = get_trait_predicates_for_trait_id(cx, generics, cx.tcx.lang_items().fn_mut_trait());
let ord_preds = get_trait_predicates_for_trait_id(cx, generics, cx.tcx.get_diagnostic_item(sym::Ord));
diff --git a/src/tools/clippy/clippy_lints/src/unit_types/let_unit_value.rs b/src/tools/clippy/clippy_lints/src/unit_types/let_unit_value.rs
index ce9ebad8c..d6167a621 100644
--- a/src/tools/clippy/clippy_lints/src/unit_types/let_unit_value.rs
+++ b/src/tools/clippy/clippy_lints/src/unit_types/let_unit_value.rs
@@ -156,7 +156,7 @@ fn needs_inferred_result_ty(
},
_ => return false,
};
- let sig = cx.tcx.fn_sig(id).skip_binder();
+ let sig = cx.tcx.fn_sig(id).subst_identity().skip_binder();
if let ty::Param(output_ty) = *sig.output().kind() {
let args: Vec<&Expr<'_>> = if let Some(receiver) = receiver {
std::iter::once(receiver).chain(args.iter()).collect()
diff --git a/src/tools/clippy/clippy_lints/src/unnecessary_owned_empty_strings.rs b/src/tools/clippy/clippy_lints/src/unnecessary_owned_empty_strings.rs
index 9f207d32f..6e802794f 100644
--- a/src/tools/clippy/clippy_lints/src/unnecessary_owned_empty_strings.rs
+++ b/src/tools/clippy/clippy_lints/src/unnecessary_owned_empty_strings.rs
@@ -7,6 +7,7 @@ use rustc_hir::{BorrowKind, Expr, ExprKind, LangItem, Mutability};
use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::ty;
use rustc_session::{declare_lint_pass, declare_tool_lint};
+use rustc_span::symbol::sym;
declare_clippy_lint! {
/// ### What it does
@@ -54,7 +55,7 @@ impl<'tcx> LateLintPass<'tcx> for UnnecessaryOwnedEmptyStrings {
);
} else {
if_chain! {
- if Some(fun_def_id) == cx.tcx.lang_items().from_fn();
+ if cx.tcx.is_diagnostic_item(sym::from_fn, fun_def_id);
if let [.., last_arg] = args;
if let ExprKind::Lit(spanned) = &last_arg.kind;
if let LitKind::Str(symbol, _) = spanned.node;
diff --git a/src/tools/clippy/clippy_lints/src/unnecessary_wraps.rs b/src/tools/clippy/clippy_lints/src/unnecessary_wraps.rs
index 84ec0d0fb..8b0e0ce5a 100644
--- a/src/tools/clippy/clippy_lints/src/unnecessary_wraps.rs
+++ b/src/tools/clippy/clippy_lints/src/unnecessary_wraps.rs
@@ -5,10 +5,11 @@ use if_chain::if_chain;
use rustc_errors::Applicability;
use rustc_hir::intravisit::FnKind;
use rustc_hir::LangItem::{OptionSome, ResultOk};
-use rustc_hir::{Body, ExprKind, FnDecl, HirId, Impl, ItemKind, Node};
+use rustc_hir::{Body, ExprKind, FnDecl, Impl, ItemKind, Node};
use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::ty;
use rustc_session::{declare_tool_lint, impl_lint_pass};
+use rustc_span::def_id::LocalDefId;
use rustc_span::symbol::sym;
use rustc_span::Span;
@@ -77,12 +78,11 @@ impl<'tcx> LateLintPass<'tcx> for UnnecessaryWraps {
fn_decl: &FnDecl<'tcx>,
body: &Body<'tcx>,
span: Span,
- hir_id: HirId,
+ def_id: LocalDefId,
) {
// Abort if public function/method or closure.
match fn_kind {
FnKind::ItemFn(..) | FnKind::Method(..) => {
- let def_id = cx.tcx.hir().local_def_id(hir_id);
if self.avoid_breaking_exported_api && cx.effective_visibilities.is_exported(def_id) {
return;
}
@@ -91,6 +91,7 @@ impl<'tcx> LateLintPass<'tcx> for UnnecessaryWraps {
}
// Abort if the method is implementing a trait or of it a trait method.
+ let hir_id = cx.tcx.hir().local_def_id_to_hir_id(def_id);
if let Some(Node::Item(item)) = cx.tcx.hir().find_parent(hir_id) {
if matches!(
item.kind,
@@ -101,17 +102,18 @@ 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, adt_def.did()) {
- ("Option", OptionSome, subst.type_at(0))
- } else if cx.tcx.is_diagnostic_item(sym::Result, adt_def.did()) {
- ("Result", ResultOk, subst.type_at(0))
+ let (return_type_label, lang_item, inner_type) =
+ if let ty::Adt(adt_def, subst) = return_ty(cx, hir_id.expect_owner()).kind() {
+ 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, adt_def.did()) {
+ ("Result", ResultOk, subst.type_at(0))
+ } else {
+ return;
+ }
} else {
return;
- }
- } else {
- return;
- };
+ };
// Check if all return expression respect the following condition and collect them.
let mut suggs = Vec::new();
diff --git a/src/tools/clippy/clippy_lints/src/unnested_or_patterns.rs b/src/tools/clippy/clippy_lints/src/unnested_or_patterns.rs
index 7355260ae..a57bf7ee8 100644
--- a/src/tools/clippy/clippy_lints/src/unnested_or_patterns.rs
+++ b/src/tools/clippy/clippy_lints/src/unnested_or_patterns.rs
@@ -12,9 +12,9 @@ use rustc_errors::Applicability;
use rustc_lint::{EarlyContext, EarlyLintPass};
use rustc_session::{declare_tool_lint, impl_lint_pass};
use rustc_span::DUMMY_SP;
-
use std::cell::Cell;
use std::mem;
+use thin_vec::{thin_vec, ThinVec};
declare_clippy_lint! {
/// ### What it does
@@ -214,7 +214,7 @@ macro_rules! always_pat {
/// Focus on `focus_idx` in `alternatives`,
/// attempting to extend it with elements of the same constructor `C`
/// in `alternatives[focus_idx + 1..]`.
-fn transform_with_focus_on_idx(alternatives: &mut Vec<P<Pat>>, focus_idx: usize) -> bool {
+fn transform_with_focus_on_idx(alternatives: &mut ThinVec<P<Pat>>, focus_idx: usize) -> bool {
// Extract the kind; we'll need to make some changes in it.
let mut focus_kind = mem::replace(&mut alternatives[focus_idx].kind, PatKind::Wild);
// We'll focus on `alternatives[focus_idx]`,
@@ -296,7 +296,7 @@ fn extend_with_struct_pat(
fps1: &mut [ast::PatField],
rest1: bool,
start: usize,
- alternatives: &mut Vec<P<Pat>>,
+ alternatives: &mut ThinVec<P<Pat>>,
) -> bool {
(0..fps1.len()).any(|idx| {
let pos_in_2 = Cell::new(None); // The element `k`.
@@ -336,9 +336,9 @@ fn extend_with_struct_pat(
fn extend_with_matching_product(
targets: &mut [P<Pat>],
start: usize,
- alternatives: &mut Vec<P<Pat>>,
+ alternatives: &mut ThinVec<P<Pat>>,
predicate: impl Fn(&PatKind, &[P<Pat>], usize) -> bool,
- extract: impl Fn(PatKind) -> Vec<P<Pat>>,
+ extract: impl Fn(PatKind) -> ThinVec<P<Pat>>,
) -> bool {
(0..targets.len()).any(|idx| {
let tail_or = drain_matching(
@@ -365,14 +365,14 @@ fn take_pat(from: &mut Pat) -> Pat {
/// Extend `target` as an or-pattern with the alternatives
/// in `tail_or` if there are any and return if there were.
-fn extend_with_tail_or(target: &mut Pat, tail_or: Vec<P<Pat>>) -> bool {
- fn extend(target: &mut Pat, mut tail_or: Vec<P<Pat>>) {
+fn extend_with_tail_or(target: &mut Pat, tail_or: ThinVec<P<Pat>>) -> bool {
+ fn extend(target: &mut Pat, mut tail_or: ThinVec<P<Pat>>) {
match target {
// On an existing or-pattern in the target, append to it.
Pat { kind: Or(ps), .. } => ps.append(&mut tail_or),
// Otherwise convert the target to an or-pattern.
target => {
- let mut init_or = vec![P(take_pat(target))];
+ let mut init_or = thin_vec![P(take_pat(target))];
init_or.append(&mut tail_or);
target.kind = Or(init_or);
},
@@ -391,26 +391,42 @@ fn extend_with_tail_or(target: &mut Pat, tail_or: Vec<P<Pat>>) -> bool {
// Only elements beginning with `start` are considered for extraction.
fn drain_matching(
start: usize,
- alternatives: &mut Vec<P<Pat>>,
+ alternatives: &mut ThinVec<P<Pat>>,
predicate: impl Fn(&PatKind) -> bool,
extract: impl Fn(PatKind) -> P<Pat>,
-) -> Vec<P<Pat>> {
- let mut tail_or = vec![];
+) -> ThinVec<P<Pat>> {
+ let mut tail_or = ThinVec::new();
let mut idx = 0;
- for pat in alternatives.drain_filter(|p| {
- // Check if we should extract, but only if `idx >= start`.
+
+ // If `ThinVec` had the `drain_filter` method, this loop could be rewritten
+ // like so:
+ //
+ // for pat in alternatives.drain_filter(|p| {
+ // // Check if we should extract, but only if `idx >= start`.
+ // idx += 1;
+ // idx > start && predicate(&p.kind)
+ // }) {
+ // tail_or.push(extract(pat.into_inner().kind));
+ // }
+ let mut i = 0;
+ while i < alternatives.len() {
idx += 1;
- idx > start && predicate(&p.kind)
- }) {
- tail_or.push(extract(pat.into_inner().kind));
+ // Check if we should extract, but only if `idx >= start`.
+ if idx > start && predicate(&alternatives[i].kind) {
+ let pat = alternatives.remove(i);
+ tail_or.push(extract(pat.into_inner().kind));
+ } else {
+ i += 1;
+ }
}
+
tail_or
}
fn extend_with_matching(
target: &mut Pat,
start: usize,
- alternatives: &mut Vec<P<Pat>>,
+ alternatives: &mut ThinVec<P<Pat>>,
predicate: impl Fn(&PatKind) -> bool,
extract: impl Fn(PatKind) -> P<Pat>,
) -> bool {
diff --git a/src/tools/clippy/clippy_lints/src/unused_async.rs b/src/tools/clippy/clippy_lints/src/unused_async.rs
index 3538bef6e..55651a28b 100644
--- a/src/tools/clippy/clippy_lints/src/unused_async.rs
+++ b/src/tools/clippy/clippy_lints/src/unused_async.rs
@@ -1,9 +1,10 @@
use clippy_utils::diagnostics::span_lint_and_help;
use rustc_hir::intravisit::{walk_expr, walk_fn, FnKind, Visitor};
-use rustc_hir::{Body, Expr, ExprKind, FnDecl, HirId, YieldSource};
+use rustc_hir::{Body, Expr, ExprKind, FnDecl, YieldSource};
use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::hir::nested_filter;
use rustc_session::{declare_lint_pass, declare_tool_lint};
+use rustc_span::def_id::LocalDefId;
use rustc_span::Span;
declare_clippy_lint! {
@@ -66,11 +67,11 @@ impl<'tcx> LateLintPass<'tcx> for UnusedAsync {
fn_decl: &'tcx FnDecl<'tcx>,
body: &Body<'tcx>,
span: Span,
- hir_id: HirId,
+ def_id: LocalDefId,
) {
if !span.from_expansion() && fn_kind.asyncness().is_async() {
let mut visitor = AsyncFnVisitor { cx, found_await: false };
- walk_fn(&mut visitor, fn_kind, fn_decl, body.id(), hir_id);
+ walk_fn(&mut visitor, fn_kind, fn_decl, body.id(), def_id);
if !visitor.found_await {
span_lint_and_help(
cx,
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 92053cec5..0e526c216 100644
--- a/src/tools/clippy/clippy_lints/src/unused_io_amount.rs
+++ b/src/tools/clippy/clippy_lints/src/unused_io_amount.rs
@@ -65,7 +65,7 @@ impl<'tcx> LateLintPass<'tcx> for UnusedIoAmount {
}
},
hir::ExprKind::MethodCall(path, arg_0, ..) => match path.ident.as_str() {
- "expect" | "unwrap" | "unwrap_or" | "unwrap_or_else" => {
+ "expect" | "unwrap" | "unwrap_or" | "unwrap_or_else" | "is_ok" | "is_err" => {
check_map_error(cx, arg_0, expr);
},
_ => (),
diff --git a/src/tools/clippy/clippy_lints/src/unwrap.rs b/src/tools/clippy/clippy_lints/src/unwrap.rs
index ea878043c..377d3fb6f 100644
--- a/src/tools/clippy/clippy_lints/src/unwrap.rs
+++ b/src/tools/clippy/clippy_lints/src/unwrap.rs
@@ -11,6 +11,7 @@ use rustc_middle::hir::nested_filter;
use rustc_middle::lint::in_external_macro;
use rustc_middle::ty::Ty;
use rustc_session::{declare_lint_pass, declare_tool_lint};
+use rustc_span::def_id::LocalDefId;
use rustc_span::source_map::Span;
use rustc_span::sym;
@@ -312,7 +313,7 @@ impl<'tcx> LateLintPass<'tcx> for Unwrap {
decl: &'tcx FnDecl<'_>,
body: &'tcx Body<'_>,
span: Span,
- fn_id: HirId,
+ fn_id: LocalDefId,
) {
if span.from_expansion() {
return;
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 f3611d174..3a1845425 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)
- || is_type_diagnostic_item(cx, return_ty(cx, impl_item.hir_id()), sym::Option);
+ if is_type_diagnostic_item(cx, return_ty(cx, impl_item.owner_id), sym::Result)
+ || is_type_diagnostic_item(cx, return_ty(cx, impl_item.owner_id), sym::Option);
then {
lint_impl_body(cx, impl_item.span, impl_item);
}
diff --git a/src/tools/clippy/clippy_lints/src/use_self.rs b/src/tools/clippy/clippy_lints/src/use_self.rs
index 6ae9d9d63..e7c540006 100644
--- a/src/tools/clippy/clippy_lints/src/use_self.rs
+++ b/src/tools/clippy/clippy_lints/src/use_self.rs
@@ -146,7 +146,7 @@ impl<'tcx> LateLintPass<'tcx> for UseSelf {
.associated_item(impl_item.owner_id)
.trait_item_def_id
.expect("impl method matches a trait method");
- let trait_method_sig = cx.tcx.fn_sig(trait_method);
+ let trait_method_sig = cx.tcx.fn_sig(trait_method).subst_identity();
let trait_method_sig = cx.tcx.erase_late_bound_regions(trait_method_sig);
// `impl_inputs_outputs` is an iterator over the types (`hir::Ty`) declared in the
@@ -218,7 +218,7 @@ impl<'tcx> LateLintPass<'tcx> for UseSelf {
} else {
hir_ty_to_ty(cx.tcx, hir_ty)
};
- if same_type_and_consts(ty, cx.tcx.type_of(impl_id));
+ if same_type_and_consts(ty, cx.tcx.type_of(impl_id).subst_identity());
then {
span_lint(cx, hir_ty.span);
}
@@ -230,7 +230,7 @@ impl<'tcx> LateLintPass<'tcx> for UseSelf {
if !expr.span.from_expansion();
if self.msrv.meets(msrvs::TYPE_ALIAS_ENUM_VARIANTS);
if let Some(&StackItem::Check { impl_id, .. }) = self.stack.last();
- if cx.typeck_results().expr_ty(expr) == cx.tcx.type_of(impl_id);
+ if cx.typeck_results().expr_ty(expr) == cx.tcx.type_of(impl_id).subst_identity();
then {} else { return; }
}
match expr.kind {
@@ -254,7 +254,7 @@ impl<'tcx> LateLintPass<'tcx> for UseSelf {
if let PatKind::Path(QPath::Resolved(_, path))
| PatKind::TupleStruct(QPath::Resolved(_, path), _, _)
| PatKind::Struct(QPath::Resolved(_, path), _, _) = pat.kind;
- if cx.typeck_results().pat_ty(pat) == cx.tcx.type_of(impl_id);
+ if cx.typeck_results().pat_ty(pat) == cx.tcx.type_of(impl_id).subst_identity();
then {
check_path(cx, path);
}
diff --git a/src/tools/clippy/clippy_lints/src/useless_conversion.rs b/src/tools/clippy/clippy_lints/src/useless_conversion.rs
index a95e7b613..fede625f7 100644
--- a/src/tools/clippy/clippy_lints/src/useless_conversion.rs
+++ b/src/tools/clippy/clippy_lints/src/useless_conversion.rs
@@ -161,7 +161,7 @@ impl<'tcx> LateLintPass<'tcx> for UselessConversion {
}
if_chain! {
- if Some(def_id) == cx.tcx.lang_items().from_fn();
+ if cx.tcx.is_diagnostic_item(sym::from_fn, def_id);
if same_type_and_consts(a, b);
then {
diff --git a/src/tools/clippy/clippy_lints/src/utils/author.rs b/src/tools/clippy/clippy_lints/src/utils/author.rs
index bd7daf077..c37e5bb67 100644
--- a/src/tools/clippy/clippy_lints/src/utils/author.rs
+++ b/src/tools/clippy/clippy_lints/src/utils/author.rs
@@ -588,7 +588,7 @@ impl<'a, 'tcx> PrintVisitor<'a, 'tcx> {
},
}
},
- ExprKind::Err => kind!("Err"),
+ ExprKind::Err(_) => kind!("Err"),
ExprKind::DropTemps(expr) => {
bind!(self, expr);
kind!("DropTemps({expr})");
diff --git a/src/tools/clippy/clippy_lints/src/utils/conf.rs b/src/tools/clippy/clippy_lints/src/utils/conf.rs
index 3e7d0028c..1c7f3e96d 100644
--- a/src/tools/clippy/clippy_lints/src/utils/conf.rs
+++ b/src/tools/clippy/clippy_lints/src/utils/conf.rs
@@ -219,7 +219,8 @@ define_Conf! {
///
/// #### Noteworthy
///
- /// A type, say `SomeType`, listed in this configuration has the same behavior of `["SomeType" , "*"], ["*", "SomeType"]` in `arithmetic_side_effects_allowed_binary`.
+ /// A type, say `SomeType`, listed in this configuration has the same behavior of
+ /// `["SomeType" , "*"], ["*", "SomeType"]` in `arithmetic_side_effects_allowed_binary`.
(arithmetic_side_effects_allowed: rustc_data_structures::fx::FxHashSet<String> = <_>::default()),
/// Lint: ARITHMETIC_SIDE_EFFECTS.
///
@@ -252,7 +253,7 @@ define_Conf! {
///
/// Suppress lints whenever the suggested change would cause breakage for other crates.
(avoid_breaking_exported_api: bool = true),
- /// 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, DEPRECATED_CFG_ATTR, INDEX_REFUTABLE_SLICE, MAP_CLONE, BORROW_AS_PTR, MANUAL_BITS, ERR_EXPECT, CAST_ABS_TO_UNSIGNED, UNINLINED_FORMAT_ARGS, MANUAL_CLAMP, MANUAL_LET_ELSE, UNCHECKED_DURATION_SUBTRACTION.
+ /// 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, DEPRECATED_CFG_ATTR, INDEX_REFUTABLE_SLICE, MAP_CLONE, BORROW_AS_PTR, MANUAL_BITS, ERR_EXPECT, CAST_ABS_TO_UNSIGNED, UNINLINED_FORMAT_ARGS, MANUAL_CLAMP, MANUAL_LET_ELSE, UNCHECKED_DURATION_SUBTRACTION, COLLAPSIBLE_STR_REPLACE, SEEK_FROM_CURRENT, SEEK_REWIND, UNNECESSARY_LAZY_EVALUATIONS, TRANSMUTE_PTR_TO_REF, ALMOST_COMPLETE_RANGE, NEEDLESS_BORROW, DERIVABLE_IMPLS, MANUAL_IS_ASCII_CHECK, MANUAL_REM_EUCLID, MANUAL_RETAIN.
///
/// The minimum rust version that the project supports
(msrv: Option<String> = None),
@@ -322,7 +323,7 @@ define_Conf! {
///
/// The maximum size (in bytes) to consider a `Copy` type for passing by value instead of by reference.
(trivial_copy_size_limit: Option<u64> = None),
- /// Lint: LARGE_TYPE_PASS_BY_MOVE.
+ /// Lint: LARGE_TYPES_PASSED_BY_VALUE.
///
/// The minimum size (in bytes) to consider a type for passing by reference instead of by value.
(pass_by_value_size_limit: u64 = 256),
@@ -410,7 +411,7 @@ define_Conf! {
/// the slice pattern that is suggested. If more elements would be necessary, the lint is suppressed.
/// For example, `[_, _, _, e, ..]` is a slice pattern with 4 elements.
(max_suggested_slice_pattern_length: u64 = 3),
- /// Lint: AWAIT_HOLDING_INVALID_TYPE
+ /// Lint: AWAIT_HOLDING_INVALID_TYPE.
(await_holding_invalid_types: Vec<crate::utils::conf::DisallowedPath> = Vec::new()),
/// Lint: LARGE_INCLUDE_FILE.
///
@@ -418,25 +419,25 @@ define_Conf! {
(max_include_file_size: u64 = 1_000_000),
/// Lint: EXPECT_USED.
///
- /// Whether `expect` should be allowed within `#[cfg(test)]`
+ /// Whether `expect` should be allowed in test functions or `#[cfg(test)]`
(allow_expect_in_tests: bool = false),
/// Lint: UNWRAP_USED.
///
- /// Whether `unwrap` should be allowed in test cfg
+ /// Whether `unwrap` should be allowed in test functions or `#[cfg(test)]`
(allow_unwrap_in_tests: bool = false),
/// Lint: DBG_MACRO.
///
- /// Whether `dbg!` should be allowed in test functions
+ /// Whether `dbg!` should be allowed in test functions or `#[cfg(test)]`
(allow_dbg_in_tests: bool = false),
/// Lint: PRINT_STDOUT, PRINT_STDERR.
///
- /// Whether print macros (ex. `println!`) should be allowed in test functions
+ /// Whether print macros (ex. `println!`) should be allowed in test functions or `#[cfg(test)]`
(allow_print_in_tests: bool = false),
/// Lint: RESULT_LARGE_ERR.
///
/// The maximum size of the `Err`-variant in a `Result` returned from a function
(large_error_threshold: u64 = 128),
- /// Lint: MUTABLE_KEY.
+ /// Lint: MUTABLE_KEY_TYPE.
///
/// A list of paths to types that should be treated like `Arc`, i.e. ignored but
/// for the generic parameters for determining interior mutability
@@ -445,7 +446,7 @@ define_Conf! {
///
/// Whether to allow mixed uninlined format args, e.g. `format!("{} {}", a, foo.bar)`
(allow_mixed_uninlined_format_args: bool = true),
- /// Lint: INDEXING_SLICING
+ /// Lint: INDEXING_SLICING.
///
/// Whether to suppress a restriction lint in constant code. In same
/// cases the restructured operation might not be unavoidable, as the
@@ -453,6 +454,11 @@ define_Conf! {
/// configuration will cause restriction lints to trigger even
/// if no suggestion can be made.
(suppress_restriction_lint_in_const: bool = false),
+ /// Lint: MISSING_DOCS_IN_PRIVATE_ITEMS.
+ ///
+ /// Whether to **only** check for missing documentation in items visible within the current
+ /// crate. For example, `pub(crate)` items.
+ (missing_docs_in_crate_items: bool = false),
}
/// Search for the configuration file.
diff --git a/src/tools/clippy/clippy_lints/src/utils/dump_hir.rs b/src/tools/clippy/clippy_lints/src/utils/dump_hir.rs
index 01efc527a..092041aec 100644
--- a/src/tools/clippy/clippy_lints/src/utils/dump_hir.rs
+++ b/src/tools/clippy/clippy_lints/src/utils/dump_hir.rs
@@ -1,4 +1,5 @@
use clippy_utils::get_attr;
+use hir::TraitItem;
use rustc_hir as hir;
use rustc_lint::{LateContext, LateLintPass, LintContext};
use rustc_session::{declare_lint_pass, declare_tool_lint};
@@ -47,6 +48,18 @@ impl<'tcx> LateLintPass<'tcx> for DumpHir {
println!("{stmt:#?}");
}
}
+
+ fn check_trait_item(&mut self, cx: &LateContext<'_>, item: &TraitItem<'_>) {
+ if has_attr(cx, item.hir_id()) {
+ println!("{item:#?}");
+ }
+ }
+
+ fn check_impl_item(&mut self, cx: &LateContext<'_>, item: &hir::ImplItem<'_>) {
+ if has_attr(cx, item.hir_id()) {
+ println!("{item:#?}");
+ }
+ }
}
fn has_attr(cx: &LateContext<'_>, hir_id: hir::HirId) -> bool {
diff --git a/src/tools/clippy/clippy_lints/src/utils/internal_lints/interning_defined_symbol.rs b/src/tools/clippy/clippy_lints/src/utils/internal_lints/interning_defined_symbol.rs
index 4b33d492a..688a8b865 100644
--- a/src/tools/clippy/clippy_lints/src/utils/internal_lints/interning_defined_symbol.rs
+++ b/src/tools/clippy/clippy_lints/src/utils/internal_lints/interning_defined_symbol.rs
@@ -78,7 +78,7 @@ impl<'tcx> LateLintPass<'tcx> for InterningDefinedSymbol {
for item in cx.tcx.module_children(def_id).iter() {
if_chain! {
if let Res::Def(DefKind::Const, item_def_id) = item.res;
- let ty = cx.tcx.type_of(item_def_id);
+ let ty = cx.tcx.type_of(item_def_id).subst_identity();
if match_type(cx, ty, &paths::SYMBOL);
if let Ok(ConstValue::Scalar(value)) = cx.tcx.const_eval_poly(item_def_id);
if let Ok(value) = value.to_u32();
diff --git a/src/tools/clippy/clippy_lints/src/utils/internal_lints/lint_without_lint_pass.rs b/src/tools/clippy/clippy_lints/src/utils/internal_lints/lint_without_lint_pass.rs
index 4c3b1b131..f71820765 100644
--- a/src/tools/clippy/clippy_lints/src/utils/internal_lints/lint_without_lint_pass.rs
+++ b/src/tools/clippy/clippy_lints/src/utils/internal_lints/lint_without_lint_pass.rs
@@ -215,14 +215,13 @@ impl<'tcx> LateLintPass<'tcx> for LintWithoutLintPass {
cx,
};
let body_id = cx.tcx.hir().body_owned_by(
- cx.tcx.hir().local_def_id(
- impl_item_refs
- .iter()
- .find(|iiref| iiref.ident.as_str() == "get_lints")
- .expect("LintPass needs to implement get_lints")
- .id
- .hir_id(),
- ),
+ impl_item_refs
+ .iter()
+ .find(|iiref| iiref.ident.as_str() == "get_lints")
+ .expect("LintPass needs to implement get_lints")
+ .id
+ .owner_id
+ .def_id,
);
collector.visit_expr(cx.tcx.hir().body(body_id).value);
}
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 c4d8c28f0..b1b5164ff 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
@@ -14,6 +14,7 @@ use clippy_utils::diagnostics::span_lint;
use clippy_utils::ty::{match_type, walk_ptrs_ty_depth};
use clippy_utils::{last_path_segment, match_def_path, match_function_call, match_path, paths};
use if_chain::if_chain;
+use itertools::Itertools;
use rustc_ast as ast;
use rustc_data_structures::fx::FxHashMap;
use rustc_hir::{
@@ -34,8 +35,10 @@ use std::path::Path;
use std::path::PathBuf;
use std::process::Command;
-/// This is the output file of the lint collector.
-const OUTPUT_FILE: &str = "../util/gh-pages/lints.json";
+/// This is the json output file of the lint collector.
+const JSON_OUTPUT_FILE: &str = "../util/gh-pages/lints.json";
+/// This is the markdown output file of the lint collector.
+const MARKDOWN_OUTPUT_FILE: &str = "../book/src/lint_configuration.md";
/// These lints are excluded from the export.
const BLACK_LISTED_LINTS: &[&str] = &["lint_author", "dump_hir", "internal_metadata_collector"];
/// These groups will be ignored by the lint group matcher. This is useful for collections like
@@ -176,6 +179,23 @@ This lint has the following configuration variables:
)
})
}
+
+ fn configs_to_markdown(&self, map_fn: fn(&ClippyConfiguration) -> String) -> String {
+ self.config
+ .iter()
+ .filter(|config| config.deprecation_reason.is_none())
+ .filter(|config| !config.lints.is_empty())
+ .map(map_fn)
+ .join("\n")
+ }
+
+ fn get_markdown_docs(&self) -> String {
+ format!(
+ "## Lint Configuration Options\n| <div style=\"width:290px\">Option</div> | Default Value |\n|--|--|\n{}\n\n{}\n",
+ self.configs_to_markdown(ClippyConfiguration::to_markdown_table_entry),
+ self.configs_to_markdown(ClippyConfiguration::to_markdown_paragraph),
+ )
+ }
}
impl Drop for MetadataCollector {
@@ -199,12 +219,37 @@ impl Drop for MetadataCollector {
collect_renames(&mut lints);
- // Outputting
- if Path::new(OUTPUT_FILE).exists() {
- fs::remove_file(OUTPUT_FILE).unwrap();
+ // Outputting json
+ if Path::new(JSON_OUTPUT_FILE).exists() {
+ fs::remove_file(JSON_OUTPUT_FILE).unwrap();
}
- let mut file = OpenOptions::new().write(true).create(true).open(OUTPUT_FILE).unwrap();
+ let mut file = OpenOptions::new()
+ .write(true)
+ .create(true)
+ .open(JSON_OUTPUT_FILE)
+ .unwrap();
writeln!(file, "{}", serde_json::to_string_pretty(&lints).unwrap()).unwrap();
+
+ // Outputting markdown
+ if Path::new(MARKDOWN_OUTPUT_FILE).exists() {
+ fs::remove_file(MARKDOWN_OUTPUT_FILE).unwrap();
+ }
+ let mut file = OpenOptions::new()
+ .write(true)
+ .create(true)
+ .open(MARKDOWN_OUTPUT_FILE)
+ .unwrap();
+ writeln!(
+ file,
+ "<!--
+This file is generated by `cargo collect-metadata`.
+Please use that command to update the file and do not edit it by hand.
+-->
+
+{}",
+ self.get_markdown_docs(),
+ )
+ .unwrap();
}
}
@@ -505,6 +550,28 @@ impl ClippyConfiguration {
deprecation_reason,
}
}
+
+ fn to_markdown_paragraph(&self) -> String {
+ format!(
+ "### {}\n{}\n\n**Default Value:** `{}` (`{}`)\n\n{}\n\n",
+ self.name,
+ self.doc
+ .lines()
+ .map(|line| line.strip_prefix(" ").unwrap_or(line))
+ .join("\n"),
+ self.default,
+ self.config_type,
+ self.lints
+ .iter()
+ .map(|name| name.to_string().split_whitespace().next().unwrap().to_string())
+ .map(|name| format!("* [{name}](https://rust-lang.github.io/rust-clippy/master/index.html#{name})"))
+ .join("\n"),
+ )
+ }
+
+ fn to_markdown_table_entry(&self) -> String {
+ format!("| [{}](#{}) | `{}` |", self.name, self.name, self.default)
+ }
}
fn collect_configs() -> Vec<ClippyConfiguration> {
diff --git a/src/tools/clippy/clippy_lints/src/utils/internal_lints/msrv_attr_impl.rs b/src/tools/clippy/clippy_lints/src/utils/internal_lints/msrv_attr_impl.rs
index 9876a8a76..09f0f0d0a 100644
--- a/src/tools/clippy/clippy_lints/src/utils/internal_lints/msrv_attr_impl.rs
+++ b/src/tools/clippy/clippy_lints/src/utils/internal_lints/msrv_attr_impl.rs
@@ -39,6 +39,7 @@ impl LateLintPass<'_> for MsrvAttrImpl {
if self_ty_def.all_fields().any(|f| {
cx.tcx
.type_of(f.did)
+ .subst_identity()
.walk()
.filter(|t| matches!(t.unpack(), GenericArgKind::Type(_)))
.any(|t| match_type(cx, t.expect_ty(), &paths::MSRV))
diff --git a/src/tools/clippy/clippy_lints/src/utils/internal_lints/unnecessary_def_path.rs b/src/tools/clippy/clippy_lints/src/utils/internal_lints/unnecessary_def_path.rs
index 714436363..b59ef4086 100644
--- a/src/tools/clippy/clippy_lints/src/utils/internal_lints/unnecessary_def_path.rs
+++ b/src/tools/clippy/clippy_lints/src/utils/internal_lints/unnecessary_def_path.rs
@@ -3,7 +3,7 @@ use clippy_utils::source::snippet_with_applicability;
use clippy_utils::{def_path_def_ids, is_lint_allowed, match_any_def_paths, peel_hir_expr_refs};
use if_chain::if_chain;
use rustc_ast::ast::LitKind;
-use rustc_data_structures::fx::FxHashSet;
+use rustc_data_structures::fx::{FxHashSet, FxIndexSet};
use rustc_errors::Applicability;
use rustc_hir as hir;
use rustc_hir::def::{DefKind, Res};
@@ -44,7 +44,7 @@ impl_lint_pass!(UnnecessaryDefPath => [UNNECESSARY_DEF_PATH]);
#[derive(Default)]
pub struct UnnecessaryDefPath {
- array_def_ids: FxHashSet<(DefId, Span)>,
+ array_def_ids: FxIndexSet<(DefId, Span)>,
linted_def_ids: FxHashSet<DefId>,
}
@@ -229,11 +229,11 @@ fn path_to_matched_type(cx: &LateContext<'_>, expr: &hir::Expr<'_>) -> Option<Ve
Res::Def(DefKind::Static(_), def_id) => read_mir_alloc_def_path(
cx,
cx.tcx.eval_static_initializer(def_id).ok()?.inner(),
- cx.tcx.type_of(def_id),
+ cx.tcx.type_of(def_id).subst_identity(),
),
Res::Def(DefKind::Const, def_id) => match cx.tcx.const_eval_poly(def_id).ok()? {
ConstValue::ByRef { alloc, offset } if offset.bytes() == 0 => {
- read_mir_alloc_def_path(cx, alloc.inner(), cx.tcx.type_of(def_id))
+ read_mir_alloc_def_path(cx, alloc.inner(), cx.tcx.type_of(def_id).subst_identity())
},
_ => None,
},
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 6cf2a955f..93e4b023c 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
@@ -5,7 +5,7 @@ use rustc_hir::{self as hir, HirId, ItemKind, Node};
use rustc_hir_analysis::hir_ty_to_ty;
use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::ty::layout::LayoutOf as _;
-use rustc_middle::ty::{Adt, Ty, TypeVisitable};
+use rustc_middle::ty::{Adt, Ty, TypeVisitableExt};
use rustc_session::{declare_lint_pass, declare_tool_lint};
use rustc_span::sym;
diff --git a/src/tools/clippy/clippy_utils/Cargo.toml b/src/tools/clippy/clippy_utils/Cargo.toml
index ac6a566b9..173469f6c 100644
--- a/src/tools/clippy/clippy_utils/Cargo.toml
+++ b/src/tools/clippy/clippy_utils/Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "clippy_utils"
-version = "0.1.68"
+version = "0.1.69"
edition = "2021"
publish = false
diff --git a/src/tools/clippy/clippy_utils/src/ast_utils.rs b/src/tools/clippy/clippy_utils/src/ast_utils.rs
index 9d0263e93..d82098523 100644
--- a/src/tools/clippy/clippy_utils/src/ast_utils.rs
+++ b/src/tools/clippy/clippy_utils/src/ast_utils.rs
@@ -144,7 +144,8 @@ pub fn eq_expr(l: &Expr, r: &Expr) -> bool {
(_, Paren(r)) => eq_expr(l, r),
(Err, Err) => true,
(Box(l), Box(r)) | (Try(l), Try(r)) | (Await(l), Await(r)) => eq_expr(l, r),
- (Array(l), Array(r)) | (Tup(l), Tup(r)) => over(l, r, |l, r| eq_expr(l, r)),
+ (Array(l), Array(r)) => over(l, r, |l, r| eq_expr(l, r)),
+ (Tup(l), Tup(r)) => over(l, r, |l, r| eq_expr(l, r)),
(Repeat(le, ls), Repeat(re, rs)) => eq_expr(le, re) && eq_expr(&ls.value, &rs.value),
(Call(lc, la), Call(rc, ra)) => eq_expr(lc, rc) && over(la, ra, |l, r| eq_expr(l, r)),
(
diff --git a/src/tools/clippy/clippy_utils/src/consts.rs b/src/tools/clippy/clippy_utils/src/consts.rs
index a67bd8d46..bb8890dca 100644
--- a/src/tools/clippy/clippy_utils/src/consts.rs
+++ b/src/tools/clippy/clippy_utils/src/consts.rs
@@ -237,7 +237,7 @@ pub fn constant<'tcx>(
typeck_results,
param_env: lcx.param_env,
needed_resolution: false,
- substs: lcx.tcx.intern_substs(&[]),
+ substs: ty::List::empty(),
};
cx.expr(e).map(|cst| (cst, cx.needed_resolution))
}
@@ -306,7 +306,7 @@ pub fn constant_context<'a, 'tcx>(
typeck_results,
param_env: lcx.param_env,
needed_resolution: false,
- substs: lcx.tcx.intern_substs(&[]),
+ substs: ty::List::empty(),
}
}
@@ -335,7 +335,7 @@ impl<'a, 'tcx> ConstEvalLateContext<'a, 'tcx> {
ExprKind::Tup(tup) => self.multi(tup).map(Constant::Tuple),
ExprKind::Repeat(value, _) => {
let n = match self.typeck_results.expr_ty(e).kind() {
- ty::Array(_, n) => n.try_eval_usize(self.lcx.tcx, self.lcx.param_env)?,
+ ty::Array(_, n) => n.try_eval_target_usize(self.lcx.tcx, self.lcx.param_env)?,
_ => span_bug!(e.span, "typeck error"),
};
self.expr(value).map(|v| Constant::Repeat(Box::new(v), n))
@@ -640,7 +640,7 @@ pub fn miri_to_const<'tcx>(tcx: TyCtxt<'tcx>, result: mir::ConstantKind<'tcx>) -
},
mir::ConstantKind::Val(ConstValue::ByRef { alloc, offset: _ }, _) => match result.ty().kind() {
ty::Array(sub_type, len) => match sub_type.kind() {
- ty::Float(FloatTy::F32) => match len.kind().try_to_machine_usize(tcx) {
+ ty::Float(FloatTy::F32) => match len.kind().try_to_target_usize(tcx) {
Some(len) => alloc
.inner()
.inspect_with_uninit_and_ptr_outside_interpreter(0..(4 * usize::try_from(len).unwrap()))
@@ -651,7 +651,7 @@ pub fn miri_to_const<'tcx>(tcx: TyCtxt<'tcx>, result: mir::ConstantKind<'tcx>) -
.map(Constant::Vec),
_ => None,
},
- ty::Float(FloatTy::F64) => match len.kind().try_to_machine_usize(tcx) {
+ ty::Float(FloatTy::F64) => match len.kind().try_to_target_usize(tcx) {
Some(len) => alloc
.inner()
.inspect_with_uninit_and_ptr_outside_interpreter(0..(8 * usize::try_from(len).unwrap()))
diff --git a/src/tools/clippy/clippy_utils/src/eager_or_lazy.rs b/src/tools/clippy/clippy_utils/src/eager_or_lazy.rs
index 967119369..ee2f816f1 100644
--- a/src/tools/clippy/clippy_utils/src/eager_or_lazy.rs
+++ b/src/tools/clippy/clippy_utils/src/eager_or_lazy.rs
@@ -50,7 +50,7 @@ fn fn_eagerness(cx: &LateContext<'_>, fn_id: DefId, name: Symbol, have_one_arg:
let name = name.as_str();
let ty = match cx.tcx.impl_of_method(fn_id) {
- Some(id) => cx.tcx.type_of(id),
+ Some(id) => cx.tcx.type_of(id).subst_identity(),
None => return Lazy,
};
@@ -71,7 +71,7 @@ fn fn_eagerness(cx: &LateContext<'_>, fn_id: DefId, name: Symbol, have_one_arg:
.variants()
.iter()
.flat_map(|v| v.fields.iter())
- .any(|x| matches!(cx.tcx.type_of(x.did).peel_refs().kind(), ty::Param(_)))
+ .any(|x| matches!(cx.tcx.type_of(x.did).subst_identity().peel_refs().kind(), ty::Param(_)))
&& all_predicates_of(cx.tcx, fn_id).all(|(pred, _)| match pred.kind().skip_binder() {
PredicateKind::Clause(ty::Clause::Trait(pred)) => cx.tcx.trait_def(pred.trait_ref.def_id).is_marker,
_ => true,
@@ -79,7 +79,7 @@ fn fn_eagerness(cx: &LateContext<'_>, fn_id: DefId, name: Symbol, have_one_arg:
&& subs.types().all(|x| matches!(x.peel_refs().kind(), ty::Param(_)))
{
// Limit the function to either `(self) -> bool` or `(&self) -> bool`
- match &**cx.tcx.fn_sig(fn_id).skip_binder().inputs_and_output {
+ match &**cx.tcx.fn_sig(fn_id).subst_identity().skip_binder().inputs_and_output {
[arg, res] if !arg.is_mutable_ptr() && arg.peel_refs() == ty && res.is_bool() => NoChange,
_ => Lazy,
}
@@ -193,7 +193,7 @@ fn expr_eagerness<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) -> EagernessS
| ExprKind::Ret(_)
| ExprKind::InlineAsm(_)
| ExprKind::Yield(..)
- | ExprKind::Err => {
+ | ExprKind::Err(_) => {
self.eagerness = ForceNoChange;
return;
},
diff --git a/src/tools/clippy/clippy_utils/src/higher.rs b/src/tools/clippy/clippy_utils/src/higher.rs
index 4604ae5c2..50bef3709 100644
--- a/src/tools/clippy/clippy_utils/src/higher.rs
+++ b/src/tools/clippy/clippy_utils/src/higher.rs
@@ -287,15 +287,12 @@ impl<'a> VecArgs<'a> {
Some(VecArgs::Repeat(&args[0], &args[1]))
} else if match_def_path(cx, fun_def_id, &paths::SLICE_INTO_VEC) && args.len() == 1 {
// `vec![a, b, c]` case
- if_chain! {
- if let hir::ExprKind::Box(boxed) = args[0].kind;
- if let hir::ExprKind::Array(args) = boxed.kind;
- then {
- return Some(VecArgs::Vec(args));
- }
+ if let hir::ExprKind::Call(_, [arg]) = &args[0].kind
+ && let hir::ExprKind::Array(args) = arg.kind {
+ Some(VecArgs::Vec(args))
+ } else {
+ None
}
-
- None
} else if match_def_path(cx, fun_def_id, &paths::VEC_NEW) && args.is_empty() {
Some(VecArgs::Vec(&[]))
} else {
diff --git a/src/tools/clippy/clippy_utils/src/hir_utils.rs b/src/tools/clippy/clippy_utils/src/hir_utils.rs
index 2bbe1a19b..0603755f8 100644
--- a/src/tools/clippy/clippy_utils/src/hir_utils.rs
+++ b/src/tools/clippy/clippy_utils/src/hir_utils.rs
@@ -714,7 +714,7 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
}
self.hash_pat(pat);
},
- ExprKind::Err => {},
+ ExprKind::Err(_) => {},
ExprKind::Lit(ref l) => {
l.node.hash(&mut self.s);
},
@@ -986,7 +986,7 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
TyKind::Typeof(anon_const) => {
self.hash_body(anon_const.body);
},
- TyKind::Err | TyKind::Infer | TyKind::Never => {},
+ TyKind::Err(_) | TyKind::Infer | TyKind::Never => {},
}
}
diff --git a/src/tools/clippy/clippy_utils/src/lib.rs b/src/tools/clippy/clippy_utils/src/lib.rs
index 7a4a9036d..f02f8ecb4 100644
--- a/src/tools/clippy/clippy_utils/src/lib.rs
+++ b/src/tools/clippy/clippy_utils/src/lib.rs
@@ -1,6 +1,5 @@
#![feature(array_chunks)]
#![feature(box_patterns)]
-#![feature(control_flow_enum)]
#![feature(let_chains)]
#![feature(lint_reasons)]
#![feature(never_type)]
@@ -105,7 +104,7 @@ use rustc_middle::ty::fast_reject::SimplifiedType::{
PtrSimplifiedType, SliceSimplifiedType, StrSimplifiedType, UintSimplifiedType,
};
use rustc_middle::ty::{
- layout::IntegerExt, BorrowKind, ClosureKind, DefIdTree, Ty, TyCtxt, TypeAndMut, TypeVisitable, UpvarCapture,
+ layout::IntegerExt, BorrowKind, ClosureKind, DefIdTree, Ty, TyCtxt, TypeAndMut, TypeVisitableExt, UpvarCapture,
};
use rustc_middle::ty::{FloatTy, IntTy, UintTy};
use rustc_span::hygiene::{ExpnKind, MacroKind};
@@ -318,7 +317,7 @@ pub fn match_trait_method(cx: &LateContext<'_>, expr: &Expr<'_>, path: &[&str])
/// Checks if a method is defined in an impl of a diagnostic item
pub fn is_diag_item_method(cx: &LateContext<'_>, def_id: DefId, diag_item: Symbol) -> bool {
if let Some(impl_did) = cx.tcx.impl_of_method(def_id) {
- if let Some(adt) = cx.tcx.type_of(impl_did).ty_adt_def() {
+ if let Some(adt) = cx.tcx.type_of(impl_did).subst_identity().ty_adt_def() {
return cx.tcx.is_diagnostic_item(diag_item, adt.did());
}
}
@@ -553,7 +552,7 @@ fn non_local_item_children_by_name(tcx: TyCtxt<'_>, def_id: DefId, name: Symbol)
.filter(|item| item.ident.name == name)
.map(|child| child.res.expect_non_local())
.collect(),
- DefKind::Impl => tcx
+ DefKind::Impl { .. } => tcx
.associated_item_def_ids(def_id)
.iter()
.copied()
@@ -813,7 +812,7 @@ fn is_default_equivalent_ctor(cx: &LateContext<'_>, def_id: DefId, path: &QPath<
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() {
+ if let Some(adt) = cx.tcx.type_of(impl_did).subst_identity().ty_adt_def() {
return std_types_symbols.iter().any(|&symbol| {
cx.tcx.is_diagnostic_item(symbol, adt.did()) || Some(adt.did()) == cx.tcx.lang_items().string()
});
@@ -1119,9 +1118,8 @@ pub fn can_move_expr_to_closure<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'
self.captures.entry(l).and_modify(|e| *e |= cap).or_insert(cap);
}
},
- ExprKind::Closure { .. } => {
- let closure_id = self.cx.tcx.hir().local_def_id(e.hir_id);
- for capture in self.cx.typeck_results().closure_min_captures_flattened(closure_id) {
+ ExprKind::Closure(closure) => {
+ for capture in self.cx.typeck_results().closure_min_captures_flattened(closure.def_id) {
let local_id = match capture.place.base {
PlaceBase::Local(id) => id,
PlaceBase::Upvar(var) => var.var_path.hir_id,
@@ -1379,7 +1377,7 @@ pub fn get_enclosing_loop_or_multi_call_closure<'tcx>(
.chain(args.iter())
.position(|arg| arg.hir_id == id)?;
let id = cx.typeck_results().type_dependent_def_id(e.hir_id)?;
- let ty = cx.tcx.fn_sig(id).skip_binder().inputs()[i];
+ let ty = cx.tcx.fn_sig(id).subst_identity().skip_binder().inputs()[i];
ty_is_fn_once_param(cx.tcx, ty, cx.tcx.param_env(id).caller_bounds()).then_some(())
},
_ => None,
@@ -1578,16 +1576,14 @@ pub fn is_direct_expn_of(span: Span, name: &str) -> Option<Span> {
}
/// Convenience function to get the return type of a function.
-pub fn return_ty<'tcx>(cx: &LateContext<'tcx>, fn_item: hir::HirId) -> Ty<'tcx> {
- let fn_def_id = cx.tcx.hir().local_def_id(fn_item);
- let ret_ty = cx.tcx.fn_sig(fn_def_id).output();
+pub fn return_ty<'tcx>(cx: &LateContext<'tcx>, fn_def_id: hir::OwnerId) -> Ty<'tcx> {
+ let ret_ty = cx.tcx.fn_sig(fn_def_id).subst_identity().output();
cx.tcx.erase_late_bound_regions(ret_ty)
}
/// Convenience function to get the nth argument type of a function.
-pub fn nth_arg<'tcx>(cx: &LateContext<'tcx>, fn_item: hir::HirId, nth: usize) -> Ty<'tcx> {
- let fn_def_id = cx.tcx.hir().local_def_id(fn_item);
- let arg = cx.tcx.fn_sig(fn_def_id).input(nth);
+pub fn nth_arg<'tcx>(cx: &LateContext<'tcx>, fn_def_id: hir::OwnerId, nth: usize) -> Ty<'tcx> {
+ let arg = cx.tcx.fn_sig(fn_def_id).subst_identity().input(nth);
cx.tcx.erase_late_bound_regions(arg)
}
@@ -2491,6 +2487,10 @@ pub fn span_extract_comment(sm: &SourceMap, span: Span) -> String {
comments_buf.join("\n")
}
+pub fn span_find_starting_semi(sm: &SourceMap, span: Span) -> Span {
+ sm.span_take_while(span, |&ch| ch == ' ' || ch == ';')
+}
+
macro_rules! op_utils {
($($name:ident $assign:ident)*) => {
/// Binary operation traits like `LangItem::Add`
diff --git a/src/tools/clippy/clippy_utils/src/macros.rs b/src/tools/clippy/clippy_utils/src/macros.rs
index 77c5f1155..be6133d32 100644
--- a/src/tools/clippy/clippy_utils/src/macros.rs
+++ b/src/tools/clippy/clippy_utils/src/macros.rs
@@ -1,6 +1,5 @@
#![allow(clippy::similar_names)] // `expr` and `expn`
-use crate::is_path_diagnostic_item;
use crate::source::snippet_opt;
use crate::visitors::{for_each_expr, Descend};
@@ -8,7 +7,7 @@ use arrayvec::ArrayVec;
use itertools::{izip, Either, Itertools};
use rustc_ast::ast::LitKind;
use rustc_hir::intravisit::{walk_expr, Visitor};
-use rustc_hir::{self as hir, Expr, ExprField, ExprKind, HirId, Node, QPath};
+use rustc_hir::{self as hir, Expr, ExprField, ExprKind, HirId, LangItem, Node, QPath, TyKind};
use rustc_lexer::unescape::unescape_literal;
use rustc_lexer::{tokenize, unescape, LiteralKind, TokenKind};
use rustc_lint::LateContext;
@@ -328,7 +327,7 @@ fn is_assert_arg(cx: &LateContext<'_>, expr: &Expr<'_>, assert_expn: ExpnId) ->
} else {
match cx.tcx.item_name(macro_call.def_id) {
// `cfg!(debug_assertions)` in `debug_assert!`
- sym::cfg => ControlFlow::CONTINUE,
+ sym::cfg => ControlFlow::Continue(()),
// assert!(other_macro!(..))
_ => ControlFlow::Break(true),
}
@@ -392,11 +391,18 @@ impl FormatString {
};
let mut unescaped = String::with_capacity(inner.len());
+ // Sometimes the original string comes from a macro which accepts a malformed string, such as in a
+ // #[display(""somestring)] attribute (accepted by the `displaythis` crate). Reconstructing the
+ // string from the span will not be possible, so we will just return None here.
+ let mut unparsable = false;
unescape_literal(inner, mode, &mut |_, ch| match ch {
Ok(ch) => unescaped.push(ch),
Err(e) if !e.is_fatal() => (),
- Err(e) => panic!("{e:?}"),
+ Err(_) => unparsable = true,
});
+ if unparsable {
+ return None;
+ }
let mut parts = Vec::new();
let _: Option<!> = for_each_expr(pieces, |expr| {
@@ -439,8 +445,7 @@ impl<'tcx> FormatArgsValues<'tcx> {
// ArgumentV1::from_usize(<val>)
if let ExprKind::Call(callee, [val]) = expr.kind
&& let ExprKind::Path(QPath::TypeRelative(ty, _)) = callee.kind
- && let hir::TyKind::Path(QPath::Resolved(_, path)) = ty.kind
- && path.segments.last().unwrap().ident.name == sym::ArgumentV1
+ && let TyKind::Path(QPath::LangItem(LangItem::FormatArgument, _, _)) = ty.kind
{
let val_idx = if val.span.ctxt() == expr.span.ctxt()
&& let ExprKind::Field(_, field) = val.kind
@@ -486,20 +491,6 @@ struct ParamPosition {
impl<'tcx> Visitor<'tcx> for ParamPosition {
fn visit_expr_field(&mut self, field: &'tcx ExprField<'tcx>) {
- fn parse_count(expr: &Expr<'_>) -> Option<usize> {
- // ::core::fmt::rt::v1::Count::Param(1usize),
- if let ExprKind::Call(ctor, [val]) = expr.kind
- && let ExprKind::Path(QPath::Resolved(_, path)) = ctor.kind
- && path.segments.last()?.ident.name == sym::Param
- && let ExprKind::Lit(lit) = &val.kind
- && let LitKind::Int(pos, _) = lit.node
- {
- Some(pos as usize)
- } else {
- None
- }
- }
-
match field.ident.name {
sym::position => {
if let ExprKind::Lit(lit) = &field.expr.kind
@@ -519,15 +510,41 @@ impl<'tcx> Visitor<'tcx> for ParamPosition {
}
}
+fn parse_count(expr: &Expr<'_>) -> Option<usize> {
+ // <::core::fmt::rt::v1::Count>::Param(1usize),
+ if let ExprKind::Call(ctor, [val]) = expr.kind
+ && let ExprKind::Path(QPath::TypeRelative(_, path)) = ctor.kind
+ && path.ident.name == sym::Param
+ && let ExprKind::Lit(lit) = &val.kind
+ && let LitKind::Int(pos, _) = lit.node
+ {
+ Some(pos as usize)
+ } else {
+ None
+ }
+}
+
/// Parses the `fmt` arg of `Arguments::new_v1_formatted(pieces, args, fmt, _)`
fn parse_rt_fmt<'tcx>(fmt_arg: &'tcx Expr<'tcx>) -> Option<impl Iterator<Item = ParamPosition> + 'tcx> {
if let ExprKind::AddrOf(.., array) = fmt_arg.kind
&& let ExprKind::Array(specs) = array.kind
{
Some(specs.iter().map(|spec| {
- let mut position = ParamPosition::default();
- position.visit_expr(spec);
- position
+ if let ExprKind::Call(f, args) = spec.kind
+ && let ExprKind::Path(QPath::TypeRelative(ty, f)) = f.kind
+ && let TyKind::Path(QPath::LangItem(LangItem::FormatPlaceholder, _, _)) = ty.kind
+ && f.ident.name == sym::new
+ && let [position, _fill, _align, _flags, precision, width] = args
+ && let ExprKind::Lit(position) = &position.kind
+ && let LitKind::Int(position, _) = position.node {
+ ParamPosition {
+ value: position as usize,
+ width: parse_count(width),
+ precision: parse_count(precision),
+ }
+ } else {
+ ParamPosition::default()
+ }
}))
} else {
None
@@ -701,8 +718,8 @@ pub struct FormatSpec<'tcx> {
pub fill: Option<char>,
/// Optionally specified alignment.
pub align: Alignment,
- /// Packed version of various flags provided, see [`rustc_parse_format::Flag`].
- pub flags: u32,
+ /// Whether all flag options are set to default (no flags specified).
+ pub no_flags: bool,
/// Represents either the maximum width or the integer precision.
pub precision: Count<'tcx>,
/// The minimum width, will be padded according to `width`/`align`
@@ -718,7 +735,7 @@ impl<'tcx> FormatSpec<'tcx> {
Some(Self {
fill: spec.fill,
align: spec.align,
- flags: spec.flags,
+ no_flags: spec.sign.is_none() && !spec.alternate && !spec.zero_pad && spec.debug_hex.is_none(),
precision: Count::new(
FormatParamUsage::Precision,
spec.precision,
@@ -760,10 +777,7 @@ impl<'tcx> FormatSpec<'tcx> {
/// Has no other formatting specifiers than setting the format trait. returns true for `{}`,
/// `{foo}`, `{:?}`, but false for `{foo:5}`, `{3:.5?}`
pub fn is_default_for_trait(&self) -> bool {
- self.width.is_implied()
- && self.precision.is_implied()
- && self.align == Alignment::AlignUnknown
- && self.flags == 0
+ self.width.is_implied() && self.precision.is_implied() && self.align == Alignment::AlignUnknown && self.no_flags
}
}
@@ -890,7 +904,7 @@ impl<'tcx> FormatArgsExpn<'tcx> {
// ::core::fmt::Arguments::new_v1_formatted(pieces, args, fmt, _unsafe_arg)
if let ExprKind::Call(callee, [pieces, args, rest @ ..]) = expr.kind
&& let ExprKind::Path(QPath::TypeRelative(ty, seg)) = callee.kind
- && is_path_diagnostic_item(cx, ty, sym::Arguments)
+ && let TyKind::Path(QPath::LangItem(LangItem::FormatArguments, _, _)) = ty.kind
&& matches!(seg.ident.as_str(), "new_v1" | "new_v1_formatted")
{
let format_string = FormatString::new(cx, pieces)?;
diff --git a/src/tools/clippy/clippy_utils/src/mir/possible_borrower.rs b/src/tools/clippy/clippy_utils/src/mir/possible_borrower.rs
index 9adae7733..920ce8e65 100644
--- a/src/tools/clippy/clippy_utils/src/mir/possible_borrower.rs
+++ b/src/tools/clippy/clippy_utils/src/mir/possible_borrower.rs
@@ -4,7 +4,7 @@ use rustc_data_structures::fx::FxHashMap;
use rustc_index::bit_set::{BitSet, HybridBitSet};
use rustc_lint::LateContext;
use rustc_middle::mir::{self, visit::Visitor as _, Mutability};
-use rustc_middle::ty::{self, visit::TypeVisitor};
+use rustc_middle::ty::{self, visit::TypeVisitor, TyCtxt};
use rustc_mir_dataflow::{impls::MaybeStorageLive, Analysis, ResultsCursor};
use std::borrow::Cow;
use std::ops::ControlFlow;
@@ -136,11 +136,11 @@ impl<'a, 'b, 'tcx> mir::visit::Visitor<'tcx> for PossibleBorrowerVisitor<'a, 'b,
struct ContainsRegion;
-impl TypeVisitor<'_> for ContainsRegion {
+impl TypeVisitor<TyCtxt<'_>> for ContainsRegion {
type BreakTy = ();
fn visit_region(&mut self, _: ty::Region<'_>) -> ControlFlow<Self::BreakTy> {
- ControlFlow::BREAK
+ ControlFlow::Break(())
}
}
diff --git a/src/tools/clippy/clippy_utils/src/numeric_literal.rs b/src/tools/clippy/clippy_utils/src/numeric_literal.rs
index 42bdfd482..c225398ad 100644
--- a/src/tools/clippy/clippy_utils/src/numeric_literal.rs
+++ b/src/tools/clippy/clippy_utils/src/numeric_literal.rs
@@ -186,7 +186,7 @@ impl<'a> NumericLiteral<'a> {
// The exponent may have a sign, output it early, otherwise it will be
// treated as a digit
if digits.clone().next() == Some('-') {
- let _ = digits.next();
+ let _: Option<char> = digits.next();
output.push('-');
}
diff --git a/src/tools/clippy/clippy_utils/src/paths.rs b/src/tools/clippy/clippy_utils/src/paths.rs
index 95eebab75..4aae0f728 100644
--- a/src/tools/clippy/clippy_utils/src/paths.rs
+++ b/src/tools/clippy/clippy_utils/src/paths.rs
@@ -115,6 +115,7 @@ pub const STD_FS_CREATE_DIR: [&str; 3] = ["std", "fs", "create_dir"];
pub const STD_IO_SEEK: [&str; 3] = ["std", "io", "Seek"];
pub const STD_IO_SEEK_FROM_CURRENT: [&str; 4] = ["std", "io", "SeekFrom", "Current"];
pub const STD_IO_SEEKFROM_START: [&str; 4] = ["std", "io", "SeekFrom", "Start"];
+pub const STD_PROCESS_COMMAND: [&str; 3] = ["std", "process", "Command"];
pub const STRING_AS_MUT_STR: [&str; 4] = ["alloc", "string", "String", "as_mut_str"];
pub const STRING_AS_STR: [&str; 4] = ["alloc", "string", "String", "as_str"];
pub const STRING_NEW: [&str; 4] = ["alloc", "string", "String", "new"];
diff --git a/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs b/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs
index e5d7da682..1a35fe050 100644
--- a/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs
+++ b/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs
@@ -30,12 +30,14 @@ pub fn is_min_const_fn<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>, msrv: &Msrv)
ty::Clause::RegionOutlives(_)
| ty::Clause::TypeOutlives(_)
| ty::Clause::Projection(_)
- | ty::Clause::Trait(..),
+ | ty::Clause::Trait(..)
+ | ty::Clause::ConstArgHasType(..),
)
| ty::PredicateKind::WellFormed(_)
| ty::PredicateKind::ConstEvaluatable(..)
| ty::PredicateKind::ConstEquate(..)
| ty::PredicateKind::TypeWellFormedFromEnv(..) => continue,
+ ty::PredicateKind::AliasEq(..) => panic!("alias eq predicate on function: {predicate:#?}"),
ty::PredicateKind::ObjectSafe(_) => panic!("object safe predicate on function: {predicate:#?}"),
ty::PredicateKind::ClosureKind(..) => panic!("closure kind predicate on function: {predicate:#?}"),
ty::PredicateKind::Subtype(_) => panic!("subtype predicate on function: {predicate:#?}"),
@@ -55,7 +57,7 @@ pub fn is_min_const_fn<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>, msrv: &Msrv)
// impl trait is gone in MIR, so check the return type manually
check_ty(
tcx,
- tcx.fn_sig(def_id).output().skip_binder(),
+ tcx.fn_sig(def_id).subst_identity().output().skip_binder(),
body.local_decls.iter().next().unwrap().source_info.span,
)?;
@@ -240,6 +242,7 @@ fn check_statement<'tcx>(
| StatementKind::Retag { .. }
| StatementKind::AscribeUserType(..)
| StatementKind::Coverage(..)
+ | StatementKind::ConstEvalCounter
| StatementKind::Nop => Ok(()),
}
}
diff --git a/src/tools/clippy/clippy_utils/src/sugg.rs b/src/tools/clippy/clippy_utils/src/sugg.rs
index e7879bb19..07feadca2 100644
--- a/src/tools/clippy/clippy_utils/src/sugg.rs
+++ b/src/tools/clippy/clippy_utils/src/sugg.rs
@@ -20,7 +20,7 @@ use rustc_middle::mir::{FakeReadCause, Mutability};
use rustc_middle::ty;
use rustc_span::source_map::{BytePos, CharPos, Pos, Span, SyntaxContext};
use std::borrow::Cow;
-use std::fmt::{Display, Write as _};
+use std::fmt::{self, Display, Write as _};
use std::ops::{Add, Neg, Not, Sub};
/// A helper type to build suggestion correctly handling parentheses.
@@ -157,7 +157,7 @@ impl<'a> Sugg<'a> {
| hir::ExprKind::Ret(..)
| hir::ExprKind::Struct(..)
| hir::ExprKind::Tup(..)
- | hir::ExprKind::Err => Sugg::NonParen(get_snippet(expr.span)),
+ | hir::ExprKind::Err(_) => Sugg::NonParen(get_snippet(expr.span)),
hir::ExprKind::DropTemps(inner) => Self::hir_from_snippet(inner, get_snippet),
hir::ExprKind::Assign(lhs, rhs, _) => {
Sugg::BinOp(AssocOp::Assign, get_snippet(lhs.span), get_snippet(rhs.span))
@@ -219,6 +219,7 @@ impl<'a> Sugg<'a> {
| ast::ExprKind::Repeat(..)
| ast::ExprKind::Ret(..)
| ast::ExprKind::Yeet(..)
+ | ast::ExprKind::FormatArgs(..)
| ast::ExprKind::Struct(..)
| ast::ExprKind::Try(..)
| ast::ExprKind::TryBlock(..)
@@ -808,7 +809,10 @@ pub struct DerefClosure {
///
/// note: this only works on single line immutable closures with exactly one input parameter.
pub fn deref_closure_args(cx: &LateContext<'_>, closure: &hir::Expr<'_>) -> Option<DerefClosure> {
- if let hir::ExprKind::Closure(&Closure { fn_decl, body, .. }) = closure.kind {
+ if let hir::ExprKind::Closure(&Closure {
+ fn_decl, def_id, body, ..
+ }) = closure.kind
+ {
let closure_body = cx.tcx.hir().body(body);
// is closure arg a type annotated double reference (i.e.: `|x: &&i32| ...`)
// a type annotation is present if param `kind` is different from `TyKind::Infer`
@@ -828,10 +832,8 @@ pub fn deref_closure_args(cx: &LateContext<'_>, closure: &hir::Expr<'_>) -> Opti
applicability: Applicability::MachineApplicable,
};
- let fn_def_id = cx.tcx.hir().local_def_id(closure.hir_id);
let infcx = cx.tcx.infer_ctxt().build();
- ExprUseVisitor::new(&mut visitor, &infcx, fn_def_id, cx.param_env, cx.typeck_results())
- .consume_body(closure_body);
+ ExprUseVisitor::new(&mut visitor, &infcx, def_id, cx.param_env, cx.typeck_results()).consume_body(closure_body);
if !visitor.suggestion_start.is_empty() {
return Some(DerefClosure {
@@ -884,7 +886,7 @@ impl<'tcx> DerefDelegate<'_, 'tcx> {
.cx
.typeck_results()
.type_dependent_def_id(parent_expr.hir_id)
- .map(|did| self.cx.tcx.fn_sig(did).skip_binder())
+ .map(|did| self.cx.tcx.fn_sig(did).subst_identity().skip_binder())
{
std::iter::once(receiver)
.chain(call_args.iter())
@@ -930,7 +932,7 @@ impl<'tcx> Delegate<'tcx> for DerefDelegate<'_, 'tcx> {
if cmt.place.projections.is_empty() {
// handle item without any projection, that needs an explicit borrowing
// i.e.: suggest `&x` instead of `x`
- let _ = write!(self.suggestion_start, "{start_snip}&{ident_str}");
+ let _: fmt::Result = write!(self.suggestion_start, "{start_snip}&{ident_str}");
} else {
// cases where a parent `Call` or `MethodCall` is using the item
// i.e.: suggest `.contains(&x)` for `.find(|x| [1, 2, 3].contains(x)).is_none()`
@@ -945,7 +947,7 @@ impl<'tcx> Delegate<'tcx> for DerefDelegate<'_, 'tcx> {
// given expression is the self argument and will be handled completely by the compiler
// i.e.: `|x| x.is_something()`
ExprKind::MethodCall(_, self_expr, ..) if self_expr.hir_id == cmt.hir_id => {
- let _ = write!(self.suggestion_start, "{start_snip}{ident_str_with_proj}");
+ let _: fmt::Result = write!(self.suggestion_start, "{start_snip}{ident_str_with_proj}");
self.next_pos = span.hi();
return;
},
@@ -1053,7 +1055,7 @@ impl<'tcx> Delegate<'tcx> for DerefDelegate<'_, 'tcx> {
}
}
- let _ = write!(self.suggestion_start, "{start_snip}{replacement_str}");
+ let _: fmt::Result = write!(self.suggestion_start, "{start_snip}{replacement_str}");
}
self.next_pos = span.hi();
}
diff --git a/src/tools/clippy/clippy_utils/src/ty.rs b/src/tools/clippy/clippy_utils/src/ty.rs
index 99fba4fe7..25654e695 100644
--- a/src/tools/clippy/clippy_utils/src/ty.rs
+++ b/src/tools/clippy/clippy_utils/src/ty.rs
@@ -17,8 +17,8 @@ use rustc_lint::LateContext;
use rustc_middle::mir::interpret::{ConstValue, Scalar};
use rustc_middle::ty::{
self, AdtDef, AliasTy, AssocKind, Binder, BoundRegion, DefIdTree, FnSig, IntTy, List, ParamEnv, Predicate,
- PredicateKind, Region, RegionKind, SubstsRef, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitor, UintTy,
- VariantDef, VariantDiscr,
+ PredicateKind, Region, RegionKind, SubstsRef, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitableExt,
+ TypeVisitor, UintTy, VariantDef, VariantDiscr,
};
use rustc_middle::ty::{GenericArg, GenericArgKind};
use rustc_span::symbol::Ident;
@@ -237,7 +237,7 @@ pub fn implements_trait_with_env<'tcx>(
kind: TypeVariableOriginKind::MiscVariable,
span: DUMMY_SP,
};
- let ty_params = tcx.mk_substs(
+ let ty_params = tcx.mk_substs_from_iter(
ty_params
.into_iter()
.map(|arg| arg.unwrap_or_else(|| infcx.next_ty_var(orig).into())),
@@ -346,7 +346,7 @@ pub fn is_non_aggregate_primitive_type(ty: Ty<'_>) -> bool {
pub fn is_recursively_primitive_type(ty: Ty<'_>) -> bool {
match *ty.kind() {
ty::Bool | ty::Char | ty::Int(_) | ty::Uint(_) | ty::Float(_) | ty::Str => true,
- ty::Ref(_, inner, _) if *inner.kind() == ty::Str => true,
+ ty::Ref(_, inner, _) if inner.is_str() => true,
ty::Array(inner_type, _) | ty::Slice(inner_type) => is_recursively_primitive_type(inner_type),
ty::Tuple(inner_types) => inner_types.iter().all(is_recursively_primitive_type),
_ => false,
@@ -628,7 +628,7 @@ impl<'tcx> ExprFnSig<'tcx> {
/// If the expression is function like, get the signature for it.
pub fn expr_sig<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'_>) -> Option<ExprFnSig<'tcx>> {
if let Res::Def(DefKind::Fn | DefKind::Ctor(_, CtorKind::Fn) | DefKind::AssocFn, id) = path_res(cx, expr) {
- Some(ExprFnSig::Sig(cx.tcx.fn_sig(id), Some(id)))
+ Some(ExprFnSig::Sig(cx.tcx.fn_sig(id).subst_identity(), Some(id)))
} else {
ty_sig(cx, cx.typeck_results().expr_ty_adjusted(expr).peel_refs())
}
@@ -646,10 +646,13 @@ pub fn ty_sig<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> Option<ExprFnSig<'t
.and_then(|id| cx.tcx.hir().fn_decl_by_hir_id(cx.tcx.hir().local_def_id_to_hir_id(id)));
Some(ExprFnSig::Closure(decl, subs.as_closure().sig()))
},
- ty::FnDef(id, subs) => Some(ExprFnSig::Sig(cx.tcx.bound_fn_sig(id).subst(cx.tcx, subs), Some(id))),
- ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. }) => {
- sig_from_bounds(cx, ty, cx.tcx.item_bounds(def_id).subst(cx.tcx, substs), cx.tcx.opt_parent(def_id))
- },
+ ty::FnDef(id, subs) => Some(ExprFnSig::Sig(cx.tcx.fn_sig(id).subst(cx.tcx, subs), Some(id))),
+ ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. }) => sig_from_bounds(
+ cx,
+ ty,
+ cx.tcx.item_bounds(def_id).subst(cx.tcx, substs),
+ cx.tcx.opt_parent(def_id),
+ ),
ty::FnPtr(sig) => Some(ExprFnSig::Sig(sig, None)),
ty::Dynamic(bounds, _, _) => {
let lang_items = cx.tcx.lang_items();
@@ -777,7 +780,7 @@ impl core::ops::Add<u32> for EnumValue {
#[expect(clippy::cast_possible_truncation, clippy::cast_possible_wrap)]
pub fn read_explicit_enum_value(tcx: TyCtxt<'_>, id: DefId) -> Option<EnumValue> {
if let Ok(ConstValue::Scalar(Scalar::Int(value))) = tcx.const_eval_poly(id) {
- match tcx.type_of(id).kind() {
+ match tcx.type_of(id).subst_identity().kind() {
ty::Int(_) => Some(EnumValue::Signed(match value.size().bytes() {
1 => i128::from(value.assert_bits(Size::from_bytes(1)) as u8 as i8),
2 => i128::from(value.assert_bits(Size::from_bytes(2)) as u16 as i16),
@@ -835,7 +838,7 @@ pub fn for_each_top_level_late_bound_region<B>(
index: u32,
f: F,
}
- impl<'tcx, B, F: FnMut(BoundRegion) -> ControlFlow<B>> TypeVisitor<'tcx> for V<F> {
+ impl<'tcx, B, F: FnMut(BoundRegion) -> ControlFlow<B>> TypeVisitor<TyCtxt<'tcx>> for V<F> {
type BreakTy = B;
fn visit_region(&mut self, r: Region<'tcx>) -> ControlFlow<Self::BreakTy> {
if let RegionKind::ReLateBound(idx, bound) = r.kind() && idx.as_u32() == self.index {
@@ -844,7 +847,7 @@ pub fn for_each_top_level_late_bound_region<B>(
ControlFlow::Continue(())
}
}
- fn visit_binder<T: TypeVisitable<'tcx>>(&mut self, t: &Binder<'tcx, T>) -> ControlFlow<Self::BreakTy> {
+ fn visit_binder<T: TypeVisitable<TyCtxt<'tcx>>>(&mut self, t: &Binder<'tcx, T>) -> ControlFlow<Self::BreakTy> {
self.index += 1;
let res = t.super_visit_with(self);
self.index -= 1;
@@ -891,16 +894,29 @@ impl AdtVariantInfo {
}
/// Gets the struct or enum variant from the given `Res`
-pub fn variant_of_res<'tcx>(cx: &LateContext<'tcx>, res: Res) -> Option<&'tcx VariantDef> {
+pub fn adt_and_variant_of_res<'tcx>(cx: &LateContext<'tcx>, res: Res) -> Option<(AdtDef<'tcx>, &'tcx VariantDef)> {
match res {
- Res::Def(DefKind::Struct, id) => Some(cx.tcx.adt_def(id).non_enum_variant()),
- Res::Def(DefKind::Variant, id) => Some(cx.tcx.adt_def(cx.tcx.parent(id)).variant_with_id(id)),
- Res::Def(DefKind::Ctor(CtorOf::Struct, _), id) => Some(cx.tcx.adt_def(cx.tcx.parent(id)).non_enum_variant()),
+ Res::Def(DefKind::Struct, id) => {
+ let adt = cx.tcx.adt_def(id);
+ Some((adt, adt.non_enum_variant()))
+ },
+ Res::Def(DefKind::Variant, id) => {
+ let adt = cx.tcx.adt_def(cx.tcx.parent(id));
+ Some((adt, adt.variant_with_id(id)))
+ },
+ Res::Def(DefKind::Ctor(CtorOf::Struct, _), id) => {
+ let adt = cx.tcx.adt_def(cx.tcx.parent(id));
+ Some((adt, adt.non_enum_variant()))
+ },
Res::Def(DefKind::Ctor(CtorOf::Variant, _), id) => {
let var_id = cx.tcx.parent(id);
- Some(cx.tcx.adt_def(cx.tcx.parent(var_id)).variant_with_id(var_id))
+ let adt = cx.tcx.adt_def(cx.tcx.parent(var_id));
+ Some((adt, adt.variant_with_id(var_id)))
+ },
+ Res::SelfCtor(id) => {
+ let adt = cx.tcx.type_of(id).subst_identity().ty_adt_def().unwrap();
+ Some((adt, adt.non_enum_variant()))
},
- Res::SelfCtor(id) => Some(cx.tcx.type_of(id).ty_adt_def().unwrap().non_enum_variant()),
_ => None,
}
}
@@ -946,7 +962,7 @@ pub fn approx_ty_size<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> u64 {
(Ok(size), _) => size,
(Err(_), ty::Tuple(list)) => list.as_substs().types().map(|t| approx_ty_size(cx, t)).sum(),
(Err(_), ty::Array(t, n)) => {
- n.try_eval_usize(cx.tcx, cx.param_env).unwrap_or_default() * approx_ty_size(cx, *t)
+ n.try_eval_target_usize(cx.tcx, cx.param_env).unwrap_or_default() * approx_ty_size(cx, *t)
},
(Err(_), ty::Adt(def, subst)) if def.is_struct() => def
.variants()
@@ -1062,7 +1078,7 @@ pub fn make_projection<'tcx>(
tcx,
container_id,
assoc_ty,
- tcx.mk_substs(substs.into_iter().map(Into::into)),
+ tcx.mk_substs_from_iter(substs.into_iter().map(Into::into)),
)
}
diff --git a/src/tools/clippy/clippy_utils/src/visitors.rs b/src/tools/clippy/clippy_utils/src/visitors.rs
index 14c01a60b..d27a20bd4 100644
--- a/src/tools/clippy/clippy_utils/src/visitors.rs
+++ b/src/tools/clippy/clippy_utils/src/visitors.rs
@@ -392,12 +392,16 @@ pub fn is_expr_unsafe<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) -> bool {
.cx
.typeck_results()
.type_dependent_def_id(e.hir_id)
- .map_or(false, |id| self.cx.tcx.fn_sig(id).unsafety() == Unsafety::Unsafe) =>
+ .map_or(false, |id| {
+ self.cx.tcx.fn_sig(id).skip_binder().unsafety() == Unsafety::Unsafe
+ }) =>
{
self.is_unsafe = true;
},
ExprKind::Call(func, _) => match *self.cx.typeck_results().expr_ty(func).peel_refs().kind() {
- ty::FnDef(id, _) if self.cx.tcx.fn_sig(id).unsafety() == Unsafety::Unsafe => self.is_unsafe = true,
+ ty::FnDef(id, _) if self.cx.tcx.fn_sig(id).skip_binder().unsafety() == Unsafety::Unsafe => {
+ self.is_unsafe = true;
+ },
ty::FnPtr(sig) if sig.unsafety() == Unsafety::Unsafe => self.is_unsafe = true,
_ => walk_expr(self, e),
},
@@ -661,7 +665,7 @@ pub fn for_each_unconsumed_temporary<'tcx, B>(
| ExprKind::Path(_)
| ExprKind::Continue(_)
| ExprKind::InlineAsm(_)
- | ExprKind::Err => (),
+ | ExprKind::Err(_) => (),
}
ControlFlow::Continue(())
}
diff --git a/src/tools/clippy/declare_clippy_lint/Cargo.toml b/src/tools/clippy/declare_clippy_lint/Cargo.toml
index c01e1062c..80eee3681 100644
--- a/src/tools/clippy/declare_clippy_lint/Cargo.toml
+++ b/src/tools/clippy/declare_clippy_lint/Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "declare_clippy_lint"
-version = "0.1.68"
+version = "0.1.69"
edition = "2021"
publish = false
diff --git a/src/tools/clippy/lintcheck/Cargo.toml b/src/tools/clippy/lintcheck/Cargo.toml
index de31c16b8..653121af5 100644
--- a/src/tools/clippy/lintcheck/Cargo.toml
+++ b/src/tools/clippy/lintcheck/Cargo.toml
@@ -10,8 +10,8 @@ edition = "2021"
publish = false
[dependencies]
-cargo_metadata = "0.14"
-clap = "3.2"
+cargo_metadata = "0.15.3"
+clap = "4.1.4"
crossbeam-channel = "0.5.6"
flate2 = "1.0"
rayon = "1.5.1"
diff --git a/src/tools/clippy/lintcheck/src/config.rs b/src/tools/clippy/lintcheck/src/config.rs
index b8824024e..e0244ddce 100644
--- a/src/tools/clippy/lintcheck/src/config.rs
+++ b/src/tools/clippy/lintcheck/src/config.rs
@@ -35,7 +35,7 @@ fn get_clap_config() -> ArgMatches {
.long("markdown")
.help("Change the reports table to use markdown links"),
Arg::new("recursive")
- .long("--recursive")
+ .long("recursive")
.help("Run clippy on the dependencies of crates specified in crates-toml")
.conflicts_with("threads")
.conflicts_with("fix"),
diff --git a/src/tools/clippy/lintcheck/src/main.rs b/src/tools/clippy/lintcheck/src/main.rs
index bd49f0960..23c852980 100644
--- a/src/tools/clippy/lintcheck/src/main.rs
+++ b/src/tools/clippy/lintcheck/src/main.rs
@@ -17,9 +17,9 @@ use crate::recursive::LintcheckServer;
use std::collections::{HashMap, HashSet};
use std::env;
use std::env::consts::EXE_SUFFIX;
-use std::fmt::Write as _;
+use std::fmt::{self, Write as _};
use std::fs;
-use std::io::ErrorKind;
+use std::io::{self, ErrorKind};
use std::path::{Path, PathBuf};
use std::process::Command;
use std::sync::atomic::{AtomicUsize, Ordering};
@@ -145,8 +145,8 @@ impl ClippyWarning {
}
let mut output = String::from("| ");
- let _ = write!(output, "[`{file_with_pos}`]({file}#L{})", self.line);
- let _ = write!(output, r#" | `{:<50}` | "{}" |"#, self.lint_type, self.message);
+ let _: fmt::Result = write!(output, "[`{file_with_pos}`]({file}#L{})", self.line);
+ let _: fmt::Result = write!(output, r#" | `{:<50}` | "{}" |"#, self.lint_type, self.message);
output.push('\n');
output
} else {
@@ -632,7 +632,7 @@ fn main() {
.unwrap();
let server = config.recursive.then(|| {
- let _ = fs::remove_dir_all("target/lintcheck/shared_target_dir/recursive");
+ let _: io::Result<()> = fs::remove_dir_all("target/lintcheck/shared_target_dir/recursive");
LintcheckServer::spawn(recursive_options)
});
@@ -689,7 +689,7 @@ fn main() {
write!(text, "{}", all_msgs.join("")).unwrap();
text.push_str("\n\n### ICEs:\n");
for (cratename, msg) in &ices {
- let _ = write!(text, "{cratename}: '{msg}'");
+ let _: fmt::Result = write!(text, "{cratename}: '{msg}'");
}
println!("Writing logs to {}", config.lintcheck_results_path.display());
diff --git a/src/tools/clippy/rust-toolchain b/src/tools/clippy/rust-toolchain
index 40a6f4709..cfe845ec7 100644
--- a/src/tools/clippy/rust-toolchain
+++ b/src/tools/clippy/rust-toolchain
@@ -1,3 +1,3 @@
[toolchain]
-channel = "nightly-2023-01-12"
+channel = "nightly-2023-02-25"
components = ["cargo", "llvm-tools", "rust-src", "rust-std", "rustc", "rustc-dev", "rustfmt"]
diff --git a/src/tools/clippy/src/driver.rs b/src/tools/clippy/src/driver.rs
index d521e8d88..dd183362f 100644
--- a/src/tools/clippy/src/driver.rs
+++ b/src/tools/clippy/src/driver.rs
@@ -209,7 +209,7 @@ fn report_clippy_ice(info: &panic::PanicInfo<'_>, bug_report_url: &str) {
// Separate the output with an empty line
eprintln!();
- let fallback_bundle = rustc_errors::fallback_fluent_bundle(rustc_errors::DEFAULT_LOCALE_RESOURCES, false);
+ let fallback_bundle = rustc_errors::fallback_fluent_bundle(rustc_driver::DEFAULT_LOCALE_RESOURCES.to_vec(), false);
let emitter = Box::new(rustc_errors::emitter::EmitterWriter::stderr(
rustc_errors::ColorConfig::Auto,
None,
@@ -220,6 +220,7 @@ fn report_clippy_ice(info: &panic::PanicInfo<'_>, bug_report_url: &str) {
None,
false,
false,
+ rustc_errors::TerminalUrl::No,
));
let handler = rustc_errors::Handler::with_emitter(true, None, emitter);
diff --git a/src/tools/clippy/src/main.rs b/src/tools/clippy/src/main.rs
index 7a78b3262..82147eba3 100644
--- a/src/tools/clippy/src/main.rs
+++ b/src/tools/clippy/src/main.rs
@@ -28,7 +28,7 @@ with:
-D --deny OPT Set lint denied
-F --forbid OPT Set lint forbidden
-You can use tool lints to allow or deny lints from your code, eg.:
+You can use tool lints to allow or deny lints from your code, e.g.:
#[allow(clippy::needless_lifetimes)]
"#;
diff --git a/src/tools/clippy/tests/ui-internal/custom_ice_message.rs b/src/tools/clippy/tests/ui-internal/custom_ice_message.rs
index 4be04f77f..837811bdf 100644
--- a/src/tools/clippy/tests/ui-internal/custom_ice_message.rs
+++ b/src/tools/clippy/tests/ui-internal/custom_ice_message.rs
@@ -1,8 +1,9 @@
// rustc-env:RUST_BACKTRACE=0
// normalize-stderr-test: "Clippy version: .*" -> "Clippy version: foo"
-// normalize-stderr-test: "internal_lints.rs:\d*:\d*" -> "internal_lints.rs"
+// normalize-stderr-test: "produce_ice.rs:\d*:\d*" -> "produce_ice.rs"
// normalize-stderr-test: "', .*clippy_lints" -> "', clippy_lints"
// normalize-stderr-test: "'rustc'" -> "'<unnamed>'"
+// normalize-stderr-test: "(?ms)query stack during panic:\n.*end of query stack\n" -> ""
#![deny(clippy::internal)]
#![allow(clippy::missing_clippy_version_attribute)]
diff --git a/src/tools/clippy/tests/ui-internal/custom_ice_message.stderr b/src/tools/clippy/tests/ui-internal/custom_ice_message.stderr
index 2ba589066..7ed0ef027 100644
--- a/src/tools/clippy/tests/ui-internal/custom_ice_message.stderr
+++ b/src/tools/clippy/tests/ui-internal/custom_ice_message.stderr
@@ -1,4 +1,4 @@
-thread '<unnamed>' panicked at 'Would you like some help with that?', clippy_lints/src/utils/internal_lints/produce_ice.rs:28:9
+thread '<unnamed>' panicked at 'Would you like some help with that?', clippy_lints/src/utils/internal_lints/produce_ice.rs
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
error: internal compiler error: unexpected panic
@@ -9,5 +9,3 @@ note: we would appreciate a bug report: https://github.com/rust-lang/rust-clippy
note: Clippy version: foo
-query stack during panic:
-end of query stack
diff --git a/src/tools/clippy/tests/ui-toml/expect_used/expect_used.rs b/src/tools/clippy/tests/ui-toml/expect_used/expect_used.rs
index bff97d97d..89f142a15 100644
--- a/src/tools/clippy/tests/ui-toml/expect_used/expect_used.rs
+++ b/src/tools/clippy/tests/ui-toml/expect_used/expect_used.rs
@@ -16,6 +16,18 @@ fn main() {
expect_result();
}
+#[test]
+fn test_expect_option() {
+ let opt = Some(0);
+ let _ = opt.expect("");
+}
+
+#[test]
+fn test_expect_result() {
+ let res: Result<u8, ()> = Ok(0);
+ let _ = res.expect("");
+}
+
#[cfg(test)]
mod issue9612 {
// should not lint in `#[cfg(test)]` modules
diff --git a/src/tools/clippy/tests/ui-toml/pub_crate_missing_docs/clippy.toml b/src/tools/clippy/tests/ui-toml/pub_crate_missing_docs/clippy.toml
new file mode 100644
index 000000000..ec210a987
--- /dev/null
+++ b/src/tools/clippy/tests/ui-toml/pub_crate_missing_docs/clippy.toml
@@ -0,0 +1 @@
+missing-docs-in-crate-items = true
diff --git a/src/tools/clippy/tests/ui-toml/pub_crate_missing_docs/pub_crate_missing_doc.rs b/src/tools/clippy/tests/ui-toml/pub_crate_missing_docs/pub_crate_missing_doc.rs
new file mode 100644
index 000000000..830d71f61
--- /dev/null
+++ b/src/tools/clippy/tests/ui-toml/pub_crate_missing_docs/pub_crate_missing_doc.rs
@@ -0,0 +1,59 @@
+//! this is crate
+#![allow(missing_docs)]
+#![warn(clippy::missing_docs_in_private_items)]
+
+/// this is mod
+mod my_mod {
+ /// some docs
+ fn priv_with_docs() {}
+ fn priv_no_docs() {}
+ /// some docs
+ pub(crate) fn crate_with_docs() {}
+ pub(crate) fn crate_no_docs() {}
+ /// some docs
+ pub(super) fn super_with_docs() {}
+ pub(super) fn super_no_docs() {}
+
+ mod my_sub {
+ /// some docs
+ fn sub_priv_with_docs() {}
+ fn sub_priv_no_docs() {}
+ /// some docs
+ pub(crate) fn sub_crate_with_docs() {}
+ pub(crate) fn sub_crate_no_docs() {}
+ /// some docs
+ pub(super) fn sub_super_with_docs() {}
+ pub(super) fn sub_super_no_docs() {}
+ }
+
+ /// some docs
+ pub(crate) struct CrateStructWithDocs {
+ /// some docs
+ pub(crate) crate_field_with_docs: (),
+ pub(crate) crate_field_no_docs: (),
+ /// some docs
+ priv_field_with_docs: (),
+ priv_field_no_docs: (),
+ }
+
+ pub(crate) struct CrateStructNoDocs {
+ /// some docs
+ pub(crate) crate_field_with_docs: (),
+ pub(crate) crate_field_no_docs: (),
+ /// some docs
+ priv_field_with_docs: (),
+ priv_field_no_docs: (),
+ }
+}
+
+/// some docs
+type CrateTypedefWithDocs = String;
+type CrateTypedefNoDocs = String;
+/// some docs
+pub type PubTypedefWithDocs = String;
+pub type PubTypedefNoDocs = String;
+
+fn main() {
+ my_mod::crate_with_docs();
+ my_mod::crate_no_docs();
+}
diff --git a/src/tools/clippy/tests/ui-toml/pub_crate_missing_docs/pub_crate_missing_doc.stderr b/src/tools/clippy/tests/ui-toml/pub_crate_missing_docs/pub_crate_missing_doc.stderr
new file mode 100644
index 000000000..a47418705
--- /dev/null
+++ b/src/tools/clippy/tests/ui-toml/pub_crate_missing_docs/pub_crate_missing_doc.stderr
@@ -0,0 +1,52 @@
+error: missing documentation for a function
+ --> $DIR/pub_crate_missing_doc.rs:12:5
+ |
+LL | pub(crate) fn crate_no_docs() {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: `-D clippy::missing-docs-in-private-items` implied by `-D warnings`
+
+error: missing documentation for a function
+ --> $DIR/pub_crate_missing_doc.rs:15:5
+ |
+LL | pub(super) fn super_no_docs() {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: missing documentation for a function
+ --> $DIR/pub_crate_missing_doc.rs:23:9
+ |
+LL | pub(crate) fn sub_crate_no_docs() {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: missing documentation for a struct field
+ --> $DIR/pub_crate_missing_doc.rs:33:9
+ |
+LL | pub(crate) crate_field_no_docs: (),
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: missing documentation for a struct
+ --> $DIR/pub_crate_missing_doc.rs:39:5
+ |
+LL | / pub(crate) struct CrateStructNoDocs {
+LL | | /// some docs
+LL | | pub(crate) crate_field_with_docs: (),
+LL | | pub(crate) crate_field_no_docs: (),
+... |
+LL | | priv_field_no_docs: (),
+LL | | }
+ | |_____^
+
+error: missing documentation for a struct field
+ --> $DIR/pub_crate_missing_doc.rs:42:9
+ |
+LL | pub(crate) crate_field_no_docs: (),
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: missing documentation for a type alias
+ --> $DIR/pub_crate_missing_doc.rs:51:1
+ |
+LL | type CrateTypedefNoDocs = String;
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 7 previous errors
+
diff --git a/src/tools/clippy/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr b/src/tools/clippy/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr
index a22c6a5a0..6a246afac 100644
--- a/src/tools/clippy/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr
+++ b/src/tools/clippy/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr
@@ -33,6 +33,7 @@ error: error reading Clippy's configuration file `$DIR/clippy.toml`: unknown fie
max-struct-bools
max-suggested-slice-pattern-length
max-trait-bounds
+ missing-docs-in-crate-items
msrv
pass-by-value-size-limit
single-char-binding-names-threshold
diff --git a/src/tools/clippy/tests/ui-toml/unwrap_used/unwrap_used.rs b/src/tools/clippy/tests/ui-toml/unwrap_used/unwrap_used.rs
index bc8e8c1f0..6525ea5bf 100644
--- a/src/tools/clippy/tests/ui-toml/unwrap_used/unwrap_used.rs
+++ b/src/tools/clippy/tests/ui-toml/unwrap_used/unwrap_used.rs
@@ -66,6 +66,12 @@ fn main() {
}
}
+#[test]
+fn test() {
+ let boxed_slice: Box<[u8]> = Box::new([0, 1, 2, 3]);
+ let _ = boxed_slice.get(1).unwrap();
+}
+
#[cfg(test)]
mod issue9612 {
// should not lint in `#[cfg(test)]` modules
diff --git a/src/tools/clippy/tests/ui-toml/unwrap_used/unwrap_used.stderr b/src/tools/clippy/tests/ui-toml/unwrap_used/unwrap_used.stderr
index 94b5ef663..8a32750e3 100644
--- a/src/tools/clippy/tests/ui-toml/unwrap_used/unwrap_used.stderr
+++ b/src/tools/clippy/tests/ui-toml/unwrap_used/unwrap_used.stderr
@@ -188,10 +188,16 @@ LL | let _ = some_vec.get_mut(0..1).unwrap().to_vec();
= help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message
error: called `.get().unwrap()` on a slice. Using `[]` is more clear and more concise
- --> $DIR/unwrap_used.rs:84:17
+ --> $DIR/unwrap_used.rs:72:13
+ |
+LL | let _ = boxed_slice.get(1).unwrap();
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&boxed_slice[1]`
+
+error: called `.get().unwrap()` on a slice. Using `[]` is more clear and more concise
+ --> $DIR/unwrap_used.rs:90:17
|
LL | let _ = Box::new([0]).get(1).unwrap();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&Box::new([0])[1]`
-error: aborting due to 27 previous errors
+error: aborting due to 28 previous errors
diff --git a/src/tools/clippy/tests/ui/arithmetic_side_effects.rs b/src/tools/clippy/tests/ui/arithmetic_side_effects.rs
index 918cf81c6..2611e3a78 100644
--- a/src/tools/clippy/tests/ui/arithmetic_side_effects.rs
+++ b/src/tools/clippy/tests/ui/arithmetic_side_effects.rs
@@ -13,6 +13,9 @@
use core::num::{Saturating, Wrapping};
+const ONE: i32 = 1;
+const ZERO: i32 = 0;
+
#[derive(Clone, Copy)]
pub struct Custom;
@@ -182,6 +185,10 @@ pub fn non_overflowing_ops_or_ops_already_handled_by_the_compiler_should_not_tri
_n += &0;
_n -= 0;
_n -= &0;
+ _n += ZERO;
+ _n += &ZERO;
+ _n -= ZERO;
+ _n -= &ZERO;
_n /= 99;
_n /= &99;
_n %= 99;
@@ -190,10 +197,18 @@ pub fn non_overflowing_ops_or_ops_already_handled_by_the_compiler_should_not_tri
_n *= &0;
_n *= 1;
_n *= &1;
+ _n *= ZERO;
+ _n *= &ZERO;
+ _n *= ONE;
+ _n *= &ONE;
_n += -0;
_n += &-0;
_n -= -0;
_n -= &-0;
+ _n += -ZERO;
+ _n += &-ZERO;
+ _n -= -ZERO;
+ _n -= &-ZERO;
_n /= -99;
_n /= &-99;
_n %= -99;
@@ -208,10 +223,18 @@ pub fn non_overflowing_ops_or_ops_already_handled_by_the_compiler_should_not_tri
_n = _n + &0;
_n = 0 + _n;
_n = &0 + _n;
+ _n = _n + ZERO;
+ _n = _n + &ZERO;
+ _n = ZERO + _n;
+ _n = &ZERO + _n;
_n = _n - 0;
_n = _n - &0;
_n = 0 - _n;
_n = &0 - _n;
+ _n = _n - ZERO;
+ _n = _n - &ZERO;
+ _n = ZERO - _n;
+ _n = &ZERO - _n;
_n = _n / 99;
_n = _n / &99;
_n = _n % 99;
@@ -222,6 +245,10 @@ pub fn non_overflowing_ops_or_ops_already_handled_by_the_compiler_should_not_tri
_n = &0 * _n;
_n = _n * 1;
_n = _n * &1;
+ _n = ZERO * _n;
+ _n = &ZERO * _n;
+ _n = _n * ONE;
+ _n = _n * &ONE;
_n = 1 * _n;
_n = &1 * _n;
_n = 23 + 85;
diff --git a/src/tools/clippy/tests/ui/arithmetic_side_effects.stderr b/src/tools/clippy/tests/ui/arithmetic_side_effects.stderr
index 5e349f6b4..17a2448fb 100644
--- a/src/tools/clippy/tests/ui/arithmetic_side_effects.stderr
+++ b/src/tools/clippy/tests/ui/arithmetic_side_effects.stderr
@@ -1,5 +1,5 @@
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:243:5
+ --> $DIR/arithmetic_side_effects.rs:270:5
|
LL | _n += 1;
| ^^^^^^^
@@ -7,589 +7,589 @@ LL | _n += 1;
= note: `-D clippy::arithmetic-side-effects` implied by `-D warnings`
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:244:5
+ --> $DIR/arithmetic_side_effects.rs:271:5
|
LL | _n += &1;
| ^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:245:5
+ --> $DIR/arithmetic_side_effects.rs:272:5
|
LL | _n -= 1;
| ^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:246:5
+ --> $DIR/arithmetic_side_effects.rs:273:5
|
LL | _n -= &1;
| ^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:247:5
+ --> $DIR/arithmetic_side_effects.rs:274:5
|
LL | _n /= 0;
| ^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:248:5
+ --> $DIR/arithmetic_side_effects.rs:275:5
|
LL | _n /= &0;
| ^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:249:5
+ --> $DIR/arithmetic_side_effects.rs:276:5
|
LL | _n %= 0;
| ^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:250:5
+ --> $DIR/arithmetic_side_effects.rs:277:5
|
LL | _n %= &0;
| ^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:251:5
+ --> $DIR/arithmetic_side_effects.rs:278:5
|
LL | _n *= 2;
| ^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:252:5
+ --> $DIR/arithmetic_side_effects.rs:279:5
|
LL | _n *= &2;
| ^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:253:5
+ --> $DIR/arithmetic_side_effects.rs:280:5
|
LL | _n += -1;
| ^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:254:5
+ --> $DIR/arithmetic_side_effects.rs:281:5
|
LL | _n += &-1;
| ^^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:255:5
+ --> $DIR/arithmetic_side_effects.rs:282:5
|
LL | _n -= -1;
| ^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:256:5
+ --> $DIR/arithmetic_side_effects.rs:283:5
|
LL | _n -= &-1;
| ^^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:257:5
+ --> $DIR/arithmetic_side_effects.rs:284:5
|
LL | _n /= -0;
| ^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:258:5
+ --> $DIR/arithmetic_side_effects.rs:285:5
|
LL | _n /= &-0;
| ^^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:259:5
+ --> $DIR/arithmetic_side_effects.rs:286:5
|
LL | _n %= -0;
| ^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:260:5
+ --> $DIR/arithmetic_side_effects.rs:287:5
|
LL | _n %= &-0;
| ^^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:261:5
+ --> $DIR/arithmetic_side_effects.rs:288:5
|
LL | _n *= -2;
| ^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:262:5
+ --> $DIR/arithmetic_side_effects.rs:289:5
|
LL | _n *= &-2;
| ^^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:263:5
+ --> $DIR/arithmetic_side_effects.rs:290:5
|
LL | _custom += Custom;
| ^^^^^^^^^^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:264:5
+ --> $DIR/arithmetic_side_effects.rs:291:5
|
LL | _custom += &Custom;
| ^^^^^^^^^^^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:265:5
+ --> $DIR/arithmetic_side_effects.rs:292:5
|
LL | _custom -= Custom;
| ^^^^^^^^^^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:266:5
+ --> $DIR/arithmetic_side_effects.rs:293:5
|
LL | _custom -= &Custom;
| ^^^^^^^^^^^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:267:5
+ --> $DIR/arithmetic_side_effects.rs:294:5
|
LL | _custom /= Custom;
| ^^^^^^^^^^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:268:5
+ --> $DIR/arithmetic_side_effects.rs:295:5
|
LL | _custom /= &Custom;
| ^^^^^^^^^^^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:269:5
+ --> $DIR/arithmetic_side_effects.rs:296:5
|
LL | _custom %= Custom;
| ^^^^^^^^^^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:270:5
+ --> $DIR/arithmetic_side_effects.rs:297:5
|
LL | _custom %= &Custom;
| ^^^^^^^^^^^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:271:5
+ --> $DIR/arithmetic_side_effects.rs:298:5
|
LL | _custom *= Custom;
| ^^^^^^^^^^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:272:5
+ --> $DIR/arithmetic_side_effects.rs:299:5
|
LL | _custom *= &Custom;
| ^^^^^^^^^^^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:273:5
+ --> $DIR/arithmetic_side_effects.rs:300:5
|
LL | _custom += -Custom;
| ^^^^^^^^^^^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:274:5
+ --> $DIR/arithmetic_side_effects.rs:301:5
|
LL | _custom += &-Custom;
| ^^^^^^^^^^^^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:275:5
+ --> $DIR/arithmetic_side_effects.rs:302:5
|
LL | _custom -= -Custom;
| ^^^^^^^^^^^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:276:5
+ --> $DIR/arithmetic_side_effects.rs:303:5
|
LL | _custom -= &-Custom;
| ^^^^^^^^^^^^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:277:5
+ --> $DIR/arithmetic_side_effects.rs:304:5
|
LL | _custom /= -Custom;
| ^^^^^^^^^^^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:278:5
+ --> $DIR/arithmetic_side_effects.rs:305:5
|
LL | _custom /= &-Custom;
| ^^^^^^^^^^^^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:279:5
+ --> $DIR/arithmetic_side_effects.rs:306:5
|
LL | _custom %= -Custom;
| ^^^^^^^^^^^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:280:5
+ --> $DIR/arithmetic_side_effects.rs:307:5
|
LL | _custom %= &-Custom;
| ^^^^^^^^^^^^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:281:5
+ --> $DIR/arithmetic_side_effects.rs:308:5
|
LL | _custom *= -Custom;
| ^^^^^^^^^^^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:282:5
+ --> $DIR/arithmetic_side_effects.rs:309:5
|
LL | _custom *= &-Custom;
| ^^^^^^^^^^^^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:285:10
+ --> $DIR/arithmetic_side_effects.rs:312:10
|
LL | _n = _n + 1;
| ^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:286:10
+ --> $DIR/arithmetic_side_effects.rs:313:10
|
LL | _n = _n + &1;
| ^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:287:10
+ --> $DIR/arithmetic_side_effects.rs:314:10
|
LL | _n = 1 + _n;
| ^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:288:10
+ --> $DIR/arithmetic_side_effects.rs:315:10
|
LL | _n = &1 + _n;
| ^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:289:10
+ --> $DIR/arithmetic_side_effects.rs:316:10
|
LL | _n = _n - 1;
| ^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:290:10
+ --> $DIR/arithmetic_side_effects.rs:317:10
|
LL | _n = _n - &1;
| ^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:291:10
+ --> $DIR/arithmetic_side_effects.rs:318:10
|
LL | _n = 1 - _n;
| ^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:292:10
+ --> $DIR/arithmetic_side_effects.rs:319:10
|
LL | _n = &1 - _n;
| ^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:293:10
+ --> $DIR/arithmetic_side_effects.rs:320:10
|
LL | _n = _n / 0;
| ^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:294:10
+ --> $DIR/arithmetic_side_effects.rs:321:10
|
LL | _n = _n / &0;
| ^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:295:10
+ --> $DIR/arithmetic_side_effects.rs:322:10
|
LL | _n = _n % 0;
| ^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:296:10
+ --> $DIR/arithmetic_side_effects.rs:323:10
|
LL | _n = _n % &0;
| ^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:297:10
+ --> $DIR/arithmetic_side_effects.rs:324:10
|
LL | _n = _n * 2;
| ^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:298:10
+ --> $DIR/arithmetic_side_effects.rs:325:10
|
LL | _n = _n * &2;
| ^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:299:10
+ --> $DIR/arithmetic_side_effects.rs:326:10
|
LL | _n = 2 * _n;
| ^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:300:10
+ --> $DIR/arithmetic_side_effects.rs:327:10
|
LL | _n = &2 * _n;
| ^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:301:10
+ --> $DIR/arithmetic_side_effects.rs:328:10
|
LL | _n = 23 + &85;
| ^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:302:10
+ --> $DIR/arithmetic_side_effects.rs:329:10
|
LL | _n = &23 + 85;
| ^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:303:10
+ --> $DIR/arithmetic_side_effects.rs:330:10
|
LL | _n = &23 + &85;
| ^^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:304:15
+ --> $DIR/arithmetic_side_effects.rs:331:15
|
LL | _custom = _custom + _custom;
| ^^^^^^^^^^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:305:15
+ --> $DIR/arithmetic_side_effects.rs:332:15
|
LL | _custom = _custom + &_custom;
| ^^^^^^^^^^^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:306:15
+ --> $DIR/arithmetic_side_effects.rs:333:15
|
LL | _custom = Custom + _custom;
| ^^^^^^^^^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:307:15
+ --> $DIR/arithmetic_side_effects.rs:334:15
|
LL | _custom = &Custom + _custom;
| ^^^^^^^^^^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:308:15
+ --> $DIR/arithmetic_side_effects.rs:335:15
|
LL | _custom = _custom - Custom;
| ^^^^^^^^^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:309:15
+ --> $DIR/arithmetic_side_effects.rs:336:15
|
LL | _custom = _custom - &Custom;
| ^^^^^^^^^^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:310:15
+ --> $DIR/arithmetic_side_effects.rs:337:15
|
LL | _custom = Custom - _custom;
| ^^^^^^^^^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:311:15
+ --> $DIR/arithmetic_side_effects.rs:338:15
|
LL | _custom = &Custom - _custom;
| ^^^^^^^^^^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:312:15
+ --> $DIR/arithmetic_side_effects.rs:339:15
|
LL | _custom = _custom / Custom;
| ^^^^^^^^^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:313:15
+ --> $DIR/arithmetic_side_effects.rs:340:15
|
LL | _custom = _custom / &Custom;
| ^^^^^^^^^^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:314:15
+ --> $DIR/arithmetic_side_effects.rs:341:15
|
LL | _custom = _custom % Custom;
| ^^^^^^^^^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:315:15
+ --> $DIR/arithmetic_side_effects.rs:342:15
|
LL | _custom = _custom % &Custom;
| ^^^^^^^^^^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:316:15
+ --> $DIR/arithmetic_side_effects.rs:343:15
|
LL | _custom = _custom * Custom;
| ^^^^^^^^^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:317:15
+ --> $DIR/arithmetic_side_effects.rs:344:15
|
LL | _custom = _custom * &Custom;
| ^^^^^^^^^^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:318:15
+ --> $DIR/arithmetic_side_effects.rs:345:15
|
LL | _custom = Custom * _custom;
| ^^^^^^^^^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:319:15
+ --> $DIR/arithmetic_side_effects.rs:346:15
|
LL | _custom = &Custom * _custom;
| ^^^^^^^^^^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:320:15
+ --> $DIR/arithmetic_side_effects.rs:347:15
|
LL | _custom = Custom + &Custom;
| ^^^^^^^^^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:321:15
+ --> $DIR/arithmetic_side_effects.rs:348:15
|
LL | _custom = &Custom + Custom;
| ^^^^^^^^^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:322:15
+ --> $DIR/arithmetic_side_effects.rs:349:15
|
LL | _custom = &Custom + &Custom;
| ^^^^^^^^^^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:325:10
+ --> $DIR/arithmetic_side_effects.rs:352:10
|
LL | _n = -_n;
| ^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:326:10
+ --> $DIR/arithmetic_side_effects.rs:353:10
|
LL | _n = -&_n;
| ^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:327:15
+ --> $DIR/arithmetic_side_effects.rs:354:15
|
LL | _custom = -_custom;
| ^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:328:15
+ --> $DIR/arithmetic_side_effects.rs:355:15
|
LL | _custom = -&_custom;
| ^^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:337:5
+ --> $DIR/arithmetic_side_effects.rs:364:5
|
LL | 1 + i;
| ^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:338:5
+ --> $DIR/arithmetic_side_effects.rs:365:5
|
LL | i * 2;
| ^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:340:5
+ --> $DIR/arithmetic_side_effects.rs:367:5
|
LL | i - 2 + 2 - i;
| ^^^^^^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:341:5
+ --> $DIR/arithmetic_side_effects.rs:368:5
|
LL | -i;
| ^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:342:5
+ --> $DIR/arithmetic_side_effects.rs:369:5
|
LL | i >> 1;
| ^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:343:5
+ --> $DIR/arithmetic_side_effects.rs:370:5
|
LL | i << 1;
| ^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:352:5
+ --> $DIR/arithmetic_side_effects.rs:379:5
|
LL | i += 1;
| ^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:353:5
+ --> $DIR/arithmetic_side_effects.rs:380:5
|
LL | i -= 1;
| ^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:354:5
+ --> $DIR/arithmetic_side_effects.rs:381:5
|
LL | i *= 2;
| ^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:356:5
+ --> $DIR/arithmetic_side_effects.rs:383:5
|
LL | i /= 0;
| ^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:358:5
+ --> $DIR/arithmetic_side_effects.rs:385:5
|
LL | i /= var1;
| ^^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:359:5
+ --> $DIR/arithmetic_side_effects.rs:386:5
|
LL | i /= var2;
| ^^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:361:5
+ --> $DIR/arithmetic_side_effects.rs:388:5
|
LL | i %= 0;
| ^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:363:5
+ --> $DIR/arithmetic_side_effects.rs:390:5
|
LL | i %= var1;
| ^^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:364:5
+ --> $DIR/arithmetic_side_effects.rs:391:5
|
LL | i %= var2;
| ^^^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:365:5
+ --> $DIR/arithmetic_side_effects.rs:392:5
|
LL | i <<= 3;
| ^^^^^^^
error: arithmetic operation that can potentially result in unexpected side-effects
- --> $DIR/arithmetic_side_effects.rs:366:5
+ --> $DIR/arithmetic_side_effects.rs:393:5
|
LL | i >>= 2;
| ^^^^^^^
diff --git a/src/tools/clippy/tests/ui/auxiliary/macro_rules.rs b/src/tools/clippy/tests/ui/auxiliary/macro_rules.rs
index 1e5f20e8c..a13af5652 100644
--- a/src/tools/clippy/tests/ui/auxiliary/macro_rules.rs
+++ b/src/tools/clippy/tests/ui/auxiliary/macro_rules.rs
@@ -149,3 +149,22 @@ macro_rules! almost_complete_range {
let _ = '0'..'9';
};
}
+
+#[macro_export]
+macro_rules! unsafe_macro {
+ () => {
+ unsafe {
+ *core::ptr::null::<()>();
+ *core::ptr::null::<()>();
+ }
+ };
+}
+
+#[macro_export]
+macro_rules! needless_lifetime {
+ () => {
+ fn needless_lifetime<'a>(x: &'a u8) -> &'a u8 {
+ unimplemented!()
+ }
+ };
+}
diff --git a/src/tools/clippy/tests/ui/bool_assert_comparison.fixed b/src/tools/clippy/tests/ui/bool_assert_comparison.fixed
new file mode 100644
index 000000000..b8dd92906
--- /dev/null
+++ b/src/tools/clippy/tests/ui/bool_assert_comparison.fixed
@@ -0,0 +1,171 @@
+// run-rustfix
+
+#![allow(unused, clippy::assertions_on_constants)]
+#![warn(clippy::bool_assert_comparison)]
+
+use std::ops::Not;
+
+macro_rules! a {
+ () => {
+ true
+ };
+}
+macro_rules! b {
+ () => {
+ true
+ };
+}
+
+// Implements the Not trait but with an output type
+// that's not bool. Should not suggest a rewrite
+#[derive(Debug, Clone, Copy)]
+enum ImplNotTraitWithoutBool {
+ VariantX(bool),
+ VariantY(u32),
+}
+
+impl PartialEq<bool> for ImplNotTraitWithoutBool {
+ fn eq(&self, other: &bool) -> bool {
+ match *self {
+ ImplNotTraitWithoutBool::VariantX(b) => b == *other,
+ _ => false,
+ }
+ }
+}
+
+impl Not for ImplNotTraitWithoutBool {
+ type Output = Self;
+
+ fn not(self) -> Self::Output {
+ match self {
+ ImplNotTraitWithoutBool::VariantX(b) => ImplNotTraitWithoutBool::VariantX(!b),
+ ImplNotTraitWithoutBool::VariantY(0) => ImplNotTraitWithoutBool::VariantY(1),
+ ImplNotTraitWithoutBool::VariantY(_) => ImplNotTraitWithoutBool::VariantY(0),
+ }
+ }
+}
+
+// This type implements the Not trait with an Output of
+// type bool. Using assert!(..) must be suggested
+#[derive(Debug, Clone, Copy)]
+struct ImplNotTraitWithBool;
+
+impl PartialEq<bool> for ImplNotTraitWithBool {
+ fn eq(&self, other: &bool) -> bool {
+ false
+ }
+}
+
+impl Not for ImplNotTraitWithBool {
+ type Output = bool;
+
+ fn not(self) -> Self::Output {
+ true
+ }
+}
+
+#[derive(Debug)]
+struct NonCopy;
+
+impl PartialEq<bool> for NonCopy {
+ fn eq(&self, other: &bool) -> bool {
+ false
+ }
+}
+
+impl Not for NonCopy {
+ type Output = bool;
+
+ fn not(self) -> Self::Output {
+ true
+ }
+}
+
+fn main() {
+ let a = ImplNotTraitWithoutBool::VariantX(true);
+ let b = ImplNotTraitWithBool;
+
+ assert_eq!("a".len(), 1);
+ assert!(!"a".is_empty());
+ assert!("".is_empty());
+ assert!("".is_empty());
+ assert_eq!(a!(), b!());
+ assert_eq!(a!(), "".is_empty());
+ assert_eq!("".is_empty(), b!());
+ assert_eq!(a, true);
+ assert!(b);
+
+ assert_ne!("a".len(), 1);
+ assert!("a".is_empty());
+ assert!(!"".is_empty());
+ assert!(!"".is_empty());
+ assert_ne!(a!(), b!());
+ assert_ne!(a!(), "".is_empty());
+ assert_ne!("".is_empty(), b!());
+ assert_ne!(a, true);
+ assert!(!b);
+
+ debug_assert_eq!("a".len(), 1);
+ debug_assert!(!"a".is_empty());
+ debug_assert!("".is_empty());
+ debug_assert!("".is_empty());
+ debug_assert_eq!(a!(), b!());
+ debug_assert_eq!(a!(), "".is_empty());
+ debug_assert_eq!("".is_empty(), b!());
+ debug_assert_eq!(a, true);
+ debug_assert!(b);
+
+ debug_assert_ne!("a".len(), 1);
+ debug_assert!("a".is_empty());
+ debug_assert!(!"".is_empty());
+ debug_assert!(!"".is_empty());
+ debug_assert_ne!(a!(), b!());
+ debug_assert_ne!(a!(), "".is_empty());
+ debug_assert_ne!("".is_empty(), b!());
+ debug_assert_ne!(a, true);
+ debug_assert!(!b);
+
+ // assert with error messages
+ assert_eq!("a".len(), 1, "tadam {}", 1);
+ assert_eq!("a".len(), 1, "tadam {}", true);
+ assert!(!"a".is_empty(), "tadam {}", 1);
+ assert!(!"a".is_empty(), "tadam {}", true);
+ assert!(!"a".is_empty(), "tadam {}", true);
+ assert_eq!(a, true, "tadam {}", false);
+
+ debug_assert_eq!("a".len(), 1, "tadam {}", 1);
+ debug_assert_eq!("a".len(), 1, "tadam {}", true);
+ debug_assert!(!"a".is_empty(), "tadam {}", 1);
+ debug_assert!(!"a".is_empty(), "tadam {}", true);
+ debug_assert!(!"a".is_empty(), "tadam {}", true);
+ debug_assert_eq!(a, true, "tadam {}", false);
+
+ assert!(a!());
+ assert!(b!());
+
+ use debug_assert_eq as renamed;
+ renamed!(a, true);
+ debug_assert!(b);
+
+ let non_copy = NonCopy;
+ assert_eq!(non_copy, true);
+ // changing the above to `assert!(non_copy)` would cause a `borrow of moved value`
+ println!("{non_copy:?}");
+
+ macro_rules! in_macro {
+ ($v:expr) => {{
+ assert_eq!($v, true);
+ }};
+ }
+ in_macro!(a);
+
+ assert!("".is_empty());
+ assert!("".is_empty());
+ assert!(!"requires negation".is_empty());
+ assert!(!"requires negation".is_empty());
+
+ debug_assert!("".is_empty());
+ debug_assert!("".is_empty());
+ debug_assert!(!"requires negation".is_empty());
+ debug_assert!(!"requires negation".is_empty());
+}
diff --git a/src/tools/clippy/tests/ui/bool_assert_comparison.rs b/src/tools/clippy/tests/ui/bool_assert_comparison.rs
index ec4d6f3ff..0a8ad34fd 100644
--- a/src/tools/clippy/tests/ui/bool_assert_comparison.rs
+++ b/src/tools/clippy/tests/ui/bool_assert_comparison.rs
@@ -1,3 +1,6 @@
+// run-rustfix
+
+#![allow(unused, clippy::assertions_on_constants)]
#![warn(clippy::bool_assert_comparison)]
use std::ops::Not;
@@ -15,7 +18,7 @@ macro_rules! b {
// Implements the Not trait but with an output type
// that's not bool. Should not suggest a rewrite
-#[derive(Debug)]
+#[derive(Debug, Clone, Copy)]
enum ImplNotTraitWithoutBool {
VariantX(bool),
VariantY(u32),
@@ -44,7 +47,7 @@ impl Not for ImplNotTraitWithoutBool {
// This type implements the Not trait with an Output of
// type bool. Using assert!(..) must be suggested
-#[derive(Debug)]
+#[derive(Debug, Clone, Copy)]
struct ImplNotTraitWithBool;
impl PartialEq<bool> for ImplNotTraitWithBool {
@@ -61,6 +64,23 @@ impl Not for ImplNotTraitWithBool {
}
}
+#[derive(Debug)]
+struct NonCopy;
+
+impl PartialEq<bool> for NonCopy {
+ fn eq(&self, other: &bool) -> bool {
+ false
+ }
+}
+
+impl Not for NonCopy {
+ type Output = bool;
+
+ fn not(self) -> Self::Output {
+ true
+ }
+}
+
fn main() {
let a = ImplNotTraitWithoutBool::VariantX(true);
let b = ImplNotTraitWithBool;
@@ -119,4 +139,33 @@ fn main() {
debug_assert_eq!("a".is_empty(), false, "tadam {}", true);
debug_assert_eq!(false, "a".is_empty(), "tadam {}", true);
debug_assert_eq!(a, true, "tadam {}", false);
+
+ assert_eq!(a!(), true);
+ assert_eq!(true, b!());
+
+ use debug_assert_eq as renamed;
+ renamed!(a, true);
+ renamed!(b, true);
+
+ let non_copy = NonCopy;
+ assert_eq!(non_copy, true);
+ // changing the above to `assert!(non_copy)` would cause a `borrow of moved value`
+ println!("{non_copy:?}");
+
+ macro_rules! in_macro {
+ ($v:expr) => {{
+ assert_eq!($v, true);
+ }};
+ }
+ in_macro!(a);
+
+ assert_eq!("".is_empty(), true);
+ assert_ne!("".is_empty(), false);
+ assert_ne!("requires negation".is_empty(), true);
+ assert_eq!("requires negation".is_empty(), false);
+
+ debug_assert_eq!("".is_empty(), true);
+ debug_assert_ne!("".is_empty(), false);
+ debug_assert_ne!("requires negation".is_empty(), true);
+ debug_assert_eq!("requires negation".is_empty(), false);
}
diff --git a/src/tools/clippy/tests/ui/bool_assert_comparison.stderr b/src/tools/clippy/tests/ui/bool_assert_comparison.stderr
index 377d51be4..89cefc95a 100644
--- a/src/tools/clippy/tests/ui/bool_assert_comparison.stderr
+++ b/src/tools/clippy/tests/ui/bool_assert_comparison.stderr
@@ -1,136 +1,399 @@
error: used `assert_eq!` with a literal bool
- --> $DIR/bool_assert_comparison.rs:69:5
+ --> $DIR/bool_assert_comparison.rs:89:5
|
LL | assert_eq!("a".is_empty(), false);
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `assert!(..)`
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: `-D clippy::bool-assert-comparison` implied by `-D warnings`
+help: replace it with `assert!(..)`
+ |
+LL - assert_eq!("a".is_empty(), false);
+LL + assert!(!"a".is_empty());
+ |
error: used `assert_eq!` with a literal bool
- --> $DIR/bool_assert_comparison.rs:70:5
+ --> $DIR/bool_assert_comparison.rs:90:5
|
LL | assert_eq!("".is_empty(), true);
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `assert!(..)`
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: replace it with `assert!(..)`
+ |
+LL - assert_eq!("".is_empty(), true);
+LL + assert!("".is_empty());
+ |
error: used `assert_eq!` with a literal bool
- --> $DIR/bool_assert_comparison.rs:71:5
+ --> $DIR/bool_assert_comparison.rs:91:5
|
LL | assert_eq!(true, "".is_empty());
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `assert!(..)`
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: replace it with `assert!(..)`
+ |
+LL - assert_eq!(true, "".is_empty());
+LL + assert!("".is_empty());
+ |
error: used `assert_eq!` with a literal bool
- --> $DIR/bool_assert_comparison.rs:76:5
+ --> $DIR/bool_assert_comparison.rs:96:5
|
LL | assert_eq!(b, true);
- | ^^^^^^^^^^^^^^^^^^^ help: replace it with: `assert!(..)`
+ | ^^^^^^^^^^^^^^^^^^^
+ |
+help: replace it with `assert!(..)`
+ |
+LL - assert_eq!(b, true);
+LL + assert!(b);
+ |
error: used `assert_ne!` with a literal bool
- --> $DIR/bool_assert_comparison.rs:79:5
+ --> $DIR/bool_assert_comparison.rs:99:5
|
LL | assert_ne!("a".is_empty(), false);
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `assert!(..)`
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: replace it with `assert!(..)`
+ |
+LL - assert_ne!("a".is_empty(), false);
+LL + assert!("a".is_empty());
+ |
error: used `assert_ne!` with a literal bool
- --> $DIR/bool_assert_comparison.rs:80:5
+ --> $DIR/bool_assert_comparison.rs:100:5
|
LL | assert_ne!("".is_empty(), true);
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `assert!(..)`
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: replace it with `assert!(..)`
+ |
+LL - assert_ne!("".is_empty(), true);
+LL + assert!(!"".is_empty());
+ |
error: used `assert_ne!` with a literal bool
- --> $DIR/bool_assert_comparison.rs:81:5
+ --> $DIR/bool_assert_comparison.rs:101:5
|
LL | assert_ne!(true, "".is_empty());
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `assert!(..)`
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: replace it with `assert!(..)`
+ |
+LL - assert_ne!(true, "".is_empty());
+LL + assert!(!"".is_empty());
+ |
error: used `assert_ne!` with a literal bool
- --> $DIR/bool_assert_comparison.rs:86:5
+ --> $DIR/bool_assert_comparison.rs:106:5
|
LL | assert_ne!(b, true);
- | ^^^^^^^^^^^^^^^^^^^ help: replace it with: `assert!(..)`
+ | ^^^^^^^^^^^^^^^^^^^
+ |
+help: replace it with `assert!(..)`
+ |
+LL - assert_ne!(b, true);
+LL + assert!(!b);
+ |
error: used `debug_assert_eq!` with a literal bool
- --> $DIR/bool_assert_comparison.rs:89:5
+ --> $DIR/bool_assert_comparison.rs:109:5
|
LL | debug_assert_eq!("a".is_empty(), false);
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `debug_assert!(..)`
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: replace it with `debug_assert!(..)`
+ |
+LL - debug_assert_eq!("a".is_empty(), false);
+LL + debug_assert!(!"a".is_empty());
+ |
error: used `debug_assert_eq!` with a literal bool
- --> $DIR/bool_assert_comparison.rs:90:5
+ --> $DIR/bool_assert_comparison.rs:110:5
|
LL | debug_assert_eq!("".is_empty(), true);
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `debug_assert!(..)`
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: replace it with `debug_assert!(..)`
+ |
+LL - debug_assert_eq!("".is_empty(), true);
+LL + debug_assert!("".is_empty());
+ |
error: used `debug_assert_eq!` with a literal bool
- --> $DIR/bool_assert_comparison.rs:91:5
+ --> $DIR/bool_assert_comparison.rs:111:5
|
LL | debug_assert_eq!(true, "".is_empty());
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `debug_assert!(..)`
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: replace it with `debug_assert!(..)`
+ |
+LL - debug_assert_eq!(true, "".is_empty());
+LL + debug_assert!("".is_empty());
+ |
error: used `debug_assert_eq!` with a literal bool
- --> $DIR/bool_assert_comparison.rs:96:5
+ --> $DIR/bool_assert_comparison.rs:116:5
|
LL | debug_assert_eq!(b, true);
- | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `debug_assert!(..)`
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: replace it with `debug_assert!(..)`
+ |
+LL - debug_assert_eq!(b, true);
+LL + debug_assert!(b);
+ |
error: used `debug_assert_ne!` with a literal bool
- --> $DIR/bool_assert_comparison.rs:99:5
+ --> $DIR/bool_assert_comparison.rs:119:5
|
LL | debug_assert_ne!("a".is_empty(), false);
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `debug_assert!(..)`
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: replace it with `debug_assert!(..)`
+ |
+LL - debug_assert_ne!("a".is_empty(), false);
+LL + debug_assert!("a".is_empty());
+ |
error: used `debug_assert_ne!` with a literal bool
- --> $DIR/bool_assert_comparison.rs:100:5
+ --> $DIR/bool_assert_comparison.rs:120:5
|
LL | debug_assert_ne!("".is_empty(), true);
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `debug_assert!(..)`
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: replace it with `debug_assert!(..)`
+ |
+LL - debug_assert_ne!("".is_empty(), true);
+LL + debug_assert!(!"".is_empty());
+ |
error: used `debug_assert_ne!` with a literal bool
- --> $DIR/bool_assert_comparison.rs:101:5
+ --> $DIR/bool_assert_comparison.rs:121:5
|
LL | debug_assert_ne!(true, "".is_empty());
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `debug_assert!(..)`
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: replace it with `debug_assert!(..)`
+ |
+LL - debug_assert_ne!(true, "".is_empty());
+LL + debug_assert!(!"".is_empty());
+ |
error: used `debug_assert_ne!` with a literal bool
- --> $DIR/bool_assert_comparison.rs:106:5
+ --> $DIR/bool_assert_comparison.rs:126:5
|
LL | debug_assert_ne!(b, true);
- | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `debug_assert!(..)`
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: replace it with `debug_assert!(..)`
+ |
+LL - debug_assert_ne!(b, true);
+LL + debug_assert!(!b);
+ |
error: used `assert_eq!` with a literal bool
- --> $DIR/bool_assert_comparison.rs:111:5
+ --> $DIR/bool_assert_comparison.rs:131:5
|
LL | assert_eq!("a".is_empty(), false, "tadam {}", 1);
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `assert!(..)`
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: replace it with `assert!(..)`
+ |
+LL - assert_eq!("a".is_empty(), false, "tadam {}", 1);
+LL + assert!(!"a".is_empty(), "tadam {}", 1);
+ |
error: used `assert_eq!` with a literal bool
- --> $DIR/bool_assert_comparison.rs:112:5
+ --> $DIR/bool_assert_comparison.rs:132:5
|
LL | assert_eq!("a".is_empty(), false, "tadam {}", true);
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `assert!(..)`
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: replace it with `assert!(..)`
+ |
+LL - assert_eq!("a".is_empty(), false, "tadam {}", true);
+LL + assert!(!"a".is_empty(), "tadam {}", true);
+ |
error: used `assert_eq!` with a literal bool
- --> $DIR/bool_assert_comparison.rs:113:5
+ --> $DIR/bool_assert_comparison.rs:133:5
|
LL | assert_eq!(false, "a".is_empty(), "tadam {}", true);
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `assert!(..)`
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: replace it with `assert!(..)`
+ |
+LL - assert_eq!(false, "a".is_empty(), "tadam {}", true);
+LL + assert!(!"a".is_empty(), "tadam {}", true);
+ |
error: used `debug_assert_eq!` with a literal bool
- --> $DIR/bool_assert_comparison.rs:118:5
+ --> $DIR/bool_assert_comparison.rs:138:5
|
LL | debug_assert_eq!("a".is_empty(), false, "tadam {}", 1);
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `debug_assert!(..)`
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: replace it with `debug_assert!(..)`
+ |
+LL - debug_assert_eq!("a".is_empty(), false, "tadam {}", 1);
+LL + debug_assert!(!"a".is_empty(), "tadam {}", 1);
+ |
error: used `debug_assert_eq!` with a literal bool
- --> $DIR/bool_assert_comparison.rs:119:5
+ --> $DIR/bool_assert_comparison.rs:139:5
|
LL | debug_assert_eq!("a".is_empty(), false, "tadam {}", true);
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `debug_assert!(..)`
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: replace it with `debug_assert!(..)`
+ |
+LL - debug_assert_eq!("a".is_empty(), false, "tadam {}", true);
+LL + debug_assert!(!"a".is_empty(), "tadam {}", true);
+ |
error: used `debug_assert_eq!` with a literal bool
- --> $DIR/bool_assert_comparison.rs:120:5
+ --> $DIR/bool_assert_comparison.rs:140:5
|
LL | debug_assert_eq!(false, "a".is_empty(), "tadam {}", true);
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `debug_assert!(..)`
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: replace it with `debug_assert!(..)`
+ |
+LL - debug_assert_eq!(false, "a".is_empty(), "tadam {}", true);
+LL + debug_assert!(!"a".is_empty(), "tadam {}", true);
+ |
+
+error: used `assert_eq!` with a literal bool
+ --> $DIR/bool_assert_comparison.rs:143:5
+ |
+LL | assert_eq!(a!(), true);
+ | ^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: replace it with `assert!(..)`
+ |
+LL - assert_eq!(a!(), true);
+LL + assert!(a!());
+ |
+
+error: used `assert_eq!` with a literal bool
+ --> $DIR/bool_assert_comparison.rs:144:5
+ |
+LL | assert_eq!(true, b!());
+ | ^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: replace it with `assert!(..)`
+ |
+LL - assert_eq!(true, b!());
+LL + assert!(b!());
+ |
+
+error: used `debug_assert_eq!` with a literal bool
+ --> $DIR/bool_assert_comparison.rs:148:5
+ |
+LL | renamed!(b, true);
+ | ^^^^^^^^^^^^^^^^^
+ |
+help: replace it with `debug_assert!(..)`
+ |
+LL - renamed!(b, true);
+LL + debug_assert!(b);
+ |
+
+error: used `assert_eq!` with a literal bool
+ --> $DIR/bool_assert_comparison.rs:162:5
+ |
+LL | assert_eq!("".is_empty(), true);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: replace it with `assert!(..)`
+ |
+LL - assert_eq!("".is_empty(), true);
+LL + assert!("".is_empty());
+ |
+
+error: used `assert_ne!` with a literal bool
+ --> $DIR/bool_assert_comparison.rs:163:5
+ |
+LL | assert_ne!("".is_empty(), false);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: replace it with `assert!(..)`
+ |
+LL - assert_ne!("".is_empty(), false);
+LL + assert!("".is_empty());
+ |
+
+error: used `assert_ne!` with a literal bool
+ --> $DIR/bool_assert_comparison.rs:164:5
+ |
+LL | assert_ne!("requires negation".is_empty(), true);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: replace it with `assert!(..)`
+ |
+LL - assert_ne!("requires negation".is_empty(), true);
+LL + assert!(!"requires negation".is_empty());
+ |
+
+error: used `assert_eq!` with a literal bool
+ --> $DIR/bool_assert_comparison.rs:165:5
+ |
+LL | assert_eq!("requires negation".is_empty(), false);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: replace it with `assert!(..)`
+ |
+LL - assert_eq!("requires negation".is_empty(), false);
+LL + assert!(!"requires negation".is_empty());
+ |
+
+error: used `debug_assert_eq!` with a literal bool
+ --> $DIR/bool_assert_comparison.rs:167:5
+ |
+LL | debug_assert_eq!("".is_empty(), true);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: replace it with `debug_assert!(..)`
+ |
+LL - debug_assert_eq!("".is_empty(), true);
+LL + debug_assert!("".is_empty());
+ |
+
+error: used `debug_assert_ne!` with a literal bool
+ --> $DIR/bool_assert_comparison.rs:168:5
+ |
+LL | debug_assert_ne!("".is_empty(), false);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: replace it with `debug_assert!(..)`
+ |
+LL - debug_assert_ne!("".is_empty(), false);
+LL + debug_assert!("".is_empty());
+ |
+
+error: used `debug_assert_ne!` with a literal bool
+ --> $DIR/bool_assert_comparison.rs:169:5
+ |
+LL | debug_assert_ne!("requires negation".is_empty(), true);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: replace it with `debug_assert!(..)`
+ |
+LL - debug_assert_ne!("requires negation".is_empty(), true);
+LL + debug_assert!(!"requires negation".is_empty());
+ |
+
+error: used `debug_assert_eq!` with a literal bool
+ --> $DIR/bool_assert_comparison.rs:170:5
+ |
+LL | debug_assert_eq!("requires negation".is_empty(), false);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: replace it with `debug_assert!(..)`
+ |
+LL - debug_assert_eq!("requires negation".is_empty(), false);
+LL + debug_assert!(!"requires negation".is_empty());
+ |
-error: aborting due to 22 previous errors
+error: aborting due to 33 previous errors
diff --git a/src/tools/clippy/tests/ui/box_default.fixed b/src/tools/clippy/tests/ui/box_default.fixed
index 7e9f074fd..59c0baf87 100644
--- a/src/tools/clippy/tests/ui/box_default.fixed
+++ b/src/tools/clippy/tests/ui/box_default.fixed
@@ -33,6 +33,7 @@ fn main() {
let _vec4: Box<_> = Box::<Vec<bool>>::default();
let _more = ret_ty_fn();
call_ty_fn(Box::default());
+ issue_10381();
}
fn ret_ty_fn() -> Box<bool> {
@@ -65,3 +66,20 @@ fn issue_10089() {
let _ = Box::<WeirdPathed>::default();
};
}
+
+fn issue_10381() {
+ #[derive(Default)]
+ pub struct Foo {}
+ pub trait Bar {}
+ impl Bar for Foo {}
+
+ fn maybe_get_bar(i: u32) -> Option<Box<dyn Bar>> {
+ if i % 2 == 0 {
+ Some(Box::<Foo>::default())
+ } else {
+ None
+ }
+ }
+
+ assert!(maybe_get_bar(2).is_some());
+}
diff --git a/src/tools/clippy/tests/ui/box_default.rs b/src/tools/clippy/tests/ui/box_default.rs
index 5c8d0b835..f7d832193 100644
--- a/src/tools/clippy/tests/ui/box_default.rs
+++ b/src/tools/clippy/tests/ui/box_default.rs
@@ -33,6 +33,7 @@ fn main() {
let _vec4: Box<_> = Box::new(Vec::from([false; 0]));
let _more = ret_ty_fn();
call_ty_fn(Box::new(u8::default()));
+ issue_10381();
}
fn ret_ty_fn() -> Box<bool> {
@@ -65,3 +66,20 @@ fn issue_10089() {
let _ = Box::new(WeirdPathed::default());
};
}
+
+fn issue_10381() {
+ #[derive(Default)]
+ pub struct Foo {}
+ pub trait Bar {}
+ impl Bar for Foo {}
+
+ fn maybe_get_bar(i: u32) -> Option<Box<dyn Bar>> {
+ if i % 2 == 0 {
+ Some(Box::new(Foo::default()))
+ } else {
+ None
+ }
+ }
+
+ assert!(maybe_get_bar(2).is_some());
+}
diff --git a/src/tools/clippy/tests/ui/box_default.stderr b/src/tools/clippy/tests/ui/box_default.stderr
index 249eb340f..78e17b9f0 100644
--- a/src/tools/clippy/tests/ui/box_default.stderr
+++ b/src/tools/clippy/tests/ui/box_default.stderr
@@ -73,22 +73,28 @@ LL | call_ty_fn(Box::new(u8::default()));
| ^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Box::default()`
error: `Box::new(_)` of default value
- --> $DIR/box_default.rs:39:5
+ --> $DIR/box_default.rs:40:5
|
LL | Box::new(bool::default())
| ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Box::<bool>::default()`
error: `Box::new(_)` of default value
- --> $DIR/box_default.rs:56:28
+ --> $DIR/box_default.rs:57:28
|
LL | let _: Box<dyn Read> = Box::new(ImplementsDefault::default());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Box::<ImplementsDefault>::default()`
error: `Box::new(_)` of default value
- --> $DIR/box_default.rs:65:17
+ --> $DIR/box_default.rs:66:17
|
LL | let _ = Box::new(WeirdPathed::default());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Box::<WeirdPathed>::default()`
-error: aborting due to 15 previous errors
+error: `Box::new(_)` of default value
+ --> $DIR/box_default.rs:78:18
+ |
+LL | Some(Box::new(Foo::default()))
+ | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Box::<Foo>::default()`
+
+error: aborting due to 16 previous errors
diff --git a/src/tools/clippy/tests/ui/bytes_nth.fixed b/src/tools/clippy/tests/ui/bytes_nth.fixed
index b1fb2e16b..a35c679af 100644
--- a/src/tools/clippy/tests/ui/bytes_nth.fixed
+++ b/src/tools/clippy/tests/ui/bytes_nth.fixed
@@ -5,7 +5,7 @@
fn main() {
let s = String::from("String");
- let _ = s.as_bytes().get(3);
- let _ = &s.as_bytes().get(3);
- let _ = s[..].as_bytes().get(3);
+ let _ = s.as_bytes().get(3).copied();
+ let _ = &s.as_bytes()[3];
+ let _ = s[..].as_bytes().get(3).copied();
}
diff --git a/src/tools/clippy/tests/ui/bytes_nth.rs b/src/tools/clippy/tests/ui/bytes_nth.rs
index 034c54e6a..1ecffea53 100644
--- a/src/tools/clippy/tests/ui/bytes_nth.rs
+++ b/src/tools/clippy/tests/ui/bytes_nth.rs
@@ -6,6 +6,6 @@
fn main() {
let s = String::from("String");
let _ = s.bytes().nth(3);
- let _ = &s.bytes().nth(3);
+ let _ = &s.bytes().nth(3).unwrap();
let _ = s[..].bytes().nth(3);
}
diff --git a/src/tools/clippy/tests/ui/bytes_nth.stderr b/src/tools/clippy/tests/ui/bytes_nth.stderr
index 9851d4791..e8b150278 100644
--- a/src/tools/clippy/tests/ui/bytes_nth.stderr
+++ b/src/tools/clippy/tests/ui/bytes_nth.stderr
@@ -2,21 +2,21 @@ error: called `.bytes().nth()` on a `String`
--> $DIR/bytes_nth.rs:8:13
|
LL | let _ = s.bytes().nth(3);
- | ^^^^^^^^^^^^^^^^ help: try: `s.as_bytes().get(3)`
+ | ^^^^^^^^^^^^^^^^ help: try: `s.as_bytes().get(3).copied()`
|
= note: `-D clippy::bytes-nth` implied by `-D warnings`
-error: called `.bytes().nth()` on a `String`
+error: called `.bytes().nth().unwrap()` on a `String`
--> $DIR/bytes_nth.rs:9:14
|
-LL | let _ = &s.bytes().nth(3);
- | ^^^^^^^^^^^^^^^^ help: try: `s.as_bytes().get(3)`
+LL | let _ = &s.bytes().nth(3).unwrap();
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `s.as_bytes()[3]`
error: called `.bytes().nth()` on a `str`
--> $DIR/bytes_nth.rs:10:13
|
LL | let _ = s[..].bytes().nth(3);
- | ^^^^^^^^^^^^^^^^^^^^ help: try: `s[..].as_bytes().get(3)`
+ | ^^^^^^^^^^^^^^^^^^^^ help: try: `s[..].as_bytes().get(3).copied()`
error: aborting due to 3 previous errors
diff --git a/src/tools/clippy/tests/ui/cast.rs b/src/tools/clippy/tests/ui/cast.rs
index e6031e9ad..8b2673c2a 100644
--- a/src/tools/clippy/tests/ui/cast.rs
+++ b/src/tools/clippy/tests/ui/cast.rs
@@ -28,6 +28,7 @@ fn main() {
1i32 as u8;
1f64 as isize;
1f64 as usize;
+ 1f32 as u32 as u16;
// Test clippy::cast_possible_wrap
1u8 as i8;
1u16 as i16;
diff --git a/src/tools/clippy/tests/ui/cast.stderr b/src/tools/clippy/tests/ui/cast.stderr
index 0c63b4af3..451078de2 100644
--- a/src/tools/clippy/tests/ui/cast.stderr
+++ b/src/tools/clippy/tests/ui/cast.stderr
@@ -42,13 +42,24 @@ error: casting `f32` to `i32` may truncate the value
LL | 1f32 as i32;
| ^^^^^^^^^^^
|
+ = help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ...
= note: `-D clippy::cast-possible-truncation` implied by `-D warnings`
+help: ... or use `try_from` and handle the error accordingly
+ |
+LL | i32::try_from(1f32);
+ | ~~~~~~~~~~~~~~~~~~~
error: casting `f32` to `u32` may truncate the value
--> $DIR/cast.rs:25:5
|
LL | 1f32 as u32;
| ^^^^^^^^^^^
+ |
+ = help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ...
+help: ... or use `try_from` and handle the error accordingly
+ |
+LL | u32::try_from(1f32);
+ | ~~~~~~~~~~~~~~~~~~~
error: casting `f32` to `u32` may lose the sign of the value
--> $DIR/cast.rs:25:5
@@ -63,30 +74,60 @@ error: casting `f64` to `f32` may truncate the value
|
LL | 1f64 as f32;
| ^^^^^^^^^^^
+ |
+ = help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ...
+help: ... or use `try_from` and handle the error accordingly
+ |
+LL | f32::try_from(1f64);
+ | ~~~~~~~~~~~~~~~~~~~
error: casting `i32` to `i8` may truncate the value
--> $DIR/cast.rs:27:5
|
LL | 1i32 as i8;
| ^^^^^^^^^^
+ |
+ = help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ...
+help: ... or use `try_from` and handle the error accordingly
+ |
+LL | i8::try_from(1i32);
+ | ~~~~~~~~~~~~~~~~~~
error: casting `i32` to `u8` may truncate the value
--> $DIR/cast.rs:28:5
|
LL | 1i32 as u8;
| ^^^^^^^^^^
+ |
+ = help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ...
+help: ... or use `try_from` and handle the error accordingly
+ |
+LL | u8::try_from(1i32);
+ | ~~~~~~~~~~~~~~~~~~
error: casting `f64` to `isize` may truncate the value
--> $DIR/cast.rs:29:5
|
LL | 1f64 as isize;
| ^^^^^^^^^^^^^
+ |
+ = help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ...
+help: ... or use `try_from` and handle the error accordingly
+ |
+LL | isize::try_from(1f64);
+ | ~~~~~~~~~~~~~~~~~~~~~
error: casting `f64` to `usize` may truncate the value
--> $DIR/cast.rs:30:5
|
LL | 1f64 as usize;
| ^^^^^^^^^^^^^
+ |
+ = help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ...
+help: ... or use `try_from` and handle the error accordingly
+ |
+LL | usize::try_from(1f64);
+ | ~~~~~~~~~~~~~~~~~~~~~
error: casting `f64` to `usize` may lose the sign of the value
--> $DIR/cast.rs:30:5
@@ -94,8 +135,38 @@ error: casting `f64` to `usize` may lose the sign of the value
LL | 1f64 as usize;
| ^^^^^^^^^^^^^
+error: casting `u32` to `u16` may truncate the value
+ --> $DIR/cast.rs:31:5
+ |
+LL | 1f32 as u32 as u16;
+ | ^^^^^^^^^^^^^^^^^^
+ |
+ = help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ...
+help: ... or use `try_from` and handle the error accordingly
+ |
+LL | u16::try_from(1f32 as u32);
+ | ~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+error: casting `f32` to `u32` may truncate the value
+ --> $DIR/cast.rs:31:5
+ |
+LL | 1f32 as u32 as u16;
+ | ^^^^^^^^^^^
+ |
+ = help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ...
+help: ... or use `try_from` and handle the error accordingly
+ |
+LL | u32::try_from(1f32) as u16;
+ | ~~~~~~~~~~~~~~~~~~~
+
+error: casting `f32` to `u32` may lose the sign of the value
+ --> $DIR/cast.rs:31:5
+ |
+LL | 1f32 as u32 as u16;
+ | ^^^^^^^^^^^
+
error: casting `u8` to `i8` may wrap around the value
- --> $DIR/cast.rs:32:5
+ --> $DIR/cast.rs:33:5
|
LL | 1u8 as i8;
| ^^^^^^^^^
@@ -103,61 +174,79 @@ LL | 1u8 as i8;
= note: `-D clippy::cast-possible-wrap` implied by `-D warnings`
error: casting `u16` to `i16` may wrap around the value
- --> $DIR/cast.rs:33:5
+ --> $DIR/cast.rs:34:5
|
LL | 1u16 as i16;
| ^^^^^^^^^^^
error: casting `u32` to `i32` may wrap around the value
- --> $DIR/cast.rs:34:5
+ --> $DIR/cast.rs:35:5
|
LL | 1u32 as i32;
| ^^^^^^^^^^^
error: casting `u64` to `i64` may wrap around the value
- --> $DIR/cast.rs:35:5
+ --> $DIR/cast.rs:36:5
|
LL | 1u64 as i64;
| ^^^^^^^^^^^
error: casting `usize` to `isize` may wrap around the value
- --> $DIR/cast.rs:36:5
+ --> $DIR/cast.rs:37:5
|
LL | 1usize as isize;
| ^^^^^^^^^^^^^^^
error: casting `i32` to `u32` may lose the sign of the value
- --> $DIR/cast.rs:39:5
+ --> $DIR/cast.rs:40:5
|
LL | -1i32 as u32;
| ^^^^^^^^^^^^
error: casting `isize` to `usize` may lose the sign of the value
- --> $DIR/cast.rs:41:5
+ --> $DIR/cast.rs:42:5
|
LL | -1isize as usize;
| ^^^^^^^^^^^^^^^^
error: casting `i64` to `i8` may truncate the value
- --> $DIR/cast.rs:108:5
+ --> $DIR/cast.rs:109:5
|
LL | (-99999999999i64).min(1) as i8; // should be linted because signed
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ...
+help: ... or use `try_from` and handle the error accordingly
+ |
+LL | i8::try_from((-99999999999i64).min(1)); // should be linted because signed
+ | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
error: casting `u64` to `u8` may truncate the value
- --> $DIR/cast.rs:120:5
+ --> $DIR/cast.rs:121:5
|
LL | 999999u64.clamp(0, 256) as u8; // should still be linted
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ...
+help: ... or use `try_from` and handle the error accordingly
+ |
+LL | u8::try_from(999999u64.clamp(0, 256)); // should still be linted
+ | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
error: casting `main::E2` to `u8` may truncate the value
- --> $DIR/cast.rs:141:21
+ --> $DIR/cast.rs:142:21
|
LL | let _ = self as u8;
| ^^^^^^^^^^
+ |
+ = help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ...
+help: ... or use `try_from` and handle the error accordingly
+ |
+LL | let _ = u8::try_from(self);
+ | ~~~~~~~~~~~~~~~~~~
error: casting `main::E2::B` to `u8` will truncate the value
- --> $DIR/cast.rs:142:21
+ --> $DIR/cast.rs:143:21
|
LL | let _ = Self::B as u8;
| ^^^^^^^^^^^^^
@@ -165,46 +254,82 @@ LL | let _ = Self::B as u8;
= note: `-D clippy::cast-enum-truncation` implied by `-D warnings`
error: casting `main::E5` to `i8` may truncate the value
- --> $DIR/cast.rs:178:21
+ --> $DIR/cast.rs:179:21
|
LL | let _ = self as i8;
| ^^^^^^^^^^
+ |
+ = help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ...
+help: ... or use `try_from` and handle the error accordingly
+ |
+LL | let _ = i8::try_from(self);
+ | ~~~~~~~~~~~~~~~~~~
error: casting `main::E5::A` to `i8` will truncate the value
- --> $DIR/cast.rs:179:21
+ --> $DIR/cast.rs:180:21
|
LL | let _ = Self::A as i8;
| ^^^^^^^^^^^^^
error: casting `main::E6` to `i16` may truncate the value
- --> $DIR/cast.rs:193:21
+ --> $DIR/cast.rs:194:21
|
LL | let _ = self as i16;
| ^^^^^^^^^^^
+ |
+ = help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ...
+help: ... or use `try_from` and handle the error accordingly
+ |
+LL | let _ = i16::try_from(self);
+ | ~~~~~~~~~~~~~~~~~~~
error: casting `main::E7` to `usize` may truncate the value on targets with 32-bit wide pointers
- --> $DIR/cast.rs:208:21
+ --> $DIR/cast.rs:209:21
|
LL | let _ = self as usize;
| ^^^^^^^^^^^^^
+ |
+ = help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ...
+help: ... or use `try_from` and handle the error accordingly
+ |
+LL | let _ = usize::try_from(self);
+ | ~~~~~~~~~~~~~~~~~~~~~
error: casting `main::E10` to `u16` may truncate the value
- --> $DIR/cast.rs:249:21
+ --> $DIR/cast.rs:250:21
|
LL | let _ = self as u16;
| ^^^^^^^^^^^
+ |
+ = help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ...
+help: ... or use `try_from` and handle the error accordingly
+ |
+LL | let _ = u16::try_from(self);
+ | ~~~~~~~~~~~~~~~~~~~
error: casting `u32` to `u8` may truncate the value
- --> $DIR/cast.rs:257:13
+ --> $DIR/cast.rs:258:13
|
LL | let c = (q >> 16) as u8;
| ^^^^^^^^^^^^^^^
+ |
+ = help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ...
+help: ... or use `try_from` and handle the error accordingly
+ |
+LL | let c = u8::try_from((q >> 16));
+ | ~~~~~~~~~~~~~~~~~~~~~~~
error: casting `u32` to `u8` may truncate the value
- --> $DIR/cast.rs:260:13
+ --> $DIR/cast.rs:261:13
|
LL | let c = (q / 1000) as u8;
| ^^^^^^^^^^^^^^^^
+ |
+ = help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ...
+help: ... or use `try_from` and handle the error accordingly
+ |
+LL | let c = u8::try_from((q / 1000));
+ | ~~~~~~~~~~~~~~~~~~~~~~~~
-error: aborting due to 33 previous errors
+error: aborting due to 36 previous errors
diff --git a/src/tools/clippy/tests/ui/cast_size.stderr b/src/tools/clippy/tests/ui/cast_size.stderr
index 95552f2e2..6d2d49d9e 100644
--- a/src/tools/clippy/tests/ui/cast_size.stderr
+++ b/src/tools/clippy/tests/ui/cast_size.stderr
@@ -4,7 +4,12 @@ error: casting `isize` to `i8` may truncate the value
LL | 1isize as i8;
| ^^^^^^^^^^^^
|
+ = help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ...
= note: `-D clippy::cast-possible-truncation` implied by `-D warnings`
+help: ... or use `try_from` and handle the error accordingly
+ |
+LL | i8::try_from(1isize);
+ | ~~~~~~~~~~~~~~~~~~~~
error: casting `isize` to `f64` causes a loss of precision on targets with 64-bit wide pointers (`isize` is 64 bits wide, but `f64`'s mantissa is only 52 bits wide)
--> $DIR/cast_size.rs:15:5
@@ -37,24 +42,48 @@ error: casting `isize` to `i32` may truncate the value on targets with 64-bit wi
|
LL | 1isize as i32;
| ^^^^^^^^^^^^^
+ |
+ = help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ...
+help: ... or use `try_from` and handle the error accordingly
+ |
+LL | i32::try_from(1isize);
+ | ~~~~~~~~~~~~~~~~~~~~~
error: casting `isize` to `u32` may truncate the value on targets with 64-bit wide pointers
--> $DIR/cast_size.rs:20:5
|
LL | 1isize as u32;
| ^^^^^^^^^^^^^
+ |
+ = help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ...
+help: ... or use `try_from` and handle the error accordingly
+ |
+LL | u32::try_from(1isize);
+ | ~~~~~~~~~~~~~~~~~~~~~
error: casting `usize` to `u32` may truncate the value on targets with 64-bit wide pointers
--> $DIR/cast_size.rs:21:5
|
LL | 1usize as u32;
| ^^^^^^^^^^^^^
+ |
+ = help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ...
+help: ... or use `try_from` and handle the error accordingly
+ |
+LL | u32::try_from(1usize);
+ | ~~~~~~~~~~~~~~~~~~~~~
error: casting `usize` to `i32` may truncate the value on targets with 64-bit wide pointers
--> $DIR/cast_size.rs:22:5
|
LL | 1usize as i32;
| ^^^^^^^^^^^^^
+ |
+ = help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ...
+help: ... or use `try_from` and handle the error accordingly
+ |
+LL | i32::try_from(1usize);
+ | ~~~~~~~~~~~~~~~~~~~~~
error: casting `usize` to `i32` may wrap around the value on targets with 32-bit wide pointers
--> $DIR/cast_size.rs:22:5
@@ -69,18 +98,36 @@ error: casting `i64` to `isize` may truncate the value on targets with 32-bit wi
|
LL | 1i64 as isize;
| ^^^^^^^^^^^^^
+ |
+ = help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ...
+help: ... or use `try_from` and handle the error accordingly
+ |
+LL | isize::try_from(1i64);
+ | ~~~~~~~~~~~~~~~~~~~~~
error: casting `i64` to `usize` may truncate the value on targets with 32-bit wide pointers
--> $DIR/cast_size.rs:25:5
|
LL | 1i64 as usize;
| ^^^^^^^^^^^^^
+ |
+ = help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ...
+help: ... or use `try_from` and handle the error accordingly
+ |
+LL | usize::try_from(1i64);
+ | ~~~~~~~~~~~~~~~~~~~~~
error: casting `u64` to `isize` may truncate the value on targets with 32-bit wide pointers
--> $DIR/cast_size.rs:26:5
|
LL | 1u64 as isize;
| ^^^^^^^^^^^^^
+ |
+ = help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ...
+help: ... or use `try_from` and handle the error accordingly
+ |
+LL | isize::try_from(1u64);
+ | ~~~~~~~~~~~~~~~~~~~~~
error: casting `u64` to `isize` may wrap around the value on targets with 64-bit wide pointers
--> $DIR/cast_size.rs:26:5
@@ -93,6 +140,12 @@ error: casting `u64` to `usize` may truncate the value on targets with 32-bit wi
|
LL | 1u64 as usize;
| ^^^^^^^^^^^^^
+ |
+ = help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ...
+help: ... or use `try_from` and handle the error accordingly
+ |
+LL | usize::try_from(1u64);
+ | ~~~~~~~~~~~~~~~~~~~~~
error: casting `u32` to `isize` may wrap around the value on targets with 32-bit wide pointers
--> $DIR/cast_size.rs:28:5
diff --git a/src/tools/clippy/tests/ui/crashes/ice-2774.stderr b/src/tools/clippy/tests/ui/crashes/ice-2774.stderr
index 1f26c7f4d..c5ea0b16d 100644
--- a/src/tools/clippy/tests/ui/crashes/ice-2774.stderr
+++ b/src/tools/clippy/tests/ui/crashes/ice-2774.stderr
@@ -5,6 +5,11 @@ LL | pub fn add_barfoos_to_foos<'a>(bars: &HashSet<&'a Bar>) {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: `-D clippy::needless-lifetimes` implied by `-D warnings`
+help: elide the lifetimes
+ |
+LL - pub fn add_barfoos_to_foos<'a>(bars: &HashSet<&'a Bar>) {
+LL + pub fn add_barfoos_to_foos(bars: &HashSet<&Bar>) {
+ |
error: aborting due to previous error
diff --git a/src/tools/clippy/tests/ui/crashes/ice-rust-107877.rs b/src/tools/clippy/tests/ui/crashes/ice-rust-107877.rs
new file mode 100644
index 000000000..7f5bae60d
--- /dev/null
+++ b/src/tools/clippy/tests/ui/crashes/ice-rust-107877.rs
@@ -0,0 +1,17 @@
+#![allow(dead_code)]
+
+struct Foo;
+
+impl<'a> std::convert::TryFrom<&'a String> for Foo {
+ type Error = std::convert::Infallible;
+
+ fn try_from(_: &'a String) -> Result<Self, Self::Error> {
+ Ok(Foo)
+ }
+}
+
+fn find<E>(_: impl std::convert::TryInto<Foo, Error = E>) {}
+
+fn main() {
+ find(&String::new());
+}
diff --git a/src/tools/clippy/tests/ui/crashes/needless_lifetimes_impl_trait.stderr b/src/tools/clippy/tests/ui/crashes/needless_lifetimes_impl_trait.stderr
index 875d5ab4f..0b0e0ad26 100644
--- a/src/tools/clippy/tests/ui/crashes/needless_lifetimes_impl_trait.stderr
+++ b/src/tools/clippy/tests/ui/crashes/needless_lifetimes_impl_trait.stderr
@@ -9,6 +9,11 @@ note: the lint level is defined here
|
LL | #![deny(clippy::needless_lifetimes)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
+help: elide the lifetimes
+ |
+LL - fn baz<'a>(&'a self) -> impl Foo + 'a {
+LL + fn baz(&self) -> impl Foo + '_ {
+ |
error: aborting due to previous error
diff --git a/src/tools/clippy/tests/ui/crashes/needless_pass_by_value-w-late-bound.rs b/src/tools/clippy/tests/ui/crashes/needless_pass_by_value-w-late-bound.rs
new file mode 100644
index 000000000..dd3d8b8b6
--- /dev/null
+++ b/src/tools/clippy/tests/ui/crashes/needless_pass_by_value-w-late-bound.rs
@@ -0,0 +1,9 @@
+// https://github.com/rust-lang/rust/issues/107147
+
+#![warn(clippy::needless_pass_by_value)]
+
+struct Foo<'a>(&'a [(); 100]);
+
+fn test(x: Foo<'_>) {}
+
+fn main() {}
diff --git a/src/tools/clippy/tests/ui/crashes/needless_pass_by_value-w-late-bound.stderr b/src/tools/clippy/tests/ui/crashes/needless_pass_by_value-w-late-bound.stderr
new file mode 100644
index 000000000..7a0a64897
--- /dev/null
+++ b/src/tools/clippy/tests/ui/crashes/needless_pass_by_value-w-late-bound.stderr
@@ -0,0 +1,15 @@
+error: this argument is passed by value, but not consumed in the function body
+ --> $DIR/needless_pass_by_value-w-late-bound.rs:7:12
+ |
+LL | fn test(x: Foo<'_>) {}
+ | ^^^^^^^ help: consider taking a reference instead: `&Foo<'_>`
+ |
+help: consider marking this type as `Copy`
+ --> $DIR/needless_pass_by_value-w-late-bound.rs:5:1
+ |
+LL | struct Foo<'a>(&'a [(); 100]);
+ | ^^^^^^^^^^^^^^
+ = note: `-D clippy::needless-pass-by-value` implied by `-D warnings`
+
+error: aborting due to previous error
+
diff --git a/src/tools/clippy/tests/ui/doc/doc-fixable.fixed b/src/tools/clippy/tests/ui/doc/doc-fixable.fixed
index 747801b40..ecb0bf364 100644
--- a/src/tools/clippy/tests/ui/doc/doc-fixable.fixed
+++ b/src/tools/clippy/tests/ui/doc/doc-fixable.fixed
@@ -78,7 +78,7 @@ fn test_allowed() {
/// This test has [a `link_with_underscores`][chunked-example] inside it. See #823.
/// See also [the issue tracker](https://github.com/rust-lang/rust-clippy/search?q=clippy::doc_markdown&type=Issues)
/// on GitHub (which is a camel-cased word, but is OK). And here is another [inline link][inline_link].
-/// It can also be [`inline_link2`].
+/// It can also be [inline_link2]. A link to [StackOverflow](https://stackoverflow.com) is also acceptable.
///
/// [chunked-example]: https://en.wikipedia.org/wiki/Chunked_transfer_encoding#Example
/// [inline_link]: https://foobar
diff --git a/src/tools/clippy/tests/ui/doc/doc-fixable.rs b/src/tools/clippy/tests/ui/doc/doc-fixable.rs
index f3cf96615..11c48dd10 100644
--- a/src/tools/clippy/tests/ui/doc/doc-fixable.rs
+++ b/src/tools/clippy/tests/ui/doc/doc-fixable.rs
@@ -75,10 +75,10 @@ fn test_units() {
fn test_allowed() {
}
-/// This test has [a link_with_underscores][chunked-example] inside it. See #823.
+/// This test has [a `link_with_underscores`][chunked-example] inside it. See #823.
/// See also [the issue tracker](https://github.com/rust-lang/rust-clippy/search?q=clippy::doc_markdown&type=Issues)
/// on GitHub (which is a camel-cased word, but is OK). And here is another [inline link][inline_link].
-/// It can also be [inline_link2].
+/// It can also be [inline_link2]. A link to [StackOverflow](https://stackoverflow.com) is also acceptable.
///
/// [chunked-example]: https://en.wikipedia.org/wiki/Chunked_transfer_encoding#Example
/// [inline_link]: https://foobar
diff --git a/src/tools/clippy/tests/ui/doc/doc-fixable.stderr b/src/tools/clippy/tests/ui/doc/doc-fixable.stderr
index 40345370c..6c67c903c 100644
--- a/src/tools/clippy/tests/ui/doc/doc-fixable.stderr
+++ b/src/tools/clippy/tests/ui/doc/doc-fixable.stderr
@@ -143,28 +143,6 @@ LL | /// `be_sure_we_got_to_the_end_of_it`
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
error: item in documentation is missing backticks
- --> $DIR/doc-fixable.rs:78:22
- |
-LL | /// This test has [a link_with_underscores][chunked-example] inside it. See #823.
- | ^^^^^^^^^^^^^^^^^^^^^
- |
-help: try
- |
-LL | /// This test has [a `link_with_underscores`][chunked-example] inside it. See #823.
- | ~~~~~~~~~~~~~~~~~~~~~~~
-
-error: item in documentation is missing backticks
- --> $DIR/doc-fixable.rs:81:21
- |
-LL | /// It can also be [inline_link2].
- | ^^^^^^^^^^^^
- |
-help: try
- |
-LL | /// It can also be [`inline_link2`].
- | ~~~~~~~~~~~~~~
-
-error: item in documentation is missing backticks
--> $DIR/doc-fixable.rs:91:5
|
LL | /// be_sure_we_got_to_the_end_of_it
@@ -329,5 +307,5 @@ help: try
LL | /// An iterator over `mycrate::Collection`'s values.
| ~~~~~~~~~~~~~~~~~~~~~
-error: aborting due to 30 previous errors
+error: aborting due to 28 previous errors
diff --git a/src/tools/clippy/tests/ui/entry.fixed b/src/tools/clippy/tests/ui/entry.fixed
index 79c29c04e..dbe09e0ff 100644
--- a/src/tools/clippy/tests/ui/entry.fixed
+++ b/src/tools/clippy/tests/ui/entry.fixed
@@ -152,4 +152,18 @@ fn hash_map<K: Eq + Hash + Copy, V: Copy>(m: &mut HashMap<K, V>, m2: &mut HashMa
});
}
+// Issue 10331
+// do not suggest a bad expansion because the compiler unrolls the first
+// occurrence of the loop
+pub fn issue_10331() {
+ let mut m = HashMap::new();
+ let mut i = 0;
+ let mut x = 0;
+ while !m.contains_key(&x) {
+ m.insert(x, i);
+ i += 1;
+ x += 1;
+ }
+}
+
fn main() {}
diff --git a/src/tools/clippy/tests/ui/entry.rs b/src/tools/clippy/tests/ui/entry.rs
index 2d7985457..30fed34fc 100644
--- a/src/tools/clippy/tests/ui/entry.rs
+++ b/src/tools/clippy/tests/ui/entry.rs
@@ -156,4 +156,18 @@ fn hash_map<K: Eq + Hash + Copy, V: Copy>(m: &mut HashMap<K, V>, m2: &mut HashMa
}
}
+// Issue 10331
+// do not suggest a bad expansion because the compiler unrolls the first
+// occurrence of the loop
+pub fn issue_10331() {
+ let mut m = HashMap::new();
+ let mut i = 0;
+ let mut x = 0;
+ while !m.contains_key(&x) {
+ m.insert(x, i);
+ i += 1;
+ x += 1;
+ }
+}
+
fn main() {}
diff --git a/src/tools/clippy/tests/ui/explicit_auto_deref.fixed b/src/tools/clippy/tests/ui/explicit_auto_deref.fixed
index 475fae5e8..5d40c8504 100644
--- a/src/tools/clippy/tests/ui/explicit_auto_deref.fixed
+++ b/src/tools/clippy/tests/ui/explicit_auto_deref.fixed
@@ -269,6 +269,9 @@ fn main() {
trait WithAssoc {
type Assoc: ?Sized;
+ fn to_assoc(&self) -> &Self::Assoc {
+ panic!()
+ }
}
impl WithAssoc for String {
type Assoc = str;
@@ -281,4 +284,15 @@ fn main() {
// Issue #9901
fn takes_ref(_: &i32) {}
takes_ref(*Box::new(&0i32));
+
+ // Issue #10384
+ impl<'a> WithAssoc for &'a u32 {
+ type Assoc = dyn core::fmt::Display;
+ fn to_assoc(&self) -> &Self::Assoc {
+ *self
+ }
+ }
+ fn return_dyn_assoc<'a>(x: &'a &'a u32) -> &'a <&'a u32 as WithAssoc>::Assoc {
+ *x
+ }
}
diff --git a/src/tools/clippy/tests/ui/explicit_auto_deref.rs b/src/tools/clippy/tests/ui/explicit_auto_deref.rs
index c1894258f..79e03f4d7 100644
--- a/src/tools/clippy/tests/ui/explicit_auto_deref.rs
+++ b/src/tools/clippy/tests/ui/explicit_auto_deref.rs
@@ -269,6 +269,9 @@ fn main() {
trait WithAssoc {
type Assoc: ?Sized;
+ fn to_assoc(&self) -> &Self::Assoc {
+ panic!()
+ }
}
impl WithAssoc for String {
type Assoc = str;
@@ -281,4 +284,15 @@ fn main() {
// Issue #9901
fn takes_ref(_: &i32) {}
takes_ref(*Box::new(&0i32));
+
+ // Issue #10384
+ impl<'a> WithAssoc for &'a u32 {
+ type Assoc = dyn core::fmt::Display;
+ fn to_assoc(&self) -> &Self::Assoc {
+ *self
+ }
+ }
+ fn return_dyn_assoc<'a>(x: &'a &'a u32) -> &'a <&'a u32 as WithAssoc>::Assoc {
+ *x
+ }
}
diff --git a/src/tools/clippy/tests/ui/extra_unused_type_parameters.rs b/src/tools/clippy/tests/ui/extra_unused_type_parameters.rs
new file mode 100644
index 000000000..480174342
--- /dev/null
+++ b/src/tools/clippy/tests/ui/extra_unused_type_parameters.rs
@@ -0,0 +1,110 @@
+#![allow(unused, clippy::needless_lifetimes)]
+#![warn(clippy::extra_unused_type_parameters)]
+
+fn unused_ty<T>(x: u8) {
+ unimplemented!()
+}
+
+fn unused_multi<T, U>(x: u8) {
+ unimplemented!()
+}
+
+fn unused_with_lt<'a, T>(x: &'a u8) {
+ unimplemented!()
+}
+
+fn used_ty<T>(x: T, y: u8) {}
+
+fn used_ref<'a, T>(x: &'a T) {}
+
+fn used_ret<T: Default>(x: u8) -> T {
+ T::default()
+}
+
+fn unused_bounded<T: Default, U>(x: U) {
+ unimplemented!();
+}
+
+fn unused_where_clause<T, U>(x: U)
+where
+ T: Default,
+{
+ unimplemented!();
+}
+
+fn some_unused<A, B, C, D: Iterator<Item = (B, C)>, E>(b: B, c: C) {
+ unimplemented!();
+}
+
+fn used_opaque<A>(iter: impl Iterator<Item = A>) -> usize {
+ iter.count()
+}
+
+fn used_ret_opaque<A>() -> impl Iterator<Item = A> {
+ std::iter::empty()
+}
+
+fn used_vec_box<T>(x: Vec<Box<T>>) {}
+
+fn used_body<T: Default + ToString>() -> String {
+ T::default().to_string()
+}
+
+fn used_closure<T: Default + ToString>() -> impl Fn() {
+ || println!("{}", T::default().to_string())
+}
+
+struct S;
+
+impl S {
+ fn unused_ty_impl<T>(&self) {
+ unimplemented!()
+ }
+}
+
+// Don't lint on trait methods
+trait Foo {
+ fn bar<T>(&self);
+}
+
+impl Foo for S {
+ fn bar<T>(&self) {}
+}
+
+fn skip_index<A, Iter>(iter: Iter, index: usize) -> impl Iterator<Item = A>
+where
+ Iter: Iterator<Item = A>,
+{
+ iter.enumerate()
+ .filter_map(move |(i, a)| if i == index { None } else { Some(a) })
+}
+
+fn unused_opaque<A, B>(dummy: impl Default) {
+ unimplemented!()
+}
+
+mod unexported_trait_bounds {
+ mod private {
+ pub trait Private {}
+ }
+
+ fn priv_trait_bound<T: private::Private>() {
+ unimplemented!();
+ }
+
+ fn unused_with_priv_trait_bound<T: private::Private, U>() {
+ unimplemented!();
+ }
+}
+
+mod issue10319 {
+ fn assert_send<T: Send>() {}
+
+ fn assert_send_where<T>()
+ where
+ T: Send,
+ {
+ }
+}
+
+fn main() {}
diff --git a/src/tools/clippy/tests/ui/extra_unused_type_parameters.stderr b/src/tools/clippy/tests/ui/extra_unused_type_parameters.stderr
new file mode 100644
index 000000000..86c88fc9b
--- /dev/null
+++ b/src/tools/clippy/tests/ui/extra_unused_type_parameters.stderr
@@ -0,0 +1,75 @@
+error: type parameter goes unused in function definition
+ --> $DIR/extra_unused_type_parameters.rs:4:13
+ |
+LL | fn unused_ty<T>(x: u8) {
+ | ^^^
+ |
+ = help: consider removing the parameter
+ = note: `-D clippy::extra-unused-type-parameters` implied by `-D warnings`
+
+error: type parameters go unused in function definition
+ --> $DIR/extra_unused_type_parameters.rs:8:16
+ |
+LL | fn unused_multi<T, U>(x: u8) {
+ | ^^^^^^
+ |
+ = help: consider removing the parameters
+
+error: type parameter goes unused in function definition
+ --> $DIR/extra_unused_type_parameters.rs:12:23
+ |
+LL | fn unused_with_lt<'a, T>(x: &'a u8) {
+ | ^
+ |
+ = help: consider removing the parameter
+
+error: type parameter goes unused in function definition
+ --> $DIR/extra_unused_type_parameters.rs:24:19
+ |
+LL | fn unused_bounded<T: Default, U>(x: U) {
+ | ^^^^^^^^^^^
+ |
+ = help: consider removing the parameter
+
+error: type parameter goes unused in function definition
+ --> $DIR/extra_unused_type_parameters.rs:28:24
+ |
+LL | fn unused_where_clause<T, U>(x: U)
+ | ^^
+ |
+ = help: consider removing the parameter
+
+error: type parameters go unused in function definition
+ --> $DIR/extra_unused_type_parameters.rs:35:16
+ |
+LL | fn some_unused<A, B, C, D: Iterator<Item = (B, C)>, E>(b: B, c: C) {
+ | ^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^
+ |
+ = help: consider removing the parameters
+
+error: type parameter goes unused in function definition
+ --> $DIR/extra_unused_type_parameters.rs:60:22
+ |
+LL | fn unused_ty_impl<T>(&self) {
+ | ^^^
+ |
+ = help: consider removing the parameter
+
+error: type parameters go unused in function definition
+ --> $DIR/extra_unused_type_parameters.rs:82:17
+ |
+LL | fn unused_opaque<A, B>(dummy: impl Default) {
+ | ^^^^^^
+ |
+ = help: consider removing the parameters
+
+error: type parameter goes unused in function definition
+ --> $DIR/extra_unused_type_parameters.rs:95:58
+ |
+LL | fn unused_with_priv_trait_bound<T: private::Private, U>() {
+ | ^
+ |
+ = help: consider removing the parameter
+
+error: aborting due to 9 previous errors
+
diff --git a/src/tools/clippy/tests/ui/format.fixed b/src/tools/clippy/tests/ui/format.fixed
index beedf2c1d..cd2f70ee8 100644
--- a/src/tools/clippy/tests/ui/format.fixed
+++ b/src/tools/clippy/tests/ui/format.fixed
@@ -1,4 +1,5 @@
// run-rustfix
+// aux-build: proc_macro_with_span.rs
#![warn(clippy::useless_format)]
#![allow(
unused_tuple_struct_fields,
@@ -9,6 +10,8 @@
clippy::uninlined_format_args
)]
+extern crate proc_macro_with_span;
+
struct Foo(pub String);
macro_rules! foo {
@@ -87,4 +90,7 @@ fn main() {
let _ = abc.to_string();
let xx = "xx";
let _ = xx.to_string();
+
+ // Issue #10148
+ println!(proc_macro_with_span::with_span!(""something ""));
}
diff --git a/src/tools/clippy/tests/ui/format.rs b/src/tools/clippy/tests/ui/format.rs
index e805f1818..c22345a79 100644
--- a/src/tools/clippy/tests/ui/format.rs
+++ b/src/tools/clippy/tests/ui/format.rs
@@ -1,4 +1,5 @@
// run-rustfix
+// aux-build: proc_macro_with_span.rs
#![warn(clippy::useless_format)]
#![allow(
unused_tuple_struct_fields,
@@ -9,6 +10,8 @@
clippy::uninlined_format_args
)]
+extern crate proc_macro_with_span;
+
struct Foo(pub String);
macro_rules! foo {
@@ -89,4 +92,7 @@ fn main() {
let _ = format!("{abc}");
let xx = "xx";
let _ = format!("{xx}");
+
+ // Issue #10148
+ println!(proc_macro_with_span::with_span!(""something ""));
}
diff --git a/src/tools/clippy/tests/ui/format.stderr b/src/tools/clippy/tests/ui/format.stderr
index 0ef0ac655..a0e5d5c8a 100644
--- a/src/tools/clippy/tests/ui/format.stderr
+++ b/src/tools/clippy/tests/ui/format.stderr
@@ -1,5 +1,5 @@
error: useless use of `format!`
- --> $DIR/format.rs:19:5
+ --> $DIR/format.rs:22:5
|
LL | format!("foo");
| ^^^^^^^^^^^^^^ help: consider using `.to_string()`: `"foo".to_string()`
@@ -7,19 +7,19 @@ LL | format!("foo");
= note: `-D clippy::useless-format` implied by `-D warnings`
error: useless use of `format!`
- --> $DIR/format.rs:20:5
+ --> $DIR/format.rs:23:5
|
LL | format!("{{}}");
| ^^^^^^^^^^^^^^^ help: consider using `.to_string()`: `"{}".to_string()`
error: useless use of `format!`
- --> $DIR/format.rs:21:5
+ --> $DIR/format.rs:24:5
|
LL | format!("{{}} abc {{}}");
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `.to_string()`: `"{} abc {}".to_string()`
error: useless use of `format!`
- --> $DIR/format.rs:22:5
+ --> $DIR/format.rs:25:5
|
LL | / format!(
LL | | r##"foo {{}}
@@ -34,67 +34,67 @@ LL ~ " bar"##.to_string();
|
error: useless use of `format!`
- --> $DIR/format.rs:27:13
+ --> $DIR/format.rs:30:13
|
LL | let _ = format!("");
| ^^^^^^^^^^^ help: consider using `String::new()`: `String::new()`
error: useless use of `format!`
- --> $DIR/format.rs:29:5
+ --> $DIR/format.rs:32:5
|
LL | format!("{}", "foo");
| ^^^^^^^^^^^^^^^^^^^^ help: consider using `.to_string()`: `"foo".to_string()`
error: useless use of `format!`
- --> $DIR/format.rs:37:5
+ --> $DIR/format.rs:40:5
|
LL | format!("{}", arg);
| ^^^^^^^^^^^^^^^^^^ help: consider using `.to_string()`: `arg.to_string()`
error: useless use of `format!`
- --> $DIR/format.rs:67:5
+ --> $DIR/format.rs:70:5
|
LL | format!("{}", 42.to_string());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `.to_string()`: `42.to_string()`
error: useless use of `format!`
- --> $DIR/format.rs:69:5
+ --> $DIR/format.rs:72:5
|
LL | format!("{}", x.display().to_string());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `.to_string()`: `x.display().to_string()`
error: useless use of `format!`
- --> $DIR/format.rs:73:18
+ --> $DIR/format.rs:76:18
|
LL | let _ = Some(format!("{}", a + "bar"));
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `.to_string()`: `a + "bar"`
error: useless use of `format!`
- --> $DIR/format.rs:77:22
+ --> $DIR/format.rs:80:22
|
LL | let _s: String = format!("{}", &*v.join("/n"));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `.to_string()`: `(&*v.join("/n")).to_string()`
error: useless use of `format!`
- --> $DIR/format.rs:83:13
+ --> $DIR/format.rs:86:13
|
LL | let _ = format!("{x}");
| ^^^^^^^^^^^^^^ help: consider using `.to_string()`: `x.to_string()`
error: useless use of `format!`
- --> $DIR/format.rs:85:13
+ --> $DIR/format.rs:88:13
|
LL | let _ = format!("{y}", y = x);
| ^^^^^^^^^^^^^^^^^^^^^ help: consider using `.to_string()`: `x.to_string()`
error: useless use of `format!`
- --> $DIR/format.rs:89:13
+ --> $DIR/format.rs:92:13
|
LL | let _ = format!("{abc}");
| ^^^^^^^^^^^^^^^^ help: consider using `.to_string()`: `abc.to_string()`
error: useless use of `format!`
- --> $DIR/format.rs:91:13
+ --> $DIR/format.rs:94:13
|
LL | let _ = format!("{xx}");
| ^^^^^^^^^^^^^^^ help: consider using `.to_string()`: `xx.to_string()`
diff --git a/src/tools/clippy/tests/ui/impl_trait_in_params.rs b/src/tools/clippy/tests/ui/impl_trait_in_params.rs
new file mode 100644
index 000000000..07560101a
--- /dev/null
+++ b/src/tools/clippy/tests/ui/impl_trait_in_params.rs
@@ -0,0 +1,17 @@
+#![allow(unused)]
+#![warn(clippy::impl_trait_in_params)]
+
+pub trait Trait {}
+pub trait AnotherTrait<T> {}
+
+// Should warn
+pub fn a(_: impl Trait) {}
+pub fn c<C: Trait>(_: C, _: impl Trait) {}
+fn d(_: impl AnotherTrait<u32>) {}
+
+// Shouldn't warn
+
+pub fn b<B: Trait>(_: B) {}
+fn e<T: AnotherTrait<u32>>(_: T) {}
+
+fn main() {}
diff --git a/src/tools/clippy/tests/ui/impl_trait_in_params.stderr b/src/tools/clippy/tests/ui/impl_trait_in_params.stderr
new file mode 100644
index 000000000..acfcc2144
--- /dev/null
+++ b/src/tools/clippy/tests/ui/impl_trait_in_params.stderr
@@ -0,0 +1,25 @@
+error: '`impl Trait` used as a function parameter'
+ --> $DIR/impl_trait_in_params.rs:8:13
+ |
+LL | pub fn a(_: impl Trait) {}
+ | ^^^^^^^^^^
+ |
+ = note: `-D clippy::impl-trait-in-params` implied by `-D warnings`
+help: add a type paremeter
+ |
+LL | pub fn a<{ /* Generic name */ }: Trait>(_: impl Trait) {}
+ | +++++++++++++++++++++++++++++++
+
+error: '`impl Trait` used as a function parameter'
+ --> $DIR/impl_trait_in_params.rs:9:29
+ |
+LL | pub fn c<C: Trait>(_: C, _: impl Trait) {}
+ | ^^^^^^^^^^
+ |
+help: add a type paremeter
+ |
+LL | pub fn c<C: Trait, { /* Generic name */ }: Trait>(_: C, _: impl Trait) {}
+ | +++++++++++++++++++++++++++++++
+
+error: aborting due to 2 previous errors
+
diff --git a/src/tools/clippy/tests/ui/large_digit_groups.fixed b/src/tools/clippy/tests/ui/large_digit_groups.fixed
index 3430c137e..ea18dac06 100644
--- a/src/tools/clippy/tests/ui/large_digit_groups.fixed
+++ b/src/tools/clippy/tests/ui/large_digit_groups.fixed
@@ -11,7 +11,7 @@ fn main() {
let _good = (
0b1011_i64,
0o1_234_u32,
- 0x0123_4567,
+ 0x1_234_567,
1_2345_6789,
1234_f32,
1_234.12_f32,
@@ -19,7 +19,7 @@ fn main() {
1.123_4_f32,
);
let _bad = (
- 0b11_0110_i64,
+ 0b1_10110_i64,
0xdead_beef_usize,
123_456_f32,
123_456.12_f32,
diff --git a/src/tools/clippy/tests/ui/large_digit_groups.stderr b/src/tools/clippy/tests/ui/large_digit_groups.stderr
index 13d108b56..19c0fae98 100644
--- a/src/tools/clippy/tests/ui/large_digit_groups.stderr
+++ b/src/tools/clippy/tests/ui/large_digit_groups.stderr
@@ -1,22 +1,10 @@
-error: digits of hex or binary literal not grouped by four
- --> $DIR/large_digit_groups.rs:14:9
- |
-LL | 0x1_234_567,
- | ^^^^^^^^^^^ help: consider: `0x0123_4567`
- |
- = note: `-D clippy::unusual-byte-groupings` implied by `-D warnings`
-
-error: digits of hex or binary literal not grouped by four
- --> $DIR/large_digit_groups.rs:22:9
- |
-LL | 0b1_10110_i64,
- | ^^^^^^^^^^^^^ help: consider: `0b11_0110_i64`
-
-error: digits of hex or binary literal not grouped by four
+error: digits of hex, binary or octal literal not in groups of equal size
--> $DIR/large_digit_groups.rs:23:9
|
LL | 0xd_e_adbee_f_usize,
| ^^^^^^^^^^^^^^^^^^^ help: consider: `0xdead_beef_usize`
+ |
+ = note: `-D clippy::unusual-byte-groupings` implied by `-D warnings`
error: digit groups should be smaller
--> $DIR/large_digit_groups.rs:24:9
@@ -44,5 +32,5 @@ error: digit groups should be smaller
LL | 1_23456.12345_6_f64,
| ^^^^^^^^^^^^^^^^^^^ help: consider: `123_456.123_456_f64`
-error: aborting due to 7 previous errors
+error: aborting due to 5 previous errors
diff --git a/src/tools/clippy/tests/ui/len_without_is_empty.rs b/src/tools/clippy/tests/ui/len_without_is_empty.rs
index 78397c2af..b5dec6c46 100644
--- a/src/tools/clippy/tests/ui/len_without_is_empty.rs
+++ b/src/tools/clippy/tests/ui/len_without_is_empty.rs
@@ -282,4 +282,50 @@ impl AsyncLen {
}
}
+// issue #9520
+pub struct NonStandardLenAndIsEmptySignature;
+impl NonStandardLenAndIsEmptySignature {
+ // don't lint
+ pub fn len(&self, something: usize) -> usize {
+ something
+ }
+
+ pub fn is_empty(&self, something: usize) -> bool {
+ something == 0
+ }
+}
+
+// test case for #9520 with generics in the function signature
+pub trait TestResource {
+ type NonStandardSignatureWithGenerics: Copy;
+ fn lookup_content(&self, item: Self::NonStandardSignatureWithGenerics) -> Result<Option<&[u8]>, String>;
+}
+pub struct NonStandardSignatureWithGenerics(u32);
+impl NonStandardSignatureWithGenerics {
+ pub fn is_empty<T, U>(self, resource: &T) -> bool
+ where
+ T: TestResource<NonStandardSignatureWithGenerics = U>,
+ U: Copy + From<NonStandardSignatureWithGenerics>,
+ {
+ if let Ok(Some(content)) = resource.lookup_content(self.into()) {
+ content.is_empty()
+ } else {
+ true
+ }
+ }
+
+ // test case for #9520 with generics in the function signature
+ pub fn len<T, U>(self, resource: &T) -> usize
+ where
+ T: TestResource<NonStandardSignatureWithGenerics = U>,
+ U: Copy + From<NonStandardSignatureWithGenerics>,
+ {
+ if let Ok(Some(content)) = resource.lookup_content(self.into()) {
+ content.len()
+ } else {
+ 0_usize
+ }
+ }
+}
+
fn main() {}
diff --git a/src/tools/clippy/tests/ui/let_underscore_untyped.rs b/src/tools/clippy/tests/ui/let_underscore_untyped.rs
new file mode 100644
index 000000000..bcb33c5c7
--- /dev/null
+++ b/src/tools/clippy/tests/ui/let_underscore_untyped.rs
@@ -0,0 +1,54 @@
+#![allow(unused)]
+#![warn(clippy::let_underscore_untyped)]
+
+use std::future::Future;
+use std::{boxed::Box, fmt::Display};
+
+fn a() -> u32 {
+ 1
+}
+
+fn b<T>(x: T) -> T {
+ x
+}
+
+fn c() -> impl Display {
+ 1
+}
+
+fn d(x: &u32) -> &u32 {
+ x
+}
+
+fn e() -> Result<u32, ()> {
+ Ok(1)
+}
+
+fn f() -> Box<dyn Display> {
+ Box::new(1)
+}
+
+fn main() {
+ let _ = a();
+ let _ = b(1);
+ let _ = c();
+ let _ = d(&1);
+ let _ = e();
+ let _ = f();
+
+ _ = a();
+ _ = b(1);
+ _ = c();
+ _ = d(&1);
+ _ = e();
+ _ = f();
+
+ let _: u32 = a();
+ let _: u32 = b(1);
+ let _: &u32 = d(&1);
+ let _: Result<_, _> = e();
+ let _: Box<_> = f();
+
+ #[allow(clippy::let_underscore_untyped)]
+ let _ = a();
+}
diff --git a/src/tools/clippy/tests/ui/let_underscore_untyped.stderr b/src/tools/clippy/tests/ui/let_underscore_untyped.stderr
new file mode 100644
index 000000000..36c3d1214
--- /dev/null
+++ b/src/tools/clippy/tests/ui/let_underscore_untyped.stderr
@@ -0,0 +1,51 @@
+error: non-binding `let` without a type annotation
+ --> $DIR/let_underscore_untyped.rs:32:5
+ |
+LL | let _ = a();
+ | ^^^^^^^^^^^^
+ |
+ = help: consider adding a type annotation or removing the `let` keyword
+ = note: `-D clippy::let-underscore-untyped` implied by `-D warnings`
+
+error: non-binding `let` without a type annotation
+ --> $DIR/let_underscore_untyped.rs:33:5
+ |
+LL | let _ = b(1);
+ | ^^^^^^^^^^^^^
+ |
+ = help: consider adding a type annotation or removing the `let` keyword
+
+error: non-binding `let` without a type annotation
+ --> $DIR/let_underscore_untyped.rs:34:5
+ |
+LL | let _ = c();
+ | ^^^^^^^^^^^^
+ |
+ = help: consider adding a type annotation or removing the `let` keyword
+
+error: non-binding `let` without a type annotation
+ --> $DIR/let_underscore_untyped.rs:35:5
+ |
+LL | let _ = d(&1);
+ | ^^^^^^^^^^^^^^
+ |
+ = help: consider adding a type annotation or removing the `let` keyword
+
+error: non-binding `let` without a type annotation
+ --> $DIR/let_underscore_untyped.rs:36:5
+ |
+LL | let _ = e();
+ | ^^^^^^^^^^^^
+ |
+ = help: consider adding a type annotation or removing the `let` keyword
+
+error: non-binding `let` without a type annotation
+ --> $DIR/let_underscore_untyped.rs:37:5
+ |
+LL | let _ = f();
+ | ^^^^^^^^^^^^
+ |
+ = help: consider adding a type annotation or removing the `let` keyword
+
+error: aborting due to 6 previous errors
+
diff --git a/src/tools/clippy/tests/ui/literals.stderr b/src/tools/clippy/tests/ui/literals.stderr
index 603d47bac..9bc7948c7 100644
--- a/src/tools/clippy/tests/ui/literals.stderr
+++ b/src/tools/clippy/tests/ui/literals.stderr
@@ -121,7 +121,7 @@ error: digits grouped inconsistently by underscores
LL | let fail23 = 3__16___23;
| ^^^^^^^^^^ help: consider: `31_623`
-error: digits of hex or binary literal not grouped by four
+error: digits of hex, binary or octal literal not in groups of equal size
--> $DIR/literals.rs:38:18
|
LL | let fail24 = 0xAB_ABC_AB;
@@ -129,12 +129,6 @@ LL | let fail24 = 0xAB_ABC_AB;
|
= note: `-D clippy::unusual-byte-groupings` implied by `-D warnings`
-error: digits of hex or binary literal not grouped by four
- --> $DIR/literals.rs:39:18
- |
-LL | let fail25 = 0b01_100_101;
- | ^^^^^^^^^^^^ help: consider: `0b0110_0101`
-
error: this is a decimal constant
--> $DIR/literals.rs:46:13
|
@@ -168,5 +162,5 @@ help: if you mean to use a decimal constant, remove the `0` to avoid confusion
LL | let _ = 89;
| ~~
-error: aborting due to 21 previous errors
+error: aborting due to 20 previous errors
diff --git a/src/tools/clippy/tests/ui/manual_assert.edition2018.fixed b/src/tools/clippy/tests/ui/manual_assert.edition2018.fixed
index 638320dd6..8c7e919bf 100644
--- a/src/tools/clippy/tests/ui/manual_assert.edition2018.fixed
+++ b/src/tools/clippy/tests/ui/manual_assert.edition2018.fixed
@@ -29,9 +29,7 @@ fn main() {
panic!("qaqaq{:?}", a);
}
assert!(a.is_empty(), "qaqaq{:?}", a);
- if !a.is_empty() {
- panic!("qwqwq");
- }
+ assert!(a.is_empty(), "qwqwq");
if a.len() == 3 {
println!("qwq");
println!("qwq");
@@ -46,21 +44,11 @@ fn main() {
println!("qwq");
}
let b = vec![1, 2, 3];
- if b.is_empty() {
- panic!("panic1");
- }
- if b.is_empty() && a.is_empty() {
- panic!("panic2");
- }
- if a.is_empty() && !b.is_empty() {
- panic!("panic3");
- }
- if b.is_empty() || a.is_empty() {
- panic!("panic4");
- }
- if a.is_empty() || !b.is_empty() {
- panic!("panic5");
- }
+ assert!(!b.is_empty(), "panic1");
+ assert!(!(b.is_empty() && a.is_empty()), "panic2");
+ assert!(!(a.is_empty() && !b.is_empty()), "panic3");
+ assert!(!(b.is_empty() || a.is_empty()), "panic4");
+ assert!(!(a.is_empty() || !b.is_empty()), "panic5");
assert!(!a.is_empty(), "with expansion {}", one!());
if a.is_empty() {
let _ = 0;
@@ -71,12 +59,11 @@ fn main() {
fn issue7730(a: u8) {
// Suggestion should preserve comment
- if a > 2 {
- // comment
- /* this is a
+ // comment
+/* this is a
multiline
comment */
- /// Doc comment
- panic!("panic with comment") // comment after `panic!`
- }
+/// Doc comment
+// comment after `panic!`
+assert!(!(a > 2), "panic with comment");
}
diff --git a/src/tools/clippy/tests/ui/manual_assert.edition2018.stderr b/src/tools/clippy/tests/ui/manual_assert.edition2018.stderr
index 1f2e1e308..3555ac292 100644
--- a/src/tools/clippy/tests/ui/manual_assert.edition2018.stderr
+++ b/src/tools/clippy/tests/ui/manual_assert.edition2018.stderr
@@ -9,6 +9,54 @@ LL | | }
= note: `-D clippy::manual-assert` implied by `-D warnings`
error: only a `panic!` in `if`-then statement
+ --> $DIR/manual_assert.rs:34:5
+ |
+LL | / if !a.is_empty() {
+LL | | panic!("qwqwq");
+LL | | }
+ | |_____^ help: try instead: `assert!(a.is_empty(), "qwqwq");`
+
+error: only a `panic!` in `if`-then statement
+ --> $DIR/manual_assert.rs:51:5
+ |
+LL | / if b.is_empty() {
+LL | | panic!("panic1");
+LL | | }
+ | |_____^ help: try instead: `assert!(!b.is_empty(), "panic1");`
+
+error: only a `panic!` in `if`-then statement
+ --> $DIR/manual_assert.rs:54:5
+ |
+LL | / if b.is_empty() && a.is_empty() {
+LL | | panic!("panic2");
+LL | | }
+ | |_____^ help: try instead: `assert!(!(b.is_empty() && a.is_empty()), "panic2");`
+
+error: only a `panic!` in `if`-then statement
+ --> $DIR/manual_assert.rs:57:5
+ |
+LL | / if a.is_empty() && !b.is_empty() {
+LL | | panic!("panic3");
+LL | | }
+ | |_____^ help: try instead: `assert!(!(a.is_empty() && !b.is_empty()), "panic3");`
+
+error: only a `panic!` in `if`-then statement
+ --> $DIR/manual_assert.rs:60:5
+ |
+LL | / if b.is_empty() || a.is_empty() {
+LL | | panic!("panic4");
+LL | | }
+ | |_____^ help: try instead: `assert!(!(b.is_empty() || a.is_empty()), "panic4");`
+
+error: only a `panic!` in `if`-then statement
+ --> $DIR/manual_assert.rs:63:5
+ |
+LL | / if a.is_empty() || !b.is_empty() {
+LL | | panic!("panic5");
+LL | | }
+ | |_____^ help: try instead: `assert!(!(a.is_empty() || !b.is_empty()), "panic5");`
+
+error: only a `panic!` in `if`-then statement
--> $DIR/manual_assert.rs:66:5
|
LL | / if a.is_empty() {
@@ -16,5 +64,22 @@ LL | | panic!("with expansion {}", one!())
LL | | }
| |_____^ help: try instead: `assert!(!a.is_empty(), "with expansion {}", one!());`
-error: aborting due to 2 previous errors
+error: only a `panic!` in `if`-then statement
+ --> $DIR/manual_assert.rs:78:5
+ |
+LL | / if a > 2 {
+LL | | // comment
+LL | | /* this is a
+LL | | multiline
+... |
+LL | | panic!("panic with comment") // comment after `panic!`
+LL | | }
+ | |_____^
+ |
+help: try instead
+ |
+LL | assert!(!(a > 2), "panic with comment");
+ |
+
+error: aborting due to 9 previous errors
diff --git a/src/tools/clippy/tests/ui/manual_let_else.rs b/src/tools/clippy/tests/ui/manual_let_else.rs
index 48a162c13..d175597a4 100644
--- a/src/tools/clippy/tests/ui/manual_let_else.rs
+++ b/src/tools/clippy/tests/ui/manual_let_else.rs
@@ -248,4 +248,15 @@ fn not_fire() {
Some(value) => value,
_ => macro_call!(),
};
+
+ // Issue 10296
+ // The let/else block in the else part is not divergent despite the presence of return
+ let _x = if let Some(x) = Some(1) {
+ x
+ } else {
+ let Some(_z) = Some(3) else {
+ return
+ };
+ 1
+ };
}
diff --git a/src/tools/clippy/tests/ui/manual_let_else_match.rs b/src/tools/clippy/tests/ui/manual_let_else_match.rs
index 28caed9d7..73b746791 100644
--- a/src/tools/clippy/tests/ui/manual_let_else_match.rs
+++ b/src/tools/clippy/tests/ui/manual_let_else_match.rs
@@ -42,13 +42,13 @@ fn fire() {
loop {
// More complex pattern for the identity arm and diverging arm
let v = match h() {
- (Some(_), Some(_)) | (None, None) => continue,
(Some(v), None) | (None, Some(v)) => v,
+ (Some(_), Some(_)) | (None, None) => continue,
};
// Custom enums are supported as long as the "else" arm is a simple _
let v = match build_enum() {
- _ => continue,
Variant::Bar(v) | Variant::Baz(v) => v,
+ _ => continue,
};
}
@@ -71,6 +71,12 @@ fn fire() {
Variant::Bar(_) | Variant::Baz(_) => (),
_ => return,
};
+
+ let data = [1_u8, 2, 3, 4, 0, 0, 0, 0];
+ let data = match data.as_slice() {
+ [data @ .., 0, 0, 0, 0] | [data @ .., 0, 0] | [data @ .., 0] => data,
+ _ => return,
+ };
}
fn not_fire() {
@@ -125,4 +131,23 @@ fn not_fire() {
Ok(v) | Err(Variant::Bar(v) | Variant::Baz(v)) => v,
Err(Variant::Foo) => return,
};
+
+ // Issue 10241
+ // The non-divergent arm arrives in second position and
+ // may cover values already matched in the first arm.
+ let v = match h() {
+ (Some(_), Some(_)) | (None, None) => return,
+ (Some(v), _) | (None, Some(v)) => v,
+ };
+
+ let v = match build_enum() {
+ _ => return,
+ Variant::Bar(v) | Variant::Baz(v) => v,
+ };
+
+ let data = [1_u8, 2, 3, 4, 0, 0, 0, 0];
+ let data = match data.as_slice() {
+ [] | [0, 0] => return,
+ [data @ .., 0, 0, 0, 0] | [data @ .., 0, 0] | [data @ ..] => data,
+ };
}
diff --git a/src/tools/clippy/tests/ui/manual_let_else_match.stderr b/src/tools/clippy/tests/ui/manual_let_else_match.stderr
index cd5e9a9ac..7abaa0b85 100644
--- a/src/tools/clippy/tests/ui/manual_let_else_match.stderr
+++ b/src/tools/clippy/tests/ui/manual_let_else_match.stderr
@@ -22,8 +22,8 @@ error: this could be rewritten as `let...else`
--> $DIR/manual_let_else_match.rs:44:9
|
LL | / let v = match h() {
-LL | | (Some(_), Some(_)) | (None, None) => continue,
LL | | (Some(v), None) | (None, Some(v)) => v,
+LL | | (Some(_), Some(_)) | (None, None) => continue,
LL | | };
| |__________^ help: consider writing: `let ((Some(v), None) | (None, Some(v))) = h() else { continue };`
@@ -31,8 +31,8 @@ error: this could be rewritten as `let...else`
--> $DIR/manual_let_else_match.rs:49:9
|
LL | / let v = match build_enum() {
-LL | | _ => continue,
LL | | Variant::Bar(v) | Variant::Baz(v) => v,
+LL | | _ => continue,
LL | | };
| |__________^ help: consider writing: `let (Variant::Bar(v) | Variant::Baz(v)) = build_enum() else { continue };`
@@ -63,5 +63,14 @@ LL | | _ => return,
LL | | };
| |______^ help: consider writing: `let (Variant::Bar(_) | Variant::Baz(_)) = f else { return };`
-error: aborting due to 7 previous errors
+error: this could be rewritten as `let...else`
+ --> $DIR/manual_let_else_match.rs:76:5
+ |
+LL | / let data = match data.as_slice() {
+LL | | [data @ .., 0, 0, 0, 0] | [data @ .., 0, 0] | [data @ .., 0] => data,
+LL | | _ => return,
+LL | | };
+ | |______^ help: consider writing: `let ([data @ .., 0, 0, 0, 0] | [data @ .., 0, 0] | [data @ .., 0]) = data.as_slice() else { return };`
+
+error: aborting due to 8 previous errors
diff --git a/src/tools/clippy/tests/ui/map_flatten_fixable.fixed b/src/tools/clippy/tests/ui/map_flatten_fixable.fixed
index 53628ef65..8e2f11389 100644
--- a/src/tools/clippy/tests/ui/map_flatten_fixable.fixed
+++ b/src/tools/clippy/tests/ui/map_flatten_fixable.fixed
@@ -1,6 +1,7 @@
// run-rustfix
#![warn(clippy::all, clippy::pedantic)]
+#![allow(clippy::let_underscore_untyped)]
#![allow(clippy::missing_docs_in_private_items)]
#![allow(clippy::map_identity)]
#![allow(clippy::redundant_closure)]
diff --git a/src/tools/clippy/tests/ui/map_flatten_fixable.rs b/src/tools/clippy/tests/ui/map_flatten_fixable.rs
index 76016c8ed..a783a99c4 100644
--- a/src/tools/clippy/tests/ui/map_flatten_fixable.rs
+++ b/src/tools/clippy/tests/ui/map_flatten_fixable.rs
@@ -1,6 +1,7 @@
// run-rustfix
#![warn(clippy::all, clippy::pedantic)]
+#![allow(clippy::let_underscore_untyped)]
#![allow(clippy::missing_docs_in_private_items)]
#![allow(clippy::map_identity)]
#![allow(clippy::redundant_closure)]
diff --git a/src/tools/clippy/tests/ui/map_flatten_fixable.stderr b/src/tools/clippy/tests/ui/map_flatten_fixable.stderr
index b6b0c4d09..c91f0b9ae 100644
--- a/src/tools/clippy/tests/ui/map_flatten_fixable.stderr
+++ b/src/tools/clippy/tests/ui/map_flatten_fixable.stderr
@@ -1,5 +1,5 @@
error: called `map(..).flatten()` on `Iterator`
- --> $DIR/map_flatten_fixable.rs:17:47
+ --> $DIR/map_flatten_fixable.rs:18:47
|
LL | let _: Vec<_> = vec![5_i8; 6].into_iter().map(option_id).flatten().collect();
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: try replacing `map` with `filter_map` and remove the `.flatten()`: `filter_map(option_id)`
@@ -7,43 +7,43 @@ LL | let _: Vec<_> = vec![5_i8; 6].into_iter().map(option_id).flatten().coll
= note: `-D clippy::map-flatten` implied by `-D warnings`
error: called `map(..).flatten()` on `Iterator`
- --> $DIR/map_flatten_fixable.rs:18:47
+ --> $DIR/map_flatten_fixable.rs:19:47
|
LL | let _: Vec<_> = vec![5_i8; 6].into_iter().map(option_id_ref).flatten().collect();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try replacing `map` with `filter_map` and remove the `.flatten()`: `filter_map(option_id_ref)`
error: called `map(..).flatten()` on `Iterator`
- --> $DIR/map_flatten_fixable.rs:19:47
+ --> $DIR/map_flatten_fixable.rs:20:47
|
LL | let _: Vec<_> = vec![5_i8; 6].into_iter().map(option_id_closure).flatten().collect();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try replacing `map` with `filter_map` and remove the `.flatten()`: `filter_map(option_id_closure)`
error: called `map(..).flatten()` on `Iterator`
- --> $DIR/map_flatten_fixable.rs:20:47
+ --> $DIR/map_flatten_fixable.rs:21:47
|
LL | let _: Vec<_> = vec![5_i8; 6].into_iter().map(|x| x.checked_add(1)).flatten().collect();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try replacing `map` with `filter_map` and remove the `.flatten()`: `filter_map(|x| x.checked_add(1))`
error: called `map(..).flatten()` on `Iterator`
- --> $DIR/map_flatten_fixable.rs:23:47
+ --> $DIR/map_flatten_fixable.rs:24:47
|
LL | let _: Vec<_> = vec![5_i8; 6].into_iter().map(|x| 0..x).flatten().collect();
| ^^^^^^^^^^^^^^^^^^^^^^^ help: try replacing `map` with `flat_map` and remove the `.flatten()`: `flat_map(|x| 0..x)`
error: called `map(..).flatten()` on `Option`
- --> $DIR/map_flatten_fixable.rs:26:40
+ --> $DIR/map_flatten_fixable.rs:27:40
|
LL | let _: Option<_> = (Some(Some(1))).map(|x| x).flatten();
| ^^^^^^^^^^^^^^^^^^^^ help: try replacing `map` with `and_then` and remove the `.flatten()`: `and_then(|x| x)`
error: called `map(..).flatten()` on `Result`
- --> $DIR/map_flatten_fixable.rs:29:42
+ --> $DIR/map_flatten_fixable.rs:30:42
|
LL | let _: Result<_, &str> = (Ok(Ok(1))).map(|x| x).flatten();
| ^^^^^^^^^^^^^^^^^^^^ help: try replacing `map` with `and_then` and remove the `.flatten()`: `and_then(|x| x)`
error: called `map(..).flatten()` on `Iterator`
- --> $DIR/map_flatten_fixable.rs:38:10
+ --> $DIR/map_flatten_fixable.rs:39:10
|
LL | .map(|n| match n {
| __________^
@@ -72,7 +72,7 @@ LL ~ });
|
error: called `map(..).flatten()` on `Option`
- --> $DIR/map_flatten_fixable.rs:58:10
+ --> $DIR/map_flatten_fixable.rs:59:10
|
LL | .map(|_| {
| __________^
diff --git a/src/tools/clippy/tests/ui/match_wildcard_for_single_variants.fixed b/src/tools/clippy/tests/ui/match_wildcard_for_single_variants.fixed
index fc252cdd3..9fd3739b6 100644
--- a/src/tools/clippy/tests/ui/match_wildcard_for_single_variants.fixed
+++ b/src/tools/clippy/tests/ui/match_wildcard_for_single_variants.fixed
@@ -123,7 +123,7 @@ fn main() {
Enum::A => (),
Enum::B => (),
Enum::C => (),
- _ => (),
+ Enum::__Private => (),
}
match Enum::A {
Enum::A => (),
diff --git a/src/tools/clippy/tests/ui/match_wildcard_for_single_variants.stderr b/src/tools/clippy/tests/ui/match_wildcard_for_single_variants.stderr
index 6fa313dc9..105b4c4b4 100644
--- a/src/tools/clippy/tests/ui/match_wildcard_for_single_variants.stderr
+++ b/src/tools/clippy/tests/ui/match_wildcard_for_single_variants.stderr
@@ -49,10 +49,16 @@ LL | _ => (),
| ^ help: try this: `Color::Blue`
error: wildcard matches only a single variant and will also match any future added variants
+ --> $DIR/match_wildcard_for_single_variants.rs:126:13
+ |
+LL | _ => (),
+ | ^ help: try this: `Enum::__Private`
+
+error: wildcard matches only a single variant and will also match any future added variants
--> $DIR/match_wildcard_for_single_variants.rs:153:13
|
LL | _ => 2,
| ^ help: try this: `Foo::B`
-error: aborting due to 9 previous errors
+error: aborting due to 10 previous errors
diff --git a/src/tools/clippy/tests/ui/methods.rs b/src/tools/clippy/tests/ui/methods.rs
index 6f22366ea..1519e4da9 100644
--- a/src/tools/clippy/tests/ui/methods.rs
+++ b/src/tools/clippy/tests/ui/methods.rs
@@ -4,6 +4,7 @@
#![allow(
clippy::disallowed_names,
clippy::default_trait_access,
+ clippy::let_underscore_untyped,
clippy::missing_docs_in_private_items,
clippy::missing_safety_doc,
clippy::non_ascii_literal,
diff --git a/src/tools/clippy/tests/ui/methods.stderr b/src/tools/clippy/tests/ui/methods.stderr
index b63672dd6..4643e09e2 100644
--- a/src/tools/clippy/tests/ui/methods.stderr
+++ b/src/tools/clippy/tests/ui/methods.stderr
@@ -1,5 +1,5 @@
error: methods called `new` usually return `Self`
- --> $DIR/methods.rs:104:5
+ --> $DIR/methods.rs:105:5
|
LL | / fn new() -> i32 {
LL | | 0
@@ -9,7 +9,7 @@ LL | | }
= note: `-D clippy::new-ret-no-self` implied by `-D warnings`
error: called `filter(..).next()` on an `Iterator`. This is more succinctly expressed by calling `.find(..)` instead
- --> $DIR/methods.rs:125:13
+ --> $DIR/methods.rs:126:13
|
LL | let _ = v.iter().filter(|&x| {
| _____________^
diff --git a/src/tools/clippy/tests/ui/missing_doc_impl.stderr b/src/tools/clippy/tests/ui/missing_doc_impl.stderr
index f22fa19db..b410f56e1 100644
--- a/src/tools/clippy/tests/ui/missing_doc_impl.stderr
+++ b/src/tools/clippy/tests/ui/missing_doc_impl.stderr
@@ -51,13 +51,13 @@ LL | | fn foo_with_impl(&self) {}
LL | | }
| |_^
-error: missing documentation for an associated function
+error: missing documentation for a method
--> $DIR/missing_doc_impl.rs:44:5
|
LL | fn foo(&self);
| ^^^^^^^^^^^^^^
-error: missing documentation for an associated function
+error: missing documentation for a method
--> $DIR/missing_doc_impl.rs:45:5
|
LL | fn foo_with_impl(&self) {}
diff --git a/src/tools/clippy/tests/ui/module_name_repetitions.stderr b/src/tools/clippy/tests/ui/module_name_repetitions.stderr
index 3f343a3e4..277801194 100644
--- a/src/tools/clippy/tests/ui/module_name_repetitions.stderr
+++ b/src/tools/clippy/tests/ui/module_name_repetitions.stderr
@@ -1,34 +1,34 @@
error: item name starts with its containing module's name
- --> $DIR/module_name_repetitions.rs:8:5
+ --> $DIR/module_name_repetitions.rs:8:12
|
LL | pub fn foo_bar() {}
- | ^^^^^^^^^^^^^^^^^^^
+ | ^^^^^^^
|
= note: `-D clippy::module-name-repetitions` implied by `-D warnings`
error: item name ends with its containing module's name
- --> $DIR/module_name_repetitions.rs:9:5
+ --> $DIR/module_name_repetitions.rs:9:12
|
LL | pub fn bar_foo() {}
- | ^^^^^^^^^^^^^^^^^^^
+ | ^^^^^^^
error: item name starts with its containing module's name
- --> $DIR/module_name_repetitions.rs:10:5
+ --> $DIR/module_name_repetitions.rs:10:16
|
LL | pub struct FooCake;
- | ^^^^^^^^^^^^^^^^^^^
+ | ^^^^^^^
error: item name ends with its containing module's name
- --> $DIR/module_name_repetitions.rs:11:5
+ --> $DIR/module_name_repetitions.rs:11:14
|
LL | pub enum CakeFoo {}
- | ^^^^^^^^^^^^^^^^^^^
+ | ^^^^^^^
error: item name starts with its containing module's name
- --> $DIR/module_name_repetitions.rs:12:5
+ --> $DIR/module_name_repetitions.rs:12:16
|
LL | pub struct Foo7Bar;
- | ^^^^^^^^^^^^^^^^^^^
+ | ^^^^^^^
error: aborting due to 5 previous errors
diff --git a/src/tools/clippy/tests/ui/multiple_unsafe_ops_per_block.rs b/src/tools/clippy/tests/ui/multiple_unsafe_ops_per_block.rs
new file mode 100644
index 000000000..4511bc99c
--- /dev/null
+++ b/src/tools/clippy/tests/ui/multiple_unsafe_ops_per_block.rs
@@ -0,0 +1,119 @@
+// aux-build:macro_rules.rs
+#![allow(unused)]
+#![allow(deref_nullptr)]
+#![allow(clippy::unnecessary_operation)]
+#![allow(clippy::drop_copy)]
+#![warn(clippy::multiple_unsafe_ops_per_block)]
+
+#[macro_use]
+extern crate macro_rules;
+
+use core::arch::asm;
+
+fn raw_ptr() -> *const () {
+ core::ptr::null()
+}
+
+unsafe fn not_very_safe() {}
+
+struct Sample;
+
+impl Sample {
+ unsafe fn not_very_safe(&self) {}
+}
+
+#[allow(non_upper_case_globals)]
+const sample: Sample = Sample;
+
+union U {
+ i: i32,
+ u: u32,
+}
+
+static mut STATIC: i32 = 0;
+
+fn test1() {
+ unsafe {
+ STATIC += 1;
+ not_very_safe();
+ }
+}
+
+fn test2() {
+ let u = U { i: 0 };
+
+ unsafe {
+ drop(u.u);
+ *raw_ptr();
+ }
+}
+
+fn test3() {
+ unsafe {
+ asm!("nop");
+ sample.not_very_safe();
+ STATIC = 0;
+ }
+}
+
+fn test_all() {
+ let u = U { i: 0 };
+ unsafe {
+ drop(u.u);
+ drop(STATIC);
+ sample.not_very_safe();
+ not_very_safe();
+ *raw_ptr();
+ asm!("nop");
+ }
+}
+
+// no lint
+fn correct1() {
+ unsafe {
+ STATIC += 1;
+ }
+}
+
+// no lint
+fn correct2() {
+ unsafe {
+ STATIC += 1;
+ }
+
+ unsafe {
+ *raw_ptr();
+ }
+}
+
+// no lint
+fn correct3() {
+ let u = U { u: 0 };
+
+ unsafe {
+ not_very_safe();
+ }
+
+ unsafe {
+ drop(u.i);
+ }
+}
+
+// tests from the issue (https://github.com/rust-lang/rust-clippy/issues/10064)
+
+unsafe fn read_char_bad(ptr: *const u8) -> char {
+ unsafe { char::from_u32_unchecked(*ptr.cast::<u32>()) }
+}
+
+// no lint
+unsafe fn read_char_good(ptr: *const u8) -> char {
+ let int_value = unsafe { *ptr.cast::<u32>() };
+ unsafe { core::char::from_u32_unchecked(int_value) }
+}
+
+// no lint
+fn issue10259() {
+ unsafe_macro!();
+}
+
+fn main() {}
diff --git a/src/tools/clippy/tests/ui/multiple_unsafe_ops_per_block.stderr b/src/tools/clippy/tests/ui/multiple_unsafe_ops_per_block.stderr
new file mode 100644
index 000000000..303aeb7ae
--- /dev/null
+++ b/src/tools/clippy/tests/ui/multiple_unsafe_ops_per_block.stderr
@@ -0,0 +1,129 @@
+error: this `unsafe` block contains 2 unsafe operations, expected only one
+ --> $DIR/multiple_unsafe_ops_per_block.rs:36:5
+ |
+LL | / unsafe {
+LL | | STATIC += 1;
+LL | | not_very_safe();
+LL | | }
+ | |_____^
+ |
+note: modification of a mutable static occurs here
+ --> $DIR/multiple_unsafe_ops_per_block.rs:37:9
+ |
+LL | STATIC += 1;
+ | ^^^^^^^^^^^
+note: unsafe function call occurs here
+ --> $DIR/multiple_unsafe_ops_per_block.rs:38:9
+ |
+LL | not_very_safe();
+ | ^^^^^^^^^^^^^^^
+ = note: `-D clippy::multiple-unsafe-ops-per-block` implied by `-D warnings`
+
+error: this `unsafe` block contains 2 unsafe operations, expected only one
+ --> $DIR/multiple_unsafe_ops_per_block.rs:45:5
+ |
+LL | / unsafe {
+LL | | drop(u.u);
+LL | | *raw_ptr();
+LL | | }
+ | |_____^
+ |
+note: union field access occurs here
+ --> $DIR/multiple_unsafe_ops_per_block.rs:46:14
+ |
+LL | drop(u.u);
+ | ^^^
+note: raw pointer dereference occurs here
+ --> $DIR/multiple_unsafe_ops_per_block.rs:47:9
+ |
+LL | *raw_ptr();
+ | ^^^^^^^^^^
+
+error: this `unsafe` block contains 3 unsafe operations, expected only one
+ --> $DIR/multiple_unsafe_ops_per_block.rs:52:5
+ |
+LL | / unsafe {
+LL | | asm!("nop");
+LL | | sample.not_very_safe();
+LL | | STATIC = 0;
+LL | | }
+ | |_____^
+ |
+note: inline assembly used here
+ --> $DIR/multiple_unsafe_ops_per_block.rs:53:9
+ |
+LL | asm!("nop");
+ | ^^^^^^^^^^^
+note: unsafe method call occurs here
+ --> $DIR/multiple_unsafe_ops_per_block.rs:54:9
+ |
+LL | sample.not_very_safe();
+ | ^^^^^^^^^^^^^^^^^^^^^^
+note: modification of a mutable static occurs here
+ --> $DIR/multiple_unsafe_ops_per_block.rs:55:9
+ |
+LL | STATIC = 0;
+ | ^^^^^^^^^^
+
+error: this `unsafe` block contains 6 unsafe operations, expected only one
+ --> $DIR/multiple_unsafe_ops_per_block.rs:61:5
+ |
+LL | / unsafe {
+LL | | drop(u.u);
+LL | | drop(STATIC);
+LL | | sample.not_very_safe();
+... |
+LL | | asm!("nop");
+LL | | }
+ | |_____^
+ |
+note: union field access occurs here
+ --> $DIR/multiple_unsafe_ops_per_block.rs:62:14
+ |
+LL | drop(u.u);
+ | ^^^
+note: access of a mutable static occurs here
+ --> $DIR/multiple_unsafe_ops_per_block.rs:63:14
+ |
+LL | drop(STATIC);
+ | ^^^^^^
+note: unsafe method call occurs here
+ --> $DIR/multiple_unsafe_ops_per_block.rs:64:9
+ |
+LL | sample.not_very_safe();
+ | ^^^^^^^^^^^^^^^^^^^^^^
+note: unsafe function call occurs here
+ --> $DIR/multiple_unsafe_ops_per_block.rs:65:9
+ |
+LL | not_very_safe();
+ | ^^^^^^^^^^^^^^^
+note: raw pointer dereference occurs here
+ --> $DIR/multiple_unsafe_ops_per_block.rs:66:9
+ |
+LL | *raw_ptr();
+ | ^^^^^^^^^^
+note: inline assembly used here
+ --> $DIR/multiple_unsafe_ops_per_block.rs:67:9
+ |
+LL | asm!("nop");
+ | ^^^^^^^^^^^
+
+error: this `unsafe` block contains 2 unsafe operations, expected only one
+ --> $DIR/multiple_unsafe_ops_per_block.rs:105:5
+ |
+LL | unsafe { char::from_u32_unchecked(*ptr.cast::<u32>()) }
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+note: unsafe function call occurs here
+ --> $DIR/multiple_unsafe_ops_per_block.rs:105:14
+ |
+LL | unsafe { char::from_u32_unchecked(*ptr.cast::<u32>()) }
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+note: raw pointer dereference occurs here
+ --> $DIR/multiple_unsafe_ops_per_block.rs:105:39
+ |
+LL | unsafe { char::from_u32_unchecked(*ptr.cast::<u32>()) }
+ | ^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 5 previous errors
+
diff --git a/src/tools/clippy/tests/ui/must_use_candidates.fixed b/src/tools/clippy/tests/ui/must_use_candidates.fixed
index 04a74a009..bbbb3cf62 100644
--- a/src/tools/clippy/tests/ui/must_use_candidates.fixed
+++ b/src/tools/clippy/tests/ui/must_use_candidates.fixed
@@ -84,7 +84,7 @@ pub unsafe fn mutates_static() -> usize {
}
#[no_mangle]
-pub fn unmangled(i: bool) -> bool {
+pub extern "C" fn unmangled(i: bool) -> bool {
!i
}
diff --git a/src/tools/clippy/tests/ui/must_use_candidates.rs b/src/tools/clippy/tests/ui/must_use_candidates.rs
index f04122f4e..94d3c83bd 100644
--- a/src/tools/clippy/tests/ui/must_use_candidates.rs
+++ b/src/tools/clippy/tests/ui/must_use_candidates.rs
@@ -84,7 +84,7 @@ pub unsafe fn mutates_static() -> usize {
}
#[no_mangle]
-pub fn unmangled(i: bool) -> bool {
+pub extern "C" fn unmangled(i: bool) -> bool {
!i
}
diff --git a/src/tools/clippy/tests/ui/needless_lifetimes.fixed b/src/tools/clippy/tests/ui/needless_lifetimes.fixed
new file mode 100644
index 000000000..f0f1f9298
--- /dev/null
+++ b/src/tools/clippy/tests/ui/needless_lifetimes.fixed
@@ -0,0 +1,548 @@
+// run-rustfix
+// aux-build:macro_rules.rs
+
+#![warn(clippy::needless_lifetimes)]
+#![allow(
+ unused,
+ clippy::boxed_local,
+ clippy::extra_unused_type_parameters,
+ clippy::needless_pass_by_value,
+ clippy::unnecessary_wraps,
+ dyn_drop,
+ clippy::get_first
+)]
+
+#[macro_use]
+extern crate macro_rules;
+
+fn distinct_lifetimes(_x: &u8, _y: &u8, _z: u8) {}
+
+fn distinct_and_static(_x: &u8, _y: &u8, _z: &'static u8) {}
+
+// No error; same lifetime on two params.
+fn same_lifetime_on_input<'a>(_x: &'a u8, _y: &'a u8) {}
+
+// No error; static involved.
+fn only_static_on_input(_x: &u8, _y: &u8, _z: &'static u8) {}
+
+fn mut_and_static_input(_x: &mut u8, _y: &'static str) {}
+
+fn in_and_out(x: &u8, _y: u8) -> &u8 {
+ x
+}
+
+// No error; multiple input refs.
+fn multiple_in_and_out_1<'a>(x: &'a u8, _y: &'a u8) -> &'a u8 {
+ x
+}
+
+// Error; multiple input refs, but the output lifetime is not elided, i.e., the following is valid:
+// fn multiple_in_and_out_2a<'a>(x: &'a u8, _y: &u8) -> &'a u8
+// ^^^
+fn multiple_in_and_out_2a<'a>(x: &'a u8, _y: &u8) -> &'a u8 {
+ x
+}
+
+// Error; multiple input refs, but the output lifetime is not elided, i.e., the following is valid:
+// fn multiple_in_and_out_2b<'b>(_x: &u8, y: &'b u8) -> &'b u8
+// ^^^
+fn multiple_in_and_out_2b<'b>(_x: &u8, y: &'b u8) -> &'b u8 {
+ y
+}
+
+// No error; multiple input refs
+async fn func<'a>(args: &[&'a str]) -> Option<&'a str> {
+ args.get(0).cloned()
+}
+
+// No error; static involved.
+fn in_static_and_out<'a>(x: &'a u8, _y: &'static u8) -> &'a u8 {
+ x
+}
+
+// Error; multiple input refs, but the output lifetime is not elided, i.e., the following is valid:
+// fn deep_reference_1a<'a>(x: &'a u8, _y: &u8) -> Result<&'a u8, ()>
+// ^^^
+fn deep_reference_1a<'a>(x: &'a u8, _y: &u8) -> Result<&'a u8, ()> {
+ Ok(x)
+}
+
+// Error; multiple input refs, but the output lifetime is not elided, i.e., the following is valid:
+// fn deep_reference_1b<'b>(_x: &u8, y: &'b u8) -> Result<&'b u8, ()>
+// ^^^
+fn deep_reference_1b<'b>(_x: &u8, y: &'b u8) -> Result<&'b u8, ()> {
+ Ok(y)
+}
+
+// No error; two input refs.
+fn deep_reference_2<'a>(x: Result<&'a u8, &'a u8>) -> &'a u8 {
+ x.unwrap()
+}
+
+fn deep_reference_3(x: &u8, _y: u8) -> Result<&u8, ()> {
+ Ok(x)
+}
+
+// Where-clause, but without lifetimes.
+fn where_clause_without_lt<T>(x: &u8, _y: u8) -> Result<&u8, ()>
+where
+ T: Copy,
+{
+ Ok(x)
+}
+
+type Ref<'r> = &'r u8;
+
+// No error; same lifetime on two params.
+fn lifetime_param_1<'a>(_x: Ref<'a>, _y: &'a u8) {}
+
+fn lifetime_param_2(_x: Ref<'_>, _y: &u8) {}
+
+// No error; bounded lifetime.
+fn lifetime_param_3<'a, 'b: 'a>(_x: Ref<'a>, _y: &'b u8) {}
+
+// No error; bounded lifetime.
+fn lifetime_param_4<'a, 'b>(_x: Ref<'a>, _y: &'b u8)
+where
+ 'b: 'a,
+{
+}
+
+struct Lt<'a, I: 'static> {
+ x: &'a I,
+}
+
+// No error; fn bound references `'a`.
+fn fn_bound<'a, F, I>(_m: Lt<'a, I>, _f: F) -> Lt<'a, I>
+where
+ F: Fn(Lt<'a, I>) -> Lt<'a, I>,
+{
+ unreachable!()
+}
+
+fn fn_bound_2<F, I>(_m: Lt<'_, I>, _f: F) -> Lt<'_, I>
+where
+ for<'x> F: Fn(Lt<'x, I>) -> Lt<'x, I>,
+{
+ unreachable!()
+}
+
+// No error; see below.
+fn fn_bound_3<'a, F: FnOnce(&'a i32)>(x: &'a i32, f: F) {
+ f(x);
+}
+
+fn fn_bound_3_cannot_elide() {
+ let x = 42;
+ let p = &x;
+ let mut q = &x;
+ // This will fail if we elide lifetimes of `fn_bound_3`.
+ fn_bound_3(p, |y| q = y);
+}
+
+// No error; multiple input refs.
+fn fn_bound_4<'a, F: FnOnce() -> &'a ()>(cond: bool, x: &'a (), f: F) -> &'a () {
+ if cond { x } else { f() }
+}
+
+struct X {
+ x: u8,
+}
+
+impl X {
+ fn self_and_out(&self) -> &u8 {
+ &self.x
+ }
+
+ // Error; multiple input refs, but the output lifetime is not elided, i.e., the following is valid:
+ // fn self_and_in_out_1<'s>(&'s self, _x: &u8) -> &'s u8
+ // ^^^
+ fn self_and_in_out_1<'s>(&'s self, _x: &u8) -> &'s u8 {
+ &self.x
+ }
+
+ // Error; multiple input refs, but the output lifetime is not elided, i.e., the following is valid:
+ // fn self_and_in_out_2<'t>(&self, x: &'t u8) -> &'t u8
+ // ^^^^^
+ fn self_and_in_out_2<'t>(&self, x: &'t u8) -> &'t u8 {
+ x
+ }
+
+ fn distinct_self_and_in(&self, _x: &u8) {}
+
+ // No error; same lifetimes on two params.
+ fn self_and_same_in<'s>(&'s self, _x: &'s u8) {}
+}
+
+struct Foo<'a>(&'a u8);
+
+impl<'a> Foo<'a> {
+ // No error; lifetime `'a` not defined in method.
+ fn self_shared_lifetime(&self, _: &'a u8) {}
+ // No error; bounds exist.
+ fn self_bound_lifetime<'b: 'a>(&self, _: &'b u8) {}
+}
+
+fn already_elided<'a>(_: &u8, _: &'a u8) -> &'a u8 {
+ unimplemented!()
+}
+
+fn struct_with_lt(_foo: Foo<'_>) -> &str {
+ unimplemented!()
+}
+
+// No warning; two input lifetimes (named on the reference, anonymous on `Foo`).
+fn struct_with_lt2<'a>(_foo: &'a Foo) -> &'a str {
+ unimplemented!()
+}
+
+// No warning; two input lifetimes (anonymous on the reference, named on `Foo`).
+fn struct_with_lt3<'a>(_foo: &Foo<'a>) -> &'a str {
+ unimplemented!()
+}
+
+// Warning; two input lifetimes, but the output lifetime is not elided, i.e., the following is
+// valid:
+// fn struct_with_lt4a<'a>(_foo: &'a Foo<'_>) -> &'a str
+// ^^
+fn struct_with_lt4a<'a>(_foo: &'a Foo<'_>) -> &'a str {
+ unimplemented!()
+}
+
+// Warning; two input lifetimes, but the output lifetime is not elided, i.e., the following is
+// valid:
+// fn struct_with_lt4b<'b>(_foo: &Foo<'b>) -> &'b str
+// ^^^^
+fn struct_with_lt4b<'b>(_foo: &Foo<'b>) -> &'b str {
+ unimplemented!()
+}
+
+trait WithLifetime<'a> {}
+
+type WithLifetimeAlias<'a> = dyn WithLifetime<'a>;
+
+// Should not warn because it won't build without the lifetime.
+fn trait_obj_elided<'a>(_arg: &'a dyn WithLifetime) -> &'a str {
+ unimplemented!()
+}
+
+// Should warn because there is no lifetime on `Drop`, so this would be
+// unambiguous if we elided the lifetime.
+fn trait_obj_elided2(_arg: &dyn Drop) -> &str {
+ unimplemented!()
+}
+
+type FooAlias<'a> = Foo<'a>;
+
+fn alias_with_lt(_foo: FooAlias<'_>) -> &str {
+ unimplemented!()
+}
+
+// No warning; two input lifetimes (named on the reference, anonymous on `FooAlias`).
+fn alias_with_lt2<'a>(_foo: &'a FooAlias) -> &'a str {
+ unimplemented!()
+}
+
+// No warning; two input lifetimes (anonymous on the reference, named on `FooAlias`).
+fn alias_with_lt3<'a>(_foo: &FooAlias<'a>) -> &'a str {
+ unimplemented!()
+}
+
+// Warning; two input lifetimes, but the output lifetime is not elided, i.e., the following is
+// valid:
+// fn alias_with_lt4a<'a>(_foo: &'a FooAlias<'_>) -> &'a str
+// ^^
+fn alias_with_lt4a<'a>(_foo: &'a FooAlias<'_>) -> &'a str {
+ unimplemented!()
+}
+
+// Warning; two input lifetimes, but the output lifetime is not elided, i.e., the following is
+// valid:
+// fn alias_with_lt4b<'b>(_foo: &FooAlias<'b>) -> &'b str
+// ^^^^^^^^^
+fn alias_with_lt4b<'b>(_foo: &FooAlias<'b>) -> &'b str {
+ unimplemented!()
+}
+
+fn named_input_elided_output(_arg: &str) -> &str {
+ unimplemented!()
+}
+
+fn elided_input_named_output<'a>(_arg: &str) -> &'a str {
+ unimplemented!()
+}
+
+fn trait_bound_ok<T: WithLifetime<'static>>(_: &u8, _: T) {
+ unimplemented!()
+}
+fn trait_bound<'a, T: WithLifetime<'a>>(_: &'a u8, _: T) {
+ unimplemented!()
+}
+
+// Don't warn on these; see issue #292.
+fn trait_bound_bug<'a, T: WithLifetime<'a>>() {
+ unimplemented!()
+}
+
+// See issue #740.
+struct Test {
+ vec: Vec<usize>,
+}
+
+impl Test {
+ fn iter<'a>(&'a self) -> Box<dyn Iterator<Item = usize> + 'a> {
+ unimplemented!()
+ }
+}
+
+trait LintContext<'a> {}
+
+fn f<'a, T: LintContext<'a>>(_: &T) {}
+
+fn test<'a>(x: &'a [u8]) -> u8 {
+ let y: &'a u8 = &x[5];
+ *y
+}
+
+// Issue #3284: give hint regarding lifetime in return type.
+struct Cow<'a> {
+ x: &'a str,
+}
+fn out_return_type_lts(e: &str) -> Cow<'_> {
+ unimplemented!()
+}
+
+// Make sure we still warn on implementations
+mod issue4291 {
+ trait BadTrait {
+ fn needless_lt(x: &u8) {}
+ }
+
+ impl BadTrait for () {
+ fn needless_lt(_x: &u8) {}
+ }
+}
+
+mod issue2944 {
+ trait Foo {}
+ struct Bar;
+ struct Baz<'a> {
+ bar: &'a Bar,
+ }
+
+ impl<'a> Foo for Baz<'a> {}
+ impl Bar {
+ fn baz(&self) -> impl Foo + '_ {
+ Baz { bar: self }
+ }
+ }
+}
+
+mod nested_elision_sites {
+ // issue #issue2944
+
+ // closure trait bounds subject to nested elision
+ // don't lint because they refer to outer lifetimes
+ fn trait_fn<'a>(i: &'a i32) -> impl Fn() -> &'a i32 {
+ move || i
+ }
+ fn trait_fn_mut<'a>(i: &'a i32) -> impl FnMut() -> &'a i32 {
+ move || i
+ }
+ fn trait_fn_once<'a>(i: &'a i32) -> impl FnOnce() -> &'a i32 {
+ move || i
+ }
+
+ // don't lint
+ fn impl_trait_in_input_position<'a>(f: impl Fn() -> &'a i32) -> &'a i32 {
+ f()
+ }
+ fn impl_trait_in_output_position<'a>(i: &'a i32) -> impl Fn() -> &'a i32 {
+ move || i
+ }
+ // lint
+ fn impl_trait_elidable_nested_named_lifetimes<'a>(i: &'a i32, f: impl for<'b> Fn(&'b i32) -> &'b i32) -> &'a i32 {
+ f(i)
+ }
+ fn impl_trait_elidable_nested_anonymous_lifetimes(i: &i32, f: impl Fn(&i32) -> &i32) -> &i32 {
+ f(i)
+ }
+
+ // don't lint
+ fn generics_not_elidable<'a, T: Fn() -> &'a i32>(f: T) -> &'a i32 {
+ f()
+ }
+ // lint
+ fn generics_elidable<T: Fn(&i32) -> &i32>(i: &i32, f: T) -> &i32 {
+ f(i)
+ }
+
+ // don't lint
+ fn where_clause_not_elidable<'a, T>(f: T) -> &'a i32
+ where
+ T: Fn() -> &'a i32,
+ {
+ f()
+ }
+ // lint
+ fn where_clause_elidadable<T>(i: &i32, f: T) -> &i32
+ where
+ T: Fn(&i32) -> &i32,
+ {
+ f(i)
+ }
+
+ // don't lint
+ fn pointer_fn_in_input_position<'a>(f: fn(&'a i32) -> &'a i32, i: &'a i32) -> &'a i32 {
+ f(i)
+ }
+ fn pointer_fn_in_output_position<'a>(_: &'a i32) -> fn(&'a i32) -> &'a i32 {
+ |i| i
+ }
+ // lint
+ fn pointer_fn_elidable(i: &i32, f: fn(&i32) -> &i32) -> &i32 {
+ f(i)
+ }
+
+ // don't lint
+ fn nested_fn_pointer_1<'a>(_: &'a i32) -> fn(fn(&'a i32) -> &'a i32) -> i32 {
+ |f| 42
+ }
+ fn nested_fn_pointer_2<'a>(_: &'a i32) -> impl Fn(fn(&'a i32)) {
+ |f| ()
+ }
+
+ // lint
+ fn nested_fn_pointer_3(_: &i32) -> fn(fn(&i32) -> &i32) -> i32 {
+ |f| 42
+ }
+ fn nested_fn_pointer_4(_: &i32) -> impl Fn(fn(&i32)) {
+ |f| ()
+ }
+}
+
+mod issue6159 {
+ use std::ops::Deref;
+ pub fn apply_deref<'a, T, F, R>(x: &'a T, f: F) -> R
+ where
+ T: Deref,
+ F: FnOnce(&'a T::Target) -> R,
+ {
+ f(x.deref())
+ }
+}
+
+mod issue7296 {
+ use std::rc::Rc;
+ use std::sync::Arc;
+
+ struct Foo;
+ impl Foo {
+ fn implicit(&self) -> &() {
+ &()
+ }
+ fn implicit_mut(&mut self) -> &() {
+ &()
+ }
+
+ fn explicit<'a>(self: &'a Arc<Self>) -> &'a () {
+ &()
+ }
+ fn explicit_mut<'a>(self: &'a mut Rc<Self>) -> &'a () {
+ &()
+ }
+
+ fn lifetime_elsewhere(self: Box<Self>, here: &()) -> &() {
+ &()
+ }
+ }
+
+ trait Bar {
+ fn implicit(&self) -> &();
+ fn implicit_provided(&self) -> &() {
+ &()
+ }
+
+ fn explicit<'a>(self: &'a Arc<Self>) -> &'a ();
+ fn explicit_provided<'a>(self: &'a Arc<Self>) -> &'a () {
+ &()
+ }
+
+ fn lifetime_elsewhere(self: Box<Self>, here: &()) -> &();
+ fn lifetime_elsewhere_provided(self: Box<Self>, here: &()) -> &() {
+ &()
+ }
+ }
+}
+
+mod pr_9743_false_negative_fix {
+ #![allow(unused)]
+
+ fn foo(x: &u8, y: &'_ u8) {}
+
+ fn bar(x: &u8, y: &'_ u8, z: &'_ u8) {}
+}
+
+mod pr_9743_output_lifetime_checks {
+ #![allow(unused)]
+
+ // lint: only one input
+ fn one_input(x: &u8) -> &u8 {
+ unimplemented!()
+ }
+
+ // lint: multiple inputs, output would not be elided
+ fn multiple_inputs_output_not_elided<'b>(x: &u8, y: &'b u8, z: &'b u8) -> &'b u8 {
+ unimplemented!()
+ }
+
+ // don't lint: multiple inputs, output would be elided (which would create an ambiguity)
+ fn multiple_inputs_output_would_be_elided<'a, 'b>(x: &'a u8, y: &'b u8, z: &'b u8) -> &'a u8 {
+ unimplemented!()
+ }
+}
+
+mod in_macro {
+ macro_rules! local_one_input_macro {
+ () => {
+ fn one_input(x: &u8) -> &u8 {
+ unimplemented!()
+ }
+ };
+ }
+
+ // lint local macro expands to function with needless lifetimes
+ local_one_input_macro!();
+
+ // no lint on external macro
+ macro_rules::needless_lifetime!();
+
+ macro_rules! expanded_lifetime {
+ ($l:lifetime) => {
+ fn f<$l>(arg: &$l str) -> &$l str {
+ arg
+ }
+ }
+ }
+
+ expanded_lifetime!('a);
+}
+
+mod issue5787 {
+ use std::sync::MutexGuard;
+
+ struct Foo;
+
+ impl Foo {
+ // doesn't get linted without async
+ pub async fn wait<'a, T>(&self, guard: MutexGuard<'a, T>) -> MutexGuard<'a, T> {
+ guard
+ }
+ }
+
+ async fn foo<'a>(_x: &i32, y: &'a str) -> &'a str {
+ y
+ }
+}
+
+fn main() {}
diff --git a/src/tools/clippy/tests/ui/needless_lifetimes.rs b/src/tools/clippy/tests/ui/needless_lifetimes.rs
index 2efc93675..ddfd10430 100644
--- a/src/tools/clippy/tests/ui/needless_lifetimes.rs
+++ b/src/tools/clippy/tests/ui/needless_lifetimes.rs
@@ -1,13 +1,20 @@
+// run-rustfix
+// aux-build:macro_rules.rs
+
#![warn(clippy::needless_lifetimes)]
#![allow(
- dead_code,
+ unused,
clippy::boxed_local,
+ clippy::extra_unused_type_parameters,
clippy::needless_pass_by_value,
clippy::unnecessary_wraps,
dyn_drop,
clippy::get_first
)]
+#[macro_use]
+extern crate macro_rules;
+
fn distinct_lifetimes<'a, 'b>(_x: &'a u8, _y: &'b u8, _z: u8) {}
fn distinct_and_static<'a, 'b>(_x: &'a u8, _y: &'b u8, _z: &'static u8) {}
@@ -495,4 +502,47 @@ mod pr_9743_output_lifetime_checks {
}
}
+mod in_macro {
+ macro_rules! local_one_input_macro {
+ () => {
+ fn one_input<'a>(x: &'a u8) -> &'a u8 {
+ unimplemented!()
+ }
+ };
+ }
+
+ // lint local macro expands to function with needless lifetimes
+ local_one_input_macro!();
+
+ // no lint on external macro
+ macro_rules::needless_lifetime!();
+
+ macro_rules! expanded_lifetime {
+ ($l:lifetime) => {
+ fn f<$l>(arg: &$l str) -> &$l str {
+ arg
+ }
+ }
+ }
+
+ expanded_lifetime!('a);
+}
+
+mod issue5787 {
+ use std::sync::MutexGuard;
+
+ struct Foo;
+
+ impl Foo {
+ // doesn't get linted without async
+ pub async fn wait<'a, T>(&self, guard: MutexGuard<'a, T>) -> MutexGuard<'a, T> {
+ guard
+ }
+ }
+
+ async fn foo<'a>(_x: &i32, y: &'a str) -> &'a str {
+ y
+ }
+}
+
fn main() {}
diff --git a/src/tools/clippy/tests/ui/needless_lifetimes.stderr b/src/tools/clippy/tests/ui/needless_lifetimes.stderr
index 5a7cf13c8..4e3c8f20d 100644
--- a/src/tools/clippy/tests/ui/needless_lifetimes.stderr
+++ b/src/tools/clippy/tests/ui/needless_lifetimes.stderr
@@ -1,316 +1,559 @@
error: the following explicit lifetimes could be elided: 'a, 'b
- --> $DIR/needless_lifetimes.rs:11:1
+ --> $DIR/needless_lifetimes.rs:18:1
|
LL | fn distinct_lifetimes<'a, 'b>(_x: &'a u8, _y: &'b u8, _z: u8) {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: `-D clippy::needless-lifetimes` implied by `-D warnings`
+help: elide the lifetimes
+ |
+LL - fn distinct_lifetimes<'a, 'b>(_x: &'a u8, _y: &'b u8, _z: u8) {}
+LL + fn distinct_lifetimes(_x: &u8, _y: &u8, _z: u8) {}
+ |
error: the following explicit lifetimes could be elided: 'a, 'b
- --> $DIR/needless_lifetimes.rs:13:1
+ --> $DIR/needless_lifetimes.rs:20:1
|
LL | fn distinct_and_static<'a, 'b>(_x: &'a u8, _y: &'b u8, _z: &'static u8) {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: elide the lifetimes
+ |
+LL - fn distinct_and_static<'a, 'b>(_x: &'a u8, _y: &'b u8, _z: &'static u8) {}
+LL + fn distinct_and_static(_x: &u8, _y: &u8, _z: &'static u8) {}
+ |
error: the following explicit lifetimes could be elided: 'a
- --> $DIR/needless_lifetimes.rs:23:1
+ --> $DIR/needless_lifetimes.rs:30:1
|
LL | fn in_and_out<'a>(x: &'a u8, _y: u8) -> &'a u8 {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: elide the lifetimes
+ |
+LL - fn in_and_out<'a>(x: &'a u8, _y: u8) -> &'a u8 {
+LL + fn in_and_out(x: &u8, _y: u8) -> &u8 {
+ |
error: the following explicit lifetimes could be elided: 'b
- --> $DIR/needless_lifetimes.rs:35:1
+ --> $DIR/needless_lifetimes.rs:42:1
|
LL | fn multiple_in_and_out_2a<'a, 'b>(x: &'a u8, _y: &'b u8) -> &'a u8 {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: elide the lifetimes
+ |
+LL - fn multiple_in_and_out_2a<'a, 'b>(x: &'a u8, _y: &'b u8) -> &'a u8 {
+LL + fn multiple_in_and_out_2a<'a>(x: &'a u8, _y: &u8) -> &'a u8 {
+ |
error: the following explicit lifetimes could be elided: 'a
- --> $DIR/needless_lifetimes.rs:42:1
+ --> $DIR/needless_lifetimes.rs:49:1
|
LL | fn multiple_in_and_out_2b<'a, 'b>(_x: &'a u8, y: &'b u8) -> &'b u8 {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: elide the lifetimes
+ |
+LL - fn multiple_in_and_out_2b<'a, 'b>(_x: &'a u8, y: &'b u8) -> &'b u8 {
+LL + fn multiple_in_and_out_2b<'b>(_x: &u8, y: &'b u8) -> &'b u8 {
+ |
error: the following explicit lifetimes could be elided: 'b
- --> $DIR/needless_lifetimes.rs:59:1
+ --> $DIR/needless_lifetimes.rs:66:1
|
LL | fn deep_reference_1a<'a, 'b>(x: &'a u8, _y: &'b u8) -> Result<&'a u8, ()> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: elide the lifetimes
+ |
+LL - fn deep_reference_1a<'a, 'b>(x: &'a u8, _y: &'b u8) -> Result<&'a u8, ()> {
+LL + fn deep_reference_1a<'a>(x: &'a u8, _y: &u8) -> Result<&'a u8, ()> {
+ |
error: the following explicit lifetimes could be elided: 'a
- --> $DIR/needless_lifetimes.rs:66:1
+ --> $DIR/needless_lifetimes.rs:73:1
|
LL | fn deep_reference_1b<'a, 'b>(_x: &'a u8, y: &'b u8) -> Result<&'b u8, ()> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: elide the lifetimes
+ |
+LL - fn deep_reference_1b<'a, 'b>(_x: &'a u8, y: &'b u8) -> Result<&'b u8, ()> {
+LL + fn deep_reference_1b<'b>(_x: &u8, y: &'b u8) -> Result<&'b u8, ()> {
+ |
error: the following explicit lifetimes could be elided: 'a
- --> $DIR/needless_lifetimes.rs:75:1
+ --> $DIR/needless_lifetimes.rs:82:1
|
LL | fn deep_reference_3<'a>(x: &'a u8, _y: u8) -> Result<&'a u8, ()> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: elide the lifetimes
+ |
+LL - fn deep_reference_3<'a>(x: &'a u8, _y: u8) -> Result<&'a u8, ()> {
+LL + fn deep_reference_3(x: &u8, _y: u8) -> Result<&u8, ()> {
+ |
error: the following explicit lifetimes could be elided: 'a
- --> $DIR/needless_lifetimes.rs:80:1
+ --> $DIR/needless_lifetimes.rs:87:1
|
LL | fn where_clause_without_lt<'a, T>(x: &'a u8, _y: u8) -> Result<&'a u8, ()>
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: elide the lifetimes
+ |
+LL - fn where_clause_without_lt<'a, T>(x: &'a u8, _y: u8) -> Result<&'a u8, ()>
+LL + fn where_clause_without_lt<T>(x: &u8, _y: u8) -> Result<&u8, ()>
+ |
error: the following explicit lifetimes could be elided: 'a, 'b
- --> $DIR/needless_lifetimes.rs:92:1
+ --> $DIR/needless_lifetimes.rs:99:1
|
LL | fn lifetime_param_2<'a, 'b>(_x: Ref<'a>, _y: &'b u8) {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
-help: replace with `'_` in generic arguments such as here
- --> $DIR/needless_lifetimes.rs:92:37
+help: elide the lifetimes
+ |
+LL - fn lifetime_param_2<'a, 'b>(_x: Ref<'a>, _y: &'b u8) {}
+LL + fn lifetime_param_2(_x: Ref<'_>, _y: &u8) {}
|
-LL | fn lifetime_param_2<'a, 'b>(_x: Ref<'a>, _y: &'b u8) {}
- | ^^
error: the following explicit lifetimes could be elided: 'a
- --> $DIR/needless_lifetimes.rs:116:1
+ --> $DIR/needless_lifetimes.rs:123:1
|
LL | fn fn_bound_2<'a, F, I>(_m: Lt<'a, I>, _f: F) -> Lt<'a, I>
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
-help: replace with `'_` in generic arguments such as here
- --> $DIR/needless_lifetimes.rs:116:32
+help: elide the lifetimes
+ |
+LL - fn fn_bound_2<'a, F, I>(_m: Lt<'a, I>, _f: F) -> Lt<'a, I>
+LL + fn fn_bound_2<F, I>(_m: Lt<'_, I>, _f: F) -> Lt<'_, I>
|
-LL | fn fn_bound_2<'a, F, I>(_m: Lt<'a, I>, _f: F) -> Lt<'a, I>
- | ^^
error: the following explicit lifetimes could be elided: 's
- --> $DIR/needless_lifetimes.rs:146:5
+ --> $DIR/needless_lifetimes.rs:153:5
|
LL | fn self_and_out<'s>(&'s self) -> &'s u8 {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: elide the lifetimes
+ |
+LL - fn self_and_out<'s>(&'s self) -> &'s u8 {
+LL + fn self_and_out(&self) -> &u8 {
+ |
error: the following explicit lifetimes could be elided: 't
- --> $DIR/needless_lifetimes.rs:153:5
+ --> $DIR/needless_lifetimes.rs:160:5
|
LL | fn self_and_in_out_1<'s, 't>(&'s self, _x: &'t u8) -> &'s u8 {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: elide the lifetimes
+ |
+LL - fn self_and_in_out_1<'s, 't>(&'s self, _x: &'t u8) -> &'s u8 {
+LL + fn self_and_in_out_1<'s>(&'s self, _x: &u8) -> &'s u8 {
+ |
error: the following explicit lifetimes could be elided: 's
- --> $DIR/needless_lifetimes.rs:160:5
+ --> $DIR/needless_lifetimes.rs:167:5
|
LL | fn self_and_in_out_2<'s, 't>(&'s self, x: &'t u8) -> &'t u8 {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: elide the lifetimes
+ |
+LL - fn self_and_in_out_2<'s, 't>(&'s self, x: &'t u8) -> &'t u8 {
+LL + fn self_and_in_out_2<'t>(&self, x: &'t u8) -> &'t u8 {
+ |
error: the following explicit lifetimes could be elided: 's, 't
- --> $DIR/needless_lifetimes.rs:164:5
+ --> $DIR/needless_lifetimes.rs:171:5
|
LL | fn distinct_self_and_in<'s, 't>(&'s self, _x: &'t u8) {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: elide the lifetimes
+ |
+LL - fn distinct_self_and_in<'s, 't>(&'s self, _x: &'t u8) {}
+LL + fn distinct_self_and_in(&self, _x: &u8) {}
+ |
error: the following explicit lifetimes could be elided: 'a
- --> $DIR/needless_lifetimes.rs:183:1
+ --> $DIR/needless_lifetimes.rs:190:1
|
LL | fn struct_with_lt<'a>(_foo: Foo<'a>) -> &'a str {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
-help: replace with `'_` in generic arguments such as here
- --> $DIR/needless_lifetimes.rs:183:33
+help: elide the lifetimes
+ |
+LL - fn struct_with_lt<'a>(_foo: Foo<'a>) -> &'a str {
+LL + fn struct_with_lt(_foo: Foo<'_>) -> &str {
|
-LL | fn struct_with_lt<'a>(_foo: Foo<'a>) -> &'a str {
- | ^^
error: the following explicit lifetimes could be elided: 'b
- --> $DIR/needless_lifetimes.rs:201:1
+ --> $DIR/needless_lifetimes.rs:208:1
|
LL | fn struct_with_lt4a<'a, 'b>(_foo: &'a Foo<'b>) -> &'a str {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
-help: replace with `'_` in generic arguments such as here
- --> $DIR/needless_lifetimes.rs:201:43
+help: elide the lifetimes
+ |
+LL - fn struct_with_lt4a<'a, 'b>(_foo: &'a Foo<'b>) -> &'a str {
+LL + fn struct_with_lt4a<'a>(_foo: &'a Foo<'_>) -> &'a str {
|
-LL | fn struct_with_lt4a<'a, 'b>(_foo: &'a Foo<'b>) -> &'a str {
- | ^^
error: the following explicit lifetimes could be elided: 'a
- --> $DIR/needless_lifetimes.rs:209:1
+ --> $DIR/needless_lifetimes.rs:216:1
|
LL | fn struct_with_lt4b<'a, 'b>(_foo: &'a Foo<'b>) -> &'b str {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: elide the lifetimes
+ |
+LL - fn struct_with_lt4b<'a, 'b>(_foo: &'a Foo<'b>) -> &'b str {
+LL + fn struct_with_lt4b<'b>(_foo: &Foo<'b>) -> &'b str {
+ |
error: the following explicit lifetimes could be elided: 'a
- --> $DIR/needless_lifetimes.rs:224:1
+ --> $DIR/needless_lifetimes.rs:231:1
|
LL | fn trait_obj_elided2<'a>(_arg: &'a dyn Drop) -> &'a str {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: elide the lifetimes
+ |
+LL - fn trait_obj_elided2<'a>(_arg: &'a dyn Drop) -> &'a str {
+LL + fn trait_obj_elided2(_arg: &dyn Drop) -> &str {
+ |
error: the following explicit lifetimes could be elided: 'a
- --> $DIR/needless_lifetimes.rs:230:1
+ --> $DIR/needless_lifetimes.rs:237:1
|
LL | fn alias_with_lt<'a>(_foo: FooAlias<'a>) -> &'a str {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
-help: replace with `'_` in generic arguments such as here
- --> $DIR/needless_lifetimes.rs:230:37
+help: elide the lifetimes
+ |
+LL - fn alias_with_lt<'a>(_foo: FooAlias<'a>) -> &'a str {
+LL + fn alias_with_lt(_foo: FooAlias<'_>) -> &str {
|
-LL | fn alias_with_lt<'a>(_foo: FooAlias<'a>) -> &'a str {
- | ^^
error: the following explicit lifetimes could be elided: 'b
- --> $DIR/needless_lifetimes.rs:248:1
+ --> $DIR/needless_lifetimes.rs:255:1
|
LL | fn alias_with_lt4a<'a, 'b>(_foo: &'a FooAlias<'b>) -> &'a str {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
-help: replace with `'_` in generic arguments such as here
- --> $DIR/needless_lifetimes.rs:248:47
+help: elide the lifetimes
+ |
+LL - fn alias_with_lt4a<'a, 'b>(_foo: &'a FooAlias<'b>) -> &'a str {
+LL + fn alias_with_lt4a<'a>(_foo: &'a FooAlias<'_>) -> &'a str {
|
-LL | fn alias_with_lt4a<'a, 'b>(_foo: &'a FooAlias<'b>) -> &'a str {
- | ^^
error: the following explicit lifetimes could be elided: 'a
- --> $DIR/needless_lifetimes.rs:256:1
+ --> $DIR/needless_lifetimes.rs:263:1
|
LL | fn alias_with_lt4b<'a, 'b>(_foo: &'a FooAlias<'b>) -> &'b str {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: elide the lifetimes
+ |
+LL - fn alias_with_lt4b<'a, 'b>(_foo: &'a FooAlias<'b>) -> &'b str {
+LL + fn alias_with_lt4b<'b>(_foo: &FooAlias<'b>) -> &'b str {
+ |
error: the following explicit lifetimes could be elided: 'a
- --> $DIR/needless_lifetimes.rs:260:1
+ --> $DIR/needless_lifetimes.rs:267:1
|
LL | fn named_input_elided_output<'a>(_arg: &'a str) -> &str {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: elide the lifetimes
+ |
+LL - fn named_input_elided_output<'a>(_arg: &'a str) -> &str {
+LL + fn named_input_elided_output(_arg: &str) -> &str {
+ |
error: the following explicit lifetimes could be elided: 'a
- --> $DIR/needless_lifetimes.rs:268:1
+ --> $DIR/needless_lifetimes.rs:275:1
|
LL | fn trait_bound_ok<'a, T: WithLifetime<'static>>(_: &'a u8, _: T) {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: elide the lifetimes
+ |
+LL - fn trait_bound_ok<'a, T: WithLifetime<'static>>(_: &'a u8, _: T) {
+LL + fn trait_bound_ok<T: WithLifetime<'static>>(_: &u8, _: T) {
+ |
error: the following explicit lifetimes could be elided: 'a
- --> $DIR/needless_lifetimes.rs:304:1
+ --> $DIR/needless_lifetimes.rs:311:1
|
LL | fn out_return_type_lts<'a>(e: &'a str) -> Cow<'a> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
-help: replace with `'_` in generic arguments such as here
- --> $DIR/needless_lifetimes.rs:304:47
+help: elide the lifetimes
+ |
+LL - fn out_return_type_lts<'a>(e: &'a str) -> Cow<'a> {
+LL + fn out_return_type_lts(e: &str) -> Cow<'_> {
|
-LL | fn out_return_type_lts<'a>(e: &'a str) -> Cow<'a> {
- | ^^
error: the following explicit lifetimes could be elided: 'a
- --> $DIR/needless_lifetimes.rs:311:9
+ --> $DIR/needless_lifetimes.rs:318:9
|
LL | fn needless_lt<'a>(x: &'a u8) {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: elide the lifetimes
+ |
+LL - fn needless_lt<'a>(x: &'a u8) {}
+LL + fn needless_lt(x: &u8) {}
+ |
error: the following explicit lifetimes could be elided: 'a
- --> $DIR/needless_lifetimes.rs:315:9
+ --> $DIR/needless_lifetimes.rs:322:9
|
LL | fn needless_lt<'a>(_x: &'a u8) {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: elide the lifetimes
+ |
+LL - fn needless_lt<'a>(_x: &'a u8) {}
+LL + fn needless_lt(_x: &u8) {}
+ |
error: the following explicit lifetimes could be elided: 'a
- --> $DIR/needless_lifetimes.rs:328:9
+ --> $DIR/needless_lifetimes.rs:335:9
|
LL | fn baz<'a>(&'a self) -> impl Foo + 'a {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: elide the lifetimes
+ |
+LL - fn baz<'a>(&'a self) -> impl Foo + 'a {
+LL + fn baz(&self) -> impl Foo + '_ {
+ |
error: the following explicit lifetimes could be elided: 'a
- --> $DIR/needless_lifetimes.rs:360:5
+ --> $DIR/needless_lifetimes.rs:367:5
|
LL | fn impl_trait_elidable_nested_anonymous_lifetimes<'a>(i: &'a i32, f: impl Fn(&i32) -> &i32) -> &'a i32 {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: elide the lifetimes
+ |
+LL - fn impl_trait_elidable_nested_anonymous_lifetimes<'a>(i: &'a i32, f: impl Fn(&i32) -> &i32) -> &'a i32 {
+LL + fn impl_trait_elidable_nested_anonymous_lifetimes(i: &i32, f: impl Fn(&i32) -> &i32) -> &i32 {
+ |
error: the following explicit lifetimes could be elided: 'a
- --> $DIR/needless_lifetimes.rs:369:5
+ --> $DIR/needless_lifetimes.rs:376:5
|
LL | fn generics_elidable<'a, T: Fn(&i32) -> &i32>(i: &'a i32, f: T) -> &'a i32 {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: elide the lifetimes
+ |
+LL - fn generics_elidable<'a, T: Fn(&i32) -> &i32>(i: &'a i32, f: T) -> &'a i32 {
+LL + fn generics_elidable<T: Fn(&i32) -> &i32>(i: &i32, f: T) -> &i32 {
+ |
error: the following explicit lifetimes could be elided: 'a
- --> $DIR/needless_lifetimes.rs:381:5
+ --> $DIR/needless_lifetimes.rs:388:5
|
LL | fn where_clause_elidadable<'a, T>(i: &'a i32, f: T) -> &'a i32
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: elide the lifetimes
+ |
+LL - fn where_clause_elidadable<'a, T>(i: &'a i32, f: T) -> &'a i32
+LL + fn where_clause_elidadable<T>(i: &i32, f: T) -> &i32
+ |
error: the following explicit lifetimes could be elided: 'a
- --> $DIR/needless_lifetimes.rs:396:5
+ --> $DIR/needless_lifetimes.rs:403:5
|
LL | fn pointer_fn_elidable<'a>(i: &'a i32, f: fn(&i32) -> &i32) -> &'a i32 {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: elide the lifetimes
+ |
+LL - fn pointer_fn_elidable<'a>(i: &'a i32, f: fn(&i32) -> &i32) -> &'a i32 {
+LL + fn pointer_fn_elidable(i: &i32, f: fn(&i32) -> &i32) -> &i32 {
+ |
error: the following explicit lifetimes could be elided: 'a
- --> $DIR/needless_lifetimes.rs:409:5
+ --> $DIR/needless_lifetimes.rs:416:5
|
LL | fn nested_fn_pointer_3<'a>(_: &'a i32) -> fn(fn(&i32) -> &i32) -> i32 {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: elide the lifetimes
+ |
+LL - fn nested_fn_pointer_3<'a>(_: &'a i32) -> fn(fn(&i32) -> &i32) -> i32 {
+LL + fn nested_fn_pointer_3(_: &i32) -> fn(fn(&i32) -> &i32) -> i32 {
+ |
error: the following explicit lifetimes could be elided: 'a
- --> $DIR/needless_lifetimes.rs:412:5
+ --> $DIR/needless_lifetimes.rs:419:5
|
LL | fn nested_fn_pointer_4<'a>(_: &'a i32) -> impl Fn(fn(&i32)) {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: elide the lifetimes
+ |
+LL - fn nested_fn_pointer_4<'a>(_: &'a i32) -> impl Fn(fn(&i32)) {
+LL + fn nested_fn_pointer_4(_: &i32) -> impl Fn(fn(&i32)) {
+ |
error: the following explicit lifetimes could be elided: 'a
- --> $DIR/needless_lifetimes.rs:434:9
+ --> $DIR/needless_lifetimes.rs:441:9
|
LL | fn implicit<'a>(&'a self) -> &'a () {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: elide the lifetimes
+ |
+LL - fn implicit<'a>(&'a self) -> &'a () {
+LL + fn implicit(&self) -> &() {
+ |
error: the following explicit lifetimes could be elided: 'a
- --> $DIR/needless_lifetimes.rs:437:9
+ --> $DIR/needless_lifetimes.rs:444:9
|
LL | fn implicit_mut<'a>(&'a mut self) -> &'a () {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: elide the lifetimes
+ |
+LL - fn implicit_mut<'a>(&'a mut self) -> &'a () {
+LL + fn implicit_mut(&mut self) -> &() {
+ |
error: the following explicit lifetimes could be elided: 'a
- --> $DIR/needless_lifetimes.rs:448:9
+ --> $DIR/needless_lifetimes.rs:455:9
|
LL | fn lifetime_elsewhere<'a>(self: Box<Self>, here: &'a ()) -> &'a () {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: elide the lifetimes
+ |
+LL - fn lifetime_elsewhere<'a>(self: Box<Self>, here: &'a ()) -> &'a () {
+LL + fn lifetime_elsewhere(self: Box<Self>, here: &()) -> &() {
+ |
error: the following explicit lifetimes could be elided: 'a
- --> $DIR/needless_lifetimes.rs:454:9
+ --> $DIR/needless_lifetimes.rs:461:9
|
LL | fn implicit<'a>(&'a self) -> &'a ();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: elide the lifetimes
+ |
+LL - fn implicit<'a>(&'a self) -> &'a ();
+LL + fn implicit(&self) -> &();
+ |
error: the following explicit lifetimes could be elided: 'a
- --> $DIR/needless_lifetimes.rs:455:9
+ --> $DIR/needless_lifetimes.rs:462:9
|
LL | fn implicit_provided<'a>(&'a self) -> &'a () {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: elide the lifetimes
+ |
+LL - fn implicit_provided<'a>(&'a self) -> &'a () {
+LL + fn implicit_provided(&self) -> &() {
+ |
error: the following explicit lifetimes could be elided: 'a
- --> $DIR/needless_lifetimes.rs:464:9
+ --> $DIR/needless_lifetimes.rs:471:9
|
LL | fn lifetime_elsewhere<'a>(self: Box<Self>, here: &'a ()) -> &'a ();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: elide the lifetimes
+ |
+LL - fn lifetime_elsewhere<'a>(self: Box<Self>, here: &'a ()) -> &'a ();
+LL + fn lifetime_elsewhere(self: Box<Self>, here: &()) -> &();
+ |
error: the following explicit lifetimes could be elided: 'a
- --> $DIR/needless_lifetimes.rs:465:9
+ --> $DIR/needless_lifetimes.rs:472:9
|
LL | fn lifetime_elsewhere_provided<'a>(self: Box<Self>, here: &'a ()) -> &'a () {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: elide the lifetimes
+ |
+LL - fn lifetime_elsewhere_provided<'a>(self: Box<Self>, here: &'a ()) -> &'a () {
+LL + fn lifetime_elsewhere_provided(self: Box<Self>, here: &()) -> &() {
+ |
error: the following explicit lifetimes could be elided: 'a
- --> $DIR/needless_lifetimes.rs:474:5
+ --> $DIR/needless_lifetimes.rs:481:5
|
LL | fn foo<'a>(x: &'a u8, y: &'_ u8) {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: elide the lifetimes
+ |
+LL - fn foo<'a>(x: &'a u8, y: &'_ u8) {}
+LL + fn foo(x: &u8, y: &'_ u8) {}
+ |
error: the following explicit lifetimes could be elided: 'a
- --> $DIR/needless_lifetimes.rs:476:5
+ --> $DIR/needless_lifetimes.rs:483:5
|
LL | fn bar<'a>(x: &'a u8, y: &'_ u8, z: &'_ u8) {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: elide the lifetimes
+ |
+LL - fn bar<'a>(x: &'a u8, y: &'_ u8, z: &'_ u8) {}
+LL + fn bar(x: &u8, y: &'_ u8, z: &'_ u8) {}
+ |
error: the following explicit lifetimes could be elided: 'a
- --> $DIR/needless_lifetimes.rs:483:5
+ --> $DIR/needless_lifetimes.rs:490:5
|
LL | fn one_input<'a>(x: &'a u8) -> &'a u8 {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: elide the lifetimes
+ |
+LL - fn one_input<'a>(x: &'a u8) -> &'a u8 {
+LL + fn one_input(x: &u8) -> &u8 {
+ |
error: the following explicit lifetimes could be elided: 'a
- --> $DIR/needless_lifetimes.rs:488:5
+ --> $DIR/needless_lifetimes.rs:495:5
|
LL | fn multiple_inputs_output_not_elided<'a, 'b>(x: &'a u8, y: &'b u8, z: &'b u8) -> &'b u8 {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: elide the lifetimes
+ |
+LL - fn multiple_inputs_output_not_elided<'a, 'b>(x: &'a u8, y: &'b u8, z: &'b u8) -> &'b u8 {
+LL + fn multiple_inputs_output_not_elided<'b>(x: &u8, y: &'b u8, z: &'b u8) -> &'b u8 {
+ |
+
+error: the following explicit lifetimes could be elided: 'a
+ --> $DIR/needless_lifetimes.rs:508:13
+ |
+LL | fn one_input<'a>(x: &'a u8) -> &'a u8 {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+...
+LL | local_one_input_macro!();
+ | ------------------------ in this macro invocation
+ |
+ = note: this error originates in the macro `local_one_input_macro` (in Nightly builds, run with -Z macro-backtrace for more info)
+help: elide the lifetimes
+ |
+LL - fn one_input<'a>(x: &'a u8) -> &'a u8 {
+LL + fn one_input(x: &u8) -> &u8 {
+ |
-error: aborting due to 45 previous errors
+error: aborting due to 46 previous errors
diff --git a/src/tools/clippy/tests/ui/needless_range_loop.stderr b/src/tools/clippy/tests/ui/needless_range_loop.stderr
index b31544ec3..cffa19bec 100644
--- a/src/tools/clippy/tests/ui/needless_range_loop.stderr
+++ b/src/tools/clippy/tests/ui/needless_range_loop.stderr
@@ -49,7 +49,7 @@ error: the loop variable `i` is used to index `vec`
LL | for i in 0..vec.len() {
| ^^^^^^^^^^^^
|
-help: consider using an iterator
+help: consider using an iterator and enumerate()
|
LL | for (i, <item>) in vec.iter().enumerate() {
| ~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~
@@ -126,7 +126,7 @@ error: the loop variable `i` is used to index `vec`
LL | for i in 5..vec.len() {
| ^^^^^^^^^^^^
|
-help: consider using an iterator
+help: consider using an iterator and enumerate()
|
LL | for (i, <item>) in vec.iter().enumerate().skip(5) {
| ~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -137,7 +137,7 @@ error: the loop variable `i` is used to index `vec`
LL | for i in 5..10 {
| ^^^^^
|
-help: consider using an iterator
+help: consider using an iterator and enumerate()
|
LL | for (i, <item>) in vec.iter().enumerate().take(10).skip(5) {
| ~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -148,7 +148,7 @@ error: the loop variable `i` is used to index `vec`
LL | for i in 0..vec.len() {
| ^^^^^^^^^^^^
|
-help: consider using an iterator
+help: consider using an iterator and enumerate()
|
LL | for (i, <item>) in vec.iter_mut().enumerate() {
| ~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~
diff --git a/src/tools/clippy/tests/ui/needless_return.fixed b/src/tools/clippy/tests/ui/needless_return.fixed
index ab1c0e590..0f525dd29 100644
--- a/src/tools/clippy/tests/ui/needless_return.fixed
+++ b/src/tools/clippy/tests/ui/needless_return.fixed
@@ -31,6 +31,16 @@ fn test_no_semicolon() -> bool {
true
}
+#[rustfmt::skip]
+fn test_multiple_semicolon() -> bool {
+ true
+}
+
+#[rustfmt::skip]
+fn test_multiple_semicolon_with_spaces() -> bool {
+ true
+}
+
fn test_if_block() -> bool {
if true {
true
@@ -287,4 +297,14 @@ fn issue10051() -> Result<String, String> {
}
}
+mod issue10049 {
+ fn single() -> u32 {
+ if true { 1 } else { 2 }
+ }
+
+ fn multiple(b1: bool, b2: bool, b3: bool) -> u32 {
+ (if b1 { 0 } else { 1 } | if b2 { 2 } else { 3 } | if b3 { 4 } else { 5 })
+ }
+}
+
fn main() {}
diff --git a/src/tools/clippy/tests/ui/needless_return.rs b/src/tools/clippy/tests/ui/needless_return.rs
index abed338bb..a1db8375d 100644
--- a/src/tools/clippy/tests/ui/needless_return.rs
+++ b/src/tools/clippy/tests/ui/needless_return.rs
@@ -31,6 +31,16 @@ fn test_no_semicolon() -> bool {
return true;
}
+#[rustfmt::skip]
+fn test_multiple_semicolon() -> bool {
+ return true;;;
+}
+
+#[rustfmt::skip]
+fn test_multiple_semicolon_with_spaces() -> bool {
+ return true;; ; ;
+}
+
fn test_if_block() -> bool {
if true {
return true;
@@ -297,4 +307,14 @@ fn issue10051() -> Result<String, String> {
}
}
+mod issue10049 {
+ fn single() -> u32 {
+ return if true { 1 } else { 2 };
+ }
+
+ fn multiple(b1: bool, b2: bool, b3: bool) -> u32 {
+ return if b1 { 0 } else { 1 } | if b2 { 2 } else { 3 } | if b3 { 4 } else { 5 };
+ }
+}
+
fn main() {}
diff --git a/src/tools/clippy/tests/ui/needless_return.stderr b/src/tools/clippy/tests/ui/needless_return.stderr
index 52eabf6e1..87d0cd3e1 100644
--- a/src/tools/clippy/tests/ui/needless_return.stderr
+++ b/src/tools/clippy/tests/ui/needless_return.stderr
@@ -16,7 +16,23 @@ LL | return true;
= help: remove `return`
error: unneeded `return` statement
- --> $DIR/needless_return.rs:36:9
+ --> $DIR/needless_return.rs:36:5
+ |
+LL | return true;;;
+ | ^^^^^^^^^^^
+ |
+ = help: remove `return`
+
+error: unneeded `return` statement
+ --> $DIR/needless_return.rs:41:5
+ |
+LL | return true;; ; ;
+ | ^^^^^^^^^^^
+ |
+ = help: remove `return`
+
+error: unneeded `return` statement
+ --> $DIR/needless_return.rs:46:9
|
LL | return true;
| ^^^^^^^^^^^
@@ -24,7 +40,7 @@ LL | return true;
= help: remove `return`
error: unneeded `return` statement
- --> $DIR/needless_return.rs:38:9
+ --> $DIR/needless_return.rs:48:9
|
LL | return false;
| ^^^^^^^^^^^^
@@ -32,7 +48,7 @@ LL | return false;
= help: remove `return`
error: unneeded `return` statement
- --> $DIR/needless_return.rs:44:17
+ --> $DIR/needless_return.rs:54:17
|
LL | true => return false,
| ^^^^^^^^^^^^
@@ -40,7 +56,7 @@ LL | true => return false,
= help: remove `return`
error: unneeded `return` statement
- --> $DIR/needless_return.rs:46:13
+ --> $DIR/needless_return.rs:56:13
|
LL | return true;
| ^^^^^^^^^^^
@@ -48,7 +64,7 @@ LL | return true;
= help: remove `return`
error: unneeded `return` statement
- --> $DIR/needless_return.rs:53:9
+ --> $DIR/needless_return.rs:63:9
|
LL | return true;
| ^^^^^^^^^^^
@@ -56,7 +72,7 @@ LL | return true;
= help: remove `return`
error: unneeded `return` statement
- --> $DIR/needless_return.rs:55:16
+ --> $DIR/needless_return.rs:65:16
|
LL | let _ = || return true;
| ^^^^^^^^^^^
@@ -64,7 +80,7 @@ LL | let _ = || return true;
= help: remove `return`
error: unneeded `return` statement
- --> $DIR/needless_return.rs:59:5
+ --> $DIR/needless_return.rs:69:5
|
LL | return the_answer!();
| ^^^^^^^^^^^^^^^^^^^^
@@ -72,7 +88,7 @@ LL | return the_answer!();
= help: remove `return`
error: unneeded `return` statement
- --> $DIR/needless_return.rs:62:21
+ --> $DIR/needless_return.rs:72:21
|
LL | fn test_void_fun() {
| _____________________^
@@ -82,7 +98,7 @@ LL | | return;
= help: remove `return`
error: unneeded `return` statement
- --> $DIR/needless_return.rs:67:11
+ --> $DIR/needless_return.rs:77:11
|
LL | if b {
| ___________^
@@ -92,7 +108,7 @@ LL | | return;
= help: remove `return`
error: unneeded `return` statement
- --> $DIR/needless_return.rs:69:13
+ --> $DIR/needless_return.rs:79:13
|
LL | } else {
| _____________^
@@ -102,7 +118,7 @@ LL | | return;
= help: remove `return`
error: unneeded `return` statement
- --> $DIR/needless_return.rs:77:14
+ --> $DIR/needless_return.rs:87:14
|
LL | _ => return,
| ^^^^^^
@@ -110,7 +126,7 @@ LL | _ => return,
= help: replace `return` with a unit value
error: unneeded `return` statement
- --> $DIR/needless_return.rs:85:24
+ --> $DIR/needless_return.rs:95:24
|
LL | let _ = 42;
| ________________________^
@@ -120,7 +136,7 @@ LL | | return;
= help: remove `return`
error: unneeded `return` statement
- --> $DIR/needless_return.rs:88:14
+ --> $DIR/needless_return.rs:98:14
|
LL | _ => return,
| ^^^^^^
@@ -128,7 +144,7 @@ LL | _ => return,
= help: replace `return` with a unit value
error: unneeded `return` statement
- --> $DIR/needless_return.rs:101:9
+ --> $DIR/needless_return.rs:111:9
|
LL | return String::from("test");
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -136,7 +152,7 @@ LL | return String::from("test");
= help: remove `return`
error: unneeded `return` statement
- --> $DIR/needless_return.rs:103:9
+ --> $DIR/needless_return.rs:113:9
|
LL | return String::new();
| ^^^^^^^^^^^^^^^^^^^^
@@ -144,7 +160,7 @@ LL | return String::new();
= help: remove `return`
error: unneeded `return` statement
- --> $DIR/needless_return.rs:125:32
+ --> $DIR/needless_return.rs:135:32
|
LL | bar.unwrap_or_else(|_| return)
| ^^^^^^
@@ -152,7 +168,7 @@ LL | bar.unwrap_or_else(|_| return)
= help: replace `return` with an empty block
error: unneeded `return` statement
- --> $DIR/needless_return.rs:129:21
+ --> $DIR/needless_return.rs:139:21
|
LL | let _ = || {
| _____________________^
@@ -162,7 +178,7 @@ LL | | return;
= help: remove `return`
error: unneeded `return` statement
- --> $DIR/needless_return.rs:132:20
+ --> $DIR/needless_return.rs:142:20
|
LL | let _ = || return;
| ^^^^^^
@@ -170,7 +186,7 @@ LL | let _ = || return;
= help: replace `return` with an empty block
error: unneeded `return` statement
- --> $DIR/needless_return.rs:138:32
+ --> $DIR/needless_return.rs:148:32
|
LL | res.unwrap_or_else(|_| return Foo)
| ^^^^^^^^^^
@@ -178,7 +194,7 @@ LL | res.unwrap_or_else(|_| return Foo)
= help: remove `return`
error: unneeded `return` statement
- --> $DIR/needless_return.rs:147:5
+ --> $DIR/needless_return.rs:157:5
|
LL | return true;
| ^^^^^^^^^^^
@@ -186,7 +202,7 @@ LL | return true;
= help: remove `return`
error: unneeded `return` statement
- --> $DIR/needless_return.rs:151:5
+ --> $DIR/needless_return.rs:161:5
|
LL | return true;
| ^^^^^^^^^^^
@@ -194,7 +210,7 @@ LL | return true;
= help: remove `return`
error: unneeded `return` statement
- --> $DIR/needless_return.rs:156:9
+ --> $DIR/needless_return.rs:166:9
|
LL | return true;
| ^^^^^^^^^^^
@@ -202,7 +218,7 @@ LL | return true;
= help: remove `return`
error: unneeded `return` statement
- --> $DIR/needless_return.rs:158:9
+ --> $DIR/needless_return.rs:168:9
|
LL | return false;
| ^^^^^^^^^^^^
@@ -210,7 +226,7 @@ LL | return false;
= help: remove `return`
error: unneeded `return` statement
- --> $DIR/needless_return.rs:164:17
+ --> $DIR/needless_return.rs:174:17
|
LL | true => return false,
| ^^^^^^^^^^^^
@@ -218,7 +234,7 @@ LL | true => return false,
= help: remove `return`
error: unneeded `return` statement
- --> $DIR/needless_return.rs:166:13
+ --> $DIR/needless_return.rs:176:13
|
LL | return true;
| ^^^^^^^^^^^
@@ -226,7 +242,7 @@ LL | return true;
= help: remove `return`
error: unneeded `return` statement
- --> $DIR/needless_return.rs:173:9
+ --> $DIR/needless_return.rs:183:9
|
LL | return true;
| ^^^^^^^^^^^
@@ -234,7 +250,7 @@ LL | return true;
= help: remove `return`
error: unneeded `return` statement
- --> $DIR/needless_return.rs:175:16
+ --> $DIR/needless_return.rs:185:16
|
LL | let _ = || return true;
| ^^^^^^^^^^^
@@ -242,7 +258,7 @@ LL | let _ = || return true;
= help: remove `return`
error: unneeded `return` statement
- --> $DIR/needless_return.rs:179:5
+ --> $DIR/needless_return.rs:189:5
|
LL | return the_answer!();
| ^^^^^^^^^^^^^^^^^^^^
@@ -250,7 +266,7 @@ LL | return the_answer!();
= help: remove `return`
error: unneeded `return` statement
- --> $DIR/needless_return.rs:182:33
+ --> $DIR/needless_return.rs:192:33
|
LL | async fn async_test_void_fun() {
| _________________________________^
@@ -260,7 +276,7 @@ LL | | return;
= help: remove `return`
error: unneeded `return` statement
- --> $DIR/needless_return.rs:187:11
+ --> $DIR/needless_return.rs:197:11
|
LL | if b {
| ___________^
@@ -270,7 +286,7 @@ LL | | return;
= help: remove `return`
error: unneeded `return` statement
- --> $DIR/needless_return.rs:189:13
+ --> $DIR/needless_return.rs:199:13
|
LL | } else {
| _____________^
@@ -280,7 +296,7 @@ LL | | return;
= help: remove `return`
error: unneeded `return` statement
- --> $DIR/needless_return.rs:197:14
+ --> $DIR/needless_return.rs:207:14
|
LL | _ => return,
| ^^^^^^
@@ -288,7 +304,7 @@ LL | _ => return,
= help: replace `return` with a unit value
error: unneeded `return` statement
- --> $DIR/needless_return.rs:210:9
+ --> $DIR/needless_return.rs:220:9
|
LL | return String::from("test");
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -296,7 +312,7 @@ LL | return String::from("test");
= help: remove `return`
error: unneeded `return` statement
- --> $DIR/needless_return.rs:212:9
+ --> $DIR/needless_return.rs:222:9
|
LL | return String::new();
| ^^^^^^^^^^^^^^^^^^^^
@@ -304,7 +320,7 @@ LL | return String::new();
= help: remove `return`
error: unneeded `return` statement
- --> $DIR/needless_return.rs:228:5
+ --> $DIR/needless_return.rs:238:5
|
LL | return format!("Hello {}", "world!");
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -312,7 +328,7 @@ LL | return format!("Hello {}", "world!");
= help: remove `return`
error: unneeded `return` statement
- --> $DIR/needless_return.rs:239:9
+ --> $DIR/needless_return.rs:249:9
|
LL | return true;
| ^^^^^^^^^^^
@@ -320,7 +336,7 @@ LL | return true;
= help: remove `return`
error: unneeded `return` statement
- --> $DIR/needless_return.rs:241:9
+ --> $DIR/needless_return.rs:251:9
|
LL | return false;
| ^^^^^^^^^^^^
@@ -328,7 +344,7 @@ LL | return false;
= help: remove `return`
error: unneeded `return` statement
- --> $DIR/needless_return.rs:248:13
+ --> $DIR/needless_return.rs:258:13
|
LL | return 10;
| ^^^^^^^^^
@@ -336,7 +352,7 @@ LL | return 10;
= help: remove `return`
error: unneeded `return` statement
- --> $DIR/needless_return.rs:251:13
+ --> $DIR/needless_return.rs:261:13
|
LL | return 100;
| ^^^^^^^^^^
@@ -344,7 +360,7 @@ LL | return 100;
= help: remove `return`
error: unneeded `return` statement
- --> $DIR/needless_return.rs:259:9
+ --> $DIR/needless_return.rs:269:9
|
LL | return 0;
| ^^^^^^^^
@@ -352,7 +368,7 @@ LL | return 0;
= help: remove `return`
error: unneeded `return` statement
- --> $DIR/needless_return.rs:266:13
+ --> $DIR/needless_return.rs:276:13
|
LL | return *(x as *const isize);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -360,7 +376,7 @@ LL | return *(x as *const isize);
= help: remove `return`
error: unneeded `return` statement
- --> $DIR/needless_return.rs:268:13
+ --> $DIR/needless_return.rs:278:13
|
LL | return !*(x as *const isize);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -368,7 +384,7 @@ LL | return !*(x as *const isize);
= help: remove `return`
error: unneeded `return` statement
- --> $DIR/needless_return.rs:275:20
+ --> $DIR/needless_return.rs:285:20
|
LL | let _ = 42;
| ____________________^
@@ -379,7 +395,7 @@ LL | | return;
= help: remove `return`
error: unneeded `return` statement
- --> $DIR/needless_return.rs:282:20
+ --> $DIR/needless_return.rs:292:20
|
LL | let _ = 42; return;
| ^^^^^^^
@@ -387,7 +403,7 @@ LL | let _ = 42; return;
= help: remove `return`
error: unneeded `return` statement
- --> $DIR/needless_return.rs:294:9
+ --> $DIR/needless_return.rs:304:9
|
LL | return Ok(format!("ok!"));
| ^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -395,12 +411,28 @@ LL | return Ok(format!("ok!"));
= help: remove `return`
error: unneeded `return` statement
- --> $DIR/needless_return.rs:296:9
+ --> $DIR/needless_return.rs:306:9
|
LL | return Err(format!("err!"));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= help: remove `return`
-error: aborting due to 48 previous errors
+error: unneeded `return` statement
+ --> $DIR/needless_return.rs:312:9
+ |
+LL | return if true { 1 } else { 2 };
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = help: remove `return`
+
+error: unneeded `return` statement
+ --> $DIR/needless_return.rs:316:9
+ |
+LL | return if b1 { 0 } else { 1 } | if b2 { 2 } else { 3 } | if b3 { 4 } else { 5 };
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = help: remove `return` and wrap the sequence with parentheses
+
+error: aborting due to 52 previous errors
diff --git a/src/tools/clippy/tests/ui/never_loop.rs b/src/tools/clippy/tests/ui/never_loop.rs
index 28e8f459d..29821ff96 100644
--- a/src/tools/clippy/tests/ui/never_loop.rs
+++ b/src/tools/clippy/tests/ui/never_loop.rs
@@ -250,6 +250,51 @@ pub fn test20() {
}
}
+pub fn test21() {
+ loop {
+ 'a: {
+ {}
+ break 'a;
+ }
+ }
+}
+
+// Issue 10304: code after break from block was not considered
+// unreachable code and was considered for further analysis of
+// whether the loop would ever be executed or not.
+pub fn test22() {
+ for _ in 0..10 {
+ 'block: {
+ break 'block;
+ return;
+ }
+ println!("looped");
+ }
+}
+
+pub fn test23() {
+ for _ in 0..10 {
+ 'block: {
+ for _ in 0..20 {
+ break 'block;
+ }
+ }
+ println!("looped");
+ }
+}
+
+pub fn test24() {
+ 'a: for _ in 0..10 {
+ 'b: {
+ let x = Some(1);
+ match x {
+ None => break 'a,
+ Some(_) => break 'b,
+ }
+ }
+ }
+}
+
fn main() {
test1();
test2();
diff --git a/src/tools/clippy/tests/ui/never_loop.stderr b/src/tools/clippy/tests/ui/never_loop.stderr
index b7029bf8b..704d44864 100644
--- a/src/tools/clippy/tests/ui/never_loop.stderr
+++ b/src/tools/clippy/tests/ui/never_loop.stderr
@@ -126,5 +126,18 @@ LL | | }
LL | | }
| |_____^
-error: aborting due to 11 previous errors
+error: this loop never actually loops
+ --> $DIR/never_loop.rs:278:13
+ |
+LL | / for _ in 0..20 {
+LL | | break 'block;
+LL | | }
+ | |_____________^
+ |
+help: if you need the first element of the iterator, try writing
+ |
+LL | if let Some(_) = (0..20).next() {
+ | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+error: aborting due to 12 previous errors
diff --git a/src/tools/clippy/tests/ui/new_without_default.rs b/src/tools/clippy/tests/ui/new_without_default.rs
index 65809023f..7803418cb 100644
--- a/src/tools/clippy/tests/ui/new_without_default.rs
+++ b/src/tools/clippy/tests/ui/new_without_default.rs
@@ -1,4 +1,9 @@
-#![allow(dead_code, clippy::missing_safety_doc, clippy::extra_unused_lifetimes)]
+#![allow(
+ dead_code,
+ clippy::missing_safety_doc,
+ clippy::extra_unused_lifetimes,
+ clippy::extra_unused_type_parameters
+)]
#![warn(clippy::new_without_default)]
pub struct Foo;
diff --git a/src/tools/clippy/tests/ui/new_without_default.stderr b/src/tools/clippy/tests/ui/new_without_default.stderr
index 212a69ab9..583dd327d 100644
--- a/src/tools/clippy/tests/ui/new_without_default.stderr
+++ b/src/tools/clippy/tests/ui/new_without_default.stderr
@@ -1,5 +1,5 @@
error: you should consider adding a `Default` implementation for `Foo`
- --> $DIR/new_without_default.rs:7:5
+ --> $DIR/new_without_default.rs:12:5
|
LL | / pub fn new() -> Foo {
LL | | Foo
@@ -17,7 +17,7 @@ LL + }
|
error: you should consider adding a `Default` implementation for `Bar`
- --> $DIR/new_without_default.rs:15:5
+ --> $DIR/new_without_default.rs:20:5
|
LL | / pub fn new() -> Self {
LL | | Bar
@@ -34,7 +34,7 @@ LL + }
|
error: you should consider adding a `Default` implementation for `LtKo<'c>`
- --> $DIR/new_without_default.rs:79:5
+ --> $DIR/new_without_default.rs:84:5
|
LL | / pub fn new() -> LtKo<'c> {
LL | | unimplemented!()
@@ -51,7 +51,7 @@ LL + }
|
error: you should consider adding a `Default` implementation for `NewNotEqualToDerive`
- --> $DIR/new_without_default.rs:172:5
+ --> $DIR/new_without_default.rs:177:5
|
LL | / pub fn new() -> Self {
LL | | NewNotEqualToDerive { foo: 1 }
@@ -68,7 +68,7 @@ LL + }
|
error: you should consider adding a `Default` implementation for `FooGenerics<T>`
- --> $DIR/new_without_default.rs:180:5
+ --> $DIR/new_without_default.rs:185:5
|
LL | / pub fn new() -> Self {
LL | | Self(Default::default())
@@ -85,7 +85,7 @@ LL + }
|
error: you should consider adding a `Default` implementation for `BarGenerics<T>`
- --> $DIR/new_without_default.rs:187:5
+ --> $DIR/new_without_default.rs:192:5
|
LL | / pub fn new() -> Self {
LL | | Self(Default::default())
@@ -102,7 +102,7 @@ LL + }
|
error: you should consider adding a `Default` implementation for `Foo<T>`
- --> $DIR/new_without_default.rs:198:9
+ --> $DIR/new_without_default.rs:203:9
|
LL | / pub fn new() -> Self {
LL | | todo!()
diff --git a/src/tools/clippy/tests/ui/no_mangle_with_rust_abi.fixed b/src/tools/clippy/tests/ui/no_mangle_with_rust_abi.fixed
new file mode 100644
index 000000000..d18dec22a
--- /dev/null
+++ b/src/tools/clippy/tests/ui/no_mangle_with_rust_abi.fixed
@@ -0,0 +1,48 @@
+// run-rustfix
+
+#![allow(unused)]
+#![warn(clippy::no_mangle_with_rust_abi)]
+
+#[no_mangle]
+extern "C" fn rust_abi_fn_one(arg_one: u32, arg_two: usize) {}
+
+#[no_mangle]
+pub extern "C" fn rust_abi_fn_two(arg_one: u32, arg_two: usize) {}
+
+/// # Safety
+/// This function shouldn't be called unless the horsemen are ready
+#[no_mangle]
+pub unsafe extern "C" fn rust_abi_fn_three(arg_one: u32, arg_two: usize) {}
+
+/// # Safety
+/// This function shouldn't be called unless the horsemen are ready
+#[no_mangle]
+unsafe extern "C" fn rust_abi_fn_four(arg_one: u32, arg_two: usize) {}
+
+#[no_mangle]
+extern "C" fn rust_abi_multiline_function_really_long_name_to_overflow_args_to_multiple_lines(
+ arg_one: u32,
+ arg_two: usize,
+) -> u32 {
+ 0
+}
+
+// Must not run on functions that explicitly opt in to Rust ABI with `extern "Rust"`
+#[no_mangle]
+#[rustfmt::skip]
+extern "Rust" fn rust_abi_fn_explicit_opt_in(arg_one: u32, arg_two: usize) {}
+
+fn rust_abi_fn_again(arg_one: u32, arg_two: usize) {}
+
+#[no_mangle]
+extern "C" fn c_abi_fn(arg_one: u32, arg_two: usize) {}
+
+extern "C" fn c_abi_fn_again(arg_one: u32, arg_two: usize) {}
+
+extern "C" {
+ fn c_abi_in_block(arg_one: u32, arg_two: usize);
+}
+
+fn main() {
+ // test code goes here
+}
diff --git a/src/tools/clippy/tests/ui/no_mangle_with_rust_abi.rs b/src/tools/clippy/tests/ui/no_mangle_with_rust_abi.rs
new file mode 100644
index 000000000..481e1b6d9
--- /dev/null
+++ b/src/tools/clippy/tests/ui/no_mangle_with_rust_abi.rs
@@ -0,0 +1,48 @@
+// run-rustfix
+
+#![allow(unused)]
+#![warn(clippy::no_mangle_with_rust_abi)]
+
+#[no_mangle]
+fn rust_abi_fn_one(arg_one: u32, arg_two: usize) {}
+
+#[no_mangle]
+pub fn rust_abi_fn_two(arg_one: u32, arg_two: usize) {}
+
+/// # Safety
+/// This function shouldn't be called unless the horsemen are ready
+#[no_mangle]
+pub unsafe fn rust_abi_fn_three(arg_one: u32, arg_two: usize) {}
+
+/// # Safety
+/// This function shouldn't be called unless the horsemen are ready
+#[no_mangle]
+unsafe fn rust_abi_fn_four(arg_one: u32, arg_two: usize) {}
+
+#[no_mangle]
+fn rust_abi_multiline_function_really_long_name_to_overflow_args_to_multiple_lines(
+ arg_one: u32,
+ arg_two: usize,
+) -> u32 {
+ 0
+}
+
+// Must not run on functions that explicitly opt in to Rust ABI with `extern "Rust"`
+#[no_mangle]
+#[rustfmt::skip]
+extern "Rust" fn rust_abi_fn_explicit_opt_in(arg_one: u32, arg_two: usize) {}
+
+fn rust_abi_fn_again(arg_one: u32, arg_two: usize) {}
+
+#[no_mangle]
+extern "C" fn c_abi_fn(arg_one: u32, arg_two: usize) {}
+
+extern "C" fn c_abi_fn_again(arg_one: u32, arg_two: usize) {}
+
+extern "C" {
+ fn c_abi_in_block(arg_one: u32, arg_two: usize);
+}
+
+fn main() {
+ // test code goes here
+}
diff --git a/src/tools/clippy/tests/ui/no_mangle_with_rust_abi.stderr b/src/tools/clippy/tests/ui/no_mangle_with_rust_abi.stderr
new file mode 100644
index 000000000..71517d318
--- /dev/null
+++ b/src/tools/clippy/tests/ui/no_mangle_with_rust_abi.stderr
@@ -0,0 +1,45 @@
+error: attribute #[no_mangle] set on a Rust ABI function
+ --> $DIR/no_mangle_with_rust_abi.rs:7:1
+ |
+LL | fn rust_abi_fn_one(arg_one: u32, arg_two: usize) {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `extern "C" fn rust_abi_fn_one(arg_one: u32, arg_two: usize)`
+ |
+ = note: `-D clippy::no-mangle-with-rust-abi` implied by `-D warnings`
+
+error: attribute #[no_mangle] set on a Rust ABI function
+ --> $DIR/no_mangle_with_rust_abi.rs:10:1
+ |
+LL | pub fn rust_abi_fn_two(arg_one: u32, arg_two: usize) {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `pub extern "C" fn rust_abi_fn_two(arg_one: u32, arg_two: usize)`
+
+error: attribute #[no_mangle] set on a Rust ABI function
+ --> $DIR/no_mangle_with_rust_abi.rs:15:1
+ |
+LL | pub unsafe fn rust_abi_fn_three(arg_one: u32, arg_two: usize) {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `pub unsafe extern "C" fn rust_abi_fn_three(arg_one: u32, arg_two: usize)`
+
+error: attribute #[no_mangle] set on a Rust ABI function
+ --> $DIR/no_mangle_with_rust_abi.rs:20:1
+ |
+LL | unsafe fn rust_abi_fn_four(arg_one: u32, arg_two: usize) {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unsafe extern "C" fn rust_abi_fn_four(arg_one: u32, arg_two: usize)`
+
+error: attribute #[no_mangle] set on a Rust ABI function
+ --> $DIR/no_mangle_with_rust_abi.rs:23:1
+ |
+LL | / fn rust_abi_multiline_function_really_long_name_to_overflow_args_to_multiple_lines(
+LL | | arg_one: u32,
+LL | | arg_two: usize,
+LL | | ) -> u32 {
+ | |________^
+ |
+help: try
+ |
+LL + extern "C" fn rust_abi_multiline_function_really_long_name_to_overflow_args_to_multiple_lines(
+LL + arg_one: u32,
+LL + arg_two: usize,
+LL ~ ) -> u32 {
+ |
+
+error: aborting due to 5 previous errors
+
diff --git a/src/tools/clippy/tests/ui/question_mark_used.rs b/src/tools/clippy/tests/ui/question_mark_used.rs
new file mode 100644
index 000000000..8c3ef7896
--- /dev/null
+++ b/src/tools/clippy/tests/ui/question_mark_used.rs
@@ -0,0 +1,15 @@
+// non rustfixable
+#![allow(unreachable_code)]
+#![allow(dead_code)]
+#![warn(clippy::question_mark_used)]
+
+fn other_function() -> Option<i32> {
+ Some(32)
+}
+
+fn my_function() -> Option<i32> {
+ other_function()?;
+ None
+}
+
+fn main() {}
diff --git a/src/tools/clippy/tests/ui/question_mark_used.stderr b/src/tools/clippy/tests/ui/question_mark_used.stderr
new file mode 100644
index 000000000..8b5fcbcdb
--- /dev/null
+++ b/src/tools/clippy/tests/ui/question_mark_used.stderr
@@ -0,0 +1,11 @@
+error: question mark operator was used
+ --> $DIR/question_mark_used.rs:11:5
+ |
+LL | other_function()?;
+ | ^^^^^^^^^^^^^^^^^
+ |
+ = help: consider using a custom macro or match expression
+ = note: `-D clippy::question-mark-used` implied by `-D warnings`
+
+error: aborting due to previous error
+
diff --git a/src/tools/clippy/tests/ui/redundant_field_names.fixed b/src/tools/clippy/tests/ui/redundant_field_names.fixed
index ec7f8ae92..276266a2d 100644
--- a/src/tools/clippy/tests/ui/redundant_field_names.fixed
+++ b/src/tools/clippy/tests/ui/redundant_field_names.fixed
@@ -1,7 +1,7 @@
// run-rustfix
#![warn(clippy::redundant_field_names)]
-#![allow(clippy::no_effect, dead_code, unused_variables)]
+#![allow(clippy::extra_unused_type_parameters, clippy::no_effect, dead_code, unused_variables)]
#[macro_use]
extern crate derive_new;
diff --git a/src/tools/clippy/tests/ui/redundant_field_names.rs b/src/tools/clippy/tests/ui/redundant_field_names.rs
index 73122016c..f674141c1 100644
--- a/src/tools/clippy/tests/ui/redundant_field_names.rs
+++ b/src/tools/clippy/tests/ui/redundant_field_names.rs
@@ -1,7 +1,7 @@
// run-rustfix
#![warn(clippy::redundant_field_names)]
-#![allow(clippy::no_effect, dead_code, unused_variables)]
+#![allow(clippy::extra_unused_type_parameters, clippy::no_effect, dead_code, unused_variables)]
#[macro_use]
extern crate derive_new;
diff --git a/src/tools/clippy/tests/ui/regex.rs b/src/tools/clippy/tests/ui/regex.rs
index f0e1a8128..ab8ac97a0 100644
--- a/src/tools/clippy/tests/ui/regex.rs
+++ b/src/tools/clippy/tests/ui/regex.rs
@@ -36,6 +36,10 @@ fn syntax_error() {
let raw_string_error = Regex::new(r"[...\/...]");
let raw_string_error = Regex::new(r#"[...\/...]"#);
+
+ let escaped_string_span = Regex::new("\\b\\c");
+
+ let aux_span = Regex::new("(?ixi)");
}
fn trivial_regex() {
diff --git a/src/tools/clippy/tests/ui/regex.stderr b/src/tools/clippy/tests/ui/regex.stderr
index 2424644c6..c2440f39e 100644
--- a/src/tools/clippy/tests/ui/regex.stderr
+++ b/src/tools/clippy/tests/ui/regex.stderr
@@ -29,7 +29,10 @@ error: regex syntax error: invalid character class range, the start must be <= t
LL | let some_unicode = Regex::new("[é-è]");
| ^^^
-error: regex syntax error on position 0: unclosed group
+error: regex parse error:
+ (
+ ^
+ error: unclosed group
--> $DIR/regex.rs:18:33
|
LL | let some_regex = Regex::new(OPENING_PAREN);
@@ -43,25 +46,37 @@ LL | let binary_pipe_in_wrong_position = BRegex::new("|");
|
= help: the regex is unlikely to be useful as it is
-error: regex syntax error on position 0: unclosed group
+error: regex parse error:
+ (
+ ^
+ error: unclosed group
--> $DIR/regex.rs:21:41
|
LL | let some_binary_regex = BRegex::new(OPENING_PAREN);
| ^^^^^^^^^^^^^
-error: regex syntax error on position 0: unclosed group
+error: regex parse error:
+ (
+ ^
+ error: unclosed group
--> $DIR/regex.rs:22:56
|
LL | let some_binary_regex_builder = BRegexBuilder::new(OPENING_PAREN);
| ^^^^^^^^^^^^^
-error: regex syntax error on position 0: unclosed group
+error: regex parse error:
+ (
+ ^
+ error: unclosed group
--> $DIR/regex.rs:34:37
|
LL | let set_error = RegexSet::new(&[OPENING_PAREN, r"[a-z]+/.(com|org|net)"]);
| ^^^^^^^^^^^^^
-error: regex syntax error on position 0: unclosed group
+error: regex parse error:
+ (
+ ^
+ error: unclosed group
--> $DIR/regex.rs:35:39
|
LL | let bset_error = BRegexSet::new(&[OPENING_PAREN, r"[a-z]+/.(com|org|net)"]);
@@ -79,8 +94,25 @@ error: regex syntax error: unrecognized escape sequence
LL | let raw_string_error = Regex::new(r#"[...//...]"#);
| ^^
+error: regex parse error:
+ /b/c
+ ^^
+ error: unrecognized escape sequence
+ --> $DIR/regex.rs:40:42
+ |
+LL | let escaped_string_span = Regex::new("/b/c");
+ | ^^^^^^^^
+ |
+ = help: consider using a raw string literal: `r".."`
+
+error: regex syntax error: duplicate flag
+ --> $DIR/regex.rs:42:34
+ |
+LL | let aux_span = Regex::new("(?ixi)");
+ | ^ ^
+
error: trivial regex
- --> $DIR/regex.rs:42:33
+ --> $DIR/regex.rs:46:33
|
LL | let trivial_eq = Regex::new("^foobar$");
| ^^^^^^^^^^
@@ -88,7 +120,7 @@ LL | let trivial_eq = Regex::new("^foobar$");
= help: consider using `==` on `str`s
error: trivial regex
- --> $DIR/regex.rs:44:48
+ --> $DIR/regex.rs:48:48
|
LL | let trivial_eq_builder = RegexBuilder::new("^foobar$");
| ^^^^^^^^^^
@@ -96,7 +128,7 @@ LL | let trivial_eq_builder = RegexBuilder::new("^foobar$");
= help: consider using `==` on `str`s
error: trivial regex
- --> $DIR/regex.rs:46:42
+ --> $DIR/regex.rs:50:42
|
LL | let trivial_starts_with = Regex::new("^foobar");
| ^^^^^^^^^
@@ -104,7 +136,7 @@ LL | let trivial_starts_with = Regex::new("^foobar");
= help: consider using `str::starts_with`
error: trivial regex
- --> $DIR/regex.rs:48:40
+ --> $DIR/regex.rs:52:40
|
LL | let trivial_ends_with = Regex::new("foobar$");
| ^^^^^^^^^
@@ -112,7 +144,7 @@ LL | let trivial_ends_with = Regex::new("foobar$");
= help: consider using `str::ends_with`
error: trivial regex
- --> $DIR/regex.rs:50:39
+ --> $DIR/regex.rs:54:39
|
LL | let trivial_contains = Regex::new("foobar");
| ^^^^^^^^
@@ -120,7 +152,7 @@ LL | let trivial_contains = Regex::new("foobar");
= help: consider using `str::contains`
error: trivial regex
- --> $DIR/regex.rs:52:39
+ --> $DIR/regex.rs:56:39
|
LL | let trivial_contains = Regex::new(NOT_A_REAL_REGEX);
| ^^^^^^^^^^^^^^^^
@@ -128,7 +160,7 @@ LL | let trivial_contains = Regex::new(NOT_A_REAL_REGEX);
= help: consider using `str::contains`
error: trivial regex
- --> $DIR/regex.rs:54:40
+ --> $DIR/regex.rs:58:40
|
LL | let trivial_backslash = Regex::new("a/.b");
| ^^^^^^^
@@ -136,7 +168,7 @@ LL | let trivial_backslash = Regex::new("a/.b");
= help: consider using `str::contains`
error: trivial regex
- --> $DIR/regex.rs:57:36
+ --> $DIR/regex.rs:61:36
|
LL | let trivial_empty = Regex::new("");
| ^^
@@ -144,7 +176,7 @@ LL | let trivial_empty = Regex::new("");
= help: the regex is unlikely to be useful as it is
error: trivial regex
- --> $DIR/regex.rs:59:36
+ --> $DIR/regex.rs:63:36
|
LL | let trivial_empty = Regex::new("^");
| ^^^
@@ -152,7 +184,7 @@ LL | let trivial_empty = Regex::new("^");
= help: the regex is unlikely to be useful as it is
error: trivial regex
- --> $DIR/regex.rs:61:36
+ --> $DIR/regex.rs:65:36
|
LL | let trivial_empty = Regex::new("^$");
| ^^^^
@@ -160,12 +192,12 @@ LL | let trivial_empty = Regex::new("^$");
= help: consider using `str::is_empty`
error: trivial regex
- --> $DIR/regex.rs:63:44
+ --> $DIR/regex.rs:67:44
|
LL | let binary_trivial_empty = BRegex::new("^$");
| ^^^^
|
= help: consider using `str::is_empty`
-error: aborting due to 23 previous errors
+error: aborting due to 25 previous errors
diff --git a/src/tools/clippy/tests/ui/seek_to_start_instead_of_rewind.fixed b/src/tools/clippy/tests/ui/seek_to_start_instead_of_rewind.fixed
index 713cff604..dc24d447c 100644
--- a/src/tools/clippy/tests/ui/seek_to_start_instead_of_rewind.fixed
+++ b/src/tools/clippy/tests/ui/seek_to_start_instead_of_rewind.fixed
@@ -26,7 +26,7 @@ fn seek_to_start_false_method(t: &mut StructWithSeekMethod) {
// This should NOT trigger clippy warning because
// StructWithSeekMethod does not implement std::io::Seek;
-fn seek_to_start_method_owned_false<T>(mut t: StructWithSeekMethod) {
+fn seek_to_start_method_owned_false(mut t: StructWithSeekMethod) {
t.seek(SeekFrom::Start(0));
}
@@ -38,7 +38,7 @@ fn seek_to_start_false_trait(t: &mut StructWithSeekTrait) {
// This should NOT trigger clippy warning because
// StructWithSeekMethod does not implement std::io::Seek;
-fn seek_to_start_false_trait_owned<T>(mut t: StructWithSeekTrait) {
+fn seek_to_start_false_trait_owned(mut t: StructWithSeekTrait) {
t.seek(SeekFrom::Start(0));
}
diff --git a/src/tools/clippy/tests/ui/seek_to_start_instead_of_rewind.rs b/src/tools/clippy/tests/ui/seek_to_start_instead_of_rewind.rs
index 467003a1a..4adde2c40 100644
--- a/src/tools/clippy/tests/ui/seek_to_start_instead_of_rewind.rs
+++ b/src/tools/clippy/tests/ui/seek_to_start_instead_of_rewind.rs
@@ -26,7 +26,7 @@ fn seek_to_start_false_method(t: &mut StructWithSeekMethod) {
// This should NOT trigger clippy warning because
// StructWithSeekMethod does not implement std::io::Seek;
-fn seek_to_start_method_owned_false<T>(mut t: StructWithSeekMethod) {
+fn seek_to_start_method_owned_false(mut t: StructWithSeekMethod) {
t.seek(SeekFrom::Start(0));
}
@@ -38,7 +38,7 @@ fn seek_to_start_false_trait(t: &mut StructWithSeekTrait) {
// This should NOT trigger clippy warning because
// StructWithSeekMethod does not implement std::io::Seek;
-fn seek_to_start_false_trait_owned<T>(mut t: StructWithSeekTrait) {
+fn seek_to_start_false_trait_owned(mut t: StructWithSeekTrait) {
t.seek(SeekFrom::Start(0));
}
diff --git a/src/tools/clippy/tests/ui/significant_drop_tightening.fixed b/src/tools/clippy/tests/ui/significant_drop_tightening.fixed
new file mode 100644
index 000000000..da998c610
--- /dev/null
+++ b/src/tools/clippy/tests/ui/significant_drop_tightening.fixed
@@ -0,0 +1,84 @@
+// run-rustfix
+
+#![warn(clippy::significant_drop_tightening)]
+
+use std::sync::Mutex;
+
+pub fn complex_return_triggers_the_lint() -> i32 {
+ fn foo() -> i32 {
+ 1
+ }
+ let mutex = Mutex::new(1);
+ let lock = mutex.lock().unwrap();
+ let _ = *lock;
+ let _ = *lock;
+ drop(lock);
+ foo()
+}
+
+pub fn path_return_can_be_ignored() -> i32 {
+ let mutex = Mutex::new(1);
+ let lock = mutex.lock().unwrap();
+ let rslt = *lock;
+ let _ = *lock;
+ rslt
+}
+
+pub fn post_bindings_can_be_ignored() {
+ let mutex = Mutex::new(1);
+ let lock = mutex.lock().unwrap();
+ let rslt = *lock;
+ let another = rslt;
+ let _ = another;
+}
+
+pub fn unnecessary_contention_with_multiple_owned_results() {
+ {
+ let mutex = Mutex::new(1i32);
+ let lock = mutex.lock().unwrap();
+ let _ = lock.abs();
+ let _ = lock.is_positive();
+ }
+
+ {
+ let mutex = Mutex::new(1i32);
+ let lock = mutex.lock().unwrap();
+ let rslt0 = lock.abs();
+ let rslt1 = lock.is_positive();
+ drop(lock);
+ do_heavy_computation_that_takes_time((rslt0, rslt1));
+ }
+}
+
+pub fn unnecessary_contention_with_single_owned_results() {
+ {
+ let mutex = Mutex::new(1i32);
+ let lock = mutex.lock().unwrap();
+ let _ = lock.abs();
+ }
+ {
+ let mutex = Mutex::new(vec![1i32]);
+ let mut lock = mutex.lock().unwrap();
+ lock.clear();
+ }
+
+ {
+ let mutex = Mutex::new(1i32);
+
+ let rslt0 = mutex.lock().unwrap().abs();
+
+ do_heavy_computation_that_takes_time(rslt0);
+ }
+ {
+ let mutex = Mutex::new(vec![1i32]);
+
+ mutex.lock().unwrap().clear();
+
+ do_heavy_computation_that_takes_time(());
+ }
+}
+
+// Marker used for illustration purposes.
+pub fn do_heavy_computation_that_takes_time<T>(_: T) {}
+
+fn main() {}
diff --git a/src/tools/clippy/tests/ui/significant_drop_tightening.rs b/src/tools/clippy/tests/ui/significant_drop_tightening.rs
new file mode 100644
index 000000000..83823f95f
--- /dev/null
+++ b/src/tools/clippy/tests/ui/significant_drop_tightening.rs
@@ -0,0 +1,80 @@
+// run-rustfix
+
+#![warn(clippy::significant_drop_tightening)]
+
+use std::sync::Mutex;
+
+pub fn complex_return_triggers_the_lint() -> i32 {
+ fn foo() -> i32 {
+ 1
+ }
+ let mutex = Mutex::new(1);
+ let lock = mutex.lock().unwrap();
+ let _ = *lock;
+ let _ = *lock;
+ foo()
+}
+
+pub fn path_return_can_be_ignored() -> i32 {
+ let mutex = Mutex::new(1);
+ let lock = mutex.lock().unwrap();
+ let rslt = *lock;
+ let _ = *lock;
+ rslt
+}
+
+pub fn post_bindings_can_be_ignored() {
+ let mutex = Mutex::new(1);
+ let lock = mutex.lock().unwrap();
+ let rslt = *lock;
+ let another = rslt;
+ let _ = another;
+}
+
+pub fn unnecessary_contention_with_multiple_owned_results() {
+ {
+ let mutex = Mutex::new(1i32);
+ let lock = mutex.lock().unwrap();
+ let _ = lock.abs();
+ let _ = lock.is_positive();
+ }
+
+ {
+ let mutex = Mutex::new(1i32);
+ let lock = mutex.lock().unwrap();
+ let rslt0 = lock.abs();
+ let rslt1 = lock.is_positive();
+ do_heavy_computation_that_takes_time((rslt0, rslt1));
+ }
+}
+
+pub fn unnecessary_contention_with_single_owned_results() {
+ {
+ let mutex = Mutex::new(1i32);
+ let lock = mutex.lock().unwrap();
+ let _ = lock.abs();
+ }
+ {
+ let mutex = Mutex::new(vec![1i32]);
+ let mut lock = mutex.lock().unwrap();
+ lock.clear();
+ }
+
+ {
+ let mutex = Mutex::new(1i32);
+ let lock = mutex.lock().unwrap();
+ let rslt0 = lock.abs();
+ do_heavy_computation_that_takes_time(rslt0);
+ }
+ {
+ let mutex = Mutex::new(vec![1i32]);
+ let mut lock = mutex.lock().unwrap();
+ lock.clear();
+ do_heavy_computation_that_takes_time(());
+ }
+}
+
+// Marker used for illustration purposes.
+pub fn do_heavy_computation_that_takes_time<T>(_: T) {}
+
+fn main() {}
diff --git a/src/tools/clippy/tests/ui/significant_drop_tightening.stderr b/src/tools/clippy/tests/ui/significant_drop_tightening.stderr
new file mode 100644
index 000000000..ab8ce356e
--- /dev/null
+++ b/src/tools/clippy/tests/ui/significant_drop_tightening.stderr
@@ -0,0 +1,94 @@
+error: temporary with significant `Drop` can be early dropped
+ --> $DIR/significant_drop_tightening.rs:12:9
+ |
+LL | pub fn complex_return_triggers_the_lint() -> i32 {
+ | __________________________________________________-
+LL | | fn foo() -> i32 {
+LL | | 1
+LL | | }
+LL | | let mutex = Mutex::new(1);
+LL | | let lock = mutex.lock().unwrap();
+ | | ^^^^
+... |
+LL | | foo()
+LL | | }
+ | |_- temporary `lock` is currently being dropped at the end of its contained scope
+ |
+ = note: this might lead to unnecessary resource contention
+ = note: `-D clippy::significant-drop-tightening` implied by `-D warnings`
+help: drop the temporary after the end of its last usage
+ |
+LL ~ let _ = *lock;
+LL + drop(lock);
+ |
+
+error: temporary with significant `Drop` can be early dropped
+ --> $DIR/significant_drop_tightening.rs:44:13
+ |
+LL | / {
+LL | | let mutex = Mutex::new(1i32);
+LL | | let lock = mutex.lock().unwrap();
+ | | ^^^^
+LL | | let rslt0 = lock.abs();
+LL | | let rslt1 = lock.is_positive();
+LL | | do_heavy_computation_that_takes_time((rslt0, rslt1));
+LL | | }
+ | |_____- temporary `lock` is currently being dropped at the end of its contained scope
+ |
+ = note: this might lead to unnecessary resource contention
+help: drop the temporary after the end of its last usage
+ |
+LL ~ let rslt1 = lock.is_positive();
+LL + drop(lock);
+ |
+
+error: temporary with significant `Drop` can be early dropped
+ --> $DIR/significant_drop_tightening.rs:65:13
+ |
+LL | / {
+LL | | let mutex = Mutex::new(1i32);
+LL | | let lock = mutex.lock().unwrap();
+ | | ^^^^
+LL | | let rslt0 = lock.abs();
+LL | | do_heavy_computation_that_takes_time(rslt0);
+LL | | }
+ | |_____- temporary `lock` is currently being dropped at the end of its contained scope
+ |
+ = note: this might lead to unnecessary resource contention
+help: merge the temporary construction with its single usage
+ |
+LL ~
+LL + let rslt0 = mutex.lock().unwrap().abs();
+ |
+help: remove separated single usage
+ |
+LL - let rslt0 = lock.abs();
+LL +
+ |
+
+error: temporary with significant `Drop` can be early dropped
+ --> $DIR/significant_drop_tightening.rs:71:17
+ |
+LL | / {
+LL | | let mutex = Mutex::new(vec![1i32]);
+LL | | let mut lock = mutex.lock().unwrap();
+ | | ^^^^
+LL | | lock.clear();
+LL | | do_heavy_computation_that_takes_time(());
+LL | | }
+ | |_____- temporary `lock` is currently being dropped at the end of its contained scope
+ |
+ = note: this might lead to unnecessary resource contention
+help: merge the temporary construction with its single usage
+ |
+LL ~
+LL + mutex.lock().unwrap().clear();
+ |
+help: remove separated single usage
+ |
+LL - lock.clear();
+LL +
+ |
+
+error: aborting due to 4 previous errors
+
diff --git a/src/tools/clippy/tests/ui/suspicious_command_arg_space.rs b/src/tools/clippy/tests/ui/suspicious_command_arg_space.rs
new file mode 100644
index 000000000..bdc6113a2
--- /dev/null
+++ b/src/tools/clippy/tests/ui/suspicious_command_arg_space.rs
@@ -0,0 +1,10 @@
+fn main() {
+ // Things it should warn about:
+ std::process::Command::new("echo").arg("-n hello").spawn().unwrap();
+ std::process::Command::new("cat").arg("--number file").spawn().unwrap();
+
+ // Things it should not warn about:
+ std::process::Command::new("echo").arg("hello world").spawn().unwrap();
+ std::process::Command::new("a").arg("--fmt=%a %b %c").spawn().unwrap();
+ std::process::Command::new("b").arg("-ldflags=-s -w").spawn().unwrap();
+}
diff --git a/src/tools/clippy/tests/ui/suspicious_command_arg_space.stderr b/src/tools/clippy/tests/ui/suspicious_command_arg_space.stderr
new file mode 100644
index 000000000..9bc0ca93a
--- /dev/null
+++ b/src/tools/clippy/tests/ui/suspicious_command_arg_space.stderr
@@ -0,0 +1,25 @@
+error: single argument that looks like it should be multiple arguments
+ --> $DIR/suspicious_command_arg_space.rs:3:44
+ |
+LL | std::process::Command::new("echo").arg("-n hello").spawn().unwrap();
+ | ^^^^^^^^^^
+ |
+ = note: `-D clippy::suspicious-command-arg-space` implied by `-D warnings`
+help: consider splitting the argument
+ |
+LL | std::process::Command::new("echo").args(["-n", "hello"]).spawn().unwrap();
+ | ~~~~ ~~~~~~~~~~~~~~~
+
+error: single argument that looks like it should be multiple arguments
+ --> $DIR/suspicious_command_arg_space.rs:4:43
+ |
+LL | std::process::Command::new("cat").arg("--number file").spawn().unwrap();
+ | ^^^^^^^^^^^^^^^
+ |
+help: consider splitting the argument
+ |
+LL | std::process::Command::new("cat").args(["--number", "file"]).spawn().unwrap();
+ | ~~~~ ~~~~~~~~~~~~~~~~~~~~
+
+error: aborting due to 2 previous errors
+
diff --git a/src/tools/clippy/tests/ui/suspicious_to_owned.stderr b/src/tools/clippy/tests/ui/suspicious_to_owned.stderr
index dec3f50d6..c4ec7aa88 100644
--- a/src/tools/clippy/tests/ui/suspicious_to_owned.stderr
+++ b/src/tools/clippy/tests/ui/suspicious_to_owned.stderr
@@ -2,27 +2,62 @@ error: this `to_owned` call clones the Cow<'_, str> itself and does not cause th
--> $DIR/suspicious_to_owned.rs:16:13
|
LL | let _ = cow.to_owned();
- | ^^^^^^^^^^^^^^ help: consider using, depending on intent: `cow.clone()` or `cow.into_owned()`
+ | ^^^^^^^^^^^^^^
|
= note: `-D clippy::suspicious-to-owned` implied by `-D warnings`
+help: depending on intent, either make the Cow an Owned variant
+ |
+LL | let _ = cow.into_owned();
+ | ~~~~~~~~~~~~~~~~
+help: or clone the Cow itself
+ |
+LL | let _ = cow.clone();
+ | ~~~~~~~~~~~
error: this `to_owned` call clones the Cow<'_, [char; 3]> itself and does not cause the Cow<'_, [char; 3]> contents to become owned
--> $DIR/suspicious_to_owned.rs:26:13
|
LL | let _ = cow.to_owned();
- | ^^^^^^^^^^^^^^ help: consider using, depending on intent: `cow.clone()` or `cow.into_owned()`
+ | ^^^^^^^^^^^^^^
+ |
+help: depending on intent, either make the Cow an Owned variant
+ |
+LL | let _ = cow.into_owned();
+ | ~~~~~~~~~~~~~~~~
+help: or clone the Cow itself
+ |
+LL | let _ = cow.clone();
+ | ~~~~~~~~~~~
error: this `to_owned` call clones the Cow<'_, Vec<char>> itself and does not cause the Cow<'_, Vec<char>> contents to become owned
--> $DIR/suspicious_to_owned.rs:36:13
|
LL | let _ = cow.to_owned();
- | ^^^^^^^^^^^^^^ help: consider using, depending on intent: `cow.clone()` or `cow.into_owned()`
+ | ^^^^^^^^^^^^^^
+ |
+help: depending on intent, either make the Cow an Owned variant
+ |
+LL | let _ = cow.into_owned();
+ | ~~~~~~~~~~~~~~~~
+help: or clone the Cow itself
+ |
+LL | let _ = cow.clone();
+ | ~~~~~~~~~~~
error: this `to_owned` call clones the Cow<'_, str> itself and does not cause the Cow<'_, str> contents to become owned
--> $DIR/suspicious_to_owned.rs:46:13
|
LL | let _ = cow.to_owned();
- | ^^^^^^^^^^^^^^ help: consider using, depending on intent: `cow.clone()` or `cow.into_owned()`
+ | ^^^^^^^^^^^^^^
+ |
+help: depending on intent, either make the Cow an Owned variant
+ |
+LL | let _ = cow.into_owned();
+ | ~~~~~~~~~~~~~~~~
+help: or clone the Cow itself
+ |
+LL | let _ = cow.clone();
+ | ~~~~~~~~~~~
error: implicitly cloning a `String` by calling `to_owned` on its dereferenced type
--> $DIR/suspicious_to_owned.rs:60:13
diff --git a/src/tools/clippy/tests/ui/swap.fixed b/src/tools/clippy/tests/ui/swap.fixed
index 805a2ba5a..fa89706a8 100644
--- a/src/tools/clippy/tests/ui/swap.fixed
+++ b/src/tools/clippy/tests/ui/swap.fixed
@@ -7,7 +7,8 @@
clippy::redundant_clone,
redundant_semicolons,
dead_code,
- unused_assignments
+ unused_assignments,
+ unused_variables
)]
struct Foo(u32);
@@ -121,6 +122,27 @@ fn main() {
std::mem::swap(&mut c.0, &mut a);
; std::mem::swap(&mut c.0, &mut a);
+
+ std::mem::swap(&mut a, &mut b);
+
+ let mut c = 1;
+ let mut d = 2;
+ std::mem::swap(&mut d, &mut c);
+
+ let mut b = 1;
+ std::mem::swap(&mut a, &mut b);
+
+ let b = 1;
+ let a = 2;
+
+ let t = b;
+ let b = a;
+ let a = t;
+
+ let mut b = 1;
+ let mut a = 2;
+
+ std::mem::swap(&mut b, &mut a);
}
fn issue_8154() {
diff --git a/src/tools/clippy/tests/ui/swap.rs b/src/tools/clippy/tests/ui/swap.rs
index a8c878479..ef8a81c83 100644
--- a/src/tools/clippy/tests/ui/swap.rs
+++ b/src/tools/clippy/tests/ui/swap.rs
@@ -7,7 +7,8 @@
clippy::redundant_clone,
redundant_semicolons,
dead_code,
- unused_assignments
+ unused_assignments,
+ unused_variables
)]
struct Foo(u32);
@@ -143,6 +144,32 @@ fn main() {
; let t = c.0;
c.0 = a;
a = t;
+
+ let a = b;
+ let b = a;
+
+ let mut c = 1;
+ let mut d = 2;
+ d = c;
+ c = d;
+
+ let mut b = 1;
+ let a = b;
+ b = a;
+
+ let b = 1;
+ let a = 2;
+
+ let t = b;
+ let b = a;
+ let a = t;
+
+ let mut b = 1;
+ let mut a = 2;
+
+ let t = b;
+ b = a;
+ a = t;
}
fn issue_8154() {
diff --git a/src/tools/clippy/tests/ui/swap.stderr b/src/tools/clippy/tests/ui/swap.stderr
index ee4b7a508..f0acbfe25 100644
--- a/src/tools/clippy/tests/ui/swap.stderr
+++ b/src/tools/clippy/tests/ui/swap.stderr
@@ -1,5 +1,5 @@
error: this looks like you are swapping `bar.a` and `bar.b` manually
- --> $DIR/swap.rs:24:5
+ --> $DIR/swap.rs:25:5
|
LL | / let temp = bar.a;
LL | | bar.a = bar.b;
@@ -10,7 +10,7 @@ LL | | bar.b = temp;
= note: `-D clippy::manual-swap` implied by `-D warnings`
error: this looks like you are swapping elements of `foo` manually
- --> $DIR/swap.rs:36:5
+ --> $DIR/swap.rs:37:5
|
LL | / let temp = foo[0];
LL | | foo[0] = foo[1];
@@ -18,7 +18,7 @@ LL | | foo[1] = temp;
| |_________________^ help: try: `foo.swap(0, 1)`
error: this looks like you are swapping elements of `foo` manually
- --> $DIR/swap.rs:45:5
+ --> $DIR/swap.rs:46:5
|
LL | / let temp = foo[0];
LL | | foo[0] = foo[1];
@@ -26,7 +26,7 @@ LL | | foo[1] = temp;
| |_________________^ help: try: `foo.swap(0, 1)`
error: this looks like you are swapping elements of `foo` manually
- --> $DIR/swap.rs:64:5
+ --> $DIR/swap.rs:65:5
|
LL | / let temp = foo[0];
LL | | foo[0] = foo[1];
@@ -34,7 +34,7 @@ LL | | foo[1] = temp;
| |_________________^ help: try: `foo.swap(0, 1)`
error: this looks like you are swapping `a` and `b` manually
- --> $DIR/swap.rs:75:5
+ --> $DIR/swap.rs:76:5
|
LL | / a ^= b;
LL | | b ^= a;
@@ -42,7 +42,7 @@ LL | | a ^= b;
| |___________^ help: try: `std::mem::swap(&mut a, &mut b)`
error: this looks like you are swapping `bar.a` and `bar.b` manually
- --> $DIR/swap.rs:83:5
+ --> $DIR/swap.rs:84:5
|
LL | / bar.a ^= bar.b;
LL | | bar.b ^= bar.a;
@@ -50,7 +50,7 @@ LL | | bar.a ^= bar.b;
| |___________________^ help: try: `std::mem::swap(&mut bar.a, &mut bar.b)`
error: this looks like you are swapping elements of `foo` manually
- --> $DIR/swap.rs:91:5
+ --> $DIR/swap.rs:92:5
|
LL | / foo[0] ^= foo[1];
LL | | foo[1] ^= foo[0];
@@ -58,7 +58,7 @@ LL | | foo[0] ^= foo[1];
| |_____________________^ help: try: `foo.swap(0, 1)`
error: this looks like you are swapping `foo[0][1]` and `bar[1][0]` manually
- --> $DIR/swap.rs:120:5
+ --> $DIR/swap.rs:121:5
|
LL | / let temp = foo[0][1];
LL | | foo[0][1] = bar[1][0];
@@ -68,7 +68,7 @@ LL | | bar[1][0] = temp;
= note: or maybe you should use `std::mem::replace`?
error: this looks like you are swapping `a` and `b` manually
- --> $DIR/swap.rs:134:7
+ --> $DIR/swap.rs:135:7
|
LL | ; let t = a;
| _______^
@@ -79,7 +79,7 @@ LL | | b = t;
= note: or maybe you should use `std::mem::replace`?
error: this looks like you are swapping `c.0` and `a` manually
- --> $DIR/swap.rs:143:7
+ --> $DIR/swap.rs:144:7
|
LL | ; let t = c.0;
| _______^
@@ -89,8 +89,18 @@ LL | | a = t;
|
= note: or maybe you should use `std::mem::replace`?
+error: this looks like you are swapping `b` and `a` manually
+ --> $DIR/swap.rs:170:5
+ |
+LL | / let t = b;
+LL | | b = a;
+LL | | a = t;
+ | |_________^ help: try: `std::mem::swap(&mut b, &mut a)`
+ |
+ = note: or maybe you should use `std::mem::replace`?
+
error: this looks like you are trying to swap `a` and `b`
- --> $DIR/swap.rs:131:5
+ --> $DIR/swap.rs:132:5
|
LL | / a = b;
LL | | b = a;
@@ -100,7 +110,7 @@ LL | | b = a;
= note: `-D clippy::almost-swapped` implied by `-D warnings`
error: this looks like you are trying to swap `c.0` and `a`
- --> $DIR/swap.rs:140:5
+ --> $DIR/swap.rs:141:5
|
LL | / c.0 = a;
LL | | a = c.0;
@@ -108,8 +118,35 @@ LL | | a = c.0;
|
= note: or maybe you should use `std::mem::replace`?
+error: this looks like you are trying to swap `a` and `b`
+ --> $DIR/swap.rs:148:5
+ |
+LL | / let a = b;
+LL | | let b = a;
+ | |_____________^ help: try: `std::mem::swap(&mut a, &mut b)`
+ |
+ = note: or maybe you should use `std::mem::replace`?
+
+error: this looks like you are trying to swap `d` and `c`
+ --> $DIR/swap.rs:153:5
+ |
+LL | / d = c;
+LL | | c = d;
+ | |_________^ help: try: `std::mem::swap(&mut d, &mut c)`
+ |
+ = note: or maybe you should use `std::mem::replace`?
+
+error: this looks like you are trying to swap `a` and `b`
+ --> $DIR/swap.rs:157:5
+ |
+LL | / let a = b;
+LL | | b = a;
+ | |_________^ help: try: `std::mem::swap(&mut a, &mut b)`
+ |
+ = note: or maybe you should use `std::mem::replace`?
+
error: this looks like you are swapping `s.0.x` and `s.0.y` manually
- --> $DIR/swap.rs:178:5
+ --> $DIR/swap.rs:205:5
|
LL | / let t = s.0.x;
LL | | s.0.x = s.0.y;
@@ -118,5 +155,5 @@ LL | | s.0.y = t;
|
= note: or maybe you should use `std::mem::replace`?
-error: aborting due to 13 previous errors
+error: aborting due to 17 previous errors
diff --git a/src/tools/clippy/tests/ui/track-diagnostics.stderr b/src/tools/clippy/tests/ui/track-diagnostics.stderr
index ec3031862..39418d359 100644
--- a/src/tools/clippy/tests/ui/track-diagnostics.stderr
+++ b/src/tools/clippy/tests/ui/track-diagnostics.stderr
@@ -2,7 +2,7 @@ error[E0308]: mismatched types
--> $DIR/track-diagnostics.rs:LL:CC
|
LL | const S: A = B;
- | ^ expected struct `A`, found struct `B`
+ | ^ expected `A`, found `B`
-Ztrack-diagnostics: created at compiler/rustc_infer/src/infer/error_reporting/mod.rs:LL:CC
error: aborting due to previous error
diff --git a/src/tools/clippy/tests/ui/transmute_int_to_non_zero.rs b/src/tools/clippy/tests/ui/transmute_int_to_non_zero.rs
new file mode 100644
index 000000000..a38406782
--- /dev/null
+++ b/src/tools/clippy/tests/ui/transmute_int_to_non_zero.rs
@@ -0,0 +1,41 @@
+#![warn(clippy::transmute_int_to_non_zero)]
+
+use core::num::*;
+
+fn main() {
+ let int_u8: u8 = 1;
+ let int_u16: u16 = 1;
+ let int_u32: u32 = 1;
+ let int_u64: u64 = 1;
+ let int_u128: u128 = 1;
+
+ let int_i8: i8 = 1;
+ let int_i16: i16 = 1;
+ let int_i32: i32 = 1;
+ let int_i64: i64 = 1;
+ let int_i128: i128 = 1;
+
+ let _: NonZeroU8 = unsafe { std::mem::transmute(int_u8) };
+ let _: NonZeroU16 = unsafe { std::mem::transmute(int_u16) };
+ let _: NonZeroU32 = unsafe { std::mem::transmute(int_u32) };
+ let _: NonZeroU64 = unsafe { std::mem::transmute(int_u64) };
+ let _: NonZeroU128 = unsafe { std::mem::transmute(int_u128) };
+
+ let _: NonZeroI8 = unsafe { std::mem::transmute(int_i8) };
+ let _: NonZeroI16 = unsafe { std::mem::transmute(int_i16) };
+ let _: NonZeroI32 = unsafe { std::mem::transmute(int_i32) };
+ let _: NonZeroI64 = unsafe { std::mem::transmute(int_i64) };
+ let _: NonZeroI128 = unsafe { std::mem::transmute(int_i128) };
+
+ let _: NonZeroU8 = unsafe { NonZeroU8::new_unchecked(int_u8) };
+ let _: NonZeroU16 = unsafe { NonZeroU16::new_unchecked(int_u16) };
+ let _: NonZeroU32 = unsafe { NonZeroU32::new_unchecked(int_u32) };
+ let _: NonZeroU64 = unsafe { NonZeroU64::new_unchecked(int_u64) };
+ let _: NonZeroU128 = unsafe { NonZeroU128::new_unchecked(int_u128) };
+
+ let _: NonZeroI8 = unsafe { NonZeroI8::new_unchecked(int_i8) };
+ let _: NonZeroI16 = unsafe { NonZeroI16::new_unchecked(int_i16) };
+ let _: NonZeroI32 = unsafe { NonZeroI32::new_unchecked(int_i32) };
+ let _: NonZeroI64 = unsafe { NonZeroI64::new_unchecked(int_i64) };
+ let _: NonZeroI128 = unsafe { NonZeroI128::new_unchecked(int_i128) };
+}
diff --git a/src/tools/clippy/tests/ui/transmute_int_to_non_zero.stderr b/src/tools/clippy/tests/ui/transmute_int_to_non_zero.stderr
new file mode 100644
index 000000000..33f8ce79e
--- /dev/null
+++ b/src/tools/clippy/tests/ui/transmute_int_to_non_zero.stderr
@@ -0,0 +1,64 @@
+error: transmute from a `u8` to a `NonZeroU8`
+ --> $DIR/transmute_int_to_non_zero.rs:18:33
+ |
+LL | let _: NonZeroU8 = unsafe { std::mem::transmute(int_u8) };
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `NonZeroU8::new_unchecked(int_u8)`
+ |
+ = note: `-D clippy::transmute-int-to-non-zero` implied by `-D warnings`
+
+error: transmute from a `u16` to a `NonZeroU16`
+ --> $DIR/transmute_int_to_non_zero.rs:19:34
+ |
+LL | let _: NonZeroU16 = unsafe { std::mem::transmute(int_u16) };
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `NonZeroU16::new_unchecked(int_u16)`
+
+error: transmute from a `u32` to a `NonZeroU32`
+ --> $DIR/transmute_int_to_non_zero.rs:20:34
+ |
+LL | let _: NonZeroU32 = unsafe { std::mem::transmute(int_u32) };
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `NonZeroU32::new_unchecked(int_u32)`
+
+error: transmute from a `u64` to a `NonZeroU64`
+ --> $DIR/transmute_int_to_non_zero.rs:21:34
+ |
+LL | let _: NonZeroU64 = unsafe { std::mem::transmute(int_u64) };
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `NonZeroU64::new_unchecked(int_u64)`
+
+error: transmute from a `u128` to a `NonZeroU128`
+ --> $DIR/transmute_int_to_non_zero.rs:22:35
+ |
+LL | let _: NonZeroU128 = unsafe { std::mem::transmute(int_u128) };
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `NonZeroU128::new_unchecked(int_u128)`
+
+error: transmute from a `i8` to a `NonZeroI8`
+ --> $DIR/transmute_int_to_non_zero.rs:24:33
+ |
+LL | let _: NonZeroI8 = unsafe { std::mem::transmute(int_i8) };
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `NonZeroI8::new_unchecked(int_i8)`
+
+error: transmute from a `i16` to a `NonZeroI16`
+ --> $DIR/transmute_int_to_non_zero.rs:25:34
+ |
+LL | let _: NonZeroI16 = unsafe { std::mem::transmute(int_i16) };
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `NonZeroI16::new_unchecked(int_i16)`
+
+error: transmute from a `i32` to a `NonZeroI32`
+ --> $DIR/transmute_int_to_non_zero.rs:26:34
+ |
+LL | let _: NonZeroI32 = unsafe { std::mem::transmute(int_i32) };
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `NonZeroI32::new_unchecked(int_i32)`
+
+error: transmute from a `i64` to a `NonZeroI64`
+ --> $DIR/transmute_int_to_non_zero.rs:27:34
+ |
+LL | let _: NonZeroI64 = unsafe { std::mem::transmute(int_i64) };
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `NonZeroI64::new_unchecked(int_i64)`
+
+error: transmute from a `i128` to a `NonZeroI128`
+ --> $DIR/transmute_int_to_non_zero.rs:28:35
+ |
+LL | let _: NonZeroI128 = unsafe { std::mem::transmute(int_i128) };
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `NonZeroI128::new_unchecked(int_i128)`
+
+error: aborting due to 10 previous errors
+
diff --git a/src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.fixed b/src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.fixed
index 7263abac1..55307506e 100644
--- a/src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.fixed
+++ b/src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.fixed
@@ -51,6 +51,8 @@ fn main() {
// e is a function pointer type and U is an integer; fptr-addr-cast
let _usize_from_fn_ptr_transmute = unsafe { foo as usize };
let _usize_from_fn_ptr = foo as *const usize;
+
+ let _usize_from_ref = unsafe { &1u32 as *const u32 as usize };
}
// If a ref-to-ptr cast of this form where the pointer type points to a type other
diff --git a/src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.rs b/src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.rs
index d8e4421d4..e7360f3f9 100644
--- a/src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.rs
+++ b/src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.rs
@@ -51,6 +51,8 @@ fn main() {
// e is a function pointer type and U is an integer; fptr-addr-cast
let _usize_from_fn_ptr_transmute = unsafe { transmute::<fn(usize) -> u8, usize>(foo) };
let _usize_from_fn_ptr = foo as *const usize;
+
+ let _usize_from_ref = unsafe { transmute::<*const u32, usize>(&1u32) };
}
// If a ref-to-ptr cast of this form where the pointer type points to a type other
diff --git a/src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.stderr b/src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.stderr
index de9418c8d..e862fcb67 100644
--- a/src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.stderr
+++ b/src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.stderr
@@ -46,11 +46,17 @@ error: transmute from `fn(usize) -> u8` to `usize` which could be expressed as a
LL | let _usize_from_fn_ptr_transmute = unsafe { transmute::<fn(usize) -> u8, usize>(foo) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `foo as usize`
+error: transmute from `*const u32` to `usize` which could be expressed as a pointer cast instead
+ --> $DIR/transmutes_expressible_as_ptr_casts.rs:55:36
+ |
+LL | let _usize_from_ref = unsafe { transmute::<*const u32, usize>(&1u32) };
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&1u32 as *const u32 as usize`
+
error: transmute from a reference to a pointer
- --> $DIR/transmutes_expressible_as_ptr_casts.rs:64:14
+ --> $DIR/transmutes_expressible_as_ptr_casts.rs:66:14
|
LL | unsafe { transmute::<&[i32; 1], *const u8>(in_param) }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `in_param as *const [i32; 1] as *const u8`
-error: aborting due to 8 previous errors
+error: aborting due to 9 previous errors
diff --git a/src/tools/clippy/tests/ui/type_repetition_in_bounds.rs b/src/tools/clippy/tests/ui/type_repetition_in_bounds.rs
index 2eca1f470..8b4613b3f 100644
--- a/src/tools/clippy/tests/ui/type_repetition_in_bounds.rs
+++ b/src/tools/clippy/tests/ui/type_repetition_in_bounds.rs
@@ -1,4 +1,5 @@
#![deny(clippy::type_repetition_in_bounds)]
+#![allow(clippy::extra_unused_type_parameters)]
use std::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Sub, SubAssign};
diff --git a/src/tools/clippy/tests/ui/type_repetition_in_bounds.stderr b/src/tools/clippy/tests/ui/type_repetition_in_bounds.stderr
index 70d700c1c..a90df03c0 100644
--- a/src/tools/clippy/tests/ui/type_repetition_in_bounds.stderr
+++ b/src/tools/clippy/tests/ui/type_repetition_in_bounds.stderr
@@ -1,5 +1,5 @@
error: this type has already been used as a bound predicate
- --> $DIR/type_repetition_in_bounds.rs:8:5
+ --> $DIR/type_repetition_in_bounds.rs:9:5
|
LL | T: Clone,
| ^^^^^^^^
@@ -12,7 +12,7 @@ LL | #![deny(clippy::type_repetition_in_bounds)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: this type has already been used as a bound predicate
- --> $DIR/type_repetition_in_bounds.rs:25:5
+ --> $DIR/type_repetition_in_bounds.rs:26:5
|
LL | Self: Copy + Default + Ord,
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -20,7 +20,7 @@ LL | Self: Copy + Default + Ord,
= help: consider combining the bounds: `Self: Clone + Copy + Default + Ord`
error: this type has already been used as a bound predicate
- --> $DIR/type_repetition_in_bounds.rs:85:5
+ --> $DIR/type_repetition_in_bounds.rs:86:5
|
LL | T: Clone,
| ^^^^^^^^
@@ -28,7 +28,7 @@ LL | T: Clone,
= help: consider combining the bounds: `T: ?Sized + Clone`
error: this type has already been used as a bound predicate
- --> $DIR/type_repetition_in_bounds.rs:90:5
+ --> $DIR/type_repetition_in_bounds.rs:91:5
|
LL | T: ?Sized,
| ^^^^^^^^^
diff --git a/src/tools/clippy/tests/ui/uninlined_format_args.fixed b/src/tools/clippy/tests/ui/uninlined_format_args.fixed
index 9d08e80cf..cbd5cc5fc 100644
--- a/src/tools/clippy/tests/ui/uninlined_format_args.fixed
+++ b/src/tools/clippy/tests/ui/uninlined_format_args.fixed
@@ -174,3 +174,7 @@ fn _meets_msrv() {
let local_i32 = 1;
println!("expand='{local_i32}'");
}
+
+fn _do_not_fire() {
+ println!("{:?}", None::<()>);
+}
diff --git a/src/tools/clippy/tests/ui/uninlined_format_args.rs b/src/tools/clippy/tests/ui/uninlined_format_args.rs
index 35b3677a8..cf0ea5be4 100644
--- a/src/tools/clippy/tests/ui/uninlined_format_args.rs
+++ b/src/tools/clippy/tests/ui/uninlined_format_args.rs
@@ -179,3 +179,7 @@ fn _meets_msrv() {
let local_i32 = 1;
println!("expand='{}'", local_i32);
}
+
+fn _do_not_fire() {
+ println!("{:?}", None::<()>);
+}
diff --git a/src/tools/clippy/tests/ui/unnecessary_safety_comment.rs b/src/tools/clippy/tests/ui/unnecessary_safety_comment.rs
index 7fefea705..89fedb145 100644
--- a/src/tools/clippy/tests/ui/unnecessary_safety_comment.rs
+++ b/src/tools/clippy/tests/ui/unnecessary_safety_comment.rs
@@ -48,4 +48,21 @@ fn unnecessary_on_stmt_and_expr() -> u32 {
24
}
+mod issue_10084 {
+ unsafe fn bar() -> i32 {
+ 42
+ }
+
+ macro_rules! foo {
+ () => {
+ // SAFETY: This is necessary
+ unsafe { bar() }
+ };
+ }
+
+ fn main() {
+ foo!();
+ }
+}
+
fn main() {}
diff --git a/src/tools/clippy/tests/ui/unreadable_literal.fixed b/src/tools/clippy/tests/ui/unreadable_literal.fixed
index a67363b09..13e5feb19 100644
--- a/src/tools/clippy/tests/ui/unreadable_literal.fixed
+++ b/src/tools/clippy/tests/ui/unreadable_literal.fixed
@@ -23,7 +23,7 @@ fn main() {
let _good = (
0b1011_i64,
0o1_234_u32,
- 0x0123_4567,
+ 0x1_234_567,
65536,
1_2345_6789,
1234_f32,
diff --git a/src/tools/clippy/tests/ui/unreadable_literal.stderr b/src/tools/clippy/tests/ui/unreadable_literal.stderr
index b51130c6a..450121b1c 100644
--- a/src/tools/clippy/tests/ui/unreadable_literal.stderr
+++ b/src/tools/clippy/tests/ui/unreadable_literal.stderr
@@ -1,11 +1,3 @@
-error: digits of hex or binary literal not grouped by four
- --> $DIR/unreadable_literal.rs:26:9
- |
-LL | 0x1_234_567,
- | ^^^^^^^^^^^ help: consider: `0x0123_4567`
- |
- = note: `-D clippy::unusual-byte-groupings` implied by `-D warnings`
-
error: long literal lacking separators
--> $DIR/unreadable_literal.rs:34:17
|
@@ -68,5 +60,5 @@ error: long literal lacking separators
LL | let _fail5 = 1.100300400;
| ^^^^^^^^^^^ help: consider: `1.100_300_400`
-error: aborting due to 11 previous errors
+error: aborting due to 10 previous errors
diff --git a/src/tools/clippy/tests/ui/unused_io_amount.rs b/src/tools/clippy/tests/ui/unused_io_amount.rs
index 4b0595581..8d3e094b7 100644
--- a/src/tools/clippy/tests/ui/unused_io_amount.rs
+++ b/src/tools/clippy/tests/ui/unused_io_amount.rs
@@ -63,6 +63,14 @@ fn combine_or(file: &str) -> Result<(), Error> {
Ok(())
}
+fn is_ok_err<T: io::Read + io::Write>(s: &mut T) {
+ s.write(b"ok").is_ok();
+ s.write(b"err").is_err();
+ let mut buf = [0u8; 0];
+ s.read(&mut buf).is_ok();
+ s.read(&mut buf).is_err();
+}
+
async fn bad_async_write<W: AsyncWrite + Unpin>(w: &mut W) {
w.write(b"hello world").await.unwrap();
}
diff --git a/src/tools/clippy/tests/ui/unused_io_amount.stderr b/src/tools/clippy/tests/ui/unused_io_amount.stderr
index 7ba7e09c0..0865c5213 100644
--- a/src/tools/clippy/tests/ui/unused_io_amount.stderr
+++ b/src/tools/clippy/tests/ui/unused_io_amount.stderr
@@ -82,13 +82,45 @@ LL | | .expect("error");
error: written amount is not handled
--> $DIR/unused_io_amount.rs:67:5
|
+LL | s.write(b"ok").is_ok();
+ | ^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = help: use `Write::write_all` instead, or handle partial writes
+
+error: written amount is not handled
+ --> $DIR/unused_io_amount.rs:68:5
+ |
+LL | s.write(b"err").is_err();
+ | ^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = help: use `Write::write_all` instead, or handle partial writes
+
+error: read amount is not handled
+ --> $DIR/unused_io_amount.rs:70:5
+ |
+LL | s.read(&mut buf).is_ok();
+ | ^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = help: use `Read::read_exact` instead, or handle partial reads
+
+error: read amount is not handled
+ --> $DIR/unused_io_amount.rs:71:5
+ |
+LL | s.read(&mut buf).is_err();
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = help: use `Read::read_exact` instead, or handle partial reads
+
+error: written amount is not handled
+ --> $DIR/unused_io_amount.rs:75:5
+ |
LL | w.write(b"hello world").await.unwrap();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= help: use `AsyncWriteExt::write_all` instead, or handle partial writes
error: read amount is not handled
- --> $DIR/unused_io_amount.rs:72:5
+ --> $DIR/unused_io_amount.rs:80:5
|
LL | r.read(&mut buf[..]).await.unwrap();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -96,7 +128,7 @@ LL | r.read(&mut buf[..]).await.unwrap();
= help: use `AsyncReadExt::read_exact` instead, or handle partial reads
error: written amount is not handled
- --> $DIR/unused_io_amount.rs:85:9
+ --> $DIR/unused_io_amount.rs:93:9
|
LL | w.write(b"hello world").await?;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -104,7 +136,7 @@ LL | w.write(b"hello world").await?;
= help: use `AsyncWriteExt::write_all` instead, or handle partial writes
error: read amount is not handled
- --> $DIR/unused_io_amount.rs:93:9
+ --> $DIR/unused_io_amount.rs:101:9
|
LL | r.read(&mut buf[..]).await.or(Err(Error::Kind))?;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -112,7 +144,7 @@ LL | r.read(&mut buf[..]).await.or(Err(Error::Kind))?;
= help: use `AsyncReadExt::read_exact` instead, or handle partial reads
error: written amount is not handled
- --> $DIR/unused_io_amount.rs:101:5
+ --> $DIR/unused_io_amount.rs:109:5
|
LL | w.write(b"hello world").await.unwrap();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -120,12 +152,12 @@ LL | w.write(b"hello world").await.unwrap();
= help: use `AsyncWriteExt::write_all` instead, or handle partial writes
error: read amount is not handled
- --> $DIR/unused_io_amount.rs:106:5
+ --> $DIR/unused_io_amount.rs:114:5
|
LL | r.read(&mut buf[..]).await.unwrap();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= help: use `AsyncReadExt::read_exact` instead, or handle partial reads
-error: aborting due to 16 previous errors
+error: aborting due to 20 previous errors
diff --git a/src/tools/clippy/tests/ui/wildcard_enum_match_arm.fixed b/src/tools/clippy/tests/ui/wildcard_enum_match_arm.fixed
index 236074978..293bf75a7 100644
--- a/src/tools/clippy/tests/ui/wildcard_enum_match_arm.fixed
+++ b/src/tools/clippy/tests/ui/wildcard_enum_match_arm.fixed
@@ -96,7 +96,7 @@ fn main() {
}
match Enum::A {
Enum::A => (),
- Enum::B | _ => (),
+ Enum::B | Enum::__Private => (),
}
}
}
diff --git a/src/tools/clippy/tests/ui/wildcard_enum_match_arm.stderr b/src/tools/clippy/tests/ui/wildcard_enum_match_arm.stderr
index efecc9576..30d29aa4e 100644
--- a/src/tools/clippy/tests/ui/wildcard_enum_match_arm.stderr
+++ b/src/tools/clippy/tests/ui/wildcard_enum_match_arm.stderr
@@ -34,11 +34,11 @@ error: wildcard matches known variants and will also match future added variants
LL | _ => {},
| ^ help: try this: `ErrorKind::PermissionDenied | _`
-error: wildcard matches known variants and will also match future added variants
+error: wildcard match will also match any future added variants
--> $DIR/wildcard_enum_match_arm.rs:99:13
|
LL | _ => (),
- | ^ help: try this: `Enum::B | _`
+ | ^ help: try this: `Enum::B | Enum::__Private`
error: aborting due to 6 previous errors
diff --git a/src/tools/compiletest/Cargo.toml b/src/tools/compiletest/Cargo.toml
index 1911f0f9c..0db043a4f 100644
--- a/src/tools/compiletest/Cargo.toml
+++ b/src/tools/compiletest/Cargo.toml
@@ -9,13 +9,14 @@ diff = "0.1.10"
unified-diff = "0.2.1"
getopts = "0.2"
miropt-test-tools = { path = "../miropt-test-tools" }
+build_helper = { path = "../build_helper" }
tracing = "0.1"
tracing-subscriber = { version = "0.3.3", default-features = false, features = ["fmt", "env-filter", "smallvec", "parking_lot", "ansi"] }
regex = "1.0"
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
rustfix = "0.6.0"
-lazy_static = "1.0"
+once_cell = "1.16.0"
walkdir = "2"
glob = "0.3.0"
lazycell = "1.3.0"
@@ -24,5 +25,5 @@ lazycell = "1.3.0"
libc = "0.2"
[target.'cfg(windows)'.dependencies]
-miow = "0.3"
+miow = "0.5"
winapi = { version = "0.3", features = ["winerror"] }
diff --git a/src/tools/compiletest/src/common.rs b/src/tools/compiletest/src/common.rs
index a5f5eb447..7fe2e6257 100644
--- a/src/tools/compiletest/src/common.rs
+++ b/src/tools/compiletest/src/common.rs
@@ -123,6 +123,7 @@ pub enum FailMode {
pub enum CompareMode {
Polonius,
Chalk,
+ NextSolver,
SplitDwarf,
SplitDwarfSingle,
}
@@ -132,6 +133,7 @@ impl CompareMode {
match *self {
CompareMode::Polonius => "polonius",
CompareMode::Chalk => "chalk",
+ CompareMode::NextSolver => "next-solver",
CompareMode::SplitDwarf => "split-dwarf",
CompareMode::SplitDwarfSingle => "split-dwarf-single",
}
@@ -141,6 +143,7 @@ impl CompareMode {
match s.as_str() {
"polonius" => CompareMode::Polonius,
"chalk" => CompareMode::Chalk,
+ "next-solver" => CompareMode::NextSolver,
"split-dwarf" => CompareMode::SplitDwarf,
"split-dwarf-single" => CompareMode::SplitDwarfSingle,
x => panic!("unknown --compare-mode option: {}", x),
@@ -377,6 +380,9 @@ pub struct Config {
/// Whether to rerun tests even if the inputs are unchanged.
pub force_rerun: bool,
+ /// Only rerun the tests that result has been modified accoring to Git status
+ pub only_modified: bool,
+
pub target_cfg: LazyCell<TargetCfg>,
}
diff --git a/src/tools/compiletest/src/errors.rs b/src/tools/compiletest/src/errors.rs
index 054235ec1..c33e66e02 100644
--- a/src/tools/compiletest/src/errors.rs
+++ b/src/tools/compiletest/src/errors.rs
@@ -7,7 +7,7 @@ use std::io::BufReader;
use std::path::Path;
use std::str::FromStr;
-use lazy_static::lazy_static;
+use once_cell::sync::Lazy;
use regex::Regex;
use tracing::*;
@@ -117,10 +117,8 @@ fn parse_expected(
// //~^^^^^
// //[cfg1]~
// //[cfg1,cfg2]~^^
- lazy_static! {
- static ref RE: Regex =
- Regex::new(r"//(?:\[(?P<cfgs>[\w,]+)])?~(?P<adjust>\||\^*)").unwrap();
- }
+ static RE: Lazy<Regex> =
+ Lazy::new(|| Regex::new(r"//(?:\[(?P<cfgs>[\w,]+)])?~(?P<adjust>\||\^*)").unwrap());
let captures = RE.captures(line)?;
diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs
index 423299495..d9b39927c 100644
--- a/src/tools/compiletest/src/header.rs
+++ b/src/tools/compiletest/src/header.rs
@@ -710,6 +710,7 @@ impl Config {
match self.compare_mode {
Some(CompareMode::Polonius) => name == "compare-mode-polonius",
Some(CompareMode::Chalk) => name == "compare-mode-chalk",
+ Some(CompareMode::NextSolver) => name == "compare-mode-next-solver",
Some(CompareMode::SplitDwarf) => name == "compare-mode-split-dwarf",
Some(CompareMode::SplitDwarfSingle) => name == "compare-mode-split-dwarf-single",
None => false,
@@ -925,7 +926,7 @@ pub fn make_test_description<R: Read>(
cfg: Option<&str>,
) -> test::TestDesc {
let mut ignore = false;
- let ignore_message = None;
+ let mut ignore_message = None;
let mut should_fail = false;
let rustc_has_profiler_support = env::var_os("RUSTC_PROFILER_SUPPORT").is_some();
@@ -934,12 +935,14 @@ pub fn make_test_description<R: Read>(
let has_asan = util::ASAN_SUPPORTED_TARGETS.contains(&&*config.target);
let has_cfi = util::CFI_SUPPORTED_TARGETS.contains(&&*config.target);
let has_kcfi = util::KCFI_SUPPORTED_TARGETS.contains(&&*config.target);
+ let has_kasan = util::KASAN_SUPPORTED_TARGETS.contains(&&*config.target);
let has_lsan = util::LSAN_SUPPORTED_TARGETS.contains(&&*config.target);
let has_msan = util::MSAN_SUPPORTED_TARGETS.contains(&&*config.target);
let has_tsan = util::TSAN_SUPPORTED_TARGETS.contains(&&*config.target);
let has_hwasan = util::HWASAN_SUPPORTED_TARGETS.contains(&&*config.target);
let has_memtag = util::MEMTAG_SUPPORTED_TARGETS.contains(&&*config.target);
let has_shadow_call_stack = util::SHADOWCALLSTACK_SUPPORTED_TARGETS.contains(&&*config.target);
+ let has_xray = util::XRAY_SUPPORTED_TARGETS.contains(&&*config.target);
// For tests using the `needs-rust-lld` directive (e.g. for `-Zgcc-ld=lld`), we need to find
// whether `rust-lld` is present in the compiler under test.
@@ -965,41 +968,69 @@ pub fn make_test_description<R: Read>(
if revision.is_some() && revision != cfg {
return;
}
+ macro_rules! reason {
+ ($e:expr) => {
+ ignore |= match $e {
+ true => {
+ ignore_message = Some(stringify!($e));
+ true
+ }
+ false => ignore,
+ }
+ };
+ }
ignore = match config.parse_cfg_name_directive(ln, "ignore") {
- ParsedNameDirective::Match => true,
+ ParsedNameDirective::Match => {
+ ignore_message = Some("cfg -> ignore => Match");
+ true
+ }
ParsedNameDirective::NoMatch => ignore,
};
+
if config.has_cfg_prefix(ln, "only") {
ignore = match config.parse_cfg_name_directive(ln, "only") {
ParsedNameDirective::Match => ignore,
- ParsedNameDirective::NoMatch => true,
+ ParsedNameDirective::NoMatch => {
+ ignore_message = Some("cfg -> only => NoMatch");
+ true
+ }
};
}
- ignore |= ignore_llvm(config, ln);
- ignore |=
- config.run_clang_based_tests_with.is_none() && config.parse_needs_matching_clang(ln);
- ignore |= !has_asm_support && config.parse_name_directive(ln, "needs-asm-support");
- ignore |= !rustc_has_profiler_support && config.parse_needs_profiler_support(ln);
- ignore |= !config.run_enabled() && config.parse_name_directive(ln, "needs-run-enabled");
- ignore |= !rustc_has_sanitizer_support
- && config.parse_name_directive(ln, "needs-sanitizer-support");
- ignore |= !has_asan && config.parse_name_directive(ln, "needs-sanitizer-address");
- ignore |= !has_cfi && config.parse_name_directive(ln, "needs-sanitizer-cfi");
- ignore |= !has_kcfi && config.parse_name_directive(ln, "needs-sanitizer-kcfi");
- ignore |= !has_lsan && config.parse_name_directive(ln, "needs-sanitizer-leak");
- ignore |= !has_msan && config.parse_name_directive(ln, "needs-sanitizer-memory");
- ignore |= !has_tsan && config.parse_name_directive(ln, "needs-sanitizer-thread");
- ignore |= !has_hwasan && config.parse_name_directive(ln, "needs-sanitizer-hwaddress");
- ignore |= !has_memtag && config.parse_name_directive(ln, "needs-sanitizer-memtag");
- ignore |= !has_shadow_call_stack
- && config.parse_name_directive(ln, "needs-sanitizer-shadow-call-stack");
- ignore |= !config.can_unwind() && config.parse_name_directive(ln, "needs-unwind");
- ignore |= config.target == "wasm32-unknown-unknown"
- && config.parse_name_directive(ln, directives::CHECK_RUN_RESULTS);
- ignore |= config.debugger == Some(Debugger::Cdb) && ignore_cdb(config, ln);
- ignore |= config.debugger == Some(Debugger::Gdb) && ignore_gdb(config, ln);
- ignore |= config.debugger == Some(Debugger::Lldb) && ignore_lldb(config, ln);
- ignore |= !has_rust_lld && config.parse_name_directive(ln, "needs-rust-lld");
+
+ reason!(ignore_llvm(config, ln));
+ reason!(
+ config.run_clang_based_tests_with.is_none() && config.parse_needs_matching_clang(ln)
+ );
+ reason!(!has_asm_support && config.parse_name_directive(ln, "needs-asm-support"));
+ reason!(!rustc_has_profiler_support && config.parse_needs_profiler_support(ln));
+ reason!(!config.run_enabled() && config.parse_name_directive(ln, "needs-run-enabled"));
+ reason!(
+ !rustc_has_sanitizer_support
+ && config.parse_name_directive(ln, "needs-sanitizer-support")
+ );
+ reason!(!has_asan && config.parse_name_directive(ln, "needs-sanitizer-address"));
+ reason!(!has_cfi && config.parse_name_directive(ln, "needs-sanitizer-cfi"));
+ reason!(!has_kcfi && config.parse_name_directive(ln, "needs-sanitizer-kcfi"));
+ reason!(!has_kasan && config.parse_name_directive(ln, "needs-sanitizer-kasan"));
+ reason!(!has_lsan && config.parse_name_directive(ln, "needs-sanitizer-leak"));
+ reason!(!has_msan && config.parse_name_directive(ln, "needs-sanitizer-memory"));
+ reason!(!has_tsan && config.parse_name_directive(ln, "needs-sanitizer-thread"));
+ reason!(!has_hwasan && config.parse_name_directive(ln, "needs-sanitizer-hwaddress"));
+ reason!(!has_memtag && config.parse_name_directive(ln, "needs-sanitizer-memtag"));
+ reason!(
+ !has_shadow_call_stack
+ && config.parse_name_directive(ln, "needs-sanitizer-shadow-call-stack")
+ );
+ reason!(!config.can_unwind() && config.parse_name_directive(ln, "needs-unwind"));
+ reason!(!has_xray && config.parse_name_directive(ln, "needs-xray"));
+ reason!(
+ config.target == "wasm32-unknown-unknown"
+ && config.parse_name_directive(ln, directives::CHECK_RUN_RESULTS)
+ );
+ reason!(config.debugger == Some(Debugger::Cdb) && ignore_cdb(config, ln));
+ reason!(config.debugger == Some(Debugger::Gdb) && ignore_gdb(config, ln));
+ reason!(config.debugger == Some(Debugger::Lldb) && ignore_lldb(config, ln));
+ reason!(!has_rust_lld && config.parse_name_directive(ln, "needs-rust-lld"));
should_fail |= config.parse_name_directive(ln, "should-fail");
});
diff --git a/src/tools/compiletest/src/main.rs b/src/tools/compiletest/src/main.rs
index 3092c656c..1760c29ec 100644
--- a/src/tools/compiletest/src/main.rs
+++ b/src/tools/compiletest/src/main.rs
@@ -8,15 +8,17 @@ extern crate test;
use crate::common::{expected_output_path, output_base_dir, output_relative_path, UI_EXTENSIONS};
use crate::common::{CompareMode, Config, Debugger, Mode, PassMode, TestPaths};
use crate::util::logv;
+use build_helper::git::{get_git_modified_files, get_git_untracked_files};
+use core::panic;
use getopts::Options;
use lazycell::LazyCell;
-use std::env;
use std::ffi::OsString;
use std::fs;
use std::io::{self, ErrorKind};
use std::path::{Path, PathBuf};
use std::process::{Command, Stdio};
use std::time::SystemTime;
+use std::{env, vec};
use test::ColorConfig;
use tracing::*;
use walkdir::WalkDir;
@@ -145,9 +147,10 @@ pub fn parse_config(args: Vec<String>) -> Config {
"",
"rustfix-coverage",
"enable this to generate a Rustfix coverage file, which is saved in \
- `./<build_base>/rustfix_missing_coverage.txt`",
+ `./<build_base>/rustfix_missing_coverage.txt`",
)
.optflag("", "force-rerun", "rerun tests even if the inputs are unchanged")
+ .optflag("", "only-modified", "only run tests that result been modified")
.optflag("h", "help", "show this message")
.reqopt("", "channel", "current Rust channel", "CHANNEL")
.optopt("", "edition", "default Rust edition", "EDITION");
@@ -279,6 +282,7 @@ pub fn parse_config(args: Vec<String>) -> Config {
lldb_python_dir: matches.opt_str("lldb-python-dir"),
verbose: matches.opt_present("verbose"),
quiet: matches.opt_present("quiet"),
+ only_modified: matches.opt_present("only-modified"),
color,
remote_test_client: matches.opt_str("remote-test-client").map(PathBuf::from),
compare_mode: matches.opt_str("compare-mode").map(CompareMode::parse),
@@ -521,8 +525,18 @@ pub fn test_opts(config: &Config) -> test::TestOpts {
pub fn make_tests(config: &Config, tests: &mut Vec<test::TestDescAndFn>) {
debug!("making tests from {:?}", config.src_base.display());
let inputs = common_inputs_stamp(config);
- collect_tests_from_dir(config, &config.src_base, &PathBuf::new(), &inputs, tests)
- .unwrap_or_else(|_| panic!("Could not read tests from {}", config.src_base.display()));
+ let modified_tests = modified_tests(config, &config.src_base).unwrap_or_else(|err| {
+ panic!("modified_tests got error from dir: {}, error: {}", config.src_base.display(), err)
+ });
+ collect_tests_from_dir(
+ config,
+ &config.src_base,
+ &PathBuf::new(),
+ &inputs,
+ tests,
+ &modified_tests,
+ )
+ .unwrap_or_else(|_| panic!("Could not read tests from {}", config.src_base.display()));
}
/// Returns a stamp constructed from input files common to all test cases.
@@ -561,12 +575,36 @@ fn common_inputs_stamp(config: &Config) -> Stamp {
stamp
}
+fn modified_tests(config: &Config, dir: &Path) -> Result<Vec<PathBuf>, String> {
+ if !config.only_modified {
+ return Ok(vec![]);
+ }
+ let files =
+ get_git_modified_files(Some(dir), &vec!["rs", "stderr", "fixed"])?.unwrap_or(vec![]);
+ // Add new test cases to the list, it will be convenient in daily development.
+ let untracked_files = get_git_untracked_files(None)?.unwrap_or(vec![]);
+
+ let all_paths = [&files[..], &untracked_files[..]].concat();
+ let full_paths = {
+ let mut full_paths: Vec<PathBuf> = all_paths
+ .into_iter()
+ .map(|f| PathBuf::from(f).with_extension("").with_extension("rs"))
+ .filter_map(|f| if Path::new(&f).exists() { f.canonicalize().ok() } else { None })
+ .collect();
+ full_paths.dedup();
+ full_paths.sort_unstable();
+ full_paths
+ };
+ Ok(full_paths)
+}
+
fn collect_tests_from_dir(
config: &Config,
dir: &Path,
relative_dir_path: &Path,
inputs: &Stamp,
tests: &mut Vec<test::TestDescAndFn>,
+ modified_tests: &Vec<PathBuf>,
) -> io::Result<()> {
// Ignore directories that contain a file named `compiletest-ignore-dir`.
if dir.join("compiletest-ignore-dir").exists() {
@@ -597,7 +635,7 @@ fn collect_tests_from_dir(
let file = file?;
let file_path = file.path();
let file_name = file.file_name();
- if is_test(&file_name) {
+ if is_test(&file_name) && (!config.only_modified || modified_tests.contains(&file_path)) {
debug!("found test file: {:?}", file_path.display());
let paths =
TestPaths { file: file_path, relative_dir: relative_dir_path.to_path_buf() };
@@ -607,7 +645,14 @@ fn collect_tests_from_dir(
let relative_file_path = relative_dir_path.join(file.file_name());
if &file_name != "auxiliary" {
debug!("found directory: {:?}", file_path.display());
- collect_tests_from_dir(config, &file_path, &relative_file_path, inputs, tests)?;
+ collect_tests_from_dir(
+ config,
+ &file_path,
+ &relative_file_path,
+ inputs,
+ tests,
+ modified_tests,
+ )?;
}
} else {
debug!("found other file/directory: {:?}", file_path.display());
diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs
index 859c0f1da..41c23ff86 100644
--- a/src/tools/compiletest/src/runtest.rs
+++ b/src/tools/compiletest/src/runtest.rs
@@ -32,7 +32,7 @@ use std::process::{Child, Command, ExitStatus, Output, Stdio};
use std::str;
use glob::glob;
-use lazy_static::lazy_static;
+use once_cell::sync::Lazy;
use tracing::*;
use crate::extract_gdb_version;
@@ -52,9 +52,8 @@ fn disable_error_reporting<F: FnOnce() -> R, R>(f: F) -> R {
use winapi::um::errhandlingapi::SetErrorMode;
use winapi::um::winbase::SEM_NOGPFAULTERRORBOX;
- lazy_static! {
- static ref LOCK: Mutex<()> = Mutex::new(());
- }
+ static LOCK: Mutex<()> = Mutex::new(());
+
// Error mode is a global variable, so lock it so only one thread will change it
let _lock = LOCK.lock().unwrap();
@@ -1433,12 +1432,13 @@ impl<'test> TestCx<'test> {
expect_help: bool,
expect_note: bool,
) -> bool {
- match actual_error.kind {
- Some(ErrorKind::Help) => expect_help,
- Some(ErrorKind::Note) => expect_note,
- Some(ErrorKind::Error) | Some(ErrorKind::Warning) => true,
- Some(ErrorKind::Suggestion) | None => false,
- }
+ !actual_error.msg.is_empty()
+ && match actual_error.kind {
+ Some(ErrorKind::Help) => expect_help,
+ Some(ErrorKind::Note) => expect_note,
+ Some(ErrorKind::Error) | Some(ErrorKind::Warning) => true,
+ Some(ErrorKind::Suggestion) | None => false,
+ }
}
fn should_emit_metadata(&self, pm: Option<PassMode>) -> Emit {
@@ -2030,6 +2030,9 @@ impl<'test> TestCx<'test> {
Some(CompareMode::Chalk) => {
rustc.args(&["-Ztrait-solver=chalk"]);
}
+ Some(CompareMode::NextSolver) => {
+ rustc.args(&["-Ztrait-solver=next"]);
+ }
Some(CompareMode::SplitDwarf) if self.config.target.contains("windows") => {
rustc.args(&["-Csplit-debuginfo=unpacked", "-Zunstable-options"]);
}
@@ -2845,11 +2848,10 @@ impl<'test> TestCx<'test> {
// the form <crate-name1>.<crate-disambiguator1>-in-<crate-name2>.<crate-disambiguator2>,
// remove all crate-disambiguators.
fn remove_crate_disambiguator_from_cgu(cgu: &str) -> String {
- lazy_static! {
- static ref RE: Regex =
- Regex::new(r"^[^\.]+(?P<d1>\.[[:alnum:]]+)(-in-[^\.]+(?P<d2>\.[[:alnum:]]+))?")
- .unwrap();
- }
+ static RE: Lazy<Regex> = Lazy::new(|| {
+ Regex::new(r"^[^\.]+(?P<d1>\.[[:alnum:]]+)(-in-[^\.]+(?P<d2>\.[[:alnum:]]+))?")
+ .unwrap()
+ });
let captures =
RE.captures(cgu).unwrap_or_else(|| panic!("invalid cgu name encountered: {}", cgu));
@@ -3167,12 +3169,12 @@ impl<'test> TestCx<'test> {
// 'uploaded "$TEST_BUILD_DIR/<test_executable>, waiting for result"'
// is printed to stdout by the client and then captured in the ProcRes,
// so it needs to be removed when comparing the run-pass test execution output
- lazy_static! {
- static ref REMOTE_TEST_RE: Regex = Regex::new(
+ static REMOTE_TEST_RE: Lazy<Regex> = Lazy::new(|| {
+ Regex::new(
"^uploaded \"\\$TEST_BUILD_DIR(/[[:alnum:]_\\-.]+)+\", waiting for result\n"
)
- .unwrap();
- }
+ .unwrap()
+ });
REMOTE_TEST_RE
.replace(
&self.normalize_output(&proc_res.stdout, &self.props.normalize_stdout),
@@ -3617,10 +3619,8 @@ impl<'test> TestCx<'test> {
// with placeholders as we do not want tests needing updated when compiler source code
// changes.
// eg. $SRC_DIR/libcore/mem.rs:323:14 becomes $SRC_DIR/libcore/mem.rs:LL:COL
- lazy_static! {
- static ref SRC_DIR_RE: Regex =
- Regex::new("SRC_DIR(.+):\\d+:\\d+(: \\d+:\\d+)?").unwrap();
- }
+ static SRC_DIR_RE: Lazy<Regex> =
+ Lazy::new(|| Regex::new("SRC_DIR(.+):\\d+:\\d+(: \\d+:\\d+)?").unwrap());
normalized = SRC_DIR_RE.replace_all(&normalized, "SRC_DIR$1:LL:COL").into_owned();
@@ -3631,19 +3631,17 @@ impl<'test> TestCx<'test> {
// since they duplicate actual errors and make the output hard to read.
// This mirrors the regex in src/tools/tidy/src/style.rs, please update
// both if either are changed.
- lazy_static! {
- static ref ANNOTATION_RE: Regex = Regex::new("\\s*//(\\[.*\\])?~.*").unwrap();
- }
+ static ANNOTATION_RE: Lazy<Regex> =
+ Lazy::new(|| Regex::new("\\s*//(\\[.*\\])?~.*").unwrap());
normalized = ANNOTATION_RE.replace_all(&normalized, "").into_owned();
// This code normalizes various hashes in v0 symbol mangling that is
// emitted in the ui and mir-opt tests.
- lazy_static! {
- static ref V0_CRATE_HASH_PREFIX_RE: Regex =
- Regex::new(r"_R.*?Cs[0-9a-zA-Z]+_").unwrap();
- static ref V0_CRATE_HASH_RE: Regex = Regex::new(r"Cs[0-9a-zA-Z]+_").unwrap();
- }
+ static V0_CRATE_HASH_PREFIX_RE: Lazy<Regex> =
+ Lazy::new(|| Regex::new(r"_R.*?Cs[0-9a-zA-Z]+_").unwrap());
+ static V0_CRATE_HASH_RE: Lazy<Regex> =
+ Lazy::new(|| Regex::new(r"Cs[0-9a-zA-Z]+_").unwrap());
const V0_CRATE_HASH_PLACEHOLDER: &str = r"CsCRATE_HASH_";
if V0_CRATE_HASH_PREFIX_RE.is_match(&normalized) {
@@ -3652,10 +3650,9 @@ impl<'test> TestCx<'test> {
V0_CRATE_HASH_RE.replace_all(&normalized, V0_CRATE_HASH_PLACEHOLDER).into_owned();
}
- lazy_static! {
- static ref V0_BACK_REF_PREFIX_RE: Regex = Regex::new(r"\(_R.*?B[0-9a-zA-Z]_").unwrap();
- static ref V0_BACK_REF_RE: Regex = Regex::new(r"B[0-9a-zA-Z]_").unwrap();
- }
+ static V0_BACK_REF_PREFIX_RE: Lazy<Regex> =
+ Lazy::new(|| Regex::new(r"\(_R.*?B[0-9a-zA-Z]_").unwrap());
+ static V0_BACK_REF_RE: Lazy<Regex> = Lazy::new(|| Regex::new(r"B[0-9a-zA-Z]_").unwrap());
const V0_BACK_REF_PLACEHOLDER: &str = r"B<REF>_";
if V0_BACK_REF_PREFIX_RE.is_match(&normalized) {
@@ -3678,21 +3675,23 @@ impl<'test> TestCx<'test> {
/// Replaces backslashes in paths with forward slashes, and replaces CRLF line endings
/// with LF.
fn normalize_platform_differences(output: &str) -> String {
- lazy_static! {
- /// Used to find Windows paths.
- ///
- /// It's not possible to detect paths in the error messages generally, but this is a
- /// decent enough heuristic.
- static ref PATH_BACKSLASH_RE: Regex = Regex::new(r#"(?x)
+ /// Used to find Windows paths.
+ ///
+ /// It's not possible to detect paths in the error messages generally, but this is a
+ /// decent enough heuristic.
+ static PATH_BACKSLASH_RE: Lazy<Regex> = Lazy::new(|| {
+ Regex::new(
+ r#"(?x)
(?:
# Match paths that don't include spaces.
(?:\\[\pL\pN\.\-_']+)+\.\pL+
|
# If the path starts with a well-known root, then allow spaces.
\$(?:DIR|SRC_DIR|TEST_BUILD_DIR|BUILD_DIR|LIB_DIR)(?:\\[\pL\pN\.\-_' ]+)+
- )"#
- ).unwrap();
- }
+ )"#,
+ )
+ .unwrap()
+ });
let output = output.replace(r"\\", r"\");
diff --git a/src/tools/compiletest/src/util.rs b/src/tools/compiletest/src/util.rs
index 6c63b760f..5f6a27e53 100644
--- a/src/tools/compiletest/src/util.rs
+++ b/src/tools/compiletest/src/util.rs
@@ -11,6 +11,8 @@ mod tests;
pub const ASAN_SUPPORTED_TARGETS: &[&str] = &[
"aarch64-apple-darwin",
+ "aarch64-apple-ios",
+ "aarch64-apple-ios-sim",
"aarch64-unknown-fuchsia",
"aarch64-linux-android",
"aarch64-unknown-linux-gnu",
@@ -19,10 +21,12 @@ pub const ASAN_SUPPORTED_TARGETS: &[&str] = &[
"i686-linux-android",
"i686-unknown-linux-gnu",
"x86_64-apple-darwin",
+ "x86_64-apple-ios",
"x86_64-unknown-fuchsia",
"x86_64-linux-android",
"x86_64-unknown-freebsd",
"x86_64-unknown-linux-gnu",
+ "s390x-unknown-linux-gnu",
];
// FIXME(rcvalle): More targets are likely supported.
@@ -44,23 +48,39 @@ pub const CFI_SUPPORTED_TARGETS: &[&str] = &[
pub const KCFI_SUPPORTED_TARGETS: &[&str] = &["aarch64-linux-none", "x86_64-linux-none"];
+pub const KASAN_SUPPORTED_TARGETS: &[&str] = &[
+ "aarch64-unknown-none",
+ "riscv64gc-unknown-none-elf",
+ "riscv64imac-unknown-none-elf",
+ "x86_64-unknown-none",
+];
+
pub const LSAN_SUPPORTED_TARGETS: &[&str] = &[
// FIXME: currently broken, see #88132
// "aarch64-apple-darwin",
"aarch64-unknown-linux-gnu",
"x86_64-apple-darwin",
"x86_64-unknown-linux-gnu",
+ "s390x-unknown-linux-gnu",
];
-pub const MSAN_SUPPORTED_TARGETS: &[&str] =
- &["aarch64-unknown-linux-gnu", "x86_64-unknown-freebsd", "x86_64-unknown-linux-gnu"];
+pub const MSAN_SUPPORTED_TARGETS: &[&str] = &[
+ "aarch64-unknown-linux-gnu",
+ "x86_64-unknown-freebsd",
+ "x86_64-unknown-linux-gnu",
+ "s390x-unknown-linux-gnu",
+];
pub const TSAN_SUPPORTED_TARGETS: &[&str] = &[
"aarch64-apple-darwin",
+ "aarch64-apple-ios",
+ "aarch64-apple-ios-sim",
"aarch64-unknown-linux-gnu",
"x86_64-apple-darwin",
+ "x86_64-apple-ios",
"x86_64-unknown-freebsd",
"x86_64-unknown-linux-gnu",
+ "s390x-unknown-linux-gnu",
];
pub const HWASAN_SUPPORTED_TARGETS: &[&str] =
@@ -71,6 +91,19 @@ pub const MEMTAG_SUPPORTED_TARGETS: &[&str] =
pub const SHADOWCALLSTACK_SUPPORTED_TARGETS: &[&str] = &["aarch64-linux-android"];
+pub const XRAY_SUPPORTED_TARGETS: &[&str] = &[
+ "aarch64-linux-android",
+ "aarch64-unknown-linux-gnu",
+ "aarch64-unknown-linux-musl",
+ "x86_64-linux-android",
+ "x86_64-unknown-freebsd",
+ "x86_64-unknown-linux-gnu",
+ "x86_64-unknown-linux-musl",
+ "x86_64-unknown-netbsd",
+ "x86_64-unknown-none-linuxkernel",
+ "x86_64-unknown-openbsd",
+];
+
pub fn make_new_path(path: &str) -> String {
assert!(cfg!(windows));
// Windows just uses PATH as the library search path, so we have to
diff --git a/src/tools/error_index_generator/Cargo.toml b/src/tools/error_index_generator/Cargo.toml
index f4dac6e94..76c2e330b 100644
--- a/src/tools/error_index_generator/Cargo.toml
+++ b/src/tools/error_index_generator/Cargo.toml
@@ -5,6 +5,7 @@ edition = "2021"
[dependencies]
mdbook = { version = "0.4", default-features = false, features = ["search"] }
+rustc_error_codes = { version = "0.0.0", path = "../../../compiler/rustc_error_codes" }
[[bin]]
name = "error_index_generator"
diff --git a/src/tools/error_index_generator/main.rs b/src/tools/error_index_generator/main.rs
index 98eda97e2..f984275b1 100644
--- a/src/tools/error_index_generator/main.rs
+++ b/src/tools/error_index_generator/main.rs
@@ -2,9 +2,6 @@
extern crate rustc_driver;
-// We use the function we generate from `register_diagnostics!`.
-use crate::error_codes::error_codes;
-
use std::env;
use std::error::Error;
use std::fs::{self, File};
@@ -17,22 +14,6 @@ use std::str::FromStr;
use mdbook::book::{parse_summary, BookItem, Chapter};
use mdbook::{Config, MDBook};
-macro_rules! register_diagnostics {
- ($($error_code:ident: $message:expr,)+ ; $($undocumented:ident,)* ) => {
- pub fn error_codes() -> Vec<(&'static str, Option<&'static str>)> {
- let mut errors: Vec<(&str, Option<&str>)> = vec![
- $((stringify!($error_code), Some($message)),)+
- $((stringify!($undocumented), None),)+
- ];
- errors.sort();
- errors
- }
- }
-}
-
-#[path = "../../../compiler/rustc_error_codes/src/error_codes.rs"]
-mod error_codes;
-
enum OutputFormat {
HTML,
Markdown,
@@ -55,11 +36,8 @@ fn render_markdown(output_path: &Path) -> Result<(), Box<dyn Error>> {
write!(output_file, "# Rust Compiler Error Index\n")?;
- for (err_code, description) in error_codes().iter() {
- match description {
- Some(ref desc) => write!(output_file, "## {}\n{}\n", err_code, desc)?,
- None => {}
- }
+ for (err_code, description) in rustc_error_codes::DIAGNOSTICS.iter() {
+ write!(output_file, "## {}\n{}\n", err_code, description)?
}
Ok(())
@@ -105,27 +83,23 @@ This page lists all the error codes emitted by the Rust compiler.
"
);
- let err_codes = error_codes();
+ let err_codes = rustc_error_codes::DIAGNOSTICS;
let mut chapters = Vec::with_capacity(err_codes.len());
for (err_code, explanation) in err_codes.iter() {
- if let Some(explanation) = explanation {
- introduction.push_str(&format!(" * [{0}](./{0}.html)\n", err_code));
-
- let content = add_rust_attribute_on_codeblock(explanation);
- chapters.push(BookItem::Chapter(Chapter {
- name: err_code.to_string(),
- content: format!("# Error code {}\n\n{}\n", err_code, content),
- number: None,
- sub_items: Vec::new(),
- // We generate it into the `error_codes` folder.
- path: Some(PathBuf::from(&format!("{}.html", err_code))),
- source_path: None,
- parent_names: Vec::new(),
- }));
- } else {
- introduction.push_str(&format!(" * {}\n", err_code));
- }
+ introduction.push_str(&format!(" * [{0}](./{0}.html)\n", err_code));
+
+ let content = add_rust_attribute_on_codeblock(explanation);
+ chapters.push(BookItem::Chapter(Chapter {
+ name: err_code.to_string(),
+ content: format!("# Error code {}\n\n{}\n", err_code, content),
+ number: None,
+ sub_items: Vec::new(),
+ // We generate it into the `error_codes` folder.
+ path: Some(PathBuf::from(&format!("{}.html", err_code))),
+ source_path: None,
+ parent_names: Vec::new(),
+ }));
}
let mut config = Config::from_str(include_str!("book_config.toml"))?;
diff --git a/src/tools/expand-yaml-anchors/src/main.rs b/src/tools/expand-yaml-anchors/src/main.rs
index 8992d165d..3fc72ecbb 100644
--- a/src/tools/expand-yaml-anchors/src/main.rs
+++ b/src/tools/expand-yaml-anchors/src/main.rs
@@ -51,7 +51,7 @@ impl App {
["generate", ref base] => (Mode::Generate, PathBuf::from(base)),
["check", ref base] => (Mode::Check, PathBuf::from(base)),
_ => {
- eprintln!("usage: expand-yaml-anchors <source-dir> <dest-dir>");
+ eprintln!("usage: expand-yaml-anchors <generate|check> <base-dir>");
std::process::exit(1);
}
};
diff --git a/src/tools/jsondoclint/src/validator.rs b/src/tools/jsondoclint/src/validator.rs
index c6f55410e..a1f675a3b 100644
--- a/src/tools/jsondoclint/src/validator.rs
+++ b/src/tools/jsondoclint/src/validator.rs
@@ -71,6 +71,19 @@ impl<'a> Validator<'a> {
}
}
+ fn check_items(&mut self, id: &Id, items: &[Id]) {
+ let mut visited_ids = HashSet::with_capacity(items.len());
+
+ for item in items {
+ if !visited_ids.insert(item) {
+ self.fail(
+ id,
+ ErrorKind::Custom(format!("Duplicated entry in `items` field: `{item:?}`")),
+ );
+ }
+ }
+ }
+
fn check_item(&mut self, id: &'a Id) {
if let Some(item) = &self.krate.index.get(id) {
item.links.values().for_each(|id| self.add_any_id(id));
@@ -83,9 +96,9 @@ impl<'a> Validator<'a> {
ItemEnum::Enum(x) => self.check_enum(x),
ItemEnum::Variant(x) => self.check_variant(x, id),
ItemEnum::Function(x) => self.check_function(x),
- ItemEnum::Trait(x) => self.check_trait(x),
+ ItemEnum::Trait(x) => self.check_trait(x, id),
ItemEnum::TraitAlias(x) => self.check_trait_alias(x),
- ItemEnum::Impl(x) => self.check_impl(x),
+ ItemEnum::Impl(x) => self.check_impl(x, id),
ItemEnum::Typedef(x) => self.check_typedef(x),
ItemEnum::OpaqueTy(x) => self.check_opaque_ty(x),
ItemEnum::Constant(x) => self.check_constant(x),
@@ -94,7 +107,7 @@ impl<'a> Validator<'a> {
ItemEnum::Macro(x) => self.check_macro(x),
ItemEnum::ProcMacro(x) => self.check_proc_macro(x),
ItemEnum::Primitive(x) => self.check_primitive_type(x),
- ItemEnum::Module(x) => self.check_module(x),
+ ItemEnum::Module(x) => self.check_module(x, id),
// FIXME: Why don't these have their own structs?
ItemEnum::ExternCrate { .. } => {}
ItemEnum::AssocConst { type_, default: _ } => self.check_type(type_),
@@ -112,7 +125,8 @@ impl<'a> Validator<'a> {
}
// Core checkers
- fn check_module(&mut self, module: &'a Module) {
+ fn check_module(&mut self, module: &'a Module, id: &Id) {
+ self.check_items(id, &module.items);
module.items.iter().for_each(|i| self.add_mod_item_id(i));
}
@@ -181,7 +195,8 @@ impl<'a> Validator<'a> {
self.check_fn_decl(&x.decl);
}
- fn check_trait(&mut self, x: &'a Trait) {
+ fn check_trait(&mut self, x: &'a Trait, id: &Id) {
+ self.check_items(id, &x.items);
self.check_generics(&x.generics);
x.items.iter().for_each(|i| self.add_trait_item_id(i));
x.bounds.iter().for_each(|i| self.check_generic_bound(i));
@@ -193,7 +208,8 @@ impl<'a> Validator<'a> {
x.params.iter().for_each(|i| self.check_generic_bound(i));
}
- fn check_impl(&mut self, x: &'a Impl) {
+ fn check_impl(&mut self, x: &'a Impl, id: &Id) {
+ self.check_items(id, &x.items);
self.check_generics(&x.generics);
if let Some(path) = &x.trait_ {
self.check_path(path, PathKind::Trait);
diff --git a/src/tools/publish_toolstate.py b/src/tools/publish_toolstate.py
index 9c16ef2cb..395bcc745 100755
--- a/src/tools/publish_toolstate.py
+++ b/src/tools/publish_toolstate.py
@@ -68,52 +68,6 @@ def load_json_from_response(resp):
print("Refusing to decode " + str(type(content)) + " to str")
return json.loads(content_str)
-def validate_maintainers(repo, github_token):
- # type: (str, str) -> None
- '''Ensure all maintainers are assignable on a GitHub repo'''
- next_link_re = re.compile(r'<([^>]+)>; rel="next"')
-
- # Load the list of assignable people in the GitHub repo
- assignable = [] # type: typing.List[str]
- url = 'https://api.github.com/repos/' \
- + '%s/collaborators?per_page=100' % repo # type: typing.Optional[str]
- while url is not None:
- response = urllib2.urlopen(urllib2.Request(url, headers={
- 'Authorization': 'token ' + github_token,
- # Properly load nested teams.
- 'Accept': 'application/vnd.github.hellcat-preview+json',
- }))
- assignable.extend(user['login'] for user in load_json_from_response(response))
- # Load the next page if available
- url = None
- link_header = response.headers.get('Link')
- if link_header:
- matches = next_link_re.match(link_header)
- if matches is not None:
- url = matches.group(1)
-
- errors = False
- for tool, maintainers in MAINTAINERS.items():
- for maintainer in maintainers:
- if maintainer not in assignable:
- errors = True
- print(
- "error: %s maintainer @%s is not assignable in the %s repo"
- % (tool, maintainer, repo),
- )
-
- if errors:
- print()
- print(" To be assignable, a person needs to be explicitly listed as a")
- print(" collaborator in the repository settings. The simple way to")
- print(" fix this is to ask someone with 'admin' privileges on the repo")
- print(" to add the person or whole team as a collaborator with 'read'")
- print(" privileges. Those privileges don't grant any extra permissions")
- print(" so it's safe to apply them.")
- print()
- print("The build will fail due to this.")
- exit(1)
-
def read_current_status(current_commit, path):
# type: (str, str) -> typing.Mapping[str, typing.Any]
@@ -280,21 +234,6 @@ def update_latest(
try:
if __name__ != '__main__':
exit(0)
- repo = os.environ.get('TOOLSTATE_VALIDATE_MAINTAINERS_REPO')
- if repo:
- github_token = os.environ.get('TOOLSTATE_REPO_ACCESS_TOKEN')
- if github_token:
- # FIXME: This is currently broken. Starting on 2021-09-15, GitHub
- # seems to have changed it so that to list the collaborators
- # requires admin permissions. I think this will probably just need
- # to be removed since we are probably not going to use an admin
- # token, and I don't see another way to do this.
- print('maintainer validation disabled')
- # validate_maintainers(repo, github_token)
- else:
- print('skipping toolstate maintainers validation since no GitHub token is present')
- # When validating maintainers don't run the full script.
- exit(0)
cur_commit = sys.argv[1]
cur_datetime = datetime.datetime.utcnow().strftime('%Y-%m-%dT%H:%M:%SZ')
diff --git a/src/tools/rust-analyzer/Cargo.lock b/src/tools/rust-analyzer/Cargo.lock
index d27ae416f..ec1977672 100644
--- a/src/tools/rust-analyzer/Cargo.lock
+++ b/src/tools/rust-analyzer/Cargo.lock
@@ -4,9 +4,9 @@ version = 3
[[package]]
name = "addr2line"
-version = "0.17.0"
+version = "0.19.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b9ecd88a8c8378ca913a680cd98f0f13ac67383d35993f86c90a70e3f137816b"
+checksum = "a76fd60b23679b7d19bd066031410fb7e458ccc5e958eb5c325888ce4baedc97"
dependencies = [
"gimli",
]
@@ -27,19 +27,10 @@ dependencies = [
]
[[package]]
-name = "ansi_term"
-version = "0.12.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2"
-dependencies = [
- "winapi",
-]
-
-[[package]]
name = "anyhow"
-version = "1.0.65"
+version = "1.0.68"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "98161a4e3e2184da77bb14f02184cdd111e83bbbcc9979dfee3c44b9a85f5602"
+checksum = "2cb2f989d18dd141ab8ae82f64d1a8cdd37e0840f73a406896cf5e99502fab61"
[[package]]
name = "anymap"
@@ -49,9 +40,9 @@ checksum = "8f1f8f5a6f3d50d89e3797d7593a50f96bb2aaa20ca0cc7be1fb673232c91d72"
[[package]]
name = "arbitrary"
-version = "1.1.7"
+version = "1.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d86fd10d912cab78764cc44307d9cd5f164e09abbeb87fb19fb6d95937e8da5f"
+checksum = "b0224938f92e7aef515fac2ff2d18bd1115c1394ddf4a092e0c87e8be9499ee5"
[[package]]
name = "arrayvec"
@@ -65,7 +56,7 @@ version = "0.2.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
dependencies = [
- "hermit-abi",
+ "hermit-abi 0.1.19",
"libc",
"winapi",
]
@@ -78,9 +69,9 @@ checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
[[package]]
name = "backtrace"
-version = "0.3.66"
+version = "0.3.67"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cab84319d616cfb654d03394f38ab7e6f0919e181b1b57e1fd15e7fb4077d9a7"
+checksum = "233d376d6d185f2a3093e58f283f60f880315b6c60075b01f36b3b85154564ca"
dependencies = [
"addr2line",
"cc",
@@ -120,9 +111,9 @@ checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"
[[package]]
name = "camino"
-version = "1.1.1"
+version = "1.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "88ad0e1e3e88dd237a156ab9f571021b8a158caa0ae44b1968a241efb5144c1e"
+checksum = "c77df041dc383319cc661b428b6961a005db4d6808d5e12536931b1ca9556055"
dependencies = [
"serde",
]
@@ -138,22 +129,23 @@ dependencies = [
[[package]]
name = "cargo_metadata"
-version = "0.15.0"
+version = "0.15.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3abb7553d5b9b8421c6de7cb02606ff15e0c6eea7d8eadd75ef013fd636bec36"
+checksum = "982a0cf6a99c350d7246035613882e376d58cebe571785abc5da4f648d53ac0a"
dependencies = [
"camino",
"cargo-platform",
"semver",
"serde",
"serde_json",
+ "thiserror",
]
[[package]]
name = "cc"
-version = "1.0.73"
+version = "1.0.78"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11"
+checksum = "a20104e2335ce8a659d6dd92a51a767a0c062599c73b343fd152cb401e828c3d"
[[package]]
name = "cfg"
@@ -229,9 +221,9 @@ dependencies = [
[[package]]
name = "command-group"
-version = "1.0.8"
+version = "2.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f7a8a86f409b4a59df3a3e4bee2de0b83f1755fdd2a25e3a9684c396fc4bed2c"
+checksum = "026c3922235f9f7d78f21251a026f3acdeb7cce3deba107fe09a4bfa63d850a2"
dependencies = [
"nix",
"winapi",
@@ -286,22 +278,22 @@ dependencies = [
[[package]]
name = "crossbeam-epoch"
-version = "0.9.11"
+version = "0.9.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f916dfc5d356b0ed9dae65f1db9fc9770aa2851d2662b988ccf4fe3516e86348"
+checksum = "01a9af1f4c2ef74bb8aa1f7e19706bc72d03598c8a570bb5de72243c7a9d9d5a"
dependencies = [
"autocfg",
"cfg-if",
"crossbeam-utils",
- "memoffset",
+ "memoffset 0.7.1",
"scopeguard",
]
[[package]]
name = "crossbeam-utils"
-version = "0.8.12"
+version = "0.8.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "edbafec5fa1f196ca66527c1b12c2ec4745ca14b50f1ad8f9f6f720b55d11fac"
+checksum = "4fb766fa798726286dbbb842f174001dab8abc7b627a1dd86e0b7222a95d929f"
dependencies = [
"cfg-if",
]
@@ -316,14 +308,14 @@ dependencies = [
"hashbrown",
"lock_api",
"once_cell",
- "parking_lot_core 0.9.4",
+ "parking_lot_core 0.9.6",
]
[[package]]
name = "derive_arbitrary"
-version = "1.1.6"
+version = "1.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "226ad66541d865d7a7173ad6a9e691c33fdb910ac723f4bc734b3e5294a1f931"
+checksum = "cf460bbff5f571bfc762da5102729f59f338be7db17a21fade44c5c4f5005350"
dependencies = [
"proc-macro2",
"quote",
@@ -332,9 +324,9 @@ dependencies = [
[[package]]
name = "dissimilar"
-version = "1.0.4"
+version = "1.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8c97b9233581d84b8e1e689cdd3a47b6f69770084fc246e86a7f78b0d9c1d4a5"
+checksum = "210ec60ae7d710bed8683e333e9d2855a8a56a3e9892b38bad3bb0d4d29b0d5e"
[[package]]
name = "dot"
@@ -375,14 +367,14 @@ dependencies = [
[[package]]
name = "filetime"
-version = "0.2.18"
+version = "0.2.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4b9663d381d07ae25dc88dbdf27df458faa83a9b25336bcac83d5e452b5fc9d3"
+checksum = "4e884668cd0c7480504233e951174ddc3b382f7c2666e3b7310b5c4e7b0c37f9"
dependencies = [
"cfg-if",
"libc",
"redox_syscall",
- "windows-sys 0.42.0",
+ "windows-sys",
]
[[package]]
@@ -393,9 +385,9 @@ checksum = "37ab347416e802de484e4d03c7316c48f1ecb56574dfd4a46a80f173ce1de04d"
[[package]]
name = "flate2"
-version = "1.0.24"
+version = "1.0.25"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f82b0f4c27ad9f8bfd1f3208d882da2b09c301bc1c828fd3a00d0216d2fbbff6"
+checksum = "a8a2db397cb1c8772f31494cb8917e48cd1e64f0fa7efac59fbd741a0a8ce841"
dependencies = [
"crc32fast",
"miniz_oxide",
@@ -450,9 +442,9 @@ checksum = "7ab85b9b05e3978cc9a9cf8fea7f01b494e1a09ed3037e16ba39edc7a29eb61a"
[[package]]
name = "gimli"
-version = "0.26.2"
+version = "0.27.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "22030e2c5a68ec659fde1e949a745124b48e6fa8b045b7ed5bd1fe4ccc5c4e5d"
+checksum = "dec7af912d60cdbd3677c1af9352ebae6fb8394d165568a2234df0fa00f87793"
[[package]]
name = "hashbrown"
@@ -479,6 +471,15 @@ dependencies = [
]
[[package]]
+name = "hermit-abi"
+version = "0.2.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ee512640fe35acbfb4bb779db6f0d80704c2cacfa2e39b601ef3e3f47d1ae4c7"
+dependencies = [
+ "libc",
+]
+
+[[package]]
name = "hir"
version = "0.0.0"
dependencies = [
@@ -519,6 +520,7 @@ dependencies = [
"hkalbasi-rustc-ap-rustc_abi",
"hkalbasi-rustc-ap-rustc_index",
"indexmap",
+ "intern",
"itertools",
"la-arena",
"limit",
@@ -544,6 +546,7 @@ dependencies = [
"either",
"expect-test",
"hashbrown",
+ "intern",
"itertools",
"la-arena",
"limit",
@@ -574,11 +577,13 @@ dependencies = [
"hir-def",
"hir-expand",
"hkalbasi-rustc-ap-rustc_index",
+ "intern",
"itertools",
"la-arena",
"limit",
"once_cell",
"profile",
+ "project-model",
"rustc-hash",
"scoped-tls",
"smallvec",
@@ -642,6 +647,7 @@ dependencies = [
"profile",
"pulldown-cmark",
"pulldown-cmark-to-cmark",
+ "smallvec",
"stdx",
"syntax",
"test-utils",
@@ -705,6 +711,7 @@ dependencies = [
"limit",
"memchr",
"once_cell",
+ "oorandom",
"parser",
"profile",
"rayon",
@@ -766,9 +773,9 @@ dependencies = [
[[package]]
name = "indexmap"
-version = "1.9.1"
+version = "1.9.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "10a35a97730320ffe8e2d410b5d3b69279b98d2c14bdb8b70ea89ecf7888d41e"
+checksum = "1885e79c1fc4b10f0e172c475f458b7f7b93061064d98c3293e98c5ba0c8b399"
dependencies = [
"autocfg",
"hashbrown",
@@ -804,6 +811,16 @@ dependencies = [
]
[[package]]
+name = "intern"
+version = "0.0.0"
+dependencies = [
+ "dashmap",
+ "hashbrown",
+ "once_cell",
+ "rustc-hash",
+]
+
+[[package]]
name = "itertools"
version = "0.10.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -814,9 +831,9 @@ dependencies = [
[[package]]
name = "itoa"
-version = "1.0.4"
+version = "1.0.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4217ad341ebadf8d8e724e264f13e593e0648f5b3e94b3896a5df283be015ecc"
+checksum = "fad582f4b9e86b6caa621cabeb0963332d92eea04729ab12892c2533951e6440"
[[package]]
name = "jod-thread"
@@ -826,9 +843,9 @@ checksum = "8b23360e99b8717f20aaa4598f5a6541efbe30630039fbc7706cf954a87947ae"
[[package]]
name = "kqueue"
-version = "1.0.6"
+version = "1.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4d6112e8f37b59803ac47a42d14f1f3a59bbf72fc6857ffc5be455e28a691f8e"
+checksum = "2c8fc60ba15bf51257aa9807a48a61013db043fcf3a78cb0d916e8e396dcad98"
dependencies = [
"kqueue-sys",
"libc",
@@ -856,15 +873,15 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
[[package]]
name = "libc"
-version = "0.2.135"
+version = "0.2.139"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "68783febc7782c6c5cb401fbda4de5a9898be1762314da0bb2c10ced61f18b0c"
+checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79"
[[package]]
name = "libloading"
-version = "0.7.3"
+version = "0.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "efbc0f03f9a775e9f6aed295c6a1ba2253c5757a9e03d55c6caa46a681abcddd"
+checksum = "b67380fd3b2fbe7527a606e18729d21c6f3951633d0500574c4dc22d2d638b9f"
dependencies = [
"cfg-if",
"winapi",
@@ -872,11 +889,12 @@ dependencies = [
[[package]]
name = "libmimalloc-sys"
-version = "0.1.26"
+version = "0.1.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8fc093ab289b0bfda3aa1bdfab9c9542be29c7ef385cfcbe77f8c9813588eb48"
+checksum = "dd8c7cbf8b89019683667e347572e6d55a7df7ea36b0c4ce69961b0cde67b174"
dependencies = [
"cc",
+ "libc",
]
[[package]]
@@ -915,9 +933,9 @@ dependencies = [
[[package]]
name = "lsp-types"
-version = "0.93.2"
+version = "0.94.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9be6e9c7e2d18f651974370d7aff703f9513e0df6e464fd795660edc77e6ca51"
+checksum = "0b63735a13a1f9cd4f4835223d828ed9c2e35c8c5e61837774399f558b6a1237"
dependencies = [
"bitflags",
"serde",
@@ -958,9 +976,9 @@ checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
[[package]]
name = "memmap2"
-version = "0.5.7"
+version = "0.5.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "95af15f345b17af2efc8ead6080fb8bc376f8cec1b35277b935637595fe77498"
+checksum = "4b182332558b18d807c4ce1ca8ca983b34c3ee32765e47b3f0f69b90355cc1dc"
dependencies = [
"libc",
]
@@ -975,33 +993,42 @@ dependencies = [
]
[[package]]
+name = "memoffset"
+version = "0.7.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5de893c32cde5f383baa4c04c5d6dbdd735cfd4a794b0debdb2bb1b421da5ff4"
+dependencies = [
+ "autocfg",
+]
+
+[[package]]
name = "mimalloc"
-version = "0.1.30"
+version = "0.1.34"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "76ce6a4b40d3bff9eb3ce9881ca0737a85072f9f975886082640cd46a75cdb35"
+checksum = "9dcb174b18635f7561a0c6c9fc2ce57218ac7523cf72c50af80e2d79ab8f3ba1"
dependencies = [
"libmimalloc-sys",
]
[[package]]
name = "miniz_oxide"
-version = "0.5.4"
+version = "0.6.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "96590ba8f175222643a85693f33d26e9c8a015f599c216509b1a6894af675d34"
+checksum = "b275950c28b37e794e8c55d88aeb5e139d0ce23fdbbeda68f8d7174abdf9e8fa"
dependencies = [
"adler",
]
[[package]]
name = "mio"
-version = "0.8.4"
+version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "57ee1c23c7c63b0c9250c339ffdc69255f110b298b901b9f6c82547b7b87caaf"
+checksum = "e5d732bc30207a6423068df043e3d02e0735b155ad7ce1a6f76fe2baa5b158de"
dependencies = [
"libc",
"log",
"wasi",
- "windows-sys 0.36.1",
+ "windows-sys",
]
[[package]]
@@ -1010,20 +1037,19 @@ version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "52ffbca2f655e33c08be35d87278e5b18b89550a37dbd598c20db92f6a471123"
dependencies = [
- "windows-sys 0.42.0",
+ "windows-sys",
]
[[package]]
name = "nix"
-version = "0.22.3"
+version = "0.26.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e4916f159ed8e5de0082076562152a76b7a1f64a01fd9d1e0fea002c37624faf"
+checksum = "bfdda3d196821d6af13126e40375cdf7da646a96114af134d5f417a9a1dc8e1a"
dependencies = [
"bitflags",
- "cc",
"cfg-if",
"libc",
- "memoffset",
+ "static_assertions",
]
[[package]]
@@ -1045,29 +1071,39 @@ dependencies = [
]
[[package]]
+name = "nu-ansi-term"
+version = "0.46.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84"
+dependencies = [
+ "overload",
+ "winapi",
+]
+
+[[package]]
name = "num_cpus"
-version = "1.13.1"
+version = "1.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "19e64526ebdee182341572e50e9ad03965aa510cd94427a4549448f285e957a1"
+checksum = "0fac9e2da13b5eb447a6ce3d392f23a29d8694bff781bf03a16cd9ac8697593b"
dependencies = [
- "hermit-abi",
+ "hermit-abi 0.2.6",
"libc",
]
[[package]]
name = "object"
-version = "0.29.0"
+version = "0.30.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "21158b2c33aa6d4561f1c0a6ea283ca92bc54802a93b263e910746d679a7eb53"
+checksum = "2b8c786513eb403643f2a88c244c2aaa270ef2153f55094587d0c48a3cf22a83"
dependencies = [
"memchr",
]
[[package]]
name = "once_cell"
-version = "1.15.0"
+version = "1.17.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e82dad04139b71a90c080c8463fe0dc7902db5192d939bd0950f074d014339e1"
+checksum = "6f61fba1741ea2b3d6a1e3178721804bb716a68a6aeba1149b5d52e3d464ea66"
[[package]]
name = "oorandom"
@@ -1076,6 +1112,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0ab1bc2a289d34bd04a330323ac98a1b4bc82c9d9fcb1e66b63caa84da26b575"
[[package]]
+name = "overload"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39"
+
+[[package]]
name = "parking_lot"
version = "0.11.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1083,7 +1125,7 @@ checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99"
dependencies = [
"instant",
"lock_api",
- "parking_lot_core 0.8.5",
+ "parking_lot_core 0.8.6",
]
[[package]]
@@ -1093,14 +1135,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f"
dependencies = [
"lock_api",
- "parking_lot_core 0.9.4",
+ "parking_lot_core 0.9.6",
]
[[package]]
name = "parking_lot_core"
-version = "0.8.5"
+version = "0.8.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d76e8e1493bcac0d2766c42737f34458f1c8c50c0d23bcb24ea953affb273216"
+checksum = "60a2cfe6f0ad2bfc16aefa463b497d5c7a5ecd44a23efa72aa342d90177356dc"
dependencies = [
"cfg-if",
"instant",
@@ -1112,15 +1154,15 @@ dependencies = [
[[package]]
name = "parking_lot_core"
-version = "0.9.4"
+version = "0.9.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4dc9e0dc2adc1c69d09143aff38d3d30c5c3f0df0dad82e6d25547af174ebec0"
+checksum = "ba1ef8814b5c993410bb3adfad7a5ed269563e4a2f90c41f5d85be7fb47133bf"
dependencies = [
"cfg-if",
"libc",
"redox_syscall",
"smallvec",
- "windows-sys 0.42.0",
+ "windows-sys",
]
[[package]]
@@ -1132,13 +1174,14 @@ dependencies = [
"limit",
"rustc-ap-rustc_lexer",
"sourcegen",
+ "stdx",
]
[[package]]
name = "paste"
-version = "1.0.9"
+version = "1.0.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b1de2e551fb905ac83f73f7aedf2f0cb4a0da7e35efa24a202a936269f1f18e1"
+checksum = "d01a5bd0424d00070b0098dd17ebca6f961a959dead1dbcbbbc1d1cd8d3deeba"
[[package]]
name = "paths"
@@ -1238,9 +1281,9 @@ version = "0.0.0"
[[package]]
name = "proc-macro2"
-version = "1.0.47"
+version = "1.0.50"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5ea3d908b0e36316caf9e9e2c4625cdde190a7e6f440d794667ed17a1855e725"
+checksum = "6ef7d57beacfaf2d8aee5937dab7b7f28de3cb8b1828479bb5de2a7106f2bae2"
dependencies = [
"unicode-ident",
]
@@ -1322,30 +1365,28 @@ dependencies = [
[[package]]
name = "quote"
-version = "1.0.21"
+version = "1.0.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179"
+checksum = "8856d8364d252a14d474036ea1358d63c9e6965c8e5c1885c18f73d70bff9c7b"
dependencies = [
"proc-macro2",
]
[[package]]
name = "rayon"
-version = "1.5.3"
+version = "1.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bd99e5772ead8baa5215278c9b15bf92087709e9c1b2d1f97cdb5a183c933a7d"
+checksum = "6db3a213adf02b3bcfd2d3846bb41cb22857d131789e01df434fb7e7bc0759b7"
dependencies = [
- "autocfg",
- "crossbeam-deque",
"either",
"rayon-core",
]
[[package]]
name = "rayon-core"
-version = "1.9.3"
+version = "1.10.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "258bcdb5ac6dad48491bb2992db6b7cf74878b0384908af124823d118c99683f"
+checksum = "cac410af5d00ab6884528b4ab69d1e8e146e8d471201800fa1b4524126de6ad3"
dependencies = [
"crossbeam-channel",
"crossbeam-deque",
@@ -1364,9 +1405,9 @@ dependencies = [
[[package]]
name = "regex"
-version = "1.6.0"
+version = "1.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4c4eb3267174b8c6c2f654116623910a0fef09c4753f8dd83db29c48a0df988b"
+checksum = "48aaa5748ba571fb95cd2c85c09f629215d3a6ece942baa100950af03a34f733"
dependencies = [
"regex-syntax",
]
@@ -1382,9 +1423,9 @@ dependencies = [
[[package]]
name = "regex-syntax"
-version = "0.6.27"
+version = "0.6.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a3f87b73ce11b1619a3c6332f45341e0047173771e8b8b73f87bfeefb7b56244"
+checksum = "456c603be3e8d448b072f410900c09faf164fbce2d480456f50eea6e25f9c848"
[[package]]
name = "rowan"
@@ -1394,7 +1435,7 @@ checksum = "5811547e7ba31e903fe48c8ceab10d40d70a101f3d15523c847cce91aa71f332"
dependencies = [
"countme",
"hashbrown",
- "memoffset",
+ "memoffset 0.6.5",
"rustc-hash",
"text-size",
]
@@ -1455,9 +1496,9 @@ dependencies = [
[[package]]
name = "rustc-ap-rustc_lexer"
-version = "725.0.0"
+version = "727.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f950742ef8a203aa7661aad3ab880438ddeb7f95d4b837c30d65db1a2c5df68e"
+checksum = "8f40f26e7abdcd3b982f36c09a634cc6187988fbf6ec466c91f8d30a12ac0237"
dependencies = [
"unicode-xid",
]
@@ -1476,9 +1517,9 @@ checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
[[package]]
name = "ryu"
-version = "1.0.11"
+version = "1.0.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4501abdff3ae82a1c1b477a17252eb69cee9e66eb915c1abaa4f44d873df9f09"
+checksum = "7b4b9743ed687d4b4bcedf9ff5eaa7398495ae14e61cba0a295704edbc7decde"
[[package]]
name = "salsa"
@@ -1529,9 +1570,9 @@ dependencies = [
[[package]]
name = "scoped-tls"
-version = "1.0.0"
+version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ea6a9290e3c9cf0f18145ef7ffa62d68ee0bf5fcd651017e586dc7fd5da448c2"
+checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294"
[[package]]
name = "scopeguard"
@@ -1541,27 +1582,27 @@ checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
[[package]]
name = "semver"
-version = "1.0.14"
+version = "1.0.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e25dfac463d778e353db5be2449d1cce89bd6fd23c9f1ea21310ce6e5a1b29c4"
+checksum = "58bc9567378fc7690d6b2addae4e60ac2eeea07becb2c64b9f218b53865cba2a"
dependencies = [
"serde",
]
[[package]]
name = "serde"
-version = "1.0.145"
+version = "1.0.152"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "728eb6351430bccb993660dfffc5a72f91ccc1295abaa8ce19b27ebe4f75568b"
+checksum = "bb7d1f0d3021d347a83e556fc4683dea2ea09d87bccdf88ff5c12545d89d5efb"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
-version = "1.0.145"
+version = "1.0.152"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "81fa1584d3d1bcacd84c277a0dfe21f5b0f6accf4a23d04d4c6d61f1af522b4c"
+checksum = "af487d118eecd09402d70a5d72551860e788df87b464af30e5ea6a38c75c541e"
dependencies = [
"proc-macro2",
"quote",
@@ -1570,9 +1611,9 @@ dependencies = [
[[package]]
name = "serde_json"
-version = "1.0.86"
+version = "1.0.91"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "41feea4228a6f1cd09ec7a3593a682276702cd67b5273544757dae23c096f074"
+checksum = "877c235533714907a8c2464236f5c4b2a17262ef1bd71f38f35ea592c8da6883"
dependencies = [
"indexmap",
"itoa",
@@ -1582,9 +1623,9 @@ dependencies = [
[[package]]
name = "serde_repr"
-version = "0.1.9"
+version = "0.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1fe39d9fbb0ebf5eb2c7cb7e2a47e4f462fad1379f1166b8ae49ad9eae89a7ca"
+checksum = "9a5ec9fa74a20ebbe5d9ac23dac1fc96ba0ecfe9f50f2843b52e537b10fbcb4e"
dependencies = [
"proc-macro2",
"quote",
@@ -1617,9 +1658,9 @@ dependencies = [
[[package]]
name = "snap"
-version = "1.0.5"
+version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "45456094d1983e2ee2a18fdfebce3189fa451699d0502cb8e3b49dba5ba41451"
+checksum = "5e9f0ab6ef7eb7353d9119c170a436d1bf248eea575ac42d19d12f4e34130831"
[[package]]
name = "sourcegen"
@@ -1629,6 +1670,12 @@ dependencies = [
]
[[package]]
+name = "static_assertions"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
+
+[[package]]
name = "stdx"
version = "0.0.0"
dependencies = [
@@ -1641,9 +1688,9 @@ dependencies = [
[[package]]
name = "syn"
-version = "1.0.102"
+version = "1.0.107"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3fcd952facd492f9be3ef0d0b7032a6e442ee9b361d4acc2b1d0c4aaa5f613a1"
+checksum = "1f4064b5b16e03ae50984a5a8ed5d4f8803e6bc1fd170a3cda91a1be4b18e3f5"
dependencies = [
"proc-macro2",
"quote",
@@ -1714,18 +1761,18 @@ checksum = "288cb548dbe72b652243ea797201f3d481a0609a967980fcc5b2315ea811560a"
[[package]]
name = "thiserror"
-version = "1.0.37"
+version = "1.0.38"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "10deb33631e3c9018b9baf9dcbbc4f737320d2b576bac10f6aefa048fa407e3e"
+checksum = "6a9cd18aa97d5c45c6603caea1da6628790b37f7a34b6ca89522331c5180fed0"
dependencies = [
"thiserror-impl",
]
[[package]]
name = "thiserror-impl"
-version = "1.0.37"
+version = "1.0.38"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "982d17546b47146b28f7c22e3d08465f6b8903d0ea13c1660d9d84a6e7adcdbb"
+checksum = "1fb327af4685e4d03fa8cbcf1716380da910eeb2bb8be417e7f9fd3fb164f36f"
dependencies = [
"proc-macro2",
"quote",
@@ -1788,10 +1835,8 @@ version = "0.3.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a561bf4617eebd33bca6434b988f39ed798e527f51a1e797d0ee4f61c0a38376"
dependencies = [
- "itoa",
"serde",
"time-core",
- "time-macros",
]
[[package]]
@@ -1801,15 +1846,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2e153e1f1acaef8acc537e68b44906d2db6436e2b35ac2c6b42640fff91f00fd"
[[package]]
-name = "time-macros"
-version = "0.2.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d967f99f534ca7e495c575c62638eebc2898a8c84c119b89e250477bc4ba16b2"
-dependencies = [
- "time-core",
-]
-
-[[package]]
name = "tinyvec"
version = "1.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1893,12 +1929,12 @@ dependencies = [
[[package]]
name = "tracing-tree"
-version = "0.2.1"
+version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d07e90b329c621ade432823988574e820212648aa40e7a2497777d58de0fb453"
+checksum = "758e983ab7c54fee18403994507e7f212b9005e957ce7984996fac8d11facedb"
dependencies = [
- "ansi_term",
"atty",
+ "nu-ansi-term",
"tracing-core",
"tracing-log",
"tracing-subscriber",
@@ -1914,9 +1950,9 @@ dependencies = [
[[package]]
name = "typed-arena"
-version = "2.0.1"
+version = "2.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0685c84d5d54d1c26f7d3eb96cd41550adb97baed141a761cf335d3d33bcd0ae"
+checksum = "6af6ae20167a9ece4bcb41af5b80f8a1f1df981f6391189ce00fd257af04126a"
[[package]]
name = "ungrammar"
@@ -1935,15 +1971,15 @@ dependencies = [
[[package]]
name = "unicode-bidi"
-version = "0.3.8"
+version = "0.3.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "099b7128301d285f79ddd55b9a83d5e6b9e97c92e0ea0daebee7263e932de992"
+checksum = "d54675592c1dbefd78cbd98db9bacd89886e1ca50692a0692baefffdeb92dd58"
[[package]]
name = "unicode-ident"
-version = "1.0.5"
+version = "1.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6ceab39d59e4c9499d4e5a8ee0e2735b891bb7308ac83dfb4e80cad195c9f6f3"
+checksum = "84a22b9f218b40614adcb3f4ff08b703773ad44fa9423e4e0d346d5db86e4ebc"
[[package]]
name = "unicode-normalization"
@@ -2064,103 +2100,60 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
[[package]]
name = "windows-sys"
-version = "0.36.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ea04155a16a59f9eab786fe12a4a450e75cdb175f9e0d80da1e17db09f55b8d2"
-dependencies = [
- "windows_aarch64_msvc 0.36.1",
- "windows_i686_gnu 0.36.1",
- "windows_i686_msvc 0.36.1",
- "windows_x86_64_gnu 0.36.1",
- "windows_x86_64_msvc 0.36.1",
-]
-
-[[package]]
-name = "windows-sys"
version = "0.42.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7"
dependencies = [
"windows_aarch64_gnullvm",
- "windows_aarch64_msvc 0.42.0",
- "windows_i686_gnu 0.42.0",
- "windows_i686_msvc 0.42.0",
- "windows_x86_64_gnu 0.42.0",
+ "windows_aarch64_msvc",
+ "windows_i686_gnu",
+ "windows_i686_msvc",
+ "windows_x86_64_gnu",
"windows_x86_64_gnullvm",
- "windows_x86_64_msvc 0.42.0",
+ "windows_x86_64_msvc",
]
[[package]]
name = "windows_aarch64_gnullvm"
-version = "0.42.0"
+version = "0.42.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "41d2aa71f6f0cbe00ae5167d90ef3cfe66527d6f613ca78ac8024c3ccab9a19e"
+checksum = "8c9864e83243fdec7fc9c5444389dcbbfd258f745e7853198f365e3c4968a608"
[[package]]
name = "windows_aarch64_msvc"
-version = "0.36.1"
+version = "0.42.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9bb8c3fd39ade2d67e9874ac4f3db21f0d710bee00fe7cab16949ec184eeaa47"
-
-[[package]]
-name = "windows_aarch64_msvc"
-version = "0.42.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dd0f252f5a35cac83d6311b2e795981f5ee6e67eb1f9a7f64eb4500fbc4dcdb4"
-
-[[package]]
-name = "windows_i686_gnu"
-version = "0.36.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "180e6ccf01daf4c426b846dfc66db1fc518f074baa793aa7d9b9aaeffad6a3b6"
+checksum = "4c8b1b673ffc16c47a9ff48570a9d85e25d265735c503681332589af6253c6c7"
[[package]]
name = "windows_i686_gnu"
-version = "0.42.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fbeae19f6716841636c28d695375df17562ca208b2b7d0dc47635a50ae6c5de7"
-
-[[package]]
-name = "windows_i686_msvc"
-version = "0.36.1"
+version = "0.42.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e2e7917148b2812d1eeafaeb22a97e4813dfa60a3f8f78ebe204bcc88f12f024"
+checksum = "de3887528ad530ba7bdbb1faa8275ec7a1155a45ffa57c37993960277145d640"
[[package]]
name = "windows_i686_msvc"
-version = "0.42.0"
+version = "0.42.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "84c12f65daa39dd2babe6e442988fc329d6243fdce47d7d2d155b8d874862246"
+checksum = "bf4d1122317eddd6ff351aa852118a2418ad4214e6613a50e0191f7004372605"
[[package]]
name = "windows_x86_64_gnu"
-version = "0.36.1"
+version = "0.42.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4dcd171b8776c41b97521e5da127a2d86ad280114807d0b2ab1e462bc764d9e1"
-
-[[package]]
-name = "windows_x86_64_gnu"
-version = "0.42.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bf7b1b21b5362cbc318f686150e5bcea75ecedc74dd157d874d754a2ca44b0ed"
+checksum = "c1040f221285e17ebccbc2591ffdc2d44ee1f9186324dd3e84e99ac68d699c45"
[[package]]
name = "windows_x86_64_gnullvm"
-version = "0.42.0"
+version = "0.42.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "09d525d2ba30eeb3297665bd434a54297e4170c7f1a44cad4ef58095b4cd2028"
+checksum = "628bfdf232daa22b0d64fdb62b09fcc36bb01f05a3939e20ab73aaf9470d0463"
[[package]]
name = "windows_x86_64_msvc"
-version = "0.36.1"
+version = "0.42.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c811ca4a8c853ef420abd8592ba53ddbbac90410fab6903b3e79972a631f7680"
-
-[[package]]
-name = "windows_x86_64_msvc"
-version = "0.42.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f40009d85759725a34da6d89a94e63d7bdc50a862acf0dbc7c8e488f1edcb6f5"
+checksum = "447660ad36a13288b1db4d4248e857b510e8c3a225c822ba4fb748c0aafecffd"
[[package]]
name = "write-json"
@@ -2170,33 +2163,33 @@ checksum = "06069a848f95fceae3e5e03c0ddc8cb78452b56654ee0c8e68f938cf790fb9e3"
[[package]]
name = "xflags"
-version = "0.3.0"
+version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cbf19f5031a1a812e96fede16f8161218883079946cea87619d3613db1efd268"
+checksum = "c4554b580522d0ca238369c16b8f6ce34524d61dafe7244993754bbd05f2c2ea"
dependencies = [
"xflags-macros",
]
[[package]]
name = "xflags-macros"
-version = "0.3.0"
+version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2afbd7f2039bb6cad2dd45f0c5dff49c0d4e26118398768b7a605524d4251809"
+checksum = "f58e7b3ca8977093aae6b87b6a7730216fc4c53a6530bab5c43a783cd810c1a8"
[[package]]
name = "xshell"
-version = "0.2.2"
+version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6d47097dc5c85234b1e41851b3422dd6d19b3befdd35b4ae5ce386724aeca981"
+checksum = "962c039b3a7b16cf4e9a4248397c6585c07547412e7d6a6e035389a802dcfe90"
dependencies = [
"xshell-macros",
]
[[package]]
name = "xshell-macros"
-version = "0.2.2"
+version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "88301b56c26dd9bf5c43d858538f82d6f3f7764767defbc5d34e59459901c41a"
+checksum = "1dbabb1cbd15a1d6d12d9ed6b35cc6777d4af87ab3ba155ea37215f20beab80c"
[[package]]
name = "xtask"
@@ -2204,6 +2197,7 @@ version = "0.1.0"
dependencies = [
"anyhow",
"flate2",
+ "time",
"write-json",
"xflags",
"xshell",
@@ -2212,9 +2206,9 @@ dependencies = [
[[package]]
name = "zip"
-version = "0.6.3"
+version = "0.6.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "537ce7411d25e54e8ae21a7ce0b15840e7bfcff15b51d697ec3266cc76bdf080"
+checksum = "0445d0fbc924bb93539b4316c11afb121ea39296f99a3c4c9edad09e3658cdef"
dependencies = [
"byteorder",
"crc32fast",
diff --git a/src/tools/rust-analyzer/Cargo.toml b/src/tools/rust-analyzer/Cargo.toml
index 286ef1e7d..333f03ce2 100644
--- a/src/tools/rust-analyzer/Cargo.toml
+++ b/src/tools/rust-analyzer/Cargo.toml
@@ -2,6 +2,12 @@
members = ["xtask/", "lib/*", "crates/*"]
exclude = ["crates/proc-macro-test/imp"]
+[workspace.package]
+rust-version = "1.66"
+edition = "2021"
+license = "MIT OR Apache-2.0"
+authors = ["rust-analyzer team"]
+
[profile.dev]
# Disabling debug info speeds up builds a bunch,
# and we don't rely on it for debugging that much.
@@ -32,3 +38,41 @@ debug = 0
# ungrammar = { path = "../ungrammar" }
# salsa = { path = "../salsa" }
+
+[workspace.dependencies]
+# local crates
+base-db = { path = "./crates/base-db", version = "0.0.0" }
+cfg = { path = "./crates/cfg", version = "0.0.0" }
+flycheck = { path = "./crates/flycheck", version = "0.0.0" }
+hir = { path = "./crates/hir", version = "0.0.0" }
+hir-def = { path = "./crates/hir-def", version = "0.0.0" }
+hir-expand = { path = "./crates/hir-expand", version = "0.0.0" }
+hir-ty = { path = "./crates/hir-ty", version = "0.0.0" }
+ide = { path = "./crates/ide", version = "0.0.0" }
+ide-assists = { path = "./crates/ide-assists", version = "0.0.0" }
+ide-completion = { path = "./crates/ide-completion", version = "0.0.0" }
+ide-db = { path = "./crates/ide-db", version = "0.0.0" }
+ide-diagnostics = { path = "./crates/ide-diagnostics", version = "0.0.0" }
+ide-ssr = { path = "./crates/ide-ssr", version = "0.0.0" }
+intern = { path = "./crates/intern", version = "0.0.0" }
+limit = { path = "./crates/limit", version = "0.0.0" }
+mbe = { path = "./crates/mbe", version = "0.0.0" }
+parser = { path = "./crates/parser", version = "0.0.0" }
+paths = { path = "./crates/paths", version = "0.0.0" }
+proc-macro-api = { path = "./crates/proc-macro-api", version = "0.0.0" }
+proc-macro-srv = { path = "./crates/proc-macro-srv", version = "0.0.0" }
+proc-macro-srv-cli = { path = "./crates/proc-macro-srv-cli", version = "0.0.0" }
+proc-macro-test = { path = "./crates/proc-macro-test", version = "0.0.0" }
+profile = { path = "./crates/profile", version = "0.0.0" }
+project-model = { path = "./crates/project-model", version = "0.0.0" }
+sourcegen = { path = "./crates/sourcegen", version = "0.0.0" }
+stdx = { path = "./crates/stdx", version = "0.0.0" }
+syntax = { path = "./crates/syntax", version = "0.0.0" }
+test-utils = { path = "./crates/test-utils", version = "0.0.0" }
+text-edit = { path = "./crates/text-edit", version = "0.0.0" }
+toolchain = { path = "./crates/toolchain", version = "0.0.0" }
+tt = { path = "./crates/tt", version = "0.0.0" }
+vfs-notify = { path = "./crates/vfs-notify", version = "0.0.0" }
+vfs = { path = "./crates/vfs", version = "0.0.0" }
+# non-local crates
+smallvec = { version = "1.10.0", features = ["const_new", "union", "const_generics"] }
diff --git a/src/tools/rust-analyzer/crates/base-db/Cargo.toml b/src/tools/rust-analyzer/crates/base-db/Cargo.toml
index a484ecec6..f6a1075c1 100644
--- a/src/tools/rust-analyzer/crates/base-db/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/base-db/Cargo.toml
@@ -2,9 +2,11 @@
name = "base-db"
version = "0.0.0"
description = "TBD"
-license = "MIT OR Apache-2.0"
-edition = "2021"
-rust-version = "1.65"
+
+authors.workspace = true
+edition.workspace = true
+license.workspace = true
+rust-version.workspace = true
[lib]
doctest = false
@@ -13,10 +15,11 @@ doctest = false
salsa = "0.17.0-pre.2"
rustc-hash = "1.1.0"
-syntax = { path = "../syntax", version = "0.0.0" }
-stdx = { path = "../stdx", version = "0.0.0" }
-cfg = { path = "../cfg", version = "0.0.0" }
-profile = { path = "../profile", version = "0.0.0" }
-tt = { path = "../tt", version = "0.0.0" }
-test-utils = { path = "../test-utils", version = "0.0.0" }
-vfs = { path = "../vfs", version = "0.0.0" }
+# local deps
+cfg.workspace = true
+profile.workspace = true
+stdx.workspace = true
+syntax.workspace = true
+test-utils.workspace = true
+tt.workspace = true
+vfs.workspace = true
diff --git a/src/tools/rust-analyzer/crates/base-db/src/fixture.rs b/src/tools/rust-analyzer/crates/base-db/src/fixture.rs
index 6f83ea40e..8a7e9dfad 100644
--- a/src/tools/rust-analyzer/crates/base-db/src/fixture.rs
+++ b/src/tools/rust-analyzer/crates/base-db/src/fixture.rs
@@ -6,7 +6,7 @@ use rustc_hash::FxHashMap;
use test_utils::{
extract_range_or_offset, Fixture, RangeOrOffset, CURSOR_MARKER, ESCAPED_CURSOR_MARKER,
};
-use tt::Subtree;
+use tt::token_id::{Leaf, Subtree, TokenTree};
use vfs::{file_set::FileSet, VfsPath};
use crate::{
@@ -110,6 +110,7 @@ impl ChangeFixture {
let mut crates = FxHashMap::default();
let mut crate_deps = Vec::new();
let mut default_crate_root: Option<FileId> = None;
+ let mut default_target_data_layout: Option<String> = None;
let mut default_cfg = CfgOptions::default();
let mut file_set = FileSet::default();
@@ -162,7 +163,10 @@ impl ChangeFixture {
Ok(Vec::new()),
false,
origin,
- meta.target_data_layout.as_deref().map(Arc::from),
+ meta.target_data_layout
+ .as_deref()
+ .map(Arc::from)
+ .ok_or_else(|| "target_data_layout unset".into()),
);
let prev = crates.insert(crate_name.clone(), crate_id);
assert!(prev.is_none());
@@ -175,6 +179,7 @@ impl ChangeFixture {
assert!(default_crate_root.is_none());
default_crate_root = Some(file_id);
default_cfg = meta.cfg;
+ default_target_data_layout = meta.target_data_layout;
}
change.change_file(file_id, Some(Arc::new(text)));
@@ -198,7 +203,9 @@ impl ChangeFixture {
Ok(Vec::new()),
false,
CrateOrigin::CratesIo { repo: None, name: None },
- None,
+ default_target_data_layout
+ .map(|x| x.into())
+ .ok_or_else(|| "target_data_layout unset".into()),
);
} else {
for (from, to, prelude) in crate_deps {
@@ -212,8 +219,10 @@ impl ChangeFixture {
.unwrap();
}
}
- let target_layout =
- crate_graph.iter().next().and_then(|it| crate_graph[it].target_layout.clone());
+ let target_layout = crate_graph.iter().next().map_or_else(
+ || Err("target_data_layout unset".into()),
+ |it| crate_graph[it].target_layout.clone(),
+ );
if let Some(mini_core) = mini_core {
let core_file = file_id;
@@ -301,7 +310,7 @@ impl ChangeFixture {
}
}
-fn default_test_proc_macros() -> [(String, ProcMacro); 4] {
+fn default_test_proc_macros() -> [(String, ProcMacro); 5] {
[
(
r#"
@@ -359,6 +368,20 @@ pub fn mirror(input: TokenStream) -> TokenStream {
expander: Arc::new(MirrorProcMacroExpander),
},
),
+ (
+ r#"
+#[proc_macro]
+pub fn shorten(input: TokenStream) -> TokenStream {
+ loop {}
+}
+"#
+ .into(),
+ ProcMacro {
+ name: "shorten".into(),
+ kind: crate::ProcMacroKind::FuncLike,
+ expander: Arc::new(ShortenProcMacroExpander),
+ },
+ ),
]
}
@@ -486,17 +509,60 @@ impl ProcMacroExpander for MirrorProcMacroExpander {
_: &Env,
) -> Result<Subtree, ProcMacroExpansionError> {
fn traverse(input: &Subtree) -> Subtree {
- let mut res = Subtree::default();
- res.delimiter = input.delimiter;
+ let mut token_trees = vec![];
for tt in input.token_trees.iter().rev() {
let tt = match tt {
tt::TokenTree::Leaf(leaf) => tt::TokenTree::Leaf(leaf.clone()),
tt::TokenTree::Subtree(sub) => tt::TokenTree::Subtree(traverse(sub)),
};
- res.token_trees.push(tt);
+ token_trees.push(tt);
}
- res
+ Subtree { delimiter: input.delimiter, token_trees }
}
Ok(traverse(input))
}
}
+
+// Replaces every literal with an empty string literal and every identifier with its first letter,
+// but retains all tokens' span. Useful for testing we don't assume token hasn't been modified by
+// macros even if it retains its span.
+#[derive(Debug)]
+struct ShortenProcMacroExpander;
+impl ProcMacroExpander for ShortenProcMacroExpander {
+ fn expand(
+ &self,
+ input: &Subtree,
+ _: Option<&Subtree>,
+ _: &Env,
+ ) -> Result<Subtree, ProcMacroExpansionError> {
+ return Ok(traverse(input));
+
+ fn traverse(input: &Subtree) -> Subtree {
+ let token_trees = input
+ .token_trees
+ .iter()
+ .map(|it| match it {
+ TokenTree::Leaf(leaf) => tt::TokenTree::Leaf(modify_leaf(leaf)),
+ TokenTree::Subtree(subtree) => tt::TokenTree::Subtree(traverse(subtree)),
+ })
+ .collect();
+ Subtree { delimiter: input.delimiter, token_trees }
+ }
+
+ fn modify_leaf(leaf: &Leaf) -> Leaf {
+ let mut leaf = leaf.clone();
+ match &mut leaf {
+ Leaf::Literal(it) => {
+ // XXX Currently replaces any literals with an empty string, but supporting
+ // "shortening" other literals would be nice.
+ it.text = "\"\"".into();
+ }
+ Leaf::Punct(_) => {}
+ Leaf::Ident(it) => {
+ it.text = it.text.chars().take(1).collect();
+ }
+ }
+ leaf
+ }
+ }
+}
diff --git a/src/tools/rust-analyzer/crates/base-db/src/input.rs b/src/tools/rust-analyzer/crates/base-db/src/input.rs
index 5fa4a8024..43388e915 100644
--- a/src/tools/rust-analyzer/crates/base-db/src/input.rs
+++ b/src/tools/rust-analyzer/crates/base-db/src/input.rs
@@ -12,7 +12,7 @@ use cfg::CfgOptions;
use rustc_hash::FxHashMap;
use stdx::hash::{NoHashHashMap, NoHashHashSet};
use syntax::SmolStr;
-use tt::Subtree;
+use tt::token_id::Subtree;
use vfs::{file_set::FileSet, AnchoredPath, FileId, VfsPath};
/// Files are grouped into source roots. A source root is a directory on the
@@ -84,15 +84,10 @@ pub struct CrateGraph {
arena: NoHashHashMap<CrateId, CrateData>,
}
-#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
+#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct CrateId(pub u32);
impl stdx::hash::NoHashHashable for CrateId {}
-impl std::hash::Hash for CrateId {
- fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
- self.0.hash(state);
- }
-}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct CrateName(SmolStr);
@@ -248,6 +243,7 @@ pub enum ProcMacroExpansionError {
}
pub type ProcMacroLoadResult = Result<Vec<ProcMacro>, String>;
+pub type TargetLayoutLoadResult = Result<Arc<str>, Arc<str>>;
#[derive(Debug, Clone)]
pub struct ProcMacro {
@@ -270,7 +266,7 @@ pub struct CrateData {
pub display_name: Option<CrateDisplayName>,
pub cfg_options: CfgOptions,
pub potential_cfg_options: CfgOptions,
- pub target_layout: Option<Arc<str>>,
+ pub target_layout: TargetLayoutLoadResult,
pub env: Env,
pub dependencies: Vec<Dependency>,
pub proc_macro: ProcMacroLoadResult,
@@ -286,7 +282,7 @@ pub enum Edition {
}
impl Edition {
- pub const CURRENT: Edition = Edition::Edition2018;
+ pub const CURRENT: Edition = Edition::Edition2021;
}
#[derive(Default, Debug, Clone, PartialEq, Eq)]
@@ -329,7 +325,7 @@ impl CrateGraph {
proc_macro: ProcMacroLoadResult,
is_proc_macro: bool,
origin: CrateOrigin,
- target_layout: Option<Arc<str>>,
+ target_layout: Result<Arc<str>, Arc<str>>,
) -> CrateId {
let data = CrateData {
root_file_id,
@@ -652,7 +648,7 @@ mod tests {
Ok(Vec::new()),
false,
CrateOrigin::CratesIo { repo: None, name: None },
- None,
+ Err("".into()),
);
let crate2 = graph.add_crate_root(
FileId(2u32),
@@ -665,7 +661,7 @@ mod tests {
Ok(Vec::new()),
false,
CrateOrigin::CratesIo { repo: None, name: None },
- None,
+ Err("".into()),
);
let crate3 = graph.add_crate_root(
FileId(3u32),
@@ -678,7 +674,7 @@ mod tests {
Ok(Vec::new()),
false,
CrateOrigin::CratesIo { repo: None, name: None },
- None,
+ Err("".into()),
);
assert!(graph
.add_dep(crate1, Dependency::new(CrateName::new("crate2").unwrap(), crate2))
@@ -705,7 +701,7 @@ mod tests {
Ok(Vec::new()),
false,
CrateOrigin::CratesIo { repo: None, name: None },
- None,
+ Err("".into()),
);
let crate2 = graph.add_crate_root(
FileId(2u32),
@@ -718,7 +714,7 @@ mod tests {
Ok(Vec::new()),
false,
CrateOrigin::CratesIo { repo: None, name: None },
- None,
+ Err("".into()),
);
assert!(graph
.add_dep(crate1, Dependency::new(CrateName::new("crate2").unwrap(), crate2))
@@ -742,7 +738,7 @@ mod tests {
Ok(Vec::new()),
false,
CrateOrigin::CratesIo { repo: None, name: None },
- None,
+ Err("".into()),
);
let crate2 = graph.add_crate_root(
FileId(2u32),
@@ -755,7 +751,7 @@ mod tests {
Ok(Vec::new()),
false,
CrateOrigin::CratesIo { repo: None, name: None },
- None,
+ Err("".into()),
);
let crate3 = graph.add_crate_root(
FileId(3u32),
@@ -768,7 +764,7 @@ mod tests {
Ok(Vec::new()),
false,
CrateOrigin::CratesIo { repo: None, name: None },
- None,
+ Err("".into()),
);
assert!(graph
.add_dep(crate1, Dependency::new(CrateName::new("crate2").unwrap(), crate2))
@@ -792,7 +788,7 @@ mod tests {
Ok(Vec::new()),
false,
CrateOrigin::CratesIo { repo: None, name: None },
- None,
+ Err("".into()),
);
let crate2 = graph.add_crate_root(
FileId(2u32),
@@ -805,7 +801,7 @@ mod tests {
Ok(Vec::new()),
false,
CrateOrigin::CratesIo { repo: None, name: None },
- None,
+ Err("".into()),
);
assert!(graph
.add_dep(
diff --git a/src/tools/rust-analyzer/crates/base-db/src/lib.rs b/src/tools/rust-analyzer/crates/base-db/src/lib.rs
index 55a51d3bb..9720db9d8 100644
--- a/src/tools/rust-analyzer/crates/base-db/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/base-db/src/lib.rs
@@ -17,6 +17,7 @@ pub use crate::{
CrateData, CrateDisplayName, CrateGraph, CrateId, CrateName, CrateOrigin, Dependency,
Edition, Env, LangCrateOrigin, ProcMacro, ProcMacroExpander, ProcMacroExpansionError,
ProcMacroId, ProcMacroKind, ProcMacroLoadResult, SourceRoot, SourceRootId,
+ TargetLayoutLoadResult,
},
};
pub use salsa::{self, Cancelled};
diff --git a/src/tools/rust-analyzer/crates/cfg/Cargo.toml b/src/tools/rust-analyzer/crates/cfg/Cargo.toml
index 2857420c2..0880bc239 100644
--- a/src/tools/rust-analyzer/crates/cfg/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/cfg/Cargo.toml
@@ -2,9 +2,11 @@
name = "cfg"
version = "0.0.0"
description = "TBD"
-license = "MIT OR Apache-2.0"
-edition = "2021"
-rust-version = "1.65"
+
+authors.workspace = true
+edition.workspace = true
+license.workspace = true
+rust-version.workspace = true
[lib]
doctest = false
@@ -12,15 +14,18 @@ doctest = false
[dependencies]
rustc-hash = "1.1.0"
-tt = { path = "../tt", version = "0.0.0" }
+# locals deps
+tt.workspace = true
[dev-dependencies]
-mbe = { path = "../mbe" }
-syntax = { path = "../syntax" }
expect-test = "1.4.0"
oorandom = "11.1.3"
# We depend on both individually instead of using `features = ["derive"]` to microoptimize the
# build graph: if the feature was enabled, syn would be built early on in the graph if `smolstr`
# supports `arbitrary`. This way, we avoid feature unification.
-arbitrary = "1.1.7"
-derive_arbitrary = "1.1.6"
+arbitrary = "1.2.2"
+derive_arbitrary = "1.2.2"
+
+# local deps
+mbe.workspace = true
+syntax.workspace = true
diff --git a/src/tools/rust-analyzer/crates/cfg/src/cfg_expr.rs b/src/tools/rust-analyzer/crates/cfg/src/cfg_expr.rs
index 5f4eefa83..fb7505ba2 100644
--- a/src/tools/rust-analyzer/crates/cfg/src/cfg_expr.rs
+++ b/src/tools/rust-analyzer/crates/cfg/src/cfg_expr.rs
@@ -66,7 +66,7 @@ impl From<CfgAtom> for CfgExpr {
}
impl CfgExpr {
- pub fn parse(tt: &tt::Subtree) -> CfgExpr {
+ pub fn parse<S>(tt: &tt::Subtree<S>) -> CfgExpr {
next_cfg_expr(&mut tt.token_trees.iter()).unwrap_or(CfgExpr::Invalid)
}
/// Fold the cfg by querying all basic `Atom` and `KeyValue` predicates.
@@ -85,7 +85,7 @@ impl CfgExpr {
}
}
-fn next_cfg_expr(it: &mut SliceIter<'_, tt::TokenTree>) -> Option<CfgExpr> {
+fn next_cfg_expr<S>(it: &mut SliceIter<'_, tt::TokenTree<S>>) -> Option<CfgExpr> {
let name = match it.next() {
None => return None,
Some(tt::TokenTree::Leaf(tt::Leaf::Ident(ident))) => ident.text.clone(),
diff --git a/src/tools/rust-analyzer/crates/flycheck/Cargo.toml b/src/tools/rust-analyzer/crates/flycheck/Cargo.toml
index 514d567fc..609d18c4e 100644
--- a/src/tools/rust-analyzer/crates/flycheck/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/flycheck/Cargo.toml
@@ -2,9 +2,11 @@
name = "flycheck"
version = "0.0.0"
description = "TBD"
-license = "MIT OR Apache-2.0"
-edition = "2021"
-rust-version = "1.65"
+
+authors.workspace = true
+edition.workspace = true
+license.workspace = true
+rust-version.workspace = true
[lib]
doctest = false
@@ -17,8 +19,9 @@ rustc-hash = "1.1.0"
serde = { version = "1.0.137", features = ["derive"] }
serde_json = "1.0.86"
jod-thread = "0.1.2"
-command-group = "1.0.8"
+command-group = "2.0.1"
-toolchain = { path = "../toolchain", version = "0.0.0" }
-stdx = { path = "../stdx", version = "0.0.0" }
-paths = { path = "../paths", version = "0.0.0" }
+# local deps
+paths.workspace = true
+stdx.workspace = true
+toolchain.workspace = true
diff --git a/src/tools/rust-analyzer/crates/hir-def/Cargo.toml b/src/tools/rust-analyzer/crates/hir-def/Cargo.toml
index 698be7665..31d4018d2 100644
--- a/src/tools/rust-analyzer/crates/hir-def/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/hir-def/Cargo.toml
@@ -2,9 +2,11 @@
name = "hir-def"
version = "0.0.0"
description = "TBD"
-license = "MIT OR Apache-2.0"
-edition = "2021"
-rust-version = "1.65"
+
+authors.workspace = true
+edition.workspace = true
+license.workspace = true
+rust-version.workspace = true
[lib]
doctest = false
@@ -23,23 +25,28 @@ hashbrown = { version = "0.12.1", default-features = false }
indexmap = "1.9.1"
itertools = "0.10.5"
la-arena = { version = "0.3.0", path = "../../lib/la-arena" }
-once_cell = "1.15.0"
+once_cell = "1.17.0"
rustc-hash = "1.1.0"
-smallvec = "1.10.0"
+smallvec.workspace = true
tracing = "0.1.35"
-stdx = { path = "../stdx", version = "0.0.0" }
-base-db = { path = "../base-db", version = "0.0.0" }
-syntax = { path = "../syntax", version = "0.0.0" }
-profile = { path = "../profile", version = "0.0.0" }
-hir-expand = { path = "../hir-expand", version = "0.0.0" }
rustc_abi = { version = "0.0.20221221", package = "hkalbasi-rustc-ap-rustc_abi", default-features = false }
rustc_index = { version = "0.0.20221221", package = "hkalbasi-rustc-ap-rustc_index", default-features = false }
-mbe = { path = "../mbe", version = "0.0.0" }
-cfg = { path = "../cfg", version = "0.0.0" }
-tt = { path = "../tt", version = "0.0.0" }
-limit = { path = "../limit", version = "0.0.0" }
+
+# local deps
+stdx.workspace = true
+intern.workspace = true
+base-db.workspace = true
+syntax.workspace = true
+profile.workspace = true
+hir-expand.workspace = true
+mbe.workspace = true
+cfg.workspace = true
+tt.workspace = true
+limit.workspace = true
[dev-dependencies]
-test-utils = { path = "../test-utils" }
expect-test = "1.4.0"
+
+# local deps
+test-utils.workspace = true
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/adt.rs b/src/tools/rust-analyzer/crates/hir-def/src/adt.rs
index db3b41948..9bc1c54a3 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/adt.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/adt.rs
@@ -3,33 +3,34 @@
use std::sync::Arc;
use base_db::CrateId;
+use cfg::CfgOptions;
use either::Either;
+
use hir_expand::{
name::{AsName, Name},
HirFileId, InFile,
};
+use intern::Interned;
use la_arena::{Arena, ArenaMap};
use rustc_abi::{Integer, IntegerType};
use syntax::ast::{self, HasName, HasVisibility};
-use tt::{Delimiter, DelimiterKind, Leaf, Subtree, TokenTree};
use crate::{
body::{CfgExpander, LowerCtx},
builtin_type::{BuiltinInt, BuiltinUint},
db::DefDatabase,
- intern::Interned,
item_tree::{AttrOwner, Field, FieldAstId, Fields, ItemTree, ModItem, RawVisibilityId},
layout::{Align, ReprFlags, ReprOptions},
nameres::diagnostics::DefDiagnostic,
src::HasChildSource,
src::HasSource,
trace::Trace,
+ tt::{Delimiter, DelimiterKind, Leaf, Subtree, TokenTree},
type_ref::TypeRef,
visibility::RawVisibility,
EnumId, LocalEnumVariantId, LocalFieldId, LocalModuleId, Lookup, ModuleId, StructId, UnionId,
VariantId,
};
-use cfg::CfgOptions;
/// Note that we use `StructData` for unions as well!
#[derive(Debug, Clone, PartialEq, Eq)]
@@ -82,7 +83,7 @@ fn repr_from_value(
fn parse_repr_tt(tt: &Subtree) -> Option<ReprOptions> {
match tt.delimiter {
- Some(Delimiter { kind: DelimiterKind::Parenthesis, .. }) => {}
+ Delimiter { kind: DelimiterKind::Parenthesis, .. } => {}
_ => return None,
}
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/attr.rs b/src/tools/rust-analyzer/crates/hir-def/src/attr.rs
index ab5d180e1..fcd92ad33 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/attr.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/attr.rs
@@ -1,27 +1,26 @@
//! A higher level attributes based on TokenTree, with also some shortcuts.
-use std::{fmt, hash::Hash, ops, sync::Arc};
+use std::{hash::Hash, ops, sync::Arc};
use base_db::CrateId;
use cfg::{CfgExpr, CfgOptions};
use either::Either;
-use hir_expand::{hygiene::Hygiene, name::AsName, HirFileId, InFile};
+use hir_expand::{
+ attrs::{collect_attrs, Attr, AttrId, RawAttrs},
+ HirFileId, InFile,
+};
use itertools::Itertools;
use la_arena::{ArenaMap, Idx, RawIdx};
-use mbe::{syntax_node_to_token_tree, DelimiterKind, Punct};
-use smallvec::{smallvec, SmallVec};
+use mbe::DelimiterKind;
use syntax::{
- ast::{self, AstNode, HasAttrs, IsString},
- match_ast, AstPtr, AstToken, SmolStr, SyntaxNode, TextRange, TextSize,
+ ast::{self, HasAttrs, IsString},
+ AstPtr, AstToken, SmolStr, TextRange, TextSize,
};
-use tt::Subtree;
use crate::{
db::DefDatabase,
- intern::Interned,
item_tree::{AttrOwner, Fields, ItemTreeId, ItemTreeNode},
nameres::{ModuleOrigin, ModuleSource},
- path::{ModPath, PathKind},
src::{HasChildSource, HasSource},
AdtId, AttrDefId, EnumId, GenericParamId, LocalEnumVariantId, LocalFieldId, Lookup, MacroId,
VariantId,
@@ -47,12 +46,6 @@ impl From<Documentation> for String {
}
}
-/// Syntactical attributes, without filtering of `cfg_attr`s.
-#[derive(Default, Debug, Clone, PartialEq, Eq)]
-pub(crate) struct RawAttrs {
- entries: Option<Arc<[Attr]>>,
-}
-
#[derive(Default, Debug, Clone, PartialEq, Eq)]
pub struct Attrs(RawAttrs);
@@ -62,30 +55,21 @@ pub struct AttrsWithOwner {
owner: AttrDefId,
}
-impl ops::Deref for RawAttrs {
- type Target = [Attr];
-
- fn deref(&self) -> &[Attr] {
- match &self.entries {
- Some(it) => &*it,
- None => &[],
- }
- }
-}
impl Attrs {
pub fn get(&self, id: AttrId) -> Option<&Attr> {
(**self).iter().find(|attr| attr.id == id)
}
+
+ pub(crate) fn filter(db: &dyn DefDatabase, krate: CrateId, raw_attrs: RawAttrs) -> Attrs {
+ Attrs(raw_attrs.filter(db.upcast(), krate))
+ }
}
impl ops::Deref for Attrs {
type Target = [Attr];
fn deref(&self) -> &[Attr] {
- match &self.0.entries {
- Some(it) => &*it,
- None => &[],
- }
+ &self.0
}
}
@@ -97,114 +81,6 @@ impl ops::Deref for AttrsWithOwner {
}
}
-impl RawAttrs {
- pub(crate) const EMPTY: Self = Self { entries: None };
-
- pub(crate) fn new(db: &dyn DefDatabase, owner: &dyn ast::HasAttrs, hygiene: &Hygiene) -> Self {
- let entries = collect_attrs(owner)
- .filter_map(|(id, attr)| match attr {
- Either::Left(attr) => {
- attr.meta().and_then(|meta| Attr::from_src(db, meta, hygiene, id))
- }
- Either::Right(comment) => comment.doc_comment().map(|doc| Attr {
- id,
- input: Some(Interned::new(AttrInput::Literal(SmolStr::new(doc)))),
- path: Interned::new(ModPath::from(hir_expand::name!(doc))),
- }),
- })
- .collect::<Arc<_>>();
-
- Self { entries: if entries.is_empty() { None } else { Some(entries) } }
- }
-
- fn from_attrs_owner(db: &dyn DefDatabase, owner: InFile<&dyn ast::HasAttrs>) -> Self {
- let hygiene = Hygiene::new(db.upcast(), owner.file_id);
- Self::new(db, owner.value, &hygiene)
- }
-
- pub(crate) fn merge(&self, other: Self) -> Self {
- // FIXME: This needs to fixup `AttrId`s
- match (&self.entries, other.entries) {
- (None, None) => Self::EMPTY,
- (None, entries @ Some(_)) => Self { entries },
- (Some(entries), None) => Self { entries: Some(entries.clone()) },
- (Some(a), Some(b)) => {
- let last_ast_index = a.last().map_or(0, |it| it.id.ast_index + 1);
- Self {
- entries: Some(
- a.iter()
- .cloned()
- .chain(b.iter().map(|it| {
- let mut it = it.clone();
- it.id.ast_index += last_ast_index;
- it
- }))
- .collect(),
- ),
- }
- }
- }
- }
-
- /// Processes `cfg_attr`s, returning the resulting semantic `Attrs`.
- pub(crate) fn filter(self, db: &dyn DefDatabase, krate: CrateId) -> Attrs {
- let has_cfg_attrs = self.iter().any(|attr| {
- attr.path.as_ident().map_or(false, |name| *name == hir_expand::name![cfg_attr])
- });
- if !has_cfg_attrs {
- return Attrs(self);
- }
-
- let crate_graph = db.crate_graph();
- let new_attrs = self
- .iter()
- .flat_map(|attr| -> SmallVec<[_; 1]> {
- let is_cfg_attr =
- attr.path.as_ident().map_or(false, |name| *name == hir_expand::name![cfg_attr]);
- if !is_cfg_attr {
- return smallvec![attr.clone()];
- }
-
- let subtree = match attr.token_tree_value() {
- Some(it) => it,
- _ => return smallvec![attr.clone()],
- };
-
- // Input subtree is: `(cfg, $(attr),+)`
- // Split it up into a `cfg` subtree and the `attr` subtrees.
- // FIXME: There should be a common API for this.
- let mut parts = subtree.token_trees.split(|tt| {
- matches!(tt, tt::TokenTree::Leaf(tt::Leaf::Punct(Punct { char: ',', .. })))
- });
- let cfg = match parts.next() {
- Some(it) => it,
- None => return smallvec![],
- };
- let cfg = Subtree { delimiter: subtree.delimiter, token_trees: cfg.to_vec() };
- let cfg = CfgExpr::parse(&cfg);
- let index = attr.id;
- let attrs = parts.filter(|a| !a.is_empty()).filter_map(|attr| {
- let tree = Subtree { delimiter: None, token_trees: attr.to_vec() };
- // FIXME hygiene
- let hygiene = Hygiene::new_unhygienic();
- Attr::from_tt(db, &tree, &hygiene, index)
- });
-
- let cfg_options = &crate_graph[krate].cfg_options;
- if cfg_options.check(&cfg) == Some(false) {
- smallvec![]
- } else {
- cov_mark::hit!(cfg_attr_active);
-
- attrs.collect()
- }
- })
- .collect();
-
- Attrs(RawAttrs { entries: Some(new_attrs) })
- }
-}
-
impl Attrs {
pub const EMPTY: Self = Self(RawAttrs::EMPTY);
@@ -251,19 +127,18 @@ impl Attrs {
let enum_ = &item_tree[loc.id.value];
let cfg_options = &crate_graph[krate].cfg_options;
- let variant = 'tri: loop {
- let mut idx = 0;
- for variant in enum_.variants.clone() {
- let attrs = item_tree.attrs(db, krate, variant.into());
- if attrs.is_cfg_enabled(cfg_options) {
- if it.local_id == Idx::from_raw(RawIdx::from(idx)) {
- break 'tri variant;
- }
- idx += 1;
- }
- }
+
+ let Some(variant) = enum_.variants.clone().filter(|variant| {
+ let attrs = item_tree.attrs(db, krate, (*variant).into());
+ attrs.is_cfg_enabled(cfg_options)
+ })
+ .zip(0u32..)
+ .find(|(_variant, idx)| it.local_id == Idx::from_raw(RawIdx::from(*idx)))
+ .map(|(variant, _idx)| variant)
+ else {
return Arc::new(res);
};
+
(item_tree[variant].fields.clone(), item_tree, krate)
}
VariantId::StructId(it) => {
@@ -358,7 +233,7 @@ impl Attrs {
pub fn has_doc_hidden(&self) -> bool {
self.by_key("doc").tt_values().any(|tt| {
- tt.delimiter_kind() == Some(DelimiterKind::Parenthesis) &&
+ tt.delimiter.kind == DelimiterKind::Parenthesis &&
matches!(&*tt.token_trees, [tt::TokenTree::Leaf(tt::Leaf::Ident(ident))] if ident.text == "hidden")
})
}
@@ -403,7 +278,7 @@ impl AttrsWithOwner {
.raw_attrs(AttrOwner::ModItem(definition_tree_id.value.into()))
.clone(),
ModuleOrigin::BlockExpr { block } => RawAttrs::from_attrs_owner(
- db,
+ db.upcast(),
InFile::new(block.file_id, block.to_node(db.upcast()))
.as_ref()
.map(|it| it as &dyn ast::HasAttrs),
@@ -439,7 +314,7 @@ impl AttrsWithOwner {
GenericParamId::ConstParamId(it) => {
let src = it.parent().child_source(db);
RawAttrs::from_attrs_owner(
- db,
+ db.upcast(),
src.with_value(src.value[it.local_id()].as_ref().either(
|it| match it {
ast::TypeOrConstParam::Type(it) => it as _,
@@ -452,7 +327,7 @@ impl AttrsWithOwner {
GenericParamId::TypeParamId(it) => {
let src = it.parent().child_source(db);
RawAttrs::from_attrs_owner(
- db,
+ db.upcast(),
src.with_value(src.value[it.local_id()].as_ref().either(
|it| match it {
ast::TypeOrConstParam::Type(it) => it as _,
@@ -464,14 +339,14 @@ impl AttrsWithOwner {
}
GenericParamId::LifetimeParamId(it) => {
let src = it.parent.child_source(db);
- RawAttrs::from_attrs_owner(db, src.with_value(&src.value[it.local_id]))
+ RawAttrs::from_attrs_owner(db.upcast(), src.with_value(&src.value[it.local_id]))
}
},
AttrDefId::ExternBlockId(it) => attrs_from_item_tree(it.lookup(db).id, db),
};
- let attrs = raw_attrs.filter(db, def.krate(db));
- Self { attrs, owner: def }
+ let attrs = raw_attrs.filter(db.upcast(), def.krate(db));
+ Self { attrs: Attrs(attrs), owner: def }
}
pub fn source_map(&self, db: &dyn DefDatabase) -> AttrSourceMap {
@@ -627,40 +502,6 @@ fn doc_indent(attrs: &Attrs) -> usize {
.unwrap_or(0)
}
-fn inner_attributes(
- syntax: &SyntaxNode,
-) -> Option<impl Iterator<Item = Either<ast::Attr, ast::Comment>>> {
- let node = match_ast! {
- match syntax {
- ast::SourceFile(_) => syntax.clone(),
- ast::ExternBlock(it) => it.extern_item_list()?.syntax().clone(),
- ast::Fn(it) => it.body()?.stmt_list()?.syntax().clone(),
- ast::Impl(it) => it.assoc_item_list()?.syntax().clone(),
- ast::Module(it) => it.item_list()?.syntax().clone(),
- ast::BlockExpr(it) => {
- use syntax::SyntaxKind::{BLOCK_EXPR , EXPR_STMT};
- // Block expressions accept outer and inner attributes, but only when they are the outer
- // expression of an expression statement or the final expression of another block expression.
- let may_carry_attributes = matches!(
- it.syntax().parent().map(|it| it.kind()),
- Some(BLOCK_EXPR | EXPR_STMT)
- );
- if !may_carry_attributes {
- return None
- }
- syntax.clone()
- },
- _ => return None,
- }
- };
-
- let attrs = ast::AttrDocCommentIter::from_syntax_node(&node).filter(|el| match el {
- Either::Left(attr) => attr.kind().is_inner(),
- Either::Right(comment) => comment.is_inner(),
- });
- Some(attrs)
-}
-
#[derive(Debug)]
pub struct AttrSourceMap {
source: Vec<Either<ast::Attr, ast::Comment>>,
@@ -703,7 +544,7 @@ impl AttrSourceMap {
}
fn source_of_id(&self, id: AttrId) -> InFile<&Either<ast::Attr, ast::Comment>> {
- let ast_idx = id.ast_index as usize;
+ let ast_idx = id.ast_index();
let file_id = match self.mod_def_site_file_id {
Some((file_id, def_site_cut)) if def_site_cut <= ast_idx => file_id,
_ => self.file_id,
@@ -779,128 +620,6 @@ fn get_doc_string_in_attr(it: &ast::Attr) -> Option<ast::String> {
}
}
-#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
-pub struct AttrId {
- pub(crate) ast_index: u32,
-}
-
-#[derive(Debug, Clone, PartialEq, Eq)]
-pub struct Attr {
- pub(crate) id: AttrId,
- pub(crate) path: Interned<ModPath>,
- pub(crate) input: Option<Interned<AttrInput>>,
-}
-
-#[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub enum AttrInput {
- /// `#[attr = "string"]`
- Literal(SmolStr),
- /// `#[attr(subtree)]`
- TokenTree(tt::Subtree, mbe::TokenMap),
-}
-
-impl fmt::Display for AttrInput {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- match self {
- AttrInput::Literal(lit) => write!(f, " = \"{}\"", lit.escape_debug()),
- AttrInput::TokenTree(subtree, _) => subtree.fmt(f),
- }
- }
-}
-
-impl Attr {
- fn from_src(
- db: &dyn DefDatabase,
- ast: ast::Meta,
- hygiene: &Hygiene,
- id: AttrId,
- ) -> Option<Attr> {
- let path = Interned::new(ModPath::from_src(db.upcast(), ast.path()?, hygiene)?);
- let input = if let Some(ast::Expr::Literal(lit)) = ast.expr() {
- let value = match lit.kind() {
- ast::LiteralKind::String(string) => string.value()?.into(),
- _ => lit.syntax().first_token()?.text().trim_matches('"').into(),
- };
- Some(Interned::new(AttrInput::Literal(value)))
- } else if let Some(tt) = ast.token_tree() {
- let (tree, map) = syntax_node_to_token_tree(tt.syntax());
- Some(Interned::new(AttrInput::TokenTree(tree, map)))
- } else {
- None
- };
- Some(Attr { id, path, input })
- }
-
- fn from_tt(
- db: &dyn DefDatabase,
- tt: &tt::Subtree,
- hygiene: &Hygiene,
- id: AttrId,
- ) -> Option<Attr> {
- let (parse, _) = mbe::token_tree_to_syntax_node(tt, mbe::TopEntryPoint::MetaItem);
- let ast = ast::Meta::cast(parse.syntax_node())?;
-
- Self::from_src(db, ast, hygiene, id)
- }
-
- pub fn path(&self) -> &ModPath {
- &self.path
- }
-}
-
-impl Attr {
- /// #[path = "string"]
- pub fn string_value(&self) -> Option<&SmolStr> {
- match self.input.as_deref()? {
- AttrInput::Literal(it) => Some(it),
- _ => None,
- }
- }
-
- /// #[path(ident)]
- pub fn single_ident_value(&self) -> Option<&tt::Ident> {
- match self.input.as_deref()? {
- AttrInput::TokenTree(subtree, _) => match &*subtree.token_trees {
- [tt::TokenTree::Leaf(tt::Leaf::Ident(ident))] => Some(ident),
- _ => None,
- },
- _ => None,
- }
- }
-
- /// #[path TokenTree]
- pub fn token_tree_value(&self) -> Option<&Subtree> {
- match self.input.as_deref()? {
- AttrInput::TokenTree(subtree, _) => Some(subtree),
- _ => None,
- }
- }
-
- /// Parses this attribute as a token tree consisting of comma separated paths.
- pub fn parse_path_comma_token_tree(&self) -> Option<impl Iterator<Item = ModPath> + '_> {
- let args = self.token_tree_value()?;
-
- if args.delimiter_kind() != Some(DelimiterKind::Parenthesis) {
- return None;
- }
- let paths = args
- .token_trees
- .split(|tt| matches!(tt, tt::TokenTree::Leaf(tt::Leaf::Punct(Punct { char: ',', .. }))))
- .filter_map(|tts| {
- if tts.is_empty() {
- return None;
- }
- let segments = tts.iter().filter_map(|tt| match tt {
- tt::TokenTree::Leaf(tt::Leaf::Ident(id)) => Some(id.as_name()),
- _ => None,
- });
- Some(ModPath::from_segments(PathKind::Plain, segments))
- });
-
- Some(paths)
- }
-}
-
#[derive(Debug, Clone, Copy)]
pub struct AttrQuery<'attr> {
attrs: &'attr Attrs,
@@ -908,7 +627,7 @@ pub struct AttrQuery<'attr> {
}
impl<'attr> AttrQuery<'attr> {
- pub fn tt_values(self) -> impl Iterator<Item = &'attr Subtree> {
+ pub fn tt_values(self) -> impl Iterator<Item = &'attr crate::tt::Subtree> {
self.attrs().filter_map(|attr| attr.token_tree_value())
}
@@ -953,21 +672,6 @@ fn attrs_from_item_tree<N: ItemTreeNode>(id: ItemTreeId<N>, db: &dyn DefDatabase
tree.raw_attrs(mod_item.into()).clone()
}
-fn collect_attrs(
- owner: &dyn ast::HasAttrs,
-) -> impl Iterator<Item = (AttrId, Either<ast::Attr, ast::Comment>)> {
- let inner_attrs = inner_attributes(owner.syntax()).into_iter().flatten();
- let outer_attrs =
- ast::AttrDocCommentIter::from_syntax_node(owner.syntax()).filter(|el| match el {
- Either::Left(attr) => attr.kind().is_outer(),
- Either::Right(comment) => comment.is_outer(),
- });
- outer_attrs
- .chain(inner_attrs)
- .enumerate()
- .map(|(id, attr)| (AttrId { ast_index: id as u32 }, attr))
-}
-
pub(crate) fn variants_attrs_source_map(
db: &dyn DefDatabase,
def: EnumId,
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/body.rs b/src/tools/rust-analyzer/crates/hir-def/src/body.rs
index 78fbaa9d7..8fd9255b8 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/body.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/body.rs
@@ -12,15 +12,17 @@ use base_db::CrateId;
use cfg::{CfgExpr, CfgOptions};
use drop_bomb::DropBomb;
use either::Either;
-use hir_expand::{hygiene::Hygiene, ExpandError, ExpandResult, HirFileId, InFile, MacroCallId};
+use hir_expand::{
+ attrs::RawAttrs, hygiene::Hygiene, ExpandError, ExpandResult, HirFileId, InFile, MacroCallId,
+};
use la_arena::{Arena, ArenaMap};
use limit::Limit;
use profile::Count;
use rustc_hash::FxHashMap;
-use syntax::{ast, AstPtr, SyntaxNodePtr};
+use syntax::{ast, AstPtr, SyntaxNode, SyntaxNodePtr};
use crate::{
- attr::{Attrs, RawAttrs},
+ attr::Attrs,
db::DefDatabase,
expr::{dummy_expr_id, Expr, ExprId, Label, LabelId, Pat, PatId},
item_scope::BuiltinShadowMode,
@@ -49,7 +51,8 @@ pub struct Expander {
def_map: Arc<DefMap>,
current_file_id: HirFileId,
module: LocalModuleId,
- recursion_limit: usize,
+ /// `recursion_depth == usize::MAX` indicates that the recursion limit has been reached.
+ recursion_depth: usize,
}
impl CfgExpander {
@@ -64,7 +67,7 @@ impl CfgExpander {
}
pub(crate) fn parse_attrs(&self, db: &dyn DefDatabase, owner: &dyn ast::HasAttrs) -> Attrs {
- RawAttrs::new(db, owner, &self.hygiene).filter(db, self.krate)
+ Attrs::filter(db, self.krate, RawAttrs::new(db.upcast(), owner, &self.hygiene))
}
pub(crate) fn is_cfg_enabled(&self, db: &dyn DefDatabase, owner: &dyn ast::HasAttrs) -> bool {
@@ -82,7 +85,7 @@ impl Expander {
def_map,
current_file_id,
module: module.local_id,
- recursion_limit: 0,
+ recursion_depth: 0,
}
}
@@ -91,31 +94,37 @@ impl Expander {
db: &dyn DefDatabase,
macro_call: ast::MacroCall,
) -> Result<ExpandResult<Option<(Mark, T)>>, UnresolvedMacro> {
- if self.recursion_limit(db).check(self.recursion_limit + 1).is_err() {
- cov_mark::hit!(your_stack_belongs_to_me);
- return Ok(ExpandResult::only_err(ExpandError::Other(
- "reached recursion limit during macro expansion".into(),
- )));
+ let mut unresolved_macro_err = None;
+
+ let result = self.within_limit(db, |this| {
+ let macro_call = InFile::new(this.current_file_id, &macro_call);
+
+ let resolver =
+ |path| this.resolve_path_as_macro(db, &path).map(|it| macro_id_to_def_id(db, it));
+
+ let mut err = None;
+ let call_id = match macro_call.as_call_id_with_errors(
+ db,
+ this.def_map.krate(),
+ resolver,
+ &mut |e| {
+ err.get_or_insert(e);
+ },
+ ) {
+ Ok(call_id) => call_id,
+ Err(resolve_err) => {
+ unresolved_macro_err = Some(resolve_err);
+ return ExpandResult { value: None, err: None };
+ }
+ };
+ ExpandResult { value: call_id.ok(), err }
+ });
+
+ if let Some(err) = unresolved_macro_err {
+ Err(err)
+ } else {
+ Ok(result)
}
-
- let macro_call = InFile::new(self.current_file_id, &macro_call);
-
- let resolver =
- |path| self.resolve_path_as_macro(db, &path).map(|it| macro_id_to_def_id(db, it));
-
- let mut err = None;
- let call_id =
- macro_call.as_call_id_with_errors(db, self.def_map.krate(), resolver, &mut |e| {
- err.get_or_insert(e);
- })?;
- let call_id = match call_id {
- Ok(it) => it,
- Err(_) => {
- return Ok(ExpandResult { value: None, err });
- }
- };
-
- Ok(self.enter_expand_inner(db, call_id, err))
}
pub fn enter_expand_id<T: ast::AstNode>(
@@ -123,15 +132,14 @@ impl Expander {
db: &dyn DefDatabase,
call_id: MacroCallId,
) -> ExpandResult<Option<(Mark, T)>> {
- self.enter_expand_inner(db, call_id, None)
+ self.within_limit(db, |_this| ExpandResult::ok(Some(call_id)))
}
- fn enter_expand_inner<T: ast::AstNode>(
- &mut self,
+ fn enter_expand_inner(
db: &dyn DefDatabase,
call_id: MacroCallId,
mut err: Option<ExpandError>,
- ) -> ExpandResult<Option<(Mark, T)>> {
+ ) -> ExpandResult<Option<(HirFileId, SyntaxNode)>> {
if err.is_none() {
err = db.macro_expand_error(call_id);
}
@@ -152,29 +160,21 @@ impl Expander {
}
};
- let node = match T::cast(raw_node) {
- Some(it) => it,
- None => {
- // This can happen without being an error, so only forward previous errors.
- return ExpandResult { value: None, err };
- }
- };
-
- tracing::debug!("macro expansion {:#?}", node.syntax());
-
- self.recursion_limit += 1;
- let mark =
- Mark { file_id: self.current_file_id, bomb: DropBomb::new("expansion mark dropped") };
- self.cfg_expander.hygiene = Hygiene::new(db.upcast(), file_id);
- self.current_file_id = file_id;
-
- ExpandResult { value: Some((mark, node)), err }
+ ExpandResult { value: Some((file_id, raw_node)), err }
}
pub fn exit(&mut self, db: &dyn DefDatabase, mut mark: Mark) {
self.cfg_expander.hygiene = Hygiene::new(db.upcast(), mark.file_id);
self.current_file_id = mark.file_id;
- self.recursion_limit -= 1;
+ if self.recursion_depth == usize::MAX {
+ // Recursion limit has been reached somewhere in the macro expansion tree. Reset the
+ // depth only when we get out of the tree.
+ if !self.current_file_id.is_macro() {
+ self.recursion_depth = 0;
+ }
+ } else {
+ self.recursion_depth -= 1;
+ }
mark.bomb.defuse();
}
@@ -213,6 +213,50 @@ impl Expander {
#[cfg(test)]
return Limit::new(std::cmp::min(32, limit));
}
+
+ fn within_limit<F, T: ast::AstNode>(
+ &mut self,
+ db: &dyn DefDatabase,
+ op: F,
+ ) -> ExpandResult<Option<(Mark, T)>>
+ where
+ F: FnOnce(&mut Self) -> ExpandResult<Option<MacroCallId>>,
+ {
+ if self.recursion_depth == usize::MAX {
+ // Recursion limit has been reached somewhere in the macro expansion tree. We should
+ // stop expanding other macro calls in this tree, or else this may result in
+ // exponential number of macro expansions, leading to a hang.
+ //
+ // The overflow error should have been reported when it occurred (see the next branch),
+ // so don't return overflow error here to avoid diagnostics duplication.
+ cov_mark::hit!(overflow_but_not_me);
+ return ExpandResult::only_err(ExpandError::RecursionOverflowPosioned);
+ } else if self.recursion_limit(db).check(self.recursion_depth + 1).is_err() {
+ self.recursion_depth = usize::MAX;
+ cov_mark::hit!(your_stack_belongs_to_me);
+ return ExpandResult::only_err(ExpandError::Other(
+ "reached recursion limit during macro expansion".into(),
+ ));
+ }
+
+ let ExpandResult { value, err } = op(self);
+ let Some(call_id) = value else {
+ return ExpandResult { value: None, err };
+ };
+
+ Self::enter_expand_inner(db, call_id, err).map(|value| {
+ value.and_then(|(new_file_id, node)| {
+ let node = T::cast(node)?;
+
+ self.recursion_depth += 1;
+ self.cfg_expander.hygiene = Hygiene::new(db.upcast(), new_file_id);
+ let old_file_id = std::mem::replace(&mut self.current_file_id, new_file_id);
+ let mark =
+ Mark { file_id: old_file_id, bomb: DropBomb::new("expansion mark dropped") };
+ Some((mark, node))
+ })
+ })
+ }
}
#[derive(Debug)]
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/body/lower.rs b/src/tools/rust-analyzer/crates/hir-def/src/body/lower.rs
index e8da24e3a..04b1c4f01 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/body/lower.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/body/lower.rs
@@ -10,6 +10,7 @@ use hir_expand::{
name::{name, AsName, Name},
AstId, ExpandError, HirFileId, InFile,
};
+use intern::Interned;
use la_arena::Arena;
use once_cell::unsync::OnceCell;
use profile::Count;
@@ -33,7 +34,6 @@ use crate::{
Label, LabelId, Literal, MatchArm, Movability, Pat, PatId, RecordFieldPat, RecordLitField,
Statement,
},
- intern::Interned,
item_scope::BuiltinShadowMode,
path::{GenericArgs, Path},
type_ref::{Mutability, Rawness, TypeRef},
@@ -67,9 +67,9 @@ impl<'a> LowerCtx<'a> {
Path::from_src(ast, self)
}
- pub(crate) fn ast_id<N: AstNode>(&self, db: &dyn DefDatabase, item: &N) -> Option<AstId<N>> {
+ pub(crate) fn ast_id<N: AstNode>(&self, item: &N) -> Option<AstId<N>> {
let &(file_id, ref ast_id_map) = self.ast_id_map.as_ref()?;
- let ast_id_map = ast_id_map.get_or_init(|| db.ast_id_map(file_id));
+ let ast_id_map = ast_id_map.get_or_init(|| self.db.ast_id_map(file_id));
Some(InFile::new(file_id, ast_id_map.ast_id(item)))
}
}
@@ -624,6 +624,10 @@ impl ExprCollector<'_> {
krate: *krate,
});
}
+ Some(ExpandError::RecursionOverflowPosioned) => {
+ // Recursion limit has been reached in the macro expansion tree, but not in
+ // this very macro call. Don't add diagnostics to avoid duplication.
+ }
Some(err) => {
self.source_map.diagnostics.push(BodyDiagnostic::MacroError {
node: InFile::new(outer_file, syntax_ptr),
@@ -636,6 +640,8 @@ impl ExprCollector<'_> {
match res.value {
Some((mark, expansion)) => {
+ // Keep collecting even with expansion errors so we can provide completions and
+ // other services in incomplete macro expressions.
self.source_map.expansions.insert(macro_call_ptr, self.expander.current_file_id);
let prev_ast_id_map = mem::replace(
&mut self.ast_id_map,
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/body/pretty.rs b/src/tools/rust-analyzer/crates/hir-def/src/body/pretty.rs
index 10b9b26bb..4b4664a1c 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/body/pretty.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/body/pretty.rs
@@ -80,7 +80,7 @@ impl<'a> Write for Printer<'a> {
fn write_str(&mut self, s: &str) -> fmt::Result {
for line in s.split_inclusive('\n') {
if self.needs_indent {
- match self.buf.chars().rev().skip_while(|ch| *ch == ' ').next() {
+ match self.buf.chars().rev().find(|ch| *ch != ' ') {
Some('\n') | None => {}
_ => self.buf.push('\n'),
}
@@ -113,7 +113,7 @@ impl<'a> Printer<'a> {
}
fn newline(&mut self) {
- match self.buf.chars().rev().skip_while(|ch| *ch == ' ').next() {
+ match self.buf.chars().rev().find(|ch| *ch != ' ') {
Some('\n') | None => {}
_ => writeln!(self).unwrap(),
}
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/body/tests.rs b/src/tools/rust-analyzer/crates/hir-def/src/body/tests.rs
index c9601f855..edee2c7ff 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/body/tests.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/body/tests.rs
@@ -62,6 +62,19 @@ fn main() { n_nuple!(1,2,3); }
}
#[test]
+fn your_stack_belongs_to_me2() {
+ cov_mark::check!(overflow_but_not_me);
+ lower(
+ r#"
+macro_rules! foo {
+ () => {{ foo!(); foo!(); }}
+}
+fn main() { foo!(); }
+"#,
+ );
+}
+
+#[test]
fn recursion_limit() {
cov_mark::check!(your_stack_belongs_to_me);
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/child_by_source.rs b/src/tools/rust-analyzer/crates/hir-def/src/child_by_source.rs
index bb1316525..19d2fe956 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/child_by_source.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/child_by_source.rs
@@ -117,7 +117,7 @@ impl ChildBySource for ItemScope {
let adt = ast_id.to_node(db.upcast());
calls.for_each(|(attr_id, call_id, calls)| {
if let Some(Either::Left(attr)) =
- adt.doc_comments_and_attrs().nth(attr_id.ast_index as usize)
+ adt.doc_comments_and_attrs().nth(attr_id.ast_index())
{
res[keys::DERIVE_MACRO_CALL].insert(attr, (attr_id, call_id, calls.into()));
}
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/data.rs b/src/tools/rust-analyzer/crates/hir-def/src/data.rs
index e6b05f27a..c3c1dfd39 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/data.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/data.rs
@@ -3,6 +3,7 @@
use std::sync::Arc;
use hir_expand::{name::Name, AstId, ExpandResult, HirFileId, InFile, MacroCallId, MacroDefKind};
+use intern::Interned;
use smallvec::SmallVec;
use syntax::ast;
@@ -10,7 +11,6 @@ use crate::{
attr::Attrs,
body::{Expander, Mark},
db::DefDatabase,
- intern::Interned,
item_tree::{self, AssocItem, FnFlags, ItemTree, ItemTreeId, ModItem, Param, TreeId},
nameres::{
attr_resolution::ResolvedAttr,
@@ -142,7 +142,7 @@ impl FunctionData {
}
}
-fn parse_rustc_legacy_const_generics(tt: &tt::Subtree) -> Box<[u32]> {
+fn parse_rustc_legacy_const_generics(tt: &crate::tt::Subtree) -> Box<[u32]> {
let mut indices = Vec::new();
for args in tt.token_trees.chunks(2) {
match &args[0] {
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/db.rs b/src/tools/rust-analyzer/crates/hir-def/src/db.rs
index 431c82554..b23427a73 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/db.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/db.rs
@@ -4,8 +4,9 @@ use std::sync::Arc;
use base_db::{salsa, CrateId, SourceDatabase, Upcast};
use either::Either;
use hir_expand::{db::AstDatabase, HirFileId};
+use intern::Interned;
use la_arena::ArenaMap;
-use syntax::{ast, AstPtr, SmolStr};
+use syntax::{ast, AstPtr};
use crate::{
adt::{EnumData, StructData},
@@ -17,9 +18,8 @@ use crate::{
},
generics::GenericParams,
import_map::ImportMap,
- intern::Interned,
item_tree::{AttrOwner, ItemTree},
- lang_item::{LangItemTarget, LangItems},
+ lang_item::{LangItem, LangItemTarget, LangItems},
nameres::{diagnostics::DefDiagnostic, DefMap},
visibility::{self, Visibility},
AttrDefId, BlockId, BlockLoc, ConstId, ConstLoc, DefWithBodyId, EnumId, EnumLoc, ExternBlockId,
@@ -183,7 +183,7 @@ pub trait DefDatabase: InternDatabase + AstDatabase + Upcast<dyn AstDatabase> {
fn crate_lang_items(&self, krate: CrateId) -> Arc<LangItems>;
#[salsa::invoke(LangItems::lang_item_query)]
- fn lang_item(&self, start_crate: CrateId, item: SmolStr) -> Option<LangItemTarget>;
+ fn lang_item(&self, start_crate: CrateId, item: LangItem) -> Option<LangItemTarget>;
#[salsa::invoke(ImportMap::import_map_query)]
fn import_map(&self, krate: CrateId) -> Arc<ImportMap>;
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/expr.rs b/src/tools/rust-analyzer/crates/hir-def/src/expr.rs
index 7b6569421..48028b7c6 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/expr.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/expr.rs
@@ -15,11 +15,11 @@
use std::fmt;
use hir_expand::name::Name;
+use intern::Interned;
use la_arena::{Idx, RawIdx};
use crate::{
builtin_type::{BuiltinFloat, BuiltinInt, BuiltinUint},
- intern::Interned,
path::{GenericArgs, Path},
type_ref::{Mutability, Rawness, TypeRef},
BlockId,
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/find_path.rs b/src/tools/rust-analyzer/crates/hir-def/src/find_path.rs
index ddd7ad99e..3f4392320 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/find_path.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/find_path.rs
@@ -811,7 +811,7 @@ pub struct S;
fn prelude() {
check_found_path(
r#"
-//- /main.rs crate:main deps:std
+//- /main.rs edition:2018 crate:main deps:std
$0
//- /std.rs crate:std
pub mod prelude {
@@ -852,7 +852,7 @@ pub mod prelude {
fn imported_prelude() {
check_found_path(
r#"
-//- /main.rs crate:main deps:std
+//- /main.rs edition:2018 crate:main deps:std
use S;
$0
//- /std.rs crate:std
@@ -872,7 +872,7 @@ pub mod prelude {
#[test]
fn enum_variant_from_prelude() {
let code = r#"
-//- /main.rs crate:main deps:std
+//- /main.rs edition:2018 crate:main deps:std
$0
//- /std.rs crate:std
pub mod prelude {
@@ -1273,7 +1273,7 @@ fn f() {
fn prelude_with_inner_items() {
check_found_path(
r#"
-//- /main.rs crate:main deps:std
+//- /main.rs edition:2018 crate:main deps:std
fn f() {
fn inner() {}
$0
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/generics.rs b/src/tools/rust-analyzer/crates/hir-def/src/generics.rs
index f74559f5d..b2ab0c30e 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/generics.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/generics.rs
@@ -9,6 +9,7 @@ use hir_expand::{
name::{AsName, Name},
ExpandResult, HirFileId, InFile,
};
+use intern::Interned;
use la_arena::{Arena, ArenaMap, Idx};
use once_cell::unsync::Lazy;
use std::ops::DerefMut;
@@ -20,7 +21,6 @@ use crate::{
child_by_source::ChildBySource,
db::DefDatabase,
dyn_map::DynMap,
- intern::Interned,
keys,
src::{HasChildSource, HasSource},
type_ref::{LifetimeRef, TypeBound, TypeRef},
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/item_scope.rs b/src/tools/rust-analyzer/crates/hir-def/src/item_scope.rs
index c7b213b7e..53a4173ff 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/item_scope.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/item_scope.rs
@@ -4,7 +4,7 @@
use std::collections::hash_map::Entry;
use base_db::CrateId;
-use hir_expand::{name::Name, AstId, MacroCallId};
+use hir_expand::{attrs::AttrId, name::Name, AstId, MacroCallId};
use itertools::Itertools;
use once_cell::sync::Lazy;
use profile::Count;
@@ -14,8 +14,8 @@ use stdx::format_to;
use syntax::ast;
use crate::{
- attr::AttrId, db::DefDatabase, per_ns::PerNs, visibility::Visibility, AdtId, BuiltinType,
- ConstId, HasModule, ImplId, LocalModuleId, MacroId, ModuleDefId, ModuleId, TraitId,
+ db::DefDatabase, per_ns::PerNs, visibility::Visibility, AdtId, BuiltinType, ConstId, HasModule,
+ ImplId, LocalModuleId, MacroId, ModuleDefId, ModuleId, TraitId,
};
#[derive(Copy, Clone, Debug)]
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/item_tree.rs b/src/tools/rust-analyzer/crates/hir-def/src/item_tree.rs
index 80297f8ad..19d01630e 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/item_tree.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/item_tree.rs
@@ -48,10 +48,12 @@ use base_db::CrateId;
use either::Either;
use hir_expand::{
ast_id_map::FileAstId,
+ attrs::RawAttrs,
hygiene::Hygiene,
name::{name, AsName, Name},
ExpandTo, HirFileId, InFile,
};
+use intern::Interned;
use la_arena::{Arena, Idx, IdxRange, RawIdx};
use profile::Count;
use rustc_hash::FxHashMap;
@@ -60,10 +62,9 @@ use stdx::never;
use syntax::{ast, match_ast, SyntaxKind};
use crate::{
- attr::{Attrs, RawAttrs},
+ attr::Attrs,
db::DefDatabase,
generics::GenericParams,
- intern::Interned,
path::{path, AssociatedTypeBinding, GenericArgs, ImportAlias, ModPath, Path, PathKind},
type_ref::{Mutability, TraitRef, TypeBound, TypeRef},
visibility::RawVisibility,
@@ -110,7 +111,8 @@ impl ItemTree {
Some(node) => node,
None => return Default::default(),
};
- if never!(syntax.kind() == SyntaxKind::ERROR) {
+ if never!(syntax.kind() == SyntaxKind::ERROR, "{:?} from {:?} {}", file_id, syntax, syntax)
+ {
// FIXME: not 100% sure why these crop up, but return an empty tree to avoid a panic
return Default::default();
}
@@ -120,7 +122,7 @@ impl ItemTree {
let mut item_tree = match_ast! {
match syntax {
ast::SourceFile(file) => {
- top_attrs = Some(RawAttrs::new(db, &file, ctx.hygiene()));
+ top_attrs = Some(RawAttrs::new(db.upcast(), &file, ctx.hygiene()));
ctx.lower_module_items(&file)
},
ast::MacroItems(items) => {
@@ -132,7 +134,7 @@ impl ItemTree {
ctx.lower_macro_stmts(stmts)
},
_ => {
- panic!("cannot create item tree from {syntax:?} {syntax}");
+ panic!("cannot create item tree for file {file_id:?} from {syntax:?} {syntax}");
},
}
};
@@ -152,7 +154,11 @@ impl ItemTree {
/// Returns the inner attributes of the source file.
pub fn top_level_attrs(&self, db: &dyn DefDatabase, krate: CrateId) -> Attrs {
- self.attrs.get(&AttrOwner::TopLevel).unwrap_or(&RawAttrs::EMPTY).clone().filter(db, krate)
+ Attrs::filter(
+ db,
+ krate,
+ self.attrs.get(&AttrOwner::TopLevel).unwrap_or(&RawAttrs::EMPTY).clone(),
+ )
}
pub(crate) fn raw_attrs(&self, of: AttrOwner) -> &RawAttrs {
@@ -160,7 +166,7 @@ impl ItemTree {
}
pub(crate) fn attrs(&self, db: &dyn DefDatabase, krate: CrateId, of: AttrOwner) -> Attrs {
- self.raw_attrs(of).clone().filter(db, krate)
+ Attrs::filter(db, krate, self.raw_attrs(of).clone())
}
pub fn pretty_print(&self) -> String {
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/item_tree/lower.rs b/src/tools/rust-analyzer/crates/hir-def/src/item_tree/lower.rs
index b25274bcc..d4d3c5ef1 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/item_tree/lower.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/item_tree/lower.rs
@@ -99,7 +99,7 @@ impl<'a> Ctx<'a> {
}
fn lower_mod_item(&mut self, item: &ast::Item) -> Option<ModItem> {
- let attrs = RawAttrs::new(self.db, item, self.hygiene());
+ let attrs = RawAttrs::new(self.db.upcast(), item, self.hygiene());
let item: ModItem = match item {
ast::Item::Struct(ast) => self.lower_struct(ast)?.into(),
ast::Item::Union(ast) => self.lower_union(ast)?.into(),
@@ -173,7 +173,7 @@ impl<'a> Ctx<'a> {
for field in fields.fields() {
if let Some(data) = self.lower_record_field(&field) {
let idx = self.data().fields.alloc(data);
- self.add_attrs(idx.into(), RawAttrs::new(self.db, &field, self.hygiene()));
+ self.add_attrs(idx.into(), RawAttrs::new(self.db.upcast(), &field, self.hygiene()));
}
}
let end = self.next_field_idx();
@@ -194,7 +194,7 @@ impl<'a> Ctx<'a> {
for (i, field) in fields.fields().enumerate() {
let data = self.lower_tuple_field(i, &field);
let idx = self.data().fields.alloc(data);
- self.add_attrs(idx.into(), RawAttrs::new(self.db, &field, self.hygiene()));
+ self.add_attrs(idx.into(), RawAttrs::new(self.db.upcast(), &field, self.hygiene()));
}
let end = self.next_field_idx();
IdxRange::new(start..end)
@@ -239,7 +239,10 @@ impl<'a> Ctx<'a> {
for variant in variants.variants() {
if let Some(data) = self.lower_variant(&variant) {
let idx = self.data().variants.alloc(data);
- self.add_attrs(idx.into(), RawAttrs::new(self.db, &variant, self.hygiene()));
+ self.add_attrs(
+ idx.into(),
+ RawAttrs::new(self.db.upcast(), &variant, self.hygiene()),
+ );
}
}
let end = self.next_variant_idx();
@@ -283,7 +286,10 @@ impl<'a> Ctx<'a> {
};
let ty = Interned::new(self_type);
let idx = self.data().params.alloc(Param::Normal(None, ty));
- self.add_attrs(idx.into(), RawAttrs::new(self.db, &self_param, self.hygiene()));
+ self.add_attrs(
+ idx.into(),
+ RawAttrs::new(self.db.upcast(), &self_param, self.hygiene()),
+ );
has_self_param = true;
}
for param in param_list.params() {
@@ -307,7 +313,7 @@ impl<'a> Ctx<'a> {
self.data().params.alloc(Param::Normal(name, ty))
}
};
- self.add_attrs(idx.into(), RawAttrs::new(self.db, &param, self.hygiene()));
+ self.add_attrs(idx.into(), RawAttrs::new(self.db.upcast(), &param, self.hygiene()));
}
}
let end_param = self.next_param_idx();
@@ -442,7 +448,7 @@ impl<'a> Ctx<'a> {
let items = trait_def.assoc_item_list().map(|list| {
list.assoc_items()
.filter_map(|item| {
- let attrs = RawAttrs::new(self.db, &item, self.hygiene());
+ let attrs = RawAttrs::new(self.db.upcast(), &item, self.hygiene());
self.lower_assoc_item(&item).map(|item| {
self.add_attrs(ModItem::from(item).into(), attrs);
item
@@ -471,7 +477,7 @@ impl<'a> Ctx<'a> {
.flat_map(|it| it.assoc_items())
.filter_map(|item| {
let assoc = self.lower_assoc_item(&item)?;
- let attrs = RawAttrs::new(self.db, &item, self.hygiene());
+ let attrs = RawAttrs::new(self.db.upcast(), &item, self.hygiene());
self.add_attrs(ModItem::from(assoc).into(), attrs);
Some(assoc)
})
@@ -541,7 +547,7 @@ impl<'a> Ctx<'a> {
// (in other words, the knowledge that they're in an extern block must not be used).
// This is because an extern block can contain macros whose ItemTree's top-level items
// should be considered to be in an extern block too.
- let attrs = RawAttrs::new(self.db, &item, self.hygiene());
+ let attrs = RawAttrs::new(self.db.upcast(), &item, self.hygiene());
let id: ModItem = match item {
ast::ExternItem::Fn(ast) => self.lower_function(&ast)?.into(),
ast::ExternItem::Static(ast) => self.lower_static(&ast)?.into(),
@@ -653,15 +659,16 @@ fn desugar_future_path(orig: TypeRef) -> Path {
let path = path![core::future::Future];
let mut generic_args: Vec<_> =
std::iter::repeat(None).take(path.segments().len() - 1).collect();
- let mut last = GenericArgs::empty();
let binding = AssociatedTypeBinding {
name: name![Output],
args: None,
type_ref: Some(orig),
- bounds: Vec::new(),
+ bounds: Box::default(),
};
- last.bindings.push(binding);
- generic_args.push(Some(Interned::new(last)));
+ generic_args.push(Some(Interned::new(GenericArgs {
+ bindings: Box::new([binding]),
+ ..GenericArgs::empty()
+ })));
Path::from_known_path(path, generic_args)
}
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/item_tree/pretty.rs b/src/tools/rust-analyzer/crates/hir-def/src/item_tree/pretty.rs
index 48c40df22..8f230b87d 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/item_tree/pretty.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/item_tree/pretty.rs
@@ -3,7 +3,6 @@
use std::fmt::{self, Write};
use crate::{
- attr::RawAttrs,
generics::{TypeOrConstParamData, WherePredicate, WherePredicateTypeTarget},
pretty::{print_path, print_type_bounds, print_type_ref},
visibility::RawVisibility,
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/keys.rs b/src/tools/rust-analyzer/crates/hir-def/src/keys.rs
index c5cb9a2af..72beec818 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/keys.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/keys.rs
@@ -2,12 +2,11 @@
use std::marker::PhantomData;
-use hir_expand::MacroCallId;
+use hir_expand::{attrs::AttrId, MacroCallId};
use rustc_hash::FxHashMap;
use syntax::{ast, AstNode, AstPtr};
use crate::{
- attr::AttrId,
dyn_map::{DynMap, Policy},
ConstId, EnumId, EnumVariantId, FieldId, FunctionId, ImplId, LifetimeParamId, Macro2Id,
MacroRulesId, ProcMacroId, StaticId, StructId, TraitId, TypeAliasId, TypeOrConstParamId,
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/lang_item.rs b/src/tools/rust-analyzer/crates/hir-def/src/lang_item.rs
index 877850184..ab9bc615d 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/lang_item.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/lang_item.rs
@@ -8,19 +8,21 @@ use rustc_hash::FxHashMap;
use syntax::SmolStr;
use crate::{
- db::DefDatabase, AdtId, AttrDefId, CrateId, EnumId, EnumVariantId, FunctionId, ImplId,
- ModuleDefId, StaticId, StructId, TraitId,
+ db::DefDatabase, AdtId, AssocItemId, AttrDefId, CrateId, EnumId, EnumVariantId, FunctionId,
+ ImplId, ModuleDefId, StaticId, StructId, TraitId, TypeAliasId, UnionId,
};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum LangItemTarget {
EnumId(EnumId),
- FunctionId(FunctionId),
- ImplDefId(ImplId),
- StaticId(StaticId),
- StructId(StructId),
- TraitId(TraitId),
- EnumVariantId(EnumVariantId),
+ Function(FunctionId),
+ ImplDef(ImplId),
+ Static(StaticId),
+ Struct(StructId),
+ Union(UnionId),
+ TypeAlias(TypeAliasId),
+ Trait(TraitId),
+ EnumVariant(EnumVariantId),
}
impl LangItemTarget {
@@ -33,42 +35,42 @@ impl LangItemTarget {
pub fn as_function(self) -> Option<FunctionId> {
match self {
- LangItemTarget::FunctionId(id) => Some(id),
+ LangItemTarget::Function(id) => Some(id),
_ => None,
}
}
pub fn as_impl_def(self) -> Option<ImplId> {
match self {
- LangItemTarget::ImplDefId(id) => Some(id),
+ LangItemTarget::ImplDef(id) => Some(id),
_ => None,
}
}
pub fn as_static(self) -> Option<StaticId> {
match self {
- LangItemTarget::StaticId(id) => Some(id),
+ LangItemTarget::Static(id) => Some(id),
_ => None,
}
}
pub fn as_struct(self) -> Option<StructId> {
match self {
- LangItemTarget::StructId(id) => Some(id),
+ LangItemTarget::Struct(id) => Some(id),
_ => None,
}
}
pub fn as_trait(self) -> Option<TraitId> {
match self {
- LangItemTarget::TraitId(id) => Some(id),
+ LangItemTarget::Trait(id) => Some(id),
_ => None,
}
}
pub fn as_enum_variant(self) -> Option<EnumVariantId> {
match self {
- LangItemTarget::EnumVariantId(id) => Some(id),
+ LangItemTarget::EnumVariant(id) => Some(id),
_ => None,
}
}
@@ -76,12 +78,12 @@ impl LangItemTarget {
#[derive(Default, Debug, Clone, PartialEq, Eq)]
pub struct LangItems {
- items: FxHashMap<SmolStr, LangItemTarget>,
+ items: FxHashMap<LangItem, LangItemTarget>,
}
impl LangItems {
- pub fn target(&self, item: &str) -> Option<LangItemTarget> {
- self.items.get(item).copied()
+ pub fn target(&self, item: LangItem) -> Option<LangItemTarget> {
+ self.items.get(&item).copied()
}
/// Salsa query. This will look for lang items in a specific crate.
@@ -94,16 +96,27 @@ impl LangItems {
for (_, module_data) in crate_def_map.modules() {
for impl_def in module_data.scope.impls() {
- lang_items.collect_lang_item(db, impl_def, LangItemTarget::ImplDefId)
+ lang_items.collect_lang_item(db, impl_def, LangItemTarget::ImplDef);
+ for assoc in db.impl_data(impl_def).items.iter().copied() {
+ match assoc {
+ AssocItemId::FunctionId(f) => {
+ lang_items.collect_lang_item(db, f, LangItemTarget::Function)
+ }
+ AssocItemId::TypeAliasId(t) => {
+ lang_items.collect_lang_item(db, t, LangItemTarget::TypeAlias)
+ }
+ AssocItemId::ConstId(_) => (),
+ }
+ }
}
for def in module_data.scope.declarations() {
match def {
ModuleDefId::TraitId(trait_) => {
- lang_items.collect_lang_item(db, trait_, LangItemTarget::TraitId);
+ lang_items.collect_lang_item(db, trait_, LangItemTarget::Trait);
db.trait_data(trait_).items.iter().for_each(|&(_, assoc_id)| {
- if let crate::AssocItemId::FunctionId(f) = assoc_id {
- lang_items.collect_lang_item(db, f, LangItemTarget::FunctionId);
+ if let AssocItemId::FunctionId(f) = assoc_id {
+ lang_items.collect_lang_item(db, f, LangItemTarget::Function);
}
});
}
@@ -113,18 +126,24 @@ impl LangItems {
lang_items.collect_lang_item(
db,
EnumVariantId { parent: e, local_id },
- LangItemTarget::EnumVariantId,
+ LangItemTarget::EnumVariant,
);
});
}
ModuleDefId::AdtId(AdtId::StructId(s)) => {
- lang_items.collect_lang_item(db, s, LangItemTarget::StructId);
+ lang_items.collect_lang_item(db, s, LangItemTarget::Struct);
+ }
+ ModuleDefId::AdtId(AdtId::UnionId(u)) => {
+ lang_items.collect_lang_item(db, u, LangItemTarget::Union);
}
ModuleDefId::FunctionId(f) => {
- lang_items.collect_lang_item(db, f, LangItemTarget::FunctionId);
+ lang_items.collect_lang_item(db, f, LangItemTarget::Function);
}
ModuleDefId::StaticId(s) => {
- lang_items.collect_lang_item(db, s, LangItemTarget::StaticId);
+ lang_items.collect_lang_item(db, s, LangItemTarget::Static);
+ }
+ ModuleDefId::TypeAliasId(t) => {
+ lang_items.collect_lang_item(db, t, LangItemTarget::TypeAlias);
}
_ => {}
}
@@ -139,7 +158,7 @@ impl LangItems {
pub(crate) fn lang_item_query(
db: &dyn DefDatabase,
start_crate: CrateId,
- item: SmolStr,
+ item: LangItem,
) -> Option<LangItemTarget> {
let _p = profile::span("lang_item_query");
let lang_items = db.crate_lang_items(start_crate);
@@ -150,7 +169,7 @@ impl LangItems {
db.crate_graph()[start_crate]
.dependencies
.iter()
- .find_map(|dep| db.lang_item(dep.crate_id, item.clone()))
+ .find_map(|dep| db.lang_item(dep.crate_id, item))
}
fn collect_lang_item<T>(
@@ -162,8 +181,8 @@ impl LangItems {
T: Into<AttrDefId> + Copy,
{
let _p = profile::span("collect_lang_item");
- if let Some(lang_item_name) = lang_attr(db, item) {
- self.items.entry(lang_item_name).or_insert_with(|| constructor(item));
+ if let Some(lang_item) = lang_attr(db, item).and_then(|it| LangItem::from_str(&it)) {
+ self.items.entry(lang_item).or_insert_with(|| constructor(item));
}
}
}
@@ -172,3 +191,224 @@ pub fn lang_attr(db: &dyn DefDatabase, item: impl Into<AttrDefId> + Copy) -> Opt
let attrs = db.attrs(item.into());
attrs.by_key("lang").string_value().cloned()
}
+
+pub enum GenericRequirement {
+ None,
+ Minimum(usize),
+ Exact(usize),
+}
+
+macro_rules! language_item_table {
+ (
+ $( $(#[$attr:meta])* $variant:ident, $name:ident, $method:ident, $target:expr, $generics:expr; )*
+ ) => {
+
+ /// A representation of all the valid language items in Rust.
+ #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
+ pub enum LangItem {
+ $(
+ #[doc = concat!("The `", stringify!($name), "` lang item.")]
+ $(#[$attr])*
+ $variant,
+ )*
+ }
+
+ impl LangItem {
+ pub fn name(self) -> SmolStr {
+ match self {
+ $( LangItem::$variant => SmolStr::new(stringify!($name)), )*
+ }
+ }
+
+ /// Opposite of [`LangItem::name`]
+ pub fn from_name(name: &hir_expand::name::Name) -> Option<Self> {
+ Self::from_str(name.as_str()?)
+ }
+
+ /// Opposite of [`LangItem::name`]
+ pub fn from_str(name: &str) -> Option<Self> {
+ match name {
+ $( stringify!($name) => Some(LangItem::$variant), )*
+ _ => None,
+ }
+ }
+ }
+ }
+}
+
+language_item_table! {
+// Variant name, Name, Getter method name, Target Generic requirements;
+ Sized, sized, sized_trait, Target::Trait, GenericRequirement::Exact(0);
+ Unsize, unsize, unsize_trait, Target::Trait, GenericRequirement::Minimum(1);
+ /// Trait injected by `#[derive(PartialEq)]`, (i.e. "Partial EQ").
+ StructuralPeq, structural_peq, structural_peq_trait, Target::Trait, GenericRequirement::None;
+ /// Trait injected by `#[derive(Eq)]`, (i.e. "Total EQ"; no, I will not apologize).
+ StructuralTeq, structural_teq, structural_teq_trait, Target::Trait, GenericRequirement::None;
+ Copy, copy, copy_trait, Target::Trait, GenericRequirement::Exact(0);
+ Clone, clone, clone_trait, Target::Trait, GenericRequirement::None;
+ Sync, sync, sync_trait, Target::Trait, GenericRequirement::Exact(0);
+ DiscriminantKind, discriminant_kind, discriminant_kind_trait, Target::Trait, GenericRequirement::None;
+ /// The associated item of the [`DiscriminantKind`] trait.
+ Discriminant, discriminant_type, discriminant_type, Target::AssocTy, GenericRequirement::None;
+
+ PointeeTrait, pointee_trait, pointee_trait, Target::Trait, GenericRequirement::None;
+ Metadata, metadata_type, metadata_type, Target::AssocTy, GenericRequirement::None;
+ DynMetadata, dyn_metadata, dyn_metadata, Target::Struct, GenericRequirement::None;
+
+ Freeze, freeze, freeze_trait, Target::Trait, GenericRequirement::Exact(0);
+
+ Drop, drop, drop_trait, Target::Trait, GenericRequirement::None;
+ Destruct, destruct, destruct_trait, Target::Trait, GenericRequirement::None;
+
+ CoerceUnsized, coerce_unsized, coerce_unsized_trait, Target::Trait, GenericRequirement::Minimum(1);
+ DispatchFromDyn, dispatch_from_dyn, dispatch_from_dyn_trait, Target::Trait, GenericRequirement::Minimum(1);
+
+ // language items relating to transmutability
+ TransmuteOpts, transmute_opts, transmute_opts, Target::Struct, GenericRequirement::Exact(0);
+ TransmuteTrait, transmute_trait, transmute_trait, Target::Trait, GenericRequirement::Exact(3);
+
+ Add, add, add_trait, Target::Trait, GenericRequirement::Exact(1);
+ Sub, sub, sub_trait, Target::Trait, GenericRequirement::Exact(1);
+ Mul, mul, mul_trait, Target::Trait, GenericRequirement::Exact(1);
+ Div, div, div_trait, Target::Trait, GenericRequirement::Exact(1);
+ Rem, rem, rem_trait, Target::Trait, GenericRequirement::Exact(1);
+ Neg, neg, neg_trait, Target::Trait, GenericRequirement::Exact(0);
+ Not, not, not_trait, Target::Trait, GenericRequirement::Exact(0);
+ BitXor, bitxor, bitxor_trait, Target::Trait, GenericRequirement::Exact(1);
+ BitAnd, bitand, bitand_trait, Target::Trait, GenericRequirement::Exact(1);
+ BitOr, bitor, bitor_trait, Target::Trait, GenericRequirement::Exact(1);
+ Shl, shl, shl_trait, Target::Trait, GenericRequirement::Exact(1);
+ Shr, shr, shr_trait, Target::Trait, GenericRequirement::Exact(1);
+ AddAssign, add_assign, add_assign_trait, Target::Trait, GenericRequirement::Exact(1);
+ SubAssign, sub_assign, sub_assign_trait, Target::Trait, GenericRequirement::Exact(1);
+ MulAssign, mul_assign, mul_assign_trait, Target::Trait, GenericRequirement::Exact(1);
+ DivAssign, div_assign, div_assign_trait, Target::Trait, GenericRequirement::Exact(1);
+ RemAssign, rem_assign, rem_assign_trait, Target::Trait, GenericRequirement::Exact(1);
+ BitXorAssign, bitxor_assign, bitxor_assign_trait, Target::Trait, GenericRequirement::Exact(1);
+ BitAndAssign, bitand_assign, bitand_assign_trait, Target::Trait, GenericRequirement::Exact(1);
+ BitOrAssign, bitor_assign, bitor_assign_trait, Target::Trait, GenericRequirement::Exact(1);
+ ShlAssign, shl_assign, shl_assign_trait, Target::Trait, GenericRequirement::Exact(1);
+ ShrAssign, shr_assign, shr_assign_trait, Target::Trait, GenericRequirement::Exact(1);
+ Index, index, index_trait, Target::Trait, GenericRequirement::Exact(1);
+ IndexMut, index_mut, index_mut_trait, Target::Trait, GenericRequirement::Exact(1);
+
+ UnsafeCell, unsafe_cell, unsafe_cell_type, Target::Struct, GenericRequirement::None;
+ VaList, va_list, va_list, Target::Struct, GenericRequirement::None;
+
+ Deref, deref, deref_trait, Target::Trait, GenericRequirement::Exact(0);
+ DerefMut, deref_mut, deref_mut_trait, Target::Trait, GenericRequirement::Exact(0);
+ DerefTarget, deref_target, deref_target, Target::AssocTy, GenericRequirement::None;
+ Receiver, receiver, receiver_trait, Target::Trait, GenericRequirement::None;
+
+ Fn, fn, fn_trait, Target::Trait, GenericRequirement::Exact(1);
+ FnMut, fn_mut, fn_mut_trait, Target::Trait, GenericRequirement::Exact(1);
+ FnOnce, fn_once, fn_once_trait, Target::Trait, GenericRequirement::Exact(1);
+
+ FnOnceOutput, fn_once_output, fn_once_output, Target::AssocTy, GenericRequirement::None;
+
+ Future, future_trait, future_trait, Target::Trait, GenericRequirement::Exact(0);
+ GeneratorState, generator_state, gen_state, Target::Enum, GenericRequirement::None;
+ Generator, generator, gen_trait, Target::Trait, GenericRequirement::Minimum(1);
+ Unpin, unpin, unpin_trait, Target::Trait, GenericRequirement::None;
+ Pin, pin, pin_type, Target::Struct, GenericRequirement::None;
+
+ PartialEq, eq, eq_trait, Target::Trait, GenericRequirement::Exact(1);
+ PartialOrd, partial_ord, partial_ord_trait, Target::Trait, GenericRequirement::Exact(1);
+
+ // A number of panic-related lang items. The `panic` item corresponds to divide-by-zero and
+ // various panic cases with `match`. The `panic_bounds_check` item is for indexing arrays.
+ //
+ // The `begin_unwind` lang item has a predefined symbol name and is sort of a "weak lang item"
+ // in the sense that a crate is not required to have it defined to use it, but a final product
+ // is required to define it somewhere. Additionally, there are restrictions on crates that use
+ // a weak lang item, but do not have it defined.
+ Panic, panic, panic_fn, Target::Fn, GenericRequirement::Exact(0);
+ PanicNounwind, panic_nounwind, panic_nounwind, Target::Fn, GenericRequirement::Exact(0);
+ PanicFmt, panic_fmt, panic_fmt, Target::Fn, GenericRequirement::None;
+ PanicDisplay, panic_display, panic_display, Target::Fn, GenericRequirement::None;
+ ConstPanicFmt, const_panic_fmt, const_panic_fmt, Target::Fn, GenericRequirement::None;
+ PanicBoundsCheck, panic_bounds_check, panic_bounds_check_fn, Target::Fn, GenericRequirement::Exact(0);
+ PanicInfo, panic_info, panic_info, Target::Struct, GenericRequirement::None;
+ PanicLocation, panic_location, panic_location, Target::Struct, GenericRequirement::None;
+ PanicImpl, panic_impl, panic_impl, Target::Fn, GenericRequirement::None;
+ PanicCannotUnwind, panic_cannot_unwind, panic_cannot_unwind, Target::Fn, GenericRequirement::Exact(0);
+ /// libstd panic entry point. Necessary for const eval to be able to catch it
+ BeginPanic, begin_panic, begin_panic_fn, Target::Fn, GenericRequirement::None;
+
+ ExchangeMalloc, exchange_malloc, exchange_malloc_fn, Target::Fn, GenericRequirement::None;
+ BoxFree, box_free, box_free_fn, Target::Fn, GenericRequirement::Minimum(1);
+ DropInPlace, drop_in_place, drop_in_place_fn, Target::Fn, GenericRequirement::Minimum(1);
+ AllocLayout, alloc_layout, alloc_layout, Target::Struct, GenericRequirement::None;
+
+ Start, start, start_fn, Target::Fn, GenericRequirement::Exact(1);
+
+ EhPersonality, eh_personality, eh_personality, Target::Fn, GenericRequirement::None;
+ EhCatchTypeinfo, eh_catch_typeinfo, eh_catch_typeinfo, Target::Static, GenericRequirement::None;
+
+ OwnedBox, owned_box, owned_box, Target::Struct, GenericRequirement::Minimum(1);
+
+ PhantomData, phantom_data, phantom_data, Target::Struct, GenericRequirement::Exact(1);
+
+ ManuallyDrop, manually_drop, manually_drop, Target::Struct, GenericRequirement::None;
+
+ MaybeUninit, maybe_uninit, maybe_uninit, Target::Union, GenericRequirement::None;
+
+ /// Align offset for stride != 1; must not panic.
+ AlignOffset, align_offset, align_offset_fn, Target::Fn, GenericRequirement::None;
+
+ Termination, termination, termination, Target::Trait, GenericRequirement::None;
+
+ Try, Try, try_trait, Target::Trait, GenericRequirement::None;
+
+ Tuple, tuple_trait, tuple_trait, Target::Trait, GenericRequirement::Exact(0);
+
+ SliceLen, slice_len_fn, slice_len_fn, Target::Method(MethodKind::Inherent), GenericRequirement::None;
+
+ // Language items from AST lowering
+ TryTraitFromResidual, from_residual, from_residual_fn, Target::Method(MethodKind::Trait { body: false }), GenericRequirement::None;
+ TryTraitFromOutput, from_output, from_output_fn, Target::Method(MethodKind::Trait { body: false }), GenericRequirement::None;
+ TryTraitBranch, branch, branch_fn, Target::Method(MethodKind::Trait { body: false }), GenericRequirement::None;
+ TryTraitFromYeet, from_yeet, from_yeet_fn, Target::Fn, GenericRequirement::None;
+
+ PointerSized, pointer_sized, pointer_sized, Target::Trait, GenericRequirement::Exact(0);
+
+ Poll, Poll, poll, Target::Enum, GenericRequirement::None;
+ PollReady, Ready, poll_ready_variant, Target::Variant, GenericRequirement::None;
+ PollPending, Pending, poll_pending_variant, Target::Variant, GenericRequirement::None;
+
+ // FIXME(swatinem): the following lang items are used for async lowering and
+ // should become obsolete eventually.
+ ResumeTy, ResumeTy, resume_ty, Target::Struct, GenericRequirement::None;
+ IdentityFuture, identity_future, identity_future_fn, Target::Fn, GenericRequirement::None;
+ GetContext, get_context, get_context_fn, Target::Fn, GenericRequirement::None;
+
+ Context, Context, context, Target::Struct, GenericRequirement::None;
+ FuturePoll, poll, future_poll_fn, Target::Method(MethodKind::Trait { body: false }), GenericRequirement::None;
+
+ FromFrom, from, from_fn, Target::Method(MethodKind::Trait { body: false }), GenericRequirement::None;
+
+ OptionSome, Some, option_some_variant, Target::Variant, GenericRequirement::None;
+ OptionNone, None, option_none_variant, Target::Variant, GenericRequirement::None;
+
+ ResultOk, Ok, result_ok_variant, Target::Variant, GenericRequirement::None;
+ ResultErr, Err, result_err_variant, Target::Variant, GenericRequirement::None;
+
+ ControlFlowContinue, Continue, cf_continue_variant, Target::Variant, GenericRequirement::None;
+ ControlFlowBreak, Break, cf_break_variant, Target::Variant, GenericRequirement::None;
+
+ IntoFutureIntoFuture, into_future, into_future_fn, Target::Method(MethodKind::Trait { body: false }), GenericRequirement::None;
+ IntoIterIntoIter, into_iter, into_iter_fn, Target::Method(MethodKind::Trait { body: false }), GenericRequirement::None;
+ IteratorNext, next, next_fn, Target::Method(MethodKind::Trait { body: false}), GenericRequirement::None;
+
+ PinNewUnchecked, new_unchecked, new_unchecked_fn, Target::Method(MethodKind::Inherent), GenericRequirement::None;
+
+ RangeFrom, RangeFrom, range_from_struct, Target::Struct, GenericRequirement::None;
+ RangeFull, RangeFull, range_full_struct, Target::Struct, GenericRequirement::None;
+ RangeInclusiveStruct, RangeInclusive, range_inclusive_struct, Target::Struct, GenericRequirement::None;
+ RangeInclusiveNew, range_inclusive_new, range_inclusive_new_method, Target::Method(MethodKind::Inherent), GenericRequirement::None;
+ Range, Range, range_struct, Target::Struct, GenericRequirement::None;
+ RangeToInclusive, RangeToInclusive, range_to_inclusive_struct, Target::Struct, GenericRequirement::None;
+ RangeTo, RangeTo, range_to_struct, Target::Struct, GenericRequirement::None;
+
+ String, String, string, Target::Struct, GenericRequirement::None;
+}
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/layout.rs b/src/tools/rust-analyzer/crates/hir-def/src/layout.rs
index 6bb4cd94f..49b1190ad 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/layout.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/layout.rs
@@ -90,6 +90,7 @@ impl IntegerExt for Integer {
pub enum LayoutError {
UserError(String),
SizeOverflow,
+ TargetLayoutNotAvailable,
HasPlaceholder,
NotImplemented,
Unknown,
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/lib.rs b/src/tools/rust-analyzer/crates/hir-def/src/lib.rs
index 8267ef09c..d07c5fb67 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/lib.rs
@@ -28,7 +28,6 @@ pub mod dyn_map;
pub mod keys;
pub mod item_tree;
-pub mod intern;
pub mod adt;
pub mod data;
@@ -61,10 +60,10 @@ use std::{
sync::Arc,
};
-use attr::Attr;
use base_db::{impl_intern_key, salsa, CrateId, ProcMacroKind};
use hir_expand::{
ast_id_map::FileAstId,
+ attrs::{Attr, AttrId, AttrInput},
builtin_attr_macro::BuiltinAttrExpander,
builtin_derive_macro::BuiltinDeriveExpander,
builtin_fn_macro::{BuiltinFnLikeExpander, EagerExpander},
@@ -80,9 +79,10 @@ use nameres::DefMap;
use stdx::impl_from;
use syntax::ast;
+use ::tt::token_id as tt;
+
use crate::{
adt::VariantData,
- attr::AttrId,
builtin_type::BuiltinType,
item_tree::{
Const, Enum, Function, Impl, ItemTreeId, ItemTreeNode, MacroDef, MacroRules, ModItem,
@@ -292,6 +292,7 @@ pub struct Macro2Loc {
pub container: ModuleId,
pub id: ItemTreeId<MacroDef>,
pub expander: MacroExpander,
+ pub allow_internal_unsafe: bool,
}
impl_intern!(Macro2Id, Macro2Loc, intern_macro2, lookup_intern_macro2);
@@ -301,8 +302,9 @@ pub struct MacroRulesId(salsa::InternId);
pub struct MacroRulesLoc {
pub container: ModuleId,
pub id: ItemTreeId<MacroRules>,
- pub local_inner: bool,
pub expander: MacroExpander,
+ pub allow_internal_unsafe: bool,
+ pub local_inner: bool,
}
impl_intern!(MacroRulesId, MacroRulesLoc, intern_macro_rules, lookup_intern_macro_rules);
@@ -896,6 +898,7 @@ pub fn macro_id_to_def_id(db: &dyn db::DefDatabase, id: MacroId) -> MacroDefId {
}
},
local_inner: false,
+ allow_internal_unsafe: loc.allow_internal_unsafe,
}
}
MacroId::MacroRulesId(it) => {
@@ -920,6 +923,7 @@ pub fn macro_id_to_def_id(db: &dyn db::DefDatabase, id: MacroId) -> MacroDefId {
}
},
local_inner: loc.local_inner,
+ allow_internal_unsafe: loc.allow_internal_unsafe,
}
}
MacroId::ProcMacroId(it) => {
@@ -935,6 +939,7 @@ pub fn macro_id_to_def_id(db: &dyn db::DefDatabase, id: MacroId) -> MacroDefId {
InFile::new(loc.id.file_id(), makro.ast_id),
),
local_inner: false,
+ allow_internal_unsafe: false,
}
}
}
@@ -943,7 +948,7 @@ pub fn macro_id_to_def_id(db: &dyn db::DefDatabase, id: MacroId) -> MacroDefId {
fn derive_macro_as_call_id(
db: &dyn db::DefDatabase,
item_attr: &AstIdWithPath<ast::Adt>,
- derive_attr: AttrId,
+ derive_attr_index: AttrId,
derive_pos: u32,
krate: CrateId,
resolver: impl Fn(path::ModPath) -> Option<(MacroId, MacroDefId)>,
@@ -956,7 +961,7 @@ fn derive_macro_as_call_id(
MacroCallKind::Derive {
ast_id: item_attr.ast_id,
derive_index: derive_pos,
- derive_attr_index: derive_attr.ast_index,
+ derive_attr_index,
},
);
Ok((macro_id, def_id, call_id))
@@ -970,23 +975,33 @@ fn attr_macro_as_call_id(
def: MacroDefId,
is_derive: bool,
) -> MacroCallId {
- let mut arg = match macro_attr.input.as_deref() {
- Some(attr::AttrInput::TokenTree(tt, map)) => (tt.clone(), map.clone()),
- _ => Default::default(),
+ let arg = match macro_attr.input.as_deref() {
+ Some(AttrInput::TokenTree(tt, map)) => (
+ {
+ let mut tt = tt.clone();
+ tt.delimiter = tt::Delimiter::UNSPECIFIED;
+ tt
+ },
+ map.clone(),
+ ),
+ _ => (tt::Subtree::empty(), Default::default()),
};
- // The parentheses are always disposed here.
- arg.0.delimiter = None;
-
- let res = def.as_lazy_macro(
+ def.as_lazy_macro(
db.upcast(),
krate,
MacroCallKind::Attr {
ast_id: item_attr.ast_id,
attr_args: Arc::new(arg),
- invoc_attr_index: macro_attr.id.ast_index,
+ invoc_attr_index: macro_attr.id,
is_derive,
},
- );
- res
-}
+ )
+}
+intern::impl_internable!(
+ crate::type_ref::TypeRef,
+ crate::type_ref::TraitRef,
+ crate::type_ref::TypeBound,
+ crate::path::GenericArgs,
+ generics::GenericParams,
+);
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests.rs b/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests.rs
index 79c85d118..5ab90d92d 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests.rs
@@ -30,7 +30,7 @@ use syntax::{
SyntaxKind::{self, COMMENT, EOF, IDENT, LIFETIME_IDENT},
SyntaxNode, TextRange, T,
};
-use tt::{Subtree, TokenId};
+use tt::token_id::{Subtree, TokenId};
use crate::{
db::DefDatabase, macro_id_to_def_id, nameres::ModuleSource, resolver::HasResolver,
@@ -97,7 +97,9 @@ pub fn identity_when_valid(_attr: TokenStream, item: TokenStream) -> TokenStream
let ast_id = AstId::new(source.file_id, file_ast_id.upcast());
let kind = MacroDefKind::Declarative(ast_id);
- let macro_def = db.macro_def(MacroDefId { krate, kind, local_inner: false }).unwrap();
+ let macro_def = db
+ .macro_def(MacroDefId { krate, kind, local_inner: false, allow_internal_unsafe: false })
+ .unwrap();
if let TokenExpander::DeclarativeMacro { mac, def_site_token_map } = &*macro_def {
let tt = match &macro_ {
ast::Macro::MacroRules(mac) => mac.token_tree().unwrap(),
@@ -251,9 +253,9 @@ fn extract_id_ranges(ranges: &mut Vec<(TextRange, TokenId)>, map: &TokenMap, tre
tree.token_trees.iter().for_each(|tree| match tree {
tt::TokenTree::Leaf(leaf) => {
let id = match leaf {
- tt::Leaf::Literal(it) => it.id,
- tt::Leaf::Punct(it) => it.id,
- tt::Leaf::Ident(it) => it.id,
+ tt::Leaf::Literal(it) => it.span,
+ tt::Leaf::Punct(it) => it.span,
+ tt::Leaf::Ident(it) => it.span,
};
ranges.extend(map.ranges_by_token(id, SyntaxKind::ERROR).map(|range| (range, id)));
}
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/mbe.rs b/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/mbe.rs
index 2d5f2a692..7a3e8c3b0 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/mbe.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/mbe.rs
@@ -97,6 +97,41 @@ fn#19 main#20(#21)#21 {#22
"##]],
);
}
+#[test]
+fn float_field_acces_macro_input() {
+ check(
+ r#"
+macro_rules! foo {
+ ($expr:expr) => {
+ fn foo() {
+ $expr;
+ }
+ };
+}
+foo!(x .0.1);
+foo!(x .2. 3);
+foo!(x .4 .5);
+"#,
+ expect![[r#"
+macro_rules! foo {
+ ($expr:expr) => {
+ fn foo() {
+ $expr;
+ }
+ };
+}
+fn foo() {
+ (x.0.1);
+}
+fn foo() {
+ (x.2.3);
+}
+fn foo() {
+ (x.4.5);
+}
+"#]],
+ );
+}
#[test]
fn mbe_smoke_test() {
@@ -1441,7 +1476,7 @@ macro_rules! m {
/* parse error: expected identifier */
/* parse error: expected SEMICOLON */
/* parse error: expected SEMICOLON */
-/* parse error: expected expression */
+/* parse error: expected expression, item or let statement */
fn f() {
K::(C("0"));
}
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/mbe/regression.rs b/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/mbe/regression.rs
index d2505e7ca..8358a46f0 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/mbe/regression.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/mbe/regression.rs
@@ -830,8 +830,7 @@ macro_rules! rgb_color {
/* parse error: expected COMMA */
/* parse error: expected R_ANGLE */
/* parse error: expected SEMICOLON */
-/* parse error: expected SEMICOLON */
-/* parse error: expected expression */
+/* parse error: expected expression, item or let statement */
pub fn new() {
let _ = 0as u32<<(8+8);
}
@@ -848,21 +847,21 @@ pub fn new() {
// BLOCK_EXPR@10..31
// STMT_LIST@10..31
// L_CURLY@10..11 "{"
-// LET_STMT@11..27
+// LET_STMT@11..28
// LET_KW@11..14 "let"
// WILDCARD_PAT@14..15
// UNDERSCORE@14..15 "_"
// EQ@15..16 "="
-// CAST_EXPR@16..27
+// CAST_EXPR@16..28
// LITERAL@16..17
// INT_NUMBER@16..17 "0"
// AS_KW@17..19 "as"
-// PATH_TYPE@19..27
-// PATH@19..27
-// PATH_SEGMENT@19..27
+// PATH_TYPE@19..28
+// PATH@19..28
+// PATH_SEGMENT@19..28
// NAME_REF@19..22
// IDENT@19..22 "u32"
-// GENERIC_ARG_LIST@22..27
+// GENERIC_ARG_LIST@22..28
// L_ANGLE@22..23 "<"
// TYPE_ARG@23..27
// DYN_TRAIT_TYPE@23..27
@@ -877,9 +876,9 @@ pub fn new() {
// ERROR@25..26
// INT_NUMBER@25..26 "8"
// PLUS@26..27 "+"
-// EXPR_STMT@27..28
-// LITERAL@27..28
-// INT_NUMBER@27..28 "8"
+// CONST_ARG@27..28
+// LITERAL@27..28
+// INT_NUMBER@27..28 "8"
// ERROR@28..29
// R_PAREN@28..29 ")"
// SEMICOLON@29..30 ";"
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/proc_macros.rs b/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/proc_macros.rs
index 118c14ed8..822bdcc12 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/proc_macros.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/proc_macros.rs
@@ -104,7 +104,7 @@ macro_rules! id {
$($t)*
};
}
-id /*+errors*/! {
+id! {
#[proc_macros::identity]
impl Foo for WrapBj {
async fn foo(&self) {
@@ -113,18 +113,17 @@ id /*+errors*/! {
}
}
"#,
- expect![[r##"
+ expect![[r#"
macro_rules! id {
($($t:tt)*) => {
$($t)*
};
}
-/* parse error: expected SEMICOLON */
#[proc_macros::identity] impl Foo for WrapBj {
async fn foo(&self ) {
self .0.id().await ;
}
}
-"##]],
+"#]],
);
}
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/nameres/attr_resolution.rs b/src/tools/rust-analyzer/crates/hir-def/src/nameres/attr_resolution.rs
index 3650204ee..79cabeb0f 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/nameres/attr_resolution.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/nameres/attr_resolution.rs
@@ -1,10 +1,9 @@
//! Post-nameres attribute resolution.
-use hir_expand::MacroCallId;
+use hir_expand::{attrs::Attr, MacroCallId};
use syntax::{ast, SmolStr};
use crate::{
- attr::Attr,
attr_macro_as_call_id, builtin_attr,
db::DefDatabase,
item_scope::BuiltinShadowMode,
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs b/src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs
index 160203b77..4b39a20d8 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs
@@ -10,6 +10,7 @@ use cfg::{CfgExpr, CfgOptions};
use either::Either;
use hir_expand::{
ast_id_map::FileAstId,
+ attrs::{Attr, AttrId},
builtin_attr_macro::find_builtin_attr,
builtin_derive_macro::find_builtin_derive,
builtin_fn_macro::find_builtin_macro,
@@ -26,7 +27,7 @@ use stdx::always;
use syntax::{ast, SmolStr};
use crate::{
- attr::{Attr, AttrId, Attrs},
+ attr::Attrs,
attr_macro_as_call_id,
db::DefDatabase,
derive_macro_as_call_id,
@@ -45,6 +46,7 @@ use crate::{
},
path::{ImportAlias, ModPath, PathKind},
per_ns::PerNs,
+ tt,
visibility::{RawVisibility, Visibility},
AdtId, AstId, AstIdWithPath, ConstLoc, EnumLoc, EnumVariantId, ExternBlockLoc, FunctionId,
FunctionLoc, ImplLoc, Intern, ItemContainerId, LocalModuleId, Macro2Id, Macro2Loc,
@@ -82,7 +84,8 @@ pub(super) fn collect_defs(db: &dyn DefDatabase, mut def_map: DefMap, tree_id: T
.enumerate()
.map(|(idx, it)| {
// FIXME: a hacky way to create a Name from string.
- let name = tt::Ident { text: it.name.clone(), id: tt::TokenId::unspecified() };
+ let name =
+ tt::Ident { text: it.name.clone(), span: tt::TokenId::unspecified() };
(
name.as_name(),
ProcMacroExpander::new(def_map.krate, base_db::ProcMacroId(idx as u32)),
@@ -450,8 +453,11 @@ impl DefCollector<'_> {
directive.module_id,
MacroCallKind::Attr {
ast_id: ast_id.ast_id,
- attr_args: Default::default(),
- invoc_attr_index: attr.id.ast_index,
+ attr_args: std::sync::Arc::new((
+ tt::Subtree::empty(),
+ Default::default(),
+ )),
+ invoc_attr_index: attr.id,
is_derive: false,
},
attr.path().clone(),
@@ -1406,7 +1412,7 @@ impl DefCollector<'_> {
directive.module_id,
MacroCallKind::Derive {
ast_id: ast_id.ast_id,
- derive_attr_index: derive_attr.ast_index,
+ derive_attr_index: *derive_attr,
derive_index: *derive_pos as u32,
},
ast_id.path.clone(),
@@ -1599,17 +1605,15 @@ impl ModCollector<'_, '_> {
FunctionLoc { container, id: ItemTreeId::new(self.tree_id, id) }.intern(db);
let vis = resolve_vis(def_map, &self.item_tree[it.visibility]);
- if self.def_collector.is_proc_macro {
- if self.module_id == def_map.root {
- if let Some(proc_macro) = attrs.parse_proc_macro_decl(&it.name) {
- let crate_root = def_map.module_id(def_map.root);
- self.def_collector.export_proc_macro(
- proc_macro,
- ItemTreeId::new(self.tree_id, id),
- fn_id,
- crate_root,
- );
- }
+ if self.def_collector.is_proc_macro && self.module_id == def_map.root {
+ if let Some(proc_macro) = attrs.parse_proc_macro_decl(&it.name) {
+ let crate_root = def_map.module_id(def_map.root);
+ self.def_collector.export_proc_macro(
+ proc_macro,
+ ItemTreeId::new(self.tree_id, id),
+ fn_id,
+ crate_root,
+ );
}
}
@@ -1948,7 +1952,8 @@ impl ModCollector<'_, '_> {
let name = match attrs.by_key("rustc_builtin_macro").string_value() {
Some(it) => {
// FIXME: a hacky way to create a Name from string.
- name = tt::Ident { text: it.clone(), id: tt::TokenId::unspecified() }.as_name();
+ name =
+ tt::Ident { text: it.clone(), span: tt::TokenId::unspecified() }.as_name();
&name
}
None => {
@@ -1983,11 +1988,13 @@ impl ModCollector<'_, '_> {
// Case 2: normal `macro_rules!` macro
MacroExpander::Declarative
};
+ let allow_internal_unsafe = attrs.by_key("allow_internal_unsafe").exists();
let macro_id = MacroRulesLoc {
container: module,
id: ItemTreeId::new(self.tree_id, id),
local_inner,
+ allow_internal_unsafe,
expander,
}
.intern(self.def_collector.db);
@@ -2047,10 +2054,15 @@ impl ModCollector<'_, '_> {
// Case 2: normal `macro`
MacroExpander::Declarative
};
+ let allow_internal_unsafe = attrs.by_key("allow_internal_unsafe").exists();
- let macro_id =
- Macro2Loc { container: module, id: ItemTreeId::new(self.tree_id, id), expander }
- .intern(self.def_collector.db);
+ let macro_id = Macro2Loc {
+ container: module,
+ id: ItemTreeId::new(self.tree_id, id),
+ expander,
+ allow_internal_unsafe,
+ }
+ .intern(self.def_collector.db);
self.def_collector.define_macro_def(
self.module_id,
mac.name.clone(),
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/nameres/diagnostics.rs b/src/tools/rust-analyzer/crates/hir-def/src/nameres/diagnostics.rs
index 066142291..b024d7c67 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/nameres/diagnostics.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/nameres/diagnostics.rs
@@ -2,12 +2,11 @@
use base_db::CrateId;
use cfg::{CfgExpr, CfgOptions};
-use hir_expand::MacroCallKind;
+use hir_expand::{attrs::AttrId, MacroCallKind};
use la_arena::Idx;
use syntax::ast::{self, AnyHasAttrs};
use crate::{
- attr::AttrId,
item_tree::{self, ItemTreeId},
nameres::LocalModuleId,
path::ModPath,
@@ -32,9 +31,9 @@ pub enum DefDiagnosticKind {
UnimplementedBuiltinMacro { ast: AstId<ast::Macro> },
- InvalidDeriveTarget { ast: AstId<ast::Item>, id: u32 },
+ InvalidDeriveTarget { ast: AstId<ast::Item>, id: usize },
- MalformedDerive { ast: AstId<ast::Adt>, id: u32 },
+ MalformedDerive { ast: AstId<ast::Adt>, id: usize },
}
#[derive(Debug, PartialEq, Eq)]
@@ -120,7 +119,7 @@ impl DefDiagnostic {
) -> Self {
Self {
in_module: container,
- kind: DefDiagnosticKind::InvalidDeriveTarget { ast, id: id.ast_index },
+ kind: DefDiagnosticKind::InvalidDeriveTarget { ast, id: id.ast_index() },
}
}
@@ -131,7 +130,7 @@ impl DefDiagnostic {
) -> Self {
Self {
in_module: container,
- kind: DefDiagnosticKind::MalformedDerive { ast, id: id.ast_index },
+ kind: DefDiagnosticKind::MalformedDerive { ast, id: id.ast_index() },
}
}
}
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/nameres/mod_resolution.rs b/src/tools/rust-analyzer/crates/hir-def/src/nameres/mod_resolution.rs
index 4c263846d..51c565fe1 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/nameres/mod_resolution.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/nameres/mod_resolution.rs
@@ -7,7 +7,7 @@ use syntax::SmolStr;
use crate::{db::DefDatabase, HirFileId};
-const MOD_DEPTH_LIMIT: Limit = Limit::new(32);
+static MOD_DEPTH_LIMIT: Limit = Limit::new(32);
#[derive(Clone, Debug)]
pub(super) struct ModDir {
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/nameres/proc_macro.rs b/src/tools/rust-analyzer/crates/hir-def/src/nameres/proc_macro.rs
index 06b23392c..caad4a1f3 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/nameres/proc_macro.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/nameres/proc_macro.rs
@@ -1,9 +1,9 @@
//! Nameres-specific procedural macro data and helpers.
use hir_expand::name::{AsName, Name};
-use tt::{Leaf, TokenTree};
use crate::attr::Attrs;
+use crate::tt::{Leaf, TokenTree};
#[derive(Debug, PartialEq, Eq)]
pub struct ProcMacroDef {
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/nameres/tests.rs b/src/tools/rust-analyzer/crates/hir-def/src/nameres/tests.rs
index 0d90047c2..8a27c60df 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/nameres/tests.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/nameres/tests.rs
@@ -476,7 +476,7 @@ pub struct Bar;
fn no_std_prelude() {
check(
r#"
- //- /main.rs crate:main deps:core,std
+ //- /main.rs edition:2018 crate:main deps:core,std
#![cfg_attr(not(never), no_std)]
use Rust;
@@ -544,7 +544,7 @@ fn edition_specific_preludes() {
fn std_prelude_takes_precedence_above_core_prelude() {
check(
r#"
-//- /main.rs crate:main deps:core,std
+//- /main.rs edition:2018 crate:main deps:core,std
use {Foo, Bar};
//- /std.rs crate:std deps:core
@@ -574,7 +574,7 @@ pub mod prelude {
fn cfg_not_test() {
check(
r#"
-//- /main.rs crate:main deps:std
+//- /main.rs edition:2018 crate:main deps:std
use {Foo, Bar, Baz};
//- /lib.rs crate:std
@@ -602,7 +602,7 @@ pub mod prelude {
fn cfg_test() {
check(
r#"
-//- /main.rs crate:main deps:std
+//- /main.rs edition:2018 crate:main deps:std
use {Foo, Bar, Baz};
//- /lib.rs crate:std cfg:test,feature=foo,feature=bar,opt=42
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/nameres/tests/macros.rs b/src/tools/rust-analyzer/crates/hir-def/src/nameres/tests/macros.rs
index fe0ad4f38..a4ccd14cb 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/nameres/tests/macros.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/nameres/tests/macros.rs
@@ -264,7 +264,7 @@ fn prelude_is_macro_use() {
cov_mark::check!(prelude_is_macro_use);
check(
r#"
-//- /main.rs crate:main deps:std
+//- /main.rs edition:2018 crate:main deps:std
structs!(Foo);
structs_priv!(Bar);
structs_outside!(Out);
@@ -634,7 +634,7 @@ fn macro_dollar_crate_is_correct_in_indirect_deps() {
// From std
check(
r#"
-//- /main.rs crate:main deps:std
+//- /main.rs edition:2018 crate:main deps:std
foo!();
//- /std.rs crate:std deps:core
@@ -1034,7 +1034,7 @@ structs!(Foo);
fn macro_in_prelude() {
check(
r#"
-//- /lib.rs crate:lib deps:std
+//- /lib.rs edition:2018 crate:lib deps:std
global_asm!();
//- /std.rs crate:std
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/path.rs b/src/tools/rust-analyzer/crates/hir-def/src/path.rs
index 592223f7d..36d4c36a2 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/path.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/path.rs
@@ -8,10 +8,10 @@ use std::{
use crate::{
body::LowerCtx,
- intern::Interned,
type_ref::{ConstScalarOrPath, LifetimeRef},
};
use hir_expand::name::Name;
+use intern::Interned;
use syntax::ast;
use crate::type_ref::{TypeBound, TypeRef};
@@ -38,18 +38,18 @@ impl Display for ImportAlias {
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct Path {
/// Type based path like `<T>::foo`.
- /// Note that paths like `<Type as Trait>::foo` are desugard to `Trait::<Self=Type>::foo`.
+ /// Note that paths like `<Type as Trait>::foo` are desugared to `Trait::<Self=Type>::foo`.
type_anchor: Option<Interned<TypeRef>>,
mod_path: Interned<ModPath>,
- /// Invariant: the same len as `self.mod_path.segments`
- generic_args: Box<[Option<Interned<GenericArgs>>]>,
+ /// Invariant: the same len as `self.mod_path.segments` or `None` if all segments are `None`.
+ generic_args: Option<Box<[Option<Interned<GenericArgs>>]>>,
}
/// Generic arguments to a path segment (e.g. the `i32` in `Option<i32>`). This
/// also includes bindings of associated types, like in `Iterator<Item = Foo>`.
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct GenericArgs {
- pub args: Vec<GenericArg>,
+ pub args: Box<[GenericArg]>,
/// This specifies whether the args contain a Self type as the first
/// element. This is the case for path segments like `<T as Trait>`, where
/// `T` is actually a type parameter for the path `Trait` specifying the
@@ -57,7 +57,7 @@ pub struct GenericArgs {
/// is left out.
pub has_self_type: bool,
/// Associated type bindings like in `Iterator<Item = T>`.
- pub bindings: Vec<AssociatedTypeBinding>,
+ pub bindings: Box<[AssociatedTypeBinding]>,
/// Whether these generic args were desugared from `Trait(Arg) -> Output`
/// parenthesis notation typically used for the `Fn` traits.
pub desugared_from_fn: bool,
@@ -77,7 +77,7 @@ pub struct AssociatedTypeBinding {
/// Bounds for the associated type, like in `Iterator<Item:
/// SomeOtherTrait>`. (This is the unstable `associated_type_bounds`
/// feature.)
- pub bounds: Vec<Interned<TypeBound>>,
+ pub bounds: Box<[Interned<TypeBound>]>,
}
/// A single generic argument.
@@ -102,7 +102,7 @@ impl Path {
) -> Path {
let generic_args = generic_args.into();
assert_eq!(path.len(), generic_args.len());
- Path { type_anchor: None, mod_path: Interned::new(path), generic_args }
+ Path { type_anchor: None, mod_path: Interned::new(path), generic_args: Some(generic_args) }
}
pub fn kind(&self) -> &PathKind {
@@ -114,7 +114,14 @@ impl Path {
}
pub fn segments(&self) -> PathSegments<'_> {
- PathSegments { segments: self.mod_path.segments(), generic_args: &self.generic_args }
+ let s = PathSegments {
+ segments: self.mod_path.segments(),
+ generic_args: self.generic_args.as_deref(),
+ };
+ if let Some(generic_args) = s.generic_args {
+ assert_eq!(s.segments.len(), generic_args.len());
+ }
+ s
}
pub fn mod_path(&self) -> &ModPath {
@@ -131,13 +138,15 @@ impl Path {
self.mod_path.kind,
self.mod_path.segments()[..self.mod_path.segments().len() - 1].iter().cloned(),
)),
- generic_args: self.generic_args[..self.generic_args.len() - 1].to_vec().into(),
+ generic_args: self.generic_args.as_ref().map(|it| it[..it.len() - 1].to_vec().into()),
};
Some(res)
}
pub fn is_self_type(&self) -> bool {
- self.type_anchor.is_none() && *self.generic_args == [None] && self.mod_path.is_Self()
+ self.type_anchor.is_none()
+ && self.generic_args.as_deref().is_none()
+ && self.mod_path.is_Self()
}
}
@@ -149,11 +158,11 @@ pub struct PathSegment<'a> {
pub struct PathSegments<'a> {
segments: &'a [Name],
- generic_args: &'a [Option<Interned<GenericArgs>>],
+ generic_args: Option<&'a [Option<Interned<GenericArgs>>]>,
}
impl<'a> PathSegments<'a> {
- pub const EMPTY: PathSegments<'static> = PathSegments { segments: &[], generic_args: &[] };
+ pub const EMPTY: PathSegments<'static> = PathSegments { segments: &[], generic_args: None };
pub fn is_empty(&self) -> bool {
self.len() == 0
}
@@ -167,26 +176,29 @@ impl<'a> PathSegments<'a> {
self.get(self.len().checked_sub(1)?)
}
pub fn get(&self, idx: usize) -> Option<PathSegment<'a>> {
- assert_eq!(self.segments.len(), self.generic_args.len());
let res = PathSegment {
name: self.segments.get(idx)?,
- args_and_bindings: self.generic_args.get(idx).unwrap().as_ref().map(|it| &**it),
+ args_and_bindings: self.generic_args.and_then(|it| it.get(idx)?.as_deref()),
};
Some(res)
}
pub fn skip(&self, len: usize) -> PathSegments<'a> {
- assert_eq!(self.segments.len(), self.generic_args.len());
- PathSegments { segments: &self.segments[len..], generic_args: &self.generic_args[len..] }
+ PathSegments {
+ segments: &self.segments.get(len..).unwrap_or(&[]),
+ generic_args: self.generic_args.and_then(|it| it.get(len..)),
+ }
}
pub fn take(&self, len: usize) -> PathSegments<'a> {
- assert_eq!(self.segments.len(), self.generic_args.len());
- PathSegments { segments: &self.segments[..len], generic_args: &self.generic_args[..len] }
+ PathSegments {
+ segments: &self.segments.get(..len).unwrap_or(&self.segments),
+ generic_args: self.generic_args.map(|it| it.get(..len).unwrap_or(it)),
+ }
}
pub fn iter(&self) -> impl Iterator<Item = PathSegment<'a>> {
- self.segments.iter().zip(self.generic_args.iter()).map(|(name, args)| PathSegment {
- name,
- args_and_bindings: args.as_ref().map(|it| &**it),
- })
+ self.segments
+ .iter()
+ .zip(self.generic_args.into_iter().flatten().chain(iter::repeat(&None)))
+ .map(|(name, args)| PathSegment { name, args_and_bindings: args.as_deref() })
}
}
@@ -200,9 +212,9 @@ impl GenericArgs {
pub(crate) fn empty() -> GenericArgs {
GenericArgs {
- args: Vec::new(),
+ args: Box::default(),
has_self_type: false,
- bindings: Vec::new(),
+ bindings: Box::default(),
desugared_from_fn: false,
}
}
@@ -213,7 +225,7 @@ impl From<Name> for Path {
Path {
type_anchor: None,
mod_path: Interned::new(ModPath::from_segments(PathKind::Plain, iter::once(name))),
- generic_args: Box::new([None]),
+ generic_args: None,
}
}
}
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/path/lower.rs b/src/tools/rust-analyzer/crates/hir-def/src/path/lower.rs
index cfa3a6baa..c85a11db6 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/path/lower.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/path/lower.rs
@@ -1,9 +1,12 @@
//! Transforms syntax into `Path` objects, ideally with accounting for hygiene
-use crate::{intern::Interned, type_ref::ConstScalarOrPath};
+use std::iter;
+
+use crate::type_ref::ConstScalarOrPath;
use either::Either;
use hir_expand::name::{name, AsName};
+use intern::Interned;
use syntax::ast::{self, AstNode, HasTypeBounds};
use super::AssociatedTypeBinding;
@@ -44,8 +47,11 @@ pub(super) fn lower_path(mut path: ast::Path, ctx: &LowerCtx<'_>) -> Option<Path
)
})
.map(Interned::new);
+ if let Some(_) = args {
+ generic_args.resize(segments.len(), None);
+ generic_args.push(args);
+ }
segments.push(name);
- generic_args.push(args)
}
Either::Right(crate_id) => {
kind = PathKind::DollarCrate(crate_id);
@@ -55,7 +61,6 @@ pub(super) fn lower_path(mut path: ast::Path, ctx: &LowerCtx<'_>) -> Option<Path
}
ast::PathSegmentKind::SelfTypeKw => {
segments.push(name![Self]);
- generic_args.push(None)
}
ast::PathSegmentKind::Type { type_ref, trait_ref } => {
assert!(path.qualifier().is_none()); // this can only occur at the first segment
@@ -76,18 +81,33 @@ pub(super) fn lower_path(mut path: ast::Path, ctx: &LowerCtx<'_>) -> Option<Path
kind = mod_path.kind;
segments.extend(mod_path.segments().iter().cloned().rev());
- generic_args.extend(Vec::from(path_generic_args).into_iter().rev());
+ if let Some(path_generic_args) = path_generic_args {
+ generic_args.resize(segments.len() - num_segments, None);
+ generic_args.extend(Vec::from(path_generic_args).into_iter().rev());
+ } else {
+ generic_args.resize(segments.len(), None);
+ }
+
+ let self_type = GenericArg::Type(self_type);
// Insert the type reference (T in the above example) as Self parameter for the trait
- let last_segment =
- generic_args.iter_mut().rev().nth(num_segments.saturating_sub(1))?;
- let mut args_inner = match last_segment {
- Some(it) => it.as_ref().clone(),
- None => GenericArgs::empty(),
- };
- args_inner.has_self_type = true;
- args_inner.args.insert(0, GenericArg::Type(self_type));
- *last_segment = Some(Interned::new(args_inner));
+ let last_segment = generic_args.get_mut(segments.len() - num_segments)?;
+ *last_segment = Some(Interned::new(match last_segment.take() {
+ Some(it) => GenericArgs {
+ args: iter::once(self_type)
+ .chain(it.args.iter().cloned())
+ .collect(),
+
+ has_self_type: true,
+ bindings: it.bindings.clone(),
+ desugared_from_fn: it.desugared_from_fn,
+ },
+ None => GenericArgs {
+ args: Box::new([self_type]),
+ has_self_type: true,
+ ..GenericArgs::empty()
+ },
+ }));
}
}
}
@@ -114,7 +134,10 @@ pub(super) fn lower_path(mut path: ast::Path, ctx: &LowerCtx<'_>) -> Option<Path
};
}
segments.reverse();
- generic_args.reverse();
+ if !generic_args.is_empty() {
+ generic_args.resize(segments.len(), None);
+ generic_args.reverse();
+ }
if segments.is_empty() && kind == PathKind::Plain && type_anchor.is_none() {
// plain empty paths don't exist, this means we got a single `self` segment as our path
@@ -134,7 +157,11 @@ pub(super) fn lower_path(mut path: ast::Path, ctx: &LowerCtx<'_>) -> Option<Path
}
let mod_path = Interned::new(ModPath::from_segments(kind, segments));
- return Some(Path { type_anchor, mod_path, generic_args: generic_args.into() });
+ return Some(Path {
+ type_anchor,
+ mod_path,
+ generic_args: if generic_args.is_empty() { None } else { Some(generic_args.into()) },
+ });
fn qualifier(path: &ast::Path) -> Option<ast::Path> {
if let Some(q) = path.qualifier() {
@@ -173,7 +200,7 @@ pub(super) fn lower_generic_args(
.map(|it| Interned::new(TypeBound::from_ast(lower_ctx, it)))
.collect()
} else {
- Vec::new()
+ Box::default()
};
bindings.push(AssociatedTypeBinding { name, args, type_ref, bounds });
}
@@ -194,7 +221,12 @@ pub(super) fn lower_generic_args(
if args.is_empty() && bindings.is_empty() {
return None;
}
- Some(GenericArgs { args, has_self_type: false, bindings, desugared_from_fn: false })
+ Some(GenericArgs {
+ args: args.into_boxed_slice(),
+ has_self_type: false,
+ bindings: bindings.into_boxed_slice(),
+ desugared_from_fn: false,
+ })
}
/// Collect `GenericArgs` from the parts of a fn-like path, i.e. `Fn(X, Y)
@@ -204,33 +236,30 @@ fn lower_generic_args_from_fn_path(
params: Option<ast::ParamList>,
ret_type: Option<ast::RetType>,
) -> Option<GenericArgs> {
- let mut args = Vec::new();
- let mut bindings = Vec::new();
let params = params?;
let mut param_types = Vec::new();
for param in params.params() {
let type_ref = TypeRef::from_ast_opt(ctx, param.ty());
param_types.push(type_ref);
}
- let arg = GenericArg::Type(TypeRef::Tuple(param_types));
- args.push(arg);
- if let Some(ret_type) = ret_type {
+ let args = Box::new([GenericArg::Type(TypeRef::Tuple(param_types))]);
+ let bindings = if let Some(ret_type) = ret_type {
let type_ref = TypeRef::from_ast_opt(ctx, ret_type.ty());
- bindings.push(AssociatedTypeBinding {
+ Box::new([AssociatedTypeBinding {
name: name![Output],
args: None,
type_ref: Some(type_ref),
- bounds: Vec::new(),
- });
+ bounds: Box::default(),
+ }])
} else {
// -> ()
let type_ref = TypeRef::Tuple(Vec::new());
- bindings.push(AssociatedTypeBinding {
+ Box::new([AssociatedTypeBinding {
name: name![Output],
args: None,
type_ref: Some(type_ref),
- bounds: Vec::new(),
- });
- }
+ bounds: Box::default(),
+ }])
+ };
Some(GenericArgs { args, has_self_type: false, bindings, desugared_from_fn: true })
}
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/pretty.rs b/src/tools/rust-analyzer/crates/hir-def/src/pretty.rs
index befd0c5ff..2d45c8c8d 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/pretty.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/pretty.rs
@@ -3,10 +3,10 @@
use std::fmt::{self, Write};
use hir_expand::mod_path::PathKind;
+use intern::Interned;
use itertools::Itertools;
use crate::{
- intern::Interned,
path::{GenericArg, GenericArgs, Path},
type_ref::{Mutability, TraitBoundModifier, TypeBound, TypeRef},
};
@@ -71,7 +71,7 @@ pub(crate) fn print_generic_args(generics: &GenericArgs, buf: &mut dyn Write) ->
first = false;
print_generic_arg(arg, buf)?;
}
- for binding in &generics.bindings {
+ for binding in generics.bindings.iter() {
if !first {
write!(buf, ", ")?;
}
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/resolver.rs b/src/tools/rust-analyzer/crates/hir-def/src/resolver.rs
index 1ef7f9577..86958e3da 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/resolver.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/resolver.rs
@@ -4,6 +4,7 @@ use std::{hash::BuildHasherDefault, sync::Arc};
use base_db::CrateId;
use hir_expand::name::{name, Name};
use indexmap::IndexMap;
+use intern::Interned;
use rustc_hash::FxHashSet;
use smallvec::{smallvec, SmallVec};
@@ -13,7 +14,6 @@ use crate::{
db::DefDatabase,
expr::{ExprId, LabelId, PatId},
generics::{GenericParams, TypeOrConstParamData},
- intern::Interned,
item_scope::{BuiltinShadowMode, BUILTIN_SCOPE},
nameres::DefMap,
path::{ModPath, PathKind},
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/type_ref.rs b/src/tools/rust-analyzer/crates/hir-def/src/type_ref.rs
index f8bb78ddc..9652b01b9 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/type_ref.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/type_ref.rs
@@ -7,13 +7,13 @@ use hir_expand::{
name::{AsName, Name},
AstId,
};
+use intern::Interned;
use syntax::ast::{self, HasName};
use crate::{
body::LowerCtx,
builtin_type::{BuiltinInt, BuiltinType, BuiltinUint},
expr::Literal,
- intern::Interned,
path::Path,
};
@@ -240,7 +240,7 @@ impl TypeRef {
TypeRef::DynTrait(type_bounds_from_ast(ctx, inner.type_bound_list()))
}
ast::Type::MacroType(mt) => match mt.macro_call() {
- Some(mc) => ctx.ast_id(ctx.db, &mc).map(TypeRef::Macro).unwrap_or(TypeRef::Error),
+ Some(mc) => ctx.ast_id(&mc).map(TypeRef::Macro).unwrap_or(TypeRef::Error),
None => TypeRef::Error,
},
}
@@ -292,7 +292,7 @@ impl TypeRef {
}
for segment in path.segments().iter() {
if let Some(args_and_bindings) = segment.args_and_bindings {
- for arg in &args_and_bindings.args {
+ for arg in args_and_bindings.args.iter() {
match arg {
crate::path::GenericArg::Type(type_ref) => {
go(type_ref, f);
@@ -301,11 +301,11 @@ impl TypeRef {
| crate::path::GenericArg::Lifetime(_) => {}
}
}
- for binding in &args_and_bindings.bindings {
+ for binding in args_and_bindings.bindings.iter() {
if let Some(type_ref) = &binding.type_ref {
go(type_ref, f);
}
- for bound in &binding.bounds {
+ for bound in binding.bounds.iter() {
match bound.as_ref() {
TypeBound::Path(path, _) | TypeBound::ForLifetime(_, path) => {
go_path(path, f)
diff --git a/src/tools/rust-analyzer/crates/hir-expand/Cargo.toml b/src/tools/rust-analyzer/crates/hir-expand/Cargo.toml
index 77eb1fd45..5c684be03 100644
--- a/src/tools/rust-analyzer/crates/hir-expand/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/hir-expand/Cargo.toml
@@ -2,9 +2,11 @@
name = "hir-expand"
version = "0.0.0"
description = "TBD"
-license = "MIT OR Apache-2.0"
-edition = "2021"
-rust-version = "1.65"
+
+authors.workspace = true
+edition.workspace = true
+license.workspace = true
+rust-version.workspace = true
[lib]
doctest = false
@@ -19,16 +21,18 @@ itertools = "0.10.5"
hashbrown = { version = "0.12.1", features = [
"inline-more",
], default-features = false }
-smallvec = { version = "1.10.0", features = ["const_new"] }
+smallvec.workspace = true
-stdx = { path = "../stdx", version = "0.0.0" }
-base-db = { path = "../base-db", version = "0.0.0" }
-cfg = { path = "../cfg", version = "0.0.0" }
-syntax = { path = "../syntax", version = "0.0.0" }
-profile = { path = "../profile", version = "0.0.0" }
-tt = { path = "../tt", version = "0.0.0" }
-mbe = { path = "../mbe", version = "0.0.0" }
-limit = { path = "../limit", version = "0.0.0" }
+# local deps
+stdx.workspace = true
+intern.workspace = true
+base-db.workspace = true
+cfg.workspace = true
+syntax.workspace = true
+profile.workspace = true
+tt.workspace = true
+mbe.workspace = true
+limit.workspace = true
[dev-dependencies]
expect-test = "1.4.0"
diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/attrs.rs b/src/tools/rust-analyzer/crates/hir-expand/src/attrs.rs
new file mode 100644
index 000000000..5c04f8e8b
--- /dev/null
+++ b/src/tools/rust-analyzer/crates/hir-expand/src/attrs.rs
@@ -0,0 +1,349 @@
+//! A higher level attributes based on TokenTree, with also some shortcuts.
+use std::{fmt, ops, sync::Arc};
+
+use base_db::CrateId;
+use cfg::CfgExpr;
+use either::Either;
+use intern::Interned;
+use mbe::{syntax_node_to_token_tree, DelimiterKind, Punct};
+use smallvec::{smallvec, SmallVec};
+use syntax::{ast, match_ast, AstNode, SmolStr, SyntaxNode};
+
+use crate::{
+ db::AstDatabase,
+ hygiene::Hygiene,
+ mod_path::{ModPath, PathKind},
+ name::AsName,
+ tt::{self, Subtree},
+ InFile,
+};
+
+/// Syntactical attributes, without filtering of `cfg_attr`s.
+#[derive(Default, Debug, Clone, PartialEq, Eq)]
+pub struct RawAttrs {
+ entries: Option<Arc<[Attr]>>,
+}
+
+impl ops::Deref for RawAttrs {
+ type Target = [Attr];
+
+ fn deref(&self) -> &[Attr] {
+ match &self.entries {
+ Some(it) => &*it,
+ None => &[],
+ }
+ }
+}
+
+impl RawAttrs {
+ pub const EMPTY: Self = Self { entries: None };
+
+ pub fn new(db: &dyn AstDatabase, owner: &dyn ast::HasAttrs, hygiene: &Hygiene) -> Self {
+ let entries = collect_attrs(owner)
+ .filter_map(|(id, attr)| match attr {
+ Either::Left(attr) => {
+ attr.meta().and_then(|meta| Attr::from_src(db, meta, hygiene, id))
+ }
+ Either::Right(comment) => comment.doc_comment().map(|doc| Attr {
+ id,
+ input: Some(Interned::new(AttrInput::Literal(SmolStr::new(doc)))),
+ path: Interned::new(ModPath::from(crate::name!(doc))),
+ }),
+ })
+ .collect::<Arc<_>>();
+
+ Self { entries: if entries.is_empty() { None } else { Some(entries) } }
+ }
+
+ pub fn from_attrs_owner(db: &dyn AstDatabase, owner: InFile<&dyn ast::HasAttrs>) -> Self {
+ let hygiene = Hygiene::new(db, owner.file_id);
+ Self::new(db, owner.value, &hygiene)
+ }
+
+ pub fn merge(&self, other: Self) -> Self {
+ match (&self.entries, other.entries) {
+ (None, None) => Self::EMPTY,
+ (None, entries @ Some(_)) => Self { entries },
+ (Some(entries), None) => Self { entries: Some(entries.clone()) },
+ (Some(a), Some(b)) => {
+ let last_ast_index = a.last().map_or(0, |it| it.id.ast_index() + 1) as u32;
+ Self {
+ entries: Some(
+ a.iter()
+ .cloned()
+ .chain(b.iter().map(|it| {
+ let mut it = it.clone();
+ it.id.id = it.id.ast_index() as u32 + last_ast_index
+ | (it.id.cfg_attr_index().unwrap_or(0) as u32)
+ << AttrId::AST_INDEX_BITS;
+ it
+ }))
+ .collect(),
+ ),
+ }
+ }
+ }
+ }
+
+ /// Processes `cfg_attr`s, returning the resulting semantic `Attrs`.
+ // FIXME: This should return a different type
+ pub fn filter(self, db: &dyn AstDatabase, krate: CrateId) -> RawAttrs {
+ let has_cfg_attrs = self
+ .iter()
+ .any(|attr| attr.path.as_ident().map_or(false, |name| *name == crate::name![cfg_attr]));
+ if !has_cfg_attrs {
+ return self;
+ }
+
+ let crate_graph = db.crate_graph();
+ let new_attrs = self
+ .iter()
+ .flat_map(|attr| -> SmallVec<[_; 1]> {
+ let is_cfg_attr =
+ attr.path.as_ident().map_or(false, |name| *name == crate::name![cfg_attr]);
+ if !is_cfg_attr {
+ return smallvec![attr.clone()];
+ }
+
+ let subtree = match attr.token_tree_value() {
+ Some(it) => it,
+ _ => return smallvec![attr.clone()],
+ };
+
+ let (cfg, parts) = match parse_cfg_attr_input(subtree) {
+ Some(it) => it,
+ None => return smallvec![attr.clone()],
+ };
+ let index = attr.id;
+ let attrs =
+ parts.enumerate().take(1 << AttrId::CFG_ATTR_BITS).filter_map(|(idx, attr)| {
+ let tree = Subtree {
+ delimiter: tt::Delimiter::unspecified(),
+ token_trees: attr.to_vec(),
+ };
+ // FIXME hygiene
+ let hygiene = Hygiene::new_unhygienic();
+ Attr::from_tt(db, &tree, &hygiene, index.with_cfg_attr(idx))
+ });
+
+ let cfg_options = &crate_graph[krate].cfg_options;
+ let cfg = Subtree { delimiter: subtree.delimiter, token_trees: cfg.to_vec() };
+ let cfg = CfgExpr::parse(&cfg);
+ if cfg_options.check(&cfg) == Some(false) {
+ smallvec![]
+ } else {
+ cov_mark::hit!(cfg_attr_active);
+
+ attrs.collect()
+ }
+ })
+ .collect();
+
+ RawAttrs { entries: Some(new_attrs) }
+ }
+}
+
+#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
+pub struct AttrId {
+ id: u32,
+}
+
+// FIXME: This only handles a single level of cfg_attr nesting
+// that is `#[cfg_attr(all(), cfg_attr(all(), cfg(any())))]` breaks again
+impl AttrId {
+ const CFG_ATTR_BITS: usize = 7;
+ const AST_INDEX_MASK: usize = 0x00FF_FFFF;
+ const AST_INDEX_BITS: usize = Self::AST_INDEX_MASK.count_ones() as usize;
+ const CFG_ATTR_SET_BITS: u32 = 1 << 31;
+
+ pub fn ast_index(&self) -> usize {
+ self.id as usize & Self::AST_INDEX_MASK
+ }
+
+ pub fn cfg_attr_index(&self) -> Option<usize> {
+ if self.id & Self::CFG_ATTR_SET_BITS == 0 {
+ None
+ } else {
+ Some(self.id as usize >> Self::AST_INDEX_BITS)
+ }
+ }
+
+ pub fn with_cfg_attr(self, idx: usize) -> AttrId {
+ AttrId { id: self.id | (idx as u32) << Self::AST_INDEX_BITS | Self::CFG_ATTR_SET_BITS }
+ }
+}
+
+#[derive(Debug, Clone, PartialEq, Eq)]
+pub struct Attr {
+ pub id: AttrId,
+ pub path: Interned<ModPath>,
+ pub input: Option<Interned<AttrInput>>,
+}
+
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub enum AttrInput {
+ /// `#[attr = "string"]`
+ Literal(SmolStr),
+ /// `#[attr(subtree)]`
+ TokenTree(tt::Subtree, mbe::TokenMap),
+}
+
+impl fmt::Display for AttrInput {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ match self {
+ AttrInput::Literal(lit) => write!(f, " = \"{}\"", lit.escape_debug()),
+ AttrInput::TokenTree(subtree, _) => subtree.fmt(f),
+ }
+ }
+}
+
+impl Attr {
+ fn from_src(
+ db: &dyn AstDatabase,
+ ast: ast::Meta,
+ hygiene: &Hygiene,
+ id: AttrId,
+ ) -> Option<Attr> {
+ let path = Interned::new(ModPath::from_src(db, ast.path()?, hygiene)?);
+ let input = if let Some(ast::Expr::Literal(lit)) = ast.expr() {
+ let value = match lit.kind() {
+ ast::LiteralKind::String(string) => string.value()?.into(),
+ _ => lit.syntax().first_token()?.text().trim_matches('"').into(),
+ };
+ Some(Interned::new(AttrInput::Literal(value)))
+ } else if let Some(tt) = ast.token_tree() {
+ let (tree, map) = syntax_node_to_token_tree(tt.syntax());
+ Some(Interned::new(AttrInput::TokenTree(tree, map)))
+ } else {
+ None
+ };
+ Some(Attr { id, path, input })
+ }
+
+ fn from_tt(
+ db: &dyn AstDatabase,
+ tt: &tt::Subtree,
+ hygiene: &Hygiene,
+ id: AttrId,
+ ) -> Option<Attr> {
+ let (parse, _) = mbe::token_tree_to_syntax_node(tt, mbe::TopEntryPoint::MetaItem);
+ let ast = ast::Meta::cast(parse.syntax_node())?;
+
+ Self::from_src(db, ast, hygiene, id)
+ }
+
+ pub fn path(&self) -> &ModPath {
+ &self.path
+ }
+}
+
+impl Attr {
+ /// #[path = "string"]
+ pub fn string_value(&self) -> Option<&SmolStr> {
+ match self.input.as_deref()? {
+ AttrInput::Literal(it) => Some(it),
+ _ => None,
+ }
+ }
+
+ /// #[path(ident)]
+ pub fn single_ident_value(&self) -> Option<&tt::Ident> {
+ match self.input.as_deref()? {
+ AttrInput::TokenTree(subtree, _) => match &*subtree.token_trees {
+ [tt::TokenTree::Leaf(tt::Leaf::Ident(ident))] => Some(ident),
+ _ => None,
+ },
+ _ => None,
+ }
+ }
+
+ /// #[path TokenTree]
+ pub fn token_tree_value(&self) -> Option<&Subtree> {
+ match self.input.as_deref()? {
+ AttrInput::TokenTree(subtree, _) => Some(subtree),
+ _ => None,
+ }
+ }
+
+ /// Parses this attribute as a token tree consisting of comma separated paths.
+ pub fn parse_path_comma_token_tree(&self) -> Option<impl Iterator<Item = ModPath> + '_> {
+ let args = self.token_tree_value()?;
+
+ if args.delimiter.kind != DelimiterKind::Parenthesis {
+ return None;
+ }
+ let paths = args
+ .token_trees
+ .split(|tt| matches!(tt, tt::TokenTree::Leaf(tt::Leaf::Punct(Punct { char: ',', .. }))))
+ .filter_map(|tts| {
+ if tts.is_empty() {
+ return None;
+ }
+ let segments = tts.iter().filter_map(|tt| match tt {
+ tt::TokenTree::Leaf(tt::Leaf::Ident(id)) => Some(id.as_name()),
+ _ => None,
+ });
+ Some(ModPath::from_segments(PathKind::Plain, segments))
+ });
+
+ Some(paths)
+ }
+}
+
+pub fn collect_attrs(
+ owner: &dyn ast::HasAttrs,
+) -> impl Iterator<Item = (AttrId, Either<ast::Attr, ast::Comment>)> {
+ let inner_attrs = inner_attributes(owner.syntax()).into_iter().flatten();
+ let outer_attrs =
+ ast::AttrDocCommentIter::from_syntax_node(owner.syntax()).filter(|el| match el {
+ Either::Left(attr) => attr.kind().is_outer(),
+ Either::Right(comment) => comment.is_outer(),
+ });
+ outer_attrs.chain(inner_attrs).enumerate().map(|(id, attr)| (AttrId { id: id as u32 }, attr))
+}
+
+fn inner_attributes(
+ syntax: &SyntaxNode,
+) -> Option<impl Iterator<Item = Either<ast::Attr, ast::Comment>>> {
+ let node = match_ast! {
+ match syntax {
+ ast::SourceFile(_) => syntax.clone(),
+ ast::ExternBlock(it) => it.extern_item_list()?.syntax().clone(),
+ ast::Fn(it) => it.body()?.stmt_list()?.syntax().clone(),
+ ast::Impl(it) => it.assoc_item_list()?.syntax().clone(),
+ ast::Module(it) => it.item_list()?.syntax().clone(),
+ ast::BlockExpr(it) => {
+ use syntax::SyntaxKind::{BLOCK_EXPR , EXPR_STMT};
+ // Block expressions accept outer and inner attributes, but only when they are the outer
+ // expression of an expression statement or the final expression of another block expression.
+ let may_carry_attributes = matches!(
+ it.syntax().parent().map(|it| it.kind()),
+ Some(BLOCK_EXPR | EXPR_STMT)
+ );
+ if !may_carry_attributes {
+ return None
+ }
+ syntax.clone()
+ },
+ _ => return None,
+ }
+ };
+
+ let attrs = ast::AttrDocCommentIter::from_syntax_node(&node).filter(|el| match el {
+ Either::Left(attr) => attr.kind().is_inner(),
+ Either::Right(comment) => comment.is_inner(),
+ });
+ Some(attrs)
+}
+
+// Input subtree is: `(cfg, $(attr),+)`
+// Split it up into a `cfg` subtree and the `attr` subtrees.
+pub fn parse_cfg_attr_input(
+ subtree: &Subtree,
+) -> Option<(&[tt::TokenTree], impl Iterator<Item = &[tt::TokenTree]>)> {
+ let mut parts = subtree
+ .token_trees
+ .split(|tt| matches!(tt, tt::TokenTree::Leaf(tt::Leaf::Punct(Punct { char: ',', .. }))));
+ let cfg = parts.next()?;
+ Some((cfg, parts.filter(|it| !it.is_empty())))
+}
diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/builtin_attr_macro.rs b/src/tools/rust-analyzer/crates/hir-expand/src/builtin_attr_macro.rs
index 58d192f9f..906ca991d 100644
--- a/src/tools/rust-analyzer/crates/hir-expand/src/builtin_attr_macro.rs
+++ b/src/tools/rust-analyzer/crates/hir-expand/src/builtin_attr_macro.rs
@@ -1,6 +1,6 @@
//! Builtin attributes.
-use crate::{db::AstDatabase, name, ExpandResult, MacroCallId, MacroCallKind};
+use crate::{db::AstDatabase, name, tt, ExpandResult, MacroCallId, MacroCallKind};
macro_rules! register_builtin {
( $(($name:ident, $variant:ident) => $expand:ident),* ) => {
@@ -97,7 +97,7 @@ fn derive_attr_expand(
let loc = db.lookup_intern_macro_call(id);
let derives = match &loc.kind {
MacroCallKind::Attr { attr_args, is_derive: true, .. } => &attr_args.0,
- _ => return ExpandResult::ok(Default::default()),
+ _ => return ExpandResult::ok(tt::Subtree::empty()),
};
pseudo_derive_attr_expansion(tt, derives)
}
@@ -110,7 +110,7 @@ pub fn pseudo_derive_attr_expansion(
tt::TokenTree::Leaf(tt::Leaf::Punct(tt::Punct {
char,
spacing: tt::Spacing::Alone,
- id: tt::TokenId::unspecified(),
+ span: tt::TokenId::unspecified(),
}))
};
diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/builtin_derive_macro.rs b/src/tools/rust-analyzer/crates/hir-expand/src/builtin_derive_macro.rs
index 8966047c9..060a68054 100644
--- a/src/tools/rust-analyzer/crates/hir-expand/src/builtin_derive_macro.rs
+++ b/src/tools/rust-analyzer/crates/hir-expand/src/builtin_derive_macro.rs
@@ -3,11 +3,11 @@
use base_db::{CrateOrigin, LangCrateOrigin};
use tracing::debug;
+use crate::tt::{self, TokenId};
use syntax::{
ast::{self, AstNode, HasGenericParams, HasModuleItem, HasName},
match_ast,
};
-use tt::TokenId;
use crate::{db::AstDatabase, name, quote, ExpandError, ExpandResult, MacroCallId};
@@ -92,7 +92,7 @@ fn parse_adt(tt: &tt::Subtree) -> Result<BasicAdtInfo, ExpandError> {
})?;
let name_token_id =
token_map.token_by_range(name.syntax().text_range()).unwrap_or_else(TokenId::unspecified);
- let name_token = tt::Ident { id: name_token_id, text: name.text().into() };
+ let name_token = tt::Ident { span: name_token_id, text: name.text().into() };
let param_types = params
.into_iter()
.flat_map(|param_list| param_list.type_or_const_params())
@@ -101,7 +101,7 @@ fn parse_adt(tt: &tt::Subtree) -> Result<BasicAdtInfo, ExpandError> {
let ty = param
.ty()
.map(|ty| mbe::syntax_node_to_token_tree(ty.syntax()).0)
- .unwrap_or_default();
+ .unwrap_or_else(tt::Subtree::empty);
Some(ty)
} else {
None
@@ -114,7 +114,7 @@ fn parse_adt(tt: &tt::Subtree) -> Result<BasicAdtInfo, ExpandError> {
fn expand_simple_derive(tt: &tt::Subtree, trait_path: tt::Subtree) -> ExpandResult<tt::Subtree> {
let info = match parse_adt(tt) {
Ok(info) => info,
- Err(e) => return ExpandResult::only_err(e),
+ Err(e) => return ExpandResult::with_err(tt::Subtree::empty(), e),
};
let (params, args): (Vec<_>, Vec<_>) = info
.param_types
@@ -122,7 +122,7 @@ fn expand_simple_derive(tt: &tt::Subtree, trait_path: tt::Subtree) -> ExpandResu
.enumerate()
.map(|(idx, param_ty)| {
let ident = tt::Leaf::Ident(tt::Ident {
- id: tt::TokenId::unspecified(),
+ span: tt::TokenId::unspecified(),
text: format!("T{idx}").into(),
});
let ident_ = ident.clone();
diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/builtin_fn_macro.rs b/src/tools/rust-analyzer/crates/hir-expand/src/builtin_fn_macro.rs
index 5522bdf3b..9f3fa73d4 100644
--- a/src/tools/rust-analyzer/crates/hir-expand/src/builtin_fn_macro.rs
+++ b/src/tools/rust-analyzer/crates/hir-expand/src/builtin_fn_macro.rs
@@ -9,7 +9,9 @@ use syntax::{
SmolStr,
};
-use crate::{db::AstDatabase, name, quote, ExpandError, ExpandResult, MacroCallId, MacroCallLoc};
+use crate::{
+ db::AstDatabase, name, quote, tt, ExpandError, ExpandResult, MacroCallId, MacroCallLoc,
+};
macro_rules! register_builtin {
( LAZY: $(($name:ident, $kind: ident) => $expand:ident),* , EAGER: $(($e_name:ident, $e_kind: ident) => $e_expand:ident),* ) => {
@@ -61,7 +63,7 @@ macro_rules! register_builtin {
};
}
-#[derive(Debug, Default)]
+#[derive(Debug)]
pub struct ExpandedEager {
pub(crate) subtree: tt::Subtree,
/// The included file ID of the include macro.
@@ -116,7 +118,7 @@ register_builtin! {
}
const DOLLAR_CRATE: tt::Ident =
- tt::Ident { text: SmolStr::new_inline("$crate"), id: tt::TokenId::unspecified() };
+ tt::Ident { text: SmolStr::new_inline("$crate"), span: tt::TokenId::unspecified() };
fn module_path_expand(
_db: &dyn AstDatabase,
@@ -162,7 +164,7 @@ fn stringify_expand(
_id: MacroCallId,
tt: &tt::Subtree,
) -> ExpandResult<tt::Subtree> {
- let pretty = tt::pretty(&tt.token_trees);
+ let pretty = ::tt::pretty(&tt.token_trees);
let expanded = quote! {
#pretty
@@ -194,11 +196,11 @@ fn assert_expand(
let expanded = match &*args {
[cond, panic_args @ ..] => {
let comma = tt::Subtree {
- delimiter: None,
+ delimiter: tt::Delimiter::unspecified(),
token_trees: vec![tt::TokenTree::Leaf(tt::Leaf::Punct(tt::Punct {
char: ',',
spacing: tt::Spacing::Alone,
- id: tt::TokenId::unspecified(),
+ span: tt::TokenId::unspecified(),
}))],
};
let cond = cond.clone();
@@ -247,7 +249,10 @@ fn format_args_expand(
let mut args = parse_exprs_with_sep(tt, ',');
if args.is_empty() {
- return ExpandResult::only_err(mbe::ExpandError::NoMatchingRule.into());
+ return ExpandResult::with_err(
+ tt::Subtree::empty(),
+ mbe::ExpandError::NoMatchingRule.into(),
+ );
}
for arg in &mut args {
// Remove `key =`.
@@ -282,7 +287,7 @@ fn asm_expand(
for tt in tt.token_trees.chunks(2) {
match tt {
[tt::TokenTree::Leaf(tt::Leaf::Literal(lit))]
- | [tt::TokenTree::Leaf(tt::Leaf::Literal(lit)), tt::TokenTree::Leaf(tt::Leaf::Punct(tt::Punct { char: ',', id: _, spacing: _ }))] =>
+ | [tt::TokenTree::Leaf(tt::Leaf::Literal(lit)), tt::TokenTree::Leaf(tt::Leaf::Punct(tt::Punct { char: ',', span: _, spacing: _ }))] =>
{
let krate = DOLLAR_CRATE.clone();
literals.push(quote!(#krate::format_args!(#lit);));
@@ -400,7 +405,7 @@ fn concat_expand(
// FIXME: hack on top of a hack: `$e:expr` captures get surrounded in parentheses
// to ensure the right parsing order, so skip the parentheses here. Ideally we'd
// implement rustc's model. cc https://github.com/rust-lang/rust-analyzer/pull/10623
- if let tt::TokenTree::Subtree(tt::Subtree { delimiter: Some(delim), token_trees }) = t {
+ if let tt::TokenTree::Subtree(tt::Subtree { delimiter: delim, token_trees }) = t {
if let [tt] = &**token_trees {
if delim.kind == tt::DelimiterKind::Parenthesis {
t = tt;
@@ -459,9 +464,7 @@ fn concat_bytes_expand(
}
}
tt::TokenTree::Leaf(tt::Leaf::Punct(punct)) if i % 2 == 1 && punct.char == ',' => (),
- tt::TokenTree::Subtree(tree)
- if tree.delimiter_kind() == Some(tt::DelimiterKind::Bracket) =>
- {
+ tt::TokenTree::Subtree(tree) if tree.delimiter.kind == tt::DelimiterKind::Bracket => {
if let Err(e) = concat_bytes_expand_subtree(tree, &mut bytes) {
err.get_or_insert(e);
break;
@@ -473,7 +476,7 @@ fn concat_bytes_expand(
}
}
}
- let ident = tt::Ident { text: bytes.join(", ").into(), id: tt::TokenId::unspecified() };
+ let ident = tt::Ident { text: bytes.join(", ").into(), span: tt::TokenId::unspecified() };
ExpandResult { value: ExpandedEager::new(quote!([#ident])), err }
}
@@ -521,7 +524,7 @@ fn concat_idents_expand(
}
}
}
- let ident = tt::Ident { text: ident.into(), id: tt::TokenId::unspecified() };
+ let ident = tt::Ident { text: ident.into(), span: tt::TokenId::unspecified() };
ExpandResult { value: ExpandedEager::new(quote!(#ident)), err }
}
@@ -572,7 +575,10 @@ fn include_expand(
Ok((subtree, file_id)) => {
ExpandResult::ok(ExpandedEager { subtree, included_file: Some(file_id) })
}
- Err(e) => ExpandResult::only_err(e),
+ Err(e) => ExpandResult::with_err(
+ ExpandedEager { subtree: tt::Subtree::empty(), included_file: None },
+ e,
+ ),
}
}
@@ -582,15 +588,18 @@ fn include_bytes_expand(
tt: &tt::Subtree,
) -> ExpandResult<ExpandedEager> {
if let Err(e) = parse_string(tt) {
- return ExpandResult::only_err(e);
+ return ExpandResult::with_err(
+ ExpandedEager { subtree: tt::Subtree::empty(), included_file: None },
+ e,
+ );
}
// FIXME: actually read the file here if the user asked for macro expansion
let res = tt::Subtree {
- delimiter: None,
+ delimiter: tt::Delimiter::unspecified(),
token_trees: vec![tt::TokenTree::Leaf(tt::Leaf::Literal(tt::Literal {
text: r#"b"""#.into(),
- id: tt::TokenId::unspecified(),
+ span: tt::TokenId::unspecified(),
}))],
};
ExpandResult::ok(ExpandedEager::new(res))
@@ -603,7 +612,12 @@ fn include_str_expand(
) -> ExpandResult<ExpandedEager> {
let path = match parse_string(tt) {
Ok(it) => it,
- Err(e) => return ExpandResult::only_err(e),
+ Err(e) => {
+ return ExpandResult::with_err(
+ ExpandedEager { subtree: tt::Subtree::empty(), included_file: None },
+ e,
+ )
+ }
};
// FIXME: we're not able to read excluded files (which is most of them because
@@ -635,7 +649,12 @@ fn env_expand(
) -> ExpandResult<ExpandedEager> {
let key = match parse_string(tt) {
Ok(it) => it,
- Err(e) => return ExpandResult::only_err(e),
+ Err(e) => {
+ return ExpandResult::with_err(
+ ExpandedEager { subtree: tt::Subtree::empty(), included_file: None },
+ e,
+ )
+ }
};
let mut err = None;
@@ -666,7 +685,12 @@ fn option_env_expand(
) -> ExpandResult<ExpandedEager> {
let key = match parse_string(tt) {
Ok(it) => it,
- Err(e) => return ExpandResult::only_err(e),
+ Err(e) => {
+ return ExpandResult::with_err(
+ ExpandedEager { subtree: tt::Subtree::empty(), included_file: None },
+ e,
+ )
+ }
};
let expanded = match get_env_inner(db, arg_id, &key) {
diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/db.rs b/src/tools/rust-analyzer/crates/hir-expand/src/db.rs
index b28e60187..76016274f 100644
--- a/src/tools/rust-analyzer/crates/hir-expand/src/db.rs
+++ b/src/tools/rust-analyzer/crates/hir-expand/src/db.rs
@@ -14,7 +14,7 @@ use syntax::{
use crate::{
ast_id_map::AstIdMap, builtin_attr_macro::pseudo_derive_attr_expansion, fixup,
- hygiene::HygieneFrame, BuiltinAttrExpander, BuiltinDeriveExpander, BuiltinFnLikeExpander,
+ hygiene::HygieneFrame, tt, BuiltinAttrExpander, BuiltinDeriveExpander, BuiltinFnLikeExpander,
ExpandError, ExpandResult, ExpandTo, HirFileId, HirFileIdRepr, MacroCallId, MacroCallKind,
MacroCallLoc, MacroDefId, MacroDefKind, MacroFile, ProcMacroExpander,
};
@@ -25,7 +25,7 @@ use crate::{
/// an error will be emitted.
///
/// Actual max for `analysis-stats .` at some point: 30672.
-static TOKEN_LIMIT: Limit = Limit::new(524_288);
+static TOKEN_LIMIT: Limit = Limit::new(1_048_576);
#[derive(Debug, Clone, Eq, PartialEq)]
pub enum TokenExpander {
@@ -168,12 +168,14 @@ pub fn expand_speculative(
// Attributes may have an input token tree, build the subtree and map for this as well
// then try finding a token id for our token if it is inside this input subtree.
let item = ast::Item::cast(speculative_args.clone())?;
- item.doc_comments_and_attrs().nth(invoc_attr_index as usize).and_then(Either::left)
+ item.doc_comments_and_attrs()
+ .nth(invoc_attr_index.ast_index())
+ .and_then(Either::left)
}?;
match attr.token_tree() {
Some(token_tree) => {
let (mut tree, map) = syntax_node_to_token_tree(attr.token_tree()?.syntax());
- tree.delimiter = None;
+ tree.delimiter = tt::Delimiter::unspecified();
let shift = mbe::Shift::new(&tt);
shift.shift_all(&mut tree);
@@ -208,7 +210,7 @@ pub fn expand_speculative(
// Otherwise the expand query will fetch the non speculative attribute args and pass those instead.
let mut speculative_expansion = match loc.def.kind {
MacroDefKind::ProcMacro(expander, ..) => {
- tt.delimiter = None;
+ tt.delimiter = tt::Delimiter::unspecified();
expander.expand(db, loc.krate, &tt, attr_arg.as_ref())
}
MacroDefKind::BuiltInAttr(BuiltinAttrExpander::Derive, _) => {
@@ -314,13 +316,13 @@ fn macro_arg(
if loc.def.is_proc_macro() {
// proc macros expect their inputs without parentheses, MBEs expect it with them included
- tt.delimiter = None;
+ tt.delimiter = tt::Delimiter::unspecified();
}
-
Some(Arc::new((tt, tmap, fixups.undo_info)))
}
fn censor_for_macro_input(loc: &MacroCallLoc, node: &SyntaxNode) -> FxHashSet<SyntaxNode> {
+ // FIXME: handle `cfg_attr`
(|| {
let censor = match loc.kind {
MacroCallKind::FnLike { .. } => return None,
@@ -328,7 +330,7 @@ fn censor_for_macro_input(loc: &MacroCallLoc, node: &SyntaxNode) -> FxHashSet<Sy
cov_mark::hit!(derive_censoring);
ast::Item::cast(node.clone())?
.attrs()
- .take(derive_attr_index as usize + 1)
+ .take(derive_attr_index.ast_index() + 1)
// FIXME, this resolution should not be done syntactically
// derive is a proper macro now, no longer builtin
// But we do not have resolution at this stage, this means
@@ -343,7 +345,7 @@ fn censor_for_macro_input(loc: &MacroCallLoc, node: &SyntaxNode) -> FxHashSet<Sy
cov_mark::hit!(attribute_macro_attr_censoring);
ast::Item::cast(node.clone())?
.doc_comments_and_attrs()
- .nth(invoc_attr_index as usize)
+ .nth(invoc_attr_index.ast_index())
.and_then(Either::left)
.map(|attr| attr.syntax().clone())
.into_iter()
@@ -476,7 +478,10 @@ fn expand_proc_macro(db: &dyn AstDatabase, id: MacroCallId) -> ExpandResult<tt::
let macro_arg = match db.macro_arg(id) {
Some(it) => it,
None => {
- return ExpandResult::only_err(ExpandError::Other("No arguments for proc-macro".into()))
+ return ExpandResult::with_err(
+ tt::Subtree::empty(),
+ ExpandError::Other("No arguments for proc-macro".into()),
+ )
}
};
diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/eager.rs b/src/tools/rust-analyzer/crates/hir-expand/src/eager.rs
index a1474c44e..dfab7ec92 100644
--- a/src/tools/rust-analyzer/crates/hir-expand/src/eager.rs
+++ b/src/tools/rust-analyzer/crates/hir-expand/src/eager.rs
@@ -108,7 +108,7 @@ pub fn expand_eager_macro(
.value
.token_tree()
.map(|tt| mbe::syntax_node_to_token_tree(tt.syntax()).0)
- .unwrap_or_default();
+ .unwrap_or_else(tt::Subtree::empty);
let ast_map = db.ast_id_map(macro_call.file_id);
let call_id = InFile::new(macro_call.file_id, ast_map.ast_id(&macro_call.value));
@@ -165,9 +165,9 @@ pub fn expand_eager_macro(
}
}
-fn to_subtree(node: &SyntaxNode) -> tt::Subtree {
+fn to_subtree(node: &SyntaxNode) -> crate::tt::Subtree {
let mut subtree = mbe::syntax_node_to_token_tree(node).0;
- subtree.delimiter = None;
+ subtree.delimiter = crate::tt::Delimiter::unspecified();
subtree
}
diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/fixup.rs b/src/tools/rust-analyzer/crates/hir-expand/src/fixup.rs
index 75d364d5f..c811d1c66 100644
--- a/src/tools/rust-analyzer/crates/hir-expand/src/fixup.rs
+++ b/src/tools/rust-analyzer/crates/hir-expand/src/fixup.rs
@@ -9,7 +9,7 @@ use syntax::{
ast::{self, AstNode, HasLoopBody},
match_ast, SyntaxElement, SyntaxKind, SyntaxNode, TextRange,
};
-use tt::Subtree;
+use tt::token_id::Subtree;
/// The result of calculating fixes for a syntax node -- a bunch of changes
/// (appending to and replacing nodes), the information that is needed to
@@ -297,9 +297,11 @@ pub(crate) fn reverse_fixups(
tt.token_trees = tts
.into_iter()
.filter(|tt| match tt {
- tt::TokenTree::Leaf(leaf) => token_map.synthetic_token_id(leaf.id()) != Some(EMPTY_ID),
+ tt::TokenTree::Leaf(leaf) => {
+ token_map.synthetic_token_id(*leaf.span()) != Some(EMPTY_ID)
+ }
tt::TokenTree::Subtree(st) => {
- st.delimiter.map_or(true, |d| token_map.synthetic_token_id(d.id) != Some(EMPTY_ID))
+ token_map.synthetic_token_id(st.delimiter.open) != Some(EMPTY_ID)
}
})
.flat_map(|tt| match tt {
@@ -308,9 +310,9 @@ pub(crate) fn reverse_fixups(
SmallVec::from_const([tt.into()])
}
tt::TokenTree::Leaf(leaf) => {
- if let Some(id) = token_map.synthetic_token_id(leaf.id()) {
+ if let Some(id) = token_map.synthetic_token_id(*leaf.span()) {
let original = undo_info.original[id.0 as usize].clone();
- if original.delimiter.is_none() {
+ if original.delimiter.kind == tt::DelimiterKind::Invisible {
original.token_trees.into()
} else {
SmallVec::from_const([original.into()])
@@ -327,6 +329,8 @@ pub(crate) fn reverse_fixups(
mod tests {
use expect_test::{expect, Expect};
+ use crate::tt;
+
use super::reverse_fixups;
// The following three functions are only meant to check partial structural equivalence of
@@ -341,7 +345,7 @@ mod tests {
}
fn check_subtree_eq(a: &tt::Subtree, b: &tt::Subtree) -> bool {
- a.delimiter.map(|it| it.kind) == b.delimiter.map(|it| it.kind)
+ a.delimiter.kind == b.delimiter.kind
&& a.token_trees.len() == b.token_trees.len()
&& a.token_trees.iter().zip(&b.token_trees).all(|(a, b)| check_tt_eq(a, b))
}
@@ -386,7 +390,7 @@ mod tests {
let (original_as_tt, _) = mbe::syntax_node_to_token_tree(&parsed.syntax_node());
assert!(
check_subtree_eq(&tt, &original_as_tt),
- "different token tree: {tt:?}, {original_as_tt:?}"
+ "different token tree: {tt:?},\n{original_as_tt:?}"
);
}
diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/hygiene.rs b/src/tools/rust-analyzer/crates/hir-expand/src/hygiene.rs
index df1e20256..2300ee9d0 100644
--- a/src/tools/rust-analyzer/crates/hir-expand/src/hygiene.rs
+++ b/src/tools/rust-analyzer/crates/hir-expand/src/hygiene.rs
@@ -128,7 +128,7 @@ struct HygieneInfo {
attr_input_or_mac_def_start: Option<InFile<TextSize>>,
macro_def: Arc<TokenExpander>,
- macro_arg: Arc<(tt::Subtree, mbe::TokenMap, fixup::SyntaxFixupUndoInfo)>,
+ macro_arg: Arc<(crate::tt::Subtree, mbe::TokenMap, fixup::SyntaxFixupUndoInfo)>,
macro_arg_shift: mbe::Shift,
exp_map: Arc<mbe::TokenMap>,
}
@@ -191,7 +191,7 @@ fn make_hygiene_info(
let tt = ast_id
.to_node(db)
.doc_comments_and_attrs()
- .nth(invoc_attr_index as usize)
+ .nth(invoc_attr_index.ast_index())
.and_then(Either::left)?
.token_tree()?;
Some(InFile::new(ast_id.file_id, tt))
diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/lib.rs b/src/tools/rust-analyzer/crates/hir-expand/src/lib.rs
index bc5f9f3b8..a52716cc0 100644
--- a/src/tools/rust-analyzer/crates/hir-expand/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/hir-expand/src/lib.rs
@@ -17,10 +17,13 @@ pub mod proc_macro;
pub mod quote;
pub mod eager;
pub mod mod_path;
+pub mod attrs;
mod fixup;
pub use mbe::{Origin, ValueResult};
+use ::tt::token_id as tt;
+
use std::{fmt, hash::Hash, iter, sync::Arc};
use base_db::{
@@ -37,6 +40,7 @@ use syntax::{
use crate::{
ast_id_map::FileAstId,
+ attrs::AttrId,
builtin_attr_macro::BuiltinAttrExpander,
builtin_derive_macro::BuiltinDeriveExpander,
builtin_fn_macro::{BuiltinFnLikeExpander, EagerExpander},
@@ -51,6 +55,7 @@ pub type ExpandResult<T> = ValueResult<T, ExpandError>;
pub enum ExpandError {
UnresolvedProcMacro(CrateId),
Mbe(mbe::ExpandError),
+ RecursionOverflowPosioned,
Other(Box<str>),
}
@@ -65,6 +70,9 @@ impl fmt::Display for ExpandError {
match self {
ExpandError::UnresolvedProcMacro(_) => f.write_str("unresolved proc-macro"),
ExpandError::Mbe(it) => it.fmt(f),
+ ExpandError::RecursionOverflowPosioned => {
+ f.write_str("overflow expanding the original macro")
+ }
ExpandError::Other(it) => f.write_str(it),
}
}
@@ -114,6 +122,7 @@ pub struct MacroDefId {
pub krate: CrateId,
pub kind: MacroDefKind,
pub local_inner: bool,
+ pub allow_internal_unsafe: bool,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
@@ -145,7 +154,7 @@ pub enum MacroCallKind {
///
/// Outer attributes are counted first, then inner attributes. This does not support
/// out-of-line modules, which may have attributes spread across 2 files!
- derive_attr_index: u32,
+ derive_attr_index: AttrId,
/// Index of the derive macro in the derive attribute
derive_index: u32,
},
@@ -156,7 +165,7 @@ pub enum MacroCallKind {
///
/// Outer attributes are counted first, then inner attributes. This does not support
/// out-of-line modules, which may have attributes spread across 2 files!
- invoc_attr_index: u32,
+ invoc_attr_index: AttrId,
/// Whether this attribute is the `#[derive]` attribute.
is_derive: bool,
},
@@ -261,10 +270,11 @@ impl HirFileId {
});
let attr_input_or_mac_def = def.or_else(|| match loc.kind {
MacroCallKind::Attr { ast_id, invoc_attr_index, .. } => {
+ // FIXME: handle `cfg_attr`
let tt = ast_id
.to_node(db)
.doc_comments_and_attrs()
- .nth(invoc_attr_index as usize)
+ .nth(invoc_attr_index.ast_index())
.and_then(Either::left)?
.token_tree()?;
Some(InFile::new(ast_id.file_id, tt))
@@ -353,6 +363,14 @@ impl HirFileId {
}
}
+ #[inline]
+ pub fn file_id(self) -> Option<FileId> {
+ match self.0 & Self::MACRO_FILE_TAG_MASK {
+ 0 => Some(FileId(self.0)),
+ _ => None,
+ }
+ }
+
fn repr(self) -> HirFileIdRepr {
match self.0 & Self::MACRO_FILE_TAG_MASK {
0 => HirFileIdRepr::FileId(FileId(self.0)),
@@ -397,8 +415,7 @@ impl MacroDefId {
}
}
-// FIXME: attribute indices do not account for `cfg_attr`, which means that we'll strip the whole
-// `cfg_attr` instead of just one of the attributes it expands to
+// FIXME: attribute indices do not account for nested `cfg_attr`
impl MacroCallKind {
/// Returns the file containing the macro invocation.
@@ -419,7 +436,7 @@ impl MacroCallKind {
// FIXME: handle `cfg_attr`
ast_id.with_value(ast_id.to_node(db)).map(|it| {
it.doc_comments_and_attrs()
- .nth(*derive_attr_index as usize)
+ .nth(derive_attr_index.ast_index())
.and_then(|it| match it {
Either::Left(attr) => Some(attr.syntax().clone()),
Either::Right(_) => None,
@@ -431,7 +448,7 @@ impl MacroCallKind {
// FIXME: handle `cfg_attr`
ast_id.with_value(ast_id.to_node(db)).map(|it| {
it.doc_comments_and_attrs()
- .nth(*invoc_attr_index as usize)
+ .nth(invoc_attr_index.ast_index())
.and_then(|it| match it {
Either::Left(attr) => Some(attr.syntax().clone()),
Either::Right(_) => None,
@@ -488,19 +505,21 @@ impl MacroCallKind {
MacroCallKind::FnLike { ast_id, .. } => ast_id.to_node(db).syntax().text_range(),
MacroCallKind::Derive { ast_id, derive_attr_index, .. } => {
// FIXME: should be the range of the macro name, not the whole derive
+ // FIXME: handle `cfg_attr`
ast_id
.to_node(db)
.doc_comments_and_attrs()
- .nth(derive_attr_index as usize)
+ .nth(derive_attr_index.ast_index())
.expect("missing derive")
.expect_left("derive is a doc comment?")
.syntax()
.text_range()
}
+ // FIXME: handle `cfg_attr`
MacroCallKind::Attr { ast_id, invoc_attr_index, .. } => ast_id
.to_node(db)
.doc_comments_and_attrs()
- .nth(invoc_attr_index as usize)
+ .nth(invoc_attr_index.ast_index())
.expect("missing attribute")
.expect_left("attribute macro is a doc comment?")
.syntax()
@@ -592,9 +611,10 @@ impl ExpansionInfo {
let token_range = token.value.text_range();
match &loc.kind {
MacroCallKind::Attr { attr_args, invoc_attr_index, is_derive, .. } => {
+ // FIXME: handle `cfg_attr`
let attr = item
.doc_comments_and_attrs()
- .nth(*invoc_attr_index as usize)
+ .nth(invoc_attr_index.ast_index())
.and_then(Either::left)?;
match attr.token_tree() {
Some(token_tree)
@@ -1031,3 +1051,5 @@ impl ExpandTo {
pub struct UnresolvedMacro {
pub path: ModPath,
}
+
+intern::impl_internable!(ModPath, attrs::AttrInput);
diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/name.rs b/src/tools/rust-analyzer/crates/hir-expand/src/name.rs
index e8b3e312a..c3462beac 100644
--- a/src/tools/rust-analyzer/crates/hir-expand/src/name.rs
+++ b/src/tools/rust-analyzer/crates/hir-expand/src/name.rs
@@ -2,7 +2,7 @@
use std::fmt;
-use syntax::{ast, SmolStr, SyntaxKind};
+use syntax::{ast, utils::is_raw_identifier, SmolStr};
/// `Name` is a wrapper around string, which is used in hir for both references
/// and declarations. In theory, names should also carry hygiene info, but we are
@@ -33,11 +33,6 @@ impl fmt::Display for Name {
}
}
-fn is_raw_identifier(name: &str) -> bool {
- let is_keyword = SyntaxKind::from_keyword(name).is_some();
- is_keyword && !matches!(name, "self" | "crate" | "super" | "Self")
-}
-
impl<'a> fmt::Display for UnescapedName<'a> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match &self.0 .0 {
@@ -133,6 +128,14 @@ impl Name {
}
}
+ /// Returns the text this name represents if it isn't a tuple field.
+ pub fn as_str(&self) -> Option<&str> {
+ match &self.0 {
+ Repr::Text(it) => Some(it),
+ _ => None,
+ }
+ }
+
/// Returns the textual representation of this name as a [`SmolStr`].
/// Prefer using this over [`ToString::to_string`] if possible as this conversion is cheaper in
/// the general case.
@@ -183,7 +186,7 @@ impl AsName for ast::NameOrNameRef {
}
}
-impl AsName for tt::Ident {
+impl<Span> AsName for tt::Ident<Span> {
fn as_name(&self) -> Name {
Name::resolve(&self.text)
}
@@ -339,6 +342,7 @@ pub mod known {
recursion_limit,
feature,
// known methods of lang items
+ call_once,
eq,
ne,
ge,
diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/proc_macro.rs b/src/tools/rust-analyzer/crates/hir-expand/src/proc_macro.rs
index 5afdcc0e6..3f4d2540c 100644
--- a/src/tools/rust-analyzer/crates/hir-expand/src/proc_macro.rs
+++ b/src/tools/rust-analyzer/crates/hir-expand/src/proc_macro.rs
@@ -3,7 +3,7 @@
use base_db::{CrateId, ProcMacroExpansionError, ProcMacroId, ProcMacroKind};
use stdx::never;
-use crate::{db::AstDatabase, ExpandError, ExpandResult};
+use crate::{db::AstDatabase, tt, ExpandError, ExpandResult};
#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
pub struct ProcMacroExpander {
@@ -39,7 +39,10 @@ impl ProcMacroExpander {
Ok(proc_macros) => proc_macros,
Err(_) => {
never!("Non-dummy expander even though there are no proc macros");
- return ExpandResult::only_err(ExpandError::Other("Internal error".into()));
+ return ExpandResult::with_err(
+ tt::Subtree::empty(),
+ ExpandError::Other("Internal error".into()),
+ );
}
};
let proc_macro = match proc_macros.get(id.0 as usize) {
@@ -50,7 +53,10 @@ impl ProcMacroExpander {
proc_macros.len(),
id.0
);
- return ExpandResult::only_err(ExpandError::Other("Internal error".into()));
+ return ExpandResult::with_err(
+ tt::Subtree::empty(),
+ ExpandError::Other("Internal error".into()),
+ );
}
};
@@ -69,13 +75,17 @@ impl ProcMacroExpander {
}
}
ProcMacroExpansionError::System(text)
- | ProcMacroExpansionError::Panic(text) => {
- ExpandResult::only_err(ExpandError::Other(text.into()))
- }
+ | ProcMacroExpansionError::Panic(text) => ExpandResult::with_err(
+ tt::Subtree::empty(),
+ ExpandError::Other(text.into()),
+ ),
},
}
}
- None => ExpandResult::only_err(ExpandError::UnresolvedProcMacro(self.krate)),
+ None => ExpandResult::with_err(
+ tt::Subtree::empty(),
+ ExpandError::UnresolvedProcMacro(self.krate),
+ ),
}
}
}
diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/quote.rs b/src/tools/rust-analyzer/crates/hir-expand/src/quote.rs
index c0a7bc7ca..63586f9da 100644
--- a/src/tools/rust-analyzer/crates/hir-expand/src/quote.rs
+++ b/src/tools/rust-analyzer/crates/hir-expand/src/quote.rs
@@ -9,17 +9,18 @@
#[macro_export]
macro_rules! __quote {
() => {
- Vec::<tt::TokenTree>::new()
+ Vec::<crate::tt::TokenTree>::new()
};
( @SUBTREE $delim:ident $($tt:tt)* ) => {
{
let children = $crate::__quote!($($tt)*);
- tt::Subtree {
- delimiter: Some(tt::Delimiter {
- kind: tt::DelimiterKind::$delim,
- id: tt::TokenId::unspecified(),
- }),
+ crate::tt::Subtree {
+ delimiter: crate::tt::Delimiter {
+ kind: crate::tt::DelimiterKind::$delim,
+ open: crate::tt::TokenId::unspecified(),
+ close: crate::tt::TokenId::unspecified(),
+ },
token_trees: $crate::quote::IntoTt::to_tokens(children),
}
}
@@ -28,10 +29,10 @@ macro_rules! __quote {
( @PUNCT $first:literal ) => {
{
vec![
- tt::Leaf::Punct(tt::Punct {
+ crate::tt::Leaf::Punct(crate::tt::Punct {
char: $first,
- spacing: tt::Spacing::Alone,
- id: tt::TokenId::unspecified(),
+ spacing: crate::tt::Spacing::Alone,
+ span: crate::tt::TokenId::unspecified(),
}).into()
]
}
@@ -40,15 +41,15 @@ macro_rules! __quote {
( @PUNCT $first:literal, $sec:literal ) => {
{
vec![
- tt::Leaf::Punct(tt::Punct {
+ crate::tt::Leaf::Punct(crate::tt::Punct {
char: $first,
- spacing: tt::Spacing::Joint,
- id: tt::TokenId::unspecified(),
+ spacing: crate::tt::Spacing::Joint,
+ span: crate::tt::TokenId::unspecified(),
}).into(),
- tt::Leaf::Punct(tt::Punct {
+ crate::tt::Leaf::Punct(crate::tt::Punct {
char: $sec,
- spacing: tt::Spacing::Alone,
- id: tt::TokenId::unspecified(),
+ spacing: crate::tt::Spacing::Alone,
+ span: crate::tt::TokenId::unspecified(),
}).into()
]
}
@@ -67,7 +68,7 @@ macro_rules! __quote {
( ## $first:ident $($tail:tt)* ) => {
{
- let mut tokens = $first.into_iter().map($crate::quote::ToTokenTree::to_token).collect::<Vec<tt::TokenTree>>();
+ let mut tokens = $first.into_iter().map($crate::quote::ToTokenTree::to_token).collect::<Vec<crate::tt::TokenTree>>();
let mut tail_tokens = $crate::quote::IntoTt::to_tokens($crate::__quote!($($tail)*));
tokens.append(&mut tail_tokens);
tokens
@@ -86,9 +87,9 @@ macro_rules! __quote {
// Ident
( $tt:ident ) => {
vec![ {
- tt::Leaf::Ident(tt::Ident {
+ crate::tt::Leaf::Ident(crate::tt::Ident {
text: stringify!($tt).into(),
- id: tt::TokenId::unspecified(),
+ span: crate::tt::TokenId::unspecified(),
}).into()
}]
};
@@ -127,42 +128,42 @@ macro_rules! quote {
}
pub(crate) trait IntoTt {
- fn to_subtree(self) -> tt::Subtree;
- fn to_tokens(self) -> Vec<tt::TokenTree>;
+ fn to_subtree(self) -> crate::tt::Subtree;
+ fn to_tokens(self) -> Vec<crate::tt::TokenTree>;
}
-impl IntoTt for Vec<tt::TokenTree> {
- fn to_subtree(self) -> tt::Subtree {
- tt::Subtree { delimiter: None, token_trees: self }
+impl IntoTt for Vec<crate::tt::TokenTree> {
+ fn to_subtree(self) -> crate::tt::Subtree {
+ crate::tt::Subtree { delimiter: crate::tt::Delimiter::unspecified(), token_trees: self }
}
- fn to_tokens(self) -> Vec<tt::TokenTree> {
+ fn to_tokens(self) -> Vec<crate::tt::TokenTree> {
self
}
}
-impl IntoTt for tt::Subtree {
- fn to_subtree(self) -> tt::Subtree {
+impl IntoTt for crate::tt::Subtree {
+ fn to_subtree(self) -> crate::tt::Subtree {
self
}
- fn to_tokens(self) -> Vec<tt::TokenTree> {
- vec![tt::TokenTree::Subtree(self)]
+ fn to_tokens(self) -> Vec<crate::tt::TokenTree> {
+ vec![crate::tt::TokenTree::Subtree(self)]
}
}
pub(crate) trait ToTokenTree {
- fn to_token(self) -> tt::TokenTree;
+ fn to_token(self) -> crate::tt::TokenTree;
}
-impl ToTokenTree for tt::TokenTree {
- fn to_token(self) -> tt::TokenTree {
+impl ToTokenTree for crate::tt::TokenTree {
+ fn to_token(self) -> crate::tt::TokenTree {
self
}
}
-impl ToTokenTree for tt::Subtree {
- fn to_token(self) -> tt::TokenTree {
+impl ToTokenTree for crate::tt::Subtree {
+ fn to_token(self) -> crate::tt::TokenTree {
self.into()
}
}
@@ -171,15 +172,15 @@ macro_rules! impl_to_to_tokentrees {
($($ty:ty => $this:ident $im:block);*) => {
$(
impl ToTokenTree for $ty {
- fn to_token($this) -> tt::TokenTree {
- let leaf: tt::Leaf = $im.into();
+ fn to_token($this) -> crate::tt::TokenTree {
+ let leaf: crate::tt::Leaf = $im.into();
leaf.into()
}
}
impl ToTokenTree for &$ty {
- fn to_token($this) -> tt::TokenTree {
- let leaf: tt::Leaf = $im.clone().into();
+ fn to_token($this) -> crate::tt::TokenTree {
+ let leaf: crate::tt::Leaf = $im.clone().into();
leaf.into()
}
}
@@ -188,16 +189,16 @@ macro_rules! impl_to_to_tokentrees {
}
impl_to_to_tokentrees! {
- u32 => self { tt::Literal{text: self.to_string().into(), id: tt::TokenId::unspecified()} };
- usize => self { tt::Literal{text: self.to_string().into(), id: tt::TokenId::unspecified()} };
- i32 => self { tt::Literal{text: self.to_string().into(), id: tt::TokenId::unspecified()} };
- bool => self { tt::Ident{text: self.to_string().into(), id: tt::TokenId::unspecified()} };
- tt::Leaf => self { self };
- tt::Literal => self { self };
- tt::Ident => self { self };
- tt::Punct => self { self };
- &str => self { tt::Literal{text: format!("\"{}\"", self.escape_default()).into(), id: tt::TokenId::unspecified()}};
- String => self { tt::Literal{text: format!("\"{}\"", self.escape_default()).into(), id: tt::TokenId::unspecified()}}
+ u32 => self { crate::tt::Literal{text: self.to_string().into(), span: crate::tt::TokenId::unspecified()} };
+ usize => self { crate::tt::Literal{text: self.to_string().into(), span: crate::tt::TokenId::unspecified()} };
+ i32 => self { crate::tt::Literal{text: self.to_string().into(), span: crate::tt::TokenId::unspecified()} };
+ bool => self { crate::tt::Ident{text: self.to_string().into(), span: crate::tt::TokenId::unspecified()} };
+ crate::tt::Leaf => self { self };
+ crate::tt::Literal => self { self };
+ crate::tt::Ident => self { self };
+ crate::tt::Punct => self { self };
+ &str => self { crate::tt::Literal{text: format!("\"{}\"", self.escape_default()).into(), span: crate::tt::TokenId::unspecified()}};
+ String => self { crate::tt::Literal{text: format!("\"{}\"", self.escape_default()).into(), span: crate::tt::TokenId::unspecified()}}
}
#[cfg(test)]
@@ -223,8 +224,8 @@ mod tests {
assert_eq!(quote!(#s).to_string(), "\"hello\"");
}
- fn mk_ident(name: &str) -> tt::Ident {
- tt::Ident { text: name.into(), id: tt::TokenId::unspecified() }
+ fn mk_ident(name: &str) -> crate::tt::Ident {
+ crate::tt::Ident { text: name.into(), span: crate::tt::TokenId::unspecified() }
}
#[test]
@@ -234,7 +235,7 @@ mod tests {
let quoted = quote!(#a);
assert_eq!(quoted.to_string(), "hello");
let t = format!("{quoted:?}");
- assert_eq!(t, "SUBTREE $\n IDENT hello 4294967295");
+ assert_eq!(t, "SUBTREE $$ 4294967295 4294967295\n IDENT hello 4294967295");
}
#[test]
@@ -263,11 +264,12 @@ mod tests {
let fields = [mk_ident("name"), mk_ident("id")];
let fields = fields.iter().flat_map(|it| quote!(#it: self.#it.clone(), ).token_trees);
- let list = tt::Subtree {
- delimiter: Some(tt::Delimiter {
- kind: tt::DelimiterKind::Brace,
- id: tt::TokenId::unspecified(),
- }),
+ let list = crate::tt::Subtree {
+ delimiter: crate::tt::Delimiter {
+ kind: crate::tt::DelimiterKind::Brace,
+ open: crate::tt::TokenId::unspecified(),
+ close: crate::tt::TokenId::unspecified(),
+ },
token_trees: fields.collect(),
};
diff --git a/src/tools/rust-analyzer/crates/hir-ty/Cargo.toml b/src/tools/rust-analyzer/crates/hir-ty/Cargo.toml
index ae837ac6d..a8b8d5222 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/hir-ty/Cargo.toml
@@ -2,9 +2,11 @@
name = "hir-ty"
version = "0.0.0"
description = "TBD"
-license = "MIT OR Apache-2.0"
-edition = "2021"
-rust-version = "1.65"
+
+authors.workspace = true
+edition.workspace = true
+license.workspace = true
+rust-version.workspace = true
[lib]
doctest = false
@@ -14,7 +16,7 @@ cov-mark = "2.0.0-pre.1"
itertools = "0.10.5"
arrayvec = "0.7.2"
bitflags = "1.3.2"
-smallvec = "1.10.0"
+smallvec.workspace = true
ena = "0.14.0"
tracing = "0.1.35"
rustc-hash = "1.1.0"
@@ -24,20 +26,21 @@ chalk-ir = "0.88.0"
chalk-recursive = { version = "0.88.0", default-features = false }
chalk-derive = "0.88.0"
la-arena = { version = "0.3.0", path = "../../lib/la-arena" }
-once_cell = "1.15.0"
+once_cell = "1.17.0"
typed-arena = "2.0.1"
rustc_index = { version = "0.0.20221221", package = "hkalbasi-rustc-ap-rustc_index", default-features = false }
-stdx = { path = "../stdx", version = "0.0.0" }
-hir-def = { path = "../hir-def", version = "0.0.0" }
-hir-expand = { path = "../hir-expand", version = "0.0.0" }
-base-db = { path = "../base-db", version = "0.0.0" }
-profile = { path = "../profile", version = "0.0.0" }
-syntax = { path = "../syntax", version = "0.0.0" }
-limit = { path = "../limit", version = "0.0.0" }
+# local deps
+stdx.workspace = true
+intern.workspace = true
+hir-def.workspace = true
+hir-expand.workspace = true
+base-db.workspace = true
+profile.workspace = true
+syntax.workspace = true
+limit.workspace = true
[dev-dependencies]
-test-utils = { path = "../test-utils" }
expect-test = "1.4.0"
tracing = "0.1.35"
tracing-subscriber = { version = "0.3.16", default-features = false, features = [
@@ -45,3 +48,7 @@ tracing-subscriber = { version = "0.3.16", default-features = false, features =
"registry",
] }
tracing-tree = "0.2.1"
+project-model = { path = "../project-model" }
+
+# local deps
+test-utils.workspace = true
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/autoderef.rs b/src/tools/rust-analyzer/crates/hir-ty/src/autoderef.rs
index cbcf8f74c..58744dd0c 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/autoderef.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/autoderef.rs
@@ -6,9 +6,9 @@
use std::sync::Arc;
use chalk_ir::cast::Cast;
+use hir_def::lang_item::LangItem;
use hir_expand::name::name;
use limit::Limit;
-use syntax::SmolStr;
use crate::{
db::HirDatabase, infer::unify::InferenceTable, Canonical, Goal, Interner, ProjectionTyExt,
@@ -17,11 +17,13 @@ use crate::{
static AUTODEREF_RECURSION_LIMIT: Limit = Limit::new(10);
+#[derive(Debug)]
pub(crate) enum AutoderefKind {
Builtin,
Overloaded,
}
+#[derive(Debug)]
pub(crate) struct Autoderef<'a, 'db> {
pub(crate) table: &'a mut InferenceTable<'db>,
ty: Ty,
@@ -117,9 +119,8 @@ fn deref_by_trait(table: &mut InferenceTable<'_>, ty: Ty) -> Option<Ty> {
}
let db = table.db;
- let deref_trait = db
- .lang_item(table.trait_env.krate, SmolStr::new_inline("deref"))
- .and_then(|l| l.as_trait())?;
+ let deref_trait =
+ db.lang_item(table.trait_env.krate, LangItem::Deref).and_then(|l| l.as_trait())?;
let target = db.trait_data(deref_trait).associated_type_by_name(&name![Target])?;
let projection = {
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/builder.rs b/src/tools/rust-analyzer/crates/hir-ty/src/builder.rs
index d5ef0c22d..8faef7bf7 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/builder.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/builder.rs
@@ -63,7 +63,7 @@ impl<D> TyBuilder<D> {
}
fn build_internal(self) -> (D, Substitution) {
- assert_eq!(self.vec.len(), self.param_kinds.len());
+ assert_eq!(self.vec.len(), self.param_kinds.len(), "{:?}", &self.param_kinds);
for (a, e) in self.vec.iter().zip(self.param_kinds.iter()) {
self.assert_match_kind(a, e);
}
@@ -282,6 +282,21 @@ impl TyBuilder<Tuple> {
let (Tuple(size), subst) = self.build_internal();
TyKind::Tuple(size, subst).intern(Interner)
}
+
+ pub fn tuple_with<I>(elements: I) -> Ty
+ where
+ I: IntoIterator<Item = Ty>,
+ <I as IntoIterator>::IntoIter: ExactSizeIterator,
+ {
+ let elements = elements.into_iter();
+ let len = elements.len();
+ let mut b =
+ TyBuilder::new(Tuple(len), iter::repeat(ParamKind::Type).take(len).collect(), None);
+ for e in elements {
+ b = b.push(e);
+ }
+ b.build()
+ }
}
impl TyBuilder<TraitId> {
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/chalk_db.rs b/src/tools/rust-analyzer/crates/hir-ty/src/chalk_db.rs
index 1c2b8de7f..6989e9fb9 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/chalk_db.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/chalk_db.rs
@@ -3,7 +3,6 @@
use std::sync::Arc;
use cov_mark::hit;
-use syntax::SmolStr;
use tracing::debug;
use chalk_ir::{cast::Cast, fold::shift::Shift, CanonicalVarKinds};
@@ -12,7 +11,7 @@ use chalk_solve::rust_ir::{self, OpaqueTyDatumBound, WellKnownTrait};
use base_db::CrateId;
use hir_def::{
expr::Movability,
- lang_item::{lang_attr, LangItemTarget},
+ lang_item::{lang_attr, LangItem, LangItemTarget},
AssocItemId, GenericDefId, HasModule, ItemContainerId, Lookup, ModuleId, TypeAliasId,
};
use hir_expand::name::name;
@@ -182,9 +181,9 @@ impl<'a> chalk_solve::RustIrDatabase<Interner> for ChalkContext<'a> {
&self,
well_known_trait: rust_ir::WellKnownTrait,
) -> Option<chalk_ir::TraitId<Interner>> {
- let lang_attr = lang_attr_from_well_known_trait(well_known_trait);
+ let lang_attr = lang_item_from_well_known_trait(well_known_trait);
let trait_ = match self.db.lang_item(self.krate, lang_attr.into()) {
- Some(LangItemTarget::TraitId(trait_)) => trait_,
+ Some(LangItemTarget::Trait(trait_)) => trait_,
_ => return None,
};
Some(to_chalk_trait_id(trait_))
@@ -206,7 +205,7 @@ impl<'a> chalk_solve::RustIrDatabase<Interner> for ChalkContext<'a> {
.return_type_impl_traits(func)
.expect("impl trait id without impl traits");
let (datas, binders) = (*datas).as_ref().into_value_and_skipped_binders();
- let data = &datas.impl_traits[idx as usize];
+ let data = &datas.impl_traits[idx];
let bound = OpaqueTyDatumBound {
bounds: make_single_type_binders(data.bounds.skip_binders().to_vec()),
where_clauses: chalk_ir::Binders::empty(Interner, vec![]),
@@ -216,7 +215,7 @@ impl<'a> chalk_solve::RustIrDatabase<Interner> for ChalkContext<'a> {
crate::ImplTraitId::AsyncBlockTypeImplTrait(..) => {
if let Some((future_trait, future_output)) = self
.db
- .lang_item(self.krate, SmolStr::new_inline("future_trait"))
+ .lang_item(self.krate, LangItem::Future)
.and_then(|item| item.as_trait())
.and_then(|trait_| {
let alias =
@@ -246,7 +245,7 @@ impl<'a> chalk_solve::RustIrDatabase<Interner> for ChalkContext<'a> {
binder.push(crate::wrap_empty_binders(impl_bound));
let sized_trait = self
.db
- .lang_item(self.krate, SmolStr::new_inline("sized"))
+ .lang_item(self.krate, LangItem::Sized)
.and_then(|item| item.as_trait());
if let Some(sized_trait_) = sized_trait {
let sized_bound = WhereClause::Implemented(TraitRef {
@@ -493,7 +492,7 @@ pub(crate) fn associated_ty_data_query(
if !ctx.unsized_types.borrow().contains(&self_ty) {
let sized_trait = db
- .lang_item(resolver.krate(), SmolStr::new_inline("sized"))
+ .lang_item(resolver.krate(), LangItem::Sized)
.and_then(|lang_item| lang_item.as_trait().map(to_chalk_trait_id));
let sized_bound = sized_trait.into_iter().map(|sized_trait| {
let trait_bound =
@@ -541,8 +540,8 @@ pub(crate) fn trait_datum_query(
let where_clauses = convert_where_clauses(db, trait_.into(), &bound_vars);
let associated_ty_ids = trait_data.associated_types().map(to_assoc_type_id).collect();
let trait_datum_bound = rust_ir::TraitDatumBound { where_clauses };
- let well_known =
- lang_attr(db.upcast(), trait_).and_then(|name| well_known_trait_from_lang_attr(&name));
+ let well_known = lang_attr(db.upcast(), trait_)
+ .and_then(|name| well_known_trait_from_lang_item(LangItem::from_str(&name)?));
let trait_datum = TraitDatum {
id: trait_id,
binders: make_binders(db, &generic_params, trait_datum_bound),
@@ -553,42 +552,42 @@ pub(crate) fn trait_datum_query(
Arc::new(trait_datum)
}
-fn well_known_trait_from_lang_attr(name: &str) -> Option<WellKnownTrait> {
- Some(match name {
- "clone" => WellKnownTrait::Clone,
- "coerce_unsized" => WellKnownTrait::CoerceUnsized,
- "copy" => WellKnownTrait::Copy,
- "discriminant_kind" => WellKnownTrait::DiscriminantKind,
- "dispatch_from_dyn" => WellKnownTrait::DispatchFromDyn,
- "drop" => WellKnownTrait::Drop,
- "fn" => WellKnownTrait::Fn,
- "fn_mut" => WellKnownTrait::FnMut,
- "fn_once" => WellKnownTrait::FnOnce,
- "generator" => WellKnownTrait::Generator,
- "sized" => WellKnownTrait::Sized,
- "unpin" => WellKnownTrait::Unpin,
- "unsize" => WellKnownTrait::Unsize,
- "tuple_trait" => WellKnownTrait::Tuple,
+fn well_known_trait_from_lang_item(item: LangItem) -> Option<WellKnownTrait> {
+ Some(match item {
+ LangItem::Clone => WellKnownTrait::Clone,
+ LangItem::CoerceUnsized => WellKnownTrait::CoerceUnsized,
+ LangItem::Copy => WellKnownTrait::Copy,
+ LangItem::DiscriminantKind => WellKnownTrait::DiscriminantKind,
+ LangItem::DispatchFromDyn => WellKnownTrait::DispatchFromDyn,
+ LangItem::Drop => WellKnownTrait::Drop,
+ LangItem::Fn => WellKnownTrait::Fn,
+ LangItem::FnMut => WellKnownTrait::FnMut,
+ LangItem::FnOnce => WellKnownTrait::FnOnce,
+ LangItem::Generator => WellKnownTrait::Generator,
+ LangItem::Sized => WellKnownTrait::Sized,
+ LangItem::Unpin => WellKnownTrait::Unpin,
+ LangItem::Unsize => WellKnownTrait::Unsize,
+ LangItem::Tuple => WellKnownTrait::Tuple,
_ => return None,
})
}
-fn lang_attr_from_well_known_trait(attr: WellKnownTrait) -> &'static str {
- match attr {
- WellKnownTrait::Clone => "clone",
- WellKnownTrait::CoerceUnsized => "coerce_unsized",
- WellKnownTrait::Copy => "copy",
- WellKnownTrait::DiscriminantKind => "discriminant_kind",
- WellKnownTrait::DispatchFromDyn => "dispatch_from_dyn",
- WellKnownTrait::Drop => "drop",
- WellKnownTrait::Fn => "fn",
- WellKnownTrait::FnMut => "fn_mut",
- WellKnownTrait::FnOnce => "fn_once",
- WellKnownTrait::Generator => "generator",
- WellKnownTrait::Sized => "sized",
- WellKnownTrait::Tuple => "tuple_trait",
- WellKnownTrait::Unpin => "unpin",
- WellKnownTrait::Unsize => "unsize",
+fn lang_item_from_well_known_trait(trait_: WellKnownTrait) -> LangItem {
+ match trait_ {
+ WellKnownTrait::Clone => LangItem::Clone,
+ WellKnownTrait::CoerceUnsized => LangItem::CoerceUnsized,
+ WellKnownTrait::Copy => LangItem::Copy,
+ WellKnownTrait::DiscriminantKind => LangItem::DiscriminantKind,
+ WellKnownTrait::DispatchFromDyn => LangItem::DispatchFromDyn,
+ WellKnownTrait::Drop => LangItem::Drop,
+ WellKnownTrait::Fn => LangItem::Fn,
+ WellKnownTrait::FnMut => LangItem::FnMut,
+ WellKnownTrait::FnOnce => LangItem::FnOnce,
+ WellKnownTrait::Generator => LangItem::Generator,
+ WellKnownTrait::Sized => LangItem::Sized,
+ WellKnownTrait::Tuple => LangItem::Tuple,
+ WellKnownTrait::Unpin => LangItem::Unpin,
+ WellKnownTrait::Unsize => LangItem::Unsize,
}
}
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/chalk_ext.rs b/src/tools/rust-analyzer/crates/hir-ty/src/chalk_ext.rs
index 996b42f5b..45c975dfc 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/chalk_ext.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/chalk_ext.rs
@@ -1,13 +1,13 @@
//! Various extensions traits for Chalk types.
-use chalk_ir::{FloatTy, IntTy, Mutability, Scalar, UintTy};
+use chalk_ir::{FloatTy, IntTy, Mutability, Scalar, TyVariableKind, UintTy};
use hir_def::{
builtin_type::{BuiltinFloat, BuiltinInt, BuiltinType, BuiltinUint},
generics::TypeOrConstParamData,
+ lang_item::LangItem,
type_ref::Rawness,
FunctionId, GenericDefId, HasModule, ItemContainerId, Lookup, TraitId,
};
-use syntax::SmolStr;
use crate::{
db::HirDatabase, from_assoc_type_id, from_chalk_trait_id, from_foreign_def_id,
@@ -18,6 +18,8 @@ use crate::{
pub trait TyExt {
fn is_unit(&self) -> bool;
+ fn is_integral(&self) -> bool;
+ fn is_floating_point(&self) -> bool;
fn is_never(&self) -> bool;
fn is_unknown(&self) -> bool;
fn is_ty_var(&self) -> bool;
@@ -51,6 +53,21 @@ impl TyExt for Ty {
matches!(self.kind(Interner), TyKind::Tuple(0, _))
}
+ fn is_integral(&self) -> bool {
+ matches!(
+ self.kind(Interner),
+ TyKind::Scalar(Scalar::Int(_) | Scalar::Uint(_))
+ | TyKind::InferenceVar(_, TyVariableKind::Integer)
+ )
+ }
+
+ fn is_floating_point(&self) -> bool {
+ matches!(
+ self.kind(Interner),
+ TyKind::Scalar(Scalar::Float(_)) | TyKind::InferenceVar(_, TyVariableKind::Float)
+ )
+ }
+
fn is_never(&self) -> bool {
matches!(self.kind(Interner), TyKind::Never)
}
@@ -197,9 +214,8 @@ impl TyExt for Ty {
match db.lookup_intern_impl_trait_id((*opaque_ty_id).into()) {
ImplTraitId::AsyncBlockTypeImplTrait(def, _expr) => {
let krate = def.module(db.upcast()).krate();
- if let Some(future_trait) = db
- .lang_item(krate, SmolStr::new_inline("future_trait"))
- .and_then(|item| item.as_trait())
+ if let Some(future_trait) =
+ db.lang_item(krate, LangItem::Future).and_then(|item| item.as_trait())
{
// This is only used by type walking.
// Parameters will be walked outside, and projection predicate is not used.
@@ -218,9 +234,8 @@ impl TyExt for Ty {
}
ImplTraitId::ReturnTypeImplTrait(func, idx) => {
db.return_type_impl_traits(func).map(|it| {
- let data = (*it)
- .as_ref()
- .map(|rpit| rpit.impl_traits[idx as usize].bounds.clone());
+ let data =
+ (*it).as_ref().map(|rpit| rpit.impl_traits[idx].bounds.clone());
data.substitute(Interner, &subst).into_value_and_skipped_binders().0
})
}
@@ -231,9 +246,8 @@ impl TyExt for Ty {
{
ImplTraitId::ReturnTypeImplTrait(func, idx) => {
db.return_type_impl_traits(func).map(|it| {
- let data = (*it)
- .as_ref()
- .map(|rpit| rpit.impl_traits[idx as usize].bounds.clone());
+ let data =
+ (*it).as_ref().map(|rpit| rpit.impl_traits[idx].bounds.clone());
data.substitute(Interner, &opaque_ty.substitution)
})
}
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/db.rs b/src/tools/rust-analyzer/crates/hir-ty/src/db.rs
index 54b244620..d45e2a943 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/db.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/db.rs
@@ -65,7 +65,7 @@ pub trait HirDatabase: DefDatabase + Upcast<dyn DefDatabase> {
fn layout_of_adt(&self, def: AdtId, subst: Substitution) -> Result<Layout, LayoutError>;
#[salsa::invoke(crate::layout::target_data_layout_query)]
- fn target_data_layout(&self, krate: CrateId) -> Arc<TargetDataLayout>;
+ fn target_data_layout(&self, krate: CrateId) -> Option<Arc<TargetDataLayout>>;
#[salsa::invoke(crate::lower::callable_item_sig)]
fn callable_item_signature(&self, def: CallableDefId) -> PolyFnSig;
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/decl_check/case_conv.rs b/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/decl_check/case_conv.rs
index 88d607194..2c1368962 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/decl_check/case_conv.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/decl_check/case_conv.rs
@@ -162,6 +162,7 @@ mod tests {
check(to_lower_snake_case, "a", expect![[""]]);
check(to_lower_snake_case, "abc", expect![[""]]);
check(to_lower_snake_case, "foo__bar", expect![["foo_bar"]]);
+ check(to_lower_snake_case, "Δ", expect!["δ"]);
}
#[test]
@@ -195,5 +196,6 @@ mod tests {
check(to_upper_snake_case, "X86_64", expect![[""]]);
check(to_upper_snake_case, "FOO_BAr", expect![["FOO_BAR"]]);
check(to_upper_snake_case, "FOO__BAR", expect![["FOO_BAR"]]);
+ check(to_upper_snake_case, "ß", expect!["SS"]);
}
}
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/expr.rs b/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/expr.rs
index c8df4c796..3286dcb5a 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/expr.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/expr.rs
@@ -5,7 +5,9 @@
use std::fmt;
use std::sync::Arc;
-use hir_def::{path::path, resolver::HasResolver, AdtId, AssocItemId, DefWithBodyId, HasModule};
+use hir_def::lang_item::LangItem;
+use hir_def::{resolver::HasResolver, AdtId, AssocItemId, DefWithBodyId, HasModule};
+use hir_def::{ItemContainerId, Lookup};
use hir_expand::name;
use itertools::Either;
use itertools::Itertools;
@@ -245,26 +247,25 @@ struct FilterMapNextChecker {
impl FilterMapNextChecker {
fn new(resolver: &hir_def::resolver::Resolver, db: &dyn HirDatabase) -> Self {
// Find and store the FunctionIds for Iterator::filter_map and Iterator::next
- let iterator_path = path![core::iter::Iterator];
- let mut filter_map_function_id = None;
- let mut next_function_id = None;
-
- if let Some(iterator_trait_id) = resolver.resolve_known_trait(db.upcast(), &iterator_path) {
- let iterator_trait_items = &db.trait_data(iterator_trait_id).items;
- for item in iterator_trait_items.iter() {
- if let (name, AssocItemId::FunctionId(id)) = item {
- if *name == name![filter_map] {
- filter_map_function_id = Some(*id);
+ let (next_function_id, filter_map_function_id) = match db
+ .lang_item(resolver.krate(), LangItem::IteratorNext)
+ .and_then(|it| it.as_function())
+ {
+ Some(next_function_id) => (
+ Some(next_function_id),
+ match next_function_id.lookup(db.upcast()).container {
+ ItemContainerId::TraitId(iterator_trait_id) => {
+ let iterator_trait_items = &db.trait_data(iterator_trait_id).items;
+ iterator_trait_items.iter().find_map(|(name, it)| match it {
+ &AssocItemId::FunctionId(id) if *name == name![filter_map] => Some(id),
+ _ => None,
+ })
}
- if *name == name![next] {
- next_function_id = Some(*id);
- }
- }
- if filter_map_function_id.is_some() && next_function_id.is_some() {
- break;
- }
- }
- }
+ _ => None,
+ },
+ ),
+ None => (None, None),
+ };
Self { filter_map_function_id, next_function_id, prev_filter_map_expr_id: None }
}
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/display.rs b/src/tools/rust-analyzer/crates/hir-ty/src/display.rs
index 66e813eed..b22064d8c 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/display.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/display.rs
@@ -11,17 +11,17 @@ use hir_def::{
db::DefDatabase,
find_path,
generics::{TypeOrConstParamData, TypeParamProvenance},
- intern::{Internable, Interned},
item_scope::ItemInNs,
+ lang_item::{LangItem, LangItemTarget},
path::{Path, PathKind},
type_ref::{ConstScalar, TraitBoundModifier, TypeBound, TypeRef},
visibility::Visibility,
HasModule, ItemContainerId, Lookup, ModuleDefId, ModuleId, TraitId,
};
use hir_expand::{hygiene::Hygiene, name::Name};
+use intern::{Internable, Interned};
use itertools::Itertools;
use smallvec::SmallVec;
-use syntax::SmolStr;
use crate::{
db::HirDatabase,
@@ -325,7 +325,7 @@ impl HirDisplay for ProjectionTy {
let trait_ref = self.trait_ref(f.db);
write!(f, "<")?;
- fmt_trait_ref(&trait_ref, f, true)?;
+ fmt_trait_ref(f, &trait_ref, true)?;
write!(f, ">::{}", f.db.type_alias_data(from_assoc_type_id(self.associated_ty_id)).name)?;
let proj_params_count =
self.substitution.len(Interner) - trait_ref.substitution.len(Interner);
@@ -383,7 +383,10 @@ impl HirDisplay for BoundVar {
}
impl HirDisplay for Ty {
- fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> {
+ fn hir_fmt(
+ &self,
+ f @ &mut HirFormatter { db, .. }: &mut HirFormatter<'_>,
+ ) -> Result<(), HirDisplayError> {
if f.should_truncate() {
return write!(f, "{TYPE_HINT_TRUNCATION}");
}
@@ -434,7 +437,7 @@ impl HirDisplay for Ty {
bounds.iter().any(|bound| {
if let WhereClause::Implemented(trait_ref) = bound.skip_binders() {
let trait_ = trait_ref.hir_trait_id();
- fn_traits(f.db.upcast(), trait_).any(|it| it == trait_)
+ fn_traits(db.upcast(), trait_).any(|it| it == trait_)
} else {
false
}
@@ -450,22 +453,20 @@ impl HirDisplay for Ty {
substitution: parameters,
}))
| TyKind::OpaqueType(opaque_ty_id, parameters) => {
- let impl_trait_id =
- f.db.lookup_intern_impl_trait_id((*opaque_ty_id).into());
+ let impl_trait_id = db.lookup_intern_impl_trait_id((*opaque_ty_id).into());
if let ImplTraitId::ReturnTypeImplTrait(func, idx) = impl_trait_id {
- let datas =
- f.db.return_type_impl_traits(func)
- .expect("impl trait id without data");
- let data = (*datas)
- .as_ref()
- .map(|rpit| rpit.impl_traits[idx as usize].bounds.clone());
+ let datas = db
+ .return_type_impl_traits(func)
+ .expect("impl trait id without data");
+ let data =
+ (*datas).as_ref().map(|rpit| rpit.impl_traits[idx].bounds.clone());
let bounds = data.substitute(Interner, parameters);
let mut len = bounds.skip_binders().len();
// Don't count Sized but count when it absent
// (i.e. when explicit ?Sized bound is set).
let default_sized = SizedByDefault::Sized {
- anchor: func.lookup(f.db.upcast()).module(f.db.upcast()).krate(),
+ anchor: func.lookup(db.upcast()).module(db.upcast()).krate(),
};
let sized_bounds = bounds
.skip_binders()
@@ -476,7 +477,7 @@ impl HirDisplay for Ty {
WhereClause::Implemented(trait_ref)
if default_sized.is_sized_trait(
trait_ref.hir_trait_id(),
- f.db.upcast(),
+ db.upcast(),
),
)
})
@@ -524,19 +525,19 @@ impl HirDisplay for Ty {
sig.hir_fmt(f)?;
}
TyKind::FnDef(def, parameters) => {
- let def = from_chalk(f.db, *def);
- let sig = f.db.callable_item_signature(def).substitute(Interner, parameters);
+ let def = from_chalk(db, *def);
+ let sig = db.callable_item_signature(def).substitute(Interner, parameters);
+ f.start_location_link(def.into());
match def {
- CallableDefId::FunctionId(ff) => {
- write!(f, "fn {}", f.db.function_data(ff).name)?
- }
- CallableDefId::StructId(s) => write!(f, "{}", f.db.struct_data(s).name)?,
+ CallableDefId::FunctionId(ff) => write!(f, "fn {}", db.function_data(ff).name)?,
+ CallableDefId::StructId(s) => write!(f, "{}", db.struct_data(s).name)?,
CallableDefId::EnumVariantId(e) => {
- write!(f, "{}", f.db.enum_data(e.parent).variants[e.local_id].name)?
+ write!(f, "{}", db.enum_data(e.parent).variants[e.local_id].name)?
}
};
+ f.end_location_link();
if parameters.len(Interner) > 0 {
- let generics = generics(f.db.upcast(), def.into());
+ let generics = generics(db.upcast(), def.into());
let (parent_params, self_param, type_params, const_params, _impl_trait_params) =
generics.provenance_split();
let total_len = parent_params + self_param + type_params + const_params;
@@ -568,15 +569,15 @@ impl HirDisplay for Ty {
match f.display_target {
DisplayTarget::Diagnostics | DisplayTarget::Test => {
let name = match *def_id {
- hir_def::AdtId::StructId(it) => f.db.struct_data(it).name.clone(),
- hir_def::AdtId::UnionId(it) => f.db.union_data(it).name.clone(),
- hir_def::AdtId::EnumId(it) => f.db.enum_data(it).name.clone(),
+ hir_def::AdtId::StructId(it) => db.struct_data(it).name.clone(),
+ hir_def::AdtId::UnionId(it) => db.union_data(it).name.clone(),
+ hir_def::AdtId::EnumId(it) => db.enum_data(it).name.clone(),
};
write!(f, "{name}")?;
}
DisplayTarget::SourceCode { module_id } => {
if let Some(path) = find_path::find_path(
- f.db.upcast(),
+ db.upcast(),
ItemInNs::Types((*def_id).into()),
module_id,
false,
@@ -596,8 +597,8 @@ impl HirDisplay for Ty {
|| f.omit_verbose_types()
{
match self
- .as_generic_def(f.db)
- .map(|generic_def_id| f.db.generic_defaults(generic_def_id))
+ .as_generic_def(db)
+ .map(|generic_def_id| db.generic_defaults(generic_def_id))
.filter(|defaults| !defaults.is_empty())
{
None => parameters.as_slice(Interner),
@@ -669,16 +670,23 @@ impl HirDisplay for Ty {
}
TyKind::AssociatedType(assoc_type_id, parameters) => {
let type_alias = from_assoc_type_id(*assoc_type_id);
- let trait_ = match type_alias.lookup(f.db.upcast()).container {
+ let trait_ = match type_alias.lookup(db.upcast()).container {
ItemContainerId::TraitId(it) => it,
_ => panic!("not an associated type"),
};
- let trait_ = f.db.trait_data(trait_);
- let type_alias_data = f.db.type_alias_data(type_alias);
+ let trait_data = db.trait_data(trait_);
+ let type_alias_data = db.type_alias_data(type_alias);
// Use placeholder associated types when the target is test (https://rust-lang.github.io/chalk/book/clauses/type_equality.html#placeholder-associated-types)
if f.display_target.is_test() {
- write!(f, "{}::{}", trait_.name, type_alias_data.name)?;
+ f.start_location_link(trait_.into());
+ write!(f, "{}", trait_data.name)?;
+ f.end_location_link();
+ write!(f, "::")?;
+
+ f.start_location_link(type_alias.into());
+ write!(f, "{}", type_alias_data.name)?;
+ f.end_location_link();
// Note that the generic args for the associated type come before those for the
// trait (including the self type).
// FIXME: reconsider the generic args order upon formatting?
@@ -697,30 +705,54 @@ impl HirDisplay for Ty {
}
}
TyKind::Foreign(type_alias) => {
- let type_alias = f.db.type_alias_data(from_foreign_def_id(*type_alias));
+ let alias = from_foreign_def_id(*type_alias);
+ let type_alias = db.type_alias_data(alias);
+ f.start_location_link(alias.into());
write!(f, "{}", type_alias.name)?;
+ f.end_location_link();
}
TyKind::OpaqueType(opaque_ty_id, parameters) => {
- let impl_trait_id = f.db.lookup_intern_impl_trait_id((*opaque_ty_id).into());
+ let impl_trait_id = db.lookup_intern_impl_trait_id((*opaque_ty_id).into());
match impl_trait_id {
ImplTraitId::ReturnTypeImplTrait(func, idx) => {
let datas =
- f.db.return_type_impl_traits(func).expect("impl trait id without data");
- let data = (*datas)
- .as_ref()
- .map(|rpit| rpit.impl_traits[idx as usize].bounds.clone());
+ db.return_type_impl_traits(func).expect("impl trait id without data");
+ let data =
+ (*datas).as_ref().map(|rpit| rpit.impl_traits[idx].bounds.clone());
let bounds = data.substitute(Interner, &parameters);
- let krate = func.lookup(f.db.upcast()).module(f.db.upcast()).krate();
+ let krate = func.lookup(db.upcast()).module(db.upcast()).krate();
write_bounds_like_dyn_trait_with_prefix(
+ f,
"impl",
bounds.skip_binders(),
SizedByDefault::Sized { anchor: krate },
- f,
)?;
// FIXME: it would maybe be good to distinguish this from the alias type (when debug printing), and to show the substitution
}
- ImplTraitId::AsyncBlockTypeImplTrait(..) => {
- write!(f, "impl Future<Output = ")?;
+ ImplTraitId::AsyncBlockTypeImplTrait(body, ..) => {
+ let future_trait = db
+ .lang_item(body.module(db.upcast()).krate(), LangItem::Future)
+ .and_then(LangItemTarget::as_trait);
+ let output = future_trait.and_then(|t| {
+ db.trait_data(t).associated_type_by_name(&hir_expand::name!(Output))
+ });
+ write!(f, "impl ")?;
+ if let Some(t) = future_trait {
+ f.start_location_link(t.into());
+ }
+ write!(f, "Future")?;
+ if let Some(_) = future_trait {
+ f.end_location_link();
+ }
+ write!(f, "<")?;
+ if let Some(t) = output {
+ f.start_location_link(t.into());
+ }
+ write!(f, "Output")?;
+ if let Some(_) = output {
+ f.end_location_link();
+ }
+ write!(f, " = ")?;
parameters.at(Interner, 0).hir_fmt(f)?;
write!(f, ">")?;
}
@@ -732,7 +764,7 @@ impl HirDisplay for Ty {
DisplaySourceCodeError::Closure,
));
}
- let sig = substs.at(Interner, 0).assert_ty_ref(Interner).callable_sig(f.db);
+ let sig = substs.at(Interner, 0).assert_ty_ref(Interner).callable_sig(db);
if let Some(sig) = sig {
if sig.params().is_empty() {
write!(f, "||")?;
@@ -751,8 +783,8 @@ impl HirDisplay for Ty {
}
}
TyKind::Placeholder(idx) => {
- let id = from_placeholder_idx(f.db, *idx);
- let generics = generics(f.db.upcast(), id.parent);
+ let id = from_placeholder_idx(db, *idx);
+ let generics = generics(db.upcast(), id.parent);
let param_data = &generics.params.type_or_consts[id.local_id];
match param_data {
TypeOrConstParamData::TypeParamData(p) => match p.provenance {
@@ -760,28 +792,28 @@ impl HirDisplay for Ty {
write!(f, "{}", p.name.clone().unwrap_or_else(Name::missing))?
}
TypeParamProvenance::ArgumentImplTrait => {
- let substs = generics.placeholder_subst(f.db);
- let bounds =
- f.db.generic_predicates(id.parent)
- .iter()
- .map(|pred| pred.clone().substitute(Interner, &substs))
- .filter(|wc| match &wc.skip_binders() {
- WhereClause::Implemented(tr) => {
- &tr.self_type_parameter(Interner) == self
- }
- WhereClause::AliasEq(AliasEq {
- alias: AliasTy::Projection(proj),
- ty: _,
- }) => &proj.self_type_parameter(f.db) == self,
- _ => false,
- })
- .collect::<Vec<_>>();
- let krate = id.parent.module(f.db.upcast()).krate();
+ let substs = generics.placeholder_subst(db);
+ let bounds = db
+ .generic_predicates(id.parent)
+ .iter()
+ .map(|pred| pred.clone().substitute(Interner, &substs))
+ .filter(|wc| match &wc.skip_binders() {
+ WhereClause::Implemented(tr) => {
+ &tr.self_type_parameter(Interner) == self
+ }
+ WhereClause::AliasEq(AliasEq {
+ alias: AliasTy::Projection(proj),
+ ty: _,
+ }) => &proj.self_type_parameter(db) == self,
+ _ => false,
+ })
+ .collect::<Vec<_>>();
+ let krate = id.parent.module(db.upcast()).krate();
write_bounds_like_dyn_trait_with_prefix(
+ f,
"impl",
&bounds,
SizedByDefault::Sized { anchor: krate },
- f,
)?;
}
},
@@ -803,29 +835,28 @@ impl HirDisplay for Ty {
bounds.extend(auto_traits);
write_bounds_like_dyn_trait_with_prefix(
+ f,
"dyn",
&bounds,
SizedByDefault::NotSized,
- f,
)?;
}
TyKind::Alias(AliasTy::Projection(p_ty)) => p_ty.hir_fmt(f)?,
TyKind::Alias(AliasTy::Opaque(opaque_ty)) => {
- let impl_trait_id = f.db.lookup_intern_impl_trait_id(opaque_ty.opaque_ty_id.into());
+ let impl_trait_id = db.lookup_intern_impl_trait_id(opaque_ty.opaque_ty_id.into());
match impl_trait_id {
ImplTraitId::ReturnTypeImplTrait(func, idx) => {
let datas =
- f.db.return_type_impl_traits(func).expect("impl trait id without data");
- let data = (*datas)
- .as_ref()
- .map(|rpit| rpit.impl_traits[idx as usize].bounds.clone());
+ db.return_type_impl_traits(func).expect("impl trait id without data");
+ let data =
+ (*datas).as_ref().map(|rpit| rpit.impl_traits[idx].bounds.clone());
let bounds = data.substitute(Interner, &opaque_ty.substitution);
- let krate = func.lookup(f.db.upcast()).module(f.db.upcast()).krate();
+ let krate = func.lookup(db.upcast()).module(db.upcast()).krate();
write_bounds_like_dyn_trait_with_prefix(
+ f,
"impl",
bounds.skip_binders(),
SizedByDefault::Sized { anchor: krate },
- f,
)?;
}
ImplTraitId::AsyncBlockTypeImplTrait(..) => {
@@ -848,7 +879,6 @@ impl HirDisplay for Ty {
DisplaySourceCodeError::Generator,
));
}
-
let subst = subst.as_slice(Interner);
let a: Option<SmallVec<[&Ty; 3]>> = subst
.get(subst.len() - 3..)
@@ -897,7 +927,7 @@ impl HirDisplay for CallableSig {
}
}
-fn fn_traits(db: &dyn DefDatabase, trait_: TraitId) -> impl Iterator<Item = TraitId> {
+fn fn_traits(db: &dyn DefDatabase, trait_: TraitId) -> impl Iterator<Item = TraitId> + '_ {
let krate = trait_.lookup(db).container.krate();
utils::fn_traits(db, krate)
}
@@ -914,7 +944,7 @@ impl SizedByDefault {
Self::NotSized => false,
Self::Sized { anchor } => {
let sized_trait = db
- .lang_item(anchor, SmolStr::new_inline("sized"))
+ .lang_item(anchor, LangItem::Sized)
.and_then(|lang_item| lang_item.as_trait());
Some(trait_) == sized_trait
}
@@ -923,26 +953,26 @@ impl SizedByDefault {
}
pub fn write_bounds_like_dyn_trait_with_prefix(
+ f: &mut HirFormatter<'_>,
prefix: &str,
predicates: &[QuantifiedWhereClause],
default_sized: SizedByDefault,
- f: &mut HirFormatter<'_>,
) -> Result<(), HirDisplayError> {
write!(f, "{prefix}")?;
if !predicates.is_empty()
|| predicates.is_empty() && matches!(default_sized, SizedByDefault::Sized { .. })
{
write!(f, " ")?;
- write_bounds_like_dyn_trait(predicates, default_sized, f)
+ write_bounds_like_dyn_trait(f, predicates, default_sized)
} else {
Ok(())
}
}
fn write_bounds_like_dyn_trait(
+ f: &mut HirFormatter<'_>,
predicates: &[QuantifiedWhereClause],
default_sized: SizedByDefault,
- f: &mut HirFormatter<'_>,
) -> Result<(), HirDisplayError> {
// Note: This code is written to produce nice results (i.e.
// corresponding to surface Rust) for types that can occur in
@@ -978,7 +1008,9 @@ fn write_bounds_like_dyn_trait(
// We assume that the self type is ^0.0 (i.e. the
// existential) here, which is the only thing that's
// possible in actual Rust, and hence don't print it
+ f.start_location_link(trait_.into());
write!(f, "{}", f.db.trait_data(trait_).name)?;
+ f.end_location_link();
if let [_, params @ ..] = &*trait_ref.substitution.as_slice(Interner) {
if is_fn_trait {
if let Some(args) =
@@ -1015,7 +1047,9 @@ fn write_bounds_like_dyn_trait(
if let AliasTy::Projection(proj) = alias {
let assoc_ty_id = from_assoc_type_id(proj.associated_ty_id);
let type_alias = f.db.type_alias_data(assoc_ty_id);
+ f.start_location_link(assoc_ty_id.into());
write!(f, "{}", type_alias.name)?;
+ f.end_location_link();
let proj_arg_count = generics(f.db.upcast(), assoc_ty_id.into()).len_self();
if proj_arg_count > 0 {
@@ -1040,19 +1074,33 @@ fn write_bounds_like_dyn_trait(
if angle_open {
write!(f, ">")?;
}
- if matches!(default_sized, SizedByDefault::Sized { .. }) {
+ if let SizedByDefault::Sized { anchor } = default_sized {
+ let sized_trait =
+ f.db.lang_item(anchor, LangItem::Sized).and_then(|lang_item| lang_item.as_trait());
if !is_sized {
- write!(f, "{}?Sized", if first { "" } else { " + " })?;
+ if !first {
+ write!(f, " + ")?;
+ }
+ if let Some(sized_trait) = sized_trait {
+ f.start_location_link(sized_trait.into());
+ }
+ write!(f, "?Sized")?;
} else if first {
+ if let Some(sized_trait) = sized_trait {
+ f.start_location_link(sized_trait.into());
+ }
write!(f, "Sized")?;
}
+ if let Some(_) = sized_trait {
+ f.end_location_link();
+ }
}
Ok(())
}
fn fmt_trait_ref(
- tr: &TraitRef,
f: &mut HirFormatter<'_>,
+ tr: &TraitRef,
use_as: bool,
) -> Result<(), HirDisplayError> {
if f.should_truncate() {
@@ -1065,7 +1113,10 @@ fn fmt_trait_ref(
} else {
write!(f, ": ")?;
}
- write!(f, "{}", f.db.trait_data(tr.hir_trait_id()).name)?;
+ let trait_ = tr.hir_trait_id();
+ f.start_location_link(trait_.into());
+ write!(f, "{}", f.db.trait_data(trait_).name)?;
+ f.end_location_link();
if tr.substitution.len(Interner) > 1 {
write!(f, "<")?;
f.write_joined(&tr.substitution.as_slice(Interner)[1..], ", ")?;
@@ -1076,7 +1127,7 @@ fn fmt_trait_ref(
impl HirDisplay for TraitRef {
fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> {
- fmt_trait_ref(self, f, false)
+ fmt_trait_ref(f, self, false)
}
}
@@ -1090,12 +1141,13 @@ impl HirDisplay for WhereClause {
WhereClause::Implemented(trait_ref) => trait_ref.hir_fmt(f)?,
WhereClause::AliasEq(AliasEq { alias: AliasTy::Projection(projection_ty), ty }) => {
write!(f, "<")?;
- fmt_trait_ref(&projection_ty.trait_ref(f.db), f, true)?;
- write!(
- f,
- ">::{} = ",
- f.db.type_alias_data(from_assoc_type_id(projection_ty.associated_ty_id)).name,
- )?;
+ fmt_trait_ref(f, &projection_ty.trait_ref(f.db), true)?;
+ write!(f, ">::",)?;
+ let type_alias = from_assoc_type_id(projection_ty.associated_ty_id);
+ f.start_location_link(type_alias.into());
+ write!(f, "{}", f.db.type_alias_data(type_alias).name,)?;
+ f.end_location_link();
+ write!(f, " = ")?;
ty.hir_fmt(f)?;
}
WhereClause::AliasEq(_) => write!(f, "{{error}}")?,
@@ -1367,7 +1419,7 @@ impl HirDisplay for Path {
write!(f, "<")?;
let mut first = true;
- for arg in &generic_args.args {
+ for arg in generic_args.args.iter() {
if first {
first = false;
if generic_args.has_self_type {
@@ -1379,7 +1431,7 @@ impl HirDisplay for Path {
}
arg.hir_fmt(f)?;
}
- for binding in &generic_args.bindings {
+ for binding in generic_args.bindings.iter() {
if first {
first = false;
} else {
@@ -1393,7 +1445,7 @@ impl HirDisplay for Path {
}
None => {
write!(f, ": ")?;
- f.write_joined(&binding.bounds, " + ")?;
+ f.write_joined(binding.bounds.iter(), " + ")?;
}
}
}
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/infer.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer.rs
index 6b59f1c20..767afdf9e 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/infer.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer.rs
@@ -22,15 +22,15 @@ use hir_def::{
builtin_type::{BuiltinInt, BuiltinType, BuiltinUint},
data::{ConstData, StaticData},
expr::{BindingAnnotation, ExprId, ExprOrPatId, PatId},
- lang_item::LangItemTarget,
+ lang_item::{LangItem, LangItemTarget},
layout::Integer,
- path::{path, Path},
+ path::Path,
resolver::{HasResolver, ResolveValueResult, Resolver, TypeNs, ValueNs},
type_ref::TypeRef,
AdtId, AssocItemId, DefWithBodyId, EnumVariantId, FieldId, FunctionId, HasModule,
ItemContainerId, Lookup, TraitId, TypeAliasId, VariantId,
};
-use hir_expand::name::{name, Name};
+use hir_expand::name::name;
use itertools::Either;
use la_arena::ArenaMap;
use rustc_hash::FxHashMap;
@@ -39,7 +39,7 @@ use stdx::always;
use crate::{
db::HirDatabase, fold_tys, fold_tys_and_consts, infer::coerce::CoerceMany,
lower::ImplTraitLoweringMode, to_assoc_type_id, AliasEq, AliasTy, Const, DomainGoal,
- GenericArg, Goal, ImplTraitId, InEnvironment, Interner, ProjectionTy, Substitution,
+ GenericArg, Goal, ImplTraitId, InEnvironment, Interner, ProjectionTy, RpitId, Substitution,
TraitEnvironment, TraitRef, Ty, TyBuilder, TyExt, TyKind,
};
@@ -219,6 +219,7 @@ struct InternedStandardTypes {
unknown: Ty,
bool_: Ty,
unit: Ty,
+ never: Ty,
}
impl Default for InternedStandardTypes {
@@ -227,6 +228,7 @@ impl Default for InternedStandardTypes {
unknown: TyKind::Error.intern(Interner),
bool_: TyKind::Scalar(Scalar::Bool).intern(Interner),
unit: TyKind::Tuple(0, Substitution::empty(Interner)).intern(Interner),
+ never: TyKind::Never.intern(Interner),
}
}
}
@@ -352,6 +354,7 @@ pub struct InferenceResult {
/// **Note**: When a pattern type is resolved it may still contain
/// unresolved or missing subpatterns or subpatterns of mismatched types.
pub type_of_pat: ArenaMap<PatId, Ty>,
+ pub type_of_rpit: ArenaMap<RpitId, Ty>,
type_mismatches: FxHashMap<ExprOrPatId, TypeMismatch>,
/// Interned common types to return references to.
standard_types: InternedStandardTypes,
@@ -525,6 +528,9 @@ impl<'a> InferenceContext<'a> {
for ty in result.type_of_pat.values_mut() {
*ty = table.resolve_completely(ty.clone());
}
+ for ty in result.type_of_rpit.iter_mut().map(|x| x.1) {
+ *ty = table.resolve_completely(ty.clone());
+ }
for mismatch in result.type_mismatches.values_mut() {
mismatch.expected = table.resolve_completely(mismatch.expected.clone());
mismatch.actual = table.resolve_completely(mismatch.actual.clone());
@@ -603,7 +609,7 @@ impl<'a> InferenceContext<'a> {
_ => unreachable!(),
};
let bounds = (*rpits).map_ref(|rpits| {
- rpits.impl_traits[idx as usize].bounds.map_ref(|it| it.into_iter())
+ rpits.impl_traits[idx].bounds.map_ref(|it| it.into_iter())
});
let var = self.table.new_type_var();
let var_subst = Substitution::from1(Interner, var.clone());
@@ -616,6 +622,7 @@ impl<'a> InferenceContext<'a> {
always!(binders.is_empty(Interner)); // quantified where clauses not yet handled
self.push_obligation(var_predicate.cast(Interner));
}
+ self.result.type_of_rpit.insert(idx, var.clone());
var
},
DebruijnIndex::INNERMOST,
@@ -917,104 +924,98 @@ impl<'a> InferenceContext<'a> {
}
}
- fn resolve_lang_item(&self, name: Name) -> Option<LangItemTarget> {
+ fn resolve_lang_item(&self, item: LangItem) -> Option<LangItemTarget> {
let krate = self.resolver.krate();
- self.db.lang_item(krate, name.to_smol_str())
+ self.db.lang_item(krate, item)
}
fn resolve_into_iter_item(&self) -> Option<TypeAliasId> {
- let path = path![core::iter::IntoIterator];
- let trait_ = self.resolver.resolve_known_trait(self.db.upcast(), &path)?;
+ let ItemContainerId::TraitId(trait_) = self.resolve_lang_item(LangItem::IntoIterIntoIter)?
+ .as_function()?
+ .lookup(self.db.upcast()).container
+ else { return None };
self.db.trait_data(trait_).associated_type_by_name(&name![IntoIter])
}
fn resolve_iterator_item(&self) -> Option<TypeAliasId> {
- let path = path![core::iter::Iterator];
- let trait_ = self.resolver.resolve_known_trait(self.db.upcast(), &path)?;
+ let ItemContainerId::TraitId(trait_) = self.resolve_lang_item(LangItem::IteratorNext)?
+ .as_function()?
+ .lookup(self.db.upcast()).container
+ else { return None };
self.db.trait_data(trait_).associated_type_by_name(&name![Item])
}
- fn resolve_ops_try_ok(&self) -> Option<TypeAliasId> {
- // FIXME resolve via lang_item once try v2 is stable
- let path = path![core::ops::Try];
- let trait_ = self.resolver.resolve_known_trait(self.db.upcast(), &path)?;
- let trait_data = self.db.trait_data(trait_);
- trait_data
- // FIXME remove once try v2 is stable
- .associated_type_by_name(&name![Ok])
- .or_else(|| trait_data.associated_type_by_name(&name![Output]))
+ fn resolve_output_on(&self, trait_: TraitId) -> Option<TypeAliasId> {
+ self.db.trait_data(trait_).associated_type_by_name(&name![Output])
+ }
+
+ fn resolve_lang_trait(&self, lang: LangItem) -> Option<TraitId> {
+ self.resolve_lang_item(lang)?.as_trait()
+ }
+
+ fn resolve_ops_try_output(&self) -> Option<TypeAliasId> {
+ self.resolve_output_on(self.resolve_lang_trait(LangItem::Try)?)
}
fn resolve_ops_neg_output(&self) -> Option<TypeAliasId> {
- let trait_ = self.resolve_lang_item(name![neg])?.as_trait()?;
- self.db.trait_data(trait_).associated_type_by_name(&name![Output])
+ self.resolve_output_on(self.resolve_lang_trait(LangItem::Neg)?)
}
fn resolve_ops_not_output(&self) -> Option<TypeAliasId> {
- let trait_ = self.resolve_lang_item(name![not])?.as_trait()?;
- self.db.trait_data(trait_).associated_type_by_name(&name![Output])
+ self.resolve_output_on(self.resolve_lang_trait(LangItem::Not)?)
}
fn resolve_future_future_output(&self) -> Option<TypeAliasId> {
- let trait_ = self
- .resolver
- .resolve_known_trait(self.db.upcast(), &path![core::future::IntoFuture])
- .or_else(|| self.resolve_lang_item(name![future_trait])?.as_trait())?;
- self.db.trait_data(trait_).associated_type_by_name(&name![Output])
+ let ItemContainerId::TraitId(trait_) = self
+ .resolve_lang_item(LangItem::IntoFutureIntoFuture)?
+ .as_function()?
+ .lookup(self.db.upcast())
+ .container
+ else { return None };
+ self.resolve_output_on(trait_)
}
fn resolve_boxed_box(&self) -> Option<AdtId> {
- let struct_ = self.resolve_lang_item(name![owned_box])?.as_struct()?;
+ let struct_ = self.resolve_lang_item(LangItem::OwnedBox)?.as_struct()?;
Some(struct_.into())
}
fn resolve_range_full(&self) -> Option<AdtId> {
- let path = path![core::ops::RangeFull];
- let struct_ = self.resolver.resolve_known_struct(self.db.upcast(), &path)?;
+ let struct_ = self.resolve_lang_item(LangItem::RangeFull)?.as_struct()?;
Some(struct_.into())
}
fn resolve_range(&self) -> Option<AdtId> {
- let path = path![core::ops::Range];
- let struct_ = self.resolver.resolve_known_struct(self.db.upcast(), &path)?;
+ let struct_ = self.resolve_lang_item(LangItem::Range)?.as_struct()?;
Some(struct_.into())
}
fn resolve_range_inclusive(&self) -> Option<AdtId> {
- let path = path![core::ops::RangeInclusive];
- let struct_ = self.resolver.resolve_known_struct(self.db.upcast(), &path)?;
+ let struct_ = self.resolve_lang_item(LangItem::RangeInclusiveStruct)?.as_struct()?;
Some(struct_.into())
}
fn resolve_range_from(&self) -> Option<AdtId> {
- let path = path![core::ops::RangeFrom];
- let struct_ = self.resolver.resolve_known_struct(self.db.upcast(), &path)?;
+ let struct_ = self.resolve_lang_item(LangItem::RangeFrom)?.as_struct()?;
Some(struct_.into())
}
fn resolve_range_to(&self) -> Option<AdtId> {
- let path = path![core::ops::RangeTo];
- let struct_ = self.resolver.resolve_known_struct(self.db.upcast(), &path)?;
+ let struct_ = self.resolve_lang_item(LangItem::RangeTo)?.as_struct()?;
Some(struct_.into())
}
fn resolve_range_to_inclusive(&self) -> Option<AdtId> {
- let path = path![core::ops::RangeToInclusive];
- let struct_ = self.resolver.resolve_known_struct(self.db.upcast(), &path)?;
+ let struct_ = self.resolve_lang_item(LangItem::RangeToInclusive)?.as_struct()?;
Some(struct_.into())
}
- fn resolve_ops_index(&self) -> Option<TraitId> {
- self.resolve_lang_item(name![index])?.as_trait()
- }
-
fn resolve_ops_index_output(&self) -> Option<TypeAliasId> {
- let trait_ = self.resolve_ops_index()?;
- self.db.trait_data(trait_).associated_type_by_name(&name![Output])
+ self.resolve_output_on(self.resolve_lang_trait(LangItem::Index)?)
}
fn resolve_va_list(&self) -> Option<AdtId> {
- let struct_ = self.resolve_lang_item(name![va_list])?.as_struct()?;
+ let struct_ = self.resolve_lang_item(LangItem::VaList)?.as_struct()?;
Some(struct_.into())
}
}
@@ -1025,7 +1026,8 @@ impl<'a> InferenceContext<'a> {
pub(crate) enum Expectation {
None,
HasType(Ty),
- // Castable(Ty), // rustc has this, we currently just don't propagate an expectation for casts
+ #[allow(dead_code)]
+ Castable(Ty),
RValueLikeUnsized(Ty),
}
@@ -1041,10 +1043,6 @@ impl Expectation {
}
}
- fn from_option(ty: Option<Ty>) -> Self {
- ty.map_or(Expectation::None, Expectation::HasType)
- }
-
/// The following explanation is copied straight from rustc:
/// Provides an expectation for an rvalue expression given an *optional*
/// hint, which is not required for type safety (the resulting type might
@@ -1082,6 +1080,7 @@ impl Expectation {
match self {
Expectation::None => Expectation::None,
Expectation::HasType(t) => Expectation::HasType(table.resolve_ty_shallow(t)),
+ Expectation::Castable(t) => Expectation::Castable(table.resolve_ty_shallow(t)),
Expectation::RValueLikeUnsized(t) => {
Expectation::RValueLikeUnsized(table.resolve_ty_shallow(t))
}
@@ -1091,20 +1090,25 @@ impl Expectation {
fn to_option(&self, table: &mut unify::InferenceTable<'_>) -> Option<Ty> {
match self.resolve(table) {
Expectation::None => None,
- Expectation::HasType(t) |
- // Expectation::Castable(t) |
- Expectation::RValueLikeUnsized(t) => Some(t),
+ Expectation::HasType(t)
+ | Expectation::Castable(t)
+ | Expectation::RValueLikeUnsized(t) => Some(t),
}
}
fn only_has_type(&self, table: &mut unify::InferenceTable<'_>) -> Option<Ty> {
match self {
Expectation::HasType(t) => Some(table.resolve_ty_shallow(t)),
- // Expectation::Castable(_) |
- Expectation::RValueLikeUnsized(_) | Expectation::None => None,
+ Expectation::Castable(_) | Expectation::RValueLikeUnsized(_) | Expectation::None => {
+ None
+ }
}
}
+ fn coercion_target_type(&self, table: &mut unify::InferenceTable<'_>) -> Ty {
+ self.only_has_type(table).unwrap_or_else(|| table.new_type_var())
+ }
+
/// Comment copied from rustc:
/// Disregard "castable to" expectations because they
/// can lead us astray. Consider for example `if cond
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/infer/closure.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer/closure.rs
index 094e460db..a6449d019 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/infer/closure.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer/closure.rs
@@ -51,7 +51,7 @@ impl InferenceContext<'_> {
.map(to_chalk_trait_id)
.collect();
- let self_ty = TyKind::Error.intern(Interner);
+ let self_ty = self.result.standard_types.unknown.clone();
let bounds = dyn_ty.bounds.clone().substitute(Interner, &[self_ty.cast(Interner)]);
for bound in bounds.iter(Interner) {
// NOTE(skip_binders): the extracted types are rebound by the returned `FnPointer`
@@ -67,7 +67,7 @@ impl InferenceContext<'_> {
let arg = projection.substitution.as_slice(Interner).get(1)?;
if let Some(subst) = arg.ty(Interner)?.as_tuple() {
let generic_args = subst.as_slice(Interner);
- let mut sig_tys = Vec::new();
+ let mut sig_tys = Vec::with_capacity(generic_args.len() + 1);
for arg in generic_args {
sig_tys.push(arg.ty(Interner)?.clone());
}
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/infer/coerce.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer/coerce.rs
index 8df25c83c..3293534a0 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/infer/coerce.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer/coerce.rs
@@ -8,9 +8,11 @@
use std::{iter, sync::Arc};
use chalk_ir::{cast::Cast, BoundVar, Goal, Mutability, TyVariableKind};
-use hir_def::{expr::ExprId, lang_item::LangItemTarget};
+use hir_def::{
+ expr::ExprId,
+ lang_item::{LangItem, LangItemTarget},
+};
use stdx::always;
-use syntax::SmolStr;
use crate::{
autoderef::{Autoderef, AutoderefKind},
@@ -570,11 +572,10 @@ impl<'a> InferenceTable<'a> {
reborrow.as_ref().map_or_else(|| from_ty.clone(), |(_, adj)| adj.target.clone());
let krate = self.trait_env.krate;
- let coerce_unsized_trait =
- match self.db.lang_item(krate, SmolStr::new_inline("coerce_unsized")) {
- Some(LangItemTarget::TraitId(trait_)) => trait_,
- _ => return Err(TypeError),
- };
+ let coerce_unsized_trait = match self.db.lang_item(krate, LangItem::CoerceUnsized) {
+ Some(LangItemTarget::Trait(trait_)) => trait_,
+ _ => return Err(TypeError),
+ };
let coerce_unsized_tref = {
let b = TyBuilder::trait_ref(self.db, coerce_unsized_trait);
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/infer/expr.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer/expr.rs
index 8f9cdac37..175fded8c 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/infer/expr.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer/expr.rs
@@ -10,15 +10,15 @@ use chalk_ir::{
};
use hir_def::{
expr::{
- ArithOp, Array, BinaryOp, ClosureKind, CmpOp, Expr, ExprId, LabelId, Literal, Statement,
- UnaryOp,
+ ArithOp, Array, BinaryOp, ClosureKind, Expr, ExprId, LabelId, Literal, Statement, UnaryOp,
},
generics::TypeOrConstParamData,
+ lang_item::LangItem,
path::{GenericArg, GenericArgs},
resolver::resolver_for_expr,
ConstParamId, FieldId, ItemContainerId, Lookup,
};
-use hir_expand::name::Name;
+use hir_expand::name::{name, Name};
use stdx::always;
use syntax::ast::RangeOp;
@@ -30,7 +30,7 @@ use crate::{
const_or_path_to_chalk, generic_arg_to_chalk, lower_to_chalk_mutability, ParamLoweringMode,
},
mapping::{from_chalk, ToChalk},
- method_resolution::{self, lang_names_for_bin_op, VisibleFromModule},
+ method_resolution::{self, lang_items_for_bin_op, VisibleFromModule},
primitive::{self, UintTy},
static_lifetime, to_chalk_trait_id,
utils::{generics, Generics},
@@ -87,16 +87,15 @@ impl<'a> InferenceContext<'a> {
let expected = &expected.adjust_for_branches(&mut self.table);
self.infer_expr(
condition,
- &Expectation::has_type(TyKind::Scalar(Scalar::Bool).intern(Interner)),
+ &Expectation::HasType(self.result.standard_types.bool_.clone()),
);
let condition_diverges = mem::replace(&mut self.diverges, Diverges::Maybe);
let mut both_arms_diverge = Diverges::Always;
- let result_ty = self.table.new_type_var();
let then_ty = self.infer_expr_inner(then_branch, expected);
both_arms_diverge &= mem::replace(&mut self.diverges, Diverges::Maybe);
- let mut coerce = CoerceMany::new(result_ty);
+ let mut coerce = CoerceMany::new(expected.coercion_target_type(&mut self.table));
coerce.coerce(self, Some(then_branch), &then_ty);
let else_ty = match else_branch {
Some(else_branch) => self.infer_expr_inner(else_branch, expected),
@@ -113,7 +112,7 @@ impl<'a> InferenceContext<'a> {
&Expr::Let { pat, expr } => {
let input_ty = self.infer_expr(expr, &Expectation::none());
self.infer_pat(pat, &input_ty, BindingMode::default());
- TyKind::Scalar(Scalar::Bool).intern(Interner)
+ self.result.standard_types.bool_.clone()
}
Expr::Block { statements, tail, label, id: _ } => {
let old_resolver = mem::replace(
@@ -158,7 +157,8 @@ impl<'a> InferenceContext<'a> {
}
// The ok-ish type that is expected from the last expression
- let ok_ty = self.resolve_associated_type(try_ty.clone(), self.resolve_ops_try_ok());
+ let ok_ty =
+ self.resolve_associated_type(try_ty.clone(), self.resolve_ops_try_output());
self.with_breakable_ctx(BreakableKind::Block, ok_ty.clone(), None, |this| {
this.infer_expr(*body, &Expectation::has_type(ok_ty));
@@ -187,10 +187,12 @@ impl<'a> InferenceContext<'a> {
.intern(Interner)
}
&Expr::Loop { body, label } => {
+ // FIXME: should be:
+ // let ty = expected.coercion_target_type(&mut self.table);
let ty = self.table.new_type_var();
let (breaks, ()) =
self.with_breakable_ctx(BreakableKind::Loop, ty, label, |this| {
- this.infer_expr(body, &Expectation::has_type(TyBuilder::unit()));
+ this.infer_expr(body, &Expectation::HasType(TyBuilder::unit()));
});
match breaks {
@@ -198,16 +200,16 @@ impl<'a> InferenceContext<'a> {
self.diverges = Diverges::Maybe;
breaks
}
- None => TyKind::Never.intern(Interner),
+ None => self.result.standard_types.never.clone(),
}
}
&Expr::While { condition, body, label } => {
self.with_breakable_ctx(BreakableKind::Loop, self.err_ty(), label, |this| {
this.infer_expr(
condition,
- &Expectation::has_type(TyKind::Scalar(Scalar::Bool).intern(Interner)),
+ &Expectation::HasType(this.result.standard_types.bool_.clone()),
);
- this.infer_expr(body, &Expectation::has_type(TyBuilder::unit()));
+ this.infer_expr(body, &Expectation::HasType(TyBuilder::unit()));
});
// the body may not run, so it diverging doesn't mean we diverge
@@ -223,7 +225,7 @@ impl<'a> InferenceContext<'a> {
self.infer_pat(pat, &pat_ty, BindingMode::default());
self.with_breakable_ctx(BreakableKind::Loop, self.err_ty(), label, |this| {
- this.infer_expr(body, &Expectation::has_type(TyBuilder::unit()));
+ this.infer_expr(body, &Expectation::HasType(TyBuilder::unit()));
});
// the body may not run, so it diverging doesn't mean we diverge
@@ -233,7 +235,7 @@ impl<'a> InferenceContext<'a> {
Expr::Closure { body, args, ret_type, arg_types, closure_kind } => {
assert_eq!(args.len(), arg_types.len());
- let mut sig_tys = Vec::new();
+ let mut sig_tys = Vec::with_capacity(arg_types.len() + 1);
// collect explicitly written argument types
for arg_type in arg_types.iter() {
@@ -254,7 +256,8 @@ impl<'a> InferenceContext<'a> {
num_binders: 0,
sig: FnSig { abi: (), safety: chalk_ir::Safety::Safe, variadic: false },
substitution: FnSubst(
- Substitution::from_iter(Interner, sig_tys.clone()).shifted_in(Interner),
+ Substitution::from_iter(Interner, sig_tys.iter().cloned())
+ .shifted_in(Interner),
),
})
.intern(Interner);
@@ -316,27 +319,34 @@ impl<'a> InferenceContext<'a> {
Expr::Call { callee, args, .. } => {
let callee_ty = self.infer_expr(*callee, &Expectation::none());
let mut derefs = Autoderef::new(&mut self.table, callee_ty.clone());
- let mut res = None;
- let mut derefed_callee = callee_ty.clone();
- // manual loop to be able to access `derefs.table`
- while let Some((callee_deref_ty, _)) = derefs.next() {
- res = derefs.table.callable_sig(&callee_deref_ty, args.len());
- if res.is_some() {
- derefed_callee = callee_deref_ty;
- break;
+ let (res, derefed_callee) = 'b: {
+ // manual loop to be able to access `derefs.table`
+ while let Some((callee_deref_ty, _)) = derefs.next() {
+ let res = derefs.table.callable_sig(&callee_deref_ty, args.len());
+ if res.is_some() {
+ break 'b (res, callee_deref_ty);
+ }
}
- }
+ (None, callee_ty.clone())
+ };
// if the function is unresolved, we use is_varargs=true to
// suppress the arg count diagnostic here
let is_varargs =
derefed_callee.callable_sig(self.db).map_or(false, |sig| sig.is_varargs)
|| res.is_none();
let (param_tys, ret_ty) = match res {
- Some(res) => {
+ Some((func, params, ret_ty)) => {
let adjustments = auto_deref_adjust_steps(&derefs);
// FIXME: Handle call adjustments for Fn/FnMut
self.write_expr_adj(*callee, adjustments);
- res
+ if let Some((trait_, func)) = func {
+ let subst = TyBuilder::subst_for_def(self.db, trait_, None)
+ .push(callee_ty.clone())
+ .push(TyBuilder::tuple_with(params.iter().cloned()))
+ .build();
+ self.write_method_resolution(tgt_expr, func, subst.clone());
+ }
+ (params, ret_ty)
}
None => (Vec::new(), self.err_ty()), // FIXME diagnostic
};
@@ -374,12 +384,9 @@ impl<'a> InferenceContext<'a> {
let expected = expected.adjust_for_branches(&mut self.table);
let result_ty = if arms.is_empty() {
- TyKind::Never.intern(Interner)
+ self.result.standard_types.never.clone()
} else {
- match &expected {
- Expectation::HasType(ty) => ty.clone(),
- _ => self.table.new_type_var(),
- }
+ expected.coercion_target_type(&mut self.table)
};
let mut coerce = CoerceMany::new(result_ty);
@@ -392,7 +399,7 @@ impl<'a> InferenceContext<'a> {
if let Some(guard_expr) = arm.guard {
self.infer_expr(
guard_expr,
- &Expectation::has_type(TyKind::Scalar(Scalar::Bool).intern(Interner)),
+ &Expectation::HasType(self.result.standard_types.bool_.clone()),
);
}
@@ -417,7 +424,7 @@ impl<'a> InferenceContext<'a> {
is_break: false,
});
};
- TyKind::Never.intern(Interner)
+ self.result.standard_types.never.clone()
}
Expr::Break { expr, label } => {
let val_ty = if let Some(expr) = *expr {
@@ -431,7 +438,7 @@ impl<'a> InferenceContext<'a> {
// avoiding the borrowck
let mut coerce = mem::replace(
&mut ctxt.coerce,
- CoerceMany::new(self.result.standard_types.unknown.clone()),
+ CoerceMany::new(expected.coercion_target_type(&mut self.table)),
);
// FIXME: create a synthetic `()` during lowering so we have something to refer to here?
@@ -449,7 +456,7 @@ impl<'a> InferenceContext<'a> {
});
}
}
- TyKind::Never.intern(Interner)
+ self.result.standard_types.never.clone()
}
Expr::Return { expr } => {
if let Some(expr) = expr {
@@ -458,7 +465,7 @@ impl<'a> InferenceContext<'a> {
let unit = TyBuilder::unit();
let _ = self.coerce(Some(tgt_expr), &unit, &self.return_ty.clone());
}
- TyKind::Never.intern(Interner)
+ self.result.standard_types.never.clone()
}
Expr::Yield { expr } => {
if let Some((resume_ty, yield_ty)) = self.resume_yield_tys.clone() {
@@ -471,14 +478,14 @@ impl<'a> InferenceContext<'a> {
resume_ty
} else {
// FIXME: report error (yield expr in non-generator)
- TyKind::Error.intern(Interner)
+ self.result.standard_types.unknown.clone()
}
}
Expr::Yeet { expr } => {
if let &Some(expr) = expr {
self.infer_expr_inner(expr, &Expectation::None);
}
- TyKind::Never.intern(Interner)
+ self.result.standard_types.never.clone()
}
Expr::RecordLit { path, fields, spread, .. } => {
let (ty, def_id) = self.resolve_variant(path.as_deref(), false);
@@ -588,12 +595,23 @@ impl<'a> InferenceContext<'a> {
}
Expr::Try { expr } => {
let inner_ty = self.infer_expr_inner(*expr, &Expectation::none());
- self.resolve_associated_type(inner_ty, self.resolve_ops_try_ok())
+ if let Some(trait_) = self.resolve_lang_trait(LangItem::Try) {
+ if let Some(func) = self.db.trait_data(trait_).method_by_name(&name!(branch)) {
+ let subst = TyBuilder::subst_for_def(self.db, trait_, None)
+ .push(inner_ty.clone())
+ .build();
+ self.write_method_resolution(tgt_expr, func, subst.clone());
+ }
+ let try_output = self.resolve_output_on(trait_);
+ self.resolve_associated_type(inner_ty, try_output)
+ } else {
+ self.err_ty()
+ }
}
Expr::Cast { expr, type_ref } => {
- // FIXME: propagate the "castable to" expectation (and find a test case that shows this is necessary)
- let _inner_ty = self.infer_expr_inner(*expr, &Expectation::none());
let cast_ty = self.make_ty(type_ref);
+ // FIXME: propagate the "castable to" expectation
+ let _inner_ty = self.infer_expr_inner(*expr, &Expectation::None);
// FIXME check the cast...
cast_ty
}
@@ -627,6 +645,7 @@ impl<'a> InferenceContext<'a> {
Expr::UnaryOp { expr, op } => {
let inner_ty = self.infer_expr_inner(*expr, &Expectation::none());
let inner_ty = self.resolve_ty_shallow(&inner_ty);
+ // FIXME: Note down method resolution her
match op {
UnaryOp::Deref => {
autoderef::deref(&mut self.table, inner_ty).unwrap_or_else(|| self.err_ty())
@@ -736,7 +755,7 @@ impl<'a> InferenceContext<'a> {
let base_ty = self.infer_expr_inner(*base, &Expectation::none());
let index_ty = self.infer_expr(*index, &Expectation::none());
- if let Some(index_trait) = self.resolve_ops_index() {
+ if let Some(index_trait) = self.resolve_lang_trait(LangItem::Index) {
let canonicalized = self.canonicalize(base_ty.clone());
let receiver_adjustments = method_resolution::resolve_indexing_op(
self.db,
@@ -749,6 +768,15 @@ impl<'a> InferenceContext<'a> {
adj.apply(&mut self.table, base_ty)
});
self.write_expr_adj(*base, adj);
+ if let Some(func) =
+ self.db.trait_data(index_trait).method_by_name(&name!(index))
+ {
+ let substs = TyBuilder::subst_for_def(self.db, index_trait, None)
+ .push(self_ty.clone())
+ .push(index_ty.clone())
+ .build();
+ self.write_method_resolution(tgt_expr, func, substs.clone());
+ }
self.resolve_associated_type_with_params(
self_ty,
self.resolve_ops_index_output(),
@@ -800,7 +828,7 @@ impl<'a> InferenceContext<'a> {
self.infer_expr_coerce(initializer, &Expectation::has_type(elem_ty));
self.infer_expr(
repeat,
- &Expectation::has_type(
+ &Expectation::HasType(
TyKind::Scalar(Scalar::Uint(UintTy::Usize)).intern(Interner),
),
);
@@ -823,7 +851,7 @@ impl<'a> InferenceContext<'a> {
TyKind::Array(coerce.complete(), len).intern(Interner)
}
Expr::Literal(lit) => match lit {
- Literal::Bool(..) => TyKind::Scalar(Scalar::Bool).intern(Interner),
+ Literal::Bool(..) => self.result.standard_types.bool_.clone(),
Literal::String(..) => {
TyKind::Ref(Mutability::Not, static_lifetime(), TyKind::Str.intern(Interner))
.intern(Interner)
@@ -1009,7 +1037,7 @@ impl<'a> InferenceContext<'a> {
let lhs_ty = self.infer_expr(lhs, &lhs_expectation);
let rhs_ty = self.table.new_type_var();
- let trait_func = lang_names_for_bin_op(op).and_then(|(name, lang_item)| {
+ let trait_func = lang_items_for_bin_op(op).and_then(|(name, lang_item)| {
let trait_id = self.resolve_lang_item(lang_item)?.as_trait()?;
let func = self.db.trait_data(trait_id).method_by_name(&name)?;
Some((trait_id, func))
@@ -1017,11 +1045,21 @@ impl<'a> InferenceContext<'a> {
let (trait_, func) = match trait_func {
Some(it) => it,
None => {
- let rhs_ty = self.builtin_binary_op_rhs_expectation(op, lhs_ty.clone());
- let rhs_ty = self.infer_expr_coerce(rhs, &Expectation::from_option(rhs_ty));
- return self
- .builtin_binary_op_return_ty(op, lhs_ty, rhs_ty)
- .unwrap_or_else(|| self.err_ty());
+ // HACK: `rhs_ty` is a general inference variable with no clue at all at this
+ // point. Passing `lhs_ty` as both operands just to check if `lhs_ty` is a builtin
+ // type applicable to `op`.
+ let ret_ty = if self.is_builtin_binop(&lhs_ty, &lhs_ty, op) {
+ // Assume both operands are builtin so we can continue inference. No guarantee
+ // on the correctness, rustc would complain as necessary lang items don't seem
+ // to exist anyway.
+ self.enforce_builtin_binop_types(&lhs_ty, &rhs_ty, op)
+ } else {
+ self.err_ty()
+ };
+
+ self.infer_expr_coerce(rhs, &Expectation::has_type(rhs_ty));
+
+ return ret_ty;
}
};
@@ -1071,11 +1109,9 @@ impl<'a> InferenceContext<'a> {
let ret_ty = self.normalize_associated_types_in(ret_ty);
- // use knowledge of built-in binary ops, which can sometimes help inference
- if let Some(builtin_rhs) = self.builtin_binary_op_rhs_expectation(op, lhs_ty.clone()) {
- self.unify(&builtin_rhs, &rhs_ty);
- }
- if let Some(builtin_ret) = self.builtin_binary_op_return_ty(op, lhs_ty, rhs_ty) {
+ if self.is_builtin_binop(&lhs_ty, &rhs_ty, op) {
+ // use knowledge of built-in binary ops, which can sometimes help inference
+ let builtin_ret = self.enforce_builtin_binop_types(&lhs_ty, &rhs_ty, op);
self.unify(&builtin_ret, &ret_ty);
}
@@ -1111,7 +1147,7 @@ impl<'a> InferenceContext<'a> {
if let Some(expr) = else_branch {
self.infer_expr_coerce(
*expr,
- &Expectation::has_type(Ty::new(Interner, TyKind::Never)),
+ &Expectation::HasType(self.result.standard_types.never.clone()),
);
}
@@ -1136,18 +1172,16 @@ impl<'a> InferenceContext<'a> {
if self.diverges.is_always() {
// we don't even make an attempt at coercion
self.table.new_maybe_never_var()
- } else {
- if let Some(t) = expected.only_has_type(&mut self.table) {
- if self.coerce(Some(expr), &TyBuilder::unit(), &t).is_err() {
- self.result.type_mismatches.insert(
- expr.into(),
- TypeMismatch { expected: t.clone(), actual: TyBuilder::unit() },
- );
- }
- t
- } else {
- TyBuilder::unit()
+ } else if let Some(t) = expected.only_has_type(&mut self.table) {
+ if self.coerce(Some(expr), &TyBuilder::unit(), &t).is_err() {
+ self.result.type_mismatches.insert(
+ expr.into(),
+ TypeMismatch { expected: t.clone(), actual: TyBuilder::unit() },
+ );
}
+ t
+ } else {
+ TyBuilder::unit()
}
}
}
@@ -1271,7 +1305,7 @@ impl<'a> InferenceContext<'a> {
// that are not closures, then we type-check the closures. This is so
// that we have more information about the types of arguments when we
// type-check the functions. This isn't really the right way to do this.
- for &check_closures in &[false, true] {
+ for check_closures in [false, true] {
let mut skip_indices = skip_indices.into_iter().copied().fuse().peekable();
let param_iter = param_tys.iter().cloned().chain(repeat(self.err_ty()));
let expected_iter = expected_inputs
@@ -1314,13 +1348,13 @@ impl<'a> InferenceContext<'a> {
} else {
param_ty
};
- if !coercion_target.is_unknown() {
- if self.coerce(Some(arg), &ty, &coercion_target).is_err() {
- self.result.type_mismatches.insert(
- arg.into(),
- TypeMismatch { expected: coercion_target, actual: ty.clone() },
- );
- }
+ if !coercion_target.is_unknown()
+ && self.coerce(Some(arg), &ty, &coercion_target).is_err()
+ {
+ self.result.type_mismatches.insert(
+ arg.into(),
+ TypeMismatch { expected: coercion_target, actual: ty.clone() },
+ );
}
}
}
@@ -1479,92 +1513,124 @@ impl<'a> InferenceContext<'a> {
indices
}
- fn builtin_binary_op_return_ty(&mut self, op: BinaryOp, lhs_ty: Ty, rhs_ty: Ty) -> Option<Ty> {
- let lhs_ty = self.resolve_ty_shallow(&lhs_ty);
- let rhs_ty = self.resolve_ty_shallow(&rhs_ty);
- match op {
- BinaryOp::LogicOp(_) | BinaryOp::CmpOp(_) => {
- Some(TyKind::Scalar(Scalar::Bool).intern(Interner))
+ /// Dereferences a single level of immutable referencing.
+ fn deref_ty_if_possible(&mut self, ty: &Ty) -> Ty {
+ let ty = self.resolve_ty_shallow(ty);
+ match ty.kind(Interner) {
+ TyKind::Ref(Mutability::Not, _, inner) => self.resolve_ty_shallow(inner),
+ _ => ty,
+ }
+ }
+
+ /// Enforces expectations on lhs type and rhs type depending on the operator and returns the
+ /// output type of the binary op.
+ fn enforce_builtin_binop_types(&mut self, lhs: &Ty, rhs: &Ty, op: BinaryOp) -> Ty {
+ // Special-case a single layer of referencing, so that things like `5.0 + &6.0f32` work (See rust-lang/rust#57447).
+ let lhs = self.deref_ty_if_possible(lhs);
+ let rhs = self.deref_ty_if_possible(rhs);
+
+ let (op, is_assign) = match op {
+ BinaryOp::Assignment { op: Some(inner) } => (BinaryOp::ArithOp(inner), true),
+ _ => (op, false),
+ };
+
+ let output_ty = match op {
+ BinaryOp::LogicOp(_) => {
+ let bool_ = self.result.standard_types.bool_.clone();
+ self.unify(&lhs, &bool_);
+ self.unify(&rhs, &bool_);
+ bool_
}
- BinaryOp::Assignment { .. } => Some(TyBuilder::unit()),
+
BinaryOp::ArithOp(ArithOp::Shl | ArithOp::Shr) => {
- // all integer combinations are valid here
- if matches!(
- lhs_ty.kind(Interner),
- TyKind::Scalar(Scalar::Int(_) | Scalar::Uint(_))
- | TyKind::InferenceVar(_, TyVariableKind::Integer)
- ) && matches!(
- rhs_ty.kind(Interner),
- TyKind::Scalar(Scalar::Int(_) | Scalar::Uint(_))
- | TyKind::InferenceVar(_, TyVariableKind::Integer)
- ) {
- Some(lhs_ty)
- } else {
- None
- }
+ // result type is same as LHS always
+ lhs
}
- BinaryOp::ArithOp(_) => match (lhs_ty.kind(Interner), rhs_ty.kind(Interner)) {
- // (int, int) | (uint, uint) | (float, float)
- (TyKind::Scalar(Scalar::Int(_)), TyKind::Scalar(Scalar::Int(_)))
- | (TyKind::Scalar(Scalar::Uint(_)), TyKind::Scalar(Scalar::Uint(_)))
- | (TyKind::Scalar(Scalar::Float(_)), TyKind::Scalar(Scalar::Float(_))) => {
- Some(rhs_ty)
- }
- // ({int}, int) | ({int}, uint)
- (
- TyKind::InferenceVar(_, TyVariableKind::Integer),
- TyKind::Scalar(Scalar::Int(_) | Scalar::Uint(_)),
- ) => Some(rhs_ty),
- // (int, {int}) | (uint, {int})
- (
- TyKind::Scalar(Scalar::Int(_) | Scalar::Uint(_)),
- TyKind::InferenceVar(_, TyVariableKind::Integer),
- ) => Some(lhs_ty),
- // ({float} | float)
- (
- TyKind::InferenceVar(_, TyVariableKind::Float),
- TyKind::Scalar(Scalar::Float(_)),
- ) => Some(rhs_ty),
- // (float, {float})
- (
- TyKind::Scalar(Scalar::Float(_)),
- TyKind::InferenceVar(_, TyVariableKind::Float),
- ) => Some(lhs_ty),
- // ({int}, {int}) | ({float}, {float})
- (
- TyKind::InferenceVar(_, TyVariableKind::Integer),
- TyKind::InferenceVar(_, TyVariableKind::Integer),
- )
- | (
- TyKind::InferenceVar(_, TyVariableKind::Float),
- TyKind::InferenceVar(_, TyVariableKind::Float),
- ) => Some(rhs_ty),
- _ => None,
- },
+
+ BinaryOp::ArithOp(_) => {
+ // LHS, RHS, and result will have the same type
+ self.unify(&lhs, &rhs);
+ lhs
+ }
+
+ BinaryOp::CmpOp(_) => {
+ // LHS and RHS will have the same type
+ self.unify(&lhs, &rhs);
+ self.result.standard_types.bool_.clone()
+ }
+
+ BinaryOp::Assignment { op: None } => {
+ stdx::never!("Simple assignment operator is not binary op.");
+ lhs
+ }
+
+ BinaryOp::Assignment { .. } => unreachable!("handled above"),
+ };
+
+ if is_assign {
+ self.result.standard_types.unit.clone()
+ } else {
+ output_ty
}
}
- fn builtin_binary_op_rhs_expectation(&mut self, op: BinaryOp, lhs_ty: Ty) -> Option<Ty> {
- Some(match op {
- BinaryOp::LogicOp(..) => TyKind::Scalar(Scalar::Bool).intern(Interner),
- BinaryOp::Assignment { op: None } => lhs_ty,
- BinaryOp::CmpOp(CmpOp::Eq { .. }) => match self
- .resolve_ty_shallow(&lhs_ty)
- .kind(Interner)
- {
- TyKind::Scalar(_) | TyKind::Str => lhs_ty,
- TyKind::InferenceVar(_, TyVariableKind::Integer | TyVariableKind::Float) => lhs_ty,
- _ => return None,
- },
- BinaryOp::ArithOp(ArithOp::Shl | ArithOp::Shr) => return None,
- BinaryOp::CmpOp(CmpOp::Ord { .. })
- | BinaryOp::Assignment { op: Some(_) }
- | BinaryOp::ArithOp(_) => match self.resolve_ty_shallow(&lhs_ty).kind(Interner) {
- TyKind::Scalar(Scalar::Int(_) | Scalar::Uint(_) | Scalar::Float(_)) => lhs_ty,
- TyKind::InferenceVar(_, TyVariableKind::Integer | TyVariableKind::Float) => lhs_ty,
- _ => return None,
- },
- })
+ fn is_builtin_binop(&mut self, lhs: &Ty, rhs: &Ty, op: BinaryOp) -> bool {
+ // Special-case a single layer of referencing, so that things like `5.0 + &6.0f32` work (See rust-lang/rust#57447).
+ let lhs = self.deref_ty_if_possible(lhs);
+ let rhs = self.deref_ty_if_possible(rhs);
+
+ let op = match op {
+ BinaryOp::Assignment { op: Some(inner) } => BinaryOp::ArithOp(inner),
+ _ => op,
+ };
+
+ match op {
+ BinaryOp::LogicOp(_) => true,
+
+ BinaryOp::ArithOp(ArithOp::Shl | ArithOp::Shr) => {
+ lhs.is_integral() && rhs.is_integral()
+ }
+
+ BinaryOp::ArithOp(
+ ArithOp::Add | ArithOp::Sub | ArithOp::Mul | ArithOp::Div | ArithOp::Rem,
+ ) => {
+ lhs.is_integral() && rhs.is_integral()
+ || lhs.is_floating_point() && rhs.is_floating_point()
+ }
+
+ BinaryOp::ArithOp(ArithOp::BitAnd | ArithOp::BitOr | ArithOp::BitXor) => {
+ lhs.is_integral() && rhs.is_integral()
+ || lhs.is_floating_point() && rhs.is_floating_point()
+ || matches!(
+ (lhs.kind(Interner), rhs.kind(Interner)),
+ (TyKind::Scalar(Scalar::Bool), TyKind::Scalar(Scalar::Bool))
+ )
+ }
+
+ BinaryOp::CmpOp(_) => {
+ let is_scalar = |kind| {
+ matches!(
+ kind,
+ &TyKind::Scalar(_)
+ | TyKind::FnDef(..)
+ | TyKind::Function(_)
+ | TyKind::Raw(..)
+ | TyKind::InferenceVar(
+ _,
+ TyVariableKind::Integer | TyVariableKind::Float
+ )
+ )
+ };
+ is_scalar(lhs.kind(Interner)) && is_scalar(rhs.kind(Interner))
+ }
+
+ BinaryOp::Assignment { op: None } => {
+ stdx::never!("Simple assignment operator is not binary op.");
+ false
+ }
+
+ BinaryOp::Assignment { .. } => unreachable!("handled above"),
+ }
}
fn with_breakable_ctx<T>(
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/infer/path.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer/path.rs
index 8bd17c0f3..0a8527afb 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/infer/path.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer/path.rs
@@ -112,7 +112,7 @@ impl<'a> InferenceContext<'a> {
let ty = TyBuilder::value_ty(self.db, typable, parent_substs)
.fill(|x| {
it.next().unwrap_or_else(|| match x {
- ParamKind::Type => TyKind::Error.intern(Interner).cast(Interner),
+ ParamKind::Type => self.result.standard_types.unknown.clone().cast(Interner),
ParamKind::Const(ty) => consteval::unknown_const_as_generic(ty.clone()),
})
})
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/infer/unify.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer/unify.rs
index e7ddd1591..46ed3533c 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/infer/unify.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer/unify.rs
@@ -8,6 +8,7 @@ use chalk_ir::{
};
use chalk_solve::infer::ParameterEnaVariableExt;
use ena::unify::UnifyKey;
+use hir_def::{FunctionId, TraitId};
use hir_expand::name;
use stdx::never;
@@ -626,18 +627,26 @@ impl<'a> InferenceTable<'a> {
}
}
- pub(crate) fn callable_sig(&mut self, ty: &Ty, num_args: usize) -> Option<(Vec<Ty>, Ty)> {
+ pub(crate) fn callable_sig(
+ &mut self,
+ ty: &Ty,
+ num_args: usize,
+ ) -> Option<(Option<(TraitId, FunctionId)>, Vec<Ty>, Ty)> {
match ty.callable_sig(self.db) {
- Some(sig) => Some((sig.params().to_vec(), sig.ret().clone())),
+ Some(sig) => Some((None, sig.params().to_vec(), sig.ret().clone())),
None => self.callable_sig_from_fn_trait(ty, num_args),
}
}
- fn callable_sig_from_fn_trait(&mut self, ty: &Ty, num_args: usize) -> Option<(Vec<Ty>, Ty)> {
+ fn callable_sig_from_fn_trait(
+ &mut self,
+ ty: &Ty,
+ num_args: usize,
+ ) -> Option<(Option<(TraitId, FunctionId)>, Vec<Ty>, Ty)> {
let krate = self.trait_env.krate;
let fn_once_trait = FnTrait::FnOnce.get_id(self.db, krate)?;
- let output_assoc_type =
- self.db.trait_data(fn_once_trait).associated_type_by_name(&name![Output])?;
+ let trait_data = self.db.trait_data(fn_once_trait);
+ let output_assoc_type = trait_data.associated_type_by_name(&name![Output])?;
let mut arg_tys = vec![];
let arg_ty = TyBuilder::tuple(num_args)
@@ -675,7 +684,11 @@ impl<'a> InferenceTable<'a> {
if self.db.trait_solve(krate, canonical.value.cast(Interner)).is_some() {
self.register_obligation(obligation.goal);
let return_ty = self.normalize_projection_ty(projection);
- Some((arg_tys, return_ty))
+ Some((
+ Some(fn_once_trait).zip(trait_data.method_by_name(&name!(call_once))),
+ arg_tys,
+ return_ty,
+ ))
} else {
None
}
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/interner.rs b/src/tools/rust-analyzer/crates/hir-ty/src/interner.rs
index 441503a30..7bf73560c 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/interner.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/interner.rs
@@ -4,11 +4,8 @@
use crate::{chalk_db, tls, GenericArg};
use base_db::salsa::InternId;
use chalk_ir::{Goal, GoalData};
-use hir_def::{
- intern::{impl_internable, InternStorage, Internable, Interned},
- type_ref::ConstScalar,
- TypeAliasId,
-};
+use hir_def::{type_ref::ConstScalar, TypeAliasId};
+use intern::{impl_internable, Interned};
use smallvec::SmallVec;
use std::{fmt, sync::Arc};
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/lang_items.rs b/src/tools/rust-analyzer/crates/hir-ty/src/lang_items.rs
index afc54e729..5308c7216 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/lang_items.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/lang_items.rs
@@ -1,20 +1,19 @@
//! Functions to detect special lang items
-use hir_def::{AdtId, HasModule};
-use hir_expand::name;
+use hir_def::{lang_item::LangItem, AdtId, HasModule};
use crate::db::HirDatabase;
pub fn is_box(adt: AdtId, db: &dyn HirDatabase) -> bool {
- let owned_box = name![owned_box].to_smol_str();
let krate = adt.module(db.upcast()).krate();
- let box_adt = db.lang_item(krate, owned_box).and_then(|it| it.as_struct()).map(AdtId::from);
+ let box_adt =
+ db.lang_item(krate, LangItem::OwnedBox).and_then(|it| it.as_struct()).map(AdtId::from);
Some(adt) == box_adt
}
pub fn is_unsafe_cell(adt: AdtId, db: &dyn HirDatabase) -> bool {
- let owned_box = name![unsafe_cell].to_smol_str();
let krate = adt.module(db.upcast()).krate();
- let box_adt = db.lang_item(krate, owned_box).and_then(|it| it.as_struct()).map(AdtId::from);
+ let box_adt =
+ db.lang_item(krate, LangItem::UnsafeCell).and_then(|it| it.as_struct()).map(AdtId::from);
Some(adt) == box_adt
}
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/layout.rs b/src/tools/rust-analyzer/crates/hir-ty/src/layout.rs
index 7a1cca314..f21b4f84c 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/layout.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/layout.rs
@@ -1,7 +1,5 @@
//! Compute the binary representation of a type
-use std::sync::Arc;
-
use base_db::CrateId;
use chalk_ir::{AdtId, TyKind};
use hir_def::{
@@ -31,19 +29,19 @@ mod adt;
mod target;
struct LayoutCx<'a> {
- db: &'a dyn HirDatabase,
krate: CrateId,
+ target: &'a TargetDataLayout,
}
-impl LayoutCalculator for LayoutCx<'_> {
- type TargetDataLayoutRef = Arc<TargetDataLayout>;
+impl<'a> LayoutCalculator for LayoutCx<'a> {
+ type TargetDataLayoutRef = &'a TargetDataLayout;
fn delay_bug(&self, txt: &str) {
never!("{}", txt);
}
- fn current_data_layout(&self) -> Arc<TargetDataLayout> {
- self.db.target_data_layout(self.krate)
+ fn current_data_layout(&self) -> &'a TargetDataLayout {
+ self.target
}
}
@@ -56,7 +54,8 @@ fn scalar(dl: &TargetDataLayout, value: Primitive) -> Layout {
}
pub fn layout_of_ty(db: &dyn HirDatabase, ty: &Ty, krate: CrateId) -> Result<Layout, LayoutError> {
- let cx = LayoutCx { db, krate };
+ let Some(target) = db.target_data_layout(krate) else { return Err(LayoutError::TargetLayoutNotAvailable) };
+ let cx = LayoutCx { krate, target: &target };
let dl = &*cx.current_data_layout();
Ok(match ty.kind(Interner) {
TyKind::Adt(AdtId(def), subst) => db.layout_of_adt(*def, subst.clone())?,
@@ -174,7 +173,7 @@ pub fn layout_of_ty(db: &dyn HirDatabase, ty: &Ty, krate: CrateId) -> Result<Lay
// let pointee = tcx.normalize_erasing_regions(param_env, pointee);
// if pointee.is_sized(tcx.at(DUMMY_SP), param_env) {
- // return Ok(tcx.intern_layout(LayoutS::scalar(cx, data_ptr)));
+ // return Ok(tcx.mk_layout(LayoutS::scalar(cx, data_ptr)));
// }
let unsized_part = struct_tail_erasing_lifetimes(db, pointee.clone());
@@ -226,10 +225,21 @@ pub fn layout_of_ty(db: &dyn HirDatabase, ty: &Ty, krate: CrateId) -> Result<Lay
ptr.valid_range_mut().start = 1;
Layout::scalar(dl, ptr)
}
- TyKind::Closure(_, _)
- | TyKind::OpaqueType(_, _)
- | TyKind::Generator(_, _)
- | TyKind::GeneratorWitness(_, _) => return Err(LayoutError::NotImplemented),
+ TyKind::OpaqueType(opaque_ty_id, _) => {
+ let impl_trait_id = db.lookup_intern_impl_trait_id((*opaque_ty_id).into());
+ match impl_trait_id {
+ crate::ImplTraitId::ReturnTypeImplTrait(func, idx) => {
+ let infer = db.infer(func.into());
+ layout_of_ty(db, &infer.type_of_rpit[idx], krate)?
+ }
+ crate::ImplTraitId::AsyncBlockTypeImplTrait(_, _) => {
+ return Err(LayoutError::NotImplemented)
+ }
+ }
+ }
+ TyKind::Closure(_, _) | TyKind::Generator(_, _) | TyKind::GeneratorWitness(_, _) => {
+ return Err(LayoutError::NotImplemented)
+ }
TyKind::AssociatedType(_, _)
| TyKind::Error
| TyKind::Alias(_)
@@ -251,17 +261,14 @@ fn layout_of_unit(cx: &LayoutCx<'_>, dl: &TargetDataLayout) -> Result<Layout, La
fn struct_tail_erasing_lifetimes(db: &dyn HirDatabase, pointee: Ty) -> Ty {
match pointee.kind(Interner) {
- TyKind::Adt(AdtId(adt), subst) => match adt {
- &hir_def::AdtId::StructId(i) => {
- let data = db.struct_data(i);
- let mut it = data.variant_data.fields().iter().rev();
- match it.next() {
- Some((f, _)) => field_ty(db, i.into(), f, subst),
- None => pointee,
- }
+ TyKind::Adt(AdtId(hir_def::AdtId::StructId(i)), subst) => {
+ let data = db.struct_data(*i);
+ let mut it = data.variant_data.fields().iter().rev();
+ match it.next() {
+ Some((f, _)) => field_ty(db, (*i).into(), f, subst),
+ None => pointee,
}
- _ => pointee,
- },
+ }
_ => pointee,
}
}
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/layout/adt.rs b/src/tools/rust-analyzer/crates/hir-ty/src/layout/adt.rs
index 23166a5a5..cb7968c14 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/layout/adt.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/layout/adt.rs
@@ -23,7 +23,9 @@ pub fn layout_of_adt_query(
def: AdtId,
subst: Substitution,
) -> Result<Layout, LayoutError> {
- let cx = LayoutCx { db, krate: def.module(db.upcast()).krate() };
+ let krate = def.module(db.upcast()).krate();
+ let Some(target) = db.target_data_layout(krate) else { return Err(LayoutError::TargetLayoutNotAvailable) };
+ let cx = LayoutCx { krate, target: &target };
let dl = cx.current_data_layout();
let handle_variant = |def: VariantId, var: &VariantData| {
var.fields()
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/layout/target.rs b/src/tools/rust-analyzer/crates/hir-ty/src/layout/target.rs
index 37b831652..adfae0a1a 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/layout/target.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/layout/target.rs
@@ -3,34 +3,22 @@
use std::sync::Arc;
use base_db::CrateId;
-use hir_def::layout::{Endian, Size, TargetDataLayout};
+use hir_def::layout::TargetDataLayout;
use crate::db::HirDatabase;
-pub fn target_data_layout_query(db: &dyn HirDatabase, krate: CrateId) -> Arc<TargetDataLayout> {
+pub fn target_data_layout_query(
+ db: &dyn HirDatabase,
+ krate: CrateId,
+) -> Option<Arc<TargetDataLayout>> {
let crate_graph = db.crate_graph();
- let target_layout = &crate_graph[krate].target_layout;
- let cfg_options = &crate_graph[krate].cfg_options;
- Arc::new(
- target_layout
- .as_ref()
- .and_then(|it| TargetDataLayout::parse_from_llvm_datalayout_string(it).ok())
- .unwrap_or_else(|| {
- let endian = match cfg_options.get_cfg_values("target_endian").next() {
- Some(x) if x.as_str() == "big" => Endian::Big,
- _ => Endian::Little,
- };
- let pointer_size = Size::from_bytes(
- match cfg_options.get_cfg_values("target_pointer_width").next() {
- Some(x) => match x.as_str() {
- "16" => 2,
- "32" => 4,
- _ => 8,
- },
- _ => 8,
- },
- );
- TargetDataLayout { endian, pointer_size, ..TargetDataLayout::default() }
- }),
- )
+ let target_layout = crate_graph[krate].target_layout.as_ref().ok()?;
+ let res = TargetDataLayout::parse_from_llvm_datalayout_string(&target_layout);
+ if let Err(_e) = &res {
+ // FIXME: Print the error here once it implements debug/display
+ // also logging here is somewhat wrong, but unfortunately this is the earliest place we can
+ // parse that doesn't impose a dependency to the rust-abi crate for project-model
+ tracing::error!("Failed to parse target data layout for {krate:?}");
+ }
+ res.ok().map(Arc::new)
}
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/layout/tests.rs b/src/tools/rust-analyzer/crates/hir-ty/src/layout/tests.rs
index 53838cf41..067bdc960 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/layout/tests.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/layout/tests.rs
@@ -1,3 +1,5 @@
+use std::collections::HashMap;
+
use base_db::fixture::WithFixture;
use chalk_ir::{AdtId, TyKind};
use hir_def::{
@@ -5,20 +7,16 @@ use hir_def::{
layout::{Layout, LayoutError},
};
-use crate::{test_db::TestDB, Interner, Substitution};
+use crate::{db::HirDatabase, test_db::TestDB, Interner, Substitution};
use super::layout_of_ty;
-fn eval_goal(ra_fixture: &str, minicore: &str) -> Result<Layout, LayoutError> {
- // using unstable cargo features failed, fall back to using plain rustc
- let mut cmd = std::process::Command::new("rustc");
- cmd.args(["-Z", "unstable-options", "--print", "target-spec-json"]).env("RUSTC_BOOTSTRAP", "1");
- let output = cmd.output().unwrap();
- assert!(output.status.success(), "{}", output.status);
- let stdout = String::from_utf8(output.stdout).unwrap();
- let target_data_layout =
- stdout.split_once(r#""data-layout": ""#).unwrap().1.split_once('"').unwrap().0.to_owned();
+fn current_machine_data_layout() -> String {
+ project_model::target_data_layout::get(None, None, &HashMap::default()).unwrap()
+}
+fn eval_goal(ra_fixture: &str, minicore: &str) -> Result<Layout, LayoutError> {
+ let target_data_layout = current_machine_data_layout();
let ra_fixture = format!(
"{minicore}//- /main.rs crate:test target_data_layout:{target_data_layout}\n{ra_fixture}",
);
@@ -45,6 +43,42 @@ fn eval_goal(ra_fixture: &str, minicore: &str) -> Result<Layout, LayoutError> {
layout_of_ty(&db, &goal_ty, module_id.krate())
}
+/// A version of `eval_goal` for types that can not be expressed in ADTs, like closures and `impl Trait`
+fn eval_expr(ra_fixture: &str, minicore: &str) -> Result<Layout, LayoutError> {
+ let target_data_layout = current_machine_data_layout();
+ let ra_fixture = format!(
+ "{minicore}//- /main.rs crate:test target_data_layout:{target_data_layout}\nfn main(){{let goal = {{{ra_fixture}}};}}",
+ );
+
+ let (db, file_id) = TestDB::with_single_file(&ra_fixture);
+ let module_id = db.module_for_file(file_id);
+ let def_map = module_id.def_map(&db);
+ let scope = &def_map[module_id.local_id].scope;
+ let adt_id = scope
+ .declarations()
+ .find_map(|x| match x {
+ hir_def::ModuleDefId::FunctionId(x) => {
+ let name = db.function_data(x).name.to_smol_str();
+ (name == "main").then_some(x)
+ }
+ _ => None,
+ })
+ .unwrap();
+ let hir_body = db.body(adt_id.into());
+ let pat = hir_body
+ .pats
+ .iter()
+ .find(|x| match x.1 {
+ hir_def::expr::Pat::Bind { name, .. } => name.to_smol_str() == "goal",
+ _ => false,
+ })
+ .unwrap()
+ .0;
+ let infer = db.infer(adt_id.into());
+ let goal_ty = infer.type_of_pat[pat].clone();
+ layout_of_ty(&db, &goal_ty, module_id.krate())
+}
+
#[track_caller]
fn check_size_and_align(ra_fixture: &str, minicore: &str, size: u64, align: u64) {
let l = eval_goal(ra_fixture, minicore).unwrap();
@@ -53,6 +87,13 @@ fn check_size_and_align(ra_fixture: &str, minicore: &str, size: u64, align: u64)
}
#[track_caller]
+fn check_size_and_align_expr(ra_fixture: &str, minicore: &str, size: u64, align: u64) {
+ let l = eval_expr(ra_fixture, minicore).unwrap();
+ assert_eq!(l.size.bytes(), size);
+ assert_eq!(l.align.abi.bytes(), align);
+}
+
+#[track_caller]
fn check_fail(ra_fixture: &str, e: LayoutError) {
let r = eval_goal(ra_fixture, "");
assert_eq!(r, Err(e));
@@ -85,11 +126,31 @@ macro_rules! size_and_align {
};
}
+macro_rules! size_and_align_expr {
+ ($($t:tt)*) => {
+ {
+ #[allow(dead_code)]
+ {
+ let val = { $($t)* };
+ check_size_and_align_expr(
+ stringify!($($t)*),
+ "",
+ ::std::mem::size_of_val(&val) as u64,
+ ::std::mem::align_of_val(&val) as u64,
+ );
+ }
+ }
+ };
+}
+
#[test]
fn hello_world() {
size_and_align! {
struct Goal(i32);
}
+ size_and_align_expr! {
+ 2i32
+ }
}
#[test]
@@ -144,6 +205,40 @@ fn generic() {
}
#[test]
+fn return_position_impl_trait() {
+ size_and_align_expr! {
+ trait T {}
+ impl T for i32 {}
+ impl T for i64 {}
+ fn foo() -> impl T { 2i64 }
+ foo()
+ }
+ size_and_align_expr! {
+ trait T {}
+ impl T for i32 {}
+ impl T for i64 {}
+ fn foo() -> (impl T, impl T, impl T) { (2i64, 5i32, 7i32) }
+ foo()
+ }
+ size_and_align_expr! {
+ struct Foo<T>(T, T, (T, T));
+ trait T {}
+ impl T for Foo<i32> {}
+ impl T for Foo<i64> {}
+
+ fn foo() -> Foo<impl T> { Foo(
+ Foo(1i64, 2, (3, 4)),
+ Foo(5, 6, (7, 8)),
+ (
+ Foo(1i64, 2, (3, 4)),
+ Foo(5, 6, (7, 8)),
+ ),
+ ) }
+ foo()
+ }
+}
+
+#[test]
fn enums() {
size_and_align! {
enum Goal {
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/lib.rs b/src/tools/rust-analyzer/crates/hir-ty/src/lib.rs
index cbe6873c7..59a5ef8c1 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/lib.rs
@@ -20,7 +20,6 @@ mod lower;
mod mapping;
mod tls;
mod utils;
-mod walk;
pub mod db;
pub mod diagnostics;
pub mod display;
@@ -40,11 +39,14 @@ use std::sync::Arc;
use chalk_ir::{
fold::{Shift, TypeFoldable},
interner::HasInterner,
- NoSolution,
+ visit::{TypeSuperVisitable, TypeVisitable, TypeVisitor},
+ NoSolution, TyData,
};
use hir_def::{expr::ExprId, type_ref::Rawness, TypeOrConstParamId};
use hir_expand::name;
use itertools::Either;
+use la_arena::{Arena, Idx};
+use rustc_hash::FxHashSet;
use traits::FnTrait;
use utils::Generics;
@@ -71,7 +73,6 @@ pub use mapping::{
};
pub use traits::TraitEnvironment;
pub use utils::{all_super_traits, is_fn_unsafe_to_call};
-pub use walk::TypeWalk;
pub use chalk_ir::{
cast::Cast, AdtId, BoundVar, DebruijnIndex, Mutability, Safety, Scalar, TyVariableKind,
@@ -107,6 +108,7 @@ pub type GenericArgData = chalk_ir::GenericArgData<Interner>;
pub type Ty = chalk_ir::Ty<Interner>;
pub type TyKind = chalk_ir::TyKind<Interner>;
+pub type TypeFlags = chalk_ir::TypeFlags;
pub type DynTy = chalk_ir::DynTy<Interner>;
pub type FnPointer = chalk_ir::FnPointer<Interner>;
// pub type FnSubst = chalk_ir::FnSubst<Interner>;
@@ -289,22 +291,24 @@ impl TypeFoldable<Interner> for CallableSig {
#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)]
pub enum ImplTraitId {
- ReturnTypeImplTrait(hir_def::FunctionId, u16),
+ ReturnTypeImplTrait(hir_def::FunctionId, RpitId),
AsyncBlockTypeImplTrait(hir_def::DefWithBodyId, ExprId),
}
#[derive(Clone, PartialEq, Eq, Debug, Hash)]
pub struct ReturnTypeImplTraits {
- pub(crate) impl_traits: Vec<ReturnTypeImplTrait>,
+ pub(crate) impl_traits: Arena<ReturnTypeImplTrait>,
}
has_interner!(ReturnTypeImplTraits);
#[derive(Clone, PartialEq, Eq, Debug, Hash)]
-pub(crate) struct ReturnTypeImplTrait {
+pub struct ReturnTypeImplTrait {
pub(crate) bounds: Binders<Vec<QuantifiedWhereClause>>,
}
+pub type RpitId = Idx<ReturnTypeImplTrait>;
+
pub fn static_lifetime() -> Lifetime {
LifetimeData::Static.intern(Interner)
}
@@ -563,3 +567,68 @@ pub fn callable_sig_from_fnonce(
Some(CallableSig::from_params_and_return(params, ret_ty, false, Safety::Safe))
}
+
+struct PlaceholderCollector<'db> {
+ db: &'db dyn HirDatabase,
+ placeholders: FxHashSet<TypeOrConstParamId>,
+}
+
+impl PlaceholderCollector<'_> {
+ fn collect(&mut self, idx: PlaceholderIndex) {
+ let id = from_placeholder_idx(self.db, idx);
+ self.placeholders.insert(id);
+ }
+}
+
+impl TypeVisitor<Interner> for PlaceholderCollector<'_> {
+ type BreakTy = ();
+
+ fn as_dyn(&mut self) -> &mut dyn TypeVisitor<Interner, BreakTy = Self::BreakTy> {
+ self
+ }
+
+ fn interner(&self) -> Interner {
+ Interner
+ }
+
+ fn visit_ty(
+ &mut self,
+ ty: &Ty,
+ outer_binder: DebruijnIndex,
+ ) -> std::ops::ControlFlow<Self::BreakTy> {
+ let has_placeholder_bits = TypeFlags::HAS_TY_PLACEHOLDER | TypeFlags::HAS_CT_PLACEHOLDER;
+ let TyData { kind, flags } = ty.data(Interner);
+
+ if let TyKind::Placeholder(idx) = kind {
+ self.collect(*idx);
+ } else if flags.intersects(has_placeholder_bits) {
+ return ty.super_visit_with(self, outer_binder);
+ } else {
+ // Fast path: don't visit inner types (e.g. generic arguments) when `flags` indicate
+ // that there are no placeholders.
+ }
+
+ std::ops::ControlFlow::Continue(())
+ }
+
+ fn visit_const(
+ &mut self,
+ constant: &chalk_ir::Const<Interner>,
+ _outer_binder: DebruijnIndex,
+ ) -> std::ops::ControlFlow<Self::BreakTy> {
+ if let chalk_ir::ConstValue::Placeholder(idx) = constant.data(Interner).value {
+ self.collect(idx);
+ }
+ std::ops::ControlFlow::Continue(())
+ }
+}
+
+/// Returns unique placeholders for types and consts contained in `value`.
+pub fn collect_placeholders<T>(value: &T, db: &dyn HirDatabase) -> Vec<TypeOrConstParamId>
+where
+ T: ?Sized + TypeVisitable<Interner>,
+{
+ let mut collector = PlaceholderCollector { db, placeholders: FxHashSet::default() };
+ value.visit_with(&mut collector, DebruijnIndex::INNERMOST);
+ collector.placeholders.into_iter().collect()
+}
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/lower.rs b/src/tools/rust-analyzer/crates/hir-ty/src/lower.rs
index 592410008..299646737 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/lower.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/lower.rs
@@ -23,24 +23,24 @@ use hir_def::{
generics::{
TypeOrConstParamData, TypeParamProvenance, WherePredicate, WherePredicateTypeTarget,
},
- intern::Interned,
- lang_item::lang_attr,
+ lang_item::{lang_attr, LangItem},
path::{GenericArg, ModPath, Path, PathKind, PathSegment, PathSegments},
resolver::{HasResolver, Resolver, TypeNs},
type_ref::{
ConstScalarOrPath, TraitBoundModifier, TraitRef as HirTraitRef, TypeBound, TypeRef,
},
AdtId, AssocItemId, ConstId, ConstParamId, EnumId, EnumVariantId, FunctionId, GenericDefId,
- HasModule, ImplId, ItemContainerId, LocalFieldId, Lookup, StaticId, StructId, TraitId,
- TypeAliasId, TypeOrConstParamId, TypeParamId, UnionId, VariantId,
+ HasModule, ImplId, ItemContainerId, LocalFieldId, Lookup, ModuleDefId, StaticId, StructId,
+ TraitId, TypeAliasId, TypeOrConstParamId, TypeParamId, UnionId, VariantId,
};
use hir_expand::{name::Name, ExpandResult};
+use intern::Interned;
use itertools::Either;
-use la_arena::ArenaMap;
+use la_arena::{Arena, ArenaMap};
use rustc_hash::FxHashSet;
use smallvec::SmallVec;
use stdx::{impl_from, never};
-use syntax::{ast, SmolStr};
+use syntax::ast;
use crate::{
all_super_traits,
@@ -58,6 +58,51 @@ use crate::{
};
#[derive(Debug)]
+enum ImplTraitLoweringState {
+ /// When turning `impl Trait` into opaque types, we have to collect the
+ /// bounds at the same time to get the IDs correct (without becoming too
+ /// complicated). I don't like using interior mutability (as for the
+ /// counter), but I've tried and failed to make the lifetimes work for
+ /// passing around a `&mut TyLoweringContext`. The core problem is that
+ /// we're grouping the mutable data (the counter and this field) together
+ /// with the immutable context (the references to the DB and resolver).
+ /// Splitting this up would be a possible fix.
+ Opaque(RefCell<Arena<ReturnTypeImplTrait>>),
+ Param(Cell<u16>),
+ Variable(Cell<u16>),
+ Disallowed,
+}
+impl ImplTraitLoweringState {
+ fn new(impl_trait_mode: ImplTraitLoweringMode) -> ImplTraitLoweringState {
+ match impl_trait_mode {
+ ImplTraitLoweringMode::Opaque => Self::Opaque(RefCell::new(Arena::new())),
+ ImplTraitLoweringMode::Param => Self::Param(Cell::new(0)),
+ ImplTraitLoweringMode::Variable => Self::Variable(Cell::new(0)),
+ ImplTraitLoweringMode::Disallowed => Self::Disallowed,
+ }
+ }
+
+ fn take(&self) -> Self {
+ match self {
+ Self::Opaque(x) => Self::Opaque(RefCell::new(x.take())),
+ Self::Param(x) => Self::Param(Cell::new(x.get())),
+ Self::Variable(x) => Self::Variable(Cell::new(x.get())),
+ Self::Disallowed => Self::Disallowed,
+ }
+ }
+
+ fn swap(&self, impl_trait_mode: &Self) {
+ match (self, impl_trait_mode) {
+ (Self::Opaque(x), Self::Opaque(y)) => x.swap(y),
+ (Self::Param(x), Self::Param(y)) => x.swap(y),
+ (Self::Variable(x), Self::Variable(y)) => x.swap(y),
+ (Self::Disallowed, Self::Disallowed) => (),
+ _ => panic!("mismatched lowering mode"),
+ }
+ }
+}
+
+#[derive(Debug)]
pub struct TyLoweringContext<'a> {
pub db: &'a dyn HirDatabase,
pub resolver: &'a Resolver,
@@ -67,17 +112,7 @@ pub struct TyLoweringContext<'a> {
/// should be converted to variables. I think in practice, this isn't
/// possible currently, so this should be fine for now.
pub type_param_mode: ParamLoweringMode,
- pub impl_trait_mode: ImplTraitLoweringMode,
- impl_trait_counter: Cell<u16>,
- /// When turning `impl Trait` into opaque types, we have to collect the
- /// bounds at the same time to get the IDs correct (without becoming too
- /// complicated). I don't like using interior mutability (as for the
- /// counter), but I've tried and failed to make the lifetimes work for
- /// passing around a `&mut TyLoweringContext`. The core problem is that
- /// we're grouping the mutable data (the counter and this field) together
- /// with the immutable context (the references to the DB and resolver).
- /// Splitting this up would be a possible fix.
- opaque_type_data: RefCell<Vec<ReturnTypeImplTrait>>,
+ impl_trait_mode: ImplTraitLoweringState,
expander: RefCell<Option<Expander>>,
/// Tracks types with explicit `?Sized` bounds.
pub(crate) unsized_types: RefCell<FxHashSet<Ty>>,
@@ -85,19 +120,15 @@ pub struct TyLoweringContext<'a> {
impl<'a> TyLoweringContext<'a> {
pub fn new(db: &'a dyn HirDatabase, resolver: &'a Resolver) -> Self {
- let impl_trait_counter = Cell::new(0);
- let impl_trait_mode = ImplTraitLoweringMode::Disallowed;
+ let impl_trait_mode = ImplTraitLoweringState::Disallowed;
let type_param_mode = ParamLoweringMode::Placeholder;
let in_binders = DebruijnIndex::INNERMOST;
- let opaque_type_data = RefCell::new(Vec::new());
Self {
db,
resolver,
in_binders,
impl_trait_mode,
- impl_trait_counter,
type_param_mode,
- opaque_type_data,
expander: RefCell::new(None),
unsized_types: RefCell::default(),
}
@@ -108,20 +139,18 @@ impl<'a> TyLoweringContext<'a> {
debruijn: DebruijnIndex,
f: impl FnOnce(&TyLoweringContext<'_>) -> T,
) -> T {
- let opaque_ty_data_vec = self.opaque_type_data.take();
+ let impl_trait_mode = self.impl_trait_mode.take();
let expander = self.expander.take();
let unsized_types = self.unsized_types.take();
let new_ctx = Self {
in_binders: debruijn,
- impl_trait_counter: Cell::new(self.impl_trait_counter.get()),
- opaque_type_data: RefCell::new(opaque_ty_data_vec),
+ impl_trait_mode,
expander: RefCell::new(expander),
unsized_types: RefCell::new(unsized_types),
..*self
};
let result = f(&new_ctx);
- self.impl_trait_counter.set(new_ctx.impl_trait_counter.get());
- self.opaque_type_data.replace(new_ctx.opaque_type_data.into_inner());
+ self.impl_trait_mode.swap(&new_ctx.impl_trait_mode);
self.expander.replace(new_ctx.expander.into_inner());
self.unsized_types.replace(new_ctx.unsized_types.into_inner());
result
@@ -136,7 +165,7 @@ impl<'a> TyLoweringContext<'a> {
}
pub fn with_impl_trait_mode(self, impl_trait_mode: ImplTraitLoweringMode) -> Self {
- Self { impl_trait_mode, ..self }
+ Self { impl_trait_mode: ImplTraitLoweringState::new(impl_trait_mode), ..self }
}
pub fn with_type_param_mode(self, type_param_mode: ParamLoweringMode) -> Self {
@@ -244,20 +273,17 @@ impl<'a> TyLoweringContext<'a> {
}
TypeRef::DynTrait(bounds) => self.lower_dyn_trait(bounds),
TypeRef::ImplTrait(bounds) => {
- match self.impl_trait_mode {
- ImplTraitLoweringMode::Opaque => {
- let idx = self.impl_trait_counter.get();
- self.impl_trait_counter.set(idx + 1);
+ match &self.impl_trait_mode {
+ ImplTraitLoweringState::Opaque(opaque_type_data) => {
let func = match self.resolver.generic_def() {
Some(GenericDefId::FunctionId(f)) => f,
_ => panic!("opaque impl trait lowering in non-function"),
};
- assert!(idx as usize == self.opaque_type_data.borrow().len());
// this dance is to make sure the data is in the right
// place even if we encounter more opaque types while
// lowering the bounds
- self.opaque_type_data.borrow_mut().push(ReturnTypeImplTrait {
+ let idx = opaque_type_data.borrow_mut().alloc(ReturnTypeImplTrait {
bounds: crate::make_single_type_binders(Vec::new()),
});
// We don't want to lower the bounds inside the binders
@@ -273,7 +299,7 @@ impl<'a> TyLoweringContext<'a> {
.with_debruijn(DebruijnIndex::INNERMOST, |ctx| {
ctx.lower_impl_trait(bounds, func)
});
- self.opaque_type_data.borrow_mut()[idx as usize] = actual_opaque_type_data;
+ opaque_type_data.borrow_mut()[idx] = actual_opaque_type_data;
let impl_trait_id = ImplTraitId::ReturnTypeImplTrait(func, idx);
let opaque_ty_id = self.db.intern_impl_trait_id(impl_trait_id).into();
@@ -281,10 +307,10 @@ impl<'a> TyLoweringContext<'a> {
let parameters = generics.bound_vars_subst(self.db, self.in_binders);
TyKind::OpaqueType(opaque_ty_id, parameters).intern(Interner)
}
- ImplTraitLoweringMode::Param => {
- let idx = self.impl_trait_counter.get();
+ ImplTraitLoweringState::Param(counter) => {
+ let idx = counter.get();
// FIXME we're probably doing something wrong here
- self.impl_trait_counter.set(idx + count_impl_traits(type_ref) as u16);
+ counter.set(idx + count_impl_traits(type_ref) as u16);
if let Some(def) = self.resolver.generic_def() {
let generics = generics(self.db.upcast(), def);
let param = generics
@@ -305,10 +331,10 @@ impl<'a> TyLoweringContext<'a> {
TyKind::Error.intern(Interner)
}
}
- ImplTraitLoweringMode::Variable => {
- let idx = self.impl_trait_counter.get();
+ ImplTraitLoweringState::Variable(counter) => {
+ let idx = counter.get();
// FIXME we're probably doing something wrong here
- self.impl_trait_counter.set(idx + count_impl_traits(type_ref) as u16);
+ counter.set(idx + count_impl_traits(type_ref) as u16);
let (
_parent_params,
self_params,
@@ -327,7 +353,7 @@ impl<'a> TyLoweringContext<'a> {
))
.intern(Interner)
}
- ImplTraitLoweringMode::Disallowed => {
+ ImplTraitLoweringState::Disallowed => {
// FIXME: report error
TyKind::Error.intern(Interner)
}
@@ -954,7 +980,7 @@ impl<'a> TyLoweringContext<'a> {
TypeBound::Path(path, TraitBoundModifier::Maybe) => {
let sized_trait = self
.db
- .lang_item(self.resolver.krate(), SmolStr::new_inline("sized"))
+ .lang_item(self.resolver.krate(), LangItem::Sized)
.and_then(|lang_item| lang_item.as_trait());
// Don't lower associated type bindings as the only possible relaxed trait bound
// `?Sized` has no of them.
@@ -999,7 +1025,7 @@ impl<'a> TyLoweringContext<'a> {
last_segment
.into_iter()
.filter_map(|segment| segment.args_and_bindings)
- .flat_map(|args_and_bindings| &args_and_bindings.bindings)
+ .flat_map(|args_and_bindings| args_and_bindings.bindings.iter())
.flat_map(move |binding| {
let found = associated_type_by_name_including_super_traits(
self.db,
@@ -1042,7 +1068,7 @@ impl<'a> TyLoweringContext<'a> {
AliasEq { alias: AliasTy::Projection(projection_ty.clone()), ty };
preds.push(crate::wrap_empty_binders(WhereClause::AliasEq(alias_eq)));
}
- for bound in &binding.bounds {
+ for bound in binding.bounds.iter() {
preds.extend(self.lower_type_bound(
bound,
TyKind::Alias(AliasTy::Projection(projection_ty.clone())).intern(Interner),
@@ -1150,7 +1176,7 @@ impl<'a> TyLoweringContext<'a> {
let krate = func.lookup(ctx.db.upcast()).module(ctx.db.upcast()).krate();
let sized_trait = ctx
.db
- .lang_item(krate, SmolStr::new_inline("sized"))
+ .lang_item(krate, LangItem::Sized)
.and_then(|lang_item| lang_item.as_trait().map(to_chalk_trait_id));
let sized_clause = sized_trait.map(|trait_id| {
let clause = WhereClause::Implemented(TraitRef {
@@ -1209,7 +1235,7 @@ fn named_associated_type_shorthand_candidates<R>(
mut cb: impl FnMut(&Name, &TraitRef, TypeAliasId) -> Option<R>,
) -> Option<R> {
let mut search = |t| {
- for t in all_super_trait_refs(db, t) {
+ all_super_trait_refs(db, t, |t| {
let data = db.trait_data(t.hir_trait_id());
for (name, assoc_id) in &data.items {
@@ -1219,8 +1245,8 @@ fn named_associated_type_shorthand_candidates<R>(
}
}
}
- }
- None
+ None
+ })
};
match res {
@@ -1489,7 +1515,7 @@ fn implicitly_sized_clauses<'a>(
let is_trait_def = matches!(def, GenericDefId::TraitId(..));
let generic_args = &substitution.as_slice(Interner)[is_trait_def as usize..];
let sized_trait = db
- .lang_item(resolver.krate(), SmolStr::new_inline("sized"))
+ .lang_item(resolver.krate(), LangItem::Sized)
.and_then(|lang_item| lang_item.as_trait().map(to_chalk_trait_id));
sized_trait.into_iter().flat_map(move |sized_trait| {
@@ -1704,6 +1730,15 @@ pub enum CallableDefId {
EnumVariantId(EnumVariantId),
}
impl_from!(FunctionId, StructId, EnumVariantId for CallableDefId);
+impl From<CallableDefId> for ModuleDefId {
+ fn from(def: CallableDefId) -> ModuleDefId {
+ match def {
+ CallableDefId::FunctionId(f) => ModuleDefId::FunctionId(f),
+ CallableDefId::StructId(s) => ModuleDefId::AdtId(AdtId::StructId(s)),
+ CallableDefId::EnumVariantId(e) => ModuleDefId::EnumVariantId(e),
+ }
+ }
+}
impl CallableDefId {
pub fn krate(self, db: &dyn HirDatabase) -> CrateId {
@@ -1854,8 +1889,12 @@ pub(crate) fn return_type_impl_traits(
.with_type_param_mode(ParamLoweringMode::Variable);
let _ret = ctx_ret.lower_ty(&data.ret_type);
let generics = generics(db.upcast(), def.into());
- let return_type_impl_traits =
- ReturnTypeImplTraits { impl_traits: ctx_ret.opaque_type_data.into_inner() };
+ let return_type_impl_traits = ReturnTypeImplTraits {
+ impl_traits: match ctx_ret.impl_trait_mode {
+ ImplTraitLoweringState::Opaque(x) => x.into_inner(),
+ _ => unreachable!(),
+ },
+ };
if return_type_impl_traits.impl_traits.is_empty() {
None
} else {
@@ -1931,7 +1970,7 @@ pub(crate) fn const_or_path_to_chalk(
debruijn: DebruijnIndex,
) -> Const {
match value {
- ConstScalarOrPath::Scalar(s) => intern_const_scalar(s.clone(), expected_ty),
+ ConstScalarOrPath::Scalar(s) => intern_const_scalar(*s, expected_ty),
ConstScalarOrPath::Path(n) => {
let path = ModPath::from_segments(PathKind::Plain, Some(n.clone()));
path_to_const(db, resolver, &path, mode, args, debruijn)
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/method_resolution.rs b/src/tools/rust-analyzer/crates/hir-ty/src/method_resolution.rs
index 2328dceb8..8c7714b9a 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/method_resolution.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/method_resolution.rs
@@ -5,10 +5,11 @@
use std::{ops::ControlFlow, sync::Arc};
use base_db::{CrateId, Edition};
-use chalk_ir::{cast::Cast, Mutability, UniverseIndex};
+use chalk_ir::{cast::Cast, Mutability, TyKind, UniverseIndex};
use hir_def::{
- data::ImplData, item_scope::ItemScope, nameres::DefMap, AssocItemId, BlockId, ConstId,
- FunctionId, HasModule, ImplId, ItemContainerId, Lookup, ModuleDefId, ModuleId, TraitId,
+ data::ImplData, item_scope::ItemScope, lang_item::LangItem, nameres::DefMap, AssocItemId,
+ BlockId, ConstId, FunctionId, HasModule, ImplId, ItemContainerId, Lookup, ModuleDefId,
+ ModuleId, TraitId,
};
use hir_expand::name::Name;
use rustc_hash::{FxHashMap, FxHashSet};
@@ -24,7 +25,7 @@ use crate::{
static_lifetime, to_chalk_trait_id,
utils::all_super_traits,
AdtId, Canonical, CanonicalVarKinds, DebruijnIndex, ForeignDefId, InEnvironment, Interner,
- Scalar, Substitution, TraitEnvironment, TraitRef, TraitRefExt, Ty, TyBuilder, TyExt, TyKind,
+ Scalar, Substitution, TraitEnvironment, TraitRef, TraitRefExt, Ty, TyBuilder, TyExt,
};
/// This is used as a key for indexing impls.
@@ -437,49 +438,49 @@ pub fn def_crates(
}
}
-pub fn lang_names_for_bin_op(op: syntax::ast::BinaryOp) -> Option<(Name, Name)> {
+pub fn lang_items_for_bin_op(op: syntax::ast::BinaryOp) -> Option<(Name, LangItem)> {
use hir_expand::name;
use syntax::ast::{ArithOp, BinaryOp, CmpOp, Ordering};
Some(match op {
BinaryOp::LogicOp(_) => return None,
BinaryOp::ArithOp(aop) => match aop {
- ArithOp::Add => (name!(add), name!(add)),
- ArithOp::Mul => (name!(mul), name!(mul)),
- ArithOp::Sub => (name!(sub), name!(sub)),
- ArithOp::Div => (name!(div), name!(div)),
- ArithOp::Rem => (name!(rem), name!(rem)),
- ArithOp::Shl => (name!(shl), name!(shl)),
- ArithOp::Shr => (name!(shr), name!(shr)),
- ArithOp::BitXor => (name!(bitxor), name!(bitxor)),
- ArithOp::BitOr => (name!(bitor), name!(bitor)),
- ArithOp::BitAnd => (name!(bitand), name!(bitand)),
+ ArithOp::Add => (name![add], LangItem::Add),
+ ArithOp::Mul => (name![mul], LangItem::Mul),
+ ArithOp::Sub => (name![sub], LangItem::Sub),
+ ArithOp::Div => (name![div], LangItem::Div),
+ ArithOp::Rem => (name![rem], LangItem::Rem),
+ ArithOp::Shl => (name![shl], LangItem::Shl),
+ ArithOp::Shr => (name![shr], LangItem::Shr),
+ ArithOp::BitXor => (name![bitxor], LangItem::BitXor),
+ ArithOp::BitOr => (name![bitor], LangItem::BitOr),
+ ArithOp::BitAnd => (name![bitand], LangItem::BitAnd),
},
BinaryOp::Assignment { op: Some(aop) } => match aop {
- ArithOp::Add => (name!(add_assign), name!(add_assign)),
- ArithOp::Mul => (name!(mul_assign), name!(mul_assign)),
- ArithOp::Sub => (name!(sub_assign), name!(sub_assign)),
- ArithOp::Div => (name!(div_assign), name!(div_assign)),
- ArithOp::Rem => (name!(rem_assign), name!(rem_assign)),
- ArithOp::Shl => (name!(shl_assign), name!(shl_assign)),
- ArithOp::Shr => (name!(shr_assign), name!(shr_assign)),
- ArithOp::BitXor => (name!(bitxor_assign), name!(bitxor_assign)),
- ArithOp::BitOr => (name!(bitor_assign), name!(bitor_assign)),
- ArithOp::BitAnd => (name!(bitand_assign), name!(bitand_assign)),
+ ArithOp::Add => (name![add_assign], LangItem::AddAssign),
+ ArithOp::Mul => (name![mul_assign], LangItem::MulAssign),
+ ArithOp::Sub => (name![sub_assign], LangItem::SubAssign),
+ ArithOp::Div => (name![div_assign], LangItem::DivAssign),
+ ArithOp::Rem => (name![rem_assign], LangItem::RemAssign),
+ ArithOp::Shl => (name![shl_assign], LangItem::ShlAssign),
+ ArithOp::Shr => (name![shr_assign], LangItem::ShrAssign),
+ ArithOp::BitXor => (name![bitxor_assign], LangItem::BitXorAssign),
+ ArithOp::BitOr => (name![bitor_assign], LangItem::BitOrAssign),
+ ArithOp::BitAnd => (name![bitand_assign], LangItem::BitAndAssign),
},
BinaryOp::CmpOp(cop) => match cop {
- CmpOp::Eq { negated: false } => (name!(eq), name!(eq)),
- CmpOp::Eq { negated: true } => (name!(ne), name!(eq)),
+ CmpOp::Eq { negated: false } => (name![eq], LangItem::PartialEq),
+ CmpOp::Eq { negated: true } => (name![ne], LangItem::PartialEq),
CmpOp::Ord { ordering: Ordering::Less, strict: false } => {
- (name!(le), name!(partial_ord))
+ (name![le], LangItem::PartialOrd)
}
CmpOp::Ord { ordering: Ordering::Less, strict: true } => {
- (name!(lt), name!(partial_ord))
+ (name![lt], LangItem::PartialOrd)
}
CmpOp::Ord { ordering: Ordering::Greater, strict: false } => {
- (name!(ge), name!(partial_ord))
+ (name![ge], LangItem::PartialOrd)
}
CmpOp::Ord { ordering: Ordering::Greater, strict: true } => {
- (name!(gt), name!(partial_ord))
+ (name![gt], LangItem::PartialOrd)
}
},
BinaryOp::Assignment { op: None } => return None,
@@ -587,25 +588,31 @@ impl ReceiverAdjustments {
}
}
}
+ if let Some(m) = self.autoref {
+ ty = TyKind::Ref(m, static_lifetime(), ty).intern(Interner);
+ adjust
+ .push(Adjustment { kind: Adjust::Borrow(AutoBorrow::Ref(m)), target: ty.clone() });
+ }
if self.unsize_array {
- ty = match ty.kind(Interner) {
- TyKind::Array(inner, _) => TyKind::Slice(inner.clone()).intern(Interner),
- _ => {
- never!("unsize_array with non-array {:?}", ty);
- ty
+ ty = 'x: {
+ if let TyKind::Ref(m, l, inner) = ty.kind(Interner) {
+ if let TyKind::Array(inner, _) = inner.kind(Interner) {
+ break 'x TyKind::Ref(
+ m.clone(),
+ l.clone(),
+ TyKind::Slice(inner.clone()).intern(Interner),
+ )
+ .intern(Interner);
+ }
}
+ never!("unsize_array with non-reference-to-array {:?}", ty);
+ ty
};
- // FIXME this is kind of wrong since the unsize needs to happen to a pointer/reference
adjust.push(Adjustment {
kind: Adjust::Pointer(PointerCast::Unsize),
target: ty.clone(),
});
}
- if let Some(m) = self.autoref {
- ty = TyKind::Ref(m, static_lifetime(), ty).intern(Interner);
- adjust
- .push(Adjustment { kind: Adjust::Borrow(AutoBorrow::Ref(m)), target: ty.clone() });
- }
(ty, adjust)
}
@@ -712,17 +719,17 @@ fn lookup_impl_assoc_item_for_trait_ref(
let table = InferenceTable::new(db, env);
let impl_data = find_matching_impl(impls, table, trait_ref)?;
- impl_data.items.iter().find_map(|it| match it {
+ impl_data.items.iter().find_map(|&it| match it {
AssocItemId::FunctionId(f) => {
- (db.function_data(*f).name == *name).then_some(AssocItemId::FunctionId(*f))
+ (db.function_data(f).name == *name).then_some(AssocItemId::FunctionId(f))
}
AssocItemId::ConstId(c) => db
- .const_data(*c)
+ .const_data(c)
.name
.as_ref()
- .map(|n| *n == *name)
- .and_then(|result| if result { Some(AssocItemId::ConstId(*c)) } else { None }),
- _ => None,
+ .map(|n| n == name)
+ .and_then(|result| if result { Some(AssocItemId::ConstId(c)) } else { None }),
+ AssocItemId::TypeAliasId(_) => None,
})
}
@@ -1094,13 +1101,13 @@ fn iterate_inherent_methods(
None => return ControlFlow::Continue(()),
};
- let (module, block) = match visible_from_module {
+ let (module, mut block) = match visible_from_module {
VisibleFromModule::Filter(module) => (Some(module), module.containing_block()),
VisibleFromModule::IncludeBlock(block) => (None, Some(block)),
VisibleFromModule::None => (None, None),
};
- if let Some(block_id) = block {
+ while let Some(block_id) = block {
if let Some(impls) = db.inherent_impls_in_block(block_id) {
impls_for_self_ty(
&impls,
@@ -1113,6 +1120,11 @@ fn iterate_inherent_methods(
callback,
)?;
}
+
+ block = db
+ .block_def_map(block_id)
+ .and_then(|map| map.parent())
+ .and_then(|module| module.containing_block());
}
for krate in def_crates {
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/tests/method_resolution.rs b/src/tools/rust-analyzer/crates/hir-ty/src/tests/method_resolution.rs
index 6c7a53299..41c53701d 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/tests/method_resolution.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/tests/method_resolution.rs
@@ -813,7 +813,7 @@ fn test() {
fn method_resolution_trait_from_prelude() {
check_types(
r#"
-//- /main.rs crate:main deps:core
+//- /main.rs edition:2018 crate:main deps:core
struct S;
impl Clone for S {}
@@ -986,14 +986,13 @@ fn main() {
}
#[test]
-fn method_resolution_encountering_fn_type() {
+fn explicit_fn_once_call_fn_item() {
check_types(
r#"
-//- /main.rs
+//- minicore: fn
fn foo() {}
-trait FnOnce { fn call(self); }
-fn test() { foo.call(); }
- //^^^^^^^^^^ {unknown}
+fn test() { foo.call_once(); }
+ //^^^^^^^^^^^^^^^ ()
"#,
);
}
@@ -1527,7 +1526,7 @@ fn f(x: U2) {
fn skip_array_during_method_dispatch() {
check_types(
r#"
-//- /main2018.rs crate:main2018 deps:core
+//- /main2018.rs crate:main2018 deps:core edition:2018
use core::IntoIterator;
fn f() {
@@ -1725,14 +1724,13 @@ fn test() {
#[test]
fn receiver_adjustment_unsize_array() {
- // FIXME not quite correct
check(
r#"
//- minicore: slice
fn test() {
let a = [1, 2, 3];
a.len();
-} //^ adjustments: Pointer(Unsize), Borrow(Ref(Not))
+} //^ adjustments: Borrow(Ref(Not)), Pointer(Unsize)
"#,
);
}
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/tests/simple.rs b/src/tools/rust-analyzer/crates/hir-ty/src/tests/simple.rs
index 146145523..2e5787b70 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/tests/simple.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/tests/simple.rs
@@ -3200,3 +3200,86 @@ fn func() {
"#,
);
}
+
+// FIXME
+#[test]
+fn castable_to() {
+ check_infer(
+ r#"
+//- minicore: sized
+#[lang = "owned_box"]
+pub struct Box<T: ?Sized> {
+ inner: *mut T,
+}
+impl<T> Box<T> {
+ fn new(t: T) -> Self { loop {} }
+}
+
+fn func() {
+ let x = Box::new([]) as Box<[i32; 0]>;
+}
+"#,
+ expect![[r#"
+ 99..100 't': T
+ 113..124 '{ loop {} }': Box<T>
+ 115..122 'loop {}': !
+ 120..122 '{}': ()
+ 138..184 '{ ...0]>; }': ()
+ 148..149 'x': Box<[i32; 0]>
+ 152..160 'Box::new': fn new<[{unknown}; 0]>([{unknown}; 0]) -> Box<[{unknown}; 0]>
+ 152..164 'Box::new([])': Box<[{unknown}; 0]>
+ 152..181 'Box::n...2; 0]>': Box<[i32; 0]>
+ 161..163 '[]': [{unknown}; 0]
+ "#]],
+ );
+}
+
+#[test]
+fn castable_to1() {
+ check_infer(
+ r#"
+struct Ark<T>(T);
+impl<T> Ark<T> {
+ fn foo(&self) -> *const T {
+ &self.0
+ }
+}
+fn f<T>(t: Ark<T>) {
+ Ark::foo(&t) as *const ();
+}
+"#,
+ expect![[r#"
+ 47..51 'self': &Ark<T>
+ 65..88 '{ ... }': *const T
+ 75..82 '&self.0': &T
+ 76..80 'self': &Ark<T>
+ 76..82 'self.0': T
+ 99..100 't': Ark<T>
+ 110..144 '{ ... (); }': ()
+ 116..124 'Ark::foo': fn foo<T>(&Ark<T>) -> *const T
+ 116..128 'Ark::foo(&t)': *const T
+ 116..141 'Ark::f...nst ()': *const ()
+ 125..127 '&t': &Ark<T>
+ 126..127 't': Ark<T>
+ "#]],
+ );
+}
+
+// FIXME
+#[test]
+fn castable_to2() {
+ check_infer(
+ r#"
+fn func() {
+ let x = &0u32 as *const _;
+}
+"#,
+ expect![[r#"
+ 10..44 '{ ...t _; }': ()
+ 20..21 'x': *const {unknown}
+ 24..29 '&0u32': &u32
+ 24..41 '&0u32 ...onst _': *const {unknown}
+ 25..29 '0u32': u32
+ "#]],
+ );
+}
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/tests/traits.rs b/src/tools/rust-analyzer/crates/hir-ty/src/tests/traits.rs
index d01fe0632..015085bde 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/tests/traits.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/tests/traits.rs
@@ -163,98 +163,22 @@ fn test() {
}
#[test]
-fn infer_try() {
+fn infer_try_trait() {
check_types(
r#"
-//- /main.rs crate:main deps:core
+//- minicore: try, result
fn test() {
let r: Result<i32, u64> = Result::Ok(1);
let v = r?;
v;
} //^ i32
-//- /core.rs crate:core
-pub mod ops {
- pub trait Try {
- type Ok;
- type Error;
- }
-}
-
-pub mod result {
- pub enum Result<O, E> {
- Ok(O),
- Err(E)
- }
-
- impl<O, E> crate::ops::Try for Result<O, E> {
- type Ok = O;
- type Error = E;
- }
-}
-
-pub mod prelude {
- pub mod rust_2018 {
- pub use crate::{result::*, ops::*};
- }
-}
-"#,
- );
-}
-
-#[test]
-fn infer_try_trait_v2() {
- check_types(
- r#"
-//- /main.rs crate:main deps:core
-fn test() {
- let r: Result<i32, u64> = Result::Ok(1);
- let v = r?;
- v;
-} //^ i32
-
-//- /core.rs crate:core
-mod ops {
- mod try_trait {
- pub trait Try: FromResidual {
- type Output;
- type Residual;
- }
- pub trait FromResidual<R = <Self as Try>::Residual> {}
- }
-
- pub use self::try_trait::FromResidual;
- pub use self::try_trait::Try;
+impl<O, E> core::ops::Try for Result<O, E> {
+ type Output = O;
+ type Error = Result<core::convert::Infallible, E>;
}
-mod convert {
- pub trait From<T> {}
- impl<T> From<T> for T {}
-}
-
-pub mod result {
- use crate::convert::From;
- use crate::ops::{Try, FromResidual};
-
- pub enum Infallible {}
- pub enum Result<O, E> {
- Ok(O),
- Err(E)
- }
-
- impl<O, E> Try for Result<O, E> {
- type Output = O;
- type Error = Result<Infallible, E>;
- }
-
- impl<T, E, F: From<E>> FromResidual<Result<Infallible, E>> for Result<T, F> {}
-}
-
-pub mod prelude {
- pub mod rust_2018 {
- pub use crate::result::*;
- }
-}
+impl<T, E, F: From<E>> core::ops::FromResidual<Result<core::convert::Infallible, E>> for Result<T, F> {}
"#,
);
}
@@ -263,7 +187,8 @@ pub mod prelude {
fn infer_for_loop() {
check_types(
r#"
-//- /main.rs crate:main deps:core,alloc
+//- minicore: iterator
+//- /main.rs crate:main deps:alloc
#![no_std]
use alloc::collections::Vec;
@@ -275,23 +200,7 @@ fn test() {
} //^ &str
}
-//- /core.rs crate:core
-pub mod iter {
- pub trait IntoIterator {
- type Item;
- type IntoIter: Iterator<Item = Self::Item>;
- }
- pub trait Iterator {
- type Item;
- }
-}
-pub mod prelude {
- pub mod rust_2018 {
- pub use crate::iter::*;
- }
-}
-
-//- /alloc.rs crate:alloc deps:core
+//- /alloc.rs crate:alloc
#![no_std]
pub mod collections {
pub struct Vec<T> {}
@@ -1848,25 +1757,19 @@ fn test() {
fn fn_trait() {
check_infer_with_mismatches(
r#"
-trait FnOnce<Args> {
- type Output;
-
- fn call_once(self, args: Args) -> <Self as FnOnce<Args>>::Output;
-}
+//- minicore: fn
fn test<F: FnOnce(u32, u64) -> u128>(f: F) {
f.call_once((1, 2));
}"#,
expect![[r#"
- 56..60 'self': Self
- 62..66 'args': Args
- 149..150 'f': F
- 155..183 '{ ...2)); }': ()
- 161..162 'f': F
- 161..180 'f.call...1, 2))': u128
- 173..179 '(1, 2)': (u32, u64)
- 174..175 '1': u32
- 177..178 '2': u64
+ 38..39 'f': F
+ 44..72 '{ ...2)); }': ()
+ 50..51 'f': F
+ 50..69 'f.call...1, 2))': u128
+ 62..68 '(1, 2)': (u32, u64)
+ 63..64 '1': u32
+ 66..67 '2': u64
"#]],
);
}
@@ -1875,12 +1778,7 @@ fn test<F: FnOnce(u32, u64) -> u128>(f: F) {
fn fn_ptr_and_item() {
check_infer_with_mismatches(
r#"
-#[lang="fn_once"]
-trait FnOnce<Args> {
- type Output;
-
- fn call_once(self, args: Args) -> Self::Output;
-}
+//- minicore: fn
trait Foo<T> {
fn foo(&self) -> T;
@@ -1906,27 +1804,25 @@ fn test() {
opt.map(f);
}"#,
expect![[r#"
- 74..78 'self': Self
- 80..84 'args': Args
- 139..143 'self': &Self
- 243..247 'self': &Bar<F>
- 260..271 '{ loop {} }': (A1, R)
- 262..269 'loop {}': !
- 267..269 '{}': ()
- 355..359 'self': Opt<T>
- 361..362 'f': F
- 377..388 '{ loop {} }': Opt<U>
- 379..386 'loop {}': !
- 384..386 '{}': ()
- 402..518 '{ ...(f); }': ()
- 412..415 'bar': Bar<fn(u8) -> u32>
- 441..444 'bar': Bar<fn(u8) -> u32>
- 441..450 'bar.foo()': (u8, u32)
- 461..464 'opt': Opt<u8>
- 483..484 'f': fn(u8) -> u32
- 505..508 'opt': Opt<u8>
- 505..515 'opt.map(f)': Opt<u32>
- 513..514 'f': fn(u8) -> u32
+ 28..32 'self': &Self
+ 132..136 'self': &Bar<F>
+ 149..160 '{ loop {} }': (A1, R)
+ 151..158 'loop {}': !
+ 156..158 '{}': ()
+ 244..248 'self': Opt<T>
+ 250..251 'f': F
+ 266..277 '{ loop {} }': Opt<U>
+ 268..275 'loop {}': !
+ 273..275 '{}': ()
+ 291..407 '{ ...(f); }': ()
+ 301..304 'bar': Bar<fn(u8) -> u32>
+ 330..333 'bar': Bar<fn(u8) -> u32>
+ 330..339 'bar.foo()': (u8, u32)
+ 350..353 'opt': Opt<u8>
+ 372..373 'f': fn(u8) -> u32
+ 394..397 'opt': Opt<u8>
+ 394..404 'opt.map(f)': Opt<u32>
+ 402..403 'f': fn(u8) -> u32
"#]],
);
}
@@ -2399,10 +2295,8 @@ fn unselected_projection_in_trait_env_no_cycle() {
// this is not a cycle
check_types(
r#"
-//- /main.rs
-trait Index {
- type Output;
-}
+//- minicore: index
+use core::ops::Index;
type Key<S: UnificationStoreBase> = <S as UnificationStoreBase>::Key;
@@ -2999,40 +2893,17 @@ fn test() {
fn integer_range_iterate() {
check_types(
r#"
-//- /main.rs crate:main deps:core
+//- minicore: range, iterator
+//- /main.rs crate:main
fn test() {
for x in 0..100 { x; }
} //^ i32
-//- /core.rs crate:core
-pub mod ops {
- pub struct Range<Idx> {
- pub start: Idx,
- pub end: Idx,
- }
-}
-
-pub mod iter {
- pub trait Iterator {
- type Item;
- }
-
- pub trait IntoIterator {
- type Item;
- type IntoIter: Iterator<Item = Self::Item>;
- }
-
- impl<T> IntoIterator for T where T: Iterator {
- type Item = <T as Iterator>::Item;
- type IntoIter = Self;
- }
-}
-
trait Step {}
impl Step for i32 {}
impl Step for i64 {}
-impl<A: Step> iter::Iterator for ops::Range<A> {
+impl<A: Step> core::iter::Iterator for core::ops::Range<A> {
type Item = A;
}
"#,
@@ -3507,14 +3378,9 @@ trait Request {
fn bin_op_adt_with_rhs_primitive() {
check_infer_with_mismatches(
r#"
-#[lang = "add"]
-pub trait Add<Rhs = Self> {
- type Output;
- fn add(self, rhs: Rhs) -> Self::Output;
-}
-
+//- minicore: add
struct Wrapper(u32);
-impl Add<u32> for Wrapper {
+impl core::ops::Add<u32> for Wrapper {
type Output = Self;
fn add(self, rhs: u32) -> Wrapper {
Wrapper(rhs)
@@ -3527,30 +3393,107 @@ fn main(){
}"#,
expect![[r#"
- 72..76 'self': Self
- 78..81 'rhs': Rhs
- 192..196 'self': Wrapper
- 198..201 'rhs': u32
- 219..247 '{ ... }': Wrapper
- 229..236 'Wrapper': Wrapper(u32) -> Wrapper
- 229..241 'Wrapper(rhs)': Wrapper
- 237..240 'rhs': u32
- 259..345 '{ ...um; }': ()
- 269..276 'wrapped': Wrapper
- 279..286 'Wrapper': Wrapper(u32) -> Wrapper
- 279..290 'Wrapper(10)': Wrapper
- 287..289 '10': u32
- 300..303 'num': u32
- 311..312 '2': u32
- 322..325 'res': Wrapper
- 328..335 'wrapped': Wrapper
- 328..341 'wrapped + num': Wrapper
- 338..341 'num': u32
+ 95..99 'self': Wrapper
+ 101..104 'rhs': u32
+ 122..150 '{ ... }': Wrapper
+ 132..139 'Wrapper': Wrapper(u32) -> Wrapper
+ 132..144 'Wrapper(rhs)': Wrapper
+ 140..143 'rhs': u32
+ 162..248 '{ ...um; }': ()
+ 172..179 'wrapped': Wrapper
+ 182..189 'Wrapper': Wrapper(u32) -> Wrapper
+ 182..193 'Wrapper(10)': Wrapper
+ 190..192 '10': u32
+ 203..206 'num': u32
+ 214..215 '2': u32
+ 225..228 'res': Wrapper
+ 231..238 'wrapped': Wrapper
+ 231..244 'wrapped + num': Wrapper
+ 241..244 'num': u32
"#]],
)
}
#[test]
+fn builtin_binop_expectation_works_on_single_reference() {
+ check_types(
+ r#"
+//- minicore: add
+use core::ops::Add;
+impl Add<i32> for i32 { type Output = i32 }
+impl Add<&i32> for i32 { type Output = i32 }
+impl Add<u32> for u32 { type Output = u32 }
+impl Add<&u32> for u32 { type Output = u32 }
+
+struct V<T>;
+impl<T> V<T> {
+ fn default() -> Self { loop {} }
+ fn get(&self, _: &T) -> &T { loop {} }
+}
+
+fn take_u32(_: u32) {}
+fn minimized() {
+ let v = V::default();
+ let p = v.get(&0);
+ //^ &u32
+ take_u32(42 + p);
+}
+"#,
+ );
+}
+
+#[test]
+fn no_builtin_binop_expectation_for_general_ty_var() {
+ // FIXME: Ideally type mismatch should be reported on `take_u32(42 - p)`.
+ check_types(
+ r#"
+//- minicore: add
+use core::ops::Add;
+impl Add<i32> for i32 { type Output = i32; }
+impl Add<&i32> for i32 { type Output = i32; }
+// This is needed to prevent chalk from giving unique solution to `i32: Add<&?0>` after applying
+// fallback to integer type variable for `42`.
+impl Add<&()> for i32 { type Output = (); }
+
+struct V<T>;
+impl<T> V<T> {
+ fn default() -> Self { loop {} }
+ fn get(&self) -> &T { loop {} }
+}
+
+fn take_u32(_: u32) {}
+fn minimized() {
+ let v = V::default();
+ let p = v.get();
+ //^ &{unknown}
+ take_u32(42 + p);
+}
+"#,
+ );
+}
+
+#[test]
+fn no_builtin_binop_expectation_for_non_builtin_types() {
+ check_no_mismatches(
+ r#"
+//- minicore: default, eq
+struct S;
+impl Default for S { fn default() -> Self { S } }
+impl Default for i32 { fn default() -> Self { 0 } }
+impl PartialEq<S> for i32 { fn eq(&self, _: &S) -> bool { true } }
+impl PartialEq<i32> for i32 { fn eq(&self, _: &S) -> bool { true } }
+
+fn take_s(_: S) {}
+fn test() {
+ let s = Default::default();
+ let _eq = 0 == s;
+ take_s(s);
+}
+"#,
+ )
+}
+
+#[test]
fn array_length() {
check_infer(
r#"
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/traits.rs b/src/tools/rust-analyzer/crates/hir-ty/src/traits.rs
index 778a6b820..3ab85c68f 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/traits.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/traits.rs
@@ -7,9 +7,11 @@ use chalk_recursive::Cache;
use chalk_solve::{logging_db::LoggingRustIrDatabase, Solver};
use base_db::CrateId;
-use hir_def::{lang_item::LangItemTarget, TraitId};
+use hir_def::{
+ lang_item::{LangItem, LangItemTarget},
+ TraitId,
+};
use stdx::panic_context;
-use syntax::SmolStr;
use crate::{
db::HirDatabase, infer::unify::InferenceTable, AliasEq, AliasTy, Canonical, DomainGoal, Goal,
@@ -177,18 +179,18 @@ pub enum FnTrait {
}
impl FnTrait {
- const fn lang_item_name(self) -> &'static str {
+ const fn lang_item(self) -> LangItem {
match self {
- FnTrait::FnOnce => "fn_once",
- FnTrait::FnMut => "fn_mut",
- FnTrait::Fn => "fn",
+ FnTrait::FnOnce => LangItem::FnOnce,
+ FnTrait::FnMut => LangItem::FnMut,
+ FnTrait::Fn => LangItem::Fn,
}
}
pub fn get_id(&self, db: &dyn HirDatabase, krate: CrateId) -> Option<TraitId> {
- let target = db.lang_item(krate, SmolStr::new_inline(self.lang_item_name()))?;
+ let target = db.lang_item(krate, self.lang_item())?;
match target {
- LangItemTarget::TraitId(t) => Some(t),
+ LangItemTarget::Trait(t) => Some(t),
_ => None,
}
}
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/utils.rs b/src/tools/rust-analyzer/crates/hir-ty/src/utils.rs
index 9893566bd..70d2d5efa 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/utils.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/utils.rs
@@ -11,39 +11,100 @@ use hir_def::{
GenericParams, TypeOrConstParamData, TypeParamProvenance, WherePredicate,
WherePredicateTypeTarget,
},
- intern::Interned,
+ lang_item::LangItem,
resolver::{HasResolver, TypeNs},
type_ref::{TraitBoundModifier, TypeRef},
ConstParamId, FunctionId, GenericDefId, ItemContainerId, Lookup, TraitId, TypeAliasId,
TypeOrConstParamId, TypeParamId,
};
use hir_expand::name::Name;
+use intern::Interned;
use itertools::Either;
use rustc_hash::FxHashSet;
use smallvec::{smallvec, SmallVec};
-use syntax::SmolStr;
use crate::{
db::HirDatabase, ChalkTraitId, Interner, Substitution, TraitRef, TraitRefExt, WhereClause,
};
-pub(crate) fn fn_traits(db: &dyn DefDatabase, krate: CrateId) -> impl Iterator<Item = TraitId> {
- [
- db.lang_item(krate, SmolStr::new_inline("fn")),
- db.lang_item(krate, SmolStr::new_inline("fn_mut")),
- db.lang_item(krate, SmolStr::new_inline("fn_once")),
- ]
- .into_iter()
- .flatten()
- .flat_map(|it| it.as_trait())
+pub(crate) fn fn_traits(
+ db: &dyn DefDatabase,
+ krate: CrateId,
+) -> impl Iterator<Item = TraitId> + '_ {
+ [LangItem::Fn, LangItem::FnMut, LangItem::FnOnce]
+ .into_iter()
+ .filter_map(move |lang| db.lang_item(krate, lang))
+ .flat_map(|it| it.as_trait())
}
-fn direct_super_traits(db: &dyn DefDatabase, trait_: TraitId) -> SmallVec<[TraitId; 4]> {
+/// Returns an iterator over the whole super trait hierarchy (including the
+/// trait itself).
+pub fn all_super_traits(db: &dyn DefDatabase, trait_: TraitId) -> SmallVec<[TraitId; 4]> {
+ // we need to take care a bit here to avoid infinite loops in case of cycles
+ // (i.e. if we have `trait A: B; trait B: A;`)
+
+ let mut result = smallvec![trait_];
+ let mut i = 0;
+ while let Some(&t) = result.get(i) {
+ // yeah this is quadratic, but trait hierarchies should be flat
+ // enough that this doesn't matter
+ direct_super_traits(db, t, |tt| {
+ if !result.contains(&tt) {
+ result.push(tt);
+ }
+ });
+ i += 1;
+ }
+ result
+}
+
+/// Given a trait ref (`Self: Trait`), builds all the implied trait refs for
+/// super traits. The original trait ref will be included. So the difference to
+/// `all_super_traits` is that we keep track of type parameters; for example if
+/// we have `Self: Trait<u32, i32>` and `Trait<T, U>: OtherTrait<U>` we'll get
+/// `Self: OtherTrait<i32>`.
+pub(super) fn all_super_trait_refs<T>(
+ db: &dyn HirDatabase,
+ trait_ref: TraitRef,
+ cb: impl FnMut(TraitRef) -> Option<T>,
+) -> Option<T> {
+ let seen = iter::once(trait_ref.trait_id).collect();
+ let mut stack = Vec::new();
+ stack.push(trait_ref);
+ SuperTraits { db, seen, stack }.find_map(cb)
+}
+
+struct SuperTraits<'a> {
+ db: &'a dyn HirDatabase,
+ stack: Vec<TraitRef>,
+ seen: FxHashSet<ChalkTraitId>,
+}
+
+impl<'a> SuperTraits<'a> {
+ fn elaborate(&mut self, trait_ref: &TraitRef) {
+ direct_super_trait_refs(self.db, trait_ref, |trait_ref| {
+ if !self.seen.contains(&trait_ref.trait_id) {
+ self.stack.push(trait_ref);
+ }
+ });
+ }
+}
+
+impl<'a> Iterator for SuperTraits<'a> {
+ type Item = TraitRef;
+
+ fn next(&mut self) -> Option<Self::Item> {
+ if let Some(next) = self.stack.pop() {
+ self.elaborate(&next);
+ Some(next)
+ } else {
+ None
+ }
+ }
+}
+
+fn direct_super_traits(db: &dyn DefDatabase, trait_: TraitId, cb: impl FnMut(TraitId)) {
let resolver = trait_.resolver(db);
- // returning the iterator directly doesn't easily work because of
- // lifetime problems, but since there usually shouldn't be more than a
- // few direct traits this should be fine (we could even use some kind of
- // SmallVec if performance is a concern)
let generic_params = db.generic_params(trait_.into());
let trait_self = generic_params.find_trait_self_param();
generic_params
@@ -73,18 +134,14 @@ fn direct_super_traits(db: &dyn DefDatabase, trait_: TraitId) -> SmallVec<[Trait
Some(TypeNs::TraitId(t)) => Some(t),
_ => None,
})
- .collect()
+ .for_each(cb);
}
-fn direct_super_trait_refs(db: &dyn HirDatabase, trait_ref: &TraitRef) -> Vec<TraitRef> {
- // returning the iterator directly doesn't easily work because of
- // lifetime problems, but since there usually shouldn't be more than a
- // few direct traits this should be fine (we could even use some kind of
- // SmallVec if performance is a concern)
+fn direct_super_trait_refs(db: &dyn HirDatabase, trait_ref: &TraitRef, cb: impl FnMut(TraitRef)) {
let generic_params = db.generic_params(trait_ref.hir_trait_id().into());
let trait_self = match generic_params.find_trait_self_param() {
Some(p) => TypeOrConstParamId { parent: trait_ref.hir_trait_id().into(), local_id: p },
- None => return Vec::new(),
+ None => return,
};
db.generic_predicates_for_param(trait_self.parent, trait_self, None)
.iter()
@@ -100,64 +157,7 @@ fn direct_super_trait_refs(db: &dyn HirDatabase, trait_ref: &TraitRef) -> Vec<Tr
})
})
.map(|pred| pred.substitute(Interner, &trait_ref.substitution))
- .collect()
-}
-
-/// Returns an iterator over the whole super trait hierarchy (including the
-/// trait itself).
-pub fn all_super_traits(db: &dyn DefDatabase, trait_: TraitId) -> SmallVec<[TraitId; 4]> {
- // we need to take care a bit here to avoid infinite loops in case of cycles
- // (i.e. if we have `trait A: B; trait B: A;`)
-
- let mut result = smallvec![trait_];
- let mut i = 0;
- while let Some(&t) = result.get(i) {
- // yeah this is quadratic, but trait hierarchies should be flat
- // enough that this doesn't matter
- for tt in direct_super_traits(db, t) {
- if !result.contains(&tt) {
- result.push(tt);
- }
- }
- i += 1;
- }
- result
-}
-
-/// Given a trait ref (`Self: Trait`), builds all the implied trait refs for
-/// super traits. The original trait ref will be included. So the difference to
-/// `all_super_traits` is that we keep track of type parameters; for example if
-/// we have `Self: Trait<u32, i32>` and `Trait<T, U>: OtherTrait<U>` we'll get
-/// `Self: OtherTrait<i32>`.
-pub(super) fn all_super_trait_refs(db: &dyn HirDatabase, trait_ref: TraitRef) -> SuperTraits<'_> {
- SuperTraits { db, seen: iter::once(trait_ref.trait_id).collect(), stack: vec![trait_ref] }
-}
-
-pub(super) struct SuperTraits<'a> {
- db: &'a dyn HirDatabase,
- stack: Vec<TraitRef>,
- seen: FxHashSet<ChalkTraitId>,
-}
-
-impl<'a> SuperTraits<'a> {
- fn elaborate(&mut self, trait_ref: &TraitRef) {
- let mut trait_refs = direct_super_trait_refs(self.db, trait_ref);
- trait_refs.retain(|tr| !self.seen.contains(&tr.trait_id));
- self.stack.extend(trait_refs);
- }
-}
-
-impl<'a> Iterator for SuperTraits<'a> {
- type Item = TraitRef;
-
- fn next(&mut self) -> Option<Self::Item> {
- if let Some(next) = self.stack.pop() {
- self.elaborate(&next);
- Some(next)
- } else {
- None
- }
- }
+ .for_each(cb);
}
pub(super) fn associated_type_by_name_including_super_traits(
@@ -165,7 +165,7 @@ pub(super) fn associated_type_by_name_including_super_traits(
trait_ref: TraitRef,
name: &Name,
) -> Option<(TraitRef, TypeAliasId)> {
- all_super_trait_refs(db, trait_ref).find_map(|t| {
+ all_super_trait_refs(db, trait_ref, |t| {
let assoc_type = db.trait_data(t.hir_trait_id()).associated_type_by_name(name)?;
Some((t, assoc_type))
})
@@ -238,15 +238,18 @@ impl Generics {
/// (parent total, self param, type param list, const param list, impl trait)
pub(crate) fn provenance_split(&self) -> (usize, usize, usize, usize, usize) {
- let ty_iter = || self.params.iter().filter_map(|x| x.1.type_param());
-
- let self_params =
- ty_iter().filter(|p| p.provenance == TypeParamProvenance::TraitSelf).count();
- let type_params =
- ty_iter().filter(|p| p.provenance == TypeParamProvenance::TypeParamList).count();
- let impl_trait_params =
- ty_iter().filter(|p| p.provenance == TypeParamProvenance::ArgumentImplTrait).count();
- let const_params = self.params.iter().filter_map(|x| x.1.const_param()).count();
+ let mut self_params = 0;
+ let mut type_params = 0;
+ let mut impl_trait_params = 0;
+ let mut const_params = 0;
+ self.params.iter().for_each(|(_, data)| match data {
+ TypeOrConstParamData::TypeParamData(p) => match p.provenance {
+ TypeParamProvenance::TypeParamList => type_params += 1,
+ TypeParamProvenance::TraitSelf => self_params += 1,
+ TypeParamProvenance::ArgumentImplTrait => impl_trait_params += 1,
+ },
+ TypeOrConstParamData::ConstParamData(_) => const_params += 1,
+ });
let parent_len = self.parent_generics().map_or(0, Generics::len);
(parent_len, self_params, type_params, const_params, impl_trait_params)
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/walk.rs b/src/tools/rust-analyzer/crates/hir-ty/src/walk.rs
deleted file mode 100644
index c47689455..000000000
--- a/src/tools/rust-analyzer/crates/hir-ty/src/walk.rs
+++ /dev/null
@@ -1,147 +0,0 @@
-//! The `TypeWalk` trait (probably to be replaced by Chalk's `Fold` and
-//! `Visit`).
-
-use chalk_ir::interner::HasInterner;
-
-use crate::{
- AliasEq, AliasTy, Binders, CallableSig, FnSubst, GenericArg, GenericArgData, Interner,
- OpaqueTy, ProjectionTy, Substitution, TraitRef, Ty, TyKind, WhereClause,
-};
-
-/// This allows walking structures that contain types to do something with those
-/// types, similar to Chalk's `Fold` trait.
-pub trait TypeWalk {
- fn walk(&self, f: &mut impl FnMut(&Ty));
-}
-
-impl TypeWalk for Ty {
- fn walk(&self, f: &mut impl FnMut(&Ty)) {
- match self.kind(Interner) {
- TyKind::Alias(AliasTy::Projection(p_ty)) => {
- for t in p_ty.substitution.iter(Interner) {
- t.walk(f);
- }
- }
- TyKind::Alias(AliasTy::Opaque(o_ty)) => {
- for t in o_ty.substitution.iter(Interner) {
- t.walk(f);
- }
- }
- TyKind::Dyn(dyn_ty) => {
- for p in dyn_ty.bounds.skip_binders().interned().iter() {
- p.walk(f);
- }
- }
- TyKind::Slice(ty)
- | TyKind::Array(ty, _)
- | TyKind::Ref(_, _, ty)
- | TyKind::Raw(_, ty) => {
- ty.walk(f);
- }
- TyKind::Function(fn_pointer) => {
- fn_pointer.substitution.0.walk(f);
- }
- TyKind::Adt(_, substs)
- | TyKind::FnDef(_, substs)
- | TyKind::Tuple(_, substs)
- | TyKind::OpaqueType(_, substs)
- | TyKind::AssociatedType(_, substs)
- | TyKind::Closure(.., substs) => {
- substs.walk(f);
- }
- _ => {}
- }
- f(self);
- }
-}
-
-impl<T: TypeWalk> TypeWalk for Vec<T> {
- fn walk(&self, f: &mut impl FnMut(&Ty)) {
- for t in self {
- t.walk(f);
- }
- }
-}
-
-impl TypeWalk for OpaqueTy {
- fn walk(&self, f: &mut impl FnMut(&Ty)) {
- self.substitution.walk(f);
- }
-}
-
-impl TypeWalk for ProjectionTy {
- fn walk(&self, f: &mut impl FnMut(&Ty)) {
- self.substitution.walk(f);
- }
-}
-
-impl TypeWalk for AliasTy {
- fn walk(&self, f: &mut impl FnMut(&Ty)) {
- match self {
- AliasTy::Projection(it) => it.walk(f),
- AliasTy::Opaque(it) => it.walk(f),
- }
- }
-}
-
-impl TypeWalk for GenericArg {
- fn walk(&self, f: &mut impl FnMut(&Ty)) {
- if let GenericArgData::Ty(ty) = &self.interned() {
- ty.walk(f);
- }
- }
-}
-
-impl TypeWalk for Substitution {
- fn walk(&self, f: &mut impl FnMut(&Ty)) {
- for t in self.iter(Interner) {
- t.walk(f);
- }
- }
-}
-
-impl<T: TypeWalk + HasInterner<Interner = Interner>> TypeWalk for Binders<T> {
- fn walk(&self, f: &mut impl FnMut(&Ty)) {
- self.skip_binders().walk(f);
- }
-}
-
-impl TypeWalk for TraitRef {
- fn walk(&self, f: &mut impl FnMut(&Ty)) {
- self.substitution.walk(f);
- }
-}
-
-impl TypeWalk for WhereClause {
- fn walk(&self, f: &mut impl FnMut(&Ty)) {
- match self {
- WhereClause::Implemented(trait_ref) => trait_ref.walk(f),
- WhereClause::AliasEq(alias_eq) => alias_eq.walk(f),
- _ => {}
- }
- }
-}
-
-impl TypeWalk for CallableSig {
- fn walk(&self, f: &mut impl FnMut(&Ty)) {
- for t in self.params_and_return.iter() {
- t.walk(f);
- }
- }
-}
-
-impl TypeWalk for AliasEq {
- fn walk(&self, f: &mut impl FnMut(&Ty)) {
- self.ty.walk(f);
- match &self.alias {
- AliasTy::Projection(projection_ty) => projection_ty.walk(f),
- AliasTy::Opaque(opaque) => opaque.walk(f),
- }
- }
-}
-
-impl TypeWalk for FnSubst<Interner> {
- fn walk(&self, f: &mut impl FnMut(&Ty)) {
- self.0.walk(f)
- }
-}
diff --git a/src/tools/rust-analyzer/crates/hir/Cargo.toml b/src/tools/rust-analyzer/crates/hir/Cargo.toml
index f780e3f53..ef40a8902 100644
--- a/src/tools/rust-analyzer/crates/hir/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/hir/Cargo.toml
@@ -2,9 +2,11 @@
name = "hir"
version = "0.0.0"
description = "TBD"
-license = "MIT OR Apache-2.0"
-edition = "2021"
-rust-version = "1.65"
+
+authors.workspace = true
+edition.workspace = true
+license.workspace = true
+rust-version.workspace = true
[lib]
doctest = false
@@ -14,15 +16,16 @@ rustc-hash = "1.1.0"
either = "1.7.0"
arrayvec = "0.7.2"
itertools = "0.10.5"
-smallvec = "1.10.0"
-once_cell = "1.15.0"
+smallvec.workspace = true
+once_cell = "1.17.0"
-stdx = { path = "../stdx", version = "0.0.0" }
-syntax = { path = "../syntax", version = "0.0.0" }
-base-db = { path = "../base-db", version = "0.0.0" }
-profile = { path = "../profile", version = "0.0.0" }
-hir-expand = { path = "../hir-expand", version = "0.0.0" }
-hir-def = { path = "../hir-def", version = "0.0.0" }
-hir-ty = { path = "../hir-ty", version = "0.0.0" }
-tt = { path = "../tt", version = "0.0.0" }
-cfg = { path = "../cfg", version = "0.0.0" }
+# local deps
+base-db.workspace = true
+cfg.workspace = true
+hir-def.workspace = true
+hir-expand.workspace = true
+hir-ty.workspace = true
+profile.workspace = true
+stdx.workspace = true
+syntax.workspace = true
+tt.workspace = true
diff --git a/src/tools/rust-analyzer/crates/hir/src/display.rs b/src/tools/rust-analyzer/crates/hir/src/display.rs
index 5a4b2f334..0d1942012 100644
--- a/src/tools/rust-analyzer/crates/hir/src/display.rs
+++ b/src/tools/rust-analyzer/crates/hir/src/display.rs
@@ -4,6 +4,7 @@ use hir_def::{
generics::{
TypeOrConstParamData, TypeParamProvenance, WherePredicate, WherePredicateTypeTarget,
},
+ lang_item::LangItem,
type_ref::{TypeBound, TypeRef},
AdtId, GenericDefId,
};
@@ -14,7 +15,6 @@ use hir_ty::{
},
Interner, TraitRefExt, WhereClause,
};
-use syntax::SmolStr;
use crate::{
Adt, Const, ConstParam, Enum, Field, Function, GenericParam, HasCrate, HasVisibility,
@@ -261,8 +261,7 @@ impl HirDisplay for TypeParam {
bounds.iter().cloned().map(|b| b.substitute(Interner, &substs)).collect();
let krate = self.id.parent().krate(f.db).id;
let sized_trait =
- f.db.lang_item(krate, SmolStr::new_inline("sized"))
- .and_then(|lang_item| lang_item.as_trait());
+ f.db.lang_item(krate, LangItem::Sized).and_then(|lang_item| lang_item.as_trait());
let has_only_sized_bound = predicates.iter().all(move |pred| match pred.skip_binders() {
WhereClause::Implemented(it) => Some(it.hir_trait_id()) == sized_trait,
_ => false,
@@ -270,7 +269,7 @@ impl HirDisplay for TypeParam {
let has_only_not_sized_bound = predicates.is_empty();
if !has_only_sized_bound || has_only_not_sized_bound {
let default_sized = SizedByDefault::Sized { anchor: krate };
- write_bounds_like_dyn_trait_with_prefix(":", &predicates, default_sized, f)?;
+ write_bounds_like_dyn_trait_with_prefix(f, ":", &predicates, default_sized)?;
}
Ok(())
}
diff --git a/src/tools/rust-analyzer/crates/hir/src/lib.rs b/src/tools/rust-analyzer/crates/hir/src/lib.rs
index 08fd4453d..2cb4ed2c3 100644
--- a/src/tools/rust-analyzer/crates/hir/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/hir/src/lib.rs
@@ -44,12 +44,13 @@ use hir_def::{
expr::{BindingAnnotation, ExprOrPatId, LabelId, Pat, PatId},
generics::{TypeOrConstParamData, TypeParamProvenance},
item_tree::ItemTreeNode,
- lang_item::LangItemTarget,
+ lang_item::{LangItem, LangItemTarget},
layout::{Layout, LayoutError, ReprOptions},
nameres::{self, diagnostics::DefDiagnostic},
per_ns::PerNs,
resolver::{HasResolver, Resolver},
src::HasSource as _,
+ type_ref::ConstScalar,
AdtId, AssocItemId, AssocItemLoc, AttrDefId, ConstId, ConstParamId, DefWithBodyId, EnumId,
EnumVariantId, FunctionId, GenericDefId, HasModule, ImplId, ItemContainerId, LifetimeParamId,
LocalEnumVariantId, LocalFieldId, Lookup, MacroExpander, MacroId, ModuleId, StaticId, StructId,
@@ -65,8 +66,9 @@ use hir_ty::{
primitive::UintTy,
traits::FnTrait,
AliasTy, CallableDefId, CallableSig, Canonical, CanonicalVarKinds, Cast, ClosureId,
- GenericArgData, Interner, ParamKind, QuantifiedWhereClause, Scalar, Substitution,
- TraitEnvironment, TraitRefExt, Ty, TyBuilder, TyDefId, TyExt, TyKind, WhereClause,
+ ConcreteConst, ConstValue, GenericArgData, Interner, ParamKind, QuantifiedWhereClause, Scalar,
+ Substitution, TraitEnvironment, TraitRefExt, Ty, TyBuilder, TyDefId, TyExt, TyKind,
+ WhereClause,
};
use itertools::Itertools;
use nameres::diagnostics::DefDiagnosticKind;
@@ -107,7 +109,7 @@ pub use {
cfg::{CfgAtom, CfgExpr, CfgOptions},
hir_def::{
adt::StructKind,
- attr::{Attr, Attrs, AttrsWithOwner, Documentation},
+ attr::{Attrs, AttrsWithOwner, Documentation},
builtin_attr::AttributeTemplate,
find_path::PrefixKind,
import_map,
@@ -122,11 +124,12 @@ pub use {
ModuleDefId,
},
hir_expand::{
+ attrs::Attr,
name::{known, Name},
ExpandResult, HirFileId, InFile, MacroFile, Origin,
},
hir_ty::{
- display::{HirDisplay, HirWrite},
+ display::{HirDisplay, HirDisplayError, HirWrite},
PointerCast, Safety,
},
};
@@ -471,8 +474,8 @@ impl Module {
let def_map = self.id.def_map(db.upcast());
let children = def_map[self.id.local_id]
.children
- .iter()
- .map(|(_, module_id)| Module { id: def_map.module_id(*module_id) })
+ .values()
+ .map(|module_id| Module { id: def_map.module_id(*module_id) })
.collect::<Vec<_>>();
children.into_iter()
}
@@ -784,7 +787,7 @@ fn precise_macro_call_location(
let token = (|| {
let derive_attr = node
.doc_comments_and_attrs()
- .nth(*derive_attr_index as usize)
+ .nth(derive_attr_index.ast_index())
.and_then(Either::left)?;
let token_tree = derive_attr.meta()?.token_tree()?;
let group_by = token_tree
@@ -812,9 +815,11 @@ fn precise_macro_call_location(
let node = ast_id.to_node(db.upcast());
let attr = node
.doc_comments_and_attrs()
- .nth((*invoc_attr_index) as usize)
+ .nth(invoc_attr_index.ast_index())
.and_then(Either::left)
- .unwrap_or_else(|| panic!("cannot find attribute #{invoc_attr_index}"));
+ .unwrap_or_else(|| {
+ panic!("cannot find attribute #{}", invoc_attr_index.ast_index())
+ });
(
ast_id.with_value(SyntaxNodePtr::from(AstPtr::new(&attr))),
@@ -920,7 +925,7 @@ impl Struct {
}
pub fn repr(self, db: &dyn HirDatabase) -> Option<ReprOptions> {
- db.struct_data(self.id).repr.clone()
+ db.struct_data(self.id).repr
}
pub fn kind(self, db: &dyn HirDatabase) -> StructKind {
@@ -1831,7 +1836,7 @@ pub struct Trait {
impl Trait {
pub fn lang(db: &dyn HirDatabase, krate: Crate, name: &Name) -> Option<Trait> {
- db.lang_item(krate.into(), name.to_smol_str())
+ db.lang_item(krate.into(), LangItem::from_name(name)?)
.and_then(LangItemTarget::as_trait)
.map(Into::into)
}
@@ -2126,7 +2131,7 @@ pub enum AssocItem {
Const(Const),
TypeAlias(TypeAlias),
}
-#[derive(Debug)]
+#[derive(Debug, Clone)]
pub enum AssocItemContainer {
Trait(Trait),
Impl(Impl),
@@ -2160,6 +2165,16 @@ impl AsAssocItem for ModuleDef {
}
}
}
+impl AsAssocItem for DefWithBody {
+ fn as_assoc_item(self, db: &dyn HirDatabase) -> Option<AssocItem> {
+ match self {
+ DefWithBody::Function(it) => it.as_assoc_item(db),
+ DefWithBody::Const(it) => it.as_assoc_item(db),
+ DefWithBody::Static(_) | DefWithBody::Variant(_) => None,
+ }
+ }
+}
+
fn as_assoc_item<ID, DEF, CTOR, AST>(db: &dyn HirDatabase, ctor: CTOR, id: ID) -> Option<AssocItem>
where
ID: Lookup<Data = AssocItemLoc<AST>>,
@@ -2406,7 +2421,7 @@ impl Local {
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub struct DeriveHelper {
pub(crate) derive: MacroId,
- pub(crate) idx: usize,
+ pub(crate) idx: u32,
}
impl DeriveHelper {
@@ -2416,15 +2431,18 @@ impl DeriveHelper {
pub fn name(&self, db: &dyn HirDatabase) -> Name {
match self.derive {
- MacroId::Macro2Id(it) => {
- db.macro2_data(it).helpers.as_deref().and_then(|it| it.get(self.idx)).cloned()
- }
+ MacroId::Macro2Id(it) => db
+ .macro2_data(it)
+ .helpers
+ .as_deref()
+ .and_then(|it| it.get(self.idx as usize))
+ .cloned(),
MacroId::MacroRulesId(_) => None,
MacroId::ProcMacroId(proc_macro) => db
.proc_macro_data(proc_macro)
.helpers
.as_deref()
- .and_then(|it| it.get(self.idx))
+ .and_then(|it| it.get(self.idx as usize))
.cloned(),
}
.unwrap_or_else(|| Name::missing())
@@ -2435,7 +2453,7 @@ impl DeriveHelper {
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub struct BuiltinAttr {
krate: Option<CrateId>,
- idx: usize,
+ idx: u32,
}
impl BuiltinAttr {
@@ -2444,7 +2462,8 @@ impl BuiltinAttr {
if let builtin @ Some(_) = Self::builtin(name) {
return builtin;
}
- let idx = db.crate_def_map(krate.id).registered_attrs().iter().position(|it| it == name)?;
+ let idx =
+ db.crate_def_map(krate.id).registered_attrs().iter().position(|it| it == name)? as u32;
Some(BuiltinAttr { krate: Some(krate.id), idx })
}
@@ -2452,21 +2471,21 @@ impl BuiltinAttr {
hir_def::builtin_attr::INERT_ATTRIBUTES
.iter()
.position(|tool| tool.name == name)
- .map(|idx| BuiltinAttr { krate: None, idx })
+ .map(|idx| BuiltinAttr { krate: None, idx: idx as u32 })
}
pub fn name(&self, db: &dyn HirDatabase) -> SmolStr {
// FIXME: Return a `Name` here
match self.krate {
- Some(krate) => db.crate_def_map(krate).registered_attrs()[self.idx].clone(),
- None => SmolStr::new(hir_def::builtin_attr::INERT_ATTRIBUTES[self.idx].name),
+ Some(krate) => db.crate_def_map(krate).registered_attrs()[self.idx as usize].clone(),
+ None => SmolStr::new(hir_def::builtin_attr::INERT_ATTRIBUTES[self.idx as usize].name),
}
}
pub fn template(&self, _: &dyn HirDatabase) -> Option<AttributeTemplate> {
match self.krate {
Some(_) => None,
- None => Some(hir_def::builtin_attr::INERT_ATTRIBUTES[self.idx].template),
+ None => Some(hir_def::builtin_attr::INERT_ATTRIBUTES[self.idx as usize].template),
}
}
}
@@ -2474,7 +2493,7 @@ impl BuiltinAttr {
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub struct ToolModule {
krate: Option<CrateId>,
- idx: usize,
+ idx: u32,
}
impl ToolModule {
@@ -2483,7 +2502,8 @@ impl ToolModule {
if let builtin @ Some(_) = Self::builtin(name) {
return builtin;
}
- let idx = db.crate_def_map(krate.id).registered_tools().iter().position(|it| it == name)?;
+ let idx =
+ db.crate_def_map(krate.id).registered_tools().iter().position(|it| it == name)? as u32;
Some(ToolModule { krate: Some(krate.id), idx })
}
@@ -2491,14 +2511,14 @@ impl ToolModule {
hir_def::builtin_attr::TOOL_MODULES
.iter()
.position(|&tool| tool == name)
- .map(|idx| ToolModule { krate: None, idx })
+ .map(|idx| ToolModule { krate: None, idx: idx as u32 })
}
pub fn name(&self, db: &dyn HirDatabase) -> SmolStr {
// FIXME: Return a `Name` here
match self.krate {
- Some(krate) => db.crate_def_map(krate).registered_tools()[self.idx].clone(),
- None => SmolStr::new(hir_def::builtin_attr::TOOL_MODULES[self.idx]),
+ Some(krate) => db.crate_def_map(krate).registered_tools()[self.idx as usize].clone(),
+ None => SmolStr::new(hir_def::builtin_attr::TOOL_MODULES[self.idx as usize]),
}
}
}
@@ -2555,6 +2575,14 @@ impl GenericParam {
GenericParam::LifetimeParam(it) => it.name(db),
}
}
+
+ pub fn parent(self) -> GenericDef {
+ match self {
+ GenericParam::TypeParam(it) => it.id.parent().into(),
+ GenericParam::ConstParam(it) => it.id.parent().into(),
+ GenericParam::LifetimeParam(it) => it.id.parent.into(),
+ }
+ }
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
@@ -2788,14 +2816,19 @@ impl Impl {
all
}
- // FIXME: the return type is wrong. This should be a hir version of
- // `TraitRef` (to account for parameters and qualifiers)
pub fn trait_(self, db: &dyn HirDatabase) -> Option<Trait> {
- let trait_ref = db.impl_trait(self.id)?.skip_binders().clone();
- let id = hir_ty::from_chalk_trait_id(trait_ref.trait_id);
+ let trait_ref = db.impl_trait(self.id)?;
+ let id = trait_ref.skip_binders().hir_trait_id();
Some(Trait { id })
}
+ pub fn trait_ref(self, db: &dyn HirDatabase) -> Option<TraitRef> {
+ let substs = TyBuilder::placeholder_subst(db, self.id);
+ let trait_ref = db.impl_trait(self.id)?.substitute(Interner, &substs);
+ let resolver = self.id.resolver(db.upcast());
+ Some(TraitRef::new_with_resolver(db, &resolver, trait_ref))
+ }
+
pub fn self_ty(self, db: &dyn HirDatabase) -> Type {
let resolver = self.id.resolver(db.upcast());
let substs = TyBuilder::placeholder_subst(db, self.id);
@@ -2821,6 +2854,48 @@ impl Impl {
}
}
+#[derive(Clone, PartialEq, Eq, Debug, Hash)]
+pub struct TraitRef {
+ env: Arc<TraitEnvironment>,
+ trait_ref: hir_ty::TraitRef,
+}
+
+impl TraitRef {
+ pub(crate) fn new_with_resolver(
+ db: &dyn HirDatabase,
+ resolver: &Resolver,
+ trait_ref: hir_ty::TraitRef,
+ ) -> TraitRef {
+ let env = resolver.generic_def().map_or_else(
+ || Arc::new(TraitEnvironment::empty(resolver.krate())),
+ |d| db.trait_environment(d),
+ );
+ TraitRef { env, trait_ref }
+ }
+
+ pub fn trait_(&self) -> Trait {
+ let id = self.trait_ref.hir_trait_id();
+ Trait { id }
+ }
+
+ pub fn self_ty(&self) -> Type {
+ let ty = self.trait_ref.self_type_parameter(Interner);
+ Type { env: self.env.clone(), ty }
+ }
+
+ /// Returns `idx`-th argument of this trait reference if it is a type argument. Note that the
+ /// first argument is the `Self` type.
+ pub fn get_type_argument(&self, idx: usize) -> Option<Type> {
+ self.trait_ref
+ .substitution
+ .as_slice(Interner)
+ .get(idx)
+ .and_then(|arg| arg.ty(Interner))
+ .cloned()
+ .map(|ty| Type { env: self.env.clone(), ty })
+ }
+}
+
#[derive(Clone, PartialEq, Eq, Debug)]
pub struct Type {
env: Arc<TraitEnvironment>,
@@ -2957,7 +3032,7 @@ impl Type {
/// This function is used in `.await` syntax completion.
pub fn impls_into_future(&self, db: &dyn HirDatabase) -> bool {
let trait_ = db
- .lang_item(self.env.krate, SmolStr::new_inline("into_future"))
+ .lang_item(self.env.krate, LangItem::IntoFutureIntoFuture)
.and_then(|it| {
let into_future_fn = it.as_function()?;
let assoc_item = as_assoc_item(db, AssocItem::Function, into_future_fn)?;
@@ -2965,8 +3040,7 @@ impl Type {
Some(into_future_trait.id)
})
.or_else(|| {
- let future_trait =
- db.lang_item(self.env.krate, SmolStr::new_inline("future_trait"))?;
+ let future_trait = db.lang_item(self.env.krate, LangItem::Future)?;
future_trait.as_trait()
});
@@ -3059,9 +3133,9 @@ impl Type {
}
pub fn is_copy(&self, db: &dyn HirDatabase) -> bool {
- let lang_item = db.lang_item(self.env.krate, SmolStr::new_inline("copy"));
+ let lang_item = db.lang_item(self.env.krate, LangItem::Copy);
let copy_trait = match lang_item {
- Some(LangItemTarget::TraitId(it)) => it,
+ Some(LangItemTarget::Trait(it)) => it,
_ => return false,
};
self.impls_trait(db, copy_trait.into(), &[])
@@ -3088,15 +3162,15 @@ impl Type {
}
pub fn is_closure(&self) -> bool {
- matches!(&self.ty.kind(Interner), TyKind::Closure { .. })
+ matches!(self.ty.kind(Interner), TyKind::Closure { .. })
}
pub fn is_fn(&self) -> bool {
- matches!(&self.ty.kind(Interner), TyKind::FnDef(..) | TyKind::Function { .. })
+ matches!(self.ty.kind(Interner), TyKind::FnDef(..) | TyKind::Function { .. })
}
pub fn is_array(&self) -> bool {
- matches!(&self.ty.kind(Interner), TyKind::Array(..))
+ matches!(self.ty.kind(Interner), TyKind::Array(..))
}
pub fn is_packed(&self, db: &dyn HirDatabase) -> bool {
@@ -3113,10 +3187,12 @@ impl Type {
}
pub fn is_raw_ptr(&self) -> bool {
- matches!(&self.ty.kind(Interner), TyKind::Raw(..))
+ matches!(self.ty.kind(Interner), TyKind::Raw(..))
}
pub fn contains_unknown(&self) -> bool {
+ // FIXME: When we get rid of `ConstScalar::Unknown`, we can just look at precomputed
+ // `TypeFlags` in `TyData`.
return go(&self.ty);
fn go(ty: &Ty) -> bool {
@@ -3182,6 +3258,19 @@ impl Type {
}
}
+ pub fn as_array(&self, _db: &dyn HirDatabase) -> Option<(Type, usize)> {
+ if let TyKind::Array(ty, len) = &self.ty.kind(Interner) {
+ match len.data(Interner).value {
+ ConstValue::Concrete(ConcreteConst { interned: ConstScalar::UInt(len) }) => {
+ Some((self.derived(ty.clone()), len as usize))
+ }
+ _ => None,
+ }
+ } else {
+ None
+ }
+ }
+
pub fn autoderef<'a>(&'a self, db: &'a dyn HirDatabase) -> impl Iterator<Item = Type> + 'a {
self.autoderef_(db).map(move |ty| self.derived(ty))
}
@@ -3418,10 +3507,9 @@ impl Type {
Type { env: self.env.clone(), ty }
}
+ /// Visits every type, including generic arguments, in this type. `cb` is called with type
+ /// itself first, and then with its generic arguments.
pub fn walk(&self, db: &dyn HirDatabase, mut cb: impl FnMut(Type)) {
- // TypeWalk::walk for a Ty at first visits parameters and only after that the Ty itself.
- // We need a different order here.
-
fn walk_substs(
db: &dyn HirDatabase,
type_: &Type,
@@ -3534,6 +3622,14 @@ impl Type {
_ => None,
}
}
+
+ /// Returns unique `GenericParam`s contained in this type.
+ pub fn generic_params(&self, db: &dyn HirDatabase) -> FxHashSet<GenericParam> {
+ hir_ty::collect_placeholders(&self.ty, db)
+ .into_iter()
+ .map(|id| TypeOrConstParam { id }.split(db).either_into())
+ .collect()
+ }
}
#[derive(Debug)]
diff --git a/src/tools/rust-analyzer/crates/hir/src/semantics.rs b/src/tools/rust-analyzer/crates/hir/src/semantics.rs
index e0d261039..486b7ee62 100644
--- a/src/tools/rust-analyzer/crates/hir/src/semantics.rs
+++ b/src/tools/rust-analyzer/crates/hir/src/semantics.rs
@@ -1319,10 +1319,7 @@ impl<'db> SemanticsImpl<'db> {
let _p = profile::span("Semantics::analyze_impl");
let node = self.find_file(node);
- let container = match self.with_ctx(|ctx| ctx.find_container(node)) {
- Some(it) => it,
- None => return None,
- };
+ let container = self.with_ctx(|ctx| ctx.find_container(node))?;
let resolver = match container {
ChildContainer::DefWithBodyId(def) => {
@@ -1472,14 +1469,7 @@ impl<'db> SemanticsImpl<'db> {
}
fn is_inside_unsafe(&self, expr: &ast::Expr) -> bool {
- let item_or_variant = |ancestor: SyntaxNode| {
- if ast::Item::can_cast(ancestor.kind()) {
- ast::Item::cast(ancestor).map(Either::Left)
- } else {
- ast::Variant::cast(ancestor).map(Either::Right)
- }
- };
- let Some(enclosing_item) = expr.syntax().ancestors().find_map(item_or_variant) else { return false };
+ let Some(enclosing_item) = expr.syntax().ancestors().find_map(Either::<ast::Item, ast::Variant>::cast) else { return false };
let def = match &enclosing_item {
Either::Left(ast::Item::Fn(it)) if it.unsafe_token().is_some() => return true,
@@ -1589,7 +1579,7 @@ fn find_root(node: &SyntaxNode) -> SyntaxNode {
node.ancestors().last().unwrap()
}
-/// `SemanticScope` encapsulates the notion of a scope (the set of visible
+/// `SemanticsScope` encapsulates the notion of a scope (the set of visible
/// names) at a particular program point.
///
/// It is a bit tricky, as scopes do not really exist inside the compiler.
diff --git a/src/tools/rust-analyzer/crates/hir/src/semantics/source_to_def.rs b/src/tools/rust-analyzer/crates/hir/src/semantics/source_to_def.rs
index fa45e3c12..2b5bfda1d 100644
--- a/src/tools/rust-analyzer/crates/hir/src/semantics/source_to_def.rs
+++ b/src/tools/rust-analyzer/crates/hir/src/semantics/source_to_def.rs
@@ -87,7 +87,6 @@
use base_db::FileId;
use hir_def::{
- attr::AttrId,
child_by_source::ChildBySource,
dyn_map::DynMap,
expr::{LabelId, PatId},
@@ -96,7 +95,7 @@ use hir_def::{
GenericDefId, GenericParamId, ImplId, LifetimeParamId, MacroId, ModuleId, StaticId, StructId,
TraitId, TypeAliasId, TypeParamId, UnionId, VariantId,
};
-use hir_expand::{name::AsName, HirFileId, MacroCallId};
+use hir_expand::{attrs::AttrId, name::AsName, HirFileId, MacroCallId};
use rustc_hash::FxHashMap;
use smallvec::SmallVec;
use stdx::impl_from;
diff --git a/src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs b/src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs
index 059b80bcf..3b39e9fa9 100644
--- a/src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs
+++ b/src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs
@@ -17,6 +17,7 @@ use hir_def::{
Body, BodySourceMap,
},
expr::{ExprId, Pat, PatId},
+ lang_item::LangItem,
macro_id_to_def_id,
path::{ModPath, Path, PathKind},
resolver::{resolver_for_scope, Resolver, TypeNs, ValueNs},
@@ -37,7 +38,7 @@ use hir_ty::{
record_literal_missing_fields, record_pattern_missing_fields, unsafe_expressions,
UnsafeExpr,
},
- method_resolution::{self, lang_names_for_bin_op},
+ method_resolution::{self, lang_items_for_bin_op},
Adjustment, InferenceResult, Interner, Substitution, Ty, TyExt, TyKind, TyLoweringContext,
};
use itertools::Itertools;
@@ -294,12 +295,8 @@ impl SourceAnalyzer {
}
}
- let future_trait = db
- .lang_item(self.resolver.krate(), hir_expand::name![future_trait].to_smol_str())?
- .as_trait()?;
- let poll_fn = db
- .lang_item(self.resolver.krate(), hir_expand::name![poll].to_smol_str())?
- .as_function()?;
+ let future_trait = db.lang_item(self.resolver.krate(), LangItem::Future)?.as_trait()?;
+ let poll_fn = db.lang_item(self.resolver.krate(), LangItem::FuturePoll)?.as_function()?;
// HACK: subst for `poll()` coincides with that for `Future` because `poll()` itself
// doesn't have any generic parameters, so we skip building another subst for `poll()`.
let substs = hir_ty::TyBuilder::subst_for_def(db, future_trait, None).push(ty).build();
@@ -311,14 +308,14 @@ impl SourceAnalyzer {
db: &dyn HirDatabase,
prefix_expr: &ast::PrefixExpr,
) -> Option<FunctionId> {
- let lang_item_name = match prefix_expr.op_kind()? {
- ast::UnaryOp::Deref => name![deref],
- ast::UnaryOp::Not => name![not],
- ast::UnaryOp::Neg => name![neg],
+ let (lang_item, fn_name) = match prefix_expr.op_kind()? {
+ ast::UnaryOp::Deref => (LangItem::Deref, name![deref]),
+ ast::UnaryOp::Not => (LangItem::Not, name![not]),
+ ast::UnaryOp::Neg => (LangItem::Neg, name![neg]),
};
let ty = self.ty_of_expr(db, &prefix_expr.expr()?)?;
- let (op_trait, op_fn) = self.lang_trait_fn(db, &lang_item_name, &lang_item_name)?;
+ let (op_trait, op_fn) = self.lang_trait_fn(db, lang_item, &fn_name)?;
// HACK: subst for all methods coincides with that for their trait because the methods
// don't have any generic parameters, so we skip building another subst for the methods.
let substs = hir_ty::TyBuilder::subst_for_def(db, op_trait, None).push(ty.clone()).build();
@@ -334,9 +331,7 @@ impl SourceAnalyzer {
let base_ty = self.ty_of_expr(db, &index_expr.base()?)?;
let index_ty = self.ty_of_expr(db, &index_expr.index()?)?;
- let lang_item_name = name![index];
-
- let (op_trait, op_fn) = self.lang_trait_fn(db, &lang_item_name, &lang_item_name)?;
+ let (op_trait, op_fn) = self.lang_trait_fn(db, LangItem::Index, &name![index])?;
// HACK: subst for all methods coincides with that for their trait because the methods
// don't have any generic parameters, so we skip building another subst for the methods.
let substs = hir_ty::TyBuilder::subst_for_def(db, op_trait, None)
@@ -355,8 +350,8 @@ impl SourceAnalyzer {
let lhs = self.ty_of_expr(db, &binop_expr.lhs()?)?;
let rhs = self.ty_of_expr(db, &binop_expr.rhs()?)?;
- let (op_trait, op_fn) = lang_names_for_bin_op(op)
- .and_then(|(name, lang_item)| self.lang_trait_fn(db, &lang_item, &name))?;
+ let (op_trait, op_fn) = lang_items_for_bin_op(op)
+ .and_then(|(name, lang_item)| self.lang_trait_fn(db, lang_item, &name))?;
// HACK: subst for `index()` coincides with that for `Index` because `index()` itself
// doesn't have any generic parameters, so we skip building another subst for `index()`.
let substs = hir_ty::TyBuilder::subst_for_def(db, op_trait, None)
@@ -374,8 +369,7 @@ impl SourceAnalyzer {
) -> Option<FunctionId> {
let ty = self.ty_of_expr(db, &try_expr.expr()?)?;
- let op_fn =
- db.lang_item(self.resolver.krate(), name![branch].to_smol_str())?.as_function()?;
+ let op_fn = db.lang_item(self.resolver.krate(), LangItem::TryTraitBranch)?.as_function()?;
let op_trait = match op_fn.lookup(db.upcast()).container {
ItemContainerId::TraitId(id) => id,
_ => return None,
@@ -504,7 +498,7 @@ impl SourceAnalyzer {
AssocItemId::ConstId(const_id) => {
self.resolve_impl_const_or_trait_def(db, const_id, subs).into()
}
- _ => assoc,
+ assoc => assoc,
};
return Some(PathResolution::Def(AssocItem::from(assoc).into()));
@@ -517,7 +511,13 @@ impl SourceAnalyzer {
prefer_value_ns = true;
} else if let Some(path_pat) = parent().and_then(ast::PathPat::cast) {
let pat_id = self.pat_id(&path_pat.into())?;
- if let Some((assoc, _)) = infer.assoc_resolutions_for_pat(pat_id) {
+ if let Some((assoc, subs)) = infer.assoc_resolutions_for_pat(pat_id) {
+ let assoc = match assoc {
+ AssocItemId::ConstId(const_id) => {
+ self.resolve_impl_const_or_trait_def(db, const_id, subs).into()
+ }
+ assoc => assoc,
+ };
return Some(PathResolution::Def(AssocItem::from(assoc).into()));
}
if let Some(VariantId::EnumVariantId(variant)) =
@@ -628,7 +628,7 @@ impl SourceAnalyzer {
{
return Some(PathResolution::DeriveHelper(DeriveHelper {
derive: *macro_id,
- idx,
+ idx: idx as u32,
}));
}
}
@@ -815,10 +815,10 @@ impl SourceAnalyzer {
fn lang_trait_fn(
&self,
db: &dyn HirDatabase,
- lang_trait: &Name,
+ lang_trait: LangItem,
method_name: &Name,
) -> Option<(TraitId, FunctionId)> {
- let trait_id = db.lang_item(self.resolver.krate(), lang_trait.to_smol_str())?.as_trait()?;
+ let trait_id = db.lang_item(self.resolver.krate(), lang_trait)?.as_trait()?;
let fn_id = db.trait_data(trait_id).method_by_name(method_name)?;
Some((trait_id, fn_id))
}
diff --git a/src/tools/rust-analyzer/crates/ide-assists/Cargo.toml b/src/tools/rust-analyzer/crates/ide-assists/Cargo.toml
index b9260473b..447e38f91 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/ide-assists/Cargo.toml
@@ -2,9 +2,11 @@
name = "ide-assists"
version = "0.0.0"
description = "TBD"
-license = "MIT OR Apache-2.0"
-edition = "2021"
-rust-version = "1.65"
+
+authors.workspace = true
+edition.workspace = true
+license.workspace = true
+rust-version.workspace = true
[lib]
doctest = false
@@ -14,19 +16,22 @@ cov-mark = "2.0.0-pre.1"
itertools = "0.10.5"
either = "1.7.0"
-smallvec = "1.10.0"
+smallvec.workspace = true
-stdx = { path = "../stdx", version = "0.0.0" }
-syntax = { path = "../syntax", version = "0.0.0" }
-text-edit = { path = "../text-edit", version = "0.0.0" }
-profile = { path = "../profile", version = "0.0.0" }
-ide-db = { path = "../ide-db", version = "0.0.0" }
-hir = { path = "../hir", version = "0.0.0" }
+# local deps
+stdx.workspace = true
+syntax.workspace = true
+text-edit.workspace = true
+profile.workspace = true
+ide-db.workspace = true
+hir.workspace = true
[dev-dependencies]
-test-utils = { path = "../test-utils" }
-sourcegen = { path = "../sourcegen" }
expect-test = "1.4.0"
+# local deps
+test-utils.workspace = true
+sourcegen.workspace = true
+
[features]
in-rust-tree = []
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_braces.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_braces.rs
new file mode 100644
index 000000000..2f4a263ee
--- /dev/null
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_braces.rs
@@ -0,0 +1,155 @@
+use syntax::{
+ ast::{self, edit::AstNodeEdit, make},
+ AstNode,
+};
+
+use crate::{AssistContext, AssistId, AssistKind, Assists};
+
+// Assist: add_braces
+//
+// Adds braces to lambda and match arm expressions.
+//
+// ```
+// fn foo(n: i32) -> i32 {
+// match n {
+// 1 =>$0 n + 1,
+// _ => 0
+// }
+// }
+// ```
+// ->
+// ```
+// fn foo(n: i32) -> i32 {
+// match n {
+// 1 => {
+// n + 1
+// },
+// _ => 0
+// }
+// }
+// ```
+pub(crate) fn add_braces(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> {
+ let (expr_type, expr) = get_replacement_node(ctx)?;
+
+ acc.add(
+ AssistId("add_braces", AssistKind::RefactorRewrite),
+ match expr_type {
+ ParentType::ClosureExpr => "Add braces to closure body",
+ ParentType::MatchArmExpr => "Add braces to arm expression",
+ },
+ expr.syntax().text_range(),
+ |builder| {
+ let block_expr = AstNodeEdit::indent(
+ &make::block_expr(None, Some(expr.clone())),
+ AstNodeEdit::indent_level(&expr),
+ );
+
+ builder.replace(expr.syntax().text_range(), block_expr.syntax().text());
+ },
+ )
+}
+
+enum ParentType {
+ MatchArmExpr,
+ ClosureExpr,
+}
+
+fn get_replacement_node(ctx: &AssistContext<'_>) -> Option<(ParentType, ast::Expr)> {
+ if let Some(match_arm) = ctx.find_node_at_offset::<ast::MatchArm>() {
+ let match_arm_expr = match_arm.expr()?;
+
+ if matches!(match_arm_expr, ast::Expr::BlockExpr(_)) {
+ return None;
+ }
+
+ return Some((ParentType::MatchArmExpr, match_arm_expr));
+ } else if let Some(closure_expr) = ctx.find_node_at_offset::<ast::ClosureExpr>() {
+ let body = closure_expr.body()?;
+
+ if matches!(body, ast::Expr::BlockExpr(_)) {
+ return None;
+ }
+
+ return Some((ParentType::ClosureExpr, body));
+ }
+
+ None
+}
+
+#[cfg(test)]
+mod tests {
+ use crate::tests::{check_assist, check_assist_not_applicable};
+
+ use super::*;
+
+ #[test]
+ fn suggest_add_braces_for_closure() {
+ check_assist(
+ add_braces,
+ r#"
+fn foo() {
+ t(|n|$0 n + 100);
+}
+"#,
+ r#"
+fn foo() {
+ t(|n| {
+ n + 100
+ });
+}
+"#,
+ );
+ }
+
+ #[test]
+ fn no_assist_for_closures_with_braces() {
+ check_assist_not_applicable(
+ add_braces,
+ r#"
+fn foo() {
+ t(|n|$0 { n + 100 });
+}
+"#,
+ );
+ }
+
+ #[test]
+ fn suggest_add_braces_for_match() {
+ check_assist(
+ add_braces,
+ r#"
+fn foo() {
+ match n {
+ Some(n) $0=> 29,
+ _ => ()
+ };
+}
+"#,
+ r#"
+fn foo() {
+ match n {
+ Some(n) => {
+ 29
+ },
+ _ => ()
+ };
+}
+"#,
+ );
+ }
+
+ #[test]
+ fn no_assist_for_match_with_braces() {
+ check_assist_not_applicable(
+ add_braces,
+ r#"
+fn foo() {
+ match n {
+ Some(n) $0=> { return 29; },
+ _ => ()
+ };
+}
+"#,
+ );
+ }
+}
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_missing_impl_members.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_missing_impl_members.rs
index 161bcc5c8..4e11b31de 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_missing_impl_members.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_missing_impl_members.rs
@@ -1,7 +1,5 @@
use hir::HasSource;
-use ide_db::{
- syntax_helpers::insert_whitespace_into_node::insert_ws_into, traits::resolve_target_trait,
-};
+use ide_db::syntax_helpers::insert_whitespace_into_node::insert_ws_into;
use syntax::ast::{self, make, AstNode};
use crate::{
@@ -107,16 +105,19 @@ fn add_missing_impl_members_inner(
) -> Option<()> {
let _p = profile::span("add_missing_impl_members_inner");
let impl_def = ctx.find_node_at_offset::<ast::Impl>()?;
+ let impl_ = ctx.sema.to_def(&impl_def)?;
if ctx.token_at_offset().all(|t| {
t.parent_ancestors()
+ .take_while(|node| node != impl_def.syntax())
.any(|s| ast::BlockExpr::can_cast(s.kind()) || ast::ParamList::can_cast(s.kind()))
}) {
return None;
}
let target_scope = ctx.sema.scope(impl_def.syntax())?;
- let trait_ = resolve_target_trait(&ctx.sema, &impl_def)?;
+ let trait_ref = impl_.trait_ref(ctx.db())?;
+ let trait_ = trait_ref.trait_();
let missing_items = filter_assoc_items(
&ctx.sema,
@@ -155,7 +156,7 @@ fn add_missing_impl_members_inner(
let placeholder;
if let DefaultMethods::No = mode {
if let ast::AssocItem::Fn(func) = &first_new_item {
- if try_gen_trait_body(ctx, func, &trait_, &impl_def).is_none() {
+ if try_gen_trait_body(ctx, func, trait_ref, &impl_def).is_none() {
if let Some(m) =
func.syntax().descendants().find_map(ast::MacroCall::cast)
{
@@ -180,13 +181,13 @@ fn add_missing_impl_members_inner(
fn try_gen_trait_body(
ctx: &AssistContext<'_>,
func: &ast::Fn,
- trait_: &hir::Trait,
+ trait_ref: hir::TraitRef,
impl_def: &ast::Impl,
) -> Option<()> {
- let trait_path = make::ext::ident_path(&trait_.name(ctx.db()).to_string());
+ let trait_path = make::ext::ident_path(&trait_ref.trait_().name(ctx.db()).to_string());
let hir_ty = ctx.sema.resolve_type(&impl_def.self_ty()?)?;
let adt = hir_ty.as_adt()?.source(ctx.db())?;
- gen_trait_fn_body(func, &trait_path, &adt.value)
+ gen_trait_fn_body(func, &trait_path, &adt.value, Some(trait_ref))
}
#[cfg(test)]
@@ -1353,6 +1354,50 @@ impl PartialEq for SomeStruct {
}
#[test]
+ fn test_partial_eq_body_when_types_semantically_match() {
+ check_assist(
+ add_missing_impl_members,
+ r#"
+//- minicore: eq
+struct S<T, U>(T, U);
+type Alias<T> = S<T, T>;
+impl<T> PartialEq<Alias<T>> for S<T, T> {$0}
+"#,
+ r#"
+struct S<T, U>(T, U);
+type Alias<T> = S<T, T>;
+impl<T> PartialEq<Alias<T>> for S<T, T> {
+ $0fn eq(&self, other: &Alias<T>) -> bool {
+ self.0 == other.0 && self.1 == other.1
+ }
+}
+"#,
+ );
+ }
+
+ #[test]
+ fn test_partial_eq_body_when_types_dont_match() {
+ check_assist(
+ add_missing_impl_members,
+ r#"
+//- minicore: eq
+struct S<T, U>(T, U);
+type Alias<T> = S<T, T>;
+impl<T> PartialEq<Alias<T>> for S<T, i32> {$0}
+"#,
+ r#"
+struct S<T, U>(T, U);
+type Alias<T> = S<T, T>;
+impl<T> PartialEq<Alias<T>> for S<T, i32> {
+ fn eq(&self, other: &Alias<T>) -> bool {
+ ${0:todo!()}
+ }
+}
+"#,
+ );
+ }
+
+ #[test]
fn test_ignore_function_body() {
check_assist_not_applicable(
add_missing_default_members,
@@ -1442,4 +1487,35 @@ impl Trait for () {
}"#,
)
}
+
+ #[test]
+ fn test_works_inside_function() {
+ check_assist(
+ add_missing_impl_members,
+ r#"
+trait Tr {
+ fn method();
+}
+fn main() {
+ struct S;
+ impl Tr for S {
+ $0
+ }
+}
+"#,
+ r#"
+trait Tr {
+ fn method();
+}
+fn main() {
+ struct S;
+ impl Tr for S {
+ fn method() {
+ ${0:todo!()}
+ }
+ }
+}
+"#,
+ );
+ }
}
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_missing_match_arms.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_missing_match_arms.rs
index 8e4ac69ae..5d81e8cfe 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_missing_match_arms.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_missing_match_arms.rs
@@ -140,6 +140,31 @@ pub(crate) fn add_missing_match_arms(acc: &mut Assists, ctx: &AssistContext<'_>)
})
.filter(|(variant_pat, _)| is_variant_missing(&top_lvl_pats, variant_pat));
((Box::new(missing_pats) as Box<dyn Iterator<Item = _>>).peekable(), is_non_exhaustive)
+ } else if let Some((enum_def, len)) = resolve_array_of_enum_def(&ctx.sema, &expr) {
+ let is_non_exhaustive = enum_def.is_non_exhaustive(ctx.db(), module.krate());
+ let variants = enum_def.variants(ctx.db());
+
+ if len.pow(variants.len() as u32) > 256 {
+ return None;
+ }
+
+ let variants_of_enums = vec![variants.clone(); len];
+
+ let missing_pats = variants_of_enums
+ .into_iter()
+ .multi_cartesian_product()
+ .inspect(|_| cov_mark::hit!(add_missing_match_arms_lazy_computation))
+ .map(|variants| {
+ let is_hidden = variants
+ .iter()
+ .any(|variant| variant.should_be_hidden(ctx.db(), module.krate()));
+ let patterns = variants.into_iter().filter_map(|variant| {
+ build_pat(ctx.db(), module, variant.clone(), ctx.config.prefer_no_std)
+ });
+ (ast::Pat::from(make::slice_pat(patterns)), is_hidden)
+ })
+ .filter(|(variant_pat, _)| is_variant_missing(&top_lvl_pats, variant_pat));
+ ((Box::new(missing_pats) as Box<dyn Iterator<Item = _>>).peekable(), is_non_exhaustive)
} else {
return None;
};
@@ -266,9 +291,13 @@ fn is_variant_missing(existing_pats: &[Pat], var: &Pat) -> bool {
fn does_pat_match_variant(pat: &Pat, var: &Pat) -> bool {
match (pat, var) {
(Pat::WildcardPat(_), _) => true,
+ (Pat::SlicePat(spat), Pat::SlicePat(svar)) => {
+ spat.pats().zip(svar.pats()).all(|(p, v)| does_pat_match_variant(&p, &v))
+ }
(Pat::TuplePat(tpat), Pat::TuplePat(tvar)) => {
tpat.fields().zip(tvar.fields()).all(|(p, v)| does_pat_match_variant(&p, &v))
}
+ (Pat::OrPat(opat), _) => opat.pats().any(|p| does_pat_match_variant(&p, var)),
_ => utils::does_pat_match_variant(pat, var),
}
}
@@ -279,7 +308,7 @@ enum ExtendedEnum {
Enum(hir::Enum),
}
-#[derive(Eq, PartialEq, Clone, Copy)]
+#[derive(Eq, PartialEq, Clone, Copy, Debug)]
enum ExtendedVariant {
True,
False,
@@ -339,15 +368,30 @@ fn resolve_tuple_of_enum_def(
.tuple_fields(sema.db)
.iter()
.map(|ty| {
- ty.autoderef(sema.db).find_map(|ty| match ty.as_adt() {
- Some(Adt::Enum(e)) => Some(lift_enum(e)),
- // For now we only handle expansion for a tuple of enums. Here
- // we map non-enum items to None and rely on `collect` to
- // convert Vec<Option<hir::Enum>> into Option<Vec<hir::Enum>>.
- _ => ty.is_bool().then_some(ExtendedEnum::Bool),
+ ty.autoderef(sema.db).find_map(|ty| {
+ match ty.as_adt() {
+ Some(Adt::Enum(e)) => Some(lift_enum(e)),
+ // For now we only handle expansion for a tuple of enums. Here
+ // we map non-enum items to None and rely on `collect` to
+ // convert Vec<Option<hir::Enum>> into Option<Vec<hir::Enum>>.
+ _ => ty.is_bool().then_some(ExtendedEnum::Bool),
+ }
})
})
- .collect()
+ .collect::<Option<Vec<ExtendedEnum>>>()
+ .and_then(|list| if list.is_empty() { None } else { Some(list) })
+}
+
+fn resolve_array_of_enum_def(
+ sema: &Semantics<'_, RootDatabase>,
+ expr: &ast::Expr,
+) -> Option<(ExtendedEnum, usize)> {
+ sema.type_of_expr(expr)?.adjusted().as_array(sema.db).and_then(|(ty, len)| {
+ ty.autoderef(sema.db).find_map(|ty| match ty.as_adt() {
+ Some(Adt::Enum(e)) => Some((lift_enum(e), len)),
+ _ => ty.is_bool().then_some((ExtendedEnum::Bool, len)),
+ })
+ })
}
fn build_pat(
@@ -376,7 +420,6 @@ fn build_pat(
}
ast::StructKind::Unit => make::path_pat(path),
};
-
Some(pat)
}
ExtendedVariant::True => Some(ast::Pat::from(make::literal_pat("true"))),
@@ -526,6 +569,19 @@ fn foo(a: bool) {
r#"
fn foo(a: bool) {
match (a, a)$0 {
+ (true | false, true) => {}
+ (true, false) => {}
+ (false, false) => {}
+ }
+}
+"#,
+ );
+
+ check_assist_not_applicable(
+ add_missing_match_arms,
+ r#"
+fn foo(a: bool) {
+ match (a, a)$0 {
(true, true) => {}
(true, false) => {}
(false, true) => {}
@@ -560,12 +616,112 @@ fn foo(a: bool) {
}
#[test]
+ fn fill_boolean_array() {
+ check_assist(
+ add_missing_match_arms,
+ r#"
+fn foo(a: bool) {
+ match [a]$0 {
+ }
+}
+"#,
+ r#"
+fn foo(a: bool) {
+ match [a] {
+ $0[true] => todo!(),
+ [false] => todo!(),
+ }
+}
+"#,
+ );
+
+ check_assist(
+ add_missing_match_arms,
+ r#"
+fn foo(a: bool) {
+ match [a,]$0 {
+ }
+}
+"#,
+ r#"
+fn foo(a: bool) {
+ match [a,] {
+ $0[true] => todo!(),
+ [false] => todo!(),
+ }
+}
+"#,
+ );
+
+ check_assist(
+ add_missing_match_arms,
+ r#"
+fn foo(a: bool) {
+ match [a, a]$0 {
+ [true, true] => todo!(),
+ }
+}
+"#,
+ r#"
+fn foo(a: bool) {
+ match [a, a] {
+ [true, true] => todo!(),
+ $0[true, false] => todo!(),
+ [false, true] => todo!(),
+ [false, false] => todo!(),
+ }
+}
+"#,
+ );
+
+ check_assist(
+ add_missing_match_arms,
+ r#"
+fn foo(a: bool) {
+ match [a, a]$0 {
+ }
+}
+"#,
+ r#"
+fn foo(a: bool) {
+ match [a, a] {
+ $0[true, true] => todo!(),
+ [true, false] => todo!(),
+ [false, true] => todo!(),
+ [false, false] => todo!(),
+ }
+}
+"#,
+ )
+ }
+
+ #[test]
fn partial_fill_boolean_tuple() {
check_assist(
add_missing_match_arms,
r#"
fn foo(a: bool) {
match (a, a)$0 {
+ (true | false, true) => {}
+ }
+}
+"#,
+ r#"
+fn foo(a: bool) {
+ match (a, a) {
+ (true | false, true) => {}
+ $0(true, false) => todo!(),
+ (false, false) => todo!(),
+ }
+}
+"#,
+ );
+
+ check_assist(
+ add_missing_match_arms,
+ r#"
+fn foo(a: bool) {
+ match (a, a)$0 {
(false, true) => {}
}
}
@@ -882,6 +1038,33 @@ fn main() {
}
"#,
);
+
+ check_assist(
+ add_missing_match_arms,
+ r#"
+enum E { A, B, C }
+fn main() {
+ use E::*;
+ match (A, B, C)$0 {
+ (A | B , A, A | B | C) => (),
+ (A | B | C , B | C, A | B | C) => (),
+ }
+}
+"#,
+ r#"
+enum E { A, B, C }
+fn main() {
+ use E::*;
+ match (A, B, C) {
+ (A | B , A, A | B | C) => (),
+ (A | B | C , B | C, A | B | C) => (),
+ $0(C, A, A) => todo!(),
+ (C, A, B) => todo!(),
+ (C, A, C) => todo!(),
+ }
+}
+"#,
+ )
}
#[test]
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_comment_block.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_comment_block.rs
index 312cb65ab..1acd5ee97 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_comment_block.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_comment_block.rs
@@ -107,7 +107,7 @@ fn line_to_block(acc: &mut Assists, comment: ast::Comment) -> Option<()> {
/// The line -> block assist can be invoked from anywhere within a sequence of line comments.
/// relevant_line_comments crawls backwards and forwards finding the complete sequence of comments that will
/// be joined.
-fn relevant_line_comments(comment: &ast::Comment) -> Vec<Comment> {
+pub(crate) fn relevant_line_comments(comment: &ast::Comment) -> Vec<Comment> {
// The prefix identifies the kind of comment we're dealing with
let prefix = comment.prefix();
let same_prefix = |c: &ast::Comment| c.prefix() == prefix;
@@ -159,7 +159,7 @@ fn relevant_line_comments(comment: &ast::Comment) -> Vec<Comment> {
// */
//
// But since such comments aren't idiomatic we're okay with this.
-fn line_comment_text(indentation: IndentLevel, comm: ast::Comment) -> String {
+pub(crate) fn line_comment_text(indentation: IndentLevel, comm: ast::Comment) -> String {
let contents_without_prefix = comm.text().strip_prefix(comm.prefix()).unwrap();
let contents = contents_without_prefix.strip_prefix(' ').unwrap_or(contents_without_prefix);
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_match_to_let_else.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_match_to_let_else.rs
index 5bf04a3ad..65c2479e9 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_match_to_let_else.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_match_to_let_else.rs
@@ -30,24 +30,23 @@ use crate::{
// ```
pub(crate) fn convert_match_to_let_else(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> {
let let_stmt: ast::LetStmt = ctx.find_node_at_offset()?;
- let binding = find_binding(let_stmt.pat()?)?;
+ let binding = let_stmt.pat()?;
- let initializer = match let_stmt.initializer() {
- Some(ast::Expr::MatchExpr(it)) => it,
- _ => return None,
- };
+ let Some(ast::Expr::MatchExpr(initializer)) = let_stmt.initializer() else { return None };
let initializer_expr = initializer.expr()?;
- let (extracting_arm, diverging_arm) = match find_arms(ctx, &initializer) {
- Some(it) => it,
- None => return None,
- };
+ let Some((extracting_arm, diverging_arm)) = find_arms(ctx, &initializer) else { return None };
if extracting_arm.guard().is_some() {
cov_mark::hit!(extracting_arm_has_guard);
return None;
}
- let diverging_arm_expr = diverging_arm.expr()?;
+ let diverging_arm_expr = match diverging_arm.expr()? {
+ ast::Expr::BlockExpr(block) if block.modifier().is_none() && block.label().is_none() => {
+ block.to_string()
+ }
+ other => format!("{{ {other} }}"),
+ };
let extracting_arm_pat = extracting_arm.pat()?;
let extracted_variable = find_extracted_variable(ctx, &extracting_arm)?;
@@ -56,24 +55,16 @@ pub(crate) fn convert_match_to_let_else(acc: &mut Assists, ctx: &AssistContext<'
"Convert match to let-else",
let_stmt.syntax().text_range(),
|builder| {
- let extracting_arm_pat = rename_variable(&extracting_arm_pat, extracted_variable, binding);
+ let extracting_arm_pat =
+ rename_variable(&extracting_arm_pat, extracted_variable, binding);
builder.replace(
let_stmt.syntax().text_range(),
- format!("let {extracting_arm_pat} = {initializer_expr} else {{ {diverging_arm_expr} }};")
+ format!("let {extracting_arm_pat} = {initializer_expr} else {diverging_arm_expr};"),
)
},
)
}
-// Given a pattern, find the name introduced to the surrounding scope.
-fn find_binding(pat: ast::Pat) -> Option<ast::IdentPat> {
- if let ast::Pat::IdentPat(ident) = pat {
- Some(ident)
- } else {
- None
- }
-}
-
// Given a match expression, find extracting and diverging arms.
fn find_arms(
ctx: &AssistContext<'_>,
@@ -87,7 +78,7 @@ fn find_arms(
let mut extracting = None;
let mut diverging = None;
for arm in arms {
- if ctx.sema.type_of_expr(&arm.expr().unwrap()).unwrap().original().is_never() {
+ if ctx.sema.type_of_expr(&arm.expr()?)?.original().is_never() {
diverging = Some(arm);
} else {
extracting = Some(arm);
@@ -124,7 +115,7 @@ fn find_extracted_variable(ctx: &AssistContext<'_>, arm: &ast::MatchArm) -> Opti
}
// Rename `extracted` with `binding` in `pat`.
-fn rename_variable(pat: &ast::Pat, extracted: ast::Name, binding: ast::IdentPat) -> SyntaxNode {
+fn rename_variable(pat: &ast::Pat, extracted: ast::Name, binding: ast::Pat) -> SyntaxNode {
let syntax = pat.syntax().clone_for_update();
let extracted_syntax = syntax.covering_element(extracted.syntax().text_range());
@@ -136,7 +127,7 @@ fn rename_variable(pat: &ast::Pat, extracted: ast::Name, binding: ast::IdentPat)
if let Some(name_ref) = record_pat_field.field_name() {
ted::replace(
record_pat_field.syntax(),
- ast::make::record_pat_field(ast::make::name_ref(&name_ref.text()), binding.into())
+ ast::make::record_pat_field(ast::make::name_ref(&name_ref.text()), binding)
.syntax()
.clone_for_update(),
);
@@ -410,4 +401,52 @@ fn foo(opt: Option<i32>) -> Option<i32> {
"#,
);
}
+
+ #[test]
+ fn complex_pattern() {
+ check_assist(
+ convert_match_to_let_else,
+ r#"
+//- minicore: option
+fn f() {
+ let (x, y) = $0match Some((0, 1)) {
+ Some(it) => it,
+ None => return,
+ };
+}
+"#,
+ r#"
+fn f() {
+ let Some((x, y)) = Some((0, 1)) else { return };
+}
+"#,
+ );
+ }
+
+ #[test]
+ fn diverging_block() {
+ check_assist(
+ convert_match_to_let_else,
+ r#"
+//- minicore: option
+fn f() {
+ let x = $0match Some(()) {
+ Some(it) => it,
+ None => {//comment
+ println!("nope");
+ return
+ },
+ };
+}
+"#,
+ r#"
+fn f() {
+ let Some(x) = Some(()) else {//comment
+ println!("nope");
+ return
+ };
+}
+"#,
+ );
+ }
}
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_named_struct_to_tuple_struct.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_named_struct_to_tuple_struct.rs
index 8d11e0bac..9dc1da246 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_named_struct_to_tuple_struct.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_named_struct_to_tuple_struct.rs
@@ -52,10 +52,7 @@ pub(crate) fn convert_named_struct_to_tuple_struct(
acc: &mut Assists,
ctx: &AssistContext<'_>,
) -> Option<()> {
- let strukt = ctx
- .find_node_at_offset::<ast::Struct>()
- .map(Either::Left)
- .or_else(|| ctx.find_node_at_offset::<ast::Variant>().map(Either::Right))?;
+ let strukt = ctx.find_node_at_offset::<Either<ast::Struct, ast::Variant>>()?;
let field_list = strukt.as_ref().either(|s| s.field_list(), |v| v.field_list())?;
let record_fields = match field_list {
ast::FieldList::RecordFieldList(it) => it,
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_tuple_struct_to_named_struct.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_tuple_struct_to_named_struct.rs
index b0383291e..772e032fb 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_tuple_struct_to_named_struct.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_tuple_struct_to_named_struct.rs
@@ -50,10 +50,7 @@ pub(crate) fn convert_tuple_struct_to_named_struct(
acc: &mut Assists,
ctx: &AssistContext<'_>,
) -> Option<()> {
- let strukt = ctx
- .find_node_at_offset::<ast::Struct>()
- .map(Either::Left)
- .or_else(|| ctx.find_node_at_offset::<ast::Variant>().map(Either::Right))?;
+ let strukt = ctx.find_node_at_offset::<Either<ast::Struct, ast::Variant>>()?;
let field_list = strukt.as_ref().either(|s| s.field_list(), |v| v.field_list())?;
let tuple_fields = match field_list {
ast::FieldList::TupleFieldList(it) => it,
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/desugar_doc_comment.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/desugar_doc_comment.rs
new file mode 100644
index 000000000..226a5dd9f
--- /dev/null
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/desugar_doc_comment.rs
@@ -0,0 +1,312 @@
+use either::Either;
+use itertools::Itertools;
+use syntax::{
+ ast::{self, edit::IndentLevel, CommentPlacement, Whitespace},
+ AstToken, TextRange,
+};
+
+use crate::{
+ handlers::convert_comment_block::{line_comment_text, relevant_line_comments},
+ utils::required_hashes,
+ AssistContext, AssistId, AssistKind, Assists,
+};
+
+// Assist: desugar_doc_comment
+//
+// Desugars doc-comments to the attribute form.
+//
+// ```
+// /// Multi-line$0
+// /// comment
+// ```
+// ->
+// ```
+// #[doc = r"Multi-line
+// comment"]
+// ```
+pub(crate) fn desugar_doc_comment(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> {
+ let comment = ctx.find_token_at_offset::<ast::Comment>()?;
+ // Only allow doc comments
+ let Some(placement) = comment.kind().doc else { return None; };
+
+ // Only allow comments which are alone on their line
+ if let Some(prev) = comment.syntax().prev_token() {
+ if Whitespace::cast(prev).filter(|w| w.text().contains('\n')).is_none() {
+ return None;
+ }
+ }
+
+ let indentation = IndentLevel::from_token(comment.syntax()).to_string();
+
+ let (target, comments) = match comment.kind().shape {
+ ast::CommentShape::Block => (comment.syntax().text_range(), Either::Left(comment)),
+ ast::CommentShape::Line => {
+ // Find all the comments we'll be desugaring
+ let comments = relevant_line_comments(&comment);
+
+ // Establish the target of our edit based on the comments we found
+ (
+ TextRange::new(
+ comments[0].syntax().text_range().start(),
+ comments.last().unwrap().syntax().text_range().end(),
+ ),
+ Either::Right(comments),
+ )
+ }
+ };
+
+ acc.add(
+ AssistId("desugar_doc_comment", AssistKind::RefactorRewrite),
+ "Desugar doc-comment to attribute macro",
+ target,
+ |edit| {
+ let text = match comments {
+ Either::Left(comment) => {
+ let text = comment.text();
+ text[comment.prefix().len()..(text.len() - "*/".len())]
+ .trim()
+ .lines()
+ .map(|l| l.strip_prefix(&indentation).unwrap_or(l))
+ .join("\n")
+ }
+ Either::Right(comments) => {
+ comments.into_iter().map(|c| line_comment_text(IndentLevel(0), c)).join("\n")
+ }
+ };
+
+ let hashes = "#".repeat(required_hashes(&text));
+
+ let prefix = match placement {
+ CommentPlacement::Inner => "#!",
+ CommentPlacement::Outer => "#",
+ };
+
+ let output = format!(r#"{prefix}[doc = r{hashes}"{text}"{hashes}]"#);
+
+ edit.replace(target, output)
+ },
+ )
+}
+
+#[cfg(test)]
+mod tests {
+ use crate::tests::{check_assist, check_assist_not_applicable};
+
+ use super::*;
+
+ #[test]
+ fn single_line() {
+ check_assist(
+ desugar_doc_comment,
+ r#"
+/// line$0 comment
+fn main() {
+ foo();
+}
+"#,
+ r#"
+#[doc = r"line comment"]
+fn main() {
+ foo();
+}
+"#,
+ );
+ check_assist(
+ desugar_doc_comment,
+ r#"
+//! line$0 comment
+fn main() {
+ foo();
+}
+"#,
+ r#"
+#![doc = r"line comment"]
+fn main() {
+ foo();
+}
+"#,
+ );
+ }
+
+ #[test]
+ fn single_line_indented() {
+ check_assist(
+ desugar_doc_comment,
+ r#"
+fn main() {
+ /// line$0 comment
+ struct Foo;
+}
+"#,
+ r#"
+fn main() {
+ #[doc = r"line comment"]
+ struct Foo;
+}
+"#,
+ );
+ }
+
+ #[test]
+ fn multiline() {
+ check_assist(
+ desugar_doc_comment,
+ r#"
+fn main() {
+ /// above
+ /// line$0 comment
+ ///
+ /// below
+ struct Foo;
+}
+"#,
+ r#"
+fn main() {
+ #[doc = r"above
+line comment
+
+below"]
+ struct Foo;
+}
+"#,
+ );
+ }
+
+ #[test]
+ fn end_of_line() {
+ check_assist_not_applicable(
+ desugar_doc_comment,
+ r#"
+fn main() { /// end-of-line$0 comment
+ struct Foo;
+}
+"#,
+ );
+ }
+
+ #[test]
+ fn single_line_different_kinds() {
+ check_assist(
+ desugar_doc_comment,
+ r#"
+fn main() {
+ //! different prefix
+ /// line$0 comment
+ /// below
+ struct Foo;
+}
+"#,
+ r#"
+fn main() {
+ //! different prefix
+ #[doc = r"line comment
+below"]
+ struct Foo;
+}
+"#,
+ );
+ }
+
+ #[test]
+ fn single_line_separate_chunks() {
+ check_assist(
+ desugar_doc_comment,
+ r#"
+/// different chunk
+
+/// line$0 comment
+/// below
+"#,
+ r#"
+/// different chunk
+
+#[doc = r"line comment
+below"]
+"#,
+ );
+ }
+
+ #[test]
+ fn block_comment() {
+ check_assist(
+ desugar_doc_comment,
+ r#"
+/**
+ hi$0 there
+*/
+"#,
+ r#"
+#[doc = r"hi there"]
+"#,
+ );
+ }
+
+ #[test]
+ fn inner_doc_block() {
+ check_assist(
+ desugar_doc_comment,
+ r#"
+/*!
+ hi$0 there
+*/
+"#,
+ r#"
+#![doc = r"hi there"]
+"#,
+ );
+ }
+
+ #[test]
+ fn block_indent() {
+ check_assist(
+ desugar_doc_comment,
+ r#"
+fn main() {
+ /*!
+ hi$0 there
+
+ ```
+ code_sample
+ ```
+ */
+}
+"#,
+ r#"
+fn main() {
+ #![doc = r"hi there
+
+```
+ code_sample
+```"]
+}
+"#,
+ );
+ }
+
+ #[test]
+ fn end_of_line_block() {
+ check_assist_not_applicable(
+ desugar_doc_comment,
+ r#"
+fn main() {
+ foo(); /** end-of-line$0 comment */
+}
+"#,
+ );
+ }
+
+ #[test]
+ fn regular_comment() {
+ check_assist_not_applicable(desugar_doc_comment, r#"// some$0 comment"#);
+ check_assist_not_applicable(desugar_doc_comment, r#"/* some$0 comment*/"#);
+ }
+
+ #[test]
+ fn quotes_and_escapes() {
+ check_assist(
+ desugar_doc_comment,
+ r###"/// some$0 "\ "## comment"###,
+ r####"#[doc = r###"some "\ "## comment"###]"####,
+ );
+ }
+}
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_type_alias.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_type_alias.rs
index 0505f5784..b310c2db9 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_type_alias.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_type_alias.rs
@@ -1,9 +1,6 @@
use either::Either;
use ide_db::syntax_helpers::node_ext::walk_ty;
-use syntax::{
- ast::{self, edit::IndentLevel, make, AstNode, HasGenericParams, HasName},
- match_ast,
-};
+use syntax::ast::{self, edit::IndentLevel, make, AstNode, HasGenericParams, HasName};
use crate::{AssistContext, AssistId, AssistKind, Assists};
@@ -31,15 +28,8 @@ pub(crate) fn extract_type_alias(acc: &mut Assists, ctx: &AssistContext<'_>) ->
let ty = ctx.find_node_at_range::<ast::Type>()?;
let item = ty.syntax().ancestors().find_map(ast::Item::cast)?;
- let assoc_owner = item.syntax().ancestors().nth(2).and_then(|it| {
- match_ast! {
- match it {
- ast::Trait(tr) => Some(Either::Left(tr)),
- ast::Impl(impl_) => Some(Either::Right(impl_)),
- _ => None,
- }
- }
- });
+ let assoc_owner =
+ item.syntax().ancestors().nth(2).and_then(Either::<ast::Trait, ast::Impl>::cast);
let node = assoc_owner.as_ref().map_or_else(
|| item.syntax(),
|impl_| impl_.as_ref().either(AstNode::syntax, AstNode::syntax),
@@ -161,19 +151,17 @@ fn collect_used_generics<'gp>(
.and_then(|lt| known_generics.iter().find(find_lifetime(&lt.text()))),
),
ast::Type::ArrayType(ar) => {
- if let Some(expr) = ar.expr() {
- if let ast::Expr::PathExpr(p) = expr {
- if let Some(path) = p.path() {
- if let Some(name_ref) = path.as_single_name_ref() {
- if let Some(param) = known_generics.iter().find(|gp| {
- if let ast::GenericParam::ConstParam(cp) = gp {
- cp.name().map_or(false, |n| n.text() == name_ref.text())
- } else {
- false
- }
- }) {
- generics.push(param);
+ if let Some(ast::Expr::PathExpr(p)) = ar.expr() {
+ if let Some(path) = p.path() {
+ if let Some(name_ref) = path.as_single_name_ref() {
+ if let Some(param) = known_generics.iter().find(|gp| {
+ if let ast::GenericParam::ConstParam(cp) = gp {
+ cp.name().map_or(false, |n| n.text() == name_ref.text())
+ } else {
+ false
}
+ }) {
+ generics.push(param);
}
}
}
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_default_from_new.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_default_from_new.rs
index 2d074a33e..860372941 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_default_from_new.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_default_from_new.rs
@@ -82,18 +82,18 @@ fn generate_trait_impl_text_from_impl(impl_: &ast::Impl, trait_text: &str, code:
let generic_params = impl_.generic_param_list().map(|generic_params| {
let lifetime_params =
generic_params.lifetime_params().map(ast::GenericParam::LifetimeParam);
- let ty_or_const_params = generic_params.type_or_const_params().filter_map(|param| {
+ let ty_or_const_params = generic_params.type_or_const_params().map(|param| {
// remove defaults since they can't be specified in impls
match param {
ast::TypeOrConstParam::Type(param) => {
let param = param.clone_for_update();
param.remove_default();
- Some(ast::GenericParam::TypeParam(param))
+ ast::GenericParam::TypeParam(param)
}
ast::TypeOrConstParam::Const(param) => {
let param = param.clone_for_update();
param.remove_default();
- Some(ast::GenericParam::ConstParam(param))
+ ast::GenericParam::ConstParam(param)
}
}
});
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_delegate_methods.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_delegate_methods.rs
index c8d0493d0..ed1b8f4e2 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_delegate_methods.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_delegate_methods.rs
@@ -109,7 +109,7 @@ pub(crate) fn generate_delegate_methods(acc: &mut Assists, ctx: &AssistContext<'
let tail_expr_finished =
if is_async { make::expr_await(tail_expr) } else { tail_expr };
let body = make::block_expr([], Some(tail_expr_finished));
- let f = make::fn_(vis, name, type_params, params, body, ret_type, is_async)
+ let f = make::fn_(vis, name, type_params, None, params, body, ret_type, is_async)
.indent(ast::edit::IndentLevel(1))
.clone_for_update();
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_function.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_function.rs
index da9b0cda5..45b27a63c 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_function.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_function.rs
@@ -1,8 +1,11 @@
-use hir::{Adt, HasSource, HirDisplay, Module, Semantics, TypeInfo};
+use hir::{
+ Adt, AsAssocItem, HasSource, HirDisplay, Module, PathResolution, Semantics, Type, TypeInfo,
+};
use ide_db::{
base_db::FileId,
defs::{Definition, NameRefClass},
famous_defs::FamousDefs,
+ path_transform::PathTransform,
FxHashMap, FxHashSet, RootDatabase, SnippetCap,
};
use stdx::to_lower_snake_case;
@@ -10,14 +13,13 @@ use syntax::{
ast::{
self,
edit::{AstNodeEdit, IndentLevel},
- make, AstNode, CallExpr, HasArgList, HasModuleItem,
+ make, AstNode, CallExpr, HasArgList, HasGenericParams, HasModuleItem, HasTypeBounds,
},
SyntaxKind, SyntaxNode, TextRange, TextSize,
};
use crate::{
- utils::convert_reference_type,
- utils::{find_struct_impl, render_snippet, Cursor},
+ utils::{convert_reference_type, find_struct_impl, render_snippet, Cursor},
AssistContext, AssistId, AssistKind, Assists,
};
@@ -107,7 +109,7 @@ fn fn_target_info(
match path.qualifier() {
Some(qualifier) => match ctx.sema.resolve_path(&qualifier) {
Some(hir::PathResolution::Def(hir::ModuleDef::Module(module))) => {
- get_fn_target_info(ctx, &Some(module), call.clone())
+ get_fn_target_info(ctx, Some(module), call.clone())
}
Some(hir::PathResolution::Def(hir::ModuleDef::Adt(adt))) => {
if let hir::Adt::Enum(_) = adt {
@@ -125,7 +127,7 @@ fn fn_target_info(
}
_ => None,
},
- _ => get_fn_target_info(ctx, &None, call.clone()),
+ _ => get_fn_target_info(ctx, None, call.clone()),
}
}
@@ -136,7 +138,8 @@ fn gen_method(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> {
}
let fn_name = call.name_ref()?;
- let adt = ctx.sema.type_of_expr(&call.receiver()?)?.original().strip_references().as_adt()?;
+ let receiver_ty = ctx.sema.type_of_expr(&call.receiver()?)?.original().strip_references();
+ let adt = receiver_ty.as_adt()?;
let current_module = ctx.sema.scope(call.syntax())?.module();
let target_module = adt.module(ctx.sema.db);
@@ -147,8 +150,14 @@ fn gen_method(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> {
let (impl_, file) = get_adt_source(ctx, &adt, fn_name.text().as_str())?;
let (target, insert_offset) = get_method_target(ctx, &impl_, &adt)?;
- let function_builder =
- FunctionBuilder::from_method_call(ctx, &call, &fn_name, target_module, target)?;
+ let function_builder = FunctionBuilder::from_method_call(
+ ctx,
+ &call,
+ &fn_name,
+ receiver_ty,
+ target_module,
+ target,
+ )?;
let text_range = call.syntax().text_range();
let adt_name = if impl_.is_none() { Some(adt.name(ctx.sema.db)) } else { None };
let label = format!("Generate {} method", function_builder.fn_name);
@@ -179,6 +188,7 @@ fn add_func_to_accumulator(
let function_template = function_builder.render(adt_name.is_some());
let mut func = function_template.to_string(ctx.config.snippet_cap);
if let Some(name) = adt_name {
+ // FIXME: adt may have generic params.
func = format!("\n{indent}impl {name} {{\n{func}\n{indent}}}");
}
builder.edit_file(file);
@@ -238,7 +248,8 @@ impl FunctionTemplate {
struct FunctionBuilder {
target: GeneratedFunctionTarget,
fn_name: ast::Name,
- type_params: Option<ast::GenericParamList>,
+ generic_param_list: Option<ast::GenericParamList>,
+ where_clause: Option<ast::WhereClause>,
params: ast::ParamList,
ret_type: Option<ast::RetType>,
should_focus_return_type: bool,
@@ -260,19 +271,32 @@ impl FunctionBuilder {
let target_module =
target_module.or_else(|| ctx.sema.scope(target.syntax()).map(|it| it.module()))?;
let fn_name = make::name(fn_name);
- let (type_params, params) =
- fn_args(ctx, target_module, ast::CallableExpr::Call(call.clone()))?;
+ let mut necessary_generic_params = FxHashSet::default();
+ let params = fn_args(
+ ctx,
+ target_module,
+ ast::CallableExpr::Call(call.clone()),
+ &mut necessary_generic_params,
+ )?;
let await_expr = call.syntax().parent().and_then(ast::AwaitExpr::cast);
let is_async = await_expr.is_some();
- let (ret_type, should_focus_return_type) =
- make_return_type(ctx, &ast::Expr::CallExpr(call.clone()), target_module);
+ let (ret_type, should_focus_return_type) = make_return_type(
+ ctx,
+ &ast::Expr::CallExpr(call.clone()),
+ target_module,
+ &mut necessary_generic_params,
+ );
+
+ let (generic_param_list, where_clause) =
+ fn_generic_params(ctx, necessary_generic_params, &target)?;
Some(Self {
target,
fn_name,
- type_params,
+ generic_param_list,
+ where_clause,
params,
ret_type,
should_focus_return_type,
@@ -285,25 +309,40 @@ impl FunctionBuilder {
ctx: &AssistContext<'_>,
call: &ast::MethodCallExpr,
name: &ast::NameRef,
+ receiver_ty: Type,
target_module: Module,
target: GeneratedFunctionTarget,
) -> Option<Self> {
let needs_pub =
!module_is_descendant(&ctx.sema.scope(call.syntax())?.module(), &target_module, ctx);
let fn_name = make::name(&name.text());
- let (type_params, params) =
- fn_args(ctx, target_module, ast::CallableExpr::MethodCall(call.clone()))?;
+ let mut necessary_generic_params = FxHashSet::default();
+ necessary_generic_params.extend(receiver_ty.generic_params(ctx.db()));
+ let params = fn_args(
+ ctx,
+ target_module,
+ ast::CallableExpr::MethodCall(call.clone()),
+ &mut necessary_generic_params,
+ )?;
let await_expr = call.syntax().parent().and_then(ast::AwaitExpr::cast);
let is_async = await_expr.is_some();
- let (ret_type, should_focus_return_type) =
- make_return_type(ctx, &ast::Expr::MethodCallExpr(call.clone()), target_module);
+ let (ret_type, should_focus_return_type) = make_return_type(
+ ctx,
+ &ast::Expr::MethodCallExpr(call.clone()),
+ target_module,
+ &mut necessary_generic_params,
+ );
+
+ let (generic_param_list, where_clause) =
+ fn_generic_params(ctx, necessary_generic_params, &target)?;
Some(Self {
target,
fn_name,
- type_params,
+ generic_param_list,
+ where_clause,
params,
ret_type,
should_focus_return_type,
@@ -319,7 +358,8 @@ impl FunctionBuilder {
let mut fn_def = make::fn_(
visibility,
self.fn_name,
- self.type_params,
+ self.generic_param_list,
+ self.where_clause,
self.params,
fn_body,
self.ret_type,
@@ -375,6 +415,7 @@ fn make_return_type(
ctx: &AssistContext<'_>,
call: &ast::Expr,
target_module: Module,
+ necessary_generic_params: &mut FxHashSet<hir::GenericParam>,
) -> (Option<ast::RetType>, bool) {
let (ret_ty, should_focus_return_type) = {
match ctx.sema.type_of_expr(call).map(TypeInfo::original) {
@@ -382,6 +423,7 @@ fn make_return_type(
None => (Some(make::ty_placeholder()), true),
Some(ty) if ty.is_unit() => (None, false),
Some(ty) => {
+ necessary_generic_params.extend(ty.generic_params(ctx.db()));
let rendered = ty.display_source_code(ctx.db(), target_module.into());
match rendered {
Ok(rendered) => (Some(make::ty(&rendered)), false),
@@ -396,16 +438,16 @@ fn make_return_type(
fn get_fn_target_info(
ctx: &AssistContext<'_>,
- target_module: &Option<Module>,
+ target_module: Option<Module>,
call: CallExpr,
) -> Option<TargetInfo> {
let (target, file, insert_offset) = get_fn_target(ctx, target_module, call)?;
- Some(TargetInfo::new(*target_module, None, target, file, insert_offset))
+ Some(TargetInfo::new(target_module, None, target, file, insert_offset))
}
fn get_fn_target(
ctx: &AssistContext<'_>,
- target_module: &Option<Module>,
+ target_module: Option<Module>,
call: CallExpr,
) -> Option<(GeneratedFunctionTarget, FileId, TextSize)> {
let mut file = ctx.file_id();
@@ -473,37 +515,386 @@ impl GeneratedFunctionTarget {
GeneratedFunctionTarget::InEmptyItemList(it) => it,
}
}
+
+ fn parent(&self) -> SyntaxNode {
+ match self {
+ GeneratedFunctionTarget::BehindItem(it) => it.parent().expect("item without parent"),
+ GeneratedFunctionTarget::InEmptyItemList(it) => it.clone(),
+ }
+ }
}
-/// Computes the type variables and arguments required for the generated function
+/// Computes parameter list for the generated function.
fn fn_args(
ctx: &AssistContext<'_>,
target_module: hir::Module,
call: ast::CallableExpr,
-) -> Option<(Option<ast::GenericParamList>, ast::ParamList)> {
+ necessary_generic_params: &mut FxHashSet<hir::GenericParam>,
+) -> Option<ast::ParamList> {
let mut arg_names = Vec::new();
let mut arg_types = Vec::new();
for arg in call.arg_list()?.args() {
arg_names.push(fn_arg_name(&ctx.sema, &arg));
- arg_types.push(fn_arg_type(ctx, target_module, &arg));
+ arg_types.push(fn_arg_type(ctx, target_module, &arg, necessary_generic_params));
}
deduplicate_arg_names(&mut arg_names);
let params = arg_names.into_iter().zip(arg_types).map(|(name, ty)| {
make::param(make::ext::simple_ident_pat(make::name(&name)).into(), make::ty(&ty))
});
- Some((
- None,
- make::param_list(
- match call {
- ast::CallableExpr::Call(_) => None,
- ast::CallableExpr::MethodCall(_) => Some(make::self_param()),
- },
- params,
- ),
+ Some(make::param_list(
+ match call {
+ ast::CallableExpr::Call(_) => None,
+ ast::CallableExpr::MethodCall(_) => Some(make::self_param()),
+ },
+ params,
))
}
+/// Gets parameter bounds and where predicates in scope and filters out irrelevant ones. Returns
+/// `None` when it fails to get scope information.
+///
+/// See comment on `filter_unnecessary_bounds()` for what bounds we consider relevant.
+///
+/// NOTE: Generic parameters returned from this function may cause name clash at `target`. We don't
+/// currently do anything about it because it's actually easy to resolve it after the assist: just
+/// use the Rename functionality.
+fn fn_generic_params(
+ ctx: &AssistContext<'_>,
+ necessary_params: FxHashSet<hir::GenericParam>,
+ target: &GeneratedFunctionTarget,
+) -> Option<(Option<ast::GenericParamList>, Option<ast::WhereClause>)> {
+ if necessary_params.is_empty() {
+ // Not really needed but fast path.
+ return Some((None, None));
+ }
+
+ // 1. Get generic parameters (with bounds) and where predicates in scope.
+ let (generic_params, where_preds) = params_and_where_preds_in_scope(ctx);
+
+ // 2. Extract type parameters included in each bound.
+ let mut generic_params = generic_params
+ .into_iter()
+ .filter_map(|it| compute_contained_params_in_generic_param(ctx, it))
+ .collect();
+ let mut where_preds = where_preds
+ .into_iter()
+ .filter_map(|it| compute_contained_params_in_where_pred(ctx, it))
+ .collect();
+
+ // 3. Filter out unnecessary bounds.
+ filter_unnecessary_bounds(&mut generic_params, &mut where_preds, necessary_params);
+ filter_bounds_in_scope(&mut generic_params, &mut where_preds, ctx, target);
+
+ let generic_params: Vec<_> =
+ generic_params.into_iter().map(|it| it.node.clone_for_update()).collect();
+ let where_preds: Vec<_> =
+ where_preds.into_iter().map(|it| it.node.clone_for_update()).collect();
+
+ // 4. Rewrite paths
+ if let Some(param) = generic_params.first() {
+ let source_scope = ctx.sema.scope(param.syntax())?;
+ let target_scope = ctx.sema.scope(&target.parent())?;
+ if source_scope.module() != target_scope.module() {
+ let transform = PathTransform::generic_transformation(&target_scope, &source_scope);
+ let generic_params = generic_params.iter().map(|it| it.syntax());
+ let where_preds = where_preds.iter().map(|it| it.syntax());
+ transform.apply_all(generic_params.chain(where_preds));
+ }
+ }
+
+ let generic_param_list = make::generic_param_list(generic_params);
+ let where_clause =
+ if where_preds.is_empty() { None } else { Some(make::where_clause(where_preds)) };
+
+ Some((Some(generic_param_list), where_clause))
+}
+
+fn params_and_where_preds_in_scope(
+ ctx: &AssistContext<'_>,
+) -> (Vec<ast::GenericParam>, Vec<ast::WherePred>) {
+ let Some(body) = containing_body(ctx) else { return Default::default(); };
+
+ let mut generic_params = Vec::new();
+ let mut where_clauses = Vec::new();
+
+ // There are two items where generic parameters currently in scope may be declared: the item
+ // the cursor is at, and its parent (if any).
+ //
+ // We handle parent first so that their generic parameters appear first in the generic
+ // parameter list of the function we're generating.
+ let db = ctx.db();
+ if let Some(parent) = body.as_assoc_item(db).map(|it| it.container(db)) {
+ match parent {
+ hir::AssocItemContainer::Impl(it) => {
+ let (params, clauses) = get_bounds_in_scope(ctx, it);
+ generic_params.extend(params);
+ where_clauses.extend(clauses);
+ }
+ hir::AssocItemContainer::Trait(it) => {
+ let (params, clauses) = get_bounds_in_scope(ctx, it);
+ generic_params.extend(params);
+ where_clauses.extend(clauses);
+ }
+ }
+ }
+
+ // Other defs with body may inherit generic parameters from its parent, but never have their
+ // own generic parameters.
+ if let hir::DefWithBody::Function(it) = body {
+ let (params, clauses) = get_bounds_in_scope(ctx, it);
+ generic_params.extend(params);
+ where_clauses.extend(clauses);
+ }
+
+ (generic_params, where_clauses)
+}
+
+fn containing_body(ctx: &AssistContext<'_>) -> Option<hir::DefWithBody> {
+ let item: ast::Item = ctx.find_node_at_offset()?;
+ let def = match item {
+ ast::Item::Fn(it) => ctx.sema.to_def(&it)?.into(),
+ ast::Item::Const(it) => ctx.sema.to_def(&it)?.into(),
+ ast::Item::Static(it) => ctx.sema.to_def(&it)?.into(),
+ _ => return None,
+ };
+ Some(def)
+}
+
+fn get_bounds_in_scope<D>(
+ ctx: &AssistContext<'_>,
+ def: D,
+) -> (impl Iterator<Item = ast::GenericParam>, impl Iterator<Item = ast::WherePred>)
+where
+ D: HasSource,
+ D::Ast: HasGenericParams,
+{
+ // This function should be only called with `Impl`, `Trait`, or `Function`, for which it's
+ // infallible to get source ast.
+ let node = ctx.sema.source(def).unwrap().value;
+ let generic_params = node.generic_param_list().into_iter().flat_map(|it| it.generic_params());
+ let where_clauses = node.where_clause().into_iter().flat_map(|it| it.predicates());
+ (generic_params, where_clauses)
+}
+
+#[derive(Debug)]
+struct ParamBoundWithParams {
+ node: ast::GenericParam,
+ /// Generic parameter `node` introduces.
+ ///
+ /// ```text
+ /// impl<T> S<T> {
+ /// fn f<U: Trait<T>>() {}
+ /// ^ this
+ /// }
+ /// ```
+ ///
+ /// `U` in this example.
+ self_ty_param: hir::GenericParam,
+ /// Generic parameters contained in the trait reference of this bound.
+ ///
+ /// ```text
+ /// impl<T> S<T> {
+ /// fn f<U: Trait<T>>() {}
+ /// ^^^^^^^^ params in this part
+ /// }
+ /// ```
+ ///
+ /// `T` in this example.
+ other_params: FxHashSet<hir::GenericParam>,
+}
+
+#[derive(Debug)]
+struct WherePredWithParams {
+ node: ast::WherePred,
+ /// Generic parameters contained in the "self type" of this where predicate.
+ ///
+ /// ```text
+ /// Struct<T, U>: Trait<T, Assoc = V>,
+ /// ^^^^^^^^^^^^ params in this part
+ /// ```
+ ///
+ /// `T` and `U` in this example.
+ self_ty_params: FxHashSet<hir::GenericParam>,
+ /// Generic parameters contained in the trait reference of this where predicate.
+ ///
+ /// ```text
+ /// Struct<T, U>: Trait<T, Assoc = V>,
+ /// ^^^^^^^^^^^^^^^^^^^ params in this part
+ /// ```
+ ///
+ /// `T` and `V` in this example.
+ other_params: FxHashSet<hir::GenericParam>,
+}
+
+fn compute_contained_params_in_generic_param(
+ ctx: &AssistContext<'_>,
+ node: ast::GenericParam,
+) -> Option<ParamBoundWithParams> {
+ match &node {
+ ast::GenericParam::TypeParam(ty) => {
+ let self_ty_param = ctx.sema.to_def(ty)?.into();
+
+ let other_params = ty
+ .type_bound_list()
+ .into_iter()
+ .flat_map(|it| it.bounds())
+ .flat_map(|bound| bound.syntax().descendants())
+ .filter_map(|node| filter_generic_params(ctx, node))
+ .collect();
+
+ Some(ParamBoundWithParams { node, self_ty_param, other_params })
+ }
+ ast::GenericParam::ConstParam(ct) => {
+ let self_ty_param = ctx.sema.to_def(ct)?.into();
+ Some(ParamBoundWithParams { node, self_ty_param, other_params: FxHashSet::default() })
+ }
+ ast::GenericParam::LifetimeParam(_) => {
+ // FIXME: It might be a good idea to handle lifetime parameters too.
+ None
+ }
+ }
+}
+
+fn compute_contained_params_in_where_pred(
+ ctx: &AssistContext<'_>,
+ node: ast::WherePred,
+) -> Option<WherePredWithParams> {
+ let self_ty = node.ty()?;
+ let bound_list = node.type_bound_list()?;
+
+ let self_ty_params = self_ty
+ .syntax()
+ .descendants()
+ .filter_map(|node| filter_generic_params(ctx, node))
+ .collect();
+
+ let other_params = bound_list
+ .bounds()
+ .flat_map(|bound| bound.syntax().descendants())
+ .filter_map(|node| filter_generic_params(ctx, node))
+ .collect();
+
+ Some(WherePredWithParams { node, self_ty_params, other_params })
+}
+
+fn filter_generic_params(ctx: &AssistContext<'_>, node: SyntaxNode) -> Option<hir::GenericParam> {
+ let path = ast::Path::cast(node)?;
+ match ctx.sema.resolve_path(&path)? {
+ PathResolution::TypeParam(it) => Some(it.into()),
+ PathResolution::ConstParam(it) => Some(it.into()),
+ _ => None,
+ }
+}
+
+/// Filters out irrelevant bounds from `generic_params` and `where_preds`.
+///
+/// Say we have a trait bound `Struct<T>: Trait<U>`. Given `necessary_params`, when is it relevant
+/// and when not? Some observations:
+/// - When `necessary_params` contains `T`, it's likely that we want this bound, but now we have
+/// an extra param to consider: `U`.
+/// - On the other hand, when `necessary_params` contains `U` (but not `T`), then it's unlikely
+/// that we want this bound because it doesn't really constrain `U`.
+///
+/// (FIXME?: The latter clause might be overstating. We may want to include the bound if the self
+/// type does *not* include generic params at all - like `Option<i32>: From<U>`)
+///
+/// Can we make this a bit more formal? Let's define "dependency" between generic parameters and
+/// trait bounds:
+/// - A generic parameter `T` depends on a trait bound if `T` appears in the self type (i.e. left
+/// part) of the bound.
+/// - A trait bound depends on a generic parameter `T` if `T` appears in the bound.
+///
+/// Using the notion, what we want is all the bounds that params in `necessary_params`
+/// *transitively* depend on!
+///
+/// Now it's not hard to solve: we build a dependency graph and compute all reachable nodes from
+/// nodes that represent params in `necessary_params` by usual and boring DFS.
+///
+/// The time complexity is O(|generic_params| + |where_preds| + |necessary_params|).
+fn filter_unnecessary_bounds(
+ generic_params: &mut Vec<ParamBoundWithParams>,
+ where_preds: &mut Vec<WherePredWithParams>,
+ necessary_params: FxHashSet<hir::GenericParam>,
+) {
+ // All `self_ty_param` should be unique as they were collected from `ast::GenericParamList`s.
+ let param_map: FxHashMap<hir::GenericParam, usize> =
+ generic_params.iter().map(|it| it.self_ty_param).zip(0..).collect();
+ let param_count = param_map.len();
+ let generic_params_upper_bound = param_count + generic_params.len();
+ let node_count = generic_params_upper_bound + where_preds.len();
+
+ // | node index range | what the node represents |
+ // |-----------------------------------------|--------------------------|
+ // | 0..param_count | generic parameter |
+ // | param_count..generic_params_upper_bound | `ast::GenericParam` |
+ // | generic_params_upper_bound..node_count | `ast::WherePred` |
+ let mut graph = Graph::new(node_count);
+ for (pred, pred_idx) in generic_params.iter().zip(param_count..) {
+ let param_idx = param_map[&pred.self_ty_param];
+ graph.add_edge(param_idx, pred_idx);
+ graph.add_edge(pred_idx, param_idx);
+
+ for param in &pred.other_params {
+ let param_idx = param_map[param];
+ graph.add_edge(pred_idx, param_idx);
+ }
+ }
+ for (pred, pred_idx) in where_preds.iter().zip(generic_params_upper_bound..) {
+ for param in &pred.self_ty_params {
+ let param_idx = param_map[param];
+ graph.add_edge(param_idx, pred_idx);
+ graph.add_edge(pred_idx, param_idx);
+ }
+ for param in &pred.other_params {
+ let param_idx = param_map[param];
+ graph.add_edge(pred_idx, param_idx);
+ }
+ }
+
+ let starting_nodes = necessary_params.iter().map(|param| param_map[param]);
+ let reachable = graph.compute_reachable_nodes(starting_nodes);
+
+ // Not pretty, but effective. If only there were `Vec::retain_index()`...
+ let mut idx = param_count;
+ generic_params.retain(|_| {
+ idx += 1;
+ reachable[idx - 1]
+ });
+ stdx::always!(idx == generic_params_upper_bound, "inconsistent index");
+ where_preds.retain(|_| {
+ idx += 1;
+ reachable[idx - 1]
+ });
+}
+
+/// Filters out bounds from impl if we're generating the function into the same impl we're
+/// generating from.
+fn filter_bounds_in_scope(
+ generic_params: &mut Vec<ParamBoundWithParams>,
+ where_preds: &mut Vec<WherePredWithParams>,
+ ctx: &AssistContext<'_>,
+ target: &GeneratedFunctionTarget,
+) -> Option<()> {
+ let target_impl = target.parent().ancestors().find_map(ast::Impl::cast)?;
+ let target_impl = ctx.sema.to_def(&target_impl)?;
+ // It's sufficient to test only the first element of `generic_params` because of the order of
+ // insertion (see `relevant_parmas_and_where_clauses()`).
+ let def = generic_params.first()?.self_ty_param.parent();
+ if def != hir::GenericDef::Impl(target_impl) {
+ return None;
+ }
+
+ // Now we know every element that belongs to an impl would be in scope at `target`, we can
+ // filter them out just by lookint at their parent.
+ generic_params.retain(|it| !matches!(it.self_ty_param.parent(), hir::GenericDef::Impl(_)));
+ where_preds.retain(|it| {
+ it.node.syntax().parent().and_then(|it| it.parent()).and_then(ast::Impl::cast).is_none()
+ });
+
+ Some(())
+}
+
/// Makes duplicate argument names unique by appending incrementing numbers.
///
/// ```
@@ -564,17 +955,25 @@ fn fn_arg_name(sema: &Semantics<'_, RootDatabase>, arg_expr: &ast::Expr) -> Stri
}
}
-fn fn_arg_type(ctx: &AssistContext<'_>, target_module: hir::Module, fn_arg: &ast::Expr) -> String {
+fn fn_arg_type(
+ ctx: &AssistContext<'_>,
+ target_module: hir::Module,
+ fn_arg: &ast::Expr,
+ generic_params: &mut FxHashSet<hir::GenericParam>,
+) -> String {
fn maybe_displayed_type(
ctx: &AssistContext<'_>,
target_module: hir::Module,
fn_arg: &ast::Expr,
+ generic_params: &mut FxHashSet<hir::GenericParam>,
) -> Option<String> {
let ty = ctx.sema.type_of_expr(fn_arg)?.adjusted();
if ty.is_unknown() {
return None;
}
+ generic_params.extend(ty.generic_params(ctx.db()));
+
if ty.is_reference() || ty.is_mutable_reference() {
let famous_defs = &FamousDefs(&ctx.sema, ctx.sema.scope(fn_arg.syntax())?.krate());
convert_reference_type(ty.strip_references(), ctx.db(), famous_defs)
@@ -585,7 +984,8 @@ fn fn_arg_type(ctx: &AssistContext<'_>, target_module: hir::Module, fn_arg: &ast
}
}
- maybe_displayed_type(ctx, target_module, fn_arg).unwrap_or_else(|| String::from("_"))
+ maybe_displayed_type(ctx, target_module, fn_arg, generic_params)
+ .unwrap_or_else(|| String::from("_"))
}
/// Returns the position inside the current mod or file
@@ -640,10 +1040,11 @@ fn next_space_for_fn_in_module(
}
fn next_space_for_fn_in_impl(impl_: &ast::Impl) -> Option<GeneratedFunctionTarget> {
- if let Some(last_item) = impl_.assoc_item_list().and_then(|it| it.assoc_items().last()) {
+ let assoc_item_list = impl_.assoc_item_list()?;
+ if let Some(last_item) = assoc_item_list.assoc_items().last() {
Some(GeneratedFunctionTarget::BehindItem(last_item.syntax().clone()))
} else {
- Some(GeneratedFunctionTarget::InEmptyItemList(impl_.assoc_item_list()?.syntax().clone()))
+ Some(GeneratedFunctionTarget::InEmptyItemList(assoc_item_list.syntax().clone()))
}
}
@@ -659,6 +1060,73 @@ fn module_is_descendant(module: &hir::Module, ans: &hir::Module, ctx: &AssistCon
false
}
+// This is never intended to be used as a generic graph strucuture. If there's ever another need of
+// graph algorithm, consider adding a library for that (and replace the following).
+/// Minimally implemented directed graph structure represented by adjacency list.
+struct Graph {
+ edges: Vec<Vec<usize>>,
+}
+
+impl Graph {
+ fn new(node_count: usize) -> Self {
+ Self { edges: vec![Vec::new(); node_count] }
+ }
+
+ fn add_edge(&mut self, from: usize, to: usize) {
+ self.edges[from].push(to);
+ }
+
+ fn edges_for(&self, node_idx: usize) -> &[usize] {
+ &self.edges[node_idx]
+ }
+
+ fn len(&self) -> usize {
+ self.edges.len()
+ }
+
+ fn compute_reachable_nodes(
+ &self,
+ starting_nodes: impl IntoIterator<Item = usize>,
+ ) -> Vec<bool> {
+ let mut visitor = Visitor::new(self);
+ for idx in starting_nodes {
+ visitor.mark_reachable(idx);
+ }
+ visitor.visited
+ }
+}
+
+struct Visitor<'g> {
+ graph: &'g Graph,
+ visited: Vec<bool>,
+ // Stack is held in this struct so we can reuse its buffer.
+ stack: Vec<usize>,
+}
+
+impl<'g> Visitor<'g> {
+ fn new(graph: &'g Graph) -> Self {
+ let visited = vec![false; graph.len()];
+ Self { graph, visited, stack: Vec::new() }
+ }
+
+ fn mark_reachable(&mut self, start_idx: usize) {
+ // non-recursive DFS
+ stdx::always!(self.stack.is_empty());
+
+ self.stack.push(start_idx);
+ while let Some(idx) = self.stack.pop() {
+ if !self.visited[idx] {
+ self.visited[idx] = true;
+ for &neighbor in self.graph.edges_for(idx) {
+ if !self.visited[neighbor] {
+ self.stack.push(neighbor);
+ }
+ }
+ }
+ }
+ }
+}
+
#[cfg(test)]
mod tests {
use crate::tests::{check_assist, check_assist_not_applicable};
@@ -1087,21 +1555,167 @@ fn bar(baz: Baz::Bof) {
}
#[test]
- fn add_function_with_generic_arg() {
- // FIXME: This is wrong, generated `bar` should include generic parameter.
+ fn generate_function_with_generic_param() {
+ check_assist(
+ generate_function,
+ r"
+fn foo<T, const N: usize>(t: [T; N]) { $0bar(t) }
+",
+ r"
+fn foo<T, const N: usize>(t: [T; N]) { bar(t) }
+
+fn bar<T, const N: usize>(t: [T; N]) {
+ ${0:todo!()}
+}
+",
+ )
+ }
+
+ #[test]
+ fn generate_function_with_parent_generic_param() {
+ check_assist(
+ generate_function,
+ r"
+struct S<T>(T);
+impl<T> S<T> {
+ fn foo<U>(t: T, u: U) { $0bar(t, u) }
+}
+",
+ r"
+struct S<T>(T);
+impl<T> S<T> {
+ fn foo<U>(t: T, u: U) { bar(t, u) }
+}
+
+fn bar<T, U>(t: T, u: U) {
+ ${0:todo!()}
+}
+",
+ )
+ }
+
+ #[test]
+ fn generic_param_in_receiver_type() {
+ // FIXME: Generic parameter `T` should be part of impl, not method.
+ check_assist(
+ generate_function,
+ r"
+struct S<T>(T);
+fn foo<T, U>(s: S<T>, u: U) { s.$0foo(u) }
+",
+ r"
+struct S<T>(T);
+impl S {
+ fn foo<T, U>(&self, u: U) {
+ ${0:todo!()}
+ }
+}
+fn foo<T, U>(s: S<T>, u: U) { s.foo(u) }
+",
+ )
+ }
+
+ #[test]
+ fn generic_param_in_return_type() {
+ check_assist(
+ generate_function,
+ r"
+fn foo<T, const N: usize>() -> [T; N] { $0bar() }
+",
+ r"
+fn foo<T, const N: usize>() -> [T; N] { bar() }
+
+fn bar<T, const N: usize>() -> [T; N] {
+ ${0:todo!()}
+}
+",
+ )
+ }
+
+ #[test]
+ fn generate_fn_with_bounds() {
+ // FIXME: where predicates should be on next lines.
+ check_assist(
+ generate_function,
+ r"
+trait A<T> {}
+struct S<T>(T);
+impl<T: A<i32>> S<T>
+where
+ T: A<i64>,
+{
+ fn foo<U>(t: T, u: U)
+ where
+ T: A<()>,
+ U: A<i32> + A<i64>,
+ {
+ $0bar(t, u)
+ }
+}
+",
+ r"
+trait A<T> {}
+struct S<T>(T);
+impl<T: A<i32>> S<T>
+where
+ T: A<i64>,
+{
+ fn foo<U>(t: T, u: U)
+ where
+ T: A<()>,
+ U: A<i32> + A<i64>,
+ {
+ bar(t, u)
+ }
+}
+
+fn bar<T: A<i32>, U>(t: T, u: U) where T: A<i64>, T: A<()>, U: A<i32> + A<i64> {
+ ${0:todo!()}
+}
+",
+ )
+ }
+
+ #[test]
+ fn include_transitive_param_dependency() {
+ // FIXME: where predicates should be on next lines.
check_assist(
generate_function,
r"
-fn foo<T>(t: T) {
- $0bar(t)
+trait A<T> { type Assoc; }
+trait B { type Item; }
+struct S<T>(T);
+impl<T, U, V: B, W> S<(T, U, V, W)>
+where
+ T: A<U, Assoc = V>,
+ S<V::Item>: A<U, Assoc = W>,
+{
+ fn foo<I>(t: T, u: U)
+ where
+ U: A<T, Assoc = I>,
+ {
+ $0bar(u)
+ }
}
",
r"
-fn foo<T>(t: T) {
- bar(t)
+trait A<T> { type Assoc; }
+trait B { type Item; }
+struct S<T>(T);
+impl<T, U, V: B, W> S<(T, U, V, W)>
+where
+ T: A<U, Assoc = V>,
+ S<V::Item>: A<U, Assoc = W>,
+{
+ fn foo<I>(t: T, u: U)
+ where
+ U: A<T, Assoc = I>,
+ {
+ bar(u)
+ }
}
-fn bar(t: T) {
+fn bar<T, U, V: B, W, I>(u: U) where T: A<U, Assoc = V>, S<V::Item>: A<U, Assoc = W>, U: A<T, Assoc = I> {
${0:todo!()}
}
",
@@ -1109,6 +1723,135 @@ fn bar(t: T) {
}
#[test]
+ fn irrelevant_bounds_are_filtered_out() {
+ check_assist(
+ generate_function,
+ r"
+trait A<T> {}
+struct S<T>(T);
+impl<T, U, V, W> S<(T, U, V, W)>
+where
+ T: A<U>,
+ V: A<W>,
+{
+ fn foo<I>(t: T, u: U)
+ where
+ U: A<T> + A<I>,
+ {
+ $0bar(u)
+ }
+}
+",
+ r"
+trait A<T> {}
+struct S<T>(T);
+impl<T, U, V, W> S<(T, U, V, W)>
+where
+ T: A<U>,
+ V: A<W>,
+{
+ fn foo<I>(t: T, u: U)
+ where
+ U: A<T> + A<I>,
+ {
+ bar(u)
+ }
+}
+
+fn bar<T, U, I>(u: U) where T: A<U>, U: A<T> + A<I> {
+ ${0:todo!()}
+}
+",
+ )
+ }
+
+ #[test]
+ fn params_in_trait_arg_are_not_dependency() {
+ // Even though `bar` depends on `U` and `I`, we don't have to copy these bounds:
+ // `T: A<I>` and `T: A<U>`.
+ check_assist(
+ generate_function,
+ r"
+trait A<T> {}
+struct S<T>(T);
+impl<T, U> S<(T, U)>
+where
+ T: A<U>,
+{
+ fn foo<I>(t: T, u: U)
+ where
+ T: A<I>,
+ U: A<I>,
+ {
+ $0bar(u)
+ }
+}
+",
+ r"
+trait A<T> {}
+struct S<T>(T);
+impl<T, U> S<(T, U)>
+where
+ T: A<U>,
+{
+ fn foo<I>(t: T, u: U)
+ where
+ T: A<I>,
+ U: A<I>,
+ {
+ bar(u)
+ }
+}
+
+fn bar<U, I>(u: U) where U: A<I> {
+ ${0:todo!()}
+}
+",
+ )
+ }
+
+ #[test]
+ fn dont_copy_bounds_already_in_scope() {
+ check_assist(
+ generate_function,
+ r"
+trait A<T> {}
+struct S<T>(T);
+impl<T: A<i32>> S<T>
+where
+ T: A<usize>,
+{
+ fn foo<U: A<()>>(t: T, u: U)
+ where
+ T: A<S<i32>>,
+ {
+ Self::$0bar(t, u);
+ }
+}
+",
+ r"
+trait A<T> {}
+struct S<T>(T);
+impl<T: A<i32>> S<T>
+where
+ T: A<usize>,
+{
+ fn foo<U: A<()>>(t: T, u: U)
+ where
+ T: A<S<i32>>,
+ {
+ Self::bar(t, u);
+ }
+
+ fn bar<U: A<()>>(t: T, u: U) ${0:-> _} where T: A<S<i32>> {
+ todo!()
+ }
+}
+",
+ )
+ }
+
+ #[test]
fn add_function_with_fn_arg() {
// FIXME: The argument in `bar` is wrong.
check_assist(
@@ -1290,6 +2033,50 @@ fn baz(foo: foo::Foo) {
}
#[test]
+ fn qualified_path_in_generic_bounds_uses_correct_scope() {
+ check_assist(
+ generate_function,
+ r"
+mod a {
+ pub trait A {};
+}
+pub mod b {
+ pub struct S<T>(T);
+}
+struct S<T>(T);
+impl<T> S<T>
+where
+ T: a::A,
+{
+ fn foo<U: a::A>(t: b::S<T>, u: S<U>) {
+ a::$0bar(t, u);
+ }
+}
+",
+ r"
+mod a {
+ pub trait A {}
+
+ pub(crate) fn bar<T, U: self::A>(t: crate::b::S<T>, u: crate::S<U>) ${0:-> _} where T: self::A {
+ todo!()
+ };
+}
+pub mod b {
+ pub struct S<T>(T);
+}
+struct S<T>(T);
+impl<T> S<T>
+where
+ T: a::A,
+{
+ fn foo<U: a::A>(t: b::S<T>, u: S<U>) {
+ a::bar(t, u);
+ }
+}
+",
+ )
+ }
+ #[test]
fn add_function_in_module_containing_other_items() {
check_assist(
generate_function,
@@ -1607,6 +2394,26 @@ fn foo() {S::bar();}
}
#[test]
+ fn create_generic_static_method() {
+ check_assist(
+ generate_function,
+ r"
+struct S;
+fn foo<T, const N: usize>(t: [T; N]) { S::bar$0(t); }
+",
+ r"
+struct S;
+impl S {
+ fn bar<T, const N: usize>(t: [T; N]) ${0:-> _} {
+ todo!()
+ }
+}
+fn foo<T, const N: usize>(t: [T; N]) { S::bar(t); }
+",
+ )
+ }
+
+ #[test]
fn create_static_method_within_an_impl() {
check_assist(
generate_function,
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_getter.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_getter.rs
index 15641b448..4595cfe29 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_getter.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_getter.rs
@@ -180,7 +180,9 @@ pub(crate) fn generate_getter_impl(
// Insert `$0` only for last getter we generate
if i == record_fields_count - 1 {
- getter_buf = getter_buf.replacen("fn ", "fn $0", 1);
+ if ctx.config.snippet_cap.is_some() {
+ getter_buf = getter_buf.replacen("fn ", "fn $0", 1);
+ }
}
// For first element we do not merge with '\n', as
@@ -330,7 +332,7 @@ fn parse_record_field(record_field: ast::RecordField, mutable: bool) -> Option<R
#[cfg(test)]
mod tests {
- use crate::tests::{check_assist, check_assist_not_applicable};
+ use crate::tests::{check_assist, check_assist_no_snippet_cap, check_assist_not_applicable};
use super::*;
@@ -378,6 +380,49 @@ impl Context {
}
#[test]
+ fn test_generate_getter_from_field_no_snippet_cap() {
+ check_assist_no_snippet_cap(
+ generate_getter,
+ r#"
+struct Context {
+ dat$0a: Data,
+}
+"#,
+ r#"
+struct Context {
+ data: Data,
+}
+
+impl Context {
+ fn data(&self) -> &Data {
+ &self.data
+ }
+}
+"#,
+ );
+
+ check_assist_no_snippet_cap(
+ generate_getter_mut,
+ r#"
+struct Context {
+ dat$0a: Data,
+}
+"#,
+ r#"
+struct Context {
+ data: Data,
+}
+
+impl Context {
+ fn data_mut(&mut self) -> &mut Data {
+ &mut self.data
+ }
+}
+"#,
+ );
+ }
+
+ #[test]
fn test_generate_getter_already_implemented() {
check_assist_not_applicable(
generate_getter,
@@ -434,6 +479,29 @@ impl Context {
}
#[test]
+ fn test_generate_getter_from_field_with_visibility_marker_no_snippet_cap() {
+ check_assist_no_snippet_cap(
+ generate_getter,
+ r#"
+pub(crate) struct Context {
+ dat$0a: Data,
+}
+"#,
+ r#"
+pub(crate) struct Context {
+ data: Data,
+}
+
+impl Context {
+ pub(crate) fn data(&self) -> &Data {
+ &self.data
+ }
+}
+"#,
+ );
+ }
+
+ #[test]
fn test_multiple_generate_getter() {
check_assist(
generate_getter,
@@ -469,6 +537,41 @@ impl Context {
}
#[test]
+ fn test_multiple_generate_getter_no_snippet_cap() {
+ check_assist_no_snippet_cap(
+ generate_getter,
+ r#"
+struct Context {
+ data: Data,
+ cou$0nt: usize,
+}
+
+impl Context {
+ fn data(&self) -> &Data {
+ &self.data
+ }
+}
+"#,
+ r#"
+struct Context {
+ data: Data,
+ count: usize,
+}
+
+impl Context {
+ fn data(&self) -> &Data {
+ &self.data
+ }
+
+ fn count(&self) -> &usize {
+ &self.count
+ }
+}
+"#,
+ );
+ }
+
+ #[test]
fn test_not_a_special_case() {
cov_mark::check_count!(convert_reference_type, 0);
// Fake string which doesn't implement AsRef<str>
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/inline_macro.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/inline_macro.rs
index 9d03f03d2..3fc552306 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/inline_macro.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/inline_macro.rs
@@ -1,3 +1,4 @@
+use ide_db::syntax_helpers::insert_whitespace_into_node::insert_ws_into;
use syntax::ast::{self, AstNode};
use crate::{AssistContext, AssistId, AssistKind, Assists};
@@ -35,7 +36,7 @@ use crate::{AssistContext, AssistId, AssistKind, Assists};
// ```
pub(crate) fn inline_macro(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> {
let unexpanded = ctx.find_node_at_offset::<ast::MacroCall>()?;
- let expanded = ctx.sema.expand(&unexpanded)?.clone_for_update();
+ let expanded = insert_ws_into(ctx.sema.expand(&unexpanded)?.clone_for_update());
let text_range = unexpanded.syntax().text_range();
@@ -230,4 +231,27 @@ fn f() { let result = foo$0(); }
"#,
);
}
+
+ #[test]
+ fn inline_macro_with_whitespace() {
+ check_assist(
+ inline_macro,
+ r#"
+macro_rules! whitespace {
+ () => {
+ if true {}
+ };
+}
+fn f() { whitespace$0!(); }
+"#,
+ r#"
+macro_rules! whitespace {
+ () => {
+ if true {}
+ };
+}
+fn f() { if true{}; }
+"#,
+ )
+ }
}
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/merge_imports.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/merge_imports.rs
index 2bdbec93b..d7ddc5f23 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/merge_imports.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/merge_imports.rs
@@ -92,7 +92,7 @@ trait Merge: AstNode + Clone {
fn try_merge_from(self, items: &mut dyn Iterator<Item = Self>) -> Option<Vec<Edit>> {
let mut edits = Vec::new();
let mut merged = self.clone();
- while let Some(item) = items.next() {
+ for item in items {
merged = merged.try_merge(&item)?;
edits.push(Edit::Remove(item.into_either()));
}
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/move_const_to_impl.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/move_const_to_impl.rs
index 0e3a1e652..d848fce4b 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/move_const_to_impl.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/move_const_to_impl.rs
@@ -5,10 +5,7 @@ use syntax::{
SyntaxKind,
};
-use crate::{
- assist_context::{AssistContext, Assists},
- utils,
-};
+use crate::assist_context::{AssistContext, Assists};
// NOTE: Code may break if the self type implements a trait that has associated const with the same
// name, but it's pretty expensive to check that (`hir::Impl::all_for_type()`) and we assume that's
@@ -130,9 +127,7 @@ pub(crate) fn move_const_to_impl(acc: &mut Assists, ctx: &AssistContext<'_>) ->
let const_ = const_.clone_for_update();
const_.reindent_to(indent);
- let mut const_text = format!("\n{indent}{const_}{fixup}");
- utils::escape_non_snippet(&mut const_text);
- builder.insert(insert_offset, const_text);
+ builder.insert(insert_offset, format!("\n{indent}{const_}{fixup}"));
},
)
}
@@ -443,39 +438,4 @@ impl S {
"#,
);
}
-
- #[test]
- fn moved_const_body_is_escaped() {
- // Note that the last argument is what *lsp clients would see* rather than
- // what users would see. Unescaping happens thereafter.
- check_assist(
- move_const_to_impl,
- r#"
-struct S;
-impl S {
- fn f() -> usize {
- /// doc comment
- /// \\
- /// ${snippet}
- const C$0: &str = "\ and $1";
-
- C.len()
- }
-}
-"#,
- r#"
-struct S;
-impl S {
- /// doc comment
- /// \\\\
- /// \${snippet}
- const C: &str = "\\ and \$1";
-
- fn f() -> usize {
- Self::C.len()
- }
-}
-"#,
- )
- }
}
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/raw_string.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/raw_string.rs
index c9bc25b27..01420430b 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/raw_string.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/raw_string.rs
@@ -2,7 +2,7 @@ use std::borrow::Cow;
use syntax::{ast, ast::IsString, AstToken, TextRange, TextSize};
-use crate::{AssistContext, AssistId, AssistKind, Assists};
+use crate::{utils::required_hashes, AssistContext, AssistId, AssistKind, Assists};
// Assist: make_raw_string
//
@@ -155,16 +155,6 @@ pub(crate) fn remove_hash(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<
})
}
-fn required_hashes(s: &str) -> usize {
- let mut res = 0usize;
- for idx in s.match_indices('"').map(|(i, _)| i) {
- let (_, sub) = s.split_at(idx + 1);
- let n_hashes = sub.chars().take_while(|c| *c == '#').count();
- res = res.max(n_hashes + 1)
- }
- res
-}
-
#[cfg(test)]
mod tests {
use crate::tests::{check_assist, check_assist_not_applicable, check_assist_target};
@@ -172,17 +162,6 @@ mod tests {
use super::*;
#[test]
- fn test_required_hashes() {
- assert_eq!(0, required_hashes("abc"));
- assert_eq!(0, required_hashes("###"));
- assert_eq!(1, required_hashes("\""));
- assert_eq!(2, required_hashes("\"#abc"));
- assert_eq!(0, required_hashes("#abc"));
- assert_eq!(3, required_hashes("#ab\"##c"));
- assert_eq!(5, required_hashes("#ab\"##\"####c"));
- }
-
- #[test]
fn make_raw_string_target() {
check_assist_target(
make_raw_string,
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/reorder_fields.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/reorder_fields.rs
index a899c7a64..58dcaf9a2 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/reorder_fields.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/reorder_fields.rs
@@ -20,10 +20,7 @@ use crate::{AssistContext, AssistId, AssistKind, Assists};
// const test: Foo = Foo {foo: 1, bar: 0}
// ```
pub(crate) fn reorder_fields(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> {
- let record = ctx
- .find_node_at_offset::<ast::RecordExpr>()
- .map(Either::Left)
- .or_else(|| ctx.find_node_at_offset::<ast::RecordPat>().map(Either::Right))?;
+ let record = ctx.find_node_at_offset::<Either<ast::RecordExpr, ast::RecordPat>>()?;
let path = record.as_ref().either(|it| it.path(), |it| it.path())?;
let ranks = compute_fields_ranks(&path, ctx)?;
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_arith_op.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_arith_op.rs
index f1ca35caf..4b20b35c4 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_arith_op.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_arith_op.rs
@@ -81,7 +81,7 @@ fn replace_arith(acc: &mut Assists, ctx: &AssistContext<'_>, kind: ArithKind) ->
let range = TextRange::new(start, end);
acc.add_group(
- &GroupLabel("replace_arith".into()),
+ &GroupLabel("Replace arithmetic...".into()),
kind.assist_id(),
kind.label(),
range,
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_derive_with_manual_impl.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_derive_with_manual_impl.rs
index a6693d7d7..4cfae0c72 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_derive_with_manual_impl.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_derive_with_manual_impl.rs
@@ -214,7 +214,7 @@ fn impl_def_from_trait(
// Generate a default `impl` function body for the derived trait.
if let ast::AssocItem::Fn(ref func) = first_assoc_item {
- let _ = gen_trait_fn_body(func, trait_path, adt);
+ let _ = gen_trait_fn_body(func, trait_path, adt, None);
};
Some((impl_def, first_assoc_item))
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_if_let_with_match.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_if_let_with_match.rs
index 484c27387..457559656 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_if_let_with_match.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_if_let_with_match.rs
@@ -13,7 +13,7 @@ use syntax::{
edit::{AstNodeEdit, IndentLevel},
make, HasName,
},
- AstNode, TextRange,
+ AstNode, TextRange, T,
};
use crate::{
@@ -96,8 +96,9 @@ pub(crate) fn replace_if_let_with_match(acc: &mut Assists, ctx: &AssistContext<'
cond_bodies.push((cond, body));
}
- if !pat_seen {
- // Don't offer turning an if (chain) without patterns into a match
+ if !pat_seen && cond_bodies.len() != 1 {
+ // Don't offer turning an if (chain) without patterns into a match,
+ // unless its a simple `if cond { .. } (else { .. })`
return None;
}
@@ -114,6 +115,11 @@ pub(crate) fn replace_if_let_with_match(acc: &mut Assists, ctx: &AssistContext<'
Either::Left(pat) => {
make::match_arm(iter::once(pat), None, unwrap_trivial_block(body))
}
+ Either::Right(_) if !pat_seen => make::match_arm(
+ iter::once(make::literal_pat("true").into()),
+ None,
+ unwrap_trivial_block(body),
+ ),
Either::Right(expr) => make::match_arm(
iter::once(make::wildcard_pat().into()),
Some(expr),
@@ -144,31 +150,36 @@ fn make_else_arm(
else_block: Option<ast::BlockExpr>,
conditionals: &[(Either<ast::Pat, ast::Expr>, ast::BlockExpr)],
) -> ast::MatchArm {
- if let Some(else_block) = else_block {
- let pattern = if let [(Either::Left(pat), _)] = conditionals {
- ctx.sema
+ let (pattern, expr) = if let Some(else_block) = else_block {
+ let pattern = match conditionals {
+ [(Either::Right(_), _)] => make::literal_pat("false").into(),
+ [(Either::Left(pat), _)] => match ctx
+ .sema
.type_of_pat(pat)
.and_then(|ty| TryEnum::from_ty(&ctx.sema, &ty.adjusted()))
- .zip(Some(pat))
- } else {
- None
- };
- let pattern = match pattern {
- Some((it, pat)) => {
- if does_pat_match_variant(pat, &it.sad_pattern()) {
- it.happy_pattern_wildcard()
- } else if does_nested_pattern(pat) {
- make::wildcard_pat().into()
- } else {
- it.sad_pattern()
+ {
+ Some(it) => {
+ if does_pat_match_variant(pat, &it.sad_pattern()) {
+ it.happy_pattern_wildcard()
+ } else if does_nested_pattern(pat) {
+ make::wildcard_pat().into()
+ } else {
+ it.sad_pattern()
+ }
}
- }
- None => make::wildcard_pat().into(),
+ None => make::wildcard_pat().into(),
+ },
+ _ => make::wildcard_pat().into(),
};
- make::match_arm(iter::once(pattern), None, unwrap_trivial_block(else_block))
+ (pattern, unwrap_trivial_block(else_block))
} else {
- make::match_arm(iter::once(make::wildcard_pat().into()), None, make::expr_unit())
- }
+ let pattern = match conditionals {
+ [(Either::Right(_), _)] => make::literal_pat("false").into(),
+ _ => make::wildcard_pat().into(),
+ };
+ (pattern, make::expr_unit())
+ };
+ make::match_arm(iter::once(pattern), None, expr)
}
// Assist: replace_match_with_if_let
@@ -231,7 +242,19 @@ pub(crate) fn replace_match_with_if_let(acc: &mut Assists, ctx: &AssistContext<'
}
}
- let condition = make::expr_let(if_let_pat, scrutinee);
+ let condition = match if_let_pat {
+ ast::Pat::LiteralPat(p)
+ if p.literal().map_or(false, |it| it.token().kind() == T![true]) =>
+ {
+ scrutinee
+ }
+ ast::Pat::LiteralPat(p)
+ if p.literal().map_or(false, |it| it.token().kind() == T![false]) =>
+ {
+ make::expr_prefix(T![!], scrutinee)
+ }
+ _ => make::expr_let(if_let_pat, scrutinee).into(),
+ };
let then_block = make_block_expr(then_expr.reset_indent());
let else_expr = if is_empty_expr(&else_expr) { None } else { Some(else_expr) };
let if_let_expr = make::expr_if(
@@ -328,6 +351,58 @@ fn main() {
}
#[test]
+ fn test_if_with_match_no_else() {
+ check_assist(
+ replace_if_let_with_match,
+ r#"
+pub fn foo(foo: bool) {
+ if foo$0 {
+ self.foo();
+ }
+}
+"#,
+ r#"
+pub fn foo(foo: bool) {
+ match foo {
+ true => {
+ self.foo();
+ }
+ false => (),
+ }
+}
+"#,
+ )
+ }
+
+ #[test]
+ fn test_if_with_match_with_else() {
+ check_assist(
+ replace_if_let_with_match,
+ r#"
+pub fn foo(foo: bool) {
+ if foo$0 {
+ self.foo();
+ } else {
+ self.bar();
+ }
+}
+"#,
+ r#"
+pub fn foo(foo: bool) {
+ match foo {
+ true => {
+ self.foo();
+ }
+ false => {
+ self.bar();
+ }
+ }
+}
+"#,
+ )
+ }
+
+ #[test]
fn test_if_let_with_match_no_else() {
check_assist(
replace_if_let_with_match,
@@ -996,4 +1071,64 @@ fn main() {
"#,
)
}
+
+ #[test]
+ fn test_replace_match_with_if_bool() {
+ check_assist(
+ replace_match_with_if_let,
+ r#"
+fn main() {
+ match$0 b {
+ true => (),
+ _ => code(),
+ }
+}
+"#,
+ r#"
+fn main() {
+ if b {
+ ()
+ } else {
+ code()
+ }
+}
+"#,
+ );
+ check_assist(
+ replace_match_with_if_let,
+ r#"
+fn main() {
+ match$0 b {
+ false => code(),
+ true => (),
+ }
+}
+"#,
+ r#"
+fn main() {
+ if !b {
+ code()
+ }
+}
+"#,
+ );
+ check_assist(
+ replace_match_with_if_let,
+ r#"
+fn main() {
+ match$0 b {
+ false => (),
+ true => code(),
+ }
+}
+"#,
+ r#"
+fn main() {
+ if b {
+ code()
+ }
+}
+"#,
+ )
+ }
}
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/unmerge_match_arm.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/unmerge_match_arm.rs
index 9565f0ee6..db789cfa3 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/unmerge_match_arm.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/unmerge_match_arm.rs
@@ -86,8 +86,7 @@ pub(crate) fn unmerge_match_arm(acc: &mut Assists, ctx: &AssistContext<'_>) -> O
it.prev_sibling_or_token()
})
.map(|it| it.kind())
- .skip_while(|it| it.is_trivia())
- .next()
+ .find(|it| !it.is_trivia())
== Some(T![,]);
let has_arms_after = neighbor(&match_arm, Direction::Next).is_some();
if !has_comma_after && !has_arms_after {
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/unwrap_block.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/unwrap_block.rs
index 53cdac03a..33b19a354 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/unwrap_block.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/unwrap_block.rs
@@ -2,6 +2,7 @@ use syntax::{
ast::{
self,
edit::{AstNodeEdit, IndentLevel},
+ make,
},
AstNode, SyntaxKind, TextRange, T,
};
@@ -37,61 +38,89 @@ pub(crate) fn unwrap_block(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option
parent = parent.ancestors().find(|it| ast::MatchExpr::can_cast(it.kind()))?
}
- if matches!(parent.kind(), SyntaxKind::STMT_LIST | SyntaxKind::EXPR_STMT | SyntaxKind::LET_STMT)
- {
- return acc.add(assist_id, assist_label, target, |builder| {
+ let kind = parent.kind();
+ if matches!(kind, SyntaxKind::STMT_LIST | SyntaxKind::EXPR_STMT) {
+ acc.add(assist_id, assist_label, target, |builder| {
builder.replace(block.syntax().text_range(), update_expr_string(block.to_string()));
- });
- }
-
- let parent = ast::Expr::cast(parent)?;
-
- match parent.clone() {
- ast::Expr::ForExpr(_) | ast::Expr::WhileExpr(_) | ast::Expr::LoopExpr(_) => (),
- ast::Expr::MatchExpr(_) => block = block.dedent(IndentLevel(1)),
- ast::Expr::IfExpr(if_expr) => {
- let then_branch = if_expr.then_branch()?;
- if then_branch == block {
- if let Some(ancestor) = if_expr.syntax().parent().and_then(ast::IfExpr::cast) {
- // For `else if` blocks
- let ancestor_then_branch = ancestor.then_branch()?;
-
+ })
+ } else if matches!(kind, SyntaxKind::LET_STMT) {
+ let parent = ast::LetStmt::cast(parent)?;
+ let pattern = ast::Pat::cast(parent.syntax().first_child()?)?;
+ let ty = parent.ty();
+ let list = block.stmt_list()?;
+ let replaced = match list.syntax().last_child() {
+ Some(last) => {
+ let stmts: Vec<ast::Stmt> = list.statements().collect();
+ let initializer = ast::Expr::cast(last.clone())?;
+ let let_stmt = make::let_stmt(pattern, ty, Some(initializer));
+ if stmts.len() > 0 {
+ let block = make::block_expr(stmts, None);
+ format!(
+ "{}\n {}",
+ update_expr_string(block.to_string()),
+ let_stmt.to_string()
+ )
+ } else {
+ let_stmt.to_string()
+ }
+ }
+ None => {
+ let empty_tuple = make::expr_tuple([]);
+ make::let_stmt(pattern, ty, Some(empty_tuple)).to_string()
+ }
+ };
+ acc.add(assist_id, assist_label, target, |builder| {
+ builder.replace(parent.syntax().text_range(), replaced);
+ })
+ } else {
+ let parent = ast::Expr::cast(parent)?;
+ match parent.clone() {
+ ast::Expr::ForExpr(_) | ast::Expr::WhileExpr(_) | ast::Expr::LoopExpr(_) => (),
+ ast::Expr::MatchExpr(_) => block = block.dedent(IndentLevel(1)),
+ ast::Expr::IfExpr(if_expr) => {
+ let then_branch = if_expr.then_branch()?;
+ if then_branch == block {
+ if let Some(ancestor) = if_expr.syntax().parent().and_then(ast::IfExpr::cast) {
+ // For `else if` blocks
+ let ancestor_then_branch = ancestor.then_branch()?;
+
+ return acc.add(assist_id, assist_label, target, |edit| {
+ let range_to_del_else_if = TextRange::new(
+ ancestor_then_branch.syntax().text_range().end(),
+ l_curly_token.text_range().start(),
+ );
+ let range_to_del_rest = TextRange::new(
+ then_branch.syntax().text_range().end(),
+ if_expr.syntax().text_range().end(),
+ );
+
+ edit.delete(range_to_del_rest);
+ edit.delete(range_to_del_else_if);
+ edit.replace(
+ target,
+ update_expr_string_without_newline(then_branch.to_string()),
+ );
+ });
+ }
+ } else {
return acc.add(assist_id, assist_label, target, |edit| {
- let range_to_del_else_if = TextRange::new(
- ancestor_then_branch.syntax().text_range().end(),
- l_curly_token.text_range().start(),
- );
- let range_to_del_rest = TextRange::new(
+ let range_to_del = TextRange::new(
then_branch.syntax().text_range().end(),
- if_expr.syntax().text_range().end(),
+ l_curly_token.text_range().start(),
);
- edit.delete(range_to_del_rest);
- edit.delete(range_to_del_else_if);
- edit.replace(
- target,
- update_expr_string_without_newline(then_branch.to_string()),
- );
+ edit.delete(range_to_del);
+ edit.replace(target, update_expr_string_without_newline(block.to_string()));
});
}
- } else {
- return acc.add(assist_id, assist_label, target, |edit| {
- let range_to_del = TextRange::new(
- then_branch.syntax().text_range().end(),
- l_curly_token.text_range().start(),
- );
-
- edit.delete(range_to_del);
- edit.replace(target, update_expr_string_without_newline(block.to_string()));
- });
}
- }
- _ => return None,
- };
+ _ => return None,
+ };
- acc.add(assist_id, assist_label, target, |builder| {
- builder.replace(parent.syntax().text_range(), update_expr_string(block.to_string()));
- })
+ acc.add(assist_id, assist_label, target, |builder| {
+ builder.replace(parent.syntax().text_range(), update_expr_string(block.to_string()));
+ })
+ }
}
fn update_expr_string(expr_string: String) -> String {
@@ -725,6 +754,19 @@ fn main() -> i32 {
unwrap_block,
r#"
fn main() {
+ let x = {$0};
+}
+"#,
+ r#"
+fn main() {
+ let x = ();
+}
+"#,
+ );
+ check_assist(
+ unwrap_block,
+ r#"
+fn main() {
let x = {$0
bar
};
@@ -736,6 +778,34 @@ fn main() {
}
"#,
);
+ check_assist(
+ unwrap_block,
+ r#"
+fn main() -> i32 {
+ let _ = {$01; 2};
+}
+"#,
+ r#"
+fn main() -> i32 {
+ 1;
+ let _ = 2;
+}
+"#,
+ );
+ check_assist(
+ unwrap_block,
+ r#"
+fn main() -> i32 {
+ let mut a = {$01; 2};
+}
+"#,
+ r#"
+fn main() -> i32 {
+ 1;
+ let mut a = 2;
+}
+"#,
+ );
}
#[test]
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/lib.rs b/src/tools/rust-analyzer/crates/ide-assists/src/lib.rs
index 7813c9f9c..276cf5f5d 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/lib.rs
@@ -106,6 +106,7 @@ mod handlers {
pub(crate) type Handler = fn(&mut Assists, &AssistContext<'_>) -> Option<()>;
+ mod add_braces;
mod add_explicit_type;
mod add_label_to_loop;
mod add_lifetime_to_type;
@@ -126,6 +127,7 @@ mod handlers {
mod convert_to_guarded_return;
mod convert_two_arm_bool_match_to_matches_macro;
mod convert_while_to_loop;
+ mod desugar_doc_comment;
mod destructure_tuple_binding;
mod expand_glob_import;
mod extract_expressions_from_format_string;
@@ -208,6 +210,7 @@ mod handlers {
pub(crate) fn all() -> &'static [Handler] {
&[
// These are alphabetic for the foolish consistency
+ add_braces::add_braces,
add_explicit_type::add_explicit_type,
add_label_to_loop::add_label_to_loop,
add_missing_match_arms::add_missing_match_arms,
@@ -231,6 +234,7 @@ mod handlers {
convert_tuple_struct_to_named_struct::convert_tuple_struct_to_named_struct,
convert_two_arm_bool_match_to_matches_macro::convert_two_arm_bool_match_to_matches_macro,
convert_while_to_loop::convert_while_to_loop,
+ desugar_doc_comment::desugar_doc_comment,
destructure_tuple_binding::destructure_tuple_binding,
expand_glob_import::expand_glob_import,
extract_expressions_from_format_string::extract_expressions_from_format_string,
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/tests.rs b/src/tools/rust-analyzer/crates/ide-assists/src/tests.rs
index fca268a1f..94be99fd7 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/tests.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/tests.rs
@@ -33,6 +33,20 @@ pub(crate) const TEST_CONFIG: AssistConfig = AssistConfig {
assist_emit_must_use: false,
};
+pub(crate) const TEST_CONFIG_NO_SNIPPET_CAP: AssistConfig = AssistConfig {
+ snippet_cap: None,
+ allowed: None,
+ insert_use: InsertUseConfig {
+ granularity: ImportGranularity::Crate,
+ prefix_kind: hir::PrefixKind::Plain,
+ enforce_granularity: true,
+ group: true,
+ skip_glob_imports: true,
+ },
+ prefer_no_std: false,
+ assist_emit_must_use: false,
+};
+
pub(crate) fn with_single_file(text: &str) -> (RootDatabase, FileId) {
RootDatabase::with_single_file(text)
}
@@ -43,6 +57,22 @@ pub(crate) fn check_assist(assist: Handler, ra_fixture_before: &str, ra_fixture_
check(assist, ra_fixture_before, ExpectedResult::After(&ra_fixture_after), None);
}
+#[track_caller]
+pub(crate) fn check_assist_no_snippet_cap(
+ assist: Handler,
+ ra_fixture_before: &str,
+ ra_fixture_after: &str,
+) {
+ let ra_fixture_after = trim_indent(ra_fixture_after);
+ check_with_config(
+ TEST_CONFIG_NO_SNIPPET_CAP,
+ assist,
+ ra_fixture_before,
+ ExpectedResult::After(&ra_fixture_after),
+ None,
+ );
+}
+
// There is no way to choose what assist within a group you want to test against,
// so this is here to allow you choose.
pub(crate) fn check_assist_by_label(
@@ -119,6 +149,17 @@ enum ExpectedResult<'a> {
#[track_caller]
fn check(handler: Handler, before: &str, expected: ExpectedResult<'_>, assist_label: Option<&str>) {
+ check_with_config(TEST_CONFIG, handler, before, expected, assist_label);
+}
+
+#[track_caller]
+fn check_with_config(
+ config: AssistConfig,
+ handler: Handler,
+ before: &str,
+ expected: ExpectedResult<'_>,
+ assist_label: Option<&str>,
+) {
let (mut db, file_with_caret_id, range_or_offset) = RootDatabase::with_range_or_offset(before);
db.set_enable_proc_attr_macros(true);
let text_without_caret = db.file_text(file_with_caret_id).to_string();
@@ -126,7 +167,6 @@ fn check(handler: Handler, before: &str, expected: ExpectedResult<'_>, assist_la
let frange = FileRange { file_id: file_with_caret_id, range: range_or_offset.into() };
let sema = Semantics::new(&db);
- let config = TEST_CONFIG;
let ctx = AssistContext::new(sema, &config, frange);
let resolve = match expected {
ExpectedResult::Unresolved => AssistResolveStrategy::None,
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/tests/generated.rs b/src/tools/rust-analyzer/crates/ide-assists/src/tests/generated.rs
index 006ae4b30..8a25e1f64 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/tests/generated.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/tests/generated.rs
@@ -3,6 +3,31 @@
use super::check_doc_test;
#[test]
+fn doctest_add_braces() {
+ check_doc_test(
+ "add_braces",
+ r#####"
+fn foo(n: i32) -> i32 {
+ match n {
+ 1 =>$0 n + 1,
+ _ => 0
+ }
+}
+"#####,
+ r#####"
+fn foo(n: i32) -> i32 {
+ match n {
+ 1 => {
+ n + 1
+ },
+ _ => 0
+ }
+}
+"#####,
+ )
+}
+
+#[test]
fn doctest_add_explicit_type() {
check_doc_test(
"add_explicit_type",
@@ -598,6 +623,21 @@ fn main() {
}
#[test]
+fn doctest_desugar_doc_comment() {
+ check_doc_test(
+ "desugar_doc_comment",
+ r#####"
+/// Multi-line$0
+/// comment
+"#####,
+ r#####"
+#[doc = r"Multi-line
+comment"]
+"#####,
+ )
+}
+
+#[test]
fn doctest_expand_glob_import() {
check_doc_test(
"expand_glob_import",
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/utils.rs b/src/tools/rust-analyzer/crates/ide-assists/src/utils.rs
index 7add66064..f323ebcf7 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/utils.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/utils.rs
@@ -208,23 +208,6 @@ pub(crate) fn render_snippet(_cap: SnippetCap, node: &SyntaxNode, cursor: Cursor
}
}
-/// Escapes text that should be rendered as-is, typically those that we're copy-pasting what the
-/// users wrote.
-///
-/// This function should only be used when the text doesn't contain snippet **AND** the text
-/// wouldn't be included in a snippet.
-pub(crate) fn escape_non_snippet(text: &mut String) {
- // While we *can* escape `}`, we don't really have to in this specific case. We only need to
- // escape it inside `${}` to disambiguate it from the ending token of the syntax, but after we
- // escape every occurrence of `$`, we wouldn't have `${}` in the first place.
- //
- // This will break if the text contains snippet or it will be included in a snippet (hence doc
- // comment). Compare `fn escape(buf)` in `render_snippet()` above, where the escaped text is
- // included in a snippet.
- stdx::replace(text, '\\', r"\\");
- stdx::replace(text, '$', r"\$");
-}
-
pub(crate) fn vis_offset(node: &SyntaxNode) -> TextSize {
node.children_with_tokens()
.find(|it| !matches!(it.kind(), WHITESPACE | COMMENT | ATTR))
@@ -758,3 +741,24 @@ pub(crate) fn convert_param_list_to_arg_list(list: ast::ParamList) -> ast::ArgLi
}
make::arg_list(args)
}
+
+/// Calculate the number of hashes required for a raw string containing `s`
+pub(crate) fn required_hashes(s: &str) -> usize {
+ let mut res = 0usize;
+ for idx in s.match_indices('"').map(|(i, _)| i) {
+ let (_, sub) = s.split_at(idx + 1);
+ let n_hashes = sub.chars().take_while(|c| *c == '#').count();
+ res = res.max(n_hashes + 1)
+ }
+ res
+}
+#[test]
+fn test_required_hashes() {
+ assert_eq!(0, required_hashes("abc"));
+ assert_eq!(0, required_hashes("###"));
+ assert_eq!(1, required_hashes("\""));
+ assert_eq!(2, required_hashes("\"#abc"));
+ assert_eq!(0, required_hashes("#abc"));
+ assert_eq!(3, required_hashes("#ab\"##c"));
+ assert_eq!(5, required_hashes("#ab\"##\"####c"));
+}
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/utils/gen_trait_fn_body.rs b/src/tools/rust-analyzer/crates/ide-assists/src/utils/gen_trait_fn_body.rs
index d4abb5125..808b23405 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/utils/gen_trait_fn_body.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/utils/gen_trait_fn_body.rs
@@ -1,5 +1,6 @@
//! This module contains functions to generate default trait impl function bodies where possible.
+use hir::TraitRef;
use syntax::{
ast::{self, edit::AstNodeEdit, make, AstNode, BinaryOp, CmpOp, HasName, LogicOp},
ted,
@@ -7,6 +8,8 @@ use syntax::{
/// Generate custom trait bodies without default implementation where possible.
///
+/// If `func` is defined within an existing impl block, pass [`TraitRef`]. Otherwise pass `None`.
+///
/// Returns `Option` so that we can use `?` rather than `if let Some`. Returning
/// `None` means that generating a custom trait body failed, and the body will remain
/// as `todo!` instead.
@@ -14,14 +17,15 @@ pub(crate) fn gen_trait_fn_body(
func: &ast::Fn,
trait_path: &ast::Path,
adt: &ast::Adt,
+ trait_ref: Option<TraitRef>,
) -> Option<()> {
match trait_path.segment()?.name_ref()?.text().as_str() {
"Clone" => gen_clone_impl(adt, func),
"Debug" => gen_debug_impl(adt, func),
"Default" => gen_default_impl(adt, func),
"Hash" => gen_hash_impl(adt, func),
- "PartialEq" => gen_partial_eq(adt, func),
- "PartialOrd" => gen_partial_ord(adt, func),
+ "PartialEq" => gen_partial_eq(adt, func, trait_ref),
+ "PartialOrd" => gen_partial_ord(adt, func, trait_ref),
_ => None,
}
}
@@ -395,7 +399,7 @@ fn gen_hash_impl(adt: &ast::Adt, func: &ast::Fn) -> Option<()> {
}
/// Generate a `PartialEq` impl based on the fields and members of the target type.
-fn gen_partial_eq(adt: &ast::Adt, func: &ast::Fn) -> Option<()> {
+fn gen_partial_eq(adt: &ast::Adt, func: &ast::Fn, trait_ref: Option<TraitRef>) -> Option<()> {
stdx::always!(func.name().map_or(false, |name| name.text() == "eq"));
fn gen_eq_chain(expr: Option<ast::Expr>, cmp: ast::Expr) -> Option<ast::Expr> {
match expr {
@@ -423,8 +427,15 @@ fn gen_partial_eq(adt: &ast::Adt, func: &ast::Fn) -> Option<()> {
ast::Pat::IdentPat(make::ident_pat(false, false, make::name(field_name)))
}
- // FIXME: return `None` if the trait carries a generic type; we can only
- // generate this code `Self` for the time being.
+ // Check that self type and rhs type match. We don't know how to implement the method
+ // automatically otherwise.
+ if let Some(trait_ref) = trait_ref {
+ let self_ty = trait_ref.self_ty();
+ let rhs_ty = trait_ref.get_type_argument(1)?;
+ if self_ty != rhs_ty {
+ return None;
+ }
+ }
let body = match adt {
// `PartialEq` cannot be derived for unions, so no default impl can be provided.
@@ -568,7 +579,7 @@ fn gen_partial_eq(adt: &ast::Adt, func: &ast::Fn) -> Option<()> {
make::block_expr(None, expr).indent(ast::edit::IndentLevel(1))
}
- // No fields in the body means there's nothing to hash.
+ // No fields in the body means there's nothing to compare.
None => {
let expr = make::expr_literal("true").into();
make::block_expr(None, Some(expr)).indent(ast::edit::IndentLevel(1))
@@ -580,7 +591,7 @@ fn gen_partial_eq(adt: &ast::Adt, func: &ast::Fn) -> Option<()> {
Some(())
}
-fn gen_partial_ord(adt: &ast::Adt, func: &ast::Fn) -> Option<()> {
+fn gen_partial_ord(adt: &ast::Adt, func: &ast::Fn, trait_ref: Option<TraitRef>) -> Option<()> {
stdx::always!(func.name().map_or(false, |name| name.text() == "partial_cmp"));
fn gen_partial_eq_match(match_target: ast::Expr) -> Option<ast::Stmt> {
let mut arms = vec![];
@@ -605,8 +616,15 @@ fn gen_partial_ord(adt: &ast::Adt, func: &ast::Fn) -> Option<()> {
make::expr_method_call(lhs, method, make::arg_list(Some(rhs)))
}
- // FIXME: return `None` if the trait carries a generic type; we can only
- // generate this code `Self` for the time being.
+ // Check that self type and rhs type match. We don't know how to implement the method
+ // automatically otherwise.
+ if let Some(trait_ref) = trait_ref {
+ let self_ty = trait_ref.self_ty();
+ let rhs_ty = trait_ref.get_type_argument(1)?;
+ if self_ty != rhs_ty {
+ return None;
+ }
+ }
let body = match adt {
// `PartialOrd` cannot be derived for unions, so no default impl can be provided.
diff --git a/src/tools/rust-analyzer/crates/ide-completion/Cargo.toml b/src/tools/rust-analyzer/crates/ide-completion/Cargo.toml
index 11310e2f1..092fb3036 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/ide-completion/Cargo.toml
@@ -2,9 +2,11 @@
name = "ide-completion"
version = "0.0.0"
description = "TBD"
-license = "MIT OR Apache-2.0"
-edition = "2021"
-rust-version = "1.65"
+
+authors.workspace = true
+edition.workspace = true
+license.workspace = true
+rust-version.workspace = true
[lib]
doctest = false
@@ -13,21 +15,23 @@ doctest = false
cov-mark = "2.0.0-pre.1"
itertools = "0.10.5"
-once_cell = "1.15.0"
-smallvec = "1.10.0"
+once_cell = "1.17.0"
+smallvec.workspace = true
-stdx = { path = "../stdx", version = "0.0.0" }
-syntax = { path = "../syntax", version = "0.0.0" }
-text-edit = { path = "../text-edit", version = "0.0.0" }
-base-db = { path = "../base-db", version = "0.0.0" }
-ide-db = { path = "../ide-db", version = "0.0.0" }
-profile = { path = "../profile", version = "0.0.0" }
+# local deps
+base-db.workspace = true
+ide-db.workspace = true
+profile.workspace = true
+stdx.workspace = true
+syntax.workspace = true
+text-edit.workspace = true
# completions crate should depend only on the top-level `hir` package. if you need
# something from some `hir-xxx` subpackage, reexport the API via `hir`.
-hir = { path = "../hir", version = "0.0.0" }
+hir.workspace = true
[dev-dependencies]
expect-test = "1.4.0"
-test-utils = { path = "../test-utils" }
+# local deps
+test-utils.workspace = true
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions/item_list/trait_impl.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions/item_list/trait_impl.rs
index 9a060857e..889d90095 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/completions/item_list/trait_impl.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions/item_list/trait_impl.rs
@@ -869,7 +869,7 @@ impl Test for T {{
};
// Enumerate some possible next siblings.
- for next_sibling in &[
+ for next_sibling in [
"",
"fn other_fn() {}", // `const $0 fn` -> `const fn`
"type OtherType = i32;",
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions/keyword.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions/keyword.rs
index 1d03c8cc5..b9ab2afca 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/completions/keyword.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions/keyword.rs
@@ -86,6 +86,7 @@ fn foo(a: A) { a.$0 }
sn match match expr {}
sn ref &expr
sn refm &mut expr
+ sn unsafe unsafe {}
"#]],
);
@@ -110,6 +111,7 @@ fn foo() {
sn match match expr {}
sn ref &expr
sn refm &mut expr
+ sn unsafe unsafe {}
"#]],
);
}
@@ -136,6 +138,7 @@ fn foo(a: A) { a.$0 }
sn match match expr {}
sn ref &expr
sn refm &mut expr
+ sn unsafe unsafe {}
"#]],
);
}
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions/postfix.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions/postfix.rs
index f4f37d77d..c55bd9aaa 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/completions/postfix.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions/postfix.rs
@@ -6,7 +6,7 @@ use hir::{Documentation, HasAttrs};
use ide_db::{imports::insert_use::ImportScope, ty_filter::TryEnum, SnippetCap};
use syntax::{
ast::{self, make, AstNode, AstToken},
- SyntaxKind::{EXPR_STMT, STMT_LIST},
+ SyntaxKind::{BLOCK_EXPR, EXPR_STMT, FOR_EXPR, IF_EXPR, LOOP_EXPR, STMT_LIST, WHILE_EXPR},
TextRange, TextSize,
};
use text_edit::TextEdit;
@@ -123,6 +123,22 @@ pub(crate) fn complete_postfix(
postfix_snippet("ref", "&expr", &format!("&{receiver_text}")).add_to(acc);
postfix_snippet("refm", "&mut expr", &format!("&mut {receiver_text}")).add_to(acc);
+ let mut unsafe_should_be_wrapped = true;
+ if dot_receiver.syntax().kind() == BLOCK_EXPR {
+ unsafe_should_be_wrapped = false;
+ if let Some(parent) = dot_receiver.syntax().parent() {
+ if matches!(parent.kind(), IF_EXPR | WHILE_EXPR | LOOP_EXPR | FOR_EXPR) {
+ unsafe_should_be_wrapped = true;
+ }
+ }
+ };
+ let unsafe_completion_string = if unsafe_should_be_wrapped {
+ format!("unsafe {{ {receiver_text} }}")
+ } else {
+ format!("unsafe {receiver_text}")
+ };
+ postfix_snippet("unsafe", "unsafe {}", &unsafe_completion_string).add_to(acc);
+
// The rest of the postfix completions create an expression that moves an argument,
// so it's better to consider references now to avoid breaking the compilation
@@ -329,18 +345,19 @@ fn main() {
}
"#,
expect![[r#"
- sn box Box::new(expr)
- sn call function(expr)
- sn dbg dbg!(expr)
- sn dbgr dbg!(&expr)
- sn if if expr {}
- sn let let
- sn letm let mut
- sn match match expr {}
- sn not !expr
- sn ref &expr
- sn refm &mut expr
- sn while while expr {}
+ sn box Box::new(expr)
+ sn call function(expr)
+ sn dbg dbg!(expr)
+ sn dbgr dbg!(&expr)
+ sn if if expr {}
+ sn let let
+ sn letm let mut
+ sn match match expr {}
+ sn not !expr
+ sn ref &expr
+ sn refm &mut expr
+ sn unsafe unsafe {}
+ sn while while expr {}
"#]],
);
}
@@ -359,16 +376,17 @@ fn main() {
}
"#,
expect![[r#"
- sn box Box::new(expr)
- sn call function(expr)
- sn dbg dbg!(expr)
- sn dbgr dbg!(&expr)
- sn if if expr {}
- sn match match expr {}
- sn not !expr
- sn ref &expr
- sn refm &mut expr
- sn while while expr {}
+ sn box Box::new(expr)
+ sn call function(expr)
+ sn dbg dbg!(expr)
+ sn dbgr dbg!(&expr)
+ sn if if expr {}
+ sn match match expr {}
+ sn not !expr
+ sn ref &expr
+ sn refm &mut expr
+ sn unsafe unsafe {}
+ sn while while expr {}
"#]],
);
}
@@ -383,15 +401,16 @@ fn main() {
}
"#,
expect![[r#"
- sn box Box::new(expr)
- sn call function(expr)
- sn dbg dbg!(expr)
- sn dbgr dbg!(&expr)
- sn let let
- sn letm let mut
- sn match match expr {}
- sn ref &expr
- sn refm &mut expr
+ sn box Box::new(expr)
+ sn call function(expr)
+ sn dbg dbg!(expr)
+ sn dbgr dbg!(&expr)
+ sn let let
+ sn letm let mut
+ sn match match expr {}
+ sn ref &expr
+ sn refm &mut expr
+ sn unsafe unsafe {}
"#]],
)
}
@@ -406,18 +425,19 @@ fn main() {
}
"#,
expect![[r#"
- sn box Box::new(expr)
- sn call function(expr)
- sn dbg dbg!(expr)
- sn dbgr dbg!(&expr)
- sn if if expr {}
- sn let let
- sn letm let mut
- sn match match expr {}
- sn not !expr
- sn ref &expr
- sn refm &mut expr
- sn while while expr {}
+ sn box Box::new(expr)
+ sn call function(expr)
+ sn dbg dbg!(expr)
+ sn dbgr dbg!(&expr)
+ sn if if expr {}
+ sn let let
+ sn letm let mut
+ sn match match expr {}
+ sn not !expr
+ sn ref &expr
+ sn refm &mut expr
+ sn unsafe unsafe {}
+ sn while while expr {}
"#]],
);
}
@@ -518,6 +538,49 @@ fn main() {
}
#[test]
+ fn postfix_completion_for_unsafe() {
+ check_edit("unsafe", r#"fn main() { foo.$0 }"#, r#"fn main() { unsafe { foo } }"#);
+ check_edit("unsafe", r#"fn main() { { foo }.$0 }"#, r#"fn main() { unsafe { foo } }"#);
+ check_edit(
+ "unsafe",
+ r#"fn main() { if x { foo }.$0 }"#,
+ r#"fn main() { unsafe { if x { foo } } }"#,
+ );
+ check_edit(
+ "unsafe",
+ r#"fn main() { loop { foo }.$0 }"#,
+ r#"fn main() { unsafe { loop { foo } } }"#,
+ );
+ check_edit(
+ "unsafe",
+ r#"fn main() { if true {}.$0 }"#,
+ r#"fn main() { unsafe { if true {} } }"#,
+ );
+ check_edit(
+ "unsafe",
+ r#"fn main() { while true {}.$0 }"#,
+ r#"fn main() { unsafe { while true {} } }"#,
+ );
+ check_edit(
+ "unsafe",
+ r#"fn main() { for i in 0..10 {}.$0 }"#,
+ r#"fn main() { unsafe { for i in 0..10 {} } }"#,
+ );
+ check_edit(
+ "unsafe",
+ r#"fn main() { let x = if true {1} else {2}.$0 }"#,
+ r#"fn main() { let x = unsafe { if true {1} else {2} } }"#,
+ );
+
+ // completion will not be triggered
+ check_edit(
+ "unsafe",
+ r#"fn main() { let x = true else {panic!()}.$0}"#,
+ r#"fn main() { let x = true else {panic!()}.unsafe}"#,
+ );
+ }
+
+ #[test]
fn custom_postfix_completion() {
let config = CompletionConfig {
snippets: vec![Snippet::new(
@@ -684,4 +747,16 @@ fn main() {
"#,
);
}
+
+ #[test]
+ fn no_postfix_completions_in_if_block_that_has_an_else() {
+ check(
+ r#"
+fn test() {
+ if true {}.$0 else {}
+}
+"#,
+ expect![[r#""#]],
+ );
+ }
}
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/config.rs b/src/tools/rust-analyzer/crates/ide-completion/src/config.rs
index a0f5e81b4..8f6a97e1e 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/config.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/config.rs
@@ -19,6 +19,7 @@ pub struct CompletionConfig {
pub insert_use: InsertUseConfig,
pub prefer_no_std: bool,
pub snippets: Vec<Snippet>,
+ pub limit: Option<usize>,
}
#[derive(Clone, Debug, PartialEq, Eq)]
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/context.rs b/src/tools/rust-analyzer/crates/ide-completion/src/context.rs
index aa77f4495..ea54068b0 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/context.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/context.rs
@@ -571,28 +571,25 @@ impl<'a> CompletionContext<'a> {
// try to skip completions on path with invalid colons
// this approach works in normal path and inside token tree
- match original_token.kind() {
- T![:] => {
- // return if no prev token before colon
- let prev_token = original_token.prev_token()?;
-
- // only has a single colon
- if prev_token.kind() != T![:] {
- return None;
- }
+ if original_token.kind() == T![:] {
+ // return if no prev token before colon
+ let prev_token = original_token.prev_token()?;
- // has 3 colon or 2 coloncolon in a row
- // special casing this as per discussion in https://github.com/rust-lang/rust-analyzer/pull/13611#discussion_r1031845205
- // and https://github.com/rust-lang/rust-analyzer/pull/13611#discussion_r1032812751
- if prev_token
- .prev_token()
- .map(|t| t.kind() == T![:] || t.kind() == T![::])
- .unwrap_or(false)
- {
- return None;
- }
+ // only has a single colon
+ if prev_token.kind() != T![:] {
+ return None;
+ }
+
+ // has 3 colon or 2 coloncolon in a row
+ // special casing this as per discussion in https://github.com/rust-lang/rust-analyzer/pull/13611#discussion_r1031845205
+ // and https://github.com/rust-lang/rust-analyzer/pull/13611#discussion_r1032812751
+ if prev_token
+ .prev_token()
+ .map(|t| t.kind() == T![:] || t.kind() == T![::])
+ .unwrap_or(false)
+ {
+ return None;
}
- _ => {}
}
let AnalysisResult {
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/context/analysis.rs b/src/tools/rust-analyzer/crates/ide-completion/src/context/analysis.rs
index e34824e22..db0045aef 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/context/analysis.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/context/analysis.rs
@@ -29,6 +29,7 @@ pub(super) struct AnalysisResult {
pub(super) analysis: CompletionAnalysis,
pub(super) expected: (Option<Type>, Option<ast::NameOrNameRef>),
pub(super) qualifier_ctx: QualifierCtx,
+ /// the original token of the expanded file
pub(super) token: SyntaxToken,
pub(super) offset: TextSize,
}
@@ -48,7 +49,9 @@ pub(super) fn expand_and_analyze(
// make the offset point to the start of the original token, as that is what the
// intermediate offsets calculated in expansion always points to
let offset = offset - relative_offset;
- let expansion = expand(sema, original_file, speculative_file, offset, fake_ident_token);
+ let expansion =
+ expand(sema, original_file, speculative_file, offset, fake_ident_token, relative_offset);
+
// add the relative offset back, so that left_biased finds the proper token
let offset = expansion.offset + relative_offset;
let token = expansion.original_file.token_at_offset(offset).left_biased()?;
@@ -67,6 +70,7 @@ fn expand(
mut speculative_file: SyntaxNode,
mut offset: TextSize,
mut fake_ident_token: SyntaxToken,
+ relative_offset: TextSize,
) -> ExpansionResult {
let _p = profile::span("CompletionContext::expand");
let mut derive_ctx = None;
@@ -97,7 +101,7 @@ fn expand(
// successful expansions
(Some(actual_expansion), Some((fake_expansion, fake_mapped_token))) => {
let new_offset = fake_mapped_token.text_range().start();
- if new_offset > actual_expansion.text_range().end() {
+ if new_offset + relative_offset > actual_expansion.text_range().end() {
// offset outside of bounds from the original expansion,
// stop here to prevent problems from happening
break 'expansion;
@@ -176,7 +180,7 @@ fn expand(
// successful expansions
(Some(actual_expansion), Some((fake_expansion, fake_mapped_token))) => {
let new_offset = fake_mapped_token.text_range().start();
- if new_offset > actual_expansion.text_range().end() {
+ if new_offset + relative_offset > actual_expansion.text_range().end() {
// offset outside of bounds from the original expansion,
// stop here to prevent problems from happening
break 'expansion;
@@ -210,15 +214,6 @@ fn analyze(
let _p = profile::span("CompletionContext::analyze");
let ExpansionResult { original_file, speculative_file, offset, fake_ident_token, derive_ctx } =
expansion_result;
- let syntax_element = NodeOrToken::Token(fake_ident_token);
- if is_in_token_of_for_loop(syntax_element.clone()) {
- // for pat $0
- // there is nothing to complete here except `in` keyword
- // don't bother populating the context
- // FIXME: the completion calculations should end up good enough
- // such that this special case becomes unnecessary
- return None;
- }
// Overwrite the path kind for derives
if let Some((original_file, file_with_fake_ident, offset, origin_attr)) = derive_ctx {
@@ -246,37 +241,35 @@ fn analyze(
return None;
}
- let name_like = match find_node_at_offset(&speculative_file, offset) {
- Some(it) => it,
- None => {
- let analysis = if let Some(original) = ast::String::cast(original_token.clone()) {
- CompletionAnalysis::String {
- original,
- expanded: ast::String::cast(self_token.clone()),
+ let Some(name_like) = find_node_at_offset(&speculative_file, offset) else {
+ let analysis = if let Some(original) = ast::String::cast(original_token.clone()) {
+ CompletionAnalysis::String {
+ original,
+ expanded: ast::String::cast(self_token.clone()),
+ }
+ } else {
+ // Fix up trailing whitespace problem
+ // #[attr(foo = $0
+ let token = syntax::algo::skip_trivia_token(self_token.clone(), Direction::Prev)?;
+ let p = token.parent()?;
+ if p.kind() == SyntaxKind::TOKEN_TREE
+ && p.ancestors().any(|it| it.kind() == SyntaxKind::META)
+ {
+ let colon_prefix = previous_non_trivia_token(self_token.clone())
+ .map_or(false, |it| T![:] == it.kind());
+ CompletionAnalysis::UnexpandedAttrTT {
+ fake_attribute_under_caret: fake_ident_token
+ .parent_ancestors()
+ .find_map(ast::Attr::cast),
+ colon_prefix,
}
} else {
- // Fix up trailing whitespace problem
- // #[attr(foo = $0
- let token = syntax::algo::skip_trivia_token(self_token.clone(), Direction::Prev)?;
- let p = token.parent()?;
- if p.kind() == SyntaxKind::TOKEN_TREE
- && p.ancestors().any(|it| it.kind() == SyntaxKind::META)
- {
- let colon_prefix = previous_non_trivia_token(self_token.clone())
- .map_or(false, |it| T![:] == it.kind());
- CompletionAnalysis::UnexpandedAttrTT {
- fake_attribute_under_caret: syntax_element
- .ancestors()
- .find_map(ast::Attr::cast),
- colon_prefix,
- }
- } else {
- return None;
- }
- };
- return Some((analysis, (None, None), QualifierCtx::default()));
- }
+ return None;
+ }
+ };
+ return Some((analysis, (None, None), QualifierCtx::default()));
};
+
let expected = expected_type_and_name(sema, self_token, &name_like);
let mut qual_ctx = QualifierCtx::default();
let analysis = match name_like {
@@ -287,6 +280,22 @@ fn analyze(
let parent = name_ref.syntax().parent()?;
let (nameref_ctx, qualifier_ctx) =
classify_name_ref(sema, &original_file, name_ref, parent)?;
+
+ if let NameRefContext {
+ kind:
+ NameRefKind::Path(PathCompletionCtx { kind: PathKind::Expr { .. }, path, .. }, ..),
+ ..
+ } = &nameref_ctx
+ {
+ if is_in_token_of_for_loop(path) {
+ // for pat $0
+ // there is nothing to complete here except `in` keyword
+ // don't bother populating the context
+ // Ideally this special casing wouldn't be needed, but the parser recovers
+ return None;
+ }
+ }
+
qual_ctx = qualifier_ctx;
CompletionAnalysis::NameRef(nameref_ctx)
}
@@ -320,16 +329,14 @@ fn expected_type_and_name(
ast::FieldExpr(e) => e
.syntax()
.ancestors()
- .map_while(ast::FieldExpr::cast)
- .last()
- .map(|it| it.syntax().clone()),
+ .take_while(|it| ast::FieldExpr::can_cast(it.kind()))
+ .last(),
ast::PathSegment(e) => e
.syntax()
.ancestors()
.skip(1)
.take_while(|it| ast::Path::can_cast(it.kind()) || ast::PathExpr::can_cast(it.kind()))
- .find_map(ast::PathExpr::cast)
- .map(|it| it.syntax().clone()),
+ .find(|it| ast::PathExpr::can_cast(it.kind())),
_ => None
}
};
@@ -602,6 +609,18 @@ fn classify_name_ref(
},
_ => false,
};
+
+ let reciever_is_part_of_indivisible_expression = match &receiver {
+ Some(ast::Expr::IfExpr(_)) => {
+ let next_token_kind = next_non_trivia_token(name_ref.syntax().clone()).map(|t| t.kind());
+ next_token_kind == Some(SyntaxKind::ELSE_KW)
+ },
+ _ => false
+ };
+ if reciever_is_part_of_indivisible_expression {
+ return None;
+ }
+
let kind = NameRefKind::DotAccess(DotAccess {
receiver_ty: receiver.as_ref().and_then(|it| sema.type_of_expr(it)),
kind: DotAccessKind::Field { receiver_is_ambiguous_float_literal },
@@ -653,8 +672,15 @@ fn classify_name_ref(
};
let after_if_expr = |node: SyntaxNode| {
let prev_expr = (|| {
+ let node = match node.parent().and_then(ast::ExprStmt::cast) {
+ Some(stmt) => stmt.syntax().clone(),
+ None => node,
+ };
let prev_sibling = non_trivia_sibling(node.into(), Direction::Prev)?.into_node()?;
- ast::ExprStmt::cast(prev_sibling)?.expr()
+
+ ast::ExprStmt::cast(prev_sibling.clone())
+ .and_then(|it| it.expr())
+ .or_else(|| ast::Expr::cast(prev_sibling))
})();
matches!(prev_expr, Some(ast::Expr::IfExpr(_)))
};
@@ -672,10 +698,10 @@ fn classify_name_ref(
{
if let Some(item) = ast::Item::cast(n) {
let is_inbetween = match &item {
- ast::Item::Const(it) => it.body().is_none(),
+ ast::Item::Const(it) => it.body().is_none() && it.semicolon_token().is_none(),
ast::Item::Enum(it) => it.variant_list().is_none(),
ast::Item::ExternBlock(it) => it.extern_item_list().is_none(),
- ast::Item::Fn(it) => it.body().is_none(),
+ ast::Item::Fn(it) => it.body().is_none() && it.semicolon_token().is_none(),
ast::Item::Impl(it) => it.assoc_item_list().is_none(),
ast::Item::Module(it) => {
it.item_list().is_none() && it.semicolon_token().is_none()
@@ -685,7 +711,7 @@ fn classify_name_ref(
it.field_list().is_none() && it.semicolon_token().is_none()
}
ast::Item::Trait(it) => it.assoc_item_list().is_none(),
- ast::Item::TypeAlias(it) => it.ty().is_none(),
+ ast::Item::TypeAlias(it) => it.ty().is_none() && it.semicolon_token().is_none(),
ast::Item::Union(it) => it.record_field_list().is_none(),
_ => false,
};
@@ -1248,40 +1274,29 @@ fn path_or_use_tree_qualifier(path: &ast::Path) -> Option<(ast::Path, bool)> {
Some((use_tree.path()?, true))
}
-pub(crate) fn is_in_token_of_for_loop(element: SyntaxElement) -> bool {
+fn is_in_token_of_for_loop(path: &ast::Path) -> bool {
// oh my ...
(|| {
- let syntax_token = element.into_token()?;
- let range = syntax_token.text_range();
- let for_expr = syntax_token.parent_ancestors().find_map(ast::ForExpr::cast)?;
-
- // check if the current token is the `in` token of a for loop
- if let Some(token) = for_expr.in_token() {
- return Some(syntax_token == token);
+ let expr = path.syntax().parent().and_then(ast::PathExpr::cast)?;
+ let for_expr = expr.syntax().parent().and_then(ast::ForExpr::cast)?;
+ if for_expr.in_token().is_some() {
+ return Some(false);
}
let pat = for_expr.pat()?;
- if range.end() < pat.syntax().text_range().end() {
- // if we are inside or before the pattern we can't be at the `in` token position
- return None;
- }
let next_sibl = next_non_trivia_sibling(pat.syntax().clone().into())?;
Some(match next_sibl {
- // the loop body is some node, if our token is at the start we are at the `in` position,
- // otherwise we could be in a recovered expression, we don't wanna ruin completions there
- syntax::NodeOrToken::Node(n) => n.text_range().start() == range.start(),
- // the loop body consists of a single token, if we are this we are certainly at the `in` token position
- syntax::NodeOrToken::Token(t) => t == syntax_token,
+ syntax::NodeOrToken::Node(n) => {
+ n.text_range().start() == path.syntax().text_range().start()
+ }
+ syntax::NodeOrToken::Token(t) => {
+ t.text_range().start() == path.syntax().text_range().start()
+ }
})
})()
.unwrap_or(false)
}
-#[test]
-fn test_for_is_prev2() {
- crate::tests::check_pattern_is_applicable(r"fn __() { for i i$0 }", is_in_token_of_for_loop);
-}
-
-pub(crate) fn is_in_loop_body(node: &SyntaxNode) -> bool {
+fn is_in_loop_body(node: &SyntaxNode) -> bool {
node.ancestors()
.take_while(|it| it.kind() != SyntaxKind::FN && it.kind() != SyntaxKind::CLOSURE_EXPR)
.find_map(|it| {
@@ -1314,6 +1329,22 @@ fn previous_non_trivia_token(e: impl Into<SyntaxElement>) -> Option<SyntaxToken>
None
}
+fn next_non_trivia_token(e: impl Into<SyntaxElement>) -> Option<SyntaxToken> {
+ let mut token = match e.into() {
+ SyntaxElement::Node(n) => n.last_token()?,
+ SyntaxElement::Token(t) => t,
+ }
+ .next_token();
+ while let Some(inner) = token {
+ if !inner.kind().is_trivia() {
+ return Some(inner);
+ } else {
+ token = inner.next_token();
+ }
+ }
+ None
+}
+
fn next_non_trivia_sibling(ele: SyntaxElement) -> Option<SyntaxElement> {
let mut e = ele.next_sibling_or_token();
while let Some(inner) = e {
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/item.rs b/src/tools/rust-analyzer/crates/ide-completion/src/item.rs
index 657eab5b1..2f65491d8 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/item.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/item.rs
@@ -14,13 +14,14 @@ use crate::{
render::{render_path_resolution, RenderContext},
};
-/// `CompletionItem` describes a single completion variant in the editor pop-up.
-/// It is basically a POD with various properties. To construct a
-/// `CompletionItem`, use `new` method and the `Builder` struct.
+/// `CompletionItem` describes a single completion entity which expands to 1 or more entries in the
+/// editor pop-up. It is basically a POD with various properties. To construct a
+/// [`CompletionItem`], use [`Builder::new`] method and the [`Builder`] struct.
#[derive(Clone)]
+#[non_exhaustive]
pub struct CompletionItem {
/// Label in the completion pop up which identifies completion.
- label: SmolStr,
+ pub label: SmolStr,
/// Range of identifier that is being completed.
///
/// It should be used primarily for UI, but we also use this to convert
@@ -29,33 +30,33 @@ pub struct CompletionItem {
/// `source_range` must contain the completion offset. `text_edit` should
/// start with what `source_range` points to, or VSCode will filter out the
/// completion silently.
- source_range: TextRange,
+ pub source_range: TextRange,
/// What happens when user selects this item.
///
/// Typically, replaces `source_range` with new identifier.
- text_edit: TextEdit,
- is_snippet: bool,
+ pub text_edit: TextEdit,
+ pub is_snippet: bool,
/// What item (struct, function, etc) are we completing.
- kind: CompletionItemKind,
+ pub kind: CompletionItemKind,
/// Lookup is used to check if completion item indeed can complete current
/// ident.
///
/// That is, in `foo.bar$0` lookup of `abracadabra` will be accepted (it
/// contains `bar` sub sequence), and `quux` will rejected.
- lookup: Option<SmolStr>,
+ pub lookup: Option<SmolStr>,
/// Additional info to show in the UI pop up.
- detail: Option<String>,
- documentation: Option<Documentation>,
+ pub detail: Option<String>,
+ pub documentation: Option<Documentation>,
/// Whether this item is marked as deprecated
- deprecated: bool,
+ pub deprecated: bool,
/// If completing a function call, ask the editor to show parameter popup
/// after completion.
- trigger_call_info: bool,
+ pub trigger_call_info: bool,
/// We use this to sort completion. Relevance records facts like "do the
/// types align precisely?". We can't sort by relevances directly, they are
@@ -64,36 +65,39 @@ pub struct CompletionItem {
/// Note that Relevance ignores fuzzy match score. We compute Relevance for
/// all possible items, and then separately build an ordered completion list
/// based on relevance and fuzzy matching with the already typed identifier.
- relevance: CompletionRelevance,
+ pub relevance: CompletionRelevance,
/// Indicates that a reference or mutable reference to this variable is a
/// possible match.
- ref_match: Option<(Mutability, TextSize)>,
+ // FIXME: We shouldn't expose Mutability here (that is HIR types at all), its fine for now though
+ // until we have more splitting completions in which case we should think about
+ // generalizing this. See https://github.com/rust-lang/rust-analyzer/issues/12571
+ pub ref_match: Option<(Mutability, TextSize)>,
/// The import data to add to completion's edits.
- import_to_add: SmallVec<[LocatedImport; 1]>,
+ pub import_to_add: SmallVec<[LocatedImport; 1]>,
}
// We use custom debug for CompletionItem to make snapshot tests more readable.
impl fmt::Debug for CompletionItem {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let mut s = f.debug_struct("CompletionItem");
- s.field("label", &self.label()).field("source_range", &self.source_range());
- if self.text_edit().len() == 1 {
- let atom = &self.text_edit().iter().next().unwrap();
+ s.field("label", &self.label).field("source_range", &self.source_range);
+ if self.text_edit.len() == 1 {
+ let atom = &self.text_edit.iter().next().unwrap();
s.field("delete", &atom.delete);
s.field("insert", &atom.insert);
} else {
s.field("text_edit", &self.text_edit);
}
- s.field("kind", &self.kind());
- if self.lookup() != self.label() {
+ s.field("kind", &self.kind);
+ if self.lookup() != self.label {
s.field("lookup", &self.lookup());
}
- if let Some(detail) = self.detail() {
+ if let Some(detail) = &self.detail {
s.field("detail", &detail);
}
- if let Some(documentation) = self.documentation() {
+ if let Some(documentation) = &self.documentation {
s.field("documentation", &documentation);
}
if self.deprecated {
@@ -351,63 +355,25 @@ impl CompletionItem {
}
}
- /// What user sees in pop-up in the UI.
- pub fn label(&self) -> &str {
- &self.label
- }
- pub fn source_range(&self) -> TextRange {
- self.source_range
- }
-
- pub fn text_edit(&self) -> &TextEdit {
- &self.text_edit
- }
- /// Whether `text_edit` is a snippet (contains `$0` markers).
- pub fn is_snippet(&self) -> bool {
- self.is_snippet
- }
-
- /// Short one-line additional information, like a type
- pub fn detail(&self) -> Option<&str> {
- self.detail.as_deref()
- }
- /// A doc-comment
- pub fn documentation(&self) -> Option<Documentation> {
- self.documentation.clone()
- }
/// What string is used for filtering.
pub fn lookup(&self) -> &str {
self.lookup.as_deref().unwrap_or(&self.label)
}
- pub fn kind(&self) -> CompletionItemKind {
- self.kind
- }
-
- pub fn deprecated(&self) -> bool {
- self.deprecated
- }
-
- pub fn relevance(&self) -> CompletionRelevance {
- self.relevance
- }
-
- pub fn trigger_call_info(&self) -> bool {
- self.trigger_call_info
- }
-
- pub fn ref_match(&self) -> Option<(Mutability, TextSize, CompletionRelevance)> {
+ pub fn ref_match(&self) -> Option<(String, text_edit::Indel, CompletionRelevance)> {
// Relevance of the ref match should be the same as the original
// match, but with exact type match set because self.ref_match
// is only set if there is an exact type match.
let mut relevance = self.relevance;
relevance.type_match = Some(CompletionRelevanceTypeMatch::Exact);
- self.ref_match.map(|(mutability, offset)| (mutability, offset, relevance))
- }
-
- pub fn imports_to_add(&self) -> &[LocatedImport] {
- &self.import_to_add
+ self.ref_match.map(|(mutability, offset)| {
+ (
+ format!("&{}{}", mutability.as_keyword_for_ref(), self.label),
+ text_edit::Indel::insert(offset, format!("&{}", mutability.as_keyword_for_ref())),
+ relevance,
+ )
+ })
}
}
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/lib.rs b/src/tools/rust-analyzer/crates/ide-completion/src/lib.rs
index 4b48ec6bc..6fe781114 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/lib.rs
@@ -156,13 +156,15 @@ pub fn completions(
// prevent `(` from triggering unwanted completion noise
if trigger_character == Some('(') {
- if let CompletionAnalysis::NameRef(NameRefContext { kind, .. }) = &analysis {
- if let NameRefKind::Path(
- path_ctx @ PathCompletionCtx { kind: PathKind::Vis { has_in_token }, .. },
- ) = kind
- {
- completions::vis::complete_vis_path(&mut completions, ctx, path_ctx, has_in_token);
- }
+ if let CompletionAnalysis::NameRef(NameRefContext {
+ kind:
+ NameRefKind::Path(
+ path_ctx @ PathCompletionCtx { kind: PathKind::Vis { has_in_token }, .. },
+ ),
+ ..
+ }) = analysis
+ {
+ completions::vis::complete_vis_path(&mut completions, ctx, path_ctx, has_in_token);
}
return Some(completions.into());
}
@@ -170,7 +172,7 @@ pub fn completions(
{
let acc = &mut completions;
- match &analysis {
+ match analysis {
CompletionAnalysis::Name(name_ctx) => completions::complete_name(acc, ctx, name_ctx),
CompletionAnalysis::NameRef(name_ref_ctx) => {
completions::complete_name_ref(acc, ctx, name_ref_ctx)
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/render.rs b/src/tools/rust-analyzer/crates/ide-completion/src/render.rs
index e48d1aecd..d99ad5f9f 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/render.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/render.rs
@@ -503,18 +503,18 @@ mod tests {
#[track_caller]
fn check_relevance_for_kinds(ra_fixture: &str, kinds: &[CompletionItemKind], expect: Expect) {
let mut actual = get_all_items(TEST_CONFIG, ra_fixture, None);
- actual.retain(|it| kinds.contains(&it.kind()));
- actual.sort_by_key(|it| cmp::Reverse(it.relevance().score()));
+ actual.retain(|it| kinds.contains(&it.kind));
+ actual.sort_by_key(|it| cmp::Reverse(it.relevance.score()));
check_relevance_(actual, expect);
}
#[track_caller]
fn check_relevance(ra_fixture: &str, expect: Expect) {
let mut actual = get_all_items(TEST_CONFIG, ra_fixture, None);
- actual.retain(|it| it.kind() != CompletionItemKind::Snippet);
- actual.retain(|it| it.kind() != CompletionItemKind::Keyword);
- actual.retain(|it| it.kind() != CompletionItemKind::BuiltinType);
- actual.sort_by_key(|it| cmp::Reverse(it.relevance().score()));
+ actual.retain(|it| it.kind != CompletionItemKind::Snippet);
+ actual.retain(|it| it.kind != CompletionItemKind::Keyword);
+ actual.retain(|it| it.kind != CompletionItemKind::BuiltinType);
+ actual.sort_by_key(|it| cmp::Reverse(it.relevance.score()));
check_relevance_(actual, expect);
}
@@ -525,12 +525,11 @@ mod tests {
.flat_map(|it| {
let mut items = vec![];
- let tag = it.kind().tag();
- let relevance = display_relevance(it.relevance());
- items.push(format!("{tag} {} {relevance}\n", it.label()));
+ let tag = it.kind.tag();
+ let relevance = display_relevance(it.relevance);
+ items.push(format!("{tag} {} {relevance}\n", it.label));
- if let Some((mutability, _offset, relevance)) = it.ref_match() {
- let label = format!("&{}{}", mutability.as_keyword_for_ref(), it.label());
+ if let Some((label, _indel, relevance)) = it.ref_match() {
let relevance = display_relevance(relevance);
items.push(format!("{tag} {label} {relevance}\n"));
@@ -587,6 +586,7 @@ fn main() { Foo::Fo$0 }
),
lookup: "Foo{}",
detail: "Foo { x: i32, y: i32 }",
+ trigger_call_info: true,
},
]
"#]],
@@ -614,6 +614,7 @@ fn main() { Foo::Fo$0 }
),
lookup: "Foo()",
detail: "Foo(i32, i32)",
+ trigger_call_info: true,
},
]
"#]],
@@ -679,6 +680,7 @@ fn main() { Foo::Fo$0 }
Variant,
),
detail: "Foo",
+ trigger_call_info: true,
},
]
"#]],
@@ -745,6 +747,7 @@ fn main() { let _: m::Spam = S$0 }
postfix_match: None,
is_definite: false,
},
+ trigger_call_info: true,
},
CompletionItem {
label: "m::Spam::Foo",
@@ -770,6 +773,7 @@ fn main() { let _: m::Spam = S$0 }
postfix_match: None,
is_definite: false,
},
+ trigger_call_info: true,
},
]
"#]],
@@ -942,6 +946,7 @@ use self::E::*;
documentation: Documentation(
"variant docs",
),
+ trigger_call_info: true,
},
CompletionItem {
label: "E",
@@ -1691,6 +1696,7 @@ fn main() {
sn while []
sn ref []
sn refm []
+ sn unsafe []
sn match []
sn box []
sn dbg []
@@ -1718,6 +1724,7 @@ fn main() {
me f() []
sn ref []
sn refm []
+ sn unsafe []
sn match []
sn box []
sn dbg []
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/render/literal.rs b/src/tools/rust-analyzer/crates/ide-completion/src/render/literal.rs
index 64dab02f7..ed78fcd8e 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/render/literal.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/render/literal.rs
@@ -113,7 +113,7 @@ fn render(
item.detail(rendered.detail);
match snippet_cap {
- Some(snippet_cap) => item.insert_snippet(snippet_cap, rendered.literal),
+ Some(snippet_cap) => item.insert_snippet(snippet_cap, rendered.literal).trigger_call_info(),
None => item.insert_text(rendered.literal),
};
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/render/union_literal.rs b/src/tools/rust-analyzer/crates/ide-completion/src/render/union_literal.rs
index 1b09ad173..6e0c53ec9 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/render/union_literal.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/render/union_literal.rs
@@ -72,7 +72,7 @@ pub(crate) fn render_union_literal(
.set_relevance(ctx.completion_relevance());
match ctx.snippet_cap() {
- Some(snippet_cap) => item.insert_snippet(snippet_cap, literal),
+ Some(snippet_cap) => item.insert_snippet(snippet_cap, literal).trigger_call_info(),
None => item.insert_text(literal),
};
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/tests.rs b/src/tools/rust-analyzer/crates/ide-completion/src/tests.rs
index abe14e48e..1fe48b9e9 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/tests.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/tests.rs
@@ -23,7 +23,7 @@ mod type_pos;
mod use_tree;
mod visibility;
-use hir::{db::DefDatabase, PrefixKind, Semantics};
+use hir::{db::DefDatabase, PrefixKind};
use ide_db::{
base_db::{fixture::ChangeFixture, FileLoader, FilePosition},
imports::insert_use::{ImportGranularity, InsertUseConfig},
@@ -31,7 +31,6 @@ use ide_db::{
};
use itertools::Itertools;
use stdx::{format_to, trim_indent};
-use syntax::{AstNode, NodeOrToken, SyntaxElement};
use test_utils::assert_eq_text;
use crate::{
@@ -75,6 +74,7 @@ pub(crate) const TEST_CONFIG: CompletionConfig = CompletionConfig {
skip_glob_imports: true,
},
snippets: Vec::new(),
+ limit: None,
};
pub(crate) fn completion_list(ra_fixture: &str) -> String {
@@ -108,10 +108,10 @@ fn completion_list_with_config(
let items = get_all_items(config, ra_fixture, trigger_character);
let items = items
.into_iter()
- .filter(|it| it.kind() != CompletionItemKind::BuiltinType || it.label() == "u32")
- .filter(|it| include_keywords || it.kind() != CompletionItemKind::Keyword)
- .filter(|it| include_keywords || it.kind() != CompletionItemKind::Snippet)
- .sorted_by_key(|it| (it.kind(), it.label().to_owned(), it.detail().map(ToOwned::to_owned)))
+ .filter(|it| it.kind != CompletionItemKind::BuiltinType || it.label == "u32")
+ .filter(|it| include_keywords || it.kind != CompletionItemKind::Keyword)
+ .filter(|it| include_keywords || it.kind != CompletionItemKind::Snippet)
+ .sorted_by_key(|it| (it.kind, it.label.clone(), it.detail.as_ref().map(ToOwned::to_owned)))
.collect();
render_completion_list(items)
}
@@ -138,8 +138,8 @@ pub(crate) fn do_completion_with_config(
) -> Vec<CompletionItem> {
get_all_items(config, code, None)
.into_iter()
- .filter(|c| c.kind() == kind)
- .sorted_by(|l, r| l.label().cmp(r.label()))
+ .filter(|c| c.kind == kind)
+ .sorted_by(|l, r| l.label.cmp(&r.label))
.collect()
}
@@ -148,18 +148,18 @@ fn render_completion_list(completions: Vec<CompletionItem>) -> String {
s.chars().count()
}
let label_width =
- completions.iter().map(|it| monospace_width(it.label())).max().unwrap_or_default().min(22);
+ completions.iter().map(|it| monospace_width(&it.label)).max().unwrap_or_default().min(22);
completions
.into_iter()
.map(|it| {
- let tag = it.kind().tag();
- let var_name = format!("{tag} {}", it.label());
+ let tag = it.kind.tag();
+ let var_name = format!("{tag} {}", it.label);
let mut buf = var_name;
- if let Some(detail) = it.detail() {
- let width = label_width.saturating_sub(monospace_width(it.label()));
+ if let Some(detail) = it.detail {
+ let width = label_width.saturating_sub(monospace_width(&it.label));
format_to!(buf, "{:width$} {}", "", detail, width = width);
}
- if it.deprecated() {
+ if it.deprecated {
format_to!(buf, " DEPRECATED");
}
format_to!(buf, "\n");
@@ -191,13 +191,13 @@ pub(crate) fn check_edit_with_config(
.unwrap_or_else(|| panic!("can't find {what:?} completion in {completions:#?}"));
let mut actual = db.file_text(position.file_id).to_string();
- let mut combined_edit = completion.text_edit().to_owned();
+ let mut combined_edit = completion.text_edit.clone();
resolve_completion_edits(
&db,
&config,
position,
- completion.imports_to_add().iter().filter_map(|import_edit| {
+ completion.import_to_add.iter().filter_map(|import_edit| {
let import_path = &import_edit.import_path;
let import_name = import_path.segments().last()?;
Some((import_path.to_string(), import_name.to_string()))
@@ -215,15 +215,6 @@ pub(crate) fn check_edit_with_config(
assert_eq_text!(&ra_fixture_after, &actual)
}
-pub(crate) fn check_pattern_is_applicable(code: &str, check: impl FnOnce(SyntaxElement) -> bool) {
- let (db, pos) = position(code);
-
- let sema = Semantics::new(&db);
- let original_file = sema.parse(pos.file_id);
- let token = original_file.syntax().token_at_offset(pos.offset).left_biased().unwrap();
- assert!(check(NodeOrToken::Token(token)));
-}
-
pub(crate) fn get_all_items(
config: CompletionConfig,
code: &str,
@@ -234,7 +225,7 @@ pub(crate) fn get_all_items(
.map_or_else(Vec::default, Into::into);
// validate
res.iter().for_each(|it| {
- let sr = it.source_range();
+ let sr = it.source_range;
assert!(
sr.contains_inclusive(position.offset),
"source range {sr:?} does not contain the offset {:?} of the completion request: {it:?}",
@@ -245,8 +236,9 @@ pub(crate) fn get_all_items(
}
#[test]
-fn test_no_completions_required() {
+fn test_no_completions_in_for_loop_in_kw_pos() {
assert_eq!(completion_list(r#"fn foo() { for i i$0 }"#), String::new());
+ assert_eq!(completion_list(r#"fn foo() { for i in$0 }"#), String::new());
}
#[test]
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/tests/expression.rs b/src/tools/rust-analyzer/crates/ide-completion/src/tests/expression.rs
index 043f552bd..c1c6a689e 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/tests/expression.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/tests/expression.rs
@@ -745,3 +745,255 @@ fn return_value_no_block() {
r#"fn f() -> i32 { match () { () => return $0 } }"#,
);
}
+
+#[test]
+fn else_completion_after_if() {
+ check_empty(
+ r#"
+fn foo() { if foo {} $0 }
+"#,
+ expect![[r#"
+ fn foo() fn()
+ bt u32
+ kw const
+ kw crate::
+ kw else
+ kw else if
+ kw enum
+ kw extern
+ kw false
+ kw fn
+ kw for
+ kw if
+ kw if let
+ kw impl
+ kw let
+ kw loop
+ kw match
+ kw mod
+ kw return
+ kw self::
+ kw static
+ kw struct
+ kw trait
+ kw true
+ kw type
+ kw union
+ kw unsafe
+ kw use
+ kw while
+ kw while let
+ sn macro_rules
+ sn pd
+ sn ppd
+ "#]],
+ );
+ check_empty(
+ r#"
+fn foo() { if foo {} el$0 }
+"#,
+ expect![[r#"
+ fn foo() fn()
+ bt u32
+ kw const
+ kw crate::
+ kw else
+ kw else if
+ kw enum
+ kw extern
+ kw false
+ kw fn
+ kw for
+ kw if
+ kw if let
+ kw impl
+ kw let
+ kw loop
+ kw match
+ kw mod
+ kw return
+ kw self::
+ kw static
+ kw struct
+ kw trait
+ kw true
+ kw type
+ kw union
+ kw unsafe
+ kw use
+ kw while
+ kw while let
+ sn macro_rules
+ sn pd
+ sn ppd
+ "#]],
+ );
+ check_empty(
+ r#"
+fn foo() { bar(if foo {} $0) }
+"#,
+ expect![[r#"
+ fn foo() fn()
+ bt u32
+ kw crate::
+ kw else
+ kw else if
+ kw false
+ kw for
+ kw if
+ kw if let
+ kw loop
+ kw match
+ kw return
+ kw self::
+ kw true
+ kw unsafe
+ kw while
+ kw while let
+ "#]],
+ );
+ check_empty(
+ r#"
+fn foo() { bar(if foo {} el$0) }
+"#,
+ expect![[r#"
+ fn foo() fn()
+ bt u32
+ kw crate::
+ kw else
+ kw else if
+ kw false
+ kw for
+ kw if
+ kw if let
+ kw loop
+ kw match
+ kw return
+ kw self::
+ kw true
+ kw unsafe
+ kw while
+ kw while let
+ "#]],
+ );
+ check_empty(
+ r#"
+fn foo() { if foo {} $0 let x = 92; }
+"#,
+ expect![[r#"
+ fn foo() fn()
+ bt u32
+ kw const
+ kw crate::
+ kw else
+ kw else if
+ kw enum
+ kw extern
+ kw false
+ kw fn
+ kw for
+ kw if
+ kw if let
+ kw impl
+ kw let
+ kw loop
+ kw match
+ kw mod
+ kw return
+ kw self::
+ kw static
+ kw struct
+ kw trait
+ kw true
+ kw type
+ kw union
+ kw unsafe
+ kw use
+ kw while
+ kw while let
+ sn macro_rules
+ sn pd
+ sn ppd
+ "#]],
+ );
+ check_empty(
+ r#"
+fn foo() { if foo {} el$0 let x = 92; }
+"#,
+ expect![[r#"
+ fn foo() fn()
+ bt u32
+ kw const
+ kw crate::
+ kw else
+ kw else if
+ kw enum
+ kw extern
+ kw false
+ kw fn
+ kw for
+ kw if
+ kw if let
+ kw impl
+ kw let
+ kw loop
+ kw match
+ kw mod
+ kw return
+ kw self::
+ kw static
+ kw struct
+ kw trait
+ kw true
+ kw type
+ kw union
+ kw unsafe
+ kw use
+ kw while
+ kw while let
+ sn macro_rules
+ sn pd
+ sn ppd
+ "#]],
+ );
+ check_empty(
+ r#"
+fn foo() { if foo {} el$0 { let x = 92; } }
+"#,
+ expect![[r#"
+ fn foo() fn()
+ bt u32
+ kw const
+ kw crate::
+ kw else
+ kw else if
+ kw enum
+ kw extern
+ kw false
+ kw fn
+ kw for
+ kw if
+ kw if let
+ kw impl
+ kw let
+ kw loop
+ kw match
+ kw mod
+ kw return
+ kw self::
+ kw static
+ kw struct
+ kw trait
+ kw true
+ kw type
+ kw union
+ kw unsafe
+ kw use
+ kw while
+ kw while let
+ sn macro_rules
+ sn pd
+ sn ppd
+ "#]],
+ );
+}
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/tests/flyimport.rs b/src/tools/rust-analyzer/crates/ide-completion/src/tests/flyimport.rs
index a63ef0068..0b485eb77 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/tests/flyimport.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/tests/flyimport.rs
@@ -541,9 +541,9 @@ fn main() {
}
"#,
expect![[r#"
- fn weird_function() (use dep::test_mod::TestTrait) fn() DEPRECATED
- ct SPECIAL_CONST (use dep::test_mod::TestTrait) DEPRECATED
- "#]],
+ ct SPECIAL_CONST (use dep::test_mod::TestTrait) DEPRECATED
+ fn weird_function() (use dep::test_mod::TestTrait) fn() DEPRECATED
+ "#]],
);
}
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/tests/item_list.rs b/src/tools/rust-analyzer/crates/ide-completion/src/tests/item_list.rs
index b62b98888..9fc731bb1 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/tests/item_list.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/tests/item_list.rs
@@ -215,6 +215,57 @@ fn in_trait_assoc_item_list() {
}
#[test]
+fn in_trait_assoc_fn_missing_body() {
+ check(
+ r#"trait Foo { fn function(); $0 }"#,
+ expect![[r#"
+ ma makro!(…) macro_rules! makro
+ md module
+ kw const
+ kw crate::
+ kw fn
+ kw self::
+ kw type
+ kw unsafe
+ "#]],
+ );
+}
+
+#[test]
+fn in_trait_assoc_const_missing_body() {
+ check(
+ r#"trait Foo { const CONST: (); $0 }"#,
+ expect![[r#"
+ ma makro!(…) macro_rules! makro
+ md module
+ kw const
+ kw crate::
+ kw fn
+ kw self::
+ kw type
+ kw unsafe
+ "#]],
+ );
+}
+
+#[test]
+fn in_trait_assoc_type_aliases_missing_ty() {
+ check(
+ r#"trait Foo { type Type; $0 }"#,
+ expect![[r#"
+ ma makro!(…) macro_rules! makro
+ md module
+ kw const
+ kw crate::
+ kw fn
+ kw self::
+ kw type
+ kw unsafe
+ "#]],
+ );
+}
+
+#[test]
fn in_trait_impl_assoc_item_list() {
check(
r#"
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/tests/proc_macros.rs b/src/tools/rust-analyzer/crates/ide-completion/src/tests/proc_macros.rs
index 9eae6f849..92ea4d15b 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/tests/proc_macros.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/tests/proc_macros.rs
@@ -24,16 +24,17 @@ fn main() {
}
"#,
expect![[r#"
- me foo() fn(&self)
- sn box Box::new(expr)
- sn call function(expr)
- sn dbg dbg!(expr)
- sn dbgr dbg!(&expr)
- sn let let
- sn letm let mut
- sn match match expr {}
- sn ref &expr
- sn refm &mut expr
+ me foo() fn(&self)
+ sn box Box::new(expr)
+ sn call function(expr)
+ sn dbg dbg!(expr)
+ sn dbgr dbg!(&expr)
+ sn let let
+ sn letm let mut
+ sn match match expr {}
+ sn ref &expr
+ sn refm &mut expr
+ sn unsafe unsafe {}
"#]],
)
}
@@ -54,16 +55,17 @@ fn main() {
}
"#,
expect![[r#"
- me foo() fn(&self)
- sn box Box::new(expr)
- sn call function(expr)
- sn dbg dbg!(expr)
- sn dbgr dbg!(&expr)
- sn let let
- sn letm let mut
- sn match match expr {}
- sn ref &expr
- sn refm &mut expr
+ me foo() fn(&self)
+ sn box Box::new(expr)
+ sn call function(expr)
+ sn dbg dbg!(expr)
+ sn dbgr dbg!(&expr)
+ sn let let
+ sn letm let mut
+ sn match match expr {}
+ sn ref &expr
+ sn refm &mut expr
+ sn unsafe unsafe {}
"#]],
)
}
@@ -86,16 +88,17 @@ impl Foo {
fn main() {}
"#,
expect![[r#"
- me foo() fn(&self)
- sn box Box::new(expr)
- sn call function(expr)
- sn dbg dbg!(expr)
- sn dbgr dbg!(&expr)
- sn let let
- sn letm let mut
- sn match match expr {}
- sn ref &expr
- sn refm &mut expr
+ me foo() fn(&self)
+ sn box Box::new(expr)
+ sn call function(expr)
+ sn dbg dbg!(expr)
+ sn dbgr dbg!(&expr)
+ sn let let
+ sn letm let mut
+ sn match match expr {}
+ sn ref &expr
+ sn refm &mut expr
+ sn unsafe unsafe {}
"#]],
)
}
@@ -118,16 +121,47 @@ impl Foo {
fn main() {}
"#,
expect![[r#"
- me foo() fn(&self)
- sn box Box::new(expr)
- sn call function(expr)
- sn dbg dbg!(expr)
- sn dbgr dbg!(&expr)
- sn let let
- sn letm let mut
- sn match match expr {}
- sn ref &expr
- sn refm &mut expr
+ me foo() fn(&self)
+ sn box Box::new(expr)
+ sn call function(expr)
+ sn dbg dbg!(expr)
+ sn dbgr dbg!(&expr)
+ sn let let
+ sn letm let mut
+ sn match match expr {}
+ sn ref &expr
+ sn refm &mut expr
+ sn unsafe unsafe {}
"#]],
)
}
+
+#[test]
+fn issue_13836_str() {
+ check(
+ r#"
+//- proc_macros: shorten
+fn main() {
+ let s = proc_macros::shorten!("text.$0");
+}
+"#,
+ expect![[r#""#]],
+ )
+}
+
+#[test]
+fn issue_13836_ident() {
+ check(
+ r#"
+//- proc_macros: shorten
+struct S;
+impl S {
+ fn foo(&self) {}
+}
+fn main() {
+ let s = proc_macros::shorten!(S.fo$0);
+}
+"#,
+ expect![[r#""#]],
+ )
+}
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/tests/special.rs b/src/tools/rust-analyzer/crates/ide-completion/src/tests/special.rs
index cad4af493..cb71c7b2b 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/tests/special.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/tests/special.rs
@@ -2,13 +2,20 @@
use expect_test::{expect, Expect};
-use crate::tests::{check_edit, completion_list_no_kw, completion_list_with_trigger_character};
+use crate::tests::{
+ check_edit, completion_list, completion_list_no_kw, completion_list_with_trigger_character,
+};
-fn check(ra_fixture: &str, expect: Expect) {
+fn check_no_kw(ra_fixture: &str, expect: Expect) {
let actual = completion_list_no_kw(ra_fixture);
expect.assert_eq(&actual)
}
+fn check(ra_fixture: &str, expect: Expect) {
+ let actual = completion_list(ra_fixture);
+ expect.assert_eq(&actual)
+}
+
pub(crate) fn check_with_trigger_character(
ra_fixture: &str,
trigger_character: Option<char>,
@@ -59,9 +66,9 @@ fn _alpha() {}
#[test]
fn completes_prelude() {
- check(
+ check_no_kw(
r#"
-//- /main.rs crate:main deps:std
+//- /main.rs edition:2018 crate:main deps:std
fn foo() { let x: $0 }
//- /std/lib.rs crate:std
@@ -81,9 +88,9 @@ pub mod prelude {
#[test]
fn completes_prelude_macros() {
- check(
+ check_no_kw(
r#"
-//- /main.rs crate:main deps:std
+//- /main.rs edition:2018 crate:main deps:std
fn f() {$0}
//- /std/lib.rs crate:std
@@ -110,21 +117,21 @@ mod macros {
#[test]
fn completes_std_prelude_if_core_is_defined() {
- check(
+ check_no_kw(
r#"
//- /main.rs crate:main deps:core,std
fn foo() { let x: $0 }
//- /core/lib.rs crate:core
pub mod prelude {
- pub mod rust_2018 {
+ pub mod rust_2021 {
pub struct Option;
}
}
//- /std/lib.rs crate:std deps:core
pub mod prelude {
- pub mod rust_2018 {
+ pub mod rust_2021 {
pub struct String;
}
}
@@ -140,7 +147,7 @@ pub mod prelude {
#[test]
fn respects_doc_hidden() {
- check(
+ check_no_kw(
r#"
//- /lib.rs crate:lib deps:std
fn f() {
@@ -168,7 +175,7 @@ pub mod prelude {
#[test]
fn respects_doc_hidden_in_assoc_item_list() {
- check(
+ check_no_kw(
r#"
//- /lib.rs crate:lib deps:std
struct S;
@@ -195,7 +202,7 @@ pub mod prelude {
#[test]
fn associated_item_visibility() {
- check(
+ check_no_kw(
r#"
//- /lib.rs crate:lib new_source_root:library
pub struct S;
@@ -222,7 +229,7 @@ fn foo() { let _ = lib::S::$0 }
#[test]
fn completes_union_associated_method() {
- check(
+ check_no_kw(
r#"
union U {};
impl U { fn m() { } }
@@ -237,7 +244,7 @@ fn foo() { let _ = U::$0 }
#[test]
fn completes_trait_associated_method_1() {
- check(
+ check_no_kw(
r#"
trait Trait { fn m(); }
@@ -251,7 +258,7 @@ fn foo() { let _ = Trait::$0 }
#[test]
fn completes_trait_associated_method_2() {
- check(
+ check_no_kw(
r#"
trait Trait { fn m(); }
@@ -268,7 +275,7 @@ fn foo() { let _ = S::$0 }
#[test]
fn completes_trait_associated_method_3() {
- check(
+ check_no_kw(
r#"
trait Trait { fn m(); }
@@ -285,7 +292,7 @@ fn foo() { let _ = <S as Trait>::$0 }
#[test]
fn completes_ty_param_assoc_ty() {
- check(
+ check_no_kw(
r#"
trait Super {
type Ty;
@@ -318,7 +325,7 @@ fn foo<T: Sub>() { T::$0 }
#[test]
fn completes_self_param_assoc_ty() {
- check(
+ check_no_kw(
r#"
trait Super {
type Ty;
@@ -358,7 +365,7 @@ impl<T> Sub for Wrap<T> {
#[test]
fn completes_type_alias() {
- check(
+ check_no_kw(
r#"
struct S;
impl S { fn foo() {} }
@@ -376,7 +383,7 @@ fn main() { T::$0; }
#[test]
fn completes_qualified_macros() {
- check(
+ check_no_kw(
r#"
#[macro_export]
macro_rules! foo { () => {} }
@@ -392,7 +399,7 @@ fn main() { let _ = crate::$0 }
#[test]
fn does_not_complete_non_fn_macros() {
- check(
+ check_no_kw(
r#"
mod m {
#[rustc_builtin_macro]
@@ -403,7 +410,7 @@ fn f() {m::$0}
"#,
expect![[r#""#]],
);
- check(
+ check_no_kw(
r#"
mod m {
#[rustc_builtin_macro]
@@ -418,7 +425,7 @@ fn f() {m::$0}
#[test]
fn completes_reexported_items_under_correct_name() {
- check(
+ check_no_kw(
r#"
fn foo() { self::m::$0 }
@@ -475,7 +482,7 @@ mod p {
#[test]
fn completes_in_simple_macro_call() {
- check(
+ check_no_kw(
r#"
macro_rules! m { ($e:expr) => { $e } }
fn main() { m!(self::f$0); }
@@ -490,7 +497,7 @@ fn foo() {}
#[test]
fn function_mod_share_name() {
- check(
+ check_no_kw(
r#"
fn foo() { self::m::$0 }
@@ -508,7 +515,7 @@ mod m {
#[test]
fn completes_hashmap_new() {
- check(
+ check_no_kw(
r#"
struct RandomState;
struct HashMap<K, V, S = RandomState> {}
@@ -529,7 +536,7 @@ fn foo() {
#[test]
fn completes_variant_through_self() {
cov_mark::check!(completes_variant_through_self);
- check(
+ check_no_kw(
r#"
enum Foo {
Bar,
@@ -552,7 +559,7 @@ impl Foo {
#[test]
fn completes_non_exhaustive_variant_within_the_defining_crate() {
- check(
+ check_no_kw(
r#"
enum Foo {
#[non_exhaustive]
@@ -570,7 +577,7 @@ fn foo(self) {
"#]],
);
- check(
+ check_no_kw(
r#"
//- /main.rs crate:main deps:e
fn foo(self) {
@@ -593,7 +600,7 @@ enum Foo {
#[test]
fn completes_primitive_assoc_const() {
cov_mark::check!(completes_primitive_assoc_const);
- check(
+ check_no_kw(
r#"
//- /lib.rs crate:lib deps:core
fn f() {
@@ -618,7 +625,7 @@ impl u8 {
#[test]
fn completes_variant_through_alias() {
cov_mark::check!(completes_variant_through_alias);
- check(
+ check_no_kw(
r#"
enum Foo {
Bar
@@ -636,7 +643,7 @@ fn main() {
#[test]
fn respects_doc_hidden2() {
- check(
+ check_no_kw(
r#"
//- /lib.rs crate:lib deps:dep
fn f() {
@@ -665,7 +672,7 @@ pub mod m {}
#[test]
fn type_anchor_empty() {
- check(
+ check_no_kw(
r#"
trait Foo {
fn foo() -> Self;
@@ -688,7 +695,7 @@ fn bar() -> Bar {
#[test]
fn type_anchor_type() {
- check(
+ check_no_kw(
r#"
trait Foo {
fn foo() -> Self;
@@ -715,7 +722,7 @@ fn bar() -> Bar {
#[test]
fn type_anchor_type_trait() {
- check(
+ check_no_kw(
r#"
trait Foo {
fn foo() -> Self;
@@ -741,7 +748,7 @@ fn bar() -> Bar {
#[test]
fn completes_fn_in_pub_trait_generated_by_macro() {
- check(
+ check_no_kw(
r#"
mod other_mod {
macro_rules! make_method {
@@ -775,7 +782,7 @@ fn main() {
#[test]
fn completes_fn_in_pub_trait_generated_by_recursive_macro() {
- check(
+ check_no_kw(
r#"
mod other_mod {
macro_rules! make_method {
@@ -815,7 +822,7 @@ fn main() {
#[test]
fn completes_const_in_pub_trait_generated_by_macro() {
- check(
+ check_no_kw(
r#"
mod other_mod {
macro_rules! make_const {
@@ -847,7 +854,7 @@ fn main() {
#[test]
fn completes_locals_from_macros() {
- check(
+ check_no_kw(
r#"
macro_rules! x {
@@ -875,7 +882,7 @@ fn main() {
#[test]
fn regression_12644() {
- check(
+ check_no_kw(
r#"
macro_rules! __rust_force_expr {
($e:expr) => {
@@ -974,7 +981,7 @@ fn foo { crate:::$0 }
"#,
expect![""],
);
- check(
+ check_no_kw(
r#"
fn foo { crate::::$0 }
"#,
diff --git a/src/tools/rust-analyzer/crates/ide-db/Cargo.toml b/src/tools/rust-analyzer/crates/ide-db/Cargo.toml
index f48cce58c..57daaf623 100644
--- a/src/tools/rust-analyzer/crates/ide-db/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/ide-db/Cargo.toml
@@ -2,9 +2,11 @@
name = "ide-db"
version = "0.0.0"
description = "TBD"
-license = "MIT OR Apache-2.0"
-edition = "2021"
-rust-version = "1.65"
+
+authors.workspace = true
+edition.workspace = true
+license.workspace = true
+rust-version.workspace = true
[lib]
doctest = false
@@ -12,29 +14,33 @@ doctest = false
[dependencies]
cov-mark = "2.0.0-pre.1"
tracing = "0.1.35"
-rayon = "1.5.3"
+rayon = "1.6.1"
fst = { version = "0.4.7", default-features = false }
rustc-hash = "1.1.0"
-once_cell = "1.15.0"
+once_cell = "1.17.0"
either = "1.7.0"
itertools = "0.10.5"
arrayvec = "0.7.2"
indexmap = "1.9.1"
memchr = "2.5.0"
-stdx = { path = "../stdx", version = "0.0.0" }
-parser = { path = "../parser", version = "0.0.0" }
-syntax = { path = "../syntax", version = "0.0.0" }
-text-edit = { path = "../text-edit", version = "0.0.0" }
-base-db = { path = "../base-db", version = "0.0.0" }
-profile = { path = "../profile", version = "0.0.0" }
+# local deps
+base-db.workspace = true
+limit.workspace = true
+parser.workspace = true
+profile.workspace = true
+stdx.workspace = true
+syntax.workspace = true
+text-edit.workspace = true
# ide should depend only on the top-level `hir` package. if you need
# something from some `hir-xxx` subpackage, reexport the API via `hir`.
-hir = { path = "../hir", version = "0.0.0" }
-limit = { path = "../limit", version = "0.0.0" }
+hir.workspace = true
[dev-dependencies]
-test-utils = { path = "../test-utils" }
-sourcegen = { path = "../sourcegen" }
-xshell = "0.2.2"
expect-test = "1.4.0"
+oorandom = "11.1.3"
+xshell = "0.2.2"
+
+# local deps
+test-utils.workspace = true
+sourcegen.workspace = true
diff --git a/src/tools/rust-analyzer/crates/ide-db/src/active_parameter.rs b/src/tools/rust-analyzer/crates/ide-db/src/active_parameter.rs
index 7109c6fd1..2b6b60547 100644
--- a/src/tools/rust-analyzer/crates/ide-db/src/active_parameter.rs
+++ b/src/tools/rust-analyzer/crates/ide-db/src/active_parameter.rs
@@ -2,9 +2,10 @@
use either::Either;
use hir::{Semantics, Type};
+use parser::T;
use syntax::{
ast::{self, HasArgList, HasName},
- AstNode, SyntaxToken,
+ match_ast, AstNode, NodeOrToken, SyntaxToken,
};
use crate::RootDatabase;
@@ -58,7 +59,7 @@ pub fn callable_for_node(
calling_node: &ast::CallableExpr,
token: &SyntaxToken,
) -> Option<(hir::Callable, Option<usize>)> {
- let callable = match &calling_node {
+ let callable = match calling_node {
ast::CallableExpr::Call(call) => {
let expr = call.expr()?;
sema.type_of_expr(&expr)?.adjusted().as_callable(sema.db)
@@ -66,13 +67,78 @@ pub fn callable_for_node(
ast::CallableExpr::MethodCall(call) => sema.resolve_method_call_as_callable(call),
}?;
let active_param = if let Some(arg_list) = calling_node.arg_list() {
- let param = arg_list
- .args()
- .take_while(|arg| arg.syntax().text_range().end() <= token.text_range().start())
- .count();
- Some(param)
+ Some(
+ arg_list
+ .syntax()
+ .children_with_tokens()
+ .filter_map(NodeOrToken::into_token)
+ .filter(|t| t.kind() == T![,])
+ .take_while(|t| t.text_range().start() <= token.text_range().start())
+ .count(),
+ )
} else {
None
};
Some((callable, active_param))
}
+
+pub fn generic_def_for_node(
+ sema: &Semantics<'_, RootDatabase>,
+ generic_arg_list: &ast::GenericArgList,
+ token: &SyntaxToken,
+) -> Option<(hir::GenericDef, usize, bool)> {
+ let parent = generic_arg_list.syntax().parent()?;
+ let def = match_ast! {
+ match parent {
+ ast::PathSegment(ps) => {
+ let res = sema.resolve_path(&ps.parent_path())?;
+ let generic_def: hir::GenericDef = match res {
+ hir::PathResolution::Def(hir::ModuleDef::Adt(it)) => it.into(),
+ hir::PathResolution::Def(hir::ModuleDef::Function(it)) => it.into(),
+ hir::PathResolution::Def(hir::ModuleDef::Trait(it)) => it.into(),
+ hir::PathResolution::Def(hir::ModuleDef::TypeAlias(it)) => it.into(),
+ hir::PathResolution::Def(hir::ModuleDef::Variant(it)) => it.into(),
+ hir::PathResolution::Def(hir::ModuleDef::BuiltinType(_))
+ | hir::PathResolution::Def(hir::ModuleDef::Const(_))
+ | hir::PathResolution::Def(hir::ModuleDef::Macro(_))
+ | hir::PathResolution::Def(hir::ModuleDef::Module(_))
+ | hir::PathResolution::Def(hir::ModuleDef::Static(_)) => return None,
+ hir::PathResolution::BuiltinAttr(_)
+ | hir::PathResolution::ToolModule(_)
+ | hir::PathResolution::Local(_)
+ | hir::PathResolution::TypeParam(_)
+ | hir::PathResolution::ConstParam(_)
+ | hir::PathResolution::SelfType(_)
+ | hir::PathResolution::DeriveHelper(_) => return None,
+ };
+
+ generic_def
+ },
+ ast::AssocTypeArg(_) => {
+ // FIXME: We don't record the resolutions for this anywhere atm
+ return None;
+ },
+ ast::MethodCallExpr(mcall) => {
+ // recv.method::<$0>()
+ let method = sema.resolve_method_call(&mcall)?;
+ method.into()
+ },
+ _ => return None,
+ }
+ };
+
+ let active_param = generic_arg_list
+ .syntax()
+ .children_with_tokens()
+ .filter_map(NodeOrToken::into_token)
+ .filter(|t| t.kind() == T![,])
+ .take_while(|t| t.text_range().start() <= token.text_range().start())
+ .count();
+
+ let first_arg_is_non_lifetime = generic_arg_list
+ .generic_args()
+ .next()
+ .map_or(false, |arg| !matches!(arg, ast::GenericArg::LifetimeArg(_)));
+
+ Some((def, active_param, first_arg_is_non_lifetime))
+}
diff --git a/src/tools/rust-analyzer/crates/ide-db/src/defs.rs b/src/tools/rust-analyzer/crates/ide-db/src/defs.rs
index 6c13c0397..ed7f04fd8 100644
--- a/src/tools/rust-analyzer/crates/ide-db/src/defs.rs
+++ b/src/tools/rust-analyzer/crates/ide-db/src/defs.rs
@@ -34,8 +34,8 @@ pub enum Definition {
TypeAlias(TypeAlias),
BuiltinType(BuiltinType),
SelfType(Impl),
- Local(Local),
GenericParam(GenericParam),
+ Local(Local),
Label(Label),
DeriveHelper(DeriveHelper),
BuiltinAttr(BuiltinAttr),
diff --git a/src/tools/rust-analyzer/crates/ide-db/src/line_index.rs b/src/tools/rust-analyzer/crates/ide-db/src/line_index.rs
index 1b8f56187..16814a1e6 100644
--- a/src/tools/rust-analyzer/crates/ide-db/src/line_index.rs
+++ b/src/tools/rust-analyzer/crates/ide-db/src/line_index.rs
@@ -7,56 +7,72 @@ use syntax::{TextRange, TextSize};
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct LineIndex {
- /// Offset the the beginning of each line, zero-based
+ /// Offset the beginning of each line, zero-based.
pub(crate) newlines: Vec<TextSize>,
- /// List of non-ASCII characters on each line
- pub(crate) utf16_lines: NoHashHashMap<u32, Vec<Utf16Char>>,
+ /// List of non-ASCII characters on each line.
+ pub(crate) line_wide_chars: NoHashHashMap<u32, Vec<WideChar>>,
}
+/// Line/Column information in native, utf8 format.
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
-pub struct LineColUtf16 {
+pub struct LineCol {
/// Zero-based
pub line: u32,
- /// Zero-based
+ /// Zero-based utf8 offset
pub col: u32,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
-pub struct LineCol {
+pub enum WideEncoding {
+ Utf16,
+ Utf32,
+}
+
+/// Line/Column information in legacy encodings.
+///
+/// Deliberately not a generic type and different from `LineCol`.
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
+pub struct WideLineCol {
/// Zero-based
pub line: u32,
- /// Zero-based utf8 offset
+ /// Zero-based
pub col: u32,
}
#[derive(Clone, Debug, Hash, PartialEq, Eq)]
-pub(crate) struct Utf16Char {
+pub(crate) struct WideChar {
/// Start offset of a character inside a line, zero-based
pub(crate) start: TextSize,
/// End offset of a character inside a line, zero-based
pub(crate) end: TextSize,
}
-impl Utf16Char {
+impl WideChar {
/// Returns the length in 8-bit UTF-8 code units.
fn len(&self) -> TextSize {
self.end - self.start
}
- /// Returns the length in 16-bit UTF-16 code units.
- fn len_utf16(&self) -> usize {
- if self.len() == TextSize::from(4) {
- 2
- } else {
- 1
+ /// Returns the length in UTF-16 or UTF-32 code units.
+ fn wide_len(&self, enc: WideEncoding) -> usize {
+ match enc {
+ WideEncoding::Utf16 => {
+ if self.len() == TextSize::from(4) {
+ 2
+ } else {
+ 1
+ }
+ }
+
+ WideEncoding::Utf32 => 1,
}
}
}
impl LineIndex {
pub fn new(text: &str) -> LineIndex {
- let mut utf16_lines = NoHashHashMap::default();
- let mut utf16_chars = Vec::new();
+ let mut line_wide_chars = NoHashHashMap::default();
+ let mut wide_chars = Vec::new();
let mut newlines = Vec::with_capacity(16);
newlines.push(TextSize::from(0));
@@ -71,8 +87,8 @@ impl LineIndex {
newlines.push(curr_row);
// Save any utf-16 characters seen in the previous line
- if !utf16_chars.is_empty() {
- utf16_lines.insert(line, mem::take(&mut utf16_chars));
+ if !wide_chars.is_empty() {
+ line_wide_chars.insert(line, mem::take(&mut wide_chars));
}
// Prepare for processing the next line
@@ -82,18 +98,18 @@ impl LineIndex {
}
if !c.is_ascii() {
- utf16_chars.push(Utf16Char { start: curr_col, end: curr_col + c_len });
+ wide_chars.push(WideChar { start: curr_col, end: curr_col + c_len });
}
curr_col += c_len;
}
// Save any utf-16 characters seen in the last line
- if !utf16_chars.is_empty() {
- utf16_lines.insert(line, utf16_chars);
+ if !wide_chars.is_empty() {
+ line_wide_chars.insert(line, wide_chars);
}
- LineIndex { newlines, utf16_lines }
+ LineIndex { newlines, line_wide_chars }
}
pub fn line_col(&self, offset: TextSize) -> LineCol {
@@ -109,13 +125,13 @@ impl LineIndex {
.map(|offset| offset + TextSize::from(line_col.col))
}
- pub fn to_utf16(&self, line_col: LineCol) -> LineColUtf16 {
- let col = self.utf8_to_utf16_col(line_col.line, line_col.col.into());
- LineColUtf16 { line: line_col.line, col: col as u32 }
+ pub fn to_wide(&self, enc: WideEncoding, line_col: LineCol) -> WideLineCol {
+ let col = self.utf8_to_wide_col(enc, line_col.line, line_col.col.into());
+ WideLineCol { line: line_col.line, col: col as u32 }
}
- pub fn to_utf8(&self, line_col: LineColUtf16) -> LineCol {
- let col = self.utf16_to_utf8_col(line_col.line, line_col.col);
+ pub fn to_utf8(&self, enc: WideEncoding, line_col: WideLineCol) -> LineCol {
+ let col = self.wide_to_utf8_col(enc, line_col.line, line_col.col);
LineCol { line: line_col.line, col: col.into() }
}
@@ -132,12 +148,12 @@ impl LineIndex {
.filter(|it| !it.is_empty())
}
- fn utf8_to_utf16_col(&self, line: u32, col: TextSize) -> usize {
+ fn utf8_to_wide_col(&self, enc: WideEncoding, line: u32, col: TextSize) -> usize {
let mut res: usize = col.into();
- if let Some(utf16_chars) = self.utf16_lines.get(&line) {
- for c in utf16_chars {
+ if let Some(wide_chars) = self.line_wide_chars.get(&line) {
+ for c in wide_chars {
if c.end <= col {
- res -= usize::from(c.len()) - c.len_utf16();
+ res -= usize::from(c.len()) - c.wide_len(enc);
} else {
// From here on, all utf16 characters come *after* the character we are mapping,
// so we don't need to take them into account
@@ -148,11 +164,11 @@ impl LineIndex {
res
}
- fn utf16_to_utf8_col(&self, line: u32, mut col: u32) -> TextSize {
- if let Some(utf16_chars) = self.utf16_lines.get(&line) {
- for c in utf16_chars {
+ fn wide_to_utf8_col(&self, enc: WideEncoding, line: u32, mut col: u32) -> TextSize {
+ if let Some(wide_chars) = self.line_wide_chars.get(&line) {
+ for c in wide_chars {
if col > u32::from(c.start) {
- col += u32::from(c.len()) - c.len_utf16() as u32;
+ col += u32::from(c.len()) - c.wide_len(enc) as u32;
} else {
// From here on, all utf16 characters come *after* the character we are mapping,
// so we don't need to take them into account
@@ -167,6 +183,9 @@ impl LineIndex {
#[cfg(test)]
mod tests {
+ use test_utils::skip_slow_tests;
+
+ use super::WideEncoding::{Utf16, Utf32};
use super::*;
#[test]
@@ -185,14 +204,14 @@ mod tests {
];
let index = LineIndex::new(text);
- for &(offset, line, col) in &table {
+ for (offset, line, col) in table {
assert_eq!(index.line_col(offset.into()), LineCol { line, col });
}
let text = "\nhello\nworld";
let table = [(0, 0, 0), (1, 1, 0), (2, 1, 1), (6, 1, 5), (7, 2, 0)];
let index = LineIndex::new(text);
- for &(offset, line, col) in &table {
+ for (offset, line, col) in table {
assert_eq!(index.line_col(offset.into()), LineCol { line, col });
}
}
@@ -210,67 +229,59 @@ mod tests {
const C: char = 'x';
",
);
- assert_eq!(col_index.utf16_lines.len(), 0);
+ assert_eq!(col_index.line_wide_chars.len(), 0);
}
#[test]
- fn test_single_char() {
- let col_index = LineIndex::new(
- "
-const C: char = 'メ';
-",
- );
-
- assert_eq!(col_index.utf16_lines.len(), 1);
- assert_eq!(col_index.utf16_lines[&1].len(), 1);
- assert_eq!(col_index.utf16_lines[&1][0], Utf16Char { start: 17.into(), end: 20.into() });
-
- // UTF-8 to UTF-16, no changes
- assert_eq!(col_index.utf8_to_utf16_col(1, 15.into()), 15);
-
- // UTF-8 to UTF-16
- assert_eq!(col_index.utf8_to_utf16_col(1, 22.into()), 20);
-
- // UTF-16 to UTF-8, no changes
- assert_eq!(col_index.utf16_to_utf8_col(1, 15), TextSize::from(15));
-
- // UTF-16 to UTF-8
- assert_eq!(col_index.utf16_to_utf8_col(1, 19), TextSize::from(21));
-
- let col_index = LineIndex::new("a𐐏b");
- assert_eq!(col_index.utf16_to_utf8_col(0, 3), TextSize::from(5));
- }
-
- #[test]
- fn test_string() {
- let col_index = LineIndex::new(
- "
-const C: char = \"メ メ\";
-",
- );
-
- assert_eq!(col_index.utf16_lines.len(), 1);
- assert_eq!(col_index.utf16_lines[&1].len(), 2);
- assert_eq!(col_index.utf16_lines[&1][0], Utf16Char { start: 17.into(), end: 20.into() });
- assert_eq!(col_index.utf16_lines[&1][1], Utf16Char { start: 21.into(), end: 24.into() });
-
- // UTF-8 to UTF-16
- assert_eq!(col_index.utf8_to_utf16_col(1, 15.into()), 15);
-
- assert_eq!(col_index.utf8_to_utf16_col(1, 21.into()), 19);
- assert_eq!(col_index.utf8_to_utf16_col(1, 25.into()), 21);
-
- assert!(col_index.utf8_to_utf16_col(2, 15.into()) == 15);
-
- // UTF-16 to UTF-8
- assert_eq!(col_index.utf16_to_utf8_col(1, 15), TextSize::from(15));
+ fn test_every_chars() {
+ if skip_slow_tests() {
+ return;
+ }
- // メ UTF-8: 0xE3 0x83 0xA1, UTF-16: 0x30E1
- assert_eq!(col_index.utf16_to_utf8_col(1, 17), TextSize::from(17)); // first メ at 17..20
- assert_eq!(col_index.utf16_to_utf8_col(1, 18), TextSize::from(20)); // space
- assert_eq!(col_index.utf16_to_utf8_col(1, 19), TextSize::from(21)); // second メ at 21..24
+ let text: String = {
+ let mut chars: Vec<char> = ((0 as char)..char::MAX).collect(); // Neat!
+ chars.extend("\n".repeat(chars.len() / 16).chars());
+ let mut rng = oorandom::Rand32::new(stdx::rand::seed());
+ stdx::rand::shuffle(&mut chars, |i| rng.rand_range(0..i as u32) as usize);
+ chars.into_iter().collect()
+ };
+ assert!(text.contains('💩')); // Sanity check.
+
+ let line_index = LineIndex::new(&text);
+
+ let mut lin_col = LineCol { line: 0, col: 0 };
+ let mut col_utf16 = 0;
+ let mut col_utf32 = 0;
+ for (offset, c) in text.char_indices() {
+ let got_offset = line_index.offset(lin_col).unwrap();
+ assert_eq!(usize::from(got_offset), offset);
+
+ let got_lin_col = line_index.line_col(got_offset);
+ assert_eq!(got_lin_col, lin_col);
+
+ for enc in [Utf16, Utf32] {
+ let wide_lin_col = line_index.to_wide(enc, lin_col);
+ let got_lin_col = line_index.to_utf8(enc, wide_lin_col);
+ assert_eq!(got_lin_col, lin_col);
+
+ let want_col = match enc {
+ Utf16 => col_utf16,
+ Utf32 => col_utf32,
+ };
+ assert_eq!(wide_lin_col.col, want_col)
+ }
- assert_eq!(col_index.utf16_to_utf8_col(2, 15), TextSize::from(15));
+ if c == '\n' {
+ lin_col.line += 1;
+ lin_col.col = 0;
+ col_utf16 = 0;
+ col_utf32 = 0;
+ } else {
+ lin_col.col += c.len_utf8() as u32;
+ col_utf16 += c.len_utf16() as u32;
+ col_utf32 += 1;
+ }
+ }
}
#[test]
diff --git a/src/tools/rust-analyzer/crates/ide-db/src/path_transform.rs b/src/tools/rust-analyzer/crates/ide-db/src/path_transform.rs
index 12d873b4a..6402a84a6 100644
--- a/src/tools/rust-analyzer/crates/ide-db/src/path_transform.rs
+++ b/src/tools/rust-analyzer/crates/ide-db/src/path_transform.rs
@@ -33,7 +33,7 @@ use syntax::{
/// }
/// ```
pub struct PathTransform<'a> {
- generic_def: hir::GenericDef,
+ generic_def: Option<hir::GenericDef>,
substs: Vec<ast::Type>,
target_scope: &'a SemanticsScope<'a>,
source_scope: &'a SemanticsScope<'a>,
@@ -49,7 +49,7 @@ impl<'a> PathTransform<'a> {
PathTransform {
source_scope,
target_scope,
- generic_def: trait_.into(),
+ generic_def: Some(trait_.into()),
substs: get_syntactic_substs(impl_).unwrap_or_default(),
}
}
@@ -63,28 +63,42 @@ impl<'a> PathTransform<'a> {
PathTransform {
source_scope,
target_scope,
- generic_def: function.into(),
+ generic_def: Some(function.into()),
substs: get_type_args_from_arg_list(generic_arg_list).unwrap_or_default(),
}
}
+ pub fn generic_transformation(
+ target_scope: &'a SemanticsScope<'a>,
+ source_scope: &'a SemanticsScope<'a>,
+ ) -> PathTransform<'a> {
+ PathTransform { source_scope, target_scope, generic_def: None, substs: Vec::new() }
+ }
+
pub fn apply(&self, syntax: &SyntaxNode) {
self.build_ctx().apply(syntax)
}
+ pub fn apply_all<'b>(&self, nodes: impl IntoIterator<Item = &'b SyntaxNode>) {
+ let ctx = self.build_ctx();
+ for node in nodes {
+ ctx.apply(node);
+ }
+ }
+
fn build_ctx(&self) -> Ctx<'a> {
let db = self.source_scope.db;
let target_module = self.target_scope.module();
let source_module = self.source_scope.module();
let skip = match self.generic_def {
// this is a trait impl, so we need to skip the first type parameter -- this is a bit hacky
- hir::GenericDef::Trait(_) => 1,
+ Some(hir::GenericDef::Trait(_)) => 1,
_ => 0,
};
let substs_by_param: FxHashMap<_, _> = self
.generic_def
- .type_params(db)
.into_iter()
+ .flat_map(|it| it.type_params(db))
.skip(skip)
// The actual list of trait type parameters may be longer than the one
// used in the `impl` block due to trailing default type parameters.
diff --git a/src/tools/rust-analyzer/crates/ide-db/src/rename.rs b/src/tools/rust-analyzer/crates/ide-db/src/rename.rs
index cd4a7e155..84d70b258 100644
--- a/src/tools/rust-analyzer/crates/ide-db/src/rename.rs
+++ b/src/tools/rust-analyzer/crates/ide-db/src/rename.rs
@@ -190,6 +190,7 @@ fn rename_mod(
let InFile { file_id, value: def_source } = module.definition_source(sema.db);
if let ModuleSource::SourceFile(..) = def_source {
+ let new_name = new_name.trim_start_matches("r#");
let anchor = file_id.original_file(sema.db);
let is_mod_rs = module.is_mod_rs(sema.db);
@@ -207,9 +208,13 @@ fn rename_mod(
// - Module has submodules defined in separate files
let dir_paths = match (is_mod_rs, has_detached_child, module.name(sema.db)) {
// Go up one level since the anchor is inside the dir we're trying to rename
- (true, _, Some(mod_name)) => Some((format!("../{mod_name}"), format!("../{new_name}"))),
+ (true, _, Some(mod_name)) => {
+ Some((format!("../{}", mod_name.unescaped()), format!("../{new_name}")))
+ }
// The anchor is on the same level as target dir
- (false, true, Some(mod_name)) => Some((mod_name.to_string(), new_name.to_string())),
+ (false, true, Some(mod_name)) => {
+ Some((mod_name.unescaped().to_string(), new_name.to_string()))
+ }
_ => None,
};
@@ -263,11 +268,10 @@ fn rename_reference(
Definition::GenericParam(hir::GenericParam::LifetimeParam(_)) | Definition::Label(_)
) {
match ident_kind {
- IdentifierKind::Ident | IdentifierKind::Underscore => {
- cov_mark::hit!(rename_not_a_lifetime_ident_ref);
+ IdentifierKind::Underscore => {
bail!("Invalid name `{}`: not a lifetime identifier", new_name);
}
- IdentifierKind::Lifetime => cov_mark::hit!(rename_lifetime),
+ _ => cov_mark::hit!(rename_lifetime),
}
} else {
match ident_kind {
@@ -334,11 +338,17 @@ pub fn source_edit_from_references(
}
_ => false,
};
- if !has_emitted_edit {
- if !edited_ranges.contains(&range.start()) {
- edit.replace(range, new_name.to_string());
- edited_ranges.push(range.start());
- }
+ if !has_emitted_edit && !edited_ranges.contains(&range.start()) {
+ let (range, new_name) = match name {
+ ast::NameLike::Lifetime(_) => (
+ TextRange::new(range.start() + syntax::TextSize::from(1), range.end()),
+ new_name.strip_prefix('\'').unwrap_or(new_name).to_owned(),
+ ),
+ _ => (range, new_name.to_owned()),
+ };
+
+ edit.replace(range, new_name);
+ edited_ranges.push(range.start());
}
}
@@ -391,19 +401,17 @@ fn source_edit_from_name_ref(
edit.delete(TextRange::new(s, e));
return true;
}
- } else if init == name_ref {
- if field_name.text() == new_name {
- cov_mark::hit!(test_rename_local_put_init_shorthand);
- // Foo { field: local } -> Foo { field }
- // ^^^^^^^ delete this
-
- // same names, we can use a shorthand here instead.
- // we do not want to erase attributes hence this range start
- let s = field_name.syntax().text_range().end();
- let e = init.syntax().text_range().end();
- edit.delete(TextRange::new(s, e));
- return true;
- }
+ } else if init == name_ref && field_name.text() == new_name {
+ cov_mark::hit!(test_rename_local_put_init_shorthand);
+ // Foo { field: local } -> Foo { field }
+ // ^^^^^^^ delete this
+
+ // same names, we can use a shorthand here instead.
+ // we do not want to erase attributes hence this range start
+ let s = field_name.syntax().text_range().end();
+ let e = init.syntax().text_range().end();
+ edit.delete(TextRange::new(s, e));
+ return true;
}
}
// init shorthand
@@ -505,7 +513,15 @@ fn source_edit_from_def(
}
}
if edit.is_empty() {
- edit.replace(range, new_name.to_string());
+ let (range, new_name) = match def {
+ Definition::GenericParam(hir::GenericParam::LifetimeParam(_))
+ | Definition::Label(_) => (
+ TextRange::new(range.start() + syntax::TextSize::from(1), range.end()),
+ new_name.strip_prefix('\'').unwrap_or(new_name).to_owned(),
+ ),
+ _ => (range, new_name.to_owned()),
+ };
+ edit.replace(range, new_name);
}
Ok((file_id, edit.finish()))
}
@@ -521,14 +537,18 @@ impl IdentifierKind {
pub fn classify(new_name: &str) -> Result<IdentifierKind> {
match parser::LexedStr::single_token(new_name) {
Some(res) => match res {
- (SyntaxKind::IDENT, _) => Ok(IdentifierKind::Ident),
+ (SyntaxKind::IDENT, _) => {
+ if let Some(inner) = new_name.strip_prefix("r#") {
+ if matches!(inner, "self" | "crate" | "super" | "Self") {
+ bail!("Invalid name: `{}` cannot be a raw identifier", inner);
+ }
+ }
+ Ok(IdentifierKind::Ident)
+ }
(T![_], _) => Ok(IdentifierKind::Underscore),
(SyntaxKind::LIFETIME_IDENT, _) if new_name != "'static" && new_name != "'_" => {
Ok(IdentifierKind::Lifetime)
}
- (SyntaxKind::LIFETIME_IDENT, _) => {
- bail!("Invalid name `{}`: not a lifetime identifier", new_name)
- }
(_, Some(syntax_error)) => bail!("Invalid name `{}`: {}", new_name, syntax_error),
(_, None) => bail!("Invalid name `{}`: not an identifier", new_name),
},
diff --git a/src/tools/rust-analyzer/crates/ide-db/src/search.rs b/src/tools/rust-analyzer/crates/ide-db/src/search.rs
index b2b0e4908..c18a27f17 100644
--- a/src/tools/rust-analyzer/crates/ide-db/src/search.rs
+++ b/src/tools/rust-analyzer/crates/ide-db/src/search.rs
@@ -7,7 +7,9 @@
use std::{mem, sync::Arc};
use base_db::{FileId, FileRange, SourceDatabase, SourceDatabaseExt};
-use hir::{DefWithBody, HasAttrs, HasSource, InFile, ModuleSource, Semantics, Visibility};
+use hir::{
+ AsAssocItem, DefWithBody, HasAttrs, HasSource, InFile, ModuleSource, Semantics, Visibility,
+};
use memchr::memmem::Finder;
use once_cell::unsync::Lazy;
use parser::SyntaxKind;
@@ -311,15 +313,15 @@ impl Definition {
pub fn usages<'a>(self, sema: &'a Semantics<'_, RootDatabase>) -> FindUsages<'a> {
FindUsages {
- local_repr: match self {
- Definition::Local(local) => Some(local.representative(sema.db)),
- _ => None,
- },
def: self,
- trait_assoc_def: as_trait_assoc_def(sema.db, self),
+ assoc_item_container: self.as_assoc_item(sema.db).map(|a| a.container(sema.db)),
sema,
scope: None,
include_self_kw_refs: None,
+ local_repr: match self {
+ Definition::Local(local) => Some(local.representative(sema.db)),
+ _ => None,
+ },
search_self_mod: false,
}
}
@@ -328,12 +330,16 @@ impl Definition {
#[derive(Clone)]
pub struct FindUsages<'a> {
def: Definition,
- /// If def is an assoc item from a trait or trait impl, this is the corresponding item of the trait definition
- trait_assoc_def: Option<Definition>,
sema: &'a Semantics<'a, RootDatabase>,
scope: Option<SearchScope>,
+ /// The container of our definition should it be an assoc item
+ assoc_item_container: Option<hir::AssocItemContainer>,
+ /// whether to search for the `Self` type of the definition
include_self_kw_refs: Option<hir::Type>,
+ /// the local representative for the local definition we are searching for
+ /// (this is required for finding all local declarations in a or-pattern)
local_repr: Option<hir::Local>,
+ /// whether to search for the `self` module
search_self_mod: bool,
}
@@ -380,7 +386,9 @@ impl<'a> FindUsages<'a> {
let sema = self.sema;
let search_scope = {
- let base = self.trait_assoc_def.unwrap_or(self.def).search_scope(sema.db);
+ // FIXME: Is the trait scope needed for trait impl assoc items?
+ let base =
+ as_trait_assoc_def(sema.db, self.def).unwrap_or(self.def).search_scope(sema.db);
match &self.scope {
None => base,
Some(scope) => base.intersection(scope),
@@ -447,15 +455,21 @@ impl<'a> FindUsages<'a> {
}
let find_nodes = move |name: &str, node: &syntax::SyntaxNode, offset: TextSize| {
- node.token_at_offset(offset).find(|it| it.text() == name).map(|token| {
- // FIXME: There should be optimization potential here
- // Currently we try to descend everything we find which
- // means we call `Semantics::descend_into_macros` on
- // every textual hit. That function is notoriously
- // expensive even for things that do not get down mapped
- // into macros.
- sema.descend_into_macros(token).into_iter().filter_map(|it| it.parent())
- })
+ node.token_at_offset(offset)
+ .find(|it| {
+ // `name` is stripped of raw ident prefix. See the comment on name retrieval above.
+ it.text().trim_start_matches("r#") == name
+ })
+ .into_iter()
+ .flat_map(|token| {
+ // FIXME: There should be optimization potential here
+ // Currently we try to descend everything we find which
+ // means we call `Semantics::descend_into_macros` on
+ // every textual hit. That function is notoriously
+ // expensive even for things that do not get down mapped
+ // into macros.
+ sema.descend_into_macros(token).into_iter().filter_map(|it| it.parent())
+ })
};
for (text, file_id, search_range) in scope_files(sema, &search_scope) {
@@ -463,30 +477,23 @@ impl<'a> FindUsages<'a> {
// Search for occurrences of the items name
for offset in match_indices(&text, finder, search_range) {
- if let Some(iter) = find_nodes(name, &tree, offset) {
- for name in iter.filter_map(ast::NameLike::cast) {
- if match name {
- ast::NameLike::NameRef(name_ref) => {
- self.found_name_ref(&name_ref, sink)
- }
- ast::NameLike::Name(name) => self.found_name(&name, sink),
- ast::NameLike::Lifetime(lifetime) => {
- self.found_lifetime(&lifetime, sink)
- }
- } {
- return;
- }
+ for name in find_nodes(name, &tree, offset).filter_map(ast::NameLike::cast) {
+ if match name {
+ ast::NameLike::NameRef(name_ref) => self.found_name_ref(&name_ref, sink),
+ ast::NameLike::Name(name) => self.found_name(&name, sink),
+ ast::NameLike::Lifetime(lifetime) => self.found_lifetime(&lifetime, sink),
+ } {
+ return;
}
}
}
// Search for occurrences of the `Self` referring to our type
if let Some((self_ty, finder)) = &include_self_kw_refs {
for offset in match_indices(&text, finder, search_range) {
- if let Some(iter) = find_nodes("Self", &tree, offset) {
- for name_ref in iter.filter_map(ast::NameRef::cast) {
- if self.found_self_ty_name_ref(self_ty, &name_ref, sink) {
- return;
- }
+ for name_ref in find_nodes("Self", &tree, offset).filter_map(ast::NameRef::cast)
+ {
+ if self.found_self_ty_name_ref(self_ty, &name_ref, sink) {
+ return;
}
}
}
@@ -494,41 +501,37 @@ impl<'a> FindUsages<'a> {
}
// Search for `super` and `crate` resolving to our module
- match self.def {
- Definition::Module(module) => {
- let scope = search_scope
- .intersection(&SearchScope::module_and_children(self.sema.db, module));
+ if let Definition::Module(module) = self.def {
+ let scope =
+ search_scope.intersection(&SearchScope::module_and_children(self.sema.db, module));
- let is_crate_root =
- module.is_crate_root(self.sema.db).then(|| Finder::new("crate"));
- let finder = &Finder::new("super");
+ let is_crate_root = module.is_crate_root(self.sema.db).then(|| Finder::new("crate"));
+ let finder = &Finder::new("super");
- for (text, file_id, search_range) in scope_files(sema, &scope) {
- let tree = Lazy::new(move || sema.parse(file_id).syntax().clone());
+ for (text, file_id, search_range) in scope_files(sema, &scope) {
+ let tree = Lazy::new(move || sema.parse(file_id).syntax().clone());
- for offset in match_indices(&text, finder, search_range) {
- if let Some(iter) = find_nodes("super", &tree, offset) {
- for name_ref in iter.filter_map(ast::NameRef::cast) {
- if self.found_name_ref(&name_ref, sink) {
- return;
- }
- }
+ for offset in match_indices(&text, finder, search_range) {
+ for name_ref in
+ find_nodes("super", &tree, offset).filter_map(ast::NameRef::cast)
+ {
+ if self.found_name_ref(&name_ref, sink) {
+ return;
}
}
- if let Some(finder) = &is_crate_root {
- for offset in match_indices(&text, finder, search_range) {
- if let Some(iter) = find_nodes("crate", &tree, offset) {
- for name_ref in iter.filter_map(ast::NameRef::cast) {
- if self.found_name_ref(&name_ref, sink) {
- return;
- }
- }
+ }
+ if let Some(finder) = &is_crate_root {
+ for offset in match_indices(&text, finder, search_range) {
+ for name_ref in
+ find_nodes("crate", &tree, offset).filter_map(ast::NameRef::cast)
+ {
+ if self.found_name_ref(&name_ref, sink) {
+ return;
}
}
}
}
}
- _ => (),
}
// search for module `self` references in our module's definition source
@@ -562,11 +565,10 @@ impl<'a> FindUsages<'a> {
let finder = &Finder::new("self");
for offset in match_indices(&text, finder, search_range) {
- if let Some(iter) = find_nodes("self", &tree, offset) {
- for name_ref in iter.filter_map(ast::NameRef::cast) {
- if self.found_self_module_name_ref(&name_ref, sink) {
- return;
- }
+ for name_ref in find_nodes("self", &tree, offset).filter_map(ast::NameRef::cast)
+ {
+ if self.found_self_module_name_ref(&name_ref, sink) {
+ return;
}
}
}
@@ -655,13 +657,26 @@ impl<'a> FindUsages<'a> {
sink(file_id, reference)
}
Some(NameRefClass::Definition(def))
- if match self.trait_assoc_def {
- Some(trait_assoc_def) => {
- // we have a trait assoc item, so force resolve all assoc items to their trait version
- convert_to_def_in_trait(self.sema.db, def) == trait_assoc_def
- }
- None => self.def == def,
- } =>
+ if self.def == def
+ // is our def a trait assoc item? then we want to find all assoc items from trait impls of our trait
+ || matches!(self.assoc_item_container, Some(hir::AssocItemContainer::Trait(_)))
+ && convert_to_def_in_trait(self.sema.db, def) == self.def =>
+ {
+ let FileRange { file_id, range } = self.sema.original_range(name_ref.syntax());
+ let reference = FileReference {
+ range,
+ name: ast::NameLike::NameRef(name_ref.clone()),
+ category: ReferenceCategory::new(&def, name_ref),
+ };
+ sink(file_id, reference)
+ }
+ // FIXME: special case type aliases, we can't filter between impl and trait defs here as we lack the substitutions
+ // so we always resolve all assoc type aliases to both their trait def and impl defs
+ Some(NameRefClass::Definition(def))
+ if self.assoc_item_container.is_some()
+ && matches!(self.def, Definition::TypeAlias(_))
+ && convert_to_def_in_trait(self.sema.db, def)
+ == convert_to_def_in_trait(self.sema.db, self.def) =>
{
let FileRange { file_id, range } = self.sema.original_range(name_ref.syntax());
let reference = FileReference {
@@ -752,13 +767,21 @@ impl<'a> FindUsages<'a> {
false
}
Some(NameClass::Definition(def)) if def != self.def => {
- // if the def we are looking for is a trait (impl) assoc item, we'll have to resolve the items to trait definition assoc item
- if !matches!(
- self.trait_assoc_def,
- Some(trait_assoc_def)
- if convert_to_def_in_trait(self.sema.db, def) == trait_assoc_def
- ) {
- return false;
+ match (&self.assoc_item_container, self.def) {
+ // for type aliases we always want to reference the trait def and all the trait impl counterparts
+ // FIXME: only until we can resolve them correctly, see FIXME above
+ (Some(_), Definition::TypeAlias(_))
+ if convert_to_def_in_trait(self.sema.db, def)
+ != convert_to_def_in_trait(self.sema.db, self.def) =>
+ {
+ return false
+ }
+ (Some(_), Definition::TypeAlias(_)) => {}
+ // We looking at an assoc item of a trait definition, so reference all the
+ // corresponding assoc items belonging to this trait's trait implementations
+ (Some(hir::AssocItemContainer::Trait(_)), _)
+ if convert_to_def_in_trait(self.sema.db, def) == self.def => {}
+ _ => return false,
}
let FileRange { file_id, range } = self.sema.original_range(name.syntax());
let reference = FileReference {
diff --git a/src/tools/rust-analyzer/crates/ide-db/src/symbol_index.rs b/src/tools/rust-analyzer/crates/ide-db/src/symbol_index.rs
index c054cc159..a91ffd1ec 100644
--- a/src/tools/rust-analyzer/crates/ide-db/src/symbol_index.rs
+++ b/src/tools/rust-analyzer/crates/ide-db/src/symbol_index.rs
@@ -323,10 +323,10 @@ impl Query {
if symbol.name != self.query {
continue;
}
- } else if self.case_sensitive {
- if self.query.chars().any(|c| !symbol.name.contains(c)) {
- continue;
- }
+ } else if self.case_sensitive
+ && self.query.chars().any(|c| !symbol.name.contains(c))
+ {
+ continue;
}
res.push(symbol.clone());
diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/Cargo.toml b/src/tools/rust-analyzer/crates/ide-diagnostics/Cargo.toml
index 7e9a1125d..e18624fcc 100644
--- a/src/tools/rust-analyzer/crates/ide-diagnostics/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/ide-diagnostics/Cargo.toml
@@ -2,9 +2,11 @@
name = "ide-diagnostics"
version = "0.0.0"
description = "TBD"
-license = "MIT OR Apache-2.0"
-edition = "2021"
-rust-version = "1.65"
+
+authors.workspace = true
+edition.workspace = true
+license.workspace = true
+rust-version.workspace = true
[lib]
doctest = false
@@ -15,19 +17,21 @@ either = "1.7.0"
itertools = "0.10.5"
serde_json = "1.0.86"
-profile = { path = "../profile", version = "0.0.0" }
-stdx = { path = "../stdx", version = "0.0.0" }
-syntax = { path = "../syntax", version = "0.0.0" }
-text-edit = { path = "../text-edit", version = "0.0.0" }
-cfg = { path = "../cfg", version = "0.0.0" }
-hir = { path = "../hir", version = "0.0.0" }
-ide-db = { path = "../ide-db", version = "0.0.0" }
+# local deps
+profile.workspace = true
+stdx.workspace = true
+syntax.workspace = true
+text-edit.workspace = true
+cfg.workspace = true
+hir.workspace = true
+ide-db.workspace = true
[dev-dependencies]
expect-test = "1.4.0"
-test-utils = { path = "../test-utils" }
-sourcegen = { path = "../sourcegen" }
+# local deps
+test-utils.workspace = true
+sourcegen.workspace = true
[features]
in-rust-tree = []
diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/json_is_not_rust.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/json_is_not_rust.rs
index e8df6dcf2..04ce1e0fe 100644
--- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/json_is_not_rust.rs
+++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/json_is_not_rust.rs
@@ -99,76 +99,66 @@ pub(crate) fn json_in_items(
&& node.last_token().map(|x| x.kind()) == Some(SyntaxKind::R_CURLY)
{
let node_string = node.to_string();
- if let Ok(it) = serde_json::from_str(&node_string) {
- if let serde_json::Value::Object(it) = it {
- let import_scope = ImportScope::find_insert_use_container(node, sema)?;
- let range = node.text_range();
- let mut edit = TextEdit::builder();
- edit.delete(range);
- let mut state = State::default();
- let semantics_scope = sema.scope(node)?;
- let scope_resolve =
- |it| semantics_scope.speculative_resolve(&make::path_from_text(it));
- let scope_has = |it| scope_resolve(it).is_some();
- let deserialize_resolved = scope_resolve("::serde::Deserialize");
- let serialize_resolved = scope_resolve("::serde::Serialize");
- state.has_deserialize = deserialize_resolved.is_some();
- state.has_serialize = serialize_resolved.is_some();
- state.build_struct(&it);
- edit.insert(range.start(), state.result);
- acc.push(
- Diagnostic::new(
- "json-is-not-rust",
- "JSON syntax is not valid as a Rust item",
- range,
- )
- .severity(Severity::WeakWarning)
- .with_fixes(Some(vec![{
- let mut scb = SourceChangeBuilder::new(file_id);
- let scope = match import_scope {
- ImportScope::File(it) => ImportScope::File(scb.make_mut(it)),
- ImportScope::Module(it) => ImportScope::Module(scb.make_mut(it)),
- ImportScope::Block(it) => ImportScope::Block(scb.make_mut(it)),
- };
- let current_module = semantics_scope.module();
- if !scope_has("Serialize") {
- if let Some(PathResolution::Def(it)) = serialize_resolved {
- if let Some(it) = current_module.find_use_path_prefixed(
- sema.db,
- it,
- config.insert_use.prefix_kind,
- config.prefer_no_std,
- ) {
- insert_use(
- &scope,
- mod_path_to_ast(&it),
- &config.insert_use,
- );
- }
+ if let Ok(serde_json::Value::Object(it)) = serde_json::from_str(&node_string) {
+ let import_scope = ImportScope::find_insert_use_container(node, sema)?;
+ let range = node.text_range();
+ let mut edit = TextEdit::builder();
+ edit.delete(range);
+ let mut state = State::default();
+ let semantics_scope = sema.scope(node)?;
+ let scope_resolve =
+ |it| semantics_scope.speculative_resolve(&make::path_from_text(it));
+ let scope_has = |it| scope_resolve(it).is_some();
+ let deserialize_resolved = scope_resolve("::serde::Deserialize");
+ let serialize_resolved = scope_resolve("::serde::Serialize");
+ state.has_deserialize = deserialize_resolved.is_some();
+ state.has_serialize = serialize_resolved.is_some();
+ state.build_struct(&it);
+ edit.insert(range.start(), state.result);
+ acc.push(
+ Diagnostic::new(
+ "json-is-not-rust",
+ "JSON syntax is not valid as a Rust item",
+ range,
+ )
+ .severity(Severity::WeakWarning)
+ .with_fixes(Some(vec![{
+ let mut scb = SourceChangeBuilder::new(file_id);
+ let scope = match import_scope {
+ ImportScope::File(it) => ImportScope::File(scb.make_mut(it)),
+ ImportScope::Module(it) => ImportScope::Module(scb.make_mut(it)),
+ ImportScope::Block(it) => ImportScope::Block(scb.make_mut(it)),
+ };
+ let current_module = semantics_scope.module();
+ if !scope_has("Serialize") {
+ if let Some(PathResolution::Def(it)) = serialize_resolved {
+ if let Some(it) = current_module.find_use_path_prefixed(
+ sema.db,
+ it,
+ config.insert_use.prefix_kind,
+ config.prefer_no_std,
+ ) {
+ insert_use(&scope, mod_path_to_ast(&it), &config.insert_use);
}
}
- if !scope_has("Deserialize") {
- if let Some(PathResolution::Def(it)) = deserialize_resolved {
- if let Some(it) = current_module.find_use_path_prefixed(
- sema.db,
- it,
- config.insert_use.prefix_kind,
- config.prefer_no_std,
- ) {
- insert_use(
- &scope,
- mod_path_to_ast(&it),
- &config.insert_use,
- );
- }
+ }
+ if !scope_has("Deserialize") {
+ if let Some(PathResolution::Def(it)) = deserialize_resolved {
+ if let Some(it) = current_module.find_use_path_prefixed(
+ sema.db,
+ it,
+ config.insert_use.prefix_kind,
+ config.prefer_no_std,
+ ) {
+ insert_use(&scope, mod_path_to_ast(&it), &config.insert_use);
}
}
- let mut sc = scb.finish();
- sc.insert_source_edit(file_id, edit.finish());
- fix("convert_json_to_struct", "Convert JSON to struct", sc, range)
- }])),
- );
- }
+ }
+ let mut sc = scb.finish();
+ sc.insert_source_edit(file_id, edit.finish());
+ fix("convert_json_to_struct", "Convert JSON to struct", sc, range)
+ }])),
+ );
}
}
Some(())
diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/private_assoc_item.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/private_assoc_item.rs
index b363a516d..0b3121c76 100644
--- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/private_assoc_item.rs
+++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/private_assoc_item.rs
@@ -11,10 +11,7 @@ pub(crate) fn private_assoc_item(
d: &hir::PrivateAssocItem,
) -> Diagnostic {
// FIXME: add quickfix
- let name = match d.item.name(ctx.sema.db) {
- Some(name) => format!("`{}` ", name),
- None => String::new(),
- };
+ let name = d.item.name(ctx.sema.db).map(|name| format!("`{name}` ")).unwrap_or_default();
Diagnostic::new(
"private-assoc-item",
format!(
diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unlinked_file.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unlinked_file.rs
index be70f0ac4..3d45a7591 100644
--- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unlinked_file.rs
+++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unlinked_file.rs
@@ -1,13 +1,15 @@
//! Diagnostic emitted for files that aren't part of any crate.
-use hir::db::DefDatabase;
+use std::iter;
+
+use hir::{db::DefDatabase, InFile, ModuleSource};
use ide_db::{
base_db::{FileId, FileLoader, SourceDatabase, SourceDatabaseExt},
source_change::SourceChange,
RootDatabase,
};
use syntax::{
- ast::{self, HasModuleItem, HasName},
+ ast::{self, edit::IndentLevel, HasModuleItem, HasName},
AstNode, TextRange, TextSize,
};
use text_edit::TextEdit;
@@ -42,47 +44,99 @@ fn fixes(ctx: &DiagnosticsContext<'_>, file_id: FileId) -> Option<Vec<Assist>> {
let source_root = ctx.sema.db.source_root(ctx.sema.db.file_source_root(file_id));
let our_path = source_root.path_for_file(&file_id)?;
- let (mut module_name, _) = our_path.name_and_extension()?;
-
- // Candidates to look for:
- // - `mod.rs`, `main.rs` and `lib.rs` in the same folder
- // - `$dir.rs` in the parent folder, where `$dir` is the directory containing `self.file_id`
let parent = our_path.parent()?;
- let paths = {
- let parent = if module_name == "mod" {
- // for mod.rs we need to actually look up one higher
- // and take the parent as our to be module name
- let (name, _) = parent.name_and_extension()?;
- module_name = name;
- parent.parent()?
- } else {
- parent
- };
- let mut paths =
- vec![parent.join("mod.rs")?, parent.join("lib.rs")?, parent.join("main.rs")?];
-
- // `submod/bla.rs` -> `submod.rs`
- let parent_mod = (|| {
+ let (module_name, _) = our_path.name_and_extension()?;
+ let (parent, module_name) = match module_name {
+ // for mod.rs we need to actually look up one higher
+ // and take the parent as our to be module name
+ "mod" => {
let (name, _) = parent.name_and_extension()?;
- parent.parent()?.join(&format!("{name}.rs"))
- })();
- paths.extend(parent_mod);
- paths
+ (parent.parent()?, name.to_owned())
+ }
+ _ => (parent, module_name.to_owned()),
};
- for &parent_id in paths.iter().filter_map(|path| source_root.file_for_path(path)) {
- for &krate in ctx.sema.db.relevant_crates(parent_id).iter() {
- let crate_def_map = ctx.sema.db.crate_def_map(krate);
- for (_, module) in crate_def_map.modules() {
- if module.origin.is_inline() {
- // We don't handle inline `mod parent {}`s, they use different paths.
- continue;
- }
+ // check crate roots, i.e. main.rs, lib.rs, ...
+ 'crates: for &krate in &*ctx.sema.db.relevant_crates(file_id) {
+ let crate_def_map = ctx.sema.db.crate_def_map(krate);
+
+ let root_module = &crate_def_map[crate_def_map.root()];
+ let Some(root_file_id) = root_module.origin.file_id() else { continue };
+ let Some(crate_root_path) = source_root.path_for_file(&root_file_id) else { continue };
+ let Some(rel) = parent.strip_prefix(&crate_root_path.parent()?) else { continue };
+
+ // try resolving the relative difference of the paths as inline modules
+ let mut current = root_module;
+ for ele in rel.as_ref().components() {
+ let seg = match ele {
+ std::path::Component::Normal(seg) => seg.to_str()?,
+ std::path::Component::RootDir => continue,
+ // shouldn't occur
+ _ => continue 'crates,
+ };
+ match current.children.iter().find(|(name, _)| name.to_smol_str() == seg) {
+ Some((_, &child)) => current = &crate_def_map[child],
+ None => continue 'crates,
+ }
+ if !current.origin.is_inline() {
+ continue 'crates;
+ }
+ }
+
+ let InFile { file_id: parent_file_id, value: source } =
+ current.definition_source(ctx.sema.db);
+ let parent_file_id = parent_file_id.file_id()?;
+ return make_fixes(ctx.sema.db, parent_file_id, source, &module_name, file_id);
+ }
- if module.origin.file_id() == Some(parent_id) {
- return make_fixes(ctx.sema.db, parent_id, module_name, file_id);
+ // if we aren't adding to a crate root, walk backwards such that we support `#[path = ...]` overrides if possible
+
+ // build all parent paths of the form `../module_name/mod.rs` and `../module_name.rs`
+ let paths = iter::successors(Some(parent.clone()), |prev| prev.parent()).filter_map(|path| {
+ let parent = path.parent()?;
+ let (name, _) = path.name_and_extension()?;
+ Some(([parent.join(&format!("{name}.rs"))?, path.join("mod.rs")?], name.to_owned()))
+ });
+ let mut stack = vec![];
+ let &parent_id =
+ paths.inspect(|(_, name)| stack.push(name.clone())).find_map(|(paths, _)| {
+ paths.into_iter().find_map(|path| source_root.file_for_path(&path))
+ })?;
+ stack.pop();
+ 'crates: for &krate in ctx.sema.db.relevant_crates(parent_id).iter() {
+ let crate_def_map = ctx.sema.db.crate_def_map(krate);
+ let Some((_, module)) =
+ crate_def_map.modules()
+ .find(|(_, module)| module.origin.file_id() == Some(parent_id) && !module.origin.is_inline())
+ else { continue };
+
+ if stack.is_empty() {
+ return make_fixes(
+ ctx.sema.db,
+ parent_id,
+ module.definition_source(ctx.sema.db).value,
+ &module_name,
+ file_id,
+ );
+ } else {
+ // direct parent file is missing,
+ // try finding a parent that has an inline tree from here on
+ let mut current = module;
+ for s in stack.iter().rev() {
+ match module.children.iter().find(|(name, _)| name.to_smol_str() == s) {
+ Some((_, child)) => {
+ current = &crate_def_map[*child];
+ }
+ None => continue 'crates,
+ }
+ if !current.origin.is_inline() {
+ continue 'crates;
}
}
+ let InFile { file_id: parent_file_id, value: source } =
+ current.definition_source(ctx.sema.db);
+ let parent_file_id = parent_file_id.file_id()?;
+ return make_fixes(ctx.sema.db, parent_file_id, source, &module_name, file_id);
}
}
@@ -92,6 +146,7 @@ fn fixes(ctx: &DiagnosticsContext<'_>, file_id: FileId) -> Option<Vec<Assist>> {
fn make_fixes(
db: &RootDatabase,
parent_file_id: FileId,
+ source: ModuleSource,
new_mod_name: &str,
added_file_id: FileId,
) -> Option<Vec<Assist>> {
@@ -102,14 +157,18 @@ fn make_fixes(
let mod_decl = format!("mod {new_mod_name};");
let pub_mod_decl = format!("pub mod {new_mod_name};");
- let ast: ast::SourceFile = db.parse(parent_file_id).tree();
-
let mut mod_decl_builder = TextEdit::builder();
let mut pub_mod_decl_builder = TextEdit::builder();
+ let mut items = match &source {
+ ModuleSource::SourceFile(it) => it.items(),
+ ModuleSource::Module(it) => it.item_list()?.items(),
+ ModuleSource::BlockExpr(_) => return None,
+ };
+
// If there's an existing `mod m;` statement matching the new one, don't emit a fix (it's
// probably `#[cfg]`d out).
- for item in ast.items() {
+ for item in items.clone() {
if let ast::Item::Module(m) = item {
if let Some(name) = m.name() {
if m.item_list().is_none() && name.to_string() == new_mod_name {
@@ -121,28 +180,40 @@ fn make_fixes(
}
// If there are existing `mod m;` items, append after them (after the first group of them, rather).
- match ast.items().skip_while(|item| !is_outline_mod(item)).take_while(is_outline_mod).last() {
+ match items.clone().skip_while(|item| !is_outline_mod(item)).take_while(is_outline_mod).last() {
Some(last) => {
cov_mark::hit!(unlinked_file_append_to_existing_mods);
let offset = last.syntax().text_range().end();
- mod_decl_builder.insert(offset, format!("\n{mod_decl}"));
- pub_mod_decl_builder.insert(offset, format!("\n{pub_mod_decl}"));
+ let indent = IndentLevel::from_node(last.syntax());
+ mod_decl_builder.insert(offset, format!("\n{indent}{mod_decl}"));
+ pub_mod_decl_builder.insert(offset, format!("\n{indent}{pub_mod_decl}"));
}
None => {
// Prepend before the first item in the file.
- match ast.items().next() {
- Some(item) => {
+ match items.next() {
+ Some(first) => {
cov_mark::hit!(unlinked_file_prepend_before_first_item);
- let offset = item.syntax().text_range().start();
- mod_decl_builder.insert(offset, format!("{mod_decl}\n\n"));
- pub_mod_decl_builder.insert(offset, format!("{pub_mod_decl}\n\n"));
+ let offset = first.syntax().text_range().start();
+ let indent = IndentLevel::from_node(first.syntax());
+ mod_decl_builder.insert(offset, format!("{mod_decl}\n\n{indent}"));
+ pub_mod_decl_builder.insert(offset, format!("{pub_mod_decl}\n\n{indent}"));
}
None => {
// No items in the file, so just append at the end.
cov_mark::hit!(unlinked_file_empty_file);
- let offset = ast.syntax().text_range().end();
- mod_decl_builder.insert(offset, format!("{mod_decl}\n"));
- pub_mod_decl_builder.insert(offset, format!("{pub_mod_decl}\n"));
+ let mut indent = IndentLevel::from(0);
+ let offset = match &source {
+ ModuleSource::SourceFile(it) => it.syntax().text_range().end(),
+ ModuleSource::Module(it) => {
+ indent = IndentLevel::from_node(it.syntax()) + 1;
+ it.item_list()?.r_curly_token()?.text_range().start()
+ }
+ ModuleSource::BlockExpr(it) => {
+ it.stmt_list()?.r_curly_token()?.text_range().start()
+ }
+ };
+ mod_decl_builder.insert(offset, format!("{indent}{mod_decl}\n"));
+ pub_mod_decl_builder.insert(offset, format!("{indent}{pub_mod_decl}\n"));
}
}
}
@@ -167,7 +238,6 @@ fn make_fixes(
#[cfg(test)]
mod tests {
-
use crate::tests::{check_diagnostics, check_fix, check_fixes, check_no_fix};
#[test]
@@ -333,4 +403,62 @@ mod foo;
"#,
);
}
+
+ #[test]
+ fn unlinked_file_insert_into_inline_simple() {
+ check_fix(
+ r#"
+//- /main.rs
+mod bar;
+//- /bar.rs
+mod foo {
+}
+//- /bar/foo/baz.rs
+$0
+"#,
+ r#"
+mod foo {
+ mod baz;
+}
+"#,
+ );
+ }
+
+ #[test]
+ fn unlinked_file_insert_into_inline_simple_modrs() {
+ check_fix(
+ r#"
+//- /main.rs
+mod bar;
+//- /bar.rs
+mod baz {
+}
+//- /bar/baz/foo/mod.rs
+$0
+"#,
+ r#"
+mod baz {
+ mod foo;
+}
+"#,
+ );
+ }
+
+ #[test]
+ fn unlinked_file_insert_into_inline_simple_modrs_main() {
+ check_fix(
+ r#"
+//- /main.rs
+mod bar {
+}
+//- /bar/foo/mod.rs
+$0
+"#,
+ r#"
+mod bar {
+ mod foo;
+}
+"#,
+ );
+ }
}
diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unresolved_proc_macro.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unresolved_proc_macro.rs
index b2ed19104..9a984ba6b 100644
--- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unresolved_proc_macro.rs
+++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unresolved_proc_macro.rs
@@ -34,10 +34,7 @@ pub(crate) fn unresolved_proc_macro(
let message = format!(
"{message}: {}",
if config_enabled {
- match def_map.proc_macro_loading_error() {
- Some(e) => e,
- None => "proc macro not found in the built dylib",
- }
+ def_map.proc_macro_loading_error().unwrap_or("proc macro not found in the built dylib")
} else {
match d.kind {
hir::MacroKind::Attr if proc_macros_enabled => {
diff --git a/src/tools/rust-analyzer/crates/ide-ssr/Cargo.toml b/src/tools/rust-analyzer/crates/ide-ssr/Cargo.toml
index 7be62a8d9..04efa7b91 100644
--- a/src/tools/rust-analyzer/crates/ide-ssr/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/ide-ssr/Cargo.toml
@@ -2,10 +2,12 @@
name = "ide-ssr"
version = "0.0.0"
description = "Structural search and replace of Rust code"
-license = "MIT OR Apache-2.0"
repository = "https://github.com/rust-lang/rust-analyzer"
-edition = "2021"
-rust-version = "1.65"
+
+authors.workspace = true
+edition.workspace = true
+license.workspace = true
+rust-version.workspace = true
[lib]
doctest = false
@@ -14,13 +16,16 @@ doctest = false
cov-mark = "2.0.0-pre.1"
itertools = "0.10.5"
-text-edit = { path = "../text-edit", version = "0.0.0" }
-parser = { path = "../parser", version = "0.0.0" }
-syntax = { path = "../syntax", version = "0.0.0" }
-ide-db = { path = "../ide-db", version = "0.0.0" }
-hir = { path = "../hir", version = "0.0.0" }
-stdx = { path = "../stdx", version = "0.0.0" }
+# local deps
+hir.workspace = true
+ide-db.workspace = true
+parser.workspace = true
+stdx.workspace = true
+syntax.workspace = true
+text-edit.workspace = true
[dev-dependencies]
-test-utils = { path = "../test-utils" }
expect-test = "1.4.0"
+
+# local deps
+test-utils.workspace = true
diff --git a/src/tools/rust-analyzer/crates/ide/Cargo.toml b/src/tools/rust-analyzer/crates/ide/Cargo.toml
index 73f202630..30e514e41 100644
--- a/src/tools/rust-analyzer/crates/ide/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/ide/Cargo.toml
@@ -2,9 +2,11 @@
name = "ide"
version = "0.0.0"
description = "TBD"
-license = "MIT OR Apache-2.0"
-edition = "2021"
-rust-version = "1.65"
+
+authors.workspace = true
+edition.workspace = true
+license.workspace = true
+rust-version.workspace = true
[lib]
doctest = false
@@ -20,28 +22,31 @@ pulldown-cmark-to-cmark = "10.0.4"
pulldown-cmark = { version = "0.9.1", default-features = false }
url = "2.3.1"
dot = "0.1.4"
+smallvec.workspace = true
-stdx = { path = "../stdx", version = "0.0.0" }
-syntax = { path = "../syntax", version = "0.0.0" }
-text-edit = { path = "../text-edit", version = "0.0.0" }
-ide-db = { path = "../ide-db", version = "0.0.0" }
-cfg = { path = "../cfg", version = "0.0.0" }
-profile = { path = "../profile", version = "0.0.0" }
-ide-assists = { path = "../ide-assists", version = "0.0.0" }
-ide-diagnostics = { path = "../ide-diagnostics", version = "0.0.0" }
-ide-ssr = { path = "../ide-ssr", version = "0.0.0" }
-ide-completion = { path = "../ide-completion", version = "0.0.0" }
-
+# local deps
+cfg.workspace = true
+ide-assists.workspace = true
+ide-completion.workspace = true
+ide-db.workspace = true
+ide-diagnostics.workspace = true
+ide-ssr.workspace = true
+profile.workspace = true
+stdx.workspace = true
+syntax.workspace = true
+text-edit.workspace = true
# ide should depend only on the top-level `hir` package. if you need
# something from some `hir-xxx` subpackage, reexport the API via `hir`.
-hir = { path = "../hir", version = "0.0.0" }
+hir.workspace = true
[target.'cfg(not(any(target_arch = "wasm32", target_os = "emscripten")))'.dependencies]
-toolchain = { path = "../toolchain", version = "0.0.0" }
+toolchain.workspace = true
[dev-dependencies]
-test-utils = { path = "../test-utils" }
expect-test = "1.4.0"
+# local deps
+test-utils.workspace = true
+
[features]
in-rust-tree = ["ide-assists/in-rust-tree", "ide-diagnostics/in-rust-tree"]
diff --git a/src/tools/rust-analyzer/crates/ide/src/file_structure.rs b/src/tools/rust-analyzer/crates/ide/src/file_structure.rs
index 68fd0952b..b23763dce 100644
--- a/src/tools/rust-analyzer/crates/ide/src/file_structure.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/file_structure.rs
@@ -160,7 +160,11 @@ fn structure_node(node: &SyntaxNode) -> Option<StructureNode> {
let label = match target_trait {
None => format!("impl {}", target_type.syntax().text()),
Some(t) => {
- format!("impl {} for {}", t.syntax().text(), target_type.syntax().text(),)
+ format!("impl {}{} for {}",
+ it.excl_token().map(|x| x.to_string()).unwrap_or_default(),
+ t.syntax().text(),
+ target_type.syntax().text(),
+ )
}
};
@@ -214,6 +218,29 @@ mod tests {
}
#[test]
+ fn test_nagative_trait_bound() {
+ let txt = r#"impl !Unpin for Test {}"#;
+ check(
+ txt,
+ expect![[r#"
+ [
+ StructureNode {
+ parent: None,
+ label: "impl !Unpin for Test",
+ navigation_range: 16..20,
+ node_range: 0..23,
+ kind: SymbolKind(
+ Impl,
+ ),
+ detail: None,
+ deprecated: false,
+ },
+ ]
+ "#]],
+ );
+ }
+
+ #[test]
fn test_file_structure() {
check(
r#"
diff --git a/src/tools/rust-analyzer/crates/ide/src/goto_declaration.rs b/src/tools/rust-analyzer/crates/ide/src/goto_declaration.rs
index c7130a2a4..e70bc2ec5 100644
--- a/src/tools/rust-analyzer/crates/ide/src/goto_declaration.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/goto_declaration.rs
@@ -17,6 +17,7 @@ use crate::{
// This is the same as `Go to Definition` with the following exceptions:
// - outline modules will navigate to the `mod name;` item declaration
// - trait assoc items will navigate to the assoc item of the trait declaration opposed to the trait impl
+// - fields in patterns will navigate to the field declaration of the struct, union or variant
pub(crate) fn goto_declaration(
db: &RootDatabase,
position: FilePosition,
diff --git a/src/tools/rust-analyzer/crates/ide/src/goto_definition.rs b/src/tools/rust-analyzer/crates/ide/src/goto_definition.rs
index 73fd518a9..93019527f 100644
--- a/src/tools/rust-analyzer/crates/ide/src/goto_definition.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/goto_definition.rs
@@ -1916,4 +1916,68 @@ fn main() {
"#,
)
}
+
+ #[test]
+ fn query_impls_in_nearest_block() {
+ check(
+ r#"
+struct S1;
+impl S1 {
+ fn e() -> () {}
+}
+fn f1() {
+ struct S1;
+ impl S1 {
+ fn e() -> () {}
+ //^
+ }
+ fn f2() {
+ fn f3() {
+ S1::e$0();
+ }
+ }
+}
+"#,
+ );
+
+ check(
+ r#"
+struct S1;
+impl S1 {
+ fn e() -> () {}
+}
+fn f1() {
+ struct S1;
+ impl S1 {
+ fn e() -> () {}
+ //^
+ }
+ fn f2() {
+ struct S2;
+ S1::e$0();
+ }
+}
+fn f12() {
+ struct S1;
+ impl S1 {
+ fn e() -> () {}
+ }
+}
+"#,
+ );
+
+ check(
+ r#"
+struct S1;
+impl S1 {
+ fn e() -> () {}
+ //^
+}
+fn f2() {
+ struct S2;
+ S1::e$0();
+}
+"#,
+ );
+ }
}
diff --git a/src/tools/rust-analyzer/crates/ide/src/highlight_related.rs b/src/tools/rust-analyzer/crates/ide/src/highlight_related.rs
index 55f8779ee..c889eb930 100644
--- a/src/tools/rust-analyzer/crates/ide/src/highlight_related.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/highlight_related.rs
@@ -1356,7 +1356,6 @@ fn main() {
r#"
trait Trait {
fn func(self) {}
- //^^^^
}
impl Trait for () {
@@ -1376,7 +1375,6 @@ fn main() {
r#"
trait Trait {
fn func(self) {}
- //^^^^
}
impl Trait for () {
diff --git a/src/tools/rust-analyzer/crates/ide/src/hover.rs b/src/tools/rust-analyzer/crates/ide/src/hover.rs
index b214fa12a..5f2c61f5b 100644
--- a/src/tools/rust-analyzer/crates/ide/src/hover.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/hover.rs
@@ -15,10 +15,11 @@ use ide_db::{
FxIndexSet, RootDatabase,
};
use itertools::Itertools;
-use syntax::{ast, match_ast, AstNode, SyntaxKind::*, SyntaxNode, SyntaxToken, T};
+use syntax::{ast, AstNode, SyntaxKind::*, SyntaxNode, T};
use crate::{
doc_links::token_as_doc_comment,
+ markdown_remove::remove_markdown,
markup::Markup,
runnables::{runnable_fn, runnable_mod},
FileId, FilePosition, NavigationTarget, RangeInfo, Runnable, TryToNav,
@@ -26,14 +27,9 @@ use crate::{
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct HoverConfig {
pub links_in_hover: bool,
- pub documentation: Option<HoverDocFormat>,
+ pub documentation: bool,
pub keywords: bool,
-}
-
-impl HoverConfig {
- fn markdown(&self) -> bool {
- matches!(self.documentation, Some(HoverDocFormat::Markdown))
- }
+ pub format: HoverDocFormat,
}
#[derive(Clone, Debug, PartialEq, Eq)]
@@ -90,19 +86,38 @@ pub struct HoverResult {
// image::https://user-images.githubusercontent.com/48062697/113020658-b5f98b80-917a-11eb-9f88-3dbc27320c95.gif[]
pub(crate) fn hover(
db: &RootDatabase,
- FileRange { file_id, range }: FileRange,
+ frange @ FileRange { file_id, range }: FileRange,
config: &HoverConfig,
) -> Option<RangeInfo<HoverResult>> {
let sema = &hir::Semantics::new(db);
let file = sema.parse(file_id).syntax().clone();
+ let mut res = if range.is_empty() {
+ hover_simple(sema, FilePosition { file_id, offset: range.start() }, file, config)
+ } else {
+ hover_ranged(sema, frange, file, config)
+ }?;
- if !range.is_empty() {
- return hover_ranged(&file, range, sema, config);
+ if let HoverDocFormat::PlainText = config.format {
+ res.info.markup = remove_markdown(res.info.markup.as_str()).into();
}
- let offset = range.start();
+ Some(res)
+}
+fn hover_simple(
+ sema: &Semantics<'_, RootDatabase>,
+ FilePosition { file_id, offset }: FilePosition,
+ file: SyntaxNode,
+ config: &HoverConfig,
+) -> Option<RangeInfo<HoverResult>> {
let original_token = pick_best_token(file.token_at_offset(offset), |kind| match kind {
- IDENT | INT_NUMBER | LIFETIME_IDENT | T![self] | T![super] | T![crate] | T![Self] => 4,
+ IDENT
+ | INT_NUMBER
+ | LIFETIME_IDENT
+ | T![self]
+ | T![super]
+ | T![crate]
+ | T![Self]
+ | T![_] => 4,
// index and prefix ops
T!['['] | T![']'] | T![?] | T![*] | T![-] | T![!] => 3,
kind if kind.is_keyword() => 2,
@@ -135,19 +150,18 @@ pub(crate) fn hover(
} else {
sema.descend_into_macros_with_same_text(original_token.clone())
};
+ let descended = || descended.iter();
- // try lint hover
- let result = descended
- .iter()
+ let result = descended()
+ // try lint hover
.find_map(|token| {
// FIXME: Definition should include known lints and the like instead of having this special case here
let attr = token.parent_ancestors().find_map(ast::Attr::cast)?;
render::try_for_lint(&attr, token)
})
- // try item definitions
+ // try definitions
.or_else(|| {
- descended
- .iter()
+ descended()
.filter_map(|token| {
let node = token.parent()?;
let class = IdentClass::classify_token(sema, token)?;
@@ -168,10 +182,12 @@ pub(crate) fn hover(
})
})
// try keywords
- .or_else(|| descended.iter().find_map(|token| render::keyword(sema, config, token)))
- // try rest item hover
+ .or_else(|| descended().find_map(|token| render::keyword(sema, config, token)))
+ // try _ hovers
+ .or_else(|| descended().find_map(|token| render::underscore(sema, config, token)))
+ // try rest pattern hover
.or_else(|| {
- descended.iter().find_map(|token| {
+ descended().find_map(|token| {
if token.kind() != DOT2 {
return None;
}
@@ -185,60 +201,43 @@ pub(crate) fn hover(
Some(render::struct_rest_pat(sema, config, &record_pat))
})
- });
-
- result
- .map(|mut res: HoverResult| {
- res.actions = dedupe_or_merge_hover_actions(res.actions);
- RangeInfo::new(original_token.text_range(), res)
})
- // fallback to type hover if there aren't any other suggestions
- // this finds its own range instead of using the closest token's range
+ // try () call hovers
.or_else(|| {
- descended.iter().find_map(|token| hover_type_fallback(sema, config, token, token))
- })
-}
+ descended().find_map(|token| {
+ if token.kind() != T!['('] && token.kind() != T![')'] {
+ return None;
+ }
+ let arg_list = token.parent().and_then(ast::ArgList::cast)?.syntax().parent()?;
+ let call_expr = syntax::match_ast! {
+ match arg_list {
+ ast::CallExpr(expr) => expr.into(),
+ ast::MethodCallExpr(expr) => expr.into(),
+ _ => return None,
+ }
+ };
+ render::type_info_of(sema, config, &Either::Left(call_expr))
+ })
+ });
-pub(crate) fn hover_for_definition(
- sema: &Semantics<'_, RootDatabase>,
- file_id: FileId,
- definition: Definition,
- node: &SyntaxNode,
- config: &HoverConfig,
-) -> Option<HoverResult> {
- let famous_defs = match &definition {
- Definition::BuiltinType(_) => Some(FamousDefs(sema, sema.scope(node)?.krate())),
- _ => None,
- };
- render::definition(sema.db, definition, famous_defs.as_ref(), config).map(|markup| {
- HoverResult {
- markup: render::process_markup(sema.db, definition, &markup, config),
- actions: show_implementations_action(sema.db, definition)
- .into_iter()
- .chain(show_fn_references_action(sema.db, definition))
- .chain(runnable_action(sema, definition, file_id))
- .chain(goto_type_action_for_def(sema.db, definition))
- .collect(),
- }
+ result.map(|mut res: HoverResult| {
+ res.actions = dedupe_or_merge_hover_actions(res.actions);
+ RangeInfo::new(original_token.text_range(), res)
})
}
fn hover_ranged(
- file: &SyntaxNode,
- range: syntax::TextRange,
sema: &Semantics<'_, RootDatabase>,
+ FileRange { range, .. }: FileRange,
+ file: SyntaxNode,
config: &HoverConfig,
) -> Option<RangeInfo<HoverResult>> {
// FIXME: make this work in attributes
- let expr_or_pat = file.covering_element(range).ancestors().find_map(|it| {
- match_ast! {
- match it {
- ast::Expr(expr) => Some(Either::Left(expr)),
- ast::Pat(pat) => Some(Either::Right(pat)),
- _ => None,
- }
- }
- })?;
+ let expr_or_pat = file
+ .covering_element(range)
+ .ancestors()
+ .take_while(|it| ast::MacroCall::can_cast(it.kind()) || !ast::Item::can_cast(it.kind()))
+ .find_map(Either::<ast::Expr, ast::Pat>::cast)?;
let res = match &expr_or_pat {
Either::Left(ast::Expr::TryExpr(try_expr)) => render::try_expr(sema, config, try_expr),
Either::Left(ast::Expr::PrefixExpr(prefix_expr))
@@ -248,7 +247,7 @@ fn hover_ranged(
}
_ => None,
};
- let res = res.or_else(|| render::type_info(sema, config, &expr_or_pat));
+ let res = res.or_else(|| render::type_info_of(sema, config, &expr_or_pat));
res.map(|it| {
let range = match expr_or_pat {
Either::Left(it) => it.syntax().text_range(),
@@ -258,37 +257,31 @@ fn hover_ranged(
})
}
-fn hover_type_fallback(
+pub(crate) fn hover_for_definition(
sema: &Semantics<'_, RootDatabase>,
+ file_id: FileId,
+ definition: Definition,
+ node: &SyntaxNode,
config: &HoverConfig,
- token: &SyntaxToken,
- original_token: &SyntaxToken,
-) -> Option<RangeInfo<HoverResult>> {
- let node =
- token.parent_ancestors().take_while(|it| !ast::Item::can_cast(it.kind())).find(|n| {
- ast::Expr::can_cast(n.kind())
- || ast::Pat::can_cast(n.kind())
- || ast::Type::can_cast(n.kind())
- })?;
-
- let expr_or_pat = match_ast! {
- match node {
- ast::Expr(it) => Either::Left(it),
- ast::Pat(it) => Either::Right(it),
- // If this node is a MACRO_CALL, it means that `descend_into_macros_many` failed to resolve.
- // (e.g expanding a builtin macro). So we give up here.
- ast::MacroCall(_it) => return None,
- _ => return None,
- }
+) -> Option<HoverResult> {
+ let famous_defs = match &definition {
+ Definition::BuiltinType(_) => Some(FamousDefs(sema, sema.scope(node)?.krate())),
+ _ => None,
};
-
- let res = render::type_info(sema, config, &expr_or_pat)?;
-
- let range = sema
- .original_range_opt(&node)
- .map(|frange| frange.range)
- .unwrap_or_else(|| original_token.text_range());
- Some(RangeInfo::new(range, res))
+ render::definition(sema.db, definition, famous_defs.as_ref(), config).map(|markup| {
+ HoverResult {
+ markup: render::process_markup(sema.db, definition, &markup, config),
+ actions: [
+ show_implementations_action(sema.db, definition),
+ show_fn_references_action(sema.db, definition),
+ runnable_action(sema, definition, file_id),
+ goto_type_action_for_def(sema.db, definition),
+ ]
+ .into_iter()
+ .flatten()
+ .collect(),
+ }
+ })
}
fn show_implementations_action(db: &RootDatabase, def: Definition) -> Option<HoverAction> {
diff --git a/src/tools/rust-analyzer/crates/ide/src/hover/render.rs b/src/tools/rust-analyzer/crates/ide/src/hover/render.rs
index 47257f0bf..22611cfb8 100644
--- a/src/tools/rust-analyzer/crates/ide/src/hover/render.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/hover/render.rs
@@ -26,58 +26,24 @@ use syntax::{
use crate::{
doc_links::{remove_links, rewrite_links},
hover::walk_and_push_ty,
- markdown_remove::remove_markdown,
HoverAction, HoverConfig, HoverResult, Markup,
};
-pub(super) fn type_info(
+pub(super) fn type_info_of(
sema: &Semantics<'_, RootDatabase>,
- config: &HoverConfig,
+ _config: &HoverConfig,
expr_or_pat: &Either<ast::Expr, ast::Pat>,
) -> Option<HoverResult> {
let TypeInfo { original, adjusted } = match expr_or_pat {
Either::Left(expr) => sema.type_of_expr(expr)?,
Either::Right(pat) => sema.type_of_pat(pat)?,
};
-
- let mut res = HoverResult::default();
- let mut targets: Vec<hir::ModuleDef> = Vec::new();
- let mut push_new_def = |item: hir::ModuleDef| {
- if !targets.contains(&item) {
- targets.push(item);
- }
- };
- walk_and_push_ty(sema.db, &original, &mut push_new_def);
-
- res.markup = if let Some(adjusted_ty) = adjusted {
- walk_and_push_ty(sema.db, &adjusted_ty, &mut push_new_def);
- let original = original.display(sema.db).to_string();
- let adjusted = adjusted_ty.display(sema.db).to_string();
- let static_text_diff_len = "Coerced to: ".len() - "Type: ".len();
- format!(
- "{bt_start}Type: {:>apad$}\nCoerced to: {:>opad$}\n{bt_end}",
- original,
- adjusted,
- apad = static_text_diff_len + adjusted.len().max(original.len()),
- opad = original.len(),
- bt_start = if config.markdown() { "```text\n" } else { "" },
- bt_end = if config.markdown() { "```\n" } else { "" }
- )
- .into()
- } else {
- if config.markdown() {
- Markup::fenced_block(&original.display(sema.db))
- } else {
- original.display(sema.db).to_string().into()
- }
- };
- res.actions.push(HoverAction::goto_type_from_targets(sema.db, targets));
- Some(res)
+ type_info(sema, _config, original, adjusted)
}
pub(super) fn try_expr(
sema: &Semantics<'_, RootDatabase>,
- config: &HoverConfig,
+ _config: &HoverConfig,
try_expr: &ast::TryExpr,
) -> Option<HoverResult> {
let inner_ty = sema.type_of_expr(&try_expr.expr()?)?.original;
@@ -153,14 +119,12 @@ pub(super) fn try_expr(
let ppad = static_text_len_diff.min(0).abs() as usize;
res.markup = format!(
- "{bt_start}{} Type: {:>pad0$}\nPropagated as: {:>pad1$}\n{bt_end}",
+ "```text\n{} Type: {:>pad0$}\nPropagated as: {:>pad1$}\n```\n",
s,
inner_ty,
body_ty,
pad0 = ty_len_max + tpad,
pad1 = ty_len_max + ppad,
- bt_start = if config.markdown() { "```text\n" } else { "" },
- bt_end = if config.markdown() { "```\n" } else { "" }
)
.into();
Some(res)
@@ -168,7 +132,7 @@ pub(super) fn try_expr(
pub(super) fn deref_expr(
sema: &Semantics<'_, RootDatabase>,
- config: &HoverConfig,
+ _config: &HoverConfig,
deref_expr: &ast::PrefixExpr,
) -> Option<HoverResult> {
let inner_ty = sema.type_of_expr(&deref_expr.expr()?)?.original;
@@ -197,15 +161,13 @@ pub(super) fn deref_expr(
.max(adjusted.len() + coerced_len)
.max(inner.len() + deref_len);
format!(
- "{bt_start}Dereferenced from: {:>ipad$}\nTo type: {:>apad$}\nCoerced to: {:>opad$}\n{bt_end}",
+ "```text\nDereferenced from: {:>ipad$}\nTo type: {:>apad$}\nCoerced to: {:>opad$}\n```\n",
inner,
original,
adjusted,
ipad = max_len - deref_len,
apad = max_len - type_len,
opad = max_len - coerced_len,
- bt_start = if config.markdown() { "```text\n" } else { "" },
- bt_end = if config.markdown() { "```\n" } else { "" }
)
.into()
} else {
@@ -215,13 +177,11 @@ pub(super) fn deref_expr(
let deref_len = "Dereferenced from: ".len();
let max_len = (original.len() + type_len).max(inner.len() + deref_len);
format!(
- "{bt_start}Dereferenced from: {:>ipad$}\nTo type: {:>apad$}\n{bt_end}",
+ "```text\nDereferenced from: {:>ipad$}\nTo type: {:>apad$}\n```\n",
inner,
original,
ipad = max_len - deref_len,
apad = max_len - type_len,
- bt_start = if config.markdown() { "```text\n" } else { "" },
- bt_end = if config.markdown() { "```\n" } else { "" }
)
.into()
};
@@ -230,12 +190,54 @@ pub(super) fn deref_expr(
Some(res)
}
+pub(super) fn underscore(
+ sema: &Semantics<'_, RootDatabase>,
+ config: &HoverConfig,
+ token: &SyntaxToken,
+) -> Option<HoverResult> {
+ if token.kind() != T![_] {
+ return None;
+ }
+ let parent = token.parent()?;
+ let _it = match_ast! {
+ match parent {
+ ast::InferType(it) => it,
+ ast::UnderscoreExpr(it) => return type_info_of(sema, config, &Either::Left(ast::Expr::UnderscoreExpr(it))),
+ ast::WildcardPat(it) => return type_info_of(sema, config, &Either::Right(ast::Pat::WildcardPat(it))),
+ _ => return None,
+ }
+ };
+ // let it = infer_type.syntax().parent()?;
+ // match_ast! {
+ // match it {
+ // ast::LetStmt(_it) => (),
+ // ast::Param(_it) => (),
+ // ast::RetType(_it) => (),
+ // ast::TypeArg(_it) => (),
+
+ // ast::CastExpr(_it) => (),
+ // ast::ParenType(_it) => (),
+ // ast::TupleType(_it) => (),
+ // ast::PtrType(_it) => (),
+ // ast::RefType(_it) => (),
+ // ast::ArrayType(_it) => (),
+ // ast::SliceType(_it) => (),
+ // ast::ForType(_it) => (),
+ // _ => return None,
+ // }
+ // }
+
+ // FIXME: https://github.com/rust-lang/rust-analyzer/issues/11762, this currently always returns Unknown
+ // type_info(sema, config, sema.resolve_type(&ast::Type::InferType(it))?, None)
+ None
+}
+
pub(super) fn keyword(
sema: &Semantics<'_, RootDatabase>,
config: &HoverConfig,
token: &SyntaxToken,
) -> Option<HoverResult> {
- if !token.kind().is_keyword() || !config.documentation.is_some() || !config.keywords {
+ if !token.kind().is_keyword() || !config.documentation || !config.keywords {
return None;
}
let parent = token.parent()?;
@@ -259,7 +261,7 @@ pub(super) fn keyword(
/// i.e. `let S {a, ..} = S {a: 1, b: 2}`
pub(super) fn struct_rest_pat(
sema: &Semantics<'_, RootDatabase>,
- config: &HoverConfig,
+ _config: &HoverConfig,
pattern: &RecordPat,
) -> HoverResult {
let missing_fields = sema.record_pattern_missing_fields(pattern);
@@ -288,11 +290,7 @@ pub(super) fn struct_rest_pat(
// get rid of trailing comma
s.truncate(s.len() - 2);
- if config.markdown() {
- Markup::fenced_block(&s)
- } else {
- s.into()
- }
+ Markup::fenced_block(&s)
};
res.actions.push(HoverAction::goto_type_from_targets(sema.db, targets));
res
@@ -346,13 +344,8 @@ pub(super) fn process_markup(
config: &HoverConfig,
) -> Markup {
let markup = markup.as_str();
- let markup = if !config.markdown() {
- remove_markdown(markup)
- } else if config.links_in_hover {
- rewrite_links(db, markup, def)
- } else {
- remove_links(markup)
- };
+ let markup =
+ if config.links_in_hover { rewrite_links(db, markup, def) } else { remove_links(markup) };
Markup::from(markup)
}
@@ -465,8 +458,9 @@ pub(super) fn definition(
Definition::DeriveHelper(it) => (format!("derive_helper {}", it.name(db)), None),
};
- let docs = match config.documentation {
- Some(_) => docs.or_else(|| {
+ let docs = docs
+ .filter(|_| config.documentation)
+ .or_else(|| {
// docs are missing, for assoc items of trait impls try to fall back to the docs of the
// original item of the trait
let assoc = def.as_assoc_item(db)?;
@@ -474,13 +468,46 @@ pub(super) fn definition(
let name = Some(assoc.name(db)?);
let item = trait_.items(db).into_iter().find(|it| it.name(db) == name)?;
item.docs(db)
- }),
- None => None,
- };
- let docs = docs.filter(|_| config.documentation.is_some()).map(Into::into);
+ })
+ .map(Into::into);
markup(docs, label, mod_path)
}
+fn type_info(
+ sema: &Semantics<'_, RootDatabase>,
+ _config: &HoverConfig,
+ original: hir::Type,
+ adjusted: Option<hir::Type>,
+) -> Option<HoverResult> {
+ let mut res = HoverResult::default();
+ let mut targets: Vec<hir::ModuleDef> = Vec::new();
+ let mut push_new_def = |item: hir::ModuleDef| {
+ if !targets.contains(&item) {
+ targets.push(item);
+ }
+ };
+ walk_and_push_ty(sema.db, &original, &mut push_new_def);
+
+ res.markup = if let Some(adjusted_ty) = adjusted {
+ walk_and_push_ty(sema.db, &adjusted_ty, &mut push_new_def);
+ let original = original.display(sema.db).to_string();
+ let adjusted = adjusted_ty.display(sema.db).to_string();
+ let static_text_diff_len = "Coerced to: ".len() - "Type: ".len();
+ format!(
+ "```text\nType: {:>apad$}\nCoerced to: {:>opad$}\n```\n",
+ original,
+ adjusted,
+ apad = static_text_diff_len + adjusted.len().max(original.len()),
+ opad = original.len(),
+ )
+ .into()
+ } else {
+ Markup::fenced_block(&original.display(sema.db))
+ };
+ res.actions.push(HoverAction::goto_type_from_targets(sema.db, targets));
+ Some(res)
+}
+
fn render_builtin_attr(db: &RootDatabase, attr: hir::BuiltinAttr) -> Option<Markup> {
let name = attr.name(db);
let desc = format!("#[{name}]");
diff --git a/src/tools/rust-analyzer/crates/ide/src/hover/tests.rs b/src/tools/rust-analyzer/crates/ide/src/hover/tests.rs
index c7f241f2f..bd7ce2f1d 100644
--- a/src/tools/rust-analyzer/crates/ide/src/hover/tests.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/hover/tests.rs
@@ -2,7 +2,7 @@ use expect_test::{expect, Expect};
use ide_db::base_db::{FileLoader, FileRange};
use syntax::TextRange;
-use crate::{fixture, hover::HoverDocFormat, HoverConfig};
+use crate::{fixture, HoverConfig, HoverDocFormat};
fn check_hover_no_result(ra_fixture: &str) {
let (analysis, position) = fixture::position(ra_fixture);
@@ -10,8 +10,9 @@ fn check_hover_no_result(ra_fixture: &str) {
.hover(
&HoverConfig {
links_in_hover: true,
- documentation: Some(HoverDocFormat::Markdown),
+ documentation: true,
keywords: true,
+ format: HoverDocFormat::Markdown,
},
FileRange { file_id: position.file_id, range: TextRange::empty(position.offset) },
)
@@ -26,8 +27,9 @@ fn check(ra_fixture: &str, expect: Expect) {
.hover(
&HoverConfig {
links_in_hover: true,
- documentation: Some(HoverDocFormat::Markdown),
+ documentation: true,
keywords: true,
+ format: HoverDocFormat::Markdown,
},
FileRange { file_id: position.file_id, range: TextRange::empty(position.offset) },
)
@@ -47,8 +49,9 @@ fn check_hover_no_links(ra_fixture: &str, expect: Expect) {
.hover(
&HoverConfig {
links_in_hover: false,
- documentation: Some(HoverDocFormat::Markdown),
+ documentation: true,
keywords: true,
+ format: HoverDocFormat::Markdown,
},
FileRange { file_id: position.file_id, range: TextRange::empty(position.offset) },
)
@@ -68,8 +71,9 @@ fn check_hover_no_markdown(ra_fixture: &str, expect: Expect) {
.hover(
&HoverConfig {
links_in_hover: true,
- documentation: Some(HoverDocFormat::PlainText),
+ documentation: true,
keywords: true,
+ format: HoverDocFormat::PlainText,
},
FileRange { file_id: position.file_id, range: TextRange::empty(position.offset) },
)
@@ -89,8 +93,9 @@ fn check_actions(ra_fixture: &str, expect: Expect) {
.hover(
&HoverConfig {
links_in_hover: true,
- documentation: Some(HoverDocFormat::Markdown),
+ documentation: true,
keywords: true,
+ format: HoverDocFormat::Markdown,
},
FileRange { file_id, range: position.range_or_empty() },
)
@@ -105,8 +110,9 @@ fn check_hover_range(ra_fixture: &str, expect: Expect) {
.hover(
&HoverConfig {
links_in_hover: false,
- documentation: Some(HoverDocFormat::Markdown),
+ documentation: true,
keywords: true,
+ format: HoverDocFormat::Markdown,
},
range,
)
@@ -121,8 +127,9 @@ fn check_hover_range_no_results(ra_fixture: &str) {
.hover(
&HoverConfig {
links_in_hover: false,
- documentation: Some(HoverDocFormat::Markdown),
+ documentation: true,
keywords: true,
+ format: HoverDocFormat::Markdown,
},
range,
)
@@ -207,37 +214,20 @@ m!(ab$0c);
}
#[test]
-fn hover_shows_type_of_an_expression() {
- check(
- r#"
-pub fn foo() -> u32 { 1 }
-
-fn main() {
- let foo_test = foo()$0;
-}
-"#,
- expect![[r#"
- *foo()*
- ```rust
- u32
- ```
- "#]],
- );
-}
-
-#[test]
fn hover_remove_markdown_if_configured() {
check_hover_no_markdown(
r#"
pub fn foo() -> u32 { 1 }
fn main() {
- let foo_test = foo()$0;
+ let foo_test = foo$0();
}
"#,
expect![[r#"
- *foo()*
- u32
+ *foo*
+ test
+
+ pub fn foo() -> u32
"#]],
);
}
@@ -297,33 +287,6 @@ fn main() { let foo_test = fo$0o(); }
"#]],
);
- // Multiple candidates but results are ambiguous.
- check(
- r#"
-//- /a.rs
-pub fn foo() -> u32 { 1 }
-
-//- /b.rs
-pub fn foo() -> &str { "" }
-
-//- /c.rs
-pub fn foo(a: u32, b: u32) {}
-
-//- /main.rs
-mod a;
-mod b;
-mod c;
-
-fn main() { let foo_test = fo$0o(); }
- "#,
- expect![[r#"
- *foo*
- ```rust
- {unknown}
- ```
- "#]],
- );
-
// Use literal `crate` in path
check(
r#"
@@ -527,6 +490,7 @@ fn hover_field_offset() {
// Hovering over the field when instantiating
check(
r#"
+//- /main.rs target_data_layout:e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128
struct Foo { fiel$0d_a: u8, field_b: i32, field_c: i16 }
"#,
expect![[r#"
@@ -548,6 +512,7 @@ fn hover_shows_struct_field_info() {
// Hovering over the field when instantiating
check(
r#"
+//- /main.rs target_data_layout:e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128
struct Foo { field_a: u32 }
fn main() {
@@ -570,6 +535,7 @@ fn main() {
// Hovering over the field in the definition
check(
r#"
+//- /main.rs target_data_layout:e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128
struct Foo { field_a$0: u32 }
fn main() {
@@ -1184,33 +1150,19 @@ fn test_hover_through_func_in_macro_recursive() {
macro_rules! id_deep { ($($tt:tt)*) => { $($tt)* } }
macro_rules! id { ($($tt:tt)*) => { id_deep!($($tt)*) } }
fn bar() -> u32 { 0 }
-fn foo() { let a = id!([0u32, bar($0)] ); }
+fn foo() { let a = id!([0u32, bar$0()] ); }
"#,
expect![[r#"
- *bar()*
- ```rust
- u32
- ```
- "#]],
- );
-}
+ *bar*
-#[test]
-fn test_hover_through_literal_string_in_macro() {
- check(
- r#"
-macro_rules! arr { ($($tt:tt)*) => { [$($tt)*] } }
-fn foo() {
- let mastered_for_itunes = "";
- let _ = arr!("Tr$0acks", &mastered_for_itunes);
-}
-"#,
- expect![[r#"
- *"Tracks"*
- ```rust
- &str
- ```
- "#]],
+ ```rust
+ test
+ ```
+
+ ```rust
+ fn bar() -> u32
+ ```
+ "#]],
);
}
@@ -1515,6 +1467,8 @@ fn my() {}
fn test_hover_struct_doc_comment() {
check(
r#"
+//- /main.rs target_data_layout:e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128
+
/// This is an example
/// multiline doc
///
@@ -1573,7 +1527,7 @@ fn foo() { let bar = Ba$0r; }
```
```rust
- struct Bar // size = 0, align = 1
+ struct Bar
```
---
@@ -1602,7 +1556,7 @@ fn foo() { let bar = Ba$0r; }
```
```rust
- struct Bar // size = 0, align = 1
+ struct Bar
```
---
@@ -1630,7 +1584,7 @@ pub struct B$0ar
```
```rust
- pub struct Bar // size = 0, align = 1
+ pub struct Bar
```
---
@@ -1657,7 +1611,7 @@ pub struct B$0ar
```
```rust
- pub struct Bar // size = 0, align = 1
+ pub struct Bar
```
---
@@ -2959,6 +2913,8 @@ fn main() { let foo_test = name_with_dashes::wrapper::Thing::new$0(); }
fn hover_field_pat_shorthand_ref_match_ergonomics() {
check(
r#"
+//- /main.rs target_data_layout:e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128
+
struct S {
f: i32,
}
@@ -4398,6 +4354,7 @@ fn main() {
fn hover_intra_doc_links() {
check(
r#"
+//- /main.rs target_data_layout:e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128
pub mod theitem {
/// This is the item. Cool!
@@ -4539,7 +4496,7 @@ trait A where
fn string_shadowed_with_inner_items() {
check(
r#"
-//- /main.rs crate:main deps:alloc
+//- /main.rs crate:main deps:alloc target_data_layout:e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128
/// Custom `String` type.
struct String;
@@ -5234,7 +5191,7 @@ foo_macro!(
```
```rust
- pub struct Foo // size = 0, align = 1
+ pub struct Foo
```
---
@@ -5248,6 +5205,8 @@ foo_macro!(
fn hover_intra_in_attr() {
check(
r#"
+//- /main.rs target_data_layout:e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128
+
#[doc = "Doc comment for [`Foo$0`]"]
pub struct Foo(i32);
"#,
@@ -5368,6 +5327,8 @@ enum Enum {
fn hover_record_variant_field() {
check(
r#"
+//- /main.rs target_data_layout:e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128
+
enum Enum {
RecordV { field$0: u32 }
}
@@ -5573,3 +5534,116 @@ fn main() {
"#]],
);
}
+
+#[test]
+fn hover_underscore_pat() {
+ check(
+ r#"
+fn main() {
+ let _$0 = 0;
+}
+"#,
+ expect![[r#"
+ *_*
+ ```rust
+ i32
+ ```
+ "#]],
+ );
+ check(
+ r#"
+fn main() {
+ let (_$0,) = (0,);
+}
+"#,
+ expect![[r#"
+ *_*
+ ```rust
+ i32
+ ```
+ "#]],
+ );
+}
+
+#[test]
+fn hover_underscore_expr() {
+ check(
+ r#"
+fn main() {
+ _$0 = 0;
+}
+"#,
+ expect![[r#"
+ *_*
+ ```rust
+ i32
+ ```
+ "#]],
+ );
+ check(
+ r#"
+fn main() {
+ (_$0,) = (0,);
+}
+"#,
+ expect![[r#"
+ *_*
+ ```rust
+ i32
+ ```
+ "#]],
+ );
+}
+
+#[test]
+fn hover_underscore_type() {
+ check_hover_no_result(
+ r#"
+fn main() {
+ let x: _$0 = 0;
+}
+"#,
+ );
+ check_hover_no_result(
+ r#"
+fn main() {
+ let x: (_$0,) = (0,);
+}
+"#,
+ );
+}
+
+#[test]
+fn hover_call_parens() {
+ check(
+ r#"
+fn foo() -> i32 {}
+fn main() {
+ foo($0);
+}
+"#,
+ expect![[r#"
+ *)*
+ ```rust
+ i32
+ ```
+ "#]],
+ );
+ check(
+ r#"
+struct S;
+impl S {
+ fn foo(self) -> i32 {}
+}
+fn main() {
+ S.foo($0);
+}
+"#,
+ expect![[r#"
+ *)*
+ ```rust
+ i32
+ ```
+ "#]],
+ );
+}
diff --git a/src/tools/rust-analyzer/crates/ide/src/inlay_hints.rs b/src/tools/rust-analyzer/crates/ide/src/inlay_hints.rs
index 48a7bbfec..ac477339e 100644
--- a/src/tools/rust-analyzer/crates/ide/src/inlay_hints.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/inlay_hints.rs
@@ -4,13 +4,16 @@ use std::{
};
use either::Either;
-use hir::{known, HasVisibility, HirDisplay, HirWrite, ModuleDef, ModuleDefId, Semantics};
+use hir::{
+ known, HasVisibility, HirDisplay, HirDisplayError, HirWrite, ModuleDef, ModuleDefId, Semantics,
+};
use ide_db::{base_db::FileRange, famous_defs::FamousDefs, RootDatabase};
use itertools::Itertools;
+use smallvec::{smallvec, SmallVec};
use stdx::never;
use syntax::{
ast::{self, AstNode},
- match_ast, NodeOrToken, SyntaxNode, TextRange, TextSize,
+ match_ast, NodeOrToken, SyntaxNode, TextRange,
};
use crate::{navigation_target::TryToNav, FileId};
@@ -28,7 +31,6 @@ mod discriminant;
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct InlayHintsConfig {
- pub location_links: bool,
pub render_colons: bool,
pub type_hints: bool,
pub discriminant_hints: DiscriminantHints,
@@ -83,75 +85,108 @@ pub enum AdjustmentHintsMode {
PreferPostfix,
}
-#[derive(Clone, Debug, PartialEq, Eq)]
+#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum InlayKind {
- BindingModeHint,
- ChainingHint,
- ClosingBraceHint,
- ClosureReturnTypeHint,
- GenericParamListHint,
- AdjustmentHint,
- AdjustmentHintPostfix,
- LifetimeHint,
- ParameterHint,
- TypeHint,
- DiscriminantHint,
+ BindingMode,
+ Chaining,
+ ClosingBrace,
+ ClosureReturnType,
+ GenericParamList,
+ Adjustment,
+ AdjustmentPostfix,
+ Lifetime,
+ Parameter,
+ Type,
+ Discriminant,
OpeningParenthesis,
ClosingParenthesis,
}
#[derive(Debug)]
pub struct InlayHint {
+ /// The text range this inlay hint applies to.
pub range: TextRange,
+ /// The kind of this inlay hint. This is used to determine side and padding of the hint for
+ /// rendering purposes.
pub kind: InlayKind,
+ /// The actual label to show in the inlay hint.
pub label: InlayHintLabel,
- pub tooltip: Option<InlayTooltip>,
+}
+
+impl InlayHint {
+ fn closing_paren(range: TextRange) -> InlayHint {
+ InlayHint { range, kind: InlayKind::ClosingParenthesis, label: InlayHintLabel::from(")") }
+ }
+ fn opening_paren(range: TextRange) -> InlayHint {
+ InlayHint { range, kind: InlayKind::OpeningParenthesis, label: InlayHintLabel::from("(") }
+ }
}
#[derive(Debug)]
pub enum InlayTooltip {
String(String),
- HoverRanged(FileId, TextRange),
- HoverOffset(FileId, TextSize),
+ Markdown(String),
}
#[derive(Default)]
pub struct InlayHintLabel {
- pub parts: Vec<InlayHintLabelPart>,
+ pub parts: SmallVec<[InlayHintLabelPart; 1]>,
}
impl InlayHintLabel {
- pub fn as_simple_str(&self) -> Option<&str> {
- match &*self.parts {
- [part] => part.as_simple_str(),
- _ => None,
+ pub fn simple(
+ s: impl Into<String>,
+ tooltip: Option<InlayTooltip>,
+ linked_location: Option<FileRange>,
+ ) -> InlayHintLabel {
+ InlayHintLabel {
+ parts: smallvec![InlayHintLabelPart { text: s.into(), linked_location, tooltip }],
}
}
pub fn prepend_str(&mut self, s: &str) {
match &mut *self.parts {
- [part, ..] if part.as_simple_str().is_some() => part.text = format!("{s}{}", part.text),
- _ => self.parts.insert(0, InlayHintLabelPart { text: s.into(), linked_location: None }),
+ [InlayHintLabelPart { text, linked_location: None, tooltip: None }, ..] => {
+ text.insert_str(0, s)
+ }
+ _ => self.parts.insert(
+ 0,
+ InlayHintLabelPart { text: s.into(), linked_location: None, tooltip: None },
+ ),
}
}
pub fn append_str(&mut self, s: &str) {
match &mut *self.parts {
- [.., part] if part.as_simple_str().is_some() => part.text.push_str(s),
- _ => self.parts.push(InlayHintLabelPart { text: s.into(), linked_location: None }),
+ [.., InlayHintLabelPart { text, linked_location: None, tooltip: None }] => {
+ text.push_str(s)
+ }
+ _ => self.parts.push(InlayHintLabelPart {
+ text: s.into(),
+ linked_location: None,
+ tooltip: None,
+ }),
}
}
}
impl From<String> for InlayHintLabel {
fn from(s: String) -> Self {
- Self { parts: vec![InlayHintLabelPart { text: s, linked_location: None }] }
+ Self {
+ parts: smallvec![InlayHintLabelPart { text: s, linked_location: None, tooltip: None }],
+ }
}
}
impl From<&str> for InlayHintLabel {
fn from(s: &str) -> Self {
- Self { parts: vec![InlayHintLabelPart { text: s.into(), linked_location: None }] }
+ Self {
+ parts: smallvec![InlayHintLabelPart {
+ text: s.into(),
+ linked_location: None,
+ tooltip: None
+ }],
+ }
}
}
@@ -175,25 +210,25 @@ pub struct InlayHintLabelPart {
/// When setting this, no tooltip must be set on the containing hint, or VS Code will display
/// them both.
pub linked_location: Option<FileRange>,
-}
-
-impl InlayHintLabelPart {
- pub fn as_simple_str(&self) -> Option<&str> {
- match self {
- Self { text, linked_location: None } => Some(text),
- _ => None,
- }
- }
+ /// The tooltip to show when hovering over the inlay hint, this may invoke other actions like
+ /// hover requests to show.
+ pub tooltip: Option<InlayTooltip>,
}
impl fmt::Debug for InlayHintLabelPart {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- match self.as_simple_str() {
- Some(string) => string.fmt(f),
- None => f
+ match self {
+ Self { text, linked_location: None, tooltip: None } => text.fmt(f),
+ Self { text, linked_location, tooltip } => f
.debug_struct("InlayHintLabelPart")
- .field("text", &self.text)
- .field("linked_location", &self.linked_location)
+ .field("text", text)
+ .field("linked_location", linked_location)
+ .field(
+ "tooltip",
+ &tooltip.as_ref().map_or("", |it| match it {
+ InlayTooltip::String(it) | InlayTooltip::Markdown(it) => it,
+ }),
+ )
.finish(),
}
}
@@ -204,7 +239,6 @@ struct InlayHintLabelBuilder<'a> {
db: &'a RootDatabase,
result: InlayHintLabel,
last_part: String,
- location_link_enabled: bool,
location: Option<FileRange>,
}
@@ -216,9 +250,6 @@ impl fmt::Write for InlayHintLabelBuilder<'_> {
impl HirWrite for InlayHintLabelBuilder<'_> {
fn start_location_link(&mut self, def: ModuleDefId) {
- if !self.location_link_enabled {
- return;
- }
if self.location.is_some() {
never!("location link is already started");
}
@@ -230,9 +261,6 @@ impl HirWrite for InlayHintLabelBuilder<'_> {
}
fn end_location_link(&mut self) {
- if !self.location_link_enabled {
- return;
- }
self.make_new_part();
}
}
@@ -242,6 +270,7 @@ impl InlayHintLabelBuilder<'_> {
self.result.parts.push(InlayHintLabelPart {
text: take(&mut self.last_part),
linked_location: self.location.take(),
+ tooltip: None,
});
}
@@ -262,34 +291,51 @@ fn label_of_ty(
mut max_length: Option<usize>,
ty: hir::Type,
label_builder: &mut InlayHintLabelBuilder<'_>,
- ) {
+ ) -> Result<(), HirDisplayError> {
let iter_item_type = hint_iterator(sema, famous_defs, &ty);
match iter_item_type {
- Some(ty) => {
- const LABEL_START: &str = "impl Iterator<Item = ";
+ Some((iter_trait, item, ty)) => {
+ const LABEL_START: &str = "impl ";
+ const LABEL_ITERATOR: &str = "Iterator";
+ const LABEL_MIDDLE: &str = "<";
+ const LABEL_ITEM: &str = "Item";
+ const LABEL_MIDDLE2: &str = " = ";
const LABEL_END: &str = ">";
- max_length =
- max_length.map(|len| len.saturating_sub(LABEL_START.len() + LABEL_END.len()));
-
- label_builder.write_str(LABEL_START).unwrap();
- rec(sema, famous_defs, max_length, ty, label_builder);
- label_builder.write_str(LABEL_END).unwrap();
- }
- None => {
- let _ = ty.display_truncated(sema.db, max_length).write_to(label_builder);
+ max_length = max_length.map(|len| {
+ len.saturating_sub(
+ LABEL_START.len()
+ + LABEL_ITERATOR.len()
+ + LABEL_MIDDLE.len()
+ + LABEL_MIDDLE2.len()
+ + LABEL_END.len(),
+ )
+ });
+
+ label_builder.write_str(LABEL_START)?;
+ label_builder.start_location_link(ModuleDef::from(iter_trait).into());
+ label_builder.write_str(LABEL_ITERATOR)?;
+ label_builder.end_location_link();
+ label_builder.write_str(LABEL_MIDDLE)?;
+ label_builder.start_location_link(ModuleDef::from(item).into());
+ label_builder.write_str(LABEL_ITEM)?;
+ label_builder.end_location_link();
+ label_builder.write_str(LABEL_MIDDLE2)?;
+ rec(sema, famous_defs, max_length, ty, label_builder)?;
+ label_builder.write_str(LABEL_END)?;
+ Ok(())
}
- };
+ None => ty.display_truncated(sema.db, max_length).write_to(label_builder),
+ }
}
let mut label_builder = InlayHintLabelBuilder {
db: sema.db,
last_part: String::new(),
location: None,
- location_link_enabled: config.location_links,
result: InlayHintLabel::default(),
};
- rec(sema, famous_defs, config.max_length, ty, &mut label_builder);
+ let _ = rec(sema, famous_defs, config.max_length, ty, &mut label_builder);
let r = label_builder.finish();
Some(r)
}
@@ -383,11 +429,9 @@ fn hints(
// static type elisions
ast::Item::Static(it) => implicit_static::hints(hints, config, Either::Left(it)),
ast::Item::Const(it) => implicit_static::hints(hints, config, Either::Right(it)),
+ ast::Item::Enum(it) => discriminant::enum_hints(hints, famous_defs, config, file_id, it),
_ => None,
},
- ast::Variant(v) => {
- discriminant::hints(hints, famous_defs, config, file_id, &v)
- },
// FIXME: fn-ptr type, dyn fn type, and trait object type elisions
ast::Type(_) => None,
_ => None,
@@ -395,12 +439,12 @@ fn hints(
};
}
-/// Checks if the type is an Iterator from std::iter and returns its item type.
+/// Checks if the type is an Iterator from std::iter and returns the iterator trait and the item type of the concrete iterator.
fn hint_iterator(
sema: &Semantics<'_, RootDatabase>,
famous_defs: &FamousDefs<'_, '_>,
ty: &hir::Type,
-) -> Option<hir::Type> {
+) -> Option<(hir::Trait, hir::TypeAlias, hir::Type)> {
let db = sema.db;
let strukt = ty.strip_references().as_adt()?;
let krate = strukt.module(db).krate();
@@ -423,7 +467,7 @@ fn hint_iterator(
_ => None,
})?;
if let Some(ty) = ty.normalize_trait_assoc_type(db, &[], assoc_type_item) {
- return Some(ty);
+ return Some((iter_trait, assoc_type_item, ty));
}
}
@@ -447,7 +491,6 @@ mod tests {
use super::ClosureReturnTypeHints;
pub(super) const DISABLED_CONFIG: InlayHintsConfig = InlayHintsConfig {
- location_links: false,
discriminant_hints: DiscriminantHints::Never,
render_colons: false,
type_hints: false,
@@ -465,8 +508,6 @@ mod tests {
max_length: None,
closing_brace_hints_min_lines: None,
};
- pub(super) const DISABLED_CONFIG_WITH_LINKS: InlayHintsConfig =
- InlayHintsConfig { location_links: true, ..DISABLED_CONFIG };
pub(super) const TEST_CONFIG: InlayHintsConfig = InlayHintsConfig {
type_hints: true,
parameter_hints: true,
@@ -474,7 +515,7 @@ mod tests {
closure_return_type_hints: ClosureReturnTypeHints::WithBlock,
binding_mode_hints: true,
lifetime_elision_hints: LifetimeElisionHints::Always,
- ..DISABLED_CONFIG_WITH_LINKS
+ ..DISABLED_CONFIG
};
#[track_caller]
diff --git a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/adjustment.rs b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/adjustment.rs
index bdd7c05e0..188eb7f97 100644
--- a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/adjustment.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/adjustment.rs
@@ -3,15 +3,19 @@
//! let _: u32 = /* <never-to-any> */ loop {};
//! let _: &u32 = /* &* */ &mut 0;
//! ```
-use hir::{Adjust, AutoBorrow, Mutability, OverloadedDeref, PointerCast, Safety, Semantics};
+use hir::{Adjust, Adjustment, AutoBorrow, HirDisplay, Mutability, PointerCast, Safety, Semantics};
use ide_db::RootDatabase;
+use stdx::never;
use syntax::{
ast::{self, make, AstNode},
ted,
};
-use crate::{AdjustmentHints, AdjustmentHintsMode, InlayHint, InlayHintsConfig, InlayKind};
+use crate::{
+ AdjustmentHints, AdjustmentHintsMode, InlayHint, InlayHintLabel, InlayHintsConfig, InlayKind,
+ InlayTooltip,
+};
pub(super) fn hints(
acc: &mut Vec<InlayHint>,
@@ -44,27 +48,12 @@ pub(super) fn hints(
mode_and_needs_parens_for_adjustment_hints(expr, config.adjustment_hints_mode);
if needs_outer_parens {
- acc.push(InlayHint {
- range: expr.syntax().text_range(),
- kind: InlayKind::OpeningParenthesis,
- label: "(".into(),
- tooltip: None,
- });
+ acc.push(InlayHint::opening_paren(expr.syntax().text_range()));
}
if postfix && needs_inner_parens {
- acc.push(InlayHint {
- range: expr.syntax().text_range(),
- kind: InlayKind::OpeningParenthesis,
- label: "(".into(),
- tooltip: None,
- });
- acc.push(InlayHint {
- range: expr.syntax().text_range(),
- kind: InlayKind::ClosingParenthesis,
- label: ")".into(),
- tooltip: None,
- });
+ acc.push(InlayHint::opening_paren(expr.syntax().text_range()));
+ acc.push(InlayHint::closing_paren(expr.syntax().text_range()));
}
let (mut tmp0, mut tmp1);
@@ -76,72 +65,71 @@ pub(super) fn hints(
&mut tmp1
};
- for adjustment in iter {
- if adjustment.source == adjustment.target {
+ for Adjustment { source, target, kind } in iter {
+ if source == target {
continue;
}
// FIXME: Add some nicer tooltips to each of these
- let text = match adjustment.kind {
+ let (text, coercion) = match kind {
Adjust::NeverToAny if config.adjustment_hints == AdjustmentHints::Always => {
- "<never-to-any>"
+ ("<never-to-any>", "never to any")
+ }
+ Adjust::Deref(_) => ("*", "dereference"),
+ Adjust::Borrow(AutoBorrow::Ref(Mutability::Shared)) => ("&", "borrow"),
+ Adjust::Borrow(AutoBorrow::Ref(Mutability::Mut)) => ("&mut ", "unique borrow"),
+ Adjust::Borrow(AutoBorrow::RawPtr(Mutability::Shared)) => {
+ ("&raw const ", "const pointer borrow")
+ }
+ Adjust::Borrow(AutoBorrow::RawPtr(Mutability::Mut)) => {
+ ("&raw mut ", "mut pointer borrow")
}
- Adjust::Deref(None) => "*",
- Adjust::Deref(Some(OverloadedDeref(Mutability::Mut))) => "*",
- Adjust::Deref(Some(OverloadedDeref(Mutability::Shared))) => "*",
- Adjust::Borrow(AutoBorrow::Ref(Mutability::Shared)) => "&",
- Adjust::Borrow(AutoBorrow::Ref(Mutability::Mut)) => "&mut ",
- Adjust::Borrow(AutoBorrow::RawPtr(Mutability::Shared)) => "&raw const ",
- Adjust::Borrow(AutoBorrow::RawPtr(Mutability::Mut)) => "&raw mut ",
// some of these could be represented via `as` casts, but that's not too nice and
// handling everything as a prefix expr makes the `(` and `)` insertion easier
Adjust::Pointer(cast) if config.adjustment_hints == AdjustmentHints::Always => {
match cast {
- PointerCast::ReifyFnPointer => "<fn-item-to-fn-pointer>",
- PointerCast::UnsafeFnPointer => "<safe-fn-pointer-to-unsafe-fn-pointer>",
+ PointerCast::ReifyFnPointer => {
+ ("<fn-item-to-fn-pointer>", "fn item to fn pointer")
+ }
+ PointerCast::UnsafeFnPointer => (
+ "<safe-fn-pointer-to-unsafe-fn-pointer>",
+ "safe fn pointer to unsafe fn pointer",
+ ),
PointerCast::ClosureFnPointer(Safety::Unsafe) => {
- "<closure-to-unsafe-fn-pointer>"
+ ("<closure-to-unsafe-fn-pointer>", "closure to unsafe fn pointer")
+ }
+ PointerCast::ClosureFnPointer(Safety::Safe) => {
+ ("<closure-to-fn-pointer>", "closure to fn pointer")
+ }
+ PointerCast::MutToConstPointer => {
+ ("<mut-ptr-to-const-ptr>", "mut ptr to const ptr")
}
- PointerCast::ClosureFnPointer(Safety::Safe) => "<closure-to-fn-pointer>",
- PointerCast::MutToConstPointer => "<mut-ptr-to-const-ptr>",
- PointerCast::ArrayToPointer => "<array-ptr-to-element-ptr>",
- PointerCast::Unsize => "<unsize>",
+ PointerCast::ArrayToPointer => ("<array-ptr-to-element-ptr>", ""),
+ PointerCast::Unsize => ("<unsize>", "unsize"),
}
}
_ => continue,
};
acc.push(InlayHint {
range: expr.syntax().text_range(),
- kind: if postfix {
- InlayKind::AdjustmentHintPostfix
- } else {
- InlayKind::AdjustmentHint
- },
- label: if postfix { format!(".{}", text.trim_end()).into() } else { text.into() },
- tooltip: None,
+ kind: if postfix { InlayKind::AdjustmentPostfix } else { InlayKind::Adjustment },
+ label: InlayHintLabel::simple(
+ if postfix { format!(".{}", text.trim_end()) } else { text.to_owned() },
+ Some(InlayTooltip::Markdown(format!(
+ "`{}` → `{}` ({coercion} coercion)",
+ source.display(sema.db),
+ target.display(sema.db),
+ ))),
+ None,
+ ),
});
}
if !postfix && needs_inner_parens {
- acc.push(InlayHint {
- range: expr.syntax().text_range(),
- kind: InlayKind::OpeningParenthesis,
- label: "(".into(),
- tooltip: None,
- });
- acc.push(InlayHint {
- range: expr.syntax().text_range(),
- kind: InlayKind::ClosingParenthesis,
- label: ")".into(),
- tooltip: None,
- });
+ acc.push(InlayHint::opening_paren(expr.syntax().text_range()));
+ acc.push(InlayHint::closing_paren(expr.syntax().text_range()));
}
if needs_outer_parens {
- acc.push(InlayHint {
- range: expr.syntax().text_range(),
- kind: InlayKind::ClosingParenthesis,
- label: ")".into(),
- tooltip: None,
- });
+ acc.push(InlayHint::closing_paren(expr.syntax().text_range()));
}
Some(())
}
@@ -223,16 +211,21 @@ fn needs_parens_for_adjustment_hints(expr: &ast::Expr, postfix: bool) -> (bool,
ted::replace(expr.syntax(), dummy_expr.syntax());
let parent = dummy_expr.syntax().parent();
- let expr = if postfix {
- let ast::Expr::TryExpr(e) = &dummy_expr else { unreachable!() };
- let Some(ast::Expr::ParenExpr(e)) = e.expr() else { unreachable!() };
+ let Some(expr) = (|| {
+ if postfix {
+ let ast::Expr::TryExpr(e) = &dummy_expr else { return None };
+ let Some(ast::Expr::ParenExpr(e)) = e.expr() else { return None };
- e.expr().unwrap()
- } else {
- let ast::Expr::RefExpr(e) = &dummy_expr else { unreachable!() };
- let Some(ast::Expr::ParenExpr(e)) = e.expr() else { unreachable!() };
+ e.expr()
+ } else {
+ let ast::Expr::RefExpr(e) = &dummy_expr else { return None };
+ let Some(ast::Expr::ParenExpr(e)) = e.expr() else { return None };
- e.expr().unwrap()
+ e.expr()
+ }
+ })() else {
+ never!("broken syntax tree?\n{:?}\n{:?}", expr, dummy_expr);
+ return (true, true)
};
// At this point
diff --git a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/bind_pat.rs b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/bind_pat.rs
index adec19c76..4af7f9bdb 100644
--- a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/bind_pat.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/bind_pat.rs
@@ -12,9 +12,7 @@ use syntax::{
match_ast,
};
-use crate::{
- inlay_hints::closure_has_block_body, InlayHint, InlayHintsConfig, InlayKind, InlayTooltip,
-};
+use crate::{inlay_hints::closure_has_block_body, InlayHint, InlayHintsConfig, InlayKind};
use super::label_of_ty;
@@ -22,7 +20,7 @@ pub(super) fn hints(
acc: &mut Vec<InlayHint>,
famous_defs @ FamousDefs(sema, _): &FamousDefs<'_, '_>,
config: &InlayHintsConfig,
- file_id: FileId,
+ _file_id: FileId,
pat: &ast::IdentPat,
) -> Option<()> {
if !config.type_hints {
@@ -50,12 +48,8 @@ pub(super) fn hints(
Some(name) => name.syntax().text_range(),
None => pat.syntax().text_range(),
},
- kind: InlayKind::TypeHint,
+ kind: InlayKind::Type,
label,
- tooltip: pat
- .name()
- .map(|it| it.syntax().text_range())
- .map(|it| InlayTooltip::HoverRanged(file_id, it)),
});
Some(())
@@ -73,28 +67,23 @@ fn should_not_display_type_hint(
return true;
}
- if let Some(hir::Adt::Struct(s)) = pat_ty.as_adt() {
- if s.fields(db).is_empty() && s.name(db).to_smol_str() == bind_pat.to_string() {
- return true;
- }
- }
-
- if config.hide_closure_initialization_hints {
- if let Some(parent) = bind_pat.syntax().parent() {
- if let Some(it) = ast::LetStmt::cast(parent) {
- if let Some(ast::Expr::ClosureExpr(closure)) = it.initializer() {
- if closure_has_block_body(&closure) {
- return true;
- }
- }
- }
- }
+ if sema.resolve_bind_pat_to_const(bind_pat).is_some() {
+ return true;
}
for node in bind_pat.syntax().ancestors() {
match_ast! {
match node {
- ast::LetStmt(it) => return it.ty().is_some(),
+ ast::LetStmt(it) => {
+ if config.hide_closure_initialization_hints {
+ if let Some(ast::Expr::ClosureExpr(closure)) = it.initializer() {
+ if closure_has_block_body(&closure) {
+ return true;
+ }
+ }
+ }
+ return it.ty().is_some()
+ },
// FIXME: We might wanna show type hints in parameters for non-top level patterns as well
ast::Param(it) => return it.ty().is_some(),
ast::MatchArm(_) => return pat_is_enum_variant(db, bind_pat, pat_ty),
@@ -194,8 +183,7 @@ mod tests {
use crate::{fixture, inlay_hints::InlayHintsConfig};
use crate::inlay_hints::tests::{
- check, check_expect, check_with_config, DISABLED_CONFIG, DISABLED_CONFIG_WITH_LINKS,
- TEST_CONFIG,
+ check, check_expect, check_with_config, DISABLED_CONFIG, TEST_CONFIG,
};
use crate::ClosureReturnTypeHints;
@@ -291,7 +279,7 @@ fn main() {
fn iterator_hint_regression_issue_12674() {
// Ensure we don't crash while solving the projection type of iterators.
check_expect(
- InlayHintsConfig { chaining_hints: true, ..DISABLED_CONFIG_WITH_LINKS },
+ InlayHintsConfig { chaining_hints: true, ..DISABLED_CONFIG },
r#"
//- minicore: iterators
struct S<T>(T);
@@ -322,22 +310,66 @@ fn main(a: SliceIter<'_, Container>) {
[
InlayHint {
range: 484..554,
- kind: ChainingHint,
+ kind: Chaining,
label: [
- "impl Iterator<Item = impl Iterator<Item = &&str>>",
- ],
- tooltip: Some(
- HoverRanged(
- FileId(
- 0,
+ "impl ",
+ InlayHintLabelPart {
+ text: "Iterator",
+ linked_location: Some(
+ FileRange {
+ file_id: FileId(
+ 1,
+ ),
+ range: 2611..2619,
+ },
+ ),
+ tooltip: "",
+ },
+ "<",
+ InlayHintLabelPart {
+ text: "Item",
+ linked_location: Some(
+ FileRange {
+ file_id: FileId(
+ 1,
+ ),
+ range: 2643..2647,
+ },
+ ),
+ tooltip: "",
+ },
+ " = impl ",
+ InlayHintLabelPart {
+ text: "Iterator",
+ linked_location: Some(
+ FileRange {
+ file_id: FileId(
+ 1,
+ ),
+ range: 2611..2619,
+ },
+ ),
+ tooltip: "",
+ },
+ "<",
+ InlayHintLabelPart {
+ text: "Item",
+ linked_location: Some(
+ FileRange {
+ file_id: FileId(
+ 1,
+ ),
+ range: 2643..2647,
+ },
),
- 484..554,
- ),
- ),
+ tooltip: "",
+ },
+ " = &&str>>",
+ ],
},
InlayHint {
range: 484..485,
- kind: ChainingHint,
+ kind: Chaining,
label: [
"",
InlayHintLabelPart {
@@ -350,6 +382,7 @@ fn main(a: SliceIter<'_, Container>) {
range: 289..298,
},
),
+ tooltip: "",
},
"<",
InlayHintLabelPart {
@@ -362,17 +395,10 @@ fn main(a: SliceIter<'_, Container>) {
range: 238..247,
},
),
+ tooltip: "",
},
">",
],
- tooltip: Some(
- HoverRanged(
- FileId(
- 0,
- ),
- 484..485,
- ),
- ),
},
]
"#]],
@@ -537,6 +563,21 @@ fn main() {
}
#[test]
+ fn const_pats_have_no_type_hints() {
+ check_types(
+ r#"
+const FOO: usize = 0;
+
+fn main() {
+ match 0 {
+ FOO => (),
+ _ => ()
+ }
+}"#,
+ );
+ }
+
+ #[test]
fn let_statement() {
check_types(
r#"
diff --git a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/binding_mode.rs b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/binding_mode.rs
index a0166d004..5d9729263 100644
--- a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/binding_mode.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/binding_mode.rs
@@ -7,7 +7,7 @@ use ide_db::RootDatabase;
use syntax::ast::{self, AstNode};
-use crate::{InlayHint, InlayHintsConfig, InlayKind, InlayTooltip};
+use crate::{InlayHint, InlayHintsConfig, InlayKind};
pub(super) fn hints(
acc: &mut Vec<InlayHint>,
@@ -29,8 +29,17 @@ pub(super) fn hints(
_ => None,
})
.last();
- let range =
- outer_paren_pat.as_ref().map_or_else(|| pat.syntax(), |it| it.syntax()).text_range();
+ let range = outer_paren_pat.as_ref().map_or_else(
+ || match pat {
+ // for ident patterns that @ bind a name, render the un-ref patterns in front of the inner pattern
+ // instead of the name as that makes it more clear and doesn't really change the outcome
+ ast::Pat::IdentPat(it) => {
+ it.pat().map_or_else(|| it.syntax().text_range(), |it| it.syntax().text_range())
+ }
+ it => it.syntax().text_range(),
+ },
+ |it| it.syntax().text_range(),
+ );
let pattern_adjustments = sema.pattern_adjustments(pat);
pattern_adjustments.iter().for_each(|ty| {
let reference = ty.is_reference();
@@ -40,12 +49,7 @@ pub(super) fn hints(
(true, false) => "&",
_ => return,
};
- acc.push(InlayHint {
- range,
- kind: InlayKind::BindingModeHint,
- label: r.to_string().into(),
- tooltip: Some(InlayTooltip::String("Inferred binding mode".into())),
- });
+ acc.push(InlayHint { range, kind: InlayKind::BindingMode, label: r.to_string().into() });
});
match pat {
ast::Pat::IdentPat(pat) if pat.ref_token().is_none() && pat.mut_token().is_none() => {
@@ -57,24 +61,13 @@ pub(super) fn hints(
};
acc.push(InlayHint {
range: pat.syntax().text_range(),
- kind: InlayKind::BindingModeHint,
+ kind: InlayKind::BindingMode,
label: bm.to_string().into(),
- tooltip: Some(InlayTooltip::String("Inferred binding mode".into())),
});
}
ast::Pat::OrPat(pat) if !pattern_adjustments.is_empty() && outer_paren_pat.is_none() => {
- acc.push(InlayHint {
- range: pat.syntax().text_range(),
- kind: InlayKind::OpeningParenthesis,
- label: "(".into(),
- tooltip: None,
- });
- acc.push(InlayHint {
- range: pat.syntax().text_range(),
- kind: InlayKind::ClosingParenthesis,
- label: ")".into(),
- tooltip: None,
- });
+ acc.push(InlayHint::opening_paren(pat.syntax().text_range()));
+ acc.push(InlayHint::closing_paren(pat.syntax().text_range()));
}
_ => (),
}
@@ -139,4 +132,20 @@ fn __(
}"#,
);
}
+
+ #[test]
+ fn hints_binding_modes_complex_ident_pat() {
+ check_with_config(
+ InlayHintsConfig { binding_mode_hints: true, ..DISABLED_CONFIG },
+ r#"
+struct Struct {
+ field: &'static str,
+}
+fn foo(s @ Struct { field, .. }: &Struct) {}
+ //^^^^^^^^^^^^^^^^^^^^^^^^ref
+ //^^^^^^^^^^^^^^^^^^^^&
+ //^^^^^ref
+"#,
+ );
+ }
}
diff --git a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/chaining.rs b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/chaining.rs
index 8810d5d34..0c54f084c 100644
--- a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/chaining.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/chaining.rs
@@ -5,7 +5,7 @@ use syntax::{
Direction, NodeOrToken, SyntaxKind, T,
};
-use crate::{FileId, InlayHint, InlayHintsConfig, InlayKind, InlayTooltip};
+use crate::{FileId, InlayHint, InlayHintsConfig, InlayKind};
use super::label_of_ty;
@@ -13,7 +13,7 @@ pub(super) fn hints(
acc: &mut Vec<InlayHint>,
famous_defs @ FamousDefs(sema, _): &FamousDefs<'_, '_>,
config: &InlayHintsConfig,
- file_id: FileId,
+ _file_id: FileId,
expr: &ast::Expr,
) -> Option<()> {
if !config.chaining_hints {
@@ -59,9 +59,8 @@ pub(super) fn hints(
}
acc.push(InlayHint {
range: expr.syntax().text_range(),
- kind: InlayKind::ChainingHint,
+ kind: InlayKind::Chaining,
label: label_of_ty(famous_defs, config, ty)?,
- tooltip: Some(InlayTooltip::HoverRanged(file_id, expr.syntax().text_range())),
});
}
}
@@ -73,10 +72,7 @@ mod tests {
use expect_test::expect;
use crate::{
- inlay_hints::tests::{
- check_expect, check_with_config, DISABLED_CONFIG, DISABLED_CONFIG_WITH_LINKS,
- TEST_CONFIG,
- },
+ inlay_hints::tests::{check_expect, check_with_config, DISABLED_CONFIG, TEST_CONFIG},
InlayHintsConfig,
};
@@ -88,11 +84,7 @@ mod tests {
#[test]
fn chaining_hints_ignore_comments() {
check_expect(
- InlayHintsConfig {
- type_hints: false,
- chaining_hints: true,
- ..DISABLED_CONFIG_WITH_LINKS
- },
+ InlayHintsConfig { type_hints: false, chaining_hints: true, ..DISABLED_CONFIG },
r#"
struct A(B);
impl A { fn into_b(self) -> B { self.0 } }
@@ -111,7 +103,7 @@ fn main() {
[
InlayHint {
range: 147..172,
- kind: ChainingHint,
+ kind: Chaining,
label: [
"",
InlayHintLabelPart {
@@ -124,21 +116,14 @@ fn main() {
range: 63..64,
},
),
+ tooltip: "",
},
"",
],
- tooltip: Some(
- HoverRanged(
- FileId(
- 0,
- ),
- 147..172,
- ),
- ),
},
InlayHint {
range: 147..154,
- kind: ChainingHint,
+ kind: Chaining,
label: [
"",
InlayHintLabelPart {
@@ -151,17 +136,10 @@ fn main() {
range: 7..8,
},
),
+ tooltip: "",
},
"",
],
- tooltip: Some(
- HoverRanged(
- FileId(
- 0,
- ),
- 147..154,
- ),
- ),
},
]
"#]],
@@ -210,33 +188,43 @@ fn main() {
[
InlayHint {
range: 143..190,
- kind: ChainingHint,
+ kind: Chaining,
label: [
- "C",
- ],
- tooltip: Some(
- HoverRanged(
- FileId(
- 0,
+ "",
+ InlayHintLabelPart {
+ text: "C",
+ linked_location: Some(
+ FileRange {
+ file_id: FileId(
+ 0,
+ ),
+ range: 51..52,
+ },
),
- 143..190,
- ),
- ),
+ tooltip: "",
+ },
+ "",
+ ],
},
InlayHint {
range: 143..179,
- kind: ChainingHint,
+ kind: Chaining,
label: [
- "B",
- ],
- tooltip: Some(
- HoverRanged(
- FileId(
- 0,
+ "",
+ InlayHintLabelPart {
+ text: "B",
+ linked_location: Some(
+ FileRange {
+ file_id: FileId(
+ 0,
+ ),
+ range: 29..30,
+ },
),
- 143..179,
- ),
- ),
+ tooltip: "",
+ },
+ "",
+ ],
},
]
"#]],
@@ -246,7 +234,7 @@ fn main() {
#[test]
fn struct_access_chaining_hints() {
check_expect(
- InlayHintsConfig { chaining_hints: true, ..DISABLED_CONFIG_WITH_LINKS },
+ InlayHintsConfig { chaining_hints: true, ..DISABLED_CONFIG },
r#"
struct A { pub b: B }
struct B { pub c: C }
@@ -269,7 +257,7 @@ fn main() {
[
InlayHint {
range: 143..190,
- kind: ChainingHint,
+ kind: Chaining,
label: [
"",
InlayHintLabelPart {
@@ -282,21 +270,14 @@ fn main() {
range: 51..52,
},
),
+ tooltip: "",
},
"",
],
- tooltip: Some(
- HoverRanged(
- FileId(
- 0,
- ),
- 143..190,
- ),
- ),
},
InlayHint {
range: 143..179,
- kind: ChainingHint,
+ kind: Chaining,
label: [
"",
InlayHintLabelPart {
@@ -309,17 +290,10 @@ fn main() {
range: 29..30,
},
),
+ tooltip: "",
},
"",
],
- tooltip: Some(
- HoverRanged(
- FileId(
- 0,
- ),
- 143..179,
- ),
- ),
},
]
"#]],
@@ -329,7 +303,7 @@ fn main() {
#[test]
fn generic_chaining_hints() {
check_expect(
- InlayHintsConfig { chaining_hints: true, ..DISABLED_CONFIG_WITH_LINKS },
+ InlayHintsConfig { chaining_hints: true, ..DISABLED_CONFIG },
r#"
struct A<T>(T);
struct B<T>(T);
@@ -353,7 +327,7 @@ fn main() {
[
InlayHint {
range: 246..283,
- kind: ChainingHint,
+ kind: Chaining,
label: [
"",
InlayHintLabelPart {
@@ -366,6 +340,7 @@ fn main() {
range: 23..24,
},
),
+ tooltip: "",
},
"<",
InlayHintLabelPart {
@@ -378,21 +353,14 @@ fn main() {
range: 55..56,
},
),
+ tooltip: "",
},
"<i32, bool>>",
],
- tooltip: Some(
- HoverRanged(
- FileId(
- 0,
- ),
- 246..283,
- ),
- ),
},
InlayHint {
range: 246..265,
- kind: ChainingHint,
+ kind: Chaining,
label: [
"",
InlayHintLabelPart {
@@ -405,6 +373,7 @@ fn main() {
range: 7..8,
},
),
+ tooltip: "",
},
"<",
InlayHintLabelPart {
@@ -417,17 +386,10 @@ fn main() {
range: 55..56,
},
),
+ tooltip: "",
},
"<i32, bool>>",
],
- tooltip: Some(
- HoverRanged(
- FileId(
- 0,
- ),
- 246..265,
- ),
- ),
},
]
"#]],
@@ -437,7 +399,7 @@ fn main() {
#[test]
fn shorten_iterator_chaining_hints() {
check_expect(
- InlayHintsConfig { chaining_hints: true, ..DISABLED_CONFIG_WITH_LINKS },
+ InlayHintsConfig { chaining_hints: true, ..DISABLED_CONFIG },
r#"
//- minicore: iterators
use core::iter;
@@ -463,52 +425,106 @@ fn main() {
[
InlayHint {
range: 174..241,
- kind: ChainingHint,
+ kind: Chaining,
label: [
- "impl Iterator<Item = ()>",
- ],
- tooltip: Some(
- HoverRanged(
- FileId(
- 0,
+ "impl ",
+ InlayHintLabelPart {
+ text: "Iterator",
+ linked_location: Some(
+ FileRange {
+ file_id: FileId(
+ 1,
+ ),
+ range: 2611..2619,
+ },
+ ),
+ tooltip: "",
+ },
+ "<",
+ InlayHintLabelPart {
+ text: "Item",
+ linked_location: Some(
+ FileRange {
+ file_id: FileId(
+ 1,
+ ),
+ range: 2643..2647,
+ },
),
- 174..241,
- ),
- ),
+ tooltip: "",
+ },
+ " = ()>",
+ ],
},
InlayHint {
range: 174..224,
- kind: ChainingHint,
+ kind: Chaining,
label: [
- "impl Iterator<Item = ()>",
- ],
- tooltip: Some(
- HoverRanged(
- FileId(
- 0,
+ "impl ",
+ InlayHintLabelPart {
+ text: "Iterator",
+ linked_location: Some(
+ FileRange {
+ file_id: FileId(
+ 1,
+ ),
+ range: 2611..2619,
+ },
),
- 174..224,
- ),
- ),
+ tooltip: "",
+ },
+ "<",
+ InlayHintLabelPart {
+ text: "Item",
+ linked_location: Some(
+ FileRange {
+ file_id: FileId(
+ 1,
+ ),
+ range: 2643..2647,
+ },
+ ),
+ tooltip: "",
+ },
+ " = ()>",
+ ],
},
InlayHint {
range: 174..206,
- kind: ChainingHint,
+ kind: Chaining,
label: [
- "impl Iterator<Item = ()>",
- ],
- tooltip: Some(
- HoverRanged(
- FileId(
- 0,
+ "impl ",
+ InlayHintLabelPart {
+ text: "Iterator",
+ linked_location: Some(
+ FileRange {
+ file_id: FileId(
+ 1,
+ ),
+ range: 2611..2619,
+ },
),
- 174..206,
- ),
- ),
+ tooltip: "",
+ },
+ "<",
+ InlayHintLabelPart {
+ text: "Item",
+ linked_location: Some(
+ FileRange {
+ file_id: FileId(
+ 1,
+ ),
+ range: 2643..2647,
+ },
+ ),
+ tooltip: "",
+ },
+ " = ()>",
+ ],
},
InlayHint {
range: 174..189,
- kind: ChainingHint,
+ kind: Chaining,
label: [
"&mut ",
InlayHintLabelPart {
@@ -521,17 +537,10 @@ fn main() {
range: 24..30,
},
),
+ tooltip: "",
},
"",
],
- tooltip: Some(
- HoverRanged(
- FileId(
- 0,
- ),
- 174..189,
- ),
- ),
},
]
"#]],
@@ -564,7 +573,7 @@ fn main() {
[
InlayHint {
range: 124..130,
- kind: TypeHint,
+ kind: Type,
label: [
"",
InlayHintLabelPart {
@@ -577,21 +586,14 @@ fn main() {
range: 7..13,
},
),
+ tooltip: "",
},
"",
],
- tooltip: Some(
- HoverRanged(
- FileId(
- 0,
- ),
- 124..130,
- ),
- ),
},
InlayHint {
range: 145..185,
- kind: ChainingHint,
+ kind: Chaining,
label: [
"",
InlayHintLabelPart {
@@ -604,21 +606,14 @@ fn main() {
range: 7..13,
},
),
+ tooltip: "",
},
"",
],
- tooltip: Some(
- HoverRanged(
- FileId(
- 0,
- ),
- 145..185,
- ),
- ),
},
InlayHint {
range: 145..168,
- kind: ChainingHint,
+ kind: Chaining,
label: [
"",
InlayHintLabelPart {
@@ -631,32 +626,28 @@ fn main() {
range: 7..13,
},
),
+ tooltip: "",
},
"",
],
- tooltip: Some(
- HoverRanged(
- FileId(
- 0,
- ),
- 145..168,
- ),
- ),
},
InlayHint {
range: 222..228,
- kind: ParameterHint,
+ kind: Parameter,
label: [
- "self",
- ],
- tooltip: Some(
- HoverOffset(
- FileId(
- 0,
+ InlayHintLabelPart {
+ text: "self",
+ linked_location: Some(
+ FileRange {
+ file_id: FileId(
+ 0,
+ ),
+ range: 42..46,
+ },
),
- 42,
- ),
- ),
+ tooltip: "",
+ },
+ ],
},
]
"#]],
diff --git a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/closing_brace.rs b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/closing_brace.rs
index e340c64c5..14c11be54 100644
--- a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/closing_brace.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/closing_brace.rs
@@ -10,9 +10,7 @@ use syntax::{
match_ast, SyntaxKind, SyntaxNode, T,
};
-use crate::{
- inlay_hints::InlayHintLabelPart, FileId, InlayHint, InlayHintLabel, InlayHintsConfig, InlayKind,
-};
+use crate::{FileId, InlayHint, InlayHintLabel, InlayHintsConfig, InlayKind};
pub(super) fn hints(
acc: &mut Vec<InlayHint>,
@@ -109,15 +107,11 @@ pub(super) fn hints(
return None;
}
- let linked_location = config
- .location_links
- .then(|| name_range.map(|range| FileRange { file_id, range }))
- .flatten();
+ let linked_location = name_range.map(|range| FileRange { file_id, range });
acc.push(InlayHint {
range: closing_token.text_range(),
- kind: InlayKind::ClosingBraceHint,
- label: InlayHintLabel { parts: vec![InlayHintLabelPart { text: label, linked_location }] },
- tooltip: None, // provided by label part location
+ kind: InlayKind::ClosingBrace,
+ label: InlayHintLabel::simple(label, None, linked_location),
});
None
diff --git a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/closure_ret.rs b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/closure_ret.rs
index d9929beaa..f03a18b8e 100644
--- a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/closure_ret.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/closure_ret.rs
@@ -4,7 +4,7 @@ use syntax::ast::{self, AstNode};
use crate::{
inlay_hints::closure_has_block_body, ClosureReturnTypeHints, InlayHint, InlayHintsConfig,
- InlayKind, InlayTooltip,
+ InlayKind,
};
use super::label_of_ty;
@@ -13,7 +13,7 @@ pub(super) fn hints(
acc: &mut Vec<InlayHint>,
famous_defs @ FamousDefs(sema, _): &FamousDefs<'_, '_>,
config: &InlayHintsConfig,
- file_id: FileId,
+ _file_id: FileId,
closure: ast::ClosureExpr,
) -> Option<()> {
if config.closure_return_type_hints == ClosureReturnTypeHints::Never {
@@ -41,9 +41,8 @@ pub(super) fn hints(
}
acc.push(InlayHint {
range: param_list.syntax().text_range(),
- kind: InlayKind::ClosureReturnTypeHint,
+ kind: InlayKind::ClosureReturnType,
label: label_of_ty(famous_defs, config, ty)?,
- tooltip: Some(InlayTooltip::HoverRanged(file_id, param_list.syntax().text_range())),
});
Some(())
}
diff --git a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/discriminant.rs b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/discriminant.rs
index f32c4bdf2..5dd51ad11 100644
--- a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/discriminant.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/discriminant.rs
@@ -4,27 +4,43 @@
//! Bar/* = 0*/,
//! }
//! ```
-use ide_db::{base_db::FileId, famous_defs::FamousDefs};
+use hir::Semantics;
+use ide_db::{base_db::FileId, famous_defs::FamousDefs, RootDatabase};
use syntax::ast::{self, AstNode, HasName};
-use crate::{DiscriminantHints, InlayHint, InlayHintsConfig, InlayKind, InlayTooltip};
+use crate::{
+ DiscriminantHints, InlayHint, InlayHintLabel, InlayHintsConfig, InlayKind, InlayTooltip,
+};
-pub(super) fn hints(
+pub(super) fn enum_hints(
acc: &mut Vec<InlayHint>,
FamousDefs(sema, _): &FamousDefs<'_, '_>,
config: &InlayHintsConfig,
_: FileId,
- variant: &ast::Variant,
+ enum_: ast::Enum,
) -> Option<()> {
- let field_list = match config.discriminant_hints {
- DiscriminantHints::Always => variant.field_list(),
- DiscriminantHints::Fieldless => match variant.field_list() {
- Some(_) => return None,
- None => None,
- },
- DiscriminantHints::Never => return None,
+ let enabled = match config.discriminant_hints {
+ DiscriminantHints::Always => true,
+ DiscriminantHints::Fieldless => {
+ !sema.to_def(&enum_)?.is_data_carrying(sema.db)
+ || enum_.variant_list()?.variants().any(|v| v.expr().is_some())
+ }
+ DiscriminantHints::Never => false,
};
+ if !enabled {
+ return None;
+ }
+ for variant in enum_.variant_list()?.variants() {
+ variant_hints(acc, sema, &variant);
+ }
+ None
+}
+fn variant_hints(
+ acc: &mut Vec<InlayHint>,
+ sema: &Semantics<'_, RootDatabase>,
+ variant: &ast::Variant,
+) -> Option<()> {
if variant.eq_token().is_some() {
return None;
}
@@ -37,19 +53,22 @@ pub(super) fn hints(
let d = v.eval(sema.db);
acc.push(InlayHint {
- range: match field_list {
+ range: match variant.field_list() {
Some(field_list) => name.syntax().text_range().cover(field_list.syntax().text_range()),
None => name.syntax().text_range(),
},
- kind: InlayKind::DiscriminantHint,
- label: match &d {
- Ok(v) => format!("{}", v).into(),
- Err(_) => "?".into(),
- },
- tooltip: Some(InlayTooltip::String(match &d {
- Ok(_) => "enum variant discriminant".into(),
- Err(e) => format!("{e:?}").into(),
- })),
+ kind: InlayKind::Discriminant,
+ label: InlayHintLabel::simple(
+ match &d {
+ Ok(v) => format!("{}", v),
+ Err(_) => "?".into(),
+ },
+ Some(InlayTooltip::String(match &d {
+ Ok(_) => "enum variant discriminant".into(),
+ Err(e) => format!("{e:?}").into(),
+ })),
+ None,
+ ),
});
Some(())
@@ -86,15 +105,30 @@ mod tests {
check_discriminants(
r#"
enum Enum {
- Variant,
- //^^^^^^^0
- Variant1,
- //^^^^^^^^1
- Variant2,
- //^^^^^^^^2
- Variant5 = 5,
- Variant6,
- //^^^^^^^^6
+ Variant,
+//^^^^^^^0
+ Variant1,
+//^^^^^^^^1
+ Variant2,
+//^^^^^^^^2
+ Variant5 = 5,
+ Variant6,
+//^^^^^^^^6
+}
+"#,
+ );
+ check_discriminants_fieldless(
+ r#"
+enum Enum {
+ Variant,
+//^^^^^^^0
+ Variant1,
+//^^^^^^^^1
+ Variant2,
+//^^^^^^^^2
+ Variant5 = 5,
+ Variant6,
+//^^^^^^^^6
}
"#,
);
@@ -128,8 +162,22 @@ enum Enum {
enum Enum {
Variant(),
Variant1,
+ Variant2 {},
+ Variant3,
+ Variant5,
+ Variant6,
+}
+"#,
+ );
+ check_discriminants_fieldless(
+ r#"
+enum Enum {
+ Variant(),
+ //^^^^^^^^^0
+ Variant1,
//^^^^^^^^1
Variant2 {},
+ //^^^^^^^^^^^2
Variant3,
//^^^^^^^^3
Variant5 = 5,
diff --git a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/fn_lifetime_fn.rs b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/fn_lifetime_fn.rs
index 2aa5e3dc7..b7182085b 100644
--- a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/fn_lifetime_fn.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/fn_lifetime_fn.rs
@@ -10,7 +10,7 @@ use syntax::{
SyntaxToken,
};
-use crate::{InlayHint, InlayHintsConfig, InlayKind, InlayTooltip, LifetimeElisionHints};
+use crate::{InlayHint, InlayHintsConfig, InlayKind, LifetimeElisionHints};
pub(super) fn hints(
acc: &mut Vec<InlayHint>,
@@ -23,9 +23,8 @@ pub(super) fn hints(
let mk_lt_hint = |t: SyntaxToken, label: String| InlayHint {
range: t.text_range(),
- kind: InlayKind::LifetimeHint,
+ kind: InlayKind::Lifetime,
label: label.into(),
- tooltip: Some(InlayTooltip::String("Elided lifetime".into())),
};
let param_list = func.param_list()?;
@@ -183,21 +182,19 @@ pub(super) fn hints(
let is_empty = gpl.generic_params().next().is_none();
acc.push(InlayHint {
range: angle_tok.text_range(),
- kind: InlayKind::LifetimeHint,
+ kind: InlayKind::Lifetime,
label: format!(
"{}{}",
allocated_lifetimes.iter().format(", "),
if is_empty { "" } else { ", " }
)
.into(),
- tooltip: Some(InlayTooltip::String("Elided lifetimes".into())),
});
}
(None, allocated_lifetimes) => acc.push(InlayHint {
range: func.name()?.syntax().text_range(),
- kind: InlayKind::GenericParamListHint,
+ kind: InlayKind::GenericParamList,
label: format!("<{}>", allocated_lifetimes.iter().format(", "),).into(),
- tooltip: Some(InlayTooltip::String("Elided lifetimes".into())),
}),
}
Some(())
diff --git a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/implicit_static.rs b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/implicit_static.rs
index 588a0e3b6..1122ee2e3 100644
--- a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/implicit_static.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/implicit_static.rs
@@ -8,7 +8,7 @@ use syntax::{
SyntaxKind,
};
-use crate::{InlayHint, InlayHintsConfig, InlayKind, InlayTooltip, LifetimeElisionHints};
+use crate::{InlayHint, InlayHintsConfig, InlayKind, LifetimeElisionHints};
pub(super) fn hints(
acc: &mut Vec<InlayHint>,
@@ -32,9 +32,8 @@ pub(super) fn hints(
let t = ty.amp_token()?;
acc.push(InlayHint {
range: t.text_range(),
- kind: InlayKind::LifetimeHint,
+ kind: InlayKind::Lifetime,
label: "'static".to_owned().into(),
- tooltip: Some(InlayTooltip::String("Elided static lifetime".into())),
});
}
}
diff --git a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/param_name.rs b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/param_name.rs
index ecee67632..9cdae6324 100644
--- a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/param_name.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/param_name.rs
@@ -10,7 +10,7 @@ use ide_db::{base_db::FileRange, RootDatabase};
use stdx::to_lower_snake_case;
use syntax::ast::{self, AstNode, HasArgList, HasName, UnaryOp};
-use crate::{InlayHint, InlayHintsConfig, InlayKind, InlayTooltip};
+use crate::{InlayHint, InlayHintLabel, InlayHintsConfig, InlayKind};
pub(super) fn hints(
acc: &mut Vec<InlayHint>,
@@ -43,21 +43,20 @@ pub(super) fn hints(
!should_hide_param_name_hint(sema, &callable, param_name, arg)
})
.map(|(param, param_name, _, FileRange { range, .. })| {
- let mut tooltip = None;
+ let mut linked_location = None;
if let Some(name) = param {
if let hir::CallableKind::Function(f) = callable.kind() {
// assert the file is cached so we can map out of macros
if let Some(_) = sema.source(f) {
- tooltip = sema.original_range_opt(name.syntax());
+ linked_location = sema.original_range_opt(name.syntax());
}
}
}
InlayHint {
range,
- kind: InlayKind::ParameterHint,
- label: param_name.into(),
- tooltip: tooltip.map(|it| InlayTooltip::HoverOffset(it.file_id, it.range.start())),
+ kind: InlayKind::Parameter,
+ label: InlayHintLabel::simple(param_name, None, linked_location),
}
});
diff --git a/src/tools/rust-analyzer/crates/ide/src/join_lines.rs b/src/tools/rust-analyzer/crates/ide/src/join_lines.rs
index edc48e84d..1cfde2362 100644
--- a/src/tools/rust-analyzer/crates/ide/src/join_lines.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/join_lines.rs
@@ -161,10 +161,8 @@ fn remove_newline(
}
}
- if config.join_assignments {
- if join_assignments(edit, &prev, &next).is_some() {
- return;
- }
+ if config.join_assignments && join_assignments(edit, &prev, &next).is_some() {
+ return;
}
if config.unwrap_trivial_blocks {
diff --git a/src/tools/rust-analyzer/crates/ide/src/lib.rs b/src/tools/rust-analyzer/crates/ide/src/lib.rs
index 239456cb2..f2b535bdc 100644
--- a/src/tools/rust-analyzer/crates/ide/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/lib.rs
@@ -82,7 +82,8 @@ pub use crate::{
hover::{HoverAction, HoverConfig, HoverDocFormat, HoverGotoTypeData, HoverResult},
inlay_hints::{
AdjustmentHints, AdjustmentHintsMode, ClosureReturnTypeHints, DiscriminantHints, InlayHint,
- InlayHintLabel, InlayHintsConfig, InlayKind, InlayTooltip, LifetimeElisionHints,
+ InlayHintLabel, InlayHintLabelPart, InlayHintsConfig, InlayKind, InlayTooltip,
+ LifetimeElisionHints,
},
join_lines::JoinLinesConfig,
markup::Markup,
@@ -114,7 +115,7 @@ pub use ide_db::{
SourceRoot, SourceRootId,
},
label::Label,
- line_index::{LineCol, LineColUtf16, LineIndex},
+ line_index::{LineCol, LineIndex},
search::{ReferenceCategory, SearchScope},
source_change::{FileSystemEdit, SourceChange},
symbol_index::Query,
@@ -236,7 +237,7 @@ impl Analysis {
Ok(Vec::new()),
false,
CrateOrigin::CratesIo { repo: None, name: None },
- None,
+ Err("Analysis::from_single_file has no target layout".into()),
);
change.change_file(file_id, Some(Arc::new(text)));
change.set_crate_graph(crate_graph);
diff --git a/src/tools/rust-analyzer/crates/ide/src/markdown_remove.rs b/src/tools/rust-analyzer/crates/ide/src/markdown_remove.rs
index 3ec5c629e..718868c87 100644
--- a/src/tools/rust-analyzer/crates/ide/src/markdown_remove.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/markdown_remove.rs
@@ -11,12 +11,146 @@ pub(crate) fn remove_markdown(markdown: &str) -> String {
for event in parser {
match event {
Event::Text(text) | Event::Code(text) => out.push_str(&text),
- Event::SoftBreak | Event::HardBreak | Event::Rule | Event::End(Tag::CodeBlock(_)) => {
- out.push('\n')
+ Event::SoftBreak => out.push(' '),
+ Event::HardBreak | Event::Rule | Event::End(Tag::CodeBlock(_)) => out.push('\n'),
+ Event::End(Tag::Paragraph) => {
+ out.push('\n');
+ out.push('\n');
}
- _ => {}
+ Event::Start(_)
+ | Event::End(_)
+ | Event::Html(_)
+ | Event::FootnoteReference(_)
+ | Event::TaskListMarker(_) => (),
}
}
+ if let Some(p) = out.rfind(|c| c != '\n') {
+ out.drain(p + 1..);
+ }
+
out
}
+
+#[cfg(test)]
+mod tests {
+ use expect_test::expect;
+
+ use super::*;
+
+ #[test]
+ fn smoke_test() {
+ let res = remove_markdown(
+ r##"
+A function or function pointer.
+
+Functions are the primary way code is executed within Rust. Function blocks, usually just
+called functions, can be defined in a variety of different places and be assigned many
+different attributes and modifiers.
+
+Standalone functions that just sit within a module not attached to anything else are common,
+but most functions will end up being inside [`impl`] blocks, either on another type itself, or
+as a trait impl for that type.
+
+```rust
+fn standalone_function() {
+ // code
+}
+
+pub fn public_thing(argument: bool) -> String {
+ // code
+ # "".to_string()
+}
+
+struct Thing {
+ foo: i32,
+}
+
+impl Thing {
+ pub fn new() -> Self {
+ Self {
+ foo: 42,
+ }
+ }
+}
+```
+
+In addition to presenting fixed types in the form of `fn name(arg: type, ..) -> return_type`,
+functions can also declare a list of type parameters along with trait bounds that they fall
+into.
+
+```rust
+fn generic_function<T: Clone>(x: T) -> (T, T, T) {
+ (x.clone(), x.clone(), x.clone())
+}
+
+fn generic_where<T>(x: T) -> T
+ where T: std::ops::Add<Output = T> + Copy
+{
+ x + x + x
+}
+```
+
+Declaring trait bounds in the angle brackets is functionally identical to using a `where`
+clause. It's up to the programmer to decide which works better in each situation, but `where`
+tends to be better when things get longer than one line.
+
+Along with being made public via `pub`, `fn` can also have an [`extern`] added for use in
+FFI.
+
+For more information on the various types of functions and how they're used, consult the [Rust
+book] or the [Reference].
+
+[`impl`]: keyword.impl.html
+[`extern`]: keyword.extern.html
+[Rust book]: ../book/ch03-03-how-functions-work.html
+[Reference]: ../reference/items/functions.html
+"##,
+ );
+ expect![[r#"
+ A function or function pointer.
+
+ Functions are the primary way code is executed within Rust. Function blocks, usually just called functions, can be defined in a variety of different places and be assigned many different attributes and modifiers.
+
+ Standalone functions that just sit within a module not attached to anything else are common, but most functions will end up being inside impl blocks, either on another type itself, or as a trait impl for that type.
+
+ fn standalone_function() {
+ // code
+ }
+
+ pub fn public_thing(argument: bool) -> String {
+ // code
+ # "".to_string()
+ }
+
+ struct Thing {
+ foo: i32,
+ }
+
+ impl Thing {
+ pub fn new() -> Self {
+ Self {
+ foo: 42,
+ }
+ }
+ }
+
+ In addition to presenting fixed types in the form of fn name(arg: type, ..) -> return_type, functions can also declare a list of type parameters along with trait bounds that they fall into.
+
+ fn generic_function<T: Clone>(x: T) -> (T, T, T) {
+ (x.clone(), x.clone(), x.clone())
+ }
+
+ fn generic_where<T>(x: T) -> T
+ where T: std::ops::Add<Output = T> + Copy
+ {
+ x + x + x
+ }
+
+ Declaring trait bounds in the angle brackets is functionally identical to using a where clause. It's up to the programmer to decide which works better in each situation, but where tends to be better when things get longer than one line.
+
+ Along with being made public via pub, fn can also have an extern added for use in FFI.
+
+ For more information on the various types of functions and how they're used, consult the Rust book or the Reference."#]].assert_eq(&res);
+ }
+}
diff --git a/src/tools/rust-analyzer/crates/ide/src/references.rs b/src/tools/rust-analyzer/crates/ide/src/references.rs
index 0f758cfa2..cabbc2872 100644
--- a/src/tools/rust-analyzer/crates/ide/src/references.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/references.rs
@@ -1636,4 +1636,399 @@ pub fn deri$0ve(_stream: TokenStream) -> TokenStream {}
"#]],
);
}
+
+ #[test]
+ fn assoc_items_trait_def() {
+ check(
+ r#"
+trait Trait {
+ const CONST$0: usize;
+}
+
+impl Trait for () {
+ const CONST: usize = 0;
+}
+
+impl Trait for ((),) {
+ const CONST: usize = 0;
+}
+
+fn f<T: Trait>() {
+ let _ = <()>::CONST;
+
+ let _ = T::CONST;
+}
+"#,
+ expect![[r#"
+ CONST Const FileId(0) 18..37 24..29
+
+ FileId(0) 71..76
+ FileId(0) 125..130
+ FileId(0) 183..188
+ FileId(0) 206..211
+ "#]],
+ );
+ check(
+ r#"
+trait Trait {
+ type TypeAlias$0;
+}
+
+impl Trait for () {
+ type TypeAlias = ();
+}
+
+impl Trait for ((),) {
+ type TypeAlias = ();
+}
+
+fn f<T: Trait>() {
+ let _: <() as Trait>::TypeAlias;
+
+ let _: T::TypeAlias;
+}
+"#,
+ expect![[r#"
+ TypeAlias TypeAlias FileId(0) 18..33 23..32
+
+ FileId(0) 66..75
+ FileId(0) 117..126
+ FileId(0) 181..190
+ FileId(0) 207..216
+ "#]],
+ );
+ check(
+ r#"
+trait Trait {
+ fn function$0() {}
+}
+
+impl Trait for () {
+ fn function() {}
+}
+
+impl Trait for ((),) {
+ fn function() {}
+}
+
+fn f<T: Trait>() {
+ let _ = <()>::function;
+
+ let _ = T::function;
+}
+"#,
+ expect![[r#"
+ function Function FileId(0) 18..34 21..29
+
+ FileId(0) 65..73
+ FileId(0) 112..120
+ FileId(0) 166..174
+ FileId(0) 192..200
+ "#]],
+ );
+ }
+
+ #[test]
+ fn assoc_items_trait_impl_def() {
+ check(
+ r#"
+trait Trait {
+ const CONST: usize;
+}
+
+impl Trait for () {
+ const CONST$0: usize = 0;
+}
+
+impl Trait for ((),) {
+ const CONST: usize = 0;
+}
+
+fn f<T: Trait>() {
+ let _ = <()>::CONST;
+
+ let _ = T::CONST;
+}
+"#,
+ expect![[r#"
+ CONST Const FileId(0) 65..88 71..76
+
+ FileId(0) 183..188
+ "#]],
+ );
+ check(
+ r#"
+trait Trait {
+ type TypeAlias;
+}
+
+impl Trait for () {
+ type TypeAlias$0 = ();
+}
+
+impl Trait for ((),) {
+ type TypeAlias = ();
+}
+
+fn f<T: Trait>() {
+ let _: <() as Trait>::TypeAlias;
+
+ let _: T::TypeAlias;
+}
+"#,
+ expect![[r#"
+ TypeAlias TypeAlias FileId(0) 61..81 66..75
+
+ FileId(0) 23..32
+ FileId(0) 117..126
+ FileId(0) 181..190
+ FileId(0) 207..216
+ "#]],
+ );
+ check(
+ r#"
+trait Trait {
+ fn function() {}
+}
+
+impl Trait for () {
+ fn function$0() {}
+}
+
+impl Trait for ((),) {
+ fn function() {}
+}
+
+fn f<T: Trait>() {
+ let _ = <()>::function;
+
+ let _ = T::function;
+}
+"#,
+ expect![[r#"
+ function Function FileId(0) 62..78 65..73
+
+ FileId(0) 166..174
+ "#]],
+ );
+ }
+
+ #[test]
+ fn assoc_items_ref() {
+ check(
+ r#"
+trait Trait {
+ const CONST: usize;
+}
+
+impl Trait for () {
+ const CONST: usize = 0;
+}
+
+impl Trait for ((),) {
+ const CONST: usize = 0;
+}
+
+fn f<T: Trait>() {
+ let _ = <()>::CONST$0;
+
+ let _ = T::CONST;
+}
+"#,
+ expect![[r#"
+ CONST Const FileId(0) 65..88 71..76
+
+ FileId(0) 183..188
+ "#]],
+ );
+ check(
+ r#"
+trait Trait {
+ type TypeAlias;
+}
+
+impl Trait for () {
+ type TypeAlias = ();
+}
+
+impl Trait for ((),) {
+ type TypeAlias = ();
+}
+
+fn f<T: Trait>() {
+ let _: <() as Trait>::TypeAlias$0;
+
+ let _: T::TypeAlias;
+}
+"#,
+ expect![[r#"
+ TypeAlias TypeAlias FileId(0) 18..33 23..32
+
+ FileId(0) 66..75
+ FileId(0) 117..126
+ FileId(0) 181..190
+ FileId(0) 207..216
+ "#]],
+ );
+ check(
+ r#"
+trait Trait {
+ fn function() {}
+}
+
+impl Trait for () {
+ fn function() {}
+}
+
+impl Trait for ((),) {
+ fn function() {}
+}
+
+fn f<T: Trait>() {
+ let _ = <()>::function$0;
+
+ let _ = T::function;
+}
+"#,
+ expect![[r#"
+ function Function FileId(0) 62..78 65..73
+
+ FileId(0) 166..174
+ "#]],
+ );
+ }
+
+ #[test]
+ fn name_clashes() {
+ check(
+ r#"
+trait Foo {
+ fn method$0(&self) -> u8;
+}
+
+struct Bar {
+ method: u8,
+}
+
+impl Foo for Bar {
+ fn method(&self) -> u8 {
+ self.method
+ }
+}
+fn method() {}
+"#,
+ expect![[r#"
+ method Function FileId(0) 16..39 19..25
+
+ FileId(0) 101..107
+ "#]],
+ );
+ check(
+ r#"
+trait Foo {
+ fn method(&self) -> u8;
+}
+
+struct Bar {
+ method$0: u8,
+}
+
+impl Foo for Bar {
+ fn method(&self) -> u8 {
+ self.method
+ }
+}
+fn method() {}
+"#,
+ expect![[r#"
+ method Field FileId(0) 60..70 60..66
+
+ FileId(0) 136..142 Read
+ "#]],
+ );
+ check(
+ r#"
+trait Foo {
+ fn method(&self) -> u8;
+}
+
+struct Bar {
+ method: u8,
+}
+
+impl Foo for Bar {
+ fn method$0(&self) -> u8 {
+ self.method
+ }
+}
+fn method() {}
+"#,
+ expect![[r#"
+ method Function FileId(0) 98..148 101..107
+
+ (no references)
+ "#]],
+ );
+ check(
+ r#"
+trait Foo {
+ fn method(&self) -> u8;
+}
+
+struct Bar {
+ method: u8,
+}
+
+impl Foo for Bar {
+ fn method(&self) -> u8 {
+ self.method$0
+ }
+}
+fn method() {}
+"#,
+ expect![[r#"
+ method Field FileId(0) 60..70 60..66
+
+ FileId(0) 136..142 Read
+ "#]],
+ );
+ check(
+ r#"
+trait Foo {
+ fn method(&self) -> u8;
+}
+
+struct Bar {
+ method: u8,
+}
+
+impl Foo for Bar {
+ fn method(&self) -> u8 {
+ self.method
+ }
+}
+fn method$0() {}
+"#,
+ expect![[r#"
+ method Function FileId(0) 151..165 154..160
+
+ (no references)
+ "#]],
+ );
+ }
+
+ #[test]
+ fn raw_identifier() {
+ check(
+ r#"
+fn r#fn$0() {}
+fn main() { r#fn(); }
+"#,
+ expect![[r#"
+ r#fn Function FileId(0) 0..12 3..7
+
+ FileId(0) 25..29
+ "#]],
+ );
+ }
}
diff --git a/src/tools/rust-analyzer/crates/ide/src/rename.rs b/src/tools/rust-analyzer/crates/ide/src/rename.rs
index 15bdf14fb..c0237e1ed 100644
--- a/src/tools/rust-analyzer/crates/ide/src/rename.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/rename.rs
@@ -13,7 +13,7 @@ use ide_db::{
};
use itertools::Itertools;
use stdx::{always, never};
-use syntax::{ast, AstNode, SyntaxNode};
+use syntax::{ast, utils::is_raw_identifier, AstNode, SmolStr, SyntaxNode, TextRange, TextSize};
use text_edit::TextEdit;
@@ -48,7 +48,13 @@ pub(crate) fn prepare_rename(
frange.range.contains_inclusive(position.offset)
&& frange.file_id == position.file_id
);
- Ok(frange.range)
+
+ Ok(match name_like {
+ ast::NameLike::Lifetime(_) => {
+ TextRange::new(frange.range.start() + TextSize::from(1), frange.range.end())
+ }
+ _ => frange.range,
+ })
})
.reduce(|acc, cur| match (acc, cur) {
// ensure all ranges are the same
@@ -116,7 +122,11 @@ pub(crate) fn will_rename_file(
let sema = Semantics::new(db);
let module = sema.to_module_def(file_id)?;
let def = Definition::Module(module);
- let mut change = def.rename(&sema, new_name_stem).ok()?;
+ let mut change = if is_raw_identifier(new_name_stem) {
+ def.rename(&sema, &SmolStr::from_iter(["r#", new_name_stem])).ok()?
+ } else {
+ def.rename(&sema, new_name_stem).ok()?
+ };
change.file_system_edits.clear();
Some(change)
}
@@ -407,7 +417,7 @@ mod tests {
#[test]
fn test_prepare_rename_namelikes() {
check_prepare(r"fn name$0<'lifetime>() {}", expect![[r#"3..7: name"#]]);
- check_prepare(r"fn name<'lifetime$0>() {}", expect![[r#"8..17: 'lifetime"#]]);
+ check_prepare(r"fn name<'lifetime$0>() {}", expect![[r#"9..17: lifetime"#]]);
check_prepare(r"fn name<'lifetime>() { name$0(); }", expect![[r#"23..27: name"#]]);
}
@@ -521,15 +531,19 @@ impl Foo {
#[test]
fn test_rename_to_invalid_identifier_lifetime2() {
- cov_mark::check!(rename_not_a_lifetime_ident_ref);
check(
- "foo",
+ "_",
r#"fn main<'a>(_: &'a$0 ()) {}"#,
- "error: Invalid name `foo`: not a lifetime identifier",
+ r#"error: Invalid name `_`: not a lifetime identifier"#,
);
}
#[test]
+ fn test_rename_accepts_lifetime_without_apostrophe() {
+ check("foo", r#"fn main<'a>(_: &'a$0 ()) {}"#, r#"fn main<'foo>(_: &'foo ()) {}"#);
+ }
+
+ #[test]
fn test_rename_to_underscore_invalid() {
cov_mark::check!(rename_underscore_multiple);
check(
@@ -549,6 +563,15 @@ impl Foo {
}
#[test]
+ fn test_rename_mod_invalid_raw_ident() {
+ check(
+ "r#self",
+ r#"mod foo$0 {}"#,
+ "error: Invalid name: `self` cannot be a raw identifier",
+ );
+ }
+
+ #[test]
fn test_rename_for_local() {
check(
"k",
@@ -1277,6 +1300,146 @@ mod bar$0;
}
#[test]
+ fn test_rename_mod_to_raw_ident() {
+ check_expect(
+ "r#fn",
+ r#"
+//- /lib.rs
+mod foo$0;
+
+fn main() { foo::bar::baz(); }
+
+//- /foo.rs
+pub mod bar;
+
+//- /foo/bar.rs
+pub fn baz() {}
+"#,
+ expect![[r#"
+ SourceChange {
+ source_file_edits: {
+ FileId(
+ 0,
+ ): TextEdit {
+ indels: [
+ Indel {
+ insert: "r#fn",
+ delete: 4..7,
+ },
+ Indel {
+ insert: "r#fn",
+ delete: 22..25,
+ },
+ ],
+ },
+ },
+ file_system_edits: [
+ MoveFile {
+ src: FileId(
+ 1,
+ ),
+ dst: AnchoredPathBuf {
+ anchor: FileId(
+ 1,
+ ),
+ path: "fn.rs",
+ },
+ },
+ MoveDir {
+ src: AnchoredPathBuf {
+ anchor: FileId(
+ 1,
+ ),
+ path: "foo",
+ },
+ src_id: FileId(
+ 1,
+ ),
+ dst: AnchoredPathBuf {
+ anchor: FileId(
+ 1,
+ ),
+ path: "fn",
+ },
+ },
+ ],
+ is_snippet: false,
+ }
+ "#]],
+ );
+ }
+
+ #[test]
+ fn test_rename_mod_from_raw_ident() {
+ check_expect(
+ "foo",
+ r#"
+//- /lib.rs
+mod r#fn$0;
+
+fn main() { r#fn::bar::baz(); }
+
+//- /fn.rs
+pub mod bar;
+
+//- /fn/bar.rs
+pub fn baz() {}
+"#,
+ expect![[r#"
+ SourceChange {
+ source_file_edits: {
+ FileId(
+ 0,
+ ): TextEdit {
+ indels: [
+ Indel {
+ insert: "foo",
+ delete: 4..8,
+ },
+ Indel {
+ insert: "foo",
+ delete: 23..27,
+ },
+ ],
+ },
+ },
+ file_system_edits: [
+ MoveFile {
+ src: FileId(
+ 1,
+ ),
+ dst: AnchoredPathBuf {
+ anchor: FileId(
+ 1,
+ ),
+ path: "foo.rs",
+ },
+ },
+ MoveDir {
+ src: AnchoredPathBuf {
+ anchor: FileId(
+ 1,
+ ),
+ path: "fn",
+ },
+ src_id: FileId(
+ 1,
+ ),
+ dst: AnchoredPathBuf {
+ anchor: FileId(
+ 1,
+ ),
+ path: "foo",
+ },
+ },
+ ],
+ is_snippet: false,
+ }
+ "#]],
+ );
+ }
+
+ #[test]
fn test_enum_variant_from_module_1() {
cov_mark::check!(rename_non_local);
check(
@@ -1832,6 +1995,31 @@ fn foo<'a>() -> &'a () {
}
#[test]
+ fn test_rename_label_new_name_without_apostrophe() {
+ check(
+ "foo",
+ r#"
+fn main() {
+ 'outer$0: loop {
+ 'inner: loop {
+ break 'outer;
+ }
+ }
+}
+ "#,
+ r#"
+fn main() {
+ 'foo: loop {
+ 'inner: loop {
+ break 'foo;
+ }
+ }
+}
+ "#,
+ );
+ }
+
+ #[test]
fn test_self_to_self() {
cov_mark::check!(rename_self_to_self);
check(
diff --git a/src/tools/rust-analyzer/crates/ide/src/shuffle_crate_graph.rs b/src/tools/rust-analyzer/crates/ide/src/shuffle_crate_graph.rs
index ae539a5d3..e606072a8 100644
--- a/src/tools/rust-analyzer/crates/ide/src/shuffle_crate_graph.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/shuffle_crate_graph.rs
@@ -18,7 +18,9 @@ pub(crate) fn shuffle_crate_graph(db: &mut RootDatabase) {
let crate_graph = db.crate_graph();
let mut shuffled_ids = crate_graph.iter().collect::<Vec<_>>();
- shuffle(&mut shuffled_ids);
+
+ let mut rng = oorandom::Rand32::new(stdx::rand::seed());
+ stdx::rand::shuffle(&mut shuffled_ids, |i| rng.rand_range(0..i as u32) as usize);
let mut new_graph = CrateGraph::default();
@@ -52,21 +54,3 @@ pub(crate) fn shuffle_crate_graph(db: &mut RootDatabase) {
db.set_crate_graph_with_durability(Arc::new(new_graph), Durability::HIGH);
}
-
-fn shuffle<T>(slice: &mut [T]) {
- let mut rng = oorandom::Rand32::new(seed());
-
- let mut remaining = slice.len() - 1;
- while remaining > 0 {
- let index = rng.rand_range(0..remaining as u32);
- slice.swap(remaining, index as usize);
- remaining -= 1;
- }
-}
-
-fn seed() -> u64 {
- use std::collections::hash_map::RandomState;
- use std::hash::{BuildHasher, Hasher};
-
- RandomState::new().build_hasher().finish()
-}
diff --git a/src/tools/rust-analyzer/crates/ide/src/signature_help.rs b/src/tools/rust-analyzer/crates/ide/src/signature_help.rs
index f807ba30f..f70ca55a5 100644
--- a/src/tools/rust-analyzer/crates/ide/src/signature_help.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/signature_help.rs
@@ -4,8 +4,14 @@
use std::collections::BTreeSet;
use either::Either;
-use hir::{AssocItem, GenericParam, HasAttrs, HirDisplay, Semantics, Trait};
-use ide_db::{active_parameter::callable_for_node, base_db::FilePosition};
+use hir::{
+ AssocItem, GenericParam, HasAttrs, HirDisplay, ModuleDef, PathResolution, Semantics, Trait,
+};
+use ide_db::{
+ active_parameter::{callable_for_node, generic_def_for_node},
+ base_db::FilePosition,
+ FxIndexMap,
+};
use stdx::format_to;
use syntax::{
algo,
@@ -37,14 +43,18 @@ impl SignatureHelp {
}
fn push_call_param(&mut self, param: &str) {
- self.push_param('(', param);
+ self.push_param("(", param);
}
fn push_generic_param(&mut self, param: &str) {
- self.push_param('<', param);
+ self.push_param("<", param);
}
- fn push_param(&mut self, opening_delim: char, param: &str) {
+ fn push_record_field(&mut self, param: &str) {
+ self.push_param("{ ", param);
+ }
+
+ fn push_param(&mut self, opening_delim: &str, param: &str) {
if !self.signature.ends_with(opening_delim) {
self.signature.push_str(", ");
}
@@ -85,6 +95,13 @@ pub(crate) fn signature_help(db: &RootDatabase, position: FilePosition) -> Optio
}
return signature_help_for_generics(&sema, garg_list, token);
},
+ ast::RecordExpr(record) => {
+ let cursor_outside = record.record_expr_field_list().and_then(|list| list.r_curly_token()).as_ref() == Some(&token);
+ if cursor_outside {
+ continue;
+ }
+ return signature_help_for_record_lit(&sema, record, token);
+ },
_ => (),
}
}
@@ -92,8 +109,10 @@ pub(crate) fn signature_help(db: &RootDatabase, position: FilePosition) -> Optio
// Stop at multi-line expressions, since the signature of the outer call is not very
// helpful inside them.
if let Some(expr) = ast::Expr::cast(node.clone()) {
- if expr.syntax().text().contains_char('\n') {
- return None;
+ if !matches!(expr, ast::Expr::RecordExpr(..))
+ && expr.syntax().text().contains_char('\n')
+ {
+ break;
}
}
}
@@ -107,18 +126,16 @@ fn signature_help_for_call(
token: SyntaxToken,
) -> Option<SignatureHelp> {
// Find the calling expression and its NameRef
- let mut node = arg_list.syntax().parent()?;
+ let mut nodes = arg_list.syntax().ancestors().skip(1);
let calling_node = loop {
- if let Some(callable) = ast::CallableExpr::cast(node.clone()) {
- if callable
+ if let Some(callable) = ast::CallableExpr::cast(nodes.next()?) {
+ let inside_callable = callable
.arg_list()
- .map_or(false, |it| it.syntax().text_range().contains(token.text_range().start()))
- {
+ .map_or(false, |it| it.syntax().text_range().contains(token.text_range().start()));
+ if inside_callable {
break callable;
}
}
-
- node = node.parent()?;
};
let (callable, active_parameter) = callable_for_node(sema, &calling_node, &token)?;
@@ -201,59 +218,11 @@ fn signature_help_for_call(
fn signature_help_for_generics(
sema: &Semantics<'_, RootDatabase>,
- garg_list: ast::GenericArgList,
+ arg_list: ast::GenericArgList,
token: SyntaxToken,
) -> Option<SignatureHelp> {
- let arg_list = garg_list
- .syntax()
- .ancestors()
- .filter_map(ast::GenericArgList::cast)
- .find(|list| list.syntax().text_range().contains(token.text_range().start()))?;
-
- let mut active_parameter = arg_list
- .generic_args()
- .take_while(|arg| arg.syntax().text_range().end() <= token.text_range().start())
- .count();
-
- let first_arg_is_non_lifetime = arg_list
- .generic_args()
- .next()
- .map_or(false, |arg| !matches!(arg, ast::GenericArg::LifetimeArg(_)));
-
- let mut generics_def = if let Some(path) =
- arg_list.syntax().ancestors().find_map(ast::Path::cast)
- {
- let res = sema.resolve_path(&path)?;
- let generic_def: hir::GenericDef = match res {
- hir::PathResolution::Def(hir::ModuleDef::Adt(it)) => it.into(),
- hir::PathResolution::Def(hir::ModuleDef::Function(it)) => it.into(),
- hir::PathResolution::Def(hir::ModuleDef::Trait(it)) => it.into(),
- hir::PathResolution::Def(hir::ModuleDef::TypeAlias(it)) => it.into(),
- hir::PathResolution::Def(hir::ModuleDef::Variant(it)) => it.into(),
- hir::PathResolution::Def(hir::ModuleDef::BuiltinType(_))
- | hir::PathResolution::Def(hir::ModuleDef::Const(_))
- | hir::PathResolution::Def(hir::ModuleDef::Macro(_))
- | hir::PathResolution::Def(hir::ModuleDef::Module(_))
- | hir::PathResolution::Def(hir::ModuleDef::Static(_)) => return None,
- hir::PathResolution::BuiltinAttr(_)
- | hir::PathResolution::ToolModule(_)
- | hir::PathResolution::Local(_)
- | hir::PathResolution::TypeParam(_)
- | hir::PathResolution::ConstParam(_)
- | hir::PathResolution::SelfType(_)
- | hir::PathResolution::DeriveHelper(_) => return None,
- };
-
- generic_def
- } else if let Some(method_call) = arg_list.syntax().parent().and_then(ast::MethodCallExpr::cast)
- {
- // recv.method::<$0>()
- let method = sema.resolve_method_call(&method_call)?;
- method.into()
- } else {
- return None;
- };
-
+ let (mut generics_def, mut active_parameter, first_arg_is_non_lifetime) =
+ generic_def_for_node(sema, &arg_list, &token)?;
let mut res = SignatureHelp {
doc: None,
signature: String::new(),
@@ -292,9 +261,9 @@ fn signature_help_for_generics(
// eg. `None::<u8>`
// We'll use the signature of the enum, but include the docs of the variant.
res.doc = it.docs(db).map(|it| it.into());
- let it = it.parent_enum(db);
- format_to!(res.signature, "enum {}", it.name(db));
- generics_def = it.into();
+ let enum_ = it.parent_enum(db);
+ format_to!(res.signature, "enum {}", enum_.name(db));
+ generics_def = enum_.into();
}
// These don't have generic args that can be specified
hir::GenericDef::Impl(_) | hir::GenericDef::Const(_) => return None,
@@ -368,6 +337,83 @@ fn add_assoc_type_bindings(
}
}
+fn signature_help_for_record_lit(
+ sema: &Semantics<'_, RootDatabase>,
+ record: ast::RecordExpr,
+ token: SyntaxToken,
+) -> Option<SignatureHelp> {
+ let active_parameter = record
+ .record_expr_field_list()?
+ .syntax()
+ .children_with_tokens()
+ .filter_map(syntax::NodeOrToken::into_token)
+ .filter(|t| t.kind() == syntax::T![,])
+ .take_while(|t| t.text_range().start() <= token.text_range().start())
+ .count();
+
+ let mut res = SignatureHelp {
+ doc: None,
+ signature: String::new(),
+ parameters: vec![],
+ active_parameter: Some(active_parameter),
+ };
+
+ let fields;
+
+ let db = sema.db;
+ let path_res = sema.resolve_path(&record.path()?)?;
+ if let PathResolution::Def(ModuleDef::Variant(variant)) = path_res {
+ fields = variant.fields(db);
+ let en = variant.parent_enum(db);
+
+ res.doc = en.docs(db).map(|it| it.into());
+ format_to!(res.signature, "enum {}::{} {{ ", en.name(db), variant.name(db));
+ } else {
+ let adt = match path_res {
+ PathResolution::SelfType(imp) => imp.self_ty(db).as_adt()?,
+ PathResolution::Def(ModuleDef::Adt(adt)) => adt,
+ _ => return None,
+ };
+
+ match adt {
+ hir::Adt::Struct(it) => {
+ fields = it.fields(db);
+ res.doc = it.docs(db).map(|it| it.into());
+ format_to!(res.signature, "struct {} {{ ", it.name(db));
+ }
+ hir::Adt::Union(it) => {
+ fields = it.fields(db);
+ res.doc = it.docs(db).map(|it| it.into());
+ format_to!(res.signature, "union {} {{ ", it.name(db));
+ }
+ _ => return None,
+ }
+ }
+
+ let mut fields =
+ fields.into_iter().map(|field| (field.name(db), Some(field))).collect::<FxIndexMap<_, _>>();
+ let mut buf = String::new();
+ for field in record.record_expr_field_list()?.fields() {
+ let Some((field, _, ty)) = sema.resolve_record_field(&field) else { continue };
+ let name = field.name(db);
+ format_to!(buf, "{name}: {}", ty.display_truncated(db, Some(20)));
+ res.push_record_field(&buf);
+ buf.clear();
+
+ if let Some(field) = fields.get_mut(&name) {
+ *field = None;
+ }
+ }
+ for (name, field) in fields {
+ let Some(field) = field else { continue };
+ format_to!(buf, "{name}: {}", field.ty(db).display_truncated(db, Some(20)));
+ res.push_record_field(&buf);
+ buf.clear();
+ }
+ res.signature.push_str(" }");
+ Some(res)
+}
+
#[cfg(test)]
mod tests {
use std::iter;
@@ -1405,4 +1451,121 @@ fn take<C, Error>(
"#]],
);
}
+
+ #[test]
+ fn record_literal() {
+ check(
+ r#"
+struct Strukt<T, U = ()> {
+ t: T,
+ u: U,
+ unit: (),
+}
+fn f() {
+ Strukt {
+ u: 0,
+ $0
+ }
+}
+"#,
+ expect![[r#"
+ struct Strukt { u: i32, t: T, unit: () }
+ ------ ^^^^ --------
+ "#]],
+ );
+ }
+
+ #[test]
+ fn record_literal_nonexistent_field() {
+ check(
+ r#"
+struct Strukt {
+ a: u8,
+}
+fn f() {
+ Strukt {
+ b: 8,
+ $0
+ }
+}
+"#,
+ expect![[r#"
+ struct Strukt { a: u8 }
+ -----
+ "#]],
+ );
+ }
+
+ #[test]
+ fn tuple_variant_record_literal() {
+ check(
+ r#"
+enum Opt {
+ Some(u8),
+}
+fn f() {
+ Opt::Some {$0}
+}
+"#,
+ expect![[r#"
+ enum Opt::Some { 0: u8 }
+ ^^^^^
+ "#]],
+ );
+ check(
+ r#"
+enum Opt {
+ Some(u8),
+}
+fn f() {
+ Opt::Some {0:0,$0}
+}
+"#,
+ expect![[r#"
+ enum Opt::Some { 0: u8 }
+ -----
+ "#]],
+ );
+ }
+
+ #[test]
+ fn record_literal_self() {
+ check(
+ r#"
+struct S { t: u8 }
+impl S {
+ fn new() -> Self {
+ Self { $0 }
+ }
+}
+ "#,
+ expect![[r#"
+ struct S { t: u8 }
+ ^^^^^
+ "#]],
+ );
+ }
+
+ #[test]
+ fn test_enum_in_nested_method_in_lambda() {
+ check(
+ r#"
+enum A {
+ A,
+ B
+}
+
+fn bar(_: A) { }
+
+fn main() {
+ let foo = Foo;
+ std::thread::spawn(move || { bar(A:$0) } );
+}
+"#,
+ expect![[r#"
+ fn bar(_: A)
+ ^^^^
+ "#]],
+ );
+ }
}
diff --git a/src/tools/rust-analyzer/crates/ide/src/static_index.rs b/src/tools/rust-analyzer/crates/ide/src/static_index.rs
index a6b30ba13..3f7f6885f 100644
--- a/src/tools/rust-analyzer/crates/ide/src/static_index.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/static_index.rs
@@ -16,8 +16,7 @@ use crate::{
inlay_hints::AdjustmentHintsMode,
moniker::{def_to_moniker, MonikerResult},
parent_module::crates_for,
- Analysis, Fold, HoverConfig, HoverDocFormat, HoverResult, InlayHint, InlayHintsConfig,
- TryToNav,
+ Analysis, Fold, HoverConfig, HoverResult, InlayHint, InlayHintsConfig, TryToNav,
};
/// A static representation of fully analyzed source code.
@@ -107,7 +106,6 @@ impl StaticIndex<'_> {
.analysis
.inlay_hints(
&InlayHintsConfig {
- location_links: true,
render_colons: true,
discriminant_hints: crate::DiscriminantHints::Fieldless,
type_hints: true,
@@ -138,8 +136,9 @@ impl StaticIndex<'_> {
});
let hover_config = HoverConfig {
links_in_hover: true,
- documentation: Some(HoverDocFormat::Markdown),
+ documentation: true,
keywords: true,
+ format: crate::HoverDocFormat::Markdown,
};
let tokens = tokens.filter(|token| {
matches!(
diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting.rs b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting.rs
index 50371d620..454a250f3 100644
--- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting.rs
@@ -413,11 +413,10 @@ fn traverse(
let string = ast::String::cast(token);
let string_to_highlight = ast::String::cast(descended_token.clone());
if let Some((string, expanded_string)) = string.zip(string_to_highlight) {
- if string.is_raw() {
- if inject::ra_fixture(hl, sema, config, &string, &expanded_string).is_some()
- {
- continue;
- }
+ if string.is_raw()
+ && inject::ra_fixture(hl, sema, config, &string, &expanded_string).is_some()
+ {
+ continue;
}
highlight_format_string(hl, &string, &expanded_string, range);
highlight_escape_string(hl, &string, range.start());
diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/tests.rs b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/tests.rs
index 2f870d769..fc9b5d3ba 100644
--- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/tests.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/tests.rs
@@ -1126,5 +1126,5 @@ fn benchmark_syntax_highlighting_parser() {
.filter(|it| it.highlight.tag == HlTag::Symbol(SymbolKind::Function))
.count()
};
- assert_eq!(hash, 1609);
+ assert_eq!(hash, 1608);
}
diff --git a/src/tools/rust-analyzer/crates/ide/src/typing.rs b/src/tools/rust-analyzer/crates/ide/src/typing.rs
index eba5a4856..c7e403f6b 100644
--- a/src/tools/rust-analyzer/crates/ide/src/typing.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/typing.rs
@@ -205,10 +205,8 @@ fn on_eq_typed(file: &SourceFile, offset: TextSize) -> Option<TextEdit> {
if expr_stmt.semicolon_token().is_some() {
return None;
}
- } else {
- if !ast::StmtList::can_cast(binop.syntax().parent()?.kind()) {
- return None;
- }
+ } else if !ast::StmtList::can_cast(binop.syntax().parent()?.kind()) {
+ return None;
}
let expr = binop.rhs()?;
@@ -255,6 +253,10 @@ fn on_eq_typed(file: &SourceFile, offset: TextSize) -> Option<TextEdit> {
if file.syntax().text().slice(offset..expr_range.start()).contains_char('\n') {
return None;
}
+ // Good indicator that we will insert into a bad spot, so bail out.
+ if expr.syntax().descendants().any(|it| it.kind() == SyntaxKind::ERROR) {
+ return None;
+ }
let offset = let_stmt.syntax().text_range().end();
Some(TextEdit::insert(offset, ";".to_string()))
}
@@ -409,15 +411,14 @@ mod tests {
#[test]
fn test_semi_after_let() {
- // do_check(r"
- // fn foo() {
- // let foo =$0
- // }
- // ", r"
- // fn foo() {
- // let foo =;
- // }
- // ");
+ type_char_noop(
+ '=',
+ r"
+fn foo() {
+ let foo =$0
+}
+",
+ );
type_char(
'=',
r#"
@@ -431,17 +432,25 @@ fn foo() {
}
"#,
);
- // do_check(r"
- // fn foo() {
- // let foo =$0
- // let bar = 1;
- // }
- // ", r"
- // fn foo() {
- // let foo =;
- // let bar = 1;
- // }
- // ");
+ type_char_noop(
+ '=',
+ r#"
+fn foo() {
+ let difference $0(counts: &HashMap<(char, char), u64>, last: char) -> u64 {
+ // ...
+ }
+}
+"#,
+ );
+ type_char_noop(
+ '=',
+ r"
+fn foo() {
+ let foo =$0
+ let bar = 1;
+}
+",
+ );
}
#[test]
diff --git a/src/tools/rust-analyzer/crates/intern/Cargo.toml b/src/tools/rust-analyzer/crates/intern/Cargo.toml
new file mode 100644
index 000000000..c73c368a1
--- /dev/null
+++ b/src/tools/rust-analyzer/crates/intern/Cargo.toml
@@ -0,0 +1,20 @@
+[package]
+name = "intern"
+version = "0.0.0"
+description = "TBD"
+
+authors.workspace = true
+edition.workspace = true
+license.workspace = true
+rust-version.workspace = true
+
+[lib]
+doctest = false
+
+
+[dependencies]
+# We need to freeze the version of the crate, as the raw-api feature is considered unstable
+dashmap = { version = "=5.4.0", features = ["raw-api"] }
+hashbrown = { version = "0.12.1", default-features = false }
+once_cell = "1.17.0"
+rustc-hash = "1.1.0"
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/intern.rs b/src/tools/rust-analyzer/crates/intern/src/lib.rs
index f08521a34..fb2903696 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/intern.rs
+++ b/src/tools/rust-analyzer/crates/intern/src/lib.rs
@@ -14,8 +14,6 @@ use hashbrown::HashMap;
use once_cell::sync::OnceCell;
use rustc_hash::FxHasher;
-use crate::generics::GenericParams;
-
type InternMap<T> = DashMap<Arc<T>, (), BuildHasherDefault<FxHasher>>;
type Guard<T> = dashmap::RwLockWriteGuard<
'static,
@@ -204,9 +202,9 @@ pub trait Internable: Hash + Eq + 'static {
#[doc(hidden)]
macro_rules! _impl_internable {
( $($t:path),+ $(,)? ) => { $(
- impl Internable for $t {
- fn storage() -> &'static InternStorage<Self> {
- static STORAGE: InternStorage<$t> = InternStorage::new();
+ impl $crate::Internable for $t {
+ fn storage() -> &'static $crate::InternStorage<Self> {
+ static STORAGE: $crate::InternStorage<$t> = $crate::InternStorage::new();
&STORAGE
}
}
@@ -215,13 +213,4 @@ macro_rules! _impl_internable {
pub use crate::_impl_internable as impl_internable;
-impl_internable!(
- crate::type_ref::TypeRef,
- crate::type_ref::TraitRef,
- crate::type_ref::TypeBound,
- crate::path::ModPath,
- crate::path::GenericArgs,
- crate::attr::AttrInput,
- GenericParams,
- str,
-);
+impl_internable!(str,);
diff --git a/src/tools/rust-analyzer/crates/limit/Cargo.toml b/src/tools/rust-analyzer/crates/limit/Cargo.toml
index 3536f73da..c08886909 100644
--- a/src/tools/rust-analyzer/crates/limit/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/limit/Cargo.toml
@@ -2,9 +2,11 @@
name = "limit"
version = "0.0.0"
description = "TBD"
-license = "MIT OR Apache-2.0"
-edition = "2021"
-rust-version = "1.65"
+
+authors.workspace = true
+edition.workspace = true
+license.workspace = true
+rust-version.workspace = true
[features]
tracking = []
diff --git a/src/tools/rust-analyzer/crates/mbe/Cargo.toml b/src/tools/rust-analyzer/crates/mbe/Cargo.toml
index bce2fc9a7..82105522e 100644
--- a/src/tools/rust-analyzer/crates/mbe/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/mbe/Cargo.toml
@@ -2,9 +2,11 @@
name = "mbe"
version = "0.0.0"
description = "TBD"
-license = "MIT OR Apache-2.0"
-edition = "2021"
-rust-version = "1.65"
+
+authors.workspace = true
+edition.workspace = true
+license.workspace = true
+rust-version.workspace = true
[lib]
doctest = false
@@ -12,13 +14,14 @@ doctest = false
[dependencies]
cov-mark = "2.0.0-pre.1"
rustc-hash = "1.1.0"
-smallvec = "1.10.0"
+smallvec.workspace = true
tracing = "0.1.35"
-syntax = { path = "../syntax", version = "0.0.0" }
-parser = { path = "../parser", version = "0.0.0" }
-tt = { path = "../tt", version = "0.0.0" }
-stdx = { path = "../stdx", version = "0.0.0" }
+# local deps
+syntax.workspace = true
+parser.workspace = true
+tt.workspace = true
+stdx.workspace = true
[dev-dependencies]
-test-utils = { path = "../test-utils" }
+test-utils.workspace = true
diff --git a/src/tools/rust-analyzer/crates/mbe/src/benchmark.rs b/src/tools/rust-analyzer/crates/mbe/src/benchmark.rs
index 4b7500250..894355fcb 100644
--- a/src/tools/rust-analyzer/crates/mbe/src/benchmark.rs
+++ b/src/tools/rust-analyzer/crates/mbe/src/benchmark.rs
@@ -9,7 +9,7 @@ use test_utils::{bench, bench_fixture, skip_slow_tests};
use crate::{
parser::{MetaVarKind, Op, RepeatKind, Separator},
- syntax_node_to_token_tree, DeclarativeMacro,
+ syntax_node_to_token_tree, tt, DeclarativeMacro,
};
#[test]
@@ -91,7 +91,14 @@ fn invocation_fixtures(rules: &FxHashMap<String, DeclarativeMacro>) -> Vec<(Stri
// So we just skip any error cases and try again
let mut try_cnt = 0;
loop {
- let mut subtree = tt::Subtree::default();
+ let mut subtree = tt::Subtree {
+ delimiter: tt::Delimiter {
+ open: tt::TokenId::UNSPECIFIED,
+ close: tt::TokenId::UNSPECIFIED,
+ kind: tt::DelimiterKind::Invisible,
+ },
+ token_trees: vec![],
+ };
for op in rule.lhs.iter() {
collect_from_op(op, &mut subtree, &mut seed);
}
@@ -145,7 +152,7 @@ fn invocation_fixtures(rules: &FxHashMap<String, DeclarativeMacro>) -> Vec<(Stri
Op::Ident(it) => parent.token_trees.push(tt::Leaf::from(it.clone()).into()),
Op::Punct(puncts) => {
for punct in puncts {
- parent.token_trees.push(tt::Leaf::from(punct.clone()).into());
+ parent.token_trees.push(tt::Leaf::from(*punct).into());
}
}
Op::Repeat { tokens, kind, separator } => {
@@ -196,12 +203,15 @@ fn invocation_fixtures(rules: &FxHashMap<String, DeclarativeMacro>) -> Vec<(Stri
*seed
}
fn make_ident(ident: &str) -> tt::TokenTree {
- tt::Leaf::Ident(tt::Ident { id: tt::TokenId::unspecified(), text: SmolStr::new(ident) })
- .into()
+ tt::Leaf::Ident(tt::Ident {
+ span: tt::TokenId::unspecified(),
+ text: SmolStr::new(ident),
+ })
+ .into()
}
fn make_punct(char: char) -> tt::TokenTree {
tt::Leaf::Punct(tt::Punct {
- id: tt::TokenId::unspecified(),
+ span: tt::TokenId::unspecified(),
char,
spacing: tt::Spacing::Alone,
})
@@ -209,7 +219,7 @@ fn invocation_fixtures(rules: &FxHashMap<String, DeclarativeMacro>) -> Vec<(Stri
}
fn make_literal(lit: &str) -> tt::TokenTree {
tt::Leaf::Literal(tt::Literal {
- id: tt::TokenId::unspecified(),
+ span: tt::TokenId::unspecified(),
text: SmolStr::new(lit),
})
.into()
@@ -219,7 +229,11 @@ fn invocation_fixtures(rules: &FxHashMap<String, DeclarativeMacro>) -> Vec<(Stri
token_trees: Option<Vec<tt::TokenTree>>,
) -> tt::TokenTree {
tt::Subtree {
- delimiter: Some(tt::Delimiter { id: tt::TokenId::unspecified(), kind }),
+ delimiter: tt::Delimiter {
+ open: tt::TokenId::unspecified(),
+ close: tt::TokenId::unspecified(),
+ kind,
+ },
token_trees: token_trees.unwrap_or_default(),
}
.into()
diff --git a/src/tools/rust-analyzer/crates/mbe/src/expander.rs b/src/tools/rust-analyzer/crates/mbe/src/expander.rs
index 100ec6bfb..7537dc322 100644
--- a/src/tools/rust-analyzer/crates/mbe/src/expander.rs
+++ b/src/tools/rust-analyzer/crates/mbe/src/expander.rs
@@ -8,7 +8,7 @@ mod transcriber;
use rustc_hash::FxHashMap;
use syntax::SmolStr;
-use crate::{parser::MetaVarKind, ExpandError, ExpandResult};
+use crate::{parser::MetaVarKind, tt, ExpandError, ExpandResult};
pub(crate) fn expand_rules(
rules: &[crate::Rule],
@@ -45,7 +45,10 @@ pub(crate) fn expand_rules(
transcriber::transcribe(&rule.rhs, &match_.bindings);
ExpandResult { value, err: match_.err.or(transcribe_err) }
} else {
- ExpandResult::only_err(ExpandError::NoMatchingRule)
+ ExpandResult::with_err(
+ tt::Subtree { delimiter: tt::Delimiter::unspecified(), token_trees: vec![] },
+ ExpandError::NoMatchingRule,
+ )
}
}
diff --git a/src/tools/rust-analyzer/crates/mbe/src/expander/matcher.rs b/src/tools/rust-analyzer/crates/mbe/src/expander/matcher.rs
index 88eae136f..f4ea9e5c8 100644
--- a/src/tools/rust-analyzer/crates/mbe/src/expander/matcher.rs
+++ b/src/tools/rust-analyzer/crates/mbe/src/expander/matcher.rs
@@ -67,6 +67,7 @@ use syntax::SmolStr;
use crate::{
expander::{Binding, Bindings, ExpandResult, Fragment},
parser::{MetaVarKind, Op, RepeatKind, Separator},
+ tt,
tt_iter::TtIter,
ExpandError, MetaTemplate, ValueResult,
};
@@ -75,7 +76,8 @@ impl Bindings {
fn push_optional(&mut self, name: &SmolStr) {
// FIXME: Do we have a better way to represent an empty token ?
// Insert an empty subtree for empty token
- let tt = tt::Subtree::default().into();
+ let tt =
+ tt::Subtree { delimiter: tt::Delimiter::unspecified(), token_trees: vec![] }.into();
self.inner.insert(name.clone(), Binding::Fragment(Fragment::Tokens(tt)));
}
@@ -462,9 +464,9 @@ fn match_loop_inner<'t>(
}
OpDelimited::Op(Op::Subtree { tokens, delimiter }) => {
if let Ok(subtree) = src.clone().expect_subtree() {
- if subtree.delimiter_kind() == delimiter.map(|it| it.kind) {
+ if subtree.delimiter.kind == delimiter.kind {
item.stack.push(item.dot);
- item.dot = tokens.iter_delimited(delimiter.as_ref());
+ item.dot = tokens.iter_delimited(Some(delimiter));
cur_items.push(item);
}
}
@@ -663,8 +665,8 @@ fn match_loop(pattern: &MetaTemplate, src: &tt::Subtree) -> Match {
}
res.add_err(ExpandError::LeftoverTokens);
- if let Some(error_reover_item) = error_recover_item {
- res.bindings = bindings_builder.build(&error_reover_item);
+ if let Some(error_recover_item) = error_recover_item {
+ res.bindings = bindings_builder.build(&error_recover_item);
}
return res;
}
@@ -782,7 +784,7 @@ fn match_meta_var(kind: MetaVarKind, input: &mut TtIter<'_>) -> ExpandResult<Opt
match neg {
None => lit.into(),
Some(neg) => tt::TokenTree::Subtree(tt::Subtree {
- delimiter: None,
+ delimiter: tt::Delimiter::unspecified(),
token_trees: vec![neg, lit.into()],
}),
}
@@ -810,7 +812,11 @@ fn collect_vars(collector_fun: &mut impl FnMut(SmolStr), pattern: &MetaTemplate)
}
impl MetaTemplate {
fn iter_delimited<'a>(&'a self, delimited: Option<&'a tt::Delimiter>) -> OpDelimitedIter<'a> {
- OpDelimitedIter { inner: &self.0, idx: 0, delimited }
+ OpDelimitedIter {
+ inner: &self.0,
+ idx: 0,
+ delimited: delimited.unwrap_or(&tt::Delimiter::UNSPECIFIED),
+ }
}
}
@@ -824,20 +830,21 @@ enum OpDelimited<'a> {
#[derive(Debug, Clone, Copy)]
struct OpDelimitedIter<'a> {
inner: &'a [Op],
- delimited: Option<&'a tt::Delimiter>,
+ delimited: &'a tt::Delimiter,
idx: usize,
}
impl<'a> OpDelimitedIter<'a> {
fn is_eof(&self) -> bool {
- let len = self.inner.len() + if self.delimited.is_some() { 2 } else { 0 };
+ let len = self.inner.len()
+ + if self.delimited.kind != tt::DelimiterKind::Invisible { 2 } else { 0 };
self.idx >= len
}
fn peek(&self) -> Option<OpDelimited<'a>> {
- match self.delimited {
- None => self.inner.get(self.idx).map(OpDelimited::Op),
- Some(_) => match self.idx {
+ match self.delimited.kind {
+ tt::DelimiterKind::Invisible => self.inner.get(self.idx).map(OpDelimited::Op),
+ _ => match self.idx {
0 => Some(OpDelimited::Open),
i if i == self.inner.len() + 1 => Some(OpDelimited::Close),
i => self.inner.get(i - 1).map(OpDelimited::Op),
@@ -860,7 +867,8 @@ impl<'a> Iterator for OpDelimitedIter<'a> {
}
fn size_hint(&self) -> (usize, Option<usize>) {
- let len = self.inner.len() + if self.delimited.is_some() { 2 } else { 0 };
+ let len = self.inner.len()
+ + if self.delimited.kind != tt::DelimiterKind::Invisible { 2 } else { 0 };
let remain = len.saturating_sub(self.idx);
(remain, Some(remain))
}
@@ -904,7 +912,10 @@ impl<'a> TtIter<'a> {
} else {
let puncts = self.expect_glued_punct()?;
let token_trees = puncts.into_iter().map(|p| tt::Leaf::Punct(p).into()).collect();
- Ok(tt::TokenTree::Subtree(tt::Subtree { delimiter: None, token_trees }))
+ Ok(tt::TokenTree::Subtree(tt::Subtree {
+ delimiter: tt::Delimiter::unspecified(),
+ token_trees,
+ }))
}
} else {
self.next().ok_or(()).cloned()
@@ -919,7 +930,7 @@ impl<'a> TtIter<'a> {
let ident = self.expect_ident_or_underscore()?;
Ok(tt::Subtree {
- delimiter: None,
+ delimiter: tt::Delimiter::unspecified(),
token_trees: vec![
tt::Leaf::Punct(*punct).into(),
tt::Leaf::Ident(ident.clone()).into(),
diff --git a/src/tools/rust-analyzer/crates/mbe/src/expander/transcriber.rs b/src/tools/rust-analyzer/crates/mbe/src/expander/transcriber.rs
index db0d327bf..dffb40d4b 100644
--- a/src/tools/rust-analyzer/crates/mbe/src/expander/transcriber.rs
+++ b/src/tools/rust-analyzer/crates/mbe/src/expander/transcriber.rs
@@ -2,11 +2,11 @@
//! `$ident => foo`, interpolates variables in the template, to get `fn foo() {}`
use syntax::SmolStr;
-use tt::{Delimiter, Subtree};
use crate::{
expander::{Binding, Bindings, Fragment},
parser::{MetaVarKind, Op, RepeatKind, Separator},
+ tt::{self, Delimiter},
ExpandError, ExpandResult, MetaTemplate,
};
@@ -44,22 +44,23 @@ impl Bindings {
Binding::Missing(it) => Ok(match it {
MetaVarKind::Stmt => {
Fragment::Tokens(tt::TokenTree::Leaf(tt::Leaf::Punct(tt::Punct {
- id: tt::TokenId::unspecified(),
+ span: tt::TokenId::unspecified(),
char: ';',
spacing: tt::Spacing::Alone,
})))
}
MetaVarKind::Block => Fragment::Tokens(tt::TokenTree::Subtree(tt::Subtree {
- delimiter: Some(tt::Delimiter {
- id: tt::TokenId::unspecified(),
+ delimiter: tt::Delimiter {
+ open: tt::TokenId::unspecified(),
+ close: tt::TokenId::unspecified(),
kind: tt::DelimiterKind::Brace,
- }),
+ },
token_trees: vec![],
})),
// FIXME: Meta and Item should get proper defaults
MetaVarKind::Meta | MetaVarKind::Item | MetaVarKind::Tt | MetaVarKind::Vis => {
Fragment::Tokens(tt::TokenTree::Subtree(tt::Subtree {
- delimiter: None,
+ delimiter: tt::Delimiter::UNSPECIFIED,
token_trees: vec![],
}))
}
@@ -71,19 +72,19 @@ impl Bindings {
| MetaVarKind::Ident => {
Fragment::Tokens(tt::TokenTree::Leaf(tt::Leaf::Ident(tt::Ident {
text: SmolStr::new_inline("missing"),
- id: tt::TokenId::unspecified(),
+ span: tt::TokenId::unspecified(),
})))
}
MetaVarKind::Lifetime => {
Fragment::Tokens(tt::TokenTree::Leaf(tt::Leaf::Ident(tt::Ident {
text: SmolStr::new_inline("'missing"),
- id: tt::TokenId::unspecified(),
+ span: tt::TokenId::unspecified(),
})))
}
MetaVarKind::Literal => {
Fragment::Tokens(tt::TokenTree::Leaf(tt::Leaf::Ident(tt::Ident {
text: SmolStr::new_inline("\"missing\""),
- id: tt::TokenId::unspecified(),
+ span: tt::TokenId::unspecified(),
})))
}
}),
@@ -138,12 +139,12 @@ fn expand_subtree(
Op::Ident(it) => arena.push(tt::Leaf::from(it.clone()).into()),
Op::Punct(puncts) => {
for punct in puncts {
- arena.push(tt::Leaf::from(punct.clone()).into());
+ arena.push(tt::Leaf::from(*punct).into());
}
}
Op::Subtree { tokens, delimiter } => {
let ExpandResult { value: tt, err: e } =
- expand_subtree(ctx, tokens, *delimiter, arena);
+ expand_subtree(ctx, tokens, Some(*delimiter), arena);
err = err.or(e);
arena.push(tt.into());
}
@@ -170,7 +171,7 @@ fn expand_subtree(
arena.push(
tt::Leaf::Literal(tt::Literal {
text: index.to_string().into(),
- id: tt::TokenId::unspecified(),
+ span: tt::TokenId::unspecified(),
})
.into(),
);
@@ -179,7 +180,13 @@ fn expand_subtree(
}
// drain the elements added in this instance of expand_subtree
let tts = arena.drain(start_elements..).collect();
- ExpandResult { value: tt::Subtree { delimiter, token_trees: tts }, err }
+ ExpandResult {
+ value: tt::Subtree {
+ delimiter: delimiter.unwrap_or_else(tt::Delimiter::unspecified),
+ token_trees: tts,
+ },
+ err,
+ }
}
fn expand_var(ctx: &mut ExpandCtx<'_>, v: &SmolStr, id: tt::TokenId) -> ExpandResult<Fragment> {
@@ -201,18 +208,25 @@ fn expand_var(ctx: &mut ExpandCtx<'_>, v: &SmolStr, id: tt::TokenId) -> ExpandRe
// ```
// We just treat it a normal tokens
let tt = tt::Subtree {
- delimiter: None,
+ delimiter: tt::Delimiter::UNSPECIFIED,
token_trees: vec![
- tt::Leaf::from(tt::Punct { char: '$', spacing: tt::Spacing::Alone, id }).into(),
- tt::Leaf::from(tt::Ident { text: v.clone(), id }).into(),
+ tt::Leaf::from(tt::Punct { char: '$', spacing: tt::Spacing::Alone, span: id })
+ .into(),
+ tt::Leaf::from(tt::Ident { text: v.clone(), span: id }).into(),
],
}
.into();
ExpandResult::ok(Fragment::Tokens(tt))
} else {
ctx.bindings.get(v, &mut ctx.nesting).map_or_else(
- |e| ExpandResult { value: Fragment::Tokens(tt::TokenTree::empty()), err: Some(e) },
- |it| ExpandResult::ok(it),
+ |e| ExpandResult {
+ value: Fragment::Tokens(tt::TokenTree::Subtree(tt::Subtree {
+ delimiter: tt::Delimiter::unspecified(),
+ token_trees: vec![],
+ })),
+ err: Some(e),
+ },
+ ExpandResult::ok,
)
}
}
@@ -249,7 +263,10 @@ fn expand_repeat(
ctx
);
return ExpandResult {
- value: Fragment::Tokens(Subtree::default().into()),
+ value: Fragment::Tokens(
+ tt::Subtree { delimiter: tt::Delimiter::unspecified(), token_trees: vec![] }
+ .into(),
+ ),
err: Some(ExpandError::LimitExceeded),
};
}
@@ -258,7 +275,7 @@ fn expand_repeat(
continue;
}
- t.delimiter = None;
+ t.delimiter = tt::Delimiter::unspecified();
push_subtree(&mut buf, t);
if let Some(sep) = separator {
@@ -292,7 +309,7 @@ fn expand_repeat(
// Check if it is a single token subtree without any delimiter
// e.g {Delimiter:None> ['>'] /Delimiter:None>}
- let tt = tt::Subtree { delimiter: None, token_trees: buf }.into();
+ let tt = tt::Subtree { delimiter: tt::Delimiter::unspecified(), token_trees: buf }.into();
if RepeatKind::OneOrMore == kind && counter == 0 {
return ExpandResult {
@@ -307,11 +324,12 @@ fn push_fragment(buf: &mut Vec<tt::TokenTree>, fragment: Fragment) {
match fragment {
Fragment::Tokens(tt::TokenTree::Subtree(tt)) => push_subtree(buf, tt),
Fragment::Expr(tt::TokenTree::Subtree(mut tt)) => {
- if tt.delimiter.is_none() {
- tt.delimiter = Some(tt::Delimiter {
- id: tt::TokenId::unspecified(),
+ if tt.delimiter.kind == tt::DelimiterKind::Invisible {
+ tt.delimiter = tt::Delimiter {
+ open: tt::TokenId::UNSPECIFIED,
+ close: tt::TokenId::UNSPECIFIED,
kind: tt::DelimiterKind::Parenthesis,
- })
+ };
}
buf.push(tt.into())
}
@@ -320,8 +338,8 @@ fn push_fragment(buf: &mut Vec<tt::TokenTree>, fragment: Fragment) {
}
fn push_subtree(buf: &mut Vec<tt::TokenTree>, tt: tt::Subtree) {
- match tt.delimiter {
- None => buf.extend(tt.token_trees),
- Some(_) => buf.push(tt.into()),
+ match tt.delimiter.kind {
+ tt::DelimiterKind::Invisible => buf.extend(tt.token_trees),
+ _ => buf.push(tt.into()),
}
}
diff --git a/src/tools/rust-analyzer/crates/mbe/src/lib.rs b/src/tools/rust-analyzer/crates/mbe/src/lib.rs
index 2373db97a..ac107a0d6 100644
--- a/src/tools/rust-analyzer/crates/mbe/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/mbe/src/lib.rs
@@ -18,6 +18,8 @@ mod to_parser_input;
mod benchmark;
mod token_map;
+use ::tt::token_id as tt;
+
use std::fmt;
use crate::{
@@ -26,8 +28,8 @@ use crate::{
};
// FIXME: we probably should re-think `token_tree_to_syntax_node` interfaces
+pub use self::tt::{Delimiter, DelimiterKind, Punct};
pub use ::parser::TopEntryPoint;
-pub use tt::{Delimiter, DelimiterKind, Punct};
pub use crate::{
syntax_bridge::{
@@ -125,24 +127,26 @@ impl Shift {
// Find the max token id inside a subtree
fn max_id(subtree: &tt::Subtree) -> Option<u32> {
- let filter = |tt: &_| match tt {
- tt::TokenTree::Subtree(subtree) => {
- let tree_id = max_id(subtree);
- match subtree.delimiter {
- Some(it) if it.id != tt::TokenId::unspecified() => {
- Some(tree_id.map_or(it.id.0, |t| t.max(it.id.0)))
+ let filter =
+ |tt: &_| match tt {
+ tt::TokenTree::Subtree(subtree) => {
+ let tree_id = max_id(subtree);
+ if subtree.delimiter.open != tt::TokenId::unspecified() {
+ Some(tree_id.map_or(subtree.delimiter.open.0, |t| {
+ t.max(subtree.delimiter.open.0)
+ }))
+ } else {
+ tree_id
}
- _ => tree_id,
}
- }
- tt::TokenTree::Leaf(leaf) => {
- let &(tt::Leaf::Ident(tt::Ident { id, .. })
- | tt::Leaf::Punct(tt::Punct { id, .. })
- | tt::Leaf::Literal(tt::Literal { id, .. })) = leaf;
+ tt::TokenTree::Leaf(leaf) => {
+ let &(tt::Leaf::Ident(tt::Ident { span, .. })
+ | tt::Leaf::Punct(tt::Punct { span, .. })
+ | tt::Leaf::Literal(tt::Literal { span, .. })) = leaf;
- (id != tt::TokenId::unspecified()).then_some(id.0)
- }
- };
+ (span != tt::TokenId::unspecified()).then_some(span.0)
+ }
+ };
subtree.token_trees.iter().filter_map(filter).max()
}
}
@@ -152,14 +156,13 @@ impl Shift {
for t in &mut tt.token_trees {
match t {
tt::TokenTree::Leaf(
- tt::Leaf::Ident(tt::Ident { id, .. })
- | tt::Leaf::Punct(tt::Punct { id, .. })
- | tt::Leaf::Literal(tt::Literal { id, .. }),
- ) => *id = self.shift(*id),
+ tt::Leaf::Ident(tt::Ident { span, .. })
+ | tt::Leaf::Punct(tt::Punct { span, .. })
+ | tt::Leaf::Literal(tt::Literal { span, .. }),
+ ) => *span = self.shift(*span),
tt::TokenTree::Subtree(tt) => {
- if let Some(it) = tt.delimiter.as_mut() {
- it.id = self.shift(it.id);
- }
+ tt.delimiter.open = self.shift(tt.delimiter.open);
+ tt.delimiter.close = self.shift(tt.delimiter.close);
self.shift_all(tt)
}
}
@@ -216,7 +219,7 @@ impl DeclarativeMacro {
let mut src = TtIter::new(tt);
let mut rules = Vec::new();
- if Some(tt::DelimiterKind::Brace) == tt.delimiter_kind() {
+ if tt::DelimiterKind::Brace == tt.delimiter.kind {
cov_mark::hit!(parse_macro_def_rules);
while src.len() > 0 {
let rule = Rule::parse(&mut src, true)?;
@@ -325,6 +328,10 @@ impl<T, E> ValueResult<T, E> {
Self { value, err: None }
}
+ pub fn with_err(value: T, err: E) -> Self {
+ Self { value, err: Some(err) }
+ }
+
pub fn only_err(err: E) -> Self
where
T: Default,
diff --git a/src/tools/rust-analyzer/crates/mbe/src/parser.rs b/src/tools/rust-analyzer/crates/mbe/src/parser.rs
index fad905e97..fd3d64719 100644
--- a/src/tools/rust-analyzer/crates/mbe/src/parser.rs
+++ b/src/tools/rust-analyzer/crates/mbe/src/parser.rs
@@ -4,7 +4,7 @@
use smallvec::{smallvec, SmallVec};
use syntax::SmolStr;
-use crate::{tt_iter::TtIter, ParseError};
+use crate::{tt, tt_iter::TtIter, ParseError};
/// Consider
///
@@ -54,7 +54,7 @@ pub(crate) enum Op {
Ignore { name: SmolStr, id: tt::TokenId },
Index { depth: u32 },
Repeat { tokens: MetaTemplate, kind: RepeatKind, separator: Option<Separator> },
- Subtree { tokens: MetaTemplate, delimiter: Option<tt::Delimiter> },
+ Subtree { tokens: MetaTemplate, delimiter: tt::Delimiter },
Literal(tt::Literal),
Punct(SmallVec<[tt::Punct; 3]>),
Ident(tt::Ident),
@@ -126,17 +126,17 @@ fn next_op(
src.next().expect("first token already peeked");
// Note that the '$' itself is a valid token inside macro_rules.
let second = match src.next() {
- None => return Ok(Op::Punct(smallvec![p.clone()])),
+ None => return Ok(Op::Punct(smallvec![*p])),
Some(it) => it,
};
match second {
- tt::TokenTree::Subtree(subtree) => match subtree.delimiter_kind() {
- Some(tt::DelimiterKind::Parenthesis) => {
+ tt::TokenTree::Subtree(subtree) => match subtree.delimiter.kind {
+ tt::DelimiterKind::Parenthesis => {
let (separator, kind) = parse_repeat(src)?;
let tokens = MetaTemplate::parse(subtree, mode)?;
Op::Repeat { tokens, separator, kind }
}
- Some(tt::DelimiterKind::Brace) => match mode {
+ tt::DelimiterKind::Brace => match mode {
Mode::Template => {
parse_metavar_expr(&mut TtIter::new(subtree)).map_err(|()| {
ParseError::unexpected("invalid metavariable expression")
@@ -157,18 +157,18 @@ fn next_op(
tt::TokenTree::Leaf(leaf) => match leaf {
tt::Leaf::Ident(ident) if ident.text == "crate" => {
// We simply produce identifier `$crate` here. And it will be resolved when lowering ast to Path.
- Op::Ident(tt::Ident { text: "$crate".into(), id: ident.id })
+ Op::Ident(tt::Ident { text: "$crate".into(), span: ident.span })
}
tt::Leaf::Ident(ident) => {
let kind = eat_fragment_kind(src, mode)?;
let name = ident.text.clone();
- let id = ident.id;
+ let id = ident.span;
Op::Var { name, kind, id }
}
tt::Leaf::Literal(lit) if is_boolean_literal(lit) => {
let kind = eat_fragment_kind(src, mode)?;
let name = lit.text.clone();
- let id = lit.id;
+ let id = lit.span;
Op::Var { name, kind, id }
}
tt::Leaf::Punct(punct @ tt::Punct { char: '$', .. }) => match mode {
@@ -284,7 +284,7 @@ fn parse_metavar_expr(src: &mut TtIter<'_>) -> Result<Op, ()> {
let func = src.expect_ident()?;
let args = src.expect_subtree()?;
- if args.delimiter_kind() != Some(tt::DelimiterKind::Parenthesis) {
+ if args.delimiter.kind != tt::DelimiterKind::Parenthesis {
return Err(());
}
@@ -293,7 +293,7 @@ fn parse_metavar_expr(src: &mut TtIter<'_>) -> Result<Op, ()> {
let op = match &*func.text {
"ignore" => {
let ident = args.expect_ident()?;
- Op::Ignore { name: ident.text.clone(), id: ident.id }
+ Op::Ignore { name: ident.text.clone(), id: ident.span }
}
"index" => {
let depth = if args.len() == 0 { 0 } else { args.expect_u32_literal()? };
diff --git a/src/tools/rust-analyzer/crates/mbe/src/syntax_bridge.rs b/src/tools/rust-analyzer/crates/mbe/src/syntax_bridge.rs
index 5c9650556..fb5313401 100644
--- a/src/tools/rust-analyzer/crates/mbe/src/syntax_bridge.rs
+++ b/src/tools/rust-analyzer/crates/mbe/src/syntax_bridge.rs
@@ -8,9 +8,16 @@ use syntax::{
SyntaxKind::*,
SyntaxNode, SyntaxToken, SyntaxTreeBuilder, TextRange, TextSize, WalkEvent, T,
};
-use tt::buffer::{Cursor, TokenBuffer};
-use crate::{to_parser_input::to_parser_input, tt_iter::TtIter, TokenMap};
+use crate::{
+ to_parser_input::to_parser_input,
+ tt::{
+ self,
+ buffer::{Cursor, TokenBuffer},
+ },
+ tt_iter::TtIter,
+ TokenMap,
+};
#[cfg(test)]
mod tests;
@@ -74,9 +81,10 @@ pub fn token_tree_to_syntax_node(
entry_point: parser::TopEntryPoint,
) -> (Parse<SyntaxNode>, TokenMap) {
let buffer = match tt {
- tt::Subtree { delimiter: None, token_trees } => {
- TokenBuffer::from_tokens(token_trees.as_slice())
- }
+ tt::Subtree {
+ delimiter: tt::Delimiter { kind: tt::DelimiterKind::Invisible, .. },
+ token_trees,
+ } => TokenBuffer::from_tokens(token_trees.as_slice()),
_ => TokenBuffer::from_subtree(tt),
};
let parser_input = to_parser_input(&buffer);
@@ -87,13 +95,15 @@ pub fn token_tree_to_syntax_node(
parser::Step::Token { kind, n_input_tokens: n_raw_tokens } => {
tree_sink.token(kind, n_raw_tokens)
}
+ parser::Step::FloatSplit { ends_in_dot: has_pseudo_dot } => {
+ tree_sink.float_split(has_pseudo_dot)
+ }
parser::Step::Enter { kind } => tree_sink.start_node(kind),
parser::Step::Exit => tree_sink.finish_node(),
parser::Step::Error { msg } => tree_sink.error(msg.to_string()),
}
}
- let (parse, range_map) = tree_sink.finish();
- (parse, range_map)
+ tree_sink.finish()
}
/// Convert a string to a `TokenTree`
@@ -132,7 +142,7 @@ pub fn parse_exprs_with_sep(tt: &tt::Subtree, sep: char) -> Vec<tt::Subtree> {
res.push(match expanded.value {
None => break,
Some(tt @ tt::TokenTree::Leaf(_)) => {
- tt::Subtree { delimiter: None, token_trees: vec![tt] }
+ tt::Subtree { delimiter: tt::Delimiter::unspecified(), token_trees: vec![tt] }
}
Some(tt::TokenTree::Subtree(tt)) => tt,
});
@@ -145,7 +155,10 @@ pub fn parse_exprs_with_sep(tt: &tt::Subtree, sep: char) -> Vec<tt::Subtree> {
}
if iter.peek_n(0).is_some() {
- res.push(tt::Subtree { delimiter: None, token_trees: iter.cloned().collect() });
+ res.push(tt::Subtree {
+ delimiter: tt::Delimiter::unspecified(),
+ token_trees: iter.cloned().collect(),
+ });
}
res
@@ -159,7 +172,7 @@ fn convert_tokens<C: TokenConverter>(conv: &mut C) -> tt::Subtree {
}
let entry = StackEntry {
- subtree: tt::Subtree { delimiter: None, ..Default::default() },
+ subtree: tt::Subtree { delimiter: tt::Delimiter::unspecified(), token_trees: vec![] },
// never used (delimiter is `None`)
idx: !0,
open_range: TextRange::empty(TextSize::of('.')),
@@ -186,7 +199,7 @@ fn convert_tokens<C: TokenConverter>(conv: &mut C) -> tt::Subtree {
if let Some(tt::TokenTree::Leaf(tt::Leaf::Literal(lit))) =
sub.token_trees.get_mut(2)
{
- lit.id = id
+ lit.span = id
}
}
tt
@@ -199,13 +212,14 @@ fn convert_tokens<C: TokenConverter>(conv: &mut C) -> tt::Subtree {
assert_eq!(range.len(), TextSize::of('.'));
}
- if let Some(delim) = subtree.delimiter {
- let expected = match delim.kind {
- tt::DelimiterKind::Parenthesis => T![')'],
- tt::DelimiterKind::Brace => T!['}'],
- tt::DelimiterKind::Bracket => T![']'],
- };
+ let expected = match subtree.delimiter.kind {
+ tt::DelimiterKind::Parenthesis => Some(T![')']),
+ tt::DelimiterKind::Brace => Some(T!['}']),
+ tt::DelimiterKind::Bracket => Some(T![']']),
+ tt::DelimiterKind::Invisible => None,
+ };
+ if let Some(expected) = expected {
if kind == expected {
if let Some(entry) = stack.pop() {
conv.id_alloc().close_delim(entry.idx, Some(range));
@@ -223,9 +237,11 @@ fn convert_tokens<C: TokenConverter>(conv: &mut C) -> tt::Subtree {
};
if let Some(kind) = delim {
- let mut subtree = tt::Subtree::default();
let (id, idx) = conv.id_alloc().open_delim(range, synth_id);
- subtree.delimiter = Some(tt::Delimiter { id, kind });
+ let subtree = tt::Subtree {
+ delimiter: tt::Delimiter { open: id, close: tt::TokenId::UNSPECIFIED, kind },
+ token_trees: vec![],
+ };
stack.push(StackEntry { subtree, idx, open_range: range });
continue;
}
@@ -240,13 +256,20 @@ fn convert_tokens<C: TokenConverter>(conv: &mut C) -> tt::Subtree {
panic!("Token from lexer must be single char: token = {token:#?}");
}
};
- tt::Leaf::from(tt::Punct { char, spacing, id: conv.id_alloc().alloc(range, synth_id) })
- .into()
+ tt::Leaf::from(tt::Punct {
+ char,
+ spacing,
+ span: conv.id_alloc().alloc(range, synth_id),
+ })
+ .into()
} else {
macro_rules! make_leaf {
($i:ident) => {
- tt::$i { id: conv.id_alloc().alloc(range, synth_id), text: token.to_text(conv) }
- .into()
+ tt::$i {
+ span: conv.id_alloc().alloc(range, synth_id),
+ text: token.to_text(conv),
+ }
+ .into()
};
}
let leaf: tt::Leaf = match kind {
@@ -261,14 +284,14 @@ fn convert_tokens<C: TokenConverter>(conv: &mut C) -> tt::Subtree {
let apostrophe = tt::Leaf::from(tt::Punct {
char: '\'',
spacing: tt::Spacing::Joint,
- id: conv.id_alloc().alloc(r, synth_id),
+ span: conv.id_alloc().alloc(r, synth_id),
});
result.push(apostrophe.into());
let r = TextRange::at(range.start() + char_unit, range.len() - char_unit);
let ident = tt::Leaf::from(tt::Ident {
text: SmolStr::new(&token.to_text(conv)[1..]),
- id: conv.id_alloc().alloc(r, synth_id),
+ span: conv.id_alloc().alloc(r, synth_id),
});
result.push(ident.into());
continue;
@@ -289,11 +312,12 @@ fn convert_tokens<C: TokenConverter>(conv: &mut C) -> tt::Subtree {
conv.id_alloc().close_delim(entry.idx, None);
let leaf: tt::Leaf = tt::Punct {
- id: conv.id_alloc().alloc(entry.open_range, None),
- char: match entry.subtree.delimiter.unwrap().kind {
+ span: conv.id_alloc().alloc(entry.open_range, None),
+ char: match entry.subtree.delimiter.kind {
tt::DelimiterKind::Parenthesis => '(',
tt::DelimiterKind::Brace => '{',
tt::DelimiterKind::Bracket => '[',
+ tt::DelimiterKind::Invisible => '$',
},
spacing: tt::Spacing::Alone,
}
@@ -373,10 +397,11 @@ fn convert_doc_comment(token: &syntax::SyntaxToken) -> Option<Vec<tt::TokenTree>
token_trees.push(mk_punct('!'));
}
token_trees.push(tt::TokenTree::from(tt::Subtree {
- delimiter: Some(tt::Delimiter {
+ delimiter: tt::Delimiter {
+ open: tt::TokenId::UNSPECIFIED,
+ close: tt::TokenId::UNSPECIFIED,
kind: tt::DelimiterKind::Bracket,
- id: tt::TokenId::unspecified(),
- }),
+ },
token_trees: meta_tkns,
}));
@@ -386,7 +411,7 @@ fn convert_doc_comment(token: &syntax::SyntaxToken) -> Option<Vec<tt::TokenTree>
fn mk_ident(s: &str) -> tt::TokenTree {
tt::TokenTree::from(tt::Leaf::from(tt::Ident {
text: s.into(),
- id: tt::TokenId::unspecified(),
+ span: tt::TokenId::unspecified(),
}))
}
@@ -394,12 +419,12 @@ fn convert_doc_comment(token: &syntax::SyntaxToken) -> Option<Vec<tt::TokenTree>
tt::TokenTree::from(tt::Leaf::from(tt::Punct {
char: c,
spacing: tt::Spacing::Alone,
- id: tt::TokenId::unspecified(),
+ span: tt::TokenId::unspecified(),
}))
}
fn mk_doc_literal(comment: &ast::Comment) -> tt::TokenTree {
- let lit = tt::Literal { text: doc_comment_text(comment), id: tt::TokenId::unspecified() };
+ let lit = tt::Literal { text: doc_comment_text(comment), span: tt::TokenId::unspecified() };
tt::TokenTree::from(tt::Leaf::from(lit))
}
@@ -761,18 +786,56 @@ impl<'a> TtTreeSink<'a> {
}
}
-fn delim_to_str(d: tt::DelimiterKind, closing: bool) -> &'static str {
+fn delim_to_str(d: tt::DelimiterKind, closing: bool) -> Option<&'static str> {
let texts = match d {
tt::DelimiterKind::Parenthesis => "()",
tt::DelimiterKind::Brace => "{}",
tt::DelimiterKind::Bracket => "[]",
+ tt::DelimiterKind::Invisible => return None,
};
let idx = closing as usize;
- &texts[idx..texts.len() - (1 - idx)]
+ Some(&texts[idx..texts.len() - (1 - idx)])
}
impl<'a> TtTreeSink<'a> {
+ /// Parses a float literal as if it was a one to two name ref nodes with a dot inbetween.
+ /// This occurs when a float literal is used as a field access.
+ fn float_split(&mut self, has_pseudo_dot: bool) {
+ let (text, _span) = match self.cursor.token_tree() {
+ Some(tt::buffer::TokenTreeRef::Leaf(tt::Leaf::Literal(lit), _)) => {
+ (lit.text.as_str(), lit.span)
+ }
+ _ => unreachable!(),
+ };
+ match text.split_once('.') {
+ Some((left, right)) => {
+ assert!(!left.is_empty());
+ self.inner.start_node(SyntaxKind::NAME_REF);
+ self.inner.token(SyntaxKind::INT_NUMBER, left);
+ self.inner.finish_node();
+
+ // here we move the exit up, the original exit has been deleted in process
+ self.inner.finish_node();
+
+ self.inner.token(SyntaxKind::DOT, ".");
+
+ if has_pseudo_dot {
+ assert!(right.is_empty(), "{left}.{right}");
+ } else {
+ self.inner.start_node(SyntaxKind::NAME_REF);
+ self.inner.token(SyntaxKind::INT_NUMBER, right);
+ self.inner.finish_node();
+
+ // the parser creates an unbalanced start node, we are required to close it here
+ self.inner.finish_node();
+ }
+ }
+ None => unreachable!(),
+ }
+ self.cursor = self.cursor.bump();
+ }
+
fn token(&mut self, kind: SyntaxKind, mut n_tokens: u8) {
if kind == LIFETIME_IDENT {
n_tokens = 2;
@@ -790,13 +853,16 @@ impl<'a> TtTreeSink<'a> {
Some(tt::buffer::TokenTreeRef::Leaf(leaf, _)) => {
// Mark the range if needed
let (text, id) = match leaf {
- tt::Leaf::Ident(ident) => (ident.text.as_str(), ident.id),
+ tt::Leaf::Ident(ident) => (ident.text.as_str(), ident.span),
tt::Leaf::Punct(punct) => {
assert!(punct.char.is_ascii());
tmp = punct.char as u8;
- (std::str::from_utf8(std::slice::from_ref(&tmp)).unwrap(), punct.id)
+ (
+ std::str::from_utf8(std::slice::from_ref(&tmp)).unwrap(),
+ punct.span,
+ )
}
- tt::Leaf::Literal(lit) => (lit.text.as_str(), lit.id),
+ tt::Leaf::Literal(lit) => (lit.text.as_str(), lit.span),
};
let range = TextRange::at(self.text_pos, TextSize::of(text));
self.token_map.insert(id, range);
@@ -805,10 +871,10 @@ impl<'a> TtTreeSink<'a> {
}
Some(tt::buffer::TokenTreeRef::Subtree(subtree, _)) => {
self.cursor = self.cursor.subtree().unwrap();
- match subtree.delimiter {
- Some(d) => {
- self.open_delims.insert(d.id, self.text_pos);
- delim_to_str(d.kind, false)
+ match delim_to_str(subtree.delimiter.kind, false) {
+ Some(it) => {
+ self.open_delims.insert(subtree.delimiter.open, self.text_pos);
+ it
}
None => continue,
}
@@ -816,15 +882,21 @@ impl<'a> TtTreeSink<'a> {
None => {
let parent = self.cursor.end().unwrap();
self.cursor = self.cursor.bump();
- match parent.delimiter {
- Some(d) => {
- if let Some(open_delim) = self.open_delims.get(&d.id) {
+ match delim_to_str(parent.delimiter.kind, true) {
+ Some(it) => {
+ if let Some(open_delim) =
+ self.open_delims.get(&parent.delimiter.open)
+ {
let open_range = TextRange::at(*open_delim, TextSize::of('('));
let close_range =
TextRange::at(self.text_pos, TextSize::of('('));
- self.token_map.insert_delim(d.id, open_range, close_range);
+ self.token_map.insert_delim(
+ parent.delimiter.open,
+ open_range,
+ close_range,
+ );
}
- delim_to_str(d.kind, true)
+ it
}
None => continue,
}
diff --git a/src/tools/rust-analyzer/crates/mbe/src/syntax_bridge/tests.rs b/src/tools/rust-analyzer/crates/mbe/src/syntax_bridge/tests.rs
index c1a608365..fa0125f3e 100644
--- a/src/tools/rust-analyzer/crates/mbe/src/syntax_bridge/tests.rs
+++ b/src/tools/rust-analyzer/crates/mbe/src/syntax_bridge/tests.rs
@@ -29,8 +29,8 @@ fn check_punct_spacing(fixture: &str) {
let mut cursor = buf.begin();
while !cursor.eof() {
while let Some(token_tree) = cursor.token_tree() {
- if let TokenTreeRef::Leaf(Leaf::Punct(Punct { spacing, id, .. }), _) = token_tree {
- if let Some(expected) = annotations.remove(id) {
+ if let TokenTreeRef::Leaf(Leaf::Punct(Punct { spacing, span, .. }), _) = token_tree {
+ if let Some(expected) = annotations.remove(span) {
assert_eq!(expected, *spacing);
}
}
diff --git a/src/tools/rust-analyzer/crates/mbe/src/to_parser_input.rs b/src/tools/rust-analyzer/crates/mbe/src/to_parser_input.rs
index 7013aa58b..051e20b3a 100644
--- a/src/tools/rust-analyzer/crates/mbe/src/to_parser_input.rs
+++ b/src/tools/rust-analyzer/crates/mbe/src/to_parser_input.rs
@@ -2,7 +2,8 @@
//! format that works for our parser.
use syntax::{SyntaxKind, SyntaxKind::*, T};
-use tt::buffer::TokenBuffer;
+
+use crate::tt::buffer::TokenBuffer;
pub(crate) fn to_parser_input(buffer: &TokenBuffer<'_>) -> parser::Input {
let mut res = parser::Input::default();
@@ -44,6 +45,13 @@ pub(crate) fn to_parser_input(buffer: &TokenBuffer<'_>) -> parser::Input {
.unwrap_or_else(|| panic!("Fail to convert given literal {:#?}", &lit));
res.push(kind);
+
+ if kind == FLOAT_NUMBER && !inner_text.ends_with('.') {
+ // Tag the token as joint if it is float with a fractional part
+ // we use this jointness to inform the parser about what token split
+ // event to emit when we encounter a float literal in a field access
+ res.was_joint();
+ }
}
tt::Leaf::Ident(ident) => match ident.text.as_ref() {
"_" => res.push(T![_]),
@@ -70,23 +78,25 @@ pub(crate) fn to_parser_input(buffer: &TokenBuffer<'_>) -> parser::Input {
cursor.bump()
}
Some(tt::buffer::TokenTreeRef::Subtree(subtree, _)) => {
- if let Some(d) = subtree.delimiter_kind() {
- res.push(match d {
- tt::DelimiterKind::Parenthesis => T!['('],
- tt::DelimiterKind::Brace => T!['{'],
- tt::DelimiterKind::Bracket => T!['['],
- });
+ if let Some(kind) = match subtree.delimiter.kind {
+ tt::DelimiterKind::Parenthesis => Some(T!['(']),
+ tt::DelimiterKind::Brace => Some(T!['{']),
+ tt::DelimiterKind::Bracket => Some(T!['[']),
+ tt::DelimiterKind::Invisible => None,
+ } {
+ res.push(kind);
}
cursor.subtree().unwrap()
}
None => match cursor.end() {
Some(subtree) => {
- if let Some(d) = subtree.delimiter_kind() {
- res.push(match d {
- tt::DelimiterKind::Parenthesis => T![')'],
- tt::DelimiterKind::Brace => T!['}'],
- tt::DelimiterKind::Bracket => T![']'],
- })
+ if let Some(kind) = match subtree.delimiter.kind {
+ tt::DelimiterKind::Parenthesis => Some(T![')']),
+ tt::DelimiterKind::Brace => Some(T!['}']),
+ tt::DelimiterKind::Bracket => Some(T![']']),
+ tt::DelimiterKind::Invisible => None,
+ } {
+ res.push(kind);
}
cursor.bump()
}
diff --git a/src/tools/rust-analyzer/crates/mbe/src/tt_iter.rs b/src/tools/rust-analyzer/crates/mbe/src/tt_iter.rs
index bee7b5de6..f744481f3 100644
--- a/src/tools/rust-analyzer/crates/mbe/src/tt_iter.rs
+++ b/src/tools/rust-analyzer/crates/mbe/src/tt_iter.rs
@@ -3,9 +3,8 @@
use smallvec::{smallvec, SmallVec};
use syntax::SyntaxKind;
-use tt::buffer::TokenBuffer;
-use crate::{to_parser_input::to_parser_input, ExpandError, ExpandResult};
+use crate::{to_parser_input::to_parser_input, tt, ExpandError, ExpandResult};
#[derive(Debug, Clone)]
pub(crate) struct TtIter<'a> {
@@ -114,7 +113,7 @@ impl<'a> TtIter<'a> {
('.', '.', Some('.' | '=')) | ('<', '<', Some('=')) | ('>', '>', Some('=')) => {
let _ = self.next().unwrap();
let _ = self.next().unwrap();
- Ok(smallvec![first, second.clone(), third.unwrap().clone()])
+ Ok(smallvec![first, *second, *third.unwrap()])
}
('-' | '!' | '*' | '/' | '&' | '%' | '^' | '+' | '<' | '=' | '>' | '|', '=', _)
| ('-' | '=' | '>', '>', _)
@@ -125,7 +124,7 @@ impl<'a> TtIter<'a> {
| ('<', '<', _)
| ('|', '|', _) => {
let _ = self.next().unwrap();
- Ok(smallvec![first, second.clone()])
+ Ok(smallvec![first, *second])
}
_ => Ok(smallvec![first]),
}
@@ -135,7 +134,7 @@ impl<'a> TtIter<'a> {
&mut self,
entry_point: parser::PrefixEntryPoint,
) -> ExpandResult<Option<tt::TokenTree>> {
- let buffer = TokenBuffer::from_tokens(self.inner.as_slice());
+ let buffer = tt::buffer::TokenBuffer::from_tokens(self.inner.as_slice());
let parser_input = to_parser_input(&buffer);
let tree_traversal = entry_point.parse(&parser_input);
@@ -151,6 +150,11 @@ impl<'a> TtIter<'a> {
cursor = cursor.bump_subtree();
}
}
+ parser::Step::FloatSplit { .. } => {
+ // FIXME: We need to split the tree properly here, but mutating the token trees
+ // in the buffer is somewhat tricky to pull off.
+ cursor = cursor.bump_subtree();
+ }
parser::Step::Enter { .. } | parser::Step::Exit => (),
parser::Step::Error { .. } => error = true,
}
@@ -167,19 +171,18 @@ impl<'a> TtIter<'a> {
if cursor.is_root() {
while curr != cursor {
- if let Some(token) = curr.token_tree() {
- res.push(token);
- }
+ let Some(token) = curr.token_tree() else { break };
+ res.push(token.cloned());
curr = curr.bump();
}
}
+
self.inner = self.inner.as_slice()[res.len()..].iter();
let res = match res.len() {
- 1 => Some(res[0].cloned()),
- 0 => None,
+ 0 | 1 => res.pop(),
_ => Some(tt::TokenTree::Subtree(tt::Subtree {
- delimiter: None,
- token_trees: res.into_iter().map(|it| it.cloned()).collect(),
+ delimiter: tt::Delimiter::unspecified(),
+ token_trees: res,
})),
};
ExpandResult { value: res, err }
diff --git a/src/tools/rust-analyzer/crates/parser/Cargo.toml b/src/tools/rust-analyzer/crates/parser/Cargo.toml
index d1420de89..6e962abd7 100644
--- a/src/tools/rust-analyzer/crates/parser/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/parser/Cargo.toml
@@ -2,18 +2,23 @@
name = "parser"
version = "0.0.0"
description = "TBD"
-license = "MIT OR Apache-2.0"
-edition = "2021"
-rust-version = "1.65"
+
+authors.workspace = true
+edition.workspace = true
+license.workspace = true
+rust-version.workspace = true
[lib]
doctest = false
[dependencies]
drop_bomb = "0.1.5"
-rustc_lexer = { version = "725.0.0", package = "rustc-ap-rustc_lexer" }
-limit = { path = "../limit", version = "0.0.0" }
+rustc_lexer = { version = "727.0.0", package = "rustc-ap-rustc_lexer" }
+
+limit.workspace = true
[dev-dependencies]
expect-test = "1.4.0"
-sourcegen = { path = "../sourcegen" }
+
+stdx.workspace = true
+sourcegen.workspace = true
diff --git a/src/tools/rust-analyzer/crates/parser/src/event.rs b/src/tools/rust-analyzer/crates/parser/src/event.rs
index b0e70e794..577eb0967 100644
--- a/src/tools/rust-analyzer/crates/parser/src/event.rs
+++ b/src/tools/rust-analyzer/crates/parser/src/event.rs
@@ -74,7 +74,13 @@ pub(crate) enum Event {
kind: SyntaxKind,
n_raw_tokens: u8,
},
-
+ /// When we parse `foo.0.0` or `foo. 0. 0` the lexer will hand us a float literal
+ /// instead of an integer literal followed by a dot as the lexer has no contextual knowledge.
+ /// This event instructs whatever consumes the events to split the float literal into
+ /// the corresponding parts.
+ FloatSplitHack {
+ ends_in_dot: bool,
+ },
Error {
msg: String,
},
@@ -125,6 +131,11 @@ pub(super) fn process(mut events: Vec<Event>) -> Output {
Event::Token { kind, n_raw_tokens } => {
res.token(kind, n_raw_tokens);
}
+ Event::FloatSplitHack { ends_in_dot } => {
+ res.float_split_hack(ends_in_dot);
+ let ev = mem::replace(&mut events[i + 1], Event::tombstone());
+ assert!(matches!(ev, Event::Finish), "{ev:?}");
+ }
Event::Error { msg } => res.error(msg),
}
}
diff --git a/src/tools/rust-analyzer/crates/parser/src/grammar.rs b/src/tools/rust-analyzer/crates/parser/src/grammar.rs
index 485b612f0..15ec9e167 100644
--- a/src/tools/rust-analyzer/crates/parser/src/grammar.rs
+++ b/src/tools/rust-analyzer/crates/parser/src/grammar.rs
@@ -200,6 +200,8 @@ impl BlockLike {
}
}
+const VISIBILITY_FIRST: TokenSet = TokenSet::new(&[T![pub], T![crate]]);
+
fn opt_visibility(p: &mut Parser<'_>, in_tuple_field: bool) -> bool {
match p.current() {
T![pub] => {
@@ -340,3 +342,31 @@ fn error_block(p: &mut Parser<'_>, message: &str) {
p.eat(T!['}']);
m.complete(p, ERROR);
}
+
+/// The `parser` passed this is required to at least consume one token if it returns `true`.
+/// If the `parser` returns false, parsing will stop.
+fn delimited(
+ p: &mut Parser<'_>,
+ bra: SyntaxKind,
+ ket: SyntaxKind,
+ delim: SyntaxKind,
+ first_set: TokenSet,
+ mut parser: impl FnMut(&mut Parser<'_>) -> bool,
+) {
+ p.bump(bra);
+ while !p.at(ket) && !p.at(EOF) {
+ if !parser(p) {
+ break;
+ }
+ if !p.at(delim) {
+ if p.at_ts(first_set) {
+ p.error(format!("expected {:?}", delim));
+ } else {
+ break;
+ }
+ } else {
+ p.bump(delim);
+ }
+ }
+ p.expect(ket);
+}
diff --git a/src/tools/rust-analyzer/crates/parser/src/grammar/attributes.rs b/src/tools/rust-analyzer/crates/parser/src/grammar/attributes.rs
index 0cf6a16f8..4ecaa6e6a 100644
--- a/src/tools/rust-analyzer/crates/parser/src/grammar/attributes.rs
+++ b/src/tools/rust-analyzer/crates/parser/src/grammar/attributes.rs
@@ -1,5 +1,7 @@
use super::*;
+pub(super) const ATTRIBUTE_FIRST: TokenSet = TokenSet::new(&[T![#]]);
+
pub(super) fn inner_attrs(p: &mut Parser<'_>) {
while p.at(T![#]) && p.nth(1) == T![!] {
attr(p, true);
diff --git a/src/tools/rust-analyzer/crates/parser/src/grammar/expressions.rs b/src/tools/rust-analyzer/crates/parser/src/grammar/expressions.rs
index 8932330b8..4b080102a 100644
--- a/src/tools/rust-analyzer/crates/parser/src/grammar/expressions.rs
+++ b/src/tools/rust-analyzer/crates/parser/src/grammar/expressions.rs
@@ -1,5 +1,7 @@
mod atom;
+use crate::grammar::attributes::ATTRIBUTE_FIRST;
+
use super::*;
pub(crate) use self::atom::{block_expr, match_arm_list};
@@ -68,6 +70,12 @@ pub(super) fn stmt(p: &mut Parser<'_>, semicolon: Semicolon) {
Err(m) => m,
};
+ if !p.at_ts(EXPR_FIRST) {
+ p.err_and_bump("expected expression, item or let statement");
+ m.abandon(p);
+ return;
+ }
+
if let Some((cm, blocklike)) = expr_stmt(p, Some(m)) {
if !(p.at(T!['}']) || (semicolon != Semicolon::Required && p.at(EOF))) {
// test no_semi_after_block
@@ -227,6 +235,12 @@ fn expr_bp(
attributes::outer_attrs(p);
m
});
+
+ if !p.at_ts(EXPR_FIRST) {
+ p.err_recover("expected expression", atom::EXPR_RECOVERY_SET);
+ m.abandon(p);
+ return None;
+ }
let mut lhs = match lhs(p, r) {
Some((lhs, blocklike)) => {
let lhs = lhs.extend_to(p, m);
@@ -379,7 +393,7 @@ fn postfix_expr(
// }
T!['('] if allow_calls => call_expr(p, lhs),
T!['['] if allow_calls => index_expr(p, lhs),
- T![.] => match postfix_dot_expr(p, lhs) {
+ T![.] => match postfix_dot_expr::<false>(p, lhs) {
Ok(it) => it,
Err(it) => {
lhs = it;
@@ -393,35 +407,44 @@ fn postfix_expr(
block_like = BlockLike::NotBlock;
}
return (lhs, block_like);
+}
- fn postfix_dot_expr(
- p: &mut Parser<'_>,
- lhs: CompletedMarker,
- ) -> Result<CompletedMarker, CompletedMarker> {
+fn postfix_dot_expr<const FLOAT_RECOVERY: bool>(
+ p: &mut Parser<'_>,
+ lhs: CompletedMarker,
+) -> Result<CompletedMarker, CompletedMarker> {
+ if !FLOAT_RECOVERY {
assert!(p.at(T![.]));
- if p.nth(1) == IDENT && (p.nth(2) == T!['('] || p.nth_at(2, T![::])) {
- return Ok(method_call_expr(p, lhs));
- }
+ }
+ let nth1 = if FLOAT_RECOVERY { 0 } else { 1 };
+ let nth2 = if FLOAT_RECOVERY { 1 } else { 2 };
- // test await_expr
- // fn foo() {
- // x.await;
- // x.0.await;
- // x.0().await?.hello();
- // }
- if p.nth(1) == T![await] {
- let m = lhs.precede(p);
- p.bump(T![.]);
- p.bump(T![await]);
- return Ok(m.complete(p, AWAIT_EXPR));
- }
+ if p.nth(nth1) == IDENT && (p.nth(nth2) == T!['('] || p.nth_at(nth2, T![::])) {
+ return Ok(method_call_expr::<FLOAT_RECOVERY>(p, lhs));
+ }
- if p.at(T![..=]) || p.at(T![..]) {
- return Err(lhs);
+ // test await_expr
+ // fn foo() {
+ // x.await;
+ // x.0.await;
+ // x.0().await?.hello();
+ // x.0.0.await;
+ // x.0. await;
+ // }
+ if p.nth(nth1) == T![await] {
+ let m = lhs.precede(p);
+ if !FLOAT_RECOVERY {
+ p.bump(T![.]);
}
+ p.bump(T![await]);
+ return Ok(m.complete(p, AWAIT_EXPR));
+ }
- Ok(field_expr(p, lhs))
+ if p.at(T![..=]) || p.at(T![..]) {
+ return Err(lhs);
}
+
+ field_expr::<FLOAT_RECOVERY>(p, lhs)
}
// test call_expr
@@ -455,11 +478,22 @@ fn index_expr(p: &mut Parser<'_>, lhs: CompletedMarker) -> CompletedMarker {
// fn foo() {
// x.foo();
// y.bar::<T>(1, 2,);
+// x.0.0.call();
+// x.0. call();
// }
-fn method_call_expr(p: &mut Parser<'_>, lhs: CompletedMarker) -> CompletedMarker {
- assert!(p.at(T![.]) && p.nth(1) == IDENT && (p.nth(2) == T!['('] || p.nth_at(2, T![::])));
+fn method_call_expr<const FLOAT_RECOVERY: bool>(
+ p: &mut Parser<'_>,
+ lhs: CompletedMarker,
+) -> CompletedMarker {
+ if FLOAT_RECOVERY {
+ assert!(p.nth(0) == IDENT && (p.nth(1) == T!['('] || p.nth_at(1, T![::])));
+ } else {
+ assert!(p.at(T![.]) && p.nth(1) == IDENT && (p.nth(2) == T!['('] || p.nth_at(2, T![::])));
+ }
let m = lhs.precede(p);
- p.bump_any();
+ if !FLOAT_RECOVERY {
+ p.bump(T![.]);
+ }
name_ref(p);
generic_args::opt_generic_arg_list(p, true);
if p.at(T!['(']) {
@@ -472,21 +506,35 @@ fn method_call_expr(p: &mut Parser<'_>, lhs: CompletedMarker) -> CompletedMarker
// fn foo() {
// x.foo;
// x.0.bar;
+// x.0.1;
+// x.0. bar;
// x.0();
// }
-fn field_expr(p: &mut Parser<'_>, lhs: CompletedMarker) -> CompletedMarker {
- assert!(p.at(T![.]));
+fn field_expr<const FLOAT_RECOVERY: bool>(
+ p: &mut Parser<'_>,
+ lhs: CompletedMarker,
+) -> Result<CompletedMarker, CompletedMarker> {
+ if !FLOAT_RECOVERY {
+ assert!(p.at(T![.]));
+ }
let m = lhs.precede(p);
- p.bump(T![.]);
+ if !FLOAT_RECOVERY {
+ p.bump(T![.]);
+ }
if p.at(IDENT) || p.at(INT_NUMBER) {
name_ref_or_index(p);
} else if p.at(FLOAT_NUMBER) {
- // FIXME: How to recover and instead parse INT + T![.]?
- p.bump_any();
+ return match p.split_float(m) {
+ (true, m) => {
+ let lhs = m.complete(p, FIELD_EXPR);
+ postfix_dot_expr::<true>(p, lhs)
+ }
+ (false, m) => Ok(m.complete(p, FIELD_EXPR)),
+ };
} else {
p.error("expected field name or number");
}
- m.complete(p, FIELD_EXPR)
+ Ok(m.complete(p, FIELD_EXPR))
}
// test try_expr
@@ -517,23 +565,20 @@ fn cast_expr(p: &mut Parser<'_>, lhs: CompletedMarker) -> CompletedMarker {
m.complete(p, CAST_EXPR)
}
+// test_err arg_list_recovery
+// fn main() {
+// foo(bar::);
+// foo(bar:);
+// foo(bar+);
+// }
fn arg_list(p: &mut Parser<'_>) {
assert!(p.at(T!['(']));
let m = p.start();
- p.bump(T!['(']);
- while !p.at(T![')']) && !p.at(EOF) {
- // test arg_with_attr
- // fn main() {
- // foo(#[attr] 92)
- // }
- if !expr(p) {
- break;
- }
- if !p.at(T![')']) && !p.expect(T![,]) {
- break;
- }
- }
- p.eat(T![')']);
+ // test arg_with_attr
+ // fn main() {
+ // foo(#[attr] 92)
+ // }
+ delimited(p, T!['('], T![')'], T![,], EXPR_FIRST.union(ATTRIBUTE_FIRST), expr);
m.complete(p, ARG_LIST);
}
diff --git a/src/tools/rust-analyzer/crates/parser/src/grammar/expressions/atom.rs b/src/tools/rust-analyzer/crates/parser/src/grammar/expressions/atom.rs
index efa399735..efc260383 100644
--- a/src/tools/rust-analyzer/crates/parser/src/grammar/expressions/atom.rs
+++ b/src/tools/rust-analyzer/crates/parser/src/grammar/expressions/atom.rs
@@ -40,26 +40,28 @@ pub(super) const ATOM_EXPR_FIRST: TokenSet =
T!['{'],
T!['['],
T![|],
- T![move],
+ T![async],
T![box],
+ T![break],
+ T![const],
+ T![continue],
+ T![do],
+ T![for],
T![if],
- T![while],
+ T![let],
+ T![loop],
T![match],
- T![unsafe],
+ T![move],
T![return],
- T![yield],
- T![do],
- T![break],
- T![continue],
- T![async],
+ T![static],
T![try],
- T![const],
- T![loop],
- T![for],
+ T![unsafe],
+ T![while],
+ T![yield],
LIFETIME_IDENT,
]));
-const EXPR_RECOVERY_SET: TokenSet = TokenSet::new(&[T![let]]);
+pub(super) const EXPR_RECOVERY_SET: TokenSet = TokenSet::new(&[T![')'], T![']']]);
pub(super) fn atom_expr(
p: &mut Parser<'_>,
@@ -116,7 +118,7 @@ pub(super) fn atom_expr(
// fn main() {
// 'loop: impl
// }
- p.error("expected a loop");
+ p.error("expected a loop or block");
m.complete(p, ERROR);
return None;
}
@@ -152,12 +154,12 @@ pub(super) fn atom_expr(
m.complete(p, BLOCK_EXPR)
}
- T![static] | T![async] | T![move] | T![|] => closure_expr(p),
+ T![const] | T![static] | T![async] | T![move] | T![|] => closure_expr(p),
T![for] if la == T![<] => closure_expr(p),
T![for] => for_expr(p, None),
_ => {
- p.err_recover("expected expression", EXPR_RECOVERY_SET);
+ p.err_and_bump("expected expression");
return None;
}
};
@@ -255,7 +257,7 @@ fn array_expr(p: &mut Parser<'_>) -> CompletedMarker {
// }
fn closure_expr(p: &mut Parser<'_>) -> CompletedMarker {
assert!(match p.current() {
- T![static] | T![async] | T![move] | T![|] => true,
+ T![const] | T![static] | T![async] | T![move] | T![|] => true,
T![for] => p.nth(1) == T![<],
_ => false,
});
@@ -265,7 +267,9 @@ fn closure_expr(p: &mut Parser<'_>) -> CompletedMarker {
if p.at(T![for]) {
types::for_binder(p);
}
-
+ // test const_closure
+ // fn main() { let cl = const || _ = 0; }
+ p.eat(T![const]);
p.eat(T![static]);
p.eat(T![async]);
p.eat(T![move]);
diff --git a/src/tools/rust-analyzer/crates/parser/src/grammar/generic_args.rs b/src/tools/rust-analyzer/crates/parser/src/grammar/generic_args.rs
index c438943a0..919d9b91e 100644
--- a/src/tools/rust-analyzer/crates/parser/src/grammar/generic_args.rs
+++ b/src/tools/rust-analyzer/crates/parser/src/grammar/generic_args.rs
@@ -5,27 +5,35 @@ pub(super) fn opt_generic_arg_list(p: &mut Parser<'_>, colon_colon_required: boo
if p.at(T![::]) && p.nth(2) == T![<] {
m = p.start();
p.bump(T![::]);
- p.bump(T![<]);
} else if !colon_colon_required && p.at(T![<]) && p.nth(1) != T![=] {
m = p.start();
- p.bump(T![<]);
} else {
return;
}
- while !p.at(EOF) && !p.at(T![>]) {
- generic_arg(p);
- if !p.at(T![>]) && !p.expect(T![,]) {
- break;
- }
- }
- p.expect(T![>]);
+ delimited(p, T![<], T![>], T![,], GENERIC_ARG_FIRST, generic_arg);
m.complete(p, GENERIC_ARG_LIST);
}
+const GENERIC_ARG_FIRST: TokenSet = TokenSet::new(&[
+ LIFETIME_IDENT,
+ IDENT,
+ T!['{'],
+ T![true],
+ T![false],
+ T![-],
+ INT_NUMBER,
+ FLOAT_NUMBER,
+ CHAR,
+ BYTE,
+ STRING,
+ BYTE_STRING,
+])
+.union(types::TYPE_FIRST);
+
// test generic_arg
// type T = S<i32>;
-fn generic_arg(p: &mut Parser<'_>) {
+fn generic_arg(p: &mut Parser<'_>) -> bool {
match p.current() {
LIFETIME_IDENT => lifetime_arg(p),
T!['{'] | T![true] | T![false] | T![-] => const_arg(p),
@@ -68,8 +76,10 @@ fn generic_arg(p: &mut Parser<'_>) {
}
}
}
- _ => type_arg(p),
+ _ if p.at_ts(types::TYPE_FIRST) => type_arg(p),
+ _ => return false,
}
+ true
}
// test lifetime_arg
diff --git a/src/tools/rust-analyzer/crates/parser/src/grammar/generic_params.rs b/src/tools/rust-analyzer/crates/parser/src/grammar/generic_params.rs
index 6db28ef13..7fcf938ba 100644
--- a/src/tools/rust-analyzer/crates/parser/src/grammar/generic_params.rs
+++ b/src/tools/rust-analyzer/crates/parser/src/grammar/generic_params.rs
@@ -1,3 +1,5 @@
+use crate::grammar::attributes::ATTRIBUTE_FIRST;
+
use super::*;
pub(super) fn opt_generic_param_list(p: &mut Parser<'_>) {
@@ -11,32 +13,31 @@ pub(super) fn opt_generic_param_list(p: &mut Parser<'_>) {
fn generic_param_list(p: &mut Parser<'_>) {
assert!(p.at(T![<]));
let m = p.start();
- p.bump(T![<]);
+ delimited(p, T![<], T![>], T![,], GENERIC_PARAM_FIRST.union(ATTRIBUTE_FIRST), |p| {
+ // test generic_param_attribute
+ // fn foo<#[lt_attr] 'a, #[t_attr] T>() {}
+ let m = p.start();
+ attributes::outer_attrs(p);
+ generic_param(p, m)
+ });
- while !p.at(EOF) && !p.at(T![>]) {
- generic_param(p);
- if !p.at(T![>]) && !p.expect(T![,]) {
- break;
- }
- }
- p.expect(T![>]);
m.complete(p, GENERIC_PARAM_LIST);
}
-fn generic_param(p: &mut Parser<'_>) {
- let m = p.start();
- // test generic_param_attribute
- // fn foo<#[lt_attr] 'a, #[t_attr] T>() {}
- attributes::outer_attrs(p);
+const GENERIC_PARAM_FIRST: TokenSet = TokenSet::new(&[IDENT, LIFETIME_IDENT, T![const]]);
+
+fn generic_param(p: &mut Parser<'_>, m: Marker) -> bool {
match p.current() {
LIFETIME_IDENT => lifetime_param(p, m),
IDENT => type_param(p, m),
T![const] => const_param(p, m),
_ => {
m.abandon(p);
- p.err_and_bump("expected type parameter");
+ p.err_and_bump("expected generic parameter");
+ return false;
}
}
+ true
}
// test lifetime_param
diff --git a/src/tools/rust-analyzer/crates/parser/src/grammar/items/adt.rs b/src/tools/rust-analyzer/crates/parser/src/grammar/items/adt.rs
index e7d30516b..17f41b8e1 100644
--- a/src/tools/rust-analyzer/crates/parser/src/grammar/items/adt.rs
+++ b/src/tools/rust-analyzer/crates/parser/src/grammar/items/adt.rs
@@ -1,3 +1,5 @@
+use crate::grammar::attributes::ATTRIBUTE_FIRST;
+
use super::*;
// test struct_item
@@ -141,28 +143,31 @@ pub(crate) fn record_field_list(p: &mut Parser<'_>) {
}
}
+const TUPLE_FIELD_FIRST: TokenSet =
+ types::TYPE_FIRST.union(ATTRIBUTE_FIRST).union(VISIBILITY_FIRST);
+
fn tuple_field_list(p: &mut Parser<'_>) {
assert!(p.at(T!['(']));
let m = p.start();
- p.bump(T!['(']);
- while !p.at(T![')']) && !p.at(EOF) {
+ delimited(p, T!['('], T![')'], T![,], TUPLE_FIELD_FIRST, |p| {
let m = p.start();
// test tuple_field_attrs
// struct S (#[attr] f32);
attributes::outer_attrs(p);
- opt_visibility(p, true);
+ let has_vis = opt_visibility(p, true);
if !p.at_ts(types::TYPE_FIRST) {
p.error("expected a type");
- m.complete(p, ERROR);
- break;
+ if has_vis {
+ m.complete(p, ERROR);
+ } else {
+ m.abandon(p);
+ }
+ return false;
}
types::type_(p);
m.complete(p, TUPLE_FIELD);
+ true
+ });
- if !p.at(T![')']) {
- p.expect(T![,]);
- }
- }
- p.expect(T![')']);
m.complete(p, TUPLE_FIELD_LIST);
}
diff --git a/src/tools/rust-analyzer/crates/parser/src/grammar/params.rs b/src/tools/rust-analyzer/crates/parser/src/grammar/params.rs
index 20e8e95f0..74eae9151 100644
--- a/src/tools/rust-analyzer/crates/parser/src/grammar/params.rs
+++ b/src/tools/rust-analyzer/crates/parser/src/grammar/params.rs
@@ -1,3 +1,5 @@
+use crate::grammar::attributes::ATTRIBUTE_FIRST;
+
use super::*;
// test param_list
@@ -66,14 +68,20 @@ fn list_(p: &mut Parser<'_>, flavor: Flavor) {
}
};
- if !p.at_ts(PARAM_FIRST) {
+ if !p.at_ts(PARAM_FIRST.union(ATTRIBUTE_FIRST)) {
p.error("expected value parameter");
m.abandon(p);
break;
}
param(p, m, flavor);
- if !p.at(ket) {
- p.expect(T![,]);
+ if !p.at(T![,]) {
+ if p.at_ts(PARAM_FIRST.union(ATTRIBUTE_FIRST)) {
+ p.error("expected `,`");
+ } else {
+ break;
+ }
+ } else {
+ p.bump(T![,]);
}
}
diff --git a/src/tools/rust-analyzer/crates/parser/src/grammar/paths.rs b/src/tools/rust-analyzer/crates/parser/src/grammar/paths.rs
index af3b6f63c..1064ae997 100644
--- a/src/tools/rust-analyzer/crates/parser/src/grammar/paths.rs
+++ b/src/tools/rust-analyzer/crates/parser/src/grammar/paths.rs
@@ -67,6 +67,10 @@ fn path_for_qualifier(
}
}
+const EXPR_PATH_SEGMENT_RECOVERY_SET: TokenSet =
+ items::ITEM_RECOVERY_SET.union(TokenSet::new(&[T![')'], T![,], T![let]]));
+const TYPE_PATH_SEGMENT_RECOVERY_SET: TokenSet = types::TYPE_RECOVERY_SET;
+
fn path_segment(p: &mut Parser<'_>, mode: Mode, first: bool) {
let m = p.start();
// test qual_paths
@@ -102,7 +106,12 @@ fn path_segment(p: &mut Parser<'_>, mode: Mode, first: bool) {
m.complete(p, NAME_REF);
}
_ => {
- p.err_recover("expected identifier", items::ITEM_RECOVERY_SET);
+ let recover_set = match mode {
+ Mode::Use => items::ITEM_RECOVERY_SET,
+ Mode::Type => TYPE_PATH_SEGMENT_RECOVERY_SET,
+ Mode::Expr => EXPR_PATH_SEGMENT_RECOVERY_SET,
+ };
+ p.err_recover("expected identifier", recover_set);
if empty {
// test_err empty_segment
// use crate::;
diff --git a/src/tools/rust-analyzer/crates/parser/src/grammar/types.rs b/src/tools/rust-analyzer/crates/parser/src/grammar/types.rs
index 5c6e18fee..7d0b156c5 100644
--- a/src/tools/rust-analyzer/crates/parser/src/grammar/types.rs
+++ b/src/tools/rust-analyzer/crates/parser/src/grammar/types.rs
@@ -17,8 +17,9 @@ pub(super) const TYPE_FIRST: TokenSet = paths::PATH_FIRST.union(TokenSet::new(&[
T![Self],
]));
-const TYPE_RECOVERY_SET: TokenSet = TokenSet::new(&[
+pub(super) const TYPE_RECOVERY_SET: TokenSet = TokenSet::new(&[
T![')'],
+ T![>],
T![,],
// test_err struct_field_recover
// struct S { f pub g: () }
diff --git a/src/tools/rust-analyzer/crates/parser/src/lexed_str.rs b/src/tools/rust-analyzer/crates/parser/src/lexed_str.rs
index b48921f19..100deff46 100644
--- a/src/tools/rust-analyzer/crates/parser/src/lexed_str.rs
+++ b/src/tools/rust-analyzer/crates/parser/src/lexed_str.rs
@@ -82,6 +82,7 @@ impl<'a> LexedStr<'a> {
pub fn text(&self, i: usize) -> &str {
self.range_text(i..i + 1)
}
+
pub fn range_text(&self, r: ops::Range<usize>) -> &str {
assert!(r.start < r.end && r.end <= self.len());
let lo = self.start[r.start] as usize;
@@ -216,6 +217,10 @@ impl<'a> Converter<'a> {
rustc_lexer::TokenKind::Caret => T![^],
rustc_lexer::TokenKind::Percent => T![%],
rustc_lexer::TokenKind::Unknown => ERROR,
+ rustc_lexer::TokenKind::UnknownPrefix => {
+ err = "unknown literal prefix";
+ IDENT
+ }
}
};
diff --git a/src/tools/rust-analyzer/crates/parser/src/lib.rs b/src/tools/rust-analyzer/crates/parser/src/lib.rs
index 87be47927..8c5aed023 100644
--- a/src/tools/rust-analyzer/crates/parser/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/parser/src/lib.rs
@@ -102,10 +102,14 @@ impl TopEntryPoint {
match step {
Step::Enter { .. } => depth += 1,
Step::Exit => depth -= 1,
+ Step::FloatSplit { ends_in_dot: has_pseudo_dot } => {
+ depth -= 1 + !has_pseudo_dot as usize
+ }
Step::Token { .. } | Step::Error { .. } => (),
}
}
assert!(!first, "no tree at all");
+ assert_eq!(depth, 0, "unbalanced tree");
}
res
diff --git a/src/tools/rust-analyzer/crates/parser/src/output.rs b/src/tools/rust-analyzer/crates/parser/src/output.rs
index 6ca841cfe..41d4c68b2 100644
--- a/src/tools/rust-analyzer/crates/parser/src/output.rs
+++ b/src/tools/rust-analyzer/crates/parser/src/output.rs
@@ -25,53 +25,88 @@ pub struct Output {
#[derive(Debug)]
pub enum Step<'a> {
Token { kind: SyntaxKind, n_input_tokens: u8 },
+ FloatSplit { ends_in_dot: bool },
Enter { kind: SyntaxKind },
Exit,
Error { msg: &'a str },
}
impl Output {
+ const EVENT_MASK: u32 = 0b1;
+ const TAG_MASK: u32 = 0x0000_00F0;
+ const N_INPUT_TOKEN_MASK: u32 = 0x0000_FF00;
+ const KIND_MASK: u32 = 0xFFFF_0000;
+
+ const ERROR_SHIFT: u32 = Self::EVENT_MASK.trailing_ones();
+ const TAG_SHIFT: u32 = Self::TAG_MASK.trailing_zeros();
+ const N_INPUT_TOKEN_SHIFT: u32 = Self::N_INPUT_TOKEN_MASK.trailing_zeros();
+ const KIND_SHIFT: u32 = Self::KIND_MASK.trailing_zeros();
+
+ const TOKEN_EVENT: u8 = 0;
+ const ENTER_EVENT: u8 = 1;
+ const EXIT_EVENT: u8 = 2;
+ const SPLIT_EVENT: u8 = 3;
+
pub fn iter(&self) -> impl Iterator<Item = Step<'_>> {
self.event.iter().map(|&event| {
- if event & 0b1 == 0 {
- return Step::Error { msg: self.error[(event as usize) >> 1].as_str() };
+ if event & Self::EVENT_MASK == 0 {
+ return Step::Error {
+ msg: self.error[(event as usize) >> Self::ERROR_SHIFT].as_str(),
+ };
}
- let tag = ((event & 0x0000_00F0) >> 4) as u8;
+ let tag = ((event & Self::TAG_MASK) >> Self::TAG_SHIFT) as u8;
match tag {
- 0 => {
- let kind: SyntaxKind = (((event & 0xFFFF_0000) >> 16) as u16).into();
- let n_input_tokens = ((event & 0x0000_FF00) >> 8) as u8;
+ Self::TOKEN_EVENT => {
+ let kind: SyntaxKind =
+ (((event & Self::KIND_MASK) >> Self::KIND_SHIFT) as u16).into();
+ let n_input_tokens =
+ ((event & Self::N_INPUT_TOKEN_MASK) >> Self::N_INPUT_TOKEN_SHIFT) as u8;
Step::Token { kind, n_input_tokens }
}
- 1 => {
- let kind: SyntaxKind = (((event & 0xFFFF_0000) >> 16) as u16).into();
+ Self::ENTER_EVENT => {
+ let kind: SyntaxKind =
+ (((event & Self::KIND_MASK) >> Self::KIND_SHIFT) as u16).into();
Step::Enter { kind }
}
- 2 => Step::Exit,
+ Self::EXIT_EVENT => Step::Exit,
+ Self::SPLIT_EVENT => {
+ Step::FloatSplit { ends_in_dot: event & Self::N_INPUT_TOKEN_MASK != 0 }
+ }
_ => unreachable!(),
}
})
}
pub(crate) fn token(&mut self, kind: SyntaxKind, n_tokens: u8) {
- let e = ((kind as u16 as u32) << 16) | ((n_tokens as u32) << 8) | 1;
+ let e = ((kind as u16 as u32) << Self::KIND_SHIFT)
+ | ((n_tokens as u32) << Self::N_INPUT_TOKEN_SHIFT)
+ | Self::EVENT_MASK;
self.event.push(e)
}
+ pub(crate) fn float_split_hack(&mut self, ends_in_dot: bool) {
+ let e = (Self::SPLIT_EVENT as u32) << Self::TAG_SHIFT
+ | ((ends_in_dot as u32) << Self::N_INPUT_TOKEN_SHIFT)
+ | Self::EVENT_MASK;
+ self.event.push(e);
+ }
+
pub(crate) fn enter_node(&mut self, kind: SyntaxKind) {
- let e = ((kind as u16 as u32) << 16) | (1 << 4) | 1;
+ let e = ((kind as u16 as u32) << Self::KIND_SHIFT)
+ | ((Self::ENTER_EVENT as u32) << Self::TAG_SHIFT)
+ | Self::EVENT_MASK;
self.event.push(e)
}
pub(crate) fn leave_node(&mut self) {
- let e = 2 << 4 | 1;
+ let e = (Self::EXIT_EVENT as u32) << Self::TAG_SHIFT | Self::EVENT_MASK;
self.event.push(e)
}
pub(crate) fn error(&mut self, error: String) {
let idx = self.error.len();
self.error.push(error);
- let e = (idx as u32) << 1;
+ let e = (idx as u32) << Self::ERROR_SHIFT;
self.event.push(e);
}
}
diff --git a/src/tools/rust-analyzer/crates/parser/src/parser.rs b/src/tools/rust-analyzer/crates/parser/src/parser.rs
index 48aecb35b..280416ae7 100644
--- a/src/tools/rust-analyzer/crates/parser/src/parser.rs
+++ b/src/tools/rust-analyzer/crates/parser/src/parser.rs
@@ -181,6 +181,35 @@ impl<'t> Parser<'t> {
self.do_bump(kind, 1);
}
+ /// Advances the parser by one token
+ pub(crate) fn split_float(&mut self, mut marker: Marker) -> (bool, Marker) {
+ assert!(self.at(SyntaxKind::FLOAT_NUMBER));
+ // we have parse `<something>.`
+ // `<something>`.0.1
+ // here we need to insert an extra event
+ //
+ // `<something>`. 0. 1;
+ // here we need to change the follow up parse, the return value will cause us to emulate a dot
+ // the actual splitting happens later
+ let ends_in_dot = !self.inp.is_joint(self.pos);
+ if !ends_in_dot {
+ let new_marker = self.start();
+ let idx = marker.pos as usize;
+ match &mut self.events[idx] {
+ Event::Start { forward_parent, kind } => {
+ *kind = SyntaxKind::FIELD_EXPR;
+ *forward_parent = Some(new_marker.pos - marker.pos);
+ }
+ _ => unreachable!(),
+ }
+ marker.bomb.defuse();
+ marker = new_marker;
+ };
+ self.pos += 1 as usize;
+ self.push_event(Event::FloatSplitHack { ends_in_dot });
+ (ends_in_dot, marker)
+ }
+
/// Advances the parser by one token, remapping its kind.
/// This is useful to create contextual keywords from
/// identifiers. For example, the lexer creates a `union`
diff --git a/src/tools/rust-analyzer/crates/parser/src/shortcuts.rs b/src/tools/rust-analyzer/crates/parser/src/shortcuts.rs
index 2be4050d1..47e4adcbb 100644
--- a/src/tools/rust-analyzer/crates/parser/src/shortcuts.rs
+++ b/src/tools/rust-analyzer/crates/parser/src/shortcuts.rs
@@ -43,7 +43,16 @@ impl<'a> LexedStr<'a> {
res.was_joint();
}
res.push(kind);
+ // Tag the token as joint if it is float with a fractional part
+ // we use this jointness to inform the parser about what token split
+ // event to emit when we encounter a float literal in a field access
+ if kind == SyntaxKind::FLOAT_NUMBER {
+ if !self.text(i).ends_with('.') {
+ res.was_joint();
+ }
+ }
}
+
was_joint = true;
}
}
@@ -63,6 +72,9 @@ impl<'a> LexedStr<'a> {
Step::Token { kind, n_input_tokens: n_raw_tokens } => {
builder.token(kind, n_raw_tokens)
}
+ Step::FloatSplit { ends_in_dot: has_pseudo_dot } => {
+ builder.float_split(has_pseudo_dot)
+ }
Step::Enter { kind } => builder.enter(kind),
Step::Exit => builder.exit(),
Step::Error { msg } => {
@@ -109,6 +121,16 @@ impl Builder<'_, '_> {
self.do_token(kind, n_tokens as usize);
}
+ fn float_split(&mut self, has_pseudo_dot: bool) {
+ match mem::replace(&mut self.state, State::Normal) {
+ State::PendingEnter => unreachable!(),
+ State::PendingExit => (self.sink)(StrStep::Exit),
+ State::Normal => (),
+ }
+ self.eat_trivias();
+ self.do_float_split(has_pseudo_dot);
+ }
+
fn enter(&mut self, kind: SyntaxKind) {
match mem::replace(&mut self.state, State::Normal) {
State::PendingEnter => {
@@ -164,6 +186,37 @@ impl Builder<'_, '_> {
self.pos += n_tokens;
(self.sink)(StrStep::Token { kind, text });
}
+
+ fn do_float_split(&mut self, has_pseudo_dot: bool) {
+ let text = &self.lexed.range_text(self.pos..self.pos + 1);
+ self.pos += 1;
+ match text.split_once('.') {
+ Some((left, right)) => {
+ assert!(!left.is_empty());
+ (self.sink)(StrStep::Enter { kind: SyntaxKind::NAME_REF });
+ (self.sink)(StrStep::Token { kind: SyntaxKind::INT_NUMBER, text: left });
+ (self.sink)(StrStep::Exit);
+
+ // here we move the exit up, the original exit has been deleted in process
+ (self.sink)(StrStep::Exit);
+
+ (self.sink)(StrStep::Token { kind: SyntaxKind::DOT, text: "." });
+
+ if has_pseudo_dot {
+ assert!(right.is_empty(), "{left}.{right}");
+ self.state = State::Normal;
+ } else {
+ (self.sink)(StrStep::Enter { kind: SyntaxKind::NAME_REF });
+ (self.sink)(StrStep::Token { kind: SyntaxKind::INT_NUMBER, text: right });
+ (self.sink)(StrStep::Exit);
+
+ // the parser creates an unbalanced start node, we are required to close it here
+ self.state = State::PendingExit;
+ }
+ }
+ None => unreachable!(),
+ }
+ }
}
fn n_attached_trivias<'a>(
diff --git a/src/tools/rust-analyzer/crates/parser/src/tests.rs b/src/tools/rust-analyzer/crates/parser/src/tests.rs
index c1b4e9a7d..2fec765bd 100644
--- a/src/tools/rust-analyzer/crates/parser/src/tests.rs
+++ b/src/tools/rust-analyzer/crates/parser/src/tests.rs
@@ -15,6 +15,7 @@ use crate::{LexedStr, TopEntryPoint};
#[test]
fn lex_ok() {
for case in TestCase::list("lexer/ok") {
+ let _guard = stdx::panic_context::enter(format!("{:?}", case.rs));
let actual = lex(&case.text);
expect_file![case.rast].assert_eq(&actual)
}
@@ -23,6 +24,7 @@ fn lex_ok() {
#[test]
fn lex_err() {
for case in TestCase::list("lexer/err") {
+ let _guard = stdx::panic_context::enter(format!("{:?}", case.rs));
let actual = lex(&case.text);
expect_file![case.rast].assert_eq(&actual)
}
@@ -46,6 +48,7 @@ fn lex(text: &str) -> String {
#[test]
fn parse_ok() {
for case in TestCase::list("parser/ok") {
+ let _guard = stdx::panic_context::enter(format!("{:?}", case.rs));
let (actual, errors) = parse(TopEntryPoint::SourceFile, &case.text);
assert!(!errors, "errors in an OK file {}:\n{actual}", case.rs.display());
expect_file![case.rast].assert_eq(&actual);
@@ -55,6 +58,7 @@ fn parse_ok() {
#[test]
fn parse_inline_ok() {
for case in TestCase::list("parser/inline/ok") {
+ let _guard = stdx::panic_context::enter(format!("{:?}", case.rs));
let (actual, errors) = parse(TopEntryPoint::SourceFile, &case.text);
assert!(!errors, "errors in an OK file {}:\n{actual}", case.rs.display());
expect_file![case.rast].assert_eq(&actual);
@@ -64,6 +68,7 @@ fn parse_inline_ok() {
#[test]
fn parse_err() {
for case in TestCase::list("parser/err") {
+ let _guard = stdx::panic_context::enter(format!("{:?}", case.rs));
let (actual, errors) = parse(TopEntryPoint::SourceFile, &case.text);
assert!(errors, "no errors in an ERR file {}:\n{actual}", case.rs.display());
expect_file![case.rast].assert_eq(&actual)
@@ -73,6 +78,7 @@ fn parse_err() {
#[test]
fn parse_inline_err() {
for case in TestCase::list("parser/inline/err") {
+ let _guard = stdx::panic_context::enter(format!("{:?}", case.rs));
let (actual, errors) = parse(TopEntryPoint::SourceFile, &case.text);
assert!(errors, "no errors in an ERR file {}:\n{actual}", case.rs.display());
expect_file![case.rast].assert_eq(&actual)
diff --git a/src/tools/rust-analyzer/crates/parser/src/tests/prefix_entries.rs b/src/tools/rust-analyzer/crates/parser/src/tests/prefix_entries.rs
index e626b4f27..40f92e588 100644
--- a/src/tools/rust-analyzer/crates/parser/src/tests/prefix_entries.rs
+++ b/src/tools/rust-analyzer/crates/parser/src/tests/prefix_entries.rs
@@ -51,6 +51,9 @@ fn expr() {
check(PrefixEntryPoint::Expr, "-1", "-1");
check(PrefixEntryPoint::Expr, "fn foo() {}", "fn");
check(PrefixEntryPoint::Expr, "#[attr] ()", "#[attr] ()");
+ check(PrefixEntryPoint::Expr, "foo.0", "foo.0");
+ check(PrefixEntryPoint::Expr, "foo.0.1", "foo.0.1");
+ check(PrefixEntryPoint::Expr, "foo.0. foo", "foo.0. foo");
}
#[test]
@@ -88,6 +91,7 @@ fn check(entry: PrefixEntryPoint, input: &str, prefix: &str) {
for step in entry.parse(&input).iter() {
match step {
Step::Token { n_input_tokens, .. } => n_tokens += n_input_tokens as usize,
+ Step::FloatSplit { .. } => n_tokens += 1,
Step::Enter { .. } | Step::Exit | Step::Error { .. } => (),
}
}
diff --git a/src/tools/rust-analyzer/crates/parser/src/tests/top_entries.rs b/src/tools/rust-analyzer/crates/parser/src/tests/top_entries.rs
index eb640dc7f..49dd9e293 100644
--- a/src/tools/rust-analyzer/crates/parser/src/tests/top_entries.rs
+++ b/src/tools/rust-analyzer/crates/parser/src/tests/top_entries.rs
@@ -65,7 +65,7 @@ fn macro_stmt() {
MACRO_STMTS
ERROR
SHEBANG "#!/usr/bin/rust"
- error 0: expected expression
+ error 0: expected expression, item or let statement
"##]],
);
check(
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/err/0009_broken_struct_type_parameter.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/err/0009_broken_struct_type_parameter.rast
index a01543217..cdc01863a 100644
--- a/src/tools/rust-analyzer/crates/parser/test_data/parser/err/0009_broken_struct_type_parameter.rast
+++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/err/0009_broken_struct_type_parameter.rast
@@ -44,8 +44,7 @@ SOURCE_FILE
IDENT "T"
SEMICOLON ";"
WHITESPACE "\n"
-error 9: expected type parameter
-error 11: expected COMMA
+error 9: expected generic parameter
error 11: expected R_ANGLE
error 11: expected `;`, `{`, or `(`
error 12: expected an item
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/err/0013_invalid_type.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/err/0013_invalid_type.rast
index eec84a0c6..b485c71ab 100644
--- a/src/tools/rust-analyzer/crates/parser/test_data/parser/err/0013_invalid_type.rast
+++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/err/0013_invalid_type.rast
@@ -43,17 +43,14 @@ SOURCE_FILE
IDENT "Box"
GENERIC_ARG_LIST
L_ANGLE "<"
- TYPE_ARG
- ERROR
- AT "@"
- WHITESPACE " "
- TUPLE_FIELD
- PATH_TYPE
- PATH
- PATH_SEGMENT
- NAME_REF
- IDENT "Any"
- ERROR
+ ERROR
+ AT "@"
+ WHITESPACE " "
+ MACRO_CALL
+ PATH
+ PATH_SEGMENT
+ NAME_REF
+ IDENT "Any"
ERROR
R_ANGLE ">"
ERROR
@@ -69,17 +66,14 @@ SOURCE_FILE
ERROR
SEMICOLON ";"
WHITESPACE "\n\n"
-error 67: expected type
-error 68: expected COMMA
-error 68: expected R_ANGLE
-error 68: expected COMMA
-error 68: expected R_ANGLE
-error 68: expected COMMA
-error 68: expected R_ANGLE
-error 68: expected COMMA
-error 72: expected COMMA
-error 72: expected a type
-error 72: expected R_PAREN
+error 67: expected R_ANGLE
+error 67: expected R_ANGLE
+error 67: expected R_ANGLE
+error 67: expected R_PAREN
+error 67: expected SEMICOLON
+error 67: expected an item
+error 72: expected BANG
+error 72: expected `{`, `[`, `(`
error 72: expected SEMICOLON
error 72: expected an item
error 73: expected an item
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/err/0022_bad_exprs.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/err/0022_bad_exprs.rast
index 900394bd9..d97fc6c72 100644
--- a/src/tools/rust-analyzer/crates/parser/test_data/parser/err/0022_bad_exprs.rast
+++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/err/0022_bad_exprs.rast
@@ -145,27 +145,29 @@ SOURCE_FILE
error 16: expected expression
error 17: expected R_BRACK
error 17: expected SEMICOLON
-error 17: expected expression
+error 17: expected expression, item or let statement
error 25: expected a name
error 26: expected `;`, `{`, or `(`
error 30: expected pattern
error 31: expected SEMICOLON
error 53: expected expression
+error 54: expected R_PAREN
error 54: expected SEMICOLON
-error 54: expected expression
+error 54: expected expression, item or let statement
error 60: expected type
error 60: expected `{`
-error 60: expected expression
+error 60: expected expression, item or let statement
error 65: expected pattern
error 65: expected SEMICOLON
-error 65: expected expression
+error 65: expected expression, item or let statement
error 92: expected expression
+error 93: expected R_PAREN
error 93: expected SEMICOLON
-error 93: expected expression
-error 95: expected expression
-error 96: expected expression
+error 93: expected expression, item or let statement
+error 95: expected expression, item or let statement
+error 96: expected expression, item or let statement
error 103: expected a name
error 104: expected `{`
error 108: expected pattern
error 108: expected SEMICOLON
-error 108: expected expression
+error 108: expected expression, item or let statement
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/err/0024_many_type_parens.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/err/0024_many_type_parens.rast
index d374f8661..f0dbc9b10 100644
--- a/src/tools/rust-analyzer/crates/parser/test_data/parser/err/0024_many_type_parens.rast
+++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/err/0024_many_type_parens.rast
@@ -168,75 +168,21 @@ SOURCE_FILE
L_PAREN "("
ERROR
QUESTION "?"
- EXPR_STMT
- PATH_EXPR
- PATH
- PATH_SEGMENT
- NAME_REF
- IDENT "Sized"
+ TYPE_ARG
+ PATH_TYPE
+ PATH
+ PATH_SEGMENT
+ NAME_REF
+ IDENT "Sized"
ERROR
R_PAREN ")"
WHITESPACE " "
ERROR
PLUS "+"
WHITESPACE " "
- TUPLE_EXPR
- L_PAREN "("
- CLOSURE_EXPR
- FOR_KW "for"
- GENERIC_PARAM_LIST
- L_ANGLE "<"
- LIFETIME_PARAM
- LIFETIME
- LIFETIME_IDENT "'a"
- R_ANGLE ">"
- WHITESPACE " "
- BIN_EXPR
- BIN_EXPR
- BIN_EXPR
- BIN_EXPR
- PATH_EXPR
- PATH
- PATH_SEGMENT
- NAME_REF
- IDENT "Trait"
- L_ANGLE "<"
- ERROR
- LIFETIME_IDENT "'a"
- R_ANGLE ">"
- ERROR
- R_PAREN ")"
- WHITESPACE " "
- PLUS "+"
- WHITESPACE " "
- PAREN_EXPR
- L_PAREN "("
- PATH_EXPR
- PATH
- PATH_SEGMENT
- NAME_REF
- IDENT "Copy"
- R_PAREN ")"
- R_ANGLE ">"
- ERROR
- SEMICOLON ";"
- WHITESPACE "\n "
- LET_EXPR
- LET_KW "let"
- WHITESPACE " "
- WILDCARD_PAT
- UNDERSCORE "_"
- ERROR
- COLON ":"
- WHITESPACE " "
+ EXPR_STMT
BIN_EXPR
BIN_EXPR
- PATH_EXPR
- PATH
- PATH_SEGMENT
- NAME_REF
- IDENT "Box"
- L_ANGLE "<"
TUPLE_EXPR
L_PAREN "("
CLOSURE_EXPR
@@ -250,78 +196,117 @@ SOURCE_FILE
WHITESPACE " "
BIN_EXPR
BIN_EXPR
- BIN_EXPR
- BIN_EXPR
- PATH_EXPR
- PATH
- PATH_SEGMENT
- NAME_REF
- IDENT "Trait"
- L_ANGLE "<"
- ERROR
- LIFETIME_IDENT "'a"
- R_ANGLE ">"
- ERROR
- R_PAREN ")"
- WHITESPACE " "
- PLUS "+"
- WHITESPACE " "
- PAREN_EXPR
- L_PAREN "("
- PATH_EXPR
- PATH
- PATH_SEGMENT
- NAME_REF
- IDENT "Copy"
- R_PAREN ")"
- WHITESPACE " "
- PLUS "+"
- WHITESPACE " "
- PAREN_EXPR
- L_PAREN "("
+ PATH_EXPR
+ PATH
+ PATH_SEGMENT
+ NAME_REF
+ IDENT "Trait"
+ L_ANGLE "<"
ERROR
- QUESTION "?"
+ LIFETIME_IDENT "'a"
+ R_ANGLE ">"
+ R_PAREN ")"
+ WHITESPACE " "
+ PLUS "+"
+ WHITESPACE " "
+ PAREN_EXPR
+ L_PAREN "("
PATH_EXPR
PATH
PATH_SEGMENT
NAME_REF
- IDENT "Sized"
+ IDENT "Copy"
R_PAREN ")"
R_ANGLE ">"
ERROR
SEMICOLON ";"
+ WHITESPACE "\n "
+ LET_STMT
+ LET_KW "let"
+ WHITESPACE " "
+ WILDCARD_PAT
+ UNDERSCORE "_"
+ COLON ":"
+ WHITESPACE " "
+ DYN_TRAIT_TYPE
+ TYPE_BOUND_LIST
+ TYPE_BOUND
+ PATH_TYPE
+ PATH
+ PATH_SEGMENT
+ NAME_REF
+ IDENT "Box"
+ GENERIC_ARG_LIST
+ L_ANGLE "<"
+ TYPE_ARG
+ PAREN_TYPE
+ L_PAREN "("
+ FOR_TYPE
+ FOR_KW "for"
+ GENERIC_PARAM_LIST
+ L_ANGLE "<"
+ LIFETIME_PARAM
+ LIFETIME
+ LIFETIME_IDENT "'a"
+ R_ANGLE ">"
+ WHITESPACE " "
+ PATH_TYPE
+ PATH
+ PATH_SEGMENT
+ NAME_REF
+ IDENT "Trait"
+ GENERIC_ARG_LIST
+ L_ANGLE "<"
+ LIFETIME_ARG
+ LIFETIME
+ LIFETIME_IDENT "'a"
+ R_ANGLE ">"
+ R_PAREN ")"
+ WHITESPACE " "
+ PLUS "+"
+ WHITESPACE " "
+ TYPE_BOUND
+ L_PAREN "("
+ PATH_TYPE
+ PATH
+ PATH_SEGMENT
+ NAME_REF
+ IDENT "Copy"
+ R_PAREN ")"
+ WHITESPACE " "
+ PLUS "+"
+ WHITESPACE " "
+ TYPE_BOUND
+ L_PAREN "("
+ QUESTION "?"
+ PATH_TYPE
+ PATH
+ PATH_SEGMENT
+ NAME_REF
+ IDENT "Sized"
+ R_PAREN ")"
+ ERROR
+ R_ANGLE ">"
+ SEMICOLON ";"
WHITESPACE "\n"
R_CURLY "}"
WHITESPACE "\n"
-error 88: expected COMMA
error 88: expected R_ANGLE
error 121: expected SEMICOLON
-error 121: expected expression
+error 121: expected expression, item or let statement
error 140: expected type
error 141: expected R_PAREN
error 141: expected COMMA
-error 141: expected R_ANGLE
-error 141: expected SEMICOLON
+error 146: expected R_ANGLE
error 146: expected SEMICOLON
-error 146: expected expression
-error 148: expected expression
+error 146: expected expression, item or let statement
+error 148: expected expression, item or let statement
error 158: expected `|`
error 158: expected COMMA
error 165: expected expression
error 168: expected expression
error 179: expected expression
-error 180: expected COMMA
-error 190: expected EQ
-error 190: expected expression
-error 191: expected COMMA
-error 204: expected `|`
-error 204: expected COMMA
-error 211: expected expression
-error 214: expected expression
-error 228: expected expression
-error 229: expected R_PAREN
-error 229: expected COMMA
-error 236: expected expression
-error 237: expected COMMA
-error 237: expected expression
-error 237: expected R_PAREN
+error 180: expected SEMICOLON
+error 215: expected R_ANGLE
+error 235: expected SEMICOLON
+error 235: expected expression, item or let statement
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/err/0025_nope.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/err/0025_nope.rast
index 6b49724ec..b6bc00883 100644
--- a/src/tools/rust-analyzer/crates/parser/test_data/parser/err/0025_nope.rast
+++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/err/0025_nope.rast
@@ -156,8 +156,7 @@ SOURCE_FILE
PATH_SEGMENT
NAME_REF
IDENT "i32"
- WHITESPACE " "
- ERROR
+ WHITESPACE " "
ERROR
L_CURLY "{"
R_CURLY "}"
@@ -199,10 +198,8 @@ error 95: expected type
error 95: expected COMMA
error 96: expected field
error 98: expected field declaration
+error 371: expected R_PAREN
error 371: expected COMMA
-error 372: expected a type
-error 372: expected R_PAREN
-error 372: expected COMMA
error 372: expected enum variant
error 374: expected enum variant
error 494: expected pattern
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/err/0042_weird_blocks.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/err/0042_weird_blocks.rast
index 9cea337ce..1cdc6e6e7 100644
--- a/src/tools/rust-analyzer/crates/parser/test_data/parser/err/0042_weird_blocks.rast
+++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/err/0042_weird_blocks.rast
@@ -72,4 +72,4 @@ SOURCE_FILE
error 24: expected existential, fn, trait or impl
error 41: expected existential, fn, trait or impl
error 56: expected a block
-error 75: expected a loop
+error 75: expected a loop or block
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/err/0048_double_fish.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/err/0048_double_fish.rast
index 3a05bfee1..207a5c24d 100644
--- a/src/tools/rust-analyzer/crates/parser/test_data/parser/err/0048_double_fish.rast
+++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/err/0048_double_fish.rast
@@ -12,7 +12,7 @@ SOURCE_FILE
STMT_LIST
L_CURLY "{"
WHITESPACE "\n "
- EXPR_STMT
+ BIN_EXPR
PATH_EXPR
PATH
PATH_SEGMENT
@@ -41,13 +41,14 @@ SOURCE_FILE
COLON2 "::"
ERROR
L_ANGLE "<"
- BIN_EXPR
- PATH_EXPR
- PATH
- PATH_SEGMENT
- NAME_REF
- IDENT "nope"
- SHR ">>"
+ TYPE_ARG
+ PATH_TYPE
+ PATH
+ PATH_SEGMENT
+ NAME_REF
+ IDENT "nope"
+ R_ANGLE ">"
+ R_ANGLE ">"
ERROR
SEMICOLON ";"
WHITESPACE "\n"
@@ -114,8 +115,6 @@ SOURCE_FILE
WHITESPACE "\n"
error 30: expected identifier
error 31: expected COMMA
-error 31: expected R_ANGLE
-error 31: expected SEMICOLON
error 37: expected expression
error 75: expected identifier
error 76: expected SEMICOLON
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0002_misplaced_label_err.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0002_misplaced_label_err.rast
index 56cea4b15..ea5203fb9 100644
--- a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0002_misplaced_label_err.rast
+++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0002_misplaced_label_err.rast
@@ -23,6 +23,6 @@ SOURCE_FILE
WHITESPACE "\n"
R_CURLY "}"
WHITESPACE "\n"
-error 22: expected a loop
+error 22: expected a loop or block
error 27: expected type
error 27: expected `{`
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0015_arg_list_recovery.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0015_arg_list_recovery.rast
new file mode 100644
index 000000000..5d0fe859c
--- /dev/null
+++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0015_arg_list_recovery.rast
@@ -0,0 +1,77 @@
+SOURCE_FILE
+ FN
+ FN_KW "fn"
+ WHITESPACE " "
+ NAME
+ IDENT "main"
+ PARAM_LIST
+ L_PAREN "("
+ R_PAREN ")"
+ WHITESPACE " "
+ BLOCK_EXPR
+ STMT_LIST
+ L_CURLY "{"
+ WHITESPACE "\n "
+ EXPR_STMT
+ CALL_EXPR
+ PATH_EXPR
+ PATH
+ PATH_SEGMENT
+ NAME_REF
+ IDENT "foo"
+ ARG_LIST
+ L_PAREN "("
+ PATH_EXPR
+ PATH
+ PATH
+ PATH_SEGMENT
+ NAME_REF
+ IDENT "bar"
+ COLON2 "::"
+ R_PAREN ")"
+ SEMICOLON ";"
+ WHITESPACE "\n "
+ EXPR_STMT
+ CALL_EXPR
+ PATH_EXPR
+ PATH
+ PATH_SEGMENT
+ NAME_REF
+ IDENT "foo"
+ ARG_LIST
+ L_PAREN "("
+ PATH_EXPR
+ PATH
+ PATH_SEGMENT
+ NAME_REF
+ IDENT "bar"
+ ERROR
+ COLON ":"
+ R_PAREN ")"
+ SEMICOLON ";"
+ WHITESPACE "\n "
+ EXPR_STMT
+ CALL_EXPR
+ PATH_EXPR
+ PATH
+ PATH_SEGMENT
+ NAME_REF
+ IDENT "foo"
+ ARG_LIST
+ L_PAREN "("
+ BIN_EXPR
+ PATH_EXPR
+ PATH
+ PATH_SEGMENT
+ NAME_REF
+ IDENT "bar"
+ PLUS "+"
+ R_PAREN ")"
+ SEMICOLON ";"
+ WHITESPACE "\n"
+ R_CURLY "}"
+ WHITESPACE "\n"
+error 25: expected identifier
+error 39: expected COMMA
+error 39: expected expression
+error 55: expected expression
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0015_arg_list_recovery.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0015_arg_list_recovery.rs
new file mode 100644
index 000000000..0e7ac9cc3
--- /dev/null
+++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0015_arg_list_recovery.rs
@@ -0,0 +1,5 @@
+fn main() {
+ foo(bar::);
+ foo(bar:);
+ foo(bar+);
+}
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0015_missing_fn_param_type.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0015_missing_fn_param_type.rast
index e72df374d..ea50ad35d 100644
--- a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0015_missing_fn_param_type.rast
+++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0015_missing_fn_param_type.rast
@@ -49,5 +49,5 @@ SOURCE_FILE
R_CURLY "}"
WHITESPACE "\n"
error 6: missing type for function parameter
-error 6: expected COMMA
+error 6: expected `,`
error 16: missing type for function parameter
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0011_field_expr.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0011_field_expr.rast
index 8498724b9..dd27dc489 100644
--- a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0011_field_expr.rast
+++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0011_field_expr.rast
@@ -41,6 +41,39 @@ SOURCE_FILE
SEMICOLON ";"
WHITESPACE "\n "
EXPR_STMT
+ FIELD_EXPR
+ FIELD_EXPR
+ PATH_EXPR
+ PATH
+ PATH_SEGMENT
+ NAME_REF
+ IDENT "x"
+ DOT "."
+ NAME_REF
+ INT_NUMBER "0"
+ DOT "."
+ NAME_REF
+ INT_NUMBER "1"
+ SEMICOLON ";"
+ WHITESPACE "\n "
+ EXPR_STMT
+ FIELD_EXPR
+ FIELD_EXPR
+ PATH_EXPR
+ PATH
+ PATH_SEGMENT
+ NAME_REF
+ IDENT "x"
+ DOT "."
+ NAME_REF
+ INT_NUMBER "0"
+ DOT "."
+ WHITESPACE " "
+ NAME_REF
+ IDENT "bar"
+ SEMICOLON ";"
+ WHITESPACE "\n "
+ EXPR_STMT
CALL_EXPR
FIELD_EXPR
PATH_EXPR
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0011_field_expr.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0011_field_expr.rs
index b8da2ddc3..98dbe45a7 100644
--- a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0011_field_expr.rs
+++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0011_field_expr.rs
@@ -1,5 +1,7 @@
fn foo() {
x.foo;
x.0.bar;
+ x.0.1;
+ x.0. bar;
x.0();
}
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0107_method_call_expr.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0107_method_call_expr.rast
index dcbcfe123..b28b8eb67 100644
--- a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0107_method_call_expr.rast
+++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0107_method_call_expr.rast
@@ -58,6 +58,49 @@ SOURCE_FILE
COMMA ","
R_PAREN ")"
SEMICOLON ";"
+ WHITESPACE "\n "
+ EXPR_STMT
+ METHOD_CALL_EXPR
+ FIELD_EXPR
+ FIELD_EXPR
+ PATH_EXPR
+ PATH
+ PATH_SEGMENT
+ NAME_REF
+ IDENT "x"
+ DOT "."
+ NAME_REF
+ INT_NUMBER "0"
+ DOT "."
+ NAME_REF
+ INT_NUMBER "0"
+ DOT "."
+ NAME_REF
+ IDENT "call"
+ ARG_LIST
+ L_PAREN "("
+ R_PAREN ")"
+ SEMICOLON ";"
+ WHITESPACE "\n "
+ EXPR_STMT
+ METHOD_CALL_EXPR
+ FIELD_EXPR
+ PATH_EXPR
+ PATH
+ PATH_SEGMENT
+ NAME_REF
+ IDENT "x"
+ DOT "."
+ NAME_REF
+ INT_NUMBER "0"
+ DOT "."
+ WHITESPACE " "
+ NAME_REF
+ IDENT "call"
+ ARG_LIST
+ L_PAREN "("
+ R_PAREN ")"
+ SEMICOLON ";"
WHITESPACE "\n"
R_CURLY "}"
WHITESPACE "\n"
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0107_method_call_expr.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0107_method_call_expr.rs
index 1a3aa35ae..48bb6381e 100644
--- a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0107_method_call_expr.rs
+++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0107_method_call_expr.rs
@@ -1,4 +1,6 @@
fn foo() {
x.foo();
y.bar::<T>(1, 2,);
+ x.0.0.call();
+ x.0. call();
}
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0137_await_expr.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0137_await_expr.rast
index 9d37ada0d..af713a220 100644
--- a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0137_await_expr.rast
+++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0137_await_expr.rast
@@ -65,6 +65,41 @@ SOURCE_FILE
L_PAREN "("
R_PAREN ")"
SEMICOLON ";"
+ WHITESPACE "\n "
+ EXPR_STMT
+ AWAIT_EXPR
+ FIELD_EXPR
+ FIELD_EXPR
+ PATH_EXPR
+ PATH
+ PATH_SEGMENT
+ NAME_REF
+ IDENT "x"
+ DOT "."
+ NAME_REF
+ INT_NUMBER "0"
+ DOT "."
+ NAME_REF
+ INT_NUMBER "0"
+ DOT "."
+ AWAIT_KW "await"
+ SEMICOLON ";"
+ WHITESPACE "\n "
+ EXPR_STMT
+ AWAIT_EXPR
+ FIELD_EXPR
+ PATH_EXPR
+ PATH
+ PATH_SEGMENT
+ NAME_REF
+ IDENT "x"
+ DOT "."
+ NAME_REF
+ INT_NUMBER "0"
+ DOT "."
+ WHITESPACE " "
+ AWAIT_KW "await"
+ SEMICOLON ";"
WHITESPACE "\n"
R_CURLY "}"
WHITESPACE "\n"
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0137_await_expr.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0137_await_expr.rs
index d2ba89ca6..fe9a3211b 100644
--- a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0137_await_expr.rs
+++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0137_await_expr.rs
@@ -2,4 +2,6 @@ fn foo() {
x.await;
x.0.await;
x.0().await?.hello();
+ x.0.0.await;
+ x.0. await;
}
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0205_const_closure.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0205_const_closure.rast
new file mode 100644
index 000000000..06442a1d0
--- /dev/null
+++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0205_const_closure.rast
@@ -0,0 +1,42 @@
+SOURCE_FILE
+ FN
+ FN_KW "fn"
+ WHITESPACE " "
+ NAME
+ IDENT "main"
+ PARAM_LIST
+ L_PAREN "("
+ R_PAREN ")"
+ WHITESPACE " "
+ BLOCK_EXPR
+ STMT_LIST
+ L_CURLY "{"
+ WHITESPACE " "
+ LET_STMT
+ LET_KW "let"
+ WHITESPACE " "
+ IDENT_PAT
+ NAME
+ IDENT "cl"
+ WHITESPACE " "
+ EQ "="
+ WHITESPACE " "
+ CLOSURE_EXPR
+ CONST_KW "const"
+ WHITESPACE " "
+ PARAM_LIST
+ PIPE "|"
+ PIPE "|"
+ WHITESPACE " "
+ BIN_EXPR
+ UNDERSCORE_EXPR
+ UNDERSCORE "_"
+ WHITESPACE " "
+ EQ "="
+ WHITESPACE " "
+ LITERAL
+ INT_NUMBER "0"
+ SEMICOLON ";"
+ WHITESPACE " "
+ R_CURLY "}"
+ WHITESPACE "\n"
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0205_const_closure.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0205_const_closure.rs
new file mode 100644
index 000000000..0c05cc70b
--- /dev/null
+++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0205_const_closure.rs
@@ -0,0 +1 @@
+fn main() { let cl = const || _ = 0; }
diff --git a/src/tools/rust-analyzer/crates/paths/Cargo.toml b/src/tools/rust-analyzer/crates/paths/Cargo.toml
index d23a63d2a..e24e6ecef 100644
--- a/src/tools/rust-analyzer/crates/paths/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/paths/Cargo.toml
@@ -2,9 +2,11 @@
name = "paths"
version = "0.0.0"
description = "TBD"
-license = "MIT OR Apache-2.0"
-edition = "2021"
-rust-version = "1.65"
+
+authors.workspace = true
+edition.workspace = true
+license.workspace = true
+rust-version.workspace = true
[lib]
doctest = false
diff --git a/src/tools/rust-analyzer/crates/proc-macro-api/Cargo.toml b/src/tools/rust-analyzer/crates/proc-macro-api/Cargo.toml
index f261f3def..28469b832 100644
--- a/src/tools/rust-analyzer/crates/proc-macro-api/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/proc-macro-api/Cargo.toml
@@ -2,15 +2,17 @@
name = "proc-macro-api"
version = "0.0.0"
description = "TBD"
-license = "MIT OR Apache-2.0"
-edition = "2021"
-rust-version = "1.65"
+
+authors.workspace = true
+edition.workspace = true
+license.workspace = true
+rust-version.workspace = true
[lib]
doctest = false
[dependencies]
-object = { version = "0.29.0", default-features = false, features = [
+object = { version = "0.30.2", default-features = false, features = [
"std",
"read_core",
"elf",
@@ -21,11 +23,12 @@ serde = { version = "1.0.137", features = ["derive"] }
serde_json = { version = "1.0.81", features = ["unbounded_depth"] }
tracing = "0.1.37"
memmap2 = "0.5.4"
-snap = "1.0.5"
+snap = "1.1.0"
-paths = { path = "../paths", version = "0.0.0" }
-tt = { path = "../tt", version = "0.0.0" }
-stdx = { path = "../stdx", version = "0.0.0" }
-profile = { path = "../profile", version = "0.0.0" }
+# local deps
+paths.workspace = true
+tt.workspace = true
+stdx.workspace = true
+profile.workspace = true
# Intentionally *not* depend on anything salsa-related
-# base-db = { path = "../base-db", version = "0.0.0" }
+# base-db.workspace = true
diff --git a/src/tools/rust-analyzer/crates/proc-macro-api/src/lib.rs b/src/tools/rust-analyzer/crates/proc-macro-api/src/lib.rs
index 7921fda33..90d06967e 100644
--- a/src/tools/rust-analyzer/crates/proc-macro-api/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/proc-macro-api/src/lib.rs
@@ -19,7 +19,8 @@ use std::{
};
use serde::{Deserialize, Serialize};
-use tt::Subtree;
+
+use ::tt::token_id as tt;
use crate::{
msg::{ExpandMacro, FlatTree, PanicMessage},
@@ -70,7 +71,7 @@ impl MacroDylib {
/// A handle to a specific macro (a `#[proc_macro]` annotated function).
///
-/// It exists withing a context of a specific [`ProcMacroProcess`] -- currently
+/// It exists within a context of a specific [`ProcMacroProcess`] -- currently
/// we share a single expander process for all macros.
#[derive(Debug, Clone)]
pub struct ProcMacro {
@@ -114,14 +115,14 @@ impl ProcMacroServer {
/// Spawns an external process as the proc macro server and returns a client connected to it.
pub fn spawn(
process_path: AbsPathBuf,
- args: impl IntoIterator<Item = impl AsRef<OsStr>>,
+ args: impl IntoIterator<Item = impl AsRef<OsStr>> + Clone,
) -> io::Result<ProcMacroServer> {
let process = ProcMacroProcessSrv::run(process_path, args)?;
Ok(ProcMacroServer { process: Arc::new(Mutex::new(process)) })
}
pub fn load_dylib(&self, dylib: MacroDylib) -> Result<Vec<ProcMacro>, ServerError> {
- let _p = profile::span("ProcMacroClient::by_dylib_path");
+ let _p = profile::span("ProcMacroClient::load_dylib");
let macros =
self.process.lock().unwrap_or_else(|e| e.into_inner()).find_proc_macros(&dylib.path)?;
@@ -151,10 +152,10 @@ impl ProcMacro {
pub fn expand(
&self,
- subtree: &Subtree,
- attr: Option<&Subtree>,
+ subtree: &tt::Subtree,
+ attr: Option<&tt::Subtree>,
env: Vec<(String, String)>,
- ) -> Result<Result<Subtree, PanicMessage>, ServerError> {
+ ) -> Result<Result<tt::Subtree, PanicMessage>, ServerError> {
let current_dir = env
.iter()
.find(|(name, _)| name == "CARGO_MANIFEST_DIR")
@@ -173,7 +174,7 @@ impl ProcMacro {
let response = self.process.lock().unwrap_or_else(|e| e.into_inner()).send_task(request)?;
match response {
msg::Response::ExpandMacro(it) => Ok(it.map(FlatTree::to_subtree)),
- msg::Response::ListMacros { .. } => {
+ msg::Response::ListMacros(..) | msg::Response::ApiVersionCheck(..) => {
Err(ServerError { message: "unexpected response".to_string(), io: None })
}
}
diff --git a/src/tools/rust-analyzer/crates/proc-macro-api/src/msg.rs b/src/tools/rust-analyzer/crates/proc-macro-api/src/msg.rs
index f9c2b9fda..4040efe93 100644
--- a/src/tools/rust-analyzer/crates/proc-macro-api/src/msg.rs
+++ b/src/tools/rust-analyzer/crates/proc-macro-api/src/msg.rs
@@ -12,16 +12,21 @@ use crate::ProcMacroKind;
pub use crate::msg::flat::FlatTree;
+pub const NO_VERSION_CHECK_VERSION: u32 = 0;
+pub const CURRENT_API_VERSION: u32 = 1;
+
#[derive(Debug, Serialize, Deserialize)]
pub enum Request {
ListMacros { dylib_path: PathBuf },
ExpandMacro(ExpandMacro),
+ ApiVersionCheck {},
}
#[derive(Debug, Serialize, Deserialize)]
pub enum Response {
ListMacros(Result<Vec<(String, ProcMacroKind)>, String>),
ExpandMacro(Result<FlatTree, PanicMessage>),
+ ApiVersionCheck(u32),
}
#[derive(Debug, Serialize, Deserialize)]
@@ -107,27 +112,31 @@ fn write_json(out: &mut impl Write, msg: &str) -> io::Result<()> {
#[cfg(test)]
mod tests {
use super::*;
- use tt::*;
+ use crate::tt::*;
fn fixture_token_tree() -> Subtree {
- let mut subtree = Subtree::default();
+ let mut subtree = Subtree { delimiter: Delimiter::unspecified(), token_trees: Vec::new() };
subtree
.token_trees
- .push(TokenTree::Leaf(Ident { text: "struct".into(), id: TokenId(0) }.into()));
+ .push(TokenTree::Leaf(Ident { text: "struct".into(), span: TokenId(0) }.into()));
subtree
.token_trees
- .push(TokenTree::Leaf(Ident { text: "Foo".into(), id: TokenId(1) }.into()));
+ .push(TokenTree::Leaf(Ident { text: "Foo".into(), span: TokenId(1) }.into()));
subtree.token_trees.push(TokenTree::Leaf(Leaf::Literal(Literal {
text: "Foo".into(),
- id: TokenId::unspecified(),
+ span: TokenId::unspecified(),
})));
subtree.token_trees.push(TokenTree::Leaf(Leaf::Punct(Punct {
char: '@',
- id: TokenId::unspecified(),
+ span: TokenId::unspecified(),
spacing: Spacing::Joint,
})));
subtree.token_trees.push(TokenTree::Subtree(Subtree {
- delimiter: Some(Delimiter { id: TokenId(2), kind: DelimiterKind::Brace }),
+ delimiter: Delimiter {
+ open: TokenId(2),
+ close: TokenId::UNSPECIFIED,
+ kind: DelimiterKind::Brace,
+ },
token_trees: vec![],
}));
subtree
diff --git a/src/tools/rust-analyzer/crates/proc-macro-api/src/msg/flat.rs b/src/tools/rust-analyzer/crates/proc-macro-api/src/msg/flat.rs
index b178c4626..fd3202e0b 100644
--- a/src/tools/rust-analyzer/crates/proc-macro-api/src/msg/flat.rs
+++ b/src/tools/rust-analyzer/crates/proc-macro-api/src/msg/flat.rs
@@ -38,7 +38,8 @@
use std::collections::{HashMap, VecDeque};
use serde::{Deserialize, Serialize};
-use tt::TokenId;
+
+use crate::tt::{self, TokenId};
#[derive(Serialize, Deserialize, Debug)]
pub struct FlatTree {
@@ -52,7 +53,7 @@ pub struct FlatTree {
struct SubtreeRepr {
id: tt::TokenId,
- kind: Option<tt::DelimiterKind>,
+ kind: tt::DelimiterKind,
tt: [u32; 2],
}
@@ -124,19 +125,19 @@ impl FlatTree {
impl SubtreeRepr {
fn write(self) -> [u32; 4] {
let kind = match self.kind {
- None => 0,
- Some(tt::DelimiterKind::Parenthesis) => 1,
- Some(tt::DelimiterKind::Brace) => 2,
- Some(tt::DelimiterKind::Bracket) => 3,
+ tt::DelimiterKind::Invisible => 0,
+ tt::DelimiterKind::Parenthesis => 1,
+ tt::DelimiterKind::Brace => 2,
+ tt::DelimiterKind::Bracket => 3,
};
[self.id.0, kind, self.tt[0], self.tt[1]]
}
fn read([id, kind, lo, len]: [u32; 4]) -> SubtreeRepr {
let kind = match kind {
- 0 => None,
- 1 => Some(tt::DelimiterKind::Parenthesis),
- 2 => Some(tt::DelimiterKind::Brace),
- 3 => Some(tt::DelimiterKind::Bracket),
+ 0 => tt::DelimiterKind::Invisible,
+ 1 => tt::DelimiterKind::Parenthesis,
+ 2 => tt::DelimiterKind::Brace,
+ 3 => tt::DelimiterKind::Bracket,
other => panic!("bad kind {other}"),
};
SubtreeRepr { id: TokenId(id), kind, tt: [lo, len] }
@@ -216,7 +217,7 @@ impl<'a> Writer<'a> {
tt::Leaf::Literal(lit) => {
let idx = self.literal.len() as u32;
let text = self.intern(&lit.text);
- self.literal.push(LiteralRepr { id: lit.id, text });
+ self.literal.push(LiteralRepr { id: lit.span, text });
idx << 2 | 0b01
}
tt::Leaf::Punct(punct) => {
@@ -224,14 +225,14 @@ impl<'a> Writer<'a> {
self.punct.push(PunctRepr {
char: punct.char,
spacing: punct.spacing,
- id: punct.id,
+ id: punct.span,
});
idx << 2 | 0b10
}
tt::Leaf::Ident(ident) => {
let idx = self.ident.len() as u32;
let text = self.intern(&ident.text);
- self.ident.push(IdentRepr { id: ident.id, text });
+ self.ident.push(IdentRepr { id: ident.span, text });
idx << 2 | 0b11
}
},
@@ -243,8 +244,8 @@ impl<'a> Writer<'a> {
fn enqueue(&mut self, subtree: &'a tt::Subtree) -> u32 {
let idx = self.subtree.len();
- let delimiter_id = subtree.delimiter.map_or(TokenId::unspecified(), |it| it.id);
- let delimiter_kind = subtree.delimiter.map(|it| it.kind);
+ let delimiter_id = subtree.delimiter.open;
+ let delimiter_kind = subtree.delimiter.kind;
self.subtree.push(SubtreeRepr { id: delimiter_id, kind: delimiter_kind, tt: [!0, !0] });
self.work.push_back((idx, subtree));
idx as u32
@@ -276,7 +277,11 @@ impl Reader {
let repr = &self.subtree[i];
let token_trees = &self.token_tree[repr.tt[0] as usize..repr.tt[1] as usize];
let s = tt::Subtree {
- delimiter: repr.kind.map(|kind| tt::Delimiter { id: repr.id, kind }),
+ delimiter: tt::Delimiter {
+ open: repr.id,
+ close: TokenId::UNSPECIFIED,
+ kind: repr.kind,
+ },
token_trees: token_trees
.iter()
.copied()
@@ -291,7 +296,7 @@ impl Reader {
let repr = &self.literal[idx];
tt::Leaf::Literal(tt::Literal {
text: self.text[repr.text as usize].as_str().into(),
- id: repr.id,
+ span: repr.id,
})
.into()
}
@@ -300,7 +305,7 @@ impl Reader {
tt::Leaf::Punct(tt::Punct {
char: repr.char,
spacing: repr.spacing,
- id: repr.id,
+ span: repr.id,
})
.into()
}
@@ -308,7 +313,7 @@ impl Reader {
let repr = &self.ident[idx];
tt::Leaf::Ident(tt::Ident {
text: self.text[repr.text as usize].as_str().into(),
- id: repr.id,
+ span: repr.id,
})
.into()
}
diff --git a/src/tools/rust-analyzer/crates/proc-macro-api/src/process.rs b/src/tools/rust-analyzer/crates/proc-macro-api/src/process.rs
index 54dcb17f4..1ccbd780f 100644
--- a/src/tools/rust-analyzer/crates/proc-macro-api/src/process.rs
+++ b/src/tools/rust-analyzer/crates/proc-macro-api/src/process.rs
@@ -10,7 +10,7 @@ use paths::{AbsPath, AbsPathBuf};
use stdx::JodChild;
use crate::{
- msg::{Message, Request, Response},
+ msg::{Message, Request, Response, CURRENT_API_VERSION},
ProcMacroKind, ServerError,
};
@@ -19,19 +19,53 @@ pub(crate) struct ProcMacroProcessSrv {
_process: Process,
stdin: ChildStdin,
stdout: BufReader<ChildStdout>,
+ version: u32,
}
impl ProcMacroProcessSrv {
pub(crate) fn run(
process_path: AbsPathBuf,
- args: impl IntoIterator<Item = impl AsRef<OsStr>>,
+ args: impl IntoIterator<Item = impl AsRef<OsStr>> + Clone,
) -> io::Result<ProcMacroProcessSrv> {
- let mut process = Process::run(process_path, args)?;
- let (stdin, stdout) = process.stdio().expect("couldn't access child stdio");
+ let create_srv = |null_stderr| {
+ let mut process = Process::run(process_path.clone(), args.clone(), null_stderr)?;
+ let (stdin, stdout) = process.stdio().expect("couldn't access child stdio");
+
+ io::Result::Ok(ProcMacroProcessSrv { _process: process, stdin, stdout, version: 0 })
+ };
+ let mut srv = create_srv(true)?;
+ tracing::info!("sending version check");
+ match srv.version_check() {
+ Ok(v) if v > CURRENT_API_VERSION => Err(io::Error::new(
+ io::ErrorKind::Other,
+ format!(
+ "proc-macro server's api version ({}) is newer than rust-analyzer's ({})",
+ v, CURRENT_API_VERSION
+ ),
+ )),
+ Ok(v) => {
+ tracing::info!("got version {v}");
+ srv = create_srv(false)?;
+ srv.version = v;
+ Ok(srv)
+ }
+ Err(e) => {
+ tracing::info!(%e, "proc-macro version check failed, restarting and assuming version 0");
+ create_srv(false)
+ }
+ }
+ }
- let srv = ProcMacroProcessSrv { _process: process, stdin, stdout };
+ pub(crate) fn version_check(&mut self) -> Result<u32, ServerError> {
+ let request = Request::ApiVersionCheck {};
+ let response = self.send_task(request)?;
- Ok(srv)
+ match response {
+ Response::ApiVersionCheck(version) => Ok(version),
+ Response::ExpandMacro { .. } | Response::ListMacros { .. } => {
+ Err(ServerError { message: "unexpected response".to_string(), io: None })
+ }
+ }
}
pub(crate) fn find_proc_macros(
@@ -44,7 +78,7 @@ impl ProcMacroProcessSrv {
match response {
Response::ListMacros(it) => Ok(it),
- Response::ExpandMacro { .. } => {
+ Response::ExpandMacro { .. } | Response::ApiVersionCheck { .. } => {
Err(ServerError { message: "unexpected response".to_string(), io: None })
}
}
@@ -65,9 +99,10 @@ impl Process {
fn run(
path: AbsPathBuf,
args: impl IntoIterator<Item = impl AsRef<OsStr>>,
+ null_stderr: bool,
) -> io::Result<Process> {
let args: Vec<OsString> = args.into_iter().map(|s| s.as_ref().into()).collect();
- let child = JodChild(mk_child(&path, args)?);
+ let child = JodChild(mk_child(&path, args, null_stderr)?);
Ok(Process { child })
}
@@ -83,13 +118,14 @@ impl Process {
fn mk_child(
path: &AbsPath,
args: impl IntoIterator<Item = impl AsRef<OsStr>>,
+ null_stderr: bool,
) -> io::Result<Child> {
Command::new(path.as_os_str())
.args(args)
.env("RUST_ANALYZER_INTERNALS_DO_NOT_USE", "this is unstable")
.stdin(Stdio::piped())
.stdout(Stdio::piped())
- .stderr(Stdio::inherit())
+ .stderr(if null_stderr { Stdio::null() } else { Stdio::inherit() })
.spawn()
}
diff --git a/src/tools/rust-analyzer/crates/proc-macro-api/src/version.rs b/src/tools/rust-analyzer/crates/proc-macro-api/src/version.rs
index 40125c2a5..cf637ec35 100644
--- a/src/tools/rust-analyzer/crates/proc-macro-api/src/version.rs
+++ b/src/tools/rust-analyzer/crates/proc-macro-api/src/version.rs
@@ -120,17 +120,20 @@ pub fn read_version(dylib_path: &AbsPath) -> io::Result<String> {
let version = u32::from_be_bytes([dot_rustc[4], dot_rustc[5], dot_rustc[6], dot_rustc[7]]);
// Last supported version is:
// https://github.com/rust-lang/rust/commit/0696e79f2740ad89309269b460579e548a5cd632
- match version {
- 5 | 6 => {}
+ let snappy_portion = match version {
+ 5 | 6 => &dot_rustc[8..],
+ 7 => {
+ let len_bytes = &dot_rustc[8..12];
+ let data_len = u32::from_be_bytes(len_bytes.try_into().unwrap()) as usize;
+ &dot_rustc[12..data_len + 12]
+ }
_ => {
return Err(io::Error::new(
io::ErrorKind::InvalidData,
format!("unsupported metadata version {version}"),
));
}
- }
-
- let snappy_portion = &dot_rustc[8..];
+ };
let mut snappy_decoder = SnapDecoder::new(snappy_portion);
diff --git a/src/tools/rust-analyzer/crates/proc-macro-srv-cli/Cargo.toml b/src/tools/rust-analyzer/crates/proc-macro-srv-cli/Cargo.toml
index 7991e125a..c402bc022 100644
--- a/src/tools/rust-analyzer/crates/proc-macro-srv-cli/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/proc-macro-srv-cli/Cargo.toml
@@ -2,12 +2,14 @@
name = "proc-macro-srv-cli"
version = "0.0.0"
description = "TBD"
-license = "MIT OR Apache-2.0"
-edition = "2021"
-rust-version = "1.65"
+
+authors.workspace = true
+edition.workspace = true
+license.workspace = true
+rust-version.workspace = true
[dependencies]
-proc-macro-srv = { version = "0.0.0", path = "../proc-macro-srv" }
+proc-macro-srv.workspace = true
[features]
sysroot-abi = ["proc-macro-srv/sysroot-abi"]
diff --git a/src/tools/rust-analyzer/crates/proc-macro-srv/Cargo.toml b/src/tools/rust-analyzer/crates/proc-macro-srv/Cargo.toml
index a136abc12..f7f07cfcb 100644
--- a/src/tools/rust-analyzer/crates/proc-macro-srv/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/proc-macro-srv/Cargo.toml
@@ -2,15 +2,17 @@
name = "proc-macro-srv"
version = "0.0.0"
description = "TBD"
-license = "MIT OR Apache-2.0"
-edition = "2021"
-rust-version = "1.65"
+
+authors.workspace = true
+edition.workspace = true
+license.workspace = true
+rust-version.workspace = true
[lib]
doctest = false
[dependencies]
-object = { version = "0.29.0", default-features = false, features = [
+object = { version = "0.30.2", default-features = false, features = [
"std",
"read_core",
"elf",
@@ -20,16 +22,16 @@ object = { version = "0.29.0", default-features = false, features = [
libloading = "0.7.3"
memmap2 = "0.5.4"
-tt = { path = "../tt", version = "0.0.0" }
-mbe = { path = "../mbe", version = "0.0.0" }
-paths = { path = "../paths", version = "0.0.0" }
-proc-macro-api = { path = "../proc-macro-api", version = "0.0.0" }
+tt.workspace = true
+mbe.workspace = true
+paths.workspace = true
+proc-macro-api.workspace = true
[dev-dependencies]
expect-test = "1.4.0"
# used as proc macro test targets
-proc-macro-test = { path = "../proc-macro-test" }
+proc-macro-test.workspace = true
[features]
sysroot-abi = []
diff --git a/src/tools/rust-analyzer/crates/proc-macro-srv/src/abis/abi_1_58/mod.rs b/src/tools/rust-analyzer/crates/proc-macro-srv/src/abis/abi_1_58/mod.rs
deleted file mode 100644
index 1c91ac0fa..000000000
--- a/src/tools/rust-analyzer/crates/proc-macro-srv/src/abis/abi_1_58/mod.rs
+++ /dev/null
@@ -1,104 +0,0 @@
-//! Macro ABI for version 1.58 of rustc
-
-#[allow(dead_code)]
-#[doc(hidden)]
-mod proc_macro;
-
-#[allow(dead_code)]
-#[doc(hidden)]
-mod ra_server;
-
-use libloading::Library;
-use proc_macro_api::ProcMacroKind;
-
-use super::PanicMessage;
-
-pub(crate) struct Abi {
- exported_macros: Vec<proc_macro::bridge::client::ProcMacro>,
-}
-
-impl From<proc_macro::bridge::PanicMessage> for PanicMessage {
- fn from(p: proc_macro::bridge::PanicMessage) -> Self {
- Self { message: p.as_str().map(|s| s.to_string()) }
- }
-}
-
-impl Abi {
- pub unsafe fn from_lib(lib: &Library, symbol_name: String) -> Result<Abi, libloading::Error> {
- let macros: libloading::Symbol<'_, &&[proc_macro::bridge::client::ProcMacro]> =
- lib.get(symbol_name.as_bytes())?;
- Ok(Self { exported_macros: macros.to_vec() })
- }
-
- pub fn expand(
- &self,
- macro_name: &str,
- macro_body: &tt::Subtree,
- attributes: Option<&tt::Subtree>,
- ) -> Result<tt::Subtree, PanicMessage> {
- let parsed_body = ra_server::TokenStream::with_subtree(macro_body.clone());
-
- let parsed_attributes = attributes.map_or(ra_server::TokenStream::new(), |attr| {
- ra_server::TokenStream::with_subtree(attr.clone())
- });
-
- for proc_macro in &self.exported_macros {
- match proc_macro {
- proc_macro::bridge::client::ProcMacro::CustomDerive {
- trait_name, client, ..
- } if *trait_name == macro_name => {
- let res = client.run(
- &proc_macro::bridge::server::SameThread,
- ra_server::RustAnalyzer::default(),
- parsed_body,
- true,
- );
- return res.map(|it| it.into_subtree()).map_err(PanicMessage::from);
- }
- proc_macro::bridge::client::ProcMacro::Bang { name, client }
- if *name == macro_name =>
- {
- let res = client.run(
- &proc_macro::bridge::server::SameThread,
- ra_server::RustAnalyzer::default(),
- parsed_body,
- true,
- );
- return res.map(|it| it.into_subtree()).map_err(PanicMessage::from);
- }
- proc_macro::bridge::client::ProcMacro::Attr { name, client }
- if *name == macro_name =>
- {
- let res = client.run(
- &proc_macro::bridge::server::SameThread,
- ra_server::RustAnalyzer::default(),
- parsed_attributes,
- parsed_body,
- true,
- );
- return res.map(|it| it.into_subtree()).map_err(PanicMessage::from);
- }
- _ => continue,
- }
- }
-
- Err(proc_macro::bridge::PanicMessage::String("Nothing to expand".to_string()).into())
- }
-
- pub fn list_macros(&self) -> Vec<(String, ProcMacroKind)> {
- self.exported_macros
- .iter()
- .map(|proc_macro| match proc_macro {
- proc_macro::bridge::client::ProcMacro::CustomDerive { trait_name, .. } => {
- (trait_name.to_string(), ProcMacroKind::CustomDerive)
- }
- proc_macro::bridge::client::ProcMacro::Bang { name, .. } => {
- (name.to_string(), ProcMacroKind::FuncLike)
- }
- proc_macro::bridge::client::ProcMacro::Attr { name, .. } => {
- (name.to_string(), ProcMacroKind::Attr)
- }
- })
- .collect()
- }
-}
diff --git a/src/tools/rust-analyzer/crates/proc-macro-srv/src/abis/abi_1_58/proc_macro/bridge/buffer.rs b/src/tools/rust-analyzer/crates/proc-macro-srv/src/abis/abi_1_58/proc_macro/bridge/buffer.rs
deleted file mode 100644
index d82669d3e..000000000
--- a/src/tools/rust-analyzer/crates/proc-macro-srv/src/abis/abi_1_58/proc_macro/bridge/buffer.rs
+++ /dev/null
@@ -1,143 +0,0 @@
-//! Buffer management for same-process client<->server communication.
-
-use std::io::{self, Write};
-use std::mem;
-use std::ops::{Deref, DerefMut};
-use std::slice;
-
-#[repr(C)]
-pub struct Buffer<T: Copy> {
- data: *mut T,
- len: usize,
- capacity: usize,
- reserve: extern "C" fn(Buffer<T>, usize) -> Buffer<T>,
- drop: extern "C" fn(Buffer<T>),
-}
-
-unsafe impl<T: Copy + Sync> Sync for Buffer<T> {}
-unsafe impl<T: Copy + Send> Send for Buffer<T> {}
-
-impl<T: Copy> Default for Buffer<T> {
- fn default() -> Self {
- Self::from(vec![])
- }
-}
-
-impl<T: Copy> Deref for Buffer<T> {
- type Target = [T];
- fn deref(&self) -> &[T] {
- unsafe { slice::from_raw_parts(self.data as *const T, self.len) }
- }
-}
-
-impl<T: Copy> DerefMut for Buffer<T> {
- fn deref_mut(&mut self) -> &mut [T] {
- unsafe { slice::from_raw_parts_mut(self.data, self.len) }
- }
-}
-
-impl<T: Copy> Buffer<T> {
- pub(super) fn new() -> Self {
- Self::default()
- }
-
- pub(super) fn clear(&mut self) {
- self.len = 0;
- }
-
- pub(super) fn take(&mut self) -> Self {
- mem::take(self)
- }
-
- // We have the array method separate from extending from a slice. This is
- // because in the case of small arrays, codegen can be more efficient
- // (avoiding a memmove call). With extend_from_slice, LLVM at least
- // currently is not able to make that optimization.
- pub(super) fn extend_from_array<const N: usize>(&mut self, xs: &[T; N]) {
- if xs.len() > (self.capacity - self.len) {
- let b = self.take();
- *self = (b.reserve)(b, xs.len());
- }
- unsafe {
- xs.as_ptr().copy_to_nonoverlapping(self.data.add(self.len), xs.len());
- self.len += xs.len();
- }
- }
-
- pub(super) fn extend_from_slice(&mut self, xs: &[T]) {
- if xs.len() > (self.capacity - self.len) {
- let b = self.take();
- *self = (b.reserve)(b, xs.len());
- }
- unsafe {
- xs.as_ptr().copy_to_nonoverlapping(self.data.add(self.len), xs.len());
- self.len += xs.len();
- }
- }
-
- pub(super) fn push(&mut self, v: T) {
- // The code here is taken from Vec::push, and we know that reserve()
- // will panic if we're exceeding isize::MAX bytes and so there's no need
- // to check for overflow.
- if self.len == self.capacity {
- let b = self.take();
- *self = (b.reserve)(b, 1);
- }
- unsafe {
- *self.data.add(self.len) = v;
- self.len += 1;
- }
- }
-}
-
-impl Write for Buffer<u8> {
- fn write(&mut self, xs: &[u8]) -> io::Result<usize> {
- self.extend_from_slice(xs);
- Ok(xs.len())
- }
-
- fn write_all(&mut self, xs: &[u8]) -> io::Result<()> {
- self.extend_from_slice(xs);
- Ok(())
- }
-
- fn flush(&mut self) -> io::Result<()> {
- Ok(())
- }
-}
-
-impl<T: Copy> Drop for Buffer<T> {
- fn drop(&mut self) {
- let b = self.take();
- (b.drop)(b);
- }
-}
-
-impl<T: Copy> From<Vec<T>> for Buffer<T> {
- fn from(mut v: Vec<T>) -> Self {
- let (data, len, capacity) = (v.as_mut_ptr(), v.len(), v.capacity());
- mem::forget(v);
-
- // This utility function is nested in here because it can *only*
- // be safely called on `Buffer`s created by *this* `proc_macro`.
- fn to_vec<T: Copy>(b: Buffer<T>) -> Vec<T> {
- unsafe {
- let Buffer { data, len, capacity, .. } = b;
- mem::forget(b);
- Vec::from_raw_parts(data, len, capacity)
- }
- }
-
- extern "C" fn reserve<T: Copy>(b: Buffer<T>, additional: usize) -> Buffer<T> {
- let mut v = to_vec(b);
- v.reserve(additional);
- Buffer::from(v)
- }
-
- extern "C" fn drop<T: Copy>(b: Buffer<T>) {
- mem::drop(to_vec(b));
- }
-
- Buffer { data, len, capacity, reserve, drop }
- }
-}
diff --git a/src/tools/rust-analyzer/crates/proc-macro-srv/src/abis/abi_1_58/proc_macro/bridge/client.rs b/src/tools/rust-analyzer/crates/proc-macro-srv/src/abis/abi_1_58/proc_macro/bridge/client.rs
deleted file mode 100644
index e78842f5c..000000000
--- a/src/tools/rust-analyzer/crates/proc-macro-srv/src/abis/abi_1_58/proc_macro/bridge/client.rs
+++ /dev/null
@@ -1,485 +0,0 @@
-//! Client-side types.
-
-use super::*;
-
-macro_rules! define_handles {
- (
- 'owned: $($oty:ident,)*
- 'interned: $($ity:ident,)*
- ) => {
- #[repr(C)]
- #[allow(non_snake_case)]
- pub struct HandleCounters {
- $($oty: AtomicUsize,)*
- $($ity: AtomicUsize,)*
- }
-
- impl HandleCounters {
- // FIXME(eddyb) use a reference to the `static COUNTERS`, instead of
- // a wrapper `fn` pointer, once `const fn` can reference `static`s.
- extern "C" fn get() -> &'static Self {
- static COUNTERS: HandleCounters = HandleCounters {
- $($oty: AtomicUsize::new(1),)*
- $($ity: AtomicUsize::new(1),)*
- };
- &COUNTERS
- }
- }
-
- // FIXME(eddyb) generate the definition of `HandleStore` in `server.rs`.
- #[repr(C)]
- #[allow(non_snake_case)]
- pub(super) struct HandleStore<S: server::Types> {
- $($oty: handle::OwnedStore<S::$oty>,)*
- $($ity: handle::InternedStore<S::$ity>,)*
- }
-
- impl<S: server::Types> HandleStore<S> {
- pub(super) fn new(handle_counters: &'static HandleCounters) -> Self {
- HandleStore {
- $($oty: handle::OwnedStore::new(&handle_counters.$oty),)*
- $($ity: handle::InternedStore::new(&handle_counters.$ity),)*
- }
- }
- }
-
- $(
- #[repr(C)]
- pub(crate) struct $oty(handle::Handle);
-
- // Forward `Drop::drop` to the inherent `drop` method.
- impl Drop for $oty {
- fn drop(&mut self) {
- $oty(self.0).drop();
- }
- }
-
- impl<S> Encode<S> for $oty {
- fn encode(self, w: &mut Writer, s: &mut S) {
- let handle = self.0;
- mem::forget(self);
- handle.encode(w, s);
- }
- }
-
- impl<S: server::Types> DecodeMut<'_, '_, HandleStore<server::MarkedTypes<S>>>
- for Marked<S::$oty, $oty>
- {
- fn decode(r: &mut Reader<'_>, s: &mut HandleStore<server::MarkedTypes<S>>) -> Self {
- s.$oty.take(handle::Handle::decode(r, &mut ()))
- }
- }
-
- impl<S> Encode<S> for &$oty {
- fn encode(self, w: &mut Writer, s: &mut S) {
- self.0.encode(w, s);
- }
- }
-
- impl<'s, S: server::Types> Decode<'_, 's, HandleStore<server::MarkedTypes<S>>>
- for &'s Marked<S::$oty, $oty>
- {
- fn decode(r: &mut Reader<'_>, s: &'s HandleStore<server::MarkedTypes<S>>) -> Self {
- &s.$oty[handle::Handle::decode(r, &mut ())]
- }
- }
-
- impl<S> Encode<S> for &mut $oty {
- fn encode(self, w: &mut Writer, s: &mut S) {
- self.0.encode(w, s);
- }
- }
-
- impl<'s, S: server::Types> DecodeMut<'_, 's, HandleStore<server::MarkedTypes<S>>>
- for &'s mut Marked<S::$oty, $oty>
- {
- fn decode(
- r: &mut Reader<'_>,
- s: &'s mut HandleStore<server::MarkedTypes<S>>
- ) -> Self {
- &mut s.$oty[handle::Handle::decode(r, &mut ())]
- }
- }
-
- impl<S: server::Types> Encode<HandleStore<server::MarkedTypes<S>>>
- for Marked<S::$oty, $oty>
- {
- fn encode(self, w: &mut Writer, s: &mut HandleStore<server::MarkedTypes<S>>) {
- s.$oty.alloc(self).encode(w, s);
- }
- }
-
- impl<S> DecodeMut<'_, '_, S> for $oty {
- fn decode(r: &mut Reader<'_>, s: &mut S) -> Self {
- $oty(handle::Handle::decode(r, s))
- }
- }
- )*
-
- $(
- #[repr(C)]
- #[derive(Copy, Clone, PartialEq, Eq, Hash)]
- pub(crate) struct $ity(handle::Handle);
-
- impl<S> Encode<S> for $ity {
- fn encode(self, w: &mut Writer, s: &mut S) {
- self.0.encode(w, s);
- }
- }
-
- impl<S: server::Types> DecodeMut<'_, '_, HandleStore<server::MarkedTypes<S>>>
- for Marked<S::$ity, $ity>
- {
- fn decode(r: &mut Reader<'_>, s: &mut HandleStore<server::MarkedTypes<S>>) -> Self {
- s.$ity.copy(handle::Handle::decode(r, &mut ()))
- }
- }
-
- impl<S: server::Types> Encode<HandleStore<server::MarkedTypes<S>>>
- for Marked<S::$ity, $ity>
- {
- fn encode(self, w: &mut Writer, s: &mut HandleStore<server::MarkedTypes<S>>) {
- s.$ity.alloc(self).encode(w, s);
- }
- }
-
- impl<S> DecodeMut<'_, '_, S> for $ity {
- fn decode(r: &mut Reader<'_>, s: &mut S) -> Self {
- $ity(handle::Handle::decode(r, s))
- }
- }
- )*
- }
-}
-define_handles! {
- 'owned:
- FreeFunctions,
- TokenStream,
- TokenStreamBuilder,
- TokenStreamIter,
- Group,
- Literal,
- SourceFile,
- MultiSpan,
- Diagnostic,
-
- 'interned:
- Punct,
- Ident,
- Span,
-}
-
-// FIXME(eddyb) generate these impls by pattern-matching on the
-// names of methods - also could use the presence of `fn drop`
-// to distinguish between 'owned and 'interned, above.
-// Alternatively, special 'modes" could be listed of types in with_api
-// instead of pattern matching on methods, here and in server decl.
-
-impl Clone for TokenStream {
- fn clone(&self) -> Self {
- self.clone()
- }
-}
-
-impl Clone for TokenStreamIter {
- fn clone(&self) -> Self {
- self.clone()
- }
-}
-
-impl Clone for Group {
- fn clone(&self) -> Self {
- self.clone()
- }
-}
-
-impl Clone for Literal {
- fn clone(&self) -> Self {
- self.clone()
- }
-}
-
-impl fmt::Debug for Literal {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- f.debug_struct("Literal")
- // format the kind without quotes, as in `kind: Float`
- .field("kind", &format_args!("{}", &self.debug_kind()))
- .field("symbol", &self.symbol())
- // format `Some("...")` on one line even in {:#?} mode
- .field("suffix", &format_args!("{:?}", &self.suffix()))
- .field("span", &self.span())
- .finish()
- }
-}
-
-impl Clone for SourceFile {
- fn clone(&self) -> Self {
- self.clone()
- }
-}
-
-impl fmt::Debug for Span {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- f.write_str(&self.debug())
- }
-}
-
-macro_rules! define_client_side {
- ($($name:ident {
- $(fn $method:ident($($arg:ident: $arg_ty:ty),* $(,)?) $(-> $ret_ty:ty)*;)*
- }),* $(,)?) => {
- $(impl $name {
- $(pub(crate) fn $method($($arg: $arg_ty),*) $(-> $ret_ty)* {
- Bridge::with(|bridge| {
- let mut b = bridge.cached_buffer.take();
-
- b.clear();
- api_tags::Method::$name(api_tags::$name::$method).encode(&mut b, &mut ());
- reverse_encode!(b; $($arg),*);
-
- b = bridge.dispatch.call(b);
-
- let r = Result::<_, PanicMessage>::decode(&mut &b[..], &mut ());
-
- bridge.cached_buffer = b;
-
- r.unwrap_or_else(|e| panic::resume_unwind(e.into()))
- })
- })*
- })*
- }
-}
-with_api!(self, self, define_client_side);
-
-enum BridgeState<'a> {
- /// No server is currently connected to this client.
- NotConnected,
-
- /// A server is connected and available for requests.
- Connected(Bridge<'a>),
-
- /// Access to the bridge is being exclusively acquired
- /// (e.g., during `BridgeState::with`).
- InUse,
-}
-
-enum BridgeStateL {}
-
-impl<'a> scoped_cell::ApplyL<'a> for BridgeStateL {
- type Out = BridgeState<'a>;
-}
-
-thread_local! {
- static BRIDGE_STATE: scoped_cell::ScopedCell<BridgeStateL> =
- scoped_cell::ScopedCell::new(BridgeState::NotConnected);
-}
-
-impl BridgeState<'_> {
- /// Take exclusive control of the thread-local
- /// `BridgeState`, and pass it to `f`, mutably.
- /// The state will be restored after `f` exits, even
- /// by panic, including modifications made to it by `f`.
- ///
- /// N.B., while `f` is running, the thread-local state
- /// is `BridgeState::InUse`.
- fn with<R>(f: impl FnOnce(&mut BridgeState<'_>) -> R) -> R {
- BRIDGE_STATE.with(|state| {
- state.replace(BridgeState::InUse, |mut state| {
- // FIXME(#52812) pass `f` directly to `replace` when `RefMutL` is gone
- f(&mut state)
- })
- })
- }
-}
-
-impl Bridge<'_> {
- pub(crate) fn is_available() -> bool {
- BridgeState::with(|state| match state {
- BridgeState::Connected(_) | BridgeState::InUse => true,
- BridgeState::NotConnected => false,
- })
- }
-
- fn enter<R>(self, f: impl FnOnce() -> R) -> R {
- let force_show_panics = self.force_show_panics;
- // Hide the default panic output within `proc_macro` expansions.
- // NB. the server can't do this because it may use a different libstd.
- static HIDE_PANICS_DURING_EXPANSION: Once = Once::new();
- HIDE_PANICS_DURING_EXPANSION.call_once(|| {
- let prev = panic::take_hook();
- panic::set_hook(Box::new(move |info| {
- let show = BridgeState::with(|state| match state {
- BridgeState::NotConnected => true,
- BridgeState::Connected(_) | BridgeState::InUse => force_show_panics,
- });
- if show {
- prev(info)
- }
- }));
- });
-
- BRIDGE_STATE.with(|state| state.set(BridgeState::Connected(self), f))
- }
-
- fn with<R>(f: impl FnOnce(&mut Bridge<'_>) -> R) -> R {
- BridgeState::with(|state| match state {
- BridgeState::NotConnected => {
- panic!("procedural macro API is used outside of a procedural macro");
- }
- BridgeState::InUse => {
- panic!("procedural macro API is used while it's already in use");
- }
- BridgeState::Connected(bridge) => f(bridge),
- })
- }
-}
-
-/// A client-side "global object" (usually a function pointer),
-/// which may be using a different `proc_macro` from the one
-/// used by the server, but can be interacted with compatibly.
-///
-/// N.B., `F` must have FFI-friendly memory layout (e.g., a pointer).
-/// The call ABI of function pointers used for `F` doesn't
-/// need to match between server and client, since it's only
-/// passed between them and (eventually) called by the client.
-#[repr(C)]
-#[derive(Copy, Clone)]
-pub struct Client<F> {
- // FIXME(eddyb) use a reference to the `static COUNTERS`, instead of
- // a wrapper `fn` pointer, once `const fn` can reference `static`s.
- pub(super) get_handle_counters: extern "C" fn() -> &'static HandleCounters,
- pub(super) run: extern "C" fn(Bridge<'_>, F) -> Buffer<u8>,
- pub(super) f: F,
-}
-
-/// Client-side helper for handling client panics, entering the bridge,
-/// deserializing input and serializing output.
-// FIXME(eddyb) maybe replace `Bridge::enter` with this?
-fn run_client<A: for<'a, 's> DecodeMut<'a, 's, ()>, R: Encode<()>>(
- mut bridge: Bridge<'_>,
- f: impl FnOnce(A) -> R,
-) -> Buffer<u8> {
- // The initial `cached_buffer` contains the input.
- let mut b = bridge.cached_buffer.take();
-
- panic::catch_unwind(panic::AssertUnwindSafe(|| {
- bridge.enter(|| {
- let reader = &mut &b[..];
- let input = A::decode(reader, &mut ());
-
- // Put the `cached_buffer` back in the `Bridge`, for requests.
- Bridge::with(|bridge| bridge.cached_buffer = b.take());
-
- let output = f(input);
-
- // Take the `cached_buffer` back out, for the output value.
- b = Bridge::with(|bridge| bridge.cached_buffer.take());
-
- // HACK(eddyb) Separate encoding a success value (`Ok(output)`)
- // from encoding a panic (`Err(e: PanicMessage)`) to avoid
- // having handles outside the `bridge.enter(|| ...)` scope, and
- // to catch panics that could happen while encoding the success.
- //
- // Note that panics should be impossible beyond this point, but
- // this is defensively trying to avoid any accidental panicking
- // reaching the `extern "C"` (which should `abort` but might not
- // at the moment, so this is also potentially preventing UB).
- b.clear();
- Ok::<_, ()>(output).encode(&mut b, &mut ());
- })
- }))
- .map_err(PanicMessage::from)
- .unwrap_or_else(|e| {
- b.clear();
- Err::<(), _>(e).encode(&mut b, &mut ());
- });
- b
-}
-
-impl Client<fn(super::super::TokenStream) -> super::super::TokenStream> {
- pub fn expand1(f: fn(super::super::TokenStream) -> super::super::TokenStream) -> Self {
- extern "C" fn run(
- bridge: Bridge<'_>,
- f: impl FnOnce(super::super::TokenStream) -> super::super::TokenStream,
- ) -> Buffer<u8> {
- run_client(bridge, |input| f(super::super::TokenStream(input)).0)
- }
- Client { get_handle_counters: HandleCounters::get, run, f }
- }
-}
-
-impl Client<fn(super::super::TokenStream, super::super::TokenStream) -> super::super::TokenStream> {
- pub fn expand2(
- f: fn(super::super::TokenStream, super::super::TokenStream) -> super::super::TokenStream,
- ) -> Self {
- extern "C" fn run(
- bridge: Bridge<'_>,
- f: impl FnOnce(
- super::super::TokenStream,
- super::super::TokenStream,
- ) -> super::super::TokenStream,
- ) -> Buffer<u8> {
- run_client(bridge, |(input, input2)| {
- f(super::super::TokenStream(input), super::super::TokenStream(input2)).0
- })
- }
- Client { get_handle_counters: HandleCounters::get, run, f }
- }
-}
-
-#[repr(C)]
-#[derive(Copy, Clone)]
-pub enum ProcMacro {
- CustomDerive {
- trait_name: &'static str,
- attributes: &'static [&'static str],
- client: Client<fn(super::super::TokenStream) -> super::super::TokenStream>,
- },
-
- Attr {
- name: &'static str,
- client: Client<
- fn(super::super::TokenStream, super::super::TokenStream) -> super::super::TokenStream,
- >,
- },
-
- Bang {
- name: &'static str,
- client: Client<fn(super::super::TokenStream) -> super::super::TokenStream>,
- },
-}
-
-impl ProcMacro {
- pub fn name(&self) -> &'static str {
- match self {
- ProcMacro::CustomDerive { trait_name, .. } => trait_name,
- ProcMacro::Attr { name, .. } => name,
- ProcMacro::Bang { name, .. } => name,
- }
- }
-
- pub fn custom_derive(
- trait_name: &'static str,
- attributes: &'static [&'static str],
- expand: fn(super::super::TokenStream) -> super::super::TokenStream,
- ) -> Self {
- ProcMacro::CustomDerive { trait_name, attributes, client: Client::expand1(expand) }
- }
-
- pub fn attr(
- name: &'static str,
- expand: fn(
- super::super::TokenStream,
- super::super::TokenStream,
- ) -> super::super::TokenStream,
- ) -> Self {
- ProcMacro::Attr { name, client: Client::expand2(expand) }
- }
-
- pub fn bang(
- name: &'static str,
- expand: fn(super::super::TokenStream) -> super::super::TokenStream,
- ) -> Self {
- ProcMacro::Bang { name, client: Client::expand1(expand) }
- }
-}
diff --git a/src/tools/rust-analyzer/crates/proc-macro-srv/src/abis/abi_1_58/proc_macro/bridge/closure.rs b/src/tools/rust-analyzer/crates/proc-macro-srv/src/abis/abi_1_58/proc_macro/bridge/closure.rs
deleted file mode 100644
index 5be71cc3d..000000000
--- a/src/tools/rust-analyzer/crates/proc-macro-srv/src/abis/abi_1_58/proc_macro/bridge/closure.rs
+++ /dev/null
@@ -1,24 +0,0 @@
-//! Closure type (equivalent to `&mut dyn FnMut(A) -> R`) that's `repr(C)`.
-
-#[repr(C)]
-pub struct Closure<'a, A, R> {
- call: unsafe extern "C" fn(&mut Env, A) -> R,
- env: &'a mut Env,
-}
-
-struct Env;
-
-impl<'a, A, R, F: FnMut(A) -> R> From<&'a mut F> for Closure<'a, A, R> {
- fn from(f: &'a mut F) -> Self {
- unsafe extern "C" fn call<A, R, F: FnMut(A) -> R>(env: &mut Env, arg: A) -> R {
- (*(env as *mut _ as *mut F))(arg)
- }
- Closure { call: call::<A, R, F>, env: unsafe { &mut *(f as *mut _ as *mut Env) } }
- }
-}
-
-impl<'a, A, R> Closure<'a, A, R> {
- pub fn call(&mut self, arg: A) -> R {
- unsafe { (self.call)(self.env, arg) }
- }
-}
diff --git a/src/tools/rust-analyzer/crates/proc-macro-srv/src/abis/abi_1_58/proc_macro/bridge/handle.rs b/src/tools/rust-analyzer/crates/proc-macro-srv/src/abis/abi_1_58/proc_macro/bridge/handle.rs
deleted file mode 100644
index bcbb86812..000000000
--- a/src/tools/rust-analyzer/crates/proc-macro-srv/src/abis/abi_1_58/proc_macro/bridge/handle.rs
+++ /dev/null
@@ -1,70 +0,0 @@
-//! Server-side handles and storage for per-handle data.
-
-use std::collections::{BTreeMap, HashMap};
-use std::hash::Hash;
-use std::num::NonZeroU32;
-use std::ops::{Index, IndexMut};
-use std::sync::atomic::{AtomicUsize, Ordering};
-
-pub(super) type Handle = NonZeroU32;
-
-pub(super) struct OwnedStore<T: 'static> {
- counter: &'static AtomicUsize,
- data: BTreeMap<Handle, T>,
-}
-
-impl<T> OwnedStore<T> {
- pub(super) fn new(counter: &'static AtomicUsize) -> Self {
- // Ensure the handle counter isn't 0, which would panic later,
- // when `NonZeroU32::new` (aka `Handle::new`) is called in `alloc`.
- assert_ne!(counter.load(Ordering::SeqCst), 0);
-
- OwnedStore { counter, data: BTreeMap::new() }
- }
-}
-
-impl<T> OwnedStore<T> {
- pub(super) fn alloc(&mut self, x: T) -> Handle {
- let counter = self.counter.fetch_add(1, Ordering::SeqCst);
- let handle = Handle::new(counter as u32).expect("`proc_macro` handle counter overflowed");
- assert!(self.data.insert(handle, x).is_none());
- handle
- }
-
- pub(super) fn take(&mut self, h: Handle) -> T {
- self.data.remove(&h).expect("use-after-free in `proc_macro` handle")
- }
-}
-
-impl<T> Index<Handle> for OwnedStore<T> {
- type Output = T;
- fn index(&self, h: Handle) -> &T {
- self.data.get(&h).expect("use-after-free in `proc_macro` handle")
- }
-}
-
-impl<T> IndexMut<Handle> for OwnedStore<T> {
- fn index_mut(&mut self, h: Handle) -> &mut T {
- self.data.get_mut(&h).expect("use-after-free in `proc_macro` handle")
- }
-}
-
-pub(super) struct InternedStore<T: 'static> {
- owned: OwnedStore<T>,
- interner: HashMap<T, Handle>,
-}
-
-impl<T: Copy + Eq + Hash> InternedStore<T> {
- pub(super) fn new(counter: &'static AtomicUsize) -> Self {
- InternedStore { owned: OwnedStore::new(counter), interner: HashMap::new() }
- }
-
- pub(super) fn alloc(&mut self, x: T) -> Handle {
- let owned = &mut self.owned;
- *self.interner.entry(x).or_insert_with(|| owned.alloc(x))
- }
-
- pub(super) fn copy(&mut self, h: Handle) -> T {
- self.owned[h]
- }
-}
diff --git a/src/tools/rust-analyzer/crates/proc-macro-srv/src/abis/abi_1_58/proc_macro/bridge/mod.rs b/src/tools/rust-analyzer/crates/proc-macro-srv/src/abis/abi_1_58/proc_macro/bridge/mod.rs
deleted file mode 100644
index b7968c529..000000000
--- a/src/tools/rust-analyzer/crates/proc-macro-srv/src/abis/abi_1_58/proc_macro/bridge/mod.rs
+++ /dev/null
@@ -1,429 +0,0 @@
-//! Internal interface for communicating between a `proc_macro` client
-//! (a proc macro crate) and a `proc_macro` server (a compiler front-end).
-//!
-//! Serialization (with C ABI buffers) and unique integer handles are employed
-//! to allow safely interfacing between two copies of `proc_macro` built
-//! (from the same source) by different compilers with potentially mismatching
-//! Rust ABIs (e.g., stage0/bin/rustc vs stage1/bin/rustc during bootstrap).
-
-#![deny(unsafe_code)]
-
-pub use super::{Delimiter, Level, LineColumn, Spacing};
-use std::fmt;
-use std::hash::Hash;
-use std::marker;
-use std::mem;
-use std::ops::Bound;
-use std::panic;
-use std::sync::atomic::AtomicUsize;
-use std::sync::Once;
-use std::thread;
-
-/// Higher-order macro describing the server RPC API, allowing automatic
-/// generation of type-safe Rust APIs, both client-side and server-side.
-///
-/// `with_api!(MySelf, my_self, my_macro)` expands to:
-/// ```rust,ignore (pseudo-code)
-/// my_macro! {
-/// // ...
-/// Literal {
-/// // ...
-/// fn character(ch: char) -> MySelf::Literal;
-/// // ...
-/// fn span(my_self: &MySelf::Literal) -> MySelf::Span;
-/// fn set_span(my_self: &mut MySelf::Literal, span: MySelf::Span);
-/// },
-/// // ...
-/// }
-/// ```
-///
-/// The first two arguments serve to customize the arguments names
-/// and argument/return types, to enable several different usecases:
-///
-/// If `my_self` is just `self`, then each `fn` signature can be used
-/// as-is for a method. If it's anything else (`self_` in practice),
-/// then the signatures don't have a special `self` argument, and
-/// can, therefore, have a different one introduced.
-///
-/// If `MySelf` is just `Self`, then the types are only valid inside
-/// a trait or a trait impl, where the trait has associated types
-/// for each of the API types. If non-associated types are desired,
-/// a module name (`self` in practice) can be used instead of `Self`.
-macro_rules! with_api {
- ($S:ident, $self:ident, $m:ident) => {
- $m! {
- FreeFunctions {
- fn drop($self: $S::FreeFunctions);
- fn track_env_var(var: &str, value: Option<&str>);
- fn track_path(path: &str);
- },
- TokenStream {
- fn drop($self: $S::TokenStream);
- fn clone($self: &$S::TokenStream) -> $S::TokenStream;
- fn new() -> $S::TokenStream;
- fn is_empty($self: &$S::TokenStream) -> bool;
- fn expand_expr($self: &$S::TokenStream) -> Result<$S::TokenStream, ()>;
- fn from_str(src: &str) -> $S::TokenStream;
- fn to_string($self: &$S::TokenStream) -> String;
- fn from_token_tree(
- tree: TokenTree<$S::Group, $S::Punct, $S::Ident, $S::Literal>,
- ) -> $S::TokenStream;
- fn into_iter($self: $S::TokenStream) -> $S::TokenStreamIter;
- },
- TokenStreamBuilder {
- fn drop($self: $S::TokenStreamBuilder);
- fn new() -> $S::TokenStreamBuilder;
- fn push($self: &mut $S::TokenStreamBuilder, stream: $S::TokenStream);
- fn build($self: $S::TokenStreamBuilder) -> $S::TokenStream;
- },
- TokenStreamIter {
- fn drop($self: $S::TokenStreamIter);
- fn clone($self: &$S::TokenStreamIter) -> $S::TokenStreamIter;
- fn next(
- $self: &mut $S::TokenStreamIter,
- ) -> Option<TokenTree<$S::Group, $S::Punct, $S::Ident, $S::Literal>>;
- },
- Group {
- fn drop($self: $S::Group);
- fn clone($self: &$S::Group) -> $S::Group;
- fn new(delimiter: Delimiter, stream: $S::TokenStream) -> $S::Group;
- fn delimiter($self: &$S::Group) -> Delimiter;
- fn stream($self: &$S::Group) -> $S::TokenStream;
- fn span($self: &$S::Group) -> $S::Span;
- fn span_open($self: &$S::Group) -> $S::Span;
- fn span_close($self: &$S::Group) -> $S::Span;
- fn set_span($self: &mut $S::Group, span: $S::Span);
- },
- Punct {
- fn new(ch: char, spacing: Spacing) -> $S::Punct;
- fn as_char($self: $S::Punct) -> char;
- fn spacing($self: $S::Punct) -> Spacing;
- fn span($self: $S::Punct) -> $S::Span;
- fn with_span($self: $S::Punct, span: $S::Span) -> $S::Punct;
- },
- Ident {
- fn new(string: &str, span: $S::Span, is_raw: bool) -> $S::Ident;
- fn span($self: $S::Ident) -> $S::Span;
- fn with_span($self: $S::Ident, span: $S::Span) -> $S::Ident;
- },
- Literal {
- fn drop($self: $S::Literal);
- fn clone($self: &$S::Literal) -> $S::Literal;
- fn from_str(s: &str) -> Result<$S::Literal, ()>;
- fn to_string($self: &$S::Literal) -> String;
- fn debug_kind($self: &$S::Literal) -> String;
- fn symbol($self: &$S::Literal) -> String;
- fn suffix($self: &$S::Literal) -> Option<String>;
- fn integer(n: &str) -> $S::Literal;
- fn typed_integer(n: &str, kind: &str) -> $S::Literal;
- fn float(n: &str) -> $S::Literal;
- fn f32(n: &str) -> $S::Literal;
- fn f64(n: &str) -> $S::Literal;
- fn string(string: &str) -> $S::Literal;
- fn character(ch: char) -> $S::Literal;
- fn byte_string(bytes: &[u8]) -> $S::Literal;
- fn span($self: &$S::Literal) -> $S::Span;
- fn set_span($self: &mut $S::Literal, span: $S::Span);
- fn subspan(
- $self: &$S::Literal,
- start: Bound<usize>,
- end: Bound<usize>,
- ) -> Option<$S::Span>;
- },
- SourceFile {
- fn drop($self: $S::SourceFile);
- fn clone($self: &$S::SourceFile) -> $S::SourceFile;
- fn eq($self: &$S::SourceFile, other: &$S::SourceFile) -> bool;
- fn path($self: &$S::SourceFile) -> String;
- fn is_real($self: &$S::SourceFile) -> bool;
- },
- MultiSpan {
- fn drop($self: $S::MultiSpan);
- fn new() -> $S::MultiSpan;
- fn push($self: &mut $S::MultiSpan, span: $S::Span);
- },
- Diagnostic {
- fn drop($self: $S::Diagnostic);
- fn new(level: Level, msg: &str, span: $S::MultiSpan) -> $S::Diagnostic;
- fn sub(
- $self: &mut $S::Diagnostic,
- level: Level,
- msg: &str,
- span: $S::MultiSpan,
- );
- fn emit($self: $S::Diagnostic);
- },
- Span {
- fn debug($self: $S::Span) -> String;
- fn def_site() -> $S::Span;
- fn call_site() -> $S::Span;
- fn mixed_site() -> $S::Span;
- fn source_file($self: $S::Span) -> $S::SourceFile;
- fn parent($self: $S::Span) -> Option<$S::Span>;
- 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<String>;
- fn save_span($self: $S::Span) -> usize;
- fn recover_proc_macro_span(id: usize) -> $S::Span;
- },
- }
- };
-}
-
-// FIXME(eddyb) this calls `encode` for each argument, but in reverse,
-// to avoid borrow conflicts from borrows started by `&mut` arguments.
-macro_rules! reverse_encode {
- ($writer:ident;) => {};
- ($writer:ident; $first:ident $(, $rest:ident)*) => {
- reverse_encode!($writer; $($rest),*);
- $first.encode(&mut $writer, &mut ());
- }
-}
-
-// FIXME(eddyb) this calls `decode` for each argument, but in reverse,
-// to avoid borrow conflicts from borrows started by `&mut` arguments.
-macro_rules! reverse_decode {
- ($reader:ident, $s:ident;) => {};
- ($reader:ident, $s:ident; $first:ident: $first_ty:ty $(, $rest:ident: $rest_ty:ty)*) => {
- reverse_decode!($reader, $s; $($rest: $rest_ty),*);
- let $first = <$first_ty>::decode(&mut $reader, $s);
- }
-}
-
-#[allow(unsafe_code)]
-mod buffer;
-#[forbid(unsafe_code)]
-pub mod client;
-#[allow(unsafe_code)]
-mod closure;
-#[forbid(unsafe_code)]
-mod handle;
-#[macro_use]
-#[forbid(unsafe_code)]
-mod rpc;
-#[allow(unsafe_code)]
-mod scoped_cell;
-#[forbid(unsafe_code)]
-pub mod server;
-
-use buffer::Buffer;
-pub use rpc::PanicMessage;
-use rpc::{Decode, DecodeMut, Encode, Reader, Writer};
-
-/// An active connection between a server and a client.
-/// The server creates the bridge (`Bridge::run_server` in `server.rs`),
-/// then passes it to the client through the function pointer in the `run`
-/// field of `client::Client`. The client holds its copy of the `Bridge`
-/// in TLS during its execution (`Bridge::{enter, with}` in `client.rs`).
-#[repr(C)]
-pub struct Bridge<'a> {
- /// Reusable buffer (only `clear`-ed, never shrunk), primarily
- /// used for making requests, but also for passing input to client.
- cached_buffer: Buffer<u8>,
-
- /// Server-side function that the client uses to make requests.
- dispatch: closure::Closure<'a, Buffer<u8>, Buffer<u8>>,
-
- /// If 'true', always invoke the default panic hook
- force_show_panics: bool,
-}
-
-#[forbid(unsafe_code)]
-#[allow(non_camel_case_types)]
-mod api_tags {
- use super::rpc::{DecodeMut, Encode, Reader, Writer};
-
- macro_rules! declare_tags {
- ($($name:ident {
- $(fn $method:ident($($arg:ident: $arg_ty:ty),* $(,)?) $(-> $ret_ty:ty)*;)*
- }),* $(,)?) => {
- $(
- pub(super) enum $name {
- $($method),*
- }
- rpc_encode_decode!(enum $name { $($method),* });
- )*
-
-
- pub(super) enum Method {
- $($name($name)),*
- }
- rpc_encode_decode!(enum Method { $($name(m)),* });
- }
- }
- with_api!(self, self, declare_tags);
-}
-
-/// Helper to wrap associated types to allow trait impl dispatch.
-/// That is, normally a pair of impls for `T::Foo` and `T::Bar`
-/// can overlap, but if the impls are, instead, on types like
-/// `Marked<T::Foo, Foo>` and `Marked<T::Bar, Bar>`, they can't.
-trait Mark {
- type Unmarked;
- fn mark(unmarked: Self::Unmarked) -> Self;
-}
-
-/// Unwrap types wrapped by `Mark::mark` (see `Mark` for details).
-trait Unmark {
- type Unmarked;
- fn unmark(self) -> Self::Unmarked;
-}
-
-#[derive(Copy, Clone, PartialEq, Eq, Hash)]
-struct Marked<T, M> {
- value: T,
- _marker: marker::PhantomData<M>,
-}
-
-impl<T, M> Mark for Marked<T, M> {
- type Unmarked = T;
- fn mark(unmarked: Self::Unmarked) -> Self {
- Marked { value: unmarked, _marker: marker::PhantomData }
- }
-}
-impl<T, M> Unmark for Marked<T, M> {
- type Unmarked = T;
- fn unmark(self) -> Self::Unmarked {
- self.value
- }
-}
-impl<'a, T, M> Unmark for &'a Marked<T, M> {
- type Unmarked = &'a T;
- fn unmark(self) -> Self::Unmarked {
- &self.value
- }
-}
-impl<'a, T, M> Unmark for &'a mut Marked<T, M> {
- type Unmarked = &'a mut T;
- fn unmark(self) -> Self::Unmarked {
- &mut self.value
- }
-}
-
-impl<T: Mark> Mark for Option<T> {
- type Unmarked = Option<T::Unmarked>;
- fn mark(unmarked: Self::Unmarked) -> Self {
- unmarked.map(T::mark)
- }
-}
-impl<T: Unmark> Unmark for Option<T> {
- type Unmarked = Option<T::Unmarked>;
- fn unmark(self) -> Self::Unmarked {
- self.map(T::unmark)
- }
-}
-
-impl<T: Mark, E: Mark> Mark for Result<T, E> {
- type Unmarked = Result<T::Unmarked, E::Unmarked>;
- fn mark(unmarked: Self::Unmarked) -> Self {
- unmarked.map(T::mark).map_err(E::mark)
- }
-}
-impl<T: Unmark, E: Unmark> Unmark for Result<T, E> {
- type Unmarked = Result<T::Unmarked, E::Unmarked>;
- fn unmark(self) -> Self::Unmarked {
- self.map(T::unmark).map_err(E::unmark)
- }
-}
-
-macro_rules! mark_noop {
- ($($ty:ty),* $(,)?) => {
- $(
- impl Mark for $ty {
- type Unmarked = Self;
- fn mark(unmarked: Self::Unmarked) -> Self {
- unmarked
- }
- }
- impl Unmark for $ty {
- type Unmarked = Self;
- fn unmark(self) -> Self::Unmarked {
- self
- }
- }
- )*
- }
-}
-mark_noop! {
- (),
- bool,
- char,
- &'_ [u8],
- &'_ str,
- String,
- usize,
- Delimiter,
- Level,
- LineColumn,
- Spacing,
- Bound<usize>,
-}
-
-rpc_encode_decode!(
- enum Delimiter {
- Parenthesis,
- Brace,
- Bracket,
- None,
- }
-);
-rpc_encode_decode!(
- enum Level {
- Error,
- Warning,
- Note,
- Help,
- }
-);
-rpc_encode_decode!(struct LineColumn { line, column });
-rpc_encode_decode!(
- enum Spacing {
- Alone,
- Joint,
- }
-);
-
-#[derive(Clone)]
-pub enum TokenTree<G, P, I, L> {
- Group(G),
- Punct(P),
- Ident(I),
- Literal(L),
-}
-
-impl<G: Mark, P: Mark, I: Mark, L: Mark> Mark for TokenTree<G, P, I, L> {
- type Unmarked = TokenTree<G::Unmarked, P::Unmarked, I::Unmarked, L::Unmarked>;
- fn mark(unmarked: Self::Unmarked) -> Self {
- match unmarked {
- TokenTree::Group(tt) => TokenTree::Group(G::mark(tt)),
- TokenTree::Punct(tt) => TokenTree::Punct(P::mark(tt)),
- TokenTree::Ident(tt) => TokenTree::Ident(I::mark(tt)),
- TokenTree::Literal(tt) => TokenTree::Literal(L::mark(tt)),
- }
- }
-}
-impl<G: Unmark, P: Unmark, I: Unmark, L: Unmark> Unmark for TokenTree<G, P, I, L> {
- type Unmarked = TokenTree<G::Unmarked, P::Unmarked, I::Unmarked, L::Unmarked>;
- fn unmark(self) -> Self::Unmarked {
- match self {
- TokenTree::Group(tt) => TokenTree::Group(tt.unmark()),
- TokenTree::Punct(tt) => TokenTree::Punct(tt.unmark()),
- TokenTree::Ident(tt) => TokenTree::Ident(tt.unmark()),
- TokenTree::Literal(tt) => TokenTree::Literal(tt.unmark()),
- }
- }
-}
-
-rpc_encode_decode!(
- enum TokenTree<G, P, I, L> {
- Group(tt),
- Punct(tt),
- Ident(tt),
- Literal(tt),
- }
-);
diff --git a/src/tools/rust-analyzer/crates/proc-macro-srv/src/abis/abi_1_58/proc_macro/bridge/rpc.rs b/src/tools/rust-analyzer/crates/proc-macro-srv/src/abis/abi_1_58/proc_macro/bridge/rpc.rs
deleted file mode 100644
index d50564d01..000000000
--- a/src/tools/rust-analyzer/crates/proc-macro-srv/src/abis/abi_1_58/proc_macro/bridge/rpc.rs
+++ /dev/null
@@ -1,305 +0,0 @@
-//! Serialization for client-server communication.
-
-use std::any::Any;
-use std::char;
-use std::io::Write;
-use std::num::NonZeroU32;
-use std::ops::Bound;
-use std::str;
-
-pub(super) type Writer = super::buffer::Buffer<u8>;
-
-pub(super) trait Encode<S>: Sized {
- fn encode(self, w: &mut Writer, s: &mut S);
-}
-
-pub(super) type Reader<'a> = &'a [u8];
-
-pub(super) trait Decode<'a, 's, S>: Sized {
- fn decode(r: &mut Reader<'a>, s: &'s S) -> Self;
-}
-
-pub(super) trait DecodeMut<'a, 's, S>: Sized {
- fn decode(r: &mut Reader<'a>, s: &'s mut S) -> Self;
-}
-
-macro_rules! rpc_encode_decode {
- (le $ty:ty) => {
- impl<S> Encode<S> for $ty {
- fn encode(self, w: &mut Writer, _: &mut S) {
- w.extend_from_array(&self.to_le_bytes());
- }
- }
-
- impl<S> DecodeMut<'_, '_, S> for $ty {
- fn decode(r: &mut Reader<'_>, _: &mut S) -> Self {
- const N: usize = ::std::mem::size_of::<$ty>();
-
- let mut bytes = [0; N];
- bytes.copy_from_slice(&r[..N]);
- *r = &r[N..];
-
- Self::from_le_bytes(bytes)
- }
- }
- };
- (struct $name:ident { $($field:ident),* $(,)? }) => {
- impl<S> Encode<S> for $name {
- fn encode(self, w: &mut Writer, s: &mut S) {
- $(self.$field.encode(w, s);)*
- }
- }
-
- impl<S> DecodeMut<'_, '_, S> for $name {
- fn decode(r: &mut Reader<'_>, s: &mut S) -> Self {
- $name {
- $($field: DecodeMut::decode(r, s)),*
- }
- }
- }
- };
- (enum $name:ident $(<$($T:ident),+>)? { $($variant:ident $(($field:ident))*),* $(,)? }) => {
- impl<S, $($($T: Encode<S>),+)?> Encode<S> for $name $(<$($T),+>)? {
- fn encode(self, w: &mut Writer, s: &mut S) {
- // HACK(eddyb): `Tag` enum duplicated between the
- // two impls as there's no other place to stash it.
- #[allow(non_upper_case_globals)]
- mod tag {
- #[repr(u8)] enum Tag { $($variant),* }
-
- $(pub const $variant: u8 = Tag::$variant as u8;)*
- }
-
- match self {
- $($name::$variant $(($field))* => {
- tag::$variant.encode(w, s);
- $($field.encode(w, s);)*
- })*
- }
- }
- }
-
- impl<'a, S, $($($T: for<'s> DecodeMut<'a, 's, S>),+)?> DecodeMut<'a, '_, S>
- for $name $(<$($T),+>)?
- {
- fn decode(r: &mut Reader<'a>, s: &mut S) -> Self {
- // HACK(eddyb): `Tag` enum duplicated between the
- // two impls as there's no other place to stash it.
- #[allow(non_upper_case_globals)]
- mod tag {
- #[repr(u8)] enum Tag { $($variant),* }
-
- $(pub const $variant: u8 = Tag::$variant as u8;)*
- }
-
- match u8::decode(r, s) {
- $(tag::$variant => {
- $(let $field = DecodeMut::decode(r, s);)*
- $name::$variant $(($field))*
- })*
- _ => unreachable!(),
- }
- }
- }
- }
-}
-
-impl<S> Encode<S> for () {
- fn encode(self, _: &mut Writer, _: &mut S) {}
-}
-
-impl<S> DecodeMut<'_, '_, S> for () {
- fn decode(_: &mut Reader<'_>, _: &mut S) -> Self {}
-}
-
-impl<S> Encode<S> for u8 {
- fn encode(self, w: &mut Writer, _: &mut S) {
- w.push(self);
- }
-}
-
-impl<S> DecodeMut<'_, '_, S> for u8 {
- fn decode(r: &mut Reader<'_>, _: &mut S) -> Self {
- let x = r[0];
- *r = &r[1..];
- x
- }
-}
-
-rpc_encode_decode!(le u32);
-rpc_encode_decode!(le usize);
-
-impl<S> Encode<S> for bool {
- fn encode(self, w: &mut Writer, s: &mut S) {
- (self as u8).encode(w, s);
- }
-}
-
-impl<S> DecodeMut<'_, '_, S> for bool {
- fn decode(r: &mut Reader<'_>, s: &mut S) -> Self {
- match u8::decode(r, s) {
- 0 => false,
- 1 => true,
- _ => unreachable!(),
- }
- }
-}
-
-impl<S> Encode<S> for char {
- fn encode(self, w: &mut Writer, s: &mut S) {
- (self as u32).encode(w, s);
- }
-}
-
-impl<S> DecodeMut<'_, '_, S> for char {
- fn decode(r: &mut Reader<'_>, s: &mut S) -> Self {
- char::from_u32(u32::decode(r, s)).unwrap()
- }
-}
-
-impl<S> Encode<S> for NonZeroU32 {
- fn encode(self, w: &mut Writer, s: &mut S) {
- self.get().encode(w, s);
- }
-}
-
-impl<S> DecodeMut<'_, '_, S> for NonZeroU32 {
- fn decode(r: &mut Reader<'_>, s: &mut S) -> Self {
- Self::new(u32::decode(r, s)).unwrap()
- }
-}
-
-impl<S, A: Encode<S>, B: Encode<S>> Encode<S> for (A, B) {
- fn encode(self, w: &mut Writer, s: &mut S) {
- self.0.encode(w, s);
- self.1.encode(w, s);
- }
-}
-
-impl<'a, S, A: for<'s> DecodeMut<'a, 's, S>, B: for<'s> DecodeMut<'a, 's, S>> DecodeMut<'a, '_, S>
- for (A, B)
-{
- fn decode(r: &mut Reader<'a>, s: &mut S) -> Self {
- (DecodeMut::decode(r, s), DecodeMut::decode(r, s))
- }
-}
-
-rpc_encode_decode!(
- enum Bound<T> {
- Included(x),
- Excluded(x),
- Unbounded,
- }
-);
-
-rpc_encode_decode!(
- enum Option<T> {
- None,
- Some(x),
- }
-);
-
-rpc_encode_decode!(
- enum Result<T, E> {
- Ok(x),
- Err(e),
- }
-);
-
-impl<S> Encode<S> for &[u8] {
- fn encode(self, w: &mut Writer, s: &mut S) {
- self.len().encode(w, s);
- w.write_all(self).unwrap();
- }
-}
-
-impl<'a, S> DecodeMut<'a, '_, S> for &'a [u8] {
- fn decode(r: &mut Reader<'a>, s: &mut S) -> Self {
- let len = usize::decode(r, s);
- let xs = &r[..len];
- *r = &r[len..];
- xs
- }
-}
-
-impl<S> Encode<S> for &str {
- fn encode(self, w: &mut Writer, s: &mut S) {
- self.as_bytes().encode(w, s);
- }
-}
-
-impl<'a, S> DecodeMut<'a, '_, S> for &'a str {
- fn decode(r: &mut Reader<'a>, s: &mut S) -> Self {
- str::from_utf8(<&[u8]>::decode(r, s)).unwrap()
- }
-}
-
-impl<S> Encode<S> for String {
- fn encode(self, w: &mut Writer, s: &mut S) {
- self[..].encode(w, s);
- }
-}
-
-impl<S> DecodeMut<'_, '_, S> for String {
- fn decode(r: &mut Reader<'_>, s: &mut S) -> Self {
- <&str>::decode(r, s).to_string()
- }
-}
-
-/// Simplified version of panic payloads, ignoring
-/// types other than `&'static str` and `String`.
-pub enum PanicMessage {
- StaticStr(&'static str),
- String(String),
- Unknown,
-}
-
-impl From<Box<dyn Any + Send>> for PanicMessage {
- fn from(payload: Box<dyn Any + Send + 'static>) -> Self {
- if let Some(s) = payload.downcast_ref::<&'static str>() {
- return PanicMessage::StaticStr(s);
- }
- if let Ok(s) = payload.downcast::<String>() {
- return PanicMessage::String(*s);
- }
- PanicMessage::Unknown
- }
-}
-
-impl Into<Box<dyn Any + Send>> for PanicMessage {
- fn into(self) -> Box<dyn Any + Send> {
- match self {
- PanicMessage::StaticStr(s) => Box::new(s),
- PanicMessage::String(s) => Box::new(s),
- PanicMessage::Unknown => {
- struct UnknownPanicMessage;
- Box::new(UnknownPanicMessage)
- }
- }
- }
-}
-
-impl PanicMessage {
- pub fn as_str(&self) -> Option<&str> {
- match self {
- PanicMessage::StaticStr(s) => Some(s),
- PanicMessage::String(s) => Some(s),
- PanicMessage::Unknown => None,
- }
- }
-}
-
-impl<S> Encode<S> for PanicMessage {
- fn encode(self, w: &mut Writer, s: &mut S) {
- self.as_str().encode(w, s);
- }
-}
-
-impl<S> DecodeMut<'_, '_, S> for PanicMessage {
- fn decode(r: &mut Reader<'_>, s: &mut S) -> Self {
- match Option::<String>::decode(r, s) {
- Some(s) => PanicMessage::String(s),
- None => PanicMessage::Unknown,
- }
- }
-}
diff --git a/src/tools/rust-analyzer/crates/proc-macro-srv/src/abis/abi_1_58/proc_macro/bridge/scoped_cell.rs b/src/tools/rust-analyzer/crates/proc-macro-srv/src/abis/abi_1_58/proc_macro/bridge/scoped_cell.rs
deleted file mode 100644
index b0c2e5b9c..000000000
--- a/src/tools/rust-analyzer/crates/proc-macro-srv/src/abis/abi_1_58/proc_macro/bridge/scoped_cell.rs
+++ /dev/null
@@ -1,81 +0,0 @@
-//! `Cell` variant for (scoped) existential lifetimes.
-
-use std::cell::Cell;
-use std::mem;
-use std::ops::{Deref, DerefMut};
-
-/// Type lambda application, with a lifetime.
-#[allow(unused_lifetimes)]
-pub trait ApplyL<'a> {
- type Out;
-}
-
-/// Type lambda taking a lifetime, i.e., `Lifetime -> Type`.
-pub trait LambdaL: for<'a> ApplyL<'a> {}
-
-impl<T: for<'a> ApplyL<'a>> LambdaL for T {}
-
-// HACK(eddyb) work around projection limitations with a newtype
-// FIXME(#52812) replace with `&'a mut <T as ApplyL<'b>>::Out`
-pub struct RefMutL<'a, 'b, T: LambdaL>(&'a mut <T as ApplyL<'b>>::Out);
-
-impl<'a, 'b, T: LambdaL> Deref for RefMutL<'a, 'b, T> {
- type Target = <T as ApplyL<'b>>::Out;
- fn deref(&self) -> &Self::Target {
- self.0
- }
-}
-
-impl<'a, 'b, T: LambdaL> DerefMut for RefMutL<'a, 'b, T> {
- fn deref_mut(&mut self) -> &mut Self::Target {
- self.0
- }
-}
-
-pub struct ScopedCell<T: LambdaL>(Cell<<T as ApplyL<'static>>::Out>);
-
-impl<T: LambdaL> ScopedCell<T> {
- pub fn new(value: <T as ApplyL<'static>>::Out) -> Self {
- ScopedCell(Cell::new(value))
- }
-
- /// Sets the value in `self` to `replacement` while
- /// running `f`, which gets the old value, mutably.
- /// The old value will be restored after `f` exits, even
- /// by panic, including modifications made to it by `f`.
- pub fn replace<'a, R>(
- &self,
- replacement: <T as ApplyL<'a>>::Out,
- f: impl for<'b, 'c> FnOnce(RefMutL<'b, 'c, T>) -> R,
- ) -> R {
- /// Wrapper that ensures that the cell always gets filled
- /// (with the original state, optionally changed by `f`),
- /// even if `f` had panicked.
- struct PutBackOnDrop<'a, T: LambdaL> {
- cell: &'a ScopedCell<T>,
- value: Option<<T as ApplyL<'static>>::Out>,
- }
-
- impl<'a, T: LambdaL> Drop for PutBackOnDrop<'a, T> {
- fn drop(&mut self) {
- self.cell.0.set(self.value.take().unwrap());
- }
- }
-
- let mut put_back_on_drop = PutBackOnDrop {
- cell: self,
- value: Some(self.0.replace(unsafe {
- let erased = mem::transmute_copy(&replacement);
- mem::forget(replacement);
- erased
- })),
- };
-
- f(RefMutL(put_back_on_drop.value.as_mut().unwrap()))
- }
-
- /// Sets the value in `self` to `value` while running `f`.
- pub fn set<R>(&self, value: <T as ApplyL<'_>>::Out, f: impl FnOnce() -> R) -> R {
- self.replace(value, |_| f())
- }
-}
diff --git a/src/tools/rust-analyzer/crates/proc-macro-srv/src/abis/abi_1_58/proc_macro/bridge/server.rs b/src/tools/rust-analyzer/crates/proc-macro-srv/src/abis/abi_1_58/proc_macro/bridge/server.rs
deleted file mode 100644
index 06a197913..000000000
--- a/src/tools/rust-analyzer/crates/proc-macro-srv/src/abis/abi_1_58/proc_macro/bridge/server.rs
+++ /dev/null
@@ -1,352 +0,0 @@
-//! Server-side traits.
-
-use super::*;
-
-// FIXME(eddyb) generate the definition of `HandleStore` in `server.rs`.
-use super::client::HandleStore;
-
-/// Declare an associated item of one of the traits below, optionally
-/// adjusting it (i.e., adding bounds to types and default bodies to methods).
-macro_rules! associated_item {
- (type FreeFunctions) =>
- (type FreeFunctions: 'static;);
- (type TokenStream) =>
- (type TokenStream: 'static + Clone;);
- (type TokenStreamBuilder) =>
- (type TokenStreamBuilder: 'static;);
- (type TokenStreamIter) =>
- (type TokenStreamIter: 'static + Clone;);
- (type Group) =>
- (type Group: 'static + Clone;);
- (type Punct) =>
- (type Punct: 'static + Copy + Eq + Hash;);
- (type Ident) =>
- (type Ident: 'static + Copy + Eq + Hash;);
- (type Literal) =>
- (type Literal: 'static + Clone;);
- (type SourceFile) =>
- (type SourceFile: 'static + Clone;);
- (type MultiSpan) =>
- (type MultiSpan: 'static;);
- (type Diagnostic) =>
- (type Diagnostic: 'static;);
- (type Span) =>
- (type Span: 'static + Copy + Eq + Hash;);
- (fn drop(&mut self, $arg:ident: $arg_ty:ty)) =>
- (fn drop(&mut self, $arg: $arg_ty) { mem::drop($arg) });
- (fn clone(&mut self, $arg:ident: $arg_ty:ty) -> $ret_ty:ty) =>
- (fn clone(&mut self, $arg: $arg_ty) -> $ret_ty { $arg.clone() });
- ($($item:tt)*) => ($($item)*;)
-}
-
-macro_rules! declare_server_traits {
- ($($name:ident {
- $(fn $method:ident($($arg:ident: $arg_ty:ty),* $(,)?) $(-> $ret_ty:ty)?;)*
- }),* $(,)?) => {
- pub trait Types {
- $(associated_item!(type $name);)*
- }
-
- $(pub trait $name: Types {
- $(associated_item!(fn $method(&mut self, $($arg: $arg_ty),*) $(-> $ret_ty)?);)*
- })*
-
- pub trait Server: Types $(+ $name)* {}
- impl<S: Types $(+ $name)*> Server for S {}
- }
-}
-with_api!(Self, self_, declare_server_traits);
-
-pub(super) struct MarkedTypes<S: Types>(S);
-
-macro_rules! define_mark_types_impls {
- ($($name:ident {
- $(fn $method:ident($($arg:ident: $arg_ty:ty),* $(,)?) $(-> $ret_ty:ty)?;)*
- }),* $(,)?) => {
- impl<S: Types> Types for MarkedTypes<S> {
- $(type $name = Marked<S::$name, client::$name>;)*
- }
-
- $(impl<S: $name> $name for MarkedTypes<S> {
- $(fn $method(&mut self, $($arg: $arg_ty),*) $(-> $ret_ty)? {
- <_>::mark($name::$method(&mut self.0, $($arg.unmark()),*))
- })*
- })*
- }
-}
-with_api!(Self, self_, define_mark_types_impls);
-
-struct Dispatcher<S: Types> {
- handle_store: HandleStore<S>,
- server: S,
-}
-
-macro_rules! define_dispatcher_impl {
- ($($name:ident {
- $(fn $method:ident($($arg:ident: $arg_ty:ty),* $(,)?) $(-> $ret_ty:ty)?;)*
- }),* $(,)?) => {
- // FIXME(eddyb) `pub` only for `ExecutionStrategy` below.
- pub trait DispatcherTrait {
- // HACK(eddyb) these are here to allow `Self::$name` to work below.
- $(type $name;)*
- fn dispatch(&mut self, b: Buffer<u8>) -> Buffer<u8>;
- }
-
- impl<S: Server> DispatcherTrait for Dispatcher<MarkedTypes<S>> {
- $(type $name = <MarkedTypes<S> as Types>::$name;)*
- fn dispatch(&mut self, mut b: Buffer<u8>) -> Buffer<u8> {
- let Dispatcher { handle_store, server } = self;
-
- let mut reader = &b[..];
- match api_tags::Method::decode(&mut reader, &mut ()) {
- $(api_tags::Method::$name(m) => match m {
- $(api_tags::$name::$method => {
- let mut call_method = || {
- reverse_decode!(reader, handle_store; $($arg: $arg_ty),*);
- $name::$method(server, $($arg),*)
- };
- // HACK(eddyb) don't use `panic::catch_unwind` in a panic.
- // If client and server happen to use the same `libstd`,
- // `catch_unwind` asserts that the panic counter was 0,
- // even when the closure passed to it didn't panic.
- let r = if thread::panicking() {
- Ok(call_method())
- } else {
- panic::catch_unwind(panic::AssertUnwindSafe(call_method))
- .map_err(PanicMessage::from)
- };
-
- b.clear();
- r.encode(&mut b, handle_store);
- })*
- }),*
- }
- b
- }
- }
- }
-}
-with_api!(Self, self_, define_dispatcher_impl);
-
-pub trait ExecutionStrategy {
- fn run_bridge_and_client<D: Copy + Send + 'static>(
- &self,
- dispatcher: &mut impl DispatcherTrait,
- input: Buffer<u8>,
- run_client: extern "C" fn(Bridge<'_>, D) -> Buffer<u8>,
- client_data: D,
- force_show_panics: bool,
- ) -> Buffer<u8>;
-}
-
-pub struct SameThread;
-
-impl ExecutionStrategy for SameThread {
- fn run_bridge_and_client<D: Copy + Send + 'static>(
- &self,
- dispatcher: &mut impl DispatcherTrait,
- input: Buffer<u8>,
- run_client: extern "C" fn(Bridge<'_>, D) -> Buffer<u8>,
- client_data: D,
- force_show_panics: bool,
- ) -> Buffer<u8> {
- let mut dispatch = |b| dispatcher.dispatch(b);
-
- run_client(
- Bridge { cached_buffer: input, dispatch: (&mut dispatch).into(), force_show_panics },
- client_data,
- )
- }
-}
-
-// NOTE(eddyb) Two implementations are provided, the second one is a bit
-// faster but neither is anywhere near as fast as same-thread execution.
-
-pub struct CrossThread1;
-
-impl ExecutionStrategy for CrossThread1 {
- fn run_bridge_and_client<D: Copy + Send + 'static>(
- &self,
- dispatcher: &mut impl DispatcherTrait,
- input: Buffer<u8>,
- run_client: extern "C" fn(Bridge<'_>, D) -> Buffer<u8>,
- client_data: D,
- force_show_panics: bool,
- ) -> Buffer<u8> {
- use std::sync::mpsc::channel;
-
- let (req_tx, req_rx) = channel();
- let (res_tx, res_rx) = channel();
-
- let join_handle = thread::spawn(move || {
- let mut dispatch = |b| {
- req_tx.send(b).unwrap();
- res_rx.recv().unwrap()
- };
-
- run_client(
- Bridge {
- cached_buffer: input,
- dispatch: (&mut dispatch).into(),
- force_show_panics,
- },
- client_data,
- )
- });
-
- for b in req_rx {
- res_tx.send(dispatcher.dispatch(b)).unwrap();
- }
-
- join_handle.join().unwrap()
- }
-}
-
-pub struct CrossThread2;
-
-impl ExecutionStrategy for CrossThread2 {
- fn run_bridge_and_client<D: Copy + Send + 'static>(
- &self,
- dispatcher: &mut impl DispatcherTrait,
- input: Buffer<u8>,
- run_client: extern "C" fn(Bridge<'_>, D) -> Buffer<u8>,
- client_data: D,
- force_show_panics: bool,
- ) -> Buffer<u8> {
- use std::sync::{Arc, Mutex};
-
- enum State<T> {
- Req(T),
- Res(T),
- }
-
- let mut state = Arc::new(Mutex::new(State::Res(Buffer::new())));
-
- let server_thread = thread::current();
- let state2 = state.clone();
- let join_handle = thread::spawn(move || {
- let mut dispatch = |b| {
- *state2.lock().unwrap() = State::Req(b);
- server_thread.unpark();
- loop {
- thread::park();
- if let State::Res(b) = &mut *state2.lock().unwrap() {
- break b.take();
- }
- }
- };
-
- let r = run_client(
- Bridge {
- cached_buffer: input,
- dispatch: (&mut dispatch).into(),
- force_show_panics,
- },
- client_data,
- );
-
- // Wake up the server so it can exit the dispatch loop.
- drop(state2);
- server_thread.unpark();
-
- r
- });
-
- // Check whether `state2` was dropped, to know when to stop.
- while Arc::get_mut(&mut state).is_none() {
- thread::park();
- let mut b = match &mut *state.lock().unwrap() {
- State::Req(b) => b.take(),
- _ => continue,
- };
- b = dispatcher.dispatch(b.take());
- *state.lock().unwrap() = State::Res(b);
- join_handle.thread().unpark();
- }
-
- join_handle.join().unwrap()
- }
-}
-
-fn run_server<
- S: Server,
- I: Encode<HandleStore<MarkedTypes<S>>>,
- O: for<'a, 's> DecodeMut<'a, 's, HandleStore<MarkedTypes<S>>>,
- D: Copy + Send + 'static,
->(
- strategy: &impl ExecutionStrategy,
- handle_counters: &'static client::HandleCounters,
- server: S,
- input: I,
- run_client: extern "C" fn(Bridge<'_>, D) -> Buffer<u8>,
- client_data: D,
- force_show_panics: bool,
-) -> Result<O, PanicMessage> {
- let mut dispatcher =
- Dispatcher { handle_store: HandleStore::new(handle_counters), server: MarkedTypes(server) };
-
- let mut b = Buffer::new();
- input.encode(&mut b, &mut dispatcher.handle_store);
-
- b = strategy.run_bridge_and_client(
- &mut dispatcher,
- b,
- run_client,
- client_data,
- force_show_panics,
- );
-
- Result::decode(&mut &b[..], &mut dispatcher.handle_store)
-}
-
-impl client::Client<fn(super::super::TokenStream) -> super::super::TokenStream> {
- pub fn run<S: Server>(
- &self,
- strategy: &impl ExecutionStrategy,
- server: S,
- input: S::TokenStream,
- force_show_panics: bool,
- ) -> Result<S::TokenStream, PanicMessage> {
- let client::Client { get_handle_counters, run, f } = *self;
- run_server(
- strategy,
- get_handle_counters(),
- server,
- <MarkedTypes<S> as Types>::TokenStream::mark(input),
- run,
- f,
- force_show_panics,
- )
- .map(<MarkedTypes<S> as Types>::TokenStream::unmark)
- }
-}
-
-impl
- client::Client<
- fn(super::super::TokenStream, super::super::TokenStream) -> super::super::TokenStream,
- >
-{
- pub fn run<S: Server>(
- &self,
- strategy: &impl ExecutionStrategy,
- server: S,
- input: S::TokenStream,
- input2: S::TokenStream,
- force_show_panics: bool,
- ) -> Result<S::TokenStream, PanicMessage> {
- let client::Client { get_handle_counters, run, f } = *self;
- run_server(
- strategy,
- get_handle_counters(),
- server,
- (
- <MarkedTypes<S> as Types>::TokenStream::mark(input),
- <MarkedTypes<S> as Types>::TokenStream::mark(input2),
- ),
- run,
- f,
- force_show_panics,
- )
- .map(<MarkedTypes<S> as Types>::TokenStream::unmark)
- }
-}
diff --git a/src/tools/rust-analyzer/crates/proc-macro-srv/src/abis/abi_1_58/proc_macro/diagnostic.rs b/src/tools/rust-analyzer/crates/proc-macro-srv/src/abis/abi_1_58/proc_macro/diagnostic.rs
deleted file mode 100644
index cda239f87..000000000
--- a/src/tools/rust-analyzer/crates/proc-macro-srv/src/abis/abi_1_58/proc_macro/diagnostic.rs
+++ /dev/null
@@ -1,166 +0,0 @@
-//! lib-proc-macro diagnostic
-//!
-//! Copy from <https://github.com/rust-lang/rust/blob/6050e523bae6de61de4e060facc43dc512adaccd/src/libproc_macro/diagnostic.rs>
-//! augmented with removing unstable features
-
-use super::Span;
-
-/// An enum representing a diagnostic level.
-#[derive(Copy, Clone, Debug)]
-#[non_exhaustive]
-pub enum Level {
- /// An error.
- Error,
- /// A warning.
- Warning,
- /// A note.
- Note,
- /// A help message.
- Help,
-}
-
-/// Trait implemented by types that can be converted into a set of `Span`s.
-pub trait MultiSpan {
- /// Converts `self` into a `Vec<Span>`.
- fn into_spans(self) -> Vec<Span>;
-}
-
-impl MultiSpan for Span {
- fn into_spans(self) -> Vec<Span> {
- vec![self]
- }
-}
-
-impl MultiSpan for Vec<Span> {
- fn into_spans(self) -> Vec<Span> {
- self
- }
-}
-
-impl<'a> MultiSpan for &'a [Span] {
- fn into_spans(self) -> Vec<Span> {
- self.to_vec()
- }
-}
-
-/// A structure representing a diagnostic message and associated children
-/// messages.
-#[derive(Clone, Debug)]
-pub struct Diagnostic {
- level: Level,
- message: String,
- spans: Vec<Span>,
- children: Vec<Diagnostic>,
-}
-
-macro_rules! diagnostic_child_methods {
- ($spanned:ident, $regular:ident, $level:expr) => {
- #[doc = concat!("Adds a new child diagnostics message to `self` with the [`",
- stringify!($level), "`] level, and the given `spans` and `message`.")]
- pub fn $spanned<S, T>(mut self, spans: S, message: T) -> Diagnostic
- where
- S: MultiSpan,
- T: Into<String>,
- {
- self.children.push(Diagnostic::spanned(spans, $level, message));
- self
- }
-
- #[doc = concat!("Adds a new child diagnostic message to `self` with the [`",
- stringify!($level), "`] level, and the given `message`.")]
- pub fn $regular<T: Into<String>>(mut self, message: T) -> Diagnostic {
- self.children.push(Diagnostic::new($level, message));
- self
- }
- };
-}
-
-/// Iterator over the children diagnostics of a `Diagnostic`.
-#[derive(Debug, Clone)]
-pub struct Children<'a>(std::slice::Iter<'a, Diagnostic>);
-
-impl<'a> Iterator for Children<'a> {
- type Item = &'a Diagnostic;
-
- fn next(&mut self) -> Option<Self::Item> {
- self.0.next()
- }
-}
-
-impl Diagnostic {
- /// Creates a new diagnostic with the given `level` and `message`.
- pub fn new<T: Into<String>>(level: Level, message: T) -> Diagnostic {
- Diagnostic { level, message: message.into(), spans: vec![], children: vec![] }
- }
-
- /// Creates a new diagnostic with the given `level` and `message` pointing to
- /// the given set of `spans`.
- pub fn spanned<S, T>(spans: S, level: Level, message: T) -> Diagnostic
- where
- S: MultiSpan,
- T: Into<String>,
- {
- Diagnostic { level, message: message.into(), spans: spans.into_spans(), children: vec![] }
- }
-
- diagnostic_child_methods!(span_error, error, Level::Error);
- diagnostic_child_methods!(span_warning, warning, Level::Warning);
- diagnostic_child_methods!(span_note, note, Level::Note);
- diagnostic_child_methods!(span_help, help, Level::Help);
-
- /// Returns the diagnostic `level` for `self`.
- pub fn level(&self) -> Level {
- self.level
- }
-
- /// Sets the level in `self` to `level`.
- pub fn set_level(&mut self, level: Level) {
- self.level = level;
- }
-
- /// Returns the message in `self`.
- pub fn message(&self) -> &str {
- &self.message
- }
-
- /// Sets the message in `self` to `message`.
- pub fn set_message<T: Into<String>>(&mut self, message: T) {
- self.message = message.into();
- }
-
- /// Returns the `Span`s in `self`.
- pub fn spans(&self) -> &[Span] {
- &self.spans
- }
-
- /// Sets the `Span`s in `self` to `spans`.
- pub fn set_spans<S: MultiSpan>(&mut self, spans: S) {
- self.spans = spans.into_spans();
- }
-
- /// Returns an iterator over the children diagnostics of `self`.
- pub fn children(&self) -> Children<'_> {
- Children(self.children.iter())
- }
-
- /// Emit the diagnostic.
- pub fn emit(self) {
- fn to_internal(spans: Vec<Span>) -> super::bridge::client::MultiSpan {
- let mut multi_span = super::bridge::client::MultiSpan::new();
- for span in spans {
- multi_span.push(span.0);
- }
- multi_span
- }
-
- let mut diag = super::bridge::client::Diagnostic::new(
- self.level,
- &self.message[..],
- to_internal(self.spans),
- );
- for c in self.children {
- diag.sub(c.level, &c.message[..], to_internal(c.spans));
- }
- diag.emit();
- }
-}
diff --git a/src/tools/rust-analyzer/crates/proc-macro-srv/src/abis/abi_1_58/proc_macro/mod.rs b/src/tools/rust-analyzer/crates/proc-macro-srv/src/abis/abi_1_58/proc_macro/mod.rs
deleted file mode 100644
index c5145d00e..000000000
--- a/src/tools/rust-analyzer/crates/proc-macro-srv/src/abis/abi_1_58/proc_macro/mod.rs
+++ /dev/null
@@ -1,1056 +0,0 @@
-//! A support library for macro authors when defining new macros.
-//!
-//! This library, provided by the standard distribution, provides the types
-//! consumed in the interfaces of procedurally defined macro definitions such as
-//! function-like macros `#[proc_macro]`, macro attributes `#[proc_macro_attribute]` and
-//! custom derive attributes`#[proc_macro_derive]`.
-//!
-//! See [the book] for more.
-//!
-//! [the book]: ../book/ch19-06-macros.html#procedural-macros-for-generating-code-from-attributes
-
-#[doc(hidden)]
-pub mod bridge;
-
-mod diagnostic;
-
-pub use diagnostic::{Diagnostic, Level, MultiSpan};
-
-use std::cmp::Ordering;
-use std::ops::RangeBounds;
-use std::path::PathBuf;
-use std::str::FromStr;
-use std::{error, fmt, iter, mem};
-
-/// Determines whether proc_macro has been made accessible to the currently
-/// running program.
-///
-/// The proc_macro crate is only intended for use inside the implementation of
-/// procedural macros. All the functions in this crate panic if invoked from
-/// outside of a procedural macro, such as from a build script or unit test or
-/// ordinary Rust binary.
-///
-/// With consideration for Rust libraries that are designed to support both
-/// macro and non-macro use cases, `proc_macro::is_available()` provides a
-/// 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.
-pub fn is_available() -> bool {
- bridge::Bridge::is_available()
-}
-
-/// The main type provided by this crate, representing an abstract stream of
-/// tokens, or, more specifically, a sequence of token trees.
-/// The type provide interfaces for iterating over those token trees and, conversely,
-/// collecting a number of token trees into one stream.
-///
-/// This is both the input and output of `#[proc_macro]`, `#[proc_macro_attribute]`
-/// and `#[proc_macro_derive]` definitions.
-#[derive(Clone)]
-pub struct TokenStream(bridge::client::TokenStream);
-
-/// Error returned from `TokenStream::from_str`.
-#[non_exhaustive]
-#[derive(Debug)]
-pub struct LexError;
-
-impl fmt::Display for LexError {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- f.write_str("cannot parse string into token stream")
- }
-}
-
-impl error::Error for LexError {}
-
-/// Error returned from `TokenStream::expand_expr`.
-#[non_exhaustive]
-#[derive(Debug)]
-pub struct ExpandError;
-
-impl fmt::Display for ExpandError {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- f.write_str("macro expansion failed")
- }
-}
-
-impl error::Error for ExpandError {}
-
-impl TokenStream {
- /// Returns an empty `TokenStream` containing no token trees.
- pub fn new() -> TokenStream {
- TokenStream(bridge::client::TokenStream::new())
- }
-
- /// Checks if this `TokenStream` is empty.
- pub fn is_empty(&self) -> bool {
- self.0.is_empty()
- }
-
- /// Parses this `TokenStream` as an expression and attempts to expand any
- /// macros within it. Returns the expanded `TokenStream`.
- ///
- /// Currently only expressions expanding to literals will succeed, although
- /// this may be relaxed in the future.
- ///
- /// NOTE: In error conditions, `expand_expr` may leave macros unexpanded,
- /// report an error, failing compilation, and/or return an `Err(..)`. The
- /// specific behavior for any error condition, and what conditions are
- /// considered errors, is unspecified and may change in the future.
- pub fn expand_expr(&self) -> Result<TokenStream, ExpandError> {
- match bridge::client::TokenStream::expand_expr(&self.0) {
- Ok(stream) => Ok(TokenStream(stream)),
- Err(_) => Err(ExpandError),
- }
- }
-}
-
-/// Attempts to break the string into tokens and parse those tokens into a token stream.
-/// May fail for a number of reasons, for example, if the string contains unbalanced delimiters
-/// or characters not existing in the language.
-/// All tokens in the parsed stream get `Span::call_site()` spans.
-///
-/// NOTE: some errors may cause panics instead of returning `LexError`. We reserve the right to
-/// change these errors into `LexError`s later.
-impl FromStr for TokenStream {
- type Err = LexError;
-
- fn from_str(src: &str) -> Result<TokenStream, LexError> {
- Ok(TokenStream(bridge::client::TokenStream::from_str(src)))
- }
-}
-
-/// Prints the token stream as a string that is supposed to be losslessly convertible back
-/// into the same token stream (modulo spans), except for possibly `TokenTree::Group`s
-/// with `Delimiter::None` delimiters and negative numeric literals.
-impl fmt::Display for TokenStream {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- f.write_str(&self.to_string())
- }
-}
-
-/// Prints token in a form convenient for debugging.
-impl fmt::Debug for TokenStream {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- f.write_str("TokenStream ")?;
- f.debug_list().entries(self.clone()).finish()
- }
-}
-
-impl Default for TokenStream {
- fn default() -> Self {
- TokenStream::new()
- }
-}
-
-pub use quote::{quote, quote_span};
-
-/// Creates a token stream containing a single token tree.
-impl From<TokenTree> for TokenStream {
- fn from(tree: TokenTree) -> TokenStream {
- TokenStream(bridge::client::TokenStream::from_token_tree(match tree {
- TokenTree::Group(tt) => bridge::TokenTree::Group(tt.0),
- TokenTree::Punct(tt) => bridge::TokenTree::Punct(tt.0),
- TokenTree::Ident(tt) => bridge::TokenTree::Ident(tt.0),
- TokenTree::Literal(tt) => bridge::TokenTree::Literal(tt.0),
- }))
- }
-}
-
-/// Collects a number of token trees into a single stream.
-impl FromIterator<TokenTree> for TokenStream {
- fn from_iter<I: IntoIterator<Item = TokenTree>>(trees: I) -> Self {
- trees.into_iter().map(TokenStream::from).collect()
- }
-}
-
-/// A "flattening" operation on token streams, collects token trees
-/// from multiple token streams into a single stream.
-impl FromIterator<TokenStream> for TokenStream {
- fn from_iter<I: IntoIterator<Item = TokenStream>>(streams: I) -> Self {
- let mut builder = bridge::client::TokenStreamBuilder::new();
- streams.into_iter().for_each(|stream| builder.push(stream.0));
- TokenStream(builder.build())
- }
-}
-
-impl Extend<TokenTree> for TokenStream {
- fn extend<I: IntoIterator<Item = TokenTree>>(&mut self, trees: I) {
- self.extend(trees.into_iter().map(TokenStream::from));
- }
-}
-
-impl Extend<TokenStream> for TokenStream {
- fn extend<I: IntoIterator<Item = TokenStream>>(&mut self, streams: I) {
- // FIXME(eddyb) Use an optimized implementation if/when possible.
- *self = iter::once(mem::replace(self, Self::new())).chain(streams).collect();
- }
-}
-
-/// Public implementation details for the `TokenStream` type, such as iterators.
-pub mod token_stream {
- use super::{bridge, Group, Ident, Literal, Punct, TokenStream, TokenTree};
-
- /// An iterator over `TokenStream`'s `TokenTree`s.
- /// The iteration is "shallow", e.g., the iterator doesn't recurse into delimited groups,
- /// and returns whole groups as token trees.
- #[derive(Clone)]
- pub struct IntoIter(bridge::client::TokenStreamIter);
-
- impl Iterator for IntoIter {
- type Item = TokenTree;
-
- fn next(&mut self) -> Option<TokenTree> {
- self.0.next().map(|tree| match tree {
- bridge::TokenTree::Group(tt) => TokenTree::Group(Group(tt)),
- bridge::TokenTree::Punct(tt) => TokenTree::Punct(Punct(tt)),
- bridge::TokenTree::Ident(tt) => TokenTree::Ident(Ident(tt)),
- bridge::TokenTree::Literal(tt) => TokenTree::Literal(Literal(tt)),
- })
- }
- }
-
- impl IntoIterator for TokenStream {
- type Item = TokenTree;
- type IntoIter = IntoIter;
-
- fn into_iter(self) -> IntoIter {
- IntoIter(self.0.into_iter())
- }
- }
-}
-
-/// `quote!(..)` accepts arbitrary tokens and expands into a `TokenStream` describing the input.
-/// For example, `quote!(a + b)` will produce an expression, that, when evaluated, constructs
-/// the `TokenStream` `[Ident("a"), Punct('+', Alone), Ident("b")]`.
-///
-/// Unquoting is done with `$`, and works by taking the single next ident as the unquoted term.
-/// To quote `$` itself, use `$$`.
-//pub macro quote($($t:tt)*) {
-//[> compiler built-in <]
-//}
-
-#[doc(hidden)]
-mod quote;
-
-/// A region of source code, along with macro expansion information.
-#[derive(Copy, Clone)]
-pub struct Span(bridge::client::Span);
-
-macro_rules! diagnostic_method {
- ($name:ident, $level:expr) => {
- /// Creates a new `Diagnostic` with the given `message` at the span
- /// `self`.
- pub fn $name<T: Into<String>>(self, message: T) -> Diagnostic {
- Diagnostic::spanned(self, $level, message)
- }
- };
-}
-
-impl Span {
- /// A span that resolves at the macro definition site.
- pub fn def_site() -> Span {
- Span(bridge::client::Span::def_site())
- }
-
- /// The span of the invocation of the current procedural macro.
- /// Identifiers created with this span will be resolved as if they were written
- /// directly at the macro call location (call-site hygiene) and other code
- /// at the macro call site will be able to refer to them as well.
- pub fn call_site() -> Span {
- Span(bridge::client::Span::call_site())
- }
-
- /// A span that represents `macro_rules` hygiene, and sometimes resolves at the macro
- /// definition site (local variables, labels, `$crate`) and sometimes at the macro
- /// call site (everything else).
- /// The span location is taken from the call-site.
- pub fn mixed_site() -> Span {
- Span(bridge::client::Span::mixed_site())
- }
-
- /// The original source file into which this span points.
- pub fn source_file(&self) -> SourceFile {
- SourceFile(self.0.source_file())
- }
-
- /// The `Span` for the tokens in the previous macro expansion from which
- /// `self` was generated from, if any.
- pub fn parent(&self) -> Option<Span> {
- self.0.parent().map(Span)
- }
-
- /// The span for the origin source code that `self` was generated from. If
- /// this `Span` wasn't generated from other macro expansions then the return
- /// value is the same as `*self`.
- pub fn source(&self) -> Span {
- Span(self.0.source())
- }
-
- /// Gets the starting line/column in the source file for this span.
- pub fn start(&self) -> LineColumn {
- self.0.start().add_1_to_column()
- }
-
- /// Gets the ending line/column in the source file for this span.
- pub fn end(&self) -> LineColumn {
- self.0.end().add_1_to_column()
- }
-
- /// Creates an empty span pointing to directly before this span.
- pub fn before(&self) -> Span {
- Span(self.0.before())
- }
-
- /// Creates an empty span pointing to directly after this span.
- 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.
- pub fn join(&self, other: Span) -> Option<Span> {
- self.0.join(other.0).map(Span)
- }
-
- /// Creates a new span with the same line/column information as `self` but
- /// that resolves symbols as though it were at `other`.
- pub fn resolved_at(&self, other: Span) -> Span {
- Span(self.0.resolved_at(other.0))
- }
-
- /// Creates a new span with the same name resolution behavior as `self` but
- /// with the line/column information of `other`.
- pub fn located_at(&self, other: Span) -> Span {
- other.resolved_at(*self)
- }
-
- /// Compares to spans to see if they're equal.
- pub fn eq(&self, other: &Span) -> bool {
- self.0 == other.0
- }
-
- /// Returns the source text behind a span. This preserves the original source
- /// code, including spaces and comments. It only returns a result if the span
- /// corresponds to real source code.
- ///
- /// Note: The observable result of a macro should only rely on the tokens and
- /// not on this source text. The result of this function is a best effort to
- /// be used for diagnostics only.
- pub fn source_text(&self) -> Option<String> {
- self.0.source_text()
- }
-
- // Used by the implementation of `Span::quote`
- #[doc(hidden)]
- pub fn save_span(&self) -> usize {
- self.0.save_span()
- }
-
- // Used by the implementation of `Span::quote`
- #[doc(hidden)]
- pub fn recover_proc_macro_span(id: usize) -> Span {
- Span(bridge::client::Span::recover_proc_macro_span(id))
- }
-
- diagnostic_method!(error, Level::Error);
- diagnostic_method!(warning, Level::Warning);
- diagnostic_method!(note, Level::Note);
- diagnostic_method!(help, Level::Help);
-}
-
-/// Prints a span in a form convenient for debugging.
-impl fmt::Debug for Span {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- self.0.fmt(f)
- }
-}
-
-/// A line-column pair representing the start or end of a `Span`.
-#[derive(Copy, Clone, Debug, PartialEq, Eq)]
-pub struct LineColumn {
- /// The 1-indexed line in the source file on which the span starts or ends (inclusive).
- pub line: usize,
- /// The 1-indexed column (number of bytes in UTF-8 encoding) in the source
- /// file on which the span starts or ends (inclusive).
- pub column: usize,
-}
-
-impl LineColumn {
- fn add_1_to_column(self) -> Self {
- LineColumn { line: self.line, column: self.column + 1 }
- }
-}
-
-impl Ord for LineColumn {
- fn cmp(&self, other: &Self) -> Ordering {
- self.line.cmp(&other.line).then(self.column.cmp(&other.column))
- }
-}
-
-impl PartialOrd for LineColumn {
- fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
- Some(self.cmp(other))
- }
-}
-
-/// The source file of a given `Span`.
-#[derive(Clone)]
-pub struct SourceFile(bridge::client::SourceFile);
-
-impl SourceFile {
- /// Gets the path to this source file.
- ///
- /// ### Note
- /// If the code span associated with this `SourceFile` was generated by an external macro, this
- /// macro, this might not be an actual path on the filesystem. Use [`is_real`] to check.
- ///
- /// Also note that even if `is_real` returns `true`, if `--remap-path-prefix` was passed on
- /// the command line, the path as given might not actually be valid.
- ///
- /// [`is_real`]: Self::is_real
- pub fn path(&self) -> PathBuf {
- PathBuf::from(self.0.path())
- }
-
- /// Returns `true` if this source file is a real source file, and not generated by an external
- /// macro's expansion.
- pub fn is_real(&self) -> bool {
- // This is a hack until intercrate spans are implemented and we can have real source files
- // for spans generated in external macros.
- // https://github.com/rust-lang/rust/pull/43604#issuecomment-333334368
- self.0.is_real()
- }
-}
-
-impl fmt::Debug for SourceFile {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- f.debug_struct("SourceFile")
- .field("path", &self.path())
- .field("is_real", &self.is_real())
- .finish()
- }
-}
-
-impl PartialEq for SourceFile {
- fn eq(&self, other: &Self) -> bool {
- self.0.eq(&other.0)
- }
-}
-
-impl Eq for SourceFile {}
-
-/// A single token or a delimited sequence of token trees (e.g., `[1, (), ..]`).
-#[derive(Clone)]
-pub enum TokenTree {
- /// A token stream surrounded by bracket delimiters.
- Group(Group),
- /// An identifier.
- Ident(Ident),
- /// A single punctuation character (`+`, `,`, `$`, etc.).
- Punct(Punct),
- /// A literal character (`'a'`), string (`"hello"`), number (`2.3`), etc.
- Literal(Literal),
-}
-
-impl TokenTree {
- /// Returns the span of this tree, delegating to the `span` method of
- /// the contained token or a delimited stream.
- pub fn span(&self) -> Span {
- match *self {
- TokenTree::Group(ref t) => t.span(),
- TokenTree::Ident(ref t) => t.span(),
- TokenTree::Punct(ref t) => t.span(),
- TokenTree::Literal(ref t) => t.span(),
- }
- }
-
- /// Configures the span for *only this token*.
- ///
- /// Note that if this token is a `Group` then this method will not configure
- /// the span of each of the internal tokens, this will simply delegate to
- /// the `set_span` method of each variant.
- pub fn set_span(&mut self, span: Span) {
- match *self {
- TokenTree::Group(ref mut t) => t.set_span(span),
- TokenTree::Ident(ref mut t) => t.set_span(span),
- TokenTree::Punct(ref mut t) => t.set_span(span),
- TokenTree::Literal(ref mut t) => t.set_span(span),
- }
- }
-}
-
-/// Prints token tree in a form convenient for debugging.
-impl fmt::Debug for TokenTree {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- // Each of these has the name in the struct type in the derived debug,
- // so don't bother with an extra layer of indirection
- match *self {
- TokenTree::Group(ref tt) => tt.fmt(f),
- TokenTree::Ident(ref tt) => tt.fmt(f),
- TokenTree::Punct(ref tt) => tt.fmt(f),
- TokenTree::Literal(ref tt) => tt.fmt(f),
- }
- }
-}
-
-impl From<Group> for TokenTree {
- fn from(g: Group) -> TokenTree {
- TokenTree::Group(g)
- }
-}
-
-impl From<Ident> for TokenTree {
- fn from(g: Ident) -> TokenTree {
- TokenTree::Ident(g)
- }
-}
-
-impl From<Punct> for TokenTree {
- fn from(g: Punct) -> TokenTree {
- TokenTree::Punct(g)
- }
-}
-
-impl From<Literal> for TokenTree {
- fn from(g: Literal) -> TokenTree {
- TokenTree::Literal(g)
- }
-}
-
-/// Prints the token tree as a string that is supposed to be losslessly convertible back
-/// into the same token tree (modulo spans), except for possibly `TokenTree::Group`s
-/// with `Delimiter::None` delimiters and negative numeric literals.
-impl fmt::Display for TokenTree {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- f.write_str(&self.to_string())
- }
-}
-
-/// A delimited token stream.
-///
-/// A `Group` internally contains a `TokenStream` which is surrounded by `Delimiter`s.
-#[derive(Clone)]
-pub struct Group(bridge::client::Group);
-
-/// Describes how a sequence of token trees is delimited.
-#[derive(Copy, Clone, Debug, PartialEq, Eq)]
-pub enum Delimiter {
- /// `( ... )`
- Parenthesis,
- /// `{ ... }`
- Brace,
- /// `[ ... ]`
- Bracket,
- /// `Ø ... Ø`
- /// An implicit delimiter, that may, for example, appear around tokens coming from a
- /// "macro variable" `$var`. It is important to preserve operator priorities in cases like
- /// `$var * 3` where `$var` is `1 + 2`.
- /// Implicit delimiters might not survive roundtrip of a token stream through a string.
- None,
-}
-
-impl Group {
- /// Creates a new `Group` with the given delimiter and token stream.
- ///
- /// This constructor will set the span for this group to
- /// `Span::call_site()`. To change the span you can use the `set_span`
- /// method below.
- pub fn new(delimiter: Delimiter, stream: TokenStream) -> Group {
- Group(bridge::client::Group::new(delimiter, stream.0))
- }
-
- /// Returns the delimiter of this `Group`
- pub fn delimiter(&self) -> Delimiter {
- self.0.delimiter()
- }
-
- /// Returns the `TokenStream` of tokens that are delimited in this `Group`.
- ///
- /// Note that the returned token stream does not include the delimiter
- /// returned above.
- pub fn stream(&self) -> TokenStream {
- TokenStream(self.0.stream())
- }
-
- /// Returns the span for the delimiters of this token stream, spanning the
- /// entire `Group`.
- ///
- /// ```text
- /// pub fn span(&self) -> Span {
- /// ^^^^^^^
- /// ```
- pub fn span(&self) -> Span {
- Span(self.0.span())
- }
-
- /// Returns the span pointing to the opening delimiter of this group.
- ///
- /// ```text
- /// pub fn span_open(&self) -> Span {
- /// ^
- /// ```
- pub fn span_open(&self) -> Span {
- Span(self.0.span_open())
- }
-
- /// Returns the span pointing to the closing delimiter of this group.
- ///
- /// ```text
- /// pub fn span_close(&self) -> Span {
- /// ^
- /// ```
- pub fn span_close(&self) -> Span {
- Span(self.0.span_close())
- }
-
- /// Configures the span for this `Group`'s delimiters, but not its internal
- /// tokens.
- ///
- /// This method will **not** set the span of all the internal tokens spanned
- /// by this group, but rather it will only set the span of the delimiter
- /// tokens at the level of the `Group`.
- pub fn set_span(&mut self, span: Span) {
- self.0.set_span(span.0);
- }
-}
-
-/// Prints the group as a string that should be losslessly convertible back
-/// into the same group (modulo spans), except for possibly `TokenTree::Group`s
-/// with `Delimiter::None` delimiters.
-impl fmt::Display for Group {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- f.write_str(&self.to_string())
- }
-}
-
-impl fmt::Debug for Group {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- f.debug_struct("Group")
- .field("delimiter", &self.delimiter())
- .field("stream", &self.stream())
- .field("span", &self.span())
- .finish()
- }
-}
-
-/// A `Punct` is a single punctuation character such as `+`, `-` or `#`.
-///
-/// Multi-character operators like `+=` are represented as two instances of `Punct` with different
-/// forms of `Spacing` returned.
-#[derive(Clone)]
-pub struct Punct(bridge::client::Punct);
-
-/// Describes whether a `Punct` is followed immediately by another `Punct` ([`Spacing::Joint`]) or
-/// by a different token or whitespace ([`Spacing::Alone`]).
-#[derive(Copy, Clone, Debug, PartialEq, Eq)]
-pub enum Spacing {
- /// A `Punct` is not immediately followed by another `Punct`.
- /// E.g. `+` is `Alone` in `+ =`, `+ident` and `+()`.
- Alone,
- /// A `Punct` is immediately followed by another `Punct`.
- /// E.g. `+` is `Joint` in `+=` and `++`.
- ///
- /// Additionally, single quote `'` can join with identifiers to form lifetimes: `'ident`.
- Joint,
-}
-
-impl Punct {
- /// Creates a new `Punct` from the given character and spacing.
- /// The `ch` argument must be a valid punctuation character permitted by the language,
- /// otherwise the function will panic.
- ///
- /// The returned `Punct` will have the default span of `Span::call_site()`
- /// which can be further configured with the `set_span` method below.
- pub fn new(ch: char, spacing: Spacing) -> Punct {
- Punct(bridge::client::Punct::new(ch, spacing))
- }
-
- /// Returns the value of this punctuation character as `char`.
- pub fn as_char(&self) -> char {
- self.0.as_char()
- }
-
- /// Returns the spacing of this punctuation character, indicating whether it's immediately
- /// followed by another `Punct` in the token stream, so they can potentially be combined into
- /// a multi-character operator (`Joint`), or it's followed by some other token or whitespace
- /// (`Alone`) so the operator has certainly ended.
- pub fn spacing(&self) -> Spacing {
- self.0.spacing()
- }
-
- /// Returns the span for this punctuation character.
- pub fn span(&self) -> Span {
- Span(self.0.span())
- }
-
- /// Configure the span for this punctuation character.
- pub fn set_span(&mut self, span: Span) {
- self.0 = self.0.with_span(span.0);
- }
-}
-
-/// Prints the punctuation character as a string that should be losslessly convertible
-/// back into the same character.
-impl fmt::Display for Punct {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- f.write_str(&self.to_string())
- }
-}
-
-impl fmt::Debug for Punct {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- f.debug_struct("Punct")
- .field("ch", &self.as_char())
- .field("spacing", &self.spacing())
- .field("span", &self.span())
- .finish()
- }
-}
-
-impl PartialEq<char> for Punct {
- fn eq(&self, rhs: &char) -> bool {
- self.as_char() == *rhs
- }
-}
-
-impl PartialEq<Punct> for char {
- fn eq(&self, rhs: &Punct) -> bool {
- *self == rhs.as_char()
- }
-}
-
-/// An identifier (`ident`).
-#[derive(Clone)]
-pub struct Ident(bridge::client::Ident);
-
-impl Ident {
- /// Creates a new `Ident` with the given `string` as well as the specified
- /// `span`.
- /// The `string` argument must be a valid identifier permitted by the
- /// language (including keywords, e.g. `self` or `fn`). Otherwise, the function will panic.
- ///
- /// Note that `span`, currently in rustc, configures the hygiene information
- /// for this identifier.
- ///
- /// As of this time `Span::call_site()` explicitly opts-in to "call-site" hygiene
- /// meaning that identifiers created with this span will be resolved as if they were written
- /// directly at the location of the macro call, and other code at the macro call site will be
- /// able to refer to them as well.
- ///
- /// Later spans like `Span::def_site()` will allow to opt-in to "definition-site" hygiene
- /// meaning that identifiers created with this span will be resolved at the location of the
- /// macro definition and other code at the macro call site will not be able to refer to them.
- ///
- /// Due to the current importance of hygiene this constructor, unlike other
- /// tokens, requires a `Span` to be specified at construction.
- pub fn new(string: &str, span: Span) -> Ident {
- Ident(bridge::client::Ident::new(string, span.0, false))
- }
-
- /// Same as `Ident::new`, but creates a raw identifier (`r#ident`).
- /// The `string` argument be a valid identifier permitted by the language
- /// (including keywords, e.g. `fn`). Keywords which are usable in path segments
- /// (e.g. `self`, `super`) are not supported, and will cause a panic.
- pub fn new_raw(string: &str, span: Span) -> Ident {
- Ident(bridge::client::Ident::new(string, span.0, true))
- }
-
- /// Returns the span of this `Ident`, encompassing the entire string returned
- /// by [`to_string`](Self::to_string).
- pub fn span(&self) -> Span {
- Span(self.0.span())
- }
-
- /// Configures the span of this `Ident`, possibly changing its hygiene context.
- pub fn set_span(&mut self, span: Span) {
- self.0 = self.0.with_span(span.0);
- }
-}
-
-/// Prints the identifier as a string that should be losslessly convertible
-/// back into the same identifier.
-impl fmt::Display for Ident {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- f.write_str(&self.to_string())
- }
-}
-
-impl fmt::Debug for Ident {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- f.debug_struct("Ident")
- .field("ident", &self.to_string())
- .field("span", &self.span())
- .finish()
- }
-}
-
-/// A literal string (`"hello"`), byte string (`b"hello"`),
-/// character (`'a'`), byte character (`b'a'`), an integer or floating point number
-/// with or without a suffix (`1`, `1u8`, `2.3`, `2.3f32`).
-/// Boolean literals like `true` and `false` do not belong here, they are `Ident`s.
-#[derive(Clone)]
-pub struct Literal(bridge::client::Literal);
-
-macro_rules! suffixed_int_literals {
- ($($name:ident => $kind:ident,)*) => ($(
- /// Creates a new suffixed integer literal with the specified value.
- ///
- /// This function will create an integer like `1u32` where the integer
- /// value specified is the first part of the token and the integral is
- /// also suffixed at the end.
- /// Literals created from negative numbers might not survive round-trips through
- /// `TokenStream` or strings and may be broken into two tokens (`-` and positive literal).
- ///
- /// Literals created through this method have the `Span::call_site()`
- /// span by default, which can be configured with the `set_span` method
- /// below.
- pub fn $name(n: $kind) -> Literal {
- Literal(bridge::client::Literal::typed_integer(&n.to_string(), stringify!($kind)))
- }
- )*)
-}
-
-macro_rules! unsuffixed_int_literals {
- ($($name:ident => $kind:ident,)*) => ($(
- /// Creates a new unsuffixed integer literal with the specified value.
- ///
- /// This function will create an integer like `1` where the integer
- /// value specified is the first part of the token. No suffix is
- /// specified on this token, meaning that invocations like
- /// `Literal::i8_unsuffixed(1)` are equivalent to
- /// `Literal::u32_unsuffixed(1)`.
- /// Literals created from negative numbers might not survive rountrips through
- /// `TokenStream` or strings and may be broken into two tokens (`-` and positive literal).
- ///
- /// Literals created through this method have the `Span::call_site()`
- /// span by default, which can be configured with the `set_span` method
- /// below.
- pub fn $name(n: $kind) -> Literal {
- Literal(bridge::client::Literal::integer(&n.to_string()))
- }
- )*)
-}
-
-impl Literal {
- suffixed_int_literals! {
- u8_suffixed => u8,
- u16_suffixed => u16,
- u32_suffixed => u32,
- u64_suffixed => u64,
- u128_suffixed => u128,
- usize_suffixed => usize,
- i8_suffixed => i8,
- i16_suffixed => i16,
- i32_suffixed => i32,
- i64_suffixed => i64,
- i128_suffixed => i128,
- isize_suffixed => isize,
- }
-
- unsuffixed_int_literals! {
- u8_unsuffixed => u8,
- u16_unsuffixed => u16,
- u32_unsuffixed => u32,
- u64_unsuffixed => u64,
- u128_unsuffixed => u128,
- usize_unsuffixed => usize,
- i8_unsuffixed => i8,
- i16_unsuffixed => i16,
- i32_unsuffixed => i32,
- i64_unsuffixed => i64,
- i128_unsuffixed => i128,
- isize_unsuffixed => isize,
- }
-
- /// Creates a new unsuffixed floating-point literal.
- ///
- /// This constructor is similar to those like `Literal::i8_unsuffixed` where
- /// the float's value is emitted directly into the token but no suffix is
- /// used, so it may be inferred to be a `f64` later in the compiler.
- /// Literals created from negative numbers might not survive rountrips through
- /// `TokenStream` or strings and may be broken into two tokens (`-` and positive literal).
- ///
- /// # Panics
- ///
- /// This function requires that the specified float is finite, for
- /// example if it is infinity or NaN this function will panic.
- pub fn f32_unsuffixed(n: f32) -> Literal {
- if !n.is_finite() {
- panic!("Invalid float literal {n}");
- }
- let mut repr = n.to_string();
- if !repr.contains('.') {
- repr.push_str(".0");
- }
- Literal(bridge::client::Literal::float(&repr))
- }
-
- /// Creates a new suffixed floating-point literal.
- ///
- /// This constructor will create a literal like `1.0f32` where the value
- /// specified is the preceding part of the token and `f32` is the suffix of
- /// the token. This token will always be inferred to be an `f32` in the
- /// compiler.
- /// Literals created from negative numbers might not survive rountrips through
- /// `TokenStream` or strings and may be broken into two tokens (`-` and positive literal).
- ///
- /// # Panics
- ///
- /// This function requires that the specified float is finite, for
- /// example if it is infinity or NaN this function will panic.
- pub fn f32_suffixed(n: f32) -> Literal {
- if !n.is_finite() {
- panic!("Invalid float literal {n}");
- }
- Literal(bridge::client::Literal::f32(&n.to_string()))
- }
-
- /// Creates a new unsuffixed floating-point literal.
- ///
- /// This constructor is similar to those like `Literal::i8_unsuffixed` where
- /// the float's value is emitted directly into the token but no suffix is
- /// used, so it may be inferred to be a `f64` later in the compiler.
- /// Literals created from negative numbers might not survive rountrips through
- /// `TokenStream` or strings and may be broken into two tokens (`-` and positive literal).
- ///
- /// # Panics
- ///
- /// This function requires that the specified float is finite, for
- /// example if it is infinity or NaN this function will panic.
- pub fn f64_unsuffixed(n: f64) -> Literal {
- if !n.is_finite() {
- panic!("Invalid float literal {n}");
- }
- let mut repr = n.to_string();
- if !repr.contains('.') {
- repr.push_str(".0");
- }
- Literal(bridge::client::Literal::float(&repr))
- }
-
- /// Creates a new suffixed floating-point literal.
- ///
- /// This constructor will create a literal like `1.0f64` where the value
- /// specified is the preceding part of the token and `f64` is the suffix of
- /// the token. This token will always be inferred to be an `f64` in the
- /// compiler.
- /// Literals created from negative numbers might not survive rountrips through
- /// `TokenStream` or strings and may be broken into two tokens (`-` and positive literal).
- ///
- /// # Panics
- ///
- /// This function requires that the specified float is finite, for
- /// example if it is infinity or NaN this function will panic.
- pub fn f64_suffixed(n: f64) -> Literal {
- if !n.is_finite() {
- panic!("Invalid float literal {n}");
- }
- Literal(bridge::client::Literal::f64(&n.to_string()))
- }
-
- /// String literal.
- pub fn string(string: &str) -> Literal {
- Literal(bridge::client::Literal::string(string))
- }
-
- /// Character literal.
- pub fn character(ch: char) -> Literal {
- Literal(bridge::client::Literal::character(ch))
- }
-
- /// Byte string literal.
- pub fn byte_string(bytes: &[u8]) -> Literal {
- Literal(bridge::client::Literal::byte_string(bytes))
- }
-
- /// Returns the span encompassing this literal.
- pub fn span(&self) -> Span {
- Span(self.0.span())
- }
-
- /// Configures the span associated for this literal.
- pub fn set_span(&mut self, span: Span) {
- self.0.set_span(span.0);
- }
-
- /// Returns a `Span` that is a subset of `self.span()` containing only the
- /// source bytes in range `range`. Returns `None` if the would-be trimmed
- /// span is outside the bounds of `self`.
- // FIXME(SergioBenitez): check that the byte range starts and ends at a
- // UTF-8 boundary of the source. otherwise, it's likely that a panic will
- // occur elsewhere when the source text is printed.
- // FIXME(SergioBenitez): there is no way for the user to know what
- // `self.span()` actually maps to, so this method can currently only be
- // called blindly. For example, `to_string()` for the character 'c' returns
- // "'\u{63}'"; there is no way for the user to know whether the source text
- // was 'c' or whether it was '\u{63}'.
- pub fn subspan<R: RangeBounds<usize>>(&self, range: R) -> Option<Span> {
- self.0.subspan(range.start_bound().cloned(), range.end_bound().cloned()).map(Span)
- }
-}
-
-/// Parse a single literal from its stringified representation.
-///
-/// In order to parse successfully, the input string must not contain anything
-/// but the literal token. Specifically, it must not contain whitespace or
-/// comments in addition to the literal.
-///
-/// The resulting literal token will have a `Span::call_site()` span.
-///
-/// NOTE: some errors may cause panics instead of returning `LexError`. We
-/// reserve the right to change these errors into `LexError`s later.
-impl FromStr for Literal {
- type Err = LexError;
-
- fn from_str(src: &str) -> Result<Self, LexError> {
- match bridge::client::Literal::from_str(src) {
- Ok(literal) => Ok(Literal(literal)),
- Err(()) => Err(LexError),
- }
- }
-}
-
-/// Prints the literal as a string that should be losslessly convertible
-/// back into the same literal (except for possible rounding for floating point literals).
-impl fmt::Display for Literal {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- f.write_str(&self.to_string())
- }
-}
-
-impl fmt::Debug for Literal {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- self.0.fmt(f)
- }
-}
-
-/// Tracked access to environment variables.
-pub mod tracked_env {
- use std::env::{self, VarError};
- use std::ffi::OsStr;
-
- /// Retrieve an environment variable and add it to build dependency info.
- /// Build system executing the compiler will know that the variable was accessed during
- /// compilation, and will be able to rerun the build when the value of that variable changes.
- /// Besides the dependency tracking this function should be equivalent to `env::var` from the
- /// standard library, except that the argument must be UTF-8.
- pub fn var<K: AsRef<OsStr> + AsRef<str>>(key: K) -> Result<String, VarError> {
- let key: &str = key.as_ref();
- let value = env::var(key);
- super::bridge::client::FreeFunctions::track_env_var(key, value.as_deref().ok());
- value
- }
-}
-
-/// Tracked access to additional files.
-pub mod tracked_path {
-
- /// Track a file explicitly.
- ///
- /// Commonly used for tracking asset preprocessing.
- pub fn path<P: AsRef<str>>(path: P) {
- let path: &str = path.as_ref();
- super::bridge::client::FreeFunctions::track_path(path);
- }
-}
diff --git a/src/tools/rust-analyzer/crates/proc-macro-srv/src/abis/abi_1_58/proc_macro/quote.rs b/src/tools/rust-analyzer/crates/proc-macro-srv/src/abis/abi_1_58/proc_macro/quote.rs
deleted file mode 100644
index b539ab9c0..000000000
--- a/src/tools/rust-analyzer/crates/proc-macro-srv/src/abis/abi_1_58/proc_macro/quote.rs
+++ /dev/null
@@ -1,140 +0,0 @@
-//! # Quasiquoter
-//! This file contains the implementation internals of the quasiquoter provided by `quote!`.
-
-//! This quasiquoter uses macros 2.0 hygiene to reliably access
-//! items from `proc_macro`, to build a `proc_macro::TokenStream`.
-
-use super::{Delimiter, Group, Ident, Literal, Punct, Spacing, Span, TokenStream, TokenTree};
-
-macro_rules! quote_tt {
- (($($t:tt)*)) => { Group::new(Delimiter::Parenthesis, quote!($($t)*)) };
- ([$($t:tt)*]) => { Group::new(Delimiter::Bracket, quote!($($t)*)) };
- ({$($t:tt)*}) => { Group::new(Delimiter::Brace, quote!($($t)*)) };
- (,) => { Punct::new(',', Spacing::Alone) };
- (.) => { Punct::new('.', Spacing::Alone) };
- (:) => { Punct::new(':', Spacing::Alone) };
- (;) => { Punct::new(';', Spacing::Alone) };
- (!) => { Punct::new('!', Spacing::Alone) };
- (<) => { Punct::new('<', Spacing::Alone) };
- (>) => { Punct::new('>', Spacing::Alone) };
- (&) => { Punct::new('&', Spacing::Alone) };
- (=) => { Punct::new('=', Spacing::Alone) };
- ($i:ident) => { Ident::new(stringify!($i), Span::def_site()) };
-}
-
-macro_rules! quote_ts {
- ((@ $($t:tt)*)) => { $($t)* };
- (::) => {
- [
- TokenTree::from(Punct::new(':', Spacing::Joint)),
- TokenTree::from(Punct::new(':', Spacing::Alone)),
- ].iter()
- .cloned()
- .map(|mut x| {
- x.set_span(Span::def_site());
- x
- })
- .collect::<TokenStream>()
- };
- ($t:tt) => { TokenTree::from(quote_tt!($t)) };
-}
-
-/// Simpler version of the real `quote!` macro, implemented solely
-/// through `macro_rules`, for bootstrapping the real implementation
-/// (see the `quote` function), which does not have access to the
-/// real `quote!` macro due to the `proc_macro` crate not being
-/// able to depend on itself.
-///
-/// Note: supported tokens are a subset of the real `quote!`, but
-/// unquoting is different: instead of `$x`, this uses `(@ expr)`.
-macro_rules! quote {
- () => { TokenStream::new() };
- ($($t:tt)*) => {
- [
- $(TokenStream::from(quote_ts!($t)),)*
- ].iter().cloned().collect::<TokenStream>()
- };
-}
-
-/// Quote a `TokenStream` into a `TokenStream`.
-/// This is the actual implementation of the `quote!()` proc macro.
-///
-/// It is loaded by the compiler in `register_builtin_macros`.
-pub fn quote(stream: TokenStream) -> TokenStream {
- if stream.is_empty() {
- return quote!(crate::TokenStream::new());
- }
- let proc_macro_crate = quote!(crate);
- let mut after_dollar = false;
- let tokens = stream
- .into_iter()
- .filter_map(|tree| {
- if after_dollar {
- after_dollar = false;
- match tree {
- TokenTree::Ident(_) => {
- return Some(quote!(Into::<crate::TokenStream>::into(
- Clone::clone(&(@ tree))),));
- }
- TokenTree::Punct(ref tt) if tt.as_char() == '$' => {}
- _ => panic!("`$` must be followed by an ident or `$` in `quote!`"),
- }
- } else if let TokenTree::Punct(ref tt) = tree {
- if tt.as_char() == '$' {
- after_dollar = true;
- return None;
- }
- }
-
- Some(quote!(crate::TokenStream::from((@ match tree {
- TokenTree::Punct(tt) => quote!(crate::TokenTree::Punct(crate::Punct::new(
- (@ TokenTree::from(Literal::character(tt.as_char()))),
- (@ match tt.spacing() {
- Spacing::Alone => quote!(crate::Spacing::Alone),
- Spacing::Joint => quote!(crate::Spacing::Joint),
- }),
- ))),
- TokenTree::Group(tt) => quote!(crate::TokenTree::Group(crate::Group::new(
- (@ match tt.delimiter() {
- Delimiter::Parenthesis => quote!(crate::Delimiter::Parenthesis),
- Delimiter::Brace => quote!(crate::Delimiter::Brace),
- Delimiter::Bracket => quote!(crate::Delimiter::Bracket),
- Delimiter::None => quote!(crate::Delimiter::None),
- }),
- (@ quote(tt.stream())),
- ))),
- TokenTree::Ident(tt) => quote!(crate::TokenTree::Ident(crate::Ident::new(
- (@ TokenTree::from(Literal::string(&tt.to_string()))),
- (@ quote_span(proc_macro_crate.clone(), tt.span())),
- ))),
- TokenTree::Literal(tt) => quote!(crate::TokenTree::Literal({
- let mut iter = (@ TokenTree::from(Literal::string(&tt.to_string())))
- .parse::<crate::TokenStream>()
- .unwrap()
- .into_iter();
- if let (Some(crate::TokenTree::Literal(mut lit)), None) =
- (iter.next(), iter.next())
- {
- lit.set_span((@ quote_span(proc_macro_crate.clone(), tt.span())));
- lit
- } else {
- unreachable!()
- }
- }))
- })),))
- })
- .collect::<TokenStream>();
-
- if after_dollar {
- panic!("unexpected trailing `$` in `quote!`");
- }
-
- quote!([(@ tokens)].iter().cloned().collect::<crate::TokenStream>())
-}
-
-/// Quote a `Span` into a `TokenStream`.
-/// This is needed to implement a custom quoter.
-pub fn quote_span(proc_macro_crate: TokenStream, span: Span) -> TokenStream {
- let id = span.save_span();
- quote!((@ proc_macro_crate ) ::Span::recover_proc_macro_span((@ TokenTree::from(Literal::usize_unsuffixed(id)))))
-}
diff --git a/src/tools/rust-analyzer/crates/proc-macro-srv/src/abis/abi_1_58/ra_server.rs b/src/tools/rust-analyzer/crates/proc-macro-srv/src/abis/abi_1_58/ra_server.rs
deleted file mode 100644
index 22d4ad94f..000000000
--- a/src/tools/rust-analyzer/crates/proc-macro-srv/src/abis/abi_1_58/ra_server.rs
+++ /dev/null
@@ -1,822 +0,0 @@
-//! Rustc proc-macro server implementation with tt
-//!
-//! Based on idea from <https://github.com/fedochet/rust-proc-macro-expander>
-//! The lib-proc-macro server backend is `TokenStream`-agnostic, such that
-//! we could provide any TokenStream implementation.
-//! The original idea from fedochet is using proc-macro2 as backend,
-//! we use tt instead for better integration with RA.
-//!
-//! FIXME: No span and source file information is implemented yet
-
-use super::proc_macro::bridge::{self, server};
-
-use std::collections::HashMap;
-use std::hash::Hash;
-use std::ops::Bound;
-use std::{ascii, vec::IntoIter};
-
-type Group = tt::Subtree;
-type TokenTree = tt::TokenTree;
-type Punct = tt::Punct;
-type Spacing = tt::Spacing;
-type Literal = tt::Literal;
-type Span = tt::TokenId;
-
-#[derive(Debug, Clone)]
-pub struct TokenStream {
- pub token_trees: Vec<TokenTree>,
-}
-
-impl TokenStream {
- pub fn new() -> Self {
- TokenStream { token_trees: Default::default() }
- }
-
- pub fn with_subtree(subtree: tt::Subtree) -> Self {
- if subtree.delimiter.is_some() {
- TokenStream { token_trees: vec![TokenTree::Subtree(subtree)] }
- } else {
- TokenStream { token_trees: subtree.token_trees }
- }
- }
-
- pub fn into_subtree(self) -> tt::Subtree {
- tt::Subtree { delimiter: None, token_trees: self.token_trees }
- }
-
- pub fn is_empty(&self) -> bool {
- self.token_trees.is_empty()
- }
-}
-
-/// Creates a token stream containing a single token tree.
-impl From<TokenTree> for TokenStream {
- fn from(tree: TokenTree) -> TokenStream {
- TokenStream { token_trees: vec![tree] }
- }
-}
-
-/// Collects a number of token trees into a single stream.
-impl FromIterator<TokenTree> for TokenStream {
- fn from_iter<I: IntoIterator<Item = TokenTree>>(trees: I) -> Self {
- trees.into_iter().map(TokenStream::from).collect()
- }
-}
-
-/// A "flattening" operation on token streams, collects token trees
-/// from multiple token streams into a single stream.
-impl FromIterator<TokenStream> for TokenStream {
- fn from_iter<I: IntoIterator<Item = TokenStream>>(streams: I) -> Self {
- let mut builder = TokenStreamBuilder::new();
- streams.into_iter().for_each(|stream| builder.push(stream));
- builder.build()
- }
-}
-
-impl Extend<TokenTree> for TokenStream {
- fn extend<I: IntoIterator<Item = TokenTree>>(&mut self, trees: I) {
- self.extend(trees.into_iter().map(TokenStream::from));
- }
-}
-
-impl Extend<TokenStream> for TokenStream {
- fn extend<I: IntoIterator<Item = TokenStream>>(&mut self, streams: I) {
- for item in streams {
- for tkn in item {
- match tkn {
- tt::TokenTree::Subtree(subtree) if subtree.delimiter.is_none() => {
- self.token_trees.extend(subtree.token_trees);
- }
- _ => {
- self.token_trees.push(tkn);
- }
- }
- }
- }
- }
-}
-
-#[derive(Clone)]
-pub struct SourceFile {
- // FIXME stub
-}
-
-type Level = super::proc_macro::Level;
-type LineColumn = super::proc_macro::LineColumn;
-
-/// A structure representing a diagnostic message and associated children
-/// messages.
-#[derive(Clone, Debug)]
-pub struct Diagnostic {
- level: Level,
- message: String,
- spans: Vec<Span>,
- children: Vec<Diagnostic>,
-}
-
-impl Diagnostic {
- /// Creates a new diagnostic with the given `level` and `message`.
- pub fn new<T: Into<String>>(level: Level, message: T) -> Diagnostic {
- Diagnostic { level, message: message.into(), spans: vec![], children: vec![] }
- }
-}
-
-// Rustc Server Ident has to be `Copyable`
-// We use a stub here for bypassing
-#[derive(Hash, Eq, PartialEq, Copy, Clone)]
-pub struct IdentId(u32);
-
-#[derive(Clone, Hash, Eq, PartialEq)]
-struct IdentData(tt::Ident);
-
-#[derive(Default)]
-struct IdentInterner {
- idents: HashMap<IdentData, u32>,
- ident_data: Vec<IdentData>,
-}
-
-impl IdentInterner {
- fn intern(&mut self, data: &IdentData) -> u32 {
- if let Some(index) = self.idents.get(data) {
- return *index;
- }
-
- let index = self.idents.len() as u32;
- self.ident_data.push(data.clone());
- self.idents.insert(data.clone(), index);
- index
- }
-
- fn get(&self, index: u32) -> &IdentData {
- &self.ident_data[index as usize]
- }
-
- #[allow(unused)]
- fn get_mut(&mut self, index: u32) -> &mut IdentData {
- self.ident_data.get_mut(index as usize).expect("Should be consistent")
- }
-}
-
-pub struct TokenStreamBuilder {
- acc: TokenStream,
-}
-
-/// Public implementation details for the `TokenStream` type, such as iterators.
-pub mod token_stream {
- use std::str::FromStr;
-
- use super::{TokenStream, TokenTree};
-
- /// An iterator over `TokenStream`'s `TokenTree`s.
- /// The iteration is "shallow", e.g., the iterator doesn't recurse into delimited groups,
- /// and returns whole groups as token trees.
- impl IntoIterator for TokenStream {
- type Item = TokenTree;
- type IntoIter = super::IntoIter<TokenTree>;
-
- fn into_iter(self) -> Self::IntoIter {
- self.token_trees.into_iter()
- }
- }
-
- type LexError = String;
-
- /// Attempts to break the string into tokens and parse those tokens into a token stream.
- /// May fail for a number of reasons, for example, if the string contains unbalanced delimiters
- /// or characters not existing in the language.
- /// All tokens in the parsed stream get `Span::call_site()` spans.
- ///
- /// NOTE: some errors may cause panics instead of returning `LexError`. We reserve the right to
- /// change these errors into `LexError`s later.
- impl FromStr for TokenStream {
- type Err = LexError;
-
- fn from_str(src: &str) -> Result<TokenStream, LexError> {
- let (subtree, _token_map) =
- mbe::parse_to_token_tree(src).ok_or("Failed to parse from mbe")?;
-
- let subtree = subtree_replace_token_ids_with_unspecified(subtree);
- Ok(TokenStream::with_subtree(subtree))
- }
- }
-
- impl ToString for TokenStream {
- fn to_string(&self) -> String {
- tt::pretty(&self.token_trees)
- }
- }
-
- fn subtree_replace_token_ids_with_unspecified(subtree: tt::Subtree) -> tt::Subtree {
- tt::Subtree {
- delimiter: subtree
- .delimiter
- .map(|d| tt::Delimiter { id: tt::TokenId::unspecified(), ..d }),
- token_trees: subtree
- .token_trees
- .into_iter()
- .map(token_tree_replace_token_ids_with_unspecified)
- .collect(),
- }
- }
-
- fn token_tree_replace_token_ids_with_unspecified(tt: tt::TokenTree) -> tt::TokenTree {
- match tt {
- tt::TokenTree::Leaf(leaf) => {
- tt::TokenTree::Leaf(leaf_replace_token_ids_with_unspecified(leaf))
- }
- tt::TokenTree::Subtree(subtree) => {
- tt::TokenTree::Subtree(subtree_replace_token_ids_with_unspecified(subtree))
- }
- }
- }
-
- fn leaf_replace_token_ids_with_unspecified(leaf: tt::Leaf) -> tt::Leaf {
- match leaf {
- tt::Leaf::Literal(lit) => {
- tt::Leaf::Literal(tt::Literal { id: tt::TokenId::unspecified(), ..lit })
- }
- tt::Leaf::Punct(punct) => {
- tt::Leaf::Punct(tt::Punct { id: tt::TokenId::unspecified(), ..punct })
- }
- tt::Leaf::Ident(ident) => {
- tt::Leaf::Ident(tt::Ident { id: tt::TokenId::unspecified(), ..ident })
- }
- }
- }
-}
-
-impl TokenStreamBuilder {
- fn new() -> TokenStreamBuilder {
- TokenStreamBuilder { acc: TokenStream::new() }
- }
-
- fn push(&mut self, stream: TokenStream) {
- self.acc.extend(stream.into_iter())
- }
-
- fn build(self) -> TokenStream {
- self.acc
- }
-}
-
-pub struct FreeFunctions;
-
-#[derive(Clone)]
-pub struct TokenStreamIter {
- trees: IntoIter<TokenTree>,
-}
-
-#[derive(Default)]
-pub struct RustAnalyzer {
- ident_interner: IdentInterner,
- // FIXME: store span information here.
-}
-
-impl server::Types for RustAnalyzer {
- type FreeFunctions = FreeFunctions;
- type TokenStream = TokenStream;
- type TokenStreamBuilder = TokenStreamBuilder;
- type TokenStreamIter = TokenStreamIter;
- type Group = Group;
- type Punct = Punct;
- type Ident = IdentId;
- type Literal = Literal;
- type SourceFile = SourceFile;
- type Diagnostic = Diagnostic;
- type Span = Span;
- type MultiSpan = Vec<Span>;
-}
-
-impl server::FreeFunctions for RustAnalyzer {
- fn track_env_var(&mut self, _var: &str, _value: Option<&str>) {
- // FIXME: track env var accesses
- // https://github.com/rust-lang/rust/pull/71858
- }
- fn track_path(&mut self, _path: &str) {}
-}
-
-impl server::TokenStream for RustAnalyzer {
- fn new(&mut self) -> Self::TokenStream {
- Self::TokenStream::new()
- }
-
- fn is_empty(&mut self, stream: &Self::TokenStream) -> bool {
- stream.is_empty()
- }
- fn from_str(&mut self, src: &str) -> Self::TokenStream {
- use std::str::FromStr;
-
- Self::TokenStream::from_str(src).expect("cannot parse string")
- }
- fn to_string(&mut self, stream: &Self::TokenStream) -> String {
- stream.to_string()
- }
- fn from_token_tree(
- &mut self,
- tree: bridge::TokenTree<Self::Group, Self::Punct, Self::Ident, Self::Literal>,
- ) -> Self::TokenStream {
- match tree {
- bridge::TokenTree::Group(group) => {
- let tree = TokenTree::from(group);
- Self::TokenStream::from_iter(vec![tree])
- }
-
- bridge::TokenTree::Ident(IdentId(index)) => {
- let IdentData(ident) = self.ident_interner.get(index).clone();
- let ident: tt::Ident = ident;
- let leaf = tt::Leaf::from(ident);
- let tree = TokenTree::from(leaf);
- Self::TokenStream::from_iter(vec![tree])
- }
-
- bridge::TokenTree::Literal(literal) => {
- let leaf = tt::Leaf::from(literal);
- let tree = TokenTree::from(leaf);
- Self::TokenStream::from_iter(vec![tree])
- }
-
- bridge::TokenTree::Punct(p) => {
- let leaf = tt::Leaf::from(p);
- let tree = TokenTree::from(leaf);
- Self::TokenStream::from_iter(vec![tree])
- }
- }
- }
-
- fn into_iter(&mut self, stream: Self::TokenStream) -> Self::TokenStreamIter {
- let trees: Vec<TokenTree> = stream.into_iter().collect();
- TokenStreamIter { trees: trees.into_iter() }
- }
-
- fn expand_expr(&mut self, self_: &Self::TokenStream) -> Result<Self::TokenStream, ()> {
- Ok(self_.clone())
- }
-}
-
-impl server::TokenStreamBuilder for RustAnalyzer {
- fn new(&mut self) -> Self::TokenStreamBuilder {
- Self::TokenStreamBuilder::new()
- }
- fn push(&mut self, builder: &mut Self::TokenStreamBuilder, stream: Self::TokenStream) {
- builder.push(stream)
- }
- fn build(&mut self, builder: Self::TokenStreamBuilder) -> Self::TokenStream {
- builder.build()
- }
-}
-
-impl server::TokenStreamIter for RustAnalyzer {
- fn next(
- &mut self,
- iter: &mut Self::TokenStreamIter,
- ) -> Option<bridge::TokenTree<Self::Group, Self::Punct, Self::Ident, Self::Literal>> {
- iter.trees.next().map(|tree| match tree {
- TokenTree::Subtree(group) => bridge::TokenTree::Group(group),
- TokenTree::Leaf(tt::Leaf::Ident(ident)) => {
- bridge::TokenTree::Ident(IdentId(self.ident_interner.intern(&IdentData(ident))))
- }
- TokenTree::Leaf(tt::Leaf::Literal(literal)) => bridge::TokenTree::Literal(literal),
- TokenTree::Leaf(tt::Leaf::Punct(punct)) => bridge::TokenTree::Punct(punct),
- })
- }
-}
-
-fn delim_to_internal(d: bridge::Delimiter) -> Option<tt::Delimiter> {
- let kind = match d {
- bridge::Delimiter::Parenthesis => tt::DelimiterKind::Parenthesis,
- bridge::Delimiter::Brace => tt::DelimiterKind::Brace,
- bridge::Delimiter::Bracket => tt::DelimiterKind::Bracket,
- bridge::Delimiter::None => return None,
- };
- Some(tt::Delimiter { id: tt::TokenId::unspecified(), kind })
-}
-
-fn delim_to_external(d: Option<tt::Delimiter>) -> bridge::Delimiter {
- match d.map(|it| it.kind) {
- Some(tt::DelimiterKind::Parenthesis) => bridge::Delimiter::Parenthesis,
- Some(tt::DelimiterKind::Brace) => bridge::Delimiter::Brace,
- Some(tt::DelimiterKind::Bracket) => bridge::Delimiter::Bracket,
- None => bridge::Delimiter::None,
- }
-}
-
-fn spacing_to_internal(spacing: bridge::Spacing) -> Spacing {
- match spacing {
- bridge::Spacing::Alone => Spacing::Alone,
- bridge::Spacing::Joint => Spacing::Joint,
- }
-}
-
-fn spacing_to_external(spacing: Spacing) -> bridge::Spacing {
- match spacing {
- Spacing::Alone => bridge::Spacing::Alone,
- Spacing::Joint => bridge::Spacing::Joint,
- }
-}
-
-impl server::Group for RustAnalyzer {
- fn new(&mut self, delimiter: bridge::Delimiter, stream: Self::TokenStream) -> Self::Group {
- Self::Group { delimiter: delim_to_internal(delimiter), token_trees: stream.token_trees }
- }
- fn delimiter(&mut self, group: &Self::Group) -> bridge::Delimiter {
- delim_to_external(group.delimiter)
- }
-
- // NOTE: Return value of do not include delimiter
- fn stream(&mut self, group: &Self::Group) -> Self::TokenStream {
- TokenStream { token_trees: group.token_trees.clone() }
- }
-
- fn span(&mut self, group: &Self::Group) -> Self::Span {
- group.delimiter.map(|it| it.id).unwrap_or_else(tt::TokenId::unspecified)
- }
-
- fn set_span(&mut self, group: &mut Self::Group, span: Self::Span) {
- if let Some(delim) = &mut group.delimiter {
- delim.id = span;
- }
- }
-
- fn span_open(&mut self, group: &Self::Group) -> Self::Span {
- // FIXME we only store one `TokenId` for the delimiters
- group.delimiter.map(|it| it.id).unwrap_or_else(tt::TokenId::unspecified)
- }
-
- fn span_close(&mut self, group: &Self::Group) -> Self::Span {
- // FIXME we only store one `TokenId` for the delimiters
- group.delimiter.map(|it| it.id).unwrap_or_else(tt::TokenId::unspecified)
- }
-}
-
-impl server::Punct for RustAnalyzer {
- fn new(&mut self, ch: char, spacing: bridge::Spacing) -> Self::Punct {
- tt::Punct {
- char: ch,
- spacing: spacing_to_internal(spacing),
- id: tt::TokenId::unspecified(),
- }
- }
- fn as_char(&mut self, punct: Self::Punct) -> char {
- punct.char
- }
- fn spacing(&mut self, punct: Self::Punct) -> bridge::Spacing {
- spacing_to_external(punct.spacing)
- }
- fn span(&mut self, punct: Self::Punct) -> Self::Span {
- punct.id
- }
- fn with_span(&mut self, punct: Self::Punct, span: Self::Span) -> Self::Punct {
- tt::Punct { id: span, ..punct }
- }
-}
-
-impl server::Ident for RustAnalyzer {
- fn new(&mut self, string: &str, span: Self::Span, is_raw: bool) -> Self::Ident {
- IdentId(self.ident_interner.intern(&IdentData(tt::Ident::new_with_is_raw(
- string.into(),
- span,
- is_raw,
- ))))
- }
-
- fn span(&mut self, ident: Self::Ident) -> Self::Span {
- self.ident_interner.get(ident.0).0.id
- }
- fn with_span(&mut self, ident: Self::Ident, span: Self::Span) -> Self::Ident {
- let data = self.ident_interner.get(ident.0);
- let new = IdentData(tt::Ident { id: span, ..data.0.clone() });
- IdentId(self.ident_interner.intern(&new))
- }
-}
-
-impl server::Literal for RustAnalyzer {
- fn debug_kind(&mut self, _literal: &Self::Literal) -> String {
- // r-a: debug_kind and suffix are unsupported; corresponding client code has been changed to not call these.
- // They must still be present to be ABI-compatible and work with upstream proc_macro.
- "".to_owned()
- }
- fn from_str(&mut self, s: &str) -> Result<Self::Literal, ()> {
- Ok(Literal { text: s.into(), id: tt::TokenId::unspecified() })
- }
- fn symbol(&mut self, literal: &Self::Literal) -> String {
- literal.text.to_string()
- }
- fn suffix(&mut self, _literal: &Self::Literal) -> Option<String> {
- None
- }
-
- fn to_string(&mut self, literal: &Self::Literal) -> String {
- literal.to_string()
- }
-
- fn integer(&mut self, n: &str) -> Self::Literal {
- let n = match n.parse::<i128>() {
- Ok(n) => n.to_string(),
- Err(_) => n.parse::<u128>().unwrap().to_string(),
- };
- Literal { text: n.into(), id: tt::TokenId::unspecified() }
- }
-
- fn typed_integer(&mut self, n: &str, kind: &str) -> Self::Literal {
- macro_rules! def_suffixed_integer {
- ($kind:ident, $($ty:ty),*) => {
- match $kind {
- $(
- stringify!($ty) => {
- let n: $ty = n.parse().unwrap();
- format!(concat!("{}", stringify!($ty)), n)
- }
- )*
- _ => unimplemented!("unknown args for typed_integer: n {}, kind {}", n, $kind),
- }
- }
- }
-
- let text = def_suffixed_integer! {kind, u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize};
-
- Literal { text: text.into(), id: tt::TokenId::unspecified() }
- }
-
- fn float(&mut self, n: &str) -> Self::Literal {
- let n: f64 = n.parse().unwrap();
- let mut text = f64::to_string(&n);
- if !text.contains('.') {
- text += ".0"
- }
- Literal { text: text.into(), id: tt::TokenId::unspecified() }
- }
-
- fn f32(&mut self, n: &str) -> Self::Literal {
- let n: f32 = n.parse().unwrap();
- let text = format!("{n}f32");
- Literal { text: text.into(), id: tt::TokenId::unspecified() }
- }
-
- fn f64(&mut self, n: &str) -> Self::Literal {
- let n: f64 = n.parse().unwrap();
- let text = format!("{n}f64");
- Literal { text: text.into(), id: tt::TokenId::unspecified() }
- }
-
- fn string(&mut self, string: &str) -> Self::Literal {
- let mut escaped = String::new();
- for ch in string.chars() {
- escaped.extend(ch.escape_debug());
- }
- Literal { text: format!("\"{escaped}\"").into(), id: tt::TokenId::unspecified() }
- }
-
- fn character(&mut self, ch: char) -> Self::Literal {
- Literal { text: format!("'{ch}'").into(), id: tt::TokenId::unspecified() }
- }
-
- fn byte_string(&mut self, bytes: &[u8]) -> Self::Literal {
- let string = bytes
- .iter()
- .cloned()
- .flat_map(ascii::escape_default)
- .map(Into::<char>::into)
- .collect::<String>();
-
- Literal { text: format!("b\"{string}\"").into(), id: tt::TokenId::unspecified() }
- }
-
- fn span(&mut self, literal: &Self::Literal) -> Self::Span {
- literal.id
- }
-
- fn set_span(&mut self, literal: &mut Self::Literal, span: Self::Span) {
- literal.id = span;
- }
-
- fn subspan(
- &mut self,
- _literal: &Self::Literal,
- _start: Bound<usize>,
- _end: Bound<usize>,
- ) -> Option<Self::Span> {
- // FIXME handle span
- None
- }
-}
-
-impl server::SourceFile for RustAnalyzer {
- // FIXME these are all stubs
- fn eq(&mut self, _file1: &Self::SourceFile, _file2: &Self::SourceFile) -> bool {
- true
- }
- fn path(&mut self, _file: &Self::SourceFile) -> String {
- String::new()
- }
- fn is_real(&mut self, _file: &Self::SourceFile) -> bool {
- true
- }
-}
-
-impl server::Diagnostic for RustAnalyzer {
- fn new(&mut self, level: Level, msg: &str, spans: Self::MultiSpan) -> Self::Diagnostic {
- let mut diag = Diagnostic::new(level, msg);
- diag.spans = spans;
- diag
- }
-
- fn sub(
- &mut self,
- _diag: &mut Self::Diagnostic,
- _level: Level,
- _msg: &str,
- _spans: Self::MultiSpan,
- ) {
- // FIXME handle diagnostic
- //
- }
-
- fn emit(&mut self, _diag: Self::Diagnostic) {
- // FIXME handle diagnostic
- // diag.emit()
- }
-}
-
-impl server::Span for RustAnalyzer {
- fn debug(&mut self, span: Self::Span) -> String {
- format!("{:?}", span.0)
- }
- fn def_site(&mut self) -> Self::Span {
- // MySpan(self.span_interner.intern(&MySpanData(Span::def_site())))
- // FIXME handle span
- tt::TokenId::unspecified()
- }
- fn call_site(&mut self) -> Self::Span {
- // MySpan(self.span_interner.intern(&MySpanData(Span::call_site())))
- // FIXME handle span
- tt::TokenId::unspecified()
- }
- fn source_file(&mut self, _span: Self::Span) -> Self::SourceFile {
- SourceFile {}
- }
- fn save_span(&mut self, _span: Self::Span) -> usize {
- // FIXME stub
- 0
- }
- fn recover_proc_macro_span(&mut self, _id: usize) -> Self::Span {
- // FIXME stub
- tt::TokenId::unspecified()
- }
- /// Recent feature, not yet in the proc_macro
- ///
- /// See PR:
- /// https://github.com/rust-lang/rust/pull/55780
- fn source_text(&mut self, _span: Self::Span) -> Option<String> {
- None
- }
-
- fn parent(&mut self, _span: Self::Span) -> Option<Self::Span> {
- // FIXME handle span
- None
- }
- fn source(&mut self, span: Self::Span) -> Self::Span {
- // FIXME handle span
- span
- }
- fn start(&mut self, _span: Self::Span) -> LineColumn {
- // FIXME handle span
- LineColumn { line: 0, column: 0 }
- }
- fn end(&mut self, _span: Self::Span) -> LineColumn {
- // FIXME handle span
- LineColumn { line: 0, column: 0 }
- }
- fn join(&mut self, first: Self::Span, _second: Self::Span) -> Option<Self::Span> {
- // Just return the first span again, because some macros will unwrap the result.
- Some(first)
- }
- fn resolved_at(&mut self, _span: Self::Span, _at: Self::Span) -> Self::Span {
- // FIXME handle span
- tt::TokenId::unspecified()
- }
-
- fn mixed_site(&mut self) -> Self::Span {
- // FIXME handle span
- tt::TokenId::unspecified()
- }
-
- fn after(&mut self, _self_: Self::Span) -> Self::Span {
- tt::TokenId::unspecified()
- }
-
- fn before(&mut self, _self_: Self::Span) -> Self::Span {
- tt::TokenId::unspecified()
- }
-}
-
-impl server::MultiSpan for RustAnalyzer {
- fn new(&mut self) -> Self::MultiSpan {
- // FIXME handle span
- vec![]
- }
-
- fn push(&mut self, other: &mut Self::MultiSpan, span: Self::Span) {
- //TODP
- other.push(span)
- }
-}
-
-#[cfg(test)]
-mod tests {
- use super::super::proc_macro::bridge::server::Literal;
- use super::*;
-
- #[test]
- fn test_ra_server_literals() {
- let mut srv = RustAnalyzer { ident_interner: IdentInterner::default() };
- assert_eq!(srv.integer("1234").text, "1234");
-
- assert_eq!(srv.typed_integer("12", "u8").text, "12u8");
- assert_eq!(srv.typed_integer("255", "u16").text, "255u16");
- assert_eq!(srv.typed_integer("1234", "u32").text, "1234u32");
- assert_eq!(srv.typed_integer("15846685", "u64").text, "15846685u64");
- assert_eq!(srv.typed_integer("15846685258", "u128").text, "15846685258u128");
- assert_eq!(srv.typed_integer("156788984", "usize").text, "156788984usize");
- assert_eq!(srv.typed_integer("127", "i8").text, "127i8");
- assert_eq!(srv.typed_integer("255", "i16").text, "255i16");
- assert_eq!(srv.typed_integer("1234", "i32").text, "1234i32");
- assert_eq!(srv.typed_integer("15846685", "i64").text, "15846685i64");
- assert_eq!(srv.typed_integer("15846685258", "i128").text, "15846685258i128");
- assert_eq!(srv.float("0").text, "0.0");
- assert_eq!(srv.float("15684.5867").text, "15684.5867");
- assert_eq!(srv.f32("15684.58").text, "15684.58f32");
- assert_eq!(srv.f64("15684.58").text, "15684.58f64");
-
- assert_eq!(srv.string("hello_world").text, "\"hello_world\"");
- assert_eq!(srv.character('c').text, "'c'");
- assert_eq!(srv.byte_string(b"1234586\x88").text, "b\"1234586\\x88\"");
-
- // u128::max
- assert_eq!(
- srv.integer("340282366920938463463374607431768211455").text,
- "340282366920938463463374607431768211455"
- );
- // i128::min
- assert_eq!(
- srv.integer("-170141183460469231731687303715884105728").text,
- "-170141183460469231731687303715884105728"
- );
- }
-
- #[test]
- fn test_ra_server_to_string() {
- let s = TokenStream {
- token_trees: vec![
- tt::TokenTree::Leaf(tt::Leaf::Ident(tt::Ident {
- text: "struct".into(),
- id: tt::TokenId::unspecified(),
- })),
- tt::TokenTree::Leaf(tt::Leaf::Ident(tt::Ident {
- text: "T".into(),
- id: tt::TokenId::unspecified(),
- })),
- tt::TokenTree::Subtree(tt::Subtree {
- delimiter: Some(tt::Delimiter {
- id: tt::TokenId::unspecified(),
- kind: tt::DelimiterKind::Brace,
- }),
- token_trees: vec![],
- }),
- ],
- };
-
- assert_eq!(s.to_string(), "struct T {}");
- }
-
- #[test]
- fn test_ra_server_from_str() {
- use std::str::FromStr;
- let subtree_paren_a = tt::TokenTree::Subtree(tt::Subtree {
- delimiter: Some(tt::Delimiter {
- id: tt::TokenId::unspecified(),
- kind: tt::DelimiterKind::Parenthesis,
- }),
- token_trees: vec![tt::TokenTree::Leaf(tt::Leaf::Ident(tt::Ident {
- text: "a".into(),
- id: tt::TokenId::unspecified(),
- }))],
- });
-
- let t1 = TokenStream::from_str("(a)").unwrap();
- assert_eq!(t1.token_trees.len(), 1);
- assert_eq!(t1.token_trees[0], subtree_paren_a);
-
- let t2 = TokenStream::from_str("(a);").unwrap();
- assert_eq!(t2.token_trees.len(), 2);
- assert_eq!(t2.token_trees[0], subtree_paren_a);
-
- let underscore = TokenStream::from_str("_").unwrap();
- assert_eq!(
- underscore.token_trees[0],
- tt::TokenTree::Leaf(tt::Leaf::Ident(tt::Ident {
- text: "_".into(),
- id: tt::TokenId::unspecified(),
- }))
- );
- }
-}
diff --git a/src/tools/rust-analyzer/crates/proc-macro-srv/src/abis/abi_1_63/mod.rs b/src/tools/rust-analyzer/crates/proc-macro-srv/src/abis/abi_1_63/mod.rs
index 76e89e319..93805c893 100644
--- a/src/tools/rust-analyzer/crates/proc-macro-srv/src/abis/abi_1_63/mod.rs
+++ b/src/tools/rust-analyzer/crates/proc-macro-srv/src/abis/abi_1_63/mod.rs
@@ -11,6 +11,7 @@ mod ra_server;
use libloading::Library;
use proc_macro_api::ProcMacroKind;
+use super::tt;
use super::PanicMessage;
pub use ra_server::TokenStream;
diff --git a/src/tools/rust-analyzer/crates/proc-macro-srv/src/abis/abi_1_63/proc_macro/mod.rs b/src/tools/rust-analyzer/crates/proc-macro-srv/src/abis/abi_1_63/proc_macro/mod.rs
index 7ab1f421d..89bd10da5 100644
--- a/src/tools/rust-analyzer/crates/proc-macro-srv/src/abis/abi_1_63/proc_macro/mod.rs
+++ b/src/tools/rust-analyzer/crates/proc-macro-srv/src/abis/abi_1_63/proc_macro/mod.rs
@@ -124,8 +124,8 @@ impl FromStr for TokenStream {
/// into the same token stream (modulo spans), except for possibly `TokenTree::Group`s
/// with `Delimiter::None` delimiters and negative numeric literals.
impl fmt::Display for TokenStream {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- f.write_str(&self.to_string())
+ fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ unimplemented!()
}
}
@@ -572,8 +572,8 @@ impl From<Literal> for TokenTree {
/// into the same token tree (modulo spans), except for possibly `TokenTree::Group`s
/// with `Delimiter::None` delimiters and negative numeric literals.
impl fmt::Display for TokenTree {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- f.write_str(&self.to_string())
+ fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ unimplemented!()
}
}
@@ -669,8 +669,8 @@ impl Group {
/// into the same group (modulo spans), except for possibly `TokenTree::Group`s
/// with `Delimiter::None` delimiters.
impl fmt::Display for Group {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- f.write_str(&self.to_string())
+ fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ unimplemented!()
}
}
@@ -743,8 +743,8 @@ impl Punct {
/// Prints the punctuation character as a string that should be losslessly convertible
/// back into the same character.
impl fmt::Display for Punct {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- f.write_str(&self.to_string())
+ fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ unimplemented!()
}
}
@@ -821,8 +821,8 @@ impl Ident {
/// Prints the identifier as a string that should be losslessly convertible
/// back into the same identifier.
impl fmt::Display for Ident {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- f.write_str(&self.to_string())
+ fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ unimplemented!()
}
}
@@ -1064,8 +1064,8 @@ impl FromStr for Literal {
/// Prints the literal as a string that should be losslessly convertible
/// back into the same literal (except for possible rounding for floating point literals).
impl fmt::Display for Literal {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- f.write_str(&self.to_string())
+ fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ unimplemented!()
}
}
diff --git a/src/tools/rust-analyzer/crates/proc-macro-srv/src/abis/abi_1_63/ra_server.rs b/src/tools/rust-analyzer/crates/proc-macro-srv/src/abis/abi_1_63/ra_server.rs
index f82f20c37..30baf3a13 100644
--- a/src/tools/rust-analyzer/crates/proc-macro-srv/src/abis/abi_1_63/ra_server.rs
+++ b/src/tools/rust-analyzer/crates/proc-macro-srv/src/abis/abi_1_63/ra_server.rs
@@ -15,6 +15,8 @@ use std::hash::Hash;
use std::ops::Bound;
use std::{ascii, vec::IntoIter};
+use crate::tt;
+
type Group = tt::Subtree;
type TokenTree = tt::TokenTree;
type Punct = tt::Punct;
@@ -33,7 +35,7 @@ impl TokenStream {
}
pub fn with_subtree(subtree: tt::Subtree) -> Self {
- if subtree.delimiter.is_some() {
+ if subtree.delimiter.kind != tt::DelimiterKind::Invisible {
TokenStream { token_trees: vec![TokenTree::Subtree(subtree)] }
} else {
TokenStream { token_trees: subtree.token_trees }
@@ -41,7 +43,7 @@ impl TokenStream {
}
pub fn into_subtree(self) -> tt::Subtree {
- tt::Subtree { delimiter: None, token_trees: self.token_trees }
+ tt::Subtree { delimiter: tt::Delimiter::UNSPECIFIED, token_trees: self.token_trees }
}
pub fn is_empty(&self) -> bool {
@@ -84,7 +86,9 @@ impl Extend<TokenStream> for TokenStream {
for item in streams {
for tkn in item {
match tkn {
- tt::TokenTree::Subtree(subtree) if subtree.delimiter.is_none() => {
+ tt::TokenTree::Subtree(subtree)
+ if subtree.delimiter.kind == tt::DelimiterKind::Invisible =>
+ {
self.token_trees.extend(subtree.token_trees);
}
_ => {
@@ -165,7 +169,7 @@ pub struct TokenStreamBuilder {
pub mod token_stream {
use std::str::FromStr;
- use super::{TokenStream, TokenTree};
+ use super::{tt, TokenStream, TokenTree};
/// An iterator over `TokenStream`'s `TokenTree`s.
/// The iteration is "shallow", e.g., the iterator doesn't recurse into delimited groups,
@@ -202,15 +206,17 @@ pub mod token_stream {
impl ToString for TokenStream {
fn to_string(&self) -> String {
- tt::pretty(&self.token_trees)
+ ::tt::pretty(&self.token_trees)
}
}
fn subtree_replace_token_ids_with_unspecified(subtree: tt::Subtree) -> tt::Subtree {
tt::Subtree {
- delimiter: subtree
- .delimiter
- .map(|d| tt::Delimiter { id: tt::TokenId::unspecified(), ..d }),
+ delimiter: tt::Delimiter {
+ open: tt::TokenId::UNSPECIFIED,
+ close: tt::TokenId::UNSPECIFIED,
+ ..subtree.delimiter
+ },
token_trees: subtree
.token_trees
.into_iter()
@@ -233,13 +239,13 @@ pub mod token_stream {
fn leaf_replace_token_ids_with_unspecified(leaf: tt::Leaf) -> tt::Leaf {
match leaf {
tt::Leaf::Literal(lit) => {
- tt::Leaf::Literal(tt::Literal { id: tt::TokenId::unspecified(), ..lit })
+ tt::Leaf::Literal(tt::Literal { span: tt::TokenId::unspecified(), ..lit })
}
tt::Leaf::Punct(punct) => {
- tt::Leaf::Punct(tt::Punct { id: tt::TokenId::unspecified(), ..punct })
+ tt::Leaf::Punct(tt::Punct { span: tt::TokenId::unspecified(), ..punct })
}
tt::Leaf::Ident(ident) => {
- tt::Leaf::Ident(tt::Ident { id: tt::TokenId::unspecified(), ..ident })
+ tt::Leaf::Ident(tt::Ident { span: tt::TokenId::unspecified(), ..ident })
}
}
}
@@ -389,22 +395,22 @@ impl server::TokenStream for RustAnalyzer {
}
}
-fn delim_to_internal(d: bridge::Delimiter) -> Option<tt::Delimiter> {
+fn delim_to_internal(d: bridge::Delimiter) -> tt::Delimiter {
let kind = match d {
bridge::Delimiter::Parenthesis => tt::DelimiterKind::Parenthesis,
bridge::Delimiter::Brace => tt::DelimiterKind::Brace,
bridge::Delimiter::Bracket => tt::DelimiterKind::Bracket,
- bridge::Delimiter::None => return None,
+ bridge::Delimiter::None => tt::DelimiterKind::Invisible,
};
- Some(tt::Delimiter { id: tt::TokenId::unspecified(), kind })
+ tt::Delimiter { open: tt::TokenId::unspecified(), close: tt::TokenId::unspecified(), kind }
}
-fn delim_to_external(d: Option<tt::Delimiter>) -> bridge::Delimiter {
- match d.map(|it| it.kind) {
- Some(tt::DelimiterKind::Parenthesis) => bridge::Delimiter::Parenthesis,
- Some(tt::DelimiterKind::Brace) => bridge::Delimiter::Brace,
- Some(tt::DelimiterKind::Bracket) => bridge::Delimiter::Bracket,
- None => bridge::Delimiter::None,
+fn delim_to_external(d: tt::Delimiter) -> bridge::Delimiter {
+ match d.kind {
+ tt::DelimiterKind::Parenthesis => bridge::Delimiter::Parenthesis,
+ tt::DelimiterKind::Brace => bridge::Delimiter::Brace,
+ tt::DelimiterKind::Bracket => bridge::Delimiter::Bracket,
+ tt::DelimiterKind::Invisible => bridge::Delimiter::None,
}
}
@@ -443,23 +449,19 @@ impl server::Group for RustAnalyzer {
}
fn span(&mut self, group: &Self::Group) -> Self::Span {
- group.delimiter.map(|it| it.id).unwrap_or_else(tt::TokenId::unspecified)
+ group.delimiter.open
}
fn set_span(&mut self, group: &mut Self::Group, span: Self::Span) {
- if let Some(delim) = &mut group.delimiter {
- delim.id = span;
- }
+ group.delimiter.open = span;
}
fn span_open(&mut self, group: &Self::Group) -> Self::Span {
- // FIXME we only store one `TokenId` for the delimiters
- group.delimiter.map(|it| it.id).unwrap_or_else(tt::TokenId::unspecified)
+ group.delimiter.open
}
fn span_close(&mut self, group: &Self::Group) -> Self::Span {
- // FIXME we only store one `TokenId` for the delimiters
- group.delimiter.map(|it| it.id).unwrap_or_else(tt::TokenId::unspecified)
+ group.delimiter.close
}
}
@@ -468,7 +470,7 @@ impl server::Punct for RustAnalyzer {
tt::Punct {
char: ch,
spacing: spacing_to_internal(spacing),
- id: tt::TokenId::unspecified(),
+ span: tt::TokenId::unspecified(),
}
}
fn as_char(&mut self, punct: Self::Punct) -> char {
@@ -478,28 +480,27 @@ impl server::Punct for RustAnalyzer {
spacing_to_external(punct.spacing)
}
fn span(&mut self, punct: Self::Punct) -> Self::Span {
- punct.id
+ punct.span
}
fn with_span(&mut self, punct: Self::Punct, span: Self::Span) -> Self::Punct {
- tt::Punct { id: span, ..punct }
+ tt::Punct { span: span, ..punct }
}
}
impl server::Ident for RustAnalyzer {
fn new(&mut self, string: &str, span: Self::Span, is_raw: bool) -> Self::Ident {
- IdentId(self.ident_interner.intern(&IdentData(tt::Ident::new_with_is_raw(
- string.into(),
+ IdentId(self.ident_interner.intern(&IdentData(tt::Ident {
+ text: if is_raw { ::tt::SmolStr::from_iter(["r#", string]) } else { string.into() },
span,
- is_raw,
- ))))
+ })))
}
fn span(&mut self, ident: Self::Ident) -> Self::Span {
- self.ident_interner.get(ident.0).0.id
+ self.ident_interner.get(ident.0).0.span
}
fn with_span(&mut self, ident: Self::Ident, span: Self::Span) -> Self::Ident {
let data = self.ident_interner.get(ident.0);
- let new = IdentData(tt::Ident { id: span, ..data.0.clone() });
+ let new = IdentData(tt::Ident { span: span, ..data.0.clone() });
IdentId(self.ident_interner.intern(&new))
}
}
@@ -511,7 +512,7 @@ impl server::Literal for RustAnalyzer {
"".to_owned()
}
fn from_str(&mut self, s: &str) -> Result<Self::Literal, ()> {
- Ok(Literal { text: s.into(), id: tt::TokenId::unspecified() })
+ Ok(Literal { text: s.into(), span: tt::TokenId::unspecified() })
}
fn symbol(&mut self, literal: &Self::Literal) -> String {
literal.text.to_string()
@@ -529,7 +530,7 @@ impl server::Literal for RustAnalyzer {
Ok(n) => n.to_string(),
Err(_) => n.parse::<u128>().unwrap().to_string(),
};
- Literal { text: n.into(), id: tt::TokenId::unspecified() }
+ Literal { text: n.into(), span: tt::TokenId::unspecified() }
}
fn typed_integer(&mut self, n: &str, kind: &str) -> Self::Literal {
@@ -549,7 +550,7 @@ impl server::Literal for RustAnalyzer {
let text = def_suffixed_integer! {kind, u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize};
- Literal { text: text.into(), id: tt::TokenId::unspecified() }
+ Literal { text: text.into(), span: tt::TokenId::unspecified() }
}
fn float(&mut self, n: &str) -> Self::Literal {
@@ -558,19 +559,19 @@ impl server::Literal for RustAnalyzer {
if !text.contains('.') {
text += ".0"
}
- Literal { text: text.into(), id: tt::TokenId::unspecified() }
+ Literal { text: text.into(), span: tt::TokenId::unspecified() }
}
fn f32(&mut self, n: &str) -> Self::Literal {
let n: f32 = n.parse().unwrap();
let text = format!("{n}f32");
- Literal { text: text.into(), id: tt::TokenId::unspecified() }
+ Literal { text: text.into(), span: tt::TokenId::unspecified() }
}
fn f64(&mut self, n: &str) -> Self::Literal {
let n: f64 = n.parse().unwrap();
let text = format!("{n}f64");
- Literal { text: text.into(), id: tt::TokenId::unspecified() }
+ Literal { text: text.into(), span: tt::TokenId::unspecified() }
}
fn string(&mut self, string: &str) -> Self::Literal {
@@ -578,11 +579,11 @@ impl server::Literal for RustAnalyzer {
for ch in string.chars() {
escaped.extend(ch.escape_debug());
}
- Literal { text: format!("\"{escaped}\"").into(), id: tt::TokenId::unspecified() }
+ Literal { text: format!("\"{escaped}\"").into(), span: tt::TokenId::unspecified() }
}
fn character(&mut self, ch: char) -> Self::Literal {
- Literal { text: format!("'{ch}'").into(), id: tt::TokenId::unspecified() }
+ Literal { text: format!("'{ch}'").into(), span: tt::TokenId::unspecified() }
}
fn byte_string(&mut self, bytes: &[u8]) -> Self::Literal {
@@ -593,15 +594,15 @@ impl server::Literal for RustAnalyzer {
.map(Into::<char>::into)
.collect::<String>();
- Literal { text: format!("b\"{string}\"").into(), id: tt::TokenId::unspecified() }
+ Literal { text: format!("b\"{string}\"").into(), span: tt::TokenId::unspecified() }
}
fn span(&mut self, literal: &Self::Literal) -> Self::Span {
- literal.id
+ literal.span
}
fn set_span(&mut self, literal: &mut Self::Literal, span: Self::Span) {
- literal.id = span;
+ literal.span = span;
}
fn subspan(
@@ -784,17 +785,18 @@ mod tests {
token_trees: vec![
tt::TokenTree::Leaf(tt::Leaf::Ident(tt::Ident {
text: "struct".into(),
- id: tt::TokenId::unspecified(),
+ span: tt::TokenId::unspecified(),
})),
tt::TokenTree::Leaf(tt::Leaf::Ident(tt::Ident {
text: "T".into(),
- id: tt::TokenId::unspecified(),
+ span: tt::TokenId::unspecified(),
})),
tt::TokenTree::Subtree(tt::Subtree {
- delimiter: Some(tt::Delimiter {
- id: tt::TokenId::unspecified(),
+ delimiter: tt::Delimiter {
+ open: tt::TokenId::unspecified(),
+ close: tt::TokenId::unspecified(),
kind: tt::DelimiterKind::Brace,
- }),
+ },
token_trees: vec![],
}),
],
@@ -807,13 +809,14 @@ mod tests {
fn test_ra_server_from_str() {
use std::str::FromStr;
let subtree_paren_a = tt::TokenTree::Subtree(tt::Subtree {
- delimiter: Some(tt::Delimiter {
- id: tt::TokenId::unspecified(),
+ delimiter: tt::Delimiter {
+ open: tt::TokenId::unspecified(),
+ close: tt::TokenId::unspecified(),
kind: tt::DelimiterKind::Parenthesis,
- }),
+ },
token_trees: vec![tt::TokenTree::Leaf(tt::Leaf::Ident(tt::Ident {
text: "a".into(),
- id: tt::TokenId::unspecified(),
+ span: tt::TokenId::unspecified(),
}))],
});
@@ -830,7 +833,7 @@ mod tests {
underscore.token_trees[0],
tt::TokenTree::Leaf(tt::Leaf::Ident(tt::Ident {
text: "_".into(),
- id: tt::TokenId::unspecified(),
+ span: tt::TokenId::unspecified(),
}))
);
}
diff --git a/src/tools/rust-analyzer/crates/proc-macro-srv/src/abis/abi_sysroot/mod.rs b/src/tools/rust-analyzer/crates/proc-macro-srv/src/abis/abi_sysroot/mod.rs
index 243972b04..0a3b8866a 100644
--- a/src/tools/rust-analyzer/crates/proc-macro-srv/src/abis/abi_sysroot/mod.rs
+++ b/src/tools/rust-analyzer/crates/proc-macro-srv/src/abis/abi_sysroot/mod.rs
@@ -9,7 +9,7 @@ mod ra_server;
use libloading::Library;
use proc_macro_api::ProcMacroKind;
-use super::PanicMessage;
+use super::{tt, PanicMessage};
pub use ra_server::TokenStream;
diff --git a/src/tools/rust-analyzer/crates/proc-macro-srv/src/abis/abi_sysroot/ra_server.rs b/src/tools/rust-analyzer/crates/proc-macro-srv/src/abis/abi_sysroot/ra_server.rs
index 068f79f82..d258a0247 100644
--- a/src/tools/rust-analyzer/crates/proc-macro-srv/src/abis/abi_sysroot/ra_server.rs
+++ b/src/tools/rust-analyzer/crates/proc-macro-srv/src/abis/abi_sysroot/ra_server.rs
@@ -22,6 +22,8 @@ pub use symbol::*;
use std::ops::Bound;
+use crate::tt;
+
type Group = tt::Subtree;
type TokenTree = tt::TokenTree;
type Punct = tt::Punct;
@@ -108,8 +110,9 @@ impl server::TokenStream for RustAnalyzer {
bridge::TokenTree::Ident(ident) => {
let text = ident.sym.text();
- let text = if ident.is_raw { tt::SmolStr::from_iter(["r#", &text]) } else { text };
- let ident: tt::Ident = tt::Ident { text, id: ident.span };
+ let text =
+ if ident.is_raw { ::tt::SmolStr::from_iter(["r#", &text]) } else { text };
+ let ident: tt::Ident = tt::Ident { text, span: ident.span };
let leaf = tt::Leaf::from(ident);
let tree = TokenTree::from(leaf);
Self::TokenStream::from_iter(vec![tree])
@@ -118,9 +121,9 @@ impl server::TokenStream for RustAnalyzer {
bridge::TokenTree::Literal(literal) => {
let literal = LiteralFormatter(literal);
let text = literal
- .with_stringify_parts(|parts| tt::SmolStr::from_iter(parts.iter().copied()));
+ .with_stringify_parts(|parts| ::tt::SmolStr::from_iter(parts.iter().copied()));
- let literal = tt::Literal { text, id: literal.0.span };
+ let literal = tt::Literal { text, span: literal.0.span };
let leaf = tt::Leaf::from(literal);
let tree = TokenTree::from(leaf);
Self::TokenStream::from_iter(vec![tree])
@@ -130,7 +133,7 @@ impl server::TokenStream for RustAnalyzer {
let punct = tt::Punct {
char: p.ch as char,
spacing: if p.joint { Spacing::Joint } else { Spacing::Alone },
- id: p.span,
+ span: p.span,
};
let leaf = tt::Leaf::from(punct);
let tree = TokenTree::from(leaf);
@@ -184,7 +187,7 @@ impl server::TokenStream for RustAnalyzer {
bridge::TokenTree::Ident(bridge::Ident {
sym: Symbol::intern(ident.text.trim_start_matches("r#")),
is_raw: ident.text.starts_with("r#"),
- span: ident.id,
+ span: ident.span,
})
}
tt::TokenTree::Leaf(tt::Leaf::Literal(lit)) => {
@@ -194,14 +197,14 @@ impl server::TokenStream for RustAnalyzer {
symbol: Symbol::intern(&lit.text),
// FIXME: handle suffixes
suffix: None,
- span: lit.id,
+ span: lit.span,
})
}
tt::TokenTree::Leaf(tt::Leaf::Punct(punct)) => {
bridge::TokenTree::Punct(bridge::Punct {
ch: punct.char as u8,
joint: punct.spacing == Spacing::Joint,
- span: punct.id,
+ span: punct.span,
})
}
tt::TokenTree::Subtree(subtree) => bridge::TokenTree::Group(bridge::Group {
@@ -211,31 +214,29 @@ impl server::TokenStream for RustAnalyzer {
} else {
Some(subtree.token_trees.into_iter().collect())
},
- span: bridge::DelimSpan::from_single(
- subtree.delimiter.map_or(Span::unspecified(), |del| del.id),
- ),
+ span: bridge::DelimSpan::from_single(subtree.delimiter.open),
}),
})
.collect()
}
}
-fn delim_to_internal(d: proc_macro::Delimiter) -> Option<tt::Delimiter> {
+fn delim_to_internal(d: proc_macro::Delimiter) -> tt::Delimiter {
let kind = match d {
proc_macro::Delimiter::Parenthesis => tt::DelimiterKind::Parenthesis,
proc_macro::Delimiter::Brace => tt::DelimiterKind::Brace,
proc_macro::Delimiter::Bracket => tt::DelimiterKind::Bracket,
- proc_macro::Delimiter::None => return None,
+ proc_macro::Delimiter::None => tt::DelimiterKind::Invisible,
};
- Some(tt::Delimiter { id: tt::TokenId::unspecified(), kind })
+ tt::Delimiter { open: tt::TokenId::unspecified(), close: tt::TokenId::unspecified(), kind }
}
-fn delim_to_external(d: Option<tt::Delimiter>) -> proc_macro::Delimiter {
- match d.map(|it| it.kind) {
- Some(tt::DelimiterKind::Parenthesis) => proc_macro::Delimiter::Parenthesis,
- Some(tt::DelimiterKind::Brace) => proc_macro::Delimiter::Brace,
- Some(tt::DelimiterKind::Bracket) => proc_macro::Delimiter::Bracket,
- None => proc_macro::Delimiter::None,
+fn delim_to_external(d: tt::Delimiter) -> proc_macro::Delimiter {
+ match d.kind {
+ tt::DelimiterKind::Parenthesis => proc_macro::Delimiter::Parenthesis,
+ tt::DelimiterKind::Brace => proc_macro::Delimiter::Brace,
+ tt::DelimiterKind::Bracket => proc_macro::Delimiter::Bracket,
+ tt::DelimiterKind::Invisible => proc_macro::Delimiter::None,
}
}
@@ -349,7 +350,7 @@ impl server::Server for RustAnalyzer {
}
fn intern_symbol(ident: &str) -> Self::Symbol {
- Symbol::intern(&tt::SmolStr::from(ident))
+ Symbol::intern(&::tt::SmolStr::from(ident))
}
fn with_symbol_string(symbol: &Self::Symbol, f: impl FnOnce(&str)) {
@@ -413,17 +414,18 @@ mod tests {
token_trees: vec![
tt::TokenTree::Leaf(tt::Leaf::Ident(tt::Ident {
text: "struct".into(),
- id: tt::TokenId::unspecified(),
+ span: tt::TokenId::unspecified(),
})),
tt::TokenTree::Leaf(tt::Leaf::Ident(tt::Ident {
text: "T".into(),
- id: tt::TokenId::unspecified(),
+ span: tt::TokenId::unspecified(),
})),
tt::TokenTree::Subtree(tt::Subtree {
- delimiter: Some(tt::Delimiter {
- id: tt::TokenId::unspecified(),
+ delimiter: tt::Delimiter {
+ open: tt::TokenId::unspecified(),
+ close: tt::TokenId::unspecified(),
kind: tt::DelimiterKind::Brace,
- }),
+ },
token_trees: vec![],
}),
],
@@ -436,13 +438,14 @@ mod tests {
fn test_ra_server_from_str() {
use std::str::FromStr;
let subtree_paren_a = tt::TokenTree::Subtree(tt::Subtree {
- delimiter: Some(tt::Delimiter {
- id: tt::TokenId::unspecified(),
+ delimiter: tt::Delimiter {
+ open: tt::TokenId::unspecified(),
+ close: tt::TokenId::unspecified(),
kind: tt::DelimiterKind::Parenthesis,
- }),
+ },
token_trees: vec![tt::TokenTree::Leaf(tt::Leaf::Ident(tt::Ident {
text: "a".into(),
- id: tt::TokenId::unspecified(),
+ span: tt::TokenId::unspecified(),
}))],
});
@@ -459,7 +462,7 @@ mod tests {
underscore.token_trees[0],
tt::TokenTree::Leaf(tt::Leaf::Ident(tt::Ident {
text: "_".into(),
- id: tt::TokenId::unspecified(),
+ span: tt::TokenId::unspecified(),
}))
);
}
diff --git a/src/tools/rust-analyzer/crates/proc-macro-srv/src/abis/abi_sysroot/ra_server/token_stream.rs b/src/tools/rust-analyzer/crates/proc-macro-srv/src/abis/abi_sysroot/ra_server/token_stream.rs
index 113bb52c1..d091d4319 100644
--- a/src/tools/rust-analyzer/crates/proc-macro-srv/src/abis/abi_sysroot/ra_server/token_stream.rs
+++ b/src/tools/rust-analyzer/crates/proc-macro-srv/src/abis/abi_sysroot/ra_server/token_stream.rs
@@ -1,6 +1,6 @@
//! TokenStream implementation used by sysroot ABI
-use tt::TokenTree;
+use crate::tt::{self, TokenTree};
#[derive(Debug, Default, Clone)]
pub struct TokenStream {
@@ -13,7 +13,7 @@ impl TokenStream {
}
pub fn with_subtree(subtree: tt::Subtree) -> Self {
- if subtree.delimiter.is_some() {
+ if subtree.delimiter.kind != tt::DelimiterKind::Invisible {
TokenStream { token_trees: vec![TokenTree::Subtree(subtree)] }
} else {
TokenStream { token_trees: subtree.token_trees }
@@ -21,7 +21,7 @@ impl TokenStream {
}
pub fn into_subtree(self) -> tt::Subtree {
- tt::Subtree { delimiter: None, token_trees: self.token_trees }
+ tt::Subtree { delimiter: tt::Delimiter::UNSPECIFIED, token_trees: self.token_trees }
}
pub fn is_empty(&self) -> bool {
@@ -64,7 +64,9 @@ impl Extend<TokenStream> for TokenStream {
for item in streams {
for tkn in item {
match tkn {
- tt::TokenTree::Subtree(subtree) if subtree.delimiter.is_none() => {
+ tt::TokenTree::Subtree(subtree)
+ if subtree.delimiter.kind == tt::DelimiterKind::Invisible =>
+ {
self.token_trees.extend(subtree.token_trees);
}
_ => {
@@ -84,7 +86,7 @@ pub struct TokenStreamBuilder {
pub mod token_stream {
use std::str::FromStr;
- use super::{TokenStream, TokenTree};
+ use super::{tt, TokenStream, TokenTree};
/// An iterator over `TokenStream`'s `TokenTree`s.
/// The iteration is "shallow", e.g., the iterator doesn't recurse into delimited groups,
@@ -121,15 +123,17 @@ pub mod token_stream {
impl ToString for TokenStream {
fn to_string(&self) -> String {
- tt::pretty(&self.token_trees)
+ ::tt::pretty(&self.token_trees)
}
}
fn subtree_replace_token_ids_with_unspecified(subtree: tt::Subtree) -> tt::Subtree {
tt::Subtree {
- delimiter: subtree
- .delimiter
- .map(|d| tt::Delimiter { id: tt::TokenId::unspecified(), ..d }),
+ delimiter: tt::Delimiter {
+ open: tt::TokenId::UNSPECIFIED,
+ close: tt::TokenId::UNSPECIFIED,
+ ..subtree.delimiter
+ },
token_trees: subtree
.token_trees
.into_iter()
@@ -152,13 +156,13 @@ pub mod token_stream {
fn leaf_replace_token_ids_with_unspecified(leaf: tt::Leaf) -> tt::Leaf {
match leaf {
tt::Leaf::Literal(lit) => {
- tt::Leaf::Literal(tt::Literal { id: tt::TokenId::unspecified(), ..lit })
+ tt::Leaf::Literal(tt::Literal { span: tt::TokenId::unspecified(), ..lit })
}
tt::Leaf::Punct(punct) => {
- tt::Leaf::Punct(tt::Punct { id: tt::TokenId::unspecified(), ..punct })
+ tt::Leaf::Punct(tt::Punct { span: tt::TokenId::unspecified(), ..punct })
}
tt::Leaf::Ident(ident) => {
- tt::Leaf::Ident(tt::Ident { id: tt::TokenId::unspecified(), ..ident })
+ tt::Leaf::Ident(tt::Ident { span: tt::TokenId::unspecified(), ..ident })
}
}
}
diff --git a/src/tools/rust-analyzer/crates/proc-macro-srv/src/abis/mod.rs b/src/tools/rust-analyzer/crates/proc-macro-srv/src/abis/mod.rs
index 5b8aca4d8..04be39cff 100644
--- a/src/tools/rust-analyzer/crates/proc-macro-srv/src/abis/mod.rs
+++ b/src/tools/rust-analyzer/crates/proc-macro-srv/src/abis/mod.rs
@@ -23,7 +23,6 @@
//! for the relevant versions of the rust compiler
//!
-mod abi_1_58;
mod abi_1_63;
#[cfg(feature = "sysroot-abi")]
mod abi_sysroot;
@@ -36,13 +35,14 @@ include!(concat!(env!("OUT_DIR"), "/rustc_version.rs"));
pub(crate) use abi_sysroot::TokenStream as TestTokenStream;
use super::dylib::LoadProcMacroDylibError;
-pub(crate) use abi_1_58::Abi as Abi_1_58;
pub(crate) use abi_1_63::Abi as Abi_1_63;
#[cfg(feature = "sysroot-abi")]
pub(crate) use abi_sysroot::Abi as Abi_Sysroot;
use libloading::Library;
use proc_macro_api::{ProcMacroKind, RustCInfo};
+use crate::tt;
+
pub struct PanicMessage {
message: Option<String>,
}
@@ -54,7 +54,6 @@ impl PanicMessage {
}
pub(crate) enum Abi {
- Abi1_58(Abi_1_58),
Abi1_63(Abi_1_63),
#[cfg(feature = "sysroot-abi")]
AbiSysroot(Abi_Sysroot),
@@ -109,10 +108,6 @@ impl Abi {
// FIXME: this should use exclusive ranges when they're stable
// https://github.com/rust-lang/rust/issues/37854
match (info.version.0, info.version.1) {
- (1, 58..=62) => {
- let inner = unsafe { Abi_1_58::from_lib(lib, symbol_name) }?;
- Ok(Abi::Abi1_58(inner))
- }
(1, 63) => {
let inner = unsafe { Abi_1_63::from_lib(lib, symbol_name) }?;
Ok(Abi::Abi1_63(inner))
@@ -128,7 +123,6 @@ impl Abi {
attributes: Option<&tt::Subtree>,
) -> Result<tt::Subtree, PanicMessage> {
match self {
- Self::Abi1_58(abi) => abi.expand(macro_name, macro_body, attributes),
Self::Abi1_63(abi) => abi.expand(macro_name, macro_body, attributes),
#[cfg(feature = "sysroot-abi")]
Self::AbiSysroot(abi) => abi.expand(macro_name, macro_body, attributes),
@@ -137,7 +131,6 @@ impl Abi {
pub fn list_macros(&self) -> Vec<(String, ProcMacroKind)> {
match self {
- Self::Abi1_58(abi) => abi.list_macros(),
Self::Abi1_63(abi) => abi.list_macros(),
#[cfg(feature = "sysroot-abi")]
Self::AbiSysroot(abi) => abi.list_macros(),
diff --git a/src/tools/rust-analyzer/crates/proc-macro-srv/src/cli.rs b/src/tools/rust-analyzer/crates/proc-macro-srv/src/cli.rs
index f1e131c13..05168feb6 100644
--- a/src/tools/rust-analyzer/crates/proc-macro-srv/src/cli.rs
+++ b/src/tools/rust-analyzer/crates/proc-macro-srv/src/cli.rs
@@ -15,6 +15,9 @@ pub fn run() -> io::Result<()> {
msg::Response::ListMacros(srv.list_macros(&dylib_path))
}
msg::Request::ExpandMacro(task) => msg::Response::ExpandMacro(srv.expand(task)),
+ msg::Request::ApiVersionCheck {} => {
+ msg::Response::ApiVersionCheck(proc_macro_api::msg::CURRENT_API_VERSION)
+ }
};
write_response(res)?
}
diff --git a/src/tools/rust-analyzer/crates/proc-macro-srv/src/dylib.rs b/src/tools/rust-analyzer/crates/proc-macro-srv/src/dylib.rs
index 0722cd89d..89ffd1f49 100644
--- a/src/tools/rust-analyzer/crates/proc-macro-srv/src/dylib.rs
+++ b/src/tools/rust-analyzer/crates/proc-macro-srv/src/dylib.rs
@@ -13,6 +13,8 @@ use object::Object;
use paths::AbsPath;
use proc_macro_api::{read_dylib_info, ProcMacroKind};
+use crate::tt;
+
use super::abis::Abi;
const NEW_REGISTRAR_SYMBOL: &str = "_rustc_proc_macro_decls_";
diff --git a/src/tools/rust-analyzer/crates/proc-macro-srv/src/lib.rs b/src/tools/rust-analyzer/crates/proc-macro-srv/src/lib.rs
index 2eb939a7c..ee70fe7d4 100644
--- a/src/tools/rust-analyzer/crates/proc-macro-srv/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/proc-macro-srv/src/lib.rs
@@ -37,6 +37,8 @@ use proc_macro_api::{
ProcMacroKind,
};
+use ::tt::token_id as tt;
+
#[derive(Default)]
pub(crate) struct ProcMacroSrv {
expanders: HashMap<(PathBuf, SystemTime), dylib::Expander>,
diff --git a/src/tools/rust-analyzer/crates/proc-macro-srv/src/tests/mod.rs b/src/tools/rust-analyzer/crates/proc-macro-srv/src/tests/mod.rs
index 1ccc170f4..04a0ae7bc 100644
--- a/src/tools/rust-analyzer/crates/proc-macro-srv/src/tests/mod.rs
+++ b/src/tools/rust-analyzer/crates/proc-macro-srv/src/tests/mod.rs
@@ -8,7 +8,7 @@ use expect_test::expect;
#[test]
fn test_derive_empty() {
- assert_expand("DeriveEmpty", r#"struct S;"#, expect![[r#"SUBTREE $"#]]);
+ assert_expand("DeriveEmpty", r#"struct S;"#, expect!["SUBTREE $$ 4294967295 4294967295"]);
}
#[test]
@@ -17,10 +17,10 @@ fn test_derive_error() {
"DeriveError",
r#"struct S;"#,
expect![[r##"
- SUBTREE $
+ SUBTREE $$ 4294967295 4294967295
IDENT compile_error 4294967295
PUNCH ! [alone] 4294967295
- SUBTREE () 4294967295
+ SUBTREE () 4294967295 4294967295
LITERAL "#[derive(DeriveError)] struct S ;" 4294967295
PUNCH ; [alone] 4294967295"##]],
);
@@ -32,14 +32,14 @@ fn test_fn_like_macro_noop() {
"fn_like_noop",
r#"ident, 0, 1, []"#,
expect![[r#"
- SUBTREE $
+ SUBTREE $$ 4294967295 4294967295
IDENT ident 4294967295
PUNCH , [alone] 4294967295
LITERAL 0 4294967295
PUNCH , [alone] 4294967295
LITERAL 1 4294967295
PUNCH , [alone] 4294967295
- SUBTREE [] 4294967295"#]],
+ SUBTREE [] 4294967295 4294967295"#]],
);
}
@@ -49,10 +49,10 @@ fn test_fn_like_macro_clone_ident_subtree() {
"fn_like_clone_tokens",
r#"ident, []"#,
expect![[r#"
- SUBTREE $
+ SUBTREE $$ 4294967295 4294967295
IDENT ident 4294967295
PUNCH , [alone] 4294967295
- SUBTREE [] 4294967295"#]],
+ SUBTREE [] 4294967295 4294967295"#]],
);
}
@@ -62,7 +62,7 @@ fn test_fn_like_macro_clone_raw_ident() {
"fn_like_clone_tokens",
"r#async",
expect![[r#"
- SUBTREE $
+ SUBTREE $$ 4294967295 4294967295
IDENT r#async 4294967295"#]],
);
}
@@ -73,7 +73,7 @@ fn test_fn_like_mk_literals() {
"fn_like_mk_literals",
r#""#,
expect![[r#"
- SUBTREE $
+ SUBTREE $$ 4294967295 4294967295
LITERAL b"byte_string" 4294967295
LITERAL 'c' 4294967295
LITERAL "string" 4294967295
@@ -90,7 +90,7 @@ fn test_fn_like_mk_idents() {
"fn_like_mk_idents",
r#""#,
expect![[r#"
- SUBTREE $
+ SUBTREE $$ 4294967295 4294967295
IDENT standard 4294967295
IDENT r#raw 4294967295"#]],
);
@@ -102,7 +102,7 @@ fn test_fn_like_macro_clone_literals() {
"fn_like_clone_tokens",
r#"1u16, 2_u32, -4i64, 3.14f32, "hello bridge""#,
expect![[r#"
- SUBTREE $
+ SUBTREE $$ 4294967295 4294967295
LITERAL 1u16 4294967295
PUNCH , [alone] 4294967295
LITERAL 2_u32 4294967295
@@ -126,10 +126,10 @@ fn test_attr_macro() {
r#"mod m {}"#,
r#"some arguments"#,
expect![[r##"
- SUBTREE $
+ SUBTREE $$ 4294967295 4294967295
IDENT compile_error 4294967295
PUNCH ! [alone] 4294967295
- SUBTREE () 4294967295
+ SUBTREE () 4294967295 4294967295
LITERAL "#[attr_error(some arguments)] mod m {}" 4294967295
PUNCH ; [alone] 4294967295"##]],
);
diff --git a/src/tools/rust-analyzer/crates/proc-macro-test/Cargo.toml b/src/tools/rust-analyzer/crates/proc-macro-test/Cargo.toml
index d2a79f910..77b4afd7d 100644
--- a/src/tools/rust-analyzer/crates/proc-macro-test/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/proc-macro-test/Cargo.toml
@@ -1,15 +1,20 @@
[package]
name = "proc-macro-test"
version = "0.0.0"
-license = "MIT OR Apache-2.0"
-edition = "2021"
-rust-version = "1.65"
publish = false
+authors.workspace = true
+edition.workspace = true
+license.workspace = true
+rust-version.workspace = true
+
[lib]
doctest = false
[build-dependencies]
-proc-macro-test-impl = { path = "imp", version = "0.0.0" }
-toolchain = { path = "../toolchain", version = "0.0.0" }
cargo_metadata = "0.15.0"
+
+proc-macro-test-impl = { path = "imp", version = "0.0.0" }
+
+# local deps
+toolchain.workspace = true
diff --git a/src/tools/rust-analyzer/crates/proc-macro-test/imp/Cargo.toml b/src/tools/rust-analyzer/crates/proc-macro-test/imp/Cargo.toml
index 1bd14070e..2a36737ce 100644
--- a/src/tools/rust-analyzer/crates/proc-macro-test/imp/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/proc-macro-test/imp/Cargo.toml
@@ -3,7 +3,6 @@ name = "proc-macro-test-impl"
version = "0.0.0"
license = "MIT OR Apache-2.0"
edition = "2021"
-rust-version = "1.65"
publish = false
[lib]
diff --git a/src/tools/rust-analyzer/crates/profile/Cargo.toml b/src/tools/rust-analyzer/crates/profile/Cargo.toml
index 01d1735bf..6273ea51d 100644
--- a/src/tools/rust-analyzer/crates/profile/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/profile/Cargo.toml
@@ -2,15 +2,17 @@
name = "profile"
version = "0.0.0"
description = "TBD"
-license = "MIT OR Apache-2.0"
-edition = "2021"
-rust-version = "1.65"
+
+authors.workspace = true
+edition.workspace = true
+license.workspace = true
+rust-version.workspace = true
[lib]
doctest = false
[dependencies]
-once_cell = "1.15.0"
+once_cell = "1.17.0"
cfg-if = "1.0.0"
libc = "0.2.135"
la-arena = { version = "0.3.0", path = "../../lib/la-arena" }
diff --git a/src/tools/rust-analyzer/crates/profile/src/lib.rs b/src/tools/rust-analyzer/crates/profile/src/lib.rs
index 7ca3c7d62..e7fc3d970 100644
--- a/src/tools/rust-analyzer/crates/profile/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/profile/src/lib.rs
@@ -26,7 +26,7 @@ pub use countme::Count;
thread_local!(static IN_SCOPE: RefCell<bool> = RefCell::new(false));
-/// Allows to check if the current code is withing some dynamic scope, can be
+/// Allows to check if the current code is within some dynamic scope, can be
/// useful during debugging to figure out why a function is called.
pub struct Scope {
prev: bool,
diff --git a/src/tools/rust-analyzer/crates/project-model/Cargo.toml b/src/tools/rust-analyzer/crates/project-model/Cargo.toml
index 39902a532..22d6a6e78 100644
--- a/src/tools/rust-analyzer/crates/project-model/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/project-model/Cargo.toml
@@ -2,9 +2,11 @@
name = "project-model"
version = "0.0.0"
description = "TBD"
-license = "MIT OR Apache-2.0"
-edition = "2021"
-rust-version = "1.65"
+
+authors.workspace = true
+edition.workspace = true
+license.workspace = true
+rust-version.workspace = true
[lib]
doctest = false
@@ -19,12 +21,13 @@ serde_json = "1.0.86"
anyhow = "1.0.62"
la-arena = { version = "0.3.0", path = "../../lib/la-arena" }
-cfg = { path = "../cfg", version = "0.0.0" }
-base-db = { path = "../base-db", version = "0.0.0" }
-toolchain = { path = "../toolchain", version = "0.0.0" }
-paths = { path = "../paths", version = "0.0.0" }
-stdx = { path = "../stdx", version = "0.0.0" }
-profile = { path = "../profile", version = "0.0.0" }
+# local deps
+base-db.workspace = true
+cfg.workspace = true
+paths.workspace = true
+profile.workspace = true
+stdx.workspace = true
+toolchain.workspace = true
[dev-dependencies]
expect-test = "1.4.0"
diff --git a/src/tools/rust-analyzer/crates/project-model/src/cargo_workspace.rs b/src/tools/rust-analyzer/crates/project-model/src/cargo_workspace.rs
index 467cf0917..fdc7859eb 100644
--- a/src/tools/rust-analyzer/crates/project-model/src/cargo_workspace.rs
+++ b/src/tools/rust-analyzer/crates/project-model/src/cargo_workspace.rs
@@ -96,6 +96,7 @@ pub struct CargoConfig {
pub target: Option<String>,
/// Sysroot loading behavior
pub sysroot: Option<RustcSource>,
+ pub sysroot_src: Option<AbsPathBuf>,
/// rustc private crate source
pub rustc_source: Option<RustcSource>,
/// crates to disable `#[cfg(test)]` on
diff --git a/src/tools/rust-analyzer/crates/project-model/src/lib.rs b/src/tools/rust-analyzer/crates/project-model/src/lib.rs
index e2f09bad2..9b6a71db8 100644
--- a/src/tools/rust-analyzer/crates/project-model/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/project-model/src/lib.rs
@@ -25,7 +25,7 @@ mod sysroot;
mod workspace;
mod rustc_cfg;
mod build_scripts;
-mod target_data_layout;
+pub mod target_data_layout;
#[cfg(test)]
mod tests;
diff --git a/src/tools/rust-analyzer/crates/project-model/src/project_json.rs b/src/tools/rust-analyzer/crates/project-model/src/project_json.rs
index 9af0eafe9..4b2448e47 100644
--- a/src/tools/rust-analyzer/crates/project-model/src/project_json.rs
+++ b/src/tools/rust-analyzer/crates/project-model/src/project_json.rs
@@ -4,6 +4,50 @@
//! idea here is that people who do not use Cargo, can instead teach their build
//! system to generate `rust-project.json` which can be ingested by
//! rust-analyzer.
+//!
+//! This short file is a somewhat big conceptual piece of the architecture of
+//! rust-analyzer, so it's worth elaborating on the underlying ideas and
+//! motivation.
+//!
+//! For rust-analyzer to function, it needs some information about the project.
+//! Specifically, it maintains an in-memory data structure which lists all the
+//! crates (compilation units) and dependencies between them. This is necessary
+//! a global singleton, as we do want, eg, find usages to always search across
+//! the whole project, rather than just in the "current" crate.
+//!
+//! Normally, we get this "crate graph" by calling `cargo metadata
+//! --message-format=json` for each cargo workspace and merging results. This
+//! works for your typical cargo project, but breaks down for large folks who
+//! have a monorepo with an infinite amount of Rust code which is built with bazel or
+//! some such.
+//!
+//! To support this use case, we need to make _something_ configurable. To avoid
+//! a [midlayer mistake](https://lwn.net/Articles/336262/), we allow configuring
+//! the lowest possible layer. `ProjectJson` is essentially a hook to just set
+//! that global singleton in-memory data structure. It is optimized for power,
+//! not for convenience (you'd be using cargo anyway if you wanted nice things,
+//! right? :)
+//!
+//! `rust-project.json` also isn't necessary a file. Architecturally, we support
+//! any convenient way to specify this data, which today is:
+//!
+//! * file on disk
+//! * a field in the config (ie, you can send a JSON request with the contents
+//! of rust-project.json to rust-analyzer, no need to write anything to disk)
+//!
+//! Another possible thing we don't do today, but which would be totally valid,
+//! is to add an extension point to VS Code extension to register custom
+//! project.
+//!
+//! In general, it is assumed that if you are going to use `rust-project.json`,
+//! you'd write a fair bit of custom code gluing your build system to ra through
+//! this JSON format. This logic can take form of a VS Code extension, or a
+//! proxy process which injects data into "configure" LSP request, or maybe just
+//! a simple build system rule to generate the file.
+//!
+//! In particular, the logic for lazily loading parts of the monorepo as the
+//! user explores them belongs to that extension (it's totally valid to change
+//! rust-project.json over time via configuration request!)
use std::path::PathBuf;
diff --git a/src/tools/rust-analyzer/crates/project-model/src/sysroot.rs b/src/tools/rust-analyzer/crates/project-model/src/sysroot.rs
index 8d5ab0061..328d2fbcf 100644
--- a/src/tools/rust-analyzer/crates/project-model/src/sysroot.rs
+++ b/src/tools/rust-analyzer/crates/project-model/src/sysroot.rs
@@ -7,6 +7,7 @@
use std::{env, fs, iter, ops, path::PathBuf, process::Command};
use anyhow::{format_err, Result};
+use base_db::CrateName;
use la_arena::{Arena, Idx};
use paths::{AbsPath, AbsPathBuf};
use rustc_hash::FxHashMap;
@@ -50,14 +51,16 @@ impl Sysroot {
&self.src_root
}
- pub fn public_deps(&self) -> impl Iterator<Item = (&'static str, SysrootCrate, bool)> + '_ {
+ pub fn public_deps(&self) -> impl Iterator<Item = (CrateName, SysrootCrate, bool)> + '_ {
// core is added as a dependency before std in order to
// mimic rustcs dependency order
["core", "alloc", "std"]
.into_iter()
.zip(iter::repeat(true))
.chain(iter::once(("test", false)))
- .filter_map(move |(name, prelude)| Some((name, self.by_name(name)?, prelude)))
+ .filter_map(move |(name, prelude)| {
+ Some((CrateName::new(name).unwrap(), self.by_name(name)?, prelude))
+ })
}
pub fn proc_macro(&self) -> Option<SysrootCrate> {
@@ -67,8 +70,13 @@ impl Sysroot {
pub fn crates(&self) -> impl Iterator<Item = SysrootCrate> + ExactSizeIterator + '_ {
self.crates.iter().map(|(id, _data)| id)
}
+
+ pub fn is_empty(&self) -> bool {
+ self.crates.is_empty()
+ }
}
+// FIXME: Expose a builder api as loading the sysroot got way too modular and complicated.
impl Sysroot {
/// Attempts to discover the toolchain's sysroot from the given `dir`.
pub fn discover(dir: &AbsPath, extra_env: &FxHashMap<String, String>) -> Result<Sysroot> {
@@ -76,8 +84,17 @@ impl Sysroot {
let sysroot_dir = discover_sysroot_dir(dir, extra_env)?;
let sysroot_src_dir =
discover_sysroot_src_dir_or_add_component(&sysroot_dir, dir, extra_env)?;
- let res = Sysroot::load(sysroot_dir, sysroot_src_dir)?;
- Ok(res)
+ Ok(Sysroot::load(sysroot_dir, sysroot_src_dir))
+ }
+
+ pub fn discover_with_src_override(
+ dir: &AbsPath,
+ extra_env: &FxHashMap<String, String>,
+ src: AbsPathBuf,
+ ) -> Result<Sysroot> {
+ tracing::debug!("discovering sysroot for {}", dir.display());
+ let sysroot_dir = discover_sysroot_dir(dir, extra_env)?;
+ Ok(Sysroot::load(sysroot_dir, src))
}
pub fn discover_rustc(
@@ -94,11 +111,10 @@ impl Sysroot {
let sysroot_src_dir = discover_sysroot_src_dir(&sysroot_dir).ok_or_else(|| {
format_err!("can't load standard library from sysroot {}", sysroot_dir.display())
})?;
- let res = Sysroot::load(sysroot_dir, sysroot_src_dir)?;
- Ok(res)
+ Ok(Sysroot::load(sysroot_dir, sysroot_src_dir))
}
- pub fn load(sysroot_dir: AbsPathBuf, sysroot_src_dir: AbsPathBuf) -> Result<Sysroot> {
+ pub fn load(sysroot_dir: AbsPathBuf, sysroot_src_dir: AbsPathBuf) -> Sysroot {
let mut sysroot =
Sysroot { root: sysroot_dir, src_root: sysroot_src_dir, crates: Arena::default() };
@@ -149,14 +165,14 @@ impl Sysroot {
} else {
""
};
- anyhow::bail!(
+ tracing::error!(
"could not find libcore in sysroot path `{}`{}",
sysroot.src_root.as_path().display(),
var_note,
);
}
- Ok(sysroot)
+ sysroot
}
fn by_name(&self, name: &str) -> Option<SysrootCrate> {
diff --git a/src/tools/rust-analyzer/crates/project-model/src/target_data_layout.rs b/src/tools/rust-analyzer/crates/project-model/src/target_data_layout.rs
index 40cf47c3f..42c06ad0e 100644
--- a/src/tools/rust-analyzer/crates/project-model/src/target_data_layout.rs
+++ b/src/tools/rust-analyzer/crates/project-model/src/target_data_layout.rs
@@ -1,15 +1,16 @@
//! Runs `rustc --print target-spec-json` to get the target_data_layout.
use std::process::Command;
+use anyhow::Result;
use rustc_hash::FxHashMap;
use crate::{utf8_stdout, ManifestPath};
-pub(super) fn get(
+pub fn get(
cargo_toml: Option<&ManifestPath>,
target: Option<&str>,
extra_env: &FxHashMap<String, String>,
-) -> Option<String> {
+) -> Result<String> {
let output = (|| {
if let Some(cargo_toml) = cargo_toml {
let mut cmd = Command::new(toolchain::rustc());
@@ -28,13 +29,13 @@ pub(super) fn get(
// using unstable cargo features failed, fall back to using plain rustc
let mut cmd = Command::new(toolchain::rustc());
cmd.envs(extra_env)
- .args(["-Z", "unstable-options", "rustc", "--print", "target-spec-json"])
+ .args(["-Z", "unstable-options", "--print", "target-spec-json"])
.env("RUSTC_BOOTSTRAP", "1");
if let Some(target) = target {
cmd.args(["--target", target]);
}
utf8_stdout(cmd)
- })()
- .ok()?;
- Some(output.split_once(r#""data-layout": ""#)?.1.split_once('"')?.0.to_owned())
+ })()?;
+ (|| Some(output.split_once(r#""data-layout": ""#)?.1.split_once('"')?.0.to_owned()))()
+ .ok_or_else(|| anyhow::format_err!("could not fetch target-spec-json from command output"))
}
diff --git a/src/tools/rust-analyzer/crates/project-model/src/tests.rs b/src/tools/rust-analyzer/crates/project-model/src/tests.rs
index 2bb9ebf99..9e9691d11 100644
--- a/src/tools/rust-analyzer/crates/project-model/src/tests.rs
+++ b/src/tools/rust-analyzer/crates/project-model/src/tests.rs
@@ -29,7 +29,7 @@ fn load_cargo_with_overrides(file: &str, cfg_overrides: CfgOverrides) -> CrateGr
rustc_cfg: Vec::new(),
cfg_overrides,
toolchain: None,
- target_layout: None,
+ target_layout: Err("target_data_layout not loaded".into()),
};
to_crate_graph(project_workspace)
}
@@ -81,7 +81,7 @@ fn get_fake_sysroot() -> Sysroot {
// fake sysroot, so we give them both the same path:
let sysroot_dir = AbsPathBuf::assert(sysroot_path);
let sysroot_src_dir = sysroot_dir.clone();
- Sysroot::load(sysroot_dir, sysroot_src_dir).unwrap()
+ Sysroot::load(sysroot_dir, sysroot_src_dir)
}
fn rooted_project_json(data: ProjectJsonData) -> ProjectJson {
@@ -151,7 +151,9 @@ fn cargo_hello_world_project_model_with_wildcard_overrides() {
"debug_assertions",
],
),
- target_layout: None,
+ target_layout: Err(
+ "target_data_layout not loaded",
+ ),
env: Env {
entries: {
"CARGO_PKG_LICENSE": "",
@@ -221,7 +223,9 @@ fn cargo_hello_world_project_model_with_wildcard_overrides() {
"debug_assertions",
],
),
- target_layout: None,
+ target_layout: Err(
+ "target_data_layout not loaded",
+ ),
env: Env {
entries: {
"CARGO_PKG_LICENSE": "",
@@ -300,7 +304,9 @@ fn cargo_hello_world_project_model_with_wildcard_overrides() {
"debug_assertions",
],
),
- target_layout: None,
+ target_layout: Err(
+ "target_data_layout not loaded",
+ ),
env: Env {
entries: {
"CARGO_PKG_LICENSE": "",
@@ -379,7 +385,9 @@ fn cargo_hello_world_project_model_with_wildcard_overrides() {
"debug_assertions",
],
),
- target_layout: None,
+ target_layout: Err(
+ "target_data_layout not loaded",
+ ),
env: Env {
entries: {
"CARGO_PKG_LICENSE": "",
@@ -467,7 +475,9 @@ fn cargo_hello_world_project_model_with_wildcard_overrides() {
"feature=use_std",
],
),
- target_layout: None,
+ target_layout: Err(
+ "target_data_layout not loaded",
+ ),
env: Env {
entries: {
"CARGO_PKG_LICENSE": "",
@@ -553,7 +563,9 @@ fn cargo_hello_world_project_model_with_selective_overrides() {
"test",
],
),
- target_layout: None,
+ target_layout: Err(
+ "target_data_layout not loaded",
+ ),
env: Env {
entries: {
"CARGO_PKG_LICENSE": "",
@@ -625,7 +637,9 @@ fn cargo_hello_world_project_model_with_selective_overrides() {
"test",
],
),
- target_layout: None,
+ target_layout: Err(
+ "target_data_layout not loaded",
+ ),
env: Env {
entries: {
"CARGO_PKG_LICENSE": "",
@@ -706,7 +720,9 @@ fn cargo_hello_world_project_model_with_selective_overrides() {
"test",
],
),
- target_layout: None,
+ target_layout: Err(
+ "target_data_layout not loaded",
+ ),
env: Env {
entries: {
"CARGO_PKG_LICENSE": "",
@@ -787,7 +803,9 @@ fn cargo_hello_world_project_model_with_selective_overrides() {
"test",
],
),
- target_layout: None,
+ target_layout: Err(
+ "target_data_layout not loaded",
+ ),
env: Env {
entries: {
"CARGO_PKG_LICENSE": "",
@@ -875,7 +893,9 @@ fn cargo_hello_world_project_model_with_selective_overrides() {
"feature=use_std",
],
),
- target_layout: None,
+ target_layout: Err(
+ "target_data_layout not loaded",
+ ),
env: Env {
entries: {
"CARGO_PKG_LICENSE": "",
@@ -952,7 +972,9 @@ fn cargo_hello_world_project_model() {
"test",
],
),
- target_layout: None,
+ target_layout: Err(
+ "target_data_layout not loaded",
+ ),
env: Env {
entries: {
"CARGO_PKG_LICENSE": "",
@@ -1024,7 +1046,9 @@ fn cargo_hello_world_project_model() {
"test",
],
),
- target_layout: None,
+ target_layout: Err(
+ "target_data_layout not loaded",
+ ),
env: Env {
entries: {
"CARGO_PKG_LICENSE": "",
@@ -1105,7 +1129,9 @@ fn cargo_hello_world_project_model() {
"test",
],
),
- target_layout: None,
+ target_layout: Err(
+ "target_data_layout not loaded",
+ ),
env: Env {
entries: {
"CARGO_PKG_LICENSE": "",
@@ -1186,7 +1212,9 @@ fn cargo_hello_world_project_model() {
"test",
],
),
- target_layout: None,
+ target_layout: Err(
+ "target_data_layout not loaded",
+ ),
env: Env {
entries: {
"CARGO_PKG_LICENSE": "",
@@ -1274,7 +1302,9 @@ fn cargo_hello_world_project_model() {
"feature=use_std",
],
),
- target_layout: None,
+ target_layout: Err(
+ "target_data_layout not loaded",
+ ),
env: Env {
entries: {
"CARGO_PKG_LICENSE": "",
@@ -1327,7 +1357,7 @@ fn rust_project_hello_world_project_model() {
root_file_id: FileId(
1,
),
- edition: Edition2018,
+ edition: Edition2021,
version: None,
display_name: Some(
CrateDisplayName {
@@ -1343,7 +1373,9 @@ fn rust_project_hello_world_project_model() {
potential_cfg_options: CfgOptions(
[],
),
- target_layout: None,
+ target_layout: Err(
+ "rust-project.json projects have no target layout set",
+ ),
env: Env {
entries: {},
},
@@ -1372,7 +1404,7 @@ fn rust_project_hello_world_project_model() {
root_file_id: FileId(
2,
),
- edition: Edition2018,
+ edition: Edition2021,
version: None,
display_name: Some(
CrateDisplayName {
@@ -1388,7 +1420,9 @@ fn rust_project_hello_world_project_model() {
potential_cfg_options: CfgOptions(
[],
),
- target_layout: None,
+ target_layout: Err(
+ "rust-project.json projects have no target layout set",
+ ),
env: Env {
entries: {},
},
@@ -1407,7 +1441,7 @@ fn rust_project_hello_world_project_model() {
root_file_id: FileId(
3,
),
- edition: Edition2018,
+ edition: Edition2021,
version: None,
display_name: Some(
CrateDisplayName {
@@ -1423,7 +1457,9 @@ fn rust_project_hello_world_project_model() {
potential_cfg_options: CfgOptions(
[],
),
- target_layout: None,
+ target_layout: Err(
+ "rust-project.json projects have no target layout set",
+ ),
env: Env {
entries: {},
},
@@ -1442,7 +1478,7 @@ fn rust_project_hello_world_project_model() {
root_file_id: FileId(
4,
),
- edition: Edition2018,
+ edition: Edition2021,
version: None,
display_name: Some(
CrateDisplayName {
@@ -1458,7 +1494,9 @@ fn rust_project_hello_world_project_model() {
potential_cfg_options: CfgOptions(
[],
),
- target_layout: None,
+ target_layout: Err(
+ "rust-project.json projects have no target layout set",
+ ),
env: Env {
entries: {},
},
@@ -1477,7 +1515,7 @@ fn rust_project_hello_world_project_model() {
root_file_id: FileId(
5,
),
- edition: Edition2018,
+ edition: Edition2021,
version: None,
display_name: Some(
CrateDisplayName {
@@ -1493,7 +1531,9 @@ fn rust_project_hello_world_project_model() {
potential_cfg_options: CfgOptions(
[],
),
- target_layout: None,
+ target_layout: Err(
+ "rust-project.json projects have no target layout set",
+ ),
env: Env {
entries: {},
},
@@ -1522,7 +1562,7 @@ fn rust_project_hello_world_project_model() {
root_file_id: FileId(
6,
),
- edition: Edition2018,
+ edition: Edition2021,
version: None,
display_name: Some(
CrateDisplayName {
@@ -1538,7 +1578,9 @@ fn rust_project_hello_world_project_model() {
potential_cfg_options: CfgOptions(
[],
),
- target_layout: None,
+ target_layout: Err(
+ "rust-project.json projects have no target layout set",
+ ),
env: Env {
entries: {},
},
@@ -1557,7 +1599,7 @@ fn rust_project_hello_world_project_model() {
root_file_id: FileId(
7,
),
- edition: Edition2018,
+ edition: Edition2021,
version: None,
display_name: Some(
CrateDisplayName {
@@ -1573,7 +1615,9 @@ fn rust_project_hello_world_project_model() {
potential_cfg_options: CfgOptions(
[],
),
- target_layout: None,
+ target_layout: Err(
+ "rust-project.json projects have no target layout set",
+ ),
env: Env {
entries: {},
},
@@ -1665,7 +1709,7 @@ fn rust_project_hello_world_project_model() {
root_file_id: FileId(
8,
),
- edition: Edition2018,
+ edition: Edition2021,
version: None,
display_name: Some(
CrateDisplayName {
@@ -1681,7 +1725,9 @@ fn rust_project_hello_world_project_model() {
potential_cfg_options: CfgOptions(
[],
),
- target_layout: None,
+ target_layout: Err(
+ "rust-project.json projects have no target layout set",
+ ),
env: Env {
entries: {},
},
@@ -1700,7 +1746,7 @@ fn rust_project_hello_world_project_model() {
root_file_id: FileId(
9,
),
- edition: Edition2018,
+ edition: Edition2021,
version: None,
display_name: Some(
CrateDisplayName {
@@ -1716,7 +1762,9 @@ fn rust_project_hello_world_project_model() {
potential_cfg_options: CfgOptions(
[],
),
- target_layout: None,
+ target_layout: Err(
+ "rust-project.json projects have no target layout set",
+ ),
env: Env {
entries: {},
},
@@ -1735,7 +1783,7 @@ fn rust_project_hello_world_project_model() {
root_file_id: FileId(
10,
),
- edition: Edition2018,
+ edition: Edition2021,
version: None,
display_name: Some(
CrateDisplayName {
@@ -1751,7 +1799,9 @@ fn rust_project_hello_world_project_model() {
potential_cfg_options: CfgOptions(
[],
),
- target_layout: None,
+ target_layout: Err(
+ "rust-project.json projects have no target layout set",
+ ),
env: Env {
entries: {},
},
@@ -1786,7 +1836,9 @@ fn rust_project_hello_world_project_model() {
potential_cfg_options: CfgOptions(
[],
),
- target_layout: None,
+ target_layout: Err(
+ "rust-project.json projects have no target layout set",
+ ),
env: Env {
entries: {},
},
diff --git a/src/tools/rust-analyzer/crates/project-model/src/workspace.rs b/src/tools/rust-analyzer/crates/project-model/src/workspace.rs
index e2382aa37..2a11f1e8e 100644
--- a/src/tools/rust-analyzer/crates/project-model/src/workspace.rs
+++ b/src/tools/rust-analyzer/crates/project-model/src/workspace.rs
@@ -7,7 +7,7 @@ use std::{collections::VecDeque, fmt, fs, process::Command, sync::Arc};
use anyhow::{format_err, Context, Result};
use base_db::{
CrateDisplayName, CrateGraph, CrateId, CrateName, CrateOrigin, Dependency, Edition, Env,
- FileId, LangCrateOrigin, ProcMacroLoadResult,
+ FileId, LangCrateOrigin, ProcMacroLoadResult, TargetLayoutLoadResult,
};
use cfg::{CfgDiff, CfgOptions};
use paths::{AbsPath, AbsPathBuf};
@@ -63,7 +63,7 @@ pub struct PackageRoot {
pub exclude: Vec<AbsPathBuf>,
}
-#[derive(Clone, Eq, PartialEq)]
+#[derive(Clone)]
pub enum ProjectWorkspace {
/// Project workspace was discovered by running `cargo metadata` and `rustc --print sysroot`.
Cargo {
@@ -79,11 +79,10 @@ pub enum ProjectWorkspace {
rustc_cfg: Vec<CfgFlag>,
cfg_overrides: CfgOverrides,
toolchain: Option<Version>,
- target_layout: Option<String>,
+ target_layout: Result<String, String>,
},
/// Project workspace was manually specified using a `rust-project.json` file.
Json { project: ProjectJson, sysroot: Option<Sysroot>, rustc_cfg: Vec<CfgFlag> },
-
// FIXME: The primary limitation of this approach is that the set of detached files needs to be fixed at the beginning.
// That's not the end user experience we should strive for.
// Ideally, you should be able to just open a random detached file in existing cargo projects, and get the basic features working.
@@ -163,7 +162,7 @@ impl ProjectWorkspace {
project_json,
config.target.as_deref(),
&config.extra_env,
- )?
+ )
}
ProjectManifest::CargoToml(cargo_toml) => {
let cargo_version = utf8_stdout({
@@ -191,24 +190,52 @@ impl ProjectWorkspace {
})?;
let cargo = CargoWorkspace::new(meta);
- let sysroot = match &config.sysroot {
- Some(RustcSource::Path(path)) => {
- Some(Sysroot::with_sysroot_dir(path.clone()).with_context(|| {
- format!("Failed to find sysroot at {}.", path.display())
- })?)
+ let sysroot = match (&config.sysroot, &config.sysroot_src) {
+ (Some(RustcSource::Path(path)), None) => {
+ match Sysroot::with_sysroot_dir(path.clone()) {
+ Ok(it) => Some(it),
+ Err(e) => {
+ tracing::error!(%e, "Failed to find sysroot at {}.", path.display());
+ None
+ }
+ }
}
- Some(RustcSource::Discover) => Some(
- Sysroot::discover(cargo_toml.parent(), &config.extra_env).with_context(
- || {
- format!(
- "Failed to find sysroot for Cargo.toml file {}. Is rust-src installed?",
- cargo_toml.display()
- )
- },
- )?,
- ),
- None => None,
+ (Some(RustcSource::Discover), None) => {
+ match Sysroot::discover(cargo_toml.parent(), &config.extra_env) {
+ Ok(it) => Some(it),
+ Err(e) => {
+ tracing::error!(
+ %e,
+ "Failed to find sysroot for Cargo.toml file {}. Is rust-src installed?",
+ cargo_toml.display()
+ );
+ None
+ }
+ }
+ }
+ (Some(RustcSource::Path(sysroot)), Some(sysroot_src)) => {
+ Some(Sysroot::load(sysroot.clone(), sysroot_src.clone()))
+ }
+ (Some(RustcSource::Discover), Some(sysroot_src)) => {
+ match Sysroot::discover_with_src_override(
+ cargo_toml.parent(),
+ &config.extra_env,
+ sysroot_src.clone(),
+ ) {
+ Ok(it) => Some(it),
+ Err(e) => {
+ tracing::error!(
+ %e,
+ "Failed to find sysroot for Cargo.toml file {}. Is rust-src installed?",
+ cargo_toml.display()
+ );
+ None
+ }
+ }
+ }
+ (None, _) => None,
};
+
if let Some(sysroot) = &sysroot {
tracing::info!(src_root = %sysroot.src_root().display(), root = %sysroot.root().display(), "Using sysroot");
}
@@ -225,18 +252,22 @@ impl ProjectWorkspace {
}
let rustc = match rustc_dir {
- Some(rustc_dir) => Some({
- let meta = CargoWorkspace::fetch_metadata(
- &rustc_dir,
- cargo_toml.parent(),
- config,
- progress,
- )
- .with_context(|| {
- "Failed to read Cargo metadata for Rust sources".to_string()
- })?;
- CargoWorkspace::new(meta)
- }),
+ Some(rustc_dir) => match CargoWorkspace::fetch_metadata(
+ &rustc_dir,
+ cargo_toml.parent(),
+ config,
+ progress,
+ ) {
+ Ok(meta) => Some(CargoWorkspace::new(meta)),
+ Err(e) => {
+ tracing::error!(
+ %e,
+ "Failed to read Cargo metadata from rustc source at {}",
+ rustc_dir.display()
+ );
+ None
+ }
+ },
None => None,
};
@@ -249,6 +280,9 @@ impl ProjectWorkspace {
config.target.as_deref(),
&config.extra_env,
);
+ if let Err(e) = &data_layout {
+ tracing::error!(%e, "failed fetching data layout for {cargo_toml:?} workspace");
+ }
ProjectWorkspace::Cargo {
cargo,
build_scripts: WorkspaceBuildScripts::default(),
@@ -257,7 +291,7 @@ impl ProjectWorkspace {
rustc_cfg,
cfg_overrides,
toolchain,
- target_layout: data_layout,
+ target_layout: data_layout.map_err(|it| it.to_string()),
}
}
};
@@ -269,15 +303,14 @@ impl ProjectWorkspace {
project_json: ProjectJson,
target: Option<&str>,
extra_env: &FxHashMap<String, String>,
- ) -> Result<ProjectWorkspace> {
+ ) -> ProjectWorkspace {
let sysroot = match (project_json.sysroot.clone(), project_json.sysroot_src.clone()) {
- (Some(sysroot), Some(sysroot_src)) => Some(Sysroot::load(sysroot, sysroot_src)?),
+ (Some(sysroot), Some(sysroot_src)) => Some(Sysroot::load(sysroot, sysroot_src)),
(Some(sysroot), None) => {
// assume sysroot is structured like rustup's and guess `sysroot_src`
let sysroot_src =
sysroot.join("lib").join("rustlib").join("src").join("rust").join("library");
-
- Some(Sysroot::load(sysroot, sysroot_src)?)
+ Some(Sysroot::load(sysroot, sysroot_src))
}
(None, Some(sysroot_src)) => {
// assume sysroot is structured like rustup's and guess `sysroot`
@@ -285,7 +318,7 @@ impl ProjectWorkspace {
for _ in 0..5 {
sysroot.pop();
}
- Some(Sysroot::load(sysroot, sysroot_src)?)
+ Some(Sysroot::load(sysroot, sysroot_src))
}
(None, None) => None,
};
@@ -294,7 +327,7 @@ impl ProjectWorkspace {
}
let rustc_cfg = rustc_cfg::get(None, target, extra_env);
- Ok(ProjectWorkspace::Json { project: project_json, sysroot, rustc_cfg })
+ ProjectWorkspace::Json { project: project_json, sysroot, rustc_cfg }
}
pub fn load_detached_files(
@@ -302,18 +335,29 @@ impl ProjectWorkspace {
config: &CargoConfig,
) -> Result<ProjectWorkspace> {
let sysroot = match &config.sysroot {
- Some(RustcSource::Path(path)) => Some(
- Sysroot::with_sysroot_dir(path.clone())
- .with_context(|| format!("Failed to find sysroot at {}.", path.display()))?,
- ),
+ Some(RustcSource::Path(path)) => match Sysroot::with_sysroot_dir(path.clone()) {
+ Ok(it) => Some(it),
+ Err(e) => {
+ tracing::error!(%e, "Failed to find sysroot at {}.", path.display());
+ None
+ }
+ },
Some(RustcSource::Discover) => {
let dir = &detached_files
.first()
.and_then(|it| it.parent())
.ok_or_else(|| format_err!("No detached files to load"))?;
- Some(Sysroot::discover(dir, &config.extra_env).with_context(|| {
- format!("Failed to find sysroot in {}. Is rust-src installed?", dir.display())
- })?)
+ match Sysroot::discover(dir, &config.extra_env) {
+ Ok(it) => Some(it),
+ Err(e) => {
+ tracing::error!(
+ %e,
+ "Failed to find sysroot for {}. Is rust-src installed?",
+ dir.display()
+ );
+ None
+ }
+ }
}
None => None,
};
@@ -366,7 +410,7 @@ impl ProjectWorkspace {
_ => None,
})
.collect();
- let ref mut outputs = match WorkspaceBuildScripts::run_once(config, &cargo_ws, progress) {
+ let outputs = &mut match WorkspaceBuildScripts::run_once(config, &cargo_ws, progress) {
Ok(it) => Ok(it.into_iter()),
// io::Error is not Clone?
Err(e) => Err(Arc::new(e)),
@@ -417,9 +461,11 @@ impl ProjectWorkspace {
/// The return type contains the path and whether or not
/// the root is a member of the current workspace
pub fn to_roots(&self) -> Vec<PackageRoot> {
- let mk_sysroot = |sysroot: Option<&Sysroot>| {
+ let mk_sysroot = |sysroot: Option<&Sysroot>, project_root: Option<&AbsPath>| {
sysroot.map(|sysroot| PackageRoot {
- is_local: false,
+ // mark the sysroot as mutable if it is located inside of the project
+ is_local: project_root
+ .map_or(false, |project_root| sysroot.src_root().starts_with(project_root)),
include: vec![sysroot.src_root().to_path_buf()],
exclude: Vec::new(),
})
@@ -434,7 +480,7 @@ impl ProjectWorkspace {
})
.collect::<FxHashSet<_>>()
.into_iter()
- .chain(mk_sysroot(sysroot.as_ref()))
+ .chain(mk_sysroot(sysroot.as_ref(), Some(project.path())))
.collect::<Vec<_>>(),
ProjectWorkspace::Cargo {
cargo,
@@ -484,7 +530,7 @@ impl ProjectWorkspace {
}
PackageRoot { is_local, include, exclude }
})
- .chain(mk_sysroot(sysroot.as_ref()))
+ .chain(mk_sysroot(sysroot.as_ref(), Some(cargo.workspace_root())))
.chain(rustc.iter().flat_map(|rustc| {
rustc.packages().map(move |krate| PackageRoot {
is_local: false,
@@ -501,7 +547,7 @@ impl ProjectWorkspace {
include: vec![detached_file.clone()],
exclude: Vec::new(),
})
- .chain(mk_sysroot(sysroot.as_ref()))
+ .chain(mk_sysroot(sysroot.as_ref(), None))
.collect(),
}
}
@@ -538,9 +584,9 @@ impl ProjectWorkspace {
load_proc_macro,
load,
project,
- sysroot,
+ sysroot.as_ref(),
extra_env,
- None,
+ Err("rust-project.json projects have no target layout set".into()),
),
ProjectWorkspace::Cargo {
cargo,
@@ -560,10 +606,19 @@ impl ProjectWorkspace {
rustc_cfg.clone(),
cfg_overrides,
build_scripts,
- target_layout.as_deref().map(Arc::from),
+ match target_layout.as_ref() {
+ Ok(it) => Ok(Arc::from(it.as_str())),
+ Err(it) => Err(Arc::from(it.as_str())),
+ },
),
ProjectWorkspace::DetachedFiles { files, sysroot, rustc_cfg } => {
- detached_files_to_crate_graph(rustc_cfg.clone(), load, files, sysroot, None)
+ detached_files_to_crate_graph(
+ rustc_cfg.clone(),
+ load,
+ files,
+ sysroot,
+ Err("detached file projects have no target layout set".into()),
+ )
}
};
if crate_graph.patch_cfg_if() {
@@ -573,6 +628,49 @@ impl ProjectWorkspace {
}
crate_graph
}
+
+ pub fn eq_ignore_build_data(&self, other: &Self) -> bool {
+ match (self, other) {
+ (
+ Self::Cargo {
+ cargo,
+ sysroot,
+ rustc,
+ rustc_cfg,
+ cfg_overrides,
+ toolchain,
+ build_scripts: _,
+ target_layout: _,
+ },
+ Self::Cargo {
+ cargo: o_cargo,
+ sysroot: o_sysroot,
+ rustc: o_rustc,
+ rustc_cfg: o_rustc_cfg,
+ cfg_overrides: o_cfg_overrides,
+ toolchain: o_toolchain,
+ build_scripts: _,
+ target_layout: _,
+ },
+ ) => {
+ cargo == o_cargo
+ && rustc == o_rustc
+ && rustc_cfg == o_rustc_cfg
+ && cfg_overrides == o_cfg_overrides
+ && toolchain == o_toolchain
+ && sysroot == o_sysroot
+ }
+ (
+ Self::Json { project, sysroot, rustc_cfg },
+ Self::Json { project: o_project, sysroot: o_sysroot, rustc_cfg: o_rustc_cfg },
+ ) => project == o_project && rustc_cfg == o_rustc_cfg && sysroot == o_sysroot,
+ (
+ Self::DetachedFiles { files, sysroot, rustc_cfg },
+ Self::DetachedFiles { files: o_files, sysroot: o_sysroot, rustc_cfg: o_rustc_cfg },
+ ) => files == o_files && sysroot == o_sysroot && rustc_cfg == o_rustc_cfg,
+ _ => false,
+ }
+ }
}
fn project_json_to_crate_graph(
@@ -580,9 +678,9 @@ fn project_json_to_crate_graph(
load_proc_macro: &mut dyn FnMut(&str, &AbsPath) -> ProcMacroLoadResult,
load: &mut dyn FnMut(&AbsPath) -> Option<FileId>,
project: &ProjectJson,
- sysroot: &Option<Sysroot>,
+ sysroot: Option<&Sysroot>,
extra_env: &FxHashMap<String, String>,
- target_layout: Option<Arc<str>>,
+ target_layout: TargetLayoutLoadResult,
) -> CrateGraph {
let mut crate_graph = CrateGraph::default();
let sysroot_deps = sysroot.as_ref().map(|sysroot| {
@@ -686,7 +784,7 @@ fn cargo_to_crate_graph(
rustc_cfg: Vec<CfgFlag>,
override_cfg: &CfgOverrides,
build_scripts: &WorkspaceBuildScripts,
- target_layout: Option<Arc<str>>,
+ target_layout: TargetLayoutLoadResult,
) -> CrateGraph {
let _p = profile::span("cargo_to_crate_graph");
let mut crate_graph = CrateGraph::default();
@@ -852,7 +950,7 @@ fn detached_files_to_crate_graph(
load: &mut dyn FnMut(&AbsPath) -> Option<FileId>,
detached_files: &[AbsPathBuf],
sysroot: &Option<Sysroot>,
- target_layout: Option<Arc<str>>,
+ target_layout: TargetLayoutLoadResult,
) -> CrateGraph {
let _p = profile::span("detached_files_to_crate_graph");
let mut crate_graph = CrateGraph::default();
@@ -917,7 +1015,7 @@ fn handle_rustc_crates(
cfg_options: &CfgOptions,
override_cfg: &CfgOverrides,
build_scripts: &WorkspaceBuildScripts,
- target_layout: Option<Arc<str>>,
+ target_layout: TargetLayoutLoadResult,
) {
let mut rustc_pkg_crates = FxHashMap::default();
// The root package of the rustc-dev component is rustc_driver, so we match that
@@ -1039,7 +1137,7 @@ fn add_target_crate_root(
file_id: FileId,
cargo_name: &str,
is_proc_macro: bool,
- target_layout: Option<Arc<str>>,
+ target_layout: TargetLayoutLoadResult,
) -> CrateId {
let edition = pkg.edition;
let mut potential_cfg_options = cfg_options.clone();
@@ -1108,7 +1206,7 @@ fn sysroot_to_crate_graph(
crate_graph: &mut CrateGraph,
sysroot: &Sysroot,
rustc_cfg: Vec<CfgFlag>,
- target_layout: Option<Arc<str>>,
+ target_layout: TargetLayoutLoadResult,
load: &mut dyn FnMut(&AbsPath) -> Option<FileId>,
) -> (SysrootPublicDeps, Option<CrateId>) {
let _p = profile::span("sysroot_to_crate_graph");
@@ -1150,9 +1248,7 @@ fn sysroot_to_crate_graph(
let public_deps = SysrootPublicDeps {
deps: sysroot
.public_deps()
- .map(|(name, idx, prelude)| {
- (CrateName::new(name).unwrap(), sysroot_crates[&idx], prelude)
- })
+ .map(|(name, idx, prelude)| (name, sysroot_crates[&idx], prelude))
.collect::<Vec<_>>(),
};
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/Cargo.toml b/src/tools/rust-analyzer/crates/rust-analyzer/Cargo.toml
index 56f14fe18..f0f1900c7 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/Cargo.toml
@@ -1,14 +1,15 @@
[package]
name = "rust-analyzer"
version = "0.0.0"
-authors = ["rust-analyzer Team"]
homepage = "https://github.com/rust-analyzer/rust-analyzer"
description = "A language server for the Rust programming language"
documentation = "https://rust-analyzer.github.io/manual.html"
-license = "MIT OR Apache-2.0"
autobins = false
-edition = "2021"
-rust-version = "1.65"
+
+authors.workspace = true
+edition.workspace = true
+license.workspace = true
+rust-version.workspace = true
[lib]
doctest = false
@@ -23,7 +24,7 @@ crossbeam-channel = "0.5.5"
dissimilar = "1.0.4"
itertools = "0.10.5"
scip = "0.1.1"
-lsp-types = { version = "=0.93.2", features = ["proposed"] }
+lsp-types = { version = "=0.94", features = ["proposed"] }
parking_lot = "0.12.1"
xflags = "0.3.0"
oorandom = "11.1.3"
@@ -31,8 +32,8 @@ rustc-hash = "1.1.0"
serde = { version = "1.0.137", features = ["derive"] }
serde_json = { version = "1.0.81", features = ["preserve_order"] }
threadpool = "1.8.1"
-rayon = "1.5.3"
-num_cpus = "1.13.1"
+rayon = "1.6.1"
+num_cpus = "1.15.0"
mimalloc = { version = "0.1.30", default-features = false, optional = true }
lsp-server = { version = "0.7.0", path = "../../lib/lsp-server" }
tracing = "0.1.35"
@@ -46,26 +47,25 @@ tracing-log = "0.1.3"
tracing-tree = "0.2.1"
always-assert = "0.1.2"
-stdx = { path = "../stdx", version = "0.0.0" }
-flycheck = { path = "../flycheck", version = "0.0.0" }
-ide = { path = "../ide", version = "0.0.0" }
-ide-db = { path = "../ide-db", version = "0.0.0" }
-profile = { path = "../profile", version = "0.0.0" }
-project-model = { path = "../project-model", version = "0.0.0" }
-syntax = { path = "../syntax", version = "0.0.0" }
-vfs = { path = "../vfs", version = "0.0.0" }
-vfs-notify = { path = "../vfs-notify", version = "0.0.0" }
-cfg = { path = "../cfg", version = "0.0.0" }
-toolchain = { path = "../toolchain", version = "0.0.0" }
-tt = { path = "../tt", version = "0.0.0" }
-proc-macro-api = { path = "../proc-macro-api", version = "0.0.0" }
-
+cfg.workspace = true
+flycheck.workspace = true
+hir-def.workspace = true
+hir-ty.workspace = true
+hir.workspace = true
+ide-db.workspace = true
# This should only be used in CLI
-ide-ssr = { path = "../ide-ssr", version = "0.0.0" }
-hir = { path = "../hir", version = "0.0.0" }
-hir-def = { path = "../hir-def", version = "0.0.0" }
-hir-ty = { path = "../hir-ty", version = "0.0.0" }
-proc-macro-srv = { path = "../proc-macro-srv", version = "0.0.0" }
+ide-ssr.workspace = true
+ide.workspace = true
+proc-macro-api.workspace = true
+proc-macro-srv.workspace = true
+profile.workspace = true
+project-model.workspace = true
+stdx.workspace = true
+syntax.workspace = true
+toolchain.workspace = true
+tt.workspace = true
+vfs-notify.workspace = true
+vfs.workspace = true
[target.'cfg(windows)'.dependencies]
winapi = "0.3.9"
@@ -78,9 +78,9 @@ expect-test = "1.4.0"
jod-thread = "0.1.2"
xshell = "0.2.2"
-test-utils = { path = "../test-utils" }
-sourcegen = { path = "../sourcegen" }
-mbe = { path = "../mbe" }
+test-utils.workspace = true
+sourcegen.workspace = true
+mbe.workspace = true
[features]
jemalloc = ["jemallocator", "profile/jemalloc"]
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/bin/main.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/bin/main.rs
index 53710749d..4de022b6e 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/bin/main.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/bin/main.rs
@@ -10,7 +10,6 @@ mod rustc_wrapper;
use std::{env, fs, path::Path, process};
use lsp_server::Connection;
-use project_model::ProjectManifest;
use rust_analyzer::{cli::flags, config::Config, from_json, Result};
use vfs::AbsPathBuf;
@@ -168,7 +167,18 @@ fn run_server() -> Result<()> {
}
};
- let mut config = Config::new(root_path, initialize_params.capabilities);
+ let workspace_roots = initialize_params
+ .workspace_folders
+ .map(|workspaces| {
+ workspaces
+ .into_iter()
+ .filter_map(|it| it.uri.to_file_path().ok())
+ .filter_map(|it| AbsPathBuf::try_from(it).ok())
+ .collect::<Vec<_>>()
+ })
+ .filter(|workspaces| !workspaces.is_empty())
+ .unwrap_or_else(|| vec![root_path.clone()]);
+ let mut config = Config::new(root_path, initialize_params.capabilities, workspace_roots);
if let Some(json) = initialize_params.initialization_options {
if let Err(e) = config.update(json) {
use lsp_types::{
@@ -183,8 +193,6 @@ fn run_server() -> Result<()> {
}
}
- config.client_specific_adjustments(&initialize_params.client_info);
-
let server_capabilities = rust_analyzer::server_capabilities(&config);
let initialize_result = lsp_types::InitializeResult {
@@ -204,25 +212,8 @@ fn run_server() -> Result<()> {
tracing::info!("Client '{}' {}", client_info.name, client_info.version.unwrap_or_default());
}
- if config.linked_projects().is_empty() && config.detached_files().is_empty() {
- let workspace_roots = initialize_params
- .workspace_folders
- .map(|workspaces| {
- workspaces
- .into_iter()
- .filter_map(|it| it.uri.to_file_path().ok())
- .filter_map(|it| AbsPathBuf::try_from(it).ok())
- .collect::<Vec<_>>()
- })
- .filter(|workspaces| !workspaces.is_empty())
- .unwrap_or_else(|| vec![config.root_path().clone()]);
-
- let discovered = ProjectManifest::discover_all(&workspace_roots);
- tracing::info!("discovered projects: {:?}", discovered);
- if discovered.is_empty() {
- tracing::error!("failed to find any projects in {:?}", workspace_roots);
- }
- config.discovered_projects = Some(discovered);
+ if !config.has_linked_projects() && config.detached_files().is_empty() {
+ config.rediscover_workspaces();
}
rust_analyzer::main_loop(config, connection)?;
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/caps.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/caps.rs
index 122d2e6ff..3628670ac 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/caps.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/caps.rs
@@ -1,4 +1,5 @@
//! Advertises the capabilities of the LSP Server.
+use ide_db::line_index::WideEncoding;
use lsp_types::{
CallHierarchyServerCapability, ClientCapabilities, CodeActionKind, CodeActionOptions,
CodeActionProviderCapability, CodeLensOptions, CompletionOptions,
@@ -10,21 +11,25 @@ use lsp_types::{
SemanticTokensFullOptions, SemanticTokensLegend, SemanticTokensOptions, ServerCapabilities,
SignatureHelpOptions, TextDocumentSyncCapability, TextDocumentSyncKind,
TextDocumentSyncOptions, TypeDefinitionProviderCapability, WorkDoneProgressOptions,
- WorkspaceFileOperationsServerCapabilities, WorkspaceServerCapabilities,
+ WorkspaceFileOperationsServerCapabilities, WorkspaceFoldersServerCapabilities,
+ WorkspaceServerCapabilities,
};
use serde_json::json;
use crate::config::{Config, RustfmtConfig};
-use crate::lsp_ext::supports_utf8;
+use crate::line_index::PositionEncoding;
+use crate::lsp_ext::negotiated_encoding;
use crate::semantic_tokens;
pub fn server_capabilities(config: &Config) -> ServerCapabilities {
ServerCapabilities {
- position_encoding: if supports_utf8(config.caps()) {
- Some(PositionEncodingKind::UTF8)
- } else {
- None
- },
+ position_encoding: Some(match negotiated_encoding(config.caps()) {
+ PositionEncoding::Utf8 => PositionEncodingKind::UTF8,
+ PositionEncoding::Wide(wide) => match wide {
+ WideEncoding::Utf16 => PositionEncodingKind::UTF16,
+ WideEncoding::Utf32 => PositionEncodingKind::UTF32,
+ },
+ }),
text_document_sync: Some(TextDocumentSyncCapability::Options(TextDocumentSyncOptions {
open_close: Some(true),
change: Some(TextDocumentSyncKind::INCREMENTAL),
@@ -80,7 +85,10 @@ pub fn server_capabilities(config: &Config) -> ServerCapabilities {
color_provider: None,
execute_command_provider: None,
workspace: Some(WorkspaceServerCapabilities {
- workspace_folders: None,
+ workspace_folders: Some(WorkspaceFoldersServerCapabilities {
+ supported: Some(true),
+ change_notifications: Some(OneOf::Left(true)),
+ }),
file_operations: Some(WorkspaceFileOperationsServerCapabilities {
did_create: None,
will_create: None,
@@ -130,6 +138,7 @@ pub fn server_capabilities(config: &Config) -> ServerCapabilities {
resolve_provider: Some(true),
},
))),
+ inline_value_provider: None,
experimental: Some(json!({
"externalDocs": true,
"hoverRange": true,
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/analysis_stats.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/analysis_stats.rs
index 053db5fc5..93297faa6 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/analysis_stats.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/analysis_stats.rs
@@ -15,7 +15,7 @@ use hir_def::{
expr::ExprId,
FunctionId,
};
-use hir_ty::{TyExt, TypeWalk};
+use hir_ty::{Interner, TyExt, TypeFlags};
use ide::{Analysis, AnalysisHost, LineCol, RootDatabase};
use ide_db::base_db::{
salsa::{self, debug::DebugQueryTable, ParallelDatabase},
@@ -33,7 +33,7 @@ use vfs::{AbsPathBuf, Vfs, VfsPath};
use crate::cli::{
flags::{self, OutputFormat},
- load_cargo::{load_workspace, LoadCargoConfig},
+ load_cargo::{load_workspace, LoadCargoConfig, ProcMacroServerChoice},
print_memory_usage,
progress_report::ProgressReport,
report_metric, Result, Verbosity,
@@ -59,11 +59,6 @@ impl flags::AnalysisStats {
true => None,
false => Some(RustcSource::Discover),
};
- let load_cargo_config = LoadCargoConfig {
- load_out_dirs_from_check: !self.disable_build_scripts,
- with_proc_macro: !self.disable_proc_macros,
- prefill_caches: false,
- };
let no_progress = &|_| ();
let mut db_load_sw = self.stop_watch();
@@ -73,6 +68,11 @@ impl flags::AnalysisStats {
let mut workspace = ProjectWorkspace::load(manifest, &cargo_config, no_progress)?;
let metadata_time = db_load_sw.elapsed();
+ let load_cargo_config = LoadCargoConfig {
+ load_out_dirs_from_check: !self.disable_build_scripts,
+ with_proc_macro_server: ProcMacroServerChoice::Sysroot,
+ prefill_caches: false,
+ };
let build_scripts_time = if self.disable_build_scripts {
None
@@ -280,12 +280,8 @@ impl flags::AnalysisStats {
}
true
} else {
- let mut is_partially_unknown = false;
- ty.walk(&mut |ty| {
- if ty.is_unknown() {
- is_partially_unknown = true;
- }
- });
+ let is_partially_unknown =
+ ty.data(Interner).flags.contains(TypeFlags::HAS_ERROR);
if is_partially_unknown {
num_exprs_partially_unknown += 1;
}
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/diagnostics.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/diagnostics.rs
index fd5b3ce61..ff821be53 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/diagnostics.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/diagnostics.rs
@@ -9,7 +9,7 @@ use ide_db::base_db::SourceDatabaseExt;
use crate::cli::{
flags,
- load_cargo::{load_workspace_at, LoadCargoConfig},
+ load_cargo::{load_workspace_at, LoadCargoConfig, ProcMacroServerChoice},
};
impl flags::Diagnostics {
@@ -17,7 +17,7 @@ impl flags::Diagnostics {
let cargo_config = Default::default();
let load_cargo_config = LoadCargoConfig {
load_out_dirs_from_check: !self.disable_build_scripts,
- with_proc_macro: !self.disable_proc_macros,
+ with_proc_macro_server: ProcMacroServerChoice::Sysroot,
prefill_caches: false,
};
let (host, _vfs, _proc_macro) =
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/load_cargo.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/load_cargo.rs
index 762d7d3a1..5a958d963 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/load_cargo.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/load_cargo.rs
@@ -1,6 +1,6 @@
//! Loads a Cargo project into a static instance of analysis, without support
//! for incorporating changes.
-use std::{path::Path, sync::Arc};
+use std::{convert::identity, path::Path, sync::Arc};
use anyhow::Result;
use crossbeam_channel::{unbounded, Receiver};
@@ -17,10 +17,17 @@ use crate::reload::{load_proc_macro, ProjectFolders, SourceRootConfig};
// what otherwise would be `pub(crate)` has to be `pub` here instead.
pub struct LoadCargoConfig {
pub load_out_dirs_from_check: bool,
- pub with_proc_macro: bool,
+ pub with_proc_macro_server: ProcMacroServerChoice,
pub prefill_caches: bool,
}
+#[derive(Debug, Clone, PartialEq, Eq)]
+pub enum ProcMacroServerChoice {
+ Sysroot,
+ Explicit(AbsPathBuf, Vec<String>),
+ None,
+}
+
// Note: Since this function is used by external tools that use rust-analyzer as a library
// what otherwise would be `pub(crate)` has to be `pub` here instead.
pub fn load_workspace_at(
@@ -59,15 +66,17 @@ pub fn load_workspace(
Box::new(loader)
};
- let proc_macro_client = if load_config.with_proc_macro {
- let (server_path, args): (_, &[_]) = match ws.find_sysroot_proc_macro_srv() {
- Some(server_path) => (server_path, &[]),
- None => (AbsPathBuf::assert(std::env::current_exe()?), &["proc-macro"]),
- };
-
- ProcMacroServer::spawn(server_path, args).map_err(|e| e.to_string())
- } else {
- Err("proc macro server disabled".to_owned())
+ let proc_macro_client = match &load_config.with_proc_macro_server {
+ ProcMacroServerChoice::Sysroot => ws
+ .find_sysroot_proc_macro_srv()
+ .ok_or_else(|| "failed to find sysroot proc-macro server".to_owned())
+ .and_then(|it| {
+ ProcMacroServer::spawn(it, identity::<&[&str]>(&[])).map_err(|e| e.to_string())
+ }),
+ ProcMacroServerChoice::Explicit(path, args) => {
+ ProcMacroServer::spawn(path.clone(), args).map_err(|e| e.to_string())
+ }
+ ProcMacroServerChoice::None => Err("proc macro server disabled".to_owned()),
};
let crate_graph = ws.to_crate_graph(
@@ -157,7 +166,7 @@ mod tests {
let cargo_config = CargoConfig::default();
let load_cargo_config = LoadCargoConfig {
load_out_dirs_from_check: false,
- with_proc_macro: false,
+ with_proc_macro_server: ProcMacroServerChoice::None,
prefill_caches: false,
};
let (host, _vfs, _proc_macro) =
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/lsif.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/lsif.rs
index af8356d04..3fc1aa4ea 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/lsif.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/lsif.rs
@@ -11,10 +11,12 @@ use ide::{
use ide_db::LineIndexDatabase;
use ide_db::base_db::salsa::{self, ParallelDatabase};
+use ide_db::line_index::WideEncoding;
use lsp_types::{self, lsif};
use project_model::{CargoConfig, ProjectManifest, ProjectWorkspace};
use vfs::{AbsPathBuf, Vfs};
+use crate::cli::load_cargo::ProcMacroServerChoice;
use crate::cli::{
flags,
load_cargo::{load_workspace, LoadCargoConfig},
@@ -126,7 +128,7 @@ impl LsifManager<'_> {
let line_index = self.db.line_index(file_id);
let line_index = LineIndex {
index: line_index,
- encoding: PositionEncoding::Utf16,
+ encoding: PositionEncoding::Wide(WideEncoding::Utf16),
endings: LineEndings::Unix,
};
let range_id = self.add_vertex(lsif::Vertex::Range {
@@ -248,7 +250,7 @@ impl LsifManager<'_> {
let line_index = self.db.line_index(file_id);
let line_index = LineIndex {
index: line_index,
- encoding: PositionEncoding::Utf16,
+ encoding: PositionEncoding::Wide(WideEncoding::Utf16),
endings: LineEndings::Unix,
};
let result = folds
@@ -291,7 +293,7 @@ impl flags::Lsif {
let no_progress = &|_| ();
let load_cargo_config = LoadCargoConfig {
load_out_dirs_from_check: true,
- with_proc_macro: true,
+ with_proc_macro_server: ProcMacroServerChoice::Sysroot,
prefill_caches: false,
};
let path = AbsPathBuf::assert(env::current_dir()?.join(&self.path));
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/scip.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/scip.rs
index b050d1e95..9a04fbea7 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/scip.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/scip.rs
@@ -5,7 +5,10 @@ use std::{
time::Instant,
};
-use crate::line_index::{LineEndings, LineIndex, PositionEncoding};
+use crate::{
+ cli::load_cargo::ProcMacroServerChoice,
+ line_index::{LineEndings, LineIndex, PositionEncoding},
+};
use hir::Name;
use ide::{
LineCol, MonikerDescriptorKind, StaticIndex, StaticIndexedFile, TextRange, TokenId,
@@ -31,7 +34,7 @@ impl flags::Scip {
let no_progress = &|s| (eprintln!("rust-analyzer: Loading {s}"));
let load_cargo_config = LoadCargoConfig {
load_out_dirs_from_check: true,
- with_proc_macro: true,
+ with_proc_macro_server: ProcMacroServerChoice::Sysroot,
prefill_caches: true,
};
let path = vfs::AbsPathBuf::assert(env::current_dir()?.join(&self.path));
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/ssr.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/ssr.rs
index 84c489171..3552f840a 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/ssr.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/ssr.rs
@@ -5,7 +5,7 @@ use project_model::CargoConfig;
use crate::cli::{
flags,
- load_cargo::{load_workspace_at, LoadCargoConfig},
+ load_cargo::{load_workspace_at, LoadCargoConfig, ProcMacroServerChoice},
Result,
};
@@ -15,7 +15,7 @@ impl flags::Ssr {
let cargo_config = CargoConfig::default();
let load_cargo_config = LoadCargoConfig {
load_out_dirs_from_check: true,
- with_proc_macro: true,
+ with_proc_macro_server: ProcMacroServerChoice::Sysroot,
prefill_caches: false,
};
let (host, vfs, _proc_macro) = load_workspace_at(
@@ -51,7 +51,7 @@ impl flags::Search {
let cargo_config = CargoConfig::default();
let load_cargo_config = LoadCargoConfig {
load_out_dirs_from_check: true,
- with_proc_macro: true,
+ with_proc_macro_server: ProcMacroServerChoice::Sysroot,
prefill_caches: false,
};
let (host, _vfs, _proc_macro) = load_workspace_at(
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs
index b0afbdc9a..f609a50a0 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs
@@ -20,7 +20,7 @@ use ide_db::{
SnippetCap,
};
use itertools::Itertools;
-use lsp_types::{ClientCapabilities, ClientInfo, MarkupKind};
+use lsp_types::{ClientCapabilities, MarkupKind};
use project_model::{
CargoConfig, CargoFeatures, ProjectJson, ProjectJsonData, ProjectManifest, RustcSource,
UnsetTestCrates,
@@ -33,7 +33,7 @@ use crate::{
caps::completion_item_edit_resolve,
diagnostics::DiagnosticsMapConfig,
line_index::PositionEncoding,
- lsp_ext::{self, supports_utf8, WorkspaceSymbolSearchKind, WorkspaceSymbolSearchScope},
+ lsp_ext::{self, negotiated_encoding, WorkspaceSymbolSearchKind, WorkspaceSymbolSearchScope},
};
mod patch_old_style;
@@ -117,6 +117,11 @@ config_data! {
///
/// This option does not take effect until rust-analyzer is restarted.
cargo_sysroot: Option<String> = "\"discover\"",
+ /// Relative path to the sysroot library sources. If left unset, this will default to
+ /// `{cargo.sysroot}/lib/rustlib/src/rust/library`.
+ ///
+ /// This option does not take effect until rust-analyzer is restarted.
+ cargo_sysrootSrc: Option<String> = "null",
/// Compilation target override (target triple).
// FIXME(@poliorcetics): move to multiple targets here too, but this will need more work
// than `checkOnSave_target`
@@ -195,6 +200,8 @@ config_data! {
completion_autoself_enable: bool = "true",
/// Whether to add parenthesis and argument snippets when completing function.
completion_callable_snippets: CallableCompletionDef = "\"fill_arguments\"",
+ /// Maximum number of completions to return. If `None`, the limit is infinite.
+ completion_limit: Option<usize> = "null",
/// Whether to show postfix snippets like `dbg`, `if`, `not`, etc.
completion_postfix_enable: bool = "true",
/// Enables completions of private items and fields that are defined in the current workspace even if they are not visible at the current position.
@@ -342,8 +349,6 @@ config_data! {
inlayHints_lifetimeElisionHints_enable: LifetimeElisionDef = "\"never\"",
/// Whether to prefer using parameter names as the name for elided lifetime hints if possible.
inlayHints_lifetimeElisionHints_useParameterNames: bool = "false",
- /// Whether to use location links for parts of type mentioned in inlay hints.
- inlayHints_locationLinks: bool = "true",
/// Maximum length for inlay hints. Set to null to have an unlimited length.
inlayHints_maxLength: Option<usize> = "25",
/// Whether to show function parameter name inlay hints at the call
@@ -521,6 +526,7 @@ impl Default for ConfigData {
#[derive(Debug, Clone)]
pub struct Config {
pub discovered_projects: Option<Vec<ProjectManifest>>,
+ pub workspace_roots: Vec<AbsPathBuf>,
caps: lsp_types::ClientCapabilities,
root_path: AbsPathBuf,
data: ConfigData,
@@ -717,7 +723,11 @@ impl fmt::Display for ConfigUpdateError {
}
impl Config {
- pub fn new(root_path: AbsPathBuf, caps: ClientCapabilities) -> Self {
+ pub fn new(
+ root_path: AbsPathBuf,
+ caps: ClientCapabilities,
+ workspace_roots: Vec<AbsPathBuf>,
+ ) -> Self {
Config {
caps,
data: ConfigData::default(),
@@ -725,20 +735,17 @@ impl Config {
discovered_projects: None,
root_path,
snippets: Default::default(),
+ workspace_roots,
}
}
- pub fn client_specific_adjustments(&mut self, client_info: &Option<ClientInfo>) {
- // FIXME: remove this when we drop support for vscode 1.65 and below
- if let Some(client) = client_info {
- if client.name.contains("Code") || client.name.contains("Codium") {
- if let Some(version) = &client.version {
- if version.as_str() < "1.76" {
- self.data.inlayHints_locationLinks = false;
- }
- }
- }
+ pub fn rediscover_workspaces(&mut self) {
+ let discovered = ProjectManifest::discover_all(&self.workspace_roots);
+ tracing::info!("discovered projects: {:?}", discovered);
+ if discovered.is_empty() {
+ tracing::error!("failed to find any projects in {:?}", &self.workspace_roots);
}
+ self.discovered_projects = Some(discovered);
}
pub fn update(&mut self, mut json: serde_json::Value) -> Result<(), ConfigUpdateError> {
@@ -837,6 +844,9 @@ macro_rules! try_or_def {
}
impl Config {
+ pub fn has_linked_projects(&self) -> bool {
+ !self.data.linkedProjects.is_empty()
+ }
pub fn linked_projects(&self) -> Vec<LinkedProject> {
match self.data.linkedProjects.as_slice() {
[] => match self.discovered_projects.as_ref() {
@@ -989,11 +999,7 @@ impl Config {
}
pub fn position_encoding(&self) -> PositionEncoding {
- if supports_utf8(&self.caps) {
- PositionEncoding::Utf8
- } else {
- PositionEncoding::Utf16
- }
+ negotiated_encoding(&self.caps)
}
fn experimental(&self, index: &'static str) -> bool {
@@ -1004,6 +1010,10 @@ impl Config {
self.experimental("codeActionGroup")
}
+ pub fn open_server_logs(&self) -> bool {
+ self.experimental("openServerLogs")
+ }
+
pub fn server_status_notification(&self) -> bool {
self.experimental("serverStatusNotification")
}
@@ -1044,7 +1054,7 @@ impl Config {
&self.data.cargo_extraEnv
}
- pub fn check_on_save_extra_env(&self) -> FxHashMap<String, String> {
+ pub fn check_extra_env(&self) -> FxHashMap<String, String> {
let mut extra_env = self.data.cargo_extraEnv.clone();
extra_env.extend(self.data.check_extraEnv.clone());
extra_env
@@ -1114,6 +1124,8 @@ impl Config {
RustcSource::Path(self.root_path.join(sysroot))
}
});
+ let sysroot_src =
+ self.data.cargo_sysrootSrc.as_ref().map(|sysroot| self.root_path.join(sysroot));
CargoConfig {
features: match &self.data.cargo_features {
@@ -1125,6 +1137,7 @@ impl Config {
},
target: self.data.cargo_target.clone(),
sysroot,
+ sysroot_src,
rustc_source,
unset_test_crates: UnsetTestCrates::Only(self.data.cargo_unsetTest.clone()),
wrap_rustc_in_build_scripts: self.data.cargo_buildScripts_useRustcWrapper,
@@ -1165,7 +1178,7 @@ impl Config {
FlycheckConfig::CustomCommand {
command,
args,
- extra_env: self.check_on_save_extra_env(),
+ extra_env: self.check_extra_env(),
invocation_strategy: match self.data.check_invocationStrategy {
InvocationStrategy::Once => flycheck::InvocationStrategy::Once,
InvocationStrategy::PerWorkspace => {
@@ -1210,7 +1223,7 @@ impl Config {
CargoFeaturesDef::Selected(it) => it,
},
extra_args: self.data.check_extraArgs.clone(),
- extra_env: self.check_on_save_extra_env(),
+ extra_env: self.check_extra_env(),
ansi_color_output: self.color_diagnostic_output(),
},
}
@@ -1229,7 +1242,6 @@ impl Config {
pub fn inlay_hints(&self) -> InlayHintsConfig {
InlayHintsConfig {
- location_links: self.data.inlayHints_locationLinks,
render_colons: self.data.inlayHints_renderColons,
type_hints: self.data.inlayHints_typeHints_enable,
parameter_hints: self.data.inlayHints_parameterHints_enable,
@@ -1329,6 +1341,7 @@ impl Config {
.snippet_support?
)),
snippets: self.snippets.clone(),
+ limit: self.data.completion_limit,
}
}
@@ -1409,7 +1422,8 @@ impl Config {
pub fn hover(&self) -> HoverConfig {
HoverConfig {
links_in_hover: self.data.hover_links_enable,
- documentation: self.data.hover_documentation_enable.then(|| {
+ documentation: self.data.hover_documentation_enable,
+ format: {
let is_markdown = try_or_def!(self
.caps
.text_document
@@ -1425,7 +1439,7 @@ impl Config {
} else {
HoverDocFormat::PlainText
}
- }),
+ },
keywords: self.data.hover_documentation_keywords_enable,
}
}
@@ -1454,6 +1468,10 @@ impl Config {
try_or_def!(self.caps.workspace.as_ref()?.code_lens.as_ref()?.refresh_support?)
}
+ pub fn inlay_hints_refresh(&self) -> bool {
+ try_or_def!(self.caps.workspace.as_ref()?.inlay_hint.as_ref()?.refresh_support?)
+ }
+
pub fn insert_replace_support(&self) -> bool {
try_or_def!(
self.caps
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/config/patch_old_style.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/config/patch_old_style.rs
index de6ac946a..73d2ed329 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/config/patch_old_style.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/config/patch_old_style.rs
@@ -114,16 +114,18 @@ pub(super) fn patch_json_for_outdated_configs(json: &mut Value) {
}
// completion_addCallArgumentSnippets completion_addCallParenthesis -> completion_callable_snippets
- let res = match (
- copy.pointer("/completion/addCallArgumentSnippets"),
- copy.pointer("/completion/addCallParenthesis"),
- ) {
- (Some(Value::Bool(true)), Some(Value::Bool(true))) => json!("fill_arguments"),
- (_, Some(Value::Bool(true))) => json!("add_parentheses"),
- (Some(Value::Bool(false)), Some(Value::Bool(false))) => json!("none"),
- (_, _) => return,
- };
- merge(json, json!({ "completion": { "callable": {"snippets": res }} }));
+ 'completion: {
+ let res = match (
+ copy.pointer("/completion/addCallArgumentSnippets"),
+ copy.pointer("/completion/addCallParenthesis"),
+ ) {
+ (Some(Value::Bool(true)), Some(Value::Bool(true))) => json!("fill_arguments"),
+ (_, Some(Value::Bool(true))) => json!("add_parentheses"),
+ (Some(Value::Bool(false)), Some(Value::Bool(false))) => json!("none"),
+ (_, _) => break 'completion,
+ };
+ merge(json, json!({ "completion": { "callable": {"snippets": res }} }));
+ }
// We need to do this due to the checkOnSave_enable -> checkOnSave change, as that key now can either be an object or a bool
// checkOnSave_* -> check_*
@@ -146,3 +148,23 @@ fn merge(dst: &mut Value, src: Value) {
(dst, src) => *dst = src,
}
}
+
+#[test]
+fn check_on_save_patching() {
+ let mut json = json!({ "checkOnSave": { "overrideCommand": "foo" }});
+ patch_json_for_outdated_configs(&mut json);
+ assert_eq!(
+ json,
+ json!({ "checkOnSave": { "overrideCommand": "foo" }, "check": { "overrideCommand": "foo" }})
+ );
+}
+
+#[test]
+fn check_on_save_patching_enable() {
+ let mut json = json!({ "checkOnSave": { "enable": true, "overrideCommand": "foo" }});
+ patch_json_for_outdated_configs(&mut json);
+ assert_eq!(
+ json,
+ json!({ "checkOnSave": true, "check": { "enable": true, "overrideCommand": "foo" }})
+ );
+}
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/diagnostics/to_proto.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/diagnostics/to_proto.rs
index acb416a06..415fa4e02 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/diagnostics/to_proto.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/diagnostics/to_proto.rs
@@ -3,6 +3,7 @@
use std::collections::HashMap;
use flycheck::{Applicability, DiagnosticLevel, DiagnosticSpan};
+use ide_db::line_index::WideEncoding;
use itertools::Itertools;
use stdx::format_to;
use vfs::{AbsPath, AbsPathBuf};
@@ -95,7 +96,8 @@ fn position(
let mut char_offset = 0;
let len_func = match position_encoding {
PositionEncoding::Utf8 => char::len_utf8,
- PositionEncoding::Utf16 => char::len_utf16,
+ PositionEncoding::Wide(WideEncoding::Utf16) => char::len_utf16,
+ PositionEncoding::Wide(WideEncoding::Utf32) => |_| 1,
};
for c in line.text.chars() {
char_offset += 1;
@@ -534,7 +536,7 @@ mod tests {
let (sender, _) = crossbeam_channel::unbounded();
let state = GlobalState::new(
sender,
- Config::new(workspace_root.to_path_buf(), ClientCapabilities::default()),
+ Config::new(workspace_root.to_path_buf(), ClientCapabilities::default(), Vec::new()),
);
let snap = state.snapshot();
let mut actual = map_rust_diagnostic_to_lsp(&config, &diagnostic, workspace_root, &snap);
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/from_proto.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/from_proto.rs
index 2dbb14fcd..50af38cd6 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/from_proto.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/from_proto.rs
@@ -1,7 +1,10 @@
//! Conversion lsp_types types to rust-analyzer specific ones.
use anyhow::format_err;
-use ide::{Annotation, AnnotationKind, AssistKind, LineCol, LineColUtf16};
-use ide_db::base_db::{FileId, FilePosition, FileRange};
+use ide::{Annotation, AnnotationKind, AssistKind, LineCol};
+use ide_db::{
+ base_db::{FileId, FilePosition, FileRange},
+ line_index::WideLineCol,
+};
use syntax::{TextRange, TextSize};
use vfs::AbsPathBuf;
@@ -26,9 +29,9 @@ pub(crate) fn vfs_path(url: &lsp_types::Url) -> Result<vfs::VfsPath> {
pub(crate) fn offset(line_index: &LineIndex, position: lsp_types::Position) -> Result<TextSize> {
let line_col = match line_index.encoding {
PositionEncoding::Utf8 => LineCol { line: position.line, col: position.character },
- PositionEncoding::Utf16 => {
- let line_col = LineColUtf16 { line: position.line, col: position.character };
- line_index.index.to_utf8(line_col)
+ PositionEncoding::Wide(enc) => {
+ let line_col = WideLineCol { line: position.line, col: position.character };
+ line_index.index.to_utf8(enc, line_col)
}
};
let text_size =
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/global_state.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/global_state.rs
index c6f4e9ce0..aca6c9235 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/global_state.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/global_state.rs
@@ -179,10 +179,9 @@ impl GlobalState {
pub(crate) fn process_changes(&mut self) -> bool {
let _p = profile::span("GlobalState::process_changes");
- // A file was added or deleted
- let mut has_structure_changes = false;
let mut workspace_structure_change = None;
+ let mut file_changes = FxHashMap::default();
let (change, changed_files) = {
let mut change = Change::new();
let (vfs, line_endings_map) = &mut *self.vfs.write();
@@ -191,43 +190,56 @@ impl GlobalState {
return false;
}
- // important: this needs to be a stable sort, the order between changes is relevant
- // for the same file ids
- changed_files.sort_by_key(|file| file.file_id);
- // We need to fix up the changed events a bit, if we have a create or modify for a file
- // id that is followed by a delete we actually no longer observe the file text from the
- // create or modify which may cause problems later on
- changed_files.dedup_by(|a, b| {
+ // We need to fix up the changed events a bit. If we have a create or modify for a file
+ // id that is followed by a delete we actually skip observing the file text from the
+ // earlier event, to avoid problems later on.
+ for changed_file in &changed_files {
use vfs::ChangeKind::*;
- if a.file_id != b.file_id {
- return false;
- }
+ file_changes
+ .entry(changed_file.file_id)
+ .and_modify(|(change, just_created)| {
+ // None -> Delete => keep
+ // Create -> Delete => collapse
+ //
+ match (change, just_created, changed_file.change_kind) {
+ // latter `Delete` wins
+ (change, _, Delete) => *change = Delete,
+ // merge `Create` with `Create` or `Modify`
+ (Create, _, Create | Modify) => {}
+ // collapse identical `Modify`es
+ (Modify, _, Modify) => {}
+ // equivalent to `Modify`
+ (change @ Delete, just_created, Create) => {
+ *change = Modify;
+ *just_created = true;
+ }
+ // shouldn't occur, but collapse into `Create`
+ (change @ Delete, just_created, Modify) => {
+ *change = Create;
+ *just_created = true;
+ }
+ // shouldn't occur, but collapse into `Modify`
+ (Modify, _, Create) => {}
+ }
+ })
+ .or_insert((
+ changed_file.change_kind,
+ matches!(changed_file.change_kind, Create),
+ ));
+ }
- match (a.change_kind, b.change_kind) {
- // duplicate can be merged
- (Create, Create) | (Modify, Modify) | (Delete, Delete) => true,
- // just leave the create, modify is irrelevant
- (Create, Modify) => {
- std::mem::swap(a, b);
- true
- }
- // modify becomes irrelevant if the file is deleted
- (Modify, Delete) => true,
- // we should fully remove this occurrence,
- // but leaving just a delete works as well
- (Create, Delete) => true,
- // this is equivalent to a modify
- (Delete, Create) => {
- a.change_kind = Modify;
- true
- }
- // can't really occur
- (Modify, Create) => false,
- (Delete, Modify) => false,
- }
- });
+ changed_files.extend(
+ file_changes
+ .into_iter()
+ .filter(|(_, (change_kind, just_created))| {
+ !matches!((change_kind, just_created), (vfs::ChangeKind::Delete, true))
+ })
+ .map(|(file_id, (change_kind, _))| vfs::ChangedFile { file_id, change_kind }),
+ );
+ // A file was added or deleted
+ let mut has_structure_changes = false;
for file in &changed_files {
if let Some(path) = vfs.file_path(file.file_id).as_path() {
let path = path.to_path_buf();
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers.rs
index 59bdd3061..4e08bd0a7 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers.rs
@@ -29,7 +29,6 @@ use project_model::{ManifestPath, ProjectWorkspace, TargetKind};
use serde_json::json;
use stdx::{format_to, never};
use syntax::{algo, ast, AstNode, TextRange, TextSize};
-use tracing::error;
use vfs::AbsPathBuf;
use crate::{
@@ -937,8 +936,7 @@ pub(crate) fn handle_hover(
let line_index = snap.file_line_index(file_range.file_id)?;
let range = to_proto::range(&line_index, info.range);
- let markup_kind =
- snap.config.hover().documentation.map_or(ide::HoverDocFormat::Markdown, |kind| kind);
+ let markup_kind = snap.config.hover().format;
let hover = lsp_ext::Hover {
hover: lsp_types::Hover {
contents: HoverContents::Markup(to_proto::markup_content(
@@ -1360,55 +1358,10 @@ pub(crate) fn handle_inlay_hints(
}
pub(crate) fn handle_inlay_hints_resolve(
- snap: GlobalStateSnapshot,
- mut hint: InlayHint,
+ _snap: GlobalStateSnapshot,
+ hint: InlayHint,
) -> Result<InlayHint> {
let _p = profile::span("handle_inlay_hints_resolve");
- let data = match hint.data.take() {
- Some(it) => it,
- None => return Ok(hint),
- };
-
- let resolve_data: lsp_ext::InlayHintResolveData = serde_json::from_value(data)?;
-
- match snap.url_file_version(&resolve_data.text_document.uri) {
- Some(version) if version == resolve_data.text_document.version => {}
- Some(version) => {
- error!(
- "attempted inlayHints/resolve of '{}' at version {} while server version is {}",
- resolve_data.text_document.uri, resolve_data.text_document.version, version,
- );
- return Ok(hint);
- }
- None => {
- error!(
- "attempted inlayHints/resolve of unknown file '{}' at version {}",
- resolve_data.text_document.uri, resolve_data.text_document.version,
- );
- return Ok(hint);
- }
- }
- let file_range = from_proto::file_range_uri(
- &snap,
- &resolve_data.text_document.uri,
- match resolve_data.position {
- PositionOrRange::Position(pos) => Range::new(pos, pos),
- PositionOrRange::Range(range) => range,
- },
- )?;
- let info = match snap.analysis.hover(&snap.config.hover(), file_range)? {
- None => return Ok(hint),
- Some(info) => info,
- };
-
- let markup_kind =
- snap.config.hover().documentation.map_or(ide::HoverDocFormat::Markdown, |kind| kind);
-
- // FIXME: hover actions?
- hint.tooltip = Some(lsp_types::InlayHintTooltip::MarkupContent(to_proto::markup_content(
- info.info.markup,
- markup_kind,
- )));
Ok(hint)
}
@@ -1516,7 +1469,8 @@ pub(crate) fn handle_semantic_tokens_full(
let mut highlight_config = snap.config.highlighting_config();
// Avoid flashing a bunch of unresolved references when the proc-macro servers haven't been spawned yet.
- highlight_config.syntactic_name_ref_highlighting = !snap.proc_macros_loaded;
+ highlight_config.syntactic_name_ref_highlighting =
+ snap.workspaces.is_empty() || !snap.proc_macros_loaded;
let highlights = snap.analysis.highlight(highlight_config, file_id)?;
let semantic_tokens = to_proto::semantic_tokens(&text, &line_index, highlights);
@@ -1539,7 +1493,8 @@ pub(crate) fn handle_semantic_tokens_full_delta(
let mut highlight_config = snap.config.highlighting_config();
// Avoid flashing a bunch of unresolved references when the proc-macro servers haven't been spawned yet.
- highlight_config.syntactic_name_ref_highlighting = !snap.proc_macros_loaded;
+ highlight_config.syntactic_name_ref_highlighting =
+ snap.workspaces.is_empty() || !snap.proc_macros_loaded;
let highlights = snap.analysis.highlight(highlight_config, file_id)?;
let semantic_tokens = to_proto::semantic_tokens(&text, &line_index, highlights);
@@ -1570,7 +1525,12 @@ pub(crate) fn handle_semantic_tokens_range(
let text = snap.analysis.file_text(frange.file_id)?;
let line_index = snap.file_line_index(frange.file_id)?;
- let highlights = snap.analysis.highlight_range(snap.config.highlighting_config(), frange)?;
+ let mut highlight_config = snap.config.highlighting_config();
+ // Avoid flashing a bunch of unresolved references when the proc-macro servers haven't been spawned yet.
+ highlight_config.syntactic_name_ref_highlighting =
+ snap.workspaces.is_empty() || !snap.proc_macros_loaded;
+
+ let highlights = snap.analysis.highlight_range(highlight_config, frange)?;
let semantic_tokens = to_proto::semantic_tokens(&text, &line_index, highlights);
Ok(Some(semantic_tokens.into()))
}
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/integrated_benchmarks.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/integrated_benchmarks.rs
index 405d261db..e8912b907 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/integrated_benchmarks.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/integrated_benchmarks.rs
@@ -21,7 +21,7 @@ use project_model::CargoConfig;
use test_utils::project_root;
use vfs::{AbsPathBuf, VfsPath};
-use crate::cli::load_cargo::{load_workspace_at, LoadCargoConfig};
+use crate::cli::load_cargo::{load_workspace_at, LoadCargoConfig, ProcMacroServerChoice};
#[test]
fn integrated_highlighting_benchmark() {
@@ -36,7 +36,7 @@ fn integrated_highlighting_benchmark() {
let cargo_config = CargoConfig::default();
let load_cargo_config = LoadCargoConfig {
load_out_dirs_from_check: true,
- with_proc_macro: false,
+ with_proc_macro_server: ProcMacroServerChoice::None,
prefill_caches: false,
};
@@ -90,7 +90,7 @@ fn integrated_completion_benchmark() {
let cargo_config = CargoConfig::default();
let load_cargo_config = LoadCargoConfig {
load_out_dirs_from_check: true,
- with_proc_macro: false,
+ with_proc_macro_server: ProcMacroServerChoice::None,
prefill_caches: true,
};
@@ -146,6 +146,7 @@ fn integrated_completion_benchmark() {
},
snippets: Vec::new(),
prefer_no_std: false,
+ limit: None,
};
let position =
FilePosition { file_id, offset: TextSize::try_from(completion_offset).unwrap() };
@@ -184,6 +185,7 @@ fn integrated_completion_benchmark() {
},
snippets: Vec::new(),
prefer_no_std: false,
+ limit: None,
};
let position =
FilePosition { file_id, offset: TextSize::try_from(completion_offset).unwrap() };
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/line_index.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/line_index.rs
index 2945dba12..791cd931d 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/line_index.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/line_index.rs
@@ -7,9 +7,12 @@
use std::sync::Arc;
+use ide_db::line_index::WideEncoding;
+
+#[derive(Clone, Copy)]
pub enum PositionEncoding {
Utf8,
- Utf16,
+ Wide(WideEncoding),
}
pub(crate) struct LineIndex {
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp_ext.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp_ext.rs
index 65620b420..e33589cc5 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp_ext.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp_ext.rs
@@ -2,14 +2,17 @@
use std::{collections::HashMap, path::PathBuf};
+use ide_db::line_index::WideEncoding;
use lsp_types::request::Request;
+use lsp_types::PositionEncodingKind;
use lsp_types::{
notification::Notification, CodeActionKind, DocumentOnTypeFormattingParams,
PartialResultParams, Position, Range, TextDocumentIdentifier, WorkDoneProgressParams,
};
-use lsp_types::{PositionEncodingKind, VersionedTextDocumentIdentifier};
use serde::{Deserialize, Serialize};
+use crate::line_index::PositionEncoding;
+
pub enum AnalyzerStatus {}
impl Request for AnalyzerStatus {
@@ -151,6 +154,13 @@ impl Notification for ClearFlycheck {
const METHOD: &'static str = "rust-analyzer/clearFlycheck";
}
+pub enum OpenServerLogs {}
+
+impl Notification for OpenServerLogs {
+ type Params = ();
+ const METHOD: &'static str = "rust-analyzer/openServerLogs";
+}
+
#[derive(Deserialize, Serialize, Debug)]
#[serde(rename_all = "camelCase")]
pub struct RunFlycheckParams {
@@ -474,16 +484,22 @@ pub(crate) enum CodeLensResolveData {
References(lsp_types::TextDocumentPositionParams),
}
-pub fn supports_utf8(caps: &lsp_types::ClientCapabilities) -> bool {
- match &caps.general {
- Some(general) => general
- .position_encodings
- .as_deref()
- .unwrap_or_default()
- .iter()
- .any(|it| it == &PositionEncodingKind::UTF8),
- _ => false,
+pub fn negotiated_encoding(caps: &lsp_types::ClientCapabilities) -> PositionEncoding {
+ let client_encodings = match &caps.general {
+ Some(general) => general.position_encodings.as_deref().unwrap_or_default(),
+ None => &[],
+ };
+
+ for enc in client_encodings {
+ if enc == &PositionEncodingKind::UTF8 {
+ return PositionEncoding::Utf8;
+ } else if enc == &PositionEncodingKind::UTF32 {
+ return PositionEncoding::Wide(WideEncoding::Utf32);
+ }
+ // NB: intentionally prefer just about anything else to utf-16.
}
+
+ PositionEncoding::Wide(WideEncoding::Utf16)
}
pub enum MoveItem {}
@@ -568,10 +584,7 @@ pub struct CompletionResolveData {
}
#[derive(Debug, Serialize, Deserialize)]
-pub struct InlayHintResolveData {
- pub text_document: VersionedTextDocumentIdentifier,
- pub position: PositionOrRange,
-}
+pub struct InlayHintResolveData {}
#[derive(Debug, Serialize, Deserialize)]
pub struct CompletionImport {
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp_utils.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp_utils.rs
index dcaee9285..30f1c53c1 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp_utils.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp_utils.rs
@@ -2,12 +2,13 @@
use std::{mem, ops::Range, sync::Arc};
use lsp_server::Notification;
+use lsp_types::request::Request;
use crate::{
from_proto,
global_state::GlobalState,
line_index::{LineEndings, LineIndex, PositionEncoding},
- LspError,
+ lsp_ext, LspError,
};
pub(crate) fn invalid_params_error(message: String) -> LspError {
@@ -46,20 +47,47 @@ impl GlobalState {
/// If `additional_info` is [`Some`], appends a note to the notification telling to check the logs.
/// This will always log `message` + `additional_info` to the server's error log.
pub(crate) fn show_and_log_error(&mut self, message: String, additional_info: Option<String>) {
- let mut message = message;
match additional_info {
Some(additional_info) => {
- tracing::error!("{}\n\n{}", &message, &additional_info);
- if tracing::enabled!(tracing::Level::ERROR) {
- message.push_str("\n\nCheck the server logs for additional info.");
+ tracing::error!("{}:\n{}", &message, &additional_info);
+ match self.config.open_server_logs() && tracing::enabled!(tracing::Level::ERROR) {
+ true => self.send_request::<lsp_types::request::ShowMessageRequest>(
+ lsp_types::ShowMessageRequestParams {
+ typ: lsp_types::MessageType::ERROR,
+ message,
+ actions: Some(vec![lsp_types::MessageActionItem {
+ title: "Open server logs".to_owned(),
+ properties: Default::default(),
+ }]),
+ },
+ |this, resp| {
+ let lsp_server::Response { error: None, result: Some(result), .. } = resp
+ else { return };
+ if let Ok(Some(_item)) = crate::from_json::<
+ <lsp_types::request::ShowMessageRequest as lsp_types::request::Request>::Result,
+ >(
+ lsp_types::request::ShowMessageRequest::METHOD, &result
+ ) {
+ this.send_notification::<lsp_ext::OpenServerLogs>(());
+ }
+ },
+ ),
+ false => self.send_notification::<lsp_types::notification::ShowMessage>(
+ lsp_types::ShowMessageParams {
+ typ: lsp_types::MessageType::ERROR,
+ message,
+ },
+ ),
}
}
- None => tracing::error!("{}", &message),
- }
+ None => {
+ tracing::error!("{}", &message);
- self.send_notification::<lsp_types::notification::ShowMessage>(
- lsp_types::ShowMessageParams { typ: lsp_types::MessageType::ERROR, message },
- )
+ self.send_notification::<lsp_types::notification::ShowMessage>(
+ lsp_types::ShowMessageParams { typ: lsp_types::MessageType::ERROR, message },
+ );
+ }
+ }
}
/// rust-analyzer is resilient -- if it fails, this doesn't usually affect
@@ -77,7 +105,7 @@ impl GlobalState {
let from_source_build = option_env!("POKE_RA_DEVS").is_some();
let profiling_enabled = std::env::var("RA_PROFILE").is_ok();
if from_source_build || profiling_enabled {
- self.show_message(lsp_types::MessageType::ERROR, message)
+ self.show_and_log_error(message, None);
}
}
@@ -133,6 +161,7 @@ impl GlobalState {
}
pub(crate) fn apply_document_changes(
+ encoding: PositionEncoding,
file_contents: impl FnOnce() -> String,
mut content_changes: Vec<lsp_types::TextDocumentContentChangeEvent>,
) -> String {
@@ -164,9 +193,9 @@ pub(crate) fn apply_document_changes(
let mut line_index = LineIndex {
// the index will be overwritten in the bottom loop's first iteration
index: Arc::new(ide::LineIndex::new(&text)),
- // We don't care about line endings or offset encoding here.
+ // We don't care about line endings here.
endings: LineEndings::Unix,
- encoding: PositionEncoding::Utf16,
+ encoding,
};
// The changes we got must be applied sequentially, but can cross lines so we
@@ -228,6 +257,7 @@ pub(crate) fn all_edits_are_disjoint(
#[cfg(test)]
mod tests {
+ use ide_db::line_index::WideEncoding;
use lsp_types::{
CompletionItem, CompletionTextEdit, InsertReplaceEdit, Position, Range,
TextDocumentContentChangeEvent,
@@ -250,9 +280,11 @@ mod tests {
};
}
- let text = apply_document_changes(|| String::new(), vec![]);
+ let encoding = PositionEncoding::Wide(WideEncoding::Utf16);
+ let text = apply_document_changes(encoding, || String::new(), vec![]);
assert_eq!(text, "");
let text = apply_document_changes(
+ encoding,
|| text,
vec![TextDocumentContentChangeEvent {
range: None,
@@ -261,39 +293,49 @@ mod tests {
}],
);
assert_eq!(text, "the");
- let text = apply_document_changes(|| text, c![0, 3; 0, 3 => " quick"]);
+ let text = apply_document_changes(encoding, || text, c![0, 3; 0, 3 => " quick"]);
assert_eq!(text, "the quick");
- let text = apply_document_changes(|| text, c![0, 0; 0, 4 => "", 0, 5; 0, 5 => " foxes"]);
+ let text =
+ apply_document_changes(encoding, || text, c![0, 0; 0, 4 => "", 0, 5; 0, 5 => " foxes"]);
assert_eq!(text, "quick foxes");
- let text = apply_document_changes(|| text, c![0, 11; 0, 11 => "\ndream"]);
+ let text = apply_document_changes(encoding, || text, c![0, 11; 0, 11 => "\ndream"]);
assert_eq!(text, "quick foxes\ndream");
- let text = apply_document_changes(|| text, c![1, 0; 1, 0 => "have "]);
+ let text = apply_document_changes(encoding, || text, c![1, 0; 1, 0 => "have "]);
assert_eq!(text, "quick foxes\nhave dream");
let text = apply_document_changes(
+ encoding,
|| text,
c![0, 0; 0, 0 => "the ", 1, 4; 1, 4 => " quiet", 1, 16; 1, 16 => "s\n"],
);
assert_eq!(text, "the quick foxes\nhave quiet dreams\n");
- let text = apply_document_changes(|| text, c![0, 15; 0, 15 => "\n", 2, 17; 2, 17 => "\n"]);
+ let text = apply_document_changes(
+ encoding,
+ || text,
+ c![0, 15; 0, 15 => "\n", 2, 17; 2, 17 => "\n"],
+ );
assert_eq!(text, "the quick foxes\n\nhave quiet dreams\n\n");
let text = apply_document_changes(
+ encoding,
|| text,
c![1, 0; 1, 0 => "DREAM", 2, 0; 2, 0 => "they ", 3, 0; 3, 0 => "DON'T THEY?"],
);
assert_eq!(text, "the quick foxes\nDREAM\nthey have quiet dreams\nDON'T THEY?\n");
- let text = apply_document_changes(|| text, c![0, 10; 1, 5 => "", 2, 0; 2, 12 => ""]);
+ let text =
+ apply_document_changes(encoding, || text, c![0, 10; 1, 5 => "", 2, 0; 2, 12 => ""]);
assert_eq!(text, "the quick \nthey have quiet dreams\n");
let text = String::from("❤️");
- let text = apply_document_changes(|| text, c![0, 0; 0, 0 => "a"]);
+ let text = apply_document_changes(encoding, || text, c![0, 0; 0, 0 => "a"]);
assert_eq!(text, "a❤️");
let text = String::from("a\nb");
- let text = apply_document_changes(|| text, c![0, 1; 1, 0 => "\nțc", 0, 1; 1, 1 => "d"]);
+ let text =
+ apply_document_changes(encoding, || text, c![0, 1; 1, 0 => "\nțc", 0, 1; 1, 1 => "d"]);
assert_eq!(text, "adcb");
let text = String::from("a\nb");
- let text = apply_document_changes(|| text, c![0, 1; 1, 0 => "ț\nc", 0, 2; 0, 2 => "c"]);
+ let text =
+ apply_document_changes(encoding, || text, c![0, 1; 1, 0 => "ț\nc", 0, 2; 0, 2 => "c"]);
assert_eq!(text, "ațc\ncb");
}
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/main_loop.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/main_loop.rs
index 0bc940dfe..d1e38b33c 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/main_loop.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/main_loop.rs
@@ -14,7 +14,7 @@ use ide_db::base_db::{SourceDatabaseExt, VfsPath};
use itertools::Itertools;
use lsp_server::{Connection, Notification, Request};
use lsp_types::notification::Notification as _;
-use vfs::{ChangeKind, FileId};
+use vfs::{AbsPathBuf, ChangeKind, FileId};
use crate::{
config::Config,
@@ -287,8 +287,10 @@ impl GlobalState {
|| self.fetch_build_data_queue.op_requested());
if became_quiescent {
- // Project has loaded properly, kick off initial flycheck
- self.flycheck.iter().for_each(FlycheckHandle::restart);
+ if self.config.check_on_save() {
+ // Project has loaded properly, kick off initial flycheck
+ self.flycheck.iter().for_each(FlycheckHandle::restart);
+ }
if self.config.prefill_caches() {
self.prime_caches_queue.request_op("became quiescent".to_string());
}
@@ -305,13 +307,18 @@ impl GlobalState {
if self.config.code_lens_refresh() {
self.send_request::<lsp_types::request::CodeLensRefresh>((), |_, _| ());
}
- }
- if !was_quiescent || state_changed || memdocs_added_or_removed {
- if self.config.publish_diagnostics() {
- self.update_diagnostics()
+ // Refresh inlay hints if the client supports it.
+ if self.config.inlay_hints_refresh() {
+ self.send_request::<lsp_types::request::InlayHintRefreshRequest>((), |_, _| ());
}
}
+
+ if (!was_quiescent || state_changed || memdocs_added_or_removed)
+ && self.config.publish_diagnostics()
+ {
+ self.update_diagnostics()
+ }
}
if let Some(diagnostic_changes) = self.diagnostics.take_changes() {
@@ -604,8 +611,8 @@ impl GlobalState {
Ok(())
});
- if let RequestDispatcher { req: Some(req), global_state: this } = &mut dispatcher {
- if this.shutdown_requested {
+ match &mut dispatcher {
+ RequestDispatcher { req: Some(req), global_state: this } if this.shutdown_requested => {
this.respond(lsp_server::Response::new_err(
req.id.clone(),
lsp_server::ErrorCode::InvalidRequest as i32,
@@ -613,16 +620,7 @@ impl GlobalState {
));
return;
}
-
- // Avoid flashing a bunch of unresolved references during initial load.
- if this.workspaces.is_empty() && !this.is_quiescent() {
- this.respond(lsp_server::Response::new_err(
- req.id.clone(),
- lsp_server::ErrorCode::ContentModified as i32,
- "waiting for cargo metadata or cargo check".to_owned(),
- ));
- return;
- }
+ _ => (),
}
dispatcher
@@ -833,6 +831,7 @@ impl GlobalState {
let vfs = &mut this.vfs.write().0;
let file_id = vfs.file_id(&path).unwrap();
let text = apply_document_changes(
+ this.config.position_encoding(),
|| std::str::from_utf8(vfs.file_contents(file_id)).unwrap().into(),
params.content_changes,
);
@@ -935,6 +934,30 @@ impl GlobalState {
Ok(())
})?
+ .on::<lsp_types::notification::DidChangeWorkspaceFolders>(|this, params| {
+ let config = Arc::make_mut(&mut this.config);
+
+ for workspace in params.event.removed {
+ let Ok(path) = workspace.uri.to_file_path() else { continue };
+ let Ok(path) = AbsPathBuf::try_from(path) else { continue };
+ let Some(position) = config.workspace_roots.iter().position(|it| it == &path) else { continue };
+ config.workspace_roots.remove(position);
+ }
+
+ let added = params
+ .event
+ .added
+ .into_iter()
+ .filter_map(|it| it.uri.to_file_path().ok())
+ .filter_map(|it| AbsPathBuf::try_from(it).ok());
+ config.workspace_roots.extend(added);
+ if !config.has_linked_projects() && config.detached_files().is_empty() {
+ config.rediscover_workspaces();
+ this.fetch_workspaces_queue.request_op("client workspaces changed".to_string())
+ }
+
+ Ok(())
+ })?
.on::<lsp_types::notification::DidChangeWatchedFiles>(|this, params| {
for change in params.changes {
if let Ok(path) = from_proto::abs_path(&change.uri) {
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/reload.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/reload.rs
index 9bbce70ec..abce0d737 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/reload.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/reload.rs
@@ -34,6 +34,8 @@ use crate::{
op_queue::Cause,
};
+use ::tt::token_id as tt;
+
#[derive(Debug)]
pub(crate) enum ProjectWorkspaceProgress {
Begin,
@@ -148,11 +150,11 @@ impl GlobalState {
)
}
LinkedProject::InlineJsonProject(it) => {
- project_model::ProjectWorkspace::load_inline(
+ Ok(project_model::ProjectWorkspace::load_inline(
it.clone(),
cargo_config.target.as_deref(),
&cargo_config.extra_env,
- )
+ ))
}
})
.collect::<Vec<_>>();
@@ -212,35 +214,11 @@ impl GlobalState {
let workspaces =
workspaces.iter().filter_map(|res| res.as_ref().ok().cloned()).collect::<Vec<_>>();
- fn eq_ignore_build_data<'a>(
- left: &'a ProjectWorkspace,
- right: &'a ProjectWorkspace,
- ) -> bool {
- let key = |p: &'a ProjectWorkspace| match p {
- ProjectWorkspace::Cargo {
- cargo,
- sysroot,
- rustc,
- rustc_cfg,
- cfg_overrides,
-
- build_scripts: _,
- toolchain: _,
- target_layout: _,
- } => Some((cargo, sysroot, rustc, rustc_cfg, cfg_overrides)),
- _ => None,
- };
- match (key(left), key(right)) {
- (Some(lk), Some(rk)) => lk == rk,
- _ => left == right,
- }
- }
-
let same_workspaces = workspaces.len() == self.workspaces.len()
&& workspaces
.iter()
.zip(self.workspaces.iter())
- .all(|(l, r)| eq_ignore_build_data(l, r));
+ .all(|(l, r)| l.eq_ignore_build_data(r));
if same_workspaces {
let (workspaces, build_scripts) = self.fetch_build_data_queue.last_op_result();
@@ -270,7 +248,8 @@ impl GlobalState {
// Here, we completely changed the workspace (Cargo.toml edit), so
// we don't care about build-script results, they are stale.
- self.workspaces = Arc::new(workspaces)
+ // FIXME: can we abort the build scripts here?
+ self.workspaces = Arc::new(workspaces);
}
if let FilesWatcher::Client = self.config.files().watcher {
@@ -289,7 +268,10 @@ impl GlobalState {
]
})
})
- .map(|glob_pattern| lsp_types::FileSystemWatcher { glob_pattern, kind: None })
+ .map(|glob_pattern| lsp_types::FileSystemWatcher {
+ glob_pattern: lsp_types::GlobPattern::String(glob_pattern),
+ kind: None,
+ })
.collect(),
};
let registration = lsp_types::Registration {
@@ -362,7 +344,7 @@ impl GlobalState {
let loader = &mut self.loader;
let mem_docs = &self.mem_docs;
let mut load = move |path: &AbsPath| {
- let _p = profile::span("GlobalState::load");
+ let _p = profile::span("switch_workspaces::load");
let vfs_path = vfs::VfsPath::from(path.to_path_buf());
if !mem_docs.contains(&vfs_path) {
let contents = loader.handle.load_sync(path);
@@ -584,10 +566,10 @@ pub(crate) fn load_proc_macro(
path: &AbsPath,
dummy_replace: &[Box<str>],
) -> ProcMacroLoadResult {
+ let server = server.map_err(ToOwned::to_owned)?;
let res: Result<Vec<_>, String> = (|| {
let dylib = MacroDylib::new(path.to_path_buf())
.map_err(|io| format!("Proc-macro dylib loading failed: {io}"))?;
- let server = server.map_err(ToOwned::to_owned)?;
let vec = server.load_dylib(dylib).map_err(|e| format!("{e}"))?;
if vec.is_empty() {
return Err("proc macro library returned no proc macros".to_string());
@@ -679,7 +661,7 @@ pub(crate) fn load_proc_macro(
_: Option<&tt::Subtree>,
_: &Env,
) -> Result<tt::Subtree, ProcMacroExpansionError> {
- Ok(tt::Subtree::default())
+ Ok(tt::Subtree::empty())
}
}
}
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/to_proto.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/to_proto.rs
index e736b2ff9..92029dc1d 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/to_proto.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/to_proto.rs
@@ -9,9 +9,9 @@ use ide::{
Annotation, AnnotationKind, Assist, AssistKind, Cancellable, CompletionItem,
CompletionItemKind, CompletionRelevance, Documentation, FileId, FileRange, FileSystemEdit,
Fold, FoldKind, Highlight, HlMod, HlOperator, HlPunct, HlRange, HlTag, Indel, InlayHint,
- InlayHintLabel, InlayKind, Markup, NavigationTarget, ReferenceCategory, RenameError, Runnable,
- Severity, SignatureHelp, SourceChange, StructureNodeKind, SymbolKind, TextEdit, TextRange,
- TextSize,
+ InlayHintLabel, InlayHintLabelPart, InlayKind, Markup, NavigationTarget, ReferenceCategory,
+ RenameError, Runnable, Severity, SignatureHelp, SourceChange, StructureNodeKind, SymbolKind,
+ TextEdit, TextRange, TextSize,
};
use itertools::Itertools;
use serde_json::to_value;
@@ -31,8 +31,8 @@ pub(crate) fn position(line_index: &LineIndex, offset: TextSize) -> lsp_types::P
let line_col = line_index.index.line_col(offset);
match line_index.encoding {
PositionEncoding::Utf8 => lsp_types::Position::new(line_col.line, line_col.col),
- PositionEncoding::Utf16 => {
- let line_col = line_index.index.to_utf16(line_col);
+ PositionEncoding::Wide(enc) => {
+ let line_col = line_index.index.to_wide(enc, line_col);
lsp_types::Position::new(line_col.line, line_col.col)
}
}
@@ -212,11 +212,17 @@ pub(crate) fn completion_items(
tdpp: lsp_types::TextDocumentPositionParams,
items: Vec<CompletionItem>,
) -> Vec<lsp_types::CompletionItem> {
- let max_relevance = items.iter().map(|it| it.relevance().score()).max().unwrap_or_default();
+ let max_relevance = items.iter().map(|it| it.relevance.score()).max().unwrap_or_default();
let mut res = Vec::with_capacity(items.len());
for item in items {
- completion_item(&mut res, config, line_index, &tdpp, max_relevance, item)
+ completion_item(&mut res, config, line_index, &tdpp, max_relevance, item);
}
+
+ if let Some(limit) = config.completion().limit {
+ res.sort_by(|item1, item2| item1.sort_text.cmp(&item2.sort_text));
+ res.truncate(limit);
+ }
+
res
}
@@ -229,22 +235,26 @@ fn completion_item(
item: CompletionItem,
) {
let insert_replace_support = config.insert_replace_support().then_some(tdpp.position);
+ let ref_match = item.ref_match();
+ let lookup = item.lookup().to_string();
+
let mut additional_text_edits = Vec::new();
// LSP does not allow arbitrary edits in completion, so we have to do a
// non-trivial mapping here.
let text_edit = {
let mut text_edit = None;
- let source_range = item.source_range();
- for indel in item.text_edit().iter() {
+ let source_range = item.source_range;
+ for indel in item.text_edit {
if indel.delete.contains_range(source_range) {
+ // Extract this indel as the main edit
text_edit = Some(if indel.delete == source_range {
self::completion_text_edit(line_index, insert_replace_support, indel.clone())
} else {
assert!(source_range.end() == indel.delete.end());
let range1 = TextRange::new(indel.delete.start(), source_range.start());
let range2 = source_range;
- let indel1 = Indel::replace(range1, String::new());
+ let indel1 = Indel::delete(range1);
let indel2 = Indel::replace(range2, indel.insert.clone());
additional_text_edits.push(self::text_edit(line_index, indel1));
self::completion_text_edit(line_index, insert_replace_support, indel2)
@@ -258,23 +268,23 @@ fn completion_item(
text_edit.unwrap()
};
- let insert_text_format = item.is_snippet().then_some(lsp_types::InsertTextFormat::SNIPPET);
- let tags = item.deprecated().then(|| vec![lsp_types::CompletionItemTag::DEPRECATED]);
- let command = if item.trigger_call_info() && config.client_commands().trigger_parameter_hints {
+ let insert_text_format = item.is_snippet.then_some(lsp_types::InsertTextFormat::SNIPPET);
+ let tags = item.deprecated.then(|| vec![lsp_types::CompletionItemTag::DEPRECATED]);
+ let command = if item.trigger_call_info && config.client_commands().trigger_parameter_hints {
Some(command::trigger_parameter_hints())
} else {
None
};
let mut lsp_item = lsp_types::CompletionItem {
- label: item.label().to_string(),
- detail: item.detail().map(|it| it.to_string()),
- filter_text: Some(item.lookup().to_string()),
- kind: Some(completion_item_kind(item.kind())),
+ label: item.label.to_string(),
+ detail: item.detail.map(|it| it.to_string()),
+ filter_text: Some(lookup),
+ kind: Some(completion_item_kind(item.kind)),
text_edit: Some(text_edit),
additional_text_edits: Some(additional_text_edits),
- documentation: item.documentation().map(documentation),
- deprecated: Some(item.deprecated()),
+ documentation: item.documentation.map(documentation),
+ deprecated: Some(item.deprecated),
tags,
command,
insert_text_format,
@@ -288,12 +298,13 @@ fn completion_item(
});
}
- set_score(&mut lsp_item, max_relevance, item.relevance());
+ set_score(&mut lsp_item, max_relevance, item.relevance);
if config.completion().enable_imports_on_the_fly {
- if let imports @ [_, ..] = item.imports_to_add() {
- let imports: Vec<_> = imports
- .iter()
+ if !item.import_to_add.is_empty() {
+ let imports: Vec<_> = item
+ .import_to_add
+ .into_iter()
.filter_map(|import_edit| {
let import_path = &import_edit.import_path;
let import_name = import_path.segments().last()?;
@@ -310,18 +321,13 @@ fn completion_item(
}
}
- if let Some((mutability, offset, relevance)) = item.ref_match() {
- let mut lsp_item_with_ref = lsp_item.clone();
+ if let Some((label, indel, relevance)) = ref_match {
+ let mut lsp_item_with_ref = lsp_types::CompletionItem { label, ..lsp_item.clone() };
+ lsp_item_with_ref
+ .additional_text_edits
+ .get_or_insert_with(Default::default)
+ .push(self::text_edit(line_index, indel));
set_score(&mut lsp_item_with_ref, max_relevance, relevance);
- lsp_item_with_ref.label =
- format!("&{}{}", mutability.as_keyword_for_ref(), lsp_item_with_ref.label);
- lsp_item_with_ref.additional_text_edits.get_or_insert_with(Default::default).push(
- self::text_edit(
- line_index,
- Indel::insert(offset, format!("&{}", mutability.as_keyword_for_ref())),
- ),
- );
-
acc.push(lsp_item_with_ref);
};
@@ -431,137 +437,140 @@ pub(crate) fn inlay_hint(
mut inlay_hint: InlayHint,
) -> Cancellable<lsp_types::InlayHint> {
match inlay_hint.kind {
- InlayKind::ParameterHint if render_colons => inlay_hint.label.append_str(":"),
- InlayKind::TypeHint if render_colons => inlay_hint.label.prepend_str(": "),
- InlayKind::ClosureReturnTypeHint => inlay_hint.label.prepend_str(" -> "),
- InlayKind::DiscriminantHint => inlay_hint.label.prepend_str(" = "),
+ InlayKind::Parameter if render_colons => inlay_hint.label.append_str(":"),
+ InlayKind::Type if render_colons => inlay_hint.label.prepend_str(": "),
+ InlayKind::ClosureReturnType => inlay_hint.label.prepend_str(" -> "),
+ InlayKind::Discriminant => inlay_hint.label.prepend_str(" = "),
_ => {}
}
+ let (label, tooltip) = inlay_hint_label(snap, inlay_hint.label)?;
+
Ok(lsp_types::InlayHint {
position: match inlay_hint.kind {
// before annotated thing
InlayKind::OpeningParenthesis
- | InlayKind::ParameterHint
- | InlayKind::AdjustmentHint
- | InlayKind::BindingModeHint => position(line_index, inlay_hint.range.start()),
+ | InlayKind::Parameter
+ | InlayKind::Adjustment
+ | InlayKind::BindingMode => position(line_index, inlay_hint.range.start()),
// after annotated thing
- InlayKind::ClosureReturnTypeHint
- | InlayKind::TypeHint
- | InlayKind::DiscriminantHint
- | InlayKind::ChainingHint
- | InlayKind::GenericParamListHint
+ InlayKind::ClosureReturnType
+ | InlayKind::Type
+ | InlayKind::Discriminant
+ | InlayKind::Chaining
+ | InlayKind::GenericParamList
| InlayKind::ClosingParenthesis
- | InlayKind::AdjustmentHintPostfix
- | InlayKind::LifetimeHint
- | InlayKind::ClosingBraceHint => position(line_index, inlay_hint.range.end()),
+ | InlayKind::AdjustmentPostfix
+ | InlayKind::Lifetime
+ | InlayKind::ClosingBrace => position(line_index, inlay_hint.range.end()),
},
padding_left: Some(match inlay_hint.kind {
- InlayKind::TypeHint => !render_colons,
- InlayKind::ChainingHint | InlayKind::ClosingBraceHint => true,
+ InlayKind::Type => !render_colons,
+ InlayKind::Chaining | InlayKind::ClosingBrace => true,
InlayKind::ClosingParenthesis
- | InlayKind::DiscriminantHint
+ | InlayKind::Discriminant
| InlayKind::OpeningParenthesis
- | InlayKind::BindingModeHint
- | InlayKind::ClosureReturnTypeHint
- | InlayKind::GenericParamListHint
- | InlayKind::AdjustmentHint
- | InlayKind::AdjustmentHintPostfix
- | InlayKind::LifetimeHint
- | InlayKind::ParameterHint => false,
+ | InlayKind::BindingMode
+ | InlayKind::ClosureReturnType
+ | InlayKind::GenericParamList
+ | InlayKind::Adjustment
+ | InlayKind::AdjustmentPostfix
+ | InlayKind::Lifetime
+ | InlayKind::Parameter => false,
}),
padding_right: Some(match inlay_hint.kind {
InlayKind::ClosingParenthesis
| InlayKind::OpeningParenthesis
- | InlayKind::ChainingHint
- | InlayKind::ClosureReturnTypeHint
- | InlayKind::GenericParamListHint
- | InlayKind::AdjustmentHint
- | InlayKind::AdjustmentHintPostfix
- | InlayKind::TypeHint
- | InlayKind::DiscriminantHint
- | InlayKind::ClosingBraceHint => false,
- InlayKind::BindingModeHint => inlay_hint.label.as_simple_str() != Some("&"),
- InlayKind::ParameterHint | InlayKind::LifetimeHint => true,
+ | InlayKind::Chaining
+ | InlayKind::ClosureReturnType
+ | InlayKind::GenericParamList
+ | InlayKind::Adjustment
+ | InlayKind::AdjustmentPostfix
+ | InlayKind::Type
+ | InlayKind::Discriminant
+ | InlayKind::ClosingBrace => false,
+ InlayKind::BindingMode => {
+ matches!(&label, lsp_types::InlayHintLabel::String(s) if s != "&")
+ }
+ InlayKind::Parameter | InlayKind::Lifetime => true,
}),
kind: match inlay_hint.kind {
- InlayKind::ParameterHint => Some(lsp_types::InlayHintKind::PARAMETER),
- InlayKind::ClosureReturnTypeHint | InlayKind::TypeHint | InlayKind::ChainingHint => {
+ InlayKind::Parameter => Some(lsp_types::InlayHintKind::PARAMETER),
+ InlayKind::ClosureReturnType | InlayKind::Type | InlayKind::Chaining => {
Some(lsp_types::InlayHintKind::TYPE)
}
InlayKind::ClosingParenthesis
- | InlayKind::DiscriminantHint
+ | InlayKind::Discriminant
| InlayKind::OpeningParenthesis
- | InlayKind::BindingModeHint
- | InlayKind::GenericParamListHint
- | InlayKind::LifetimeHint
- | InlayKind::AdjustmentHint
- | InlayKind::AdjustmentHintPostfix
- | InlayKind::ClosingBraceHint => None,
+ | InlayKind::BindingMode
+ | InlayKind::GenericParamList
+ | InlayKind::Lifetime
+ | InlayKind::Adjustment
+ | InlayKind::AdjustmentPostfix
+ | InlayKind::ClosingBrace => None,
},
text_edits: None,
- data: (|| match inlay_hint.tooltip {
- Some(ide::InlayTooltip::HoverOffset(file_id, offset)) => {
- let uri = url(snap, file_id);
- let line_index = snap.file_line_index(file_id).ok()?;
-
- let text_document = lsp_types::VersionedTextDocumentIdentifier {
- version: snap.url_file_version(&uri)?,
- uri,
- };
- to_value(lsp_ext::InlayHintResolveData {
- text_document,
- position: lsp_ext::PositionOrRange::Position(position(&line_index, offset)),
- })
- .ok()
- }
- Some(ide::InlayTooltip::HoverRanged(file_id, text_range)) => {
- let uri = url(snap, file_id);
- let text_document = lsp_types::VersionedTextDocumentIdentifier {
- version: snap.url_file_version(&uri)?,
- uri,
- };
- let line_index = snap.file_line_index(file_id).ok()?;
- to_value(lsp_ext::InlayHintResolveData {
- text_document,
- position: lsp_ext::PositionOrRange::Range(range(&line_index, text_range)),
- })
- .ok()
- }
- _ => None,
- })(),
- tooltip: Some(match inlay_hint.tooltip {
- Some(ide::InlayTooltip::String(s)) => lsp_types::InlayHintTooltip::String(s),
- _ => lsp_types::InlayHintTooltip::String(inlay_hint.label.to_string()),
- }),
- label: inlay_hint_label(snap, inlay_hint.label)?,
+ data: None,
+ tooltip,
+ label,
})
}
fn inlay_hint_label(
snap: &GlobalStateSnapshot,
- label: InlayHintLabel,
-) -> Cancellable<lsp_types::InlayHintLabel> {
- Ok(match label.as_simple_str() {
- Some(s) => lsp_types::InlayHintLabel::String(s.into()),
- None => lsp_types::InlayHintLabel::LabelParts(
- label
+ mut label: InlayHintLabel,
+) -> Cancellable<(lsp_types::InlayHintLabel, Option<lsp_types::InlayHintTooltip>)> {
+ let res = match &*label.parts {
+ [InlayHintLabelPart { linked_location: None, .. }] => {
+ let InlayHintLabelPart { text, tooltip, .. } = label.parts.pop().unwrap();
+ (
+ lsp_types::InlayHintLabel::String(text),
+ match tooltip {
+ Some(ide::InlayTooltip::String(s)) => {
+ Some(lsp_types::InlayHintTooltip::String(s))
+ }
+ Some(ide::InlayTooltip::Markdown(s)) => {
+ Some(lsp_types::InlayHintTooltip::MarkupContent(lsp_types::MarkupContent {
+ kind: lsp_types::MarkupKind::Markdown,
+ value: s,
+ }))
+ }
+ None => None,
+ },
+ )
+ }
+ _ => {
+ let parts = label
.parts
.into_iter()
.map(|part| {
- Ok(lsp_types::InlayHintLabelPart {
- value: part.text,
- tooltip: None,
- location: part
- .linked_location
- .map(|range| location(snap, range))
- .transpose()?,
- command: None,
- })
+ part.linked_location.map(|range| location(snap, range)).transpose().map(
+ |location| lsp_types::InlayHintLabelPart {
+ value: part.text,
+ tooltip: match part.tooltip {
+ Some(ide::InlayTooltip::String(s)) => {
+ Some(lsp_types::InlayHintLabelPartTooltip::String(s))
+ }
+ Some(ide::InlayTooltip::Markdown(s)) => {
+ Some(lsp_types::InlayHintLabelPartTooltip::MarkupContent(
+ lsp_types::MarkupContent {
+ kind: lsp_types::MarkupKind::Markdown,
+ value: s,
+ },
+ ))
+ }
+ None => None,
+ },
+ location,
+ command: None,
+ },
+ )
})
- .collect::<Cancellable<Vec<_>>>()?,
- ),
- })
+ .collect::<Cancellable<_>>()?;
+ (lsp_types::InlayHintLabel::LabelParts(parts), None)
+ }
+ };
+ Ok(res)
}
static TOKEN_RESULT_COUNTER: AtomicU32 = AtomicU32::new(1);
@@ -757,6 +766,7 @@ pub(crate) fn folding_range(
end_line,
end_character: None,
kind,
+ collapsed_text: None,
}
} else {
lsp_types::FoldingRange {
@@ -765,6 +775,7 @@ pub(crate) fn folding_range(
end_line: range.end.line,
end_character: Some(range.end.character),
kind,
+ collapsed_text: None,
}
}
}
@@ -1351,7 +1362,7 @@ pub(crate) mod command {
pub(crate) fn trigger_parameter_hints() -> lsp_types::Command {
lsp_types::Command {
title: "triggerParameterHints".into(),
- command: "editor.action.triggerParameterHints".into(),
+ command: "rust-analyzer.triggerParameterHints".into(),
arguments: None,
}
}
@@ -1420,7 +1431,7 @@ fn main() {
let line_index = LineIndex {
index: Arc::new(ide::LineIndex::new(text)),
endings: LineEndings::Unix,
- encoding: PositionEncoding::Utf16,
+ encoding: PositionEncoding::Utf8,
};
let converted: Vec<lsp_types::FoldingRange> =
folds.into_iter().map(|it| folding_range(text, &line_index, true, it)).collect();
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/tests/slow-tests/main.rs b/src/tools/rust-analyzer/crates/rust-analyzer/tests/slow-tests/main.rs
index 5e3e19d44..587d64096 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/tests/slow-tests/main.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/tests/slow-tests/main.rs
@@ -22,7 +22,7 @@ use lsp_types::{
notification::DidOpenTextDocument,
request::{
CodeActionRequest, Completion, Formatting, GotoTypeDefinition, HoverRequest,
- WillRenameFiles, WorkspaceSymbol,
+ WillRenameFiles, WorkspaceSymbolRequest,
},
CodeActionContext, CodeActionParams, CompletionParams, DidOpenTextDocumentParams,
DocumentFormattingParams, FileRename, FormattingOptions, GotoDefinitionParams, HoverParams,
@@ -1095,5 +1095,5 @@ pub fn bar() {}
.server()
.wait_until_workspace_is_loaded();
- server.request::<WorkspaceSymbol>(Default::default(), json!([]));
+ server.request::<WorkspaceSymbolRequest>(Default::default(), json!([]));
}
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/tests/slow-tests/support.rs b/src/tools/rust-analyzer/crates/rust-analyzer/tests/slow-tests/support.rs
index 269212ebb..037fc89ac 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/tests/slow-tests/support.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/tests/slow-tests/support.rs
@@ -107,6 +107,7 @@ impl<'a> Project<'a> {
did_change_watched_files: Some(
lsp_types::DidChangeWatchedFilesClientCapabilities {
dynamic_registration: Some(true),
+ relative_pattern_support: None,
},
),
..Default::default()
@@ -137,6 +138,7 @@ impl<'a> Project<'a> {
})),
..Default::default()
},
+ Vec::new(),
);
config.discovered_projects = Some(discovered_projects);
config.update(self.config).expect("invalid config");
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/tests/slow-tests/tidy.rs b/src/tools/rust-analyzer/crates/rust-analyzer/tests/slow-tests/tidy.rs
index 35b5af731..8e3097fce 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/tests/slow-tests/tidy.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/tests/slow-tests/tidy.rs
@@ -82,7 +82,6 @@ fn files_are_tidy() {
check_dbg(&path, &text);
check_test_attrs(&path, &text);
check_trailing_ws(&path, &text);
- deny_clippy(&path, &text);
tidy_docs.visit(&path, &text);
tidy_marks.visit(&path, &text);
}
@@ -144,32 +143,6 @@ fn check_cargo_toml(path: &Path, text: String) {
}
}
-fn deny_clippy(path: &Path, text: &str) {
- let ignore = &[
- // The documentation in string literals may contain anything for its own purposes
- "ide-db/src/generated/lints.rs",
- // The tests test clippy lint hovers
- "ide/src/hover/tests.rs",
- // The tests test clippy lint completions
- "ide-completion/src/tests/attribute.rs",
- ];
- if ignore.iter().any(|p| path.ends_with(p)) {
- return;
- }
-
- if text.contains("\u{61}llow(clippy") {
- panic!(
- "\n\nallowing lints is forbidden: {}.
-rust-analyzer intentionally doesn't check clippy on CI.
-You can allow lint globally via `xtask clippy`.
-See https://github.com/rust-lang/rust-clippy/issues/5537 for discussion.
-
-",
- path.display()
- )
- }
-}
-
#[cfg(not(feature = "in-rust-tree"))]
#[test]
fn check_licenses() {
diff --git a/src/tools/rust-analyzer/crates/sourcegen/Cargo.toml b/src/tools/rust-analyzer/crates/sourcegen/Cargo.toml
index 593dc4e55..fb2b9ebef 100644
--- a/src/tools/rust-analyzer/crates/sourcegen/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/sourcegen/Cargo.toml
@@ -2,9 +2,11 @@
name = "sourcegen"
version = "0.0.0"
description = "TBD"
-license = "MIT OR Apache-2.0"
-edition = "2021"
-rust-version = "1.65"
+
+authors.workspace = true
+edition.workspace = true
+license.workspace = true
+rust-version.workspace = true
[lib]
doctest = false
diff --git a/src/tools/rust-analyzer/crates/stdx/Cargo.toml b/src/tools/rust-analyzer/crates/stdx/Cargo.toml
index f7b7d0964..c881f2fd3 100644
--- a/src/tools/rust-analyzer/crates/stdx/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/stdx/Cargo.toml
@@ -2,9 +2,11 @@
name = "stdx"
version = "0.0.0"
description = "TBD"
-license = "MIT OR Apache-2.0"
-edition = "2021"
-rust-version = "1.65"
+
+authors.workspace = true
+edition.workspace = true
+license.workspace = true
+rust-version.workspace = true
[lib]
doctest = false
diff --git a/src/tools/rust-analyzer/crates/stdx/src/lib.rs b/src/tools/rust-analyzer/crates/stdx/src/lib.rs
index 51e109798..5639aaf57 100644
--- a/src/tools/rust-analyzer/crates/stdx/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/stdx/src/lib.rs
@@ -2,15 +2,16 @@
#![warn(rust_2018_idioms, unused_lifetimes, semicolon_in_expressions_from_macros)]
+use std::io as sio;
use std::process::Command;
use std::{cmp::Ordering, ops, time::Instant};
-use std::{io as sio, iter};
mod macros;
pub mod hash;
pub mod process;
pub mod panic_context;
pub mod non_empty_vec;
+pub mod rand;
pub use always_assert::{always, never};
@@ -39,15 +40,19 @@ Uncomment `default = [ "backtrace" ]` in `crates/stdx/Cargo.toml`.
}
pub fn to_lower_snake_case(s: &str) -> String {
- to_snake_case(s, char::to_ascii_lowercase)
+ to_snake_case(s, char::to_lowercase)
}
pub fn to_upper_snake_case(s: &str) -> String {
- to_snake_case(s, char::to_ascii_uppercase)
+ to_snake_case(s, char::to_uppercase)
}
// Code partially taken from rust/compiler/rustc_lint/src/nonstandard_style.rs
// commit: 9626f2b
-fn to_snake_case<F: Fn(&char) -> char>(mut s: &str, change_case: F) -> String {
+fn to_snake_case<F, I>(mut s: &str, change_case: F) -> String
+where
+ F: Fn(char) -> I,
+ I: Iterator<Item = char>,
+{
let mut words = vec![];
// Preserve leading underscores
@@ -75,7 +80,7 @@ fn to_snake_case<F: Fn(&char) -> char>(mut s: &str, change_case: F) -> String {
}
last_upper = ch.is_uppercase();
- buf.extend(iter::once(change_case(&ch)));
+ buf.extend(change_case(ch));
}
words.push(buf);
diff --git a/src/tools/rust-analyzer/crates/stdx/src/macros.rs b/src/tools/rust-analyzer/crates/stdx/src/macros.rs
index d91fc690c..1a9982fa8 100644
--- a/src/tools/rust-analyzer/crates/stdx/src/macros.rs
+++ b/src/tools/rust-analyzer/crates/stdx/src/macros.rs
@@ -43,5 +43,14 @@ macro_rules! impl_from {
}
)*)?
)*
+ };
+ ($($variant:ident$(<$V:ident>)?),* for $enum:ident) => {
+ $(
+ impl$(<$V>)? From<$variant$(<$V>)?> for $enum$(<$V>)? {
+ fn from(it: $variant$(<$V>)?) -> $enum$(<$V>)? {
+ $enum::$variant(it)
+ }
+ }
+ )*
}
}
diff --git a/src/tools/rust-analyzer/crates/stdx/src/rand.rs b/src/tools/rust-analyzer/crates/stdx/src/rand.rs
new file mode 100644
index 000000000..64aa57eae
--- /dev/null
+++ b/src/tools/rust-analyzer/crates/stdx/src/rand.rs
@@ -0,0 +1,21 @@
+//! We don't use `rand`, as that's too many things for us.
+//!
+//! We currently use oorandom instead, but it's missing these two utilities.
+//! Perhaps we should switch to `fastrand`, or our own small PRNG, it's not like
+//! we need anything more complicated than xor-shift.
+
+pub fn shuffle<T>(slice: &mut [T], mut rand_index: impl FnMut(usize) -> usize) {
+ let mut remaining = slice.len() - 1;
+ while remaining > 0 {
+ let index = rand_index(remaining);
+ slice.swap(remaining, index);
+ remaining -= 1;
+ }
+}
+
+pub fn seed() -> u64 {
+ use std::collections::hash_map::RandomState;
+ use std::hash::{BuildHasher, Hasher};
+
+ RandomState::new().build_hasher().finish()
+}
diff --git a/src/tools/rust-analyzer/crates/syntax/Cargo.toml b/src/tools/rust-analyzer/crates/syntax/Cargo.toml
index 00743cca5..8fc493a23 100644
--- a/src/tools/rust-analyzer/crates/syntax/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/syntax/Cargo.toml
@@ -2,10 +2,12 @@
name = "syntax"
version = "0.0.0"
description = "Comment and whitespace preserving parser for the Rust language"
-license = "MIT OR Apache-2.0"
repository = "https://github.com/rust-lang/rust-analyzer"
-edition = "2021"
-rust-version = "1.65"
+
+authors.workspace = true
+edition.workspace = true
+license.workspace = true
+rust-version.workspace = true
[lib]
doctest = false
@@ -14,26 +16,26 @@ doctest = false
cov-mark = "2.0.0-pre.1"
itertools = "0.10.5"
rowan = "0.15.10"
-rustc_lexer = { version = "725.0.0", package = "rustc-ap-rustc_lexer" }
+rustc_lexer = { version = "727.0.0", package = "rustc-ap-rustc_lexer" }
rustc-hash = "1.1.0"
-once_cell = "1.15.0"
+once_cell = "1.17.0"
indexmap = "1.9.1"
smol_str = "0.1.23"
-stdx = { path = "../stdx", version = "0.0.0" }
-text-edit = { path = "../text-edit", version = "0.0.0" }
-parser = { path = "../parser", version = "0.0.0" }
-profile = { path = "../profile", version = "0.0.0" }
+parser.workspace = true
+profile.workspace = true
+stdx.workspace = true
+text-edit.workspace = true
[dev-dependencies]
-rayon = "1.5.3"
+rayon = "1.6.1"
expect-test = "1.4.0"
proc-macro2 = "1.0.47"
quote = "1.0.20"
ungrammar = "1.16.1"
-test-utils = { path = "../test-utils" }
-sourcegen = { path = "../sourcegen" }
+test-utils.workspace = true
+sourcegen.workspace = true
[features]
in-rust-tree = []
diff --git a/src/tools/rust-analyzer/crates/syntax/fuzz/Cargo.toml b/src/tools/rust-analyzer/crates/syntax/fuzz/Cargo.toml
index f295c4006..6070222f1 100644
--- a/src/tools/rust-analyzer/crates/syntax/fuzz/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/syntax/fuzz/Cargo.toml
@@ -1,18 +1,17 @@
-
[package]
name = "syntax-fuzz"
version = "0.0.1"
publish = false
edition = "2021"
-rust-version = "1.65"
+rust-version = "1.66.1"
[package.metadata]
cargo-fuzz = true
[dependencies]
syntax = { path = "..", version = "0.0.0" }
-text_edit = { path = "../../text_edit", version = "0.0.0" }
-libfuzzer-sys = { git = "https://github.com/rust-fuzz/libfuzzer-sys.git" }
+text-edit = { path = "../../text-edit", version = "0.0.0" }
+libfuzzer-sys = "0.4.5"
# Prevent this from interfering with workspaces
[workspace]
diff --git a/src/tools/rust-analyzer/crates/syntax/rust.ungram b/src/tools/rust-analyzer/crates/syntax/rust.ungram
index 2c67586a3..36ad5fddf 100644
--- a/src/tools/rust-analyzer/crates/syntax/rust.ungram
+++ b/src/tools/rust-analyzer/crates/syntax/rust.ungram
@@ -452,7 +452,7 @@ FieldExpr =
Attr* Expr '.' NameRef
ClosureExpr =
- Attr* ('for' GenericParamList)? 'static'? 'async'? 'move'? ParamList RetType?
+ Attr* ('for' GenericParamList)? 'const'? 'static'? 'async'? 'move'? ParamList RetType?
body:Expr
IfExpr =
diff --git a/src/tools/rust-analyzer/crates/syntax/src/ast.rs b/src/tools/rust-analyzer/crates/syntax/src/ast.rs
index 10c045758..385a4e0a3 100644
--- a/src/tools/rust-analyzer/crates/syntax/src/ast.rs
+++ b/src/tools/rust-analyzer/crates/syntax/src/ast.rs
@@ -13,6 +13,8 @@ pub mod prec;
use std::marker::PhantomData;
+use itertools::Either;
+
use crate::{
syntax_node::{SyntaxNode, SyntaxNodeChildren, SyntaxToken},
SyntaxKind,
@@ -98,6 +100,34 @@ impl<N: AstNode> Iterator for AstChildren<N> {
}
}
+impl<L, R> AstNode for Either<L, R>
+where
+ L: AstNode,
+ R: AstNode,
+{
+ fn can_cast(kind: SyntaxKind) -> bool
+ where
+ Self: Sized,
+ {
+ L::can_cast(kind) || R::can_cast(kind)
+ }
+
+ fn cast(syntax: SyntaxNode) -> Option<Self>
+ where
+ Self: Sized,
+ {
+ if L::can_cast(syntax.kind()) {
+ L::cast(syntax).map(Either::Left)
+ } else {
+ R::cast(syntax).map(Either::Right)
+ }
+ }
+
+ fn syntax(&self) -> &SyntaxNode {
+ self.as_ref().either(L::syntax, R::syntax)
+ }
+}
+
mod support {
use super::{AstChildren, AstNode, SyntaxKind, SyntaxNode, SyntaxToken};
diff --git a/src/tools/rust-analyzer/crates/syntax/src/ast/generated/nodes.rs b/src/tools/rust-analyzer/crates/syntax/src/ast/generated/nodes.rs
index a214a5e44..642a3bfc3 100644
--- a/src/tools/rust-analyzer/crates/syntax/src/ast/generated/nodes.rs
+++ b/src/tools/rust-analyzer/crates/syntax/src/ast/generated/nodes.rs
@@ -842,6 +842,7 @@ impl ast::HasAttrs for ClosureExpr {}
impl ClosureExpr {
pub fn for_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![for]) }
pub fn generic_param_list(&self) -> Option<GenericParamList> { support::child(&self.syntax) }
+ pub fn const_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![const]) }
pub fn static_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![static]) }
pub fn async_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![async]) }
pub fn move_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![move]) }
diff --git a/src/tools/rust-analyzer/crates/syntax/src/ast/make.rs b/src/tools/rust-analyzer/crates/syntax/src/ast/make.rs
index d5b329698..5aebe4cd9 100644
--- a/src/tools/rust-analyzer/crates/syntax/src/ast/make.rs
+++ b/src/tools/rust-analyzer/crates/syntax/src/ast/make.rs
@@ -12,7 +12,7 @@
use itertools::Itertools;
use stdx::{format_to, never};
-use crate::{ast, AstNode, SourceFile, SyntaxKind, SyntaxToken};
+use crate::{ast, utils::is_raw_identifier, AstNode, SourceFile, SyntaxKind, SyntaxToken};
/// While the parent module defines basic atomic "constructors", the `ext`
/// module defines shortcuts for common things.
@@ -111,8 +111,7 @@ pub fn name_ref(name_ref: &str) -> ast::NameRef {
ast_from_text(&format!("fn f() {{ {raw_escape}{name_ref}; }}"))
}
fn raw_ident_esc(ident: &str) -> &'static str {
- let is_keyword = parser::SyntaxKind::from_keyword(ident).is_some();
- if is_keyword && !matches!(ident, "self" | "crate" | "super" | "Self") {
+ if is_raw_identifier(ident) {
"r#"
} else {
""
@@ -520,6 +519,15 @@ pub fn literal_pat(lit: &str) -> ast::LiteralPat {
}
}
+pub fn slice_pat(pats: impl IntoIterator<Item = ast::Pat>) -> ast::SlicePat {
+ let pats_str = pats.into_iter().join(", ");
+ return from_text(&format!("[{pats_str}]"));
+
+ fn from_text(text: &str) -> ast::SlicePat {
+ ast_from_text(&format!("fn f() {{ match () {{{text} => ()}} }}"))
+ }
+}
+
/// Creates a tuple of patterns from an iterator of patterns.
///
/// Invariant: `pats` must be length > 0
@@ -814,6 +822,7 @@ pub fn fn_(
visibility: Option<ast::Visibility>,
fn_name: ast::Name,
type_params: Option<ast::GenericParamList>,
+ where_clause: Option<ast::WhereClause>,
params: ast::ParamList,
body: ast::BlockExpr,
ret_type: Option<ast::RetType>,
@@ -823,6 +832,10 @@ pub fn fn_(
Some(type_params) => format!("{type_params}"),
None => "".into(),
};
+ let where_clause = match where_clause {
+ Some(it) => format!("{it} "),
+ None => "".into(),
+ };
let ret_type = match ret_type {
Some(ret_type) => format!("{ret_type} "),
None => "".into(),
@@ -835,7 +848,7 @@ pub fn fn_(
let async_literal = if is_async { "async " } else { "" };
ast_from_text(&format!(
- "{visibility}{async_literal}fn {fn_name}{type_params}{params} {ret_type}{body}",
+ "{visibility}{async_literal}fn {fn_name}{type_params}{params} {ret_type}{where_clause}{body}",
))
}
diff --git a/src/tools/rust-analyzer/crates/syntax/src/lib.rs b/src/tools/rust-analyzer/crates/syntax/src/lib.rs
index 84c66b27e..6f57cbad6 100644
--- a/src/tools/rust-analyzer/crates/syntax/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/syntax/src/lib.rs
@@ -186,7 +186,7 @@ impl SourceFile {
/// ```
#[macro_export]
macro_rules! match_ast {
- (match $node:ident { $($tt:tt)* }) => { match_ast!(match ($node) { $($tt)* }) };
+ (match $node:ident { $($tt:tt)* }) => { $crate::match_ast!(match ($node) { $($tt)* }) };
(match ($node:expr) {
$( $( $path:ident )::+ ($it:pat) => $res:expr, )*
diff --git a/src/tools/rust-analyzer/crates/syntax/src/syntax_node.rs b/src/tools/rust-analyzer/crates/syntax/src/syntax_node.rs
index a08c01597..2e9e0bc22 100644
--- a/src/tools/rust-analyzer/crates/syntax/src/syntax_node.rs
+++ b/src/tools/rust-analyzer/crates/syntax/src/syntax_node.rs
@@ -48,6 +48,7 @@ impl SyntaxTreeBuilder {
pub fn finish(self) -> Parse<SyntaxNode> {
let (green, errors) = self.finish_raw();
// Disable block validation, see https://github.com/rust-lang/rust-analyzer/pull/10357
+ #[allow(clippy::overly_complex_bool_expr)]
if cfg!(debug_assertions) && false {
let node = SyntaxNode::new_root(green.clone());
crate::validation::validate_block_structure(&node);
diff --git a/src/tools/rust-analyzer/crates/syntax/src/utils.rs b/src/tools/rust-analyzer/crates/syntax/src/utils.rs
index f4c02518b..25f34ea9d 100644
--- a/src/tools/rust-analyzer/crates/syntax/src/utils.rs
+++ b/src/tools/rust-analyzer/crates/syntax/src/utils.rs
@@ -2,7 +2,7 @@
use itertools::Itertools;
-use crate::{ast, match_ast, AstNode};
+use crate::{ast, match_ast, AstNode, SyntaxKind};
pub fn path_to_string_stripping_turbo_fish(path: &ast::Path) -> String {
path.syntax()
@@ -23,6 +23,11 @@ pub fn path_to_string_stripping_turbo_fish(path: &ast::Path) -> String {
.join("::")
}
+pub fn is_raw_identifier(name: &str) -> bool {
+ let is_keyword = SyntaxKind::from_keyword(name).is_some();
+ is_keyword && !matches!(name, "self" | "crate" | "super" | "Self")
+}
+
#[cfg(test)]
mod tests {
use super::path_to_string_stripping_turbo_fish;
diff --git a/src/tools/rust-analyzer/crates/test-utils/Cargo.toml b/src/tools/rust-analyzer/crates/test-utils/Cargo.toml
index 1047373b1..92b1ef23e 100644
--- a/src/tools/rust-analyzer/crates/test-utils/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/test-utils/Cargo.toml
@@ -2,9 +2,11 @@
name = "test-utils"
version = "0.0.0"
description = "TBD"
-license = "MIT OR Apache-2.0"
-edition = "2021"
-rust-version = "1.65"
+
+authors.workspace = true
+edition.workspace = true
+license.workspace = true
+rust-version.workspace = true
[lib]
doctest = false
@@ -15,5 +17,5 @@ dissimilar = "1.0.4"
text-size = "1.1.0"
rustc-hash = "1.1.0"
-stdx = { path = "../stdx", version = "0.0.0" }
-profile = { path = "../profile", version = "0.0.0" }
+stdx.workspace = true
+profile.workspace = true
diff --git a/src/tools/rust-analyzer/crates/test-utils/src/minicore.rs b/src/tools/rust-analyzer/crates/test-utils/src/minicore.rs
index 3ca63fcab..3b033e1aa 100644
--- a/src/tools/rust-analyzer/crates/test-utils/src/minicore.rs
+++ b/src/tools/rust-analyzer/crates/test-utils/src/minicore.rs
@@ -28,6 +28,7 @@
//! generator: pin
//! hash:
//! index: sized
+//! infallible:
//! iterator: option
//! iterators: iterator, fn
//! non_zero:
@@ -40,7 +41,7 @@
//! sized:
//! slice:
//! sync: sized
-//! try:
+//! try: infallible
//! unsize: sized
pub mod marker {
@@ -105,6 +106,11 @@ pub mod marker {
impl<T: ?Sized> Copy for &T {}
}
// endregion:copy
+
+ // region:fn
+ #[lang = "tuple_trait"]
+ pub trait Tuple {}
+ // endregion:fn
}
// region:default
@@ -172,6 +178,9 @@ pub mod convert {
fn as_ref(&self) -> &T;
}
// endregion:as_ref
+ // region:infallible
+ pub enum Infallibe {}
+ // endregion:infallible
}
pub mod ops {
@@ -269,6 +278,24 @@ pub mod ops {
}
}
+ impl<T, I, const N: usize> Index<I> for [T; N]
+ where
+ I: SliceIndex<[T]>,
+ {
+ type Output = I::Output;
+ fn index(&self, index: I) -> &I::Output {
+ loop {}
+ }
+ }
+ impl<T, I, const N: usize> IndexMut<I> for [T; N]
+ where
+ I: SliceIndex<[T]>,
+ {
+ fn index_mut(&mut self, index: I) -> &mut I::Output {
+ loop {}
+ }
+ }
+
pub unsafe trait SliceIndex<T: ?Sized> {
type Output: ?Sized;
}
@@ -325,19 +352,26 @@ pub mod ops {
// region:fn
mod function {
+ use crate::marker::Tuple;
+
#[lang = "fn"]
#[fundamental]
- pub trait Fn<Args>: FnMut<Args> {}
+ pub trait Fn<Args: Tuple>: FnMut<Args> {
+ extern "rust-call" fn call(&self, args: Args) -> Self::Output;
+ }
#[lang = "fn_mut"]
#[fundamental]
- pub trait FnMut<Args>: FnOnce<Args> {}
+ pub trait FnMut<Args: Tuple>: FnOnce<Args> {
+ extern "rust-call" fn call_mut(&mut self, args: Args) -> Self::Output;
+ }
#[lang = "fn_once"]
#[fundamental]
- pub trait FnOnce<Args> {
+ pub trait FnOnce<Args: Tuple> {
#[lang = "fn_once_output"]
type Output;
+ extern "rust-call" fn call_once(self, args: Args) -> Self::Output;
}
}
pub use self::function::{Fn, FnMut, FnOnce};
@@ -352,7 +386,7 @@ pub mod ops {
#[lang = "from_residual"]
fn from_residual(residual: R) -> Self;
}
- #[lang = "try"]
+ #[lang = "Try"]
pub trait Try: FromResidual<Self::Residual> {
type Output;
type Residual;
diff --git a/src/tools/rust-analyzer/crates/text-edit/Cargo.toml b/src/tools/rust-analyzer/crates/text-edit/Cargo.toml
index 8df7e1af6..337cd2347 100644
--- a/src/tools/rust-analyzer/crates/text-edit/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/text-edit/Cargo.toml
@@ -2,9 +2,11 @@
name = "text-edit"
version = "0.0.0"
description = "TBD"
-license = "MIT OR Apache-2.0"
-edition = "2021"
-rust-version = "1.65"
+
+authors.workspace = true
+edition.workspace = true
+license.workspace = true
+rust-version.workspace = true
[lib]
doctest = false
diff --git a/src/tools/rust-analyzer/crates/toolchain/Cargo.toml b/src/tools/rust-analyzer/crates/toolchain/Cargo.toml
index a6a3ae742..a283f9a88 100644
--- a/src/tools/rust-analyzer/crates/toolchain/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/toolchain/Cargo.toml
@@ -2,9 +2,11 @@
name = "toolchain"
version = "0.0.0"
description = "TBD"
-license = "MIT OR Apache-2.0"
-edition = "2021"
-rust-version = "1.65"
+
+authors.workspace = true
+edition.workspace = true
+license.workspace = true
+rust-version.workspace = true
[lib]
doctest = false
diff --git a/src/tools/rust-analyzer/crates/tt/Cargo.toml b/src/tools/rust-analyzer/crates/tt/Cargo.toml
index 4f2103f3a..b84693831 100644
--- a/src/tools/rust-analyzer/crates/tt/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/tt/Cargo.toml
@@ -2,9 +2,11 @@
name = "tt"
version = "0.0.0"
description = "TBD"
-license = "MIT OR Apache-2.0"
-edition = "2021"
-rust-version = "1.65"
+
+authors.workspace = true
+edition.workspace = true
+license.workspace = true
+rust-version.workspace = true
[lib]
doctest = false
@@ -12,4 +14,4 @@ doctest = false
[dependencies]
smol_str = "0.1.23"
-stdx = { path = "../stdx", version = "0.0.0" }
+stdx.workspace = true
diff --git a/src/tools/rust-analyzer/crates/tt/src/buffer.rs b/src/tools/rust-analyzer/crates/tt/src/buffer.rs
index d27a7aa0d..0615a3763 100644
--- a/src/tools/rust-analyzer/crates/tt/src/buffer.rs
+++ b/src/tools/rust-analyzer/crates/tt/src/buffer.rs
@@ -7,33 +7,43 @@ use crate::{Leaf, Subtree, TokenTree};
struct EntryId(usize);
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
-struct EntryPtr(EntryId, usize);
+struct EntryPtr(
+ /// The index of the buffer containing the entry.
+ EntryId,
+ /// The index of the entry within the buffer.
+ usize,
+);
/// Internal type which is used instead of `TokenTree` to represent a token tree
/// within a `TokenBuffer`.
#[derive(Debug)]
-enum Entry<'t> {
+enum Entry<'t, Span> {
// Mimicking types from proc-macro.
- Subtree(Option<&'t TokenTree>, &'t Subtree, EntryId),
- Leaf(&'t TokenTree),
- // End entries contain a pointer to the entry from the containing
- // token tree, or None if this is the outermost level.
+ Subtree(Option<&'t TokenTree<Span>>, &'t Subtree<Span>, EntryId),
+ Leaf(&'t TokenTree<Span>),
+ /// End entries contain a pointer to the entry from the containing
+ /// token tree, or [`None`] if this is the outermost level.
End(Option<EntryPtr>),
}
/// A token tree buffer
/// The safe version of `syn` [`TokenBuffer`](https://github.com/dtolnay/syn/blob/6533607f91686545cb034d2838beea338d9d0742/src/buffer.rs#L41)
#[derive(Debug)]
-pub struct TokenBuffer<'t> {
- buffers: Vec<Box<[Entry<'t>]>>,
+pub struct TokenBuffer<'t, Span> {
+ buffers: Vec<Box<[Entry<'t, Span>]>>,
}
-trait TokenList<'a> {
- fn entries(&self) -> (Vec<(usize, (&'a Subtree, Option<&'a TokenTree>))>, Vec<Entry<'a>>);
+trait TokenList<'a, Span> {
+ fn entries(
+ &self,
+ ) -> (Vec<(usize, (&'a Subtree<Span>, Option<&'a TokenTree<Span>>))>, Vec<Entry<'a, Span>>);
}
-impl<'a> TokenList<'a> for &'a [TokenTree] {
- fn entries(&self) -> (Vec<(usize, (&'a Subtree, Option<&'a TokenTree>))>, Vec<Entry<'a>>) {
+impl<'a, Span> TokenList<'a, Span> for &'a [TokenTree<Span>] {
+ fn entries(
+ &self,
+ ) -> (Vec<(usize, (&'a Subtree<Span>, Option<&'a TokenTree<Span>>))>, Vec<Entry<'a, Span>>)
+ {
// Must contain everything in tokens and then the Entry::End
let start_capacity = self.len() + 1;
let mut entries = Vec::with_capacity(start_capacity);
@@ -53,8 +63,11 @@ impl<'a> TokenList<'a> for &'a [TokenTree] {
}
}
-impl<'a> TokenList<'a> for &'a Subtree {
- fn entries(&self) -> (Vec<(usize, (&'a Subtree, Option<&'a TokenTree>))>, Vec<Entry<'a>>) {
+impl<'a, Span> TokenList<'a, Span> for &'a Subtree<Span> {
+ fn entries(
+ &self,
+ ) -> (Vec<(usize, (&'a Subtree<Span>, Option<&'a TokenTree<Span>>))>, Vec<Entry<'a, Span>>)
+ {
// Must contain everything in tokens and then the Entry::End
let mut entries = vec![];
let mut children = vec![];
@@ -64,25 +77,25 @@ impl<'a> TokenList<'a> for &'a Subtree {
}
}
-impl<'t> TokenBuffer<'t> {
- pub fn from_tokens(tokens: &'t [TokenTree]) -> TokenBuffer<'t> {
+impl<'t, Span> TokenBuffer<'t, Span> {
+ pub fn from_tokens(tokens: &'t [TokenTree<Span>]) -> TokenBuffer<'t, Span> {
Self::new(tokens)
}
- pub fn from_subtree(subtree: &'t Subtree) -> TokenBuffer<'t> {
+ pub fn from_subtree(subtree: &'t Subtree<Span>) -> TokenBuffer<'t, Span> {
Self::new(subtree)
}
- fn new<T: TokenList<'t>>(tokens: T) -> TokenBuffer<'t> {
+ fn new<T: TokenList<'t, Span>>(tokens: T) -> TokenBuffer<'t, Span> {
let mut buffers = vec![];
let idx = TokenBuffer::new_inner(tokens, &mut buffers, None);
assert_eq!(idx, 0);
TokenBuffer { buffers }
}
- fn new_inner<T: TokenList<'t>>(
+ fn new_inner<T: TokenList<'t, Span>>(
tokens: T,
- buffers: &mut Vec<Box<[Entry<'t>]>>,
+ buffers: &mut Vec<Box<[Entry<'t, Span>]>>,
next: Option<EntryPtr>,
) -> usize {
let (children, mut entries) = tokens.entries();
@@ -105,25 +118,25 @@ impl<'t> TokenBuffer<'t> {
/// Creates a cursor referencing the first token in the buffer and able to
/// traverse until the end of the buffer.
- pub fn begin(&self) -> Cursor<'_> {
+ pub fn begin(&self) -> Cursor<'_, Span> {
Cursor::create(self, EntryPtr(EntryId(0), 0))
}
- fn entry(&self, ptr: &EntryPtr) -> Option<&Entry<'_>> {
+ fn entry(&self, ptr: &EntryPtr) -> Option<&Entry<'_, Span>> {
let id = ptr.0;
self.buffers[id.0].get(ptr.1)
}
}
#[derive(Debug)]
-pub enum TokenTreeRef<'a> {
- Subtree(&'a Subtree, Option<&'a TokenTree>),
- Leaf(&'a Leaf, &'a TokenTree),
+pub enum TokenTreeRef<'a, Span> {
+ Subtree(&'a Subtree<Span>, Option<&'a TokenTree<Span>>),
+ Leaf(&'a Leaf<Span>, &'a TokenTree<Span>),
}
-impl<'a> TokenTreeRef<'a> {
- pub fn cloned(&self) -> TokenTree {
- match &self {
+impl<'a, Span: Clone> TokenTreeRef<'a, Span> {
+ pub fn cloned(&self) -> TokenTree<Span> {
+ match self {
TokenTreeRef::Subtree(subtree, tt) => match tt {
Some(it) => (*it).clone(),
None => (*subtree).clone().into(),
@@ -135,20 +148,20 @@ impl<'a> TokenTreeRef<'a> {
/// A safe version of `Cursor` from `syn` crate <https://github.com/dtolnay/syn/blob/6533607f91686545cb034d2838beea338d9d0742/src/buffer.rs#L125>
#[derive(Copy, Clone, Debug)]
-pub struct Cursor<'a> {
- buffer: &'a TokenBuffer<'a>,
+pub struct Cursor<'a, Span> {
+ buffer: &'a TokenBuffer<'a, Span>,
ptr: EntryPtr,
}
-impl<'a> PartialEq for Cursor<'a> {
- fn eq(&self, other: &Cursor<'_>) -> bool {
+impl<'a, Span> PartialEq for Cursor<'a, Span> {
+ fn eq(&self, other: &Cursor<'_, Span>) -> bool {
self.ptr == other.ptr && std::ptr::eq(self.buffer, other.buffer)
}
}
-impl<'a> Eq for Cursor<'a> {}
+impl<'a, Span> Eq for Cursor<'a, Span> {}
-impl<'a> Cursor<'a> {
+impl<'a, Span> Cursor<'a, Span> {
/// Check whether it is eof
pub fn eof(self) -> bool {
matches!(self.buffer.entry(&self.ptr), None | Some(Entry::End(None)))
@@ -156,7 +169,7 @@ impl<'a> Cursor<'a> {
/// If the cursor is pointing at the end of a subtree, returns
/// the parent subtree
- pub fn end(self) -> Option<&'a Subtree> {
+ pub fn end(self) -> Option<&'a Subtree<Span>> {
match self.entry() {
Some(Entry::End(Some(ptr))) => {
let idx = ptr.1;
@@ -171,13 +184,13 @@ impl<'a> Cursor<'a> {
}
}
- fn entry(self) -> Option<&'a Entry<'a>> {
+ fn entry(&self) -> Option<&'a Entry<'a, Span>> {
self.buffer.entry(&self.ptr)
}
/// If the cursor is pointing at a `Subtree`, returns
/// a cursor into that subtree
- pub fn subtree(self) -> Option<Cursor<'a>> {
+ pub fn subtree(self) -> Option<Cursor<'a, Span>> {
match self.entry() {
Some(Entry::Subtree(_, _, entry_id)) => {
Some(Cursor::create(self.buffer, EntryPtr(*entry_id, 0)))
@@ -187,7 +200,7 @@ impl<'a> Cursor<'a> {
}
/// If the cursor is pointing at a `TokenTree`, returns it
- pub fn token_tree(self) -> Option<TokenTreeRef<'a>> {
+ pub fn token_tree(self) -> Option<TokenTreeRef<'a, Span>> {
match self.entry() {
Some(Entry::Leaf(tt)) => match tt {
TokenTree::Leaf(leaf) => Some(TokenTreeRef::Leaf(leaf, tt)),
@@ -198,12 +211,12 @@ impl<'a> Cursor<'a> {
}
}
- fn create(buffer: &'a TokenBuffer<'_>, ptr: EntryPtr) -> Cursor<'a> {
+ fn create(buffer: &'a TokenBuffer<'_, Span>, ptr: EntryPtr) -> Cursor<'a, Span> {
Cursor { buffer, ptr }
}
/// Bump the cursor
- pub fn bump(self) -> Cursor<'a> {
+ pub fn bump(self) -> Cursor<'a, Span> {
if let Some(Entry::End(exit)) = self.buffer.entry(&self.ptr) {
match exit {
Some(exit) => Cursor::create(self.buffer, *exit),
@@ -216,10 +229,16 @@ impl<'a> Cursor<'a> {
/// Bump the cursor, if it is a subtree, returns
/// a cursor into that subtree
- pub fn bump_subtree(self) -> Cursor<'a> {
+ pub fn bump_subtree(self) -> Cursor<'a, Span> {
match self.entry() {
- Some(Entry::Subtree(_, _, _)) => self.subtree().unwrap(),
- _ => self.bump(),
+ Some(&Entry::Subtree(_, _, entry_id)) => {
+ Cursor::create(self.buffer, EntryPtr(entry_id, 0))
+ }
+ Some(Entry::End(exit)) => match exit {
+ Some(exit) => Cursor::create(self.buffer, *exit),
+ None => self,
+ },
+ _ => Cursor::create(self.buffer, EntryPtr(self.ptr.0, self.ptr.1 + 1)),
}
}
diff --git a/src/tools/rust-analyzer/crates/tt/src/lib.rs b/src/tools/rust-analyzer/crates/tt/src/lib.rs
index 353b09fd8..b7dbc82e1 100644
--- a/src/tools/rust-analyzer/crates/tt/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/tt/src/lib.rs
@@ -16,45 +16,106 @@ pub use smol_str::SmolStr;
/// which source tokens. We do it by assigning an distinct identity to each
/// source token and making sure that identities are preserved during macro
/// expansion.
-#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
+#[derive(Clone, Copy, PartialEq, Eq, Hash)]
pub struct TokenId(pub u32);
+impl fmt::Debug for TokenId {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ self.0.fmt(f)
+ }
+}
+
impl TokenId {
+ pub const UNSPECIFIED: TokenId = TokenId(!0);
pub const fn unspecified() -> TokenId {
- TokenId(!0)
+ Self::UNSPECIFIED
}
}
-#[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub enum TokenTree {
- Leaf(Leaf),
- Subtree(Subtree),
-}
-impl_from!(Leaf, Subtree for TokenTree);
+pub mod token_id {
+ pub use crate::{DelimiterKind, Spacing, TokenId};
+ pub type Span = crate::TokenId;
+ pub type Subtree = crate::Subtree<Span>;
+ pub type Punct = crate::Punct<Span>;
+ pub type Delimiter = crate::Delimiter<Span>;
+ pub type Leaf = crate::Leaf<Span>;
+ pub type Ident = crate::Ident<Span>;
+ pub type Literal = crate::Literal<Span>;
+ pub type TokenTree = crate::TokenTree<Span>;
+ pub mod buffer {
+ pub type TokenBuffer<'a> = crate::buffer::TokenBuffer<'a, super::Span>;
+ pub type Cursor<'a> = crate::buffer::Cursor<'a, super::Span>;
+ pub type TokenTreeRef<'a> = crate::buffer::TokenTreeRef<'a, super::Span>;
+ }
-impl TokenTree {
- pub fn empty() -> Self {
- TokenTree::Subtree(Subtree::default())
+ impl Delimiter {
+ pub const UNSPECIFIED: Self = Self {
+ open: TokenId::UNSPECIFIED,
+ close: TokenId::UNSPECIFIED,
+ kind: DelimiterKind::Invisible,
+ };
+ pub const fn unspecified() -> Self {
+ Self::UNSPECIFIED
+ }
+ }
+ impl Subtree {
+ pub const fn empty() -> Self {
+ Subtree { delimiter: Delimiter::unspecified(), token_trees: vec![] }
+ }
+ }
+ impl TokenTree {
+ pub const fn empty() -> Self {
+ Self::Subtree(Subtree { delimiter: Delimiter::unspecified(), token_trees: vec![] })
+ }
}
}
+#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
+pub struct SyntaxContext(pub u32);
+
+// #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
+// pub struct Span {
+// pub id: TokenId,
+// pub ctx: SyntaxContext,
+// }
+// pub type Span = (TokenId, SyntaxContext);
+
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub enum Leaf {
- Literal(Literal),
- Punct(Punct),
- Ident(Ident),
+pub enum TokenTree<Span> {
+ Leaf(Leaf<Span>),
+ Subtree(Subtree<Span>),
}
-impl_from!(Literal, Punct, Ident for Leaf);
+impl_from!(Leaf<Span>, Subtree<Span> for TokenTree);
-#[derive(Clone, PartialEq, Eq, Hash, Default)]
-pub struct Subtree {
- pub delimiter: Option<Delimiter>,
- pub token_trees: Vec<TokenTree>,
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub enum Leaf<Span> {
+ Literal(Literal<Span>),
+ Punct(Punct<Span>),
+ Ident(Ident<Span>),
+}
+
+impl<Span> Leaf<Span> {
+ pub fn span(&self) -> &Span {
+ match self {
+ Leaf::Literal(it) => &it.span,
+ Leaf::Punct(it) => &it.span,
+ Leaf::Ident(it) => &it.span,
+ }
+ }
+}
+impl_from!(Literal<Span>, Punct<Span>, Ident<Span> for Leaf);
+
+#[derive(Clone, PartialEq, Eq, Hash)]
+pub struct Subtree<Span> {
+ // FIXME, this should not be Option
+ pub delimiter: Delimiter<Span>,
+ pub token_trees: Vec<TokenTree<Span>>,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
-pub struct Delimiter {
- pub id: TokenId,
+pub struct Delimiter<Span> {
+ pub open: Span,
+ pub close: Span,
pub kind: DelimiterKind,
}
@@ -63,19 +124,20 @@ pub enum DelimiterKind {
Parenthesis,
Brace,
Bracket,
+ Invisible,
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct Literal {
+pub struct Literal<Span> {
pub text: SmolStr,
- pub id: TokenId,
+ pub span: Span,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
-pub struct Punct {
+pub struct Punct<Span> {
pub char: char,
pub spacing: Spacing,
- pub id: TokenId,
+ pub span: Span,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
@@ -85,39 +147,25 @@ pub enum Spacing {
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct Ident {
- /// Identifier or keyword. Unlike rustc, we keep "r#" prefix when it represents a raw identifier.
+/// Identifier or keyword. Unlike rustc, we keep "r#" prefix when it represents a raw identifier.
+pub struct Ident<Span> {
pub text: SmolStr,
- pub id: TokenId,
+ pub span: Span,
}
-impl Ident {
- /// Constructor intended to be used only by proc macro server. `text` should not contain raw
- /// identifier prefix.
- pub fn new_with_is_raw(text: SmolStr, id: TokenId, is_raw: bool) -> Self {
- let text = if is_raw { SmolStr::from_iter(["r#", &text]) } else { text };
- Ident { text, id }
- }
-}
-
-impl Leaf {
- pub fn id(&self) -> TokenId {
- match self {
- Leaf::Literal(l) => l.id,
- Leaf::Punct(p) => p.id,
- Leaf::Ident(i) => i.id,
- }
- }
-}
-
-fn print_debug_subtree(f: &mut fmt::Formatter<'_>, subtree: &Subtree, level: usize) -> fmt::Result {
+fn print_debug_subtree<Span: fmt::Debug>(
+ f: &mut fmt::Formatter<'_>,
+ subtree: &Subtree<Span>,
+ level: usize,
+) -> fmt::Result {
let align = " ".repeat(level);
- let aux = match subtree.delimiter.map(|it| (it.kind, it.id.0)) {
- None => "$".to_string(),
- Some((DelimiterKind::Parenthesis, id)) => format!("() {id}"),
- Some((DelimiterKind::Brace, id)) => format!("{{}} {id}"),
- Some((DelimiterKind::Bracket, id)) => format!("[] {id}"),
+ let Delimiter { kind, open, close } = &subtree.delimiter;
+ let aux = match kind {
+ DelimiterKind::Invisible => format!("$$ {:?} {:?}", open, close),
+ DelimiterKind::Parenthesis => format!("() {:?} {:?}", open, close),
+ DelimiterKind::Brace => format!("{{}} {:?} {:?}", open, close),
+ DelimiterKind::Bracket => format!("[] {:?} {:?}", open, close),
};
if subtree.token_trees.is_empty() {
@@ -135,21 +183,25 @@ fn print_debug_subtree(f: &mut fmt::Formatter<'_>, subtree: &Subtree, level: usi
Ok(())
}
-fn print_debug_token(f: &mut fmt::Formatter<'_>, tkn: &TokenTree, level: usize) -> fmt::Result {
+fn print_debug_token<Span: fmt::Debug>(
+ f: &mut fmt::Formatter<'_>,
+ tkn: &TokenTree<Span>,
+ level: usize,
+) -> fmt::Result {
let align = " ".repeat(level);
match tkn {
TokenTree::Leaf(leaf) => match leaf {
- Leaf::Literal(lit) => write!(f, "{align}LITERAL {} {}", lit.text, lit.id.0)?,
+ Leaf::Literal(lit) => write!(f, "{}LITERAL {} {:?}", align, lit.text, lit.span)?,
Leaf::Punct(punct) => write!(
f,
- "{}PUNCH {} [{}] {}",
+ "{}PUNCH {} [{}] {:?}",
align,
punct.char,
if punct.spacing == Spacing::Alone { "alone" } else { "joint" },
- punct.id.0
+ punct.span
)?,
- Leaf::Ident(ident) => write!(f, "{align}IDENT {} {}", ident.text, ident.id.0)?,
+ Leaf::Ident(ident) => write!(f, "{}IDENT {} {:?}", align, ident.text, ident.span)?,
},
TokenTree::Subtree(subtree) => {
print_debug_subtree(f, subtree, level)?;
@@ -159,13 +211,13 @@ fn print_debug_token(f: &mut fmt::Formatter<'_>, tkn: &TokenTree, level: usize)
Ok(())
}
-impl fmt::Debug for Subtree {
+impl<Span: fmt::Debug> fmt::Debug for Subtree<Span> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
print_debug_subtree(f, self, 0)
}
}
-impl fmt::Display for TokenTree {
+impl<Span> fmt::Display for TokenTree<Span> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
TokenTree::Leaf(it) => fmt::Display::fmt(it, f),
@@ -174,13 +226,13 @@ impl fmt::Display for TokenTree {
}
}
-impl fmt::Display for Subtree {
+impl<Span> fmt::Display for Subtree<Span> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- let (l, r) = match self.delimiter_kind() {
- Some(DelimiterKind::Parenthesis) => ("(", ")"),
- Some(DelimiterKind::Brace) => ("{", "}"),
- Some(DelimiterKind::Bracket) => ("[", "]"),
- None => ("", ""),
+ let (l, r) = match self.delimiter.kind {
+ DelimiterKind::Parenthesis => ("(", ")"),
+ DelimiterKind::Brace => ("{", "}"),
+ DelimiterKind::Bracket => ("[", "]"),
+ DelimiterKind::Invisible => ("", ""),
};
f.write_str(l)?;
let mut needs_space = false;
@@ -202,7 +254,7 @@ impl fmt::Display for Subtree {
}
}
-impl fmt::Display for Leaf {
+impl<Span> fmt::Display for Leaf<Span> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Leaf::Ident(it) => fmt::Display::fmt(it, f),
@@ -212,25 +264,25 @@ impl fmt::Display for Leaf {
}
}
-impl fmt::Display for Ident {
+impl<Span> fmt::Display for Ident<Span> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Display::fmt(&self.text, f)
}
}
-impl fmt::Display for Literal {
+impl<Span> fmt::Display for Literal<Span> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Display::fmt(&self.text, f)
}
}
-impl fmt::Display for Punct {
+impl<Span> fmt::Display for Punct<Span> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Display::fmt(&self.char, f)
}
}
-impl Subtree {
+impl<Span> Subtree<Span> {
/// Count the number of tokens recursively
pub fn count(&self) -> usize {
let children_count = self
@@ -244,20 +296,16 @@ impl Subtree {
self.token_trees.len() + children_count
}
-
- pub fn delimiter_kind(&self) -> Option<DelimiterKind> {
- self.delimiter.map(|it| it.kind)
- }
}
-impl Subtree {
+impl<Span> Subtree<Span> {
/// A simple line string used for debugging
pub fn as_debug_string(&self) -> String {
- let delim = match self.delimiter_kind() {
- Some(DelimiterKind::Brace) => ("{", "}"),
- Some(DelimiterKind::Bracket) => ("[", "]"),
- Some(DelimiterKind::Parenthesis) => ("(", ")"),
- None => (" ", " "),
+ let delim = match self.delimiter.kind {
+ DelimiterKind::Brace => ("{", "}"),
+ DelimiterKind::Bracket => ("[", "]"),
+ DelimiterKind::Parenthesis => ("(", ")"),
+ DelimiterKind::Invisible => ("$", "$"),
};
let mut res = String::new();
@@ -275,7 +323,7 @@ impl Subtree {
(Leaf::Ident(_), Some(&TokenTree::Leaf(Leaf::Ident(_)))) => {
" ".to_string() + &s
}
- (Leaf::Punct(_), Some(&TokenTree::Leaf(Leaf::Punct(punct)))) => {
+ (Leaf::Punct(_), Some(TokenTree::Leaf(Leaf::Punct(punct)))) => {
if punct.spacing == Spacing::Alone {
" ".to_string() + &s
} else {
@@ -298,19 +346,19 @@ impl Subtree {
pub mod buffer;
-pub fn pretty(tkns: &[TokenTree]) -> String {
- fn tokentree_to_text(tkn: &TokenTree) -> String {
+pub fn pretty<Span>(tkns: &[TokenTree<Span>]) -> String {
+ fn tokentree_to_text<Span>(tkn: &TokenTree<Span>) -> String {
match tkn {
TokenTree::Leaf(Leaf::Ident(ident)) => ident.text.clone().into(),
TokenTree::Leaf(Leaf::Literal(literal)) => literal.text.clone().into(),
TokenTree::Leaf(Leaf::Punct(punct)) => format!("{}", punct.char),
TokenTree::Subtree(subtree) => {
let content = pretty(&subtree.token_trees);
- let (open, close) = match subtree.delimiter.map(|it| it.kind) {
- None => ("", ""),
- Some(DelimiterKind::Brace) => ("{", "}"),
- Some(DelimiterKind::Parenthesis) => ("(", ")"),
- Some(DelimiterKind::Bracket) => ("[", "]"),
+ let (open, close) = match subtree.delimiter.kind {
+ DelimiterKind::Brace => ("{", "}"),
+ DelimiterKind::Bracket => ("[", "]"),
+ DelimiterKind::Parenthesis => ("(", ")"),
+ DelimiterKind::Invisible => ("", ""),
};
format!("{open}{content}{close}")
}
diff --git a/src/tools/rust-analyzer/crates/vfs-notify/Cargo.toml b/src/tools/rust-analyzer/crates/vfs-notify/Cargo.toml
index 061f3c157..e06b98d81 100644
--- a/src/tools/rust-analyzer/crates/vfs-notify/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/vfs-notify/Cargo.toml
@@ -2,9 +2,11 @@
name = "vfs-notify"
version = "0.0.0"
description = "TBD"
-license = "MIT OR Apache-2.0"
-edition = "2021"
-rust-version = "1.65"
+
+authors.workspace = true
+edition.workspace = true
+license.workspace = true
+rust-version.workspace = true
[lib]
doctest = false
@@ -16,5 +18,5 @@ walkdir = "2.3.2"
crossbeam-channel = "0.5.5"
notify = "5.0"
-vfs = { path = "../vfs", version = "0.0.0" }
-paths = { path = "../paths", version = "0.0.0" }
+vfs.workspace = true
+paths.workspace = true
diff --git a/src/tools/rust-analyzer/crates/vfs/Cargo.toml b/src/tools/rust-analyzer/crates/vfs/Cargo.toml
index e55bf6f29..802a30006 100644
--- a/src/tools/rust-analyzer/crates/vfs/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/vfs/Cargo.toml
@@ -2,9 +2,11 @@
name = "vfs"
version = "0.0.0"
description = "TBD"
-license = "MIT OR Apache-2.0"
-edition = "2021"
-rust-version = "1.65"
+
+authors.workspace = true
+edition.workspace = true
+license.workspace = true
+rust-version.workspace = true
[lib]
doctest = false
@@ -14,5 +16,5 @@ rustc-hash = "1.1.0"
fst = "0.4.7"
indexmap = "1.9.1"
-paths = { path = "../paths", version = "0.0.0" }
-stdx = { path = "../stdx", version = "0.0.0" }
+paths.workspace = true
+stdx.workspace = true
diff --git a/src/tools/rust-analyzer/crates/vfs/src/lib.rs b/src/tools/rust-analyzer/crates/vfs/src/lib.rs
index c61f30387..14972d290 100644
--- a/src/tools/rust-analyzer/crates/vfs/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/vfs/src/lib.rs
@@ -75,6 +75,7 @@ pub struct Vfs {
}
/// Changed file in the [`Vfs`].
+#[derive(Debug)]
pub struct ChangedFile {
/// Id of the changed file
pub file_id: FileId,
@@ -161,9 +162,9 @@ impl Vfs {
let file_id = self.alloc_file_id(path);
let change_kind = match (&self.get(file_id), &contents) {
(None, None) => return false,
+ (Some(old), Some(new)) if old == new => return false,
(None, Some(_)) => ChangeKind::Create,
(Some(_), None) => ChangeKind::Delete,
- (Some(old), Some(new)) if old == new => return false,
(Some(_), Some(_)) => ChangeKind::Modify,
};
diff --git a/src/tools/rust-analyzer/crates/vfs/src/vfs_path.rs b/src/tools/rust-analyzer/crates/vfs/src/vfs_path.rs
index b23c9f196..38501a8ba 100644
--- a/src/tools/rust-analyzer/crates/vfs/src/vfs_path.rs
+++ b/src/tools/rust-analyzer/crates/vfs/src/vfs_path.rs
@@ -1,7 +1,7 @@
//! Abstract-ish representation of paths for VFS.
use std::fmt;
-use paths::{AbsPath, AbsPathBuf};
+use paths::{AbsPath, AbsPathBuf, RelPath};
/// Path in [`Vfs`].
///
@@ -84,6 +84,14 @@ impl VfsPath {
}
}
+ pub fn strip_prefix(&self, other: &VfsPath) -> Option<&RelPath> {
+ match (&self.0, &other.0) {
+ (VfsPathRepr::PathBuf(lhs), VfsPathRepr::PathBuf(rhs)) => lhs.strip_prefix(rhs),
+ (VfsPathRepr::VirtualPath(lhs), VfsPathRepr::VirtualPath(rhs)) => lhs.strip_prefix(rhs),
+ (VfsPathRepr::PathBuf(_) | VfsPathRepr::VirtualPath(_), _) => None,
+ }
+ }
+
/// Returns the `VfsPath` without its final component, if there is one.
///
/// Returns [`None`] if the path is a root or prefix.
@@ -320,6 +328,13 @@ impl VirtualPath {
self.0.starts_with(&other.0)
}
+ fn strip_prefix(&self, base: &VirtualPath) -> Option<&RelPath> {
+ <_ as AsRef<std::path::Path>>::as_ref(&self.0)
+ .strip_prefix(&base.0)
+ .ok()
+ .map(RelPath::new_unchecked)
+ }
+
/// Remove the last component of `self`.
///
/// This will find the last `'/'` in `self`, and remove everything after it,
diff --git a/src/tools/rust-analyzer/docs/dev/architecture.md b/src/tools/rust-analyzer/docs/dev/architecture.md
index a07cf036e..895de5798 100644
--- a/src/tools/rust-analyzer/docs/dev/architecture.md
+++ b/src/tools/rust-analyzer/docs/dev/architecture.md
@@ -119,7 +119,7 @@ See [#93](https://github.com/rust-lang/rust-analyzer/pull/93) for an example PR
**Architecture Invariant:** `syntax` crate is completely independent from the rest of rust-analyzer. It knows nothing about salsa or LSP.
This is important because it is possible to make useful tooling using only the syntax tree.
Without semantic information, you don't need to be able to _build_ code, which makes the tooling more robust.
-See also https://web.stanford.edu/~mlfbrown/paper.pdf.
+See also https://mlfbrown.com/paper.pdf.
You can view the `syntax` crate as an entry point to rust-analyzer.
`syntax` crate is an **API Boundary**.
diff --git a/src/tools/rust-analyzer/docs/dev/lsp-extensions.md b/src/tools/rust-analyzer/docs/dev/lsp-extensions.md
index a4780af1a..c3623a5cc 100644
--- a/src/tools/rust-analyzer/docs/dev/lsp-extensions.md
+++ b/src/tools/rust-analyzer/docs/dev/lsp-extensions.md
@@ -1,5 +1,5 @@
<!---
-lsp_ext.rs hash: 45bd7985265725c5
+lsp_ext.rs hash: d87477896dfe41d4
If you need to change the above hash to make the test pass, please check if you
need to adjust this doc as well and ping this issue:
diff --git a/src/tools/rust-analyzer/docs/user/generated_config.adoc b/src/tools/rust-analyzer/docs/user/generated_config.adoc
index b33a2e795..50e3670a7 100644
--- a/src/tools/rust-analyzer/docs/user/generated_config.adoc
+++ b/src/tools/rust-analyzer/docs/user/generated_config.adoc
@@ -99,6 +99,14 @@ Unsetting this disables sysroot loading.
This option does not take effect until rust-analyzer is restarted.
--
+[[rust-analyzer.cargo.sysrootSrc]]rust-analyzer.cargo.sysrootSrc (default: `null`)::
++
+--
+Relative path to the sysroot library sources. If left unset, this will default to
+`{cargo.sysroot}/lib/rustlib/src/rust/library`.
+
+This option does not take effect until rust-analyzer is restarted.
+--
[[rust-analyzer.cargo.target]]rust-analyzer.cargo.target (default: `null`)::
+
--
@@ -219,6 +227,11 @@ with `self` prefixed to them when inside a method.
--
Whether to add parenthesis and argument snippets when completing function.
--
+[[rust-analyzer.completion.limit]]rust-analyzer.completion.limit (default: `null`)::
++
+--
+Maximum number of completions to return. If `None`, the limit is infinite.
+--
[[rust-analyzer.completion.postfix.enable]]rust-analyzer.completion.postfix.enable (default: `true`)::
+
--
@@ -486,11 +499,6 @@ Whether to show inlay type hints for elided lifetimes in function signatures.
--
Whether to prefer using parameter names as the name for elided lifetime hints if possible.
--
-[[rust-analyzer.inlayHints.locationLinks]]rust-analyzer.inlayHints.locationLinks (default: `true`)::
-+
---
-Whether to use location links for parts of type mentioned in inlay hints.
---
[[rust-analyzer.inlayHints.maxLength]]rust-analyzer.inlayHints.maxLength (default: `25`)::
+
--
diff --git a/src/tools/rust-analyzer/docs/user/manual.adoc b/src/tools/rust-analyzer/docs/user/manual.adoc
index 1a4c70575..cb96feeb5 100644
--- a/src/tools/rust-analyzer/docs/user/manual.adoc
+++ b/src/tools/rust-analyzer/docs/user/manual.adoc
@@ -232,18 +232,66 @@ The `rust-analyzer` binary can be installed via https://brew.sh/[Homebrew].
$ brew install rust-analyzer
----
-=== Emacs
+=== VS Code or VSCodium in Flatpak
+
+Setting up `rust-analyzer` with a Flatpak version of Code is not trivial because of the Flatpak sandbox.
+While the sandbox can be disabled for some directories, `/usr/bin` will always be mounted under `/run/host/usr/bin`.
+This prevents access to the system's C compiler, a system-wide installation of Rust, or any other libraries you might want to link to.
+Some compilers and libraries can be acquired as Flatpak SDKs, such as `org.freedesktop.Sdk.Extension.rust-stable` or `org.freedesktop.Sdk.Extension.llvm15`.
+
+If you use a Flatpak SDK for Rust, there should be no extra steps necessary.
-Note this excellent https://robert.kra.hn/posts/2021-02-07_rust-with-emacs/[guide] from https://github.com/rksm[@rksm].
+If you want to use Flatpak in combination with `rustup`, the following steps might help:
+
+ - both Rust and `rustup` have to be installed using https://rustup.rs. Distro packages _will not_ work.
+ - you need to launch Code, open a terminal and run `echo $PATH`
+ - using https://flathub.org/apps/details/com.github.tchx84.Flatseal[Flatseal], you must add an environment variable called `PATH`.
+ Set its value to the output from above, appending `:~/.cargo/bin`, where `~` is the path to your home directory.
+ You must replace `~`, as it won't be expanded otherwise.
+ - while Flatseal is open, you must enable access to "All user files"
+
+A C compiler should already be available via `org.freedesktop.Sdk`.
+Any other tools or libraries you will need to acquire from Flatpak.
+
+=== Emacs
Prerequisites: You have installed the <<rust-analyzer-language-server-binary,`rust-analyzer` binary>>.
-Emacs support is maintained as part of the https://github.com/emacs-lsp/lsp-mode[Emacs-LSP] package in https://github.com/emacs-lsp/lsp-mode/blob/master/lsp-rust.el[lsp-rust.el].
+To use `rust-analyzer`, you need to install and enable one of the two popular two popular LSP client implementations for Emacs, https://github.com/joaotavora/eglot[Eglot] or https://github.com/emacs-lsp/lsp-mode[LSP Mode]. Both enable `rust-analyzer` by default in rust buffers if it is available.
+
+==== Eglot
+
+Eglot is the more minimalistic and lightweight LSP client for Emacs, integrates well with existing Emacs functionality and will be built into Emacs starting from release 29.
+
+After installing Eglot, e.g. via `M-x package-install` (not needed from Emacs 29), you can enable it via the `M-x eglot` command or load it automatically in `rust-mode` via
+
+[source,emacs-lisp]
+----
+(add-hook 'rust-mode-hook 'eglot-ensure)
+----
+
+For more detailed instructions and options see the https://joaotavora.github.io/eglot[Eglot manual] (also available from Emacs via `M-x info`) and the
+https://github.com/joaotavora/eglot/blob/master/README.md[Eglot readme].
+
+Eglot does not support the rust-analyzer extensions to the language-server protocol and does not aim to do so in the future. The https://github.com/nemethf/eglot-x#rust-analyzer-extensions[eglot-x] package adds experimental support for those LSP extensions.
+
+==== LSP Mode
+
+LSP-mode is the original LSP-client for emacs. Compared to Eglot it has a larger codebase and supports more features, like LSP protocol extensions.
+With extension packages like https://github.com/emacs-lsp/lsp-mode[LSP UI] it offers a lot of visual eyecandy.
+Further it integrates well with https://github.com/emacs-lsp/dap-mode[DAP mode] for support of the Debug Adapter Protocol.
+
+You can install LSP-mode via `M-x package-install` and then run it via the `M-x lsp` command or load it automatically in rust buffers with
+
+[source,emacs-lisp]
+----
+(add-hook 'rust-mode-hook 'lsp-deferred)
+----
+
+For more information on how to set up LSP mode and its extension package see the instructions in the https://emacs-lsp.github.io/lsp-mode/page/installation[LSP mode manual].
+Also see the https://emacs-lsp.github.io/lsp-mode/page/lsp-rust-analyzer/[rust-analyzer section] for `rust-analyzer` specific options and commands, which you can optionally bind to keys.
-1. Install the most recent version of `emacs-lsp` package by following the https://github.com/emacs-lsp/lsp-mode[Emacs-LSP instructions].
-2. Set `lsp-rust-server` to `'rust-analyzer`.
-3. Run `lsp` in a Rust buffer.
-4. (Optionally) bind commands like `lsp-rust-analyzer-join-lines`, `lsp-extend-selection` and `lsp-rust-analyzer-expand-macro` to keys.
+Note the excellent https://robert.kra.hn/posts/2021-02-07_rust-with-emacs/[guide] from https://github.com/rksm[@rksm] on how to set-up Emacs for Rust development with LSP mode and several other packages.
=== Vim/NeoVim
@@ -487,6 +535,47 @@ https://docs.helix-editor.com/[Helix] supports LSP by default.
However, it won't install `rust-analyzer` automatically.
You can follow instructions for installing <<rust-analyzer-language-server-binary,`rust-analyzer` binary>>.
+=== Visual Studio 2022
+
+There are multiple rust-analyzer extensions for Visual Studio 2022 on Windows:
+
+==== rust-analyzer.vs
+
+(License: Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International)
+
+https://marketplace.visualstudio.com/items?itemName=kitamstudios.RustAnalyzer[Visual Studio Marketplace]
+
+https://github.com/kitamstudios/rust-analyzer/[GitHub]
+
+Support for Rust development in the Visual Studio IDE is enabled by the link:https://marketplace.visualstudio.com/items?itemName=kitamstudios.RustAnalyzer[rust-analyzer] package. Either click on the download link or install from IDE's extension manager.
+For now link:https://visualstudio.microsoft.com/downloads/[Visual Studio 2022] is required. All editions are supported viz. Community, Professional & Enterprise.
+The package aims to provide 0-friction installation and therefore comes loaded with most things required including rust-analyzer binary. If anything it needs is missing, appropriate errors / warnings will guide the user. E.g. cargo.exe needs to be in path and the package will tell you as much.
+This package is under rapid active development. So if you encounter any issues please file it at link:https://github.com/kitamstudios/rust-analyzer/[rust-analyzer.vs].
+
+==== VS_RustAnalyzer
+
+(License: GPL)
+
+https://marketplace.visualstudio.com/items?itemName=cchharris.vsrustanalyzer[Visual Studio Marketplace]
+
+https://github.com/cchharris/VS-RustAnalyzer[GitHub]
+
+==== SourceGear Rust
+
+(License: closed source)
+
+https://marketplace.visualstudio.com/items?itemName=SourceGear.SourceGearRust[Visual Studio Marketplace]
+
+https://github.com/sourcegear/rust-vs-extension[GitHub (docs, issues, discussions)]
+
+* Free (no-cost)
+* Supports all editions of Visual Studio 2022 on Windows: Community, Professional, or Enterprise
+
+=== Lapce
+
+https://lapce.dev/[Lapce] has a Rust plugin which you can install directly.
+Unfortunately, it downloads an old version of `rust-analyzer`, but you can set the server path under Settings.
+
=== Crates
There is a package named `ra_ap_rust_analyzer` available on https://crates.io/crates/ra_ap_rust-analyzer[crates.io], for someone who wants to use it programmatically.
@@ -684,14 +773,18 @@ See https://github.com/rust-analyzer/rust-project.json-example for a small examp
You can set the `RA_LOG` environment variable to `rust_analyzer=info` to inspect how rust-analyzer handles config and project loading.
-Note that calls to `cargo check` are disabled when using `rust-project.json` by default, so compilation errors and warnings will no longer be sent to your LSP client. To enable these compilation errors you will need to specify explicitly what command rust-analyzer should run to perform the checks using the `checkOnSave.overrideCommand` configuration. As an example, the following configuration explicitly sets `cargo check` as the `checkOnSave` command.
+Note that calls to `cargo check` are disabled when using `rust-project.json` by default, so compilation errors and warnings will no longer be sent to your LSP client.
+To enable these compilation errors you will need to specify explicitly what command rust-analyzer should run to perform the checks using the `rust-analyzer.check.overrideCommand` configuration.
+As an example, the following configuration explicitly sets `cargo check` as the `check` command.
[source,json]
----
-{ "rust-analyzer.checkOnSave.overrideCommand": ["cargo", "check", "--message-format=json"] }
+{ "rust-analyzer.check.overrideCommand": ["cargo", "check", "--message-format=json"] }
----
-The `checkOnSave.overrideCommand` requires the command specified to output json error messages for rust-analyzer to consume. The `--message-format=json` flag does this for `cargo check` so whichever command you use must also output errors in this format. See the <<Configuration>> section for more information.
+`check.overrideCommand` requires the command specified to output json error messages for rust-analyzer to consume.
+The `--message-format=json` flag does this for `cargo check` so whichever command you use must also output errors in this format.
+See the <<Configuration>> section for more information.
== Security
@@ -732,6 +825,10 @@ include::./generated_assists.adoc[]
While most errors and warnings provided by rust-analyzer come from the `cargo check` integration, there's a growing number of diagnostics implemented using rust-analyzer's own analysis.
Some of these diagnostics don't respect `\#[allow]` or `\#[deny]` attributes yet, but can be turned off using the `rust-analyzer.diagnostics.enable`, `rust-analyzer.diagnostics.experimental.enable` or `rust-analyzer.diagnostics.disabled` settings.
+=== Clippy
+
+To run `cargo clippy` instead of `cargo check`, you can set `"rust-analyzer.check.command": "clippy"`.
+
include::./generated_diagnostic.adoc[]
== Editor Features
@@ -864,7 +961,7 @@ Also note that a full runnable name is something like *run bin_or_example_name*,
Instead of relying on the built-in `cargo check`, you can configure Code to run a command in the background and use the `$rustc-watch` problem matcher to generate inline error markers from its output.
-To do this you need to create a new https://code.visualstudio.com/docs/editor/tasks[VS Code Task] and set `rust-analyzer.checkOnSave.enable: false` in preferences.
+To do this you need to create a new https://code.visualstudio.com/docs/editor/tasks[VS Code Task] and set `"rust-analyzer.checkOnSave": false` in preferences.
For example, if you want to run https://crates.io/crates/cargo-watch[`cargo watch`] instead, you might add the following to `.vscode/tasks.json`:
diff --git a/src/tools/rust-analyzer/lib/lsp-server/Cargo.toml b/src/tools/rust-analyzer/lib/lsp-server/Cargo.toml
index 9bba9e87e..6e32e3960 100644
--- a/src/tools/rust-analyzer/lib/lsp-server/Cargo.toml
+++ b/src/tools/rust-analyzer/lib/lsp-server/Cargo.toml
@@ -13,4 +13,4 @@ serde = { version = "1.0.144", features = ["derive"] }
crossbeam-channel = "0.5.6"
[dev-dependencies]
-lsp-types = "=0.93.2"
+lsp-types = "=0.94"
diff --git a/src/tools/rust-analyzer/lib/lsp-server/src/stdio.rs b/src/tools/rust-analyzer/lib/lsp-server/src/stdio.rs
index cdee6432d..49a825e57 100644
--- a/src/tools/rust-analyzer/lib/lsp-server/src/stdio.rs
+++ b/src/tools/rust-analyzer/lib/lsp-server/src/stdio.rs
@@ -21,10 +21,7 @@ pub(crate) fn stdio_transport() -> (Sender<Message>, Receiver<Message>, IoThread
let stdin = stdin();
let mut stdin = stdin.lock();
while let Some(msg) = Message::read(&mut stdin)? {
- let is_exit = match &msg {
- Message::Notification(n) => n.is_exit(),
- _ => false,
- };
+ let is_exit = matches!(&msg, Message::Notification(n) if n.is_exit());
reader_sender.send(msg).unwrap();
diff --git a/src/tools/rust-analyzer/xtask/Cargo.toml b/src/tools/rust-analyzer/xtask/Cargo.toml
index 2dd01796c..b4b294c30 100644
--- a/src/tools/rust-analyzer/xtask/Cargo.toml
+++ b/src/tools/rust-analyzer/xtask/Cargo.toml
@@ -12,5 +12,6 @@ flate2 = "1.0.24"
write-json = "0.1.2"
xshell = "0.2.2"
xflags = "0.3.0"
+time = { version = "0.3", default-features = false }
zip = { version = "0.6", default-features = false, features = ["deflate", "time"] }
# Avoid adding more dependencies to this crate
diff --git a/src/tools/rust-analyzer/xtask/src/dist.rs b/src/tools/rust-analyzer/xtask/src/dist.rs
index 74715c53e..5a03c71b2 100644
--- a/src/tools/rust-analyzer/xtask/src/dist.rs
+++ b/src/tools/rust-analyzer/xtask/src/dist.rs
@@ -6,6 +6,7 @@ use std::{
};
use flate2::{write::GzEncoder, Compression};
+use time::OffsetDateTime;
use xshell::{cmd, Shell};
use zip::{write::FileOptions, DateTime, ZipWriter};
@@ -112,7 +113,8 @@ fn zip(src_path: &Path, symbols_path: Option<&PathBuf>, dest_path: &Path) -> any
src_path.file_name().unwrap().to_str().unwrap(),
FileOptions::default()
.last_modified_time(
- DateTime::from_time(std::fs::metadata(src_path)?.modified()?.into()).unwrap(),
+ DateTime::try_from(OffsetDateTime::from(std::fs::metadata(src_path)?.modified()?))
+ .unwrap(),
)
.unix_permissions(0o755)
.compression_method(zip::CompressionMethod::Deflated)
@@ -125,7 +127,10 @@ fn zip(src_path: &Path, symbols_path: Option<&PathBuf>, dest_path: &Path) -> any
symbols_path.file_name().unwrap().to_str().unwrap(),
FileOptions::default()
.last_modified_time(
- DateTime::from_time(std::fs::metadata(src_path)?.modified()?.into()).unwrap(),
+ DateTime::try_from(OffsetDateTime::from(
+ std::fs::metadata(src_path)?.modified()?,
+ ))
+ .unwrap(),
)
.compression_method(zip::CompressionMethod::Deflated)
.compression_level(Some(9)),
diff --git a/src/tools/rust-analyzer/xtask/src/publish.rs b/src/tools/rust-analyzer/xtask/src/publish.rs
index 79b5f3d2f..cdb7d8fac 100644
--- a/src/tools/rust-analyzer/xtask/src/publish.rs
+++ b/src/tools/rust-analyzer/xtask/src/publish.rs
@@ -13,7 +13,7 @@ impl flags::PublishReleaseNotes {
let tag_name = &file_name[0..10];
let original_changelog_url = create_original_changelog_url(&file_name);
let additional_paragraph =
- format!("\nSee also [original changelog]({original_changelog_url}).");
+ format!("\nSee also the [changelog post]({original_changelog_url}).");
markdown.push_str(&additional_paragraph);
if self.dry_run {
println!("{markdown}");
diff --git a/src/tools/rust-analyzer/xtask/src/release/changelog.rs b/src/tools/rust-analyzer/xtask/src/release/changelog.rs
index d2a1483e3..675384148 100644
--- a/src/tools/rust-analyzer/xtask/src/release/changelog.rs
+++ b/src/tools/rust-analyzer/xtask/src/release/changelog.rs
@@ -69,7 +69,7 @@ pub(crate) fn get_changelog(
:page-layout: post
Commit: commit:{commit}[] +
-Release: release:{today}[]
+Release: release:{today}[] (`TBD`)
== New Features
@@ -156,7 +156,7 @@ fn parse_title_line(s: &str) -> PrInfo {
("minor: ", PrKind::Skip),
];
- for &(prefix, kind) in &PREFIXES {
+ for (prefix, kind) in PREFIXES {
if lower.starts_with(prefix) {
let message = match &kind {
PrKind::Skip => None,
diff --git a/src/tools/rust-installer/src/generator.rs b/src/tools/rust-installer/src/generator.rs
index 6a4cb9b4b..1e4d00b05 100644
--- a/src/tools/rust-installer/src/generator.rs
+++ b/src/tools/rust-installer/src/generator.rs
@@ -3,6 +3,7 @@ use super::Tarballer;
use crate::compression::CompressionFormats;
use crate::util::*;
use anyhow::{bail, format_err, Context, Result};
+use std::collections::BTreeSet;
use std::io::Write;
use std::path::Path;
@@ -121,13 +122,14 @@ impl Generator {
/// Copies the `src` directory recursively to `dst`, writing `manifest.in` too.
fn copy_and_manifest(src: &Path, dst: &Path, bulk_dirs: &str) -> Result<()> {
- let manifest = create_new_file(dst.join("manifest.in"))?;
+ let mut manifest = create_new_file(dst.join("manifest.in"))?;
let bulk_dirs: Vec<_> = bulk_dirs
.split(',')
.filter(|s| !s.is_empty())
.map(Path::new)
.collect();
+ let mut paths = BTreeSet::new();
copy_with_callback(src, dst, |path, file_type| {
// We need paths to be compatible with both Unix and Windows.
if path
@@ -157,14 +159,20 @@ fn copy_and_manifest(src: &Path, dst: &Path, bulk_dirs: &str) -> Result<()> {
if file_type.is_dir() {
// Only manifest directories that are explicitly bulk.
if bulk_dirs.contains(&path) {
- writeln!(&manifest, "dir:{}", string)?;
+ paths.insert(format!("dir:{}\n", string));
}
} else {
// Only manifest files that aren't under bulk directories.
if !bulk_dirs.iter().any(|d| path.starts_with(d)) {
- writeln!(&manifest, "file:{}", string)?;
+ paths.insert(format!("file:{}\n", string));
}
}
Ok(())
- })
+ })?;
+
+ for path in paths {
+ manifest.write_all(path.as_bytes())?;
+ }
+
+ Ok(())
}
diff --git a/src/tools/rustdoc-js/tester.js b/src/tools/rustdoc-js/tester.js
index 3da4fed33..ea5780f66 100644
--- a/src/tools/rustdoc-js/tester.js
+++ b/src/tools/rustdoc-js/tester.js
@@ -138,8 +138,20 @@ function valueCheck(fullPath, expected, result, error_text, queryName) {
error_text.push('==> Unknown key "' + key + '"');
break;
}
+ let result_v = result[key];
+ if (result_v !== null && key === "error") {
+ result_v.forEach((value, index) => {
+ value = value.split("&nbsp;").join(" ");
+ if (index % 2 === 1) {
+ result_v[index] = "`" + value + "`";
+ } else {
+ result_v[index] = value;
+ }
+ });
+ result_v = result_v.join("");
+ }
const obj_path = fullPath + (fullPath.length > 0 ? '.' : '') + key;
- valueCheck(obj_path, expected[key], result[key], error_text, queryName);
+ valueCheck(obj_path, expected[key], result_v, error_text, queryName);
}
} else {
expectedValue = JSON.stringify(expected);
diff --git a/src/tools/rustfmt/.github/workflows/check_diff.yml b/src/tools/rustfmt/.github/workflows/check_diff.yml
new file mode 100644
index 000000000..8bfb58345
--- /dev/null
+++ b/src/tools/rustfmt/.github/workflows/check_diff.yml
@@ -0,0 +1,33 @@
+name: Diff Check
+on:
+ workflow_dispatch:
+ inputs:
+ clone_url:
+ description: 'Git url of a rustfmt fork to compare against the latest master rustfmt'
+ required: true
+ branch_name:
+ description: 'Name of the feature branch on the forked repo'
+ required: true
+ commit_hash:
+ description: 'Optional commit hash from the feature branch'
+ required: false
+ rustfmt_configs:
+ description: 'Optional comma separated list of rustfmt config options to pass when running the feature branch'
+ required: false
+
+jobs:
+ diff_check:
+ runs-on: ubuntu-latest
+
+ steps:
+ - name: checkout
+ uses: actions/checkout@v3
+
+ - name: install rustup
+ run: |
+ curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs > rustup-init.sh
+ sh rustup-init.sh -y --default-toolchain none
+ rustup target add x86_64-unknown-linux-gnu
+
+ - name: check diff
+ run: bash ${GITHUB_WORKSPACE}/ci/check_diff.sh ${{ github.event.inputs.clone_url }} ${{ github.event.inputs.branch_name }} ${{ github.event.inputs.commit_hash }} ${{ github.event.inputs.rustfmt_configs }}
diff --git a/src/tools/rustfmt/.github/workflows/integration.yml b/src/tools/rustfmt/.github/workflows/integration.yml
index 4d8899b43..314ce0e84 100644
--- a/src/tools/rustfmt/.github/workflows/integration.yml
+++ b/src/tools/rustfmt/.github/workflows/integration.yml
@@ -27,7 +27,6 @@ jobs:
tempdir,
futures-rs,
rust-clippy,
- failure,
]
include:
# Allowed Failures
@@ -63,9 +62,6 @@ jobs:
# Original comment was: temporal build failure due to breaking changes in the nightly compiler
- integration: rust-semverver
allow-failure: true
- # Can be moved back to include section after https://github.com/rust-lang-nursery/failure/pull/298 is merged
- - integration: failure
- allow-failure: true
steps:
- name: checkout
diff --git a/src/tools/rustfmt/CHANGELOG.md b/src/tools/rustfmt/CHANGELOG.md
index 0c1893bf8..60f961fa1 100644
--- a/src/tools/rustfmt/CHANGELOG.md
+++ b/src/tools/rustfmt/CHANGELOG.md
@@ -2,6 +2,32 @@
## [Unreleased]
+## [1.5.2] 2023-01-24
+
+### Fixed
+
+- Resolve issue when comments are found within const generic defaults in unit structs [#5668](https://github.com/rust-lang/rustfmt/issues/5668)
+- Resolve issue when block comments are found within trait generics [#5358](https://github.com/rust-lang/rustfmt/issues/5358)
+- Correctly handle alignment of comments containing unicode characters [#5504](https://github.com/rust-lang/rustfmt/issues/5504)
+- Properly indent a single generic bound that requires being written across multiple lines [#4689](https://github.com/rust-lang/rustfmt/issues/4689) (n.b. this change is version gated and will only appear when the `version` configuration option is set to `Two`)
+
+### Changed
+
+- Renamed `fn_args_layout` configuration option to `fn_params_layout` [#4149](https://github.com/rust-lang/rustfmt/issues/4149). Note that `fn_args_layout` has only been soft deprecated: `fn_args_layout` will continue to work without issue, but rustfmt will display a warning to encourage users to switch to the new name
+
+### Added
+
+- New configuration option (`skip_macro_invocations`)[https://rust-lang.github.io/rustfmt/?version=master&search=#skip_macro_invocations] [#5347](https://github.com/rust-lang/rustfmt/pull/5347) that can be used to globally define a single enumerated list of macro calls that rustfmt should skip formatting. rustfmt [currently also supports this via a custom tool attribute](https://github.com/rust-lang/rustfmt#tips), however, these cannot be used in all contexts because [custom inner attributes are unstable](https://github.com/rust-lang/rust/issues/54726)
+
+### Misc
+
+- rustfmt now internally supports the ability to have both stable and unstable variants of a configuration option [#5378](https://github.com/rust-lang/rustfmt/issues/5378). This ability will allow the rustfmt team to make certain configuration options available on stable toolchains more quickly because we no longer have to wait for _every_ variant to be stable-ready before stabilizing _any_ variant.
+
+### Install/Download Options
+- **rustup (nightly)** - nightly-2023-01-24
+- **GitHub Release Binaries** - [Release v1.5.2](https://github.com/rust-lang/rustfmt/releases/tag/v1.5.2)
+- **Build from source** - [Tag v1.5.2](https://github.com/rust-lang/rustfmt/tree/v1.5.2), see instructions for how to [install rustfmt from source][install-from-source]
+
## [1.5.1] 2022-06-24
**N.B** A bug was introduced in v1.5.0/nightly-2022-06-15 which modified formatting. If you happened to run rustfmt over your code with one of those ~10 nightlies it's possible you may have seen formatting changes, and you may see additional changes after this fix since that bug has now been reverted.
@@ -840,7 +866,7 @@ from formatting an attribute #3665
- Fix formatting of raw string literals #2983
- Handle chain with try operators with spaces #2986
- Use correct shape in Visual tuple rewriting #2987
-- Impove formatting of arguments with `visual_style = "Visual"` option #2988
+- Improve formatting of arguments with `visual_style = "Visual"` option #2988
- Change `print_diff` to output the correct line number 992b179
- Propagate errors about failing to rewrite a macro 6f318e3
- Handle formatting of long function signature #3010
diff --git a/src/tools/rustfmt/Cargo.lock b/src/tools/rustfmt/Cargo.lock
index 311df226d..24166d51c 100644
--- a/src/tools/rustfmt/Cargo.lock
+++ b/src/tools/rustfmt/Cargo.lock
@@ -476,7 +476,7 @@ checksum = "fc71d2faa173b74b232dedc235e3ee1696581bb132fc116fa3626d6151a1a8fb"
[[package]]
name = "rustfmt-config_proc_macro"
-version = "0.2.0"
+version = "0.3.0"
dependencies = [
"proc-macro2",
"quote",
@@ -485,7 +485,7 @@ dependencies = [
[[package]]
name = "rustfmt-nightly"
-version = "1.5.1"
+version = "1.5.2"
dependencies = [
"annotate-snippets",
"anyhow",
diff --git a/src/tools/rustfmt/Cargo.toml b/src/tools/rustfmt/Cargo.toml
index 7a4e02d69..87ce59d02 100644
--- a/src/tools/rustfmt/Cargo.toml
+++ b/src/tools/rustfmt/Cargo.toml
@@ -1,7 +1,7 @@
[package]
name = "rustfmt-nightly"
-version = "1.5.1"
+version = "1.5.2"
description = "Tool to find and fix Rust formatting issues"
repository = "https://github.com/rust-lang/rustfmt"
readme = "README.md"
@@ -57,7 +57,7 @@ unicode-segmentation = "1.9"
unicode-width = "0.1"
unicode_categories = "0.1"
-rustfmt-config_proc_macro = { version = "0.2", path = "config_proc_macro" }
+rustfmt-config_proc_macro = { version = "0.3", path = "config_proc_macro" }
# A noop dependency that changes in the Rust repository, it's a bit of a hack.
# See the `src/tools/rustc-workspace-hack/README.md` file in `rust-lang/rust`
diff --git a/src/tools/rustfmt/Configurations.md b/src/tools/rustfmt/Configurations.md
index 8b96b9d36..49e7e4e64 100644
--- a/src/tools/rustfmt/Configurations.md
+++ b/src/tools/rustfmt/Configurations.md
@@ -1,6 +1,6 @@
# Configuring Rustfmt
-Rustfmt is designed to be very configurable. You can create a TOML file called `rustfmt.toml` or `.rustfmt.toml`, place it in the project or any other parent directory and it will apply the options in that file. If none of these directories contain such a file, both your home directory and a directory called `rustfmt` in your [global config directory](https://docs.rs/dirs/1.0.4/dirs/fn.config_dir.html) (e.g. `.config/rustfmt/`) are checked as well.
+Rustfmt is designed to be very configurable. You can create a TOML file called `rustfmt.toml` or `.rustfmt.toml`, place it in the project or any other parent directory and it will apply the options in that file. If none of these directories contain such a file, both your home directory and a directory called `rustfmt` in your [global config directory](https://docs.rs/dirs/4.0.0/dirs/fn.config_dir.html) (e.g. `.config/rustfmt/`) are checked as well.
A possible content of `rustfmt.toml` or `.rustfmt.toml` might look like this:
@@ -425,7 +425,7 @@ fn example() {
## `comment_width`
-Maximum length of comments. No effect unless`wrap_comments = true`.
+Maximum length of comments. No effect unless `wrap_comments = true`.
- **Default value**: `80`
- **Possible values**: any positive integer
@@ -589,7 +589,7 @@ doesn't get ignored when aligning.
#### `0` (default):
```rust
-enum Bar {
+enum Foo {
A = 0,
Bb = 1,
RandomLongVariantGoesHere = 10,
@@ -645,7 +645,8 @@ trailing whitespaces.
## `fn_args_layout`
-Control the layout of arguments in a function
+This option is deprecated and has been renamed to `fn_params_layout` to better communicate that
+it affects the layout of parameters in function signatures.
- **Default value**: `"Tall"`
- **Possible values**: `"Compressed"`, `"Tall"`, `"Vertical"`
@@ -753,6 +754,8 @@ trait Lorem {
}
```
+See also [`fn_params_layout`](#fn_params_layout)
+
## `fn_call_width`
Maximum width of the args of a function call before falling back to vertical formatting.
@@ -765,6 +768,117 @@ By default this option is set as a percentage of [`max_width`](#max_width) provi
See also [`max_width`](#max_width) and [`use_small_heuristics`](#use_small_heuristics)
+## `fn_params_layout`
+
+Control the layout of parameters in function signatures.
+
+- **Default value**: `"Tall"`
+- **Possible values**: `"Compressed"`, `"Tall"`, `"Vertical"`
+- **Stable**: Yes
+
+#### `"Tall"` (default):
+
+```rust
+trait Lorem {
+ fn lorem(ipsum: Ipsum, dolor: Dolor, sit: Sit, amet: Amet);
+
+ fn lorem(ipsum: Ipsum, dolor: Dolor, sit: Sit, amet: Amet) {
+ // body
+ }
+
+ fn lorem(
+ ipsum: Ipsum,
+ dolor: Dolor,
+ sit: Sit,
+ amet: Amet,
+ consectetur: Consectetur,
+ adipiscing: Adipiscing,
+ elit: Elit,
+ );
+
+ fn lorem(
+ ipsum: Ipsum,
+ dolor: Dolor,
+ sit: Sit,
+ amet: Amet,
+ consectetur: Consectetur,
+ adipiscing: Adipiscing,
+ elit: Elit,
+ ) {
+ // body
+ }
+}
+```
+
+#### `"Compressed"`:
+
+```rust
+trait Lorem {
+ fn lorem(ipsum: Ipsum, dolor: Dolor, sit: Sit, amet: Amet);
+
+ fn lorem(ipsum: Ipsum, dolor: Dolor, sit: Sit, amet: Amet) {
+ // body
+ }
+
+ fn lorem(
+ ipsum: Ipsum, dolor: Dolor, sit: Sit, amet: Amet, consectetur: Consectetur,
+ adipiscing: Adipiscing, elit: Elit,
+ );
+
+ fn lorem(
+ ipsum: Ipsum, dolor: Dolor, sit: Sit, amet: Amet, consectetur: Consectetur,
+ adipiscing: Adipiscing, elit: Elit,
+ ) {
+ // body
+ }
+}
+```
+
+#### `"Vertical"`:
+
+```rust
+trait Lorem {
+ fn lorem(
+ ipsum: Ipsum,
+ dolor: Dolor,
+ sit: Sit,
+ amet: Amet,
+ );
+
+ fn lorem(
+ ipsum: Ipsum,
+ dolor: Dolor,
+ sit: Sit,
+ amet: Amet,
+ ) {
+ // body
+ }
+
+ fn lorem(
+ ipsum: Ipsum,
+ dolor: Dolor,
+ sit: Sit,
+ amet: Amet,
+ consectetur: Consectetur,
+ adipiscing: Adipiscing,
+ elit: Elit,
+ );
+
+ fn lorem(
+ ipsum: Ipsum,
+ dolor: Dolor,
+ sit: Sit,
+ amet: Amet,
+ consectetur: Consectetur,
+ adipiscing: Adipiscing,
+ elit: Elit,
+ ) {
+ // body
+ }
+}
+```
+
+
## `fn_single_line`
Put single-expression functions on a single line
@@ -1014,6 +1128,62 @@ macro_rules! foo {
See also [`format_macro_matchers`](#format_macro_matchers).
+## `skip_macro_invocations`
+
+Skip formatting the bodies of macro invocations with the following names.
+
+rustfmt will not format any macro invocation for macros with names set in this list.
+Including the special value "*" will prevent any macro invocations from being formatted.
+
+Note: This option does not have any impact on how rustfmt formats macro definitions.
+
+- **Default value**: `[]`
+- **Possible values**: a list of macro name idents, `["name_0", "name_1", ..., "*"]`
+- **Stable**: No (tracking issue: [#5346](https://github.com/rust-lang/rustfmt/issues/5346))
+
+#### `[]` (default):
+
+rustfmt will follow its standard approach to formatting macro invocations.
+
+No macro invocations will be skipped based on their name. More information about rustfmt's standard macro invocation formatting behavior can be found in [#5437](https://github.com/rust-lang/rustfmt/discussions/5437).
+
+```rust
+lorem!(
+ const _: u8 = 0;
+);
+
+ipsum!(
+ const _: u8 = 0;
+);
+```
+
+#### `["lorem"]`:
+
+The named macro invocations will be skipped.
+
+```rust
+lorem!(
+ const _: u8 = 0;
+);
+
+ipsum!(
+ const _: u8 = 0;
+);
+```
+
+#### `["*"]`:
+
+The special selector `*` will skip all macro invocations.
+
+```rust
+lorem!(
+ const _: u8 = 0;
+);
+
+ipsum!(
+ const _: u8 = 0;
+);
+```
## `format_strings`
@@ -1687,13 +1857,16 @@ pub enum Foo {}
## `imports_granularity`
-How imports should be grouped into `use` statements. Imports will be merged or split to the configured level of granularity.
+Controls how imports are structured in `use` statements. Imports will be merged or split to the configured level of granularity.
+
+Similar to other `import` related configuration options, this option operates within the bounds of user-defined groups of imports. See [`group_imports`](#group_imports) for more information on import groups.
+
+Note that rustfmt will not modify the granularity of imports containing comments if doing so could potentially lose or misplace said comments.
- **Default value**: `Preserve`
- **Possible values**: `Preserve`, `Crate`, `Module`, `Item`, `One`
- **Stable**: No (tracking issue: [#4991](https://github.com/rust-lang/rustfmt/issues/4991))
-Note that rustfmt will not modify the granularity of imports containing comments if doing so could potentially lose or misplace said comments.
#### `Preserve` (default):
diff --git a/src/tools/rustfmt/Processes.md b/src/tools/rustfmt/Processes.md
index f763b5714..61abc87ee 100644
--- a/src/tools/rustfmt/Processes.md
+++ b/src/tools/rustfmt/Processes.md
@@ -2,7 +2,7 @@ This document outlines processes regarding management of rustfmt.
# Stabilising an Option
-In this Section, we describe how to stabilise an option of the rustfmt's configration.
+In this Section, we describe how to stabilise an option of the rustfmt's configuration.
## Conditions
diff --git a/src/tools/rustfmt/ci/build_and_test.bat b/src/tools/rustfmt/ci/build_and_test.bat
index ef4101778..69dae1fff 100755
--- a/src/tools/rustfmt/ci/build_and_test.bat
+++ b/src/tools/rustfmt/ci/build_and_test.bat
@@ -1,4 +1,5 @@
set "RUSTFLAGS=-D warnings"
+set "RUSTFMT_CI=1"
:: Print version information
rustc -Vv || exit /b 1
diff --git a/src/tools/rustfmt/ci/build_and_test.sh b/src/tools/rustfmt/ci/build_and_test.sh
index 8fa0f67b0..949918532 100755
--- a/src/tools/rustfmt/ci/build_and_test.sh
+++ b/src/tools/rustfmt/ci/build_and_test.sh
@@ -3,6 +3,7 @@
set -euo pipefail
export RUSTFLAGS="-D warnings"
+export RUSTFMT_CI=1
# Print version information
rustc -Vv
diff --git a/src/tools/rustfmt/ci/check_diff.sh b/src/tools/rustfmt/ci/check_diff.sh
new file mode 100755
index 000000000..062c2dd86
--- /dev/null
+++ b/src/tools/rustfmt/ci/check_diff.sh
@@ -0,0 +1,199 @@
+#!/bin/bash
+
+function print_usage() {
+ echo "usage check_diff REMOTE_REPO FEATURE_BRANCH [COMMIT_HASH] [OPTIONAL_RUSTFMT_CONFIGS]"
+}
+
+if [ $# -le 1 ]; then
+ print_usage
+ exit 1
+fi
+
+REMOTE_REPO=$1
+FEATURE_BRANCH=$2
+OPTIONAL_COMMIT_HASH=$3
+OPTIONAL_RUSTFMT_CONFIGS=$4
+
+# OUTPUT array used to collect all the status of running diffs on various repos
+STATUSES=()
+
+# Clone a git repository and cd into it.
+#
+# Parameters:
+# $1: git clone url
+# $2: directory where the repo should be cloned
+function clone_repo() {
+ GIT_TERMINAL_PROMPT=0 git clone --quiet $1 --depth 1 $2 && cd $2
+}
+
+# Initialize Git submoduels for the repo.
+#
+# Parameters
+# $1: list of directories to initialize
+function init_submodules() {
+ git submodule update --init $1
+}
+
+# Run rusfmt with the --check flag to see if a diff is produced.
+#
+# Parameters:
+# $1: Path to a rustfmt binary
+# $2: Output file path for the diff
+# $3: Any additional configuration options to pass to rustfmt
+#
+# Globlas:
+# $OPTIONAL_RUSTFMT_CONFIGS: Optional configs passed to the script from $4
+function create_diff() {
+ local config;
+ if [ -z "$3" ]; then
+ config="--config=error_on_line_overflow=false,error_on_unformatted=false"
+ else
+ config="--config=error_on_line_overflow=false,error_on_unformatted=false,$OPTIONAL_RUSTFMT_CONFIGS"
+ fi
+
+ for i in `find . | grep "\.rs$"`
+ do
+ $1 --unstable-features --skip-children --check --color=always $config $i >> $2 2>/dev/null
+ done
+}
+
+# Run the master rustfmt binary and the feature branch binary in the current directory and compare the diffs
+#
+# Parameters
+# $1: Name of the repository (used for logging)
+#
+# Globlas:
+# $RUSFMT_BIN: Path to the rustfmt master binary. Created when running `compile_rustfmt`
+# $FEATURE_BIN: Path to the rustfmt feature binary. Created when running `compile_rustfmt`
+# $OPTIONAL_RUSTFMT_CONFIGS: Optional configs passed to the script from $4
+function check_diff() {
+ echo "running rustfmt (master) on $1"
+ create_diff $RUSFMT_BIN rustfmt_diff.txt
+
+ echo "running rustfmt (feature) on $1"
+ create_diff $FEATURE_BIN feature_diff.txt $OPTIONAL_RUSTFMT_CONFIGS
+
+ echo "checking diff"
+ local diff;
+ # we don't add color to the diff since we added color when running rustfmt --check.
+ # tail -n + 6 removes the git diff header info
+ # cut -c 2- removes the leading diff characters("+","-"," ") from running git diff.
+ # Again, the diff output we care about was already added when we ran rustfmt --check
+ diff=$(
+ git --no-pager diff --color=never \
+ --unified=0 --no-index rustfmt_diff.txt feature_diff.txt 2>&1 | tail -n +6 | cut -c 2-
+ )
+
+ if [ -z "$diff" ]; then
+ echo "no diff detected between rustfmt and the feture branch"
+ return 0
+ else
+ echo "$diff"
+ return 1
+ fi
+}
+
+# Compiles and produces two rustfmt binaries.
+# One for the current master, and another for the feature branch
+#
+# Parameters:
+# $1: Directory where rustfmt will be cloned
+#
+# Globlas:
+# $REMOTE_REPO: Clone URL to the rustfmt fork that we want to test
+# $FEATURE_BRANCH: Name of the feature branch
+# $OPTIONAL_COMMIT_HASH: Optional commit hash that will be checked out if provided
+function compile_rustfmt() {
+ RUSTFMT_REPO="https://github.com/rust-lang/rustfmt.git"
+ clone_repo $RUSTFMT_REPO $1
+ git remote add feature $REMOTE_REPO
+ git fetch feature $FEATURE_BRANCH
+
+ cargo build --release --bin rustfmt && cp target/release/rustfmt $1/rustfmt
+ if [ -z "$OPTIONAL_COMMIT_HASH" ]; then
+ git switch $FEATURE_BRANCH
+ else
+ git switch $OPTIONAL_COMMIT_HASH --detach
+ fi
+ cargo build --release --bin rustfmt && cp target/release/rustfmt $1/feature_rustfmt
+ RUSFMT_BIN=$1/rustfmt
+ FEATURE_BIN=$1/feature_rustfmt
+}
+
+# Check the diff for running rustfmt and the feature branch on all the .rs files in the repo.
+#
+# Parameters
+# $1: Clone URL for the repo
+# $2: Name of the repo (mostly used for logging)
+# $3: Path to any submodules that should be initialized
+function check_repo() {
+ WORKDIR=$(pwd)
+ REPO_URL=$1
+ REPO_NAME=$2
+ SUBMODULES=$3
+
+ local tmp_dir;
+ tmp_dir=$(mktemp -d -t $REPO_NAME-XXXXXXXX)
+ clone_repo $REPO_URL $tmp_dir
+
+ if [ ! -z "$SUBMODULES" ]; then
+ init_submodules $SUBMODULES
+ fi
+
+ check_diff $REPO_NAME
+ # append the status of running `check_diff` to the STATUSES array
+ STATUSES+=($?)
+
+ echo "removing tmp_dir $tmp_dir"
+ rm -rf $tmp_dir
+ cd $WORKDIR
+}
+
+function main() {
+ tmp_dir=$(mktemp -d -t rustfmt-XXXXXXXX)
+ echo Created tmp_dir $tmp_dir
+
+ compile_rustfmt $tmp_dir
+
+ # run checks
+ check_repo "https://github.com/rust-lang/rust.git" rust-lang-rust
+ check_repo "https://github.com/rust-lang/cargo.git" cargo
+ check_repo "https://github.com/rust-lang/miri.git" miri
+ check_repo "https://github.com/rust-lang/rust-analyzer.git" rust-analyzer
+ check_repo "https://github.com/bitflags/bitflags.git" bitflags
+ check_repo "https://github.com/rust-lang/log.git" log
+ check_repo "https://github.com/rust-lang/mdBook.git" mdBook
+ check_repo "https://github.com/rust-lang/packed_simd.git" packed_simd
+ check_repo "https://github.com/rust-lang/rust-semverver.git" check_repo
+ check_repo "https://github.com/Stebalien/tempfile.git" tempfile
+ check_repo "https://github.com/rust-lang/futures-rs.git" futures-rs
+ check_repo "https://github.com/dtolnay/anyhow.git" anyhow
+ check_repo "https://github.com/dtolnay/thiserror.git" thiserror
+ check_repo "https://github.com/dtolnay/syn.git" syn
+ check_repo "https://github.com/serde-rs/serde.git" serde
+ check_repo "https://github.com/rust-lang/rustlings.git" rustlings
+ check_repo "https://github.com/rust-lang/rustup.git" rustup
+ check_repo "https://github.com/SergioBenitez/Rocket.git" Rocket
+ check_repo "https://github.com/rustls/rustls.git" rustls
+ check_repo "https://github.com/rust-lang/rust-bindgen.git" rust-bindgen
+ check_repo "https://github.com/hyperium/hyper.git" hyper
+ check_repo "https://github.com/actix/actix.git" actix
+ check_repo "https://github.com/denoland/deno.git" denoland_deno
+
+ # cleanup temp dir
+ echo removing tmp_dir $tmp_dir
+ rm -rf $tmp_dir
+
+ # figure out the exit code
+ for status in ${STATUSES[@]}
+ do
+ if [ $status -eq 1 ]; then
+ echo "formatting diff found 💔"
+ return 1
+ fi
+ done
+
+ echo "no diff found 😊"
+}
+
+main
diff --git a/src/tools/rustfmt/ci/integration.sh b/src/tools/rustfmt/ci/integration.sh
index 562d5d70c..19d502bc5 100755
--- a/src/tools/rustfmt/ci/integration.sh
+++ b/src/tools/rustfmt/ci/integration.sh
@@ -91,14 +91,28 @@ case ${INTEGRATION} in
cd -
;;
crater)
- git clone --depth=1 https://github.com/rust-lang-nursery/${INTEGRATION}.git
+ git clone --depth=1 https://github.com/rust-lang/${INTEGRATION}.git
cd ${INTEGRATION}
show_head
check_fmt_with_lib_tests
cd -
;;
+ bitflags)
+ git clone --depth=1 https://github.com/bitflags/${INTEGRATION}.git
+ cd ${INTEGRATION}
+ show_head
+ check_fmt_with_all_tests
+ cd -
+ ;;
+ error-chain | tempdir)
+ git clone --depth=1 https://github.com/rust-lang-deprecated/${INTEGRATION}.git
+ cd ${INTEGRATION}
+ show_head
+ check_fmt_with_all_tests
+ cd -
+ ;;
*)
- git clone --depth=1 https://github.com/rust-lang-nursery/${INTEGRATION}.git
+ git clone --depth=1 https://github.com/rust-lang/${INTEGRATION}.git
cd ${INTEGRATION}
show_head
check_fmt_with_all_tests
diff --git a/src/tools/rustfmt/config_proc_macro/Cargo.lock b/src/tools/rustfmt/config_proc_macro/Cargo.lock
index ecf561f28..49f2f72a8 100644
--- a/src/tools/rustfmt/config_proc_macro/Cargo.lock
+++ b/src/tools/rustfmt/config_proc_macro/Cargo.lock
@@ -22,7 +22,7 @@ dependencies = [
[[package]]
name = "rustfmt-config_proc_macro"
-version = "0.2.0"
+version = "0.3.0"
dependencies = [
"proc-macro2",
"quote",
diff --git a/src/tools/rustfmt/config_proc_macro/Cargo.toml b/src/tools/rustfmt/config_proc_macro/Cargo.toml
index a41b3a5e6..d10d0469c 100644
--- a/src/tools/rustfmt/config_proc_macro/Cargo.toml
+++ b/src/tools/rustfmt/config_proc_macro/Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "rustfmt-config_proc_macro"
-version = "0.2.0"
+version = "0.3.0"
edition = "2018"
description = "A collection of procedural macros for rustfmt"
license = "Apache-2.0/MIT"
diff --git a/src/tools/rustfmt/config_proc_macro/src/attrs.rs b/src/tools/rustfmt/config_proc_macro/src/attrs.rs
index 0baba046f..dd18ff572 100644
--- a/src/tools/rustfmt/config_proc_macro/src/attrs.rs
+++ b/src/tools/rustfmt/config_proc_macro/src/attrs.rs
@@ -1,8 +1,10 @@
//! This module provides utilities for handling attributes on variants
-//! of `config_type` enum. Currently there are two types of attributes
-//! that could appear on the variants of `config_type` enum: `doc_hint`
-//! and `value`. Both comes in the form of name-value pair whose value
-//! is string literal.
+//! of `config_type` enum. Currently there are the following attributes
+//! that could appear on the variants of `config_type` enum:
+//!
+//! - `doc_hint`: name-value pair whose value is string literal
+//! - `value`: name-value pair whose value is string literal
+//! - `unstable_variant`: name only
/// Returns the value of the first `doc_hint` attribute in the given slice or
/// `None` if `doc_hint` attribute is not available.
@@ -27,6 +29,11 @@ pub fn find_config_value(attrs: &[syn::Attribute]) -> Option<String> {
attrs.iter().filter_map(config_value).next()
}
+/// Returns `true` if the there is at least one `unstable` attribute in the given slice.
+pub fn any_unstable_variant(attrs: &[syn::Attribute]) -> bool {
+ attrs.iter().any(is_unstable_variant)
+}
+
/// Returns a string literal value if the given attribute is `value`
/// attribute or `None` otherwise.
pub fn config_value(attr: &syn::Attribute) -> Option<String> {
@@ -38,6 +45,11 @@ pub fn is_config_value(attr: &syn::Attribute) -> bool {
is_attr_name_value(attr, "value")
}
+/// Returns `true` if the given attribute is an `unstable` attribute.
+pub fn is_unstable_variant(attr: &syn::Attribute) -> bool {
+ is_attr_path(attr, "unstable_variant")
+}
+
fn is_attr_name_value(attr: &syn::Attribute, name: &str) -> bool {
attr.parse_meta().ok().map_or(false, |meta| match meta {
syn::Meta::NameValue(syn::MetaNameValue { ref path, .. }) if path.is_ident(name) => true,
@@ -45,6 +57,13 @@ fn is_attr_name_value(attr: &syn::Attribute, name: &str) -> bool {
})
}
+fn is_attr_path(attr: &syn::Attribute, name: &str) -> bool {
+ attr.parse_meta().ok().map_or(false, |meta| match meta {
+ syn::Meta::Path(path) if path.is_ident(name) => true,
+ _ => false,
+ })
+}
+
fn get_name_value_str_lit(attr: &syn::Attribute, name: &str) -> Option<String> {
attr.parse_meta().ok().and_then(|meta| match meta {
syn::Meta::NameValue(syn::MetaNameValue {
diff --git a/src/tools/rustfmt/config_proc_macro/src/item_enum.rs b/src/tools/rustfmt/config_proc_macro/src/item_enum.rs
index dcee77a85..731a7ea06 100644
--- a/src/tools/rustfmt/config_proc_macro/src/item_enum.rs
+++ b/src/tools/rustfmt/config_proc_macro/src/item_enum.rs
@@ -1,5 +1,6 @@
use proc_macro2::TokenStream;
-use quote::quote;
+use quote::{quote, quote_spanned};
+use syn::spanned::Spanned;
use crate::attrs::*;
use crate::utils::*;
@@ -47,12 +48,23 @@ fn process_variant(variant: &syn::Variant) -> TokenStream {
let metas = variant
.attrs
.iter()
- .filter(|attr| !is_doc_hint(attr) && !is_config_value(attr));
+ .filter(|attr| !is_doc_hint(attr) && !is_config_value(attr) && !is_unstable_variant(attr));
let attrs = fold_quote(metas, |meta| quote!(#meta));
let syn::Variant { ident, fields, .. } = variant;
quote!(#attrs #ident #fields)
}
+/// Return the correct syntax to pattern match on the enum variant, discarding all
+/// internal field data.
+fn fields_in_variant(variant: &syn::Variant) -> TokenStream {
+ // With thanks to https://stackoverflow.com/a/65182902
+ match &variant.fields {
+ syn::Fields::Unnamed(_) => quote_spanned! { variant.span() => (..) },
+ syn::Fields::Unit => quote_spanned! { variant.span() => },
+ syn::Fields::Named(_) => quote_spanned! { variant.span() => {..} },
+ }
+}
+
fn impl_doc_hint(ident: &syn::Ident, variants: &Variants) -> TokenStream {
let doc_hint = variants
.iter()
@@ -60,12 +72,26 @@ fn impl_doc_hint(ident: &syn::Ident, variants: &Variants) -> TokenStream {
.collect::<Vec<_>>()
.join("|");
let doc_hint = format!("[{}]", doc_hint);
+
+ let variant_stables = variants
+ .iter()
+ .map(|v| (&v.ident, fields_in_variant(&v), !unstable_of_variant(v)));
+ let match_patterns = fold_quote(variant_stables, |(v, fields, stable)| {
+ quote! {
+ #ident::#v #fields => #stable,
+ }
+ });
quote! {
use crate::config::ConfigType;
impl ConfigType for #ident {
fn doc_hint() -> String {
#doc_hint.to_owned()
}
+ fn stable_variant(&self) -> bool {
+ match self {
+ #match_patterns
+ }
+ }
}
}
}
@@ -123,13 +149,21 @@ fn impl_from_str(ident: &syn::Ident, variants: &Variants) -> TokenStream {
}
fn doc_hint_of_variant(variant: &syn::Variant) -> String {
- find_doc_hint(&variant.attrs).unwrap_or(variant.ident.to_string())
+ let mut text = find_doc_hint(&variant.attrs).unwrap_or(variant.ident.to_string());
+ if unstable_of_variant(&variant) {
+ text.push_str(" (unstable)")
+ };
+ text
}
fn config_value_of_variant(variant: &syn::Variant) -> String {
find_config_value(&variant.attrs).unwrap_or(variant.ident.to_string())
}
+fn unstable_of_variant(variant: &syn::Variant) -> bool {
+ any_unstable_variant(&variant.attrs)
+}
+
fn impl_serde(ident: &syn::Ident, variants: &Variants) -> TokenStream {
let arms = fold_quote(variants.iter(), |v| {
let v_ident = &v.ident;
diff --git a/src/tools/rustfmt/config_proc_macro/src/lib.rs b/src/tools/rustfmt/config_proc_macro/src/lib.rs
index e772c53f4..0c54c132c 100644
--- a/src/tools/rustfmt/config_proc_macro/src/lib.rs
+++ b/src/tools/rustfmt/config_proc_macro/src/lib.rs
@@ -69,3 +69,16 @@ pub fn stable_only_test(_args: TokenStream, input: TokenStream) -> TokenStream {
TokenStream::from_str("").unwrap()
}
}
+
+/// Used to conditionally output the TokenStream for tests that should be run as part of rustfmts
+/// test suite, but should be ignored when running in the rust-lang/rust test suite.
+#[proc_macro_attribute]
+pub fn rustfmt_only_ci_test(_args: TokenStream, input: TokenStream) -> TokenStream {
+ if option_env!("RUSTFMT_CI").is_some() {
+ input
+ } else {
+ let mut token_stream = TokenStream::from_str("#[ignore]").unwrap();
+ token_stream.extend(input);
+ token_stream
+ }
+}
diff --git a/src/tools/rustfmt/config_proc_macro/tests/smoke.rs b/src/tools/rustfmt/config_proc_macro/tests/smoke.rs
index 940a8a0c2..c8a83e39c 100644
--- a/src/tools/rustfmt/config_proc_macro/tests/smoke.rs
+++ b/src/tools/rustfmt/config_proc_macro/tests/smoke.rs
@@ -1,6 +1,7 @@
pub mod config {
pub trait ConfigType: Sized {
fn doc_hint() -> String;
+ fn stable_variant(&self) -> bool;
}
}
diff --git a/src/tools/rustfmt/rust-toolchain b/src/tools/rustfmt/rust-toolchain
index 2640a9e0e..22283b3d6 100644
--- a/src/tools/rustfmt/rust-toolchain
+++ b/src/tools/rustfmt/rust-toolchain
@@ -1,3 +1,3 @@
[toolchain]
-channel = "nightly-2022-06-21"
-components = ["rustc-dev"]
+channel = "nightly-2023-01-24"
+components = ["llvm-tools", "rustc-dev"]
diff --git a/src/tools/rustfmt/src/attr.rs b/src/tools/rustfmt/src/attr.rs
index c503eeeb9..5648e1254 100644
--- a/src/tools/rustfmt/src/attr.rs
+++ b/src/tools/rustfmt/src/attr.rs
@@ -336,7 +336,7 @@ impl Rewrite for ast::Attribute {
} else {
let should_skip = self
.ident()
- .map(|s| context.skip_context.skip_attribute(s.name.as_str()))
+ .map(|s| context.skip_context.attributes.skip(s.name.as_str()))
.unwrap_or(false);
let prefix = attr_prefix(self);
@@ -390,7 +390,7 @@ impl Rewrite for [ast::Attribute] {
// Determine if the source text is annotated with `#[rustfmt::skip::attributes(derive)]`
// or `#![rustfmt::skip::attributes(derive)]`
- let skip_derives = context.skip_context.skip_attribute("derive");
+ let skip_derives = context.skip_context.attributes.skip("derive");
// This is not just a simple map because we need to handle doc comments
// (where we take as many doc comment attributes as possible) and possibly
diff --git a/src/tools/rustfmt/src/bin/main.rs b/src/tools/rustfmt/src/bin/main.rs
index 8e871e61f..be64559e8 100644
--- a/src/tools/rustfmt/src/bin/main.rs
+++ b/src/tools/rustfmt/src/bin/main.rs
@@ -136,7 +136,7 @@ fn make_opts() -> Options {
"l",
"files-with-diff",
"Prints the names of mismatched files that were formatted. Prints the names of \
- files that would be formated when used with `--check` mode. ",
+ files that would be formatted when used with `--check` mode. ",
);
opts.optmulti(
"",
diff --git a/src/tools/rustfmt/src/cargo-fmt/main.rs b/src/tools/rustfmt/src/cargo-fmt/main.rs
index 9031d29b4..2b714b68d 100644
--- a/src/tools/rustfmt/src/cargo-fmt/main.rs
+++ b/src/tools/rustfmt/src/cargo-fmt/main.rs
@@ -198,12 +198,10 @@ fn convert_message_format_to_rustfmt_args(
Ok(())
}
"human" => Ok(()),
- _ => {
- return Err(format!(
- "invalid --message-format value: {}. Allowed values are: short|json|human",
- message_format
- ));
- }
+ _ => Err(format!(
+ "invalid --message-format value: {}. Allowed values are: short|json|human",
+ message_format
+ )),
}
}
@@ -215,7 +213,7 @@ fn print_usage_to_stderr(reason: &str) {
.expect("failed to write to stderr");
}
-#[derive(Debug, Clone, Copy, PartialEq)]
+#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Verbosity {
Verbose,
Normal,
diff --git a/src/tools/rustfmt/src/cargo-fmt/test/mod.rs b/src/tools/rustfmt/src/cargo-fmt/test/mod.rs
index 56e52fbab..696326e4f 100644
--- a/src/tools/rustfmt/src/cargo-fmt/test/mod.rs
+++ b/src/tools/rustfmt/src/cargo-fmt/test/mod.rs
@@ -70,9 +70,9 @@ fn mandatory_separator() {
.is_err()
);
assert!(
- !Opts::command()
+ Opts::command()
.try_get_matches_from(&["test", "--", "--emit"])
- .is_err()
+ .is_ok()
);
}
diff --git a/src/tools/rustfmt/src/chains.rs b/src/tools/rustfmt/src/chains.rs
index a1a73cf4b..cbe523c6c 100644
--- a/src/tools/rustfmt/src/chains.rs
+++ b/src/tools/rustfmt/src/chains.rs
@@ -70,10 +70,66 @@ use crate::rewrite::{Rewrite, RewriteContext};
use crate::shape::Shape;
use crate::source_map::SpanUtils;
use crate::utils::{
- self, first_line_width, last_line_extendable, last_line_width, mk_sp, rewrite_ident,
- trimmed_last_line_width, wrap_str,
+ self, filtered_str_fits, first_line_width, last_line_extendable, last_line_width, mk_sp,
+ rewrite_ident, trimmed_last_line_width, wrap_str,
};
+use thin_vec::ThinVec;
+
+/// Provides the original input contents from the span
+/// of a chain element with trailing spaces trimmed.
+fn format_overflow_style(span: Span, context: &RewriteContext<'_>) -> Option<String> {
+ context.snippet_provider.span_to_snippet(span).map(|s| {
+ s.lines()
+ .map(|l| l.trim_end())
+ .collect::<Vec<_>>()
+ .join("\n")
+ })
+}
+
+fn format_chain_item(
+ item: &ChainItem,
+ context: &RewriteContext<'_>,
+ rewrite_shape: Shape,
+ allow_overflow: bool,
+) -> Option<String> {
+ if allow_overflow {
+ item.rewrite(context, rewrite_shape)
+ .or_else(|| format_overflow_style(item.span, context))
+ } else {
+ item.rewrite(context, rewrite_shape)
+ }
+}
+
+fn get_block_child_shape(
+ prev_ends_with_block: bool,
+ context: &RewriteContext<'_>,
+ shape: Shape,
+) -> Shape {
+ if prev_ends_with_block {
+ shape.block_indent(0)
+ } else {
+ shape.block_indent(context.config.tab_spaces())
+ }
+ .with_max_width(context.config)
+}
+
+fn get_visual_style_child_shape(
+ context: &RewriteContext<'_>,
+ shape: Shape,
+ offset: usize,
+ parent_overflowing: bool,
+) -> Option<Shape> {
+ if !parent_overflowing {
+ shape
+ .with_max_width(context.config)
+ .offset_left(offset)
+ .map(|s| s.visual_indent(0))
+ } else {
+ Some(shape.visual_indent(offset))
+ }
+}
+
pub(crate) fn rewrite_chain(
expr: &ast::Expr,
context: &RewriteContext<'_>,
@@ -114,7 +170,7 @@ enum ChainItemKind {
MethodCall(
ast::PathSegment,
Vec<ast::GenericArg>,
- Vec<ptr::P<ast::Expr>>,
+ ThinVec<ptr::P<ast::Expr>>,
),
StructField(symbol::Ident),
TupleField(symbol::Ident, bool),
@@ -496,6 +552,8 @@ struct ChainFormatterShared<'a> {
// The number of children in the chain. This is not equal to `self.children.len()`
// because `self.children` will change size as we process the chain.
child_count: usize,
+ // Whether elements are allowed to overflow past the max_width limit
+ allow_overflow: bool,
}
impl<'a> ChainFormatterShared<'a> {
@@ -505,6 +563,8 @@ impl<'a> ChainFormatterShared<'a> {
rewrites: Vec::with_capacity(chain.children.len() + 1),
fits_single_line: false,
child_count: chain.children.len(),
+ // TODO(calebcartwright)
+ allow_overflow: false,
}
}
@@ -517,6 +577,14 @@ impl<'a> ChainFormatterShared<'a> {
}
}
+ fn format_children(&mut self, context: &RewriteContext<'_>, child_shape: Shape) -> Option<()> {
+ for item in &self.children[..self.children.len() - 1] {
+ let rewrite = format_chain_item(item, context, child_shape, self.allow_overflow)?;
+ self.rewrites.push(rewrite);
+ }
+ Some(())
+ }
+
// Rewrite the last child. The last child of a chain requires special treatment. We need to
// know whether 'overflowing' the last child make a better formatting:
//
@@ -729,22 +797,12 @@ impl<'a> ChainFormatter for ChainFormatterBlock<'a> {
}
fn child_shape(&self, context: &RewriteContext<'_>, shape: Shape) -> Option<Shape> {
- Some(
- if self.root_ends_with_block {
- shape.block_indent(0)
- } else {
- shape.block_indent(context.config.tab_spaces())
- }
- .with_max_width(context.config),
- )
+ let block_end = self.root_ends_with_block;
+ Some(get_block_child_shape(block_end, context, shape))
}
fn format_children(&mut self, context: &RewriteContext<'_>, child_shape: Shape) -> Option<()> {
- for item in &self.shared.children[..self.shared.children.len() - 1] {
- let rewrite = item.rewrite(context, child_shape)?;
- self.shared.rewrites.push(rewrite);
- }
- Some(())
+ self.shared.format_children(context, child_shape)
}
fn format_last_child(
@@ -808,15 +866,14 @@ impl<'a> ChainFormatter for ChainFormatterVisual<'a> {
.visual_indent(self.offset)
.sub_width(self.offset)?;
let rewrite = item.rewrite(context, child_shape)?;
- match wrap_str(rewrite, context.config.max_width(), shape) {
- Some(rewrite) => root_rewrite.push_str(&rewrite),
- None => {
- // We couldn't fit in at the visual indent, try the last
- // indent.
- let rewrite = item.rewrite(context, parent_shape)?;
- root_rewrite.push_str(&rewrite);
- self.offset = 0;
- }
+ if filtered_str_fits(&rewrite, context.config.max_width(), shape) {
+ root_rewrite.push_str(&rewrite);
+ } else {
+ // We couldn't fit in at the visual indent, try the last
+ // indent.
+ let rewrite = item.rewrite(context, parent_shape)?;
+ root_rewrite.push_str(&rewrite);
+ self.offset = 0;
}
self.shared.children = &self.shared.children[1..];
@@ -827,18 +884,17 @@ impl<'a> ChainFormatter for ChainFormatterVisual<'a> {
}
fn child_shape(&self, context: &RewriteContext<'_>, shape: Shape) -> Option<Shape> {
- shape
- .with_max_width(context.config)
- .offset_left(self.offset)
- .map(|s| s.visual_indent(0))
+ get_visual_style_child_shape(
+ context,
+ shape,
+ self.offset,
+ // TODO(calebcartwright): self.shared.permissibly_overflowing_parent,
+ false,
+ )
}
fn format_children(&mut self, context: &RewriteContext<'_>, child_shape: Shape) -> Option<()> {
- for item in &self.shared.children[..self.shared.children.len() - 1] {
- let rewrite = item.rewrite(context, child_shape)?;
- self.shared.rewrites.push(rewrite);
- }
- Some(())
+ self.shared.format_children(context, child_shape)
}
fn format_last_child(
diff --git a/src/tools/rustfmt/src/closures.rs b/src/tools/rustfmt/src/closures.rs
index 8fd0fcf8f..340113866 100644
--- a/src/tools/rustfmt/src/closures.rs
+++ b/src/tools/rustfmt/src/closures.rs
@@ -1,5 +1,6 @@
use rustc_ast::{ast, ptr};
use rustc_span::Span;
+use thin_vec::thin_vec;
use crate::attr::get_attrs_from_stmt;
use crate::config::lists::*;
@@ -150,7 +151,7 @@ fn rewrite_closure_with_block(
}
let block = ast::Block {
- stmts: vec![ast::Stmt {
+ stmts: thin_vec![ast::Stmt {
id: ast::NodeId::root(),
kind: ast::StmtKind::Expr(ptr::P(body.clone())),
span: body.span,
diff --git a/src/tools/rustfmt/src/config/config_type.rs b/src/tools/rustfmt/src/config/config_type.rs
index c5e61658a..54ca7676d 100644
--- a/src/tools/rustfmt/src/config/config_type.rs
+++ b/src/tools/rustfmt/src/config/config_type.rs
@@ -1,4 +1,5 @@
use crate::config::file_lines::FileLines;
+use crate::config::macro_names::MacroSelectors;
use crate::config::options::{IgnoreList, WidthHeuristics};
/// Trait for types that can be used in `Config`.
@@ -6,6 +7,14 @@ pub(crate) trait ConfigType: Sized {
/// Returns hint text for use in `Config::print_docs()`. For enum types, this is a
/// pipe-separated list of variants; for other types it returns `<type>`.
fn doc_hint() -> String;
+
+ /// Return `true` if the variant (i.e. value of this type) is stable.
+ ///
+ /// By default, return true for all values. Enums annotated with `#[config_type]`
+ /// are automatically implemented, based on the `#[unstable_variant]` annotation.
+ fn stable_variant(&self) -> bool {
+ true
+ }
}
impl ConfigType for bool {
@@ -38,6 +47,12 @@ impl ConfigType for FileLines {
}
}
+impl ConfigType for MacroSelectors {
+ fn doc_hint() -> String {
+ String::from("[<string>, ...]")
+ }
+}
+
impl ConfigType for WidthHeuristics {
fn doc_hint() -> String {
String::new()
@@ -51,6 +66,13 @@ impl ConfigType for IgnoreList {
}
macro_rules! create_config {
+ // Options passed in to the macro.
+ //
+ // - $i: the ident name of the option
+ // - $ty: the type of the option value
+ // - $def: the default value of the option
+ // - $stb: true if the option is stable
+ // - $dstring: description of the option
($($i:ident: $ty:ty, $def:expr, $stb:expr, $( $dstring:expr ),+ );+ $(;)*) => (
#[cfg(test)]
use std::collections::HashSet;
@@ -61,9 +83,12 @@ macro_rules! create_config {
#[derive(Clone)]
#[allow(unreachable_pub)]
pub struct Config {
- // For each config item, we store a bool indicating whether it has
- // been accessed and the value, and a bool whether the option was
- // manually initialised, or taken from the default,
+ // For each config item, we store:
+ //
+ // - 0: true if the value has been access
+ // - 1: true if the option was manually initialized
+ // - 2: the option value
+ // - 3: true if the option is unstable
$($i: (Cell<bool>, bool, $ty, bool)),+
}
@@ -102,6 +127,7 @@ macro_rules! create_config {
| "array_width"
| "chain_width" => self.0.set_heuristics(),
"merge_imports" => self.0.set_merge_imports(),
+ "fn_args_layout" => self.0.set_fn_args_layout(),
&_ => (),
}
}
@@ -143,24 +169,20 @@ macro_rules! create_config {
fn fill_from_parsed_config(mut self, parsed: PartialConfig, dir: &Path) -> Config {
$(
- if let Some(val) = parsed.$i {
- if self.$i.3 {
+ if let Some(option_value) = parsed.$i {
+ let option_stable = self.$i.3;
+ if $crate::config::config_type::is_stable_option_and_value(
+ stringify!($i), option_stable, &option_value
+ ) {
self.$i.1 = true;
- self.$i.2 = val;
- } else {
- if crate::is_nightly_channel!() {
- self.$i.1 = true;
- self.$i.2 = val;
- } else {
- eprintln!("Warning: can't set `{} = {:?}`, unstable features are only \
- available in nightly channel.", stringify!($i), val);
- }
+ self.$i.2 = option_value;
}
}
)+
self.set_heuristics();
self.set_ignore(dir);
self.set_merge_imports();
+ self.set_fn_args_layout();
self
}
@@ -221,12 +243,22 @@ macro_rules! create_config {
match key {
$(
stringify!($i) => {
- self.$i.1 = true;
- self.$i.2 = val.parse::<$ty>()
+ let option_value = val.parse::<$ty>()
.expect(&format!("Failed to parse override for {} (\"{}\") as a {}",
stringify!($i),
val,
stringify!($ty)));
+
+ // Users are currently allowed to set unstable
+ // options/variants via the `--config` options override.
+ //
+ // There is ongoing discussion about how to move forward here:
+ // https://github.com/rust-lang/rustfmt/pull/5379
+ //
+ // For now, do not validate whether the option or value is stable,
+ // just always set it.
+ self.$i.1 = true;
+ self.$i.2 = option_value;
}
)+
_ => panic!("Unknown config key in override: {}", key)
@@ -243,14 +275,21 @@ macro_rules! create_config {
| "array_width"
| "chain_width" => self.set_heuristics(),
"merge_imports" => self.set_merge_imports(),
+ "fn_args_layout" => self.set_fn_args_layout(),
&_ => (),
}
}
#[allow(unreachable_pub)]
pub fn is_hidden_option(name: &str) -> bool {
- const HIDE_OPTIONS: [&str; 5] =
- ["verbose", "verbose_diff", "file_lines", "width_heuristics", "merge_imports"];
+ const HIDE_OPTIONS: [&str; 6] = [
+ "verbose",
+ "verbose_diff",
+ "file_lines",
+ "width_heuristics",
+ "merge_imports",
+ "fn_args_layout"
+ ];
HIDE_OPTIONS.contains(&name)
}
@@ -400,6 +439,18 @@ macro_rules! create_config {
}
}
+ fn set_fn_args_layout(&mut self) {
+ if self.was_set().fn_args_layout() {
+ eprintln!(
+ "Warning: the `fn_args_layout` option is deprecated. \
+ Use `fn_params_layout`. instead"
+ );
+ if !self.was_set().fn_params_layout() {
+ self.fn_params_layout.2 = self.fn_args_layout();
+ }
+ }
+ }
+
#[allow(unreachable_pub)]
/// Returns `true` if the config key was explicitly set and is the default value.
pub fn is_default(&self, key: &str) -> bool {
@@ -424,3 +475,38 @@ macro_rules! create_config {
}
)
}
+
+pub(crate) fn is_stable_option_and_value<T>(
+ option_name: &str,
+ option_stable: bool,
+ option_value: &T,
+) -> bool
+where
+ T: PartialEq + std::fmt::Debug + ConfigType,
+{
+ let nightly = crate::is_nightly_channel!();
+ let variant_stable = option_value.stable_variant();
+ match (nightly, option_stable, variant_stable) {
+ // Stable with an unstable option
+ (false, false, _) => {
+ eprintln!(
+ "Warning: can't set `{} = {:?}`, unstable features are only \
+ available in nightly channel.",
+ option_name, option_value
+ );
+ false
+ }
+ // Stable with a stable option, but an unstable variant
+ (false, true, false) => {
+ eprintln!(
+ "Warning: can't set `{} = {:?}`, unstable variants are only \
+ available in nightly channel.",
+ option_name, option_value
+ );
+ false
+ }
+ // Nightly: everything allowed
+ // Stable with stable option and variant: allowed
+ (true, _, _) | (false, true, true) => true,
+ }
+}
diff --git a/src/tools/rustfmt/src/config/macro_names.rs b/src/tools/rustfmt/src/config/macro_names.rs
new file mode 100644
index 000000000..26ad78d6d
--- /dev/null
+++ b/src/tools/rustfmt/src/config/macro_names.rs
@@ -0,0 +1,118 @@
+//! This module contains types and functions to support formatting specific macros.
+
+use itertools::Itertools;
+use std::{fmt, str};
+
+use serde::{Deserialize, Serialize};
+use serde_json as json;
+use thiserror::Error;
+
+/// Defines the name of a macro.
+#[derive(Clone, Debug, Eq, PartialEq, Hash, Ord, PartialOrd, Deserialize, Serialize)]
+pub struct MacroName(String);
+
+impl MacroName {
+ pub fn new(other: String) -> Self {
+ Self(other)
+ }
+}
+
+impl fmt::Display for MacroName {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ self.0.fmt(f)
+ }
+}
+
+impl From<MacroName> for String {
+ fn from(other: MacroName) -> Self {
+ other.0
+ }
+}
+
+/// Defines a selector to match against a macro.
+#[derive(Clone, Debug, Eq, PartialEq, Hash, Ord, PartialOrd, Deserialize, Serialize)]
+pub enum MacroSelector {
+ Name(MacroName),
+ All,
+}
+
+impl fmt::Display for MacroSelector {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ match self {
+ Self::Name(name) => name.fmt(f),
+ Self::All => write!(f, "*"),
+ }
+ }
+}
+
+impl str::FromStr for MacroSelector {
+ type Err = std::convert::Infallible;
+
+ fn from_str(s: &str) -> Result<Self, Self::Err> {
+ Ok(match s {
+ "*" => MacroSelector::All,
+ name => MacroSelector::Name(MacroName(name.to_owned())),
+ })
+ }
+}
+
+/// A set of macro selectors.
+#[derive(Clone, Debug, Default, PartialEq, Deserialize, Serialize)]
+pub struct MacroSelectors(pub Vec<MacroSelector>);
+
+impl fmt::Display for MacroSelectors {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ write!(f, "{}", self.0.iter().format(", "))
+ }
+}
+
+#[derive(Error, Debug)]
+pub enum MacroSelectorsError {
+ #[error("{0}")]
+ Json(json::Error),
+}
+
+// This impl is needed for `Config::override_value` to work for use in tests.
+impl str::FromStr for MacroSelectors {
+ type Err = MacroSelectorsError;
+
+ fn from_str(s: &str) -> Result<Self, Self::Err> {
+ let raw: Vec<&str> = json::from_str(s).map_err(MacroSelectorsError::Json)?;
+ Ok(Self(
+ raw.into_iter()
+ .map(|raw| {
+ MacroSelector::from_str(raw).expect("MacroSelector from_str is infallible")
+ })
+ .collect(),
+ ))
+ }
+}
+
+#[cfg(test)]
+mod test {
+ use super::*;
+ use std::str::FromStr;
+
+ #[test]
+ fn macro_names_from_str() {
+ let macro_names = MacroSelectors::from_str(r#"["foo", "*", "bar"]"#).unwrap();
+ assert_eq!(
+ macro_names,
+ MacroSelectors(
+ [
+ MacroSelector::Name(MacroName("foo".to_owned())),
+ MacroSelector::All,
+ MacroSelector::Name(MacroName("bar".to_owned()))
+ ]
+ .into_iter()
+ .collect()
+ )
+ );
+ }
+
+ #[test]
+ fn macro_names_display() {
+ let macro_names = MacroSelectors::from_str(r#"["foo", "*", "bar"]"#).unwrap();
+ assert_eq!(format!("{}", macro_names), "foo, *, bar");
+ }
+}
diff --git a/src/tools/rustfmt/src/config/mod.rs b/src/tools/rustfmt/src/config/mod.rs
index f49c18d3a..14f27f3f8 100644
--- a/src/tools/rustfmt/src/config/mod.rs
+++ b/src/tools/rustfmt/src/config/mod.rs
@@ -13,15 +13,20 @@ pub use crate::config::file_lines::{FileLines, FileName, Range};
#[allow(unreachable_pub)]
pub use crate::config::lists::*;
#[allow(unreachable_pub)]
+pub use crate::config::macro_names::{MacroSelector, MacroSelectors};
+#[allow(unreachable_pub)]
pub use crate::config::options::*;
#[macro_use]
pub(crate) mod config_type;
#[macro_use]
+#[allow(unreachable_pub)]
pub(crate) mod options;
pub(crate) mod file_lines;
+#[allow(unreachable_pub)]
pub(crate) mod lists;
+pub(crate) mod macro_names;
// This macro defines configuration options used in rustfmt. Each option
// is defined as follows:
@@ -67,6 +72,8 @@ create_config! {
format_macro_matchers: bool, false, false,
"Format the metavariable matching patterns in macros";
format_macro_bodies: bool, true, false, "Format the bodies of macros";
+ skip_macro_invocations: MacroSelectors, MacroSelectors::default(), false,
+ "Skip formatting the bodies of macros invoked with the following names.";
hex_literal_case: HexLiteralCase, HexLiteralCase::Preserve, false,
"Format hexadecimal integer literals";
@@ -119,7 +126,9 @@ create_config! {
force_multiline_blocks: bool, false, false,
"Force multiline closure bodies and match arms to be wrapped in a block";
fn_args_layout: Density, Density::Tall, true,
- "Control the layout of arguments in a function";
+ "(deprecated: use fn_params_layout instead)";
+ fn_params_layout: Density, Density::Tall, true,
+ "Control the layout of parameters in function signatures.";
brace_style: BraceStyle, BraceStyle::SameLineWhere, false, "Brace style for items";
control_brace_style: ControlBraceStyle, ControlBraceStyle::AlwaysSameLine, false,
"Brace style for control flow constructs";
@@ -175,7 +184,7 @@ create_config! {
make_backup: bool, false, false, "Backup changed files";
print_misformatted_file_names: bool, false, true,
"Prints the names of mismatched files that were formatted. Prints the names of \
- files that would be formated when used with `--check` mode. ";
+ files that would be formatted when used with `--check` mode. ";
}
#[derive(Error, Debug)]
@@ -191,6 +200,7 @@ impl PartialConfig {
cloned.width_heuristics = None;
cloned.print_misformatted_file_names = None;
cloned.merge_imports = None;
+ cloned.fn_args_layout = None;
::toml::to_string(&cloned).map_err(ToTomlError)
}
@@ -403,11 +413,21 @@ mod test {
use super::*;
use std::str;
+ use crate::config::macro_names::MacroName;
use rustfmt_config_proc_macro::{nightly_only_test, stable_only_test};
#[allow(dead_code)]
mod mock {
use super::super::*;
+ use rustfmt_config_proc_macro::config_type;
+
+ #[config_type]
+ pub(crate) enum PartiallyUnstableOption {
+ V1,
+ V2,
+ #[unstable_variant]
+ V3,
+ }
create_config! {
// Options that are used by the generated functions
@@ -427,6 +447,12 @@ mod test {
"Merge imports";
merge_imports: bool, false, false, "(deprecated: use imports_granularity instead)";
+ // fn_args_layout renamed to fn_params_layout
+ fn_args_layout: Density, Density::Tall, true,
+ "(deprecated: use fn_params_layout instead)";
+ fn_params_layout: Density, Density::Tall, true,
+ "Control the layout of parameters in a function signatures.";
+
// Width Heuristics
use_small_heuristics: Heuristics, Heuristics::Default, true,
"Whether to use different formatting for items and \
@@ -451,6 +477,63 @@ mod test {
// Options that are used by the tests
stable_option: bool, false, true, "A stable option";
unstable_option: bool, false, false, "An unstable option";
+ partially_unstable_option: PartiallyUnstableOption, PartiallyUnstableOption::V1, true,
+ "A partially unstable option";
+ }
+
+ #[cfg(test)]
+ mod partially_unstable_option {
+ use super::{Config, PartialConfig, PartiallyUnstableOption};
+ use rustfmt_config_proc_macro::{nightly_only_test, stable_only_test};
+ use std::path::Path;
+
+ /// From the config file, we can fill with a stable variant
+ #[test]
+ fn test_from_toml_stable_value() {
+ let toml = r#"
+ partially_unstable_option = "V2"
+ "#;
+ let partial_config: PartialConfig = toml::from_str(toml).unwrap();
+ let config = Config::default();
+ let config = config.fill_from_parsed_config(partial_config, Path::new(""));
+ assert_eq!(
+ config.partially_unstable_option(),
+ PartiallyUnstableOption::V2
+ );
+ }
+
+ /// From the config file, we cannot fill with an unstable variant (stable only)
+ #[stable_only_test]
+ #[test]
+ fn test_from_toml_unstable_value_on_stable() {
+ let toml = r#"
+ partially_unstable_option = "V3"
+ "#;
+ let partial_config: PartialConfig = toml::from_str(toml).unwrap();
+ let config = Config::default();
+ let config = config.fill_from_parsed_config(partial_config, Path::new(""));
+ assert_eq!(
+ config.partially_unstable_option(),
+ // default value from config, i.e. fill failed
+ PartiallyUnstableOption::V1
+ );
+ }
+
+ /// From the config file, we can fill with an unstable variant (nightly only)
+ #[nightly_only_test]
+ #[test]
+ fn test_from_toml_unstable_value_on_nightly() {
+ let toml = r#"
+ partially_unstable_option = "V3"
+ "#;
+ let partial_config: PartialConfig = toml::from_str(toml).unwrap();
+ let config = Config::default();
+ let config = config.fill_from_parsed_config(partial_config, Path::new(""));
+ assert_eq!(
+ config.partially_unstable_option(),
+ PartiallyUnstableOption::V3
+ );
+ }
}
}
@@ -489,6 +572,11 @@ mod test {
assert_eq!(config.was_set().verbose(), false);
}
+ const PRINT_DOCS_STABLE_OPTION: &str = "stable_option <boolean> Default: false";
+ const PRINT_DOCS_UNSTABLE_OPTION: &str = "unstable_option <boolean> Default: false (unstable)";
+ const PRINT_DOCS_PARTIALLY_UNSTABLE_OPTION: &str =
+ "partially_unstable_option [V1|V2|V3 (unstable)] Default: V1";
+
#[test]
fn test_print_docs_exclude_unstable() {
use self::mock::Config;
@@ -497,10 +585,9 @@ mod test {
Config::print_docs(&mut output, false);
let s = str::from_utf8(&output).unwrap();
-
- assert_eq!(s.contains("stable_option"), true);
- assert_eq!(s.contains("unstable_option"), false);
- assert_eq!(s.contains("(unstable)"), false);
+ assert_eq!(s.contains(PRINT_DOCS_STABLE_OPTION), true);
+ assert_eq!(s.contains(PRINT_DOCS_UNSTABLE_OPTION), false);
+ assert_eq!(s.contains(PRINT_DOCS_PARTIALLY_UNSTABLE_OPTION), true);
}
#[test]
@@ -511,9 +598,9 @@ mod test {
Config::print_docs(&mut output, true);
let s = str::from_utf8(&output).unwrap();
- assert_eq!(s.contains("stable_option"), true);
- assert_eq!(s.contains("unstable_option"), true);
- assert_eq!(s.contains("(unstable)"), true);
+ assert_eq!(s.contains(PRINT_DOCS_STABLE_OPTION), true);
+ assert_eq!(s.contains(PRINT_DOCS_UNSTABLE_OPTION), true);
+ assert_eq!(s.contains(PRINT_DOCS_PARTIALLY_UNSTABLE_OPTION), true);
}
#[test]
@@ -541,6 +628,7 @@ normalize_doc_attributes = false
format_strings = false
format_macro_matchers = false
format_macro_bodies = true
+skip_macro_invocations = []
hex_literal_case = "Preserve"
empty_item_single_line = true
struct_lit_single_line = true
@@ -567,7 +655,7 @@ enum_discrim_align_threshold = 0
match_arm_blocks = true
match_arm_leading_pipes = "Never"
force_multiline_blocks = false
-fn_args_layout = "Tall"
+fn_params_layout = "Tall"
brace_style = "SameLineWhere"
control_brace_style = "AlwaysSameLine"
trailing_semicolon = true
@@ -921,4 +1009,45 @@ make_backup = false
assert_eq!(config.single_line_if_else_max_width(), 100);
}
}
+
+ #[cfg(test)]
+ mod partially_unstable_option {
+ use super::mock::{Config, PartiallyUnstableOption};
+ use super::*;
+
+ /// From the command line, we can override with a stable variant.
+ #[test]
+ fn test_override_stable_value() {
+ let mut config = Config::default();
+ config.override_value("partially_unstable_option", "V2");
+ assert_eq!(
+ config.partially_unstable_option(),
+ PartiallyUnstableOption::V2
+ );
+ }
+
+ /// From the command line, we can override with an unstable variant.
+ #[test]
+ fn test_override_unstable_value() {
+ let mut config = Config::default();
+ config.override_value("partially_unstable_option", "V3");
+ assert_eq!(
+ config.partially_unstable_option(),
+ PartiallyUnstableOption::V3
+ );
+ }
+ }
+
+ #[test]
+ fn test_override_skip_macro_invocations() {
+ let mut config = Config::default();
+ config.override_value("skip_macro_invocations", r#"["*", "println"]"#);
+ assert_eq!(
+ config.skip_macro_invocations(),
+ MacroSelectors(vec![
+ MacroSelector::All,
+ MacroSelector::Name(MacroName::new("println".to_owned()))
+ ])
+ );
+ }
}
diff --git a/src/tools/rustfmt/src/expr.rs b/src/tools/rustfmt/src/expr.rs
index 868ff045a..3f0f217f8 100644
--- a/src/tools/rustfmt/src/expr.rs
+++ b/src/tools/rustfmt/src/expr.rs
@@ -29,9 +29,9 @@ use crate::spanned::Spanned;
use crate::string::{rewrite_string, StringFormat};
use crate::types::{rewrite_path, PathContext};
use crate::utils::{
- colon_spaces, contains_skip, count_newlines, first_line_ends_with, inner_attributes,
- last_line_extendable, last_line_width, mk_sp, outer_attributes, semicolon_for_expr,
- unicode_str_width, wrap_str,
+ colon_spaces, contains_skip, count_newlines, filtered_str_fits, first_line_ends_with,
+ inner_attributes, last_line_extendable, last_line_width, mk_sp, outer_attributes,
+ semicolon_for_expr, unicode_str_width, wrap_str,
};
use crate::vertical::rewrite_with_alignment;
use crate::visitor::FmtVisitor;
@@ -400,7 +400,10 @@ pub(crate) fn format_expr(
}
}
ast::ExprKind::Underscore => Some("_".to_owned()),
- ast::ExprKind::IncludedBytes(..) => unreachable!(),
+ ast::ExprKind::FormatArgs(..) | ast::ExprKind::IncludedBytes(..) => {
+ // These do not occur in the AST because macros aren't expanded.
+ unreachable!()
+ }
ast::ExprKind::Err => None,
};
@@ -2050,8 +2053,7 @@ fn choose_rhs<R: Rewrite>(
match (orig_rhs, new_rhs) {
(Some(ref orig_rhs), Some(ref new_rhs))
- if wrap_str(new_rhs.clone(), context.config.max_width(), new_shape)
- .is_none() =>
+ if !filtered_str_fits(&new_rhs, context.config.max_width(), new_shape) =>
{
Some(format!("{}{}", before_space_str, orig_rhs))
}
diff --git a/src/tools/rustfmt/src/imports.rs b/src/tools/rustfmt/src/imports.rs
index d9dc8d004..339e5cef5 100644
--- a/src/tools/rustfmt/src/imports.rs
+++ b/src/tools/rustfmt/src/imports.rs
@@ -251,8 +251,8 @@ fn flatten_use_trees(
use_trees: Vec<UseTree>,
import_granularity: ImportGranularity,
) -> Vec<UseTree> {
- // Return non-sorted single occurance of the use-trees text string;
- // order is by first occurance of the use-tree.
+ // Return non-sorted single occurrence of the use-trees text string;
+ // order is by first occurrence of the use-tree.
use_trees
.into_iter()
.flat_map(|tree| tree.flatten(import_granularity))
diff --git a/src/tools/rustfmt/src/items.rs b/src/tools/rustfmt/src/items.rs
index a2a73f0a5..25e8a0248 100644
--- a/src/tools/rustfmt/src/items.rs
+++ b/src/tools/rustfmt/src/items.rs
@@ -1084,7 +1084,11 @@ pub(crate) fn format_trait(
let item_snippet = context.snippet(item.span);
if let Some(lo) = item_snippet.find('/') {
// 1 = `{`
- let comment_hi = body_lo - BytePos(1);
+ let comment_hi = if generics.params.len() > 0 {
+ generics.span.lo() - BytePos(1)
+ } else {
+ body_lo - BytePos(1)
+ };
let comment_lo = item.span.lo() + BytePos(lo as u32);
if comment_lo < comment_hi {
match recover_missing_comment_in_span(
@@ -1241,7 +1245,7 @@ fn format_unit_struct(
) -> Option<String> {
let header_str = format_header(context, p.prefix, p.ident, p.vis, offset);
let generics_str = if let Some(generics) = p.generics {
- let hi = context.snippet_provider.span_before(p.span, ";");
+ let hi = context.snippet_provider.span_before_last(p.span, ";");
format_generics(
context,
generics,
@@ -2602,7 +2606,7 @@ fn rewrite_params(
&param_items,
context
.config
- .fn_args_layout()
+ .fn_params_layout()
.to_list_tactic(param_items.len()),
Separator::Comma,
one_line_budget,
diff --git a/src/tools/rustfmt/src/lib.rs b/src/tools/rustfmt/src/lib.rs
index 0c27bcacf..b27405efd 100644
--- a/src/tools/rustfmt/src/lib.rs
+++ b/src/tools/rustfmt/src/lib.rs
@@ -23,6 +23,7 @@ extern crate rustc_expand;
extern crate rustc_parse;
extern crate rustc_session;
extern crate rustc_span;
+extern crate thin_vec;
// Necessary to pull in object code as the rest of the rustc crates are shipped only as rmeta
// files.
diff --git a/src/tools/rustfmt/src/lists.rs b/src/tools/rustfmt/src/lists.rs
index e87850507..a878e6cf9 100644
--- a/src/tools/rustfmt/src/lists.rs
+++ b/src/tools/rustfmt/src/lists.rs
@@ -297,9 +297,9 @@ where
} else {
inner_item.as_ref()
};
- let mut item_last_line_width = item_last_line.len() + item_sep_len;
+ let mut item_last_line_width = unicode_str_width(item_last_line) + item_sep_len;
if item_last_line.starts_with(&**indent_str) {
- item_last_line_width -= indent_str.len();
+ item_last_line_width -= unicode_str_width(indent_str);
}
if !item.is_substantial() {
@@ -449,7 +449,7 @@ where
} else if starts_with_newline(comment) {
false
} else {
- comment.trim().contains('\n') || comment.trim().len() > width
+ comment.trim().contains('\n') || unicode_str_width(comment.trim()) > width
};
rewrite_comment(
@@ -465,7 +465,7 @@ where
if !starts_with_newline(comment) {
if formatting.align_comments {
let mut comment_alignment =
- post_comment_alignment(item_max_width, inner_item.len());
+ post_comment_alignment(item_max_width, unicode_str_width(inner_item));
if first_line_width(&formatted_comment)
+ last_line_width(&result)
+ comment_alignment
@@ -475,7 +475,7 @@ where
item_max_width = None;
formatted_comment = rewrite_post_comment(&mut item_max_width)?;
comment_alignment =
- post_comment_alignment(item_max_width, inner_item.len());
+ post_comment_alignment(item_max_width, unicode_str_width(inner_item));
}
for _ in 0..=comment_alignment {
result.push(' ');
@@ -533,7 +533,7 @@ where
let mut first = true;
for item in items.clone().into_iter().skip(i) {
let item = item.as_ref();
- let inner_item_width = item.inner_as_ref().len();
+ let inner_item_width = unicode_str_width(item.inner_as_ref());
if !first
&& (item.is_different_group()
|| item.post_comment.is_none()
@@ -552,8 +552,8 @@ where
max_width
}
-fn post_comment_alignment(item_max_width: Option<usize>, inner_item_len: usize) -> usize {
- item_max_width.unwrap_or(0).saturating_sub(inner_item_len)
+fn post_comment_alignment(item_max_width: Option<usize>, inner_item_width: usize) -> usize {
+ item_max_width.unwrap_or(0).saturating_sub(inner_item_width)
}
pub(crate) struct ListItems<'a, I, F1, F2, F3>
diff --git a/src/tools/rustfmt/src/macros.rs b/src/tools/rustfmt/src/macros.rs
index df9493880..7978d8cba 100644
--- a/src/tools/rustfmt/src/macros.rs
+++ b/src/tools/rustfmt/src/macros.rs
@@ -13,7 +13,7 @@ use std::collections::HashMap;
use std::panic::{catch_unwind, AssertUnwindSafe};
use rustc_ast::token::{BinOpToken, Delimiter, Token, TokenKind};
-use rustc_ast::tokenstream::{Cursor, TokenStream, TokenTree};
+use rustc_ast::tokenstream::{TokenStream, TokenTree, TokenTreeCursor};
use rustc_ast::{ast, ptr};
use rustc_ast_pretty::pprust;
use rustc_span::{
@@ -35,8 +35,8 @@ use crate::shape::{Indent, Shape};
use crate::source_map::SpanUtils;
use crate::spanned::Spanned;
use crate::utils::{
- format_visibility, indent_next_line, is_empty_line, mk_sp, remove_trailing_white_spaces,
- rewrite_ident, trim_left_preserve_layout, wrap_str, NodeIdExt,
+ filtered_str_fits, format_visibility, indent_next_line, is_empty_line, mk_sp,
+ remove_trailing_white_spaces, rewrite_ident, trim_left_preserve_layout, NodeIdExt,
};
use crate::visitor::FmtVisitor;
@@ -157,7 +157,8 @@ pub(crate) fn rewrite_macro(
) -> Option<String> {
let should_skip = context
.skip_context
- .skip_macro(context.snippet(mac.path.span));
+ .macros
+ .skip(context.snippet(mac.path.span));
if should_skip {
None
} else {
@@ -735,7 +736,7 @@ impl MacroArgParser {
self.buf.clear();
}
- fn add_meta_variable(&mut self, iter: &mut Cursor) -> Option<()> {
+ fn add_meta_variable(&mut self, iter: &mut TokenTreeCursor) -> Option<()> {
match iter.next() {
Some(TokenTree::Token(
Token {
@@ -767,7 +768,7 @@ impl MacroArgParser {
&mut self,
inner: Vec<ParsedMacroArg>,
delim: Delimiter,
- iter: &mut Cursor,
+ iter: &mut TokenTreeCursor,
) -> Option<()> {
let mut buffer = String::new();
let mut first = true;
@@ -1120,7 +1121,7 @@ pub(crate) fn macro_style(mac: &ast::MacCall, context: &RewriteContext<'_>) -> D
// Currently we do not attempt to parse any further than that.
#[derive(new)]
struct MacroParser {
- toks: Cursor,
+ toks: TokenTreeCursor,
}
impl MacroParser {
@@ -1265,15 +1266,14 @@ impl MacroBranch {
}
}
};
- let new_body = wrap_str(
- new_body_snippet.snippet.to_string(),
- config.max_width(),
- shape,
- )?;
+
+ if !filtered_str_fits(&new_body_snippet.snippet, config.max_width(), shape) {
+ return None;
+ }
// Indent the body since it is in a block.
let indent_str = body_indent.to_string(&config);
- let mut new_body = LineClasses::new(new_body.trim_end())
+ let mut new_body = LineClasses::new(new_body_snippet.snippet.trim_end())
.enumerate()
.fold(
(String::new(), true),
diff --git a/src/tools/rustfmt/src/modules.rs b/src/tools/rustfmt/src/modules.rs
index 7a0d1736c..af9a154a6 100644
--- a/src/tools/rustfmt/src/modules.rs
+++ b/src/tools/rustfmt/src/modules.rs
@@ -6,6 +6,7 @@ use rustc_ast::ast;
use rustc_ast::visit::Visitor;
use rustc_span::symbol::{self, sym, Symbol};
use rustc_span::Span;
+use thin_vec::ThinVec;
use thiserror::Error;
use crate::attr::MetaVisitor;
@@ -25,7 +26,7 @@ type FileModMap<'ast> = BTreeMap<FileName, Module<'ast>>;
#[derive(Debug, Clone)]
pub(crate) struct Module<'a> {
ast_mod_kind: Option<Cow<'a, ast::ModKind>>,
- pub(crate) items: Cow<'a, Vec<rustc_ast::ptr::P<ast::Item>>>,
+ pub(crate) items: Cow<'a, ThinVec<rustc_ast::ptr::P<ast::Item>>>,
inner_attr: ast::AttrVec,
pub(crate) span: Span,
}
@@ -34,7 +35,7 @@ impl<'a> Module<'a> {
pub(crate) fn new(
mod_span: Span,
ast_mod_kind: Option<Cow<'a, ast::ModKind>>,
- mod_items: Cow<'a, Vec<rustc_ast::ptr::P<ast::Item>>>,
+ mod_items: Cow<'a, ThinVec<rustc_ast::ptr::P<ast::Item>>>,
mod_attrs: Cow<'a, ast::AttrVec>,
) -> Self {
let inner_attr = mod_attrs
@@ -157,7 +158,7 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> {
Module::new(
module_item.item.span,
Some(Cow::Owned(sub_mod_kind.clone())),
- Cow::Owned(vec![]),
+ Cow::Owned(ThinVec::new()),
Cow::Owned(ast::AttrVec::new()),
),
)?;
@@ -169,7 +170,7 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> {
/// Visit modules defined inside macro calls.
fn visit_mod_outside_ast(
&mut self,
- items: Vec<rustc_ast::ptr::P<ast::Item>>,
+ items: ThinVec<rustc_ast::ptr::P<ast::Item>>,
) -> Result<(), ModuleResolutionError> {
for item in items {
if is_cfg_if(&item) {
@@ -184,7 +185,7 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> {
Module::new(
span,
Some(Cow::Owned(sub_mod_kind.clone())),
- Cow::Owned(vec![]),
+ Cow::Owned(ThinVec::new()),
Cow::Owned(ast::AttrVec::new()),
),
)?;
@@ -210,7 +211,7 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> {
Module::new(
span,
Some(Cow::Borrowed(sub_mod_kind)),
- Cow::Owned(vec![]),
+ Cow::Owned(ThinVec::new()),
Cow::Borrowed(&item.attrs),
),
)?;
diff --git a/src/tools/rustfmt/src/parse/parser.rs b/src/tools/rustfmt/src/parse/parser.rs
index e0bd06551..7ab042506 100644
--- a/src/tools/rustfmt/src/parse/parser.rs
+++ b/src/tools/rustfmt/src/parse/parser.rs
@@ -6,6 +6,7 @@ use rustc_ast::{ast, ptr};
use rustc_errors::Diagnostic;
use rustc_parse::{new_parser_from_file, parser::Parser as RawParser};
use rustc_span::{sym, Span};
+use thin_vec::ThinVec;
use crate::attr::first_attr_value_str_by_name;
use crate::parse::session::ParseSess;
@@ -109,7 +110,7 @@ impl<'a> Parser<'a> {
sess: &'a ParseSess,
path: &Path,
span: Span,
- ) -> Result<(ast::AttrVec, Vec<ptr::P<ast::Item>>, Span), ParserError> {
+ ) -> Result<(ast::AttrVec, ThinVec<ptr::P<ast::Item>>, Span), ParserError> {
let result = catch_unwind(AssertUnwindSafe(|| {
let mut parser = new_parser_from_file(sess.inner(), path, Some(span));
match parser.parse_mod(&TokenKind::Eof) {
diff --git a/src/tools/rustfmt/src/parse/session.rs b/src/tools/rustfmt/src/parse/session.rs
index 6bfec79cd..a64963db6 100644
--- a/src/tools/rustfmt/src/parse/session.rs
+++ b/src/tools/rustfmt/src/parse/session.rs
@@ -4,7 +4,7 @@ use std::sync::atomic::{AtomicBool, Ordering};
use rustc_data_structures::sync::{Lrc, Send};
use rustc_errors::emitter::{Emitter, EmitterWriter};
use rustc_errors::translation::Translate;
-use rustc_errors::{ColorConfig, Diagnostic, Handler, Level as DiagnosticLevel};
+use rustc_errors::{ColorConfig, Diagnostic, Handler, Level as DiagnosticLevel, TerminalUrl};
use rustc_session::parse::ParseSess as RawParseSess;
use rustc_span::{
source_map::{FilePathMapping, SourceMap},
@@ -123,8 +123,10 @@ fn default_handler(
let emitter = if hide_parse_errors {
silent_emitter()
} else {
- let fallback_bundle =
- rustc_errors::fallback_fluent_bundle(rustc_errors::DEFAULT_LOCALE_RESOURCES, false);
+ let fallback_bundle = rustc_errors::fallback_fluent_bundle(
+ rustc_driver::DEFAULT_LOCALE_RESOURCES.to_vec(),
+ false,
+ );
Box::new(EmitterWriter::stderr(
color_cfg,
Some(source_map.clone()),
@@ -135,6 +137,7 @@ fn default_handler(
None,
false,
false,
+ TerminalUrl::No,
))
};
Handler::with_emitter(
diff --git a/src/tools/rustfmt/src/skip.rs b/src/tools/rustfmt/src/skip.rs
index 032922d42..68f85b2ad 100644
--- a/src/tools/rustfmt/src/skip.rs
+++ b/src/tools/rustfmt/src/skip.rs
@@ -2,33 +2,84 @@
use rustc_ast::ast;
use rustc_ast_pretty::pprust;
+use std::collections::HashSet;
-/// Take care of skip name stack. You can update it by attributes slice or
-/// by other context. Query this context to know if you need skip a block.
+/// Track which blocks of code are to be skipped when formatting.
+///
+/// You can update it by:
+///
+/// - attributes slice
+/// - manually feeding values into the underlying contexts
+///
+/// Query this context to know if you need to skip a block.
#[derive(Default, Clone)]
pub(crate) struct SkipContext {
- macros: Vec<String>,
- attributes: Vec<String>,
+ pub(crate) macros: SkipNameContext,
+ pub(crate) attributes: SkipNameContext,
}
impl SkipContext {
pub(crate) fn update_with_attrs(&mut self, attrs: &[ast::Attribute]) {
- self.macros.append(&mut get_skip_names("macros", attrs));
- self.attributes
- .append(&mut get_skip_names("attributes", attrs));
+ self.macros.extend(get_skip_names("macros", attrs));
+ self.attributes.extend(get_skip_names("attributes", attrs));
}
- pub(crate) fn update(&mut self, mut other: SkipContext) {
- self.macros.append(&mut other.macros);
- self.attributes.append(&mut other.attributes);
+ pub(crate) fn update(&mut self, other: SkipContext) {
+ let SkipContext { macros, attributes } = other;
+ self.macros.update(macros);
+ self.attributes.update(attributes);
+ }
+}
+
+/// Track which names to skip.
+///
+/// Query this context with a string to know whether to skip it.
+#[derive(Clone)]
+pub(crate) enum SkipNameContext {
+ All,
+ Values(HashSet<String>),
+}
+
+impl Default for SkipNameContext {
+ fn default() -> Self {
+ Self::Values(Default::default())
+ }
+}
+
+impl Extend<String> for SkipNameContext {
+ fn extend<T: IntoIterator<Item = String>>(&mut self, iter: T) {
+ match self {
+ Self::All => {}
+ Self::Values(values) => values.extend(iter),
+ }
+ }
+}
+
+impl SkipNameContext {
+ pub(crate) fn update(&mut self, other: Self) {
+ match (self, other) {
+ // If we're already skipping everything, nothing more can be added
+ (Self::All, _) => {}
+ // If we want to skip all, set it
+ (this, Self::All) => {
+ *this = Self::All;
+ }
+ // If we have some new values to skip, add them
+ (Self::Values(existing_values), Self::Values(new_values)) => {
+ existing_values.extend(new_values)
+ }
+ }
}
- pub(crate) fn skip_macro(&self, name: &str) -> bool {
- self.macros.iter().any(|n| n == name)
+ pub(crate) fn skip(&self, name: &str) -> bool {
+ match self {
+ Self::All => true,
+ Self::Values(values) => values.contains(name),
+ }
}
- pub(crate) fn skip_attribute(&self, name: &str) -> bool {
- self.attributes.iter().any(|n| n == name)
+ pub(crate) fn skip_all(&mut self) {
+ *self = Self::All;
}
}
diff --git a/src/tools/rustfmt/src/test/configuration_snippet.rs b/src/tools/rustfmt/src/test/configuration_snippet.rs
index c8fda7c85..c70b3c5fa 100644
--- a/src/tools/rustfmt/src/test/configuration_snippet.rs
+++ b/src/tools/rustfmt/src/test/configuration_snippet.rs
@@ -27,8 +27,13 @@ impl ConfigurationSection {
lazy_static! {
static ref CONFIG_NAME_REGEX: regex::Regex =
regex::Regex::new(r"^## `([^`]+)`").expect("failed creating configuration pattern");
+ // Configuration values, which will be passed to `from_str`:
+ //
+ // - must be prefixed with `####`
+ // - must be wrapped in backticks
+ // - may by wrapped in double quotes (which will be stripped)
static ref CONFIG_VALUE_REGEX: regex::Regex =
- regex::Regex::new(r#"^#### `"?([^`"]+)"?`"#)
+ regex::Regex::new(r#"^#### `"?([^`]+?)"?`"#)
.expect("failed creating configuration value pattern");
}
diff --git a/src/tools/rustfmt/src/test/mod.rs b/src/tools/rustfmt/src/test/mod.rs
index 6b5bc2b30..cfad4a8ed 100644
--- a/src/tools/rustfmt/src/test/mod.rs
+++ b/src/tools/rustfmt/src/test/mod.rs
@@ -982,11 +982,7 @@ fn rustfmt() -> PathBuf {
assert!(
me.is_file() || me.with_extension("exe").is_file(),
"{}",
- if cfg!(release) {
- "no rustfmt bin, try running `cargo build --release` before testing"
- } else {
- "no rustfmt bin, try running `cargo build` before testing"
- }
+ "no rustfmt bin, try running `cargo build` or `cargo build --release` before testing"
);
me
}
diff --git a/src/tools/rustfmt/src/types.rs b/src/tools/rustfmt/src/types.rs
index c1991e8d2..01e2fb6e6 100644
--- a/src/tools/rustfmt/src/types.rs
+++ b/src/tools/rustfmt/src/types.rs
@@ -941,6 +941,28 @@ fn join_bounds_inner(
ast::GenericBound::Trait(..) => last_line_extendable(s),
};
+ // Whether a GenericBound item is a PathSegment segment that includes internal array
+ // that contains more than one item
+ let is_item_with_multi_items_array = |item: &ast::GenericBound| match item {
+ ast::GenericBound::Trait(ref poly_trait_ref, ..) => {
+ let segments = &poly_trait_ref.trait_ref.path.segments;
+ if segments.len() > 1 {
+ true
+ } else {
+ if let Some(args_in) = &segments[0].args {
+ matches!(
+ args_in.deref(),
+ ast::GenericArgs::AngleBracketed(bracket_args)
+ if bracket_args.args.len() > 1
+ )
+ } else {
+ false
+ }
+ }
+ }
+ _ => false,
+ };
+
let result = items.iter().enumerate().try_fold(
(String::new(), None, false),
|(strs, prev_trailing_span, prev_extendable), (i, item)| {
@@ -1035,10 +1057,24 @@ fn join_bounds_inner(
},
)?;
- if !force_newline
- && items.len() > 1
- && (result.0.contains('\n') || result.0.len() > shape.width)
- {
+ // Whether to retry with a forced newline:
+ // Only if result is not already multiline and did not exceed line width,
+ // and either there is more than one item;
+ // or the single item is of type `Trait`,
+ // and any of the internal arrays contains more than one item;
+ let retry_with_force_newline = match context.config.version() {
+ Version::One => {
+ !force_newline
+ && items.len() > 1
+ && (result.0.contains('\n') || result.0.len() > shape.width)
+ }
+ Version::Two if force_newline => false,
+ Version::Two if (!result.0.contains('\n') && result.0.len() <= shape.width) => false,
+ Version::Two if items.len() > 1 => true,
+ Version::Two => is_item_with_multi_items_array(&items[0]),
+ };
+
+ if retry_with_force_newline {
join_bounds_inner(context, shape, items, need_indent, true)
} else {
Some(result.0)
diff --git a/src/tools/rustfmt/src/utils.rs b/src/tools/rustfmt/src/utils.rs
index 3e884419f..1e89f3ae7 100644
--- a/src/tools/rustfmt/src/utils.rs
+++ b/src/tools/rustfmt/src/utils.rs
@@ -384,14 +384,15 @@ macro_rules! skip_out_of_file_lines_range_visitor {
// Wraps String in an Option. Returns Some when the string adheres to the
// Rewrite constraints defined for the Rewrite trait and None otherwise.
pub(crate) fn wrap_str(s: String, max_width: usize, shape: Shape) -> Option<String> {
- if is_valid_str(&filter_normal_code(&s), max_width, shape) {
+ if filtered_str_fits(&s, max_width, shape) {
Some(s)
} else {
None
}
}
-fn is_valid_str(snippet: &str, max_width: usize, shape: Shape) -> bool {
+pub(crate) fn filtered_str_fits(snippet: &str, max_width: usize, shape: Shape) -> bool {
+ let snippet = &filter_normal_code(snippet);
if !snippet.is_empty() {
// First line must fits with `shape.width`.
if first_line_width(snippet) > shape.width {
@@ -462,6 +463,7 @@ pub(crate) fn first_line_ends_with(s: &str, c: char) -> bool {
pub(crate) fn is_block_expr(context: &RewriteContext<'_>, expr: &ast::Expr, repr: &str) -> bool {
match expr.kind {
ast::ExprKind::MacCall(..)
+ | ast::ExprKind::FormatArgs(..)
| ast::ExprKind::Call(..)
| ast::ExprKind::MethodCall(..)
| ast::ExprKind::Array(..)
diff --git a/src/tools/rustfmt/src/visitor.rs b/src/tools/rustfmt/src/visitor.rs
index 9c3cc7820..f4d84d138 100644
--- a/src/tools/rustfmt/src/visitor.rs
+++ b/src/tools/rustfmt/src/visitor.rs
@@ -8,7 +8,7 @@ use rustc_span::{symbol, BytePos, Pos, Span};
use crate::attr::*;
use crate::comment::{contains_comment, rewrite_comment, CodeCharKind, CommentCodeSlices};
use crate::config::Version;
-use crate::config::{BraceStyle, Config};
+use crate::config::{BraceStyle, Config, MacroSelector};
use crate::coverage::transform_missing_snippet;
use crate::items::{
format_impl, format_trait, format_trait_alias, is_mod_decl, is_use_item, rewrite_extern_crate,
@@ -770,6 +770,15 @@ impl<'b, 'a: 'b> FmtVisitor<'a> {
snippet_provider: &'a SnippetProvider,
report: FormatReport,
) -> FmtVisitor<'a> {
+ let mut skip_context = SkipContext::default();
+ let mut macro_names = Vec::new();
+ for macro_selector in config.skip_macro_invocations().0 {
+ match macro_selector {
+ MacroSelector::Name(name) => macro_names.push(name.to_string()),
+ MacroSelector::All => skip_context.macros.skip_all(),
+ }
+ }
+ skip_context.macros.extend(macro_names);
FmtVisitor {
parent_context: None,
parse_sess: parse_session,
@@ -784,7 +793,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> {
is_macro_def: false,
macro_rewrite_failure: false,
report,
- skip_context: Default::default(),
+ skip_context,
}
}
diff --git a/src/tools/rustfmt/tests/cargo-fmt/main.rs b/src/tools/rustfmt/tests/cargo-fmt/main.rs
index 348876cd2..701c36fad 100644
--- a/src/tools/rustfmt/tests/cargo-fmt/main.rs
+++ b/src/tools/rustfmt/tests/cargo-fmt/main.rs
@@ -4,6 +4,8 @@ use std::env;
use std::path::Path;
use std::process::Command;
+use rustfmt_config_proc_macro::rustfmt_only_ci_test;
+
/// Run the cargo-fmt executable and return its output.
fn cargo_fmt(args: &[&str]) -> (String, String) {
let mut bin_dir = env::current_exe().unwrap();
@@ -47,7 +49,7 @@ macro_rules! assert_that {
};
}
-#[ignore]
+#[rustfmt_only_ci_test]
#[test]
fn version() {
assert_that!(&["--version"], starts_with("rustfmt "));
@@ -56,7 +58,7 @@ fn version() {
assert_that!(&["--", "--version"], starts_with("rustfmt "));
}
-#[ignore]
+#[rustfmt_only_ci_test]
#[test]
fn print_config() {
assert_that!(
@@ -65,7 +67,7 @@ fn print_config() {
);
}
-#[ignore]
+#[rustfmt_only_ci_test]
#[test]
fn rustfmt_help() {
assert_that!(&["--", "--help"], contains("Format Rust code"));
@@ -73,7 +75,7 @@ fn rustfmt_help() {
assert_that!(&["--", "--help=config"], contains("Configuration Options:"));
}
-#[ignore]
+#[rustfmt_only_ci_test]
#[test]
fn cargo_fmt_out_of_line_test_modules() {
// See also https://github.com/rust-lang/rustfmt/issues/5119
@@ -96,3 +98,22 @@ fn cargo_fmt_out_of_line_test_modules() {
assert!(stdout.contains(&format!("Diff in {}", path.display())))
}
}
+
+#[rustfmt_only_ci_test]
+#[test]
+fn cargo_fmt_emits_error_on_line_overflow_true() {
+ // See also https://github.com/rust-lang/rustfmt/issues/3164
+ let args = [
+ "--check",
+ "--manifest-path",
+ "tests/cargo-fmt/source/issue_3164/Cargo.toml",
+ "--",
+ "--config",
+ "error_on_line_overflow=true",
+ ];
+
+ let (_stdout, stderr) = cargo_fmt(&args);
+ assert!(stderr.contains(
+ "line formatted, but exceeded maximum width (maximum: 100 (see `max_width` option)"
+ ))
+}
diff --git a/src/tools/rustfmt/tests/cargo-fmt/source/issue_3164/Cargo.toml b/src/tools/rustfmt/tests/cargo-fmt/source/issue_3164/Cargo.toml
new file mode 100644
index 000000000..580ef7e6e
--- /dev/null
+++ b/src/tools/rustfmt/tests/cargo-fmt/source/issue_3164/Cargo.toml
@@ -0,0 +1,8 @@
+[package]
+name = "issue_3164"
+version = "0.1.0"
+edition = "2021"
+
+# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
+
+[dependencies]
diff --git a/src/tools/rustfmt/tests/cargo-fmt/source/issue_3164/src/main.rs b/src/tools/rustfmt/tests/cargo-fmt/source/issue_3164/src/main.rs
new file mode 100644
index 000000000..9330107ac
--- /dev/null
+++ b/src/tools/rustfmt/tests/cargo-fmt/source/issue_3164/src/main.rs
@@ -0,0 +1,13 @@
+#[allow(unused_macros)]
+macro_rules! foo {
+ ($id:ident) => {
+ macro_rules! bar {
+ ($id2:tt) => {
+ #[cfg(any(target_feature = $id2, target_feature = $id2, target_feature = $id2, target_feature = $id2, target_feature = $id2))]
+ fn $id() {}
+ };
+ }
+ };
+}
+
+fn main() {}
diff --git a/src/tools/rustfmt/tests/config/small_tabs.toml b/src/tools/rustfmt/tests/config/small_tabs.toml
index c3cfd3431..4c3710089 100644
--- a/src/tools/rustfmt/tests/config/small_tabs.toml
+++ b/src/tools/rustfmt/tests/config/small_tabs.toml
@@ -3,7 +3,7 @@ comment_width = 80
tab_spaces = 2
newline_style = "Unix"
brace_style = "SameLineWhere"
-fn_args_layout = "Tall"
+fn_params_layout = "Tall"
trailing_comma = "Vertical"
indent_style = "Block"
reorder_imports = false
diff --git a/src/tools/rustfmt/tests/mod-resolver/issue-5198/lib/c/d/explanation.txt b/src/tools/rustfmt/tests/mod-resolver/issue-5198/lib/c/d/explanation.txt
index 92c9e3021..254102eba 100644
--- a/src/tools/rustfmt/tests/mod-resolver/issue-5198/lib/c/d/explanation.txt
+++ b/src/tools/rustfmt/tests/mod-resolver/issue-5198/lib/c/d/explanation.txt
@@ -9,7 +9,7 @@ The directory name './lib/c/d/' conflicts with the './lib/c/d.rs' file name.
* mod g;
Module resolution will fail if we look for './lib/c/d/e.rs' or './lib/c/d/e/mod.rs',
-so we should fall back to looking for './lib/c/e.rs', which correctly finds the modlue, that
+so we should fall back to looking for './lib/c/e.rs', which correctly finds the module, that
rustfmt should format.
'./lib/c/d/f.rs' and './lib/c/d/g/mod.rs' exist at the default submodule paths so we should be able
diff --git a/src/tools/rustfmt/tests/mod-resolver/issue-5198/lib/explanation.txt b/src/tools/rustfmt/tests/mod-resolver/issue-5198/lib/explanation.txt
index d436a8076..90464def8 100644
--- a/src/tools/rustfmt/tests/mod-resolver/issue-5198/lib/explanation.txt
+++ b/src/tools/rustfmt/tests/mod-resolver/issue-5198/lib/explanation.txt
@@ -9,7 +9,7 @@ The directory name './lib' conflicts with the './lib.rs' file name.
* mod c;
Module resolution will fail if we look for './lib/a.rs' or './lib/a/mod.rs',
-so we should fall back to looking for './a.rs', which correctly finds the modlue that
+so we should fall back to looking for './a.rs', which correctly finds the module that
rustfmt should format.
'./lib/b.rs' and './lib/c/mod.rs' exist at the default submodule paths so we should be able
diff --git a/src/tools/rustfmt/tests/rustfmt/main.rs b/src/tools/rustfmt/tests/rustfmt/main.rs
index 4c6d52726..7ff301e80 100644
--- a/src/tools/rustfmt/tests/rustfmt/main.rs
+++ b/src/tools/rustfmt/tests/rustfmt/main.rs
@@ -5,6 +5,8 @@ use std::fs::remove_file;
use std::path::Path;
use std::process::Command;
+use rustfmt_config_proc_macro::rustfmt_only_ci_test;
+
/// Run the rustfmt executable and return its output.
fn rustfmt(args: &[&str]) -> (String, String) {
let mut bin_dir = env::current_exe().unwrap();
@@ -47,7 +49,7 @@ macro_rules! assert_that {
};
}
-#[ignore]
+#[rustfmt_only_ci_test]
#[test]
fn print_config() {
assert_that!(
@@ -76,7 +78,7 @@ fn print_config() {
remove_file("minimal-config").unwrap();
}
-#[ignore]
+#[rustfmt_only_ci_test]
#[test]
fn inline_config() {
// single invocation
@@ -157,3 +159,18 @@ fn mod_resolution_error_path_attribute_does_not_exist() {
// The path attribute points to a file that does not exist
assert!(stderr.contains("does_not_exist.rs does not exist"));
}
+
+#[test]
+fn rustfmt_emits_error_on_line_overflow_true() {
+ // See also https://github.com/rust-lang/rustfmt/issues/3164
+ let args = [
+ "--config",
+ "error_on_line_overflow=true",
+ "tests/cargo-fmt/source/issue_3164/src/main.rs",
+ ];
+
+ let (_stdout, stderr) = rustfmt(&args);
+ assert!(stderr.contains(
+ "line formatted, but exceeded maximum width (maximum: 100 (see `max_width` option)"
+ ))
+}
diff --git a/src/tools/rustfmt/tests/source/cfg_if/detect/arch/x86.rs b/src/tools/rustfmt/tests/source/cfg_if/detect/arch/x86.rs
index d26f4ee89..131cbb855 100644
--- a/src/tools/rustfmt/tests/source/cfg_if/detect/arch/x86.rs
+++ b/src/tools/rustfmt/tests/source/cfg_if/detect/arch/x86.rs
@@ -329,7 +329,7 @@ pub enum Feature {
tbm,
/// POPCNT (Population Count)
popcnt,
- /// FXSR (Floating-point context fast save and restor)
+ /// FXSR (Floating-point context fast save and restore)
fxsr,
/// XSAVE (Save Processor Extended States)
xsave,
diff --git a/src/tools/rustfmt/tests/source/comments_unicode.rs b/src/tools/rustfmt/tests/source/comments_unicode.rs
new file mode 100644
index 000000000..e65a245ba
--- /dev/null
+++ b/src/tools/rustfmt/tests/source/comments_unicode.rs
@@ -0,0 +1,140 @@
+impl Default for WhitespaceCharacters {
+ fn default() -> Self {
+ Self {
+ space: '·', // U+00B7
+ nbsp: '⍽', // U+237D
+ tab: '→', // U+2192
+ newline: '⏎', // U+23CE
+ }
+ }
+}
+
+const RAINBOWS: &[&str] = &[
+ "rаinЬοѡ", // hue: 0
+ "raіnЬοw", // hue: 2
+ "rаіɴЬow", // hue: 2
+ "raіɴЬoѡ", // hue: 8
+ "ʀainЬow", // hue: 8
+ "ʀaіɴboѡ", // hue: 8
+ "ʀаіnbοw", // hue: 11
+ "rainЬoѡ", // hue: 14
+ "raіɴbow", // hue: 14
+ "rаiɴЬow", // hue: 20
+ "raіnЬow", // hue: 26
+ "ʀaiɴbοw", // hue: 32
+ "raіɴboѡ", // hue: 35
+ "rаiɴbow", // hue: 35
+ "rаіnbοw", // hue: 38
+ "rаinЬow", // hue: 47
+ "ʀaіnboѡ", // hue: 47
+ "ʀaіnЬoѡ", // hue: 47
+ "ʀаіɴbοw", // hue: 53
+ "ʀaіnЬοѡ", // hue: 57
+ "raiɴЬoѡ", // hue: 68
+ "ʀainbοѡ", // hue: 68
+ "ʀаinboѡ", // hue: 68
+ "ʀаiɴbοw", // hue: 68
+ "ʀаіnbow", // hue: 68
+ "rаіnЬοѡ", // hue: 69
+ "ʀainЬοw", // hue: 71
+ "raiɴbow", // hue: 73
+ "raіnЬoѡ", // hue: 74
+ "rаіɴbοw", // hue: 77
+ "raіnЬοѡ", // hue: 81
+ "raiɴЬow", // hue: 83
+ "ʀainbοw", // hue: 83
+ "ʀаinbow", // hue: 83
+ "ʀаiɴbοѡ", // hue: 83
+ "ʀаіnboѡ", // hue: 83
+ "ʀаіɴЬοѡ", // hue: 84
+ "rainЬow", // hue: 85
+ "ʀаiɴЬοw", // hue: 86
+ "ʀаіnbοѡ", // hue: 89
+ "ʀаіnЬοw", // hue: 92
+ "rаiɴbοw", // hue: 95
+ "ʀаіɴbοѡ", // hue: 98
+ "ʀаiɴЬοѡ", // hue: 99
+ "raіnbοw", // hue: 101
+ "ʀаіɴЬοw", // hue: 101
+ "ʀaiɴboѡ", // hue: 104
+ "ʀаinbοѡ", // hue: 104
+ "rаiɴbοѡ", // hue: 107
+ "ʀаinЬοw", // hue: 107
+ "rаiɴЬοw", // hue: 110
+ "rаіnboѡ", // hue: 110
+ "rаіnbοѡ", // hue: 113
+ "ʀainЬοѡ", // hue: 114
+ "rаіnЬοw", // hue: 116
+ "ʀaіɴЬow", // hue: 116
+ "rаinbοw", // hue: 122
+ "ʀаіɴboѡ", // hue: 125
+ "rаinbοѡ", // hue: 131
+ "rainbow", // hue: 134
+ "rаinЬοw", // hue: 134
+ "ʀаiɴboѡ", // hue: 140
+ "rainЬοѡ", // hue: 141
+ "raіɴЬow", // hue: 143
+ "ʀainЬoѡ", // hue: 143
+ "ʀaіɴbow", // hue: 143
+ "ʀainbow", // hue: 148
+ "rаіɴboѡ", // hue: 149
+ "ʀainboѡ", // hue: 155
+ "ʀaіnbow", // hue: 155
+ "ʀaіnЬow", // hue: 155
+ "raiɴbοw", // hue: 158
+ "ʀаiɴЬoѡ", // hue: 158
+ "rainbοw", // hue: 160
+ "rаinbow", // hue: 160
+ "ʀaіɴbοѡ", // hue: 164
+ "ʀаiɴbow", // hue: 164
+ "ʀаіnЬoѡ", // hue: 164
+ "ʀaiɴЬοѡ", // hue: 165
+ "rаiɴboѡ", // hue: 167
+ "ʀaіɴЬοw", // hue: 167
+ "ʀaіɴЬοѡ", // hue: 171
+ "raіnboѡ", // hue: 173
+ "ʀаіɴЬoѡ", // hue: 173
+ "rаіɴbοѡ", // hue: 176
+ "ʀаinЬow", // hue: 176
+ "rаiɴЬοѡ", // hue: 177
+ "rаіɴЬοw", // hue: 179
+ "ʀаinЬoѡ", // hue: 179
+ "ʀаіɴbow", // hue: 179
+ "rаiɴЬoѡ", // hue: 182
+ "raіɴbοѡ", // hue: 188
+ "rаіnЬoѡ", // hue: 188
+ "raiɴЬοѡ", // hue: 189
+ "raіɴЬοw", // hue: 191
+ "ʀaіɴbοw", // hue: 191
+ "ʀаіnЬow", // hue: 191
+ "rainbοѡ", // hue: 194
+ "rаinboѡ", // hue: 194
+ "rаіnbow", // hue: 194
+ "rainЬοw", // hue: 197
+ "rаinЬoѡ", // hue: 206
+ "rаіɴbow", // hue: 206
+ "rаіɴЬοѡ", // hue: 210
+ "ʀaiɴЬow", // hue: 212
+ "raіɴbοw", // hue: 218
+ "rаіnЬow", // hue: 218
+ "ʀaiɴbοѡ", // hue: 221
+ "ʀaiɴЬοw", // hue: 224
+ "ʀaіnbοѡ", // hue: 227
+ "raiɴboѡ", // hue: 230
+ "ʀaіnbοw", // hue: 230
+ "ʀaіnЬοw", // hue: 230
+ "ʀаinЬοѡ", // hue: 231
+ "rainboѡ", // hue: 232
+ "raіnbow", // hue: 232
+ "ʀаіɴЬow", // hue: 233
+ "ʀaіɴЬoѡ", // hue: 239
+ "ʀаіnЬοѡ", // hue: 246
+ "raiɴbοѡ", // hue: 248
+ "ʀаiɴЬow", // hue: 248
+ "raіɴЬοѡ", // hue: 249
+ "raiɴЬοw", // hue: 251
+ "rаіɴЬoѡ", // hue: 251
+ "ʀaiɴbow", // hue: 251
+ "ʀаinbοw", // hue: 251
+ "raіnbοѡ", // hue: 254
+];
diff --git a/src/tools/rustfmt/tests/source/configs/fn_args_layout/compressed.rs b/src/tools/rustfmt/tests/source/configs/fn_params_layout/compressed.rs
index 66a371c25..eb573d312 100644
--- a/src/tools/rustfmt/tests/source/configs/fn_args_layout/compressed.rs
+++ b/src/tools/rustfmt/tests/source/configs/fn_params_layout/compressed.rs
@@ -1,4 +1,4 @@
-// rustfmt-fn_args_layout: Compressed
+// rustfmt-fn_params_layout: Compressed
// Function arguments density
trait Lorem {
diff --git a/src/tools/rustfmt/tests/source/configs/fn_args_layout/tall.rs b/src/tools/rustfmt/tests/source/configs/fn_params_layout/tall.rs
index f11e86fd3..4be34f0fe 100644
--- a/src/tools/rustfmt/tests/source/configs/fn_args_layout/tall.rs
+++ b/src/tools/rustfmt/tests/source/configs/fn_params_layout/tall.rs
@@ -1,4 +1,4 @@
-// rustfmt-fn_args_layout: Tall
+// rustfmt-fn_params_layout: Tall
// Function arguments density
trait Lorem {
diff --git a/src/tools/rustfmt/tests/source/configs/fn_args_layout/vertical.rs b/src/tools/rustfmt/tests/source/configs/fn_params_layout/vertical.rs
index a23cc0252..674968023 100644
--- a/src/tools/rustfmt/tests/source/configs/fn_args_layout/vertical.rs
+++ b/src/tools/rustfmt/tests/source/configs/fn_params_layout/vertical.rs
@@ -1,4 +1,4 @@
-// rustfmt-fn_args_layout: Vertical
+// rustfmt-fn_params_layout: Vertical
// Function arguments density
trait Lorem {
diff --git a/src/tools/rustfmt/tests/source/enum.rs b/src/tools/rustfmt/tests/source/enum.rs
index 0ed9651ab..a7b961692 100644
--- a/src/tools/rustfmt/tests/source/enum.rs
+++ b/src/tools/rustfmt/tests/source/enum.rs
@@ -36,7 +36,7 @@ enum StructLikeVariants {
Normal(u32, String, ),
StructLike { x: i32, // Test comment
// Pre-comment
- #[Attr50] y: SomeType, // Aanother Comment
+ #[Attr50] y: SomeType, // Another Comment
}, SL { a: A }
}
diff --git a/src/tools/rustfmt/tests/source/fn-custom-7.rs b/src/tools/rustfmt/tests/source/fn-custom-7.rs
index d5330196b..3ecd87017 100644
--- a/src/tools/rustfmt/tests/source/fn-custom-7.rs
+++ b/src/tools/rustfmt/tests/source/fn-custom-7.rs
@@ -1,5 +1,5 @@
// rustfmt-normalize_comments: true
-// rustfmt-fn_args_layout: Vertical
+// rustfmt-fn_params_layout: Vertical
// rustfmt-brace_style: AlwaysNextLine
// Case with only one variable.
diff --git a/src/tools/rustfmt/tests/source/fn-custom.rs b/src/tools/rustfmt/tests/source/fn-custom.rs
index 77ced4c5e..64ef0ecfa 100644
--- a/src/tools/rustfmt/tests/source/fn-custom.rs
+++ b/src/tools/rustfmt/tests/source/fn-custom.rs
@@ -1,4 +1,4 @@
-// rustfmt-fn_args_layout: Compressed
+// rustfmt-fn_params_layout: Compressed
// Test some of the ways function signatures can be customised.
// Test compressed layout of args.
diff --git a/src/tools/rustfmt/tests/source/fn_args_layout-vertical.rs b/src/tools/rustfmt/tests/source/fn_args_layout-vertical.rs
index 759bc83d0..fd6e3f044 100644
--- a/src/tools/rustfmt/tests/source/fn_args_layout-vertical.rs
+++ b/src/tools/rustfmt/tests/source/fn_args_layout-vertical.rs
@@ -1,4 +1,4 @@
-// rustfmt-fn_args_layout: Vertical
+// rustfmt-fn_params_layout: Vertical
// Empty list should stay on one line.
fn do_bar(
diff --git a/src/tools/rustfmt/tests/source/issue-3987/format_macro_bodies_true.rs b/src/tools/rustfmt/tests/source/issue-3987/format_macro_bodies_true.rs
new file mode 100644
index 000000000..9af114fbe
--- /dev/null
+++ b/src/tools/rustfmt/tests/source/issue-3987/format_macro_bodies_true.rs
@@ -0,0 +1,26 @@
+// rustfmt-format_macro_bodies: true
+
+// with comments
+macro_rules! macros {
+ () => {{
+ Struct {
+ field: (
+ 42 + //comment 1
+ 42
+ //comment 2
+ ),
+ };
+ }};
+}
+
+// without comments
+macro_rules! macros {
+ () => {{
+ Struct {
+ field: (
+ 42 +
+ 42
+ ),
+ };
+ }};
+}
diff --git a/src/tools/rustfmt/tests/source/issue-4643.rs b/src/tools/rustfmt/tests/source/issue-4643.rs
new file mode 100644
index 000000000..382072d90
--- /dev/null
+++ b/src/tools/rustfmt/tests/source/issue-4643.rs
@@ -0,0 +1,23 @@
+// output doesn't get corrupted when using comments within generic type parameters of a trait
+
+pub trait Something<
+ A,
+ // some comment
+ B,
+ C
+> {
+ fn a(&self, x: A) -> i32;
+ fn b(&self, x: B) -> i32;
+ fn c(&self, x: C) -> i32;
+}
+
+pub trait SomethingElse<
+ A,
+ /* some comment */
+ B,
+ C
+> {
+ fn a(&self, x: A) -> i32;
+ fn b(&self, x: B) -> i32;
+ fn c(&self, x: C) -> i32;
+}
diff --git a/src/tools/rustfmt/tests/source/issue-4689/one.rs b/src/tools/rustfmt/tests/source/issue-4689/one.rs
new file mode 100644
index 000000000..d048eb10f
--- /dev/null
+++ b/src/tools/rustfmt/tests/source/issue-4689/one.rs
@@ -0,0 +1,149 @@
+// rustfmt-version: One
+
+// Based on the issue description
+pub trait PrettyPrinter<'tcx>:
+Printer<
+'tcx,
+Error = fmt::Error,
+Path = Self,
+Region = Self,
+Type = Self,
+DynExistential = Self,
+Const = Self,
+>
+{
+//
+}
+pub trait PrettyPrinter<'tcx>:
+Printer<
+'tcx,
+Error = fmt::Error,
+Path = Self,
+Region = Self,
+Type = Self,
+DynExistential = Self,
+Const = Self,
+> + fmt::Write
+{
+//
+}
+pub trait PrettyPrinter<'tcx>:
+Printer<
+'tcx,
+Error = fmt::Error,
+Path = Self,
+Region = Self,
+Type = Self,
+DynExistential = Self,
+Const = Self,
+> + fmt::Write1 + fmt::Write2
+{
+//
+}
+pub trait PrettyPrinter<'tcx>:
+fmt::Write + Printer<
+'tcx,
+Error = fmt::Error,
+Path = Self,
+Region = Self,
+Type = Self,
+DynExistential = Self,
+Const = Self,
+>
+{
+//
+}
+pub trait PrettyPrinter<'tcx>:
+fmt::Write + Printer1<
+'tcx,
+Error = fmt::Error,
+Path = Self,
+Region = Self,
+Type = Self,
+DynExistential = Self,
+Const = Self,
+> + Printer2<
+'tcx,
+Error = fmt::Error,
+Path = Self,
+Region = Self,
+Type = Self,
+DynExistential = Self,
+Const = Self,
+>
+{
+//
+}
+
+// Some test cases to ensure other cases formatting were not changed
+fn f() -> Box<
+FnMut() -> Thing<
+WithType = LongItemName,
+Error = LONGLONGLONGLONGLONGONGEvenLongerErrorNameLongerLonger,
+>,
+> {
+}
+fn f() -> Box<
+FnMut() -> Thing<
+WithType = LongItemName,
+Error = LONGLONGLONGLONGLONGONGEvenLongerErrorNameLongerLonger,
+> + fmt::Write1
++ fmt::Write2,
+> {
+}
+
+fn foo<F>(foo2: F)
+where
+F: Fn(
+// this comment is deleted
+)
+{
+}
+fn foo<F>(foo2: F)
+where
+F: Fn(
+// this comment is deleted
+) + fmt::Write
+{
+}
+
+fn elaborate_bounds<F>(mut mk_cand: F)
+where
+F: for<> FnMut(
+&mut ProbeContext<>,
+ty::PolyTraitRefffffffffffffffffffffffffffffffff<>,
+tyyyyyyyyyyyyyyyyyyyyy::AssociatedItem,
+),
+{
+}
+fn elaborate_bounds<F>(mut mk_cand: F)
+where
+F: for<> FnMut(
+&mut ProbeContext<>,
+ty::PolyTraitRefffffffffffffffffffffffffffffffff<>,
+tyyyyyyyyyyyyyyyyyyyyy::AssociatedItem,
+) + fmt::Write,
+{
+}
+
+fn build_sorted_static_get_entry_names(
+mut entries: entryyyyyyyy,
+) -> (
+impl Fn(
+AlphabeticalTraversal,
+Seconddddddddddddddddddddddddddddddddddd
+) -> Parammmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
++ Sendddddddddddddddddddddddddddddddddddddddddddd
+) {
+}
+
+pub trait SomeTrait:
+Cloneeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee
++ Eqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq
+{
+}
+
+trait B = where
+for<'b> &'b Self: Send
++ Cloneeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee
++ Copyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy;
diff --git a/src/tools/rustfmt/tests/source/issue-4689/two.rs b/src/tools/rustfmt/tests/source/issue-4689/two.rs
new file mode 100644
index 000000000..ea7feda82
--- /dev/null
+++ b/src/tools/rustfmt/tests/source/issue-4689/two.rs
@@ -0,0 +1,149 @@
+// rustfmt-version: Two
+
+// Based on the issue description
+pub trait PrettyPrinter<'tcx>:
+Printer<
+'tcx,
+Error = fmt::Error,
+Path = Self,
+Region = Self,
+Type = Self,
+DynExistential = Self,
+Const = Self,
+>
+{
+//
+}
+pub trait PrettyPrinter<'tcx>:
+Printer<
+'tcx,
+Error = fmt::Error,
+Path = Self,
+Region = Self,
+Type = Self,
+DynExistential = Self,
+Const = Self,
+> + fmt::Write
+{
+//
+}
+pub trait PrettyPrinter<'tcx>:
+Printer<
+'tcx,
+Error = fmt::Error,
+Path = Self,
+Region = Self,
+Type = Self,
+DynExistential = Self,
+Const = Self,
+> + fmt::Write1 + fmt::Write2
+{
+//
+}
+pub trait PrettyPrinter<'tcx>:
+fmt::Write + Printer<
+'tcx,
+Error = fmt::Error,
+Path = Self,
+Region = Self,
+Type = Self,
+DynExistential = Self,
+Const = Self,
+>
+{
+//
+}
+pub trait PrettyPrinter<'tcx>:
+fmt::Write + Printer1<
+'tcx,
+Error = fmt::Error,
+Path = Self,
+Region = Self,
+Type = Self,
+DynExistential = Self,
+Const = Self,
+> + Printer2<
+'tcx,
+Error = fmt::Error,
+Path = Self,
+Region = Self,
+Type = Self,
+DynExistential = Self,
+Const = Self,
+>
+{
+//
+}
+
+// Some test cases to ensure other cases formatting were not changed
+fn f() -> Box<
+FnMut() -> Thing<
+WithType = LongItemName,
+Error = LONGLONGLONGLONGLONGONGEvenLongerErrorNameLongerLonger,
+>,
+> {
+}
+fn f() -> Box<
+FnMut() -> Thing<
+WithType = LongItemName,
+Error = LONGLONGLONGLONGLONGONGEvenLongerErrorNameLongerLonger,
+> + fmt::Write1
++ fmt::Write2,
+> {
+}
+
+fn foo<F>(foo2: F)
+where
+F: Fn(
+// this comment is deleted
+)
+{
+}
+fn foo<F>(foo2: F)
+where
+F: Fn(
+// this comment is deleted
+) + fmt::Write
+{
+}
+
+fn elaborate_bounds<F>(mut mk_cand: F)
+where
+F: for<> FnMut(
+&mut ProbeContext<>,
+ty::PolyTraitRefffffffffffffffffffffffffffffffff<>,
+tyyyyyyyyyyyyyyyyyyyyy::AssociatedItem,
+),
+{
+}
+fn elaborate_bounds<F>(mut mk_cand: F)
+where
+F: for<> FnMut(
+&mut ProbeContext<>,
+ty::PolyTraitRefffffffffffffffffffffffffffffffff<>,
+tyyyyyyyyyyyyyyyyyyyyy::AssociatedItem,
+) + fmt::Write,
+{
+}
+
+fn build_sorted_static_get_entry_names(
+mut entries: entryyyyyyyy,
+) -> (
+impl Fn(
+AlphabeticalTraversal,
+Seconddddddddddddddddddddddddddddddddddd
+) -> Parammmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
++ Sendddddddddddddddddddddddddddddddddddddddddddd
+) {
+}
+
+pub trait SomeTrait:
+Cloneeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee
++ Eqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq
+{
+}
+
+trait B = where
+for<'b> &'b Self: Send
++ Cloneeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee
++ Copyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy;
diff --git a/src/tools/rustfmt/tests/source/issue_1306.rs b/src/tools/rustfmt/tests/source/issue_1306.rs
new file mode 100644
index 000000000..03b78e341
--- /dev/null
+++ b/src/tools/rustfmt/tests/source/issue_1306.rs
@@ -0,0 +1,29 @@
+// rustfmt-max_width: 160
+// rustfmt-fn_call_width: 96
+// rustfmt-fn_args_layout: Compressed
+// rustfmt-trailing_comma: Always
+// rustfmt-wrap_comments: true
+
+fn foo() {
+ for elem in try!(gen_epub_book::ops::parse_descriptor_file(&mut try!(File::open(&opts.source_file.1).map_err(|_| {
+ gen_epub_book::Error::Io {
+ desc: "input file",
+ op: "open",
+ more: None,
+ }
+ })),
+ "input file")) {
+ println!("{}", elem);
+ }
+}
+
+fn write_content() {
+ io::copy(try!(File::open(in_f).map_err(|_| {
+ Error::Io {
+ desc: "Content",
+ op: "open",
+ more: None,
+ }
+ })),
+ w);
+}
diff --git a/src/tools/rustfmt/tests/source/issue_3245.rs b/src/tools/rustfmt/tests/source/issue_3245.rs
new file mode 100644
index 000000000..0279246ed
--- /dev/null
+++ b/src/tools/rustfmt/tests/source/issue_3245.rs
@@ -0,0 +1,4 @@
+fn main() {
+ let x = 1;
+ ;let y = 3;
+}
diff --git a/src/tools/rustfmt/tests/source/issue_3561.rs b/src/tools/rustfmt/tests/source/issue_3561.rs
new file mode 100644
index 000000000..8f6cd8f9f
--- /dev/null
+++ b/src/tools/rustfmt/tests/source/issue_3561.rs
@@ -0,0 +1,6 @@
+fn main() {;7
+}
+
+fn main() {
+ ;7
+}
diff --git a/src/tools/rustfmt/tests/source/skip_macro_invocations/all.rs b/src/tools/rustfmt/tests/source/skip_macro_invocations/all.rs
new file mode 100644
index 000000000..d0437ee10
--- /dev/null
+++ b/src/tools/rustfmt/tests/source/skip_macro_invocations/all.rs
@@ -0,0 +1,11 @@
+// rustfmt-skip_macro_invocations: ["*"]
+
+// Should skip this invocation
+items!(
+ const _: u8 = 0;
+);
+
+// Should skip this invocation
+renamed_items!(
+ const _: u8 = 0;
+);
diff --git a/src/tools/rustfmt/tests/source/skip_macro_invocations/all_and_name.rs b/src/tools/rustfmt/tests/source/skip_macro_invocations/all_and_name.rs
new file mode 100644
index 000000000..1f6722344
--- /dev/null
+++ b/src/tools/rustfmt/tests/source/skip_macro_invocations/all_and_name.rs
@@ -0,0 +1,11 @@
+// rustfmt-skip_macro_invocations: ["*","items"]
+
+// Should skip this invocation
+items!(
+ const _: u8 = 0;
+);
+
+// Should also skip this invocation, as the wildcard covers it
+renamed_items!(
+ const _: u8 = 0;
+);
diff --git a/src/tools/rustfmt/tests/source/skip_macro_invocations/empty.rs b/src/tools/rustfmt/tests/source/skip_macro_invocations/empty.rs
new file mode 100644
index 000000000..f3dd89dc4
--- /dev/null
+++ b/src/tools/rustfmt/tests/source/skip_macro_invocations/empty.rs
@@ -0,0 +1,11 @@
+// rustfmt-skip_macro_invocations: []
+
+// Should not skip this invocation
+items!(
+ const _: u8 = 0;
+);
+
+// Should not skip this invocation
+renamed_items!(
+ const _: u8 = 0;
+);
diff --git a/src/tools/rustfmt/tests/source/skip_macro_invocations/name.rs b/src/tools/rustfmt/tests/source/skip_macro_invocations/name.rs
new file mode 100644
index 000000000..7fa5d3a6f
--- /dev/null
+++ b/src/tools/rustfmt/tests/source/skip_macro_invocations/name.rs
@@ -0,0 +1,11 @@
+// rustfmt-skip_macro_invocations: ["items"]
+
+// Should skip this invocation
+items!(
+ const _: u8 = 0;
+);
+
+// Should not skip this invocation
+renamed_items!(
+ const _: u8 = 0;
+);
diff --git a/src/tools/rustfmt/tests/source/skip_macro_invocations/name_unknown.rs b/src/tools/rustfmt/tests/source/skip_macro_invocations/name_unknown.rs
new file mode 100644
index 000000000..d56695325
--- /dev/null
+++ b/src/tools/rustfmt/tests/source/skip_macro_invocations/name_unknown.rs
@@ -0,0 +1,6 @@
+// rustfmt-skip_macro_invocations: ["unknown"]
+
+// Should not skip this invocation
+items!(
+ const _: u8 = 0;
+);
diff --git a/src/tools/rustfmt/tests/source/skip_macro_invocations/names.rs b/src/tools/rustfmt/tests/source/skip_macro_invocations/names.rs
new file mode 100644
index 000000000..a920381a4
--- /dev/null
+++ b/src/tools/rustfmt/tests/source/skip_macro_invocations/names.rs
@@ -0,0 +1,16 @@
+// rustfmt-skip_macro_invocations: ["foo","bar"]
+
+// Should skip this invocation
+foo!(
+ const _: u8 = 0;
+);
+
+// Should skip this invocation
+bar!(
+ const _: u8 = 0;
+);
+
+// Should not skip this invocation
+baz!(
+ const _: u8 = 0;
+);
diff --git a/src/tools/rustfmt/tests/source/skip_macro_invocations/path_qualified_invocation_mismatch.rs b/src/tools/rustfmt/tests/source/skip_macro_invocations/path_qualified_invocation_mismatch.rs
new file mode 100644
index 000000000..61296869a
--- /dev/null
+++ b/src/tools/rustfmt/tests/source/skip_macro_invocations/path_qualified_invocation_mismatch.rs
@@ -0,0 +1,6 @@
+// rustfmt-skip_macro_invocations: ["items"]
+
+// Should not skip this invocation
+self::items!(
+ const _: u8 = 0;
+);
diff --git a/src/tools/rustfmt/tests/source/skip_macro_invocations/path_qualified_match.rs b/src/tools/rustfmt/tests/source/skip_macro_invocations/path_qualified_match.rs
new file mode 100644
index 000000000..9398918a9
--- /dev/null
+++ b/src/tools/rustfmt/tests/source/skip_macro_invocations/path_qualified_match.rs
@@ -0,0 +1,6 @@
+// rustfmt-skip_macro_invocations: ["self::items"]
+
+// Should skip this invocation
+self::items!(
+ const _: u8 = 0;
+);
diff --git a/src/tools/rustfmt/tests/source/skip_macro_invocations/path_qualified_name_mismatch.rs b/src/tools/rustfmt/tests/source/skip_macro_invocations/path_qualified_name_mismatch.rs
new file mode 100644
index 000000000..4e3eb542d
--- /dev/null
+++ b/src/tools/rustfmt/tests/source/skip_macro_invocations/path_qualified_name_mismatch.rs
@@ -0,0 +1,6 @@
+// rustfmt-skip_macro_invocations: ["self::items"]
+
+// Should not skip this invocation
+items!(
+ const _: u8 = 0;
+);
diff --git a/src/tools/rustfmt/tests/source/skip_macro_invocations/use_alias_examples.rs b/src/tools/rustfmt/tests/source/skip_macro_invocations/use_alias_examples.rs
new file mode 100644
index 000000000..43cb8015d
--- /dev/null
+++ b/src/tools/rustfmt/tests/source/skip_macro_invocations/use_alias_examples.rs
@@ -0,0 +1,32 @@
+// rustfmt-skip_macro_invocations: ["aaa","ccc"]
+
+// These tests demonstrate a realistic use case with use aliases.
+// The use statements should not impact functionality in any way.
+
+use crate::{aaa, bbb, ddd};
+
+// No use alias, invocation in list
+// Should skip this invocation
+aaa!(
+ const _: u8 = 0;
+);
+
+// Use alias, invocation in list
+// Should skip this invocation
+use crate::bbb as ccc;
+ccc!(
+ const _: u8 = 0;
+);
+
+// Use alias, invocation not in list
+// Should not skip this invocation
+use crate::ddd as eee;
+eee!(
+ const _: u8 = 0;
+);
+
+// No use alias, invocation not in list
+// Should not skip this invocation
+fff!(
+ const _: u8 = 0;
+);
diff --git a/src/tools/rustfmt/tests/source/tuple.rs b/src/tools/rustfmt/tests/source/tuple.rs
index 9a0f979fb..5189a7454 100644
--- a/src/tools/rustfmt/tests/source/tuple.rs
+++ b/src/tools/rustfmt/tests/source/tuple.rs
@@ -1,4 +1,4 @@
-// Test tuple litterals
+// Test tuple literals
fn foo() {
let a = (a, a, a, a, a);
diff --git a/src/tools/rustfmt/tests/source/wrap_comments_should_not_imply_format_doc_comments.rs b/src/tools/rustfmt/tests/source/wrap_comments_should_not_imply_format_doc_comments.rs
index 78b3ce146..56064e4a4 100644
--- a/src/tools/rustfmt/tests/source/wrap_comments_should_not_imply_format_doc_comments.rs
+++ b/src/tools/rustfmt/tests/source/wrap_comments_should_not_imply_format_doc_comments.rs
@@ -11,6 +11,6 @@
///
fn foo() {}
-/// A long commment for wrapping
+/// A long comment for wrapping
/// This is a long long long long long long long long long long long long long long long long long long long long sentence.
fn bar() {}
diff --git a/src/tools/rustfmt/tests/target/cfg_if/detect/arch/x86.rs b/src/tools/rustfmt/tests/target/cfg_if/detect/arch/x86.rs
index 02d5eed1c..47210cae2 100644
--- a/src/tools/rustfmt/tests/target/cfg_if/detect/arch/x86.rs
+++ b/src/tools/rustfmt/tests/target/cfg_if/detect/arch/x86.rs
@@ -314,7 +314,7 @@ pub enum Feature {
tbm,
/// POPCNT (Population Count)
popcnt,
- /// FXSR (Floating-point context fast save and restor)
+ /// FXSR (Floating-point context fast save and restore)
fxsr,
/// XSAVE (Save Processor Extended States)
xsave,
diff --git a/src/tools/rustfmt/tests/target/comments_unicode.rs b/src/tools/rustfmt/tests/target/comments_unicode.rs
new file mode 100644
index 000000000..3e1b6b0a2
--- /dev/null
+++ b/src/tools/rustfmt/tests/target/comments_unicode.rs
@@ -0,0 +1,140 @@
+impl Default for WhitespaceCharacters {
+ fn default() -> Self {
+ Self {
+ space: '·', // U+00B7
+ nbsp: '⍽', // U+237D
+ tab: '→', // U+2192
+ newline: '⏎', // U+23CE
+ }
+ }
+}
+
+const RAINBOWS: &[&str] = &[
+ "rаinЬοѡ", // hue: 0
+ "raіnЬοw", // hue: 2
+ "rаіɴЬow", // hue: 2
+ "raіɴЬoѡ", // hue: 8
+ "ʀainЬow", // hue: 8
+ "ʀaіɴboѡ", // hue: 8
+ "ʀаіnbοw", // hue: 11
+ "rainЬoѡ", // hue: 14
+ "raіɴbow", // hue: 14
+ "rаiɴЬow", // hue: 20
+ "raіnЬow", // hue: 26
+ "ʀaiɴbοw", // hue: 32
+ "raіɴboѡ", // hue: 35
+ "rаiɴbow", // hue: 35
+ "rаіnbοw", // hue: 38
+ "rаinЬow", // hue: 47
+ "ʀaіnboѡ", // hue: 47
+ "ʀaіnЬoѡ", // hue: 47
+ "ʀаіɴbοw", // hue: 53
+ "ʀaіnЬοѡ", // hue: 57
+ "raiɴЬoѡ", // hue: 68
+ "ʀainbοѡ", // hue: 68
+ "ʀаinboѡ", // hue: 68
+ "ʀаiɴbοw", // hue: 68
+ "ʀаіnbow", // hue: 68
+ "rаіnЬοѡ", // hue: 69
+ "ʀainЬοw", // hue: 71
+ "raiɴbow", // hue: 73
+ "raіnЬoѡ", // hue: 74
+ "rаіɴbοw", // hue: 77
+ "raіnЬοѡ", // hue: 81
+ "raiɴЬow", // hue: 83
+ "ʀainbοw", // hue: 83
+ "ʀаinbow", // hue: 83
+ "ʀаiɴbοѡ", // hue: 83
+ "ʀаіnboѡ", // hue: 83
+ "ʀаіɴЬοѡ", // hue: 84
+ "rainЬow", // hue: 85
+ "ʀаiɴЬοw", // hue: 86
+ "ʀаіnbοѡ", // hue: 89
+ "ʀаіnЬοw", // hue: 92
+ "rаiɴbοw", // hue: 95
+ "ʀаіɴbοѡ", // hue: 98
+ "ʀаiɴЬοѡ", // hue: 99
+ "raіnbοw", // hue: 101
+ "ʀаіɴЬοw", // hue: 101
+ "ʀaiɴboѡ", // hue: 104
+ "ʀаinbοѡ", // hue: 104
+ "rаiɴbοѡ", // hue: 107
+ "ʀаinЬοw", // hue: 107
+ "rаiɴЬοw", // hue: 110
+ "rаіnboѡ", // hue: 110
+ "rаіnbοѡ", // hue: 113
+ "ʀainЬοѡ", // hue: 114
+ "rаіnЬοw", // hue: 116
+ "ʀaіɴЬow", // hue: 116
+ "rаinbοw", // hue: 122
+ "ʀаіɴboѡ", // hue: 125
+ "rаinbοѡ", // hue: 131
+ "rainbow", // hue: 134
+ "rаinЬοw", // hue: 134
+ "ʀаiɴboѡ", // hue: 140
+ "rainЬοѡ", // hue: 141
+ "raіɴЬow", // hue: 143
+ "ʀainЬoѡ", // hue: 143
+ "ʀaіɴbow", // hue: 143
+ "ʀainbow", // hue: 148
+ "rаіɴboѡ", // hue: 149
+ "ʀainboѡ", // hue: 155
+ "ʀaіnbow", // hue: 155
+ "ʀaіnЬow", // hue: 155
+ "raiɴbοw", // hue: 158
+ "ʀаiɴЬoѡ", // hue: 158
+ "rainbοw", // hue: 160
+ "rаinbow", // hue: 160
+ "ʀaіɴbοѡ", // hue: 164
+ "ʀаiɴbow", // hue: 164
+ "ʀаіnЬoѡ", // hue: 164
+ "ʀaiɴЬοѡ", // hue: 165
+ "rаiɴboѡ", // hue: 167
+ "ʀaіɴЬοw", // hue: 167
+ "ʀaіɴЬοѡ", // hue: 171
+ "raіnboѡ", // hue: 173
+ "ʀаіɴЬoѡ", // hue: 173
+ "rаіɴbοѡ", // hue: 176
+ "ʀаinЬow", // hue: 176
+ "rаiɴЬοѡ", // hue: 177
+ "rаіɴЬοw", // hue: 179
+ "ʀаinЬoѡ", // hue: 179
+ "ʀаіɴbow", // hue: 179
+ "rаiɴЬoѡ", // hue: 182
+ "raіɴbοѡ", // hue: 188
+ "rаіnЬoѡ", // hue: 188
+ "raiɴЬοѡ", // hue: 189
+ "raіɴЬοw", // hue: 191
+ "ʀaіɴbοw", // hue: 191
+ "ʀаіnЬow", // hue: 191
+ "rainbοѡ", // hue: 194
+ "rаinboѡ", // hue: 194
+ "rаіnbow", // hue: 194
+ "rainЬοw", // hue: 197
+ "rаinЬoѡ", // hue: 206
+ "rаіɴbow", // hue: 206
+ "rаіɴЬοѡ", // hue: 210
+ "ʀaiɴЬow", // hue: 212
+ "raіɴbοw", // hue: 218
+ "rаіnЬow", // hue: 218
+ "ʀaiɴbοѡ", // hue: 221
+ "ʀaiɴЬοw", // hue: 224
+ "ʀaіnbοѡ", // hue: 227
+ "raiɴboѡ", // hue: 230
+ "ʀaіnbοw", // hue: 230
+ "ʀaіnЬοw", // hue: 230
+ "ʀаinЬοѡ", // hue: 231
+ "rainboѡ", // hue: 232
+ "raіnbow", // hue: 232
+ "ʀаіɴЬow", // hue: 233
+ "ʀaіɴЬoѡ", // hue: 239
+ "ʀаіnЬοѡ", // hue: 246
+ "raiɴbοѡ", // hue: 248
+ "ʀаiɴЬow", // hue: 248
+ "raіɴЬοѡ", // hue: 249
+ "raiɴЬοw", // hue: 251
+ "rаіɴЬoѡ", // hue: 251
+ "ʀaiɴbow", // hue: 251
+ "ʀаinbοw", // hue: 251
+ "raіnbοѡ", // hue: 254
+];
diff --git a/src/tools/rustfmt/tests/target/configs/fn_args_layout/compressed.rs b/src/tools/rustfmt/tests/target/configs/fn_params_layout/compressed.rs
index f189446e2..ff32f0f1d 100644
--- a/src/tools/rustfmt/tests/target/configs/fn_args_layout/compressed.rs
+++ b/src/tools/rustfmt/tests/target/configs/fn_params_layout/compressed.rs
@@ -1,4 +1,4 @@
-// rustfmt-fn_args_layout: Compressed
+// rustfmt-fn_params_layout: Compressed
// Function arguments density
trait Lorem {
diff --git a/src/tools/rustfmt/tests/target/configs/fn_args_layout/tall.rs b/src/tools/rustfmt/tests/target/configs/fn_params_layout/tall.rs
index 20f308973..25a86799a 100644
--- a/src/tools/rustfmt/tests/target/configs/fn_args_layout/tall.rs
+++ b/src/tools/rustfmt/tests/target/configs/fn_params_layout/tall.rs
@@ -1,4 +1,4 @@
-// rustfmt-fn_args_layout: Tall
+// rustfmt-fn_params_layout: Tall
// Function arguments density
trait Lorem {
diff --git a/src/tools/rustfmt/tests/target/configs/fn_args_layout/vertical.rs b/src/tools/rustfmt/tests/target/configs/fn_params_layout/vertical.rs
index 6c695a75d..7a0e42415 100644
--- a/src/tools/rustfmt/tests/target/configs/fn_args_layout/vertical.rs
+++ b/src/tools/rustfmt/tests/target/configs/fn_params_layout/vertical.rs
@@ -1,4 +1,4 @@
-// rustfmt-fn_args_layout: Vertical
+// rustfmt-fn_params_layout: Vertical
// Function arguments density
trait Lorem {
diff --git a/src/tools/rustfmt/tests/target/enum.rs b/src/tools/rustfmt/tests/target/enum.rs
index 9a25126b4..70fc8ab37 100644
--- a/src/tools/rustfmt/tests/target/enum.rs
+++ b/src/tools/rustfmt/tests/target/enum.rs
@@ -43,7 +43,7 @@ enum StructLikeVariants {
x: i32, // Test comment
// Pre-comment
#[Attr50]
- y: SomeType, // Aanother Comment
+ y: SomeType, // Another Comment
},
SL {
a: A,
diff --git a/src/tools/rustfmt/tests/target/fn-custom-7.rs b/src/tools/rustfmt/tests/target/fn-custom-7.rs
index 2c20ac5a7..f6a1a90c3 100644
--- a/src/tools/rustfmt/tests/target/fn-custom-7.rs
+++ b/src/tools/rustfmt/tests/target/fn-custom-7.rs
@@ -1,5 +1,5 @@
// rustfmt-normalize_comments: true
-// rustfmt-fn_args_layout: Vertical
+// rustfmt-fn_params_layout: Vertical
// rustfmt-brace_style: AlwaysNextLine
// Case with only one variable.
diff --git a/src/tools/rustfmt/tests/target/fn-custom.rs b/src/tools/rustfmt/tests/target/fn-custom.rs
index 2eb2a973d..506d9de34 100644
--- a/src/tools/rustfmt/tests/target/fn-custom.rs
+++ b/src/tools/rustfmt/tests/target/fn-custom.rs
@@ -1,4 +1,4 @@
-// rustfmt-fn_args_layout: Compressed
+// rustfmt-fn_params_layout: Compressed
// Test some of the ways function signatures can be customised.
// Test compressed layout of args.
diff --git a/src/tools/rustfmt/tests/target/fn_args_layout-vertical.rs b/src/tools/rustfmt/tests/target/fn_args_layout-vertical.rs
index da0ac981d..bfeca15c9 100644
--- a/src/tools/rustfmt/tests/target/fn_args_layout-vertical.rs
+++ b/src/tools/rustfmt/tests/target/fn_args_layout-vertical.rs
@@ -1,4 +1,4 @@
-// rustfmt-fn_args_layout: Vertical
+// rustfmt-fn_params_layout: Vertical
// Empty list should stay on one line.
fn do_bar() -> u8 {
diff --git a/src/tools/rustfmt/tests/target/issue-2534/format_macro_matchers_false.rs b/src/tools/rustfmt/tests/target/issue-2534/format_macro_matchers_false.rs
new file mode 100644
index 000000000..2038ed7f1
--- /dev/null
+++ b/src/tools/rustfmt/tests/target/issue-2534/format_macro_matchers_false.rs
@@ -0,0 +1,6 @@
+// rustfmt-format_macro_matchers: false
+
+macro_rules! foo {
+ ($a:ident : $b:ty) => {};
+ ($a:ident $b:ident $c:ident) => {};
+}
diff --git a/src/tools/rustfmt/tests/target/issue-2534/format_macro_matchers_true.rs b/src/tools/rustfmt/tests/target/issue-2534/format_macro_matchers_true.rs
new file mode 100644
index 000000000..01d939add
--- /dev/null
+++ b/src/tools/rustfmt/tests/target/issue-2534/format_macro_matchers_true.rs
@@ -0,0 +1,6 @@
+// rustfmt-format_macro_matchers: true
+
+macro_rules! foo {
+ ($a:ident : $b:ty) => {};
+ ($a:ident $b:ident $c:ident) => {};
+}
diff --git a/src/tools/rustfmt/tests/target/issue-3987/format_macro_bodies_false.rs b/src/tools/rustfmt/tests/target/issue-3987/format_macro_bodies_false.rs
new file mode 100644
index 000000000..1352b762e
--- /dev/null
+++ b/src/tools/rustfmt/tests/target/issue-3987/format_macro_bodies_false.rs
@@ -0,0 +1,26 @@
+// rustfmt-format_macro_bodies: false
+
+// with comments
+macro_rules! macros {
+ () => {{
+ Struct {
+ field: (
+ 42 + //comment 1
+ 42
+ //comment 2
+ ),
+ };
+ }};
+}
+
+// without comments
+macro_rules! macros {
+ () => {{
+ Struct {
+ field: (
+ 42 +
+ 42
+ ),
+ };
+ }};
+}
diff --git a/src/tools/rustfmt/tests/target/issue-3987/format_macro_bodies_true.rs b/src/tools/rustfmt/tests/target/issue-3987/format_macro_bodies_true.rs
new file mode 100644
index 000000000..88d57159c
--- /dev/null
+++ b/src/tools/rustfmt/tests/target/issue-3987/format_macro_bodies_true.rs
@@ -0,0 +1,21 @@
+// rustfmt-format_macro_bodies: true
+
+// with comments
+macro_rules! macros {
+ () => {{
+ Struct {
+ field: (
+ 42 + //comment 1
+ 42
+ //comment 2
+ ),
+ };
+ }};
+}
+
+// without comments
+macro_rules! macros {
+ () => {{
+ Struct { field: (42 + 42) };
+ }};
+}
diff --git a/src/tools/rustfmt/tests/target/issue-4643.rs b/src/tools/rustfmt/tests/target/issue-4643.rs
new file mode 100644
index 000000000..ef99e4db3
--- /dev/null
+++ b/src/tools/rustfmt/tests/target/issue-4643.rs
@@ -0,0 +1,19 @@
+// output doesn't get corrupted when using comments within generic type parameters of a trait
+
+pub trait Something<
+ A,
+ // some comment
+ B,
+ C,
+>
+{
+ fn a(&self, x: A) -> i32;
+ fn b(&self, x: B) -> i32;
+ fn c(&self, x: C) -> i32;
+}
+
+pub trait SomethingElse<A, /* some comment */ B, C> {
+ fn a(&self, x: A) -> i32;
+ fn b(&self, x: B) -> i32;
+ fn c(&self, x: C) -> i32;
+}
diff --git a/src/tools/rustfmt/tests/target/issue-4689/one.rs b/src/tools/rustfmt/tests/target/issue-4689/one.rs
new file mode 100644
index 000000000..7735e34f3
--- /dev/null
+++ b/src/tools/rustfmt/tests/target/issue-4689/one.rs
@@ -0,0 +1,150 @@
+// rustfmt-version: One
+
+// Based on the issue description
+pub trait PrettyPrinter<'tcx>:
+ Printer<
+ 'tcx,
+ Error = fmt::Error,
+ Path = Self,
+ Region = Self,
+ Type = Self,
+ DynExistential = Self,
+ Const = Self,
+>
+{
+ //
+}
+pub trait PrettyPrinter<'tcx>:
+ Printer<
+ 'tcx,
+ Error = fmt::Error,
+ Path = Self,
+ Region = Self,
+ Type = Self,
+ DynExistential = Self,
+ Const = Self,
+ > + fmt::Write
+{
+ //
+}
+pub trait PrettyPrinter<'tcx>:
+ Printer<
+ 'tcx,
+ Error = fmt::Error,
+ Path = Self,
+ Region = Self,
+ Type = Self,
+ DynExistential = Self,
+ Const = Self,
+ > + fmt::Write1
+ + fmt::Write2
+{
+ //
+}
+pub trait PrettyPrinter<'tcx>:
+ fmt::Write
+ + Printer<
+ 'tcx,
+ Error = fmt::Error,
+ Path = Self,
+ Region = Self,
+ Type = Self,
+ DynExistential = Self,
+ Const = Self,
+ >
+{
+ //
+}
+pub trait PrettyPrinter<'tcx>:
+ fmt::Write
+ + Printer1<
+ 'tcx,
+ Error = fmt::Error,
+ Path = Self,
+ Region = Self,
+ Type = Self,
+ DynExistential = Self,
+ Const = Self,
+ > + Printer2<
+ 'tcx,
+ Error = fmt::Error,
+ Path = Self,
+ Region = Self,
+ Type = Self,
+ DynExistential = Self,
+ Const = Self,
+ >
+{
+ //
+}
+
+// Some test cases to ensure other cases formatting were not changed
+fn f() -> Box<
+ FnMut() -> Thing<
+ WithType = LongItemName,
+ Error = LONGLONGLONGLONGLONGONGEvenLongerErrorNameLongerLonger,
+ >,
+> {
+}
+fn f() -> Box<
+ FnMut() -> Thing<
+ WithType = LongItemName,
+ Error = LONGLONGLONGLONGLONGONGEvenLongerErrorNameLongerLonger,
+ > + fmt::Write1
+ + fmt::Write2,
+> {
+}
+
+fn foo<F>(foo2: F)
+where
+ F: Fn(
+ // this comment is deleted
+ ),
+{
+}
+fn foo<F>(foo2: F)
+where
+ F: Fn(
+ // this comment is deleted
+ ) + fmt::Write,
+{
+}
+
+fn elaborate_bounds<F>(mut mk_cand: F)
+where
+ F: FnMut(
+ &mut ProbeContext,
+ ty::PolyTraitRefffffffffffffffffffffffffffffffff,
+ tyyyyyyyyyyyyyyyyyyyyy::AssociatedItem,
+ ),
+{
+}
+fn elaborate_bounds<F>(mut mk_cand: F)
+where
+ F: FnMut(
+ &mut ProbeContext,
+ ty::PolyTraitRefffffffffffffffffffffffffffffffff,
+ tyyyyyyyyyyyyyyyyyyyyy::AssociatedItem,
+ ) + fmt::Write,
+{
+}
+
+fn build_sorted_static_get_entry_names(
+ mut entries: entryyyyyyyy,
+) -> (impl Fn(
+ AlphabeticalTraversal,
+ Seconddddddddddddddddddddddddddddddddddd,
+) -> Parammmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ + Sendddddddddddddddddddddddddddddddddddddddddddd) {
+}
+
+pub trait SomeTrait:
+ Cloneeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee
+ + Eqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq
+{
+}
+
+trait B = where
+ for<'b> &'b Self: Send
+ + Cloneeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee
+ + Copyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy;
diff --git a/src/tools/rustfmt/tests/target/issue-4689/two.rs b/src/tools/rustfmt/tests/target/issue-4689/two.rs
new file mode 100644
index 000000000..e3b5cd228
--- /dev/null
+++ b/src/tools/rustfmt/tests/target/issue-4689/two.rs
@@ -0,0 +1,152 @@
+// rustfmt-version: Two
+
+// Based on the issue description
+pub trait PrettyPrinter<'tcx>:
+ Printer<
+ 'tcx,
+ Error = fmt::Error,
+ Path = Self,
+ Region = Self,
+ Type = Self,
+ DynExistential = Self,
+ Const = Self,
+ >
+{
+ //
+}
+pub trait PrettyPrinter<'tcx>:
+ Printer<
+ 'tcx,
+ Error = fmt::Error,
+ Path = Self,
+ Region = Self,
+ Type = Self,
+ DynExistential = Self,
+ Const = Self,
+ > + fmt::Write
+{
+ //
+}
+pub trait PrettyPrinter<'tcx>:
+ Printer<
+ 'tcx,
+ Error = fmt::Error,
+ Path = Self,
+ Region = Self,
+ Type = Self,
+ DynExistential = Self,
+ Const = Self,
+ > + fmt::Write1
+ + fmt::Write2
+{
+ //
+}
+pub trait PrettyPrinter<'tcx>:
+ fmt::Write
+ + Printer<
+ 'tcx,
+ Error = fmt::Error,
+ Path = Self,
+ Region = Self,
+ Type = Self,
+ DynExistential = Self,
+ Const = Self,
+ >
+{
+ //
+}
+pub trait PrettyPrinter<'tcx>:
+ fmt::Write
+ + Printer1<
+ 'tcx,
+ Error = fmt::Error,
+ Path = Self,
+ Region = Self,
+ Type = Self,
+ DynExistential = Self,
+ Const = Self,
+ > + Printer2<
+ 'tcx,
+ Error = fmt::Error,
+ Path = Self,
+ Region = Self,
+ Type = Self,
+ DynExistential = Self,
+ Const = Self,
+ >
+{
+ //
+}
+
+// Some test cases to ensure other cases formatting were not changed
+fn f() -> Box<
+ FnMut() -> Thing<
+ WithType = LongItemName,
+ Error = LONGLONGLONGLONGLONGONGEvenLongerErrorNameLongerLonger,
+ >,
+> {
+}
+fn f() -> Box<
+ FnMut() -> Thing<
+ WithType = LongItemName,
+ Error = LONGLONGLONGLONGLONGONGEvenLongerErrorNameLongerLonger,
+ > + fmt::Write1
+ + fmt::Write2,
+> {
+}
+
+fn foo<F>(foo2: F)
+where
+ F: Fn(
+ // this comment is deleted
+ ),
+{
+}
+fn foo<F>(foo2: F)
+where
+ F: Fn(
+ // this comment is deleted
+ ) + fmt::Write,
+{
+}
+
+fn elaborate_bounds<F>(mut mk_cand: F)
+where
+ F: FnMut(
+ &mut ProbeContext,
+ ty::PolyTraitRefffffffffffffffffffffffffffffffff,
+ tyyyyyyyyyyyyyyyyyyyyy::AssociatedItem,
+ ),
+{
+}
+fn elaborate_bounds<F>(mut mk_cand: F)
+where
+ F: FnMut(
+ &mut ProbeContext,
+ ty::PolyTraitRefffffffffffffffffffffffffffffffff,
+ tyyyyyyyyyyyyyyyyyyyyy::AssociatedItem,
+ ) + fmt::Write,
+{
+}
+
+fn build_sorted_static_get_entry_names(
+ mut entries: entryyyyyyyy,
+) -> (
+ impl Fn(
+ AlphabeticalTraversal,
+ Seconddddddddddddddddddddddddddddddddddd,
+ ) -> Parammmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+ + Sendddddddddddddddddddddddddddddddddddddddddddd
+) {
+}
+
+pub trait SomeTrait:
+ Cloneeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee
+ + Eqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq
+{
+}
+
+trait B = where
+ for<'b> &'b Self: Send
+ + Cloneeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee
+ + Copyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy;
diff --git a/src/tools/rustfmt/tests/target/issue-4791/issue_4928.rs b/src/tools/rustfmt/tests/target/issue-4791/issue_4928.rs
index 588656b53..29f6bda90 100644
--- a/src/tools/rustfmt/tests/target/issue-4791/issue_4928.rs
+++ b/src/tools/rustfmt/tests/target/issue-4791/issue_4928.rs
@@ -1,7 +1,7 @@
// rustfmt-brace_style: SameLineWhere
// rustfmt-comment_width: 100
// rustfmt-edition: 2018
-// rustfmt-fn_args_layout: Compressed
+// rustfmt-fn_params_layout: Compressed
// rustfmt-hard_tabs: false
// rustfmt-match_block_trailing_comma: true
// rustfmt-max_width: 100
diff --git a/src/tools/rustfmt/tests/target/issue-5358.rs b/src/tools/rustfmt/tests/target/issue-5358.rs
new file mode 100644
index 000000000..d4bf4909a
--- /dev/null
+++ b/src/tools/rustfmt/tests/target/issue-5358.rs
@@ -0,0 +1,4 @@
+// Test /* comment */ inside trait generics does not get duplicated.
+trait Test</* comment */ T> {}
+
+trait TestTwo</* comment */ T, /* comment */ V> {}
diff --git a/src/tools/rustfmt/tests/target/issue_1306.rs b/src/tools/rustfmt/tests/target/issue_1306.rs
new file mode 100644
index 000000000..6bb514cdf
--- /dev/null
+++ b/src/tools/rustfmt/tests/target/issue_1306.rs
@@ -0,0 +1,33 @@
+// rustfmt-max_width: 160
+// rustfmt-fn_call_width: 96
+// rustfmt-fn_args_layout: Compressed
+// rustfmt-trailing_comma: Always
+// rustfmt-wrap_comments: true
+
+fn foo() {
+ for elem in try!(gen_epub_book::ops::parse_descriptor_file(
+ &mut try!(File::open(&opts.source_file.1).map_err(|_| {
+ gen_epub_book::Error::Io {
+ desc: "input file",
+ op: "open",
+ more: None,
+ }
+ })),
+ "input file"
+ )) {
+ println!("{}", elem);
+ }
+}
+
+fn write_content() {
+ io::copy(
+ try!(File::open(in_f).map_err(|_| {
+ Error::Io {
+ desc: "Content",
+ op: "open",
+ more: None,
+ }
+ })),
+ w,
+ );
+}
diff --git a/src/tools/rustfmt/tests/target/issue_3033.rs b/src/tools/rustfmt/tests/target/issue_3033.rs
new file mode 100644
index 000000000..e12249a6d
--- /dev/null
+++ b/src/tools/rustfmt/tests/target/issue_3033.rs
@@ -0,0 +1,2 @@
+use dom::bindings::codegen::Bindings::BluetoothRemoteGATTServerBinding::BluetoothRemoteGATTServerBinding::
+ BluetoothRemoteGATTServerMethods;
diff --git a/src/tools/rustfmt/tests/target/issue_3245.rs b/src/tools/rustfmt/tests/target/issue_3245.rs
new file mode 100644
index 000000000..8f442f118
--- /dev/null
+++ b/src/tools/rustfmt/tests/target/issue_3245.rs
@@ -0,0 +1,4 @@
+fn main() {
+ let x = 1;
+ let y = 3;
+}
diff --git a/src/tools/rustfmt/tests/target/issue_3561.rs b/src/tools/rustfmt/tests/target/issue_3561.rs
new file mode 100644
index 000000000..846a14d86
--- /dev/null
+++ b/src/tools/rustfmt/tests/target/issue_3561.rs
@@ -0,0 +1,7 @@
+fn main() {
+ 7
+}
+
+fn main() {
+ 7
+}
diff --git a/src/tools/rustfmt/tests/target/issue_4350.rs b/src/tools/rustfmt/tests/target/issue_4350.rs
new file mode 100644
index 000000000..a94c5c321
--- /dev/null
+++ b/src/tools/rustfmt/tests/target/issue_4350.rs
@@ -0,0 +1,13 @@
+//rustfmt-format_macro_bodies: true
+
+macro_rules! mto_text_left {
+ ($buf:ident, $n:ident, $pos:ident, $state:ident) => {{
+ let cursor = loop {
+ state = match iter.next() {
+ None if $pos == DP::Start => break last_char_idx($buf),
+ None /*some comment */ => break 0,
+ };
+ };
+ Ok(saturate_cursor($buf, cursor))
+ }};
+}
diff --git a/src/tools/rustfmt/tests/target/issue_5668.rs b/src/tools/rustfmt/tests/target/issue_5668.rs
new file mode 100644
index 000000000..bbd9a530b
--- /dev/null
+++ b/src/tools/rustfmt/tests/target/issue_5668.rs
@@ -0,0 +1,8 @@
+type Foo = impl Send;
+struct Struct<
+ const C: usize = {
+ let _: Foo = ();
+ //~^ ERROR: mismatched types
+ 0
+ },
+>;
diff --git a/src/tools/rustfmt/tests/target/skip_macro_invocations/all.rs b/src/tools/rustfmt/tests/target/skip_macro_invocations/all.rs
new file mode 100644
index 000000000..d0437ee10
--- /dev/null
+++ b/src/tools/rustfmt/tests/target/skip_macro_invocations/all.rs
@@ -0,0 +1,11 @@
+// rustfmt-skip_macro_invocations: ["*"]
+
+// Should skip this invocation
+items!(
+ const _: u8 = 0;
+);
+
+// Should skip this invocation
+renamed_items!(
+ const _: u8 = 0;
+);
diff --git a/src/tools/rustfmt/tests/target/skip_macro_invocations/all_and_name.rs b/src/tools/rustfmt/tests/target/skip_macro_invocations/all_and_name.rs
new file mode 100644
index 000000000..1f6722344
--- /dev/null
+++ b/src/tools/rustfmt/tests/target/skip_macro_invocations/all_and_name.rs
@@ -0,0 +1,11 @@
+// rustfmt-skip_macro_invocations: ["*","items"]
+
+// Should skip this invocation
+items!(
+ const _: u8 = 0;
+);
+
+// Should also skip this invocation, as the wildcard covers it
+renamed_items!(
+ const _: u8 = 0;
+);
diff --git a/src/tools/rustfmt/tests/target/skip_macro_invocations/empty.rs b/src/tools/rustfmt/tests/target/skip_macro_invocations/empty.rs
new file mode 100644
index 000000000..4a398cc59
--- /dev/null
+++ b/src/tools/rustfmt/tests/target/skip_macro_invocations/empty.rs
@@ -0,0 +1,11 @@
+// rustfmt-skip_macro_invocations: []
+
+// Should not skip this invocation
+items!(
+ const _: u8 = 0;
+);
+
+// Should not skip this invocation
+renamed_items!(
+ const _: u8 = 0;
+);
diff --git a/src/tools/rustfmt/tests/target/skip_macro_invocations/name.rs b/src/tools/rustfmt/tests/target/skip_macro_invocations/name.rs
new file mode 100644
index 000000000..c4d577269
--- /dev/null
+++ b/src/tools/rustfmt/tests/target/skip_macro_invocations/name.rs
@@ -0,0 +1,11 @@
+// rustfmt-skip_macro_invocations: ["items"]
+
+// Should skip this invocation
+items!(
+ const _: u8 = 0;
+);
+
+// Should not skip this invocation
+renamed_items!(
+ const _: u8 = 0;
+);
diff --git a/src/tools/rustfmt/tests/target/skip_macro_invocations/name_unknown.rs b/src/tools/rustfmt/tests/target/skip_macro_invocations/name_unknown.rs
new file mode 100644
index 000000000..7ab144039
--- /dev/null
+++ b/src/tools/rustfmt/tests/target/skip_macro_invocations/name_unknown.rs
@@ -0,0 +1,6 @@
+// rustfmt-skip_macro_invocations: ["unknown"]
+
+// Should not skip this invocation
+items!(
+ const _: u8 = 0;
+);
diff --git a/src/tools/rustfmt/tests/target/skip_macro_invocations/names.rs b/src/tools/rustfmt/tests/target/skip_macro_invocations/names.rs
new file mode 100644
index 000000000..c6b41ff93
--- /dev/null
+++ b/src/tools/rustfmt/tests/target/skip_macro_invocations/names.rs
@@ -0,0 +1,16 @@
+// rustfmt-skip_macro_invocations: ["foo","bar"]
+
+// Should skip this invocation
+foo!(
+ const _: u8 = 0;
+);
+
+// Should skip this invocation
+bar!(
+ const _: u8 = 0;
+);
+
+// Should not skip this invocation
+baz!(
+ const _: u8 = 0;
+);
diff --git a/src/tools/rustfmt/tests/target/skip_macro_invocations/path_qualified_invocation_mismatch.rs b/src/tools/rustfmt/tests/target/skip_macro_invocations/path_qualified_invocation_mismatch.rs
new file mode 100644
index 000000000..6e372c726
--- /dev/null
+++ b/src/tools/rustfmt/tests/target/skip_macro_invocations/path_qualified_invocation_mismatch.rs
@@ -0,0 +1,6 @@
+// rustfmt-skip_macro_invocations: ["items"]
+
+// Should not skip this invocation
+self::items!(
+ const _: u8 = 0;
+);
diff --git a/src/tools/rustfmt/tests/target/skip_macro_invocations/path_qualified_match.rs b/src/tools/rustfmt/tests/target/skip_macro_invocations/path_qualified_match.rs
new file mode 100644
index 000000000..9398918a9
--- /dev/null
+++ b/src/tools/rustfmt/tests/target/skip_macro_invocations/path_qualified_match.rs
@@ -0,0 +1,6 @@
+// rustfmt-skip_macro_invocations: ["self::items"]
+
+// Should skip this invocation
+self::items!(
+ const _: u8 = 0;
+);
diff --git a/src/tools/rustfmt/tests/target/skip_macro_invocations/path_qualified_name_mismatch.rs b/src/tools/rustfmt/tests/target/skip_macro_invocations/path_qualified_name_mismatch.rs
new file mode 100644
index 000000000..aa57a2a65
--- /dev/null
+++ b/src/tools/rustfmt/tests/target/skip_macro_invocations/path_qualified_name_mismatch.rs
@@ -0,0 +1,6 @@
+// rustfmt-skip_macro_invocations: ["self::items"]
+
+// Should not skip this invocation
+items!(
+ const _: u8 = 0;
+);
diff --git a/src/tools/rustfmt/tests/target/skip_macro_invocations/use_alias_examples.rs b/src/tools/rustfmt/tests/target/skip_macro_invocations/use_alias_examples.rs
new file mode 100644
index 000000000..799dd8c08
--- /dev/null
+++ b/src/tools/rustfmt/tests/target/skip_macro_invocations/use_alias_examples.rs
@@ -0,0 +1,32 @@
+// rustfmt-skip_macro_invocations: ["aaa","ccc"]
+
+// These tests demonstrate a realistic use case with use aliases.
+// The use statements should not impact functionality in any way.
+
+use crate::{aaa, bbb, ddd};
+
+// No use alias, invocation in list
+// Should skip this invocation
+aaa!(
+ const _: u8 = 0;
+);
+
+// Use alias, invocation in list
+// Should skip this invocation
+use crate::bbb as ccc;
+ccc!(
+ const _: u8 = 0;
+);
+
+// Use alias, invocation not in list
+// Should not skip this invocation
+use crate::ddd as eee;
+eee!(
+ const _: u8 = 0;
+);
+
+// No use alias, invocation not in list
+// Should not skip this invocation
+fff!(
+ const _: u8 = 0;
+);
diff --git a/src/tools/rustfmt/tests/target/tuple.rs b/src/tools/rustfmt/tests/target/tuple.rs
index 68bb2f3bc..24fcf8cfd 100644
--- a/src/tools/rustfmt/tests/target/tuple.rs
+++ b/src/tools/rustfmt/tests/target/tuple.rs
@@ -1,4 +1,4 @@
-// Test tuple litterals
+// Test tuple literals
fn foo() {
let a = (a, a, a, a, a);
diff --git a/src/tools/rustfmt/tests/target/wrap_comments_should_not_imply_format_doc_comments.rs b/src/tools/rustfmt/tests/target/wrap_comments_should_not_imply_format_doc_comments.rs
index d61d4d7c2..6ccecc7e0 100644
--- a/src/tools/rustfmt/tests/target/wrap_comments_should_not_imply_format_doc_comments.rs
+++ b/src/tools/rustfmt/tests/target/wrap_comments_should_not_imply_format_doc_comments.rs
@@ -10,7 +10,7 @@
/// ```
fn foo() {}
-/// A long commment for wrapping
+/// A long comment for wrapping
/// This is a long long long long long long long long long long long long long
/// long long long long long long long sentence.
fn bar() {}
diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs
index bc2edf634..bddfdcfaf 100644
--- a/src/tools/tidy/src/deps.rs
+++ b/src/tools/tidy/src/deps.rs
@@ -59,7 +59,6 @@ const EXCEPTIONS_CRANELIFT: &[(&str, &str)] = &[
("cranelift-codegen", "Apache-2.0 WITH LLVM-exception"),
("cranelift-codegen-meta", "Apache-2.0 WITH LLVM-exception"),
("cranelift-codegen-shared", "Apache-2.0 WITH LLVM-exception"),
- ("cranelift-egraph", "Apache-2.0 WITH LLVM-exception"),
("cranelift-entity", "Apache-2.0 WITH LLVM-exception"),
("cranelift-frontend", "Apache-2.0 WITH LLVM-exception"),
("cranelift-isle", "Apache-2.0 WITH LLVM-exception"),
@@ -121,6 +120,7 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[
"dissimilar",
"dlmalloc",
"either",
+ "elsa",
"ena",
"expect-test",
"fallible-iterator", // dependency of `thorin`
@@ -179,6 +179,7 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[
"ppv-lite86",
"proc-macro-hack",
"proc-macro2",
+ "pulldown-cmark",
"psm",
"punycode",
"quote",
@@ -192,8 +193,6 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[
"regex-automata",
"regex-syntax",
"remove_dir_all",
- "rls-data",
- "rls-span",
"rustc-demangle",
"rustc-hash",
"rustc-rayon",
@@ -247,6 +246,7 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[
"unic-langid-macros",
"unic-langid-macros-impl",
"unic-ucd-version",
+ "unicase",
"unicode-ident",
"unicode-normalization",
"unicode-script",
@@ -286,7 +286,6 @@ const PERMITTED_CRANELIFT_DEPENDENCIES: &[&str] = &[
"cranelift-codegen",
"cranelift-codegen-meta",
"cranelift-codegen-shared",
- "cranelift-egraph",
"cranelift-entity",
"cranelift-frontend",
"cranelift-isle",
@@ -321,10 +320,12 @@ const PERMITTED_CRANELIFT_DEPENDENCIES: &[&str] = &[
"winapi-i686-pc-windows-gnu",
"winapi-x86_64-pc-windows-gnu",
"windows-sys",
+ "windows_aarch64_gnullvm",
"windows_aarch64_msvc",
"windows_i686_gnu",
"windows_i686_msvc",
"windows_x86_64_gnu",
+ "windows_x86_64_gnullvm",
"windows_x86_64_msvc",
];
diff --git a/src/tools/tidy/src/error_codes.rs b/src/tools/tidy/src/error_codes.rs
index 5b84b51a0..c60caa0d4 100644
--- a/src/tools/tidy/src/error_codes.rs
+++ b/src/tools/tidy/src/error_codes.rs
@@ -31,7 +31,7 @@ const IGNORE_DOCTEST_CHECK: &[&str] = &["E0464", "E0570", "E0601", "E0602", "E06
// Error codes that don't yet have a UI test. This list will eventually be removed.
const IGNORE_UI_TEST_CHECK: &[&str] =
- &["E0461", "E0465", "E0476", "E0514", "E0523", "E0554", "E0640", "E0717", "E0729", "E0789"];
+ &["E0461", "E0465", "E0514", "E0554", "E0640", "E0717", "E0729"];
macro_rules! verbose_print {
($verbose:expr, $($fmt:tt)*) => {
@@ -45,7 +45,7 @@ pub fn check(root_path: &Path, search_paths: &[&Path], verbose: bool, bad: &mut
let mut errors = Vec::new();
// Stage 1: create list
- let error_codes = extract_error_codes(root_path, &mut errors, verbose);
+ let error_codes = extract_error_codes(root_path, &mut errors);
println!("Found {} error codes", error_codes.len());
println!("Highest error code: `{}`", error_codes.iter().max().unwrap());
@@ -65,18 +65,17 @@ pub fn check(root_path: &Path, search_paths: &[&Path], verbose: bool, bad: &mut
}
/// Stage 1: Parses a list of error codes from `error_codes.rs`.
-fn extract_error_codes(root_path: &Path, errors: &mut Vec<String>, verbose: bool) -> Vec<String> {
+fn extract_error_codes(root_path: &Path, errors: &mut Vec<String>) -> Vec<String> {
let path = root_path.join(Path::new(ERROR_CODES_PATH));
let file =
fs::read_to_string(&path).unwrap_or_else(|e| panic!("failed to read `{path:?}`: {e}"));
let mut error_codes = Vec::new();
- let mut reached_undocumented_codes = false;
for line in file.lines() {
let line = line.trim();
- if !reached_undocumented_codes && line.starts_with('E') {
+ if line.starts_with('E') {
let split_line = line.split_once(':');
// Extract the error code from the line, emitting a fatal error if it is not in a correct format.
@@ -111,23 +110,6 @@ fn extract_error_codes(root_path: &Path, errors: &mut Vec<String>, verbose: bool
}
error_codes.push(err_code);
- } else if reached_undocumented_codes && line.starts_with('E') {
- let err_code = match line.split_once(',') {
- None => line,
- Some((err_code, _)) => err_code,
- }
- .to_string();
-
- verbose_print!(verbose, "warning: Error code `{}` is undocumented.", err_code);
-
- if error_codes.contains(&err_code) {
- errors.push(format!("Found duplicate error code: `{}`", err_code));
- }
-
- error_codes.push(err_code);
- } else if line == ";" {
- // Once we reach the undocumented error codes, adapt to different syntax.
- reached_undocumented_codes = true;
}
}
diff --git a/src/tools/tidy/src/ui_tests.rs b/src/tools/tidy/src/ui_tests.rs
index 806e84025..409f75631 100644
--- a/src/tools/tidy/src/ui_tests.rs
+++ b/src/tools/tidy/src/ui_tests.rs
@@ -9,8 +9,8 @@ use std::path::Path;
const ENTRY_LIMIT: usize = 1000;
// FIXME: The following limits should be reduced eventually.
-const ROOT_ENTRY_LIMIT: usize = 939;
-const ISSUES_ENTRY_LIMIT: usize = 1998;
+const ROOT_ENTRY_LIMIT: usize = 940;
+const ISSUES_ENTRY_LIMIT: usize = 1978;
fn check_entries(path: &Path, bad: &mut bool) {
for dir in Walk::new(&path.join("ui")) {
diff --git a/src/tools/x/Cargo.toml b/src/tools/x/Cargo.toml
index 315027279..84a42ca36 100644
--- a/src/tools/x/Cargo.toml
+++ b/src/tools/x/Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "x"
-version = "0.1.0"
+version = "0.1.1"
description = "Run x.py slightly more conveniently"
edition = "2021"
publish = false
diff --git a/src/tools/x/src/main.rs b/src/tools/x/src/main.rs
index 01f718785..5da8a2888 100644
--- a/src/tools/x/src/main.rs
+++ b/src/tools/x/src/main.rs
@@ -9,11 +9,47 @@
//! We also don't use `pwsh` on Windows, because it is not installed by default;
use std::{
- env, io,
+ env::{self, consts::EXE_EXTENSION},
+ io,
path::Path,
process::{self, Command, ExitStatus},
};
+const PYTHON: &str = "python";
+const PYTHON2: &str = "python2";
+const PYTHON3: &str = "python3";
+
+fn python() -> &'static str {
+ let val = match env::var_os("PATH") {
+ Some(val) => val,
+ None => return PYTHON,
+ };
+
+ let mut python2 = false;
+ let mut python3 = false;
+
+ for dir in env::split_paths(&val) {
+ // `python` should always take precedence over python2 / python3 if it exists
+ if dir.join(PYTHON).with_extension(EXE_EXTENSION).exists() {
+ return PYTHON;
+ }
+
+ python2 |= dir.join(PYTHON2).with_extension(EXE_EXTENSION).exists();
+ python3 |= dir.join(PYTHON3).with_extension(EXE_EXTENSION).exists();
+ }
+
+ // try 3 before 2
+ if python3 {
+ PYTHON3
+ } else if python2 {
+ PYTHON2
+ } else {
+ // Python was not found on path, so exit
+ eprintln!("Unable to find python in your PATH. Please check it is installed.");
+ process::exit(1);
+ }
+}
+
#[cfg(windows)]
fn x_command(dir: &Path) -> Command {
let mut cmd = Command::new("powershell.exe");
@@ -51,6 +87,17 @@ fn exec_or_status(command: &mut Command) -> io::Result<ExitStatus> {
command.status()
}
+fn handle_result(result: io::Result<ExitStatus>, cmd: Command) {
+ match result {
+ Err(error) => {
+ eprintln!("Failed to invoke `{:?}`: {}", cmd, error);
+ }
+ Ok(status) => {
+ process::exit(status.code().unwrap_or(1));
+ }
+ }
+}
+
fn main() {
match env::args().skip(1).next().as_deref() {
Some("--wrapper-version") => {
@@ -70,22 +117,19 @@ fn main() {
for dir in current.ancestors() {
let candidate = dir.join("x.py");
-
if candidate.exists() {
- let mut cmd = x_command(dir);
-
- cmd.args(env::args().skip(1)).current_dir(dir);
-
- let result = exec_or_status(&mut cmd);
-
- match result {
- Err(error) => {
- eprintln!("Failed to invoke `{:?}`: {}", cmd, error);
- }
- Ok(status) => {
- process::exit(status.code().unwrap_or(1));
- }
+ let shell_script_candidate = dir.join("x");
+ let mut cmd: Command;
+ if shell_script_candidate.exists() {
+ cmd = x_command(dir);
+ cmd.args(env::args().skip(1)).current_dir(dir);
+ } else {
+ // For older checkouts that do not have the x shell script, default to python
+ cmd = Command::new(python());
+ cmd.arg(&candidate).args(env::args().skip(1)).current_dir(dir);
}
+ let result = exec_or_status(&mut cmd);
+ handle_result(result, cmd);
}
}
diff --git a/src/version b/src/version
index 5deab586f..493498565 100644
--- a/src/version
+++ b/src/version
@@ -1 +1 @@
-1.68.2
+1.69.0
diff --git a/tests/assembly/align_offset.rs b/tests/assembly/align_offset.rs
index c5eefca34..116edf62b 100644
--- a/tests/assembly/align_offset.rs
+++ b/tests/assembly/align_offset.rs
@@ -1,7 +1,6 @@
// assembly-output: emit-asm
// compile-flags: -Copt-level=1
// only-x86_64
-// min-llvm-version: 14.0
#![crate_type="rlib"]
// CHECK-LABEL: align_offset_byte_ptr
diff --git a/tests/codegen/array-equality.rs b/tests/codegen/array-equality.rs
index cd5e82a92..abfe295f8 100644
--- a/tests/codegen/array-equality.rs
+++ b/tests/codegen/array-equality.rs
@@ -1,4 +1,4 @@
-// compile-flags: -O
+// compile-flags: -O -Z merge-functions=disabled
// only-x86_64
#![crate_type = "lib"]
@@ -43,6 +43,15 @@ pub fn array_eq_long(a: &[u16; 1234], b: &[u16; 1234]) -> bool {
a == b
}
+// CHECK-LABEL: @array_char_eq
+#[no_mangle]
+pub fn array_char_eq(a: [char; 2], b: [char; 2]) -> bool {
+ // CHECK-NEXT: start:
+ // CHECK-NEXT: %[[EQ:.+]] = icmp eq i64 %0, %1
+ // CHECK-NEXT: ret i1 %[[EQ]]
+ a == b
+}
+
// CHECK-LABEL: @array_eq_zero_short(i48
#[no_mangle]
pub fn array_eq_zero_short(x: [u16; 3]) -> bool {
@@ -52,6 +61,25 @@ pub fn array_eq_zero_short(x: [u16; 3]) -> bool {
x == [0; 3]
}
+// CHECK-LABEL: @array_eq_none_short(i40
+#[no_mangle]
+pub fn array_eq_none_short(x: [Option<std::num::NonZeroU8>; 5]) -> bool {
+ // CHECK-NEXT: start:
+ // CHECK-NEXT: %[[EQ:.+]] = icmp eq i40 %0, 0
+ // CHECK-NEXT: ret i1 %[[EQ]]
+ x == [None; 5]
+}
+
+// CHECK-LABEL: @array_eq_zero_nested(
+#[no_mangle]
+pub fn array_eq_zero_nested(x: [[u8; 3]; 3]) -> bool {
+ // CHECK: %[[VAL:.+]] = load i72
+ // CHECK-SAME: align 1
+ // CHECK: %[[EQ:.+]] = icmp eq i72 %[[VAL]], 0
+ // CHECK: ret i1 %[[EQ]]
+ x == [[0; 3]; 3]
+}
+
// CHECK-LABEL: @array_eq_zero_mid(
#[no_mangle]
pub fn array_eq_zero_mid(x: [u16; 8]) -> bool {
diff --git a/tests/codegen/array-map.rs b/tests/codegen/array-map.rs
new file mode 100644
index 000000000..9298e89e3
--- /dev/null
+++ b/tests/codegen/array-map.rs
@@ -0,0 +1,49 @@
+// compile-flags: -C opt-level=3 -C target-cpu=x86-64-v3
+// no-system-llvm
+// only-x86_64
+// ignore-debug (the extra assertions get in the way)
+
+#![crate_type = "lib"]
+#![feature(array_zip)]
+
+// CHECK-LABEL: @short_integer_map
+#[no_mangle]
+pub fn short_integer_map(x: [u32; 8]) -> [u32; 8] {
+ // CHECK: load <8 x i32>
+ // CHECK: shl <8 x i32>
+ // CHECK: or <8 x i32>
+ // CHECK: store <8 x i32>
+ x.map(|x| 2 * x + 1)
+}
+
+// CHECK-LABEL: @short_integer_zip_map
+#[no_mangle]
+pub fn short_integer_zip_map(x: [u32; 8], y: [u32; 8]) -> [u32; 8] {
+ // CHECK: %[[A:.+]] = load <8 x i32>
+ // CHECK: %[[B:.+]] = load <8 x i32>
+ // CHECK: sub <8 x i32> %[[A]], %[[B]]
+ // CHECK: store <8 x i32>
+ x.zip(y).map(|(x, y)| x - y)
+}
+
+// This test is checking that LLVM can SRoA away a bunch of the overhead,
+// like fully moving the iterators to registers. Notably, previous implementations
+// of `map` ended up `alloca`ing the whole `array::IntoIterator`, meaning both a
+// hard-to-eliminate `memcpy` and that the iteration counts needed to be written
+// out to stack every iteration, even for infallible operations on `Copy` types.
+//
+// This is still imperfect, as there's more copies than would be ideal,
+// but hopefully work like #103830 will improve that in future,
+// and update this test to be stricter.
+//
+// CHECK-LABEL: @long_integer_map
+#[no_mangle]
+pub fn long_integer_map(x: [u32; 64]) -> [u32; 64] {
+ // CHECK: start:
+ // CHECK-NEXT: alloca [64 x i32]
+ // CHECK-NEXT: alloca %"core::mem::manually_drop::ManuallyDrop<[u32; 64]>"
+ // CHECK-NOT: alloca
+ // CHECK: mul <{{[0-9]+}} x i32>
+ // CHECK: add <{{[0-9]+}} x i32>
+ x.map(|x| 13 * x + 7)
+}
diff --git a/tests/codegen/autovectorize-f32x4.rs b/tests/codegen/autovectorize-f32x4.rs
index 6b09c8fc9..9ecea53f1 100644
--- a/tests/codegen/autovectorize-f32x4.rs
+++ b/tests/codegen/autovectorize-f32x4.rs
@@ -1,6 +1,7 @@
-// compile-flags: -C opt-level=3
+// compile-flags: -C opt-level=3 -Z merge-functions=disabled
// only-x86_64
#![crate_type = "lib"]
+#![feature(array_zip)]
// CHECK-LABEL: @auto_vectorize_direct
#[no_mangle]
@@ -30,3 +31,13 @@ pub fn auto_vectorize_loop(a: [f32; 4], b: [f32; 4]) -> [f32; 4] {
}
c
}
+
+// CHECK-LABEL: @auto_vectorize_array_zip_map
+#[no_mangle]
+pub fn auto_vectorize_array_zip_map(a: [f32; 4], b: [f32; 4]) -> [f32; 4] {
+// CHECK: load <4 x float>
+// CHECK: load <4 x float>
+// CHECK: fadd <4 x float>
+// CHECK: store <4 x float>
+ a.zip(b).map(|(a, b)| a + b)
+}
diff --git a/tests/codegen/avr/avr-func-addrspace.rs b/tests/codegen/avr/avr-func-addrspace.rs
index e9740e30d..bc11e1081 100644
--- a/tests/codegen/avr/avr-func-addrspace.rs
+++ b/tests/codegen/avr/avr-func-addrspace.rs
@@ -109,3 +109,28 @@ pub unsafe fn transmute_fn_ptr_to_data(x: fn()) -> *const () {
// as long as it doesn't cause a verifier error by using `bitcast`.
transmute(x)
}
+
+pub enum Either<T, U> { A(T), B(U) }
+
+// Previously, we would codegen this as passing/returning a scalar pair of `{ i8, ptr }`,
+// with the `ptr` field representing both `&i32` and `fn()` depending on the variant.
+// This is incorrect, because `fn()` should be `ptr addrspace(1)`, not `ptr`.
+
+// CHECK: define{{.+}}void @should_not_combine_addrspace({{.+\*|ptr}}{{.+}}sret{{.+}}%0, {{.+\*|ptr}}{{.+}}%x)
+#[no_mangle]
+#[inline(never)]
+pub fn should_not_combine_addrspace(x: Either<&i32, fn()>) -> Either<&i32, fn()> {
+ x
+}
+
+// The incorrectness described above would result in us producing (after optimizations)
+// a `ptrtoint`/`inttoptr` roundtrip to convert from `ptr` to `ptr addrspace(1)`.
+
+// CHECK-LABEL: @call_with_fn_ptr
+#[no_mangle]
+pub fn call_with_fn_ptr<'a>(f: fn()) -> Either<&'a i32, fn()> {
+ // CHECK-NOT: ptrtoint
+ // CHECK-NOT: inttoptr
+ // CHECK: call addrspace(1) void @should_not_combine_addrspace
+ should_not_combine_addrspace(Either::B(f))
+}
diff --git a/tests/codegen/consts.rs b/tests/codegen/consts.rs
index 260d9de86..dd22fd0f7 100644
--- a/tests/codegen/consts.rs
+++ b/tests/codegen/consts.rs
@@ -1,5 +1,4 @@
// compile-flags: -C no-prepopulate-passes
-// min-llvm-version: 14.0
#![crate_type = "lib"]
@@ -10,11 +9,11 @@
// CHECK: @STATIC = {{.*}}, align 4
// This checks the constants from inline_enum_const
-// CHECK: @alloc12 = {{.*}}, align 2
+// CHECK: @alloc_76bfe2f13a3e3b01074971d122eac57e = {{.*}}, align 2
// This checks the constants from {low,high}_align_const, they share the same
// constant, but the alignment differs, so the higher one should be used
-// CHECK: [[LOW_HIGH:@alloc[0-9]+]] = {{.*}}, align 4
+// CHECK: [[LOW_HIGH:@alloc_[a-f0-9]+]] = {{.*}}, align 4
#[derive(Copy, Clone)]
// repr(i16) is required for the {low,high}_align_const test
diff --git a/tests/codegen/debug-vtable.rs b/tests/codegen/debug-vtable.rs
index bdd312878..d82b737de 100644
--- a/tests/codegen/debug-vtable.rs
+++ b/tests/codegen/debug-vtable.rs
@@ -9,6 +9,14 @@
// compile-flags: -Cdebuginfo=2 -Copt-level=0 -Csymbol-mangling-version=v0
// ignore-tidy-linelength
+// Make sure that vtables don't have the unnamed_addr attribute when debuginfo is enabled.
+// This helps debuggers more reliably map from dyn pointer to concrete type.
+// CHECK: @vtable.0 = private constant <{
+// CHECK: @vtable.1 = private constant <{
+// CHECK: @vtable.2 = private constant <{
+// CHECK: @vtable.3 = private constant <{
+// CHECK: @vtable.4 = private constant <{
+
// NONMSVC: ![[USIZE:[0-9]+]] = !DIBasicType(name: "usize"
// MSVC: ![[USIZE:[0-9]+]] = !DIDerivedType(tag: DW_TAG_typedef, name: "usize"
// NONMSVC: ![[PTR:[0-9]+]] = !DIDerivedType(tag: DW_TAG_pointer_type, name: "*const ()"
diff --git a/tests/codegen/function-arguments-noopt.rs b/tests/codegen/function-arguments-noopt.rs
index ff76405a4..0c62e0d35 100644
--- a/tests/codegen/function-arguments-noopt.rs
+++ b/tests/codegen/function-arguments-noopt.rs
@@ -29,6 +29,12 @@ pub fn borrow(x: &i32) -> &i32 {
x
}
+// CHECK: align 4 {{i32\*|ptr}} @borrow_mut({{i32\*|ptr}} align 4 %x)
+#[no_mangle]
+pub fn borrow_mut(x: &mut i32) -> &mut i32 {
+ x
+}
+
// CHECK-LABEL: @borrow_call
#[no_mangle]
pub fn borrow_call(x: &i32, f: fn(&i32) -> &i32) -> &i32 {
diff --git a/tests/codegen/function-arguments.rs b/tests/codegen/function-arguments.rs
index 1f979d7b9..d6f019016 100644
--- a/tests/codegen/function-arguments.rs
+++ b/tests/codegen/function-arguments.rs
@@ -1,6 +1,7 @@
// compile-flags: -O -C no-prepopulate-passes
#![crate_type = "lib"]
+#![feature(dyn_star)]
use std::mem::MaybeUninit;
use std::num::NonZeroU64;
@@ -85,6 +86,12 @@ pub fn option_nonzero_int(x: Option<NonZeroU64>) -> Option<NonZeroU64> {
pub fn readonly_borrow(_: &i32) {
}
+// CHECK: noundef align 4 dereferenceable(4) {{i32\*|ptr}} @readonly_borrow_ret()
+#[no_mangle]
+pub fn readonly_borrow_ret() -> &'static i32 {
+ loop {}
+}
+
// CHECK: @static_borrow({{i32\*|ptr}} noalias noundef readonly align 4 dereferenceable(4) %_1)
// static borrow may be captured
#[no_mangle]
@@ -115,9 +122,17 @@ pub fn mutable_unsafe_borrow(_: &mut UnsafeInner) {
pub fn mutable_borrow(_: &mut i32) {
}
+// CHECK: noundef align 4 dereferenceable(4) {{i32\*|ptr}} @mutable_borrow_ret()
#[no_mangle]
-// CHECK: @mutable_notunpin_borrow({{i32\*|ptr}} noundef align 4 dereferenceable(4) %_1)
+pub fn mutable_borrow_ret() -> &'static mut i32 {
+ loop {}
+}
+
+#[no_mangle]
+// CHECK: @mutable_notunpin_borrow({{i32\*|ptr}} noundef nonnull align 4 %_1)
// This one is *not* `noalias` because it might be self-referential.
+// It is also not `dereferenceable` due to
+// <https://github.com/rust-lang/unsafe-code-guidelines/issues/381>.
pub fn mutable_notunpin_borrow(_: &mut NotUnpin) {
}
@@ -167,6 +182,12 @@ pub fn _box(x: Box<i32>) -> Box<i32> {
x
}
+// CHECK: noundef nonnull align 4 {{i32\*|ptr}} @notunpin_box({{i32\*|ptr}} noundef nonnull align 4 %x)
+#[no_mangle]
+pub fn notunpin_box(x: Box<NotUnpin>) -> Box<NotUnpin> {
+ x
+}
+
// CHECK: @struct_return({{%S\*|ptr}} noalias nocapture noundef sret(%S) dereferenceable(32){{( %0)?}})
#[no_mangle]
pub fn struct_return() -> S {
@@ -233,12 +254,12 @@ pub fn trait_raw(_: *const dyn Drop) {
// CHECK: @trait_box({{\{\}\*|ptr}} noalias noundef nonnull align 1{{( %0)?}}, {{.+}} noalias noundef readonly align {{.*}} dereferenceable({{.*}}){{( %1)?}})
#[no_mangle]
-pub fn trait_box(_: Box<dyn Drop>) {
+pub fn trait_box(_: Box<dyn Drop + Unpin>) {
}
// CHECK: { {{i8\*|ptr}}, {{i8\*|ptr}} } @trait_option({{i8\*|ptr}} noalias noundef align 1 %x.0, {{i8\*|ptr}} %x.1)
#[no_mangle]
-pub fn trait_option(x: Option<Box<dyn Drop>>) -> Option<Box<dyn Drop>> {
+pub fn trait_option(x: Option<Box<dyn Drop + Unpin>>) -> Option<Box<dyn Drop + Unpin>> {
x
}
@@ -259,3 +280,11 @@ pub fn enum_id_1(x: Option<Result<u16, u16>>) -> Option<Result<u16, u16>> {
pub fn enum_id_2(x: Option<u8>) -> Option<u8> {
x
}
+
+// CHECK: { {{\{\}\*|ptr}}, {{.+}} } @dyn_star({{\{\}\*|ptr}} noundef %x.0, {{.+}} noalias noundef readonly align {{.*}} dereferenceable({{.*}}) %x.1)
+// Expect an ABI something like `{ {}*, [3 x i64]* }`, but that's hard to match on generically,
+// so do like the `trait_box` test and just match on `{{.+}}` for the vtable.
+#[no_mangle]
+pub fn dyn_star(x: dyn* Drop) -> dyn* Drop {
+ x
+}
diff --git a/tests/codegen/inherit_overflow.rs b/tests/codegen/inherit_overflow.rs
new file mode 100644
index 000000000..0b0b890b2
--- /dev/null
+++ b/tests/codegen/inherit_overflow.rs
@@ -0,0 +1,14 @@
+// compile-flags: -Zmir-enable-passes=+Inline,+ConstProp --crate-type lib
+// revisions: ASSERT NOASSERT
+//[ASSERT] compile-flags: -Coverflow-checks=on
+//[NOASSERT] compile-flags: -Coverflow-checks=off
+
+// CHECK-LABEL: define{{.*}} @assertion
+// ASSERT: call void @_ZN4core9panicking5panic17h
+// NOASSERT: ret i8 0
+#[no_mangle]
+pub fn assertion() -> u8 {
+ // Optimized MIR will replace this `CheckedBinaryOp` by `const (0, true)`.
+ // Verify that codegen does or does not emit the panic.
+ <u8 as std::ops::Add>::add(255, 1)
+}
diff --git a/tests/codegen/instrument-xray/basic.rs b/tests/codegen/instrument-xray/basic.rs
new file mode 100644
index 000000000..d3e49d531
--- /dev/null
+++ b/tests/codegen/instrument-xray/basic.rs
@@ -0,0 +1,9 @@
+// Checks that `-Z instrument-xray` produces expected instrumentation.
+//
+// needs-xray
+// compile-flags: -Z instrument-xray=always
+
+#![crate_type = "lib"]
+
+// CHECK: attributes #{{.*}} "function-instrument"="xray-always"
+pub fn function() {}
diff --git a/tests/codegen/instrument-xray/options-combine.rs b/tests/codegen/instrument-xray/options-combine.rs
new file mode 100644
index 000000000..f7e500b65
--- /dev/null
+++ b/tests/codegen/instrument-xray/options-combine.rs
@@ -0,0 +1,12 @@
+// Checks that `-Z instrument-xray` options can be specified multiple times.
+//
+// needs-xray
+// compile-flags: -Z instrument-xray=skip-exit
+// compile-flags: -Z instrument-xray=instruction-threshold=123
+// compile-flags: -Z instrument-xray=instruction-threshold=456
+
+#![crate_type = "lib"]
+
+// CHECK: attributes #{{.*}} "xray-instruction-threshold"="456" "xray-skip-exit"
+// CHECK-NOT: attributes #{{.*}} "xray-instruction-threshold"="123"
+pub fn function() {}
diff --git a/tests/codegen/instrument-xray/options-override.rs b/tests/codegen/instrument-xray/options-override.rs
new file mode 100644
index 000000000..00f818379
--- /dev/null
+++ b/tests/codegen/instrument-xray/options-override.rs
@@ -0,0 +1,11 @@
+// Checks that the last `-Z instrument-xray` option wins.
+//
+// needs-xray
+// compile-flags: -Z instrument-xray=always
+// compile-flags: -Z instrument-xray=never
+
+#![crate_type = "lib"]
+
+// CHECK: attributes #{{.*}} "function-instrument"="xray-never"
+// CHECK-NOT: attributes #{{.*}} "function-instrument"="xray-always"
+pub fn function() {}
diff --git a/tests/codegen/issue-75659.rs b/tests/codegen/issue-75659.rs
index 6bcb59aff..9394868c0 100644
--- a/tests/codegen/issue-75659.rs
+++ b/tests/codegen/issue-75659.rs
@@ -1,7 +1,7 @@
// This test checks that the call to memchr/slice_contains is optimized away
// when searching in small slices.
-// compile-flags: -O -Zinline-mir=no
+// compile-flags: -O -Zinline-mir=false
// only-x86_64
#![crate_type = "lib"]
diff --git a/tests/codegen/merge-functions.rs b/tests/codegen/merge-functions.rs
index 8e8fe5c96..d6caeeee8 100644
--- a/tests/codegen/merge-functions.rs
+++ b/tests/codegen/merge-functions.rs
@@ -1,4 +1,3 @@
-// min-llvm-version: 14.0
// revisions: O Os
//[Os] compile-flags: -Copt-level=s
//[O] compile-flags: -O
diff --git a/tests/codegen/move-operands.rs b/tests/codegen/move-operands.rs
index 6c51324a3..1d8209e8e 100644
--- a/tests/codegen/move-operands.rs
+++ b/tests/codegen/move-operands.rs
@@ -1,4 +1,4 @@
-// compile-flags: -C no-prepopulate-passes -Zmir-enable-passes=+DestinationPropagation
+// compile-flags: -C no-prepopulate-passes -Zmir-enable-passes=+DestinationPropagation,-CopyProp
#![crate_type = "lib"]
diff --git a/tests/codegen/option-as-slice.rs b/tests/codegen/option-as-slice.rs
new file mode 100644
index 000000000..d5077dbf6
--- /dev/null
+++ b/tests/codegen/option-as-slice.rs
@@ -0,0 +1,28 @@
+// compile-flags: -O
+// only-x86_64
+
+#![crate_type = "lib"]
+#![feature(option_as_slice)]
+
+extern crate core;
+
+use core::num::NonZeroU64;
+use core::option::Option;
+
+// CHECK-LABEL: @u64_opt_as_slice
+#[no_mangle]
+pub fn u64_opt_as_slice(o: &Option<u64>) -> &[u64] {
+ // CHECK: start:
+ // CHECK-NOT: select
+ // CHECK: ret
+ o.as_slice()
+}
+
+// CHECK-LABEL: @nonzero_u64_opt_as_slice
+#[no_mangle]
+pub fn nonzero_u64_opt_as_slice(o: &Option<NonZeroU64>) -> &[NonZeroU64] {
+ // CHECK: start:
+ // CHECK-NOT: select
+ // CHECK: ret
+ o.as_slice()
+}
diff --git a/tests/codegen/option-nonzero-eq.rs b/tests/codegen/option-nonzero-eq.rs
index 598dcc19b..835decd3e 100644
--- a/tests/codegen/option-nonzero-eq.rs
+++ b/tests/codegen/option-nonzero-eq.rs
@@ -3,6 +3,7 @@
#![crate_type = "lib"]
extern crate core;
+use core::cmp::Ordering;
use core::num::{NonZeroU32, NonZeroI64};
use core::ptr::NonNull;
@@ -32,3 +33,12 @@ pub fn non_null_eq(l: Option<NonNull<u8>>, r: Option<NonNull<u8>>) -> bool {
// CHECK-NEXT: ret i1
l == r
}
+
+// CHECK-lABEL: @ordering_eq
+#[no_mangle]
+pub fn ordering_eq(l: Option<Ordering>, r: Option<Ordering>) -> bool {
+ // CHECK: start:
+ // CHECK-NEXT: icmp eq i8
+ // CHECK-NEXT: ret i1
+ l == r
+}
diff --git a/tests/codegen/remap_path_prefix/main.rs b/tests/codegen/remap_path_prefix/main.rs
index 78ebbccfc..6c0cd6997 100644
--- a/tests/codegen/remap_path_prefix/main.rs
+++ b/tests/codegen/remap_path_prefix/main.rs
@@ -12,7 +12,7 @@ mod aux_mod;
include!("aux_mod.rs");
// Here we check that the expansion of the file!() macro is mapped.
-// CHECK: @alloc2 = private unnamed_addr constant <{ [34 x i8] }> <{ [34 x i8] c"/the/src/remap_path_prefix/main.rs" }>
+// CHECK: @alloc_92a59126a55aa3c0019b6c8a007fe001 = private unnamed_addr constant <{ [34 x i8] }> <{ [34 x i8] c"/the/src/remap_path_prefix/main.rs" }>
pub static FILE_PATH: &'static str = file!();
fn main() {
diff --git a/tests/codegen/sanitizer-kasan-emits-instrumentation.rs b/tests/codegen/sanitizer-kasan-emits-instrumentation.rs
new file mode 100644
index 000000000..d6e3f2719
--- /dev/null
+++ b/tests/codegen/sanitizer-kasan-emits-instrumentation.rs
@@ -0,0 +1,47 @@
+// Verifies that `-Zsanitizer=kernel-address` emits sanitizer instrumentation.
+
+// compile-flags: -Zsanitizer=kernel-address
+// revisions: aarch64 riscv64imac riscv64gc x86_64
+//[aarch64] compile-flags: --target aarch64-unknown-none
+//[aarch64] needs-llvm-components: aarch64
+//[riscv64imac] compile-flags: --target riscv64imac-unknown-none-elf
+//[riscv64imac] needs-llvm-components: riscv
+//[riscv64imac] min-llvm-version: 16
+//[riscv64gc] compile-flags: --target riscv64gc-unknown-none-elf
+//[riscv64gc] needs-llvm-components: riscv
+//[riscv64gc] min-llvm-version: 16
+//[x86_64] compile-flags: --target x86_64-unknown-none
+//[x86_64] needs-llvm-components: x86
+
+#![crate_type = "rlib"]
+#![feature(no_core, no_sanitize, lang_items)]
+#![no_core]
+
+#[lang = "sized"]
+trait Sized {}
+
+#[lang = "copy"]
+trait Copy {}
+
+impl Copy for u8 {}
+
+// CHECK-LABEL: ; sanitizer_kasan_emits_instrumentation::unsanitized
+// CHECK-NEXT: ; Function Attrs:
+// CHECK-NOT: sanitize_address
+// CHECK: start:
+// CHECK-NOT: call void @__asan_report_load
+// CHECK: }
+#[no_sanitize(address)]
+pub fn unsanitized(b: &mut u8) -> u8 {
+ *b
+}
+
+// CHECK-LABEL: ; sanitizer_kasan_emits_instrumentation::sanitized
+// CHECK-NEXT: ; Function Attrs:
+// CHECK: sanitize_address
+// CHECK: start:
+// CHECK: call void @__asan_report_load
+// CHECK: }
+pub fn sanitized(b: &mut u8) -> u8 {
+ *b
+}
diff --git a/tests/codegen/simd-intrinsic/simd-intrinsic-generic-arithmetic-saturating.rs b/tests/codegen/simd-intrinsic/simd-intrinsic-generic-arithmetic-saturating.rs
index 6fb0ceb40..faac7566a 100644
--- a/tests/codegen/simd-intrinsic/simd-intrinsic-generic-arithmetic-saturating.rs
+++ b/tests/codegen/simd-intrinsic/simd-intrinsic-generic-arithmetic-saturating.rs
@@ -116,150 +116,150 @@ extern "platform-intrinsic" {
fn simd_saturating_sub<T>(x: T, y: T) -> T;
}
-// NOTE(eddyb) `%{{x|_3}}` is used because on some targets (e.g. WASM)
+// NOTE(eddyb) `%{{x|1}}` is used because on some targets (e.g. WASM)
// SIMD vectors are passed directly, resulting in `%x` being a vector,
// while on others they're passed indirectly, resulting in `%x` being
-// a pointer to a vector, and `%_3` a vector loaded from that pointer.
+// a pointer to a vector, and `%1` a vector loaded from that pointer.
// This is controlled by the target spec option `simd_types_indirect`.
-// The same applies to `%{{y|_4}}` as well.
+// The same applies to `%{{y|2}}` as well.
// CHECK-LABEL: @sadd_i8x2
#[no_mangle]
pub unsafe fn sadd_i8x2(x: i8x2, y: i8x2) -> i8x2 {
- // CHECK: %{{[0-9]+}} = call <2 x i8> @llvm.sadd.sat.v2i8(<2 x i8> %{{x|_3}}, <2 x i8> %{{y|_4}})
+ // CHECK: %{{[0-9]+}} = call <2 x i8> @llvm.sadd.sat.v2i8(<2 x i8> %{{x|1}}, <2 x i8> %{{y|2}})
simd_saturating_add(x, y)
}
// CHECK-LABEL: @sadd_i8x4
#[no_mangle]
pub unsafe fn sadd_i8x4(x: i8x4, y: i8x4) -> i8x4 {
- // CHECK: %{{[0-9]+}} = call <4 x i8> @llvm.sadd.sat.v4i8(<4 x i8> %{{x|_3}}, <4 x i8> %{{y|_4}})
+ // CHECK: %{{[0-9]+}} = call <4 x i8> @llvm.sadd.sat.v4i8(<4 x i8> %{{x|1}}, <4 x i8> %{{y|2}})
simd_saturating_add(x, y)
}
// CHECK-LABEL: @sadd_i8x8
#[no_mangle]
pub unsafe fn sadd_i8x8(x: i8x8, y: i8x8) -> i8x8 {
- // CHECK: %{{[0-9]+}} = call <8 x i8> @llvm.sadd.sat.v8i8(<8 x i8> %{{x|_3}}, <8 x i8> %{{y|_4}})
+ // CHECK: %{{[0-9]+}} = call <8 x i8> @llvm.sadd.sat.v8i8(<8 x i8> %{{x|1}}, <8 x i8> %{{y|2}})
simd_saturating_add(x, y)
}
// CHECK-LABEL: @sadd_i8x16
#[no_mangle]
pub unsafe fn sadd_i8x16(x: i8x16, y: i8x16) -> i8x16 {
- // CHECK: %{{[0-9]+}} = call <16 x i8> @llvm.sadd.sat.v16i8(<16 x i8> %{{x|_3}}, <16 x i8> %{{y|_4}})
+ // CHECK: %{{[0-9]+}} = call <16 x i8> @llvm.sadd.sat.v16i8(<16 x i8> %{{x|1}}, <16 x i8> %{{y|2}})
simd_saturating_add(x, y)
}
// CHECK-LABEL: @sadd_i8x32
#[no_mangle]
pub unsafe fn sadd_i8x32(x: i8x32, y: i8x32) -> i8x32 {
- // CHECK: %{{[0-9]+}} = call <32 x i8> @llvm.sadd.sat.v32i8(<32 x i8> %{{x|_3}}, <32 x i8> %{{y|_4}})
+ // CHECK: %{{[0-9]+}} = call <32 x i8> @llvm.sadd.sat.v32i8(<32 x i8> %{{x|1}}, <32 x i8> %{{y|2}})
simd_saturating_add(x, y)
}
// CHECK-LABEL: @sadd_i8x64
#[no_mangle]
pub unsafe fn sadd_i8x64(x: i8x64, y: i8x64) -> i8x64 {
- // CHECK: %{{[0-9]+}} = call <64 x i8> @llvm.sadd.sat.v64i8(<64 x i8> %{{x|_3}}, <64 x i8> %{{y|_4}})
+ // CHECK: %{{[0-9]+}} = call <64 x i8> @llvm.sadd.sat.v64i8(<64 x i8> %{{x|1}}, <64 x i8> %{{y|2}})
simd_saturating_add(x, y)
}
// CHECK-LABEL: @sadd_i16x2
#[no_mangle]
pub unsafe fn sadd_i16x2(x: i16x2, y: i16x2) -> i16x2 {
- // CHECK: %{{[0-9]+}} = call <2 x i16> @llvm.sadd.sat.v2i16(<2 x i16> %{{x|_3}}, <2 x i16> %{{y|_4}})
+ // CHECK: %{{[0-9]+}} = call <2 x i16> @llvm.sadd.sat.v2i16(<2 x i16> %{{x|1}}, <2 x i16> %{{y|2}})
simd_saturating_add(x, y)
}
// CHECK-LABEL: @sadd_i16x4
#[no_mangle]
pub unsafe fn sadd_i16x4(x: i16x4, y: i16x4) -> i16x4 {
- // CHECK: %{{[0-9]+}} = call <4 x i16> @llvm.sadd.sat.v4i16(<4 x i16> %{{x|_3}}, <4 x i16> %{{y|_4}})
+ // CHECK: %{{[0-9]+}} = call <4 x i16> @llvm.sadd.sat.v4i16(<4 x i16> %{{x|1}}, <4 x i16> %{{y|2}})
simd_saturating_add(x, y)
}
// CHECK-LABEL: @sadd_i16x8
#[no_mangle]
pub unsafe fn sadd_i16x8(x: i16x8, y: i16x8) -> i16x8 {
- // CHECK: %{{[0-9]+}} = call <8 x i16> @llvm.sadd.sat.v8i16(<8 x i16> %{{x|_3}}, <8 x i16> %{{y|_4}})
+ // CHECK: %{{[0-9]+}} = call <8 x i16> @llvm.sadd.sat.v8i16(<8 x i16> %{{x|1}}, <8 x i16> %{{y|2}})
simd_saturating_add(x, y)
}
// CHECK-LABEL: @sadd_i16x16
#[no_mangle]
pub unsafe fn sadd_i16x16(x: i16x16, y: i16x16) -> i16x16 {
- // CHECK: %{{[0-9]+}} = call <16 x i16> @llvm.sadd.sat.v16i16(<16 x i16> %{{x|_3}}, <16 x i16> %{{y|_4}})
+ // CHECK: %{{[0-9]+}} = call <16 x i16> @llvm.sadd.sat.v16i16(<16 x i16> %{{x|1}}, <16 x i16> %{{y|2}})
simd_saturating_add(x, y)
}
// CHECK-LABEL: @sadd_i16x32
#[no_mangle]
pub unsafe fn sadd_i16x32(x: i16x32, y: i16x32) -> i16x32 {
- // CHECK: %{{[0-9]+}} = call <32 x i16> @llvm.sadd.sat.v32i16(<32 x i16> %{{x|_3}}, <32 x i16> %{{y|_4}})
+ // CHECK: %{{[0-9]+}} = call <32 x i16> @llvm.sadd.sat.v32i16(<32 x i16> %{{x|1}}, <32 x i16> %{{y|2}})
simd_saturating_add(x, y)
}
// CHECK-LABEL: @sadd_i32x2
#[no_mangle]
pub unsafe fn sadd_i32x2(x: i32x2, y: i32x2) -> i32x2 {
- // CHECK: %{{[0-9]+}} = call <2 x i32> @llvm.sadd.sat.v2i32(<2 x i32> %{{x|_3}}, <2 x i32> %{{y|_4}})
+ // CHECK: %{{[0-9]+}} = call <2 x i32> @llvm.sadd.sat.v2i32(<2 x i32> %{{x|1}}, <2 x i32> %{{y|2}})
simd_saturating_add(x, y)
}
// CHECK-LABEL: @sadd_i32x4
#[no_mangle]
pub unsafe fn sadd_i32x4(x: i32x4, y: i32x4) -> i32x4 {
- // CHECK: %{{[0-9]+}} = call <4 x i32> @llvm.sadd.sat.v4i32(<4 x i32> %{{x|_3}}, <4 x i32> %{{y|_4}})
+ // CHECK: %{{[0-9]+}} = call <4 x i32> @llvm.sadd.sat.v4i32(<4 x i32> %{{x|1}}, <4 x i32> %{{y|2}})
simd_saturating_add(x, y)
}
// CHECK-LABEL: @sadd_i32x8
#[no_mangle]
pub unsafe fn sadd_i32x8(x: i32x8, y: i32x8) -> i32x8 {
- // CHECK: %{{[0-9]+}} = call <8 x i32> @llvm.sadd.sat.v8i32(<8 x i32> %{{x|_3}}, <8 x i32> %{{y|_4}})
+ // CHECK: %{{[0-9]+}} = call <8 x i32> @llvm.sadd.sat.v8i32(<8 x i32> %{{x|1}}, <8 x i32> %{{y|2}})
simd_saturating_add(x, y)
}
// CHECK-LABEL: @sadd_i32x16
#[no_mangle]
pub unsafe fn sadd_i32x16(x: i32x16, y: i32x16) -> i32x16 {
- // CHECK: %{{[0-9]+}} = call <16 x i32> @llvm.sadd.sat.v16i32(<16 x i32> %{{x|_3}}, <16 x i32> %{{y|_4}})
+ // CHECK: %{{[0-9]+}} = call <16 x i32> @llvm.sadd.sat.v16i32(<16 x i32> %{{x|1}}, <16 x i32> %{{y|2}})
simd_saturating_add(x, y)
}
// CHECK-LABEL: @sadd_i64x2
#[no_mangle]
pub unsafe fn sadd_i64x2(x: i64x2, y: i64x2) -> i64x2 {
- // CHECK: %{{[0-9]+}} = call <2 x i64> @llvm.sadd.sat.v2i64(<2 x i64> %{{x|_3}}, <2 x i64> %{{y|_4}})
+ // CHECK: %{{[0-9]+}} = call <2 x i64> @llvm.sadd.sat.v2i64(<2 x i64> %{{x|1}}, <2 x i64> %{{y|2}})
simd_saturating_add(x, y)
}
// CHECK-LABEL: @sadd_i64x4
#[no_mangle]
pub unsafe fn sadd_i64x4(x: i64x4, y: i64x4) -> i64x4 {
- // CHECK: %{{[0-9]+}} = call <4 x i64> @llvm.sadd.sat.v4i64(<4 x i64> %{{x|_3}}, <4 x i64> %{{y|_4}})
+ // CHECK: %{{[0-9]+}} = call <4 x i64> @llvm.sadd.sat.v4i64(<4 x i64> %{{x|1}}, <4 x i64> %{{y|2}})
simd_saturating_add(x, y)
}
// CHECK-LABEL: @sadd_i64x8
#[no_mangle]
pub unsafe fn sadd_i64x8(x: i64x8, y: i64x8) -> i64x8 {
- // CHECK: %{{[0-9]+}} = call <8 x i64> @llvm.sadd.sat.v8i64(<8 x i64> %{{x|_3}}, <8 x i64> %{{y|_4}})
+ // CHECK: %{{[0-9]+}} = call <8 x i64> @llvm.sadd.sat.v8i64(<8 x i64> %{{x|1}}, <8 x i64> %{{y|2}})
simd_saturating_add(x, y)
}
// CHECK-LABEL: @sadd_i128x2
#[no_mangle]
pub unsafe fn sadd_i128x2(x: i128x2, y: i128x2) -> i128x2 {
- // CHECK: %{{[0-9]+}} = call <2 x i128> @llvm.sadd.sat.v2i128(<2 x i128> %{{x|_3}}, <2 x i128> %{{y|_4}})
+ // CHECK: %{{[0-9]+}} = call <2 x i128> @llvm.sadd.sat.v2i128(<2 x i128> %{{x|1}}, <2 x i128> %{{y|2}})
simd_saturating_add(x, y)
}
// CHECK-LABEL: @sadd_i128x4
#[no_mangle]
pub unsafe fn sadd_i128x4(x: i128x4, y: i128x4) -> i128x4 {
- // CHECK: %{{[0-9]+}} = call <4 x i128> @llvm.sadd.sat.v4i128(<4 x i128> %{{x|_3}}, <4 x i128> %{{y|_4}})
+ // CHECK: %{{[0-9]+}} = call <4 x i128> @llvm.sadd.sat.v4i128(<4 x i128> %{{x|1}}, <4 x i128> %{{y|2}})
simd_saturating_add(x, y)
}
@@ -268,140 +268,140 @@ pub unsafe fn sadd_i128x4(x: i128x4, y: i128x4) -> i128x4 {
// CHECK-LABEL: @uadd_u8x2
#[no_mangle]
pub unsafe fn uadd_u8x2(x: u8x2, y: u8x2) -> u8x2 {
- // CHECK: %{{[0-9]+}} = call <2 x i8> @llvm.uadd.sat.v2i8(<2 x i8> %{{x|_3}}, <2 x i8> %{{y|_4}})
+ // CHECK: %{{[0-9]+}} = call <2 x i8> @llvm.uadd.sat.v2i8(<2 x i8> %{{x|1}}, <2 x i8> %{{y|2}})
simd_saturating_add(x, y)
}
// CHECK-LABEL: @uadd_u8x4
#[no_mangle]
pub unsafe fn uadd_u8x4(x: u8x4, y: u8x4) -> u8x4 {
- // CHECK: %{{[0-9]+}} = call <4 x i8> @llvm.uadd.sat.v4i8(<4 x i8> %{{x|_3}}, <4 x i8> %{{y|_4}})
+ // CHECK: %{{[0-9]+}} = call <4 x i8> @llvm.uadd.sat.v4i8(<4 x i8> %{{x|1}}, <4 x i8> %{{y|2}})
simd_saturating_add(x, y)
}
// CHECK-LABEL: @uadd_u8x8
#[no_mangle]
pub unsafe fn uadd_u8x8(x: u8x8, y: u8x8) -> u8x8 {
- // CHECK: %{{[0-9]+}} = call <8 x i8> @llvm.uadd.sat.v8i8(<8 x i8> %{{x|_3}}, <8 x i8> %{{y|_4}})
+ // CHECK: %{{[0-9]+}} = call <8 x i8> @llvm.uadd.sat.v8i8(<8 x i8> %{{x|1}}, <8 x i8> %{{y|2}})
simd_saturating_add(x, y)
}
// CHECK-LABEL: @uadd_u8x16
#[no_mangle]
pub unsafe fn uadd_u8x16(x: u8x16, y: u8x16) -> u8x16 {
- // CHECK: %{{[0-9]+}} = call <16 x i8> @llvm.uadd.sat.v16i8(<16 x i8> %{{x|_3}}, <16 x i8> %{{y|_4}})
+ // CHECK: %{{[0-9]+}} = call <16 x i8> @llvm.uadd.sat.v16i8(<16 x i8> %{{x|1}}, <16 x i8> %{{y|2}})
simd_saturating_add(x, y)
}
// CHECK-LABEL: @uadd_u8x32
#[no_mangle]
pub unsafe fn uadd_u8x32(x: u8x32, y: u8x32) -> u8x32 {
- // CHECK: %{{[0-9]+}} = call <32 x i8> @llvm.uadd.sat.v32i8(<32 x i8> %{{x|_3}}, <32 x i8> %{{y|_4}})
+ // CHECK: %{{[0-9]+}} = call <32 x i8> @llvm.uadd.sat.v32i8(<32 x i8> %{{x|1}}, <32 x i8> %{{y|2}})
simd_saturating_add(x, y)
}
// CHECK-LABEL: @uadd_u8x64
#[no_mangle]
pub unsafe fn uadd_u8x64(x: u8x64, y: u8x64) -> u8x64 {
- // CHECK: %{{[0-9]+}} = call <64 x i8> @llvm.uadd.sat.v64i8(<64 x i8> %{{x|_3}}, <64 x i8> %{{y|_4}})
+ // CHECK: %{{[0-9]+}} = call <64 x i8> @llvm.uadd.sat.v64i8(<64 x i8> %{{x|1}}, <64 x i8> %{{y|2}})
simd_saturating_add(x, y)
}
// CHECK-LABEL: @uadd_u16x2
#[no_mangle]
pub unsafe fn uadd_u16x2(x: u16x2, y: u16x2) -> u16x2 {
- // CHECK: %{{[0-9]+}} = call <2 x i16> @llvm.uadd.sat.v2i16(<2 x i16> %{{x|_3}}, <2 x i16> %{{y|_4}})
+ // CHECK: %{{[0-9]+}} = call <2 x i16> @llvm.uadd.sat.v2i16(<2 x i16> %{{x|1}}, <2 x i16> %{{y|2}})
simd_saturating_add(x, y)
}
// CHECK-LABEL: @uadd_u16x4
#[no_mangle]
pub unsafe fn uadd_u16x4(x: u16x4, y: u16x4) -> u16x4 {
- // CHECK: %{{[0-9]+}} = call <4 x i16> @llvm.uadd.sat.v4i16(<4 x i16> %{{x|_3}}, <4 x i16> %{{y|_4}})
+ // CHECK: %{{[0-9]+}} = call <4 x i16> @llvm.uadd.sat.v4i16(<4 x i16> %{{x|1}}, <4 x i16> %{{y|2}})
simd_saturating_add(x, y)
}
// CHECK-LABEL: @uadd_u16x8
#[no_mangle]
pub unsafe fn uadd_u16x8(x: u16x8, y: u16x8) -> u16x8 {
- // CHECK: %{{[0-9]+}} = call <8 x i16> @llvm.uadd.sat.v8i16(<8 x i16> %{{x|_3}}, <8 x i16> %{{y|_4}})
+ // CHECK: %{{[0-9]+}} = call <8 x i16> @llvm.uadd.sat.v8i16(<8 x i16> %{{x|1}}, <8 x i16> %{{y|2}})
simd_saturating_add(x, y)
}
// CHECK-LABEL: @uadd_u16x16
#[no_mangle]
pub unsafe fn uadd_u16x16(x: u16x16, y: u16x16) -> u16x16 {
- // CHECK: %{{[0-9]+}} = call <16 x i16> @llvm.uadd.sat.v16i16(<16 x i16> %{{x|_3}}, <16 x i16> %{{y|_4}})
+ // CHECK: %{{[0-9]+}} = call <16 x i16> @llvm.uadd.sat.v16i16(<16 x i16> %{{x|1}}, <16 x i16> %{{y|2}})
simd_saturating_add(x, y)
}
// CHECK-LABEL: @uadd_u16x32
#[no_mangle]
pub unsafe fn uadd_u16x32(x: u16x32, y: u16x32) -> u16x32 {
- // CHECK: %{{[0-9]+}} = call <32 x i16> @llvm.uadd.sat.v32i16(<32 x i16> %{{x|_3}}, <32 x i16> %{{y|_4}})
+ // CHECK: %{{[0-9]+}} = call <32 x i16> @llvm.uadd.sat.v32i16(<32 x i16> %{{x|1}}, <32 x i16> %{{y|2}})
simd_saturating_add(x, y)
}
// CHECK-LABEL: @uadd_u32x2
#[no_mangle]
pub unsafe fn uadd_u32x2(x: u32x2, y: u32x2) -> u32x2 {
- // CHECK: %{{[0-9]+}} = call <2 x i32> @llvm.uadd.sat.v2i32(<2 x i32> %{{x|_3}}, <2 x i32> %{{y|_4}})
+ // CHECK: %{{[0-9]+}} = call <2 x i32> @llvm.uadd.sat.v2i32(<2 x i32> %{{x|1}}, <2 x i32> %{{y|2}})
simd_saturating_add(x, y)
}
// CHECK-LABEL: @uadd_u32x4
#[no_mangle]
pub unsafe fn uadd_u32x4(x: u32x4, y: u32x4) -> u32x4 {
- // CHECK: %{{[0-9]+}} = call <4 x i32> @llvm.uadd.sat.v4i32(<4 x i32> %{{x|_3}}, <4 x i32> %{{y|_4}})
+ // CHECK: %{{[0-9]+}} = call <4 x i32> @llvm.uadd.sat.v4i32(<4 x i32> %{{x|1}}, <4 x i32> %{{y|2}})
simd_saturating_add(x, y)
}
// CHECK-LABEL: @uadd_u32x8
#[no_mangle]
pub unsafe fn uadd_u32x8(x: u32x8, y: u32x8) -> u32x8 {
- // CHECK: %{{[0-9]+}} = call <8 x i32> @llvm.uadd.sat.v8i32(<8 x i32> %{{x|_3}}, <8 x i32> %{{y|_4}})
+ // CHECK: %{{[0-9]+}} = call <8 x i32> @llvm.uadd.sat.v8i32(<8 x i32> %{{x|1}}, <8 x i32> %{{y|2}})
simd_saturating_add(x, y)
}
// CHECK-LABEL: @uadd_u32x16
#[no_mangle]
pub unsafe fn uadd_u32x16(x: u32x16, y: u32x16) -> u32x16 {
- // CHECK: %{{[0-9]+}} = call <16 x i32> @llvm.uadd.sat.v16i32(<16 x i32> %{{x|_3}}, <16 x i32> %{{y|_4}})
+ // CHECK: %{{[0-9]+}} = call <16 x i32> @llvm.uadd.sat.v16i32(<16 x i32> %{{x|1}}, <16 x i32> %{{y|2}})
simd_saturating_add(x, y)
}
// CHECK-LABEL: @uadd_u64x2
#[no_mangle]
pub unsafe fn uadd_u64x2(x: u64x2, y: u64x2) -> u64x2 {
- // CHECK: %{{[0-9]+}} = call <2 x i64> @llvm.uadd.sat.v2i64(<2 x i64> %{{x|_3}}, <2 x i64> %{{y|_4}})
+ // CHECK: %{{[0-9]+}} = call <2 x i64> @llvm.uadd.sat.v2i64(<2 x i64> %{{x|1}}, <2 x i64> %{{y|2}})
simd_saturating_add(x, y)
}
// CHECK-LABEL: @uadd_u64x4
#[no_mangle]
pub unsafe fn uadd_u64x4(x: u64x4, y: u64x4) -> u64x4 {
- // CHECK: %{{[0-9]+}} = call <4 x i64> @llvm.uadd.sat.v4i64(<4 x i64> %{{x|_3}}, <4 x i64> %{{y|_4}})
+ // CHECK: %{{[0-9]+}} = call <4 x i64> @llvm.uadd.sat.v4i64(<4 x i64> %{{x|1}}, <4 x i64> %{{y|2}})
simd_saturating_add(x, y)
}
// CHECK-LABEL: @uadd_u64x8
#[no_mangle]
pub unsafe fn uadd_u64x8(x: u64x8, y: u64x8) -> u64x8 {
- // CHECK: %{{[0-9]+}} = call <8 x i64> @llvm.uadd.sat.v8i64(<8 x i64> %{{x|_3}}, <8 x i64> %{{y|_4}})
+ // CHECK: %{{[0-9]+}} = call <8 x i64> @llvm.uadd.sat.v8i64(<8 x i64> %{{x|1}}, <8 x i64> %{{y|2}})
simd_saturating_add(x, y)
}
// CHECK-LABEL: @uadd_u128x2
#[no_mangle]
pub unsafe fn uadd_u128x2(x: u128x2, y: u128x2) -> u128x2 {
- // CHECK: %{{[0-9]+}} = call <2 x i128> @llvm.uadd.sat.v2i128(<2 x i128> %{{x|_3}}, <2 x i128> %{{y|_4}})
+ // CHECK: %{{[0-9]+}} = call <2 x i128> @llvm.uadd.sat.v2i128(<2 x i128> %{{x|1}}, <2 x i128> %{{y|2}})
simd_saturating_add(x, y)
}
// CHECK-LABEL: @uadd_u128x4
#[no_mangle]
pub unsafe fn uadd_u128x4(x: u128x4, y: u128x4) -> u128x4 {
- // CHECK: %{{[0-9]+}} = call <4 x i128> @llvm.uadd.sat.v4i128(<4 x i128> %{{x|_3}}, <4 x i128> %{{y|_4}})
+ // CHECK: %{{[0-9]+}} = call <4 x i128> @llvm.uadd.sat.v4i128(<4 x i128> %{{x|1}}, <4 x i128> %{{y|2}})
simd_saturating_add(x, y)
}
@@ -412,140 +412,140 @@ pub unsafe fn uadd_u128x4(x: u128x4, y: u128x4) -> u128x4 {
// CHECK-LABEL: @ssub_i8x2
#[no_mangle]
pub unsafe fn ssub_i8x2(x: i8x2, y: i8x2) -> i8x2 {
- // CHECK: %{{[0-9]+}} = call <2 x i8> @llvm.ssub.sat.v2i8(<2 x i8> %{{x|_3}}, <2 x i8> %{{y|_4}})
+ // CHECK: %{{[0-9]+}} = call <2 x i8> @llvm.ssub.sat.v2i8(<2 x i8> %{{x|1}}, <2 x i8> %{{y|2}})
simd_saturating_sub(x, y)
}
// CHECK-LABEL: @ssub_i8x4
#[no_mangle]
pub unsafe fn ssub_i8x4(x: i8x4, y: i8x4) -> i8x4 {
- // CHECK: %{{[0-9]+}} = call <4 x i8> @llvm.ssub.sat.v4i8(<4 x i8> %{{x|_3}}, <4 x i8> %{{y|_4}})
+ // CHECK: %{{[0-9]+}} = call <4 x i8> @llvm.ssub.sat.v4i8(<4 x i8> %{{x|1}}, <4 x i8> %{{y|2}})
simd_saturating_sub(x, y)
}
// CHECK-LABEL: @ssub_i8x8
#[no_mangle]
pub unsafe fn ssub_i8x8(x: i8x8, y: i8x8) -> i8x8 {
- // CHECK: %{{[0-9]+}} = call <8 x i8> @llvm.ssub.sat.v8i8(<8 x i8> %{{x|_3}}, <8 x i8> %{{y|_4}})
+ // CHECK: %{{[0-9]+}} = call <8 x i8> @llvm.ssub.sat.v8i8(<8 x i8> %{{x|1}}, <8 x i8> %{{y|2}})
simd_saturating_sub(x, y)
}
// CHECK-LABEL: @ssub_i8x16
#[no_mangle]
pub unsafe fn ssub_i8x16(x: i8x16, y: i8x16) -> i8x16 {
- // CHECK: %{{[0-9]+}} = call <16 x i8> @llvm.ssub.sat.v16i8(<16 x i8> %{{x|_3}}, <16 x i8> %{{y|_4}})
+ // CHECK: %{{[0-9]+}} = call <16 x i8> @llvm.ssub.sat.v16i8(<16 x i8> %{{x|1}}, <16 x i8> %{{y|2}})
simd_saturating_sub(x, y)
}
// CHECK-LABEL: @ssub_i8x32
#[no_mangle]
pub unsafe fn ssub_i8x32(x: i8x32, y: i8x32) -> i8x32 {
- // CHECK: %{{[0-9]+}} = call <32 x i8> @llvm.ssub.sat.v32i8(<32 x i8> %{{x|_3}}, <32 x i8> %{{y|_4}})
+ // CHECK: %{{[0-9]+}} = call <32 x i8> @llvm.ssub.sat.v32i8(<32 x i8> %{{x|1}}, <32 x i8> %{{y|2}})
simd_saturating_sub(x, y)
}
// CHECK-LABEL: @ssub_i8x64
#[no_mangle]
pub unsafe fn ssub_i8x64(x: i8x64, y: i8x64) -> i8x64 {
- // CHECK: %{{[0-9]+}} = call <64 x i8> @llvm.ssub.sat.v64i8(<64 x i8> %{{x|_3}}, <64 x i8> %{{y|_4}})
+ // CHECK: %{{[0-9]+}} = call <64 x i8> @llvm.ssub.sat.v64i8(<64 x i8> %{{x|1}}, <64 x i8> %{{y|2}})
simd_saturating_sub(x, y)
}
// CHECK-LABEL: @ssub_i16x2
#[no_mangle]
pub unsafe fn ssub_i16x2(x: i16x2, y: i16x2) -> i16x2 {
- // CHECK: %{{[0-9]+}} = call <2 x i16> @llvm.ssub.sat.v2i16(<2 x i16> %{{x|_3}}, <2 x i16> %{{y|_4}})
+ // CHECK: %{{[0-9]+}} = call <2 x i16> @llvm.ssub.sat.v2i16(<2 x i16> %{{x|1}}, <2 x i16> %{{y|2}})
simd_saturating_sub(x, y)
}
// CHECK-LABEL: @ssub_i16x4
#[no_mangle]
pub unsafe fn ssub_i16x4(x: i16x4, y: i16x4) -> i16x4 {
- // CHECK: %{{[0-9]+}} = call <4 x i16> @llvm.ssub.sat.v4i16(<4 x i16> %{{x|_3}}, <4 x i16> %{{y|_4}})
+ // CHECK: %{{[0-9]+}} = call <4 x i16> @llvm.ssub.sat.v4i16(<4 x i16> %{{x|1}}, <4 x i16> %{{y|2}})
simd_saturating_sub(x, y)
}
// CHECK-LABEL: @ssub_i16x8
#[no_mangle]
pub unsafe fn ssub_i16x8(x: i16x8, y: i16x8) -> i16x8 {
- // CHECK: %{{[0-9]+}} = call <8 x i16> @llvm.ssub.sat.v8i16(<8 x i16> %{{x|_3}}, <8 x i16> %{{y|_4}})
+ // CHECK: %{{[0-9]+}} = call <8 x i16> @llvm.ssub.sat.v8i16(<8 x i16> %{{x|1}}, <8 x i16> %{{y|2}})
simd_saturating_sub(x, y)
}
// CHECK-LABEL: @ssub_i16x16
#[no_mangle]
pub unsafe fn ssub_i16x16(x: i16x16, y: i16x16) -> i16x16 {
- // CHECK: %{{[0-9]+}} = call <16 x i16> @llvm.ssub.sat.v16i16(<16 x i16> %{{x|_3}}, <16 x i16> %{{y|_4}})
+ // CHECK: %{{[0-9]+}} = call <16 x i16> @llvm.ssub.sat.v16i16(<16 x i16> %{{x|1}}, <16 x i16> %{{y|2}})
simd_saturating_sub(x, y)
}
// CHECK-LABEL: @ssub_i16x32
#[no_mangle]
pub unsafe fn ssub_i16x32(x: i16x32, y: i16x32) -> i16x32 {
- // CHECK: %{{[0-9]+}} = call <32 x i16> @llvm.ssub.sat.v32i16(<32 x i16> %{{x|_3}}, <32 x i16> %{{y|_4}})
+ // CHECK: %{{[0-9]+}} = call <32 x i16> @llvm.ssub.sat.v32i16(<32 x i16> %{{x|1}}, <32 x i16> %{{y|2}})
simd_saturating_sub(x, y)
}
// CHECK-LABEL: @ssub_i32x2
#[no_mangle]
pub unsafe fn ssub_i32x2(x: i32x2, y: i32x2) -> i32x2 {
- // CHECK: %{{[0-9]+}} = call <2 x i32> @llvm.ssub.sat.v2i32(<2 x i32> %{{x|_3}}, <2 x i32> %{{y|_4}})
+ // CHECK: %{{[0-9]+}} = call <2 x i32> @llvm.ssub.sat.v2i32(<2 x i32> %{{x|1}}, <2 x i32> %{{y|2}})
simd_saturating_sub(x, y)
}
// CHECK-LABEL: @ssub_i32x4
#[no_mangle]
pub unsafe fn ssub_i32x4(x: i32x4, y: i32x4) -> i32x4 {
- // CHECK: %{{[0-9]+}} = call <4 x i32> @llvm.ssub.sat.v4i32(<4 x i32> %{{x|_3}}, <4 x i32> %{{y|_4}})
+ // CHECK: %{{[0-9]+}} = call <4 x i32> @llvm.ssub.sat.v4i32(<4 x i32> %{{x|1}}, <4 x i32> %{{y|2}})
simd_saturating_sub(x, y)
}
// CHECK-LABEL: @ssub_i32x8
#[no_mangle]
pub unsafe fn ssub_i32x8(x: i32x8, y: i32x8) -> i32x8 {
- // CHECK: %{{[0-9]+}} = call <8 x i32> @llvm.ssub.sat.v8i32(<8 x i32> %{{x|_3}}, <8 x i32> %{{y|_4}})
+ // CHECK: %{{[0-9]+}} = call <8 x i32> @llvm.ssub.sat.v8i32(<8 x i32> %{{x|1}}, <8 x i32> %{{y|2}})
simd_saturating_sub(x, y)
}
// CHECK-LABEL: @ssub_i32x16
#[no_mangle]
pub unsafe fn ssub_i32x16(x: i32x16, y: i32x16) -> i32x16 {
- // CHECK: %{{[0-9]+}} = call <16 x i32> @llvm.ssub.sat.v16i32(<16 x i32> %{{x|_3}}, <16 x i32> %{{y|_4}})
+ // CHECK: %{{[0-9]+}} = call <16 x i32> @llvm.ssub.sat.v16i32(<16 x i32> %{{x|1}}, <16 x i32> %{{y|2}})
simd_saturating_sub(x, y)
}
// CHECK-LABEL: @ssub_i64x2
#[no_mangle]
pub unsafe fn ssub_i64x2(x: i64x2, y: i64x2) -> i64x2 {
- // CHECK: %{{[0-9]+}} = call <2 x i64> @llvm.ssub.sat.v2i64(<2 x i64> %{{x|_3}}, <2 x i64> %{{y|_4}})
+ // CHECK: %{{[0-9]+}} = call <2 x i64> @llvm.ssub.sat.v2i64(<2 x i64> %{{x|1}}, <2 x i64> %{{y|2}})
simd_saturating_sub(x, y)
}
// CHECK-LABEL: @ssub_i64x4
#[no_mangle]
pub unsafe fn ssub_i64x4(x: i64x4, y: i64x4) -> i64x4 {
- // CHECK: %{{[0-9]+}} = call <4 x i64> @llvm.ssub.sat.v4i64(<4 x i64> %{{x|_3}}, <4 x i64> %{{y|_4}})
+ // CHECK: %{{[0-9]+}} = call <4 x i64> @llvm.ssub.sat.v4i64(<4 x i64> %{{x|1}}, <4 x i64> %{{y|2}})
simd_saturating_sub(x, y)
}
// CHECK-LABEL: @ssub_i64x8
#[no_mangle]
pub unsafe fn ssub_i64x8(x: i64x8, y: i64x8) -> i64x8 {
- // CHECK: %{{[0-9]+}} = call <8 x i64> @llvm.ssub.sat.v8i64(<8 x i64> %{{x|_3}}, <8 x i64> %{{y|_4}})
+ // CHECK: %{{[0-9]+}} = call <8 x i64> @llvm.ssub.sat.v8i64(<8 x i64> %{{x|1}}, <8 x i64> %{{y|2}})
simd_saturating_sub(x, y)
}
// CHECK-LABEL: @ssub_i128x2
#[no_mangle]
pub unsafe fn ssub_i128x2(x: i128x2, y: i128x2) -> i128x2 {
- // CHECK: %{{[0-9]+}} = call <2 x i128> @llvm.ssub.sat.v2i128(<2 x i128> %{{x|_3}}, <2 x i128> %{{y|_4}})
+ // CHECK: %{{[0-9]+}} = call <2 x i128> @llvm.ssub.sat.v2i128(<2 x i128> %{{x|1}}, <2 x i128> %{{y|2}})
simd_saturating_sub(x, y)
}
// CHECK-LABEL: @ssub_i128x4
#[no_mangle]
pub unsafe fn ssub_i128x4(x: i128x4, y: i128x4) -> i128x4 {
- // CHECK: %{{[0-9]+}} = call <4 x i128> @llvm.ssub.sat.v4i128(<4 x i128> %{{x|_3}}, <4 x i128> %{{y|_4}})
+ // CHECK: %{{[0-9]+}} = call <4 x i128> @llvm.ssub.sat.v4i128(<4 x i128> %{{x|1}}, <4 x i128> %{{y|2}})
simd_saturating_sub(x, y)
}
@@ -554,139 +554,139 @@ pub unsafe fn ssub_i128x4(x: i128x4, y: i128x4) -> i128x4 {
// CHECK-LABEL: @usub_u8x2
#[no_mangle]
pub unsafe fn usub_u8x2(x: u8x2, y: u8x2) -> u8x2 {
- // CHECK: %{{[0-9]+}} = call <2 x i8> @llvm.usub.sat.v2i8(<2 x i8> %{{x|_3}}, <2 x i8> %{{y|_4}})
+ // CHECK: %{{[0-9]+}} = call <2 x i8> @llvm.usub.sat.v2i8(<2 x i8> %{{x|1}}, <2 x i8> %{{y|2}})
simd_saturating_sub(x, y)
}
// CHECK-LABEL: @usub_u8x4
#[no_mangle]
pub unsafe fn usub_u8x4(x: u8x4, y: u8x4) -> u8x4 {
- // CHECK: %{{[0-9]+}} = call <4 x i8> @llvm.usub.sat.v4i8(<4 x i8> %{{x|_3}}, <4 x i8> %{{y|_4}})
+ // CHECK: %{{[0-9]+}} = call <4 x i8> @llvm.usub.sat.v4i8(<4 x i8> %{{x|1}}, <4 x i8> %{{y|2}})
simd_saturating_sub(x, y)
}
// CHECK-LABEL: @usub_u8x8
#[no_mangle]
pub unsafe fn usub_u8x8(x: u8x8, y: u8x8) -> u8x8 {
- // CHECK: %{{[0-9]+}} = call <8 x i8> @llvm.usub.sat.v8i8(<8 x i8> %{{x|_3}}, <8 x i8> %{{y|_4}})
+ // CHECK: %{{[0-9]+}} = call <8 x i8> @llvm.usub.sat.v8i8(<8 x i8> %{{x|1}}, <8 x i8> %{{y|2}})
simd_saturating_sub(x, y)
}
// CHECK-LABEL: @usub_u8x16
#[no_mangle]
pub unsafe fn usub_u8x16(x: u8x16, y: u8x16) -> u8x16 {
- // CHECK: %{{[0-9]+}} = call <16 x i8> @llvm.usub.sat.v16i8(<16 x i8> %{{x|_3}}, <16 x i8> %{{y|_4}})
+ // CHECK: %{{[0-9]+}} = call <16 x i8> @llvm.usub.sat.v16i8(<16 x i8> %{{x|1}}, <16 x i8> %{{y|2}})
simd_saturating_sub(x, y)
}
// CHECK-LABEL: @usub_u8x32
#[no_mangle]
pub unsafe fn usub_u8x32(x: u8x32, y: u8x32) -> u8x32 {
- // CHECK: %{{[0-9]+}} = call <32 x i8> @llvm.usub.sat.v32i8(<32 x i8> %{{x|_3}}, <32 x i8> %{{y|_4}})
+ // CHECK: %{{[0-9]+}} = call <32 x i8> @llvm.usub.sat.v32i8(<32 x i8> %{{x|1}}, <32 x i8> %{{y|2}})
simd_saturating_sub(x, y)
}
// CHECK-LABEL: @usub_u8x64
#[no_mangle]
pub unsafe fn usub_u8x64(x: u8x64, y: u8x64) -> u8x64 {
- // CHECK: %{{[0-9]+}} = call <64 x i8> @llvm.usub.sat.v64i8(<64 x i8> %{{x|_3}}, <64 x i8> %{{y|_4}})
+ // CHECK: %{{[0-9]+}} = call <64 x i8> @llvm.usub.sat.v64i8(<64 x i8> %{{x|1}}, <64 x i8> %{{y|2}})
simd_saturating_sub(x, y)
}
// CHECK-LABEL: @usub_u16x2
#[no_mangle]
pub unsafe fn usub_u16x2(x: u16x2, y: u16x2) -> u16x2 {
- // CHECK: %{{[0-9]+}} = call <2 x i16> @llvm.usub.sat.v2i16(<2 x i16> %{{x|_3}}, <2 x i16> %{{y|_4}})
+ // CHECK: %{{[0-9]+}} = call <2 x i16> @llvm.usub.sat.v2i16(<2 x i16> %{{x|1}}, <2 x i16> %{{y|2}})
simd_saturating_sub(x, y)
}
// CHECK-LABEL: @usub_u16x4
#[no_mangle]
pub unsafe fn usub_u16x4(x: u16x4, y: u16x4) -> u16x4 {
- // CHECK: %{{[0-9]+}} = call <4 x i16> @llvm.usub.sat.v4i16(<4 x i16> %{{x|_3}}, <4 x i16> %{{y|_4}})
+ // CHECK: %{{[0-9]+}} = call <4 x i16> @llvm.usub.sat.v4i16(<4 x i16> %{{x|1}}, <4 x i16> %{{y|2}})
simd_saturating_sub(x, y)
}
// CHECK-LABEL: @usub_u16x8
#[no_mangle]
pub unsafe fn usub_u16x8(x: u16x8, y: u16x8) -> u16x8 {
- // CHECK: %{{[0-9]+}} = call <8 x i16> @llvm.usub.sat.v8i16(<8 x i16> %{{x|_3}}, <8 x i16> %{{y|_4}})
+ // CHECK: %{{[0-9]+}} = call <8 x i16> @llvm.usub.sat.v8i16(<8 x i16> %{{x|1}}, <8 x i16> %{{y|2}})
simd_saturating_sub(x, y)
}
// CHECK-LABEL: @usub_u16x16
#[no_mangle]
pub unsafe fn usub_u16x16(x: u16x16, y: u16x16) -> u16x16 {
- // CHECK: %{{[0-9]+}} = call <16 x i16> @llvm.usub.sat.v16i16(<16 x i16> %{{x|_3}}, <16 x i16> %{{y|_4}})
+ // CHECK: %{{[0-9]+}} = call <16 x i16> @llvm.usub.sat.v16i16(<16 x i16> %{{x|1}}, <16 x i16> %{{y|2}})
simd_saturating_sub(x, y)
}
// CHECK-LABEL: @usub_u16x32
#[no_mangle]
pub unsafe fn usub_u16x32(x: u16x32, y: u16x32) -> u16x32 {
- // CHECK: %{{[0-9]+}} = call <32 x i16> @llvm.usub.sat.v32i16(<32 x i16> %{{x|_3}}, <32 x i16> %{{y|_4}})
+ // CHECK: %{{[0-9]+}} = call <32 x i16> @llvm.usub.sat.v32i16(<32 x i16> %{{x|1}}, <32 x i16> %{{y|2}})
simd_saturating_sub(x, y)
}
// CHECK-LABEL: @usub_u32x2
#[no_mangle]
pub unsafe fn usub_u32x2(x: u32x2, y: u32x2) -> u32x2 {
- // CHECK: %{{[0-9]+}} = call <2 x i32> @llvm.usub.sat.v2i32(<2 x i32> %{{x|_3}}, <2 x i32> %{{y|_4}})
+ // CHECK: %{{[0-9]+}} = call <2 x i32> @llvm.usub.sat.v2i32(<2 x i32> %{{x|1}}, <2 x i32> %{{y|2}})
simd_saturating_sub(x, y)
}
// CHECK-LABEL: @usub_u32x4
#[no_mangle]
pub unsafe fn usub_u32x4(x: u32x4, y: u32x4) -> u32x4 {
- // CHECK: %{{[0-9]+}} = call <4 x i32> @llvm.usub.sat.v4i32(<4 x i32> %{{x|_3}}, <4 x i32> %{{y|_4}})
+ // CHECK: %{{[0-9]+}} = call <4 x i32> @llvm.usub.sat.v4i32(<4 x i32> %{{x|1}}, <4 x i32> %{{y|2}})
simd_saturating_sub(x, y)
}
// CHECK-LABEL: @usub_u32x8
#[no_mangle]
pub unsafe fn usub_u32x8(x: u32x8, y: u32x8) -> u32x8 {
- // CHECK: %{{[0-9]+}} = call <8 x i32> @llvm.usub.sat.v8i32(<8 x i32> %{{x|_3}}, <8 x i32> %{{y|_4}})
+ // CHECK: %{{[0-9]+}} = call <8 x i32> @llvm.usub.sat.v8i32(<8 x i32> %{{x|1}}, <8 x i32> %{{y|2}})
simd_saturating_sub(x, y)
}
// CHECK-LABEL: @usub_u32x16
#[no_mangle]
pub unsafe fn usub_u32x16(x: u32x16, y: u32x16) -> u32x16 {
- // CHECK: %{{[0-9]+}} = call <16 x i32> @llvm.usub.sat.v16i32(<16 x i32> %{{x|_3}}, <16 x i32> %{{y|_4}})
+ // CHECK: %{{[0-9]+}} = call <16 x i32> @llvm.usub.sat.v16i32(<16 x i32> %{{x|1}}, <16 x i32> %{{y|2}})
simd_saturating_sub(x, y)
}
// CHECK-LABEL: @usub_u64x2
#[no_mangle]
pub unsafe fn usub_u64x2(x: u64x2, y: u64x2) -> u64x2 {
- // CHECK: %{{[0-9]+}} = call <2 x i64> @llvm.usub.sat.v2i64(<2 x i64> %{{x|_3}}, <2 x i64> %{{y|_4}})
+ // CHECK: %{{[0-9]+}} = call <2 x i64> @llvm.usub.sat.v2i64(<2 x i64> %{{x|1}}, <2 x i64> %{{y|2}})
simd_saturating_sub(x, y)
}
// CHECK-LABEL: @usub_u64x4
#[no_mangle]
pub unsafe fn usub_u64x4(x: u64x4, y: u64x4) -> u64x4 {
- // CHECK: %{{[0-9]+}} = call <4 x i64> @llvm.usub.sat.v4i64(<4 x i64> %{{x|_3}}, <4 x i64> %{{y|_4}})
+ // CHECK: %{{[0-9]+}} = call <4 x i64> @llvm.usub.sat.v4i64(<4 x i64> %{{x|1}}, <4 x i64> %{{y|2}})
simd_saturating_sub(x, y)
}
// CHECK-LABEL: @usub_u64x8
#[no_mangle]
pub unsafe fn usub_u64x8(x: u64x8, y: u64x8) -> u64x8 {
- // CHECK: %{{[0-9]+}} = call <8 x i64> @llvm.usub.sat.v8i64(<8 x i64> %{{x|_3}}, <8 x i64> %{{y|_4}})
+ // CHECK: %{{[0-9]+}} = call <8 x i64> @llvm.usub.sat.v8i64(<8 x i64> %{{x|1}}, <8 x i64> %{{y|2}})
simd_saturating_sub(x, y)
}
// CHECK-LABEL: @usub_u128x2
#[no_mangle]
pub unsafe fn usub_u128x2(x: u128x2, y: u128x2) -> u128x2 {
- // CHECK: %{{[0-9]+}} = call <2 x i128> @llvm.usub.sat.v2i128(<2 x i128> %{{x|_3}}, <2 x i128> %{{y|_4}})
+ // CHECK: %{{[0-9]+}} = call <2 x i128> @llvm.usub.sat.v2i128(<2 x i128> %{{x|1}}, <2 x i128> %{{y|2}})
simd_saturating_sub(x, y)
}
// CHECK-LABEL: @usub_u128x4
#[no_mangle]
pub unsafe fn usub_u128x4(x: u128x4, y: u128x4) -> u128x4 {
- // CHECK: %{{[0-9]+}} = call <4 x i128> @llvm.usub.sat.v4i128(<4 x i128> %{{x|_3}}, <4 x i128> %{{y|_4}})
+ // CHECK: %{{[0-9]+}} = call <4 x i128> @llvm.usub.sat.v4i128(<4 x i128> %{{x|1}}, <4 x i128> %{{y|2}})
simd_saturating_sub(x, y)
}
diff --git a/tests/codegen/simd-intrinsic/simd-intrinsic-generic-bitmask.rs b/tests/codegen/simd-intrinsic/simd-intrinsic-generic-bitmask.rs
index 4a98d797b..ea24569bd 100644
--- a/tests/codegen/simd-intrinsic/simd-intrinsic-generic-bitmask.rs
+++ b/tests/codegen/simd-intrinsic/simd-intrinsic-generic-bitmask.rs
@@ -26,16 +26,16 @@ extern "platform-intrinsic" {
fn simd_bitmask<T, U>(x: T) -> U;
}
-// NOTE(eddyb) `%{{x|_2}}` is used because on some targets (e.g. WASM)
+// NOTE(eddyb) `%{{x|1}}` is used because on some targets (e.g. WASM)
// SIMD vectors are passed directly, resulting in `%x` being a vector,
// while on others they're passed indirectly, resulting in `%x` being
-// a pointer to a vector, and `%_2` a vector loaded from that pointer.
+// a pointer to a vector, and `%1` a vector loaded from that pointer.
// This is controlled by the target spec option `simd_types_indirect`.
// CHECK-LABEL: @bitmask_int
#[no_mangle]
pub unsafe fn bitmask_int(x: i32x2) -> u8 {
- // CHECK: [[A:%[0-9]+]] = lshr <2 x i32> %{{x|_2}}, <i32 31, i32 31>
+ // CHECK: [[A:%[0-9]+]] = lshr <2 x i32> %{{x|1}}, <i32 31, i32 31>
// CHECK: [[B:%[0-9]+]] = trunc <2 x i32> [[A]] to <2 x i1>
// CHECK: [[C:%[0-9]+]] = bitcast <2 x i1> [[B]] to i2
// CHECK: %{{[0-9]+}} = zext i2 [[C]] to i8
@@ -45,7 +45,7 @@ pub unsafe fn bitmask_int(x: i32x2) -> u8 {
// CHECK-LABEL: @bitmask_uint
#[no_mangle]
pub unsafe fn bitmask_uint(x: u32x2) -> u8 {
- // CHECK: [[A:%[0-9]+]] = lshr <2 x i32> %{{x|_2}}, <i32 31, i32 31>
+ // CHECK: [[A:%[0-9]+]] = lshr <2 x i32> %{{x|1}}, <i32 31, i32 31>
// CHECK: [[B:%[0-9]+]] = trunc <2 x i32> [[A]] to <2 x i1>
// CHECK: [[C:%[0-9]+]] = bitcast <2 x i1> [[B]] to i2
// CHECK: %{{[0-9]+}} = zext i2 [[C]] to i8
@@ -55,7 +55,7 @@ pub unsafe fn bitmask_uint(x: u32x2) -> u8 {
// CHECK-LABEL: @bitmask_int16
#[no_mangle]
pub unsafe fn bitmask_int16(x: i8x16) -> u16 {
- // CHECK: [[A:%[0-9]+]] = lshr <16 x i8> %{{x|_2}}, <i8 7, i8 7, i8 7, i8 7, i8 7, i8 7, i8 7, i8 7, i8 7, i8 7, i8 7, i8 7, i8 7, i8 7, i8 7, i8 7>
+ // CHECK: [[A:%[0-9]+]] = lshr <16 x i8> %{{x|1|2}}, <i8 7, i8 7, i8 7, i8 7, i8 7, i8 7, i8 7, i8 7, i8 7, i8 7, i8 7, i8 7, i8 7, i8 7, i8 7, i8 7>
// CHECK: [[B:%[0-9]+]] = trunc <16 x i8> [[A]] to <16 x i1>
// CHECK: %{{[0-9]+}} = bitcast <16 x i1> [[B]] to i16
// CHECK-NOT: zext
diff --git a/tests/codegen/simd-intrinsic/simd-intrinsic-generic-extract-insert.rs b/tests/codegen/simd-intrinsic/simd-intrinsic-generic-extract-insert.rs
index b5b0b1330..80583dec1 100644
--- a/tests/codegen/simd-intrinsic/simd-intrinsic-generic-extract-insert.rs
+++ b/tests/codegen/simd-intrinsic/simd-intrinsic-generic-extract-insert.rs
@@ -21,27 +21,27 @@ extern "platform-intrinsic" {
// CHECK-LABEL: @extract_m
#[no_mangle]
pub unsafe fn extract_m(v: M, i: u32) -> f32 {
- // CHECK: extractelement <4 x float> %{{v|_3}}, i32 %i
+ // CHECK: extractelement <4 x float> %{{v|1|2}}, i32 %i
simd_extract(v, i)
}
// CHECK-LABEL: @extract_s
#[no_mangle]
pub unsafe fn extract_s(v: S<4>, i: u32) -> f32 {
- // CHECK: extractelement <4 x float> %{{v|_3}}, i32 %i
+ // CHECK: extractelement <4 x float> %{{v|1|2}}, i32 %i
simd_extract(v, i)
}
// CHECK-LABEL: @insert_m
#[no_mangle]
pub unsafe fn insert_m(v: M, i: u32, j: f32) -> M {
- // CHECK: insertelement <4 x float> %{{v|_4}}, float %j, i32 %i
+ // CHECK: insertelement <4 x float> %{{v|1|2}}, float %j, i32 %i
simd_insert(v, i, j)
}
// CHECK-LABEL: @insert_s
#[no_mangle]
pub unsafe fn insert_s(v: S<4>, i: u32, j: f32) -> S<4> {
- // CHECK: insertelement <4 x float> %{{v|_4}}, float %j, i32 %i
+ // CHECK: insertelement <4 x float> %{{v|1|2}}, float %j, i32 %i
simd_insert(v, i, j)
}
diff --git a/tests/codegen/simd-intrinsic/simd-intrinsic-transmute-array.rs b/tests/codegen/simd-intrinsic/simd-intrinsic-transmute-array.rs
index db5b60567..7c77398df 100644
--- a/tests/codegen/simd-intrinsic/simd-intrinsic-transmute-array.rs
+++ b/tests/codegen/simd-intrinsic/simd-intrinsic-transmute-array.rs
@@ -22,7 +22,6 @@ pub struct U(f32, f32, f32, f32);
#[no_mangle]
pub fn build_array_s(x: [f32; 4]) -> S<4> {
// CHECK: call void @llvm.memcpy.{{.+}}({{.*}}, i{{[0-9]+}} 16, i1 false)
- // CHECK: call void @llvm.memcpy.{{.+}}({{.*}}, i{{[0-9]+}} 16, i1 false)
S::<4>(x)
}
@@ -30,7 +29,6 @@ pub fn build_array_s(x: [f32; 4]) -> S<4> {
#[no_mangle]
pub fn build_array_t(x: [f32; 4]) -> T {
// CHECK: call void @llvm.memcpy.{{.+}}({{.*}}, i{{[0-9]+}} 16, i1 false)
- // CHECK: call void @llvm.memcpy.{{.+}}({{.*}}, i{{[0-9]+}} 16, i1 false)
T(x)
}
@@ -38,6 +36,5 @@ pub fn build_array_t(x: [f32; 4]) -> T {
#[no_mangle]
pub fn build_array_u(x: [f32; 4]) -> U {
// CHECK: call void @llvm.memcpy.{{.+}}({{.*}}, i{{[0-9]+}} 16, i1 false)
- // CHECK: call void @llvm.memcpy.{{.+}}({{.*}}, i{{[0-9]+}} 16, i1 false)
unsafe { std::mem::transmute(x) }
}
diff --git a/tests/codegen/simd_arith_offset.rs b/tests/codegen/simd_arith_offset.rs
index 7b623a22a..f23337773 100644
--- a/tests/codegen/simd_arith_offset.rs
+++ b/tests/codegen/simd_arith_offset.rs
@@ -21,6 +21,6 @@ pub struct Simd<T, const LANES: usize>([T; LANES]);
// CHECK-LABEL: smoke
#[no_mangle]
pub fn smoke(ptrs: SimdConstPtr<u8, 8>, offsets: Simd<usize, 8>) -> SimdConstPtr<u8, 8> {
- // CHECK: getelementptr i8, <8 x {{i8\*|ptr}}> %_3, <8 x i64> %_4
+ // CHECK: getelementptr i8, <8 x {{i8\*|ptr}}> %1, <8 x i64> %2
unsafe { simd_arith_offset(ptrs, offsets) }
}
diff --git a/tests/codegen/slice-ref-equality.rs b/tests/codegen/slice-ref-equality.rs
index 47fde12bf..8f0adab35 100644
--- a/tests/codegen/slice-ref-equality.rs
+++ b/tests/codegen/slice-ref-equality.rs
@@ -1,7 +1,10 @@
-// compile-flags: -C opt-level=3 -Zmerge-functions=disabled
+// compile-flags: -O -Zmerge-functions=disabled
+// ignore-debug (the extra assertions get in the way)
#![crate_type = "lib"]
+use std::num::{NonZeroI16, NonZeroU32};
+
// #71602 reported a simple array comparison just generating a loop.
// This was originally fixed by ensuring it generates a single bcmp,
// but we now generate it as a load+icmp instead. `is_zero_slice` was
@@ -36,3 +39,54 @@ pub fn is_zero_array(data: &[u8; 4]) -> bool {
// CHECK-NEXT: ret i1 %[[EQ]]
*data == [0; 4]
}
+
+// The following test the extra specializations to make sure that slice
+// equality for non-byte types also just emit a `bcmp`, not a loop.
+
+// CHECK-LABEL: @eq_slice_of_nested_u8(
+// CHECK-SAME: [[USIZE:i16|i32|i64]] noundef %1
+// CHECK-SAME: [[USIZE]] noundef %3
+#[no_mangle]
+fn eq_slice_of_nested_u8(x: &[[u8; 3]], y: &[[u8; 3]]) -> bool {
+ // CHECK: icmp eq [[USIZE]] %1, %3
+ // CHECK: %[[BYTES:.+]] = mul nsw [[USIZE]] %1, 3
+ // CHECK: tail call{{( noundef)?}} i32 @{{bcmp|memcmp}}({{i8\*|ptr}}
+ // CHECK-SAME: , [[USIZE]]{{( noundef)?}} %[[BYTES]])
+ x == y
+}
+
+// CHECK-LABEL: @eq_slice_of_i32(
+// CHECK-SAME: [[USIZE:i16|i32|i64]] noundef %1
+// CHECK-SAME: [[USIZE]] noundef %3
+#[no_mangle]
+fn eq_slice_of_i32(x: &[i32], y: &[i32]) -> bool {
+ // CHECK: icmp eq [[USIZE]] %1, %3
+ // CHECK: %[[BYTES:.+]] = shl nsw [[USIZE]] %1, 2
+ // CHECK: tail call{{( noundef)?}} i32 @{{bcmp|memcmp}}({{i32\*|ptr}}
+ // CHECK-SAME: , [[USIZE]]{{( noundef)?}} %[[BYTES]])
+ x == y
+}
+
+// CHECK-LABEL: @eq_slice_of_nonzero(
+// CHECK-SAME: [[USIZE:i16|i32|i64]] noundef %1
+// CHECK-SAME: [[USIZE]] noundef %3
+#[no_mangle]
+fn eq_slice_of_nonzero(x: &[NonZeroU32], y: &[NonZeroU32]) -> bool {
+ // CHECK: icmp eq [[USIZE]] %1, %3
+ // CHECK: %[[BYTES:.+]] = shl nsw [[USIZE]] %1, 2
+ // CHECK: tail call{{( noundef)?}} i32 @{{bcmp|memcmp}}({{i32\*|ptr}}
+ // CHECK-SAME: , [[USIZE]]{{( noundef)?}} %[[BYTES]])
+ x == y
+}
+
+// CHECK-LABEL: @eq_slice_of_option_of_nonzero(
+// CHECK-SAME: [[USIZE:i16|i32|i64]] noundef %1
+// CHECK-SAME: [[USIZE]] noundef %3
+#[no_mangle]
+fn eq_slice_of_option_of_nonzero(x: &[Option<NonZeroI16>], y: &[Option<NonZeroI16>]) -> bool {
+ // CHECK: icmp eq [[USIZE]] %1, %3
+ // CHECK: %[[BYTES:.+]] = shl nsw [[USIZE]] %1, 1
+ // CHECK: tail call{{( noundef)?}} i32 @{{bcmp|memcmp}}({{i16\*|ptr}}
+ // CHECK-SAME: , [[USIZE]]{{( noundef)?}} %[[BYTES]])
+ x == y
+}
diff --git a/tests/codegen/sse42-implies-crc32.rs b/tests/codegen/sse42-implies-crc32.rs
index 47b1a8993..56079d32a 100644
--- a/tests/codegen/sse42-implies-crc32.rs
+++ b/tests/codegen/sse42-implies-crc32.rs
@@ -1,5 +1,4 @@
// only-x86_64
-// min-llvm-version: 14.0
// compile-flags: -Copt-level=3
#![crate_type = "lib"]
diff --git a/tests/codegen/thread-local.rs b/tests/codegen/thread-local.rs
index 0f1b29ca7..aa7fab7fb 100644
--- a/tests/codegen/thread-local.rs
+++ b/tests/codegen/thread-local.rs
@@ -4,6 +4,7 @@
// ignore-wasm globals are used instead of thread locals
// ignore-emscripten globals are used instead of thread locals
// ignore-android does not use #[thread_local]
+// ignore-nto does not use #[thread_local]
#![crate_type = "lib"]
diff --git a/tests/codegen/uninit-consts.rs b/tests/codegen/uninit-consts.rs
index 98a6761f8..54e9a9e9b 100644
--- a/tests/codegen/uninit-consts.rs
+++ b/tests/codegen/uninit-consts.rs
@@ -1,5 +1,4 @@
// compile-flags: -C no-prepopulate-passes
-// min-llvm-version: 14.0
// Check that we use undef (and not zero) for uninitialized bytes in constants.
diff --git a/tests/codegen/vec-in-place.rs b/tests/codegen/vec-in-place.rs
index 5df366905..999260422 100644
--- a/tests/codegen/vec-in-place.rs
+++ b/tests/codegen/vec-in-place.rs
@@ -1,4 +1,3 @@
-// min-llvm-version: 14.0
// ignore-debug: the debug assertions get in the way
// compile-flags: -O -Z merge-functions=disabled
#![crate_type = "lib"]
diff --git a/tests/debuginfo/captured-fields-1.rs b/tests/debuginfo/captured-fields-1.rs
index afbf942d4..b71734c23 100644
--- a/tests/debuginfo/captured-fields-1.rs
+++ b/tests/debuginfo/captured-fields-1.rs
@@ -1,5 +1,5 @@
// compile-flags:-g
-
+// edition:2021
// === GDB TESTS ===================================================================================
// gdb-command:run
@@ -44,7 +44,6 @@
// lldbg-check:(captured_fields_1::main::{closure_env#5}) $5 = { my_var = { my_field1 = 11 my_field2 = 22 } }
// lldb-command:continue
-#![feature(capture_disjoint_fields)]
#![allow(unused)]
struct MyStruct {
diff --git a/tests/debuginfo/captured-fields-2.rs b/tests/debuginfo/captured-fields-2.rs
index c872354a9..8d463fb24 100644
--- a/tests/debuginfo/captured-fields-2.rs
+++ b/tests/debuginfo/captured-fields-2.rs
@@ -1,5 +1,5 @@
// compile-flags:-g
-
+// edition:2021
// === GDB TESTS ===================================================================================
// gdb-command:run
@@ -20,7 +20,6 @@
// lldbg-check:(unsigned int) $1 = 22
// lldb-command:continue
-#![feature(capture_disjoint_fields)]
#![allow(unused)]
struct MyStruct {
@@ -29,10 +28,7 @@ struct MyStruct {
}
fn main() {
- let mut my_var = MyStruct {
- my_field1: 11,
- my_field2: 22,
- };
+ let mut my_var = MyStruct { my_field1: 11, my_field2: 22 };
let my_ref = &mut my_var;
let test = || {
diff --git a/tests/debuginfo/embedded-visualizer.rs b/tests/debuginfo/embedded-visualizer.rs
index 0269015b4..2898e75e0 100644
--- a/tests/debuginfo/embedded-visualizer.rs
+++ b/tests/debuginfo/embedded-visualizer.rs
@@ -1,6 +1,7 @@
// compile-flags:-g
// min-gdb-version: 8.1
// ignore-lldb
+// ignore-windows-gnu // emit_debug_gdb_scripts is disabled on Windows
// === CDB TESTS ==================================================================================
diff --git a/tests/debuginfo/numeric-types.rs b/tests/debuginfo/numeric-types.rs
index c41c9ee21..c122112e6 100644
--- a/tests/debuginfo/numeric-types.rs
+++ b/tests/debuginfo/numeric-types.rs
@@ -1,6 +1,7 @@
// compile-flags:-g
// min-gdb-version: 8.1
+// ignore-windows-gnu // emit_debug_gdb_scripts is disabled on Windows
// Tests the visualizations for `NonZero{I,U}{8,16,32,64,128,size}`, `Wrapping<T>` and
// `Atomic{Bool,I8,I16,I32,I64,Isize,U8,U16,U32,U64,Usize}` located in `libcore.natvis`.
diff --git a/tests/debuginfo/vec-slices.rs b/tests/debuginfo/vec-slices.rs
index 7d88e45ca..de4099a7f 100644
--- a/tests/debuginfo/vec-slices.rs
+++ b/tests/debuginfo/vec-slices.rs
@@ -1,4 +1,3 @@
-// ignore-windows
// min-lldb-version: 310
// compile-flags:-g
diff --git a/tests/mir-opt/76803_regression.encode.SimplifyBranchSame.diff b/tests/mir-opt/76803_regression.encode.SimplifyBranchSame.diff
deleted file mode 100644
index 9780332d8..000000000
--- a/tests/mir-opt/76803_regression.encode.SimplifyBranchSame.diff
+++ /dev/null
@@ -1,29 +0,0 @@
-- // MIR for `encode` before SimplifyBranchSame
-+ // MIR for `encode` after SimplifyBranchSame
-
- fn encode(_1: Type) -> Type {
- debug v => _1; // in scope 0 at $DIR/76803_regression.rs:+0:15: +0:16
- let mut _0: Type; // return place in scope 0 at $DIR/76803_regression.rs:+0:27: +0:31
- let mut _2: isize; // in scope 0 at $DIR/76803_regression.rs:+2:9: +2:16
-
- bb0: {
- _2 = discriminant(_1); // scope 0 at $DIR/76803_regression.rs:+1:11: +1:12
- switchInt(move _2) -> [0: bb2, otherwise: bb1]; // scope 0 at $DIR/76803_regression.rs:+1:5: +1:12
- }
-
- bb1: {
- _0 = move _1; // scope 0 at $DIR/76803_regression.rs:+3:14: +3:15
- goto -> bb3; // scope 0 at $DIR/76803_regression.rs:+3:14: +3:15
- }
-
- bb2: {
- Deinit(_0); // scope 0 at $DIR/76803_regression.rs:+2:20: +2:27
- discriminant(_0) = 1; // scope 0 at $DIR/76803_regression.rs:+2:20: +2:27
- goto -> bb3; // scope 0 at $DIR/76803_regression.rs:+2:20: +2:27
- }
-
- bb3: {
- return; // scope 0 at $DIR/76803_regression.rs:+5:2: +5:2
- }
- }
-
diff --git a/tests/mir-opt/76803_regression.rs b/tests/mir-opt/76803_regression.rs
deleted file mode 100644
index 05dc3c978..000000000
--- a/tests/mir-opt/76803_regression.rs
+++ /dev/null
@@ -1,19 +0,0 @@
-// compile-flags: -Z mir-opt-level=1
-// EMIT_MIR 76803_regression.encode.SimplifyBranchSame.diff
-
-#[derive(Debug, Eq, PartialEq)]
-pub enum Type {
- A,
- B,
-}
-
-pub fn encode(v: Type) -> Type {
- match v {
- Type::A => Type::B,
- _ => v,
- }
-}
-
-fn main() {
- assert_eq!(Type::B, encode(Type::A));
-}
diff --git a/tests/mir-opt/building/async_await.a-{closure#0}.generator_resume.0.mir b/tests/mir-opt/building/async_await.a-{closure#0}.generator_resume.0.mir
index 2a7f90fe9..accb504c0 100644
--- a/tests/mir-opt/building/async_await.a-{closure#0}.generator_resume.0.mir
+++ b/tests/mir-opt/building/async_await.a-{closure#0}.generator_resume.0.mir
@@ -24,9 +24,7 @@ fn a::{closure#0}(_1: Pin<&mut [async fn body@$DIR/async_await.rs:11:14: 11:16]>
bb1: {
_4 = move _2; // scope 0 at $DIR/async_await.rs:+0:14: +0:16
_3 = const (); // scope 0 at $DIR/async_await.rs:+0:14: +0:16
- Deinit(_0); // scope 0 at $DIR/async_await.rs:+0:16: +0:16
- ((_0 as Ready).0: ()) = move _3; // scope 0 at $DIR/async_await.rs:+0:16: +0:16
- discriminant(_0) = 0; // scope 0 at $DIR/async_await.rs:+0:16: +0:16
+ _0 = Poll::<()>::Ready(move _3); // scope 0 at $DIR/async_await.rs:+0:16: +0:16
discriminant((*(_1.0: &mut [async fn body@$DIR/async_await.rs:11:14: 11:16]))) = 1; // scope 0 at $DIR/async_await.rs:+0:16: +0:16
return; // scope 0 at $DIR/async_await.rs:+0:16: +0:16
}
diff --git a/tests/mir-opt/building/async_await.b-{closure#0}.generator_resume.0.mir b/tests/mir-opt/building/async_await.b-{closure#0}.generator_resume.0.mir
index 05edc4797..ad4e5c6fc 100644
--- a/tests/mir-opt/building/async_await.b-{closure#0}.generator_resume.0.mir
+++ b/tests/mir-opt/building/async_await.b-{closure#0}.generator_resume.0.mir
@@ -1,8 +1,22 @@
// MIR for `b::{closure#0}` 0 generator_resume
/* generator_layout = GeneratorLayout {
field_tys: {
- _0: impl std::future::Future<Output = ()>,
- _1: impl std::future::Future<Output = ()>,
+ _0: GeneratorSavedTy {
+ ty: impl std::future::Future<Output = ()>,
+ source_info: SourceInfo {
+ span: $DIR/async_await.rs:15:8: 15:14 (#9),
+ scope: scope[0],
+ },
+ ignore_for_traits: false,
+ },
+ _1: GeneratorSavedTy {
+ ty: impl std::future::Future<Output = ()>,
+ source_info: SourceInfo {
+ span: $DIR/async_await.rs:16:8: 16:14 (#12),
+ scope: scope[0],
+ },
+ ignore_for_traits: false,
+ },
},
variant_fields: {
Unresumed(0): [],
@@ -153,8 +167,7 @@ fn b::{closure#0}(_1: Pin<&mut [async fn body@$DIR/async_await.rs:14:18: 17:2]>,
StorageLive(_19); // scope 1 at $DIR/async_await.rs:+1:8: +1:14
StorageLive(_20); // scope 1 at $DIR/async_await.rs:+1:8: +1:14
_20 = (); // scope 1 at $DIR/async_await.rs:+1:8: +1:14
- Deinit(_0); // scope 1 at $DIR/async_await.rs:+1:8: +1:14
- discriminant(_0) = 1; // scope 1 at $DIR/async_await.rs:+1:8: +1:14
+ _0 = Poll::<()>::Pending; // scope 1 at $DIR/async_await.rs:+1:8: +1:14
discriminant((*(_1.0: &mut [async fn body@$DIR/async_await.rs:14:18: 17:2]))) = 3; // scope 1 at $DIR/async_await.rs:+1:8: +1:14
return; // scope 1 at $DIR/async_await.rs:+1:8: +1:14
}
@@ -262,8 +275,7 @@ fn b::{closure#0}(_1: Pin<&mut [async fn body@$DIR/async_await.rs:14:18: 17:2]>,
StorageLive(_35); // scope 4 at $DIR/async_await.rs:+2:8: +2:14
StorageLive(_36); // scope 4 at $DIR/async_await.rs:+2:8: +2:14
_36 = (); // scope 4 at $DIR/async_await.rs:+2:8: +2:14
- Deinit(_0); // scope 4 at $DIR/async_await.rs:+2:8: +2:14
- discriminant(_0) = 1; // scope 4 at $DIR/async_await.rs:+2:8: +2:14
+ _0 = Poll::<()>::Pending; // scope 4 at $DIR/async_await.rs:+2:8: +2:14
discriminant((*(_1.0: &mut [async fn body@$DIR/async_await.rs:14:18: 17:2]))) = 4; // scope 4 at $DIR/async_await.rs:+2:8: +2:14
return; // scope 4 at $DIR/async_await.rs:+2:8: +2:14
}
@@ -303,9 +315,7 @@ fn b::{closure#0}(_1: Pin<&mut [async fn body@$DIR/async_await.rs:14:18: 17:2]>,
}
bb26: {
- Deinit(_0); // scope 0 at $DIR/async_await.rs:+3:2: +3:2
- ((_0 as Ready).0: ()) = move _37; // scope 0 at $DIR/async_await.rs:+3:2: +3:2
- discriminant(_0) = 0; // scope 0 at $DIR/async_await.rs:+3:2: +3:2
+ _0 = Poll::<()>::Ready(move _37); // scope 0 at $DIR/async_await.rs:+3:2: +3:2
discriminant((*(_1.0: &mut [async fn body@$DIR/async_await.rs:14:18: 17:2]))) = 1; // scope 0 at $DIR/async_await.rs:+3:2: +3:2
return; // scope 0 at $DIR/async_await.rs:+3:2: +3:2
}
diff --git a/tests/mir-opt/building/custom/arrays.arrays.built.after.mir b/tests/mir-opt/building/custom/arrays.arrays.built.after.mir
new file mode 100644
index 000000000..4c9212728
--- /dev/null
+++ b/tests/mir-opt/building/custom/arrays.arrays.built.after.mir
@@ -0,0 +1,14 @@
+// MIR for `arrays` after built
+
+fn arrays() -> usize {
+ let mut _0: usize; // return place in scope 0 at $DIR/arrays.rs:+0:32: +0:37
+ let mut _1: [i32; C]; // in scope 0 at $SRC_DIR/core/src/intrinsics/mir.rs:LL:COL
+ let mut _2: usize; // in scope 0 at $SRC_DIR/core/src/intrinsics/mir.rs:LL:COL
+
+ bb0: {
+ _1 = [const 5_i32; C]; // scope 0 at $SRC_DIR/core/src/intrinsics/mir.rs:LL:COL
+ _2 = Len(_1); // scope 0 at $SRC_DIR/core/src/intrinsics/mir.rs:LL:COL
+ _0 = _2; // scope 0 at $DIR/arrays.rs:+4:9: +4:16
+ return; // scope 0 at $DIR/arrays.rs:+5:9: +5:17
+ }
+}
diff --git a/tests/mir-opt/building/custom/arrays.rs b/tests/mir-opt/building/custom/arrays.rs
new file mode 100644
index 000000000..8e0a1fd7a
--- /dev/null
+++ b/tests/mir-opt/building/custom/arrays.rs
@@ -0,0 +1,19 @@
+#![feature(custom_mir, core_intrinsics, inline_const)]
+
+extern crate core;
+use core::intrinsics::mir::*;
+
+// EMIT_MIR arrays.arrays.built.after.mir
+#[custom_mir(dialect = "built")]
+fn arrays<const C: usize>() -> usize {
+ mir!({
+ let x = [5_i32; C];
+ let c = Len(x);
+ RET = c;
+ Return()
+ })
+}
+
+fn main() {
+ assert_eq!(arrays::<20>(), 20);
+}
diff --git a/tests/mir-opt/building/custom/enums.rs b/tests/mir-opt/building/custom/enums.rs
index e5cd45637..eca5b792e 100644
--- a/tests/mir-opt/building/custom/enums.rs
+++ b/tests/mir-opt/building/custom/enums.rs
@@ -86,6 +86,7 @@ fn switch_option_repr(option: Bool) -> bool {
#[custom_mir(dialect = "runtime", phase = "initial")]
fn set_discr(option: &mut Option<()>) {
mir!({
+ Deinit(*option);
SetDiscriminant(*option, 0);
Return()
})
diff --git a/tests/mir-opt/building/custom/enums.set_discr.built.after.mir b/tests/mir-opt/building/custom/enums.set_discr.built.after.mir
index 7de9ed098..6d0747365 100644
--- a/tests/mir-opt/building/custom/enums.set_discr.built.after.mir
+++ b/tests/mir-opt/building/custom/enums.set_discr.built.after.mir
@@ -4,7 +4,8 @@ fn set_discr(_1: &mut Option<()>) -> () {
let mut _0: (); // return place in scope 0 at $DIR/enums.rs:+0:39: +0:39
bb0: {
- discriminant((*_1)) = 0; // scope 0 at $DIR/enums.rs:+2:9: +2:36
- return; // scope 0 at $DIR/enums.rs:+3:9: +3:17
+ Deinit((*_1)); // scope 0 at $DIR/enums.rs:+2:9: +2:24
+ discriminant((*_1)) = 0; // scope 0 at $DIR/enums.rs:+3:9: +3:36
+ return; // scope 0 at $DIR/enums.rs:+4:9: +4:17
}
}
diff --git a/tests/mir-opt/building/custom/operators.f.built.after.mir b/tests/mir-opt/building/custom/operators.f.built.after.mir
new file mode 100644
index 000000000..cb43d5e6e
--- /dev/null
+++ b/tests/mir-opt/building/custom/operators.f.built.after.mir
@@ -0,0 +1,30 @@
+// MIR for `f` after built
+
+fn f(_1: i32, _2: bool) -> i32 {
+ let mut _0: i32; // return place in scope 0 at $DIR/operators.rs:+0:30: +0:33
+ let mut _3: (i32, bool); // in scope 0 at $SRC_DIR/core/src/intrinsics/mir.rs:LL:COL
+
+ bb0: {
+ _1 = Neg(_1); // scope 0 at $DIR/operators.rs:+2:9: +2:15
+ _2 = Not(_2); // scope 0 at $DIR/operators.rs:+3:9: +3:15
+ _1 = Add(_1, _1); // scope 0 at $DIR/operators.rs:+4:9: +4:18
+ _1 = Sub(_1, _1); // scope 0 at $DIR/operators.rs:+5:9: +5:18
+ _1 = Mul(_1, _1); // scope 0 at $DIR/operators.rs:+6:9: +6:18
+ _1 = Div(_1, _1); // scope 0 at $DIR/operators.rs:+7:9: +7:18
+ _1 = Rem(_1, _1); // scope 0 at $DIR/operators.rs:+8:9: +8:18
+ _1 = BitXor(_1, _1); // scope 0 at $DIR/operators.rs:+9:9: +9:18
+ _1 = BitAnd(_1, _1); // scope 0 at $DIR/operators.rs:+10:9: +10:18
+ _1 = Shl(_1, _1); // scope 0 at $DIR/operators.rs:+11:9: +11:19
+ _1 = Shr(_1, _1); // scope 0 at $DIR/operators.rs:+12:9: +12:19
+ _2 = Eq(_1, _1); // scope 0 at $DIR/operators.rs:+13:9: +13:19
+ _2 = Lt(_1, _1); // scope 0 at $DIR/operators.rs:+14:9: +14:18
+ _2 = Le(_1, _1); // scope 0 at $DIR/operators.rs:+15:9: +15:19
+ _2 = Ge(_1, _1); // scope 0 at $DIR/operators.rs:+16:9: +16:19
+ _2 = Gt(_1, _1); // scope 0 at $DIR/operators.rs:+17:9: +17:18
+ _3 = CheckedAdd(_1, _1); // scope 0 at $SRC_DIR/core/src/intrinsics/mir.rs:LL:COL
+ _2 = (_3.1: bool); // scope 0 at $DIR/operators.rs:+19:9: +19:18
+ _1 = (_3.0: i32); // scope 0 at $DIR/operators.rs:+20:9: +20:18
+ _0 = _1; // scope 0 at $DIR/operators.rs:+21:9: +21:16
+ return; // scope 0 at $DIR/operators.rs:+22:9: +22:17
+ }
+}
diff --git a/tests/mir-opt/building/custom/operators.rs b/tests/mir-opt/building/custom/operators.rs
new file mode 100644
index 000000000..db7a48317
--- /dev/null
+++ b/tests/mir-opt/building/custom/operators.rs
@@ -0,0 +1,31 @@
+// compile-flags: --crate-type=lib
+#![feature(custom_mir, core_intrinsics, inline_const)]
+use std::intrinsics::mir::*;
+
+// EMIT_MIR operators.f.built.after.mir
+#[custom_mir(dialect = "built")]
+pub fn f(a: i32, b: bool) -> i32 {
+ mir!({
+ a = -a;
+ b = !b;
+ a = a + a;
+ a = a - a;
+ a = a * a;
+ a = a / a;
+ a = a % a;
+ a = a ^ a;
+ a = a & a;
+ a = a << a;
+ a = a >> a;
+ b = a == a;
+ b = a < a;
+ b = a <= a;
+ b = a >= a;
+ b = a > a;
+ let res = Checked(a + a);
+ b = res.1;
+ a = res.0;
+ RET = a;
+ Return()
+ })
+}
diff --git a/tests/mir-opt/casts.redundant.InstCombine.diff b/tests/mir-opt/casts.redundant.InstCombine.diff
new file mode 100644
index 000000000..528a8e5a9
--- /dev/null
+++ b/tests/mir-opt/casts.redundant.InstCombine.diff
@@ -0,0 +1,25 @@
+- // MIR for `redundant` before InstCombine
++ // MIR for `redundant` after InstCombine
+
+ fn redundant(_1: *const &u8) -> *const &u8 {
+ debug x => _1; // in scope 0 at $DIR/casts.rs:+0:30: +0:31
+ let mut _0: *const &u8; // return place in scope 0 at $DIR/casts.rs:+0:51: +0:64
+ let mut _2: *const &u8; // in scope 0 at $DIR/casts.rs:+1:5: +1:55
+ let mut _3: *const &u8; // in scope 0 at $DIR/casts.rs:+1:36: +1:37
+ scope 1 (inlined generic_cast::<&u8, &u8>) { // at $DIR/casts.rs:6:5: 6:38
+ debug x => _3; // in scope 1 at $DIR/casts.rs:10:23: 10:24
+ }
+
+ bb0: {
+ StorageLive(_2); // scope 0 at $DIR/casts.rs:+1:5: +1:55
+ StorageLive(_3); // scope 0 at $DIR/casts.rs:+1:36: +1:37
+ _3 = _1; // scope 0 at $DIR/casts.rs:+1:36: +1:37
+- _2 = _3 as *const &u8 (PtrToPtr); // scope 1 at $DIR/casts.rs:11:5: 11:18
++ _2 = _3; // scope 1 at $DIR/casts.rs:11:5: 11:18
+ StorageDead(_3); // scope 0 at $DIR/casts.rs:+1:37: +1:38
+ _0 = _2; // scope 0 at $DIR/casts.rs:+1:5: +1:55
+ StorageDead(_2); // scope 0 at $DIR/casts.rs:+2:1: +2:2
+ return; // scope 0 at $DIR/casts.rs:+2:2: +2:2
+ }
+ }
+
diff --git a/tests/mir-opt/casts.redundant.PreCodegen.after.mir b/tests/mir-opt/casts.redundant.PreCodegen.after.mir
new file mode 100644
index 000000000..21a470ea3
--- /dev/null
+++ b/tests/mir-opt/casts.redundant.PreCodegen.after.mir
@@ -0,0 +1,14 @@
+// MIR for `redundant` after PreCodegen
+
+fn redundant(_1: *const &u8) -> *const &u8 {
+ debug x => _1; // in scope 0 at $DIR/casts.rs:+0:30: +0:31
+ let mut _0: *const &u8; // return place in scope 0 at $DIR/casts.rs:+0:51: +0:64
+ scope 1 (inlined generic_cast::<&u8, &u8>) { // at $DIR/casts.rs:6:5: 6:38
+ debug x => _1; // in scope 1 at $DIR/casts.rs:10:23: 10:24
+ }
+
+ bb0: {
+ _0 = _1; // scope 0 at $DIR/casts.rs:+1:5: +1:55
+ return; // scope 0 at $DIR/casts.rs:+2:2: +2:2
+ }
+}
diff --git a/tests/mir-opt/casts.roundtrip.PreCodegen.after.mir b/tests/mir-opt/casts.roundtrip.PreCodegen.after.mir
new file mode 100644
index 000000000..0c793984c
--- /dev/null
+++ b/tests/mir-opt/casts.roundtrip.PreCodegen.after.mir
@@ -0,0 +1,15 @@
+// MIR for `roundtrip` after PreCodegen
+
+fn roundtrip(_1: *const u8) -> *const u8 {
+ debug x => _1; // in scope 0 at $DIR/casts.rs:+0:18: +0:19
+ let mut _0: *const u8; // return place in scope 0 at $DIR/casts.rs:+0:35: +0:44
+ let mut _2: *mut u8; // in scope 0 at $DIR/casts.rs:+1:5: +1:17
+
+ bb0: {
+ StorageLive(_2); // scope 0 at $DIR/casts.rs:+1:5: +1:17
+ _2 = _1 as *mut u8 (PtrToPtr); // scope 0 at $DIR/casts.rs:+1:5: +1:17
+ _0 = move _2 as *const u8 (Pointer(MutToConstPointer)); // scope 0 at $DIR/casts.rs:+1:5: +1:17
+ StorageDead(_2); // scope 0 at $DIR/casts.rs:+1:16: +1:17
+ return; // scope 0 at $DIR/casts.rs:+2:2: +2:2
+ }
+}
diff --git a/tests/mir-opt/casts.rs b/tests/mir-opt/casts.rs
new file mode 100644
index 000000000..259c462da
--- /dev/null
+++ b/tests/mir-opt/casts.rs
@@ -0,0 +1,17 @@
+#![crate_type = "lib"]
+
+// EMIT_MIR casts.redundant.InstCombine.diff
+// EMIT_MIR casts.redundant.PreCodegen.after.mir
+pub fn redundant<'a, 'b: 'a>(x: *const &'a u8) -> *const &'a u8 {
+ generic_cast::<&'a u8, &'b u8>(x) as *const &'a u8
+}
+
+#[inline]
+fn generic_cast<T, U>(x: *const T) -> *const U {
+ x as *const U
+}
+
+// EMIT_MIR casts.roundtrip.PreCodegen.after.mir
+pub fn roundtrip(x: *const u8) -> *const u8 {
+ x as *mut u8 as *const u8
+}
diff --git a/tests/mir-opt/combine_clone_of_primitives.{impl#0}-clone.InstCombine.diff b/tests/mir-opt/combine_clone_of_primitives.{impl#0}-clone.InstCombine.diff
index 6f01553ee..20b0fb964 100644
--- a/tests/mir-opt/combine_clone_of_primitives.{impl#0}-clone.InstCombine.diff
+++ b/tests/mir-opt/combine_clone_of_primitives.{impl#0}-clone.InstCombine.diff
@@ -61,10 +61,7 @@
bb3: {
StorageDead(_9); // scope 0 at $DIR/combine_clone_of_primitives.rs:10:15: 10:16
- Deinit(_0); // scope 0 at $DIR/combine_clone_of_primitives.rs:+0:10: +0:15
- (_0.0: T) = move _2; // scope 0 at $DIR/combine_clone_of_primitives.rs:+0:10: +0:15
- (_0.1: u64) = move _5; // scope 0 at $DIR/combine_clone_of_primitives.rs:+0:10: +0:15
- (_0.2: [f32; 3]) = move _8; // scope 0 at $DIR/combine_clone_of_primitives.rs:+0:10: +0:15
+ _0 = MyThing::<T> { v: move _2, i: move _5, a: move _8 }; // scope 0 at $DIR/combine_clone_of_primitives.rs:+0:10: +0:15
StorageDead(_8); // scope 0 at $DIR/combine_clone_of_primitives.rs:+0:14: +0:15
StorageDead(_5); // scope 0 at $DIR/combine_clone_of_primitives.rs:+0:14: +0:15
StorageDead(_2); // scope 0 at $DIR/combine_clone_of_primitives.rs:+0:14: +0:15
diff --git a/tests/mir-opt/const_allocation.main.ConstProp.after.32bit.mir b/tests/mir-opt/const_allocation.main.ConstProp.after.32bit.mir
index 6140fc52f..9b69f79c2 100644
--- a/tests/mir-opt/const_allocation.main.ConstProp.after.32bit.mir
+++ b/tests/mir-opt/const_allocation.main.ConstProp.after.32bit.mir
@@ -26,17 +26,17 @@ alloc1 (static: FOO, size: 8, align: 4) {
alloc18 (size: 48, align: 4) {
0x00 │ 00 00 00 00 __ __ __ __ ╾─alloc5──╼ 00 00 00 00 │ ....░░░░╾──╼....
- 0x10 │ 00 00 00 00 __ __ __ __ ╾─alloc9──╼ 02 00 00 00 │ ....░░░░╾──╼....
- 0x20 │ 01 00 00 00 2a 00 00 00 ╾─alloc14─╼ 03 00 00 00 │ ....*...╾──╼....
+ 0x10 │ 00 00 00 00 __ __ __ __ ╾─alloc8──╼ 02 00 00 00 │ ....░░░░╾──╼....
+ 0x20 │ 01 00 00 00 2a 00 00 00 ╾─alloc13─╼ 03 00 00 00 │ ....*...╾──╼....
}
alloc5 (size: 0, align: 4) {}
-alloc9 (size: 16, align: 4) {
- ╾─alloc8──╼ 03 00 00 00 ╾─alloc10─╼ 03 00 00 00 │ ╾──╼....╾──╼....
+alloc8 (size: 16, align: 4) {
+ ╾─alloc9──╼ 03 00 00 00 ╾─alloc10─╼ 03 00 00 00 │ ╾──╼....╾──╼....
}
-alloc8 (size: 3, align: 1) {
+alloc9 (size: 3, align: 1) {
66 6f 6f │ foo
}
@@ -44,12 +44,12 @@ alloc10 (size: 3, align: 1) {
62 61 72 │ bar
}
-alloc14 (size: 24, align: 4) {
- 0x00 │ ╾─alloc13─╼ 03 00 00 00 ╾─alloc15─╼ 03 00 00 00 │ ╾──╼....╾──╼....
+alloc13 (size: 24, align: 4) {
+ 0x00 │ ╾─alloc14─╼ 03 00 00 00 ╾─alloc15─╼ 03 00 00 00 │ ╾──╼....╾──╼....
0x10 │ ╾─alloc16─╼ 04 00 00 00 │ ╾──╼....
}
-alloc13 (size: 3, align: 1) {
+alloc14 (size: 3, align: 1) {
6d 65 68 │ meh
}
diff --git a/tests/mir-opt/const_allocation.main.ConstProp.after.64bit.mir b/tests/mir-opt/const_allocation.main.ConstProp.after.64bit.mir
index b2ed23c68..d0f196e72 100644
--- a/tests/mir-opt/const_allocation.main.ConstProp.after.64bit.mir
+++ b/tests/mir-opt/const_allocation.main.ConstProp.after.64bit.mir
@@ -27,19 +27,19 @@ alloc1 (static: FOO, size: 16, align: 8) {
alloc18 (size: 72, align: 8) {
0x00 │ 00 00 00 00 __ __ __ __ ╾───────alloc5────────╼ │ ....░░░░╾──────╼
0x10 │ 00 00 00 00 00 00 00 00 00 00 00 00 __ __ __ __ │ ............░░░░
- 0x20 │ ╾───────alloc9────────╼ 02 00 00 00 00 00 00 00 │ ╾──────╼........
- 0x30 │ 01 00 00 00 2a 00 00 00 ╾───────alloc14───────╼ │ ....*...╾──────╼
+ 0x20 │ ╾───────alloc8────────╼ 02 00 00 00 00 00 00 00 │ ╾──────╼........
+ 0x30 │ 01 00 00 00 2a 00 00 00 ╾───────alloc13───────╼ │ ....*...╾──────╼
0x40 │ 03 00 00 00 00 00 00 00 │ ........
}
alloc5 (size: 0, align: 8) {}
-alloc9 (size: 32, align: 8) {
- 0x00 │ ╾───────alloc8────────╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........
+alloc8 (size: 32, align: 8) {
+ 0x00 │ ╾───────alloc9────────╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........
0x10 │ ╾───────alloc10───────╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........
}
-alloc8 (size: 3, align: 1) {
+alloc9 (size: 3, align: 1) {
66 6f 6f │ foo
}
@@ -47,13 +47,13 @@ alloc10 (size: 3, align: 1) {
62 61 72 │ bar
}
-alloc14 (size: 48, align: 8) {
- 0x00 │ ╾───────alloc13───────╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........
+alloc13 (size: 48, align: 8) {
+ 0x00 │ ╾───────alloc14───────╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........
0x10 │ ╾───────alloc15───────╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........
0x20 │ ╾───────alloc16───────╼ 04 00 00 00 00 00 00 00 │ ╾──────╼........
}
-alloc13 (size: 3, align: 1) {
+alloc14 (size: 3, align: 1) {
6d 65 68 │ meh
}
diff --git a/tests/mir-opt/const_debuginfo.main.ConstDebugInfo.diff b/tests/mir-opt/const_debuginfo.main.ConstDebugInfo.diff
index dd548adde..f1f53a481 100644
--- a/tests/mir-opt/const_debuginfo.main.ConstDebugInfo.diff
+++ b/tests/mir-opt/const_debuginfo.main.ConstDebugInfo.diff
@@ -56,25 +56,13 @@
}
bb0: {
- StorageLive(_1); // scope 0 at $DIR/const_debuginfo.rs:+1:9: +1:10
_1 = const 1_u8; // scope 0 at $DIR/const_debuginfo.rs:+1:13: +1:16
- StorageLive(_2); // scope 1 at $DIR/const_debuginfo.rs:+2:9: +2:10
_2 = const 2_u8; // scope 1 at $DIR/const_debuginfo.rs:+2:13: +2:16
- StorageLive(_3); // scope 2 at $DIR/const_debuginfo.rs:+3:9: +3:10
_3 = const 3_u8; // scope 2 at $DIR/const_debuginfo.rs:+3:13: +3:16
StorageLive(_4); // scope 3 at $DIR/const_debuginfo.rs:+4:9: +4:12
StorageLive(_5); // scope 3 at $DIR/const_debuginfo.rs:+4:15: +4:20
- StorageLive(_6); // scope 3 at $DIR/const_debuginfo.rs:+4:15: +4:16
- _6 = const 1_u8; // scope 3 at $DIR/const_debuginfo.rs:+4:15: +4:16
- StorageLive(_7); // scope 3 at $DIR/const_debuginfo.rs:+4:19: +4:20
- _7 = const 2_u8; // scope 3 at $DIR/const_debuginfo.rs:+4:19: +4:20
_5 = const 3_u8; // scope 3 at $DIR/const_debuginfo.rs:+4:15: +4:20
- StorageDead(_7); // scope 3 at $DIR/const_debuginfo.rs:+4:19: +4:20
- StorageDead(_6); // scope 3 at $DIR/const_debuginfo.rs:+4:19: +4:20
- StorageLive(_8); // scope 3 at $DIR/const_debuginfo.rs:+4:23: +4:24
- _8 = const 3_u8; // scope 3 at $DIR/const_debuginfo.rs:+4:23: +4:24
_4 = const 6_u8; // scope 3 at $DIR/const_debuginfo.rs:+4:15: +4:24
- StorageDead(_8); // scope 3 at $DIR/const_debuginfo.rs:+4:23: +4:24
StorageDead(_5); // scope 3 at $DIR/const_debuginfo.rs:+4:23: +4:24
StorageLive(_9); // scope 4 at $DIR/const_debuginfo.rs:+6:9: +6:10
_9 = const "hello, world!"; // scope 4 at $DIR/const_debuginfo.rs:+6:13: +6:28
@@ -84,42 +72,22 @@
StorageLive(_14); // scope 5 at $DIR/const_debuginfo.rs:+8:9: +8:10
StorageLive(_15); // scope 5 at $DIR/const_debuginfo.rs:+8:9: +8:10
StorageLive(_16); // scope 5 at $DIR/const_debuginfo.rs:+8:9: +8:10
- Deinit(_14); // scope 5 at $DIR/const_debuginfo.rs:+8:13: +8:34
- Deinit(_15); // scope 5 at $DIR/const_debuginfo.rs:+8:13: +8:34
- Deinit(_16); // scope 5 at $DIR/const_debuginfo.rs:+8:13: +8:34
_14 = const true; // scope 5 at $DIR/const_debuginfo.rs:+8:13: +8:34
_15 = const false; // scope 5 at $DIR/const_debuginfo.rs:+8:13: +8:34
_16 = const 123_u32; // scope 5 at $DIR/const_debuginfo.rs:+8:13: +8:34
StorageLive(_10); // scope 6 at $DIR/const_debuginfo.rs:+10:9: +10:10
- Deinit(_10); // scope 6 at $DIR/const_debuginfo.rs:+10:13: +10:24
- ((_10 as Some).0: u16) = const 99_u16; // scope 6 at $DIR/const_debuginfo.rs:+10:13: +10:24
- discriminant(_10) = 1; // scope 6 at $DIR/const_debuginfo.rs:+10:13: +10:24
- StorageLive(_17); // scope 7 at $DIR/const_debuginfo.rs:+12:9: +12:10
- StorageLive(_18); // scope 7 at $DIR/const_debuginfo.rs:+12:9: +12:10
- Deinit(_17); // scope 7 at $DIR/const_debuginfo.rs:+12:13: +12:35
- Deinit(_18); // scope 7 at $DIR/const_debuginfo.rs:+12:13: +12:35
+ _10 = Option::<u16>::Some(const 99_u16); // scope 6 at $DIR/const_debuginfo.rs:+10:13: +10:24
_17 = const 32_u32; // scope 7 at $DIR/const_debuginfo.rs:+12:13: +12:35
_18 = const 32_u32; // scope 7 at $DIR/const_debuginfo.rs:+12:13: +12:35
StorageLive(_11); // scope 8 at $DIR/const_debuginfo.rs:+13:9: +13:10
- StorageLive(_12); // scope 8 at $DIR/const_debuginfo.rs:+13:13: +13:16
- _12 = const 32_u32; // scope 8 at $DIR/const_debuginfo.rs:+13:13: +13:16
- StorageLive(_13); // scope 8 at $DIR/const_debuginfo.rs:+13:19: +13:22
- _13 = const 32_u32; // scope 8 at $DIR/const_debuginfo.rs:+13:19: +13:22
_11 = const 64_u32; // scope 8 at $DIR/const_debuginfo.rs:+13:13: +13:22
- StorageDead(_13); // scope 8 at $DIR/const_debuginfo.rs:+13:21: +13:22
- StorageDead(_12); // scope 8 at $DIR/const_debuginfo.rs:+13:21: +13:22
StorageDead(_11); // scope 8 at $DIR/const_debuginfo.rs:+14:1: +14:2
- StorageDead(_17); // scope 7 at $DIR/const_debuginfo.rs:+14:1: +14:2
- StorageDead(_18); // scope 7 at $DIR/const_debuginfo.rs:+14:1: +14:2
StorageDead(_10); // scope 6 at $DIR/const_debuginfo.rs:+14:1: +14:2
StorageDead(_14); // scope 5 at $DIR/const_debuginfo.rs:+14:1: +14:2
StorageDead(_15); // scope 5 at $DIR/const_debuginfo.rs:+14:1: +14:2
StorageDead(_16); // scope 5 at $DIR/const_debuginfo.rs:+14:1: +14:2
StorageDead(_9); // scope 4 at $DIR/const_debuginfo.rs:+14:1: +14:2
StorageDead(_4); // scope 3 at $DIR/const_debuginfo.rs:+14:1: +14:2
- StorageDead(_3); // scope 2 at $DIR/const_debuginfo.rs:+14:1: +14:2
- StorageDead(_2); // scope 1 at $DIR/const_debuginfo.rs:+14:1: +14:2
- StorageDead(_1); // scope 0 at $DIR/const_debuginfo.rs:+14:1: +14:2
return; // scope 0 at $DIR/const_debuginfo.rs:+14:2: +14:2
}
}
diff --git a/tests/mir-opt/const_goto_storage.match_nested_if.ConstGoto.diff b/tests/mir-opt/const_goto_storage.match_nested_if.ConstGoto.diff
index f54577259..4dc98f856 100644
--- a/tests/mir-opt/const_goto_storage.match_nested_if.ConstGoto.diff
+++ b/tests/mir-opt/const_goto_storage.match_nested_if.ConstGoto.diff
@@ -17,7 +17,7 @@
bb0: {
StorageLive(_1); // scope 0 at $DIR/const_goto_storage.rs:+1:9: +1:12
- StorageLive(_2); // scope 0 at $DIR/const_goto_storage.rs:+1:21: +1:23
-- Deinit(_2); // scope 0 at $DIR/const_goto_storage.rs:+1:21: +1:23
+- _2 = (); // scope 0 at $DIR/const_goto_storage.rs:+1:21: +1:23
- StorageLive(_3); // scope 0 at $DIR/const_goto_storage.rs:+2:15: +6:10
- StorageLive(_4); // scope 0 at $DIR/const_goto_storage.rs:+2:18: +2:76
- StorageLive(_5); // scope 0 at $DIR/const_goto_storage.rs:+2:21: +2:52
diff --git a/tests/mir-opt/const_prop/aggregate.foo.ConstProp.diff b/tests/mir-opt/const_prop/aggregate.foo.ConstProp.diff
new file mode 100644
index 000000000..6ac460db8
--- /dev/null
+++ b/tests/mir-opt/const_prop/aggregate.foo.ConstProp.diff
@@ -0,0 +1,55 @@
+- // MIR for `foo` before ConstProp
++ // MIR for `foo` after ConstProp
+
+ fn foo(_1: u8) -> () {
+ debug x => _1; // in scope 0 at $DIR/aggregate.rs:+0:8: +0:9
+ let mut _0: (); // return place in scope 0 at $DIR/aggregate.rs:+0:15: +0:15
+ let _2: i32; // in scope 0 at $DIR/aggregate.rs:+2:9: +2:14
+ let mut _3: i32; // in scope 0 at $DIR/aggregate.rs:+2:17: +2:25
+ let mut _4: (i32, u8); // in scope 0 at $DIR/aggregate.rs:+2:17: +2:23
+ let mut _5: u8; // in scope 0 at $DIR/aggregate.rs:+2:21: +2:22
+ let mut _7: i32; // in scope 0 at $DIR/aggregate.rs:+3:18: +3:26
+ let mut _8: (u8, i32); // in scope 0 at $DIR/aggregate.rs:+3:18: +3:24
+ let mut _9: u8; // in scope 0 at $DIR/aggregate.rs:+3:19: +3:20
+ scope 1 {
+ debug first => _2; // in scope 1 at $DIR/aggregate.rs:+2:9: +2:14
+ let _6: i32; // in scope 1 at $DIR/aggregate.rs:+3:9: +3:15
+ scope 2 {
+ debug second => _6; // in scope 2 at $DIR/aggregate.rs:+3:9: +3:15
+ }
+ }
+
+ bb0: {
+ StorageLive(_2); // scope 0 at $DIR/aggregate.rs:+2:9: +2:14
+ StorageLive(_3); // scope 0 at $DIR/aggregate.rs:+2:17: +2:25
+ StorageLive(_4); // scope 0 at $DIR/aggregate.rs:+2:17: +2:23
+ StorageLive(_5); // scope 0 at $DIR/aggregate.rs:+2:21: +2:22
+ _5 = _1; // scope 0 at $DIR/aggregate.rs:+2:21: +2:22
+ _4 = (const 0_i32, move _5); // scope 0 at $DIR/aggregate.rs:+2:17: +2:23
+ StorageDead(_5); // scope 0 at $DIR/aggregate.rs:+2:22: +2:23
+- _3 = (_4.0: i32); // scope 0 at $DIR/aggregate.rs:+2:17: +2:25
+- _2 = Add(move _3, const 1_i32); // scope 0 at $DIR/aggregate.rs:+2:17: +2:29
++ _3 = const 0_i32; // scope 0 at $DIR/aggregate.rs:+2:17: +2:25
++ _2 = const 1_i32; // scope 0 at $DIR/aggregate.rs:+2:17: +2:29
+ StorageDead(_3); // scope 0 at $DIR/aggregate.rs:+2:28: +2:29
+ StorageDead(_4); // scope 0 at $DIR/aggregate.rs:+2:29: +2:30
+ StorageLive(_6); // scope 1 at $DIR/aggregate.rs:+3:9: +3:15
+ StorageLive(_7); // scope 1 at $DIR/aggregate.rs:+3:18: +3:26
+ StorageLive(_8); // scope 1 at $DIR/aggregate.rs:+3:18: +3:24
+ StorageLive(_9); // scope 1 at $DIR/aggregate.rs:+3:19: +3:20
+ _9 = _1; // scope 1 at $DIR/aggregate.rs:+3:19: +3:20
+ _8 = (move _9, const 1_i32); // scope 1 at $DIR/aggregate.rs:+3:18: +3:24
+ StorageDead(_9); // scope 1 at $DIR/aggregate.rs:+3:23: +3:24
+- _7 = (_8.1: i32); // scope 1 at $DIR/aggregate.rs:+3:18: +3:26
+- _6 = Add(move _7, const 2_i32); // scope 1 at $DIR/aggregate.rs:+3:18: +3:30
++ _7 = const 1_i32; // scope 1 at $DIR/aggregate.rs:+3:18: +3:26
++ _6 = const 3_i32; // scope 1 at $DIR/aggregate.rs:+3:18: +3:30
+ StorageDead(_7); // scope 1 at $DIR/aggregate.rs:+3:29: +3:30
+ StorageDead(_8); // scope 1 at $DIR/aggregate.rs:+3:30: +3:31
+ _0 = const (); // scope 0 at $DIR/aggregate.rs:+0:15: +4:2
+ StorageDead(_6); // scope 1 at $DIR/aggregate.rs:+4:1: +4:2
+ StorageDead(_2); // scope 0 at $DIR/aggregate.rs:+4:1: +4:2
+ return; // scope 0 at $DIR/aggregate.rs:+4:2: +4:2
+ }
+ }
+
diff --git a/tests/mir-opt/const_prop/aggregate.foo.PreCodegen.after.mir b/tests/mir-opt/const_prop/aggregate.foo.PreCodegen.after.mir
new file mode 100644
index 000000000..2ef6d74e5
--- /dev/null
+++ b/tests/mir-opt/const_prop/aggregate.foo.PreCodegen.after.mir
@@ -0,0 +1,49 @@
+// MIR for `foo` after PreCodegen
+
+fn foo(_1: u8) -> () {
+ debug x => _1; // in scope 0 at $DIR/aggregate.rs:+0:8: +0:9
+ let mut _0: (); // return place in scope 0 at $DIR/aggregate.rs:+0:15: +0:15
+ let _2: i32; // in scope 0 at $DIR/aggregate.rs:+2:9: +2:14
+ let mut _3: i32; // in scope 0 at $DIR/aggregate.rs:+2:17: +2:25
+ let mut _4: (i32, u8); // in scope 0 at $DIR/aggregate.rs:+2:17: +2:23
+ let mut _5: u8; // in scope 0 at $DIR/aggregate.rs:+2:21: +2:22
+ let mut _7: i32; // in scope 0 at $DIR/aggregate.rs:+3:18: +3:26
+ let mut _8: (u8, i32); // in scope 0 at $DIR/aggregate.rs:+3:18: +3:24
+ let mut _9: u8; // in scope 0 at $DIR/aggregate.rs:+3:19: +3:20
+ scope 1 {
+ debug first => _2; // in scope 1 at $DIR/aggregate.rs:+2:9: +2:14
+ let _6: i32; // in scope 1 at $DIR/aggregate.rs:+3:9: +3:15
+ scope 2 {
+ debug second => _6; // in scope 2 at $DIR/aggregate.rs:+3:9: +3:15
+ }
+ }
+
+ bb0: {
+ StorageLive(_2); // scope 0 at $DIR/aggregate.rs:+2:9: +2:14
+ StorageLive(_3); // scope 0 at $DIR/aggregate.rs:+2:17: +2:25
+ StorageLive(_4); // scope 0 at $DIR/aggregate.rs:+2:17: +2:23
+ StorageLive(_5); // scope 0 at $DIR/aggregate.rs:+2:21: +2:22
+ _5 = _1; // scope 0 at $DIR/aggregate.rs:+2:21: +2:22
+ _4 = (const 0_i32, move _5); // scope 0 at $DIR/aggregate.rs:+2:17: +2:23
+ StorageDead(_5); // scope 0 at $DIR/aggregate.rs:+2:22: +2:23
+ _3 = const 0_i32; // scope 0 at $DIR/aggregate.rs:+2:17: +2:25
+ _2 = const 1_i32; // scope 0 at $DIR/aggregate.rs:+2:17: +2:29
+ StorageDead(_3); // scope 0 at $DIR/aggregate.rs:+2:28: +2:29
+ StorageDead(_4); // scope 0 at $DIR/aggregate.rs:+2:29: +2:30
+ StorageLive(_6); // scope 1 at $DIR/aggregate.rs:+3:9: +3:15
+ StorageLive(_7); // scope 1 at $DIR/aggregate.rs:+3:18: +3:26
+ StorageLive(_8); // scope 1 at $DIR/aggregate.rs:+3:18: +3:24
+ StorageLive(_9); // scope 1 at $DIR/aggregate.rs:+3:19: +3:20
+ _9 = _1; // scope 1 at $DIR/aggregate.rs:+3:19: +3:20
+ _8 = (move _9, const 1_i32); // scope 1 at $DIR/aggregate.rs:+3:18: +3:24
+ StorageDead(_9); // scope 1 at $DIR/aggregate.rs:+3:23: +3:24
+ _7 = const 1_i32; // scope 1 at $DIR/aggregate.rs:+3:18: +3:26
+ _6 = const 3_i32; // scope 1 at $DIR/aggregate.rs:+3:18: +3:30
+ StorageDead(_7); // scope 1 at $DIR/aggregate.rs:+3:29: +3:30
+ StorageDead(_8); // scope 1 at $DIR/aggregate.rs:+3:30: +3:31
+ _0 = const (); // scope 0 at $DIR/aggregate.rs:+0:15: +4:2
+ StorageDead(_6); // scope 1 at $DIR/aggregate.rs:+4:1: +4:2
+ StorageDead(_2); // scope 0 at $DIR/aggregate.rs:+4:1: +4:2
+ return; // scope 0 at $DIR/aggregate.rs:+4:2: +4:2
+ }
+}
diff --git a/tests/mir-opt/const_prop/aggregate.main.ConstProp.diff b/tests/mir-opt/const_prop/aggregate.main.ConstProp.diff
index 04378dbf3..f6e58955b 100644
--- a/tests/mir-opt/const_prop/aggregate.main.ConstProp.diff
+++ b/tests/mir-opt/const_prop/aggregate.main.ConstProp.diff
@@ -3,9 +3,11 @@
fn main() -> () {
let mut _0: (); // return place in scope 0 at $DIR/aggregate.rs:+0:11: +0:11
- let _1: i32; // in scope 0 at $DIR/aggregate.rs:+1:9: +1:10
- let mut _2: i32; // in scope 0 at $DIR/aggregate.rs:+1:13: +1:24
- let mut _3: (i32, i32, i32); // in scope 0 at $DIR/aggregate.rs:+1:13: +1:22
+ let _1: u8; // in scope 0 at $DIR/aggregate.rs:+1:9: +1:10
+ let mut _2: u8; // in scope 0 at $DIR/aggregate.rs:+1:13: +1:24
+ let mut _3: (i32, u8, i32); // in scope 0 at $DIR/aggregate.rs:+1:13: +1:22
+ let _4: (); // in scope 0 at $DIR/aggregate.rs:+2:5: +2:11
+ let mut _5: u8; // in scope 0 at $DIR/aggregate.rs:+2:9: +2:10
scope 1 {
debug x => _1; // in scope 1 at $DIR/aggregate.rs:+1:9: +1:10
}
@@ -14,19 +16,29 @@
StorageLive(_1); // scope 0 at $DIR/aggregate.rs:+1:9: +1:10
StorageLive(_2); // scope 0 at $DIR/aggregate.rs:+1:13: +1:24
StorageLive(_3); // scope 0 at $DIR/aggregate.rs:+1:13: +1:22
- Deinit(_3); // scope 0 at $DIR/aggregate.rs:+1:13: +1:22
- (_3.0: i32) = const 0_i32; // scope 0 at $DIR/aggregate.rs:+1:13: +1:22
- (_3.1: i32) = const 1_i32; // scope 0 at $DIR/aggregate.rs:+1:13: +1:22
- (_3.2: i32) = const 2_i32; // scope 0 at $DIR/aggregate.rs:+1:13: +1:22
-- _2 = (_3.1: i32); // scope 0 at $DIR/aggregate.rs:+1:13: +1:24
-- _1 = Add(move _2, const 0_i32); // scope 0 at $DIR/aggregate.rs:+1:13: +1:28
-+ _2 = const 1_i32; // scope 0 at $DIR/aggregate.rs:+1:13: +1:24
-+ _1 = const 1_i32; // scope 0 at $DIR/aggregate.rs:+1:13: +1:28
+ _3 = (const 0_i32, const 1_u8, const 2_i32); // scope 0 at $DIR/aggregate.rs:+1:13: +1:22
+- _2 = (_3.1: u8); // scope 0 at $DIR/aggregate.rs:+1:13: +1:24
+- _1 = Add(move _2, const 0_u8); // scope 0 at $DIR/aggregate.rs:+1:13: +1:28
++ _2 = const 1_u8; // scope 0 at $DIR/aggregate.rs:+1:13: +1:24
++ _1 = const 1_u8; // scope 0 at $DIR/aggregate.rs:+1:13: +1:28
StorageDead(_2); // scope 0 at $DIR/aggregate.rs:+1:27: +1:28
StorageDead(_3); // scope 0 at $DIR/aggregate.rs:+1:28: +1:29
- _0 = const (); // scope 0 at $DIR/aggregate.rs:+0:11: +2:2
- StorageDead(_1); // scope 0 at $DIR/aggregate.rs:+2:1: +2:2
- return; // scope 0 at $DIR/aggregate.rs:+2:2: +2:2
+ StorageLive(_4); // scope 1 at $DIR/aggregate.rs:+2:5: +2:11
+ StorageLive(_5); // scope 1 at $DIR/aggregate.rs:+2:9: +2:10
+- _5 = _1; // scope 1 at $DIR/aggregate.rs:+2:9: +2:10
++ _5 = const 1_u8; // scope 1 at $DIR/aggregate.rs:+2:9: +2:10
+ _4 = foo(move _5) -> bb1; // scope 1 at $DIR/aggregate.rs:+2:5: +2:11
+ // mir::Constant
+ // + span: $DIR/aggregate.rs:8:5: 8:8
+ // + literal: Const { ty: fn(u8) {foo}, val: Value(<ZST>) }
+ }
+
+ bb1: {
+ StorageDead(_5); // scope 1 at $DIR/aggregate.rs:+2:10: +2:11
+ StorageDead(_4); // scope 1 at $DIR/aggregate.rs:+2:11: +2:12
+ _0 = const (); // scope 0 at $DIR/aggregate.rs:+0:11: +3:2
+ StorageDead(_1); // scope 0 at $DIR/aggregate.rs:+3:1: +3:2
+ return; // scope 0 at $DIR/aggregate.rs:+3:2: +3:2
}
}
diff --git a/tests/mir-opt/const_prop/aggregate.main.PreCodegen.after.mir b/tests/mir-opt/const_prop/aggregate.main.PreCodegen.after.mir
index cfc9a72e3..4706af92c 100644
--- a/tests/mir-opt/const_prop/aggregate.main.PreCodegen.after.mir
+++ b/tests/mir-opt/const_prop/aggregate.main.PreCodegen.after.mir
@@ -2,9 +2,11 @@
fn main() -> () {
let mut _0: (); // return place in scope 0 at $DIR/aggregate.rs:+0:11: +0:11
- let _1: i32; // in scope 0 at $DIR/aggregate.rs:+1:9: +1:10
- let mut _2: i32; // in scope 0 at $DIR/aggregate.rs:+1:13: +1:24
- let mut _3: (i32, i32, i32); // in scope 0 at $DIR/aggregate.rs:+1:13: +1:22
+ let _1: u8; // in scope 0 at $DIR/aggregate.rs:+1:9: +1:10
+ let mut _2: u8; // in scope 0 at $DIR/aggregate.rs:+1:13: +1:24
+ let mut _3: (i32, u8, i32); // in scope 0 at $DIR/aggregate.rs:+1:13: +1:22
+ let _4: (); // in scope 0 at $DIR/aggregate.rs:+2:5: +2:11
+ let mut _5: u8; // in scope 0 at $DIR/aggregate.rs:+2:9: +2:10
scope 1 {
debug x => _1; // in scope 1 at $DIR/aggregate.rs:+1:9: +1:10
}
@@ -13,16 +15,25 @@ fn main() -> () {
StorageLive(_1); // scope 0 at $DIR/aggregate.rs:+1:9: +1:10
StorageLive(_2); // scope 0 at $DIR/aggregate.rs:+1:13: +1:24
StorageLive(_3); // scope 0 at $DIR/aggregate.rs:+1:13: +1:22
- Deinit(_3); // scope 0 at $DIR/aggregate.rs:+1:13: +1:22
- (_3.0: i32) = const 0_i32; // scope 0 at $DIR/aggregate.rs:+1:13: +1:22
- (_3.1: i32) = const 1_i32; // scope 0 at $DIR/aggregate.rs:+1:13: +1:22
- (_3.2: i32) = const 2_i32; // scope 0 at $DIR/aggregate.rs:+1:13: +1:22
- _2 = const 1_i32; // scope 0 at $DIR/aggregate.rs:+1:13: +1:24
- _1 = const 1_i32; // scope 0 at $DIR/aggregate.rs:+1:13: +1:28
+ _3 = (const 0_i32, const 1_u8, const 2_i32); // scope 0 at $DIR/aggregate.rs:+1:13: +1:22
+ _2 = const 1_u8; // scope 0 at $DIR/aggregate.rs:+1:13: +1:24
+ _1 = const 1_u8; // scope 0 at $DIR/aggregate.rs:+1:13: +1:28
StorageDead(_2); // scope 0 at $DIR/aggregate.rs:+1:27: +1:28
StorageDead(_3); // scope 0 at $DIR/aggregate.rs:+1:28: +1:29
- _0 = const (); // scope 0 at $DIR/aggregate.rs:+0:11: +2:2
- StorageDead(_1); // scope 0 at $DIR/aggregate.rs:+2:1: +2:2
- return; // scope 0 at $DIR/aggregate.rs:+2:2: +2:2
+ StorageLive(_4); // scope 1 at $DIR/aggregate.rs:+2:5: +2:11
+ StorageLive(_5); // scope 1 at $DIR/aggregate.rs:+2:9: +2:10
+ _5 = const 1_u8; // scope 1 at $DIR/aggregate.rs:+2:9: +2:10
+ _4 = foo(move _5) -> bb1; // scope 1 at $DIR/aggregate.rs:+2:5: +2:11
+ // mir::Constant
+ // + span: $DIR/aggregate.rs:8:5: 8:8
+ // + literal: Const { ty: fn(u8) {foo}, val: Value(<ZST>) }
+ }
+
+ bb1: {
+ StorageDead(_5); // scope 1 at $DIR/aggregate.rs:+2:10: +2:11
+ StorageDead(_4); // scope 1 at $DIR/aggregate.rs:+2:11: +2:12
+ _0 = const (); // scope 0 at $DIR/aggregate.rs:+0:11: +3:2
+ StorageDead(_1); // scope 0 at $DIR/aggregate.rs:+3:1: +3:2
+ return; // scope 0 at $DIR/aggregate.rs:+3:2: +3:2
}
}
diff --git a/tests/mir-opt/const_prop/aggregate.rs b/tests/mir-opt/const_prop/aggregate.rs
index 6a3080384..aa123b7a8 100644
--- a/tests/mir-opt/const_prop/aggregate.rs
+++ b/tests/mir-opt/const_prop/aggregate.rs
@@ -5,4 +5,13 @@
// EMIT_MIR aggregate.main.PreCodegen.after.mir
fn main() {
let x = (0, 1, 2).1 + 0;
+ foo(x);
+}
+
+// EMIT_MIR aggregate.foo.ConstProp.diff
+// EMIT_MIR aggregate.foo.PreCodegen.after.mir
+fn foo(x: u8) {
+ // Verify that we still propagate if part of the aggregate is not known.
+ let first = (0, x).0 + 1;
+ let second = (x, 1).1 + 2;
}
diff --git a/tests/mir-opt/const_prop/bad_op_div_by_zero.main.ConstProp.diff b/tests/mir-opt/const_prop/bad_op_div_by_zero.main.ConstProp.diff
index bea32a67e..900061a48 100644
--- a/tests/mir-opt/const_prop/bad_op_div_by_zero.main.ConstProp.diff
+++ b/tests/mir-opt/const_prop/bad_op_div_by_zero.main.ConstProp.diff
@@ -24,9 +24,10 @@
StorageLive(_3); // scope 1 at $DIR/bad_op_div_by_zero.rs:+2:18: +2:19
- _3 = _1; // scope 1 at $DIR/bad_op_div_by_zero.rs:+2:18: +2:19
- _4 = Eq(_3, const 0_i32); // scope 1 at $DIR/bad_op_div_by_zero.rs:+2:14: +2:19
+- assert(!move _4, "attempt to divide `{}` by zero", const 1_i32) -> bb1; // scope 1 at $DIR/bad_op_div_by_zero.rs:+2:14: +2:19
+ _3 = const 0_i32; // scope 1 at $DIR/bad_op_div_by_zero.rs:+2:18: +2:19
+ _4 = const true; // scope 1 at $DIR/bad_op_div_by_zero.rs:+2:14: +2:19
- assert(!move _4, "attempt to divide `{}` by zero", const 1_i32) -> bb1; // scope 1 at $DIR/bad_op_div_by_zero.rs:+2:14: +2:19
++ assert(!const true, "attempt to divide `{}` by zero", const 1_i32) -> bb1; // scope 1 at $DIR/bad_op_div_by_zero.rs:+2:14: +2:19
}
bb1: {
diff --git a/tests/mir-opt/const_prop/bad_op_mod_by_zero.main.ConstProp.diff b/tests/mir-opt/const_prop/bad_op_mod_by_zero.main.ConstProp.diff
index 8485703e3..ae9ffd519 100644
--- a/tests/mir-opt/const_prop/bad_op_mod_by_zero.main.ConstProp.diff
+++ b/tests/mir-opt/const_prop/bad_op_mod_by_zero.main.ConstProp.diff
@@ -18,35 +18,27 @@
}
bb0: {
- StorageLive(_1); // scope 0 at $DIR/bad_op_mod_by_zero.rs:+1:9: +1:10
_1 = const 0_i32; // scope 0 at $DIR/bad_op_mod_by_zero.rs:+1:13: +1:14
StorageLive(_2); // scope 1 at $DIR/bad_op_mod_by_zero.rs:+2:9: +2:11
- StorageLive(_3); // scope 1 at $DIR/bad_op_mod_by_zero.rs:+2:18: +2:19
-- _3 = _1; // scope 1 at $DIR/bad_op_mod_by_zero.rs:+2:18: +2:19
-- _4 = Eq(_3, const 0_i32); // scope 1 at $DIR/bad_op_mod_by_zero.rs:+2:14: +2:19
+- _4 = Eq(_1, const 0_i32); // scope 1 at $DIR/bad_op_mod_by_zero.rs:+2:14: +2:19
- assert(!move _4, "attempt to calculate the remainder of `{}` with a divisor of zero", const 1_i32) -> bb1; // scope 1 at $DIR/bad_op_mod_by_zero.rs:+2:14: +2:19
-+ _3 = const 0_i32; // scope 1 at $DIR/bad_op_mod_by_zero.rs:+2:18: +2:19
+ _4 = const true; // scope 1 at $DIR/bad_op_mod_by_zero.rs:+2:14: +2:19
+ assert(!const true, "attempt to calculate the remainder of `{}` with a divisor of zero", const 1_i32) -> bb1; // scope 1 at $DIR/bad_op_mod_by_zero.rs:+2:14: +2:19
}
bb1: {
-- _5 = Eq(_3, const -1_i32); // scope 1 at $DIR/bad_op_mod_by_zero.rs:+2:14: +2:19
+ _5 = Eq(_1, const -1_i32); // scope 1 at $DIR/bad_op_mod_by_zero.rs:+2:14: +2:19
- _6 = Eq(const 1_i32, const i32::MIN); // scope 1 at $DIR/bad_op_mod_by_zero.rs:+2:14: +2:19
- _7 = BitAnd(move _5, move _6); // scope 1 at $DIR/bad_op_mod_by_zero.rs:+2:14: +2:19
-- assert(!move _7, "attempt to compute the remainder of `{} % {}`, which would overflow", const 1_i32, _3) -> bb2; // scope 1 at $DIR/bad_op_mod_by_zero.rs:+2:14: +2:19
-+ _5 = const false; // scope 1 at $DIR/bad_op_mod_by_zero.rs:+2:14: +2:19
+- assert(!move _7, "attempt to compute the remainder of `{} % {}`, which would overflow", const 1_i32, _1) -> bb2; // scope 1 at $DIR/bad_op_mod_by_zero.rs:+2:14: +2:19
+ _6 = const false; // scope 1 at $DIR/bad_op_mod_by_zero.rs:+2:14: +2:19
+ _7 = const false; // scope 1 at $DIR/bad_op_mod_by_zero.rs:+2:14: +2:19
-+ assert(!const false, "attempt to compute the remainder of `{} % {}`, which would overflow", const 1_i32, const 0_i32) -> bb2; // scope 1 at $DIR/bad_op_mod_by_zero.rs:+2:14: +2:19
++ assert(!const false, "attempt to compute the remainder of `{} % {}`, which would overflow", const 1_i32, _1) -> bb2; // scope 1 at $DIR/bad_op_mod_by_zero.rs:+2:14: +2:19
}
bb2: {
-- _2 = Rem(const 1_i32, move _3); // scope 1 at $DIR/bad_op_mod_by_zero.rs:+2:14: +2:19
-+ _2 = Rem(const 1_i32, const 0_i32); // scope 1 at $DIR/bad_op_mod_by_zero.rs:+2:14: +2:19
- StorageDead(_3); // scope 1 at $DIR/bad_op_mod_by_zero.rs:+2:18: +2:19
+ _2 = Rem(const 1_i32, _1); // scope 1 at $DIR/bad_op_mod_by_zero.rs:+2:14: +2:19
StorageDead(_2); // scope 1 at $DIR/bad_op_mod_by_zero.rs:+3:1: +3:2
- StorageDead(_1); // scope 0 at $DIR/bad_op_mod_by_zero.rs:+3:1: +3:2
return; // scope 0 at $DIR/bad_op_mod_by_zero.rs:+3:2: +3:2
}
}
diff --git a/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.ConstProp.32bit.diff b/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.ConstProp.32bit.diff
index 27e41d486..38d402b8f 100644
--- a/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.ConstProp.32bit.diff
+++ b/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.ConstProp.32bit.diff
@@ -23,24 +23,21 @@
bb0: {
StorageLive(_1); // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+1:9: +1:10
StorageLive(_2); // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+1:25: +1:35
- StorageLive(_3); // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+1:25: +1:35
_8 = const _; // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+1:25: +1:35
// mir::Constant
// + span: $DIR/bad_op_unsafe_oob_for_slices.rs:5:25: 5:35
// + literal: Const { ty: &[i32; 3], val: Unevaluated(main, [], Some(promoted[0])) }
- _3 = _8; // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+1:25: +1:35
- _2 = &raw const (*_3); // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+1:25: +1:35
+ _2 = &raw const (*_8); // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+1:25: +1:35
_1 = move _2 as *const [i32] (Pointer(Unsize)); // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+1:25: +1:35
StorageDead(_2); // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+1:34: +1:35
- StorageDead(_3); // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+1:35: +1:36
StorageLive(_4); // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:13: +3:15
StorageLive(_5); // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:23: +3:24
_5 = const 3_usize; // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:23: +3:24
- _6 = Len((*_1)); // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:18: +3:25
+ _6 = const 3_usize; // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:18: +3:25
- _7 = Lt(_5, _6); // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:18: +3:25
- assert(move _7, "index out of bounds: the length is {} but the index is {}", move _6, _5) -> bb1; // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:18: +3:25
-+ _7 = Lt(const 3_usize, _6); // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:18: +3:25
-+ assert(move _7, "index out of bounds: the length is {} but the index is {}", move _6, const 3_usize) -> bb1; // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:18: +3:25
++ _7 = const false; // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:18: +3:25
++ assert(const false, "index out of bounds: the length is {} but the index is {}", const 3_usize, const 3_usize) -> bb1; // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:18: +3:25
}
bb1: {
diff --git a/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.ConstProp.64bit.diff b/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.ConstProp.64bit.diff
index 27e41d486..38d402b8f 100644
--- a/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.ConstProp.64bit.diff
+++ b/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.ConstProp.64bit.diff
@@ -23,24 +23,21 @@
bb0: {
StorageLive(_1); // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+1:9: +1:10
StorageLive(_2); // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+1:25: +1:35
- StorageLive(_3); // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+1:25: +1:35
_8 = const _; // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+1:25: +1:35
// mir::Constant
// + span: $DIR/bad_op_unsafe_oob_for_slices.rs:5:25: 5:35
// + literal: Const { ty: &[i32; 3], val: Unevaluated(main, [], Some(promoted[0])) }
- _3 = _8; // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+1:25: +1:35
- _2 = &raw const (*_3); // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+1:25: +1:35
+ _2 = &raw const (*_8); // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+1:25: +1:35
_1 = move _2 as *const [i32] (Pointer(Unsize)); // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+1:25: +1:35
StorageDead(_2); // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+1:34: +1:35
- StorageDead(_3); // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+1:35: +1:36
StorageLive(_4); // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:13: +3:15
StorageLive(_5); // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:23: +3:24
_5 = const 3_usize; // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:23: +3:24
- _6 = Len((*_1)); // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:18: +3:25
+ _6 = const 3_usize; // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:18: +3:25
- _7 = Lt(_5, _6); // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:18: +3:25
- assert(move _7, "index out of bounds: the length is {} but the index is {}", move _6, _5) -> bb1; // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:18: +3:25
-+ _7 = Lt(const 3_usize, _6); // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:18: +3:25
-+ assert(move _7, "index out of bounds: the length is {} but the index is {}", move _6, const 3_usize) -> bb1; // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:18: +3:25
++ _7 = const false; // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:18: +3:25
++ assert(const false, "index out of bounds: the length is {} but the index is {}", const 3_usize, const 3_usize) -> bb1; // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:18: +3:25
}
bb1: {
diff --git a/tests/mir-opt/const_prop/boolean_identities.test.ConstProp.diff b/tests/mir-opt/const_prop/boolean_identities.test.ConstProp.diff
index 0de800917..549b4711e 100644
--- a/tests/mir-opt/const_prop/boolean_identities.test.ConstProp.diff
+++ b/tests/mir-opt/const_prop/boolean_identities.test.ConstProp.diff
@@ -12,18 +12,12 @@
bb0: {
StorageLive(_3); // scope 0 at $DIR/boolean_identities.rs:+1:5: +1:15
- StorageLive(_4); // scope 0 at $DIR/boolean_identities.rs:+1:6: +1:7
- _4 = _2; // scope 0 at $DIR/boolean_identities.rs:+1:6: +1:7
-- _3 = BitOr(move _4, const true); // scope 0 at $DIR/boolean_identities.rs:+1:5: +1:15
+- _3 = BitOr(_2, const true); // scope 0 at $DIR/boolean_identities.rs:+1:5: +1:15
+ _3 = const true; // scope 0 at $DIR/boolean_identities.rs:+1:5: +1:15
- StorageDead(_4); // scope 0 at $DIR/boolean_identities.rs:+1:14: +1:15
StorageLive(_5); // scope 0 at $DIR/boolean_identities.rs:+1:18: +1:29
- StorageLive(_6); // scope 0 at $DIR/boolean_identities.rs:+1:19: +1:20
- _6 = _1; // scope 0 at $DIR/boolean_identities.rs:+1:19: +1:20
-- _5 = BitAnd(move _6, const false); // scope 0 at $DIR/boolean_identities.rs:+1:18: +1:29
-+ _5 = const false; // scope 0 at $DIR/boolean_identities.rs:+1:18: +1:29
- StorageDead(_6); // scope 0 at $DIR/boolean_identities.rs:+1:28: +1:29
+- _5 = BitAnd(_1, const false); // scope 0 at $DIR/boolean_identities.rs:+1:18: +1:29
- _0 = BitAnd(move _3, move _5); // scope 0 at $DIR/boolean_identities.rs:+1:5: +1:29
++ _5 = const false; // scope 0 at $DIR/boolean_identities.rs:+1:18: +1:29
+ _0 = const false; // scope 0 at $DIR/boolean_identities.rs:+1:5: +1:29
StorageDead(_5); // scope 0 at $DIR/boolean_identities.rs:+1:28: +1:29
StorageDead(_3); // scope 0 at $DIR/boolean_identities.rs:+1:28: +1:29
diff --git a/tests/mir-opt/const_prop/discriminant.main.ConstProp.32bit.diff b/tests/mir-opt/const_prop/discriminant.main.ConstProp.32bit.diff
index b4dccecc6..b9a10704b 100644
--- a/tests/mir-opt/const_prop/discriminant.main.ConstProp.32bit.diff
+++ b/tests/mir-opt/const_prop/discriminant.main.ConstProp.32bit.diff
@@ -17,17 +17,20 @@
StorageLive(_1); // scope 0 at $DIR/discriminant.rs:+1:9: +1:10
StorageLive(_2); // scope 0 at $DIR/discriminant.rs:+1:13: +1:64
StorageLive(_3); // scope 2 at $DIR/discriminant.rs:+1:34: +1:44
- Deinit(_3); // scope 2 at $DIR/discriminant.rs:+1:34: +1:44
- ((_3 as Some).0: bool) = const true; // scope 2 at $DIR/discriminant.rs:+1:34: +1:44
- discriminant(_3) = 1; // scope 2 at $DIR/discriminant.rs:+1:34: +1:44
+- _3 = Option::<bool>::Some(const true); // scope 2 at $DIR/discriminant.rs:+1:34: +1:44
- _4 = discriminant(_3); // scope 2 at $DIR/discriminant.rs:+1:21: +1:31
- switchInt(move _4) -> [1: bb1, otherwise: bb3]; // scope 2 at $DIR/discriminant.rs:+1:21: +1:31
++ _3 = const Option::<bool>::Some(true); // scope 2 at $DIR/discriminant.rs:+1:34: +1:44
++ // mir::Constant
++ // + span: $DIR/discriminant.rs:12:34: 12:44
++ // + literal: Const { ty: Option<bool>, val: Value(Scalar(0x01)) }
+ _4 = const 1_isize; // scope 2 at $DIR/discriminant.rs:+1:21: +1:31
+ switchInt(const 1_isize) -> [1: bb1, otherwise: bb3]; // scope 2 at $DIR/discriminant.rs:+1:21: +1:31
}
bb1: {
- switchInt(((_3 as Some).0: bool)) -> [0: bb3, otherwise: bb2]; // scope 2 at $DIR/discriminant.rs:+1:21: +1:31
+- switchInt(((_3 as Some).0: bool)) -> [0: bb3, otherwise: bb2]; // scope 2 at $DIR/discriminant.rs:+1:21: +1:31
++ switchInt(const true) -> [0: bb3, otherwise: bb2]; // scope 2 at $DIR/discriminant.rs:+1:21: +1:31
}
bb2: {
diff --git a/tests/mir-opt/const_prop/discriminant.main.ConstProp.64bit.diff b/tests/mir-opt/const_prop/discriminant.main.ConstProp.64bit.diff
index b4dccecc6..b9a10704b 100644
--- a/tests/mir-opt/const_prop/discriminant.main.ConstProp.64bit.diff
+++ b/tests/mir-opt/const_prop/discriminant.main.ConstProp.64bit.diff
@@ -17,17 +17,20 @@
StorageLive(_1); // scope 0 at $DIR/discriminant.rs:+1:9: +1:10
StorageLive(_2); // scope 0 at $DIR/discriminant.rs:+1:13: +1:64
StorageLive(_3); // scope 2 at $DIR/discriminant.rs:+1:34: +1:44
- Deinit(_3); // scope 2 at $DIR/discriminant.rs:+1:34: +1:44
- ((_3 as Some).0: bool) = const true; // scope 2 at $DIR/discriminant.rs:+1:34: +1:44
- discriminant(_3) = 1; // scope 2 at $DIR/discriminant.rs:+1:34: +1:44
+- _3 = Option::<bool>::Some(const true); // scope 2 at $DIR/discriminant.rs:+1:34: +1:44
- _4 = discriminant(_3); // scope 2 at $DIR/discriminant.rs:+1:21: +1:31
- switchInt(move _4) -> [1: bb1, otherwise: bb3]; // scope 2 at $DIR/discriminant.rs:+1:21: +1:31
++ _3 = const Option::<bool>::Some(true); // scope 2 at $DIR/discriminant.rs:+1:34: +1:44
++ // mir::Constant
++ // + span: $DIR/discriminant.rs:12:34: 12:44
++ // + literal: Const { ty: Option<bool>, val: Value(Scalar(0x01)) }
+ _4 = const 1_isize; // scope 2 at $DIR/discriminant.rs:+1:21: +1:31
+ switchInt(const 1_isize) -> [1: bb1, otherwise: bb3]; // scope 2 at $DIR/discriminant.rs:+1:21: +1:31
}
bb1: {
- switchInt(((_3 as Some).0: bool)) -> [0: bb3, otherwise: bb2]; // scope 2 at $DIR/discriminant.rs:+1:21: +1:31
+- switchInt(((_3 as Some).0: bool)) -> [0: bb3, otherwise: bb2]; // scope 2 at $DIR/discriminant.rs:+1:21: +1:31
++ switchInt(const true) -> [0: bb3, otherwise: bb2]; // scope 2 at $DIR/discriminant.rs:+1:21: +1:31
}
bb2: {
diff --git a/tests/mir-opt/const_prop/inherit_overflow.main.ConstProp.diff b/tests/mir-opt/const_prop/inherit_overflow.main.ConstProp.diff
new file mode 100644
index 000000000..d03c23a3f
--- /dev/null
+++ b/tests/mir-opt/const_prop/inherit_overflow.main.ConstProp.diff
@@ -0,0 +1,39 @@
+- // MIR for `main` before ConstProp
++ // MIR for `main` after ConstProp
+
+ fn main() -> () {
+ let mut _0: (); // return place in scope 0 at $DIR/inherit_overflow.rs:+0:11: +0:11
+ let mut _1: u8; // in scope 0 at $DIR/inherit_overflow.rs:+3:13: +3:47
+ let mut _2: u8; // in scope 0 at $DIR/inherit_overflow.rs:+3:13: +3:47
+ let mut _3: u8; // in scope 0 at $DIR/inherit_overflow.rs:+3:13: +3:47
+ scope 1 {
+ }
+ scope 2 (inlined <u8 as Add>::add) { // at $DIR/inherit_overflow.rs:8:13: 8:47
+ debug self => _2; // in scope 2 at $SRC_DIR/core/src/ops/arith.rs:LL:COL
+ debug other => _3; // in scope 2 at $SRC_DIR/core/src/ops/arith.rs:LL:COL
+ let mut _4: (u8, bool); // in scope 2 at $SRC_DIR/core/src/ops/arith.rs:LL:COL
+ }
+
+ bb0: {
+ StorageLive(_1); // scope 0 at $DIR/inherit_overflow.rs:+3:13: +3:47
+ StorageLive(_2); // scope 0 at $DIR/inherit_overflow.rs:+3:13: +3:47
+ _2 = const u8::MAX; // scope 0 at $DIR/inherit_overflow.rs:+3:13: +3:47
+ StorageLive(_3); // scope 0 at $DIR/inherit_overflow.rs:+3:13: +3:47
+ _3 = const 1_u8; // scope 0 at $DIR/inherit_overflow.rs:+3:13: +3:47
+- _4 = CheckedAdd(_2, _3); // scope 2 at $SRC_DIR/core/src/ops/arith.rs:LL:COL
+- assert(!move (_4.1: bool), "attempt to compute `{} + {}`, which would overflow", _2, _3) -> bb1; // scope 2 at $SRC_DIR/core/src/ops/arith.rs:LL:COL
++ _4 = const (0_u8, true); // scope 2 at $SRC_DIR/core/src/ops/arith.rs:LL:COL
++ assert(!const true, "attempt to compute `{} + {}`, which would overflow", _2, _3) -> bb1; // scope 2 at $SRC_DIR/core/src/ops/arith.rs:LL:COL
+ }
+
+ bb1: {
+- _1 = move (_4.0: u8); // scope 2 at $SRC_DIR/core/src/ops/arith.rs:LL:COL
++ _1 = const 0_u8; // scope 2 at $SRC_DIR/core/src/ops/arith.rs:LL:COL
+ StorageDead(_3); // scope 0 at $DIR/inherit_overflow.rs:+3:13: +3:47
+ StorageDead(_2); // scope 0 at $DIR/inherit_overflow.rs:+3:13: +3:47
+ StorageDead(_1); // scope 0 at $DIR/inherit_overflow.rs:+3:47: +3:48
+ _0 = const (); // scope 0 at $DIR/inherit_overflow.rs:+0:11: +4:2
+ return; // scope 0 at $DIR/inherit_overflow.rs:+4:2: +4:2
+ }
+ }
+
diff --git a/tests/mir-opt/const_prop/inherit_overflow.rs b/tests/mir-opt/const_prop/inherit_overflow.rs
new file mode 100644
index 000000000..541a8c5c3
--- /dev/null
+++ b/tests/mir-opt/const_prop/inherit_overflow.rs
@@ -0,0 +1,9 @@
+// unit-test: ConstProp
+// compile-flags: -Zmir-enable-passes=+Inline
+
+// EMIT_MIR inherit_overflow.main.ConstProp.diff
+fn main() {
+ // After inlining, this will contain a `CheckedBinaryOp`.
+ // Propagating the overflow is ok as codegen will just skip emitting the panic.
+ let _ = <u8 as std::ops::Add>::add(255, 1);
+}
diff --git a/tests/mir-opt/const_prop/invalid_constant.main.ConstProp.diff b/tests/mir-opt/const_prop/invalid_constant.main.ConstProp.diff
index 6c4757c1a..4f056dd85 100644
--- a/tests/mir-opt/const_prop/invalid_constant.main.ConstProp.diff
+++ b/tests/mir-opt/const_prop/invalid_constant.main.ConstProp.diff
@@ -32,16 +32,14 @@
bb0: {
StorageLive(_1); // scope 0 at $DIR/invalid_constant.rs:+6:9: +6:22
StorageLive(_2); // scope 2 at $DIR/invalid_constant.rs:+6:34: +6:63
- Deinit(_2); // scope 2 at $DIR/invalid_constant.rs:+6:34: +6:63
- (_2.0: u32) = const 1114113_u32; // scope 2 at $DIR/invalid_constant.rs:+6:34: +6:63
+ _2 = InvalidChar { int: const 1114113_u32 }; // scope 2 at $DIR/invalid_constant.rs:+6:34: +6:63
- _1 = (_2.1: char); // scope 2 at $DIR/invalid_constant.rs:+6:34: +6:67
+ _1 = const {transmute(0x00110001): char}; // scope 2 at $DIR/invalid_constant.rs:+6:34: +6:67
StorageDead(_2); // scope 0 at $DIR/invalid_constant.rs:+6:69: +6:70
StorageLive(_3); // scope 1 at $DIR/invalid_constant.rs:+13:9: +13:21
StorageLive(_4); // scope 1 at $DIR/invalid_constant.rs:+13:25: +13:59
StorageLive(_5); // scope 4 at $DIR/invalid_constant.rs:+13:34: +13:55
- Deinit(_5); // scope 4 at $DIR/invalid_constant.rs:+13:34: +13:55
- (_5.0: u32) = const 4_u32; // scope 4 at $DIR/invalid_constant.rs:+13:34: +13:55
+ _5 = InvalidTag { int: const 4_u32 }; // scope 4 at $DIR/invalid_constant.rs:+13:34: +13:55
- _4 = (_5.1: E); // scope 4 at $DIR/invalid_constant.rs:+13:34: +13:57
- _3 = [move _4]; // scope 1 at $DIR/invalid_constant.rs:+13:24: +13:60
+ _4 = const Scalar(0x00000004): E; // scope 4 at $DIR/invalid_constant.rs:+13:34: +13:57
diff --git a/tests/mir-opt/const_prop/issue_66971.main.ConstProp.diff b/tests/mir-opt/const_prop/issue_66971.main.ConstProp.diff
index 488e772d0..964dd3080 100644
--- a/tests/mir-opt/const_prop/issue_66971.main.ConstProp.diff
+++ b/tests/mir-opt/const_prop/issue_66971.main.ConstProp.diff
@@ -5,13 +5,14 @@
let mut _0: (); // return place in scope 0 at $DIR/issue_66971.rs:+0:11: +0:11
let _1: (); // in scope 0 at $DIR/issue_66971.rs:+1:5: +1:23
let mut _2: ((), u8, u8); // in scope 0 at $DIR/issue_66971.rs:+1:12: +1:22
+ let mut _3: (); // in scope 0 at $DIR/issue_66971.rs:+1:13: +1:15
bb0: {
StorageLive(_1); // scope 0 at $DIR/issue_66971.rs:+1:5: +1:23
StorageLive(_2); // scope 0 at $DIR/issue_66971.rs:+1:12: +1:22
- Deinit(_2); // scope 0 at $DIR/issue_66971.rs:+1:12: +1:22
- (_2.1: u8) = const 0_u8; // scope 0 at $DIR/issue_66971.rs:+1:12: +1:22
- (_2.2: u8) = const 0_u8; // scope 0 at $DIR/issue_66971.rs:+1:12: +1:22
+ StorageLive(_3); // scope 0 at $DIR/issue_66971.rs:+1:13: +1:15
+ _2 = (move _3, const 0_u8, const 0_u8); // scope 0 at $DIR/issue_66971.rs:+1:12: +1:22
+ StorageDead(_3); // scope 0 at $DIR/issue_66971.rs:+1:21: +1:22
_1 = encode(move _2) -> bb1; // scope 0 at $DIR/issue_66971.rs:+1:5: +1:23
// mir::Constant
// + span: $DIR/issue_66971.rs:17:5: 17:11
diff --git a/tests/mir-opt/const_prop/issue_67019.main.ConstProp.diff b/tests/mir-opt/const_prop/issue_67019.main.ConstProp.diff
index cd5304859..a631cb310 100644
--- a/tests/mir-opt/const_prop/issue_67019.main.ConstProp.diff
+++ b/tests/mir-opt/const_prop/issue_67019.main.ConstProp.diff
@@ -11,12 +11,9 @@
StorageLive(_1); // scope 0 at $DIR/issue_67019.rs:+1:5: +1:20
StorageLive(_2); // scope 0 at $DIR/issue_67019.rs:+1:10: +1:19
StorageLive(_3); // scope 0 at $DIR/issue_67019.rs:+1:11: +1:17
- Deinit(_3); // scope 0 at $DIR/issue_67019.rs:+1:11: +1:17
- (_3.0: u8) = const 1_u8; // scope 0 at $DIR/issue_67019.rs:+1:11: +1:17
- (_3.1: u8) = const 2_u8; // scope 0 at $DIR/issue_67019.rs:+1:11: +1:17
- Deinit(_2); // scope 0 at $DIR/issue_67019.rs:+1:10: +1:19
-- (_2.0: (u8, u8)) = move _3; // scope 0 at $DIR/issue_67019.rs:+1:10: +1:19
-+ (_2.0: (u8, u8)) = const (1_u8, 2_u8); // scope 0 at $DIR/issue_67019.rs:+1:10: +1:19
+- _3 = (const 1_u8, const 2_u8); // scope 0 at $DIR/issue_67019.rs:+1:11: +1:17
++ _3 = const (1_u8, 2_u8); // scope 0 at $DIR/issue_67019.rs:+1:11: +1:17
+ _2 = (move _3,); // scope 0 at $DIR/issue_67019.rs:+1:10: +1:19
StorageDead(_3); // scope 0 at $DIR/issue_67019.rs:+1:18: +1:19
_1 = test(move _2) -> bb1; // scope 0 at $DIR/issue_67019.rs:+1:5: +1:20
// mir::Constant
diff --git a/tests/mir-opt/const_prop/mult_by_zero.test.ConstProp.diff b/tests/mir-opt/const_prop/mult_by_zero.test.ConstProp.diff
index 629c8e601..1cfe47d0a 100644
--- a/tests/mir-opt/const_prop/mult_by_zero.test.ConstProp.diff
+++ b/tests/mir-opt/const_prop/mult_by_zero.test.ConstProp.diff
@@ -7,11 +7,8 @@
let mut _2: i32; // in scope 0 at $DIR/mult_by_zero.rs:+1:3: +1:4
bb0: {
- StorageLive(_2); // scope 0 at $DIR/mult_by_zero.rs:+1:3: +1:4
- _2 = _1; // scope 0 at $DIR/mult_by_zero.rs:+1:3: +1:4
-- _0 = Mul(move _2, const 0_i32); // scope 0 at $DIR/mult_by_zero.rs:+1:3: +1:8
+- _0 = Mul(_1, const 0_i32); // scope 0 at $DIR/mult_by_zero.rs:+1:3: +1:8
+ _0 = const 0_i32; // scope 0 at $DIR/mult_by_zero.rs:+1:3: +1:8
- StorageDead(_2); // scope 0 at $DIR/mult_by_zero.rs:+1:7: +1:8
return; // scope 0 at $DIR/mult_by_zero.rs:+2:2: +2:2
}
}
diff --git a/tests/mir-opt/const_prop/mutable_variable_aggregate.main.ConstProp.diff b/tests/mir-opt/const_prop/mutable_variable_aggregate.main.ConstProp.diff
index f6bf52206..d088c4f66 100644
--- a/tests/mir-opt/const_prop/mutable_variable_aggregate.main.ConstProp.diff
+++ b/tests/mir-opt/const_prop/mutable_variable_aggregate.main.ConstProp.diff
@@ -3,26 +3,27 @@
fn main() -> () {
let mut _0: (); // return place in scope 0 at $DIR/mutable_variable_aggregate.rs:+0:11: +0:11
- let mut _1: (i32, i32); // in scope 0 at $DIR/mutable_variable_aggregate.rs:+1:9: +1:14
+ let mut _3: i32; // in scope 0 at $DIR/mutable_variable_aggregate.rs:+1:9: +1:14
+ let mut _4: i32; // in scope 0 at $DIR/mutable_variable_aggregate.rs:+1:9: +1:14
scope 1 {
- debug x => _1; // in scope 1 at $DIR/mutable_variable_aggregate.rs:+1:9: +1:14
- let _2: (i32, i32); // in scope 1 at $DIR/mutable_variable_aggregate.rs:+3:9: +3:10
+ debug x => (i32, i32){ .0 => _3, .1 => _4, }; // in scope 1 at $DIR/mutable_variable_aggregate.rs:+1:9: +1:14
+ let _1: i32; // in scope 1 at $DIR/mutable_variable_aggregate.rs:+3:9: +3:10
+ let _2: i32; // in scope 1 at $DIR/mutable_variable_aggregate.rs:+3:9: +3:10
scope 2 {
- debug y => _2; // in scope 2 at $DIR/mutable_variable_aggregate.rs:+3:9: +3:10
+ debug y => (i32, i32){ .0 => _3, .1 => _2, }; // in scope 2 at $DIR/mutable_variable_aggregate.rs:+3:9: +3:10
}
}
bb0: {
- StorageLive(_1); // scope 0 at $DIR/mutable_variable_aggregate.rs:+1:9: +1:14
- Deinit(_1); // scope 0 at $DIR/mutable_variable_aggregate.rs:+1:17: +1:25
- (_1.0: i32) = const 42_i32; // scope 0 at $DIR/mutable_variable_aggregate.rs:+1:17: +1:25
- (_1.1: i32) = const 43_i32; // scope 0 at $DIR/mutable_variable_aggregate.rs:+1:17: +1:25
- (_1.1: i32) = const 99_i32; // scope 1 at $DIR/mutable_variable_aggregate.rs:+2:5: +2:13
+ StorageLive(_4); // scope 0 at $DIR/mutable_variable_aggregate.rs:+1:9: +1:14
+ _3 = const 42_i32; // scope 0 at $DIR/mutable_variable_aggregate.rs:+1:17: +1:25
+ _4 = const 43_i32; // scope 0 at $DIR/mutable_variable_aggregate.rs:+1:17: +1:25
+ _4 = const 99_i32; // scope 1 at $DIR/mutable_variable_aggregate.rs:+2:5: +2:13
StorageLive(_2); // scope 1 at $DIR/mutable_variable_aggregate.rs:+3:9: +3:10
-- _2 = _1; // scope 1 at $DIR/mutable_variable_aggregate.rs:+3:13: +3:14
-+ _2 = const (42_i32, 99_i32); // scope 1 at $DIR/mutable_variable_aggregate.rs:+3:13: +3:14
+- _2 = _4; // scope 1 at $DIR/mutable_variable_aggregate.rs:+3:13: +3:14
++ _2 = const 99_i32; // scope 1 at $DIR/mutable_variable_aggregate.rs:+3:13: +3:14
StorageDead(_2); // scope 1 at $DIR/mutable_variable_aggregate.rs:+4:1: +4:2
- StorageDead(_1); // scope 0 at $DIR/mutable_variable_aggregate.rs:+4:1: +4:2
+ StorageDead(_4); // scope 0 at $DIR/mutable_variable_aggregate.rs:+4:1: +4:2
return; // scope 0 at $DIR/mutable_variable_aggregate.rs:+4:2: +4:2
}
}
diff --git a/tests/mir-opt/const_prop/mutable_variable_aggregate_mut_ref.main.ConstProp.diff b/tests/mir-opt/const_prop/mutable_variable_aggregate_mut_ref.main.ConstProp.diff
index 213a70227..134f0c080 100644
--- a/tests/mir-opt/const_prop/mutable_variable_aggregate_mut_ref.main.ConstProp.diff
+++ b/tests/mir-opt/const_prop/mutable_variable_aggregate_mut_ref.main.ConstProp.diff
@@ -9,24 +9,26 @@
let _2: &mut (i32, i32); // in scope 1 at $DIR/mutable_variable_aggregate_mut_ref.rs:+2:9: +2:10
scope 2 {
debug z => _2; // in scope 2 at $DIR/mutable_variable_aggregate_mut_ref.rs:+2:9: +2:10
- let _3: (i32, i32); // in scope 2 at $DIR/mutable_variable_aggregate_mut_ref.rs:+4:9: +4:10
+ let _3: i32; // in scope 2 at $DIR/mutable_variable_aggregate_mut_ref.rs:+4:9: +4:10
+ let _4: i32; // in scope 2 at $DIR/mutable_variable_aggregate_mut_ref.rs:+4:9: +4:10
scope 3 {
- debug y => _3; // in scope 3 at $DIR/mutable_variable_aggregate_mut_ref.rs:+4:9: +4:10
+ debug y => (i32, i32){ .0 => _3, .1 => _4, }; // in scope 3 at $DIR/mutable_variable_aggregate_mut_ref.rs:+4:9: +4:10
}
}
}
bb0: {
StorageLive(_1); // scope 0 at $DIR/mutable_variable_aggregate_mut_ref.rs:+1:9: +1:14
- Deinit(_1); // scope 0 at $DIR/mutable_variable_aggregate_mut_ref.rs:+1:17: +1:25
- (_1.0: i32) = const 42_i32; // scope 0 at $DIR/mutable_variable_aggregate_mut_ref.rs:+1:17: +1:25
- (_1.1: i32) = const 43_i32; // scope 0 at $DIR/mutable_variable_aggregate_mut_ref.rs:+1:17: +1:25
+ _1 = (const 42_i32, const 43_i32); // scope 0 at $DIR/mutable_variable_aggregate_mut_ref.rs:+1:17: +1:25
StorageLive(_2); // scope 1 at $DIR/mutable_variable_aggregate_mut_ref.rs:+2:9: +2:10
_2 = &mut _1; // scope 1 at $DIR/mutable_variable_aggregate_mut_ref.rs:+2:13: +2:19
((*_2).1: i32) = const 99_i32; // scope 2 at $DIR/mutable_variable_aggregate_mut_ref.rs:+3:5: +3:13
StorageLive(_3); // scope 2 at $DIR/mutable_variable_aggregate_mut_ref.rs:+4:9: +4:10
- _3 = _1; // scope 2 at $DIR/mutable_variable_aggregate_mut_ref.rs:+4:13: +4:14
+ StorageLive(_4); // scope 2 at $DIR/mutable_variable_aggregate_mut_ref.rs:+4:9: +4:10
+ _3 = (_1.0: i32); // scope 2 at $DIR/mutable_variable_aggregate_mut_ref.rs:+4:13: +4:14
+ _4 = (_1.1: i32); // scope 2 at $DIR/mutable_variable_aggregate_mut_ref.rs:+4:13: +4:14
StorageDead(_3); // scope 2 at $DIR/mutable_variable_aggregate_mut_ref.rs:+5:1: +5:2
+ StorageDead(_4); // scope 2 at $DIR/mutable_variable_aggregate_mut_ref.rs:+5:1: +5:2
StorageDead(_2); // scope 1 at $DIR/mutable_variable_aggregate_mut_ref.rs:+5:1: +5:2
StorageDead(_1); // scope 0 at $DIR/mutable_variable_aggregate_mut_ref.rs:+5:1: +5:2
return; // scope 0 at $DIR/mutable_variable_aggregate_mut_ref.rs:+5:2: +5:2
diff --git a/tests/mir-opt/const_prop/mutable_variable_unprop_assign.main.ConstProp.diff b/tests/mir-opt/const_prop/mutable_variable_unprop_assign.main.ConstProp.diff
index c3f77b960..4010dd6c6 100644
--- a/tests/mir-opt/const_prop/mutable_variable_unprop_assign.main.ConstProp.diff
+++ b/tests/mir-opt/const_prop/mutable_variable_unprop_assign.main.ConstProp.diff
@@ -16,7 +16,7 @@
debug y => _3; // in scope 3 at $DIR/mutable_variable_unprop_assign.rs:+4:9: +4:10
let _4: i32; // in scope 3 at $DIR/mutable_variable_unprop_assign.rs:+5:9: +5:10
scope 4 {
- debug z => _4; // in scope 4 at $DIR/mutable_variable_unprop_assign.rs:+5:9: +5:10
+ debug z => _5; // in scope 4 at $DIR/mutable_variable_unprop_assign.rs:+5:9: +5:10
}
}
}
@@ -31,10 +31,7 @@
}
bb1: {
- StorageLive(_5); // scope 1 at $DIR/mutable_variable_unprop_assign.rs:+2:9: +2:14
StorageLive(_6); // scope 1 at $DIR/mutable_variable_unprop_assign.rs:+2:9: +2:14
- Deinit(_5); // scope 1 at $DIR/mutable_variable_unprop_assign.rs:+2:29: +2:35
- Deinit(_6); // scope 1 at $DIR/mutable_variable_unprop_assign.rs:+2:29: +2:35
_5 = const 1_i32; // scope 1 at $DIR/mutable_variable_unprop_assign.rs:+2:29: +2:35
_6 = const 2_i32; // scope 1 at $DIR/mutable_variable_unprop_assign.rs:+2:29: +2:35
StorageLive(_2); // scope 2 at $DIR/mutable_variable_unprop_assign.rs:+3:11: +3:12
@@ -43,12 +40,7 @@
StorageDead(_2); // scope 2 at $DIR/mutable_variable_unprop_assign.rs:+3:11: +3:12
StorageLive(_3); // scope 2 at $DIR/mutable_variable_unprop_assign.rs:+4:9: +4:10
_3 = _6; // scope 2 at $DIR/mutable_variable_unprop_assign.rs:+4:13: +4:16
- StorageLive(_4); // scope 3 at $DIR/mutable_variable_unprop_assign.rs:+5:9: +5:10
-- _4 = _5; // scope 3 at $DIR/mutable_variable_unprop_assign.rs:+5:13: +5:16
-+ _4 = const 1_i32; // scope 3 at $DIR/mutable_variable_unprop_assign.rs:+5:13: +5:16
- StorageDead(_4); // scope 3 at $DIR/mutable_variable_unprop_assign.rs:+6:1: +6:2
StorageDead(_3); // scope 2 at $DIR/mutable_variable_unprop_assign.rs:+6:1: +6:2
- StorageDead(_5); // scope 1 at $DIR/mutable_variable_unprop_assign.rs:+6:1: +6:2
StorageDead(_6); // scope 1 at $DIR/mutable_variable_unprop_assign.rs:+6:1: +6:2
StorageDead(_1); // scope 0 at $DIR/mutable_variable_unprop_assign.rs:+6:1: +6:2
return; // scope 0 at $DIR/mutable_variable_unprop_assign.rs:+6:2: +6:2
diff --git a/tests/mir-opt/const_prop/optimizes_into_variable.main.ConstProp.32bit.diff b/tests/mir-opt/const_prop/optimizes_into_variable.main.ConstProp.32bit.diff
index 7c7aeac4c..691aa01a5 100644
--- a/tests/mir-opt/const_prop/optimizes_into_variable.main.ConstProp.32bit.diff
+++ b/tests/mir-opt/const_prop/optimizes_into_variable.main.ConstProp.32bit.diff
@@ -17,7 +17,7 @@
debug y => _3; // in scope 2 at $DIR/optimizes_into_variable.rs:+2:9: +2:10
let _8: u32; // in scope 2 at $DIR/optimizes_into_variable.rs:+3:9: +3:10
scope 3 {
- debug z => _8; // in scope 3 at $DIR/optimizes_into_variable.rs:+3:9: +3:10
+ debug z => _9; // in scope 3 at $DIR/optimizes_into_variable.rs:+3:9: +3:10
}
}
}
@@ -50,14 +50,7 @@
+ _3 = const 3_i32; // scope 1 at $DIR/optimizes_into_variable.rs:+2:13: +2:34
StorageDead(_5); // scope 1 at $DIR/optimizes_into_variable.rs:+2:34: +2:35
StorageDead(_4); // scope 1 at $DIR/optimizes_into_variable.rs:+2:34: +2:35
- StorageLive(_8); // scope 2 at $DIR/optimizes_into_variable.rs:+3:9: +3:10
- StorageLive(_9); // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:36
- Deinit(_9); // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:36
_9 = const 42_u32; // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:36
-- _8 = _9; // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:38
-+ _8 = const 42_u32; // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:38
- StorageDead(_9); // scope 2 at $DIR/optimizes_into_variable.rs:+3:38: +3:39
- StorageDead(_8); // scope 2 at $DIR/optimizes_into_variable.rs:+4:1: +4:2
StorageDead(_3); // scope 1 at $DIR/optimizes_into_variable.rs:+4:1: +4:2
StorageDead(_1); // scope 0 at $DIR/optimizes_into_variable.rs:+4:1: +4:2
return; // scope 0 at $DIR/optimizes_into_variable.rs:+4:2: +4:2
diff --git a/tests/mir-opt/const_prop/optimizes_into_variable.main.ConstProp.64bit.diff b/tests/mir-opt/const_prop/optimizes_into_variable.main.ConstProp.64bit.diff
index 7c7aeac4c..691aa01a5 100644
--- a/tests/mir-opt/const_prop/optimizes_into_variable.main.ConstProp.64bit.diff
+++ b/tests/mir-opt/const_prop/optimizes_into_variable.main.ConstProp.64bit.diff
@@ -17,7 +17,7 @@
debug y => _3; // in scope 2 at $DIR/optimizes_into_variable.rs:+2:9: +2:10
let _8: u32; // in scope 2 at $DIR/optimizes_into_variable.rs:+3:9: +3:10
scope 3 {
- debug z => _8; // in scope 3 at $DIR/optimizes_into_variable.rs:+3:9: +3:10
+ debug z => _9; // in scope 3 at $DIR/optimizes_into_variable.rs:+3:9: +3:10
}
}
}
@@ -50,14 +50,7 @@
+ _3 = const 3_i32; // scope 1 at $DIR/optimizes_into_variable.rs:+2:13: +2:34
StorageDead(_5); // scope 1 at $DIR/optimizes_into_variable.rs:+2:34: +2:35
StorageDead(_4); // scope 1 at $DIR/optimizes_into_variable.rs:+2:34: +2:35
- StorageLive(_8); // scope 2 at $DIR/optimizes_into_variable.rs:+3:9: +3:10
- StorageLive(_9); // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:36
- Deinit(_9); // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:36
_9 = const 42_u32; // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:36
-- _8 = _9; // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:38
-+ _8 = const 42_u32; // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:38
- StorageDead(_9); // scope 2 at $DIR/optimizes_into_variable.rs:+3:38: +3:39
- StorageDead(_8); // scope 2 at $DIR/optimizes_into_variable.rs:+4:1: +4:2
StorageDead(_3); // scope 1 at $DIR/optimizes_into_variable.rs:+4:1: +4:2
StorageDead(_1); // scope 0 at $DIR/optimizes_into_variable.rs:+4:1: +4:2
return; // scope 0 at $DIR/optimizes_into_variable.rs:+4:2: +4:2
diff --git a/tests/mir-opt/const_prop/optimizes_into_variable.main.PreCodegen.after.32bit.mir b/tests/mir-opt/const_prop/optimizes_into_variable.main.PreCodegen.after.32bit.mir
index 9db87cfc8..81cfd22db 100644
--- a/tests/mir-opt/const_prop/optimizes_into_variable.main.PreCodegen.after.32bit.mir
+++ b/tests/mir-opt/const_prop/optimizes_into_variable.main.PreCodegen.after.32bit.mir
@@ -3,12 +3,12 @@
fn main() -> () {
let mut _0: (); // return place in scope 0 at $DIR/optimizes_into_variable.rs:+0:11: +0:11
let _1: i32; // in scope 0 at $DIR/optimizes_into_variable.rs:+1:9: +1:10
+ let mut _3: u32; // in scope 0 at $DIR/optimizes_into_variable.rs:+3:13: +3:36
scope 1 {
debug x => _1; // in scope 1 at $DIR/optimizes_into_variable.rs:+1:9: +1:10
let _2: i32; // in scope 1 at $DIR/optimizes_into_variable.rs:+2:9: +2:10
scope 2 {
debug y => _2; // in scope 2 at $DIR/optimizes_into_variable.rs:+2:9: +2:10
- let _3: u32; // in scope 2 at $DIR/optimizes_into_variable.rs:+3:9: +3:10
scope 3 {
debug z => _3; // in scope 3 at $DIR/optimizes_into_variable.rs:+3:9: +3:10
}
@@ -18,8 +18,6 @@ fn main() -> () {
bb0: {
StorageLive(_1); // scope 0 at $DIR/optimizes_into_variable.rs:+1:9: +1:10
StorageLive(_2); // scope 1 at $DIR/optimizes_into_variable.rs:+2:9: +2:10
- StorageLive(_3); // scope 2 at $DIR/optimizes_into_variable.rs:+3:9: +3:10
- StorageDead(_3); // scope 2 at $DIR/optimizes_into_variable.rs:+4:1: +4:2
StorageDead(_2); // scope 1 at $DIR/optimizes_into_variable.rs:+4:1: +4:2
StorageDead(_1); // scope 0 at $DIR/optimizes_into_variable.rs:+4:1: +4:2
return; // scope 0 at $DIR/optimizes_into_variable.rs:+4:2: +4:2
diff --git a/tests/mir-opt/const_prop/optimizes_into_variable.main.PreCodegen.after.64bit.mir b/tests/mir-opt/const_prop/optimizes_into_variable.main.PreCodegen.after.64bit.mir
index 9db87cfc8..81cfd22db 100644
--- a/tests/mir-opt/const_prop/optimizes_into_variable.main.PreCodegen.after.64bit.mir
+++ b/tests/mir-opt/const_prop/optimizes_into_variable.main.PreCodegen.after.64bit.mir
@@ -3,12 +3,12 @@
fn main() -> () {
let mut _0: (); // return place in scope 0 at $DIR/optimizes_into_variable.rs:+0:11: +0:11
let _1: i32; // in scope 0 at $DIR/optimizes_into_variable.rs:+1:9: +1:10
+ let mut _3: u32; // in scope 0 at $DIR/optimizes_into_variable.rs:+3:13: +3:36
scope 1 {
debug x => _1; // in scope 1 at $DIR/optimizes_into_variable.rs:+1:9: +1:10
let _2: i32; // in scope 1 at $DIR/optimizes_into_variable.rs:+2:9: +2:10
scope 2 {
debug y => _2; // in scope 2 at $DIR/optimizes_into_variable.rs:+2:9: +2:10
- let _3: u32; // in scope 2 at $DIR/optimizes_into_variable.rs:+3:9: +3:10
scope 3 {
debug z => _3; // in scope 3 at $DIR/optimizes_into_variable.rs:+3:9: +3:10
}
@@ -18,8 +18,6 @@ fn main() -> () {
bb0: {
StorageLive(_1); // scope 0 at $DIR/optimizes_into_variable.rs:+1:9: +1:10
StorageLive(_2); // scope 1 at $DIR/optimizes_into_variable.rs:+2:9: +2:10
- StorageLive(_3); // scope 2 at $DIR/optimizes_into_variable.rs:+3:9: +3:10
- StorageDead(_3); // scope 2 at $DIR/optimizes_into_variable.rs:+4:1: +4:2
StorageDead(_2); // scope 1 at $DIR/optimizes_into_variable.rs:+4:1: +4:2
StorageDead(_1); // scope 0 at $DIR/optimizes_into_variable.rs:+4:1: +4:2
return; // scope 0 at $DIR/optimizes_into_variable.rs:+4:2: +4:2
diff --git a/tests/mir-opt/const_prop/optimizes_into_variable.main.ScalarReplacementOfAggregates.32bit.diff b/tests/mir-opt/const_prop/optimizes_into_variable.main.ScalarReplacementOfAggregates.32bit.diff
index 3f9f3b2ea..98cd020da 100644
--- a/tests/mir-opt/const_prop/optimizes_into_variable.main.ScalarReplacementOfAggregates.32bit.diff
+++ b/tests/mir-opt/const_prop/optimizes_into_variable.main.ScalarReplacementOfAggregates.32bit.diff
@@ -48,20 +48,19 @@
StorageDead(_4); // scope 1 at $DIR/optimizes_into_variable.rs:+2:34: +2:35
StorageLive(_8); // scope 2 at $DIR/optimizes_into_variable.rs:+3:9: +3:10
- StorageLive(_9); // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:36
-- Deinit(_9); // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:36
-- (_9.0: u32) = const 12_u32; // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:36
-- (_9.1: u32) = const 42_u32; // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:36
+- _9 = Point { x: const 12_u32, y: const 42_u32 }; // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:36
- _8 = (_9.1: u32); // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:38
- StorageDead(_9); // scope 2 at $DIR/optimizes_into_variable.rs:+3:38: +3:39
+ StorageLive(_10); // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:36
+ StorageLive(_11); // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:36
-+ Deinit(_10); // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:36
-+ Deinit(_11); // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:36
++ nop; // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:36
+ _10 = const 12_u32; // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:36
+ _11 = const 42_u32; // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:36
++ nop; // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:36
+ _8 = _11; // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:38
+ StorageDead(_10); // scope 2 at $DIR/optimizes_into_variable.rs:+3:38: +3:39
+ StorageDead(_11); // scope 2 at $DIR/optimizes_into_variable.rs:+3:38: +3:39
++ nop; // scope 2 at $DIR/optimizes_into_variable.rs:+3:38: +3:39
nop; // scope 0 at $DIR/optimizes_into_variable.rs:+0:11: +4:2
StorageDead(_8); // scope 2 at $DIR/optimizes_into_variable.rs:+4:1: +4:2
StorageDead(_3); // scope 1 at $DIR/optimizes_into_variable.rs:+4:1: +4:2
diff --git a/tests/mir-opt/const_prop/optimizes_into_variable.main.ScalarReplacementOfAggregates.64bit.diff b/tests/mir-opt/const_prop/optimizes_into_variable.main.ScalarReplacementOfAggregates.64bit.diff
index 3f9f3b2ea..98cd020da 100644
--- a/tests/mir-opt/const_prop/optimizes_into_variable.main.ScalarReplacementOfAggregates.64bit.diff
+++ b/tests/mir-opt/const_prop/optimizes_into_variable.main.ScalarReplacementOfAggregates.64bit.diff
@@ -48,20 +48,19 @@
StorageDead(_4); // scope 1 at $DIR/optimizes_into_variable.rs:+2:34: +2:35
StorageLive(_8); // scope 2 at $DIR/optimizes_into_variable.rs:+3:9: +3:10
- StorageLive(_9); // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:36
-- Deinit(_9); // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:36
-- (_9.0: u32) = const 12_u32; // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:36
-- (_9.1: u32) = const 42_u32; // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:36
+- _9 = Point { x: const 12_u32, y: const 42_u32 }; // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:36
- _8 = (_9.1: u32); // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:38
- StorageDead(_9); // scope 2 at $DIR/optimizes_into_variable.rs:+3:38: +3:39
+ StorageLive(_10); // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:36
+ StorageLive(_11); // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:36
-+ Deinit(_10); // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:36
-+ Deinit(_11); // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:36
++ nop; // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:36
+ _10 = const 12_u32; // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:36
+ _11 = const 42_u32; // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:36
++ nop; // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:36
+ _8 = _11; // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:38
+ StorageDead(_10); // scope 2 at $DIR/optimizes_into_variable.rs:+3:38: +3:39
+ StorageDead(_11); // scope 2 at $DIR/optimizes_into_variable.rs:+3:38: +3:39
++ nop; // scope 2 at $DIR/optimizes_into_variable.rs:+3:38: +3:39
nop; // scope 0 at $DIR/optimizes_into_variable.rs:+0:11: +4:2
StorageDead(_8); // scope 2 at $DIR/optimizes_into_variable.rs:+4:1: +4:2
StorageDead(_3); // scope 1 at $DIR/optimizes_into_variable.rs:+4:1: +4:2
diff --git a/tests/mir-opt/const_prop/optimizes_into_variable.main.SimplifyLocals-final.after.32bit.mir b/tests/mir-opt/const_prop/optimizes_into_variable.main.SimplifyLocals-final.after.32bit.mir
index d926b9df7..002e914e8 100644
--- a/tests/mir-opt/const_prop/optimizes_into_variable.main.SimplifyLocals-final.after.32bit.mir
+++ b/tests/mir-opt/const_prop/optimizes_into_variable.main.SimplifyLocals-final.after.32bit.mir
@@ -3,12 +3,12 @@
fn main() -> () {
let mut _0: (); // return place in scope 0 at $DIR/optimizes_into_variable.rs:+0:11: +0:11
let _1: i32; // in scope 0 at $DIR/optimizes_into_variable.rs:+1:9: +1:10
+ let mut _3: u32; // in scope 0 at $DIR/optimizes_into_variable.rs:+3:13: +3:36
scope 1 {
debug x => _1; // in scope 1 at $DIR/optimizes_into_variable.rs:+1:9: +1:10
let _2: i32; // in scope 1 at $DIR/optimizes_into_variable.rs:+2:9: +2:10
scope 2 {
debug y => _2; // in scope 2 at $DIR/optimizes_into_variable.rs:+2:9: +2:10
- let _3: u32; // in scope 2 at $DIR/optimizes_into_variable.rs:+3:9: +3:10
scope 3 {
debug z => _3; // in scope 3 at $DIR/optimizes_into_variable.rs:+3:9: +3:10
}
@@ -18,8 +18,6 @@ fn main() -> () {
bb0: {
StorageLive(_1); // scope 0 at $DIR/optimizes_into_variable.rs:+1:9: +1:10
StorageLive(_2); // scope 1 at $DIR/optimizes_into_variable.rs:+2:9: +2:10
- StorageLive(_3); // scope 2 at $DIR/optimizes_into_variable.rs:+3:9: +3:10
- StorageDead(_3); // scope 2 at $DIR/optimizes_into_variable.rs:+4:1: +4:2
StorageDead(_2); // scope 1 at $DIR/optimizes_into_variable.rs:+4:1: +4:2
StorageDead(_1); // scope 0 at $DIR/optimizes_into_variable.rs:+4:1: +4:2
return; // scope 0 at $DIR/optimizes_into_variable.rs:+4:2: +4:2
diff --git a/tests/mir-opt/const_prop/optimizes_into_variable.main.SimplifyLocals-final.after.64bit.mir b/tests/mir-opt/const_prop/optimizes_into_variable.main.SimplifyLocals-final.after.64bit.mir
index d926b9df7..002e914e8 100644
--- a/tests/mir-opt/const_prop/optimizes_into_variable.main.SimplifyLocals-final.after.64bit.mir
+++ b/tests/mir-opt/const_prop/optimizes_into_variable.main.SimplifyLocals-final.after.64bit.mir
@@ -3,12 +3,12 @@
fn main() -> () {
let mut _0: (); // return place in scope 0 at $DIR/optimizes_into_variable.rs:+0:11: +0:11
let _1: i32; // in scope 0 at $DIR/optimizes_into_variable.rs:+1:9: +1:10
+ let mut _3: u32; // in scope 0 at $DIR/optimizes_into_variable.rs:+3:13: +3:36
scope 1 {
debug x => _1; // in scope 1 at $DIR/optimizes_into_variable.rs:+1:9: +1:10
let _2: i32; // in scope 1 at $DIR/optimizes_into_variable.rs:+2:9: +2:10
scope 2 {
debug y => _2; // in scope 2 at $DIR/optimizes_into_variable.rs:+2:9: +2:10
- let _3: u32; // in scope 2 at $DIR/optimizes_into_variable.rs:+3:9: +3:10
scope 3 {
debug z => _3; // in scope 3 at $DIR/optimizes_into_variable.rs:+3:9: +3:10
}
@@ -18,8 +18,6 @@ fn main() -> () {
bb0: {
StorageLive(_1); // scope 0 at $DIR/optimizes_into_variable.rs:+1:9: +1:10
StorageLive(_2); // scope 1 at $DIR/optimizes_into_variable.rs:+2:9: +2:10
- StorageLive(_3); // scope 2 at $DIR/optimizes_into_variable.rs:+3:9: +3:10
- StorageDead(_3); // scope 2 at $DIR/optimizes_into_variable.rs:+4:1: +4:2
StorageDead(_2); // scope 1 at $DIR/optimizes_into_variable.rs:+4:1: +4:2
StorageDead(_1); // scope 0 at $DIR/optimizes_into_variable.rs:+4:1: +4:2
return; // scope 0 at $DIR/optimizes_into_variable.rs:+4:2: +4:2
diff --git a/tests/mir-opt/const_prop/ref_deref.main.ConstProp.diff b/tests/mir-opt/const_prop/ref_deref.main.ConstProp.diff
index 8a73f0390..924a267f3 100644
--- a/tests/mir-opt/const_prop/ref_deref.main.ConstProp.diff
+++ b/tests/mir-opt/const_prop/ref_deref.main.ConstProp.diff
@@ -13,14 +13,13 @@
StorageLive(_2); // scope 0 at $DIR/ref_deref.rs:+1:6: +1:10
_4 = const _; // scope 0 at $DIR/ref_deref.rs:+1:6: +1:10
// mir::Constant
- // + span: $DIR/ref_deref.rs:6:6: 6:10
+ // + span: $DIR/ref_deref.rs:5:6: 5:10
// + literal: Const { ty: &i32, val: Unevaluated(main, [], Some(promoted[0])) }
- _2 = _4; // scope 0 at $DIR/ref_deref.rs:+1:6: +1:10
-- _1 = (*_2); // scope 0 at $DIR/ref_deref.rs:+1:5: +1:10
-+ _1 = const 4_i32; // scope 0 at $DIR/ref_deref.rs:+1:5: +1:10
+ _2 = &(*_4); // scope 0 at $DIR/ref_deref.rs:+1:6: +1:10
+ _1 = (*_2); // scope 0 at $DIR/ref_deref.rs:+1:5: +1:10
StorageDead(_2); // scope 0 at $DIR/ref_deref.rs:+1:10: +1:11
StorageDead(_1); // scope 0 at $DIR/ref_deref.rs:+1:10: +1:11
- nop; // scope 0 at $DIR/ref_deref.rs:+0:11: +2:2
+ _0 = const (); // scope 0 at $DIR/ref_deref.rs:+0:11: +2:2
return; // scope 0 at $DIR/ref_deref.rs:+2:2: +2:2
}
}
diff --git a/tests/mir-opt/const_prop/ref_deref.main.PromoteTemps.diff b/tests/mir-opt/const_prop/ref_deref.main.PromoteTemps.diff
deleted file mode 100644
index 015ec4d07..000000000
--- a/tests/mir-opt/const_prop/ref_deref.main.PromoteTemps.diff
+++ /dev/null
@@ -1,30 +0,0 @@
-- // MIR for `main` before PromoteTemps
-+ // MIR for `main` after PromoteTemps
-
- fn main() -> () {
- let mut _0: (); // return place in scope 0 at $DIR/ref_deref.rs:+0:11: +0:11
- let _1: i32; // in scope 0 at $DIR/ref_deref.rs:+1:5: +1:10
- let mut _2: &i32; // in scope 0 at $DIR/ref_deref.rs:+1:6: +1:10
- let _3: i32; // in scope 0 at $DIR/ref_deref.rs:+1:8: +1:9
-+ let mut _4: &i32; // in scope 0 at $DIR/ref_deref.rs:+1:6: +1:10
-
- bb0: {
- StorageLive(_1); // scope 0 at $DIR/ref_deref.rs:+1:5: +1:10
- StorageLive(_2); // scope 0 at $DIR/ref_deref.rs:+1:6: +1:10
-- StorageLive(_3); // scope 0 at $DIR/ref_deref.rs:+1:8: +1:9
-- _3 = const 4_i32; // scope 0 at $DIR/ref_deref.rs:+1:8: +1:9
-- _2 = &_3; // scope 0 at $DIR/ref_deref.rs:+1:6: +1:10
-+ _4 = const _; // scope 0 at $DIR/ref_deref.rs:+1:6: +1:10
-+ // mir::Constant
-+ // + span: $DIR/ref_deref.rs:6:6: 6:10
-+ // + literal: Const { ty: &i32, val: Unevaluated(main, [], Some(promoted[0])) }
-+ _2 = &(*_4); // scope 0 at $DIR/ref_deref.rs:+1:6: +1:10
- _1 = (*_2); // scope 0 at $DIR/ref_deref.rs:+1:5: +1:10
-- StorageDead(_3); // scope 0 at $DIR/ref_deref.rs:+1:10: +1:11
- StorageDead(_2); // scope 0 at $DIR/ref_deref.rs:+1:10: +1:11
- StorageDead(_1); // scope 0 at $DIR/ref_deref.rs:+1:10: +1:11
- _0 = const (); // scope 0 at $DIR/ref_deref.rs:+0:11: +2:2
- return; // scope 0 at $DIR/ref_deref.rs:+2:2: +2:2
- }
- }
-
diff --git a/tests/mir-opt/const_prop/ref_deref.rs b/tests/mir-opt/const_prop/ref_deref.rs
index d2549c8b6..76e56916a 100644
--- a/tests/mir-opt/const_prop/ref_deref.rs
+++ b/tests/mir-opt/const_prop/ref_deref.rs
@@ -1,5 +1,4 @@
-// compile-flags: -Zmir-enable-passes=-SimplifyLocals-before-const-prop
-// EMIT_MIR ref_deref.main.PromoteTemps.diff
+// unit-test: ConstProp
// EMIT_MIR ref_deref.main.ConstProp.diff
fn main() {
diff --git a/tests/mir-opt/const_prop/ref_deref_project.main.ConstProp.diff b/tests/mir-opt/const_prop/ref_deref_project.main.ConstProp.diff
index ec3d90433..59095b448 100644
--- a/tests/mir-opt/const_prop/ref_deref_project.main.ConstProp.diff
+++ b/tests/mir-opt/const_prop/ref_deref_project.main.ConstProp.diff
@@ -13,13 +13,13 @@
StorageLive(_2); // scope 0 at $DIR/ref_deref_project.rs:+1:6: +1:17
_4 = const _; // scope 0 at $DIR/ref_deref_project.rs:+1:6: +1:17
// mir::Constant
- // + span: $DIR/ref_deref_project.rs:6:6: 6:17
+ // + span: $DIR/ref_deref_project.rs:5:6: 5:17
// + literal: Const { ty: &(i32, i32), val: Unevaluated(main, [], Some(promoted[0])) }
_2 = &((*_4).1: i32); // scope 0 at $DIR/ref_deref_project.rs:+1:6: +1:17
_1 = (*_2); // scope 0 at $DIR/ref_deref_project.rs:+1:5: +1:17
StorageDead(_2); // scope 0 at $DIR/ref_deref_project.rs:+1:17: +1:18
StorageDead(_1); // scope 0 at $DIR/ref_deref_project.rs:+1:17: +1:18
- nop; // scope 0 at $DIR/ref_deref_project.rs:+0:11: +2:2
+ _0 = const (); // scope 0 at $DIR/ref_deref_project.rs:+0:11: +2:2
return; // scope 0 at $DIR/ref_deref_project.rs:+2:2: +2:2
}
}
diff --git a/tests/mir-opt/const_prop/ref_deref_project.main.PromoteTemps.diff b/tests/mir-opt/const_prop/ref_deref_project.main.PromoteTemps.diff
deleted file mode 100644
index cd0616e65..000000000
--- a/tests/mir-opt/const_prop/ref_deref_project.main.PromoteTemps.diff
+++ /dev/null
@@ -1,30 +0,0 @@
-- // MIR for `main` before PromoteTemps
-+ // MIR for `main` after PromoteTemps
-
- fn main() -> () {
- let mut _0: (); // return place in scope 0 at $DIR/ref_deref_project.rs:+0:11: +0:11
- let _1: i32; // in scope 0 at $DIR/ref_deref_project.rs:+1:5: +1:17
- let mut _2: &i32; // in scope 0 at $DIR/ref_deref_project.rs:+1:6: +1:17
- let _3: (i32, i32); // in scope 0 at $DIR/ref_deref_project.rs:+1:8: +1:14
-+ let mut _4: &(i32, i32); // in scope 0 at $DIR/ref_deref_project.rs:+1:6: +1:17
-
- bb0: {
- StorageLive(_1); // scope 0 at $DIR/ref_deref_project.rs:+1:5: +1:17
- StorageLive(_2); // scope 0 at $DIR/ref_deref_project.rs:+1:6: +1:17
-- StorageLive(_3); // scope 0 at $DIR/ref_deref_project.rs:+1:8: +1:14
-- _3 = (const 4_i32, const 5_i32); // scope 0 at $DIR/ref_deref_project.rs:+1:8: +1:14
-- _2 = &(_3.1: i32); // scope 0 at $DIR/ref_deref_project.rs:+1:6: +1:17
-+ _4 = const _; // scope 0 at $DIR/ref_deref_project.rs:+1:6: +1:17
-+ // mir::Constant
-+ // + span: $DIR/ref_deref_project.rs:6:6: 6:17
-+ // + literal: Const { ty: &(i32, i32), val: Unevaluated(main, [], Some(promoted[0])) }
-+ _2 = &((*_4).1: i32); // scope 0 at $DIR/ref_deref_project.rs:+1:6: +1:17
- _1 = (*_2); // scope 0 at $DIR/ref_deref_project.rs:+1:5: +1:17
-- StorageDead(_3); // scope 0 at $DIR/ref_deref_project.rs:+1:17: +1:18
- StorageDead(_2); // scope 0 at $DIR/ref_deref_project.rs:+1:17: +1:18
- StorageDead(_1); // scope 0 at $DIR/ref_deref_project.rs:+1:17: +1:18
- _0 = const (); // scope 0 at $DIR/ref_deref_project.rs:+0:11: +2:2
- return; // scope 0 at $DIR/ref_deref_project.rs:+2:2: +2:2
- }
- }
-
diff --git a/tests/mir-opt/const_prop/ref_deref_project.rs b/tests/mir-opt/const_prop/ref_deref_project.rs
index 2fdd4e153..04fc7f8da 100644
--- a/tests/mir-opt/const_prop/ref_deref_project.rs
+++ b/tests/mir-opt/const_prop/ref_deref_project.rs
@@ -1,5 +1,4 @@
-// compile-flags: -Zmir-enable-passes=-SimplifyLocals-before-const-prop
-// EMIT_MIR ref_deref_project.main.PromoteTemps.diff
+// unit-test: ConstProp
// EMIT_MIR ref_deref_project.main.ConstProp.diff
fn main() {
diff --git a/tests/mir-opt/const_prop/scalar_literal_propagation.main.ConstProp.diff b/tests/mir-opt/const_prop/scalar_literal_propagation.main.ConstProp.diff
index d518eff04..22f710387 100644
--- a/tests/mir-opt/const_prop/scalar_literal_propagation.main.ConstProp.diff
+++ b/tests/mir-opt/const_prop/scalar_literal_propagation.main.ConstProp.diff
@@ -11,13 +11,9 @@
}
bb0: {
- StorageLive(_1); // scope 0 at $DIR/scalar_literal_propagation.rs:+1:9: +1:10
_1 = const 1_u32; // scope 0 at $DIR/scalar_literal_propagation.rs:+1:13: +1:14
StorageLive(_2); // scope 1 at $DIR/scalar_literal_propagation.rs:+2:5: +2:15
- StorageLive(_3); // scope 1 at $DIR/scalar_literal_propagation.rs:+2:13: +2:14
-- _3 = _1; // scope 1 at $DIR/scalar_literal_propagation.rs:+2:13: +2:14
-- _2 = consume(move _3) -> bb1; // scope 1 at $DIR/scalar_literal_propagation.rs:+2:5: +2:15
-+ _3 = const 1_u32; // scope 1 at $DIR/scalar_literal_propagation.rs:+2:13: +2:14
+- _2 = consume(_1) -> bb1; // scope 1 at $DIR/scalar_literal_propagation.rs:+2:5: +2:15
+ _2 = consume(const 1_u32) -> bb1; // scope 1 at $DIR/scalar_literal_propagation.rs:+2:5: +2:15
// mir::Constant
// + span: $DIR/scalar_literal_propagation.rs:4:5: 4:12
@@ -25,9 +21,7 @@
}
bb1: {
- StorageDead(_3); // scope 1 at $DIR/scalar_literal_propagation.rs:+2:14: +2:15
StorageDead(_2); // scope 1 at $DIR/scalar_literal_propagation.rs:+2:15: +2:16
- StorageDead(_1); // scope 0 at $DIR/scalar_literal_propagation.rs:+3:1: +3:2
return; // scope 0 at $DIR/scalar_literal_propagation.rs:+3:2: +3:2
}
}
diff --git a/tests/mir-opt/const_prop/slice_len.main.ConstProp.32bit.diff b/tests/mir-opt/const_prop/slice_len.main.ConstProp.32bit.diff
index 9017fd18e..b99b83b0c 100644
--- a/tests/mir-opt/const_prop/slice_len.main.ConstProp.32bit.diff
+++ b/tests/mir-opt/const_prop/slice_len.main.ConstProp.32bit.diff
@@ -20,7 +20,7 @@
StorageLive(_4); // scope 0 at $DIR/slice_len.rs:+1:6: +1:19
_9 = const _; // scope 0 at $DIR/slice_len.rs:+1:6: +1:19
// mir::Constant
- // + span: $DIR/slice_len.rs:6:6: 6:19
+ // + span: $DIR/slice_len.rs:7:6: 7:19
// + literal: Const { ty: &[u32; 3], val: Unevaluated(main, [], Some(promoted[0])) }
_4 = _9; // scope 0 at $DIR/slice_len.rs:+1:6: +1:19
_3 = _4; // scope 0 at $DIR/slice_len.rs:+1:6: +1:19
@@ -33,7 +33,7 @@
- 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:+1:5: +1:33
+ _7 = const 3_usize; // scope 0 at $DIR/slice_len.rs:+1:5: +1:33
+ _8 = const true; // scope 0 at $DIR/slice_len.rs:+1:5: +1: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:+1:5: +1:33
++ assert(const true, "index out of bounds: the length is {} but the index is {}", move _7, _6) -> bb1; // scope 0 at $DIR/slice_len.rs:+1:5: +1:33
}
bb1: {
@@ -43,7 +43,7 @@
StorageDead(_4); // scope 0 at $DIR/slice_len.rs:+1:33: +1:34
StorageDead(_2); // scope 0 at $DIR/slice_len.rs:+1:33: +1:34
StorageDead(_1); // scope 0 at $DIR/slice_len.rs:+1:33: +1:34
- nop; // scope 0 at $DIR/slice_len.rs:+0:11: +2:2
+ _0 = const (); // scope 0 at $DIR/slice_len.rs:+0:11: +2:2
return; // scope 0 at $DIR/slice_len.rs:+2:2: +2:2
}
}
diff --git a/tests/mir-opt/const_prop/slice_len.main.ConstProp.64bit.diff b/tests/mir-opt/const_prop/slice_len.main.ConstProp.64bit.diff
index 9017fd18e..b99b83b0c 100644
--- a/tests/mir-opt/const_prop/slice_len.main.ConstProp.64bit.diff
+++ b/tests/mir-opt/const_prop/slice_len.main.ConstProp.64bit.diff
@@ -20,7 +20,7 @@
StorageLive(_4); // scope 0 at $DIR/slice_len.rs:+1:6: +1:19
_9 = const _; // scope 0 at $DIR/slice_len.rs:+1:6: +1:19
// mir::Constant
- // + span: $DIR/slice_len.rs:6:6: 6:19
+ // + span: $DIR/slice_len.rs:7:6: 7:19
// + literal: Const { ty: &[u32; 3], val: Unevaluated(main, [], Some(promoted[0])) }
_4 = _9; // scope 0 at $DIR/slice_len.rs:+1:6: +1:19
_3 = _4; // scope 0 at $DIR/slice_len.rs:+1:6: +1:19
@@ -33,7 +33,7 @@
- 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:+1:5: +1:33
+ _7 = const 3_usize; // scope 0 at $DIR/slice_len.rs:+1:5: +1:33
+ _8 = const true; // scope 0 at $DIR/slice_len.rs:+1:5: +1: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:+1:5: +1:33
++ assert(const true, "index out of bounds: the length is {} but the index is {}", move _7, _6) -> bb1; // scope 0 at $DIR/slice_len.rs:+1:5: +1:33
}
bb1: {
@@ -43,7 +43,7 @@
StorageDead(_4); // scope 0 at $DIR/slice_len.rs:+1:33: +1:34
StorageDead(_2); // scope 0 at $DIR/slice_len.rs:+1:33: +1:34
StorageDead(_1); // scope 0 at $DIR/slice_len.rs:+1:33: +1:34
- nop; // scope 0 at $DIR/slice_len.rs:+0:11: +2:2
+ _0 = const (); // scope 0 at $DIR/slice_len.rs:+0:11: +2:2
return; // scope 0 at $DIR/slice_len.rs:+2:2: +2:2
}
}
diff --git a/tests/mir-opt/const_prop/slice_len.rs b/tests/mir-opt/const_prop/slice_len.rs
index eaaf34b96..8183def0c 100644
--- a/tests/mir-opt/const_prop/slice_len.rs
+++ b/tests/mir-opt/const_prop/slice_len.rs
@@ -1,4 +1,5 @@
-// compile-flags: -Zmir-enable-passes=-SimplifyLocals-before-const-prop
+// unit-test: ConstProp
+// compile-flags: -Zmir-enable-passes=+InstCombine
// EMIT_MIR_FOR_EACH_BIT_WIDTH
// EMIT_MIR slice_len.main.ConstProp.diff
diff --git a/tests/mir-opt/const_prop/tuple_literal_propagation.main.ConstProp.diff b/tests/mir-opt/const_prop/tuple_literal_propagation.main.ConstProp.diff
index e4c92b617..270a1ccf5 100644
--- a/tests/mir-opt/const_prop/tuple_literal_propagation.main.ConstProp.diff
+++ b/tests/mir-opt/const_prop/tuple_literal_propagation.main.ConstProp.diff
@@ -11,24 +11,17 @@
}
bb0: {
- StorageLive(_1); // scope 0 at $DIR/tuple_literal_propagation.rs:+1:9: +1:10
- Deinit(_1); // scope 0 at $DIR/tuple_literal_propagation.rs:+1:13: +1:19
- (_1.0: u32) = const 1_u32; // scope 0 at $DIR/tuple_literal_propagation.rs:+1:13: +1:19
- (_1.1: u32) = const 2_u32; // scope 0 at $DIR/tuple_literal_propagation.rs:+1:13: +1:19
+- _1 = (const 1_u32, const 2_u32); // scope 0 at $DIR/tuple_literal_propagation.rs:+1:13: +1:19
++ _1 = const (1_u32, 2_u32); // scope 0 at $DIR/tuple_literal_propagation.rs:+1:13: +1:19
StorageLive(_2); // scope 1 at $DIR/tuple_literal_propagation.rs:+3:5: +3:15
- StorageLive(_3); // scope 1 at $DIR/tuple_literal_propagation.rs:+3:13: +3:14
-- _3 = _1; // scope 1 at $DIR/tuple_literal_propagation.rs:+3:13: +3:14
-+ _3 = const (1_u32, 2_u32); // scope 1 at $DIR/tuple_literal_propagation.rs:+3:13: +3:14
- _2 = consume(move _3) -> bb1; // scope 1 at $DIR/tuple_literal_propagation.rs:+3:5: +3:15
+ _2 = consume(_1) -> bb1; // scope 1 at $DIR/tuple_literal_propagation.rs:+3:5: +3:15
// mir::Constant
// + span: $DIR/tuple_literal_propagation.rs:5:5: 5:12
// + literal: Const { ty: fn((u32, u32)) {consume}, val: Value(<ZST>) }
}
bb1: {
- StorageDead(_3); // scope 1 at $DIR/tuple_literal_propagation.rs:+3:14: +3:15
StorageDead(_2); // scope 1 at $DIR/tuple_literal_propagation.rs:+3:15: +3:16
- StorageDead(_1); // scope 0 at $DIR/tuple_literal_propagation.rs:+4:1: +4:2
return; // scope 0 at $DIR/tuple_literal_propagation.rs:+4:2: +4:2
}
}
diff --git a/tests/mir-opt/const_prop_miscompile.bar.ConstProp.diff b/tests/mir-opt/const_prop_miscompile.bar.ConstProp.diff
index ea9fec0aa..def9fc642 100644
--- a/tests/mir-opt/const_prop_miscompile.bar.ConstProp.diff
+++ b/tests/mir-opt/const_prop_miscompile.bar.ConstProp.diff
@@ -4,32 +4,37 @@
fn bar() -> () {
let mut _0: (); // return place in scope 0 at $DIR/const_prop_miscompile.rs:+0:10: +0:10
let mut _1: (i32,); // in scope 0 at $DIR/const_prop_miscompile.rs:+1:9: +1:14
- let mut _2: *mut i32; // in scope 0 at $DIR/const_prop_miscompile.rs:+3:10: +3:22
- let mut _4: i32; // in scope 0 at $DIR/const_prop_miscompile.rs:+5:13: +5:20
+ let _2: (); // in scope 0 at $DIR/const_prop_miscompile.rs:+2:5: +4:6
+ let mut _3: *mut i32; // in scope 0 at $DIR/const_prop_miscompile.rs:+3:10: +3:22
+ let mut _5: i32; // in scope 0 at $DIR/const_prop_miscompile.rs:+5:13: +5:20
scope 1 {
debug v => _1; // in scope 1 at $DIR/const_prop_miscompile.rs:+1:9: +1:14
- let _3: bool; // in scope 1 at $DIR/const_prop_miscompile.rs:+5:9: +5:10
+ let _4: bool; // in scope 1 at $DIR/const_prop_miscompile.rs:+5:9: +5:10
scope 2 {
}
scope 3 {
- debug y => _3; // in scope 3 at $DIR/const_prop_miscompile.rs:+5:9: +5:10
+ debug y => _4; // in scope 3 at $DIR/const_prop_miscompile.rs:+5:9: +5:10
}
}
bb0: {
StorageLive(_1); // scope 0 at $DIR/const_prop_miscompile.rs:+1:9: +1:14
- Deinit(_1); // scope 0 at $DIR/const_prop_miscompile.rs:+1:17: +1:21
- (_1.0: i32) = const 1_i32; // scope 0 at $DIR/const_prop_miscompile.rs:+1:17: +1:21
- StorageLive(_2); // scope 2 at $DIR/const_prop_miscompile.rs:+3:10: +3:22
- _2 = &raw mut (_1.0: i32); // scope 2 at $DIR/const_prop_miscompile.rs:+3:10: +3:22
- (*_2) = const 5_i32; // scope 2 at $DIR/const_prop_miscompile.rs:+3:9: +3:26
- StorageDead(_2); // scope 2 at $DIR/const_prop_miscompile.rs:+3:26: +3:27
- StorageLive(_3); // scope 1 at $DIR/const_prop_miscompile.rs:+5:9: +5:10
- StorageLive(_4); // scope 1 at $DIR/const_prop_miscompile.rs:+5:13: +5:20
- _4 = (_1.0: i32); // scope 1 at $DIR/const_prop_miscompile.rs:+5:15: +5:18
- _3 = Eq(move _4, const 5_i32); // scope 1 at $DIR/const_prop_miscompile.rs:+5:13: +5:25
- StorageDead(_4); // scope 1 at $DIR/const_prop_miscompile.rs:+5:24: +5:25
- StorageDead(_3); // scope 1 at $DIR/const_prop_miscompile.rs:+6:1: +6:2
+- _1 = (const 1_i32,); // scope 0 at $DIR/const_prop_miscompile.rs:+1:17: +1:21
++ _1 = const (1_i32,); // scope 0 at $DIR/const_prop_miscompile.rs:+1:17: +1:21
+ StorageLive(_2); // scope 1 at $DIR/const_prop_miscompile.rs:+2:5: +4:6
+ StorageLive(_3); // scope 2 at $DIR/const_prop_miscompile.rs:+3:10: +3:22
+ _3 = &raw mut (_1.0: i32); // scope 2 at $DIR/const_prop_miscompile.rs:+3:10: +3:22
+ (*_3) = const 5_i32; // scope 2 at $DIR/const_prop_miscompile.rs:+3:9: +3:26
+ StorageDead(_3); // scope 2 at $DIR/const_prop_miscompile.rs:+3:26: +3:27
+ _2 = const (); // scope 2 at $DIR/const_prop_miscompile.rs:+2:5: +4:6
+ StorageDead(_2); // scope 1 at $DIR/const_prop_miscompile.rs:+4:5: +4:6
+ StorageLive(_4); // scope 1 at $DIR/const_prop_miscompile.rs:+5:9: +5:10
+ StorageLive(_5); // scope 1 at $DIR/const_prop_miscompile.rs:+5:13: +5:20
+ _5 = (_1.0: i32); // scope 1 at $DIR/const_prop_miscompile.rs:+5:15: +5:18
+ _4 = Eq(move _5, const 5_i32); // scope 1 at $DIR/const_prop_miscompile.rs:+5:13: +5:25
+ StorageDead(_5); // scope 1 at $DIR/const_prop_miscompile.rs:+5:24: +5:25
+ _0 = const (); // scope 0 at $DIR/const_prop_miscompile.rs:+0:10: +6:2
+ StorageDead(_4); // scope 1 at $DIR/const_prop_miscompile.rs:+6:1: +6:2
StorageDead(_1); // scope 0 at $DIR/const_prop_miscompile.rs:+6:1: +6:2
return; // scope 0 at $DIR/const_prop_miscompile.rs:+6:2: +6:2
}
diff --git a/tests/mir-opt/const_prop_miscompile.foo.ConstProp.diff b/tests/mir-opt/const_prop_miscompile.foo.ConstProp.diff
index 043f40474..b54c10a14 100644
--- a/tests/mir-opt/const_prop_miscompile.foo.ConstProp.diff
+++ b/tests/mir-opt/const_prop_miscompile.foo.ConstProp.diff
@@ -16,8 +16,8 @@
bb0: {
StorageLive(_1); // scope 0 at $DIR/const_prop_miscompile.rs:+1:9: +1:14
- Deinit(_1); // scope 0 at $DIR/const_prop_miscompile.rs:+1:17: +1:21
- (_1.0: i32) = const 1_i32; // scope 0 at $DIR/const_prop_miscompile.rs:+1:17: +1:21
+- _1 = (const 1_i32,); // scope 0 at $DIR/const_prop_miscompile.rs:+1:17: +1:21
++ _1 = const (1_i32,); // scope 0 at $DIR/const_prop_miscompile.rs:+1:17: +1:21
StorageLive(_2); // scope 1 at $DIR/const_prop_miscompile.rs:+2:6: +2:14
_2 = &mut (_1.0: i32); // scope 1 at $DIR/const_prop_miscompile.rs:+2:6: +2:14
(*_2) = const 5_i32; // scope 1 at $DIR/const_prop_miscompile.rs:+2:5: +2:18
@@ -27,6 +27,7 @@
_4 = (_1.0: i32); // scope 1 at $DIR/const_prop_miscompile.rs:+3:15: +3:18
_3 = Eq(move _4, const 5_i32); // scope 1 at $DIR/const_prop_miscompile.rs:+3:13: +3:25
StorageDead(_4); // scope 1 at $DIR/const_prop_miscompile.rs:+3:24: +3:25
+ _0 = const (); // scope 0 at $DIR/const_prop_miscompile.rs:+0:10: +4:2
StorageDead(_3); // scope 1 at $DIR/const_prop_miscompile.rs:+4:1: +4:2
StorageDead(_1); // scope 0 at $DIR/const_prop_miscompile.rs:+4:1: +4:2
return; // scope 0 at $DIR/const_prop_miscompile.rs:+4:2: +4:2
diff --git a/tests/mir-opt/const_prop_miscompile.rs b/tests/mir-opt/const_prop_miscompile.rs
index bc54556b3..dbbe5ee08 100644
--- a/tests/mir-opt/const_prop_miscompile.rs
+++ b/tests/mir-opt/const_prop_miscompile.rs
@@ -1,3 +1,4 @@
+// unit-test: ConstProp
#![feature(raw_ref_op)]
// EMIT_MIR const_prop_miscompile.foo.ConstProp.diff
diff --git a/tests/mir-opt/copy-prop/borrowed_local.f.CopyProp.diff b/tests/mir-opt/copy-prop/borrowed_local.f.CopyProp.diff
new file mode 100644
index 000000000..b183865a9
--- /dev/null
+++ b/tests/mir-opt/copy-prop/borrowed_local.f.CopyProp.diff
@@ -0,0 +1,34 @@
+- // MIR for `f` before CopyProp
++ // MIR for `f` after CopyProp
+
+ fn f() -> bool {
+ let mut _0: bool; // return place in scope 0 at $DIR/borrowed_local.rs:+0:11: +0:15
+ let mut _1: u8; // in scope 0 at $SRC_DIR/core/src/intrinsics/mir.rs:LL:COL
+ let mut _2: &u8; // in scope 0 at $SRC_DIR/core/src/intrinsics/mir.rs:LL:COL
+ let mut _3: u8; // in scope 0 at $SRC_DIR/core/src/intrinsics/mir.rs:LL:COL
+ let mut _4: &u8; // in scope 0 at $SRC_DIR/core/src/intrinsics/mir.rs:LL:COL
+
+ bb0: {
+ _1 = const 5_u8; // scope 0 at $SRC_DIR/core/src/intrinsics/mir.rs:LL:COL
+ _2 = &_1; // scope 0 at $SRC_DIR/core/src/intrinsics/mir.rs:LL:COL
+ _3 = _1; // scope 0 at $SRC_DIR/core/src/intrinsics/mir.rs:LL:COL
+ _4 = &_3; // scope 0 at $SRC_DIR/core/src/intrinsics/mir.rs:LL:COL
+ _0 = cmp_ref(_2, _4) -> bb1; // scope 0 at $DIR/borrowed_local.rs:+8:13: +8:45
+ // mir::Constant
+ // + span: $DIR/borrowed_local.rs:23:29: 23:36
+ // + literal: Const { ty: for<'a, 'b> fn(&'a u8, &'b u8) -> bool {cmp_ref}, val: Value(<ZST>) }
+ }
+
+ bb1: {
+- _0 = opaque::<u8>(_3) -> bb2; // scope 0 at $DIR/borrowed_local.rs:+12:13: +12:38
++ _0 = opaque::<u8>(_1) -> bb2; // scope 0 at $DIR/borrowed_local.rs:+12:13: +12:38
+ // mir::Constant
+ // + span: $DIR/borrowed_local.rs:27:28: 27:34
+ // + literal: Const { ty: fn(u8) -> bool {opaque::<u8>}, val: Value(<ZST>) }
+ }
+
+ bb2: {
+ return; // scope 0 at $DIR/borrowed_local.rs:+15:13: +15:21
+ }
+ }
+
diff --git a/tests/mir-opt/copy-prop/borrowed_local.rs b/tests/mir-opt/copy-prop/borrowed_local.rs
new file mode 100644
index 000000000..c4b980e2b
--- /dev/null
+++ b/tests/mir-opt/copy-prop/borrowed_local.rs
@@ -0,0 +1,39 @@
+// unit-test: CopyProp
+
+#![feature(custom_mir, core_intrinsics)]
+#![allow(unused_assignments)]
+extern crate core;
+use core::intrinsics::mir::*;
+
+fn opaque(_: impl Sized) -> bool { true }
+
+fn cmp_ref(a: &u8, b: &u8) -> bool {
+ std::ptr::eq(a as *const u8, b as *const u8)
+}
+
+#[custom_mir(dialect = "analysis", phase = "post-cleanup")]
+fn f() -> bool {
+ mir!(
+ {
+ let a = 5_u8;
+ let r1 = &a;
+ let b = a;
+ // We cannot propagate the place `a`.
+ let r2 = &b;
+ Call(RET, next, cmp_ref(r1, r2))
+ }
+ next = {
+ // But we can propagate the value `a`.
+ Call(RET, ret, opaque(b))
+ }
+ ret = {
+ Return()
+ }
+ )
+}
+
+fn main() {
+ assert!(!f());
+}
+
+// EMIT_MIR borrowed_local.f.CopyProp.diff
diff --git a/tests/mir-opt/copy-prop/branch.foo.CopyProp.diff b/tests/mir-opt/copy-prop/branch.foo.CopyProp.diff
new file mode 100644
index 000000000..8b116532d
--- /dev/null
+++ b/tests/mir-opt/copy-prop/branch.foo.CopyProp.diff
@@ -0,0 +1,65 @@
+- // MIR for `foo` before CopyProp
++ // MIR for `foo` after CopyProp
+
+ fn foo() -> i32 {
+ let mut _0: i32; // return place in scope 0 at $DIR/branch.rs:+0:13: +0:16
+ let _1: i32; // in scope 0 at $DIR/branch.rs:+1:9: +1:10
+ let mut _3: bool; // in scope 0 at $DIR/branch.rs:+3:16: +3:22
+ let _4: i32; // in scope 0 at $DIR/branch.rs:+6:9: +6:14
+ scope 1 {
+ debug x => _1; // in scope 1 at $DIR/branch.rs:+1:9: +1:10
+ let _2: i32; // in scope 1 at $DIR/branch.rs:+3:9: +3:10
+ scope 2 {
+ debug y => _2; // in scope 2 at $DIR/branch.rs:+3:9: +3:10
+ }
+ }
+
+ bb0: {
+ StorageLive(_1); // scope 0 at $DIR/branch.rs:+1:9: +1:10
+ _1 = val() -> bb1; // scope 0 at $DIR/branch.rs:+1:13: +1:18
+ // mir::Constant
+ // + span: $DIR/branch.rs:13:13: 13:16
+ // + literal: Const { ty: fn() -> i32 {val}, val: Value(<ZST>) }
+ }
+
+ bb1: {
+ StorageLive(_2); // scope 1 at $DIR/branch.rs:+3:9: +3:10
+ StorageLive(_3); // scope 1 at $DIR/branch.rs:+3:16: +3:22
+ _3 = cond() -> bb2; // scope 1 at $DIR/branch.rs:+3:16: +3:22
+ // mir::Constant
+ // + span: $DIR/branch.rs:15:16: 15:20
+ // + literal: Const { ty: fn() -> bool {cond}, val: Value(<ZST>) }
+ }
+
+ bb2: {
+ switchInt(move _3) -> [0: bb4, otherwise: bb3]; // scope 1 at $DIR/branch.rs:+3:16: +3:22
+ }
+
+ bb3: {
+ _2 = _1; // scope 1 at $DIR/branch.rs:+4:9: +4:10
+ goto -> bb6; // scope 1 at $DIR/branch.rs:+3:13: +8:6
+ }
+
+ bb4: {
+ StorageLive(_4); // scope 1 at $DIR/branch.rs:+6:9: +6:14
+ _4 = val() -> bb5; // scope 1 at $DIR/branch.rs:+6:9: +6:14
+ // mir::Constant
+ // + span: $DIR/branch.rs:18:9: 18:12
+ // + literal: Const { ty: fn() -> i32 {val}, val: Value(<ZST>) }
+ }
+
+ bb5: {
+ StorageDead(_4); // scope 1 at $DIR/branch.rs:+6:14: +6:15
+ _2 = _1; // scope 1 at $DIR/branch.rs:+7:9: +7:10
+ goto -> bb6; // scope 1 at $DIR/branch.rs:+3:13: +8:6
+ }
+
+ bb6: {
+ StorageDead(_3); // scope 1 at $DIR/branch.rs:+8:5: +8:6
+ _0 = _2; // scope 2 at $DIR/branch.rs:+10:5: +10:6
+ StorageDead(_2); // scope 1 at $DIR/branch.rs:+11:1: +11:2
+ StorageDead(_1); // scope 0 at $DIR/branch.rs:+11:1: +11:2
+ return; // scope 0 at $DIR/branch.rs:+11:2: +11:2
+ }
+ }
+
diff --git a/tests/mir-opt/copy-prop/branch.rs b/tests/mir-opt/copy-prop/branch.rs
new file mode 100644
index 000000000..50b1e00fa
--- /dev/null
+++ b/tests/mir-opt/copy-prop/branch.rs
@@ -0,0 +1,27 @@
+//! Tests that we bail out when there are multiple assignments to the same local.
+// unit-test: CopyProp
+fn val() -> i32 {
+ 1
+}
+
+fn cond() -> bool {
+ true
+}
+
+// EMIT_MIR branch.foo.CopyProp.diff
+fn foo() -> i32 {
+ let x = val();
+
+ let y = if cond() {
+ x
+ } else {
+ val();
+ x
+ };
+
+ y
+}
+
+fn main() {
+ foo();
+}
diff --git a/tests/mir-opt/copy-prop/copy_propagation_arg.arg_src.CopyProp.diff b/tests/mir-opt/copy-prop/copy_propagation_arg.arg_src.CopyProp.diff
new file mode 100644
index 000000000..69acebf76
--- /dev/null
+++ b/tests/mir-opt/copy-prop/copy_propagation_arg.arg_src.CopyProp.diff
@@ -0,0 +1,21 @@
+- // MIR for `arg_src` before CopyProp
++ // MIR for `arg_src` after CopyProp
+
+ fn arg_src(_1: i32) -> i32 {
+ debug x => _1; // in scope 0 at $DIR/copy_propagation_arg.rs:+0:12: +0:17
+ let mut _0: i32; // return place in scope 0 at $DIR/copy_propagation_arg.rs:+0:27: +0:30
+ let _2: i32; // in scope 0 at $DIR/copy_propagation_arg.rs:+1:9: +1:10
+ scope 1 {
+ debug y => _2; // in scope 1 at $DIR/copy_propagation_arg.rs:+1:9: +1:10
+ }
+
+ bb0: {
+ StorageLive(_2); // scope 0 at $DIR/copy_propagation_arg.rs:+1:9: +1:10
+ _2 = _1; // scope 0 at $DIR/copy_propagation_arg.rs:+1:13: +1:14
+ _1 = const 123_i32; // scope 1 at $DIR/copy_propagation_arg.rs:+2:5: +2:12
+ _0 = _2; // scope 1 at $DIR/copy_propagation_arg.rs:+3:5: +3:6
+ StorageDead(_2); // scope 0 at $DIR/copy_propagation_arg.rs:+4:1: +4:2
+ return; // scope 0 at $DIR/copy_propagation_arg.rs:+4:2: +4:2
+ }
+ }
+
diff --git a/tests/mir-opt/copy-prop/copy_propagation_arg.bar.CopyProp.diff b/tests/mir-opt/copy-prop/copy_propagation_arg.bar.CopyProp.diff
new file mode 100644
index 000000000..ac4e9a2bf
--- /dev/null
+++ b/tests/mir-opt/copy-prop/copy_propagation_arg.bar.CopyProp.diff
@@ -0,0 +1,28 @@
+- // MIR for `bar` before CopyProp
++ // MIR for `bar` after CopyProp
+
+ fn bar(_1: u8) -> () {
+ debug x => _1; // in scope 0 at $DIR/copy_propagation_arg.rs:+0:8: +0:13
+ let mut _0: (); // return place in scope 0 at $DIR/copy_propagation_arg.rs:+0:19: +0:19
+ let _2: u8; // in scope 0 at $DIR/copy_propagation_arg.rs:+1:5: +1:13
+ let mut _3: u8; // in scope 0 at $DIR/copy_propagation_arg.rs:+1:11: +1:12
+
+ bb0: {
+ StorageLive(_2); // scope 0 at $DIR/copy_propagation_arg.rs:+1:5: +1:13
+ StorageLive(_3); // scope 0 at $DIR/copy_propagation_arg.rs:+1:11: +1:12
+ _3 = _1; // scope 0 at $DIR/copy_propagation_arg.rs:+1:11: +1:12
+ _2 = dummy(move _3) -> bb1; // scope 0 at $DIR/copy_propagation_arg.rs:+1:5: +1:13
+ // mir::Constant
+ // + span: $DIR/copy_propagation_arg.rs:16:5: 16:10
+ // + literal: Const { ty: fn(u8) -> u8 {dummy}, val: Value(<ZST>) }
+ }
+
+ bb1: {
+ StorageDead(_3); // scope 0 at $DIR/copy_propagation_arg.rs:+1:12: +1:13
+ StorageDead(_2); // scope 0 at $DIR/copy_propagation_arg.rs:+1:13: +1:14
+ _1 = const 5_u8; // scope 0 at $DIR/copy_propagation_arg.rs:+2:5: +2:10
+ _0 = const (); // scope 0 at $DIR/copy_propagation_arg.rs:+0:19: +3:2
+ return; // scope 0 at $DIR/copy_propagation_arg.rs:+3:2: +3:2
+ }
+ }
+
diff --git a/tests/mir-opt/copy-prop/copy_propagation_arg.baz.CopyProp.diff b/tests/mir-opt/copy-prop/copy_propagation_arg.baz.CopyProp.diff
new file mode 100644
index 000000000..7ab6ebb7d
--- /dev/null
+++ b/tests/mir-opt/copy-prop/copy_propagation_arg.baz.CopyProp.diff
@@ -0,0 +1,18 @@
+- // MIR for `baz` before CopyProp
++ // MIR for `baz` after CopyProp
+
+ fn baz(_1: i32) -> i32 {
+ debug x => _1; // in scope 0 at $DIR/copy_propagation_arg.rs:+0:8: +0:13
+ let mut _0: i32; // return place in scope 0 at $DIR/copy_propagation_arg.rs:+0:23: +0:26
+ let mut _2: i32; // in scope 0 at $DIR/copy_propagation_arg.rs:+2:9: +2:10
+
+ bb0: {
+ StorageLive(_2); // scope 0 at $DIR/copy_propagation_arg.rs:+2:9: +2:10
+ _2 = _1; // scope 0 at $DIR/copy_propagation_arg.rs:+2:9: +2:10
+ _1 = move _2; // scope 0 at $DIR/copy_propagation_arg.rs:+2:5: +2:10
+ StorageDead(_2); // scope 0 at $DIR/copy_propagation_arg.rs:+2:9: +2:10
+ _0 = _1; // scope 0 at $DIR/copy_propagation_arg.rs:+3:5: +3:6
+ return; // scope 0 at $DIR/copy_propagation_arg.rs:+4:2: +4:2
+ }
+ }
+
diff --git a/tests/mir-opt/copy-prop/copy_propagation_arg.foo.CopyProp.diff b/tests/mir-opt/copy-prop/copy_propagation_arg.foo.CopyProp.diff
new file mode 100644
index 000000000..0a3e985e7
--- /dev/null
+++ b/tests/mir-opt/copy-prop/copy_propagation_arg.foo.CopyProp.diff
@@ -0,0 +1,28 @@
+- // MIR for `foo` before CopyProp
++ // MIR for `foo` after CopyProp
+
+ fn foo(_1: u8) -> () {
+ debug x => _1; // in scope 0 at $DIR/copy_propagation_arg.rs:+0:8: +0:13
+ let mut _0: (); // return place in scope 0 at $DIR/copy_propagation_arg.rs:+0:19: +0:19
+ let mut _2: u8; // in scope 0 at $DIR/copy_propagation_arg.rs:+2:9: +2:17
+ let mut _3: u8; // in scope 0 at $DIR/copy_propagation_arg.rs:+2:15: +2:16
+
+ bb0: {
+ StorageLive(_2); // scope 0 at $DIR/copy_propagation_arg.rs:+2:9: +2:17
+ StorageLive(_3); // scope 0 at $DIR/copy_propagation_arg.rs:+2:15: +2:16
+ _3 = _1; // scope 0 at $DIR/copy_propagation_arg.rs:+2:15: +2:16
+ _2 = dummy(move _3) -> bb1; // scope 0 at $DIR/copy_propagation_arg.rs:+2:9: +2:17
+ // mir::Constant
+ // + span: $DIR/copy_propagation_arg.rs:11:9: 11:14
+ // + literal: Const { ty: fn(u8) -> u8 {dummy}, val: Value(<ZST>) }
+ }
+
+ bb1: {
+ StorageDead(_3); // scope 0 at $DIR/copy_propagation_arg.rs:+2:16: +2:17
+ _1 = move _2; // scope 0 at $DIR/copy_propagation_arg.rs:+2:5: +2:17
+ StorageDead(_2); // scope 0 at $DIR/copy_propagation_arg.rs:+2:16: +2:17
+ _0 = const (); // scope 0 at $DIR/copy_propagation_arg.rs:+0:19: +3:2
+ return; // scope 0 at $DIR/copy_propagation_arg.rs:+3:2: +3:2
+ }
+ }
+
diff --git a/tests/mir-opt/copy-prop/copy_propagation_arg.rs b/tests/mir-opt/copy-prop/copy_propagation_arg.rs
new file mode 100644
index 000000000..cc98985f1
--- /dev/null
+++ b/tests/mir-opt/copy-prop/copy_propagation_arg.rs
@@ -0,0 +1,40 @@
+// Check that CopyProp does not propagate an assignment to a function argument
+// (doing so can break usages of the original argument value)
+// unit-test: CopyProp
+fn dummy(x: u8) -> u8 {
+ x
+}
+
+// EMIT_MIR copy_propagation_arg.foo.CopyProp.diff
+fn foo(mut x: u8) {
+ // calling `dummy` to make a use of `x` that copyprop cannot eliminate
+ x = dummy(x); // this will assign a local to `x`
+}
+
+// EMIT_MIR copy_propagation_arg.bar.CopyProp.diff
+fn bar(mut x: u8) {
+ dummy(x);
+ x = 5;
+}
+
+// EMIT_MIR copy_propagation_arg.baz.CopyProp.diff
+fn baz(mut x: i32) -> i32 {
+ // self-assignment to a function argument should be eliminated
+ x = x;
+ x
+}
+
+// EMIT_MIR copy_propagation_arg.arg_src.CopyProp.diff
+fn arg_src(mut x: i32) -> i32 {
+ let y = x;
+ x = 123; // Don't propagate this assignment to `y`
+ y
+}
+
+fn main() {
+ // Make sure the function actually gets instantiated.
+ foo(0);
+ bar(0);
+ baz(0);
+ arg_src(0);
+}
diff --git a/tests/mir-opt/copy-prop/custom_move_arg.f.CopyProp.diff b/tests/mir-opt/copy-prop/custom_move_arg.f.CopyProp.diff
new file mode 100644
index 000000000..6ca73ffdd
--- /dev/null
+++ b/tests/mir-opt/copy-prop/custom_move_arg.f.CopyProp.diff
@@ -0,0 +1,31 @@
+- // MIR for `f` before CopyProp
++ // MIR for `f` after CopyProp
+
+ fn f(_1: NotCopy) -> () {
+ let mut _0: (); // return place in scope 0 at $DIR/custom_move_arg.rs:+0:19: +0:19
+ let mut _2: NotCopy; // in scope 0 at $SRC_DIR/core/src/intrinsics/mir.rs:LL:COL
+ let mut _3: NotCopy; // in scope 0 at $SRC_DIR/core/src/intrinsics/mir.rs:LL:COL
+
+ bb0: {
+- _2 = _1; // scope 0 at $SRC_DIR/core/src/intrinsics/mir.rs:LL:COL
+- _0 = opaque::<NotCopy>(move _1) -> bb1; // scope 0 at $DIR/custom_move_arg.rs:+3:9: +3:41
++ _0 = opaque::<NotCopy>(_1) -> bb1; // scope 0 at $DIR/custom_move_arg.rs:+3:9: +3:41
+ // mir::Constant
+ // + span: $DIR/custom_move_arg.rs:15:24: 15:30
+ // + literal: Const { ty: fn(NotCopy) {opaque::<NotCopy>}, val: Value(<ZST>) }
+ }
+
+ bb1: {
+- _3 = move _2; // scope 0 at $SRC_DIR/core/src/intrinsics/mir.rs:LL:COL
+- _0 = opaque::<NotCopy>(_3) -> bb2; // scope 0 at $DIR/custom_move_arg.rs:+7:9: +7:35
++ _0 = opaque::<NotCopy>(_1) -> bb2; // scope 0 at $DIR/custom_move_arg.rs:+7:9: +7:35
+ // mir::Constant
+ // + span: $DIR/custom_move_arg.rs:19:24: 19:30
+ // + literal: Const { ty: fn(NotCopy) {opaque::<NotCopy>}, val: Value(<ZST>) }
+ }
+
+ bb2: {
+ return; // scope 0 at $DIR/custom_move_arg.rs:+10:9: +10:17
+ }
+ }
+
diff --git a/tests/mir-opt/copy-prop/custom_move_arg.rs b/tests/mir-opt/copy-prop/custom_move_arg.rs
new file mode 100644
index 000000000..4a591146e
--- /dev/null
+++ b/tests/mir-opt/copy-prop/custom_move_arg.rs
@@ -0,0 +1,32 @@
+// unit-test: CopyProp
+
+#![feature(custom_mir, core_intrinsics)]
+#![allow(unused_assignments)]
+extern crate core;
+use core::intrinsics::mir::*;
+
+struct NotCopy(bool);
+
+// EMIT_MIR custom_move_arg.f.CopyProp.diff
+#[custom_mir(dialect = "analysis", phase = "post-cleanup")]
+fn f(_1: NotCopy) {
+ mir!({
+ let _2 = _1;
+ Call(RET, bb1, opaque(Move(_1)))
+ }
+ bb1 = {
+ let _3 = Move(_2);
+ Call(RET, bb2, opaque(_3))
+ }
+ bb2 = {
+ Return()
+ })
+}
+
+#[inline(never)]
+fn opaque<T>(_t: T) {}
+
+fn main() {
+ f(NotCopy(true));
+ println!("hi");
+}
diff --git a/tests/mir-opt/copy-prop/cycle.main.CopyProp.diff b/tests/mir-opt/copy-prop/cycle.main.CopyProp.diff
new file mode 100644
index 000000000..3e61869e8
--- /dev/null
+++ b/tests/mir-opt/copy-prop/cycle.main.CopyProp.diff
@@ -0,0 +1,60 @@
+- // MIR for `main` before CopyProp
++ // MIR for `main` after CopyProp
+
+ fn main() -> () {
+ let mut _0: (); // return place in scope 0 at $DIR/cycle.rs:+0:11: +0:11
+ let mut _1: i32; // in scope 0 at $DIR/cycle.rs:+1:9: +1:14
+ let mut _4: i32; // in scope 0 at $DIR/cycle.rs:+4:9: +4:10
+ let _5: (); // in scope 0 at $DIR/cycle.rs:+6:5: +6:12
+ let mut _6: i32; // in scope 0 at $DIR/cycle.rs:+6:10: +6:11
+ scope 1 {
+ debug x => _1; // in scope 1 at $DIR/cycle.rs:+1:9: +1:14
+ let _2: i32; // in scope 1 at $DIR/cycle.rs:+2:9: +2:10
+ scope 2 {
+ debug y => _2; // in scope 2 at $DIR/cycle.rs:+2:9: +2:10
+ let _3: i32; // in scope 2 at $DIR/cycle.rs:+3:9: +3:10
+ scope 3 {
+- debug z => _3; // in scope 3 at $DIR/cycle.rs:+3:9: +3:10
++ debug z => _2; // in scope 3 at $DIR/cycle.rs:+3:9: +3:10
+ }
+ }
+ }
+
+ bb0: {
+ StorageLive(_1); // scope 0 at $DIR/cycle.rs:+1:9: +1:14
+ _1 = val() -> bb1; // scope 0 at $DIR/cycle.rs:+1:17: +1:22
+ // mir::Constant
+ // + span: $DIR/cycle.rs:9:17: 9:20
+ // + literal: Const { ty: fn() -> i32 {val}, val: Value(<ZST>) }
+ }
+
+ bb1: {
+- StorageLive(_2); // scope 1 at $DIR/cycle.rs:+2:9: +2:10
+ _2 = _1; // scope 1 at $DIR/cycle.rs:+2:13: +2:14
+- StorageLive(_3); // scope 2 at $DIR/cycle.rs:+3:9: +3:10
+- _3 = _2; // scope 2 at $DIR/cycle.rs:+3:13: +3:14
+- StorageLive(_4); // scope 3 at $DIR/cycle.rs:+4:9: +4:10
+- _4 = _3; // scope 3 at $DIR/cycle.rs:+4:9: +4:10
+- _1 = move _4; // scope 3 at $DIR/cycle.rs:+4:5: +4:10
+- StorageDead(_4); // scope 3 at $DIR/cycle.rs:+4:9: +4:10
++ _1 = _2; // scope 3 at $DIR/cycle.rs:+4:5: +4:10
+ StorageLive(_5); // scope 3 at $DIR/cycle.rs:+6:5: +6:12
+ StorageLive(_6); // scope 3 at $DIR/cycle.rs:+6:10: +6:11
+ _6 = _1; // scope 3 at $DIR/cycle.rs:+6:10: +6:11
+ _5 = std::mem::drop::<i32>(move _6) -> bb2; // scope 3 at $DIR/cycle.rs:+6:5: +6:12
+ // mir::Constant
+ // + span: $DIR/cycle.rs:14:5: 14:9
+ // + literal: Const { ty: fn(i32) {std::mem::drop::<i32>}, val: Value(<ZST>) }
+ }
+
+ bb2: {
+ StorageDead(_6); // scope 3 at $DIR/cycle.rs:+6:11: +6:12
+ StorageDead(_5); // scope 3 at $DIR/cycle.rs:+6:12: +6:13
+ _0 = const (); // scope 0 at $DIR/cycle.rs:+0:11: +7:2
+- StorageDead(_3); // scope 2 at $DIR/cycle.rs:+7:1: +7:2
+- StorageDead(_2); // scope 1 at $DIR/cycle.rs:+7:1: +7:2
+ StorageDead(_1); // scope 0 at $DIR/cycle.rs:+7:1: +7:2
+ return; // scope 0 at $DIR/cycle.rs:+7:2: +7:2
+ }
+ }
+
diff --git a/tests/mir-opt/copy-prop/cycle.rs b/tests/mir-opt/copy-prop/cycle.rs
new file mode 100644
index 000000000..b74c39726
--- /dev/null
+++ b/tests/mir-opt/copy-prop/cycle.rs
@@ -0,0 +1,15 @@
+//! Tests that cyclic assignments don't hang CopyProp, and result in reasonable code.
+// unit-test: CopyProp
+fn val() -> i32 {
+ 1
+}
+
+// EMIT_MIR cycle.main.CopyProp.diff
+fn main() {
+ let mut x = val();
+ let y = x;
+ let z = y;
+ x = z;
+
+ drop(x);
+}
diff --git a/tests/mir-opt/copy-prop/dead_stores_79191.f.CopyProp.after.mir b/tests/mir-opt/copy-prop/dead_stores_79191.f.CopyProp.after.mir
new file mode 100644
index 000000000..d48b04e2d
--- /dev/null
+++ b/tests/mir-opt/copy-prop/dead_stores_79191.f.CopyProp.after.mir
@@ -0,0 +1,29 @@
+// MIR for `f` after CopyProp
+
+fn f(_1: usize) -> usize {
+ debug a => _1; // in scope 0 at $DIR/dead_stores_79191.rs:+0:6: +0:11
+ let mut _0: usize; // return place in scope 0 at $DIR/dead_stores_79191.rs:+0:23: +0:28
+ let _2: usize; // in scope 0 at $DIR/dead_stores_79191.rs:+1:9: +1:10
+ let mut _3: usize; // in scope 0 at $DIR/dead_stores_79191.rs:+3:9: +3:10
+ let mut _4: usize; // in scope 0 at $DIR/dead_stores_79191.rs:+4:8: +4:9
+ scope 1 {
+ debug b => _2; // in scope 1 at $DIR/dead_stores_79191.rs:+1:9: +1:10
+ }
+
+ bb0: {
+ _2 = _1; // scope 0 at $DIR/dead_stores_79191.rs:+1:13: +1:14
+ _1 = const 5_usize; // scope 1 at $DIR/dead_stores_79191.rs:+2:5: +2:10
+ _1 = _2; // scope 1 at $DIR/dead_stores_79191.rs:+3:5: +3:10
+ StorageLive(_4); // scope 1 at $DIR/dead_stores_79191.rs:+4:8: +4:9
+ _4 = _1; // scope 1 at $DIR/dead_stores_79191.rs:+4:8: +4:9
+ _0 = id::<usize>(move _4) -> bb1; // scope 1 at $DIR/dead_stores_79191.rs:+4:5: +4:10
+ // mir::Constant
+ // + span: $DIR/dead_stores_79191.rs:12:5: 12:7
+ // + literal: Const { ty: fn(usize) -> usize {id::<usize>}, val: Value(<ZST>) }
+ }
+
+ bb1: {
+ StorageDead(_4); // scope 1 at $DIR/dead_stores_79191.rs:+4:9: +4:10
+ return; // scope 0 at $DIR/dead_stores_79191.rs:+5:2: +5:2
+ }
+}
diff --git a/tests/mir-opt/copy-prop/dead_stores_79191.rs b/tests/mir-opt/copy-prop/dead_stores_79191.rs
new file mode 100644
index 000000000..e3493b8b7
--- /dev/null
+++ b/tests/mir-opt/copy-prop/dead_stores_79191.rs
@@ -0,0 +1,17 @@
+// unit-test: CopyProp
+
+fn id<T>(x: T) -> T {
+ x
+}
+
+// EMIT_MIR dead_stores_79191.f.CopyProp.after.mir
+fn f(mut a: usize) -> usize {
+ let b = a;
+ a = 5;
+ a = b;
+ id(a)
+}
+
+fn main() {
+ f(0);
+}
diff --git a/tests/mir-opt/copy-prop/dead_stores_better.f.CopyProp.after.mir b/tests/mir-opt/copy-prop/dead_stores_better.f.CopyProp.after.mir
new file mode 100644
index 000000000..727791f50
--- /dev/null
+++ b/tests/mir-opt/copy-prop/dead_stores_better.f.CopyProp.after.mir
@@ -0,0 +1,29 @@
+// MIR for `f` after CopyProp
+
+fn f(_1: usize) -> usize {
+ debug a => _1; // in scope 0 at $DIR/dead_stores_better.rs:+0:10: +0:15
+ let mut _0: usize; // return place in scope 0 at $DIR/dead_stores_better.rs:+0:27: +0:32
+ let _2: usize; // in scope 0 at $DIR/dead_stores_better.rs:+1:9: +1:10
+ let mut _3: usize; // in scope 0 at $DIR/dead_stores_better.rs:+3:9: +3:10
+ let mut _4: usize; // in scope 0 at $DIR/dead_stores_better.rs:+4:8: +4:9
+ scope 1 {
+ debug b => _2; // in scope 1 at $DIR/dead_stores_better.rs:+1:9: +1:10
+ }
+
+ bb0: {
+ _2 = _1; // scope 0 at $DIR/dead_stores_better.rs:+1:13: +1:14
+ _1 = const 5_usize; // scope 1 at $DIR/dead_stores_better.rs:+2:5: +2:10
+ _1 = _2; // scope 1 at $DIR/dead_stores_better.rs:+3:5: +3:10
+ StorageLive(_4); // scope 1 at $DIR/dead_stores_better.rs:+4:8: +4:9
+ _4 = _1; // scope 1 at $DIR/dead_stores_better.rs:+4:8: +4:9
+ _0 = id::<usize>(move _4) -> bb1; // scope 1 at $DIR/dead_stores_better.rs:+4:5: +4:10
+ // mir::Constant
+ // + span: $DIR/dead_stores_better.rs:16:5: 16:7
+ // + literal: Const { ty: fn(usize) -> usize {id::<usize>}, val: Value(<ZST>) }
+ }
+
+ bb1: {
+ StorageDead(_4); // scope 1 at $DIR/dead_stores_better.rs:+4:9: +4:10
+ return; // scope 0 at $DIR/dead_stores_better.rs:+5:2: +5:2
+ }
+}
diff --git a/tests/mir-opt/copy-prop/dead_stores_better.rs b/tests/mir-opt/copy-prop/dead_stores_better.rs
new file mode 100644
index 000000000..8465b3c98
--- /dev/null
+++ b/tests/mir-opt/copy-prop/dead_stores_better.rs
@@ -0,0 +1,21 @@
+// This is a copy of the `dead_stores_79191` test, except that we turn on DSE. This demonstrates
+// that that pass enables this one to do more optimizations.
+
+// unit-test: CopyProp
+// compile-flags: -Zmir-enable-passes=+DeadStoreElimination
+
+fn id<T>(x: T) -> T {
+ x
+}
+
+// EMIT_MIR dead_stores_better.f.CopyProp.after.mir
+pub fn f(mut a: usize) -> usize {
+ let b = a;
+ a = 5;
+ a = b;
+ id(a)
+}
+
+fn main() {
+ f(0);
+}
diff --git a/tests/mir-opt/copy-prop/issue_107511.main.CopyProp.diff b/tests/mir-opt/copy-prop/issue_107511.main.CopyProp.diff
new file mode 100644
index 000000000..97d0a01e0
--- /dev/null
+++ b/tests/mir-opt/copy-prop/issue_107511.main.CopyProp.diff
@@ -0,0 +1,138 @@
+- // MIR for `main` before CopyProp
++ // MIR for `main` after CopyProp
+
+ fn main() -> () {
+ let mut _0: (); // return place in scope 0 at $DIR/issue_107511.rs:+0:11: +0:11
+ let mut _1: i32; // in scope 0 at $DIR/issue_107511.rs:+1:9: +1:16
+ let mut _3: std::ops::Range<usize>; // in scope 0 at $DIR/issue_107511.rs:+6:14: +6:24
+ let mut _4: std::ops::Range<usize>; // in scope 0 at $DIR/issue_107511.rs:+6:14: +6:24
+ let mut _5: usize; // in scope 0 at $DIR/issue_107511.rs:+6:17: +6:24
+ let mut _6: &[i32]; // in scope 0 at $DIR/issue_107511.rs:+6:17: +6:24
+ let mut _7: &[i32; 4]; // in scope 0 at $DIR/issue_107511.rs:+6:17: +6:24
+ let mut _9: (); // in scope 0 at $DIR/issue_107511.rs:+0:1: +9:2
+ let _10: (); // in scope 0 at $DIR/issue_107511.rs:+6:14: +6:24
+ let mut _11: std::option::Option<usize>; // in scope 0 at $DIR/issue_107511.rs:+6:14: +6:24
+ let mut _12: &mut std::ops::Range<usize>; // in scope 0 at $DIR/issue_107511.rs:+6:14: +6:24
+ let mut _13: &mut std::ops::Range<usize>; // in scope 0 at $DIR/issue_107511.rs:+6:14: +6:24
+ let mut _14: isize; // in scope 0 at $DIR/issue_107511.rs:+6:5: +8:6
+ let mut _15: !; // in scope 0 at $DIR/issue_107511.rs:+6:5: +8:6
+ let mut _17: i32; // in scope 0 at $DIR/issue_107511.rs:+7:16: +7:20
+ let _18: usize; // in scope 0 at $DIR/issue_107511.rs:+7:18: +7:19
+ let mut _19: usize; // in scope 0 at $DIR/issue_107511.rs:+7:16: +7:20
+ let mut _20: bool; // in scope 0 at $DIR/issue_107511.rs:+7:16: +7:20
+ scope 1 {
+ debug sum => _1; // in scope 1 at $DIR/issue_107511.rs:+1:9: +1:16
+ let _2: [i32; 4]; // in scope 1 at $DIR/issue_107511.rs:+2:9: +2:10
+ scope 2 {
+ debug a => _2; // in scope 2 at $DIR/issue_107511.rs:+2:9: +2:10
+ let mut _8: std::ops::Range<usize>; // in scope 2 at $DIR/issue_107511.rs:+6:14: +6:24
+ scope 3 {
+ debug iter => _8; // in scope 3 at $DIR/issue_107511.rs:+6:14: +6:24
+ let _16: usize; // in scope 3 at $DIR/issue_107511.rs:+6:9: +6:10
+ scope 4 {
+ debug i => _16; // in scope 4 at $DIR/issue_107511.rs:+6:9: +6:10
+ }
+ }
+ }
+ }
+
+ bb0: {
+ StorageLive(_1); // scope 0 at $DIR/issue_107511.rs:+1:9: +1:16
+ _1 = const 0_i32; // scope 0 at $DIR/issue_107511.rs:+1:19: +1:20
+ StorageLive(_2); // scope 1 at $DIR/issue_107511.rs:+2:9: +2:10
+ _2 = [const 0_i32, const 10_i32, const 20_i32, const 30_i32]; // scope 1 at $DIR/issue_107511.rs:+2:13: +2:28
+ StorageLive(_3); // scope 2 at $DIR/issue_107511.rs:+6:14: +6:24
+ StorageLive(_4); // scope 2 at $DIR/issue_107511.rs:+6:14: +6:24
+ StorageLive(_5); // scope 2 at $DIR/issue_107511.rs:+6:17: +6:24
+ StorageLive(_6); // scope 2 at $DIR/issue_107511.rs:+6:17: +6:24
+ StorageLive(_7); // scope 2 at $DIR/issue_107511.rs:+6:17: +6:24
+ _7 = &_2; // scope 2 at $DIR/issue_107511.rs:+6:17: +6:24
+ _6 = move _7 as &[i32] (Pointer(Unsize)); // scope 2 at $DIR/issue_107511.rs:+6:17: +6:24
+ StorageDead(_7); // scope 2 at $DIR/issue_107511.rs:+6:17: +6:18
+ _5 = core::slice::<impl [i32]>::len(move _6) -> bb1; // scope 2 at $DIR/issue_107511.rs:+6:17: +6:24
+ // mir::Constant
+ // + span: $DIR/issue_107511.rs:10:19: 10:22
+ // + literal: Const { ty: for<'a> fn(&'a [i32]) -> usize {core::slice::<impl [i32]>::len}, val: Value(<ZST>) }
+ }
+
+ bb1: {
+ StorageDead(_6); // scope 2 at $DIR/issue_107511.rs:+6:23: +6:24
+ _4 = std::ops::Range::<usize> { start: const 0_usize, end: move _5 }; // scope 2 at $DIR/issue_107511.rs:+6:14: +6:24
+ StorageDead(_5); // scope 2 at $DIR/issue_107511.rs:+6:23: +6:24
+ _3 = <std::ops::Range<usize> as IntoIterator>::into_iter(move _4) -> bb2; // scope 2 at $DIR/issue_107511.rs:+6:14: +6:24
+ // mir::Constant
+ // + span: $DIR/issue_107511.rs:10:14: 10:24
+ // + literal: Const { ty: fn(std::ops::Range<usize>) -> <std::ops::Range<usize> as IntoIterator>::IntoIter {<std::ops::Range<usize> as IntoIterator>::into_iter}, val: Value(<ZST>) }
+ }
+
+ bb2: {
+ StorageDead(_4); // scope 2 at $DIR/issue_107511.rs:+6:23: +6:24
+ StorageLive(_8); // scope 2 at $DIR/issue_107511.rs:+6:14: +6:24
+ _8 = move _3; // scope 2 at $DIR/issue_107511.rs:+6:14: +6:24
+ goto -> bb3; // scope 3 at $DIR/issue_107511.rs:+6:5: +8:6
+ }
+
+ bb3: {
+- StorageLive(_10); // scope 3 at $DIR/issue_107511.rs:+6:14: +6:24
+ StorageLive(_11); // scope 3 at $DIR/issue_107511.rs:+6:14: +6:24
+ StorageLive(_12); // scope 3 at $DIR/issue_107511.rs:+6:14: +6:24
+ StorageLive(_13); // scope 3 at $DIR/issue_107511.rs:+6:14: +6:24
+ _13 = &mut _8; // scope 3 at $DIR/issue_107511.rs:+6:14: +6:24
+ _12 = &mut (*_13); // scope 3 at $DIR/issue_107511.rs:+6:14: +6:24
+ _11 = <std::ops::Range<usize> as Iterator>::next(move _12) -> bb4; // scope 3 at $DIR/issue_107511.rs:+6:14: +6:24
+ // mir::Constant
+ // + span: $DIR/issue_107511.rs:10:14: 10:24
+ // + literal: Const { ty: for<'a> fn(&'a mut std::ops::Range<usize>) -> Option<<std::ops::Range<usize> as Iterator>::Item> {<std::ops::Range<usize> as Iterator>::next}, val: Value(<ZST>) }
+ }
+
+ bb4: {
+ StorageDead(_12); // scope 3 at $DIR/issue_107511.rs:+6:23: +6:24
+ _14 = discriminant(_11); // scope 3 at $DIR/issue_107511.rs:+6:14: +6:24
+ switchInt(move _14) -> [0: bb7, 1: bb5, otherwise: bb6]; // scope 3 at $DIR/issue_107511.rs:+6:14: +6:24
+ }
+
+ bb5: {
+- StorageLive(_16); // scope 3 at $DIR/issue_107511.rs:+6:9: +6:10
+ _16 = ((_11 as Some).0: usize); // scope 3 at $DIR/issue_107511.rs:+6:9: +6:10
+ StorageLive(_17); // scope 4 at $DIR/issue_107511.rs:+7:16: +7:20
+- StorageLive(_18); // scope 4 at $DIR/issue_107511.rs:+7:18: +7:19
+- _18 = _16; // scope 4 at $DIR/issue_107511.rs:+7:18: +7:19
+ _19 = Len(_2); // scope 4 at $DIR/issue_107511.rs:+7:16: +7:20
+- _20 = Lt(_18, _19); // scope 4 at $DIR/issue_107511.rs:+7:16: +7:20
+- assert(move _20, "index out of bounds: the length is {} but the index is {}", move _19, _18) -> bb8; // scope 4 at $DIR/issue_107511.rs:+7:16: +7:20
++ _20 = Lt(_16, _19); // scope 4 at $DIR/issue_107511.rs:+7:16: +7:20
++ assert(move _20, "index out of bounds: the length is {} but the index is {}", move _19, _16) -> bb8; // scope 4 at $DIR/issue_107511.rs:+7:16: +7:20
+ }
+
+ bb6: {
+ unreachable; // scope 3 at $DIR/issue_107511.rs:+6:14: +6:24
+ }
+
+ bb7: {
+ _0 = const (); // scope 3 at $DIR/issue_107511.rs:+6:5: +8:6
+ StorageDead(_13); // scope 3 at $DIR/issue_107511.rs:+8:5: +8:6
+ StorageDead(_11); // scope 3 at $DIR/issue_107511.rs:+8:5: +8:6
+- StorageDead(_10); // scope 3 at $DIR/issue_107511.rs:+8:5: +8:6
+ StorageDead(_8); // scope 2 at $DIR/issue_107511.rs:+8:5: +8:6
+ StorageDead(_3); // scope 2 at $DIR/issue_107511.rs:+8:5: +8:6
+ StorageDead(_2); // scope 1 at $DIR/issue_107511.rs:+9:1: +9:2
+ StorageDead(_1); // scope 0 at $DIR/issue_107511.rs:+9:1: +9:2
+ return; // scope 0 at $DIR/issue_107511.rs:+9:2: +9:2
+ }
+
+ bb8: {
+- _17 = _2[_18]; // scope 4 at $DIR/issue_107511.rs:+7:16: +7:20
++ _17 = _2[_16]; // scope 4 at $DIR/issue_107511.rs:+7:16: +7:20
+ _1 = Add(_1, move _17); // scope 4 at $DIR/issue_107511.rs:+7:9: +7:20
+ StorageDead(_17); // scope 4 at $DIR/issue_107511.rs:+7:19: +7:20
+- StorageDead(_18); // scope 4 at $DIR/issue_107511.rs:+7:20: +7:21
+- _10 = const (); // scope 4 at $DIR/issue_107511.rs:+6:25: +8:6
+- StorageDead(_16); // scope 3 at $DIR/issue_107511.rs:+8:5: +8:6
+ StorageDead(_13); // scope 3 at $DIR/issue_107511.rs:+8:5: +8:6
+ StorageDead(_11); // scope 3 at $DIR/issue_107511.rs:+8:5: +8:6
+- StorageDead(_10); // scope 3 at $DIR/issue_107511.rs:+8:5: +8:6
+- _9 = const (); // scope 3 at $DIR/issue_107511.rs:+6:5: +8:6
+ goto -> bb3; // scope 3 at $DIR/issue_107511.rs:+6:5: +8:6
+ }
+ }
+
diff --git a/tests/mir-opt/copy-prop/issue_107511.rs b/tests/mir-opt/copy-prop/issue_107511.rs
new file mode 100644
index 000000000..d593f2872
--- /dev/null
+++ b/tests/mir-opt/copy-prop/issue_107511.rs
@@ -0,0 +1,13 @@
+// unit-test: CopyProp
+
+// EMIT_MIR issue_107511.main.CopyProp.diff
+fn main() {
+ let mut sum = 0;
+ let a = [0, 10, 20, 30];
+
+ // `i` is assigned in a loop. Only removing its `StorageDead` would mean that
+ // execution sees repeated `StorageLive`. This would be UB.
+ for i in 0..a.len() {
+ sum += a[i];
+ }
+}
diff --git a/tests/mir-opt/copy-prop/move_arg.f.CopyProp.diff b/tests/mir-opt/copy-prop/move_arg.f.CopyProp.diff
new file mode 100644
index 000000000..d76bf1cfe
--- /dev/null
+++ b/tests/mir-opt/copy-prop/move_arg.f.CopyProp.diff
@@ -0,0 +1,40 @@
+- // MIR for `f` before CopyProp
++ // MIR for `f` after CopyProp
+
+ fn f(_1: T) -> () {
+ debug a => _1; // in scope 0 at $DIR/move_arg.rs:+0:19: +0:20
+ let mut _0: (); // return place in scope 0 at $DIR/move_arg.rs:+0:25: +0:25
+ let _2: T; // in scope 0 at $DIR/move_arg.rs:+1:9: +1:10
+ let _3: (); // in scope 0 at $DIR/move_arg.rs:+2:5: +2:12
+ let mut _4: T; // in scope 0 at $DIR/move_arg.rs:+2:7: +2:8
+ let mut _5: T; // in scope 0 at $DIR/move_arg.rs:+2:10: +2:11
+ scope 1 {
+- debug b => _2; // in scope 1 at $DIR/move_arg.rs:+1:9: +1:10
++ debug b => _1; // in scope 1 at $DIR/move_arg.rs:+1:9: +1:10
+ }
+
+ bb0: {
+- StorageLive(_2); // scope 0 at $DIR/move_arg.rs:+1:9: +1:10
+- _2 = _1; // scope 0 at $DIR/move_arg.rs:+1:13: +1:14
+ StorageLive(_3); // scope 1 at $DIR/move_arg.rs:+2:5: +2:12
+- StorageLive(_4); // scope 1 at $DIR/move_arg.rs:+2:7: +2:8
+- _4 = _1; // scope 1 at $DIR/move_arg.rs:+2:7: +2:8
+- StorageLive(_5); // scope 1 at $DIR/move_arg.rs:+2:10: +2:11
+- _5 = _2; // scope 1 at $DIR/move_arg.rs:+2:10: +2:11
+- _3 = g::<T>(move _4, move _5) -> bb1; // scope 1 at $DIR/move_arg.rs:+2:5: +2:12
++ _3 = g::<T>(_1, _1) -> bb1; // scope 1 at $DIR/move_arg.rs:+2:5: +2:12
+ // mir::Constant
+ // + span: $DIR/move_arg.rs:7:5: 7:6
+ // + literal: Const { ty: fn(T, T) {g::<T>}, val: Value(<ZST>) }
+ }
+
+ bb1: {
+- StorageDead(_5); // scope 1 at $DIR/move_arg.rs:+2:11: +2:12
+- StorageDead(_4); // scope 1 at $DIR/move_arg.rs:+2:11: +2:12
+ StorageDead(_3); // scope 1 at $DIR/move_arg.rs:+2:12: +2:13
+ _0 = const (); // scope 0 at $DIR/move_arg.rs:+0:25: +3:2
+- StorageDead(_2); // scope 0 at $DIR/move_arg.rs:+3:1: +3:2
+ return; // scope 0 at $DIR/move_arg.rs:+3:2: +3:2
+ }
+ }
+
diff --git a/tests/mir-opt/copy-prop/move_arg.rs b/tests/mir-opt/copy-prop/move_arg.rs
new file mode 100644
index 000000000..40ae1d8f4
--- /dev/null
+++ b/tests/mir-opt/copy-prop/move_arg.rs
@@ -0,0 +1,15 @@
+// Test that we do not move multiple times from the same local.
+// unit-test: CopyProp
+
+// EMIT_MIR move_arg.f.CopyProp.diff
+pub fn f<T: Copy>(a: T) {
+ let b = a;
+ g(a, b);
+}
+
+#[inline(never)]
+pub fn g<T: Copy>(_: T, _: T) {}
+
+fn main() {
+ f(5)
+}
diff --git a/tests/mir-opt/copy-prop/move_projection.f.CopyProp.diff b/tests/mir-opt/copy-prop/move_projection.f.CopyProp.diff
new file mode 100644
index 000000000..02308beb8
--- /dev/null
+++ b/tests/mir-opt/copy-prop/move_projection.f.CopyProp.diff
@@ -0,0 +1,31 @@
+- // MIR for `f` before CopyProp
++ // MIR for `f` after CopyProp
+
+ fn f(_1: Foo) -> bool {
+ let mut _0: bool; // return place in scope 0 at $DIR/move_projection.rs:+0:17: +0:21
+ let mut _2: Foo; // in scope 0 at $SRC_DIR/core/src/intrinsics/mir.rs:LL:COL
+ let mut _3: u8; // in scope 0 at $SRC_DIR/core/src/intrinsics/mir.rs:LL:COL
+
+ bb0: {
+- _2 = _1; // scope 0 at $SRC_DIR/core/src/intrinsics/mir.rs:LL:COL
+- _3 = move (_2.0: u8); // scope 0 at $SRC_DIR/core/src/intrinsics/mir.rs:LL:COL
+- _0 = opaque::<Foo>(move _1) -> bb1; // scope 0 at $DIR/move_projection.rs:+6:13: +6:44
++ _3 = (_1.0: u8); // scope 0 at $SRC_DIR/core/src/intrinsics/mir.rs:LL:COL
++ _0 = opaque::<Foo>(_1) -> bb1; // scope 0 at $DIR/move_projection.rs:+6:13: +6:44
+ // mir::Constant
+ // + span: $DIR/move_projection.rs:19:28: 19:34
+ // + literal: Const { ty: fn(Foo) -> bool {opaque::<Foo>}, val: Value(<ZST>) }
+ }
+
+ bb1: {
+ _0 = opaque::<u8>(move _3) -> bb2; // scope 0 at $DIR/move_projection.rs:+9:13: +9:44
+ // mir::Constant
+ // + span: $DIR/move_projection.rs:22:28: 22:34
+ // + literal: Const { ty: fn(u8) -> bool {opaque::<u8>}, val: Value(<ZST>) }
+ }
+
+ bb2: {
+ return; // scope 0 at $DIR/move_projection.rs:+12:13: +12:21
+ }
+ }
+
diff --git a/tests/mir-opt/copy-prop/move_projection.rs b/tests/mir-opt/copy-prop/move_projection.rs
new file mode 100644
index 000000000..2a1bbae99
--- /dev/null
+++ b/tests/mir-opt/copy-prop/move_projection.rs
@@ -0,0 +1,34 @@
+// unit-test: CopyProp
+
+#![feature(custom_mir, core_intrinsics)]
+#![allow(unused_assignments)]
+extern crate core;
+use core::intrinsics::mir::*;
+
+fn opaque(_: impl Sized) -> bool { true }
+
+struct Foo(u8);
+
+#[custom_mir(dialect = "analysis", phase = "post-cleanup")]
+fn f(a: Foo) -> bool {
+ mir!(
+ {
+ let b = a;
+ // This is a move out of a copy, so must become a copy of `a.0`.
+ let c = Move(b.0);
+ Call(RET, bb1, opaque(Move(a)))
+ }
+ bb1 = {
+ Call(RET, ret, opaque(Move(c)))
+ }
+ ret = {
+ Return()
+ }
+ )
+}
+
+fn main() {
+ assert!(f(Foo(0)));
+}
+
+// EMIT_MIR move_projection.f.CopyProp.diff
diff --git a/tests/mir-opt/copy-prop/mutate_through_pointer.f.CopyProp.diff b/tests/mir-opt/copy-prop/mutate_through_pointer.f.CopyProp.diff
new file mode 100644
index 000000000..61fdd6f8c
--- /dev/null
+++ b/tests/mir-opt/copy-prop/mutate_through_pointer.f.CopyProp.diff
@@ -0,0 +1,19 @@
+- // MIR for `f` before CopyProp
++ // MIR for `f` after CopyProp
+
+ fn f(_1: bool) -> bool {
+ let mut _0: bool; // return place in scope 0 at $DIR/mutate_through_pointer.rs:+0:18: +0:22
+ let mut _2: bool; // in scope 0 at $SRC_DIR/core/src/intrinsics/mir.rs:LL:COL
+ let mut _3: *const bool; // in scope 0 at $SRC_DIR/core/src/intrinsics/mir.rs:LL:COL
+ let mut _4: *mut bool; // in scope 0 at $SRC_DIR/core/src/intrinsics/mir.rs:LL:COL
+
+ bb0: {
+ _2 = _1; // scope 0 at $SRC_DIR/core/src/intrinsics/mir.rs:LL:COL
+ _3 = &raw const _2; // scope 0 at $SRC_DIR/core/src/intrinsics/mir.rs:LL:COL
+ _4 = &raw mut (*_3); // scope 0 at $SRC_DIR/core/src/intrinsics/mir.rs:LL:COL
+ (*_4) = const false; // scope 0 at $DIR/mutate_through_pointer.rs:+5:9: +5:20
+ _0 = _1; // scope 0 at $DIR/mutate_through_pointer.rs:+6:9: +6:16
+ return; // scope 0 at $DIR/mutate_through_pointer.rs:+7:9: +7:17
+ }
+ }
+
diff --git a/tests/mir-opt/copy-prop/mutate_through_pointer.rs b/tests/mir-opt/copy-prop/mutate_through_pointer.rs
new file mode 100644
index 000000000..da142e339
--- /dev/null
+++ b/tests/mir-opt/copy-prop/mutate_through_pointer.rs
@@ -0,0 +1,32 @@
+// This attempts to mutate `a` via a pointer derived from `addr_of!(a)`. That is UB
+// according to Miri. However, the decision to make this UB - and to allow
+// rustc to rely on that fact for the purpose of optimizations - has not been
+// finalized.
+//
+// As such, we include this test to ensure that copy prop does not rely on that
+// fact. Specifically, if `addr_of!(a)` could not be used to modify a, it would
+// be correct for CopyProp to replace all occurrences of `a` with `c` - but that
+// would cause `f(true)` to output `false` instead of `true`.
+
+#![feature(custom_mir, core_intrinsics)]
+#![allow(unused_assignments)]
+extern crate core;
+use core::intrinsics::mir::*;
+
+#[custom_mir(dialect = "analysis", phase = "post-cleanup")]
+fn f(c: bool) -> bool {
+ mir!({
+ let a = c;
+ let p = core::ptr::addr_of!(a);
+ let p2 = core::ptr::addr_of_mut!(*p);
+ *p2 = false;
+ RET = c;
+ Return()
+ })
+}
+
+fn main() {
+ assert_eq!(true, f(true));
+}
+
+// EMIT_MIR mutate_through_pointer.f.CopyProp.diff
diff --git a/tests/mir-opt/copy-prop/non_dominate.f.CopyProp.diff b/tests/mir-opt/copy-prop/non_dominate.f.CopyProp.diff
new file mode 100644
index 000000000..9760fd374
--- /dev/null
+++ b/tests/mir-opt/copy-prop/non_dominate.f.CopyProp.diff
@@ -0,0 +1,29 @@
+- // MIR for `f` before CopyProp
++ // MIR for `f` after CopyProp
+
+ fn f(_1: bool) -> bool {
+ let mut _0: bool; // return place in scope 0 at $DIR/non_dominate.rs:+0:18: +0:22
+ let mut _2: bool; // in scope 0 at $SRC_DIR/core/src/intrinsics/mir.rs:LL:COL
+ let mut _3: bool; // in scope 0 at $SRC_DIR/core/src/intrinsics/mir.rs:LL:COL
+
+ bb0: {
+ goto -> bb1; // scope 0 at $DIR/non_dominate.rs:+4:11: +4:20
+ }
+
+ bb1: {
+ _3 = _1; // scope 0 at $DIR/non_dominate.rs:+5:17: +5:22
+ switchInt(_3) -> [0: bb3, otherwise: bb2]; // scope 0 at $DIR/non_dominate.rs:+5:24: +5:58
+ }
+
+ bb2: {
+ _2 = _3; // scope 0 at $DIR/non_dominate.rs:+8:17: +8:22
+ _1 = const false; // scope 0 at $DIR/non_dominate.rs:+8:24: +8:33
+ goto -> bb1; // scope 0 at $DIR/non_dominate.rs:+8:35: +8:44
+ }
+
+ bb3: {
+ _0 = _2; // scope 0 at $DIR/non_dominate.rs:+9:17: +9:24
+ return; // scope 0 at $DIR/non_dominate.rs:+9:26: +9:34
+ }
+ }
+
diff --git a/tests/mir-opt/copy-prop/non_dominate.rs b/tests/mir-opt/copy-prop/non_dominate.rs
new file mode 100644
index 000000000..c0ea838e1
--- /dev/null
+++ b/tests/mir-opt/copy-prop/non_dominate.rs
@@ -0,0 +1,26 @@
+// unit-test: CopyProp
+
+#![feature(custom_mir, core_intrinsics)]
+#![allow(unused_assignments)]
+extern crate core;
+use core::intrinsics::mir::*;
+
+#[custom_mir(dialect = "analysis", phase = "post-cleanup")]
+fn f(c: bool) -> bool {
+ mir!(
+ let a: bool;
+ let b: bool;
+ { Goto(bb1) }
+ bb1 = { b = c; match b { false => bb3, _ => bb2 }}
+ // This assignment to `a` does not dominate the use in `bb3`.
+ // It should not be replaced by `b`.
+ bb2 = { a = b; c = false; Goto(bb1) }
+ bb3 = { RET = a; Return() }
+ )
+}
+
+fn main() {
+ assert_eq!(true, f(true));
+}
+
+// EMIT_MIR non_dominate.f.CopyProp.diff
diff --git a/tests/mir-opt/dataflow-const-prop/checked.main.DataflowConstProp.diff b/tests/mir-opt/dataflow-const-prop/checked.main.DataflowConstProp.diff
index a4ebd0c8c..944afed8f 100644
--- a/tests/mir-opt/dataflow-const-prop/checked.main.DataflowConstProp.diff
+++ b/tests/mir-opt/dataflow-const-prop/checked.main.DataflowConstProp.diff
@@ -61,7 +61,7 @@
- assert(!move (_10.1: bool), "attempt to compute `{} + {}`, which would overflow", move _9, const 1_i32) -> bb2; // scope 4 at $DIR/checked.rs:+6:13: +6:18
+ _9 = const i32::MAX; // scope 4 at $DIR/checked.rs:+6:13: +6:14
+ _10 = CheckedAdd(const i32::MAX, const 1_i32); // scope 4 at $DIR/checked.rs:+6:13: +6:18
-+ assert(!move (_10.1: bool), "attempt to compute `{} + {}`, which would overflow", const i32::MAX, const 1_i32) -> bb2; // scope 4 at $DIR/checked.rs:+6:13: +6:18
++ assert(!const true, "attempt to compute `{} + {}`, which would overflow", const i32::MAX, const 1_i32) -> bb2; // scope 4 at $DIR/checked.rs:+6:13: +6:18
}
bb2: {
diff --git a/tests/mir-opt/dataflow-const-prop/enum.multiple.DataflowConstProp.diff b/tests/mir-opt/dataflow-const-prop/enum.multiple.DataflowConstProp.diff
new file mode 100644
index 000000000..c4002d65e
--- /dev/null
+++ b/tests/mir-opt/dataflow-const-prop/enum.multiple.DataflowConstProp.diff
@@ -0,0 +1,82 @@
+- // MIR for `multiple` before DataflowConstProp
++ // MIR for `multiple` after DataflowConstProp
+
+ fn multiple(_1: bool, _2: u8) -> () {
+ debug x => _1; // in scope 0 at $DIR/enum.rs:+0:13: +0:14
+ debug i => _2; // in scope 0 at $DIR/enum.rs:+0:22: +0:23
+ let mut _0: (); // return place in scope 0 at $DIR/enum.rs:+0:29: +0:29
+ let _3: std::option::Option<u8>; // in scope 0 at $DIR/enum.rs:+1:9: +1:10
+ let mut _4: bool; // in scope 0 at $DIR/enum.rs:+1:16: +1:17
+ let mut _5: u8; // in scope 0 at $DIR/enum.rs:+2:14: +2:15
+ let mut _7: isize; // in scope 0 at $DIR/enum.rs:+9:23: +9:30
+ scope 1 {
+ debug e => _3; // in scope 1 at $DIR/enum.rs:+1:9: +1:10
+ let _6: u8; // in scope 1 at $DIR/enum.rs:+9:9: +9:10
+ let _8: u8; // in scope 1 at $DIR/enum.rs:+9:28: +9:29
+ scope 2 {
+ debug x => _6; // in scope 2 at $DIR/enum.rs:+9:9: +9:10
+ let _9: u8; // in scope 2 at $DIR/enum.rs:+11:9: +11:10
+ scope 4 {
+ debug y => _9; // in scope 4 at $DIR/enum.rs:+11:9: +11:10
+ }
+ }
+ scope 3 {
+ debug i => _8; // in scope 3 at $DIR/enum.rs:+9:28: +9:29
+ }
+ }
+
+ bb0: {
+ StorageLive(_3); // scope 0 at $DIR/enum.rs:+1:9: +1:10
+ StorageLive(_4); // scope 0 at $DIR/enum.rs:+1:16: +1:17
+ _4 = _1; // scope 0 at $DIR/enum.rs:+1:16: +1:17
+ switchInt(move _4) -> [0: bb2, otherwise: bb1]; // scope 0 at $DIR/enum.rs:+1:16: +1:17
+ }
+
+ bb1: {
+ StorageLive(_5); // scope 0 at $DIR/enum.rs:+2:14: +2:15
+ _5 = _2; // scope 0 at $DIR/enum.rs:+2:14: +2:15
+ _3 = Option::<u8>::Some(move _5); // scope 0 at $DIR/enum.rs:+2:9: +2:16
+ StorageDead(_5); // scope 0 at $DIR/enum.rs:+2:15: +2:16
+ goto -> bb3; // scope 0 at $DIR/enum.rs:+1:13: +5:6
+ }
+
+ bb2: {
+ _3 = Option::<u8>::None; // scope 0 at $DIR/enum.rs:+4:9: +4:13
+ goto -> bb3; // scope 0 at $DIR/enum.rs:+1:13: +5:6
+ }
+
+ bb3: {
+ StorageDead(_4); // scope 0 at $DIR/enum.rs:+5:5: +5:6
+ StorageLive(_6); // scope 1 at $DIR/enum.rs:+9:9: +9:10
+ _7 = discriminant(_3); // scope 1 at $DIR/enum.rs:+9:19: +9:20
+ switchInt(move _7) -> [0: bb4, 1: bb6, otherwise: bb5]; // scope 1 at $DIR/enum.rs:+9:13: +9:20
+ }
+
+ bb4: {
+ _6 = const 0_u8; // scope 1 at $DIR/enum.rs:+9:45: +9:46
+ goto -> bb7; // scope 1 at $DIR/enum.rs:+9:45: +9:46
+ }
+
+ bb5: {
+ unreachable; // scope 1 at $DIR/enum.rs:+9:19: +9:20
+ }
+
+ bb6: {
+ StorageLive(_8); // scope 1 at $DIR/enum.rs:+9:28: +9:29
+ _8 = ((_3 as Some).0: u8); // scope 1 at $DIR/enum.rs:+9:28: +9:29
+ _6 = _8; // scope 3 at $DIR/enum.rs:+9:34: +9:35
+ StorageDead(_8); // scope 1 at $DIR/enum.rs:+9:34: +9:35
+ goto -> bb7; // scope 1 at $DIR/enum.rs:+9:34: +9:35
+ }
+
+ bb7: {
+ StorageLive(_9); // scope 2 at $DIR/enum.rs:+11:9: +11:10
+ _9 = _6; // scope 2 at $DIR/enum.rs:+11:13: +11:14
+ _0 = const (); // scope 0 at $DIR/enum.rs:+0:29: +12:2
+ StorageDead(_9); // scope 2 at $DIR/enum.rs:+12:1: +12:2
+ StorageDead(_6); // scope 1 at $DIR/enum.rs:+12:1: +12:2
+ StorageDead(_3); // scope 0 at $DIR/enum.rs:+12:1: +12:2
+ return; // scope 0 at $DIR/enum.rs:+12:2: +12:2
+ }
+ }
+
diff --git a/tests/mir-opt/dataflow-const-prop/enum.mutate_discriminant.DataflowConstProp.diff b/tests/mir-opt/dataflow-const-prop/enum.mutate_discriminant.DataflowConstProp.diff
new file mode 100644
index 000000000..038e6c6bd
--- /dev/null
+++ b/tests/mir-opt/dataflow-const-prop/enum.mutate_discriminant.DataflowConstProp.diff
@@ -0,0 +1,26 @@
+- // MIR for `mutate_discriminant` before DataflowConstProp
++ // MIR for `mutate_discriminant` after DataflowConstProp
+
+ fn mutate_discriminant() -> u8 {
+ let mut _0: u8; // return place in scope 0 at $DIR/enum.rs:+0:29: +0:31
+ let mut _1: std::option::Option<NonZeroUsize>; // in scope 0 at $SRC_DIR/core/src/intrinsics/mir.rs:LL:COL
+ let mut _2: isize; // in scope 0 at $SRC_DIR/core/src/intrinsics/mir.rs:LL:COL
+
+ bb0: {
+ discriminant(_1) = 1; // scope 0 at $DIR/enum.rs:+4:13: +4:34
+ (((_1 as variant#1).0: NonZeroUsize).0: usize) = const 0_usize; // scope 0 at $DIR/enum.rs:+6:13: +6:64
+ _2 = discriminant(_1); // scope 0 at $SRC_DIR/core/src/intrinsics/mir.rs:LL:COL
+ switchInt(_2) -> [0: bb1, otherwise: bb2]; // scope 0 at $DIR/enum.rs:+9:13: +12:14
+ }
+
+ bb1: {
+ _0 = const 1_u8; // scope 0 at $DIR/enum.rs:+15:13: +15:20
+ return; // scope 0 at $DIR/enum.rs:+16:13: +16:21
+ }
+
+ bb2: {
+ _0 = const 2_u8; // scope 0 at $DIR/enum.rs:+19:13: +19:20
+ unreachable; // scope 0 at $DIR/enum.rs:+20:13: +20:26
+ }
+ }
+
diff --git a/tests/mir-opt/dataflow-const-prop/enum.rs b/tests/mir-opt/dataflow-const-prop/enum.rs
index 13288577d..79a20d7ef 100644
--- a/tests/mir-opt/dataflow-const-prop/enum.rs
+++ b/tests/mir-opt/dataflow-const-prop/enum.rs
@@ -1,13 +1,68 @@
// unit-test: DataflowConstProp
-// Not trackable, because variants could be aliased.
+#![feature(custom_mir, core_intrinsics, rustc_attrs)]
+
+use std::intrinsics::mir::*;
+
enum E {
V1(i32),
V2(i32)
}
-// EMIT_MIR enum.main.DataflowConstProp.diff
-fn main() {
+// EMIT_MIR enum.simple.DataflowConstProp.diff
+fn simple() {
let e = E::V1(0);
let x = match e { E::V1(x) => x, E::V2(x) => x };
}
+
+#[rustc_layout_scalar_valid_range_start(1)]
+#[rustc_nonnull_optimization_guaranteed]
+struct NonZeroUsize(usize);
+
+// EMIT_MIR enum.mutate_discriminant.DataflowConstProp.diff
+#[custom_mir(dialect = "runtime", phase = "post-cleanup")]
+fn mutate_discriminant() -> u8 {
+ mir!(
+ let x: Option<NonZeroUsize>;
+ {
+ SetDiscriminant(x, 1);
+ // This assignment overwrites the niche in which the discriminant is stored.
+ place!(Field(Field(Variant(x, 1), 0), 0)) = 0_usize;
+ // So we cannot know the value of this discriminant.
+ let a = Discriminant(x);
+ match a {
+ 0 => bb1,
+ _ => bad,
+ }
+ }
+ bb1 = {
+ RET = 1;
+ Return()
+ }
+ bad = {
+ RET = 2;
+ Unreachable()
+ }
+ )
+}
+
+// EMIT_MIR enum.multiple.DataflowConstProp.diff
+fn multiple(x: bool, i: u8) {
+ let e = if x {
+ Some(i)
+ } else {
+ None
+ };
+ // The dataflow state must have:
+ // discriminant(e) => Top
+ // (e as Some).0 => Top
+ let x = match e { Some(i) => i, None => 0 };
+ // Therefore, `x` should be `Top` here, and no replacement shall happen.
+ let y = x;
+}
+
+fn main() {
+ simple();
+ mutate_discriminant();
+ multiple(false, 5);
+}
diff --git a/tests/mir-opt/dataflow-const-prop/enum.main.DataflowConstProp.diff b/tests/mir-opt/dataflow-const-prop/enum.simple.DataflowConstProp.diff
index fce18fae4..22bdc35d6 100644
--- a/tests/mir-opt/dataflow-const-prop/enum.main.DataflowConstProp.diff
+++ b/tests/mir-opt/dataflow-const-prop/enum.simple.DataflowConstProp.diff
@@ -1,8 +1,8 @@
-- // MIR for `main` before DataflowConstProp
-+ // MIR for `main` after DataflowConstProp
+- // MIR for `simple` before DataflowConstProp
++ // MIR for `simple` after DataflowConstProp
- fn main() -> () {
- let mut _0: (); // return place in scope 0 at $DIR/enum.rs:+0:11: +0:11
+ fn simple() -> () {
+ let mut _0: (); // return place in scope 0 at $DIR/enum.rs:+0:13: +0:13
let _1: E; // in scope 0 at $DIR/enum.rs:+1:9: +1:10
let mut _3: isize; // in scope 0 at $DIR/enum.rs:+2:23: +2:31
scope 1 {
@@ -23,12 +23,12 @@
bb0: {
StorageLive(_1); // scope 0 at $DIR/enum.rs:+1:9: +1:10
- Deinit(_1); // scope 0 at $DIR/enum.rs:+1:13: +1:21
- ((_1 as V1).0: i32) = const 0_i32; // scope 0 at $DIR/enum.rs:+1:13: +1:21
- discriminant(_1) = 0; // scope 0 at $DIR/enum.rs:+1:13: +1:21
+ _1 = E::V1(const 0_i32); // scope 0 at $DIR/enum.rs:+1:13: +1:21
StorageLive(_2); // scope 1 at $DIR/enum.rs:+2:9: +2:10
- _3 = discriminant(_1); // scope 1 at $DIR/enum.rs:+2:19: +2:20
- switchInt(move _3) -> [0: bb3, 1: bb1, otherwise: bb2]; // scope 1 at $DIR/enum.rs:+2:13: +2:20
+- _3 = discriminant(_1); // scope 1 at $DIR/enum.rs:+2:19: +2:20
+- switchInt(move _3) -> [0: bb3, 1: bb1, otherwise: bb2]; // scope 1 at $DIR/enum.rs:+2:13: +2:20
++ _3 = const 0_isize; // scope 1 at $DIR/enum.rs:+2:19: +2:20
++ switchInt(const 0_isize) -> [0: bb3, 1: bb1, otherwise: bb2]; // scope 1 at $DIR/enum.rs:+2:13: +2:20
}
bb1: {
@@ -45,14 +45,16 @@
bb3: {
StorageLive(_4); // scope 1 at $DIR/enum.rs:+2:29: +2:30
- _4 = ((_1 as V1).0: i32); // scope 1 at $DIR/enum.rs:+2:29: +2:30
- _2 = _4; // scope 3 at $DIR/enum.rs:+2:35: +2:36
+- _4 = ((_1 as V1).0: i32); // scope 1 at $DIR/enum.rs:+2:29: +2:30
+- _2 = _4; // scope 3 at $DIR/enum.rs:+2:35: +2:36
++ _4 = const 0_i32; // scope 1 at $DIR/enum.rs:+2:29: +2:30
++ _2 = const 0_i32; // scope 3 at $DIR/enum.rs:+2:35: +2:36
StorageDead(_4); // scope 1 at $DIR/enum.rs:+2:35: +2:36
goto -> bb4; // scope 1 at $DIR/enum.rs:+2:35: +2:36
}
bb4: {
- _0 = const (); // scope 0 at $DIR/enum.rs:+0:11: +3:2
+ _0 = const (); // scope 0 at $DIR/enum.rs:+0:13: +3:2
StorageDead(_2); // scope 1 at $DIR/enum.rs:+3:1: +3:2
StorageDead(_1); // scope 0 at $DIR/enum.rs:+3:1: +3:2
return; // scope 0 at $DIR/enum.rs:+3:2: +3:2
diff --git a/tests/mir-opt/dataflow-const-prop/inherit_overflow.main.DataflowConstProp.diff b/tests/mir-opt/dataflow-const-prop/inherit_overflow.main.DataflowConstProp.diff
index 02aafd7ac..29781e9ce 100644
--- a/tests/mir-opt/dataflow-const-prop/inherit_overflow.main.DataflowConstProp.diff
+++ b/tests/mir-opt/dataflow-const-prop/inherit_overflow.main.DataflowConstProp.diff
@@ -5,34 +5,34 @@
let mut _0: (); // return place in scope 0 at $DIR/inherit_overflow.rs:+0:11: +0:11
let mut _1: u8; // in scope 0 at $DIR/inherit_overflow.rs:+3:13: +3:47
let mut _2: u8; // in scope 0 at $DIR/inherit_overflow.rs:+3:13: +3:47
+ let mut _3: u8; // in scope 0 at $DIR/inherit_overflow.rs:+3:13: +3:47
scope 1 {
}
- scope 2 (inlined <u8 as Add>::add) { // at $DIR/inherit_overflow.rs:7:13: 7:47
- debug self => _1; // in scope 2 at $SRC_DIR/core/src/ops/arith.rs:LL:COL
- debug other => _2; // in scope 2 at $SRC_DIR/core/src/ops/arith.rs:LL:COL
- let mut _3: u8; // in scope 2 at $SRC_DIR/core/src/ops/arith.rs:LL:COL
- let mut _4: u8; // in scope 2 at $SRC_DIR/core/src/ops/arith.rs:LL:COL
- let mut _5: (u8, bool); // in scope 2 at $SRC_DIR/core/src/ops/arith.rs:LL:COL
+ scope 2 (inlined <u8 as Add>::add) { // at $DIR/inherit_overflow.rs:8:13: 8:47
+ debug self => _2; // in scope 2 at $SRC_DIR/core/src/ops/arith.rs:LL:COL
+ debug other => _3; // in scope 2 at $SRC_DIR/core/src/ops/arith.rs:LL:COL
+ let mut _4: (u8, bool); // in scope 2 at $SRC_DIR/core/src/ops/arith.rs:LL:COL
}
bb0: {
StorageLive(_1); // scope 0 at $DIR/inherit_overflow.rs:+3:13: +3:47
- _1 = const u8::MAX; // scope 0 at $DIR/inherit_overflow.rs:+3:13: +3:47
StorageLive(_2); // scope 0 at $DIR/inherit_overflow.rs:+3:13: +3:47
- _2 = const 1_u8; // scope 0 at $DIR/inherit_overflow.rs:+3:13: +3:47
- StorageLive(_3); // scope 2 at $SRC_DIR/core/src/ops/arith.rs:LL:COL
- _3 = const u8::MAX; // scope 2 at $SRC_DIR/core/src/ops/arith.rs:LL:COL
- StorageLive(_4); // scope 2 at $SRC_DIR/core/src/ops/arith.rs:LL:COL
- _4 = const 1_u8; // scope 2 at $SRC_DIR/core/src/ops/arith.rs:LL:COL
- _5 = CheckedAdd(const u8::MAX, const 1_u8); // scope 2 at $SRC_DIR/core/src/ops/arith.rs:LL:COL
- assert(!move (_5.1: bool), "attempt to compute `{} + {}`, which would overflow", const u8::MAX, const 1_u8) -> bb1; // scope 2 at $SRC_DIR/core/src/ops/arith.rs:LL:COL
+ _2 = const u8::MAX; // scope 0 at $DIR/inherit_overflow.rs:+3:13: +3:47
+ StorageLive(_3); // scope 0 at $DIR/inherit_overflow.rs:+3:13: +3:47
+ _3 = const 1_u8; // scope 0 at $DIR/inherit_overflow.rs:+3:13: +3:47
+- _4 = CheckedAdd(_2, _3); // scope 2 at $SRC_DIR/core/src/ops/arith.rs:LL:COL
+- assert(!move (_4.1: bool), "attempt to compute `{} + {}`, which would overflow", _2, _3) -> bb1; // scope 2 at $SRC_DIR/core/src/ops/arith.rs:LL:COL
++ _4 = CheckedAdd(const u8::MAX, const 1_u8); // scope 2 at $SRC_DIR/core/src/ops/arith.rs:LL:COL
++ assert(!const true, "attempt to compute `{} + {}`, which would overflow", const u8::MAX, const 1_u8) -> bb1; // scope 2 at $SRC_DIR/core/src/ops/arith.rs:LL:COL
}
bb1: {
- StorageDead(_4); // scope 2 at $SRC_DIR/core/src/ops/arith.rs:LL:COL
- StorageDead(_3); // scope 2 at $SRC_DIR/core/src/ops/arith.rs:LL:COL
+- _1 = move (_4.0: u8); // scope 2 at $SRC_DIR/core/src/ops/arith.rs:LL:COL
++ _1 = const 0_u8; // scope 2 at $SRC_DIR/core/src/ops/arith.rs:LL:COL
+ StorageDead(_3); // scope 0 at $DIR/inherit_overflow.rs:+3:13: +3:47
StorageDead(_2); // scope 0 at $DIR/inherit_overflow.rs:+3:13: +3:47
- StorageDead(_1); // scope 0 at $DIR/inherit_overflow.rs:+3:13: +3:47
+ StorageDead(_1); // scope 0 at $DIR/inherit_overflow.rs:+3:47: +3:48
+ _0 = const (); // scope 0 at $DIR/inherit_overflow.rs:+0:11: +4:2
return; // scope 0 at $DIR/inherit_overflow.rs:+4:2: +4:2
}
}
diff --git a/tests/mir-opt/dataflow-const-prop/inherit_overflow.rs b/tests/mir-opt/dataflow-const-prop/inherit_overflow.rs
index 2f2d9d010..f4aba60f0 100644
--- a/tests/mir-opt/dataflow-const-prop/inherit_overflow.rs
+++ b/tests/mir-opt/dataflow-const-prop/inherit_overflow.rs
@@ -1,8 +1,9 @@
-// compile-flags: -Zunsound-mir-opts
+// unit-test: DataflowConstProp
+// compile-flags: -Zmir-enable-passes=+Inline
// EMIT_MIR inherit_overflow.main.DataflowConstProp.diff
fn main() {
- // After inlining, this will contain a `CheckedBinaryOp`. The overflow
- // must be ignored by the constant propagation to avoid triggering a panic.
+ // After inlining, this will contain a `CheckedBinaryOp`.
+ // Propagating the overflow is ok as codegen will just skip emitting the panic.
let _ = <u8 as std::ops::Add>::add(255, 1);
}
diff --git a/tests/mir-opt/dataflow-const-prop/repr_transparent.main.DataflowConstProp.diff b/tests/mir-opt/dataflow-const-prop/repr_transparent.main.DataflowConstProp.diff
index f66b00a9a..8f045eedf 100644
--- a/tests/mir-opt/dataflow-const-prop/repr_transparent.main.DataflowConstProp.diff
+++ b/tests/mir-opt/dataflow-const-prop/repr_transparent.main.DataflowConstProp.diff
@@ -17,8 +17,7 @@
bb0: {
StorageLive(_1); // scope 0 at $DIR/repr_transparent.rs:+1:9: +1:10
- Deinit(_1); // scope 0 at $DIR/repr_transparent.rs:+1:13: +1:19
- (_1.0: i32) = const 0_i32; // scope 0 at $DIR/repr_transparent.rs:+1:13: +1:19
+ _1 = I32(const 0_i32); // scope 0 at $DIR/repr_transparent.rs:+1:13: +1:19
StorageLive(_2); // scope 1 at $DIR/repr_transparent.rs:+2:9: +2:10
StorageLive(_3); // scope 1 at $DIR/repr_transparent.rs:+2:17: +2:26
StorageLive(_4); // scope 1 at $DIR/repr_transparent.rs:+2:17: +2:20
@@ -31,9 +30,8 @@
+ _3 = const 0_i32; // scope 1 at $DIR/repr_transparent.rs:+2:17: +2:26
StorageDead(_5); // scope 1 at $DIR/repr_transparent.rs:+2:25: +2:26
StorageDead(_4); // scope 1 at $DIR/repr_transparent.rs:+2:25: +2:26
- Deinit(_2); // scope 1 at $DIR/repr_transparent.rs:+2:13: +2:27
-- (_2.0: i32) = move _3; // scope 1 at $DIR/repr_transparent.rs:+2:13: +2:27
-+ (_2.0: i32) = const 0_i32; // scope 1 at $DIR/repr_transparent.rs:+2:13: +2:27
+- _2 = I32(move _3); // scope 1 at $DIR/repr_transparent.rs:+2:13: +2:27
++ _2 = I32(const 0_i32); // scope 1 at $DIR/repr_transparent.rs:+2:13: +2:27
StorageDead(_3); // scope 1 at $DIR/repr_transparent.rs:+2:26: +2:27
_0 = const (); // scope 0 at $DIR/repr_transparent.rs:+0:11: +3:2
StorageDead(_2); // scope 1 at $DIR/repr_transparent.rs:+3:1: +3:2
diff --git a/tests/mir-opt/dataflow-const-prop/sibling_ptr.main.DataflowConstProp.diff b/tests/mir-opt/dataflow-const-prop/sibling_ptr.main.DataflowConstProp.diff
index 8126d4b85..004643e36 100644
--- a/tests/mir-opt/dataflow-const-prop/sibling_ptr.main.DataflowConstProp.diff
+++ b/tests/mir-opt/dataflow-const-prop/sibling_ptr.main.DataflowConstProp.diff
@@ -23,9 +23,7 @@
bb0: {
StorageLive(_1); // scope 0 at $DIR/sibling_ptr.rs:+1:9: +1:14
- Deinit(_1); // scope 0 at $DIR/sibling_ptr.rs:+1:27: +1:33
- (_1.0: u8) = const 0_u8; // scope 0 at $DIR/sibling_ptr.rs:+1:27: +1:33
- (_1.1: u8) = const 0_u8; // scope 0 at $DIR/sibling_ptr.rs:+1:27: +1:33
+ _1 = (const 0_u8, const 0_u8); // scope 0 at $DIR/sibling_ptr.rs:+1:27: +1:33
StorageLive(_2); // scope 1 at $DIR/sibling_ptr.rs:+2:5: +5:6
StorageLive(_3); // scope 2 at $DIR/sibling_ptr.rs:+3:13: +3:14
_3 = &raw mut (_1.0: u8); // scope 2 at $SRC_DIR/core/src/ptr/mod.rs:LL:COL
@@ -34,7 +32,7 @@
_5 = _3; // scope 3 at $DIR/sibling_ptr.rs:+4:10: +4:11
_4 = ptr::mut_ptr::<impl *mut u8>::add(move _5, const 1_usize) -> bb1; // scope 3 at $DIR/sibling_ptr.rs:+4:10: +4:18
// mir::Constant
- // + span: $DIR/sibling_ptr.rs:8:12: 8:15
+ // + span: $DIR/sibling_ptr.rs:15:12: 15:15
// + literal: Const { ty: unsafe fn(*mut u8, usize) -> *mut u8 {ptr::mut_ptr::<impl *mut u8>::add}, val: Value(<ZST>) }
}
diff --git a/tests/mir-opt/dataflow-const-prop/sibling_ptr.rs b/tests/mir-opt/dataflow-const-prop/sibling_ptr.rs
index 87ef00d18..6dfb3a4ed 100644
--- a/tests/mir-opt/dataflow-const-prop/sibling_ptr.rs
+++ b/tests/mir-opt/dataflow-const-prop/sibling_ptr.rs
@@ -1,3 +1,10 @@
+// This attempts to modify `x.1` via a pointer derived from `addr_of_mut!(x.0)`.
+// According to Miri, that is UB. However, T-opsem has not finalized that
+// decision and as such we cannot rely on it in optimizations. Consequently,
+// DataflowConstProp must treat the `addr_of_mut!(x.0)` as potentially being
+// used to modify `x.1` - if it did not, then it might incorrectly assume that it
+// can infer the value of `x.1` at the end of this function.
+
// unit-test: DataflowConstProp
// EMIT_MIR sibling_ptr.main.DataflowConstProp.diff
@@ -7,5 +14,5 @@ fn main() {
let p = std::ptr::addr_of_mut!(x.0);
*p.add(1) = 1;
}
- let x1 = x.1; // should not be propagated
+ let x1 = x.1; // should not be propagated
}
diff --git a/tests/mir-opt/dataflow-const-prop/struct.main.DataflowConstProp.diff b/tests/mir-opt/dataflow-const-prop/struct.main.DataflowConstProp.diff
index cfb2706c1..53c62c081 100644
--- a/tests/mir-opt/dataflow-const-prop/struct.main.DataflowConstProp.diff
+++ b/tests/mir-opt/dataflow-const-prop/struct.main.DataflowConstProp.diff
@@ -21,8 +21,7 @@
bb0: {
StorageLive(_1); // scope 0 at $DIR/struct.rs:+1:9: +1:14
- Deinit(_1); // scope 0 at $DIR/struct.rs:+1:17: +1:21
- (_1.0: i32) = const 1_i32; // scope 0 at $DIR/struct.rs:+1:17: +1:21
+ _1 = S(const 1_i32); // scope 0 at $DIR/struct.rs:+1:17: +1:21
StorageLive(_2); // scope 1 at $DIR/struct.rs:+2:9: +2:10
StorageLive(_3); // scope 1 at $DIR/struct.rs:+2:13: +2:16
- _3 = (_1.0: i32); // scope 1 at $DIR/struct.rs:+2:13: +2:16
diff --git a/tests/mir-opt/dataflow-const-prop/tuple.main.DataflowConstProp.diff b/tests/mir-opt/dataflow-const-prop/tuple.main.DataflowConstProp.diff
index e028def00..8ce4ce4ba 100644
--- a/tests/mir-opt/dataflow-const-prop/tuple.main.DataflowConstProp.diff
+++ b/tests/mir-opt/dataflow-const-prop/tuple.main.DataflowConstProp.diff
@@ -25,9 +25,7 @@
bb0: {
StorageLive(_1); // scope 0 at $DIR/tuple.rs:+1:9: +1:14
- Deinit(_1); // scope 0 at $DIR/tuple.rs:+1:17: +1:23
- (_1.0: i32) = const 1_i32; // scope 0 at $DIR/tuple.rs:+1:17: +1:23
- (_1.1: i32) = const 2_i32; // scope 0 at $DIR/tuple.rs:+1:17: +1:23
+ _1 = (const 1_i32, const 2_i32); // scope 0 at $DIR/tuple.rs:+1:17: +1:23
StorageLive(_2); // scope 1 at $DIR/tuple.rs:+2:9: +2:10
StorageLive(_3); // scope 1 at $DIR/tuple.rs:+2:13: +2:22
StorageLive(_4); // scope 1 at $DIR/tuple.rs:+2:13: +2:16
@@ -43,9 +41,7 @@
- _2 = Add(move _3, const 3_i32); // scope 1 at $DIR/tuple.rs:+2:13: +2:26
+ _2 = const 6_i32; // scope 1 at $DIR/tuple.rs:+2:13: +2:26
StorageDead(_3); // scope 1 at $DIR/tuple.rs:+2:25: +2:26
- Deinit(_1); // scope 2 at $DIR/tuple.rs:+3:5: +3:15
- (_1.0: i32) = const 2_i32; // scope 2 at $DIR/tuple.rs:+3:5: +3:15
- (_1.1: i32) = const 3_i32; // scope 2 at $DIR/tuple.rs:+3:5: +3:15
+ _1 = (const 2_i32, const 3_i32); // scope 2 at $DIR/tuple.rs:+3:5: +3:15
StorageLive(_6); // scope 2 at $DIR/tuple.rs:+4:9: +4:10
StorageLive(_7); // scope 2 at $DIR/tuple.rs:+4:13: +4:22
StorageLive(_8); // scope 2 at $DIR/tuple.rs:+4:13: +4:16
diff --git a/tests/mir-opt/deaggregator_test.bar.Deaggregator.diff b/tests/mir-opt/deaggregator_test.bar.Deaggregator.diff
deleted file mode 100644
index db136485a..000000000
--- a/tests/mir-opt/deaggregator_test.bar.Deaggregator.diff
+++ /dev/null
@@ -1,21 +0,0 @@
-- // MIR for `bar` before Deaggregator
-+ // MIR for `bar` after Deaggregator
-
- fn bar(_1: usize) -> Baz {
- debug a => _1; // in scope 0 at $DIR/deaggregator_test.rs:+0:8: +0:9
- let mut _0: Baz; // return place in scope 0 at $DIR/deaggregator_test.rs:+0:21: +0:24
- let mut _2: usize; // in scope 0 at $DIR/deaggregator_test.rs:+1:14: +1:15
-
- bb0: {
- StorageLive(_2); // scope 0 at $DIR/deaggregator_test.rs:+1:14: +1:15
- _2 = _1; // scope 0 at $DIR/deaggregator_test.rs:+1:14: +1:15
-- _0 = Baz { x: move _2, y: const 0f32, z: const false }; // scope 0 at $DIR/deaggregator_test.rs:+1:5: +1:35
-+ Deinit(_0); // scope 0 at $DIR/deaggregator_test.rs:+1:5: +1:35
-+ (_0.0: usize) = move _2; // scope 0 at $DIR/deaggregator_test.rs:+1:5: +1:35
-+ (_0.1: f32) = const 0f32; // scope 0 at $DIR/deaggregator_test.rs:+1:5: +1:35
-+ (_0.2: bool) = const false; // scope 0 at $DIR/deaggregator_test.rs:+1:5: +1:35
- StorageDead(_2); // scope 0 at $DIR/deaggregator_test.rs:+1:34: +1:35
- return; // scope 0 at $DIR/deaggregator_test.rs:+2:2: +2:2
- }
- }
-
diff --git a/tests/mir-opt/deaggregator_test.rs b/tests/mir-opt/deaggregator_test.rs
deleted file mode 100644
index ee59402af..000000000
--- a/tests/mir-opt/deaggregator_test.rs
+++ /dev/null
@@ -1,17 +0,0 @@
-// unit-test: Deaggregator
-
-struct Baz {
- x: usize,
- y: f32,
- z: bool,
-}
-
-// EMIT_MIR deaggregator_test.bar.Deaggregator.diff
-fn bar(a: usize) -> Baz {
- Baz { x: a, y: 0.0, z: false }
-}
-
-fn main() {
- // Make sure the function actually gets instantiated.
- bar(0);
-}
diff --git a/tests/mir-opt/deaggregator_test_enum.bar.Deaggregator.diff b/tests/mir-opt/deaggregator_test_enum.bar.Deaggregator.diff
deleted file mode 100644
index f28c2b482..000000000
--- a/tests/mir-opt/deaggregator_test_enum.bar.Deaggregator.diff
+++ /dev/null
@@ -1,20 +0,0 @@
-- // MIR for `bar` before Deaggregator
-+ // MIR for `bar` after Deaggregator
-
- fn bar(_1: usize) -> Baz {
- debug a => _1; // in scope 0 at $DIR/deaggregator_test_enum.rs:+0:8: +0:9
- let mut _0: Baz; // return place in scope 0 at $DIR/deaggregator_test_enum.rs:+0:21: +0:24
- let mut _2: usize; // in scope 0 at $DIR/deaggregator_test_enum.rs:+1:19: +1:20
-
- bb0: {
- StorageLive(_2); // scope 0 at $DIR/deaggregator_test_enum.rs:+1:19: +1:20
- _2 = _1; // scope 0 at $DIR/deaggregator_test_enum.rs:+1:19: +1:20
-- _0 = Baz::Foo { x: move _2 }; // scope 0 at $DIR/deaggregator_test_enum.rs:+1:5: +1:22
-+ Deinit(_0); // scope 0 at $DIR/deaggregator_test_enum.rs:+1:5: +1:22
-+ ((_0 as Foo).0: usize) = move _2; // scope 0 at $DIR/deaggregator_test_enum.rs:+1:5: +1:22
-+ discriminant(_0) = 1; // scope 0 at $DIR/deaggregator_test_enum.rs:+1:5: +1:22
- StorageDead(_2); // scope 0 at $DIR/deaggregator_test_enum.rs:+1:21: +1:22
- return; // scope 0 at $DIR/deaggregator_test_enum.rs:+2:2: +2:2
- }
- }
-
diff --git a/tests/mir-opt/deaggregator_test_enum.rs b/tests/mir-opt/deaggregator_test_enum.rs
deleted file mode 100644
index ea402dafd..000000000
--- a/tests/mir-opt/deaggregator_test_enum.rs
+++ /dev/null
@@ -1,19 +0,0 @@
-// unit-test: Deaggregator
-
-enum Baz {
- Empty,
- Foo { x: usize },
-}
-
-// EMIT_MIR deaggregator_test_enum.bar.Deaggregator.diff
-fn bar(a: usize) -> Baz {
- Baz::Foo { x: a }
-}
-
-fn main() {
- let x = bar(10);
- match x {
- Baz::Empty => println!("empty"),
- Baz::Foo { x } => println!("{}", x),
- };
-}
diff --git a/tests/mir-opt/deaggregator_test_enum_2.rs b/tests/mir-opt/deaggregator_test_enum_2.rs
deleted file mode 100644
index 955c31732..000000000
--- a/tests/mir-opt/deaggregator_test_enum_2.rs
+++ /dev/null
@@ -1,21 +0,0 @@
-// unit-test: Deaggregator
-// Test that deaggregate fires in more than one basic block
-
-enum Foo {
- A(i32),
- B(i32),
-}
-
-// EMIT_MIR deaggregator_test_enum_2.test1.Deaggregator.diff
-fn test1(x: bool, y: i32) -> Foo {
- if x {
- Foo::A(y)
- } else {
- Foo::B(y)
- }
-}
-
-fn main() {
- // Make sure the function actually gets instantiated.
- test1(false, 0);
-}
diff --git a/tests/mir-opt/deaggregator_test_enum_2.test1.Deaggregator.diff b/tests/mir-opt/deaggregator_test_enum_2.test1.Deaggregator.diff
deleted file mode 100644
index 210d3849e..000000000
--- a/tests/mir-opt/deaggregator_test_enum_2.test1.Deaggregator.diff
+++ /dev/null
@@ -1,45 +0,0 @@
-- // MIR for `test1` before Deaggregator
-+ // MIR for `test1` after Deaggregator
-
- fn test1(_1: bool, _2: i32) -> Foo {
- debug x => _1; // in scope 0 at $DIR/deaggregator_test_enum_2.rs:+0:10: +0:11
- debug y => _2; // in scope 0 at $DIR/deaggregator_test_enum_2.rs:+0:19: +0:20
- let mut _0: Foo; // return place in scope 0 at $DIR/deaggregator_test_enum_2.rs:+0:30: +0:33
- let mut _3: bool; // in scope 0 at $DIR/deaggregator_test_enum_2.rs:+1:8: +1:9
- let mut _4: i32; // in scope 0 at $DIR/deaggregator_test_enum_2.rs:+2:16: +2:17
- let mut _5: i32; // in scope 0 at $DIR/deaggregator_test_enum_2.rs:+4:16: +4:17
-
- bb0: {
- StorageLive(_3); // scope 0 at $DIR/deaggregator_test_enum_2.rs:+1:8: +1:9
- _3 = _1; // scope 0 at $DIR/deaggregator_test_enum_2.rs:+1:8: +1:9
- switchInt(move _3) -> [0: bb2, otherwise: bb1]; // scope 0 at $DIR/deaggregator_test_enum_2.rs:+1:8: +1:9
- }
-
- bb1: {
- StorageLive(_4); // scope 0 at $DIR/deaggregator_test_enum_2.rs:+2:16: +2:17
- _4 = _2; // scope 0 at $DIR/deaggregator_test_enum_2.rs:+2:16: +2:17
-- _0 = Foo::A(move _4); // scope 0 at $DIR/deaggregator_test_enum_2.rs:+2:9: +2:18
-+ Deinit(_0); // scope 0 at $DIR/deaggregator_test_enum_2.rs:+2:9: +2:18
-+ ((_0 as A).0: i32) = move _4; // scope 0 at $DIR/deaggregator_test_enum_2.rs:+2:9: +2:18
-+ discriminant(_0) = 0; // scope 0 at $DIR/deaggregator_test_enum_2.rs:+2:9: +2:18
- StorageDead(_4); // scope 0 at $DIR/deaggregator_test_enum_2.rs:+2:17: +2:18
- goto -> bb3; // scope 0 at $DIR/deaggregator_test_enum_2.rs:+1:5: +5:6
- }
-
- bb2: {
- StorageLive(_5); // scope 0 at $DIR/deaggregator_test_enum_2.rs:+4:16: +4:17
- _5 = _2; // scope 0 at $DIR/deaggregator_test_enum_2.rs:+4:16: +4:17
-- _0 = Foo::B(move _5); // scope 0 at $DIR/deaggregator_test_enum_2.rs:+4:9: +4:18
-+ Deinit(_0); // scope 0 at $DIR/deaggregator_test_enum_2.rs:+4:9: +4:18
-+ ((_0 as B).0: i32) = move _5; // scope 0 at $DIR/deaggregator_test_enum_2.rs:+4:9: +4:18
-+ discriminant(_0) = 1; // scope 0 at $DIR/deaggregator_test_enum_2.rs:+4:9: +4:18
- StorageDead(_5); // scope 0 at $DIR/deaggregator_test_enum_2.rs:+4:17: +4:18
- goto -> bb3; // scope 0 at $DIR/deaggregator_test_enum_2.rs:+1:5: +5:6
- }
-
- bb3: {
- StorageDead(_3); // scope 0 at $DIR/deaggregator_test_enum_2.rs:+5:5: +5:6
- return; // scope 0 at $DIR/deaggregator_test_enum_2.rs:+6:2: +6:2
- }
- }
-
diff --git a/tests/mir-opt/deaggregator_test_multiple.rs b/tests/mir-opt/deaggregator_test_multiple.rs
deleted file mode 100644
index 46305fe21..000000000
--- a/tests/mir-opt/deaggregator_test_multiple.rs
+++ /dev/null
@@ -1,17 +0,0 @@
-// unit-test: Deaggregator
-// Test that deaggregate fires more than once per block
-
-enum Foo {
- A(i32),
- B,
-}
-
-// EMIT_MIR deaggregator_test_multiple.test.Deaggregator.diff
-fn test(x: i32) -> [Foo; 2] {
- [Foo::A(x), Foo::A(x)]
-}
-
-fn main() {
- // Make sure the function actually gets instantiated.
- test(0);
-}
diff --git a/tests/mir-opt/deaggregator_test_multiple.test.Deaggregator.diff b/tests/mir-opt/deaggregator_test_multiple.test.Deaggregator.diff
deleted file mode 100644
index cf5da273c..000000000
--- a/tests/mir-opt/deaggregator_test_multiple.test.Deaggregator.diff
+++ /dev/null
@@ -1,35 +0,0 @@
-- // MIR for `test` before Deaggregator
-+ // MIR for `test` after Deaggregator
-
- fn test(_1: i32) -> [Foo; 2] {
- debug x => _1; // in scope 0 at $DIR/deaggregator_test_multiple.rs:+0:9: +0:10
- let mut _0: [Foo; 2]; // return place in scope 0 at $DIR/deaggregator_test_multiple.rs:+0:20: +0:28
- let mut _2: Foo; // in scope 0 at $DIR/deaggregator_test_multiple.rs:+1:6: +1:15
- let mut _3: i32; // in scope 0 at $DIR/deaggregator_test_multiple.rs:+1:13: +1:14
- let mut _4: Foo; // in scope 0 at $DIR/deaggregator_test_multiple.rs:+1:17: +1:26
- let mut _5: i32; // in scope 0 at $DIR/deaggregator_test_multiple.rs:+1:24: +1:25
-
- bb0: {
- StorageLive(_2); // scope 0 at $DIR/deaggregator_test_multiple.rs:+1:6: +1:15
- StorageLive(_3); // scope 0 at $DIR/deaggregator_test_multiple.rs:+1:13: +1:14
- _3 = _1; // scope 0 at $DIR/deaggregator_test_multiple.rs:+1:13: +1:14
-- _2 = Foo::A(move _3); // scope 0 at $DIR/deaggregator_test_multiple.rs:+1:6: +1:15
-+ Deinit(_2); // scope 0 at $DIR/deaggregator_test_multiple.rs:+1:6: +1:15
-+ ((_2 as A).0: i32) = move _3; // scope 0 at $DIR/deaggregator_test_multiple.rs:+1:6: +1:15
-+ discriminant(_2) = 0; // scope 0 at $DIR/deaggregator_test_multiple.rs:+1:6: +1:15
- StorageDead(_3); // scope 0 at $DIR/deaggregator_test_multiple.rs:+1:14: +1:15
- StorageLive(_4); // scope 0 at $DIR/deaggregator_test_multiple.rs:+1:17: +1:26
- StorageLive(_5); // scope 0 at $DIR/deaggregator_test_multiple.rs:+1:24: +1:25
- _5 = _1; // scope 0 at $DIR/deaggregator_test_multiple.rs:+1:24: +1:25
-- _4 = Foo::A(move _5); // scope 0 at $DIR/deaggregator_test_multiple.rs:+1:17: +1:26
-+ Deinit(_4); // scope 0 at $DIR/deaggregator_test_multiple.rs:+1:17: +1:26
-+ ((_4 as A).0: i32) = move _5; // scope 0 at $DIR/deaggregator_test_multiple.rs:+1:17: +1:26
-+ discriminant(_4) = 0; // scope 0 at $DIR/deaggregator_test_multiple.rs:+1:17: +1:26
- StorageDead(_5); // scope 0 at $DIR/deaggregator_test_multiple.rs:+1:25: +1:26
- _0 = [move _2, move _4]; // scope 0 at $DIR/deaggregator_test_multiple.rs:+1:5: +1:27
- StorageDead(_4); // scope 0 at $DIR/deaggregator_test_multiple.rs:+1:26: +1:27
- StorageDead(_2); // scope 0 at $DIR/deaggregator_test_multiple.rs:+1:26: +1:27
- return; // scope 0 at $DIR/deaggregator_test_multiple.rs:+2:2: +2:2
- }
- }
-
diff --git a/tests/mir-opt/div_overflow.const_dividend.PreCodegen.after.mir b/tests/mir-opt/div_overflow.const_dividend.PreCodegen.after.mir
index d7f66a6bf..1a7fb916e 100644
--- a/tests/mir-opt/div_overflow.const_dividend.PreCodegen.after.mir
+++ b/tests/mir-opt/div_overflow.const_dividend.PreCodegen.after.mir
@@ -11,7 +11,7 @@ fn const_dividend(_1: i32) -> i32 {
}
bb1: {
- _0 = Div(const 256_i32, move _1); // scope 0 at $DIR/div_overflow.rs:+1:5: +1:12
+ _0 = Div(const 256_i32, _1); // scope 0 at $DIR/div_overflow.rs:+1:5: +1:12
return; // scope 0 at $DIR/div_overflow.rs:+2:2: +2:2
}
}
diff --git a/tests/mir-opt/div_overflow.const_divisor.PreCodegen.after.mir b/tests/mir-opt/div_overflow.const_divisor.PreCodegen.after.mir
index 7b7ab1978..5526a194b 100644
--- a/tests/mir-opt/div_overflow.const_divisor.PreCodegen.after.mir
+++ b/tests/mir-opt/div_overflow.const_divisor.PreCodegen.after.mir
@@ -5,7 +5,7 @@ fn const_divisor(_1: i32) -> i32 {
let mut _0: i32; // return place in scope 0 at $DIR/div_overflow.rs:+0:33: +0:36
bb0: {
- _0 = Div(move _1, const 256_i32); // scope 0 at $DIR/div_overflow.rs:+1:5: +1:12
+ _0 = Div(_1, const 256_i32); // scope 0 at $DIR/div_overflow.rs:+1:5: +1:12
return; // scope 0 at $DIR/div_overflow.rs:+2:2: +2:2
}
}
diff --git a/tests/mir-opt/dont_yeet_assert.generic.InstCombine.diff b/tests/mir-opt/dont_yeet_assert.generic.InstCombine.diff
new file mode 100644
index 000000000..c1a42a47e
--- /dev/null
+++ b/tests/mir-opt/dont_yeet_assert.generic.InstCombine.diff
@@ -0,0 +1,23 @@
+- // MIR for `generic` before InstCombine
++ // MIR for `generic` after InstCombine
+
+ fn generic() -> () {
+ let mut _0: (); // return place in scope 0 at $DIR/dont_yeet_assert.rs:+0:21: +0:21
+ let _1: (); // in scope 0 at $DIR/dont_yeet_assert.rs:+1:5: +1:61
+
+ bb0: {
+ StorageLive(_1); // scope 0 at $DIR/dont_yeet_assert.rs:+1:5: +1:61
+ _1 = assert_mem_uninitialized_valid::<&T>() -> bb1; // scope 0 at $DIR/dont_yeet_assert.rs:+1:5: +1:61
+ // mir::Constant
+ // + span: $DIR/dont_yeet_assert.rs:10:5: 10:59
+ // + user_ty: UserType(0)
+ // + literal: Const { ty: extern "rust-intrinsic" fn() {assert_mem_uninitialized_valid::<&T>}, val: Value(<ZST>) }
+ }
+
+ bb1: {
+ StorageDead(_1); // scope 0 at $DIR/dont_yeet_assert.rs:+1:61: +1:62
+ _0 = const (); // scope 0 at $DIR/dont_yeet_assert.rs:+0:21: +2:2
+ return; // scope 0 at $DIR/dont_yeet_assert.rs:+2:2: +2:2
+ }
+ }
+
diff --git a/tests/mir-opt/dont_yeet_assert.rs b/tests/mir-opt/dont_yeet_assert.rs
new file mode 100644
index 000000000..7cec761ea
--- /dev/null
+++ b/tests/mir-opt/dont_yeet_assert.rs
@@ -0,0 +1,11 @@
+// compile-flags: --crate-type=lib
+// unit-test: InstCombine
+
+#![feature(core_intrinsics)]
+
+// Want to make sure this assertion isn't compiled away in generic code.
+
+// EMIT_MIR dont_yeet_assert.generic.InstCombine.diff
+pub fn generic<T>() {
+ core::intrinsics::assert_mem_uninitialized_valid::<&T>();
+}
diff --git a/tests/mir-opt/early_otherwise_branch.opt1.EarlyOtherwiseBranch.diff b/tests/mir-opt/early_otherwise_branch.opt1.EarlyOtherwiseBranch.diff
index 98a02ee38..5383d1be1 100644
--- a/tests/mir-opt/early_otherwise_branch.opt1.EarlyOtherwiseBranch.diff
+++ b/tests/mir-opt/early_otherwise_branch.opt1.EarlyOtherwiseBranch.diff
@@ -25,9 +25,7 @@
_4 = _1; // scope 0 at $DIR/early_otherwise_branch.rs:+1:12: +1:13
StorageLive(_5); // scope 0 at $DIR/early_otherwise_branch.rs:+1:15: +1:16
_5 = _2; // scope 0 at $DIR/early_otherwise_branch.rs:+1:15: +1:16
- Deinit(_3); // scope 0 at $DIR/early_otherwise_branch.rs:+1:11: +1:17
- (_3.0: std::option::Option<u32>) = move _4; // scope 0 at $DIR/early_otherwise_branch.rs:+1:11: +1:17
- (_3.1: std::option::Option<u32>) = move _5; // scope 0 at $DIR/early_otherwise_branch.rs:+1:11: +1:17
+ _3 = (move _4, move _5); // scope 0 at $DIR/early_otherwise_branch.rs:+1:11: +1:17
StorageDead(_5); // scope 0 at $DIR/early_otherwise_branch.rs:+1:16: +1:17
StorageDead(_4); // scope 0 at $DIR/early_otherwise_branch.rs:+1:16: +1:17
_7 = discriminant((_3.0: std::option::Option<u32>)); // scope 0 at $DIR/early_otherwise_branch.rs:+1:11: +1:17
diff --git a/tests/mir-opt/early_otherwise_branch.opt2.EarlyOtherwiseBranch.diff b/tests/mir-opt/early_otherwise_branch.opt2.EarlyOtherwiseBranch.diff
index aa75c44b8..b3e21ff49 100644
--- a/tests/mir-opt/early_otherwise_branch.opt2.EarlyOtherwiseBranch.diff
+++ b/tests/mir-opt/early_otherwise_branch.opt2.EarlyOtherwiseBranch.diff
@@ -26,9 +26,7 @@
_4 = _1; // scope 0 at $DIR/early_otherwise_branch.rs:+1:12: +1:13
StorageLive(_5); // scope 0 at $DIR/early_otherwise_branch.rs:+1:15: +1:16
_5 = _2; // scope 0 at $DIR/early_otherwise_branch.rs:+1:15: +1:16
- Deinit(_3); // scope 0 at $DIR/early_otherwise_branch.rs:+1:11: +1:17
- (_3.0: std::option::Option<u32>) = move _4; // scope 0 at $DIR/early_otherwise_branch.rs:+1:11: +1:17
- (_3.1: std::option::Option<u32>) = move _5; // scope 0 at $DIR/early_otherwise_branch.rs:+1:11: +1:17
+ _3 = (move _4, move _5); // scope 0 at $DIR/early_otherwise_branch.rs:+1:11: +1:17
StorageDead(_5); // scope 0 at $DIR/early_otherwise_branch.rs:+1:16: +1:17
StorageDead(_4); // scope 0 at $DIR/early_otherwise_branch.rs:+1:16: +1:17
_8 = discriminant((_3.0: std::option::Option<u32>)); // scope 0 at $DIR/early_otherwise_branch.rs:+1:11: +1:17
diff --git a/tests/mir-opt/early_otherwise_branch.opt3.EarlyOtherwiseBranch.diff b/tests/mir-opt/early_otherwise_branch.opt3.EarlyOtherwiseBranch.diff
index cea6ff7cd..e098a88eb 100644
--- a/tests/mir-opt/early_otherwise_branch.opt3.EarlyOtherwiseBranch.diff
+++ b/tests/mir-opt/early_otherwise_branch.opt3.EarlyOtherwiseBranch.diff
@@ -25,9 +25,7 @@
_4 = _1; // scope 0 at $DIR/early_otherwise_branch.rs:+1:12: +1:13
StorageLive(_5); // scope 0 at $DIR/early_otherwise_branch.rs:+1:15: +1:16
_5 = _2; // scope 0 at $DIR/early_otherwise_branch.rs:+1:15: +1:16
- Deinit(_3); // scope 0 at $DIR/early_otherwise_branch.rs:+1:11: +1:17
- (_3.0: std::option::Option<u32>) = move _4; // scope 0 at $DIR/early_otherwise_branch.rs:+1:11: +1:17
- (_3.1: std::option::Option<bool>) = move _5; // scope 0 at $DIR/early_otherwise_branch.rs:+1:11: +1:17
+ _3 = (move _4, move _5); // scope 0 at $DIR/early_otherwise_branch.rs:+1:11: +1:17
StorageDead(_5); // scope 0 at $DIR/early_otherwise_branch.rs:+1:16: +1:17
StorageDead(_4); // scope 0 at $DIR/early_otherwise_branch.rs:+1:16: +1:17
_7 = discriminant((_3.0: std::option::Option<u32>)); // scope 0 at $DIR/early_otherwise_branch.rs:+1:11: +1:17
diff --git a/tests/mir-opt/early_otherwise_branch_3_element_tuple.opt1.EarlyOtherwiseBranch.diff b/tests/mir-opt/early_otherwise_branch_3_element_tuple.opt1.EarlyOtherwiseBranch.diff
index b90d70ce4..ec3b4bbdf 100644
--- a/tests/mir-opt/early_otherwise_branch_3_element_tuple.opt1.EarlyOtherwiseBranch.diff
+++ b/tests/mir-opt/early_otherwise_branch_3_element_tuple.opt1.EarlyOtherwiseBranch.diff
@@ -34,10 +34,7 @@
_6 = _2; // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:+1:15: +1:16
StorageLive(_7); // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:+1:18: +1:19
_7 = _3; // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:+1:18: +1:19
- Deinit(_4); // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:+1:11: +1:20
- (_4.0: std::option::Option<u32>) = move _5; // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:+1:11: +1:20
- (_4.1: std::option::Option<u32>) = move _6; // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:+1:11: +1:20
- (_4.2: std::option::Option<u32>) = move _7; // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:+1:11: +1:20
+ _4 = (move _5, move _6, move _7); // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:+1:11: +1:20
StorageDead(_7); // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:+1:19: +1:20
StorageDead(_6); // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:+1:19: +1:20
StorageDead(_5); // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:+1:19: +1:20
diff --git a/tests/mir-opt/early_otherwise_branch_68867.try_sum.EarlyOtherwiseBranch.diff b/tests/mir-opt/early_otherwise_branch_68867.try_sum.EarlyOtherwiseBranch.diff
index 9edd1a39f..a91d0d7cf 100644
--- a/tests/mir-opt/early_otherwise_branch_68867.try_sum.EarlyOtherwiseBranch.diff
+++ b/tests/mir-opt/early_otherwise_branch_68867.try_sum.EarlyOtherwiseBranch.diff
@@ -73,9 +73,7 @@
_5 = _1; // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:15: +5:16
StorageLive(_6); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:18: +5:23
_6 = _2; // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:18: +5:23
- Deinit(_4); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:14: +5:24
- (_4.0: &ViewportPercentageLength) = move _5; // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:14: +5:24
- (_4.1: &ViewportPercentageLength) = move _6; // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:14: +5:24
+ _4 = (move _5, move _6); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:14: +5:24
StorageDead(_6); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:23: +5:24
StorageDead(_5); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:23: +5:24
_34 = deref_copy (_4.0: &ViewportPercentageLength); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:14: +5:24
@@ -91,10 +89,8 @@
bb2: {
StorageLive(_33); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+10:25: +10:27
- Deinit(_33); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+10:25: +10:27
- Deinit(_0); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+10:21: +10:28
- ((_0 as Err).0: ()) = move _33; // scope 0 at $DIR/early_otherwise_branch_68867.rs:+10:21: +10:28
- discriminant(_0) = 1; // scope 0 at $DIR/early_otherwise_branch_68867.rs:+10:21: +10:28
+ _33 = (); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+10:25: +10:27
+ _0 = Result::<ViewportPercentageLength, ()>::Err(move _33); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+10:21: +10:28
StorageDead(_33); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+10:27: +10:28
StorageDead(_3); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+11:6: +11:7
StorageDead(_4); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+12:1: +12:2
@@ -134,9 +130,7 @@
_14 = Add(move _15, move _16); // scope 1 at $DIR/early_otherwise_branch_68867.rs:+6:38: +6:49
StorageDead(_16); // scope 1 at $DIR/early_otherwise_branch_68867.rs:+6:48: +6:49
StorageDead(_15); // scope 1 at $DIR/early_otherwise_branch_68867.rs:+6:48: +6:49
- Deinit(_3); // scope 1 at $DIR/early_otherwise_branch_68867.rs:+6:35: +6:50
- ((_3 as Vw).0: f32) = move _14; // scope 1 at $DIR/early_otherwise_branch_68867.rs:+6:35: +6:50
- discriminant(_3) = 0; // scope 1 at $DIR/early_otherwise_branch_68867.rs:+6:35: +6:50
+ _3 = ViewportPercentageLength::Vw(move _14); // scope 1 at $DIR/early_otherwise_branch_68867.rs:+6:35: +6:50
StorageDead(_14); // scope 1 at $DIR/early_otherwise_branch_68867.rs:+6:49: +6:50
StorageDead(_13); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+6:49: +6:50
StorageDead(_12); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+6:49: +6:50
@@ -158,9 +152,7 @@
_19 = Add(move _20, move _21); // scope 2 at $DIR/early_otherwise_branch_68867.rs:+7:38: +7:49
StorageDead(_21); // scope 2 at $DIR/early_otherwise_branch_68867.rs:+7:48: +7:49
StorageDead(_20); // scope 2 at $DIR/early_otherwise_branch_68867.rs:+7:48: +7:49
- Deinit(_3); // scope 2 at $DIR/early_otherwise_branch_68867.rs:+7:35: +7:50
- ((_3 as Vh).0: f32) = move _19; // scope 2 at $DIR/early_otherwise_branch_68867.rs:+7:35: +7:50
- discriminant(_3) = 1; // scope 2 at $DIR/early_otherwise_branch_68867.rs:+7:35: +7:50
+ _3 = ViewportPercentageLength::Vh(move _19); // scope 2 at $DIR/early_otherwise_branch_68867.rs:+7:35: +7:50
StorageDead(_19); // scope 2 at $DIR/early_otherwise_branch_68867.rs:+7:49: +7:50
StorageDead(_18); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+7:49: +7:50
StorageDead(_17); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+7:49: +7:50
@@ -182,9 +174,7 @@
_24 = Add(move _25, move _26); // scope 3 at $DIR/early_otherwise_branch_68867.rs:+8:44: +8:55
StorageDead(_26); // scope 3 at $DIR/early_otherwise_branch_68867.rs:+8:54: +8:55
StorageDead(_25); // scope 3 at $DIR/early_otherwise_branch_68867.rs:+8:54: +8:55
- Deinit(_3); // scope 3 at $DIR/early_otherwise_branch_68867.rs:+8:39: +8:56
- ((_3 as Vmin).0: f32) = move _24; // scope 3 at $DIR/early_otherwise_branch_68867.rs:+8:39: +8:56
- discriminant(_3) = 2; // scope 3 at $DIR/early_otherwise_branch_68867.rs:+8:39: +8:56
+ _3 = ViewportPercentageLength::Vmin(move _24); // scope 3 at $DIR/early_otherwise_branch_68867.rs:+8:39: +8:56
StorageDead(_24); // scope 3 at $DIR/early_otherwise_branch_68867.rs:+8:55: +8:56
StorageDead(_23); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+8:55: +8:56
StorageDead(_22); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+8:55: +8:56
@@ -206,9 +196,7 @@
_29 = Add(move _30, move _31); // scope 4 at $DIR/early_otherwise_branch_68867.rs:+9:44: +9:55
StorageDead(_31); // scope 4 at $DIR/early_otherwise_branch_68867.rs:+9:54: +9:55
StorageDead(_30); // scope 4 at $DIR/early_otherwise_branch_68867.rs:+9:54: +9:55
- Deinit(_3); // scope 4 at $DIR/early_otherwise_branch_68867.rs:+9:39: +9:56
- ((_3 as Vmax).0: f32) = move _29; // scope 4 at $DIR/early_otherwise_branch_68867.rs:+9:39: +9:56
- discriminant(_3) = 3; // scope 4 at $DIR/early_otherwise_branch_68867.rs:+9:39: +9:56
+ _3 = ViewportPercentageLength::Vmax(move _29); // scope 4 at $DIR/early_otherwise_branch_68867.rs:+9:39: +9:56
StorageDead(_29); // scope 4 at $DIR/early_otherwise_branch_68867.rs:+9:55: +9:56
StorageDead(_28); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+9:55: +9:56
StorageDead(_27); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+9:55: +9:56
@@ -216,9 +204,7 @@
}
bb10: {
- Deinit(_0); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:5: +11:7
- ((_0 as Ok).0: ViewportPercentageLength) = move _3; // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:5: +11:7
- discriminant(_0) = 0; // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:5: +11:7
+ _0 = Result::<ViewportPercentageLength, ()>::Ok(move _3); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:5: +11:7
StorageDead(_3); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+11:6: +11:7
StorageDead(_4); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+12:1: +12:2
goto -> bb11; // scope 0 at $DIR/early_otherwise_branch_68867.rs:+12:2: +12:2
diff --git a/tests/mir-opt/early_otherwise_branch_noopt.noopt1.EarlyOtherwiseBranch.diff b/tests/mir-opt/early_otherwise_branch_noopt.noopt1.EarlyOtherwiseBranch.diff
index 82d8b2fc5..6468eb5f8 100644
--- a/tests/mir-opt/early_otherwise_branch_noopt.noopt1.EarlyOtherwiseBranch.diff
+++ b/tests/mir-opt/early_otherwise_branch_noopt.noopt1.EarlyOtherwiseBranch.diff
@@ -32,9 +32,7 @@
_4 = _1; // scope 0 at $DIR/early_otherwise_branch_noopt.rs:+1:12: +1:13
StorageLive(_5); // scope 0 at $DIR/early_otherwise_branch_noopt.rs:+1:15: +1:16
_5 = _2; // scope 0 at $DIR/early_otherwise_branch_noopt.rs:+1:15: +1:16
- Deinit(_3); // scope 0 at $DIR/early_otherwise_branch_noopt.rs:+1:11: +1:17
- (_3.0: std::option::Option<u32>) = move _4; // scope 0 at $DIR/early_otherwise_branch_noopt.rs:+1:11: +1:17
- (_3.1: std::option::Option<u32>) = move _5; // scope 0 at $DIR/early_otherwise_branch_noopt.rs:+1:11: +1:17
+ _3 = (move _4, move _5); // scope 0 at $DIR/early_otherwise_branch_noopt.rs:+1:11: +1:17
StorageDead(_5); // scope 0 at $DIR/early_otherwise_branch_noopt.rs:+1:16: +1:17
StorageDead(_4); // scope 0 at $DIR/early_otherwise_branch_noopt.rs:+1:16: +1:17
_8 = discriminant((_3.0: std::option::Option<u32>)); // scope 0 at $DIR/early_otherwise_branch_noopt.rs:+1:11: +1:17
diff --git a/tests/mir-opt/enum_opt.cand.EnumSizeOpt.32bit.diff b/tests/mir-opt/enum_opt.cand.EnumSizeOpt.32bit.diff
new file mode 100644
index 000000000..b139deeee
--- /dev/null
+++ b/tests/mir-opt/enum_opt.cand.EnumSizeOpt.32bit.diff
@@ -0,0 +1,68 @@
+- // MIR for `cand` before EnumSizeOpt
++ // MIR for `cand` after EnumSizeOpt
+
+ fn cand() -> Candidate {
+ let mut _0: Candidate; // return place in scope 0 at $DIR/enum_opt.rs:+0:18: +0:27
+ let mut _1: Candidate; // in scope 0 at $DIR/enum_opt.rs:+1:7: +1:12
+ let mut _2: Candidate; // in scope 0 at $DIR/enum_opt.rs:+2:7: +2:34
+ let mut _3: [u8; 8196]; // in scope 0 at $DIR/enum_opt.rs:+2:24: +2:33
++ let mut _4: [usize; 2]; // in scope 0 at $DIR/enum_opt.rs:+2:3: +2:34
++ let mut _5: isize; // in scope 0 at $DIR/enum_opt.rs:+2:3: +2:34
++ let mut _6: usize; // in scope 0 at $DIR/enum_opt.rs:+2:3: +2:34
++ let mut _7: usize; // in scope 0 at $DIR/enum_opt.rs:+2:3: +2:34
++ let mut _8: *mut Candidate; // in scope 0 at $DIR/enum_opt.rs:+2:3: +2:34
++ let mut _9: *mut u8; // in scope 0 at $DIR/enum_opt.rs:+2:3: +2:34
++ let mut _10: *const Candidate; // in scope 0 at $DIR/enum_opt.rs:+2:3: +2:34
++ let mut _11: *const u8; // in scope 0 at $DIR/enum_opt.rs:+2:3: +2:34
++ let mut _12: [usize; 2]; // in scope 0 at $DIR/enum_opt.rs:+3:3: +3:4
++ let mut _13: isize; // in scope 0 at $DIR/enum_opt.rs:+3:3: +3:4
++ let mut _14: usize; // in scope 0 at $DIR/enum_opt.rs:+3:3: +3:4
++ let mut _15: usize; // in scope 0 at $DIR/enum_opt.rs:+3:3: +3:4
++ let mut _16: *mut Candidate; // in scope 0 at $DIR/enum_opt.rs:+3:3: +3:4
++ let mut _17: *mut u8; // in scope 0 at $DIR/enum_opt.rs:+3:3: +3:4
++ let mut _18: *const Candidate; // in scope 0 at $DIR/enum_opt.rs:+3:3: +3:4
++ let mut _19: *const u8; // in scope 0 at $DIR/enum_opt.rs:+3:3: +3:4
+ scope 1 {
+ debug a => _1; // in scope 1 at $DIR/enum_opt.rs:+1:7: +1:12
+ }
+
+ bb0: {
+ StorageLive(_1); // scope 0 at $DIR/enum_opt.rs:+1:7: +1:12
+ _1 = Candidate::Small(const 1_u8); // scope 0 at $DIR/enum_opt.rs:+1:15: +1:34
+ StorageLive(_2); // scope 1 at $DIR/enum_opt.rs:+2:7: +2:34
+ StorageLive(_3); // scope 1 at $DIR/enum_opt.rs:+2:24: +2:33
+ _3 = [const 1_u8; 8196]; // scope 1 at $DIR/enum_opt.rs:+2:24: +2:33
+ _2 = Candidate::Large(move _3); // scope 1 at $DIR/enum_opt.rs:+2:7: +2:34
+ StorageDead(_3); // scope 1 at $DIR/enum_opt.rs:+2:33: +2:34
+- _1 = move _2; // scope 1 at $DIR/enum_opt.rs:+2:3: +2:34
++ StorageLive(_4); // scope 1 at $DIR/enum_opt.rs:+2:3: +2:34
++ _4 = const [2_usize, 8197_usize]; // scope 1 at $DIR/enum_opt.rs:+2:3: +2:34
++ _5 = discriminant(_2); // scope 1 at $DIR/enum_opt.rs:+2:3: +2:34
++ _6 = _5 as usize (IntToInt); // scope 1 at $DIR/enum_opt.rs:+2:3: +2:34
++ _7 = _4[_6]; // scope 1 at $DIR/enum_opt.rs:+2:3: +2:34
++ _8 = &raw mut _1; // scope 1 at $DIR/enum_opt.rs:+2:3: +2:34
++ _9 = _8 as *mut u8 (PtrToPtr); // scope 1 at $DIR/enum_opt.rs:+2:3: +2:34
++ _10 = &raw const _2; // scope 1 at $DIR/enum_opt.rs:+2:3: +2:34
++ _11 = _10 as *const u8 (PtrToPtr); // scope 1 at $DIR/enum_opt.rs:+2:3: +2:34
++ Deinit(_8); // scope 1 at $DIR/enum_opt.rs:+2:3: +2:34
++ copy_nonoverlapping(dst = _9, src = _11, count = _7); // scope 1 at $DIR/enum_opt.rs:+2:3: +2:34
++ StorageDead(_4); // scope 1 at $DIR/enum_opt.rs:+2:3: +2:34
+ StorageDead(_2); // scope 1 at $DIR/enum_opt.rs:+2:33: +2:34
+- _0 = move _1; // scope 1 at $DIR/enum_opt.rs:+3:3: +3:4
++ StorageLive(_12); // scope 1 at $DIR/enum_opt.rs:+3:3: +3:4
++ _12 = const [2_usize, 8197_usize]; // scope 1 at $DIR/enum_opt.rs:+3:3: +3:4
++ _13 = discriminant(_1); // scope 1 at $DIR/enum_opt.rs:+3:3: +3:4
++ _14 = _13 as usize (IntToInt); // scope 1 at $DIR/enum_opt.rs:+3:3: +3:4
++ _15 = _12[_14]; // scope 1 at $DIR/enum_opt.rs:+3:3: +3:4
++ _16 = &raw mut _0; // scope 1 at $DIR/enum_opt.rs:+3:3: +3:4
++ _17 = _16 as *mut u8 (PtrToPtr); // scope 1 at $DIR/enum_opt.rs:+3:3: +3:4
++ _18 = &raw const _1; // scope 1 at $DIR/enum_opt.rs:+3:3: +3:4
++ _19 = _18 as *const u8 (PtrToPtr); // scope 1 at $DIR/enum_opt.rs:+3:3: +3:4
++ Deinit(_16); // scope 1 at $DIR/enum_opt.rs:+3:3: +3:4
++ copy_nonoverlapping(dst = _17, src = _19, count = _15); // scope 1 at $DIR/enum_opt.rs:+3:3: +3:4
++ StorageDead(_12); // scope 1 at $DIR/enum_opt.rs:+3:3: +3:4
+ StorageDead(_1); // scope 0 at $DIR/enum_opt.rs:+4:1: +4:2
+ return; // scope 0 at $DIR/enum_opt.rs:+4:2: +4:2
+ }
+ }
+
diff --git a/tests/mir-opt/enum_opt.cand.EnumSizeOpt.64bit.diff b/tests/mir-opt/enum_opt.cand.EnumSizeOpt.64bit.diff
new file mode 100644
index 000000000..b139deeee
--- /dev/null
+++ b/tests/mir-opt/enum_opt.cand.EnumSizeOpt.64bit.diff
@@ -0,0 +1,68 @@
+- // MIR for `cand` before EnumSizeOpt
++ // MIR for `cand` after EnumSizeOpt
+
+ fn cand() -> Candidate {
+ let mut _0: Candidate; // return place in scope 0 at $DIR/enum_opt.rs:+0:18: +0:27
+ let mut _1: Candidate; // in scope 0 at $DIR/enum_opt.rs:+1:7: +1:12
+ let mut _2: Candidate; // in scope 0 at $DIR/enum_opt.rs:+2:7: +2:34
+ let mut _3: [u8; 8196]; // in scope 0 at $DIR/enum_opt.rs:+2:24: +2:33
++ let mut _4: [usize; 2]; // in scope 0 at $DIR/enum_opt.rs:+2:3: +2:34
++ let mut _5: isize; // in scope 0 at $DIR/enum_opt.rs:+2:3: +2:34
++ let mut _6: usize; // in scope 0 at $DIR/enum_opt.rs:+2:3: +2:34
++ let mut _7: usize; // in scope 0 at $DIR/enum_opt.rs:+2:3: +2:34
++ let mut _8: *mut Candidate; // in scope 0 at $DIR/enum_opt.rs:+2:3: +2:34
++ let mut _9: *mut u8; // in scope 0 at $DIR/enum_opt.rs:+2:3: +2:34
++ let mut _10: *const Candidate; // in scope 0 at $DIR/enum_opt.rs:+2:3: +2:34
++ let mut _11: *const u8; // in scope 0 at $DIR/enum_opt.rs:+2:3: +2:34
++ let mut _12: [usize; 2]; // in scope 0 at $DIR/enum_opt.rs:+3:3: +3:4
++ let mut _13: isize; // in scope 0 at $DIR/enum_opt.rs:+3:3: +3:4
++ let mut _14: usize; // in scope 0 at $DIR/enum_opt.rs:+3:3: +3:4
++ let mut _15: usize; // in scope 0 at $DIR/enum_opt.rs:+3:3: +3:4
++ let mut _16: *mut Candidate; // in scope 0 at $DIR/enum_opt.rs:+3:3: +3:4
++ let mut _17: *mut u8; // in scope 0 at $DIR/enum_opt.rs:+3:3: +3:4
++ let mut _18: *const Candidate; // in scope 0 at $DIR/enum_opt.rs:+3:3: +3:4
++ let mut _19: *const u8; // in scope 0 at $DIR/enum_opt.rs:+3:3: +3:4
+ scope 1 {
+ debug a => _1; // in scope 1 at $DIR/enum_opt.rs:+1:7: +1:12
+ }
+
+ bb0: {
+ StorageLive(_1); // scope 0 at $DIR/enum_opt.rs:+1:7: +1:12
+ _1 = Candidate::Small(const 1_u8); // scope 0 at $DIR/enum_opt.rs:+1:15: +1:34
+ StorageLive(_2); // scope 1 at $DIR/enum_opt.rs:+2:7: +2:34
+ StorageLive(_3); // scope 1 at $DIR/enum_opt.rs:+2:24: +2:33
+ _3 = [const 1_u8; 8196]; // scope 1 at $DIR/enum_opt.rs:+2:24: +2:33
+ _2 = Candidate::Large(move _3); // scope 1 at $DIR/enum_opt.rs:+2:7: +2:34
+ StorageDead(_3); // scope 1 at $DIR/enum_opt.rs:+2:33: +2:34
+- _1 = move _2; // scope 1 at $DIR/enum_opt.rs:+2:3: +2:34
++ StorageLive(_4); // scope 1 at $DIR/enum_opt.rs:+2:3: +2:34
++ _4 = const [2_usize, 8197_usize]; // scope 1 at $DIR/enum_opt.rs:+2:3: +2:34
++ _5 = discriminant(_2); // scope 1 at $DIR/enum_opt.rs:+2:3: +2:34
++ _6 = _5 as usize (IntToInt); // scope 1 at $DIR/enum_opt.rs:+2:3: +2:34
++ _7 = _4[_6]; // scope 1 at $DIR/enum_opt.rs:+2:3: +2:34
++ _8 = &raw mut _1; // scope 1 at $DIR/enum_opt.rs:+2:3: +2:34
++ _9 = _8 as *mut u8 (PtrToPtr); // scope 1 at $DIR/enum_opt.rs:+2:3: +2:34
++ _10 = &raw const _2; // scope 1 at $DIR/enum_opt.rs:+2:3: +2:34
++ _11 = _10 as *const u8 (PtrToPtr); // scope 1 at $DIR/enum_opt.rs:+2:3: +2:34
++ Deinit(_8); // scope 1 at $DIR/enum_opt.rs:+2:3: +2:34
++ copy_nonoverlapping(dst = _9, src = _11, count = _7); // scope 1 at $DIR/enum_opt.rs:+2:3: +2:34
++ StorageDead(_4); // scope 1 at $DIR/enum_opt.rs:+2:3: +2:34
+ StorageDead(_2); // scope 1 at $DIR/enum_opt.rs:+2:33: +2:34
+- _0 = move _1; // scope 1 at $DIR/enum_opt.rs:+3:3: +3:4
++ StorageLive(_12); // scope 1 at $DIR/enum_opt.rs:+3:3: +3:4
++ _12 = const [2_usize, 8197_usize]; // scope 1 at $DIR/enum_opt.rs:+3:3: +3:4
++ _13 = discriminant(_1); // scope 1 at $DIR/enum_opt.rs:+3:3: +3:4
++ _14 = _13 as usize (IntToInt); // scope 1 at $DIR/enum_opt.rs:+3:3: +3:4
++ _15 = _12[_14]; // scope 1 at $DIR/enum_opt.rs:+3:3: +3:4
++ _16 = &raw mut _0; // scope 1 at $DIR/enum_opt.rs:+3:3: +3:4
++ _17 = _16 as *mut u8 (PtrToPtr); // scope 1 at $DIR/enum_opt.rs:+3:3: +3:4
++ _18 = &raw const _1; // scope 1 at $DIR/enum_opt.rs:+3:3: +3:4
++ _19 = _18 as *const u8 (PtrToPtr); // scope 1 at $DIR/enum_opt.rs:+3:3: +3:4
++ Deinit(_16); // scope 1 at $DIR/enum_opt.rs:+3:3: +3:4
++ copy_nonoverlapping(dst = _17, src = _19, count = _15); // scope 1 at $DIR/enum_opt.rs:+3:3: +3:4
++ StorageDead(_12); // scope 1 at $DIR/enum_opt.rs:+3:3: +3:4
+ StorageDead(_1); // scope 0 at $DIR/enum_opt.rs:+4:1: +4:2
+ return; // scope 0 at $DIR/enum_opt.rs:+4:2: +4:2
+ }
+ }
+
diff --git a/tests/mir-opt/enum_opt.invalid.EnumSizeOpt.32bit.diff b/tests/mir-opt/enum_opt.invalid.EnumSizeOpt.32bit.diff
new file mode 100644
index 000000000..a80001149
--- /dev/null
+++ b/tests/mir-opt/enum_opt.invalid.EnumSizeOpt.32bit.diff
@@ -0,0 +1,28 @@
+- // MIR for `invalid` before EnumSizeOpt
++ // MIR for `invalid` after EnumSizeOpt
+
+ fn invalid() -> InvalidIdxs {
+ let mut _0: InvalidIdxs; // return place in scope 0 at $DIR/enum_opt.rs:+0:21: +0:32
+ let mut _1: InvalidIdxs; // in scope 0 at $DIR/enum_opt.rs:+1:7: +1:12
+ let mut _2: InvalidIdxs; // in scope 0 at $DIR/enum_opt.rs:+2:7: +2:36
+ let mut _3: [u64; 1024]; // in scope 0 at $DIR/enum_opt.rs:+2:26: +2:35
+ scope 1 {
+ debug a => _1; // in scope 1 at $DIR/enum_opt.rs:+1:7: +1:12
+ }
+
+ bb0: {
+ StorageLive(_1); // scope 0 at $DIR/enum_opt.rs:+1:7: +1:12
+ _1 = InvalidIdxs::A; // scope 0 at $DIR/enum_opt.rs:+1:15: +1:29
+ StorageLive(_2); // scope 1 at $DIR/enum_opt.rs:+2:7: +2:36
+ StorageLive(_3); // scope 1 at $DIR/enum_opt.rs:+2:26: +2:35
+ _3 = [const 0_u64; 1024]; // scope 1 at $DIR/enum_opt.rs:+2:26: +2:35
+ _2 = InvalidIdxs::Large(move _3); // scope 1 at $DIR/enum_opt.rs:+2:7: +2:36
+ StorageDead(_3); // scope 1 at $DIR/enum_opt.rs:+2:35: +2:36
+ _1 = move _2; // scope 1 at $DIR/enum_opt.rs:+2:3: +2:36
+ StorageDead(_2); // scope 1 at $DIR/enum_opt.rs:+2:35: +2:36
+ _0 = move _1; // scope 1 at $DIR/enum_opt.rs:+3:3: +3:4
+ StorageDead(_1); // scope 0 at $DIR/enum_opt.rs:+4:1: +4:2
+ return; // scope 0 at $DIR/enum_opt.rs:+4:2: +4:2
+ }
+ }
+
diff --git a/tests/mir-opt/enum_opt.invalid.EnumSizeOpt.64bit.diff b/tests/mir-opt/enum_opt.invalid.EnumSizeOpt.64bit.diff
new file mode 100644
index 000000000..a80001149
--- /dev/null
+++ b/tests/mir-opt/enum_opt.invalid.EnumSizeOpt.64bit.diff
@@ -0,0 +1,28 @@
+- // MIR for `invalid` before EnumSizeOpt
++ // MIR for `invalid` after EnumSizeOpt
+
+ fn invalid() -> InvalidIdxs {
+ let mut _0: InvalidIdxs; // return place in scope 0 at $DIR/enum_opt.rs:+0:21: +0:32
+ let mut _1: InvalidIdxs; // in scope 0 at $DIR/enum_opt.rs:+1:7: +1:12
+ let mut _2: InvalidIdxs; // in scope 0 at $DIR/enum_opt.rs:+2:7: +2:36
+ let mut _3: [u64; 1024]; // in scope 0 at $DIR/enum_opt.rs:+2:26: +2:35
+ scope 1 {
+ debug a => _1; // in scope 1 at $DIR/enum_opt.rs:+1:7: +1:12
+ }
+
+ bb0: {
+ StorageLive(_1); // scope 0 at $DIR/enum_opt.rs:+1:7: +1:12
+ _1 = InvalidIdxs::A; // scope 0 at $DIR/enum_opt.rs:+1:15: +1:29
+ StorageLive(_2); // scope 1 at $DIR/enum_opt.rs:+2:7: +2:36
+ StorageLive(_3); // scope 1 at $DIR/enum_opt.rs:+2:26: +2:35
+ _3 = [const 0_u64; 1024]; // scope 1 at $DIR/enum_opt.rs:+2:26: +2:35
+ _2 = InvalidIdxs::Large(move _3); // scope 1 at $DIR/enum_opt.rs:+2:7: +2:36
+ StorageDead(_3); // scope 1 at $DIR/enum_opt.rs:+2:35: +2:36
+ _1 = move _2; // scope 1 at $DIR/enum_opt.rs:+2:3: +2:36
+ StorageDead(_2); // scope 1 at $DIR/enum_opt.rs:+2:35: +2:36
+ _0 = move _1; // scope 1 at $DIR/enum_opt.rs:+3:3: +3:4
+ StorageDead(_1); // scope 0 at $DIR/enum_opt.rs:+4:1: +4:2
+ return; // scope 0 at $DIR/enum_opt.rs:+4:2: +4:2
+ }
+ }
+
diff --git a/tests/mir-opt/enum_opt.rs b/tests/mir-opt/enum_opt.rs
new file mode 100644
index 000000000..2768d7080
--- /dev/null
+++ b/tests/mir-opt/enum_opt.rs
@@ -0,0 +1,86 @@
+// unit-test: EnumSizeOpt
+// EMIT_MIR_FOR_EACH_BIT_WIDTH
+// compile-flags: -Zunsound-mir-opts
+
+#![feature(arbitrary_enum_discriminant, repr128)]
+
+// Tests that an enum with a variant with no data gets correctly transformed.
+pub enum NoData {
+ Large([u8; 8196]),
+ None,
+}
+
+// Tests that an enum with a variant with data that is a valid candidate gets transformed.
+pub enum Candidate {
+ Small(u8),
+ Large([u8; 8196]),
+}
+
+// Tests that an enum which has a discriminant much higher than the variant does not get
+// tformed.
+#[repr(u32)]
+pub enum InvalidIdxs {
+ A = 302,
+ Large([u64; 1024]),
+}
+
+// Tests that an enum with too high of a discriminant index (not in bounds of usize) does not
+// get tformed.
+#[repr(u128)]
+pub enum NotTrunctable {
+ A = 0,
+ B([u8; 1024]) = 1,
+ C([u8; 4096]) = 0x10000000000000001,
+}
+
+// Tests that an enum with discriminants in random order still gets tformed correctly.
+#[repr(u32)]
+pub enum RandOrderDiscr {
+ A = 13,
+ B([u8; 1024]) = 5,
+ C = 7,
+}
+
+// EMIT_MIR enum_opt.unin.EnumSizeOpt.diff
+pub fn unin() -> NoData {
+ let mut a = NoData::None;
+ a = NoData::Large([1; 8196]);
+ a
+}
+
+// EMIT_MIR enum_opt.cand.EnumSizeOpt.diff
+pub fn cand() -> Candidate {
+ let mut a = Candidate::Small(1);
+ a = Candidate::Large([1; 8196]);
+ a
+}
+
+// EMIT_MIR enum_opt.invalid.EnumSizeOpt.diff
+pub fn invalid() -> InvalidIdxs {
+ let mut a = InvalidIdxs::A;
+ a = InvalidIdxs::Large([0; 1024]);
+ a
+}
+
+// EMIT_MIR enum_opt.trunc.EnumSizeOpt.diff
+pub fn trunc() -> NotTrunctable {
+ let mut a = NotTrunctable::A;
+ a = NotTrunctable::B([0; 1024]);
+ a = NotTrunctable::C([0; 4096]);
+ a
+}
+
+pub fn rand_order() -> RandOrderDiscr {
+ let mut a = RandOrderDiscr::A;
+ a = RandOrderDiscr::B([0; 1024]);
+ a = RandOrderDiscr::C;
+ a
+}
+
+pub fn main() {
+ unin();
+ cand();
+ invalid();
+ trunc();
+ rand_order();
+}
diff --git a/tests/mir-opt/enum_opt.trunc.EnumSizeOpt.32bit.diff b/tests/mir-opt/enum_opt.trunc.EnumSizeOpt.32bit.diff
new file mode 100644
index 000000000..1ef79044d
--- /dev/null
+++ b/tests/mir-opt/enum_opt.trunc.EnumSizeOpt.32bit.diff
@@ -0,0 +1,37 @@
+- // MIR for `trunc` before EnumSizeOpt
++ // MIR for `trunc` after EnumSizeOpt
+
+ fn trunc() -> NotTrunctable {
+ let mut _0: NotTrunctable; // return place in scope 0 at $DIR/enum_opt.rs:+0:19: +0:32
+ let mut _1: NotTrunctable; // in scope 0 at $DIR/enum_opt.rs:+1:7: +1:12
+ let mut _2: NotTrunctable; // in scope 0 at $DIR/enum_opt.rs:+2:7: +2:34
+ let mut _3: [u8; 1024]; // in scope 0 at $DIR/enum_opt.rs:+2:24: +2:33
+ let mut _4: NotTrunctable; // in scope 0 at $DIR/enum_opt.rs:+3:7: +3:34
+ let mut _5: [u8; 4096]; // in scope 0 at $DIR/enum_opt.rs:+3:24: +3:33
+ scope 1 {
+ debug a => _1; // in scope 1 at $DIR/enum_opt.rs:+1:7: +1:12
+ }
+
+ bb0: {
+ StorageLive(_1); // scope 0 at $DIR/enum_opt.rs:+1:7: +1:12
+ _1 = NotTrunctable::A; // scope 0 at $DIR/enum_opt.rs:+1:15: +1:31
+ StorageLive(_2); // scope 1 at $DIR/enum_opt.rs:+2:7: +2:34
+ StorageLive(_3); // scope 1 at $DIR/enum_opt.rs:+2:24: +2:33
+ _3 = [const 0_u8; 1024]; // scope 1 at $DIR/enum_opt.rs:+2:24: +2:33
+ _2 = NotTrunctable::B(move _3); // scope 1 at $DIR/enum_opt.rs:+2:7: +2:34
+ StorageDead(_3); // scope 1 at $DIR/enum_opt.rs:+2:33: +2:34
+ _1 = move _2; // scope 1 at $DIR/enum_opt.rs:+2:3: +2:34
+ StorageDead(_2); // scope 1 at $DIR/enum_opt.rs:+2:33: +2:34
+ StorageLive(_4); // scope 1 at $DIR/enum_opt.rs:+3:7: +3:34
+ StorageLive(_5); // scope 1 at $DIR/enum_opt.rs:+3:24: +3:33
+ _5 = [const 0_u8; 4096]; // scope 1 at $DIR/enum_opt.rs:+3:24: +3:33
+ _4 = NotTrunctable::C(move _5); // scope 1 at $DIR/enum_opt.rs:+3:7: +3:34
+ StorageDead(_5); // scope 1 at $DIR/enum_opt.rs:+3:33: +3:34
+ _1 = move _4; // scope 1 at $DIR/enum_opt.rs:+3:3: +3:34
+ StorageDead(_4); // scope 1 at $DIR/enum_opt.rs:+3:33: +3:34
+ _0 = move _1; // scope 1 at $DIR/enum_opt.rs:+4:3: +4:4
+ StorageDead(_1); // scope 0 at $DIR/enum_opt.rs:+5:1: +5:2
+ return; // scope 0 at $DIR/enum_opt.rs:+5:2: +5:2
+ }
+ }
+
diff --git a/tests/mir-opt/enum_opt.trunc.EnumSizeOpt.64bit.diff b/tests/mir-opt/enum_opt.trunc.EnumSizeOpt.64bit.diff
new file mode 100644
index 000000000..1ef79044d
--- /dev/null
+++ b/tests/mir-opt/enum_opt.trunc.EnumSizeOpt.64bit.diff
@@ -0,0 +1,37 @@
+- // MIR for `trunc` before EnumSizeOpt
++ // MIR for `trunc` after EnumSizeOpt
+
+ fn trunc() -> NotTrunctable {
+ let mut _0: NotTrunctable; // return place in scope 0 at $DIR/enum_opt.rs:+0:19: +0:32
+ let mut _1: NotTrunctable; // in scope 0 at $DIR/enum_opt.rs:+1:7: +1:12
+ let mut _2: NotTrunctable; // in scope 0 at $DIR/enum_opt.rs:+2:7: +2:34
+ let mut _3: [u8; 1024]; // in scope 0 at $DIR/enum_opt.rs:+2:24: +2:33
+ let mut _4: NotTrunctable; // in scope 0 at $DIR/enum_opt.rs:+3:7: +3:34
+ let mut _5: [u8; 4096]; // in scope 0 at $DIR/enum_opt.rs:+3:24: +3:33
+ scope 1 {
+ debug a => _1; // in scope 1 at $DIR/enum_opt.rs:+1:7: +1:12
+ }
+
+ bb0: {
+ StorageLive(_1); // scope 0 at $DIR/enum_opt.rs:+1:7: +1:12
+ _1 = NotTrunctable::A; // scope 0 at $DIR/enum_opt.rs:+1:15: +1:31
+ StorageLive(_2); // scope 1 at $DIR/enum_opt.rs:+2:7: +2:34
+ StorageLive(_3); // scope 1 at $DIR/enum_opt.rs:+2:24: +2:33
+ _3 = [const 0_u8; 1024]; // scope 1 at $DIR/enum_opt.rs:+2:24: +2:33
+ _2 = NotTrunctable::B(move _3); // scope 1 at $DIR/enum_opt.rs:+2:7: +2:34
+ StorageDead(_3); // scope 1 at $DIR/enum_opt.rs:+2:33: +2:34
+ _1 = move _2; // scope 1 at $DIR/enum_opt.rs:+2:3: +2:34
+ StorageDead(_2); // scope 1 at $DIR/enum_opt.rs:+2:33: +2:34
+ StorageLive(_4); // scope 1 at $DIR/enum_opt.rs:+3:7: +3:34
+ StorageLive(_5); // scope 1 at $DIR/enum_opt.rs:+3:24: +3:33
+ _5 = [const 0_u8; 4096]; // scope 1 at $DIR/enum_opt.rs:+3:24: +3:33
+ _4 = NotTrunctable::C(move _5); // scope 1 at $DIR/enum_opt.rs:+3:7: +3:34
+ StorageDead(_5); // scope 1 at $DIR/enum_opt.rs:+3:33: +3:34
+ _1 = move _4; // scope 1 at $DIR/enum_opt.rs:+3:3: +3:34
+ StorageDead(_4); // scope 1 at $DIR/enum_opt.rs:+3:33: +3:34
+ _0 = move _1; // scope 1 at $DIR/enum_opt.rs:+4:3: +4:4
+ StorageDead(_1); // scope 0 at $DIR/enum_opt.rs:+5:1: +5:2
+ return; // scope 0 at $DIR/enum_opt.rs:+5:2: +5:2
+ }
+ }
+
diff --git a/tests/mir-opt/enum_opt.unin.EnumSizeOpt.32bit.diff b/tests/mir-opt/enum_opt.unin.EnumSizeOpt.32bit.diff
new file mode 100644
index 000000000..ad9f12cf9
--- /dev/null
+++ b/tests/mir-opt/enum_opt.unin.EnumSizeOpt.32bit.diff
@@ -0,0 +1,68 @@
+- // MIR for `unin` before EnumSizeOpt
++ // MIR for `unin` after EnumSizeOpt
+
+ fn unin() -> NoData {
+ let mut _0: NoData; // return place in scope 0 at $DIR/enum_opt.rs:+0:18: +0:24
+ let mut _1: NoData; // in scope 0 at $DIR/enum_opt.rs:+1:7: +1:12
+ let mut _2: NoData; // in scope 0 at $DIR/enum_opt.rs:+2:7: +2:31
+ let mut _3: [u8; 8196]; // in scope 0 at $DIR/enum_opt.rs:+2:21: +2:30
++ let mut _4: [usize; 2]; // in scope 0 at $DIR/enum_opt.rs:+2:3: +2:31
++ let mut _5: isize; // in scope 0 at $DIR/enum_opt.rs:+2:3: +2:31
++ let mut _6: usize; // in scope 0 at $DIR/enum_opt.rs:+2:3: +2:31
++ let mut _7: usize; // in scope 0 at $DIR/enum_opt.rs:+2:3: +2:31
++ let mut _8: *mut NoData; // in scope 0 at $DIR/enum_opt.rs:+2:3: +2:31
++ let mut _9: *mut u8; // in scope 0 at $DIR/enum_opt.rs:+2:3: +2:31
++ let mut _10: *const NoData; // in scope 0 at $DIR/enum_opt.rs:+2:3: +2:31
++ let mut _11: *const u8; // in scope 0 at $DIR/enum_opt.rs:+2:3: +2:31
++ let mut _12: [usize; 2]; // in scope 0 at $DIR/enum_opt.rs:+3:3: +3:4
++ let mut _13: isize; // in scope 0 at $DIR/enum_opt.rs:+3:3: +3:4
++ let mut _14: usize; // in scope 0 at $DIR/enum_opt.rs:+3:3: +3:4
++ let mut _15: usize; // in scope 0 at $DIR/enum_opt.rs:+3:3: +3:4
++ let mut _16: *mut NoData; // in scope 0 at $DIR/enum_opt.rs:+3:3: +3:4
++ let mut _17: *mut u8; // in scope 0 at $DIR/enum_opt.rs:+3:3: +3:4
++ let mut _18: *const NoData; // in scope 0 at $DIR/enum_opt.rs:+3:3: +3:4
++ let mut _19: *const u8; // in scope 0 at $DIR/enum_opt.rs:+3:3: +3:4
+ scope 1 {
+ debug a => _1; // in scope 1 at $DIR/enum_opt.rs:+1:7: +1:12
+ }
+
+ bb0: {
+ StorageLive(_1); // scope 0 at $DIR/enum_opt.rs:+1:7: +1:12
+ _1 = NoData::None; // scope 0 at $DIR/enum_opt.rs:+1:15: +1:27
+ StorageLive(_2); // scope 1 at $DIR/enum_opt.rs:+2:7: +2:31
+ StorageLive(_3); // scope 1 at $DIR/enum_opt.rs:+2:21: +2:30
+ _3 = [const 1_u8; 8196]; // scope 1 at $DIR/enum_opt.rs:+2:21: +2:30
+ _2 = NoData::Large(move _3); // scope 1 at $DIR/enum_opt.rs:+2:7: +2:31
+ StorageDead(_3); // scope 1 at $DIR/enum_opt.rs:+2:30: +2:31
+- _1 = move _2; // scope 1 at $DIR/enum_opt.rs:+2:3: +2:31
++ StorageLive(_4); // scope 1 at $DIR/enum_opt.rs:+2:3: +2:31
++ _4 = const [8197_usize, 1_usize]; // scope 1 at $DIR/enum_opt.rs:+2:3: +2:31
++ _5 = discriminant(_2); // scope 1 at $DIR/enum_opt.rs:+2:3: +2:31
++ _6 = _5 as usize (IntToInt); // scope 1 at $DIR/enum_opt.rs:+2:3: +2:31
++ _7 = _4[_6]; // scope 1 at $DIR/enum_opt.rs:+2:3: +2:31
++ _8 = &raw mut _1; // scope 1 at $DIR/enum_opt.rs:+2:3: +2:31
++ _9 = _8 as *mut u8 (PtrToPtr); // scope 1 at $DIR/enum_opt.rs:+2:3: +2:31
++ _10 = &raw const _2; // scope 1 at $DIR/enum_opt.rs:+2:3: +2:31
++ _11 = _10 as *const u8 (PtrToPtr); // scope 1 at $DIR/enum_opt.rs:+2:3: +2:31
++ Deinit(_8); // scope 1 at $DIR/enum_opt.rs:+2:3: +2:31
++ copy_nonoverlapping(dst = _9, src = _11, count = _7); // scope 1 at $DIR/enum_opt.rs:+2:3: +2:31
++ StorageDead(_4); // scope 1 at $DIR/enum_opt.rs:+2:3: +2:31
+ StorageDead(_2); // scope 1 at $DIR/enum_opt.rs:+2:30: +2:31
+- _0 = move _1; // scope 1 at $DIR/enum_opt.rs:+3:3: +3:4
++ StorageLive(_12); // scope 1 at $DIR/enum_opt.rs:+3:3: +3:4
++ _12 = const [8197_usize, 1_usize]; // scope 1 at $DIR/enum_opt.rs:+3:3: +3:4
++ _13 = discriminant(_1); // scope 1 at $DIR/enum_opt.rs:+3:3: +3:4
++ _14 = _13 as usize (IntToInt); // scope 1 at $DIR/enum_opt.rs:+3:3: +3:4
++ _15 = _12[_14]; // scope 1 at $DIR/enum_opt.rs:+3:3: +3:4
++ _16 = &raw mut _0; // scope 1 at $DIR/enum_opt.rs:+3:3: +3:4
++ _17 = _16 as *mut u8 (PtrToPtr); // scope 1 at $DIR/enum_opt.rs:+3:3: +3:4
++ _18 = &raw const _1; // scope 1 at $DIR/enum_opt.rs:+3:3: +3:4
++ _19 = _18 as *const u8 (PtrToPtr); // scope 1 at $DIR/enum_opt.rs:+3:3: +3:4
++ Deinit(_16); // scope 1 at $DIR/enum_opt.rs:+3:3: +3:4
++ copy_nonoverlapping(dst = _17, src = _19, count = _15); // scope 1 at $DIR/enum_opt.rs:+3:3: +3:4
++ StorageDead(_12); // scope 1 at $DIR/enum_opt.rs:+3:3: +3:4
+ StorageDead(_1); // scope 0 at $DIR/enum_opt.rs:+4:1: +4:2
+ return; // scope 0 at $DIR/enum_opt.rs:+4:2: +4:2
+ }
+ }
+
diff --git a/tests/mir-opt/enum_opt.unin.EnumSizeOpt.64bit.diff b/tests/mir-opt/enum_opt.unin.EnumSizeOpt.64bit.diff
new file mode 100644
index 000000000..ad9f12cf9
--- /dev/null
+++ b/tests/mir-opt/enum_opt.unin.EnumSizeOpt.64bit.diff
@@ -0,0 +1,68 @@
+- // MIR for `unin` before EnumSizeOpt
++ // MIR for `unin` after EnumSizeOpt
+
+ fn unin() -> NoData {
+ let mut _0: NoData; // return place in scope 0 at $DIR/enum_opt.rs:+0:18: +0:24
+ let mut _1: NoData; // in scope 0 at $DIR/enum_opt.rs:+1:7: +1:12
+ let mut _2: NoData; // in scope 0 at $DIR/enum_opt.rs:+2:7: +2:31
+ let mut _3: [u8; 8196]; // in scope 0 at $DIR/enum_opt.rs:+2:21: +2:30
++ let mut _4: [usize; 2]; // in scope 0 at $DIR/enum_opt.rs:+2:3: +2:31
++ let mut _5: isize; // in scope 0 at $DIR/enum_opt.rs:+2:3: +2:31
++ let mut _6: usize; // in scope 0 at $DIR/enum_opt.rs:+2:3: +2:31
++ let mut _7: usize; // in scope 0 at $DIR/enum_opt.rs:+2:3: +2:31
++ let mut _8: *mut NoData; // in scope 0 at $DIR/enum_opt.rs:+2:3: +2:31
++ let mut _9: *mut u8; // in scope 0 at $DIR/enum_opt.rs:+2:3: +2:31
++ let mut _10: *const NoData; // in scope 0 at $DIR/enum_opt.rs:+2:3: +2:31
++ let mut _11: *const u8; // in scope 0 at $DIR/enum_opt.rs:+2:3: +2:31
++ let mut _12: [usize; 2]; // in scope 0 at $DIR/enum_opt.rs:+3:3: +3:4
++ let mut _13: isize; // in scope 0 at $DIR/enum_opt.rs:+3:3: +3:4
++ let mut _14: usize; // in scope 0 at $DIR/enum_opt.rs:+3:3: +3:4
++ let mut _15: usize; // in scope 0 at $DIR/enum_opt.rs:+3:3: +3:4
++ let mut _16: *mut NoData; // in scope 0 at $DIR/enum_opt.rs:+3:3: +3:4
++ let mut _17: *mut u8; // in scope 0 at $DIR/enum_opt.rs:+3:3: +3:4
++ let mut _18: *const NoData; // in scope 0 at $DIR/enum_opt.rs:+3:3: +3:4
++ let mut _19: *const u8; // in scope 0 at $DIR/enum_opt.rs:+3:3: +3:4
+ scope 1 {
+ debug a => _1; // in scope 1 at $DIR/enum_opt.rs:+1:7: +1:12
+ }
+
+ bb0: {
+ StorageLive(_1); // scope 0 at $DIR/enum_opt.rs:+1:7: +1:12
+ _1 = NoData::None; // scope 0 at $DIR/enum_opt.rs:+1:15: +1:27
+ StorageLive(_2); // scope 1 at $DIR/enum_opt.rs:+2:7: +2:31
+ StorageLive(_3); // scope 1 at $DIR/enum_opt.rs:+2:21: +2:30
+ _3 = [const 1_u8; 8196]; // scope 1 at $DIR/enum_opt.rs:+2:21: +2:30
+ _2 = NoData::Large(move _3); // scope 1 at $DIR/enum_opt.rs:+2:7: +2:31
+ StorageDead(_3); // scope 1 at $DIR/enum_opt.rs:+2:30: +2:31
+- _1 = move _2; // scope 1 at $DIR/enum_opt.rs:+2:3: +2:31
++ StorageLive(_4); // scope 1 at $DIR/enum_opt.rs:+2:3: +2:31
++ _4 = const [8197_usize, 1_usize]; // scope 1 at $DIR/enum_opt.rs:+2:3: +2:31
++ _5 = discriminant(_2); // scope 1 at $DIR/enum_opt.rs:+2:3: +2:31
++ _6 = _5 as usize (IntToInt); // scope 1 at $DIR/enum_opt.rs:+2:3: +2:31
++ _7 = _4[_6]; // scope 1 at $DIR/enum_opt.rs:+2:3: +2:31
++ _8 = &raw mut _1; // scope 1 at $DIR/enum_opt.rs:+2:3: +2:31
++ _9 = _8 as *mut u8 (PtrToPtr); // scope 1 at $DIR/enum_opt.rs:+2:3: +2:31
++ _10 = &raw const _2; // scope 1 at $DIR/enum_opt.rs:+2:3: +2:31
++ _11 = _10 as *const u8 (PtrToPtr); // scope 1 at $DIR/enum_opt.rs:+2:3: +2:31
++ Deinit(_8); // scope 1 at $DIR/enum_opt.rs:+2:3: +2:31
++ copy_nonoverlapping(dst = _9, src = _11, count = _7); // scope 1 at $DIR/enum_opt.rs:+2:3: +2:31
++ StorageDead(_4); // scope 1 at $DIR/enum_opt.rs:+2:3: +2:31
+ StorageDead(_2); // scope 1 at $DIR/enum_opt.rs:+2:30: +2:31
+- _0 = move _1; // scope 1 at $DIR/enum_opt.rs:+3:3: +3:4
++ StorageLive(_12); // scope 1 at $DIR/enum_opt.rs:+3:3: +3:4
++ _12 = const [8197_usize, 1_usize]; // scope 1 at $DIR/enum_opt.rs:+3:3: +3:4
++ _13 = discriminant(_1); // scope 1 at $DIR/enum_opt.rs:+3:3: +3:4
++ _14 = _13 as usize (IntToInt); // scope 1 at $DIR/enum_opt.rs:+3:3: +3:4
++ _15 = _12[_14]; // scope 1 at $DIR/enum_opt.rs:+3:3: +3:4
++ _16 = &raw mut _0; // scope 1 at $DIR/enum_opt.rs:+3:3: +3:4
++ _17 = _16 as *mut u8 (PtrToPtr); // scope 1 at $DIR/enum_opt.rs:+3:3: +3:4
++ _18 = &raw const _1; // scope 1 at $DIR/enum_opt.rs:+3:3: +3:4
++ _19 = _18 as *const u8 (PtrToPtr); // scope 1 at $DIR/enum_opt.rs:+3:3: +3:4
++ Deinit(_16); // scope 1 at $DIR/enum_opt.rs:+3:3: +3:4
++ copy_nonoverlapping(dst = _17, src = _19, count = _15); // scope 1 at $DIR/enum_opt.rs:+3:3: +3:4
++ StorageDead(_12); // scope 1 at $DIR/enum_opt.rs:+3:3: +3:4
+ StorageDead(_1); // scope 0 at $DIR/enum_opt.rs:+4:1: +4:2
+ return; // scope 0 at $DIR/enum_opt.rs:+4:2: +4:2
+ }
+ }
+
diff --git a/tests/mir-opt/funky_arms.float_to_exponential_common.ConstProp.diff b/tests/mir-opt/funky_arms.float_to_exponential_common.ConstProp.diff
index c1c2cde71..1f5c53381 100644
--- a/tests/mir-opt/funky_arms.float_to_exponential_common.ConstProp.diff
+++ b/tests/mir-opt/funky_arms.float_to_exponential_common.ConstProp.diff
@@ -51,14 +51,20 @@
}
bb2: {
- Deinit(_6); // scope 1 at $DIR/funky_arms.rs:+10:17: +10:41
- discriminant(_6) = 1; // scope 1 at $DIR/funky_arms.rs:+10:17: +10:41
+- _6 = MinusPlus; // scope 1 at $DIR/funky_arms.rs:+10:17: +10:41
++ _6 = const MinusPlus; // scope 1 at $DIR/funky_arms.rs:+10:17: +10:41
++ // mir::Constant
++ // + span: $DIR/funky_arms.rs:21:17: 21:41
++ // + literal: Const { ty: Sign, val: Value(Scalar(0x01)) }
goto -> bb4; // scope 1 at $DIR/funky_arms.rs:+10:17: +10:41
}
bb3: {
- Deinit(_6); // scope 1 at $DIR/funky_arms.rs:+9:18: +9:38
- discriminant(_6) = 0; // scope 1 at $DIR/funky_arms.rs:+9:18: +9:38
+- _6 = Minus; // scope 1 at $DIR/funky_arms.rs:+9:18: +9:38
++ _6 = const Minus; // scope 1 at $DIR/funky_arms.rs:+9:18: +9:38
++ // mir::Constant
++ // + span: $DIR/funky_arms.rs:20:18: 20:38
++ // + literal: Const { ty: Sign, val: Value(Scalar(0x00)) }
goto -> bb4; // scope 1 at $DIR/funky_arms.rs:+9:18: +9:38
}
@@ -79,60 +85,37 @@
}
bb6: {
- StorageLive(_10); // scope 3 at $DIR/funky_arms.rs:+13:17: +13:26
_10 = ((_7 as Some).0: usize); // scope 3 at $DIR/funky_arms.rs:+13:17: +13:26
- StorageLive(_11); // scope 3 at $DIR/funky_arms.rs:+15:43: +15:46
- _11 = &mut (*_1); // scope 3 at $DIR/funky_arms.rs:+15:43: +15:46
- StorageLive(_12); // scope 3 at $DIR/funky_arms.rs:+15:48: +15:51
- _12 = _2; // scope 3 at $DIR/funky_arms.rs:+15:48: +15:51
StorageLive(_13); // scope 3 at $DIR/funky_arms.rs:+15:53: +15:57
_13 = _6; // scope 3 at $DIR/funky_arms.rs:+15:53: +15:57
StorageLive(_14); // scope 3 at $DIR/funky_arms.rs:+15:59: +15:79
StorageLive(_15); // scope 3 at $DIR/funky_arms.rs:+15:59: +15:75
- StorageLive(_16); // scope 3 at $DIR/funky_arms.rs:+15:59: +15:68
- _16 = _10; // scope 3 at $DIR/funky_arms.rs:+15:59: +15:68
- _15 = move _16 as u32 (IntToInt); // scope 3 at $DIR/funky_arms.rs:+15:59: +15:75
- StorageDead(_16); // scope 3 at $DIR/funky_arms.rs:+15:74: +15:75
+ _15 = _10 as u32 (IntToInt); // scope 3 at $DIR/funky_arms.rs:+15:59: +15:75
_14 = Add(move _15, const 1_u32); // scope 3 at $DIR/funky_arms.rs:+15:59: +15:79
StorageDead(_15); // scope 3 at $DIR/funky_arms.rs:+15:78: +15:79
- StorageLive(_17); // scope 3 at $DIR/funky_arms.rs:+15:81: +15:86
- _17 = _3; // scope 3 at $DIR/funky_arms.rs:+15:81: +15:86
- _0 = float_to_exponential_common_exact::<T>(move _11, move _12, move _13, move _14, move _17) -> bb7; // scope 3 at $DIR/funky_arms.rs:+15:9: +15:87
+ _0 = float_to_exponential_common_exact::<T>(_1, _2, move _13, move _14, _3) -> bb7; // scope 3 at $DIR/funky_arms.rs:+15:9: +15:87
// mir::Constant
// + span: $DIR/funky_arms.rs:26:9: 26:42
// + literal: Const { ty: for<'a, 'b, 'c> fn(&'a mut Formatter<'b>, &'c T, Sign, u32, bool) -> Result<(), std::fmt::Error> {float_to_exponential_common_exact::<T>}, val: Value(<ZST>) }
}
bb7: {
- StorageDead(_17); // scope 3 at $DIR/funky_arms.rs:+15:86: +15:87
StorageDead(_14); // scope 3 at $DIR/funky_arms.rs:+15:86: +15:87
StorageDead(_13); // scope 3 at $DIR/funky_arms.rs:+15:86: +15:87
- StorageDead(_12); // scope 3 at $DIR/funky_arms.rs:+15:86: +15:87
- StorageDead(_11); // scope 3 at $DIR/funky_arms.rs:+15:86: +15:87
- StorageDead(_10); // scope 2 at $DIR/funky_arms.rs:+16:5: +16:6
goto -> bb10; // scope 2 at $DIR/funky_arms.rs:+13:5: +18:6
}
bb8: {
- StorageLive(_18); // scope 2 at $DIR/funky_arms.rs:+17:46: +17:49
- _18 = &mut (*_1); // scope 2 at $DIR/funky_arms.rs:+17:46: +17:49
- StorageLive(_19); // scope 2 at $DIR/funky_arms.rs:+17:51: +17:54
- _19 = _2; // scope 2 at $DIR/funky_arms.rs:+17:51: +17:54
StorageLive(_20); // scope 2 at $DIR/funky_arms.rs:+17:56: +17:60
_20 = _6; // scope 2 at $DIR/funky_arms.rs:+17:56: +17:60
- StorageLive(_21); // scope 2 at $DIR/funky_arms.rs:+17:62: +17:67
- _21 = _3; // scope 2 at $DIR/funky_arms.rs:+17:62: +17:67
- _0 = float_to_exponential_common_shortest::<T>(move _18, move _19, move _20, move _21) -> bb9; // scope 2 at $DIR/funky_arms.rs:+17:9: +17:68
+ _0 = float_to_exponential_common_shortest::<T>(_1, _2, move _20, _3) -> bb9; // scope 2 at $DIR/funky_arms.rs:+17:9: +17:68
// mir::Constant
// + span: $DIR/funky_arms.rs:28:9: 28:45
// + literal: Const { ty: for<'a, 'b, 'c> fn(&'a mut Formatter<'b>, &'c T, Sign, bool) -> Result<(), std::fmt::Error> {float_to_exponential_common_shortest::<T>}, val: Value(<ZST>) }
}
bb9: {
- StorageDead(_21); // scope 2 at $DIR/funky_arms.rs:+17:67: +17:68
StorageDead(_20); // scope 2 at $DIR/funky_arms.rs:+17:67: +17:68
- StorageDead(_19); // scope 2 at $DIR/funky_arms.rs:+17:67: +17:68
- StorageDead(_18); // scope 2 at $DIR/funky_arms.rs:+17:67: +17:68
goto -> bb10; // scope 2 at $DIR/funky_arms.rs:+13:5: +18:6
}
diff --git a/tests/mir-opt/generator_drop_cleanup.main-{closure#0}.generator_drop.0.mir b/tests/mir-opt/generator_drop_cleanup.main-{closure#0}.generator_drop.0.mir
index a8e090020..afe518642 100644
--- a/tests/mir-opt/generator_drop_cleanup.main-{closure#0}.generator_drop.0.mir
+++ b/tests/mir-opt/generator_drop_cleanup.main-{closure#0}.generator_drop.0.mir
@@ -1,7 +1,14 @@
// MIR for `main::{closure#0}` 0 generator_drop
/* generator_layout = GeneratorLayout {
field_tys: {
- _0: std::string::String,
+ _0: GeneratorSavedTy {
+ ty: std::string::String,
+ source_info: SourceInfo {
+ span: $DIR/generator_drop_cleanup.rs:11:13: 11:15 (#0),
+ scope: scope[0],
+ },
+ ignore_for_traits: false,
+ },
},
variant_fields: {
Unresumed(0): [],
diff --git a/tests/mir-opt/generator_tiny.main-{closure#0}.generator_resume.0.mir b/tests/mir-opt/generator_tiny.main-{closure#0}.generator_resume.0.mir
index b3d3c768a..7efda05d2 100644
--- a/tests/mir-opt/generator_tiny.main-{closure#0}.generator_resume.0.mir
+++ b/tests/mir-opt/generator_tiny.main-{closure#0}.generator_resume.0.mir
@@ -1,7 +1,14 @@
// MIR for `main::{closure#0}` 0 generator_resume
/* generator_layout = GeneratorLayout {
field_tys: {
- _0: HasDrop,
+ _0: GeneratorSavedTy {
+ ty: HasDrop,
+ source_info: SourceInfo {
+ span: $DIR/generator_tiny.rs:20:13: 20:15 (#0),
+ scope: scope[0],
+ },
+ ignore_for_traits: false,
+ },
},
variant_fields: {
Unresumed(0): [],
@@ -47,9 +54,7 @@ fn main::{closure#0}(_1: Pin<&mut [generator@$DIR/generator_tiny.rs:19:16: 19:24
StorageLive(_6); // scope 1 at $DIR/generator_tiny.rs:+3:13: +3:18
StorageLive(_7); // scope 1 at $DIR/generator_tiny.rs:+3:13: +3:18
_7 = (); // scope 1 at $DIR/generator_tiny.rs:+3:13: +3:18
- Deinit(_0); // scope 1 at $DIR/generator_tiny.rs:+3:13: +3:18
- ((_0 as Yielded).0: ()) = move _7; // scope 1 at $DIR/generator_tiny.rs:+3:13: +3:18
- discriminant(_0) = 0; // scope 1 at $DIR/generator_tiny.rs:+3:13: +3:18
+ _0 = GeneratorState::<(), ()>::Yielded(move _7); // scope 1 at $DIR/generator_tiny.rs:+3:13: +3:18
discriminant((*(_1.0: &mut [generator@$DIR/generator_tiny.rs:19:16: 19:24]))) = 3; // scope 1 at $DIR/generator_tiny.rs:+3:13: +3:18
return; // scope 1 at $DIR/generator_tiny.rs:+3:13: +3:18
}
diff --git a/tests/mir-opt/inline/cycle.f.Inline.diff b/tests/mir-opt/inline/cycle.f.Inline.diff
index 75ea69a42..501390c3b 100644
--- a/tests/mir-opt/inline/cycle.f.Inline.diff
+++ b/tests/mir-opt/inline/cycle.f.Inline.diff
@@ -13,7 +13,7 @@
StorageLive(_3); // scope 0 at $DIR/cycle.rs:+1:5: +1:6
_3 = &_1; // scope 0 at $DIR/cycle.rs:+1:5: +1:6
StorageLive(_4); // scope 0 at $DIR/cycle.rs:+1:5: +1:8
- Deinit(_4); // scope 0 at $DIR/cycle.rs:+1:5: +1:8
+ _4 = (); // scope 0 at $DIR/cycle.rs:+1:5: +1:8
_2 = <impl Fn() as Fn<()>>::call(move _3, move _4) -> [return: bb1, unwind: bb3]; // scope 0 at $DIR/cycle.rs:+1:5: +1:8
// mir::Constant
// + span: $DIR/cycle.rs:6:5: 6:6
diff --git a/tests/mir-opt/inline/dyn_trait.get_query.Inline.diff b/tests/mir-opt/inline/dyn_trait.get_query.Inline.diff
index 8ea1a0757..64c3e47ff 100644
--- a/tests/mir-opt/inline/dyn_trait.get_query.Inline.diff
+++ b/tests/mir-opt/inline/dyn_trait.get_query.Inline.diff
@@ -35,8 +35,8 @@
_4 = &(*_2); // scope 1 at $DIR/dyn_trait.rs:+2:23: +2:24
- _0 = try_execute_query::<<Q as Query>::C>(move _4) -> bb2; // scope 1 at $DIR/dyn_trait.rs:+2:5: +2:25
+ StorageLive(_5); // scope 2 at $DIR/dyn_trait.rs:27:14: 27:15
-+ _5 = move _4 as &dyn Cache<V = <Q as Query>::V> (Pointer(Unsize)); // scope 2 at $DIR/dyn_trait.rs:27:14: 27:15
-+ _0 = <dyn Cache<V = <Q as Query>::V> as Cache>::store_nocache(move _5) -> bb2; // scope 3 at $DIR/dyn_trait.rs:21:5: 21:22
++ _5 = _4 as &dyn Cache<V = <Q as Query>::V> (Pointer(Unsize)); // scope 2 at $DIR/dyn_trait.rs:27:14: 27:15
++ _0 = <dyn Cache<V = <Q as Query>::V> as Cache>::store_nocache(_5) -> bb2; // scope 3 at $DIR/dyn_trait.rs:21:5: 21:22
// mir::Constant
- // + span: $DIR/dyn_trait.rs:34:5: 34:22
- // + literal: Const { ty: for<'a> fn(&'a <Q as Query>::C) {try_execute_query::<<Q as Query>::C>}, val: Value(<ZST>) }
diff --git a/tests/mir-opt/inline/dyn_trait.try_execute_query.Inline.diff b/tests/mir-opt/inline/dyn_trait.try_execute_query.Inline.diff
index a71d73b74..3fa9c3e88 100644
--- a/tests/mir-opt/inline/dyn_trait.try_execute_query.Inline.diff
+++ b/tests/mir-opt/inline/dyn_trait.try_execute_query.Inline.diff
@@ -17,7 +17,7 @@
_2 = move _3 as &dyn Cache<V = <C as Cache>::V> (Pointer(Unsize)); // scope 0 at $DIR/dyn_trait.rs:+1:14: +1:15
StorageDead(_3); // scope 0 at $DIR/dyn_trait.rs:+1:14: +1:15
- _0 = mk_cycle::<<C as Cache>::V>(move _2) -> bb1; // scope 0 at $DIR/dyn_trait.rs:+1:5: +1:16
-+ _0 = <dyn Cache<V = <C as Cache>::V> as Cache>::store_nocache(move _2) -> bb1; // scope 1 at $DIR/dyn_trait.rs:21:5: 21:22
++ _0 = <dyn Cache<V = <C as Cache>::V> as Cache>::store_nocache(_2) -> bb1; // scope 1 at $DIR/dyn_trait.rs:21:5: 21:22
// mir::Constant
- // + span: $DIR/dyn_trait.rs:27:5: 27:13
- // + literal: Const { ty: for<'a> fn(&'a (dyn Cache<V = <C as Cache>::V> + 'a)) {mk_cycle::<<C as Cache>::V>}, val: Value(<ZST>) }
diff --git a/tests/mir-opt/inline/inline_any_operand.bar.Inline.after.mir b/tests/mir-opt/inline/inline_any_operand.bar.Inline.after.mir
index 3502c2586..20f737cc2 100644
--- a/tests/mir-opt/inline/inline_any_operand.bar.Inline.after.mir
+++ b/tests/mir-opt/inline/inline_any_operand.bar.Inline.after.mir
@@ -26,7 +26,7 @@ fn bar() -> bool {
_3 = const 1_i32; // scope 1 at $DIR/inline_any_operand.rs:+2:5: +2:13
StorageLive(_4); // scope 1 at $DIR/inline_any_operand.rs:+2:5: +2:13
_4 = const -1_i32; // scope 1 at $DIR/inline_any_operand.rs:+2:5: +2:13
- _0 = Eq(move _3, move _4); // scope 2 at $DIR/inline_any_operand.rs:17:5: 17:11
+ _0 = Eq(_3, _4); // scope 2 at $DIR/inline_any_operand.rs:17:5: 17:11
StorageDead(_4); // scope 1 at $DIR/inline_any_operand.rs:+2:5: +2:13
StorageDead(_3); // scope 1 at $DIR/inline_any_operand.rs:+2:5: +2:13
StorageDead(_2); // scope 1 at $DIR/inline_any_operand.rs:+2:12: +2:13
diff --git a/tests/mir-opt/inline/inline_closure.foo.Inline.after.mir b/tests/mir-opt/inline/inline_closure.foo.Inline.after.mir
index 9eb3a01ee..fff8d0171 100644
--- a/tests/mir-opt/inline/inline_closure.foo.Inline.after.mir
+++ b/tests/mir-opt/inline/inline_closure.foo.Inline.after.mir
@@ -21,7 +21,15 @@ fn foo(_1: T, _2: i32) -> i32 {
bb0: {
StorageLive(_3); // scope 0 at $DIR/inline_closure.rs:+1:9: +1:10
- Deinit(_3); // scope 0 at $DIR/inline_closure.rs:+1:13: +1:24
+ _3 = [closure@foo::<T>::{closure#0}]; // scope 0 at $DIR/inline_closure.rs:+1:13: +1:24
+ // closure
+ // + def_id: DefId(0:6 ~ inline_closure[92ba]::foo::{closure#0})
+ // + substs: [
+ // T,
+ // i8,
+ // extern "rust-call" fn((i32, i32)) -> i32,
+ // (),
+ // ]
StorageLive(_4); // scope 1 at $DIR/inline_closure.rs:+2:5: +2:6
_4 = &_3; // scope 1 at $DIR/inline_closure.rs:+2:5: +2:6
StorageLive(_5); // scope 1 at $DIR/inline_closure.rs:+2:5: +2:12
@@ -29,9 +37,7 @@ fn foo(_1: T, _2: i32) -> i32 {
_6 = _2; // scope 1 at $DIR/inline_closure.rs:+2:7: +2:8
StorageLive(_7); // scope 1 at $DIR/inline_closure.rs:+2:10: +2:11
_7 = _2; // scope 1 at $DIR/inline_closure.rs:+2:10: +2:11
- Deinit(_5); // scope 1 at $DIR/inline_closure.rs:+2:5: +2:12
- (_5.0: i32) = move _6; // scope 1 at $DIR/inline_closure.rs:+2:5: +2:12
- (_5.1: i32) = move _7; // scope 1 at $DIR/inline_closure.rs:+2:5: +2:12
+ _5 = (move _6, move _7); // scope 1 at $DIR/inline_closure.rs:+2:5: +2:12
StorageLive(_8); // scope 1 at $DIR/inline_closure.rs:+2:5: +2:12
_8 = move (_5.0: i32); // scope 1 at $DIR/inline_closure.rs:+2:5: +2:12
StorageLive(_9); // scope 1 at $DIR/inline_closure.rs:+2:5: +2:12
diff --git a/tests/mir-opt/inline/inline_closure_borrows_arg.foo.Inline.after.mir b/tests/mir-opt/inline/inline_closure_borrows_arg.foo.Inline.after.mir
index dd32eb2d8..dab204306 100644
--- a/tests/mir-opt/inline/inline_closure_borrows_arg.foo.Inline.after.mir
+++ b/tests/mir-opt/inline/inline_closure_borrows_arg.foo.Inline.after.mir
@@ -24,7 +24,15 @@ fn foo(_1: T, _2: &i32) -> i32 {
bb0: {
StorageLive(_3); // scope 0 at $DIR/inline_closure_borrows_arg.rs:+1:9: +1:10
- Deinit(_3); // scope 0 at $DIR/inline_closure_borrows_arg.rs:+1:13: +4:6
+ _3 = [closure@foo::<T>::{closure#0}]; // scope 0 at $DIR/inline_closure_borrows_arg.rs:+1:13: +4:6
+ // closure
+ // + def_id: DefId(0:6 ~ inline_closure_borrows_arg[96e9]::foo::{closure#0})
+ // + substs: [
+ // T,
+ // i8,
+ // for<'a, 'b> extern "rust-call" fn((&'a i32, &'b i32)) -> i32,
+ // (),
+ // ]
StorageLive(_4); // scope 1 at $DIR/inline_closure_borrows_arg.rs:+5:5: +5:6
_4 = &_3; // scope 1 at $DIR/inline_closure_borrows_arg.rs:+5:5: +5:6
StorageLive(_5); // scope 1 at $DIR/inline_closure_borrows_arg.rs:+5:5: +5:12
@@ -32,9 +40,7 @@ fn foo(_1: T, _2: &i32) -> i32 {
_6 = &(*_2); // scope 1 at $DIR/inline_closure_borrows_arg.rs:+5:7: +5:8
StorageLive(_7); // scope 1 at $DIR/inline_closure_borrows_arg.rs:+5:10: +5:11
_7 = &(*_2); // scope 1 at $DIR/inline_closure_borrows_arg.rs:+5:10: +5:11
- Deinit(_5); // scope 1 at $DIR/inline_closure_borrows_arg.rs:+5:5: +5:12
- (_5.0: &i32) = move _6; // scope 1 at $DIR/inline_closure_borrows_arg.rs:+5:5: +5:12
- (_5.1: &i32) = move _7; // scope 1 at $DIR/inline_closure_borrows_arg.rs:+5:5: +5:12
+ _5 = (move _6, move _7); // scope 1 at $DIR/inline_closure_borrows_arg.rs:+5:5: +5:12
StorageLive(_8); // scope 1 at $DIR/inline_closure_borrows_arg.rs:+5:5: +5:12
_8 = move (_5.0: &i32); // scope 1 at $DIR/inline_closure_borrows_arg.rs:+5:5: +5:12
StorageLive(_9); // scope 1 at $DIR/inline_closure_borrows_arg.rs:+5:5: +5:12
diff --git a/tests/mir-opt/inline/inline_closure_captures.foo.Inline.after.mir b/tests/mir-opt/inline/inline_closure_captures.foo.Inline.after.mir
index fd19c2886..84fd051e0 100644
--- a/tests/mir-opt/inline/inline_closure_captures.foo.Inline.after.mir
+++ b/tests/mir-opt/inline/inline_closure_captures.foo.Inline.after.mir
@@ -30,9 +30,15 @@ fn foo(_1: T, _2: i32) -> (i32, T) {
_4 = &_2; // scope 0 at $DIR/inline_closure_captures.rs:+1:13: +1:24
StorageLive(_5); // scope 0 at $DIR/inline_closure_captures.rs:+1:13: +1:24
_5 = &_1; // scope 0 at $DIR/inline_closure_captures.rs:+1:13: +1:24
- Deinit(_3); // scope 0 at $DIR/inline_closure_captures.rs:+1:13: +1:24
- (_3.0: &i32) = move _4; // scope 0 at $DIR/inline_closure_captures.rs:+1:13: +1:24
- (_3.1: &T) = move _5; // scope 0 at $DIR/inline_closure_captures.rs:+1:13: +1:24
+ _3 = [closure@foo::<T>::{closure#0}] { q: move _4, t: move _5 }; // scope 0 at $DIR/inline_closure_captures.rs:+1:13: +1:24
+ // closure
+ // + def_id: DefId(0:6 ~ inline_closure_captures[8bc0]::foo::{closure#0})
+ // + substs: [
+ // T,
+ // i8,
+ // extern "rust-call" fn((i32,)) -> (i32, T),
+ // (&i32, &T),
+ // ]
StorageDead(_5); // scope 0 at $DIR/inline_closure_captures.rs:+1:16: +1:17
StorageDead(_4); // scope 0 at $DIR/inline_closure_captures.rs:+1:16: +1:17
StorageLive(_6); // scope 1 at $DIR/inline_closure_captures.rs:+2:5: +2:6
@@ -40,8 +46,7 @@ fn foo(_1: T, _2: i32) -> (i32, T) {
StorageLive(_7); // scope 1 at $DIR/inline_closure_captures.rs:+2:5: +2:9
StorageLive(_8); // scope 1 at $DIR/inline_closure_captures.rs:+2:7: +2:8
_8 = _2; // scope 1 at $DIR/inline_closure_captures.rs:+2:7: +2:8
- Deinit(_7); // scope 1 at $DIR/inline_closure_captures.rs:+2:5: +2:9
- (_7.0: i32) = move _8; // scope 1 at $DIR/inline_closure_captures.rs:+2:5: +2:9
+ _7 = (move _8,); // scope 1 at $DIR/inline_closure_captures.rs:+2:5: +2:9
StorageLive(_9); // scope 1 at $DIR/inline_closure_captures.rs:+2:5: +2:9
_9 = move (_7.0: i32); // scope 1 at $DIR/inline_closure_captures.rs:+2:5: +2:9
StorageLive(_10); // scope 2 at $DIR/inline_closure_captures.rs:+1:19: +1:20
@@ -50,9 +55,7 @@ fn foo(_1: T, _2: i32) -> (i32, T) {
StorageLive(_11); // scope 2 at $DIR/inline_closure_captures.rs:+1:22: +1:23
_13 = deref_copy ((*_6).1: &T); // scope 2 at $DIR/inline_closure_captures.rs:+1:22: +1:23
_11 = (*_13); // scope 2 at $DIR/inline_closure_captures.rs:+1:22: +1:23
- Deinit(_0); // scope 2 at $DIR/inline_closure_captures.rs:+1:18: +1:24
- (_0.0: i32) = move _10; // scope 2 at $DIR/inline_closure_captures.rs:+1:18: +1:24
- (_0.1: T) = move _11; // scope 2 at $DIR/inline_closure_captures.rs:+1:18: +1:24
+ _0 = (move _10, move _11); // scope 2 at $DIR/inline_closure_captures.rs:+1:18: +1:24
StorageDead(_11); // scope 2 at $DIR/inline_closure_captures.rs:+1:23: +1:24
StorageDead(_10); // scope 2 at $DIR/inline_closure_captures.rs:+1:23: +1:24
StorageDead(_9); // scope 1 at $DIR/inline_closure_captures.rs:+2:5: +2:9
diff --git a/tests/mir-opt/inline/inline_diverging.h.Inline.diff b/tests/mir-opt/inline/inline_diverging.h.Inline.diff
index f82fcf4c8..e1b2f7dbf 100644
--- a/tests/mir-opt/inline/inline_diverging.h.Inline.diff
+++ b/tests/mir-opt/inline/inline_diverging.h.Inline.diff
@@ -48,9 +48,7 @@
+ StorageDead(_6); // scope 2 at $DIR/inline_diverging.rs:28:15: 28:16
+ StorageLive(_8); // scope 3 at $DIR/inline_diverging.rs:29:6: 29:7
+ _8 = move _3; // scope 3 at $DIR/inline_diverging.rs:29:6: 29:7
-+ Deinit(_1); // scope 3 at $DIR/inline_diverging.rs:29:5: 29:11
-+ (_1.0: !) = move _8; // scope 3 at $DIR/inline_diverging.rs:29:5: 29:11
-+ (_1.1: !) = move _9; // scope 3 at $DIR/inline_diverging.rs:29:5: 29:11
++ _1 = (move _8, move _9); // scope 3 at $DIR/inline_diverging.rs:29:5: 29:11
+ StorageDead(_8); // scope 3 at $DIR/inline_diverging.rs:29:10: 29:11
+ StorageDead(_3); // scope 1 at $DIR/inline_diverging.rs:30:1: 30:2
+ drop(_2) -> bb2; // scope 1 at $DIR/inline_diverging.rs:30:1: 30:2
diff --git a/tests/mir-opt/inline/inline_generator.main.Inline.diff b/tests/mir-opt/inline/inline_generator.main.Inline.diff
index f27b64c30..01f5052b6 100644
--- a/tests/mir-opt/inline/inline_generator.main.Inline.diff
+++ b/tests/mir-opt/inline/inline_generator.main.Inline.diff
@@ -7,7 +7,7 @@
let mut _2: std::pin::Pin<&mut [generator@$DIR/inline_generator.rs:15:5: 15:8]>; // in scope 0 at $DIR/inline_generator.rs:+1:14: +1:32
let mut _3: &mut [generator@$DIR/inline_generator.rs:15:5: 15:8]; // in scope 0 at $DIR/inline_generator.rs:+1:23: +1:31
let mut _4: [generator@$DIR/inline_generator.rs:15:5: 15:8]; // in scope 0 at $DIR/inline_generator.rs:+1:28: +1:31
-+ let mut _7: bool; // in scope 0 at $DIR/inline_generator.rs:+1:33: +1:46
++ let mut _5: bool; // in scope 0 at $DIR/inline_generator.rs:+1:33: +1:46
scope 1 {
debug _r => _1; // in scope 1 at $DIR/inline_generator.rs:+1:9: +1:11
}
@@ -15,21 +15,19 @@
+ }
+ scope 3 (inlined Pin::<&mut [generator@$DIR/inline_generator.rs:15:5: 15:8]>::new) { // at $DIR/inline_generator.rs:9:14: 9:32
+ debug pointer => _3; // in scope 3 at $SRC_DIR/core/src/pin.rs:LL:COL
-+ let mut _5: &mut [generator@$DIR/inline_generator.rs:15:5: 15:8]; // in scope 3 at $SRC_DIR/core/src/pin.rs:LL:COL
+ scope 4 {
+ scope 5 (inlined Pin::<&mut [generator@$DIR/inline_generator.rs:15:5: 15:8]>::new_unchecked) { // at $SRC_DIR/core/src/pin.rs:LL:COL
-+ debug pointer => _5; // in scope 5 at $SRC_DIR/core/src/pin.rs:LL:COL
-+ let mut _6: &mut [generator@$DIR/inline_generator.rs:15:5: 15:8]; // in scope 5 at $SRC_DIR/core/src/pin.rs:LL:COL
++ debug pointer => _3; // in scope 5 at $SRC_DIR/core/src/pin.rs:LL:COL
+ }
+ }
+ }
+ scope 6 (inlined g::{closure#0}) { // at $DIR/inline_generator.rs:9:33: 9:46
-+ debug a => _7; // in scope 6 at $DIR/inline_generator.rs:15:6: 15:7
-+ let mut _8: i32; // in scope 6 at $DIR/inline_generator.rs:15:17: 15:39
-+ let mut _9: u32; // in scope 6 at $DIR/inline_generator.rs:15:5: 15:41
++ debug a => _5; // in scope 6 at $DIR/inline_generator.rs:15:6: 15:7
++ let mut _6: i32; // in scope 6 at $DIR/inline_generator.rs:15:17: 15:39
++ let mut _7: u32; // in scope 6 at $DIR/inline_generator.rs:15:5: 15:41
++ let mut _8: &mut [generator@$DIR/inline_generator.rs:15:5: 15:8]; // in scope 6 at $DIR/inline_generator.rs:15:5: 15:41
++ let mut _9: &mut [generator@$DIR/inline_generator.rs:15:5: 15:8]; // in scope 6 at $DIR/inline_generator.rs:15:5: 15:41
+ let mut _10: &mut [generator@$DIR/inline_generator.rs:15:5: 15:8]; // in scope 6 at $DIR/inline_generator.rs:15:5: 15:41
-+ let mut _11: &mut [generator@$DIR/inline_generator.rs:15:5: 15:8]; // in scope 6 at $DIR/inline_generator.rs:15:5: 15:41
-+ let mut _12: &mut [generator@$DIR/inline_generator.rs:15:5: 15:8]; // in scope 6 at $DIR/inline_generator.rs:15:5: 15:41
+ }
bb0: {
@@ -44,8 +42,17 @@
- }
-
- bb1: {
-+ Deinit(_4); // scope 2 at $DIR/inline_generator.rs:15:5: 15:41
-+ discriminant(_4) = 0; // scope 2 at $DIR/inline_generator.rs:15:5: 15:41
++ _4 = [generator@$DIR/inline_generator.rs:15:5: 15:8 (#0)]; // scope 2 at $DIR/inline_generator.rs:15:5: 15:41
++ // generator
++ // + def_id: DefId(0:7 ~ inline_generator[ea31]::g::{closure#0})
++ // + substs: [
++ // bool,
++ // i32,
++ // bool,
++ // {bool, i32},
++ // (),
++ // ]
++ // + movability: Movable
_3 = &mut _4; // scope 0 at $DIR/inline_generator.rs:+1:23: +1:31
- _2 = Pin::<&mut [generator@$DIR/inline_generator.rs:15:5: 15:8]>::new(move _3) -> [return: bb2, unwind: bb4]; // scope 0 at $DIR/inline_generator.rs:+1:14: +1:32
- // mir::Constant
@@ -55,29 +62,22 @@
- }
-
- bb2: {
-+ StorageLive(_5); // scope 4 at $SRC_DIR/core/src/pin.rs:LL:COL
-+ _5 = move _3; // scope 4 at $SRC_DIR/core/src/pin.rs:LL:COL
-+ StorageLive(_6); // scope 5 at $SRC_DIR/core/src/pin.rs:LL:COL
-+ _6 = move _5; // scope 5 at $SRC_DIR/core/src/pin.rs:LL:COL
-+ Deinit(_2); // scope 5 at $SRC_DIR/core/src/pin.rs:LL:COL
-+ (_2.0: &mut [generator@$DIR/inline_generator.rs:15:5: 15:8]) = move _6; // scope 5 at $SRC_DIR/core/src/pin.rs:LL:COL
-+ StorageDead(_6); // scope 5 at $SRC_DIR/core/src/pin.rs:LL:COL
-+ StorageDead(_5); // scope 4 at $SRC_DIR/core/src/pin.rs:LL:COL
++ _2 = Pin::<&mut [generator@$DIR/inline_generator.rs:15:5: 15:8]> { pointer: move _3 }; // scope 5 at $SRC_DIR/core/src/pin.rs:LL:COL
StorageDead(_3); // scope 0 at $DIR/inline_generator.rs:+1:31: +1:32
- _1 = <[generator@$DIR/inline_generator.rs:15:5: 15:8] as Generator<bool>>::resume(move _2, const false) -> [return: bb3, unwind: bb4]; // scope 0 at $DIR/inline_generator.rs:+1:14: +1:46
- // mir::Constant
- // + span: $DIR/inline_generator.rs:9:33: 9:39
- // + literal: Const { ty: for<'a> fn(Pin<&'a mut [generator@$DIR/inline_generator.rs:15:5: 15:8]>, bool) -> GeneratorState<<[generator@$DIR/inline_generator.rs:15:5: 15:8] as Generator<bool>>::Yield, <[generator@$DIR/inline_generator.rs:15:5: 15:8] as Generator<bool>>::Return> {<[generator@$DIR/inline_generator.rs:15:5: 15:8] as Generator<bool>>::resume}, val: Value(<ZST>) }
-+ StorageLive(_7); // scope 0 at $DIR/inline_generator.rs:+1:33: +1:46
-+ _7 = const false; // scope 0 at $DIR/inline_generator.rs:+1:33: +1:46
-+ _10 = deref_copy (_2.0: &mut [generator@$DIR/inline_generator.rs:15:5: 15:8]); // scope 6 at $DIR/inline_generator.rs:15:5: 15:41
-+ _9 = discriminant((*_10)); // scope 6 at $DIR/inline_generator.rs:15:5: 15:41
-+ switchInt(move _9) -> [0: bb3, 1: bb8, 3: bb7, otherwise: bb9]; // scope 6 at $DIR/inline_generator.rs:15:5: 15:41
++ StorageLive(_5); // scope 0 at $DIR/inline_generator.rs:+1:33: +1:46
++ _5 = const false; // scope 0 at $DIR/inline_generator.rs:+1:33: +1:46
++ _8 = deref_copy (_2.0: &mut [generator@$DIR/inline_generator.rs:15:5: 15:8]); // scope 6 at $DIR/inline_generator.rs:15:5: 15:41
++ _7 = discriminant((*_8)); // scope 6 at $DIR/inline_generator.rs:15:5: 15:41
++ switchInt(move _7) -> [0: bb3, 1: bb8, 3: bb7, otherwise: bb9]; // scope 6 at $DIR/inline_generator.rs:15:5: 15:41
}
- bb3: {
+ bb1: {
-+ StorageDead(_7); // scope 0 at $DIR/inline_generator.rs:+1:33: +1:46
++ StorageDead(_5); // scope 0 at $DIR/inline_generator.rs:+1:33: +1:46
StorageDead(_2); // scope 0 at $DIR/inline_generator.rs:+1:45: +1:46
StorageDead(_4); // scope 0 at $DIR/inline_generator.rs:+1:46: +1:47
_0 = const (); // scope 0 at $DIR/inline_generator.rs:+0:11: +2:2
@@ -91,37 +91,33 @@
+ }
+
+ bb3: {
-+ StorageLive(_8); // scope 6 at $DIR/inline_generator.rs:15:17: 15:39
-+ switchInt(move _7) -> [0: bb5, otherwise: bb4]; // scope 6 at $DIR/inline_generator.rs:15:20: 15:21
++ StorageLive(_6); // scope 6 at $DIR/inline_generator.rs:15:17: 15:39
++ switchInt(_5) -> [0: bb5, otherwise: bb4]; // scope 6 at $DIR/inline_generator.rs:15:20: 15:21
+ }
+
+ bb4: {
-+ _8 = const 7_i32; // scope 6 at $DIR/inline_generator.rs:15:24: 15:25
++ _6 = const 7_i32; // scope 6 at $DIR/inline_generator.rs:15:24: 15:25
+ goto -> bb6; // scope 6 at $DIR/inline_generator.rs:15:17: 15:39
+ }
+
+ bb5: {
-+ _8 = const 13_i32; // scope 6 at $DIR/inline_generator.rs:15:35: 15:37
++ _6 = const 13_i32; // scope 6 at $DIR/inline_generator.rs:15:35: 15:37
+ goto -> bb6; // scope 6 at $DIR/inline_generator.rs:15:17: 15:39
+ }
+
+ bb6: {
-+ Deinit(_1); // scope 6 at $DIR/inline_generator.rs:15:11: 15:39
-+ ((_1 as Yielded).0: i32) = move _8; // scope 6 at $DIR/inline_generator.rs:15:11: 15:39
-+ discriminant(_1) = 0; // scope 6 at $DIR/inline_generator.rs:15:11: 15:39
-+ _11 = deref_copy (_2.0: &mut [generator@$DIR/inline_generator.rs:15:5: 15:8]); // scope 6 at $DIR/inline_generator.rs:15:11: 15:39
-+ discriminant((*_11)) = 3; // scope 6 at $DIR/inline_generator.rs:15:11: 15:39
++ _1 = GeneratorState::<i32, bool>::Yielded(move _6); // scope 6 at $DIR/inline_generator.rs:15:11: 15:39
++ _9 = deref_copy (_2.0: &mut [generator@$DIR/inline_generator.rs:15:5: 15:8]); // scope 6 at $DIR/inline_generator.rs:15:11: 15:39
++ discriminant((*_9)) = 3; // scope 6 at $DIR/inline_generator.rs:15:11: 15:39
+ goto -> bb1; // scope 0 at $DIR/inline_generator.rs:15:11: 15:39
+ }
+
+ bb7: {
-+ StorageLive(_8); // scope 6 at $DIR/inline_generator.rs:15:5: 15:41
-+ StorageDead(_8); // scope 6 at $DIR/inline_generator.rs:15:38: 15:39
-+ Deinit(_1); // scope 6 at $DIR/inline_generator.rs:15:41: 15:41
-+ ((_1 as Complete).0: bool) = move _7; // scope 6 at $DIR/inline_generator.rs:15:41: 15:41
-+ discriminant(_1) = 1; // scope 6 at $DIR/inline_generator.rs:15:41: 15:41
-+ _12 = deref_copy (_2.0: &mut [generator@$DIR/inline_generator.rs:15:5: 15:8]); // scope 6 at $DIR/inline_generator.rs:15:41: 15:41
-+ discriminant((*_12)) = 1; // scope 6 at $DIR/inline_generator.rs:15:41: 15:41
++ StorageLive(_6); // scope 6 at $DIR/inline_generator.rs:15:5: 15:41
++ StorageDead(_6); // scope 6 at $DIR/inline_generator.rs:15:38: 15:39
++ _1 = GeneratorState::<i32, bool>::Complete(_5); // scope 6 at $DIR/inline_generator.rs:15:41: 15:41
++ _10 = deref_copy (_2.0: &mut [generator@$DIR/inline_generator.rs:15:5: 15:8]); // scope 6 at $DIR/inline_generator.rs:15:41: 15:41
++ discriminant((*_10)) = 1; // scope 6 at $DIR/inline_generator.rs:15:41: 15:41
+ goto -> bb1; // scope 0 at $DIR/inline_generator.rs:15:41: 15:41
+ }
+
diff --git a/tests/mir-opt/inline/inline_into_box_place.main.Inline.diff b/tests/mir-opt/inline/inline_into_box_place.main.Inline.diff
index a28da146e..a1cbf0d3e 100644
--- a/tests/mir-opt/inline/inline_into_box_place.main.Inline.diff
+++ b/tests/mir-opt/inline/inline_into_box_place.main.Inline.diff
@@ -51,9 +51,7 @@
+ // + span: $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
+ // + user_ty: UserType(0)
+ // + literal: Const { ty: alloc::raw_vec::RawVec<u32>, val: Unevaluated(alloc::raw_vec::RawVec::<T>::NEW, [u32], None) }
-+ Deinit(_9); // scope 3 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
-+ (_9.0: alloc::raw_vec::RawVec<u32>) = move _10; // scope 3 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
-+ (_9.1: usize) = const 0_usize; // scope 3 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
++ _9 = Vec::<u32> { buf: move _10, len: const 0_usize }; // scope 3 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
+ StorageDead(_10); // scope 3 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
+ (*_8) = move _9; // scope 0 at $DIR/inline_into_box_place.rs:+1:33: +1:43
+ StorageDead(_9); // scope 0 at $DIR/inline_into_box_place.rs:+1:33: +1:43
diff --git a/tests/mir-opt/inline/inline_trait_method_2.test2.Inline.after.mir b/tests/mir-opt/inline/inline_trait_method_2.test2.Inline.after.mir
index 73aea719e..b7c5bbecb 100644
--- a/tests/mir-opt/inline/inline_trait_method_2.test2.Inline.after.mir
+++ b/tests/mir-opt/inline/inline_trait_method_2.test2.Inline.after.mir
@@ -15,7 +15,7 @@ fn test2(_1: &dyn X) -> bool {
_3 = &(*_1); // scope 0 at $DIR/inline_trait_method_2.rs:+1:10: +1:11
_2 = move _3 as &dyn X (Pointer(Unsize)); // scope 0 at $DIR/inline_trait_method_2.rs:+1:10: +1:11
StorageDead(_3); // scope 0 at $DIR/inline_trait_method_2.rs:+1:10: +1:11
- _0 = <dyn X as X>::y(move _2) -> bb1; // scope 1 at $DIR/inline_trait_method_2.rs:10:5: 10:10
+ _0 = <dyn X as X>::y(_2) -> bb1; // scope 1 at $DIR/inline_trait_method_2.rs:10:5: 10:10
// mir::Constant
// + span: $DIR/inline_trait_method_2.rs:10:7: 10:8
// + literal: Const { ty: for<'a> fn(&'a dyn X) -> bool {<dyn X as X>::y}, val: Value(<ZST>) }
diff --git a/tests/mir-opt/inline/issue_58867_inline_as_ref_as_mut.a.Inline.after.mir b/tests/mir-opt/inline/issue_58867_inline_as_ref_as_mut.a.Inline.after.mir
index dc0c32350..6441a9668 100644
--- a/tests/mir-opt/inline/issue_58867_inline_as_ref_as_mut.a.Inline.after.mir
+++ b/tests/mir-opt/inline/issue_58867_inline_as_ref_as_mut.a.Inline.after.mir
@@ -8,7 +8,6 @@ fn a(_1: &mut [T]) -> &mut [T] {
let mut _4: &mut [T]; // in scope 0 at $DIR/issue_58867_inline_as_ref_as_mut.rs:+1:5: +1:15
scope 1 (inlined <[T] as AsMut<[T]>>::as_mut) { // at $DIR/issue_58867_inline_as_ref_as_mut.rs:3:7: 3:15
debug self => _4; // in scope 1 at $SRC_DIR/core/src/convert/mod.rs:LL:COL
- let mut _5: &mut [T]; // in scope 1 at $SRC_DIR/core/src/convert/mod.rs:LL:COL
}
bb0: {
@@ -16,10 +15,7 @@ fn a(_1: &mut [T]) -> &mut [T] {
StorageLive(_3); // scope 0 at $DIR/issue_58867_inline_as_ref_as_mut.rs:+1:5: +1:15
StorageLive(_4); // scope 0 at $DIR/issue_58867_inline_as_ref_as_mut.rs:+1:5: +1:15
_4 = &mut (*_1); // scope 0 at $DIR/issue_58867_inline_as_ref_as_mut.rs:+1:5: +1:15
- StorageLive(_5); // scope 1 at $SRC_DIR/core/src/convert/mod.rs:LL:COL
- _5 = &mut (*_4); // scope 1 at $SRC_DIR/core/src/convert/mod.rs:LL:COL
- _3 = &mut (*_5); // scope 1 at $SRC_DIR/core/src/convert/mod.rs:LL:COL
- StorageDead(_5); // scope 1 at $SRC_DIR/core/src/convert/mod.rs:LL:COL
+ _3 = _4; // scope 1 at $SRC_DIR/core/src/convert/mod.rs:LL:COL
_2 = &mut (*_3); // scope 0 at $DIR/issue_58867_inline_as_ref_as_mut.rs:+1:5: +1:15
StorageDead(_4); // scope 0 at $DIR/issue_58867_inline_as_ref_as_mut.rs:+1:14: +1:15
_0 = &mut (*_2); // scope 0 at $DIR/issue_58867_inline_as_ref_as_mut.rs:+1:5: +1:15
diff --git a/tests/mir-opt/inline/issue_58867_inline_as_ref_as_mut.b.Inline.after.mir b/tests/mir-opt/inline/issue_58867_inline_as_ref_as_mut.b.Inline.after.mir
index b6aff3014..21570a88a 100644
--- a/tests/mir-opt/inline/issue_58867_inline_as_ref_as_mut.b.Inline.after.mir
+++ b/tests/mir-opt/inline/issue_58867_inline_as_ref_as_mut.b.Inline.after.mir
@@ -8,10 +8,8 @@ fn b(_1: &mut Box<T>) -> &mut T {
let mut _4: &mut std::boxed::Box<T>; // in scope 0 at $DIR/issue_58867_inline_as_ref_as_mut.rs:+1:5: +1:15
scope 1 (inlined <Box<T> as AsMut<T>>::as_mut) { // at $DIR/issue_58867_inline_as_ref_as_mut.rs:8:7: 8:15
debug self => _4; // in scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL
- let mut _5: &mut T; // in scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL
- let mut _6: &mut T; // in scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL
- let mut _7: std::boxed::Box<T>; // in scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL
- let mut _8: *const T; // in scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL
+ let mut _5: std::boxed::Box<T>; // in scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL
+ let mut _6: *const T; // in scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL
}
bb0: {
@@ -19,15 +17,9 @@ fn b(_1: &mut Box<T>) -> &mut T {
StorageLive(_3); // scope 0 at $DIR/issue_58867_inline_as_ref_as_mut.rs:+1:5: +1:15
StorageLive(_4); // scope 0 at $DIR/issue_58867_inline_as_ref_as_mut.rs:+1:5: +1:15
_4 = &mut (*_1); // scope 0 at $DIR/issue_58867_inline_as_ref_as_mut.rs:+1:5: +1:15
- StorageLive(_5); // scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL
- StorageLive(_6); // scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL
- _7 = deref_copy (*_4); // scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL
- _8 = (((_7.0: std::ptr::Unique<T>).0: std::ptr::NonNull<T>).0: *const T); // scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL
- _6 = &mut (*_8); // scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL
- _5 = &mut (*_6); // scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL
- _3 = &mut (*_5); // scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL
- StorageDead(_6); // scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL
- StorageDead(_5); // scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL
+ _5 = deref_copy (*_4); // scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL
+ _6 = (((_5.0: std::ptr::Unique<T>).0: std::ptr::NonNull<T>).0: *const T); // scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL
+ _3 = &mut (*_6); // scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL
_2 = &mut (*_3); // scope 0 at $DIR/issue_58867_inline_as_ref_as_mut.rs:+1:5: +1:15
StorageDead(_4); // scope 0 at $DIR/issue_58867_inline_as_ref_as_mut.rs:+1:14: +1:15
_0 = &mut (*_2); // scope 0 at $DIR/issue_58867_inline_as_ref_as_mut.rs:+1:5: +1:15
diff --git a/tests/mir-opt/inline/issue_76997_inline_scopes_parenting.main.Inline.after.mir b/tests/mir-opt/inline/issue_76997_inline_scopes_parenting.main.Inline.after.mir
index d99ae1a6c..4dd1aad48 100644
--- a/tests/mir-opt/inline/issue_76997_inline_scopes_parenting.main.Inline.after.mir
+++ b/tests/mir-opt/inline/issue_76997_inline_scopes_parenting.main.Inline.after.mir
@@ -20,14 +20,20 @@ fn main() -> () {
bb0: {
StorageLive(_1); // scope 0 at $DIR/issue_76997_inline_scopes_parenting.rs:+1:9: +1:10
- Deinit(_1); // scope 0 at $DIR/issue_76997_inline_scopes_parenting.rs:+1:13: +1:33
+ _1 = [closure@$DIR/issue_76997_inline_scopes_parenting.rs:5:13: 5:16]; // scope 0 at $DIR/issue_76997_inline_scopes_parenting.rs:+1:13: +1:33
+ // closure
+ // + def_id: DefId(0:4 ~ issue_76997_inline_scopes_parenting[bc59]::main::{closure#0})
+ // + substs: [
+ // i8,
+ // extern "rust-call" fn(((),)),
+ // (),
+ // ]
StorageLive(_2); // scope 1 at $DIR/issue_76997_inline_scopes_parenting.rs:+2:5: +2:6
_2 = &_1; // scope 1 at $DIR/issue_76997_inline_scopes_parenting.rs:+2:5: +2:6
StorageLive(_3); // scope 1 at $DIR/issue_76997_inline_scopes_parenting.rs:+2:5: +2:10
StorageLive(_4); // scope 1 at $DIR/issue_76997_inline_scopes_parenting.rs:+2:7: +2:9
- Deinit(_4); // scope 1 at $DIR/issue_76997_inline_scopes_parenting.rs:+2:7: +2:9
- Deinit(_3); // scope 1 at $DIR/issue_76997_inline_scopes_parenting.rs:+2:5: +2:10
- (_3.0: ()) = move _4; // scope 1 at $DIR/issue_76997_inline_scopes_parenting.rs:+2:5: +2:10
+ _4 = (); // scope 1 at $DIR/issue_76997_inline_scopes_parenting.rs:+2:7: +2:9
+ _3 = (move _4,); // scope 1 at $DIR/issue_76997_inline_scopes_parenting.rs:+2:5: +2:10
StorageLive(_5); // scope 1 at $DIR/issue_76997_inline_scopes_parenting.rs:+2:5: +2:10
_5 = move (_3.0: ()); // scope 1 at $DIR/issue_76997_inline_scopes_parenting.rs:+2:5: +2:10
StorageLive(_6); // scope 2 at $DIR/issue_76997_inline_scopes_parenting.rs:+1:23: +1:24
diff --git a/tests/mir-opt/inline/issue_78442.bar.Inline.diff b/tests/mir-opt/inline/issue_78442.bar.Inline.diff
index 51a98465f..aa62e4a16 100644
--- a/tests/mir-opt/inline/issue_78442.bar.Inline.diff
+++ b/tests/mir-opt/inline/issue_78442.bar.Inline.diff
@@ -25,7 +25,7 @@
bb1: {
_3 = &_4; // scope 0 at $DIR/issue_78442.rs:+4:5: +4:15
StorageLive(_5); // scope 0 at $DIR/issue_78442.rs:+4:5: +4:17
- Deinit(_5); // scope 0 at $DIR/issue_78442.rs:+4:5: +4:17
+ _5 = (); // scope 0 at $DIR/issue_78442.rs:+4:5: +4:17
- _2 = <fn() {foo} as Fn<()>>::call(move _3, move _5) -> [return: bb2, unwind: bb4]; // scope 0 at $DIR/issue_78442.rs:+4:5: +4:17
- // mir::Constant
- // + span: $DIR/issue_78442.rs:11:5: 11:15
diff --git a/tests/mir-opt/inline/issue_78442.bar.RevealAll.diff b/tests/mir-opt/inline/issue_78442.bar.RevealAll.diff
index e47466c5e..21055c6bf 100644
--- a/tests/mir-opt/inline/issue_78442.bar.RevealAll.diff
+++ b/tests/mir-opt/inline/issue_78442.bar.RevealAll.diff
@@ -24,7 +24,7 @@
bb1: {
_3 = &_4; // scope 0 at $DIR/issue_78442.rs:+4:5: +4:15
StorageLive(_5); // scope 0 at $DIR/issue_78442.rs:+4:5: +4:17
- Deinit(_5); // scope 0 at $DIR/issue_78442.rs:+4:5: +4:17
+ _5 = (); // scope 0 at $DIR/issue_78442.rs:+4:5: +4:17
- _2 = <impl Fn() as Fn<()>>::call(move _3, move _5) -> [return: bb2, unwind: bb4]; // scope 0 at $DIR/issue_78442.rs:+4:5: +4:17
+ _2 = <fn() {foo} as Fn<()>>::call(move _3, move _5) -> [return: bb2, unwind: bb4]; // scope 0 at $DIR/issue_78442.rs:+4:5: +4:17
// mir::Constant
diff --git a/tests/mir-opt/intrinsic_asserts.generic.InstCombine.diff b/tests/mir-opt/intrinsic_asserts.generic.InstCombine.diff
new file mode 100644
index 000000000..8ff64c1ea
--- /dev/null
+++ b/tests/mir-opt/intrinsic_asserts.generic.InstCombine.diff
@@ -0,0 +1,42 @@
+- // MIR for `generic` before InstCombine
++ // MIR for `generic` after InstCombine
+
+ fn generic() -> () {
+ let mut _0: (); // return place in scope 0 at $DIR/intrinsic_asserts.rs:+0:21: +0:21
+ let _1: (); // in scope 0 at $DIR/intrinsic_asserts.rs:+1:5: +1:46
+ let _2: (); // in scope 0 at $DIR/intrinsic_asserts.rs:+2:5: +2:47
+ let _3: (); // in scope 0 at $DIR/intrinsic_asserts.rs:+3:5: +3:60
+
+ bb0: {
+ StorageLive(_1); // scope 0 at $DIR/intrinsic_asserts.rs:+1:5: +1:46
+ _1 = assert_inhabited::<T>() -> bb1; // scope 0 at $DIR/intrinsic_asserts.rs:+1:5: +1:46
+ // mir::Constant
+ // + span: $DIR/intrinsic_asserts.rs:25:5: 25:44
+ // + literal: Const { ty: extern "rust-intrinsic" fn() {assert_inhabited::<T>}, val: Value(<ZST>) }
+ }
+
+ bb1: {
+ StorageDead(_1); // scope 0 at $DIR/intrinsic_asserts.rs:+1:46: +1:47
+ StorageLive(_2); // scope 0 at $DIR/intrinsic_asserts.rs:+2:5: +2:47
+ _2 = assert_zero_valid::<T>() -> bb2; // scope 0 at $DIR/intrinsic_asserts.rs:+2:5: +2:47
+ // mir::Constant
+ // + span: $DIR/intrinsic_asserts.rs:26:5: 26:45
+ // + literal: Const { ty: extern "rust-intrinsic" fn() {assert_zero_valid::<T>}, val: Value(<ZST>) }
+ }
+
+ bb2: {
+ StorageDead(_2); // scope 0 at $DIR/intrinsic_asserts.rs:+2:47: +2:48
+ StorageLive(_3); // scope 0 at $DIR/intrinsic_asserts.rs:+3:5: +3:60
+ _3 = assert_mem_uninitialized_valid::<T>() -> bb3; // scope 0 at $DIR/intrinsic_asserts.rs:+3:5: +3:60
+ // mir::Constant
+ // + span: $DIR/intrinsic_asserts.rs:27:5: 27:58
+ // + literal: Const { ty: extern "rust-intrinsic" fn() {assert_mem_uninitialized_valid::<T>}, val: Value(<ZST>) }
+ }
+
+ bb3: {
+ StorageDead(_3); // scope 0 at $DIR/intrinsic_asserts.rs:+3:60: +3:61
+ nop; // scope 0 at $DIR/intrinsic_asserts.rs:+0:21: +4:2
+ return; // scope 0 at $DIR/intrinsic_asserts.rs:+4:2: +4:2
+ }
+ }
+
diff --git a/tests/mir-opt/intrinsic_asserts.panics.InstCombine.diff b/tests/mir-opt/intrinsic_asserts.panics.InstCombine.diff
new file mode 100644
index 000000000..ddc015903
--- /dev/null
+++ b/tests/mir-opt/intrinsic_asserts.panics.InstCombine.diff
@@ -0,0 +1,47 @@
+- // MIR for `panics` before InstCombine
++ // MIR for `panics` after InstCombine
+
+ fn panics() -> () {
+ let mut _0: (); // return place in scope 0 at $DIR/intrinsic_asserts.rs:+0:17: +0:17
+ let _1: (); // in scope 0 at $DIR/intrinsic_asserts.rs:+1:5: +1:50
+ let _2: (); // in scope 0 at $DIR/intrinsic_asserts.rs:+2:5: +2:49
+ let _3: (); // in scope 0 at $DIR/intrinsic_asserts.rs:+3:5: +3:62
+
+ bb0: {
+ StorageLive(_1); // scope 0 at $DIR/intrinsic_asserts.rs:+1:5: +1:50
+- _1 = assert_inhabited::<Never>() -> bb1; // scope 0 at $DIR/intrinsic_asserts.rs:+1:5: +1:50
++ _1 = assert_inhabited::<Never>(); // scope 0 at $DIR/intrinsic_asserts.rs:+1:5: +1:50
+ // mir::Constant
+ // + span: $DIR/intrinsic_asserts.rs:17:5: 17:48
+ // + literal: Const { ty: extern "rust-intrinsic" fn() {assert_inhabited::<Never>}, val: Value(<ZST>) }
+ }
+
+ bb1: {
+ StorageDead(_1); // scope 0 at $DIR/intrinsic_asserts.rs:+1:50: +1:51
+ StorageLive(_2); // scope 0 at $DIR/intrinsic_asserts.rs:+2:5: +2:49
+- _2 = assert_zero_valid::<&u8>() -> bb2; // scope 0 at $DIR/intrinsic_asserts.rs:+2:5: +2:49
++ _2 = assert_zero_valid::<&u8>(); // scope 0 at $DIR/intrinsic_asserts.rs:+2:5: +2:49
+ // mir::Constant
+ // + span: $DIR/intrinsic_asserts.rs:18:5: 18:47
+ // + user_ty: UserType(0)
+ // + literal: Const { ty: extern "rust-intrinsic" fn() {assert_zero_valid::<&u8>}, val: Value(<ZST>) }
+ }
+
+ bb2: {
+ StorageDead(_2); // scope 0 at $DIR/intrinsic_asserts.rs:+2:49: +2:50
+ StorageLive(_3); // scope 0 at $DIR/intrinsic_asserts.rs:+3:5: +3:62
+- _3 = assert_mem_uninitialized_valid::<&u8>() -> bb3; // scope 0 at $DIR/intrinsic_asserts.rs:+3:5: +3:62
++ _3 = assert_mem_uninitialized_valid::<&u8>(); // scope 0 at $DIR/intrinsic_asserts.rs:+3:5: +3:62
+ // mir::Constant
+ // + span: $DIR/intrinsic_asserts.rs:19:5: 19:60
+ // + user_ty: UserType(1)
+ // + literal: Const { ty: extern "rust-intrinsic" fn() {assert_mem_uninitialized_valid::<&u8>}, val: Value(<ZST>) }
+ }
+
+ bb3: {
+ StorageDead(_3); // scope 0 at $DIR/intrinsic_asserts.rs:+3:62: +3:63
+ nop; // scope 0 at $DIR/intrinsic_asserts.rs:+0:17: +4:2
+ return; // scope 0 at $DIR/intrinsic_asserts.rs:+4:2: +4:2
+ }
+ }
+
diff --git a/tests/mir-opt/intrinsic_asserts.removable.InstCombine.diff b/tests/mir-opt/intrinsic_asserts.removable.InstCombine.diff
new file mode 100644
index 000000000..568fbf1a0
--- /dev/null
+++ b/tests/mir-opt/intrinsic_asserts.removable.InstCombine.diff
@@ -0,0 +1,45 @@
+- // MIR for `removable` before InstCombine
++ // MIR for `removable` after InstCombine
+
+ fn removable() -> () {
+ let mut _0: (); // return place in scope 0 at $DIR/intrinsic_asserts.rs:+0:20: +0:20
+ let _1: (); // in scope 0 at $DIR/intrinsic_asserts.rs:+1:5: +1:47
+ let _2: (); // in scope 0 at $DIR/intrinsic_asserts.rs:+2:5: +2:48
+ let _3: (); // in scope 0 at $DIR/intrinsic_asserts.rs:+3:5: +3:61
+
+ bb0: {
+ StorageLive(_1); // scope 0 at $DIR/intrinsic_asserts.rs:+1:5: +1:47
+- _1 = assert_inhabited::<()>() -> bb1; // scope 0 at $DIR/intrinsic_asserts.rs:+1:5: +1:47
+- // mir::Constant
+- // + span: $DIR/intrinsic_asserts.rs:7:5: 7:45
+- // + literal: Const { ty: extern "rust-intrinsic" fn() {assert_inhabited::<()>}, val: Value(<ZST>) }
++ goto -> bb1; // scope 0 at $DIR/intrinsic_asserts.rs:+1:5: +1:47
+ }
+
+ bb1: {
+ StorageDead(_1); // scope 0 at $DIR/intrinsic_asserts.rs:+1:47: +1:48
+ StorageLive(_2); // scope 0 at $DIR/intrinsic_asserts.rs:+2:5: +2:48
+- _2 = assert_zero_valid::<u8>() -> bb2; // scope 0 at $DIR/intrinsic_asserts.rs:+2:5: +2:48
+- // mir::Constant
+- // + span: $DIR/intrinsic_asserts.rs:8:5: 8:46
+- // + literal: Const { ty: extern "rust-intrinsic" fn() {assert_zero_valid::<u8>}, val: Value(<ZST>) }
++ goto -> bb2; // scope 0 at $DIR/intrinsic_asserts.rs:+2:5: +2:48
+ }
+
+ bb2: {
+ StorageDead(_2); // scope 0 at $DIR/intrinsic_asserts.rs:+2:48: +2:49
+ StorageLive(_3); // scope 0 at $DIR/intrinsic_asserts.rs:+3:5: +3:61
+- _3 = assert_mem_uninitialized_valid::<u8>() -> bb3; // scope 0 at $DIR/intrinsic_asserts.rs:+3:5: +3:61
+- // mir::Constant
+- // + span: $DIR/intrinsic_asserts.rs:9:5: 9:59
+- // + literal: Const { ty: extern "rust-intrinsic" fn() {assert_mem_uninitialized_valid::<u8>}, val: Value(<ZST>) }
++ goto -> bb3; // scope 0 at $DIR/intrinsic_asserts.rs:+3:5: +3:61
+ }
+
+ bb3: {
+ StorageDead(_3); // scope 0 at $DIR/intrinsic_asserts.rs:+3:61: +3:62
+ nop; // scope 0 at $DIR/intrinsic_asserts.rs:+0:20: +4:2
+ return; // scope 0 at $DIR/intrinsic_asserts.rs:+4:2: +4:2
+ }
+ }
+
diff --git a/tests/mir-opt/intrinsic_asserts.rs b/tests/mir-opt/intrinsic_asserts.rs
new file mode 100644
index 000000000..8fb99cdf6
--- /dev/null
+++ b/tests/mir-opt/intrinsic_asserts.rs
@@ -0,0 +1,28 @@
+#![crate_type = "lib"]
+#![feature(core_intrinsics)]
+
+// All these assertions pass, so all the intrinsic calls should be deleted.
+// EMIT_MIR intrinsic_asserts.removable.InstCombine.diff
+pub fn removable() {
+ core::intrinsics::assert_inhabited::<()>();
+ core::intrinsics::assert_zero_valid::<u8>();
+ core::intrinsics::assert_mem_uninitialized_valid::<u8>();
+}
+
+enum Never {}
+
+// These assertions all diverge, so their target blocks should become None.
+// EMIT_MIR intrinsic_asserts.panics.InstCombine.diff
+pub fn panics() {
+ core::intrinsics::assert_inhabited::<Never>();
+ core::intrinsics::assert_zero_valid::<&u8>();
+ core::intrinsics::assert_mem_uninitialized_valid::<&u8>();
+}
+
+// Whether or not these asserts pass isn't known, so they shouldn't be modified.
+// EMIT_MIR intrinsic_asserts.generic.InstCombine.diff
+pub fn generic<T>() {
+ core::intrinsics::assert_inhabited::<T>();
+ core::intrinsics::assert_zero_valid::<T>();
+ core::intrinsics::assert_mem_uninitialized_valid::<T>();
+}
diff --git a/tests/mir-opt/issue_101973.inner.ConstProp.diff b/tests/mir-opt/issue_101973.inner.ConstProp.diff
index b2706e5a4..6db8e4d26 100644
--- a/tests/mir-opt/issue_101973.inner.ConstProp.diff
+++ b/tests/mir-opt/issue_101973.inner.ConstProp.diff
@@ -15,7 +15,7 @@
let mut _10: (u32, bool); // in scope 0 at $DIR/issue_101973.rs:+1:32: +1:45
let mut _11: (u32, bool); // in scope 0 at $DIR/issue_101973.rs:+1:31: +1:57
scope 1 (inlined imm8) { // at $DIR/issue_101973.rs:14:5: 14:17
- debug x => _5; // in scope 1 at $DIR/issue_101973.rs:5:13: 5:14
+ debug x => _1; // in scope 1 at $DIR/issue_101973.rs:5:13: 5:14
let mut _12: u32; // in scope 1 at $DIR/issue_101973.rs:7:12: 7:27
let mut _13: u32; // in scope 1 at $DIR/issue_101973.rs:7:12: 7:20
let mut _14: (u32, bool); // in scope 1 at $DIR/issue_101973.rs:7:12: 7:20
@@ -26,25 +26,20 @@
scope 3 (inlined core::num::<impl u32>::rotate_right) { // at $DIR/issue_101973.rs:14:18: 14:58
debug self => _4; // in scope 3 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
debug n => _6; // in scope 3 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
- let mut _15: u32; // in scope 3 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
- let mut _16: u32; // in scope 3 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
}
bb0: {
StorageLive(_2); // scope 0 at $DIR/issue_101973.rs:+1:5: +1:65
StorageLive(_3); // scope 0 at $DIR/issue_101973.rs:+1:5: +1:58
StorageLive(_4); // scope 0 at $DIR/issue_101973.rs:+1:5: +1:17
- StorageLive(_5); // scope 0 at $DIR/issue_101973.rs:+1:10: +1:16
- _5 = _1; // scope 0 at $DIR/issue_101973.rs:+1:10: +1:16
StorageLive(_12); // scope 2 at $DIR/issue_101973.rs:7:12: 7:27
StorageLive(_13); // scope 2 at $DIR/issue_101973.rs:7:12: 7:20
- _14 = CheckedShr(_5, const 0_i32); // scope 2 at $DIR/issue_101973.rs:7:12: 7:20
+ _14 = CheckedShr(_1, const 0_i32); // scope 2 at $DIR/issue_101973.rs:7:12: 7:20
assert(!move (_14.1: bool), "attempt to shift right by `{}`, which would overflow", const 0_i32) -> bb3; // scope 2 at $DIR/issue_101973.rs:7:12: 7:20
}
bb1: {
_8 = move (_10.0: u32); // scope 0 at $DIR/issue_101973.rs:+1:32: +1:45
- StorageDead(_9); // scope 0 at $DIR/issue_101973.rs:+1:44: +1:45
_7 = BitAnd(move _8, const 15_u32); // scope 0 at $DIR/issue_101973.rs:+1:31: +1:52
StorageDead(_8); // scope 0 at $DIR/issue_101973.rs:+1:51: +1:52
_11 = CheckedShl(_7, const 1_i32); // scope 0 at $DIR/issue_101973.rs:+1:31: +1:57
@@ -54,11 +49,7 @@
bb2: {
_6 = move (_11.0: u32); // scope 0 at $DIR/issue_101973.rs:+1:31: +1:57
StorageDead(_7); // scope 0 at $DIR/issue_101973.rs:+1:56: +1:57
- StorageLive(_15); // scope 3 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
- _15 = _4; // scope 3 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
- StorageLive(_16); // scope 3 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
- _16 = _6; // scope 3 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
- _3 = rotate_right::<u32>(move _15, move _16) -> bb4; // scope 3 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
+ _3 = rotate_right::<u32>(_4, _6) -> bb4; // scope 3 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
// mir::Constant
// + span: $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
// + literal: Const { ty: extern "rust-intrinsic" fn(u32, u32) -> u32 {rotate_right::<u32>}, val: Value(<ZST>) }
@@ -70,19 +61,14 @@
StorageDead(_13); // scope 2 at $DIR/issue_101973.rs:7:26: 7:27
_4 = BitOr(const 0_u32, move _12); // scope 2 at $DIR/issue_101973.rs:7:5: 7:27
StorageDead(_12); // scope 2 at $DIR/issue_101973.rs:7:26: 7:27
- StorageDead(_5); // scope 0 at $DIR/issue_101973.rs:+1:16: +1:17
StorageLive(_6); // scope 0 at $DIR/issue_101973.rs:+1:31: +1:57
StorageLive(_7); // scope 0 at $DIR/issue_101973.rs:+1:31: +1:52
StorageLive(_8); // scope 0 at $DIR/issue_101973.rs:+1:32: +1:45
- StorageLive(_9); // scope 0 at $DIR/issue_101973.rs:+1:33: +1:39
- _9 = _1; // scope 0 at $DIR/issue_101973.rs:+1:33: +1:39
- _10 = CheckedShr(_9, const 8_i32); // scope 0 at $DIR/issue_101973.rs:+1:32: +1:45
+ _10 = CheckedShr(_1, const 8_i32); // scope 0 at $DIR/issue_101973.rs:+1:32: +1:45
assert(!move (_10.1: bool), "attempt to shift right by `{}`, which would overflow", const 8_i32) -> bb1; // scope 0 at $DIR/issue_101973.rs:+1:32: +1:45
}
bb4: {
- StorageDead(_16); // scope 3 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
- StorageDead(_15); // scope 3 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
StorageDead(_6); // scope 0 at $DIR/issue_101973.rs:+1:57: +1:58
StorageDead(_4); // scope 0 at $DIR/issue_101973.rs:+1:57: +1:58
_2 = move _3 as i32 (IntToInt); // scope 0 at $DIR/issue_101973.rs:+1:5: +1:65
diff --git a/tests/mir-opt/issue_41110.main.ElaborateDrops.after.mir b/tests/mir-opt/issue_41110.main.ElaborateDrops.after.mir
deleted file mode 100644
index c2ea3ac50..000000000
--- a/tests/mir-opt/issue_41110.main.ElaborateDrops.after.mir
+++ /dev/null
@@ -1,70 +0,0 @@
-// MIR for `main` after ElaborateDrops
-
-fn main() -> () {
- let mut _0: (); // return place in scope 0 at $DIR/issue_41110.rs:+0:11: +0:11
- let _1: (); // in scope 0 at $DIR/issue_41110.rs:+1:9: +1:10
- let mut _2: S; // in scope 0 at $DIR/issue_41110.rs:+1:13: +1:14
- let mut _3: S; // in scope 0 at $DIR/issue_41110.rs:+1:21: +1:27
- let mut _4: S; // in scope 0 at $DIR/issue_41110.rs:+1:21: +1:22
- let mut _5: bool; // in scope 0 at $DIR/issue_41110.rs:+1:27: +1:28
- scope 1 {
- debug x => _1; // in scope 1 at $DIR/issue_41110.rs:+1:9: +1:10
- }
-
- bb0: {
- _5 = const false; // scope 0 at $DIR/issue_41110.rs:+1:9: +1:10
- StorageLive(_1); // scope 0 at $DIR/issue_41110.rs:+1:9: +1:10
- StorageLive(_2); // scope 0 at $DIR/issue_41110.rs:+1:13: +1:14
- _5 = const true; // scope 0 at $DIR/issue_41110.rs:+1:13: +1:14
- _2 = S; // scope 0 at $DIR/issue_41110.rs:+1:13: +1:14
- StorageLive(_3); // scope 0 at $DIR/issue_41110.rs:+1:21: +1:27
- StorageLive(_4); // scope 0 at $DIR/issue_41110.rs:+1:21: +1:22
- _4 = S; // scope 0 at $DIR/issue_41110.rs:+1:21: +1:22
- _3 = S::id(move _4) -> [return: bb1, unwind: bb4]; // scope 0 at $DIR/issue_41110.rs:+1:21: +1:27
- // mir::Constant
- // + span: $DIR/issue_41110.rs:8:23: 8:25
- // + literal: Const { ty: fn(S) -> S {S::id}, val: Value(<ZST>) }
- }
-
- bb1: {
- StorageDead(_4); // scope 0 at $DIR/issue_41110.rs:+1:26: +1:27
- _5 = const false; // scope 0 at $DIR/issue_41110.rs:+1:13: +1:28
- _1 = S::other(move _2, move _3) -> [return: bb2, unwind: bb3]; // scope 0 at $DIR/issue_41110.rs:+1:13: +1:28
- // mir::Constant
- // + span: $DIR/issue_41110.rs:8:15: 8:20
- // + literal: Const { ty: fn(S, S) {S::other}, val: Value(<ZST>) }
- }
-
- bb2: {
- StorageDead(_3); // scope 0 at $DIR/issue_41110.rs:+1:27: +1:28
- _5 = const false; // scope 0 at $DIR/issue_41110.rs:+1:27: +1:28
- StorageDead(_2); // scope 0 at $DIR/issue_41110.rs:+1:27: +1:28
- _0 = const (); // scope 0 at $DIR/issue_41110.rs:+0:11: +2:2
- StorageDead(_1); // scope 0 at $DIR/issue_41110.rs:+2:1: +2:2
- return; // scope 0 at $DIR/issue_41110.rs:+2:2: +2:2
- }
-
- bb3 (cleanup): {
- goto -> bb5; // scope 0 at $DIR/issue_41110.rs:+1:27: +1:28
- }
-
- bb4 (cleanup): {
- goto -> bb5; // scope 0 at $DIR/issue_41110.rs:+1:26: +1:27
- }
-
- bb5 (cleanup): {
- goto -> bb8; // scope 0 at $DIR/issue_41110.rs:+1:27: +1:28
- }
-
- bb6 (cleanup): {
- resume; // scope 0 at $DIR/issue_41110.rs:+0:1: +2:2
- }
-
- bb7 (cleanup): {
- drop(_2) -> bb6; // scope 0 at $DIR/issue_41110.rs:+1:27: +1:28
- }
-
- bb8 (cleanup): {
- switchInt(_5) -> [0: bb6, otherwise: bb7]; // scope 0 at $DIR/issue_41110.rs:+1:27: +1:28
- }
-}
diff --git a/tests/mir-opt/issue_41110.main.ElaborateDrops.diff b/tests/mir-opt/issue_41110.main.ElaborateDrops.diff
new file mode 100644
index 000000000..7ac75b51a
--- /dev/null
+++ b/tests/mir-opt/issue_41110.main.ElaborateDrops.diff
@@ -0,0 +1,75 @@
+- // MIR for `main` before ElaborateDrops
++ // MIR for `main` after ElaborateDrops
+
+ fn main() -> () {
+ let mut _0: (); // return place in scope 0 at $DIR/issue_41110.rs:+0:11: +0:11
+ let _1: (); // in scope 0 at $DIR/issue_41110.rs:+1:9: +1:10
+ let mut _2: S; // in scope 0 at $DIR/issue_41110.rs:+1:13: +1:14
+ let mut _3: S; // in scope 0 at $DIR/issue_41110.rs:+1:21: +1:27
+ let mut _4: S; // in scope 0 at $DIR/issue_41110.rs:+1:21: +1:22
++ let mut _5: bool; // in scope 0 at $DIR/issue_41110.rs:+1:27: +1:28
+ scope 1 {
+ debug x => _1; // in scope 1 at $DIR/issue_41110.rs:+1:9: +1:10
+ }
+
+ bb0: {
++ _5 = const false; // scope 0 at $DIR/issue_41110.rs:+1:9: +1:10
+ StorageLive(_1); // scope 0 at $DIR/issue_41110.rs:+1:9: +1:10
+ StorageLive(_2); // scope 0 at $DIR/issue_41110.rs:+1:13: +1:14
++ _5 = const true; // scope 0 at $DIR/issue_41110.rs:+1:13: +1:14
+ _2 = S; // scope 0 at $DIR/issue_41110.rs:+1:13: +1:14
+ StorageLive(_3); // scope 0 at $DIR/issue_41110.rs:+1:21: +1:27
+ StorageLive(_4); // scope 0 at $DIR/issue_41110.rs:+1:21: +1:22
+ _4 = S; // scope 0 at $DIR/issue_41110.rs:+1:21: +1:22
+ _3 = S::id(move _4) -> [return: bb1, unwind: bb4]; // scope 0 at $DIR/issue_41110.rs:+1:21: +1:27
+ // mir::Constant
+ // + span: $DIR/issue_41110.rs:8:23: 8:25
+ // + literal: Const { ty: fn(S) -> S {S::id}, val: Value(<ZST>) }
+ }
+
+ bb1: {
+ StorageDead(_4); // scope 0 at $DIR/issue_41110.rs:+1:26: +1:27
++ _5 = const false; // scope 0 at $DIR/issue_41110.rs:+1:13: +1:28
+ _1 = S::other(move _2, move _3) -> [return: bb2, unwind: bb3]; // scope 0 at $DIR/issue_41110.rs:+1:13: +1:28
+ // mir::Constant
+ // + span: $DIR/issue_41110.rs:8:15: 8:20
+ // + literal: Const { ty: fn(S, S) {S::other}, val: Value(<ZST>) }
+ }
+
+ bb2: {
+ StorageDead(_3); // scope 0 at $DIR/issue_41110.rs:+1:27: +1:28
++ _5 = const false; // scope 0 at $DIR/issue_41110.rs:+1:27: +1:28
+ StorageDead(_2); // scope 0 at $DIR/issue_41110.rs:+1:27: +1:28
+ _0 = const (); // scope 0 at $DIR/issue_41110.rs:+0:11: +2:2
+ StorageDead(_1); // scope 0 at $DIR/issue_41110.rs:+2:1: +2:2
+ return; // scope 0 at $DIR/issue_41110.rs:+2:2: +2:2
+ }
+
+ bb3 (cleanup): {
+- drop(_3) -> bb5; // scope 0 at $DIR/issue_41110.rs:+1:27: +1:28
++ goto -> bb5; // scope 0 at $DIR/issue_41110.rs:+1:27: +1:28
+ }
+
+ bb4 (cleanup): {
+- drop(_4) -> bb5; // scope 0 at $DIR/issue_41110.rs:+1:26: +1:27
++ goto -> bb5; // scope 0 at $DIR/issue_41110.rs:+1:26: +1:27
+ }
+
+ bb5 (cleanup): {
+- drop(_2) -> bb6; // scope 0 at $DIR/issue_41110.rs:+1:27: +1:28
++ goto -> bb8; // scope 0 at $DIR/issue_41110.rs:+1:27: +1:28
+ }
+
+ bb6 (cleanup): {
+ resume; // scope 0 at $DIR/issue_41110.rs:+0:1: +2:2
++ }
++
++ bb7 (cleanup): {
++ drop(_2) -> bb6; // scope 0 at $DIR/issue_41110.rs:+1:27: +1:28
++ }
++
++ bb8 (cleanup): {
++ switchInt(_5) -> [0: bb6, otherwise: bb7]; // scope 0 at $DIR/issue_41110.rs:+1:27: +1:28
+ }
+ }
+
diff --git a/tests/mir-opt/issue_41110.rs b/tests/mir-opt/issue_41110.rs
index 638dc601e..e1067ce53 100644
--- a/tests/mir-opt/issue_41110.rs
+++ b/tests/mir-opt/issue_41110.rs
@@ -3,14 +3,14 @@
// check that we don't emit multiple drop flags when they are not needed.
-// EMIT_MIR issue_41110.main.ElaborateDrops.after.mir
+// EMIT_MIR issue_41110.main.ElaborateDrops.diff
fn main() {
let x = S.other(S.id());
}
// no_mangle to make sure this gets instantiated even in an executable.
#[no_mangle]
-// EMIT_MIR issue_41110.test.ElaborateDrops.after.mir
+// EMIT_MIR issue_41110.test.ElaborateDrops.diff
pub fn test() {
let u = S;
let mut v = S;
diff --git a/tests/mir-opt/issue_41110.test.ElaborateDrops.after.mir b/tests/mir-opt/issue_41110.test.ElaborateDrops.after.mir
deleted file mode 100644
index 82989c3f0..000000000
--- a/tests/mir-opt/issue_41110.test.ElaborateDrops.after.mir
+++ /dev/null
@@ -1,101 +0,0 @@
-// MIR for `test` after ElaborateDrops
-
-fn test() -> () {
- let mut _0: (); // return place in scope 0 at $DIR/issue_41110.rs:+0:15: +0:15
- let _1: S; // in scope 0 at $DIR/issue_41110.rs:+1:9: +1:10
- let _3: (); // in scope 0 at $DIR/issue_41110.rs:+3:5: +3:12
- let mut _4: S; // in scope 0 at $DIR/issue_41110.rs:+3:10: +3:11
- let mut _5: S; // in scope 0 at $DIR/issue_41110.rs:+4:9: +4:10
- let mut _6: bool; // in scope 0 at $DIR/issue_41110.rs:+5:1: +5:2
- scope 1 {
- debug u => _1; // in scope 1 at $DIR/issue_41110.rs:+1:9: +1:10
- let mut _2: S; // in scope 1 at $DIR/issue_41110.rs:+2:9: +2:14
- scope 2 {
- debug v => _2; // in scope 2 at $DIR/issue_41110.rs:+2:9: +2:14
- }
- }
-
- bb0: {
- _6 = const false; // scope 0 at $DIR/issue_41110.rs:+1:9: +1:10
- StorageLive(_1); // scope 0 at $DIR/issue_41110.rs:+1:9: +1:10
- _6 = const true; // scope 0 at $DIR/issue_41110.rs:+1:13: +1:14
- _1 = S; // scope 0 at $DIR/issue_41110.rs:+1:13: +1:14
- StorageLive(_2); // scope 1 at $DIR/issue_41110.rs:+2:9: +2:14
- _2 = S; // scope 1 at $DIR/issue_41110.rs:+2:17: +2:18
- StorageLive(_3); // scope 2 at $DIR/issue_41110.rs:+3:5: +3:12
- StorageLive(_4); // scope 2 at $DIR/issue_41110.rs:+3:10: +3:11
- _4 = move _2; // scope 2 at $DIR/issue_41110.rs:+3:10: +3:11
- _3 = std::mem::drop::<S>(move _4) -> [return: bb1, unwind: bb7]; // scope 2 at $DIR/issue_41110.rs:+3:5: +3:12
- // mir::Constant
- // + span: $DIR/issue_41110.rs:17:5: 17:9
- // + literal: Const { ty: fn(S) {std::mem::drop::<S>}, val: Value(<ZST>) }
- }
-
- bb1: {
- StorageDead(_4); // scope 2 at $DIR/issue_41110.rs:+3:11: +3:12
- StorageDead(_3); // scope 2 at $DIR/issue_41110.rs:+3:12: +3:13
- StorageLive(_5); // scope 2 at $DIR/issue_41110.rs:+4:9: +4:10
- _6 = const false; // scope 2 at $DIR/issue_41110.rs:+4:9: +4:10
- _5 = move _1; // scope 2 at $DIR/issue_41110.rs:+4:9: +4:10
- goto -> bb12; // scope 2 at $DIR/issue_41110.rs:+4:5: +4:6
- }
-
- bb2: {
- goto -> bb3; // scope 2 at $DIR/issue_41110.rs:+4:9: +4:10
- }
-
- bb3: {
- StorageDead(_5); // scope 2 at $DIR/issue_41110.rs:+4:9: +4:10
- _0 = const (); // scope 0 at $DIR/issue_41110.rs:+0:15: +5:2
- drop(_2) -> [return: bb4, unwind: bb9]; // scope 1 at $DIR/issue_41110.rs:+5:1: +5:2
- }
-
- bb4: {
- StorageDead(_2); // scope 1 at $DIR/issue_41110.rs:+5:1: +5:2
- goto -> bb5; // scope 0 at $DIR/issue_41110.rs:+5:1: +5:2
- }
-
- bb5: {
- _6 = const false; // scope 0 at $DIR/issue_41110.rs:+5:1: +5:2
- StorageDead(_1); // scope 0 at $DIR/issue_41110.rs:+5:1: +5:2
- return; // scope 0 at $DIR/issue_41110.rs:+5:2: +5:2
- }
-
- bb6 (cleanup): {
- goto -> bb8; // scope 2 at $DIR/issue_41110.rs:+4:9: +4:10
- }
-
- bb7 (cleanup): {
- goto -> bb8; // scope 2 at $DIR/issue_41110.rs:+3:11: +3:12
- }
-
- bb8 (cleanup): {
- goto -> bb9; // scope 1 at $DIR/issue_41110.rs:+5:1: +5:2
- }
-
- bb9 (cleanup): {
- goto -> bb14; // scope 0 at $DIR/issue_41110.rs:+5:1: +5:2
- }
-
- bb10 (cleanup): {
- resume; // scope 0 at $DIR/issue_41110.rs:+0:1: +5:2
- }
-
- bb11 (cleanup): {
- _2 = move _5; // scope 2 at $DIR/issue_41110.rs:+4:5: +4:6
- goto -> bb6; // scope 2 at $DIR/issue_41110.rs:+4:5: +4:6
- }
-
- bb12: {
- _2 = move _5; // scope 2 at $DIR/issue_41110.rs:+4:5: +4:6
- goto -> bb2; // scope 2 at $DIR/issue_41110.rs:+4:5: +4:6
- }
-
- bb13 (cleanup): {
- drop(_1) -> bb10; // scope 0 at $DIR/issue_41110.rs:+5:1: +5:2
- }
-
- bb14 (cleanup): {
- switchInt(_6) -> [0: bb10, otherwise: bb13]; // scope 0 at $DIR/issue_41110.rs:+5:1: +5:2
- }
-}
diff --git a/tests/mir-opt/issue_41110.test.ElaborateDrops.diff b/tests/mir-opt/issue_41110.test.ElaborateDrops.diff
new file mode 100644
index 000000000..79e3d073b
--- /dev/null
+++ b/tests/mir-opt/issue_41110.test.ElaborateDrops.diff
@@ -0,0 +1,109 @@
+- // MIR for `test` before ElaborateDrops
++ // MIR for `test` after ElaborateDrops
+
+ fn test() -> () {
+ let mut _0: (); // return place in scope 0 at $DIR/issue_41110.rs:+0:15: +0:15
+ let _1: S; // in scope 0 at $DIR/issue_41110.rs:+1:9: +1:10
+ let _3: (); // in scope 0 at $DIR/issue_41110.rs:+3:5: +3:12
+ let mut _4: S; // in scope 0 at $DIR/issue_41110.rs:+3:10: +3:11
+ let mut _5: S; // in scope 0 at $DIR/issue_41110.rs:+4:9: +4:10
++ let mut _6: bool; // in scope 0 at $DIR/issue_41110.rs:+5:1: +5:2
+ scope 1 {
+ debug u => _1; // in scope 1 at $DIR/issue_41110.rs:+1:9: +1:10
+ let mut _2: S; // in scope 1 at $DIR/issue_41110.rs:+2:9: +2:14
+ scope 2 {
+ debug v => _2; // in scope 2 at $DIR/issue_41110.rs:+2:9: +2:14
+ }
+ }
+
+ bb0: {
++ _6 = const false; // scope 0 at $DIR/issue_41110.rs:+1:9: +1:10
+ StorageLive(_1); // scope 0 at $DIR/issue_41110.rs:+1:9: +1:10
++ _6 = const true; // scope 0 at $DIR/issue_41110.rs:+1:13: +1:14
+ _1 = S; // scope 0 at $DIR/issue_41110.rs:+1:13: +1:14
+ StorageLive(_2); // scope 1 at $DIR/issue_41110.rs:+2:9: +2:14
+ _2 = S; // scope 1 at $DIR/issue_41110.rs:+2:17: +2:18
+ StorageLive(_3); // scope 2 at $DIR/issue_41110.rs:+3:5: +3:12
+ StorageLive(_4); // scope 2 at $DIR/issue_41110.rs:+3:10: +3:11
+ _4 = move _2; // scope 2 at $DIR/issue_41110.rs:+3:10: +3:11
+ _3 = std::mem::drop::<S>(move _4) -> [return: bb1, unwind: bb7]; // scope 2 at $DIR/issue_41110.rs:+3:5: +3:12
+ // mir::Constant
+ // + span: $DIR/issue_41110.rs:17:5: 17:9
+ // + literal: Const { ty: fn(S) {std::mem::drop::<S>}, val: Value(<ZST>) }
+ }
+
+ bb1: {
+ StorageDead(_4); // scope 2 at $DIR/issue_41110.rs:+3:11: +3:12
+ StorageDead(_3); // scope 2 at $DIR/issue_41110.rs:+3:12: +3:13
+ StorageLive(_5); // scope 2 at $DIR/issue_41110.rs:+4:9: +4:10
++ _6 = const false; // scope 2 at $DIR/issue_41110.rs:+4:9: +4:10
+ _5 = move _1; // scope 2 at $DIR/issue_41110.rs:+4:9: +4:10
+- replace(_2 <- move _5) -> [return: bb2, unwind: bb6]; // scope 2 at $DIR/issue_41110.rs:+4:5: +4:6
++ goto -> bb12; // scope 2 at $DIR/issue_41110.rs:+4:5: +4:6
+ }
+
+ bb2: {
+- drop(_5) -> [return: bb3, unwind: bb8]; // scope 2 at $DIR/issue_41110.rs:+4:9: +4:10
++ goto -> bb3; // scope 2 at $DIR/issue_41110.rs:+4:9: +4:10
+ }
+
+ bb3: {
+ StorageDead(_5); // scope 2 at $DIR/issue_41110.rs:+4:9: +4:10
+ _0 = const (); // scope 0 at $DIR/issue_41110.rs:+0:15: +5:2
+ drop(_2) -> [return: bb4, unwind: bb9]; // scope 1 at $DIR/issue_41110.rs:+5:1: +5:2
+ }
+
+ bb4: {
+ StorageDead(_2); // scope 1 at $DIR/issue_41110.rs:+5:1: +5:2
+- drop(_1) -> bb5; // scope 0 at $DIR/issue_41110.rs:+5:1: +5:2
++ goto -> bb5; // scope 0 at $DIR/issue_41110.rs:+5:1: +5:2
+ }
+
+ bb5: {
++ _6 = const false; // scope 0 at $DIR/issue_41110.rs:+5:1: +5:2
+ StorageDead(_1); // scope 0 at $DIR/issue_41110.rs:+5:1: +5:2
+ return; // scope 0 at $DIR/issue_41110.rs:+5:2: +5:2
+ }
+
+ bb6 (cleanup): {
+ drop(_5) -> bb8; // scope 2 at $DIR/issue_41110.rs:+4:9: +4:10
+ }
+
+ bb7 (cleanup): {
+- drop(_4) -> bb8; // scope 2 at $DIR/issue_41110.rs:+3:11: +3:12
++ goto -> bb8; // scope 2 at $DIR/issue_41110.rs:+3:11: +3:12
+ }
+
+ bb8 (cleanup): {
+- drop(_2) -> bb9; // scope 1 at $DIR/issue_41110.rs:+5:1: +5:2
++ goto -> bb9; // scope 1 at $DIR/issue_41110.rs:+5:1: +5:2
+ }
+
+ bb9 (cleanup): {
+- drop(_1) -> bb10; // scope 0 at $DIR/issue_41110.rs:+5:1: +5:2
++ goto -> bb14; // scope 0 at $DIR/issue_41110.rs:+5:1: +5:2
+ }
+
+ bb10 (cleanup): {
+ resume; // scope 0 at $DIR/issue_41110.rs:+0:1: +5:2
++ }
++
++ bb11 (cleanup): {
++ _2 = move _5; // scope 2 at $DIR/issue_41110.rs:+4:5: +4:6
++ goto -> bb10; // scope 2 at $DIR/issue_41110.rs:+4:5: +4:6
++ }
++
++ bb12: {
++ _2 = move _5; // scope 2 at $DIR/issue_41110.rs:+4:5: +4:6
++ goto -> bb2; // scope 2 at $DIR/issue_41110.rs:+4:5: +4:6
++ }
++
++ bb13 (cleanup): {
++ drop(_1) -> bb10; // scope 0 at $DIR/issue_41110.rs:+5:1: +5:2
++ }
++
++ bb14 (cleanup): {
++ switchInt(_6) -> [0: bb10, otherwise: bb13]; // scope 0 at $DIR/issue_41110.rs:+5:1: +5:2
+ }
+ }
+
diff --git a/tests/mir-opt/issue_41888.main.ElaborateDrops.after.mir b/tests/mir-opt/issue_41888.main.ElaborateDrops.after.mir
deleted file mode 100644
index 005042732..000000000
--- a/tests/mir-opt/issue_41888.main.ElaborateDrops.after.mir
+++ /dev/null
@@ -1,152 +0,0 @@
-// MIR for `main` after ElaborateDrops
-
-fn main() -> () {
- let mut _0: (); // return place in scope 0 at $DIR/issue_41888.rs:+0:11: +0:11
- let _1: E; // in scope 0 at $DIR/issue_41888.rs:+1:9: +1:10
- let mut _2: bool; // in scope 0 at $DIR/issue_41888.rs:+2:8: +2:14
- let mut _3: E; // in scope 0 at $DIR/issue_41888.rs:+3:13: +3:20
- let mut _4: K; // in scope 0 at $DIR/issue_41888.rs:+3:18: +3:19
- let mut _5: isize; // in scope 0 at $DIR/issue_41888.rs:+4:16: +4:24
- let mut _7: bool; // in scope 0 at $DIR/issue_41888.rs:+9:1: +9:2
- let mut _8: bool; // in scope 0 at $DIR/issue_41888.rs:+9:1: +9:2
- let mut _9: bool; // in scope 0 at $DIR/issue_41888.rs:+9:1: +9:2
- let mut _10: isize; // in scope 0 at $DIR/issue_41888.rs:+9:1: +9:2
- let mut _11: isize; // in scope 0 at $DIR/issue_41888.rs:+9:1: +9:2
- scope 1 {
- debug e => _1; // in scope 1 at $DIR/issue_41888.rs:+1:9: +1:10
- scope 2 {
- debug _k => _6; // in scope 2 at $DIR/issue_41888.rs:+4:21: +4:23
- let _6: K; // in scope 2 at $DIR/issue_41888.rs:+4:21: +4:23
- }
- }
-
- bb0: {
- _9 = const false; // scope 0 at $DIR/issue_41888.rs:+1:9: +1:10
- _7 = const false; // scope 0 at $DIR/issue_41888.rs:+1:9: +1:10
- _8 = const false; // scope 0 at $DIR/issue_41888.rs:+1:9: +1:10
- StorageLive(_1); // scope 0 at $DIR/issue_41888.rs:+1:9: +1:10
- StorageLive(_2); // scope 1 at $DIR/issue_41888.rs:+2:8: +2:14
- _2 = cond() -> [return: bb1, unwind: bb11]; // scope 1 at $DIR/issue_41888.rs:+2:8: +2:14
- // mir::Constant
- // + span: $DIR/issue_41888.rs:8:8: 8:12
- // + literal: Const { ty: fn() -> bool {cond}, val: Value(<ZST>) }
- }
-
- bb1: {
- switchInt(move _2) -> [0: bb7, otherwise: bb2]; // scope 1 at $DIR/issue_41888.rs:+2:8: +2:14
- }
-
- bb2: {
- StorageLive(_3); // scope 1 at $DIR/issue_41888.rs:+3:13: +3:20
- StorageLive(_4); // scope 1 at $DIR/issue_41888.rs:+3:18: +3:19
- _4 = K; // scope 1 at $DIR/issue_41888.rs:+3:18: +3:19
- _3 = E::F(move _4); // scope 1 at $DIR/issue_41888.rs:+3:13: +3:20
- StorageDead(_4); // scope 1 at $DIR/issue_41888.rs:+3:19: +3:20
- goto -> bb14; // scope 1 at $DIR/issue_41888.rs:+3:9: +3:10
- }
-
- bb3: {
- goto -> bb4; // scope 1 at $DIR/issue_41888.rs:+3:19: +3:20
- }
-
- bb4: {
- StorageDead(_3); // scope 1 at $DIR/issue_41888.rs:+3:19: +3:20
- _5 = discriminant(_1); // scope 2 at $DIR/issue_41888.rs:+4:16: +4:24
- switchInt(move _5) -> [0: bb5, otherwise: bb6]; // scope 2 at $DIR/issue_41888.rs:+4:16: +4:24
- }
-
- bb5: {
- StorageLive(_6); // scope 2 at $DIR/issue_41888.rs:+4:21: +4:23
- _9 = const false; // scope 2 at $DIR/issue_41888.rs:+4:21: +4:23
- _6 = move ((_1 as F).0: K); // scope 2 at $DIR/issue_41888.rs:+4:21: +4:23
- _0 = const (); // scope 2 at $DIR/issue_41888.rs:+4:29: +7:10
- StorageDead(_6); // scope 1 at $DIR/issue_41888.rs:+7:9: +7:10
- goto -> bb8; // scope 1 at $DIR/issue_41888.rs:+4:9: +7:10
- }
-
- bb6: {
- _0 = const (); // scope 1 at $DIR/issue_41888.rs:+7:10: +7:10
- goto -> bb8; // scope 1 at $DIR/issue_41888.rs:+4:9: +7:10
- }
-
- bb7: {
- _0 = const (); // scope 1 at $DIR/issue_41888.rs:+8:6: +8:6
- goto -> bb8; // scope 1 at $DIR/issue_41888.rs:+2:5: +8:6
- }
-
- bb8: {
- StorageDead(_2); // scope 1 at $DIR/issue_41888.rs:+8:5: +8:6
- goto -> bb20; // scope 0 at $DIR/issue_41888.rs:+9:1: +9:2
- }
-
- bb9: {
- _7 = const false; // scope 0 at $DIR/issue_41888.rs:+9:1: +9:2
- _8 = const false; // scope 0 at $DIR/issue_41888.rs:+9:1: +9:2
- _9 = const false; // scope 0 at $DIR/issue_41888.rs:+9:1: +9:2
- StorageDead(_1); // scope 0 at $DIR/issue_41888.rs:+9:1: +9:2
- return; // scope 0 at $DIR/issue_41888.rs:+9:2: +9:2
- }
-
- bb10 (cleanup): {
- goto -> bb11; // scope 1 at $DIR/issue_41888.rs:+3:19: +3:20
- }
-
- bb11 (cleanup): {
- goto -> bb12; // scope 0 at $DIR/issue_41888.rs:+9:1: +9:2
- }
-
- bb12 (cleanup): {
- resume; // scope 0 at $DIR/issue_41888.rs:+0:1: +9:2
- }
-
- bb13 (cleanup): {
- _7 = const true; // scope 1 at $DIR/issue_41888.rs:+3:9: +3:10
- _8 = const true; // scope 1 at $DIR/issue_41888.rs:+3:9: +3:10
- _9 = const true; // scope 1 at $DIR/issue_41888.rs:+3:9: +3:10
- _1 = move _3; // scope 1 at $DIR/issue_41888.rs:+3:9: +3:10
- goto -> bb10; // scope 1 at $DIR/issue_41888.rs:+3:9: +3:10
- }
-
- bb14: {
- _7 = const true; // scope 1 at $DIR/issue_41888.rs:+3:9: +3:10
- _8 = const true; // scope 1 at $DIR/issue_41888.rs:+3:9: +3:10
- _9 = const true; // scope 1 at $DIR/issue_41888.rs:+3:9: +3:10
- _1 = move _3; // scope 1 at $DIR/issue_41888.rs:+3:9: +3:10
- goto -> bb3; // scope 1 at $DIR/issue_41888.rs:+3:9: +3:10
- }
-
- bb15: {
- _7 = const false; // scope 0 at $DIR/issue_41888.rs:+9:1: +9:2
- goto -> bb9; // scope 0 at $DIR/issue_41888.rs:+9:1: +9:2
- }
-
- bb16 (cleanup): {
- goto -> bb12; // scope 0 at $DIR/issue_41888.rs:+9:1: +9:2
- }
-
- bb17: {
- drop(_1) -> [return: bb15, unwind: bb12]; // scope 0 at $DIR/issue_41888.rs:+9:1: +9:2
- }
-
- bb18 (cleanup): {
- drop(_1) -> bb12; // scope 0 at $DIR/issue_41888.rs:+9:1: +9:2
- }
-
- bb19: {
- _10 = discriminant(_1); // scope 0 at $DIR/issue_41888.rs:+9:1: +9:2
- switchInt(move _10) -> [0: bb15, otherwise: bb17]; // scope 0 at $DIR/issue_41888.rs:+9:1: +9:2
- }
-
- bb20: {
- switchInt(_7) -> [0: bb15, otherwise: bb19]; // scope 0 at $DIR/issue_41888.rs:+9:1: +9:2
- }
-
- bb21 (cleanup): {
- _11 = discriminant(_1); // scope 0 at $DIR/issue_41888.rs:+9:1: +9:2
- switchInt(move _11) -> [0: bb16, otherwise: bb18]; // scope 0 at $DIR/issue_41888.rs:+9:1: +9:2
- }
-
- bb22 (cleanup): {
- switchInt(_7) -> [0: bb12, otherwise: bb21]; // scope 0 at $DIR/issue_41888.rs:+9:1: +9:2
- }
-}
diff --git a/tests/mir-opt/issue_41888.main.ElaborateDrops.diff b/tests/mir-opt/issue_41888.main.ElaborateDrops.diff
new file mode 100644
index 000000000..257f0b1e6
--- /dev/null
+++ b/tests/mir-opt/issue_41888.main.ElaborateDrops.diff
@@ -0,0 +1,158 @@
+- // MIR for `main` before ElaborateDrops
++ // MIR for `main` after ElaborateDrops
+
+ fn main() -> () {
+ let mut _0: (); // return place in scope 0 at $DIR/issue_41888.rs:+0:11: +0:11
+ let _1: E; // in scope 0 at $DIR/issue_41888.rs:+1:9: +1:10
+ let mut _2: bool; // in scope 0 at $DIR/issue_41888.rs:+2:8: +2:14
+ let mut _3: E; // in scope 0 at $DIR/issue_41888.rs:+3:13: +3:20
+ let mut _4: K; // in scope 0 at $DIR/issue_41888.rs:+3:18: +3:19
+ let mut _5: isize; // in scope 0 at $DIR/issue_41888.rs:+4:16: +4:24
++ let mut _7: bool; // in scope 0 at $DIR/issue_41888.rs:+9:1: +9:2
++ let mut _8: bool; // in scope 0 at $DIR/issue_41888.rs:+9:1: +9:2
++ let mut _9: bool; // in scope 0 at $DIR/issue_41888.rs:+9:1: +9:2
++ let mut _10: isize; // in scope 0 at $DIR/issue_41888.rs:+9:1: +9:2
++ let mut _11: isize; // in scope 0 at $DIR/issue_41888.rs:+9:1: +9:2
+ scope 1 {
+ debug e => _1; // in scope 1 at $DIR/issue_41888.rs:+1:9: +1:10
+ scope 2 {
+ debug _k => _6; // in scope 2 at $DIR/issue_41888.rs:+4:21: +4:23
+ let _6: K; // in scope 2 at $DIR/issue_41888.rs:+4:21: +4:23
+ }
+ }
+
+ bb0: {
++ _9 = const false; // scope 0 at $DIR/issue_41888.rs:+1:9: +1:10
++ _7 = const false; // scope 0 at $DIR/issue_41888.rs:+1:9: +1:10
++ _8 = const false; // scope 0 at $DIR/issue_41888.rs:+1:9: +1:10
+ StorageLive(_1); // scope 0 at $DIR/issue_41888.rs:+1:9: +1:10
+ StorageLive(_2); // scope 1 at $DIR/issue_41888.rs:+2:8: +2:14
+ _2 = cond() -> [return: bb1, unwind: bb11]; // scope 1 at $DIR/issue_41888.rs:+2:8: +2:14
+ // mir::Constant
+ // + span: $DIR/issue_41888.rs:8:8: 8:12
+ // + literal: Const { ty: fn() -> bool {cond}, val: Value(<ZST>) }
+ }
+
+ bb1: {
+ switchInt(move _2) -> [0: bb7, otherwise: bb2]; // scope 1 at $DIR/issue_41888.rs:+2:8: +2:14
+ }
+
+ bb2: {
+ StorageLive(_3); // scope 1 at $DIR/issue_41888.rs:+3:13: +3:20
+ StorageLive(_4); // scope 1 at $DIR/issue_41888.rs:+3:18: +3:19
+ _4 = K; // scope 1 at $DIR/issue_41888.rs:+3:18: +3:19
+ _3 = E::F(move _4); // scope 1 at $DIR/issue_41888.rs:+3:13: +3:20
+ StorageDead(_4); // scope 1 at $DIR/issue_41888.rs:+3:19: +3:20
+- replace(_1 <- move _3) -> [return: bb3, unwind: bb10]; // scope 1 at $DIR/issue_41888.rs:+3:9: +3:10
++ goto -> bb14; // scope 1 at $DIR/issue_41888.rs:+3:9: +3:10
+ }
+
+ bb3: {
+- drop(_3) -> [return: bb4, unwind: bb11]; // scope 1 at $DIR/issue_41888.rs:+3:19: +3:20
++ goto -> bb4; // scope 1 at $DIR/issue_41888.rs:+3:19: +3:20
+ }
+
+ bb4: {
+ StorageDead(_3); // scope 1 at $DIR/issue_41888.rs:+3:19: +3:20
+ _5 = discriminant(_1); // scope 2 at $DIR/issue_41888.rs:+4:16: +4:24
+ switchInt(move _5) -> [0: bb5, otherwise: bb6]; // scope 2 at $DIR/issue_41888.rs:+4:16: +4:24
+ }
+
+ bb5: {
+ StorageLive(_6); // scope 2 at $DIR/issue_41888.rs:+4:21: +4:23
++ _9 = const false; // scope 2 at $DIR/issue_41888.rs:+4:21: +4:23
+ _6 = move ((_1 as F).0: K); // scope 2 at $DIR/issue_41888.rs:+4:21: +4:23
+ _0 = const (); // scope 2 at $DIR/issue_41888.rs:+4:29: +7:10
+ StorageDead(_6); // scope 1 at $DIR/issue_41888.rs:+7:9: +7:10
+ goto -> bb8; // scope 1 at $DIR/issue_41888.rs:+4:9: +7:10
+ }
+
+ bb6: {
+ _0 = const (); // scope 1 at $DIR/issue_41888.rs:+7:10: +7:10
+ goto -> bb8; // scope 1 at $DIR/issue_41888.rs:+4:9: +7:10
+ }
+
+ bb7: {
+ _0 = const (); // scope 1 at $DIR/issue_41888.rs:+8:6: +8:6
+ goto -> bb8; // scope 1 at $DIR/issue_41888.rs:+2:5: +8:6
+ }
+
+ bb8: {
+ StorageDead(_2); // scope 1 at $DIR/issue_41888.rs:+8:5: +8:6
+- drop(_1) -> bb9; // scope 0 at $DIR/issue_41888.rs:+9:1: +9:2
++ goto -> bb20; // scope 0 at $DIR/issue_41888.rs:+9:1: +9:2
+ }
+
+ bb9: {
++ _7 = const false; // scope 0 at $DIR/issue_41888.rs:+9:1: +9:2
++ _8 = const false; // scope 0 at $DIR/issue_41888.rs:+9:1: +9:2
++ _9 = const false; // scope 0 at $DIR/issue_41888.rs:+9:1: +9:2
+ StorageDead(_1); // scope 0 at $DIR/issue_41888.rs:+9:1: +9:2
+ return; // scope 0 at $DIR/issue_41888.rs:+9:2: +9:2
+ }
+
+ bb10 (cleanup): {
+ drop(_3) -> bb11; // scope 1 at $DIR/issue_41888.rs:+3:19: +3:20
+ }
+
+ bb11 (cleanup): {
+- drop(_1) -> bb12; // scope 0 at $DIR/issue_41888.rs:+9:1: +9:2
++ goto -> bb12; // scope 0 at $DIR/issue_41888.rs:+9:1: +9:2
+ }
+
+ bb12 (cleanup): {
+ resume; // scope 0 at $DIR/issue_41888.rs:+0:1: +9:2
++ }
++
++ bb13 (cleanup): {
++ _7 = const true; // scope 1 at $DIR/issue_41888.rs:+3:9: +3:10
++ _8 = const true; // scope 1 at $DIR/issue_41888.rs:+3:9: +3:10
++ _9 = const true; // scope 1 at $DIR/issue_41888.rs:+3:9: +3:10
++ _1 = move _3; // scope 1 at $DIR/issue_41888.rs:+3:9: +3:10
++ goto -> bb12; // scope 1 at $DIR/issue_41888.rs:+3:9: +3:10
++ }
++
++ bb14: {
++ _7 = const true; // scope 1 at $DIR/issue_41888.rs:+3:9: +3:10
++ _8 = const true; // scope 1 at $DIR/issue_41888.rs:+3:9: +3:10
++ _9 = const true; // scope 1 at $DIR/issue_41888.rs:+3:9: +3:10
++ _1 = move _3; // scope 1 at $DIR/issue_41888.rs:+3:9: +3:10
++ goto -> bb3; // scope 1 at $DIR/issue_41888.rs:+3:9: +3:10
++ }
++
++ bb15: {
++ _7 = const false; // scope 0 at $DIR/issue_41888.rs:+9:1: +9:2
++ goto -> bb9; // scope 0 at $DIR/issue_41888.rs:+9:1: +9:2
++ }
++
++ bb16 (cleanup): {
++ goto -> bb12; // scope 0 at $DIR/issue_41888.rs:+9:1: +9:2
++ }
++
++ bb17: {
++ drop(_1) -> [return: bb15, unwind: bb12]; // scope 0 at $DIR/issue_41888.rs:+9:1: +9:2
++ }
++
++ bb18 (cleanup): {
++ drop(_1) -> bb12; // scope 0 at $DIR/issue_41888.rs:+9:1: +9:2
++ }
++
++ bb19: {
++ _10 = discriminant(_1); // scope 0 at $DIR/issue_41888.rs:+9:1: +9:2
++ switchInt(move _10) -> [0: bb15, otherwise: bb17]; // scope 0 at $DIR/issue_41888.rs:+9:1: +9:2
++ }
++
++ bb20: {
++ switchInt(_7) -> [0: bb15, otherwise: bb19]; // scope 0 at $DIR/issue_41888.rs:+9:1: +9:2
++ }
++
++ bb21 (cleanup): {
++ _11 = discriminant(_1); // scope 0 at $DIR/issue_41888.rs:+9:1: +9:2
++ switchInt(move _11) -> [0: bb16, otherwise: bb18]; // scope 0 at $DIR/issue_41888.rs:+9:1: +9:2
++ }
++
++ bb22 (cleanup): {
++ switchInt(_7) -> [0: bb12, otherwise: bb21]; // scope 0 at $DIR/issue_41888.rs:+9:1: +9:2
+ }
+ }
+
diff --git a/tests/mir-opt/issue_41888.rs b/tests/mir-opt/issue_41888.rs
index c1046c14d..0f10c0a1d 100644
--- a/tests/mir-opt/issue_41888.rs
+++ b/tests/mir-opt/issue_41888.rs
@@ -2,7 +2,7 @@
// check that we clear the "ADT master drop flag" even when there are
// no fields to be dropped.
-// EMIT_MIR issue_41888.main.ElaborateDrops.after.mir
+// EMIT_MIR issue_41888.main.ElaborateDrops.diff
fn main() {
let e;
if cond() {
diff --git a/tests/mir-opt/issue_73223.main.SimplifyArmIdentity.diff b/tests/mir-opt/issue_73223.main.SimplifyArmIdentity.diff
deleted file mode 100644
index bf3bcfdb5..000000000
--- a/tests/mir-opt/issue_73223.main.SimplifyArmIdentity.diff
+++ /dev/null
@@ -1,156 +0,0 @@
-- // MIR for `main` before SimplifyArmIdentity
-+ // MIR for `main` after SimplifyArmIdentity
-
- fn main() -> () {
- let mut _0: (); // return place in scope 0 at $DIR/issue_73223.rs:+0:11: +0:11
- let _1: i32; // in scope 0 at $DIR/issue_73223.rs:+1:9: +1:14
- let mut _2: std::option::Option<i32>; // in scope 0 at $DIR/issue_73223.rs:+1:23: +1:30
- let mut _3: isize; // in scope 0 at $DIR/issue_73223.rs:+2:9: +2:16
- let _4: i32; // in scope 0 at $DIR/issue_73223.rs:+2:14: +2:15
- let mut _6: i32; // in scope 0 at $DIR/issue_73223.rs:+6:22: +6:27
- let mut _7: &i32; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- let mut _8: &i32; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- let mut _11: bool; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- let mut _12: bool; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- let mut _13: i32; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- let mut _14: i32; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- let _16: !; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- let mut _17: core::panicking::AssertKind; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- let mut _18: &i32; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- let _19: &i32; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- let mut _20: &i32; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- let _21: &i32; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- let mut _22: std::option::Option<std::fmt::Arguments<'_>>; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- let mut _24: &i32; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- let mut _25: &i32; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- scope 1 {
- debug split => _1; // in scope 1 at $DIR/issue_73223.rs:+1:9: +1:14
- let _5: std::option::Option<i32>; // in scope 1 at $DIR/issue_73223.rs:+6:9: +6:14
- scope 3 {
- debug _prev => _5; // in scope 3 at $DIR/issue_73223.rs:+6:9: +6:14
- let _9: &i32; // in scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- let _10: &i32; // in scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- let mut _23: &i32; // in scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- scope 4 {
- debug left_val => _9; // in scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- debug right_val => _10; // in scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- let _15: core::panicking::AssertKind; // in scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- scope 5 {
- debug kind => _15; // in scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- }
- }
- }
- }
- scope 2 {
- debug v => _4; // in scope 2 at $DIR/issue_73223.rs:+2:14: +2:15
- }
-
- bb0: {
- StorageLive(_1); // scope 0 at $DIR/issue_73223.rs:+1:9: +1:14
- StorageLive(_2); // scope 0 at $DIR/issue_73223.rs:+1:23: +1:30
- Deinit(_2); // scope 0 at $DIR/issue_73223.rs:+1:23: +1:30
- ((_2 as Some).0: i32) = const 1_i32; // scope 0 at $DIR/issue_73223.rs:+1:23: +1:30
- discriminant(_2) = 1; // scope 0 at $DIR/issue_73223.rs:+1:23: +1:30
- _3 = const 1_isize; // scope 0 at $DIR/issue_73223.rs:+1:23: +1:30
- goto -> bb3; // scope 0 at $DIR/issue_73223.rs:+1:17: +1:30
- }
-
- bb1: {
- StorageDead(_2); // scope 0 at $DIR/issue_73223.rs:+4:6: +4:7
- StorageDead(_1); // scope 0 at $DIR/issue_73223.rs:+8:1: +8:2
- return; // scope 0 at $DIR/issue_73223.rs:+8:2: +8:2
- }
-
- bb2: {
- unreachable; // scope 0 at $DIR/issue_73223.rs:+1:23: +1:30
- }
-
- bb3: {
- StorageLive(_4); // scope 0 at $DIR/issue_73223.rs:+2:14: +2:15
- _4 = ((_2 as Some).0: i32); // scope 0 at $DIR/issue_73223.rs:+2:14: +2:15
- _1 = _4; // scope 2 at $DIR/issue_73223.rs:+2:20: +2:21
- StorageDead(_4); // scope 0 at $DIR/issue_73223.rs:+2:20: +2:21
- StorageDead(_2); // scope 0 at $DIR/issue_73223.rs:+4:6: +4:7
- StorageLive(_5); // scope 1 at $DIR/issue_73223.rs:+6:9: +6:14
- StorageLive(_6); // scope 1 at $DIR/issue_73223.rs:+6:22: +6:27
- _6 = _1; // scope 1 at $DIR/issue_73223.rs:+6:22: +6:27
- Deinit(_5); // scope 1 at $DIR/issue_73223.rs:+6:17: +6:28
- ((_5 as Some).0: i32) = move _6; // scope 1 at $DIR/issue_73223.rs:+6:17: +6:28
- discriminant(_5) = 1; // scope 1 at $DIR/issue_73223.rs:+6:17: +6:28
- StorageDead(_6); // scope 1 at $DIR/issue_73223.rs:+6:27: +6:28
- StorageLive(_24); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- StorageLive(_25); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- StorageLive(_7); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- _7 = &_1; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- StorageLive(_8); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- _23 = const _; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- // mir::Constant
- // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL
- // + literal: Const { ty: &i32, val: Unevaluated(main, [], Some(promoted[0])) }
- _8 = _23; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- Deinit(_24); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- Deinit(_25); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- _24 = move _7; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- _25 = move _8; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- StorageDead(_8); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- StorageDead(_7); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- StorageLive(_9); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- _9 = _24; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- StorageLive(_10); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- _10 = _25; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- StorageLive(_11); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- StorageLive(_12); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- StorageLive(_13); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- _13 = (*_9); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- StorageLive(_14); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- _14 = const 1_i32; // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- _12 = Eq(move _13, const 1_i32); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- StorageDead(_14); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- StorageDead(_13); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- _11 = Not(move _12); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- StorageDead(_12); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- switchInt(move _11) -> [0: bb5, otherwise: bb4]; // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- }
-
- bb4: {
- StorageLive(_15); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- Deinit(_15); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- discriminant(_15) = 0; // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- StorageLive(_16); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- StorageLive(_17); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- _17 = const core::panicking::AssertKind::Eq; // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- // mir::Constant
- // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL
- // + literal: Const { ty: core::panicking::AssertKind, val: Value(Scalar(0x00)) }
- StorageLive(_18); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- StorageLive(_19); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- _19 = _9; // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- _18 = _19; // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- StorageLive(_20); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- StorageLive(_21); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- _21 = _10; // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- _20 = _21; // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- StorageLive(_22); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- Deinit(_22); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- discriminant(_22) = 0; // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- _16 = core::panicking::assert_failed::<i32, i32>(const core::panicking::AssertKind::Eq, move _18, move _20, move _22); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- // mir::Constant
- // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL
- // + literal: Const { ty: for<'a, 'b, 'c> fn(core::panicking::AssertKind, &'a i32, &'b i32, Option<Arguments<'c>>) -> ! {core::panicking::assert_failed::<i32, i32>}, val: Value(<ZST>) }
- // mir::Constant
- // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL
- // + literal: Const { ty: core::panicking::AssertKind, val: Value(Scalar(0x00)) }
- }
-
- bb5: {
- StorageDead(_11); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- StorageDead(_10); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- StorageDead(_9); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- StorageDead(_24); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- StorageDead(_25); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- StorageDead(_5); // scope 1 at $DIR/issue_73223.rs:+8:1: +8:2
- StorageDead(_1); // scope 0 at $DIR/issue_73223.rs:+8:1: +8:2
- return; // scope 0 at $DIR/issue_73223.rs:+8:2: +8:2
- }
- }
-
diff --git a/tests/mir-opt/issue_73223.rs b/tests/mir-opt/issue_73223.rs
deleted file mode 100644
index be114cab7..000000000
--- a/tests/mir-opt/issue_73223.rs
+++ /dev/null
@@ -1,12 +0,0 @@
-fn main() {
- let split = match Some(1) {
- Some(v) => v,
- None => return,
- };
-
- let _prev = Some(split);
- assert_eq!(split, 1);
-}
-
-
-// EMIT_MIR issue_73223.main.SimplifyArmIdentity.diff
diff --git a/tests/mir-opt/issue_76432.rs b/tests/mir-opt/issue_76432.rs
index c8b405ca8..fbbfd4ceb 100644
--- a/tests/mir-opt/issue_76432.rs
+++ b/tests/mir-opt/issue_76432.rs
@@ -1,3 +1,4 @@
+// compile-flags: -Zmir-enable-passes=-NormalizeArrayLen
// Check that we do not insert StorageDead at each target if StorageDead was never seen
// EMIT_MIR issue_76432.test.SimplifyComparisonIntegral.diff
diff --git a/tests/mir-opt/issue_76432.test.SimplifyComparisonIntegral.diff b/tests/mir-opt/issue_76432.test.SimplifyComparisonIntegral.diff
index c24543dae..cc4f7cc06 100644
--- a/tests/mir-opt/issue_76432.test.SimplifyComparisonIntegral.diff
+++ b/tests/mir-opt/issue_76432.test.SimplifyComparisonIntegral.diff
@@ -29,24 +29,10 @@
bb0: {
StorageLive(_2); // scope 0 at $DIR/issue_76432.rs:+1:9: +1:10
- StorageLive(_3); // scope 0 at $DIR/issue_76432.rs:+1:19: +1:29
- StorageLive(_4); // scope 0 at $DIR/issue_76432.rs:+1:19: +1:29
StorageLive(_5); // scope 0 at $DIR/issue_76432.rs:+1:20: +1:29
- StorageLive(_6); // scope 0 at $DIR/issue_76432.rs:+1:21: +1:22
- _6 = _1; // scope 0 at $DIR/issue_76432.rs:+1:21: +1:22
- StorageLive(_7); // scope 0 at $DIR/issue_76432.rs:+1:24: +1:25
- _7 = _1; // scope 0 at $DIR/issue_76432.rs:+1:24: +1:25
- StorageLive(_8); // scope 0 at $DIR/issue_76432.rs:+1:27: +1:28
- _8 = _1; // scope 0 at $DIR/issue_76432.rs:+1:27: +1:28
- _5 = [move _6, move _7, move _8]; // scope 0 at $DIR/issue_76432.rs:+1:20: +1:29
- StorageDead(_8); // scope 0 at $DIR/issue_76432.rs:+1:28: +1:29
- StorageDead(_7); // scope 0 at $DIR/issue_76432.rs:+1:28: +1:29
- StorageDead(_6); // scope 0 at $DIR/issue_76432.rs:+1:28: +1:29
+ _5 = [_1, _1, _1]; // scope 0 at $DIR/issue_76432.rs:+1:20: +1:29
_4 = &_5; // scope 0 at $DIR/issue_76432.rs:+1:19: +1:29
- _3 = _4; // scope 0 at $DIR/issue_76432.rs:+1:19: +1:29
- _2 = move _3 as &[T] (Pointer(Unsize)); // scope 0 at $DIR/issue_76432.rs:+1:19: +1:29
- StorageDead(_3); // scope 0 at $DIR/issue_76432.rs:+1:28: +1:29
- StorageDead(_4); // scope 0 at $DIR/issue_76432.rs:+1:29: +1:30
+ _2 = _4 as &[T] (Pointer(Unsize)); // scope 0 at $DIR/issue_76432.rs:+1:19: +1:29
_9 = Len((*_2)); // scope 1 at $DIR/issue_76432.rs:+3:9: +3:33
_10 = const 3_usize; // scope 1 at $DIR/issue_76432.rs:+3:9: +3:33
- _11 = Eq(move _9, const 3_usize); // scope 1 at $DIR/issue_76432.rs:+3:9: +3:33
diff --git a/tests/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.mir b/tests/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.mir
index c17d221f8..291fc5063 100644
--- a/tests/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.mir
+++ b/tests/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.mir
@@ -5,15 +5,14 @@ fn num_to_digit(_1: char) -> u32 {
let mut _0: u32; // return place in scope 0 at $DIR/issue_59352.rs:+0:35: +0:38
let mut _2: std::option::Option<u32>; // in scope 0 at $DIR/issue_59352.rs:+2:26: +2:41
let mut _3: u32; // in scope 0 at $DIR/issue_59352.rs:+2:12: +2:23
- let mut _9: isize; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
scope 1 (inlined char::methods::<impl char>::is_digit) { // at $DIR/issue_59352.rs:14:12: 14:23
debug self => _1; // in scope 1 at $SRC_DIR/core/src/char/methods.rs:LL:COL
debug radix => _3; // in scope 1 at $SRC_DIR/core/src/char/methods.rs:LL:COL
let mut _4: &std::option::Option<u32>; // in scope 1 at $SRC_DIR/core/src/char/methods.rs:LL:COL
let _5: std::option::Option<u32>; // in scope 1 at $SRC_DIR/core/src/char/methods.rs:LL:COL
- let mut _6: char; // in scope 1 at $SRC_DIR/core/src/char/methods.rs:LL:COL
scope 2 (inlined Option::<u32>::is_some) { // at $SRC_DIR/core/src/char/methods.rs:LL:COL
debug self => _4; // in scope 2 at $SRC_DIR/core/src/option.rs:LL:COL
+ let mut _6: isize; // in scope 2 at $SRC_DIR/core/src/option.rs:LL:COL
}
}
scope 3 (inlined #[track_caller] Option::<u32>::unwrap) { // at $DIR/issue_59352.rs:14:42: 14:50
@@ -29,9 +28,7 @@ fn num_to_digit(_1: char) -> u32 {
StorageLive(_3); // scope 0 at $DIR/issue_59352.rs:+2:12: +2:23
StorageLive(_4); // scope 1 at $SRC_DIR/core/src/char/methods.rs:LL:COL
StorageLive(_5); // scope 1 at $SRC_DIR/core/src/char/methods.rs:LL:COL
- StorageLive(_6); // scope 1 at $SRC_DIR/core/src/char/methods.rs:LL:COL
- _6 = _1; // scope 1 at $SRC_DIR/core/src/char/methods.rs:LL:COL
- _5 = char::methods::<impl char>::to_digit(move _6, const 8_u32) -> bb5; // scope 1 at $SRC_DIR/core/src/char/methods.rs:LL:COL
+ _5 = char::methods::<impl char>::to_digit(_1, const 8_u32) -> bb5; // scope 1 at $SRC_DIR/core/src/char/methods.rs:LL:COL
// mir::Constant
// + span: $SRC_DIR/core/src/char/methods.rs:LL:COL
// + literal: Const { ty: fn(char, u32) -> Option<u32> {char::methods::<impl char>::to_digit}, val: Value(<ZST>) }
@@ -39,7 +36,7 @@ fn num_to_digit(_1: char) -> u32 {
bb1: {
StorageLive(_2); // scope 0 at $DIR/issue_59352.rs:+2:26: +2:41
- _2 = char::methods::<impl char>::to_digit(move _1, const 8_u32) -> bb2; // scope 0 at $DIR/issue_59352.rs:+2:26: +2:41
+ _2 = char::methods::<impl char>::to_digit(_1, const 8_u32) -> bb2; // scope 0 at $DIR/issue_59352.rs:+2:26: +2:41
// mir::Constant
// + span: $DIR/issue_59352.rs:14:30: 14:38
// + literal: Const { ty: fn(char, u32) -> Option<u32> {char::methods::<impl char>::to_digit}, val: Value(<ZST>) }
@@ -61,12 +58,11 @@ fn num_to_digit(_1: char) -> u32 {
bb5: {
_4 = &_5; // scope 1 at $SRC_DIR/core/src/char/methods.rs:LL:COL
- StorageDead(_6); // scope 1 at $SRC_DIR/core/src/char/methods.rs:LL:COL
- _9 = discriminant((*_4)); // scope 2 at $SRC_DIR/core/src/option.rs:LL:COL
+ _6 = discriminant((*_4)); // scope 2 at $SRC_DIR/core/src/option.rs:LL:COL
StorageDead(_4); // scope 1 at $SRC_DIR/core/src/char/methods.rs:LL:COL
StorageDead(_5); // scope 1 at $SRC_DIR/core/src/char/methods.rs:LL:COL
StorageDead(_3); // scope 0 at $DIR/issue_59352.rs:+2:12: +2:23
- switchInt(move _9) -> [1: bb1, otherwise: bb3]; // scope 0 at $DIR/issue_59352.rs:+2:8: +2:23
+ switchInt(move _6) -> [1: bb1, otherwise: bb3]; // scope 0 at $DIR/issue_59352.rs:+2:8: +2:23
}
bb6: {
diff --git a/tests/mir-opt/issues/issue_75439.foo.MatchBranchSimplification.diff b/tests/mir-opt/issues/issue_75439.foo.MatchBranchSimplification.diff
index 938047803..bcda12880 100644
--- a/tests/mir-opt/issues/issue_75439.foo.MatchBranchSimplification.diff
+++ b/tests/mir-opt/issues/issue_75439.foo.MatchBranchSimplification.diff
@@ -67,17 +67,14 @@
bb7: {
StorageDead(_6); // scope 4 at $DIR/issue_75439.rs:+5:35: +5:36
- Deinit(_0); // scope 3 at $DIR/issue_75439.rs:+5:9: +5:39
- ((_0 as Some).0: [u8; 4]) = move _5; // scope 3 at $DIR/issue_75439.rs:+5:9: +5:39
- discriminant(_0) = 1; // scope 3 at $DIR/issue_75439.rs:+5:9: +5:39
+ _0 = Option::<[u8; 4]>::Some(move _5); // scope 3 at $DIR/issue_75439.rs:+5:9: +5:39
StorageDead(_5); // scope 3 at $DIR/issue_75439.rs:+5:38: +5:39
StorageDead(_4); // scope 1 at $DIR/issue_75439.rs:+6:5: +6:6
goto -> bb9; // scope 1 at $DIR/issue_75439.rs:+4:5: +8:6
}
bb8: {
- Deinit(_0); // scope 1 at $DIR/issue_75439.rs:+7:9: +7:13
- discriminant(_0) = 0; // scope 1 at $DIR/issue_75439.rs:+7:9: +7:13
+ _0 = Option::<[u8; 4]>::None; // scope 1 at $DIR/issue_75439.rs:+7:9: +7:13
goto -> bb9; // scope 1 at $DIR/issue_75439.rs:+4:5: +8:6
}
diff --git a/tests/mir-opt/lower_array_len.array_bound.NormalizeArrayLen.diff b/tests/mir-opt/lower_array_len.array_bound.NormalizeArrayLen.diff
index 9bc7060e9..59de067f4 100644
--- a/tests/mir-opt/lower_array_len.array_bound.NormalizeArrayLen.diff
+++ b/tests/mir-opt/lower_array_len.array_bound.NormalizeArrayLen.diff
@@ -13,7 +13,6 @@
let _8: usize; // in scope 0 at $DIR/lower_array_len.rs:+2:15: +2:20
let mut _9: usize; // in scope 0 at $DIR/lower_array_len.rs:+2:9: +2:21
let mut _10: bool; // in scope 0 at $DIR/lower_array_len.rs:+2:9: +2:21
-+ let mut _11: &[u8; N]; // in scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27
bb0: {
StorageLive(_3); // scope 0 at $DIR/lower_array_len.rs:+1:8: +1:27
@@ -23,13 +22,10 @@
StorageLive(_6); // scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27
StorageLive(_7); // scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27
_7 = &(*_2); // scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27
-+ StorageLive(_11); // scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27
-+ _11 = _7; // scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27
_6 = move _7 as &[u8] (Pointer(Unsize)); // scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27
StorageDead(_7); // scope 0 at $DIR/lower_array_len.rs:+1:20: +1:21
- _5 = Len((*_6)); // scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27
-+ _5 = Len((*_11)); // scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27
-+ StorageDead(_11); // scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27
++ _5 = const N; // scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27
goto -> bb1; // scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27
}
diff --git a/tests/mir-opt/lower_array_len.array_bound_mut.NormalizeArrayLen.diff b/tests/mir-opt/lower_array_len.array_bound_mut.NormalizeArrayLen.diff
index cf427cfd1..17574b1b6 100644
--- a/tests/mir-opt/lower_array_len.array_bound_mut.NormalizeArrayLen.diff
+++ b/tests/mir-opt/lower_array_len.array_bound_mut.NormalizeArrayLen.diff
@@ -16,7 +16,6 @@
let _11: usize; // in scope 0 at $DIR/lower_array_len.rs:+4:15: +4:16
let mut _12: usize; // in scope 0 at $DIR/lower_array_len.rs:+4:9: +4:17
let mut _13: bool; // in scope 0 at $DIR/lower_array_len.rs:+4:9: +4:17
-+ let mut _14: &[u8; N]; // in scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27
bb0: {
StorageLive(_3); // scope 0 at $DIR/lower_array_len.rs:+1:8: +1:27
@@ -26,13 +25,10 @@
StorageLive(_6); // scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27
StorageLive(_7); // scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27
_7 = &(*_2); // scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27
-+ StorageLive(_14); // scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27
-+ _14 = _7; // scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27
_6 = move _7 as &[u8] (Pointer(Unsize)); // scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27
StorageDead(_7); // scope 0 at $DIR/lower_array_len.rs:+1:20: +1:21
- _5 = Len((*_6)); // scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27
-+ _5 = Len((*_14)); // scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27
-+ StorageDead(_14); // scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27
++ _5 = const N; // scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27
goto -> bb1; // scope 0 at $DIR/lower_array_len.rs:+1:16: +1:27
}
diff --git a/tests/mir-opt/lower_array_len.array_len.NormalizeArrayLen.diff b/tests/mir-opt/lower_array_len.array_len.NormalizeArrayLen.diff
index 3ed68f5f7..66feff62f 100644
--- a/tests/mir-opt/lower_array_len.array_len.NormalizeArrayLen.diff
+++ b/tests/mir-opt/lower_array_len.array_len.NormalizeArrayLen.diff
@@ -6,19 +6,15 @@
let mut _0: usize; // return place in scope 0 at $DIR/lower_array_len.rs:+0:52: +0:57
let mut _2: &[u8]; // in scope 0 at $DIR/lower_array_len.rs:+1:5: +1:14
let mut _3: &[u8; N]; // in scope 0 at $DIR/lower_array_len.rs:+1:5: +1:14
-+ let mut _4: &[u8; N]; // in scope 0 at $DIR/lower_array_len.rs:+1:5: +1:14
bb0: {
StorageLive(_2); // scope 0 at $DIR/lower_array_len.rs:+1:5: +1:14
StorageLive(_3); // scope 0 at $DIR/lower_array_len.rs:+1:5: +1:14
_3 = &(*_1); // scope 0 at $DIR/lower_array_len.rs:+1:5: +1:14
-+ StorageLive(_4); // scope 0 at $DIR/lower_array_len.rs:+1:5: +1:14
-+ _4 = _3; // scope 0 at $DIR/lower_array_len.rs:+1:5: +1:14
_2 = move _3 as &[u8] (Pointer(Unsize)); // scope 0 at $DIR/lower_array_len.rs:+1:5: +1:14
StorageDead(_3); // scope 0 at $DIR/lower_array_len.rs:+1:7: +1:8
- _0 = Len((*_2)); // scope 0 at $DIR/lower_array_len.rs:+1:5: +1:14
-+ _0 = Len((*_4)); // scope 0 at $DIR/lower_array_len.rs:+1:5: +1:14
-+ StorageDead(_4); // scope 0 at $DIR/lower_array_len.rs:+1:5: +1:14
++ _0 = const N; // scope 0 at $DIR/lower_array_len.rs:+1:5: +1:14
goto -> bb1; // scope 0 at $DIR/lower_array_len.rs:+1:5: +1:14
}
diff --git a/tests/mir-opt/lower_array_len.array_len_by_value.NormalizeArrayLen.diff b/tests/mir-opt/lower_array_len.array_len_by_value.NormalizeArrayLen.diff
index f0e0cdcfd..c0a277edc 100644
--- a/tests/mir-opt/lower_array_len.array_len_by_value.NormalizeArrayLen.diff
+++ b/tests/mir-opt/lower_array_len.array_len_by_value.NormalizeArrayLen.diff
@@ -6,19 +6,15 @@
let mut _0: usize; // return place in scope 0 at $DIR/lower_array_len.rs:+0:60: +0:65
let mut _2: &[u8]; // in scope 0 at $DIR/lower_array_len.rs:+1:5: +1:14
let mut _3: &[u8; N]; // in scope 0 at $DIR/lower_array_len.rs:+1:5: +1:14
-+ let mut _4: &[u8; N]; // in scope 0 at $DIR/lower_array_len.rs:+1:5: +1:14
bb0: {
StorageLive(_2); // scope 0 at $DIR/lower_array_len.rs:+1:5: +1:14
StorageLive(_3); // scope 0 at $DIR/lower_array_len.rs:+1:5: +1:14
_3 = &_1; // scope 0 at $DIR/lower_array_len.rs:+1:5: +1:14
-+ StorageLive(_4); // scope 0 at $DIR/lower_array_len.rs:+1:5: +1:14
-+ _4 = _3; // scope 0 at $DIR/lower_array_len.rs:+1:5: +1:14
_2 = move _3 as &[u8] (Pointer(Unsize)); // scope 0 at $DIR/lower_array_len.rs:+1:5: +1:14
StorageDead(_3); // scope 0 at $DIR/lower_array_len.rs:+1:7: +1:8
- _0 = Len((*_2)); // scope 0 at $DIR/lower_array_len.rs:+1:5: +1:14
-+ _0 = Len((*_4)); // scope 0 at $DIR/lower_array_len.rs:+1:5: +1:14
-+ StorageDead(_4); // scope 0 at $DIR/lower_array_len.rs:+1:5: +1:14
++ _0 = const N; // scope 0 at $DIR/lower_array_len.rs:+1:5: +1:14
goto -> bb1; // scope 0 at $DIR/lower_array_len.rs:+1:5: +1:14
}
diff --git a/tests/mir-opt/lower_array_len.array_len_raw.NormalizeArrayLen.diff b/tests/mir-opt/lower_array_len.array_len_raw.NormalizeArrayLen.diff
new file mode 100644
index 000000000..8b35fd57f
--- /dev/null
+++ b/tests/mir-opt/lower_array_len.array_len_raw.NormalizeArrayLen.diff
@@ -0,0 +1,50 @@
+- // MIR for `array_len_raw` before NormalizeArrayLen
++ // MIR for `array_len_raw` after NormalizeArrayLen
+
+ fn array_len_raw(_1: [u8; N]) -> usize {
+ debug arr => _1; // in scope 0 at $DIR/lower_array_len.rs:+0:38: +0:41
+ let mut _0: usize; // return place in scope 0 at $DIR/lower_array_len.rs:+0:55: +0:60
+ let _2: &[u8]; // in scope 0 at $DIR/lower_array_len.rs:+1:9: +1:12
+ let mut _3: &[u8; N]; // in scope 0 at $DIR/lower_array_len.rs:+1:21: +1:25
+ let _4: &[u8; N]; // in scope 0 at $DIR/lower_array_len.rs:+1:21: +1:25
+ let mut _6: &[u8]; // in scope 0 at $DIR/lower_array_len.rs:+3:5: +3:27
+ let _7: &[u8]; // in scope 0 at $DIR/lower_array_len.rs:+3:14: +3:19
+ scope 1 {
+ debug arr => _2; // in scope 1 at $DIR/lower_array_len.rs:+1:9: +1:12
+ let _5: *const [u8]; // in scope 1 at $DIR/lower_array_len.rs:+2:9: +2:12
+ scope 2 {
+ debug arr => _5; // in scope 2 at $DIR/lower_array_len.rs:+2:9: +2:12
+ scope 3 {
+ }
+ }
+ }
+
+ bb0: {
+ StorageLive(_2); // scope 0 at $DIR/lower_array_len.rs:+1:9: +1:12
+ StorageLive(_3); // scope 0 at $DIR/lower_array_len.rs:+1:21: +1:25
+ StorageLive(_4); // scope 0 at $DIR/lower_array_len.rs:+1:21: +1:25
+ _4 = &_1; // scope 0 at $DIR/lower_array_len.rs:+1:21: +1:25
+ _3 = &(*_4); // scope 0 at $DIR/lower_array_len.rs:+1:21: +1:25
+ _2 = move _3 as &[u8] (Pointer(Unsize)); // scope 0 at $DIR/lower_array_len.rs:+1:21: +1:25
+ StorageDead(_3); // scope 0 at $DIR/lower_array_len.rs:+1:24: +1:25
+ StorageDead(_4); // scope 0 at $DIR/lower_array_len.rs:+1:25: +1:26
+ StorageLive(_5); // scope 1 at $DIR/lower_array_len.rs:+2:9: +2:12
+ _5 = &raw const (*_2); // scope 1 at $SRC_DIR/core/src/ptr/mod.rs:LL:COL
+ StorageLive(_6); // scope 2 at $DIR/lower_array_len.rs:+3:5: +3:27
+ StorageLive(_7); // scope 2 at $DIR/lower_array_len.rs:+3:14: +3:19
+ _7 = &(*_5); // scope 3 at $DIR/lower_array_len.rs:+3:14: +3:19
+ _6 = &(*_7); // scope 2 at $DIR/lower_array_len.rs:+3:5: +3:27
+- _0 = Len((*_6)); // scope 2 at $DIR/lower_array_len.rs:+3:5: +3:27
++ _0 = const N; // scope 2 at $DIR/lower_array_len.rs:+3:5: +3:27
+ goto -> bb1; // scope 2 at $DIR/lower_array_len.rs:+3:5: +3:27
+ }
+
+ bb1: {
+ StorageDead(_6); // scope 2 at $DIR/lower_array_len.rs:+3:26: +3:27
+ StorageDead(_5); // scope 1 at $DIR/lower_array_len.rs:+4:1: +4:2
+ StorageDead(_2); // scope 0 at $DIR/lower_array_len.rs:+4:1: +4:2
+ StorageDead(_7); // scope 0 at $DIR/lower_array_len.rs:+4:1: +4:2
+ return; // scope 0 at $DIR/lower_array_len.rs:+4:2: +4:2
+ }
+ }
+
diff --git a/tests/mir-opt/lower_array_len.array_len_reborrow.NormalizeArrayLen.diff b/tests/mir-opt/lower_array_len.array_len_reborrow.NormalizeArrayLen.diff
new file mode 100644
index 000000000..8bdd2ede6
--- /dev/null
+++ b/tests/mir-opt/lower_array_len.array_len_reborrow.NormalizeArrayLen.diff
@@ -0,0 +1,44 @@
+- // MIR for `array_len_reborrow` before NormalizeArrayLen
++ // MIR for `array_len_reborrow` after NormalizeArrayLen
+
+ fn array_len_reborrow(_1: [u8; N]) -> usize {
+ debug arr => _1; // in scope 0 at $DIR/lower_array_len.rs:+0:43: +0:50
+ let mut _0: usize; // return place in scope 0 at $DIR/lower_array_len.rs:+0:64: +0:69
+ let _2: &mut [u8]; // in scope 0 at $DIR/lower_array_len.rs:+1:9: +1:12
+ let mut _3: &mut [u8; N]; // in scope 0 at $DIR/lower_array_len.rs:+1:25: +1:33
+ let mut _4: &mut [u8; N]; // in scope 0 at $DIR/lower_array_len.rs:+1:25: +1:33
+ let mut _6: &[u8]; // in scope 0 at $DIR/lower_array_len.rs:+3:5: +3:14
+ scope 1 {
+ debug arr => _2; // in scope 1 at $DIR/lower_array_len.rs:+1:9: +1:12
+ let _5: &[u8]; // in scope 1 at $DIR/lower_array_len.rs:+2:9: +2:12
+ scope 2 {
+ debug arr => _5; // in scope 2 at $DIR/lower_array_len.rs:+2:9: +2:12
+ }
+ }
+
+ bb0: {
+ StorageLive(_2); // scope 0 at $DIR/lower_array_len.rs:+1:9: +1:12
+ StorageLive(_3); // scope 0 at $DIR/lower_array_len.rs:+1:25: +1:33
+ StorageLive(_4); // scope 0 at $DIR/lower_array_len.rs:+1:25: +1:33
+ _4 = &mut _1; // scope 0 at $DIR/lower_array_len.rs:+1:25: +1:33
+ _3 = &mut (*_4); // scope 0 at $DIR/lower_array_len.rs:+1:25: +1:33
+ _2 = move _3 as &mut [u8] (Pointer(Unsize)); // scope 0 at $DIR/lower_array_len.rs:+1:25: +1:33
+ StorageDead(_3); // scope 0 at $DIR/lower_array_len.rs:+1:32: +1:33
+ StorageDead(_4); // scope 0 at $DIR/lower_array_len.rs:+1:33: +1:34
+ StorageLive(_5); // scope 1 at $DIR/lower_array_len.rs:+2:9: +2:12
+ _5 = &(*_2); // scope 1 at $DIR/lower_array_len.rs:+2:15: +2:20
+ StorageLive(_6); // scope 2 at $DIR/lower_array_len.rs:+3:5: +3:14
+ _6 = &(*_5); // scope 2 at $DIR/lower_array_len.rs:+3:5: +3:14
+- _0 = Len((*_6)); // scope 2 at $DIR/lower_array_len.rs:+3:5: +3:14
++ _0 = const N; // scope 2 at $DIR/lower_array_len.rs:+3:5: +3:14
+ goto -> bb1; // scope 2 at $DIR/lower_array_len.rs:+3:5: +3:14
+ }
+
+ bb1: {
+ StorageDead(_6); // scope 2 at $DIR/lower_array_len.rs:+3:13: +3:14
+ StorageDead(_5); // scope 1 at $DIR/lower_array_len.rs:+4:1: +4:2
+ StorageDead(_2); // scope 0 at $DIR/lower_array_len.rs:+4:1: +4:2
+ return; // scope 0 at $DIR/lower_array_len.rs:+4:2: +4:2
+ }
+ }
+
diff --git a/tests/mir-opt/lower_array_len.rs b/tests/mir-opt/lower_array_len.rs
index ea0224b21..972d46cb8 100644
--- a/tests/mir-opt/lower_array_len.rs
+++ b/tests/mir-opt/lower_array_len.rs
@@ -31,10 +31,26 @@ pub fn array_len_by_value<const N: usize>(arr: [u8; N]) -> usize {
arr.len()
}
+// EMIT_MIR lower_array_len.array_len_reborrow.NormalizeArrayLen.diff
+pub fn array_len_reborrow<const N: usize>(mut arr: [u8; N]) -> usize {
+ let arr: &mut [_] = &mut arr;
+ let arr = &*arr;
+ arr.len()
+}
+
+// EMIT_MIR lower_array_len.array_len_raw.NormalizeArrayLen.diff
+pub fn array_len_raw<const N: usize>(arr: [u8; N]) -> usize {
+ let arr: &[_] = &arr;
+ let arr = std::ptr::addr_of!(*arr);
+ unsafe { &*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]);
+ let _ = array_len_reborrow([0, 2]);
+ let _ = array_len_raw([0, 2]);
}
diff --git a/tests/mir-opt/lower_array_len_e2e.array_bound.PreCodegen.after.mir b/tests/mir-opt/lower_array_len_e2e.array_bound.PreCodegen.after.mir
deleted file mode 100644
index 701c2ad70..000000000
--- a/tests/mir-opt/lower_array_len_e2e.array_bound.PreCodegen.after.mir
+++ /dev/null
@@ -1,45 +0,0 @@
-// MIR for `array_bound` after PreCodegen
-
-fn array_bound(_1: usize, _2: &[u8; N]) -> u8 {
- debug index => _1; // in scope 0 at $DIR/lower_array_len_e2e.rs:+0:36: +0:41
- debug slice => _2; // in scope 0 at $DIR/lower_array_len_e2e.rs:+0:50: +0:55
- let mut _0: u8; // return place in scope 0 at $DIR/lower_array_len_e2e.rs:+0:70: +0:72
- let mut _3: bool; // in scope 0 at $DIR/lower_array_len_e2e.rs:+1:8: +1:27
- let mut _4: usize; // in scope 0 at $DIR/lower_array_len_e2e.rs:+1:8: +1:13
- let mut _5: usize; // in scope 0 at $DIR/lower_array_len_e2e.rs:+1:16: +1:27
- let mut _6: usize; // in scope 0 at $DIR/lower_array_len_e2e.rs:+2:9: +2:21
- let mut _7: bool; // in scope 0 at $DIR/lower_array_len_e2e.rs:+2:9: +2:21
-
- bb0: {
- StorageLive(_3); // scope 0 at $DIR/lower_array_len_e2e.rs:+1:8: +1:27
- StorageLive(_4); // scope 0 at $DIR/lower_array_len_e2e.rs:+1:8: +1:13
- _4 = _1; // scope 0 at $DIR/lower_array_len_e2e.rs:+1:8: +1:13
- StorageLive(_5); // scope 0 at $DIR/lower_array_len_e2e.rs:+1:16: +1:27
- _5 = const N; // scope 0 at $DIR/lower_array_len_e2e.rs:+1:16: +1:27
- _3 = Lt(move _4, move _5); // scope 0 at $DIR/lower_array_len_e2e.rs:+1:8: +1:27
- StorageDead(_5); // scope 0 at $DIR/lower_array_len_e2e.rs:+1:26: +1:27
- StorageDead(_4); // scope 0 at $DIR/lower_array_len_e2e.rs:+1:26: +1:27
- switchInt(move _3) -> [0: bb3, otherwise: bb1]; // scope 0 at $DIR/lower_array_len_e2e.rs:+1:8: +1:27
- }
-
- bb1: {
- _6 = const N; // scope 0 at $DIR/lower_array_len_e2e.rs:+2:9: +2:21
- _7 = Lt(_1, _6); // scope 0 at $DIR/lower_array_len_e2e.rs:+2:9: +2:21
- assert(move _7, "index out of bounds: the length is {} but the index is {}", move _6, _1) -> bb2; // scope 0 at $DIR/lower_array_len_e2e.rs:+2:9: +2:21
- }
-
- bb2: {
- _0 = (*_2)[_1]; // scope 0 at $DIR/lower_array_len_e2e.rs:+2:9: +2:21
- goto -> bb4; // scope 0 at $DIR/lower_array_len_e2e.rs:+1:5: +5:6
- }
-
- bb3: {
- _0 = const 42_u8; // scope 0 at $DIR/lower_array_len_e2e.rs:+4:9: +4:11
- goto -> bb4; // scope 0 at $DIR/lower_array_len_e2e.rs:+1:5: +5:6
- }
-
- bb4: {
- StorageDead(_3); // scope 0 at $DIR/lower_array_len_e2e.rs:+5:5: +5:6
- return; // scope 0 at $DIR/lower_array_len_e2e.rs:+6:2: +6:2
- }
-}
diff --git a/tests/mir-opt/lower_array_len_e2e.array_bound_mut.PreCodegen.after.mir b/tests/mir-opt/lower_array_len_e2e.array_bound_mut.PreCodegen.after.mir
deleted file mode 100644
index 0440cfce2..000000000
--- a/tests/mir-opt/lower_array_len_e2e.array_bound_mut.PreCodegen.after.mir
+++ /dev/null
@@ -1,58 +0,0 @@
-// MIR for `array_bound_mut` after PreCodegen
-
-fn array_bound_mut(_1: usize, _2: &mut [u8; N]) -> u8 {
- debug index => _1; // in scope 0 at $DIR/lower_array_len_e2e.rs:+0:40: +0:45
- debug slice => _2; // in scope 0 at $DIR/lower_array_len_e2e.rs:+0:54: +0:59
- let mut _0: u8; // return place in scope 0 at $DIR/lower_array_len_e2e.rs:+0:78: +0:80
- let mut _3: bool; // in scope 0 at $DIR/lower_array_len_e2e.rs:+1:8: +1:27
- let mut _4: usize; // in scope 0 at $DIR/lower_array_len_e2e.rs:+1:8: +1:13
- let mut _5: usize; // in scope 0 at $DIR/lower_array_len_e2e.rs:+1:16: +1:27
- let mut _6: usize; // in scope 0 at $DIR/lower_array_len_e2e.rs:+2:9: +2:21
- let mut _7: bool; // in scope 0 at $DIR/lower_array_len_e2e.rs:+2:9: +2:21
- let _8: usize; // in scope 0 at $DIR/lower_array_len_e2e.rs:+4:15: +4:16
- let mut _9: usize; // in scope 0 at $DIR/lower_array_len_e2e.rs:+4:9: +4:17
- let mut _10: bool; // in scope 0 at $DIR/lower_array_len_e2e.rs:+4:9: +4:17
-
- bb0: {
- StorageLive(_3); // scope 0 at $DIR/lower_array_len_e2e.rs:+1:8: +1:27
- StorageLive(_4); // scope 0 at $DIR/lower_array_len_e2e.rs:+1:8: +1:13
- _4 = _1; // scope 0 at $DIR/lower_array_len_e2e.rs:+1:8: +1:13
- StorageLive(_5); // scope 0 at $DIR/lower_array_len_e2e.rs:+1:16: +1:27
- _5 = const N; // scope 0 at $DIR/lower_array_len_e2e.rs:+1:16: +1:27
- _3 = Lt(move _4, move _5); // scope 0 at $DIR/lower_array_len_e2e.rs:+1:8: +1:27
- StorageDead(_5); // scope 0 at $DIR/lower_array_len_e2e.rs:+1:26: +1:27
- StorageDead(_4); // scope 0 at $DIR/lower_array_len_e2e.rs:+1:26: +1:27
- switchInt(move _3) -> [0: bb3, otherwise: bb1]; // scope 0 at $DIR/lower_array_len_e2e.rs:+1:8: +1:27
- }
-
- bb1: {
- _6 = const N; // scope 0 at $DIR/lower_array_len_e2e.rs:+2:9: +2:21
- _7 = Lt(_1, _6); // scope 0 at $DIR/lower_array_len_e2e.rs:+2:9: +2:21
- assert(move _7, "index out of bounds: the length is {} but the index is {}", move _6, _1) -> bb2; // scope 0 at $DIR/lower_array_len_e2e.rs:+2:9: +2:21
- }
-
- bb2: {
- _0 = (*_2)[_1]; // scope 0 at $DIR/lower_array_len_e2e.rs:+2:9: +2:21
- goto -> bb5; // scope 0 at $DIR/lower_array_len_e2e.rs:+1:5: +7:6
- }
-
- bb3: {
- StorageLive(_8); // scope 0 at $DIR/lower_array_len_e2e.rs:+4:15: +4:16
- _8 = const 0_usize; // scope 0 at $DIR/lower_array_len_e2e.rs:+4:15: +4:16
- _9 = const N; // scope 0 at $DIR/lower_array_len_e2e.rs:+4:9: +4:17
- _10 = Lt(const 0_usize, _9); // scope 0 at $DIR/lower_array_len_e2e.rs:+4:9: +4:17
- assert(move _10, "index out of bounds: the length is {} but the index is {}", move _9, const 0_usize) -> bb4; // scope 0 at $DIR/lower_array_len_e2e.rs:+4:9: +4:17
- }
-
- bb4: {
- (*_2)[_8] = const 42_u8; // scope 0 at $DIR/lower_array_len_e2e.rs:+4:9: +4:22
- StorageDead(_8); // scope 0 at $DIR/lower_array_len_e2e.rs:+4:22: +4:23
- _0 = const 42_u8; // scope 0 at $DIR/lower_array_len_e2e.rs:+6:9: +6:11
- goto -> bb5; // scope 0 at $DIR/lower_array_len_e2e.rs:+1:5: +7:6
- }
-
- bb5: {
- StorageDead(_3); // scope 0 at $DIR/lower_array_len_e2e.rs:+7:5: +7:6
- return; // scope 0 at $DIR/lower_array_len_e2e.rs:+8:2: +8:2
- }
-}
diff --git a/tests/mir-opt/lower_array_len_e2e.array_len.PreCodegen.after.mir b/tests/mir-opt/lower_array_len_e2e.array_len.PreCodegen.after.mir
deleted file mode 100644
index 4b19f6795..000000000
--- a/tests/mir-opt/lower_array_len_e2e.array_len.PreCodegen.after.mir
+++ /dev/null
@@ -1,11 +0,0 @@
-// MIR for `array_len` after PreCodegen
-
-fn array_len(_1: &[u8; N]) -> usize {
- debug arr => _1; // in scope 0 at $DIR/lower_array_len_e2e.rs:+0:34: +0:37
- let mut _0: usize; // return place in scope 0 at $DIR/lower_array_len_e2e.rs:+0:52: +0:57
-
- bb0: {
- _0 = const N; // scope 0 at $DIR/lower_array_len_e2e.rs:+1:5: +1:14
- return; // scope 0 at $DIR/lower_array_len_e2e.rs:+2:2: +2:2
- }
-}
diff --git a/tests/mir-opt/lower_array_len_e2e.array_len_by_value.PreCodegen.after.mir b/tests/mir-opt/lower_array_len_e2e.array_len_by_value.PreCodegen.after.mir
deleted file mode 100644
index 4dc0ba9a2..000000000
--- a/tests/mir-opt/lower_array_len_e2e.array_len_by_value.PreCodegen.after.mir
+++ /dev/null
@@ -1,11 +0,0 @@
-// MIR for `array_len_by_value` after PreCodegen
-
-fn array_len_by_value(_1: [u8; N]) -> usize {
- debug arr => _1; // in scope 0 at $DIR/lower_array_len_e2e.rs:+0:43: +0:46
- let mut _0: usize; // return place in scope 0 at $DIR/lower_array_len_e2e.rs:+0:60: +0:65
-
- bb0: {
- _0 = const N; // scope 0 at $DIR/lower_array_len_e2e.rs:+1:5: +1:14
- return; // scope 0 at $DIR/lower_array_len_e2e.rs:+2:2: +2:2
- }
-}
diff --git a/tests/mir-opt/lower_array_len_e2e.rs b/tests/mir-opt/lower_array_len_e2e.rs
deleted file mode 100644
index d8e4e521e..000000000
--- a/tests/mir-opt/lower_array_len_e2e.rs
+++ /dev/null
@@ -1,39 +0,0 @@
-// compile-flags: -Z mir-opt-level=4 -Zunsound-mir-opts
-
-// EMIT_MIR lower_array_len_e2e.array_bound.PreCodegen.after.mir
-pub fn array_bound<const N: usize>(index: usize, slice: &[u8; N]) -> u8 {
- if index < slice.len() {
- slice[index]
- } else {
- 42
- }
-}
-
-// EMIT_MIR lower_array_len_e2e.array_bound_mut.PreCodegen.after.mir
-pub fn array_bound_mut<const N: usize>(index: usize, slice: &mut [u8; N]) -> u8 {
- if index < slice.len() {
- slice[index]
- } else {
- slice[0] = 42;
-
- 42
- }
-}
-
-// EMIT_MIR lower_array_len_e2e.array_len.PreCodegen.after.mir
-pub fn array_len<const N: usize>(arr: &[u8; N]) -> usize {
- arr.len()
-}
-
-// EMIT_MIR lower_array_len_e2e.array_len_by_value.PreCodegen.after.mir
-pub fn array_len_by_value<const N: usize>(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/tests/mir-opt/lower_intrinsics.f_copy_nonoverlapping.LowerIntrinsics.diff b/tests/mir-opt/lower_intrinsics.f_copy_nonoverlapping.LowerIntrinsics.diff
index ec15fd1ef..5c972a00e 100644
--- a/tests/mir-opt/lower_intrinsics.f_copy_nonoverlapping.LowerIntrinsics.diff
+++ b/tests/mir-opt/lower_intrinsics.f_copy_nonoverlapping.LowerIntrinsics.diff
@@ -25,9 +25,9 @@
bb0: {
StorageLive(_1); // scope 0 at $DIR/lower_intrinsics.rs:+1:9: +1:12
- Deinit(_1); // scope 0 at $DIR/lower_intrinsics.rs:+1:15: +1:17
+ _1 = (); // scope 0 at $DIR/lower_intrinsics.rs:+1:15: +1:17
StorageLive(_2); // scope 1 at $DIR/lower_intrinsics.rs:+2:9: +2:16
- Deinit(_2); // scope 1 at $DIR/lower_intrinsics.rs:+2:19: +2:21
+ _2 = (); // scope 1 at $DIR/lower_intrinsics.rs:+2:19: +2:21
StorageLive(_3); // scope 3 at $DIR/lower_intrinsics.rs:+4:9: +4:95
StorageLive(_4); // scope 3 at $DIR/lower_intrinsics.rs:+4:29: +4:59
StorageLive(_5); // scope 3 at $DIR/lower_intrinsics.rs:+4:29: +4:45
diff --git a/tests/mir-opt/lower_intrinsics.rs b/tests/mir-opt/lower_intrinsics.rs
index 66dae0e46..7147be43c 100644
--- a/tests/mir-opt/lower_intrinsics.rs
+++ b/tests/mir-opt/lower_intrinsics.rs
@@ -72,3 +72,10 @@ pub fn assume() {
std::intrinsics::assume(true);
}
}
+
+// EMIT_MIR lower_intrinsics.with_overflow.LowerIntrinsics.diff
+pub fn with_overflow(a: i32, b: i32) {
+ let _x = core::intrinsics::add_with_overflow(a, b);
+ let _y = core::intrinsics::sub_with_overflow(a, b);
+ let _z = core::intrinsics::mul_with_overflow(a, b);
+}
diff --git a/tests/mir-opt/lower_intrinsics.with_overflow.LowerIntrinsics.diff b/tests/mir-opt/lower_intrinsics.with_overflow.LowerIntrinsics.diff
new file mode 100644
index 000000000..9870a70de
--- /dev/null
+++ b/tests/mir-opt/lower_intrinsics.with_overflow.LowerIntrinsics.diff
@@ -0,0 +1,83 @@
+- // MIR for `with_overflow` before LowerIntrinsics
++ // MIR for `with_overflow` after LowerIntrinsics
+
+ fn with_overflow(_1: i32, _2: i32) -> () {
+ debug a => _1; // in scope 0 at $DIR/lower_intrinsics.rs:+0:22: +0:23
+ debug b => _2; // in scope 0 at $DIR/lower_intrinsics.rs:+0:30: +0:31
+ let mut _0: (); // return place in scope 0 at $DIR/lower_intrinsics.rs:+0:38: +0:38
+ let _3: (i32, bool); // in scope 0 at $DIR/lower_intrinsics.rs:+1:9: +1:11
+ let mut _4: i32; // in scope 0 at $DIR/lower_intrinsics.rs:+1:50: +1:51
+ let mut _5: i32; // in scope 0 at $DIR/lower_intrinsics.rs:+1:53: +1:54
+ let mut _7: i32; // in scope 0 at $DIR/lower_intrinsics.rs:+2:50: +2:51
+ let mut _8: i32; // in scope 0 at $DIR/lower_intrinsics.rs:+2:53: +2:54
+ let mut _10: i32; // in scope 0 at $DIR/lower_intrinsics.rs:+3:50: +3:51
+ let mut _11: i32; // in scope 0 at $DIR/lower_intrinsics.rs:+3:53: +3:54
+ scope 1 {
+ debug _x => _3; // in scope 1 at $DIR/lower_intrinsics.rs:+1:9: +1:11
+ let _6: (i32, bool); // in scope 1 at $DIR/lower_intrinsics.rs:+2:9: +2:11
+ scope 2 {
+ debug _y => _6; // in scope 2 at $DIR/lower_intrinsics.rs:+2:9: +2:11
+ let _9: (i32, bool); // in scope 2 at $DIR/lower_intrinsics.rs:+3:9: +3:11
+ scope 3 {
+ debug _z => _9; // in scope 3 at $DIR/lower_intrinsics.rs:+3:9: +3:11
+ }
+ }
+ }
+
+ bb0: {
+ StorageLive(_3); // scope 0 at $DIR/lower_intrinsics.rs:+1:9: +1:11
+ StorageLive(_4); // scope 0 at $DIR/lower_intrinsics.rs:+1:50: +1:51
+ _4 = _1; // scope 0 at $DIR/lower_intrinsics.rs:+1:50: +1:51
+ StorageLive(_5); // scope 0 at $DIR/lower_intrinsics.rs:+1:53: +1:54
+ _5 = _2; // scope 0 at $DIR/lower_intrinsics.rs:+1:53: +1:54
+- _3 = add_with_overflow::<i32>(move _4, move _5) -> bb1; // scope 0 at $DIR/lower_intrinsics.rs:+1:14: +1:55
+- // mir::Constant
+- // + span: $DIR/lower_intrinsics.rs:78:14: 78:49
+- // + literal: Const { ty: extern "rust-intrinsic" fn(i32, i32) -> (i32, bool) {add_with_overflow::<i32>}, val: Value(<ZST>) }
++ _3 = CheckedAdd(move _4, move _5); // scope 0 at $DIR/lower_intrinsics.rs:+1:14: +1:55
++ goto -> bb1; // scope 0 at $DIR/lower_intrinsics.rs:+1:14: +1:55
+ }
+
+ bb1: {
+ StorageDead(_5); // scope 0 at $DIR/lower_intrinsics.rs:+1:54: +1:55
+ StorageDead(_4); // scope 0 at $DIR/lower_intrinsics.rs:+1:54: +1:55
+ StorageLive(_6); // scope 1 at $DIR/lower_intrinsics.rs:+2:9: +2:11
+ StorageLive(_7); // scope 1 at $DIR/lower_intrinsics.rs:+2:50: +2:51
+ _7 = _1; // scope 1 at $DIR/lower_intrinsics.rs:+2:50: +2:51
+ StorageLive(_8); // scope 1 at $DIR/lower_intrinsics.rs:+2:53: +2:54
+ _8 = _2; // scope 1 at $DIR/lower_intrinsics.rs:+2:53: +2:54
+- _6 = sub_with_overflow::<i32>(move _7, move _8) -> bb2; // scope 1 at $DIR/lower_intrinsics.rs:+2:14: +2:55
+- // mir::Constant
+- // + span: $DIR/lower_intrinsics.rs:79:14: 79:49
+- // + literal: Const { ty: extern "rust-intrinsic" fn(i32, i32) -> (i32, bool) {sub_with_overflow::<i32>}, val: Value(<ZST>) }
++ _6 = CheckedSub(move _7, move _8); // scope 1 at $DIR/lower_intrinsics.rs:+2:14: +2:55
++ goto -> bb2; // scope 1 at $DIR/lower_intrinsics.rs:+2:14: +2:55
+ }
+
+ bb2: {
+ StorageDead(_8); // scope 1 at $DIR/lower_intrinsics.rs:+2:54: +2:55
+ StorageDead(_7); // scope 1 at $DIR/lower_intrinsics.rs:+2:54: +2:55
+ StorageLive(_9); // scope 2 at $DIR/lower_intrinsics.rs:+3:9: +3:11
+ StorageLive(_10); // scope 2 at $DIR/lower_intrinsics.rs:+3:50: +3:51
+ _10 = _1; // scope 2 at $DIR/lower_intrinsics.rs:+3:50: +3:51
+ StorageLive(_11); // scope 2 at $DIR/lower_intrinsics.rs:+3:53: +3:54
+ _11 = _2; // scope 2 at $DIR/lower_intrinsics.rs:+3:53: +3:54
+- _9 = mul_with_overflow::<i32>(move _10, move _11) -> bb3; // scope 2 at $DIR/lower_intrinsics.rs:+3:14: +3:55
+- // mir::Constant
+- // + span: $DIR/lower_intrinsics.rs:80:14: 80:49
+- // + literal: Const { ty: extern "rust-intrinsic" fn(i32, i32) -> (i32, bool) {mul_with_overflow::<i32>}, val: Value(<ZST>) }
++ _9 = CheckedMul(move _10, move _11); // scope 2 at $DIR/lower_intrinsics.rs:+3:14: +3:55
++ goto -> bb3; // scope 2 at $DIR/lower_intrinsics.rs:+3:14: +3:55
+ }
+
+ bb3: {
+ StorageDead(_11); // scope 2 at $DIR/lower_intrinsics.rs:+3:54: +3:55
+ StorageDead(_10); // scope 2 at $DIR/lower_intrinsics.rs:+3:54: +3:55
+ _0 = const (); // scope 0 at $DIR/lower_intrinsics.rs:+0:38: +4:2
+ StorageDead(_9); // scope 2 at $DIR/lower_intrinsics.rs:+4:1: +4:2
+ StorageDead(_6); // scope 1 at $DIR/lower_intrinsics.rs:+4:1: +4:2
+ StorageDead(_3); // scope 0 at $DIR/lower_intrinsics.rs:+4:1: +4:2
+ return; // scope 0 at $DIR/lower_intrinsics.rs:+4:2: +4:2
+ }
+ }
+
diff --git a/tests/mir-opt/matches_reduce_branches.bar.MatchBranchSimplification.diff b/tests/mir-opt/matches_reduce_branches.bar.MatchBranchSimplification.diff
index be91b0bfe..92f8d4e14 100644
--- a/tests/mir-opt/matches_reduce_branches.bar.MatchBranchSimplification.diff
+++ b/tests/mir-opt/matches_reduce_branches.bar.MatchBranchSimplification.diff
@@ -41,7 +41,7 @@
- _3 = const false; // scope 4 at $DIR/matches_reduce_branches.rs:+16:13: +16:22
- _4 = const false; // scope 4 at $DIR/matches_reduce_branches.rs:+17:13: +17:22
- _5 = const true; // scope 4 at $DIR/matches_reduce_branches.rs:+18:13: +18:21
-- Deinit(_6); // scope 4 at $DIR/matches_reduce_branches.rs:+19:13: +19:15
+- _6 = (); // scope 4 at $DIR/matches_reduce_branches.rs:+19:13: +19:15
- goto -> bb3; // scope 4 at $DIR/matches_reduce_branches.rs:+19:13: +19:15
- }
-
@@ -54,7 +54,7 @@
+ _3 = Eq(_11, const 7_i32); // scope 4 at $DIR/matches_reduce_branches.rs:+9:13: +9:21
_4 = const false; // scope 4 at $DIR/matches_reduce_branches.rs:+10:13: +10:22
_5 = const true; // scope 4 at $DIR/matches_reduce_branches.rs:+11:13: +11:21
- Deinit(_6); // scope 4 at $DIR/matches_reduce_branches.rs:+12:13: +12:15
+ _6 = (); // scope 4 at $DIR/matches_reduce_branches.rs:+12:13: +12:15
- goto -> bb3; // scope 4 at $DIR/matches_reduce_branches.rs:+12:13: +12:15
- }
-
@@ -69,11 +69,7 @@
_9 = _4; // scope 4 at $DIR/matches_reduce_branches.rs:+23:12: +23:13
StorageLive(_10); // scope 4 at $DIR/matches_reduce_branches.rs:+23:15: +23:16
_10 = _5; // scope 4 at $DIR/matches_reduce_branches.rs:+23:15: +23:16
- Deinit(_0); // scope 4 at $DIR/matches_reduce_branches.rs:+23:5: +23:17
- (_0.0: bool) = move _7; // scope 4 at $DIR/matches_reduce_branches.rs:+23:5: +23:17
- (_0.1: bool) = move _8; // scope 4 at $DIR/matches_reduce_branches.rs:+23:5: +23:17
- (_0.2: bool) = move _9; // scope 4 at $DIR/matches_reduce_branches.rs:+23:5: +23:17
- (_0.3: bool) = move _10; // scope 4 at $DIR/matches_reduce_branches.rs:+23:5: +23:17
+ _0 = (move _7, move _8, move _9, move _10); // scope 4 at $DIR/matches_reduce_branches.rs:+23:5: +23:17
StorageDead(_10); // scope 4 at $DIR/matches_reduce_branches.rs:+23:16: +23:17
StorageDead(_9); // scope 4 at $DIR/matches_reduce_branches.rs:+23:16: +23:17
StorageDead(_8); // scope 4 at $DIR/matches_reduce_branches.rs:+23:16: +23:17
diff --git a/tests/mir-opt/matches_reduce_branches.foo.MatchBranchSimplification.diff b/tests/mir-opt/matches_reduce_branches.foo.MatchBranchSimplification.diff
index aa8092ece..0580f7334 100644
--- a/tests/mir-opt/matches_reduce_branches.foo.MatchBranchSimplification.diff
+++ b/tests/mir-opt/matches_reduce_branches.foo.MatchBranchSimplification.diff
@@ -34,7 +34,7 @@
- }
-
- bb4: {
- Deinit(_0); // scope 0 at $DIR/matches_reduce_branches.rs:+2:9: +2:11
+ _0 = (); // scope 0 at $DIR/matches_reduce_branches.rs:+2:9: +2:11
- goto -> bb6; // scope 0 at $DIR/matches_reduce_branches.rs:+1:5: +3:6
+ goto -> bb3; // scope 0 at $DIR/matches_reduce_branches.rs:+1:5: +3:6
}
diff --git a/tests/mir-opt/matches_reduce_branches.match_nested_if.MatchBranchSimplification.diff b/tests/mir-opt/matches_reduce_branches.match_nested_if.MatchBranchSimplification.diff
index 193104dd3..20e8ef2f7 100644
--- a/tests/mir-opt/matches_reduce_branches.match_nested_if.MatchBranchSimplification.diff
+++ b/tests/mir-opt/matches_reduce_branches.match_nested_if.MatchBranchSimplification.diff
@@ -20,7 +20,7 @@
bb0: {
StorageLive(_1); // scope 0 at $DIR/matches_reduce_branches.rs:+1:9: +1:12
StorageLive(_2); // scope 0 at $DIR/matches_reduce_branches.rs:+1:21: +1:23
- Deinit(_2); // scope 0 at $DIR/matches_reduce_branches.rs:+1:21: +1:23
+ _2 = (); // scope 0 at $DIR/matches_reduce_branches.rs:+1:21: +1:23
StorageLive(_3); // scope 0 at $DIR/matches_reduce_branches.rs:+2:15: +6:10
StorageLive(_4); // scope 0 at $DIR/matches_reduce_branches.rs:+2:18: +2:76
StorageLive(_5); // scope 0 at $DIR/matches_reduce_branches.rs:+2:21: +2:52
diff --git a/tests/mir-opt/packed_struct_drop_aligned.main.SimplifyCfg-elaborate-drops.after.mir b/tests/mir-opt/packed_struct_drop_aligned.main.SimplifyCfg-elaborate-drops.after.mir
index e52253486..210f178a0 100644
--- a/tests/mir-opt/packed_struct_drop_aligned.main.SimplifyCfg-elaborate-drops.after.mir
+++ b/tests/mir-opt/packed_struct_drop_aligned.main.SimplifyCfg-elaborate-drops.after.mir
@@ -16,20 +16,15 @@ fn main() -> () {
StorageLive(_1); // scope 0 at $DIR/packed_struct_drop_aligned.rs:+1:9: +1:14
StorageLive(_2); // scope 0 at $DIR/packed_struct_drop_aligned.rs:+1:24: +1:42
StorageLive(_3); // scope 0 at $DIR/packed_struct_drop_aligned.rs:+1:32: +1:41
- Deinit(_3); // scope 0 at $DIR/packed_struct_drop_aligned.rs:+1:32: +1:41
- (_3.0: usize) = const 0_usize; // scope 0 at $DIR/packed_struct_drop_aligned.rs:+1:32: +1:41
- Deinit(_2); // scope 0 at $DIR/packed_struct_drop_aligned.rs:+1:24: +1:42
- (_2.0: Droppy) = move _3; // scope 0 at $DIR/packed_struct_drop_aligned.rs:+1:24: +1:42
+ _3 = Droppy(const 0_usize); // scope 0 at $DIR/packed_struct_drop_aligned.rs:+1:32: +1:41
+ _2 = Aligned(move _3); // scope 0 at $DIR/packed_struct_drop_aligned.rs:+1:24: +1:42
StorageDead(_3); // scope 0 at $DIR/packed_struct_drop_aligned.rs:+1:41: +1:42
- Deinit(_1); // scope 0 at $DIR/packed_struct_drop_aligned.rs:+1:17: +1:43
- (_1.0: Aligned) = move _2; // scope 0 at $DIR/packed_struct_drop_aligned.rs:+1:17: +1:43
+ _1 = Packed(move _2); // scope 0 at $DIR/packed_struct_drop_aligned.rs:+1:17: +1:43
StorageDead(_2); // scope 0 at $DIR/packed_struct_drop_aligned.rs:+1:42: +1:43
StorageLive(_4); // scope 1 at $DIR/packed_struct_drop_aligned.rs:+2:11: +2:29
StorageLive(_5); // scope 1 at $DIR/packed_struct_drop_aligned.rs:+2:19: +2:28
- Deinit(_5); // scope 1 at $DIR/packed_struct_drop_aligned.rs:+2:19: +2:28
- (_5.0: usize) = const 0_usize; // scope 1 at $DIR/packed_struct_drop_aligned.rs:+2:19: +2:28
- Deinit(_4); // scope 1 at $DIR/packed_struct_drop_aligned.rs:+2:11: +2:29
- (_4.0: Droppy) = move _5; // scope 1 at $DIR/packed_struct_drop_aligned.rs:+2:11: +2:29
+ _5 = Droppy(const 0_usize); // scope 1 at $DIR/packed_struct_drop_aligned.rs:+2:19: +2:28
+ _4 = Aligned(move _5); // scope 1 at $DIR/packed_struct_drop_aligned.rs:+2:11: +2:29
StorageDead(_5); // scope 1 at $DIR/packed_struct_drop_aligned.rs:+2:28: +2:29
StorageLive(_6); // scope 1 at $DIR/packed_struct_drop_aligned.rs:+2:5: +2:8
_6 = move (_1.0: Aligned); // scope 1 at $DIR/packed_struct_drop_aligned.rs:+2:5: +2:8
diff --git a/tests/mir-opt/remove_storage_markers.main.RemoveStorageMarkers.diff b/tests/mir-opt/remove_storage_markers.main.RemoveStorageMarkers.diff
index ed1d0b87f..a8dd91efc 100644
--- a/tests/mir-opt/remove_storage_markers.main.RemoveStorageMarkers.diff
+++ b/tests/mir-opt/remove_storage_markers.main.RemoveStorageMarkers.diff
@@ -31,9 +31,7 @@
_1 = const 0_i32; // scope 0 at $DIR/remove_storage_markers.rs:+1:19: +1:20
- StorageLive(_2); // scope 1 at $DIR/remove_storage_markers.rs:+2:14: +2:19
- StorageLive(_3); // scope 1 at $DIR/remove_storage_markers.rs:+2:14: +2:19
- Deinit(_3); // scope 1 at $DIR/remove_storage_markers.rs:+2:14: +2:19
- (_3.0: i32) = const 0_i32; // scope 1 at $DIR/remove_storage_markers.rs:+2:14: +2:19
- (_3.1: i32) = const 10_i32; // scope 1 at $DIR/remove_storage_markers.rs:+2:14: +2:19
+ _3 = std::ops::Range::<i32> { start: const 0_i32, end: const 10_i32 }; // scope 1 at $DIR/remove_storage_markers.rs:+2:14: +2:19
_2 = <std::ops::Range<i32> as IntoIterator>::into_iter(move _3) -> bb1; // scope 1 at $DIR/remove_storage_markers.rs:+2:14: +2:19
// mir::Constant
// + span: $DIR/remove_storage_markers.rs:10:14: 10:19
diff --git a/tests/mir-opt/remove_zsts.get_union.PreCodegen.after.mir b/tests/mir-opt/remove_zsts.get_union.PreCodegen.after.mir
index 12e914e25..af34bc5ed 100644
--- a/tests/mir-opt/remove_zsts.get_union.PreCodegen.after.mir
+++ b/tests/mir-opt/remove_zsts.get_union.PreCodegen.after.mir
@@ -2,9 +2,12 @@
fn get_union() -> Foo {
let mut _0: Foo; // return place in scope 0 at $DIR/remove_zsts.rs:+0:19: +0:22
+ let mut _1: (); // in scope 0 at $DIR/remove_zsts.rs:+1:14: +1:16
bb0: {
- Deinit(_0); // scope 0 at $DIR/remove_zsts.rs:+1:5: +1:18
+ StorageLive(_1); // scope 0 at $DIR/remove_zsts.rs:+1:14: +1:16
+ _0 = Foo { x: move _1 }; // scope 0 at $DIR/remove_zsts.rs:+1:5: +1:18
+ StorageDead(_1); // scope 0 at $DIR/remove_zsts.rs:+1:17: +1:18
return; // scope 0 at $DIR/remove_zsts.rs:+2:2: +2:2
}
}
diff --git a/tests/mir-opt/remove_zsts.get_union.RemoveZsts.diff b/tests/mir-opt/remove_zsts.get_union.RemoveZsts.diff
index 169b7b105..0af29b2ba 100644
--- a/tests/mir-opt/remove_zsts.get_union.RemoveZsts.diff
+++ b/tests/mir-opt/remove_zsts.get_union.RemoveZsts.diff
@@ -7,11 +7,9 @@
bb0: {
StorageLive(_1); // scope 0 at $DIR/remove_zsts.rs:+1:14: +1:16
-- Deinit(_1); // scope 0 at $DIR/remove_zsts.rs:+1:14: +1:16
+- _1 = (); // scope 0 at $DIR/remove_zsts.rs:+1:14: +1:16
+ nop; // scope 0 at $DIR/remove_zsts.rs:+1:14: +1:16
- Deinit(_0); // scope 0 at $DIR/remove_zsts.rs:+1:5: +1:18
-- (_0.0: ()) = move _1; // scope 0 at $DIR/remove_zsts.rs:+1:5: +1:18
-+ nop; // scope 0 at $DIR/remove_zsts.rs:+1:5: +1:18
+ _0 = Foo { x: move _1 }; // scope 0 at $DIR/remove_zsts.rs:+1:5: +1:18
StorageDead(_1); // scope 0 at $DIR/remove_zsts.rs:+1:17: +1:18
return; // scope 0 at $DIR/remove_zsts.rs:+2:2: +2:2
}
diff --git a/tests/mir-opt/retag.array_casts.SimplifyCfg-elaborate-drops.after.mir b/tests/mir-opt/retag.array_casts.SimplifyCfg-elaborate-drops.after.mir
index 19b726e74..3b479710b 100644
--- a/tests/mir-opt/retag.array_casts.SimplifyCfg-elaborate-drops.after.mir
+++ b/tests/mir-opt/retag.array_casts.SimplifyCfg-elaborate-drops.after.mir
@@ -122,9 +122,7 @@ fn array_casts() -> () {
// + literal: Const { ty: &usize, val: Unevaluated(array_casts, [], Some(promoted[0])) }
Retag(_35); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
_18 = &(*_35); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- Deinit(_13); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- (_13.0: &usize) = move _14; // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- (_13.1: &usize) = move _18; // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+ _13 = (move _14, move _18); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
Retag(_13); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
StorageDead(_18); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
StorageDead(_14); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
@@ -150,8 +148,7 @@ fn array_casts() -> () {
bb3: {
StorageLive(_27); // scope 7 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- Deinit(_27); // scope 7 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- discriminant(_27) = 0; // scope 7 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+ _27 = core::panicking::AssertKind::Eq; // scope 7 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
StorageLive(_28); // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
StorageLive(_29); // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
_29 = move _27; // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
@@ -164,8 +161,7 @@ fn array_casts() -> () {
_33 = &(*_21); // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
_32 = &(*_33); // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
StorageLive(_34); // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- Deinit(_34); // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- discriminant(_34) = 0; // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+ _34 = Option::<Arguments<'_>>::None; // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
Retag(_34); // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
_28 = core::panicking::assert_failed::<usize, usize>(move _29, move _30, move _32, move _34); // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
// mir::Constant
diff --git a/tests/mir-opt/retag.main.SimplifyCfg-elaborate-drops.after.mir b/tests/mir-opt/retag.main.SimplifyCfg-elaborate-drops.after.mir
index b853e4505..d7b6d64b6 100644
--- a/tests/mir-opt/retag.main.SimplifyCfg-elaborate-drops.after.mir
+++ b/tests/mir-opt/retag.main.SimplifyCfg-elaborate-drops.after.mir
@@ -62,8 +62,7 @@ fn main() -> () {
StorageLive(_3); // scope 1 at $DIR/retag.rs:+3:13: +3:14
StorageLive(_4); // scope 1 at $DIR/retag.rs:+3:17: +3:36
StorageLive(_5); // scope 1 at $DIR/retag.rs:+3:17: +3:24
- Deinit(_5); // scope 1 at $DIR/retag.rs:+3:17: +3:24
- (_5.0: i32) = const 0_i32; // scope 1 at $DIR/retag.rs:+3:17: +3:24
+ _5 = Test(const 0_i32); // scope 1 at $DIR/retag.rs:+3:17: +3:24
_4 = &_5; // scope 1 at $DIR/retag.rs:+3:17: +3:36
StorageLive(_6); // scope 1 at $DIR/retag.rs:+3:29: +3:35
StorageLive(_7); // scope 1 at $DIR/retag.rs:+3:29: +3:35
@@ -107,7 +106,14 @@ fn main() -> () {
StorageDead(_2); // scope 1 at $DIR/retag.rs:+8:5: +8:6
StorageLive(_13); // scope 1 at $DIR/retag.rs:+11:9: +11:10
StorageLive(_14); // scope 1 at $DIR/retag.rs:+11:31: +14:6
- Deinit(_14); // scope 1 at $DIR/retag.rs:+11:31: +14:6
+ _14 = [closure@main::{closure#0}]; // scope 1 at $DIR/retag.rs:+11:31: +14:6
+ // closure
+ // + def_id: DefId(0:14 ~ retag[4622]::main::{closure#0})
+ // + substs: [
+ // i8,
+ // for<'a> extern "rust-call" fn((&'a i32,)) -> &'a i32,
+ // (),
+ // ]
Retag(_14); // scope 1 at $DIR/retag.rs:+11:31: +14:6
_13 = move _14 as for<'a> fn(&'a i32) -> &'a i32 (Pointer(ClosureFnPointer(Normal))); // scope 1 at $DIR/retag.rs:+11:31: +14:6
StorageDead(_14); // scope 1 at $DIR/retag.rs:+11:47: +11:48
@@ -129,8 +135,7 @@ fn main() -> () {
StorageLive(_19); // scope 7 at $DIR/retag.rs:+18:5: +18:24
StorageLive(_20); // scope 7 at $DIR/retag.rs:+18:5: +18:24
StorageLive(_21); // scope 7 at $DIR/retag.rs:+18:5: +18:12
- Deinit(_21); // scope 7 at $DIR/retag.rs:+18:5: +18:12
- (_21.0: i32) = const 0_i32; // scope 7 at $DIR/retag.rs:+18:5: +18:12
+ _21 = Test(const 0_i32); // scope 7 at $DIR/retag.rs:+18:5: +18:12
_20 = &_21; // scope 7 at $DIR/retag.rs:+18:5: +18:24
StorageLive(_22); // scope 7 at $DIR/retag.rs:+18:21: +18:23
StorageLive(_23); // scope 7 at $DIR/retag.rs:+18:21: +18:23
diff --git a/tests/mir-opt/separate_const_switch.identity.SeparateConstSwitch.diff b/tests/mir-opt/separate_const_switch.identity.SeparateConstSwitch.diff
index e57544e09..cfcd43093 100644
--- a/tests/mir-opt/separate_const_switch.identity.SeparateConstSwitch.diff
+++ b/tests/mir-opt/separate_const_switch.identity.SeparateConstSwitch.diff
@@ -12,18 +12,18 @@
let mut _7: !; // in scope 0 at $DIR/separate_const_switch.rs:+1:9: +1:10
let mut _8: std::result::Result<std::convert::Infallible, i32>; // in scope 0 at $DIR/separate_const_switch.rs:+1:9: +1:10
let _9: i32; // in scope 0 at $DIR/separate_const_switch.rs:+1:8: +1:10
+ let mut _16: i32; // in scope 0 at $SRC_DIR/core/src/result.rs:LL:COL
scope 1 {
debug residual => _6; // in scope 1 at $DIR/separate_const_switch.rs:+1:9: +1:10
scope 2 {
scope 8 (inlined #[track_caller] <Result<i32, i32> as FromResidual<Result<Infallible, i32>>>::from_residual) { // at $DIR/separate_const_switch.rs:25:8: 25:10
debug residual => _8; // in scope 8 at $SRC_DIR/core/src/result.rs:LL:COL
- let _16: i32; // in scope 8 at $SRC_DIR/core/src/result.rs:LL:COL
- let mut _17: i32; // in scope 8 at $SRC_DIR/core/src/result.rs:LL:COL
- let mut _18: i32; // in scope 8 at $SRC_DIR/core/src/result.rs:LL:COL
+ let _14: i32; // in scope 8 at $SRC_DIR/core/src/result.rs:LL:COL
+ let mut _15: i32; // in scope 8 at $SRC_DIR/core/src/result.rs:LL:COL
scope 9 {
- debug e => _16; // in scope 9 at $SRC_DIR/core/src/result.rs:LL:COL
+ debug e => _14; // in scope 9 at $SRC_DIR/core/src/result.rs:LL:COL
scope 10 (inlined <i32 as From<i32>>::from) { // at $SRC_DIR/core/src/result.rs:LL:COL
- debug t => _18; // in scope 10 at $SRC_DIR/core/src/convert/mod.rs:LL:COL
+ debug t => _16; // in scope 10 at $SRC_DIR/core/src/convert/mod.rs:LL:COL
}
}
}
@@ -38,15 +38,13 @@
debug self => _4; // in scope 5 at $SRC_DIR/core/src/result.rs:LL:COL
let mut _10: isize; // in scope 5 at $SRC_DIR/core/src/result.rs:LL:COL
let _11: i32; // in scope 5 at $SRC_DIR/core/src/result.rs:LL:COL
- let mut _12: i32; // in scope 5 at $SRC_DIR/core/src/result.rs:LL:COL
- let _13: i32; // in scope 5 at $SRC_DIR/core/src/result.rs:LL:COL
- let mut _14: std::result::Result<std::convert::Infallible, i32>; // in scope 5 at $SRC_DIR/core/src/result.rs:LL:COL
- let mut _15: i32; // in scope 5 at $SRC_DIR/core/src/result.rs:LL:COL
+ let _12: i32; // in scope 5 at $SRC_DIR/core/src/result.rs:LL:COL
+ let mut _13: std::result::Result<std::convert::Infallible, i32>; // in scope 5 at $SRC_DIR/core/src/result.rs:LL:COL
scope 6 {
debug v => _11; // in scope 6 at $SRC_DIR/core/src/result.rs:LL:COL
}
scope 7 {
- debug e => _13; // in scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
+ debug e => _12; // in scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
}
}
@@ -55,53 +53,50 @@
StorageLive(_3); // scope 0 at $DIR/separate_const_switch.rs:+1:8: +1:10
StorageLive(_4); // scope 0 at $DIR/separate_const_switch.rs:+1:8: +1:9
_4 = _1; // scope 0 at $DIR/separate_const_switch.rs:+1:8: +1:9
+ StorageLive(_11); // scope 0 at $DIR/separate_const_switch.rs:+1:8: +1:10
+ StorageLive(_12); // scope 0 at $DIR/separate_const_switch.rs:+1:8: +1:10
_10 = discriminant(_4); // scope 5 at $SRC_DIR/core/src/result.rs:LL:COL
-- switchInt(move _10) -> [0: bb7, 1: bb5, otherwise: bb6]; // scope 5 at $SRC_DIR/core/src/result.rs:LL:COL
-+ switchInt(move _10) -> [0: bb6, 1: bb4, otherwise: bb5]; // scope 5 at $SRC_DIR/core/src/result.rs:LL:COL
+ switchInt(move _10) -> [0: bb7, 1: bb5, otherwise: bb6]; // scope 5 at $SRC_DIR/core/src/result.rs:LL:COL
}
bb1: {
-- StorageDead(_4); // scope 0 at $DIR/separate_const_switch.rs:+1:9: +1:10
-- _5 = discriminant(_3); // scope 0 at $DIR/separate_const_switch.rs:+1:8: +1:10
-- switchInt(move _5) -> [0: bb2, 1: bb4, otherwise: bb3]; // scope 0 at $DIR/separate_const_switch.rs:+1:8: +1:10
-- }
--
-- bb2: {
+ StorageDead(_12); // scope 0 at $DIR/separate_const_switch.rs:+1:8: +1:10
+ StorageDead(_11); // scope 0 at $DIR/separate_const_switch.rs:+1:8: +1:10
+ StorageDead(_4); // scope 0 at $DIR/separate_const_switch.rs:+1:9: +1:10
+ _5 = discriminant(_3); // scope 0 at $DIR/separate_const_switch.rs:+1:8: +1:10
+ switchInt(move _5) -> [0: bb2, 1: bb4, otherwise: bb3]; // scope 0 at $DIR/separate_const_switch.rs:+1:8: +1:10
+ }
+
+ bb2: {
StorageLive(_9); // scope 0 at $DIR/separate_const_switch.rs:+1:8: +1:10
_9 = ((_3 as Continue).0: i32); // scope 0 at $DIR/separate_const_switch.rs:+1:8: +1:10
_2 = _9; // scope 4 at $DIR/separate_const_switch.rs:+1:8: +1:10
StorageDead(_9); // scope 0 at $DIR/separate_const_switch.rs:+1:9: +1:10
- Deinit(_0); // scope 0 at $DIR/separate_const_switch.rs:+1:5: +1:11
- ((_0 as Ok).0: i32) = move _2; // scope 0 at $DIR/separate_const_switch.rs:+1:5: +1:11
- discriminant(_0) = 0; // scope 0 at $DIR/separate_const_switch.rs:+1:5: +1:11
+ _0 = Result::<i32, i32>::Ok(move _2); // scope 0 at $DIR/separate_const_switch.rs:+1:5: +1:11
StorageDead(_2); // scope 0 at $DIR/separate_const_switch.rs:+1:10: +1:11
StorageDead(_3); // scope 0 at $DIR/separate_const_switch.rs:+2:1: +2:2
return; // scope 0 at $DIR/separate_const_switch.rs:+2:2: +2:2
}
-- bb3: {
-+ bb2: {
+ bb3: {
unreachable; // scope 0 at $DIR/separate_const_switch.rs:+1:8: +1:10
}
-- bb4: {
-+ bb3: {
+ bb4: {
StorageLive(_6); // scope 0 at $DIR/separate_const_switch.rs:+1:9: +1:10
_6 = ((_3 as Break).0: std::result::Result<std::convert::Infallible, i32>); // scope 0 at $DIR/separate_const_switch.rs:+1:9: +1:10
StorageLive(_8); // scope 2 at $DIR/separate_const_switch.rs:+1:9: +1:10
_8 = _6; // scope 2 at $DIR/separate_const_switch.rs:+1:9: +1:10
- StorageLive(_16); // scope 8 at $SRC_DIR/core/src/result.rs:LL:COL
- _16 = move ((_8 as Err).0: i32); // scope 8 at $SRC_DIR/core/src/result.rs:LL:COL
- StorageLive(_17); // scope 9 at $SRC_DIR/core/src/result.rs:LL:COL
- StorageLive(_18); // scope 9 at $SRC_DIR/core/src/result.rs:LL:COL
- _18 = move _16; // scope 9 at $SRC_DIR/core/src/result.rs:LL:COL
- _17 = move _18; // scope 10 at $SRC_DIR/core/src/convert/mod.rs:LL:COL
- StorageDead(_18); // scope 9 at $SRC_DIR/core/src/result.rs:LL:COL
- Deinit(_0); // scope 9 at $SRC_DIR/core/src/result.rs:LL:COL
- ((_0 as Err).0: i32) = move _17; // scope 9 at $SRC_DIR/core/src/result.rs:LL:COL
- discriminant(_0) = 1; // scope 9 at $SRC_DIR/core/src/result.rs:LL:COL
- StorageDead(_17); // scope 9 at $SRC_DIR/core/src/result.rs:LL:COL
- StorageDead(_16); // scope 8 at $SRC_DIR/core/src/result.rs:LL:COL
+ StorageLive(_14); // scope 2 at $DIR/separate_const_switch.rs:+1:8: +1:10
+ _14 = move ((_8 as Err).0: i32); // scope 8 at $SRC_DIR/core/src/result.rs:LL:COL
+ StorageLive(_15); // scope 9 at $SRC_DIR/core/src/result.rs:LL:COL
+ StorageLive(_16); // scope 9 at $SRC_DIR/core/src/result.rs:LL:COL
+ _16 = move _14; // scope 9 at $SRC_DIR/core/src/result.rs:LL:COL
+ _15 = move _16; // scope 10 at $SRC_DIR/core/src/convert/mod.rs:LL:COL
+ StorageDead(_16); // scope 9 at $SRC_DIR/core/src/result.rs:LL:COL
+ _0 = Result::<i32, i32>::Err(move _15); // scope 9 at $SRC_DIR/core/src/result.rs:LL:COL
+ StorageDead(_15); // scope 9 at $SRC_DIR/core/src/result.rs:LL:COL
+ StorageDead(_14); // scope 2 at $DIR/separate_const_switch.rs:+1:8: +1:10
StorageDead(_8); // scope 2 at $DIR/separate_const_switch.rs:+1:9: +1:10
StorageDead(_6); // scope 0 at $DIR/separate_const_switch.rs:+1:9: +1:10
StorageDead(_2); // scope 0 at $DIR/separate_const_switch.rs:+1:10: +1:11
@@ -109,48 +104,23 @@
return; // scope 0 at $DIR/separate_const_switch.rs:+2:2: +2:2
}
-- bb5: {
-+ bb4: {
- StorageLive(_13); // scope 5 at $SRC_DIR/core/src/result.rs:LL:COL
- _13 = move ((_4 as Err).0: i32); // scope 5 at $SRC_DIR/core/src/result.rs:LL:COL
- StorageLive(_14); // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
- StorageLive(_15); // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
- _15 = move _13; // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
- Deinit(_14); // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
- ((_14 as Err).0: i32) = move _15; // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
- discriminant(_14) = 1; // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
- StorageDead(_15); // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
- Deinit(_3); // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
- ((_3 as Break).0: std::result::Result<std::convert::Infallible, i32>) = move _14; // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
- discriminant(_3) = 1; // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
- StorageDead(_14); // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
- StorageDead(_13); // scope 5 at $SRC_DIR/core/src/result.rs:LL:COL
-- goto -> bb1; // scope 5 at $SRC_DIR/core/src/result.rs:LL:COL
-+ StorageDead(_4); // scope 0 at $DIR/separate_const_switch.rs:+1:9: +1:10
-+ _5 = discriminant(_3); // scope 0 at $DIR/separate_const_switch.rs:+1:8: +1:10
-+ switchInt(move _5) -> [0: bb1, 1: bb3, otherwise: bb2]; // scope 0 at $DIR/separate_const_switch.rs:+1:8: +1:10
+ bb5: {
+ _12 = move ((_4 as Err).0: i32); // scope 5 at $SRC_DIR/core/src/result.rs:LL:COL
+ StorageLive(_13); // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
+ _13 = Result::<Infallible, i32>::Err(move _12); // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
+ _3 = ControlFlow::<Result<Infallible, i32>, i32>::Break(move _13); // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
+ StorageDead(_13); // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
+ goto -> bb1; // scope 5 at $SRC_DIR/core/src/result.rs:LL:COL
}
-- bb6: {
-+ bb5: {
+ bb6: {
unreachable; // scope 5 at $SRC_DIR/core/src/result.rs:LL:COL
}
-- bb7: {
-+ bb6: {
- StorageLive(_11); // scope 5 at $SRC_DIR/core/src/result.rs:LL:COL
+ bb7: {
_11 = move ((_4 as Ok).0: i32); // scope 5 at $SRC_DIR/core/src/result.rs:LL:COL
- StorageLive(_12); // scope 6 at $SRC_DIR/core/src/result.rs:LL:COL
- _12 = move _11; // scope 6 at $SRC_DIR/core/src/result.rs:LL:COL
- Deinit(_3); // scope 6 at $SRC_DIR/core/src/result.rs:LL:COL
- ((_3 as Continue).0: i32) = move _12; // scope 6 at $SRC_DIR/core/src/result.rs:LL:COL
- discriminant(_3) = 0; // scope 6 at $SRC_DIR/core/src/result.rs:LL:COL
- StorageDead(_12); // scope 6 at $SRC_DIR/core/src/result.rs:LL:COL
- StorageDead(_11); // scope 5 at $SRC_DIR/core/src/result.rs:LL:COL
-- goto -> bb1; // scope 5 at $SRC_DIR/core/src/result.rs:LL:COL
-+ StorageDead(_4); // scope 0 at $DIR/separate_const_switch.rs:+1:9: +1:10
-+ _5 = discriminant(_3); // scope 0 at $DIR/separate_const_switch.rs:+1:8: +1:10
-+ switchInt(move _5) -> [0: bb1, 1: bb3, otherwise: bb2]; // scope 0 at $DIR/separate_const_switch.rs:+1:8: +1:10
+ _3 = ControlFlow::<Result<Infallible, i32>, i32>::Continue(move _11); // scope 6 at $SRC_DIR/core/src/result.rs:LL:COL
+ goto -> bb1; // scope 5 at $SRC_DIR/core/src/result.rs:LL:COL
}
}
diff --git a/tests/mir-opt/separate_const_switch.too_complex.SeparateConstSwitch.diff b/tests/mir-opt/separate_const_switch.too_complex.SeparateConstSwitch.diff
index 8cc0c6a18..3c7e9dc61 100644
--- a/tests/mir-opt/separate_const_switch.too_complex.SeparateConstSwitch.diff
+++ b/tests/mir-opt/separate_const_switch.too_complex.SeparateConstSwitch.diff
@@ -38,14 +38,10 @@
_6 = ((_1 as Err).0: usize); // scope 0 at $DIR/separate_const_switch.rs:+8:17: +8:18
StorageLive(_7); // scope 2 at $DIR/separate_const_switch.rs:+8:42: +8:43
_7 = _6; // scope 2 at $DIR/separate_const_switch.rs:+8:42: +8:43
- Deinit(_2); // scope 2 at $DIR/separate_const_switch.rs:+8:23: +8:44
- ((_2 as Break).0: usize) = move _7; // scope 2 at $DIR/separate_const_switch.rs:+8:23: +8:44
- discriminant(_2) = 1; // scope 2 at $DIR/separate_const_switch.rs:+8:23: +8:44
+ _2 = ControlFlow::<usize, i32>::Break(move _7); // scope 2 at $DIR/separate_const_switch.rs:+8:23: +8:44
StorageDead(_7); // scope 2 at $DIR/separate_const_switch.rs:+8:43: +8:44
StorageDead(_6); // scope 0 at $DIR/separate_const_switch.rs:+8:43: +8:44
-- goto -> bb4; // scope 0 at $DIR/separate_const_switch.rs:+8:43: +8:44
-+ _8 = discriminant(_2); // scope 0 at $DIR/separate_const_switch.rs:+5:11: +10:6
-+ switchInt(move _8) -> [0: bb6, 1: bb4, otherwise: bb5]; // scope 0 at $DIR/separate_const_switch.rs:+5:5: +10:6
+ goto -> bb4; // scope 0 at $DIR/separate_const_switch.rs:+8:43: +8:44
}
bb2: {
@@ -57,53 +53,41 @@
_4 = ((_1 as Ok).0: i32); // scope 0 at $DIR/separate_const_switch.rs:+7:16: +7:17
StorageLive(_5); // scope 1 at $DIR/separate_const_switch.rs:+7:44: +7:45
_5 = _4; // scope 1 at $DIR/separate_const_switch.rs:+7:44: +7:45
- Deinit(_2); // scope 1 at $DIR/separate_const_switch.rs:+7:22: +7:46
- ((_2 as Continue).0: i32) = move _5; // scope 1 at $DIR/separate_const_switch.rs:+7:22: +7:46
- discriminant(_2) = 0; // scope 1 at $DIR/separate_const_switch.rs:+7:22: +7:46
+ _2 = ControlFlow::<usize, i32>::Continue(move _5); // scope 1 at $DIR/separate_const_switch.rs:+7:22: +7:46
StorageDead(_5); // scope 1 at $DIR/separate_const_switch.rs:+7:45: +7:46
StorageDead(_4); // scope 0 at $DIR/separate_const_switch.rs:+7:45: +7:46
-- goto -> bb4; // scope 0 at $DIR/separate_const_switch.rs:+7:45: +7:46
-- }
--
-- bb4: {
+ goto -> bb4; // scope 0 at $DIR/separate_const_switch.rs:+7:45: +7:46
+ }
+
+ bb4: {
_8 = discriminant(_2); // scope 0 at $DIR/separate_const_switch.rs:+5:11: +10:6
-- switchInt(move _8) -> [0: bb7, 1: bb5, otherwise: bb6]; // scope 0 at $DIR/separate_const_switch.rs:+5:5: +10:6
-+ switchInt(move _8) -> [0: bb6, 1: bb4, otherwise: bb5]; // scope 0 at $DIR/separate_const_switch.rs:+5:5: +10:6
+ switchInt(move _8) -> [0: bb7, 1: bb5, otherwise: bb6]; // scope 0 at $DIR/separate_const_switch.rs:+5:5: +10:6
}
-- bb5: {
-+ bb4: {
+ bb5: {
StorageLive(_11); // scope 0 at $DIR/separate_const_switch.rs:+12:28: +12:29
_11 = ((_2 as Break).0: usize); // scope 0 at $DIR/separate_const_switch.rs:+12:28: +12:29
- Deinit(_0); // scope 4 at $DIR/separate_const_switch.rs:+12:34: +12:38
- discriminant(_0) = 0; // scope 4 at $DIR/separate_const_switch.rs:+12:34: +12:38
+ _0 = Option::<i32>::None; // scope 4 at $DIR/separate_const_switch.rs:+12:34: +12:38
StorageDead(_11); // scope 0 at $DIR/separate_const_switch.rs:+12:37: +12:38
-- goto -> bb8; // scope 0 at $DIR/separate_const_switch.rs:+12:37: +12:38
-+ goto -> bb7; // scope 0 at $DIR/separate_const_switch.rs:+12:37: +12:38
+ goto -> bb8; // scope 0 at $DIR/separate_const_switch.rs:+12:37: +12:38
}
-- bb6: {
-+ bb5: {
+ bb6: {
unreachable; // scope 0 at $DIR/separate_const_switch.rs:+5:11: +10:6
}
-- bb7: {
-+ bb6: {
+ bb7: {
StorageLive(_9); // scope 0 at $DIR/separate_const_switch.rs:+11:31: +11:32
_9 = ((_2 as Continue).0: i32); // scope 0 at $DIR/separate_const_switch.rs:+11:31: +11:32
StorageLive(_10); // scope 3 at $DIR/separate_const_switch.rs:+11:42: +11:43
_10 = _9; // scope 3 at $DIR/separate_const_switch.rs:+11:42: +11:43
- Deinit(_0); // scope 3 at $DIR/separate_const_switch.rs:+11:37: +11:44
- ((_0 as Some).0: i32) = move _10; // scope 3 at $DIR/separate_const_switch.rs:+11:37: +11:44
- discriminant(_0) = 1; // scope 3 at $DIR/separate_const_switch.rs:+11:37: +11:44
+ _0 = Option::<i32>::Some(move _10); // scope 3 at $DIR/separate_const_switch.rs:+11:37: +11:44
StorageDead(_10); // scope 3 at $DIR/separate_const_switch.rs:+11:43: +11:44
StorageDead(_9); // scope 0 at $DIR/separate_const_switch.rs:+11:43: +11:44
-- goto -> bb8; // scope 0 at $DIR/separate_const_switch.rs:+11:43: +11:44
-+ goto -> bb7; // scope 0 at $DIR/separate_const_switch.rs:+11:43: +11:44
+ goto -> bb8; // scope 0 at $DIR/separate_const_switch.rs:+11:43: +11:44
}
-- bb8: {
-+ bb7: {
+ bb8: {
StorageDead(_2); // scope 0 at $DIR/separate_const_switch.rs:+14:1: +14:2
return; // scope 0 at $DIR/separate_const_switch.rs:+14:2: +14:2
}
diff --git a/tests/mir-opt/simple_option_map_e2e.ezmap.PreCodegen.after.mir b/tests/mir-opt/simple_option_map_e2e.ezmap.PreCodegen.after.mir
index 916f99049..66ba4df76 100644
--- a/tests/mir-opt/simple_option_map_e2e.ezmap.PreCodegen.after.mir
+++ b/tests/mir-opt/simple_option_map_e2e.ezmap.PreCodegen.after.mir
@@ -8,12 +8,12 @@ fn ezmap(_1: Option<i32>) -> Option<i32> {
debug slf => _1; // in scope 1 at $DIR/simple_option_map_e2e.rs:2:17: 2:20
debug f => _2; // in scope 1 at $DIR/simple_option_map_e2e.rs:2:33: 2:34
let mut _3: isize; // in scope 1 at $DIR/simple_option_map_e2e.rs:7:9: 7:16
- let mut _4: i32; // in scope 1 at $DIR/simple_option_map_e2e.rs:7:25: 7:29
+ let _4: i32; // in scope 1 at $DIR/simple_option_map_e2e.rs:7:14: 7:15
let mut _5: i32; // in scope 1 at $DIR/simple_option_map_e2e.rs:7:25: 7:29
scope 2 {
- debug x => _5; // in scope 2 at $DIR/simple_option_map_e2e.rs:7:14: 7:15
+ debug x => _4; // in scope 2 at $DIR/simple_option_map_e2e.rs:7:14: 7:15
scope 3 (inlined ezmap::{closure#0}) { // at $DIR/simple_option_map_e2e.rs:7:25: 7:29
- debug n => _5; // in scope 3 at $DIR/simple_option_map_e2e.rs:+1:13: +1:14
+ debug n => _4; // in scope 3 at $DIR/simple_option_map_e2e.rs:+1:13: +1:14
}
}
}
@@ -25,8 +25,7 @@ fn ezmap(_1: Option<i32>) -> Option<i32> {
}
bb1: {
- Deinit(_0); // scope 1 at $DIR/simple_option_map_e2e.rs:8:17: 8:21
- discriminant(_0) = 0; // scope 1 at $DIR/simple_option_map_e2e.rs:8:17: 8:21
+ _0 = Option::<i32>::None; // scope 1 at $DIR/simple_option_map_e2e.rs:8:17: 8:21
goto -> bb4; // scope 1 at $DIR/simple_option_map_e2e.rs:8:17: 8:21
}
@@ -35,13 +34,11 @@ fn ezmap(_1: Option<i32>) -> Option<i32> {
}
bb3: {
- _5 = move ((_1 as Some).0: i32); // scope 1 at $DIR/simple_option_map_e2e.rs:7:14: 7:15
- StorageLive(_4); // scope 2 at $DIR/simple_option_map_e2e.rs:7:25: 7:29
- _4 = Add(move _5, const 1_i32); // scope 3 at $DIR/simple_option_map_e2e.rs:+1:16: +1:21
- Deinit(_0); // scope 2 at $DIR/simple_option_map_e2e.rs:7:20: 7:30
- ((_0 as Some).0: i32) = move _4; // scope 2 at $DIR/simple_option_map_e2e.rs:7:20: 7:30
- discriminant(_0) = 1; // scope 2 at $DIR/simple_option_map_e2e.rs:7:20: 7:30
- StorageDead(_4); // scope 2 at $DIR/simple_option_map_e2e.rs:7:29: 7:30
+ _4 = ((_1 as Some).0: i32); // scope 1 at $DIR/simple_option_map_e2e.rs:7:14: 7:15
+ StorageLive(_5); // scope 2 at $DIR/simple_option_map_e2e.rs:7:25: 7:29
+ _5 = Add(_4, const 1_i32); // scope 3 at $DIR/simple_option_map_e2e.rs:+1:16: +1:21
+ _0 = Option::<i32>::Some(move _5); // scope 2 at $DIR/simple_option_map_e2e.rs:7:20: 7:30
+ StorageDead(_5); // scope 2 at $DIR/simple_option_map_e2e.rs:7:29: 7:30
goto -> bb4; // scope 1 at $DIR/simple_option_map_e2e.rs:10:1: 10:2
}
diff --git a/tests/mir-opt/simplify_locals.d1.SimplifyLocals-before-const-prop.diff b/tests/mir-opt/simplify_locals.d1.SimplifyLocals-before-const-prop.diff
index 981738030..946595e32 100644
--- a/tests/mir-opt/simplify_locals.d1.SimplifyLocals-before-const-prop.diff
+++ b/tests/mir-opt/simplify_locals.d1.SimplifyLocals-before-const-prop.diff
@@ -9,8 +9,7 @@
bb0: {
- StorageLive(_1); // scope 0 at $DIR/simplify_locals.rs:+2:13: +2:17
-- Deinit(_1); // scope 0 at $DIR/simplify_locals.rs:+2:13: +2:17
-- discriminant(_1) = 0; // scope 0 at $DIR/simplify_locals.rs:+2:13: +2:17
+- _1 = E::A; // scope 0 at $DIR/simplify_locals.rs:+2:13: +2:17
- StorageDead(_1); // scope 0 at $DIR/simplify_locals.rs:+2:17: +2:18
_0 = const (); // scope 0 at $DIR/simplify_locals.rs:+0:9: +3:2
return; // scope 0 at $DIR/simplify_locals.rs:+3:2: +3:2
diff --git a/tests/mir-opt/simplify_locals.d2.SimplifyLocals-before-const-prop.diff b/tests/mir-opt/simplify_locals.d2.SimplifyLocals-before-const-prop.diff
index b152dc8cc..6a5dc56e2 100644
--- a/tests/mir-opt/simplify_locals.d2.SimplifyLocals-before-const-prop.diff
+++ b/tests/mir-opt/simplify_locals.d2.SimplifyLocals-before-const-prop.diff
@@ -9,15 +9,11 @@
bb0: {
- StorageLive(_1); // scope 0 at $DIR/simplify_locals.rs:+2:22: +2:26
-- Deinit(_1); // scope 0 at $DIR/simplify_locals.rs:+2:22: +2:26
-- discriminant(_1) = 1; // scope 0 at $DIR/simplify_locals.rs:+2:22: +2:26
+- _1 = E::B; // scope 0 at $DIR/simplify_locals.rs:+2:22: +2:26
- StorageLive(_2); // scope 0 at $DIR/simplify_locals.rs:+2:5: +2:17
- StorageLive(_3); // scope 0 at $DIR/simplify_locals.rs:+2:11: +2:15
-- Deinit(_3); // scope 0 at $DIR/simplify_locals.rs:+2:11: +2:15
-- discriminant(_3) = 0; // scope 0 at $DIR/simplify_locals.rs:+2:11: +2:15
-- Deinit(_2); // scope 0 at $DIR/simplify_locals.rs:+2:6: +2:16
-- (_2.0: i32) = const 10_i32; // scope 0 at $DIR/simplify_locals.rs:+2:6: +2:16
-- (_2.1: E) = move _3; // scope 0 at $DIR/simplify_locals.rs:+2:6: +2:16
+- _3 = E::A; // scope 0 at $DIR/simplify_locals.rs:+2:11: +2:15
+- _2 = (const 10_i32, move _3); // scope 0 at $DIR/simplify_locals.rs:+2:6: +2:16
- StorageDead(_3); // scope 0 at $DIR/simplify_locals.rs:+2:15: +2:16
- (_2.1: E) = move _1; // scope 0 at $DIR/simplify_locals.rs:+2:5: +2:26
- StorageDead(_1); // scope 0 at $DIR/simplify_locals.rs:+2:25: +2:26
diff --git a/tests/mir-opt/simplify_locals_fixedpoint.foo.SimplifyLocals-final.diff b/tests/mir-opt/simplify_locals_fixedpoint.foo.SimplifyLocals-final.diff
index f888c622d..f908e8dd0 100644
--- a/tests/mir-opt/simplify_locals_fixedpoint.foo.SimplifyLocals-final.diff
+++ b/tests/mir-opt/simplify_locals_fixedpoint.foo.SimplifyLocals-final.diff
@@ -18,14 +18,10 @@
bb0: {
StorageLive(_1); // scope 1 at $DIR/simplify_locals_fixedpoint.rs:+1:30: +1:69
StorageLive(_2); // scope 1 at $DIR/simplify_locals_fixedpoint.rs:+1:31: +1:49
- Deinit(_2); // scope 1 at $DIR/simplify_locals_fixedpoint.rs:+1:31: +1:49
- discriminant(_2) = 0; // scope 1 at $DIR/simplify_locals_fixedpoint.rs:+1:31: +1:49
+ _2 = Option::<u8>::None; // scope 1 at $DIR/simplify_locals_fixedpoint.rs:+1:31: +1:49
StorageLive(_3); // scope 1 at $DIR/simplify_locals_fixedpoint.rs:+1:51: +1:68
- Deinit(_3); // scope 1 at $DIR/simplify_locals_fixedpoint.rs:+1:51: +1:68
- discriminant(_3) = 0; // scope 1 at $DIR/simplify_locals_fixedpoint.rs:+1:51: +1:68
- Deinit(_1); // scope 1 at $DIR/simplify_locals_fixedpoint.rs:+1:30: +1:69
- (_1.0: std::option::Option<u8>) = move _2; // scope 1 at $DIR/simplify_locals_fixedpoint.rs:+1:30: +1:69
- (_1.1: std::option::Option<T>) = move _3; // scope 1 at $DIR/simplify_locals_fixedpoint.rs:+1:30: +1:69
+ _3 = Option::<T>::None; // scope 1 at $DIR/simplify_locals_fixedpoint.rs:+1:51: +1:68
+ _1 = (move _2, move _3); // scope 1 at $DIR/simplify_locals_fixedpoint.rs:+1:30: +1:69
StorageDead(_3); // scope 1 at $DIR/simplify_locals_fixedpoint.rs:+1:68: +1:69
StorageDead(_2); // scope 1 at $DIR/simplify_locals_fixedpoint.rs:+1:68: +1:69
_5 = discriminant((_1.0: std::option::Option<u8>)); // scope 1 at $DIR/simplify_locals_fixedpoint.rs:+1:12: +1:27
@@ -38,15 +34,10 @@
}
bb2: {
- StorageLive(_6); // scope 1 at $DIR/simplify_locals_fixedpoint.rs:+1:18: +1:19
_6 = (((_1.0: std::option::Option<u8>) as Some).0: u8); // scope 1 at $DIR/simplify_locals_fixedpoint.rs:+1:18: +1:19
- StorageLive(_7); // scope 1 at $DIR/simplify_locals_fixedpoint.rs:+2:12: +2:20
-- StorageLive(_8); // scope 1 at $DIR/simplify_locals_fixedpoint.rs:+2:12: +2:13
-- _8 = _6; // scope 1 at $DIR/simplify_locals_fixedpoint.rs:+2:12: +2:13
-- _7 = Gt(move _8, const 42_u8); // scope 1 at $DIR/simplify_locals_fixedpoint.rs:+2:12: +2:20
-- StorageDead(_8); // scope 1 at $DIR/simplify_locals_fixedpoint.rs:+2:19: +2:20
+- _7 = Gt(_6, const 42_u8); // scope 1 at $DIR/simplify_locals_fixedpoint.rs:+2:12: +2:20
- StorageDead(_7); // scope 1 at $DIR/simplify_locals_fixedpoint.rs:+4:9: +4:10
- StorageDead(_6); // scope 0 at $DIR/simplify_locals_fixedpoint.rs:+5:5: +5:6
goto -> bb3; // scope 0 at $DIR/simplify_locals_fixedpoint.rs:+1:5: +5:6
}
diff --git a/tests/mir-opt/simplify_locals_removes_unused_consts.main.SimplifyLocals-before-const-prop.diff b/tests/mir-opt/simplify_locals_removes_unused_consts.main.SimplifyLocals-before-const-prop.diff
index efb2b0961..0f8866f9c 100644
--- a/tests/mir-opt/simplify_locals_removes_unused_consts.main.SimplifyLocals-before-const-prop.diff
+++ b/tests/mir-opt/simplify_locals_removes_unused_consts.main.SimplifyLocals-before-const-prop.diff
@@ -28,36 +28,30 @@
bb0: {
- StorageLive(_1); // scope 0 at $DIR/simplify_locals_removes_unused_consts.rs:+1:20: +1:28
- StorageLive(_2); // scope 0 at $DIR/simplify_locals_removes_unused_consts.rs:+1:21: +1:23
-- Deinit(_2); // scope 0 at $DIR/simplify_locals_removes_unused_consts.rs:+1:21: +1:23
+- _2 = (); // scope 0 at $DIR/simplify_locals_removes_unused_consts.rs:+1:21: +1:23
- StorageLive(_3); // scope 0 at $DIR/simplify_locals_removes_unused_consts.rs:+1:25: +1:27
-- Deinit(_3); // scope 0 at $DIR/simplify_locals_removes_unused_consts.rs:+1:25: +1:27
-- Deinit(_1); // scope 0 at $DIR/simplify_locals_removes_unused_consts.rs:+1:20: +1:28
-- (_1.0: ()) = move _2; // scope 0 at $DIR/simplify_locals_removes_unused_consts.rs:+1:20: +1:28
-- (_1.1: ()) = move _3; // scope 0 at $DIR/simplify_locals_removes_unused_consts.rs:+1:20: +1:28
+- _3 = (); // scope 0 at $DIR/simplify_locals_removes_unused_consts.rs:+1:25: +1:27
+- _1 = (move _2, move _3); // scope 0 at $DIR/simplify_locals_removes_unused_consts.rs:+1:20: +1:28
- StorageDead(_3); // scope 0 at $DIR/simplify_locals_removes_unused_consts.rs:+1:27: +1:28
- StorageDead(_2); // scope 0 at $DIR/simplify_locals_removes_unused_consts.rs:+1:27: +1:28
- StorageDead(_1); // scope 0 at $DIR/simplify_locals_removes_unused_consts.rs:+1:28: +1:29
- StorageLive(_4); // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+2:5: +2:22
- StorageLive(_5); // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+2:13: +2:21
- StorageLive(_6); // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+2:14: +2:16
-- Deinit(_6); // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+2:14: +2:16
+- _6 = (); // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+2:14: +2:16
- StorageLive(_7); // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+2:18: +2:20
-- Deinit(_7); // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+2:18: +2:20
-- Deinit(_5); // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+2:13: +2:21
-- (_5.0: ()) = move _6; // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+2:13: +2:21
-- (_5.1: ()) = move _7; // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+2:13: +2:21
+- _7 = (); // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+2:18: +2:20
+- _5 = (move _6, move _7); // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+2:13: +2:21
- StorageDead(_7); // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+2:20: +2:21
- StorageDead(_6); // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+2:20: +2:21
- _4 = use_zst(move _5) -> bb1; // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+2:5: +2:22
+ StorageLive(_1); // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+2:5: +2:22
+ StorageLive(_2); // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+2:13: +2:21
+ StorageLive(_3); // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+2:14: +2:16
-+ Deinit(_3); // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+2:14: +2:16
++ _3 = (); // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+2:14: +2:16
+ StorageLive(_4); // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+2:18: +2:20
-+ Deinit(_4); // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+2:18: +2:20
-+ Deinit(_2); // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+2:13: +2:21
-+ (_2.0: ()) = move _3; // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+2:13: +2:21
-+ (_2.1: ()) = move _4; // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+2:13: +2:21
++ _4 = (); // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+2:18: +2:20
++ _2 = (move _3, move _4); // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+2:13: +2:21
+ StorageDead(_4); // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+2:20: +2:21
+ StorageDead(_3); // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+2:20: +2:21
+ _1 = use_zst(move _2) -> bb1; // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+2:5: +2:22
@@ -73,8 +67,7 @@
- StorageLive(_9); // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+4:12: +4:34
- StorageLive(_10); // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+4:12: +4:30
- StorageLive(_11); // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+4:12: +4:28
-- Deinit(_11); // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+4:12: +4:28
-- (_11.0: u8) = const 40_u8; // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+4:12: +4:28
+- _11 = Temp { x: const 40_u8 }; // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+4:12: +4:28
- _10 = (_11.0: u8); // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+4:12: +4:30
- _9 = Add(move _10, const 2_u8); // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+4:12: +4:34
- StorageDead(_10); // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+4:33: +4:34
@@ -85,8 +78,7 @@
+ StorageLive(_6); // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+4:12: +4:34
+ StorageLive(_7); // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+4:12: +4:30
+ StorageLive(_8); // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+4:12: +4:28
-+ Deinit(_8); // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+4:12: +4:28
-+ (_8.0: u8) = const 40_u8; // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+4:12: +4:28
++ _8 = Temp { x: const 40_u8 }; // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+4:12: +4:28
+ _7 = (_8.0: u8); // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+4:12: +4:30
+ _6 = Add(move _7, const 2_u8); // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+4:12: +4:34
+ StorageDead(_7); // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+4:33: +4:34
diff --git a/tests/mir-opt/simplify_locals_removes_unused_discriminant_reads.map.SimplifyLocals-before-const-prop.diff b/tests/mir-opt/simplify_locals_removes_unused_discriminant_reads.map.SimplifyLocals-before-const-prop.diff
index 027c983e6..3f9af31d8 100644
--- a/tests/mir-opt/simplify_locals_removes_unused_discriminant_reads.map.SimplifyLocals-before-const-prop.diff
+++ b/tests/mir-opt/simplify_locals_removes_unused_discriminant_reads.map.SimplifyLocals-before-const-prop.diff
@@ -26,9 +26,7 @@
_3 = move ((_1 as Some).0: std::boxed::Box<()>); // scope 0 at $DIR/simplify_locals_removes_unused_discriminant_reads.rs:+3:14: +3:15
StorageLive(_4); // scope 1 at $DIR/simplify_locals_removes_unused_discriminant_reads.rs:+3:25: +3:26
_4 = move _3; // scope 1 at $DIR/simplify_locals_removes_unused_discriminant_reads.rs:+3:25: +3:26
- Deinit(_0); // scope 1 at $DIR/simplify_locals_removes_unused_discriminant_reads.rs:+3:20: +3:27
- ((_0 as Some).0: std::boxed::Box<()>) = move _4; // scope 1 at $DIR/simplify_locals_removes_unused_discriminant_reads.rs:+3:20: +3:27
- discriminant(_0) = 1; // scope 1 at $DIR/simplify_locals_removes_unused_discriminant_reads.rs:+3:20: +3:27
+ _0 = Option::<Box<()>>::Some(move _4); // scope 1 at $DIR/simplify_locals_removes_unused_discriminant_reads.rs:+3:20: +3:27
StorageDead(_4); // scope 1 at $DIR/simplify_locals_removes_unused_discriminant_reads.rs:+3:26: +3:27
StorageDead(_3); // scope 0 at $DIR/simplify_locals_removes_unused_discriminant_reads.rs:+3:26: +3:27
goto -> bb4; // scope 0 at $DIR/simplify_locals_removes_unused_discriminant_reads.rs:+3:26: +3:27
@@ -39,8 +37,7 @@
}
bb3: {
- Deinit(_0); // scope 0 at $DIR/simplify_locals_removes_unused_discriminant_reads.rs:+2:17: +2:21
- discriminant(_0) = 0; // scope 0 at $DIR/simplify_locals_removes_unused_discriminant_reads.rs:+2:17: +2:21
+ _0 = Option::<Box<()>>::None; // scope 0 at $DIR/simplify_locals_removes_unused_discriminant_reads.rs:+2:17: +2:21
goto -> bb4; // scope 0 at $DIR/simplify_locals_removes_unused_discriminant_reads.rs:+2:17: +2:21
}
diff --git a/tests/mir-opt/simplify_match.main.ConstProp.diff b/tests/mir-opt/simplify_match.main.ConstProp.diff
index 70bfbf1b3..b700adfb1 100644
--- a/tests/mir-opt/simplify_match.main.ConstProp.diff
+++ b/tests/mir-opt/simplify_match.main.ConstProp.diff
@@ -10,13 +10,8 @@
}
bb0: {
- StorageLive(_1); // scope 0 at $DIR/simplify_match.rs:+1:11: +1:31
- StorageLive(_2); // scope 0 at $DIR/simplify_match.rs:+1:17: +1:18
_2 = const false; // scope 0 at $DIR/simplify_match.rs:+1:21: +1:26
-- _1 = _2; // scope 1 at $DIR/simplify_match.rs:+1:28: +1:29
-+ _1 = const false; // scope 1 at $DIR/simplify_match.rs:+1:28: +1:29
- StorageDead(_2); // scope 0 at $DIR/simplify_match.rs:+1:30: +1:31
-- switchInt(_1) -> [0: bb1, otherwise: bb2]; // scope 0 at $DIR/simplify_match.rs:+1:5: +1:31
+- switchInt(_2) -> [0: bb1, otherwise: bb2]; // scope 0 at $DIR/simplify_match.rs:+1:5: +1:31
+ switchInt(const false) -> [0: bb1, otherwise: bb2]; // scope 0 at $DIR/simplify_match.rs:+1:5: +1:31
}
@@ -32,7 +27,6 @@
}
bb3: {
- StorageDead(_1); // scope 0 at $DIR/simplify_match.rs:+5:1: +5:2
return; // scope 0 at $DIR/simplify_match.rs:+5:2: +5:2
}
}
diff --git a/tests/mir-opt/slice_filter.rs b/tests/mir-opt/slice_filter.rs
new file mode 100644
index 000000000..97c18af31
--- /dev/null
+++ b/tests/mir-opt/slice_filter.rs
@@ -0,0 +1,18 @@
+fn main() {
+ let input = vec![];
+ let _variant_a_result = variant_a(&input);
+ let _variant_b_result = variant_b(&input);
+}
+
+pub fn variant_a(input: &[(usize, usize, usize, usize)]) -> usize {
+ input.iter().filter(|(a, b, c, d)| a <= c && d <= b || c <= a && b <= d).count()
+}
+
+pub fn variant_b(input: &[(usize, usize, usize, usize)]) -> usize {
+ input.iter().filter(|&&(a, b, c, d)| a <= c && d <= b || c <= a && b <= d).count()
+}
+
+// EMIT_MIR slice_filter.variant_a-{closure#0}.CopyProp.diff
+// EMIT_MIR slice_filter.variant_a-{closure#0}.DestinationPropagation.diff
+// EMIT_MIR slice_filter.variant_b-{closure#0}.CopyProp.diff
+// EMIT_MIR slice_filter.variant_b-{closure#0}.DestinationPropagation.diff
diff --git a/tests/mir-opt/slice_filter.variant_a-{closure#0}.CopyProp.diff b/tests/mir-opt/slice_filter.variant_a-{closure#0}.CopyProp.diff
new file mode 100644
index 000000000..3bb0358ff
--- /dev/null
+++ b/tests/mir-opt/slice_filter.variant_a-{closure#0}.CopyProp.diff
@@ -0,0 +1,279 @@
+- // MIR for `variant_a::{closure#0}` before CopyProp
++ // MIR for `variant_a::{closure#0}` after CopyProp
+
+ fn variant_a::{closure#0}(_1: &mut [closure@$DIR/slice_filter.rs:8:25: 8:39], _2: &&(usize, usize, usize, usize)) -> bool {
+ let mut _0: bool; // return place in scope 0 at $DIR/slice_filter.rs:+0:40: +0:40
+ let _3: &usize; // in scope 0 at $DIR/slice_filter.rs:+0:27: +0:28
+ let _4: &usize; // in scope 0 at $DIR/slice_filter.rs:+0:30: +0:31
+ let _5: &usize; // in scope 0 at $DIR/slice_filter.rs:+0:33: +0:34
+ let _6: &usize; // in scope 0 at $DIR/slice_filter.rs:+0:36: +0:37
+ let mut _7: bool; // in scope 0 at $DIR/slice_filter.rs:+0:40: +0:56
+ let mut _8: bool; // in scope 0 at $DIR/slice_filter.rs:+0:40: +0:46
+ let mut _9: &&usize; // in scope 0 at $DIR/slice_filter.rs:+0:40: +0:41
+ let mut _10: &&usize; // in scope 0 at $DIR/slice_filter.rs:+0:45: +0:46
+ let _11: &usize; // in scope 0 at $DIR/slice_filter.rs:+0:45: +0:46
+ let mut _12: bool; // in scope 0 at $DIR/slice_filter.rs:+0:50: +0:56
+ let mut _13: &&usize; // in scope 0 at $DIR/slice_filter.rs:+0:50: +0:51
+ let mut _14: &&usize; // in scope 0 at $DIR/slice_filter.rs:+0:55: +0:56
+ let _15: &usize; // in scope 0 at $DIR/slice_filter.rs:+0:55: +0:56
+ let mut _16: bool; // in scope 0 at $DIR/slice_filter.rs:+0:60: +0:76
+ let mut _17: bool; // in scope 0 at $DIR/slice_filter.rs:+0:60: +0:66
+ let mut _18: &&usize; // in scope 0 at $DIR/slice_filter.rs:+0:60: +0:61
+ let mut _19: &&usize; // in scope 0 at $DIR/slice_filter.rs:+0:65: +0:66
+ let _20: &usize; // in scope 0 at $DIR/slice_filter.rs:+0:65: +0:66
+ let mut _21: bool; // in scope 0 at $DIR/slice_filter.rs:+0:70: +0:76
+ let mut _22: &&usize; // in scope 0 at $DIR/slice_filter.rs:+0:70: +0:71
+ let mut _23: &&usize; // in scope 0 at $DIR/slice_filter.rs:+0:75: +0:76
+ let _24: &usize; // in scope 0 at $DIR/slice_filter.rs:+0:75: +0:76
+ let mut _25: &(usize, usize, usize, usize); // in scope 0 at $DIR/slice_filter.rs:+0:26: +0:38
+ let mut _26: &(usize, usize, usize, usize); // in scope 0 at $DIR/slice_filter.rs:+0:26: +0:38
+ let mut _27: &(usize, usize, usize, usize); // in scope 0 at $DIR/slice_filter.rs:+0:26: +0:38
+ let mut _28: &(usize, usize, usize, usize); // in scope 0 at $DIR/slice_filter.rs:+0:26: +0:38
+ let mut _31: &usize; // in scope 0 at $SRC_DIR/core/src/cmp.rs:LL:COL
+ let mut _32: &usize; // in scope 0 at $SRC_DIR/core/src/cmp.rs:LL:COL
+ let mut _37: &usize; // in scope 0 at $SRC_DIR/core/src/cmp.rs:LL:COL
+ let mut _38: &usize; // in scope 0 at $SRC_DIR/core/src/cmp.rs:LL:COL
+ let mut _43: &usize; // in scope 0 at $SRC_DIR/core/src/cmp.rs:LL:COL
+ let mut _44: &usize; // in scope 0 at $SRC_DIR/core/src/cmp.rs:LL:COL
+ let mut _49: &usize; // in scope 0 at $SRC_DIR/core/src/cmp.rs:LL:COL
+ let mut _50: &usize; // in scope 0 at $SRC_DIR/core/src/cmp.rs:LL:COL
+ scope 1 {
+ debug a => _3; // in scope 1 at $DIR/slice_filter.rs:+0:27: +0:28
+ debug b => _4; // in scope 1 at $DIR/slice_filter.rs:+0:30: +0:31
+ debug c => _5; // in scope 1 at $DIR/slice_filter.rs:+0:33: +0:34
+ debug d => _6; // in scope 1 at $DIR/slice_filter.rs:+0:36: +0:37
+ scope 2 (inlined cmp::impls::<impl PartialOrd for &usize>::le) { // at $DIR/slice_filter.rs:8:40: 8:46
+ debug self => _9; // in scope 2 at $SRC_DIR/core/src/cmp.rs:LL:COL
+ debug other => _10; // in scope 2 at $SRC_DIR/core/src/cmp.rs:LL:COL
+ let mut _29: &usize; // in scope 2 at $SRC_DIR/core/src/cmp.rs:LL:COL
+ let mut _30: &usize; // in scope 2 at $SRC_DIR/core/src/cmp.rs:LL:COL
+ scope 3 (inlined cmp::impls::<impl PartialOrd for usize>::le) { // at $SRC_DIR/core/src/cmp.rs:LL:COL
+- debug self => _31; // in scope 3 at $SRC_DIR/core/src/cmp.rs:LL:COL
+- debug other => _32; // in scope 3 at $SRC_DIR/core/src/cmp.rs:LL:COL
++ debug self => _29; // in scope 3 at $SRC_DIR/core/src/cmp.rs:LL:COL
++ debug other => _30; // in scope 3 at $SRC_DIR/core/src/cmp.rs:LL:COL
+ let mut _33: usize; // in scope 3 at $SRC_DIR/core/src/cmp.rs:LL:COL
+ let mut _34: usize; // in scope 3 at $SRC_DIR/core/src/cmp.rs:LL:COL
+ }
+ }
+ scope 4 (inlined cmp::impls::<impl PartialOrd for &usize>::le) { // at $DIR/slice_filter.rs:8:60: 8:66
+ debug self => _18; // in scope 4 at $SRC_DIR/core/src/cmp.rs:LL:COL
+ debug other => _19; // in scope 4 at $SRC_DIR/core/src/cmp.rs:LL:COL
+ let mut _35: &usize; // in scope 4 at $SRC_DIR/core/src/cmp.rs:LL:COL
+ let mut _36: &usize; // in scope 4 at $SRC_DIR/core/src/cmp.rs:LL:COL
+ scope 5 (inlined cmp::impls::<impl PartialOrd for usize>::le) { // at $SRC_DIR/core/src/cmp.rs:LL:COL
+- debug self => _37; // in scope 5 at $SRC_DIR/core/src/cmp.rs:LL:COL
+- debug other => _38; // in scope 5 at $SRC_DIR/core/src/cmp.rs:LL:COL
++ debug self => _35; // in scope 5 at $SRC_DIR/core/src/cmp.rs:LL:COL
++ debug other => _36; // in scope 5 at $SRC_DIR/core/src/cmp.rs:LL:COL
+ let mut _39: usize; // in scope 5 at $SRC_DIR/core/src/cmp.rs:LL:COL
+ let mut _40: usize; // in scope 5 at $SRC_DIR/core/src/cmp.rs:LL:COL
+ }
+ }
+ scope 6 (inlined cmp::impls::<impl PartialOrd for &usize>::le) { // at $DIR/slice_filter.rs:8:50: 8:56
+ debug self => _13; // in scope 6 at $SRC_DIR/core/src/cmp.rs:LL:COL
+ debug other => _14; // in scope 6 at $SRC_DIR/core/src/cmp.rs:LL:COL
+ let mut _41: &usize; // in scope 6 at $SRC_DIR/core/src/cmp.rs:LL:COL
+ let mut _42: &usize; // in scope 6 at $SRC_DIR/core/src/cmp.rs:LL:COL
+ scope 7 (inlined cmp::impls::<impl PartialOrd for usize>::le) { // at $SRC_DIR/core/src/cmp.rs:LL:COL
+- debug self => _43; // in scope 7 at $SRC_DIR/core/src/cmp.rs:LL:COL
+- debug other => _44; // in scope 7 at $SRC_DIR/core/src/cmp.rs:LL:COL
++ debug self => _41; // in scope 7 at $SRC_DIR/core/src/cmp.rs:LL:COL
++ debug other => _42; // in scope 7 at $SRC_DIR/core/src/cmp.rs:LL:COL
+ let mut _45: usize; // in scope 7 at $SRC_DIR/core/src/cmp.rs:LL:COL
+ let mut _46: usize; // in scope 7 at $SRC_DIR/core/src/cmp.rs:LL:COL
+ }
+ }
+ scope 8 (inlined cmp::impls::<impl PartialOrd for &usize>::le) { // at $DIR/slice_filter.rs:8:70: 8:76
+ debug self => _22; // in scope 8 at $SRC_DIR/core/src/cmp.rs:LL:COL
+ debug other => _23; // in scope 8 at $SRC_DIR/core/src/cmp.rs:LL:COL
+ let mut _47: &usize; // in scope 8 at $SRC_DIR/core/src/cmp.rs:LL:COL
+ let mut _48: &usize; // in scope 8 at $SRC_DIR/core/src/cmp.rs:LL:COL
+ scope 9 (inlined cmp::impls::<impl PartialOrd for usize>::le) { // at $SRC_DIR/core/src/cmp.rs:LL:COL
+- debug self => _49; // in scope 9 at $SRC_DIR/core/src/cmp.rs:LL:COL
+- debug other => _50; // in scope 9 at $SRC_DIR/core/src/cmp.rs:LL:COL
++ debug self => _47; // in scope 9 at $SRC_DIR/core/src/cmp.rs:LL:COL
++ debug other => _48; // in scope 9 at $SRC_DIR/core/src/cmp.rs:LL:COL
+ let mut _51: usize; // in scope 9 at $SRC_DIR/core/src/cmp.rs:LL:COL
+ let mut _52: usize; // in scope 9 at $SRC_DIR/core/src/cmp.rs:LL:COL
+ }
+ }
+ }
+
+ bb0: {
+- StorageLive(_3); // scope 0 at $DIR/slice_filter.rs:+0:27: +0:28
+ _25 = deref_copy (*_2); // scope 0 at $DIR/slice_filter.rs:+0:27: +0:28
+ _3 = &((*_25).0: usize); // scope 0 at $DIR/slice_filter.rs:+0:27: +0:28
+- StorageLive(_4); // scope 0 at $DIR/slice_filter.rs:+0:30: +0:31
+ _26 = deref_copy (*_2); // scope 0 at $DIR/slice_filter.rs:+0:30: +0:31
+ _4 = &((*_26).1: usize); // scope 0 at $DIR/slice_filter.rs:+0:30: +0:31
+- StorageLive(_5); // scope 0 at $DIR/slice_filter.rs:+0:33: +0:34
+ _27 = deref_copy (*_2); // scope 0 at $DIR/slice_filter.rs:+0:33: +0:34
+ _5 = &((*_27).2: usize); // scope 0 at $DIR/slice_filter.rs:+0:33: +0:34
+- StorageLive(_6); // scope 0 at $DIR/slice_filter.rs:+0:36: +0:37
+ _28 = deref_copy (*_2); // scope 0 at $DIR/slice_filter.rs:+0:36: +0:37
+ _6 = &((*_28).3: usize); // scope 0 at $DIR/slice_filter.rs:+0:36: +0:37
+ StorageLive(_7); // scope 1 at $DIR/slice_filter.rs:+0:40: +0:56
+ StorageLive(_8); // scope 1 at $DIR/slice_filter.rs:+0:40: +0:46
+ StorageLive(_9); // scope 1 at $DIR/slice_filter.rs:+0:40: +0:41
+ _9 = &_3; // scope 1 at $DIR/slice_filter.rs:+0:40: +0:41
+ StorageLive(_10); // scope 1 at $DIR/slice_filter.rs:+0:45: +0:46
+ StorageLive(_11); // scope 1 at $DIR/slice_filter.rs:+0:45: +0:46
+ _11 = _5; // scope 1 at $DIR/slice_filter.rs:+0:45: +0:46
+ _10 = &_11; // scope 1 at $DIR/slice_filter.rs:+0:45: +0:46
+ _29 = deref_copy (*_9); // scope 2 at $SRC_DIR/core/src/cmp.rs:LL:COL
+ _30 = deref_copy (*_10); // scope 2 at $SRC_DIR/core/src/cmp.rs:LL:COL
+- StorageLive(_31); // scope 2 at $SRC_DIR/core/src/cmp.rs:LL:COL
+- _31 = _29; // scope 2 at $SRC_DIR/core/src/cmp.rs:LL:COL
+- StorageLive(_32); // scope 2 at $SRC_DIR/core/src/cmp.rs:LL:COL
+- _32 = _30; // scope 2 at $SRC_DIR/core/src/cmp.rs:LL:COL
+ StorageLive(_33); // scope 3 at $SRC_DIR/core/src/cmp.rs:LL:COL
+- _33 = (*_31); // scope 3 at $SRC_DIR/core/src/cmp.rs:LL:COL
++ _33 = (*_29); // scope 3 at $SRC_DIR/core/src/cmp.rs:LL:COL
+ StorageLive(_34); // scope 3 at $SRC_DIR/core/src/cmp.rs:LL:COL
+- _34 = (*_32); // scope 3 at $SRC_DIR/core/src/cmp.rs:LL:COL
++ _34 = (*_30); // scope 3 at $SRC_DIR/core/src/cmp.rs:LL:COL
+ _8 = Le(move _33, move _34); // scope 3 at $SRC_DIR/core/src/cmp.rs:LL:COL
+ StorageDead(_34); // scope 3 at $SRC_DIR/core/src/cmp.rs:LL:COL
+ StorageDead(_33); // scope 3 at $SRC_DIR/core/src/cmp.rs:LL:COL
+- StorageDead(_32); // scope 2 at $SRC_DIR/core/src/cmp.rs:LL:COL
+- StorageDead(_31); // scope 2 at $SRC_DIR/core/src/cmp.rs:LL:COL
+ StorageDead(_11); // scope 1 at $DIR/slice_filter.rs:+0:45: +0:46
+ StorageDead(_10); // scope 1 at $DIR/slice_filter.rs:+0:45: +0:46
+ StorageDead(_9); // scope 1 at $DIR/slice_filter.rs:+0:45: +0:46
+ switchInt(move _8) -> [0: bb4, otherwise: bb5]; // scope 1 at $DIR/slice_filter.rs:+0:40: +0:56
+ }
+
+ bb1: {
+ _0 = const true; // scope 1 at $DIR/slice_filter.rs:+0:40: +0:76
+ goto -> bb3; // scope 1 at $DIR/slice_filter.rs:+0:40: +0:76
+ }
+
+ bb2: {
+ StorageLive(_16); // scope 1 at $DIR/slice_filter.rs:+0:60: +0:76
+ StorageLive(_17); // scope 1 at $DIR/slice_filter.rs:+0:60: +0:66
+ StorageLive(_18); // scope 1 at $DIR/slice_filter.rs:+0:60: +0:61
+ _18 = &_5; // scope 1 at $DIR/slice_filter.rs:+0:60: +0:61
+ StorageLive(_19); // scope 1 at $DIR/slice_filter.rs:+0:65: +0:66
+ StorageLive(_20); // scope 1 at $DIR/slice_filter.rs:+0:65: +0:66
+ _20 = _3; // scope 1 at $DIR/slice_filter.rs:+0:65: +0:66
+ _19 = &_20; // scope 1 at $DIR/slice_filter.rs:+0:65: +0:66
+ _35 = deref_copy (*_18); // scope 4 at $SRC_DIR/core/src/cmp.rs:LL:COL
+ _36 = deref_copy (*_19); // scope 4 at $SRC_DIR/core/src/cmp.rs:LL:COL
+- StorageLive(_37); // scope 4 at $SRC_DIR/core/src/cmp.rs:LL:COL
+- _37 = _35; // scope 4 at $SRC_DIR/core/src/cmp.rs:LL:COL
+- StorageLive(_38); // scope 4 at $SRC_DIR/core/src/cmp.rs:LL:COL
+- _38 = _36; // scope 4 at $SRC_DIR/core/src/cmp.rs:LL:COL
+ StorageLive(_39); // scope 5 at $SRC_DIR/core/src/cmp.rs:LL:COL
+- _39 = (*_37); // scope 5 at $SRC_DIR/core/src/cmp.rs:LL:COL
++ _39 = (*_35); // scope 5 at $SRC_DIR/core/src/cmp.rs:LL:COL
+ StorageLive(_40); // scope 5 at $SRC_DIR/core/src/cmp.rs:LL:COL
+- _40 = (*_38); // scope 5 at $SRC_DIR/core/src/cmp.rs:LL:COL
++ _40 = (*_36); // scope 5 at $SRC_DIR/core/src/cmp.rs:LL:COL
+ _17 = Le(move _39, move _40); // scope 5 at $SRC_DIR/core/src/cmp.rs:LL:COL
+ StorageDead(_40); // scope 5 at $SRC_DIR/core/src/cmp.rs:LL:COL
+ StorageDead(_39); // scope 5 at $SRC_DIR/core/src/cmp.rs:LL:COL
+- StorageDead(_38); // scope 4 at $SRC_DIR/core/src/cmp.rs:LL:COL
+- StorageDead(_37); // scope 4 at $SRC_DIR/core/src/cmp.rs:LL:COL
+ StorageDead(_20); // scope 1 at $DIR/slice_filter.rs:+0:65: +0:66
+ StorageDead(_19); // scope 1 at $DIR/slice_filter.rs:+0:65: +0:66
+ StorageDead(_18); // scope 1 at $DIR/slice_filter.rs:+0:65: +0:66
+ switchInt(move _17) -> [0: bb6, otherwise: bb7]; // scope 1 at $DIR/slice_filter.rs:+0:60: +0:76
+ }
+
+ bb3: {
+ StorageDead(_16); // scope 1 at $DIR/slice_filter.rs:+0:75: +0:76
+ StorageDead(_7); // scope 1 at $DIR/slice_filter.rs:+0:75: +0:76
+- StorageDead(_6); // scope 0 at $DIR/slice_filter.rs:+0:75: +0:76
+- StorageDead(_5); // scope 0 at $DIR/slice_filter.rs:+0:75: +0:76
+- StorageDead(_4); // scope 0 at $DIR/slice_filter.rs:+0:75: +0:76
+- StorageDead(_3); // scope 0 at $DIR/slice_filter.rs:+0:75: +0:76
+ return; // scope 0 at $DIR/slice_filter.rs:+0:76: +0:76
+ }
+
+ bb4: {
+ _7 = const false; // scope 1 at $DIR/slice_filter.rs:+0:40: +0:56
+ StorageDead(_12); // scope 1 at $DIR/slice_filter.rs:+0:55: +0:56
+ StorageDead(_8); // scope 1 at $DIR/slice_filter.rs:+0:55: +0:56
+ goto -> bb2; // scope 1 at $DIR/slice_filter.rs:+0:40: +0:56
+ }
+
+ bb5: {
+ StorageLive(_12); // scope 1 at $DIR/slice_filter.rs:+0:50: +0:56
+ StorageLive(_13); // scope 1 at $DIR/slice_filter.rs:+0:50: +0:51
+ _13 = &_6; // scope 1 at $DIR/slice_filter.rs:+0:50: +0:51
+ StorageLive(_14); // scope 1 at $DIR/slice_filter.rs:+0:55: +0:56
+ StorageLive(_15); // scope 1 at $DIR/slice_filter.rs:+0:55: +0:56
+ _15 = _4; // scope 1 at $DIR/slice_filter.rs:+0:55: +0:56
+ _14 = &_15; // scope 1 at $DIR/slice_filter.rs:+0:55: +0:56
+ _41 = deref_copy (*_13); // scope 6 at $SRC_DIR/core/src/cmp.rs:LL:COL
+ _42 = deref_copy (*_14); // scope 6 at $SRC_DIR/core/src/cmp.rs:LL:COL
+- StorageLive(_43); // scope 6 at $SRC_DIR/core/src/cmp.rs:LL:COL
+- _43 = _41; // scope 6 at $SRC_DIR/core/src/cmp.rs:LL:COL
+- StorageLive(_44); // scope 6 at $SRC_DIR/core/src/cmp.rs:LL:COL
+- _44 = _42; // scope 6 at $SRC_DIR/core/src/cmp.rs:LL:COL
+ StorageLive(_45); // scope 7 at $SRC_DIR/core/src/cmp.rs:LL:COL
+- _45 = (*_43); // scope 7 at $SRC_DIR/core/src/cmp.rs:LL:COL
++ _45 = (*_41); // scope 7 at $SRC_DIR/core/src/cmp.rs:LL:COL
+ StorageLive(_46); // scope 7 at $SRC_DIR/core/src/cmp.rs:LL:COL
+- _46 = (*_44); // scope 7 at $SRC_DIR/core/src/cmp.rs:LL:COL
++ _46 = (*_42); // scope 7 at $SRC_DIR/core/src/cmp.rs:LL:COL
+ _12 = Le(move _45, move _46); // scope 7 at $SRC_DIR/core/src/cmp.rs:LL:COL
+ StorageDead(_46); // scope 7 at $SRC_DIR/core/src/cmp.rs:LL:COL
+ StorageDead(_45); // scope 7 at $SRC_DIR/core/src/cmp.rs:LL:COL
+- StorageDead(_44); // scope 6 at $SRC_DIR/core/src/cmp.rs:LL:COL
+- StorageDead(_43); // scope 6 at $SRC_DIR/core/src/cmp.rs:LL:COL
+ StorageDead(_15); // scope 1 at $DIR/slice_filter.rs:+0:55: +0:56
+ StorageDead(_14); // scope 1 at $DIR/slice_filter.rs:+0:55: +0:56
+ StorageDead(_13); // scope 1 at $DIR/slice_filter.rs:+0:55: +0:56
+ _7 = move _12; // scope 1 at $DIR/slice_filter.rs:+0:40: +0:56
+ StorageDead(_12); // scope 1 at $DIR/slice_filter.rs:+0:55: +0:56
+ StorageDead(_8); // scope 1 at $DIR/slice_filter.rs:+0:55: +0:56
+ switchInt(move _7) -> [0: bb2, otherwise: bb1]; // scope 1 at $DIR/slice_filter.rs:+0:40: +0:76
+ }
+
+ bb6: {
+ _16 = const false; // scope 1 at $DIR/slice_filter.rs:+0:60: +0:76
+ goto -> bb8; // scope 1 at $DIR/slice_filter.rs:+0:60: +0:76
+ }
+
+ bb7: {
+ StorageLive(_21); // scope 1 at $DIR/slice_filter.rs:+0:70: +0:76
+ StorageLive(_22); // scope 1 at $DIR/slice_filter.rs:+0:70: +0:71
+ _22 = &_4; // scope 1 at $DIR/slice_filter.rs:+0:70: +0:71
+ StorageLive(_23); // scope 1 at $DIR/slice_filter.rs:+0:75: +0:76
+ StorageLive(_24); // scope 1 at $DIR/slice_filter.rs:+0:75: +0:76
+ _24 = _6; // scope 1 at $DIR/slice_filter.rs:+0:75: +0:76
+ _23 = &_24; // scope 1 at $DIR/slice_filter.rs:+0:75: +0:76
+ _47 = deref_copy (*_22); // scope 8 at $SRC_DIR/core/src/cmp.rs:LL:COL
+ _48 = deref_copy (*_23); // scope 8 at $SRC_DIR/core/src/cmp.rs:LL:COL
+- StorageLive(_49); // scope 8 at $SRC_DIR/core/src/cmp.rs:LL:COL
+- _49 = _47; // scope 8 at $SRC_DIR/core/src/cmp.rs:LL:COL
+- StorageLive(_50); // scope 8 at $SRC_DIR/core/src/cmp.rs:LL:COL
+- _50 = _48; // scope 8 at $SRC_DIR/core/src/cmp.rs:LL:COL
+ StorageLive(_51); // scope 9 at $SRC_DIR/core/src/cmp.rs:LL:COL
+- _51 = (*_49); // scope 9 at $SRC_DIR/core/src/cmp.rs:LL:COL
++ _51 = (*_47); // scope 9 at $SRC_DIR/core/src/cmp.rs:LL:COL
+ StorageLive(_52); // scope 9 at $SRC_DIR/core/src/cmp.rs:LL:COL
+- _52 = (*_50); // scope 9 at $SRC_DIR/core/src/cmp.rs:LL:COL
++ _52 = (*_48); // scope 9 at $SRC_DIR/core/src/cmp.rs:LL:COL
+ _21 = Le(move _51, move _52); // scope 9 at $SRC_DIR/core/src/cmp.rs:LL:COL
+ StorageDead(_52); // scope 9 at $SRC_DIR/core/src/cmp.rs:LL:COL
+ StorageDead(_51); // scope 9 at $SRC_DIR/core/src/cmp.rs:LL:COL
+- StorageDead(_50); // scope 8 at $SRC_DIR/core/src/cmp.rs:LL:COL
+- StorageDead(_49); // scope 8 at $SRC_DIR/core/src/cmp.rs:LL:COL
+ StorageDead(_24); // scope 1 at $DIR/slice_filter.rs:+0:75: +0:76
+ StorageDead(_23); // scope 1 at $DIR/slice_filter.rs:+0:75: +0:76
+ StorageDead(_22); // scope 1 at $DIR/slice_filter.rs:+0:75: +0:76
+ _16 = move _21; // scope 1 at $DIR/slice_filter.rs:+0:60: +0:76
+ goto -> bb8; // scope 1 at $DIR/slice_filter.rs:+0:60: +0:76
+ }
+
+ bb8: {
+ StorageDead(_21); // scope 1 at $DIR/slice_filter.rs:+0:75: +0:76
+ StorageDead(_17); // scope 1 at $DIR/slice_filter.rs:+0:75: +0:76
+ _0 = move _16; // scope 1 at $DIR/slice_filter.rs:+0:40: +0:76
+ goto -> bb3; // scope 1 at $DIR/slice_filter.rs:+0:40: +0:76
+ }
+ }
+
diff --git a/tests/mir-opt/slice_filter.variant_a-{closure#0}.DestinationPropagation.diff b/tests/mir-opt/slice_filter.variant_a-{closure#0}.DestinationPropagation.diff
new file mode 100644
index 000000000..294c3272f
--- /dev/null
+++ b/tests/mir-opt/slice_filter.variant_a-{closure#0}.DestinationPropagation.diff
@@ -0,0 +1,237 @@
+- // MIR for `variant_a::{closure#0}` before DestinationPropagation
++ // MIR for `variant_a::{closure#0}` after DestinationPropagation
+
+ fn variant_a::{closure#0}(_1: &mut [closure@$DIR/slice_filter.rs:8:25: 8:39], _2: &&(usize, usize, usize, usize)) -> bool {
+ let mut _0: bool; // return place in scope 0 at $DIR/slice_filter.rs:+0:40: +0:40
+ let _3: &usize; // in scope 0 at $DIR/slice_filter.rs:+0:27: +0:28
+ let _4: &usize; // in scope 0 at $DIR/slice_filter.rs:+0:30: +0:31
+ let _5: &usize; // in scope 0 at $DIR/slice_filter.rs:+0:33: +0:34
+ let _6: &usize; // in scope 0 at $DIR/slice_filter.rs:+0:36: +0:37
+ let mut _7: bool; // in scope 0 at $DIR/slice_filter.rs:+0:40: +0:56
+ let mut _8: bool; // in scope 0 at $DIR/slice_filter.rs:+0:40: +0:46
+ let mut _9: &&usize; // in scope 0 at $DIR/slice_filter.rs:+0:40: +0:41
+ let mut _10: &&usize; // in scope 0 at $DIR/slice_filter.rs:+0:45: +0:46
+ let _11: &usize; // in scope 0 at $DIR/slice_filter.rs:+0:45: +0:46
+ let mut _12: bool; // in scope 0 at $DIR/slice_filter.rs:+0:50: +0:56
+ let mut _13: &&usize; // in scope 0 at $DIR/slice_filter.rs:+0:50: +0:51
+ let mut _14: &&usize; // in scope 0 at $DIR/slice_filter.rs:+0:55: +0:56
+ let _15: &usize; // in scope 0 at $DIR/slice_filter.rs:+0:55: +0:56
+ let mut _16: bool; // in scope 0 at $DIR/slice_filter.rs:+0:60: +0:76
+ let mut _17: bool; // in scope 0 at $DIR/slice_filter.rs:+0:60: +0:66
+ let mut _18: &&usize; // in scope 0 at $DIR/slice_filter.rs:+0:60: +0:61
+ let mut _19: &&usize; // in scope 0 at $DIR/slice_filter.rs:+0:65: +0:66
+ let _20: &usize; // in scope 0 at $DIR/slice_filter.rs:+0:65: +0:66
+ let mut _21: bool; // in scope 0 at $DIR/slice_filter.rs:+0:70: +0:76
+ let mut _22: &&usize; // in scope 0 at $DIR/slice_filter.rs:+0:70: +0:71
+ let mut _23: &&usize; // in scope 0 at $DIR/slice_filter.rs:+0:75: +0:76
+ let _24: &usize; // in scope 0 at $DIR/slice_filter.rs:+0:75: +0:76
+ let mut _25: &(usize, usize, usize, usize); // in scope 0 at $DIR/slice_filter.rs:+0:26: +0:38
+ let mut _26: &(usize, usize, usize, usize); // in scope 0 at $DIR/slice_filter.rs:+0:26: +0:38
+ let mut _27: &(usize, usize, usize, usize); // in scope 0 at $DIR/slice_filter.rs:+0:26: +0:38
+ let mut _28: &(usize, usize, usize, usize); // in scope 0 at $DIR/slice_filter.rs:+0:26: +0:38
+ scope 1 {
+ debug a => _3; // in scope 1 at $DIR/slice_filter.rs:+0:27: +0:28
+ debug b => _4; // in scope 1 at $DIR/slice_filter.rs:+0:30: +0:31
+ debug c => _5; // in scope 1 at $DIR/slice_filter.rs:+0:33: +0:34
+ debug d => _6; // in scope 1 at $DIR/slice_filter.rs:+0:36: +0:37
+ scope 2 (inlined cmp::impls::<impl PartialOrd for &usize>::le) { // at $DIR/slice_filter.rs:8:40: 8:46
+ debug self => _9; // in scope 2 at $SRC_DIR/core/src/cmp.rs:LL:COL
+ debug other => _10; // in scope 2 at $SRC_DIR/core/src/cmp.rs:LL:COL
+ let mut _29: &usize; // in scope 2 at $SRC_DIR/core/src/cmp.rs:LL:COL
+ let mut _30: &usize; // in scope 2 at $SRC_DIR/core/src/cmp.rs:LL:COL
+ scope 3 (inlined cmp::impls::<impl PartialOrd for usize>::le) { // at $SRC_DIR/core/src/cmp.rs:LL:COL
+ debug self => _29; // in scope 3 at $SRC_DIR/core/src/cmp.rs:LL:COL
+ debug other => _30; // in scope 3 at $SRC_DIR/core/src/cmp.rs:LL:COL
+ let mut _31: usize; // in scope 3 at $SRC_DIR/core/src/cmp.rs:LL:COL
+ let mut _32: usize; // in scope 3 at $SRC_DIR/core/src/cmp.rs:LL:COL
+ }
+ }
+ scope 4 (inlined cmp::impls::<impl PartialOrd for &usize>::le) { // at $DIR/slice_filter.rs:8:60: 8:66
+ debug self => _18; // in scope 4 at $SRC_DIR/core/src/cmp.rs:LL:COL
+ debug other => _19; // in scope 4 at $SRC_DIR/core/src/cmp.rs:LL:COL
+ let mut _33: &usize; // in scope 4 at $SRC_DIR/core/src/cmp.rs:LL:COL
+ let mut _34: &usize; // in scope 4 at $SRC_DIR/core/src/cmp.rs:LL:COL
+ scope 5 (inlined cmp::impls::<impl PartialOrd for usize>::le) { // at $SRC_DIR/core/src/cmp.rs:LL:COL
+ debug self => _33; // in scope 5 at $SRC_DIR/core/src/cmp.rs:LL:COL
+ debug other => _34; // in scope 5 at $SRC_DIR/core/src/cmp.rs:LL:COL
+ let mut _35: usize; // in scope 5 at $SRC_DIR/core/src/cmp.rs:LL:COL
+ let mut _36: usize; // in scope 5 at $SRC_DIR/core/src/cmp.rs:LL:COL
+ }
+ }
+ scope 6 (inlined cmp::impls::<impl PartialOrd for &usize>::le) { // at $DIR/slice_filter.rs:8:50: 8:56
+ debug self => _13; // in scope 6 at $SRC_DIR/core/src/cmp.rs:LL:COL
+ debug other => _14; // in scope 6 at $SRC_DIR/core/src/cmp.rs:LL:COL
+ let mut _37: &usize; // in scope 6 at $SRC_DIR/core/src/cmp.rs:LL:COL
+ let mut _38: &usize; // in scope 6 at $SRC_DIR/core/src/cmp.rs:LL:COL
+ scope 7 (inlined cmp::impls::<impl PartialOrd for usize>::le) { // at $SRC_DIR/core/src/cmp.rs:LL:COL
+ debug self => _37; // in scope 7 at $SRC_DIR/core/src/cmp.rs:LL:COL
+ debug other => _38; // in scope 7 at $SRC_DIR/core/src/cmp.rs:LL:COL
+ let mut _39: usize; // in scope 7 at $SRC_DIR/core/src/cmp.rs:LL:COL
+ let mut _40: usize; // in scope 7 at $SRC_DIR/core/src/cmp.rs:LL:COL
+ }
+ }
+ scope 8 (inlined cmp::impls::<impl PartialOrd for &usize>::le) { // at $DIR/slice_filter.rs:8:70: 8:76
+ debug self => _22; // in scope 8 at $SRC_DIR/core/src/cmp.rs:LL:COL
+ debug other => _23; // in scope 8 at $SRC_DIR/core/src/cmp.rs:LL:COL
+ let mut _41: &usize; // in scope 8 at $SRC_DIR/core/src/cmp.rs:LL:COL
+ let mut _42: &usize; // in scope 8 at $SRC_DIR/core/src/cmp.rs:LL:COL
+ scope 9 (inlined cmp::impls::<impl PartialOrd for usize>::le) { // at $SRC_DIR/core/src/cmp.rs:LL:COL
+ debug self => _41; // in scope 9 at $SRC_DIR/core/src/cmp.rs:LL:COL
+ debug other => _42; // in scope 9 at $SRC_DIR/core/src/cmp.rs:LL:COL
+ let mut _43: usize; // in scope 9 at $SRC_DIR/core/src/cmp.rs:LL:COL
+ let mut _44: usize; // in scope 9 at $SRC_DIR/core/src/cmp.rs:LL:COL
+ }
+ }
+ }
+
+ bb0: {
+ _25 = deref_copy (*_2); // scope 0 at $DIR/slice_filter.rs:+0:27: +0:28
+ _3 = &((*_25).0: usize); // scope 0 at $DIR/slice_filter.rs:+0:27: +0:28
+ _26 = deref_copy (*_2); // scope 0 at $DIR/slice_filter.rs:+0:30: +0:31
+ _4 = &((*_26).1: usize); // scope 0 at $DIR/slice_filter.rs:+0:30: +0:31
+ _27 = deref_copy (*_2); // scope 0 at $DIR/slice_filter.rs:+0:33: +0:34
+ _5 = &((*_27).2: usize); // scope 0 at $DIR/slice_filter.rs:+0:33: +0:34
+ _28 = deref_copy (*_2); // scope 0 at $DIR/slice_filter.rs:+0:36: +0:37
+ _6 = &((*_28).3: usize); // scope 0 at $DIR/slice_filter.rs:+0:36: +0:37
+- StorageLive(_7); // scope 1 at $DIR/slice_filter.rs:+0:40: +0:56
++ nop; // scope 1 at $DIR/slice_filter.rs:+0:40: +0:56
+ StorageLive(_8); // scope 1 at $DIR/slice_filter.rs:+0:40: +0:46
+ StorageLive(_9); // scope 1 at $DIR/slice_filter.rs:+0:40: +0:41
+ _9 = &_3; // scope 1 at $DIR/slice_filter.rs:+0:40: +0:41
+ StorageLive(_10); // scope 1 at $DIR/slice_filter.rs:+0:45: +0:46
+ StorageLive(_11); // scope 1 at $DIR/slice_filter.rs:+0:45: +0:46
+ _11 = _5; // scope 1 at $DIR/slice_filter.rs:+0:45: +0:46
+ _10 = &_11; // scope 1 at $DIR/slice_filter.rs:+0:45: +0:46
+ _29 = deref_copy (*_9); // scope 2 at $SRC_DIR/core/src/cmp.rs:LL:COL
+ _30 = deref_copy (*_10); // scope 2 at $SRC_DIR/core/src/cmp.rs:LL:COL
+ StorageLive(_31); // scope 3 at $SRC_DIR/core/src/cmp.rs:LL:COL
+ _31 = (*_29); // scope 3 at $SRC_DIR/core/src/cmp.rs:LL:COL
+ StorageLive(_32); // scope 3 at $SRC_DIR/core/src/cmp.rs:LL:COL
+ _32 = (*_30); // scope 3 at $SRC_DIR/core/src/cmp.rs:LL:COL
+ _8 = Le(move _31, move _32); // scope 3 at $SRC_DIR/core/src/cmp.rs:LL:COL
+ StorageDead(_32); // scope 3 at $SRC_DIR/core/src/cmp.rs:LL:COL
+ StorageDead(_31); // scope 3 at $SRC_DIR/core/src/cmp.rs:LL:COL
+ StorageDead(_11); // scope 1 at $DIR/slice_filter.rs:+0:45: +0:46
+ StorageDead(_10); // scope 1 at $DIR/slice_filter.rs:+0:45: +0:46
+ StorageDead(_9); // scope 1 at $DIR/slice_filter.rs:+0:45: +0:46
+ switchInt(move _8) -> [0: bb4, otherwise: bb5]; // scope 1 at $DIR/slice_filter.rs:+0:40: +0:56
+ }
+
+ bb1: {
+ _0 = const true; // scope 1 at $DIR/slice_filter.rs:+0:40: +0:76
+ goto -> bb3; // scope 1 at $DIR/slice_filter.rs:+0:40: +0:76
+ }
+
+ bb2: {
+- StorageLive(_16); // scope 1 at $DIR/slice_filter.rs:+0:60: +0:76
++ nop; // scope 1 at $DIR/slice_filter.rs:+0:60: +0:76
+ StorageLive(_17); // scope 1 at $DIR/slice_filter.rs:+0:60: +0:66
+ StorageLive(_18); // scope 1 at $DIR/slice_filter.rs:+0:60: +0:61
+ _18 = &_5; // scope 1 at $DIR/slice_filter.rs:+0:60: +0:61
+ StorageLive(_19); // scope 1 at $DIR/slice_filter.rs:+0:65: +0:66
+ StorageLive(_20); // scope 1 at $DIR/slice_filter.rs:+0:65: +0:66
+ _20 = _3; // scope 1 at $DIR/slice_filter.rs:+0:65: +0:66
+ _19 = &_20; // scope 1 at $DIR/slice_filter.rs:+0:65: +0:66
+ _33 = deref_copy (*_18); // scope 4 at $SRC_DIR/core/src/cmp.rs:LL:COL
+ _34 = deref_copy (*_19); // scope 4 at $SRC_DIR/core/src/cmp.rs:LL:COL
+ StorageLive(_35); // scope 5 at $SRC_DIR/core/src/cmp.rs:LL:COL
+ _35 = (*_33); // scope 5 at $SRC_DIR/core/src/cmp.rs:LL:COL
+ StorageLive(_36); // scope 5 at $SRC_DIR/core/src/cmp.rs:LL:COL
+ _36 = (*_34); // scope 5 at $SRC_DIR/core/src/cmp.rs:LL:COL
+ _17 = Le(move _35, move _36); // scope 5 at $SRC_DIR/core/src/cmp.rs:LL:COL
+ StorageDead(_36); // scope 5 at $SRC_DIR/core/src/cmp.rs:LL:COL
+ StorageDead(_35); // scope 5 at $SRC_DIR/core/src/cmp.rs:LL:COL
+ StorageDead(_20); // scope 1 at $DIR/slice_filter.rs:+0:65: +0:66
+ StorageDead(_19); // scope 1 at $DIR/slice_filter.rs:+0:65: +0:66
+ StorageDead(_18); // scope 1 at $DIR/slice_filter.rs:+0:65: +0:66
+ switchInt(move _17) -> [0: bb6, otherwise: bb7]; // scope 1 at $DIR/slice_filter.rs:+0:60: +0:76
+ }
+
+ bb3: {
+- StorageDead(_16); // scope 1 at $DIR/slice_filter.rs:+0:75: +0:76
+- StorageDead(_7); // scope 1 at $DIR/slice_filter.rs:+0:75: +0:76
++ nop; // scope 1 at $DIR/slice_filter.rs:+0:75: +0:76
++ nop; // scope 1 at $DIR/slice_filter.rs:+0:75: +0:76
+ return; // scope 0 at $DIR/slice_filter.rs:+0:76: +0:76
+ }
+
+ bb4: {
+- StorageDead(_12); // scope 1 at $DIR/slice_filter.rs:+0:55: +0:56
++ nop; // scope 1 at $DIR/slice_filter.rs:+0:55: +0:56
+ StorageDead(_8); // scope 1 at $DIR/slice_filter.rs:+0:55: +0:56
+ goto -> bb2; // scope 1 at $DIR/slice_filter.rs:+0:40: +0:56
+ }
+
+ bb5: {
+- StorageLive(_12); // scope 1 at $DIR/slice_filter.rs:+0:50: +0:56
++ nop; // scope 1 at $DIR/slice_filter.rs:+0:50: +0:56
+ StorageLive(_13); // scope 1 at $DIR/slice_filter.rs:+0:50: +0:51
+ _13 = &_6; // scope 1 at $DIR/slice_filter.rs:+0:50: +0:51
+ StorageLive(_14); // scope 1 at $DIR/slice_filter.rs:+0:55: +0:56
+ StorageLive(_15); // scope 1 at $DIR/slice_filter.rs:+0:55: +0:56
+ _15 = _4; // scope 1 at $DIR/slice_filter.rs:+0:55: +0:56
+ _14 = &_15; // scope 1 at $DIR/slice_filter.rs:+0:55: +0:56
+ _37 = deref_copy (*_13); // scope 6 at $SRC_DIR/core/src/cmp.rs:LL:COL
+ _38 = deref_copy (*_14); // scope 6 at $SRC_DIR/core/src/cmp.rs:LL:COL
+ StorageLive(_39); // scope 7 at $SRC_DIR/core/src/cmp.rs:LL:COL
+ _39 = (*_37); // scope 7 at $SRC_DIR/core/src/cmp.rs:LL:COL
+ StorageLive(_40); // scope 7 at $SRC_DIR/core/src/cmp.rs:LL:COL
+ _40 = (*_38); // scope 7 at $SRC_DIR/core/src/cmp.rs:LL:COL
+ _12 = Le(move _39, move _40); // scope 7 at $SRC_DIR/core/src/cmp.rs:LL:COL
+ StorageDead(_40); // scope 7 at $SRC_DIR/core/src/cmp.rs:LL:COL
+ StorageDead(_39); // scope 7 at $SRC_DIR/core/src/cmp.rs:LL:COL
+ StorageDead(_15); // scope 1 at $DIR/slice_filter.rs:+0:55: +0:56
+ StorageDead(_14); // scope 1 at $DIR/slice_filter.rs:+0:55: +0:56
+ StorageDead(_13); // scope 1 at $DIR/slice_filter.rs:+0:55: +0:56
+- _7 = move _12; // scope 1 at $DIR/slice_filter.rs:+0:40: +0:56
+- StorageDead(_12); // scope 1 at $DIR/slice_filter.rs:+0:55: +0:56
++ nop; // scope 1 at $DIR/slice_filter.rs:+0:40: +0:56
++ nop; // scope 1 at $DIR/slice_filter.rs:+0:55: +0:56
+ StorageDead(_8); // scope 1 at $DIR/slice_filter.rs:+0:55: +0:56
+- switchInt(move _7) -> [0: bb2, otherwise: bb1]; // scope 1 at $DIR/slice_filter.rs:+0:40: +0:76
++ switchInt(move _12) -> [0: bb2, otherwise: bb1]; // scope 1 at $DIR/slice_filter.rs:+0:40: +0:76
+ }
+
+ bb6: {
+- _16 = const false; // scope 1 at $DIR/slice_filter.rs:+0:60: +0:76
++ _0 = const false; // scope 1 at $DIR/slice_filter.rs:+0:60: +0:76
+ goto -> bb8; // scope 1 at $DIR/slice_filter.rs:+0:60: +0:76
+ }
+
+ bb7: {
+- StorageLive(_21); // scope 1 at $DIR/slice_filter.rs:+0:70: +0:76
++ nop; // scope 1 at $DIR/slice_filter.rs:+0:70: +0:76
+ StorageLive(_22); // scope 1 at $DIR/slice_filter.rs:+0:70: +0:71
+ _22 = &_4; // scope 1 at $DIR/slice_filter.rs:+0:70: +0:71
+ StorageLive(_23); // scope 1 at $DIR/slice_filter.rs:+0:75: +0:76
+ StorageLive(_24); // scope 1 at $DIR/slice_filter.rs:+0:75: +0:76
+ _24 = _6; // scope 1 at $DIR/slice_filter.rs:+0:75: +0:76
+ _23 = &_24; // scope 1 at $DIR/slice_filter.rs:+0:75: +0:76
+ _41 = deref_copy (*_22); // scope 8 at $SRC_DIR/core/src/cmp.rs:LL:COL
+ _42 = deref_copy (*_23); // scope 8 at $SRC_DIR/core/src/cmp.rs:LL:COL
+ StorageLive(_43); // scope 9 at $SRC_DIR/core/src/cmp.rs:LL:COL
+ _43 = (*_41); // scope 9 at $SRC_DIR/core/src/cmp.rs:LL:COL
+ StorageLive(_44); // scope 9 at $SRC_DIR/core/src/cmp.rs:LL:COL
+ _44 = (*_42); // scope 9 at $SRC_DIR/core/src/cmp.rs:LL:COL
+- _21 = Le(move _43, move _44); // scope 9 at $SRC_DIR/core/src/cmp.rs:LL:COL
++ _0 = Le(move _43, move _44); // scope 9 at $SRC_DIR/core/src/cmp.rs:LL:COL
+ StorageDead(_44); // scope 9 at $SRC_DIR/core/src/cmp.rs:LL:COL
+ StorageDead(_43); // scope 9 at $SRC_DIR/core/src/cmp.rs:LL:COL
+ StorageDead(_24); // scope 1 at $DIR/slice_filter.rs:+0:75: +0:76
+ StorageDead(_23); // scope 1 at $DIR/slice_filter.rs:+0:75: +0:76
+ StorageDead(_22); // scope 1 at $DIR/slice_filter.rs:+0:75: +0:76
+- _16 = move _21; // scope 1 at $DIR/slice_filter.rs:+0:60: +0:76
++ nop; // scope 1 at $DIR/slice_filter.rs:+0:60: +0:76
+ goto -> bb8; // scope 1 at $DIR/slice_filter.rs:+0:60: +0:76
+ }
+
+ bb8: {
+- StorageDead(_21); // scope 1 at $DIR/slice_filter.rs:+0:75: +0:76
++ nop; // scope 1 at $DIR/slice_filter.rs:+0:75: +0:76
+ StorageDead(_17); // scope 1 at $DIR/slice_filter.rs:+0:75: +0:76
+- _0 = move _16; // scope 1 at $DIR/slice_filter.rs:+0:40: +0:76
++ nop; // scope 1 at $DIR/slice_filter.rs:+0:40: +0:76
+ goto -> bb3; // scope 1 at $DIR/slice_filter.rs:+0:40: +0:76
+ }
+ }
+
diff --git a/tests/mir-opt/slice_filter.variant_b-{closure#0}.CopyProp.diff b/tests/mir-opt/slice_filter.variant_b-{closure#0}.CopyProp.diff
new file mode 100644
index 000000000..5e4bdbdfa
--- /dev/null
+++ b/tests/mir-opt/slice_filter.variant_b-{closure#0}.CopyProp.diff
@@ -0,0 +1,139 @@
+- // MIR for `variant_b::{closure#0}` before CopyProp
++ // MIR for `variant_b::{closure#0}` after CopyProp
+
+ fn variant_b::{closure#0}(_1: &mut [closure@$DIR/slice_filter.rs:12:25: 12:41], _2: &&(usize, usize, usize, usize)) -> bool {
+ let mut _0: bool; // return place in scope 0 at $DIR/slice_filter.rs:+0:42: +0:42
+ let _3: usize; // in scope 0 at $DIR/slice_filter.rs:+0:29: +0:30
+ let _4: usize; // in scope 0 at $DIR/slice_filter.rs:+0:32: +0:33
+ let _5: usize; // in scope 0 at $DIR/slice_filter.rs:+0:35: +0:36
+ let _6: usize; // in scope 0 at $DIR/slice_filter.rs:+0:38: +0:39
+ let mut _7: bool; // in scope 0 at $DIR/slice_filter.rs:+0:42: +0:58
+ let mut _8: bool; // in scope 0 at $DIR/slice_filter.rs:+0:42: +0:48
+ let mut _9: usize; // in scope 0 at $DIR/slice_filter.rs:+0:42: +0:43
+ let mut _10: usize; // in scope 0 at $DIR/slice_filter.rs:+0:47: +0:48
+ let mut _11: bool; // in scope 0 at $DIR/slice_filter.rs:+0:52: +0:58
+ let mut _12: usize; // in scope 0 at $DIR/slice_filter.rs:+0:52: +0:53
+ let mut _13: usize; // in scope 0 at $DIR/slice_filter.rs:+0:57: +0:58
+ let mut _14: bool; // in scope 0 at $DIR/slice_filter.rs:+0:62: +0:78
+ let mut _15: bool; // in scope 0 at $DIR/slice_filter.rs:+0:62: +0:68
+ let mut _16: usize; // in scope 0 at $DIR/slice_filter.rs:+0:62: +0:63
+ let mut _17: usize; // in scope 0 at $DIR/slice_filter.rs:+0:67: +0:68
+ let mut _18: bool; // in scope 0 at $DIR/slice_filter.rs:+0:72: +0:78
+ let mut _19: usize; // in scope 0 at $DIR/slice_filter.rs:+0:72: +0:73
+ let mut _20: usize; // in scope 0 at $DIR/slice_filter.rs:+0:77: +0:78
+ let mut _21: &(usize, usize, usize, usize); // in scope 0 at $DIR/slice_filter.rs:+0:26: +0:40
+ let mut _22: &(usize, usize, usize, usize); // in scope 0 at $DIR/slice_filter.rs:+0:26: +0:40
+ let mut _23: &(usize, usize, usize, usize); // in scope 0 at $DIR/slice_filter.rs:+0:26: +0:40
+ let mut _24: &(usize, usize, usize, usize); // in scope 0 at $DIR/slice_filter.rs:+0:26: +0:40
+ scope 1 {
+ debug a => _3; // in scope 1 at $DIR/slice_filter.rs:+0:29: +0:30
+ debug b => _4; // in scope 1 at $DIR/slice_filter.rs:+0:32: +0:33
+ debug c => _5; // in scope 1 at $DIR/slice_filter.rs:+0:35: +0:36
+ debug d => _6; // in scope 1 at $DIR/slice_filter.rs:+0:38: +0:39
+ }
+
+ bb0: {
+- StorageLive(_3); // scope 0 at $DIR/slice_filter.rs:+0:29: +0:30
+ _21 = deref_copy (*_2); // scope 0 at $DIR/slice_filter.rs:+0:29: +0:30
+ _3 = ((*_21).0: usize); // scope 0 at $DIR/slice_filter.rs:+0:29: +0:30
+- StorageLive(_4); // scope 0 at $DIR/slice_filter.rs:+0:32: +0:33
+ _22 = deref_copy (*_2); // scope 0 at $DIR/slice_filter.rs:+0:32: +0:33
+ _4 = ((*_22).1: usize); // scope 0 at $DIR/slice_filter.rs:+0:32: +0:33
+- StorageLive(_5); // scope 0 at $DIR/slice_filter.rs:+0:35: +0:36
+ _23 = deref_copy (*_2); // scope 0 at $DIR/slice_filter.rs:+0:35: +0:36
+ _5 = ((*_23).2: usize); // scope 0 at $DIR/slice_filter.rs:+0:35: +0:36
+- StorageLive(_6); // scope 0 at $DIR/slice_filter.rs:+0:38: +0:39
+ _24 = deref_copy (*_2); // scope 0 at $DIR/slice_filter.rs:+0:38: +0:39
+ _6 = ((*_24).3: usize); // scope 0 at $DIR/slice_filter.rs:+0:38: +0:39
+ StorageLive(_7); // scope 1 at $DIR/slice_filter.rs:+0:42: +0:58
+ StorageLive(_8); // scope 1 at $DIR/slice_filter.rs:+0:42: +0:48
+- StorageLive(_9); // scope 1 at $DIR/slice_filter.rs:+0:42: +0:43
+- _9 = _3; // scope 1 at $DIR/slice_filter.rs:+0:42: +0:43
+- StorageLive(_10); // scope 1 at $DIR/slice_filter.rs:+0:47: +0:48
+- _10 = _5; // scope 1 at $DIR/slice_filter.rs:+0:47: +0:48
+- _8 = Le(move _9, move _10); // scope 1 at $DIR/slice_filter.rs:+0:42: +0:48
+- StorageDead(_10); // scope 1 at $DIR/slice_filter.rs:+0:47: +0:48
+- StorageDead(_9); // scope 1 at $DIR/slice_filter.rs:+0:47: +0:48
++ _8 = Le(_3, _5); // scope 1 at $DIR/slice_filter.rs:+0:42: +0:48
+ switchInt(move _8) -> [0: bb4, otherwise: bb5]; // scope 1 at $DIR/slice_filter.rs:+0:42: +0:58
+ }
+
+ bb1: {
+ _0 = const true; // scope 1 at $DIR/slice_filter.rs:+0:42: +0:78
+ goto -> bb3; // scope 1 at $DIR/slice_filter.rs:+0:42: +0:78
+ }
+
+ bb2: {
+ StorageLive(_14); // scope 1 at $DIR/slice_filter.rs:+0:62: +0:78
+ StorageLive(_15); // scope 1 at $DIR/slice_filter.rs:+0:62: +0:68
+- StorageLive(_16); // scope 1 at $DIR/slice_filter.rs:+0:62: +0:63
+- _16 = _5; // scope 1 at $DIR/slice_filter.rs:+0:62: +0:63
+- StorageLive(_17); // scope 1 at $DIR/slice_filter.rs:+0:67: +0:68
+- _17 = _3; // scope 1 at $DIR/slice_filter.rs:+0:67: +0:68
+- _15 = Le(move _16, move _17); // scope 1 at $DIR/slice_filter.rs:+0:62: +0:68
+- StorageDead(_17); // scope 1 at $DIR/slice_filter.rs:+0:67: +0:68
+- StorageDead(_16); // scope 1 at $DIR/slice_filter.rs:+0:67: +0:68
++ _15 = Le(_5, _3); // scope 1 at $DIR/slice_filter.rs:+0:62: +0:68
+ switchInt(move _15) -> [0: bb6, otherwise: bb7]; // scope 1 at $DIR/slice_filter.rs:+0:62: +0:78
+ }
+
+ bb3: {
+ StorageDead(_14); // scope 1 at $DIR/slice_filter.rs:+0:77: +0:78
+ StorageDead(_7); // scope 1 at $DIR/slice_filter.rs:+0:77: +0:78
+- StorageDead(_6); // scope 0 at $DIR/slice_filter.rs:+0:77: +0:78
+- StorageDead(_5); // scope 0 at $DIR/slice_filter.rs:+0:77: +0:78
+- StorageDead(_4); // scope 0 at $DIR/slice_filter.rs:+0:77: +0:78
+- StorageDead(_3); // scope 0 at $DIR/slice_filter.rs:+0:77: +0:78
+ return; // scope 0 at $DIR/slice_filter.rs:+0:78: +0:78
+ }
+
+ bb4: {
+ _7 = const false; // scope 1 at $DIR/slice_filter.rs:+0:42: +0:58
+ StorageDead(_11); // scope 1 at $DIR/slice_filter.rs:+0:57: +0:58
+ StorageDead(_8); // scope 1 at $DIR/slice_filter.rs:+0:57: +0:58
+ goto -> bb2; // scope 1 at $DIR/slice_filter.rs:+0:42: +0:58
+ }
+
+ bb5: {
+ StorageLive(_11); // scope 1 at $DIR/slice_filter.rs:+0:52: +0:58
+- StorageLive(_12); // scope 1 at $DIR/slice_filter.rs:+0:52: +0:53
+- _12 = _6; // scope 1 at $DIR/slice_filter.rs:+0:52: +0:53
+- StorageLive(_13); // scope 1 at $DIR/slice_filter.rs:+0:57: +0:58
+- _13 = _4; // scope 1 at $DIR/slice_filter.rs:+0:57: +0:58
+- _11 = Le(move _12, move _13); // scope 1 at $DIR/slice_filter.rs:+0:52: +0:58
+- StorageDead(_13); // scope 1 at $DIR/slice_filter.rs:+0:57: +0:58
+- StorageDead(_12); // scope 1 at $DIR/slice_filter.rs:+0:57: +0:58
++ _11 = Le(_6, _4); // scope 1 at $DIR/slice_filter.rs:+0:52: +0:58
+ _7 = move _11; // scope 1 at $DIR/slice_filter.rs:+0:42: +0:58
+ StorageDead(_11); // scope 1 at $DIR/slice_filter.rs:+0:57: +0:58
+ StorageDead(_8); // scope 1 at $DIR/slice_filter.rs:+0:57: +0:58
+ switchInt(move _7) -> [0: bb2, otherwise: bb1]; // scope 1 at $DIR/slice_filter.rs:+0:42: +0:78
+ }
+
+ bb6: {
+ _14 = const false; // scope 1 at $DIR/slice_filter.rs:+0:62: +0:78
+ goto -> bb8; // scope 1 at $DIR/slice_filter.rs:+0:62: +0:78
+ }
+
+ bb7: {
+ StorageLive(_18); // scope 1 at $DIR/slice_filter.rs:+0:72: +0:78
+- StorageLive(_19); // scope 1 at $DIR/slice_filter.rs:+0:72: +0:73
+- _19 = _4; // scope 1 at $DIR/slice_filter.rs:+0:72: +0:73
+- StorageLive(_20); // scope 1 at $DIR/slice_filter.rs:+0:77: +0:78
+- _20 = _6; // scope 1 at $DIR/slice_filter.rs:+0:77: +0:78
+- _18 = Le(move _19, move _20); // scope 1 at $DIR/slice_filter.rs:+0:72: +0:78
+- StorageDead(_20); // scope 1 at $DIR/slice_filter.rs:+0:77: +0:78
+- StorageDead(_19); // scope 1 at $DIR/slice_filter.rs:+0:77: +0:78
++ _18 = Le(_4, _6); // scope 1 at $DIR/slice_filter.rs:+0:72: +0:78
+ _14 = move _18; // scope 1 at $DIR/slice_filter.rs:+0:62: +0:78
+ goto -> bb8; // scope 1 at $DIR/slice_filter.rs:+0:62: +0:78
+ }
+
+ bb8: {
+ StorageDead(_18); // scope 1 at $DIR/slice_filter.rs:+0:77: +0:78
+ StorageDead(_15); // scope 1 at $DIR/slice_filter.rs:+0:77: +0:78
+ _0 = move _14; // scope 1 at $DIR/slice_filter.rs:+0:42: +0:78
+ goto -> bb3; // scope 1 at $DIR/slice_filter.rs:+0:42: +0:78
+ }
+ }
+
diff --git a/tests/mir-opt/slice_filter.variant_b-{closure#0}.DestinationPropagation.diff b/tests/mir-opt/slice_filter.variant_b-{closure#0}.DestinationPropagation.diff
new file mode 100644
index 000000000..45af6600c
--- /dev/null
+++ b/tests/mir-opt/slice_filter.variant_b-{closure#0}.DestinationPropagation.diff
@@ -0,0 +1,109 @@
+- // MIR for `variant_b::{closure#0}` before DestinationPropagation
++ // MIR for `variant_b::{closure#0}` after DestinationPropagation
+
+ fn variant_b::{closure#0}(_1: &mut [closure@$DIR/slice_filter.rs:12:25: 12:41], _2: &&(usize, usize, usize, usize)) -> bool {
+ let mut _0: bool; // return place in scope 0 at $DIR/slice_filter.rs:+0:42: +0:42
+ let _3: usize; // in scope 0 at $DIR/slice_filter.rs:+0:29: +0:30
+ let _4: usize; // in scope 0 at $DIR/slice_filter.rs:+0:32: +0:33
+ let _5: usize; // in scope 0 at $DIR/slice_filter.rs:+0:35: +0:36
+ let _6: usize; // in scope 0 at $DIR/slice_filter.rs:+0:38: +0:39
+ let mut _7: bool; // in scope 0 at $DIR/slice_filter.rs:+0:42: +0:58
+ let mut _8: bool; // in scope 0 at $DIR/slice_filter.rs:+0:42: +0:48
+ let mut _9: bool; // in scope 0 at $DIR/slice_filter.rs:+0:52: +0:58
+ let mut _10: bool; // in scope 0 at $DIR/slice_filter.rs:+0:62: +0:78
+ let mut _11: bool; // in scope 0 at $DIR/slice_filter.rs:+0:62: +0:68
+ let mut _12: bool; // in scope 0 at $DIR/slice_filter.rs:+0:72: +0:78
+ let mut _13: &(usize, usize, usize, usize); // in scope 0 at $DIR/slice_filter.rs:+0:26: +0:40
+ let mut _14: &(usize, usize, usize, usize); // in scope 0 at $DIR/slice_filter.rs:+0:26: +0:40
+ let mut _15: &(usize, usize, usize, usize); // in scope 0 at $DIR/slice_filter.rs:+0:26: +0:40
+ let mut _16: &(usize, usize, usize, usize); // in scope 0 at $DIR/slice_filter.rs:+0:26: +0:40
+ scope 1 {
+ debug a => _3; // in scope 1 at $DIR/slice_filter.rs:+0:29: +0:30
+ debug b => _4; // in scope 1 at $DIR/slice_filter.rs:+0:32: +0:33
+ debug c => _5; // in scope 1 at $DIR/slice_filter.rs:+0:35: +0:36
+ debug d => _6; // in scope 1 at $DIR/slice_filter.rs:+0:38: +0:39
+ }
+
+ bb0: {
+ _13 = deref_copy (*_2); // scope 0 at $DIR/slice_filter.rs:+0:29: +0:30
+ _3 = ((*_13).0: usize); // scope 0 at $DIR/slice_filter.rs:+0:29: +0:30
+ _14 = deref_copy (*_2); // scope 0 at $DIR/slice_filter.rs:+0:32: +0:33
+ _4 = ((*_14).1: usize); // scope 0 at $DIR/slice_filter.rs:+0:32: +0:33
+ _15 = deref_copy (*_2); // scope 0 at $DIR/slice_filter.rs:+0:35: +0:36
+ _5 = ((*_15).2: usize); // scope 0 at $DIR/slice_filter.rs:+0:35: +0:36
+ _16 = deref_copy (*_2); // scope 0 at $DIR/slice_filter.rs:+0:38: +0:39
+ _6 = ((*_16).3: usize); // scope 0 at $DIR/slice_filter.rs:+0:38: +0:39
+- StorageLive(_7); // scope 1 at $DIR/slice_filter.rs:+0:42: +0:58
++ nop; // scope 1 at $DIR/slice_filter.rs:+0:42: +0:58
+ StorageLive(_8); // scope 1 at $DIR/slice_filter.rs:+0:42: +0:48
+ _8 = Le(_3, _5); // scope 1 at $DIR/slice_filter.rs:+0:42: +0:48
+ switchInt(move _8) -> [0: bb4, otherwise: bb5]; // scope 1 at $DIR/slice_filter.rs:+0:42: +0:58
+ }
+
+ bb1: {
+ _0 = const true; // scope 1 at $DIR/slice_filter.rs:+0:42: +0:78
+ goto -> bb3; // scope 1 at $DIR/slice_filter.rs:+0:42: +0:78
+ }
+
+ bb2: {
+- StorageLive(_10); // scope 1 at $DIR/slice_filter.rs:+0:62: +0:78
++ nop; // scope 1 at $DIR/slice_filter.rs:+0:62: +0:78
+ StorageLive(_11); // scope 1 at $DIR/slice_filter.rs:+0:62: +0:68
+ _11 = Le(_5, _3); // scope 1 at $DIR/slice_filter.rs:+0:62: +0:68
+ switchInt(move _11) -> [0: bb6, otherwise: bb7]; // scope 1 at $DIR/slice_filter.rs:+0:62: +0:78
+ }
+
+ bb3: {
+- StorageDead(_10); // scope 1 at $DIR/slice_filter.rs:+0:77: +0:78
+- StorageDead(_7); // scope 1 at $DIR/slice_filter.rs:+0:77: +0:78
++ nop; // scope 1 at $DIR/slice_filter.rs:+0:77: +0:78
++ nop; // scope 1 at $DIR/slice_filter.rs:+0:77: +0:78
+ return; // scope 0 at $DIR/slice_filter.rs:+0:78: +0:78
+ }
+
+ bb4: {
+- StorageDead(_9); // scope 1 at $DIR/slice_filter.rs:+0:57: +0:58
++ nop; // scope 1 at $DIR/slice_filter.rs:+0:57: +0:58
+ StorageDead(_8); // scope 1 at $DIR/slice_filter.rs:+0:57: +0:58
+ goto -> bb2; // scope 1 at $DIR/slice_filter.rs:+0:42: +0:58
+ }
+
+ bb5: {
+- StorageLive(_9); // scope 1 at $DIR/slice_filter.rs:+0:52: +0:58
++ nop; // scope 1 at $DIR/slice_filter.rs:+0:52: +0:58
+ _9 = Le(_6, _4); // scope 1 at $DIR/slice_filter.rs:+0:52: +0:58
+- _7 = move _9; // scope 1 at $DIR/slice_filter.rs:+0:42: +0:58
+- StorageDead(_9); // scope 1 at $DIR/slice_filter.rs:+0:57: +0:58
++ nop; // scope 1 at $DIR/slice_filter.rs:+0:42: +0:58
++ nop; // scope 1 at $DIR/slice_filter.rs:+0:57: +0:58
+ StorageDead(_8); // scope 1 at $DIR/slice_filter.rs:+0:57: +0:58
+- switchInt(move _7) -> [0: bb2, otherwise: bb1]; // scope 1 at $DIR/slice_filter.rs:+0:42: +0:78
++ switchInt(move _9) -> [0: bb2, otherwise: bb1]; // scope 1 at $DIR/slice_filter.rs:+0:42: +0:78
+ }
+
+ bb6: {
+- _10 = const false; // scope 1 at $DIR/slice_filter.rs:+0:62: +0:78
++ _0 = const false; // scope 1 at $DIR/slice_filter.rs:+0:62: +0:78
+ goto -> bb8; // scope 1 at $DIR/slice_filter.rs:+0:62: +0:78
+ }
+
+ bb7: {
+- StorageLive(_12); // scope 1 at $DIR/slice_filter.rs:+0:72: +0:78
+- _12 = Le(_4, _6); // scope 1 at $DIR/slice_filter.rs:+0:72: +0:78
+- _10 = move _12; // scope 1 at $DIR/slice_filter.rs:+0:62: +0:78
++ nop; // scope 1 at $DIR/slice_filter.rs:+0:72: +0:78
++ _0 = Le(_4, _6); // scope 1 at $DIR/slice_filter.rs:+0:72: +0:78
++ nop; // scope 1 at $DIR/slice_filter.rs:+0:62: +0:78
+ goto -> bb8; // scope 1 at $DIR/slice_filter.rs:+0:62: +0:78
+ }
+
+ bb8: {
+- StorageDead(_12); // scope 1 at $DIR/slice_filter.rs:+0:77: +0:78
++ nop; // scope 1 at $DIR/slice_filter.rs:+0:77: +0:78
+ StorageDead(_11); // scope 1 at $DIR/slice_filter.rs:+0:77: +0:78
+- _0 = move _10; // scope 1 at $DIR/slice_filter.rs:+0:42: +0:78
++ nop; // scope 1 at $DIR/slice_filter.rs:+0:42: +0:78
+ goto -> bb3; // scope 1 at $DIR/slice_filter.rs:+0:42: +0:78
+ }
+ }
+
diff --git a/tests/mir-opt/sroa.constant.ScalarReplacementOfAggregates.diff b/tests/mir-opt/sroa.constant.ScalarReplacementOfAggregates.diff
new file mode 100644
index 000000000..9e33215f2
--- /dev/null
+++ b/tests/mir-opt/sroa.constant.ScalarReplacementOfAggregates.diff
@@ -0,0 +1,46 @@
+- // MIR for `constant` before ScalarReplacementOfAggregates
++ // MIR for `constant` after ScalarReplacementOfAggregates
+
+ fn constant() -> () {
+ let mut _0: (); // return place in scope 0 at $DIR/sroa.rs:+0:15: +0:15
+ let _1: (usize, u8); // in scope 0 at $DIR/sroa.rs:+2:9: +2:10
++ let _4: usize; // in scope 0 at $DIR/sroa.rs:+2:9: +2:10
++ let _5: u8; // in scope 0 at $DIR/sroa.rs:+2:9: +2:10
+ scope 1 {
+- debug y => _1; // in scope 1 at $DIR/sroa.rs:+2:9: +2:10
++ debug y => (usize, u8){ .0 => _4, .1 => _5, }; // in scope 1 at $DIR/sroa.rs:+2:9: +2:10
+ let _2: usize; // in scope 1 at $DIR/sroa.rs:+3:9: +3:10
+ scope 2 {
+ debug t => _2; // in scope 2 at $DIR/sroa.rs:+3:9: +3:10
+ let _3: u8; // in scope 2 at $DIR/sroa.rs:+4:9: +4:10
+ scope 3 {
+ debug u => _3; // in scope 3 at $DIR/sroa.rs:+4:9: +4:10
+ }
+ }
+ }
+
+ bb0: {
+- StorageLive(_1); // scope 0 at $DIR/sroa.rs:+2:9: +2:10
++ StorageLive(_4); // scope 0 at $DIR/sroa.rs:+2:9: +2:10
++ StorageLive(_5); // scope 0 at $DIR/sroa.rs:+2:9: +2:10
++ nop; // scope 0 at $DIR/sroa.rs:+2:9: +2:10
+ _1 = const _; // scope 0 at $DIR/sroa.rs:+2:13: +2:14
++ _4 = move (_1.0: usize); // scope 1 at $DIR/sroa.rs:+3:9: +3:10
++ _5 = move (_1.1: u8); // scope 1 at $DIR/sroa.rs:+3:9: +3:10
+ StorageLive(_2); // scope 1 at $DIR/sroa.rs:+3:9: +3:10
+- _2 = (_1.0: usize); // scope 1 at $DIR/sroa.rs:+3:13: +3:16
++ _2 = _4; // scope 1 at $DIR/sroa.rs:+3:13: +3:16
+ StorageLive(_3); // scope 2 at $DIR/sroa.rs:+4:9: +4:10
+- _3 = (_1.1: u8); // scope 2 at $DIR/sroa.rs:+4:13: +4:16
++ _3 = _5; // scope 2 at $DIR/sroa.rs:+4:13: +4:16
+ _0 = const (); // scope 0 at $DIR/sroa.rs:+0:15: +5:2
+ StorageDead(_3); // scope 2 at $DIR/sroa.rs:+5:1: +5:2
+ StorageDead(_2); // scope 1 at $DIR/sroa.rs:+5:1: +5:2
+- StorageDead(_1); // scope 0 at $DIR/sroa.rs:+5:1: +5:2
++ StorageDead(_4); // scope 0 at $DIR/sroa.rs:+5:1: +5:2
++ StorageDead(_5); // scope 0 at $DIR/sroa.rs:+5:1: +5:2
++ nop; // scope 0 at $DIR/sroa.rs:+5:1: +5:2
+ return; // scope 0 at $DIR/sroa.rs:+5:2: +5:2
+ }
+ }
+
diff --git a/tests/mir-opt/sroa.copies.ScalarReplacementOfAggregates.diff b/tests/mir-opt/sroa.copies.ScalarReplacementOfAggregates.diff
new file mode 100644
index 000000000..976f6d44b
--- /dev/null
+++ b/tests/mir-opt/sroa.copies.ScalarReplacementOfAggregates.diff
@@ -0,0 +1,91 @@
+- // MIR for `copies` before ScalarReplacementOfAggregates
++ // MIR for `copies` after ScalarReplacementOfAggregates
+
+ fn copies(_1: Foo) -> () {
+ debug x => _1; // in scope 0 at $DIR/sroa.rs:+0:11: +0:12
+ let mut _0: (); // return place in scope 0 at $DIR/sroa.rs:+0:19: +0:19
+ let _2: Foo; // in scope 0 at $DIR/sroa.rs:+1:9: +1:10
++ let _11: u8; // in scope 0 at $DIR/sroa.rs:+1:9: +1:10
++ let _12: (); // in scope 0 at $DIR/sroa.rs:+1:9: +1:10
++ let _13: &str; // in scope 0 at $DIR/sroa.rs:+1:9: +1:10
++ let _14: std::option::Option<isize>; // in scope 0 at $DIR/sroa.rs:+1:9: +1:10
+ scope 1 {
+- debug y => _2; // in scope 1 at $DIR/sroa.rs:+1:9: +1:10
++ debug y => Foo{ .0 => _11, .1 => _12, .2 => _13, .3 => _14, }; // in scope 1 at $DIR/sroa.rs:+1:9: +1:10
+ let _3: u8; // in scope 1 at $DIR/sroa.rs:+2:9: +2:10
+ scope 2 {
+ debug t => _3; // in scope 2 at $DIR/sroa.rs:+2:9: +2:10
+ let _4: &str; // in scope 2 at $DIR/sroa.rs:+3:9: +3:10
+ scope 3 {
+ debug u => _4; // in scope 3 at $DIR/sroa.rs:+3:9: +3:10
+ let _5: Foo; // in scope 3 at $DIR/sroa.rs:+4:9: +4:10
++ let _7: u8; // in scope 3 at $DIR/sroa.rs:+4:9: +4:10
++ let _8: (); // in scope 3 at $DIR/sroa.rs:+4:9: +4:10
++ let _9: &str; // in scope 3 at $DIR/sroa.rs:+4:9: +4:10
++ let _10: std::option::Option<isize>; // in scope 3 at $DIR/sroa.rs:+4:9: +4:10
+ scope 4 {
+- debug z => _5; // in scope 4 at $DIR/sroa.rs:+4:9: +4:10
++ debug z => Foo{ .0 => _7, .1 => _8, .2 => _9, .3 => _10, }; // in scope 4 at $DIR/sroa.rs:+4:9: +4:10
+ let _6: (); // in scope 4 at $DIR/sroa.rs:+5:9: +5:10
+ scope 5 {
+ debug a => _6; // in scope 5 at $DIR/sroa.rs:+5:9: +5:10
+ }
+ }
+ }
+ }
+ }
+
+ bb0: {
+- StorageLive(_2); // scope 0 at $DIR/sroa.rs:+1:9: +1:10
+- _2 = _1; // scope 0 at $DIR/sroa.rs:+1:13: +1:14
++ StorageLive(_11); // scope 0 at $DIR/sroa.rs:+1:9: +1:10
++ StorageLive(_12); // scope 0 at $DIR/sroa.rs:+1:9: +1:10
++ StorageLive(_13); // scope 0 at $DIR/sroa.rs:+1:9: +1:10
++ StorageLive(_14); // scope 0 at $DIR/sroa.rs:+1:9: +1:10
++ nop; // scope 0 at $DIR/sroa.rs:+1:9: +1:10
++ _11 = (_1.0: u8); // scope 0 at $DIR/sroa.rs:+1:13: +1:14
++ _12 = (_1.1: ()); // scope 0 at $DIR/sroa.rs:+1:13: +1:14
++ _13 = (_1.2: &str); // scope 0 at $DIR/sroa.rs:+1:13: +1:14
++ _14 = (_1.3: std::option::Option<isize>); // scope 0 at $DIR/sroa.rs:+1:13: +1:14
++ nop; // scope 0 at $DIR/sroa.rs:+1:13: +1:14
+ StorageLive(_3); // scope 1 at $DIR/sroa.rs:+2:9: +2:10
+- _3 = (_2.0: u8); // scope 1 at $DIR/sroa.rs:+2:13: +2:16
++ _3 = _11; // scope 1 at $DIR/sroa.rs:+2:13: +2:16
+ StorageLive(_4); // scope 2 at $DIR/sroa.rs:+3:9: +3:10
+- _4 = (_2.2: &str); // scope 2 at $DIR/sroa.rs:+3:13: +3:16
+- StorageLive(_5); // scope 3 at $DIR/sroa.rs:+4:9: +4:10
+- _5 = _2; // scope 3 at $DIR/sroa.rs:+4:13: +4:14
++ _4 = _13; // scope 2 at $DIR/sroa.rs:+3:13: +3:16
++ StorageLive(_7); // scope 3 at $DIR/sroa.rs:+4:9: +4:10
++ StorageLive(_8); // scope 3 at $DIR/sroa.rs:+4:9: +4:10
++ StorageLive(_9); // scope 3 at $DIR/sroa.rs:+4:9: +4:10
++ StorageLive(_10); // scope 3 at $DIR/sroa.rs:+4:9: +4:10
++ nop; // scope 3 at $DIR/sroa.rs:+4:9: +4:10
++ _7 = _11; // scope 3 at $DIR/sroa.rs:+4:13: +4:14
++ _8 = _12; // scope 3 at $DIR/sroa.rs:+4:13: +4:14
++ _9 = _13; // scope 3 at $DIR/sroa.rs:+4:13: +4:14
++ _10 = _14; // scope 3 at $DIR/sroa.rs:+4:13: +4:14
++ nop; // scope 3 at $DIR/sroa.rs:+4:13: +4:14
+ StorageLive(_6); // scope 4 at $DIR/sroa.rs:+5:9: +5:10
+- _6 = (_5.1: ()); // scope 4 at $DIR/sroa.rs:+5:13: +5:16
++ _6 = _8; // scope 4 at $DIR/sroa.rs:+5:13: +5:16
+ _0 = const (); // scope 0 at $DIR/sroa.rs:+0:19: +6:2
+ StorageDead(_6); // scope 4 at $DIR/sroa.rs:+6:1: +6:2
+- StorageDead(_5); // scope 3 at $DIR/sroa.rs:+6:1: +6:2
++ StorageDead(_7); // scope 3 at $DIR/sroa.rs:+6:1: +6:2
++ StorageDead(_8); // scope 3 at $DIR/sroa.rs:+6:1: +6:2
++ StorageDead(_9); // scope 3 at $DIR/sroa.rs:+6:1: +6:2
++ StorageDead(_10); // scope 3 at $DIR/sroa.rs:+6:1: +6:2
++ nop; // scope 3 at $DIR/sroa.rs:+6:1: +6:2
+ StorageDead(_4); // scope 2 at $DIR/sroa.rs:+6:1: +6:2
+ StorageDead(_3); // scope 1 at $DIR/sroa.rs:+6:1: +6:2
+- StorageDead(_2); // scope 0 at $DIR/sroa.rs:+6:1: +6:2
++ StorageDead(_11); // scope 0 at $DIR/sroa.rs:+6:1: +6:2
++ StorageDead(_12); // scope 0 at $DIR/sroa.rs:+6:1: +6:2
++ StorageDead(_13); // scope 0 at $DIR/sroa.rs:+6:1: +6:2
++ StorageDead(_14); // scope 0 at $DIR/sroa.rs:+6:1: +6:2
++ nop; // scope 0 at $DIR/sroa.rs:+6:1: +6:2
+ return; // scope 0 at $DIR/sroa.rs:+6:2: +6:2
+ }
+ }
+
diff --git a/tests/mir-opt/sroa.dropping.ScalarReplacementOfAggregates.diff b/tests/mir-opt/sroa.dropping.ScalarReplacementOfAggregates.diff
index eb8830446..17a89e7d8 100644
--- a/tests/mir-opt/sroa.dropping.ScalarReplacementOfAggregates.diff
+++ b/tests/mir-opt/sroa.dropping.ScalarReplacementOfAggregates.diff
@@ -13,18 +13,12 @@
StorageLive(_1); // scope 0 at $DIR/sroa.rs:+1:5: +1:32
StorageLive(_2); // scope 0 at $DIR/sroa.rs:+1:5: +1:30
StorageLive(_3); // scope 0 at $DIR/sroa.rs:+1:7: +1:13
- Deinit(_3); // scope 0 at $DIR/sroa.rs:+1:7: +1:13
- (_3.0: usize) = const 0_usize; // scope 0 at $DIR/sroa.rs:+1:7: +1:13
+ _3 = Tag(const 0_usize); // scope 0 at $DIR/sroa.rs:+1:7: +1:13
StorageLive(_4); // scope 0 at $DIR/sroa.rs:+1:15: +1:21
- Deinit(_4); // scope 0 at $DIR/sroa.rs:+1:15: +1:21
- (_4.0: usize) = const 1_usize; // scope 0 at $DIR/sroa.rs:+1:15: +1:21
+ _4 = Tag(const 1_usize); // scope 0 at $DIR/sroa.rs:+1:15: +1:21
StorageLive(_5); // scope 0 at $DIR/sroa.rs:+1:23: +1:29
- Deinit(_5); // scope 0 at $DIR/sroa.rs:+1:23: +1:29
- (_5.0: usize) = const 2_usize; // scope 0 at $DIR/sroa.rs:+1:23: +1:29
- Deinit(_2); // scope 0 at $DIR/sroa.rs:+1:5: +1:30
- (_2.0: Tag) = move _3; // scope 0 at $DIR/sroa.rs:+1:5: +1:30
- (_2.1: Tag) = move _4; // scope 0 at $DIR/sroa.rs:+1:5: +1:30
- (_2.2: Tag) = move _5; // scope 0 at $DIR/sroa.rs:+1:5: +1:30
+ _5 = Tag(const 2_usize); // scope 0 at $DIR/sroa.rs:+1:23: +1:29
+ _2 = S(move _3, move _4, move _5); // scope 0 at $DIR/sroa.rs:+1:5: +1:30
StorageDead(_5); // scope 0 at $DIR/sroa.rs:+1:29: +1:30
StorageDead(_4); // scope 0 at $DIR/sroa.rs:+1:29: +1:30
StorageDead(_3); // scope 0 at $DIR/sroa.rs:+1:29: +1:30
diff --git a/tests/mir-opt/sroa.enums.ScalarReplacementOfAggregates.diff b/tests/mir-opt/sroa.enums.ScalarReplacementOfAggregates.diff
index a5488c1ec..04d26162a 100644
--- a/tests/mir-opt/sroa.enums.ScalarReplacementOfAggregates.diff
+++ b/tests/mir-opt/sroa.enums.ScalarReplacementOfAggregates.diff
@@ -16,9 +16,7 @@
StorageLive(_2); // scope 1 at $DIR/sroa.rs:+1:22: +1:29
StorageLive(_3); // scope 1 at $DIR/sroa.rs:+1:27: +1:28
_3 = _1; // scope 1 at $DIR/sroa.rs:+1:27: +1:28
- Deinit(_2); // scope 1 at $DIR/sroa.rs:+1:22: +1:29
- ((_2 as Some).0: usize) = move _3; // scope 1 at $DIR/sroa.rs:+1:22: +1:29
- discriminant(_2) = 1; // scope 1 at $DIR/sroa.rs:+1:22: +1:29
+ _2 = Option::<usize>::Some(move _3); // scope 1 at $DIR/sroa.rs:+1:22: +1:29
StorageDead(_3); // scope 1 at $DIR/sroa.rs:+1:28: +1:29
_4 = discriminant(_2); // scope 1 at $DIR/sroa.rs:+1:12: +1:19
switchInt(move _4) -> [1: bb1, otherwise: bb2]; // scope 1 at $DIR/sroa.rs:+1:12: +1:19
diff --git a/tests/mir-opt/sroa.escaping.ScalarReplacementOfAggregates.diff b/tests/mir-opt/sroa.escaping.ScalarReplacementOfAggregates.diff
index 64559b58f..fd691fdd1 100644
--- a/tests/mir-opt/sroa.escaping.ScalarReplacementOfAggregates.diff
+++ b/tests/mir-opt/sroa.escaping.ScalarReplacementOfAggregates.diff
@@ -3,45 +3,42 @@
fn escaping() -> () {
let mut _0: (); // return place in scope 0 at $DIR/sroa.rs:+0:19: +0:19
- let _1: (); // in scope 0 at $DIR/sroa.rs:+2:5: +2:42
- let mut _2: *const u32; // in scope 0 at $DIR/sroa.rs:+2:7: +2:41
- let _3: &u32; // in scope 0 at $DIR/sroa.rs:+2:7: +2:41
- let _4: Escaping; // in scope 0 at $DIR/sroa.rs:+2:8: +2:39
- let mut _5: u32; // in scope 0 at $DIR/sroa.rs:+2:34: +2:37
+ let _1: (); // in scope 0 at $DIR/sroa.rs:+1:5: +1:42
+ let mut _2: *const u32; // in scope 0 at $DIR/sroa.rs:+1:7: +1:41
+ let _3: &u32; // in scope 0 at $DIR/sroa.rs:+1:7: +1:41
+ let _4: Escaping; // in scope 0 at $DIR/sroa.rs:+1:8: +1:39
+ let mut _5: u32; // in scope 0 at $DIR/sroa.rs:+1:34: +1:37
bb0: {
- StorageLive(_1); // scope 0 at $DIR/sroa.rs:+2:5: +2:42
- StorageLive(_2); // scope 0 at $DIR/sroa.rs:+2:7: +2:41
- StorageLive(_3); // scope 0 at $DIR/sroa.rs:+2:7: +2:41
- StorageLive(_4); // scope 0 at $DIR/sroa.rs:+2:8: +2:39
- StorageLive(_5); // scope 0 at $DIR/sroa.rs:+2:34: +2:37
- _5 = g() -> bb1; // scope 0 at $DIR/sroa.rs:+2:34: +2:37
+ StorageLive(_1); // scope 0 at $DIR/sroa.rs:+1:5: +1:42
+ StorageLive(_2); // scope 0 at $DIR/sroa.rs:+1:7: +1:41
+ StorageLive(_3); // scope 0 at $DIR/sroa.rs:+1:7: +1:41
+ StorageLive(_4); // scope 0 at $DIR/sroa.rs:+1:8: +1:39
+ StorageLive(_5); // scope 0 at $DIR/sroa.rs:+1:34: +1:37
+ _5 = g() -> bb1; // scope 0 at $DIR/sroa.rs:+1:34: +1:37
// mir::Constant
// + span: $DIR/sroa.rs:78:34: 78:35
// + literal: Const { ty: fn() -> u32 {g}, val: Value(<ZST>) }
}
bb1: {
- Deinit(_4); // scope 0 at $DIR/sroa.rs:+2:8: +2:39
- (_4.0: u32) = const 1_u32; // scope 0 at $DIR/sroa.rs:+2:8: +2:39
- (_4.1: u32) = const 2_u32; // scope 0 at $DIR/sroa.rs:+2:8: +2:39
- (_4.2: u32) = move _5; // scope 0 at $DIR/sroa.rs:+2:8: +2:39
- StorageDead(_5); // scope 0 at $DIR/sroa.rs:+2:38: +2:39
- _3 = &(_4.0: u32); // scope 0 at $DIR/sroa.rs:+2:7: +2:41
- _2 = &raw const (*_3); // scope 0 at $DIR/sroa.rs:+2:7: +2:41
- _1 = f(move _2) -> bb2; // scope 0 at $DIR/sroa.rs:+2:5: +2:42
+ _4 = Escaping { a: const 1_u32, b: const 2_u32, c: move _5 }; // scope 0 at $DIR/sroa.rs:+1:8: +1:39
+ StorageDead(_5); // scope 0 at $DIR/sroa.rs:+1:38: +1:39
+ _3 = &(_4.0: u32); // scope 0 at $DIR/sroa.rs:+1:7: +1:41
+ _2 = &raw const (*_3); // scope 0 at $DIR/sroa.rs:+1:7: +1:41
+ _1 = f(move _2) -> bb2; // scope 0 at $DIR/sroa.rs:+1:5: +1:42
// mir::Constant
// + span: $DIR/sroa.rs:78:5: 78:6
// + literal: Const { ty: fn(*const u32) {f}, val: Value(<ZST>) }
}
bb2: {
- StorageDead(_2); // scope 0 at $DIR/sroa.rs:+2:41: +2:42
- StorageDead(_4); // scope 0 at $DIR/sroa.rs:+2:42: +2:43
- StorageDead(_3); // scope 0 at $DIR/sroa.rs:+2:42: +2:43
- StorageDead(_1); // scope 0 at $DIR/sroa.rs:+2:42: +2:43
- _0 = const (); // scope 0 at $DIR/sroa.rs:+0:19: +3:2
- return; // scope 0 at $DIR/sroa.rs:+3:2: +3:2
+ StorageDead(_2); // scope 0 at $DIR/sroa.rs:+1:41: +1:42
+ StorageDead(_4); // scope 0 at $DIR/sroa.rs:+1:42: +1:43
+ StorageDead(_3); // scope 0 at $DIR/sroa.rs:+1:42: +1:43
+ StorageDead(_1); // scope 0 at $DIR/sroa.rs:+1:42: +1:43
+ _0 = const (); // scope 0 at $DIR/sroa.rs:+0:19: +2:2
+ return; // scope 0 at $DIR/sroa.rs:+2:2: +2:2
}
}
diff --git a/tests/mir-opt/sroa.flat.ScalarReplacementOfAggregates.diff b/tests/mir-opt/sroa.flat.ScalarReplacementOfAggregates.diff
index d4c04d5e6..69631fc02 100644
--- a/tests/mir-opt/sroa.flat.ScalarReplacementOfAggregates.diff
+++ b/tests/mir-opt/sroa.flat.ScalarReplacementOfAggregates.diff
@@ -35,28 +35,20 @@
+ StorageLive(_9); // scope 0 at $DIR/sroa.rs:+1:30: +1:70
+ StorageLive(_10); // scope 0 at $DIR/sroa.rs:+1:30: +1:70
+ StorageLive(_11); // scope 0 at $DIR/sroa.rs:+1:30: +1:70
++ nop; // scope 0 at $DIR/sroa.rs:+1:30: +1:70
StorageLive(_6); // scope 0 at $DIR/sroa.rs:+1:45: +1:47
- Deinit(_6); // scope 0 at $DIR/sroa.rs:+1:45: +1:47
+ _6 = (); // scope 0 at $DIR/sroa.rs:+1:45: +1:47
StorageLive(_7); // scope 0 at $DIR/sroa.rs:+1:60: +1:68
- Deinit(_7); // scope 0 at $DIR/sroa.rs:+1:60: +1:68
- ((_7 as Some).0: isize) = const -4_isize; // scope 0 at $DIR/sroa.rs:+1:60: +1:68
- discriminant(_7) = 1; // scope 0 at $DIR/sroa.rs:+1:60: +1:68
-- Deinit(_5); // scope 0 at $DIR/sroa.rs:+1:30: +1:70
-- (_5.0: u8) = const 5_u8; // scope 0 at $DIR/sroa.rs:+1:30: +1:70
-- (_5.1: ()) = move _6; // scope 0 at $DIR/sroa.rs:+1:30: +1:70
-- (_5.2: &str) = const "a"; // scope 0 at $DIR/sroa.rs:+1:30: +1:70
-+ Deinit(_8); // scope 0 at $DIR/sroa.rs:+1:30: +1:70
-+ Deinit(_9); // scope 0 at $DIR/sroa.rs:+1:30: +1:70
-+ Deinit(_10); // scope 0 at $DIR/sroa.rs:+1:30: +1:70
-+ Deinit(_11); // scope 0 at $DIR/sroa.rs:+1:30: +1:70
+ _7 = Option::<isize>::Some(const -4_isize); // scope 0 at $DIR/sroa.rs:+1:60: +1:68
+- _5 = Foo { a: const 5_u8, b: move _6, c: const "a", d: move _7 }; // scope 0 at $DIR/sroa.rs:+1:30: +1:70
+ _8 = const 5_u8; // scope 0 at $DIR/sroa.rs:+1:30: +1:70
+ _9 = move _6; // scope 0 at $DIR/sroa.rs:+1:30: +1:70
+ _10 = const "a"; // scope 0 at $DIR/sroa.rs:+1:30: +1:70
// mir::Constant
- // + span: $DIR/sroa.rs:57:52: 57:55
+ // + span: $DIR/sroa.rs:53:52: 53:55
// + literal: Const { ty: &str, val: Value(Slice(..)) }
-- (_5.3: std::option::Option<isize>) = move _7; // scope 0 at $DIR/sroa.rs:+1:30: +1:70
+ _11 = move _7; // scope 0 at $DIR/sroa.rs:+1:30: +1:70
++ nop; // scope 0 at $DIR/sroa.rs:+1:30: +1:70
StorageDead(_7); // scope 0 at $DIR/sroa.rs:+1:69: +1:70
StorageDead(_6); // scope 0 at $DIR/sroa.rs:+1:69: +1:70
StorageLive(_1); // scope 0 at $DIR/sroa.rs:+1:15: +1:16
@@ -76,6 +68,7 @@
+ StorageDead(_9); // scope 0 at $DIR/sroa.rs:+1:70: +1:71
+ StorageDead(_10); // scope 0 at $DIR/sroa.rs:+1:70: +1:71
+ StorageDead(_11); // scope 0 at $DIR/sroa.rs:+1:70: +1:71
++ nop; // scope 0 at $DIR/sroa.rs:+1:70: +1:71
_0 = const (); // scope 0 at $DIR/sroa.rs:+0:15: +6:2
StorageDead(_4); // scope 0 at $DIR/sroa.rs:+6:1: +6:2
StorageDead(_3); // scope 0 at $DIR/sroa.rs:+6:1: +6:2
diff --git a/tests/mir-opt/sroa.ref_copies.ScalarReplacementOfAggregates.diff b/tests/mir-opt/sroa.ref_copies.ScalarReplacementOfAggregates.diff
new file mode 100644
index 000000000..f0d62220d
--- /dev/null
+++ b/tests/mir-opt/sroa.ref_copies.ScalarReplacementOfAggregates.diff
@@ -0,0 +1,56 @@
+- // MIR for `ref_copies` before ScalarReplacementOfAggregates
++ // MIR for `ref_copies` after ScalarReplacementOfAggregates
+
+ fn ref_copies(_1: &Foo) -> () {
+ debug x => _1; // in scope 0 at $DIR/sroa.rs:+0:15: +0:16
+ let mut _0: (); // return place in scope 0 at $DIR/sroa.rs:+0:24: +0:24
+ let _2: Foo; // in scope 0 at $DIR/sroa.rs:+1:9: +1:10
++ let _5: u8; // in scope 0 at $DIR/sroa.rs:+1:9: +1:10
++ let _6: (); // in scope 0 at $DIR/sroa.rs:+1:9: +1:10
++ let _7: &str; // in scope 0 at $DIR/sroa.rs:+1:9: +1:10
++ let _8: std::option::Option<isize>; // in scope 0 at $DIR/sroa.rs:+1:9: +1:10
+ scope 1 {
+- debug y => _2; // in scope 1 at $DIR/sroa.rs:+1:9: +1:10
++ debug y => Foo{ .0 => _5, .1 => _6, .2 => _7, .3 => _8, }; // in scope 1 at $DIR/sroa.rs:+1:9: +1:10
+ let _3: u8; // in scope 1 at $DIR/sroa.rs:+2:9: +2:10
+ scope 2 {
+ debug t => _3; // in scope 2 at $DIR/sroa.rs:+2:9: +2:10
+ let _4: &str; // in scope 2 at $DIR/sroa.rs:+3:9: +3:10
+ scope 3 {
+ debug u => _4; // in scope 3 at $DIR/sroa.rs:+3:9: +3:10
+ }
+ }
+ }
+
+ bb0: {
+- StorageLive(_2); // scope 0 at $DIR/sroa.rs:+1:9: +1:10
+- _2 = (*_1); // scope 0 at $DIR/sroa.rs:+1:13: +1:15
++ StorageLive(_5); // scope 0 at $DIR/sroa.rs:+1:9: +1:10
++ StorageLive(_6); // scope 0 at $DIR/sroa.rs:+1:9: +1:10
++ StorageLive(_7); // scope 0 at $DIR/sroa.rs:+1:9: +1:10
++ StorageLive(_8); // scope 0 at $DIR/sroa.rs:+1:9: +1:10
++ nop; // scope 0 at $DIR/sroa.rs:+1:9: +1:10
++ _5 = ((*_1).0: u8); // scope 0 at $DIR/sroa.rs:+1:13: +1:15
++ _6 = ((*_1).1: ()); // scope 0 at $DIR/sroa.rs:+1:13: +1:15
++ _7 = ((*_1).2: &str); // scope 0 at $DIR/sroa.rs:+1:13: +1:15
++ _8 = ((*_1).3: std::option::Option<isize>); // scope 0 at $DIR/sroa.rs:+1:13: +1:15
++ nop; // scope 0 at $DIR/sroa.rs:+1:13: +1:15
+ StorageLive(_3); // scope 1 at $DIR/sroa.rs:+2:9: +2:10
+- _3 = (_2.0: u8); // scope 1 at $DIR/sroa.rs:+2:13: +2:16
++ _3 = _5; // scope 1 at $DIR/sroa.rs:+2:13: +2:16
+ StorageLive(_4); // scope 2 at $DIR/sroa.rs:+3:9: +3:10
+- _4 = (_2.2: &str); // scope 2 at $DIR/sroa.rs:+3:13: +3:16
++ _4 = _7; // scope 2 at $DIR/sroa.rs:+3:13: +3:16
+ _0 = const (); // scope 0 at $DIR/sroa.rs:+0:24: +4:2
+ StorageDead(_4); // scope 2 at $DIR/sroa.rs:+4:1: +4:2
+ StorageDead(_3); // scope 1 at $DIR/sroa.rs:+4:1: +4:2
+- StorageDead(_2); // scope 0 at $DIR/sroa.rs:+4:1: +4:2
++ StorageDead(_5); // scope 0 at $DIR/sroa.rs:+4:1: +4:2
++ StorageDead(_6); // scope 0 at $DIR/sroa.rs:+4:1: +4:2
++ StorageDead(_7); // scope 0 at $DIR/sroa.rs:+4:1: +4:2
++ StorageDead(_8); // scope 0 at $DIR/sroa.rs:+4:1: +4:2
++ nop; // scope 0 at $DIR/sroa.rs:+4:1: +4:2
+ return; // scope 0 at $DIR/sroa.rs:+4:2: +4:2
+ }
+ }
+
diff --git a/tests/mir-opt/sroa.rs b/tests/mir-opt/sroa.rs
index ff8deb40d..fff92cf8d 100644
--- a/tests/mir-opt/sroa.rs
+++ b/tests/mir-opt/sroa.rs
@@ -12,17 +12,14 @@ impl Drop for Tag {
fn drop(&mut self) {}
}
-// EMIT_MIR sroa.dropping.ScalarReplacementOfAggregates.diff
pub fn dropping() {
S(Tag(0), Tag(1), Tag(2)).1;
}
-// EMIT_MIR sroa.enums.ScalarReplacementOfAggregates.diff
pub fn enums(a: usize) -> usize {
if let Some(a) = Some(a) { a } else { 0 }
}
-// EMIT_MIR sroa.structs.ScalarReplacementOfAggregates.diff
pub fn structs(a: f32) -> f32 {
struct U {
_foo: usize,
@@ -32,7 +29,6 @@ pub fn structs(a: f32) -> f32 {
U { _foo: 0, a }.a
}
-// EMIT_MIR sroa.unions.ScalarReplacementOfAggregates.diff
pub fn unions(a: f32) -> u32 {
union Repr {
f: f32,
@@ -41,6 +37,7 @@ pub fn unions(a: f32) -> u32 {
unsafe { Repr { f: a }.u }
}
+#[derive(Copy, Clone)]
struct Foo {
a: u8,
b: (),
@@ -52,7 +49,6 @@ fn g() -> u32 {
3
}
-// EMIT_MIR sroa.flat.ScalarReplacementOfAggregates.diff
pub fn flat() {
let Foo { a, b, c, d } = Foo { a: 5, b: (), c: "a", d: Some(-4) };
let _ = a;
@@ -72,12 +68,37 @@ fn f(a: *const u32) {
println!("{}", unsafe { *a.add(2) });
}
-// EMIT_MIR sroa.escaping.ScalarReplacementOfAggregates.diff
+// `f` uses the `&e.a` to access `e.c`. This is UB according to Miri today; however,
+// T-opsem has not finalized that decision and as such rustc should not rely on
+// it. If SROA were to rely on it, it would be (almost) correct to turn `e` into
+// three distinct locals - one for each field - and pass a reference to only one
+// of them to `f`. However, this would lead to a miscompilation because `b` and `c`
+// might no longer appear right after `a` in memory.
pub fn escaping() {
- // Verify this struct is not flattened.
f(&Escaping { a: 1, b: 2, c: g() }.a);
}
+fn copies(x: Foo) {
+ let y = x;
+ let t = y.a;
+ let u = y.c;
+ let z = y;
+ let a = z.b;
+}
+
+fn ref_copies(x: &Foo) {
+ let y = *x;
+ let t = y.a;
+ let u = y.c;
+}
+
+fn constant() {
+ const U: (usize, u8) = (5, 9);
+ let y = U;
+ let t = y.0;
+ let u = y.1;
+}
+
fn main() {
dropping();
enums(5);
@@ -85,4 +106,17 @@ fn main() {
unions(5.);
flat();
escaping();
+ copies(Foo { a: 5, b: (), c: "a", d: Some(-4) });
+ ref_copies(&Foo { a: 5, b: (), c: "a", d: Some(-4) });
+ constant();
}
+
+// EMIT_MIR sroa.dropping.ScalarReplacementOfAggregates.diff
+// EMIT_MIR sroa.enums.ScalarReplacementOfAggregates.diff
+// EMIT_MIR sroa.structs.ScalarReplacementOfAggregates.diff
+// EMIT_MIR sroa.unions.ScalarReplacementOfAggregates.diff
+// EMIT_MIR sroa.flat.ScalarReplacementOfAggregates.diff
+// EMIT_MIR sroa.escaping.ScalarReplacementOfAggregates.diff
+// EMIT_MIR sroa.copies.ScalarReplacementOfAggregates.diff
+// EMIT_MIR sroa.ref_copies.ScalarReplacementOfAggregates.diff
+// EMIT_MIR sroa.constant.ScalarReplacementOfAggregates.diff
diff --git a/tests/mir-opt/sroa.structs.ScalarReplacementOfAggregates.diff b/tests/mir-opt/sroa.structs.ScalarReplacementOfAggregates.diff
index 69d74c351..2c63d8b26 100644
--- a/tests/mir-opt/sroa.structs.ScalarReplacementOfAggregates.diff
+++ b/tests/mir-opt/sroa.structs.ScalarReplacementOfAggregates.diff
@@ -13,21 +13,20 @@
- StorageLive(_2); // scope 0 at $DIR/sroa.rs:+6:5: +6:21
+ StorageLive(_4); // scope 0 at $DIR/sroa.rs:+6:5: +6:21
+ StorageLive(_5); // scope 0 at $DIR/sroa.rs:+6:5: +6:21
++ nop; // scope 0 at $DIR/sroa.rs:+6:5: +6:21
StorageLive(_3); // scope 0 at $DIR/sroa.rs:+6:18: +6:19
_3 = _1; // scope 0 at $DIR/sroa.rs:+6:18: +6:19
-- Deinit(_2); // scope 0 at $DIR/sroa.rs:+6:5: +6:21
-- (_2.0: usize) = const 0_usize; // scope 0 at $DIR/sroa.rs:+6:5: +6:21
-- (_2.1: f32) = move _3; // scope 0 at $DIR/sroa.rs:+6:5: +6:21
-+ Deinit(_4); // scope 0 at $DIR/sroa.rs:+6:5: +6:21
-+ Deinit(_5); // scope 0 at $DIR/sroa.rs:+6:5: +6:21
+- _2 = U { _foo: const 0_usize, a: move _3 }; // scope 0 at $DIR/sroa.rs:+6:5: +6:21
+ _4 = const 0_usize; // scope 0 at $DIR/sroa.rs:+6:5: +6:21
+ _5 = move _3; // scope 0 at $DIR/sroa.rs:+6:5: +6:21
++ nop; // scope 0 at $DIR/sroa.rs:+6:5: +6:21
StorageDead(_3); // scope 0 at $DIR/sroa.rs:+6:20: +6:21
- _0 = (_2.1: f32); // scope 0 at $DIR/sroa.rs:+6:5: +6:23
- StorageDead(_2); // scope 0 at $DIR/sroa.rs:+7:1: +7:2
+ _0 = _5; // scope 0 at $DIR/sroa.rs:+6:5: +6:23
+ StorageDead(_4); // scope 0 at $DIR/sroa.rs:+7:1: +7:2
+ StorageDead(_5); // scope 0 at $DIR/sroa.rs:+7:1: +7:2
++ nop; // scope 0 at $DIR/sroa.rs:+7:1: +7:2
return; // scope 0 at $DIR/sroa.rs:+7:2: +7:2
}
}
diff --git a/tests/mir-opt/sroa.unions.ScalarReplacementOfAggregates.diff b/tests/mir-opt/sroa.unions.ScalarReplacementOfAggregates.diff
index 03ca976df..adfb01385 100644
--- a/tests/mir-opt/sroa.unions.ScalarReplacementOfAggregates.diff
+++ b/tests/mir-opt/sroa.unions.ScalarReplacementOfAggregates.diff
@@ -13,8 +13,7 @@
StorageLive(_2); // scope 1 at $DIR/sroa.rs:+5:14: +5:27
StorageLive(_3); // scope 1 at $DIR/sroa.rs:+5:24: +5:25
_3 = _1; // scope 1 at $DIR/sroa.rs:+5:24: +5:25
- Deinit(_2); // scope 1 at $DIR/sroa.rs:+5:14: +5:27
- (_2.0: f32) = move _3; // scope 1 at $DIR/sroa.rs:+5:14: +5:27
+ _2 = Repr { f: move _3 }; // scope 1 at $DIR/sroa.rs:+5:14: +5:27
StorageDead(_3); // scope 1 at $DIR/sroa.rs:+5:26: +5:27
_0 = (_2.1: u32); // scope 1 at $DIR/sroa.rs:+5:14: +5:29
StorageDead(_2); // scope 0 at $DIR/sroa.rs:+6:1: +6:2
diff --git a/tests/mir-opt/try_identity_e2e.new.PreCodegen.after.mir b/tests/mir-opt/try_identity_e2e.new.PreCodegen.after.mir
index b254bfeb7..b9cc10575 100644
--- a/tests/mir-opt/try_identity_e2e.new.PreCodegen.after.mir
+++ b/tests/mir-opt/try_identity_e2e.new.PreCodegen.after.mir
@@ -5,11 +5,11 @@ fn new(_1: Result<T, E>) -> Result<T, E> {
let mut _0: std::result::Result<T, E>; // return place in scope 0 at $DIR/try_identity_e2e.rs:+0:34: +0:46
let mut _2: std::ops::ControlFlow<E, T>; // in scope 0 at $DIR/try_identity_e2e.rs:+2:15: +7:10
let mut _3: isize; // in scope 0 at $DIR/try_identity_e2e.rs:+4:17: +4:22
- let mut _4: T; // in scope 0 at $DIR/try_identity_e2e.rs:+4:48: +4:49
- let mut _5: E; // in scope 0 at $DIR/try_identity_e2e.rs:+5:46: +5:47
+ let _4: T; // in scope 0 at $DIR/try_identity_e2e.rs:+4:20: +4:21
+ let _5: E; // in scope 0 at $DIR/try_identity_e2e.rs:+5:21: +5:22
let mut _6: isize; // in scope 0 at $DIR/try_identity_e2e.rs:+8:13: +8:37
let _7: T; // in scope 0 at $DIR/try_identity_e2e.rs:+8:35: +8:36
- let mut _8: E; // in scope 0 at $DIR/try_identity_e2e.rs:+9:49: +9:50
+ let _8: E; // in scope 0 at $DIR/try_identity_e2e.rs:+9:32: +9:33
scope 1 {
debug v => _4; // in scope 1 at $DIR/try_identity_e2e.rs:+4:20: +4:21
}
@@ -26,45 +26,40 @@ fn new(_1: Result<T, E>) -> Result<T, E> {
bb0: {
StorageLive(_2); // scope 0 at $DIR/try_identity_e2e.rs:+2:15: +7:10
_3 = discriminant(_1); // scope 0 at $DIR/try_identity_e2e.rs:+3:19: +3:20
- switchInt(move _3) -> [0: bb2, 1: bb1, otherwise: bb4]; // scope 0 at $DIR/try_identity_e2e.rs:+3:13: +3:20
+ switchInt(move _3) -> [0: bb2, 1: bb1, otherwise: bb5]; // scope 0 at $DIR/try_identity_e2e.rs:+3:13: +3:20
}
bb1: {
_5 = move ((_1 as Err).0: E); // scope 0 at $DIR/try_identity_e2e.rs:+5:21: +5:22
- Deinit(_2); // scope 2 at $DIR/try_identity_e2e.rs:+5:27: +5:48
- ((_2 as Break).0: E) = move _5; // scope 2 at $DIR/try_identity_e2e.rs:+5:27: +5:48
- discriminant(_2) = 1; // scope 2 at $DIR/try_identity_e2e.rs:+5:27: +5:48
- _6 = discriminant(_2); // scope 0 at $DIR/try_identity_e2e.rs:+2:15: +7:10
- switchInt(move _6) -> [0: bb5, 1: bb3, otherwise: bb4]; // scope 0 at $DIR/try_identity_e2e.rs:+2:9: +7:10
+ _2 = ControlFlow::<E, T>::Break(move _5); // scope 2 at $DIR/try_identity_e2e.rs:+5:27: +5:48
+ goto -> bb3; // scope 0 at $DIR/try_identity_e2e.rs:+5:47: +5:48
}
bb2: {
_4 = move ((_1 as Ok).0: T); // scope 0 at $DIR/try_identity_e2e.rs:+4:20: +4:21
- Deinit(_2); // scope 1 at $DIR/try_identity_e2e.rs:+4:26: +4:50
- ((_2 as Continue).0: T) = move _4; // scope 1 at $DIR/try_identity_e2e.rs:+4:26: +4:50
- discriminant(_2) = 0; // scope 1 at $DIR/try_identity_e2e.rs:+4:26: +4:50
- _6 = discriminant(_2); // scope 0 at $DIR/try_identity_e2e.rs:+2:15: +7:10
- switchInt(move _6) -> [0: bb5, 1: bb3, otherwise: bb4]; // scope 0 at $DIR/try_identity_e2e.rs:+2:9: +7:10
+ _2 = ControlFlow::<E, T>::Continue(move _4); // scope 1 at $DIR/try_identity_e2e.rs:+4:26: +4:50
+ goto -> bb3; // scope 0 at $DIR/try_identity_e2e.rs:+4:49: +4:50
}
bb3: {
+ _6 = discriminant(_2); // scope 0 at $DIR/try_identity_e2e.rs:+2:15: +7:10
+ switchInt(move _6) -> [0: bb6, 1: bb4, otherwise: bb5]; // scope 0 at $DIR/try_identity_e2e.rs:+2:9: +7:10
+ }
+
+ bb4: {
_8 = move ((_2 as Break).0: E); // scope 0 at $DIR/try_identity_e2e.rs:+9:32: +9:33
- Deinit(_0); // scope 4 at $DIR/try_identity_e2e.rs:+9:45: +9:51
- ((_0 as Err).0: E) = move _8; // scope 4 at $DIR/try_identity_e2e.rs:+9:45: +9:51
- discriminant(_0) = 1; // scope 4 at $DIR/try_identity_e2e.rs:+9:45: +9:51
+ _0 = Result::<T, E>::Err(move _8); // scope 4 at $DIR/try_identity_e2e.rs:+9:45: +9:51
StorageDead(_2); // scope 0 at $DIR/try_identity_e2e.rs:+12:1: +12:2
return; // scope 0 at $DIR/try_identity_e2e.rs:+12:1: +12:2
}
- bb4: {
+ bb5: {
unreachable; // scope 0 at $DIR/try_identity_e2e.rs:+2:15: +7:10
}
- bb5: {
+ bb6: {
_7 = move ((_2 as Continue).0: T); // scope 0 at $DIR/try_identity_e2e.rs:+8:35: +8:36
- Deinit(_0); // scope 0 at $DIR/try_identity_e2e.rs:+1:5: +11:6
- ((_0 as Ok).0: T) = move _7; // scope 0 at $DIR/try_identity_e2e.rs:+1:5: +11:6
- discriminant(_0) = 0; // scope 0 at $DIR/try_identity_e2e.rs:+1:5: +11:6
+ _0 = Result::<T, E>::Ok(move _7); // scope 0 at $DIR/try_identity_e2e.rs:+1:5: +11:6
StorageDead(_2); // scope 0 at $DIR/try_identity_e2e.rs:+12:1: +12:2
return; // scope 0 at $DIR/try_identity_e2e.rs:+12:1: +12:2
}
diff --git a/tests/mir-opt/try_identity_e2e.old.PreCodegen.after.mir b/tests/mir-opt/try_identity_e2e.old.PreCodegen.after.mir
index cdbc0681c..d88ae5ac9 100644
--- a/tests/mir-opt/try_identity_e2e.old.PreCodegen.after.mir
+++ b/tests/mir-opt/try_identity_e2e.old.PreCodegen.after.mir
@@ -5,7 +5,7 @@ fn old(_1: Result<T, E>) -> Result<T, E> {
let mut _0: std::result::Result<T, E>; // return place in scope 0 at $DIR/try_identity_e2e.rs:+0:34: +0:46
let mut _2: isize; // in scope 0 at $DIR/try_identity_e2e.rs:+3:13: +3:18
let _3: T; // in scope 0 at $DIR/try_identity_e2e.rs:+3:16: +3:17
- let mut _4: E; // in scope 0 at $DIR/try_identity_e2e.rs:+4:34: +4:35
+ let _4: E; // in scope 0 at $DIR/try_identity_e2e.rs:+4:17: +4:18
scope 1 {
debug v => _3; // in scope 1 at $DIR/try_identity_e2e.rs:+3:16: +3:17
}
@@ -20,9 +20,7 @@ fn old(_1: Result<T, E>) -> Result<T, E> {
bb1: {
_4 = move ((_1 as Err).0: E); // scope 0 at $DIR/try_identity_e2e.rs:+4:17: +4:18
- Deinit(_0); // scope 2 at $DIR/try_identity_e2e.rs:+4:30: +4:36
- ((_0 as Err).0: E) = move _4; // scope 2 at $DIR/try_identity_e2e.rs:+4:30: +4:36
- discriminant(_0) = 1; // scope 2 at $DIR/try_identity_e2e.rs:+4:30: +4:36
+ _0 = Result::<T, E>::Err(move _4); // scope 2 at $DIR/try_identity_e2e.rs:+4:30: +4:36
return; // scope 0 at $DIR/try_identity_e2e.rs:+7:1: +7:2
}
@@ -32,9 +30,7 @@ fn old(_1: Result<T, E>) -> Result<T, E> {
bb3: {
_3 = move ((_1 as Ok).0: T); // scope 0 at $DIR/try_identity_e2e.rs:+3:16: +3:17
- Deinit(_0); // scope 0 at $DIR/try_identity_e2e.rs:+1:5: +6:6
- ((_0 as Ok).0: T) = move _3; // scope 0 at $DIR/try_identity_e2e.rs:+1:5: +6:6
- discriminant(_0) = 0; // scope 0 at $DIR/try_identity_e2e.rs:+1:5: +6:6
+ _0 = Result::<T, E>::Ok(move _3); // scope 0 at $DIR/try_identity_e2e.rs:+1:5: +6:6
return; // scope 0 at $DIR/try_identity_e2e.rs:+7:1: +7:2
}
}
diff --git a/tests/mir-opt/uninhabited_enum_branching.main.SimplifyCfg-after-uninhabited-enum-branching.after.mir b/tests/mir-opt/uninhabited_enum_branching.main.SimplifyCfg-after-uninhabited-enum-branching.after.mir
index 39ec05277..03f37b14b 100644
--- a/tests/mir-opt/uninhabited_enum_branching.main.SimplifyCfg-after-uninhabited-enum-branching.after.mir
+++ b/tests/mir-opt/uninhabited_enum_branching.main.SimplifyCfg-after-uninhabited-enum-branching.after.mir
@@ -15,8 +15,7 @@ fn main() -> () {
bb0: {
StorageLive(_1); // scope 0 at $DIR/uninhabited_enum_branching.rs:+1:5: +5:6
StorageLive(_2); // scope 0 at $DIR/uninhabited_enum_branching.rs:+1:11: +1:19
- Deinit(_2); // scope 0 at $DIR/uninhabited_enum_branching.rs:+1:11: +1:19
- discriminant(_2) = 2; // scope 0 at $DIR/uninhabited_enum_branching.rs:+1:11: +1:19
+ _2 = Test1::C; // scope 0 at $DIR/uninhabited_enum_branching.rs:+1:11: +1:19
_3 = discriminant(_2); // scope 0 at $DIR/uninhabited_enum_branching.rs:+1:11: +1:19
switchInt(move _3) -> [2: bb1, otherwise: bb2]; // scope 0 at $DIR/uninhabited_enum_branching.rs:+1:5: +1:19
}
@@ -33,8 +32,7 @@ fn main() -> () {
StorageDead(_1); // scope 0 at $DIR/uninhabited_enum_branching.rs:+5:6: +5:7
StorageLive(_6); // scope 0 at $DIR/uninhabited_enum_branching.rs:+7:5: +10:6
StorageLive(_7); // scope 0 at $DIR/uninhabited_enum_branching.rs:+7:11: +7:19
- Deinit(_7); // scope 0 at $DIR/uninhabited_enum_branching.rs:+7:11: +7:19
- discriminant(_7) = 0; // scope 0 at $DIR/uninhabited_enum_branching.rs:+7:11: +7:19
+ _7 = Test2::D; // scope 0 at $DIR/uninhabited_enum_branching.rs:+7:11: +7:19
_8 = discriminant(_7); // scope 0 at $DIR/uninhabited_enum_branching.rs:+7:11: +7:19
switchInt(move _8) -> [4: bb5, 5: bb3, otherwise: bb4]; // scope 0 at $DIR/uninhabited_enum_branching.rs:+7:5: +7:19
}
diff --git a/tests/mir-opt/uninhabited_enum_branching.main.UninhabitedEnumBranching.diff b/tests/mir-opt/uninhabited_enum_branching.main.UninhabitedEnumBranching.diff
index 598413a1d..671e11622 100644
--- a/tests/mir-opt/uninhabited_enum_branching.main.UninhabitedEnumBranching.diff
+++ b/tests/mir-opt/uninhabited_enum_branching.main.UninhabitedEnumBranching.diff
@@ -16,8 +16,7 @@
bb0: {
StorageLive(_1); // scope 0 at $DIR/uninhabited_enum_branching.rs:+1:5: +5:6
StorageLive(_2); // scope 0 at $DIR/uninhabited_enum_branching.rs:+1:11: +1:19
- Deinit(_2); // scope 0 at $DIR/uninhabited_enum_branching.rs:+1:11: +1:19
- discriminant(_2) = 2; // scope 0 at $DIR/uninhabited_enum_branching.rs:+1:11: +1:19
+ _2 = Test1::C; // scope 0 at $DIR/uninhabited_enum_branching.rs:+1:11: +1:19
_3 = discriminant(_2); // scope 0 at $DIR/uninhabited_enum_branching.rs:+1:11: +1:19
- switchInt(move _3) -> [0: bb3, 1: bb4, 2: bb1, otherwise: bb2]; // scope 0 at $DIR/uninhabited_enum_branching.rs:+1:5: +1:19
+ switchInt(move _3) -> [2: bb1, otherwise: bb2]; // scope 0 at $DIR/uninhabited_enum_branching.rs:+1:5: +1:19
@@ -62,8 +61,7 @@
StorageDead(_1); // scope 0 at $DIR/uninhabited_enum_branching.rs:+5:6: +5:7
StorageLive(_6); // scope 0 at $DIR/uninhabited_enum_branching.rs:+7:5: +10:6
StorageLive(_7); // scope 0 at $DIR/uninhabited_enum_branching.rs:+7:11: +7:19
- Deinit(_7); // scope 0 at $DIR/uninhabited_enum_branching.rs:+7:11: +7:19
- discriminant(_7) = 0; // scope 0 at $DIR/uninhabited_enum_branching.rs:+7:11: +7:19
+ _7 = Test2::D; // scope 0 at $DIR/uninhabited_enum_branching.rs:+7:11: +7:19
_8 = discriminant(_7); // scope 0 at $DIR/uninhabited_enum_branching.rs:+7:11: +7:19
switchInt(move _8) -> [4: bb8, 5: bb6, otherwise: bb7]; // scope 0 at $DIR/uninhabited_enum_branching.rs:+7:5: +7:19
}
diff --git a/tests/mir-opt/uninhabited_enum_branching2.main.SimplifyCfg-after-uninhabited-enum-branching.after.mir b/tests/mir-opt/uninhabited_enum_branching2.main.SimplifyCfg-after-uninhabited-enum-branching.after.mir
index c8cd6f6c1..eb2a76ed1 100644
--- a/tests/mir-opt/uninhabited_enum_branching2.main.SimplifyCfg-after-uninhabited-enum-branching.after.mir
+++ b/tests/mir-opt/uninhabited_enum_branching2.main.SimplifyCfg-after-uninhabited-enum-branching.after.mir
@@ -22,11 +22,8 @@ fn main() -> () {
bb0: {
StorageLive(_1); // scope 0 at $DIR/uninhabited_enum_branching2.rs:+1:9: +1:13
StorageLive(_2); // scope 0 at $DIR/uninhabited_enum_branching2.rs:+1:38: +1:46
- Deinit(_2); // scope 0 at $DIR/uninhabited_enum_branching2.rs:+1:38: +1:46
- discriminant(_2) = 2; // scope 0 at $DIR/uninhabited_enum_branching2.rs:+1:38: +1:46
- Deinit(_1); // scope 0 at $DIR/uninhabited_enum_branching2.rs:+1:16: +1:48
- (_1.0: u32) = const 51_u32; // scope 0 at $DIR/uninhabited_enum_branching2.rs:+1:16: +1:48
- (_1.1: Test1) = move _2; // scope 0 at $DIR/uninhabited_enum_branching2.rs:+1:16: +1:48
+ _2 = Test1::C; // scope 0 at $DIR/uninhabited_enum_branching2.rs:+1:38: +1:46
+ _1 = Plop { xx: const 51_u32, test1: move _2 }; // scope 0 at $DIR/uninhabited_enum_branching2.rs:+1:16: +1:48
StorageDead(_2); // scope 0 at $DIR/uninhabited_enum_branching2.rs:+1:47: +1:48
StorageLive(_3); // scope 1 at $DIR/uninhabited_enum_branching2.rs:+3:5: +8:6
StorageLive(_4); // scope 1 at $DIR/uninhabited_enum_branching2.rs:+3:11: +3:22
diff --git a/tests/mir-opt/uninhabited_enum_branching2.main.UninhabitedEnumBranching.diff b/tests/mir-opt/uninhabited_enum_branching2.main.UninhabitedEnumBranching.diff
index 2aee6d268..4e797774d 100644
--- a/tests/mir-opt/uninhabited_enum_branching2.main.UninhabitedEnumBranching.diff
+++ b/tests/mir-opt/uninhabited_enum_branching2.main.UninhabitedEnumBranching.diff
@@ -23,11 +23,8 @@
bb0: {
StorageLive(_1); // scope 0 at $DIR/uninhabited_enum_branching2.rs:+1:9: +1:13
StorageLive(_2); // scope 0 at $DIR/uninhabited_enum_branching2.rs:+1:38: +1:46
- Deinit(_2); // scope 0 at $DIR/uninhabited_enum_branching2.rs:+1:38: +1:46
- discriminant(_2) = 2; // scope 0 at $DIR/uninhabited_enum_branching2.rs:+1:38: +1:46
- Deinit(_1); // scope 0 at $DIR/uninhabited_enum_branching2.rs:+1:16: +1:48
- (_1.0: u32) = const 51_u32; // scope 0 at $DIR/uninhabited_enum_branching2.rs:+1:16: +1:48
- (_1.1: Test1) = move _2; // scope 0 at $DIR/uninhabited_enum_branching2.rs:+1:16: +1:48
+ _2 = Test1::C; // scope 0 at $DIR/uninhabited_enum_branching2.rs:+1:38: +1:46
+ _1 = Plop { xx: const 51_u32, test1: move _2 }; // scope 0 at $DIR/uninhabited_enum_branching2.rs:+1:16: +1:48
StorageDead(_2); // scope 0 at $DIR/uninhabited_enum_branching2.rs:+1:47: +1:48
StorageLive(_3); // scope 1 at $DIR/uninhabited_enum_branching2.rs:+3:5: +8:6
StorageLive(_4); // scope 1 at $DIR/uninhabited_enum_branching2.rs:+3:11: +3:22
diff --git a/tests/mir-opt/unusual_item_types.Test-X-{constructor#0}.built.after.mir b/tests/mir-opt/unusual_item_types.Test-X-{constructor#0}.built.after.mir
index ee0296763..8b271135c 100644
--- a/tests/mir-opt/unusual_item_types.Test-X-{constructor#0}.built.after.mir
+++ b/tests/mir-opt/unusual_item_types.Test-X-{constructor#0}.built.after.mir
@@ -4,9 +4,7 @@ fn Test::X(_1: usize) -> Test {
let mut _0: Test; // return place in scope 0 at $DIR/unusual_item_types.rs:+0:5: +0:6
bb0: {
- Deinit(_0); // scope 0 at $DIR/unusual_item_types.rs:+0:5: +0:6
- ((_0 as X).0: usize) = move _1; // scope 0 at $DIR/unusual_item_types.rs:+0:5: +0:6
- discriminant(_0) = 0; // scope 0 at $DIR/unusual_item_types.rs:+0:5: +0:6
+ _0 = Test::X(move _1); // scope 0 at $DIR/unusual_item_types.rs:+0:5: +0:6
return; // scope 0 at $DIR/unusual_item_types.rs:+0:5: +0:6
}
}
diff --git a/tests/mir-opt/while_let_loops.change_loop_body.ConstProp.diff b/tests/mir-opt/while_let_loops.change_loop_body.ConstProp.diff
index bb1de59d4..a4f2d8c84 100644
--- a/tests/mir-opt/while_let_loops.change_loop_body.ConstProp.diff
+++ b/tests/mir-opt/while_let_loops.change_loop_body.ConstProp.diff
@@ -16,8 +16,7 @@
StorageLive(_1); // scope 0 at $DIR/while_let_loops.rs:+1:9: +1:15
_1 = const 0_i32; // scope 0 at $DIR/while_let_loops.rs:+1:18: +1:19
StorageLive(_2); // scope 2 at $DIR/while_let_loops.rs:+2:28: +2:32
- Deinit(_2); // scope 2 at $DIR/while_let_loops.rs:+2:28: +2:32
- discriminant(_2) = 0; // scope 2 at $DIR/while_let_loops.rs:+2:28: +2:32
+ _2 = Option::<u32>::None; // scope 2 at $DIR/while_let_loops.rs:+2:28: +2:32
- _3 = discriminant(_2); // scope 2 at $DIR/while_let_loops.rs:+2:15: +2:25
- switchInt(move _3) -> [1: bb1, otherwise: bb3]; // scope 2 at $DIR/while_let_loops.rs:+2:15: +2:25
+ _3 = const 0_isize; // scope 2 at $DIR/while_let_loops.rs:+2:15: +2:25
diff --git a/tests/mir-opt/while_storage.while_loop.PreCodegen.after.mir b/tests/mir-opt/while_storage.while_loop.PreCodegen.after.mir
index b95d91b13..318119bd4 100644
--- a/tests/mir-opt/while_storage.while_loop.PreCodegen.after.mir
+++ b/tests/mir-opt/while_storage.while_loop.PreCodegen.after.mir
@@ -4,9 +4,7 @@ fn while_loop(_1: bool) -> () {
debug c => _1; // in scope 0 at $DIR/while_storage.rs:+0:15: +0:16
let mut _0: (); // return place in scope 0 at $DIR/while_storage.rs:+0:24: +0:24
let mut _2: bool; // in scope 0 at $DIR/while_storage.rs:+1:11: +1:22
- let mut _3: bool; // in scope 0 at $DIR/while_storage.rs:+1:20: +1:21
- let mut _4: bool; // in scope 0 at $DIR/while_storage.rs:+2:12: +2:23
- let mut _5: bool; // in scope 0 at $DIR/while_storage.rs:+2:21: +2:22
+ let mut _3: bool; // in scope 0 at $DIR/while_storage.rs:+2:12: +2:23
bb0: {
goto -> bb1; // scope 0 at $DIR/while_storage.rs:+1:5: +5:6
@@ -14,41 +12,35 @@ fn while_loop(_1: bool) -> () {
bb1: {
StorageLive(_2); // scope 0 at $DIR/while_storage.rs:+1:11: +1:22
- StorageLive(_3); // scope 0 at $DIR/while_storage.rs:+1:20: +1:21
- _3 = _1; // scope 0 at $DIR/while_storage.rs:+1:20: +1:21
- _2 = get_bool(move _3) -> bb2; // scope 0 at $DIR/while_storage.rs:+1:11: +1:22
+ _2 = get_bool(_1) -> bb2; // scope 0 at $DIR/while_storage.rs:+1:11: +1:22
// mir::Constant
// + span: $DIR/while_storage.rs:10:11: 10:19
// + literal: Const { ty: fn(bool) -> bool {get_bool}, val: Value(<ZST>) }
}
bb2: {
- StorageDead(_3); // scope 0 at $DIR/while_storage.rs:+1:21: +1:22
switchInt(move _2) -> [0: bb7, otherwise: bb3]; // scope 0 at $DIR/while_storage.rs:+1:11: +1:22
}
bb3: {
- StorageLive(_4); // scope 0 at $DIR/while_storage.rs:+2:12: +2:23
- StorageLive(_5); // scope 0 at $DIR/while_storage.rs:+2:21: +2:22
- _5 = _1; // scope 0 at $DIR/while_storage.rs:+2:21: +2:22
- _4 = get_bool(move _5) -> bb4; // scope 0 at $DIR/while_storage.rs:+2:12: +2:23
+ StorageLive(_3); // scope 0 at $DIR/while_storage.rs:+2:12: +2:23
+ _3 = get_bool(_1) -> bb4; // scope 0 at $DIR/while_storage.rs:+2:12: +2:23
// mir::Constant
// + span: $DIR/while_storage.rs:11:12: 11:20
// + literal: Const { ty: fn(bool) -> bool {get_bool}, val: Value(<ZST>) }
}
bb4: {
- StorageDead(_5); // scope 0 at $DIR/while_storage.rs:+2:22: +2:23
- switchInt(move _4) -> [0: bb6, otherwise: bb5]; // scope 0 at $DIR/while_storage.rs:+2:12: +2:23
+ switchInt(move _3) -> [0: bb6, otherwise: bb5]; // scope 0 at $DIR/while_storage.rs:+2:12: +2:23
}
bb5: {
- StorageDead(_4); // scope 0 at $DIR/while_storage.rs:+4:9: +4:10
+ StorageDead(_3); // scope 0 at $DIR/while_storage.rs:+4:9: +4:10
goto -> bb7; // scope 0 at no-location
}
bb6: {
- StorageDead(_4); // scope 0 at $DIR/while_storage.rs:+4:9: +4:10
+ StorageDead(_3); // scope 0 at $DIR/while_storage.rs:+4:9: +4:10
StorageDead(_2); // scope 0 at $DIR/while_storage.rs:+5:5: +5:6
goto -> bb1; // scope 0 at $DIR/while_storage.rs:+1:5: +5:6
}
diff --git a/tests/pretty/dollar-crate.pp b/tests/pretty/dollar-crate.pp
index 3af37955f..60fddb630 100644
--- a/tests/pretty/dollar-crate.pp
+++ b/tests/pretty/dollar-crate.pp
@@ -8,6 +8,4 @@ extern crate std;
// pretty-mode:expanded
// pp-exact:dollar-crate.pp
-fn main() {
- { ::std::io::_print(::core::fmt::Arguments::new_v1(&["rust\n"], &[])); };
-}
+fn main() { { ::std::io::_print(format_args!("rust\n")); }; }
diff --git a/tests/pretty/issue-4264.pp b/tests/pretty/issue-4264.pp
index 18e6d75b1..e0fa1fe28 100644
--- a/tests/pretty/issue-4264.pp
+++ b/tests/pretty/issue-4264.pp
@@ -32,12 +32,13 @@ fn bar() ({
({
let res =
((::alloc::fmt::format as
- for<'a> fn(Arguments<'a>) -> String {format})(((::core::fmt::Arguments::new_v1
+ for<'a> fn(Arguments<'a>) -> String {format})(((<#[lang = "format_arguments"]>::new_v1
as
- fn(&[&'static str], &[ArgumentV1<'_>]) -> Arguments<'_> {Arguments::<'_>::new_v1})((&([("test"
+ fn(&[&'static str], &[core::fmt::ArgumentV1<'_>]) -> Arguments<'_> {Arguments::<'_>::new_v1})((&([("test"
as &str)] as [&str; 1]) as &[&str; 1]),
- (&([] as [ArgumentV1<'_>; 0]) as &[ArgumentV1<'_>; 0])) as
- Arguments<'_>)) as String);
+ (&([] as [core::fmt::ArgumentV1<'_>; 0]) as
+ &[core::fmt::ArgumentV1<'_>; 0])) as Arguments<'_>)) as
+ String);
(res as String)
} as String);
} as ())
diff --git a/tests/run-make-fulldeps/hotplug_codegen_backend/the_backend.rs b/tests/run-make-fulldeps/hotplug_codegen_backend/the_backend.rs
index 3aa57d589..8dac53c2a 100644
--- a/tests/run-make-fulldeps/hotplug_codegen_backend/the_backend.rs
+++ b/tests/run-make-fulldeps/hotplug_codegen_backend/the_backend.rs
@@ -27,6 +27,8 @@ use std::any::Any;
struct TheBackend;
impl CodegenBackend for TheBackend {
+ fn locale_resource(&self) -> &'static str { "" }
+
fn codegen_crate<'a, 'tcx>(
&self,
tcx: TyCtxt<'tcx>,
diff --git a/tests/run-make-fulldeps/issue-19371/foo.rs b/tests/run-make-fulldeps/issue-19371/foo.rs
index 5bb38fc02..53ec79e47 100644
--- a/tests/run-make-fulldeps/issue-19371/foo.rs
+++ b/tests/run-make-fulldeps/issue-19371/foo.rs
@@ -53,6 +53,7 @@ fn compile(code: String, output: PathBuf, sysroot: PathBuf) {
output_file: Some(output),
output_dir: None,
file_loader: None,
+ locale_resources: &[],
lint_caps: Default::default(),
parse_sess_created: None,
register_lints: None,
diff --git a/tests/run-make-fulldeps/issues-41478-43796/Makefile b/tests/run-make-fulldeps/issues-41478-43796/Makefile
deleted file mode 100644
index e451cb031..000000000
--- a/tests/run-make-fulldeps/issues-41478-43796/Makefile
+++ /dev/null
@@ -1,8 +0,0 @@
-include ../tools.mk
-
-all:
- # Work in /tmp, because we need to create the `save-analysis-temp` folder.
- cp a.rs $(TMPDIR)/
- cd $(TMPDIR) && $(RUSTC) -Zsave-analysis $(TMPDIR)/a.rs 2> $(TMPDIR)/stderr.txt || ( cat $(TMPDIR)/stderr.txt && exit 1 )
- [ ! -s $(TMPDIR)/stderr.txt ] || ( cat $(TMPDIR)/stderr.txt && exit 1 )
- [ -f $(TMPDIR)/save-analysis/liba.json ] || ( ls -la $(TMPDIR) && exit 1 )
diff --git a/tests/run-make-fulldeps/issues-41478-43796/a.rs b/tests/run-make-fulldeps/issues-41478-43796/a.rs
deleted file mode 100644
index b072235b5..000000000
--- a/tests/run-make-fulldeps/issues-41478-43796/a.rs
+++ /dev/null
@@ -1,9 +0,0 @@
-#![crate_type = "lib"]
-pub struct V<S>(#[allow(unused_tuple_struct_fields)] S);
-pub trait An {
- type U;
-}
-pub trait F<A> {
-}
-impl<A: An> F<A> for V<<A as An>::U> {
-}
diff --git a/tests/run-make-fulldeps/save-analysis-fail/Makefile b/tests/run-make-fulldeps/save-analysis-fail/Makefile
deleted file mode 100644
index 69a2b2746..000000000
--- a/tests/run-make-fulldeps/save-analysis-fail/Makefile
+++ /dev/null
@@ -1,6 +0,0 @@
-include ../tools.mk
-all: code
-krate2: krate2.rs
- $(RUSTC) $<
-code: foo.rs krate2
- $(RUSTC) foo.rs -Zsave-analysis || exit 0
diff --git a/tests/run-make-fulldeps/save-analysis-fail/SameDir.rs b/tests/run-make-fulldeps/save-analysis-fail/SameDir.rs
deleted file mode 100644
index 2c690d5f7..000000000
--- a/tests/run-make-fulldeps/save-analysis-fail/SameDir.rs
+++ /dev/null
@@ -1,5 +0,0 @@
-// sub-module in the same directory as the main crate file
-
-pub struct SameStruct {
- pub name: String
-}
diff --git a/tests/run-make-fulldeps/save-analysis-fail/SameDir3.rs b/tests/run-make-fulldeps/save-analysis-fail/SameDir3.rs
deleted file mode 100644
index fab03ee2e..000000000
--- a/tests/run-make-fulldeps/save-analysis-fail/SameDir3.rs
+++ /dev/null
@@ -1,3 +0,0 @@
-pub fn hello(x: isize) {
- println!("macro {} :-(", x);
-}
diff --git a/tests/run-make-fulldeps/save-analysis-fail/SubDir/mod.rs b/tests/run-make-fulldeps/save-analysis-fail/SubDir/mod.rs
deleted file mode 100644
index 511721d92..000000000
--- a/tests/run-make-fulldeps/save-analysis-fail/SubDir/mod.rs
+++ /dev/null
@@ -1,27 +0,0 @@
-// sub-module in a sub-directory
-
-use sub::sub2 as msalias;
-use sub::sub2;
-
-static yy: usize = 25;
-
-mod sub {
- pub mod sub2 {
- pub mod sub3 {
- pub fn hello() {
- println!("hello from module 3");
- }
- }
- pub fn hello() {
- println!("hello from a module");
- }
-
- pub struct nested_struct {
- pub field2: u32,
- }
- }
-}
-
-pub struct SubStruct {
- pub name: String
-}
diff --git a/tests/run-make-fulldeps/save-analysis-fail/foo.rs b/tests/run-make-fulldeps/save-analysis-fail/foo.rs
deleted file mode 100644
index c5a70605e..000000000
--- a/tests/run-make-fulldeps/save-analysis-fail/foo.rs
+++ /dev/null
@@ -1,463 +0,0 @@
-#![crate_name = "test"]
-#![feature(rustc_private)]
-
-extern crate rustc_graphviz;
-// A simple rust project
-
-extern crate krate2;
-extern crate krate2 as krate3;
-
-use rustc_graphviz::RenderOption;
-use std::cell::RefCell;
-use std::collections::{HashMap, HashSet};
-use std::io::Write;
-
-use sub::sub2 as msalias;
-use sub::sub2;
-use sub::sub2::nested_struct as sub_struct;
-
-use std::mem::size_of;
-
-use std::char::from_u32;
-
-static uni: &'static str = "Les Miséééééééérables";
-static yy: usize = 25;
-
-static bob: Option<graphviz::RenderOption> = None;
-
-// buglink test - see issue #1337.
-
-fn test_alias<I: Iterator>(i: Option<<I as Iterator>::Item>) {
- let s = sub_struct { field2: 45u32 };
-
- // import tests
- fn foo(x: &Write) {}
- let _: Option<_> = from_u32(45);
-
- let x = 42usize;
-
- krate2::hello();
- krate3::hello();
-
- let x = (3isize, 4usize);
- let y = x.1;
-}
-
-// Issue #37700
-const LUT_BITS: usize = 3;
-pub struct HuffmanTable {
- ac_lut: Option<[(i16, u8); 1 << LUT_BITS]>,
-}
-
-struct TupStruct(isize, isize, Box<str>);
-
-fn test_tup_struct(x: TupStruct) -> isize {
- x.1
-}
-
-fn println(s: &str) {
- std::io::stdout().write_all(s.as_bytes());
-}
-
-mod sub {
- pub mod sub2 {
- use std::io::Write;
- pub mod sub3 {
- use std::io::Write;
- pub fn hello() {
- ::println("hello from module 3");
- }
- }
- pub fn hello() {
- ::println("hello from a module");
- }
-
- pub struct nested_struct {
- pub field2: u32,
- }
-
- pub enum nested_enum {
- Nest2 = 2,
- Nest3 = 3,
- }
- }
-}
-
-pub mod SameDir;
-pub mod SubDir;
-
-#[path = "SameDir3.rs"]
-pub mod SameDir2;
-
-struct nofields;
-
-#[derive(Clone)]
-struct some_fields {
- field1: u32,
-}
-
-type SF = some_fields;
-
-trait SuperTrait {
- fn qux(&self) {
- panic!();
- }
-}
-
-trait SomeTrait: SuperTrait {
- fn Method(&self, x: u32) -> u32;
-
- fn prov(&self, x: u32) -> u32 {
- println(&x.to_string());
- 42
- }
- fn provided_method(&self) -> u32 {
- 42
- }
-}
-
-trait SubTrait: SomeTrait {
- fn stat2(x: &Self) -> u32 {
- 32
- }
-}
-
-trait SizedTrait: Sized {}
-
-fn error(s: &SizedTrait) {
- let foo = 42;
- println!("Hello world! {}", foo);
-}
-
-impl SomeTrait for some_fields {
- fn Method(&self, x: u32) -> u32 {
- println(&x.to_string());
- self.field1
- }
-}
-
-impl SuperTrait for some_fields {}
-
-impl SubTrait for some_fields {}
-
-impl some_fields {
- fn stat(x: u32) -> u32 {
- println(&x.to_string());
- 42
- }
- fn stat2(x: &some_fields) -> u32 {
- 42
- }
-
- fn align_to<T>(&mut self) {}
-
- fn test(&mut self) {
- self.align_to::<bool>();
- }
-}
-
-impl SuperTrait for nofields {}
-impl SomeTrait for nofields {
- fn Method(&self, x: u32) -> u32 {
- self.Method(x);
- 43
- }
-
- fn provided_method(&self) -> u32 {
- 21
- }
-}
-
-impl SubTrait for nofields {}
-
-impl SuperTrait for (Box<nofields>, Box<some_fields>) {}
-
-fn f_with_params<T: SomeTrait>(x: &T) {
- x.Method(41);
-}
-
-type MyType = Box<some_fields>;
-
-enum SomeEnum<'a> {
- Ints(isize, isize),
- Floats(f64, f64),
- Strings(&'a str, &'a str, &'a str),
- MyTypes(MyType, MyType),
-}
-
-#[derive(Copy, Clone)]
-enum SomeOtherEnum {
- SomeConst1,
- SomeConst2,
- SomeConst3,
-}
-
-enum SomeStructEnum {
- EnumStruct { a: isize, b: isize },
- EnumStruct2 { f1: MyType, f2: MyType },
- EnumStruct3 { f1: MyType, f2: MyType, f3: SomeEnum<'static> },
-}
-
-fn matchSomeEnum(val: SomeEnum) {
- match val {
- SomeEnum::Ints(int1, int2) => {
- println(&(int1 + int2).to_string());
- }
- SomeEnum::Floats(float1, float2) => {
- println(&(float2 * float1).to_string());
- }
- SomeEnum::Strings(.., s3) => {
- println(s3);
- }
- SomeEnum::MyTypes(mt1, mt2) => {
- println(&(mt1.field1 - mt2.field1).to_string());
- }
- }
-}
-
-fn matchSomeStructEnum(se: SomeStructEnum) {
- match se {
- SomeStructEnum::EnumStruct { a: a, .. } => println(&a.to_string()),
- SomeStructEnum::EnumStruct2 { f1: f1, f2: f_2 } => println(&f_2.field1.to_string()),
- SomeStructEnum::EnumStruct3 { f1, .. } => println(&f1.field1.to_string()),
- }
-}
-
-fn matchSomeStructEnum2(se: SomeStructEnum) {
- use SomeStructEnum::*;
- match se {
- EnumStruct { a: ref aaa, .. } => println(&aaa.to_string()),
- EnumStruct2 { f1, f2: f2 } => println(&f1.field1.to_string()),
- EnumStruct3 { f1, f3: SomeEnum::Ints(..), f2 } => println(&f1.field1.to_string()),
- _ => {}
- }
-}
-
-fn matchSomeOtherEnum(val: SomeOtherEnum) {
- use SomeOtherEnum::{SomeConst2, SomeConst3};
- match val {
- SomeOtherEnum::SomeConst1 => {
- println("I'm const1.");
- }
- SomeConst2 | SomeConst3 => {
- println("I'm const2 or const3.");
- }
- }
-}
-
-fn hello<X: SomeTrait>((z, a): (u32, String), ex: X) {
- SameDir2::hello(43);
-
- println(&yy.to_string());
- let (x, y): (u32, u32) = (5, 3);
- println(&x.to_string());
- println(&z.to_string());
- let x: u32 = x;
- println(&x.to_string());
- let x = "hello";
- println(x);
-
- let x = 32.0f32;
- let _ = (x + ((x * x) + 1.0).sqrt()).ln();
-
- let s: Box<SomeTrait> = Box::new(some_fields { field1: 43 });
- let s2: Box<some_fields> = Box::new(some_fields { field1: 43 });
- let s3 = Box::new(nofields);
-
- s.Method(43);
- s3.Method(43);
- s2.Method(43);
-
- ex.prov(43);
-
- let y: u32 = 56;
- // static method on struct
- let r = some_fields::stat(y);
- // trait static method, calls default
- let r = SubTrait::stat2(&*s3);
-
- let s4 = s3 as Box<SomeTrait>;
- s4.Method(43);
-
- s4.provided_method();
- s2.prov(45);
-
- let closure = |x: u32, s: &SomeTrait| {
- s.Method(23);
- return x + y;
- };
-
- let z = closure(10, &*s);
-}
-
-pub struct blah {
- used_link_args: RefCell<[&'static str; 0]>,
-}
-
-#[macro_use]
-mod macro_use_test {
- macro_rules! test_rec {
- (q, $src: expr) => {{
- print!("{}", $src);
- test_rec!($src);
- }};
- ($src: expr) => {
- print!("{}", $src);
- };
- }
-
- macro_rules! internal_vars {
- ($src: ident) => {{
- let mut x = $src;
- x += 100;
- }};
- }
-}
-
-fn main() {
- // foo
- let s = Box::new(some_fields { field1: 43 });
- hello((43, "a".to_string()), *s);
- sub::sub2::hello();
- sub2::sub3::hello();
-
- let h = sub2::sub3::hello;
- h();
-
- // utf8 chars
- let ut = "Les Miséééééééérables";
-
- // For some reason, this pattern of macro_rules foiled our generated code
- // avoiding strategy.
- macro_rules! variable_str(($name:expr) => (
- some_fields {
- field1: $name,
- }
- ));
- let vs = variable_str!(32);
-
- let mut candidates: RefCell<HashMap<&'static str, &'static str>> = RefCell::new(HashMap::new());
- let _ = blah { used_link_args: RefCell::new([]) };
- let s1 = nofields;
- let s2 = SF { field1: 55 };
- let s3: some_fields = some_fields { field1: 55 };
- let s4: msalias::nested_struct = sub::sub2::nested_struct { field2: 55 };
- let s4: msalias::nested_struct = sub2::nested_struct { field2: 55 };
- println(&s2.field1.to_string());
- let s5: MyType = Box::new(some_fields { field1: 55 });
- let s = SameDir::SameStruct { name: "Bob".to_string() };
- let s = SubDir::SubStruct { name: "Bob".to_string() };
- let s6: SomeEnum = SomeEnum::MyTypes(Box::new(s2.clone()), s5);
- let s7: SomeEnum = SomeEnum::Strings("one", "two", "three");
- matchSomeEnum(s6);
- matchSomeEnum(s7);
- let s8: SomeOtherEnum = SomeOtherEnum::SomeConst2;
- matchSomeOtherEnum(s8);
- let s9: SomeStructEnum =
- SomeStructEnum::EnumStruct2 { f1: Box::new(some_fields { field1: 10 }), f2: Box::new(s2) };
- matchSomeStructEnum(s9);
-
- for x in &vec![1, 2, 3] {
- let _y = x;
- }
-
- let s7: SomeEnum = SomeEnum::Strings("one", "two", "three");
- if let SomeEnum::Strings(..) = s7 {
- println!("hello!");
- }
-
- for i in 0..5 {
- foo_foo(i);
- }
-
- if let Some(x) = None {
- foo_foo(x);
- }
-
- if false {
- } else if let Some(y) = None {
- foo_foo(y);
- }
-
- while let Some(z) = None {
- foo_foo(z);
- }
-
- let mut x = 4;
- test_rec!(q, "Hello");
- assert_eq!(x, 4);
- internal_vars!(x);
-}
-
-fn foo_foo(_: i32) {}
-
-impl Iterator for nofields {
- type Item = (usize, usize);
-
- fn next(&mut self) -> Option<(usize, usize)> {
- panic!()
- }
-
- fn size_hint(&self) -> (usize, Option<usize>) {
- panic!()
- }
-}
-
-trait Pattern<'a> {
- type Searcher;
-}
-
-struct CharEqPattern;
-
-impl<'a> Pattern<'a> for CharEqPattern {
- type Searcher = CharEqPattern;
-}
-
-struct CharSearcher<'a>(<CharEqPattern as Pattern<'a>>::Searcher);
-
-pub trait Error {}
-
-impl Error + 'static {
- pub fn is<T: Error + 'static>(&self) -> bool {
- panic!()
- }
-}
-
-impl Error + 'static + Send {
- pub fn is<T: Error + 'static>(&self) -> bool {
- <Error + 'static>::is::<T>(self)
- }
-}
-extern crate serialize;
-#[derive(Clone, Copy, Hash, Encodable, Decodable, PartialEq, Eq, PartialOrd, Ord, Debug, Default)]
-struct AllDerives(i32);
-
-fn test_format_args() {
- let x = 1;
- let y = 2;
- let name = "Joe Blogg";
- println!("Hello {}", name);
- print!("Hello {0}", name);
- print!("{0} + {} = {}", x, y);
- print!("x is {}, y is {1}, name is {n}", x, y, n = name);
-}
-
-extern "C" {
- static EXTERN_FOO: u8;
- fn extern_foo(a: u8, b: i32) -> String;
-}
-
-struct Rls699 {
- f: u32,
-}
-
-fn new(f: u32) -> Rls699 {
- Rls699 { fs }
-}
-
-fn invalid_tuple_struct_access() {
- bar.0;
-
- struct S;
- S.0;
-}
diff --git a/tests/run-make-fulldeps/save-analysis-fail/krate2.rs b/tests/run-make-fulldeps/save-analysis-fail/krate2.rs
deleted file mode 100644
index 7d787e0c9..000000000
--- a/tests/run-make-fulldeps/save-analysis-fail/krate2.rs
+++ /dev/null
@@ -1,8 +0,0 @@
-#![ crate_name = "krate2" ]
-#![ crate_type = "lib" ]
-
-use std::io::Write;
-
-pub fn hello() {
- std::io::stdout().write_all(b"hello world!\n");
-}
diff --git a/tests/run-make-fulldeps/save-analysis-rfc2126/Makefile b/tests/run-make-fulldeps/save-analysis-rfc2126/Makefile
deleted file mode 100644
index 30f57034b..000000000
--- a/tests/run-make-fulldeps/save-analysis-rfc2126/Makefile
+++ /dev/null
@@ -1,8 +0,0 @@
-include ../tools.mk
-
-all: extern_absolute_paths.rs krate2
- $(RUSTC) extern_absolute_paths.rs -Zsave-analysis --edition=2018 --extern krate2
- cat $(TMPDIR)/save-analysis/extern_absolute_paths.json | "$(PYTHON)" validate_json.py
-
-krate2: krate2.rs
- $(RUSTC) $<
diff --git a/tests/run-make-fulldeps/save-analysis-rfc2126/extern_absolute_paths.rs b/tests/run-make-fulldeps/save-analysis-rfc2126/extern_absolute_paths.rs
deleted file mode 100644
index 7a8e3fff0..000000000
--- a/tests/run-make-fulldeps/save-analysis-rfc2126/extern_absolute_paths.rs
+++ /dev/null
@@ -1,6 +0,0 @@
-use krate2::hello;
-
-fn main() {
- hello();
- ::krate2::hello();
-}
diff --git a/tests/run-make-fulldeps/save-analysis-rfc2126/krate2.rs b/tests/run-make-fulldeps/save-analysis-rfc2126/krate2.rs
deleted file mode 100644
index d24c68862..000000000
--- a/tests/run-make-fulldeps/save-analysis-rfc2126/krate2.rs
+++ /dev/null
@@ -1,5 +0,0 @@
-#![crate_name = "krate2"]
-#![crate_type = "lib"]
-
-pub fn hello() {
-}
diff --git a/tests/run-make-fulldeps/save-analysis-rfc2126/validate_json.py b/tests/run-make-fulldeps/save-analysis-rfc2126/validate_json.py
deleted file mode 100644
index 882d29a8b..000000000
--- a/tests/run-make-fulldeps/save-analysis-rfc2126/validate_json.py
+++ /dev/null
@@ -1,7 +0,0 @@
-#!/usr/bin/env python
-
-import sys
-import json
-
-crates = json.loads(sys.stdin.readline().strip())["prelude"]["external_crates"]
-assert any(map(lambda c: c["id"]["name"] == "krate2", crates))
diff --git a/tests/run-make-fulldeps/save-analysis/Makefile b/tests/run-make-fulldeps/save-analysis/Makefile
deleted file mode 100644
index b8b6be13d..000000000
--- a/tests/run-make-fulldeps/save-analysis/Makefile
+++ /dev/null
@@ -1,6 +0,0 @@
-include ../tools.mk
-all: code
-krate2: krate2.rs
- $(RUSTC) $<
-code: foo.rs krate2
- $(RUSTC) foo.rs -Zsave-analysis
diff --git a/tests/run-make-fulldeps/save-analysis/SameDir.rs b/tests/run-make-fulldeps/save-analysis/SameDir.rs
deleted file mode 100644
index 2c690d5f7..000000000
--- a/tests/run-make-fulldeps/save-analysis/SameDir.rs
+++ /dev/null
@@ -1,5 +0,0 @@
-// sub-module in the same directory as the main crate file
-
-pub struct SameStruct {
- pub name: String
-}
diff --git a/tests/run-make-fulldeps/save-analysis/SameDir3.rs b/tests/run-make-fulldeps/save-analysis/SameDir3.rs
deleted file mode 100644
index fab03ee2e..000000000
--- a/tests/run-make-fulldeps/save-analysis/SameDir3.rs
+++ /dev/null
@@ -1,3 +0,0 @@
-pub fn hello(x: isize) {
- println!("macro {} :-(", x);
-}
diff --git a/tests/run-make-fulldeps/save-analysis/SubDir/mod.rs b/tests/run-make-fulldeps/save-analysis/SubDir/mod.rs
deleted file mode 100644
index 511721d92..000000000
--- a/tests/run-make-fulldeps/save-analysis/SubDir/mod.rs
+++ /dev/null
@@ -1,27 +0,0 @@
-// sub-module in a sub-directory
-
-use sub::sub2 as msalias;
-use sub::sub2;
-
-static yy: usize = 25;
-
-mod sub {
- pub mod sub2 {
- pub mod sub3 {
- pub fn hello() {
- println!("hello from module 3");
- }
- }
- pub fn hello() {
- println!("hello from a module");
- }
-
- pub struct nested_struct {
- pub field2: u32,
- }
- }
-}
-
-pub struct SubStruct {
- pub name: String
-}
diff --git a/tests/run-make-fulldeps/save-analysis/extra-docs.md b/tests/run-make-fulldeps/save-analysis/extra-docs.md
deleted file mode 100644
index 0605ca517..000000000
--- a/tests/run-make-fulldeps/save-analysis/extra-docs.md
+++ /dev/null
@@ -1 +0,0 @@
-Extra docs for this struct.
diff --git a/tests/run-make-fulldeps/save-analysis/foo.rs b/tests/run-make-fulldeps/save-analysis/foo.rs
deleted file mode 100644
index 384589de3..000000000
--- a/tests/run-make-fulldeps/save-analysis/foo.rs
+++ /dev/null
@@ -1,465 +0,0 @@
-#![crate_name = "test"]
-#![feature(rustc_private)]
-#![feature(associated_type_defaults)]
-
-extern crate rustc_graphviz;
-// A simple rust project
-
-// Necessary to pull in object code as the rest of the rustc crates are shipped only as rmeta
-// files.
-#[allow(unused_extern_crates)]
-extern crate rustc_driver;
-
-extern crate krate2;
-extern crate krate2 as krate3;
-
-use rustc_graphviz::RenderOption;
-use std::cell::RefCell;
-use std::collections::{HashMap, HashSet};
-use std::io::Write;
-
-use sub::sub2 as msalias;
-use sub::sub2;
-use sub::sub2::nested_struct as sub_struct;
-
-use std::mem::size_of;
-
-use std::char::from_u32;
-
-static uni: &'static str = "Les Miséééééééérables";
-static yy: usize = 25;
-
-static bob: Option<rustc_graphviz::RenderOption> = None;
-
-// buglink test - see issue #1337.
-
-fn test_alias<I: Iterator>(i: Option<<I as Iterator>::Item>) {
- let s = sub_struct { field2: 45u32 };
-
- // import tests
- fn foo(x: &Write) {}
- let _: Option<_> = from_u32(45);
-
- let x = 42usize;
-
- krate2::hello();
- krate3::hello();
-
- let x = (3isize, 4usize);
- let y = x.1;
-}
-
-// Issue #37700
-const LUT_BITS: usize = 3;
-pub struct HuffmanTable {
- ac_lut: Option<[(i16, u8); 1 << LUT_BITS]>,
-}
-
-struct TupStruct(isize, isize, Box<str>);
-
-fn test_tup_struct(x: TupStruct) -> isize {
- x.1
-}
-
-fn println(s: &str) {
- std::io::stdout().write_all(s.as_bytes());
-}
-
-mod sub {
- pub mod sub2 {
- use std::io::Write;
- pub mod sub3 {
- use std::io::Write;
- pub fn hello() {
- ::println("hello from module 3");
- }
- }
- pub fn hello() {
- ::println("hello from a module");
- }
-
- pub struct nested_struct {
- pub field2: u32,
- }
-
- pub enum nested_enum {
- Nest2 = 2,
- Nest3 = 3,
- }
- }
-}
-
-pub mod SameDir;
-pub mod SubDir;
-
-#[path = "SameDir3.rs"]
-pub mod SameDir2;
-
-struct nofields;
-
-#[derive(Clone)]
-struct some_fields {
- field1: u32,
-}
-
-type SF = some_fields;
-
-trait SuperTrait {
- fn qux(&self) {
- panic!();
- }
-}
-
-trait SomeTrait: SuperTrait {
- fn Method(&self, x: u32) -> u32;
-
- fn prov(&self, x: u32) -> u32 {
- println(&x.to_string());
- 42
- }
- fn provided_method(&self) -> u32 {
- 42
- }
-}
-
-trait SubTrait: SomeTrait {
- fn stat2(x: &Self) -> u32 {
- 32
- }
-}
-
-impl SomeTrait for some_fields {
- fn Method(&self, x: u32) -> u32 {
- println(&x.to_string());
- self.field1
- }
-}
-
-impl SuperTrait for some_fields {}
-
-impl SubTrait for some_fields {}
-
-impl some_fields {
- fn stat(x: u32) -> u32 {
- println(&x.to_string());
- 42
- }
- fn stat2(x: &some_fields) -> u32 {
- 42
- }
-
- fn align_to<T>(&mut self) {}
-
- fn test(&mut self) {
- self.align_to::<bool>();
- }
-}
-
-impl SuperTrait for nofields {}
-impl SomeTrait for nofields {
- fn Method(&self, x: u32) -> u32 {
- self.Method(x);
- 43
- }
-
- fn provided_method(&self) -> u32 {
- 21
- }
-}
-
-impl SubTrait for nofields {}
-
-impl SuperTrait for (Box<nofields>, Box<some_fields>) {}
-
-fn f_with_params<T: SomeTrait>(x: &T) {
- x.Method(41);
-}
-
-type MyType = Box<some_fields>;
-
-enum SomeEnum<'a> {
- Ints(isize, isize),
- Floats(f64, f64),
- Strings(&'a str, &'a str, &'a str),
- MyTypes(MyType, MyType),
-}
-
-#[derive(Copy, Clone)]
-enum SomeOtherEnum {
- SomeConst1,
- SomeConst2,
- SomeConst3,
-}
-
-enum SomeStructEnum {
- EnumStruct { a: isize, b: isize },
- EnumStruct2 { f1: MyType, f2: MyType },
- EnumStruct3 { f1: MyType, f2: MyType, f3: SomeEnum<'static> },
-}
-
-fn matchSomeEnum(val: SomeEnum) {
- match val {
- SomeEnum::Ints(int1, int2) => {
- println(&(int1 + int2).to_string());
- }
- SomeEnum::Floats(float1, float2) => {
- println(&(float2 * float1).to_string());
- }
- SomeEnum::Strings(.., s3) => {
- println(s3);
- }
- SomeEnum::MyTypes(mt1, mt2) => {
- println(&(mt1.field1 - mt2.field1).to_string());
- }
- }
-}
-
-fn matchSomeStructEnum(se: SomeStructEnum) {
- match se {
- SomeStructEnum::EnumStruct { a: a, .. } => println(&a.to_string()),
- SomeStructEnum::EnumStruct2 { f1: f1, f2: f_2 } => println(&f_2.field1.to_string()),
- SomeStructEnum::EnumStruct3 { f1, .. } => println(&f1.field1.to_string()),
- }
-}
-
-fn matchSomeStructEnum2(se: SomeStructEnum) {
- use SomeStructEnum::*;
- match se {
- EnumStruct { a: ref aaa, .. } => println(&aaa.to_string()),
- EnumStruct2 { f1, f2: f2 } => println(&f1.field1.to_string()),
- EnumStruct3 { f1, f3: SomeEnum::Ints(..), f2 } => println(&f1.field1.to_string()),
- _ => {}
- }
-}
-
-fn matchSomeOtherEnum(val: SomeOtherEnum) {
- use SomeOtherEnum::{SomeConst2, SomeConst3};
- match val {
- SomeOtherEnum::SomeConst1 => {
- println("I'm const1.");
- }
- SomeConst2 | SomeConst3 => {
- println("I'm const2 or const3.");
- }
- }
-}
-
-fn hello<X: SomeTrait>((z, a): (u32, String), ex: X) {
- SameDir2::hello(43);
-
- println(&yy.to_string());
- let (x, y): (u32, u32) = (5, 3);
- println(&x.to_string());
- println(&z.to_string());
- let x: u32 = x;
- println(&x.to_string());
- let x = "hello";
- println(x);
-
- let x = 32.0f32;
- let _ = (x + ((x * x) + 1.0).sqrt()).ln();
-
- let s: Box<SomeTrait> = Box::new(some_fields { field1: 43 });
- let s2: Box<some_fields> = Box::new(some_fields { field1: 43 });
- let s3 = Box::new(nofields);
-
- s.Method(43);
- s3.Method(43);
- s2.Method(43);
-
- ex.prov(43);
-
- let y: u32 = 56;
- // static method on struct
- let r = some_fields::stat(y);
- // trait static method, calls default
- let r = SubTrait::stat2(&*s3);
-
- let s4 = s3 as Box<SomeTrait>;
- s4.Method(43);
-
- s4.provided_method();
- s2.prov(45);
-
- let closure = |x: u32, s: &SomeTrait| {
- s.Method(23);
- return x + y;
- };
-
- let z = closure(10, &*s);
-}
-
-pub struct blah {
- used_link_args: RefCell<[&'static str; 0]>,
-}
-
-#[macro_use]
-mod macro_use_test {
- macro_rules! test_rec {
- (q, $src: expr) => {{
- print!("{}", $src);
- test_rec!($src);
- }};
- ($src: expr) => {
- print!("{}", $src);
- };
- }
-
- macro_rules! internal_vars {
- ($src: ident) => {{
- let mut x = $src;
- x += 100;
- }};
- }
-}
-
-fn main() {
- // foo
- let s = Box::new(some_fields { field1: 43 });
- hello((43, "a".to_string()), *s);
- sub::sub2::hello();
- sub2::sub3::hello();
-
- let h = sub2::sub3::hello;
- h();
-
- // utf8 chars
- let ut = "Les Miséééééééérables";
-
- // For some reason, this pattern of macro_rules foiled our generated code
- // avoiding strategy.
- macro_rules! variable_str(($name:expr) => (
- some_fields {
- field1: $name,
- }
- ));
- let vs = variable_str!(32);
-
- let mut candidates: RefCell<HashMap<&'static str, &'static str>> = RefCell::new(HashMap::new());
- let _ = blah { used_link_args: RefCell::new([]) };
- let s1 = nofields;
- let s2 = SF { field1: 55 };
- let s3: some_fields = some_fields { field1: 55 };
- let s4: msalias::nested_struct = sub::sub2::nested_struct { field2: 55 };
- let s4: msalias::nested_struct = sub2::nested_struct { field2: 55 };
- println(&s2.field1.to_string());
- let s5: MyType = Box::new(some_fields { field1: 55 });
- let s = SameDir::SameStruct { name: "Bob".to_string() };
- let s = SubDir::SubStruct { name: "Bob".to_string() };
- let s6: SomeEnum = SomeEnum::MyTypes(Box::new(s2.clone()), s5);
- let s7: SomeEnum = SomeEnum::Strings("one", "two", "three");
- matchSomeEnum(s6);
- matchSomeEnum(s7);
- let s8: SomeOtherEnum = SomeOtherEnum::SomeConst2;
- matchSomeOtherEnum(s8);
- let s9: SomeStructEnum =
- SomeStructEnum::EnumStruct2 { f1: Box::new(some_fields { field1: 10 }), f2: Box::new(s2) };
- matchSomeStructEnum(s9);
-
- for x in &vec![1, 2, 3] {
- let _y = x;
- }
-
- let s7: SomeEnum = SomeEnum::Strings("one", "two", "three");
- if let SomeEnum::Strings(..) = s7 {
- println!("hello!");
- }
-
- for i in 0..5 {
- foo_foo(i);
- }
-
- if let Some(x) = None {
- foo_foo(x);
- }
-
- if false {
- } else if let Some(y) = None {
- foo_foo(y);
- }
-
- while let Some(z) = None {
- foo_foo(z);
- }
-
- let mut x = 4;
- test_rec!(q, "Hello");
- assert_eq!(x, 4);
- internal_vars!(x);
-}
-
-fn foo_foo(_: i32) {}
-
-impl Iterator for nofields {
- type Item = (usize, usize);
-
- fn next(&mut self) -> Option<(usize, usize)> {
- panic!()
- }
-
- fn size_hint(&self) -> (usize, Option<usize>) {
- panic!()
- }
-}
-
-trait Pattern<'a> {
- type Searcher;
-}
-
-struct CharEqPattern;
-
-impl<'a> Pattern<'a> for CharEqPattern {
- type Searcher = CharEqPattern;
-}
-
-struct CharSearcher<'a>(<CharEqPattern as Pattern<'a>>::Searcher);
-
-pub trait Error {}
-
-impl Error + 'static {
- pub fn is<T: Error + 'static>(&self) -> bool {
- panic!()
- }
-}
-
-impl Error + 'static + Send {
- pub fn is<T: Error + 'static>(&self) -> bool {
- <Error + 'static>::is::<T>(self)
- }
-}
-extern crate rustc_serialize;
-#[derive(Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord, Debug, Default)]
-struct AllDerives(i32);
-
-fn test_format_args() {
- let x = 1;
- let y = 2;
- let name = "Joe Blogg";
- println!("Hello {}", name);
- print!("Hello {0}", name);
- print!("{0} + {} = {}", x, y);
- print!("x is {}, y is {1}, name is {n}", x, y, n = name);
-}
-
-union TestUnion {
- f1: u32,
-}
-
-struct FrameBuffer;
-
-struct SilenceGenerator;
-
-impl Iterator for SilenceGenerator {
- type Item = FrameBuffer;
-
- fn next(&mut self) -> Option<Self::Item> {
- panic!();
- }
-}
-
-#[doc = include_str!("extra-docs.md")]
-struct StructWithDocs;
-
-trait Foo {
- type Bar = FrameBuffer;
-}
diff --git a/tests/run-make-fulldeps/save-analysis/krate2.rs b/tests/run-make-fulldeps/save-analysis/krate2.rs
deleted file mode 100644
index 7d787e0c9..000000000
--- a/tests/run-make-fulldeps/save-analysis/krate2.rs
+++ /dev/null
@@ -1,8 +0,0 @@
-#![ crate_name = "krate2" ]
-#![ crate_type = "lib" ]
-
-use std::io::Write;
-
-pub fn hello() {
- std::io::stdout().write_all(b"hello world!\n");
-}
diff --git a/tests/run-make-fulldeps/split-debuginfo/Makefile b/tests/run-make-fulldeps/split-debuginfo/Makefile
index 1831ab38f..44cda0d3d 100644
--- a/tests/run-make-fulldeps/split-debuginfo/Makefile
+++ b/tests/run-make-fulldeps/split-debuginfo/Makefile
@@ -254,12 +254,12 @@ unpacked-remapped-single:
$(RUSTC) $(UNSTABLEOPTS) -C split-debuginfo=unpacked -C debuginfo=2 \
-Z split-dwarf-kind=single --remap-path-prefix $(TMPDIR)=/a foo.rs -g
objdump -Wi $(TMPDIR)/foo | grep DW_AT_GNU_dwo_name | (! grep $(TMPDIR)) || exit 1
- ls $(TMPDIR)/*.o
+ rm $(TMPDIR)/*.o
ls $(TMPDIR)/*.dwo && exit 1 || exit 0
ls $(TMPDIR)/*.dwp && exit 1 || exit 0
rm $(TMPDIR)/$(call BIN,foo)
-unpacked-crosscrate: packed-crosscrate-split packed-crosscrate-single
+unpacked-crosscrate: unpacked-crosscrate-split unpacked-crosscrate-single
# - Debuginfo in `.dwo` files
# - (bar) `.rlib` file created, contains `.dwo`
diff --git a/tests/run-make-fulldeps/type-mismatch-same-crate-name/Makefile b/tests/run-make-fulldeps/type-mismatch-same-crate-name/Makefile
index 9f4be7126..a2a2a41c7 100644
--- a/tests/run-make-fulldeps/type-mismatch-same-crate-name/Makefile
+++ b/tests/run-make-fulldeps/type-mismatch-same-crate-name/Makefile
@@ -11,7 +11,7 @@ all:
tr -d '\r\n' | $(CGREP) -e \
"mismatched types.*\
crateB::try_foo\(foo2\);.*\
- expected struct \`crateA::foo::Foo\`, found struct \`Foo\`.*\
+ expected \`crateA::foo::Foo\`, found \`Foo\`.*\
different versions of crate \`crateA\`.*\
mismatched types.*\
crateB::try_bar\(bar2\);.*\
diff --git a/tests/run-make/incremental-session-fail/Makefile b/tests/run-make/incremental-session-fail/Makefile
index 0461bb926..6ce137092 100644
--- a/tests/run-make/incremental-session-fail/Makefile
+++ b/tests/run-make/incremental-session-fail/Makefile
@@ -9,6 +9,6 @@ all:
touch $(SESSION_DIR)
# Check exit code is 1 for an error, and not 101 for ICE.
$(RUSTC) foo.rs --crate-type=rlib -C incremental=$(SESSION_DIR) > $(OUTPUT_FILE) 2>&1; [ $$? -eq 1 ]
- $(CGREP) "Could not create incremental compilation crate directory" < $(OUTPUT_FILE)
+ $(CGREP) "could not create incremental compilation crate directory" < $(OUTPUT_FILE)
# -v tests are fragile, hopefully this text won't change
$(CGREP) -v "internal compiler error" < $(OUTPUT_FILE)
diff --git a/tests/run-make/native-link-modifier-bundle/Makefile b/tests/run-make/native-link-modifier-bundle/Makefile
index 7c78d7783..e8a1121bf 100644
--- a/tests/run-make/native-link-modifier-bundle/Makefile
+++ b/tests/run-make/native-link-modifier-bundle/Makefile
@@ -5,7 +5,12 @@ include ../../run-make-fulldeps/tools.mk
# We're using the llvm-nm instead of the system nm to ensure it is compatible
# with the LLVM bitcode generated by rustc.
+# Except on Windows where piping/IO redirection under MSYS2 is wonky with llvm-nm.
+ifndef IS_WINDOWS
NM = "$(LLVM_BIN_DIR)"/llvm-nm
+else
+NM = nm
+endif
all: $(call NATIVE_STATICLIB,native-staticlib)
# Build a staticlib and a rlib, the `native_func` symbol will be bundled into them
diff --git a/tests/run-make/no-input-file/Makefile b/tests/run-make/no-input-file/Makefile
new file mode 100644
index 000000000..2f0215922
--- /dev/null
+++ b/tests/run-make/no-input-file/Makefile
@@ -0,0 +1,4 @@
+include ../../run-make-fulldeps/tools.mk
+
+all:
+ $(RUSTC) --print crate-name 2>&1 | diff - no-input-file.stderr
diff --git a/tests/run-make/no-input-file/no-input-file.stderr b/tests/run-make/no-input-file/no-input-file.stderr
new file mode 100644
index 000000000..b843eb524
--- /dev/null
+++ b/tests/run-make/no-input-file/no-input-file.stderr
@@ -0,0 +1,2 @@
+error: no input filename given
+
diff --git a/tests/run-make/overwrite-input/Makefile b/tests/run-make/overwrite-input/Makefile
new file mode 100644
index 000000000..03b03eb14
--- /dev/null
+++ b/tests/run-make/overwrite-input/Makefile
@@ -0,0 +1,13 @@
+include ../../run-make-fulldeps/tools.mk
+
+all:
+ $(RUSTC) main.rs -o main.rs 2> $(TMPDIR)/file.stderr || echo "failed successfully"
+ $(RUSTC) main.rs -o . 2> $(TMPDIR)/folder.stderr || echo "failed successfully"
+
+ifdef RUSTC_BLESS_TEST
+ cp "$(TMPDIR)"/file.stderr file.stderr
+ cp "$(TMPDIR)"/folder.stderr folder.stderr
+else
+ $(DIFF) file.stderr "$(TMPDIR)"/file.stderr
+ $(DIFF) folder.stderr "$(TMPDIR)"/folder.stderr
+endif
diff --git a/tests/run-make/overwrite-input/file.stderr b/tests/run-make/overwrite-input/file.stderr
new file mode 100644
index 000000000..9936962b4
--- /dev/null
+++ b/tests/run-make/overwrite-input/file.stderr
@@ -0,0 +1,6 @@
+warning: ignoring --out-dir flag due to -o flag
+
+error: the input file "main.rs" would be overwritten by the generated executable
+
+error: aborting due to previous error; 1 warning emitted
+
diff --git a/tests/run-make/overwrite-input/folder.stderr b/tests/run-make/overwrite-input/folder.stderr
new file mode 100644
index 000000000..81b1e7367
--- /dev/null
+++ b/tests/run-make/overwrite-input/folder.stderr
@@ -0,0 +1,6 @@
+warning: ignoring --out-dir flag due to -o flag
+
+error: the generated executable for the input file "main.rs" conflicts with the existing directory "."
+
+error: aborting due to previous error; 1 warning emitted
+
diff --git a/tests/run-make/overwrite-input/main.rs b/tests/run-make/overwrite-input/main.rs
new file mode 100644
index 000000000..f328e4d9d
--- /dev/null
+++ b/tests/run-make/overwrite-input/main.rs
@@ -0,0 +1 @@
+fn main() {}
diff --git a/tests/run-make/overwrite-input/main.stderr b/tests/run-make/overwrite-input/main.stderr
new file mode 100644
index 000000000..9936962b4
--- /dev/null
+++ b/tests/run-make/overwrite-input/main.stderr
@@ -0,0 +1,6 @@
+warning: ignoring --out-dir flag due to -o flag
+
+error: the input file "main.rs" would be overwritten by the generated executable
+
+error: aborting due to previous error; 1 warning emitted
+
diff --git a/tests/run-make/raw-dylib-inline-cross-dylib/Makefile b/tests/run-make/raw-dylib-inline-cross-dylib/Makefile
index 9e603f958..722a49b02 100644
--- a/tests/run-make/raw-dylib-inline-cross-dylib/Makefile
+++ b/tests/run-make/raw-dylib-inline-cross-dylib/Makefile
@@ -4,15 +4,19 @@
include ../../run-make-fulldeps/tools.mk
+# We'd be using the llvm-objdump instead of the system objdump to ensure compatibility
+# with the LLVM bitcode generated by rustc but on Windows piping/IO redirection under MSYS2 is wonky with llvm-objdump.
+OBJDUMP = objdump
+
all:
$(RUSTC) --crate-type dylib --crate-name raw_dylib_test lib.rs -C prefer-dynamic
$(RUSTC) --crate-type dylib --crate-name raw_dylib_test_wrapper lib_wrapper.rs -C prefer-dynamic
$(RUSTC) --crate-type bin driver.rs -L "$(TMPDIR)" -C prefer-dynamic
# Make sure we don't find an import to the functions we expect to be inlined.
- "$(LLVM_BIN_DIR)"/llvm-objdump -p $(TMPDIR)/driver.exe | $(CGREP) -v -e "inline_library_function"
- "$(LLVM_BIN_DIR)"/llvm-objdump -p $(TMPDIR)/driver.exe | $(CGREP) -v -e "inline_library_function_calls_inline"
+ $(OBJDUMP) -p $(TMPDIR)/driver.exe | $(CGREP) -v -e "inline_library_function"
+ $(OBJDUMP) -p $(TMPDIR)/driver.exe | $(CGREP) -v -e "inline_library_function_calls_inline"
# Make sure we do find an import to the functions we expect to be imported.
- "$(LLVM_BIN_DIR)"/llvm-objdump -p $(TMPDIR)/driver.exe | $(CGREP) -e "library_function"
+ $(OBJDUMP) -p $(TMPDIR)/driver.exe | $(CGREP) -e "library_function"
$(call COMPILE_OBJ,"$(TMPDIR)"/extern_1.obj,extern_1.c)
$(call COMPILE_OBJ,"$(TMPDIR)"/extern_2.obj,extern_2.c)
ifdef IS_MSVC
diff --git a/tests/run-make/rlib-format-packed-bundled-libs-2/Makefile b/tests/run-make/rlib-format-packed-bundled-libs-2/Makefile
index 4574cf17f..37b8d809a 100644
--- a/tests/run-make/rlib-format-packed-bundled-libs-2/Makefile
+++ b/tests/run-make/rlib-format-packed-bundled-libs-2/Makefile
@@ -6,7 +6,12 @@
# We're using the llvm-nm instead of the system nm to ensure it is compatible
# with the LLVM bitcode generated by rustc.
+# Except on Windows where piping/IO redirection under MSYS2 is wonky with llvm-nm.
+ifndef IS_WINDOWS
NM = "$(LLVM_BIN_DIR)"/llvm-nm
+else
+NM = nm
+endif
all:
# Build strange-named dep.
diff --git a/tests/run-make/rlib-format-packed-bundled-libs-3/Makefile b/tests/run-make/rlib-format-packed-bundled-libs-3/Makefile
new file mode 100644
index 000000000..62dc1b5f6
--- /dev/null
+++ b/tests/run-make/rlib-format-packed-bundled-libs-3/Makefile
@@ -0,0 +1,35 @@
+-include ../../run-make-fulldeps/tools.mk
+
+# ignore-cross-compile
+# only-linux
+
+# Make sure -Zpacked_bundled_libs-like behavior activates with whole-archive.
+
+# We're using the llvm-nm instead of the system nm to ensure it is compatible
+# with the LLVM bitcode generated by rustc.
+NM = "$(LLVM_BIN_DIR)"/llvm-nm
+
+all: $(call NATIVE_STATICLIB,native_dep_1) $(call NATIVE_STATICLIB,native_dep_2) $(call NATIVE_STATICLIB,native_dep_3) $(call NATIVE_STATICLIB,native_dep_4)
+ # test cfg with packed bundle
+ $(RUSTC) rust_dep_cfg.rs --crate-type=rlib -Zpacked_bundled_libs
+ $(RUSTC) main.rs --extern rust_dep=$(TMPDIR)/librust_dep_cfg.rlib --crate-type=staticlib --cfg should_add
+ $(AR) t $(TMPDIR)/librust_dep_cfg.rlib | $(CGREP) -e "libnative_dep_1.a"
+ $(AR) t $(TMPDIR)/librust_dep_cfg.rlib | $(CGREP) -e "libnative_dep_2.a"
+ $(AR) t $(TMPDIR)/libmain.a | $(CGREP) -e "libnative_dep_1.o"
+ $(AR) t $(TMPDIR)/libmain.a | $(CGREP) -ev "libnative_dep_2.o"
+
+
+ # test bundle with whole_archive
+ $(RUSTC) rust_dep.rs --crate-type=rlib
+ $(AR) t $(TMPDIR)/librust_dep.rlib | $(CGREP) -e "native_dep_1"
+ $(AR) t $(TMPDIR)/librust_dep.rlib | $(CGREP) -e "native_dep_3"
+ $(AR) t $(TMPDIR)/librust_dep.rlib | $(CGREP) -ev "native_dep_2"
+ $(AR) t $(TMPDIR)/librust_dep.rlib | $(CGREP) -ev "native_dep_4"
+
+ # Make sure compiler doesn't use files, that it shouldn't know about.
+ rm $(TMPDIR)/libnative_dep_1.a
+ rm $(TMPDIR)/libnative_dep_3.a
+
+ $(RUSTC) main.rs --extern rust_dep=$(TMPDIR)/librust_dep.rlib --print link-args > $(TMPDIR)/link_args
+ cat $(TMPDIR)/link_args | $(CGREP) -ev "native_dep_3"
+ cat $(TMPDIR)/link_args | $(CGREP) -e "--whole-archive.*native_dep_1.*--whole-archive.*lnative_dep_2.*no-whole-archive.*lnative_dep_4"
diff --git a/tests/run-make/rlib-format-packed-bundled-libs-3/main.rs b/tests/run-make/rlib-format-packed-bundled-libs-3/main.rs
new file mode 100644
index 000000000..8d2b8a285
--- /dev/null
+++ b/tests/run-make/rlib-format-packed-bundled-libs-3/main.rs
@@ -0,0 +1,5 @@
+extern crate rust_dep;
+
+pub fn main() {
+ rust_dep::rust_dep();
+}
diff --git a/tests/run-make/rlib-format-packed-bundled-libs-3/native_dep_1.c b/tests/run-make/rlib-format-packed-bundled-libs-3/native_dep_1.c
new file mode 100644
index 000000000..07be8562c
--- /dev/null
+++ b/tests/run-make/rlib-format-packed-bundled-libs-3/native_dep_1.c
@@ -0,0 +1 @@
+int native_f1() { return 1; }
diff --git a/tests/run-make/rlib-format-packed-bundled-libs-3/native_dep_2.c b/tests/run-make/rlib-format-packed-bundled-libs-3/native_dep_2.c
new file mode 100644
index 000000000..a1b94e40d
--- /dev/null
+++ b/tests/run-make/rlib-format-packed-bundled-libs-3/native_dep_2.c
@@ -0,0 +1 @@
+int native_f2() { return 2; }
diff --git a/tests/run-make/rlib-format-packed-bundled-libs-3/native_dep_3.c b/tests/run-make/rlib-format-packed-bundled-libs-3/native_dep_3.c
new file mode 100644
index 000000000..f81f397a4
--- /dev/null
+++ b/tests/run-make/rlib-format-packed-bundled-libs-3/native_dep_3.c
@@ -0,0 +1 @@
+int native_f3() { return 3; }
diff --git a/tests/run-make/rlib-format-packed-bundled-libs-3/native_dep_4.c b/tests/run-make/rlib-format-packed-bundled-libs-3/native_dep_4.c
new file mode 100644
index 000000000..14d41d60b
--- /dev/null
+++ b/tests/run-make/rlib-format-packed-bundled-libs-3/native_dep_4.c
@@ -0,0 +1 @@
+int native_f4() { return 4; }
diff --git a/tests/run-make/rlib-format-packed-bundled-libs-3/rust_dep.rs b/tests/run-make/rlib-format-packed-bundled-libs-3/rust_dep.rs
new file mode 100644
index 000000000..abd846b68
--- /dev/null
+++ b/tests/run-make/rlib-format-packed-bundled-libs-3/rust_dep.rs
@@ -0,0 +1,16 @@
+#![feature(packed_bundled_libs)]
+
+#[link(name = "native_dep_1", kind = "static", modifiers = "+whole-archive,+bundle")]
+extern "C" {}
+
+#[link(name = "native_dep_2", kind = "static", modifiers = "+whole-archive,-bundle")]
+extern "C" {}
+
+#[link(name = "native_dep_3", kind = "static", modifiers = "+bundle")]
+extern "C" {}
+
+#[link(name = "native_dep_4", kind = "static", modifiers = "-bundle")]
+extern "C" {}
+
+#[no_mangle]
+pub fn rust_dep() {}
diff --git a/tests/run-make/rlib-format-packed-bundled-libs-3/rust_dep_cfg.rs b/tests/run-make/rlib-format-packed-bundled-libs-3/rust_dep_cfg.rs
new file mode 100644
index 000000000..506ca62a8
--- /dev/null
+++ b/tests/run-make/rlib-format-packed-bundled-libs-3/rust_dep_cfg.rs
@@ -0,0 +1,10 @@
+#![feature(link_cfg)]
+
+#[link(name = "native_dep_1", kind = "static", cfg(should_add))]
+extern "C" {}
+
+#[link(name = "native_dep_2", kind = "static", cfg(should_not_add))]
+extern "C" {}
+
+#[no_mangle]
+pub fn rust_dep() {}
diff --git a/tests/run-make/rlib-format-packed-bundled-libs/Makefile b/tests/run-make/rlib-format-packed-bundled-libs/Makefile
index 0b991ac42..7fb6ce8d1 100644
--- a/tests/run-make/rlib-format-packed-bundled-libs/Makefile
+++ b/tests/run-make/rlib-format-packed-bundled-libs/Makefile
@@ -6,7 +6,12 @@
# We're using the llvm-nm instead of the system nm to ensure it is compatible
# with the LLVM bitcode generated by rustc.
+# Except on Windows where piping/IO redirection under MSYS2 is wonky with llvm-nm.
+ifndef IS_WINDOWS
NM = "$(LLVM_BIN_DIR)"/llvm-nm
+else
+NM = nm
+endif
all: $(call NATIVE_STATICLIB,native_dep_1) $(call NATIVE_STATICLIB,native_dep_2) $(call NATIVE_STATICLIB,native_dep_3)
$(RUSTC) rust_dep_up.rs --crate-type=rlib -Zpacked_bundled_libs
diff --git a/tests/run-make/translation/Makefile b/tests/run-make/translation/Makefile
index 20e86c7f9..5b0b331ca 100644
--- a/tests/run-make/translation/Makefile
+++ b/tests/run-make/translation/Makefile
@@ -6,8 +6,10 @@ include ../../run-make-fulldeps/tools.mk
SYSROOT:=$(shell $(RUSTC) --print sysroot)
FAKEROOT=$(TMPDIR)/fakeroot
+RUSTC_LOG:=rustc_error_messages
+export RUSTC_TRANSLATION_NO_DEBUG_ASSERT:=1
-all: normal custom sysroot
+all: normal custom missing broken sysroot sysroot-invalid sysroot-missing
# Check that the test works normally, using the built-in fallback bundle.
normal: test.rs
@@ -32,6 +34,7 @@ broken: test.rs broken.ftl
# identifier by making a local copy of the sysroot and adding the custom locale
# to it.
sysroot: test.rs working.ftl
+ rm -rf $(FAKEROOT)
mkdir $(FAKEROOT)
ln -s $(SYSROOT)/* $(FAKEROOT)
rm -f $(FAKEROOT)/lib
@@ -51,12 +54,12 @@ sysroot: test.rs working.ftl
# found. This test might start failing if there actually exists a Klingon
# translation of rustc's error messages.
sysroot-missing:
- $(RUSTC) $< -Ztranslate-lang=tlh 2>&1 || grep "missing locale directory"
+ $(RUSTC) $< -Ztranslate-lang=tlh 2>&1 | grep "missing locale directory"
-# Check that the compiler errors out when the sysroot requested cannot be
-# found. This test might start failing if there actually exists a Klingon
-# translation of rustc's error messages.
+# Check that the compiler errors out when the directory for the locale in the
+# sysroot is actually a file.
sysroot-invalid: test.rs working.ftl
+ rm -rf $(FAKEROOT)
mkdir $(FAKEROOT)
ln -s $(SYSROOT)/* $(FAKEROOT)
rm -f $(FAKEROOT)/lib
@@ -68,5 +71,6 @@ sysroot-invalid: test.rs working.ftl
rm -f $(FAKEROOT)/lib/rustlib/src
mkdir $(FAKEROOT)/lib/rustlib/src
ln -s $(SYSROOT)/lib/rustlib/src/* $(FAKEROOT)/lib/rustlib/src
- touch $(FAKEROOT)/share/locale/zh-CN/
- $(RUSTC) $< --sysroot $(FAKEROOT) -Ztranslate-lang=zh-CN 2>&1 || grep "`\$sysroot/share/locales/\$locale` is not a directory"
+ mkdir -p $(FAKEROOT)/share/locale
+ touch $(FAKEROOT)/share/locale/zh-CN
+ $(RUSTC) $< --sysroot $(FAKEROOT) -Ztranslate-lang=zh-CN 2>&1 | grep "`\$sysroot/share/locales/\$locale` is not a directory"
diff --git a/tests/rustdoc-gui/code-tags.goml b/tests/rustdoc-gui/code-tags.goml
index 8561f537f..ca337cbc3 100644
--- a/tests/rustdoc-gui/code-tags.goml
+++ b/tests/rustdoc-gui/code-tags.goml
@@ -9,16 +9,16 @@ size: (1080, 600)
// Check that their content is inside <pre><code>
assert-count: (".example-wrap pre > code", 4)
// Check that function signature is inside <pre><code>
-assert: ".item-decl pre.rust > code"
+assert: "pre.rust.item-decl > code"
goto: "file://" + |DOC_PATH| + "/test_docs/struct.Foo.html"
-assert: ".item-decl pre.rust > code"
+assert: "pre.rust.item-decl > code"
goto: "file://" + |DOC_PATH| + "/test_docs/enum.AnEnum.html"
-assert: ".item-decl pre.rust > code"
+assert: "pre.rust.item-decl > code"
goto: "file://" + |DOC_PATH| + "/test_docs/trait.AnotherOne.html"
-assert: ".item-decl pre.rust > code"
+assert: "pre.rust.item-decl > code"
goto: "file://" + |DOC_PATH| + "/test_docs/type.SomeType.html"
-assert: ".item-decl pre.rust > code"
+assert: "pre.rust.item-decl > code"
diff --git a/tests/rustdoc-gui/codeblock-tooltip.goml b/tests/rustdoc-gui/codeblock-tooltip.goml
index a3ef4e77b..36b67073a 100644
--- a/tests/rustdoc-gui/codeblock-tooltip.goml
+++ b/tests/rustdoc-gui/codeblock-tooltip.goml
@@ -30,24 +30,16 @@ define-function: (
".docblock .example-wrap.compile_fail",
{"border-left": "2px solid rgb(255, 0, 0)"},
)
- assert-css: (
- ".docblock .example-wrap.compile_fail .tooltip::after",
- {
- "content": '"This example deliberately fails to compile"',
- "padding": "5px 3px 3px",
- "background-color": |background|,
- "color": |color|,
- "border": "1px solid " + |border|,
- },
- )
- assert-css: (
- ".docblock .example-wrap.compile_fail .tooltip::before",
- {
- "border-width": "5px",
- "border-style": "solid",
- "border-color": "rgba(0, 0, 0, 0) " + |background| + " rgba(0, 0, 0, 0) rgba(0, 0, 0, 0)",
- },
- )
+ click: ".docblock .example-wrap.compile_fail .tooltip"
+ assert-text: (
+ ".popover.tooltip",
+ "This example deliberately fails to compile"
+ )
+ assert-css: (".popover.tooltip", {
+ "color": |color|,
+ "background-color": |background|,
+ "border-color": |border|,
+ })
// should_panic block
assert-css: (
@@ -69,24 +61,16 @@ define-function: (
".docblock .example-wrap.should_panic",
{"border-left": "2px solid rgb(255, 0, 0)"},
)
- assert-css: (
- ".docblock .example-wrap.should_panic .tooltip::after",
- {
- "content": '"This example panics"',
- "padding": "5px 3px 3px",
- "background-color": |background|,
- "color": |color|,
- "border": "1px solid " + |border|,
- },
- )
- assert-css: (
- ".docblock .example-wrap.should_panic .tooltip::before",
- {
- "border-width": "5px",
- "border-style": "solid",
- "border-color": "rgba(0, 0, 0, 0) " + |background| + " rgba(0, 0, 0, 0) rgba(0, 0, 0, 0)",
- },
+ click: ".docblock .example-wrap.should_panic .tooltip"
+ assert-text: (
+ ".popover.tooltip",
+ "This example panics"
)
+ assert-css: (".popover.tooltip", {
+ "color": |color|,
+ "background-color": |background|,
+ "border-color": |border|,
+ })
// ignore block
assert-css: (
@@ -108,42 +92,36 @@ define-function: (
".docblock .example-wrap.ignore",
{"border-left": "2px solid rgb(255, 142, 0)"},
)
- assert-css: (
- ".docblock .example-wrap.ignore .tooltip::after",
- {
- "content": '"This example is not tested"',
- "padding": "5px 3px 3px",
- "background-color": |background|,
- "color": |color|,
- "border": "1px solid " + |border|,
- },
- )
- assert-css: (
- ".docblock .example-wrap.ignore .tooltip::before",
- {
- "border-width": "5px",
- "border-style": "solid",
- "border-color": "rgba(0, 0, 0, 0) " + |background| + " rgba(0, 0, 0, 0) rgba(0, 0, 0, 0)",
- },
- )
+ click: ".docblock .example-wrap.ignore .tooltip"
+ assert-text: (
+ ".popover.tooltip",
+ "This example is not tested"
+ )
+ assert-css: (".popover.tooltip", {
+ "color": |color|,
+ "background-color": |background|,
+ "border-color": |border|,
+ })
+ click: ".docblock .example-wrap.ignore .tooltip"
+ assert-false: ".popover.tooltip"
},
)
call-function: ("check-colors", {
"theme": "ayu",
- "background": "rgb(49, 69, 89)",
+ "background": "rgb(15, 20, 25)",
"color": "rgb(197, 197, 197)",
"border": "rgb(92, 103, 115)",
})
call-function: ("check-colors", {
"theme": "dark",
- "background": "rgb(0, 0, 0)",
- "color": "rgb(255, 255, 255)",
+ "background": "rgb(53, 53, 53)",
+ "color": "rgb(221, 221, 221)",
"border": "rgb(224, 224, 224)",
})
call-function: ("check-colors", {
"theme": "light",
- "background": "rgb(0, 0, 0)",
- "color": "rgb(255, 255, 255)",
+ "background": "rgb(255, 255, 255)",
+ "color": "rgb(0, 0, 0)",
"border": "rgb(224, 224, 224)",
})
diff --git a/tests/rustdoc-gui/font-weight.goml b/tests/rustdoc-gui/font-weight.goml
index fafb15631..aad334d2b 100644
--- a/tests/rustdoc-gui/font-weight.goml
+++ b/tests/rustdoc-gui/font-weight.goml
@@ -1,6 +1,6 @@
// This test checks that the font weight is correctly applied.
goto: "file://" + |DOC_PATH| + "/lib2/struct.Foo.html"
-assert-css: ("//*[@class='item-decl']//a[text()='Alias']", {"font-weight": "400"})
+assert-css: ("//*[@class='rust item-decl']//a[text()='Alias']", {"font-weight": "400"})
assert-css: (
"//*[@class='structfield small-section-header']//a[text()='Alias']",
{"font-weight": "400"},
@@ -19,8 +19,7 @@ goto: "file://" + |DOC_PATH| + "/lib2/trait.Trait.html"
// This is a complex selector, so here's how it works:
//
-// * //*[@class='item-decl'] — selects element of any tag with classes docblock and item-decl
-// * /pre[@class='rust'] — selects immediate child with tag pre and class rust
+// * //pre[@class='rust item-decl'] — selects item-decl code block
// * /code — selects immediate child with tag code
// * /a[@class='constant'] — selects immediate child with tag a and class constant
// * //text() — selects child that is text node
@@ -29,11 +28,11 @@ goto: "file://" + |DOC_PATH| + "/lib2/trait.Trait.html"
// This uses '/parent::*' as a proxy for the style of the text node.
// We can't just select the '<a>' because intermediate tags could be added.
assert-count: (
- "//*[@class='item-decl']/pre[@class='rust']/code/a[@class='constant']//text()/parent::*",
+ "//pre[@class='rust item-decl']/code/a[@class='constant']//text()/parent::*",
1,
)
assert-css: (
- "//*[@class='item-decl']/pre[@class='rust']/code/a[@class='constant']//text()/parent::*",
+ "//pre[@class='rust item-decl']/code/a[@class='constant']//text()/parent::*",
{"font-weight": "400"},
)
diff --git a/tests/rustdoc-gui/help-page.goml b/tests/rustdoc-gui/help-page.goml
index 5f4c1ba2f..6e2321a69 100644
--- a/tests/rustdoc-gui/help-page.goml
+++ b/tests/rustdoc-gui/help-page.goml
@@ -68,5 +68,4 @@ size: (1000, 1000) // Popover only appears when the screen width is >700px.
assert-false: "#help"
click: "#help-button > a"
click: ".popover a[href='https://doc.rust-lang.org/rustdoc/']"
-wait-for: 2000
-assert-document-property: {"URL": "https://doc.rust-lang.org/rustdoc/"}
+wait-for-document-property: {"URL": "https://doc.rust-lang.org/rustdoc/"}
diff --git a/tests/rustdoc-gui/huge-collection-of-constants.goml b/tests/rustdoc-gui/huge-collection-of-constants.goml
index 3ccd33f1c..636382a91 100644
--- a/tests/rustdoc-gui/huge-collection-of-constants.goml
+++ b/tests/rustdoc-gui/huge-collection-of-constants.goml
@@ -3,7 +3,7 @@
goto: "file://" + |DOC_PATH| + "/test_docs/huge_amount_of_consts/index.html"
compare-elements-position-near-false: (
- "//*[@class='item-table']//div[last()-1]",
- "//*[@class='item-table']//div[last()-3]",
+ "//ul[@class='item-table']/li[last()-1]",
+ "//ul[@class='item-table']/li[last()-3]",
{"y": 12},
)
diff --git a/tests/rustdoc-gui/item-summary-table.goml b/tests/rustdoc-gui/item-summary-table.goml
index 2a92e9da5..7a219bd54 100644
--- a/tests/rustdoc-gui/item-summary-table.goml
+++ b/tests/rustdoc-gui/item-summary-table.goml
@@ -1,6 +1,6 @@
// This test ensures that <table> elements aren't display in items summary.
goto: "file://" + |DOC_PATH| + "/lib2/summary_table/index.html"
// We check that we picked the right item first.
-assert-text: (".item-table .item-left", "Foo")
+assert-text: (".item-table .item-name", "Foo")
// Then we check that its summary is empty.
-assert-false: ".item-table .item-right"
+assert-false: ".item-table .desc"
diff --git a/tests/rustdoc-gui/label-next-to-symbol.goml b/tests/rustdoc-gui/label-next-to-symbol.goml
index 05f8ddc71..412e475dc 100644
--- a/tests/rustdoc-gui/label-next-to-symbol.goml
+++ b/tests/rustdoc-gui/label-next-to-symbol.goml
@@ -9,31 +9,31 @@ assert: (".stab.portability")
// make sure that deprecated and portability have the right colors
assert-css: (
- ".item-table .item-left .stab.deprecated",
+ ".item-table .item-name .stab.deprecated",
{ "background-color": "rgb(255, 245, 214)" },
)
assert-css: (
- ".item-table .item-left .stab.portability",
+ ".item-table .item-name .stab.portability",
{ "background-color": "rgb(255, 245, 214)" },
)
// table like view
-assert-css: (".item-right.docblock-short", { "padding-left": "0px" })
+assert-css: (".desc.docblock-short", { "padding-left": "0px" })
compare-elements-position-near: (
- "//*[@class='item-left module-item']//a[text()='replaced_function']",
- ".item-left .stab.deprecated",
+ "//*[@class='item-name']//a[text()='replaced_function']",
+ ".item-name .stab.deprecated",
{"y": 2},
)
compare-elements-position: (
- ".item-left .stab.deprecated",
- ".item-left .stab.portability",
+ ".item-name .stab.deprecated",
+ ".item-name .stab.portability",
("y"),
)
// Ensure no wrap
compare-elements-position: (
- "//*[@class='item-left module-item']//a[text()='replaced_function']/..",
- "//*[@class='item-right docblock-short'][text()='a thing with a label']",
+ "//*[@class='item-name']//a[text()='replaced_function']/..",
+ "//*[@class='desc docblock-short'][text()='a thing with a label']",
("y"),
)
@@ -41,26 +41,26 @@ compare-elements-position: (
// Mobile view
size: (600, 600)
// staggered layout with 2em spacing
-assert-css: (".item-right.docblock-short", { "padding-left": "32px" })
+assert-css: (".desc.docblock-short", { "padding-left": "32px" })
compare-elements-position-near: (
- "//*[@class='item-left module-item']//a[text()='replaced_function']",
- ".item-left .stab.deprecated",
+ "//*[@class='item-name']//a[text()='replaced_function']",
+ ".item-name .stab.deprecated",
{"y": 2},
)
compare-elements-position: (
- ".item-left .stab.deprecated",
- ".item-left .stab.portability",
+ ".item-name .stab.deprecated",
+ ".item-name .stab.portability",
("y"),
)
// Ensure wrap
compare-elements-position-false: (
- "//*[@class='item-left module-item']//a[text()='replaced_function']/..",
- "//*[@class='item-right docblock-short'][text()='a thing with a label']",
+ "//*[@class='item-name']//a[text()='replaced_function']/..",
+ "//*[@class='desc docblock-short'][text()='a thing with a label']",
("y"),
)
compare-elements-position-false: (
- ".item-left .stab.deprecated",
- "//*[@class='item-right docblock-short'][text()='a thing with a label']",
+ ".item-name .stab.deprecated",
+ "//*[@class='desc docblock-short'][text()='a thing with a label']",
("y"),
)
diff --git a/tests/rustdoc-gui/list_code_block.goml b/tests/rustdoc-gui/list_code_block.goml
index c527cfbfc..4c477d70c 100644
--- a/tests/rustdoc-gui/list_code_block.goml
+++ b/tests/rustdoc-gui/list_code_block.goml
@@ -1,4 +1,4 @@
// This test checks that code blocks in list are supported.
goto: "file://" + |DOC_PATH| + "/test_docs/index.html"
goto: "./fn.check_list_code_block.html"
-assert: (".item-decl pre.rust")
+assert: ("pre.rust.item-decl")
diff --git a/tests/rustdoc-gui/mobile.goml b/tests/rustdoc-gui/mobile.goml
index 895864d89..8c8516ebf 100644
--- a/tests/rustdoc-gui/mobile.goml
+++ b/tests/rustdoc-gui/mobile.goml
@@ -12,7 +12,7 @@ assert-css: (".main-heading", {
"flex-direction": "column"
})
-assert-property: (".mobile-topbar h2", {"offsetHeight": 36})
+assert-property: (".mobile-topbar h2", {"offsetHeight": 33})
// Note: We can't use assert-text here because the 'Since' is set by CSS and
// is therefore not part of the DOM.
@@ -28,7 +28,7 @@ goto: "file://" + |DOC_PATH| + "/settings.html"
size: (400, 600)
// Ignored for now https://github.com/rust-lang/rust/issues/93784.
// compare-elements-position-near-false: (
-// "#preferred-light-theme .setting-name",
-// "#preferred-light-theme .choice",
+// "#preferred-light-theme .setting-radio-name",
+// "#preferred-light-theme .setting-radio",
// {"y": 16},
// )
diff --git a/tests/rustdoc-gui/module-items-font.goml b/tests/rustdoc-gui/module-items-font.goml
index cd3676a98..23823f8b6 100644
--- a/tests/rustdoc-gui/module-items-font.goml
+++ b/tests/rustdoc-gui/module-items-font.goml
@@ -1,7 +1,7 @@
// This test checks that the correct font is used on module items (in index.html pages).
goto: "file://" + |DOC_PATH| + "/test_docs/index.html"
assert-css: (
- ".item-table .module-item a",
+ ".item-table .item-name > a",
{"font-family": '"Fira Sans", Arial, NanumBarunGothic, sans-serif'},
ALL,
)
@@ -13,55 +13,55 @@ assert-css: (
// modules
assert-css: (
- "#modules + .item-table .item-left a",
+ "#modules + .item-table .item-name a",
{"font-family": '"Fira Sans", Arial, NanumBarunGothic, sans-serif'},
)
assert-css: (
- "#modules + .item-table .item-right.docblock-short",
+ "#modules + .item-table .desc.docblock-short",
{"font-family": '"Source Serif 4", NanumBarunGothic, serif'},
)
// structs
assert-css: (
- "#structs + .item-table .item-left a",
+ "#structs + .item-table .item-name a",
{"font-family": '"Fira Sans", Arial, NanumBarunGothic, sans-serif'},
)
assert-css: (
- "#structs + .item-table .item-right.docblock-short",
+ "#structs + .item-table .desc.docblock-short",
{"font-family": '"Source Serif 4", NanumBarunGothic, serif'},
)
// enums
assert-css: (
- "#enums + .item-table .item-left a",
+ "#enums + .item-table .item-name a",
{"font-family": '"Fira Sans", Arial, NanumBarunGothic, sans-serif'},
)
assert-css: (
- "#enums + .item-table .item-right.docblock-short",
+ "#enums + .item-table .desc.docblock-short",
{"font-family": '"Source Serif 4", NanumBarunGothic, serif'},
)
// traits
assert-css: (
- "#traits + .item-table .item-left a",
+ "#traits + .item-table .item-name a",
{"font-family": '"Fira Sans", Arial, NanumBarunGothic, sans-serif'},
)
assert-css: (
- "#traits + .item-table .item-right.docblock-short",
+ "#traits + .item-table .desc.docblock-short",
{"font-family": '"Source Serif 4", NanumBarunGothic, serif'},
)
// functions
assert-css: (
- "#functions + .item-table .item-left a",
+ "#functions + .item-table .item-name a",
{"font-family": '"Fira Sans", Arial, NanumBarunGothic, sans-serif'},
)
assert-css: (
- "#functions + .item-table .item-right.docblock-short",
+ "#functions + .item-table .desc.docblock-short",
{"font-family": '"Source Serif 4", NanumBarunGothic, serif'},
)
// keywords
assert-css: (
- "#keywords + .item-table .item-left a",
+ "#keywords + .item-table .item-name a",
{"font-family": '"Fira Sans", Arial, NanumBarunGothic, sans-serif'},
)
assert-css: (
- "#keywords + .item-table .item-right.docblock-short",
+ "#keywords + .item-table .desc.docblock-short",
{"font-family": '"Source Serif 4", NanumBarunGothic, serif'},
)
diff --git a/tests/rustdoc-gui/notable-trait.goml b/tests/rustdoc-gui/notable-trait.goml
index b4fa7d0db..207289151 100644
--- a/tests/rustdoc-gui/notable-trait.goml
+++ b/tests/rustdoc-gui/notable-trait.goml
@@ -6,13 +6,13 @@ size: (1100, 600)
// Checking they have the same y position.
compare-elements-position: (
"//*[@id='method.create_an_iterator_from_read']//a[text()='NotableStructWithLongName']",
- "//*[@id='method.create_an_iterator_from_read']//*[@class='notable-traits']",
+ "//*[@id='method.create_an_iterator_from_read']//*[@class='tooltip']",
("y"),
)
// Checking they don't have the same x position.
compare-elements-position-false: (
"//*[@id='method.create_an_iterator_from_read']//a[text()='NotableStructWithLongName']",
- "//*[@id='method.create_an_iterator_from_read']//*[@class='notable-traits']",
+ "//*[@id='method.create_an_iterator_from_read']//*[@class='tooltip']",
("x"),
)
// The `i` should be *after* the type.
@@ -21,33 +21,33 @@ assert-position: (
{"x": 677},
)
assert-position: (
- "//*[@id='method.create_an_iterator_from_read']//*[@class='notable-traits']",
+ "//*[@id='method.create_an_iterator_from_read']//*[@class='tooltip']",
{"x": 955},
)
// The tooltip should be below the `i`
// Also, clicking the tooltip should bring its text into the DOM
-assert-count: ("//*[@class='notable popover']", 0)
-click: "//*[@id='method.create_an_iterator_from_read']//*[@class='notable-traits']"
-assert-count: ("//*[@class='notable popover']", 1)
+assert-count: ("//*[@class='tooltip popover']", 0)
+click: "//*[@id='method.create_an_iterator_from_read']//*[@class='tooltip']"
+assert-count: ("//*[@class='tooltip popover']", 1)
compare-elements-position-near: (
- "//*[@id='method.create_an_iterator_from_read']//*[@class='notable-traits']",
- "//*[@class='notable popover']",
+ "//*[@id='method.create_an_iterator_from_read']//*[@class='tooltip']",
+ "//*[@class='tooltip popover']",
{"y": 30}
)
compare-elements-position-false: (
- "//*[@id='method.create_an_iterator_from_read']//*[@class='notable-traits']",
- "//*[@class='notable popover']",
+ "//*[@id='method.create_an_iterator_from_read']//*[@class='tooltip']",
+ "//*[@class='tooltip popover']",
("x")
)
-click: "//*[@id='method.create_an_iterator_from_read']//*[@class='notable-traits']"
+click: "//*[@id='method.create_an_iterator_from_read']//*[@class='tooltip']"
move-cursor-to: "//h1"
-assert-count: ("//*[@class='notable popover']", 0)
+assert-count: ("//*[@class='tooltip popover']", 0)
// Now only the `i` should be on the next line.
size: (1055, 600)
compare-elements-position-false: (
"//*[@id='method.create_an_iterator_from_read']//a[text()='NotableStructWithLongName']",
- "//*[@id='method.create_an_iterator_from_read']//*[@class='notable-traits']",
+ "//*[@id='method.create_an_iterator_from_read']//*[@class='tooltip']",
("y", "x"),
)
@@ -56,13 +56,13 @@ size: (980, 600)
// Checking they have the same y position.
compare-elements-position: (
"//*[@id='method.create_an_iterator_from_read']//a[text()='NotableStructWithLongName']",
- "//*[@id='method.create_an_iterator_from_read']//*[@class='notable-traits']",
+ "//*[@id='method.create_an_iterator_from_read']//*[@class='tooltip']",
("y"),
)
// Checking they don't have the same x position.
compare-elements-position-false: (
"//*[@id='method.create_an_iterator_from_read']//a[text()='NotableStructWithLongName']",
- "//*[@id='method.create_an_iterator_from_read']//*[@class='notable-traits']",
+ "//*[@id='method.create_an_iterator_from_read']//*[@class='tooltip']",
("x"),
)
// The `i` should be *after* the type.
@@ -71,7 +71,7 @@ assert-position: (
{"x": 245},
)
assert-position: (
- "//*[@id='method.create_an_iterator_from_read']//*[@class='notable-traits']",
+ "//*[@id='method.create_an_iterator_from_read']//*[@class='tooltip']",
{"x": 523},
)
@@ -80,13 +80,13 @@ size: (650, 600)
// Checking they have the same y position.
compare-elements-position: (
"//*[@id='method.create_an_iterator_from_read']//a[text()='NotableStructWithLongName']",
- "//*[@id='method.create_an_iterator_from_read']//*[@class='notable-traits']",
+ "//*[@id='method.create_an_iterator_from_read']//*[@class='tooltip']",
("y"),
)
// Checking they don't have the same x position.
compare-elements-position-false: (
"//*[@id='method.create_an_iterator_from_read']//a[text()='NotableStructWithLongName']",
- "//*[@id='method.create_an_iterator_from_read']//*[@class='notable-traits']",
+ "//*[@id='method.create_an_iterator_from_read']//*[@class='tooltip']",
("x"),
)
// The `i` should be *after* the type.
@@ -95,29 +95,29 @@ assert-position: (
{"x": 15},
)
assert-position: (
- "//*[@id='method.create_an_iterator_from_read']//*[@class='notable-traits']",
+ "//*[@id='method.create_an_iterator_from_read']//*[@class='tooltip']",
{"x": 293},
)
// The tooltip should STILL be below `i`
-click: "//*[@id='method.create_an_iterator_from_read']//*[@class='notable-traits']"
-assert-count: ("//*[@class='notable popover']", 1)
+click: "//*[@id='method.create_an_iterator_from_read']//*[@class='tooltip']"
+assert-count: ("//*[@class='tooltip popover']", 1)
compare-elements-position-near: (
- "//*[@id='method.create_an_iterator_from_read']//*[@class='notable-traits']",
- "//*[@class='notable popover']",
+ "//*[@id='method.create_an_iterator_from_read']//*[@class='tooltip']",
+ "//*[@class='tooltip popover']",
{"y": 30}
)
compare-elements-position-false: (
- "//*[@id='method.create_an_iterator_from_read']//*[@class='notable-traits']",
- "//*[@class='notable popover']",
+ "//*[@id='method.create_an_iterator_from_read']//*[@class='tooltip']",
+ "//*[@class='tooltip popover']",
("x")
)
assert-position: (
- "//*[@class='notable popover']",
+ "//*[@class='tooltip popover']",
{"x": 0}
)
-click: "//*[@id='method.create_an_iterator_from_read']//*[@class='notable-traits']"
+click: "//*[@id='method.create_an_iterator_from_read']//*[@class='tooltip']"
move-cursor-to: "//h1"
-assert-count: ("//*[@class='notable popover']", 0)
+assert-count: ("//*[@class='tooltip popover']", 0)
// Now check the colors.
define-function: (
@@ -133,26 +133,26 @@ define-function: (
// We reload the page so the local storage settings are being used.
reload:
- move-cursor-to: "//*[@id='method.create_an_iterator_from_read']//*[@class='notable-traits']"
- assert-count: (".notable.popover", 1)
+ move-cursor-to: "//*[@id='method.create_an_iterator_from_read']//*[@class='tooltip']"
+ assert-count: (".tooltip.popover", 1)
assert-css: (
- ".notable.popover h3",
+ ".tooltip.popover h3",
{"color": |header_color|},
ALL,
)
assert-css: (
- ".notable.popover pre",
+ ".tooltip.popover pre",
{"color": |content_color|},
ALL,
)
assert-css: (
- ".notable.popover pre a.struct",
+ ".tooltip.popover pre a.struct",
{"color": |type_color|},
ALL,
)
assert-css: (
- ".notable.popover pre a.trait",
+ ".tooltip.popover pre a.trait",
{"color": |trait_color|},
ALL,
)
@@ -195,24 +195,24 @@ call-function: (
reload:
// Check that pressing escape works
-click: "//*[@id='method.create_an_iterator_from_read']//*[@class='notable-traits']"
-move-cursor-to: "//*[@class='notable popover']"
-assert-count: ("//*[@class='notable popover']", 1)
+click: "//*[@id='method.create_an_iterator_from_read']//*[@class='tooltip']"
+move-cursor-to: "//*[@class='tooltip popover']"
+assert-count: ("//*[@class='tooltip popover']", 1)
press-key: "Escape"
-assert-count: ("//*[@class='notable popover']", 0)
-assert: "#method\.create_an_iterator_from_read .notable-traits:focus"
+assert-count: ("//*[@class='tooltip popover']", 0)
+assert: "#method\.create_an_iterator_from_read .tooltip:focus"
// Check that clicking outside works.
-click: "//*[@id='method.create_an_iterator_from_read']//*[@class='notable-traits']"
-assert-count: ("//*[@class='notable popover']", 1)
+click: "//*[@id='method.create_an_iterator_from_read']//*[@class='tooltip']"
+assert-count: ("//*[@class='tooltip popover']", 1)
click: ".search-input"
-assert-count: ("//*[@class='notable popover']", 0)
-assert-false: "#method\.create_an_iterator_from_read .notable-traits:focus"
+assert-count: ("//*[@class='tooltip popover']", 0)
+assert-false: "#method\.create_an_iterator_from_read .tooltip:focus"
// Check that pressing tab over and over works.
-click: "//*[@id='method.create_an_iterator_from_read']//*[@class='notable-traits']"
-move-cursor-to: "//*[@class='notable popover']"
-assert-count: ("//*[@class='notable popover']", 1)
+click: "//*[@id='method.create_an_iterator_from_read']//*[@class='tooltip']"
+move-cursor-to: "//*[@class='tooltip popover']"
+assert-count: ("//*[@class='tooltip popover']", 1)
press-key: "Tab"
press-key: "Tab"
press-key: "Tab"
@@ -220,8 +220,8 @@ press-key: "Tab"
press-key: "Tab"
press-key: "Tab"
press-key: "Tab"
-assert-count: ("//*[@class='notable popover']", 0)
-assert: "#method\.create_an_iterator_from_read .notable-traits:focus"
+assert-count: ("//*[@class='tooltip popover']", 0)
+assert: "#method\.create_an_iterator_from_read .tooltip:focus"
// Now we check that the focus isn't given back to the wrong item when opening
// another popover.
@@ -231,8 +231,8 @@ click: "#method\.create_an_iterator_from_read .fn"
assert-window-property-false: {"scrollY": |scroll|}
// Store the new position.
store-window-property: (scroll, "scrollY")
-click: "//*[@id='method.create_an_iterator_from_read']//*[@class='notable-traits']"
-wait-for: "//*[@class='notable popover']"
+click: "//*[@id='method.create_an_iterator_from_read']//*[@class='tooltip']"
+wait-for: "//*[@class='tooltip popover']"
click: "#settings-menu a"
click: ".search-input"
// We ensure we didn't come back to the previous focused item.
@@ -245,8 +245,8 @@ click: "#method\.create_an_iterator_from_read .fn"
assert-window-property-false: {"scrollY": |scroll|}
// Store the new position.
store-window-property: (scroll, "scrollY")
-click: "//*[@id='method.create_an_iterator_from_read']//*[@class='notable-traits']"
-wait-for: "//*[@class='notable popover']"
+click: "//*[@id='method.create_an_iterator_from_read']//*[@class='tooltip']"
+wait-for: "//*[@class='tooltip popover']"
click: "#settings-menu a"
press-key: "Escape"
// We ensure we didn't come back to the previous focused item.
@@ -254,23 +254,23 @@ assert-window-property-false: {"scrollY": |scroll|}
// Opening the mobile sidebar should close the popover.
size: (650, 600)
-click: "//*[@id='method.create_an_iterator_from_read']//*[@class='notable-traits']"
-assert-count: ("//*[@class='notable popover']", 1)
+click: "//*[@id='method.create_an_iterator_from_read']//*[@class='tooltip']"
+assert-count: ("//*[@class='tooltip popover']", 1)
click: ".sidebar-menu-toggle"
assert: "//*[@class='sidebar shown']"
-assert-count: ("//*[@class='notable popover']", 0)
-assert-false: "#method\.create_an_iterator_from_read .notable-traits:focus"
-// Clicking a notable popover should close the sidebar.
-click: "//*[@id='method.create_an_iterator_from_read']//*[@class='notable-traits']"
-assert-count: ("//*[@class='notable popover']", 1)
+assert-count: ("//*[@class='tooltip popover']", 0)
+assert-false: "#method\.create_an_iterator_from_read .tooltip:focus"
+// Clicking a notable trait tooltip popover should close the sidebar.
+click: "//*[@id='method.create_an_iterator_from_read']//*[@class='tooltip']"
+assert-count: ("//*[@class='tooltip popover']", 1)
assert-false: "//*[@class='sidebar shown']"
// Also check the focus handling for the help button.
size: (1100, 600)
reload:
-assert-count: ("//*[@class='notable popover']", 0)
-click: "//*[@id='method.create_an_iterator_from_read']//*[@class='notable-traits']"
-assert-count: ("//*[@class='notable popover']", 1)
+assert-count: ("//*[@class='tooltip popover']", 0)
+click: "//*[@id='method.create_an_iterator_from_read']//*[@class='tooltip']"
+assert-count: ("//*[@class='tooltip popover']", 1)
click: "#help-button a"
-assert-count: ("//*[@class='notable popover']", 0)
-assert-false: "#method\.create_an_iterator_from_read .notable-traits:focus"
+assert-count: ("//*[@class='tooltip popover']", 0)
+assert-false: "#method\.create_an_iterator_from_read .tooltip:focus"
diff --git a/tests/rustdoc-gui/scrape-examples-color.goml b/tests/rustdoc-gui/scrape-examples-color.goml
index 40f31b277..67c58826e 100644
--- a/tests/rustdoc-gui/scrape-examples-color.goml
+++ b/tests/rustdoc-gui/scrape-examples-color.goml
@@ -58,3 +58,39 @@ call-function: ("check-colors", {
"help_hover_border": "rgb(0, 0, 0)",
"help_hover_color": "rgb(0, 0, 0)",
})
+
+// Now testing the top and bottom background in case there is only one scraped examples.
+goto: "file://" + |DOC_PATH| + "/scrape_examples/fn.test.html"
+
+define-function: (
+ "check-background",
+ (theme, background_color_start, background_color_end),
+ block {
+ local-storage: { "rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false", }
+ reload:
+ assert-css: (".scraped-example:not(.expanded) .code-wrapper::before", {
+ "background-image": "linear-gradient(" + |background_color_start| + ", " +
+ |background_color_end| + ")",
+ })
+ assert-css: (".scraped-example:not(.expanded) .code-wrapper::after", {
+ "background-image": "linear-gradient(to top, " + |background_color_start| + ", " +
+ |background_color_end| + ")",
+ })
+ },
+)
+
+call-function: ("check-background", {
+ "theme": "ayu",
+ "background_color_start": "rgb(15, 20, 25)",
+ "background_color_end": "rgba(15, 20, 25, 0)",
+})
+call-function: ("check-background", {
+ "theme": "dark",
+ "background_color_start": "rgb(53, 53, 53)",
+ "background_color_end": "rgba(53, 53, 53, 0)",
+})
+call-function: ("check-background", {
+ "theme": "light",
+ "background_color_start": "rgb(255, 255, 255)",
+ "background_color_end": "rgba(255, 255, 255, 0)",
+})
diff --git a/tests/rustdoc-gui/scrape-examples-layout.goml b/tests/rustdoc-gui/scrape-examples-layout.goml
index 95102528e..dad727c77 100644
--- a/tests/rustdoc-gui/scrape-examples-layout.goml
+++ b/tests/rustdoc-gui/scrape-examples-layout.goml
@@ -40,10 +40,10 @@ assert-property: (
store-value: (offset_y, 4)
// First with desktop
-assert-position: (".scraped-example .code-wrapper", {"y": 255})
-assert-position: (".scraped-example .code-wrapper .prev", {"y": 255 + |offset_y|})
+assert-position: (".scraped-example .code-wrapper", {"y": 253})
+assert-position: (".scraped-example .code-wrapper .prev", {"y": 253 + |offset_y|})
// Then with mobile
size: (600, 600)
-assert-position: (".scraped-example .code-wrapper", {"y": 314})
-assert-position: (".scraped-example .code-wrapper .prev", {"y": 314 + |offset_y|})
+assert-position: (".scraped-example .code-wrapper", {"y": 308})
+assert-position: (".scraped-example .code-wrapper .prev", {"y": 308 + |offset_y|})
diff --git a/tests/rustdoc-gui/search-error.goml b/tests/rustdoc-gui/search-error.goml
new file mode 100644
index 000000000..2a10a647b
--- /dev/null
+++ b/tests/rustdoc-gui/search-error.goml
@@ -0,0 +1,39 @@
+// Checks that the crate search filtering is handled correctly and changes the results.
+goto: "file://" + |DOC_PATH| + "/test_docs/index.html?search=sa'%3Bda'%3Bds"
+show-text: true
+
+define-function: (
+ "check-colors",
+ (theme, error_background),
+ block {
+ // Setting the theme.
+ local-storage: {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"}
+ // We reload the page so the local storage settings are being used.
+ reload:
+
+ wait-for: "#search .error code"
+ assert-css: ("#search .error code", {"background-color": |error_background|})
+ }
+)
+
+call-function: (
+ "check-colors",
+ {
+ "theme": "ayu",
+ "error_background": "rgb(79, 76, 76)",
+ },
+)
+call-function: (
+ "check-colors",
+ {
+ "theme": "dark",
+ "error_background": "rgb(72, 72, 72)",
+ },
+)
+call-function: (
+ "check-colors",
+ {
+ "theme": "light",
+ "error_background": "rgb(208, 204, 204)",
+ },
+)
diff --git a/tests/rustdoc-gui/search-result-display.goml b/tests/rustdoc-gui/search-result-display.goml
index 43e608228..20a88c36e 100644
--- a/tests/rustdoc-gui/search-result-display.goml
+++ b/tests/rustdoc-gui/search-result-display.goml
@@ -22,7 +22,7 @@ size: (900, 900)
// First we check the current width, height and position.
assert-css: ("#crate-search", {"width": "223px"})
-assert-css: (".search-results-title", {"height": "44px", "width": "640px"})
+assert-css: (".search-results-title", {"height": "50px", "width": "640px"})
assert-css: ("#search", {"width": "640px"})
// Then we update the text of one of the `<option>`.
@@ -33,7 +33,7 @@ text: (
// Then we compare again to confirm the height didn't change.
assert-css: ("#crate-search", {"width": "527px"})
-assert-css: (".search-results-title", {"height": "44px", "width": "640px"})
+assert-css: (".search-results-title", {"height": "50px", "width": "640px"})
// And we check that the `<select>` isn't bigger than its container (".search-results-title").
assert-css: ("#search", {"width": "640px"})
diff --git a/tests/rustdoc-gui/settings.goml b/tests/rustdoc-gui/settings.goml
index 419cc5eba..a84172885 100644
--- a/tests/rustdoc-gui/settings.goml
+++ b/tests/rustdoc-gui/settings.goml
@@ -43,12 +43,12 @@ wait-for: "#settings"
// We check that the "Use system theme" is disabled.
assert-property: ("#theme-system-preference", {"checked": "false"})
// Meaning that only the "theme" menu is showing up.
-assert: ".setting-line:not(.hidden) #theme"
-assert: ".setting-line.hidden #preferred-dark-theme"
-assert: ".setting-line.hidden #preferred-light-theme"
+assert: "#theme.setting-line:not(.hidden)"
+assert: "#preferred-dark-theme.setting-line.hidden"
+assert: "#preferred-light-theme.setting-line.hidden"
// We check that the correct theme is selected.
-assert-property: ("#theme .choices #theme-dark", {"checked": "true"})
+assert-property: ("#theme .setting-radio-choices #theme-dark", {"checked": "true"})
// Some style checks...
move-cursor-to: "#settings-menu > a"
@@ -109,31 +109,31 @@ assert-css: (
"box-shadow": "rgb(33, 150, 243) 0px 0px 1px 1px",
},
)
-// Now we check the setting-name for radio buttons is on a different line than the label.
+// Now we check the setting-radio-name is on a different line than the label.
compare-elements-position-near: (
- "#theme .setting-name",
- "#theme .choices",
+ "#theme .setting-radio-name",
+ "#theme .setting-radio-choices",
{"x": 1}
)
compare-elements-position-near-false: (
- "#theme .setting-name",
- "#theme .choices",
+ "#theme .setting-radio-name",
+ "#theme .setting-radio-choices",
{"y": 1}
)
// Now we check that the label positions are all on the same line.
compare-elements-position-near: (
- "#theme .choices #theme-light",
- "#theme .choices #theme-dark",
+ "#theme .setting-radio-choices #theme-light",
+ "#theme .setting-radio-choices #theme-dark",
{"y": 1}
)
compare-elements-position-near: (
- "#theme .choices #theme-dark",
- "#theme .choices #theme-ayu",
+ "#theme .setting-radio-choices #theme-dark",
+ "#theme .setting-radio-choices #theme-ayu",
{"y": 1}
)
compare-elements-position-near: (
- "#theme .choices #theme-ayu",
- "#theme .choices #theme-system-preference",
+ "#theme .setting-radio-choices #theme-ayu",
+ "#theme .setting-radio-choices #theme-system-preference",
{"y": 1}
)
@@ -180,17 +180,17 @@ assert-css: (
// We now switch the display.
click: "#theme-system-preference"
// Wait for the hidden element to show up.
-wait-for: ".setting-line:not(.hidden) #preferred-dark-theme"
-assert: ".setting-line:not(.hidden) #preferred-light-theme"
+wait-for: "#preferred-dark-theme.setting-line:not(.hidden)"
+assert: "#preferred-light-theme.setting-line:not(.hidden)"
// We check their text as well.
-assert-text: ("#preferred-dark-theme .setting-name", "Preferred dark theme")
-assert-text: ("#preferred-light-theme .setting-name", "Preferred light theme")
+assert-text: ("#preferred-dark-theme .setting-radio-name", "Preferred dark theme")
+assert-text: ("#preferred-light-theme .setting-radio-name", "Preferred light theme")
// We now check that clicking on the toggles' text is like clicking on the checkbox.
// To test it, we use the "Disable keyboard shortcuts".
local-storage: {"rustdoc-disable-shortcuts": "false"}
-click: ".setting-line:last-child .settings-toggle .label"
+click: ".setting-line:last-child .setting-check span"
assert-local-storage: {"rustdoc-disable-shortcuts": "true"}
// Make sure that "Disable keyboard shortcuts" actually took effect.
@@ -200,7 +200,7 @@ assert-false: "#help-button .popover"
wait-for-css: ("#settings-menu .popover", {"display": "block"})
// Now turn keyboard shortcuts back on, and see if they work.
-click: ".setting-line:last-child .settings-toggle .label"
+click: ".setting-line:last-child .setting-check span"
assert-local-storage: {"rustdoc-disable-shortcuts": "false"}
press-key: "Escape"
press-key: "?"
diff --git a/tests/rustdoc-gui/sidebar-mobile-scroll.goml b/tests/rustdoc-gui/sidebar-mobile-scroll.goml
index 2449269b1..4442b263e 100644
--- a/tests/rustdoc-gui/sidebar-mobile-scroll.goml
+++ b/tests/rustdoc-gui/sidebar-mobile-scroll.goml
@@ -6,7 +6,7 @@ assert-css: (".sidebar", {"display": "block", "left": "-1000px"})
// Scroll down.
scroll-to: "//h2[@id='blanket-implementations']"
-assert-window-property: {"pageYOffset": "627"}
+assert-window-property: {"pageYOffset": "622"}
// Open the sidebar menu.
click: ".sidebar-menu-toggle"
@@ -21,11 +21,11 @@ assert-window-property: {"pageYOffset": "0"}
// Close the sidebar menu. Make sure the scroll position gets restored.
click: ".sidebar-menu-toggle"
wait-for-css: (".sidebar", {"left": "-1000px"})
-assert-window-property: {"pageYOffset": "627"}
+assert-window-property: {"pageYOffset": "622"}
// Now test that scrollability returns when the browser window is just resized.
click: ".sidebar-menu-toggle"
wait-for-css: (".sidebar", {"left": "0px"})
assert-window-property: {"pageYOffset": "0"}
size: (900, 600)
-assert-window-property: {"pageYOffset": "627"}
+assert-window-property: {"pageYOffset": "622"}
diff --git a/tests/rustdoc-gui/sidebar-mobile.goml b/tests/rustdoc-gui/sidebar-mobile.goml
index d5f4b6196..cc6267c3d 100644
--- a/tests/rustdoc-gui/sidebar-mobile.goml
+++ b/tests/rustdoc-gui/sidebar-mobile.goml
@@ -45,7 +45,7 @@ assert-property: (".mobile-topbar", {"clientHeight": "45"})
// so the target is not obscured by the topbar.
click: ".sidebar-menu-toggle"
click: ".sidebar-elems section .block li > a"
-assert-position: ("#method\.must_use", {"y": 45})
+assert-position: ("#method\.must_use", {"y": 46})
// Check that the bottom-most item on the sidebar menu can be scrolled fully into view.
click: ".sidebar-menu-toggle"
diff --git a/tests/rustdoc-gui/sidebar.goml b/tests/rustdoc-gui/sidebar.goml
index 9c742be05..a6d517090 100644
--- a/tests/rustdoc-gui/sidebar.goml
+++ b/tests/rustdoc-gui/sidebar.goml
@@ -70,8 +70,8 @@ assert-text: (".sidebar-elems section ul > li:nth-child(8)", "Functions")
assert-text: (".sidebar-elems section ul > li:nth-child(9)", "Type Definitions")
assert-text: (".sidebar-elems section ul > li:nth-child(10)", "Unions")
assert-text: (".sidebar-elems section ul > li:nth-child(11)", "Keywords")
-assert-text: ("#structs + .item-table .item-left > a", "Foo")
-click: "#structs + .item-table .item-left > a"
+assert-text: ("#structs + .item-table .item-name > a", "Foo")
+click: "#structs + .item-table .item-name > a"
// PAGE: struct.Foo.html
assert-count: (".sidebar .location", 1)
@@ -103,8 +103,8 @@ assert-text: (".sidebar-elems > section ul.block > li:nth-child(2)", "Structs")
assert-text: (".sidebar-elems > section ul.block > li:nth-child(3)", "Traits")
assert-text: (".sidebar-elems > section ul.block > li:nth-child(4)", "Functions")
assert-text: (".sidebar-elems > section ul.block > li:nth-child(5)", "Type Definitions")
-assert-text: ("#functions + .item-table .item-left > a", "foobar")
-click: "#functions + .item-table .item-left > a"
+assert-text: ("#functions + .item-table .item-name > a", "foobar")
+click: "#functions + .item-table .item-name > a"
// PAGE: fn.foobar.html
// In items containing no items (like functions or constants) and in modules, we have no
@@ -127,7 +127,7 @@ assert-text: (".sidebar > .location", "Module sub_sub_module")
// We check that we don't have the crate list.
assert-false: ".sidebar-elems .crate"
assert-text: (".sidebar-elems > section ul > li:nth-child(1)", "Functions")
-assert-text: ("#functions + .item-table .item-left > a", "foo")
+assert-text: ("#functions + .item-table .item-name > a", "foo")
// Links to trait implementations in the sidebar should not wrap even if they are long.
goto: "file://" + |DOC_PATH| + "/lib2/struct.HasALongTraitWithParams.html"
diff --git a/tests/rustdoc-gui/src-font-size.goml b/tests/rustdoc-gui/src-font-size.goml
index 9233f3744..bab66dae7 100644
--- a/tests/rustdoc-gui/src-font-size.goml
+++ b/tests/rustdoc-gui/src-font-size.goml
@@ -4,13 +4,13 @@
goto: "file://" + |DOC_PATH| + "/test_docs/struct.Foo.html"
show-text: true
// Check the impl headers.
-assert-css: (".impl.has-srclink .srclink", {"font-size": "16px", "font-weight": 400}, ALL)
-assert-css: (".impl.has-srclink .code-header", {"font-size": "18px", "font-weight": 600}, ALL)
+assert-css: (".impl .srclink", {"font-size": "16px", "font-weight": 400}, ALL)
+assert-css: (".impl .code-header", {"font-size": "18px", "font-weight": 600}, ALL)
// Check the impl items.
-assert-css: (".impl-items .has-srclink .srclink", {"font-size": "16px", "font-weight": 400}, ALL)
-assert-css: (".impl-items .has-srclink .code-header", {"font-size": "16px", "font-weight": 600}, ALL)
+assert-css: (".impl-items .srclink", {"font-size": "16px", "font-weight": 400}, ALL)
+assert-css: (".impl-items .code-header", {"font-size": "16px", "font-weight": 600}, ALL)
// Check that we can click on source link
store-document-property: (url, "URL")
-click: ".impl-items .has-srclink .srclink"
+click: ".impl-items .srclink"
assert-document-property-false: {"URL": |url|}
diff --git a/tests/rustdoc-gui/src/test_docs/lib.rs b/tests/rustdoc-gui/src/test_docs/lib.rs
index 512504396..6ad1e8b4f 100644
--- a/tests/rustdoc-gui/src/test_docs/lib.rs
+++ b/tests/rustdoc-gui/src/test_docs/lib.rs
@@ -340,7 +340,7 @@ pub mod details {
pub mod doc_block_table {
pub trait DocBlockTableTrait {
- fn func();
+ fn foo();
}
/// Struct doc.
@@ -359,7 +359,7 @@ pub mod doc_block_table {
/// | header1 | header2 |
/// |--------------------------|--------------------------|
/// | Lorem Ipsum, Lorem Ipsum | Lorem Ipsum, Lorem Ipsum |
- fn func() {
+ fn foo() {
println!();
}
}
@@ -474,3 +474,15 @@ impl TypeWithImplDoc {
///
/// </sub>
pub mod codeblock_sub {}
+pub mod search_results {
+
+ pub struct SearchResults {
+ pub foo: i32,
+ }
+
+ #[macro_export]
+ macro_rules! foo {
+ () => {};
+ }
+
+}
diff --git a/tests/rustdoc-gui/theme-change.goml b/tests/rustdoc-gui/theme-change.goml
index cc47f1f45..31c9d99aa 100644
--- a/tests/rustdoc-gui/theme-change.goml
+++ b/tests/rustdoc-gui/theme-change.goml
@@ -43,7 +43,7 @@ assert-local-storage: { "rustdoc-theme": "ayu" }
assert-local-storage-false: { "rustdoc-use-system-theme": "true" }
click: "#theme-system-preference"
-wait-for: ".setting-line:not(.hidden) #preferred-light-theme"
+wait-for: "#preferred-light-theme.setting-line:not(.hidden)"
assert-local-storage: { "rustdoc-use-system-theme": "true" }
// We click on both preferred light and dark themes to be sure that there is a change.
click: "#preferred-light-theme-dark"
@@ -52,16 +52,16 @@ wait-for-css: ("body", { "background-color": |background_dark| })
reload:
// Ensure that the "preferred themes" are still displayed.
-wait-for: ".setting-line:not(.hidden) #preferred-light-theme"
+wait-for: "#preferred-light-theme.setting-line:not(.hidden)"
click: "#theme-light"
wait-for-css: ("body", { "background-color": |background_light| })
assert-local-storage: { "rustdoc-theme": "light" }
// Ensure it's now hidden again
-wait-for: ".setting-line.hidden #preferred-light-theme"
+wait-for: "#preferred-light-theme.setting-line.hidden"
// And ensure the theme was rightly set.
wait-for-css: ("body", { "background-color": |background_light| })
assert-local-storage: { "rustdoc-theme": "light" }
reload:
wait-for: "#settings"
-assert: ".setting-line.hidden #preferred-light-theme"
+assert: "#preferred-light-theme.setting-line.hidden"
diff --git a/tests/rustdoc-gui/type-declation-overflow.goml b/tests/rustdoc-gui/type-declation-overflow.goml
index 644429c01..708e9dca0 100644
--- a/tests/rustdoc-gui/type-declation-overflow.goml
+++ b/tests/rustdoc-gui/type-declation-overflow.goml
@@ -12,7 +12,7 @@ size: (1100, 800)
// Logically, the <body> scroll width should be the width of the window.
assert-property: ("body", {"scrollWidth": "1100"})
// However, since there is overflow in the type declaration, its scroll width is bigger.
-assert-property: (".item-decl pre", {"scrollWidth": "1324"})
+assert-property: ("pre.item-decl", {"scrollWidth": "1324"})
// In the table-ish view on the module index, the name should not be wrapped more than necessary.
goto: "file://" + |DOC_PATH| + "/lib2/too_long/index.html"
@@ -24,7 +24,7 @@ assert-property: ("body", {"scrollWidth": "1100"})
// We now check that the section width hasn't grown because of it.
assert-property: ("#main-content", {"scrollWidth": "840"})
// And now checking that it has scrollable content.
-assert-property: (".item-decl pre", {"scrollWidth": "1103"})
+assert-property: ("pre.item-decl", {"scrollWidth": "1103"})
// ... and constant.
// On a sidenote, it also checks that the (very) long title isn't changing the docblock width.
@@ -33,7 +33,7 @@ assert-property: ("body", {"scrollWidth": "1100"})
// We now check that the section width hasn't grown because of it.
assert-property: ("#main-content", {"scrollWidth": "840"})
// And now checking that it has scrollable content.
-assert-property: (".item-decl pre", {"scrollWidth": "950"})
+assert-property: ("pre.item-decl", {"scrollWidth": "950"})
// On mobile:
size: (600, 600)
@@ -65,12 +65,12 @@ compare-elements-position-false: (".main-heading h1", ".main-heading .out-of-ban
goto: "file://" + |DOC_PATH| + "/lib2/scroll_traits/trait.Iterator.html"
click: ".item-decl .type-contents-toggle"
-assert-property: (".item-decl > pre", {"scrollLeft": 0})
-scroll-to: "//*[@class='item-decl']//details/a[text()='String']"
-assert-property-false: (".item-decl > pre", {"scrollLeft": 0})
+assert-property: ("pre.item-decl", {"scrollLeft": 0})
+scroll-to: "//*[@class='rust item-decl']//details/a[text()='String']"
+assert-property-false: ("pre.item-decl", {"scrollLeft": 0})
// Then on an item without "hidden methods".
goto: "file://" + |DOC_PATH| + "/lib2/scroll_traits/trait.TraitWithLongItemsName.html"
-assert-property: (".item-decl > pre", {"scrollLeft": 0})
-scroll-to: "//*[@class='item-decl']//code/a[text()='String']"
-assert-property-false: (".item-decl > pre", {"scrollLeft": 0})
+assert-property: ("pre.item-decl", {"scrollLeft": 0})
+scroll-to: "//*[@class='rust item-decl']//code/a[text()='String']"
+assert-property-false: ("pre.item-decl", {"scrollLeft": 0})
diff --git a/tests/rustdoc-gui/unsafe-fn.goml b/tests/rustdoc-gui/unsafe-fn.goml
index d3a672ddd..9d2577178 100644
--- a/tests/rustdoc-gui/unsafe-fn.goml
+++ b/tests/rustdoc-gui/unsafe-fn.goml
@@ -4,8 +4,8 @@ goto: "file://" + |DOC_PATH| + "/test_docs/index.html"
show-text: true
compare-elements-property: (
- "//a[@title='test_docs::safe_fn fn']/..",
- "//a[@title='test_docs::unsafe_fn fn']/..",
+ "//a[@title='fn test_docs::safe_fn']/..",
+ "//a[@title='fn test_docs::unsafe_fn']/..",
["clientHeight"]
)
@@ -19,7 +19,7 @@ define-function: (
local-storage: {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"}
// We reload the page so the local storage settings are being used.
reload:
- assert-css: (".item-left sup", {"color": |color|})
+ assert-css: (".item-name sup", {"color": |color|})
},
)
diff --git a/tests/rustdoc-js-std/parser-errors.js b/tests/rustdoc-js-std/parser-errors.js
index dc42031e0..98c6f27ca 100644
--- a/tests/rustdoc-js-std/parser-errors.js
+++ b/tests/rustdoc-js-std/parser-errors.js
@@ -37,6 +37,9 @@ const QUERY = [
"mod : :",
"a!a",
"a!!",
+ "mod:a!",
+ "a!::a",
+ "a<",
];
const PARSED = [
@@ -65,7 +68,7 @@ const PARSED = [
returned: [],
typeFilter: -1,
userQuery: "a<\"p\">",
- error: "`\"` cannot be used in generics",
+ error: "Unexpected `\"` in generics",
},
{
elems: [],
@@ -371,7 +374,7 @@ const PARSED = [
returned: [],
typeFilter: -1,
userQuery: "a!a",
- error: '`!` can only be at the end of an ident',
+ error: 'Unexpected `!`: it can only be at the end of an ident',
},
{
elems: [],
@@ -382,4 +385,31 @@ const PARSED = [
userQuery: "a!!",
error: 'Cannot have more than one `!` in an ident',
},
+ {
+ elems: [],
+ foundElems: 0,
+ original: "mod:a!",
+ returned: [],
+ typeFilter: -1,
+ userQuery: "mod:a!",
+ error: 'Invalid search type: macro `!` and `mod` both specified',
+ },
+ {
+ elems: [],
+ foundElems: 0,
+ original: "a!::a",
+ returned: [],
+ typeFilter: -1,
+ userQuery: "a!::a",
+ error: 'Cannot have associated items in macros',
+ },
+ {
+ elems: [],
+ foundElems: 0,
+ original: "a<",
+ returned: [],
+ typeFilter: -1,
+ userQuery: "a<",
+ error: "Unclosed `<`",
+ },
];
diff --git a/tests/rustdoc-js-std/parser-filter.js b/tests/rustdoc-js-std/parser-filter.js
index e5a87a415..01f65b478 100644
--- a/tests/rustdoc-js-std/parser-filter.js
+++ b/tests/rustdoc-js-std/parser-filter.js
@@ -1,4 +1,4 @@
-const QUERY = ['fn:foo', 'enum : foo', 'macro<f>:foo'];
+const QUERY = ['fn:foo', 'enum : foo', 'macro<f>:foo', 'macro!', 'macro:mac!', 'a::mac!'];
const PARSED = [
{
@@ -40,4 +40,49 @@ const PARSED = [
userQuery: "macro<f>:foo",
error: "Unexpected `:`",
},
+ {
+ elems: [{
+ name: "macro",
+ fullPath: ["macro"],
+ pathWithoutLast: [],
+ pathLast: "macro",
+ generics: [],
+ }],
+ foundElems: 1,
+ original: "macro!",
+ returned: [],
+ typeFilter: 14,
+ userQuery: "macro!",
+ error: null,
+ },
+ {
+ elems: [{
+ name: "mac",
+ fullPath: ["mac"],
+ pathWithoutLast: [],
+ pathLast: "mac",
+ generics: [],
+ }],
+ foundElems: 1,
+ original: "macro:mac!",
+ returned: [],
+ typeFilter: 14,
+ userQuery: "macro:mac!",
+ error: null,
+ },
+ {
+ elems: [{
+ name: "a::mac",
+ fullPath: ["a", "mac"],
+ pathWithoutLast: ["a"],
+ pathLast: "mac",
+ generics: [],
+ }],
+ foundElems: 1,
+ original: "a::mac!",
+ returned: [],
+ typeFilter: 14,
+ userQuery: "a::mac!",
+ error: null,
+ },
];
diff --git a/tests/rustdoc-js-std/parser-ident.js b/tests/rustdoc-js-std/parser-ident.js
index 4b5ab01ac..6c17d00f1 100644
--- a/tests/rustdoc-js-std/parser-ident.js
+++ b/tests/rustdoc-js-std/parser-ident.js
@@ -3,6 +3,7 @@ const QUERY = [
"!",
"a!",
"a!::b",
+ "!::b",
"a!::b!",
];
@@ -47,47 +48,50 @@ const PARSED = [
},
{
elems: [{
- name: "a!",
- fullPath: ["a!"],
+ name: "a",
+ fullPath: ["a"],
pathWithoutLast: [],
- pathLast: "a!",
+ pathLast: "a",
generics: [],
}],
foundElems: 1,
original: "a!",
returned: [],
- typeFilter: -1,
+ typeFilter: 14,
userQuery: "a!",
error: null,
},
{
- elems: [{
- name: "a!::b",
- fullPath: ["a!", "b"],
- pathWithoutLast: ["a!"],
- pathLast: "b",
- generics: [],
- }],
- foundElems: 1,
+ elems: [],
+ foundElems: 0,
original: "a!::b",
returned: [],
typeFilter: -1,
userQuery: "a!::b",
- error: null,
+ error: "Cannot have associated items in macros",
},
{
elems: [{
- name: "a!::b!",
- fullPath: ["a!", "b!"],
- pathWithoutLast: ["a!"],
- pathLast: "b!",
+ name: "!::b",
+ fullPath: ["!", "b"],
+ pathWithoutLast: ["!"],
+ pathLast: "b",
generics: [],
}],
foundElems: 1,
+ original: "!::b",
+ returned: [],
+ typeFilter: -1,
+ userQuery: "!::b",
+ error: null,
+ },
+ {
+ elems: [],
+ foundElems: 0,
original: "a!::b!",
returned: [],
typeFilter: -1,
userQuery: "a!::b!",
- error: null,
+ error: "Cannot have associated items in macros",
},
];
diff --git a/tests/rustdoc-js-std/reference-shrink.js b/tests/rustdoc-js-std/reference-shrink.js
new file mode 100644
index 000000000..f90be6d1b
--- /dev/null
+++ b/tests/rustdoc-js-std/reference-shrink.js
@@ -0,0 +1,8 @@
+// exact-check
+
+const QUERY = 'reference::shrink';
+
+const EXPECTED = {
+ // avoid including the method that's not going to be in the HTML
+ 'others': [],
+};
diff --git a/tests/rustdoc-js-std/regex.js b/tests/rustdoc-js-std/regex.js
new file mode 100644
index 000000000..a6843c595
--- /dev/null
+++ b/tests/rustdoc-js-std/regex.js
@@ -0,0 +1,10 @@
+// exact-check
+
+// https://github.com/rust-lang/rust/issues/103357
+const QUERY = 'regex';
+
+const EXPECTED = {
+ 'others': [],
+ 'in_args': [],
+ 'returned': [],
+};
diff --git a/tests/rustdoc-js-std/typed-query.js b/tests/rustdoc-js-std/typed-query.js
index fd5c5489d..eeb3e1888 100644
--- a/tests/rustdoc-js-std/typed-query.js
+++ b/tests/rustdoc-js-std/typed-query.js
@@ -9,9 +9,5 @@ const EXPECTED = {
{ 'path': 'std', 'name': 'println' },
{ 'path': 'std', 'name': 'eprint' },
{ 'path': 'std', 'name': 'eprintln' },
- { 'path': 'std::pin', 'name': 'pin' },
- { 'path': 'std::future', 'name': 'join' },
- { 'path': 'std', 'name': 'line' },
- { 'path': 'std', 'name': 'write' },
],
};
diff --git a/tests/rustdoc-js/doc-alias.js b/tests/rustdoc-js/doc-alias.js
index 7bb0cbe38..62c8e7a74 100644
--- a/tests/rustdoc-js/doc-alias.js
+++ b/tests/rustdoc-js/doc-alias.js
@@ -1,5 +1,3 @@
-// exact-check
-
const QUERY = [
'StructItem',
'StructFieldItem',
diff --git a/tests/rustdoc-js/macro-search.js b/tests/rustdoc-js/macro-search.js
new file mode 100644
index 000000000..2b179ce14
--- /dev/null
+++ b/tests/rustdoc-js/macro-search.js
@@ -0,0 +1,10 @@
+// exact-check
+
+const QUERY = 'abracadabra!';
+
+const EXPECTED = {
+ 'others': [
+ { 'path': 'macro_search', 'name': 'abracadabra' },
+ { 'path': 'macro_search', 'name': 'abracadabra_b' },
+ ],
+};
diff --git a/tests/rustdoc-js/macro-search.rs b/tests/rustdoc-js/macro-search.rs
new file mode 100644
index 000000000..dc397490c
--- /dev/null
+++ b/tests/rustdoc-js/macro-search.rs
@@ -0,0 +1,10 @@
+#[macro_export]
+macro_rules! abracadabra {
+ () => {}
+}
+#[macro_export]
+macro_rules! abracadabra_b {
+ () => {}
+}
+pub fn abracadabra() {}
+pub fn abracadabra_c() {}
diff --git a/tests/rustdoc-js/module-substring.js b/tests/rustdoc-js/module-substring.js
index a446c39eb..f17a97f13 100644
--- a/tests/rustdoc-js/module-substring.js
+++ b/tests/rustdoc-js/module-substring.js
@@ -4,6 +4,5 @@ const EXPECTED = {
'others': [
{ 'path': 'module_substring::Sig', 'name': 'pc' },
{ 'path': 'module_substring::Si', 'name': 'pc' },
- { 'path': 'module_substring::Si', 'name': 'pa' },
],
};
diff --git a/tests/rustdoc-json/reexport/same_name_different_types.rs b/tests/rustdoc-json/reexport/same_name_different_types.rs
new file mode 100644
index 000000000..2314a4eb9
--- /dev/null
+++ b/tests/rustdoc-json/reexport/same_name_different_types.rs
@@ -0,0 +1,25 @@
+// Regression test for <https://github.com/rust-lang/rust/issues/107677>.
+
+#![feature(no_core)]
+#![no_core]
+
+pub mod nested {
+ // @set foo_struct = "$.index[*][?(@.docs == 'Foo the struct')].id"
+
+ /// Foo the struct
+ pub struct Foo {}
+
+ // @set foo_fn = "$.index[*][?(@.docs == 'Foo the function')].id"
+
+ #[allow(non_snake_case)]
+ /// Foo the function
+ pub fn Foo() {}
+}
+
+// @ismany "$.index[*][?(@.inner.name == 'Foo' && @.kind == 'import')].inner.id" $foo_fn $foo_struct
+// @ismany "$.index[*][?(@.inner.name == 'Bar' && @.kind == 'import')].inner.id" $foo_fn $foo_struct
+
+// @count "$.index[*][?(@.inner.name == 'Foo' && @.kind == 'import')]" 2
+pub use nested::Foo;
+// @count "$.index[*][?(@.inner.name == 'Bar' && @.kind == 'import')]" 2
+pub use Foo as Bar;
diff --git a/tests/rustdoc-ui/auxiliary/panic-handler.rs b/tests/rustdoc-ui/auxiliary/panic-handler.rs
new file mode 100644
index 000000000..0aaaeee10
--- /dev/null
+++ b/tests/rustdoc-ui/auxiliary/panic-handler.rs
@@ -0,0 +1,9 @@
+// compile-flags: -C panic=abort
+
+#![no_std]
+#![no_main]
+
+#[panic_handler]
+fn panic(_: &core::panic::PanicInfo) -> ! {
+ loop {}
+}
diff --git a/tests/rustdoc-ui/bounded-hr-lifetime.stderr b/tests/rustdoc-ui/bounded-hr-lifetime.stderr
index d8fcd6cb4..580f70c97 100644
--- a/tests/rustdoc-ui/bounded-hr-lifetime.stderr
+++ b/tests/rustdoc-ui/bounded-hr-lifetime.stderr
@@ -4,7 +4,5 @@ error: lifetime bounds cannot be used in this context
LL | for<'a: 'b + 'c> &'a (): std::fmt::Debug,
| ^^ ^^
-error: Compilation failed, aborting rustdoc
-
-error: aborting due to 2 previous errors
+error: aborting due to previous error
diff --git a/tests/rustdoc-ui/check-fail.rs b/tests/rustdoc-ui/check-fail.rs
index c5e1759ee..02632b4ce 100644
--- a/tests/rustdoc-ui/check-fail.rs
+++ b/tests/rustdoc-ui/check-fail.rs
@@ -2,6 +2,7 @@
#![feature(rustdoc_missing_doc_code_examples)]
#![deny(missing_docs)]
+#![deny(rustdoc::missing_doc_code_examples)]
#![deny(rustdoc::all)]
//! ```rust,testharness
diff --git a/tests/rustdoc-ui/check-fail.stderr b/tests/rustdoc-ui/check-fail.stderr
index d8aeccbfc..f05e457af 100644
--- a/tests/rustdoc-ui/check-fail.stderr
+++ b/tests/rustdoc-ui/check-fail.stderr
@@ -1,5 +1,5 @@
error: missing documentation for a function
- --> $DIR/check-fail.rs:12:1
+ --> $DIR/check-fail.rs:13:1
|
LL | pub fn foo() {}
| ^^^^^^^^^^^^
@@ -11,7 +11,7 @@ LL | #![deny(missing_docs)]
| ^^^^^^^^^^^^
error: missing code example in this documentation
- --> $DIR/check-fail.rs:12:1
+ --> $DIR/check-fail.rs:13:1
|
LL | pub fn foo() {}
| ^^^^^^^^^^^^^^^
@@ -19,12 +19,11 @@ LL | pub fn foo() {}
note: the lint level is defined here
--> $DIR/check-fail.rs:5:9
|
-LL | #![deny(rustdoc::all)]
- | ^^^^^^^^^^^^
- = note: `#[deny(rustdoc::missing_doc_code_examples)]` implied by `#[deny(rustdoc::all)]`
+LL | #![deny(rustdoc::missing_doc_code_examples)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: unknown attribute `testharness`. Did you mean `test_harness`?
- --> $DIR/check-fail.rs:7:1
+ --> $DIR/check-fail.rs:8:1
|
LL | / //! ```rust,testharness
LL | |
@@ -33,10 +32,15 @@ LL | | //! ```
| |_______^
|
= help: the code block will either not be tested if not marked as a rust one or the code will be wrapped inside a main function
+note: the lint level is defined here
+ --> $DIR/check-fail.rs:6:9
+ |
+LL | #![deny(rustdoc::all)]
+ | ^^^^^^^^^^^^
= note: `#[deny(rustdoc::invalid_codeblock_attributes)]` implied by `#[deny(rustdoc::all)]`
error: unknown attribute `testharness`. Did you mean `test_harness`?
- --> $DIR/check-fail.rs:16:1
+ --> $DIR/check-fail.rs:17:1
|
LL | / /// hello
LL | |
diff --git a/tests/rustdoc-ui/check.rs b/tests/rustdoc-ui/check.rs
index f70b03361..e389a81bb 100644
--- a/tests/rustdoc-ui/check.rs
+++ b/tests/rustdoc-ui/check.rs
@@ -7,6 +7,7 @@
//~^^ WARN
#![warn(missing_docs)]
+#![warn(rustdoc::missing_doc_code_examples)]
#![warn(rustdoc::all)]
pub fn foo() {}
diff --git a/tests/rustdoc-ui/check.stderr b/tests/rustdoc-ui/check.stderr
index d379f33f2..c5ed5d0c3 100644
--- a/tests/rustdoc-ui/check.stderr
+++ b/tests/rustdoc-ui/check.stderr
@@ -17,7 +17,7 @@ LL | #![warn(missing_docs)]
| ^^^^^^^^^^^^
warning: missing documentation for a function
- --> $DIR/check.rs:12:1
+ --> $DIR/check.rs:13:1
|
LL | pub fn foo() {}
| ^^^^^^^^^^^^
@@ -27,7 +27,7 @@ warning: no documentation found for this crate's top-level module
= help: The following guide may be of use:
https://doc.rust-lang.org/$CHANNEL/rustdoc/how-to-write-documentation.html
note: the lint level is defined here
- --> $DIR/check.rs:10:9
+ --> $DIR/check.rs:11:9
|
LL | #![warn(rustdoc::all)]
| ^^^^^^^^^^^^
@@ -45,10 +45,14 @@ LL | |
LL | | pub fn foo() {}
| |_______________^
|
- = note: `#[warn(rustdoc::missing_doc_code_examples)]` implied by `#[warn(rustdoc::all)]`
+note: the lint level is defined here
+ --> $DIR/check.rs:10:9
+ |
+LL | #![warn(rustdoc::missing_doc_code_examples)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
warning: missing code example in this documentation
- --> $DIR/check.rs:12:1
+ --> $DIR/check.rs:13:1
|
LL | pub fn foo() {}
| ^^^^^^^^^^^^^^^
diff --git a/tests/rustdoc-ui/feature-gate-doc_cfg_hide.stderr b/tests/rustdoc-ui/feature-gate-doc_cfg_hide.stderr
index ba42c7bbb..0864159c8 100644
--- a/tests/rustdoc-ui/feature-gate-doc_cfg_hide.stderr
+++ b/tests/rustdoc-ui/feature-gate-doc_cfg_hide.stderr
@@ -7,8 +7,6 @@ LL | #![doc(cfg_hide(test))]
= note: see issue #43781 <https://github.com/rust-lang/rust/issues/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
+error: aborting due to previous error
For more information about this error, try `rustc --explain E0658`.
diff --git a/tests/rustdoc-ui/feature-gate-rustdoc_missing_doc_code_examples.rs b/tests/rustdoc-ui/feature-gate-rustdoc_missing_doc_code_examples.rs
index daba69868..c34ea0567 100644
--- a/tests/rustdoc-ui/feature-gate-rustdoc_missing_doc_code_examples.rs
+++ b/tests/rustdoc-ui/feature-gate-rustdoc_missing_doc_code_examples.rs
@@ -1,10 +1,12 @@
#![deny(unknown_lints)]
//~^ NOTE defined here
-
#![allow(rustdoc::missing_doc_code_examples)]
//~^ ERROR unknown lint
//~| ERROR unknown lint
+//~| ERROR unknown lint
+//~| NOTE lint is unstable
//~| NOTE lint is unstable
//~| NOTE lint is unstable
//~| NOTE see issue
//~| NOTE see issue
+//~| NOTE see issue
diff --git a/tests/rustdoc-ui/feature-gate-rustdoc_missing_doc_code_examples.stderr b/tests/rustdoc-ui/feature-gate-rustdoc_missing_doc_code_examples.stderr
index cbe9a3d14..326dcfe3b 100644
--- a/tests/rustdoc-ui/feature-gate-rustdoc_missing_doc_code_examples.stderr
+++ b/tests/rustdoc-ui/feature-gate-rustdoc_missing_doc_code_examples.stderr
@@ -1,5 +1,5 @@
error: unknown lint: `rustdoc::missing_doc_code_examples`
- --> $DIR/feature-gate-rustdoc_missing_doc_code_examples.rs:4:1
+ --> $DIR/feature-gate-rustdoc_missing_doc_code_examples.rs:3:1
|
LL | #![allow(rustdoc::missing_doc_code_examples)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -14,7 +14,7 @@ LL | #![deny(unknown_lints)]
| ^^^^^^^^^^^^^
error: unknown lint: `rustdoc::missing_doc_code_examples`
- --> $DIR/feature-gate-rustdoc_missing_doc_code_examples.rs:4:1
+ --> $DIR/feature-gate-rustdoc_missing_doc_code_examples.rs:3:1
|
LL | #![allow(rustdoc::missing_doc_code_examples)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -23,7 +23,15 @@ LL | #![allow(rustdoc::missing_doc_code_examples)]
= note: see issue #101730 <https://github.com/rust-lang/rust/issues/101730> for more information
= help: add `#![feature(rustdoc_missing_doc_code_examples)]` to the crate attributes to enable
-error: Compilation failed, aborting rustdoc
+error: unknown lint: `rustdoc::missing_doc_code_examples`
+ --> $DIR/feature-gate-rustdoc_missing_doc_code_examples.rs:3:1
+ |
+LL | #![allow(rustdoc::missing_doc_code_examples)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: the `rustdoc::missing_doc_code_examples` lint is unstable
+ = note: see issue #101730 <https://github.com/rust-lang/rust/issues/101730> for more information
+ = help: add `#![feature(rustdoc_missing_doc_code_examples)]` to the crate attributes to enable
error: aborting due to 3 previous errors
diff --git a/tests/rustdoc-ui/impl-fn-nesting.stderr b/tests/rustdoc-ui/impl-fn-nesting.stderr
index 608749af8..75e6b4ed2 100644
--- a/tests/rustdoc-ui/impl-fn-nesting.stderr
+++ b/tests/rustdoc-ui/impl-fn-nesting.stderr
@@ -58,9 +58,7 @@ error[E0412]: cannot find type `UnknownType` in this scope
LL | pub fn doubly_nested(c: UnknownType) {
| ^^^^^^^^^^^ not found in this scope
-error: Compilation failed, aborting rustdoc
-
-error: aborting due to 11 previous errors
+error: aborting due to 10 previous errors
Some errors have detailed explanations: E0405, E0412.
For more information about an error, try `rustc --explain E0405`.
diff --git a/tests/rustdoc-ui/infinite-recursive-type-impl-trait-return.rs b/tests/rustdoc-ui/infinite-recursive-type-impl-trait-return.rs
index 4b1e04234..939da186f 100644
--- a/tests/rustdoc-ui/infinite-recursive-type-impl-trait-return.rs
+++ b/tests/rustdoc-ui/infinite-recursive-type-impl-trait-return.rs
@@ -1,12 +1,10 @@
-// check-pass
// normalize-stderr-test: "`.*`" -> "`DEF_ID`"
// normalize-stdout-test: "`.*`" -> "`DEF_ID`"
// edition:2018
pub async fn f() -> impl std::fmt::Debug {
- // rustdoc doesn't care that this is infinitely sized
#[derive(Debug)]
- enum E {
+ enum E { //~ ERROR
This(E),
Unit,
}
diff --git a/tests/rustdoc-ui/infinite-recursive-type-impl-trait-return.stderr b/tests/rustdoc-ui/infinite-recursive-type-impl-trait-return.stderr
new file mode 100644
index 000000000..aff7402bc
--- /dev/null
+++ b/tests/rustdoc-ui/infinite-recursive-type-impl-trait-return.stderr
@@ -0,0 +1,16 @@
+error[E0072]: recursive type `DEF_ID` has infinite size
+ --> $DIR/infinite-recursive-type-impl-trait-return.rs:7:5
+ |
+LL | enum E {
+ | ^^^^^^
+LL | This(E),
+ | - recursive without indirection
+ |
+help: insert some indirection (e.g., a `DEF_ID`) to break the cycle
+ |
+LL | This(Box<E>),
+ | ++++ +
+
+error: aborting due to previous error
+
+For more information about this error, try `DEF_ID`.
diff --git a/tests/rustdoc-ui/infinite-recursive-type-impl-trait.rs b/tests/rustdoc-ui/infinite-recursive-type-impl-trait.rs
index ac79582fb..ac5172574 100644
--- a/tests/rustdoc-ui/infinite-recursive-type-impl-trait.rs
+++ b/tests/rustdoc-ui/infinite-recursive-type-impl-trait.rs
@@ -1,8 +1,5 @@
-// check-pass
-
fn f() -> impl Sized {
- // rustdoc doesn't care that this is infinitely sized
- enum E {
+ enum E { //~ ERROR
V(E),
}
unimplemented!()
diff --git a/tests/rustdoc-ui/infinite-recursive-type-impl-trait.stderr b/tests/rustdoc-ui/infinite-recursive-type-impl-trait.stderr
new file mode 100644
index 000000000..a61577bd1
--- /dev/null
+++ b/tests/rustdoc-ui/infinite-recursive-type-impl-trait.stderr
@@ -0,0 +1,16 @@
+error[E0072]: recursive type `f::E` has infinite size
+ --> $DIR/infinite-recursive-type-impl-trait.rs:2:5
+ |
+LL | enum E {
+ | ^^^^^^
+LL | V(E),
+ | - recursive without indirection
+ |
+help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to break the cycle
+ |
+LL | V(Box<E>),
+ | ++++ +
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0072`.
diff --git a/tests/rustdoc-ui/intra-doc/errors.rs b/tests/rustdoc-ui/intra-doc/errors.rs
index b29f7c29b..95dd2b98e 100644
--- a/tests/rustdoc-ui/intra-doc/errors.rs
+++ b/tests/rustdoc-ui/intra-doc/errors.rs
@@ -103,3 +103,19 @@ pub trait T {
macro_rules! m {
() => {};
}
+
+///[`TestEnum::Variant1::field_name`]
+//~^ ERROR unresolved link
+//~| NOTE variant `Variant1` has no such field
+pub enum TestEnum {
+ Variant1 {},
+ Variant2 { field_name: u64 },
+}
+
+///[`TestEnumNoFields::Variant1::field_name`]
+//~^ ERROR unresolved link
+//~| NOTE `Variant1` is a variant, not a module or type, and cannot have associated items
+pub enum TestEnumNoFields {
+ Variant1 (),
+ Variant2 {},
+}
diff --git a/tests/rustdoc-ui/intra-doc/errors.stderr b/tests/rustdoc-ui/intra-doc/errors.stderr
index 9a1896fb0..1b2416d7d 100644
--- a/tests/rustdoc-ui/intra-doc/errors.stderr
+++ b/tests/rustdoc-ui/intra-doc/errors.stderr
@@ -142,6 +142,18 @@ error: unresolved link to `T::h`
LL | /// [T::h!]
| ^^^^^ the trait `T` has no macro named `h`
+error: unresolved link to `TestEnum::Variant1::field_name`
+ --> $DIR/errors.rs:107:6
+ |
+LL | ///[`TestEnum::Variant1::field_name`]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ variant `Variant1` has no such field
+
+error: unresolved link to `TestEnumNoFields::Variant1::field_name`
+ --> $DIR/errors.rs:115:6
+ |
+LL | ///[`TestEnumNoFields::Variant1::field_name`]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `Variant1` is a variant, not a module or type, and cannot have associated items
+
error: unresolved link to `m`
--> $DIR/errors.rs:98:6
|
@@ -153,5 +165,5 @@ help: to link to the macro, add an exclamation mark
LL | /// [m!()]
| +
-error: aborting due to 20 previous errors
+error: aborting due to 22 previous errors
diff --git a/tests/rustdoc-ui/intra-doc/import-inline-merge.rs b/tests/rustdoc-ui/intra-doc/import-inline-merge.rs
new file mode 100644
index 000000000..31fef032b
--- /dev/null
+++ b/tests/rustdoc-ui/intra-doc/import-inline-merge.rs
@@ -0,0 +1,16 @@
+// Import for `A` is inlined and doc comments on the import and `A` itself are merged.
+// After the merge they still have correct parent scopes to resolve both `[A]` and `[B]`.
+
+// check-pass
+
+#![allow(rustdoc::private_intra_doc_links)]
+
+mod m {
+ /// [B]
+ pub struct A {}
+
+ pub struct B {}
+}
+
+/// [A]
+pub use m::A;
diff --git a/tests/rustdoc-ui/intra-doc/proc-macro-doc.rs b/tests/rustdoc-ui/intra-doc/proc-macro-doc.rs
new file mode 100644
index 000000000..8335fc902
--- /dev/null
+++ b/tests/rustdoc-ui/intra-doc/proc-macro-doc.rs
@@ -0,0 +1,27 @@
+// check-pass
+// force-host
+// no-prefer-dynamic
+// compile-flags: --crate-type proc-macro
+
+#![deny(rustdoc::broken_intra_doc_links)]
+
+extern crate proc_macro;
+use proc_macro::*;
+
+/// [`Unpin`]
+#[proc_macro_derive(F)]
+pub fn derive_(t: proc_macro::TokenStream) -> proc_macro::TokenStream {
+ t
+}
+
+/// [`Vec`]
+#[proc_macro_attribute]
+pub fn attr(t: proc_macro::TokenStream, _: proc_macro::TokenStream) -> proc_macro::TokenStream {
+ t
+}
+
+/// [`std::fs::File`]
+#[proc_macro]
+pub fn func(t: proc_macro::TokenStream) -> proc_macro::TokenStream {
+ t
+}
diff --git a/tests/rustdoc-ui/intra-doc/unknown-disambiguator.stderr b/tests/rustdoc-ui/intra-doc/unknown-disambiguator.stderr
index 19e541736..741a7f51a 100644
--- a/tests/rustdoc-ui/intra-doc/unknown-disambiguator.stderr
+++ b/tests/rustdoc-ui/intra-doc/unknown-disambiguator.stderr
@@ -20,22 +20,6 @@ LL | //! Linking to [foo@banana] and [`bar@banana!()`].
|
= note: see https://doc.rust-lang.org/$CHANNEL/rustdoc/write-documentation/linking-to-items-by-name.html#namespaces-and-disambiguators for more info about disambiguators
-error: unknown disambiguator `foo`
- --> $DIR/unknown-disambiguator.rs:10:34
- |
-LL | //! And with weird backticks: [``foo@hello``] [foo`@`hello].
- | ^^^
- |
- = note: see https://doc.rust-lang.org/$CHANNEL/rustdoc/write-documentation/linking-to-items-by-name.html#namespaces-and-disambiguators for more info about disambiguators
-
-error: unknown disambiguator `foo`
- --> $DIR/unknown-disambiguator.rs:10:48
- |
-LL | //! And with weird backticks: [``foo@hello``] [foo`@`hello].
- | ^^^
- |
- = note: see https://doc.rust-lang.org/$CHANNEL/rustdoc/write-documentation/linking-to-items-by-name.html#namespaces-and-disambiguators for more info about disambiguators
-
error: unknown disambiguator ``
--> $DIR/unknown-disambiguator.rs:7:31
|
@@ -52,5 +36,21 @@ LL | //! And to [no disambiguator](@nectarine) and [another](@apricot!()).
|
= note: see https://doc.rust-lang.org/$CHANNEL/rustdoc/write-documentation/linking-to-items-by-name.html#namespaces-and-disambiguators for more info about disambiguators
+error: unknown disambiguator `foo`
+ --> $DIR/unknown-disambiguator.rs:10:34
+ |
+LL | //! And with weird backticks: [``foo@hello``] [foo`@`hello].
+ | ^^^
+ |
+ = note: see https://doc.rust-lang.org/$CHANNEL/rustdoc/write-documentation/linking-to-items-by-name.html#namespaces-and-disambiguators for more info about disambiguators
+
+error: unknown disambiguator `foo`
+ --> $DIR/unknown-disambiguator.rs:10:48
+ |
+LL | //! And with weird backticks: [``foo@hello``] [foo`@`hello].
+ | ^^^
+ |
+ = note: see https://doc.rust-lang.org/$CHANNEL/rustdoc/write-documentation/linking-to-items-by-name.html#namespaces-and-disambiguators for more info about disambiguators
+
error: aborting due to 6 previous errors
diff --git a/tests/rustdoc-ui/intra-doc/unresolved-import-recovery.stderr b/tests/rustdoc-ui/intra-doc/unresolved-import-recovery.stderr
index b54f82006..14f560618 100644
--- a/tests/rustdoc-ui/intra-doc/unresolved-import-recovery.stderr
+++ b/tests/rustdoc-ui/intra-doc/unresolved-import-recovery.stderr
@@ -6,8 +6,6 @@ LL | use unresolved_crate::module::Name;
|
= help: consider adding `extern crate unresolved_crate` to use the `unresolved_crate` crate
-error: Compilation failed, aborting rustdoc
-
-error: aborting due to 2 previous errors
+error: aborting due to previous error
For more information about this error, try `rustc --explain E0433`.
diff --git a/tests/rustdoc-ui/issue-105742.rs b/tests/rustdoc-ui/issue-105742.rs
index cb1de7433..9f36e5315 100644
--- a/tests/rustdoc-ui/issue-105742.rs
+++ b/tests/rustdoc-ui/issue-105742.rs
@@ -3,38 +3,17 @@
use std::ops::Index;
pub fn next<'a, T>(s: &'a mut dyn SVec<Item = T, Output = T>) {
-//~^ ERROR
-//~^^ ERROR
-//~^^^ ERROR
let _ = s;
}
pub trait SVec: Index<
<Self as SVec>::Item,
-//~^ ERROR
-//~^^ ERROR
-//~^^^ ERROR
-//~^^^^ ERROR
Output = <Index<<Self as SVec>::Item,
-//~^ ERROR
-//~^^ ERROR
-//~^^^ ERROR
-//~^^^^ ERROR
Output = <Self as SVec>::Item> as SVec>::Item,
-//~^ ERROR
-//~^^ ERROR
-//~^^^ ERROR
-//~^^^^ ERROR
-//~^^^^^ ERROR
-//~^^^^^^ ERROR
-//~^^^^^^^ ERROR
-//~^^^^^^^^ ERROR
> {
type Item<'a, T>;
fn len(&self) -> <Self as SVec>::Item;
//~^ ERROR
//~^^ ERROR
- //~^^^ ERROR
- //~^^^^ ERROR
}
diff --git a/tests/rustdoc-ui/issue-105742.stderr b/tests/rustdoc-ui/issue-105742.stderr
index ffb602cf8..4d2ee9726 100644
--- a/tests/rustdoc-ui/issue-105742.stderr
+++ b/tests/rustdoc-ui/issue-105742.stderr
@@ -1,360 +1,11 @@
error[E0107]: missing generics for associated type `SVec::Item`
- --> $DIR/issue-105742.rs:13:21
- |
-LL | <Self as SVec>::Item,
- | ^^^^ expected 1 lifetime argument
- |
-note: associated type defined here, with 1 lifetime parameter: `'a`
- --> $DIR/issue-105742.rs:33:10
- |
-LL | type Item<'a, T>;
- | ^^^^ --
-help: add missing lifetime argument
- |
-LL | <Self as SVec>::Item<'a>,
- | ++++
-
-error[E0107]: missing generics for associated type `SVec::Item`
- --> $DIR/issue-105742.rs:13:21
- |
-LL | <Self as SVec>::Item,
- | ^^^^ expected 1 generic argument
- |
-note: associated type defined here, with 1 generic parameter: `T`
- --> $DIR/issue-105742.rs:33:10
- |
-LL | type Item<'a, T>;
- | ^^^^ -
-help: add missing generic argument
- |
-LL | <Self as SVec>::Item<T>,
- | +++
-
-error[E0107]: missing generics for associated type `SVec::Item`
- --> $DIR/issue-105742.rs:18:37
- |
-LL | Output = <Index<<Self as SVec>::Item,
- | ^^^^ expected 1 lifetime argument
- |
-note: associated type defined here, with 1 lifetime parameter: `'a`
- --> $DIR/issue-105742.rs:33:10
- |
-LL | type Item<'a, T>;
- | ^^^^ --
-help: add missing lifetime argument
- |
-LL | Output = <Index<<Self as SVec>::Item<'a>,
- | ++++
-
-error[E0107]: missing generics for associated type `SVec::Item`
- --> $DIR/issue-105742.rs:18:37
- |
-LL | Output = <Index<<Self as SVec>::Item,
- | ^^^^ expected 1 generic argument
- |
-note: associated type defined here, with 1 generic parameter: `T`
- --> $DIR/issue-105742.rs:33:10
- |
-LL | type Item<'a, T>;
- | ^^^^ -
-help: add missing generic argument
- |
-LL | Output = <Index<<Self as SVec>::Item<T>,
- | +++
-
-error[E0107]: missing generics for associated type `SVec::Item`
- --> $DIR/issue-105742.rs:23:30
- |
-LL | Output = <Self as SVec>::Item> as SVec>::Item,
- | ^^^^ expected 1 lifetime argument
- |
-note: associated type defined here, with 1 lifetime parameter: `'a`
- --> $DIR/issue-105742.rs:33:10
- |
-LL | type Item<'a, T>;
- | ^^^^ --
-help: add missing lifetime argument
- |
-LL | Output = <Self as SVec>::Item<'a>> as SVec>::Item,
- | ++++
-
-error[E0107]: missing generics for associated type `SVec::Item`
- --> $DIR/issue-105742.rs:23:30
- |
-LL | Output = <Self as SVec>::Item> as SVec>::Item,
- | ^^^^ expected 1 generic argument
- |
-note: associated type defined here, with 1 generic parameter: `T`
- --> $DIR/issue-105742.rs:33:10
- |
-LL | type Item<'a, T>;
- | ^^^^ -
-help: add missing generic argument
- |
-LL | Output = <Self as SVec>::Item<T>> as SVec>::Item,
- | +++
-
-error[E0107]: missing generics for associated type `SVec::Item`
- --> $DIR/issue-105742.rs:23:46
- |
-LL | Output = <Self as SVec>::Item> as SVec>::Item,
- | ^^^^ expected 1 lifetime argument
- |
-note: associated type defined here, with 1 lifetime parameter: `'a`
- --> $DIR/issue-105742.rs:33:10
- |
-LL | type Item<'a, T>;
- | ^^^^ --
-help: add missing lifetime argument
- |
-LL | Output = <Self as SVec>::Item> as SVec>::Item<'a>,
- | ++++
-
-error[E0107]: missing generics for associated type `SVec::Item`
- --> $DIR/issue-105742.rs:23:46
- |
-LL | Output = <Self as SVec>::Item> as SVec>::Item,
- | ^^^^ expected 1 generic argument
- |
-note: associated type defined here, with 1 generic parameter: `T`
- --> $DIR/issue-105742.rs:33:10
- |
-LL | type Item<'a, T>;
- | ^^^^ -
-help: add missing generic argument
- |
-LL | Output = <Self as SVec>::Item> as SVec>::Item<T>,
- | +++
-
-error[E0107]: missing generics for associated type `SVec::Item`
- --> $DIR/issue-105742.rs:5:40
- |
-LL | pub fn next<'a, T>(s: &'a mut dyn SVec<Item = T, Output = T>) {
- | ^^^^ expected 1 lifetime argument
- |
-note: associated type defined here, with 1 lifetime parameter: `'a`
- --> $DIR/issue-105742.rs:33:10
- |
-LL | type Item<'a, T>;
- | ^^^^ --
-help: add missing lifetime argument
- |
-LL | pub fn next<'a, T>(s: &'a mut dyn SVec<Item<'_> = T, Output = T>) {
- | ++++
-
-error[E0107]: missing generics for associated type `SVec::Item`
- --> $DIR/issue-105742.rs:5:40
- |
-LL | pub fn next<'a, T>(s: &'a mut dyn SVec<Item = T, Output = T>) {
- | ^^^^ expected 1 generic argument
- |
-note: associated type defined here, with 1 generic parameter: `T`
- --> $DIR/issue-105742.rs:33:10
- |
-LL | type Item<'a, T>;
- | ^^^^ -
-help: add missing generic argument
- |
-LL | pub fn next<'a, T>(s: &'a mut dyn SVec<Item<T> = T, Output = T>) {
- | +++
-
-error[E0107]: missing generics for associated type `SVec::Item`
- --> $DIR/issue-105742.rs:13:21
- |
-LL | <Self as SVec>::Item,
- | ^^^^ expected 1 lifetime argument
- |
-note: associated type defined here, with 1 lifetime parameter: `'a`
- --> $DIR/issue-105742.rs:33:10
- |
-LL | type Item<'a, T>;
- | ^^^^ --
-help: add missing lifetime argument
- |
-LL | <Self as SVec>::Item<'a>,
- | ++++
-
-error[E0107]: missing generics for associated type `SVec::Item`
- --> $DIR/issue-105742.rs:13:21
- |
-LL | <Self as SVec>::Item,
- | ^^^^ expected 1 generic argument
- |
-note: associated type defined here, with 1 generic parameter: `T`
- --> $DIR/issue-105742.rs:33:10
- |
-LL | type Item<'a, T>;
- | ^^^^ -
-help: add missing generic argument
- |
-LL | <Self as SVec>::Item<T>,
- | +++
-
-error[E0107]: missing generics for associated type `SVec::Item`
- --> $DIR/issue-105742.rs:18:37
- |
-LL | Output = <Index<<Self as SVec>::Item,
- | ^^^^ expected 1 lifetime argument
- |
-note: associated type defined here, with 1 lifetime parameter: `'a`
- --> $DIR/issue-105742.rs:33:10
- |
-LL | type Item<'a, T>;
- | ^^^^ --
-help: add missing lifetime argument
- |
-LL | Output = <Index<<Self as SVec>::Item<'a>,
- | ++++
-
-error[E0107]: missing generics for associated type `SVec::Item`
- --> $DIR/issue-105742.rs:18:37
- |
-LL | Output = <Index<<Self as SVec>::Item,
- | ^^^^ expected 1 generic argument
- |
-note: associated type defined here, with 1 generic parameter: `T`
- --> $DIR/issue-105742.rs:33:10
- |
-LL | type Item<'a, T>;
- | ^^^^ -
-help: add missing generic argument
- |
-LL | Output = <Index<<Self as SVec>::Item<T>,
- | +++
-
-error[E0107]: missing generics for associated type `SVec::Item`
- --> $DIR/issue-105742.rs:23:30
- |
-LL | Output = <Self as SVec>::Item> as SVec>::Item,
- | ^^^^ expected 1 lifetime argument
- |
-note: associated type defined here, with 1 lifetime parameter: `'a`
- --> $DIR/issue-105742.rs:33:10
- |
-LL | type Item<'a, T>;
- | ^^^^ --
-help: add missing lifetime argument
- |
-LL | Output = <Self as SVec>::Item<'a>> as SVec>::Item,
- | ++++
-
-error[E0107]: missing generics for associated type `SVec::Item`
- --> $DIR/issue-105742.rs:23:30
- |
-LL | Output = <Self as SVec>::Item> as SVec>::Item,
- | ^^^^ expected 1 generic argument
- |
-note: associated type defined here, with 1 generic parameter: `T`
- --> $DIR/issue-105742.rs:33:10
- |
-LL | type Item<'a, T>;
- | ^^^^ -
-help: add missing generic argument
- |
-LL | Output = <Self as SVec>::Item<T>> as SVec>::Item,
- | +++
-
-error[E0107]: missing generics for associated type `SVec::Item`
- --> $DIR/issue-105742.rs:23:46
- |
-LL | Output = <Self as SVec>::Item> as SVec>::Item,
- | ^^^^ expected 1 lifetime argument
- |
-note: associated type defined here, with 1 lifetime parameter: `'a`
- --> $DIR/issue-105742.rs:33:10
- |
-LL | type Item<'a, T>;
- | ^^^^ --
-help: add missing lifetime argument
- |
-LL | Output = <Self as SVec>::Item> as SVec>::Item<'a>,
- | ++++
-
-error[E0107]: missing generics for associated type `SVec::Item`
- --> $DIR/issue-105742.rs:23:46
- |
-LL | Output = <Self as SVec>::Item> as SVec>::Item,
- | ^^^^ expected 1 generic argument
- |
-note: associated type defined here, with 1 generic parameter: `T`
- --> $DIR/issue-105742.rs:33:10
- |
-LL | type Item<'a, T>;
- | ^^^^ -
-help: add missing generic argument
- |
-LL | Output = <Self as SVec>::Item> as SVec>::Item<T>,
- | +++
-
-error[E0038]: the trait `SVec` cannot be made into an object
- --> $DIR/issue-105742.rs:5:31
- |
-LL | pub fn next<'a, T>(s: &'a mut dyn SVec<Item = T, Output = T>) {
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `SVec` cannot be made into an object
- |
-note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
- --> $DIR/issue-105742.rs:12:17
- |
-LL | pub trait SVec: Index<
- | ____________----__^
- | | |
- | | this trait cannot be made into an object...
-LL | | <Self as SVec>::Item,
-LL | |
-LL | |
-... |
-LL | |/ Output = <Index<<Self as SVec>::Item,
-LL | ||
-LL | ||
-LL | ||
-LL | ||
-LL | || Output = <Self as SVec>::Item> as SVec>::Item,
- | ||_________________________________________________^ ...because it uses `Self` as a type parameter
-... |
-LL | |
-LL | | > {
- | |__^ ...because it uses `Self` as a type parameter
-
-error[E0107]: missing generics for associated type `SVec::Item`
- --> $DIR/issue-105742.rs:35:38
- |
-LL | fn len(&self) -> <Self as SVec>::Item;
- | ^^^^ expected 1 lifetime argument
- |
-note: associated type defined here, with 1 lifetime parameter: `'a`
- --> $DIR/issue-105742.rs:33:10
- |
-LL | type Item<'a, T>;
- | ^^^^ --
-help: add missing lifetime argument
- |
-LL | fn len(&self) -> <Self as SVec>::Item<'_>;
- | ++++
-
-error[E0107]: missing generics for associated type `SVec::Item`
- --> $DIR/issue-105742.rs:35:38
- |
-LL | fn len(&self) -> <Self as SVec>::Item;
- | ^^^^ expected 1 generic argument
- |
-note: associated type defined here, with 1 generic parameter: `T`
- --> $DIR/issue-105742.rs:33:10
- |
-LL | type Item<'a, T>;
- | ^^^^ -
-help: add missing generic argument
- |
-LL | fn len(&self) -> <Self as SVec>::Item<T>;
- | +++
-
-error[E0107]: missing generics for associated type `SVec::Item`
- --> $DIR/issue-105742.rs:35:38
+ --> $DIR/issue-105742.rs:16:38
|
LL | fn len(&self) -> <Self as SVec>::Item;
| ^^^^ expected 1 lifetime argument
|
note: associated type defined here, with 1 lifetime parameter: `'a`
- --> $DIR/issue-105742.rs:33:10
+ --> $DIR/issue-105742.rs:14:10
|
LL | type Item<'a, T>;
| ^^^^ --
@@ -364,13 +15,13 @@ LL | fn len(&self) -> <Self as SVec>::Item<'_>;
| ++++
error[E0107]: missing generics for associated type `SVec::Item`
- --> $DIR/issue-105742.rs:35:38
+ --> $DIR/issue-105742.rs:16:38
|
LL | fn len(&self) -> <Self as SVec>::Item;
| ^^^^ expected 1 generic argument
|
note: associated type defined here, with 1 generic parameter: `T`
- --> $DIR/issue-105742.rs:33:10
+ --> $DIR/issue-105742.rs:14:10
|
LL | type Item<'a, T>;
| ^^^^ -
@@ -379,7 +30,6 @@ help: add missing generic argument
LL | fn len(&self) -> <Self as SVec>::Item<T>;
| +++
-error: aborting due to 23 previous errors
+error: aborting due to 2 previous errors
-Some errors have detailed explanations: E0038, E0107.
-For more information about an error, try `rustc --explain E0038`.
+For more information about this error, try `rustc --explain E0107`.
diff --git a/tests/rustdoc-ui/issue-107918.rs b/tests/rustdoc-ui/issue-107918.rs
new file mode 100644
index 000000000..13788df0f
--- /dev/null
+++ b/tests/rustdoc-ui/issue-107918.rs
@@ -0,0 +1,12 @@
+// aux-build:panic-handler.rs
+// compile-flags: --document-private-items
+// build-pass
+// ignore-windows
+
+#![no_std]
+#![no_main]
+
+#[panic_handler]
+fn panic(_: &core::panic::PanicInfo) -> ! {
+ loop {}
+}
diff --git a/tests/rustdoc-ui/issue-61732.stderr b/tests/rustdoc-ui/issue-61732.stderr
index 38fadaa44..d16ec6a85 100644
--- a/tests/rustdoc-ui/issue-61732.stderr
+++ b/tests/rustdoc-ui/issue-61732.stderr
@@ -6,8 +6,6 @@ LL | pub(in crate::r#mod) fn main() {}
|
= help: consider adding `extern crate r#mod` to use the `r#mod` crate
-error: Compilation failed, aborting rustdoc
-
-error: aborting due to 2 previous errors
+error: aborting due to previous error
For more information about this error, try `rustc --explain E0433`.
diff --git a/tests/rustdoc-ui/lint-group.rs b/tests/rustdoc-ui/lint-group.rs
index 09aca6d2b..ad88157f6 100644
--- a/tests/rustdoc-ui/lint-group.rs
+++ b/tests/rustdoc-ui/lint-group.rs
@@ -6,6 +6,7 @@
//! println!("sup");
//! ```
+#![deny(rustdoc::missing_doc_code_examples)]
#![deny(rustdoc::all)]
/// what up, let's make an [error]
diff --git a/tests/rustdoc-ui/lint-group.stderr b/tests/rustdoc-ui/lint-group.stderr
index 4f2c96588..7ff09fcc4 100644
--- a/tests/rustdoc-ui/lint-group.stderr
+++ b/tests/rustdoc-ui/lint-group.stderr
@@ -1,5 +1,5 @@
error: missing code example in this documentation
- --> $DIR/lint-group.rs:18:1
+ --> $DIR/lint-group.rs:19:1
|
LL | /// wait, this doesn't have a doctest?
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -7,12 +7,11 @@ LL | /// wait, this doesn't have a doctest?
note: the lint level is defined here
--> $DIR/lint-group.rs:9:9
|
-LL | #![deny(rustdoc::all)]
- | ^^^^^^^^^^^^
- = note: `#[deny(rustdoc::missing_doc_code_examples)]` implied by `#[deny(rustdoc::all)]`
+LL | #![deny(rustdoc::missing_doc_code_examples)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: documentation test in private item
- --> $DIR/lint-group.rs:21:1
+ --> $DIR/lint-group.rs:22:1
|
LL | / /// wait, this *does* have a doctest?
LL | | ///
@@ -21,16 +20,21 @@ LL | | /// println!("sup");
LL | | /// ```
| |_______^
|
+note: the lint level is defined here
+ --> $DIR/lint-group.rs:10:9
+ |
+LL | #![deny(rustdoc::all)]
+ | ^^^^^^^^^^^^
= note: `#[deny(rustdoc::private_doc_tests)]` implied by `#[deny(rustdoc::all)]`
error: missing code example in this documentation
- --> $DIR/lint-group.rs:28:1
+ --> $DIR/lint-group.rs:29:1
|
LL | /// <unknown>
| ^^^^^^^^^^^^^
error: unresolved link to `error`
- --> $DIR/lint-group.rs:11:29
+ --> $DIR/lint-group.rs:12:29
|
LL | /// what up, let's make an [error]
| ^^^^^ no item named `error` in scope
@@ -39,7 +43,7 @@ LL | /// what up, let's make an [error]
= note: `#[deny(rustdoc::broken_intra_doc_links)]` implied by `#[deny(rustdoc::all)]`
error: unclosed HTML tag `unknown`
- --> $DIR/lint-group.rs:28:5
+ --> $DIR/lint-group.rs:29:5
|
LL | /// <unknown>
| ^^^^^^^^^
diff --git a/tests/rustdoc-ui/proc_macro_bug.rs b/tests/rustdoc-ui/proc_macro_bug.rs
new file mode 100644
index 000000000..e384e4863
--- /dev/null
+++ b/tests/rustdoc-ui/proc_macro_bug.rs
@@ -0,0 +1,12 @@
+// regression test for failing to pass `--crate-type proc-macro` to rustdoc
+// when documenting a proc macro crate https://github.com/rust-lang/rust/pull/107291
+
+extern crate proc_macro;
+
+use proc_macro::TokenStream;
+
+#[proc_macro_derive(DeriveA)]
+//~^ ERROR the `#[proc_macro_derive]` attribute is only usable with crates of the `proc-macro` crate type
+pub fn a_derive(input: TokenStream) -> TokenStream {
+ input
+}
diff --git a/tests/rustdoc-ui/proc_macro_bug.stderr b/tests/rustdoc-ui/proc_macro_bug.stderr
new file mode 100644
index 000000000..5b048097c
--- /dev/null
+++ b/tests/rustdoc-ui/proc_macro_bug.stderr
@@ -0,0 +1,8 @@
+error: the `#[proc_macro_derive]` attribute is only usable with crates of the `proc-macro` crate type
+ --> $DIR/proc_macro_bug.rs:8:1
+ |
+LL | #[proc_macro_derive(DeriveA)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/tests/rustdoc-ui/rustdoc-all-only-stable-lints.rs b/tests/rustdoc-ui/rustdoc-all-only-stable-lints.rs
new file mode 100644
index 000000000..e106d06af
--- /dev/null
+++ b/tests/rustdoc-ui/rustdoc-all-only-stable-lints.rs
@@ -0,0 +1,6 @@
+// check-pass
+
+// Ensure `rustdoc::all` only affects stable lints. See #106289.
+
+#![deny(unknown_lints)]
+#![allow(rustdoc::all)]
diff --git a/tests/rustdoc-ui/track-diagnostics.stderr b/tests/rustdoc-ui/track-diagnostics.stderr
index ec3031862..39418d359 100644
--- a/tests/rustdoc-ui/track-diagnostics.stderr
+++ b/tests/rustdoc-ui/track-diagnostics.stderr
@@ -2,7 +2,7 @@ error[E0308]: mismatched types
--> $DIR/track-diagnostics.rs:LL:CC
|
LL | const S: A = B;
- | ^ expected struct `A`, found struct `B`
+ | ^ expected `A`, found `B`
-Ztrack-diagnostics: created at compiler/rustc_infer/src/infer/error_reporting/mod.rs:LL:CC
error: aborting due to previous error
diff --git a/tests/rustdoc-ui/unable-fulfill-trait.stderr b/tests/rustdoc-ui/unable-fulfill-trait.stderr
index a16b5b6eb..72f35cb92 100644
--- a/tests/rustdoc-ui/unable-fulfill-trait.stderr
+++ b/tests/rustdoc-ui/unable-fulfill-trait.stderr
@@ -1,4 +1,4 @@
-error[E0107]: this trait takes 1 generic argument but 0 generic arguments were supplied
+error[E0107]: trait takes 1 generic argument but 0 generic arguments were supplied
--> $DIR/unable-fulfill-trait.rs:4:17
|
LL | field1: dyn Bar<'a, 'b,>,
diff --git a/tests/rustdoc-ui/unknown-renamed-lints.stderr b/tests/rustdoc-ui/unknown-renamed-lints.stderr
index b105f47d7..bf529b9f8 100644
--- a/tests/rustdoc-ui/unknown-renamed-lints.stderr
+++ b/tests/rustdoc-ui/unknown-renamed-lints.stderr
@@ -58,7 +58,5 @@ error: unknown lint: `rustdoc::intra_doc_link_resolution_failure`
LL | #![deny(rustdoc::intra_doc_link_resolution_failure)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-error: Compilation failed, aborting rustdoc
-
-error: aborting due to 9 previous errors
+error: aborting due to 8 previous errors
diff --git a/tests/rustdoc-ui/z-help.stdout b/tests/rustdoc-ui/z-help.stdout
index 4bdecdc1b..79e6b94f1 100644
--- a/tests/rustdoc-ui/z-help.stdout
+++ b/tests/rustdoc-ui/z-help.stdout
@@ -1,193 +1,204 @@
- -Z allow-features=val -- only allow the listed language features to be enabled in code (comma separated)
- -Z always-encode-mir=val -- encode MIR of all functions into the crate metadata (default: no)
- -Z asm-comments=val -- generate comments into the assembly (may change behavior) (default: no)
- -Z assert-incr-state=val -- assert that the incremental cache is in given state: either `loaded` or `not-loaded`.
- -Z assume-incomplete-release=val -- make cfg(version) treat the current version as incomplete (default: no)
- -Z binary-dep-depinfo=val -- include artifacts (sysroot, crate dependencies) used during compilation in dep-info (default: no)
- -Z box-noalias=val -- emit noalias metadata for box (default: yes)
- -Z branch-protection=val -- set options for branch target identification and pointer authentication on AArch64
- -Z cf-protection=val -- instrument control-flow architecture protection
- -Z cgu-partitioning-strategy=val -- the codegen unit partitioning strategy to use
- -Z codegen-backend=val -- the backend to use
- -Z combine-cgu=val -- combine CGUs into a single one
- -Z crate-attr=val -- inject the given attribute in the crate
- -Z debug-info-for-profiling=val -- emit discriminators and other data necessary for AutoFDO
- -Z debug-macros=val -- emit line numbers debug info inside macros (default: no)
- -Z deduplicate-diagnostics=val -- deduplicate identical diagnostics (default: yes)
- -Z dep-info-omit-d-target=val -- in dep-info output, omit targets for tracking dependencies of the dep-info files themselves (default: no)
- -Z dep-tasks=val -- print tasks that execute and the color their dep node gets (requires debug build) (default: no)
- -Z diagnostic-width=val -- set the current output width for diagnostic truncation
- -Z dlltool=val -- import library generation tool (windows-gnu only)
- -Z dont-buffer-diagnostics=val -- emit diagnostics rather than buffering (breaks NLL error downgrading, sorting) (default: no)
- -Z drop-tracking=val -- enables drop tracking in generators (default: no)
- -Z dual-proc-macros=val -- load proc macros for both target and host, but only link to the target (default: no)
- -Z dump-dep-graph=val -- dump the dependency graph to $RUST_DEP_GRAPH (default: /tmp/dep_graph.gv) (default: no)
- -Z dump-drop-tracking-cfg=val -- dump drop-tracking control-flow graph as a `.dot` file (default: no)
- -Z dump-mir=val -- dump MIR state to file.
+ -Z allow-features=val -- only allow the listed language features to be enabled in code (comma separated)
+ -Z always-encode-mir=val -- encode MIR of all functions into the crate metadata (default: no)
+ -Z asm-comments=val -- generate comments into the assembly (may change behavior) (default: no)
+ -Z assert-incr-state=val -- assert that the incremental cache is in given state: either `loaded` or `not-loaded`.
+ -Z assume-incomplete-release=val -- make cfg(version) treat the current version as incomplete (default: no)
+ -Z binary-dep-depinfo=val -- include artifacts (sysroot, crate dependencies) used during compilation in dep-info (default: no)
+ -Z box-noalias=val -- emit noalias metadata for box (default: yes)
+ -Z branch-protection=val -- set options for branch target identification and pointer authentication on AArch64
+ -Z cf-protection=val -- instrument control-flow architecture protection
+ -Z cgu-partitioning-strategy=val -- the codegen unit partitioning strategy to use
+ -Z codegen-backend=val -- the backend to use
+ -Z combine-cgu=val -- combine CGUs into a single one
+ -Z crate-attr=val -- inject the given attribute in the crate
+ -Z debug-info-for-profiling=val -- emit discriminators and other data necessary for AutoFDO
+ -Z debug-macros=val -- emit line numbers debug info inside macros (default: no)
+ -Z deduplicate-diagnostics=val -- deduplicate identical diagnostics (default: yes)
+ -Z dep-info-omit-d-target=val -- in dep-info output, omit targets for tracking dependencies of the dep-info files themselves (default: no)
+ -Z dep-tasks=val -- print tasks that execute and the color their dep node gets (requires debug build) (default: no)
+ -Z diagnostic-width=val -- set the current output width for diagnostic truncation
+ -Z dlltool=val -- import library generation tool (windows-gnu only)
+ -Z dont-buffer-diagnostics=val -- emit diagnostics rather than buffering (breaks NLL error downgrading, sorting) (default: no)
+ -Z drop-tracking=val -- enables drop tracking in generators (default: no)
+ -Z drop-tracking-mir=val -- enables drop tracking on MIR in generators (default: no)
+ -Z dual-proc-macros=val -- load proc macros for both target and host, but only link to the target (default: no)
+ -Z dump-dep-graph=val -- dump the dependency graph to $RUST_DEP_GRAPH (default: /tmp/dep_graph.gv) (default: no)
+ -Z dump-drop-tracking-cfg=val -- dump drop-tracking control-flow graph as a `.dot` file (default: no)
+ -Z dump-mir=val -- dump MIR state to file.
`val` is used to select which passes and functions to dump. For example:
`all` matches all passes and functions,
`foo` matches all passes for functions whose name contains 'foo',
`foo & ConstProp` only the 'ConstProp' pass for function names containing 'foo',
`foo | bar` all passes for function names containing 'foo' or 'bar'.
- -Z dump-mir-dataflow=val -- in addition to `.mir` files, create graphviz `.dot` files with dataflow results (default: no)
- -Z dump-mir-dir=val -- the directory the MIR is dumped into (default: `mir_dump`)
- -Z dump-mir-exclude-pass-number=val -- exclude the pass number when dumping MIR (used in tests) (default: no)
- -Z dump-mir-graphviz=val -- in addition to `.mir` files, create graphviz `.dot` files (and with `-Z instrument-coverage`, also create a `.dot` file for the MIR-derived coverage graph) (default: no)
- -Z dump-mir-spanview=val -- in addition to `.mir` files, create `.html` files to view spans for all `statement`s (including terminators), only `terminator` spans, or computed `block` spans (one span encompassing a block's terminator and all statements). If `-Z instrument-coverage` is also enabled, create an additional `.html` file showing the computed coverage spans.
- -Z dump-mono-stats=val -- output statistics about monomorphization collection
- -Z dump-mono-stats-format=val -- the format to use for -Z dump-mono-stats (`markdown` (default) or `json`)
- -Z dwarf-version=val -- version of DWARF debug information to emit (default: 2 or 4, depending on platform)
- -Z dylib-lto=val -- enables LTO for dylib crate type
- -Z emit-stack-sizes=val -- emit a section containing stack size metadata (default: no)
- -Z emit-thin-lto=val -- emit the bc module with thin LTO info (default: yes)
- -Z export-executable-symbols=val -- export symbols from executables, as if they were dynamic libraries
- -Z extra-const-ub-checks=val -- turns on more checks to detect const UB, which can be slow (default: no)
- -Z fewer-names=val -- reduce memory use by retaining fewer names within compilation artifacts (LLVM-IR) (default: no)
- -Z force-unstable-if-unmarked=val -- force all crates to be `rustc_private` unstable (default: no)
- -Z fuel=val -- set the optimization fuel quota for a crate
- -Z function-sections=val -- whether each function should go in its own section
- -Z future-incompat-test=val -- forces all lints to be future incompatible, used for internal testing (default: no)
- -Z gcc-ld=val -- implementation of ld used by cc
- -Z graphviz-dark-mode=val -- use dark-themed colors in graphviz output (default: no)
- -Z graphviz-font=val -- use the given `fontname` in graphviz output; can be overridden by setting environment variable `RUSTC_GRAPHVIZ_FONT` (default: `Courier, monospace`)
- -Z hir-stats=val -- print some statistics about AST and HIR (default: no)
- -Z human-readable-cgu-names=val -- generate human-readable, predictable names for codegen units (default: no)
- -Z identify-regions=val -- display unnamed regions as `'<id>`, using a non-ident unique id (default: no)
- -Z incremental-ignore-spans=val -- ignore spans during ICH computation -- used for testing (default: no)
- -Z incremental-info=val -- print high-level information about incremental reuse (or the lack thereof) (default: no)
- -Z incremental-relative-spans=val -- hash spans relative to their parent item for incr. comp. (default: no)
- -Z incremental-verify-ich=val -- verify incr. comp. hashes of green query instances (default: no)
- -Z inline-in-all-cgus=val -- control whether `#[inline]` functions are in all CGUs
- -Z inline-llvm=val -- enable LLVM inlining (default: yes)
- -Z inline-mir=val -- enable MIR inlining (default: no)
- -Z inline-mir-hint-threshold=val -- inlining threshold for functions with inline hint (default: 100)
- -Z inline-mir-threshold=val -- a default MIR inlining threshold (default: 50)
- -Z input-stats=val -- gather statistics about the input (default: no)
- -Z instrument-coverage=val -- instrument the generated code to support LLVM source-based code coverage reports (note, the compiler build config must include `profiler = true`); implies `-C symbol-mangling-version=v0`. Optional values are:
+ -Z dump-mir-dataflow=val -- in addition to `.mir` files, create graphviz `.dot` files with dataflow results (default: no)
+ -Z dump-mir-dir=val -- the directory the MIR is dumped into (default: `mir_dump`)
+ -Z dump-mir-exclude-pass-number=val -- exclude the pass number when dumping MIR (used in tests) (default: no)
+ -Z dump-mir-graphviz=val -- in addition to `.mir` files, create graphviz `.dot` files (and with `-Z instrument-coverage`, also create a `.dot` file for the MIR-derived coverage graph) (default: no)
+ -Z dump-mir-spanview=val -- in addition to `.mir` files, create `.html` files to view spans for all `statement`s (including terminators), only `terminator` spans, or computed `block` spans (one span encompassing a block's terminator and all statements). If `-Z instrument-coverage` is also enabled, create an additional `.html` file showing the computed coverage spans.
+ -Z dump-mono-stats=val -- output statistics about monomorphization collection
+ -Z dump-mono-stats-format=val -- the format to use for -Z dump-mono-stats (`markdown` (default) or `json`)
+ -Z dwarf-version=val -- version of DWARF debug information to emit (default: 2 or 4, depending on platform)
+ -Z dylib-lto=val -- enables LTO for dylib crate type
+ -Z emit-stack-sizes=val -- emit a section containing stack size metadata (default: no)
+ -Z emit-thin-lto=val -- emit the bc module with thin LTO info (default: yes)
+ -Z export-executable-symbols=val -- export symbols from executables, as if they were dynamic libraries
+ -Z extra-const-ub-checks=val -- turns on more checks to detect const UB, which can be slow (default: no)
+ -Z fewer-names=val -- reduce memory use by retaining fewer names within compilation artifacts (LLVM-IR) (default: no)
+ -Z force-unstable-if-unmarked=val -- force all crates to be `rustc_private` unstable (default: no)
+ -Z fuel=val -- set the optimization fuel quota for a crate
+ -Z function-sections=val -- whether each function should go in its own section
+ -Z future-incompat-test=val -- forces all lints to be future incompatible, used for internal testing (default: no)
+ -Z gcc-ld=val -- implementation of ld used by cc
+ -Z graphviz-dark-mode=val -- use dark-themed colors in graphviz output (default: no)
+ -Z graphviz-font=val -- use the given `fontname` in graphviz output; can be overridden by setting environment variable `RUSTC_GRAPHVIZ_FONT` (default: `Courier, monospace`)
+ -Z hir-stats=val -- print some statistics about AST and HIR (default: no)
+ -Z human-readable-cgu-names=val -- generate human-readable, predictable names for codegen units (default: no)
+ -Z identify-regions=val -- display unnamed regions as `'<id>`, using a non-ident unique id (default: no)
+ -Z incremental-ignore-spans=val -- ignore spans during ICH computation -- used for testing (default: no)
+ -Z incremental-info=val -- print high-level information about incremental reuse (or the lack thereof) (default: no)
+ -Z incremental-relative-spans=val -- hash spans relative to their parent item for incr. comp. (default: no)
+ -Z incremental-verify-ich=val -- verify incr. comp. hashes of green query instances (default: no)
+ -Z inline-in-all-cgus=val -- control whether `#[inline]` functions are in all CGUs
+ -Z inline-llvm=val -- enable LLVM inlining (default: yes)
+ -Z inline-mir=val -- enable MIR inlining (default: no)
+ -Z inline-mir-hint-threshold=val -- inlining threshold for functions with inline hint (default: 100)
+ -Z inline-mir-threshold=val -- a default MIR inlining threshold (default: 50)
+ -Z input-stats=val -- gather statistics about the input (default: no)
+ -Z instrument-coverage=val -- instrument the generated code to support LLVM source-based code coverage reports (note, the compiler build config must include `profiler = true`); implies `-C symbol-mangling-version=v0`. Optional values are:
`=all` (implicit value)
`=except-unused-generics`
`=except-unused-functions`
`=off` (default)
- -Z instrument-mcount=val -- insert function instrument code for mcount-based tracing (default: no)
- -Z keep-hygiene-data=val -- keep hygiene data after analysis (default: no)
- -Z layout-seed=val -- seed layout randomization
- -Z link-native-libraries=val -- link native libraries in the linker invocation (default: yes)
- -Z link-only=val -- link the `.rlink` file generated by `-Z no-link` (default: no)
- -Z llvm-plugins=val -- a list LLVM plugins to enable (space separated)
- -Z llvm-time-trace=val -- generate JSON tracing data file from LLVM data (default: no)
- -Z location-detail=val -- what location details should be tracked when using caller_location, either `none`, or a comma separated list of location details, for which valid options are `file`, `line`, and `column` (default: `file,line,column`)
- -Z log-backtrace=val -- add a backtrace along with logging
- -Z ls=val -- list the symbols defined by a library crate (default: no)
- -Z macro-backtrace=val -- show macro backtraces (default: no)
- -Z maximal-hir-to-mir-coverage=val -- save as much information as possible about the correspondence between MIR and HIR as source scopes (default: no)
- -Z merge-functions=val -- control the operation of the MergeFunctions LLVM pass, taking the same values as the target option of the same name
- -Z meta-stats=val -- gather metadata statistics (default: no)
- -Z mir-emit-retag=val -- emit Retagging MIR statements, interpreted e.g., by miri; implies -Zmir-opt-level=0 (default: no)
- -Z mir-enable-passes=val -- use like `-Zmir-enable-passes=+DestProp,-InstCombine`. Forces the specified passes to be enabled, overriding all other checks. Passes that are not specified are enabled or disabled by other flags as usual.
- -Z mir-opt-level=val -- MIR optimization level (0-4; default: 1 in non optimized builds and 2 in optimized builds)
- -Z mir-pretty-relative-line-numbers=val -- use line numbers relative to the function in mir pretty printing
- -Z move-size-limit=val -- the size at which the `large_assignments` lint starts to be emitted
- -Z mutable-noalias=val -- emit noalias metadata for mutable references (default: yes)
- -Z nll-facts=val -- dump facts from NLL analysis into side files (default: no)
- -Z nll-facts-dir=val -- the directory the NLL facts are dumped into (default: `nll-facts`)
- -Z no-analysis=val -- parse and expand the source, but run no analysis
- -Z no-codegen=val -- run all passes except codegen; no output
- -Z no-generate-arange-section=val -- omit DWARF address ranges that give faster lookups
- -Z no-jump-tables=val -- disable the jump tables and lookup tables that can be generated from a switch case lowering
- -Z no-leak-check=val -- disable the 'leak check' for subtyping; unsound, but useful for tests
- -Z no-link=val -- compile without linking
- -Z no-parallel-llvm=val -- run LLVM in non-parallel mode (while keeping codegen-units and ThinLTO)
- -Z no-profiler-runtime=val -- prevent automatic injection of the profiler_builtins crate
- -Z no-unique-section-names=val -- do not use unique names for text and data sections when -Z function-sections is used
- -Z normalize-docs=val -- normalize associated items in rustdoc when generating documentation
- -Z oom=val -- panic strategy for out-of-memory handling
- -Z osx-rpath-install-name=val -- pass `-install_name @rpath/...` to the macOS linker (default: no)
- -Z packed-bundled-libs=val -- change rlib format to store native libraries as archives
- -Z panic-abort-tests=val -- support compiling tests with panic=abort (default: no)
- -Z panic-in-drop=val -- panic strategy for panics in drops
- -Z parse-only=val -- parse only; do not compile, assemble, or link (default: no)
- -Z perf-stats=val -- print some performance-related statistics (default: no)
- -Z pick-stable-methods-before-any-unstable=val -- try to pick stable methods first before picking any unstable methods (default: yes)
- -Z plt=val -- whether to use the PLT when calling into shared libraries;
+ -Z instrument-mcount=val -- insert function instrument code for mcount-based tracing (default: no)
+ -Z instrument-xray=val -- insert function instrument code for XRay-based tracing (default: no)
+ Optional extra settings:
+ `=always`
+ `=never`
+ `=ignore-loops`
+ `=instruction-threshold=N`
+ `=skip-entry`
+ `=skip-exit`
+ Multiple options can be combined with commas.
+ -Z keep-hygiene-data=val -- keep hygiene data after analysis (default: no)
+ -Z layout-seed=val -- seed layout randomization
+ -Z link-directives=val -- honor #[link] directives in the compiled crate (default: yes)
+ -Z link-native-libraries=val -- link native libraries in the linker invocation (default: yes)
+ -Z link-only=val -- link the `.rlink` file generated by `-Z no-link` (default: no)
+ -Z llvm-plugins=val -- a list LLVM plugins to enable (space separated)
+ -Z llvm-time-trace=val -- generate JSON tracing data file from LLVM data (default: no)
+ -Z location-detail=val -- what location details should be tracked when using caller_location, either `none`, or a comma separated list of location details, for which valid options are `file`, `line`, and `column` (default: `file,line,column`)
+ -Z lower-impl-trait-in-trait-to-assoc-ty=val -- modify the lowering strategy for `impl Trait` in traits so that they are lowered to generic associated types
+ -Z ls=val -- list the symbols defined by a library crate (default: no)
+ -Z macro-backtrace=val -- show macro backtraces (default: no)
+ -Z maximal-hir-to-mir-coverage=val -- save as much information as possible about the correspondence between MIR and HIR as source scopes (default: no)
+ -Z merge-functions=val -- control the operation of the MergeFunctions LLVM pass, taking the same values as the target option of the same name
+ -Z meta-stats=val -- gather metadata statistics (default: no)
+ -Z mir-emit-retag=val -- emit Retagging MIR statements, interpreted e.g., by miri; implies -Zmir-opt-level=0 (default: no)
+ -Z mir-enable-passes=val -- use like `-Zmir-enable-passes=+DestProp,-InstCombine`. Forces the specified passes to be enabled, overriding all other checks. Passes that are not specified are enabled or disabled by other flags as usual.
+ -Z mir-opt-level=val -- MIR optimization level (0-4; default: 1 in non optimized builds and 2 in optimized builds)
+ -Z mir-pretty-relative-line-numbers=val -- use line numbers relative to the function in mir pretty printing
+ -Z move-size-limit=val -- the size at which the `large_assignments` lint starts to be emitted
+ -Z mutable-noalias=val -- emit noalias metadata for mutable references (default: yes)
+ -Z nll-facts=val -- dump facts from NLL analysis into side files (default: no)
+ -Z nll-facts-dir=val -- the directory the NLL facts are dumped into (default: `nll-facts`)
+ -Z no-analysis=val -- parse and expand the source, but run no analysis
+ -Z no-codegen=val -- run all passes except codegen; no output
+ -Z no-generate-arange-section=val -- omit DWARF address ranges that give faster lookups
+ -Z no-jump-tables=val -- disable the jump tables and lookup tables that can be generated from a switch case lowering
+ -Z no-leak-check=val -- disable the 'leak check' for subtyping; unsound, but useful for tests
+ -Z no-link=val -- compile without linking
+ -Z no-parallel-llvm=val -- run LLVM in non-parallel mode (while keeping codegen-units and ThinLTO)
+ -Z no-profiler-runtime=val -- prevent automatic injection of the profiler_builtins crate
+ -Z no-unique-section-names=val -- do not use unique names for text and data sections when -Z function-sections is used
+ -Z normalize-docs=val -- normalize associated items in rustdoc when generating documentation
+ -Z oom=val -- panic strategy for out-of-memory handling
+ -Z osx-rpath-install-name=val -- pass `-install_name @rpath/...` to the macOS linker (default: no)
+ -Z packed-bundled-libs=val -- change rlib format to store native libraries as archives
+ -Z panic-abort-tests=val -- support compiling tests with panic=abort (default: no)
+ -Z panic-in-drop=val -- panic strategy for panics in drops
+ -Z parse-only=val -- parse only; do not compile, assemble, or link (default: no)
+ -Z perf-stats=val -- print some performance-related statistics (default: no)
+ -Z plt=val -- whether to use the PLT when calling into shared libraries;
only has effect for PIC code on systems with ELF binaries
(default: PLT is disabled if full relro is enabled)
- -Z polonius=val -- enable polonius-based borrow-checker (default: no)
- -Z polymorphize=val -- perform polymorphization analysis
- -Z pre-link-arg=val -- a single extra argument to prepend the linker invocation (can be used several times)
- -Z pre-link-args=val -- extra arguments to prepend to the linker invocation (space separated)
- -Z precise-enum-drop-elaboration=val -- use a more precise version of drop elaboration for matches on enums (default: yes). This results in better codegen, but has caused miscompilations on some tier 2 platforms. See #77382 and #74551.
- -Z print-fuel=val -- make rustc print the total optimization fuel used by a crate
- -Z print-llvm-passes=val -- print the LLVM optimization passes being run (default: no)
- -Z print-mono-items=val -- print the result of the monomorphization collection pass
- -Z print-type-sizes=val -- print layout information for each type encountered (default: no)
- -Z proc-macro-backtrace=val -- show backtraces for panics during proc-macro execution (default: no)
- -Z proc-macro-execution-strategy=val -- how to run proc-macro code (default: same-thread)
- -Z profile=val -- insert profiling code (default: no)
- -Z profile-closures=val -- profile size of closures
- -Z profile-emit=val -- file path to emit profiling data at runtime when using 'profile' (default based on relative source path)
- -Z profile-sample-use=val -- use the given `.prof` file for sampled profile-guided optimization (also known as AutoFDO)
- -Z profiler-runtime=val -- name of the profiler runtime crate to automatically inject (default: `profiler_builtins`)
- -Z query-dep-graph=val -- enable queries of the dependency graph for regression testing (default: no)
- -Z randomize-layout=val -- randomize the layout of types (default: no)
- -Z relax-elf-relocations=val -- whether ELF relocations can be relaxed
- -Z relro-level=val -- choose which RELRO level to use
- -Z remap-cwd-prefix=val -- remap paths under the current working directory to this path prefix
- -Z report-delayed-bugs=val -- immediately print bugs registered with `delay_span_bug` (default: no)
- -Z sanitizer=val -- use a sanitizer
- -Z sanitizer-memory-track-origins=val -- enable origins tracking in MemorySanitizer
- -Z sanitizer-recover=val -- enable recovery for selected sanitizers
- -Z saturating-float-casts=val -- make float->int casts UB-free: numbers outside the integer type's range are clipped to the max/min integer respectively, and NaN is mapped to 0 (default: yes)
- -Z save-analysis=val -- write syntax and type analysis (in JSON format) information, in addition to normal output (default: no)
- -Z self-profile=val -- run the self profiler and output the raw event data
- -Z self-profile-counter=val -- counter used by the self profiler (default: `wall-time`), one of:
+ -Z polonius=val -- enable polonius-based borrow-checker (default: no)
+ -Z polymorphize=val -- perform polymorphization analysis
+ -Z pre-link-arg=val -- a single extra argument to prepend the linker invocation (can be used several times)
+ -Z pre-link-args=val -- extra arguments to prepend to the linker invocation (space separated)
+ -Z precise-enum-drop-elaboration=val -- use a more precise version of drop elaboration for matches on enums (default: yes). This results in better codegen, but has caused miscompilations on some tier 2 platforms. See #77382 and #74551.
+ -Z print-fuel=val -- make rustc print the total optimization fuel used by a crate
+ -Z print-llvm-passes=val -- print the LLVM optimization passes being run (default: no)
+ -Z print-mono-items=val -- print the result of the monomorphization collection pass
+ -Z print-type-sizes=val -- print layout information for each type encountered (default: no)
+ -Z proc-macro-backtrace=val -- show backtraces for panics during proc-macro execution (default: no)
+ -Z proc-macro-execution-strategy=val -- how to run proc-macro code (default: same-thread)
+ -Z profile=val -- insert profiling code (default: no)
+ -Z profile-closures=val -- profile size of closures
+ -Z profile-emit=val -- file path to emit profiling data at runtime when using 'profile' (default based on relative source path)
+ -Z profile-sample-use=val -- use the given `.prof` file for sampled profile-guided optimization (also known as AutoFDO)
+ -Z profiler-runtime=val -- name of the profiler runtime crate to automatically inject (default: `profiler_builtins`)
+ -Z query-dep-graph=val -- enable queries of the dependency graph for regression testing (default: no)
+ -Z randomize-layout=val -- randomize the layout of types (default: no)
+ -Z relax-elf-relocations=val -- whether ELF relocations can be relaxed
+ -Z relro-level=val -- choose which RELRO level to use
+ -Z remap-cwd-prefix=val -- remap paths under the current working directory to this path prefix
+ -Z report-delayed-bugs=val -- immediately print bugs registered with `delay_span_bug` (default: no)
+ -Z sanitizer=val -- use a sanitizer
+ -Z sanitizer-memory-track-origins=val -- enable origins tracking in MemorySanitizer
+ -Z sanitizer-recover=val -- enable recovery for selected sanitizers
+ -Z saturating-float-casts=val -- make float->int casts UB-free: numbers outside the integer type's range are clipped to the max/min integer respectively, and NaN is mapped to 0 (default: yes)
+ -Z self-profile=val -- run the self profiler and output the raw event data
+ -Z self-profile-counter=val -- counter used by the self profiler (default: `wall-time`), one of:
`wall-time` (monotonic clock, i.e. `std::time::Instant`)
`instructions:u` (retired instructions, userspace-only)
`instructions-minus-irqs:u` (subtracting hardware interrupt counts for extra accuracy)
- -Z self-profile-events=val -- specify the events recorded by the self profiler;
+ -Z self-profile-events=val -- specify the events recorded by the self profiler;
for example: `-Z self-profile-events=default,query-keys`
all options: none, all, default, generic-activity, query-provider, query-cache-hit
query-blocked, incr-cache-load, incr-result-hashing, query-keys, function-args, args, llvm, artifact-sizes
- -Z share-generics=val -- make the current crate share its generic instantiations
- -Z show-span=val -- show spans for compiler debugging (expr|pat|ty)
- -Z simulate-remapped-rust-src-base=val -- simulate the effect of remap-debuginfo = true at bootstrapping by remapping path to rust's source base directory. only meant for testing purposes
- -Z span-debug=val -- forward proc_macro::Span's `Debug` impl to `Span`
- -Z span-free-formats=val -- exclude spans when debug-printing compiler state (default: no)
- -Z split-dwarf-inlining=val -- provide minimal debug info in the object/executable to facilitate online symbolication/stack traces in the absence of .dwo/.dwp files when using Split DWARF
- -Z split-dwarf-kind=val -- split dwarf variant (only if -Csplit-debuginfo is enabled and on relevant platform)
+ -Z share-generics=val -- make the current crate share its generic instantiations
+ -Z show-span=val -- show spans for compiler debugging (expr|pat|ty)
+ -Z simulate-remapped-rust-src-base=val -- simulate the effect of remap-debuginfo = true at bootstrapping by remapping path to rust's source base directory. only meant for testing purposes
+ -Z span-debug=val -- forward proc_macro::Span's `Debug` impl to `Span`
+ -Z span-free-formats=val -- exclude spans when debug-printing compiler state (default: no)
+ -Z split-dwarf-inlining=val -- provide minimal debug info in the object/executable to facilitate online symbolication/stack traces in the absence of .dwo/.dwp files when using Split DWARF
+ -Z split-dwarf-kind=val -- split dwarf variant (only if -Csplit-debuginfo is enabled and on relevant platform)
(default: `split`)
`split`: sections which do not require relocation are written into a DWARF object (`.dwo`)
file which is ignored by the linker
`single`: sections which do not require relocation are written into object file but ignored
by the linker
- -Z src-hash-algorithm=val -- hash algorithm of source files in debug info (`md5`, `sha1`, or `sha256`)
- -Z stack-protector=val -- control stack smash protection strategy (`rustc --print stack-protector-strategies` for details)
- -Z strict-init-checks=val -- control if mem::uninitialized and mem::zeroed panic on more UB
- -Z strip=val -- tell the linker which information to strip (`none` (default), `debuginfo` or `symbols`)
- -Z symbol-mangling-version=val -- which mangling version to use for symbol names ('legacy' (default) or 'v0')
- -Z teach=val -- show extended diagnostic help (default: no)
- -Z temps-dir=val -- the directory the intermediate files are written to
- -Z thinlto=val -- enable ThinLTO when possible
- -Z thir-unsafeck=val -- use the THIR unsafety checker (default: no)
- -Z threads=val -- use a thread pool with N threads
- -Z time-llvm-passes=val -- measure time of each LLVM pass (default: no)
- -Z time-passes=val -- measure time of each rustc pass (default: no)
- -Z tls-model=val -- choose the TLS model to use (`rustc --print tls-models` for details)
- -Z trace-macros=val -- for every macro invocation, print its name and arguments (default: no)
- -Z track-diagnostics=val -- tracks where in rustc a diagnostic was emitted
- -Z trait-solver=val -- specify the trait solver mode used by rustc (default: classic)
- -Z translate-additional-ftl=val -- additional fluent translation to preferentially use (for testing translation)
- -Z translate-directionality-markers=val -- emit directionality isolation markers in translated diagnostics
- -Z translate-lang=val -- language identifier for diagnostic output
- -Z translate-remapped-path-to-local-path=val -- translate remapped paths into local paths when possible (default: yes)
- -Z trap-unreachable=val -- generate trap instructions for unreachable intrinsics (default: use target setting, usually yes)
- -Z treat-err-as-bug=val -- treat error number `val` that occurs as bug
- -Z trim-diagnostic-paths=val -- in diagnostics, use heuristics to shorten paths referring to items
- -Z tune-cpu=val -- select processor to schedule for (`rustc --print target-cpus` for details)
- -Z ui-testing=val -- emit compiler diagnostics in a form suitable for UI testing (default: no)
- -Z uninit-const-chunk-threshold=val -- allow generating const initializers with mixed init/uninit chunks, and set the maximum number of chunks for which this is allowed (default: 16)
- -Z unleash-the-miri-inside-of-you=val -- take the brakes off const evaluation. NOTE: this is unsound (default: no)
- -Z unpretty=val -- present the input source, unstable (and less-pretty) variants;
+ -Z src-hash-algorithm=val -- hash algorithm of source files in debug info (`md5`, `sha1`, or `sha256`)
+ -Z stack-protector=val -- control stack smash protection strategy (`rustc --print stack-protector-strategies` for details)
+ -Z strict-init-checks=val -- control if mem::uninitialized and mem::zeroed panic on more UB
+ -Z strip=val -- tell the linker which information to strip (`none` (default), `debuginfo` or `symbols`)
+ -Z symbol-mangling-version=val -- which mangling version to use for symbol names ('legacy' (default) or 'v0')
+ -Z teach=val -- show extended diagnostic help (default: no)
+ -Z temps-dir=val -- the directory the intermediate files are written to
+ -Z terminal-urls=val -- use the OSC 8 hyperlink terminal specification to print hyperlinks in the compiler output
+ -Z thinlto=val -- enable ThinLTO when possible
+ -Z thir-unsafeck=val -- use the THIR unsafety checker (default: no)
+ -Z threads=val -- use a thread pool with N threads
+ -Z time-llvm-passes=val -- measure time of each LLVM pass (default: no)
+ -Z time-passes=val -- measure time of each rustc pass (default: no)
+ -Z tiny-const-eval-limit=val -- sets a tiny, non-configurable limit for const eval; useful for compiler tests
+ -Z tls-model=val -- choose the TLS model to use (`rustc --print tls-models` for details)
+ -Z trace-macros=val -- for every macro invocation, print its name and arguments (default: no)
+ -Z track-diagnostics=val -- tracks where in rustc a diagnostic was emitted
+ -Z trait-solver=val -- specify the trait solver mode used by rustc (default: classic)
+ -Z translate-additional-ftl=val -- additional fluent translation to preferentially use (for testing translation)
+ -Z translate-directionality-markers=val -- emit directionality isolation markers in translated diagnostics
+ -Z translate-lang=val -- language identifier for diagnostic output
+ -Z translate-remapped-path-to-local-path=val -- translate remapped paths into local paths when possible (default: yes)
+ -Z trap-unreachable=val -- generate trap instructions for unreachable intrinsics (default: use target setting, usually yes)
+ -Z treat-err-as-bug=val -- treat error number `val` that occurs as bug
+ -Z trim-diagnostic-paths=val -- in diagnostics, use heuristics to shorten paths referring to items
+ -Z tune-cpu=val -- select processor to schedule for (`rustc --print target-cpus` for details)
+ -Z ui-testing=val -- emit compiler diagnostics in a form suitable for UI testing (default: no)
+ -Z uninit-const-chunk-threshold=val -- allow generating const initializers with mixed init/uninit chunks, and set the maximum number of chunks for which this is allowed (default: 16)
+ -Z unleash-the-miri-inside-of-you=val -- take the brakes off const evaluation. NOTE: this is unsound (default: no)
+ -Z unpretty=val -- present the input source, unstable (and less-pretty) variants;
`normal`, `identified`,
`expanded`, `expanded,identified`,
`expanded,hygiene` (with internal representations),
@@ -197,11 +208,11 @@
`hir,typed` (HIR with types for each node),
`hir-tree` (dump the raw HIR),
`mir` (the MIR), or `mir-cfg` (graphviz formatted MIR)
- -Z unsound-mir-opts=val -- enable unsound and buggy MIR optimizations (default: no)
- -Z unstable-options=val -- adds unstable command line options to rustc interface (default: no)
- -Z use-ctors-section=val -- use legacy .ctors section for initializers rather than .init_array
- -Z validate-mir=val -- validate MIR after each transformation
- -Z verbose=val -- in general, enable more debug printouts (default: no)
- -Z verify-llvm-ir=val -- verify LLVM IR (default: no)
- -Z virtual-function-elimination=val -- enables dead virtual function elimination optimization. Requires `-Clto[=[fat,yes]]`
- -Z wasi-exec-model=val -- whether to build a wasi command or reactor
+ -Z unsound-mir-opts=val -- enable unsound and buggy MIR optimizations (default: no)
+ -Z unstable-options=val -- adds unstable command line options to rustc interface (default: no)
+ -Z use-ctors-section=val -- use legacy .ctors section for initializers rather than .init_array
+ -Z validate-mir=val -- validate MIR after each transformation
+ -Z verbose=val -- in general, enable more debug printouts (default: no)
+ -Z verify-llvm-ir=val -- verify LLVM IR (default: no)
+ -Z virtual-function-elimination=val -- enables dead virtual function elimination optimization. Requires `-Clto[=[fat,yes]]`
+ -Z wasi-exec-model=val -- whether to build a wasi command or reactor
diff --git a/tests/rustdoc/anchors.no_const_anchor.html b/tests/rustdoc/anchors.no_const_anchor.html
index 75e67330a..a8587829d 100644
--- a/tests/rustdoc/anchors.no_const_anchor.html
+++ b/tests/rustdoc/anchors.no_const_anchor.html
@@ -1 +1 @@
-<section id="associatedconstant.YOLO" class="method has-srclink"><a class="srclink rightside" href="../src/foo/anchors.rs.html#16">source</a><h4 class="code-header">const <a href="#associatedconstant.YOLO" class="constant">YOLO</a>: <a class="primitive" href="{{channel}}/std/primitive.u32.html">u32</a></h4></section> \ No newline at end of file
+<section id="associatedconstant.YOLO" class="method"><a class="srclink rightside" href="../src/foo/anchors.rs.html#16">source</a><h4 class="code-header">const <a href="#associatedconstant.YOLO" class="constant">YOLO</a>: <a class="primitive" href="{{channel}}/std/primitive.u32.html">u32</a></h4></section> \ No newline at end of file
diff --git a/tests/rustdoc/anchors.no_const_anchor2.html b/tests/rustdoc/anchors.no_const_anchor2.html
index c00251976..4c5e45fea 100644
--- a/tests/rustdoc/anchors.no_const_anchor2.html
+++ b/tests/rustdoc/anchors.no_const_anchor2.html
@@ -1 +1 @@
-<section id="associatedconstant.X" class="associatedconstant has-srclink"><a class="srclink rightside" href="../src/foo/anchors.rs.html#42">source</a><h4 class="code-header">pub const <a href="#associatedconstant.X" class="constant">X</a>: <a class="primitive" href="{{channel}}/std/primitive.i32.html">i32</a> = 0i32</h4></section> \ No newline at end of file
+<section id="associatedconstant.X" class="associatedconstant"><a class="srclink rightside" href="../src/foo/anchors.rs.html#42">source</a><h4 class="code-header">pub const <a href="#associatedconstant.X" class="constant">X</a>: <a class="primitive" href="{{channel}}/std/primitive.i32.html">i32</a> = 0i32</h4></section> \ No newline at end of file
diff --git a/tests/rustdoc/anchors.no_method_anchor.html b/tests/rustdoc/anchors.no_method_anchor.html
index b9ec8bf4c..44957a5b7 100644
--- a/tests/rustdoc/anchors.no_method_anchor.html
+++ b/tests/rustdoc/anchors.no_method_anchor.html
@@ -1 +1 @@
-<section id="method.new" class="method has-srclink"><a class="srclink rightside" href="../src/foo/anchors.rs.html#48">source</a><h4 class="code-header">pub fn <a href="#method.new" class="fn">new</a>() -&gt; Self</h4></section> \ No newline at end of file
+<section id="method.new" class="method"><a class="srclink rightside" href="../src/foo/anchors.rs.html#48">source</a><h4 class="code-header">pub fn <a href="#method.new" class="fn">new</a>() -&gt; Self</h4></section> \ No newline at end of file
diff --git a/tests/rustdoc/anchors.no_trait_method_anchor.html b/tests/rustdoc/anchors.no_trait_method_anchor.html
index 4308ddad4..75c2caf87 100644
--- a/tests/rustdoc/anchors.no_trait_method_anchor.html
+++ b/tests/rustdoc/anchors.no_trait_method_anchor.html
@@ -1 +1 @@
-<section id="method.bar" class="method has-srclink"><a class="srclink rightside" href="../src/foo/anchors.rs.html#23">source</a><h4 class="code-header">fn <a href="#method.bar" class="fn">bar</a>()</h4></section> \ No newline at end of file
+<section id="method.bar" class="method"><a class="srclink rightside" href="../src/foo/anchors.rs.html#23">source</a><h4 class="code-header">fn <a href="#method.bar" class="fn">bar</a>()</h4></section> \ No newline at end of file
diff --git a/tests/rustdoc/anchors.no_tymethod_anchor.html b/tests/rustdoc/anchors.no_tymethod_anchor.html
index 91eed8a37..38575eadf 100644
--- a/tests/rustdoc/anchors.no_tymethod_anchor.html
+++ b/tests/rustdoc/anchors.no_tymethod_anchor.html
@@ -1 +1 @@
-<section id="tymethod.foo" class="method has-srclink"><a class="srclink rightside" href="../src/foo/anchors.rs.html#20">source</a><h4 class="code-header">fn <a href="#tymethod.foo" class="fn">foo</a>()</h4></section> \ No newline at end of file
+<section id="tymethod.foo" class="method"><a class="srclink rightside" href="../src/foo/anchors.rs.html#20">source</a><h4 class="code-header">fn <a href="#tymethod.foo" class="fn">foo</a>()</h4></section> \ No newline at end of file
diff --git a/tests/rustdoc/anchors.no_type_anchor.html b/tests/rustdoc/anchors.no_type_anchor.html
index 2c66d5aa3..dd65d98fe 100644
--- a/tests/rustdoc/anchors.no_type_anchor.html
+++ b/tests/rustdoc/anchors.no_type_anchor.html
@@ -1 +1 @@
-<section id="associatedtype.T" class="method has-srclink"><a class="srclink rightside" href="../src/foo/anchors.rs.html#13">source</a><h4 class="code-header">type <a href="#associatedtype.T" class="associatedtype">T</a></h4></section> \ No newline at end of file
+<section id="associatedtype.T" class="method"><a class="srclink rightside" href="../src/foo/anchors.rs.html#13">source</a><h4 class="code-header">type <a href="#associatedtype.T" class="associatedtype">T</a></h4></section> \ No newline at end of file
diff --git a/tests/rustdoc/anchors.no_type_anchor2.html b/tests/rustdoc/anchors.no_type_anchor2.html
index 72a1186bf..f8b59160f 100644
--- a/tests/rustdoc/anchors.no_type_anchor2.html
+++ b/tests/rustdoc/anchors.no_type_anchor2.html
@@ -1 +1 @@
-<section id="associatedtype.Y" class="associatedtype has-srclink"><h4 class="code-header">type <a href="#associatedtype.Y" class="associatedtype">Y</a> = <a class="primitive" href="{{channel}}/std/primitive.u32.html">u32</a></h4></section>
+<section id="associatedtype.Y" class="associatedtype"><h4 class="code-header">type <a href="#associatedtype.Y" class="associatedtype">Y</a> = <a class="primitive" href="{{channel}}/std/primitive.u32.html">u32</a></h4></section> \ No newline at end of file
diff --git a/tests/rustdoc/array-links.rs b/tests/rustdoc/array-links.rs
index e7c0ee2de..8ee294daa 100644
--- a/tests/rustdoc/array-links.rs
+++ b/tests/rustdoc/array-links.rs
@@ -4,25 +4,25 @@
pub struct MyBox<T: ?Sized>(*const T);
// @has 'foo/fn.alpha.html'
-// @snapshot link_slice_u32 - '//div[@class="item-decl"]/pre[@class="rust"]/code'
+// @snapshot link_slice_u32 - '//pre[@class="rust item-decl"]/code'
pub fn alpha() -> &'static [u32; 1] {
loop {}
}
// @has 'foo/fn.beta.html'
-// @snapshot link_slice_generic - '//div[@class="item-decl"]/pre[@class="rust"]/code'
+// @snapshot link_slice_generic - '//pre[@class="rust item-decl"]/code'
pub fn beta<T>() -> &'static [T; 1] {
loop {}
}
// @has 'foo/fn.gamma.html'
-// @snapshot link_box_u32 - '//div[@class="item-decl"]/pre[@class="rust"]/code'
+// @snapshot link_box_u32 - '//pre[@class="rust item-decl"]/code'
pub fn gamma() -> MyBox<[u32; 1]> {
loop {}
}
// @has 'foo/fn.delta.html'
-// @snapshot link_box_generic - '//div[@class="item-decl"]/pre[@class="rust"]/code'
+// @snapshot link_box_generic - '//pre[@class="rust item-decl"]/code'
pub fn delta<T>() -> MyBox<[T; 1]> {
loop {}
}
diff --git a/tests/rustdoc/assoc-consts.rs b/tests/rustdoc/assoc-consts.rs
index 77b139b64..68a11c57b 100644
--- a/tests/rustdoc/assoc-consts.rs
+++ b/tests/rustdoc/assoc-consts.rs
@@ -1,5 +1,5 @@
pub trait Foo {
- // @has assoc_consts/trait.Foo.html '//div[@class="item-decl"]/pre[@class="rust"]' \
+ // @has assoc_consts/trait.Foo.html '//pre[@class="rust item-decl"]' \
// 'const FOO: usize = 13usize;'
// @has - '//*[@id="associatedconstant.FOO"]' 'const FOO: usize'
const FOO: usize = 12 + 1;
diff --git a/tests/rustdoc/assoc-item-cast.rs b/tests/rustdoc/assoc-item-cast.rs
index ab9702a24..ad8235985 100644
--- a/tests/rustdoc/assoc-item-cast.rs
+++ b/tests/rustdoc/assoc-item-cast.rs
@@ -10,5 +10,5 @@ pub trait AsExpression<T> {
}
// @has foo/type.AsExprOf.html
-// @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'type AsExprOf<Item, Type> = <Item as AsExpression<Type>>::Expression;'
+// @has - '//pre[@class="rust item-decl"]' 'type AsExprOf<Item, Type> = <Item as AsExpression<Type>>::Expression;'
pub type AsExprOf<Item, Type> = <Item as AsExpression<Type>>::Expression;
diff --git a/tests/rustdoc/assoc-types.rs b/tests/rustdoc/assoc-types.rs
index de36c8ffe..e74db7578 100644
--- a/tests/rustdoc/assoc-types.rs
+++ b/tests/rustdoc/assoc-types.rs
@@ -12,8 +12,8 @@ pub trait Index<I: ?Sized> {
}
// @has assoc_types/fn.use_output.html
-// @has - '//div[@class="item-decl"]/pre[@class="rust"]' '-> &T::Output'
-// @has - '//div[@class="item-decl"]/pre[@class="rust"]//a[@href="trait.Index.html#associatedtype.Output"]' 'Output'
+// @has - '//pre[@class="rust item-decl"]' '-> &T::Output'
+// @has - '//pre[@class="rust item-decl"]//a[@href="trait.Index.html#associatedtype.Output"]' 'Output'
pub fn use_output<T: Index<usize>>(obj: &T, index: usize) -> &T::Output {
obj.index(index)
}
@@ -23,13 +23,13 @@ pub trait Feed {
}
// @has assoc_types/fn.use_input.html
-// @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'T::Input'
-// @has - '//div[@class="item-decl"]/pre[@class="rust"]//a[@href="trait.Feed.html#associatedtype.Input"]' 'Input'
+// @has - '//pre[@class="rust item-decl"]' 'T::Input'
+// @has - '//pre[@class="rust item-decl"]//a[@href="trait.Feed.html#associatedtype.Input"]' 'Input'
pub fn use_input<T: Feed>(_feed: &T, _element: T::Input) { }
// @has assoc_types/fn.cmp_input.html
-// @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'where T::Input: PartialEq<U::Input>'
-// @has - '//div[@class="item-decl"]/pre[@class="rust"]//a[@href="trait.Feed.html#associatedtype.Input"]' 'Input'
+// @has - '//pre[@class="rust item-decl"]' 'where T::Input: PartialEq<U::Input>'
+// @has - '//pre[@class="rust item-decl"]//a[@href="trait.Feed.html#associatedtype.Input"]' 'Input'
pub fn cmp_input<T: Feed, U: Feed>(a: &T::Input, b: &U::Input) -> bool
where T::Input: PartialEq<U::Input>
{
diff --git a/tests/rustdoc/async-fn-opaque-item.rs b/tests/rustdoc/async-fn-opaque-item.rs
new file mode 100644
index 000000000..a73e84f3f
--- /dev/null
+++ b/tests/rustdoc/async-fn-opaque-item.rs
@@ -0,0 +1,15 @@
+// compile-flags: --document-private-items --crate-type=lib
+// edition: 2021
+
+// Issue 109931 -- test against accidentally documenting the `impl Future`
+// that comes from an async fn desugaring.
+
+// Check that we don't document an unnamed opaque type
+// @!has async_fn_opaque_item/opaque..html
+
+// Checking there is only a "Functions" header and no "Opaque types".
+// @has async_fn_opaque_item/index.html
+// @count - '//*[@class="small-section-header"]' 1
+// @has - '//*[@class="small-section-header"]' 'Functions'
+
+pub async fn test() {}
diff --git a/tests/rustdoc/async-fn.rs b/tests/rustdoc/async-fn.rs
index fb7ebb5f8..70bcbcb6f 100644
--- a/tests/rustdoc/async-fn.rs
+++ b/tests/rustdoc/async-fn.rs
@@ -1,35 +1,35 @@
// edition:2018
-// @has async_fn/fn.foo.html '//div[@class="item-decl"]/pre[@class="rust"]' 'pub async fn foo() -> Option<Foo>'
+// @has async_fn/fn.foo.html '//pre[@class="rust item-decl"]' 'pub async fn foo() -> Option<Foo>'
pub async fn foo() -> Option<Foo> {
None
}
-// @has async_fn/fn.bar.html '//div[@class="item-decl"]/pre[@class="rust"]' 'pub async fn bar(a: i32, b: i32) -> i32'
+// @has async_fn/fn.bar.html '//pre[@class="rust item-decl"]' 'pub async fn bar(a: i32, b: i32) -> i32'
pub async fn bar(a: i32, b: i32) -> i32 {
0
}
-// @has async_fn/fn.baz.html '//div[@class="item-decl"]/pre[@class="rust"]' 'pub async fn baz<T>(a: T) -> T'
+// @has async_fn/fn.baz.html '//pre[@class="rust item-decl"]' 'pub async fn baz<T>(a: T) -> T'
pub async fn baz<T>(a: T) -> T {
a
}
-// @has async_fn/fn.qux.html '//div[@class="item-decl"]/pre[@class="rust"]' 'pub async unsafe fn qux() -> char'
+// @has async_fn/fn.qux.html '//pre[@class="rust item-decl"]' 'pub async unsafe fn qux() -> char'
pub async unsafe fn qux() -> char {
'⚠'
}
-// @has async_fn/fn.mut_args.html '//div[@class="item-decl"]/pre[@class="rust"]' 'pub async fn mut_args(a: usize)'
+// @has async_fn/fn.mut_args.html '//pre[@class="rust item-decl"]' 'pub async fn mut_args(a: usize)'
pub async fn mut_args(mut a: usize) {}
-// @has async_fn/fn.mut_ref.html '//div[@class="item-decl"]/pre[@class="rust"]' 'pub async fn mut_ref(x: i32)'
+// @has async_fn/fn.mut_ref.html '//pre[@class="rust item-decl"]' 'pub async fn mut_ref(x: i32)'
pub async fn mut_ref(ref mut x: i32) {}
trait Bar {}
impl Bar for () {}
-// @has async_fn/fn.quux.html '//div[@class="item-decl"]/pre[@class="rust"]' 'pub async fn quux() -> impl Bar'
+// @has async_fn/fn.quux.html '//pre[@class="rust item-decl"]' 'pub async fn quux() -> impl Bar'
pub async fn quux() -> impl Bar {
()
}
@@ -50,46 +50,46 @@ pub trait Pattern<'a> {}
pub trait Trait<const N: usize> {}
// @has async_fn/fn.const_generics.html
-// @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'pub async fn const_generics<const N: usize>(_: impl Trait<N>)'
+// @has - '//pre[@class="rust item-decl"]' 'pub async fn const_generics<const N: usize>(_: impl Trait<N>)'
pub async fn const_generics<const N: usize>(_: impl Trait<N>) {}
// test that elided lifetimes are properly elided and not displayed as `'_`
// regression test for #63037
// @has async_fn/fn.elided.html
-// @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'pub async fn elided(foo: &str) -> &str'
+// @has - '//pre[@class="rust item-decl"]' 'pub async fn elided(foo: &str) -> &str'
pub async fn elided(foo: &str) -> &str {}
// This should really be shown as written, but for implementation reasons it's difficult.
// See `impl Clean for TyKind::Ref`.
// @has async_fn/fn.user_elided.html
-// @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'pub async fn user_elided(foo: &str) -> &str'
+// @has - '//pre[@class="rust item-decl"]' 'pub async fn user_elided(foo: &str) -> &str'
pub async fn user_elided(foo: &'_ str) -> &str {}
// @has async_fn/fn.static_trait.html
-// @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'pub async fn static_trait(foo: &str) -> Box<dyn Bar>'
+// @has - '//pre[@class="rust item-decl"]' 'pub async fn static_trait(foo: &str) -> Box<dyn Bar>'
pub async fn static_trait(foo: &str) -> Box<dyn Bar> {}
// @has async_fn/fn.lifetime_for_trait.html
-// @has - '//div[@class="item-decl"]/pre[@class="rust"]' "pub async fn lifetime_for_trait(foo: &str) -> Box<dyn Bar + '_>"
+// @has - '//pre[@class="rust item-decl"]' "pub async fn lifetime_for_trait(foo: &str) -> Box<dyn Bar + '_>"
pub async fn lifetime_for_trait(foo: &str) -> Box<dyn Bar + '_> {}
// @has async_fn/fn.elided_in_input_trait.html
-// @has - '//div[@class="item-decl"]/pre[@class="rust"]' "pub async fn elided_in_input_trait(t: impl Pattern<'_>)"
+// @has - '//pre[@class="rust item-decl"]' "pub async fn elided_in_input_trait(t: impl Pattern<'_>)"
pub async fn elided_in_input_trait(t: impl Pattern<'_>) {}
struct AsyncFdReadyGuard<'a, T> { x: &'a T }
impl Foo {
// @has async_fn/struct.Foo.html
- // @has - '//*[@class="method has-srclink"]' 'pub async fn complicated_lifetimes( &self, context: &impl Bar) -> impl Iterator<Item = &usize>'
+ // @has - '//*[@class="method"]' 'pub async fn complicated_lifetimes( &self, context: &impl Bar ) -> impl Iterator<Item = &usize>'
pub async fn complicated_lifetimes(&self, context: &impl Bar) -> impl Iterator<Item = &usize> {}
// taken from `tokio` as an example of a method that was particularly bad before
- // @has - '//*[@class="method has-srclink"]' "pub async fn readable<T>(&self) -> Result<AsyncFdReadyGuard<'_, T>, ()>"
+ // @has - '//*[@class="method"]' "pub async fn readable<T>(&self) -> Result<AsyncFdReadyGuard<'_, T>, ()>"
pub async fn readable<T>(&self) -> Result<AsyncFdReadyGuard<'_, T>, ()> {}
- // @has - '//*[@class="method has-srclink"]' "pub async fn mut_self(&mut self)"
+ // @has - '//*[@class="method"]' "pub async fn mut_self(&mut self)"
pub async fn mut_self(&mut self) {}
}
// test named lifetimes, just in case
// @has async_fn/fn.named.html
-// @has - '//div[@class="item-decl"]/pre[@class="rust"]' "pub async fn named<'a, 'b>(foo: &'a str) -> &'b str"
+// @has - '//pre[@class="rust item-decl"]' "pub async fn named<'a, 'b>(foo: &'a str) -> &'b str"
pub async fn named<'a, 'b>(foo: &'a str) -> &'b str {}
// @has async_fn/fn.named_trait.html
-// @has - '//div[@class="item-decl"]/pre[@class="rust"]' "pub async fn named_trait<'a, 'b>(foo: impl Pattern<'a>) -> impl Pattern<'b>"
+// @has - '//pre[@class="rust item-decl"]' "pub async fn named_trait<'a, 'b>(foo: impl Pattern<'a>) -> impl Pattern<'b>"
pub async fn named_trait<'a, 'b>(foo: impl Pattern<'a>) -> impl Pattern<'b> {}
diff --git a/tests/rustdoc/attribute-rendering.rs b/tests/rustdoc/attribute-rendering.rs
index 36e10923c..a652fda16 100644
--- a/tests/rustdoc/attribute-rendering.rs
+++ b/tests/rustdoc/attribute-rendering.rs
@@ -1,7 +1,7 @@
#![crate_name = "foo"]
// @has 'foo/fn.f.html'
-// @has - //*[@'class="item-decl"]' '#[export_name = "f"] pub fn f()'
+// @has - //*[@'class="rust item-decl"]' '#[export_name = "f"] pub fn f()'
#[export_name = "\
f"]
pub fn f() {}
diff --git a/tests/rustdoc/attributes.rs b/tests/rustdoc/attributes.rs
index 70e2e5c29..86333c753 100644
--- a/tests/rustdoc/attributes.rs
+++ b/tests/rustdoc/attributes.rs
@@ -1,13 +1,13 @@
#![crate_name = "foo"]
-// @has foo/fn.f.html '//div[@class="item-decl"]/pre[@class="rust"]' '#[no_mangle]'
+// @has foo/fn.f.html '//pre[@class="rust item-decl"]' '#[no_mangle]'
#[no_mangle]
pub extern "C" fn f() {}
-// @has foo/fn.g.html '//div[@class="item-decl"]/pre[@class="rust"]' '#[export_name = "bar"]'
+// @has foo/fn.g.html '//pre[@class="rust item-decl"]' '#[export_name = "bar"]'
#[export_name = "bar"]
pub extern "C" fn g() {}
-// @has foo/struct.Repr.html '//div[@class="item-decl"]' '#[repr(C, align(8))]'
+// @has foo/struct.Repr.html '//pre[@class="rust item-decl"]' '#[repr(C, align(8))]'
#[repr(C, align(8))]
pub struct Repr;
diff --git a/tests/rustdoc/auxiliary/inline-default-methods.rs b/tests/rustdoc/auxiliary/inline-default-methods.rs
index 8a636f449..f06a20b27 100644
--- a/tests/rustdoc/auxiliary/inline-default-methods.rs
+++ b/tests/rustdoc/auxiliary/inline-default-methods.rs
@@ -4,3 +4,15 @@ pub trait Foo {
fn bar(&self);
fn foo(&mut self) {}
}
+
+pub trait Bar {
+ fn bar(&self);
+ fn foo1(&mut self) {}
+ fn foo2(&mut self) {}
+}
+
+pub trait Baz {
+ fn bar1(&self);
+ fn bar2(&self);
+ fn foo(&mut self) {}
+}
diff --git a/tests/rustdoc/auxiliary/issue-85454.rs b/tests/rustdoc/auxiliary/issue-85454.rs
index 5143968bb..5db4fe053 100644
--- a/tests/rustdoc/auxiliary/issue-85454.rs
+++ b/tests/rustdoc/auxiliary/issue-85454.rs
@@ -1,5 +1,5 @@
// @has issue_85454/trait.FromResidual.html
-// @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'pub trait FromResidual<R = <Self as Try>::Residual> { fn from_residual(residual: R) -> Self; }'
+// @has - '//pre[@class="rust item-decl"]' 'pub trait FromResidual<R = <Self as Try>::Residual> { fn from_residual(residual: R) -> Self; }'
pub trait FromResidual<R = <Self as Try>::Residual> {
fn from_residual(residual: R) -> Self;
}
diff --git a/tests/rustdoc/cfg_doc_reexport.rs b/tests/rustdoc/cfg_doc_reexport.rs
index addb6709d..a10c84f2c 100644
--- a/tests/rustdoc/cfg_doc_reexport.rs
+++ b/tests/rustdoc/cfg_doc_reexport.rs
@@ -5,8 +5,8 @@
#![no_core]
// @has 'foo/index.html'
-// @has - '//*[@class="item-left module-item"]/*[@class="stab portability"]' 'foobar'
-// @has - '//*[@class="item-left module-item"]/*[@class="stab portability"]' 'bar'
+// @has - '//*[@class="item-name"]/*[@class="stab portability"]' 'foobar'
+// @has - '//*[@class="item-name"]/*[@class="stab portability"]' 'bar'
#[doc(cfg(feature = "foobar"))]
mod imp_priv {
diff --git a/tests/rustdoc/codeblock-title.rs b/tests/rustdoc/codeblock-title.rs
index b9b0b0d1a..761afb8bd 100644
--- a/tests/rustdoc/codeblock-title.rs
+++ b/tests/rustdoc/codeblock-title.rs
@@ -3,7 +3,7 @@
// @has foo/fn.bar.html '//*[@class="example-wrap compile_fail"]/*[@class="tooltip"]' "ⓘ"
// @has foo/fn.bar.html '//*[@class="example-wrap ignore"]/*[@class="tooltip"]' "ⓘ"
// @has foo/fn.bar.html '//*[@class="example-wrap should_panic"]/*[@class="tooltip"]' "ⓘ"
-// @has foo/fn.bar.html '//*[@data-edition="2018"]' "ⓘ"
+// @has foo/fn.bar.html '//*[@title="This example runs with edition 2018"]' "ⓘ"
/// foo
///
diff --git a/tests/rustdoc/const-fn.rs b/tests/rustdoc/const-fn.rs
index 4366ad4d0..f66161856 100644
--- a/tests/rustdoc/const-fn.rs
+++ b/tests/rustdoc/const-fn.rs
@@ -1,14 +1,14 @@
#![crate_name = "foo"]
// @has foo/fn.bar.html
-// @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'pub const fn bar() -> '
+// @has - '//pre[@class="rust item-decl"]' 'pub const fn bar() -> '
/// foo
pub const fn bar() -> usize {
2
}
// @has foo/struct.Foo.html
-// @has - '//*[@class="method has-srclink"]' 'const fn new()'
+// @has - '//*[@class="method"]' 'const fn new()'
pub struct Foo(usize);
impl Foo {
diff --git a/tests/rustdoc/const-generics/add-impl.rs b/tests/rustdoc/const-generics/add-impl.rs
index b5226ad3f..195e47bc8 100644
--- a/tests/rustdoc/const-generics/add-impl.rs
+++ b/tests/rustdoc/const-generics/add-impl.rs
@@ -2,7 +2,7 @@
use std::ops::Add;
-// @has foo/struct.Simd.html '//div[@class="item-decl"]/pre[@class="rust"]' 'pub struct Simd<T, const WIDTH: usize>'
+// @has foo/struct.Simd.html '//pre[@class="rust item-decl"]' 'pub struct Simd<T, const WIDTH: usize>'
pub struct Simd<T, const WIDTH: usize> {
inner: T,
}
diff --git a/tests/rustdoc/const-generics/const-generic-defaults.rs b/tests/rustdoc/const-generics/const-generic-defaults.rs
index acc3b853e..f781c6a62 100644
--- a/tests/rustdoc/const-generics/const-generic-defaults.rs
+++ b/tests/rustdoc/const-generics/const-generic-defaults.rs
@@ -1,5 +1,5 @@
#![crate_name = "foo"]
-// @has foo/struct.Foo.html '//div[@class="item-decl"]/pre[@class="rust"]' \
+// @has foo/struct.Foo.html '//pre[@class="rust item-decl"]' \
// 'pub struct Foo<const M: usize = 10, const N: usize = M, T = i32>(_);'
pub struct Foo<const M: usize = 10, const N: usize = M, T = i32>(T);
diff --git a/tests/rustdoc/const-generics/const-generic-slice.rs b/tests/rustdoc/const-generics/const-generic-slice.rs
index 4279de91f..80a9ab3f1 100644
--- a/tests/rustdoc/const-generics/const-generic-slice.rs
+++ b/tests/rustdoc/const-generics/const-generic-slice.rs
@@ -5,7 +5,7 @@ pub trait Array {
}
// @has foo/trait.Array.html
-// @has - '//*[@class="impl has-srclink"]' 'impl<T, const N: usize> Array for [T; N]'
+// @has - '//*[@class="impl"]' 'impl<T, const N: usize> Array for [T; N]'
impl<T, const N: usize> Array for [T; N] {
type Item = T;
}
diff --git a/tests/rustdoc/const-generics/const-generics-docs.rs b/tests/rustdoc/const-generics/const-generics-docs.rs
index 543332d2c..828486a41 100644
--- a/tests/rustdoc/const-generics/const-generics-docs.rs
+++ b/tests/rustdoc/const-generics/const-generics-docs.rs
@@ -3,26 +3,26 @@
#![crate_name = "foo"]
extern crate extern_crate;
-// @has foo/fn.extern_fn.html '//div[@class="item-decl"]/pre[@class="rust"]' \
+// @has foo/fn.extern_fn.html '//pre[@class="rust item-decl"]' \
// 'pub fn extern_fn<const N: usize>() -> impl Iterator<Item = [u8; N]>'
pub use extern_crate::extern_fn;
-// @has foo/struct.ExternTy.html '//div[@class="item-decl"]/pre[@class="rust"]' \
+// @has foo/struct.ExternTy.html '//pre[@class="rust item-decl"]' \
// 'pub struct ExternTy<const N: usize> {'
pub use extern_crate::ExternTy;
-// @has foo/type.TyAlias.html '//div[@class="item-decl"]/pre[@class="rust"]' \
+// @has foo/type.TyAlias.html '//pre[@class="rust item-decl"]' \
// 'type TyAlias<const N: usize> = ExternTy<N>;'
pub use extern_crate::TyAlias;
-// @has foo/trait.WTrait.html '//div[@class="item-decl"]/pre[@class="rust"]' \
+// @has foo/trait.WTrait.html '//pre[@class="rust item-decl"]' \
// 'pub trait WTrait<const N: usize, const M: usize>'
-// @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'fn hey<const P: usize>() -> usize'
+// @has - '//pre[@class="rust item-decl"]' 'fn hey<const P: usize>() -> usize'
pub use extern_crate::WTrait;
-// @has foo/trait.Trait.html '//div[@class="item-decl"]/pre[@class="rust"]' \
+// @has foo/trait.Trait.html '//pre[@class="rust item-decl"]' \
// 'pub trait Trait<const N: usize>'
// @has - '//*[@id="impl-Trait%3C1%3E-for-u8"]//h3[@class="code-header"]' 'impl Trait<1> for u8'
// @has - '//*[@id="impl-Trait%3C2%3E-for-u8"]//h3[@class="code-header"]' 'impl Trait<2> for u8'
-// @has - '//*[@id="impl-Trait%3C{1%20+%202}%3E-for-u8"]//h3[@class="code-header"]' 'impl Trait<{1 + 2}> for u8'
-// @has - '//*[@id="impl-Trait%3CN%3E-for-%5Bu8%3B%20N%5D"]//h3[@class="code-header"]' \
+// @has - '//*[@id="impl-Trait%3C%7B1+%2B+2%7D%3E-for-u8"]//h3[@class="code-header"]' 'impl Trait<{1 + 2}> for u8'
+// @has - '//*[@id="impl-Trait%3CN%3E-for-%5Bu8;+N%5D"]//h3[@class="code-header"]' \
// 'impl<const N: usize> Trait<N> for [u8; N]'
pub trait Trait<const N: usize> {}
impl Trait<1> for u8 {}
@@ -30,10 +30,10 @@ impl Trait<2> for u8 {}
impl Trait<{1 + 2}> for u8 {}
impl<const N: usize> Trait<N> for [u8; N] {}
-// @has foo/struct.Foo.html '//div[@class="item-decl"]/pre[@class="rust"]' \
-// 'pub struct Foo<const N: usize>where u8: Trait<N>'
+// @has foo/struct.Foo.html '//pre[@class="rust item-decl"]' \
+// 'pub struct Foo<const N: usize> where u8: Trait<N>'
pub struct Foo<const N: usize> where u8: Trait<N>;
-// @has foo/struct.Bar.html '//div[@class="item-decl"]/pre[@class="rust"]' 'pub struct Bar<T, const N: usize>(_)'
+// @has foo/struct.Bar.html '//pre[@class="rust item-decl"]' 'pub struct Bar<T, const N: usize>(_)'
pub struct Bar<T, const N: usize>([T; N]);
// @has foo/struct.Foo.html '//*[@id="impl-Foo%3CM%3E"]/h3[@class="code-header"]' 'impl<const M: usize> Foo<M>where u8: Trait<M>'
@@ -47,7 +47,7 @@ impl<const M: usize> Foo<M> where u8: Trait<M> {
}
}
-// @has foo/struct.Bar.html '//*[@id="impl-Bar%3Cu8%2C%20M%3E"]/h3[@class="code-header"]' 'impl<const M: usize> Bar<u8, M>'
+// @has foo/struct.Bar.html '//*[@id="impl-Bar%3Cu8,+M%3E"]/h3[@class="code-header"]' 'impl<const M: usize> Bar<u8, M>'
impl<const M: usize> Bar<u8, M> {
// @has - '//*[@id="method.hey"]' \
// 'pub fn hey<const N: usize>(&self) -> Foo<N>where u8: Trait<N>'
@@ -56,32 +56,32 @@ impl<const M: usize> Bar<u8, M> {
}
}
-// @has foo/fn.test.html '//div[@class="item-decl"]/pre[@class="rust"]' \
+// @has foo/fn.test.html '//pre[@class="rust item-decl"]' \
// 'pub fn test<const N: usize>() -> impl Trait<N>where u8: Trait<N>'
pub fn test<const N: usize>() -> impl Trait<N> where u8: Trait<N> {
2u8
}
-// @has foo/fn.a_sink.html '//div[@class="item-decl"]/pre[@class="rust"]' \
+// @has foo/fn.a_sink.html '//pre[@class="rust item-decl"]' \
// 'pub async fn a_sink<const N: usize>(v: [u8; N]) -> impl Trait<N>'
pub async fn a_sink<const N: usize>(v: [u8; N]) -> impl Trait<N> {
v
}
-// @has foo/fn.b_sink.html '//div[@class="item-decl"]/pre[@class="rust"]' \
+// @has foo/fn.b_sink.html '//pre[@class="rust item-decl"]' \
// 'pub async fn b_sink<const N: usize>(_: impl Trait<N>)'
pub async fn b_sink<const N: usize>(_: impl Trait<N>) {}
-// @has foo/fn.concrete.html '//div[@class="item-decl"]/pre[@class="rust"]' \
+// @has foo/fn.concrete.html '//pre[@class="rust item-decl"]' \
// 'pub fn concrete() -> [u8; 22]'
pub fn concrete() -> [u8; 3 + std::mem::size_of::<u64>() << 1] {
Default::default()
}
-// @has foo/type.Faz.html '//div[@class="item-decl"]/pre[@class="rust"]' \
+// @has foo/type.Faz.html '//pre[@class="rust item-decl"]' \
// 'type Faz<const N: usize> = [u8; N];'
pub type Faz<const N: usize> = [u8; N];
-// @has foo/type.Fiz.html '//div[@class="item-decl"]/pre[@class="rust"]' \
+// @has foo/type.Fiz.html '//pre[@class="rust item-decl"]' \
// 'type Fiz<const N: usize> = [[u8; N]; 48];'
pub type Fiz<const N: usize> = [[u8; N]; 3 << 4];
@@ -91,7 +91,7 @@ macro_rules! define_me {
}
}
-// @has foo/struct.Foz.html '//div[@class="item-decl"]/pre[@class="rust"]' \
+// @has foo/struct.Foz.html '//pre[@class="rust item-decl"]' \
// 'pub struct Foz<const N: usize>(_);'
define_me!(Foz<N>);
@@ -103,13 +103,13 @@ impl<const N: usize> Q for [u8; N] {
const ASSOC: usize = N;
}
-// @has foo/fn.q_user.html '//div[@class="item-decl"]/pre[@class="rust"]' \
+// @has foo/fn.q_user.html '//pre[@class="rust item-decl"]' \
// 'pub fn q_user() -> [u8; 13]'
pub fn q_user() -> [u8; <[u8; 13] as Q>::ASSOC] {
[0; <[u8; 13] as Q>::ASSOC]
}
-// @has foo/union.Union.html '//div[@class="item-decl"]/pre[@class="rust"]' \
+// @has foo/union.Union.html '//pre[@class="rust item-decl"]' \
// 'pub union Union<const N: usize>'
pub union Union<const N: usize> {
// @has - //pre "pub arr: [u8; N]"
@@ -118,7 +118,7 @@ pub union Union<const N: usize> {
pub another_arr: [(); N],
}
-// @has foo/enum.Enum.html '//div[@class="item-decl"]/pre[@class="rust"]' \
+// @has foo/enum.Enum.html '//pre[@class="rust item-decl"]' \
// 'pub enum Enum<const N: usize>'
pub enum Enum<const N: usize> {
// @has - //pre "Variant([u8; N])"
diff --git a/tests/rustdoc/const-generics/const-impl.rs b/tests/rustdoc/const-generics/const-impl.rs
index 726fb8f0c..152b643bf 100644
--- a/tests/rustdoc/const-generics/const-impl.rs
+++ b/tests/rustdoc/const-generics/const-impl.rs
@@ -8,21 +8,21 @@ pub enum Order {
Unsorted,
}
-// @has foo/struct.VSet.html '//div[@class="item-decl"]/pre[@class="rust"]' 'pub struct VSet<T, const ORDER: Order>'
-// @has foo/struct.VSet.html '//*[@id="impl-Send-for-VSet%3CT%2C%20ORDER%3E"]/h3[@class="code-header"]' 'impl<T, const ORDER: Order> Send for VSet<T, ORDER>'
-// @has foo/struct.VSet.html '//*[@id="impl-Sync-for-VSet%3CT%2C%20ORDER%3E"]/h3[@class="code-header"]' 'impl<T, const ORDER: Order> Sync for VSet<T, ORDER>'
+// @has foo/struct.VSet.html '//pre[@class="rust item-decl"]' 'pub struct VSet<T, const ORDER: Order>'
+// @has foo/struct.VSet.html '//*[@id="impl-Send-for-VSet%3CT,+ORDER%3E"]/h3[@class="code-header"]' 'impl<T, const ORDER: Order> Send for VSet<T, ORDER>'
+// @has foo/struct.VSet.html '//*[@id="impl-Sync-for-VSet%3CT,+ORDER%3E"]/h3[@class="code-header"]' 'impl<T, const ORDER: Order> Sync for VSet<T, ORDER>'
pub struct VSet<T, const ORDER: Order> {
inner: Vec<T>,
}
-// @has foo/struct.VSet.html '//*[@id="impl-VSet%3CT%2C%20{%20Order%3A%3ASorted%20}%3E"]/h3[@class="code-header"]' 'impl<T> VSet<T, { Order::Sorted }>'
+// @has foo/struct.VSet.html '//*[@id="impl-VSet%3CT,+%7B+Order::Sorted+%7D%3E"]/h3[@class="code-header"]' 'impl<T> VSet<T, { Order::Sorted }>'
impl<T> VSet<T, { Order::Sorted }> {
pub fn new() -> Self {
Self { inner: Vec::new() }
}
}
-// @has foo/struct.VSet.html '//*[@id="impl-VSet%3CT%2C%20{%20Order%3A%3AUnsorted%20}%3E"]/h3[@class="code-header"]' 'impl<T> VSet<T, { Order::Unsorted }>'
+// @has foo/struct.VSet.html '//*[@id="impl-VSet%3CT,+%7B+Order::Unsorted+%7D%3E"]/h3[@class="code-header"]' 'impl<T> VSet<T, { Order::Unsorted }>'
impl<T> VSet<T, { Order::Unsorted }> {
pub fn new() -> Self {
Self { inner: Vec::new() }
@@ -31,7 +31,7 @@ impl<T> VSet<T, { Order::Unsorted }> {
pub struct Escape<const S: &'static str>;
-// @has foo/struct.Escape.html '//*[@id="impl-Escape%3Cr#%22%3Cscript%3Ealert(%22Escape%22)%3B%3C/script%3E%22#%3E"]/h3[@class="code-header"]' 'impl Escape<r#"<script>alert("Escape");</script>"#>'
+// @has foo/struct.Escape.html '//*[@id="impl-Escape%3Cr%23%22%3Cscript%3Ealert(%22Escape%22);%3C/script%3E%22%23%3E"]/h3[@class="code-header"]' 'impl Escape<r#"<script>alert("Escape");</script>"#>'
impl Escape<r#"<script>alert("Escape");</script>"#> {
pub fn f() {}
}
diff --git a/tests/rustdoc/const-generics/generic_const_exprs.rs b/tests/rustdoc/const-generics/generic_const_exprs.rs
index c53cf6dcd..e23b3006d 100644
--- a/tests/rustdoc/const-generics/generic_const_exprs.rs
+++ b/tests/rustdoc/const-generics/generic_const_exprs.rs
@@ -2,6 +2,6 @@
#![feature(generic_const_exprs)]
#![allow(incomplete_features)]
// make sure that `ConstEvaluatable` predicates dont cause rustdoc to ICE #77647
-// @has foo/struct.Ice.html '//div[@class="item-decl"]/pre[@class="rust"]' \
+// @has foo/struct.Ice.html '//pre[@class="rust item-decl"]' \
// 'pub struct Ice<const N: usize>;'
pub struct Ice<const N: usize> where [(); N + 1]:;
diff --git a/tests/rustdoc/const-generics/type-alias.rs b/tests/rustdoc/const-generics/type-alias.rs
index 72473a112..4b93e72d2 100644
--- a/tests/rustdoc/const-generics/type-alias.rs
+++ b/tests/rustdoc/const-generics/type-alias.rs
@@ -1,4 +1,4 @@
#![crate_name = "foo"]
-// @has foo/type.CellIndex.html '//div[@class="item-decl"]/pre[@class="rust"]' 'type CellIndex<const D: usize> = [i64; D];'
+// @has foo/type.CellIndex.html '//pre[@class="rust item-decl"]' 'type CellIndex<const D: usize> = [i64; D];'
pub type CellIndex<const D: usize> = [i64; D];
diff --git a/tests/rustdoc/const-intrinsic.rs b/tests/rustdoc/const-intrinsic.rs
index 42f6ac792..6d2c6cce2 100644
--- a/tests/rustdoc/const-intrinsic.rs
+++ b/tests/rustdoc/const-intrinsic.rs
@@ -6,20 +6,20 @@
extern "rust-intrinsic" {
// @has 'foo/fn.transmute.html'
- // @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'pub const unsafe extern "rust-intrinsic" fn transmute<T, U>(_: T) -> U'
+ // @has - '//pre[@class="rust item-decl"]' 'pub const unsafe extern "rust-intrinsic" fn transmute<T, U>(_: T) -> U'
#[stable(since="1.0.0", feature="rust1")]
#[rustc_const_stable(feature = "const_transmute", since = "1.56.0")]
pub fn transmute<T, U>(_: T) -> U;
// @has 'foo/fn.unreachable.html'
- // @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'pub unsafe extern "rust-intrinsic" fn unreachable() -> !'
+ // @has - '//pre[@class="rust item-decl"]' 'pub unsafe extern "rust-intrinsic" fn unreachable() -> !'
#[stable(since="1.0.0", feature="rust1")]
pub fn unreachable() -> !;
}
extern "C" {
// @has 'foo/fn.needs_drop.html'
- // @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'pub unsafe extern "C" fn needs_drop() -> !'
+ // @has - '//pre[@class="rust item-decl"]' 'pub unsafe extern "C" fn needs_drop() -> !'
#[stable(since="1.0.0", feature="rust1")]
pub fn needs_drop() -> !;
}
diff --git a/tests/rustdoc/const-value-display.rs b/tests/rustdoc/const-value-display.rs
index 8d95f0de9..a7548ad2c 100644
--- a/tests/rustdoc/const-value-display.rs
+++ b/tests/rustdoc/const-value-display.rs
@@ -1,9 +1,9 @@
#![crate_name = "foo"]
// @has 'foo/constant.HOUR_IN_SECONDS.html'
-// @has - '//*[@class="item-decl"]//code' 'pub const HOUR_IN_SECONDS: u64 = _; // 3_600u64'
+// @has - '//*[@class="rust item-decl"]//code' 'pub const HOUR_IN_SECONDS: u64 = _; // 3_600u64'
pub const HOUR_IN_SECONDS: u64 = 60 * 60;
// @has 'foo/constant.NEGATIVE.html'
-// @has - '//*[@class="item-decl"]//code' 'pub const NEGATIVE: i64 = _; // -3_600i64'
+// @has - '//*[@class="rust item-decl"]//code' 'pub const NEGATIVE: i64 = _; // -3_600i64'
pub const NEGATIVE: i64 = -60 * 60;
diff --git a/tests/rustdoc/decl-trailing-whitespace.declaration.html b/tests/rustdoc/decl-trailing-whitespace.declaration.html
index 02b51b344..d73393633 100644
--- a/tests/rustdoc/decl-trailing-whitespace.declaration.html
+++ b/tests/rustdoc/decl-trailing-whitespace.declaration.html
@@ -1,7 +1,23 @@
<code>pub trait Write {
- fn <a href="#tymethod.poll_write" class="fn">poll_write</a>(<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;self: <a class="enum" href="{{channel}}/core/option/enum.Option.html" title="enum core::option::Option">Option</a>&lt;<a class="struct" href="{{channel}}/alloc/string/struct.String.html" title="struct alloc::string::String">String</a>&gt;,<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;cx: &amp;mut <a class="enum" href="{{channel}}/core/option/enum.Option.html" title="enum core::option::Option">Option</a>&lt;<a class="struct" href="{{channel}}/alloc/string/struct.String.html" title="struct alloc::string::String">String</a>&gt;,<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;buf: &amp;mut [<a class="primitive" href="{{channel}}/std/primitive.usize.html">usize</a>]<br />&#160;&#160;&#160;&#160;) -&gt; <a class="enum" href="{{channel}}/core/option/enum.Option.html" title="enum core::option::Option">Option</a>&lt;<a class="enum" href="{{channel}}/core/result/enum.Result.html" title="enum core::result::Result">Result</a>&lt;<a class="primitive" href="{{channel}}/std/primitive.usize.html">usize</a>, <a class="struct" href="struct.Error.html" title="struct foo::Error">Error</a>&gt;&gt;;
-<span class="item-spacer" /> fn <a href="#tymethod.poll_flush" class="fn">poll_flush</a>(<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;self: <a class="enum" href="{{channel}}/core/option/enum.Option.html" title="enum core::option::Option">Option</a>&lt;<a class="struct" href="{{channel}}/alloc/string/struct.String.html" title="struct alloc::string::String">String</a>&gt;,<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;cx: &amp;mut <a class="enum" href="{{channel}}/core/option/enum.Option.html" title="enum core::option::Option">Option</a>&lt;<a class="struct" href="{{channel}}/alloc/string/struct.String.html" title="struct alloc::string::String">String</a>&gt;<br />&#160;&#160;&#160;&#160;) -&gt; <a class="enum" href="{{channel}}/core/option/enum.Option.html" title="enum core::option::Option">Option</a>&lt;<a class="enum" href="{{channel}}/core/result/enum.Result.html" title="enum core::result::Result">Result</a>&lt;<a class="primitive" href="{{channel}}/std/primitive.unit.html">()</a>, <a class="struct" href="struct.Error.html" title="struct foo::Error">Error</a>&gt;&gt;;
-<span class="item-spacer" /> fn <a href="#tymethod.poll_close" class="fn">poll_close</a>(<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;self: <a class="enum" href="{{channel}}/core/option/enum.Option.html" title="enum core::option::Option">Option</a>&lt;<a class="struct" href="{{channel}}/alloc/string/struct.String.html" title="struct alloc::string::String">String</a>&gt;,<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;cx: &amp;mut <a class="enum" href="{{channel}}/core/option/enum.Option.html" title="enum core::option::Option">Option</a>&lt;<a class="struct" href="{{channel}}/alloc/string/struct.String.html" title="struct alloc::string::String">String</a>&gt;<br />&#160;&#160;&#160;&#160;) -&gt; <a class="enum" href="{{channel}}/core/option/enum.Option.html" title="enum core::option::Option">Option</a>&lt;<a class="enum" href="{{channel}}/core/result/enum.Result.html" title="enum core::result::Result">Result</a>&lt;<a class="primitive" href="{{channel}}/std/primitive.unit.html">()</a>, <a class="struct" href="struct.Error.html" title="struct foo::Error">Error</a>&gt;&gt;;
+ // Required methods
+ fn <a href="#tymethod.poll_write" class="fn">poll_write</a>(
+ self: <a class="enum" href="{{channel}}/core/option/enum.Option.html" title="enum core::option::Option">Option</a>&lt;<a class="struct" href="{{channel}}/alloc/string/struct.String.html" title="struct alloc::string::String">String</a>&gt;,
+ cx: &amp;mut <a class="enum" href="{{channel}}/core/option/enum.Option.html" title="enum core::option::Option">Option</a>&lt;<a class="struct" href="{{channel}}/alloc/string/struct.String.html" title="struct alloc::string::String">String</a>&gt;,
+ buf: &amp;mut [<a class="primitive" href="{{channel}}/std/primitive.usize.html">usize</a>]
+ ) -&gt; <a class="enum" href="{{channel}}/core/option/enum.Option.html" title="enum core::option::Option">Option</a>&lt;<a class="enum" href="{{channel}}/core/result/enum.Result.html" title="enum core::result::Result">Result</a>&lt;<a class="primitive" href="{{channel}}/std/primitive.usize.html">usize</a>, <a class="struct" href="struct.Error.html" title="struct foo::Error">Error</a>&gt;&gt;;
+<span class="item-spacer" /> fn <a href="#tymethod.poll_flush" class="fn">poll_flush</a>(
+ self: <a class="enum" href="{{channel}}/core/option/enum.Option.html" title="enum core::option::Option">Option</a>&lt;<a class="struct" href="{{channel}}/alloc/string/struct.String.html" title="struct alloc::string::String">String</a>&gt;,
+ cx: &amp;mut <a class="enum" href="{{channel}}/core/option/enum.Option.html" title="enum core::option::Option">Option</a>&lt;<a class="struct" href="{{channel}}/alloc/string/struct.String.html" title="struct alloc::string::String">String</a>&gt;
+ ) -&gt; <a class="enum" href="{{channel}}/core/option/enum.Option.html" title="enum core::option::Option">Option</a>&lt;<a class="enum" href="{{channel}}/core/result/enum.Result.html" title="enum core::result::Result">Result</a>&lt;<a class="primitive" href="{{channel}}/std/primitive.unit.html">()</a>, <a class="struct" href="struct.Error.html" title="struct foo::Error">Error</a>&gt;&gt;;
+<span class="item-spacer" /> fn <a href="#tymethod.poll_close" class="fn">poll_close</a>(
+ self: <a class="enum" href="{{channel}}/core/option/enum.Option.html" title="enum core::option::Option">Option</a>&lt;<a class="struct" href="{{channel}}/alloc/string/struct.String.html" title="struct alloc::string::String">String</a>&gt;,
+ cx: &amp;mut <a class="enum" href="{{channel}}/core/option/enum.Option.html" title="enum core::option::Option">Option</a>&lt;<a class="struct" href="{{channel}}/alloc/string/struct.String.html" title="struct alloc::string::String">String</a>&gt;
+ ) -&gt; <a class="enum" href="{{channel}}/core/option/enum.Option.html" title="enum core::option::Option">Option</a>&lt;<a class="enum" href="{{channel}}/core/result/enum.Result.html" title="enum core::result::Result">Result</a>&lt;<a class="primitive" href="{{channel}}/std/primitive.unit.html">()</a>, <a class="struct" href="struct.Error.html" title="struct foo::Error">Error</a>&gt;&gt;;
- fn <a href="#method.poll_write_vectored" class="fn">poll_write_vectored</a>(<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;self: <a class="enum" href="{{channel}}/core/option/enum.Option.html" title="enum core::option::Option">Option</a>&lt;<a class="struct" href="{{channel}}/alloc/string/struct.String.html" title="struct alloc::string::String">String</a>&gt;,<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;cx: &amp;mut <a class="enum" href="{{channel}}/core/option/enum.Option.html" title="enum core::option::Option">Option</a>&lt;<a class="struct" href="{{channel}}/alloc/string/struct.String.html" title="struct alloc::string::String">String</a>&gt;,<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;bufs: &amp;[<a class="primitive" href="{{channel}}/std/primitive.usize.html">usize</a>]<br />&#160;&#160;&#160;&#160;) -&gt; <a class="enum" href="{{channel}}/core/option/enum.Option.html" title="enum core::option::Option">Option</a>&lt;<a class="enum" href="{{channel}}/core/result/enum.Result.html" title="enum core::result::Result">Result</a>&lt;<a class="primitive" href="{{channel}}/std/primitive.usize.html">usize</a>, <a class="struct" href="struct.Error.html" title="struct foo::Error">Error</a>&gt;&gt; { ... }
+ // Provided method
+ fn <a href="#method.poll_write_vectored" class="fn">poll_write_vectored</a>(
+ self: <a class="enum" href="{{channel}}/core/option/enum.Option.html" title="enum core::option::Option">Option</a>&lt;<a class="struct" href="{{channel}}/alloc/string/struct.String.html" title="struct alloc::string::String">String</a>&gt;,
+ cx: &amp;mut <a class="enum" href="{{channel}}/core/option/enum.Option.html" title="enum core::option::Option">Option</a>&lt;<a class="struct" href="{{channel}}/alloc/string/struct.String.html" title="struct alloc::string::String">String</a>&gt;,
+ bufs: &amp;[<a class="primitive" href="{{channel}}/std/primitive.usize.html">usize</a>]
+ ) -&gt; <a class="enum" href="{{channel}}/core/option/enum.Option.html" title="enum core::option::Option">Option</a>&lt;<a class="enum" href="{{channel}}/core/result/enum.Result.html" title="enum core::result::Result">Result</a>&lt;<a class="primitive" href="{{channel}}/std/primitive.usize.html">usize</a>, <a class="struct" href="struct.Error.html" title="struct foo::Error">Error</a>&gt;&gt; { ... }
}</code> \ No newline at end of file
diff --git a/tests/rustdoc/decl-trailing-whitespace.rs b/tests/rustdoc/decl-trailing-whitespace.rs
index e47edc132..d2a12435d 100644
--- a/tests/rustdoc/decl-trailing-whitespace.rs
+++ b/tests/rustdoc/decl-trailing-whitespace.rs
@@ -7,7 +7,7 @@ pub struct Error;
// @has 'foo/trait.Write.html'
pub trait Write {
- // @snapshot 'declaration' - '//*[@class="item-decl"]//code'
+ // @snapshot 'declaration' - '//*[@class="rust item-decl"]//code'
fn poll_write(
self: Option<String>,
cx: &mut Option<String>,
diff --git a/tests/rustdoc/deprecated.rs b/tests/rustdoc/deprecated.rs
index b3178da98..51860441b 100644
--- a/tests/rustdoc/deprecated.rs
+++ b/tests/rustdoc/deprecated.rs
@@ -1,6 +1,6 @@
-// @has deprecated/index.html '//*[@class="item-left module-item"]/span[@class="stab deprecated"]' \
+// @has deprecated/index.html '//*[@class="item-name"]/span[@class="stab deprecated"]' \
// 'Deprecated'
-// @has - '//*[@class="item-right docblock-short"]' 'Deprecated docs'
+// @has - '//*[@class="desc docblock-short"]' 'Deprecated docs'
// @has deprecated/struct.S.html '//*[@class="stab deprecated"]' \
// 'Deprecated since 1.0.0: text'
@@ -8,7 +8,7 @@
#[deprecated(since = "1.0.0", note = "text")]
pub struct S;
-// @matches deprecated/index.html '//*[@class="item-right docblock-short"]' '^Docs'
+// @matches deprecated/index.html '//*[@class="desc docblock-short"]' '^Docs'
/// Docs
pub struct T;
diff --git a/tests/rustdoc/description.rs b/tests/rustdoc/description.rs
index 05ec42822..43cd59ebd 100644
--- a/tests/rustdoc/description.rs
+++ b/tests/rustdoc/description.rs
@@ -22,3 +22,9 @@ pub mod foo_mod {
// 'Only paragraph.'
/// Only paragraph.
pub fn foo_fn() {}
+
+// @has 'foo/fn.bar_fn.html' '//meta[@name="description"]/@content' \
+// 'Description with intra-doc link to foo_fn and [nonexistent_item] and foo_fn.'
+#[allow(rustdoc::broken_intra_doc_links)]
+/// Description with intra-doc link to [foo_fn] and [nonexistent_item] and [foo_fn](self::foo_fn).
+pub fn bar_fn() {}
diff --git a/tests/rustdoc/doc-assoc-item.rs b/tests/rustdoc/doc-assoc-item.rs
index 4f1541865..4d5c9f83e 100644
--- a/tests/rustdoc/doc-assoc-item.rs
+++ b/tests/rustdoc/doc-assoc-item.rs
@@ -8,7 +8,7 @@ pub trait Bar {
fn foo(foo: Self::Fuu);
}
-// @has doc_assoc_item/struct.Foo.html '//*[@class="impl has-srclink"]' 'impl<T: Bar<Fuu = u32>> Foo<T>'
+// @has doc_assoc_item/struct.Foo.html '//*[@class="impl"]' 'impl<T: Bar<Fuu = u32>> Foo<T>'
impl<T: Bar<Fuu = u32>> Foo<T> {
pub fn new(t: T) -> Foo<T> {
Foo {
diff --git a/tests/rustdoc/doc-cfg.rs b/tests/rustdoc/doc-cfg.rs
index 4cddb0b76..c4702d410 100644
--- a/tests/rustdoc/doc-cfg.rs
+++ b/tests/rustdoc/doc-cfg.rs
@@ -12,7 +12,7 @@ pub struct Portable;
// @has doc_cfg/unix_only/index.html \
// '//*[@id="main-content"]/*[@class="item-info"]/*[@class="stab portability"]' \
// 'Available on Unix only.'
-// @matches - '//*[@class="item-left module-item"]//*[@class="stab portability"]' '\AARM\Z'
+// @matches - '//*[@class="item-name"]//*[@class="stab portability"]' '\AARM\Z'
// @count - '//*[@class="stab portability"]' 2
#[doc(cfg(unix))]
pub mod unix_only {
@@ -42,7 +42,7 @@ pub mod unix_only {
// @has doc_cfg/wasi_only/index.html \
// '//*[@id="main-content"]/*[@class="item-info"]/*[@class="stab portability"]' \
// 'Available on WASI only.'
-// @matches - '//*[@class="item-left module-item"]//*[@class="stab portability"]' '\AWebAssembly\Z'
+// @matches - '//*[@class="item-name"]//*[@class="stab portability"]' '\AWebAssembly\Z'
// @count - '//*[@class="stab portability"]' 2
#[doc(cfg(target_os = "wasi"))]
pub mod wasi_only {
@@ -74,7 +74,7 @@ pub mod wasi_only {
// the portability header is different on the module view versus the full view
// @has doc_cfg/index.html
-// @matches - '//*[@class="item-left module-item"]//*[@class="stab portability"]' '\Aavx\Z'
+// @matches - '//*[@class="item-name"]//*[@class="stab portability"]' '\Aavx\Z'
// @has doc_cfg/fn.uses_target_feature.html
// @has - '//*[@id="main-content"]/*[@class="item-info"]/*[@class="stab portability"]' \
diff --git a/tests/rustdoc/doc-notable_trait.rs b/tests/rustdoc/doc-notable_trait.rs
index 279faf554..d8941769f 100644
--- a/tests/rustdoc/doc-notable_trait.rs
+++ b/tests/rustdoc/doc-notable_trait.rs
@@ -9,7 +9,7 @@ impl<T: SomeTrait> SomeTrait for Wrapper<T> {}
#[doc(notable_trait)]
pub trait SomeTrait {
// @has doc_notable_trait/trait.SomeTrait.html
- // @has - '//a[@class="notable-traits"]/@data-ty' 'Wrapper<Self>'
+ // @has - '//a[@class="tooltip"]/@data-notable-ty' 'Wrapper<Self>'
// @snapshot wrap-me - '//script[@id="notable-traits-data"]'
fn wrap_me(self) -> Wrapper<Self> where Self: Sized {
Wrapper {
@@ -23,7 +23,7 @@ impl SomeTrait for SomeStruct {}
impl SomeStruct {
// @has doc_notable_trait/struct.SomeStruct.html
- // @has - '//a[@class="notable-traits"]/@data-ty' 'SomeStruct'
+ // @has - '//a[@class="tooltip"]/@data-notable-ty' 'SomeStruct'
// @snapshot some-struct-new - '//script[@id="notable-traits-data"]'
pub fn new() -> SomeStruct {
SomeStruct
@@ -31,7 +31,7 @@ impl SomeStruct {
}
// @has doc_notable_trait/fn.bare_fn.html
-// @has - '//a[@class="notable-traits"]/@data-ty' 'SomeStruct'
+// @has - '//a[@class="tooltip"]/@data-notable-ty' 'SomeStruct'
// @snapshot bare-fn - '//script[@id="notable-traits-data"]'
pub fn bare_fn() -> SomeStruct {
SomeStruct
diff --git a/tests/rustdoc/doc-notable_trait.some-struct-new.html b/tests/rustdoc/doc-notable_trait.some-struct-new.html
index 384be6689..e8f4f6000 100644
--- a/tests/rustdoc/doc-notable_trait.some-struct-new.html
+++ b/tests/rustdoc/doc-notable_trait.some-struct-new.html
@@ -1 +1 @@
-<script type="text/json" id="notable-traits-data">{"SomeStruct":"&lt;h3&gt;Notable traits for &lt;code&gt;&lt;a class=\"struct\" href=\"struct.SomeStruct.html\" title=\"struct doc_notable_trait::SomeStruct\"&gt;SomeStruct&lt;/a&gt;&lt;/code&gt;&lt;/h3&gt;&lt;pre&gt;&lt;code&gt;&lt;span class=\"where fmt-newline\"&gt;impl &lt;a class=\"trait\" href=\"trait.SomeTrait.html\" title=\"trait doc_notable_trait::SomeTrait\"&gt;SomeTrait&lt;/a&gt; for &lt;a class=\"struct\" href=\"struct.SomeStruct.html\" title=\"struct doc_notable_trait::SomeStruct\"&gt;SomeStruct&lt;/a&gt;&lt;/span&gt;","Wrapper&lt;Self&gt;":"&lt;h3&gt;Notable traits for &lt;code&gt;&lt;a class=\"struct\" href=\"struct.Wrapper.html\" title=\"struct doc_notable_trait::Wrapper\"&gt;Wrapper&lt;/a&gt;&amp;lt;T&amp;gt;&lt;/code&gt;&lt;/h3&gt;&lt;pre&gt;&lt;code&gt;&lt;span class=\"where fmt-newline\"&gt;impl&amp;lt;T:&amp;nbsp;&lt;a class=\"trait\" href=\"trait.SomeTrait.html\" title=\"trait doc_notable_trait::SomeTrait\"&gt;SomeTrait&lt;/a&gt;&amp;gt; &lt;a class=\"trait\" href=\"trait.SomeTrait.html\" title=\"trait doc_notable_trait::SomeTrait\"&gt;SomeTrait&lt;/a&gt; for &lt;a class=\"struct\" href=\"struct.Wrapper.html\" title=\"struct doc_notable_trait::Wrapper\"&gt;Wrapper&lt;/a&gt;&amp;lt;T&amp;gt;&lt;/span&gt;"}</script> \ No newline at end of file
+<script type="text/json" id="notable-traits-data">{"SomeStruct":"&lt;h3&gt;Notable traits for &lt;code&gt;&lt;a class=\"struct\" href=\"struct.SomeStruct.html\" title=\"struct doc_notable_trait::SomeStruct\"&gt;SomeStruct&lt;/a&gt;&lt;/code&gt;&lt;/h3&gt;&lt;pre&gt;&lt;code&gt;&lt;span class=\"where fmt-newline\"&gt;impl &lt;a class=\"trait\" href=\"trait.SomeTrait.html\" title=\"trait doc_notable_trait::SomeTrait\"&gt;SomeTrait&lt;/a&gt; for &lt;a class=\"struct\" href=\"struct.SomeStruct.html\" title=\"struct doc_notable_trait::SomeStruct\"&gt;SomeStruct&lt;/a&gt;&lt;/span&gt;","Wrapper&lt;Self&gt;":"&lt;h3&gt;Notable traits for &lt;code&gt;&lt;a class=\"struct\" href=\"struct.Wrapper.html\" title=\"struct doc_notable_trait::Wrapper\"&gt;Wrapper&lt;/a&gt;&amp;lt;T&amp;gt;&lt;/code&gt;&lt;/h3&gt;&lt;pre&gt;&lt;code&gt;&lt;span class=\"where fmt-newline\"&gt;impl&amp;lt;T: &lt;a class=\"trait\" href=\"trait.SomeTrait.html\" title=\"trait doc_notable_trait::SomeTrait\"&gt;SomeTrait&lt;/a&gt;&amp;gt; &lt;a class=\"trait\" href=\"trait.SomeTrait.html\" title=\"trait doc_notable_trait::SomeTrait\"&gt;SomeTrait&lt;/a&gt; for &lt;a class=\"struct\" href=\"struct.Wrapper.html\" title=\"struct doc_notable_trait::Wrapper\"&gt;Wrapper&lt;/a&gt;&amp;lt;T&amp;gt;&lt;/span&gt;"}</script> \ No newline at end of file
diff --git a/tests/rustdoc/doc-notable_trait.wrap-me.html b/tests/rustdoc/doc-notable_trait.wrap-me.html
index 0cc1ee10f..e7909669b 100644
--- a/tests/rustdoc/doc-notable_trait.wrap-me.html
+++ b/tests/rustdoc/doc-notable_trait.wrap-me.html
@@ -1 +1 @@
-<script type="text/json" id="notable-traits-data">{"Wrapper&lt;Self&gt;":"&lt;h3&gt;Notable traits for &lt;code&gt;&lt;a class=\"struct\" href=\"struct.Wrapper.html\" title=\"struct doc_notable_trait::Wrapper\"&gt;Wrapper&lt;/a&gt;&amp;lt;T&amp;gt;&lt;/code&gt;&lt;/h3&gt;&lt;pre&gt;&lt;code&gt;&lt;span class=\"where fmt-newline\"&gt;impl&amp;lt;T:&amp;nbsp;&lt;a class=\"trait\" href=\"trait.SomeTrait.html\" title=\"trait doc_notable_trait::SomeTrait\"&gt;SomeTrait&lt;/a&gt;&amp;gt; &lt;a class=\"trait\" href=\"trait.SomeTrait.html\" title=\"trait doc_notable_trait::SomeTrait\"&gt;SomeTrait&lt;/a&gt; for &lt;a class=\"struct\" href=\"struct.Wrapper.html\" title=\"struct doc_notable_trait::Wrapper\"&gt;Wrapper&lt;/a&gt;&amp;lt;T&amp;gt;&lt;/span&gt;"}</script> \ No newline at end of file
+<script type="text/json" id="notable-traits-data">{"Wrapper&lt;Self&gt;":"&lt;h3&gt;Notable traits for &lt;code&gt;&lt;a class=\"struct\" href=\"struct.Wrapper.html\" title=\"struct doc_notable_trait::Wrapper\"&gt;Wrapper&lt;/a&gt;&amp;lt;T&amp;gt;&lt;/code&gt;&lt;/h3&gt;&lt;pre&gt;&lt;code&gt;&lt;span class=\"where fmt-newline\"&gt;impl&amp;lt;T: &lt;a class=\"trait\" href=\"trait.SomeTrait.html\" title=\"trait doc_notable_trait::SomeTrait\"&gt;SomeTrait&lt;/a&gt;&amp;gt; &lt;a class=\"trait\" href=\"trait.SomeTrait.html\" title=\"trait doc_notable_trait::SomeTrait\"&gt;SomeTrait&lt;/a&gt; for &lt;a class=\"struct\" href=\"struct.Wrapper.html\" title=\"struct doc_notable_trait::Wrapper\"&gt;Wrapper&lt;/a&gt;&amp;lt;T&amp;gt;&lt;/span&gt;"}</script> \ No newline at end of file
diff --git a/tests/rustdoc/document-item-with-associated-const-in-where-clause.rs b/tests/rustdoc/document-item-with-associated-const-in-where-clause.rs
new file mode 100644
index 000000000..c9408ef33
--- /dev/null
+++ b/tests/rustdoc/document-item-with-associated-const-in-where-clause.rs
@@ -0,0 +1,17 @@
+#![feature(generic_const_exprs)]
+#![allow(incomplete_features)]
+
+pub trait Enumerable {
+ const N: usize;
+}
+
+#[derive(Clone)]
+pub struct SymmetricGroup<S>
+where
+ S: Enumerable,
+ [(); S::N]: Sized,
+{
+ _phantom: std::marker::PhantomData<S>,
+}
+
+fn main() {}
diff --git a/tests/rustdoc/double-quote-escape.rs b/tests/rustdoc/double-quote-escape.rs
index 350c89741..4f4436377 100644
--- a/tests/rustdoc/double-quote-escape.rs
+++ b/tests/rustdoc/double-quote-escape.rs
@@ -7,5 +7,5 @@ pub trait Foo<T> {
pub struct Bar;
// @has foo/struct.Bar.html
-// @has - '//*[@class="sidebar-elems"]//section//a[@href="#impl-Foo%3Cunsafe%20extern%20%22C%22%20fn()%3E-for-Bar"]' 'Foo<unsafe extern "C" fn()>'
+// @has - '//*[@class="sidebar-elems"]//section//a[@href="#impl-Foo%3Cunsafe+extern+%22C%22+fn()%3E-for-Bar"]' 'Foo<unsafe extern "C" fn()>'
impl Foo<unsafe extern "C" fn()> for Bar {}
diff --git a/tests/rustdoc/duplicate-cfg.rs b/tests/rustdoc/duplicate-cfg.rs
index 18f3900b2..12846c5c1 100644
--- a/tests/rustdoc/duplicate-cfg.rs
+++ b/tests/rustdoc/duplicate-cfg.rs
@@ -2,8 +2,8 @@
#![feature(doc_cfg)]
// @has 'foo/index.html'
-// @matches '-' '//*[@class="item-left module-item"]//*[@class="stab portability"]' '^sync$'
-// @has '-' '//*[@class="item-left module-item"]//*[@class="stab portability"]/@title' 'Available on crate feature `sync` only'
+// @matches '-' '//*[@class="item-name"]//*[@class="stab portability"]' '^sync$'
+// @has '-' '//*[@class="item-name"]//*[@class="stab portability"]/@title' 'Available on crate feature `sync` only'
// @has 'foo/struct.Foo.html'
// @has '-' '//*[@class="stab portability"]' 'sync'
diff --git a/tests/rustdoc/duplicate_impls/issue-33054.rs b/tests/rustdoc/duplicate_impls/issue-33054.rs
index c1f95ac91..4c2071b83 100644
--- a/tests/rustdoc/duplicate_impls/issue-33054.rs
+++ b/tests/rustdoc/duplicate_impls/issue-33054.rs
@@ -3,8 +3,8 @@
// @has issue_33054/impls/struct.Foo.html
// @has - '//h3[@class="code-header"]' 'impl Foo'
// @has - '//h3[@class="code-header"]' 'impl Bar for Foo'
-// @count - '//*[@id="trait-implementations-list"]//*[@class="impl has-srclink"]' 1
-// @count - '//*[@id="main-content"]/div[@id="implementations-list"]/details/summary/*[@class="impl has-srclink"]' 1
+// @count - '//*[@id="trait-implementations-list"]//*[@class="impl"]' 1
+// @count - '//*[@id="main-content"]/div[@id="implementations-list"]/details/summary/*[@class="impl"]' 1
// @has issue_33054/impls/bar/trait.Bar.html
// @has - '//h3[@class="code-header"]' 'impl Bar for Foo'
// @count - '//*[@class="struct"]' 1
diff --git a/tests/rustdoc/duplicated_impl.rs b/tests/rustdoc/duplicated_impl.rs
index 4e901b31c..f32cf3100 100644
--- a/tests/rustdoc/duplicated_impl.rs
+++ b/tests/rustdoc/duplicated_impl.rs
@@ -7,7 +7,7 @@
// blanket implementations.
// @has 'foo/struct.Whatever.html'
-// @count - '//*[@id="blanket-implementations-list"]/section[@class="impl has-srclink"]' 1
+// @count - '//*[@id="blanket-implementations-list"]/section[@class="impl"]' 1
pub trait Something<T> { }
pub struct Whatever;
diff --git a/tests/rustdoc/empty-impl-block-private-with-doc.rs b/tests/rustdoc/empty-impl-block-private-with-doc.rs
index 439719961..e6cff97b1 100644
--- a/tests/rustdoc/empty-impl-block-private-with-doc.rs
+++ b/tests/rustdoc/empty-impl-block-private-with-doc.rs
@@ -10,7 +10,7 @@ pub struct Foo;
// There are 3 impl blocks with public item and one that should not be displayed
// by default because it only contains private items (but not in this case because
// we used `--document-private-items`).
-// @count - '//*[@class="impl has-srclink"]' 'impl Foo' 4
+// @count - '//*[@class="impl"]' 'impl Foo' 4
// Impl block only containing private items should not be displayed unless the
// `--document-private-items` flag is used.
diff --git a/tests/rustdoc/empty-impl-block-private.rs b/tests/rustdoc/empty-impl-block-private.rs
index 5caf02065..d44b4a47c 100644
--- a/tests/rustdoc/empty-impl-block-private.rs
+++ b/tests/rustdoc/empty-impl-block-private.rs
@@ -7,7 +7,7 @@ pub struct Foo;
// There are 3 impl blocks with public item and one that should not be displayed
// because it only contains private items.
-// @count - '//*[@class="impl has-srclink"]' 'impl Foo' 3
+// @count - '//*[@class="impl"]' 'impl Foo' 3
// Impl block only containing private items should not be displayed.
/// Private
diff --git a/tests/rustdoc/empty-impl-block.rs b/tests/rustdoc/empty-impl-block.rs
index 95d4db06b..da780580b 100644
--- a/tests/rustdoc/empty-impl-block.rs
+++ b/tests/rustdoc/empty-impl-block.rs
@@ -8,7 +8,7 @@ pub struct Foo;
/// Hello empty impl block!
impl Foo {}
// We ensure that this empty impl block without doc isn't rendered.
-// @count - '//*[@class="impl has-srclink"]' 'impl Foo' 1
+// @count - '//*[@class="impl"]' 'impl Foo' 1
impl Foo {}
// Just to ensure that empty trait impl blocks are rendered.
diff --git a/tests/rustdoc/fn-pointer-arg-name.rs b/tests/rustdoc/fn-pointer-arg-name.rs
index 96c64ac4e..359ca64ee 100644
--- a/tests/rustdoc/fn-pointer-arg-name.rs
+++ b/tests/rustdoc/fn-pointer-arg-name.rs
@@ -1,5 +1,5 @@
#![crate_name = "foo"]
// @has foo/fn.f.html
-// @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'pub fn f(callback: fn(len: usize, foo: u32))'
+// @has - '//pre[@class="rust item-decl"]' 'pub fn f(callback: fn(len: usize, foo: u32))'
pub fn f(callback: fn(len: usize, foo: u32)) {}
diff --git a/tests/rustdoc/generic-associated-types/gats.rs b/tests/rustdoc/generic-associated-types/gats.rs
index bcead3115..7ab82bb58 100644
--- a/tests/rustdoc/generic-associated-types/gats.rs
+++ b/tests/rustdoc/generic-associated-types/gats.rs
@@ -2,7 +2,7 @@
// @has foo/trait.LendingIterator.html
pub trait LendingIterator {
- // @has - '//*[@id="associatedtype.Item"]//h4[@class="code-header"]' "type Item<'a>where Self: 'a"
+ // @has - '//*[@id="associatedtype.Item"]//h4[@class="code-header"]' "type Item<'a> where Self: 'a"
type Item<'a> where Self: 'a;
// @has - '//*[@id="tymethod.next"]//h4[@class="code-header"]' \
@@ -23,7 +23,7 @@ impl LendingIterator for () {
pub struct Infinite<T>(T);
// @has foo/trait.LendingIterator.html
-// @has - '//*[@id="associatedtype.Item-2"]//h4[@class="code-header"]' "type Item<'a>where Self: 'a = &'a T"
+// @has - '//*[@id="associatedtype.Item-2"]//h4[@class="code-header"]' "type Item<'a> where Self: 'a = &'a T"
impl<T> LendingIterator for Infinite<T> {
type Item<'a> where Self: 'a = &'a T;
diff --git a/tests/rustdoc/glob-shadowing-const.rs b/tests/rustdoc/glob-shadowing-const.rs
index 5b786cf53..58fe8173e 100644
--- a/tests/rustdoc/glob-shadowing-const.rs
+++ b/tests/rustdoc/glob-shadowing-const.rs
@@ -15,6 +15,6 @@ mod sub4 {
pub use sub4::inner::*;
// @has 'foo/index.html'
-// @has - '//div[@class="item-right docblock-short"]' '1'
-// @!has - '//div[@class="item-right docblock-short"]' '0'
+// @has - '//div[@class="desc docblock-short"]' '1'
+// @!has - '//div[@class="desc docblock-short"]' '0'
fn main() { assert_eq!(X, 1); }
diff --git a/tests/rustdoc/glob-shadowing.rs b/tests/rustdoc/glob-shadowing.rs
index 66a31c42b..c117b9d64 100644
--- a/tests/rustdoc/glob-shadowing.rs
+++ b/tests/rustdoc/glob-shadowing.rs
@@ -1,17 +1,17 @@
// @has 'glob_shadowing/index.html'
-// @count - '//div[@class="item-left module-item"]' 6
-// @!has - '//div[@class="item-right docblock-short"]' 'sub1::describe'
-// @has - '//div[@class="item-right docblock-short"]' 'sub2::describe'
+// @count - '//div[@class="item-name"]' 6
+// @!has - '//div[@class="desc docblock-short"]' 'sub1::describe'
+// @has - '//div[@class="desc docblock-short"]' 'sub2::describe'
-// @!has - '//div[@class="item-right docblock-short"]' 'sub1::describe2'
+// @!has - '//div[@class="desc docblock-short"]' 'sub1::describe2'
-// @!has - '//div[@class="item-right docblock-short"]' 'sub1::prelude'
-// @has - '//div[@class="item-right docblock-short"]' 'mod::prelude'
+// @!has - '//div[@class="desc docblock-short"]' 'sub1::prelude'
+// @has - '//div[@class="desc docblock-short"]' 'mod::prelude'
-// @has - '//div[@class="item-right docblock-short"]' 'sub1::Foo (struct)'
-// @has - '//div[@class="item-right docblock-short"]' 'mod::Foo (function)'
+// @has - '//div[@class="desc docblock-short"]' 'sub1::Foo (struct)'
+// @has - '//div[@class="desc docblock-short"]' 'mod::Foo (function)'
-// @has - '//div[@class="item-right docblock-short"]' 'sub4::inner::X'
+// @has - '//div[@class="desc docblock-short"]' 'sub4::inner::X'
// @has 'glob_shadowing/fn.describe.html'
// @has - '//div[@class="docblock"]' 'sub2::describe'
diff --git a/tests/rustdoc/hidden-private.rs b/tests/rustdoc/hidden-private.rs
new file mode 100644
index 000000000..834ba5231
--- /dev/null
+++ b/tests/rustdoc/hidden-private.rs
@@ -0,0 +1,50 @@
+// This is a regression test for <https://github.com/rust-lang/rust/issues/106373>.
+// It ensures that the items in the `doc(hidden)` const block don't show up in the
+// generated docs.
+
+// compile-flags: --document-private-items
+
+#![crate_name = "foo"]
+
+// @has 'foo/index.html'
+// @count - '//*[@class="item-table"]//a[@class="struct"]' 2
+// @count - '//*[@class="item-table"]//a[@class="trait"]' 1
+// @count - '//*[@class="item-table"]//a[@class="macro"]' 0
+#[doc(hidden)]
+const _: () = {
+ macro_rules! stry {
+ () => {};
+ }
+
+ struct ShouldBeHidden;
+
+ // @has 'foo/struct.Foo.html'
+ // @!has - '//*[@class="code-header"]' 'impl Bar for Foo'
+ #[doc(hidden)]
+ impl Bar for Foo {
+ fn bar(&self) {
+ struct SHouldAlsoBeHidden;
+ }
+ }
+
+ // @has 'foo/struct.Private.html'
+ // @has - '//*[@id="impl-Bar-for-Private"]/*[@class="code-header"]' 'impl Bar for Private'
+ // @has - '//*[@id="method.bar"]/*[@class="code-header"]' 'fn bar(&self)'
+ impl Bar for Private {
+ fn bar(&self) {}
+ }
+
+ // @has - '//*[@id="impl-Private"]/*[@class="code-header"]' 'impl Private'
+ // @has - '//*[@id="method.tralala"]/*[@class="code-header"]' 'fn tralala()'
+ impl Private {
+ fn tralala() {}
+ }
+};
+
+
+struct Private;
+pub struct Foo;
+
+pub trait Bar {
+ fn bar(&self);
+}
diff --git a/tests/rustdoc/hide-complex-unevaluated-const-arguments.rs b/tests/rustdoc/hide-complex-unevaluated-const-arguments.rs
index 406157ce2..d368db909 100644
--- a/tests/rustdoc/hide-complex-unevaluated-const-arguments.rs
+++ b/tests/rustdoc/hide-complex-unevaluated-const-arguments.rs
@@ -63,7 +63,7 @@ impl<const S: Struct, St: Stage + ?Sized> Helper<S> for St {
// this test as long as one can ensure that private fields are not leaked!
//
// @has hide_complex_unevaluated_const_arguments/trait.Sub.html \
-// '//div[@class="item-decl"]/pre[@class="rust"]' \
+// '//pre[@class="rust item-decl"]' \
// 'pub trait Sub: Sup<{ _ }, { _ }> { }'
pub trait Sub: Sup<{ 90 * 20 * 4 }, { Struct { private: () } }> {}
diff --git a/tests/rustdoc/impl-in-const-block.rs b/tests/rustdoc/impl-in-const-block.rs
new file mode 100644
index 000000000..b44e71352
--- /dev/null
+++ b/tests/rustdoc/impl-in-const-block.rs
@@ -0,0 +1,43 @@
+// Regression test for #83026.
+// The goal of this test is to ensure that impl blocks inside
+// const expressions are documented as well.
+
+#![crate_name = "foo"]
+
+// @has 'foo/struct.A.html'
+// @has - '//*[@id="method.new"]/*[@class="code-header"]' 'pub fn new() -> A'
+// @has - '//*[@id="method.bar"]/*[@class="code-header"]' 'pub fn bar(&self)'
+// @has - '//*[@id="method.woo"]/*[@class="code-header"]' 'pub fn woo(&self)'
+// @has - '//*[@id="method.yoo"]/*[@class="code-header"]' 'pub fn yoo()'
+// @has - '//*[@id="method.yuu"]/*[@class="code-header"]' 'pub fn yuu()'
+pub struct A;
+
+const _: () = {
+ impl A {
+ const FOO: () = {
+ impl A {
+ pub fn woo(&self) {}
+ }
+ };
+
+ pub fn new() -> A {
+ A
+ }
+ }
+};
+pub const X: () = {
+ impl A {
+ pub fn bar(&self) {}
+ }
+};
+
+fn foo() {
+ impl A {
+ pub fn yoo() {}
+ }
+ const _: () = {
+ impl A {
+ pub fn yuu() {}
+ }
+ };
+}
diff --git a/tests/rustdoc/impl-parts.rs b/tests/rustdoc/impl-parts.rs
index 90cbb77cb..f7738060e 100644
--- a/tests/rustdoc/impl-parts.rs
+++ b/tests/rustdoc/impl-parts.rs
@@ -5,7 +5,7 @@ pub auto trait AnAutoTrait {}
pub struct Foo<T> { field: T }
-// @has impl_parts/struct.Foo.html '//*[@class="impl has-srclink"]//h3[@class="code-header"]' \
+// @has impl_parts/struct.Foo.html '//*[@class="impl"]//h3[@class="code-header"]' \
// "impl<T> !AnAutoTrait for Foo<T>where T: Sync + Clone,"
// @has impl_parts/trait.AnAutoTrait.html '//*[@id="implementors-list"]//h3[@class="code-header"]' \
// "impl<T> !AnAutoTrait for Foo<T>where T: Sync + Clone,"
diff --git a/tests/rustdoc/inline-default-methods.rs b/tests/rustdoc/inline-default-methods.rs
index a4ca928f3..7706cb139 100644
--- a/tests/rustdoc/inline-default-methods.rs
+++ b/tests/rustdoc/inline-default-methods.rs
@@ -4,6 +4,18 @@
extern crate inline_default_methods;
// @has inline_default_methods/trait.Foo.html
-// @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'fn bar(&self);'
-// @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'fn foo(&mut self) { ... }'
+// @has - '//pre[@class="rust item-decl"]' '// Required method fn bar(&self);'
+// @has - '//pre[@class="rust item-decl"]' '// Provided method fn foo(&mut self)'
pub use inline_default_methods::Foo;
+
+// @has inline_default_methods/trait.Bar.html
+// @has - '//pre[@class="rust item-decl"]' '// Required method fn bar(&self);'
+// @has - '//pre[@class="rust item-decl"]' '// Provided methods fn foo1(&mut self)'
+// @has - '//pre[@class="rust item-decl"]' 'fn foo2(&mut self)'
+pub use inline_default_methods::Bar;
+
+// @has inline_default_methods/trait.Baz.html
+// @has - '//pre[@class="rust item-decl"]' '// Required methods fn bar1(&self);'
+// @has - '//pre[@class="rust item-decl"]' 'fn bar2(&self);'
+// @has - '//pre[@class="rust item-decl"]' '// Provided method fn foo(&mut self)'
+pub use inline_default_methods::Baz;
diff --git a/tests/rustdoc/inline_cross/dyn_trait.rs b/tests/rustdoc/inline_cross/dyn_trait.rs
index 0da8bfc3a..649d98f71 100644
--- a/tests/rustdoc/inline_cross/dyn_trait.rs
+++ b/tests/rustdoc/inline_cross/dyn_trait.rs
@@ -4,28 +4,28 @@
// edition:2021
// @has user/type.Ty0.html
-// @has - '//*[@class="item-decl"]//code' "dyn for<'any> FnOnce(&'any str) -> bool + 'static"
+// @has - '//*[@class="rust item-decl"]//code' "dyn for<'any> FnOnce(&'any str) -> bool + 'static"
// FIXME(fmease): Hide default lifetime bound `'static`
pub use dyn_trait::Ty0;
// @has user/type.Ty1.html
-// @has - '//*[@class="item-decl"]//code' "dyn Display + 'obj"
+// @has - '//*[@class="rust item-decl"]//code' "dyn Display + 'obj"
pub use dyn_trait::Ty1;
// @has user/type.Ty2.html
-// @has - '//*[@class="item-decl"]//code' "dyn for<'a, 'r> Container<'r, Item<'a, 'static> = ()>"
+// @has - '//*[@class="rust item-decl"]//code' "dyn for<'a, 'r> Container<'r, Item<'a, 'static> = ()>"
pub use dyn_trait::Ty2;
// @has user/type.Ty3.html
-// @has - '//*[@class="item-decl"]//code' "&'s (dyn ToString + 's)"
+// @has - '//*[@class="rust item-decl"]//code' "&'s (dyn ToString + 's)"
// FIXME(fmease): Hide default lifetime bound, render "&'s dyn ToString"
pub use dyn_trait::Ty3;
// @has user/fn.func0.html
-// @has - '//div[@class="item-decl"]/pre[@class="rust"]' "func0(_: &dyn Fn())"
+// @has - '//pre[@class="rust item-decl"]' "func0(_: &dyn Fn())"
// FIXME(fmease): Show placeholder-lifetime bound, render "func0(_: &(dyn Fn() + '_))"
pub use dyn_trait::func0;
// @has user/fn.func1.html
-// @has - '//div[@class="item-decl"]/pre[@class="rust"]' "func1<'func>(_: &(dyn Fn() + 'func))"
+// @has - '//pre[@class="rust item-decl"]' "func1<'func>(_: &(dyn Fn() + 'func))"
pub use dyn_trait::func1;
diff --git a/tests/rustdoc/inline_cross/impl_trait.rs b/tests/rustdoc/inline_cross/impl_trait.rs
index e8587209b..b6a1552bc 100644
--- a/tests/rustdoc/inline_cross/impl_trait.rs
+++ b/tests/rustdoc/inline_cross/impl_trait.rs
@@ -4,37 +4,37 @@
extern crate impl_trait_aux;
// @has impl_trait/fn.func.html
-// @has - '//div[@class="item-decl"]/pre[@class="rust"]' "pub fn func<'a>(_x: impl Clone + Into<Vec<u8, Global>> + 'a)"
-// @!has - '//div[@class="item-decl"]/pre[@class="rust"]' 'where'
+// @has - '//pre[@class="rust item-decl"]' "pub fn func<'a>(_x: impl Clone + Into<Vec<u8, Global>> + 'a)"
+// @!has - '//pre[@class="rust item-decl"]' 'where'
pub use impl_trait_aux::func;
// @has impl_trait/fn.func2.html
-// @has - '//div[@class="item-decl"]/pre[@class="rust"]' "func2<T>("
-// @has - '//div[@class="item-decl"]/pre[@class="rust"]' "_x: impl Deref<Target = Option<T>> + Iterator<Item = T>,"
-// @has - '//div[@class="item-decl"]/pre[@class="rust"]' "_y: impl Iterator<Item = u8>)"
-// @!has - '//div[@class="item-decl"]/pre[@class="rust"]' 'where'
+// @has - '//pre[@class="rust item-decl"]' "func2<T>("
+// @has - '//pre[@class="rust item-decl"]' "_x: impl Deref<Target = Option<T>> + Iterator<Item = T>,"
+// @has - '//pre[@class="rust item-decl"]' "_y: impl Iterator<Item = u8> )"
+// @!has - '//pre[@class="rust item-decl"]' 'where'
pub use impl_trait_aux::func2;
// @has impl_trait/fn.func3.html
-// @has - '//div[@class="item-decl"]/pre[@class="rust"]' "func3("
-// @has - '//div[@class="item-decl"]/pre[@class="rust"]' "_x: impl Iterator<Item = impl Iterator<Item = u8>> + Clone)"
-// @!has - '//div[@class="item-decl"]/pre[@class="rust"]' 'where'
+// @has - '//pre[@class="rust item-decl"]' "func3("
+// @has - '//pre[@class="rust item-decl"]' "_x: impl Iterator<Item = impl Iterator<Item = u8>> + Clone)"
+// @!has - '//pre[@class="rust item-decl"]' 'where'
pub use impl_trait_aux::func3;
// @has impl_trait/fn.func4.html
-// @has - '//div[@class="item-decl"]/pre[@class="rust"]' "func4<T>("
-// @has - '//div[@class="item-decl"]/pre[@class="rust"]' "T: Iterator<Item = impl Clone>,"
+// @has - '//pre[@class="rust item-decl"]' "func4<T>("
+// @has - '//pre[@class="rust item-decl"]' "T: Iterator<Item = impl Clone>,"
pub use impl_trait_aux::func4;
// @has impl_trait/fn.func5.html
-// @has - '//div[@class="item-decl"]/pre[@class="rust"]' "func5("
-// @has - '//div[@class="item-decl"]/pre[@class="rust"]' "_f: impl for<'any> Fn(&'any str, &'any str) -> bool + for<'r> Other<T<'r> = ()>,"
-// @has - '//div[@class="item-decl"]/pre[@class="rust"]' "_a: impl for<'alpha, 'beta> Auxiliary<'alpha, Item<'beta> = fn(_: &'beta ())>"
-// @!has - '//div[@class="item-decl"]/pre[@class="rust"]' 'where'
+// @has - '//pre[@class="rust item-decl"]' "func5("
+// @has - '//pre[@class="rust item-decl"]' "_f: impl for<'any> Fn(&'any str, &'any str) -> bool + for<'r> Other<T<'r> = ()>,"
+// @has - '//pre[@class="rust item-decl"]' "_a: impl for<'alpha, 'beta> Auxiliary<'alpha, Item<'beta> = fn(_: &'beta ())>"
+// @!has - '//pre[@class="rust item-decl"]' 'where'
pub use impl_trait_aux::func5;
// @has impl_trait/fn.async_fn.html
-// @has - '//div[@class="item-decl"]/pre[@class="rust"]' "pub async fn async_fn()"
+// @has - '//pre[@class="rust item-decl"]' "pub async fn async_fn()"
pub use impl_trait_aux::async_fn;
// @has impl_trait/struct.Foo.html
diff --git a/tests/rustdoc/inline_cross/issue-24183.rs b/tests/rustdoc/inline_cross/issue-24183.rs
index d11b6955f..751a32385 100644
--- a/tests/rustdoc/inline_cross/issue-24183.rs
+++ b/tests/rustdoc/inline_cross/issue-24183.rs
@@ -5,7 +5,7 @@
// edition: 2021
// @has usr/trait.U.html
-// @has - '//*[@class="item-decl"]' "pub trait U {"
+// @has - '//*[@class="rust item-decl"]' "pub trait U {"
// @has - '//*[@id="method.modified"]' \
// "fn modified(self) -> Self\
// where \
@@ -14,5 +14,5 @@
pub use issue_24183::U;
// @has usr/trait.S.html
-// @has - '//*[@class="item-decl"]' 'pub trait S: Sized {'
+// @has - '//*[@class="rust item-decl"]' 'pub trait S: Sized {'
pub use issue_24183::S;
diff --git a/tests/rustdoc/inline_cross/issue-31948-1.rs b/tests/rustdoc/inline_cross/issue-31948-1.rs
index 6e89167b3..571eaf6be 100644
--- a/tests/rustdoc/inline_cross/issue-31948-1.rs
+++ b/tests/rustdoc/inline_cross/issue-31948-1.rs
@@ -5,8 +5,8 @@
extern crate rustdoc_nonreachable_impls;
// @has issue_31948_1/struct.Wobble.html
-// @has - '//*[@class="impl has-srclink"]//h3[@class="code-header"]' 'Bark for'
-// @has - '//*[@class="impl has-srclink"]//h3[@class="code-header"]' 'Woof for'
+// @has - '//*[@class="impl"]//h3[@class="code-header"]' 'Bark for'
+// @has - '//*[@class="impl"]//h3[@class="code-header"]' 'Woof for'
// @!has - '//*[@class="impl"]//h3[@class="code-header"]' 'Bar for'
// @!has - '//*[@class="impl"]//h3[@class="code-header"]' 'Qux for'
pub use rustdoc_nonreachable_impls::hidden::Wobble;
diff --git a/tests/rustdoc/inline_cross/issue-31948-2.rs b/tests/rustdoc/inline_cross/issue-31948-2.rs
index 141e07656..7eae21046 100644
--- a/tests/rustdoc/inline_cross/issue-31948-2.rs
+++ b/tests/rustdoc/inline_cross/issue-31948-2.rs
@@ -5,9 +5,9 @@
extern crate rustdoc_nonreachable_impls;
// @has issue_31948_2/struct.Wobble.html
-// @has - '//*[@class="impl has-srclink"]//h3[@class="code-header"]' 'Qux for'
-// @has - '//*[@class="impl has-srclink"]//h3[@class="code-header"]' 'Bark for'
-// @has - '//*[@class="impl has-srclink"]//h3[@class="code-header"]' 'Woof for'
+// @has - '//*[@class="impl"]//h3[@class="code-header"]' 'Qux for'
+// @has - '//*[@class="impl"]//h3[@class="code-header"]' 'Bark for'
+// @has - '//*[@class="impl"]//h3[@class="code-header"]' 'Woof for'
// @!has - '//*[@class="impl"]//h3[@class="code-header"]' 'Bar for'
pub use rustdoc_nonreachable_impls::hidden::Wobble;
diff --git a/tests/rustdoc/inline_cross/issue-31948.rs b/tests/rustdoc/inline_cross/issue-31948.rs
index 96fc6ca47..9c271bf4a 100644
--- a/tests/rustdoc/inline_cross/issue-31948.rs
+++ b/tests/rustdoc/inline_cross/issue-31948.rs
@@ -5,9 +5,9 @@
extern crate rustdoc_nonreachable_impls;
// @has issue_31948/struct.Foo.html
-// @has - '//*[@class="impl has-srclink"]//h3[@class="code-header"]' 'Bark for'
-// @has - '//*[@class="impl has-srclink"]//h3[@class="code-header"]' 'Woof for'
-// @!has - '//*[@class="impl has-srclink"]//h3[@class="code-header"]' 'Bar for'
+// @has - '//*[@class="impl"]//h3[@class="code-header"]' 'Bark for'
+// @has - '//*[@class="impl"]//h3[@class="code-header"]' 'Woof for'
+// @!has - '//*[@class="impl"]//h3[@class="code-header"]' 'Bar for'
// @!has - '//*[@class="impl"]//h3[@class="code-header"]' 'Qux for'
pub use rustdoc_nonreachable_impls::Foo;
diff --git a/tests/rustdoc/inline_cross/macros.rs b/tests/rustdoc/inline_cross/macros.rs
index 5daa0d4ba..a41b9c5b1 100644
--- a/tests/rustdoc/inline_cross/macros.rs
+++ b/tests/rustdoc/inline_cross/macros.rs
@@ -6,9 +6,9 @@
extern crate macros;
-// @has foo/index.html '//*[@class="item-left unstable deprecated module-item"]/span[@class="stab deprecated"]' \
+// @has foo/index.html '//*[@class="item-name"]/span[@class="stab deprecated"]' \
// Deprecated
-// @has - '//*[@class="item-left unstable deprecated module-item"]/span[@class="stab unstable"]' \
+// @has - '//*[@class="item-name"]/span[@class="stab unstable"]' \
// Experimental
// @has foo/macro.my_macro.html
diff --git a/tests/rustdoc/internal.rs b/tests/rustdoc/internal.rs
index caad43a08..27b089768 100644
--- a/tests/rustdoc/internal.rs
+++ b/tests/rustdoc/internal.rs
@@ -3,12 +3,12 @@
// Check that the unstable marker is not added for "rustc_private".
// @!matches internal/index.html \
-// '//*[@class="item-right docblock-short"]/span[@class="stab unstable"]' \
+// '//*[@class="desc docblock-short"]/span[@class="stab unstable"]' \
// ''
// @!matches internal/index.html \
-// '//*[@class="item-right docblock-short"]/span[@class="stab internal"]' \
+// '//*[@class="desc docblock-short"]/span[@class="stab internal"]' \
// ''
-// @matches - '//*[@class="item-right docblock-short"]' 'Docs'
+// @matches - '//*[@class="desc docblock-short"]' 'Docs'
// @!has internal/struct.S.html '//*[@class="stab unstable"]' ''
// @!has internal/struct.S.html '//*[@class="stab internal"]' ''
diff --git a/tests/rustdoc/intra-doc/basic.rs b/tests/rustdoc/intra-doc/basic.rs
index 39f5c298b..96e21137b 100644
--- a/tests/rustdoc/intra-doc/basic.rs
+++ b/tests/rustdoc/intra-doc/basic.rs
@@ -1,30 +1,53 @@
// @has basic/index.html
// @has - '//a/@href' 'struct.ThisType.html'
+// @has - '//a/@title' 'struct basic::ThisType'
// @has - '//a/@href' 'struct.ThisType.html#method.this_method'
+// @has - '//a/@title' 'method basic::ThisType::this_method'
+// @has - '//a/@href' 'struct.ThisType.html#method.this_assoc_fn'
+// @has - '//a/@title' 'associated function basic::ThisType::this_assoc_fn'
// @has - '//a/@href' 'enum.ThisEnum.html'
+// @has - '//a/@title' 'enum basic::ThisEnum'
// @has - '//a/@href' 'enum.ThisEnum.html#variant.ThisVariant'
+// @has - '//a/@title' 'variant basic::ThisEnum::ThisVariant'
// @has - '//a/@href' 'trait.ThisTrait.html'
+// @has - '//a/@title' 'trait basic::ThisTrait'
// @has - '//a/@href' 'trait.ThisTrait.html#tymethod.this_associated_method'
+// @has - '//a/@title' 'method basic::ThisTrait::this_associated_method'
+// @has - '//a/@href' 'trait.ThisTrait.html#tymethod.this_associated_fn'
+// @has - '//a/@title' 'associated function basic::ThisTrait::this_associated_fn'
// @has - '//a/@href' 'trait.ThisTrait.html#associatedtype.ThisAssociatedType'
+// @has - '//a/@title' 'associated type basic::ThisTrait::ThisAssociatedType'
// @has - '//a/@href' 'trait.ThisTrait.html#associatedconstant.THIS_ASSOCIATED_CONST'
+// @has - '//a/@title' 'associated constant basic::ThisTrait::THIS_ASSOCIATED_CONST'
// @has - '//a/@href' 'trait.ThisTrait.html'
+// @has - '//a/@title' 'trait basic::ThisTrait'
// @has - '//a/@href' 'type.ThisAlias.html'
+// @has - '//a/@title' 'type basic::ThisAlias'
// @has - '//a/@href' 'union.ThisUnion.html'
+// @has - '//a/@title' 'union basic::ThisUnion'
// @has - '//a/@href' 'fn.this_function.html'
+// @has - '//a/@title' 'fn basic::this_function'
// @has - '//a/@href' 'constant.THIS_CONST.html'
+// @has - '//a/@title' 'constant basic::THIS_CONST'
// @has - '//a/@href' 'static.THIS_STATIC.html'
+// @has - '//a/@title' 'static basic::THIS_STATIC'
// @has - '//a/@href' 'macro.this_macro.html'
+// @has - '//a/@title' 'macro basic::this_macro'
// @has - '//a/@href' 'trait.SoAmbiguous.html'
+// @has - '//a/@title' 'trait basic::SoAmbiguous'
// @has - '//a/@href' 'fn.SoAmbiguous.html'
+// @has - '//a/@title' 'fn basic::SoAmbiguous'
//! In this crate we would like to link to:
//!
//! * [`ThisType`](ThisType)
//! * [`ThisType::this_method`](ThisType::this_method)
+//! * [`ThisType::this_assoc_fn`](ThisType::this_assoc_fn)
//! * [`ThisEnum`](ThisEnum)
//! * [`ThisEnum::ThisVariant`](ThisEnum::ThisVariant)
//! * [`ThisEnum::ThisVariantCtor`](ThisEnum::ThisVariantCtor)
//! * [`ThisTrait`](ThisTrait)
//! * [`ThisTrait::this_associated_method`](ThisTrait::this_associated_method)
+//! * [`ThisTrait::this_associated_fn`](ThisTrait::this_associated_fn)
//! * [`ThisTrait::ThisAssociatedType`](ThisTrait::ThisAssociatedType)
//! * [`ThisTrait::THIS_ASSOCIATED_CONST`](ThisTrait::THIS_ASSOCIATED_CONST)
//! * [`ThisAlias`](ThisAlias)
@@ -51,13 +74,15 @@ macro_rules! this_macro {
pub struct ThisType;
impl ThisType {
- pub fn this_method() {}
+ pub fn this_assoc_fn() {}
+ pub fn this_method(self) {}
}
pub enum ThisEnum { ThisVariant, ThisVariantCtor(u32), }
pub trait ThisTrait {
type ThisAssociatedType;
const THIS_ASSOCIATED_CONST: u8;
- fn this_associated_method();
+ fn this_associated_fn();
+ fn this_associated_method(&self);
}
pub type ThisAlias = Result<(), ()>;
pub union ThisUnion { this_field: usize, }
diff --git a/tests/rustdoc/issue-107995.rs b/tests/rustdoc/issue-107995.rs
new file mode 100644
index 000000000..1273e4fdd
--- /dev/null
+++ b/tests/rustdoc/issue-107995.rs
@@ -0,0 +1,28 @@
+// Regression test for <https://github.com/rust-lang/rust/issues/107995>.
+
+#![crate_name = "foo"]
+
+// @has 'foo/fn.foo.html'
+// @has - '//*[@class="docblock"]//a[@href="fn.bar.html"]' 'bar`'
+/// A foo, see also [ bar`]
+pub fn foo() {}
+
+// @has 'foo/fn.bar.html'
+// @has - '//*[@class="docblock"]' 'line Path line'
+// @has - '//*[@class="docblock"]//a[@href="struct.Path.html"]' 'Path'
+#[doc = "line ["]
+#[doc = "Path"]
+#[doc = "] line"]
+pub fn bar() {}
+
+// @has 'foo/fn.another.html'
+// @has - '//*[@class="docblock"]//a[@href="struct.Path.html"]' 'Path'
+/// [ `Path`]
+pub fn another() {}
+
+// @has 'foo/fn.last.html'
+// @has - '//*[@class="docblock"]//a[@href="struct.Path.html"]' 'Path'
+/// [ Path`]
+pub fn last() {}
+
+pub struct Path;
diff --git a/tests/rustdoc/issue-108231.rs b/tests/rustdoc/issue-108231.rs
new file mode 100644
index 000000000..684f0494f
--- /dev/null
+++ b/tests/rustdoc/issue-108231.rs
@@ -0,0 +1,23 @@
+// Regression test for <https://github.com/rust-lang/rust/issues/108231>.
+// Macros with `#[macro_export]` attribute should be visible at the top level
+// even if they are inside a doc hidden item.
+
+#![crate_name = "foo"]
+
+// @has 'foo/index.html'
+// @count - '//*[@id="main-content"]//a[@class="macro"]' 1
+// @has - '//*[@id="main-content"]//a[@class="macro"]' 'foo'
+
+#[doc(hidden)]
+pub mod __internal {
+ /// This one should be visible.
+ #[macro_export]
+ macro_rules! foo {
+ () => {};
+ }
+
+ /// This one should be hidden.
+ macro_rules! bar {
+ () => {};
+ }
+}
diff --git a/tests/rustdoc/issue-108281.rs b/tests/rustdoc/issue-108281.rs
new file mode 100644
index 000000000..8e1b6ba88
--- /dev/null
+++ b/tests/rustdoc/issue-108281.rs
@@ -0,0 +1,25 @@
+// Regression test for <https://github.com/rust-lang/rust/issues/108281>.
+// It ensures that the attributes on the first reexport are not duplicated.
+
+#![crate_name = "foo"]
+
+// @has 'foo/index.html'
+
+#[doc(hidden)]
+pub fn bar() {}
+mod sub {
+ pub fn public() {}
+}
+
+// @matches - '//*[@class="desc docblock-short"]' '^Displayed$'
+/// Displayed
+#[doc(inline)]
+pub use crate::bar as Bar;
+// @matches - '//*[@class="desc docblock-short"]' '^Hello\sDisplayed$'
+#[doc(inline)]
+/// Hello
+pub use crate::Bar as Bar2;
+
+// @matches - '//*[@class="desc docblock-short"]' '^Public$'
+/// Public
+pub use crate::sub::public as Public;
diff --git a/tests/rustdoc/issue-20646.rs b/tests/rustdoc/issue-20646.rs
index a774b0ca7..b2ee9c260 100644
--- a/tests/rustdoc/issue-20646.rs
+++ b/tests/rustdoc/issue-20646.rs
@@ -13,7 +13,7 @@ pub trait Trait {
}
// @has issue_20646/fn.fun.html \
-// '//div[@class="item-decl"]/pre[@class="rust"]' 'where T: Trait<Output = i32>'
+// '//pre[@class="rust item-decl"]' 'where T: Trait<Output = i32>'
pub fn fun<T>(_: T) where T: Trait<Output=i32> {}
pub mod reexport {
@@ -21,6 +21,6 @@ pub mod reexport {
// '//*[@id="associatedtype.Output"]' \
// 'type Output'
// @has issue_20646/reexport/fn.fun.html \
- // '//div[@class="item-decl"]/pre[@class="rust"]' 'where T: Trait<Output = i32>'
+ // '//pre[@class="rust item-decl"]' 'where T: Trait<Output = i32>'
pub use issue_20646::{Trait, fun};
}
diff --git a/tests/rustdoc/issue-20727-2.rs b/tests/rustdoc/issue-20727-2.rs
index 026b4f5ac..c1aa9617b 100644
--- a/tests/rustdoc/issue-20727-2.rs
+++ b/tests/rustdoc/issue-20727-2.rs
@@ -5,18 +5,18 @@ extern crate issue_20727;
// @has issue_20727_2/trait.Add.html
pub trait Add<RHS = Self> {
- // @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'trait Add<RHS = Self> {'
- // @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'type Output;'
+ // @has - '//pre[@class="rust item-decl"]' 'trait Add<RHS = Self> {'
+ // @has - '//pre[@class="rust item-decl"]' 'type Output;'
type Output;
- // @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'fn add(self, rhs: RHS) -> Self::Output;'
+ // @has - '//pre[@class="rust item-decl"]' 'fn add(self, rhs: RHS) -> Self::Output;'
fn add(self, rhs: RHS) -> Self::Output;
}
// @has issue_20727_2/reexport/trait.Add.html
pub mod reexport {
- // @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'trait Add<RHS = Self> {'
- // @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'type Output;'
- // @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'fn add(self, rhs: RHS) -> Self::Output;'
+ // @has - '//pre[@class="rust item-decl"]' 'trait Add<RHS = Self> {'
+ // @has - '//pre[@class="rust item-decl"]' 'type Output;'
+ // @has - '//pre[@class="rust item-decl"]' 'fn add(self, rhs: RHS) -> Self::Output;'
pub use issue_20727::Add;
}
diff --git a/tests/rustdoc/issue-20727-3.rs b/tests/rustdoc/issue-20727-3.rs
index 741ce8023..2f9d91fc5 100644
--- a/tests/rustdoc/issue-20727-3.rs
+++ b/tests/rustdoc/issue-20727-3.rs
@@ -7,18 +7,18 @@ pub trait Bar {}
// @has issue_20727_3/trait.Deref2.html
pub trait Deref2 {
- // @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'trait Deref2 {'
- // @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'type Target: Bar;'
+ // @has - '//pre[@class="rust item-decl"]' 'trait Deref2 {'
+ // @has - '//pre[@class="rust item-decl"]' 'type Target: Bar;'
type Target: Bar;
- // @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'fn deref(&self) -> Self::Target;'
+ // @has - '//pre[@class="rust item-decl"]' 'fn deref(&self) -> Self::Target;'
fn deref(&self) -> Self::Target;
}
// @has issue_20727_3/reexport/trait.Deref2.html
pub mod reexport {
- // @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'trait Deref2 {'
- // @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'type Target: Bar;'
- // @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'fn deref(&self) -> Self::Target;'
+ // @has - '//pre[@class="rust item-decl"]' 'trait Deref2 {'
+ // @has - '//pre[@class="rust item-decl"]' 'type Target: Bar;'
+ // @has - '//pre[@class="rust item-decl"]' 'fn deref(&self) -> Self::Target;'
pub use issue_20727::Deref2;
}
diff --git a/tests/rustdoc/issue-20727-4.rs b/tests/rustdoc/issue-20727-4.rs
index b8fac4da6..ec9f18fc3 100644
--- a/tests/rustdoc/issue-20727-4.rs
+++ b/tests/rustdoc/issue-20727-4.rs
@@ -5,36 +5,36 @@ extern crate issue_20727;
// @has issue_20727_4/trait.Index.html
pub trait Index<Idx: ?Sized> {
- // @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'trait Index<Idx: ?Sized> {'
- // @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'type Output: ?Sized'
+ // @has - '//pre[@class="rust item-decl"]' 'trait Index<Idx: ?Sized> {'
+ // @has - '//pre[@class="rust item-decl"]' 'type Output: ?Sized'
type Output: ?Sized;
- // @has - '//div[@class="item-decl"]/pre[@class="rust"]' \
+ // @has - '//pre[@class="rust item-decl"]' \
// 'fn index(&self, index: Idx) -> &Self::Output'
fn index(&self, index: Idx) -> &Self::Output;
}
// @has issue_20727_4/trait.IndexMut.html
pub trait IndexMut<Idx: ?Sized>: Index<Idx> {
- // @has - '//div[@class="item-decl"]/pre[@class="rust"]' \
+ // @has - '//pre[@class="rust item-decl"]' \
// 'trait IndexMut<Idx: ?Sized>: Index<Idx> {'
- // @has - '//div[@class="item-decl"]/pre[@class="rust"]' \
+ // @has - '//pre[@class="rust item-decl"]' \
// 'fn index_mut(&mut self, index: Idx) -> &mut Self::Output;'
fn index_mut(&mut self, index: Idx) -> &mut Self::Output;
}
pub mod reexport {
// @has issue_20727_4/reexport/trait.Index.html
- // @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'trait Index<Idx>where Idx: ?Sized,{'
- // @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'type Output: ?Sized'
- // @has - '//div[@class="item-decl"]/pre[@class="rust"]' \
+ // @has - '//pre[@class="rust item-decl"]' 'trait Index<Idx>where Idx: ?Sized,{'
+ // @has - '//pre[@class="rust item-decl"]' 'type Output: ?Sized'
+ // @has - '//pre[@class="rust item-decl"]' \
// 'fn index(&self, index: Idx) -> &Self::Output'
pub use issue_20727::Index;
// @has issue_20727_4/reexport/trait.IndexMut.html
- // @has - '//div[@class="item-decl"]/pre[@class="rust"]' \
+ // @has - '//pre[@class="rust item-decl"]' \
// 'trait IndexMut<Idx>: Index<Idx>where Idx: ?Sized,{'
- // @has - '//div[@class="item-decl"]/pre[@class="rust"]' \
+ // @has - '//pre[@class="rust item-decl"]' \
// 'fn index_mut(&mut self, index: Idx) -> &mut Self::Output;'
pub use issue_20727::IndexMut;
}
diff --git a/tests/rustdoc/issue-20727.rs b/tests/rustdoc/issue-20727.rs
index df334821c..266848bee 100644
--- a/tests/rustdoc/issue-20727.rs
+++ b/tests/rustdoc/issue-20727.rs
@@ -5,20 +5,20 @@ extern crate issue_20727;
// @has issue_20727/trait.Deref.html
pub trait Deref {
- // @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'trait Deref {'
- // @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'type Target: ?Sized;'
+ // @has - '//pre[@class="rust item-decl"]' 'trait Deref {'
+ // @has - '//pre[@class="rust item-decl"]' 'type Target: ?Sized;'
type Target: ?Sized;
- // @has - '//div[@class="item-decl"]/pre[@class="rust"]' \
+ // @has - '//pre[@class="rust item-decl"]' \
// "fn deref<'a>(&'a self) -> &'a Self::Target;"
fn deref<'a>(&'a self) -> &'a Self::Target;
}
// @has issue_20727/reexport/trait.Deref.html
pub mod reexport {
- // @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'trait Deref {'
- // @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'type Target: ?Sized;'
- // @has - '//div[@class="item-decl"]/pre[@class="rust"]' \
+ // @has - '//pre[@class="rust item-decl"]' 'trait Deref {'
+ // @has - '//pre[@class="rust item-decl"]' 'type Target: ?Sized;'
+ // @has - '//pre[@class="rust item-decl"]' \
// "fn deref<'a>(&'a self) -> &'a Self::Target;"
pub use issue_20727::Deref;
}
diff --git a/tests/rustdoc/issue-21474.rs b/tests/rustdoc/issue-21474.rs
index 43ce13fd9..5de26abac 100644
--- a/tests/rustdoc/issue-21474.rs
+++ b/tests/rustdoc/issue-21474.rs
@@ -7,5 +7,5 @@ mod inner {
pub trait Blah { }
// @count issue_21474/struct.What.html \
-// '//*[@id="trait-implementations-list"]//*[@class="impl has-srclink"]' 1
+// '//*[@id="trait-implementations-list"]//*[@class="impl"]' 1
pub struct What;
diff --git a/tests/rustdoc/issue-22038.rs b/tests/rustdoc/issue-22038.rs
index 19e626ba1..de6cc7870 100644
--- a/tests/rustdoc/issue-22038.rs
+++ b/tests/rustdoc/issue-22038.rs
@@ -1,19 +1,19 @@
extern "C" {
// @has issue_22038/fn.foo1.html \
- // '//div[@class="item-decl"]/pre[@class="rust"]' 'pub unsafe extern "C" fn foo1()'
+ // '//pre[@class="rust item-decl"]' 'pub unsafe extern "C" fn foo1()'
pub fn foo1();
}
extern "system" {
// @has issue_22038/fn.foo2.html \
- // '//div[@class="item-decl"]/pre[@class="rust"]' 'pub unsafe extern "system" fn foo2()'
+ // '//pre[@class="rust item-decl"]' 'pub unsafe extern "system" fn foo2()'
pub fn foo2();
}
// @has issue_22038/fn.bar.html \
-// '//div[@class="item-decl"]/pre[@class="rust"]' 'pub extern "C" fn bar()'
+// '//pre[@class="rust item-decl"]' 'pub extern "C" fn bar()'
pub extern "C" fn bar() {}
// @has issue_22038/fn.baz.html \
-// '//div[@class="item-decl"]/pre[@class="rust"]' 'pub extern "system" fn baz()'
+// '//pre[@class="rust item-decl"]' 'pub extern "system" fn baz()'
pub extern "system" fn baz() {}
diff --git a/tests/rustdoc/issue-32374.rs b/tests/rustdoc/issue-32374.rs
index 8d2c27cf3..985bf03a1 100644
--- a/tests/rustdoc/issue-32374.rs
+++ b/tests/rustdoc/issue-32374.rs
@@ -2,11 +2,11 @@
#![doc(issue_tracker_base_url = "https://issue_url/")]
#![unstable(feature = "test", issue = "32374")]
-// @matches issue_32374/index.html '//*[@class="item-left unstable deprecated module-item"]/span[@class="stab deprecated"]' \
+// @matches issue_32374/index.html '//*[@class="item-name"]/span[@class="stab deprecated"]' \
// 'Deprecated'
-// @matches issue_32374/index.html '//*[@class="item-left unstable deprecated module-item"]/span[@class="stab unstable"]' \
+// @matches issue_32374/index.html '//*[@class="item-name"]/span[@class="stab unstable"]' \
// 'Experimental'
-// @matches issue_32374/index.html '//*[@class="item-right docblock-short"]/text()' 'Docs'
+// @matches issue_32374/index.html '//*[@class="desc docblock-short"]/text()' 'Docs'
// @has issue_32374/struct.T.html '//*[@class="stab deprecated"]/span' '👎'
// @has issue_32374/struct.T.html '//*[@class="stab deprecated"]/span' \
diff --git a/tests/rustdoc/issue-33302.rs b/tests/rustdoc/issue-33302.rs
index b4c52e2f1..a316f3ad9 100644
--- a/tests/rustdoc/issue-33302.rs
+++ b/tests/rustdoc/issue-33302.rs
@@ -6,23 +6,23 @@ macro_rules! make {
pub struct S;
// @has issue_33302/constant.CST.html \
- // '//div[@class="item-decl"]/pre[@class="rust"]' 'pub const CST: i32'
+ // '//pre[@class="rust item-decl"]' 'pub const CST: i32'
pub const CST: i32 = ($n * $n);
// @has issue_33302/static.ST.html \
- // '//div[@class="item-decl"]/pre[@class="rust"]' 'pub static ST: i32'
+ // '//pre[@class="rust item-decl"]' 'pub static ST: i32'
pub static ST: i32 = ($n * $n);
pub trait T<X> {
fn ignore(_: &X) {}
const C: X;
// @has issue_33302/trait.T.html \
- // '//div[@class="item-decl"]/pre[@class="rust"]' 'const D: i32'
+ // '//pre[@class="rust item-decl"]' 'const D: i32'
// @has - '//*[@id="associatedconstant.D"]' 'const D: i32'
const D: i32 = ($n * $n);
}
// @has issue_33302/struct.S.html \
- // '//*[@class="impl has-srclink"]' 'impl T<[i32; 16]> for S'
+ // '//*[@class="impl"]' 'impl T<[i32; 16]> for S'
// @has - '//*[@id="associatedconstant.C"]' 'const C: [i32; 16]'
// @has - '//*[@id="associatedconstant.D"]' 'const D: i32'
impl T<[i32; ($n * $n)]> for S {
@@ -30,7 +30,7 @@ macro_rules! make {
}
// @has issue_33302/struct.S.html \
- // '//*[@class="impl has-srclink"]' 'impl T<[i32; 16]> for S'
+ // '//*[@class="impl"]' 'impl T<[i32; 16]> for S'
// @has - '//*[@id="associatedconstant.C-1"]' 'const C: (i32,)'
// @has - '//*[@id="associatedconstant.D-1"]' 'const D: i32'
impl T<(i32,)> for S {
@@ -38,7 +38,7 @@ macro_rules! make {
}
// @has issue_33302/struct.S.html \
- // '//*[@class="impl has-srclink"]' 'impl T<(i32, i32)> for S'
+ // '//*[@class="impl"]' 'impl T<(i32, i32)> for S'
// @has - '//*[@id="associatedconstant.C-2"]' 'const C: (i32, i32)'
// @has - '//*[@id="associatedconstant.D-2"]' 'const D: i32'
impl T<(i32, i32)> for S {
diff --git a/tests/rustdoc/issue-34928.rs b/tests/rustdoc/issue-34928.rs
index 91b677574..4184086f6 100644
--- a/tests/rustdoc/issue-34928.rs
+++ b/tests/rustdoc/issue-34928.rs
@@ -2,5 +2,5 @@
pub trait Bar {}
-// @has foo/struct.Foo.html '//pre' 'pub struct Foo<T>(pub T)where T: Bar;'
+// @has foo/struct.Foo.html '//pre' 'pub struct Foo<T>(pub T) where T: Bar;'
pub struct Foo<T>(pub T) where T: Bar;
diff --git a/tests/rustdoc/issue-45584.rs b/tests/rustdoc/issue-45584.rs
index 86479e6fb..8a5f04138 100644
--- a/tests/rustdoc/issue-45584.rs
+++ b/tests/rustdoc/issue-45584.rs
@@ -4,12 +4,12 @@ pub trait Bar<T, U> {}
// @has 'foo/struct.Foo1.html'
pub struct Foo1;
-// @count - '//*[@id="trait-implementations-list"]//*[@class="impl has-srclink"]' 1
-// @has - '//*[@class="impl has-srclink"]' "impl Bar<Foo1, &'static Foo1> for Foo1"
+// @count - '//*[@id="trait-implementations-list"]//*[@class="impl"]' 1
+// @has - '//*[@class="impl"]' "impl Bar<Foo1, &'static Foo1> for Foo1"
impl Bar<Foo1, &'static Foo1> for Foo1 {}
// @has 'foo/struct.Foo2.html'
pub struct Foo2;
-// @count - '//*[@id="trait-implementations-list"]//*[@class="impl has-srclink"]' 1
-// @has - '//*[@class="impl has-srclink"]' "impl Bar<&'static Foo2, Foo2> for u8"
+// @count - '//*[@id="trait-implementations-list"]//*[@class="impl"]' 1
+// @has - '//*[@class="impl"]' "impl Bar<&'static Foo2, Foo2> for u8"
impl Bar<&'static Foo2, Foo2> for u8 {}
diff --git a/tests/rustdoc/issue-46377.rs b/tests/rustdoc/issue-46377.rs
index 4489f038c..1311b4721 100644
--- a/tests/rustdoc/issue-46377.rs
+++ b/tests/rustdoc/issue-46377.rs
@@ -1,3 +1,3 @@
-// @has 'issue_46377/index.html' '//*[@class="item-right docblock-short"]' 'Check out this struct!'
+// @has 'issue_46377/index.html' '//*[@class="desc docblock-short"]' 'Check out this struct!'
/// # Check out this struct!
pub struct SomeStruct;
diff --git a/tests/rustdoc/issue-50159.rs b/tests/rustdoc/issue-50159.rs
index 04bc4f304..13bedd5db 100644
--- a/tests/rustdoc/issue-50159.rs
+++ b/tests/rustdoc/issue-50159.rs
@@ -14,7 +14,7 @@ impl<B, C> Signal2 for B where B: Signal<Item = C> {
// @has - '//h3[@class="code-header"]' 'impl<B> Send for Switch<B>where <B as Signal>::Item: Send'
// @has - '//h3[@class="code-header"]' 'impl<B> Sync for Switch<B>where <B as Signal>::Item: Sync'
// @count - '//*[@id="implementations-list"]//*[@class="impl"]' 0
-// @count - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]' 5
+// @count - '//*[@id="synthetic-implementations-list"]//*[@class="impl"]' 5
pub struct Switch<B: Signal> {
pub inner: <B as Signal2>::Item2,
}
diff --git a/tests/rustdoc/issue-51236.rs b/tests/rustdoc/issue-51236.rs
index 1c7aa9c7e..04664805a 100644
--- a/tests/rustdoc/issue-51236.rs
+++ b/tests/rustdoc/issue-51236.rs
@@ -7,7 +7,7 @@ pub mod traits {
}
// @has issue_51236/struct.Owned.html
-// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header"]' \
+// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl"]//h3[@class="code-header"]' \
// "impl<T> Send for Owned<T>where <T as Owned<'static>>::Reader: Send"
pub struct Owned<T> where T: for<'a> ::traits::Owned<'a> {
marker: PhantomData<<T as ::traits::Owned<'static>>::Reader>,
diff --git a/tests/rustdoc/issue-53812.rs b/tests/rustdoc/issue-53812.rs
index c68ffd521..dc1eb304c 100644
--- a/tests/rustdoc/issue-53812.rs
+++ b/tests/rustdoc/issue-53812.rs
@@ -12,9 +12,9 @@ macro_rules! array_impls {
}
// @has issue_53812/trait.MyIterator.html
-// @has - '//*[@id="implementors-list"]/*[@class="impl has-srclink"][1]' 'MyStruct<[T; 0]>'
-// @has - '//*[@id="implementors-list"]/*[@class="impl has-srclink"][2]' 'MyStruct<[T; 1]>'
-// @has - '//*[@id="implementors-list"]/*[@class="impl has-srclink"][3]' 'MyStruct<[T; 2]>'
-// @has - '//*[@id="implementors-list"]/*[@class="impl has-srclink"][4]' 'MyStruct<[T; 3]>'
-// @has - '//*[@id="implementors-list"]/*[@class="impl has-srclink"][5]' 'MyStruct<[T; 10]>'
+// @has - '//*[@id="implementors-list"]/*[@class="impl"][1]' 'MyStruct<[T; 0]>'
+// @has - '//*[@id="implementors-list"]/*[@class="impl"][2]' 'MyStruct<[T; 1]>'
+// @has - '//*[@id="implementors-list"]/*[@class="impl"][3]' 'MyStruct<[T; 2]>'
+// @has - '//*[@id="implementors-list"]/*[@class="impl"][4]' 'MyStruct<[T; 3]>'
+// @has - '//*[@id="implementors-list"]/*[@class="impl"][5]' 'MyStruct<[T; 10]>'
array_impls! { 10 3 2 1 0 }
diff --git a/tests/rustdoc/issue-54705.rs b/tests/rustdoc/issue-54705.rs
index 7b7290ab4..a886eb0de 100644
--- a/tests/rustdoc/issue-54705.rs
+++ b/tests/rustdoc/issue-54705.rs
@@ -1,10 +1,10 @@
pub trait ScopeHandle<'scope> {}
// @has issue_54705/struct.ScopeFutureContents.html
-// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header"]' \
+// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl"]//h3[@class="code-header"]' \
// "impl<'scope, S> Send for ScopeFutureContents<'scope, S>where S: Sync"
//
-// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header"]' \
+// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl"]//h3[@class="code-header"]' \
// "impl<'scope, S> Sync for ScopeFutureContents<'scope, S>where S: Sync"
pub struct ScopeFutureContents<'scope, S>
where S: ScopeHandle<'scope>,
diff --git a/tests/rustdoc/issue-55321.rs b/tests/rustdoc/issue-55321.rs
index 22a18ef90..d3c2070d9 100644
--- a/tests/rustdoc/issue-55321.rs
+++ b/tests/rustdoc/issue-55321.rs
@@ -1,9 +1,9 @@
#![feature(negative_impls)]
// @has issue_55321/struct.A.html
-// @has - '//*[@id="trait-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header"]' \
+// @has - '//*[@id="trait-implementations-list"]//*[@class="impl"]//h3[@class="code-header"]' \
// "impl !Send for A"
-// @has - '//*[@id="trait-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header"]' \
+// @has - '//*[@id="trait-implementations-list"]//*[@class="impl"]//h3[@class="code-header"]' \
// "impl !Sync for A"
pub struct A();
@@ -11,8 +11,8 @@ impl !Send for A {}
impl !Sync for A {}
// @has issue_55321/struct.B.html
-// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header"]' \
+// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl"]//h3[@class="code-header"]' \
// "impl<T> !Send for B<T>"
-// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header"]' \
+// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl"]//h3[@class="code-header"]' \
// "impl<T> !Sync for B<T>"
pub struct B<T: ?Sized>(A, Box<T>);
diff --git a/tests/rustdoc/issue-55364.rs b/tests/rustdoc/issue-55364.rs
index 14a6f5041..941cb3ce1 100644
--- a/tests/rustdoc/issue-55364.rs
+++ b/tests/rustdoc/issue-55364.rs
@@ -29,8 +29,8 @@ pub mod subone {
// @has - '//section[@id="main-content"]/details/div[@class="docblock"]//a[@href="../fn.foo.html"]' 'foo'
// @has - '//section[@id="main-content"]/details/div[@class="docblock"]//a[@href="../fn.bar.html"]' 'bar'
// Though there should be such links later
-// @has - '//section[@id="main-content"]/div[@class="item-table"]//div[@class="item-left module-item"]/a[@class="fn"][@href="fn.foo.html"]' 'foo'
-// @has - '//section[@id="main-content"]/div[@class="item-table"]//div[@class="item-left module-item"]/a[@class="fn"][@href="fn.bar.html"]' 'bar'
+// @has - '//section[@id="main-content"]/ul[@class="item-table"]//div[@class="item-name"]/a[@class="fn"][@href="fn.foo.html"]' 'foo'
+// @has - '//section[@id="main-content"]/ul[@class="item-table"]//div[@class="item-name"]/a[@class="fn"][@href="fn.bar.html"]' 'bar'
/// See either [foo] or [bar].
pub mod subtwo {
@@ -68,8 +68,8 @@ pub mod subthree {
// Next we go *deeper* - In order to ensure it's not just "this or parent"
// we test `crate::` and a `super::super::...` chain
// @has issue_55364/subfour/subfive/subsix/subseven/subeight/index.html
-// @has - '//section[@id="main-content"]/div[@class="item-table"]//div[@class="item-right docblock-short"]//a[@href="../../../../../subone/fn.foo.html"]' 'other foo'
-// @has - '//section[@id="main-content"]/div[@class="item-table"]//div[@class="item-right docblock-short"]//a[@href="../../../../../subtwo/fn.bar.html"]' 'other bar'
+// @has - '//section[@id="main-content"]/ul[@class="item-table"]//div[@class="desc docblock-short"]//a[@href="../../../../../subone/fn.foo.html"]' 'other foo'
+// @has - '//section[@id="main-content"]/ul[@class="item-table"]//div[@class="desc docblock-short"]//a[@href="../../../../../subtwo/fn.bar.html"]' 'other bar'
pub mod subfour {
pub mod subfive {
pub mod subsix {
diff --git a/tests/rustdoc/issue-56822.rs b/tests/rustdoc/issue-56822.rs
index b4eef344b..c9a743357 100644
--- a/tests/rustdoc/issue-56822.rs
+++ b/tests/rustdoc/issue-56822.rs
@@ -17,7 +17,7 @@ impl<'a, T> MyTrait for Inner<'a, T> {
}
// @has issue_56822/struct.Parser.html
-// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header"]' \
+// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl"]//h3[@class="code-header"]' \
// "impl<'a> Send for Parser<'a>"
pub struct Parser<'a> {
field: <Wrapper<Inner<'a, u8>> as MyTrait>::Output
diff --git a/tests/rustdoc/issue-60726.rs b/tests/rustdoc/issue-60726.rs
index fbb0f82ae..e337e4a4f 100644
--- a/tests/rustdoc/issue-60726.rs
+++ b/tests/rustdoc/issue-60726.rs
@@ -26,9 +26,9 @@ where
{}
// @has issue_60726/struct.IntoIter.html
-// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header"]' \
+// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl"]//h3[@class="code-header"]' \
// "impl<T> !Send for IntoIter<T>"
-// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header"]' \
+// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl"]//h3[@class="code-header"]' \
// "impl<T> !Sync for IntoIter<T>"
pub struct IntoIter<T>{
hello:DynTrait<FooInterface<T>>,
diff --git a/tests/rustdoc/issue-76501.rs b/tests/rustdoc/issue-76501.rs
index a90e0fea0..5caea0ec9 100644
--- a/tests/rustdoc/issue-76501.rs
+++ b/tests/rustdoc/issue-76501.rs
@@ -8,7 +8,7 @@ pub const fn bloop() -> i32 {
pub struct Struct {}
impl Struct {
- // @has 'issue_76501/struct.Struct.html' '//*[@class="method has-srclink"]' \
+ // @has 'issue_76501/struct.Struct.html' '//*[@class="method"]' \
// 'pub const fn blurp() -> i32'
/// A useless function that always returns 1.
pub const fn blurp() -> i32 {
diff --git a/tests/rustdoc/issue-78673.rs b/tests/rustdoc/issue-78673.rs
index 2e4bec254..d09141c32 100644
--- a/tests/rustdoc/issue-78673.rs
+++ b/tests/rustdoc/issue-78673.rs
@@ -7,8 +7,8 @@ pub trait AnAmazingTrait {}
impl<T: Something> AnAmazingTrait for T {}
// @has 'issue_78673/struct.MyStruct.html'
-// @has - '//*[@class="impl has-srclink"]' 'AnAmazingTrait for MyStruct'
-// @!has - '//*[@class="impl has-srclink"]' 'AnAmazingTrait for T'
+// @has - '//*[@class="impl"]' 'AnAmazingTrait for MyStruct'
+// @!has - '//*[@class="impl"]' 'AnAmazingTrait for T'
pub struct MyStruct;
impl AnAmazingTrait for MyStruct {}
@@ -16,8 +16,8 @@ impl AnAmazingTrait for MyStruct {}
// generic structs may have _both_ specific and blanket impls that apply
// @has 'issue_78673/struct.AnotherStruct.html'
-// @has - '//*[@class="impl has-srclink"]' 'AnAmazingTrait for AnotherStruct<()>'
-// @has - '//*[@class="impl has-srclink"]' 'AnAmazingTrait for T'
+// @has - '//*[@class="impl"]' 'AnAmazingTrait for AnotherStruct<()>'
+// @has - '//*[@class="impl"]' 'AnAmazingTrait for T'
pub struct AnotherStruct<T>(T);
impl<T: Something> Something for AnotherStruct<T> {}
diff --git a/tests/rustdoc/issue-83375-multiple-mods-w-same-name-doc-inline-last-item.rs b/tests/rustdoc/issue-83375-multiple-mods-w-same-name-doc-inline-last-item.rs
index d3a7a870b..9bce25846 100644
--- a/tests/rustdoc/issue-83375-multiple-mods-w-same-name-doc-inline-last-item.rs
+++ b/tests/rustdoc/issue-83375-multiple-mods-w-same-name-doc-inline-last-item.rs
@@ -11,6 +11,6 @@ pub mod sub {
#[doc(inline)]
pub use sub::*;
-// @count foo/index.html '//a[@class="mod"][@title="foo::prelude mod"]' 1
+// @count foo/index.html '//a[@class="mod"][@title="mod foo::prelude"]' 1
// @count foo/prelude/index.html '//div[@class="item-row"]' 0
pub mod prelude {}
diff --git a/tests/rustdoc/issue-83375-multiple-mods-w-same-name-doc-inline.rs b/tests/rustdoc/issue-83375-multiple-mods-w-same-name-doc-inline.rs
index b83692509..d0960dfef 100644
--- a/tests/rustdoc/issue-83375-multiple-mods-w-same-name-doc-inline.rs
+++ b/tests/rustdoc/issue-83375-multiple-mods-w-same-name-doc-inline.rs
@@ -8,7 +8,7 @@ pub mod sub {
}
}
-// @count foo/index.html '//a[@class="mod"][@title="foo::prelude mod"]' 1
+// @count foo/index.html '//a[@class="mod"][@title="mod foo::prelude"]' 1
// @count foo/prelude/index.html '//div[@class="item-row"]' 0
pub mod prelude {}
diff --git a/tests/rustdoc/issue-85454.rs b/tests/rustdoc/issue-85454.rs
index 74fc22b31..5a49a9d06 100644
--- a/tests/rustdoc/issue-85454.rs
+++ b/tests/rustdoc/issue-85454.rs
@@ -5,7 +5,7 @@
extern crate issue_85454;
// @has foo/trait.FromResidual.html
-// @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'pub trait FromResidual<R = <Self as Try>::Residual> { fn from_residual(residual: R) -> Self; }'
+// @has - '//pre[@class="rust item-decl"]' 'pub trait FromResidual<R = <Self as Try>::Residual> { // Required method fn from_residual(residual: R) -> Self; }'
pub trait FromResidual<R = <Self as Try>::Residual> {
fn from_residual(residual: R) -> Self;
}
@@ -24,6 +24,6 @@ pub enum ControlFlow<B, C = ()> {
pub mod reexport {
// @has foo/reexport/trait.FromResidual.html
- // @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'pub trait FromResidual<R = <Self as Try>::Residual> { fn from_residual(residual: R) -> Self; }'
+ // @has - '//pre[@class="rust item-decl"]' 'pub trait FromResidual<R = <Self as Try>::Residual> { // Required method fn from_residual(residual: R) -> Self; }'
pub use issue_85454::*;
}
diff --git a/tests/rustdoc/issue-95873.rs b/tests/rustdoc/issue-95873.rs
index ff33fb63a..83f1f2f75 100644
--- a/tests/rustdoc/issue-95873.rs
+++ b/tests/rustdoc/issue-95873.rs
@@ -1,2 +1,2 @@
-// @has issue_95873/index.html "//*[@class='item-left import-item']" "pub use ::std as x;"
+// @has issue_95873/index.html "//*[@class='item-name']" "pub use ::std as x;"
pub use ::std as x;
diff --git a/tests/rustdoc/issue-98697.rs b/tests/rustdoc/issue-98697.rs
index 884b63ac9..5d5aee1fe 100644
--- a/tests/rustdoc/issue-98697.rs
+++ b/tests/rustdoc/issue-98697.rs
@@ -8,8 +8,8 @@
extern crate issue_98697_reexport_with_anonymous_lifetime;
-// @has issue_98697/fn.repro.html '//div[@class="item-decl"]/pre[@class="rust"]/code' 'fn repro<F>()where F: Fn(&str)'
-// @!has issue_98697/fn.repro.html '//div[@class="item-decl"]/pre[@class="rust"]/code' 'for<'
+// @has issue_98697/fn.repro.html '//pre[@class="rust item-decl"]/code' 'fn repro<F>()where F: Fn(&str)'
+// @!has issue_98697/fn.repro.html '//pre[@class="rust item-decl"]/code' 'for<'
pub use issue_98697_reexport_with_anonymous_lifetime::repro;
// @has issue_98697/struct.Extra.html '//div[@id="trait-implementations-list"]//h3[@class="code-header"]' 'impl MyTrait<&Extra> for Extra'
diff --git a/tests/rustdoc/issue-99221-multiple-structs-w-same-name.rs b/tests/rustdoc/issue-99221-multiple-structs-w-same-name.rs
index 41e64726a..ba29a77eb 100644
--- a/tests/rustdoc/issue-99221-multiple-structs-w-same-name.rs
+++ b/tests/rustdoc/issue-99221-multiple-structs-w-same-name.rs
@@ -9,6 +9,6 @@ extern crate issue_99221_aux;
pub use issue_99221_aux::*;
-// @count foo/index.html '//a[@class="struct"][@title="foo::Print struct"]' 1
+// @count foo/index.html '//a[@class="struct"][@title="struct foo::Print"]' 1
pub struct Print;
diff --git a/tests/rustdoc/issue-99734-multiple-foreigns-w-same-name.rs b/tests/rustdoc/issue-99734-multiple-foreigns-w-same-name.rs
index 3208fea05..b56ec6e11 100644
--- a/tests/rustdoc/issue-99734-multiple-foreigns-w-same-name.rs
+++ b/tests/rustdoc/issue-99734-multiple-foreigns-w-same-name.rs
@@ -9,7 +9,7 @@ extern crate issue_99734_aux;
pub use issue_99734_aux::*;
-// @count foo/index.html '//a[@class="fn"][@title="foo::main fn"]' 1
+// @count foo/index.html '//a[@class="fn"][@title="fn foo::main"]' 1
extern "C" {
pub fn main() -> std::ffi::c_int;
diff --git a/tests/rustdoc/issue-99734-multiple-mods-w-same-name.rs b/tests/rustdoc/issue-99734-multiple-mods-w-same-name.rs
index b2f9b8b46..8f5d6fa3d 100644
--- a/tests/rustdoc/issue-99734-multiple-mods-w-same-name.rs
+++ b/tests/rustdoc/issue-99734-multiple-mods-w-same-name.rs
@@ -9,6 +9,6 @@ extern crate issue_99734_aux;
pub use issue_99734_aux::*;
-// @count foo/index.html '//a[@class="mod"][@title="foo::task mod"]' 1
+// @count foo/index.html '//a[@class="mod"][@title="mod foo::task"]' 1
pub mod task {}
diff --git a/tests/rustdoc/item-desc-list-at-start.item-table.html b/tests/rustdoc/item-desc-list-at-start.item-table.html
new file mode 100644
index 000000000..72bde573c
--- /dev/null
+++ b/tests/rustdoc/item-desc-list-at-start.item-table.html
@@ -0,0 +1 @@
+<ul class="item-table"><li><div class="item-name"><a class="constant" href="constant.MY_CONSTANT.html" title="constant item_desc_list_at_start::MY_CONSTANT">MY_CONSTANT</a></div><div class="desc docblock-short">Groups: <code>SamplePatternSGIS</code>, <code>SamplePatternEXT</code></div></li></ul> \ No newline at end of file
diff --git a/tests/rustdoc/item-desc-list-at-start.rs b/tests/rustdoc/item-desc-list-at-start.rs
new file mode 100644
index 000000000..d88c61d33
--- /dev/null
+++ b/tests/rustdoc/item-desc-list-at-start.rs
@@ -0,0 +1,9 @@
+// @has item_desc_list_at_start/index.html
+// @count - '//ul[@class="item-table"]/li/div/li' 0
+// @count - '//ul[@class="item-table"]/li' 1
+// @snapshot item-table - '//ul[@class="item-table"]'
+
+// based on https://docs.rs/gl_constants/0.1.1/src/gl_constants/lib.rs.html#16
+
+/// * Groups: `SamplePatternSGIS`, `SamplePatternEXT`
+pub const MY_CONSTANT: usize = 0;
diff --git a/tests/rustdoc/legacy-const-generic.rs b/tests/rustdoc/legacy-const-generic.rs
index 14533624e..3a488bdd2 100644
--- a/tests/rustdoc/legacy-const-generic.rs
+++ b/tests/rustdoc/legacy-const-generic.rs
@@ -2,14 +2,14 @@
#![feature(rustc_attrs)]
// @has 'foo/fn.foo.html'
-// @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'fn foo(x: usize, const Y: usize, z: usize) -> [usize; 3]'
+// @has - '//pre[@class="rust item-decl"]' 'fn foo(x: usize, const Y: usize, z: usize) -> [usize; 3]'
#[rustc_legacy_const_generics(1)]
pub fn foo<const Y: usize>(x: usize, z: usize) -> [usize; 3] {
[x, Y, z]
}
// @has 'foo/fn.bar.html'
-// @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'fn bar(x: usize, const Y: usize, const Z: usize) -> [usize; 3]'
+// @has - '//pre[@class="rust item-decl"]' 'fn bar(x: usize, const Y: usize, const Z: usize) -> [usize; 3]'
#[rustc_legacy_const_generics(1, 2)]
pub fn bar<const Y: usize, const Z: usize>(x: usize) -> [usize; 3] {
[x, Y, z]
diff --git a/tests/rustdoc/lifetime-name.rs b/tests/rustdoc/lifetime-name.rs
index 0fb660591..15e09f516 100644
--- a/tests/rustdoc/lifetime-name.rs
+++ b/tests/rustdoc/lifetime-name.rs
@@ -1,5 +1,5 @@
#![crate_name = "foo"]
// @has 'foo/type.Resolutions.html'
-// @has - '//div[@class="item-decl"]/pre[@class="rust"]' "pub type Resolutions<'tcx> = &'tcx u8;"
+// @has - '//pre[@class="rust item-decl"]' "pub type Resolutions<'tcx> = &'tcx u8;"
pub type Resolutions<'tcx> = &'tcx u8;
diff --git a/tests/rustdoc/macro-higher-kinded-function.rs b/tests/rustdoc/macro-higher-kinded-function.rs
index b8c52b7b7..a45ef37a7 100644
--- a/tests/rustdoc/macro-higher-kinded-function.rs
+++ b/tests/rustdoc/macro-higher-kinded-function.rs
@@ -11,8 +11,8 @@ macro_rules! gen {
}
// @has 'foo/struct.Providers.html'
-// @has - '//*[@class="item-decl"]//code' "pub a: for<'tcx> fn(_: TyCtxt<'tcx>, _: u8) -> i8,"
-// @has - '//*[@class="item-decl"]//code' "pub b: for<'tcx> fn(_: TyCtxt<'tcx>, _: u16) -> i16,"
+// @has - '//*[@class="rust item-decl"]//code' "pub a: for<'tcx> fn(_: TyCtxt<'tcx>, _: u8) -> i8,"
+// @has - '//*[@class="rust item-decl"]//code' "pub b: for<'tcx> fn(_: TyCtxt<'tcx>, _: u16) -> i16,"
// @has - '//*[@id="structfield.a"]/code' "a: for<'tcx> fn(_: TyCtxt<'tcx>, _: u8) -> i8"
// @has - '//*[@id="structfield.b"]/code' "b: for<'tcx> fn(_: TyCtxt<'tcx>, _: u16) -> i16"
gen! {
diff --git a/tests/rustdoc/markdown-summaries.rs b/tests/rustdoc/markdown-summaries.rs
deleted file mode 100644
index 31e7072b5..000000000
--- a/tests/rustdoc/markdown-summaries.rs
+++ /dev/null
@@ -1,27 +0,0 @@
-#![crate_type = "lib"]
-#![crate_name = "summaries"]
-
-//! This *summary* has a [link] and `code`.
-//!
-//! This is the second paragraph.
-//!
-//! [link]: https://example.com
-
-// @hasraw search-index.js 'This <em>summary</em> has a link and <code>code</code>.'
-// @!hasraw - 'second paragraph'
-
-/// This `code` will be rendered in a code tag.
-///
-/// This text should not be rendered.
-pub struct Sidebar;
-
-// @hasraw search-index.js 'This <code>code</code> will be rendered in a code tag.'
-// @hasraw summaries/sidebar-items.js 'This `code` will be rendered in a code tag.'
-// @!hasraw - 'text should not be rendered'
-
-/// ```text
-/// this block should not be rendered
-/// ```
-pub struct Sidebar2;
-
-// @!hasraw summaries/sidebar-items.js 'block should not be rendered'
diff --git a/tests/rustdoc/mut-params.rs b/tests/rustdoc/mut-params.rs
index 3b862e651..e403b7b78 100644
--- a/tests/rustdoc/mut-params.rs
+++ b/tests/rustdoc/mut-params.rs
@@ -5,7 +5,7 @@
pub struct Foo;
-// @count foo/struct.Foo.html '//*[@class="impl-items"]//*[@class="method has-srclink"]' 2
+// @count foo/struct.Foo.html '//*[@class="impl-items"]//*[@class="method"]' 2
// @!has - '//*[@class="impl-items"]//*[@class="method"]' 'mut'
impl Foo {
pub fn foo(mut self) {}
@@ -13,6 +13,6 @@ impl Foo {
pub fn bar(mut bar: ()) {}
}
-// @count foo/fn.baz.html '//div[@class="item-decl"]/pre[@class="rust"]' 1
-// @!has - '//div[@class="item-decl"]/pre[@class="rust"]' 'mut'
+// @count foo/fn.baz.html '//pre[@class="rust item-decl"]' 1
+// @!has - '//pre[@class="rust item-decl"]' 'mut'
pub fn baz(mut foo: Foo) {}
diff --git a/tests/rustdoc/negative-impl.rs b/tests/rustdoc/negative-impl.rs
index af19c784d..51223af67 100644
--- a/tests/rustdoc/negative-impl.rs
+++ b/tests/rustdoc/negative-impl.rs
@@ -5,10 +5,10 @@ pub struct Alpha;
// @matches negative_impl/struct.Bravo.html '//pre' "pub struct Bravo<B>"
pub struct Bravo<B>(B);
-// @matches negative_impl/struct.Alpha.html '//*[@class="impl has-srclink"]//h3[@class="code-header"]' \
+// @matches negative_impl/struct.Alpha.html '//*[@class="impl"]//h3[@class="code-header"]' \
// "impl !Send for Alpha"
impl !Send for Alpha {}
-// @matches negative_impl/struct.Bravo.html '//*[@class="impl has-srclink"]//h3[@class="code-header"]' "\
+// @matches negative_impl/struct.Bravo.html '//*[@class="impl"]//h3[@class="code-header"]' "\
// impl<B> !Send for Bravo<B>"
impl<B> !Send for Bravo<B> {}
diff --git a/tests/rustdoc/normalize-assoc-item.rs b/tests/rustdoc/normalize-assoc-item.rs
index 659480479..af7b2f955 100644
--- a/tests/rustdoc/normalize-assoc-item.rs
+++ b/tests/rustdoc/normalize-assoc-item.rs
@@ -19,12 +19,12 @@ impl Trait for isize {
type X = <() as Trait>::X;
}
-// @has 'normalize_assoc_item/fn.f.html' '//div[@class="item-decl"]/pre[@class="rust"]' 'pub fn f() -> isize'
+// @has 'normalize_assoc_item/fn.f.html' '//pre[@class="rust item-decl"]' 'pub fn f() -> isize'
pub fn f() -> <usize as Trait>::X {
0
}
-// @has 'normalize_assoc_item/fn.f2.html' '//div[@class="item-decl"]/pre[@class="rust"]' 'pub fn f2() -> fn() -> i32'
+// @has 'normalize_assoc_item/fn.f2.html' '//pre[@class="rust item-decl"]' 'pub fn f2() -> fn() -> i32'
pub fn f2() -> <isize as Trait>::X {
todo!()
}
@@ -49,10 +49,10 @@ impl<Inner: Trait> Trait for Generic<Inner> {
// These can't be normalized because they depend on a generic parameter.
// However the user can choose whether the text should be displayed as `Inner::X` or `<Inner as Trait>::X`.
-// @has 'normalize_assoc_item/struct.Unknown.html' '//div[@class="item-decl"]/pre[@class="rust"]' 'pub struct Unknown<Inner: Trait>(pub <Inner as Trait>::X);'
+// @has 'normalize_assoc_item/struct.Unknown.html' '//pre[@class="rust item-decl"]' 'pub struct Unknown<Inner: Trait>(pub <Inner as Trait>::X);'
pub struct Unknown<Inner: Trait>(pub <Inner as Trait>::X);
-// @has 'normalize_assoc_item/struct.Unknown2.html' '//div[@class="item-decl"]/pre[@class="rust"]' 'pub struct Unknown2<Inner: Trait>(pub Inner::X);'
+// @has 'normalize_assoc_item/struct.Unknown2.html' '//pre[@class="rust item-decl"]' 'pub struct Unknown2<Inner: Trait>(pub Inner::X);'
pub struct Unknown2<Inner: Trait>(pub Inner::X);
trait Lifetimes<'a> {
@@ -63,20 +63,20 @@ impl<'a> Lifetimes<'a> for usize {
type Y = &'a isize;
}
-// @has 'normalize_assoc_item/fn.g.html' '//div[@class="item-decl"]/pre[@class="rust"]' "pub fn g() -> &isize"
+// @has 'normalize_assoc_item/fn.g.html' '//pre[@class="rust item-decl"]' "pub fn g() -> &isize"
pub fn g() -> <usize as Lifetimes<'static>>::Y {
&0
}
-// @has 'normalize_assoc_item/constant.A.html' '//div[@class="item-decl"]/pre[@class="rust"]' "pub const A: &isize"
+// @has 'normalize_assoc_item/constant.A.html' '//pre[@class="rust item-decl"]' "pub const A: &isize"
pub const A: <usize as Lifetimes<'static>>::Y = &0;
// test cross-crate re-exports
extern crate inner;
-// @has 'normalize_assoc_item/fn.foo.html' '//div[@class="item-decl"]/pre[@class="rust"]' "pub fn foo() -> i32"
+// @has 'normalize_assoc_item/fn.foo.html' '//pre[@class="rust item-decl"]' "pub fn foo() -> i32"
pub use inner::foo;
-// @has 'normalize_assoc_item/fn.h.html' '//div[@class="item-decl"]/pre[@class="rust"]' "pub fn h<T>() -> IntoIter<T, Global>"
+// @has 'normalize_assoc_item/fn.h.html' '//pre[@class="rust item-decl"]' "pub fn h<T>() -> IntoIter<T, Global>"
pub fn h<T>() -> <Vec<T> as IntoIterator>::IntoIter {
vec![].into_iter()
}
diff --git a/tests/rustdoc/playground-arg.rs b/tests/rustdoc/playground-arg.rs
index 69c896265..f3811fe0b 100644
--- a/tests/rustdoc/playground-arg.rs
+++ b/tests/rustdoc/playground-arg.rs
@@ -10,4 +10,4 @@
pub fn dummy() {}
// ensure that `extern crate foo;` was inserted into code snips automatically:
-// @matches foo/index.html '//a[@class="test-arrow"][@href="https://example.com/?code=%23!%5Ballow(unused)%5D%0Aextern%20crate%20r%23foo%3B%0Afn%20main()%20%7B%0Ause%20foo%3A%3Adummy%3B%0Adummy()%3B%0A%7D&edition=2015"]' "Run"
+// @matches foo/index.html '//a[@class="test-arrow"][@href="https://example.com/?code=%23!%5Ballow(unused)%5D%0Aextern+crate+r%23foo;%0Afn+main()+%7B%0Ause+foo::dummy;%0Adummy();%0A%7D&edition=2015"]' "Run"
diff --git a/tests/rustdoc/playground.rs b/tests/rustdoc/playground.rs
index 877ea1cfb..5c7fa33ef 100644
--- a/tests/rustdoc/playground.rs
+++ b/tests/rustdoc/playground.rs
@@ -22,6 +22,6 @@
//! }
//! ```
-// @matches foo/index.html '//a[@class="test-arrow"][@href="https://www.example.com/?code=%23!%5Ballow(unused)%5D%0Afn%20main()%20%7B%0A%20%20%20%20println!(%22Hello%2C%20world!%22)%3B%0A%7D&edition=2015"]' "Run"
-// @matches foo/index.html '//a[@class="test-arrow"][@href="https://www.example.com/?code=%23!%5Ballow(unused)%5D%0Afn%20main()%20%7B%0Aprintln!(%22Hello%2C%20world!%22)%3B%0A%7D&edition=2015"]' "Run"
-// @matches foo/index.html '//a[@class="test-arrow"][@href="https://www.example.com/?code=%23!%5Ballow(unused)%5D%0A%23!%5Bfeature(something)%5D%0A%0Afn%20main()%20%7B%0A%20%20%20%20println!(%22Hello%2C%20world!%22)%3B%0A%7D&version=nightly&edition=2015"]' "Run"
+// @matches foo/index.html '//a[@class="test-arrow"][@href="https://www.example.com/?code=%23!%5Ballow(unused)%5D%0Afn+main()+%7B%0Aprintln!(%22Hello,+world!%22);%0A%7D&edition=2015"]' "Run"
+// @matches foo/index.html '//a[@class="test-arrow"][@href="https://www.example.com/?code=%23!%5Ballow(unused)%5D%0Afn+main()+%7B%0A++++println!(%22Hello,+world!%22);%0A%7D&edition=2015"]' "Run"
+// @matches foo/index.html '//a[@class="test-arrow"][@href="https://www.example.com/?code=%23!%5Ballow(unused)%5D%0A%23!%5Bfeature(something)%5D%0A%0Afn+main()+%7B%0A++++println!(%22Hello,+world!%22);%0A%7D&version=nightly&edition=2015"]' "Run"
diff --git a/tests/rustdoc/primitive-reference.rs b/tests/rustdoc/primitive-reference.rs
index c3a5eb6d3..10efbefd2 100644
--- a/tests/rustdoc/primitive-reference.rs
+++ b/tests/rustdoc/primitive-reference.rs
@@ -13,7 +13,7 @@
// @has - '//section[@id="main-content"]//div[@class="docblock"]//p' 'this is a test!'
// There should be only one implementation listed.
-// @count - '//*[@class="impl has-srclink"]' 1
+// @count - '//*[@class="impl"]' 1
// @has - '//*[@id="impl-Foo%3C%26A%3E-for-%26B"]/*[@class="code-header"]' \
// 'impl<A, B> Foo<&A> for &B'
#[doc(primitive = "reference")]
diff --git a/tests/rustdoc/primitive-tuple-variadic.rs b/tests/rustdoc/primitive-tuple-variadic.rs
index db7cfd60c..846028bbb 100644
--- a/tests/rustdoc/primitive-tuple-variadic.rs
+++ b/tests/rustdoc/primitive-tuple-variadic.rs
@@ -6,13 +6,13 @@
pub trait Foo {}
// @has foo/trait.Foo.html
-// @has - '//section[@id="impl-Foo-for-(T%2C)"]/h3' 'impl<T> Foo for (T₁, T₂, …, Tₙ)'
+// @has - '//section[@id="impl-Foo-for-(T,)"]/h3' 'impl<T> Foo for (T₁, T₂, …, Tₙ)'
#[doc(fake_variadic)]
impl<T> Foo for (T,) {}
pub trait Bar {}
// @has foo/trait.Bar.html
-// @has - '//section[@id="impl-Bar-for-(U%2C)"]/h3' 'impl<U: Foo> Bar for (U₁, U₂, …, Uₙ)'
+// @has - '//section[@id="impl-Bar-for-(U,)"]/h3' 'impl<U: Foo> Bar for (U₁, U₂, …, Uₙ)'
#[doc(fake_variadic)]
impl<U: Foo> Bar for (U,) {}
diff --git a/tests/rustdoc/pub-method.rs b/tests/rustdoc/pub-method.rs
index 0dca3f672..ea4791579 100644
--- a/tests/rustdoc/pub-method.rs
+++ b/tests/rustdoc/pub-method.rs
@@ -3,15 +3,15 @@
#![crate_name = "foo"]
// @has foo/fn.bar.html
-// @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'pub fn bar() -> '
+// @has - '//pre[@class="rust item-decl"]' 'pub fn bar() -> '
/// foo
pub fn bar() -> usize {
2
}
// @has foo/struct.Foo.html
-// @has - '//*[@class="method has-srclink"]' 'pub fn new()'
-// @has - '//*[@class="method has-srclink"]' 'fn not_pub()'
+// @has - '//*[@class="method"]' 'pub fn new()'
+// @has - '//*[@class="method"]' 'fn not_pub()'
pub struct Foo(usize);
impl Foo {
diff --git a/tests/rustdoc/range-arg-pattern.rs b/tests/rustdoc/range-arg-pattern.rs
index bdbcc47c9..d0d9111bb 100644
--- a/tests/rustdoc/range-arg-pattern.rs
+++ b/tests/rustdoc/range-arg-pattern.rs
@@ -1,5 +1,5 @@
#![crate_name = "foo"]
// @has foo/fn.f.html
-// @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'pub fn f(_: u8)'
+// @has - '//pre[@class="rust item-decl"]' 'pub fn f(_: u8)'
pub fn f(0u8..=255: u8) {}
diff --git a/tests/rustdoc/redirect.rs b/tests/rustdoc/redirect.rs
index e3a14c7a7..5b7a76e1a 100644
--- a/tests/rustdoc/redirect.rs
+++ b/tests/rustdoc/redirect.rs
@@ -9,9 +9,10 @@ pub trait Foo {}
// @has redirect/index.html
// @has - '//code' 'pub use reexp_stripped::Bar'
// @has - '//code/a' 'Bar'
+// @has - '//a[@href="../reexp_stripped/hidden/struct.Bar.html"]' 'Bar'
// @has reexp_stripped/hidden/struct.Bar.html
-// @has - '//p/a' '../../reexp_stripped/struct.Bar.html'
// @has 'reexp_stripped/struct.Bar.html'
+// @has - '//a[@href="struct.Bar.html"]' 'Bar'
#[doc(no_inline)]
pub use reexp_stripped::Bar;
impl Foo for Bar {}
diff --git a/tests/rustdoc/reexport-attr-merge.rs b/tests/rustdoc/reexport-attr-merge.rs
new file mode 100644
index 000000000..f6c23a136
--- /dev/null
+++ b/tests/rustdoc/reexport-attr-merge.rs
@@ -0,0 +1,33 @@
+// Regression test for <https://github.com/rust-lang/rust/issues/59368>.
+// The goal is to ensure that `doc(hidden)`, `doc(inline)` and `doc(no_inline)`
+// are not copied from an item when inlined.
+
+#![crate_name = "foo"]
+#![feature(doc_cfg)]
+
+// @has 'foo/index.html'
+
+#[doc(hidden, cfg(feature = "foo"))]
+pub struct Foo;
+
+#[doc(hidden, no_inline, cfg(feature = "bar"))]
+pub use Foo as Foo1;
+
+#[doc(hidden, inline)]
+pub use Foo1 as Foo2;
+
+// First we ensure that only the reexport `Bar2` and the inlined struct `Bar`
+// are inlined.
+// @count - '//a[@class="struct"]' 2
+// Then we check that both `cfg` are displayed.
+// @has - '//*[@class="stab portability"]' 'foo'
+// @has - '//*[@class="stab portability"]' 'bar'
+// And finally we check that the only element displayed is `Bar`.
+// @has - '//a[@class="struct"]' 'Bar'
+#[doc(inline)]
+pub use Foo2 as Bar;
+
+// This one should appear but `Bar2` won't be linked because there is no
+// `#[doc(inline)]`.
+// @has - '//*[@id="reexport.Bar2"]' 'pub use Foo2 as Bar2;'
+pub use Foo2 as Bar2;
diff --git a/tests/rustdoc/reexport-check.rs b/tests/rustdoc/reexport-check.rs
index db1f90c69..5908d2150 100644
--- a/tests/rustdoc/reexport-check.rs
+++ b/tests/rustdoc/reexport-check.rs
@@ -4,15 +4,17 @@
extern crate reexport_check;
// @!has 'foo/index.html' '//code' 'pub use self::i32;'
-// @has 'foo/index.html' '//div[@class="item-left deprecated module-item"]' 'i32'
// @has 'foo/i32/index.html'
#[allow(deprecated, deprecated_in_future)]
pub use std::i32;
// @!has 'foo/index.html' '//code' 'pub use self::string::String;'
-// @has 'foo/index.html' '//div[@class="item-left module-item"]' 'String'
+// @has 'foo/index.html' '//div[@class="item-name"]' 'String'
pub use std::string::String;
-// @has 'foo/index.html' '//div[@class="item-right docblock-short"]' 'Docs in original'
+// i32 is deprecated, String is not
+// @count 'foo/index.html' '//span[@class="stab deprecated"]' 1
+
+// @has 'foo/index.html' '//div[@class="desc docblock-short"]' 'Docs in original'
// this is a no-op, but shows what happens if there's an attribute that isn't a doc-comment
#[doc(inline)]
pub use reexport_check::S;
diff --git a/tests/rustdoc/reexport-dep-foreign-fn.rs b/tests/rustdoc/reexport-dep-foreign-fn.rs
index 6694c91d1..e7f5720d5 100644
--- a/tests/rustdoc/reexport-dep-foreign-fn.rs
+++ b/tests/rustdoc/reexport-dep-foreign-fn.rs
@@ -8,5 +8,5 @@
extern crate all_item_types;
// @has 'foo/fn.foo_ffn.html'
-// @has - '//*[@class="item-decl"]//code' 'pub unsafe extern "C" fn foo_ffn()'
+// @has - '//*[@class="rust item-decl"]//code' 'pub unsafe extern "C" fn foo_ffn()'
pub use all_item_types::foo_ffn;
diff --git a/tests/rustdoc/reexport-hidden-macro.rs b/tests/rustdoc/reexport-hidden-macro.rs
new file mode 100644
index 000000000..afcfa9796
--- /dev/null
+++ b/tests/rustdoc/reexport-hidden-macro.rs
@@ -0,0 +1,22 @@
+// Ensure that inlined reexport of hidden macros is working as expected.
+// Part of <https://github.com/rust-lang/rust/issues/59368>.
+
+#![crate_name = "foo"]
+
+// @has 'foo/index.html'
+// @has - '//*[@id="main-content"]//a[@href="macro.Macro2.html"]' 'Macro2'
+
+// @has 'foo/macro.Macro2.html'
+// @has - '//*[@class="docblock"]' 'Displayed'
+
+#[macro_export]
+#[doc(hidden)]
+macro_rules! foo {
+ () => {};
+}
+
+/// not displayed
+pub use crate::foo as Macro;
+/// Displayed
+#[doc(inline)]
+pub use crate::foo as Macro2;
diff --git a/tests/rustdoc/reexport-macro.rs b/tests/rustdoc/reexport-macro.rs
new file mode 100644
index 000000000..c4dec703a
--- /dev/null
+++ b/tests/rustdoc/reexport-macro.rs
@@ -0,0 +1,23 @@
+// Ensure that macros are correctly reexported and that they get both the comment from the
+// `pub use` and from the macro.
+
+#![crate_name = "foo"]
+
+// @has 'foo/macro.foo.html'
+// @!has - '//*[@class="toggle top-doc"]/*[@class="docblock"]' 'x y'
+// @has - '//*[@class="toggle top-doc"]/*[@class="docblock"]' 'y'
+#[macro_use]
+mod my_module {
+ /// y
+ #[macro_export]
+ macro_rules! foo {
+ () => ();
+ }
+}
+
+// @has 'foo/another_mod/macro.bar.html'
+// @has - '//*[@class="toggle top-doc"]/*[@class="docblock"]' 'x y'
+pub mod another_mod {
+ /// x
+ pub use crate::foo as bar;
+}
diff --git a/tests/rustdoc/reexports-of-same-name.rs b/tests/rustdoc/reexports-of-same-name.rs
new file mode 100644
index 000000000..fe6f1b38c
--- /dev/null
+++ b/tests/rustdoc/reexports-of-same-name.rs
@@ -0,0 +1,26 @@
+// This test ensures that there are 4 imports as expected:
+// * 2 for `Foo`
+// * 2 for `Bar`
+
+#![crate_name = "foo"]
+
+// @has 'foo/index.html'
+
+pub mod nested {
+ /// Foo the struct
+ pub struct Foo {}
+
+ #[allow(non_snake_case)]
+ /// Foo the function
+ pub fn Foo() {}
+}
+
+// @count - '//*[@id="main-content"]//code' 'pub use nested::Foo;' 2
+// @has - '//*[@id="reexport.Foo"]//a[@href="nested/struct.Foo.html"]' 'Foo'
+// @has - '//*[@id="reexport.Foo-1"]//a[@href="nested/fn.Foo.html"]' 'Foo'
+pub use nested::Foo;
+
+// @count - '//*[@id="main-content"]//code' 'pub use Foo as Bar;' 2
+// @has - '//*[@id="reexport.Bar"]//a[@href="nested/struct.Foo.html"]' 'Foo'
+// @has - '//*[@id="reexport.Bar-1"]//a[@href="nested/fn.Foo.html"]' 'Foo'
+pub use Foo as Bar;
diff --git a/tests/rustdoc/reexports-priv.rs b/tests/rustdoc/reexports-priv.rs
index 35c90ba5d..571d7f06f 100644
--- a/tests/rustdoc/reexports-priv.rs
+++ b/tests/rustdoc/reexports-priv.rs
@@ -5,7 +5,7 @@
extern crate reexports;
-// @has 'foo/macro.addr_of.html' '//*[@class="item-decl"]' 'pub macro addr_of($place:expr) {'
+// @has 'foo/macro.addr_of.html' '//*[@class="rust item-decl"]' 'pub macro addr_of($place:expr) {'
pub use reexports::addr_of;
// @!has 'foo/macro.addr_of_crate.html'
pub(crate) use reexports::addr_of_crate;
@@ -14,7 +14,7 @@ pub(self) use reexports::addr_of_self;
// @!has 'foo/macro.addr_of_local.html'
use reexports::addr_of_local;
-// @has 'foo/struct.Foo.html' '//*[@class="item-decl"]' 'pub struct Foo;'
+// @has 'foo/struct.Foo.html' '//*[@class="rust item-decl"]' 'pub struct Foo;'
pub use reexports::Foo;
// @!has 'foo/struct.FooCrate.html'
pub(crate) use reexports::FooCrate;
@@ -23,7 +23,7 @@ pub(self) use reexports::FooSelf;
// @!has 'foo/struct.FooLocal.html'
use reexports::FooLocal;
-// @has 'foo/enum.Bar.html' '//*[@class="item-decl"]' 'pub enum Bar {'
+// @has 'foo/enum.Bar.html' '//*[@class="rust item-decl"]' 'pub enum Bar {'
pub use reexports::Bar;
// @!has 'foo/enum.BarCrate.html'
pub(crate) use reexports::BarCrate;
@@ -32,7 +32,7 @@ pub(self) use reexports::BarSelf;
// @!has 'foo/enum.BarLocal.html'
use reexports::BarLocal;
-// @has 'foo/fn.foo.html' '//div[@class="item-decl"]/pre[@class="rust"]' 'pub fn foo()'
+// @has 'foo/fn.foo.html' '//pre[@class="rust item-decl"]' 'pub fn foo()'
pub use reexports::foo;
// @!has 'foo/fn.foo_crate.html'
pub(crate) use reexports::foo_crate;
@@ -41,7 +41,7 @@ pub(self) use reexports::foo_self;
// @!has 'foo/fn.foo_local.html'
use reexports::foo_local;
-// @has 'foo/type.Type.html' '//div[@class="item-decl"]/pre[@class="rust"]' 'pub type Type ='
+// @has 'foo/type.Type.html' '//pre[@class="rust item-decl"]' 'pub type Type ='
pub use reexports::Type;
// @!has 'foo/type.TypeCrate.html'
pub(crate) use reexports::TypeCrate;
@@ -50,7 +50,7 @@ pub(self) use reexports::TypeSelf;
// @!has 'foo/type.TypeLocal.html'
use reexports::TypeLocal;
-// @has 'foo/union.Union.html' '//*[@class="item-decl"]' 'pub union Union {'
+// @has 'foo/union.Union.html' '//*[@class="rust item-decl"]' 'pub union Union {'
pub use reexports::Union;
// @!has 'foo/union.UnionCrate.html'
pub(crate) use reexports::UnionCrate;
@@ -61,66 +61,66 @@ use reexports::UnionLocal;
pub mod outer {
pub mod inner {
- // @has 'foo/outer/inner/macro.addr_of.html' '//*[@class="item-decl"]' 'pub macro addr_of($place:expr) {'
+ // @has 'foo/outer/inner/macro.addr_of.html' '//*[@class="rust item-decl"]' 'pub macro addr_of($place:expr) {'
pub use reexports::addr_of;
- // @has 'foo/outer/inner/macro.addr_of_crate.html' '//*[@class="item-decl"]' 'pub(crate) macro addr_of_crate($place:expr) {'
+ // @has 'foo/outer/inner/macro.addr_of_crate.html' '//*[@class="rust item-decl"]' 'pub(crate) macro addr_of_crate($place:expr) {'
pub(crate) use reexports::addr_of_crate;
- // @has 'foo/outer/inner/macro.addr_of_super.html' '//*[@class="item-decl"]' 'pub(in outer) macro addr_of_super($place:expr) {'
+ // @has 'foo/outer/inner/macro.addr_of_super.html' '//*[@class="rust item-decl"]' 'pub(in outer) macro addr_of_super($place:expr) {'
pub(super) use reexports::addr_of_super;
// @!has 'foo/outer/inner/macro.addr_of_self.html'
pub(self) use reexports::addr_of_self;
// @!has 'foo/outer/inner/macro.addr_of_local.html'
use reexports::addr_of_local;
- // @has 'foo/outer/inner/struct.Foo.html' '//*[@class="item-decl"]' 'pub struct Foo;'
+ // @has 'foo/outer/inner/struct.Foo.html' '//*[@class="rust item-decl"]' 'pub struct Foo;'
pub use reexports::Foo;
- // @has 'foo/outer/inner/struct.FooCrate.html' '//*[@class="item-decl"]' 'pub(crate) struct FooCrate;'
+ // @has 'foo/outer/inner/struct.FooCrate.html' '//*[@class="rust item-decl"]' 'pub(crate) struct FooCrate;'
pub(crate) use reexports::FooCrate;
- // @has 'foo/outer/inner/struct.FooSuper.html' '//*[@class="item-decl"]' 'pub(in outer) struct FooSuper;'
+ // @has 'foo/outer/inner/struct.FooSuper.html' '//*[@class="rust item-decl"]' 'pub(in outer) struct FooSuper;'
pub(super) use reexports::FooSuper;
// @!has 'foo/outer/inner/struct.FooSelf.html'
pub(self) use reexports::FooSelf;
// @!has 'foo/outer/inner/struct.FooLocal.html'
use reexports::FooLocal;
- // @has 'foo/outer/inner/enum.Bar.html' '//*[@class="item-decl"]' 'pub enum Bar {'
+ // @has 'foo/outer/inner/enum.Bar.html' '//*[@class="rust item-decl"]' 'pub enum Bar {'
pub use reexports::Bar;
- // @has 'foo/outer/inner/enum.BarCrate.html' '//*[@class="item-decl"]' 'pub(crate) enum BarCrate {'
+ // @has 'foo/outer/inner/enum.BarCrate.html' '//*[@class="rust item-decl"]' 'pub(crate) enum BarCrate {'
pub(crate) use reexports::BarCrate;
- // @has 'foo/outer/inner/enum.BarSuper.html' '//*[@class="item-decl"]' 'pub(in outer) enum BarSuper {'
+ // @has 'foo/outer/inner/enum.BarSuper.html' '//*[@class="rust item-decl"]' 'pub(in outer) enum BarSuper {'
pub(super) use reexports::BarSuper;
// @!has 'foo/outer/inner/enum.BarSelf.html'
pub(self) use reexports::BarSelf;
// @!has 'foo/outer/inner/enum.BarLocal.html'
use reexports::BarLocal;
- // @has 'foo/outer/inner/fn.foo.html' '//div[@class="item-decl"]/pre[@class="rust"]' 'pub fn foo()'
+ // @has 'foo/outer/inner/fn.foo.html' '//pre[@class="rust item-decl"]' 'pub fn foo()'
pub use reexports::foo;
- // @has 'foo/outer/inner/fn.foo_crate.html' '//div[@class="item-decl"]/pre[@class="rust"]' 'pub(crate) fn foo_crate()'
+ // @has 'foo/outer/inner/fn.foo_crate.html' '//pre[@class="rust item-decl"]' 'pub(crate) fn foo_crate()'
pub(crate) use reexports::foo_crate;
- // @has 'foo/outer/inner/fn.foo_super.html' '//div[@class="item-decl"]/pre[@class="rust"]' 'pub(in outer) fn foo_super()'
+ // @has 'foo/outer/inner/fn.foo_super.html' '//pre[@class="rust item-decl"]' 'pub(in outer) fn foo_super( )'
pub(super) use::reexports::foo_super;
// @!has 'foo/outer/inner/fn.foo_self.html'
pub(self) use reexports::foo_self;
// @!has 'foo/outer/inner/fn.foo_local.html'
use reexports::foo_local;
- // @has 'foo/outer/inner/type.Type.html' '//div[@class="item-decl"]/pre[@class="rust"]' 'pub type Type ='
+ // @has 'foo/outer/inner/type.Type.html' '//pre[@class="rust item-decl"]' 'pub type Type ='
pub use reexports::Type;
- // @has 'foo/outer/inner/type.TypeCrate.html' '//div[@class="item-decl"]/pre[@class="rust"]' 'pub(crate) type TypeCrate ='
+ // @has 'foo/outer/inner/type.TypeCrate.html' '//pre[@class="rust item-decl"]' 'pub(crate) type TypeCrate ='
pub(crate) use reexports::TypeCrate;
- // @has 'foo/outer/inner/type.TypeSuper.html' '//div[@class="item-decl"]/pre[@class="rust"]' 'pub(in outer) type TypeSuper ='
+ // @has 'foo/outer/inner/type.TypeSuper.html' '//pre[@class="rust item-decl"]' 'pub(in outer) type TypeSuper ='
pub(super) use reexports::TypeSuper;
// @!has 'foo/outer/inner/type.TypeSelf.html'
pub(self) use reexports::TypeSelf;
// @!has 'foo/outer/inner/type.TypeLocal.html'
use reexports::TypeLocal;
- // @has 'foo/outer/inner/union.Union.html' '//*[@class="item-decl"]' 'pub union Union {'
+ // @has 'foo/outer/inner/union.Union.html' '//*[@class="rust item-decl"]' 'pub union Union {'
pub use reexports::Union;
- // @has 'foo/outer/inner/union.UnionCrate.html' '//*[@class="item-decl"]' 'pub(crate) union UnionCrate {'
+ // @has 'foo/outer/inner/union.UnionCrate.html' '//*[@class="rust item-decl"]' 'pub(crate) union UnionCrate {'
pub(crate) use reexports::UnionCrate;
- // @has 'foo/outer/inner/union.UnionSuper.html' '//*[@class="item-decl"]' 'pub(in outer) union UnionSuper {'
+ // @has 'foo/outer/inner/union.UnionSuper.html' '//*[@class="rust item-decl"]' 'pub(in outer) union UnionSuper {'
pub(super) use reexports::UnionSuper;
// @!has 'foo/outer/inner/union.UnionSelf.html'
pub(self) use reexports::UnionSelf;
diff --git a/tests/rustdoc/reexports.rs b/tests/rustdoc/reexports.rs
index 65d305c6d..3c51ac395 100644
--- a/tests/rustdoc/reexports.rs
+++ b/tests/rustdoc/reexports.rs
@@ -4,7 +4,7 @@
extern crate reexports;
-// @has 'foo/macro.addr_of.html' '//*[@class="item-decl"]' 'pub macro addr_of($place:expr) {'
+// @has 'foo/macro.addr_of.html' '//*[@class="rust item-decl"]' 'pub macro addr_of($place:expr) {'
pub use reexports::addr_of;
// @!has 'foo/macro.addr_of_crate.html'
pub(crate) use reexports::addr_of_crate;
@@ -13,7 +13,7 @@ pub(self) use reexports::addr_of_self;
// @!has 'foo/macro.addr_of_local.html'
use reexports::addr_of_local;
-// @has 'foo/struct.Foo.html' '//*[@class="item-decl"]' 'pub struct Foo;'
+// @has 'foo/struct.Foo.html' '//*[@class="rust item-decl"]' 'pub struct Foo;'
pub use reexports::Foo;
// @!has 'foo/struct.FooCrate.html'
pub(crate) use reexports::FooCrate;
@@ -22,7 +22,7 @@ pub(self) use reexports::FooSelf;
// @!has 'foo/struct.FooLocal.html'
use reexports::FooLocal;
-// @has 'foo/enum.Bar.html' '//*[@class="item-decl"]' 'pub enum Bar {'
+// @has 'foo/enum.Bar.html' '//*[@class="rust item-decl"]' 'pub enum Bar {'
pub use reexports::Bar;
// @!has 'foo/enum.BarCrate.html'
pub(crate) use reexports::BarCrate;
@@ -31,7 +31,7 @@ pub(self) use reexports::BarSelf;
// @!has 'foo/enum.BarLocal.html'
use reexports::BarLocal;
-// @has 'foo/fn.foo.html' '//div[@class="item-decl"]/pre[@class="rust"]' 'pub fn foo()'
+// @has 'foo/fn.foo.html' '//pre[@class="rust item-decl"]' 'pub fn foo()'
pub use reexports::foo;
// @!has 'foo/fn.foo_crate.html'
pub(crate) use reexports::foo_crate;
@@ -40,7 +40,7 @@ pub(self) use reexports::foo_self;
// @!has 'foo/fn.foo_local.html'
use reexports::foo_local;
-// @has 'foo/type.Type.html' '//div[@class="item-decl"]/pre[@class="rust"]' 'pub type Type ='
+// @has 'foo/type.Type.html' '//pre[@class="rust item-decl"]' 'pub type Type ='
pub use reexports::Type;
// @!has 'foo/type.TypeCrate.html'
pub(crate) use reexports::TypeCrate;
@@ -49,7 +49,7 @@ pub(self) use reexports::TypeSelf;
// @!has 'foo/type.TypeLocal.html'
use reexports::TypeLocal;
-// @has 'foo/union.Union.html' '//*[@class="item-decl"]' 'pub union Union {'
+// @has 'foo/union.Union.html' '//*[@class="rust item-decl"]' 'pub union Union {'
pub use reexports::Union;
// @!has 'foo/union.UnionCrate.html'
pub(crate) use reexports::UnionCrate;
@@ -60,7 +60,7 @@ use reexports::UnionLocal;
pub mod outer {
pub mod inner {
- // @has 'foo/outer/inner/macro.addr_of.html' '//*[@class="item-decl"]' 'pub macro addr_of($place:expr) {'
+ // @has 'foo/outer/inner/macro.addr_of.html' '//*[@class="rust item-decl"]' 'pub macro addr_of($place:expr) {'
pub use reexports::addr_of;
// @!has 'foo/outer/inner/macro.addr_of_crate.html'
pub(crate) use reexports::addr_of_crate;
@@ -71,7 +71,7 @@ pub mod outer {
// @!has 'foo/outer/inner/macro.addr_of_local.html'
use reexports::addr_of_local;
- // @has 'foo/outer/inner/struct.Foo.html' '//*[@class="item-decl"]' 'pub struct Foo;'
+ // @has 'foo/outer/inner/struct.Foo.html' '//*[@class="rust item-decl"]' 'pub struct Foo;'
pub use reexports::Foo;
// @!has 'foo/outer/inner/struct.FooCrate.html'
pub(crate) use reexports::FooCrate;
@@ -82,7 +82,7 @@ pub mod outer {
// @!has 'foo/outer/inner/struct.FooLocal.html'
use reexports::FooLocal;
- // @has 'foo/outer/inner/enum.Bar.html' '//*[@class="item-decl"]' 'pub enum Bar {'
+ // @has 'foo/outer/inner/enum.Bar.html' '//*[@class="rust item-decl"]' 'pub enum Bar {'
pub use reexports::Bar;
// @!has 'foo/outer/inner/enum.BarCrate.html'
pub(crate) use reexports::BarCrate;
@@ -93,7 +93,7 @@ pub mod outer {
// @!has 'foo/outer/inner/enum.BarLocal.html'
use reexports::BarLocal;
- // @has 'foo/outer/inner/fn.foo.html' '//div[@class="item-decl"]/pre[@class="rust"]' 'pub fn foo()'
+ // @has 'foo/outer/inner/fn.foo.html' '//pre[@class="rust item-decl"]' 'pub fn foo()'
pub use reexports::foo;
// @!has 'foo/outer/inner/fn.foo_crate.html'
pub(crate) use reexports::foo_crate;
@@ -104,7 +104,7 @@ pub mod outer {
// @!has 'foo/outer/inner/fn.foo_local.html'
use reexports::foo_local;
- // @has 'foo/outer/inner/type.Type.html' '//div[@class="item-decl"]/pre[@class="rust"]' 'pub type Type ='
+ // @has 'foo/outer/inner/type.Type.html' '//pre[@class="rust item-decl"]' 'pub type Type ='
pub use reexports::Type;
// @!has 'foo/outer/inner/type.TypeCrate.html'
pub(crate) use reexports::TypeCrate;
@@ -115,7 +115,7 @@ pub mod outer {
// @!has 'foo/outer/inner/type.TypeLocal.html'
use reexports::TypeLocal;
- // @has 'foo/outer/inner/union.Union.html' '//*[@class="item-decl"]' 'pub union Union {'
+ // @has 'foo/outer/inner/union.Union.html' '//*[@class="rust item-decl"]' 'pub union Union {'
pub use reexports::Union;
// @!has 'foo/outer/inner/union.UnionCrate.html'
pub(crate) use reexports::UnionCrate;
diff --git a/tests/rustdoc/rfc-2632-const-trait-impl.rs b/tests/rustdoc/rfc-2632-const-trait-impl.rs
index a229a4e29..1120302ac 100644
--- a/tests/rustdoc/rfc-2632-const-trait-impl.rs
+++ b/tests/rustdoc/rfc-2632-const-trait-impl.rs
@@ -12,10 +12,10 @@ use std::marker::Destruct;
pub struct S<T>(T);
-// @!has foo/trait.Tr.html '//div[@class="item-decl"]/pre[@class="rust"]/code/a[@class="trait"]' '~const'
-// @has - '//div[@class="item-decl"]/pre[@class="rust"]/code/a[@class="trait"]' 'Clone'
-// @!has - '//div[@class="item-decl"]/pre[@class="rust"]/code/span[@class="where"]' '~const'
-// @has - '//div[@class="item-decl"]/pre[@class="rust"]/code/span[@class="where"]' ': Clone'
+// @!has foo/trait.Tr.html '//pre[@class="rust item-decl"]/code/a[@class="trait"]' '~const'
+// @has - '//pre[@class="rust item-decl"]/code/a[@class="trait"]' 'Clone'
+// @!has - '//pre[@class="rust item-decl"]/code/span[@class="where"]' '~const'
+// @has - '//pre[@class="rust item-decl"]/code/span[@class="where"]' ': Clone'
#[const_trait]
pub trait Tr<T> {
// @!has - '//section[@id="method.a"]/h4[@class="code-header"]' '~const'
@@ -45,10 +45,10 @@ where
}
}
-// @!has foo/fn.foo.html '//div[@class="item-decl"]/pre[@class="rust"]/code/a[@class="trait"]' '~const'
-// @has - '//div[@class="item-decl"]/pre[@class="rust"]/code/a[@class="trait"]' 'Clone'
-// @!has - '//div[@class="item-decl"]/pre[@class="rust"]/code/span[@class="where fmt-newline"]' '~const'
-// @has - '//div[@class="item-decl"]/pre[@class="rust"]/code/span[@class="where fmt-newline"]' ': Clone'
+// @!has foo/fn.foo.html '//pre[@class="rust item-decl"]/code/a[@class="trait"]' '~const'
+// @has - '//pre[@class="rust item-decl"]/code/a[@class="trait"]' 'Clone'
+// @!has - '//pre[@class="rust item-decl"]/code/span[@class="where fmt-newline"]' '~const'
+// @has - '//pre[@class="rust item-decl"]/code/span[@class="where fmt-newline"]' ': Clone'
pub const fn foo<F: ~const Clone + ~const Destruct>()
where
Option<F>: ~const Clone + ~const Destruct,
diff --git a/tests/rustdoc/safe-intrinsic.rs b/tests/rustdoc/safe-intrinsic.rs
index 0b65bf1df..c508909f9 100644
--- a/tests/rustdoc/safe-intrinsic.rs
+++ b/tests/rustdoc/safe-intrinsic.rs
@@ -7,16 +7,16 @@
extern "rust-intrinsic" {
// @has 'foo/fn.abort.html'
- // @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'pub extern "rust-intrinsic" fn abort() -> !'
+ // @has - '//pre[@class="rust item-decl"]' 'pub extern "rust-intrinsic" fn abort() -> !'
#[rustc_safe_intrinsic]
pub fn abort() -> !;
// @has 'foo/fn.unreachable.html'
- // @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'pub unsafe extern "rust-intrinsic" fn unreachable() -> !'
+ // @has - '//pre[@class="rust item-decl"]' 'pub unsafe extern "rust-intrinsic" fn unreachable() -> !'
pub fn unreachable() -> !;
}
extern "C" {
// @has 'foo/fn.needs_drop.html'
- // @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'pub unsafe extern "C" fn needs_drop() -> !'
+ // @has - '//pre[@class="rust item-decl"]' 'pub unsafe extern "C" fn needs_drop() -> !'
pub fn needs_drop() -> !;
}
diff --git a/tests/rustdoc/short-docblock-codeblock.rs b/tests/rustdoc/short-docblock-codeblock.rs
index 3c5fa7b36..7ecd80b8c 100644
--- a/tests/rustdoc/short-docblock-codeblock.rs
+++ b/tests/rustdoc/short-docblock-codeblock.rs
@@ -1,6 +1,6 @@
#![crate_name = "foo"]
-// @count foo/index.html '//*[@class="item-right docblock-short"]' 0
+// @count foo/index.html '//*[@class="desc docblock-short"]' 0
/// ```
/// let x = 12;
diff --git a/tests/rustdoc/short-docblock.rs b/tests/rustdoc/short-docblock.rs
index 1a8a689be..791d3547c 100644
--- a/tests/rustdoc/short-docblock.rs
+++ b/tests/rustdoc/short-docblock.rs
@@ -1,7 +1,7 @@
#![crate_name = "foo"]
-// @has foo/index.html '//*[@class="item-right docblock-short"]' 'fooo'
-// @!has foo/index.html '//*[@class="item-right docblock-short"]/h1' 'fooo'
+// @has foo/index.html '//*[@class="desc docblock-short"]' 'fooo'
+// @!has foo/index.html '//*[@class="desc docblock-short"]/h1' 'fooo'
// @has foo/fn.foo.html '//h2[@id="fooo"]/a[@href="#fooo"]' 'fooo'
/// # fooo
@@ -9,8 +9,8 @@
/// foo
pub fn foo() {}
-// @has foo/index.html '//*[@class="item-right docblock-short"]' 'mooood'
-// @!has foo/index.html '//*[@class="item-right docblock-short"]/h2' 'mooood'
+// @has foo/index.html '//*[@class="desc docblock-short"]' 'mooood'
+// @!has foo/index.html '//*[@class="desc docblock-short"]/h2' 'mooood'
// @has foo/foo/index.html '//h3[@id="mooood"]/a[@href="#mooood"]' 'mooood'
/// ## mooood
@@ -18,7 +18,7 @@ pub fn foo() {}
/// foo mod
pub mod foo {}
-// @has foo/index.html '//*[@class="item-right docblock-short"]/a[@href=\
+// @has foo/index.html '//*[@class="desc docblock-short"]/a[@href=\
// "https://nougat.world"]/code' 'nougat'
/// [`nougat`](https://nougat.world)
diff --git a/tests/rustdoc/sidebar-links-to-foreign-impl.rs b/tests/rustdoc/sidebar-links-to-foreign-impl.rs
index 11e946948..caa17dfbb 100644
--- a/tests/rustdoc/sidebar-links-to-foreign-impl.rs
+++ b/tests/rustdoc/sidebar-links-to-foreign-impl.rs
@@ -7,8 +7,8 @@
// @has - '//h2[@id="foreign-impls"]' 'Implementations on Foreign Types'
// @has - '//*[@class="sidebar-elems"]//section//a[@href="#impl-Foo-for-u32"]' 'u32'
// @has - '//*[@id="impl-Foo-for-u32"]//h3[@class="code-header"]' 'impl Foo for u32'
-// @has - '//*[@class="sidebar-elems"]//section//a[@href="#impl-Foo-for-%26%27a%20str"]' "&'a str"
-// @has - '//*[@id="impl-Foo-for-%26%27a%20str"]//h3[@class="code-header"]' "impl<'a> Foo for &'a str"
+// @has - "//*[@class=\"sidebar-elems\"]//section//a[@href=\"#impl-Foo-for-%26'a+str\"]" "&'a str"
+// @has - "//*[@id=\"impl-Foo-for-%26'a+str\"]//h3[@class=\"code-header\"]" "impl<'a> Foo for &'a str"
pub trait Foo {}
impl Foo for u32 {}
diff --git a/tests/rustdoc/slice-links.rs b/tests/rustdoc/slice-links.rs
index 67137fdca..6dea3b74e 100644
--- a/tests/rustdoc/slice-links.rs
+++ b/tests/rustdoc/slice-links.rs
@@ -4,25 +4,25 @@
pub struct MyBox<T: ?Sized>(*const T);
// @has 'foo/fn.alpha.html'
-// @snapshot link_slice_u32 - '//div[@class="item-decl"]/pre[@class="rust"]/code'
+// @snapshot link_slice_u32 - '//pre[@class="rust item-decl"]/code'
pub fn alpha() -> &'static [u32] {
loop {}
}
// @has 'foo/fn.beta.html'
-// @snapshot link_slice_generic - '//div[@class="item-decl"]/pre[@class="rust"]/code'
+// @snapshot link_slice_generic - '//pre[@class="rust item-decl"]/code'
pub fn beta<T>() -> &'static [T] {
loop {}
}
// @has 'foo/fn.gamma.html'
-// @snapshot link_box_u32 - '//div[@class="item-decl"]/pre[@class="rust"]/code'
+// @snapshot link_box_u32 - '//pre[@class="rust item-decl"]/code'
pub fn gamma() -> MyBox<[u32]> {
loop {}
}
// @has 'foo/fn.delta.html'
-// @snapshot link_box_generic - '//div[@class="item-decl"]/pre[@class="rust"]/code'
+// @snapshot link_box_generic - '//pre[@class="rust item-decl"]/code'
pub fn delta<T>() -> MyBox<[T]> {
loop {}
}
diff --git a/tests/rustdoc/spotlight-from-dependency.rs b/tests/rustdoc/spotlight-from-dependency.rs
index 090ad187d..426759c7b 100644
--- a/tests/rustdoc/spotlight-from-dependency.rs
+++ b/tests/rustdoc/spotlight-from-dependency.rs
@@ -3,7 +3,7 @@
use std::iter::Iterator;
// @has foo/struct.Odd.html
-// @has - '//*[@id="method.new"]//a[@class="notable-traits"]/@data-ty' 'Odd'
+// @has - '//*[@id="method.new"]//a[@class="tooltip"]/@data-notable-ty' 'Odd'
// @snapshot odd - '//script[@id="notable-traits-data"]'
pub struct Odd {
current: usize,
diff --git a/tests/rustdoc/struct-arg-pattern.rs b/tests/rustdoc/struct-arg-pattern.rs
index 3bfb43a0b..6f06c8c9c 100644
--- a/tests/rustdoc/struct-arg-pattern.rs
+++ b/tests/rustdoc/struct-arg-pattern.rs
@@ -4,7 +4,7 @@ struct BodyId {
hir_id: usize,
}
-// @has 'foo/fn.body_owner.html' '//div[@class="item-decl"]/pre[@class="rust"]' 'pub fn body_owner(_: BodyId)'
+// @has 'foo/fn.body_owner.html' '//pre[@class="rust item-decl"]' 'pub fn body_owner(_: BodyId)'
pub fn body_owner(BodyId { hir_id }: BodyId) {
// ...
}
diff --git a/tests/rustdoc/synthetic_auto/basic.rs b/tests/rustdoc/synthetic_auto/basic.rs
index 7c6a38865..043ac2414 100644
--- a/tests/rustdoc/synthetic_auto/basic.rs
+++ b/tests/rustdoc/synthetic_auto/basic.rs
@@ -1,8 +1,8 @@
// @has basic/struct.Foo.html
// @has - '//h3[@class="code-header"]' 'impl<T> Send for Foo<T>where T: Send'
// @has - '//h3[@class="code-header"]' 'impl<T> Sync for Foo<T>where T: Sync'
-// @count - '//*[@id="implementations-list"]//*[@class="impl has-srclink"]' 0
-// @count - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]' 5
+// @count - '//*[@id="implementations-list"]//*[@class="impl"]' 0
+// @count - '//*[@id="synthetic-implementations-list"]//*[@class="impl"]' 5
pub struct Foo<T> {
field: T,
}
diff --git a/tests/rustdoc/synthetic_auto/complex.rs b/tests/rustdoc/synthetic_auto/complex.rs
index 43393c21f..4c39f0bf1 100644
--- a/tests/rustdoc/synthetic_auto/complex.rs
+++ b/tests/rustdoc/synthetic_auto/complex.rs
@@ -20,7 +20,7 @@ mod foo {
}
// @has complex/struct.NotOuter.html
-// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header"]' \
+// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl"]//h3[@class="code-header"]' \
// "impl<'a, T, K: ?Sized> Send for Outer<'a, T, K>where K: for<'b> Fn((&'b bool, &'a u8)) \
// -> &'b i8, T: MyTrait<'a>, <T as MyTrait<'a>>::MyItem: Copy, 'a: 'static"
diff --git a/tests/rustdoc/synthetic_auto/lifetimes.rs b/tests/rustdoc/synthetic_auto/lifetimes.rs
index 33170a844..71265b307 100644
--- a/tests/rustdoc/synthetic_auto/lifetimes.rs
+++ b/tests/rustdoc/synthetic_auto/lifetimes.rs
@@ -9,10 +9,10 @@ where
{}
// @has lifetimes/struct.Foo.html
-// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header"]' \
+// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl"]//h3[@class="code-header"]' \
// "impl<'c, K> Send for Foo<'c, K>where K: for<'b> Fn(&'b bool) -> &'c u8, 'c: 'static"
//
-// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header"]' \
+// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl"]//h3[@class="code-header"]' \
// "impl<'c, K> Sync for Foo<'c, K>where K: Sync"
pub struct Foo<'c, K: 'c> {
inner_field: Inner<'c, K>,
diff --git a/tests/rustdoc/synthetic_auto/manual.rs b/tests/rustdoc/synthetic_auto/manual.rs
index 77c04ad2a..7fc8447df 100644
--- a/tests/rustdoc/synthetic_auto/manual.rs
+++ b/tests/rustdoc/synthetic_auto/manual.rs
@@ -1,12 +1,12 @@
// @has manual/struct.Foo.html
-// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header"]' \
+// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl"]//h3[@class="code-header"]' \
// 'impl<T> Sync for Foo<T>where T: Sync'
//
-// @has - '//*[@id="trait-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header"]' \
+// @has - '//*[@id="trait-implementations-list"]//*[@class="impl"]//h3[@class="code-header"]' \
// 'impl<T> Send for Foo<T>'
//
-// @count - '//*[@id="trait-implementations-list"]//*[@class="impl has-srclink"]' 1
-// @count - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]' 4
+// @count - '//*[@id="trait-implementations-list"]//*[@class="impl"]' 1
+// @count - '//*[@id="synthetic-implementations-list"]//*[@class="impl"]' 4
pub struct Foo<T> {
field: T,
}
diff --git a/tests/rustdoc/synthetic_auto/negative.rs b/tests/rustdoc/synthetic_auto/negative.rs
index 2c2c848a5..97da2d574 100644
--- a/tests/rustdoc/synthetic_auto/negative.rs
+++ b/tests/rustdoc/synthetic_auto/negative.rs
@@ -3,10 +3,10 @@ pub struct Inner<T: Copy> {
}
// @has negative/struct.Outer.html
-// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header"]' \
+// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl"]//h3[@class="code-header"]' \
// "impl<T> !Send for Outer<T>"
//
-// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header"]' \
+// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl"]//h3[@class="code-header"]' \
// "impl<T> !Sync for Outer<T>"
pub struct Outer<T: Copy> {
inner_field: Inner<T>,
diff --git a/tests/rustdoc/synthetic_auto/nested.rs b/tests/rustdoc/synthetic_auto/nested.rs
index 423bf115a..e4aead71b 100644
--- a/tests/rustdoc/synthetic_auto/nested.rs
+++ b/tests/rustdoc/synthetic_auto/nested.rs
@@ -9,10 +9,10 @@ where
}
// @has nested/struct.Foo.html
-// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header"]' \
+// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl"]//h3[@class="code-header"]' \
// 'impl<T> Send for Foo<T>where T: Copy'
//
-// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header"]' \
+// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl"]//h3[@class="code-header"]' \
// 'impl<T> Sync for Foo<T>where T: Sync'
pub struct Foo<T> {
inner_field: Inner<T>,
diff --git a/tests/rustdoc/synthetic_auto/no-redundancy.rs b/tests/rustdoc/synthetic_auto/no-redundancy.rs
index 59f336233..ea57d7388 100644
--- a/tests/rustdoc/synthetic_auto/no-redundancy.rs
+++ b/tests/rustdoc/synthetic_auto/no-redundancy.rs
@@ -9,7 +9,7 @@ where
}
// @has no_redundancy/struct.Outer.html
-// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header"]' \
+// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl"]//h3[@class="code-header"]' \
// "impl<T> Send for Outer<T>where T: Send + Copy"
pub struct Outer<T> {
inner_field: Inner<T>,
diff --git a/tests/rustdoc/synthetic_auto/project.rs b/tests/rustdoc/synthetic_auto/project.rs
index 558ff2add..7c9412ae9 100644
--- a/tests/rustdoc/synthetic_auto/project.rs
+++ b/tests/rustdoc/synthetic_auto/project.rs
@@ -23,10 +23,10 @@ where
}
// @has project/struct.Foo.html
-// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header"]' \
+// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl"]//h3[@class="code-header"]' \
// "impl<'c, K> Send for Foo<'c, K>where K: MyTrait<MyItem = bool>, 'c: 'static"
//
-// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header"]' \
+// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl"]//h3[@class="code-header"]' \
// "impl<'c, K> Sync for Foo<'c, K>where K: MyTrait, <K as MyTrait>::MyItem: OtherTrait, \
// 'c: 'static,"
pub struct Foo<'c, K: 'c> {
diff --git a/tests/rustdoc/synthetic_auto/self-referential.rs b/tests/rustdoc/synthetic_auto/self-referential.rs
index c6ae96de7..145a2b7e0 100644
--- a/tests/rustdoc/synthetic_auto/self-referential.rs
+++ b/tests/rustdoc/synthetic_auto/self-referential.rs
@@ -23,7 +23,7 @@ impl<T> Pattern for Wrapper<T> {
// @has self_referential/struct.WriteAndThen.html
-// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header"]' \
+// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl"]//h3[@class="code-header"]' \
// "impl<P1> Send for WriteAndThen<P1>where <P1 as Pattern>::Value: Send"
pub struct WriteAndThen<P1>(pub P1::Value,pub <Constrain<P1, Wrapper<P1::Value>> as Pattern>::Value)
where P1: Pattern;
diff --git a/tests/rustdoc/synthetic_auto/static-region.rs b/tests/rustdoc/synthetic_auto/static-region.rs
index 1a76cb919..9dc6211ec 100644
--- a/tests/rustdoc/synthetic_auto/static-region.rs
+++ b/tests/rustdoc/synthetic_auto/static-region.rs
@@ -3,7 +3,7 @@ pub trait OwnedTrait<'a> {
}
// @has static_region/struct.Owned.html
-// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header"]' \
+// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl"]//h3[@class="code-header"]' \
// "impl<T> Send for Owned<T>where <T as OwnedTrait<'static>>::Reader: Send"
pub struct Owned<T> where T: OwnedTrait<'static> {
marker: <T as OwnedTrait<'static>>::Reader,
diff --git a/tests/rustdoc/test-parens.rs b/tests/rustdoc/test-parens.rs
index f5fdb1f52..9640b96b6 100644
--- a/tests/rustdoc/test-parens.rs
+++ b/tests/rustdoc/test-parens.rs
@@ -1,5 +1,5 @@
#![crate_name = "foo"]
// @has foo/fn.foo.html
-// @has - '//div[@class="item-decl"]/pre[@class="rust"]' "_: &(dyn ToString + 'static)"
+// @has - '//pre[@class="rust item-decl"]' "_: &(dyn ToString + 'static)"
pub fn foo(_: &(ToString + 'static)) {}
diff --git a/tests/rustdoc/toggle-item-contents.rs b/tests/rustdoc/toggle-item-contents.rs
index 5d34ec09b..1f7450438 100644
--- a/tests/rustdoc/toggle-item-contents.rs
+++ b/tests/rustdoc/toggle-item-contents.rs
@@ -55,7 +55,7 @@ pub union Union {
// @has 'toggle_item_contents/struct.PrivStruct.html'
// @count - '//details[@class="toggle type-contents-toggle"]' 0
-// @has - '//div[@class="item-decl"]' '/* private fields */'
+// @has - '//pre[@class="rust item-decl"]' '/* private fields */'
pub struct PrivStruct {
a: usize,
b: usize,
@@ -81,8 +81,8 @@ pub enum EnumStructVariant {
}
// @has 'toggle_item_contents/enum.LargeEnum.html'
-// @count - '//div[@class="item-decl"]/pre//details[@class="toggle type-contents-toggle"]' 1
-// @has - '//div[@class="item-decl"]/pre//details[@class="toggle type-contents-toggle"]' 'Show 13 variants'
+// @count - '//pre[@class="rust item-decl"]//details[@class="toggle type-contents-toggle"]' 1
+// @has - '//pre[@class="rust item-decl"]//details[@class="toggle type-contents-toggle"]' 'Show 13 variants'
pub enum LargeEnum {
A, B, C, D, E, F(u8), G, H, I, J, K, L, M
}
diff --git a/tests/rustdoc/trait_alias.rs b/tests/rustdoc/trait_alias.rs
index 791c099cc..5c3f82c6b 100644
--- a/tests/rustdoc/trait_alias.rs
+++ b/tests/rustdoc/trait_alias.rs
@@ -14,13 +14,13 @@ use std::fmt::Debug;
// @has foo/index.html '//a[@class="traitalias"]' 'Foo'
// @has foo/traitalias.CopyAlias.html
-// @has - '//section[@id="main-content"]/div[@class="item-decl"]/pre' 'trait CopyAlias = Copy;'
+// @has - '//section[@id="main-content"]/pre[@class="rust item-decl"]' 'trait CopyAlias = Copy;'
pub trait CopyAlias = Copy;
// @has foo/traitalias.Alias2.html
-// @has - '//section[@id="main-content"]/div[@class="item-decl"]/pre' 'trait Alias2 = Copy + Debug;'
+// @has - '//section[@id="main-content"]/pre[@class="rust item-decl"]' 'trait Alias2 = Copy + Debug;'
pub trait Alias2 = Copy + Debug;
// @has foo/traitalias.Foo.html
-// @has - '//section[@id="main-content"]/div[@class="item-decl"]/pre' 'trait Foo<T> = Into<T> + Debug;'
+// @has - '//section[@id="main-content"]/pre[@class="rust item-decl"]' 'trait Foo<T> = Into<T> + Debug;'
pub trait Foo<T> = Into<T> + Debug;
// @has foo/fn.bar.html '//a[@href="traitalias.Alias2.html"]' 'Alias2'
pub fn bar<T>() where T: Alias2 {}
diff --git a/tests/rustdoc/tuple-struct-fields-doc.rs b/tests/rustdoc/tuple-struct-fields-doc.rs
index d72c10f2b..2836ddedc 100644
--- a/tests/rustdoc/tuple-struct-fields-doc.rs
+++ b/tests/rustdoc/tuple-struct-fields-doc.rs
@@ -19,7 +19,7 @@ pub struct Foo(
);
// @has foo/enum.Bar.html
-// @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'BarVariant(String),'
+// @has - '//pre[@class="rust item-decl"]' 'BarVariant(String),'
// @matches - '//*[@id="variant.BarVariant.fields"]/h4' '^Tuple Fields$'
// @has - '//*[@id="variant.BarVariant.field.0"]' '0: String'
// @has - '//*[@id="variant.BarVariant.fields"]//*[@class="docblock"]' 'Hello docs'
diff --git a/tests/rustdoc/tuples.rs b/tests/rustdoc/tuples.rs
index e716de8b5..0ea5b5bfa 100644
--- a/tests/rustdoc/tuples.rs
+++ b/tests/rustdoc/tuples.rs
@@ -1,20 +1,20 @@
#![crate_name = "foo"]
// @has foo/fn.tuple0.html //pre 'pub fn tuple0(x: ())'
-// @snapshot link_unit - '//div[@class="item-decl"]/pre[@class="rust"]/code'
+// @snapshot link_unit - '//pre[@class="rust item-decl"]/code'
pub fn tuple0(x: ()) -> () { x }
// @has foo/fn.tuple1.html //pre 'pub fn tuple1(x: (i32,)) -> (i32,)'
-// @snapshot link1_i32 - '//div[@class="item-decl"]/pre[@class="rust"]/code'
+// @snapshot link1_i32 - '//pre[@class="rust item-decl"]/code'
pub fn tuple1(x: (i32,)) -> (i32,) { x }
// @has foo/fn.tuple2.html //pre 'pub fn tuple2(x: (i32, i32)) -> (i32, i32)'
-// @snapshot link2_i32 - '//div[@class="item-decl"]/pre[@class="rust"]/code'
+// @snapshot link2_i32 - '//pre[@class="rust item-decl"]/code'
pub fn tuple2(x: (i32, i32)) -> (i32, i32) { x }
// @has foo/fn.tuple1_t.html //pre 'pub fn tuple1_t<T>(x: (T,)) -> (T,)'
-// @snapshot link1_t - '//div[@class="item-decl"]/pre[@class="rust"]/code'
+// @snapshot link1_t - '//pre[@class="rust item-decl"]/code'
pub fn tuple1_t<T>(x: (T,)) -> (T,) { x }
// @has foo/fn.tuple2_t.html //pre 'pub fn tuple2_t<T>(x: (T, T)) -> (T, T)'
-// @snapshot link2_t - '//div[@class="item-decl"]/pre[@class="rust"]/code'
+// @snapshot link2_t - '//pre[@class="rust item-decl"]/code'
pub fn tuple2_t<T>(x: (T, T)) -> (T, T) { x }
// @has foo/fn.tuple2_tu.html //pre 'pub fn tuple2_tu<T, U>(x: (T, U)) -> (T, U)'
-// @snapshot link2_tu - '//div[@class="item-decl"]/pre[@class="rust"]/code'
+// @snapshot link2_tu - '//pre[@class="rust item-decl"]/code'
pub fn tuple2_tu<T, U>(x: (T, U)) -> (T, U) { x }
diff --git a/tests/rustdoc/typedef.rs b/tests/rustdoc/typedef.rs
index d5dfa9484..63e2973c7 100644
--- a/tests/rustdoc/typedef.rs
+++ b/tests/rustdoc/typedef.rs
@@ -9,8 +9,8 @@ impl MyStruct {
}
// @has typedef/type.MyAlias.html
-// @has - '//*[@class="impl has-srclink"]//h3[@class="code-header"]' 'impl MyAlias'
-// @has - '//*[@class="impl has-srclink"]//h3[@class="code-header"]' 'impl MyTrait for MyAlias'
+// @has - '//*[@class="impl"]//h3[@class="code-header"]' 'impl MyAlias'
+// @has - '//*[@class="impl"]//h3[@class="code-header"]' 'impl MyTrait for MyAlias'
// @hasraw - 'Alias docstring'
// @has - '//*[@class="sidebar"]//*[@class="location"]' 'MyAlias'
// @has - '//*[@class="sidebar"]//a[@href="#implementations"]' 'Methods'
diff --git a/tests/rustdoc/unit-return.rs b/tests/rustdoc/unit-return.rs
index 353cd1c47..6ddfa0c4d 100644
--- a/tests/rustdoc/unit-return.rs
+++ b/tests/rustdoc/unit-return.rs
@@ -4,14 +4,14 @@
extern crate unit_return;
-// @has 'foo/fn.f0.html' '//div[@class="item-decl"]/pre[@class="rust"]' 'F: FnMut(u8) + Clone'
+// @has 'foo/fn.f0.html' '//pre[@class="rust item-decl"]' 'F: FnMut(u8) + Clone'
pub fn f0<F: FnMut(u8) + Clone>(f: F) {}
-// @has 'foo/fn.f1.html' '//div[@class="item-decl"]/pre[@class="rust"]' 'F: FnMut(u16) + Clone'
+// @has 'foo/fn.f1.html' '//pre[@class="rust item-decl"]' 'F: FnMut(u16) + Clone'
pub fn f1<F: FnMut(u16) -> () + Clone>(f: F) {}
-// @has 'foo/fn.f2.html' '//div[@class="item-decl"]/pre[@class="rust"]' 'F: FnMut(u32) + Clone'
+// @has 'foo/fn.f2.html' '//pre[@class="rust item-decl"]' 'F: FnMut(u32) + Clone'
pub use unit_return::f2;
-// @has 'foo/fn.f3.html' '//div[@class="item-decl"]/pre[@class="rust"]' 'F: FnMut(u64) + Clone'
+// @has 'foo/fn.f3.html' '//pre[@class="rust item-decl"]' 'F: FnMut(u64) + Clone'
pub use unit_return::f3;
diff --git a/tests/rustdoc/where-clause-order.rs b/tests/rustdoc/where-clause-order.rs
index b8502e10a..b10f8f685 100644
--- a/tests/rustdoc/where-clause-order.rs
+++ b/tests/rustdoc/where-clause-order.rs
@@ -7,7 +7,7 @@ where
}
// @has 'foo/trait.SomeTrait.html'
-// @has - "//*[@id='impl-SomeTrait%3C(A%2C%20B%2C%20C%2C%20D%2C%20E)%3E-for-(A%2C%20B%2C%20C%2C%20D%2C%20E)']/h3" "impl<A, B, C, D, E> SomeTrait<(A, B, C, D, E)> for (A, B, C, D, E)where A: PartialOrd<A> + PartialEq<A>, B: PartialOrd<B> + PartialEq<B>, C: PartialOrd<C> + PartialEq<C>, D: PartialOrd<D> + PartialEq<D>, E: PartialOrd<E> + PartialEq<E> + ?Sized, "
+// @has - "//*[@id='impl-SomeTrait%3C(A,+B,+C,+D,+E)%3E-for-(A,+B,+C,+D,+E)']/h3" "impl<A, B, C, D, E> SomeTrait<(A, B, C, D, E)> for (A, B, C, D, E)where A: PartialOrd<A> + PartialEq<A>, B: PartialOrd<B> + PartialEq<B>, C: PartialOrd<C> + PartialEq<C>, D: PartialOrd<D> + PartialEq<D>, E: PartialOrd<E> + PartialEq<E> + ?Sized, "
impl<A, B, C, D, E> SomeTrait<(A, B, C, D, E)> for (A, B, C, D, E)
where
A: PartialOrd<A> + PartialEq<A>,
diff --git a/tests/rustdoc/where-sized.rs b/tests/rustdoc/where-sized.rs
index c0c085e6a..c1ac834b2 100644
--- a/tests/rustdoc/where-sized.rs
+++ b/tests/rustdoc/where-sized.rs
@@ -1,6 +1,6 @@
#![crate_name = "foo"]
// @has foo/fn.foo.html
-// @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'pub fn foo<X, Y: ?Sized>(_: &X)'
-// @has - '//div[@class="item-decl"]/pre[@class="rust"]' 'where X: ?Sized,'
+// @has - '//pre[@class="rust item-decl"]' 'pub fn foo<X, Y: ?Sized>(_: &X)'
+// @has - '//pre[@class="rust item-decl"]' 'where X: ?Sized,'
pub fn foo<X, Y: ?Sized>(_: &X) where X: ?Sized {}
diff --git a/tests/rustdoc/where.SWhere_Simd_item-decl.html b/tests/rustdoc/where.SWhere_Simd_item-decl.html
index f84cb3753..ef4294c8f 100644
--- a/tests/rustdoc/where.SWhere_Simd_item-decl.html
+++ b/tests/rustdoc/where.SWhere_Simd_item-decl.html
@@ -1 +1,3 @@
-<div class="item-decl"><pre class="rust"><code>pub struct Simd&lt;T&gt;(_)<br /><span class="where">where<br />&#160;&#160;&#160;&#160;T: <a class="trait" href="trait.MyTrait.html" title="trait foo::MyTrait">MyTrait</a></span>;</code></pre></div> \ No newline at end of file
+<pre class="rust item-decl"><code>pub struct Simd&lt;T&gt;(_)
+<span class="where">where
+ T: <a class="trait" href="trait.MyTrait.html" title="trait foo::MyTrait">MyTrait</a></span>;</code></pre> \ No newline at end of file
diff --git a/tests/rustdoc/where.SWhere_TraitWhere_item-decl.html b/tests/rustdoc/where.SWhere_TraitWhere_item-decl.html
index 85b626674..e8ab061e6 100644
--- a/tests/rustdoc/where.SWhere_TraitWhere_item-decl.html
+++ b/tests/rustdoc/where.SWhere_TraitWhere_item-decl.html
@@ -1,8 +1,13 @@
-<div class="item-decl"><pre class="rust"><code>pub trait TraitWhere {
- type <a href="#associatedtype.Item" class="associatedtype">Item</a>&lt;'a&gt;<br />&#160;&#160;&#160;&#160;<span class="where">where<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;Self: 'a</span>;
+<pre class="rust item-decl"><code>pub trait TraitWhere {
+ type <a href="#associatedtype.Item" class="associatedtype">Item</a>&lt;'a&gt;
+ <span class="where">where Self: 'a</span>;
- fn <a href="#method.func" class="fn">func</a>(self)<br />&#160;&#160;&#160;&#160;<span class="where">where<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;Self: <a class="trait" href="{{channel}}/core/marker/trait.Sized.html" title="trait core::marker::Sized">Sized</a></span>,
- { ... }
-<span class="item-spacer" /> fn <a href="#method.lines" class="fn">lines</a>(self) -&gt; <a class="struct" href="{{channel}}/std/io/struct.Lines.html" title="struct std::io::Lines">Lines</a>&lt;Self&gt;<br />&#160;&#160;&#160;&#160;<span class="where">where<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;Self: <a class="trait" href="{{channel}}/core/marker/trait.Sized.html" title="trait core::marker::Sized">Sized</a></span>,
- { ... }
-}</code></pre></div> \ No newline at end of file
+ // Provided methods
+ fn <a href="#method.func" class="fn">func</a>(self)
+ <span class="where">where Self: <a class="trait" href="{{channel}}/core/marker/trait.Sized.html" title="trait core::marker::Sized">Sized</a></span> { ... }
+<span class="item-spacer" /> fn <a href="#method.lines" class="fn">lines</a>(self) -&gt; <a class="struct" href="{{channel}}/std/io/struct.Lines.html" title="struct std::io::Lines">Lines</a>&lt;Self&gt;
+ <span class="where">where Self: <a class="trait" href="{{channel}}/core/marker/trait.Sized.html" title="trait core::marker::Sized">Sized</a></span> { ... }
+<span class="item-spacer" /> fn <a href="#method.merge" class="fn">merge</a>&lt;T&gt;(self, a: T)
+ <span class="where">where Self: <a class="trait" href="{{channel}}/core/marker/trait.Sized.html" title="trait core::marker::Sized">Sized</a>,
+ T: <a class="trait" href="{{channel}}/core/marker/trait.Sized.html" title="trait core::marker::Sized">Sized</a></span> { ... }
+}</code></pre> \ No newline at end of file
diff --git a/tests/rustdoc/where.rs b/tests/rustdoc/where.rs
index 3ac0c6872..8b8a126e8 100644
--- a/tests/rustdoc/where.rs
+++ b/tests/rustdoc/where.rs
@@ -4,7 +4,7 @@ use std::io::Lines;
pub trait MyTrait { fn dummy(&self) { } }
-// @has foo/struct.Alpha.html '//pre' "pub struct Alpha<A>(_)where A: MyTrait"
+// @has foo/struct.Alpha.html '//pre' "pub struct Alpha<A>(_) where A: MyTrait"
pub struct Alpha<A>(A) where A: MyTrait;
// @has foo/trait.Bravo.html '//pre' "pub trait Bravo<B>where B: MyTrait"
pub trait Bravo<B> where B: MyTrait { fn get(&self, B: B); }
@@ -13,7 +13,7 @@ pub fn charlie<C>() where C: MyTrait {}
pub struct Delta<D>(D);
-// @has foo/struct.Delta.html '//*[@class="impl has-srclink"]//h3[@class="code-header"]' \
+// @has foo/struct.Delta.html '//*[@class="impl"]//h3[@class="code-header"]' \
// "impl<D> Delta<D>where D: MyTrait"
impl<D> Delta<D> where D: MyTrait {
pub fn delta() {}
@@ -22,13 +22,13 @@ impl<D> Delta<D> where D: MyTrait {
pub struct Echo<E>(E);
// @has 'foo/struct.Simd.html'
-// @snapshot SWhere_Simd_item-decl - '//div[@class="item-decl"]'
+// @snapshot SWhere_Simd_item-decl - '//pre[@class="rust item-decl"]'
pub struct Simd<T>([T; 1])
where
T: MyTrait;
// @has 'foo/trait.TraitWhere.html'
-// @snapshot SWhere_TraitWhere_item-decl - '//div[@class="item-decl"]'
+// @snapshot SWhere_TraitWhere_item-decl - '//pre[@class="rust item-decl"]'
pub trait TraitWhere {
type Item<'a> where Self: 'a;
@@ -41,9 +41,15 @@ pub trait TraitWhere {
where
Self: Sized,
{ todo!() }
+
+ fn merge<T>(self, a: T)
+ where
+ Self: Sized,
+ T: Sized,
+ { todo!() }
}
-// @has foo/struct.Echo.html '//*[@class="impl has-srclink"]//h3[@class="code-header"]' \
+// @has foo/struct.Echo.html '//*[@class="impl"]//h3[@class="code-header"]' \
// "impl<E> MyTrait for Echo<E>where E: MyTrait"
// @has foo/trait.MyTrait.html '//*[@id="implementors-list"]//h3[@class="code-header"]' \
// "impl<E> MyTrait for Echo<E>where E: MyTrait"
@@ -51,12 +57,12 @@ impl<E> MyTrait for Echo<E>where E: MyTrait {}
pub enum Foxtrot<F> { Foxtrot1(F) }
-// @has foo/enum.Foxtrot.html '//*[@class="impl has-srclink"]//h3[@class="code-header"]' \
+// @has foo/enum.Foxtrot.html '//*[@class="impl"]//h3[@class="code-header"]' \
// "impl<F> MyTrait for Foxtrot<F>where F: MyTrait"
// @has foo/trait.MyTrait.html '//*[@id="implementors-list"]//h3[@class="code-header"]' \
// "impl<F> MyTrait for Foxtrot<F>where F: MyTrait"
impl<F> MyTrait for Foxtrot<F>where F: MyTrait {}
-// @has foo/type.Golf.html '//div[@class="item-decl"]/pre[@class="rust"]' \
+// @has foo/type.Golf.html '//pre[@class="rust item-decl"]' \
// "type Golf<T>where T: Clone, = (T, T)"
pub type Golf<T> where T: Clone = (T, T);
diff --git a/tests/rustdoc/whitespace-after-where-clause.enum.html b/tests/rustdoc/whitespace-after-where-clause.enum.html
index 20bde549a..20b60b68e 100644
--- a/tests/rustdoc/whitespace-after-where-clause.enum.html
+++ b/tests/rustdoc/whitespace-after-where-clause.enum.html
@@ -1,4 +1,5 @@
-<div class="item-decl"><pre class="rust"><code>pub enum Cow&lt;'a, B&gt;<span class="where fmt-newline">where<br />&#160;&#160;&#160;&#160;B: <a class="trait" href="trait.ToOwned.html" title="trait foo::ToOwned">ToOwned</a>&lt;dyn <a class="trait" href="{{channel}}/core/clone/trait.Clone.html" title="trait core::clone::Clone">Clone</a>&gt; + ?<a class="trait" href="{{channel}}/core/marker/trait.Sized.html" title="trait core::marker::Sized">Sized</a> + 'a,</span>{
- Borrowed(<a class="primitive" href="{{channel}}/std/primitive.reference.html">&amp;'a </a>B),
+<pre class="rust item-decl"><code>pub enum Cow&lt;'a, B&gt;<span class="where fmt-newline">where
+ B: <a class="trait" href="trait.ToOwned.html" title="trait foo::ToOwned">ToOwned</a>&lt;dyn <a class="trait" href="{{channel}}/core/clone/trait.Clone.html" title="trait core::clone::Clone">Clone</a>&gt; + ?<a class="trait" href="{{channel}}/core/marker/trait.Sized.html" title="trait core::marker::Sized">Sized</a> + 'a,</span>{
+ Borrowed(<a class="primitive" href="{{channel}}/std/primitive.reference.html">&amp;'a B</a>),
Whatever(<a class="primitive" href="{{channel}}/std/primitive.u32.html">u32</a>),
-}</code></pre></div> \ No newline at end of file
+}</code></pre> \ No newline at end of file
diff --git a/tests/rustdoc/whitespace-after-where-clause.enum2.html b/tests/rustdoc/whitespace-after-where-clause.enum2.html
index d9fc0c223..065ce757d 100644
--- a/tests/rustdoc/whitespace-after-where-clause.enum2.html
+++ b/tests/rustdoc/whitespace-after-where-clause.enum2.html
@@ -1,4 +1,4 @@
-<div class="item-decl"><pre class="rust"><code>pub enum Cow2&lt;'a, B:&#160;?<a class="trait" href="{{channel}}/core/marker/trait.Sized.html" title="trait core::marker::Sized">Sized</a> + <a class="trait" href="trait.ToOwned.html" title="trait foo::ToOwned">ToOwned</a>&lt;dyn <a class="trait" href="{{channel}}/core/clone/trait.Clone.html" title="trait core::clone::Clone">Clone</a>&gt; + 'a&gt; {
- Borrowed(<a class="primitive" href="{{channel}}/std/primitive.reference.html">&amp;'a </a>B),
+<pre class="rust item-decl"><code>pub enum Cow2&lt;'a, B: ?<a class="trait" href="{{channel}}/core/marker/trait.Sized.html" title="trait core::marker::Sized">Sized</a> + <a class="trait" href="trait.ToOwned.html" title="trait foo::ToOwned">ToOwned</a>&lt;dyn <a class="trait" href="{{channel}}/core/clone/trait.Clone.html" title="trait core::clone::Clone">Clone</a>&gt; + 'a&gt; {
+ Borrowed(<a class="primitive" href="{{channel}}/std/primitive.reference.html">&amp;'a B</a>),
Whatever(<a class="primitive" href="{{channel}}/std/primitive.u32.html">u32</a>),
-}</code></pre></div> \ No newline at end of file
+}</code></pre> \ No newline at end of file
diff --git a/tests/rustdoc/whitespace-after-where-clause.rs b/tests/rustdoc/whitespace-after-where-clause.rs
index 4b740b970..b540c7c97 100644
--- a/tests/rustdoc/whitespace-after-where-clause.rs
+++ b/tests/rustdoc/whitespace-after-where-clause.rs
@@ -4,7 +4,7 @@
#![crate_name = "foo"]
// @has 'foo/trait.ToOwned.html'
-// @snapshot trait - '//*[@class="item-decl"]'
+// @snapshot trait - '//*[@class="rust item-decl"]'
pub trait ToOwned<T>
where T: Clone
{
@@ -14,7 +14,7 @@ where T: Clone
}
// @has 'foo/trait.ToOwned2.html'
-// @snapshot trait2 - '//*[@class="item-decl"]'
+// @snapshot trait2 - '//*[@class="rust item-decl"]'
// There should be a whitespace before `{` in this case!
pub trait ToOwned2<T: Clone> {
type Owned;
@@ -23,7 +23,7 @@ pub trait ToOwned2<T: Clone> {
}
// @has 'foo/enum.Cow.html'
-// @snapshot enum - '//*[@class="item-decl"]'
+// @snapshot enum - '//*[@class="rust item-decl"]'
pub enum Cow<'a, B: ?Sized + 'a>
where
B: ToOwned<Clone>,
@@ -33,7 +33,7 @@ where
}
// @has 'foo/enum.Cow2.html'
-// @snapshot enum2 - '//*[@class="item-decl"]'
+// @snapshot enum2 - '//*[@class="rust item-decl"]'
// There should be a whitespace before `{` in this case!
pub enum Cow2<'a, B: ?Sized + ToOwned<Clone> + 'a> {
Borrowed(&'a B),
@@ -41,7 +41,7 @@ pub enum Cow2<'a, B: ?Sized + ToOwned<Clone> + 'a> {
}
// @has 'foo/struct.Struct.html'
-// @snapshot struct - '//*[@class="item-decl"]'
+// @snapshot struct - '//*[@class="rust item-decl"]'
pub struct Struct<'a, B: ?Sized + 'a>
where
B: ToOwned<Clone>,
@@ -51,7 +51,7 @@ where
}
// @has 'foo/struct.Struct2.html'
-// @snapshot struct2 - '//*[@class="item-decl"]'
+// @snapshot struct2 - '//*[@class="rust item-decl"]'
// There should be a whitespace before `{` in this case!
pub struct Struct2<'a, B: ?Sized + ToOwned<Clone> + 'a> {
pub a: &'a B,
@@ -59,7 +59,7 @@ pub struct Struct2<'a, B: ?Sized + ToOwned<Clone> + 'a> {
}
// @has 'foo/union.Union.html'
-// @snapshot union - '//*[@class="item-decl"]'
+// @snapshot union - '//*[@class="rust item-decl"]'
pub union Union<'a, B: ?Sized + 'a>
where
B: ToOwned<Clone>,
@@ -69,7 +69,7 @@ where
}
// @has 'foo/union.Union2.html'
-// @snapshot union2 - '//*[@class="item-decl"]'
+// @snapshot union2 - '//*[@class="rust item-decl"]'
// There should be a whitespace before `{` in this case!
pub union Union2<'a, B: ?Sized + ToOwned<Clone> + 'a> {
a: &'a B,
diff --git a/tests/rustdoc/whitespace-after-where-clause.struct.html b/tests/rustdoc/whitespace-after-where-clause.struct.html
index f375265d7..948ddc499 100644
--- a/tests/rustdoc/whitespace-after-where-clause.struct.html
+++ b/tests/rustdoc/whitespace-after-where-clause.struct.html
@@ -1,4 +1,5 @@
-<div class="item-decl"><pre class="rust"><code>pub struct Struct&lt;'a, B&gt;<span class="where fmt-newline">where<br />&#160;&#160;&#160;&#160;B: <a class="trait" href="trait.ToOwned.html" title="trait foo::ToOwned">ToOwned</a>&lt;dyn <a class="trait" href="{{channel}}/core/clone/trait.Clone.html" title="trait core::clone::Clone">Clone</a>&gt; + ?<a class="trait" href="{{channel}}/core/marker/trait.Sized.html" title="trait core::marker::Sized">Sized</a> + 'a,</span>{
- pub a: <a class="primitive" href="{{channel}}/std/primitive.reference.html">&amp;'a </a>B,
+<pre class="rust item-decl"><code>pub struct Struct&lt;'a, B&gt;<span class="where fmt-newline">where
+ B: <a class="trait" href="trait.ToOwned.html" title="trait foo::ToOwned">ToOwned</a>&lt;dyn <a class="trait" href="{{channel}}/core/clone/trait.Clone.html" title="trait core::clone::Clone">Clone</a>&gt; + ?<a class="trait" href="{{channel}}/core/marker/trait.Sized.html" title="trait core::marker::Sized">Sized</a> + 'a,</span>{
+ pub a: <a class="primitive" href="{{channel}}/std/primitive.reference.html">&amp;'a B</a>,
pub b: <a class="primitive" href="{{channel}}/std/primitive.u32.html">u32</a>,
-}</code></pre></div> \ No newline at end of file
+}</code></pre> \ No newline at end of file
diff --git a/tests/rustdoc/whitespace-after-where-clause.struct2.html b/tests/rustdoc/whitespace-after-where-clause.struct2.html
index 1c59962eb..c647e8d71 100644
--- a/tests/rustdoc/whitespace-after-where-clause.struct2.html
+++ b/tests/rustdoc/whitespace-after-where-clause.struct2.html
@@ -1,4 +1,4 @@
-<div class="item-decl"><pre class="rust"><code>pub struct Struct2&lt;'a, B:&#160;?<a class="trait" href="{{channel}}/core/marker/trait.Sized.html" title="trait core::marker::Sized">Sized</a> + <a class="trait" href="trait.ToOwned.html" title="trait foo::ToOwned">ToOwned</a>&lt;dyn <a class="trait" href="{{channel}}/core/clone/trait.Clone.html" title="trait core::clone::Clone">Clone</a>&gt; + 'a&gt; {
- pub a: <a class="primitive" href="{{channel}}/std/primitive.reference.html">&amp;'a </a>B,
+<pre class="rust item-decl"><code>pub struct Struct2&lt;'a, B: ?<a class="trait" href="{{channel}}/core/marker/trait.Sized.html" title="trait core::marker::Sized">Sized</a> + <a class="trait" href="trait.ToOwned.html" title="trait foo::ToOwned">ToOwned</a>&lt;dyn <a class="trait" href="{{channel}}/core/clone/trait.Clone.html" title="trait core::clone::Clone">Clone</a>&gt; + 'a&gt; {
+ pub a: <a class="primitive" href="{{channel}}/std/primitive.reference.html">&amp;'a B</a>,
pub b: <a class="primitive" href="{{channel}}/std/primitive.u32.html">u32</a>,
-}</code></pre></div> \ No newline at end of file
+}</code></pre> \ No newline at end of file
diff --git a/tests/rustdoc/whitespace-after-where-clause.trait.html b/tests/rustdoc/whitespace-after-where-clause.trait.html
index a2df06e77..0928b48e6 100644
--- a/tests/rustdoc/whitespace-after-where-clause.trait.html
+++ b/tests/rustdoc/whitespace-after-where-clause.trait.html
@@ -1,6 +1,8 @@
-<div class="item-decl"><pre class="rust"><code>pub trait ToOwned&lt;T&gt;<span class="where fmt-newline">where<br />&#160;&#160;&#160;&#160;T: <a class="trait" href="{{channel}}/core/clone/trait.Clone.html" title="trait core::clone::Clone">Clone</a>,</span>{
+<pre class="rust item-decl"><code>pub trait ToOwned&lt;T&gt;<span class="where fmt-newline">where
+ T: <a class="trait" href="{{channel}}/core/clone/trait.Clone.html" title="trait core::clone::Clone">Clone</a>,</span>{
type <a href="#associatedtype.Owned" class="associatedtype">Owned</a>;
+ // Required methods
fn <a href="#tymethod.to_owned" class="fn">to_owned</a>(&amp;self) -&gt; Self::<a class="associatedtype" href="trait.ToOwned.html#associatedtype.Owned" title="type foo::ToOwned::Owned">Owned</a>;
<span class="item-spacer" /> fn <a href="#tymethod.whatever" class="fn">whatever</a>(&amp;self) -&gt; T;
-}</code></pre></div> \ No newline at end of file
+}</code></pre> \ No newline at end of file
diff --git a/tests/rustdoc/whitespace-after-where-clause.trait2.html b/tests/rustdoc/whitespace-after-where-clause.trait2.html
index 2bfd6f768..e6fafde1e 100644
--- a/tests/rustdoc/whitespace-after-where-clause.trait2.html
+++ b/tests/rustdoc/whitespace-after-where-clause.trait2.html
@@ -1,6 +1,7 @@
-<div class="item-decl"><pre class="rust"><code>pub trait ToOwned2&lt;T:&#160;<a class="trait" href="{{channel}}/core/clone/trait.Clone.html" title="trait core::clone::Clone">Clone</a>&gt; {
+<pre class="rust item-decl"><code>pub trait ToOwned2&lt;T:&#160;<a class="trait" href="{{channel}}/core/clone/trait.Clone.html" title="trait core::clone::Clone">Clone</a>&gt; {
type <a href="#associatedtype.Owned" class="associatedtype">Owned</a>;
+ // Required methods
fn <a href="#tymethod.to_owned" class="fn">to_owned</a>(&amp;self) -&gt; Self::<a class="associatedtype" href="trait.ToOwned2.html#associatedtype.Owned" title="type foo::ToOwned2::Owned">Owned</a>;
<span class="item-spacer" /> fn <a href="#tymethod.whatever" class="fn">whatever</a>(&amp;self) -&gt; T;
-}</code></pre></div> \ No newline at end of file
+}</code></pre> \ No newline at end of file
diff --git a/tests/rustdoc/whitespace-after-where-clause.union.html b/tests/rustdoc/whitespace-after-where-clause.union.html
index 066f8f87b..38b6cb8b5 100644
--- a/tests/rustdoc/whitespace-after-where-clause.union.html
+++ b/tests/rustdoc/whitespace-after-where-clause.union.html
@@ -1,3 +1,4 @@
-<div class="item-decl"><pre class="rust"><code>pub union Union&lt;'a, B&gt;<span class="where fmt-newline">where<br />&#160;&#160;&#160;&#160;B: <a class="trait" href="trait.ToOwned.html" title="trait foo::ToOwned">ToOwned</a>&lt;dyn <a class="trait" href="{{channel}}/core/clone/trait.Clone.html" title="trait core::clone::Clone">Clone</a>&gt; + ?<a class="trait" href="{{channel}}/core/marker/trait.Sized.html" title="trait core::marker::Sized">Sized</a> + 'a,</span>{
+<pre class="rust item-decl"><code>pub union Union&lt;'a, B&gt;<span class="where fmt-newline">where
+ B: <a class="trait" href="trait.ToOwned.html" title="trait foo::ToOwned">ToOwned</a>&lt;dyn <a class="trait" href="{{channel}}/core/clone/trait.Clone.html" title="trait core::clone::Clone">Clone</a>&gt; + ?<a class="trait" href="{{channel}}/core/marker/trait.Sized.html" title="trait core::marker::Sized">Sized</a> + 'a,</span>{
/* private fields */
-}</code></pre></div> \ No newline at end of file
+}</code></pre> \ No newline at end of file
diff --git a/tests/rustdoc/whitespace-after-where-clause.union2.html b/tests/rustdoc/whitespace-after-where-clause.union2.html
index 6b48c5dbd..66ad30c92 100644
--- a/tests/rustdoc/whitespace-after-where-clause.union2.html
+++ b/tests/rustdoc/whitespace-after-where-clause.union2.html
@@ -1,3 +1,3 @@
-<div class="item-decl"><pre class="rust"><code>pub union Union2&lt;'a, B:&#160;?<a class="trait" href="{{channel}}/core/marker/trait.Sized.html" title="trait core::marker::Sized">Sized</a> + <a class="trait" href="trait.ToOwned.html" title="trait foo::ToOwned">ToOwned</a>&lt;dyn <a class="trait" href="{{channel}}/core/clone/trait.Clone.html" title="trait core::clone::Clone">Clone</a>&gt; + 'a&gt; {
+<pre class="rust item-decl"><code>pub union Union2&lt;'a, B: ?<a class="trait" href="{{channel}}/core/marker/trait.Sized.html" title="trait core::marker::Sized">Sized</a> + <a class="trait" href="trait.ToOwned.html" title="trait foo::ToOwned">ToOwned</a>&lt;dyn <a class="trait" href="{{channel}}/core/clone/trait.Clone.html" title="trait core::clone::Clone">Clone</a>&gt; + 'a&gt; {
/* private fields */
-}</code></pre></div> \ No newline at end of file
+}</code></pre> \ No newline at end of file
diff --git a/tests/rustdoc/wrapping.rs b/tests/rustdoc/wrapping.rs
index 178b8adc3..dd5c70032 100644
--- a/tests/rustdoc/wrapping.rs
+++ b/tests/rustdoc/wrapping.rs
@@ -1,5 +1,5 @@
use std::fmt::Debug;
-// @has 'wrapping/fn.foo.html' '//div[@class="item-decl"]/pre[@class="rust"]' 'pub fn foo() -> impl Debug'
-// @count - '//div[@class="item-decl"]/pre[@class="rust"]/br' 0
+// @has 'wrapping/fn.foo.html' '//pre[@class="rust item-decl"]' 'pub fn foo() -> impl Debug'
+// @count - '//pre[@class="rust item-decl"]/br' 0
pub fn foo() -> impl Debug {}
diff --git a/tests/ui-fulldeps/auxiliary/issue-40001-plugin.rs b/tests/ui-fulldeps/auxiliary/issue-40001-plugin.rs
index c05443488..3f6caecaa 100644
--- a/tests/ui-fulldeps/auxiliary/issue-40001-plugin.rs
+++ b/tests/ui-fulldeps/auxiliary/issue-40001-plugin.rs
@@ -16,6 +16,7 @@ use rustc_hir as hir;
use rustc_hir::intravisit;
use rustc_hir::Node;
use rustc_lint::{LateContext, LateLintPass, LintContext};
+use rustc_span::def_id::LocalDefId;
use rustc_span::source_map;
#[no_mangle]
@@ -40,8 +41,9 @@ impl<'tcx> LateLintPass<'tcx> for MissingAllowedAttrPass {
_: &'tcx hir::FnDecl,
_: &'tcx hir::Body,
span: source_map::Span,
- id: hir::HirId,
+ def_id: LocalDefId,
) {
+ let id = cx.tcx.hir().local_def_id_to_hir_id(def_id);
let item = match cx.tcx.hir().get(id) {
Node::Item(item) => item,
_ => cx.tcx.hir().expect_item(cx.tcx.hir().get_parent_item(id).def_id),
diff --git a/tests/ui-fulldeps/create-dir-all-bare.rs b/tests/ui-fulldeps/create-dir-all-bare.rs
deleted file mode 100644
index 4554680ec..000000000
--- a/tests/ui-fulldeps/create-dir-all-bare.rs
+++ /dev/null
@@ -1,11 +0,0 @@
-// run-pass
-
-use std::env;
-use std::fs;
-use std::path::PathBuf;
-
-fn main() {
- let path = PathBuf::from(env::var_os("RUST_TEST_TMPDIR").unwrap());
- env::set_current_dir(&path).unwrap();
- fs::create_dir_all("create-dir-all-bare").unwrap();
-}
diff --git a/tests/ui-fulldeps/dropck-tarena-cycle-checked.stderr b/tests/ui-fulldeps/dropck-tarena-cycle-checked.stderr
index 429968822..47897dc00 100644
--- a/tests/ui-fulldeps/dropck-tarena-cycle-checked.stderr
+++ b/tests/ui-fulldeps/dropck-tarena-cycle-checked.stderr
@@ -1,6 +1,8 @@
error[E0597]: `arena` does not live long enough
--> $DIR/dropck-tarena-cycle-checked.rs:116:7
|
+LL | let arena = TypedArena::default();
+ | ----- binding `arena` declared here
LL | f(&arena);
| ^^^^^^ borrowed value does not live long enough
LL | }
diff --git a/tests/ui-fulldeps/dropck-tarena-unsound-drop.stderr b/tests/ui-fulldeps/dropck-tarena-unsound-drop.stderr
index ccffee9cd..493d74b0b 100644
--- a/tests/ui-fulldeps/dropck-tarena-unsound-drop.stderr
+++ b/tests/ui-fulldeps/dropck-tarena-unsound-drop.stderr
@@ -1,6 +1,8 @@
error[E0597]: `arena` does not live long enough
--> $DIR/dropck-tarena-unsound-drop.rs:41:7
|
+LL | let arena: TypedArena<C> = TypedArena::default();
+ | ----- binding `arena` declared here
LL | f(&arena);
| ^^^^^^ borrowed value does not live long enough
LL | }
diff --git a/tests/ui-fulldeps/fluent-messages/duplicate.ftl b/tests/ui-fulldeps/fluent-messages/duplicate.ftl
new file mode 100644
index 000000000..871550b23
--- /dev/null
+++ b/tests/ui-fulldeps/fluent-messages/duplicate.ftl
@@ -0,0 +1,3 @@
+no_crate_a_b_key = Value
+
+no_crate_a_b_key = Another Value
diff --git a/tests/ui-fulldeps/fluent-messages/label-with-hyphens.ftl b/tests/ui-fulldeps/fluent-messages/label-with-hyphens.ftl
index 016cbeef6..3088b1f8d 100644
--- a/tests/ui-fulldeps/fluent-messages/label-with-hyphens.ftl
+++ b/tests/ui-fulldeps/fluent-messages/label-with-hyphens.ftl
@@ -1,2 +1,2 @@
-label_with_hyphens_some_slug = hi
+no_crate_some_slug = hi
.label-has-hyphens = test
diff --git a/tests/ui-fulldeps/fluent-messages/missing-crate-name.ftl b/tests/ui-fulldeps/fluent-messages/missing-crate-name.ftl
index 9bd035c1b..0a64e3894 100644
--- a/tests/ui-fulldeps/fluent-messages/missing-crate-name.ftl
+++ b/tests/ui-fulldeps/fluent-messages/missing-crate-name.ftl
@@ -1,2 +1,2 @@
with-hyphens = 1234
-test-crate_foo = abcd
+no-crate_foo = abcd
diff --git a/tests/ui-fulldeps/fluent-messages/missing-message-ref.ftl b/tests/ui-fulldeps/fluent-messages/missing-message-ref.ftl
new file mode 100644
index 000000000..4c6514a97
--- /dev/null
+++ b/tests/ui-fulldeps/fluent-messages/missing-message-ref.ftl
@@ -0,0 +1 @@
+no_crate_missing_message_ref = {message}
diff --git a/tests/ui-fulldeps/fluent-messages/missing-message.ftl b/tests/ui-fulldeps/fluent-messages/missing-message.ftl
index 74b2aa1d4..61f56fd4d 100644
--- a/tests/ui-fulldeps/fluent-messages/missing-message.ftl
+++ b/tests/ui-fulldeps/fluent-messages/missing-message.ftl
@@ -1 +1 @@
-missing_message =
+no_crate_missing_message =
diff --git a/tests/ui-fulldeps/fluent-messages/slug-with-hyphens.ftl b/tests/ui-fulldeps/fluent-messages/slug-with-hyphens.ftl
index 86ba9a268..a64c85094 100644
--- a/tests/ui-fulldeps/fluent-messages/slug-with-hyphens.ftl
+++ b/tests/ui-fulldeps/fluent-messages/slug-with-hyphens.ftl
@@ -1 +1 @@
-slug_with_hyphens_this-slug-has-hyphens = hi
+no_crate_this-slug-has-hyphens = hi
diff --git a/tests/ui-fulldeps/fluent-messages/test.rs b/tests/ui-fulldeps/fluent-messages/test.rs
index 4e8147e2b..66575eb8e 100644
--- a/tests/ui-fulldeps/fluent-messages/test.rs
+++ b/tests/ui-fulldeps/fluent-messages/test.rs
@@ -21,78 +21,74 @@ pub enum SubdiagnosticMessage {
mod missing_absolute {
use super::fluent_messages;
- fluent_messages! {
- missing_absolute => "/definitely_does_not_exist.ftl",
-//~^ ERROR could not open Fluent resource
- }
+ fluent_messages! { "/definitely_does_not_exist.ftl" }
+ //~^ ERROR could not open Fluent resource
}
mod missing_relative {
use super::fluent_messages;
- fluent_messages! {
- missing_relative => "../definitely_does_not_exist.ftl",
-//~^ ERROR could not open Fluent resource
- }
+ fluent_messages! { "../definitely_does_not_exist.ftl" }
+ //~^ ERROR could not open Fluent resource
}
mod missing_message {
use super::fluent_messages;
- fluent_messages! {
- missing_message => "./missing-message.ftl",
-//~^ ERROR could not parse Fluent resource
- }
+ fluent_messages! { "./missing-message.ftl" }
+ //~^ ERROR could not parse Fluent resource
}
mod duplicate {
use super::fluent_messages;
- fluent_messages! {
-//~^ ERROR the name `a_b_key` is defined multiple times
- a => "./duplicate-a.ftl",
- a_b => "./duplicate-a-b.ftl",
-//~^ ERROR overrides existing message: `a_b_key`
- }
+ fluent_messages! { "./duplicate.ftl" }
+ //~^ ERROR overrides existing message: `no_crate_a_b_key`
}
mod slug_with_hyphens {
use super::fluent_messages;
- fluent_messages! {
- slug_with_hyphens => "./slug-with-hyphens.ftl",
-//~^ ERROR name `slug_with_hyphens_this-slug-has-hyphens` contains a '-' character
- }
+ fluent_messages! { "./slug-with-hyphens.ftl" }
+ //~^ ERROR name `no_crate_this-slug-has-hyphens` contains a '-' character
}
mod label_with_hyphens {
use super::fluent_messages;
- fluent_messages! {
- label_with_hyphens => "./label-with-hyphens.ftl",
-//~^ ERROR attribute `label-has-hyphens` contains a '-' character
- }
+ fluent_messages! { "./label-with-hyphens.ftl" }
+ //~^ ERROR attribute `label-has-hyphens` contains a '-' character
}
mod valid {
use super::fluent_messages;
- fluent_messages! {
- valid => "./valid.ftl",
- }
+ fluent_messages! { "./valid.ftl" }
- use self::fluent_generated::{DEFAULT_LOCALE_RESOURCES, valid_key};
+ mod test_generated {
+ use super::{fluent_generated::no_crate_key, DEFAULT_LOCALE_RESOURCE};
+ }
}
mod missing_crate_name {
use super::fluent_messages;
- fluent_messages! {
- test_crate => "./missing-crate-name.ftl",
-//~^ ERROR name `test-crate_foo` contains a '-' character
-//~| ERROR name `with-hyphens` contains a '-' character
-//~| ERROR name `with-hyphens` does not start with the crate name
+ fluent_messages! { "./missing-crate-name.ftl" }
+ //~^ ERROR name `no-crate_foo` contains a '-' character
+ //~| ERROR name `with-hyphens` contains a '-' character
+ //~| ERROR name `with-hyphens` does not start with the crate name
+
+ mod test_generated {
+ use super::{
+ fluent_generated::{no_crate_foo, with_hyphens},
+ DEFAULT_LOCALE_RESOURCE,
+ };
}
+}
+
+mod missing_message_ref {
+ use super::fluent_messages;
- use self::fluent_generated::{DEFAULT_LOCALE_RESOURCES, test_crate_foo, with_hyphens};
+ fluent_messages! { "./missing-message-ref.ftl" }
+ //~^ ERROR referenced message `message` does not exist
}
diff --git a/tests/ui-fulldeps/fluent-messages/test.stderr b/tests/ui-fulldeps/fluent-messages/test.stderr
index d1cd4fe26..c7961ed22 100644
--- a/tests/ui-fulldeps/fluent-messages/test.stderr
+++ b/tests/ui-fulldeps/fluent-messages/test.stderr
@@ -1,98 +1,87 @@
error: could not open Fluent resource
- --> $DIR/test.rs:25:29
+ --> $DIR/test.rs:24:24
|
-LL | missing_absolute => "/definitely_does_not_exist.ftl",
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | fluent_messages! { "/definitely_does_not_exist.ftl" }
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: os-specific message
error: could not open Fluent resource
- --> $DIR/test.rs:34:29
+ --> $DIR/test.rs:31:24
|
-LL | missing_relative => "../definitely_does_not_exist.ftl",
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | fluent_messages! { "../definitely_does_not_exist.ftl" }
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: os-specific message
error: could not parse Fluent resource
- --> $DIR/test.rs:43:28
+ --> $DIR/test.rs:38:24
|
-LL | missing_message => "./missing-message.ftl",
- | ^^^^^^^^^^^^^^^^^^^^^^^
+LL | fluent_messages! { "./missing-message.ftl" }
+ | ^^^^^^^^^^^^^^^^^^^^^^^
|
= help: see additional errors emitted
-error: expected a message field for "missing_message"
+error: expected a message field for "no_crate_missing_message"
--> ./missing-message.ftl:1:1
|
-1 | missing_message =
- | ^^^^^^^^^^^^^^^^^
+1 | no_crate_missing_message =
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
-error: overrides existing message: `a_b_key`
- --> $DIR/test.rs:54:16
+error: overrides existing message: `no_crate_a_b_key`
+ --> $DIR/test.rs:45:24
|
-LL | a_b => "./duplicate-a-b.ftl",
- | ^^^^^^^^^^^^^^^^^^^^^
- |
-help: previously defined in this resource
- --> $DIR/test.rs:53:14
- |
-LL | a => "./duplicate-a.ftl",
- | ^^^^^^^^^^^^^^^^^^^
-
-error[E0428]: the name `a_b_key` is defined multiple times
- --> $DIR/test.rs:51:5
- |
-LL | fluent_messages! {
- | ^^^^^^^^^^^^^^^^
- | |
- | `a_b_key` redefined here
- | previous definition of the value `a_b_key` here
- |
- = note: os-specific message
- = note: os-specific message
+LL | fluent_messages! { "./duplicate.ftl" }
+ | ^^^^^^^^^^^^^^^^^
-error: name `slug_with_hyphens_this-slug-has-hyphens` contains a '-' character
- --> $DIR/test.rs:63:30
+error: name `no_crate_this-slug-has-hyphens` contains a '-' character
+ --> $DIR/test.rs:52:24
|
-LL | slug_with_hyphens => "./slug-with-hyphens.ftl",
- | ^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | fluent_messages! { "./slug-with-hyphens.ftl" }
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^
|
= help: replace any '-'s with '_'s
error: attribute `label-has-hyphens` contains a '-' character
- --> $DIR/test.rs:72:31
+ --> $DIR/test.rs:59:24
|
-LL | label_with_hyphens => "./label-with-hyphens.ftl",
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | fluent_messages! { "./label-with-hyphens.ftl" }
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= help: replace any '-'s with '_'s
error: name `with-hyphens` contains a '-' character
- --> $DIR/test.rs:91:23
+ --> $DIR/test.rs:76:24
|
-LL | test_crate => "./missing-crate-name.ftl",
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | fluent_messages! { "./missing-crate-name.ftl" }
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= help: replace any '-'s with '_'s
error: name `with-hyphens` does not start with the crate name
- --> $DIR/test.rs:91:23
+ --> $DIR/test.rs:76:24
|
-LL | test_crate => "./missing-crate-name.ftl",
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | fluent_messages! { "./missing-crate-name.ftl" }
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
- = help: prepend `test_crate_` to the slug name: `test_crate_with_hyphens`
+ = help: prepend `no_crate_` to the slug name: `no_crate_with_hyphens`
-error: name `test-crate_foo` contains a '-' character
- --> $DIR/test.rs:91:23
+error: name `no-crate_foo` contains a '-' character
+ --> $DIR/test.rs:76:24
|
-LL | test_crate => "./missing-crate-name.ftl",
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | fluent_messages! { "./missing-crate-name.ftl" }
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= help: replace any '-'s with '_'s
+error: referenced message `message` does not exist (in message `no_crate_missing_message_ref`)
+ --> $DIR/test.rs:92:24
+ |
+LL | fluent_messages! { "./missing-message-ref.ftl" }
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = help: you may have meant to use a variable reference (`{$message}`)
+
error: aborting due to 10 previous errors
-For more information about this error, try `rustc --explain E0428`.
diff --git a/tests/ui-fulldeps/fluent-messages/valid.ftl b/tests/ui-fulldeps/fluent-messages/valid.ftl
index 549274306..598473adb 100644
--- a/tests/ui-fulldeps/fluent-messages/valid.ftl
+++ b/tests/ui-fulldeps/fluent-messages/valid.ftl
@@ -1 +1 @@
-valid_key = Valid!
+no_crate_key = Valid!
diff --git a/compiler/rustc_error_messages/locales/en-US/compiletest.ftl b/tests/ui-fulldeps/internal-lints/diagnostics.ftl
index 55061fbce..cb2d476d8 100644
--- a/compiler/rustc_error_messages/locales/en-US/compiletest.ftl
+++ b/tests/ui-fulldeps/internal-lints/diagnostics.ftl
@@ -1,4 +1,4 @@
-compiletest_example = this is an example message used in testing
+no_crate_example = this is an example message used in testing
.note = with a note
.help = with a help
.suggestion = with a suggestion
diff --git a/tests/ui-fulldeps/internal-lints/diagnostics.rs b/tests/ui-fulldeps/internal-lints/diagnostics.rs
index 643e81d99..3aa65d53d 100644
--- a/tests/ui-fulldeps/internal-lints/diagnostics.rs
+++ b/tests/ui-fulldeps/internal-lints/diagnostics.rs
@@ -13,20 +13,22 @@ extern crate rustc_span;
use rustc_errors::{
AddToDiagnostic, IntoDiagnostic, Diagnostic, DiagnosticBuilder,
- ErrorGuaranteed, Handler, fluent, SubdiagnosticMessage,
+ ErrorGuaranteed, Handler, DiagnosticMessage, SubdiagnosticMessage,
};
-use rustc_macros::{Diagnostic, Subdiagnostic};
+use rustc_macros::{fluent_messages, Diagnostic, Subdiagnostic};
use rustc_span::Span;
+fluent_messages! { "./diagnostics.ftl" }
+
#[derive(Diagnostic)]
-#[diag(compiletest_example)]
+#[diag(no_crate_example)]
struct DeriveDiagnostic {
#[primary_span]
span: Span,
}
#[derive(Subdiagnostic)]
-#[note(compiletest_example)]
+#[note(no_crate_example)]
struct Note {
#[primary_span]
span: Span,
@@ -45,7 +47,7 @@ pub struct TranslatableInIntoDiagnostic;
impl<'a> IntoDiagnostic<'a, ErrorGuaranteed> for TranslatableInIntoDiagnostic {
fn into_diagnostic(self, handler: &'a Handler) -> DiagnosticBuilder<'a, ErrorGuaranteed> {
- handler.struct_err(fluent::compiletest_example)
+ handler.struct_err(crate::fluent_generated::no_crate_example)
}
}
@@ -68,12 +70,12 @@ impl AddToDiagnostic for TranslatableInAddToDiagnostic {
where
F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage,
{
- diag.note(fluent::note);
+ diag.note(crate::fluent_generated::no_crate_note);
}
}
pub fn make_diagnostics<'a>(handler: &'a Handler) {
- let _diag = handler.struct_err(fluent::compiletest_example);
+ let _diag = handler.struct_err(crate::fluent_generated::no_crate_example);
//~^ ERROR diagnostics should only be created in `IntoDiagnostic`/`AddToDiagnostic` impls
let _diag = handler.struct_err("untranslatable diagnostic");
diff --git a/tests/ui-fulldeps/internal-lints/diagnostics.stderr b/tests/ui-fulldeps/internal-lints/diagnostics.stderr
index 510d6a171..6f797ebc2 100644
--- a/tests/ui-fulldeps/internal-lints/diagnostics.stderr
+++ b/tests/ui-fulldeps/internal-lints/diagnostics.stderr
@@ -1,5 +1,5 @@
error: diagnostics should be created using translatable messages
- --> $DIR/diagnostics.rs:39:17
+ --> $DIR/diagnostics.rs:41:17
|
LL | handler.struct_err("untranslatable diagnostic")
| ^^^^^^^^^^
@@ -11,15 +11,15 @@ LL | #![deny(rustc::untranslatable_diagnostic)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: diagnostics should be created using translatable messages
- --> $DIR/diagnostics.rs:59:14
+ --> $DIR/diagnostics.rs:61:14
|
LL | diag.note("untranslatable diagnostic");
| ^^^^
error: diagnostics should only be created in `IntoDiagnostic`/`AddToDiagnostic` impls
- --> $DIR/diagnostics.rs:76:25
+ --> $DIR/diagnostics.rs:78:25
|
-LL | let _diag = handler.struct_err(fluent::compiletest_example);
+LL | let _diag = handler.struct_err(crate::fluent_generated::no_crate_example);
| ^^^^^^^^^^
|
note: the lint level is defined here
@@ -29,13 +29,13 @@ LL | #![deny(rustc::diagnostic_outside_of_impl)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: diagnostics should only be created in `IntoDiagnostic`/`AddToDiagnostic` impls
- --> $DIR/diagnostics.rs:79:25
+ --> $DIR/diagnostics.rs:81:25
|
LL | let _diag = handler.struct_err("untranslatable diagnostic");
| ^^^^^^^^^^
error: diagnostics should be created using translatable messages
- --> $DIR/diagnostics.rs:79:25
+ --> $DIR/diagnostics.rs:81:25
|
LL | let _diag = handler.struct_err("untranslatable diagnostic");
| ^^^^^^^^^^
diff --git a/tests/ui-fulldeps/internal-lints/ty_tykind_usage.rs b/tests/ui-fulldeps/internal-lints/ty_tykind_usage.rs
index 3f7429a5f..bf655510a 100644
--- a/tests/ui-fulldeps/internal-lints/ty_tykind_usage.rs
+++ b/tests/ui-fulldeps/internal-lints/ty_tykind_usage.rs
@@ -31,6 +31,7 @@ fn main() {
TyKind::Closure(..) => (), //~ ERROR usage of `ty::TyKind::<kind>`
TyKind::Generator(..) => (), //~ ERROR usage of `ty::TyKind::<kind>`
TyKind::GeneratorWitness(..) => (), //~ ERROR usage of `ty::TyKind::<kind>`
+ TyKind::GeneratorWitnessMIR(..) => (), //~ ERROR usage of `ty::TyKind::<kind>`
TyKind::Never => (), //~ ERROR usage of `ty::TyKind::<kind>`
TyKind::Tuple(..) => (), //~ ERROR usage of `ty::TyKind::<kind>`
TyKind::Alias(..) => (), //~ ERROR usage of `ty::TyKind::<kind>`
diff --git a/tests/ui-fulldeps/internal-lints/ty_tykind_usage.stderr b/tests/ui-fulldeps/internal-lints/ty_tykind_usage.stderr
index 1f49d6b64..9f8c0bea0 100644
--- a/tests/ui-fulldeps/internal-lints/ty_tykind_usage.stderr
+++ b/tests/ui-fulldeps/internal-lints/ty_tykind_usage.stderr
@@ -121,59 +121,65 @@ LL | TyKind::GeneratorWitness(..) => (),
error: usage of `ty::TyKind::<kind>`
--> $DIR/ty_tykind_usage.rs:34:9
|
-LL | TyKind::Never => (),
+LL | TyKind::GeneratorWitnessMIR(..) => (),
| ^^^^^^ help: try using `ty::<kind>` directly: `ty`
error: usage of `ty::TyKind::<kind>`
--> $DIR/ty_tykind_usage.rs:35:9
|
-LL | TyKind::Tuple(..) => (),
+LL | TyKind::Never => (),
| ^^^^^^ help: try using `ty::<kind>` directly: `ty`
error: usage of `ty::TyKind::<kind>`
--> $DIR/ty_tykind_usage.rs:36:9
|
-LL | TyKind::Alias(..) => (),
+LL | TyKind::Tuple(..) => (),
| ^^^^^^ help: try using `ty::<kind>` directly: `ty`
error: usage of `ty::TyKind::<kind>`
--> $DIR/ty_tykind_usage.rs:37:9
|
-LL | TyKind::Param(..) => (),
+LL | TyKind::Alias(..) => (),
| ^^^^^^ help: try using `ty::<kind>` directly: `ty`
error: usage of `ty::TyKind::<kind>`
--> $DIR/ty_tykind_usage.rs:38:9
|
-LL | TyKind::Bound(..) => (),
+LL | TyKind::Param(..) => (),
| ^^^^^^ help: try using `ty::<kind>` directly: `ty`
error: usage of `ty::TyKind::<kind>`
--> $DIR/ty_tykind_usage.rs:39:9
|
-LL | TyKind::Placeholder(..) => (),
+LL | TyKind::Bound(..) => (),
| ^^^^^^ help: try using `ty::<kind>` directly: `ty`
error: usage of `ty::TyKind::<kind>`
--> $DIR/ty_tykind_usage.rs:40:9
|
-LL | TyKind::Infer(..) => (),
+LL | TyKind::Placeholder(..) => (),
| ^^^^^^ help: try using `ty::<kind>` directly: `ty`
error: usage of `ty::TyKind::<kind>`
--> $DIR/ty_tykind_usage.rs:41:9
|
+LL | TyKind::Infer(..) => (),
+ | ^^^^^^ help: try using `ty::<kind>` directly: `ty`
+
+error: usage of `ty::TyKind::<kind>`
+ --> $DIR/ty_tykind_usage.rs:42:9
+ |
LL | TyKind::Error(_) => (),
| ^^^^^^ help: try using `ty::<kind>` directly: `ty`
error: usage of `ty::TyKind::<kind>`
- --> $DIR/ty_tykind_usage.rs:46:12
+ --> $DIR/ty_tykind_usage.rs:47:12
|
LL | if let TyKind::Int(int_ty) = kind {}
| ^^^^^^ help: try using `ty::<kind>` directly: `ty`
error: usage of `ty::TyKind`
- --> $DIR/ty_tykind_usage.rs:48:24
+ --> $DIR/ty_tykind_usage.rs:49:24
|
LL | fn ty_kind(ty_bad: TyKind<'_>, ty_good: Ty<'_>) {}
| ^^^^^^^^^^
@@ -181,7 +187,7 @@ LL | fn ty_kind(ty_bad: TyKind<'_>, ty_good: Ty<'_>) {}
= help: try using `Ty` instead
error: usage of `ty::TyKind`
- --> $DIR/ty_tykind_usage.rs:50:37
+ --> $DIR/ty_tykind_usage.rs:51:37
|
LL | fn ir_ty_kind<I: Interner>(bad: IrTyKind<I>) -> IrTyKind<I> {
| ^^^^^^^^^^^
@@ -189,7 +195,7 @@ LL | fn ir_ty_kind<I: Interner>(bad: IrTyKind<I>) -> IrTyKind<I> {
= help: try using `Ty` instead
error: usage of `ty::TyKind`
- --> $DIR/ty_tykind_usage.rs:50:53
+ --> $DIR/ty_tykind_usage.rs:51:53
|
LL | fn ir_ty_kind<I: Interner>(bad: IrTyKind<I>) -> IrTyKind<I> {
| ^^^^^^^^^^^
@@ -197,12 +203,12 @@ LL | fn ir_ty_kind<I: Interner>(bad: IrTyKind<I>) -> IrTyKind<I> {
= help: try using `Ty` instead
error: usage of `ty::TyKind::<kind>`
- --> $DIR/ty_tykind_usage.rs:53:9
+ --> $DIR/ty_tykind_usage.rs:54:9
|
LL | IrTyKind::Bool
| --------^^^^^^
| |
| help: try using `ty::<kind>` directly: `ty`
-error: aborting due to 32 previous errors
+error: aborting due to 33 previous errors
diff --git a/tests/ui-fulldeps/mod_dir_path_canonicalized.rs b/tests/ui-fulldeps/mod_dir_path_canonicalized.rs
index bdfd9628c..ddc86c1dc 100644
--- a/tests/ui-fulldeps/mod_dir_path_canonicalized.rs
+++ b/tests/ui-fulldeps/mod_dir_path_canonicalized.rs
@@ -31,7 +31,10 @@ pub fn main() {
}
fn parse() {
- let parse_session = ParseSess::new(FilePathMapping::empty());
+ let parse_session = ParseSess::new(
+ vec![rustc_parse::DEFAULT_LOCALE_RESOURCE],
+ FilePathMapping::empty()
+ );
let path = Path::new(file!());
let path = path.canonicalize().unwrap();
diff --git a/tests/ui-fulldeps/pprust-expr-roundtrip.rs b/tests/ui-fulldeps/pprust-expr-roundtrip.rs
index 7a91dcf0d..e417a6a83 100644
--- a/tests/ui-fulldeps/pprust-expr-roundtrip.rs
+++ b/tests/ui-fulldeps/pprust-expr-roundtrip.rs
@@ -41,7 +41,7 @@ use rustc_session::parse::ParseSess;
use rustc_span::source_map::FilePathMapping;
use rustc_span::source_map::{FileName, Spanned, DUMMY_SP};
use rustc_span::symbol::Ident;
-use thin_vec::thin_vec;
+use thin_vec::{thin_vec, ThinVec};
fn parse_expr(ps: &ParseSess, src: &str) -> Option<P<Expr>> {
let src_as_string = src.to_string();
@@ -76,17 +76,17 @@ fn iter_exprs(depth: usize, f: &mut dyn FnMut(P<Expr>)) {
for kind in 0..=19 {
match kind {
0 => iter_exprs(depth - 1, &mut |e| g(ExprKind::Box(e))),
- 1 => iter_exprs(depth - 1, &mut |e| g(ExprKind::Call(e, vec![]))),
+ 1 => iter_exprs(depth - 1, &mut |e| g(ExprKind::Call(e, thin_vec![]))),
2 => {
let seg = PathSegment::from_ident(Ident::from_str("x"));
iter_exprs(depth - 1, &mut |e| {
g(ExprKind::MethodCall(Box::new(MethodCall {
- seg: seg.clone(), receiver: e, args: vec![make_x()], span: DUMMY_SP
+ seg: seg.clone(), receiver: e, args: thin_vec![make_x()], span: DUMMY_SP
}))
)});
iter_exprs(depth - 1, &mut |e| {
g(ExprKind::MethodCall(Box::new(MethodCall {
- seg: seg.clone(), receiver: make_x(), args: vec![e], span: DUMMY_SP
+ seg: seg.clone(), receiver: make_x(), args: thin_vec![e], span: DUMMY_SP
}))
)});
}
@@ -111,7 +111,7 @@ fn iter_exprs(depth: usize, f: &mut dyn FnMut(P<Expr>)) {
}
10 => {
let block = P(Block {
- stmts: Vec::new(),
+ stmts: ThinVec::new(),
id: DUMMY_NODE_ID,
rules: BlockCheckMode::Default,
span: DUMMY_SP,
@@ -121,7 +121,7 @@ fn iter_exprs(depth: usize, f: &mut dyn FnMut(P<Expr>)) {
iter_exprs(depth - 1, &mut |e| g(ExprKind::If(e, block.clone(), None)));
}
11 => {
- let decl = P(FnDecl { inputs: vec![], output: FnRetTy::Default(DUMMY_SP) });
+ let decl = P(FnDecl { inputs: thin_vec![], output: FnRetTy::Default(DUMMY_SP) });
iter_exprs(depth - 1, &mut |e| {
g(ExprKind::Closure(Box::new(Closure {
binder: ClosureBinder::NotPresent,
@@ -165,7 +165,7 @@ fn iter_exprs(depth: usize, f: &mut dyn FnMut(P<Expr>)) {
g(ExprKind::Struct(P(StructExpr {
qself: None,
path,
- fields: vec![],
+ fields: thin_vec![],
rest: StructRest::Base(make_x()),
})));
}
@@ -220,7 +220,7 @@ fn main() {
}
fn run() {
- let ps = ParseSess::new(FilePathMapping::empty());
+ let ps = ParseSess::new(vec![rustc_parse::DEFAULT_LOCALE_RESOURCE], FilePathMapping::empty());
iter_exprs(2, &mut |mut e| {
// If the pretty printer is correct, then `parse(print(e))` should be identical to `e`,
diff --git a/tests/ui-fulldeps/rename-directory.rs b/tests/ui-fulldeps/rename-directory.rs
deleted file mode 100644
index 8fc340cb9..000000000
--- a/tests/ui-fulldeps/rename-directory.rs
+++ /dev/null
@@ -1,30 +0,0 @@
-// run-pass
-
-#![allow(unused_must_use)]
-#![allow(unused_imports)]
-// This test can't be a unit test in std,
-// because it needs TempDir, which is in extra
-
-// ignore-cross-compile
-
-use std::env;
-use std::ffi::CString;
-use std::fs::{self, File};
-use std::path::PathBuf;
-
-fn rename_directory() {
- let tmpdir = PathBuf::from(env::var_os("RUST_TEST_TMPDIR").unwrap());
- let old_path = tmpdir.join("foo/bar/baz");
- fs::create_dir_all(&old_path).unwrap();
- let test_file = &old_path.join("temp.txt");
-
- File::create(test_file).unwrap();
-
- let new_path = tmpdir.join("quux/blat");
- fs::create_dir_all(&new_path).unwrap();
- fs::rename(&old_path, &new_path.join("newdir"));
- assert!(new_path.join("newdir").is_dir());
- assert!(new_path.join("newdir/temp.txt").exists());
-}
-
-pub fn main() { rename_directory() }
diff --git a/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.rs b/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.rs
index 65d9601e7..01e6434b0 100644
--- a/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.rs
+++ b/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.rs
@@ -17,26 +17,28 @@ use rustc_span::symbol::Ident;
use rustc_span::Span;
extern crate rustc_macros;
-use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic};
+use rustc_macros::{fluent_messages, Diagnostic, LintDiagnostic, Subdiagnostic};
extern crate rustc_middle;
use rustc_middle::ty::Ty;
extern crate rustc_errors;
-use rustc_errors::{Applicability, MultiSpan};
+use rustc_errors::{Applicability, DiagnosticMessage, MultiSpan, SubdiagnosticMessage};
extern crate rustc_session;
+fluent_messages! { "./example.ftl" }
+
#[derive(Diagnostic)]
-#[diag(compiletest_example, code = "E0123")]
+#[diag(no_crate_example, code = "E0123")]
struct Hello {}
#[derive(Diagnostic)]
-#[diag(compiletest_example, code = "E0123")]
+#[diag(no_crate_example, code = "E0123")]
struct HelloWarn {}
#[derive(Diagnostic)]
-#[diag(compiletest_example, code = "E0123")]
+#[diag(no_crate_example, code = "E0123")]
//~^ ERROR unsupported type attribute for diagnostic derive enum
enum DiagnosticOnEnum {
Foo,
@@ -46,13 +48,13 @@ enum DiagnosticOnEnum {
}
#[derive(Diagnostic)]
-#[diag(compiletest_example, code = "E0123")]
+#[diag(no_crate_example, code = "E0123")]
#[diag = "E0123"]
//~^ ERROR `#[diag = ...]` is not a valid attribute
struct WrongStructAttrStyle {}
#[derive(Diagnostic)]
-#[nonsense(compiletest_example, code = "E0123")]
+#[nonsense(no_crate_example, code = "E0123")]
//~^ ERROR `#[nonsense(...)]` is not a valid attribute
//~^^ ERROR diagnostic slug not specified
//~^^^ ERROR cannot find attribute `nonsense` in this scope
@@ -66,7 +68,7 @@ struct InvalidLitNestedAttr {}
#[derive(Diagnostic)]
#[diag(nonsense, code = "E0123")]
-//~^ ERROR cannot find value `nonsense` in module `rustc_errors::fluent`
+//~^ ERROR cannot find value `nonsense` in module `crate::fluent_generated`
struct InvalidNestedStructAttr {}
#[derive(Diagnostic)]
@@ -90,12 +92,12 @@ struct InvalidNestedStructAttr2 {}
struct InvalidNestedStructAttr3 {}
#[derive(Diagnostic)]
-#[diag(compiletest_example, code = "E0123", slug = "foo")]
+#[diag(no_crate_example, code = "E0123", slug = "foo")]
//~^ ERROR `#[diag(slug = ...)]` is not a valid attribute
struct InvalidNestedStructAttr4 {}
#[derive(Diagnostic)]
-#[diag(compiletest_example, code = "E0123")]
+#[diag(no_crate_example, code = "E0123")]
struct WrongPlaceField {
#[suggestion = "bar"]
//~^ ERROR `#[suggestion = ...]` is not a valid attribute
@@ -103,20 +105,20 @@ struct WrongPlaceField {
}
#[derive(Diagnostic)]
-#[diag(compiletest_example, code = "E0123")]
-#[diag(compiletest_example, code = "E0456")]
+#[diag(no_crate_example, code = "E0123")]
+#[diag(no_crate_example, code = "E0456")]
//~^ ERROR specified multiple times
//~^^ ERROR specified multiple times
struct DiagSpecifiedTwice {}
#[derive(Diagnostic)]
-#[diag(compiletest_example, code = "E0456", code = "E0457")]
+#[diag(no_crate_example, code = "E0456", code = "E0457")]
//~^ ERROR specified multiple times
struct CodeSpecifiedTwice {}
#[derive(Diagnostic)]
-#[diag(compiletest_example, compiletest_example, code = "E0456")]
-//~^ ERROR `#[diag(compiletest_example)]` is not a valid attribute
+#[diag(no_crate_example, no_crate::example, code = "E0456")]
+//~^ ERROR `#[diag(no_crate::example)]` is not a valid attribute
struct SlugSpecifiedTwice {}
#[derive(Diagnostic)]
@@ -128,11 +130,11 @@ struct KindNotProvided {} //~ ERROR diagnostic slug not specified
struct SlugNotProvided {}
#[derive(Diagnostic)]
-#[diag(compiletest_example)]
+#[diag(no_crate_example)]
struct CodeNotProvided {}
#[derive(Diagnostic)]
-#[diag(compiletest_example, code = "E0123")]
+#[diag(no_crate_example, code = "E0123")]
struct MessageWrongType {
#[primary_span]
//~^ ERROR `#[primary_span]` attribute can only be applied to fields of type `Span` or `MultiSpan`
@@ -140,7 +142,7 @@ struct MessageWrongType {
}
#[derive(Diagnostic)]
-#[diag(compiletest_example, code = "E0123")]
+#[diag(no_crate_example, code = "E0123")]
struct InvalidPathFieldAttr {
#[nonsense]
//~^ ERROR `#[nonsense]` is not a valid attribute
@@ -149,34 +151,34 @@ struct InvalidPathFieldAttr {
}
#[derive(Diagnostic)]
-#[diag(compiletest_example, code = "E0123")]
+#[diag(no_crate_example, code = "E0123")]
struct ErrorWithField {
name: String,
- #[label(label)]
+ #[label(no_crate_label)]
span: Span,
}
#[derive(Diagnostic)]
-#[diag(compiletest_example, code = "E0123")]
+#[diag(no_crate_example, code = "E0123")]
struct ErrorWithMessageAppliedToField {
- #[label(label)]
+ #[label(no_crate_label)]
//~^ ERROR the `#[label(...)]` attribute can only be applied to fields of type `Span` or `MultiSpan`
name: String,
}
#[derive(Diagnostic)]
-#[diag(compiletest_example, code = "E0123")]
+#[diag(no_crate_example, code = "E0123")]
struct ErrorWithNonexistentField {
- #[suggestion(suggestion, code = "{name}")]
+ #[suggestion(no_crate_suggestion, code = "{name}")]
//~^ ERROR `name` doesn't refer to a field on this type
suggestion: (Span, Applicability),
}
#[derive(Diagnostic)]
//~^ ERROR invalid format string: expected `'}'`
-#[diag(compiletest_example, code = "E0123")]
+#[diag(no_crate_example, code = "E0123")]
struct ErrorMissingClosingBrace {
- #[suggestion(suggestion, code = "{name")]
+ #[suggestion(no_crate_suggestion, code = "{name")]
suggestion: (Span, Applicability),
name: String,
val: usize,
@@ -184,50 +186,50 @@ struct ErrorMissingClosingBrace {
#[derive(Diagnostic)]
//~^ ERROR invalid format string: unmatched `}`
-#[diag(compiletest_example, code = "E0123")]
+#[diag(no_crate_example, code = "E0123")]
struct ErrorMissingOpeningBrace {
- #[suggestion(suggestion, code = "name}")]
+ #[suggestion(no_crate_suggestion, code = "name}")]
suggestion: (Span, Applicability),
name: String,
val: usize,
}
#[derive(Diagnostic)]
-#[diag(compiletest_example, code = "E0123")]
+#[diag(no_crate_example, code = "E0123")]
struct LabelOnSpan {
- #[label(label)]
+ #[label(no_crate_label)]
sp: Span,
}
#[derive(Diagnostic)]
-#[diag(compiletest_example, code = "E0123")]
+#[diag(no_crate_example, code = "E0123")]
struct LabelOnNonSpan {
- #[label(label)]
+ #[label(no_crate_label)]
//~^ ERROR the `#[label(...)]` attribute can only be applied to fields of type `Span` or `MultiSpan`
id: u32,
}
#[derive(Diagnostic)]
-#[diag(compiletest_example, code = "E0123")]
+#[diag(no_crate_example, code = "E0123")]
struct Suggest {
- #[suggestion(suggestion, code = "This is the suggested code")]
- #[suggestion(suggestion, code = "This is the suggested code", style = "normal")]
- #[suggestion(suggestion, code = "This is the suggested code", style = "short")]
- #[suggestion(suggestion, code = "This is the suggested code", style = "hidden")]
- #[suggestion(suggestion, code = "This is the suggested code", style = "verbose")]
+ #[suggestion(no_crate_suggestion, code = "This is the suggested code")]
+ #[suggestion(no_crate_suggestion, code = "This is the suggested code", style = "normal")]
+ #[suggestion(no_crate_suggestion, code = "This is the suggested code", style = "short")]
+ #[suggestion(no_crate_suggestion, code = "This is the suggested code", style = "hidden")]
+ #[suggestion(no_crate_suggestion, code = "This is the suggested code", style = "verbose")]
suggestion: (Span, Applicability),
}
#[derive(Diagnostic)]
-#[diag(compiletest_example, code = "E0123")]
+#[diag(no_crate_example, code = "E0123")]
struct SuggestWithoutCode {
- #[suggestion(suggestion)]
+ #[suggestion(no_crate_suggestion)]
//~^ ERROR suggestion without `code = "..."`
suggestion: (Span, Applicability),
}
#[derive(Diagnostic)]
-#[diag(compiletest_example, code = "E0123")]
+#[diag(no_crate_example, code = "E0123")]
struct SuggestWithBadKey {
#[suggestion(nonsense = "bar")]
//~^ ERROR `#[suggestion(nonsense = ...)]` is not a valid attribute
@@ -236,7 +238,7 @@ struct SuggestWithBadKey {
}
#[derive(Diagnostic)]
-#[diag(compiletest_example, code = "E0123")]
+#[diag(no_crate_example, code = "E0123")]
struct SuggestWithShorthandMsg {
#[suggestion(msg = "bar")]
//~^ ERROR `#[suggestion(msg = ...)]` is not a valid attribute
@@ -245,52 +247,52 @@ struct SuggestWithShorthandMsg {
}
#[derive(Diagnostic)]
-#[diag(compiletest_example, code = "E0123")]
+#[diag(no_crate_example, code = "E0123")]
struct SuggestWithoutMsg {
#[suggestion(code = "bar")]
suggestion: (Span, Applicability),
}
#[derive(Diagnostic)]
-#[diag(compiletest_example, code = "E0123")]
+#[diag(no_crate_example, code = "E0123")]
struct SuggestWithTypesSwapped {
- #[suggestion(suggestion, code = "This is suggested code")]
+ #[suggestion(no_crate_suggestion, code = "This is suggested code")]
suggestion: (Applicability, Span),
}
#[derive(Diagnostic)]
-#[diag(compiletest_example, code = "E0123")]
+#[diag(no_crate_example, code = "E0123")]
struct SuggestWithWrongTypeApplicabilityOnly {
- #[suggestion(suggestion, code = "This is suggested code")]
+ #[suggestion(no_crate_suggestion, code = "This is suggested code")]
//~^ ERROR wrong field type for suggestion
suggestion: Applicability,
}
#[derive(Diagnostic)]
-#[diag(compiletest_example, code = "E0123")]
+#[diag(no_crate_example, code = "E0123")]
struct SuggestWithSpanOnly {
- #[suggestion(suggestion, code = "This is suggested code")]
+ #[suggestion(no_crate_suggestion, code = "This is suggested code")]
suggestion: Span,
}
#[derive(Diagnostic)]
-#[diag(compiletest_example, code = "E0123")]
+#[diag(no_crate_example, code = "E0123")]
struct SuggestWithDuplicateSpanAndApplicability {
- #[suggestion(suggestion, code = "This is suggested code")]
+ #[suggestion(no_crate_suggestion, code = "This is suggested code")]
suggestion: (Span, Span, Applicability),
//~^ ERROR specified multiple times
}
#[derive(Diagnostic)]
-#[diag(compiletest_example, code = "E0123")]
+#[diag(no_crate_example, code = "E0123")]
struct SuggestWithDuplicateApplicabilityAndSpan {
- #[suggestion(suggestion, code = "This is suggested code")]
+ #[suggestion(no_crate_suggestion, code = "This is suggested code")]
suggestion: (Applicability, Applicability, Span),
//~^ ERROR specified multiple times
}
#[derive(Diagnostic)]
-#[diag(compiletest_example, code = "E0123")]
+#[diag(no_crate_example, code = "E0123")]
struct WrongKindOfAnnotation {
#[label = "bar"]
//~^ ERROR `#[label = ...]` is not a valid attribute
@@ -298,38 +300,38 @@ struct WrongKindOfAnnotation {
}
#[derive(Diagnostic)]
-#[diag(compiletest_example, code = "E0123")]
+#[diag(no_crate_example, code = "E0123")]
struct OptionsInErrors {
- #[label(label)]
+ #[label(no_crate_label)]
label: Option<Span>,
- #[suggestion(suggestion, code = "...")]
+ #[suggestion(no_crate_suggestion, code = "...")]
opt_sugg: Option<(Span, Applicability)>,
}
#[derive(Diagnostic)]
-#[diag(compiletest_example, code = "E0456")]
+#[diag(no_crate_example, code = "E0456")]
struct MoveOutOfBorrowError<'tcx> {
name: Ident,
ty: Ty<'tcx>,
#[primary_span]
- #[label(label)]
+ #[label(no_crate_label)]
span: Span,
- #[label(label)]
+ #[label(no_crate_label)]
other_span: Span,
- #[suggestion(suggestion, code = "{name}.clone()")]
+ #[suggestion(no_crate_suggestion, code = "{name}.clone()")]
opt_sugg: Option<(Span, Applicability)>,
}
#[derive(Diagnostic)]
-#[diag(compiletest_example, code = "E0123")]
+#[diag(no_crate_example, code = "E0123")]
struct ErrorWithLifetime<'a> {
- #[label(label)]
+ #[label(no_crate_label)]
span: Span,
name: &'a str,
}
#[derive(Diagnostic)]
-#[diag(compiletest_example, code = "E0123")]
+#[diag(no_crate_example, code = "E0123")]
struct ErrorWithDefaultLabelAttr<'a> {
#[label]
span: Span,
@@ -338,7 +340,7 @@ struct ErrorWithDefaultLabelAttr<'a> {
#[derive(Diagnostic)]
//~^ ERROR the trait bound `Hello: IntoDiagnosticArg` is not satisfied
-#[diag(compiletest_example, code = "E0123")]
+#[diag(no_crate_example, code = "E0123")]
struct ArgFieldWithoutSkip {
#[primary_span]
span: Span,
@@ -346,7 +348,7 @@ struct ArgFieldWithoutSkip {
}
#[derive(Diagnostic)]
-#[diag(compiletest_example, code = "E0123")]
+#[diag(no_crate_example, code = "E0123")]
struct ArgFieldWithSkip {
#[primary_span]
span: Span,
@@ -357,132 +359,132 @@ struct ArgFieldWithSkip {
}
#[derive(Diagnostic)]
-#[diag(compiletest_example, code = "E0123")]
+#[diag(no_crate_example, code = "E0123")]
struct ErrorWithSpannedNote {
#[note]
span: Span,
}
#[derive(Diagnostic)]
-#[diag(compiletest_example, code = "E0123")]
+#[diag(no_crate_example, code = "E0123")]
struct ErrorWithSpannedNoteCustom {
- #[note(note)]
+ #[note(no_crate_note)]
span: Span,
}
#[derive(Diagnostic)]
-#[diag(compiletest_example, code = "E0123")]
+#[diag(no_crate_example, code = "E0123")]
#[note]
struct ErrorWithNote {
val: String,
}
#[derive(Diagnostic)]
-#[diag(compiletest_example, code = "E0123")]
-#[note(note)]
+#[diag(no_crate_example, code = "E0123")]
+#[note(no_crate_note)]
struct ErrorWithNoteCustom {
val: String,
}
#[derive(Diagnostic)]
-#[diag(compiletest_example, code = "E0123")]
+#[diag(no_crate_example, code = "E0123")]
struct ErrorWithSpannedHelp {
#[help]
span: Span,
}
#[derive(Diagnostic)]
-#[diag(compiletest_example, code = "E0123")]
+#[diag(no_crate_example, code = "E0123")]
struct ErrorWithSpannedHelpCustom {
- #[help(help)]
+ #[help(no_crate_help)]
span: Span,
}
#[derive(Diagnostic)]
-#[diag(compiletest_example, code = "E0123")]
+#[diag(no_crate_example, code = "E0123")]
#[help]
struct ErrorWithHelp {
val: String,
}
#[derive(Diagnostic)]
-#[diag(compiletest_example, code = "E0123")]
-#[help(help)]
+#[diag(no_crate_example, code = "E0123")]
+#[help(no_crate_help)]
struct ErrorWithHelpCustom {
val: String,
}
#[derive(Diagnostic)]
#[help]
-#[diag(compiletest_example, code = "E0123")]
+#[diag(no_crate_example, code = "E0123")]
struct ErrorWithHelpWrongOrder {
val: String,
}
#[derive(Diagnostic)]
-#[help(help)]
-#[diag(compiletest_example, code = "E0123")]
+#[help(no_crate_help)]
+#[diag(no_crate_example, code = "E0123")]
struct ErrorWithHelpCustomWrongOrder {
val: String,
}
#[derive(Diagnostic)]
#[note]
-#[diag(compiletest_example, code = "E0123")]
+#[diag(no_crate_example, code = "E0123")]
struct ErrorWithNoteWrongOrder {
val: String,
}
#[derive(Diagnostic)]
-#[note(note)]
-#[diag(compiletest_example, code = "E0123")]
+#[note(no_crate_note)]
+#[diag(no_crate_example, code = "E0123")]
struct ErrorWithNoteCustomWrongOrder {
val: String,
}
#[derive(Diagnostic)]
-#[diag(compiletest_example, code = "E0123")]
+#[diag(no_crate_example, code = "E0123")]
struct ApplicabilityInBoth {
- #[suggestion(suggestion, code = "...", applicability = "maybe-incorrect")]
+ #[suggestion(no_crate_suggestion, code = "...", applicability = "maybe-incorrect")]
//~^ ERROR specified multiple times
suggestion: (Span, Applicability),
}
#[derive(Diagnostic)]
-#[diag(compiletest_example, code = "E0123")]
+#[diag(no_crate_example, code = "E0123")]
struct InvalidApplicability {
- #[suggestion(suggestion, code = "...", applicability = "batman")]
+ #[suggestion(no_crate_suggestion, code = "...", applicability = "batman")]
//~^ ERROR invalid applicability
suggestion: Span,
}
#[derive(Diagnostic)]
-#[diag(compiletest_example, code = "E0123")]
+#[diag(no_crate_example, code = "E0123")]
struct ValidApplicability {
- #[suggestion(suggestion, code = "...", applicability = "maybe-incorrect")]
+ #[suggestion(no_crate_suggestion, code = "...", applicability = "maybe-incorrect")]
suggestion: Span,
}
#[derive(Diagnostic)]
-#[diag(compiletest_example, code = "E0123")]
+#[diag(no_crate_example, code = "E0123")]
struct NoApplicability {
- #[suggestion(suggestion, code = "...")]
+ #[suggestion(no_crate_suggestion, code = "...")]
suggestion: Span,
}
#[derive(Subdiagnostic)]
-#[note(parse_add_paren)]
+#[note(no_crate_example)]
struct Note;
#[derive(Diagnostic)]
-#[diag(compiletest_example)]
+#[diag(no_crate_example)]
struct Subdiagnostic {
#[subdiagnostic]
note: Note,
}
#[derive(Diagnostic)]
-#[diag(compiletest_example, code = "E0123")]
+#[diag(no_crate_example, code = "E0123")]
struct VecField {
#[primary_span]
#[label]
@@ -490,57 +492,57 @@ struct VecField {
}
#[derive(Diagnostic)]
-#[diag(compiletest_example, code = "E0123")]
+#[diag(no_crate_example, code = "E0123")]
struct UnitField {
#[primary_span]
spans: Span,
#[help]
foo: (),
- #[help(help)]
+ #[help(no_crate_help)]
bar: (),
}
#[derive(Diagnostic)]
-#[diag(compiletest_example, code = "E0123")]
+#[diag(no_crate_example, code = "E0123")]
struct OptUnitField {
#[primary_span]
spans: Span,
#[help]
foo: Option<()>,
- #[help(help)]
+ #[help(no_crate_help)]
bar: Option<()>,
}
#[derive(Diagnostic)]
-#[diag(compiletest_example, code = "E0123")]
+#[diag(no_crate_example, code = "E0123")]
struct LabelWithTrailingPath {
- #[label(label, foo)]
+ #[label(no_crate_label, foo)]
//~^ ERROR `#[label(foo)]` is not a valid attribute
span: Span,
}
#[derive(Diagnostic)]
-#[diag(compiletest_example, code = "E0123")]
+#[diag(no_crate_example, code = "E0123")]
struct LabelWithTrailingNameValue {
- #[label(label, foo = "...")]
+ #[label(no_crate_label, foo = "...")]
//~^ ERROR `#[label(foo = ...)]` is not a valid attribute
span: Span,
}
#[derive(Diagnostic)]
-#[diag(compiletest_example, code = "E0123")]
+#[diag(no_crate_example, code = "E0123")]
struct LabelWithTrailingList {
- #[label(label, foo("..."))]
+ #[label(no_crate_label, foo("..."))]
//~^ ERROR `#[label(foo(...))]` is not a valid attribute
span: Span,
}
#[derive(LintDiagnostic)]
-#[diag(compiletest_example)]
+#[diag(no_crate_example)]
struct LintsGood {}
#[derive(LintDiagnostic)]
-#[diag(compiletest_example)]
+#[diag(no_crate_example)]
struct PrimarySpanOnLint {
#[primary_span]
//~^ ERROR `#[primary_span]` is not a valid attribute
@@ -548,42 +550,42 @@ struct PrimarySpanOnLint {
}
#[derive(Diagnostic)]
-#[diag(compiletest_example, code = "E0123")]
+#[diag(no_crate_example, code = "E0123")]
struct ErrorWithMultiSpan {
#[primary_span]
span: MultiSpan,
}
#[derive(Diagnostic)]
-#[diag(compiletest_example, code = "E0123")]
+#[diag(no_crate_example, code = "E0123")]
#[warning]
struct ErrorWithWarn {
val: String,
}
#[derive(Diagnostic)]
-#[error(compiletest_example, code = "E0123")]
+#[error(no_crate_example, code = "E0123")]
//~^ ERROR `#[error(...)]` is not a valid attribute
//~| ERROR diagnostic slug not specified
//~| ERROR cannot find attribute `error` in this scope
struct ErrorAttribute {}
#[derive(Diagnostic)]
-#[warn_(compiletest_example, code = "E0123")]
+#[warn_(no_crate_example, code = "E0123")]
//~^ ERROR `#[warn_(...)]` is not a valid attribute
//~| ERROR diagnostic slug not specified
//~| ERROR cannot find attribute `warn_` in this scope
struct WarnAttribute {}
#[derive(Diagnostic)]
-#[lint(compiletest_example, code = "E0123")]
+#[lint(no_crate_example, code = "E0123")]
//~^ ERROR `#[lint(...)]` is not a valid attribute
//~| ERROR diagnostic slug not specified
//~| ERROR cannot find attribute `lint` in this scope
struct LintAttributeOnSessionDiag {}
#[derive(LintDiagnostic)]
-#[lint(compiletest_example, code = "E0123")]
+#[lint(no_crate_example, code = "E0123")]
//~^ ERROR `#[lint(...)]` is not a valid attribute
//~| ERROR `#[lint(...)]` is not a valid attribute
//~| ERROR diagnostic slug not specified
@@ -591,55 +593,55 @@ struct LintAttributeOnSessionDiag {}
struct LintAttributeOnLintDiag {}
#[derive(Diagnostic)]
-#[diag(compiletest_example, code = "E0123")]
+#[diag(no_crate_example, code = "E0123")]
struct DuplicatedSuggestionCode {
- #[suggestion(suggestion, code = "...", code = ",,,")]
+ #[suggestion(no_crate_suggestion, code = "...", code = ",,,")]
//~^ ERROR specified multiple times
suggestion: Span,
}
#[derive(Diagnostic)]
-#[diag(compiletest_example, code = "E0123")]
+#[diag(no_crate_example, code = "E0123")]
struct InvalidTypeInSuggestionTuple {
- #[suggestion(suggestion, code = "...")]
+ #[suggestion(no_crate_suggestion, code = "...")]
suggestion: (Span, usize),
//~^ ERROR wrong types for suggestion
}
#[derive(Diagnostic)]
-#[diag(compiletest_example, code = "E0123")]
+#[diag(no_crate_example, code = "E0123")]
struct MissingApplicabilityInSuggestionTuple {
- #[suggestion(suggestion, code = "...")]
+ #[suggestion(no_crate_suggestion, code = "...")]
suggestion: (Span,),
//~^ ERROR wrong types for suggestion
}
#[derive(Diagnostic)]
-#[diag(compiletest_example, code = "E0123")]
+#[diag(no_crate_example, code = "E0123")]
struct MissingCodeInSuggestion {
- #[suggestion(suggestion)]
+ #[suggestion(no_crate_suggestion)]
//~^ ERROR suggestion without `code = "..."`
suggestion: Span,
}
#[derive(Diagnostic)]
-#[diag(compiletest_example, code = "E0123")]
-#[multipart_suggestion(suggestion)]
+#[diag(no_crate_example, code = "E0123")]
+#[multipart_suggestion(no_crate_suggestion)]
//~^ ERROR `#[multipart_suggestion(...)]` is not a valid attribute
//~| ERROR cannot find attribute `multipart_suggestion` in this scope
#[multipart_suggestion()]
//~^ ERROR `#[multipart_suggestion(...)]` is not a valid attribute
//~| ERROR cannot find attribute `multipart_suggestion` in this scope
struct MultipartSuggestion {
- #[multipart_suggestion(suggestion)]
+ #[multipart_suggestion(no_crate_suggestion)]
//~^ ERROR `#[multipart_suggestion(...)]` is not a valid attribute
//~| ERROR cannot find attribute `multipart_suggestion` in this scope
suggestion: Span,
}
#[derive(Diagnostic)]
-#[diag(compiletest_example, code = "E0123")]
-#[suggestion(suggestion, code = "...")]
+#[diag(no_crate_example, code = "E0123")]
+#[suggestion(no_crate_suggestion, code = "...")]
//~^ ERROR `#[suggestion(...)]` is not a valid attribute
struct SuggestionOnStruct {
#[primary_span]
@@ -647,7 +649,7 @@ struct SuggestionOnStruct {
}
#[derive(Diagnostic)]
-#[diag(compiletest_example, code = "E0123")]
+#[diag(no_crate_example, code = "E0123")]
#[label]
//~^ ERROR `#[label]` is not a valid attribute
struct LabelOnStruct {
@@ -657,30 +659,30 @@ struct LabelOnStruct {
#[derive(Diagnostic)]
enum ExampleEnum {
- #[diag(compiletest_example)]
+ #[diag(no_crate_example)]
Foo {
#[primary_span]
sp: Span,
#[note]
note_sp: Span,
},
- #[diag(compiletest_example)]
+ #[diag(no_crate_example)]
Bar {
#[primary_span]
sp: Span,
},
- #[diag(compiletest_example)]
+ #[diag(no_crate_example)]
Baz,
}
#[derive(Diagnostic)]
-#[diag(compiletest_example, code = "E0123")]
+#[diag(no_crate_example, code = "E0123")]
struct RawIdentDiagnosticArg {
pub r#type: String,
}
#[derive(Diagnostic)]
-#[diag(compiletest_example)]
+#[diag(no_crate_example)]
struct SubdiagnosticBad {
#[subdiagnostic(bad)]
//~^ ERROR `#[subdiagnostic(...)]` is not a valid attribute
@@ -688,7 +690,7 @@ struct SubdiagnosticBad {
}
#[derive(Diagnostic)]
-#[diag(compiletest_example)]
+#[diag(no_crate_example)]
struct SubdiagnosticBadStr {
#[subdiagnostic = "bad"]
//~^ ERROR `#[subdiagnostic = ...]` is not a valid attribute
@@ -696,7 +698,7 @@ struct SubdiagnosticBadStr {
}
#[derive(Diagnostic)]
-#[diag(compiletest_example)]
+#[diag(no_crate_example)]
struct SubdiagnosticBadTwice {
#[subdiagnostic(bad, bad)]
//~^ ERROR `#[subdiagnostic(...)]` is not a valid attribute
@@ -704,7 +706,7 @@ struct SubdiagnosticBadTwice {
}
#[derive(Diagnostic)]
-#[diag(compiletest_example)]
+#[diag(no_crate_example)]
struct SubdiagnosticBadLitStr {
#[subdiagnostic("bad")]
//~^ ERROR `#[subdiagnostic(...)]` is not a valid attribute
@@ -712,7 +714,7 @@ struct SubdiagnosticBadLitStr {
}
#[derive(LintDiagnostic)]
-#[diag(compiletest_example)]
+#[diag(no_crate_example)]
struct SubdiagnosticEagerLint {
#[subdiagnostic(eager)]
//~^ ERROR `#[subdiagnostic(...)]` is not a valid attribute
@@ -720,7 +722,7 @@ struct SubdiagnosticEagerLint {
}
#[derive(Diagnostic)]
-#[diag(compiletest_example)]
+#[diag(no_crate_example)]
struct SubdiagnosticEagerCorrect {
#[subdiagnostic(eager)]
note: Note,
@@ -731,7 +733,7 @@ struct SubdiagnosticEagerCorrect {
// after the `span_suggestion` call - which breaks eager translation.
#[derive(Subdiagnostic)]
-#[suggestion(use_instead, applicability = "machine-applicable", code = "{correct}")]
+#[suggestion(no_crate_example, applicability = "machine-applicable", code = "{correct}")]
pub(crate) struct SubdiagnosticWithSuggestion {
#[primary_span]
span: Span,
@@ -740,7 +742,7 @@ pub(crate) struct SubdiagnosticWithSuggestion {
}
#[derive(Diagnostic)]
-#[diag(compiletest_example)]
+#[diag(no_crate_example)]
struct SubdiagnosticEagerSuggestion {
#[subdiagnostic(eager)]
sub: SubdiagnosticWithSuggestion,
@@ -748,7 +750,7 @@ struct SubdiagnosticEagerSuggestion {
/// with a doc comment on the type..
#[derive(Diagnostic)]
-#[diag(compiletest_example, code = "E0123")]
+#[diag(no_crate_example, code = "E0123")]
struct WithDocComment {
/// ..and the field
#[primary_span]
@@ -756,21 +758,21 @@ struct WithDocComment {
}
#[derive(Diagnostic)]
-#[diag(compiletest_example)]
+#[diag(no_crate_example)]
struct SuggestionsGood {
#[suggestion(code("foo", "bar"))]
sub: Span,
}
#[derive(Diagnostic)]
-#[diag(compiletest_example)]
+#[diag(no_crate_example)]
struct SuggestionsSingleItem {
#[suggestion(code("foo"))]
sub: Span,
}
#[derive(Diagnostic)]
-#[diag(compiletest_example)]
+#[diag(no_crate_example)]
struct SuggestionsNoItem {
#[suggestion(code())]
//~^ ERROR expected at least one string literal for `code(...)`
@@ -778,7 +780,7 @@ struct SuggestionsNoItem {
}
#[derive(Diagnostic)]
-#[diag(compiletest_example)]
+#[diag(no_crate_example)]
struct SuggestionsInvalidItem {
#[suggestion(code(foo))]
//~^ ERROR `code(...)` must contain only string literals
@@ -786,7 +788,7 @@ struct SuggestionsInvalidItem {
}
#[derive(Diagnostic)]
-#[diag(compiletest_example)]
+#[diag(no_crate_example)]
struct SuggestionsInvalidLiteral {
#[suggestion(code = 3)]
//~^ ERROR `code = "..."`/`code(...)` must contain only string literals
@@ -794,8 +796,16 @@ struct SuggestionsInvalidLiteral {
}
#[derive(Diagnostic)]
-#[diag(compiletest_example)]
+#[diag(no_crate_example)]
struct SuggestionStyleGood {
#[suggestion(code = "", style = "hidden")]
sub: Span,
}
+
+#[derive(Diagnostic)]
+#[diag(no_crate_example)]
+struct SuggestionOnVec {
+ #[suggestion(no_crate_suggestion, code = "")]
+ //~^ ERROR `#[suggestion(...)]` is not a valid attribute
+ sub: Vec<Span>,
+}
diff --git a/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr b/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr
index 13e806a43..fc0cd8419 100644
--- a/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr
+++ b/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr
@@ -1,11 +1,11 @@
error: unsupported type attribute for diagnostic derive enum
- --> $DIR/diagnostic-derive.rs:39:1
+ --> $DIR/diagnostic-derive.rs:41:1
|
-LL | #[diag(compiletest_example, code = "E0123")]
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | #[diag(no_crate_example, code = "E0123")]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: diagnostic slug not specified
- --> $DIR/diagnostic-derive.rs:42:5
+ --> $DIR/diagnostic-derive.rs:44:5
|
LL | Foo,
| ^^^
@@ -13,7 +13,7 @@ LL | Foo,
= help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis_example_error)]`
error: diagnostic slug not specified
- --> $DIR/diagnostic-derive.rs:44:5
+ --> $DIR/diagnostic-derive.rs:46:5
|
LL | Bar,
| ^^^
@@ -21,21 +21,21 @@ LL | Bar,
= help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis_example_error)]`
error: `#[diag = ...]` is not a valid attribute
- --> $DIR/diagnostic-derive.rs:50:1
+ --> $DIR/diagnostic-derive.rs:52:1
|
LL | #[diag = "E0123"]
| ^^^^^^^^^^^^^^^^^
error: `#[nonsense(...)]` is not a valid attribute
- --> $DIR/diagnostic-derive.rs:55:1
+ --> $DIR/diagnostic-derive.rs:57:1
|
-LL | #[nonsense(compiletest_example, code = "E0123")]
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | #[nonsense(no_crate_example, code = "E0123")]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: diagnostic slug not specified
- --> $DIR/diagnostic-derive.rs:55:1
+ --> $DIR/diagnostic-derive.rs:57:1
|
-LL | / #[nonsense(compiletest_example, code = "E0123")]
+LL | / #[nonsense(no_crate_example, code = "E0123")]
LL | |
LL | |
LL | |
@@ -45,7 +45,7 @@ LL | | struct InvalidStructAttr {}
= help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis_example_error)]`
error: `#[diag("...")]` is not a valid attribute
- --> $DIR/diagnostic-derive.rs:62:8
+ --> $DIR/diagnostic-derive.rs:64:8
|
LL | #[diag("E0123")]
| ^^^^^^^
@@ -53,7 +53,7 @@ LL | #[diag("E0123")]
= help: a diagnostic slug is required as the first argument
error: diagnostic slug not specified
- --> $DIR/diagnostic-derive.rs:62:1
+ --> $DIR/diagnostic-derive.rs:64:1
|
LL | / #[diag("E0123")]
LL | |
@@ -64,7 +64,7 @@ LL | | struct InvalidLitNestedAttr {}
= help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis_example_error)]`
error: `#[diag(nonsense(...))]` is not a valid attribute
- --> $DIR/diagnostic-derive.rs:73:8
+ --> $DIR/diagnostic-derive.rs:75:8
|
LL | #[diag(nonsense("foo"), code = "E0123", slug = "foo")]
| ^^^^^^^^^^^^^^^
@@ -72,7 +72,7 @@ LL | #[diag(nonsense("foo"), code = "E0123", slug = "foo")]
= help: a diagnostic slug is required as the first argument
error: diagnostic slug not specified
- --> $DIR/diagnostic-derive.rs:73:1
+ --> $DIR/diagnostic-derive.rs:75:1
|
LL | / #[diag(nonsense("foo"), code = "E0123", slug = "foo")]
LL | |
@@ -83,7 +83,7 @@ LL | | struct InvalidNestedStructAttr1 {}
= help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis_example_error)]`
error: `#[diag(nonsense = ...)]` is not a valid attribute
- --> $DIR/diagnostic-derive.rs:79:8
+ --> $DIR/diagnostic-derive.rs:81:8
|
LL | #[diag(nonsense = "...", code = "E0123", slug = "foo")]
| ^^^^^^^^^^^^^^^^
@@ -91,7 +91,7 @@ LL | #[diag(nonsense = "...", code = "E0123", slug = "foo")]
= help: only `code` is a valid nested attributes following the slug
error: `#[diag(slug = ...)]` is not a valid attribute
- --> $DIR/diagnostic-derive.rs:79:42
+ --> $DIR/diagnostic-derive.rs:81:42
|
LL | #[diag(nonsense = "...", code = "E0123", slug = "foo")]
| ^^^^^^^^^^^^
@@ -99,7 +99,7 @@ LL | #[diag(nonsense = "...", code = "E0123", slug = "foo")]
= help: only `code` is a valid nested attributes following the slug
error: diagnostic slug not specified
- --> $DIR/diagnostic-derive.rs:79:1
+ --> $DIR/diagnostic-derive.rs:81:1
|
LL | / #[diag(nonsense = "...", code = "E0123", slug = "foo")]
LL | |
@@ -111,13 +111,13 @@ LL | | struct InvalidNestedStructAttr2 {}
= help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis_example_error)]`
error: `#[diag(nonsense = ...)]` is not a valid attribute
- --> $DIR/diagnostic-derive.rs:86:8
+ --> $DIR/diagnostic-derive.rs:88:8
|
LL | #[diag(nonsense = 4, code = "E0123", slug = "foo")]
| ^^^^^^^^^^^^
error: `#[diag(slug = ...)]` is not a valid attribute
- --> $DIR/diagnostic-derive.rs:86:38
+ --> $DIR/diagnostic-derive.rs:88:38
|
LL | #[diag(nonsense = 4, code = "E0123", slug = "foo")]
| ^^^^^^^^^^^^
@@ -125,7 +125,7 @@ LL | #[diag(nonsense = 4, code = "E0123", slug = "foo")]
= help: only `code` is a valid nested attributes following the slug
error: diagnostic slug not specified
- --> $DIR/diagnostic-derive.rs:86:1
+ --> $DIR/diagnostic-derive.rs:88:1
|
LL | / #[diag(nonsense = 4, code = "E0123", slug = "foo")]
LL | |
@@ -137,65 +137,65 @@ LL | | struct InvalidNestedStructAttr3 {}
= help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis_example_error)]`
error: `#[diag(slug = ...)]` is not a valid attribute
- --> $DIR/diagnostic-derive.rs:93:45
+ --> $DIR/diagnostic-derive.rs:95:42
|
-LL | #[diag(compiletest_example, code = "E0123", slug = "foo")]
- | ^^^^^^^^^^^^
+LL | #[diag(no_crate_example, code = "E0123", slug = "foo")]
+ | ^^^^^^^^^^^^
|
= help: only `code` is a valid nested attributes following the slug
error: `#[suggestion = ...]` is not a valid attribute
- --> $DIR/diagnostic-derive.rs:100:5
+ --> $DIR/diagnostic-derive.rs:102:5
|
LL | #[suggestion = "bar"]
| ^^^^^^^^^^^^^^^^^^^^^
error: specified multiple times
- --> $DIR/diagnostic-derive.rs:107:8
+ --> $DIR/diagnostic-derive.rs:109:8
|
-LL | #[diag(compiletest_example, code = "E0456")]
- | ^^^^^^^^^^^^^^^^^^^
+LL | #[diag(no_crate_example, code = "E0456")]
+ | ^^^^^^^^^^^^^^^^
|
note: previously specified here
- --> $DIR/diagnostic-derive.rs:106:8
+ --> $DIR/diagnostic-derive.rs:108:8
|
-LL | #[diag(compiletest_example, code = "E0123")]
- | ^^^^^^^^^^^^^^^^^^^
+LL | #[diag(no_crate_example, code = "E0123")]
+ | ^^^^^^^^^^^^^^^^
error: specified multiple times
- --> $DIR/diagnostic-derive.rs:107:36
+ --> $DIR/diagnostic-derive.rs:109:33
|
-LL | #[diag(compiletest_example, code = "E0456")]
- | ^^^^^^^
+LL | #[diag(no_crate_example, code = "E0456")]
+ | ^^^^^^^
|
note: previously specified here
- --> $DIR/diagnostic-derive.rs:106:36
+ --> $DIR/diagnostic-derive.rs:108:33
|
-LL | #[diag(compiletest_example, code = "E0123")]
- | ^^^^^^^
+LL | #[diag(no_crate_example, code = "E0123")]
+ | ^^^^^^^
error: specified multiple times
- --> $DIR/diagnostic-derive.rs:113:52
+ --> $DIR/diagnostic-derive.rs:115:49
|
-LL | #[diag(compiletest_example, code = "E0456", code = "E0457")]
- | ^^^^^^^
+LL | #[diag(no_crate_example, code = "E0456", code = "E0457")]
+ | ^^^^^^^
|
note: previously specified here
- --> $DIR/diagnostic-derive.rs:113:36
+ --> $DIR/diagnostic-derive.rs:115:33
|
-LL | #[diag(compiletest_example, code = "E0456", code = "E0457")]
- | ^^^^^^^
+LL | #[diag(no_crate_example, code = "E0456", code = "E0457")]
+ | ^^^^^^^
-error: `#[diag(compiletest_example)]` is not a valid attribute
- --> $DIR/diagnostic-derive.rs:118:29
+error: `#[diag(no_crate::example)]` is not a valid attribute
+ --> $DIR/diagnostic-derive.rs:120:26
|
-LL | #[diag(compiletest_example, compiletest_example, code = "E0456")]
- | ^^^^^^^^^^^^^^^^^^^
+LL | #[diag(no_crate_example, no_crate::example, code = "E0456")]
+ | ^^^^^^^^^^^^^^^^^
|
= help: diagnostic slug must be the first argument
error: diagnostic slug not specified
- --> $DIR/diagnostic-derive.rs:123:1
+ --> $DIR/diagnostic-derive.rs:125:1
|
LL | struct KindNotProvided {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -203,7 +203,7 @@ LL | struct KindNotProvided {}
= help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis_example_error)]`
error: diagnostic slug not specified
- --> $DIR/diagnostic-derive.rs:126:1
+ --> $DIR/diagnostic-derive.rs:128:1
|
LL | / #[diag(code = "E0456")]
LL | |
@@ -213,31 +213,31 @@ LL | | struct SlugNotProvided {}
= help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis_example_error)]`
error: the `#[primary_span]` attribute can only be applied to fields of type `Span` or `MultiSpan`
- --> $DIR/diagnostic-derive.rs:137:5
+ --> $DIR/diagnostic-derive.rs:139:5
|
LL | #[primary_span]
| ^^^^^^^^^^^^^^^
error: `#[nonsense]` is not a valid attribute
- --> $DIR/diagnostic-derive.rs:145:5
+ --> $DIR/diagnostic-derive.rs:147:5
|
LL | #[nonsense]
| ^^^^^^^^^^^
error: the `#[label(...)]` attribute can only be applied to fields of type `Span` or `MultiSpan`
- --> $DIR/diagnostic-derive.rs:162:5
+ --> $DIR/diagnostic-derive.rs:164:5
|
-LL | #[label(label)]
- | ^^^^^^^^^^^^^^^
+LL | #[label(no_crate_label)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^
error: `name` doesn't refer to a field on this type
- --> $DIR/diagnostic-derive.rs:170:37
+ --> $DIR/diagnostic-derive.rs:172:46
|
-LL | #[suggestion(suggestion, code = "{name}")]
- | ^^^^^^^^
+LL | #[suggestion(no_crate_suggestion, code = "{name}")]
+ | ^^^^^^^^
error: invalid format string: expected `'}'` but string was terminated
- --> $DIR/diagnostic-derive.rs:175:10
+ --> $DIR/diagnostic-derive.rs:177:10
|
LL | #[derive(Diagnostic)]
| ^^^^^^^^^^ expected `'}'` in format string
@@ -246,7 +246,7 @@ LL | #[derive(Diagnostic)]
= note: this error originates in the derive macro `Diagnostic` (in Nightly builds, run with -Z macro-backtrace for more info)
error: invalid format string: unmatched `}` found
- --> $DIR/diagnostic-derive.rs:185:10
+ --> $DIR/diagnostic-derive.rs:187:10
|
LL | #[derive(Diagnostic)]
| ^^^^^^^^^^ unmatched `}` in format string
@@ -255,19 +255,19 @@ LL | #[derive(Diagnostic)]
= note: this error originates in the derive macro `Diagnostic` (in Nightly builds, run with -Z macro-backtrace for more info)
error: the `#[label(...)]` attribute can only be applied to fields of type `Span` or `MultiSpan`
- --> $DIR/diagnostic-derive.rs:205:5
+ --> $DIR/diagnostic-derive.rs:207:5
|
-LL | #[label(label)]
- | ^^^^^^^^^^^^^^^
+LL | #[label(no_crate_label)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^
error: suggestion without `code = "..."`
- --> $DIR/diagnostic-derive.rs:224:5
+ --> $DIR/diagnostic-derive.rs:226:5
|
-LL | #[suggestion(suggestion)]
- | ^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | #[suggestion(no_crate_suggestion)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: `#[suggestion(nonsense = ...)]` is not a valid attribute
- --> $DIR/diagnostic-derive.rs:232:18
+ --> $DIR/diagnostic-derive.rs:234:18
|
LL | #[suggestion(nonsense = "bar")]
| ^^^^^^^^^^^^^^^^
@@ -275,13 +275,13 @@ LL | #[suggestion(nonsense = "bar")]
= help: only `style`, `code` and `applicability` are valid nested attributes
error: suggestion without `code = "..."`
- --> $DIR/diagnostic-derive.rs:232:5
+ --> $DIR/diagnostic-derive.rs:234:5
|
LL | #[suggestion(nonsense = "bar")]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: `#[suggestion(msg = ...)]` is not a valid attribute
- --> $DIR/diagnostic-derive.rs:241:18
+ --> $DIR/diagnostic-derive.rs:243:18
|
LL | #[suggestion(msg = "bar")]
| ^^^^^^^^^^^
@@ -289,15 +289,15 @@ LL | #[suggestion(msg = "bar")]
= help: only `style`, `code` and `applicability` are valid nested attributes
error: suggestion without `code = "..."`
- --> $DIR/diagnostic-derive.rs:241:5
+ --> $DIR/diagnostic-derive.rs:243:5
|
LL | #[suggestion(msg = "bar")]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
error: wrong field type for suggestion
- --> $DIR/diagnostic-derive.rs:264:5
+ --> $DIR/diagnostic-derive.rs:266:5
|
-LL | / #[suggestion(suggestion, code = "This is suggested code")]
+LL | / #[suggestion(no_crate_suggestion, code = "This is suggested code")]
LL | |
LL | | suggestion: Applicability,
| |_____________________________^
@@ -305,75 +305,75 @@ LL | | suggestion: Applicability,
= help: `#[suggestion(...)]` should be applied to fields of type `Span` or `(Span, Applicability)`
error: specified multiple times
- --> $DIR/diagnostic-derive.rs:280:24
+ --> $DIR/diagnostic-derive.rs:282:24
|
LL | suggestion: (Span, Span, Applicability),
| ^^^^
|
note: previously specified here
- --> $DIR/diagnostic-derive.rs:280:18
+ --> $DIR/diagnostic-derive.rs:282:18
|
LL | suggestion: (Span, Span, Applicability),
| ^^^^
error: specified multiple times
- --> $DIR/diagnostic-derive.rs:288:33
+ --> $DIR/diagnostic-derive.rs:290:33
|
LL | suggestion: (Applicability, Applicability, Span),
| ^^^^^^^^^^^^^
|
note: previously specified here
- --> $DIR/diagnostic-derive.rs:288:18
+ --> $DIR/diagnostic-derive.rs:290:18
|
LL | suggestion: (Applicability, Applicability, Span),
| ^^^^^^^^^^^^^
error: `#[label = ...]` is not a valid attribute
- --> $DIR/diagnostic-derive.rs:295:5
+ --> $DIR/diagnostic-derive.rs:297:5
|
LL | #[label = "bar"]
| ^^^^^^^^^^^^^^^^
error: specified multiple times
- --> $DIR/diagnostic-derive.rs:446:44
+ --> $DIR/diagnostic-derive.rs:448:53
|
-LL | #[suggestion(suggestion, code = "...", applicability = "maybe-incorrect")]
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | #[suggestion(no_crate_suggestion, code = "...", applicability = "maybe-incorrect")]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
note: previously specified here
- --> $DIR/diagnostic-derive.rs:448:24
+ --> $DIR/diagnostic-derive.rs:450:24
|
LL | suggestion: (Span, Applicability),
| ^^^^^^^^^^^^^
error: invalid applicability
- --> $DIR/diagnostic-derive.rs:454:44
+ --> $DIR/diagnostic-derive.rs:456:53
|
-LL | #[suggestion(suggestion, code = "...", applicability = "batman")]
- | ^^^^^^^^^^^^^^^^^^^^^^^^
+LL | #[suggestion(no_crate_suggestion, code = "...", applicability = "batman")]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^
error: `#[label(foo)]` is not a valid attribute
- --> $DIR/diagnostic-derive.rs:517:20
+ --> $DIR/diagnostic-derive.rs:519:29
|
-LL | #[label(label, foo)]
- | ^^^
+LL | #[label(no_crate_label, foo)]
+ | ^^^
|
= help: a diagnostic slug must be the first argument to the attribute
error: `#[label(foo = ...)]` is not a valid attribute
- --> $DIR/diagnostic-derive.rs:525:20
+ --> $DIR/diagnostic-derive.rs:527:29
|
-LL | #[label(label, foo = "...")]
- | ^^^^^^^^^^^
+LL | #[label(no_crate_label, foo = "...")]
+ | ^^^^^^^^^^^
error: `#[label(foo(...))]` is not a valid attribute
- --> $DIR/diagnostic-derive.rs:533:20
+ --> $DIR/diagnostic-derive.rs:535:29
|
-LL | #[label(label, foo("..."))]
- | ^^^^^^^^^^
+LL | #[label(no_crate_label, foo("..."))]
+ | ^^^^^^^^^^
error: `#[primary_span]` is not a valid attribute
- --> $DIR/diagnostic-derive.rs:545:5
+ --> $DIR/diagnostic-derive.rs:547:5
|
LL | #[primary_span]
| ^^^^^^^^^^^^^^^
@@ -381,15 +381,15 @@ LL | #[primary_span]
= help: the `primary_span` field attribute is not valid for lint diagnostics
error: `#[error(...)]` is not a valid attribute
- --> $DIR/diagnostic-derive.rs:565:1
+ --> $DIR/diagnostic-derive.rs:567:1
|
-LL | #[error(compiletest_example, code = "E0123")]
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | #[error(no_crate_example, code = "E0123")]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: diagnostic slug not specified
- --> $DIR/diagnostic-derive.rs:565:1
+ --> $DIR/diagnostic-derive.rs:567:1
|
-LL | / #[error(compiletest_example, code = "E0123")]
+LL | / #[error(no_crate_example, code = "E0123")]
LL | |
LL | |
LL | |
@@ -399,15 +399,15 @@ LL | | struct ErrorAttribute {}
= help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis_example_error)]`
error: `#[warn_(...)]` is not a valid attribute
- --> $DIR/diagnostic-derive.rs:572:1
+ --> $DIR/diagnostic-derive.rs:574:1
|
-LL | #[warn_(compiletest_example, code = "E0123")]
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | #[warn_(no_crate_example, code = "E0123")]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: diagnostic slug not specified
- --> $DIR/diagnostic-derive.rs:572:1
+ --> $DIR/diagnostic-derive.rs:574:1
|
-LL | / #[warn_(compiletest_example, code = "E0123")]
+LL | / #[warn_(no_crate_example, code = "E0123")]
LL | |
LL | |
LL | |
@@ -417,15 +417,15 @@ LL | | struct WarnAttribute {}
= help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis_example_error)]`
error: `#[lint(...)]` is not a valid attribute
- --> $DIR/diagnostic-derive.rs:579:1
+ --> $DIR/diagnostic-derive.rs:581:1
|
-LL | #[lint(compiletest_example, code = "E0123")]
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | #[lint(no_crate_example, code = "E0123")]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: diagnostic slug not specified
- --> $DIR/diagnostic-derive.rs:579:1
+ --> $DIR/diagnostic-derive.rs:581:1
|
-LL | / #[lint(compiletest_example, code = "E0123")]
+LL | / #[lint(no_crate_example, code = "E0123")]
LL | |
LL | |
LL | |
@@ -435,21 +435,21 @@ LL | | struct LintAttributeOnSessionDiag {}
= help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis_example_error)]`
error: `#[lint(...)]` is not a valid attribute
- --> $DIR/diagnostic-derive.rs:586:1
+ --> $DIR/diagnostic-derive.rs:588:1
|
-LL | #[lint(compiletest_example, code = "E0123")]
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | #[lint(no_crate_example, code = "E0123")]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: `#[lint(...)]` is not a valid attribute
- --> $DIR/diagnostic-derive.rs:586:1
+ --> $DIR/diagnostic-derive.rs:588:1
|
-LL | #[lint(compiletest_example, code = "E0123")]
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | #[lint(no_crate_example, code = "E0123")]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: diagnostic slug not specified
- --> $DIR/diagnostic-derive.rs:586:1
+ --> $DIR/diagnostic-derive.rs:588:1
|
-LL | / #[lint(compiletest_example, code = "E0123")]
+LL | / #[lint(no_crate_example, code = "E0123")]
LL | |
LL | |
LL | |
@@ -460,19 +460,19 @@ LL | | struct LintAttributeOnLintDiag {}
= help: specify the slug as the first argument to the attribute, such as `#[diag(compiletest_example)]`
error: specified multiple times
- --> $DIR/diagnostic-derive.rs:596:44
+ --> $DIR/diagnostic-derive.rs:598:53
|
-LL | #[suggestion(suggestion, code = "...", code = ",,,")]
- | ^^^^^^^^^^^^
+LL | #[suggestion(no_crate_suggestion, code = "...", code = ",,,")]
+ | ^^^^^^^^^^^^
|
note: previously specified here
- --> $DIR/diagnostic-derive.rs:596:30
+ --> $DIR/diagnostic-derive.rs:598:39
|
-LL | #[suggestion(suggestion, code = "...", code = ",,,")]
- | ^^^^^^^^^^^^
+LL | #[suggestion(no_crate_suggestion, code = "...", code = ",,,")]
+ | ^^^^^^^^^^^^
error: wrong types for suggestion
- --> $DIR/diagnostic-derive.rs:605:24
+ --> $DIR/diagnostic-derive.rs:607:24
|
LL | suggestion: (Span, usize),
| ^^^^^
@@ -480,7 +480,7 @@ LL | suggestion: (Span, usize),
= help: `#[suggestion(...)]` on a tuple field must be applied to fields of type `(Span, Applicability)`
error: wrong types for suggestion
- --> $DIR/diagnostic-derive.rs:613:17
+ --> $DIR/diagnostic-derive.rs:615:17
|
LL | suggestion: (Span,),
| ^^^^^^^
@@ -488,21 +488,21 @@ LL | suggestion: (Span,),
= help: `#[suggestion(...)]` on a tuple field must be applied to fields of type `(Span, Applicability)`
error: suggestion without `code = "..."`
- --> $DIR/diagnostic-derive.rs:620:5
+ --> $DIR/diagnostic-derive.rs:622:5
|
-LL | #[suggestion(suggestion)]
- | ^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | #[suggestion(no_crate_suggestion)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: `#[multipart_suggestion(...)]` is not a valid attribute
- --> $DIR/diagnostic-derive.rs:627:1
+ --> $DIR/diagnostic-derive.rs:629:1
|
-LL | #[multipart_suggestion(suggestion)]
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | #[multipart_suggestion(no_crate_suggestion)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= help: consider creating a `Subdiagnostic` instead
error: `#[multipart_suggestion(...)]` is not a valid attribute
- --> $DIR/diagnostic-derive.rs:630:1
+ --> $DIR/diagnostic-derive.rs:632:1
|
LL | #[multipart_suggestion()]
| ^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -510,23 +510,23 @@ LL | #[multipart_suggestion()]
= help: consider creating a `Subdiagnostic` instead
error: `#[multipart_suggestion(...)]` is not a valid attribute
- --> $DIR/diagnostic-derive.rs:634:5
+ --> $DIR/diagnostic-derive.rs:636:5
|
-LL | #[multipart_suggestion(suggestion)]
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | #[multipart_suggestion(no_crate_suggestion)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= help: consider creating a `Subdiagnostic` instead
error: `#[suggestion(...)]` is not a valid attribute
- --> $DIR/diagnostic-derive.rs:642:1
+ --> $DIR/diagnostic-derive.rs:644:1
|
-LL | #[suggestion(suggestion, code = "...")]
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | #[suggestion(no_crate_suggestion, code = "...")]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= help: `#[label]` and `#[suggestion]` can only be applied to fields
error: `#[label]` is not a valid attribute
- --> $DIR/diagnostic-derive.rs:651:1
+ --> $DIR/diagnostic-derive.rs:653:1
|
LL | #[label]
| ^^^^^^^^
@@ -534,7 +534,7 @@ LL | #[label]
= help: `#[label]` and `#[suggestion]` can only be applied to fields
error: `#[subdiagnostic(...)]` is not a valid attribute
- --> $DIR/diagnostic-derive.rs:685:5
+ --> $DIR/diagnostic-derive.rs:687:5
|
LL | #[subdiagnostic(bad)]
| ^^^^^^^^^^^^^^^^^^^^^
@@ -542,13 +542,13 @@ LL | #[subdiagnostic(bad)]
= help: `eager` is the only supported nested attribute for `subdiagnostic`
error: `#[subdiagnostic = ...]` is not a valid attribute
- --> $DIR/diagnostic-derive.rs:693:5
+ --> $DIR/diagnostic-derive.rs:695:5
|
LL | #[subdiagnostic = "bad"]
| ^^^^^^^^^^^^^^^^^^^^^^^^
error: `#[subdiagnostic(...)]` is not a valid attribute
- --> $DIR/diagnostic-derive.rs:701:5
+ --> $DIR/diagnostic-derive.rs:703:5
|
LL | #[subdiagnostic(bad, bad)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -556,7 +556,7 @@ LL | #[subdiagnostic(bad, bad)]
= help: `eager` is the only supported nested attribute for `subdiagnostic`
error: `#[subdiagnostic(...)]` is not a valid attribute
- --> $DIR/diagnostic-derive.rs:709:5
+ --> $DIR/diagnostic-derive.rs:711:5
|
LL | #[subdiagnostic("bad")]
| ^^^^^^^^^^^^^^^^^^^^^^^
@@ -564,7 +564,7 @@ LL | #[subdiagnostic("bad")]
= help: `eager` is the only supported nested attribute for `subdiagnostic`
error: `#[subdiagnostic(...)]` is not a valid attribute
- --> $DIR/diagnostic-derive.rs:717:5
+ --> $DIR/diagnostic-derive.rs:719:5
|
LL | #[subdiagnostic(eager)]
| ^^^^^^^^^^^^^^^^^^^^^^^
@@ -572,85 +572,95 @@ LL | #[subdiagnostic(eager)]
= help: eager subdiagnostics are not supported on lints
error: expected at least one string literal for `code(...)`
- --> $DIR/diagnostic-derive.rs:775:18
+ --> $DIR/diagnostic-derive.rs:777:18
|
LL | #[suggestion(code())]
| ^^^^^^
error: `code(...)` must contain only string literals
- --> $DIR/diagnostic-derive.rs:783:23
+ --> $DIR/diagnostic-derive.rs:785:23
|
LL | #[suggestion(code(foo))]
| ^^^
error: `code = "..."`/`code(...)` must contain only string literals
- --> $DIR/diagnostic-derive.rs:791:18
+ --> $DIR/diagnostic-derive.rs:793:18
|
LL | #[suggestion(code = 3)]
| ^^^^^^^^
+error: `#[suggestion(...)]` is not a valid attribute
+ --> $DIR/diagnostic-derive.rs:808:5
+ |
+LL | #[suggestion(no_crate_suggestion, code = "")]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: `#[suggestion(...)]` applied to `Vec` field is ambiguous
+ = help: to show a suggestion consisting of multiple parts, use a `Subdiagnostic` annotated with `#[multipart_suggestion(...)]`
+ = help: to show a variable set of suggestions, use a `Vec` of `Subdiagnostic`s annotated with `#[suggestion(...)]`
+
error: cannot find attribute `nonsense` in this scope
- --> $DIR/diagnostic-derive.rs:55:3
+ --> $DIR/diagnostic-derive.rs:57:3
|
-LL | #[nonsense(compiletest_example, code = "E0123")]
+LL | #[nonsense(no_crate_example, code = "E0123")]
| ^^^^^^^^
error: cannot find attribute `nonsense` in this scope
- --> $DIR/diagnostic-derive.rs:145:7
+ --> $DIR/diagnostic-derive.rs:147:7
|
LL | #[nonsense]
| ^^^^^^^^
error: cannot find attribute `error` in this scope
- --> $DIR/diagnostic-derive.rs:565:3
+ --> $DIR/diagnostic-derive.rs:567:3
|
-LL | #[error(compiletest_example, code = "E0123")]
+LL | #[error(no_crate_example, code = "E0123")]
| ^^^^^
error: cannot find attribute `warn_` in this scope
- --> $DIR/diagnostic-derive.rs:572:3
+ --> $DIR/diagnostic-derive.rs:574:3
|
-LL | #[warn_(compiletest_example, code = "E0123")]
+LL | #[warn_(no_crate_example, code = "E0123")]
| ^^^^^ help: a built-in attribute with a similar name exists: `warn`
error: cannot find attribute `lint` in this scope
- --> $DIR/diagnostic-derive.rs:579:3
+ --> $DIR/diagnostic-derive.rs:581:3
|
-LL | #[lint(compiletest_example, code = "E0123")]
+LL | #[lint(no_crate_example, code = "E0123")]
| ^^^^ help: a built-in attribute with a similar name exists: `link`
error: cannot find attribute `lint` in this scope
- --> $DIR/diagnostic-derive.rs:586:3
+ --> $DIR/diagnostic-derive.rs:588:3
|
-LL | #[lint(compiletest_example, code = "E0123")]
+LL | #[lint(no_crate_example, code = "E0123")]
| ^^^^ help: a built-in attribute with a similar name exists: `link`
error: cannot find attribute `multipart_suggestion` in this scope
- --> $DIR/diagnostic-derive.rs:627:3
+ --> $DIR/diagnostic-derive.rs:629:3
|
-LL | #[multipart_suggestion(suggestion)]
+LL | #[multipart_suggestion(no_crate_suggestion)]
| ^^^^^^^^^^^^^^^^^^^^
error: cannot find attribute `multipart_suggestion` in this scope
- --> $DIR/diagnostic-derive.rs:630:3
+ --> $DIR/diagnostic-derive.rs:632:3
|
LL | #[multipart_suggestion()]
| ^^^^^^^^^^^^^^^^^^^^
error: cannot find attribute `multipart_suggestion` in this scope
- --> $DIR/diagnostic-derive.rs:634:7
+ --> $DIR/diagnostic-derive.rs:636:7
|
-LL | #[multipart_suggestion(suggestion)]
+LL | #[multipart_suggestion(no_crate_suggestion)]
| ^^^^^^^^^^^^^^^^^^^^
-error[E0425]: cannot find value `nonsense` in module `rustc_errors::fluent`
- --> $DIR/diagnostic-derive.rs:68:8
+error[E0425]: cannot find value `nonsense` in module `crate::fluent_generated`
+ --> $DIR/diagnostic-derive.rs:70:8
|
LL | #[diag(nonsense, code = "E0123")]
- | ^^^^^^^^ not found in `rustc_errors::fluent`
+ | ^^^^^^^^ not found in `crate::fluent_generated`
error[E0277]: the trait bound `Hello: IntoDiagnosticArg` is not satisfied
- --> $DIR/diagnostic-derive.rs:339:10
+ --> $DIR/diagnostic-derive.rs:341:10
|
LL | #[derive(Diagnostic)]
| ^^^^^^^^^^ the trait `IntoDiagnosticArg` is not implemented for `Hello`
@@ -660,7 +670,7 @@ note: required by a bound in `DiagnosticBuilder::<'a, G>::set_arg`
--> $COMPILER_DIR/rustc_errors/src/diagnostic_builder.rs:LL:CC
= note: this error originates in the derive macro `Diagnostic` which comes from the expansion of the macro `forward` (in Nightly builds, run with -Z macro-backtrace for more info)
-error: aborting due to 83 previous errors
+error: aborting due to 84 previous errors
Some errors have detailed explanations: E0277, E0425.
For more information about an error, try `rustc --explain E0277`.
diff --git a/tests/ui-fulldeps/session-diagnostic/example.ftl b/tests/ui-fulldeps/session-diagnostic/example.ftl
new file mode 100644
index 000000000..cb2d476d8
--- /dev/null
+++ b/tests/ui-fulldeps/session-diagnostic/example.ftl
@@ -0,0 +1,5 @@
+no_crate_example = this is an example message used in testing
+ .note = with a note
+ .help = with a help
+ .suggestion = with a suggestion
+ .label = with a label
diff --git a/tests/ui-fulldeps/session-diagnostic/subdiagnostic-derive.rs b/tests/ui-fulldeps/session-diagnostic/subdiagnostic-derive.rs
index 61ac456a6..c882f7792 100644
--- a/tests/ui-fulldeps/session-diagnostic/subdiagnostic-derive.rs
+++ b/tests/ui-fulldeps/session-diagnostic/subdiagnostic-derive.rs
@@ -15,12 +15,14 @@ extern crate rustc_macros;
extern crate rustc_session;
extern crate rustc_span;
-use rustc_errors::Applicability;
-use rustc_macros::Subdiagnostic;
+use rustc_errors::{Applicability, DiagnosticMessage, SubdiagnosticMessage};
+use rustc_macros::{fluent_messages, Subdiagnostic};
use rustc_span::Span;
+fluent_messages! { "./example.ftl" }
+
#[derive(Subdiagnostic)]
-#[label(parse_add_paren)]
+#[label(no_crate_example)]
struct A {
#[primary_span]
span: Span,
@@ -29,13 +31,13 @@ struct A {
#[derive(Subdiagnostic)]
enum B {
- #[label(parse_add_paren)]
+ #[label(no_crate_example)]
A {
#[primary_span]
span: Span,
var: String,
},
- #[label(parse_add_paren)]
+ #[label(no_crate_example)]
B {
#[primary_span]
span: Span,
@@ -44,7 +46,7 @@ enum B {
}
#[derive(Subdiagnostic)]
-#[label(parse_add_paren)]
+#[label(no_crate_example)]
//~^ ERROR label without `#[primary_span]` field
struct C {
var: String,
@@ -120,8 +122,8 @@ struct K {
#[derive(Subdiagnostic)]
#[label(slug)]
-//~^ ERROR cannot find value `slug` in module `rustc_errors::fluent`
-//~^^ NOTE not found in `rustc_errors::fluent`
+//~^ ERROR cannot find value `slug` in module `crate::fluent_generated`
+//~^^ NOTE not found in `crate::fluent_generated`
struct L {
#[primary_span]
span: Span,
@@ -138,7 +140,7 @@ struct M {
}
#[derive(Subdiagnostic)]
-#[label(parse_add_paren, code = "...")]
+#[label(no_crate_example, code = "...")]
//~^ ERROR `#[label(code = ...)]` is not a valid attribute
struct N {
#[primary_span]
@@ -147,7 +149,7 @@ struct N {
}
#[derive(Subdiagnostic)]
-#[label(parse_add_paren, applicability = "machine-applicable")]
+#[label(no_crate_example, applicability = "machine-applicable")]
//~^ ERROR `#[label(applicability = ...)]` is not a valid attribute
struct O {
#[primary_span]
@@ -160,7 +162,7 @@ struct O {
//~^ ERROR cannot find attribute `foo` in this scope
//~^^ ERROR unsupported type attribute for subdiagnostic enum
enum P {
- #[label(parse_add_paren)]
+ #[label(no_crate_example)]
A {
#[primary_span]
span: Span,
@@ -230,7 +232,7 @@ enum U {
#[derive(Subdiagnostic)]
enum V {
- #[label(parse_add_paren)]
+ #[label(no_crate_example)]
A {
#[primary_span]
span: Span,
@@ -244,7 +246,7 @@ enum V {
}
#[derive(Subdiagnostic)]
-#[label(parse_add_paren)]
+#[label(no_crate_example)]
//~^ ERROR label without `#[primary_span]` field
struct W {
#[primary_span]
@@ -253,7 +255,7 @@ struct W {
}
#[derive(Subdiagnostic)]
-#[label(parse_add_paren)]
+#[label(no_crate_example)]
struct X {
#[primary_span]
span: Span,
@@ -263,7 +265,7 @@ struct X {
}
#[derive(Subdiagnostic)]
-#[label(parse_add_paren)]
+#[label(no_crate_example)]
struct Y {
#[primary_span]
span: Span,
@@ -274,7 +276,7 @@ struct Y {
}
#[derive(Subdiagnostic)]
-#[label(parse_add_paren)]
+#[label(no_crate_example)]
struct Z {
#[primary_span]
span: Span,
@@ -285,7 +287,7 @@ struct Z {
}
#[derive(Subdiagnostic)]
-#[label(parse_add_paren)]
+#[label(no_crate_example)]
struct AA {
#[primary_span]
span: Span,
@@ -296,7 +298,7 @@ struct AA {
}
#[derive(Subdiagnostic)]
-#[label(parse_add_paren)]
+#[label(no_crate_example)]
struct AB {
#[primary_span]
span: Span,
@@ -312,23 +314,23 @@ union AC {
}
#[derive(Subdiagnostic)]
-#[label(parse_add_paren)]
-#[label(parse_add_paren)]
+#[label(no_crate_example)]
+#[label(no_crate_example)]
struct AD {
#[primary_span]
span: Span,
}
#[derive(Subdiagnostic)]
-#[label(parse_add_paren, parse_add_paren)]
-//~^ ERROR `#[label(parse_add_paren)]` is not a valid attribute
+#[label(no_crate_example, no_crate::example)]
+//~^ ERROR `#[label(no_crate::example)]` is not a valid attribute
struct AE {
#[primary_span]
span: Span,
}
#[derive(Subdiagnostic)]
-#[label(parse_add_paren)]
+#[label(no_crate_example)]
struct AF {
#[primary_span]
//~^ NOTE previously specified here
@@ -346,7 +348,7 @@ struct AG {
}
#[derive(Subdiagnostic)]
-#[suggestion(parse_add_paren, code = "...")]
+#[suggestion(no_crate_example, code = "...")]
struct AH {
#[primary_span]
span: Span,
@@ -357,7 +359,7 @@ struct AH {
#[derive(Subdiagnostic)]
enum AI {
- #[suggestion(parse_add_paren, code = "...")]
+ #[suggestion(no_crate_example, code = "...")]
A {
#[primary_span]
span: Span,
@@ -365,7 +367,7 @@ enum AI {
applicability: Applicability,
var: String,
},
- #[suggestion(parse_add_paren, code = "...")]
+ #[suggestion(no_crate_example, code = "...")]
B {
#[primary_span]
span: Span,
@@ -376,7 +378,7 @@ enum AI {
}
#[derive(Subdiagnostic)]
-#[suggestion(parse_add_paren, code = "...", code = "...")]
+#[suggestion(no_crate_example, code = "...", code = "...")]
//~^ ERROR specified multiple times
//~^^ NOTE previously specified here
struct AJ {
@@ -387,7 +389,7 @@ struct AJ {
}
#[derive(Subdiagnostic)]
-#[suggestion(parse_add_paren, code = "...")]
+#[suggestion(no_crate_example, code = "...")]
struct AK {
#[primary_span]
span: Span,
@@ -400,7 +402,7 @@ struct AK {
}
#[derive(Subdiagnostic)]
-#[suggestion(parse_add_paren, code = "...")]
+#[suggestion(no_crate_example, code = "...")]
struct AL {
#[primary_span]
span: Span,
@@ -410,14 +412,14 @@ struct AL {
}
#[derive(Subdiagnostic)]
-#[suggestion(parse_add_paren, code = "...")]
+#[suggestion(no_crate_example, code = "...")]
struct AM {
#[primary_span]
span: Span,
}
#[derive(Subdiagnostic)]
-#[suggestion(parse_add_paren)]
+#[suggestion(no_crate_example)]
//~^ ERROR suggestion without `code = "..."`
struct AN {
#[primary_span]
@@ -427,7 +429,7 @@ struct AN {
}
#[derive(Subdiagnostic)]
-#[suggestion(parse_add_paren, code = "...", applicability = "foo")]
+#[suggestion(no_crate_example, code = "...", applicability = "foo")]
//~^ ERROR invalid applicability
struct AO {
#[primary_span]
@@ -435,24 +437,24 @@ struct AO {
}
#[derive(Subdiagnostic)]
-#[help(parse_add_paren)]
+#[help(no_crate_example)]
struct AP {
var: String,
}
#[derive(Subdiagnostic)]
-#[note(parse_add_paren)]
+#[note(no_crate_example)]
struct AQ;
#[derive(Subdiagnostic)]
-#[suggestion(parse_add_paren, code = "...")]
+#[suggestion(no_crate_example, code = "...")]
//~^ ERROR suggestion without `#[primary_span]` field
struct AR {
var: String,
}
#[derive(Subdiagnostic)]
-#[suggestion(parse_add_paren, code = "...", applicability = "machine-applicable")]
+#[suggestion(no_crate_example, code = "...", applicability = "machine-applicable")]
struct AS {
#[primary_span]
span: Span,
@@ -462,7 +464,7 @@ struct AS {
#[label]
//~^ ERROR unsupported type attribute for subdiagnostic enum
enum AT {
- #[label(parse_add_paren)]
+ #[label(no_crate_example)]
A {
#[primary_span]
span: Span,
@@ -471,7 +473,7 @@ enum AT {
}
#[derive(Subdiagnostic)]
-#[suggestion(parse_add_paren, code = "{var}", applicability = "machine-applicable")]
+#[suggestion(no_crate_example, code = "{var}", applicability = "machine-applicable")]
struct AU {
#[primary_span]
span: Span,
@@ -479,7 +481,7 @@ struct AU {
}
#[derive(Subdiagnostic)]
-#[suggestion(parse_add_paren, code = "{var}", applicability = "machine-applicable")]
+#[suggestion(no_crate_example, code = "{var}", applicability = "machine-applicable")]
//~^ ERROR `var` doesn't refer to a field on this type
struct AV {
#[primary_span]
@@ -488,7 +490,7 @@ struct AV {
#[derive(Subdiagnostic)]
enum AW {
- #[suggestion(parse_add_paren, code = "{var}", applicability = "machine-applicable")]
+ #[suggestion(no_crate_example, code = "{var}", applicability = "machine-applicable")]
A {
#[primary_span]
span: Span,
@@ -498,7 +500,7 @@ enum AW {
#[derive(Subdiagnostic)]
enum AX {
- #[suggestion(parse_add_paren, code = "{var}", applicability = "machine-applicable")]
+ #[suggestion(no_crate_example, code = "{var}", applicability = "machine-applicable")]
//~^ ERROR `var` doesn't refer to a field on this type
A {
#[primary_span]
@@ -507,18 +509,18 @@ enum AX {
}
#[derive(Subdiagnostic)]
-#[warning(parse_add_paren)]
+#[warning(no_crate_example)]
struct AY {}
#[derive(Subdiagnostic)]
-#[warning(parse_add_paren)]
+#[warning(no_crate_example)]
struct AZ {
#[primary_span]
span: Span,
}
#[derive(Subdiagnostic)]
-#[suggestion(parse_add_paren, code = "...")]
+#[suggestion(no_crate_example, code = "...")]
//~^ ERROR suggestion without `#[primary_span]` field
struct BA {
#[suggestion_part]
@@ -533,7 +535,7 @@ struct BA {
}
#[derive(Subdiagnostic)]
-#[multipart_suggestion(parse_add_paren, code = "...", applicability = "machine-applicable")]
+#[multipart_suggestion(no_crate_example, code = "...", applicability = "machine-applicable")]
//~^ ERROR multipart suggestion without any `#[suggestion_part(...)]` fields
//~| ERROR `#[multipart_suggestion(code = ...)]` is not a valid attribute
struct BBa {
@@ -541,7 +543,7 @@ struct BBa {
}
#[derive(Subdiagnostic)]
-#[multipart_suggestion(parse_add_paren, applicability = "machine-applicable")]
+#[multipart_suggestion(no_crate_example, applicability = "machine-applicable")]
struct BBb {
#[suggestion_part]
//~^ ERROR `#[suggestion_part(...)]` attribute without `code = "..."`
@@ -549,7 +551,7 @@ struct BBb {
}
#[derive(Subdiagnostic)]
-#[multipart_suggestion(parse_add_paren, applicability = "machine-applicable")]
+#[multipart_suggestion(no_crate_example, applicability = "machine-applicable")]
struct BBc {
#[suggestion_part()]
//~^ ERROR `#[suggestion_part(...)]` attribute without `code = "..."`
@@ -557,7 +559,7 @@ struct BBc {
}
#[derive(Subdiagnostic)]
-#[multipart_suggestion(parse_add_paren)]
+#[multipart_suggestion(no_crate_example)]
//~^ ERROR multipart suggestion without any `#[suggestion_part(...)]` fields
struct BC {
#[primary_span]
@@ -566,7 +568,7 @@ struct BC {
}
#[derive(Subdiagnostic)]
-#[multipart_suggestion(parse_add_paren)]
+#[multipart_suggestion(no_crate_example)]
struct BD {
#[suggestion_part]
//~^ ERROR `#[suggestion_part(...)]` attribute without `code = "..."`
@@ -586,7 +588,7 @@ struct BD {
}
#[derive(Subdiagnostic)]
-#[multipart_suggestion(parse_add_paren, applicability = "machine-applicable")]
+#[multipart_suggestion(no_crate_example, applicability = "machine-applicable")]
struct BE {
#[suggestion_part(code = "...", code = ",,,")]
//~^ ERROR specified multiple times
@@ -595,7 +597,7 @@ struct BE {
}
#[derive(Subdiagnostic)]
-#[multipart_suggestion(parse_add_paren, applicability = "machine-applicable")]
+#[multipart_suggestion(no_crate_example, applicability = "machine-applicable")]
struct BF {
#[suggestion_part(code = "(")]
first: Span,
@@ -604,7 +606,7 @@ struct BF {
}
#[derive(Subdiagnostic)]
-#[multipart_suggestion(parse_add_paren)]
+#[multipart_suggestion(no_crate_example)]
struct BG {
#[applicability]
appl: Applicability,
@@ -615,7 +617,7 @@ struct BG {
}
#[derive(Subdiagnostic)]
-#[multipart_suggestion(parse_add_paren, applicability = "machine-applicable")]
+#[multipart_suggestion(no_crate_example, applicability = "machine-applicable")]
struct BH {
#[applicability]
//~^ ERROR `#[applicability]` has no effect
@@ -627,14 +629,14 @@ struct BH {
}
#[derive(Subdiagnostic)]
-#[multipart_suggestion(parse_add_paren, applicability = "machine-applicable")]
+#[multipart_suggestion(no_crate_example, applicability = "machine-applicable")]
struct BI {
#[suggestion_part(code = "")]
spans: Vec<Span>,
}
#[derive(Subdiagnostic)]
-#[label(parse_add_paren)]
+#[label(no_crate_example)]
struct BJ {
#[primary_span]
span: Span,
@@ -643,7 +645,7 @@ struct BJ {
/// with a doc comment on the type..
#[derive(Subdiagnostic)]
-#[label(parse_add_paren)]
+#[label(no_crate_example)]
struct BK {
/// ..and the field
#[primary_span]
@@ -654,7 +656,7 @@ struct BK {
#[derive(Subdiagnostic)]
enum BL {
/// ..and the variant..
- #[label(parse_add_paren)]
+ #[label(no_crate_example)]
Foo {
/// ..and the field
#[primary_span]
@@ -663,7 +665,7 @@ enum BL {
}
#[derive(Subdiagnostic)]
-#[multipart_suggestion(parse_add_paren)]
+#[multipart_suggestion(no_crate_example)]
struct BM {
#[suggestion_part(code("foo"))]
//~^ ERROR expected exactly one string literal for `code = ...`
@@ -672,7 +674,7 @@ struct BM {
}
#[derive(Subdiagnostic)]
-#[multipart_suggestion(parse_add_paren)]
+#[multipart_suggestion(no_crate_example)]
struct BN {
#[suggestion_part(code("foo", "bar"))]
//~^ ERROR expected exactly one string literal for `code = ...`
@@ -681,7 +683,7 @@ struct BN {
}
#[derive(Subdiagnostic)]
-#[multipart_suggestion(parse_add_paren)]
+#[multipart_suggestion(no_crate_example)]
struct BO {
#[suggestion_part(code(3))]
//~^ ERROR expected exactly one string literal for `code = ...`
@@ -690,7 +692,7 @@ struct BO {
}
#[derive(Subdiagnostic)]
-#[multipart_suggestion(parse_add_paren)]
+#[multipart_suggestion(no_crate_example)]
struct BP {
#[suggestion_part(code())]
//~^ ERROR expected exactly one string literal for `code = ...`
@@ -699,7 +701,7 @@ struct BP {
}
#[derive(Subdiagnostic)]
-#[multipart_suggestion(parse_add_paren)]
+#[multipart_suggestion(no_crate_example)]
struct BQ {
#[suggestion_part(code = 3)]
//~^ ERROR `code = "..."`/`code(...)` must contain only string literals
@@ -708,42 +710,42 @@ struct BQ {
}
#[derive(Subdiagnostic)]
-#[suggestion(parse_add_paren, code = "")]
+#[suggestion(no_crate_example, code = "")]
struct SuggestionStyleDefault {
#[primary_span]
sub: Span,
}
#[derive(Subdiagnostic)]
-#[suggestion(parse_add_paren, code = "", style = "short")]
+#[suggestion(no_crate_example, code = "", style = "short")]
struct SuggestionStyleShort {
#[primary_span]
sub: Span,
}
#[derive(Subdiagnostic)]
-#[suggestion(parse_add_paren, code = "", style = "hidden")]
+#[suggestion(no_crate_example, code = "", style = "hidden")]
struct SuggestionStyleHidden {
#[primary_span]
sub: Span,
}
#[derive(Subdiagnostic)]
-#[suggestion(parse_add_paren, code = "", style = "verbose")]
+#[suggestion(no_crate_example, code = "", style = "verbose")]
struct SuggestionStyleVerbose {
#[primary_span]
sub: Span,
}
#[derive(Subdiagnostic)]
-#[suggestion(parse_add_paren, code = "", style = "tool-only")]
+#[suggestion(no_crate_example, code = "", style = "tool-only")]
struct SuggestionStyleToolOnly {
#[primary_span]
sub: Span,
}
#[derive(Subdiagnostic)]
-#[suggestion(parse_add_paren, code = "", style = "hidden", style = "normal")]
+#[suggestion(no_crate_example, code = "", style = "hidden", style = "normal")]
//~^ ERROR specified multiple times
//~| NOTE previously specified here
struct SuggestionStyleTwice {
@@ -752,7 +754,7 @@ struct SuggestionStyleTwice {
}
#[derive(Subdiagnostic)]
-#[suggestion_hidden(parse_add_paren, code = "")]
+#[suggestion_hidden(no_crate_example, code = "")]
//~^ ERROR #[suggestion_hidden(...)]` is not a valid attribute
struct SuggestionStyleOldSyntax {
#[primary_span]
@@ -760,7 +762,7 @@ struct SuggestionStyleOldSyntax {
}
#[derive(Subdiagnostic)]
-#[suggestion_hidden(parse_add_paren, code = "", style = "normal")]
+#[suggestion_hidden(no_crate_example, code = "", style = "normal")]
//~^ ERROR #[suggestion_hidden(...)]` is not a valid attribute
struct SuggestionStyleOldAndNewSyntax {
#[primary_span]
@@ -768,7 +770,7 @@ struct SuggestionStyleOldAndNewSyntax {
}
#[derive(Subdiagnostic)]
-#[suggestion(parse_add_paren, code = "", style = "foo")]
+#[suggestion(no_crate_example, code = "", style = "foo")]
//~^ ERROR invalid suggestion style
struct SuggestionStyleInvalid1 {
#[primary_span]
@@ -776,7 +778,7 @@ struct SuggestionStyleInvalid1 {
}
#[derive(Subdiagnostic)]
-#[suggestion(parse_add_paren, code = "", style = 42)]
+#[suggestion(no_crate_example, code = "", style = 42)]
//~^ ERROR `#[suggestion(style = ...)]` is not a valid attribute
struct SuggestionStyleInvalid2 {
#[primary_span]
@@ -784,7 +786,7 @@ struct SuggestionStyleInvalid2 {
}
#[derive(Subdiagnostic)]
-#[suggestion(parse_add_paren, code = "", style)]
+#[suggestion(no_crate_example, code = "", style)]
//~^ ERROR `#[suggestion(style)]` is not a valid attribute
struct SuggestionStyleInvalid3 {
#[primary_span]
@@ -792,9 +794,19 @@ struct SuggestionStyleInvalid3 {
}
#[derive(Subdiagnostic)]
-#[suggestion(parse_add_paren, code = "", style("foo"))]
+#[suggestion(no_crate_example, code = "", style("foo"))]
//~^ ERROR `#[suggestion(style(...))]` is not a valid attribute
struct SuggestionStyleInvalid4 {
#[primary_span]
sub: Span,
}
+
+#[derive(Subdiagnostic)]
+#[suggestion(no_crate_example, code = "")]
+//~^ ERROR suggestion without `#[primary_span]` field
+struct PrimarySpanOnVec {
+ #[primary_span]
+ //~^ ERROR `#[primary_span]` is not a valid attribute
+ //~| NOTE there must be exactly one primary span
+ sub: Vec<Span>,
+}
diff --git a/tests/ui-fulldeps/session-diagnostic/subdiagnostic-derive.stderr b/tests/ui-fulldeps/session-diagnostic/subdiagnostic-derive.stderr
index b594fa6cd..343134af6 100644
--- a/tests/ui-fulldeps/session-diagnostic/subdiagnostic-derive.stderr
+++ b/tests/ui-fulldeps/session-diagnostic/subdiagnostic-derive.stderr
@@ -1,7 +1,7 @@
error: label without `#[primary_span]` field
- --> $DIR/subdiagnostic-derive.rs:47:1
+ --> $DIR/subdiagnostic-derive.rs:49:1
|
-LL | / #[label(parse_add_paren)]
+LL | / #[label(no_crate_example)]
LL | |
LL | | struct C {
LL | | var: String,
@@ -9,141 +9,141 @@ LL | | }
| |_^
error: diagnostic slug must be first argument of a `#[label(...)]` attribute
- --> $DIR/subdiagnostic-derive.rs:54:1
+ --> $DIR/subdiagnostic-derive.rs:56:1
|
LL | #[label]
| ^^^^^^^^
error: `#[foo]` is not a valid attribute
- --> $DIR/subdiagnostic-derive.rs:63:1
+ --> $DIR/subdiagnostic-derive.rs:65:1
|
LL | #[foo]
| ^^^^^^
error: `#[label = ...]` is not a valid attribute
- --> $DIR/subdiagnostic-derive.rs:73:1
+ --> $DIR/subdiagnostic-derive.rs:75:1
|
LL | #[label = "..."]
| ^^^^^^^^^^^^^^^^
error: `#[label(bug = ...)]` is not a valid attribute
- --> $DIR/subdiagnostic-derive.rs:82:9
+ --> $DIR/subdiagnostic-derive.rs:84:9
|
LL | #[label(bug = "...")]
| ^^^^^^^^^^^
error: diagnostic slug must be first argument of a `#[label(...)]` attribute
- --> $DIR/subdiagnostic-derive.rs:82:1
+ --> $DIR/subdiagnostic-derive.rs:84:1
|
LL | #[label(bug = "...")]
| ^^^^^^^^^^^^^^^^^^^^^
error: `#[label("...")]` is not a valid attribute
- --> $DIR/subdiagnostic-derive.rs:92:9
+ --> $DIR/subdiagnostic-derive.rs:94:9
|
LL | #[label("...")]
| ^^^^^
error: diagnostic slug must be first argument of a `#[label(...)]` attribute
- --> $DIR/subdiagnostic-derive.rs:92:1
+ --> $DIR/subdiagnostic-derive.rs:94:1
|
LL | #[label("...")]
| ^^^^^^^^^^^^^^^
error: `#[label(slug = ...)]` is not a valid attribute
- --> $DIR/subdiagnostic-derive.rs:102:9
+ --> $DIR/subdiagnostic-derive.rs:104:9
|
LL | #[label(slug = 4)]
| ^^^^^^^^
error: diagnostic slug must be first argument of a `#[label(...)]` attribute
- --> $DIR/subdiagnostic-derive.rs:102:1
+ --> $DIR/subdiagnostic-derive.rs:104:1
|
LL | #[label(slug = 4)]
| ^^^^^^^^^^^^^^^^^^
error: `#[label(slug(...))]` is not a valid attribute
- --> $DIR/subdiagnostic-derive.rs:112:9
+ --> $DIR/subdiagnostic-derive.rs:114:9
|
LL | #[label(slug("..."))]
| ^^^^^^^^^^^
error: diagnostic slug must be first argument of a `#[label(...)]` attribute
- --> $DIR/subdiagnostic-derive.rs:112:1
+ --> $DIR/subdiagnostic-derive.rs:114:1
|
LL | #[label(slug("..."))]
| ^^^^^^^^^^^^^^^^^^^^^
error: diagnostic slug must be first argument of a `#[label(...)]` attribute
- --> $DIR/subdiagnostic-derive.rs:132:1
+ --> $DIR/subdiagnostic-derive.rs:134:1
|
LL | #[label()]
| ^^^^^^^^^^
error: `#[label(code = ...)]` is not a valid attribute
- --> $DIR/subdiagnostic-derive.rs:141:26
+ --> $DIR/subdiagnostic-derive.rs:143:27
|
-LL | #[label(parse_add_paren, code = "...")]
- | ^^^^^^^^^^^^
+LL | #[label(no_crate_example, code = "...")]
+ | ^^^^^^^^^^^^
error: `#[label(applicability = ...)]` is not a valid attribute
- --> $DIR/subdiagnostic-derive.rs:150:26
+ --> $DIR/subdiagnostic-derive.rs:152:27
|
-LL | #[label(parse_add_paren, applicability = "machine-applicable")]
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | #[label(no_crate_example, applicability = "machine-applicable")]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: unsupported type attribute for subdiagnostic enum
- --> $DIR/subdiagnostic-derive.rs:159:1
+ --> $DIR/subdiagnostic-derive.rs:161:1
|
LL | #[foo]
| ^^^^^^
error: `#[bar]` is not a valid attribute
- --> $DIR/subdiagnostic-derive.rs:173:5
+ --> $DIR/subdiagnostic-derive.rs:175:5
|
LL | #[bar]
| ^^^^^^
error: `#[bar = ...]` is not a valid attribute
- --> $DIR/subdiagnostic-derive.rs:185:5
+ --> $DIR/subdiagnostic-derive.rs:187:5
|
LL | #[bar = "..."]
| ^^^^^^^^^^^^^^
error: `#[bar = ...]` is not a valid attribute
- --> $DIR/subdiagnostic-derive.rs:197:5
+ --> $DIR/subdiagnostic-derive.rs:199:5
|
LL | #[bar = 4]
| ^^^^^^^^^^
error: `#[bar(...)]` is not a valid attribute
- --> $DIR/subdiagnostic-derive.rs:209:5
+ --> $DIR/subdiagnostic-derive.rs:211:5
|
LL | #[bar("...")]
| ^^^^^^^^^^^^^
error: `#[label(code = ...)]` is not a valid attribute
- --> $DIR/subdiagnostic-derive.rs:221:13
+ --> $DIR/subdiagnostic-derive.rs:223:13
|
LL | #[label(code = "...")]
| ^^^^^^^^^^^^
error: diagnostic slug must be first argument of a `#[label(...)]` attribute
- --> $DIR/subdiagnostic-derive.rs:221:5
+ --> $DIR/subdiagnostic-derive.rs:223:5
|
LL | #[label(code = "...")]
| ^^^^^^^^^^^^^^^^^^^^^^
error: the `#[primary_span]` attribute can only be applied to fields of type `Span` or `MultiSpan`
- --> $DIR/subdiagnostic-derive.rs:250:5
+ --> $DIR/subdiagnostic-derive.rs:252:5
|
LL | #[primary_span]
| ^^^^^^^^^^^^^^^
error: label without `#[primary_span]` field
- --> $DIR/subdiagnostic-derive.rs:247:1
+ --> $DIR/subdiagnostic-derive.rs:249:1
|
-LL | / #[label(parse_add_paren)]
+LL | / #[label(no_crate_example)]
LL | |
LL | | struct W {
LL | | #[primary_span]
@@ -153,13 +153,13 @@ LL | | }
| |_^
error: `#[applicability]` is only valid on suggestions
- --> $DIR/subdiagnostic-derive.rs:260:5
+ --> $DIR/subdiagnostic-derive.rs:262:5
|
LL | #[applicability]
| ^^^^^^^^^^^^^^^^
error: `#[bar]` is not a valid attribute
- --> $DIR/subdiagnostic-derive.rs:270:5
+ --> $DIR/subdiagnostic-derive.rs:272:5
|
LL | #[bar]
| ^^^^^^
@@ -167,13 +167,13 @@ LL | #[bar]
= help: only `primary_span`, `applicability` and `skip_arg` are valid field attributes
error: `#[bar = ...]` is not a valid attribute
- --> $DIR/subdiagnostic-derive.rs:281:5
+ --> $DIR/subdiagnostic-derive.rs:283:5
|
LL | #[bar = "..."]
| ^^^^^^^^^^^^^^
error: `#[bar(...)]` is not a valid attribute
- --> $DIR/subdiagnostic-derive.rs:292:5
+ --> $DIR/subdiagnostic-derive.rs:294:5
|
LL | #[bar("...")]
| ^^^^^^^^^^^^^
@@ -181,7 +181,7 @@ LL | #[bar("...")]
= help: only `primary_span`, `applicability` and `skip_arg` are valid field attributes
error: unexpected unsupported untagged union
- --> $DIR/subdiagnostic-derive.rs:308:1
+ --> $DIR/subdiagnostic-derive.rs:310:1
|
LL | / union AC {
LL | |
@@ -190,78 +190,78 @@ LL | | b: u64,
LL | | }
| |_^
-error: `#[label(parse_add_paren)]` is not a valid attribute
- --> $DIR/subdiagnostic-derive.rs:323:26
+error: `#[label(no_crate::example)]` is not a valid attribute
+ --> $DIR/subdiagnostic-derive.rs:325:27
|
-LL | #[label(parse_add_paren, parse_add_paren)]
- | ^^^^^^^^^^^^^^^
+LL | #[label(no_crate_example, no_crate::example)]
+ | ^^^^^^^^^^^^^^^^^
|
= help: a diagnostic slug must be the first argument to the attribute
error: specified multiple times
- --> $DIR/subdiagnostic-derive.rs:336:5
+ --> $DIR/subdiagnostic-derive.rs:338:5
|
LL | #[primary_span]
| ^^^^^^^^^^^^^^^
|
note: previously specified here
- --> $DIR/subdiagnostic-derive.rs:333:5
+ --> $DIR/subdiagnostic-derive.rs:335:5
|
LL | #[primary_span]
| ^^^^^^^^^^^^^^^
error: subdiagnostic kind not specified
- --> $DIR/subdiagnostic-derive.rs:342:8
+ --> $DIR/subdiagnostic-derive.rs:344:8
|
LL | struct AG {
| ^^
error: specified multiple times
- --> $DIR/subdiagnostic-derive.rs:379:45
+ --> $DIR/subdiagnostic-derive.rs:381:46
|
-LL | #[suggestion(parse_add_paren, code = "...", code = "...")]
- | ^^^^^^^^^^^^
+LL | #[suggestion(no_crate_example, code = "...", code = "...")]
+ | ^^^^^^^^^^^^
|
note: previously specified here
- --> $DIR/subdiagnostic-derive.rs:379:31
+ --> $DIR/subdiagnostic-derive.rs:381:32
|
-LL | #[suggestion(parse_add_paren, code = "...", code = "...")]
- | ^^^^^^^^^^^^
+LL | #[suggestion(no_crate_example, code = "...", code = "...")]
+ | ^^^^^^^^^^^^
error: specified multiple times
- --> $DIR/subdiagnostic-derive.rs:397:5
+ --> $DIR/subdiagnostic-derive.rs:399:5
|
LL | #[applicability]
| ^^^^^^^^^^^^^^^^
|
note: previously specified here
- --> $DIR/subdiagnostic-derive.rs:394:5
+ --> $DIR/subdiagnostic-derive.rs:396:5
|
LL | #[applicability]
| ^^^^^^^^^^^^^^^^
error: the `#[applicability]` attribute can only be applied to fields of type `Applicability`
- --> $DIR/subdiagnostic-derive.rs:407:5
+ --> $DIR/subdiagnostic-derive.rs:409:5
|
LL | #[applicability]
| ^^^^^^^^^^^^^^^^
error: suggestion without `code = "..."`
- --> $DIR/subdiagnostic-derive.rs:420:1
+ --> $DIR/subdiagnostic-derive.rs:422:1
|
-LL | #[suggestion(parse_add_paren)]
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | #[suggestion(no_crate_example)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: invalid applicability
- --> $DIR/subdiagnostic-derive.rs:430:45
+ --> $DIR/subdiagnostic-derive.rs:432:46
|
-LL | #[suggestion(parse_add_paren, code = "...", applicability = "foo")]
- | ^^^^^^^^^^^^^^^^^^^^^
+LL | #[suggestion(no_crate_example, code = "...", applicability = "foo")]
+ | ^^^^^^^^^^^^^^^^^^^^^
error: suggestion without `#[primary_span]` field
- --> $DIR/subdiagnostic-derive.rs:448:1
+ --> $DIR/subdiagnostic-derive.rs:450:1
|
-LL | / #[suggestion(parse_add_paren, code = "...")]
+LL | / #[suggestion(no_crate_example, code = "...")]
LL | |
LL | | struct AR {
LL | | var: String,
@@ -269,25 +269,25 @@ LL | | }
| |_^
error: unsupported type attribute for subdiagnostic enum
- --> $DIR/subdiagnostic-derive.rs:462:1
+ --> $DIR/subdiagnostic-derive.rs:464:1
|
LL | #[label]
| ^^^^^^^^
error: `var` doesn't refer to a field on this type
- --> $DIR/subdiagnostic-derive.rs:482:38
+ --> $DIR/subdiagnostic-derive.rs:484:39
|
-LL | #[suggestion(parse_add_paren, code = "{var}", applicability = "machine-applicable")]
- | ^^^^^^^
+LL | #[suggestion(no_crate_example, code = "{var}", applicability = "machine-applicable")]
+ | ^^^^^^^
error: `var` doesn't refer to a field on this type
- --> $DIR/subdiagnostic-derive.rs:501:42
+ --> $DIR/subdiagnostic-derive.rs:503:43
|
-LL | #[suggestion(parse_add_paren, code = "{var}", applicability = "machine-applicable")]
- | ^^^^^^^
+LL | #[suggestion(no_crate_example, code = "{var}", applicability = "machine-applicable")]
+ | ^^^^^^^
error: `#[suggestion_part]` is not a valid attribute
- --> $DIR/subdiagnostic-derive.rs:524:5
+ --> $DIR/subdiagnostic-derive.rs:526:5
|
LL | #[suggestion_part]
| ^^^^^^^^^^^^^^^^^^
@@ -295,7 +295,7 @@ LL | #[suggestion_part]
= help: `#[suggestion_part(...)]` is only valid in multipart suggestions, use `#[primary_span]` instead
error: `#[suggestion_part(...)]` is not a valid attribute
- --> $DIR/subdiagnostic-derive.rs:527:5
+ --> $DIR/subdiagnostic-derive.rs:529:5
|
LL | #[suggestion_part(code = "...")]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -303,9 +303,9 @@ LL | #[suggestion_part(code = "...")]
= help: `#[suggestion_part(...)]` is only valid in multipart suggestions
error: suggestion without `#[primary_span]` field
- --> $DIR/subdiagnostic-derive.rs:521:1
+ --> $DIR/subdiagnostic-derive.rs:523:1
|
-LL | / #[suggestion(parse_add_paren, code = "...")]
+LL | / #[suggestion(no_crate_example, code = "...")]
LL | |
LL | | struct BA {
LL | | #[suggestion_part]
@@ -315,17 +315,17 @@ LL | | }
| |_^
error: `#[multipart_suggestion(code = ...)]` is not a valid attribute
- --> $DIR/subdiagnostic-derive.rs:536:41
+ --> $DIR/subdiagnostic-derive.rs:538:42
|
-LL | #[multipart_suggestion(parse_add_paren, code = "...", applicability = "machine-applicable")]
- | ^^^^^^^^^^^^
+LL | #[multipart_suggestion(no_crate_example, code = "...", applicability = "machine-applicable")]
+ | ^^^^^^^^^^^^
|
= help: only `style` and `applicability` are valid nested attributes
error: multipart suggestion without any `#[suggestion_part(...)]` fields
- --> $DIR/subdiagnostic-derive.rs:536:1
+ --> $DIR/subdiagnostic-derive.rs:538:1
|
-LL | / #[multipart_suggestion(parse_add_paren, code = "...", applicability = "machine-applicable")]
+LL | / #[multipart_suggestion(no_crate_example, code = "...", applicability = "machine-applicable")]
LL | |
LL | |
LL | | struct BBa {
@@ -334,19 +334,19 @@ LL | | }
| |_^
error: `#[suggestion_part(...)]` attribute without `code = "..."`
- --> $DIR/subdiagnostic-derive.rs:546:5
+ --> $DIR/subdiagnostic-derive.rs:548:5
|
LL | #[suggestion_part]
| ^^^^^^^^^^^^^^^^^^
error: `#[suggestion_part(...)]` attribute without `code = "..."`
- --> $DIR/subdiagnostic-derive.rs:554:5
+ --> $DIR/subdiagnostic-derive.rs:556:5
|
LL | #[suggestion_part()]
| ^^^^^^^^^^^^^^^^^^^^
error: `#[primary_span]` is not a valid attribute
- --> $DIR/subdiagnostic-derive.rs:563:5
+ --> $DIR/subdiagnostic-derive.rs:565:5
|
LL | #[primary_span]
| ^^^^^^^^^^^^^^^
@@ -354,9 +354,9 @@ LL | #[primary_span]
= help: multipart suggestions use one or more `#[suggestion_part]`s rather than one `#[primary_span]`
error: multipart suggestion without any `#[suggestion_part(...)]` fields
- --> $DIR/subdiagnostic-derive.rs:560:1
+ --> $DIR/subdiagnostic-derive.rs:562:1
|
-LL | / #[multipart_suggestion(parse_add_paren)]
+LL | / #[multipart_suggestion(no_crate_example)]
LL | |
LL | | struct BC {
LL | | #[primary_span]
@@ -366,19 +366,19 @@ LL | | }
| |_^
error: `#[suggestion_part(...)]` attribute without `code = "..."`
- --> $DIR/subdiagnostic-derive.rs:571:5
+ --> $DIR/subdiagnostic-derive.rs:573:5
|
LL | #[suggestion_part]
| ^^^^^^^^^^^^^^^^^^
error: `#[suggestion_part(...)]` attribute without `code = "..."`
- --> $DIR/subdiagnostic-derive.rs:574:5
+ --> $DIR/subdiagnostic-derive.rs:576:5
|
LL | #[suggestion_part()]
| ^^^^^^^^^^^^^^^^^^^^
error: `#[suggestion_part(foo = ...)]` is not a valid attribute
- --> $DIR/subdiagnostic-derive.rs:577:23
+ --> $DIR/subdiagnostic-derive.rs:579:23
|
LL | #[suggestion_part(foo = "bar")]
| ^^^^^^^^^^^
@@ -386,181 +386,202 @@ LL | #[suggestion_part(foo = "bar")]
= help: `code` is the only valid nested attribute
error: the `#[suggestion_part(...)]` attribute can only be applied to fields of type `Span` or `MultiSpan`
- --> $DIR/subdiagnostic-derive.rs:580:5
+ --> $DIR/subdiagnostic-derive.rs:582:5
|
LL | #[suggestion_part(code = "...")]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: the `#[suggestion_part(...)]` attribute can only be applied to fields of type `Span` or `MultiSpan`
- --> $DIR/subdiagnostic-derive.rs:583:5
+ --> $DIR/subdiagnostic-derive.rs:585:5
|
LL | #[suggestion_part()]
| ^^^^^^^^^^^^^^^^^^^^
error: specified multiple times
- --> $DIR/subdiagnostic-derive.rs:591:37
+ --> $DIR/subdiagnostic-derive.rs:593:37
|
LL | #[suggestion_part(code = "...", code = ",,,")]
| ^^^^^^^^^^^^
|
note: previously specified here
- --> $DIR/subdiagnostic-derive.rs:591:23
+ --> $DIR/subdiagnostic-derive.rs:593:23
|
LL | #[suggestion_part(code = "...", code = ",,,")]
| ^^^^^^^^^^^^
error: `#[applicability]` has no effect if all `#[suggestion]`/`#[multipart_suggestion]` attributes have a static `applicability = "..."`
- --> $DIR/subdiagnostic-derive.rs:620:5
+ --> $DIR/subdiagnostic-derive.rs:622:5
|
LL | #[applicability]
| ^^^^^^^^^^^^^^^^
error: expected exactly one string literal for `code = ...`
- --> $DIR/subdiagnostic-derive.rs:668:23
+ --> $DIR/subdiagnostic-derive.rs:670:23
|
LL | #[suggestion_part(code("foo"))]
| ^^^^^^^^^^^
error: expected exactly one string literal for `code = ...`
- --> $DIR/subdiagnostic-derive.rs:677:23
+ --> $DIR/subdiagnostic-derive.rs:679:23
|
LL | #[suggestion_part(code("foo", "bar"))]
| ^^^^^^^^^^^^^^^^^^
error: expected exactly one string literal for `code = ...`
- --> $DIR/subdiagnostic-derive.rs:686:23
+ --> $DIR/subdiagnostic-derive.rs:688:23
|
LL | #[suggestion_part(code(3))]
| ^^^^^^^
error: expected exactly one string literal for `code = ...`
- --> $DIR/subdiagnostic-derive.rs:695:23
+ --> $DIR/subdiagnostic-derive.rs:697:23
|
LL | #[suggestion_part(code())]
| ^^^^^^
error: `code = "..."`/`code(...)` must contain only string literals
- --> $DIR/subdiagnostic-derive.rs:704:23
+ --> $DIR/subdiagnostic-derive.rs:706:23
|
LL | #[suggestion_part(code = 3)]
| ^^^^^^^^
error: specified multiple times
- --> $DIR/subdiagnostic-derive.rs:746:60
+ --> $DIR/subdiagnostic-derive.rs:748:61
|
-LL | #[suggestion(parse_add_paren, code = "", style = "hidden", style = "normal")]
- | ^^^^^^^^^^^^^^^^
+LL | #[suggestion(no_crate_example, code = "", style = "hidden", style = "normal")]
+ | ^^^^^^^^^^^^^^^^
|
note: previously specified here
- --> $DIR/subdiagnostic-derive.rs:746:42
+ --> $DIR/subdiagnostic-derive.rs:748:43
|
-LL | #[suggestion(parse_add_paren, code = "", style = "hidden", style = "normal")]
- | ^^^^^^^^^^^^^^^^
+LL | #[suggestion(no_crate_example, code = "", style = "hidden", style = "normal")]
+ | ^^^^^^^^^^^^^^^^
error: `#[suggestion_hidden(...)]` is not a valid attribute
- --> $DIR/subdiagnostic-derive.rs:755:1
+ --> $DIR/subdiagnostic-derive.rs:757:1
|
-LL | #[suggestion_hidden(parse_add_paren, code = "")]
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | #[suggestion_hidden(no_crate_example, code = "")]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= help: Use `#[suggestion(..., style = "hidden")]` instead
error: `#[suggestion_hidden(...)]` is not a valid attribute
- --> $DIR/subdiagnostic-derive.rs:763:1
+ --> $DIR/subdiagnostic-derive.rs:765:1
|
-LL | #[suggestion_hidden(parse_add_paren, code = "", style = "normal")]
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | #[suggestion_hidden(no_crate_example, code = "", style = "normal")]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= help: Use `#[suggestion(..., style = "hidden")]` instead
error: invalid suggestion style
- --> $DIR/subdiagnostic-derive.rs:771:50
+ --> $DIR/subdiagnostic-derive.rs:773:51
|
-LL | #[suggestion(parse_add_paren, code = "", style = "foo")]
- | ^^^^^
+LL | #[suggestion(no_crate_example, code = "", style = "foo")]
+ | ^^^^^
|
= help: valid styles are `normal`, `short`, `hidden`, `verbose` and `tool-only`
error: `#[suggestion(style = ...)]` is not a valid attribute
- --> $DIR/subdiagnostic-derive.rs:779:42
+ --> $DIR/subdiagnostic-derive.rs:781:43
|
-LL | #[suggestion(parse_add_paren, code = "", style = 42)]
- | ^^^^^^^^^^
+LL | #[suggestion(no_crate_example, code = "", style = 42)]
+ | ^^^^^^^^^^
error: `#[suggestion(style)]` is not a valid attribute
- --> $DIR/subdiagnostic-derive.rs:787:42
+ --> $DIR/subdiagnostic-derive.rs:789:43
|
-LL | #[suggestion(parse_add_paren, code = "", style)]
- | ^^^^^
+LL | #[suggestion(no_crate_example, code = "", style)]
+ | ^^^^^
|
= help: a diagnostic slug must be the first argument to the attribute
error: `#[suggestion(style(...))]` is not a valid attribute
- --> $DIR/subdiagnostic-derive.rs:795:42
+ --> $DIR/subdiagnostic-derive.rs:797:43
|
-LL | #[suggestion(parse_add_paren, code = "", style("foo"))]
- | ^^^^^^^^^^^^
+LL | #[suggestion(no_crate_example, code = "", style("foo"))]
+ | ^^^^^^^^^^^^
+
+error: `#[primary_span]` is not a valid attribute
+ --> $DIR/subdiagnostic-derive.rs:808:5
+ |
+LL | #[primary_span]
+ | ^^^^^^^^^^^^^^^
+ |
+ = note: there must be exactly one primary span
+ = help: to create a suggestion with multiple spans, use `#[multipart_suggestion]` instead
+
+error: suggestion without `#[primary_span]` field
+ --> $DIR/subdiagnostic-derive.rs:805:1
+ |
+LL | / #[suggestion(no_crate_example, code = "")]
+LL | |
+LL | | struct PrimarySpanOnVec {
+LL | | #[primary_span]
+... |
+LL | | sub: Vec<Span>,
+LL | | }
+ | |_^
error: cannot find attribute `foo` in this scope
- --> $DIR/subdiagnostic-derive.rs:63:3
+ --> $DIR/subdiagnostic-derive.rs:65:3
|
LL | #[foo]
| ^^^
error: cannot find attribute `foo` in this scope
- --> $DIR/subdiagnostic-derive.rs:159:3
+ --> $DIR/subdiagnostic-derive.rs:161:3
|
LL | #[foo]
| ^^^
error: cannot find attribute `bar` in this scope
- --> $DIR/subdiagnostic-derive.rs:173:7
+ --> $DIR/subdiagnostic-derive.rs:175:7
|
LL | #[bar]
| ^^^
error: cannot find attribute `bar` in this scope
- --> $DIR/subdiagnostic-derive.rs:185:7
+ --> $DIR/subdiagnostic-derive.rs:187:7
|
LL | #[bar = "..."]
| ^^^
error: cannot find attribute `bar` in this scope
- --> $DIR/subdiagnostic-derive.rs:197:7
+ --> $DIR/subdiagnostic-derive.rs:199:7
|
LL | #[bar = 4]
| ^^^
error: cannot find attribute `bar` in this scope
- --> $DIR/subdiagnostic-derive.rs:209:7
+ --> $DIR/subdiagnostic-derive.rs:211:7
|
LL | #[bar("...")]
| ^^^
error: cannot find attribute `bar` in this scope
- --> $DIR/subdiagnostic-derive.rs:270:7
+ --> $DIR/subdiagnostic-derive.rs:272:7
|
LL | #[bar]
| ^^^
error: cannot find attribute `bar` in this scope
- --> $DIR/subdiagnostic-derive.rs:281:7
+ --> $DIR/subdiagnostic-derive.rs:283:7
|
LL | #[bar = "..."]
| ^^^
error: cannot find attribute `bar` in this scope
- --> $DIR/subdiagnostic-derive.rs:292:7
+ --> $DIR/subdiagnostic-derive.rs:294:7
|
LL | #[bar("...")]
| ^^^
-error[E0425]: cannot find value `slug` in module `rustc_errors::fluent`
- --> $DIR/subdiagnostic-derive.rs:122:9
+error[E0425]: cannot find value `slug` in module `crate::fluent_generated`
+ --> $DIR/subdiagnostic-derive.rs:124:9
|
LL | #[label(slug)]
- | ^^^^ not found in `rustc_errors::fluent`
+ | ^^^^ not found in `crate::fluent_generated`
-error: aborting due to 79 previous errors
+error: aborting due to 81 previous errors
For more information about this error, try `rustc --explain E0425`.
diff --git a/tests/ui-fulldeps/issue-15149.rs b/tests/ui-fulldeps/std/issue-15149.rs
index 064472f57..064472f57 100644
--- a/tests/ui-fulldeps/issue-15149.rs
+++ b/tests/ui-fulldeps/std/issue-15149.rs
diff --git a/tests/ui-fulldeps/issue-81357-unsound-file-methods.rs b/tests/ui-fulldeps/std/issue-81357-unsound-file-methods.rs
index fdf1150f8..fdf1150f8 100644
--- a/tests/ui-fulldeps/issue-81357-unsound-file-methods.rs
+++ b/tests/ui-fulldeps/std/issue-81357-unsound-file-methods.rs
diff --git a/tests/ui-fulldeps/stdio-from.rs b/tests/ui-fulldeps/std/stdio-from.rs
index fef9f27fc..fef9f27fc 100644
--- a/tests/ui-fulldeps/stdio-from.rs
+++ b/tests/ui-fulldeps/std/stdio-from.rs
diff --git a/tests/ui-fulldeps/switch-stdout.rs b/tests/ui-fulldeps/std/switch-stdout.rs
index e9501a809..e9501a809 100644
--- a/tests/ui-fulldeps/switch-stdout.rs
+++ b/tests/ui-fulldeps/std/switch-stdout.rs
diff --git a/tests/ui/abi/stack-probes-lto.rs b/tests/ui/abi/stack-probes-lto.rs
index 6d934538f..a455eef42 100644
--- a/tests/ui/abi/stack-probes-lto.rs
+++ b/tests/ui/abi/stack-probes-lto.rs
@@ -13,5 +13,6 @@
// ignore-fuchsia no exception handler registered for segfault
// compile-flags: -C lto
// no-prefer-dynamic
+// ignore-nto Crash analysis impossible at SIGSEGV in QNX Neutrino
include!("stack-probes.rs");
diff --git a/tests/ui/abi/stack-probes.rs b/tests/ui/abi/stack-probes.rs
index e7b91644b..8dba54c3f 100644
--- a/tests/ui/abi/stack-probes.rs
+++ b/tests/ui/abi/stack-probes.rs
@@ -9,6 +9,7 @@
// ignore-emscripten no processes
// ignore-sgx no processes
// ignore-fuchsia no exception handler registered for segfault
+// ignore-nto Crash analysis impossible at SIGSEGV in QNX Neutrino
use std::env;
use std::mem::MaybeUninit;
diff --git a/tests/ui/alloc-error/alloc-error-handler-bad-signature-1.stderr b/tests/ui/alloc-error/alloc-error-handler-bad-signature-1.stderr
index 59192a1ec..de92841d7 100644
--- a/tests/ui/alloc-error/alloc-error-handler-bad-signature-1.stderr
+++ b/tests/ui/alloc-error/alloc-error-handler-bad-signature-1.stderr
@@ -10,7 +10,7 @@ LL | || ) -> ()
LL | | {
LL | | loop {}
LL | | }
- | |__^ expected `&Layout`, found struct `Layout`
+ | |__^ expected `&Layout`, found `Layout`
|
note: function defined here
--> $DIR/alloc-error-handler-bad-signature-1.rs:10:4
diff --git a/tests/ui/alloc-error/alloc-error-handler-bad-signature-2.stderr b/tests/ui/alloc-error/alloc-error-handler-bad-signature-2.stderr
index 7d23c2fc0..7a495380f 100644
--- a/tests/ui/alloc-error/alloc-error-handler-bad-signature-2.stderr
+++ b/tests/ui/alloc-error/alloc-error-handler-bad-signature-2.stderr
@@ -9,12 +9,12 @@ LL | || ) {
| ||_- arguments to this function are incorrect
LL | | loop {}
LL | | }
- | |__^ expected struct `Layout`, found struct `core::alloc::Layout`
+ | |__^ expected `Layout`, found `core::alloc::Layout`
|
- = note: struct `core::alloc::Layout` and struct `Layout` have similar names, but are actually distinct types
-note: struct `core::alloc::Layout` is defined in crate `core`
+ = note: `core::alloc::Layout` and `Layout` have similar names, but are actually distinct types
+note: `core::alloc::Layout` is defined in crate `core`
--> $SRC_DIR/core/src/alloc/layout.rs:LL:COL
-note: struct `Layout` is defined in the current crate
+note: `Layout` is defined in the current crate
--> $DIR/alloc-error-handler-bad-signature-2.rs:7:1
|
LL | struct Layout;
diff --git a/tests/ui/alloc-error/alloc-error-handler-bad-signature-3.stderr b/tests/ui/alloc-error/alloc-error-handler-bad-signature-3.stderr
index 77ea8ef05..eb739b149 100644
--- a/tests/ui/alloc-error/alloc-error-handler-bad-signature-3.stderr
+++ b/tests/ui/alloc-error/alloc-error-handler-bad-signature-3.stderr
@@ -7,7 +7,7 @@ LL | fn oom() -> ! {
| _-^^^^^^^^^^^^
LL | | loop {}
LL | | }
- | |_- argument of type `core::alloc::Layout` unexpected
+ | |_- unexpected argument of type `core::alloc::Layout`
|
note: function defined here
--> $DIR/alloc-error-handler-bad-signature-3.rs:10:4
@@ -15,10 +15,6 @@ note: function defined here
LL | fn oom() -> ! {
| ^^^
= note: this error originates in the attribute macro `alloc_error_handler` (in Nightly builds, run with -Z macro-backtrace for more info)
-help: remove the extra argument
- |
-LL | fn oom() -> !() {
- | ++
error: aborting due to previous error
diff --git a/tests/ui/argument-suggestions/basic.stderr b/tests/ui/argument-suggestions/basic.stderr
index 062b37688..c74186285 100644
--- a/tests/ui/argument-suggestions/basic.stderr
+++ b/tests/ui/argument-suggestions/basic.stderr
@@ -16,17 +16,16 @@ error[E0061]: this function takes 0 arguments but 1 argument was supplied
--> $DIR/basic.rs:21:5
|
LL | extra("");
- | ^^^^^ -- argument of type `&'static str` unexpected
+ | ^^^^^ --
+ | |
+ | unexpected argument of type `&'static str`
+ | help: remove the extra argument
|
note: function defined here
--> $DIR/basic.rs:14:4
|
LL | fn extra() {}
| ^^^^^
-help: remove the extra argument
- |
-LL | extra();
- | ~~
error[E0061]: this function takes 1 argument but 0 arguments were supplied
--> $DIR/basic.rs:22:5
diff --git a/tests/ui/argument-suggestions/exotic-calls.stderr b/tests/ui/argument-suggestions/exotic-calls.stderr
index 0580e53c5..ff795b507 100644
--- a/tests/ui/argument-suggestions/exotic-calls.stderr
+++ b/tests/ui/argument-suggestions/exotic-calls.stderr
@@ -2,65 +2,61 @@ error[E0057]: this function takes 0 arguments but 1 argument was supplied
--> $DIR/exotic-calls.rs:2:5
|
LL | t(1i32);
- | ^ ---- argument of type `i32` unexpected
+ | ^ ----
+ | |
+ | unexpected argument of type `i32`
+ | help: remove the extra argument
|
note: callable defined here
--> $DIR/exotic-calls.rs:1:11
|
LL | fn foo<T: Fn()>(t: T) {
| ^^^^
-help: remove the extra argument
- |
-LL | t();
- | ~~
error[E0057]: this function takes 0 arguments but 1 argument was supplied
--> $DIR/exotic-calls.rs:7:5
|
LL | t(1i32);
- | ^ ---- argument of type `i32` unexpected
+ | ^ ----
+ | |
+ | unexpected argument of type `i32`
+ | help: remove the extra argument
|
note: type parameter defined here
--> $DIR/exotic-calls.rs:6:11
|
LL | fn bar(t: impl Fn()) {
| ^^^^^^^^^
-help: remove the extra argument
- |
-LL | t();
- | ~~
error[E0057]: this function takes 0 arguments but 1 argument was supplied
--> $DIR/exotic-calls.rs:16:5
|
LL | baz()(1i32)
- | ^^^^^ ---- argument of type `i32` unexpected
+ | ^^^^^ ----
+ | |
+ | unexpected argument of type `i32`
+ | help: remove the extra argument
|
note: opaque type defined here
--> $DIR/exotic-calls.rs:11:13
|
LL | fn baz() -> impl Fn() {
| ^^^^^^^^^
-help: remove the extra argument
- |
-LL | baz()()
- | ~~
error[E0057]: this function takes 0 arguments but 1 argument was supplied
--> $DIR/exotic-calls.rs:22:5
|
LL | x(1i32);
- | ^ ---- argument of type `i32` unexpected
+ | ^ ----
+ | |
+ | unexpected argument of type `i32`
+ | help: remove the extra argument
|
note: closure defined here
--> $DIR/exotic-calls.rs:21:13
|
LL | let x = || {};
| ^^
-help: remove the extra argument
- |
-LL | x();
- | ~~
error: aborting due to 4 previous errors
diff --git a/tests/ui/argument-suggestions/extra_arguments.rs b/tests/ui/argument-suggestions/extra_arguments.rs
index 3f83de95e..144206232 100644
--- a/tests/ui/argument-suggestions/extra_arguments.rs
+++ b/tests/ui/argument-suggestions/extra_arguments.rs
@@ -3,8 +3,15 @@ fn one_arg(_a: i32) {}
fn two_arg_same(_a: i32, _b: i32) {}
fn two_arg_diff(_a: i32, _b: &str) {}
+macro_rules! foo {
+ ($x:expr) => {
+ empty($x, 1); //~ ERROR function takes
+ }
+}
+
fn main() {
empty(""); //~ ERROR function takes
+ empty(1, 1); //~ ERROR function takes
one_arg(1, 1); //~ ERROR function takes
one_arg(1, ""); //~ ERROR function takes
@@ -32,4 +39,5 @@ fn main() {
1,
""
);
+ foo!(1);
}
diff --git a/tests/ui/argument-suggestions/extra_arguments.stderr b/tests/ui/argument-suggestions/extra_arguments.stderr
index 48787b0c3..11c710997 100644
--- a/tests/ui/argument-suggestions/extra_arguments.stderr
+++ b/tests/ui/argument-suggestions/extra_arguments.stderr
@@ -1,58 +1,74 @@
error[E0061]: this function takes 0 arguments but 1 argument was supplied
- --> $DIR/extra_arguments.rs:7:3
+ --> $DIR/extra_arguments.rs:13:3
|
LL | empty("");
- | ^^^^^ -- argument of type `&'static str` unexpected
+ | ^^^^^ --
+ | |
+ | unexpected argument of type `&'static str`
+ | help: remove the extra argument
|
note: function defined here
--> $DIR/extra_arguments.rs:1:4
|
LL | fn empty() {}
| ^^^^^
-help: remove the extra argument
+
+error[E0061]: this function takes 0 arguments but 2 arguments were supplied
+ --> $DIR/extra_arguments.rs:14:3
+ |
+LL | empty(1, 1);
+ | ^^^^^ - - unexpected argument of type `{integer}`
+ | |
+ | unexpected argument of type `{integer}`
+ |
+note: function defined here
+ --> $DIR/extra_arguments.rs:1:4
+ |
+LL | fn empty() {}
+ | ^^^^^
+help: remove the extra arguments
+ |
+LL - empty(1, 1);
+LL + empty();
|
-LL | empty();
- | ~~
error[E0061]: this function takes 1 argument but 2 arguments were supplied
- --> $DIR/extra_arguments.rs:9:3
+ --> $DIR/extra_arguments.rs:16:3
|
LL | one_arg(1, 1);
- | ^^^^^^^ - argument of type `{integer}` unexpected
+ | ^^^^^^^ ---
+ | | |
+ | | unexpected argument of type `{integer}`
+ | help: remove the extra argument
|
note: function defined here
--> $DIR/extra_arguments.rs:2:4
|
LL | fn one_arg(_a: i32) {}
| ^^^^^^^ -------
-help: remove the extra argument
- |
-LL | one_arg(1);
- | ~~~
error[E0061]: this function takes 1 argument but 2 arguments were supplied
- --> $DIR/extra_arguments.rs:10:3
+ --> $DIR/extra_arguments.rs:17:3
|
LL | one_arg(1, "");
- | ^^^^^^^ -- argument of type `&'static str` unexpected
+ | ^^^^^^^ ----
+ | | |
+ | | unexpected argument of type `&'static str`
+ | help: remove the extra argument
|
note: function defined here
--> $DIR/extra_arguments.rs:2:4
|
LL | fn one_arg(_a: i32) {}
| ^^^^^^^ -------
-help: remove the extra argument
- |
-LL | one_arg(1);
- | ~~~
error[E0061]: this function takes 1 argument but 3 arguments were supplied
- --> $DIR/extra_arguments.rs:11:3
+ --> $DIR/extra_arguments.rs:18:3
|
LL | one_arg(1, "", 1.0);
- | ^^^^^^^ -- --- argument of type `{float}` unexpected
+ | ^^^^^^^ -- --- unexpected argument of type `{float}`
| |
- | argument of type `&'static str` unexpected
+ | unexpected argument of type `&'static str`
|
note: function defined here
--> $DIR/extra_arguments.rs:2:4
@@ -61,80 +77,77 @@ LL | fn one_arg(_a: i32) {}
| ^^^^^^^ -------
help: remove the extra arguments
|
-LL | one_arg(1);
- | ~~~
+LL - one_arg(1, "", 1.0);
+LL + one_arg(1);
+ |
error[E0061]: this function takes 2 arguments but 3 arguments were supplied
- --> $DIR/extra_arguments.rs:13:3
+ --> $DIR/extra_arguments.rs:20:3
|
LL | two_arg_same(1, 1, 1);
- | ^^^^^^^^^^^^ - argument of type `{integer}` unexpected
+ | ^^^^^^^^^^^^ ---
+ | | |
+ | | unexpected argument of type `{integer}`
+ | help: remove the extra argument
|
note: function defined here
--> $DIR/extra_arguments.rs:3:4
|
LL | fn two_arg_same(_a: i32, _b: i32) {}
| ^^^^^^^^^^^^ ------- -------
-help: remove the extra argument
- |
-LL | two_arg_same(1, 1);
- | ~~~~~~
error[E0061]: this function takes 2 arguments but 3 arguments were supplied
- --> $DIR/extra_arguments.rs:14:3
+ --> $DIR/extra_arguments.rs:21:3
|
LL | two_arg_same(1, 1, 1.0);
- | ^^^^^^^^^^^^ --- argument of type `{float}` unexpected
+ | ^^^^^^^^^^^^ -----
+ | | |
+ | | unexpected argument of type `{float}`
+ | help: remove the extra argument
|
note: function defined here
--> $DIR/extra_arguments.rs:3:4
|
LL | fn two_arg_same(_a: i32, _b: i32) {}
| ^^^^^^^^^^^^ ------- -------
-help: remove the extra argument
- |
-LL | two_arg_same(1, 1);
- | ~~~~~~
error[E0061]: this function takes 2 arguments but 3 arguments were supplied
- --> $DIR/extra_arguments.rs:16:3
+ --> $DIR/extra_arguments.rs:23:3
|
LL | two_arg_diff(1, 1, "");
- | ^^^^^^^^^^^^ - argument of type `{integer}` unexpected
+ | ^^^^^^^^^^^^ ---
+ | | |
+ | | unexpected argument of type `{integer}`
+ | help: remove the extra argument
|
note: function defined here
--> $DIR/extra_arguments.rs:4:4
|
LL | fn two_arg_diff(_a: i32, _b: &str) {}
| ^^^^^^^^^^^^ ------- --------
-help: remove the extra argument
- |
-LL | two_arg_diff(1, "");
- | ~~~~~~~
error[E0061]: this function takes 2 arguments but 3 arguments were supplied
- --> $DIR/extra_arguments.rs:17:3
+ --> $DIR/extra_arguments.rs:24:3
|
LL | two_arg_diff(1, "", "");
- | ^^^^^^^^^^^^ -- argument of type `&'static str` unexpected
+ | ^^^^^^^^^^^^ ----
+ | | |
+ | | unexpected argument of type `&'static str`
+ | help: remove the extra argument
|
note: function defined here
--> $DIR/extra_arguments.rs:4:4
|
LL | fn two_arg_diff(_a: i32, _b: &str) {}
| ^^^^^^^^^^^^ ------- --------
-help: remove the extra argument
- |
-LL | two_arg_diff(1, "");
- | ~~~~~~~
error[E0061]: this function takes 2 arguments but 4 arguments were supplied
- --> $DIR/extra_arguments.rs:18:3
+ --> $DIR/extra_arguments.rs:25:3
|
LL | two_arg_diff(1, 1, "", "");
- | ^^^^^^^^^^^^ - -- argument of type `&'static str` unexpected
+ | ^^^^^^^^^^^^ - -- unexpected argument of type `&'static str`
| |
- | argument of type `{integer}` unexpected
+ | unexpected argument of type `{integer}`
|
note: function defined here
--> $DIR/extra_arguments.rs:4:4
@@ -143,16 +156,17 @@ LL | fn two_arg_diff(_a: i32, _b: &str) {}
| ^^^^^^^^^^^^ ------- --------
help: remove the extra arguments
|
-LL | two_arg_diff(1, "");
- | ~~~~~~~
+LL - two_arg_diff(1, 1, "", "");
+LL + two_arg_diff(1, "");
+ |
error[E0061]: this function takes 2 arguments but 4 arguments were supplied
- --> $DIR/extra_arguments.rs:19:3
+ --> $DIR/extra_arguments.rs:26:3
|
LL | two_arg_diff(1, "", 1, "");
- | ^^^^^^^^^^^^ - -- argument of type `&'static str` unexpected
+ | ^^^^^^^^^^^^ - -- unexpected argument of type `&'static str`
| |
- | argument of type `{integer}` unexpected
+ | unexpected argument of type `{integer}`
|
note: function defined here
--> $DIR/extra_arguments.rs:4:4
@@ -161,79 +175,99 @@ LL | fn two_arg_diff(_a: i32, _b: &str) {}
| ^^^^^^^^^^^^ ------- --------
help: remove the extra arguments
|
-LL | two_arg_diff(1, "");
- | ~~~~~~~
+LL - two_arg_diff(1, "", 1, "");
+LL + two_arg_diff(1, "");
+ |
error[E0061]: this function takes 2 arguments but 3 arguments were supplied
- --> $DIR/extra_arguments.rs:22:3
+ --> $DIR/extra_arguments.rs:29:3
|
LL | two_arg_same(1, 1, "");
- | ^^^^^^^^^^^^ -- argument of type `&'static str` unexpected
+ | ^^^^^^^^^^^^ --------
+ | | |
+ | | unexpected argument of type `&'static str`
+ | help: remove the extra argument
|
note: function defined here
--> $DIR/extra_arguments.rs:3:4
|
LL | fn two_arg_same(_a: i32, _b: i32) {}
| ^^^^^^^^^^^^ ------- -------
-help: remove the extra argument
- |
-LL | two_arg_same(1, 1);
- | ~~~~~~
error[E0061]: this function takes 2 arguments but 3 arguments were supplied
- --> $DIR/extra_arguments.rs:23:3
+ --> $DIR/extra_arguments.rs:30:3
|
LL | two_arg_diff(1, 1, "");
- | ^^^^^^^^^^^^ - argument of type `{integer}` unexpected
+ | ^^^^^^^^^^^^ ---
+ | | |
+ | | unexpected argument of type `{integer}`
+ | help: remove the extra argument
|
note: function defined here
--> $DIR/extra_arguments.rs:4:4
|
LL | fn two_arg_diff(_a: i32, _b: &str) {}
| ^^^^^^^^^^^^ ------- --------
-help: remove the extra argument
- |
-LL | two_arg_diff(1, "");
- | ~~~~~~~
error[E0061]: this function takes 2 arguments but 3 arguments were supplied
- --> $DIR/extra_arguments.rs:24:3
- |
-LL | two_arg_same(
- | ^^^^^^^^^^^^
-...
-LL | ""
- | -- argument of type `&'static str` unexpected
+ --> $DIR/extra_arguments.rs:31:3
+ |
+LL | two_arg_same(
+ | ^^^^^^^^^^^^
+LL | 1,
+LL | 1,
+ | ______-
+LL | | ""
+ | | --
+ | |_____||
+ | |help: remove the extra argument
+ | unexpected argument of type `&'static str`
|
note: function defined here
--> $DIR/extra_arguments.rs:3:4
|
LL | fn two_arg_same(_a: i32, _b: i32) {}
| ^^^^^^^^^^^^ ------- -------
-help: remove the extra argument
- |
-LL | two_arg_same(1, 1);
- | ~~~~~~
error[E0061]: this function takes 2 arguments but 3 arguments were supplied
- --> $DIR/extra_arguments.rs:30:3
- |
-LL | two_arg_diff(
- | ^^^^^^^^^^^^
-LL | 1,
-LL | 1,
- | - argument of type `{integer}` unexpected
+ --> $DIR/extra_arguments.rs:37:3
+ |
+LL | two_arg_diff(
+ | ^^^^^^^^^^^^
+LL | 1,
+ | ______-
+LL | | 1,
+ | | -
+ | | |
+ | |_____unexpected argument of type `{integer}`
+ | help: remove the extra argument
|
note: function defined here
--> $DIR/extra_arguments.rs:4:4
|
LL | fn two_arg_diff(_a: i32, _b: &str) {}
| ^^^^^^^^^^^^ ------- --------
-help: remove the extra argument
+
+error[E0061]: this function takes 0 arguments but 2 arguments were supplied
+ --> $DIR/extra_arguments.rs:8:9
+ |
+LL | empty($x, 1);
+ | ^^^^^ - unexpected argument of type `{integer}`
+...
+LL | foo!(1);
+ | -------
+ | | |
+ | | unexpected argument of type `{integer}`
+ | | help: remove the extra argument
+ | in this macro invocation
+ |
+note: function defined here
+ --> $DIR/extra_arguments.rs:1:4
|
-LL | two_arg_diff(1, "");
- | ~~~~~~~
+LL | fn empty() {}
+ | ^^^^^
+ = note: this error originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info)
-error: aborting due to 14 previous errors
+error: aborting due to 16 previous errors
For more information about this error, try `rustc --explain E0061`.
diff --git a/tests/ui/argument-suggestions/formal-and-expected-differ.stderr b/tests/ui/argument-suggestions/formal-and-expected-differ.stderr
index 905875b52..6076b7ccb 100644
--- a/tests/ui/argument-suggestions/formal-and-expected-differ.stderr
+++ b/tests/ui/argument-suggestions/formal-and-expected-differ.stderr
@@ -2,7 +2,7 @@ error[E0308]: mismatched types
--> $DIR/formal-and-expected-differ.rs:22:29
|
LL | let _: U<_, u32> = U(1, S(3u32));
- | - ^^^^^^^ expected `f32`, found `u32`
+ | - ^^^^^^^ expected `S<f32>`, found `S<u32>`
| |
| arguments to this struct are incorrect
|
@@ -18,7 +18,7 @@ error[E0308]: mismatched types
--> $DIR/formal-and-expected-differ.rs:22:24
|
LL | let _: U<_, u32> = U(1, S(3u32));
- | --------- ^^^^^^^^^^^^^ expected `u32`, found `f32`
+ | --------- ^^^^^^^^^^^^^ expected `U<_, u32>`, found `U<i32, f32>`
| |
| expected due to this
|
diff --git a/tests/ui/argument-suggestions/invalid_arguments.stderr b/tests/ui/argument-suggestions/invalid_arguments.stderr
index 303f08695..d26f33d09 100644
--- a/tests/ui/argument-suggestions/invalid_arguments.stderr
+++ b/tests/ui/argument-suggestions/invalid_arguments.stderr
@@ -100,7 +100,7 @@ error[E0308]: mismatched types
--> $DIR/invalid_arguments.rs:24:18
|
LL | three_arg_diff(X{}, 1.0, "");
- | -------------- ^^^ expected `i32`, found struct `X`
+ | -------------- ^^^ expected `i32`, found `X`
| |
| arguments to this function are incorrect
|
@@ -114,7 +114,7 @@ error[E0308]: mismatched types
--> $DIR/invalid_arguments.rs:25:21
|
LL | three_arg_diff(1, X {}, "");
- | -------------- ^^^^ expected `f32`, found struct `X`
+ | -------------- ^^^^ expected `f32`, found `X`
| |
| arguments to this function are incorrect
|
@@ -128,7 +128,7 @@ error[E0308]: mismatched types
--> $DIR/invalid_arguments.rs:26:26
|
LL | three_arg_diff(1, 1.0, X {});
- | -------------- ^^^^ expected `&str`, found struct `X`
+ | -------------- ^^^^ expected `&str`, found `X`
| |
| arguments to this function are incorrect
|
@@ -142,9 +142,9 @@ error[E0308]: arguments to this function are incorrect
--> $DIR/invalid_arguments.rs:28:3
|
LL | three_arg_diff(X {}, X {}, "");
- | ^^^^^^^^^^^^^^ ---- ---- expected `f32`, found struct `X`
+ | ^^^^^^^^^^^^^^ ---- ---- expected `f32`, found `X`
| |
- | expected `i32`, found struct `X`
+ | expected `i32`, found `X`
|
note: function defined here
--> $DIR/invalid_arguments.rs:8:4
@@ -156,9 +156,9 @@ error[E0308]: arguments to this function are incorrect
--> $DIR/invalid_arguments.rs:29:3
|
LL | three_arg_diff(X {}, 1.0, X {});
- | ^^^^^^^^^^^^^^ ---- ---- expected `&str`, found struct `X`
+ | ^^^^^^^^^^^^^^ ---- ---- expected `&str`, found `X`
| |
- | expected `i32`, found struct `X`
+ | expected `i32`, found `X`
|
note: function defined here
--> $DIR/invalid_arguments.rs:8:4
@@ -170,9 +170,9 @@ error[E0308]: arguments to this function are incorrect
--> $DIR/invalid_arguments.rs:30:3
|
LL | three_arg_diff(1, X {}, X {});
- | ^^^^^^^^^^^^^^ ---- ---- expected `&str`, found struct `X`
+ | ^^^^^^^^^^^^^^ ---- ---- expected `&str`, found `X`
| |
- | expected `f32`, found struct `X`
+ | expected `f32`, found `X`
|
note: function defined here
--> $DIR/invalid_arguments.rs:8:4
@@ -184,10 +184,10 @@ error[E0308]: arguments to this function are incorrect
--> $DIR/invalid_arguments.rs:32:3
|
LL | three_arg_diff(X {}, X {}, X {});
- | ^^^^^^^^^^^^^^ ---- ---- ---- expected `&str`, found struct `X`
+ | ^^^^^^^^^^^^^^ ---- ---- ---- expected `&str`, found `X`
| | |
- | | expected `f32`, found struct `X`
- | expected `i32`, found struct `X`
+ | | expected `f32`, found `X`
+ | expected `i32`, found `X`
|
note: function defined here
--> $DIR/invalid_arguments.rs:8:4
@@ -199,7 +199,7 @@ error[E0308]: mismatched types
--> $DIR/invalid_arguments.rs:34:20
|
LL | three_arg_repeat(X {}, 1, "");
- | ---------------- ^^^^ expected `i32`, found struct `X`
+ | ---------------- ^^^^ expected `i32`, found `X`
| |
| arguments to this function are incorrect
|
@@ -213,7 +213,7 @@ error[E0308]: mismatched types
--> $DIR/invalid_arguments.rs:35:23
|
LL | three_arg_repeat(1, X {}, "");
- | ---------------- ^^^^ expected `i32`, found struct `X`
+ | ---------------- ^^^^ expected `i32`, found `X`
| |
| arguments to this function are incorrect
|
@@ -227,7 +227,7 @@ error[E0308]: mismatched types
--> $DIR/invalid_arguments.rs:36:26
|
LL | three_arg_repeat(1, 1, X {});
- | ---------------- ^^^^ expected `&str`, found struct `X`
+ | ---------------- ^^^^ expected `&str`, found `X`
| |
| arguments to this function are incorrect
|
@@ -241,9 +241,9 @@ error[E0308]: arguments to this function are incorrect
--> $DIR/invalid_arguments.rs:38:3
|
LL | three_arg_repeat(X {}, X {}, "");
- | ^^^^^^^^^^^^^^^^ ---- ---- expected `i32`, found struct `X`
+ | ^^^^^^^^^^^^^^^^ ---- ---- expected `i32`, found `X`
| |
- | expected `i32`, found struct `X`
+ | expected `i32`, found `X`
|
note: function defined here
--> $DIR/invalid_arguments.rs:9:4
@@ -255,9 +255,9 @@ error[E0308]: arguments to this function are incorrect
--> $DIR/invalid_arguments.rs:39:3
|
LL | three_arg_repeat(X {}, 1, X {});
- | ^^^^^^^^^^^^^^^^ ---- ---- expected `&str`, found struct `X`
+ | ^^^^^^^^^^^^^^^^ ---- ---- expected `&str`, found `X`
| |
- | expected `i32`, found struct `X`
+ | expected `i32`, found `X`
|
note: function defined here
--> $DIR/invalid_arguments.rs:9:4
@@ -269,9 +269,9 @@ error[E0308]: arguments to this function are incorrect
--> $DIR/invalid_arguments.rs:40:3
|
LL | three_arg_repeat(1, X {}, X{});
- | ^^^^^^^^^^^^^^^^ ---- --- expected `&str`, found struct `X`
+ | ^^^^^^^^^^^^^^^^ ---- --- expected `&str`, found `X`
| |
- | expected `i32`, found struct `X`
+ | expected `i32`, found `X`
|
note: function defined here
--> $DIR/invalid_arguments.rs:9:4
@@ -283,10 +283,10 @@ error[E0308]: arguments to this function are incorrect
--> $DIR/invalid_arguments.rs:42:3
|
LL | three_arg_repeat(X {}, X {}, X {});
- | ^^^^^^^^^^^^^^^^ ---- ---- ---- expected `&str`, found struct `X`
+ | ^^^^^^^^^^^^^^^^ ---- ---- ---- expected `&str`, found `X`
| | |
- | | expected `i32`, found struct `X`
- | expected `i32`, found struct `X`
+ | | expected `i32`, found `X`
+ | expected `i32`, found `X`
|
note: function defined here
--> $DIR/invalid_arguments.rs:9:4
diff --git a/tests/ui/argument-suggestions/issue-100154.stderr b/tests/ui/argument-suggestions/issue-100154.stderr
index 1499229c3..2504f616f 100644
--- a/tests/ui/argument-suggestions/issue-100154.stderr
+++ b/tests/ui/argument-suggestions/issue-100154.stderr
@@ -1,4 +1,4 @@
-error[E0107]: this function takes 0 generic arguments but 1 generic argument was supplied
+error[E0107]: function takes 0 generic arguments but 1 generic argument was supplied
--> $DIR/issue-100154.rs:4:5
|
LL | foo::<()>(());
diff --git a/tests/ui/argument-suggestions/issue-100478.stderr b/tests/ui/argument-suggestions/issue-100478.stderr
index df02a312c..e4304988f 100644
--- a/tests/ui/argument-suggestions/issue-100478.stderr
+++ b/tests/ui/argument-suggestions/issue-100478.stderr
@@ -41,7 +41,7 @@ error[E0308]: arguments to this function are incorrect
--> $DIR/issue-100478.rs:36:5
|
LL | four_shuffle(T3::default(), T2::default(), T1::default(), T3::default());
- | ^^^^^^^^^^^^ ------------- ------------- ------------- expected struct `T4`, found struct `T3`
+ | ^^^^^^^^^^^^ ------------- ------------- ------------- expected `T4`, found `T3`
| | |
| | expected `T3`, found `T1`
| expected `T1`, found `T3`
diff --git a/tests/ui/argument-suggestions/issue-101097.stderr b/tests/ui/argument-suggestions/issue-101097.stderr
index 096f8c226..061f51014 100644
--- a/tests/ui/argument-suggestions/issue-101097.stderr
+++ b/tests/ui/argument-suggestions/issue-101097.stderr
@@ -4,7 +4,7 @@ error[E0061]: this function takes 6 arguments but 7 arguments were supplied
LL | f(C, A, A, A, B, B, C);
| ^ - - - - expected `C`, found `B`
| | | |
- | | | argument of type `A` unexpected
+ | | | unexpected argument of type `A`
| | expected `B`, found `A`
| expected `A`, found `C`
|
@@ -64,8 +64,8 @@ error[E0308]: arguments to this function are incorrect
LL | f(A, A, D, D, B, B);
| ^ - - ---- two arguments of type `C` and `C` are missing
| | |
- | | argument of type `D` unexpected
- | argument of type `D` unexpected
+ | | unexpected argument of type `D`
+ | unexpected argument of type `D`
|
note: function defined here
--> $DIR/issue-101097.rs:6:4
@@ -128,7 +128,7 @@ LL | f(C, C, A, B, A, A);
| ^ - - - - - expected `C`, found `A`
| | | | |
| | | | expected `C`, found `A`
- | | | expected struct `B`, found struct `A`
+ | | | expected `B`, found `A`
| | expected `A`, found `C`
| expected `A`, found `C`
|
diff --git a/tests/ui/argument-suggestions/issue-97484.stderr b/tests/ui/argument-suggestions/issue-97484.stderr
index caa50f14b..a86cbbf18 100644
--- a/tests/ui/argument-suggestions/issue-97484.stderr
+++ b/tests/ui/argument-suggestions/issue-97484.stderr
@@ -2,11 +2,11 @@ error[E0061]: this function takes 4 arguments but 7 arguments were supplied
--> $DIR/issue-97484.rs:12:5
|
LL | foo(&&A, B, C, D, E, F, G);
- | ^^^ - - - - argument of type `F` unexpected
+ | ^^^ - - - - unexpected argument of type `F`
| | | |
- | | | expected `&E`, found struct `E`
- | | argument of type `C` unexpected
- | argument of type `B` unexpected
+ | | | expected `&E`, found `E`
+ | | unexpected argument of type `C`
+ | unexpected argument of type `B`
|
note: function defined here
--> $DIR/issue-97484.rs:9:4
@@ -19,8 +19,9 @@ LL | foo(&&A, B, C, D, &E, F, G);
| ~~
help: remove the extra arguments
|
-LL | foo(&&A, D, /* &E */, G);
- | ~~~~~~~~~~~~~~~~~~~~~
+LL - foo(&&A, B, C, D, E, F, G);
+LL + foo(&&A, D, /* &E */, G);
+ |
error: aborting due to previous error
diff --git a/tests/ui/argument-suggestions/mixed_cases.stderr b/tests/ui/argument-suggestions/mixed_cases.stderr
index 8c525db1a..c645dd381 100644
--- a/tests/ui/argument-suggestions/mixed_cases.stderr
+++ b/tests/ui/argument-suggestions/mixed_cases.stderr
@@ -2,7 +2,7 @@ error[E0061]: this function takes 2 arguments but 3 arguments were supplied
--> $DIR/mixed_cases.rs:10:3
|
LL | two_args(1, "", X {});
- | ^^^^^^^^ -- ---- argument of type `X` unexpected
+ | ^^^^^^^^ -- ---- unexpected argument of type `X`
| |
| expected `f32`, found `&str`
|
@@ -13,16 +13,17 @@ LL | fn two_args(_a: i32, _b: f32) {}
| ^^^^^^^^ ------- -------
help: remove the extra argument
|
-LL | two_args(1, /* f32 */);
- | ~~~~~~~~~~~~~~
+LL - two_args(1, "", X {});
+LL + two_args(1, /* f32 */);
+ |
error[E0061]: this function takes 3 arguments but 4 arguments were supplied
--> $DIR/mixed_cases.rs:11:3
|
LL | three_args(1, "", X {}, "");
- | ^^^^^^^^^^ -- ---- -- argument of type `&'static str` unexpected
+ | ^^^^^^^^^^ -- ---- -- unexpected argument of type `&'static str`
| | |
- | | argument of type `X` unexpected
+ | | unexpected argument of type `X`
| an argument of type `f32` is missing
|
note: function defined here
@@ -41,7 +42,7 @@ error[E0061]: this function takes 3 arguments but 2 arguments were supplied
LL | three_args(1, X {});
| ^^^^^^^^^^---------
| | |
- | | expected `f32`, found struct `X`
+ | | expected `f32`, found `X`
| an argument of type `&str` is missing
|
note: function defined here
@@ -58,7 +59,7 @@ error[E0308]: arguments to this function are incorrect
--> $DIR/mixed_cases.rs:17:3
|
LL | three_args(1, "", X {});
- | ^^^^^^^^^^ -- ---- argument of type `X` unexpected
+ | ^^^^^^^^^^ -- ---- unexpected argument of type `X`
| |
| an argument of type `f32` is missing
|
@@ -78,7 +79,7 @@ error[E0308]: arguments to this function are incorrect
LL | three_args("", X {}, 1);
| ^^^^^^^^^^ -- ---- - expected `&str`, found `{integer}`
| | |
- | | expected `f32`, found struct `X`
+ | | expected `f32`, found `X`
| expected `i32`, found `&'static str`
|
note: function defined here
diff --git a/tests/ui/argument-suggestions/too-long.stderr b/tests/ui/argument-suggestions/too-long.stderr
index 492894329..bb6f06a35 100644
--- a/tests/ui/argument-suggestions/too-long.stderr
+++ b/tests/ui/argument-suggestions/too-long.stderr
@@ -6,7 +6,7 @@ LL | qux.foo(a, b, c, d, e, f, g, h, i, j, k, l);
| |
| arguments to this method are incorrect
|
-note: associated function defined here
+note: method defined here
--> $DIR/too-long.rs:4:8
|
LL | fn foo(
diff --git a/tests/ui/argument-suggestions/two-mismatch-notes.stderr b/tests/ui/argument-suggestions/two-mismatch-notes.stderr
index 7873cf964..38cf23ddc 100644
--- a/tests/ui/argument-suggestions/two-mismatch-notes.stderr
+++ b/tests/ui/argument-suggestions/two-mismatch-notes.stderr
@@ -4,14 +4,15 @@ error[E0308]: arguments to this function are incorrect
LL | foo(f, w);
| ^^^
|
-note: expected `i32`, found `u32`
+note: expected fn pointer, found fn item
--> $DIR/two-mismatch-notes.rs:10:9
|
LL | foo(f, w);
| ^
= note: expected fn pointer `fn(i32)`
found fn item `fn(u32) {f}`
-note: expected `i32`, found `isize`
+ = note: when the arguments and return types match, functions can be coerced to function pointers
+note: expected `Wrapper<i32>`, found `Wrapper<isize>`
--> $DIR/two-mismatch-notes.rs:10:12
|
LL | foo(f, w);
diff --git a/tests/ui/array-slice-vec/array-not-vector.rs b/tests/ui/array-slice-vec/array-not-vector.rs
index 5e46f015b..d8b5b10d5 100644
--- a/tests/ui/array-slice-vec/array-not-vector.rs
+++ b/tests/ui/array-slice-vec/array-not-vector.rs
@@ -1,12 +1,12 @@
fn main() {
let _x: i32 = [1, 2, 3];
//~^ ERROR mismatched types
- //~| expected `i32`, found array
+ //~| expected `i32`, found `[{integer}; 3]`
let x: &[i32] = &[1, 2, 3];
let _y: &i32 = x;
//~^ ERROR mismatched types
//~| expected reference `&i32`
//~| found reference `&[i32]`
- //~| expected `i32`, found slice
+ //~| expected `&i32`, found `&[i32]`
}
diff --git a/tests/ui/array-slice-vec/array-not-vector.stderr b/tests/ui/array-slice-vec/array-not-vector.stderr
index 0e187d907..f20d99524 100644
--- a/tests/ui/array-slice-vec/array-not-vector.stderr
+++ b/tests/ui/array-slice-vec/array-not-vector.stderr
@@ -2,7 +2,7 @@ error[E0308]: mismatched types
--> $DIR/array-not-vector.rs:2:19
|
LL | let _x: i32 = [1, 2, 3];
- | --- ^^^^^^^^^ expected `i32`, found array `[{integer}; 3]`
+ | --- ^^^^^^^^^ expected `i32`, found `[{integer}; 3]`
| |
| expected due to this
@@ -10,7 +10,7 @@ error[E0308]: mismatched types
--> $DIR/array-not-vector.rs:7:20
|
LL | let _y: &i32 = x;
- | ---- ^ expected `i32`, found slice `[i32]`
+ | ---- ^ expected `&i32`, found `&[i32]`
| |
| expected due to this
|
diff --git a/tests/ui/array-slice-vec/slice-to-vec-comparison.stderr b/tests/ui/array-slice-vec/slice-to-vec-comparison.stderr
index e3b3b040f..47008e1d9 100644
--- a/tests/ui/array-slice-vec/slice-to-vec-comparison.stderr
+++ b/tests/ui/array-slice-vec/slice-to-vec-comparison.stderr
@@ -2,7 +2,7 @@ error[E0308]: mismatched types
--> $DIR/slice-to-vec-comparison.rs:4:9
|
LL | a > b;
- | ^ expected array of 0 elements, found struct `Vec`
+ | ^ expected `&[_; 0]`, found `&Vec<u8>`
|
= note: expected reference `&[_; 0]`
found reference `&Vec<u8>`
diff --git a/tests/ui/asm/issue-72570.rs b/tests/ui/asm/issue-72570.rs
index bb1381634..ac589de23 100644
--- a/tests/ui/asm/issue-72570.rs
+++ b/tests/ui/asm/issue-72570.rs
@@ -1,6 +1,4 @@
-// compile-flags: -Zsave-analysis
// needs-asm-support
-// Also test for #72960
use std::arch::asm;
diff --git a/tests/ui/asm/issue-72570.stderr b/tests/ui/asm/issue-72570.stderr
index fa5792688..49013a23c 100644
--- a/tests/ui/asm/issue-72570.stderr
+++ b/tests/ui/asm/issue-72570.stderr
@@ -1,5 +1,5 @@
error: invalid register `invalid`: unknown register
- --> $DIR/issue-72570.rs:9:18
+ --> $DIR/issue-72570.rs:7:18
|
LL | asm!("", in("invalid") "".len());
| ^^^^^^^^^^^^^^^^^^^^^^
diff --git a/tests/ui/asm/type-check-4.stderr b/tests/ui/asm/type-check-4.stderr
index c97cd171b..b5ecb3e1b 100644
--- a/tests/ui/asm/type-check-4.stderr
+++ b/tests/ui/asm/type-check-4.stderr
@@ -2,9 +2,9 @@ error[E0506]: cannot assign to `a` because it is borrowed
--> $DIR/type-check-4.rs:14:9
|
LL | let p = &a;
- | -- borrow of `a` occurs here
+ | -- `a` is borrowed here
LL | asm!("{}", out(reg) a);
- | ^^^^^^^^^^^^^^^^^^^^^^ assignment to borrowed `a` occurs here
+ | ^^^^^^^^^^^^^^^^^^^^^^ `a` is assigned to here but it was already borrowed
LL |
LL | println!("{}", p);
| - borrow later used here
@@ -13,7 +13,7 @@ error[E0503]: cannot use `a` because it was mutably borrowed
--> $DIR/type-check-4.rs:22:28
|
LL | let p = &mut a;
- | ------ borrow of `a` occurs here
+ | ------ `a` is borrowed here
LL | asm!("{}", in(reg) a);
| ^ use of borrowed `a`
LL |
diff --git a/tests/ui/associated-consts/associated-const-generic-obligations.stderr b/tests/ui/associated-consts/associated-const-generic-obligations.stderr
index f45fa0ad5..d45868151 100644
--- a/tests/ui/associated-consts/associated-const-generic-obligations.stderr
+++ b/tests/ui/associated-consts/associated-const-generic-obligations.stderr
@@ -2,7 +2,7 @@ error[E0326]: implemented const `FROM` has an incompatible type for trait
--> $DIR/associated-const-generic-obligations.rs:14:17
|
LL | const FROM: &'static str = "foo";
- | ^^^^^^^^^^^^ expected associated type, found `&str`
+ | ^^^^^^^^^^^^ expected associated type, found `&'static str`
|
note: type in trait
--> $DIR/associated-const-generic-obligations.rs:10:17
diff --git a/tests/ui/associated-consts/issue-105330.stderr b/tests/ui/associated-consts/issue-105330.stderr
index 30c380152..bbafc55da 100644
--- a/tests/ui/associated-consts/issue-105330.stderr
+++ b/tests/ui/associated-consts/issue-105330.stderr
@@ -33,7 +33,7 @@ LL | fn main<A: TraitWAssocConst<A=32>>() {
= note: see issue #92827 <https://github.com/rust-lang/rust/issues/92827> for more information
= help: add `#![feature(associated_const_equality)]` to the crate attributes to enable
-error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in type
+error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in impl headers
--> $DIR/issue-105330.rs:6:27
|
LL | impl TraitWAssocConst for impl Demo {
diff --git a/tests/ui/associated-inherent-types/ambiguity.rs b/tests/ui/associated-inherent-types/ambiguity.rs
new file mode 100644
index 000000000..73920555b
--- /dev/null
+++ b/tests/ui/associated-inherent-types/ambiguity.rs
@@ -0,0 +1,16 @@
+#![feature(inherent_associated_types)]
+#![allow(incomplete_features)]
+
+struct Wrapper<T>(T);
+
+impl Wrapper<i32> {
+ type Foo = i32;
+}
+
+impl Wrapper<()> {
+ type Foo = ();
+}
+
+fn main() {
+ let _: Wrapper<_>::Foo = (); //~ ERROR multiple applicable items in scope
+}
diff --git a/tests/ui/associated-inherent-types/ambiguity.stderr b/tests/ui/associated-inherent-types/ambiguity.stderr
new file mode 100644
index 000000000..155c296cb
--- /dev/null
+++ b/tests/ui/associated-inherent-types/ambiguity.stderr
@@ -0,0 +1,20 @@
+error[E0034]: multiple applicable items in scope
+ --> $DIR/ambiguity.rs:15:24
+ |
+LL | let _: Wrapper<_>::Foo = ();
+ | ^^^ multiple `Foo` found
+ |
+note: candidate #1 is defined in an impl for the type `Wrapper<i32>`
+ --> $DIR/ambiguity.rs:7:5
+ |
+LL | type Foo = i32;
+ | ^^^^^^^^
+note: candidate #2 is defined in an impl for the type `Wrapper<()>`
+ --> $DIR/ambiguity.rs:11:5
+ |
+LL | type Foo = ();
+ | ^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0034`.
diff --git a/tests/ui/associated-inherent-types/bugs/ice-substitution.rs b/tests/ui/associated-inherent-types/bugs/ice-substitution.rs
new file mode 100644
index 000000000..53ac79e05
--- /dev/null
+++ b/tests/ui/associated-inherent-types/bugs/ice-substitution.rs
@@ -0,0 +1,23 @@
+// known-bug: unknown
+// failure-status: 101
+// normalize-stderr-test "note: .*\n\n" -> ""
+// normalize-stderr-test "thread 'rustc' panicked.*\n" -> ""
+// rustc-env:RUST_BACKTRACE=0
+
+// FIXME: I presume a type variable that couldn't be solved by `resolve_vars_if_possible`
+// escapes the InferCtxt snapshot.
+
+#![feature(inherent_associated_types)]
+#![allow(incomplete_features)]
+
+struct Cont<T>(T);
+
+impl<T: Copy> Cont<T> {
+ type Out = Vec<T>;
+}
+
+pub fn weird<T: Copy>(x: T) {
+ let _: Cont<_>::Out = vec![true];
+}
+
+fn main() {}
diff --git a/tests/ui/associated-inherent-types/bugs/ice-substitution.stderr b/tests/ui/associated-inherent-types/bugs/ice-substitution.stderr
new file mode 100644
index 000000000..7b0d1c505
--- /dev/null
+++ b/tests/ui/associated-inherent-types/bugs/ice-substitution.stderr
@@ -0,0 +1,6 @@
+error: the compiler unexpectedly panicked. this is a bug.
+
+query stack during panic:
+#0 [typeck] type-checking `weird`
+#1 [typeck_item_bodies] type-checking all item bodies
+end of query stack
diff --git a/tests/ui/associated-inherent-types/bugs/inference-fail.rs b/tests/ui/associated-inherent-types/bugs/inference-fail.rs
new file mode 100644
index 000000000..a920b412b
--- /dev/null
+++ b/tests/ui/associated-inherent-types/bugs/inference-fail.rs
@@ -0,0 +1,15 @@
+// known-bug: unknown
+
+#![feature(inherent_associated_types)]
+#![allow(incomplete_features)]
+
+struct S<T>(T);
+
+impl S<()> {
+ type P = i128;
+}
+
+fn main() {
+ // We fail to infer `_ == ()` here.
+ let _: S<_>::P;
+}
diff --git a/tests/ui/associated-inherent-types/bugs/inference-fail.stderr b/tests/ui/associated-inherent-types/bugs/inference-fail.stderr
new file mode 100644
index 000000000..425691bd6
--- /dev/null
+++ b/tests/ui/associated-inherent-types/bugs/inference-fail.stderr
@@ -0,0 +1,9 @@
+error[E0282]: type annotations needed
+ --> $DIR/inference-fail.rs:14:14
+ |
+LL | let _: S<_>::P;
+ | ^ cannot infer type
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0282`.
diff --git a/tests/ui/associated-inherent-types/bugs/lack-of-regionck.rs b/tests/ui/associated-inherent-types/bugs/lack-of-regionck.rs
new file mode 100644
index 000000000..632dbf385
--- /dev/null
+++ b/tests/ui/associated-inherent-types/bugs/lack-of-regionck.rs
@@ -0,0 +1,19 @@
+// known-bug: unknown
+// check-pass
+
+// We currently don't region-check inherent associated type projections at all.
+
+#![feature(inherent_associated_types)]
+#![allow(incomplete_features, dead_code)]
+
+struct S<T>(T);
+
+impl S<&'static ()> {
+ type T = ();
+}
+
+fn usr<'a>() {
+ let _: S::<&'a ()>::T; // this should *fail* but it doesn't!
+}
+
+fn main() {}
diff --git a/tests/ui/associated-inherent-types/dispatch-on-self-type-0.rs b/tests/ui/associated-inherent-types/dispatch-on-self-type-0.rs
new file mode 100644
index 000000000..f846bfa41
--- /dev/null
+++ b/tests/ui/associated-inherent-types/dispatch-on-self-type-0.rs
@@ -0,0 +1,41 @@
+// check-pass
+
+#![feature(inherent_associated_types)]
+#![allow(incomplete_features)]
+
+// Check that inherent associated types are dispatched on the concrete Self type.
+
+struct Select<T>(T);
+
+impl Select<u8> {
+ type Projection = ();
+}
+
+impl Select<String> {
+ type Projection = bool;
+}
+
+struct Choose<T>(T);
+struct NonCopy;
+
+impl<T: Copy> Choose<T> {
+ type Result = Vec<T>;
+}
+
+impl Choose<NonCopy> {
+ type Result = ();
+}
+
+fn main() {
+ let _: Select<String>::Projection = false;
+ let _: Select<u8>::Projection = ();
+
+ let _: Choose<NonCopy>::Result = ();
+ let _: Choose<bool>::Result = vec![true];
+}
+
+// Test if we use the correct `ParamEnv` when proving obligations.
+
+pub fn parameterized<T: Copy>(x: T) {
+ let _: Choose<T>::Result = vec![x];
+}
diff --git a/tests/ui/associated-inherent-types/dispatch-on-self-type-1.rs b/tests/ui/associated-inherent-types/dispatch-on-self-type-1.rs
new file mode 100644
index 000000000..9b0fa8dc6
--- /dev/null
+++ b/tests/ui/associated-inherent-types/dispatch-on-self-type-1.rs
@@ -0,0 +1,39 @@
+// check-pass
+
+#![feature(inherent_associated_types, auto_traits, negative_impls)]
+#![allow(incomplete_features)]
+
+use std::cmp::Ordering;
+
+// Check that inherent associated types are dispatched on the concrete Self type.
+
+struct Select<T, U>(T, U);
+
+impl<T: Ordinary, U: Ordinary> Select<T, U> {
+ type Type = ();
+}
+
+impl<T: Ordinary> Select<T, Special> {
+ type Type = bool;
+}
+
+impl<T: Ordinary> Select<Special, T> {
+ type Type = Ordering;
+}
+
+impl Select<Special, Special> {
+ type Type = (bool, bool);
+}
+
+fn main() {
+ let _: Select<String, Special>::Type = false;
+ let _: Select<Special, Special>::Type = (true, false);
+ let _: Select<Special, u8>::Type = Ordering::Equal;
+ let _: Select<i128, ()>::Type = ();
+}
+
+enum Special {}
+
+impl !Ordinary for Special {}
+
+auto trait Ordinary {}
diff --git a/tests/ui/associated-inherent-types/dispatch-on-self-type-2.rs b/tests/ui/associated-inherent-types/dispatch-on-self-type-2.rs
new file mode 100644
index 000000000..7b205952f
--- /dev/null
+++ b/tests/ui/associated-inherent-types/dispatch-on-self-type-2.rs
@@ -0,0 +1,17 @@
+#![feature(inherent_associated_types)]
+#![allow(incomplete_features)]
+
+struct Parameterized<T, U>(T, U);
+
+impl Parameterized<(), ()> {
+ type Output = bool;
+}
+
+impl<T> Parameterized<bool, T> {
+ type Result = T;
+}
+
+fn main() {
+ let _: Parameterized<(), ()>::Output = String::new(); //~ ERROR mismatched types
+ let _: Parameterized<bool, u32>::Result = (); //~ ERROR mismatched types
+}
diff --git a/tests/ui/associated-inherent-types/dispatch-on-self-type-2.stderr b/tests/ui/associated-inherent-types/dispatch-on-self-type-2.stderr
new file mode 100644
index 000000000..c9a48872a
--- /dev/null
+++ b/tests/ui/associated-inherent-types/dispatch-on-self-type-2.stderr
@@ -0,0 +1,19 @@
+error[E0308]: mismatched types
+ --> $DIR/dispatch-on-self-type-2.rs:15:44
+ |
+LL | let _: Parameterized<(), ()>::Output = String::new();
+ | ----------------------------- ^^^^^^^^^^^^^ expected `bool`, found `String`
+ | |
+ | expected due to this
+
+error[E0308]: mismatched types
+ --> $DIR/dispatch-on-self-type-2.rs:16:47
+ |
+LL | let _: Parameterized<bool, u32>::Result = ();
+ | -------------------------------- ^^ expected `u32`, found `()`
+ | |
+ | expected due to this
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/associated-inherent-types/not-found-self-type-differs-shadowing-trait-item.rs b/tests/ui/associated-inherent-types/not-found-self-type-differs-shadowing-trait-item.rs
new file mode 100644
index 000000000..d2efb24c6
--- /dev/null
+++ b/tests/ui/associated-inherent-types/not-found-self-type-differs-shadowing-trait-item.rs
@@ -0,0 +1,31 @@
+#![feature(inherent_associated_types)]
+#![allow(incomplete_features)]
+
+// Check that it's okay to report “[inherent] associated type […] not found” for inherent associated
+// type candidates that are not applicable (due to unsuitable Self type) even if there exists a
+// “shadowed” associated type from a trait with the same name since its use would be ambiguous
+// anyway if the IAT didn't exist.
+// FIXME(inherent_associated_types): Figure out which error would be more helpful here.
+
+// revisions: shadowed uncovered
+
+struct S<T>(T);
+
+trait Tr {
+ type Pr;
+}
+
+impl<T> Tr for S<T> {
+ type Pr = ();
+}
+
+#[cfg(shadowed)]
+impl S<()> {
+ type Pr = i32;
+}
+
+fn main() {
+ let _: S::<bool>::Pr = ();
+ //[shadowed]~^ ERROR associated type `Pr` not found
+ //[uncovered]~^^ ERROR ambiguous associated type
+}
diff --git a/tests/ui/associated-inherent-types/not-found-self-type-differs-shadowing-trait-item.shadowed.stderr b/tests/ui/associated-inherent-types/not-found-self-type-differs-shadowing-trait-item.shadowed.stderr
new file mode 100644
index 000000000..3561db354
--- /dev/null
+++ b/tests/ui/associated-inherent-types/not-found-self-type-differs-shadowing-trait-item.shadowed.stderr
@@ -0,0 +1,15 @@
+error[E0220]: associated type `Pr` not found for `S<bool>` in the current scope
+ --> $DIR/not-found-self-type-differs-shadowing-trait-item.rs:28:23
+ |
+LL | struct S<T>(T);
+ | ----------- associated item `Pr` not found for this struct
+...
+LL | let _: S::<bool>::Pr = ();
+ | ^^ associated item not found in `S<bool>`
+ |
+ = note: the associated type was found for
+ - `S<()>`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0220`.
diff --git a/tests/ui/associated-inherent-types/not-found-self-type-differs-shadowing-trait-item.uncovered.stderr b/tests/ui/associated-inherent-types/not-found-self-type-differs-shadowing-trait-item.uncovered.stderr
new file mode 100644
index 000000000..88c72042c
--- /dev/null
+++ b/tests/ui/associated-inherent-types/not-found-self-type-differs-shadowing-trait-item.uncovered.stderr
@@ -0,0 +1,9 @@
+error[E0223]: ambiguous associated type
+ --> $DIR/not-found-self-type-differs-shadowing-trait-item.rs:28:12
+ |
+LL | let _: S::<bool>::Pr = ();
+ | ^^^^^^^^^^^^^ help: use the fully-qualified path: `<S<bool> as Tr>::Pr`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0223`.
diff --git a/tests/ui/associated-inherent-types/not-found-self-type-differs.alias.stderr b/tests/ui/associated-inherent-types/not-found-self-type-differs.alias.stderr
new file mode 100644
index 000000000..4396435a6
--- /dev/null
+++ b/tests/ui/associated-inherent-types/not-found-self-type-differs.alias.stderr
@@ -0,0 +1,16 @@
+error[E0220]: associated type `Proj` not found for `Family<Option<()>>` in the current scope
+ --> $DIR/not-found-self-type-differs.rs:17:34
+ |
+LL | struct Family<T>(T);
+ | ---------------- associated item `Proj` not found for this struct
+...
+LL | type Alias = Family<Option<()>>::Proj;
+ | ^^^^ associated item not found in `Family<Option<()>>`
+ |
+ = note: the associated type was found for
+ - `Family<()>`
+ - `Family<Result<T, ()>>`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0220`.
diff --git a/tests/ui/associated-inherent-types/not-found-self-type-differs.local.stderr b/tests/ui/associated-inherent-types/not-found-self-type-differs.local.stderr
new file mode 100644
index 000000000..d527db022
--- /dev/null
+++ b/tests/ui/associated-inherent-types/not-found-self-type-differs.local.stderr
@@ -0,0 +1,16 @@
+error[E0220]: associated type `Proj` not found for `Family<PathBuf>` in the current scope
+ --> $DIR/not-found-self-type-differs.rs:21:40
+ |
+LL | struct Family<T>(T);
+ | ---------------- associated item `Proj` not found for this struct
+...
+LL | let _: Family<std::path::PathBuf>::Proj = ();
+ | ^^^^ associated item not found in `Family<PathBuf>`
+ |
+ = note: the associated type was found for
+ - `Family<()>`
+ - `Family<Result<T, ()>>`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0220`.
diff --git a/tests/ui/associated-inherent-types/not-found-self-type-differs.rs b/tests/ui/associated-inherent-types/not-found-self-type-differs.rs
new file mode 100644
index 000000000..93f58dcb6
--- /dev/null
+++ b/tests/ui/associated-inherent-types/not-found-self-type-differs.rs
@@ -0,0 +1,22 @@
+// revisions: local alias
+
+#![feature(inherent_associated_types)]
+#![allow(incomplete_features)]
+
+struct Family<T>(T);
+
+impl Family<()> {
+ type Proj = ();
+}
+
+impl<T> Family<Result<T, ()>> {
+ type Proj = Self;
+}
+
+#[cfg(alias)]
+type Alias = Family<Option<()>>::Proj; //[alias]~ ERROR associated type `Proj` not found for `Family<Option<()>>`
+
+fn main() {
+ #[cfg(local)]
+ let _: Family<std::path::PathBuf>::Proj = (); //[local]~ ERROR associated type `Proj` not found for `Family<PathBuf>`
+}
diff --git a/tests/ui/associated-inherent-types/not-found-unsatisfied-bounds-0.rs b/tests/ui/associated-inherent-types/not-found-unsatisfied-bounds-0.rs
new file mode 100644
index 000000000..b00830fa1
--- /dev/null
+++ b/tests/ui/associated-inherent-types/not-found-unsatisfied-bounds-0.rs
@@ -0,0 +1,21 @@
+// Regression test for issue #104251.
+
+#![feature(inherent_associated_types)]
+#![allow(incomplete_features)]
+
+struct Container<T: ?Sized>(T);
+
+impl<T> Container<T> {
+ type Yield = i32;
+}
+
+struct Duple<T, U>(T, U);
+
+impl<T: Copy, U: Send> Duple<T, U> {
+ type Combination = (T, U);
+}
+
+fn main() {
+ let _: Container<[u8]>::Yield = 1; //~ ERROR the associated type `Yield` exists for `Container<[u8]>`, but its trait bounds were not satisfied
+ let _: Duple<String, std::rc::Rc<str>>::Combination; //~ ERROR the associated type `Combination` exists for `Duple<String, Rc<str>>`, but its trait bounds were not satisfied
+}
diff --git a/tests/ui/associated-inherent-types/not-found-unsatisfied-bounds-0.stderr b/tests/ui/associated-inherent-types/not-found-unsatisfied-bounds-0.stderr
new file mode 100644
index 000000000..736579067
--- /dev/null
+++ b/tests/ui/associated-inherent-types/not-found-unsatisfied-bounds-0.stderr
@@ -0,0 +1,27 @@
+error: the associated type `Yield` exists for `Container<[u8]>`, but its trait bounds were not satisfied
+ --> $DIR/not-found-unsatisfied-bounds-0.rs:19:29
+ |
+LL | struct Container<T: ?Sized>(T);
+ | --------------------------- associated item `Yield` not found for this struct
+...
+LL | let _: Container<[u8]>::Yield = 1;
+ | ^^^^^ associated type cannot be referenced on `Container<[u8]>` due to unsatisfied trait bounds
+ |
+ = note: the following trait bounds were not satisfied:
+ `[u8]: Sized`
+
+error: the associated type `Combination` exists for `Duple<String, Rc<str>>`, but its trait bounds were not satisfied
+ --> $DIR/not-found-unsatisfied-bounds-0.rs:20:45
+ |
+LL | struct Duple<T, U>(T, U);
+ | ------------------ associated item `Combination` not found for this struct
+...
+LL | let _: Duple<String, std::rc::Rc<str>>::Combination;
+ | ^^^^^^^^^^^ associated type cannot be referenced on `Duple<String, Rc<str>>` due to unsatisfied trait bounds
+ |
+ = note: the following trait bounds were not satisfied:
+ `Rc<str>: Send`
+ `String: Copy`
+
+error: aborting due to 2 previous errors
+
diff --git a/tests/ui/associated-inherent-types/not-found-unsatisfied-bounds-1.rs b/tests/ui/associated-inherent-types/not-found-unsatisfied-bounds-1.rs
new file mode 100644
index 000000000..c80b1364a
--- /dev/null
+++ b/tests/ui/associated-inherent-types/not-found-unsatisfied-bounds-1.rs
@@ -0,0 +1,18 @@
+// fail-check
+
+#![feature(inherent_associated_types)]
+#![allow(incomplete_features)]
+
+// Test if we use the correct `ParamEnv` when proving obligations.
+
+fn parameterized<T>() {
+ let _: Container<T>::Proj = String::new(); //~ ERROR the associated type `Proj` exists for `Container<T>`, but its trait bounds were not satisfied
+}
+
+struct Container<T>(T);
+
+impl<T: Clone> Container<T> {
+ type Proj = String;
+}
+
+fn main() {}
diff --git a/tests/ui/associated-inherent-types/not-found-unsatisfied-bounds-1.stderr b/tests/ui/associated-inherent-types/not-found-unsatisfied-bounds-1.stderr
new file mode 100644
index 000000000..230bfa538
--- /dev/null
+++ b/tests/ui/associated-inherent-types/not-found-unsatisfied-bounds-1.stderr
@@ -0,0 +1,14 @@
+error: the associated type `Proj` exists for `Container<T>`, but its trait bounds were not satisfied
+ --> $DIR/not-found-unsatisfied-bounds-1.rs:9:26
+ |
+LL | let _: Container<T>::Proj = String::new();
+ | ^^^^ associated type cannot be referenced on `Container<T>` due to unsatisfied trait bounds
+...
+LL | struct Container<T>(T);
+ | ------------------- associated item `Proj` not found for this struct
+ |
+ = note: the following trait bounds were not satisfied:
+ `T: Clone`
+
+error: aborting due to previous error
+
diff --git a/tests/ui/associated-inherent-types/not-found-unsatisfied-bounds-in-multiple-impls.rs b/tests/ui/associated-inherent-types/not-found-unsatisfied-bounds-in-multiple-impls.rs
new file mode 100644
index 000000000..5b0e8de9c
--- /dev/null
+++ b/tests/ui/associated-inherent-types/not-found-unsatisfied-bounds-in-multiple-impls.rs
@@ -0,0 +1,20 @@
+#![feature(inherent_associated_types)]
+#![allow(incomplete_features)]
+
+struct S<A, B>(A, B);
+struct Featureless;
+
+trait One {}
+trait Two {}
+
+impl<T: One> S<Featureless, T> {
+ type X = ();
+}
+
+impl<T: Two> S<T, Featureless> {
+ type X = String;
+}
+
+fn main() {
+ let _: S::<Featureless, Featureless>::X; //~ ERROR the associated type `X` exists for `S<Featureless, Featureless>`, but its trait bounds were not satisfied
+}
diff --git a/tests/ui/associated-inherent-types/not-found-unsatisfied-bounds-in-multiple-impls.stderr b/tests/ui/associated-inherent-types/not-found-unsatisfied-bounds-in-multiple-impls.stderr
new file mode 100644
index 000000000..3ddab25de
--- /dev/null
+++ b/tests/ui/associated-inherent-types/not-found-unsatisfied-bounds-in-multiple-impls.stderr
@@ -0,0 +1,20 @@
+error: the associated type `X` exists for `S<Featureless, Featureless>`, but its trait bounds were not satisfied
+ --> $DIR/not-found-unsatisfied-bounds-in-multiple-impls.rs:19:43
+ |
+LL | struct S<A, B>(A, B);
+ | -------------- associated item `X` not found for this struct
+LL | struct Featureless;
+ | ------------------
+ | |
+ | doesn't satisfy `Featureless: One`
+ | doesn't satisfy `Featureless: Two`
+...
+LL | let _: S::<Featureless, Featureless>::X;
+ | ^ associated type cannot be referenced on `S<Featureless, Featureless>` due to unsatisfied trait bounds
+ |
+ = note: the following trait bounds were not satisfied:
+ `Featureless: One`
+ `Featureless: Two`
+
+error: aborting due to previous error
+
diff --git a/tests/ui/associated-inherent-types/substitute-params-bad.rs b/tests/ui/associated-inherent-types/substitute-params-bad.rs
new file mode 100644
index 000000000..00eb1a14d
--- /dev/null
+++ b/tests/ui/associated-inherent-types/substitute-params-bad.rs
@@ -0,0 +1,23 @@
+// Regression test for issue #105305 and for
+// https://github.com/rust-lang/rust/issues/107468#issuecomment-1409096700
+
+#![feature(inherent_associated_types)]
+#![allow(incomplete_features)]
+
+struct S<T>(T);
+
+impl<T, 'a> S<T> { //~ ERROR lifetime parameters must be declared prior to type and const parameters
+ type P = T;
+}
+
+struct Subj<T>(T);
+
+impl<T, S> Subj<(T, S)> {
+ type Un = (T, S);
+}
+
+fn main() {
+ type A = S<()>::P;
+
+ let _: Subj<(i32, i32)>::Un = 0i32; //~ ERROR mismatched types
+}
diff --git a/tests/ui/associated-inherent-types/substitute-params-bad.stderr b/tests/ui/associated-inherent-types/substitute-params-bad.stderr
new file mode 100644
index 000000000..7a7808ba6
--- /dev/null
+++ b/tests/ui/associated-inherent-types/substitute-params-bad.stderr
@@ -0,0 +1,20 @@
+error: lifetime parameters must be declared prior to type and const parameters
+ --> $DIR/substitute-params-bad.rs:9:9
+ |
+LL | impl<T, 'a> S<T> {
+ | ----^^- help: reorder the parameters: lifetimes, then consts and types: `<'a, T>`
+
+error[E0308]: mismatched types
+ --> $DIR/substitute-params-bad.rs:22:35
+ |
+LL | let _: Subj<(i32, i32)>::Un = 0i32;
+ | -------------------- ^^^^ expected `(i32, i32)`, found `i32`
+ | |
+ | expected due to this
+ |
+ = note: expected tuple `(i32, i32)`
+ found type `i32`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/associated-inherent-types/struct-generics.rs b/tests/ui/associated-inherent-types/substitute-params.rs
index 8952b3791..e94d68331 100644
--- a/tests/ui/associated-inherent-types/struct-generics.rs
+++ b/tests/ui/associated-inherent-types/substitute-params.rs
@@ -9,7 +9,15 @@ impl<T> S<T> {
type P = T;
}
+impl<T> S<(T,)> {
+ type Un = T;
+}
+
fn main() {
+ // Regression test for issue #104240.
type A = S<()>::P;
let _: A = ();
+
+ // Regression test for issue #107468.
+ let _: S<(i32,)>::Un = 0i32;
}
diff --git a/tests/ui/associated-type-bounds/bad-universal-in-dyn-in-where-clause.rs b/tests/ui/associated-type-bounds/bad-universal-in-dyn-in-where-clause.rs
new file mode 100644
index 000000000..8cab1f66c
--- /dev/null
+++ b/tests/ui/associated-type-bounds/bad-universal-in-dyn-in-where-clause.rs
@@ -0,0 +1,14 @@
+#![feature(associated_type_bounds)]
+
+trait B {
+ type AssocType;
+}
+
+fn f()
+where
+ dyn for<'j> B<AssocType: 'j>:,
+ //~^ ERROR associated type bounds are only allowed in where clauses and function signatures
+{
+}
+
+fn main() {}
diff --git a/tests/ui/associated-type-bounds/bad-universal-in-dyn-in-where-clause.stderr b/tests/ui/associated-type-bounds/bad-universal-in-dyn-in-where-clause.stderr
new file mode 100644
index 000000000..6fa266d23
--- /dev/null
+++ b/tests/ui/associated-type-bounds/bad-universal-in-dyn-in-where-clause.stderr
@@ -0,0 +1,8 @@
+error: associated type bounds are only allowed in where clauses and function signatures, not in bounds
+ --> $DIR/bad-universal-in-dyn-in-where-clause.rs:9:19
+ |
+LL | dyn for<'j> B<AssocType: 'j>:,
+ | ^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/tests/ui/associated-type-bounds/bad-universal-in-impl-sig.rs b/tests/ui/associated-type-bounds/bad-universal-in-impl-sig.rs
new file mode 100644
index 000000000..1d5d181ef
--- /dev/null
+++ b/tests/ui/associated-type-bounds/bad-universal-in-impl-sig.rs
@@ -0,0 +1,13 @@
+#![feature(associated_type_bounds)]
+
+trait Trait {
+ type Item;
+}
+
+trait Trait2 {}
+
+// It's not possible to insert a universal `impl Trait` here!
+impl dyn Trait<Item: Trait2> {}
+//~^ ERROR associated type bounds are only allowed in where clauses and function signatures
+
+fn main() {}
diff --git a/tests/ui/associated-type-bounds/bad-universal-in-impl-sig.stderr b/tests/ui/associated-type-bounds/bad-universal-in-impl-sig.stderr
new file mode 100644
index 000000000..8b66627d5
--- /dev/null
+++ b/tests/ui/associated-type-bounds/bad-universal-in-impl-sig.stderr
@@ -0,0 +1,8 @@
+error: associated type bounds are only allowed in where clauses and function signatures, not in impl headers
+ --> $DIR/bad-universal-in-impl-sig.rs:10:16
+ |
+LL | impl dyn Trait<Item: Trait2> {}
+ | ^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/tests/ui/associated-type-bounds/elision.stderr b/tests/ui/associated-type-bounds/elision.stderr
index ea3024627..cc10bbcc0 100644
--- a/tests/ui/associated-type-bounds/elision.stderr
+++ b/tests/ui/associated-type-bounds/elision.stderr
@@ -14,12 +14,12 @@ error[E0308]: mismatched types
--> $DIR/elision.rs:5:79
|
LL | fn f(x: &mut dyn Iterator<Item: Iterator<Item = &'_ ()>>) -> Option<&'_ ()> { x.next() }
- | ----------------------------- -------------- ^^^^^^^^ expected `&()`, found type parameter `impl Iterator<Item = &'_ ()>`
+ | ----------------------------- -------------- ^^^^^^^^ expected `Option<&()>`, found `Option<impl Iterator<Item = &'_ ()>>`
| | |
- | | expected `Option<&'static ()>` because of return type
+ | | expected `Option<&()>` because of return type
| this type parameter
|
- = note: expected enum `Option<&'static ()>`
+ = note: expected enum `Option<&()>`
found enum `Option<impl Iterator<Item = &'_ ()>>`
error: aborting due to 2 previous errors
diff --git a/tests/ui/associated-type-bounds/inside-adt.rs b/tests/ui/associated-type-bounds/inside-adt.rs
index 8eb8c44bb..057966941 100644
--- a/tests/ui/associated-type-bounds/inside-adt.rs
+++ b/tests/ui/associated-type-bounds/inside-adt.rs
@@ -3,28 +3,24 @@
use std::mem::ManuallyDrop;
struct S1 { f: dyn Iterator<Item: Copy> }
-//~^ ERROR associated type bounds are not allowed within structs, enums, or unions
+//~^ ERROR associated type bounds are only allowed in where clauses and function signatures
struct S2 { f: Box<dyn Iterator<Item: Copy>> }
-//~^ ERROR associated type bounds are not allowed within structs, enums, or unions
+//~^ ERROR associated type bounds are only allowed in where clauses and function signatures
struct S3 { f: dyn Iterator<Item: 'static> }
-//~^ ERROR associated type bounds are not allowed within structs, enums, or unions
+//~^ ERROR associated type bounds are only allowed in where clauses and function signatures
enum E1 { V(dyn Iterator<Item: Copy>) }
-//~^ ERROR associated type bounds are not allowed within structs, enums, or unions
-//~| ERROR the size for values of type `(dyn Iterator<Item = impl Copy> + 'static)`
+//~^ ERROR associated type bounds are only allowed in where clauses and function signatures
enum E2 { V(Box<dyn Iterator<Item: Copy>>) }
-//~^ ERROR associated type bounds are not allowed within structs, enums, or unions
+//~^ ERROR associated type bounds are only allowed in where clauses and function signatures
enum E3 { V(dyn Iterator<Item: 'static>) }
-//~^ ERROR associated type bounds are not allowed within structs, enums, or unions
-//~| ERROR the size for values of type `(dyn Iterator<Item = impl Sized + 'static> + 'static)`
+//~^ ERROR associated type bounds are only allowed in where clauses and function signatures
union U1 { f: ManuallyDrop<dyn Iterator<Item: Copy>> }
-//~^ ERROR associated type bounds are not allowed within structs, enums, or unions
-//~| ERROR the size for values of type `(dyn Iterator<Item = impl Copy> + 'static)`
+//~^ ERROR associated type bounds are only allowed in where clauses and function signatures
union U2 { f: ManuallyDrop<Box<dyn Iterator<Item: Copy>>> }
-//~^ ERROR associated type bounds are not allowed within structs, enums, or unions
+//~^ ERROR associated type bounds are only allowed in where clauses and function signatures
union U3 { f: ManuallyDrop<dyn Iterator<Item: 'static>> }
-//~^ ERROR associated type bounds are not allowed within structs, enums, or unions
-//~| ERROR the size for values of type `(dyn Iterator<Item = impl Sized + 'static> + 'static)`
+//~^ ERROR associated type bounds are only allowed in where clauses and function signatures
fn main() {}
diff --git a/tests/ui/associated-type-bounds/inside-adt.stderr b/tests/ui/associated-type-bounds/inside-adt.stderr
index dbfcfa580..f848bd798 100644
--- a/tests/ui/associated-type-bounds/inside-adt.stderr
+++ b/tests/ui/associated-type-bounds/inside-adt.stderr
@@ -1,131 +1,56 @@
-error: associated type bounds are not allowed within structs, enums, or unions
+error: associated type bounds are only allowed in where clauses and function signatures, not in field types
--> $DIR/inside-adt.rs:5:29
|
LL | struct S1 { f: dyn Iterator<Item: Copy> }
| ^^^^^^^^^^
-error: associated type bounds are not allowed within structs, enums, or unions
+error: associated type bounds are only allowed in where clauses and function signatures, not in field types
--> $DIR/inside-adt.rs:7:33
|
LL | struct S2 { f: Box<dyn Iterator<Item: Copy>> }
| ^^^^^^^^^^
-error: associated type bounds are not allowed within structs, enums, or unions
+error: associated type bounds are only allowed in where clauses and function signatures, not in field types
--> $DIR/inside-adt.rs:9:29
|
LL | struct S3 { f: dyn Iterator<Item: 'static> }
| ^^^^^^^^^^^^^
-error: associated type bounds are not allowed within structs, enums, or unions
+error: associated type bounds are only allowed in where clauses and function signatures, not in field types
--> $DIR/inside-adt.rs:12:26
|
LL | enum E1 { V(dyn Iterator<Item: Copy>) }
| ^^^^^^^^^^
-error: associated type bounds are not allowed within structs, enums, or unions
- --> $DIR/inside-adt.rs:15:30
+error: associated type bounds are only allowed in where clauses and function signatures, not in field types
+ --> $DIR/inside-adt.rs:14:30
|
LL | enum E2 { V(Box<dyn Iterator<Item: Copy>>) }
| ^^^^^^^^^^
-error: associated type bounds are not allowed within structs, enums, or unions
- --> $DIR/inside-adt.rs:17:26
+error: associated type bounds are only allowed in where clauses and function signatures, not in field types
+ --> $DIR/inside-adt.rs:16:26
|
LL | enum E3 { V(dyn Iterator<Item: 'static>) }
| ^^^^^^^^^^^^^
-error: associated type bounds are not allowed within structs, enums, or unions
- --> $DIR/inside-adt.rs:21:41
+error: associated type bounds are only allowed in where clauses and function signatures, not in field types
+ --> $DIR/inside-adt.rs:19:41
|
LL | union U1 { f: ManuallyDrop<dyn Iterator<Item: Copy>> }
| ^^^^^^^^^^
-error: associated type bounds are not allowed within structs, enums, or unions
- --> $DIR/inside-adt.rs:24:45
+error: associated type bounds are only allowed in where clauses and function signatures, not in field types
+ --> $DIR/inside-adt.rs:21:45
|
LL | union U2 { f: ManuallyDrop<Box<dyn Iterator<Item: Copy>>> }
| ^^^^^^^^^^
-error: associated type bounds are not allowed within structs, enums, or unions
- --> $DIR/inside-adt.rs:26:41
+error: associated type bounds are only allowed in where clauses and function signatures, not in field types
+ --> $DIR/inside-adt.rs:23:41
|
LL | union U3 { f: ManuallyDrop<dyn Iterator<Item: 'static>> }
| ^^^^^^^^^^^^^
-error[E0277]: the size for values of type `(dyn Iterator<Item = impl Copy> + 'static)` cannot be known at compilation time
- --> $DIR/inside-adt.rs:12:13
- |
-LL | enum E1 { V(dyn Iterator<Item: Copy>) }
- | ^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
- |
- = help: the trait `Sized` is not implemented for `(dyn Iterator<Item = impl Copy> + 'static)`
- = note: no field of an enum variant may have a dynamically sized type
- = help: change the field's type to have a statically known size
-help: borrowed types always have a statically known size
- |
-LL | enum E1 { V(&dyn Iterator<Item: Copy>) }
- | +
-help: the `Box` type always has a statically known size and allocates its contents in the heap
- |
-LL | enum E1 { V(Box<dyn Iterator<Item: Copy>>) }
- | ++++ +
-
-error[E0277]: the size for values of type `(dyn Iterator<Item = impl Sized + 'static> + 'static)` cannot be known at compilation time
- --> $DIR/inside-adt.rs:17:13
- |
-LL | enum E3 { V(dyn Iterator<Item: 'static>) }
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
- |
- = help: the trait `Sized` is not implemented for `(dyn Iterator<Item = impl Sized + 'static> + 'static)`
- = note: no field of an enum variant may have a dynamically sized type
- = help: change the field's type to have a statically known size
-help: borrowed types always have a statically known size
- |
-LL | enum E3 { V(&dyn Iterator<Item: 'static>) }
- | +
-help: the `Box` type always has a statically known size and allocates its contents in the heap
- |
-LL | enum E3 { V(Box<dyn Iterator<Item: 'static>>) }
- | ++++ +
-
-error[E0277]: the size for values of type `(dyn Iterator<Item = impl Copy> + 'static)` cannot be known at compilation time
- --> $DIR/inside-adt.rs:21:15
- |
-LL | union U1 { f: ManuallyDrop<dyn Iterator<Item: Copy>> }
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
- |
- = help: within `ManuallyDrop<(dyn Iterator<Item = impl Copy> + 'static)>`, the trait `Sized` is not implemented for `(dyn Iterator<Item = impl Copy> + 'static)`
- = note: required because it appears within the type `ManuallyDrop<(dyn Iterator<Item = impl Copy> + 'static)>`
- = note: no field of a union may have a dynamically sized type
- = help: change the field's type to have a statically known size
-help: borrowed types always have a statically known size
- |
-LL | union U1 { f: &ManuallyDrop<dyn Iterator<Item: Copy>> }
- | +
-help: the `Box` type always has a statically known size and allocates its contents in the heap
- |
-LL | union U1 { f: Box<ManuallyDrop<dyn Iterator<Item: Copy>>> }
- | ++++ +
-
-error[E0277]: the size for values of type `(dyn Iterator<Item = impl Sized + 'static> + 'static)` cannot be known at compilation time
- --> $DIR/inside-adt.rs:26:15
- |
-LL | union U3 { f: ManuallyDrop<dyn Iterator<Item: 'static>> }
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
- |
- = help: within `ManuallyDrop<(dyn Iterator<Item = impl Sized + 'static> + 'static)>`, the trait `Sized` is not implemented for `(dyn Iterator<Item = impl Sized + 'static> + 'static)`
- = note: required because it appears within the type `ManuallyDrop<(dyn Iterator<Item = impl Sized + 'static> + 'static)>`
- = note: no field of a union may have a dynamically sized type
- = help: change the field's type to have a statically known size
-help: borrowed types always have a statically known size
- |
-LL | union U3 { f: &ManuallyDrop<dyn Iterator<Item: 'static>> }
- | +
-help: the `Box` type always has a statically known size and allocates its contents in the heap
- |
-LL | union U3 { f: Box<ManuallyDrop<dyn Iterator<Item: 'static>>> }
- | ++++ +
-
-error: aborting due to 13 previous errors
+error: aborting due to 9 previous errors
-For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/associated-type-bounds/issue-71443-1.stderr b/tests/ui/associated-type-bounds/issue-71443-1.stderr
index a9459ee74..15cc9646b 100644
--- a/tests/ui/associated-type-bounds/issue-71443-1.stderr
+++ b/tests/ui/associated-type-bounds/issue-71443-1.stderr
@@ -4,7 +4,7 @@ error[E0308]: mismatched types
LL | fn hello<F: for<'a> Iterator<Item: 'a>>() {
| - help: try adding a return type: `-> Incorrect`
LL | Incorrect
- | ^^^^^^^^^ expected `()`, found struct `Incorrect`
+ | ^^^^^^^^^ expected `()`, found `Incorrect`
error: aborting due to previous error
diff --git a/tests/ui/associated-types/associated-type-projection-from-supertrait.stderr b/tests/ui/associated-types/associated-type-projection-from-supertrait.stderr
index d6b18d4ed..3f3bf22b0 100644
--- a/tests/ui/associated-types/associated-type-projection-from-supertrait.stderr
+++ b/tests/ui/associated-types/associated-type-projection-from-supertrait.stderr
@@ -2,7 +2,7 @@ error[E0308]: mismatched types
--> $DIR/associated-type-projection-from-supertrait.rs:27:23
|
LL | fn b() { dent(ModelT, Blue); }
- | ---- ^^^^ expected struct `Black`, found struct `Blue`
+ | ---- ^^^^ expected `Black`, found `Blue`
| |
| arguments to this function are incorrect
|
@@ -16,7 +16,7 @@ error[E0308]: mismatched types
--> $DIR/associated-type-projection-from-supertrait.rs:28:23
|
LL | fn c() { dent(ModelU, Black); }
- | ---- ^^^^^ expected struct `Blue`, found struct `Black`
+ | ---- ^^^^^ expected `Blue`, found `Black`
| |
| arguments to this function are incorrect
|
@@ -30,11 +30,11 @@ error[E0308]: mismatched types
--> $DIR/associated-type-projection-from-supertrait.rs:32:28
|
LL | fn f() { ModelT.chip_paint(Blue); }
- | ---------- ^^^^ expected struct `Black`, found struct `Blue`
+ | ---------- ^^^^ expected `Black`, found `Blue`
| |
| arguments to this method are incorrect
|
-note: associated function defined here
+note: method defined here
--> $DIR/associated-type-projection-from-supertrait.rs:12:8
|
LL | fn chip_paint(&self, c: Self::Color) { }
@@ -44,11 +44,11 @@ error[E0308]: mismatched types
--> $DIR/associated-type-projection-from-supertrait.rs:33:28
|
LL | fn g() { ModelU.chip_paint(Black); }
- | ---------- ^^^^^ expected struct `Blue`, found struct `Black`
+ | ---------- ^^^^^ expected `Blue`, found `Black`
| |
| arguments to this method are incorrect
|
-note: associated function defined here
+note: method defined here
--> $DIR/associated-type-projection-from-supertrait.rs:12:8
|
LL | fn chip_paint(&self, c: Self::Color) { }
diff --git a/tests/ui/associated-types/associated-types-eq-3.rs b/tests/ui/associated-types/associated-types-eq-3.rs
index f6988dcf6..380d0e95c 100644
--- a/tests/ui/associated-types/associated-types-eq-3.rs
+++ b/tests/ui/associated-types/associated-types-eq-3.rs
@@ -23,7 +23,7 @@ fn foo2<I: Foo>(x: I) {
let _: Bar = x.boo();
//~^ ERROR mismatched types
//~| found associated type `<I as Foo>::A`
- //~| expected struct `Bar`, found associated type
+ //~| expected `Bar`, found
//~| expected struct `Bar`
}
diff --git a/tests/ui/associated-types/associated-types-eq-3.stderr b/tests/ui/associated-types/associated-types-eq-3.stderr
index fbe1a1ee8..15ce4fc91 100644
--- a/tests/ui/associated-types/associated-types-eq-3.stderr
+++ b/tests/ui/associated-types/associated-types-eq-3.stderr
@@ -2,7 +2,7 @@ error[E0308]: mismatched types
--> $DIR/associated-types-eq-3.rs:23:18
|
LL | let _: Bar = x.boo();
- | --- ^^^^^^^ expected struct `Bar`, found associated type
+ | --- ^^^^^^^ expected `Bar`, found associated type
| |
| expected due to this
|
diff --git a/tests/ui/associated-types/associated-types-eq-hr.stderr b/tests/ui/associated-types/associated-types-eq-hr.stderr
index 6cff403b3..3e1142d5d 100644
--- a/tests/ui/associated-types/associated-types-eq-hr.stderr
+++ b/tests/ui/associated-types/associated-types-eq-hr.stderr
@@ -1,8 +1,8 @@
-error[E0271]: type mismatch resolving `for<'x> <UintStruct as TheTrait<&'x isize>>::A == &'x isize`
+error[E0271]: type mismatch resolving `<UintStruct as TheTrait<&isize>>::A == &isize`
--> $DIR/associated-types-eq-hr.rs:87:11
|
LL | foo::<UintStruct>();
- | ^^^^^^^^^^ type mismatch resolving `for<'x> <UintStruct as TheTrait<&'x isize>>::A == &'x isize`
+ | ^^^^^^^^^^ type mismatch resolving `<UintStruct as TheTrait<&isize>>::A == &isize`
|
note: expected this to be `&isize`
--> $DIR/associated-types-eq-hr.rs:26:14
@@ -15,16 +15,16 @@ note: required by a bound in `foo`
--> $DIR/associated-types-eq-hr.rs:45:36
|
LL | fn foo<T>()
- | --- required by a bound in this
+ | --- required by a bound in this function
LL | where
LL | T: for<'x> TheTrait<&'x isize, A = &'x isize>,
| ^^^^^^^^^^^^^ required by this bound in `foo`
-error[E0271]: type mismatch resolving `for<'x> <IntStruct as TheTrait<&'x isize>>::A == &'x usize`
+error[E0271]: type mismatch resolving `<IntStruct as TheTrait<&isize>>::A == &usize`
--> $DIR/associated-types-eq-hr.rs:91:11
|
LL | bar::<IntStruct>();
- | ^^^^^^^^^ type mismatch resolving `for<'x> <IntStruct as TheTrait<&'x isize>>::A == &'x usize`
+ | ^^^^^^^^^ type mismatch resolving `<IntStruct as TheTrait<&isize>>::A == &usize`
|
note: expected this to be `&usize`
--> $DIR/associated-types-eq-hr.rs:14:14
@@ -37,7 +37,7 @@ note: required by a bound in `bar`
--> $DIR/associated-types-eq-hr.rs:52:36
|
LL | fn bar<T>()
- | --- required by a bound in this
+ | --- required by a bound in this function
LL | where
LL | T: for<'x> TheTrait<&'x isize, A = &'x usize>,
| ^^^^^^^^^^^^^ required by this bound in `bar`
diff --git a/tests/ui/associated-types/associated-types-outlives.stderr b/tests/ui/associated-types/associated-types-outlives.stderr
index 840e33b4b..2fe3f2d4a 100644
--- a/tests/ui/associated-types/associated-types-outlives.stderr
+++ b/tests/ui/associated-types/associated-types-outlives.stderr
@@ -1,6 +1,9 @@
error[E0505]: cannot move out of `x` because it is borrowed
--> $DIR/associated-types-outlives.rs:22:14
|
+LL | F: for<'a> FnOnce(<T as Foo<'a>>::Bar)>(x: T, f: F) {
+ | - binding `x` declared here
+...
LL | 's: loop { y = denormalise(&x); break }
| -- borrow of `x` occurs here
LL | drop(x);
diff --git a/tests/ui/associated-types/defaults-in-other-trait-items.rs b/tests/ui/associated-types/defaults-in-other-trait-items.rs
index 505751969..f26380955 100644
--- a/tests/ui/associated-types/defaults-in-other-trait-items.rs
+++ b/tests/ui/associated-types/defaults-in-other-trait-items.rs
@@ -44,4 +44,18 @@ impl AssocConst for () {
const C: Self::Ty = 0u8;
}
+pub trait Trait {
+ type Res = isize; //~ NOTE associated type defaults can't be assumed inside the trait defining them
+
+ fn infer_me_correctly() -> Self::Res {
+ //~^ NOTE expected `<Self as Trait>::Res` because of return type
+
+ // {integer} == isize
+ 2
+ //~^ ERROR mismatched types
+ //~| NOTE expected associated type, found integer
+ //~| NOTE expected associated type `<Self as Trait>::Res`
+ }
+}
+
fn main() {}
diff --git a/tests/ui/associated-types/defaults-in-other-trait-items.stderr b/tests/ui/associated-types/defaults-in-other-trait-items.stderr
index 71d421926..bdcfadd39 100644
--- a/tests/ui/associated-types/defaults-in-other-trait-items.stderr
+++ b/tests/ui/associated-types/defaults-in-other-trait-items.stderr
@@ -24,6 +24,21 @@ LL | const C: Self::Ty = 0u8;
= note: expected associated type `<Self as AssocConst>::Ty`
found type `u8`
-error: aborting due to 2 previous errors
+error[E0308]: mismatched types
+ --> $DIR/defaults-in-other-trait-items.rs:54:9
+ |
+LL | type Res = isize;
+ | ----------------- associated type defaults can't be assumed inside the trait defining them
+LL |
+LL | fn infer_me_correctly() -> Self::Res {
+ | --------- expected `<Self as Trait>::Res` because of return type
+...
+LL | 2
+ | ^ expected associated type, found integer
+ |
+ = note: expected associated type `<Self as Trait>::Res`
+ found type `{integer}`
+
+error: aborting due to 3 previous errors
For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/associated-types/defaults-suitability.stderr b/tests/ui/associated-types/defaults-suitability.stderr
index eadad4cd5..248575875 100644
--- a/tests/ui/associated-types/defaults-suitability.stderr
+++ b/tests/ui/associated-types/defaults-suitability.stderr
@@ -27,7 +27,7 @@ LL | Self::Ty: Clone,
| ^^^^^ required by this bound in `Tr2::Ty`
LL | {
LL | type Ty = NotClone;
- | -- required by a bound in this
+ | -- required by a bound in this associated type
help: consider annotating `NotClone` with `#[derive(Clone)]`
|
LL | #[derive(Clone)]
@@ -75,7 +75,7 @@ LL | Self::Assoc: IsU8<Self::Assoc>,
| ^^^^^^^^^^^^^^^^^ required by this bound in `D::Assoc`
...
LL | type Assoc = NotClone;
- | ----- required by a bound in this
+ | ----- required by a bound in this associated type
error[E0277]: the trait bound `<Self as Foo2<T>>::Baz: Clone` is not satisfied
--> $DIR/defaults-suitability.rs:65:23
@@ -124,7 +124,7 @@ LL | Self::Baz: Clone,
| ^^^^^ required by this bound in `Foo3::Baz`
...
LL | type Baz = T;
- | --- required by a bound in this
+ | --- required by a bound in this associated type
help: consider further restricting type parameter `T`
|
LL | Self::Baz: Clone, T: std::clone::Clone
diff --git a/tests/ui/associated-types/hr-associated-type-bound-1.stderr b/tests/ui/associated-types/hr-associated-type-bound-1.stderr
index 73b5e1053..b380a1b6f 100644
--- a/tests/ui/associated-types/hr-associated-type-bound-1.stderr
+++ b/tests/ui/associated-types/hr-associated-type-bound-1.stderr
@@ -9,7 +9,7 @@ note: required by a bound in `X`
--> $DIR/hr-associated-type-bound-1.rs:3:33
|
LL | trait X<'a>
- | - required by a bound in this
+ | - required by a bound in this trait
LL | where
LL | for<'b> <Self as X<'b>>::U: Clone,
| ^^^^^ required by this bound in `X`
diff --git a/tests/ui/associated-types/hr-associated-type-bound-object.stderr b/tests/ui/associated-types/hr-associated-type-bound-object.stderr
index 6d19186bd..a0a6f76a5 100644
--- a/tests/ui/associated-types/hr-associated-type-bound-object.stderr
+++ b/tests/ui/associated-types/hr-associated-type-bound-object.stderr
@@ -8,7 +8,7 @@ note: required by a bound in `X`
--> $DIR/hr-associated-type-bound-object.rs:3:33
|
LL | trait X<'a>
- | - required by a bound in this
+ | - required by a bound in this trait
LL | where
LL | for<'b> <Self as X<'b>>::U: Clone,
| ^^^^^ required by this bound in `X`
diff --git a/tests/ui/associated-types/hr-associated-type-bound-param-1.stderr b/tests/ui/associated-types/hr-associated-type-bound-param-1.stderr
index af2e61689..e249f2e0c 100644
--- a/tests/ui/associated-types/hr-associated-type-bound-param-1.stderr
+++ b/tests/ui/associated-types/hr-associated-type-bound-param-1.stderr
@@ -9,7 +9,7 @@ note: required by a bound in `Y`
--> $DIR/hr-associated-type-bound-param-1.rs:4:36
|
LL | trait Y<'a, T: ?Sized>
- | - required by a bound in this
+ | - required by a bound in this trait
...
LL | for<'b> <Self as Y<'b, T>>::V: Clone,
| ^^^^^ required by this bound in `Y`
diff --git a/tests/ui/associated-types/hr-associated-type-bound-param-2.stderr b/tests/ui/associated-types/hr-associated-type-bound-param-2.stderr
index 52294f8c9..366670269 100644
--- a/tests/ui/associated-types/hr-associated-type-bound-param-2.stderr
+++ b/tests/ui/associated-types/hr-associated-type-bound-param-2.stderr
@@ -9,7 +9,7 @@ note: required by a bound in `Z`
--> $DIR/hr-associated-type-bound-param-2.rs:6:35
|
LL | trait Z<'a, T: ?Sized>
- | - required by a bound in this
+ | - required by a bound in this trait
...
LL | for<'b> <T as Z<'b, u16>>::W: Clone,
| ^^^^^ required by this bound in `Z`
@@ -25,7 +25,7 @@ note: required by a bound in `Z`
--> $DIR/hr-associated-type-bound-param-2.rs:6:35
|
LL | trait Z<'a, T: ?Sized>
- | - required by a bound in this
+ | - required by a bound in this trait
...
LL | for<'b> <T as Z<'b, u16>>::W: Clone,
| ^^^^^ required by this bound in `Z`
@@ -41,7 +41,7 @@ note: required by a bound in `Z`
--> $DIR/hr-associated-type-bound-param-2.rs:6:35
|
LL | trait Z<'a, T: ?Sized>
- | - required by a bound in this
+ | - required by a bound in this trait
...
LL | for<'b> <T as Z<'b, u16>>::W: Clone,
| ^^^^^ required by this bound in `Z`
diff --git a/tests/ui/associated-types/hr-associated-type-bound-param-3.stderr b/tests/ui/associated-types/hr-associated-type-bound-param-3.stderr
index 84d5e0494..f49439d35 100644
--- a/tests/ui/associated-types/hr-associated-type-bound-param-3.stderr
+++ b/tests/ui/associated-types/hr-associated-type-bound-param-3.stderr
@@ -9,7 +9,7 @@ note: required by a bound in `X`
--> $DIR/hr-associated-type-bound-param-3.rs:4:33
|
LL | trait X<'a, T>
- | - required by a bound in this
+ | - required by a bound in this trait
...
LL | for<'b> <T as X<'b, T>>::U: Clone,
| ^^^^^ required by this bound in `X`
diff --git a/tests/ui/associated-types/hr-associated-type-bound-param-4.stderr b/tests/ui/associated-types/hr-associated-type-bound-param-4.stderr
index ee1d5d324..f8733b423 100644
--- a/tests/ui/associated-types/hr-associated-type-bound-param-4.stderr
+++ b/tests/ui/associated-types/hr-associated-type-bound-param-4.stderr
@@ -9,7 +9,7 @@ note: required by a bound in `X`
--> $DIR/hr-associated-type-bound-param-4.rs:4:36
|
LL | trait X<'a, T>
- | - required by a bound in this
+ | - required by a bound in this trait
...
LL | for<'b> <(T,) as X<'b, T>>::U: Clone,
| ^^^^^ required by this bound in `X`
diff --git a/tests/ui/associated-types/hr-associated-type-bound-param-5.stderr b/tests/ui/associated-types/hr-associated-type-bound-param-5.stderr
index ece3151ba..aae80a9b2 100644
--- a/tests/ui/associated-types/hr-associated-type-bound-param-5.stderr
+++ b/tests/ui/associated-types/hr-associated-type-bound-param-5.stderr
@@ -9,7 +9,7 @@ note: required by a bound in `X`
--> $DIR/hr-associated-type-bound-param-5.rs:17:45
|
LL | trait X<'a, T: Cycle + for<'b> X<'b, T>>
- | - required by a bound in this
+ | - required by a bound in this trait
...
LL | for<'b> <T::Next as X<'b, T::Next>>::U: Clone,
| ^^^^^ required by this bound in `X`
@@ -25,7 +25,7 @@ note: required by a bound in `X`
--> $DIR/hr-associated-type-bound-param-5.rs:17:45
|
LL | trait X<'a, T: Cycle + for<'b> X<'b, T>>
- | - required by a bound in this
+ | - required by a bound in this trait
...
LL | for<'b> <T::Next as X<'b, T::Next>>::U: Clone,
| ^^^^^ required by this bound in `X`
diff --git a/tests/ui/associated-types/hr-associated-type-projection-1.stderr b/tests/ui/associated-types/hr-associated-type-projection-1.stderr
index a65f84ae5..dd0389c34 100644
--- a/tests/ui/associated-types/hr-associated-type-projection-1.stderr
+++ b/tests/ui/associated-types/hr-associated-type-projection-1.stderr
@@ -10,14 +10,14 @@ note: required by a bound in `UnsafeCopy`
--> $DIR/hr-associated-type-projection-1.rs:3:64
|
LL | trait UnsafeCopy<'a, T: Copy>
- | ---------- required by a bound in this
+ | ---------- required by a bound in this trait
LL | where
LL | for<'b> <Self as UnsafeCopy<'b, T>>::Item: std::ops::Deref<Target = T>,
| ^^^^^^^^^^ required by this bound in `UnsafeCopy`
help: consider further restricting this bound
|
-LL | impl<T: Copy + std::ops::Deref + Deref<Target = T>> UnsafeCopy<'_, T> for T {
- | +++++++++++++++++++
+LL | impl<T: Copy + std::ops::Deref<Target = T>> UnsafeCopy<'_, T> for T {
+ | ++++++++++++
error: aborting due to previous error
diff --git a/tests/ui/associated-types/issue-26681.stderr b/tests/ui/associated-types/issue-26681.stderr
index 74411008c..977620d90 100644
--- a/tests/ui/associated-types/issue-26681.stderr
+++ b/tests/ui/associated-types/issue-26681.stderr
@@ -1,13 +1,13 @@
error[E0308]: mismatched types
--> $DIR/issue-26681.rs:17:39
|
+LL | type Fv: Foo = u8;
+ | ------------------ associated type defaults can't be assumed inside the trait defining them
LL | const C: <Self::Fv as Foo>::Bar = 6665;
| ^^^^ expected associated type, found integer
|
= note: expected associated type `<<Self as Baz>::Fv as Foo>::Bar`
found type `{integer}`
- = help: consider constraining the associated type `<<Self as Baz>::Fv as Foo>::Bar` to `{integer}`
- = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html
error: aborting due to previous error
diff --git a/tests/ui/issues/issue-38821.rs b/tests/ui/associated-types/issue-38821.rs
index 6753860e9..6753860e9 100644
--- a/tests/ui/issues/issue-38821.rs
+++ b/tests/ui/associated-types/issue-38821.rs
diff --git a/tests/ui/issues/issue-38821.stderr b/tests/ui/associated-types/issue-38821.stderr
index a52a9c138..a52a9c138 100644
--- a/tests/ui/issues/issue-38821.stderr
+++ b/tests/ui/associated-types/issue-38821.stderr
diff --git a/tests/ui/associated-types/issue-43924.stderr b/tests/ui/associated-types/issue-43924.stderr
index 526f425b2..ab1a9511e 100644
--- a/tests/ui/associated-types/issue-43924.stderr
+++ b/tests/ui/associated-types/issue-43924.stderr
@@ -14,7 +14,7 @@ error[E0599]: no function or associated item named `default` found for trait obj
--> $DIR/issue-43924.rs:14:39
|
LL | assert_eq!(<() as Foo<u32>>::Out::default().to_string(), "false");
- | ^^^^^^^ function or associated item not found in `(dyn ToString + 'static)`
+ | ^^^^^^^ function or associated item not found in `dyn ToString`
error: aborting due to 2 previous errors
diff --git a/tests/ui/associated-types/issue-87261.rs b/tests/ui/associated-types/issue-87261.rs
index e8548d402..384561f8c 100644
--- a/tests/ui/associated-types/issue-87261.rs
+++ b/tests/ui/associated-types/issue-87261.rs
@@ -77,10 +77,10 @@ where
fn main() {
accepts_trait(returns_opaque());
- //~^ ERROR type mismatch resolving `<impl Trait + 'static as Trait>::Associated == ()`
+ //~^ ERROR type mismatch resolving `<impl Trait as Trait>::Associated == ()`
accepts_trait(returns_opaque_derived());
- //~^ ERROR type mismatch resolving `<impl DerivedTrait + 'static as Trait>::Associated == ()`
+ //~^ ERROR type mismatch resolving `<impl DerivedTrait as Trait>::Associated == ()`
accepts_trait(returns_opaque_foo());
//~^ ERROR type mismatch resolving `<impl Trait + Foo as Trait>::Associated == ()`
@@ -89,7 +89,7 @@ fn main() {
//~^ ERROR type mismatch resolving `<impl DerivedTrait + Foo as Trait>::Associated == ()`
accepts_generic_trait(returns_opaque_generic());
- //~^ ERROR type mismatch resolving `<impl GenericTrait<()> + 'static as GenericTrait<()>>::Associated == ()`
+ //~^ ERROR type mismatch resolving `<impl GenericTrait<()> as GenericTrait<()>>::Associated == ()`
accepts_generic_trait(returns_opaque_generic_foo());
//~^ ERROR type mismatch resolving `<impl GenericTrait<()> + Foo as GenericTrait<()>>::Associated == ()`
diff --git a/tests/ui/associated-types/issue-87261.stderr b/tests/ui/associated-types/issue-87261.stderr
index 2cce6b947..f5c6d8247 100644
--- a/tests/ui/associated-types/issue-87261.stderr
+++ b/tests/ui/associated-types/issue-87261.stderr
@@ -132,7 +132,7 @@ note: required by a bound in `accepts_generic_trait`
LL | fn accepts_generic_trait<T: GenericTrait<(), Associated = ()>>(_: T) {}
| ^^^^^^^^^^^^^^^ required by this bound in `accepts_generic_trait`
-error[E0271]: type mismatch resolving `<impl Trait + 'static as Trait>::Associated == ()`
+error[E0271]: type mismatch resolving `<impl Trait as Trait>::Associated == ()`
--> $DIR/issue-87261.rs:79:19
|
LL | fn returns_opaque() -> impl Trait + 'static {
@@ -155,7 +155,7 @@ help: consider constraining the associated type `<impl Trait + 'static as Trait>
LL | fn returns_opaque() -> impl Trait<Associated = ()> + 'static {
| +++++++++++++++++
-error[E0271]: type mismatch resolving `<impl DerivedTrait + 'static as Trait>::Associated == ()`
+error[E0271]: type mismatch resolving `<impl DerivedTrait as Trait>::Associated == ()`
--> $DIR/issue-87261.rs:82:19
|
LL | fn returns_opaque_derived() -> impl DerivedTrait + 'static {
@@ -222,7 +222,7 @@ note: required by a bound in `accepts_trait`
LL | fn accepts_trait<T: Trait<Associated = ()>>(_: T) {}
| ^^^^^^^^^^^^^^^ required by this bound in `accepts_trait`
-error[E0271]: type mismatch resolving `<impl GenericTrait<()> + 'static as GenericTrait<()>>::Associated == ()`
+error[E0271]: type mismatch resolving `<impl GenericTrait<()> as GenericTrait<()>>::Associated == ()`
--> $DIR/issue-87261.rs:91:27
|
LL | fn returns_opaque_generic() -> impl GenericTrait<()> + 'static {
diff --git a/tests/ui/associated-types/point-at-type-on-obligation-failure-2.stderr b/tests/ui/associated-types/point-at-type-on-obligation-failure-2.stderr
index 2e7a1dd2a..3b4689e08 100644
--- a/tests/ui/associated-types/point-at-type-on-obligation-failure-2.stderr
+++ b/tests/ui/associated-types/point-at-type-on-obligation-failure-2.stderr
@@ -23,7 +23,7 @@ LL | Self::Assoc: Bar,
| ^^^ required by this bound in `Baz::Assoc`
LL | {
LL | type Assoc;
- | ----- required by a bound in this
+ | ----- required by a bound in this associated type
error[E0277]: the trait bound `bool: Bar` is not satisfied
--> $DIR/point-at-type-on-obligation-failure-2.rs:30:18
@@ -38,7 +38,7 @@ LL | <Self as Bat>::Assoc: Bar,
| ^^^ required by this bound in `Bat::Assoc`
LL | {
LL | type Assoc;
- | ----- required by a bound in this
+ | ----- required by a bound in this associated type
error: aborting due to 3 previous errors
diff --git a/tests/ui/async-await/async-await-let-else.drop_tracking.stderr b/tests/ui/async-await/async-await-let-else.drop_tracking.stderr
new file mode 100644
index 000000000..fb83ca90a
--- /dev/null
+++ b/tests/ui/async-await/async-await-let-else.drop_tracking.stderr
@@ -0,0 +1,106 @@
+error: future cannot be sent between threads safely
+ --> $DIR/async-await-let-else.rs:48:13
+ |
+LL | is_send(foo(Some(true)));
+ | ^^^^^^^^^^^^^^^ future returned by `foo` is not `Send`
+ |
+ = help: within `impl Future<Output = ()>`, the trait `Send` is not implemented for `Rc<()>`
+note: future is not `Send` as this value is used across an await
+ --> $DIR/async-await-let-else.rs:11:14
+ |
+LL | let r = Rc::new(());
+ | - has type `Rc<()>` which is not `Send`
+LL | bar().await
+ | ^^^^^^ await occurs here, with `r` maybe used later
+LL | };
+ | - `r` is later dropped here
+note: required by a bound in `is_send`
+ --> $DIR/async-await-let-else.rs:19:15
+ |
+LL | fn is_send<T: Send>(_: T) {}
+ | ^^^^ required by this bound in `is_send`
+
+error[E0277]: `Rc<()>` cannot be sent between threads safely
+ --> $DIR/async-await-let-else.rs:50:13
+ |
+LL | async fn foo2(x: Option<bool>) {
+ | - within this `impl Future<Output = ()>`
+...
+LL | is_send(foo2(Some(true)));
+ | ------- ^^^^^^^^^^^^^^^^ `Rc<()>` cannot be sent between threads safely
+ | |
+ | required by a bound introduced by this call
+ |
+ = help: within `impl Future<Output = ()>`, the trait `Send` is not implemented for `Rc<()>`
+note: required because it's used within this `async fn` body
+ --> $DIR/async-await-let-else.rs:27:29
+ |
+LL | async fn bar2<T>(_: T) -> ! {
+ | _____________________________^
+LL | | panic!()
+LL | | }
+ | |_^
+ = note: required because it captures the following types: `ResumeTy`, `Option<bool>`, `impl Future<Output = !>`, `()`
+note: required because it's used within this `async fn` body
+ --> $DIR/async-await-let-else.rs:21:32
+ |
+LL | async fn foo2(x: Option<bool>) {
+ | ________________________________^
+LL | | let Some(_) = x else {
+LL | | bar2(Rc::new(())).await
+LL | | };
+LL | | }
+ | |_^
+note: required by a bound in `is_send`
+ --> $DIR/async-await-let-else.rs:19:15
+ |
+LL | fn is_send<T: Send>(_: T) {}
+ | ^^^^ required by this bound in `is_send`
+
+error: future cannot be sent between threads safely
+ --> $DIR/async-await-let-else.rs:52:13
+ |
+LL | is_send(foo3(Some(true)));
+ | ^^^^^^^^^^^^^^^^ future returned by `foo3` is not `Send`
+ |
+ = help: within `impl Future<Output = ()>`, the trait `Send` is not implemented for `Rc<()>`
+note: future is not `Send` as this value is used across an await
+ --> $DIR/async-await-let-else.rs:33:28
+ |
+LL | (Rc::new(()), bar().await);
+ | ----------- ^^^^^^ - `Rc::new(())` is later dropped here
+ | | |
+ | | await occurs here, with `Rc::new(())` maybe used later
+ | has type `Rc<()>` which is not `Send`
+note: required by a bound in `is_send`
+ --> $DIR/async-await-let-else.rs:19:15
+ |
+LL | fn is_send<T: Send>(_: T) {}
+ | ^^^^ required by this bound in `is_send`
+
+error: future cannot be sent between threads safely
+ --> $DIR/async-await-let-else.rs:54:13
+ |
+LL | is_send(foo4(Some(true)));
+ | ^^^^^^^^^^^^^^^^ future returned by `foo4` is not `Send`
+ |
+ = help: within `impl Future<Output = ()>`, the trait `Send` is not implemented for `Rc<()>`
+note: future is not `Send` as this value is used across an await
+ --> $DIR/async-await-let-else.rs:41:14
+ |
+LL | let r = Rc::new(());
+ | - has type `Rc<()>` which is not `Send`
+LL | bar().await;
+ | ^^^^^^ await occurs here, with `r` maybe used later
+...
+LL | };
+ | - `r` is later dropped here
+note: required by a bound in `is_send`
+ --> $DIR/async-await-let-else.rs:19:15
+ |
+LL | fn is_send<T: Send>(_: T) {}
+ | ^^^^ required by this bound in `is_send`
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/async-await/async-await-let-else.drop_tracking_mir.stderr b/tests/ui/async-await/async-await-let-else.drop_tracking_mir.stderr
new file mode 100644
index 000000000..c284bbfb1
--- /dev/null
+++ b/tests/ui/async-await/async-await-let-else.drop_tracking_mir.stderr
@@ -0,0 +1,100 @@
+error: future cannot be sent between threads safely
+ --> $DIR/async-await-let-else.rs:48:13
+ |
+LL | is_send(foo(Some(true)));
+ | ^^^^^^^^^^^^^^^ future returned by `foo` is not `Send`
+ |
+ = help: within `impl Future<Output = ()>`, the trait `Send` is not implemented for `Rc<()>`
+note: future is not `Send` as this value is used across an await
+ --> $DIR/async-await-let-else.rs:11:14
+ |
+LL | let r = Rc::new(());
+ | - has type `Rc<()>` which is not `Send`
+LL | bar().await
+ | ^^^^^^ await occurs here, with `r` maybe used later
+note: required by a bound in `is_send`
+ --> $DIR/async-await-let-else.rs:19:15
+ |
+LL | fn is_send<T: Send>(_: T) {}
+ | ^^^^ required by this bound in `is_send`
+
+error[E0277]: `Rc<()>` cannot be sent between threads safely
+ --> $DIR/async-await-let-else.rs:50:13
+ |
+LL | async fn foo2(x: Option<bool>) {
+ | - within this `impl Future<Output = ()>`
+...
+LL | is_send(foo2(Some(true)));
+ | ------- ^^^^^^^^^^^^^^^^ `Rc<()>` cannot be sent between threads safely
+ | |
+ | required by a bound introduced by this call
+ |
+ = help: within `impl Future<Output = ()>`, the trait `Send` is not implemented for `Rc<()>`
+note: required because it's used within this `async fn` body
+ --> $DIR/async-await-let-else.rs:27:29
+ |
+LL | async fn bar2<T>(_: T) -> ! {
+ | _____________________________^
+LL | | panic!()
+LL | | }
+ | |_^
+ = note: required because it captures the following types: `impl Future<Output = !>`
+note: required because it's used within this `async fn` body
+ --> $DIR/async-await-let-else.rs:21:32
+ |
+LL | async fn foo2(x: Option<bool>) {
+ | ________________________________^
+LL | | let Some(_) = x else {
+LL | | bar2(Rc::new(())).await
+LL | | };
+LL | | }
+ | |_^
+note: required by a bound in `is_send`
+ --> $DIR/async-await-let-else.rs:19:15
+ |
+LL | fn is_send<T: Send>(_: T) {}
+ | ^^^^ required by this bound in `is_send`
+
+error: future cannot be sent between threads safely
+ --> $DIR/async-await-let-else.rs:52:13
+ |
+LL | is_send(foo3(Some(true)));
+ | ^^^^^^^^^^^^^^^^ future returned by `foo3` is not `Send`
+ |
+ = help: within `impl Future<Output = ()>`, the trait `Send` is not implemented for `Rc<()>`
+note: future is not `Send` as this value is used across an await
+ --> $DIR/async-await-let-else.rs:33:28
+ |
+LL | (Rc::new(()), bar().await);
+ | ----------- ^^^^^^ await occurs here, with `Rc::new(())` maybe used later
+ | |
+ | has type `Rc<()>` which is not `Send`
+note: required by a bound in `is_send`
+ --> $DIR/async-await-let-else.rs:19:15
+ |
+LL | fn is_send<T: Send>(_: T) {}
+ | ^^^^ required by this bound in `is_send`
+
+error: future cannot be sent between threads safely
+ --> $DIR/async-await-let-else.rs:54:13
+ |
+LL | is_send(foo4(Some(true)));
+ | ^^^^^^^^^^^^^^^^ future returned by `foo4` is not `Send`
+ |
+ = help: within `impl Future<Output = ()>`, the trait `Send` is not implemented for `Rc<()>`
+note: future is not `Send` as this value is used across an await
+ --> $DIR/async-await-let-else.rs:41:14
+ |
+LL | let r = Rc::new(());
+ | - has type `Rc<()>` which is not `Send`
+LL | bar().await;
+ | ^^^^^^ await occurs here, with `r` maybe used later
+note: required by a bound in `is_send`
+ --> $DIR/async-await-let-else.rs:19:15
+ |
+LL | fn is_send<T: Send>(_: T) {}
+ | ^^^^ required by this bound in `is_send`
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/async-await/async-await-let-else.no_drop_tracking.stderr b/tests/ui/async-await/async-await-let-else.no_drop_tracking.stderr
new file mode 100644
index 000000000..d3c5e80a3
--- /dev/null
+++ b/tests/ui/async-await/async-await-let-else.no_drop_tracking.stderr
@@ -0,0 +1,90 @@
+error: future cannot be sent between threads safely
+ --> $DIR/async-await-let-else.rs:48:13
+ |
+LL | is_send(foo(Some(true)));
+ | ^^^^^^^^^^^^^^^ future returned by `foo` is not `Send`
+ |
+ = help: within `impl Future<Output = ()>`, the trait `Send` is not implemented for `Rc<()>`
+note: future is not `Send` as this value is used across an await
+ --> $DIR/async-await-let-else.rs:11:14
+ |
+LL | let r = Rc::new(());
+ | - has type `Rc<()>` which is not `Send`
+LL | bar().await
+ | ^^^^^^ await occurs here, with `r` maybe used later
+LL | };
+ | - `r` is later dropped here
+note: required by a bound in `is_send`
+ --> $DIR/async-await-let-else.rs:19:15
+ |
+LL | fn is_send<T: Send>(_: T) {}
+ | ^^^^ required by this bound in `is_send`
+
+error: future cannot be sent between threads safely
+ --> $DIR/async-await-let-else.rs:50:13
+ |
+LL | is_send(foo2(Some(true)));
+ | ^^^^^^^^^^^^^^^^ future returned by `foo2` is not `Send`
+ |
+ = help: within `impl Future<Output = ()>`, the trait `Send` is not implemented for `Rc<()>`
+note: future is not `Send` as this value is used across an await
+ --> $DIR/async-await-let-else.rs:23:26
+ |
+LL | bar2(Rc::new(())).await
+ | ----------- ^^^^^^ await occurs here, with `Rc::new(())` maybe used later
+ | |
+ | has type `Rc<()>` which is not `Send`
+LL | };
+ | - `Rc::new(())` is later dropped here
+note: required by a bound in `is_send`
+ --> $DIR/async-await-let-else.rs:19:15
+ |
+LL | fn is_send<T: Send>(_: T) {}
+ | ^^^^ required by this bound in `is_send`
+
+error: future cannot be sent between threads safely
+ --> $DIR/async-await-let-else.rs:52:13
+ |
+LL | is_send(foo3(Some(true)));
+ | ^^^^^^^^^^^^^^^^ future returned by `foo3` is not `Send`
+ |
+ = help: within `impl Future<Output = ()>`, the trait `Send` is not implemented for `Rc<()>`
+note: future is not `Send` as this value is used across an await
+ --> $DIR/async-await-let-else.rs:33:28
+ |
+LL | (Rc::new(()), bar().await);
+ | ----------- ^^^^^^ - `Rc::new(())` is later dropped here
+ | | |
+ | | await occurs here, with `Rc::new(())` maybe used later
+ | has type `Rc<()>` which is not `Send`
+note: required by a bound in `is_send`
+ --> $DIR/async-await-let-else.rs:19:15
+ |
+LL | fn is_send<T: Send>(_: T) {}
+ | ^^^^ required by this bound in `is_send`
+
+error: future cannot be sent between threads safely
+ --> $DIR/async-await-let-else.rs:54:13
+ |
+LL | is_send(foo4(Some(true)));
+ | ^^^^^^^^^^^^^^^^ future returned by `foo4` is not `Send`
+ |
+ = help: within `impl Future<Output = ()>`, the trait `Send` is not implemented for `Rc<()>`
+note: future is not `Send` as this value is used across an await
+ --> $DIR/async-await-let-else.rs:41:14
+ |
+LL | let r = Rc::new(());
+ | - has type `Rc<()>` which is not `Send`
+LL | bar().await;
+ | ^^^^^^ await occurs here, with `r` maybe used later
+...
+LL | };
+ | - `r` is later dropped here
+note: required by a bound in `is_send`
+ --> $DIR/async-await-let-else.rs:19:15
+ |
+LL | fn is_send<T: Send>(_: T) {}
+ | ^^^^ required by this bound in `is_send`
+
+error: aborting due to 4 previous errors
+
diff --git a/tests/ui/async-await/async-await-let-else.rs b/tests/ui/async-await/async-await-let-else.rs
index 3fb2142b9..113d576b5 100644
--- a/tests/ui/async-await/async-await-let-else.rs
+++ b/tests/ui/async-await/async-await-let-else.rs
@@ -1,7 +1,7 @@
// edition:2021
-// revisions: drop-tracking no-drop-tracking
-// [drop-tracking] compile-flags: -Zdrop-tracking=yes
-// [no-drop-tracking] compile-flags: -Zdrop-tracking=no
+// revisions: no_drop_tracking drop_tracking drop_tracking_mir
+// [drop_tracking] compile-flags: -Zdrop-tracking
+// [drop_tracking_mir] compile-flags: -Zdrop-tracking-mir
use std::rc::Rc;
diff --git a/tests/ui/async-await/async-block-control-flow-static-semantics.stderr b/tests/ui/async-await/async-block-control-flow-static-semantics.stderr
index c4487eb84..a6dbb0716 100644
--- a/tests/ui/async-await/async-block-control-flow-static-semantics.stderr
+++ b/tests/ui/async-await/async-block-control-flow-static-semantics.stderr
@@ -57,7 +57,7 @@ error[E0308]: mismatched types
--> $DIR/async-block-control-flow-static-semantics.rs:49:44
|
LL | fn rethrow_targets_async_block_not_fn() -> Result<u8, MyErr> {
- | ---------------------------------- ^^^^^^^^^^^^^^^^^ expected enum `Result`, found `()`
+ | ---------------------------------- ^^^^^^^^^^^^^^^^^ expected `Result<u8, MyErr>`, found `()`
| |
| implicitly returns `()` as its body has no tail or `return` expression
|
@@ -68,7 +68,7 @@ error[E0308]: mismatched types
--> $DIR/async-block-control-flow-static-semantics.rs:58:50
|
LL | fn rethrow_targets_async_block_not_async_fn() -> Result<u8, MyErr> {
- | ---------------------------------------- ^^^^^^^^^^^^^^^^^ expected enum `Result`, found `()`
+ | ---------------------------------------- ^^^^^^^^^^^^^^^^^ expected `Result<u8, MyErr>`, found `()`
| |
| implicitly returns `()` as its body has no tail or `return` expression
|
diff --git a/tests/ui/async-await/async-error-span.stderr b/tests/ui/async-await/async-error-span.drop_tracking.stderr
index 7d4447b6d..c6257cb32 100644
--- a/tests/ui/async-await/async-error-span.stderr
+++ b/tests/ui/async-await/async-error-span.drop_tracking.stderr
@@ -1,5 +1,5 @@
error[E0277]: `()` is not a future
- --> $DIR/async-error-span.rs:7:20
+ --> $DIR/async-error-span.rs:10:20
|
LL | fn get_future() -> impl Future<Output = ()> {
| ^^^^^^^^^^^^^^^^^^^^^^^^ `()` is not a future
@@ -8,13 +8,13 @@ LL | fn get_future() -> impl Future<Output = ()> {
= note: () must be a future or must implement `IntoFuture` to be awaited
error[E0698]: type inside `async fn` body must be known in this context
- --> $DIR/async-error-span.rs:13:9
+ --> $DIR/async-error-span.rs:16:9
|
LL | let a;
| ^ cannot infer type
|
note: the type is part of the `async fn` body because of this `await`
- --> $DIR/async-error-span.rs:14:17
+ --> $DIR/async-error-span.rs:19:17
|
LL | get_future().await;
| ^^^^^^
diff --git a/tests/ui/async-await/async-error-span.drop_tracking_mir.stderr b/tests/ui/async-await/async-error-span.drop_tracking_mir.stderr
new file mode 100644
index 000000000..2f29ee6cd
--- /dev/null
+++ b/tests/ui/async-await/async-error-span.drop_tracking_mir.stderr
@@ -0,0 +1,24 @@
+error[E0277]: `()` is not a future
+ --> $DIR/async-error-span.rs:10:20
+ |
+LL | fn get_future() -> impl Future<Output = ()> {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^ `()` is not a future
+ |
+ = help: the trait `Future` is not implemented for `()`
+ = note: () must be a future or must implement `IntoFuture` to be awaited
+
+error[E0282]: type annotations needed
+ --> $DIR/async-error-span.rs:16:9
+ |
+LL | let a;
+ | ^
+ |
+help: consider giving `a` an explicit type
+ |
+LL | let a: /* Type */;
+ | ++++++++++++
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0277, E0282.
+For more information about an error, try `rustc --explain E0277`.
diff --git a/tests/ui/async-await/async-error-span.no_drop_tracking.stderr b/tests/ui/async-await/async-error-span.no_drop_tracking.stderr
new file mode 100644
index 000000000..c6257cb32
--- /dev/null
+++ b/tests/ui/async-await/async-error-span.no_drop_tracking.stderr
@@ -0,0 +1,25 @@
+error[E0277]: `()` is not a future
+ --> $DIR/async-error-span.rs:10:20
+ |
+LL | fn get_future() -> impl Future<Output = ()> {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^ `()` is not a future
+ |
+ = help: the trait `Future` is not implemented for `()`
+ = note: () must be a future or must implement `IntoFuture` to be awaited
+
+error[E0698]: type inside `async fn` body must be known in this context
+ --> $DIR/async-error-span.rs:16:9
+ |
+LL | let a;
+ | ^ cannot infer type
+ |
+note: the type is part of the `async fn` body because of this `await`
+ --> $DIR/async-error-span.rs:19:17
+ |
+LL | get_future().await;
+ | ^^^^^^
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0277, E0698.
+For more information about an error, try `rustc --explain E0277`.
diff --git a/tests/ui/async-await/async-error-span.rs b/tests/ui/async-await/async-error-span.rs
index 86d459bf0..c9ecf359e 100644
--- a/tests/ui/async-await/async-error-span.rs
+++ b/tests/ui/async-await/async-error-span.rs
@@ -1,3 +1,6 @@
+// revisions: no_drop_tracking drop_tracking drop_tracking_mir
+// [drop_tracking] compile-flags: -Zdrop-tracking
+// [drop_tracking_mir] compile-flags: -Zdrop-tracking-mir
// edition:2018
// Regression test for issue #62382.
@@ -10,7 +13,9 @@ fn get_future() -> impl Future<Output = ()> {
}
async fn foo() {
- let a; //~ ERROR type inside `async fn` body must be known in this context
+ let a;
+ //[no_drop_tracking,drop_tracking]~^ ERROR type inside `async fn` body must be known in this context
+ //[drop_tracking_mir]~^^ ERROR type annotations needed
get_future().await;
}
diff --git a/tests/ui/async-await/async-fn-nonsend.drop_tracking.stderr b/tests/ui/async-await/async-fn-nonsend.drop_tracking.stderr
new file mode 100644
index 000000000..0f0dc335e
--- /dev/null
+++ b/tests/ui/async-await/async-fn-nonsend.drop_tracking.stderr
@@ -0,0 +1,49 @@
+error: future cannot be sent between threads safely
+ --> $DIR/async-fn-nonsend.rs:72:17
+ |
+LL | assert_send(non_send_temporary_in_match());
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ future returned by `non_send_temporary_in_match` is not `Send`
+ |
+ = help: within `impl Future<Output = ()>`, the trait `Send` is not implemented for `Rc<()>`
+note: future is not `Send` as this value is used across an await
+ --> $DIR/async-fn-nonsend.rs:36:25
+ |
+LL | match Some(non_send()) {
+ | ---------------- has type `Option<impl Debug>` which is not `Send`
+LL | Some(_) => fut().await,
+ | ^^^^^^ await occurs here, with `Some(non_send())` maybe used later
+...
+LL | }
+ | - `Some(non_send())` is later dropped here
+note: required by a bound in `assert_send`
+ --> $DIR/async-fn-nonsend.rs:67:24
+ |
+LL | fn assert_send(_: impl Send) {}
+ | ^^^^ required by this bound in `assert_send`
+
+error: future cannot be sent between threads safely
+ --> $DIR/async-fn-nonsend.rs:74:17
+ |
+LL | assert_send(non_sync_with_method_call());
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ future returned by `non_sync_with_method_call` is not `Send`
+ |
+ = help: within `impl Future<Output = ()>`, the trait `Send` is not implemented for `dyn std::fmt::Write`
+note: future is not `Send` as this value is used across an await
+ --> $DIR/async-fn-nonsend.rs:49:14
+ |
+LL | let f: &mut std::fmt::Formatter = &mut get_formatter();
+ | --------------- has type `Formatter<'_>` which is not `Send`
+...
+LL | fut().await;
+ | ^^^^^^ await occurs here, with `get_formatter()` maybe used later
+LL | }
+LL | }
+ | - `get_formatter()` is later dropped here
+note: required by a bound in `assert_send`
+ --> $DIR/async-fn-nonsend.rs:67:24
+ |
+LL | fn assert_send(_: impl Send) {}
+ | ^^^^ required by this bound in `assert_send`
+
+error: aborting due to 2 previous errors
+
diff --git a/tests/ui/async-await/async-fn-nonsend.drop_tracking_mir.stderr b/tests/ui/async-await/async-fn-nonsend.drop_tracking_mir.stderr
new file mode 100644
index 000000000..57a012801
--- /dev/null
+++ b/tests/ui/async-await/async-fn-nonsend.drop_tracking_mir.stderr
@@ -0,0 +1,43 @@
+error: future cannot be sent between threads safely
+ --> $DIR/async-fn-nonsend.rs:72:17
+ |
+LL | assert_send(non_send_temporary_in_match());
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ future returned by `non_send_temporary_in_match` is not `Send`
+ |
+ = help: within `impl Future<Output = ()>`, the trait `Send` is not implemented for `Rc<()>`
+note: future is not `Send` as this value is used across an await
+ --> $DIR/async-fn-nonsend.rs:36:25
+ |
+LL | match Some(non_send()) {
+ | ---------------- has type `Option<impl Debug>` which is not `Send`
+LL | Some(_) => fut().await,
+ | ^^^^^^ await occurs here, with `Some(non_send())` maybe used later
+note: required by a bound in `assert_send`
+ --> $DIR/async-fn-nonsend.rs:67:24
+ |
+LL | fn assert_send(_: impl Send) {}
+ | ^^^^ required by this bound in `assert_send`
+
+error: future cannot be sent between threads safely
+ --> $DIR/async-fn-nonsend.rs:74:17
+ |
+LL | assert_send(non_sync_with_method_call());
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ future returned by `non_sync_with_method_call` is not `Send`
+ |
+ = help: within `impl Future<Output = ()>`, the trait `Send` is not implemented for `dyn std::fmt::Write`
+note: future is not `Send` as this value is used across an await
+ --> $DIR/async-fn-nonsend.rs:49:14
+ |
+LL | let f: &mut std::fmt::Formatter = &mut get_formatter();
+ | --------------- has type `Formatter<'_>` which is not `Send`
+...
+LL | fut().await;
+ | ^^^^^^ await occurs here, with `get_formatter()` maybe used later
+note: required by a bound in `assert_send`
+ --> $DIR/async-fn-nonsend.rs:67:24
+ |
+LL | fn assert_send(_: impl Send) {}
+ | ^^^^ required by this bound in `assert_send`
+
+error: aborting due to 2 previous errors
+
diff --git a/tests/ui/async-await/async-fn-nonsend.no_drop_tracking.stderr b/tests/ui/async-await/async-fn-nonsend.no_drop_tracking.stderr
new file mode 100644
index 000000000..5cec21d89
--- /dev/null
+++ b/tests/ui/async-await/async-fn-nonsend.no_drop_tracking.stderr
@@ -0,0 +1,120 @@
+error: future cannot be sent between threads safely
+ --> $DIR/async-fn-nonsend.rs:70:17
+ |
+LL | assert_send(local_dropped_before_await());
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ future returned by `local_dropped_before_await` is not `Send`
+ |
+ = help: within `impl Future<Output = ()>`, the trait `Send` is not implemented for `Rc<()>`
+note: future is not `Send` as this value is used across an await
+ --> $DIR/async-fn-nonsend.rs:27:10
+ |
+LL | let x = non_send();
+ | - has type `impl Debug` which is not `Send`
+LL | drop(x);
+LL | fut().await;
+ | ^^^^^^ await occurs here, with `x` maybe used later
+LL | }
+ | - `x` is later dropped here
+note: required by a bound in `assert_send`
+ --> $DIR/async-fn-nonsend.rs:67:24
+ |
+LL | fn assert_send(_: impl Send) {}
+ | ^^^^ required by this bound in `assert_send`
+
+error: future cannot be sent between threads safely
+ --> $DIR/async-fn-nonsend.rs:72:17
+ |
+LL | assert_send(non_send_temporary_in_match());
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ future returned by `non_send_temporary_in_match` is not `Send`
+ |
+ = help: within `impl Future<Output = ()>`, the trait `Send` is not implemented for `Rc<()>`
+note: future is not `Send` as this value is used across an await
+ --> $DIR/async-fn-nonsend.rs:36:25
+ |
+LL | match Some(non_send()) {
+ | ---------- has type `impl Debug` which is not `Send`
+LL | Some(_) => fut().await,
+ | ^^^^^^ await occurs here, with `non_send()` maybe used later
+...
+LL | }
+ | - `non_send()` is later dropped here
+note: required by a bound in `assert_send`
+ --> $DIR/async-fn-nonsend.rs:67:24
+ |
+LL | fn assert_send(_: impl Send) {}
+ | ^^^^ required by this bound in `assert_send`
+
+error: future cannot be sent between threads safely
+ --> $DIR/async-fn-nonsend.rs:74:17
+ |
+LL | assert_send(non_sync_with_method_call());
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ future returned by `non_sync_with_method_call` is not `Send`
+ |
+ = help: within `impl Future<Output = ()>`, the trait `Send` is not implemented for `dyn std::fmt::Write`
+note: future is not `Send` as this value is used across an await
+ --> $DIR/async-fn-nonsend.rs:49:14
+ |
+LL | let f: &mut std::fmt::Formatter = &mut get_formatter();
+ | --------------- has type `Formatter<'_>` which is not `Send`
+...
+LL | fut().await;
+ | ^^^^^^ await occurs here, with `get_formatter()` maybe used later
+LL | }
+LL | }
+ | - `get_formatter()` is later dropped here
+note: required by a bound in `assert_send`
+ --> $DIR/async-fn-nonsend.rs:67:24
+ |
+LL | fn assert_send(_: impl Send) {}
+ | ^^^^ required by this bound in `assert_send`
+
+error: future cannot be sent between threads safely
+ --> $DIR/async-fn-nonsend.rs:76:17
+ |
+LL | assert_send(non_sync_with_method_call_panic());
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ future returned by `non_sync_with_method_call_panic` is not `Send`
+ |
+ = help: within `impl Future<Output = ()>`, the trait `Send` is not implemented for `dyn std::fmt::Write`
+note: future is not `Send` as this value is used across an await
+ --> $DIR/async-fn-nonsend.rs:56:14
+ |
+LL | let f: &mut std::fmt::Formatter = panic!();
+ | - has type `&mut Formatter<'_>` which is not `Send`
+LL | if non_sync().fmt(f).unwrap() == () {
+LL | fut().await;
+ | ^^^^^^ await occurs here, with `f` maybe used later
+LL | }
+LL | }
+ | - `f` is later dropped here
+note: required by a bound in `assert_send`
+ --> $DIR/async-fn-nonsend.rs:67:24
+ |
+LL | fn assert_send(_: impl Send) {}
+ | ^^^^ required by this bound in `assert_send`
+
+error: future cannot be sent between threads safely
+ --> $DIR/async-fn-nonsend.rs:78:17
+ |
+LL | assert_send(non_sync_with_method_call_infinite_loop());
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ future returned by `non_sync_with_method_call_infinite_loop` is not `Send`
+ |
+ = help: within `impl Future<Output = ()>`, the trait `Send` is not implemented for `dyn std::fmt::Write`
+note: future is not `Send` as this value is used across an await
+ --> $DIR/async-fn-nonsend.rs:63:14
+ |
+LL | let f: &mut std::fmt::Formatter = loop {};
+ | - has type `&mut Formatter<'_>` which is not `Send`
+LL | if non_sync().fmt(f).unwrap() == () {
+LL | fut().await;
+ | ^^^^^^ await occurs here, with `f` maybe used later
+LL | }
+LL | }
+ | - `f` is later dropped here
+note: required by a bound in `assert_send`
+ --> $DIR/async-fn-nonsend.rs:67:24
+ |
+LL | fn assert_send(_: impl Send) {}
+ | ^^^^ required by this bound in `assert_send`
+
+error: aborting due to 5 previous errors
+
diff --git a/tests/ui/async-await/async-fn-nonsend.rs b/tests/ui/async-await/async-fn-nonsend.rs
index d7f8d7ac5..ed440bd01 100644
--- a/tests/ui/async-await/async-fn-nonsend.rs
+++ b/tests/ui/async-await/async-fn-nonsend.rs
@@ -1,5 +1,8 @@
+// revisions: no_drop_tracking drop_tracking drop_tracking_mir
+// [drop_tracking] compile-flags: -Zdrop-tracking
+// [drop_tracking_mir] compile-flags: -Zdrop-tracking-mir
// edition:2018
-// compile-flags: --crate-type lib -Zdrop-tracking
+// compile-flags: --crate-type lib
use std::{cell::RefCell, fmt::Debug, rc::Rc};
@@ -65,10 +68,13 @@ fn assert_send(_: impl Send) {}
pub fn pass_assert() {
assert_send(local_dropped_before_await());
+ //[no_drop_tracking]~^ ERROR future cannot be sent between threads safely
assert_send(non_send_temporary_in_match());
//~^ ERROR future cannot be sent between threads safely
assert_send(non_sync_with_method_call());
//~^ ERROR future cannot be sent between threads safely
assert_send(non_sync_with_method_call_panic());
+ //[no_drop_tracking]~^ ERROR future cannot be sent between threads safely
assert_send(non_sync_with_method_call_infinite_loop());
+ //[no_drop_tracking]~^ ERROR future cannot be sent between threads safely
}
diff --git a/tests/ui/async-await/async-fn-nonsend.stderr b/tests/ui/async-await/async-fn-nonsend.stderr
index a7b872fe4..0f0dc335e 100644
--- a/tests/ui/async-await/async-fn-nonsend.stderr
+++ b/tests/ui/async-await/async-fn-nonsend.stderr
@@ -1,12 +1,12 @@
error: future cannot be sent between threads safely
- --> $DIR/async-fn-nonsend.rs:68:17
+ --> $DIR/async-fn-nonsend.rs:72:17
|
LL | assert_send(non_send_temporary_in_match());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ future returned by `non_send_temporary_in_match` is not `Send`
|
= help: within `impl Future<Output = ()>`, the trait `Send` is not implemented for `Rc<()>`
note: future is not `Send` as this value is used across an await
- --> $DIR/async-fn-nonsend.rs:33:25
+ --> $DIR/async-fn-nonsend.rs:36:25
|
LL | match Some(non_send()) {
| ---------------- has type `Option<impl Debug>` which is not `Send`
@@ -16,20 +16,20 @@ LL | Some(_) => fut().await,
LL | }
| - `Some(non_send())` is later dropped here
note: required by a bound in `assert_send`
- --> $DIR/async-fn-nonsend.rs:64:24
+ --> $DIR/async-fn-nonsend.rs:67:24
|
LL | fn assert_send(_: impl Send) {}
| ^^^^ required by this bound in `assert_send`
error: future cannot be sent between threads safely
- --> $DIR/async-fn-nonsend.rs:70:17
+ --> $DIR/async-fn-nonsend.rs:74:17
|
LL | assert_send(non_sync_with_method_call());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ future returned by `non_sync_with_method_call` is not `Send`
|
= help: within `impl Future<Output = ()>`, the trait `Send` is not implemented for `dyn std::fmt::Write`
note: future is not `Send` as this value is used across an await
- --> $DIR/async-fn-nonsend.rs:46:14
+ --> $DIR/async-fn-nonsend.rs:49:14
|
LL | let f: &mut std::fmt::Formatter = &mut get_formatter();
| --------------- has type `Formatter<'_>` which is not `Send`
@@ -40,7 +40,7 @@ LL | }
LL | }
| - `get_formatter()` is later dropped here
note: required by a bound in `assert_send`
- --> $DIR/async-fn-nonsend.rs:64:24
+ --> $DIR/async-fn-nonsend.rs:67:24
|
LL | fn assert_send(_: impl Send) {}
| ^^^^ required by this bound in `assert_send`
diff --git a/tests/ui/async-await/async-fn-path-elision.stderr b/tests/ui/async-await/async-fn-path-elision.stderr
index 5e0c8c299..224198653 100644
--- a/tests/ui/async-await/async-fn-path-elision.stderr
+++ b/tests/ui/async-await/async-fn-path-elision.stderr
@@ -4,7 +4,6 @@ error[E0726]: implicit elided lifetime not allowed here
LL | async fn error(lt: HasLifetime) {
| ^^^^^^^^^^^ expected lifetime parameter
|
- = note: assuming a `'static` lifetime...
help: indicate the anonymous lifetime
|
LL | async fn error(lt: HasLifetime<'_>) {
diff --git a/tests/ui/async-await/default-struct-update.rs b/tests/ui/async-await/default-struct-update.rs
index 64fb6280d..daee8469a 100644
--- a/tests/ui/async-await/default-struct-update.rs
+++ b/tests/ui/async-await/default-struct-update.rs
@@ -1,6 +1,8 @@
+// revisions: no_drop_tracking drop_tracking drop_tracking_mir
+// [drop_tracking] compile-flags: -Zdrop-tracking
+// [drop_tracking_mir] compile-flags: -Zdrop-tracking-mir
// build-pass
// edition:2018
-// compile-flags: -Zdrop-tracking=y
fn main() {
let _ = foo();
diff --git a/tests/ui/async-await/dont-suggest-missing-await.stderr b/tests/ui/async-await/dont-suggest-missing-await.stderr
index 627bf05bb..1fa4e5db0 100644
--- a/tests/ui/async-await/dont-suggest-missing-await.stderr
+++ b/tests/ui/async-await/dont-suggest-missing-await.stderr
@@ -2,17 +2,15 @@ error[E0308]: mismatched types
--> $DIR/dont-suggest-missing-await.rs:14:18
|
LL | take_u32(x)
- | -------- ^ expected `u32`, found opaque type
+ | -------- ^ expected `u32`, found future
| |
| arguments to this function are incorrect
|
-note: while checking the return type of the `async fn`
- --> $DIR/dont-suggest-missing-await.rs:7:24
+note: calling an async function returns a future
+ --> $DIR/dont-suggest-missing-await.rs:14:18
|
-LL | async fn make_u32() -> u32 {
- | ^^^ checked the `Output` of this `async fn`, found opaque type
- = note: expected type `u32`
- found opaque type `impl Future<Output = u32>`
+LL | take_u32(x)
+ | ^
note: function defined here
--> $DIR/dont-suggest-missing-await.rs:5:4
|
diff --git a/tests/ui/async-await/drop-and-assign.rs b/tests/ui/async-await/drop-and-assign.rs
index fa3f33036..e520dfbdc 100644
--- a/tests/ui/async-await/drop-and-assign.rs
+++ b/tests/ui/async-await/drop-and-assign.rs
@@ -1,5 +1,7 @@
+// revisions: no_drop_tracking drop_tracking drop_tracking_mir
+// [drop_tracking] compile-flags: -Zdrop-tracking
+// [drop_tracking_mir] compile-flags: -Zdrop-tracking-mir
// edition:2021
-// compile-flags: -Zdrop-tracking
// build-pass
struct A;
diff --git a/tests/ui/async-await/drop-track-field-assign-nonsend.stderr b/tests/ui/async-await/drop-track-field-assign-nonsend.drop_tracking.stderr
index d95483c81..e2bba812d 100644
--- a/tests/ui/async-await/drop-track-field-assign-nonsend.stderr
+++ b/tests/ui/async-await/drop-track-field-assign-nonsend.drop_tracking.stderr
@@ -1,12 +1,12 @@
error: future cannot be sent between threads safely
- --> $DIR/drop-track-field-assign-nonsend.rs:43:17
+ --> $DIR/drop-track-field-assign-nonsend.rs:45:17
|
LL | assert_send(agent.handle());
| ^^^^^^^^^^^^^^ future returned by `handle` is not `Send`
|
= help: within `impl Future<Output = ()>`, the trait `Send` is not implemented for `Rc<String>`
note: future is not `Send` as this value is used across an await
- --> $DIR/drop-track-field-assign-nonsend.rs:21:38
+ --> $DIR/drop-track-field-assign-nonsend.rs:23:38
|
LL | let mut info = self.info_result.clone();
| -------- has type `InfoResult` which is not `Send`
@@ -16,7 +16,7 @@ LL | let _ = send_element(element).await;
LL | }
| - `mut info` is later dropped here
note: required by a bound in `assert_send`
- --> $DIR/drop-track-field-assign-nonsend.rs:38:19
+ --> $DIR/drop-track-field-assign-nonsend.rs:40:19
|
LL | fn assert_send<T: Send>(_: T) {}
| ^^^^ required by this bound in `assert_send`
diff --git a/tests/ui/async-await/drop-track-field-assign-nonsend.drop_tracking_mir.stderr b/tests/ui/async-await/drop-track-field-assign-nonsend.drop_tracking_mir.stderr
new file mode 100644
index 000000000..b89d86804
--- /dev/null
+++ b/tests/ui/async-await/drop-track-field-assign-nonsend.drop_tracking_mir.stderr
@@ -0,0 +1,23 @@
+error: future cannot be sent between threads safely
+ --> $DIR/drop-track-field-assign-nonsend.rs:45:17
+ |
+LL | assert_send(agent.handle());
+ | ^^^^^^^^^^^^^^ future returned by `handle` is not `Send`
+ |
+ = help: within `impl Future<Output = ()>`, the trait `Send` is not implemented for `Rc<String>`
+note: future is not `Send` as this value is used across an await
+ --> $DIR/drop-track-field-assign-nonsend.rs:23:38
+ |
+LL | let mut info = self.info_result.clone();
+ | -------- has type `InfoResult` which is not `Send`
+...
+LL | let _ = send_element(element).await;
+ | ^^^^^^ await occurs here, with `mut info` maybe used later
+note: required by a bound in `assert_send`
+ --> $DIR/drop-track-field-assign-nonsend.rs:40:19
+ |
+LL | fn assert_send<T: Send>(_: T) {}
+ | ^^^^ required by this bound in `assert_send`
+
+error: aborting due to previous error
+
diff --git a/tests/ui/async-await/drop-track-field-assign-nonsend.no_drop_tracking.stderr b/tests/ui/async-await/drop-track-field-assign-nonsend.no_drop_tracking.stderr
new file mode 100644
index 000000000..e2bba812d
--- /dev/null
+++ b/tests/ui/async-await/drop-track-field-assign-nonsend.no_drop_tracking.stderr
@@ -0,0 +1,25 @@
+error: future cannot be sent between threads safely
+ --> $DIR/drop-track-field-assign-nonsend.rs:45:17
+ |
+LL | assert_send(agent.handle());
+ | ^^^^^^^^^^^^^^ future returned by `handle` is not `Send`
+ |
+ = help: within `impl Future<Output = ()>`, the trait `Send` is not implemented for `Rc<String>`
+note: future is not `Send` as this value is used across an await
+ --> $DIR/drop-track-field-assign-nonsend.rs:23:38
+ |
+LL | let mut info = self.info_result.clone();
+ | -------- has type `InfoResult` which is not `Send`
+...
+LL | let _ = send_element(element).await;
+ | ^^^^^^ await occurs here, with `mut info` maybe used later
+LL | }
+ | - `mut info` is later dropped here
+note: required by a bound in `assert_send`
+ --> $DIR/drop-track-field-assign-nonsend.rs:40:19
+ |
+LL | fn assert_send<T: Send>(_: T) {}
+ | ^^^^ required by this bound in `assert_send`
+
+error: aborting due to previous error
+
diff --git a/tests/ui/async-await/drop-track-field-assign-nonsend.rs b/tests/ui/async-await/drop-track-field-assign-nonsend.rs
index b6c0fda15..3e2228000 100644
--- a/tests/ui/async-await/drop-track-field-assign-nonsend.rs
+++ b/tests/ui/async-await/drop-track-field-assign-nonsend.rs
@@ -1,6 +1,8 @@
+// revisions: no_drop_tracking drop_tracking drop_tracking_mir
+// [drop_tracking] compile-flags: -Zdrop-tracking
+// [drop_tracking_mir] compile-flags: -Zdrop-tracking-mir
// Derived from an ICE found in tokio-xmpp during a crater run.
// edition:2021
-// compile-flags: -Zdrop-tracking
#![allow(dead_code)]
diff --git a/tests/ui/async-await/drop-track-field-assign.rs b/tests/ui/async-await/drop-track-field-assign.rs
index 3a393cd16..dd0e3f11c 100644
--- a/tests/ui/async-await/drop-track-field-assign.rs
+++ b/tests/ui/async-await/drop-track-field-assign.rs
@@ -1,6 +1,8 @@
+// revisions: no_drop_tracking drop_tracking drop_tracking_mir
+// [drop_tracking] compile-flags: -Zdrop-tracking
+// [drop_tracking_mir] compile-flags: -Zdrop-tracking-mir
// Derived from an ICE found in tokio-xmpp during a crater run.
// edition:2021
-// compile-flags: -Zdrop-tracking
// build-pass
#![allow(dead_code)]
diff --git a/tests/ui/async-await/field-assign-nonsend.drop_tracking.stderr b/tests/ui/async-await/field-assign-nonsend.drop_tracking.stderr
new file mode 100644
index 000000000..ac461a671
--- /dev/null
+++ b/tests/ui/async-await/field-assign-nonsend.drop_tracking.stderr
@@ -0,0 +1,25 @@
+error: future cannot be sent between threads safely
+ --> $DIR/field-assign-nonsend.rs:45:17
+ |
+LL | assert_send(agent.handle());
+ | ^^^^^^^^^^^^^^ future returned by `handle` is not `Send`
+ |
+ = help: within `impl Future<Output = ()>`, the trait `Send` is not implemented for `Rc<String>`
+note: future is not `Send` as this value is used across an await
+ --> $DIR/field-assign-nonsend.rs:23:38
+ |
+LL | let mut info = self.info_result.clone();
+ | -------- has type `InfoResult` which is not `Send`
+...
+LL | let _ = send_element(element).await;
+ | ^^^^^^ await occurs here, with `mut info` maybe used later
+LL | }
+ | - `mut info` is later dropped here
+note: required by a bound in `assert_send`
+ --> $DIR/field-assign-nonsend.rs:40:19
+ |
+LL | fn assert_send<T: Send>(_: T) {}
+ | ^^^^ required by this bound in `assert_send`
+
+error: aborting due to previous error
+
diff --git a/tests/ui/async-await/field-assign-nonsend.drop_tracking_mir.stderr b/tests/ui/async-await/field-assign-nonsend.drop_tracking_mir.stderr
new file mode 100644
index 000000000..8c9d14d62
--- /dev/null
+++ b/tests/ui/async-await/field-assign-nonsend.drop_tracking_mir.stderr
@@ -0,0 +1,23 @@
+error: future cannot be sent between threads safely
+ --> $DIR/field-assign-nonsend.rs:45:17
+ |
+LL | assert_send(agent.handle());
+ | ^^^^^^^^^^^^^^ future returned by `handle` is not `Send`
+ |
+ = help: within `impl Future<Output = ()>`, the trait `Send` is not implemented for `Rc<String>`
+note: future is not `Send` as this value is used across an await
+ --> $DIR/field-assign-nonsend.rs:23:38
+ |
+LL | let mut info = self.info_result.clone();
+ | -------- has type `InfoResult` which is not `Send`
+...
+LL | let _ = send_element(element).await;
+ | ^^^^^^ await occurs here, with `mut info` maybe used later
+note: required by a bound in `assert_send`
+ --> $DIR/field-assign-nonsend.rs:40:19
+ |
+LL | fn assert_send<T: Send>(_: T) {}
+ | ^^^^ required by this bound in `assert_send`
+
+error: aborting due to previous error
+
diff --git a/tests/ui/async-await/field-assign-nonsend.no_drop_tracking.stderr b/tests/ui/async-await/field-assign-nonsend.no_drop_tracking.stderr
new file mode 100644
index 000000000..ac461a671
--- /dev/null
+++ b/tests/ui/async-await/field-assign-nonsend.no_drop_tracking.stderr
@@ -0,0 +1,25 @@
+error: future cannot be sent between threads safely
+ --> $DIR/field-assign-nonsend.rs:45:17
+ |
+LL | assert_send(agent.handle());
+ | ^^^^^^^^^^^^^^ future returned by `handle` is not `Send`
+ |
+ = help: within `impl Future<Output = ()>`, the trait `Send` is not implemented for `Rc<String>`
+note: future is not `Send` as this value is used across an await
+ --> $DIR/field-assign-nonsend.rs:23:38
+ |
+LL | let mut info = self.info_result.clone();
+ | -------- has type `InfoResult` which is not `Send`
+...
+LL | let _ = send_element(element).await;
+ | ^^^^^^ await occurs here, with `mut info` maybe used later
+LL | }
+ | - `mut info` is later dropped here
+note: required by a bound in `assert_send`
+ --> $DIR/field-assign-nonsend.rs:40:19
+ |
+LL | fn assert_send<T: Send>(_: T) {}
+ | ^^^^ required by this bound in `assert_send`
+
+error: aborting due to previous error
+
diff --git a/tests/ui/async-await/field-assign-nonsend.rs b/tests/ui/async-await/field-assign-nonsend.rs
new file mode 100644
index 000000000..3e2228000
--- /dev/null
+++ b/tests/ui/async-await/field-assign-nonsend.rs
@@ -0,0 +1,47 @@
+// revisions: no_drop_tracking drop_tracking drop_tracking_mir
+// [drop_tracking] compile-flags: -Zdrop-tracking
+// [drop_tracking_mir] compile-flags: -Zdrop-tracking-mir
+// Derived from an ICE found in tokio-xmpp during a crater run.
+// edition:2021
+
+#![allow(dead_code)]
+
+#[derive(Clone)]
+struct InfoResult {
+ node: Option<std::rc::Rc<String>>
+}
+
+struct Agent {
+ info_result: InfoResult
+}
+
+impl Agent {
+ async fn handle(&mut self) {
+ let mut info = self.info_result.clone();
+ info.node = None;
+ let element = parse_info(info);
+ let _ = send_element(element).await;
+ }
+}
+
+struct Element {
+}
+
+async fn send_element(_: Element) {}
+
+fn parse(_: &[u8]) -> Result<(), ()> {
+ Ok(())
+}
+
+fn parse_info(_: InfoResult) -> Element {
+ Element { }
+}
+
+fn assert_send<T: Send>(_: T) {}
+
+fn main() {
+ let agent = Agent { info_result: InfoResult { node: None } };
+ // FIXME: It would be nice for this to work. See #94067.
+ assert_send(agent.handle());
+ //~^ cannot be sent between threads safely
+}
diff --git a/tests/ui/async-await/field-assign.rs b/tests/ui/async-await/field-assign.rs
new file mode 100644
index 000000000..dd0e3f11c
--- /dev/null
+++ b/tests/ui/async-await/field-assign.rs
@@ -0,0 +1,46 @@
+// revisions: no_drop_tracking drop_tracking drop_tracking_mir
+// [drop_tracking] compile-flags: -Zdrop-tracking
+// [drop_tracking_mir] compile-flags: -Zdrop-tracking-mir
+// Derived from an ICE found in tokio-xmpp during a crater run.
+// edition:2021
+// build-pass
+
+#![allow(dead_code)]
+
+#[derive(Clone)]
+struct InfoResult {
+ node: Option<String>
+}
+
+struct Agent {
+ info_result: InfoResult
+}
+
+impl Agent {
+ async fn handle(&mut self) {
+ let mut info = self.info_result.clone();
+ info.node = Some("bar".into());
+ let element = parse_info(info);
+ let _ = send_element(element).await;
+ }
+}
+
+struct Element {
+}
+
+async fn send_element(_: Element) {}
+
+fn parse(_: &[u8]) -> Result<(), ()> {
+ Ok(())
+}
+
+fn parse_info(_: InfoResult) -> Element {
+ Element { }
+}
+
+fn main() {
+ let mut agent = Agent {
+ info_result: InfoResult { node: None }
+ };
+ let _ = agent.handle();
+}
diff --git a/tests/ui/async-await/future-sizes/async-awaiting-fut.rs b/tests/ui/async-await/future-sizes/async-awaiting-fut.rs
new file mode 100644
index 000000000..1816d842d
--- /dev/null
+++ b/tests/ui/async-await/future-sizes/async-awaiting-fut.rs
@@ -0,0 +1,24 @@
+// compile-flags: -Z print-type-sizes --crate-type lib
+// edition:2021
+// build-pass
+// ignore-pass
+
+async fn wait() {}
+
+async fn big_fut(arg: [u8; 1024]) {}
+
+async fn calls_fut(fut: impl std::future::Future<Output = ()>) {
+ loop {
+ wait().await;
+ if true {
+ return fut.await;
+ } else {
+ wait().await;
+ }
+ }
+}
+
+pub async fn test() {
+ let fut = big_fut([0u8; 1024]);
+ calls_fut(fut).await;
+}
diff --git a/tests/ui/async-await/future-sizes/async-awaiting-fut.stdout b/tests/ui/async-await/future-sizes/async-awaiting-fut.stdout
new file mode 100644
index 000000000..eaf3e4b61
--- /dev/null
+++ b/tests/ui/async-await/future-sizes/async-awaiting-fut.stdout
@@ -0,0 +1,72 @@
+print-type-size type: `[async fn body@$DIR/async-awaiting-fut.rs:21:21: 24:2]`: 3078 bytes, alignment: 1 bytes
+print-type-size discriminant: 1 bytes
+print-type-size variant `Unresumed`: 0 bytes
+print-type-size variant `Suspend0`: 3077 bytes
+print-type-size local `.__awaitee`: 3077 bytes, offset: 0 bytes, alignment: 1 bytes
+print-type-size variant `Returned`: 0 bytes
+print-type-size variant `Panicked`: 0 bytes
+print-type-size type: `[async fn body@$DIR/async-awaiting-fut.rs:10:64: 19:2]`: 3077 bytes, alignment: 1 bytes
+print-type-size discriminant: 1 bytes
+print-type-size variant `Unresumed`: 2051 bytes
+print-type-size padding: 1026 bytes
+print-type-size upvar `.fut`: 1025 bytes, alignment: 1 bytes
+print-type-size variant `Suspend0`: 2052 bytes
+print-type-size local `.fut`: 1025 bytes, offset: 0 bytes, alignment: 1 bytes
+print-type-size local `..generator_field4`: 1 bytes
+print-type-size padding: 1 bytes
+print-type-size upvar `.fut`: 1025 bytes, alignment: 1 bytes
+print-type-size local `.__awaitee`: 1 bytes
+print-type-size variant `Suspend1`: 3076 bytes
+print-type-size padding: 1024 bytes
+print-type-size local `..generator_field4`: 1 bytes, alignment: 1 bytes
+print-type-size padding: 1 bytes
+print-type-size upvar `.fut`: 1025 bytes, alignment: 1 bytes
+print-type-size local `.__awaitee`: 1025 bytes
+print-type-size variant `Suspend2`: 2052 bytes
+print-type-size local `.fut`: 1025 bytes, offset: 0 bytes, alignment: 1 bytes
+print-type-size local `..generator_field4`: 1 bytes
+print-type-size padding: 1 bytes
+print-type-size upvar `.fut`: 1025 bytes, alignment: 1 bytes
+print-type-size local `.__awaitee`: 1 bytes
+print-type-size variant `Returned`: 2051 bytes
+print-type-size padding: 1026 bytes
+print-type-size upvar `.fut`: 1025 bytes, alignment: 1 bytes
+print-type-size variant `Panicked`: 2051 bytes
+print-type-size padding: 1026 bytes
+print-type-size upvar `.fut`: 1025 bytes, alignment: 1 bytes
+print-type-size type: `std::mem::ManuallyDrop<[async fn body@$DIR/async-awaiting-fut.rs:10:64: 19:2]>`: 3077 bytes, alignment: 1 bytes
+print-type-size field `.value`: 3077 bytes
+print-type-size type: `std::mem::MaybeUninit<[async fn body@$DIR/async-awaiting-fut.rs:10:64: 19:2]>`: 3077 bytes, alignment: 1 bytes
+print-type-size variant `MaybeUninit`: 3077 bytes
+print-type-size field `.uninit`: 0 bytes
+print-type-size field `.value`: 3077 bytes
+print-type-size type: `[async fn body@$DIR/async-awaiting-fut.rs:8:35: 8:37]`: 1025 bytes, alignment: 1 bytes
+print-type-size discriminant: 1 bytes
+print-type-size variant `Unresumed`: 1024 bytes
+print-type-size upvar `.arg`: 1024 bytes, offset: 0 bytes, alignment: 1 bytes
+print-type-size variant `Returned`: 1024 bytes
+print-type-size upvar `.arg`: 1024 bytes, offset: 0 bytes, alignment: 1 bytes
+print-type-size variant `Panicked`: 1024 bytes
+print-type-size upvar `.arg`: 1024 bytes, offset: 0 bytes, alignment: 1 bytes
+print-type-size type: `std::mem::ManuallyDrop<[async fn body@$DIR/async-awaiting-fut.rs:8:35: 8:37]>`: 1025 bytes, alignment: 1 bytes
+print-type-size field `.value`: 1025 bytes
+print-type-size type: `std::mem::MaybeUninit<[async fn body@$DIR/async-awaiting-fut.rs:8:35: 8:37]>`: 1025 bytes, alignment: 1 bytes
+print-type-size variant `MaybeUninit`: 1025 bytes
+print-type-size field `.uninit`: 0 bytes
+print-type-size field `.value`: 1025 bytes
+print-type-size type: `[async fn body@$DIR/async-awaiting-fut.rs:6:17: 6:19]`: 1 bytes, alignment: 1 bytes
+print-type-size discriminant: 1 bytes
+print-type-size variant `Unresumed`: 0 bytes
+print-type-size variant `Returned`: 0 bytes
+print-type-size variant `Panicked`: 0 bytes
+print-type-size type: `std::mem::ManuallyDrop<bool>`: 1 bytes, alignment: 1 bytes
+print-type-size field `.value`: 1 bytes
+print-type-size type: `std::mem::MaybeUninit<bool>`: 1 bytes, alignment: 1 bytes
+print-type-size variant `MaybeUninit`: 1 bytes
+print-type-size field `.uninit`: 0 bytes
+print-type-size field `.value`: 1 bytes
+print-type-size type: `std::task::Poll<()>`: 1 bytes, alignment: 1 bytes
+print-type-size discriminant: 1 bytes
+print-type-size variant `Ready`: 0 bytes
+print-type-size field `.0`: 0 bytes
+print-type-size variant `Pending`: 0 bytes
diff --git a/tests/ui/async-await/future-sizes/future-as-arg.rs b/tests/ui/async-await/future-sizes/future-as-arg.rs
new file mode 100644
index 000000000..93c69b052
--- /dev/null
+++ b/tests/ui/async-await/future-sizes/future-as-arg.rs
@@ -0,0 +1,16 @@
+// edition: 2021
+// run-pass
+
+async fn test(_arg: [u8; 16]) {}
+
+async fn use_future(fut: impl std::future::Future<Output = ()>) {
+ fut.await
+}
+
+fn main() {
+ let actual = std::mem::size_of_val(
+ &use_future(use_future(use_future(use_future(use_future(test([0; 16])))))));
+ // Not using an exact number in case it slightly changes over different commits
+ let expected = 550;
+ assert!(actual > expected, "expected: >{expected}, actual: {actual}");
+}
diff --git a/tests/ui/async-await/future-sizes/large-arg.rs b/tests/ui/async-await/future-sizes/large-arg.rs
new file mode 100644
index 000000000..7e7ff9d8d
--- /dev/null
+++ b/tests/ui/async-await/future-sizes/large-arg.rs
@@ -0,0 +1,18 @@
+// compile-flags: -Z print-type-sizes --crate-type=lib
+// edition: 2021
+// build-pass
+// ignore-pass
+
+pub async fn test() {
+ let _ = a([0u8; 1024]).await;
+}
+
+pub async fn a<T>(t: T) -> T {
+ b(t).await
+}
+async fn b<T>(t: T) -> T {
+ c(t).await
+}
+async fn c<T>(t: T) -> T {
+ t
+}
diff --git a/tests/ui/async-await/future-sizes/large-arg.stdout b/tests/ui/async-await/future-sizes/large-arg.stdout
new file mode 100644
index 000000000..91db4b153
--- /dev/null
+++ b/tests/ui/async-await/future-sizes/large-arg.stdout
@@ -0,0 +1,60 @@
+print-type-size type: `[async fn body@$DIR/large-arg.rs:6:21: 8:2]`: 3076 bytes, alignment: 1 bytes
+print-type-size discriminant: 1 bytes
+print-type-size variant `Unresumed`: 0 bytes
+print-type-size variant `Suspend0`: 3075 bytes
+print-type-size local `.__awaitee`: 3075 bytes, offset: 0 bytes, alignment: 1 bytes
+print-type-size variant `Returned`: 0 bytes
+print-type-size variant `Panicked`: 0 bytes
+print-type-size type: `[async fn body@$DIR/large-arg.rs:10:30: 12:2]`: 3075 bytes, alignment: 1 bytes
+print-type-size discriminant: 1 bytes
+print-type-size variant `Unresumed`: 1024 bytes
+print-type-size upvar `.t`: 1024 bytes, offset: 0 bytes, alignment: 1 bytes
+print-type-size variant `Suspend0`: 3074 bytes
+print-type-size upvar `.t`: 1024 bytes, offset: 0 bytes, alignment: 1 bytes
+print-type-size local `.__awaitee`: 2050 bytes
+print-type-size variant `Returned`: 1024 bytes
+print-type-size upvar `.t`: 1024 bytes, offset: 0 bytes, alignment: 1 bytes
+print-type-size variant `Panicked`: 1024 bytes
+print-type-size upvar `.t`: 1024 bytes, offset: 0 bytes, alignment: 1 bytes
+print-type-size type: `std::mem::ManuallyDrop<[async fn body@$DIR/large-arg.rs:10:30: 12:2]>`: 3075 bytes, alignment: 1 bytes
+print-type-size field `.value`: 3075 bytes
+print-type-size type: `std::mem::MaybeUninit<[async fn body@$DIR/large-arg.rs:10:30: 12:2]>`: 3075 bytes, alignment: 1 bytes
+print-type-size variant `MaybeUninit`: 3075 bytes
+print-type-size field `.uninit`: 0 bytes
+print-type-size field `.value`: 3075 bytes
+print-type-size type: `[async fn body@$DIR/large-arg.rs:13:26: 15:2]`: 2050 bytes, alignment: 1 bytes
+print-type-size discriminant: 1 bytes
+print-type-size variant `Unresumed`: 1024 bytes
+print-type-size upvar `.t`: 1024 bytes, offset: 0 bytes, alignment: 1 bytes
+print-type-size variant `Suspend0`: 2049 bytes
+print-type-size upvar `.t`: 1024 bytes, offset: 0 bytes, alignment: 1 bytes
+print-type-size local `.__awaitee`: 1025 bytes
+print-type-size variant `Returned`: 1024 bytes
+print-type-size upvar `.t`: 1024 bytes, offset: 0 bytes, alignment: 1 bytes
+print-type-size variant `Panicked`: 1024 bytes
+print-type-size upvar `.t`: 1024 bytes, offset: 0 bytes, alignment: 1 bytes
+print-type-size type: `std::mem::ManuallyDrop<[async fn body@$DIR/large-arg.rs:13:26: 15:2]>`: 2050 bytes, alignment: 1 bytes
+print-type-size field `.value`: 2050 bytes
+print-type-size type: `std::mem::MaybeUninit<[async fn body@$DIR/large-arg.rs:13:26: 15:2]>`: 2050 bytes, alignment: 1 bytes
+print-type-size variant `MaybeUninit`: 2050 bytes
+print-type-size field `.uninit`: 0 bytes
+print-type-size field `.value`: 2050 bytes
+print-type-size type: `[async fn body@$DIR/large-arg.rs:16:26: 18:2]`: 1025 bytes, alignment: 1 bytes
+print-type-size discriminant: 1 bytes
+print-type-size variant `Unresumed`: 1024 bytes
+print-type-size upvar `.t`: 1024 bytes, offset: 0 bytes, alignment: 1 bytes
+print-type-size variant `Returned`: 1024 bytes
+print-type-size upvar `.t`: 1024 bytes, offset: 0 bytes, alignment: 1 bytes
+print-type-size variant `Panicked`: 1024 bytes
+print-type-size upvar `.t`: 1024 bytes, offset: 0 bytes, alignment: 1 bytes
+print-type-size type: `std::mem::ManuallyDrop<[async fn body@$DIR/large-arg.rs:16:26: 18:2]>`: 1025 bytes, alignment: 1 bytes
+print-type-size field `.value`: 1025 bytes
+print-type-size type: `std::mem::MaybeUninit<[async fn body@$DIR/large-arg.rs:16:26: 18:2]>`: 1025 bytes, alignment: 1 bytes
+print-type-size variant `MaybeUninit`: 1025 bytes
+print-type-size field `.uninit`: 0 bytes
+print-type-size field `.value`: 1025 bytes
+print-type-size type: `std::task::Poll<[u8; 1024]>`: 1025 bytes, alignment: 1 bytes
+print-type-size discriminant: 1 bytes
+print-type-size variant `Ready`: 1024 bytes
+print-type-size field `.0`: 1024 bytes
+print-type-size variant `Pending`: 0 bytes
diff --git a/tests/ui/async-await/generator-desc.stderr b/tests/ui/async-await/generator-desc.stderr
index 963c6ba57..51ac9d86b 100644
--- a/tests/ui/async-await/generator-desc.stderr
+++ b/tests/ui/async-await/generator-desc.stderr
@@ -17,22 +17,10 @@ error[E0308]: mismatched types
--> $DIR/generator-desc.rs:12:16
|
LL | fun(one(), two());
- | --- ^^^^^ expected opaque type, found a different opaque type
+ | --- ^^^^^ expected future, found a different future
| |
| arguments to this function are incorrect
|
-note: while checking the return type of the `async fn`
- --> $DIR/generator-desc.rs:5:16
- |
-LL | async fn one() {}
- | ^ checked the `Output` of this `async fn`, expected opaque type
-note: while checking the return type of the `async fn`
- --> $DIR/generator-desc.rs:6:16
- |
-LL | async fn two() {}
- | ^ checked the `Output` of this `async fn`, found opaque type
- = note: expected opaque type `impl Future<Output = ()>` (opaque type at <$DIR/generator-desc.rs:5:16>)
- found opaque type `impl Future<Output = ()>` (opaque type at <$DIR/generator-desc.rs:6:16>)
= help: consider `await`ing on both `Future`s
= note: distinct uses of `impl Trait` result in different opaque types
note: function defined here
diff --git a/tests/ui/async-await/in-trait/async-default-fn-overridden.rs b/tests/ui/async-await/in-trait/async-default-fn-overridden.rs
new file mode 100644
index 000000000..0fd1a2703
--- /dev/null
+++ b/tests/ui/async-await/in-trait/async-default-fn-overridden.rs
@@ -0,0 +1,66 @@
+// run-pass
+// edition:2021
+
+#![feature(async_fn_in_trait)]
+//~^ WARN the feature `async_fn_in_trait` is incomplete and may not be safe to use
+
+use std::future::Future;
+
+trait AsyncTrait {
+ async fn default_impl() {
+ assert!(false);
+ }
+
+ async fn call_default_impl() {
+ Self::default_impl().await
+ }
+}
+
+struct AsyncType;
+
+impl AsyncTrait for AsyncType {
+ async fn default_impl() {
+ // :)
+ }
+}
+
+async fn async_main() {
+ // Should not assert false
+ AsyncType::call_default_impl().await;
+}
+
+// ------------------------------------------------------------------------- //
+// Implementation Details Below...
+
+use std::pin::Pin;
+use std::task::*;
+
+pub fn noop_waker() -> Waker {
+ let raw = RawWaker::new(std::ptr::null(), &NOOP_WAKER_VTABLE);
+
+ // SAFETY: the contracts for RawWaker and RawWakerVTable are upheld
+ unsafe { Waker::from_raw(raw) }
+}
+
+const NOOP_WAKER_VTABLE: RawWakerVTable = RawWakerVTable::new(noop_clone, noop, noop, noop);
+
+unsafe fn noop_clone(_p: *const ()) -> RawWaker {
+ RawWaker::new(std::ptr::null(), &NOOP_WAKER_VTABLE)
+}
+
+unsafe fn noop(_p: *const ()) {}
+
+fn main() {
+ let mut fut = async_main();
+
+ // Poll loop, just to test the future...
+ let waker = noop_waker();
+ let ctx = &mut Context::from_waker(&waker);
+
+ loop {
+ match unsafe { Pin::new_unchecked(&mut fut).poll(ctx) } {
+ Poll::Pending => {}
+ Poll::Ready(()) => break,
+ }
+ }
+}
diff --git a/tests/ui/async-await/in-trait/async-default-fn-overridden.stderr b/tests/ui/async-await/in-trait/async-default-fn-overridden.stderr
new file mode 100644
index 000000000..61a826258
--- /dev/null
+++ b/tests/ui/async-await/in-trait/async-default-fn-overridden.stderr
@@ -0,0 +1,11 @@
+warning: the feature `async_fn_in_trait` is incomplete and may not be safe to use and/or cause compiler crashes
+ --> $DIR/async-default-fn-overridden.rs:4:12
+ |
+LL | #![feature(async_fn_in_trait)]
+ | ^^^^^^^^^^^^^^^^^
+ |
+ = note: see issue #91611 <https://github.com/rust-lang/rust/issues/91611> for more information
+ = note: `#[warn(incomplete_features)]` on by default
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/async-await/in-trait/async-example-desugared-boxed-in-trait.stderr b/tests/ui/async-await/in-trait/async-example-desugared-boxed-in-trait.stderr
index 13e722255..168ef8e9e 100644
--- a/tests/ui/async-await/in-trait/async-example-desugared-boxed-in-trait.stderr
+++ b/tests/ui/async-await/in-trait/async-example-desugared-boxed-in-trait.stderr
@@ -2,7 +2,7 @@ error[E0053]: method `foo` has an incompatible type for trait
--> $DIR/async-example-desugared-boxed-in-trait.rs:15:28
|
LL | async fn foo(&self) -> i32 {
- | ^^^ expected struct `Pin`, found opaque type
+ | ^^^ expected `Pin<Box<dyn Future<Output = i32>>>`, found future
|
note: type in trait
--> $DIR/async-example-desugared-boxed-in-trait.rs:11:22
diff --git a/tests/ui/async-await/in-trait/dont-project-to-specializable-projection.rs b/tests/ui/async-await/in-trait/dont-project-to-specializable-projection.rs
new file mode 100644
index 000000000..afd3db5e0
--- /dev/null
+++ b/tests/ui/async-await/in-trait/dont-project-to-specializable-projection.rs
@@ -0,0 +1,71 @@
+// edition: 2021
+// known-bug: #108309
+
+#![feature(async_fn_in_trait)]
+#![feature(min_specialization)]
+
+struct MyStruct;
+
+trait MyTrait<T> {
+ async fn foo(_: T) -> &'static str;
+}
+
+impl<T> MyTrait<T> for MyStruct {
+ default async fn foo(_: T) -> &'static str {
+ "default"
+ }
+}
+
+impl MyTrait<i32> for MyStruct {
+ async fn foo(_: i32) -> &'static str {
+ "specialized"
+ }
+}
+
+async fn async_main() {
+ assert_eq!(MyStruct::foo(42).await, "specialized");
+ assert_eq!(indirection(42).await, "specialized");
+}
+
+async fn indirection<T>(x: T) -> &'static str {
+ //explicit type coercion is currently necessary
+ // because of https://github.com/rust-lang/rust/issues/67918
+ <MyStruct as MyTrait<T>>::foo(x).await
+}
+
+// ------------------------------------------------------------------------- //
+// Implementation Details Below...
+
+use std::future::Future;
+use std::pin::Pin;
+use std::task::*;
+
+pub fn noop_waker() -> Waker {
+ let raw = RawWaker::new(std::ptr::null(), &NOOP_WAKER_VTABLE);
+
+ // SAFETY: the contracts for RawWaker and RawWakerVTable are upheld
+ unsafe { Waker::from_raw(raw) }
+}
+
+const NOOP_WAKER_VTABLE: RawWakerVTable = RawWakerVTable::new(noop_clone, noop, noop, noop);
+
+unsafe fn noop_clone(_p: *const ()) -> RawWaker {
+ RawWaker::new(std::ptr::null(), &NOOP_WAKER_VTABLE)
+}
+
+unsafe fn noop(_p: *const ()) {}
+
+fn main() {
+ let mut fut = async_main();
+
+ // Poll loop, just to test the future...
+ let waker = noop_waker();
+ let ctx = &mut Context::from_waker(&waker);
+
+ loop {
+ match unsafe { Pin::new_unchecked(&mut fut).poll(ctx) } {
+ Poll::Pending => {}
+ Poll::Ready(()) => break,
+ }
+ }
+}
diff --git a/tests/ui/async-await/in-trait/dont-project-to-specializable-projection.stderr b/tests/ui/async-await/in-trait/dont-project-to-specializable-projection.stderr
new file mode 100644
index 000000000..f71fd9980
--- /dev/null
+++ b/tests/ui/async-await/in-trait/dont-project-to-specializable-projection.stderr
@@ -0,0 +1,19 @@
+warning: the feature `async_fn_in_trait` is incomplete and may not be safe to use and/or cause compiler crashes
+ --> $DIR/dont-project-to-specializable-projection.rs:4:12
+ |
+LL | #![feature(async_fn_in_trait)]
+ | ^^^^^^^^^^^^^^^^^
+ |
+ = note: see issue #91611 <https://github.com/rust-lang/rust/issues/91611> for more information
+ = note: `#[warn(incomplete_features)]` on by default
+
+error: async associated function in trait cannot be specialized
+ --> $DIR/dont-project-to-specializable-projection.rs:14:5
+ |
+LL | default async fn foo(_: T) -> &'static str {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: specialization behaves in inconsistent and surprising ways with `#![feature(async_fn_in_trait)]`, and for now is disallowed
+
+error: aborting due to previous error; 1 warning emitted
+
diff --git a/tests/ui/async-await/in-trait/fn-not-async-err2.rs b/tests/ui/async-await/in-trait/fn-not-async-err2.rs
index 2c4ed5535..78017429f 100644
--- a/tests/ui/async-await/in-trait/fn-not-async-err2.rs
+++ b/tests/ui/async-await/in-trait/fn-not-async-err2.rs
@@ -11,7 +11,7 @@ trait MyTrait {
impl MyTrait for i32 {
fn foo(&self) -> impl Future<Output = i32> {
- //~^ ERROR `impl Trait` only allowed in function and inherent method return types, not in `impl` method return [E0562]
+ //~^ ERROR `impl Trait` only allowed in function and inherent method return types, not in `impl` method return types
async { *self }
}
}
diff --git a/tests/ui/async-await/in-trait/fn-not-async-err2.stderr b/tests/ui/async-await/in-trait/fn-not-async-err2.stderr
index f591f1847..37d9669c0 100644
--- a/tests/ui/async-await/in-trait/fn-not-async-err2.stderr
+++ b/tests/ui/async-await/in-trait/fn-not-async-err2.stderr
@@ -1,4 +1,4 @@
-error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `impl` method return
+error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `impl` method return types
--> $DIR/fn-not-async-err2.rs:13:22
|
LL | fn foo(&self) -> impl Future<Output = i32> {
diff --git a/tests/ui/async-await/in-trait/return-type-suggestion.stderr b/tests/ui/async-await/in-trait/return-type-suggestion.stderr
index 5a9b15e54..b8d83d0f2 100644
--- a/tests/ui/async-await/in-trait/return-type-suggestion.stderr
+++ b/tests/ui/async-await/in-trait/return-type-suggestion.stderr
@@ -13,7 +13,7 @@ error[E0308]: mismatched types
LL | Ok(())
| ^^^^^^- help: consider using a semicolon here: `;`
| |
- | expected `()`, found enum `Result`
+ | expected `()`, found `Result<(), _>`
|
= note: expected unit type `()`
found enum `Result<(), _>`
diff --git a/tests/ui/async-await/issue-61076.rs b/tests/ui/async-await/issue-61076.rs
index 750fad839..cf6e5b4e4 100644
--- a/tests/ui/async-await/issue-61076.rs
+++ b/tests/ui/async-await/issue-61076.rs
@@ -54,9 +54,6 @@ async fn struct_() -> Struct {
}
async fn tuple() -> Tuple {
- //~^ NOTE checked the `Output` of this `async fn`, expected opaque type
- //~| NOTE while checking the return type of the `async fn`
- //~| NOTE in this expansion of desugaring of `async` block or function
Tuple(1i32)
}
@@ -89,7 +86,7 @@ async fn match_() {
match tuple() { //~ HELP consider `await`ing on the `Future`
//~^ NOTE this expression has type `impl Future<Output = Tuple>`
Tuple(_) => {} //~ ERROR mismatched types
- //~^ NOTE expected opaque type, found struct `Tuple`
+ //~^ NOTE expected future, found `Tuple`
//~| NOTE expected opaque type `impl Future<Output = Tuple>`
}
}
diff --git a/tests/ui/async-await/issue-61076.stderr b/tests/ui/async-await/issue-61076.stderr
index 33839ea59..44de28298 100644
--- a/tests/ui/async-await/issue-61076.stderr
+++ b/tests/ui/async-await/issue-61076.stderr
@@ -11,7 +11,7 @@ LL | foo().await?;
| ++++++
error[E0277]: the `?` operator can only be applied to values that implement `Try`
- --> $DIR/issue-61076.rs:65:5
+ --> $DIR/issue-61076.rs:62:5
|
LL | t?;
| ^^ the `?` operator cannot be applied to type `T`
@@ -23,7 +23,7 @@ LL | t.await?;
| ++++++
error[E0609]: no field `0` on type `impl Future<Output = Tuple>`
- --> $DIR/issue-61076.rs:74:26
+ --> $DIR/issue-61076.rs:71:26
|
LL | let _: i32 = tuple().0;
| ^ field not available in `impl Future`, but it is available in its `Output`
@@ -34,7 +34,7 @@ LL | let _: i32 = tuple().await.0;
| ++++++
error[E0609]: no field `a` on type `impl Future<Output = Struct>`
- --> $DIR/issue-61076.rs:78:28
+ --> $DIR/issue-61076.rs:75:28
|
LL | let _: i32 = struct_().a;
| ^ field not available in `impl Future`, but it is available in its `Output`
@@ -45,7 +45,7 @@ LL | let _: i32 = struct_().await.a;
| ++++++
error[E0599]: no method named `method` found for opaque type `impl Future<Output = Struct>` in the current scope
- --> $DIR/issue-61076.rs:82:15
+ --> $DIR/issue-61076.rs:79:15
|
LL | struct_().method();
| ^^^^^^ method not found in `impl Future<Output = Struct>`
@@ -56,19 +56,14 @@ LL | struct_().await.method();
| ++++++
error[E0308]: mismatched types
- --> $DIR/issue-61076.rs:91:9
+ --> $DIR/issue-61076.rs:88:9
|
LL | match tuple() {
| ------- this expression has type `impl Future<Output = Tuple>`
LL |
LL | Tuple(_) => {}
- | ^^^^^^^^ expected opaque type, found struct `Tuple`
+ | ^^^^^^^^ expected future, found `Tuple`
|
-note: while checking the return type of the `async fn`
- --> $DIR/issue-61076.rs:56:21
- |
-LL | async fn tuple() -> Tuple {
- | ^^^^^ checked the `Output` of this `async fn`, expected opaque type
= note: expected opaque type `impl Future<Output = Tuple>`
found struct `Tuple`
help: consider `await`ing on the `Future`
diff --git a/tests/ui/async-await/issue-64130-1-sync.drop_tracking.stderr b/tests/ui/async-await/issue-64130-1-sync.drop_tracking.stderr
new file mode 100644
index 000000000..c4c7f26c7
--- /dev/null
+++ b/tests/ui/async-await/issue-64130-1-sync.drop_tracking.stderr
@@ -0,0 +1,25 @@
+error: future cannot be shared between threads safely
+ --> $DIR/issue-64130-1-sync.rs:25:13
+ |
+LL | is_sync(bar());
+ | ^^^^^ future returned by `bar` is not `Sync`
+ |
+ = help: within `impl Future<Output = ()>`, the trait `Sync` is not implemented for `Foo`
+note: future is not `Sync` as this value is used across an await
+ --> $DIR/issue-64130-1-sync.rs:18:10
+ |
+LL | let x = Foo;
+ | - has type `Foo` which is not `Sync`
+LL | baz().await;
+ | ^^^^^^ await occurs here, with `x` maybe used later
+LL | drop(x);
+LL | }
+ | - `x` is later dropped here
+note: required by a bound in `is_sync`
+ --> $DIR/issue-64130-1-sync.rs:14:15
+ |
+LL | fn is_sync<T: Sync>(t: T) { }
+ | ^^^^ required by this bound in `is_sync`
+
+error: aborting due to previous error
+
diff --git a/tests/ui/async-await/issue-64130-1-sync.drop_tracking_mir.stderr b/tests/ui/async-await/issue-64130-1-sync.drop_tracking_mir.stderr
new file mode 100644
index 000000000..6f43b568a
--- /dev/null
+++ b/tests/ui/async-await/issue-64130-1-sync.drop_tracking_mir.stderr
@@ -0,0 +1,22 @@
+error: future cannot be shared between threads safely
+ --> $DIR/issue-64130-1-sync.rs:25:13
+ |
+LL | is_sync(bar());
+ | ^^^^^ future returned by `bar` is not `Sync`
+ |
+ = help: within `impl Future<Output = ()>`, the trait `Sync` is not implemented for `Foo`
+note: future is not `Sync` as this value is used across an await
+ --> $DIR/issue-64130-1-sync.rs:18:10
+ |
+LL | let x = Foo;
+ | - has type `Foo` which is not `Sync`
+LL | baz().await;
+ | ^^^^^^ await occurs here, with `x` maybe used later
+note: required by a bound in `is_sync`
+ --> $DIR/issue-64130-1-sync.rs:14:15
+ |
+LL | fn is_sync<T: Sync>(t: T) { }
+ | ^^^^ required by this bound in `is_sync`
+
+error: aborting due to previous error
+
diff --git a/tests/ui/async-await/issue-64130-1-sync.no_drop_tracking.stderr b/tests/ui/async-await/issue-64130-1-sync.no_drop_tracking.stderr
new file mode 100644
index 000000000..c4c7f26c7
--- /dev/null
+++ b/tests/ui/async-await/issue-64130-1-sync.no_drop_tracking.stderr
@@ -0,0 +1,25 @@
+error: future cannot be shared between threads safely
+ --> $DIR/issue-64130-1-sync.rs:25:13
+ |
+LL | is_sync(bar());
+ | ^^^^^ future returned by `bar` is not `Sync`
+ |
+ = help: within `impl Future<Output = ()>`, the trait `Sync` is not implemented for `Foo`
+note: future is not `Sync` as this value is used across an await
+ --> $DIR/issue-64130-1-sync.rs:18:10
+ |
+LL | let x = Foo;
+ | - has type `Foo` which is not `Sync`
+LL | baz().await;
+ | ^^^^^^ await occurs here, with `x` maybe used later
+LL | drop(x);
+LL | }
+ | - `x` is later dropped here
+note: required by a bound in `is_sync`
+ --> $DIR/issue-64130-1-sync.rs:14:15
+ |
+LL | fn is_sync<T: Sync>(t: T) { }
+ | ^^^^ required by this bound in `is_sync`
+
+error: aborting due to previous error
+
diff --git a/tests/ui/async-await/issue-64130-1-sync.rs b/tests/ui/async-await/issue-64130-1-sync.rs
index 1714cec52..44646e0e5 100644
--- a/tests/ui/async-await/issue-64130-1-sync.rs
+++ b/tests/ui/async-await/issue-64130-1-sync.rs
@@ -1,3 +1,6 @@
+// revisions: no_drop_tracking drop_tracking drop_tracking_mir
+// [drop_tracking] compile-flags: -Zdrop-tracking
+// [drop_tracking_mir] compile-flags: -Zdrop-tracking-mir
#![feature(negative_impls)]
// edition:2018
@@ -13,6 +16,7 @@ fn is_sync<T: Sync>(t: T) { }
async fn bar() {
let x = Foo;
baz().await;
+ drop(x);
}
async fn baz() { }
diff --git a/tests/ui/async-await/issue-64130-1-sync.stderr b/tests/ui/async-await/issue-64130-1-sync.stderr
index e205de473..8d5169a63 100644
--- a/tests/ui/async-await/issue-64130-1-sync.stderr
+++ b/tests/ui/async-await/issue-64130-1-sync.stderr
@@ -1,12 +1,12 @@
error: future cannot be shared between threads safely
- --> $DIR/issue-64130-1-sync.rs:21:13
+ --> $DIR/issue-64130-1-sync.rs:24:13
|
LL | is_sync(bar());
| ^^^^^ future returned by `bar` is not `Sync`
|
= help: within `impl Future<Output = ()>`, the trait `Sync` is not implemented for `Foo`
note: future is not `Sync` as this value is used across an await
- --> $DIR/issue-64130-1-sync.rs:15:10
+ --> $DIR/issue-64130-1-sync.rs:18:10
|
LL | let x = Foo;
| - has type `Foo` which is not `Sync`
@@ -15,7 +15,7 @@ LL | baz().await;
LL | }
| - `x` is later dropped here
note: required by a bound in `is_sync`
- --> $DIR/issue-64130-1-sync.rs:11:15
+ --> $DIR/issue-64130-1-sync.rs:14:15
|
LL | fn is_sync<T: Sync>(t: T) { }
| ^^^^ required by this bound in `is_sync`
diff --git a/tests/ui/async-await/issue-64130-2-send.drop_tracking.stderr b/tests/ui/async-await/issue-64130-2-send.drop_tracking.stderr
new file mode 100644
index 000000000..b6a73c2a5
--- /dev/null
+++ b/tests/ui/async-await/issue-64130-2-send.drop_tracking.stderr
@@ -0,0 +1,28 @@
+error: future cannot be sent between threads safely
+ --> $DIR/issue-64130-2-send.rs:24:13
+ |
+LL | is_send(bar());
+ | ^^^^^ future returned by `bar` is not `Send`
+ |
+ = note: the trait bound `Unique<Foo>: Send` is not satisfied
+note: future is not `Send` as this value is used across an await
+ --> $DIR/issue-64130-2-send.rs:18:10
+ |
+LL | let x = Box::new(Foo);
+ | - has type `Box<Foo>` which is not `Send`
+LL | baz().await;
+ | ^^^^^^ await occurs here, with `x` maybe used later
+LL | }
+ | - `x` is later dropped here
+note: required by a bound in `is_send`
+ --> $DIR/issue-64130-2-send.rs:14:15
+ |
+LL | fn is_send<T: Send>(t: T) { }
+ | ^^^^ required by this bound in `is_send`
+help: consider borrowing here
+ |
+LL | is_send(&bar());
+ | +
+
+error: aborting due to previous error
+
diff --git a/tests/ui/async-await/issue-64130-2-send.drop_tracking_mir.stderr b/tests/ui/async-await/issue-64130-2-send.drop_tracking_mir.stderr
new file mode 100644
index 000000000..560560f60
--- /dev/null
+++ b/tests/ui/async-await/issue-64130-2-send.drop_tracking_mir.stderr
@@ -0,0 +1,26 @@
+error: future cannot be sent between threads safely
+ --> $DIR/issue-64130-2-send.rs:24:13
+ |
+LL | is_send(bar());
+ | ^^^^^ future returned by `bar` is not `Send`
+ |
+ = note: the trait bound `Unique<Foo>: Send` is not satisfied
+note: future is not `Send` as this value is used across an await
+ --> $DIR/issue-64130-2-send.rs:18:10
+ |
+LL | let x = Box::new(Foo);
+ | - has type `Box<Foo>` which is not `Send`
+LL | baz().await;
+ | ^^^^^^ await occurs here, with `x` maybe used later
+note: required by a bound in `is_send`
+ --> $DIR/issue-64130-2-send.rs:14:15
+ |
+LL | fn is_send<T: Send>(t: T) { }
+ | ^^^^ required by this bound in `is_send`
+help: consider borrowing here
+ |
+LL | is_send(&bar());
+ | +
+
+error: aborting due to previous error
+
diff --git a/tests/ui/async-await/issue-64130-2-send.no_drop_tracking.stderr b/tests/ui/async-await/issue-64130-2-send.no_drop_tracking.stderr
new file mode 100644
index 000000000..b6a73c2a5
--- /dev/null
+++ b/tests/ui/async-await/issue-64130-2-send.no_drop_tracking.stderr
@@ -0,0 +1,28 @@
+error: future cannot be sent between threads safely
+ --> $DIR/issue-64130-2-send.rs:24:13
+ |
+LL | is_send(bar());
+ | ^^^^^ future returned by `bar` is not `Send`
+ |
+ = note: the trait bound `Unique<Foo>: Send` is not satisfied
+note: future is not `Send` as this value is used across an await
+ --> $DIR/issue-64130-2-send.rs:18:10
+ |
+LL | let x = Box::new(Foo);
+ | - has type `Box<Foo>` which is not `Send`
+LL | baz().await;
+ | ^^^^^^ await occurs here, with `x` maybe used later
+LL | }
+ | - `x` is later dropped here
+note: required by a bound in `is_send`
+ --> $DIR/issue-64130-2-send.rs:14:15
+ |
+LL | fn is_send<T: Send>(t: T) { }
+ | ^^^^ required by this bound in `is_send`
+help: consider borrowing here
+ |
+LL | is_send(&bar());
+ | +
+
+error: aborting due to previous error
+
diff --git a/tests/ui/async-await/issue-64130-2-send.rs b/tests/ui/async-await/issue-64130-2-send.rs
index 7a6e5952c..d6d855bac 100644
--- a/tests/ui/async-await/issue-64130-2-send.rs
+++ b/tests/ui/async-await/issue-64130-2-send.rs
@@ -1,3 +1,6 @@
+// revisions: no_drop_tracking drop_tracking drop_tracking_mir
+// [drop_tracking] compile-flags: -Zdrop-tracking
+// [drop_tracking_mir] compile-flags: -Zdrop-tracking-mir
#![feature(negative_impls)]
// edition:2018
@@ -11,7 +14,7 @@ impl !Send for Foo {}
fn is_send<T: Send>(t: T) { }
async fn bar() {
- let x = Foo;
+ let x = Box::new(Foo);
baz().await;
}
diff --git a/tests/ui/async-await/issue-64130-2-send.stderr b/tests/ui/async-await/issue-64130-2-send.stderr
index 2225000e2..f6505cad6 100644
--- a/tests/ui/async-await/issue-64130-2-send.stderr
+++ b/tests/ui/async-await/issue-64130-2-send.stderr
@@ -1,12 +1,12 @@
error: future cannot be sent between threads safely
- --> $DIR/issue-64130-2-send.rs:21:13
+ --> $DIR/issue-64130-2-send.rs:24:13
|
LL | is_send(bar());
| ^^^^^ future returned by `bar` is not `Send`
|
= help: within `impl Future<Output = ()>`, the trait `Send` is not implemented for `Foo`
note: future is not `Send` as this value is used across an await
- --> $DIR/issue-64130-2-send.rs:15:10
+ --> $DIR/issue-64130-2-send.rs:18:10
|
LL | let x = Foo;
| - has type `Foo` which is not `Send`
@@ -15,7 +15,7 @@ LL | baz().await;
LL | }
| - `x` is later dropped here
note: required by a bound in `is_send`
- --> $DIR/issue-64130-2-send.rs:11:15
+ --> $DIR/issue-64130-2-send.rs:14:15
|
LL | fn is_send<T: Send>(t: T) { }
| ^^^^ required by this bound in `is_send`
diff --git a/tests/ui/async-await/issue-64130-3-other.drop_tracking.stderr b/tests/ui/async-await/issue-64130-3-other.drop_tracking.stderr
new file mode 100644
index 000000000..d65aae8cc
--- /dev/null
+++ b/tests/ui/async-await/issue-64130-3-other.drop_tracking.stderr
@@ -0,0 +1,27 @@
+error[E0277]: the trait bound `Foo: Qux` is not satisfied in `impl Future<Output = ()>`
+ --> $DIR/issue-64130-3-other.rs:27:12
+ |
+LL | async fn bar() {
+ | - within this `impl Future<Output = ()>`
+...
+LL | is_qux(bar());
+ | ^^^^^ within `impl Future<Output = ()>`, the trait `Qux` is not implemented for `Foo`
+ |
+note: future does not implement `Qux` as this value is used across an await
+ --> $DIR/issue-64130-3-other.rs:21:10
+ |
+LL | let x = Box::new(Foo);
+ | - has type `Box<Foo>` which does not implement `Qux`
+LL | baz().await;
+ | ^^^^^^ await occurs here, with `x` maybe used later
+LL | }
+ | - `x` is later dropped here
+note: required by a bound in `is_qux`
+ --> $DIR/issue-64130-3-other.rs:17:14
+ |
+LL | fn is_qux<T: Qux>(t: T) {}
+ | ^^^ required by this bound in `is_qux`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/async-await/issue-64130-3-other.drop_tracking_mir.stderr b/tests/ui/async-await/issue-64130-3-other.drop_tracking_mir.stderr
new file mode 100644
index 000000000..8fed69d9d
--- /dev/null
+++ b/tests/ui/async-await/issue-64130-3-other.drop_tracking_mir.stderr
@@ -0,0 +1,25 @@
+error[E0277]: the trait bound `Foo: Qux` is not satisfied in `impl Future<Output = ()>`
+ --> $DIR/issue-64130-3-other.rs:27:12
+ |
+LL | async fn bar() {
+ | - within this `impl Future<Output = ()>`
+...
+LL | is_qux(bar());
+ | ^^^^^ within `impl Future<Output = ()>`, the trait `Qux` is not implemented for `Foo`
+ |
+note: future does not implement `Qux` as this value is used across an await
+ --> $DIR/issue-64130-3-other.rs:21:10
+ |
+LL | let x = Box::new(Foo);
+ | - has type `Box<Foo>` which does not implement `Qux`
+LL | baz().await;
+ | ^^^^^^ await occurs here, with `x` maybe used later
+note: required by a bound in `is_qux`
+ --> $DIR/issue-64130-3-other.rs:17:14
+ |
+LL | fn is_qux<T: Qux>(t: T) {}
+ | ^^^ required by this bound in `is_qux`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/async-await/issue-64130-3-other.no_drop_tracking.stderr b/tests/ui/async-await/issue-64130-3-other.no_drop_tracking.stderr
new file mode 100644
index 000000000..d65aae8cc
--- /dev/null
+++ b/tests/ui/async-await/issue-64130-3-other.no_drop_tracking.stderr
@@ -0,0 +1,27 @@
+error[E0277]: the trait bound `Foo: Qux` is not satisfied in `impl Future<Output = ()>`
+ --> $DIR/issue-64130-3-other.rs:27:12
+ |
+LL | async fn bar() {
+ | - within this `impl Future<Output = ()>`
+...
+LL | is_qux(bar());
+ | ^^^^^ within `impl Future<Output = ()>`, the trait `Qux` is not implemented for `Foo`
+ |
+note: future does not implement `Qux` as this value is used across an await
+ --> $DIR/issue-64130-3-other.rs:21:10
+ |
+LL | let x = Box::new(Foo);
+ | - has type `Box<Foo>` which does not implement `Qux`
+LL | baz().await;
+ | ^^^^^^ await occurs here, with `x` maybe used later
+LL | }
+ | - `x` is later dropped here
+note: required by a bound in `is_qux`
+ --> $DIR/issue-64130-3-other.rs:17:14
+ |
+LL | fn is_qux<T: Qux>(t: T) {}
+ | ^^^ required by this bound in `is_qux`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/async-await/issue-64130-3-other.rs b/tests/ui/async-await/issue-64130-3-other.rs
index 630fb2c41..92d3b7c81 100644
--- a/tests/ui/async-await/issue-64130-3-other.rs
+++ b/tests/ui/async-await/issue-64130-3-other.rs
@@ -1,3 +1,6 @@
+// revisions: no_drop_tracking drop_tracking drop_tracking_mir
+// [drop_tracking] compile-flags: -Zdrop-tracking
+// [drop_tracking_mir] compile-flags: -Zdrop-tracking-mir
#![feature(auto_traits)]
#![feature(negative_impls)]
// edition:2018
@@ -14,7 +17,7 @@ impl !Qux for Foo {}
fn is_qux<T: Qux>(t: T) {}
async fn bar() {
- let x = Foo;
+ let x = Box::new(Foo);
baz().await;
}
diff --git a/tests/ui/async-await/issue-64130-3-other.stderr b/tests/ui/async-await/issue-64130-3-other.stderr
index 17867a6a3..cb36a3811 100644
--- a/tests/ui/async-await/issue-64130-3-other.stderr
+++ b/tests/ui/async-await/issue-64130-3-other.stderr
@@ -1,5 +1,5 @@
error[E0277]: the trait bound `Foo: Qux` is not satisfied in `impl Future<Output = ()>`
- --> $DIR/issue-64130-3-other.rs:24:12
+ --> $DIR/issue-64130-3-other.rs:27:12
|
LL | async fn bar() {
| - within this `impl Future<Output = ()>`
@@ -8,7 +8,7 @@ LL | is_qux(bar());
| ^^^^^ within `impl Future<Output = ()>`, the trait `Qux` is not implemented for `Foo`
|
note: future does not implement `Qux` as this value is used across an await
- --> $DIR/issue-64130-3-other.rs:18:10
+ --> $DIR/issue-64130-3-other.rs:21:10
|
LL | let x = Foo;
| - has type `Foo` which does not implement `Qux`
@@ -17,7 +17,7 @@ LL | baz().await;
LL | }
| - `x` is later dropped here
note: required by a bound in `is_qux`
- --> $DIR/issue-64130-3-other.rs:14:14
+ --> $DIR/issue-64130-3-other.rs:17:14
|
LL | fn is_qux<T: Qux>(t: T) {}
| ^^^ required by this bound in `is_qux`
diff --git a/tests/ui/async-await/issue-64130-4-async-move.drop-tracking.stderr b/tests/ui/async-await/issue-64130-4-async-move.drop-tracking.stderr
index f609e3636..884619f4d 100644
--- a/tests/ui/async-await/issue-64130-4-async-move.drop-tracking.stderr
+++ b/tests/ui/async-await/issue-64130-4-async-move.drop-tracking.stderr
@@ -1,12 +1,12 @@
error: future cannot be sent between threads safely
- --> $DIR/issue-64130-4-async-move.rs:19:17
+ --> $DIR/issue-64130-4-async-move.rs:20:17
|
LL | pub fn foo() -> impl Future + Send {
| ^^^^^^^^^^^^^^^^^^ future created by async block is not `Send`
|
= help: the trait `Sync` is not implemented for `(dyn Any + Send + 'static)`
note: future is not `Send` as this value is used across an await
- --> $DIR/issue-64130-4-async-move.rs:25:31
+ --> $DIR/issue-64130-4-async-move.rs:27:31
|
LL | match client.status() {
| ------ has type `&Client` which is not `Send`
@@ -17,7 +17,7 @@ LL | let _x = get().await;
LL | }
| - `client` is later dropped here
help: consider moving this into a `let` binding to create a shorter lived borrow
- --> $DIR/issue-64130-4-async-move.rs:23:15
+ --> $DIR/issue-64130-4-async-move.rs:25:15
|
LL | match client.status() {
| ^^^^^^^^^^^^^^^
diff --git a/tests/ui/async-await/issue-64130-4-async-move.no_drop_tracking.stderr b/tests/ui/async-await/issue-64130-4-async-move.no_drop_tracking.stderr
index f609e3636..0bc7cb2f2 100644
--- a/tests/ui/async-await/issue-64130-4-async-move.no_drop_tracking.stderr
+++ b/tests/ui/async-await/issue-64130-4-async-move.no_drop_tracking.stderr
@@ -1,12 +1,12 @@
error: future cannot be sent between threads safely
- --> $DIR/issue-64130-4-async-move.rs:19:17
+ --> $DIR/issue-64130-4-async-move.rs:21:17
|
LL | pub fn foo() -> impl Future + Send {
| ^^^^^^^^^^^^^^^^^^ future created by async block is not `Send`
|
= help: the trait `Sync` is not implemented for `(dyn Any + Send + 'static)`
note: future is not `Send` as this value is used across an await
- --> $DIR/issue-64130-4-async-move.rs:25:31
+ --> $DIR/issue-64130-4-async-move.rs:27:31
|
LL | match client.status() {
| ------ has type `&Client` which is not `Send`
@@ -17,7 +17,7 @@ LL | let _x = get().await;
LL | }
| - `client` is later dropped here
help: consider moving this into a `let` binding to create a shorter lived borrow
- --> $DIR/issue-64130-4-async-move.rs:23:15
+ --> $DIR/issue-64130-4-async-move.rs:25:15
|
LL | match client.status() {
| ^^^^^^^^^^^^^^^
diff --git a/tests/ui/async-await/issue-64130-4-async-move.rs b/tests/ui/async-await/issue-64130-4-async-move.rs
index a38428fc0..bcb297aaa 100644
--- a/tests/ui/async-await/issue-64130-4-async-move.rs
+++ b/tests/ui/async-await/issue-64130-4-async-move.rs
@@ -1,8 +1,10 @@
// edition:2018
-// revisions: no_drop_tracking drop_tracking
+// revisions: no_drop_tracking drop_tracking drop_tracking_mir
+// [drop_tracking] compile-flags: -Zdrop-tracking
+// [drop_tracking_mir] compile-flags: -Zdrop-tracking-mir
+// [drop_tracking_mir] check-pass
// [drop_tracking] check-pass
-// [drop_tracking] compile-flags: -Zdrop-tracking=yes
-// [no_drop_tracking] compile-flags: -Zdrop-tracking=no
+
use std::any::Any;
use std::future::Future;
diff --git a/tests/ui/async-await/issue-67252-unnamed-future.drop_tracking.stderr b/tests/ui/async-await/issue-67252-unnamed-future.drop_tracking.stderr
new file mode 100644
index 000000000..fc8bcc8ae
--- /dev/null
+++ b/tests/ui/async-await/issue-67252-unnamed-future.drop_tracking.stderr
@@ -0,0 +1,30 @@
+error: future cannot be sent between threads safely
+ --> $DIR/issue-67252-unnamed-future.rs:21:11
+ |
+LL | spawn(async {
+ | ___________^
+LL | | let a = std::ptr::null_mut::<()>(); // `*mut ()` is not `Send`
+LL | | AFuture.await;
+LL | | drop(a);
+LL | | });
+ | |_____^ future created by async block is not `Send`
+ |
+ = help: within `[async block@$DIR/issue-67252-unnamed-future.rs:21:11: 25:6]`, the trait `Send` is not implemented for `*mut ()`
+note: future is not `Send` as this value is used across an await
+ --> $DIR/issue-67252-unnamed-future.rs:23:16
+ |
+LL | let a = std::ptr::null_mut::<()>(); // `*mut ()` is not `Send`
+ | - has type `*mut ()` which is not `Send`
+LL | AFuture.await;
+ | ^^^^^^ await occurs here, with `a` maybe used later
+LL | drop(a);
+LL | });
+ | - `a` is later dropped here
+note: required by a bound in `spawn`
+ --> $DIR/issue-67252-unnamed-future.rs:9:13
+ |
+LL | fn spawn<T: Send>(_: T) {}
+ | ^^^^ required by this bound in `spawn`
+
+error: aborting due to previous error
+
diff --git a/tests/ui/async-await/issue-67252-unnamed-future.drop_tracking_mir.stderr b/tests/ui/async-await/issue-67252-unnamed-future.drop_tracking_mir.stderr
new file mode 100644
index 000000000..a3ef7add1
--- /dev/null
+++ b/tests/ui/async-await/issue-67252-unnamed-future.drop_tracking_mir.stderr
@@ -0,0 +1,22 @@
+error: future cannot be sent between threads safely
+ --> $DIR/issue-67252-unnamed-future.rs:21:5
+ |
+LL | spawn(async {
+ | ^^^^^ future created by async block is not `Send`
+ |
+ = help: within `[async block@$DIR/issue-67252-unnamed-future.rs:21:11: 25:6]`, the trait `Send` is not implemented for `*mut ()`
+note: future is not `Send` as this value is used across an await
+ --> $DIR/issue-67252-unnamed-future.rs:23:16
+ |
+LL | let a = std::ptr::null_mut::<()>(); // `*mut ()` is not `Send`
+ | - has type `*mut ()` which is not `Send`
+LL | AFuture.await;
+ | ^^^^^^ await occurs here, with `a` maybe used later
+note: required by a bound in `spawn`
+ --> $DIR/issue-67252-unnamed-future.rs:9:13
+ |
+LL | fn spawn<T: Send>(_: T) {}
+ | ^^^^ required by this bound in `spawn`
+
+error: aborting due to previous error
+
diff --git a/tests/ui/async-await/issue-67252-unnamed-future.no_drop_tracking.stderr b/tests/ui/async-await/issue-67252-unnamed-future.no_drop_tracking.stderr
new file mode 100644
index 000000000..fc8bcc8ae
--- /dev/null
+++ b/tests/ui/async-await/issue-67252-unnamed-future.no_drop_tracking.stderr
@@ -0,0 +1,30 @@
+error: future cannot be sent between threads safely
+ --> $DIR/issue-67252-unnamed-future.rs:21:11
+ |
+LL | spawn(async {
+ | ___________^
+LL | | let a = std::ptr::null_mut::<()>(); // `*mut ()` is not `Send`
+LL | | AFuture.await;
+LL | | drop(a);
+LL | | });
+ | |_____^ future created by async block is not `Send`
+ |
+ = help: within `[async block@$DIR/issue-67252-unnamed-future.rs:21:11: 25:6]`, the trait `Send` is not implemented for `*mut ()`
+note: future is not `Send` as this value is used across an await
+ --> $DIR/issue-67252-unnamed-future.rs:23:16
+ |
+LL | let a = std::ptr::null_mut::<()>(); // `*mut ()` is not `Send`
+ | - has type `*mut ()` which is not `Send`
+LL | AFuture.await;
+ | ^^^^^^ await occurs here, with `a` maybe used later
+LL | drop(a);
+LL | });
+ | - `a` is later dropped here
+note: required by a bound in `spawn`
+ --> $DIR/issue-67252-unnamed-future.rs:9:13
+ |
+LL | fn spawn<T: Send>(_: T) {}
+ | ^^^^ required by this bound in `spawn`
+
+error: aborting due to previous error
+
diff --git a/tests/ui/async-await/issue-67252-unnamed-future.rs b/tests/ui/async-await/issue-67252-unnamed-future.rs
index 1a7ff6133..bb9ad77ce 100644
--- a/tests/ui/async-await/issue-67252-unnamed-future.rs
+++ b/tests/ui/async-await/issue-67252-unnamed-future.rs
@@ -1,3 +1,6 @@
+// revisions: no_drop_tracking drop_tracking drop_tracking_mir
+// [drop_tracking] compile-flags: -Zdrop-tracking
+// [drop_tracking_mir] compile-flags: -Zdrop-tracking-mir
// edition:2018
use std::future::Future;
use std::pin::Pin;
@@ -16,8 +19,9 @@ impl Future for AFuture{
async fn foo() {
spawn(async { //~ ERROR future cannot be sent between threads safely
- let _a = std::ptr::null_mut::<()>(); // `*mut ()` is not `Send`
+ let a = std::ptr::null_mut::<()>(); // `*mut ()` is not `Send`
AFuture.await;
+ drop(a);
});
}
diff --git a/tests/ui/async-await/issue-67252-unnamed-future.stderr b/tests/ui/async-await/issue-67252-unnamed-future.stderr
deleted file mode 100644
index fcba4410b..000000000
--- a/tests/ui/async-await/issue-67252-unnamed-future.stderr
+++ /dev/null
@@ -1,28 +0,0 @@
-error: future cannot be sent between threads safely
- --> $DIR/issue-67252-unnamed-future.rs:18:11
- |
-LL | spawn(async {
- | ___________^
-LL | | let _a = std::ptr::null_mut::<()>(); // `*mut ()` is not `Send`
-LL | | AFuture.await;
-LL | | });
- | |_____^ future created by async block is not `Send`
- |
- = help: within `[async block@$DIR/issue-67252-unnamed-future.rs:18:11: 21:6]`, the trait `Send` is not implemented for `*mut ()`
-note: future is not `Send` as this value is used across an await
- --> $DIR/issue-67252-unnamed-future.rs:20:16
- |
-LL | let _a = std::ptr::null_mut::<()>(); // `*mut ()` is not `Send`
- | -- has type `*mut ()` which is not `Send`
-LL | AFuture.await;
- | ^^^^^^ await occurs here, with `_a` maybe used later
-LL | });
- | - `_a` is later dropped here
-note: required by a bound in `spawn`
- --> $DIR/issue-67252-unnamed-future.rs:6:13
- |
-LL | fn spawn<T: Send>(_: T) {}
- | ^^^^ required by this bound in `spawn`
-
-error: aborting due to previous error
-
diff --git a/tests/ui/async-await/issue-68112.drop_tracking.stderr b/tests/ui/async-await/issue-68112.drop_tracking.stderr
index f2802698f..bd648de30 100644
--- a/tests/ui/async-await/issue-68112.drop_tracking.stderr
+++ b/tests/ui/async-await/issue-68112.drop_tracking.stderr
@@ -5,6 +5,7 @@ LL | require_send(send_fut);
| ^^^^^^^^ future created by async block is not `Send`
|
= help: the trait `Sync` is not implemented for `RefCell<i32>`
+ = note: if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` instead
note: future is not `Send` as it awaits another future which is not `Send`
--> $DIR/issue-68112.rs:34:17
|
@@ -23,6 +24,7 @@ LL | require_send(send_fut);
| ^^^^^^^^ future created by async block is not `Send`
|
= help: the trait `Sync` is not implemented for `RefCell<i32>`
+ = note: if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` instead
note: future is not `Send` as it awaits another future which is not `Send`
--> $DIR/issue-68112.rs:43:17
|
@@ -43,6 +45,7 @@ LL | require_send(send_fut);
| required by a bound introduced by this call
|
= help: the trait `Sync` is not implemented for `RefCell<i32>`
+ = note: if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` instead
= note: required for `Arc<RefCell<i32>>` to implement `Send`
note: required because it's used within this `async fn` body
--> $DIR/issue-68112.rs:50:31
diff --git a/tests/ui/async-await/issue-68112.drop_tracking_mir.stderr b/tests/ui/async-await/issue-68112.drop_tracking_mir.stderr
new file mode 100644
index 000000000..7a9242cba
--- /dev/null
+++ b/tests/ui/async-await/issue-68112.drop_tracking_mir.stderr
@@ -0,0 +1,80 @@
+error: future cannot be sent between threads safely
+ --> $DIR/issue-68112.rs:37:5
+ |
+LL | require_send(send_fut);
+ | ^^^^^^^^^^^^ future created by async block is not `Send`
+ |
+ = help: the trait `Sync` is not implemented for `RefCell<i32>`
+ = note: if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` instead
+note: future is not `Send` as it awaits another future which is not `Send`
+ --> $DIR/issue-68112.rs:34:17
+ |
+LL | let _ = non_send_fut.await;
+ | ^^^^^^^^^^^^ await occurs here on type `impl Future<Output = Arc<RefCell<i32>>>`, which is not `Send`
+note: required by a bound in `require_send`
+ --> $DIR/issue-68112.rs:14:25
+ |
+LL | fn require_send(_: impl Send) {}
+ | ^^^^ required by this bound in `require_send`
+
+error: future cannot be sent between threads safely
+ --> $DIR/issue-68112.rs:46:5
+ |
+LL | require_send(send_fut);
+ | ^^^^^^^^^^^^ future created by async block is not `Send`
+ |
+ = help: the trait `Sync` is not implemented for `RefCell<i32>`
+ = note: if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` instead
+note: future is not `Send` as it awaits another future which is not `Send`
+ --> $DIR/issue-68112.rs:43:17
+ |
+LL | let _ = make_non_send_future1().await;
+ | ^^^^^^^^^^^^^^^^^^^^^^^ await occurs here on type `impl Future<Output = Arc<RefCell<i32>>>`, which is not `Send`
+note: required by a bound in `require_send`
+ --> $DIR/issue-68112.rs:14:25
+ |
+LL | fn require_send(_: impl Send) {}
+ | ^^^^ required by this bound in `require_send`
+
+error[E0277]: `RefCell<i32>` cannot be shared between threads safely
+ --> $DIR/issue-68112.rs:65:5
+ |
+LL | require_send(send_fut);
+ | ^^^^^^^^^^^^ `RefCell<i32>` cannot be shared between threads safely
+ |
+ = help: the trait `Sync` is not implemented for `RefCell<i32>`
+ = note: if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` instead
+ = note: required for `Arc<RefCell<i32>>` to implement `Send`
+note: required because it's used within this `async fn` body
+ --> $DIR/issue-68112.rs:50:31
+ |
+LL | async fn ready2<T>(t: T) -> T {
+ | _______________________________^
+LL | | t
+LL | | }
+ | |_^
+note: required because it appears within the type `impl Future<Output = Arc<RefCell<i32>>>`
+ --> $DIR/issue-68112.rs:53:31
+ |
+LL | fn make_non_send_future2() -> impl Future<Output = Arc<RefCell<i32>>> {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ = note: required because it captures the following types: `impl Future<Output = Arc<RefCell<i32>>>`, `Ready<i32>`
+note: required because it's used within this `async` block
+ --> $DIR/issue-68112.rs:60:20
+ |
+LL | let send_fut = async {
+ | ____________________^
+LL | | let non_send_fut = make_non_send_future2();
+LL | | let _ = non_send_fut.await;
+LL | | ready(0).await;
+LL | | };
+ | |_____^
+note: required by a bound in `require_send`
+ --> $DIR/issue-68112.rs:14:25
+ |
+LL | fn require_send(_: impl Send) {}
+ | ^^^^ required by this bound in `require_send`
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/async-await/issue-68112.no_drop_tracking.stderr b/tests/ui/async-await/issue-68112.no_drop_tracking.stderr
index 38eb85b30..35b7341f6 100644
--- a/tests/ui/async-await/issue-68112.no_drop_tracking.stderr
+++ b/tests/ui/async-await/issue-68112.no_drop_tracking.stderr
@@ -5,6 +5,7 @@ LL | require_send(send_fut);
| ^^^^^^^^ future created by async block is not `Send`
|
= help: the trait `Sync` is not implemented for `RefCell<i32>`
+ = note: if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` instead
note: future is not `Send` as it awaits another future which is not `Send`
--> $DIR/issue-68112.rs:34:17
|
@@ -23,6 +24,7 @@ LL | require_send(send_fut);
| ^^^^^^^^ future created by async block is not `Send`
|
= help: the trait `Sync` is not implemented for `RefCell<i32>`
+ = note: if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` instead
note: future is not `Send` as it awaits another future which is not `Send`
--> $DIR/issue-68112.rs:43:17
|
@@ -43,6 +45,7 @@ LL | require_send(send_fut);
| required by a bound introduced by this call
|
= help: the trait `Sync` is not implemented for `RefCell<i32>`
+ = note: if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` instead
= note: required for `Arc<RefCell<i32>>` to implement `Send`
note: required because it's used within this `async fn` body
--> $DIR/issue-68112.rs:50:31
diff --git a/tests/ui/async-await/issue-68112.rs b/tests/ui/async-await/issue-68112.rs
index 9c705137a..19119ae0f 100644
--- a/tests/ui/async-await/issue-68112.rs
+++ b/tests/ui/async-await/issue-68112.rs
@@ -1,7 +1,7 @@
// edition:2018
-// revisions: no_drop_tracking drop_tracking
-// [drop_tracking] compile-flags: -Zdrop-tracking=yes
-// [no_drop_tracking] compile-flags: -Zdrop-tracking=no
+// revisions: no_drop_tracking drop_tracking drop_tracking_mir
+// [drop_tracking] compile-flags: -Zdrop-tracking
+// [drop_tracking_mir] compile-flags: -Zdrop-tracking-mir
use std::{
cell::RefCell,
@@ -14,7 +14,7 @@ use std::{
fn require_send(_: impl Send) {}
struct Ready<T>(Option<T>);
-impl<T> Future for Ready<T> {
+impl<T: Unpin> Future for Ready<T> {
type Output = T;
fn poll(mut self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<T> {
Poll::Ready(self.0.take().unwrap())
diff --git a/tests/ui/async-await/issue-70818.drop_tracking.stderr b/tests/ui/async-await/issue-70818.drop_tracking.stderr
new file mode 100644
index 000000000..ab0698c3e
--- /dev/null
+++ b/tests/ui/async-await/issue-70818.drop_tracking.stderr
@@ -0,0 +1,18 @@
+error: future cannot be sent between threads safely
+ --> $DIR/issue-70818.rs:7:38
+ |
+LL | fn foo<T: Send, U>(ty: T, ty1: U) -> impl Future<Output = (T, U)> + Send {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ future created by async block is not `Send`
+ |
+note: captured value is not `Send`
+ --> $DIR/issue-70818.rs:9:18
+ |
+LL | async { (ty, ty1) }
+ | ^^^ has type `U` which is not `Send`
+help: consider restricting type parameter `U`
+ |
+LL | fn foo<T: Send, U: std::marker::Send>(ty: T, ty1: U) -> impl Future<Output = (T, U)> + Send {
+ | +++++++++++++++++++
+
+error: aborting due to previous error
+
diff --git a/tests/ui/async-await/issue-70818.drop_tracking_mir.stderr b/tests/ui/async-await/issue-70818.drop_tracking_mir.stderr
new file mode 100644
index 000000000..ab0698c3e
--- /dev/null
+++ b/tests/ui/async-await/issue-70818.drop_tracking_mir.stderr
@@ -0,0 +1,18 @@
+error: future cannot be sent between threads safely
+ --> $DIR/issue-70818.rs:7:38
+ |
+LL | fn foo<T: Send, U>(ty: T, ty1: U) -> impl Future<Output = (T, U)> + Send {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ future created by async block is not `Send`
+ |
+note: captured value is not `Send`
+ --> $DIR/issue-70818.rs:9:18
+ |
+LL | async { (ty, ty1) }
+ | ^^^ has type `U` which is not `Send`
+help: consider restricting type parameter `U`
+ |
+LL | fn foo<T: Send, U: std::marker::Send>(ty: T, ty1: U) -> impl Future<Output = (T, U)> + Send {
+ | +++++++++++++++++++
+
+error: aborting due to previous error
+
diff --git a/tests/ui/async-await/issue-70818.no_drop_tracking.stderr b/tests/ui/async-await/issue-70818.no_drop_tracking.stderr
new file mode 100644
index 000000000..ab0698c3e
--- /dev/null
+++ b/tests/ui/async-await/issue-70818.no_drop_tracking.stderr
@@ -0,0 +1,18 @@
+error: future cannot be sent between threads safely
+ --> $DIR/issue-70818.rs:7:38
+ |
+LL | fn foo<T: Send, U>(ty: T, ty1: U) -> impl Future<Output = (T, U)> + Send {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ future created by async block is not `Send`
+ |
+note: captured value is not `Send`
+ --> $DIR/issue-70818.rs:9:18
+ |
+LL | async { (ty, ty1) }
+ | ^^^ has type `U` which is not `Send`
+help: consider restricting type parameter `U`
+ |
+LL | fn foo<T: Send, U: std::marker::Send>(ty: T, ty1: U) -> impl Future<Output = (T, U)> + Send {
+ | +++++++++++++++++++
+
+error: aborting due to previous error
+
diff --git a/tests/ui/async-await/issue-70818.rs b/tests/ui/async-await/issue-70818.rs
index 019c56eb2..2941de0f5 100644
--- a/tests/ui/async-await/issue-70818.rs
+++ b/tests/ui/async-await/issue-70818.rs
@@ -1,3 +1,6 @@
+// revisions: no_drop_tracking drop_tracking drop_tracking_mir
+// [drop_tracking] compile-flags: -Zdrop-tracking
+// [drop_tracking_mir] compile-flags: -Zdrop-tracking-mir
// edition:2018
use std::future::Future;
diff --git a/tests/ui/async-await/issue-70818.stderr b/tests/ui/async-await/issue-70818.stderr
index 20109d4d1..ab0698c3e 100644
--- a/tests/ui/async-await/issue-70818.stderr
+++ b/tests/ui/async-await/issue-70818.stderr
@@ -1,11 +1,11 @@
error: future cannot be sent between threads safely
- --> $DIR/issue-70818.rs:4:38
+ --> $DIR/issue-70818.rs:7:38
|
LL | fn foo<T: Send, U>(ty: T, ty1: U) -> impl Future<Output = (T, U)> + Send {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ future created by async block is not `Send`
|
note: captured value is not `Send`
- --> $DIR/issue-70818.rs:6:18
+ --> $DIR/issue-70818.rs:9:18
|
LL | async { (ty, ty1) }
| ^^^ has type `U` which is not `Send`
diff --git a/tests/ui/async-await/issue-70935-complex-spans.drop_tracking_mir.stderr b/tests/ui/async-await/issue-70935-complex-spans.drop_tracking_mir.stderr
new file mode 100644
index 000000000..c636be15a
--- /dev/null
+++ b/tests/ui/async-await/issue-70935-complex-spans.drop_tracking_mir.stderr
@@ -0,0 +1,34 @@
+error[E0277]: `Sender<i32>` cannot be shared between threads safely
+ --> $DIR/issue-70935-complex-spans.rs:13:45
+ |
+LL | fn foo(tx: std::sync::mpsc::Sender<i32>) -> impl Future + Send {
+ | ^^^^^^^^^^^^^^^^^^ `Sender<i32>` cannot be shared between threads safely
+ |
+ = help: the trait `Sync` is not implemented for `Sender<i32>`
+ = note: required for `&Sender<i32>` to implement `Send`
+note: required because it's used within this closure
+ --> $DIR/issue-70935-complex-spans.rs:17:13
+ |
+LL | baz(|| async{
+ | ^^
+note: required because it's used within this `async fn` body
+ --> $DIR/issue-70935-complex-spans.rs:10:67
+ |
+LL | async fn baz<T>(_c: impl FnMut() -> T) where T: Future<Output=()> {
+ | ___________________________________________________________________^
+LL | | }
+ | |_^
+ = note: required because it captures the following types: `impl Future<Output = ()>`
+note: required because it's used within this `async` block
+ --> $DIR/issue-70935-complex-spans.rs:16:5
+ |
+LL | / async move {
+LL | | baz(|| async{
+LL | | foo(tx.clone());
+LL | | }).await;
+LL | | }
+ | |_____^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/async-await/issue-70935-complex-spans.rs b/tests/ui/async-await/issue-70935-complex-spans.rs
index b6d17f93a..78625bd39 100644
--- a/tests/ui/async-await/issue-70935-complex-spans.rs
+++ b/tests/ui/async-await/issue-70935-complex-spans.rs
@@ -1,7 +1,7 @@
// edition:2018
-// revisions: no_drop_tracking drop_tracking
-// [no_drop_tracking]compile-flags:-Zdrop-tracking=no
-// [drop_tracking]compile-flags:-Zdrop-tracking
+// revisions: no_drop_tracking drop_tracking drop_tracking_mir
+// [drop_tracking] compile-flags: -Zdrop-tracking
+// [drop_tracking_mir] compile-flags: -Zdrop-tracking-mir
// #70935: Check if we do not emit snippet
// with newlines which lead complex diagnostics.
@@ -12,7 +12,7 @@ async fn baz<T>(_c: impl FnMut() -> T) where T: Future<Output=()> {
fn foo(tx: std::sync::mpsc::Sender<i32>) -> impl Future + Send {
//[no_drop_tracking]~^ ERROR future cannot be sent between threads safely
- //[drop_tracking]~^^ ERROR `Sender<i32>` cannot be shared between threads
+ //[drop_tracking,drop_tracking_mir]~^^ ERROR `Sender<i32>` cannot be shared between threads
async move {
baz(|| async{
foo(tx.clone());
diff --git a/tests/ui/async-await/issue-73741-type-err-drop-tracking.drop_tracking.stderr b/tests/ui/async-await/issue-73741-type-err-drop-tracking.drop_tracking.stderr
new file mode 100644
index 000000000..6d19c3beb
--- /dev/null
+++ b/tests/ui/async-await/issue-73741-type-err-drop-tracking.drop_tracking.stderr
@@ -0,0 +1,11 @@
+error[E0070]: invalid left-hand side of assignment
+ --> $DIR/issue-73741-type-err-drop-tracking.rs:11:7
+ |
+LL | 1 = 2;
+ | - ^
+ | |
+ | cannot assign to this expression
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0070`.
diff --git a/tests/ui/async-await/issue-73741-type-err-drop-tracking.drop_tracking_mir.stderr b/tests/ui/async-await/issue-73741-type-err-drop-tracking.drop_tracking_mir.stderr
new file mode 100644
index 000000000..6d19c3beb
--- /dev/null
+++ b/tests/ui/async-await/issue-73741-type-err-drop-tracking.drop_tracking_mir.stderr
@@ -0,0 +1,11 @@
+error[E0070]: invalid left-hand side of assignment
+ --> $DIR/issue-73741-type-err-drop-tracking.rs:11:7
+ |
+LL | 1 = 2;
+ | - ^
+ | |
+ | cannot assign to this expression
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0070`.
diff --git a/tests/ui/async-await/issue-73741-type-err-drop-tracking.no_drop_tracking.stderr b/tests/ui/async-await/issue-73741-type-err-drop-tracking.no_drop_tracking.stderr
new file mode 100644
index 000000000..6d19c3beb
--- /dev/null
+++ b/tests/ui/async-await/issue-73741-type-err-drop-tracking.no_drop_tracking.stderr
@@ -0,0 +1,11 @@
+error[E0070]: invalid left-hand side of assignment
+ --> $DIR/issue-73741-type-err-drop-tracking.rs:11:7
+ |
+LL | 1 = 2;
+ | - ^
+ | |
+ | cannot assign to this expression
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0070`.
diff --git a/tests/ui/async-await/issue-73741-type-err-drop-tracking.rs b/tests/ui/async-await/issue-73741-type-err-drop-tracking.rs
index c3423ad62..1fa8d6914 100644
--- a/tests/ui/async-await/issue-73741-type-err-drop-tracking.rs
+++ b/tests/ui/async-await/issue-73741-type-err-drop-tracking.rs
@@ -1,5 +1,8 @@
// edition:2018
-// compile-flags: -Zdrop-tracking
+// revisions: no_drop_tracking drop_tracking drop_tracking_mir
+// [drop_tracking] compile-flags: -Zdrop-tracking
+// [drop_tracking_mir] compile-flags: -Zdrop-tracking-mir
+//
// Regression test for issue #73741
// Ensures that we don't emit spurious errors when
// a type error ocurrs in an `async fn`
diff --git a/tests/ui/async-await/issue-73741-type-err-drop-tracking.stderr b/tests/ui/async-await/issue-73741-type-err-drop-tracking.stderr
index d4e3b6c3b..6d19c3beb 100644
--- a/tests/ui/async-await/issue-73741-type-err-drop-tracking.stderr
+++ b/tests/ui/async-await/issue-73741-type-err-drop-tracking.stderr
@@ -1,5 +1,5 @@
error[E0070]: invalid left-hand side of assignment
- --> $DIR/issue-73741-type-err-drop-tracking.rs:8:7
+ --> $DIR/issue-73741-type-err-drop-tracking.rs:11:7
|
LL | 1 = 2;
| - ^
diff --git a/tests/ui/async-await/issue-74072-lifetime-name-annotations.stderr b/tests/ui/async-await/issue-74072-lifetime-name-annotations.stderr
index b96cab9f0..628ba1a48 100644
--- a/tests/ui/async-await/issue-74072-lifetime-name-annotations.stderr
+++ b/tests/ui/async-await/issue-74072-lifetime-name-annotations.stderr
@@ -4,9 +4,9 @@ error[E0506]: cannot assign to `*x` because it is borrowed
LL | pub async fn async_fn(x: &mut i32) -> &i32 {
| - let's call the lifetime of this reference `'1`
LL | let y = &*x;
- | --- borrow of `*x` occurs here
+ | --- `*x` is borrowed here
LL | *x += 1;
- | ^^^^^^^ assignment to borrowed `*x` occurs here
+ | ^^^^^^^ `*x` is assigned to here but it was already borrowed
LL | y
| - returning this value requires that `*x` is borrowed for `'1`
@@ -14,9 +14,9 @@ error[E0506]: cannot assign to `*x` because it is borrowed
--> $DIR/issue-74072-lifetime-name-annotations.rs:16:9
|
LL | let y = &*x;
- | --- borrow of `*x` occurs here
+ | --- `*x` is borrowed here
LL | *x += 1;
- | ^^^^^^^ assignment to borrowed `*x` occurs here
+ | ^^^^^^^ `*x` is assigned to here but it was already borrowed
LL | y
| - returning this value requires that `*x` is borrowed for `'1`
LL | })()
@@ -28,9 +28,9 @@ error[E0506]: cannot assign to `*x` because it is borrowed
LL | (async move || -> &i32 {
| - let's call the lifetime of this reference `'1`
LL | let y = &*x;
- | --- borrow of `*x` occurs here
+ | --- `*x` is borrowed here
LL | *x += 1;
- | ^^^^^^^ assignment to borrowed `*x` occurs here
+ | ^^^^^^^ `*x` is assigned to here but it was already borrowed
LL | y
| - returning this value requires that `*x` is borrowed for `'1`
@@ -38,9 +38,9 @@ error[E0506]: cannot assign to `*x` because it is borrowed
--> $DIR/issue-74072-lifetime-name-annotations.rs:32:9
|
LL | let y = &*x;
- | --- borrow of `*x` occurs here
+ | --- `*x` is borrowed here
LL | *x += 1;
- | ^^^^^^^ assignment to borrowed `*x` occurs here
+ | ^^^^^^^ `*x` is assigned to here but it was already borrowed
LL | y
| - returning this value requires that `*x` is borrowed for `'1`
LL | }
diff --git a/tests/ui/async-await/issue-75785-confusing-named-region.stderr b/tests/ui/async-await/issue-75785-confusing-named-region.stderr
index 3b731d9c6..b69033a0e 100644
--- a/tests/ui/async-await/issue-75785-confusing-named-region.stderr
+++ b/tests/ui/async-await/issue-75785-confusing-named-region.stderr
@@ -4,9 +4,9 @@ error[E0506]: cannot assign to `*x` because it is borrowed
LL | pub async fn async_fn(x: &mut i32) -> (&i32, &i32) {
| - let's call the lifetime of this reference `'1`
LL | let y = &*x;
- | --- borrow of `*x` occurs here
+ | --- `*x` is borrowed here
LL | *x += 1;
- | ^^^^^^^ assignment to borrowed `*x` occurs here
+ | ^^^^^^^ `*x` is assigned to here but it was already borrowed
LL | (&32, y)
| -------- returning this value requires that `*x` is borrowed for `'1`
diff --git a/tests/ui/async-await/issue-86507.stderr b/tests/ui/async-await/issue-86507.drop_tracking.stderr
index 8c2c06da2..5c8b7ef1b 100644
--- a/tests/ui/async-await/issue-86507.stderr
+++ b/tests/ui/async-await/issue-86507.drop_tracking.stderr
@@ -1,5 +1,5 @@
error: future cannot be sent between threads safely
- --> $DIR/issue-86507.rs:17:13
+ --> $DIR/issue-86507.rs:20:13
|
LL | / Box::pin(
LL | | async move {
@@ -9,11 +9,11 @@ LL | | )
| |_____________^ future created by async block is not `Send`
|
note: captured value is not `Send` because `&` references cannot be sent unless their referent is `Sync`
- --> $DIR/issue-86507.rs:19:29
+ --> $DIR/issue-86507.rs:22:29
|
LL | let x = x;
| ^ has type `&T` which is not `Send`, because `T` is not `Sync`
- = note: required for the cast from `[async block@$DIR/issue-86507.rs:18:17: 20:18]` to the object type `dyn Future<Output = ()> + Send`
+ = note: required for the cast from `[async block@$DIR/issue-86507.rs:21:17: 23:18]` to the object type `dyn Future<Output = ()> + Send`
help: consider further restricting this bound
|
LL | fn bar<'me, 'async_trait, T: Send + std::marker::Sync>(x: &'me T)
diff --git a/tests/ui/async-await/issue-86507.drop_tracking_mir.stderr b/tests/ui/async-await/issue-86507.drop_tracking_mir.stderr
new file mode 100644
index 000000000..5c8b7ef1b
--- /dev/null
+++ b/tests/ui/async-await/issue-86507.drop_tracking_mir.stderr
@@ -0,0 +1,23 @@
+error: future cannot be sent between threads safely
+ --> $DIR/issue-86507.rs:20:13
+ |
+LL | / Box::pin(
+LL | | async move {
+LL | | let x = x;
+LL | | }
+LL | | )
+ | |_____________^ future created by async block is not `Send`
+ |
+note: captured value is not `Send` because `&` references cannot be sent unless their referent is `Sync`
+ --> $DIR/issue-86507.rs:22:29
+ |
+LL | let x = x;
+ | ^ has type `&T` which is not `Send`, because `T` is not `Sync`
+ = note: required for the cast from `[async block@$DIR/issue-86507.rs:21:17: 23:18]` to the object type `dyn Future<Output = ()> + Send`
+help: consider further restricting this bound
+ |
+LL | fn bar<'me, 'async_trait, T: Send + std::marker::Sync>(x: &'me T)
+ | +++++++++++++++++++
+
+error: aborting due to previous error
+
diff --git a/tests/ui/async-await/issue-86507.no_drop_tracking.stderr b/tests/ui/async-await/issue-86507.no_drop_tracking.stderr
new file mode 100644
index 000000000..5c8b7ef1b
--- /dev/null
+++ b/tests/ui/async-await/issue-86507.no_drop_tracking.stderr
@@ -0,0 +1,23 @@
+error: future cannot be sent between threads safely
+ --> $DIR/issue-86507.rs:20:13
+ |
+LL | / Box::pin(
+LL | | async move {
+LL | | let x = x;
+LL | | }
+LL | | )
+ | |_____________^ future created by async block is not `Send`
+ |
+note: captured value is not `Send` because `&` references cannot be sent unless their referent is `Sync`
+ --> $DIR/issue-86507.rs:22:29
+ |
+LL | let x = x;
+ | ^ has type `&T` which is not `Send`, because `T` is not `Sync`
+ = note: required for the cast from `[async block@$DIR/issue-86507.rs:21:17: 23:18]` to the object type `dyn Future<Output = ()> + Send`
+help: consider further restricting this bound
+ |
+LL | fn bar<'me, 'async_trait, T: Send + std::marker::Sync>(x: &'me T)
+ | +++++++++++++++++++
+
+error: aborting due to previous error
+
diff --git a/tests/ui/async-await/issue-86507.rs b/tests/ui/async-await/issue-86507.rs
index 317f03176..63c298dbe 100644
--- a/tests/ui/async-await/issue-86507.rs
+++ b/tests/ui/async-await/issue-86507.rs
@@ -1,3 +1,6 @@
+// revisions: no_drop_tracking drop_tracking drop_tracking_mir
+// [drop_tracking] compile-flags: -Zdrop-tracking
+// [drop_tracking_mir] compile-flags: -Zdrop-tracking-mir
// edition:2018
use ::core::pin::Pin;
diff --git a/tests/ui/async-await/issue-93648.rs b/tests/ui/async-await/issue-93648.rs
index 4ce3ac1e8..ec2249ca5 100644
--- a/tests/ui/async-await/issue-93648.rs
+++ b/tests/ui/async-await/issue-93648.rs
@@ -1,6 +1,8 @@
+// revisions: no_drop_tracking drop_tracking drop_tracking_mir
+// [drop_tracking] compile-flags: -Zdrop-tracking
+// [drop_tracking_mir] compile-flags: -Zdrop-tracking-mir
// edition:2021
// build-pass
-// compile-flags: -Zdrop-tracking
fn main() {
let _ = async {
diff --git a/tests/ui/async-await/issue-98634.rs b/tests/ui/async-await/issue-98634.rs
index b0d38687f..169cc7f9b 100644
--- a/tests/ui/async-await/issue-98634.rs
+++ b/tests/ui/async-await/issue-98634.rs
@@ -43,8 +43,8 @@ impl Runtime {
fn main() {
Runtime.block_on(async {
StructAsync { callback }.await;
- //~^ ERROR expected `fn() -> impl Future<Output = ()> {callback}` to be a fn item that returns `Pin<Box<(dyn Future<Output = ()> + 'static)>>`, but it returns `impl Future<Output = ()>`
- //~| ERROR expected `fn() -> impl Future<Output = ()> {callback}` to be a fn item that returns `Pin<Box<(dyn Future<Output = ()> + 'static)>>`, but it returns `impl Future<Output = ()>`
- //~| ERROR expected `fn() -> impl Future<Output = ()> {callback}` to be a fn item that returns `Pin<Box<(dyn Future<Output = ()> + 'static)>>`, but it returns `impl Future<Output = ()>`
+ //~^ ERROR expected `callback` to be a fn item that returns `Pin<Box<dyn Future<Output = ()>>>`, but it returns `impl Future<Output = ()>`
+ //~| ERROR expected `callback` to be a fn item that returns `Pin<Box<dyn Future<Output = ()>>>`, but it returns `impl Future<Output = ()>`
+ //~| ERROR expected `callback` to be a fn item that returns `Pin<Box<dyn Future<Output = ()>>>`, but it returns `impl Future<Output = ()>`
});
}
diff --git a/tests/ui/async-await/issue-98634.stderr b/tests/ui/async-await/issue-98634.stderr
index 5160e48d8..5b7f18a98 100644
--- a/tests/ui/async-await/issue-98634.stderr
+++ b/tests/ui/async-await/issue-98634.stderr
@@ -1,54 +1,33 @@
-error[E0271]: expected `fn() -> impl Future<Output = ()> {callback}` to be a fn item that returns `Pin<Box<(dyn Future<Output = ()> + 'static)>>`, but it returns `impl Future<Output = ()>`
+error[E0271]: expected `callback` to be a fn item that returns `Pin<Box<dyn Future<Output = ()>>>`, but it returns `impl Future<Output = ()>`
--> $DIR/issue-98634.rs:45:23
|
LL | StructAsync { callback }.await;
- | ^^^^^^^^ expected struct `Pin`, found opaque type
+ | ^^^^^^^^ expected `Pin<Box<dyn Future<Output = ()>>>`, found future
|
-note: while checking the return type of the `async fn`
- --> $DIR/issue-98634.rs:24:21
- |
-LL | async fn callback() {}
- | ^ checked the `Output` of this `async fn`, found opaque type
- = note: expected struct `Pin<Box<(dyn Future<Output = ()> + 'static)>>`
- found opaque type `impl Future<Output = ()>`
note: required by a bound in `StructAsync`
--> $DIR/issue-98634.rs:9:35
|
LL | pub struct StructAsync<F: Fn() -> Pin<Box<dyn Future<Output = ()>>>> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `StructAsync`
-error[E0271]: expected `fn() -> impl Future<Output = ()> {callback}` to be a fn item that returns `Pin<Box<(dyn Future<Output = ()> + 'static)>>`, but it returns `impl Future<Output = ()>`
+error[E0271]: expected `callback` to be a fn item that returns `Pin<Box<dyn Future<Output = ()>>>`, but it returns `impl Future<Output = ()>`
--> $DIR/issue-98634.rs:45:9
|
LL | StructAsync { callback }.await;
- | ^^^^^^^^^^^^^^^^^^^^^^^^ expected struct `Pin`, found opaque type
- |
-note: while checking the return type of the `async fn`
- --> $DIR/issue-98634.rs:24:21
+ | ^^^^^^^^^^^^^^^^^^^^^^^^ expected `Pin<Box<dyn Future<Output = ()>>>`, found future
|
-LL | async fn callback() {}
- | ^ checked the `Output` of this `async fn`, found opaque type
- = note: expected struct `Pin<Box<(dyn Future<Output = ()> + 'static)>>`
- found opaque type `impl Future<Output = ()>`
note: required by a bound in `StructAsync`
--> $DIR/issue-98634.rs:9:35
|
LL | pub struct StructAsync<F: Fn() -> Pin<Box<dyn Future<Output = ()>>>> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `StructAsync`
-error[E0271]: expected `fn() -> impl Future<Output = ()> {callback}` to be a fn item that returns `Pin<Box<(dyn Future<Output = ()> + 'static)>>`, but it returns `impl Future<Output = ()>`
+error[E0271]: expected `callback` to be a fn item that returns `Pin<Box<dyn Future<Output = ()>>>`, but it returns `impl Future<Output = ()>`
--> $DIR/issue-98634.rs:45:33
|
LL | StructAsync { callback }.await;
- | ^^^^^^ expected struct `Pin`, found opaque type
- |
-note: while checking the return type of the `async fn`
- --> $DIR/issue-98634.rs:24:21
+ | ^^^^^^ expected `Pin<Box<dyn Future<Output = ()>>>`, found future
|
-LL | async fn callback() {}
- | ^ checked the `Output` of this `async fn`, found opaque type
- = note: expected struct `Pin<Box<(dyn Future<Output = ()> + 'static)>>`
- found opaque type `impl Future<Output = ()>`
note: required by a bound in `StructAsync`
--> $DIR/issue-98634.rs:9:35
|
diff --git a/tests/ui/async-await/issues/auxiliary/issue_67893.rs b/tests/ui/async-await/issues/auxiliary/issue_67893.rs
index 387966a50..d53944698 100644
--- a/tests/ui/async-await/issues/auxiliary/issue_67893.rs
+++ b/tests/ui/async-await/issues/auxiliary/issue_67893.rs
@@ -1,3 +1,6 @@
+// revisions: no_drop_tracking drop_tracking drop_tracking_mir
+// [drop_tracking] compile-flags: -Zdrop-tracking
+// [drop_tracking_mir] compile-flags: -Zdrop-tracking-mir
// edition:2018
use std::sync::{Arc, Mutex};
diff --git a/tests/ui/async-await/issues/issue-102206.stderr b/tests/ui/async-await/issues/issue-102206.stderr
index 2ab790ac7..750b7a886 100644
--- a/tests/ui/async-await/issues/issue-102206.stderr
+++ b/tests/ui/async-await/issues/issue-102206.stderr
@@ -4,17 +4,10 @@ error[E0308]: mismatched types
LL | std::mem::size_of_val(foo());
| --------------------- ^^^^^
| | |
- | | expected reference, found opaque type
+ | | expected `&_`, found future
| | help: consider borrowing here: `&foo()`
| arguments to this function are incorrect
|
-note: while checking the return type of the `async fn`
- --> $DIR/issue-102206.rs:3:16
- |
-LL | async fn foo() {}
- | ^ checked the `Output` of this `async fn`, found opaque type
- = note: expected reference `&_`
- found opaque type `impl Future<Output = ()>`
note: function defined here
--> $SRC_DIR/core/src/mem/mod.rs:LL:COL
diff --git a/tests/ui/async-await/issues/issue-107280.rs b/tests/ui/async-await/issues/issue-107280.rs
new file mode 100644
index 000000000..85fce8740
--- /dev/null
+++ b/tests/ui/async-await/issues/issue-107280.rs
@@ -0,0 +1,15 @@
+// edition:2021
+
+async fn foo() {
+ inner::<false>().await
+ //~^ ERROR: function takes 2 generic arguments but 1 generic argument was supplied
+ //~| ERROR: type inside `async fn` body must be known in this context
+ //~| ERROR: type inside `async fn` body must be known in this context
+ //~| ERROR: type inside `async fn` body must be known in this context
+ //~| ERROR: type inside `async fn` body must be known in this context
+ //~| ERROR: type inside `async fn` body must be known in this context
+}
+
+async fn inner<T, const PING: bool>() {}
+
+fn main() {}
diff --git a/tests/ui/async-await/issues/issue-107280.stderr b/tests/ui/async-await/issues/issue-107280.stderr
new file mode 100644
index 000000000..dd3e10fcc
--- /dev/null
+++ b/tests/ui/async-await/issues/issue-107280.stderr
@@ -0,0 +1,82 @@
+error[E0107]: function takes 2 generic arguments but 1 generic argument was supplied
+ --> $DIR/issue-107280.rs:4:5
+ |
+LL | inner::<false>().await
+ | ^^^^^ ----- supplied 1 generic argument
+ | |
+ | expected 2 generic arguments
+ |
+note: function defined here, with 2 generic parameters: `T`, `PING`
+ --> $DIR/issue-107280.rs:13:10
+ |
+LL | async fn inner<T, const PING: bool>() {}
+ | ^^^^^ - ----------------
+help: add missing generic argument
+ |
+LL | inner::<false, PING>().await
+ | ++++++
+
+error[E0698]: type inside `async fn` body must be known in this context
+ --> $DIR/issue-107280.rs:4:5
+ |
+LL | inner::<false>().await
+ | ^^^^^^^^^^^^^^ cannot infer the value of const parameter `PING` declared on the function `inner`
+ |
+note: the type is part of the `async fn` body because of this `await`
+ --> $DIR/issue-107280.rs:4:21
+ |
+LL | inner::<false>().await
+ | ^^^^^^
+
+error[E0698]: type inside `async fn` body must be known in this context
+ --> $DIR/issue-107280.rs:4:5
+ |
+LL | inner::<false>().await
+ | ^^^^^^^^^^^^^^ cannot infer the value of const parameter `PING` declared on the function `inner`
+ |
+note: the type is part of the `async fn` body because of this `await`
+ --> $DIR/issue-107280.rs:4:21
+ |
+LL | inner::<false>().await
+ | ^^^^^^
+
+error[E0698]: type inside `async fn` body must be known in this context
+ --> $DIR/issue-107280.rs:4:5
+ |
+LL | inner::<false>().await
+ | ^^^^^^^^^^^^^^ cannot infer the value of const parameter `PING` declared on the function `inner`
+ |
+note: the type is part of the `async fn` body because of this `await`
+ --> $DIR/issue-107280.rs:4:21
+ |
+LL | inner::<false>().await
+ | ^^^^^^
+
+error[E0698]: type inside `async fn` body must be known in this context
+ --> $DIR/issue-107280.rs:4:5
+ |
+LL | inner::<false>().await
+ | ^^^^^^^^^^^^^^ cannot infer the value of const parameter `PING` declared on the function `inner`
+ |
+note: the type is part of the `async fn` body because of this `await`
+ --> $DIR/issue-107280.rs:4:21
+ |
+LL | inner::<false>().await
+ | ^^^^^^
+
+error[E0698]: type inside `async fn` body must be known in this context
+ --> $DIR/issue-107280.rs:4:5
+ |
+LL | inner::<false>().await
+ | ^^^^^^^^^^^^^^ cannot infer the value of const parameter `PING` declared on the function `inner`
+ |
+note: the type is part of the `async fn` body because of this `await`
+ --> $DIR/issue-107280.rs:4:21
+ |
+LL | inner::<false>().await
+ | ^^^^^^
+
+error: aborting due to 6 previous errors
+
+Some errors have detailed explanations: E0107, E0698.
+For more information about an error, try `rustc --explain E0107`.
diff --git a/tests/ui/async-await/issues/issue-62097.rs b/tests/ui/async-await/issues/issue-62097.rs
index a24c84cff..13c72abb1 100644
--- a/tests/ui/async-await/issues/issue-62097.rs
+++ b/tests/ui/async-await/issues/issue-62097.rs
@@ -12,7 +12,7 @@ impl Struct {
pub async fn run_dummy_fn(&self) {
foo(|| self.bar()).await;
//~^ ERROR closure may outlive the current function
- //~| ERROR borrowed data escapes outside of associated function
+ //~| ERROR borrowed data escapes outside of method
}
pub fn bar(&self) {}
diff --git a/tests/ui/async-await/issues/issue-62097.stderr b/tests/ui/async-await/issues/issue-62097.stderr
index 786f62132..21a61548d 100644
--- a/tests/ui/async-await/issues/issue-62097.stderr
+++ b/tests/ui/async-await/issues/issue-62097.stderr
@@ -16,18 +16,18 @@ help: to force the closure to take ownership of `self` (and any other referenced
LL | foo(move || self.bar()).await;
| ++++
-error[E0521]: borrowed data escapes outside of associated function
+error[E0521]: borrowed data escapes outside of method
--> $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 method 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 method body here
| argument requires that `'1` must outlive `'static`
error: aborting due to 2 previous errors
diff --git a/tests/ui/async-await/issues/issue-65159.rs b/tests/ui/async-await/issues/issue-65159.rs
index df2ca0257..6e547508b 100644
--- a/tests/ui/async-await/issues/issue-65159.rs
+++ b/tests/ui/async-await/issues/issue-65159.rs
@@ -3,7 +3,7 @@
// edition:2018
async fn copy() -> Result<()>
-//~^ ERROR this enum takes 2 generic arguments
+//~^ ERROR enum takes 2 generic arguments
{
Ok(())
}
diff --git a/tests/ui/async-await/issues/issue-65159.stderr b/tests/ui/async-await/issues/issue-65159.stderr
index 40c0e72b2..b8741333c 100644
--- a/tests/ui/async-await/issues/issue-65159.stderr
+++ b/tests/ui/async-await/issues/issue-65159.stderr
@@ -1,4 +1,4 @@
-error[E0107]: this enum takes 2 generic arguments but 1 generic argument was supplied
+error[E0107]: enum takes 2 generic arguments but 1 generic argument was supplied
--> $DIR/issue-65159.rs:5:20
|
LL | async fn copy() -> Result<()>
diff --git a/tests/ui/async-await/issues/issue-65436-raw-ptr-not-send.no_drop_tracking.stderr b/tests/ui/async-await/issues/issue-65436-raw-ptr-not-send.no_drop_tracking.stderr
index 1033fa6cc..8745bdd97 100644
--- a/tests/ui/async-await/issues/issue-65436-raw-ptr-not-send.no_drop_tracking.stderr
+++ b/tests/ui/async-await/issues/issue-65436-raw-ptr-not-send.no_drop_tracking.stderr
@@ -1,5 +1,5 @@
error: future cannot be sent between threads safely
- --> $DIR/issue-65436-raw-ptr-not-send.rs:16:17
+ --> $DIR/issue-65436-raw-ptr-not-send.rs:17:17
|
LL | assert_send(async {
| _________________^
@@ -8,9 +8,9 @@ LL | | bar(Foo(std::ptr::null())).await;
LL | | })
| |_____^ future created by async block is not `Send`
|
- = help: within `[async block@$DIR/issue-65436-raw-ptr-not-send.rs:16:17: 19:6]`, the trait `Send` is not implemented for `*const u8`
+ = help: within `[async block@$DIR/issue-65436-raw-ptr-not-send.rs:17:17: 20:6]`, the trait `Send` is not implemented for `*const u8`
note: future is not `Send` as this value is used across an await
- --> $DIR/issue-65436-raw-ptr-not-send.rs:18:35
+ --> $DIR/issue-65436-raw-ptr-not-send.rs:19:35
|
LL | bar(Foo(std::ptr::null())).await;
| ---------------- ^^^^^^- `std::ptr::null()` is later dropped here
@@ -18,12 +18,12 @@ LL | bar(Foo(std::ptr::null())).await;
| | await occurs here, with `std::ptr::null()` maybe used later
| has type `*const u8` which is not `Send`
help: consider moving this into a `let` binding to create a shorter lived borrow
- --> $DIR/issue-65436-raw-ptr-not-send.rs:18:13
+ --> $DIR/issue-65436-raw-ptr-not-send.rs:19:13
|
LL | bar(Foo(std::ptr::null())).await;
| ^^^^^^^^^^^^^^^^^^^^^
note: required by a bound in `assert_send`
- --> $DIR/issue-65436-raw-ptr-not-send.rs:13:19
+ --> $DIR/issue-65436-raw-ptr-not-send.rs:14:19
|
LL | fn assert_send<T: Send>(_: T) {}
| ^^^^ required by this bound in `assert_send`
diff --git a/tests/ui/async-await/issues/issue-65436-raw-ptr-not-send.rs b/tests/ui/async-await/issues/issue-65436-raw-ptr-not-send.rs
index 91edbc10d..d7ef92951 100644
--- a/tests/ui/async-await/issues/issue-65436-raw-ptr-not-send.rs
+++ b/tests/ui/async-await/issues/issue-65436-raw-ptr-not-send.rs
@@ -1,8 +1,9 @@
// edition:2018
-// revisions: no_drop_tracking drop_tracking
+// revisions: no_drop_tracking drop_tracking drop_tracking_mir
+// [drop_tracking] compile-flags: -Zdrop-tracking
+// [drop_tracking_mir] compile-flags: -Zdrop-tracking-mir
// [drop_tracking] check-pass
-// [drop_tracking] compile-flags: -Zdrop-tracking=yes
-// [no_drop_tracking] compile-flags: -Zdrop-tracking=no
+// [drop_tracking_mir] check-pass
struct Foo(*const u8);
diff --git a/tests/ui/async-await/issues/issue-67611-static-mut-refs.rs b/tests/ui/async-await/issues/issue-67611-static-mut-refs.rs
index dda4a151d..c4f8f607d 100644
--- a/tests/ui/async-await/issues/issue-67611-static-mut-refs.rs
+++ b/tests/ui/async-await/issues/issue-67611-static-mut-refs.rs
@@ -1,6 +1,10 @@
// build-pass
// edition:2018
+// revisions: no_drop_tracking drop_tracking drop_tracking_mir
+// [drop_tracking] compile-flags: -Zdrop-tracking
+// [drop_tracking_mir] compile-flags: -Zdrop-tracking-mir
+
static mut A: [i32; 5] = [1, 2, 3, 4, 5];
fn is_send_sync<T: Send + Sync>(_: T) {}
diff --git a/tests/ui/async-await/issues/issue-67893.stderr b/tests/ui/async-await/issues/issue-67893.stderr
index 2ce68a782..ce9424c8b 100644
--- a/tests/ui/async-await/issues/issue-67893.stderr
+++ b/tests/ui/async-await/issues/issue-67893.stderr
@@ -6,7 +6,7 @@ LL | g(issue_67893::run())
|
= help: within `impl Future<Output = ()>`, the trait `Send` is not implemented for `MutexGuard<'_, ()>`
note: future is not `Send` as this value is used across an await
- --> $DIR/auxiliary/issue_67893.rs:9:26
+ --> $DIR/auxiliary/issue_67893.rs:12:26
|
LL | f(*x.lock().unwrap()).await;
| ----------------- ^^^^^^- `x.lock().unwrap()` is later dropped here
diff --git a/tests/ui/async-await/issues/issue-72312.stderr b/tests/ui/async-await/issues/issue-72312.stderr
index aa947b690..679272858 100644
--- a/tests/ui/async-await/issues/issue-72312.stderr
+++ b/tests/ui/async-await/issues/issue-72312.stderr
@@ -1,10 +1,10 @@
-error[E0521]: borrowed data escapes outside of associated function
+error[E0521]: borrowed data escapes outside of method
--> $DIR/issue-72312.rs:12:9
|
LL | pub async fn start(&self) {
| -----
| |
- | `self` is a reference that is only valid in the associated function body
+ | `self` is a reference that is only valid in the method body
| let's call the lifetime of this reference `'1`
...
LL | / require_static(async move {
@@ -15,7 +15,7 @@ LL | | &self;
LL | | });
| | ^
| | |
- | |__________`self` escapes the associated function body here
+ | |__________`self` escapes the method body here
| argument requires that `'1` must outlive `'static`
error: aborting due to previous error
diff --git a/tests/ui/async-await/multiple-lifetimes/member-constraints-min-choice-issue-63033.rs b/tests/ui/async-await/multiple-lifetimes/member-constraints-min-choice-issue-63033.rs
new file mode 100644
index 000000000..614f18972
--- /dev/null
+++ b/tests/ui/async-await/multiple-lifetimes/member-constraints-min-choice-issue-63033.rs
@@ -0,0 +1,10 @@
+// Regression test for #63033.
+
+// check-pass
+// edition: 2018
+
+async fn test1(_: &'static u8, _: &'_ u8, _: &'_ u8) {}
+
+async fn test2<'s>(_: &'s u8, _: &'_ &'s u8, _: &'_ &'s u8) {}
+
+fn main() {}
diff --git a/tests/ui/async-await/multiple-lifetimes/ret-impl-trait-one.stderr b/tests/ui/async-await/multiple-lifetimes/ret-impl-trait-one.stderr
index ae4d0d585..5ae1d78a9 100644
--- a/tests/ui/async-await/multiple-lifetimes/ret-impl-trait-one.stderr
+++ b/tests/ui/async-await/multiple-lifetimes/ret-impl-trait-one.stderr
@@ -17,8 +17,9 @@ error[E0700]: hidden type for `impl Trait<'a>` captures lifetime that does not a
--> $DIR/ret-impl-trait-one.rs:16:80
|
LL | async fn async_ret_impl_trait1<'a, 'b>(a: &'a u8, b: &'b u8) -> impl Trait<'a> {
- | ____________________________________--__________________________________________^
- | | |
+ | ____________________________________--___________________________--------------_^
+ | | | |
+ | | | opaque type defined here
| | hidden type `(&'a u8, &'b u8)` captures the lifetime `'b` as defined here
LL | |
LL | | (a, b)
diff --git a/tests/ui/async-await/multiple-lifetimes/ret-ref.stderr b/tests/ui/async-await/multiple-lifetimes/ret-ref.stderr
index d86e84033..a599ac1d9 100644
--- a/tests/ui/async-await/multiple-lifetimes/ret-ref.stderr
+++ b/tests/ui/async-await/multiple-lifetimes/ret-ref.stderr
@@ -2,9 +2,9 @@ error[E0506]: cannot assign to `a` because it is borrowed
--> $DIR/ret-ref.rs:16:5
|
LL | let future = multiple_named_lifetimes(&a, &b);
- | -- borrow of `a` occurs here
+ | -- `a` is borrowed here
LL | a += 1;
- | ^^^^^^ assignment to borrowed `a` occurs here
+ | ^^^^^^ `a` is assigned to here but it was already borrowed
LL | b += 1;
LL | let p = future.await;
| ------ borrow later used here
@@ -13,10 +13,10 @@ error[E0506]: cannot assign to `b` because it is borrowed
--> $DIR/ret-ref.rs:17:5
|
LL | let future = multiple_named_lifetimes(&a, &b);
- | -- borrow of `b` occurs here
+ | -- `b` is borrowed here
LL | a += 1;
LL | b += 1;
- | ^^^^^^ assignment to borrowed `b` occurs here
+ | ^^^^^^ `b` is assigned to here but it was already borrowed
LL | let p = future.await;
| ------ borrow later used here
@@ -24,10 +24,10 @@ error[E0506]: cannot assign to `a` because it is borrowed
--> $DIR/ret-ref.rs:28:5
|
LL | let future = multiple_named_lifetimes(&a, &b);
- | -- borrow of `a` occurs here
+ | -- `a` is borrowed here
LL | let p = future.await;
LL | a += 1;
- | ^^^^^^ assignment to borrowed `a` occurs here
+ | ^^^^^^ `a` is assigned to here but it was already borrowed
LL | b += 1;
LL | drop(p);
| - borrow later used here
diff --git a/tests/ui/async-await/mutually-recursive-async-impl-trait-type.drop_tracking.stderr b/tests/ui/async-await/mutually-recursive-async-impl-trait-type.drop_tracking.stderr
new file mode 100644
index 000000000..8a7317bb9
--- /dev/null
+++ b/tests/ui/async-await/mutually-recursive-async-impl-trait-type.drop_tracking.stderr
@@ -0,0 +1,21 @@
+error[E0733]: recursion in an `async fn` requires boxing
+ --> $DIR/mutually-recursive-async-impl-trait-type.rs:9:18
+ |
+LL | async fn rec_1() {
+ | ^ recursive `async fn`
+ |
+ = note: a recursive `async fn` must be rewritten to return a boxed `dyn Future`
+ = note: consider using the `async_recursion` crate: https://crates.io/crates/async_recursion
+
+error[E0733]: recursion in an `async fn` requires boxing
+ --> $DIR/mutually-recursive-async-impl-trait-type.rs:13:18
+ |
+LL | async fn rec_2() {
+ | ^ recursive `async fn`
+ |
+ = note: a recursive `async fn` must be rewritten to return a boxed `dyn Future`
+ = note: consider using the `async_recursion` crate: https://crates.io/crates/async_recursion
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0733`.
diff --git a/tests/ui/async-await/mutually-recursive-async-impl-trait-type.drop_tracking_mir.stderr b/tests/ui/async-await/mutually-recursive-async-impl-trait-type.drop_tracking_mir.stderr
new file mode 100644
index 000000000..8a7317bb9
--- /dev/null
+++ b/tests/ui/async-await/mutually-recursive-async-impl-trait-type.drop_tracking_mir.stderr
@@ -0,0 +1,21 @@
+error[E0733]: recursion in an `async fn` requires boxing
+ --> $DIR/mutually-recursive-async-impl-trait-type.rs:9:18
+ |
+LL | async fn rec_1() {
+ | ^ recursive `async fn`
+ |
+ = note: a recursive `async fn` must be rewritten to return a boxed `dyn Future`
+ = note: consider using the `async_recursion` crate: https://crates.io/crates/async_recursion
+
+error[E0733]: recursion in an `async fn` requires boxing
+ --> $DIR/mutually-recursive-async-impl-trait-type.rs:13:18
+ |
+LL | async fn rec_2() {
+ | ^ recursive `async fn`
+ |
+ = note: a recursive `async fn` must be rewritten to return a boxed `dyn Future`
+ = note: consider using the `async_recursion` crate: https://crates.io/crates/async_recursion
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0733`.
diff --git a/tests/ui/async-await/mutually-recursive-async-impl-trait-type.no_drop_tracking.stderr b/tests/ui/async-await/mutually-recursive-async-impl-trait-type.no_drop_tracking.stderr
new file mode 100644
index 000000000..8a7317bb9
--- /dev/null
+++ b/tests/ui/async-await/mutually-recursive-async-impl-trait-type.no_drop_tracking.stderr
@@ -0,0 +1,21 @@
+error[E0733]: recursion in an `async fn` requires boxing
+ --> $DIR/mutually-recursive-async-impl-trait-type.rs:9:18
+ |
+LL | async fn rec_1() {
+ | ^ recursive `async fn`
+ |
+ = note: a recursive `async fn` must be rewritten to return a boxed `dyn Future`
+ = note: consider using the `async_recursion` crate: https://crates.io/crates/async_recursion
+
+error[E0733]: recursion in an `async fn` requires boxing
+ --> $DIR/mutually-recursive-async-impl-trait-type.rs:13:18
+ |
+LL | async fn rec_2() {
+ | ^ recursive `async fn`
+ |
+ = note: a recursive `async fn` must be rewritten to return a boxed `dyn Future`
+ = note: consider using the `async_recursion` crate: https://crates.io/crates/async_recursion
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0733`.
diff --git a/tests/ui/async-await/mutually-recursive-async-impl-trait-type.rs b/tests/ui/async-await/mutually-recursive-async-impl-trait-type.rs
index bb2a61f03..a241f30e7 100644
--- a/tests/ui/async-await/mutually-recursive-async-impl-trait-type.rs
+++ b/tests/ui/async-await/mutually-recursive-async-impl-trait-type.rs
@@ -1,3 +1,7 @@
+// revisions: no_drop_tracking drop_tracking drop_tracking_mir
+// [drop_tracking] compile-flags: -Zdrop-tracking
+// [drop_tracking_mir] compile-flags: -Zdrop-tracking-mir
+
// edition:2018
// Test that impl trait does not allow creating recursive types that are
// otherwise forbidden when using `async` and `await`.
diff --git a/tests/ui/async-await/mutually-recursive-async-impl-trait-type.stderr b/tests/ui/async-await/mutually-recursive-async-impl-trait-type.stderr
index f789ad2a0..8a7317bb9 100644
--- a/tests/ui/async-await/mutually-recursive-async-impl-trait-type.stderr
+++ b/tests/ui/async-await/mutually-recursive-async-impl-trait-type.stderr
@@ -1,5 +1,5 @@
error[E0733]: recursion in an `async fn` requires boxing
- --> $DIR/mutually-recursive-async-impl-trait-type.rs:5:18
+ --> $DIR/mutually-recursive-async-impl-trait-type.rs:9:18
|
LL | async fn rec_1() {
| ^ recursive `async fn`
@@ -8,7 +8,7 @@ LL | async fn rec_1() {
= note: consider using the `async_recursion` crate: https://crates.io/crates/async_recursion
error[E0733]: recursion in an `async fn` requires boxing
- --> $DIR/mutually-recursive-async-impl-trait-type.rs:9:18
+ --> $DIR/mutually-recursive-async-impl-trait-type.rs:13:18
|
LL | async fn rec_2() {
| ^ recursive `async fn`
diff --git a/tests/ui/async-await/no-const-async.stderr b/tests/ui/async-await/no-const-async.stderr
index c5bd520aa..71c228958 100644
--- a/tests/ui/async-await/no-const-async.stderr
+++ b/tests/ui/async-await/no-const-async.stderr
@@ -28,8 +28,8 @@ note: ...which requires const checking `x`...
|
LL | pub const async fn x() {}
| ^^^^^^^^^^^^^^^^^^^^^^
- = note: ...which requires computing whether `impl core::future::future::Future<Output = ()>` is freeze...
- = note: ...which requires evaluating trait selection obligation `impl core::future::future::Future<Output = ()>: core::marker::Freeze`...
+ = note: ...which requires computing whether `x::{opaque#0}` is freeze...
+ = note: ...which requires evaluating trait selection obligation `x::{opaque#0}: core::marker::Freeze`...
= note: ...which again requires computing type of `x::{opaque#0}`, completing the cycle
note: cycle used when checking item types in top-level module
--> $DIR/no-const-async.rs:4:1
diff --git a/tests/ui/async-await/non-trivial-drop.rs b/tests/ui/async-await/non-trivial-drop.rs
index a3167215d..d4df9d439 100644
--- a/tests/ui/async-await/non-trivial-drop.rs
+++ b/tests/ui/async-await/non-trivial-drop.rs
@@ -1,6 +1,8 @@
+// revisions: no_drop_tracking drop_tracking drop_tracking_mir
+// [drop_tracking] compile-flags: -Zdrop-tracking
+// [drop_tracking_mir] compile-flags: -Zdrop-tracking-mir
// build-pass
// edition:2018
-// compile-flags: -Zdrop-tracking=y
#![feature(generators)]
diff --git a/tests/ui/async-await/proper-span-for-type-error.stderr b/tests/ui/async-await/proper-span-for-type-error.stderr
index 25f05156c..592ef7faf 100644
--- a/tests/ui/async-await/proper-span-for-type-error.stderr
+++ b/tests/ui/async-await/proper-span-for-type-error.stderr
@@ -2,7 +2,7 @@ error[E0308]: mismatched types
--> $DIR/proper-span-for-type-error.rs:8:5
|
LL | a().await
- | ^^^^^^^^^ expected enum `Result`, found `()`
+ | ^^^^^^^^^ expected `Result<(), i32>`, found `()`
|
= note: expected enum `Result<(), i32>`
found unit type `()`
diff --git a/tests/ui/async-await/recursive-async-impl-trait-type.drop_tracking.stderr b/tests/ui/async-await/recursive-async-impl-trait-type.drop_tracking.stderr
new file mode 100644
index 000000000..7e63a8da5
--- /dev/null
+++ b/tests/ui/async-await/recursive-async-impl-trait-type.drop_tracking.stderr
@@ -0,0 +1,12 @@
+error[E0733]: recursion in an `async fn` requires boxing
+ --> $DIR/recursive-async-impl-trait-type.rs:8:40
+ |
+LL | async fn recursive_async_function() -> () {
+ | ^^ recursive `async fn`
+ |
+ = note: a recursive `async fn` must be rewritten to return a boxed `dyn Future`
+ = note: consider using the `async_recursion` crate: https://crates.io/crates/async_recursion
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0733`.
diff --git a/tests/ui/async-await/recursive-async-impl-trait-type.drop_tracking_mir.stderr b/tests/ui/async-await/recursive-async-impl-trait-type.drop_tracking_mir.stderr
new file mode 100644
index 000000000..7e63a8da5
--- /dev/null
+++ b/tests/ui/async-await/recursive-async-impl-trait-type.drop_tracking_mir.stderr
@@ -0,0 +1,12 @@
+error[E0733]: recursion in an `async fn` requires boxing
+ --> $DIR/recursive-async-impl-trait-type.rs:8:40
+ |
+LL | async fn recursive_async_function() -> () {
+ | ^^ recursive `async fn`
+ |
+ = note: a recursive `async fn` must be rewritten to return a boxed `dyn Future`
+ = note: consider using the `async_recursion` crate: https://crates.io/crates/async_recursion
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0733`.
diff --git a/tests/ui/async-await/recursive-async-impl-trait-type.no_drop_tracking.stderr b/tests/ui/async-await/recursive-async-impl-trait-type.no_drop_tracking.stderr
new file mode 100644
index 000000000..7e63a8da5
--- /dev/null
+++ b/tests/ui/async-await/recursive-async-impl-trait-type.no_drop_tracking.stderr
@@ -0,0 +1,12 @@
+error[E0733]: recursion in an `async fn` requires boxing
+ --> $DIR/recursive-async-impl-trait-type.rs:8:40
+ |
+LL | async fn recursive_async_function() -> () {
+ | ^^ recursive `async fn`
+ |
+ = note: a recursive `async fn` must be rewritten to return a boxed `dyn Future`
+ = note: consider using the `async_recursion` crate: https://crates.io/crates/async_recursion
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0733`.
diff --git a/tests/ui/async-await/recursive-async-impl-trait-type.rs b/tests/ui/async-await/recursive-async-impl-trait-type.rs
index edc4cb8ac..60b34d3a1 100644
--- a/tests/ui/async-await/recursive-async-impl-trait-type.rs
+++ b/tests/ui/async-await/recursive-async-impl-trait-type.rs
@@ -1,3 +1,6 @@
+// revisions: no_drop_tracking drop_tracking drop_tracking_mir
+// [drop_tracking] compile-flags: -Zdrop-tracking
+// [drop_tracking_mir] compile-flags: -Zdrop-tracking-mir
// edition:2018
// Test that impl trait does not allow creating recursive types that are
// otherwise forbidden when using `async` and `await`.
diff --git a/tests/ui/async-await/recursive-async-impl-trait-type.stderr b/tests/ui/async-await/recursive-async-impl-trait-type.stderr
index 63f64f445..7e63a8da5 100644
--- a/tests/ui/async-await/recursive-async-impl-trait-type.stderr
+++ b/tests/ui/async-await/recursive-async-impl-trait-type.stderr
@@ -1,5 +1,5 @@
error[E0733]: recursion in an `async fn` requires boxing
- --> $DIR/recursive-async-impl-trait-type.rs:5:40
+ --> $DIR/recursive-async-impl-trait-type.rs:8:40
|
LL | async fn recursive_async_function() -> () {
| ^^ recursive `async fn`
diff --git a/tests/ui/async-await/send-bound-async-closure.rs b/tests/ui/async-await/send-bound-async-closure.rs
new file mode 100644
index 000000000..4e9e7309b
--- /dev/null
+++ b/tests/ui/async-await/send-bound-async-closure.rs
@@ -0,0 +1,37 @@
+// edition: 2021
+// check-pass
+
+// This test verifies that we do not create a query cycle when typechecking has several inference
+// variables that point to the same generator interior type.
+
+use std::future::Future;
+use std::pin::Pin;
+use std::task::{Context, Poll};
+
+type ChannelTask = Pin<Box<dyn Future<Output = ()> + Send>>;
+
+pub fn register_message_type() -> ChannelTask {
+ Box::pin(async move {
+ let f = |__cx: &mut Context<'_>| Poll::<()>::Pending;
+ PollFn { f }.await
+ })
+}
+
+struct PollFn<F> {
+ f: F,
+}
+
+impl<F> Unpin for PollFn<F> {}
+
+impl<T, F> Future for PollFn<F>
+where
+ F: FnMut(&mut Context<'_>) -> Poll<T>,
+{
+ type Output = T;
+
+ fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<T> {
+ (&mut self.f)(cx)
+ }
+}
+
+fn main() {}
diff --git a/tests/ui/async-await/suggest-missing-await-closure.stderr b/tests/ui/async-await/suggest-missing-await-closure.stderr
index a5958baff..d44af5b8d 100644
--- a/tests/ui/async-await/suggest-missing-await-closure.stderr
+++ b/tests/ui/async-await/suggest-missing-await-closure.stderr
@@ -2,17 +2,15 @@ error[E0308]: mismatched types
--> $DIR/suggest-missing-await-closure.rs:16:18
|
LL | take_u32(x)
- | -------- ^ expected `u32`, found opaque type
+ | -------- ^ expected `u32`, found future
| |
| arguments to this function are incorrect
|
-note: while checking the return type of the `async fn`
- --> $DIR/suggest-missing-await-closure.rs:8:24
+note: calling an async function returns a future
+ --> $DIR/suggest-missing-await-closure.rs:16:18
|
-LL | async fn make_u32() -> u32 {
- | ^^^ checked the `Output` of this `async fn`, found opaque type
- = note: expected type `u32`
- found opaque type `impl Future<Output = u32>`
+LL | take_u32(x)
+ | ^
note: function defined here
--> $DIR/suggest-missing-await-closure.rs:6:4
|
diff --git a/tests/ui/async-await/suggest-missing-await.stderr b/tests/ui/async-await/suggest-missing-await.stderr
index 1196601ac..f0ec34a6a 100644
--- a/tests/ui/async-await/suggest-missing-await.stderr
+++ b/tests/ui/async-await/suggest-missing-await.stderr
@@ -2,17 +2,15 @@ error[E0308]: mismatched types
--> $DIR/suggest-missing-await.rs:12:14
|
LL | take_u32(x)
- | -------- ^ expected `u32`, found opaque type
+ | -------- ^ expected `u32`, found future
| |
| arguments to this function are incorrect
|
-note: while checking the return type of the `async fn`
- --> $DIR/suggest-missing-await.rs:5:24
+note: calling an async function returns a future
+ --> $DIR/suggest-missing-await.rs:12:14
|
-LL | async fn make_u32() -> u32 {
- | ^^^ checked the `Output` of this `async fn`, found opaque type
- = note: expected type `u32`
- found opaque type `impl Future<Output = u32>`
+LL | take_u32(x)
+ | ^
note: function defined here
--> $DIR/suggest-missing-await.rs:3:4
|
@@ -27,15 +25,13 @@ error[E0308]: mismatched types
--> $DIR/suggest-missing-await.rs:22:5
|
LL | dummy()
- | ^^^^^^^ expected `()`, found opaque type
+ | ^^^^^^^ expected `()`, found future
|
-note: while checking the return type of the `async fn`
- --> $DIR/suggest-missing-await.rs:18:18
+note: calling an async function returns a future
+ --> $DIR/suggest-missing-await.rs:22:5
|
-LL | async fn dummy() {}
- | ^ checked the `Output` of this `async fn`, found opaque type
- = note: expected unit type `()`
- found opaque type `impl Future<Output = ()>`
+LL | dummy()
+ | ^^^^^^^
help: consider `await`ing on the `Future`
|
LL | dummy().await
@@ -55,16 +51,11 @@ LL | | dummy()
LL | |
LL | | } else {
LL | | dummy().await
- | | ^^^^^^^^^^^^^ expected opaque type, found `()`
+ | | ^^^^^^^^^^^^^ expected future, found `()`
LL | |
LL | | };
| |_____- `if` and `else` have incompatible types
|
-note: while checking the return type of the `async fn`
- --> $DIR/suggest-missing-await.rs:18:18
- |
-LL | async fn dummy() {}
- | ^ checked the `Output` of this `async fn`, expected opaque type
= note: expected opaque type `impl Future<Output = ()>`
found unit type `()`
help: consider `await`ing on the `Future`
@@ -82,16 +73,11 @@ LL | | 0 => dummy(),
LL | | 1 => dummy(),
| | ------- this is found to be of type `impl Future<Output = ()>`
LL | | 2 => dummy().await,
- | | ^^^^^^^^^^^^^ expected opaque type, found `()`
+ | | ^^^^^^^^^^^^^ expected future, found `()`
LL | |
LL | | };
| |_____- `match` arms have incompatible types
|
-note: while checking the return type of the `async fn`
- --> $DIR/suggest-missing-await.rs:18:18
- |
-LL | async fn dummy() {}
- | ^ checked the `Output` of this `async fn`, expected opaque type
= note: expected opaque type `impl Future<Output = ()>`
found unit type `()`
help: consider `await`ing on the `Future`
@@ -106,13 +92,8 @@ error[E0308]: mismatched types
LL | let _x = match dummy() {
| ------- this expression has type `impl Future<Output = ()>`
LL | () => {}
- | ^^ expected opaque type, found `()`
- |
-note: while checking the return type of the `async fn`
- --> $DIR/suggest-missing-await.rs:18:18
+ | ^^ expected future, found `()`
|
-LL | async fn dummy() {}
- | ^ checked the `Output` of this `async fn`, expected opaque type
= note: expected opaque type `impl Future<Output = ()>`
found unit type `()`
help: consider `await`ing on the `Future`
@@ -127,13 +108,8 @@ LL | match dummy_result() {
| -------------- this expression has type `impl Future<Output = Result<(), ()>>`
...
LL | Ok(_) => {}
- | ^^^^^ expected opaque type, found enum `Result`
+ | ^^^^^ expected future, found `Result<_, _>`
|
-note: while checking the return type of the `async fn`
- --> $DIR/suggest-missing-await.rs:57:28
- |
-LL | async fn dummy_result() -> Result<(), ()> {
- | ^^^^^^^^^^^^^^ checked the `Output` of this `async fn`, expected opaque type
= note: expected opaque type `impl Future<Output = Result<(), ()>>`
found enum `Result<_, _>`
help: consider `await`ing on the `Future`
@@ -148,13 +124,8 @@ LL | match dummy_result() {
| -------------- this expression has type `impl Future<Output = Result<(), ()>>`
...
LL | Err(_) => {}
- | ^^^^^^ expected opaque type, found enum `Result`
- |
-note: while checking the return type of the `async fn`
- --> $DIR/suggest-missing-await.rs:57:28
+ | ^^^^^^ expected future, found `Result<_, _>`
|
-LL | async fn dummy_result() -> Result<(), ()> {
- | ^^^^^^^^^^^^^^ checked the `Output` of this `async fn`, expected opaque type
= note: expected opaque type `impl Future<Output = Result<(), ()>>`
found enum `Result<_, _>`
help: consider `await`ing on the `Future`
diff --git a/tests/ui/async-await/unresolved_type_param.drop_tracking.stderr b/tests/ui/async-await/unresolved_type_param.drop_tracking.stderr
new file mode 100644
index 000000000..912e2b34c
--- /dev/null
+++ b/tests/ui/async-await/unresolved_type_param.drop_tracking.stderr
@@ -0,0 +1,39 @@
+error[E0698]: type inside `async fn` body must be known in this context
+ --> $DIR/unresolved_type_param.rs:12:5
+ |
+LL | bar().await;
+ | ^^^ cannot infer type for type parameter `T` declared on the function `bar`
+ |
+note: the type is part of the `async fn` body because of this `await`
+ --> $DIR/unresolved_type_param.rs:12:10
+ |
+LL | bar().await;
+ | ^^^^^^
+
+error[E0698]: type inside `async fn` body must be known in this context
+ --> $DIR/unresolved_type_param.rs:12:5
+ |
+LL | bar().await;
+ | ^^^ cannot infer type for type parameter `T` declared on the function `bar`
+ |
+note: the type is part of the `async fn` body because of this `await`
+ --> $DIR/unresolved_type_param.rs:12:10
+ |
+LL | bar().await;
+ | ^^^^^^
+
+error[E0698]: type inside `async fn` body must be known in this context
+ --> $DIR/unresolved_type_param.rs:12:5
+ |
+LL | bar().await;
+ | ^^^ cannot infer type for type parameter `T` declared on the function `bar`
+ |
+note: the type is part of the `async fn` body because of this `await`
+ --> $DIR/unresolved_type_param.rs:12:10
+ |
+LL | bar().await;
+ | ^^^^^^
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0698`.
diff --git a/tests/ui/async-await/unresolved_type_param.drop_tracking_mir.stderr b/tests/ui/async-await/unresolved_type_param.drop_tracking_mir.stderr
new file mode 100644
index 000000000..95c799468
--- /dev/null
+++ b/tests/ui/async-await/unresolved_type_param.drop_tracking_mir.stderr
@@ -0,0 +1,14 @@
+error[E0282]: type annotations needed
+ --> $DIR/unresolved_type_param.rs:12:5
+ |
+LL | bar().await;
+ | ^^^ cannot infer type of the type parameter `T` declared on the function `bar`
+ |
+help: consider specifying the generic argument
+ |
+LL | bar::<T>().await;
+ | +++++
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0282`.
diff --git a/tests/ui/async-await/unresolved_type_param.no_drop_tracking.stderr b/tests/ui/async-await/unresolved_type_param.no_drop_tracking.stderr
new file mode 100644
index 000000000..16d618caa
--- /dev/null
+++ b/tests/ui/async-await/unresolved_type_param.no_drop_tracking.stderr
@@ -0,0 +1,63 @@
+error[E0698]: type inside `async fn` body must be known in this context
+ --> $DIR/unresolved_type_param.rs:12:5
+ |
+LL | bar().await;
+ | ^^^ cannot infer type for type parameter `T` declared on the function `bar`
+ |
+note: the type is part of the `async fn` body because of this `await`
+ --> $DIR/unresolved_type_param.rs:12:10
+ |
+LL | bar().await;
+ | ^^^^^^
+
+error[E0698]: type inside `async fn` body must be known in this context
+ --> $DIR/unresolved_type_param.rs:12:5
+ |
+LL | bar().await;
+ | ^^^ cannot infer type for type parameter `T` declared on the function `bar`
+ |
+note: the type is part of the `async fn` body because of this `await`
+ --> $DIR/unresolved_type_param.rs:12:10
+ |
+LL | bar().await;
+ | ^^^^^^
+
+error[E0698]: type inside `async fn` body must be known in this context
+ --> $DIR/unresolved_type_param.rs:12:5
+ |
+LL | bar().await;
+ | ^^^ cannot infer type for type parameter `T` declared on the function `bar`
+ |
+note: the type is part of the `async fn` body because of this `await`
+ --> $DIR/unresolved_type_param.rs:12:10
+ |
+LL | bar().await;
+ | ^^^^^^
+
+error[E0698]: type inside `async fn` body must be known in this context
+ --> $DIR/unresolved_type_param.rs:12:5
+ |
+LL | bar().await;
+ | ^^^ cannot infer type for type parameter `T` declared on the function `bar`
+ |
+note: the type is part of the `async fn` body because of this `await`
+ --> $DIR/unresolved_type_param.rs:12:10
+ |
+LL | bar().await;
+ | ^^^^^^
+
+error[E0698]: type inside `async fn` body must be known in this context
+ --> $DIR/unresolved_type_param.rs:12:5
+ |
+LL | bar().await;
+ | ^^^ cannot infer type for type parameter `T` declared on the function `bar`
+ |
+note: the type is part of the `async fn` body because of this `await`
+ --> $DIR/unresolved_type_param.rs:12:10
+ |
+LL | bar().await;
+ | ^^^^^^
+
+error: aborting due to 5 previous errors
+
+For more information about this error, try `rustc --explain E0698`.
diff --git a/tests/ui/async-await/unresolved_type_param.rs b/tests/ui/async-await/unresolved_type_param.rs
index 6d6d80614..ca0a92b94 100644
--- a/tests/ui/async-await/unresolved_type_param.rs
+++ b/tests/ui/async-await/unresolved_type_param.rs
@@ -1,24 +1,36 @@
+// revisions: no_drop_tracking drop_tracking drop_tracking_mir
+// [drop_tracking] compile-flags: -Zdrop-tracking
+// [drop_tracking_mir] compile-flags: -Zdrop-tracking-mir
// Provoke an unresolved type error (T).
// Error message should pinpoint the type parameter T as needing to be bound
// (rather than give a general error message)
// edition:2018
-// compile-flags: -Zdrop-tracking
async fn bar<T>() -> () {}
async fn foo() {
bar().await;
- //~^ ERROR type inside `async fn` body must be known in this context
- //~| ERROR type inside `async fn` body must be known in this context
- //~| ERROR type inside `async fn` body must be known in this context
- //~| NOTE cannot infer type for type parameter `T`
- //~| NOTE cannot infer type for type parameter `T`
- //~| NOTE cannot infer type for type parameter `T`
- //~| NOTE the type is part of the `async fn` body because of this `await`
- //~| NOTE the type is part of the `async fn` body because of this `await`
- //~| NOTE the type is part of the `async fn` body because of this `await`
- //~| NOTE in this expansion of desugaring of `await`
- //~| NOTE in this expansion of desugaring of `await`
- //~| NOTE in this expansion of desugaring of `await`
+ //[drop_tracking_mir]~^ ERROR type annotations needed
+ //[drop_tracking_mir]~| NOTE cannot infer type of the type parameter `T`
+ //[no_drop_tracking,drop_tracking]~^^^ ERROR type inside `async fn` body must be known in this context
+ //[no_drop_tracking,drop_tracking]~| ERROR type inside `async fn` body must be known in this context
+ //[no_drop_tracking,drop_tracking]~| ERROR type inside `async fn` body must be known in this context
+ //[no_drop_tracking,drop_tracking]~| NOTE cannot infer type for type parameter `T`
+ //[no_drop_tracking,drop_tracking]~| NOTE cannot infer type for type parameter `T`
+ //[no_drop_tracking,drop_tracking]~| NOTE cannot infer type for type parameter `T`
+ //[no_drop_tracking,drop_tracking]~| NOTE the type is part of the `async fn` body because of this `await`
+ //[no_drop_tracking,drop_tracking]~| NOTE the type is part of the `async fn` body because of this `await`
+ //[no_drop_tracking,drop_tracking]~| NOTE the type is part of the `async fn` body because of this `await`
+ //[no_drop_tracking,drop_tracking]~| NOTE in this expansion of desugaring of `await`
+ //[no_drop_tracking,drop_tracking]~| NOTE in this expansion of desugaring of `await`
+ //[no_drop_tracking,drop_tracking]~| NOTE in this expansion of desugaring of `await`
+ //[no_drop_tracking]~^^^^^^^^^^^^^^^ ERROR type inside `async fn` body must be known in this context
+ //[no_drop_tracking]~| ERROR type inside `async fn` body must be known in this context
+ //[no_drop_tracking]~| NOTE cannot infer type for type parameter `T`
+ //[no_drop_tracking]~| NOTE cannot infer type for type parameter `T`
+ //[no_drop_tracking]~| NOTE the type is part of the `async fn` body because of this `await`
+ //[no_drop_tracking]~| NOTE the type is part of the `async fn` body because of this `await`
+ //[no_drop_tracking]~| NOTE in this expansion of desugaring of `await`
+ //[no_drop_tracking]~| NOTE in this expansion of desugaring of `await`
}
fn main() {}
diff --git a/tests/ui/async-await/unresolved_type_param.stderr b/tests/ui/async-await/unresolved_type_param.stderr
index 7236c681f..64a31b5fc 100644
--- a/tests/ui/async-await/unresolved_type_param.stderr
+++ b/tests/ui/async-await/unresolved_type_param.stderr
@@ -1,35 +1,35 @@
error[E0698]: type inside `async fn` body must be known in this context
- --> $DIR/unresolved_type_param.rs:10:5
+ --> $DIR/unresolved_type_param.rs:13:5
|
LL | bar().await;
| ^^^ cannot infer type for type parameter `T` declared on the function `bar`
|
note: the type is part of the `async fn` body because of this `await`
- --> $DIR/unresolved_type_param.rs:10:10
+ --> $DIR/unresolved_type_param.rs:13:10
|
LL | bar().await;
| ^^^^^^
error[E0698]: type inside `async fn` body must be known in this context
- --> $DIR/unresolved_type_param.rs:10:5
+ --> $DIR/unresolved_type_param.rs:13:5
|
LL | bar().await;
| ^^^ cannot infer type for type parameter `T` declared on the function `bar`
|
note: the type is part of the `async fn` body because of this `await`
- --> $DIR/unresolved_type_param.rs:10:10
+ --> $DIR/unresolved_type_param.rs:13:10
|
LL | bar().await;
| ^^^^^^
error[E0698]: type inside `async fn` body must be known in this context
- --> $DIR/unresolved_type_param.rs:10:5
+ --> $DIR/unresolved_type_param.rs:13:5
|
LL | bar().await;
| ^^^ cannot infer type for type parameter `T` declared on the function `bar`
|
note: the type is part of the `async fn` body because of this `await`
- --> $DIR/unresolved_type_param.rs:10:10
+ --> $DIR/unresolved_type_param.rs:13:10
|
LL | bar().await;
| ^^^^^^
diff --git a/tests/ui/attributes/invalid_macro_export_argument.rs b/tests/ui/attributes/invalid_macro_export_argument.rs
new file mode 100644
index 000000000..85d009f11
--- /dev/null
+++ b/tests/ui/attributes/invalid_macro_export_argument.rs
@@ -0,0 +1,26 @@
+// check-pass
+#[macro_export(hello, world)] //~ WARN `#[macro_export]` can only take 1 or 0 arguments
+macro_rules! a {
+ () => ()
+}
+
+#[macro_export(not_local_inner_macros)] //~ WARN `not_local_inner_macros` isn't a valid `#[macro_export]` argument
+macro_rules! b {
+ () => ()
+}
+
+#[macro_export]
+macro_rules! c {
+ () => ()
+}
+#[macro_export(local_inner_macros)]
+macro_rules! d {
+ () => ()
+}
+
+#[macro_export()]
+macro_rules! e {
+ () => ()
+}
+
+fn main() {}
diff --git a/tests/ui/attributes/invalid_macro_export_argument.stderr b/tests/ui/attributes/invalid_macro_export_argument.stderr
new file mode 100644
index 000000000..a4e17642c
--- /dev/null
+++ b/tests/ui/attributes/invalid_macro_export_argument.stderr
@@ -0,0 +1,16 @@
+warning: `#[macro_export]` can only take 1 or 0 arguments
+ --> $DIR/invalid_macro_export_argument.rs:2:1
+ |
+LL | #[macro_export(hello, world)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: `#[warn(invalid_macro_export_arguments)]` on by default
+
+warning: `not_local_inner_macros` isn't a valid `#[macro_export]` argument
+ --> $DIR/invalid_macro_export_argument.rs:7:16
+ |
+LL | #[macro_export(not_local_inner_macros)]
+ | ^^^^^^^^^^^^^^^^^^^^^^
+
+warning: 2 warnings emitted
+
diff --git a/tests/ui/attributes/key-value-expansion.stderr b/tests/ui/attributes/key-value-expansion.stderr
index 1b776322a..aaa8b1695 100644
--- a/tests/ui/attributes/key-value-expansion.stderr
+++ b/tests/ui/attributes/key-value-expansion.stderr
@@ -15,12 +15,7 @@ LL | bug!();
|
= note: this error originates in the macro `bug` (in Nightly builds, run with -Z macro-backtrace for more info)
-error: unexpected expression: `{
- let res =
- ::alloc::fmt::format(::core::fmt::Arguments::new_v1(&[""],
- &[::core::fmt::ArgumentV1::new_display(&"u8")]));
- res
- }.as_str()`
+error: unexpected expression: `{ let res = ::alloc::fmt::format(format_args!("{0}", "u8")); res }.as_str()`
--> $DIR/key-value-expansion.rs:48:23
|
LL | doc_comment! {format!("{coor}", coor = stringify!($t1)).as_str()}
diff --git a/tests/ui/attributes/log-backtrace.rs b/tests/ui/attributes/log-backtrace.rs
index 3979d2001..e42edf1d4 100644
--- a/tests/ui/attributes/log-backtrace.rs
+++ b/tests/ui/attributes/log-backtrace.rs
@@ -1,9 +1,9 @@
// run-pass
//
-// This test makes sure that log-backtrace option doesn't give a compilation error.
+// This test makes sure that log-backtrace option at least parses correctly
//
// dont-check-compiler-stdout
// dont-check-compiler-stderr
// rustc-env:RUSTC_LOG=info
-// compile-flags: -Zlog-backtrace=rustc_metadata::creader
+// rustc-env:RUSTC_LOG_BACKTRACE=rustc_metadata::creader
fn main() {}
diff --git a/tests/ui/attributes/rustc-box.rs b/tests/ui/attributes/rustc-box.rs
new file mode 100644
index 000000000..b3726fb38
--- /dev/null
+++ b/tests/ui/attributes/rustc-box.rs
@@ -0,0 +1,18 @@
+#![feature(rustc_attrs, stmt_expr_attributes)]
+
+fn foo(_: u32, _: u32) {}
+fn bar(_: u32) {}
+
+fn main() {
+ #[rustc_box]
+ Box::new(1); // OK
+ #[rustc_box]
+ Box::pin(1); //~ ERROR `#[rustc_box]` attribute used incorrectly
+ #[rustc_box]
+ foo(1, 1); //~ ERROR `#[rustc_box]` attribute used incorrectly
+ #[rustc_box]
+ bar(1); //~ ERROR `#[rustc_box]` attribute used incorrectly
+ #[rustc_box] //~ ERROR `#[rustc_box]` attribute used incorrectly
+ #[rustfmt::skip]
+ Box::new(1);
+}
diff --git a/tests/ui/attributes/rustc-box.stderr b/tests/ui/attributes/rustc-box.stderr
new file mode 100644
index 000000000..073a18c7d
--- /dev/null
+++ b/tests/ui/attributes/rustc-box.stderr
@@ -0,0 +1,34 @@
+error: `#[rustc_box]` attribute used incorrectly
+ --> $DIR/rustc-box.rs:10:5
+ |
+LL | Box::pin(1);
+ | ^^^^^^^^^^^
+ |
+ = note: `#[rustc_box]` may only be applied to a `Box::new()` call
+
+error: `#[rustc_box]` attribute used incorrectly
+ --> $DIR/rustc-box.rs:12:5
+ |
+LL | foo(1, 1);
+ | ^^^^^^^^^
+ |
+ = note: `#[rustc_box]` may only be applied to a `Box::new()` call
+
+error: `#[rustc_box]` attribute used incorrectly
+ --> $DIR/rustc-box.rs:14:5
+ |
+LL | bar(1);
+ | ^^^^^^
+ |
+ = note: `#[rustc_box]` may only be applied to a `Box::new()` call
+
+error: `#[rustc_box]` attribute used incorrectly
+ --> $DIR/rustc-box.rs:15:5
+ |
+LL | #[rustc_box]
+ | ^^^^^^^^^^^^
+ |
+ = note: no other attributes may be applied
+
+error: aborting due to 4 previous errors
+
diff --git a/tests/ui/augmented-assignments.rs b/tests/ui/augmented-assignments.rs
index 20c7fb3a9..bd2435a78 100644
--- a/tests/ui/augmented-assignments.rs
+++ b/tests/ui/augmented-assignments.rs
@@ -9,7 +9,7 @@ impl AddAssign for Int {
}
fn main() {
- let mut x = Int(1);
+ let mut x = Int(1); //~ NOTE binding `x` declared here
x
//~^ NOTE borrow of `x` occurs here
+=
diff --git a/tests/ui/augmented-assignments.stderr b/tests/ui/augmented-assignments.stderr
index 2910c910d..d1096aea2 100644
--- a/tests/ui/augmented-assignments.stderr
+++ b/tests/ui/augmented-assignments.stderr
@@ -1,6 +1,8 @@
error[E0505]: cannot move out of `x` because it is borrowed
--> $DIR/augmented-assignments.rs:16:5
|
+LL | let mut x = Int(1);
+ | ----- binding `x` declared here
LL | x
| - borrow of `x` occurs here
...
diff --git a/tests/ui/auto-traits/auto-trait-validation.stderr b/tests/ui/auto-traits/auto-trait-validation.stderr
index 2c380e5b0..89b63d23d 100644
--- a/tests/ui/auto-traits/auto-trait-validation.stderr
+++ b/tests/ui/auto-traits/auto-trait-validation.stderr
@@ -12,7 +12,7 @@ error[E0568]: auto traits cannot have super traits or lifetime bounds
LL | auto trait Bound : Copy {}
| -----^^^^^^^ help: remove the super traits or lifetime bounds
| |
- | auto trait cannot have super traits or lifetime bounds
+ | auto traits cannot have super traits or lifetime bounds
error[E0568]: auto traits cannot have super traits or lifetime bounds
--> $DIR/auto-trait-validation.rs:9:25
@@ -20,7 +20,7 @@ error[E0568]: auto traits cannot have super traits or lifetime bounds
LL | auto trait LifetimeBound : 'static {}
| -------------^^^^^^^^^^ help: remove the super traits or lifetime bounds
| |
- | auto trait cannot have super traits or lifetime bounds
+ | auto traits cannot have super traits or lifetime bounds
error[E0380]: auto traits cannot have associated items
--> $DIR/auto-trait-validation.rs:11:25
@@ -29,7 +29,7 @@ LL | auto trait MyTrait { fn foo() {} }
| ------- ---^^^-----
| | |
| | help: remove these associated items
- | auto trait cannot have associated items
+ | auto traits cannot have associated items
error: aborting due to 4 previous errors
diff --git a/tests/ui/auto-traits/issue-23080-2.stderr b/tests/ui/auto-traits/issue-23080-2.stderr
index 267a712f6..fed485612 100644
--- a/tests/ui/auto-traits/issue-23080-2.stderr
+++ b/tests/ui/auto-traits/issue-23080-2.stderr
@@ -2,7 +2,7 @@ error[E0380]: auto traits cannot have associated items
--> $DIR/issue-23080-2.rs:5:10
|
LL | unsafe auto trait Trait {
- | ----- auto trait cannot have associated items
+ | ----- auto traits cannot have associated items
LL | type Output;
| -----^^^^^^- help: remove these associated items
diff --git a/tests/ui/auto-traits/issue-23080.stderr b/tests/ui/auto-traits/issue-23080.stderr
index c1b16b2f4..f5d607298 100644
--- a/tests/ui/auto-traits/issue-23080.stderr
+++ b/tests/ui/auto-traits/issue-23080.stderr
@@ -2,7 +2,7 @@ error[E0380]: auto traits cannot have associated items
--> $DIR/issue-23080.rs:5:8
|
LL | unsafe auto trait Trait {
- | ----- auto trait cannot have associated items
+ | ----- auto traits cannot have associated items
LL | fn method(&self) {
| _____- ^^^^^^
LL | | println!("Hello");
diff --git a/tests/ui/auto-traits/issue-84075.stderr b/tests/ui/auto-traits/issue-84075.stderr
index 02dca598e..6fbdc669b 100644
--- a/tests/ui/auto-traits/issue-84075.stderr
+++ b/tests/ui/auto-traits/issue-84075.stderr
@@ -4,7 +4,7 @@ error[E0568]: auto traits cannot have super traits or lifetime bounds
LL | auto trait Magic where Self: Copy {}
| ----- ^^^^^^^^^^^^^^^^ help: remove the super traits or lifetime bounds
| |
- | auto trait cannot have super traits or lifetime bounds
+ | auto traits cannot have super traits or lifetime bounds
error: aborting due to previous error
diff --git a/tests/ui/auto-traits/str-contains-slice-conceptually.rs b/tests/ui/auto-traits/str-contains-slice-conceptually.rs
new file mode 100644
index 000000000..6a16fdcf2
--- /dev/null
+++ b/tests/ui/auto-traits/str-contains-slice-conceptually.rs
@@ -0,0 +1,13 @@
+#![feature(negative_impls)]
+#![feature(auto_traits)]
+
+auto trait AutoTrait {}
+
+impl<T> !AutoTrait for [T] {}
+
+fn needs_auto_trait<T: AutoTrait + ?Sized>() {}
+
+fn main() {
+ needs_auto_trait::<str>();
+ //~^ ERROR the trait bound `[u8]: AutoTrait` is not satisfied in `str`
+}
diff --git a/tests/ui/auto-traits/str-contains-slice-conceptually.stderr b/tests/ui/auto-traits/str-contains-slice-conceptually.stderr
new file mode 100644
index 000000000..1cf16cebd
--- /dev/null
+++ b/tests/ui/auto-traits/str-contains-slice-conceptually.stderr
@@ -0,0 +1,16 @@
+error[E0277]: the trait bound `[u8]: AutoTrait` is not satisfied in `str`
+ --> $DIR/str-contains-slice-conceptually.rs:11:22
+ |
+LL | needs_auto_trait::<str>();
+ | ^^^ within `str`, the trait `AutoTrait` is not implemented for `[u8]`
+ |
+ = note: `str` is considered to contain a `[u8]` slice for auto trait purposes
+note: required by a bound in `needs_auto_trait`
+ --> $DIR/str-contains-slice-conceptually.rs:8:24
+ |
+LL | fn needs_auto_trait<T: AutoTrait + ?Sized>() {}
+ | ^^^^^^^^^ required by this bound in `needs_auto_trait`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/auto-traits/typeck-auto-trait-no-supertraits-2.stderr b/tests/ui/auto-traits/typeck-auto-trait-no-supertraits-2.stderr
index 4827916fa..547b4bb54 100644
--- a/tests/ui/auto-traits/typeck-auto-trait-no-supertraits-2.stderr
+++ b/tests/ui/auto-traits/typeck-auto-trait-no-supertraits-2.stderr
@@ -4,7 +4,7 @@ error[E0568]: auto traits cannot have super traits or lifetime bounds
LL | auto trait Magic : Sized where Option<Self> : Magic {}
| -----^^^^^^^^ help: remove the super traits or lifetime bounds
| |
- | auto trait cannot have super traits or lifetime bounds
+ | auto traits cannot have super traits or lifetime bounds
error[E0568]: auto traits cannot have super traits or lifetime bounds
--> $DIR/typeck-auto-trait-no-supertraits-2.rs:4:26
@@ -12,7 +12,7 @@ error[E0568]: auto traits cannot have super traits or lifetime bounds
LL | auto trait Magic : Sized where Option<Self> : Magic {}
| ----- ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove the super traits or lifetime bounds
| |
- | auto trait cannot have super traits or lifetime bounds
+ | auto traits cannot have super traits or lifetime bounds
error: aborting due to 2 previous errors
diff --git a/tests/ui/auto-traits/typeck-auto-trait-no-supertraits.stderr b/tests/ui/auto-traits/typeck-auto-trait-no-supertraits.stderr
index d7716f4b6..80f074103 100644
--- a/tests/ui/auto-traits/typeck-auto-trait-no-supertraits.stderr
+++ b/tests/ui/auto-traits/typeck-auto-trait-no-supertraits.stderr
@@ -4,7 +4,7 @@ error[E0568]: auto traits cannot have super traits or lifetime bounds
LL | auto trait Magic: Copy {}
| -----^^^^^^ help: remove the super traits or lifetime bounds
| |
- | auto trait cannot have super traits or lifetime bounds
+ | auto traits cannot have super traits or lifetime bounds
error: aborting due to previous error
diff --git a/tests/ui/autoref-autoderef/issue-38940.stderr b/tests/ui/autoref-autoderef/issue-38940.stderr
index f0b840577..8e98bfcd9 100644
--- a/tests/ui/autoref-autoderef/issue-38940.stderr
+++ b/tests/ui/autoref-autoderef/issue-38940.stderr
@@ -10,7 +10,7 @@ error[E0308]: mismatched types
--> $DIR/issue-38940.rs:49:22
|
LL | let x: &Bottom = &t;
- | ------- ^^ expected struct `Bottom`, found struct `Top`
+ | ------- ^^ expected `&Bottom`, found `&Top`
| |
| expected due to this
|
diff --git a/tests/ui/binding/issue-53114-safety-checks.rs b/tests/ui/binding/issue-53114-safety-checks.rs
index d0eb28c57..e234db516 100644
--- a/tests/ui/binding/issue-53114-safety-checks.rs
+++ b/tests/ui/binding/issue-53114-safety-checks.rs
@@ -21,13 +21,11 @@ fn let_wild_gets_unsafe_field() {
let u2 = U { a: I(1) };
let p = P { a: &2, b: &3 };
let _ = &p.b; //~ ERROR reference to packed field
- //~^ WARN will become a hard error
let _ = u1.a; // #53114: should eventually signal error as well
let _ = &u2.a; //~ ERROR [E0133]
// variation on above with `_` in substructure
let (_,) = (&p.b,); //~ ERROR reference to packed field
- //~^ WARN will become a hard error
let (_,) = (u1.a,); //~ ERROR [E0133]
let (_,) = (&u2.a,); //~ ERROR [E0133]
}
@@ -37,13 +35,11 @@ fn match_unsafe_field_to_wild() {
let u2 = U { a: I(1) };
let p = P { a: &2, b: &3 };
match &p.b { _ => { } } //~ ERROR reference to packed field
- //~^ WARN will become a hard error
match u1.a { _ => { } } //~ ERROR [E0133]
match &u2.a { _ => { } } //~ ERROR [E0133]
// variation on above with `_` in substructure
match (&p.b,) { (_,) => { } } //~ ERROR reference to packed field
- //~^ WARN will become a hard error
match (u1.a,) { (_,) => { } } //~ ERROR [E0133]
match (&u2.a,) { (_,) => { } } //~ ERROR [E0133]
}
diff --git a/tests/ui/binding/issue-53114-safety-checks.stderr b/tests/ui/binding/issue-53114-safety-checks.stderr
index 57a065d6d..5c9d78772 100644
--- a/tests/ui/binding/issue-53114-safety-checks.stderr
+++ b/tests/ui/binding/issue-53114-safety-checks.stderr
@@ -1,50 +1,41 @@
-error: reference to packed field is unaligned
+error[E0793]: reference to packed field is unaligned
--> $DIR/issue-53114-safety-checks.rs:23:13
|
LL | let _ = &p.b;
| ^^^^
|
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523>
= note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
= help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
- = note: `#[deny(unaligned_references)]` on by default
-error: reference to packed field is unaligned
- --> $DIR/issue-53114-safety-checks.rs:29:17
+error[E0793]: reference to packed field is unaligned
+ --> $DIR/issue-53114-safety-checks.rs:28:17
|
LL | let (_,) = (&p.b,);
| ^^^^
|
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523>
= note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
= help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
-error: reference to packed field is unaligned
- --> $DIR/issue-53114-safety-checks.rs:39:11
+error[E0793]: reference to packed field is unaligned
+ --> $DIR/issue-53114-safety-checks.rs:37:11
|
LL | match &p.b { _ => { } }
| ^^^^
|
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523>
= note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
= help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
-error: reference to packed field is unaligned
- --> $DIR/issue-53114-safety-checks.rs:45:12
+error[E0793]: reference to packed field is unaligned
+ --> $DIR/issue-53114-safety-checks.rs:42:12
|
LL | match (&p.b,) { (_,) => { } }
| ^^^^
|
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523>
= note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
= help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
error[E0133]: access to union field is unsafe and requires unsafe function or block
- --> $DIR/issue-53114-safety-checks.rs:26:13
+ --> $DIR/issue-53114-safety-checks.rs:25:13
|
LL | let _ = &u2.a;
| ^^^^^ access to union field
@@ -52,7 +43,7 @@ LL | let _ = &u2.a;
= note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
error[E0133]: access to union field is unsafe and requires unsafe function or block
- --> $DIR/issue-53114-safety-checks.rs:31:17
+ --> $DIR/issue-53114-safety-checks.rs:29:17
|
LL | let (_,) = (u1.a,);
| ^^^^ access to union field
@@ -60,7 +51,7 @@ LL | let (_,) = (u1.a,);
= note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
error[E0133]: access to union field is unsafe and requires unsafe function or block
- --> $DIR/issue-53114-safety-checks.rs:32:17
+ --> $DIR/issue-53114-safety-checks.rs:30:17
|
LL | let (_,) = (&u2.a,);
| ^^^^^ access to union field
@@ -68,7 +59,7 @@ LL | let (_,) = (&u2.a,);
= note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
error[E0133]: access to union field is unsafe and requires unsafe function or block
- --> $DIR/issue-53114-safety-checks.rs:41:11
+ --> $DIR/issue-53114-safety-checks.rs:38:11
|
LL | match u1.a { _ => { } }
| ^^^^ access to union field
@@ -76,7 +67,7 @@ LL | match u1.a { _ => { } }
= note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
error[E0133]: access to union field is unsafe and requires unsafe function or block
- --> $DIR/issue-53114-safety-checks.rs:42:11
+ --> $DIR/issue-53114-safety-checks.rs:39:11
|
LL | match &u2.a { _ => { } }
| ^^^^^ access to union field
@@ -84,7 +75,7 @@ LL | match &u2.a { _ => { } }
= note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
error[E0133]: access to union field is unsafe and requires unsafe function or block
- --> $DIR/issue-53114-safety-checks.rs:47:12
+ --> $DIR/issue-53114-safety-checks.rs:43:12
|
LL | match (u1.a,) { (_,) => { } }
| ^^^^ access to union field
@@ -92,7 +83,7 @@ LL | match (u1.a,) { (_,) => { } }
= note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
error[E0133]: access to union field is unsafe and requires unsafe function or block
- --> $DIR/issue-53114-safety-checks.rs:48:12
+ --> $DIR/issue-53114-safety-checks.rs:44:12
|
LL | match (&u2.a,) { (_,) => { } }
| ^^^^^ access to union field
@@ -101,56 +92,5 @@ LL | match (&u2.a,) { (_,) => { } }
error: aborting due to 11 previous errors
-For more information about this error, try `rustc --explain E0133`.
-Future incompatibility report: Future breakage diagnostic:
-error: reference to packed field is unaligned
- --> $DIR/issue-53114-safety-checks.rs:23:13
- |
-LL | let _ = &p.b;
- | ^^^^
- |
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523>
- = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
- = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
- = note: `#[deny(unaligned_references)]` on by default
-
-Future breakage diagnostic:
-error: reference to packed field is unaligned
- --> $DIR/issue-53114-safety-checks.rs:29:17
- |
-LL | let (_,) = (&p.b,);
- | ^^^^
- |
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523>
- = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
- = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
- = note: `#[deny(unaligned_references)]` on by default
-
-Future breakage diagnostic:
-error: reference to packed field is unaligned
- --> $DIR/issue-53114-safety-checks.rs:39:11
- |
-LL | match &p.b { _ => { } }
- | ^^^^
- |
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523>
- = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
- = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
- = note: `#[deny(unaligned_references)]` on by default
-
-Future breakage diagnostic:
-error: reference to packed field is unaligned
- --> $DIR/issue-53114-safety-checks.rs:45:12
- |
-LL | match (&p.b,) { (_,) => { } }
- | ^^^^
- |
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523>
- = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
- = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
- = note: `#[deny(unaligned_references)]` on by default
-
+Some errors have detailed explanations: E0133, E0793.
+For more information about an error, try `rustc --explain E0133`.
diff --git a/tests/ui/binop/binary-op-on-double-ref.fixed b/tests/ui/binop/binary-op-on-double-ref.fixed
index de9dc19af..586d2568c 100644
--- a/tests/ui/binop/binary-op-on-double-ref.fixed
+++ b/tests/ui/binop/binary-op-on-double-ref.fixed
@@ -3,7 +3,7 @@ fn main() {
let v = vec![1, 2, 3, 4, 5, 6, 7, 8, 9];
let vr = v.iter().filter(|x| {
*x % 2 == 0
- //~^ ERROR cannot mod `&&{integer}` by `{integer}`
+ //~^ ERROR cannot calculate the remainder of `&&{integer}` divided by `{integer}`
});
println!("{:?}", vr);
}
diff --git a/tests/ui/binop/binary-op-on-double-ref.rs b/tests/ui/binop/binary-op-on-double-ref.rs
index 2616c560c..48ee44546 100644
--- a/tests/ui/binop/binary-op-on-double-ref.rs
+++ b/tests/ui/binop/binary-op-on-double-ref.rs
@@ -3,7 +3,7 @@ fn main() {
let v = vec![1, 2, 3, 4, 5, 6, 7, 8, 9];
let vr = v.iter().filter(|x| {
x % 2 == 0
- //~^ ERROR cannot mod `&&{integer}` by `{integer}`
+ //~^ ERROR cannot calculate the remainder of `&&{integer}` divided by `{integer}`
});
println!("{:?}", vr);
}
diff --git a/tests/ui/binop/binary-op-on-double-ref.stderr b/tests/ui/binop/binary-op-on-double-ref.stderr
index 34826d2f4..2e8aeebc6 100644
--- a/tests/ui/binop/binary-op-on-double-ref.stderr
+++ b/tests/ui/binop/binary-op-on-double-ref.stderr
@@ -1,4 +1,4 @@
-error[E0369]: cannot mod `&&{integer}` by `{integer}`
+error[E0369]: cannot calculate the remainder of `&&{integer}` divided by `{integer}`
--> $DIR/binary-op-on-double-ref.rs:5:11
|
LL | x % 2 == 0
diff --git a/tests/ui/binop/binop-move-semantics.stderr b/tests/ui/binop/binop-move-semantics.stderr
index dae267da0..8645169b9 100644
--- a/tests/ui/binop/binop-move-semantics.stderr
+++ b/tests/ui/binop/binop-move-semantics.stderr
@@ -41,6 +41,8 @@ LL | fn move_then_borrow<T: Add<Output=()> + Clone + Copy>(x: T) {
error[E0505]: cannot move out of `x` because it is borrowed
--> $DIR/binop-move-semantics.rs:21:5
|
+LL | fn move_borrowed<T: Add<Output=()>>(x: T, mut y: T) {
+ | - binding `x` declared here
LL | let m = &x;
| -- borrow of `x` occurs here
...
@@ -53,6 +55,9 @@ LL | use_mut(n); use_imm(m);
error[E0505]: cannot move out of `y` because it is borrowed
--> $DIR/binop-move-semantics.rs:23:5
|
+LL | fn move_borrowed<T: Add<Output=()>>(x: T, mut y: T) {
+ | ----- binding `y` declared here
+LL | let m = &x;
LL | let n = &mut y;
| ------ borrow of `y` occurs here
...
diff --git a/tests/ui/binop/issue-28837.rs b/tests/ui/binop/issue-28837.rs
index 9719c3afa..54c8838e4 100644
--- a/tests/ui/binop/issue-28837.rs
+++ b/tests/ui/binop/issue-28837.rs
@@ -11,7 +11,7 @@ fn main() {
a / a; //~ ERROR cannot divide `A` by `A`
- a % a; //~ ERROR cannot mod `A` by `A`
+ a % a; //~ ERROR cannot calculate the remainder of `A` divided by `A`
a & a; //~ ERROR no implementation for `A & A`
diff --git a/tests/ui/binop/issue-28837.stderr b/tests/ui/binop/issue-28837.stderr
index 6e236ca52..cca1da3b6 100644
--- a/tests/ui/binop/issue-28837.stderr
+++ b/tests/ui/binop/issue-28837.stderr
@@ -62,7 +62,7 @@ LL | struct A;
note: the trait `Div` must be implemented
--> $SRC_DIR/core/src/ops/arith.rs:LL:COL
-error[E0369]: cannot mod `A` by `A`
+error[E0369]: cannot calculate the remainder of `A` divided by `A`
--> $DIR/issue-28837.rs:14:7
|
LL | a % a;
diff --git a/tests/ui/blind/blind-item-block-middle.stderr b/tests/ui/blind/blind-item-block-middle.stderr
index eb64fea94..63e6d7684 100644
--- a/tests/ui/blind/blind-item-block-middle.stderr
+++ b/tests/ui/blind/blind-item-block-middle.stderr
@@ -7,7 +7,7 @@ LL | mod foo { pub struct bar; }
LL | let bar = 5;
| ^^^ - this expression has type `{integer}`
| |
- | expected integer, found struct `bar`
+ | expected integer, found `bar`
| `bar` is interpreted as a unit struct, not a new binding
| help: introduce a new binding instead: `other_bar`
diff --git a/tests/ui/block-result/consider-removing-last-semi.stderr b/tests/ui/block-result/consider-removing-last-semi.stderr
index 9be0367ae..d30ab1293 100644
--- a/tests/ui/block-result/consider-removing-last-semi.stderr
+++ b/tests/ui/block-result/consider-removing-last-semi.stderr
@@ -2,7 +2,7 @@ error[E0308]: mismatched types
--> $DIR/consider-removing-last-semi.rs:3:15
|
LL | pub fn f() -> String {
- | - ^^^^^^ expected struct `String`, found `()`
+ | - ^^^^^^ expected `String`, found `()`
| |
| implicitly returns `()` as its body has no tail or `return` expression
LL | 0u8;
@@ -13,7 +13,7 @@ error[E0308]: mismatched types
--> $DIR/consider-removing-last-semi.rs:8:15
|
LL | pub fn g() -> String {
- | - ^^^^^^ expected struct `String`, found `()`
+ | - ^^^^^^ expected `String`, found `()`
| |
| implicitly returns `()` as its body has no tail or `return` expression
LL | "this won't work".to_string();
diff --git a/tests/ui/block-result/issue-13428.stderr b/tests/ui/block-result/issue-13428.stderr
index 2b386d10c..c119b69da 100644
--- a/tests/ui/block-result/issue-13428.stderr
+++ b/tests/ui/block-result/issue-13428.stderr
@@ -2,7 +2,7 @@ error[E0308]: mismatched types
--> $DIR/issue-13428.rs:3:13
|
LL | fn foo() -> String {
- | --- ^^^^^^ expected struct `String`, found `()`
+ | --- ^^^^^^ expected `String`, found `()`
| |
| implicitly returns `()` as its body has no tail or `return` expression
@@ -10,7 +10,7 @@ error[E0308]: mismatched types
--> $DIR/issue-13428.rs:11:13
|
LL | fn bar() -> String {
- | --- ^^^^^^ expected struct `String`, found `()`
+ | --- ^^^^^^ expected `String`, found `()`
| |
| implicitly returns `()` as its body has no tail or `return` expression
LL | "foobar".to_string()
diff --git a/tests/ui/block-result/issue-13624.rs b/tests/ui/block-result/issue-13624.rs
index 4d2844cc5..8f93e5a35 100644
--- a/tests/ui/block-result/issue-13624.rs
+++ b/tests/ui/block-result/issue-13624.rs
@@ -6,7 +6,7 @@ mod a {
pub fn get_enum_struct_variant() -> () {
Enum::EnumStructVariant { x: 1, y: 2, z: 3 }
//~^ ERROR mismatched types
- //~| expected `()`, found enum `Enum`
+ //~| expected `()`, found `Enum`
}
}
@@ -19,7 +19,7 @@ mod b {
match enum_struct_variant {
a::Enum::EnumStructVariant { x, y, z } => {
//~^ ERROR mismatched types
- //~| expected `()`, found enum `Enum`
+ //~| expected `()`, found `Enum`
}
}
}
diff --git a/tests/ui/block-result/issue-13624.stderr b/tests/ui/block-result/issue-13624.stderr
index 13070b4e8..d41bd057f 100644
--- a/tests/ui/block-result/issue-13624.stderr
+++ b/tests/ui/block-result/issue-13624.stderr
@@ -4,7 +4,7 @@ error[E0308]: mismatched types
LL | pub fn get_enum_struct_variant() -> () {
| -- expected `()` because of return type
LL | Enum::EnumStructVariant { x: 1, y: 2, z: 3 }
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found enum `Enum`
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found `Enum`
error[E0308]: mismatched types
--> $DIR/issue-13624.rs:20:9
@@ -12,7 +12,7 @@ error[E0308]: mismatched types
LL | match enum_struct_variant {
| ------------------- this expression has type `()`
LL | a::Enum::EnumStructVariant { x, y, z } => {
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found enum `Enum`
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found `Enum`
error: aborting due to 2 previous errors
diff --git a/tests/ui/block-result/issue-22645.stderr b/tests/ui/block-result/issue-22645.stderr
index 24341c0f5..677b40aaa 100644
--- a/tests/ui/block-result/issue-22645.stderr
+++ b/tests/ui/block-result/issue-22645.stderr
@@ -20,7 +20,7 @@ LL | fn main() {
| - expected `()` because of default return type
LL | let b = Bob + 3.5;
LL | b + 3
- | ^^^^^ expected `()`, found struct `Bob`
+ | ^^^^^ expected `()`, found `Bob`
error: aborting due to 2 previous errors
diff --git a/tests/ui/block-result/issue-5500.rs b/tests/ui/block-result/issue-5500.rs
index 577987a45..de7fd39a2 100644
--- a/tests/ui/block-result/issue-5500.rs
+++ b/tests/ui/block-result/issue-5500.rs
@@ -3,5 +3,5 @@ fn main() {
//~^ ERROR mismatched types
//~| expected unit type `()`
//~| found reference `&_`
- //~| expected `()`, found reference
+ //~| expected `()`, found `&_`
}
diff --git a/tests/ui/block-result/issue-5500.stderr b/tests/ui/block-result/issue-5500.stderr
index 211a60528..8cd4bd658 100644
--- a/tests/ui/block-result/issue-5500.stderr
+++ b/tests/ui/block-result/issue-5500.stderr
@@ -4,7 +4,7 @@ error[E0308]: mismatched types
LL | fn main() {
| - expected `()` because of default return type
LL | &panic!()
- | ^^^^^^^^^ expected `()`, found reference
+ | ^^^^^^^^^ expected `()`, found `&_`
|
= note: expected unit type `()`
found reference `&_`
diff --git a/tests/ui/borrowck/bindings-after-at-or-patterns-slice-patterns-box-patterns.stderr b/tests/ui/borrowck/bindings-after-at-or-patterns-slice-patterns-box-patterns.stderr
index 50eee1049..5835f0675 100644
--- a/tests/ui/borrowck/bindings-after-at-or-patterns-slice-patterns-box-patterns.stderr
+++ b/tests/ui/borrowck/bindings-after-at-or-patterns-slice-patterns-box-patterns.stderr
@@ -4,8 +4,8 @@ error: cannot borrow value as mutable because it is also borrowed as immutable
LL | ref foo @ [.., ref mut bar] => (),
| -------^^^^^^^^-----------^
| | |
- | | mutable borrow, by `bar`, occurs here
- | immutable borrow, by `foo`, occurs here
+ | | value is mutably borrowed by `bar` here
+ | value is borrowed by `foo` here
error: cannot borrow value as mutable because it is also borrowed as immutable
--> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:120:9
@@ -13,8 +13,8 @@ error: cannot borrow value as mutable because it is also borrowed as immutable
LL | ref foo @ Some(box ref mut s) => (),
| -------^^^^^^^^^^^^---------^
| | |
- | | mutable borrow, by `s`, occurs here
- | immutable borrow, by `foo`, occurs here
+ | | value is mutably borrowed by `s` here
+ | value is borrowed by `foo` here
error[E0382]: borrow of moved value: `x`
--> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:18:5
diff --git a/tests/ui/borrowck/borrow-tuple-fields.stderr b/tests/ui/borrowck/borrow-tuple-fields.stderr
index befa751a6..d7d3efe49 100644
--- a/tests/ui/borrowck/borrow-tuple-fields.stderr
+++ b/tests/ui/borrowck/borrow-tuple-fields.stderr
@@ -1,6 +1,8 @@
error[E0505]: cannot move out of `x` because it is borrowed
--> $DIR/borrow-tuple-fields.rs:12:13
|
+LL | let x: (Box<_>, _) = (Box::new(1), 2);
+ | - binding `x` declared here
LL | let r = &x.0;
| ---- borrow of `x.0` occurs here
LL | let y = x;
@@ -32,6 +34,8 @@ LL | a.use_ref();
error[E0505]: cannot move out of `x` because it is borrowed
--> $DIR/borrow-tuple-fields.rs:28:13
|
+LL | let x = Foo(Box::new(1), 2);
+ | - binding `x` declared here
LL | let r = &x.0;
| ---- borrow of `x.0` occurs here
LL | let y = x;
diff --git a/tests/ui/borrowck/borrowck-anon-fields-variant.stderr b/tests/ui/borrowck/borrowck-anon-fields-variant.stderr
index 98f6f00a7..c1d668f74 100644
--- a/tests/ui/borrowck/borrowck-anon-fields-variant.stderr
+++ b/tests/ui/borrowck/borrowck-anon-fields-variant.stderr
@@ -2,7 +2,7 @@ error[E0503]: cannot use `y` because it was mutably borrowed
--> $DIR/borrowck-anon-fields-variant.rs:16:19
|
LL | Foo::Y(ref mut a, _) => a,
- | --------- borrow of `y.0` occurs here
+ | --------- `y.0` is borrowed here
...
LL | let b = match y {
| ^ use of borrowed `y.0`
@@ -14,7 +14,7 @@ error[E0503]: cannot use `y` because it was mutably borrowed
--> $DIR/borrowck-anon-fields-variant.rs:34:19
|
LL | Foo::Y(ref mut a, _) => a,
- | --------- borrow of `y.0` occurs here
+ | --------- `y.0` is borrowed here
...
LL | let b = match y {
| ^ use of borrowed `y.0`
diff --git a/tests/ui/borrowck/borrowck-assign-comp.stderr b/tests/ui/borrowck/borrowck-assign-comp.stderr
index 2b7cef7b3..d35f2331a 100644
--- a/tests/ui/borrowck/borrowck-assign-comp.stderr
+++ b/tests/ui/borrowck/borrowck-assign-comp.stderr
@@ -2,10 +2,10 @@ error[E0506]: cannot assign to `p.x` because it is borrowed
--> $DIR/borrowck-assign-comp.rs:10:5
|
LL | let q = &p;
- | -- borrow of `p.x` occurs here
+ | -- `p.x` is borrowed here
...
LL | p.x = 5;
- | ^^^^^^^ assignment to borrowed `p.x` occurs here
+ | ^^^^^^^ `p.x` is assigned to here but it was already borrowed
LL | q.x;
| --- borrow later used here
@@ -13,9 +13,9 @@ error[E0506]: cannot assign to `p` because it is borrowed
--> $DIR/borrowck-assign-comp.rs:20:5
|
LL | let q = &p.y;
- | ---- borrow of `p` occurs here
+ | ---- `p` is borrowed here
LL | p = Point {x: 5, y: 7};
- | ^^^^^^^^^^^^^^^^^^^^^^ assignment to borrowed `p` occurs here
+ | ^^^^^^^^^^^^^^^^^^^^^^ `p` is assigned to here but it was already borrowed
LL | p.x; // silence warning
LL | *q; // stretch loan
| -- borrow later used here
@@ -24,9 +24,9 @@ error[E0506]: cannot assign to `p.y` because it is borrowed
--> $DIR/borrowck-assign-comp.rs:31:5
|
LL | let q = &p.y;
- | ---- borrow of `p.y` occurs here
+ | ---- `p.y` is borrowed here
LL | p.y = 5;
- | ^^^^^^^ assignment to borrowed `p.y` occurs here
+ | ^^^^^^^ `p.y` is assigned to here but it was already borrowed
LL | *q;
| -- borrow later used here
diff --git a/tests/ui/borrowck/borrowck-assign-to-andmut-in-borrowed-loc.stderr b/tests/ui/borrowck/borrowck-assign-to-andmut-in-borrowed-loc.stderr
index 0b21d113f..8c0a8efcc 100644
--- a/tests/ui/borrowck/borrowck-assign-to-andmut-in-borrowed-loc.stderr
+++ b/tests/ui/borrowck/borrowck-assign-to-andmut-in-borrowed-loc.stderr
@@ -2,7 +2,7 @@ error[E0503]: cannot use `*y.pointer` because it was mutably borrowed
--> $DIR/borrowck-assign-to-andmut-in-borrowed-loc.rs:18:9
|
LL | let z = copy_borrowed_ptr(&mut y);
- | ------ borrow of `y` occurs here
+ | ------ `y` is borrowed here
LL | *y.pointer += 1;
| ^^^^^^^^^^^^^^^ use of borrowed `y`
...
@@ -13,9 +13,9 @@ error[E0506]: cannot assign to `*y.pointer` because it is borrowed
--> $DIR/borrowck-assign-to-andmut-in-borrowed-loc.rs:18:9
|
LL | let z = copy_borrowed_ptr(&mut y);
- | ------ borrow of `*y.pointer` occurs here
+ | ------ `*y.pointer` is borrowed here
LL | *y.pointer += 1;
- | ^^^^^^^^^^^^^^^ assignment to borrowed `*y.pointer` occurs here
+ | ^^^^^^^^^^^^^^^ `*y.pointer` is assigned to here but it was already borrowed
...
LL | *z.pointer += 1;
| --------------- borrow later used here
diff --git a/tests/ui/borrowck/borrowck-bad-nested-calls-move.stderr b/tests/ui/borrowck/borrowck-bad-nested-calls-move.stderr
index 371bcf2b6..e582ec605 100644
--- a/tests/ui/borrowck/borrowck-bad-nested-calls-move.stderr
+++ b/tests/ui/borrowck/borrowck-bad-nested-calls-move.stderr
@@ -1,6 +1,9 @@
error[E0505]: cannot move out of `a` because it is borrowed
--> $DIR/borrowck-bad-nested-calls-move.rs:25:9
|
+LL | let mut a: Box<_> = Box::new(1);
+ | ----- binding `a` declared here
+...
LL | add(
| --- borrow later used by call
LL | &*a,
@@ -11,6 +14,8 @@ LL | a);
error[E0505]: cannot move out of `a` because it is borrowed
--> $DIR/borrowck-bad-nested-calls-move.rs:32:9
|
+LL | let mut a: Box<_> = Box::new(1);
+ | ----- binding `a` declared here
LL | add(
| --- borrow later used by call
LL | &*a,
diff --git a/tests/ui/borrowck/borrowck-borrow-mut-base-ptr-in-aliasable-loc.stderr b/tests/ui/borrowck/borrowck-borrow-mut-base-ptr-in-aliasable-loc.stderr
index ce9f7aa05..dd0817ff2 100644
--- a/tests/ui/borrowck/borrowck-borrow-mut-base-ptr-in-aliasable-loc.stderr
+++ b/tests/ui/borrowck/borrowck-borrow-mut-base-ptr-in-aliasable-loc.stderr
@@ -1,11 +1,13 @@
error[E0594]: cannot assign to `**t1`, which is behind a `&` reference
--> $DIR/borrowck-borrow-mut-base-ptr-in-aliasable-loc.rs:9:5
|
-LL | let t1 = t0;
- | -- consider changing this binding's type to be: `&mut &mut isize`
-LL | let p: &isize = &**t0;
LL | **t1 = 22;
| ^^^^^^^^^ `t1` is a `&` reference, so the data it refers to cannot be written
+ |
+help: consider specifying this binding's type
+ |
+LL | let t1: &mut &mut isize = t0;
+ | +++++++++++++++++
error[E0502]: cannot borrow `**t0` as immutable because it is also borrowed as mutable
--> $DIR/borrowck-borrow-mut-base-ptr-in-aliasable-loc.rs:14:21
diff --git a/tests/ui/borrowck/borrowck-closures-mut-and-imm.stderr b/tests/ui/borrowck/borrowck-closures-mut-and-imm.stderr
index fadcd11a5..8a7870e0c 100644
--- a/tests/ui/borrowck/borrowck-closures-mut-and-imm.stderr
+++ b/tests/ui/borrowck/borrowck-closures-mut-and-imm.stderr
@@ -49,9 +49,9 @@ error[E0506]: cannot assign to `x` because it is borrowed
LL | let c2 = || x * 5;
| -- - borrow occurs due to use in closure
| |
- | borrow of `x` occurs here
+ | `x` is borrowed here
LL | x = 5;
- | ^^^^^ assignment to borrowed `x` occurs here
+ | ^^^^^ `x` is assigned to here but it was already borrowed
LL |
LL | drop(c2);
| -- borrow later used here
@@ -62,9 +62,9 @@ error[E0506]: cannot assign to `x` because it is borrowed
LL | let c1 = || get(&x);
| -- - borrow occurs due to use in closure
| |
- | borrow of `x` occurs here
+ | `x` is borrowed here
LL | x = 5;
- | ^^^^^ assignment to borrowed `x` occurs here
+ | ^^^^^ `x` is assigned to here but it was already borrowed
LL |
LL | drop(c1);
| -- borrow later used here
@@ -75,9 +75,9 @@ error[E0506]: cannot assign to `*x` because it is borrowed
LL | let c1 = || get(&*x);
| -- -- borrow occurs due to use in closure
| |
- | borrow of `*x` occurs here
+ | `*x` is borrowed here
LL | *x = 5;
- | ^^^^^^ assignment to borrowed `*x` occurs here
+ | ^^^^^^ `*x` is assigned to here but it was already borrowed
LL |
LL | drop(c1);
| -- borrow later used here
@@ -88,9 +88,9 @@ error[E0506]: cannot assign to `*x.f` because it is borrowed
LL | let c1 = || get(&*x.f);
| -- ---- borrow occurs due to use in closure
| |
- | borrow of `*x.f` occurs here
+ | `*x.f` is borrowed here
LL | *x.f = 5;
- | ^^^^^^^^ assignment to borrowed `*x.f` occurs here
+ | ^^^^^^^^ `*x.f` is assigned to here but it was already borrowed
LL |
LL | drop(c1);
| -- borrow later used here
diff --git a/tests/ui/borrowck/borrowck-describe-lvalue.stderr b/tests/ui/borrowck/borrowck-describe-lvalue.stderr
index 2c1b9c10d..cb29c9fda 100644
--- a/tests/ui/borrowck/borrowck-describe-lvalue.stderr
+++ b/tests/ui/borrowck/borrowck-describe-lvalue.stderr
@@ -45,7 +45,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
+ | ----- `f` is borrowed here
LL | f.x;
| ^^^ use of borrowed `f`
LL | drop(x);
@@ -55,7 +55,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
+ | ----- `g` is borrowed here
LL | g.0;
| ^^^ use of borrowed `g`
LL | drop(x);
@@ -65,7 +65,7 @@ error[E0503]: cannot use `h.0` because it was mutably borrowed
--> $DIR/borrowck-describe-lvalue.rs:51:9
|
LL | let x = &mut h.0;
- | -------- borrow of `h.0` occurs here
+ | -------- `h.0` is borrowed here
LL | h.0;
| ^^^ use of borrowed `h.0`
LL | drop(x);
@@ -75,7 +75,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
+ | ----- `e` is borrowed here
LL | match e {
LL | Baz::X(value) => value
| ^^^^^ use of borrowed `e`
@@ -87,7 +87,7 @@ error[E0503]: cannot use `u.a` because it was mutably borrowed
--> $DIR/borrowck-describe-lvalue.rs:67:9
|
LL | let x = &mut u.a;
- | -------- borrow of `u.a` occurs here
+ | -------- `u.a` is borrowed here
LL | u.a;
| ^^^ use of borrowed `u.a`
LL | drop(x);
@@ -97,7 +97,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
+ | ----- `*f` is borrowed here
LL | f.x;
| ^^^ use of borrowed `*f`
LL | drop(x);
@@ -107,7 +107,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
+ | ----- `*g` is borrowed here
LL | g.0;
| ^^^ use of borrowed `*g`
LL | drop(x);
@@ -117,7 +117,7 @@ error[E0503]: cannot use `h.0` because it was mutably borrowed
--> $DIR/borrowck-describe-lvalue.rs:88:9
|
LL | let x = &mut h.0;
- | -------- borrow of `h.0` occurs here
+ | -------- `h.0` is borrowed here
LL | h.0;
| ^^^ use of borrowed `h.0`
LL | drop(x);
@@ -127,7 +127,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
+ | ----- `*e` is borrowed here
LL | match *e {
LL | Baz::X(value) => value
| ^^^^^ use of borrowed `*e`
@@ -139,7 +139,7 @@ error[E0503]: cannot use `u.a` because it was mutably borrowed
--> $DIR/borrowck-describe-lvalue.rs:105:9
|
LL | let x = &mut u.a;
- | -------- borrow of `u.a` occurs here
+ | -------- `u.a` is borrowed here
LL | u.a;
| ^^^ use of borrowed `u.a`
LL | drop(x);
@@ -149,7 +149,7 @@ error[E0503]: cannot use `v[..]` because it was mutably borrowed
--> $DIR/borrowck-describe-lvalue.rs:113:15
|
LL | let x = &mut v;
- | ------ borrow of `v` occurs here
+ | ------ `v` is borrowed here
LL | match v {
LL | &[x, _, .., _, _] => println!("{}", x),
| ^ use of borrowed `v`
@@ -161,7 +161,7 @@ error[E0503]: cannot use `v[..]` because it was mutably borrowed
--> $DIR/borrowck-describe-lvalue.rs:118:18
|
LL | let x = &mut v;
- | ------ borrow of `v` occurs here
+ | ------ `v` is borrowed here
...
LL | &[_, x, .., _, _] => println!("{}", x),
| ^ use of borrowed `v`
@@ -173,7 +173,7 @@ error[E0503]: cannot use `v[..]` because it was mutably borrowed
--> $DIR/borrowck-describe-lvalue.rs:123:25
|
LL | let x = &mut v;
- | ------ borrow of `v` occurs here
+ | ------ `v` is borrowed here
...
LL | &[_, _, .., x, _] => println!("{}", x),
| ^ use of borrowed `v`
@@ -185,7 +185,7 @@ error[E0503]: cannot use `v[..]` because it was mutably borrowed
--> $DIR/borrowck-describe-lvalue.rs:128:28
|
LL | let x = &mut v;
- | ------ borrow of `v` occurs here
+ | ------ `v` is borrowed here
...
LL | &[_, _, .., _, x] => println!("{}", x),
| ^ use of borrowed `v`
@@ -197,7 +197,7 @@ error[E0503]: cannot use `v[..]` because it was mutably borrowed
--> $DIR/borrowck-describe-lvalue.rs:139:15
|
LL | let x = &mut v;
- | ------ borrow of `v` occurs here
+ | ------ `v` is borrowed here
LL | match v {
LL | &[x @ ..] => println!("{:?}", x),
| ^ use of borrowed `v`
@@ -209,7 +209,7 @@ error[E0503]: cannot use `v[..]` because it was mutably borrowed
--> $DIR/borrowck-describe-lvalue.rs:144:18
|
LL | let x = &mut v;
- | ------ borrow of `v` occurs here
+ | ------ `v` is borrowed here
...
LL | &[_, x @ ..] => println!("{:?}", x),
| ^ use of borrowed `v`
@@ -221,7 +221,7 @@ error[E0503]: cannot use `v[..]` because it was mutably borrowed
--> $DIR/borrowck-describe-lvalue.rs:149:15
|
LL | let x = &mut v;
- | ------ borrow of `v` occurs here
+ | ------ `v` is borrowed here
...
LL | &[x @ .., _] => println!("{:?}", x),
| ^ use of borrowed `v`
@@ -233,7 +233,7 @@ error[E0503]: cannot use `v[..]` because it was mutably borrowed
--> $DIR/borrowck-describe-lvalue.rs:154:18
|
LL | let x = &mut v;
- | ------ borrow of `v` occurs here
+ | ------ `v` is borrowed here
...
LL | &[_, x @ .., _] => println!("{:?}", x),
| ^ use of borrowed `v`
@@ -245,7 +245,7 @@ error[E0503]: cannot use `e` because it was mutably borrowed
--> $DIR/borrowck-describe-lvalue.rs:166:15
|
LL | let x = &mut e;
- | ------ borrow of `e` occurs here
+ | ------ `e` is borrowed here
LL | match e {
| ^ use of borrowed `e`
...
@@ -304,7 +304,7 @@ error[E0503]: cannot use `*v` because it was mutably borrowed
--> $DIR/borrowck-describe-lvalue.rs:232:9
|
LL | let x = &mut v;
- | ------ borrow of `v` occurs here
+ | ------ `v` is borrowed here
LL | v[0].y;
| ^^^^ use of borrowed `v`
...
@@ -315,7 +315,7 @@ error[E0503]: cannot use `v[_].y` because it was mutably borrowed
--> $DIR/borrowck-describe-lvalue.rs:232:9
|
LL | let x = &mut v;
- | ------ borrow of `v` occurs here
+ | ------ `v` is borrowed here
LL | v[0].y;
| ^^^^^^ use of borrowed `v`
...
diff --git a/tests/ui/borrowck/borrowck-field-sensitivity.stderr b/tests/ui/borrowck/borrowck-field-sensitivity.stderr
index e009f5913..11812847d 100644
--- a/tests/ui/borrowck/borrowck-field-sensitivity.stderr
+++ b/tests/ui/borrowck/borrowck-field-sensitivity.stderr
@@ -41,6 +41,8 @@ LL | let p = &x.b;
error[E0505]: cannot move out of `x.b` because it is borrowed
--> $DIR/borrowck-field-sensitivity.rs:34:10
|
+LL | let x = A { a: 1, b: Box::new(2) };
+ | - binding `x` declared here
LL | let p = &x.b;
| ---- borrow of `x.b` occurs here
LL | drop(x.b);
@@ -51,6 +53,8 @@ LL | drop(**p);
error[E0505]: cannot move out of `x.b` because it is borrowed
--> $DIR/borrowck-field-sensitivity.rs:41:14
|
+LL | let x = A { a: 1, b: Box::new(2) };
+ | - binding `x` declared here
LL | let p = &x.b;
| ---- borrow of `x.b` occurs here
LL | let _y = A { a: 3, .. x };
diff --git a/tests/ui/borrowck/borrowck-imm-ref-to-mut-rec-field-issue-3162-c.stderr b/tests/ui/borrowck/borrowck-imm-ref-to-mut-rec-field-issue-3162-c.stderr
index a66db05cc..1a20ec85f 100644
--- a/tests/ui/borrowck/borrowck-imm-ref-to-mut-rec-field-issue-3162-c.stderr
+++ b/tests/ui/borrowck/borrowck-imm-ref-to-mut-rec-field-issue-3162-c.stderr
@@ -2,10 +2,10 @@ error[E0506]: cannot assign to `_a` because it is borrowed
--> $DIR/borrowck-imm-ref-to-mut-rec-field-issue-3162-c.rs:6:9
|
LL | let b = &mut _a;
- | ------- borrow of `_a` occurs here
+ | ------- `_a` is borrowed here
...
LL | _a = 4;
- | ^^^^^^ assignment to borrowed `_a` occurs here
+ | ^^^^^^ `_a` is assigned to here but it was already borrowed
...
LL | drop(b);
| - borrow later used here
diff --git a/tests/ui/borrowck/borrowck-issue-14498.stderr b/tests/ui/borrowck/borrowck-issue-14498.stderr
index 42a55b7a8..374c5ee3e 100644
--- a/tests/ui/borrowck/borrowck-issue-14498.stderr
+++ b/tests/ui/borrowck/borrowck-issue-14498.stderr
@@ -13,10 +13,10 @@ error[E0506]: cannot assign to `**y` because it is borrowed
--> $DIR/borrowck-issue-14498.rs:25:5
|
LL | let p = &y;
- | -- borrow of `**y` occurs here
+ | -- `**y` is borrowed here
LL | let q = &***p;
LL | **y = 2;
- | ^^^^^^^ assignment to borrowed `**y` occurs here
+ | ^^^^^^^ `**y` is assigned to here but it was already borrowed
LL | drop(p);
| - borrow later used here
@@ -24,10 +24,10 @@ error[E0506]: cannot assign to `**y` because it is borrowed
--> $DIR/borrowck-issue-14498.rs:35:5
|
LL | let p = &y;
- | -- borrow of `**y` occurs here
+ | -- `**y` is borrowed here
LL | let q = &***p;
LL | **y = 2;
- | ^^^^^^^ assignment to borrowed `**y` occurs here
+ | ^^^^^^^ `**y` is assigned to here but it was already borrowed
LL | drop(p);
| - borrow later used here
@@ -35,10 +35,10 @@ error[E0506]: cannot assign to `**y` because it is borrowed
--> $DIR/borrowck-issue-14498.rs:45:5
|
LL | let p = &y;
- | -- borrow of `**y` occurs here
+ | -- `**y` is borrowed here
LL | let q = &***p;
LL | **y = 2;
- | ^^^^^^^ assignment to borrowed `**y` occurs here
+ | ^^^^^^^ `**y` is assigned to here but it was already borrowed
LL | drop(p);
| - borrow later used here
@@ -46,10 +46,10 @@ error[E0506]: cannot assign to `**y` because it is borrowed
--> $DIR/borrowck-issue-14498.rs:55:5
|
LL | let p = &y;
- | -- borrow of `**y` occurs here
+ | -- `**y` is borrowed here
LL | let q = &***p;
LL | **y = 2;
- | ^^^^^^^ assignment to borrowed `**y` occurs here
+ | ^^^^^^^ `**y` is assigned to here but it was already borrowed
LL | drop(p);
| - borrow later used here
@@ -57,10 +57,10 @@ error[E0506]: cannot assign to `**y.a` because it is borrowed
--> $DIR/borrowck-issue-14498.rs:65:5
|
LL | let p = &y.a;
- | ---- borrow of `**y.a` occurs here
+ | ---- `**y.a` is borrowed here
LL | let q = &***p;
LL | **y.a = 2;
- | ^^^^^^^^^ assignment to borrowed `**y.a` occurs here
+ | ^^^^^^^^^ `**y.a` is assigned to here but it was already borrowed
LL | drop(p);
| - borrow later used here
@@ -68,10 +68,10 @@ error[E0506]: cannot assign to `**y.a` because it is borrowed
--> $DIR/borrowck-issue-14498.rs:75:5
|
LL | let p = &y.a;
- | ---- borrow of `**y.a` occurs here
+ | ---- `**y.a` is borrowed here
LL | let q = &***p;
LL | **y.a = 2;
- | ^^^^^^^^^ assignment to borrowed `**y.a` occurs here
+ | ^^^^^^^^^ `**y.a` is assigned to here but it was already borrowed
LL | drop(p);
| - borrow later used here
@@ -79,10 +79,10 @@ error[E0506]: cannot assign to `**y.a` because it is borrowed
--> $DIR/borrowck-issue-14498.rs:85:5
|
LL | let p = &y.a;
- | ---- borrow of `**y.a` occurs here
+ | ---- `**y.a` is borrowed here
LL | let q = &***p;
LL | **y.a = 2;
- | ^^^^^^^^^ assignment to borrowed `**y.a` occurs here
+ | ^^^^^^^^^ `**y.a` is assigned to here but it was already borrowed
LL | drop(p);
| - borrow later used here
@@ -90,10 +90,10 @@ error[E0506]: cannot assign to `**y.a` because it is borrowed
--> $DIR/borrowck-issue-14498.rs:95:5
|
LL | let p = &y.a;
- | ---- borrow of `**y.a` occurs here
+ | ---- `**y.a` is borrowed here
LL | let q = &***p;
LL | **y.a = 2;
- | ^^^^^^^^^ assignment to borrowed `**y.a` occurs here
+ | ^^^^^^^^^ `**y.a` is assigned to here but it was already borrowed
LL | drop(p);
| - borrow later used here
diff --git a/tests/ui/borrowck/borrowck-lend-flow-match.stderr b/tests/ui/borrowck/borrowck-lend-flow-match.stderr
index 66f1cd9bd..6cdce7bee 100644
--- a/tests/ui/borrowck/borrowck-lend-flow-match.stderr
+++ b/tests/ui/borrowck/borrowck-lend-flow-match.stderr
@@ -2,9 +2,9 @@ error[E0506]: cannot assign to `x` because it is borrowed
--> $DIR/borrowck-lend-flow-match.rs:12:13
|
LL | Some(ref r) => {
- | ----- borrow of `x` occurs here
+ | ----- `x` is borrowed here
LL | x = Some(1);
- | ^^^^^^^^^^^ assignment to borrowed `x` occurs here
+ | ^^^^^^^^^^^ `x` is assigned to here but it was already borrowed
LL | drop(r);
| - borrow later used here
diff --git a/tests/ui/borrowck/borrowck-loan-blocks-move-cc.stderr b/tests/ui/borrowck/borrowck-loan-blocks-move-cc.stderr
index 3548da35b..6eabfff90 100644
--- a/tests/ui/borrowck/borrowck-loan-blocks-move-cc.stderr
+++ b/tests/ui/borrowck/borrowck-loan-blocks-move-cc.stderr
@@ -1,6 +1,8 @@
error[E0505]: cannot move out of `v` because it is borrowed
--> $DIR/borrowck-loan-blocks-move-cc.rs:14:19
|
+LL | let v: Box<_> = Box::new(3);
+ | - binding `v` declared here
LL | let w = &v;
| -- borrow of `v` occurs here
LL | thread::spawn(move|| {
@@ -15,6 +17,8 @@ LL | w.use_ref();
error[E0505]: cannot move out of `v` because it is borrowed
--> $DIR/borrowck-loan-blocks-move-cc.rs:24:19
|
+LL | let v: Box<_> = Box::new(3);
+ | - binding `v` declared here
LL | let w = &v;
| -- borrow of `v` occurs here
LL | thread::spawn(move|| {
diff --git a/tests/ui/borrowck/borrowck-loan-blocks-move.stderr b/tests/ui/borrowck/borrowck-loan-blocks-move.stderr
index b5c6b101f..38e06fa01 100644
--- a/tests/ui/borrowck/borrowck-loan-blocks-move.stderr
+++ b/tests/ui/borrowck/borrowck-loan-blocks-move.stderr
@@ -1,6 +1,8 @@
error[E0505]: cannot move out of `v` because it is borrowed
--> $DIR/borrowck-loan-blocks-move.rs:11:10
|
+LL | let v = Box::new(3);
+ | - binding `v` declared here
LL | let w = &v;
| -- borrow of `v` occurs here
LL | take(v);
diff --git a/tests/ui/borrowck/borrowck-loan-of-static-data-issue-27616.stderr b/tests/ui/borrowck/borrowck-loan-of-static-data-issue-27616.stderr
index 6994c837d..311369a26 100644
--- a/tests/ui/borrowck/borrowck-loan-of-static-data-issue-27616.stderr
+++ b/tests/ui/borrowck/borrowck-loan-of-static-data-issue-27616.stderr
@@ -2,12 +2,12 @@ error[E0506]: cannot assign to `*s` because it is borrowed
--> $DIR/borrowck-loan-of-static-data-issue-27616.rs:16:5
|
LL | let alias: &'static mut String = s;
- | ------------------- - borrow of `*s` occurs here
+ | ------------------- - `*s` is borrowed here
| |
| type annotation requires that `*s` is borrowed for `'static`
...
LL | *s = String::new();
- | ^^ assignment to borrowed `*s` occurs here
+ | ^^ `*s` is assigned to here but it was already borrowed
error: aborting due to previous error
diff --git a/tests/ui/borrowck/borrowck-loan-rcvr-overloaded-op.stderr b/tests/ui/borrowck/borrowck-loan-rcvr-overloaded-op.stderr
index 24cc4933e..f1640d3b7 100644
--- a/tests/ui/borrowck/borrowck-loan-rcvr-overloaded-op.stderr
+++ b/tests/ui/borrowck/borrowck-loan-rcvr-overloaded-op.stderr
@@ -2,7 +2,7 @@ error[E0503]: cannot use `p` because it was mutably borrowed
--> $DIR/borrowck-loan-rcvr-overloaded-op.rs:38:5
|
LL | let q = &mut p;
- | ------ borrow of `p` occurs here
+ | ------ `p` is borrowed here
LL |
LL | p + 3;
| ^ use of borrowed `p`
diff --git a/tests/ui/borrowck/borrowck-local-borrow-with-panic-outlives-fn.stderr b/tests/ui/borrowck/borrowck-local-borrow-with-panic-outlives-fn.stderr
index 6ea6951ad..0fdb1dabb 100644
--- a/tests/ui/borrowck/borrowck-local-borrow-with-panic-outlives-fn.stderr
+++ b/tests/ui/borrowck/borrowck-local-borrow-with-panic-outlives-fn.stderr
@@ -1,6 +1,8 @@
error[E0597]: `z.1` does not live long enough
--> $DIR/borrowck-local-borrow-with-panic-outlives-fn.rs:3:15
|
+LL | let mut z = (0, 0);
+ | ----- binding `z` declared here
LL | *x = Some(&mut z.1);
| ----------^^^^^^^^-
| | |
diff --git a/tests/ui/borrowck/borrowck-match-already-borrowed.stderr b/tests/ui/borrowck/borrowck-match-already-borrowed.stderr
index 39047be9d..e5c0ec960 100644
--- a/tests/ui/borrowck/borrowck-match-already-borrowed.stderr
+++ b/tests/ui/borrowck/borrowck-match-already-borrowed.stderr
@@ -2,7 +2,7 @@ error[E0503]: cannot use `foo` because it was mutably borrowed
--> $DIR/borrowck-match-already-borrowed.rs:9:19
|
LL | let p = &mut foo;
- | -------- borrow of `foo` occurs here
+ | -------- `foo` is borrowed here
LL | let _ = match foo {
| ^^^ use of borrowed `foo`
...
@@ -13,7 +13,7 @@ error[E0503]: cannot use `foo.0` because it was mutably borrowed
--> $DIR/borrowck-match-already-borrowed.rs:12:16
|
LL | let p = &mut foo;
- | -------- borrow of `foo` occurs here
+ | -------- `foo` is borrowed here
...
LL | Foo::A(x) => x
| ^ use of borrowed `foo`
@@ -25,7 +25,7 @@ error[E0503]: cannot use `x` because it was mutably borrowed
--> $DIR/borrowck-match-already-borrowed.rs:22:9
|
LL | let r = &mut x;
- | ------ borrow of `x` occurs here
+ | ------ `x` is borrowed here
LL | let _ = match x {
LL | x => x + 1,
| ^ use of borrowed `x`
@@ -37,7 +37,7 @@ error[E0503]: cannot use `x` because it was mutably borrowed
--> $DIR/borrowck-match-already-borrowed.rs:23:9
|
LL | let r = &mut x;
- | ------ borrow of `x` occurs here
+ | ------ `x` is borrowed here
...
LL | y => y + 2,
| ^ use of borrowed `x`
diff --git a/tests/ui/borrowck/borrowck-move-by-capture.stderr b/tests/ui/borrowck/borrowck-move-by-capture.stderr
index 8ddc48b2a..6eaa1fa31 100644
--- a/tests/ui/borrowck/borrowck-move-by-capture.stderr
+++ b/tests/ui/borrowck/borrowck-move-by-capture.stderr
@@ -10,7 +10,7 @@ LL | let _h = to_fn_once(move || -> isize { *bar });
| | |
| | variable moved due to use in closure
| | move occurs because `bar` has type `Box<isize>`, which does not implement the `Copy` trait
- | move out of `bar` occurs here
+ | `bar` is moved here
error: aborting due to previous error
diff --git a/tests/ui/borrowck/borrowck-move-from-subpath-of-borrowed-path.stderr b/tests/ui/borrowck/borrowck-move-from-subpath-of-borrowed-path.stderr
index f833abcc0..bd94f1a42 100644
--- a/tests/ui/borrowck/borrowck-move-from-subpath-of-borrowed-path.stderr
+++ b/tests/ui/borrowck/borrowck-move-from-subpath-of-borrowed-path.stderr
@@ -1,6 +1,8 @@
error[E0505]: cannot move out of `*a` because it is borrowed
--> $DIR/borrowck-move-from-subpath-of-borrowed-path.rs:12:13
|
+LL | let a: Box<Box<_>> = Box::new(Box::new(2));
+ | - binding `a` declared here
LL | let b = &a;
| -- borrow of `a` occurs here
LL |
diff --git a/tests/ui/borrowck/borrowck-move-mut-base-ptr.stderr b/tests/ui/borrowck/borrowck-move-mut-base-ptr.stderr
index d5ff0c501..cdad20c52 100644
--- a/tests/ui/borrowck/borrowck-move-mut-base-ptr.stderr
+++ b/tests/ui/borrowck/borrowck-move-mut-base-ptr.stderr
@@ -1,6 +1,8 @@
error[E0505]: cannot move out of `t0` because it is borrowed
--> $DIR/borrowck-move-mut-base-ptr.rs:10:14
|
+LL | fn foo(t0: &mut isize) {
+ | -- binding `t0` declared here
LL | let p: &isize = &*t0; // Freezes `*t0`
| ---- borrow of `*t0` occurs here
LL | let t1 = t0;
diff --git a/tests/ui/borrowck/borrowck-move-subcomponent.stderr b/tests/ui/borrowck/borrowck-move-subcomponent.stderr
index 8c9083fcf..341146bd1 100644
--- a/tests/ui/borrowck/borrowck-move-subcomponent.stderr
+++ b/tests/ui/borrowck/borrowck-move-subcomponent.stderr
@@ -1,6 +1,8 @@
error[E0505]: cannot move out of `a.x` because it is borrowed
--> $DIR/borrowck-move-subcomponent.rs:15:14
|
+LL | let a : S = S { x : Box::new(1) };
+ | - binding `a` declared here
LL | let pb = &a;
| -- borrow of `a` occurs here
LL | let S { x: ax } = a;
diff --git a/tests/ui/borrowck/borrowck-multiple-captures.stderr b/tests/ui/borrowck/borrowck-multiple-captures.stderr
index f94cbc30d..70abe7b34 100644
--- a/tests/ui/borrowck/borrowck-multiple-captures.stderr
+++ b/tests/ui/borrowck/borrowck-multiple-captures.stderr
@@ -1,6 +1,8 @@
error[E0505]: cannot move out of `x1` because it is borrowed
--> $DIR/borrowck-multiple-captures.rs:12:19
|
+LL | let x1: Box<_> = Box::new(1);
+ | -- binding `x1` declared here
LL | let p1 = &x1;
| --- borrow of `x1` occurs here
...
@@ -16,6 +18,8 @@ LL | borrow(&*p1);
error[E0505]: cannot move out of `x2` because it is borrowed
--> $DIR/borrowck-multiple-captures.rs:12:19
|
+LL | let x2: Box<_> = Box::new(2);
+ | -- binding `x2` declared here
LL | let p2 = &x2;
| --- borrow of `x2` occurs here
LL | thread::spawn(move|| {
@@ -77,6 +81,8 @@ LL | drop(x);
error[E0505]: cannot move out of `x` because it is borrowed
--> $DIR/borrowck-multiple-captures.rs:38:19
|
+LL | let x: Box<_> = Box::new(1);
+ | - binding `x` declared here
LL | let p = &x;
| -- borrow of `x` occurs here
LL | thread::spawn(move|| {
diff --git a/tests/ui/borrowck/borrowck-overloaded-index-and-overloaded-deref.stderr b/tests/ui/borrowck/borrowck-overloaded-index-and-overloaded-deref.stderr
index 5d52e4919..7f42becd2 100644
--- a/tests/ui/borrowck/borrowck-overloaded-index-and-overloaded-deref.stderr
+++ b/tests/ui/borrowck/borrowck-overloaded-index-and-overloaded-deref.stderr
@@ -2,9 +2,9 @@ error[E0506]: cannot assign to `v` because it is borrowed
--> $DIR/borrowck-overloaded-index-and-overloaded-deref.rs:31:5
|
LL | let i = &v[0].f;
- | - borrow of `v` occurs here
+ | - `v` is borrowed here
LL | v = MyVec { x: MyPtr { x: Foo { f: 23 } } };
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ assignment to borrowed `v` occurs here
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `v` is assigned to here but it was already borrowed
LL |
LL | read(*i);
| -- borrow later used here
diff --git a/tests/ui/borrowck/borrowck-overloaded-index-autoderef.stderr b/tests/ui/borrowck/borrowck-overloaded-index-autoderef.stderr
index 087f2ac79..fb7af50bc 100644
--- a/tests/ui/borrowck/borrowck-overloaded-index-autoderef.stderr
+++ b/tests/ui/borrowck/borrowck-overloaded-index-autoderef.stderr
@@ -42,9 +42,9 @@ error[E0506]: cannot assign to `f.foo` because it is borrowed
--> $DIR/borrowck-overloaded-index-autoderef.rs:71:5
|
LL | let p = &f.foo[&s];
- | ----- borrow of `f.foo` occurs here
+ | ----- `f.foo` is borrowed here
LL | f.foo = g;
- | ^^^^^^^^^ assignment to borrowed `f.foo` occurs here
+ | ^^^^^^^^^ `f.foo` is assigned to here but it was already borrowed
LL | p.use_ref();
| ----------- borrow later used here
@@ -52,9 +52,9 @@ error[E0506]: cannot assign to `*f` because it is borrowed
--> $DIR/borrowck-overloaded-index-autoderef.rs:77:5
|
LL | let p = &f.foo[&s];
- | ----- borrow of `*f` occurs here
+ | ----- `*f` is borrowed here
LL | *f = g;
- | ^^^^^^ assignment to borrowed `*f` occurs here
+ | ^^^^^^ `*f` is assigned to here but it was already borrowed
LL | p.use_ref();
| ----------- borrow later used here
@@ -62,9 +62,9 @@ error[E0506]: cannot assign to `f.foo` because it is borrowed
--> $DIR/borrowck-overloaded-index-autoderef.rs:83:5
|
LL | let p = &mut f.foo[&s];
- | ----- borrow of `f.foo` occurs here
+ | ----- `f.foo` is borrowed here
LL | f.foo = g;
- | ^^^^^^^^^ assignment to borrowed `f.foo` occurs here
+ | ^^^^^^^^^ `f.foo` is assigned to here but it was already borrowed
LL | p.use_mut();
| ----------- borrow later used here
@@ -72,9 +72,9 @@ error[E0506]: cannot assign to `*f` because it is borrowed
--> $DIR/borrowck-overloaded-index-autoderef.rs:89:5
|
LL | let p = &mut f.foo[&s];
- | ----- borrow of `*f` occurs here
+ | ----- `*f` is borrowed here
LL | *f = g;
- | ^^^^^^ assignment to borrowed `*f` occurs here
+ | ^^^^^^ `*f` is assigned to here but it was already borrowed
LL | p.use_mut();
| ----------- borrow later used here
diff --git a/tests/ui/borrowck/borrowck-overloaded-index-move-index.stderr b/tests/ui/borrowck/borrowck-overloaded-index-move-index.stderr
index fb0e274c2..7f8cc74a7 100644
--- a/tests/ui/borrowck/borrowck-overloaded-index-move-index.stderr
+++ b/tests/ui/borrowck/borrowck-overloaded-index-move-index.stderr
@@ -1,6 +1,8 @@
error[E0505]: cannot move out of `s` because it is borrowed
--> $DIR/borrowck-overloaded-index-move-index.rs:50:22
|
+LL | let mut s = "hello".to_string();
+ | ----- binding `s` declared here
LL | let rs = &mut s;
| ------ borrow of `s` occurs here
LL |
@@ -13,6 +15,8 @@ LL | use_mut(rs);
error[E0505]: cannot move out of `s` because it is borrowed
--> $DIR/borrowck-overloaded-index-move-index.rs:53:7
|
+LL | let mut s = "hello".to_string();
+ | ----- binding `s` declared here
LL | let rs = &mut s;
| ------ borrow of `s` occurs here
...
diff --git a/tests/ui/borrowck/borrowck-pat-reassign-binding.stderr b/tests/ui/borrowck/borrowck-pat-reassign-binding.stderr
index 9e65ccf5a..b86a86938 100644
--- a/tests/ui/borrowck/borrowck-pat-reassign-binding.stderr
+++ b/tests/ui/borrowck/borrowck-pat-reassign-binding.stderr
@@ -2,10 +2,10 @@ error[E0506]: cannot assign to `x` because it is borrowed
--> $DIR/borrowck-pat-reassign-binding.rs:10:11
|
LL | Some(ref i) => {
- | ----- borrow of `x` occurs here
+ | ----- `x` is borrowed here
LL | // But on this branch, `i` is an outstanding borrow
LL | x = Some(*i+1);
- | ^^^^^^^^^^^^^^ assignment to borrowed `x` occurs here
+ | ^^^^^^^^^^^^^^ `x` is assigned to here but it was already borrowed
LL | drop(i);
| - borrow later used here
diff --git a/tests/ui/borrowck/borrowck-unary-move.stderr b/tests/ui/borrowck/borrowck-unary-move.stderr
index aab225ed4..f3b962059 100644
--- a/tests/ui/borrowck/borrowck-unary-move.stderr
+++ b/tests/ui/borrowck/borrowck-unary-move.stderr
@@ -1,6 +1,8 @@
error[E0505]: cannot move out of `x` because it is borrowed
--> $DIR/borrowck-unary-move.rs:3:10
|
+LL | fn foo(x: Box<isize>) -> isize {
+ | - binding `x` declared here
LL | let y = &*x;
| --- borrow of `*x` occurs here
LL | free(x);
diff --git a/tests/ui/borrowck/borrowck-union-borrow-nested.stderr b/tests/ui/borrowck/borrowck-union-borrow-nested.stderr
index 4bd7d54cf..a87a14e7c 100644
--- a/tests/ui/borrowck/borrowck-union-borrow-nested.stderr
+++ b/tests/ui/borrowck/borrowck-union-borrow-nested.stderr
@@ -2,7 +2,7 @@ error[E0503]: cannot use `u.c` because it was mutably borrowed
--> $DIR/borrowck-union-borrow-nested.rs:24:21
|
LL | let ra = &mut u.s.a;
- | ---------- borrow of `u.s.a` occurs here
+ | ---------- `u.s.a` is borrowed here
LL | let b = u.c;
| ^^^ use of borrowed `u.s.a`
LL | ra.use_mut();
diff --git a/tests/ui/borrowck/borrowck-union-borrow.stderr b/tests/ui/borrowck/borrowck-union-borrow.stderr
index 090c7b6b5..11a28f674 100644
--- a/tests/ui/borrowck/borrowck-union-borrow.stderr
+++ b/tests/ui/borrowck/borrowck-union-borrow.stderr
@@ -12,9 +12,9 @@ error[E0506]: cannot assign to `u.a` because it is borrowed
--> $DIR/borrowck-union-borrow.rs:28:13
|
LL | let ra = &u.a;
- | ---- borrow of `u.a` occurs here
+ | ---- `u.a` is borrowed here
LL | u.a = 1;
- | ^^^^^^^ assignment to borrowed `u.a` occurs here
+ | ^^^^^^^ `u.a` is assigned to here but it was already borrowed
LL | drop(ra);
| -- borrow later used here
@@ -34,9 +34,9 @@ error[E0506]: cannot assign to `u.b` because it is borrowed
--> $DIR/borrowck-union-borrow.rs:49:13
|
LL | let ra = &u.a;
- | ---- borrow of `u.b` occurs here
+ | ---- `u.b` is borrowed here
LL | u.b = 1;
- | ^^^^^^^ assignment to borrowed `u.b` occurs here
+ | ^^^^^^^ `u.b` is assigned to here but it was already borrowed
LL | drop(ra);
| -- borrow later used here
@@ -54,7 +54,7 @@ error[E0503]: cannot use `u.a` because it was mutably borrowed
--> $DIR/borrowck-union-borrow.rs:60:21
|
LL | let ra = &mut u.a;
- | -------- borrow of `u.a` occurs here
+ | -------- `u.a` is borrowed here
LL | let a = u.a;
| ^^^ use of borrowed `u.a`
LL | drop(ra);
@@ -74,9 +74,9 @@ error[E0506]: cannot assign to `u.a` because it is borrowed
--> $DIR/borrowck-union-borrow.rs:70:13
|
LL | let rma = &mut u.a;
- | -------- borrow of `u.a` occurs here
+ | -------- `u.a` is borrowed here
LL | u.a = 1;
- | ^^^^^^^ assignment to borrowed `u.a` occurs here
+ | ^^^^^^^ `u.a` is assigned to here but it was already borrowed
LL | drop(rma);
| --- borrow later used here
@@ -96,7 +96,7 @@ error[E0503]: cannot use `u.b` because it was mutably borrowed
--> $DIR/borrowck-union-borrow.rs:81:21
|
LL | let ra = &mut u.a;
- | -------- borrow of `u.a` occurs here
+ | -------- `u.a` is borrowed here
LL | let b = u.b;
| ^^^ use of borrowed `u.a`
LL |
@@ -119,9 +119,9 @@ error[E0506]: cannot assign to `u.b` because it is borrowed
--> $DIR/borrowck-union-borrow.rs:92:13
|
LL | let rma = &mut u.a;
- | -------- borrow of `u.b` occurs here
+ | -------- `u.b` is borrowed here
LL | u.b = 1;
- | ^^^^^^^ assignment to borrowed `u.b` occurs here
+ | ^^^^^^^ `u.b` is assigned to here but it was already borrowed
LL | drop(rma);
| --- borrow later used here
diff --git a/tests/ui/borrowck/borrowck-use-mut-borrow.stderr b/tests/ui/borrowck/borrowck-use-mut-borrow.stderr
index 91d69c51e..4d300ae3c 100644
--- a/tests/ui/borrowck/borrowck-use-mut-borrow.stderr
+++ b/tests/ui/borrowck/borrowck-use-mut-borrow.stderr
@@ -2,7 +2,7 @@ error[E0503]: cannot use `x` because it was mutably borrowed
--> $DIR/borrowck-use-mut-borrow.rs:11:10
|
LL | let p = &mut x;
- | ------ borrow of `x` occurs here
+ | ------ `x` is borrowed here
LL | drop(x);
| ^ use of borrowed `x`
LL | *p = 2;
@@ -12,7 +12,7 @@ error[E0503]: cannot use `x` because it was mutably borrowed
--> $DIR/borrowck-use-mut-borrow.rs:18:10
|
LL | let p = &mut x.a;
- | -------- borrow of `x.a` occurs here
+ | -------- `x.a` is borrowed here
LL | drop(x);
| ^ use of borrowed `x.a`
LL | *p = 3;
@@ -22,7 +22,7 @@ error[E0503]: cannot use `x.a` because it was mutably borrowed
--> $DIR/borrowck-use-mut-borrow.rs:25:10
|
LL | let p = &mut x;
- | ------ borrow of `x` occurs here
+ | ------ `x` is borrowed here
LL | drop(x.a);
| ^^^ use of borrowed `x`
LL | p.a = 3;
@@ -32,7 +32,7 @@ error[E0503]: cannot use `x.a` because it was mutably borrowed
--> $DIR/borrowck-use-mut-borrow.rs:32:10
|
LL | let p = &mut x.a;
- | -------- borrow of `x.a` occurs here
+ | -------- `x.a` is borrowed here
LL | drop(x.a);
| ^^^ use of borrowed `x.a`
LL | *p = 3;
@@ -42,7 +42,7 @@ error[E0503]: cannot use `x.a` because it was mutably borrowed
--> $DIR/borrowck-use-mut-borrow.rs:39:13
|
LL | let p = &mut x;
- | ------ borrow of `x` occurs here
+ | ------ `x` is borrowed here
LL | let y = A { b: 3, .. x };
| ^^^^^^^^^^^^^^^^ use of borrowed `x`
LL | drop(y);
@@ -53,7 +53,7 @@ error[E0503]: cannot use `x.a` because it was mutably borrowed
--> $DIR/borrowck-use-mut-borrow.rs:47:13
|
LL | let p = &mut x.a;
- | -------- borrow of `x.a` occurs here
+ | -------- `x.a` is borrowed here
LL | let y = A { b: 3, .. x };
| ^^^^^^^^^^^^^^^^ use of borrowed `x.a`
LL | drop(y);
@@ -64,7 +64,7 @@ error[E0503]: cannot use `*x` because it was mutably borrowed
--> $DIR/borrowck-use-mut-borrow.rs:55:10
|
LL | let p = &mut x;
- | ------ borrow of `x` occurs here
+ | ------ `x` is borrowed here
LL | drop(*x);
| ^^ use of borrowed `x`
LL | **p = 2;
@@ -74,7 +74,7 @@ error[E0503]: cannot use `*x.b` because it was mutably borrowed
--> $DIR/borrowck-use-mut-borrow.rs:62:10
|
LL | let p = &mut x;
- | ------ borrow of `x` occurs here
+ | ------ `x` is borrowed here
LL | drop(*x.b);
| ^^^^ use of borrowed `x`
LL | p.a = 3;
@@ -84,7 +84,7 @@ error[E0503]: cannot use `*x.b` because it was mutably borrowed
--> $DIR/borrowck-use-mut-borrow.rs:69:10
|
LL | let p = &mut x.b;
- | -------- borrow of `x.b` occurs here
+ | -------- `x.b` is borrowed here
LL | drop(*x.b);
| ^^^^ use of borrowed `x.b`
LL | **p = 3;
diff --git a/tests/ui/borrowck/borrowck-vec-pattern-move-tail.stderr b/tests/ui/borrowck/borrowck-vec-pattern-move-tail.stderr
index 0ac7df944..494d8c351 100644
--- a/tests/ui/borrowck/borrowck-vec-pattern-move-tail.stderr
+++ b/tests/ui/borrowck/borrowck-vec-pattern-move-tail.stderr
@@ -2,10 +2,10 @@ error[E0506]: cannot assign to `a[_]` because it is borrowed
--> $DIR/borrowck-vec-pattern-move-tail.rs:8:5
|
LL | [1, 2, ref tail @ ..] => tail,
- | -------- borrow of `a[_]` occurs here
+ | -------- `a[_]` is borrowed here
...
LL | a[2] = 0;
- | ^^^^^^^^ assignment to borrowed `a[_]` occurs here
+ | ^^^^^^^^ `a[_]` is assigned to here but it was already borrowed
LL | println!("t[0]: {}", t[0]);
| ---- borrow later used here
diff --git a/tests/ui/borrowck/borrowck-vec-pattern-nesting.rs b/tests/ui/borrowck/borrowck-vec-pattern-nesting.rs
index 0e9284a2c..1bda7a497 100644
--- a/tests/ui/borrowck/borrowck-vec-pattern-nesting.rs
+++ b/tests/ui/borrowck/borrowck-vec-pattern-nesting.rs
@@ -5,9 +5,9 @@ fn a() {
let mut vec = [Box::new(1), Box::new(2), Box::new(3)];
match vec {
[box ref _a, _, _] => {
- //~^ NOTE borrow of `vec[_]` occurs here
+ //~^ NOTE `vec[_]` is borrowed here
vec[0] = Box::new(4); //~ ERROR cannot assign
- //~^ NOTE assignment to borrowed `vec[_]` occurs here
+ //~^ NOTE `vec[_]` is assigned to here
_a.use_ref();
//~^ NOTE borrow later used here
}
@@ -19,9 +19,9 @@ fn b() {
let vec: &mut [Box<isize>] = &mut vec;
match vec {
&mut [ref _b @ ..] => {
- //~^ borrow of `vec[_]` occurs here
+ //~^ `vec[_]` is borrowed here
vec[0] = Box::new(4); //~ ERROR cannot assign
- //~^ NOTE assignment to borrowed `vec[_]` occurs here
+ //~^ NOTE `vec[_]` is assigned to here
_b.use_ref();
//~^ NOTE borrow later used here
}
diff --git a/tests/ui/borrowck/borrowck-vec-pattern-nesting.stderr b/tests/ui/borrowck/borrowck-vec-pattern-nesting.stderr
index 0dc5e64e4..70b9e4f44 100644
--- a/tests/ui/borrowck/borrowck-vec-pattern-nesting.stderr
+++ b/tests/ui/borrowck/borrowck-vec-pattern-nesting.stderr
@@ -2,10 +2,10 @@ error[E0506]: cannot assign to `vec[_]` because it is borrowed
--> $DIR/borrowck-vec-pattern-nesting.rs:9:13
|
LL | [box ref _a, _, _] => {
- | ------ borrow of `vec[_]` occurs here
+ | ------ `vec[_]` is borrowed here
LL |
LL | vec[0] = Box::new(4);
- | ^^^^^^ assignment to borrowed `vec[_]` occurs here
+ | ^^^^^^ `vec[_]` is assigned to here but it was already borrowed
LL |
LL | _a.use_ref();
| ------------ borrow later used here
@@ -14,10 +14,10 @@ error[E0506]: cannot assign to `vec[_]` because it is borrowed
--> $DIR/borrowck-vec-pattern-nesting.rs:23:13
|
LL | &mut [ref _b @ ..] => {
- | ------ borrow of `vec[_]` occurs here
+ | ------ `vec[_]` is borrowed here
LL |
LL | vec[0] = Box::new(4);
- | ^^^^^^ assignment to borrowed `vec[_]` occurs here
+ | ^^^^^^ `vec[_]` is assigned to here but it was already borrowed
LL |
LL | _b.use_ref();
| ------------ borrow later used here
diff --git a/tests/ui/borrowck/issue-103624.rs b/tests/ui/borrowck/issue-103624.rs
index f1fa95f92..d95a40bd4 100644
--- a/tests/ui/borrowck/issue-103624.rs
+++ b/tests/ui/borrowck/issue-103624.rs
@@ -12,7 +12,7 @@ impl StructA {
async fn foo(&self) {
let bar = self.b.bar().await;
spawn_blocking(move || {
- //~^ ERROR borrowed data escapes outside of associated function
+ //~^ ERROR borrowed data escapes outside of method
self.b;
//~^ ERROR cannot move out of `self.b`, as `self` is a captured variable in an `Fn` closure
})
diff --git a/tests/ui/borrowck/issue-103624.stderr b/tests/ui/borrowck/issue-103624.stderr
index e6a35dd88..7a281e8aa 100644
--- a/tests/ui/borrowck/issue-103624.stderr
+++ b/tests/ui/borrowck/issue-103624.stderr
@@ -10,13 +10,13 @@ LL |
LL | self.b;
| ^^^^^^ move occurs because `self.b` has type `StructB`, which does not implement the `Copy` trait
-error[E0521]: borrowed data escapes outside of associated function
+error[E0521]: borrowed data escapes outside of method
--> $DIR/issue-103624.rs:14:9
|
LL | async fn foo(&self) {
| -----
| |
- | `self` is a reference that is only valid in the associated function body
+ | `self` is a reference that is only valid in the method body
| let's call the lifetime of this reference `'1`
LL | let bar = self.b.bar().await;
LL | / spawn_blocking(move || {
@@ -26,7 +26,7 @@ LL | |
LL | | })
| | ^
| | |
- | |__________`self` escapes the associated function body here
+ | |__________`self` escapes the method body here
| argument requires that `'1` must outlive `'static`
error: aborting due to 2 previous errors
diff --git a/tests/ui/borrowck/issue-25793.stderr b/tests/ui/borrowck/issue-25793.stderr
index da3412f11..27dab53e4 100644
--- a/tests/ui/borrowck/issue-25793.stderr
+++ b/tests/ui/borrowck/issue-25793.stderr
@@ -5,7 +5,7 @@ LL | $this.width.unwrap()
| ^^^^^^^^^^^ use of borrowed `*self`
...
LL | let r = &mut *self;
- | ---------- borrow of `*self` occurs here
+ | ---------- `*self` is borrowed here
LL | r.get_size(width!(self))
| -------- ------------ in this macro invocation
| |
diff --git a/tests/ui/borrowck/issue-52713-bug.stderr b/tests/ui/borrowck/issue-52713-bug.stderr
index 4abb6fb2c..3f7715645 100644
--- a/tests/ui/borrowck/issue-52713-bug.stderr
+++ b/tests/ui/borrowck/issue-52713-bug.stderr
@@ -2,10 +2,10 @@ error[E0506]: cannot assign to `x` because it is borrowed
--> $DIR/issue-52713-bug.rs:12:5
|
LL | let y = &x;
- | -- borrow of `x` occurs here
+ | -- `x` is borrowed here
...
LL | x += 1;
- | ^^^^^^ assignment to borrowed `x` occurs here
+ | ^^^^^^ `x` is assigned to here but it was already borrowed
LL | println!("{}", y);
| - borrow later used here
diff --git a/tests/ui/borrowck/issue-58776-borrowck-scans-children.stderr b/tests/ui/borrowck/issue-58776-borrowck-scans-children.stderr
index 57803247b..0870b4237 100644
--- a/tests/ui/borrowck/issue-58776-borrowck-scans-children.stderr
+++ b/tests/ui/borrowck/issue-58776-borrowck-scans-children.stderr
@@ -4,10 +4,10 @@ error[E0506]: cannot assign to `greeting` because it is borrowed
LL | let res = (|| (|| &greeting)())();
| -- -------- borrow occurs due to use in closure
| |
- | borrow of `greeting` occurs here
+ | `greeting` is borrowed here
LL |
LL | greeting = "DEALLOCATED".to_string();
- | ^^^^^^^^ assignment to borrowed `greeting` occurs here
+ | ^^^^^^^^ `greeting` is assigned to here but it was already borrowed
...
LL | println!("thread result: {:?}", res);
| --- borrow later used here
diff --git a/tests/ui/borrowck/issue-81365-1.stderr b/tests/ui/borrowck/issue-81365-1.stderr
index d79394834..0d803b042 100644
--- a/tests/ui/borrowck/issue-81365-1.stderr
+++ b/tests/ui/borrowck/issue-81365-1.stderr
@@ -2,9 +2,9 @@ error[E0506]: cannot assign to `self.container_field` because it is borrowed
--> $DIR/issue-81365-1.rs:21:9
|
LL | let first = &self.target_field;
- | ---- borrow of `self.container_field` occurs here
+ | ---- `self.container_field` is borrowed here
LL | self.container_field = true;
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ assignment to borrowed `self.container_field` occurs here
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ `self.container_field` is assigned to here but it was already borrowed
LL | first;
| ----- borrow later used here
|
diff --git a/tests/ui/borrowck/issue-81365-10.stderr b/tests/ui/borrowck/issue-81365-10.stderr
index 27123ef2b..d0986e9f9 100644
--- a/tests/ui/borrowck/issue-81365-10.stderr
+++ b/tests/ui/borrowck/issue-81365-10.stderr
@@ -2,9 +2,9 @@ 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
+ | ------------ `self.container_field` is borrowed here
LL | self.container_field = true;
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ assignment to borrowed `self.container_field` occurs here
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ `self.container_field` is assigned to here but it was already borrowed
LL | first;
| ----- borrow later used here
diff --git a/tests/ui/borrowck/issue-81365-11.stderr b/tests/ui/borrowck/issue-81365-11.stderr
index 0770c1366..5f7e86f11 100644
--- a/tests/ui/borrowck/issue-81365-11.stderr
+++ b/tests/ui/borrowck/issue-81365-11.stderr
@@ -2,9 +2,9 @@ error[E0506]: cannot assign to `self.container_field` because it is borrowed
--> $DIR/issue-81365-11.rs:27:9
|
LL | let first = &mut self.target_field;
- | ---- borrow of `self.container_field` occurs here
+ | ---- `self.container_field` is borrowed here
LL | self.container_field = true;
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ assignment to borrowed `self.container_field` occurs here
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ `self.container_field` is assigned to here but it was already borrowed
LL | first;
| ----- borrow later used here
diff --git a/tests/ui/borrowck/issue-81365-2.stderr b/tests/ui/borrowck/issue-81365-2.stderr
index 764eaaa7c..d9aeaf15f 100644
--- a/tests/ui/borrowck/issue-81365-2.stderr
+++ b/tests/ui/borrowck/issue-81365-2.stderr
@@ -2,9 +2,9 @@ error[E0506]: cannot assign to `self.container.container_field` because it is bo
--> $DIR/issue-81365-2.rs:25:9
|
LL | let first = &self.container.target_field;
- | -------------- borrow of `self.container.container_field` occurs here
+ | -------------- `self.container.container_field` is borrowed here
LL | self.container.container_field = true;
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ assignment to borrowed `self.container.container_field` occurs here
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `self.container.container_field` is assigned to here but it was already borrowed
LL | first;
| ----- borrow later used here
|
diff --git a/tests/ui/borrowck/issue-81365-3.stderr b/tests/ui/borrowck/issue-81365-3.stderr
index 9447174fd..0c0d1994b 100644
--- a/tests/ui/borrowck/issue-81365-3.stderr
+++ b/tests/ui/borrowck/issue-81365-3.stderr
@@ -2,9 +2,9 @@ error[E0506]: cannot assign to `self.container.container_field` because it is bo
--> $DIR/issue-81365-3.rs:32:9
|
LL | let first = &self.target_field;
- | ---- borrow of `self.container.container_field` occurs here
+ | ---- `self.container.container_field` is borrowed here
LL | self.container.container_field = true;
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ assignment to borrowed `self.container.container_field` occurs here
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `self.container.container_field` is assigned to here but it was already borrowed
LL | first;
| ----- borrow later used here
|
diff --git a/tests/ui/borrowck/issue-81365-4.stderr b/tests/ui/borrowck/issue-81365-4.stderr
index 0ab3fa927..98093daa9 100644
--- a/tests/ui/borrowck/issue-81365-4.stderr
+++ b/tests/ui/borrowck/issue-81365-4.stderr
@@ -2,9 +2,9 @@ error[E0506]: cannot assign to `self.outer_field` because it is borrowed
--> $DIR/issue-81365-4.rs:33:9
|
LL | let first = &self.target_field;
- | ---- borrow of `self.outer_field` occurs here
+ | ---- `self.outer_field` is borrowed here
LL | self.outer_field = true;
- | ^^^^^^^^^^^^^^^^^^^^^^^ assignment to borrowed `self.outer_field` occurs here
+ | ^^^^^^^^^^^^^^^^^^^^^^^ `self.outer_field` is assigned to here but it was already borrowed
LL | first;
| ----- borrow later used here
|
diff --git a/tests/ui/borrowck/issue-81365-5.stderr b/tests/ui/borrowck/issue-81365-5.stderr
index 20ff229ff..c00e48288 100644
--- a/tests/ui/borrowck/issue-81365-5.stderr
+++ b/tests/ui/borrowck/issue-81365-5.stderr
@@ -2,9 +2,9 @@ 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
+ | ---------- `self.container_field` is borrowed here
LL | self.container_field = true;
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ assignment to borrowed `self.container_field` occurs here
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ `self.container_field` is assigned to here but it was already borrowed
LL | first;
| ----- borrow later used here
|
diff --git a/tests/ui/borrowck/issue-81365-6.stderr b/tests/ui/borrowck/issue-81365-6.stderr
index 575aed73b..e61dc95ec 100644
--- a/tests/ui/borrowck/issue-81365-6.stderr
+++ b/tests/ui/borrowck/issue-81365-6.stderr
@@ -2,9 +2,9 @@ error[E0506]: cannot assign to `self.container_field` because it is borrowed
--> $DIR/issue-81365-6.rs:18:9
|
LL | let first = &self[0];
- | ---- borrow of `self.container_field` occurs here
+ | ---- `self.container_field` is borrowed here
LL | self.container_field = true;
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ assignment to borrowed `self.container_field` occurs here
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ `self.container_field` is assigned to here but it was already borrowed
LL | first;
| ----- borrow later used here
|
diff --git a/tests/ui/borrowck/issue-81365-7.stderr b/tests/ui/borrowck/issue-81365-7.stderr
index 52d2d9e75..0565127e3 100644
--- a/tests/ui/borrowck/issue-81365-7.stderr
+++ b/tests/ui/borrowck/issue-81365-7.stderr
@@ -2,9 +2,9 @@ error[E0506]: cannot assign to `c.container_field` because it is borrowed
--> $DIR/issue-81365-7.rs:20:5
|
LL | let first = &c.target_field;
- | - borrow of `c.container_field` occurs here
+ | - `c.container_field` is borrowed here
LL | c.container_field = true;
- | ^^^^^^^^^^^^^^^^^^^^^^^^ assignment to borrowed `c.container_field` occurs here
+ | ^^^^^^^^^^^^^^^^^^^^^^^^ `c.container_field` is assigned to here but it was already borrowed
LL | first;
| ----- borrow later used here
|
diff --git a/tests/ui/borrowck/issue-81365-8.stderr b/tests/ui/borrowck/issue-81365-8.stderr
index fd83e10a2..0ca732ff2 100644
--- a/tests/ui/borrowck/issue-81365-8.stderr
+++ b/tests/ui/borrowck/issue-81365-8.stderr
@@ -2,9 +2,9 @@ error[E0506]: cannot assign to `self.container_field` because it is borrowed
--> $DIR/issue-81365-8.rs:21:9
|
LL | let first = &(*self).target_field;
- | ------- borrow of `self.container_field` occurs here
+ | ------- `self.container_field` is borrowed here
LL | self.container_field = true;
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ assignment to borrowed `self.container_field` occurs here
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ `self.container_field` is assigned to here but it was already borrowed
LL | first;
| ----- borrow later used here
|
diff --git a/tests/ui/borrowck/issue-81365-9.stderr b/tests/ui/borrowck/issue-81365-9.stderr
index c7d48214f..4d305268a 100644
--- a/tests/ui/borrowck/issue-81365-9.stderr
+++ b/tests/ui/borrowck/issue-81365-9.stderr
@@ -2,9 +2,9 @@ error[E0506]: cannot assign to `self.container_field` because it is borrowed
--> $DIR/issue-81365-9.rs:21:9
|
LL | let first = &Deref::deref(self).target_field;
- | ---- borrow of `self.container_field` occurs here
+ | ---- `self.container_field` is borrowed here
LL | self.container_field = true;
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ assignment to borrowed `self.container_field` occurs here
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ `self.container_field` is assigned to here but it was already borrowed
LL | first;
| ----- borrow later used here
diff --git a/tests/ui/borrowck/issue-82126-mismatched-subst-and-hir.rs b/tests/ui/borrowck/issue-82126-mismatched-subst-and-hir.rs
index dd0320bc5..d067ff447 100644
--- a/tests/ui/borrowck/issue-82126-mismatched-subst-and-hir.rs
+++ b/tests/ui/borrowck/issue-82126-mismatched-subst-and-hir.rs
@@ -14,8 +14,8 @@ impl MarketMultiplier {
}
async fn buy_lock(generator: &Mutex<MarketMultiplier>) -> 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
+ //~^ ERROR struct takes 0 lifetime arguments but 1 lifetime argument was supplied
+ //~^^ ERROR struct takes 1 generic argument but 0 generic arguments were supplied
LockedMarket(generator.lock().unwrap().buy())
}
diff --git a/tests/ui/borrowck/issue-82126-mismatched-subst-and-hir.stderr b/tests/ui/borrowck/issue-82126-mismatched-subst-and-hir.stderr
index d2b927fb6..73e0aaf1e 100644
--- a/tests/ui/borrowck/issue-82126-mismatched-subst-and-hir.stderr
+++ b/tests/ui/borrowck/issue-82126-mismatched-subst-and-hir.stderr
@@ -1,4 +1,4 @@
-error[E0107]: this struct takes 0 lifetime arguments but 1 lifetime argument was supplied
+error[E0107]: struct takes 0 lifetime arguments but 1 lifetime argument was supplied
--> $DIR/issue-82126-mismatched-subst-and-hir.rs:16:59
|
LL | async fn buy_lock(generator: &Mutex<MarketMultiplier>) -> LockedMarket<'_> {
@@ -12,7 +12,7 @@ note: struct defined here, with 0 lifetime parameters
LL | struct LockedMarket<T>(T);
| ^^^^^^^^^^^^
-error[E0107]: this struct takes 1 generic argument but 0 generic arguments were supplied
+error[E0107]: struct takes 1 generic argument but 0 generic arguments were supplied
--> $DIR/issue-82126-mismatched-subst-and-hir.rs:16:59
|
LL | async fn buy_lock(generator: &Mutex<MarketMultiplier>) -> LockedMarket<'_> {
diff --git a/tests/ui/issues/issue-83924.fixed b/tests/ui/borrowck/issue-83924.fixed
index aa40da12b..aa40da12b 100644
--- a/tests/ui/issues/issue-83924.fixed
+++ b/tests/ui/borrowck/issue-83924.fixed
diff --git a/tests/ui/issues/issue-83924.rs b/tests/ui/borrowck/issue-83924.rs
index 22b80fe2f..22b80fe2f 100644
--- a/tests/ui/issues/issue-83924.rs
+++ b/tests/ui/borrowck/issue-83924.rs
diff --git a/tests/ui/issues/issue-83924.stderr b/tests/ui/borrowck/issue-83924.stderr
index 572414df2..572414df2 100644
--- a/tests/ui/issues/issue-83924.stderr
+++ b/tests/ui/borrowck/issue-83924.stderr
diff --git a/tests/ui/borrowck/issue-85765.rs b/tests/ui/borrowck/issue-85765.rs
index 1598cd5d3..76e0b5173 100644
--- a/tests/ui/borrowck/issue-85765.rs
+++ b/tests/ui/borrowck/issue-85765.rs
@@ -1,7 +1,7 @@
fn main() {
let mut test = Vec::new();
let rofl: &Vec<Vec<i32>> = &mut test;
- //~^ NOTE consider changing this binding's type to be
+ //~^ HELP consider changing this binding's type
rofl.push(Vec::new());
//~^ ERROR cannot borrow `*rofl` as mutable, as it is behind a `&` reference
//~| NOTE `rofl` is a `&` reference, so the data it refers to cannot be borrowed as mutable
@@ -15,14 +15,14 @@ fn main() {
#[rustfmt::skip]
let x: &usize = &mut{0};
- //~^ NOTE consider changing this binding's type to be
+ //~^ HELP consider changing this binding's type
*x = 1;
//~^ ERROR cannot assign to `*x`, which is behind a `&` reference
//~| NOTE `x` is a `&` reference, so the data it refers to cannot be written
#[rustfmt::skip]
let y: &usize = &mut(0);
- //~^ NOTE consider changing this binding's type to be
+ //~^ HELP consider changing this binding's type
*y = 1;
//~^ ERROR cannot assign to `*y`, which is behind a `&` reference
//~| NOTE `y` is a `&` reference, so the data it refers to cannot be written
diff --git a/tests/ui/borrowck/issue-85765.stderr b/tests/ui/borrowck/issue-85765.stderr
index 7da7dba68..b4bb128cb 100644
--- a/tests/ui/borrowck/issue-85765.stderr
+++ b/tests/ui/borrowck/issue-85765.stderr
@@ -1,11 +1,13 @@
error[E0596]: cannot borrow `*rofl` as mutable, as it is behind a `&` reference
--> $DIR/issue-85765.rs:5:5
|
-LL | let rofl: &Vec<Vec<i32>> = &mut test;
- | ---- consider changing this binding's type to be: `&mut Vec<Vec<i32>>`
-LL |
LL | rofl.push(Vec::new());
| ^^^^^^^^^^^^^^^^^^^^^ `rofl` is a `&` reference, so the data it refers to cannot be borrowed as mutable
+ |
+help: consider changing this binding's type
+ |
+LL | let rofl: &mut Vec<Vec<i32>> = &mut test;
+ | ~~~~~~~~~~~~~~~~~~
error[E0594]: cannot assign to `*r`, which is behind a `&` reference
--> $DIR/issue-85765.rs:12:5
@@ -21,20 +23,24 @@ LL | let r = &mut mutvar;
error[E0594]: cannot assign to `*x`, which is behind a `&` reference
--> $DIR/issue-85765.rs:19:5
|
-LL | let x: &usize = &mut{0};
- | - consider changing this binding's type to be: `&mut usize`
-LL |
LL | *x = 1;
| ^^^^^^ `x` is a `&` reference, so the data it refers to cannot be written
+ |
+help: consider changing this binding's type
+ |
+LL | let x: &mut usize = &mut{0};
+ | ~~~~~~~~~~
error[E0594]: cannot assign to `*y`, which is behind a `&` reference
--> $DIR/issue-85765.rs:26:5
|
-LL | let y: &usize = &mut(0);
- | - consider changing this binding's type to be: `&mut usize`
-LL |
LL | *y = 1;
| ^^^^^^ `y` is a `&` reference, so the data it refers to cannot be written
+ |
+help: consider changing this binding's type
+ |
+LL | let y: &mut usize = &mut(0);
+ | ~~~~~~~~~~
error: aborting due to 4 previous errors
diff --git a/tests/ui/borrowck/issue-91206.rs b/tests/ui/borrowck/issue-91206.rs
index 67407c1ea..e062a2537 100644
--- a/tests/ui/borrowck/issue-91206.rs
+++ b/tests/ui/borrowck/issue-91206.rs
@@ -9,7 +9,7 @@ impl TestClient {
fn main() {
let client = TestClient;
let inner = client.get_inner_ref();
- //~^ NOTE consider changing this binding's type to be
+ //~^ HELP consider specifying this binding's type
inner.clear();
//~^ ERROR cannot borrow `*inner` as mutable, as it is behind a `&` reference [E0596]
//~| NOTE `inner` is a `&` reference, so the data it refers to cannot be borrowed as mutable
diff --git a/tests/ui/borrowck/issue-91206.stderr b/tests/ui/borrowck/issue-91206.stderr
index 12d8d27c5..6653d4978 100644
--- a/tests/ui/borrowck/issue-91206.stderr
+++ b/tests/ui/borrowck/issue-91206.stderr
@@ -1,11 +1,13 @@
error[E0596]: cannot borrow `*inner` as mutable, as it is behind a `&` reference
--> $DIR/issue-91206.rs:13:5
|
-LL | let inner = client.get_inner_ref();
- | ----- consider changing this binding's type to be: `&mut Vec<usize>`
-LL |
LL | inner.clear();
| ^^^^^^^^^^^^^ `inner` is a `&` reference, so the data it refers to cannot be borrowed as mutable
+ |
+help: consider specifying this binding's type
+ |
+LL | let inner: &mut Vec<usize> = client.get_inner_ref();
+ | +++++++++++++++++
error: aborting due to previous error
diff --git a/tests/ui/borrowck/issue-92015.stderr b/tests/ui/borrowck/issue-92015.stderr
index 62b1183e7..ea4f9abb8 100644
--- a/tests/ui/borrowck/issue-92015.stderr
+++ b/tests/ui/borrowck/issue-92015.stderr
@@ -1,10 +1,13 @@
error[E0594]: cannot assign to `*foo`, which is behind a `&` reference
--> $DIR/issue-92015.rs:6:5
|
-LL | let foo = Some(&0).unwrap();
- | --- consider changing this binding's type to be: `&mut i32`
LL | *foo = 1;
| ^^^^^^^^ `foo` is a `&` reference, so the data it refers to cannot be written
+ |
+help: consider specifying this binding's type
+ |
+LL | let foo: &mut i32 = Some(&0).unwrap();
+ | ++++++++++
error: aborting due to previous error
diff --git a/tests/ui/borrowck/issue-95079-missing-move-in-nested-closure.fixed b/tests/ui/borrowck/issue-95079-missing-move-in-nested-closure.fixed
new file mode 100644
index 000000000..1a0847006
--- /dev/null
+++ b/tests/ui/borrowck/issue-95079-missing-move-in-nested-closure.fixed
@@ -0,0 +1,26 @@
+// run-rustfix
+#![allow(dead_code, path_statements)]
+fn foo1(s: &str) -> impl Iterator<Item = String> + '_ {
+ None.into_iter()
+ .flat_map(move |()| s.chars().map(move |c| format!("{}{}", c, s)))
+ //~^ ERROR captured variable cannot escape `FnMut` closure body
+ //~| HELP consider adding 'move' keyword before the nested closure
+}
+
+fn foo2(s: &str) -> impl Sized + '_ {
+ move |()| s.chars().map(move |c| format!("{}{}", c, s))
+ //~^ ERROR lifetime may not live long enough
+ //~| HELP consider adding 'move' keyword before the nested closure
+}
+
+pub struct X;
+pub fn foo3<'a>(
+ bar: &'a X,
+) -> impl Iterator<Item = ()> + 'a {
+ Some(()).iter().flat_map(move |()| {
+ Some(()).iter().map(move |()| { bar; }) //~ ERROR captured variable cannot escape
+ //~^ HELP consider adding 'move' keyword before the nested closure
+ })
+}
+
+fn main() {}
diff --git a/tests/ui/borrowck/issue-95079-missing-move-in-nested-closure.rs b/tests/ui/borrowck/issue-95079-missing-move-in-nested-closure.rs
index 95847d8d3..b93292e35 100644
--- a/tests/ui/borrowck/issue-95079-missing-move-in-nested-closure.rs
+++ b/tests/ui/borrowck/issue-95079-missing-move-in-nested-closure.rs
@@ -1,3 +1,5 @@
+// run-rustfix
+#![allow(dead_code, path_statements)]
fn foo1(s: &str) -> impl Iterator<Item = String> + '_ {
None.into_iter()
.flat_map(move |()| s.chars().map(|c| format!("{}{}", c, s)))
@@ -11,4 +13,14 @@ fn foo2(s: &str) -> impl Sized + '_ {
//~| HELP consider adding 'move' keyword before the nested closure
}
+pub struct X;
+pub fn foo3<'a>(
+ bar: &'a X,
+) -> impl Iterator<Item = ()> + 'a {
+ Some(()).iter().flat_map(move |()| {
+ Some(()).iter().map(|()| { bar; }) //~ ERROR captured variable cannot escape
+ //~^ HELP consider adding 'move' keyword before the nested closure
+ })
+}
+
fn main() {}
diff --git a/tests/ui/borrowck/issue-95079-missing-move-in-nested-closure.stderr b/tests/ui/borrowck/issue-95079-missing-move-in-nested-closure.stderr
index 2eae614a2..776c338de 100644
--- a/tests/ui/borrowck/issue-95079-missing-move-in-nested-closure.stderr
+++ b/tests/ui/borrowck/issue-95079-missing-move-in-nested-closure.stderr
@@ -1,5 +1,5 @@
error: captured variable cannot escape `FnMut` closure body
- --> $DIR/issue-95079-missing-move-in-nested-closure.rs:3:29
+ --> $DIR/issue-95079-missing-move-in-nested-closure.rs:5:29
|
LL | fn foo1(s: &str) -> impl Iterator<Item = String> + '_ {
| - variable defined here
@@ -7,7 +7,7 @@ LL | None.into_iter()
LL | .flat_map(move |()| s.chars().map(|c| format!("{}{}", c, s)))
| - -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| | |
- | | returns a reference to a captured variable which escapes the closure body
+ | | returns a closure that contains a reference to a captured variable, which then escapes the closure body
| | variable captured here
| inferred to be a `FnMut` closure
|
@@ -19,12 +19,12 @@ LL | .flat_map(move |()| s.chars().map(move |c| format!("{}{}", c, s)))
| ++++
error: lifetime may not live long enough
- --> $DIR/issue-95079-missing-move-in-nested-closure.rs:9:15
+ --> $DIR/issue-95079-missing-move-in-nested-closure.rs:11:15
|
LL | move |()| s.chars().map(|c| format!("{}{}", c, s))
| --------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ returning this value requires that `'1` must outlive `'2`
| | |
- | | return type of closure `Map<Chars<'_>, [closure@$DIR/issue-95079-missing-move-in-nested-closure.rs:9:29: 9:32]>` contains a lifetime `'2`
+ | | return type of closure `Map<Chars<'_>, [closure@$DIR/issue-95079-missing-move-in-nested-closure.rs:11:29: 11:32]>` contains a lifetime `'2`
| lifetime `'1` represents this closure's body
|
= note: closure implements `Fn`, so references to captured variables can't escape the closure
@@ -33,5 +33,26 @@ help: consider adding 'move' keyword before the nested closure
LL | move |()| s.chars().map(move |c| format!("{}{}", c, s))
| ++++
-error: aborting due to 2 previous errors
+error: captured variable cannot escape `FnMut` closure body
+ --> $DIR/issue-95079-missing-move-in-nested-closure.rs:21:9
+ |
+LL | bar: &'a X,
+ | --- variable defined here
+LL | ) -> impl Iterator<Item = ()> + 'a {
+LL | Some(()).iter().flat_map(move |()| {
+ | - inferred to be a `FnMut` closure
+LL | Some(()).iter().map(|()| { bar; })
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^---^^^^
+ | | |
+ | | variable captured here
+ | returns a closure that contains a reference to a captured variable, which then escapes the closure body
+ |
+ = note: `FnMut` closures only have access to their captured variables while they are executing...
+ = note: ...therefore, they cannot allow references to captured variables to escape
+help: consider adding 'move' keyword before the nested closure
+ |
+LL | Some(()).iter().map(move |()| { bar; })
+ | ++++
+
+error: aborting due to 3 previous errors
diff --git a/tests/ui/borrowck/two-phase-allow-access-during-reservation.nll_target.stderr b/tests/ui/borrowck/two-phase-allow-access-during-reservation.nll_target.stderr
index a57ceb847..1356c8049 100644
--- a/tests/ui/borrowck/two-phase-allow-access-during-reservation.nll_target.stderr
+++ b/tests/ui/borrowck/two-phase-allow-access-during-reservation.nll_target.stderr
@@ -2,7 +2,7 @@ error[E0503]: cannot use `i` because it was mutably borrowed
--> $DIR/two-phase-allow-access-during-reservation.rs:26:19
|
LL | /*1*/ let p = &mut i; // (reservation of `i` starts here)
- | ------ borrow of `i` occurs here
+ | ------ `i` is borrowed here
LL |
LL | /*2*/ let j = i; // OK: `i` is only reserved here
| ^ use of borrowed `i`
@@ -14,7 +14,7 @@ error[E0503]: cannot use `i` because it was mutably borrowed
--> $DIR/two-phase-allow-access-during-reservation.rs:31:19
|
LL | /*1*/ let p = &mut i; // (reservation of `i` starts here)
- | ------ borrow of `i` occurs here
+ | ------ `i` is borrowed here
...
LL | /*4*/ let k = i;
| ^ use of borrowed `i`
diff --git a/tests/ui/borrowck/two-phase-surprise-no-conflict.stderr b/tests/ui/borrowck/two-phase-surprise-no-conflict.stderr
index 5a240d900..e75094d4f 100644
--- a/tests/ui/borrowck/two-phase-surprise-no-conflict.stderr
+++ b/tests/ui/borrowck/two-phase-surprise-no-conflict.stderr
@@ -2,7 +2,7 @@ error[E0503]: cannot use `self.cx` because it was mutably borrowed
--> $DIR/two-phase-surprise-no-conflict.rs:21:23
|
LL | let _mut_borrow = &mut *self;
- | ---------- borrow of `*self` occurs here
+ | ---------- `*self` is borrowed here
LL | let _access = self.cx;
| ^^^^^^^ use of borrowed `*self`
LL |
diff --git a/tests/ui/bounds-lifetime.stderr b/tests/ui/bounds-lifetime.stderr
index a0395ed49..f0bfe784c 100644
--- a/tests/ui/bounds-lifetime.stderr
+++ b/tests/ui/bounds-lifetime.stderr
@@ -16,17 +16,24 @@ error: lifetime bounds cannot be used in this context
LL | type C = for<'b, 'a: 'b +> fn();
| ^^
-error: only lifetime parameters can be used in this context
+error[E0658]: only lifetime parameters can be used in this context
--> $DIR/bounds-lifetime.rs:4:18
|
LL | type D = for<'a, T> fn();
| ^
+ |
+ = note: see issue #108185 <https://github.com/rust-lang/rust/issues/108185> for more information
+ = help: add `#![feature(non_lifetime_binders)]` to the crate attributes to enable
-error: only lifetime parameters can be used in this context
+error[E0658]: only lifetime parameters can be used in this context
--> $DIR/bounds-lifetime.rs:5:18
|
LL | type E = dyn for<T> Fn();
| ^
+ |
+ = note: see issue #108185 <https://github.com/rust-lang/rust/issues/108185> for more information
+ = help: add `#![feature(non_lifetime_binders)]` to the crate attributes to enable
error: aborting due to 5 previous errors
+For more information about this error, try `rustc --explain E0658`.
diff --git a/tests/ui/box/issue-82446.stderr b/tests/ui/box/issue-82446.stderr
index 037473795..c03f35884 100644
--- a/tests/ui/box/issue-82446.stderr
+++ b/tests/ui/box/issue-82446.stderr
@@ -2,7 +2,7 @@ error[E0308]: mismatched types
--> $DIR/issue-82446.rs:11:9
|
LL | val
- | ^^^ expected struct `Box`, found reference
+ | ^^^ expected `Box<dyn MyTrait>`, found `&Box<dyn MyTrait>`
|
= note: expected struct `Box<(dyn MyTrait + 'static)>`
found reference `&Box<(dyn MyTrait + 'static)>`
diff --git a/tests/ui/box/leak-alloc.stderr b/tests/ui/box/leak-alloc.stderr
index e8a6ad099..5140b5893 100644
--- a/tests/ui/box/leak-alloc.stderr
+++ b/tests/ui/box/leak-alloc.stderr
@@ -1,6 +1,8 @@
error[E0505]: cannot move out of `alloc` because it is borrowed
--> $DIR/leak-alloc.rs:26:10
|
+LL | let alloc = Alloc {};
+ | ----- binding `alloc` declared here
LL | let boxed = Box::new_in(10, alloc.by_ref());
| -------------- borrow of `alloc` occurs here
LL | let theref = Box::leak(boxed);
diff --git a/tests/ui/btreemap/btreemap_dropck.stderr b/tests/ui/btreemap/btreemap_dropck.stderr
index e953e7ae8..d405e465a 100644
--- a/tests/ui/btreemap/btreemap_dropck.stderr
+++ b/tests/ui/btreemap/btreemap_dropck.stderr
@@ -1,6 +1,8 @@
error[E0505]: cannot move out of `s` because it is borrowed
--> $DIR/btreemap_dropck.rs:15:10
|
+LL | let s = String::from("Hello World!");
+ | - binding `s` declared here
LL | let _map = BTreeMap::from_iter([((), PrintOnDrop(&s))]);
| -- borrow of `s` occurs here
LL | drop(s);
diff --git a/tests/ui/c-variadic/variadic-ffi-1.stderr b/tests/ui/c-variadic/variadic-ffi-1.stderr
index 4beea83d8..c78993381 100644
--- a/tests/ui/c-variadic/variadic-ffi-1.stderr
+++ b/tests/ui/c-variadic/variadic-ffi-1.stderr
@@ -46,6 +46,7 @@ LL | let x: unsafe extern "C" fn(f: isize, x: u8) = foo;
|
= note: expected fn pointer `unsafe extern "C" fn(_, _)`
found fn item `unsafe extern "C" fn(_, _, ...) {foo}`
+ = note: when the arguments and return types match, functions can be coerced to function pointers
error[E0308]: mismatched types
--> $DIR/variadic-ffi-1.rs:26:54
@@ -57,6 +58,7 @@ LL | let y: extern "C" fn(f: isize, x: u8, ...) = bar;
|
= note: expected fn pointer `extern "C" fn(_, _, ...)`
found fn item `extern "C" fn(_, _) {bar}`
+ = note: when the arguments and return types match, functions can be coerced to function pointers
error[E0617]: can't pass `f32` to variadic function
--> $DIR/variadic-ffi-1.rs:28:19
diff --git a/tests/ui/c-variadic/variadic-ffi-4.stderr b/tests/ui/c-variadic/variadic-ffi-4.stderr
index 6f8e53298..c9d90d73d 100644
--- a/tests/ui/c-variadic/variadic-ffi-4.stderr
+++ b/tests/ui/c-variadic/variadic-ffi-4.stderr
@@ -107,7 +107,9 @@ error[E0597]: `ap1` does not live long enough
--> $DIR/variadic-ffi-4.rs:28:11
|
LL | pub unsafe extern "C" fn no_escape4(_: usize, mut ap0: &mut VaListImpl, mut ap1: ...) {
- | - let's call the lifetime of this reference `'3`
+ | - ------- binding `ap1` declared here
+ | |
+ | let's call the lifetime of this reference `'3`
LL | ap0 = &mut ap1;
| ------^^^^^^^^
| | |
diff --git a/tests/ui/check-cfg/invalid-cfg-value.stderr b/tests/ui/check-cfg/invalid-cfg-value.stderr
index 60abcb188..83383ea61 100644
--- a/tests/ui/check-cfg/invalid-cfg-value.stderr
+++ b/tests/ui/check-cfg/invalid-cfg-value.stderr
@@ -2,7 +2,9 @@ warning: unexpected `cfg` condition value
--> $DIR/invalid-cfg-value.rs:7:7
|
LL | #[cfg(feature = "sedre")]
- | ^^^^^^^^^^^^^^^^^
+ | ^^^^^^^^^^-------
+ | |
+ | help: did you mean: `"serde"`
|
= note: expected values for `feature` are: full, serde
= note: `#[warn(unexpected_cfgs)]` on by default
diff --git a/tests/ui/closure-expected-type/expect-infer-var-appearing-twice.stderr b/tests/ui/closure-expected-type/expect-infer-var-appearing-twice.stderr
index 8dccf929b..c50892950 100644
--- a/tests/ui/closure-expected-type/expect-infer-var-appearing-twice.stderr
+++ b/tests/ui/closure-expected-type/expect-infer-var-appearing-twice.stderr
@@ -12,7 +12,7 @@ note: required by a bound in `with_closure`
--> $DIR/expect-infer-var-appearing-twice.rs:2:14
|
LL | fn with_closure<F, A>(_: F)
- | ------------ required by a bound in this
+ | ------------ required by a bound in this function
LL | where F: FnOnce(A, A)
| ^^^^^^^^^^^^ required by this bound in `with_closure`
diff --git a/tests/ui/closures/2229_closure_analysis/diagnostics/arrays.stderr b/tests/ui/closures/2229_closure_analysis/diagnostics/arrays.stderr
index 4f41060dc..9e5200ef3 100644
--- a/tests/ui/closures/2229_closure_analysis/diagnostics/arrays.stderr
+++ b/tests/ui/closures/2229_closure_analysis/diagnostics/arrays.stderr
@@ -2,7 +2,7 @@ error[E0503]: cannot use `arr` because it was mutably borrowed
--> $DIR/arrays.rs:14:5
|
LL | let mut c = || {
- | -- borrow of `arr` occurs here
+ | -- `arr` is borrowed here
LL | arr[0] += 10;
| --- borrow occurs due to use of `arr` in closure
...
@@ -16,7 +16,7 @@ error[E0503]: cannot use `arr[_]` because it was mutably borrowed
--> $DIR/arrays.rs:14:5
|
LL | let mut c = || {
- | -- borrow of `arr` occurs here
+ | -- `arr` is borrowed here
LL | arr[0] += 10;
| --- borrow occurs due to use of `arr` in closure
...
@@ -30,12 +30,12 @@ error[E0506]: cannot assign to `arr[_]` because it is borrowed
--> $DIR/arrays.rs:29:5
|
LL | let c = || {
- | -- borrow of `arr[_]` occurs here
+ | -- `arr[_]` is borrowed here
LL | println!("{:#?}", &arr[3..4]);
| --- borrow occurs due to use in closure
...
LL | arr[1] += 10;
- | ^^^^^^^^^^^^ assignment to borrowed `arr[_]` occurs here
+ | ^^^^^^^^^^^^ `arr[_]` is assigned to here but it was already borrowed
LL |
LL | c();
| - borrow later used here
@@ -44,12 +44,12 @@ error[E0506]: cannot assign to `arr[_]` because it is borrowed
--> $DIR/arrays.rs:43:5
|
LL | let c = || {
- | -- borrow of `arr[_]` occurs here
+ | -- `arr[_]` is borrowed here
LL | println!("{}", arr[3]);
| --- borrow occurs due to use in closure
...
LL | arr[1] += 10;
- | ^^^^^^^^^^^^ assignment to borrowed `arr[_]` occurs here
+ | ^^^^^^^^^^^^ `arr[_]` is assigned to here but it was already borrowed
LL |
LL | c();
| - borrow later used here
@@ -58,7 +58,7 @@ error[E0503]: cannot use `arr` because it was mutably borrowed
--> $DIR/arrays.rs:57:20
|
LL | let mut c = || {
- | -- borrow of `arr` occurs here
+ | -- `arr` is borrowed here
LL | arr[1] += 10;
| --- borrow occurs due to use of `arr` in closure
...
diff --git a/tests/ui/closures/2229_closure_analysis/diagnostics/box.stderr b/tests/ui/closures/2229_closure_analysis/diagnostics/box.stderr
index f8b178752..2e3259e64 100644
--- a/tests/ui/closures/2229_closure_analysis/diagnostics/box.stderr
+++ b/tests/ui/closures/2229_closure_analysis/diagnostics/box.stderr
@@ -2,12 +2,12 @@ error[E0506]: cannot assign to `e.0.0.m.x` because it is borrowed
--> $DIR/box.rs:21:5
|
LL | let mut c = || {
- | -- borrow of `e.0.0.m.x` occurs here
+ | -- `e.0.0.m.x` is borrowed here
LL | e.0.0.m.x = format!("not-x");
| --------- borrow occurs due to use in closure
...
LL | e.0.0.m.x = format!("not-x");
- | ^^^^^^^^^ assignment to borrowed `e.0.0.m.x` occurs here
+ | ^^^^^^^^^ `e.0.0.m.x` is assigned to here but it was already borrowed
LL |
LL | c();
| - borrow later used here
@@ -32,12 +32,12 @@ error[E0506]: cannot assign to `e.0.0.m.x` because it is borrowed
--> $DIR/box.rs:55:5
|
LL | let c = || {
- | -- borrow of `e.0.0.m.x` occurs here
+ | -- `e.0.0.m.x` is borrowed here
LL | println!("{}", e.0.0.m.x);
| --------- borrow occurs due to use in closure
...
LL | e.0.0.m.x = format!("not-x");
- | ^^^^^^^^^ assignment to borrowed `e.0.0.m.x` occurs here
+ | ^^^^^^^^^ `e.0.0.m.x` is assigned to here but it was already borrowed
LL |
LL | c();
| - borrow later used here
diff --git a/tests/ui/closures/2229_closure_analysis/diagnostics/repr_packed.rs b/tests/ui/closures/2229_closure_analysis/diagnostics/repr_packed.rs
index 1488f3296..c7ee90ea7 100644
--- a/tests/ui/closures/2229_closure_analysis/diagnostics/repr_packed.rs
+++ b/tests/ui/closures/2229_closure_analysis/diagnostics/repr_packed.rs
@@ -20,7 +20,6 @@ fn test_missing_unsafe_warning_on_repr_packed() {
let c = || {
println!("{}", foo.x);
//~^ ERROR: reference to packed field is unaligned
- //~| WARNING: this was previously accepted by the compiler but is being phased out
let _z = foo.x;
};
diff --git a/tests/ui/closures/2229_closure_analysis/diagnostics/repr_packed.stderr b/tests/ui/closures/2229_closure_analysis/diagnostics/repr_packed.stderr
index 508c4b911..9c2c43457 100644
--- a/tests/ui/closures/2229_closure_analysis/diagnostics/repr_packed.stderr
+++ b/tests/ui/closures/2229_closure_analysis/diagnostics/repr_packed.stderr
@@ -1,29 +1,13 @@
-error: reference to packed field is unaligned
+error[E0793]: reference to packed field is unaligned
--> $DIR/repr_packed.rs:21:24
|
LL | println!("{}", foo.x);
| ^^^^^
|
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523>
= note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
= help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
- = note: `#[deny(unaligned_references)]` on by default
= note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to previous error
-Future incompatibility report: Future breakage diagnostic:
-error: reference to packed field is unaligned
- --> $DIR/repr_packed.rs:21:24
- |
-LL | println!("{}", foo.x);
- | ^^^^^
- |
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523>
- = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
- = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
- = note: `#[deny(unaligned_references)]` on by default
- = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info)
-
+For more information about this error, try `rustc --explain E0793`.
diff --git a/tests/ui/closures/2229_closure_analysis/diagnostics/union.rs b/tests/ui/closures/2229_closure_analysis/diagnostics/union.rs
index 46b54846e..695337ea8 100644
--- a/tests/ui/closures/2229_closure_analysis/diagnostics/union.rs
+++ b/tests/ui/closures/2229_closure_analysis/diagnostics/union.rs
@@ -11,7 +11,7 @@ union A {
fn main() {
let mut a = A { y: 1 };
let mut c = || {
- //~^ borrow of `a.y` occurs here
+ //~^ `a.y` is borrowed here
let _ = unsafe { &a.y };
let _ = &mut a;
//~^ borrow occurs due to use in closure
@@ -19,7 +19,7 @@ fn main() {
};
a.y = 1;
//~^ cannot assign to `a.y` because it is borrowed [E0506]
- //~| assignment to borrowed `a.y` occurs here
+ //~| `a.y` is assigned to here
c();
//~^ borrow later used here
}
diff --git a/tests/ui/closures/2229_closure_analysis/diagnostics/union.stderr b/tests/ui/closures/2229_closure_analysis/diagnostics/union.stderr
index 7c34e2336..17834e612 100644
--- a/tests/ui/closures/2229_closure_analysis/diagnostics/union.stderr
+++ b/tests/ui/closures/2229_closure_analysis/diagnostics/union.stderr
@@ -2,13 +2,13 @@ error[E0506]: cannot assign to `a.y` because it is borrowed
--> $DIR/union.rs:20:5
|
LL | let mut c = || {
- | -- borrow of `a.y` occurs here
+ | -- `a.y` is borrowed here
...
LL | let _ = &mut a;
| - borrow occurs due to use in closure
...
LL | a.y = 1;
- | ^^^^^^^ assignment to borrowed `a.y` occurs here
+ | ^^^^^^^ `a.y` is assigned to here but it was already borrowed
...
LL | c();
| - borrow later used here
diff --git a/tests/ui/closures/2229_closure_analysis/issue_88118.rs b/tests/ui/closures/2229_closure_analysis/issue_88118.rs
index 453b7e04a..bfb487649 100644
--- a/tests/ui/closures/2229_closure_analysis/issue_88118.rs
+++ b/tests/ui/closures/2229_closure_analysis/issue_88118.rs
@@ -1,10 +1,7 @@
// Regression test for #88118. Used to ICE.
-//
+// edition:2021
// check-pass
-#![allow(incomplete_features)]
-#![feature(capture_disjoint_fields)]
-
fn foo<MsU>(handler: impl FnOnce() -> MsU + Clone + 'static) {
Box::new(move |value| {
(|_| handler.clone()())(value);
diff --git a/tests/ui/closures/2229_closure_analysis/migrations/auto_traits.fixed b/tests/ui/closures/2229_closure_analysis/migrations/auto_traits.fixed
index 26703fbf8..b74b5e94e 100644
--- a/tests/ui/closures/2229_closure_analysis/migrations/auto_traits.fixed
+++ b/tests/ui/closures/2229_closure_analysis/migrations/auto_traits.fixed
@@ -26,7 +26,7 @@ fn test_send_trait() {
//~| HELP: add a dummy let to cause `fptr` to be fully captured
*fptr.0 = 20;
//~^ NOTE: in Rust 2018, this closure captures all of `fptr`, but in Rust 2021, it will only capture `fptr.0`
- } });
+ } }).join().unwrap();
}
/* Test Sync Trait Migration */
@@ -47,7 +47,7 @@ fn test_sync_trait() {
//~| HELP: add a dummy let to cause `fptr` to be fully captured
*fptr.0.0 = 20;
//~^ NOTE: in Rust 2018, this closure captures all of `fptr`, but in Rust 2021, it will only capture `fptr.0.0`
- } });
+ } }).join().unwrap();
}
/* Test Clone Trait Migration */
diff --git a/tests/ui/closures/2229_closure_analysis/migrations/auto_traits.rs b/tests/ui/closures/2229_closure_analysis/migrations/auto_traits.rs
index 932db51d4..e4965e33c 100644
--- a/tests/ui/closures/2229_closure_analysis/migrations/auto_traits.rs
+++ b/tests/ui/closures/2229_closure_analysis/migrations/auto_traits.rs
@@ -26,7 +26,7 @@ fn test_send_trait() {
//~| HELP: add a dummy let to cause `fptr` to be fully captured
*fptr.0 = 20;
//~^ NOTE: in Rust 2018, this closure captures all of `fptr`, but in Rust 2021, it will only capture `fptr.0`
- });
+ }).join().unwrap();
}
/* Test Sync Trait Migration */
@@ -47,7 +47,7 @@ fn test_sync_trait() {
//~| HELP: add a dummy let to cause `fptr` to be fully captured
*fptr.0.0 = 20;
//~^ NOTE: in Rust 2018, this closure captures all of `fptr`, but in Rust 2021, it will only capture `fptr.0.0`
- });
+ }).join().unwrap();
}
/* Test Clone Trait Migration */
diff --git a/tests/ui/closures/2229_closure_analysis/migrations/auto_traits.stderr b/tests/ui/closures/2229_closure_analysis/migrations/auto_traits.stderr
index 3a42cc8b8..856ec4a5b 100644
--- a/tests/ui/closures/2229_closure_analysis/migrations/auto_traits.stderr
+++ b/tests/ui/closures/2229_closure_analysis/migrations/auto_traits.stderr
@@ -19,7 +19,7 @@ LL ~ thread::spawn(move || { let _ = &fptr; unsafe {
LL |
...
LL |
-LL ~ } });
+LL ~ } }).join().unwrap();
|
error: changes to closure capture in Rust 2021 will affect which traits the closure implements
@@ -41,7 +41,7 @@ LL ~ thread::spawn(move || { let _ = &fptr; unsafe {
LL |
...
LL |
-LL ~ } });
+LL ~ } }).join().unwrap();
|
error: changes to closure capture in Rust 2021 will affect drop order and which traits the closure implements
diff --git a/tests/ui/closures/2229_closure_analysis/migrations/multi_diagnostics.fixed b/tests/ui/closures/2229_closure_analysis/migrations/multi_diagnostics.fixed
index 173dd2e2c..bde8c7497 100644
--- a/tests/ui/closures/2229_closure_analysis/migrations/multi_diagnostics.fixed
+++ b/tests/ui/closures/2229_closure_analysis/migrations/multi_diagnostics.fixed
@@ -145,7 +145,7 @@ fn test_multi_traits_issues() {
//~^ NOTE: in Rust 2018, this closure captures all of `fptr1`, but in Rust 2021, it will only capture `fptr1.0.0`
*fptr2.0 = 20;
//~^ NOTE: in Rust 2018, this closure captures all of `fptr2`, but in Rust 2021, it will only capture `fptr2.0`
- } });
+ } }).join().unwrap();
}
fn main() {
diff --git a/tests/ui/closures/2229_closure_analysis/migrations/multi_diagnostics.rs b/tests/ui/closures/2229_closure_analysis/migrations/multi_diagnostics.rs
index cfc4555ca..584c52ea1 100644
--- a/tests/ui/closures/2229_closure_analysis/migrations/multi_diagnostics.rs
+++ b/tests/ui/closures/2229_closure_analysis/migrations/multi_diagnostics.rs
@@ -141,7 +141,7 @@ fn test_multi_traits_issues() {
//~^ NOTE: in Rust 2018, this closure captures all of `fptr1`, but in Rust 2021, it will only capture `fptr1.0.0`
*fptr2.0 = 20;
//~^ NOTE: in Rust 2018, this closure captures all of `fptr2`, but in Rust 2021, it will only capture `fptr2.0`
- });
+ }).join().unwrap();
}
fn main() {
diff --git a/tests/ui/closures/2229_closure_analysis/migrations/multi_diagnostics.stderr b/tests/ui/closures/2229_closure_analysis/migrations/multi_diagnostics.stderr
index efb264447..344bc662e 100644
--- a/tests/ui/closures/2229_closure_analysis/migrations/multi_diagnostics.stderr
+++ b/tests/ui/closures/2229_closure_analysis/migrations/multi_diagnostics.stderr
@@ -111,7 +111,7 @@ LL ~ thread::spawn(move || { let _ = (&fptr1, &fptr2); unsafe {
LL |
...
LL |
-LL ~ } });
+LL ~ } }).join().unwrap();
|
error: aborting due to 5 previous errors
diff --git a/tests/ui/closures/binder/const-bound.rs b/tests/ui/closures/binder/const-bound.rs
new file mode 100644
index 000000000..b1c79db13
--- /dev/null
+++ b/tests/ui/closures/binder/const-bound.rs
@@ -0,0 +1,7 @@
+#![feature(closure_lifetime_binder, non_lifetime_binders)]
+//~^ WARN is incomplete and may not be safe to use
+
+fn main() {
+ for<const N: i32> || -> () {};
+ //~^ ERROR late-bound const parameter not allowed on closures
+}
diff --git a/tests/ui/closures/binder/const-bound.stderr b/tests/ui/closures/binder/const-bound.stderr
new file mode 100644
index 000000000..c016465c1
--- /dev/null
+++ b/tests/ui/closures/binder/const-bound.stderr
@@ -0,0 +1,17 @@
+warning: the feature `non_lifetime_binders` is incomplete and may not be safe to use and/or cause compiler crashes
+ --> $DIR/const-bound.rs:1:37
+ |
+LL | #![feature(closure_lifetime_binder, non_lifetime_binders)]
+ | ^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: see issue #108185 <https://github.com/rust-lang/rust/issues/108185> for more information
+ = note: `#[warn(incomplete_features)]` on by default
+
+error: late-bound const parameter not allowed on closures
+ --> $DIR/const-bound.rs:5:9
+ |
+LL | for<const N: i32> || -> () {};
+ | ^^^^^^^^^^^^
+
+error: aborting due to previous error; 1 warning emitted
+
diff --git a/tests/ui/closures/binder/disallow-const.stderr b/tests/ui/closures/binder/disallow-const.stderr
index 3c3b43d8c..59f299315 100644
--- a/tests/ui/closures/binder/disallow-const.stderr
+++ b/tests/ui/closures/binder/disallow-const.stderr
@@ -1,8 +1,12 @@
-error: only lifetime parameters can be used in this context
+error[E0658]: only lifetime parameters can be used in this context
--> $DIR/disallow-const.rs:4:15
|
LL | for<const N: i32> || -> () {};
| ^
+ |
+ = note: see issue #108185 <https://github.com/rust-lang/rust/issues/108185> for more information
+ = help: add `#![feature(non_lifetime_binders)]` 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/tests/ui/closures/binder/disallow-ty.stderr b/tests/ui/closures/binder/disallow-ty.stderr
index 51b6773ed..3370e21bd 100644
--- a/tests/ui/closures/binder/disallow-ty.stderr
+++ b/tests/ui/closures/binder/disallow-ty.stderr
@@ -1,8 +1,12 @@
-error: only lifetime parameters can be used in this context
+error[E0658]: only lifetime parameters can be used in this context
--> $DIR/disallow-ty.rs:4:9
|
LL | for<T> || -> () {};
| ^
+ |
+ = note: see issue #108185 <https://github.com/rust-lang/rust/issues/108185> for more information
+ = help: add `#![feature(non_lifetime_binders)]` 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/tests/ui/closures/binder/type-bound-2.rs b/tests/ui/closures/binder/type-bound-2.rs
new file mode 100644
index 000000000..f4edcdaa9
--- /dev/null
+++ b/tests/ui/closures/binder/type-bound-2.rs
@@ -0,0 +1,7 @@
+#![feature(closure_lifetime_binder, non_lifetime_binders)]
+//~^ WARN is incomplete and may not be safe to use
+
+fn main() {
+ for<T> || -> () {};
+ //~^ ERROR late-bound type parameter not allowed on closures
+}
diff --git a/tests/ui/closures/binder/type-bound-2.stderr b/tests/ui/closures/binder/type-bound-2.stderr
new file mode 100644
index 000000000..14b2dbf03
--- /dev/null
+++ b/tests/ui/closures/binder/type-bound-2.stderr
@@ -0,0 +1,17 @@
+warning: the feature `non_lifetime_binders` is incomplete and may not be safe to use and/or cause compiler crashes
+ --> $DIR/type-bound-2.rs:1:37
+ |
+LL | #![feature(closure_lifetime_binder, non_lifetime_binders)]
+ | ^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: see issue #108185 <https://github.com/rust-lang/rust/issues/108185> for more information
+ = note: `#[warn(incomplete_features)]` on by default
+
+error: late-bound type parameter not allowed on closures
+ --> $DIR/type-bound-2.rs:5:9
+ |
+LL | for<T> || -> () {};
+ | ^
+
+error: aborting due to previous error; 1 warning emitted
+
diff --git a/tests/ui/closures/binder/type-bound.rs b/tests/ui/closures/binder/type-bound.rs
new file mode 100644
index 000000000..59a3353f4
--- /dev/null
+++ b/tests/ui/closures/binder/type-bound.rs
@@ -0,0 +1,7 @@
+#![feature(closure_lifetime_binder, non_lifetime_binders)]
+//~^ WARN is incomplete and may not be safe to use
+
+fn main() {
+ for<T> || -> T {};
+ //~^ ERROR late-bound type parameter not allowed on closures
+}
diff --git a/tests/ui/closures/binder/type-bound.stderr b/tests/ui/closures/binder/type-bound.stderr
new file mode 100644
index 000000000..ef00a2dff
--- /dev/null
+++ b/tests/ui/closures/binder/type-bound.stderr
@@ -0,0 +1,17 @@
+warning: the feature `non_lifetime_binders` is incomplete and may not be safe to use and/or cause compiler crashes
+ --> $DIR/type-bound.rs:1:37
+ |
+LL | #![feature(closure_lifetime_binder, non_lifetime_binders)]
+ | ^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: see issue #108185 <https://github.com/rust-lang/rust/issues/108185> for more information
+ = note: `#[warn(incomplete_features)]` on by default
+
+error: late-bound type parameter not allowed on closures
+ --> $DIR/type-bound.rs:5:9
+ |
+LL | for<T> || -> T {};
+ | ^
+
+error: aborting due to previous error; 1 warning emitted
+
diff --git a/tests/ui/closures/issue-78720.stderr b/tests/ui/closures/issue-78720.stderr
index 1e860d32b..5d65c87b0 100644
--- a/tests/ui/closures/issue-78720.stderr
+++ b/tests/ui/closures/issue-78720.stderr
@@ -26,7 +26,7 @@ error[E0308]: mismatched types
--> $DIR/issue-78720.rs:7:39
|
LL | fn map2<F>(self, f: F) -> Map2<F> {}
- | ^^ expected struct `Map2`, found `()`
+ | ^^ expected `Map2<F>`, found `()`
|
= note: expected struct `Map2<F>`
found unit type `()`
diff --git a/tests/ui/coercion/coerce-block-tail-26978.stderr b/tests/ui/coercion/coerce-block-tail-26978.stderr
index 384debd48..90eb75f2b 100644
--- a/tests/ui/coercion/coerce-block-tail-26978.stderr
+++ b/tests/ui/coercion/coerce-block-tail-26978.stderr
@@ -2,7 +2,7 @@ error[E0308]: mismatched types
--> $DIR/coerce-block-tail-26978.rs:9:9
|
LL | f(&{x});
- | ^ expected `i32`, found struct `Box`
+ | ^ expected `i32`, found `Box<i32>`
|
= note: expected type `i32`
found struct `Box<i32>`
diff --git a/tests/ui/coercion/coerce-block-tail-57749.stderr b/tests/ui/coercion/coerce-block-tail-57749.stderr
index d5660c81d..7e14f42ea 100644
--- a/tests/ui/coercion/coerce-block-tail-57749.stderr
+++ b/tests/ui/coercion/coerce-block-tail-57749.stderr
@@ -2,7 +2,7 @@ error[E0308]: mismatched types
--> $DIR/coerce-block-tail-57749.rs:33:14
|
LL | reset(&{ Homura });
- | ^^^^^^ expected `u32`, found struct `Homura`
+ | ^^^^^^ expected `u32`, found `Homura`
|
help: consider dereferencing the type
|
diff --git a/tests/ui/coercion/coerce-block-tail-83783.stderr b/tests/ui/coercion/coerce-block-tail-83783.stderr
index 5f53606ce..d556d013b 100644
--- a/tests/ui/coercion/coerce-block-tail-83783.stderr
+++ b/tests/ui/coercion/coerce-block-tail-83783.stderr
@@ -2,7 +2,7 @@ error[E0308]: mismatched types
--> $DIR/coerce-block-tail-83783.rs:7:32
|
LL | _consume_reference::<i32>(&async { Box::new(7_i32) }.await);
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `i32`, found struct `Box`
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `i32`, found `Box<i32>`
|
= note: expected type `i32`
found struct `Box<i32>`
diff --git a/tests/ui/coercion/coerce-block-tail-83850.stderr b/tests/ui/coercion/coerce-block-tail-83850.stderr
index bbf607543..3cfebb8a5 100644
--- a/tests/ui/coercion/coerce-block-tail-83850.stderr
+++ b/tests/ui/coercion/coerce-block-tail-83850.stderr
@@ -2,7 +2,7 @@ error[E0308]: mismatched types
--> $DIR/coerce-block-tail-83850.rs:5:7
|
LL | f(&Box::new([1, 2]));
- | - ^^^^^^^^^^^^^^^^^ expected slice `[i32]`, found struct `Box`
+ | - ^^^^^^^^^^^^^^^^^ expected `&[i32]`, found `&Box<[{integer}; 2]>`
| |
| arguments to this function are incorrect
|
diff --git a/tests/ui/coercion/coerce-block-tail.stderr b/tests/ui/coercion/coerce-block-tail.stderr
index 318cf7586..7044fc3ce 100644
--- a/tests/ui/coercion/coerce-block-tail.stderr
+++ b/tests/ui/coercion/coerce-block-tail.stderr
@@ -2,7 +2,7 @@ error[E0308]: mismatched types
--> $DIR/coerce-block-tail.rs:4:23
|
LL | let _: &i32 = & { Box::new(1i32) };
- | ^^^^^^^^^^^^^^ expected `i32`, found struct `Box`
+ | ^^^^^^^^^^^^^^ expected `i32`, found `Box<i32>`
|
= note: expected type `i32`
found struct `Box<i32>`
diff --git a/tests/ui/coercion/coerce-expect-unsized-ascribed.stderr b/tests/ui/coercion/coerce-expect-unsized-ascribed.stderr
index 44968244c..f94422a92 100644
--- a/tests/ui/coercion/coerce-expect-unsized-ascribed.stderr
+++ b/tests/ui/coercion/coerce-expect-unsized-ascribed.stderr
@@ -2,7 +2,7 @@ error[E0308]: mismatched types
--> $DIR/coerce-expect-unsized-ascribed.rs:9:27
|
LL | let _ = type_ascribe!(box { [1, 2, 3] }, Box<[i32]>);
- | ^^^^^^^^^^^^^^^^^ expected slice `[i32]`, found array `[i32; 3]`
+ | ^^^^^^^^^^^^^^^^^ expected `Box<[i32]>`, found `Box<[i32; 3]>`
|
= note: expected struct `Box<[i32]>`
found struct `Box<[i32; 3]>`
@@ -11,7 +11,7 @@ error[E0308]: mismatched types
--> $DIR/coerce-expect-unsized-ascribed.rs:10:27
|
LL | let _ = type_ascribe!(box if true { [1, 2, 3] } else { [1, 3, 4] }, Box<[i32]>);
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected slice `[i32]`, found array `[i32; 3]`
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `Box<[i32]>`, found `Box<[i32; 3]>`
|
= note: expected struct `Box<[i32]>`
found struct `Box<[i32; 3]>`
@@ -20,7 +20,7 @@ error[E0308]: mismatched types
--> $DIR/coerce-expect-unsized-ascribed.rs:11:27
|
LL | let _ = type_ascribe!(box match true { true => [1, 2, 3], false => [1, 3, 4] }, Box<[i32]>);
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected slice `[i32]`, found array `[i32; 3]`
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `Box<[i32]>`, found `Box<[i32; 3]>`
|
= note: expected struct `Box<[i32]>`
found struct `Box<[i32; 3]>`
@@ -29,7 +29,7 @@ error[E0308]: mismatched types
--> $DIR/coerce-expect-unsized-ascribed.rs:13:27
|
LL | let _ = type_ascribe!(box { |x| (x as u8) }, Box<dyn Fn(i32) -> _>);
- | ^^^^^^^^^^^^^^^^^^^^^ expected trait object `dyn Fn`, found closure
+ | ^^^^^^^^^^^^^^^^^^^^^ expected `Box<dyn Fn(i32) -> u8>`, found `Box<[closure@coerce-expect-unsized-ascribed.rs:13:33]>`
|
= note: expected struct `Box<dyn Fn(i32) -> u8>`
found struct `Box<[closure@$DIR/coerce-expect-unsized-ascribed.rs:13:33: 13:36]>`
@@ -38,7 +38,7 @@ error[E0308]: mismatched types
--> $DIR/coerce-expect-unsized-ascribed.rs:14:27
|
LL | let _ = type_ascribe!(box if true { false } else { true }, Box<dyn Debug>);
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected trait object `dyn Debug`, found `bool`
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `Box<dyn Debug>`, found `Box<bool>`
|
= note: expected struct `Box<dyn Debug>`
found struct `Box<bool>`
@@ -47,7 +47,7 @@ error[E0308]: mismatched types
--> $DIR/coerce-expect-unsized-ascribed.rs:15:27
|
LL | let _ = type_ascribe!(box match true { true => 'a', false => 'b' }, Box<dyn Debug>);
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected trait object `dyn Debug`, found `char`
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `Box<dyn Debug>`, found `Box<char>`
|
= note: expected struct `Box<dyn Debug>`
found struct `Box<char>`
@@ -56,7 +56,7 @@ error[E0308]: mismatched types
--> $DIR/coerce-expect-unsized-ascribed.rs:17:27
|
LL | let _ = type_ascribe!(&{ [1, 2, 3] }, &[i32]);
- | ^^^^^^^^^^^^^^ expected slice `[i32]`, found array `[i32; 3]`
+ | ^^^^^^^^^^^^^^ expected `&[i32]`, found `&[i32; 3]`
|
= note: expected reference `&[i32]`
found reference `&[i32; 3]`
@@ -65,7 +65,7 @@ error[E0308]: mismatched types
--> $DIR/coerce-expect-unsized-ascribed.rs:18:27
|
LL | let _ = type_ascribe!(&if true { [1, 2, 3] } else { [1, 3, 4] }, &[i32]);
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected slice `[i32]`, found array `[i32; 3]`
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `&[i32]`, found `&[i32; 3]`
|
= note: expected reference `&[i32]`
found reference `&[i32; 3]`
@@ -74,7 +74,7 @@ error[E0308]: mismatched types
--> $DIR/coerce-expect-unsized-ascribed.rs:19:27
|
LL | let _ = type_ascribe!(&match true { true => [1, 2, 3], false => [1, 3, 4] }, &[i32]);
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected slice `[i32]`, found array `[i32; 3]`
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `&[i32]`, found `&[i32; 3]`
|
= note: expected reference `&[i32]`
found reference `&[i32; 3]`
@@ -83,7 +83,7 @@ error[E0308]: mismatched types
--> $DIR/coerce-expect-unsized-ascribed.rs:21:27
|
LL | let _ = type_ascribe!(&{ |x| (x as u8) }, &dyn Fn(i32) -> _);
- | ^^^^^^^^^^^^^^^^^^ expected trait object `dyn Fn`, found closure
+ | ^^^^^^^^^^^^^^^^^^ expected `&dyn Fn(i32) -> u8`, found `&[closure@coerce-expect-unsized-ascribed.rs:21:30]`
|
= note: expected reference `&dyn Fn(i32) -> u8`
found reference `&[closure@$DIR/coerce-expect-unsized-ascribed.rs:21:30: 21:33]`
@@ -92,7 +92,7 @@ error[E0308]: mismatched types
--> $DIR/coerce-expect-unsized-ascribed.rs:22:27
|
LL | let _ = type_ascribe!(&if true { false } else { true }, &dyn Debug);
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected trait object `dyn Debug`, found `bool`
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `&dyn Debug`, found `&bool`
|
= note: expected reference `&dyn Debug`
found reference `&bool`
@@ -101,7 +101,7 @@ error[E0308]: mismatched types
--> $DIR/coerce-expect-unsized-ascribed.rs:23:27
|
LL | let _ = type_ascribe!(&match true { true => 'a', false => 'b' }, &dyn Debug);
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected trait object `dyn Debug`, found `char`
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `&dyn Debug`, found `&char`
|
= note: expected reference `&dyn Debug`
found reference `&char`
@@ -110,7 +110,7 @@ error[E0308]: mismatched types
--> $DIR/coerce-expect-unsized-ascribed.rs:25:27
|
LL | let _ = type_ascribe!(Box::new([1, 2, 3]), Box<[i32]>);
- | ^^^^^^^^^^^^^^^^^^^ expected slice `[i32]`, found array `[i32; 3]`
+ | ^^^^^^^^^^^^^^^^^^^ expected `Box<[i32]>`, found `Box<[i32; 3]>`
|
= note: expected struct `Box<[i32]>`
found struct `Box<[i32; 3]>`
@@ -119,7 +119,7 @@ error[E0308]: mismatched types
--> $DIR/coerce-expect-unsized-ascribed.rs:26:27
|
LL | let _ = type_ascribe!(Box::new(|x| (x as u8)), Box<dyn Fn(i32) -> _>);
- | ^^^^^^^^^^^^^^^^^^^^^^^ expected trait object `dyn Fn`, found closure
+ | ^^^^^^^^^^^^^^^^^^^^^^^ expected `Box<dyn Fn(i32) -> u8>`, found `Box<[closure@coerce-expect-unsized-ascribed.rs:26:36]>`
|
= note: expected struct `Box<dyn Fn(i32) -> u8>`
found struct `Box<[closure@$DIR/coerce-expect-unsized-ascribed.rs:26:36: 26:39]>`
diff --git a/tests/ui/coercion/coerce-overloaded-autoderef-fail.stderr b/tests/ui/coercion/coerce-overloaded-autoderef-fail.stderr
index d067c3b3a..d412b8b08 100644
--- a/tests/ui/coercion/coerce-overloaded-autoderef-fail.stderr
+++ b/tests/ui/coercion/coerce-overloaded-autoderef-fail.stderr
@@ -13,10 +13,10 @@ error[E0506]: cannot assign to `**x` because it is borrowed
--> $DIR/coerce-overloaded-autoderef-fail.rs:17:5
|
LL | let y = borrow(x);
- | - borrow of `**x` occurs here
+ | - `**x` is borrowed here
LL | let z = borrow(x);
LL | **x += 1;
- | ^^^^^^^^ assignment to borrowed `**x` occurs here
+ | ^^^^^^^^ `**x` is assigned to here but it was already borrowed
LL |
LL | drop((y, z));
| - borrow later used here
diff --git a/tests/ui/coercion/coerce-to-bang.stderr b/tests/ui/coercion/coerce-to-bang.stderr
index 1207dc7e7..3c737358a 100644
--- a/tests/ui/coercion/coerce-to-bang.stderr
+++ b/tests/ui/coercion/coerce-to-bang.stderr
@@ -82,7 +82,7 @@ error[E0308]: mismatched types
--> $DIR/coerce-to-bang.rs:50:21
|
LL | let x: [!; 2] = [return, 22];
- | ------ ^^^^^^^^^^^^ expected `!`, found integer
+ | ------ ^^^^^^^^^^^^ expected `[!; 2]`, found `[{integer}; 2]`
| |
| expected due to this
|
diff --git a/tests/ui/coercion/coercion-missing-tail-expected-type.stderr b/tests/ui/coercion/coercion-missing-tail-expected-type.stderr
index 4c04bb113..288e945f1 100644
--- a/tests/ui/coercion/coercion-missing-tail-expected-type.stderr
+++ b/tests/ui/coercion/coercion-missing-tail-expected-type.stderr
@@ -12,7 +12,7 @@ error[E0308]: mismatched types
--> $DIR/coercion-missing-tail-expected-type.rs:8:13
|
LL | fn foo() -> Result<u8, u64> {
- | --- ^^^^^^^^^^^^^^^ expected enum `Result`, found `()`
+ | --- ^^^^^^^^^^^^^^^ expected `Result<u8, u64>`, found `()`
| |
| implicitly returns `()` as its body has no tail or `return` expression
LL | Ok(1);
diff --git a/tests/ui/coercion/coercion-slice.rs b/tests/ui/coercion/coercion-slice.rs
index b756c8f82..b99235dd3 100644
--- a/tests/ui/coercion/coercion-slice.rs
+++ b/tests/ui/coercion/coercion-slice.rs
@@ -3,5 +3,5 @@
fn main() {
let _: &[i32] = [0];
//~^ ERROR mismatched types
- //~| expected `&[i32]`, found array `[{integer}; 1]`
+ //~| expected `&[i32]`, found `[{integer}; 1]`
}
diff --git a/tests/ui/coercion/coercion-slice.stderr b/tests/ui/coercion/coercion-slice.stderr
index 42dc954ff..c7b856a57 100644
--- a/tests/ui/coercion/coercion-slice.stderr
+++ b/tests/ui/coercion/coercion-slice.stderr
@@ -4,7 +4,7 @@ error[E0308]: mismatched types
LL | let _: &[i32] = [0];
| ------ ^^^
| | |
- | | expected `&[i32]`, found array `[{integer}; 1]`
+ | | expected `&[i32]`, found `[{integer}; 1]`
| | help: consider borrowing here: `&[0]`
| expected due to this
diff --git a/tests/ui/coherence/coherence-impl-trait-for-marker-trait-negative.rs b/tests/ui/coherence/coherence-impl-trait-for-marker-trait-negative.rs
index 50d9a480a..98f1558b7 100644
--- a/tests/ui/coherence/coherence-impl-trait-for-marker-trait-negative.rs
+++ b/tests/ui/coherence/coherence-impl-trait-for-marker-trait-negative.rs
@@ -12,19 +12,26 @@ auto trait Marker2 {}
trait Object: Marker1 {}
// A supertrait marker is illegal...
-impl !Marker1 for dyn Object + Marker2 { } //~ ERROR E0371
+impl !Marker1 for dyn Object + Marker2 {} //~ ERROR E0371
+ //~^ ERROR 0321
// ...and also a direct component.
-impl !Marker2 for dyn Object + Marker2 { } //~ ERROR E0371
-
-// But implementing a marker if it is not present is OK.
-impl !Marker2 for dyn Object {} // OK
+impl !Marker2 for dyn Object + Marker2 {} //~ ERROR E0371
+ //~^ ERROR 0321
// A non-principal trait-object type is orphan even in its crate.
impl !Send for dyn Marker2 {} //~ ERROR E0117
-// And impl'ing a remote marker for a local trait object is forbidden
-// by one of these special orphan-like rules.
+// Implementing a marker for a local trait object is forbidden by a special
+// orphan-like rule.
+impl !Marker2 for dyn Object {} //~ ERROR E0321
impl !Send for dyn Object {} //~ ERROR E0321
impl !Send for dyn Object + Marker2 {} //~ ERROR E0321
-fn main() { }
+// Blanket impl that applies to dyn Object is equally problematic.
+auto trait Marker3 {}
+impl<T: ?Sized> !Marker3 for T {} //~ ERROR E0321
+
+auto trait Marker4 {}
+impl<T> !Marker4 for T {} // okay
+
+fn main() {}
diff --git a/tests/ui/coherence/coherence-impl-trait-for-marker-trait-negative.stderr b/tests/ui/coherence/coherence-impl-trait-for-marker-trait-negative.stderr
index c364c707f..ea38afc40 100644
--- a/tests/ui/coherence/coherence-impl-trait-for-marker-trait-negative.stderr
+++ b/tests/ui/coherence/coherence-impl-trait-for-marker-trait-negative.stderr
@@ -1,17 +1,41 @@
error[E0371]: the object type `(dyn Object + Marker2 + 'static)` automatically implements the trait `Marker1`
--> $DIR/coherence-impl-trait-for-marker-trait-negative.rs:15:1
|
-LL | impl !Marker1 for dyn Object + Marker2 { }
+LL | impl !Marker1 for dyn Object + Marker2 {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `(dyn Object + Marker2 + 'static)` automatically implements trait `Marker1`
+error[E0321]: traits with a default impl, like `Marker1`, cannot be implemented for trait object `(dyn Object + Marker2 + 'static)`
+ --> $DIR/coherence-impl-trait-for-marker-trait-negative.rs:15:1
+ |
+LL | impl !Marker1 for dyn Object + Marker2 {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: a trait object implements `Marker1` if and only if `Marker1` is one of the trait object's trait bounds
+
error[E0371]: the object type `(dyn Object + Marker2 + 'static)` automatically implements the trait `Marker2`
- --> $DIR/coherence-impl-trait-for-marker-trait-negative.rs:17:1
+ --> $DIR/coherence-impl-trait-for-marker-trait-negative.rs:18:1
|
-LL | impl !Marker2 for dyn Object + Marker2 { }
+LL | impl !Marker2 for dyn Object + Marker2 {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `(dyn Object + Marker2 + 'static)` automatically implements trait `Marker2`
+error[E0321]: traits with a default impl, like `Marker2`, cannot be implemented for trait object `(dyn Object + Marker2 + 'static)`
+ --> $DIR/coherence-impl-trait-for-marker-trait-negative.rs:18:1
+ |
+LL | impl !Marker2 for dyn Object + Marker2 {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: a trait object implements `Marker2` if and only if `Marker2` is one of the trait object's trait bounds
+
+error[E0321]: traits with a default impl, like `Marker2`, cannot be implemented for trait object `(dyn Object + 'static)`
+ --> $DIR/coherence-impl-trait-for-marker-trait-negative.rs:26:1
+ |
+LL | impl !Marker2 for dyn Object {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: a trait object implements `Marker2` if and only if `Marker2` is one of the trait object's trait bounds
+
error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
- --> $DIR/coherence-impl-trait-for-marker-trait-negative.rs:23:1
+ --> $DIR/coherence-impl-trait-for-marker-trait-negative.rs:22:1
|
LL | impl !Send for dyn Marker2 {}
| ^^^^^^^^^^^^^^^-----------
@@ -33,7 +57,15 @@ error[E0321]: cross-crate traits with a default impl, like `Send`, can only be i
LL | impl !Send for dyn Object + Marker2 {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't implement cross-crate trait with a default impl for non-struct/enum type
-error: aborting due to 5 previous errors
+error[E0321]: traits with a default impl, like `Marker3`, cannot be implemented for generic type `T`
+ --> $DIR/coherence-impl-trait-for-marker-trait-negative.rs:32:1
+ |
+LL | impl<T: ?Sized> !Marker3 for T {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: a trait object implements `Marker3` if and only if `Marker3` is one of the trait object's trait bounds
+
+error: aborting due to 9 previous errors
Some errors have detailed explanations: E0117, E0321, E0371.
For more information about an error, try `rustc --explain E0117`.
diff --git a/tests/ui/coherence/coherence-impl-trait-for-marker-trait-positive.rs b/tests/ui/coherence/coherence-impl-trait-for-marker-trait-positive.rs
index faac6d983..db2e2b450 100644
--- a/tests/ui/coherence/coherence-impl-trait-for-marker-trait-positive.rs
+++ b/tests/ui/coherence/coherence-impl-trait-for-marker-trait-positive.rs
@@ -12,19 +12,26 @@ auto trait Marker2 {}
trait Object: Marker1 {}
// A supertrait marker is illegal...
-impl Marker1 for dyn Object + Marker2 { } //~ ERROR E0371
+impl Marker1 for dyn Object + Marker2 {} //~ ERROR E0371
+ //~^ ERROR E0321
// ...and also a direct component.
-impl Marker2 for dyn Object + Marker2 { } //~ ERROR E0371
-
-// But implementing a marker if it is not present is OK.
-impl Marker2 for dyn Object {} // OK
+impl Marker2 for dyn Object + Marker2 {} //~ ERROR E0371
+ //~^ ERROR E0321
// A non-principal trait-object type is orphan even in its crate.
unsafe impl Send for dyn Marker2 {} //~ ERROR E0117
-// And impl'ing a remote marker for a local trait object is forbidden
-// by one of these special orphan-like rules.
+// Implementing a marker for a local trait object is forbidden by a special
+// orphan-like rule.
+impl Marker2 for dyn Object {} //~ ERROR E0321
unsafe impl Send for dyn Object {} //~ ERROR E0321
unsafe impl Send for dyn Object + Marker2 {} //~ ERROR E0321
-fn main() { }
+// Blanket impl that applies to dyn Object is equally problematic.
+auto trait Marker3 {}
+impl<T: ?Sized> Marker3 for T {} //~ ERROR E0321
+
+auto trait Marker4 {}
+impl<T> Marker4 for T {} // okay
+
+fn main() {}
diff --git a/tests/ui/coherence/coherence-impl-trait-for-marker-trait-positive.stderr b/tests/ui/coherence/coherence-impl-trait-for-marker-trait-positive.stderr
index b80429794..2a8713bc3 100644
--- a/tests/ui/coherence/coherence-impl-trait-for-marker-trait-positive.stderr
+++ b/tests/ui/coherence/coherence-impl-trait-for-marker-trait-positive.stderr
@@ -1,17 +1,41 @@
error[E0371]: the object type `(dyn Object + Marker2 + 'static)` automatically implements the trait `Marker1`
--> $DIR/coherence-impl-trait-for-marker-trait-positive.rs:15:1
|
-LL | impl Marker1 for dyn Object + Marker2 { }
+LL | impl Marker1 for dyn Object + Marker2 {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `(dyn Object + Marker2 + 'static)` automatically implements trait `Marker1`
+error[E0321]: traits with a default impl, like `Marker1`, cannot be implemented for trait object `(dyn Object + Marker2 + 'static)`
+ --> $DIR/coherence-impl-trait-for-marker-trait-positive.rs:15:1
+ |
+LL | impl Marker1 for dyn Object + Marker2 {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: a trait object implements `Marker1` if and only if `Marker1` is one of the trait object's trait bounds
+
error[E0371]: the object type `(dyn Object + Marker2 + 'static)` automatically implements the trait `Marker2`
- --> $DIR/coherence-impl-trait-for-marker-trait-positive.rs:17:1
+ --> $DIR/coherence-impl-trait-for-marker-trait-positive.rs:18:1
|
-LL | impl Marker2 for dyn Object + Marker2 { }
+LL | impl Marker2 for dyn Object + Marker2 {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `(dyn Object + Marker2 + 'static)` automatically implements trait `Marker2`
+error[E0321]: traits with a default impl, like `Marker2`, cannot be implemented for trait object `(dyn Object + Marker2 + 'static)`
+ --> $DIR/coherence-impl-trait-for-marker-trait-positive.rs:18:1
+ |
+LL | impl Marker2 for dyn Object + Marker2 {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: a trait object implements `Marker2` if and only if `Marker2` is one of the trait object's trait bounds
+
+error[E0321]: traits with a default impl, like `Marker2`, cannot be implemented for trait object `(dyn Object + 'static)`
+ --> $DIR/coherence-impl-trait-for-marker-trait-positive.rs:26:1
+ |
+LL | impl Marker2 for dyn Object {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: a trait object implements `Marker2` if and only if `Marker2` is one of the trait object's trait bounds
+
error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
- --> $DIR/coherence-impl-trait-for-marker-trait-positive.rs:23:1
+ --> $DIR/coherence-impl-trait-for-marker-trait-positive.rs:22:1
|
LL | unsafe impl Send for dyn Marker2 {}
| ^^^^^^^^^^^^^^^^^^^^^-----------
@@ -33,7 +57,15 @@ error[E0321]: cross-crate traits with a default impl, like `Send`, can only be i
LL | unsafe impl Send for dyn Object + Marker2 {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't implement cross-crate trait with a default impl for non-struct/enum type
-error: aborting due to 5 previous errors
+error[E0321]: traits with a default impl, like `Marker3`, cannot be implemented for generic type `T`
+ --> $DIR/coherence-impl-trait-for-marker-trait-positive.rs:32:1
+ |
+LL | impl<T: ?Sized> Marker3 for T {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: a trait object implements `Marker3` if and only if `Marker3` is one of the trait object's trait bounds
+
+error: aborting due to 9 previous errors
Some errors have detailed explanations: E0117, E0321, E0371.
For more information about an error, try `rustc --explain E0117`.
diff --git a/tests/ui/coherence/issue-85026.stderr b/tests/ui/coherence/issue-85026.stderr
index a5da19bbf..fb6e99765 100644
--- a/tests/ui/coherence/issue-85026.stderr
+++ b/tests/ui/coherence/issue-85026.stderr
@@ -1,16 +1,16 @@
error[E0785]: cannot define inherent `impl` for a dyn auto trait
- --> $DIR/issue-85026.rs:5:6
+ --> $DIR/issue-85026.rs:5:1
|
LL | impl dyn AutoTrait {}
- | ^^^^^^^^^^^^^ impl requires at least one non-auto trait
+ | ^^^^^^^^^^^^^^^^^^ impl requires at least one non-auto trait
|
= note: define and implement a new trait or type instead
error[E0785]: cannot define inherent `impl` for a dyn auto trait
- --> $DIR/issue-85026.rs:8:6
+ --> $DIR/issue-85026.rs:8:1
|
LL | impl dyn Unpin {}
- | ^^^^^^^^^ impl requires at least one non-auto trait
+ | ^^^^^^^^^^^^^^ impl requires at least one non-auto trait
|
= note: define and implement a new trait or type instead
diff --git a/tests/ui/coinduction/canonicalization-rerun.rs b/tests/ui/coinduction/canonicalization-rerun.rs
new file mode 100644
index 000000000..b10ba3a81
--- /dev/null
+++ b/tests/ui/coinduction/canonicalization-rerun.rs
@@ -0,0 +1,54 @@
+// check-pass
+// revisions: old new
+//[new] compile-flags: -Ztrait-solver=next
+
+// If we use canonical goals during trait solving we have to reevaluate
+// the root goal of a cycle until we hit a fixpoint.
+//
+// Here `main` has a goal `(?0, ?1): Trait` which is canonicalized to
+// `exists<^0, ^1> (^0, ^1): Trait`.
+//
+// - `exists<^0, ^1> (^0, ^1): Trait` -instantiate-> `(?0, ?1): Trait`
+// -`(?1, ?0): Trait` -canonicalize-> `exists<^0, ^1> (^0, ^1): Trait`
+// - COINDUCTIVE CYCLE OK (no constraints)
+// - `(): ConstrainToU32<?0>` -canonicalize-> `exists<^0> (): ConstrainToU32<^0>`
+// - OK (^0 = u32 -apply-> ?0 = u32)
+// - OK (?0 = u32 -canonicalize-> ^0 = u32)
+// - coinductive cycle with provisional result != final result, rerun
+//
+// - `exists<^0, ^1> (^0, ^1): Trait` -instantiate-> `(?0, ?1): Trait`
+// -`(?1, ?0): Trait` -canonicalize-> `exists<^0, ^1> (^0, ^1): Trait`
+// - COINDUCTIVE CYCLE OK (^0 = u32 -apply-> ?1 = u32)
+// - `(): ConstrainToU32<?0>` -canonicalize-> `exists<^0> (): ConstrainToU32<^0>`
+// - OK (^0 = u32 -apply-> ?1 = u32)
+// - OK (?0 = u32, ?1 = u32 -canonicalize-> ^0 = u32, ^1 = u32)
+// - coinductive cycle with provisional result != final result, rerun
+//
+// - `exists<^0, ^1> (^0, ^1): Trait` -instantiate-> `(?0, ?1): Trait`
+// -`(?1, ?0): Trait` -canonicalize-> `exists<^0, ^1> (^0, ^1): Trait`
+// - COINDUCTIVE CYCLE OK (^0 = u32, ^1 = u32 -apply-> ?1 = u32, ?0 = u32)
+// - `(): ConstrainToU32<?0>` -canonicalize-> `exists<^0> (): ConstrainToU32<^0>`
+// - OK (^0 = u32 -apply-> ?1 = u32)
+// - OK (?0 = u32, ?1 = u32 -canonicalize-> ^0 = u32, ^1 = u32)
+// - coinductive cycle with provisional result == final result, DONE
+#![feature(rustc_attrs)]
+#[rustc_coinductive]
+trait Trait {}
+
+impl<T, U> Trait for (T, U)
+where
+ (U, T): Trait,
+ (): ConstrainToU32<T>,
+{}
+
+trait ConstrainToU32<T> {}
+impl ConstrainToU32<u32> for () {}
+
+fn impls_trait<T, U>()
+where
+ (T, U): Trait,
+{}
+
+fn main() {
+ impls_trait::<_, _>();
+}
diff --git a/tests/ui/command/command-setgroups.rs b/tests/ui/command/command-setgroups.rs
index aff67f91b..7e321f2f0 100644
--- a/tests/ui/command/command-setgroups.rs
+++ b/tests/ui/command/command-setgroups.rs
@@ -3,6 +3,7 @@
// ignore-emscripten
// ignore-sgx
// ignore-musl - returns dummy result for _SC_NGROUPS_MAX
+// ignore-nto - does not have `/bin/id`, expects groups to be i32 (not u32)
#![feature(rustc_private)]
#![feature(setgroups)]
diff --git a/tests/ui/compare-method/bad-self-type.stderr b/tests/ui/compare-method/bad-self-type.stderr
index cad942e64..f632a53f2 100644
--- a/tests/ui/compare-method/bad-self-type.stderr
+++ b/tests/ui/compare-method/bad-self-type.stderr
@@ -4,7 +4,7 @@ error[E0053]: method `poll` has an incompatible type for trait
LL | fn poll(self, _: &mut Context<'_>) -> Poll<()> {
| ^^^^
| |
- | expected struct `Pin`, found struct `MyFuture`
+ | expected `Pin<&mut MyFuture>`, found `MyFuture`
| help: change the self-receiver type to match the trait: `self: Pin<&mut MyFuture>`
|
= note: expected signature `fn(Pin<&mut MyFuture>, &mut Context<'_>) -> Poll<_>`
@@ -16,7 +16,7 @@ error[E0053]: method `foo` has an incompatible type for trait
LL | fn foo(self: Box<Self>) {}
| ------^^^^^^^^^
| | |
- | | expected struct `MyFuture`, found struct `Box`
+ | | expected `MyFuture`, found `Box<MyFuture>`
| help: change the self-receiver type to match the trait: `self`
|
note: type in trait
@@ -31,7 +31,7 @@ error[E0053]: method `bar` has an incompatible type for trait
--> $DIR/bad-self-type.rs:24:18
|
LL | fn bar(self) {}
- | ^ expected enum `Option`, found `()`
+ | ^ expected `Option<()>`, found `()`
|
note: type in trait
--> $DIR/bad-self-type.rs:18:21
diff --git a/tests/ui/conditional-compilation/cfg-generic-params.stderr b/tests/ui/conditional-compilation/cfg-generic-params.stderr
index 4d6560e96..f733c09c2 100644
--- a/tests/ui/conditional-compilation/cfg-generic-params.stderr
+++ b/tests/ui/conditional-compilation/cfg-generic-params.stderr
@@ -1,21 +1,3 @@
-error: only lifetime parameters can be used in this context
- --> $DIR/cfg-generic-params.rs:7:45
- |
-LL | type FnBad = for<#[cfg(no)] 'a, #[cfg(yes)] T> fn();
- | ^
-
-error: only lifetime parameters can be used in this context
- --> $DIR/cfg-generic-params.rs:11:51
- |
-LL | type PolyBad = dyn for<#[cfg(no)] 'a, #[cfg(yes)] T> Copy;
- | ^
-
-error: only lifetime parameters can be used in this context
- --> $DIR/cfg-generic-params.rs:15:54
- |
-LL | struct WhereBad where for<#[cfg(no)] 'a, #[cfg(yes)] T> u8: Copy;
- | ^
-
error: cannot find attribute `unknown` in this scope
--> $DIR/cfg-generic-params.rs:19:29
|
@@ -46,5 +28,33 @@ error: cannot find attribute `unknown` in this scope
LL | struct WhereYes where for<#[cfg_attr(yes, unknown)] 'a> u8: Copy;
| ^^^^^^^
+error[E0658]: only lifetime parameters can be used in this context
+ --> $DIR/cfg-generic-params.rs:7:45
+ |
+LL | type FnBad = for<#[cfg(no)] 'a, #[cfg(yes)] T> fn();
+ | ^
+ |
+ = note: see issue #108185 <https://github.com/rust-lang/rust/issues/108185> for more information
+ = help: add `#![feature(non_lifetime_binders)]` to the crate attributes to enable
+
+error[E0658]: only lifetime parameters can be used in this context
+ --> $DIR/cfg-generic-params.rs:11:51
+ |
+LL | type PolyBad = dyn for<#[cfg(no)] 'a, #[cfg(yes)] T> Copy;
+ | ^
+ |
+ = note: see issue #108185 <https://github.com/rust-lang/rust/issues/108185> for more information
+ = help: add `#![feature(non_lifetime_binders)]` to the crate attributes to enable
+
+error[E0658]: only lifetime parameters can be used in this context
+ --> $DIR/cfg-generic-params.rs:15:54
+ |
+LL | struct WhereBad where for<#[cfg(no)] 'a, #[cfg(yes)] T> u8: Copy;
+ | ^
+ |
+ = note: see issue #108185 <https://github.com/rust-lang/rust/issues/108185> for more information
+ = help: add `#![feature(non_lifetime_binders)]` to the crate attributes to enable
+
error: aborting due to 8 previous errors
+For more information about this error, try `rustc --explain E0658`.
diff --git a/tests/ui/confuse-field-and-method/issue-33784.stderr b/tests/ui/confuse-field-and-method/issue-33784.stderr
index 3906d64c9..34debb683 100644
--- a/tests/ui/confuse-field-and-method/issue-33784.stderr
+++ b/tests/ui/confuse-field-and-method/issue-33784.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no method named `closure` found for reference `&Obj<[closure@issue-33784.rs:25:43]>` in the current scope
+error[E0599]: no method named `closure` found for reference `&Obj<[closure@$DIR/issue-33784.rs:25:43: 25:45]>` in the current scope
--> $DIR/issue-33784.rs:27:7
|
LL | p.closure();
@@ -9,7 +9,7 @@ help: to call the function stored in `closure`, surround the field access with p
LL | (p.closure)();
| + +
-error[E0599]: no method named `fn_ptr` found for reference `&&Obj<[closure@issue-33784.rs:25:43]>` in the current scope
+error[E0599]: no method named `fn_ptr` found for reference `&&Obj<[closure@$DIR/issue-33784.rs:25:43: 25:45]>` in the current scope
--> $DIR/issue-33784.rs:29:7
|
LL | q.fn_ptr();
diff --git a/tests/ui/const-generics/bad-const-generic-exprs.rs b/tests/ui/const-generics/bad-const-generic-exprs.rs
index ca91643ed..423752ca2 100644
--- a/tests/ui/const-generics/bad-const-generic-exprs.rs
+++ b/tests/ui/const-generics/bad-const-generic-exprs.rs
@@ -13,10 +13,34 @@ fn main() {
let _: Wow<A.0>;
//~^ ERROR expected one of
//~| HELP expressions must be enclosed in braces to be used as const generic arguments
-
- // FIXME(compiler-errors): This one is still unsatisfying,
- // and probably a case I could see someone typing by accident..
+ let _: Wow<[]>;
+ //~^ ERROR expected type
+ //~| HELP expressions must be enclosed in braces to be used as const generic arguments
let _: Wow<[12]>;
- //~^ ERROR expected type, found
- //~| ERROR type provided when a constant was expected
+ //~^ ERROR expected type
+ //~| ERROR invalid const generic expression
+ //~| HELP expressions must be enclosed in braces to be used as const generic arguments
+ let _: Wow<[0, 1, 3]>;
+ //~^ ERROR expected type
+ //~| HELP expressions must be enclosed in braces to be used as const generic arguments
+ let _: Wow<[0xff; 8]>;
+ //~^ ERROR expected type
+ //~| ERROR invalid const generic expression
+ //~| HELP expressions must be enclosed in braces to be used as const generic arguments
+ let _: Wow<[1, 2]>; // Regression test for issue #81698.
+ //~^ ERROR expected type
+ //~| HELP expressions must be enclosed in braces to be used as const generic arguments
+ let _: Wow<&0>;
+ //~^ ERROR expected type
+ //~| HELP expressions must be enclosed in braces to be used as const generic arguments
+ let _: Wow<("", 0)>;
+ //~^ ERROR expected type
+ //~| HELP expressions must be enclosed in braces to be used as const generic arguments
+ let _: Wow<(1 + 2) * 3>;
+ //~^ ERROR expected type
+ //~| HELP expressions must be enclosed in braces to be used as const generic arguments
+ // FIXME(fmease): This one is pretty bad.
+ let _: Wow<!0>;
+ //~^ ERROR expected one of
+ //~| HELP you might have meant to end the type parameters here
}
diff --git a/tests/ui/const-generics/bad-const-generic-exprs.stderr b/tests/ui/const-generics/bad-const-generic-exprs.stderr
index 24668b08b..17a63a96f 100644
--- a/tests/ui/const-generics/bad-const-generic-exprs.stderr
+++ b/tests/ui/const-generics/bad-const-generic-exprs.stderr
@@ -42,18 +42,118 @@ help: expressions must be enclosed in braces to be used as const generic argumen
LL | let _: Wow<{ A.0 }>;
| + +
+error: expected type, found `]`
+ --> $DIR/bad-const-generic-exprs.rs:16:17
+ |
+LL | let _: Wow<[]>;
+ | ^ expected type
+ |
+help: expressions must be enclosed in braces to be used as const generic arguments
+ |
+LL | let _: Wow<{ [] }>;
+ | + +
+
error: expected type, found `12`
--> $DIR/bad-const-generic-exprs.rs:19:17
|
LL | let _: Wow<[12]>;
| ^^ expected type
-error[E0747]: type provided when a constant was expected
+error: invalid const generic expression
--> $DIR/bad-const-generic-exprs.rs:19:16
|
LL | let _: Wow<[12]>;
| ^^^^
+ |
+help: expressions must be enclosed in braces to be used as const generic arguments
+ |
+LL | let _: Wow<{ [12] }>;
+ | + +
+
+error: expected type, found `0`
+ --> $DIR/bad-const-generic-exprs.rs:23:17
+ |
+LL | let _: Wow<[0, 1, 3]>;
+ | ^ expected type
+ |
+help: expressions must be enclosed in braces to be used as const generic arguments
+ |
+LL | let _: Wow<{ [0, 1, 3] }>;
+ | + +
+
+error: expected type, found `0xff`
+ --> $DIR/bad-const-generic-exprs.rs:26:17
+ |
+LL | let _: Wow<[0xff; 8]>;
+ | ^^^^ expected type
+
+error: invalid const generic expression
+ --> $DIR/bad-const-generic-exprs.rs:26:16
+ |
+LL | let _: Wow<[0xff; 8]>;
+ | ^^^^^^^^^
+ |
+help: expressions must be enclosed in braces to be used as const generic arguments
+ |
+LL | let _: Wow<{ [0xff; 8] }>;
+ | + +
+
+error: expected type, found `1`
+ --> $DIR/bad-const-generic-exprs.rs:30:17
+ |
+LL | let _: Wow<[1, 2]>; // Regression test for issue #81698.
+ | ^ expected type
+ |
+help: expressions must be enclosed in braces to be used as const generic arguments
+ |
+LL | let _: Wow<{ [1, 2] }>; // Regression test for issue #81698.
+ | + +
+
+error: expected type, found `0`
+ --> $DIR/bad-const-generic-exprs.rs:33:17
+ |
+LL | let _: Wow<&0>;
+ | ^ expected type
+ |
+help: expressions must be enclosed in braces to be used as const generic arguments
+ |
+LL | let _: Wow<{ &0 }>;
+ | + +
+
+error: expected type, found `""`
+ --> $DIR/bad-const-generic-exprs.rs:36:17
+ |
+LL | let _: Wow<("", 0)>;
+ | ^^ expected type
+ |
+help: expressions must be enclosed in braces to be used as const generic arguments
+ |
+LL | let _: Wow<{ ("", 0) }>;
+ | + +
+
+error: expected type, found `1`
+ --> $DIR/bad-const-generic-exprs.rs:39:17
+ |
+LL | let _: Wow<(1 + 2) * 3>;
+ | ^ expected type
+ |
+help: expressions must be enclosed in braces to be used as const generic arguments
+ |
+LL | let _: Wow<{ (1 + 2) * 3 }>;
+ | + +
+
+error: expected one of `,` or `>`, found `0`
+ --> $DIR/bad-const-generic-exprs.rs:43:17
+ |
+LL | let _: Wow<!0>;
+ | - ^ expected one of `,` or `>`
+ | |
+ | while parsing the type for `_`
+ |
+help: you might have meant to end the type parameters here
+ |
+LL | let _: Wow<!>0>;
+ | +
-error: aborting due to 6 previous errors
+error: aborting due to 15 previous errors
-For more information about this error, try `rustc --explain E0747`.
diff --git a/tests/ui/const-generics/const-argument-non-static-lifetime.min.stderr b/tests/ui/const-generics/const-argument-non-static-lifetime.min.stderr
index f1f3a9c3d..82030731c 100644
--- a/tests/ui/const-generics/const-argument-non-static-lifetime.min.stderr
+++ b/tests/ui/const-generics/const-argument-non-static-lifetime.min.stderr
@@ -1,5 +1,5 @@
error[E0658]: a non-static lifetime is not allowed in a `const`
- --> $DIR/const-argument-non-static-lifetime.rs:15:17
+ --> $DIR/const-argument-non-static-lifetime.rs:14:17
|
LL | let _: &'a ();
| ^^
diff --git a/tests/ui/const-generics/const-argument-non-static-lifetime.rs b/tests/ui/const-generics/const-argument-non-static-lifetime.rs
index 36a569784..0357e4ed5 100644
--- a/tests/ui/const-generics/const-argument-non-static-lifetime.rs
+++ b/tests/ui/const-generics/const-argument-non-static-lifetime.rs
@@ -2,7 +2,6 @@
// revisions: full min
// regression test for #78180
-// compile-flags: -Zsave-analysis
#![cfg_attr(full, feature(generic_const_exprs))]
#![cfg_attr(full, allow(incomplete_features))]
diff --git a/tests/ui/const-generics/const-param-elided-lifetime.min.stderr b/tests/ui/const-generics/const-param-elided-lifetime.min.stderr
index 4bba42c77..656bc2946 100644
--- a/tests/ui/const-generics/const-param-elided-lifetime.min.stderr
+++ b/tests/ui/const-generics/const-param-elided-lifetime.min.stderr
@@ -28,7 +28,7 @@ error[E0637]: `&` without an explicit lifetime name cannot be used here
LL | fn bar<const N: &u8>() {}
| ^ explicit lifetime name needed here
-error: `&'static u8` is forbidden as the type of a const generic parameter
+error: `&u8` is forbidden as the type of a const generic parameter
--> $DIR/const-param-elided-lifetime.rs:9:19
|
LL | struct A<const N: &u8>;
@@ -37,7 +37,7 @@ LL | struct A<const N: &u8>;
= note: the only supported types are integers, `bool` and `char`
= help: more complex types are supported with `#![feature(adt_const_params)]`
-error: `&'static u8` is forbidden as the type of a const generic parameter
+error: `&u8` is forbidden as the type of a const generic parameter
--> $DIR/const-param-elided-lifetime.rs:14:15
|
LL | impl<const N: &u8> A<N> {
@@ -46,7 +46,7 @@ LL | impl<const N: &u8> A<N> {
= note: the only supported types are integers, `bool` and `char`
= help: more complex types are supported with `#![feature(adt_const_params)]`
-error: `&'static u8` is forbidden as the type of a const generic parameter
+error: `&u8` is forbidden as the type of a const generic parameter
--> $DIR/const-param-elided-lifetime.rs:22:15
|
LL | impl<const N: &u8> B for A<N> {}
@@ -55,7 +55,7 @@ LL | impl<const N: &u8> B for A<N> {}
= note: the only supported types are integers, `bool` and `char`
= help: more complex types are supported with `#![feature(adt_const_params)]`
-error: `&'static u8` is forbidden as the type of a const generic parameter
+error: `&u8` is forbidden as the type of a const generic parameter
--> $DIR/const-param-elided-lifetime.rs:26:17
|
LL | fn bar<const N: &u8>() {}
@@ -64,7 +64,7 @@ LL | fn bar<const N: &u8>() {}
= note: the only supported types are integers, `bool` and `char`
= help: more complex types are supported with `#![feature(adt_const_params)]`
-error: `&'static u8` is forbidden as the type of a const generic parameter
+error: `&u8` is forbidden as the type of a const generic parameter
--> $DIR/const-param-elided-lifetime.rs:17:21
|
LL | fn foo<const M: &u8>(&self) {}
diff --git a/tests/ui/const-generics/const-param-elided-lifetime.rs b/tests/ui/const-generics/const-param-elided-lifetime.rs
index 487b82dbf..45611d6bf 100644
--- a/tests/ui/const-generics/const-param-elided-lifetime.rs
+++ b/tests/ui/const-generics/const-param-elided-lifetime.rs
@@ -8,23 +8,23 @@
struct A<const N: &u8>;
//~^ ERROR `&` without an explicit lifetime name cannot be used here
-//[min]~^^ ERROR `&'static u8` is forbidden
+//[min]~^^ ERROR `&u8` is forbidden
trait B {}
impl<const N: &u8> A<N> {
//~^ ERROR `&` without an explicit lifetime name cannot be used here
-//[min]~^^ ERROR `&'static u8` is forbidden
+//[min]~^^ ERROR `&u8` is forbidden
fn foo<const M: &u8>(&self) {}
//~^ ERROR `&` without an explicit lifetime name cannot be used here
- //[min]~^^ ERROR `&'static u8` is forbidden
+ //[min]~^^ ERROR `&u8` is forbidden
}
impl<const N: &u8> B for A<N> {}
//~^ ERROR `&` without an explicit lifetime name cannot be used here
-//[min]~^^ ERROR `&'static u8` is forbidden
+//[min]~^^ ERROR `&u8` is forbidden
fn bar<const N: &u8>() {}
//~^ ERROR `&` without an explicit lifetime name cannot be used here
-//[min]~^^ ERROR `&'static u8` is forbidden
+//[min]~^^ ERROR `&u8` is forbidden
fn main() {}
diff --git a/tests/ui/const-generics/const-param-type-depends-on-type-param-ungated.rs b/tests/ui/const-generics/const-param-type-depends-on-type-param-ungated.rs
index 781f50e61..b776f2017 100644
--- a/tests/ui/const-generics/const-param-type-depends-on-type-param-ungated.rs
+++ b/tests/ui/const-generics/const-param-type-depends-on-type-param-ungated.rs
@@ -1,6 +1,3 @@
-// compile-flags: -Zsave-analysis
-// Regression test for #69414 ^
-
use std::marker::PhantomData;
struct B<T, const N: T>(PhantomData<[T; N]>);
diff --git a/tests/ui/const-generics/const-param-type-depends-on-type-param-ungated.stderr b/tests/ui/const-generics/const-param-type-depends-on-type-param-ungated.stderr
index 8e14defd6..9c5c97bef 100644
--- a/tests/ui/const-generics/const-param-type-depends-on-type-param-ungated.stderr
+++ b/tests/ui/const-generics/const-param-type-depends-on-type-param-ungated.stderr
@@ -1,5 +1,5 @@
error[E0770]: the type of const parameters must not depend on other generic parameters
- --> $DIR/const-param-type-depends-on-type-param-ungated.rs:6:22
+ --> $DIR/const-param-type-depends-on-type-param-ungated.rs:3:22
|
LL | struct B<T, const N: T>(PhantomData<[T; N]>);
| ^ the type must not depend on the parameter `T`
diff --git a/tests/ui/const-generics/defaults/mismatch.stderr b/tests/ui/const-generics/defaults/mismatch.stderr
index 52c54aace..9c4f0bc95 100644
--- a/tests/ui/const-generics/defaults/mismatch.stderr
+++ b/tests/ui/const-generics/defaults/mismatch.stderr
@@ -2,7 +2,7 @@ error[E0308]: mismatched types
--> $DIR/mismatch.rs:7:26
|
LL | let e: Example<13> = ();
- | ----------- ^^ expected struct `Example`, found `()`
+ | ----------- ^^ expected `Example`, found `()`
| |
| expected due to this
|
@@ -13,7 +13,7 @@ error[E0308]: mismatched types
--> $DIR/mismatch.rs:10:32
|
LL | let e: Example2<u32, 13> = ();
- | ----------------- ^^ expected struct `Example2`, found `()`
+ | ----------------- ^^ expected `Example2`, found `()`
| |
| expected due to this
|
@@ -24,7 +24,7 @@ error[E0308]: mismatched types
--> $DIR/mismatch.rs:13:32
|
LL | let e: Example3<13, u32> = ();
- | ----------------- ^^ expected struct `Example3`, found `()`
+ | ----------------- ^^ expected `Example3`, found `()`
| |
| expected due to this
|
@@ -35,7 +35,7 @@ error[E0308]: mismatched types
--> $DIR/mismatch.rs:16:26
|
LL | let e: Example3<7> = ();
- | ----------- ^^ expected struct `Example3`, found `()`
+ | ----------- ^^ expected `Example3<7>`, found `()`
| |
| expected due to this
|
@@ -46,7 +46,7 @@ error[E0308]: mismatched types
--> $DIR/mismatch.rs:19:26
|
LL | let e: Example4<7> = ();
- | ----------- ^^ expected struct `Example4`, found `()`
+ | ----------- ^^ expected `Example4<7>`, found `()`
| |
| expected due to this
|
diff --git a/tests/ui/const-generics/defaults/wfness.stderr b/tests/ui/const-generics/defaults/wfness.stderr
index 25038f830..bd9bfcd7d 100644
--- a/tests/ui/const-generics/defaults/wfness.stderr
+++ b/tests/ui/const-generics/defaults/wfness.stderr
@@ -23,7 +23,7 @@ note: required by a bound in `WhereClause`
--> $DIR/wfness.rs:8:9
|
LL | struct WhereClause<const N: u8 = 2>
- | ----------- required by a bound in this
+ | ----------- required by a bound in this struct
LL | where
LL | (): Trait<N>;
| ^^^^^^^^ required by this bound in `WhereClause`
diff --git a/tests/ui/const-generics/early/invalid-const-arguments.stderr b/tests/ui/const-generics/early/invalid-const-arguments.stderr
index b46e7e24f..cee34e3b7 100644
--- a/tests/ui/const-generics/early/invalid-const-arguments.stderr
+++ b/tests/ui/const-generics/early/invalid-const-arguments.stderr
@@ -49,12 +49,9 @@ error[E0747]: type provided when a constant was expected
--> $DIR/invalid-const-arguments.rs:10:19
|
LL | impl<N> Foo for B<N> {}
- | ^
- |
-help: consider changing this type parameter to be a `const` generic
- |
-LL | impl<const N: u8> Foo for B<N> {}
- | ~~~~~~~~~~~
+ | - ^
+ | |
+ | help: consider changing this type parameter to a const parameter: `const N: u8`
error[E0747]: unresolved item provided when a constant was expected
--> $DIR/invalid-const-arguments.rs:14:32
diff --git a/tests/ui/const-generics/ensure_is_evaluatable.stderr b/tests/ui/const-generics/ensure_is_evaluatable.stderr
index bf6c35ad8..ab2871ff2 100644
--- a/tests/ui/const-generics/ensure_is_evaluatable.stderr
+++ b/tests/ui/const-generics/ensure_is_evaluatable.stderr
@@ -9,7 +9,7 @@ note: required by a bound in `bar`
--> $DIR/ensure_is_evaluatable.rs:15:10
|
LL | fn bar<const N: usize>() -> [(); N]
- | --- required by a bound in this
+ | --- required by a bound in this function
LL | where
LL | [(); N + 1]:,
| ^^^^^ required by this bound in `bar`
diff --git a/tests/ui/const-generics/fn_with_two_const_inputs.stderr b/tests/ui/const-generics/fn_with_two_const_inputs.stderr
index 614e7e0d2..c124010aa 100644
--- a/tests/ui/const-generics/fn_with_two_const_inputs.stderr
+++ b/tests/ui/const-generics/fn_with_two_const_inputs.stderr
@@ -9,7 +9,7 @@ note: required by a bound in `bar`
--> $DIR/fn_with_two_const_inputs.rs:18:10
|
LL | fn bar<const N: usize>() -> [(); N]
- | --- required by a bound in this
+ | --- required by a bound in this function
LL | where
LL | [(); N + 1]:,
| ^^^^^ required by this bound in `bar`
diff --git a/tests/ui/const-generics/generic_const_exprs/const_kind_expr/relate_binop_arg_tys.rs b/tests/ui/const-generics/generic_const_exprs/const_kind_expr/relate_binop_arg_tys.rs
new file mode 100644
index 000000000..fd52fc355
--- /dev/null
+++ b/tests/ui/const-generics/generic_const_exprs/const_kind_expr/relate_binop_arg_tys.rs
@@ -0,0 +1,18 @@
+// checks that when we relate a `Expr::Binop` we also relate the types of the
+// const arguments.
+#![feature(generic_const_exprs)]
+#![allow(incomplete_features)]
+
+struct Bar<const B: bool>;
+
+const fn make_generic(_: usize, a: bool) -> bool {
+ a
+}
+
+fn foo<const N: usize>() -> Bar<{ make_generic(N, true == false) }> {
+ Bar::<{ make_generic(N, 1_u8 == 0_u8) }>
+ //~^ error: mismatched types
+ //~| error: unconstrained generic constant
+}
+
+fn main() {}
diff --git a/tests/ui/const-generics/generic_const_exprs/const_kind_expr/relate_binop_arg_tys.stderr b/tests/ui/const-generics/generic_const_exprs/const_kind_expr/relate_binop_arg_tys.stderr
new file mode 100644
index 000000000..ba824e84a
--- /dev/null
+++ b/tests/ui/const-generics/generic_const_exprs/const_kind_expr/relate_binop_arg_tys.stderr
@@ -0,0 +1,20 @@
+error[E0308]: mismatched types
+ --> $DIR/relate_binop_arg_tys.rs:13:5
+ |
+LL | Bar::<{ make_generic(N, 1_u8 == 0_u8) }>
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `{ make_generic(N, true == false) }`, found `{ make_generic(N, 1_u8 == 0_u8) }`
+ |
+ = note: expected constant `{ make_generic(N, true == false) }`
+ found constant `{ make_generic(N, 1_u8 == 0_u8) }`
+
+error: unconstrained generic constant
+ --> $DIR/relate_binop_arg_tys.rs:13:11
+ |
+LL | Bar::<{ make_generic(N, 1_u8 == 0_u8) }>
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = help: try adding a `where` bound using this expression: `where [(); { make_generic(N, 1_u8 == 0_u8) }]:`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/const-generics/generic_const_exprs/const_kind_expr/relate_cast_arg_ty.rs b/tests/ui/const-generics/generic_const_exprs/const_kind_expr/relate_cast_arg_ty.rs
new file mode 100644
index 000000000..bef9d4b9e
--- /dev/null
+++ b/tests/ui/const-generics/generic_const_exprs/const_kind_expr/relate_cast_arg_ty.rs
@@ -0,0 +1,12 @@
+// checks that when we relate a `Expr::Cast` we also relate the type of the
+// const argument.
+#![feature(generic_const_exprs)]
+#![allow(incomplete_features)]
+
+fn foo<const N: usize>() -> [(); (true as usize) + N] {
+ [(); (1_u8 as usize) + N]
+ //~^ error: mismatched types
+ //~| error: unconstrained generic constant
+}
+
+fn main() {}
diff --git a/tests/ui/const-generics/generic_const_exprs/const_kind_expr/relate_cast_arg_ty.stderr b/tests/ui/const-generics/generic_const_exprs/const_kind_expr/relate_cast_arg_ty.stderr
new file mode 100644
index 000000000..d3ba870a2
--- /dev/null
+++ b/tests/ui/const-generics/generic_const_exprs/const_kind_expr/relate_cast_arg_ty.stderr
@@ -0,0 +1,20 @@
+error[E0308]: mismatched types
+ --> $DIR/relate_cast_arg_ty.rs:7:5
+ |
+LL | [(); (1_u8 as usize) + N]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^ expected `(true as usize) + N`, found `(1_u8 as usize) + N`
+ |
+ = note: expected constant `(true as usize) + N`
+ found constant `(1_u8 as usize) + N`
+
+error: unconstrained generic constant
+ --> $DIR/relate_cast_arg_ty.rs:7:10
+ |
+LL | [(); (1_u8 as usize) + N]
+ | ^^^^^^^^^^^^^^^^^^^
+ |
+ = help: try adding a `where` bound using this expression: `where [(); (1_u8 as usize) + N]:`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/const-generics/generic_const_exprs/const_kind_expr/relate_ty_with_infer_1.rs b/tests/ui/const-generics/generic_const_exprs/const_kind_expr/relate_ty_with_infer_1.rs
new file mode 100644
index 000000000..1e2484118
--- /dev/null
+++ b/tests/ui/const-generics/generic_const_exprs/const_kind_expr/relate_ty_with_infer_1.rs
@@ -0,0 +1,30 @@
+// check-pass
+#![feature(generic_const_exprs)]
+#![allow(incomplete_features)]
+
+// issue #107899
+// We end up relating `Const(ty: size_of<?0>, kind: Value(Branch([])))` with
+// `Const(ty: size_of<T>, kind: Value(Branch([])))` which if you were to `==`
+// the `ty` fields would return `false` and ICE. This test checks that we use
+// actual semantic equality that takes into account aliases and infer vars.
+
+use std::mem::size_of;
+
+trait X<T> {
+ fn f(self);
+ fn g(self);
+}
+
+struct Y;
+
+impl<T> X<T> for Y
+where
+ [(); size_of::<T>()]: Sized,
+{
+ fn f(self) {
+ self.g();
+ }
+ fn g(self) {}
+}
+
+fn main() {}
diff --git a/tests/ui/const-generics/generic_const_exprs/const_kind_expr/relate_ty_with_infer_2.rs b/tests/ui/const-generics/generic_const_exprs/const_kind_expr/relate_ty_with_infer_2.rs
new file mode 100644
index 000000000..91a8a7c4a
--- /dev/null
+++ b/tests/ui/const-generics/generic_const_exprs/const_kind_expr/relate_ty_with_infer_2.rs
@@ -0,0 +1,151 @@
+// check-pass
+#![feature(inline_const, generic_const_exprs)]
+#![allow(incomplete_features)]
+use std::marker::PhantomData;
+
+pub struct Equal<const T: usize, const R: usize>();
+pub trait True {}
+impl<const T: usize> True for Equal<T, T> {}
+
+// replacement for generativity
+pub struct Id<'id>(PhantomData<fn(&'id ()) -> &'id ()>);
+pub struct Guard<'id>(Id<'id>);
+fn make_guard<'id>(i: &'id Id<'id>) -> Guard<'id> {
+ Guard(Id(PhantomData))
+}
+
+impl<'id> Into<Id<'id>> for Guard<'id> {
+ fn into(self) -> Id<'id> {
+ self.0
+ }
+}
+
+pub struct Arena<'life> {
+ bytes: *mut [u8],
+ //bitmap: RefCell<RoaringBitmap>,
+ _token: PhantomData<Id<'life>>,
+}
+
+#[repr(transparent)]
+pub struct Item<'life, T> {
+ data: T,
+ _phantom: PhantomData<Id<'life>>,
+}
+
+#[repr(transparent)]
+pub struct Token<'life, 'borrow, 'compact, 'reborrow, T>
+where
+ 'life: 'reborrow,
+ T: Tokenize<'life, 'borrow, 'compact, 'reborrow>,
+{
+ //ptr: *mut <T as Tokenize>::Tokenized,
+ ptr: core::ptr::NonNull<T::Tokenized>,
+ _phantom: PhantomData<Id<'life>>,
+ _compact: PhantomData<&'borrow Guard<'compact>>,
+ _result: PhantomData<&'reborrow T::Untokenized>,
+}
+
+impl<'life> Arena<'life> {
+ pub fn tokenize<'before, 'compact, 'borrow, 'reborrow, T, U>(
+ &self,
+ guard: &'borrow Guard<'compact>,
+ item: Item<'life, &'before mut T>,
+ ) -> Token<'life, 'borrow, 'compact, 'reborrow, U>
+ where
+ T: Tokenize<'life, 'borrow, 'compact, 'reborrow, Untokenized = U>,
+ T::Untokenized: Tokenize<'life, 'borrow, 'compact, 'reborrow>,
+ Equal<{ core::mem::size_of::<T>() }, { core::mem::size_of::<U>() }>: True,
+ 'compact: 'borrow,
+ 'life: 'reborrow,
+ 'life: 'compact,
+ 'life: 'borrow,
+ // 'borrow: 'before ??
+ {
+ let dst = item.data as *mut T as *mut T::Tokenized;
+ Token {
+ ptr: core::ptr::NonNull::new(dst as *mut _).unwrap(),
+ _phantom: PhantomData,
+ _compact: PhantomData,
+ _result: PhantomData,
+ }
+ }
+}
+
+pub trait Tokenize<'life, 'borrow, 'compact, 'reborrow>
+where
+ 'compact: 'borrow,
+ 'life: 'reborrow,
+ 'life: 'borrow,
+ 'life: 'compact,
+{
+ type Tokenized;
+ type Untokenized;
+ const TO: fn(&Arena<'life>, &'borrow Guard<'compact>, Self) -> Self::Tokenized;
+ const FROM: fn(&'reborrow Arena<'life>, Self::Tokenized) -> Self::Untokenized;
+}
+
+macro_rules! tokenize {
+ ($to:expr, $from:expr) => {
+ const TO: fn(&Arena<'life>, &'borrow Guard<'compact>, Self) -> Self::Tokenized = $to;
+ const FROM: fn(&'reborrow Arena<'life>, Self::Tokenized) -> Self::Untokenized = $from;
+ };
+}
+
+struct Foo<'life, 'borrow>(Option<Item<'life, &'borrow mut Bar>>);
+struct TokenFoo<'life, 'borrow, 'compact, 'reborrow>(
+ Option<Token<'life, 'borrow, 'compact, 'reborrow, Bar>>,
+);
+struct Bar(u8);
+
+impl<'life, 'before, 'borrow, 'compact, 'reborrow> Tokenize<'life, 'borrow, 'compact, 'reborrow>
+ for Foo<'life, 'before>
+where
+ 'compact: 'borrow,
+ 'life: 'reborrow,
+ 'life: 'borrow,
+ 'life: 'compact,
+{
+ type Tokenized = TokenFoo<'life, 'borrow, 'compact, 'reborrow>;
+ type Untokenized = Foo<'life, 'reborrow>;
+ tokenize!(foo_to, foo_from);
+}
+
+impl<'life, 'borrow, 'compact, 'reborrow> Tokenize<'life, 'borrow, 'compact, 'reborrow> for Bar
+where
+ 'compact: 'borrow,
+ 'life: 'reborrow,
+ 'life: 'borrow,
+ 'life: 'compact,
+{
+ type Tokenized = Bar;
+ type Untokenized = Bar;
+ tokenize!(bar_to, bar_from);
+}
+
+fn bar_to<'life, 'borrow, 'compact>(
+ arena: &Arena<'life>,
+ guard: &'borrow Guard<'compact>,
+ s: Bar,
+) -> Bar {
+ s
+}
+fn bar_from<'life, 'reborrow>(arena: &'reborrow Arena<'life>, s: Bar) -> Bar {
+ s
+}
+
+fn foo_to<'life, 'borrow, 'compact, 'reborrow, 'before>(
+ arena: &'before Arena<'life>,
+ guard: &'borrow Guard<'compact>,
+ s: Foo<'life, 'before>,
+) -> TokenFoo<'life, 'borrow, 'compact, 'reborrow> {
+ let Foo(bar) = s;
+ TokenFoo(bar.map(|bar| arena.tokenize(guard, bar)))
+}
+fn foo_from<'life, 'borrow, 'compact, 'reborrow>(
+ arena: &'reborrow Arena<'life>,
+ s: TokenFoo<'life, 'borrow, 'compact, 'reborrow>,
+) -> Foo<'life, 'reborrow> {
+ Foo(s.0.map(|bar| panic!()))
+}
+
+fn main() {}
diff --git a/tests/ui/const-generics/generic_const_exprs/issue-102768.rs b/tests/ui/const-generics/generic_const_exprs/issue-102768.rs
index 7aea0d30d..18a9b53cf 100644
--- a/tests/ui/const-generics/generic_const_exprs/issue-102768.rs
+++ b/tests/ui/const-generics/generic_const_exprs/issue-102768.rs
@@ -7,8 +7,8 @@ trait X {
const _: () = {
fn f2<'a>(arg: Box<dyn X<Y<1> = &'a ()>>) {}
- //~^ ERROR this associated type takes 1 lifetime argument but 0 lifetime arguments
- //~| ERROR this associated type takes 0 generic arguments but 1 generic argument
+ //~^ ERROR associated type takes 1 lifetime argument but 0 lifetime arguments
+ //~| ERROR associated type takes 0 generic arguments but 1 generic argument
};
fn main() {}
diff --git a/tests/ui/const-generics/generic_const_exprs/issue-102768.stderr b/tests/ui/const-generics/generic_const_exprs/issue-102768.stderr
index 8278edabe..175d54e41 100644
--- a/tests/ui/const-generics/generic_const_exprs/issue-102768.stderr
+++ b/tests/ui/const-generics/generic_const_exprs/issue-102768.stderr
@@ -1,4 +1,4 @@
-error[E0107]: this associated type takes 1 lifetime argument but 0 lifetime arguments were supplied
+error[E0107]: associated type takes 1 lifetime argument but 0 lifetime arguments were supplied
--> $DIR/issue-102768.rs:9:30
|
LL | fn f2<'a>(arg: Box<dyn X<Y<1> = &'a ()>>) {}
@@ -14,7 +14,7 @@ help: add missing lifetime argument
LL | fn f2<'a>(arg: Box<dyn X<Y<'_, 1> = &'a ()>>) {}
| +++
-error[E0107]: this associated type takes 0 generic arguments but 1 generic argument was supplied
+error[E0107]: associated type takes 0 generic arguments but 1 generic argument was supplied
--> $DIR/issue-102768.rs:9:30
|
LL | fn f2<'a>(arg: Box<dyn X<Y<1> = &'a ()>>) {}
diff --git a/tests/ui/const-generics/generic_const_exprs/issue-105608.stderr b/tests/ui/const-generics/generic_const_exprs/issue-105608.stderr
index 0be4c43da..827dd59d9 100644
--- a/tests/ui/const-generics/generic_const_exprs/issue-105608.stderr
+++ b/tests/ui/const-generics/generic_const_exprs/issue-105608.stderr
@@ -2,7 +2,7 @@ error[E0282]: type annotations needed
--> $DIR/issue-105608.rs:13:22
|
LL | Combination::<0>.and::<_>().and::<_>();
- | ^^^ cannot infer type of the type parameter `M` declared on the associated function `and`
+ | ^^^ cannot infer type of the type parameter `M` declared on the method `and`
|
help: consider specifying the generic argument
|
diff --git a/tests/ui/const-generics/generic_const_exprs/issue-72819-generic-in-const-eval.full.stderr b/tests/ui/const-generics/generic_const_exprs/issue-72819-generic-in-const-eval.full.stderr
index f2fddfbfb..996b75493 100644
--- a/tests/ui/const-generics/generic_const_exprs/issue-72819-generic-in-const-eval.full.stderr
+++ b/tests/ui/const-generics/generic_const_exprs/issue-72819-generic-in-const-eval.full.stderr
@@ -10,7 +10,7 @@ note: required by a bound in `Arr`
--> $DIR/issue-72819-generic-in-const-eval.rs:8:39
|
LL | struct Arr<const N: usize>
- | --- required by a bound in this
+ | --- required by a bound in this struct
LL | where Assert::<{N < usize::MAX / 2}>: IsTrue,
| ^^^^^^ required by this bound in `Arr`
@@ -26,7 +26,7 @@ note: required by a bound in `Arr`
--> $DIR/issue-72819-generic-in-const-eval.rs:8:39
|
LL | struct Arr<const N: usize>
- | --- required by a bound in this
+ | --- required by a bound in this struct
LL | where Assert::<{N < usize::MAX / 2}>: IsTrue,
| ^^^^^^ required by this bound in `Arr`
diff --git a/tests/ui/const-generics/generic_const_exprs/issue-76595.stderr b/tests/ui/const-generics/generic_const_exprs/issue-76595.stderr
index c587a7e15..302da5965 100644
--- a/tests/ui/const-generics/generic_const_exprs/issue-76595.stderr
+++ b/tests/ui/const-generics/generic_const_exprs/issue-76595.stderr
@@ -1,4 +1,4 @@
-error[E0107]: this function takes 2 generic arguments but 1 generic argument was supplied
+error[E0107]: function takes 2 generic arguments but 1 generic argument was supplied
--> $DIR/issue-76595.rs:15:5
|
LL | test::<2>();
diff --git a/tests/ui/const-generics/generic_const_exprs/issue-79518-default_trait_method_normalization.stderr b/tests/ui/const-generics/generic_const_exprs/issue-79518-default_trait_method_normalization.stderr
index 9baf9790e..511ae58a1 100644
--- a/tests/ui/const-generics/generic_const_exprs/issue-79518-default_trait_method_normalization.stderr
+++ b/tests/ui/const-generics/generic_const_exprs/issue-79518-default_trait_method_normalization.stderr
@@ -2,7 +2,7 @@ error[E0308]: mismatched types
--> $DIR/issue-79518-default_trait_method_normalization.rs:16:32
|
LL | Self::AssocInstance == [(); std::mem::size_of::<Self::Assoc>()];
- | ------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected associated type, found array `[(); std::mem::size_of::<Self::Assoc>()]`
+ | ------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected associated type, found `[(); std::mem::size_of::<Self::Assoc>()]`
| |
| expected because this is `<Self as Foo>::Assoc`
|
diff --git a/tests/ui/const-generics/generic_const_exprs/obligation-cause.stderr b/tests/ui/const-generics/generic_const_exprs/obligation-cause.stderr
index a253ec676..63e6fcc8e 100644
--- a/tests/ui/const-generics/generic_const_exprs/obligation-cause.stderr
+++ b/tests/ui/const-generics/generic_const_exprs/obligation-cause.stderr
@@ -10,7 +10,7 @@ note: required by a bound in `g`
--> $DIR/obligation-cause.rs:13:44
|
LL | fn g<T>()
- | - required by a bound in this
+ | - required by a bound in this function
...
LL | Is<{ std::mem::size_of::<T>() == 0 }>: True,
| ^^^^ required by this bound in `g`
diff --git a/tests/ui/const-generics/generic_const_exprs/single-satisfied-ConstEvaluatable-in-probe.rs b/tests/ui/const-generics/generic_const_exprs/single-satisfied-ConstEvaluatable-in-probe.rs
new file mode 100644
index 000000000..0ba0c5a72
--- /dev/null
+++ b/tests/ui/const-generics/generic_const_exprs/single-satisfied-ConstEvaluatable-in-probe.rs
@@ -0,0 +1,39 @@
+// check-pass
+
+#![allow(incomplete_features)]
+#![feature(generic_const_exprs)]
+
+use std::marker::PhantomData;
+
+pub trait Bytes {
+ const BYTES: usize;
+}
+
+#[derive(Clone, Debug)]
+pub struct Conster<OT>
+where
+ OT: Bytes,
+ [(); OT::BYTES]: Sized,
+{
+ _offset_type: PhantomData<fn(OT) -> OT>,
+}
+
+impl<OT> Conster<OT>
+where
+ OT: Bytes,
+ [(); OT::BYTES]: Sized,
+{
+ pub fn new() -> Self {
+ Conster { _offset_type: PhantomData }
+ }
+}
+
+pub fn make_conster<COT>() -> Conster<COT>
+where
+ COT: Bytes,
+ [(); COT::BYTES]: Sized,
+{
+ Conster::new()
+}
+
+fn main() {}
diff --git a/tests/ui/const-generics/incorrect-number-of-const-args.stderr b/tests/ui/const-generics/incorrect-number-of-const-args.stderr
index a845454f7..01ac4e69a 100644
--- a/tests/ui/const-generics/incorrect-number-of-const-args.stderr
+++ b/tests/ui/const-generics/incorrect-number-of-const-args.stderr
@@ -1,4 +1,4 @@
-error[E0107]: this function takes 2 generic arguments but 1 generic argument was supplied
+error[E0107]: function takes 2 generic arguments but 1 generic argument was supplied
--> $DIR/incorrect-number-of-const-args.rs:6:5
|
LL | foo::<0>();
@@ -16,7 +16,7 @@ help: add missing generic argument
LL | foo::<0, Y>();
| +++
-error[E0107]: this function takes 2 generic arguments but 3 generic arguments were supplied
+error[E0107]: function takes 2 generic arguments but 3 generic arguments were supplied
--> $DIR/incorrect-number-of-const-args.rs:9:5
|
LL | foo::<0, 0, 0>();
diff --git a/tests/ui/const-generics/infer/method-chain.stderr b/tests/ui/const-generics/infer/method-chain.stderr
index ff6da535b..f527ee6e4 100644
--- a/tests/ui/const-generics/infer/method-chain.stderr
+++ b/tests/ui/const-generics/infer/method-chain.stderr
@@ -2,7 +2,7 @@ error[E0282]: type annotations needed
--> $DIR/method-chain.rs:15:33
|
LL | Foo.bar().bar().bar().bar().baz();
- | ^^^ cannot infer the value of the const parameter `N` declared on the associated function `baz`
+ | ^^^ cannot infer the value of the const parameter `N` declared on the method `baz`
|
help: consider specifying the generic argument
|
diff --git a/tests/ui/const-generics/infer/uninferred-consts.stderr b/tests/ui/const-generics/infer/uninferred-consts.stderr
index 3980ecea8..20daf4570 100644
--- a/tests/ui/const-generics/infer/uninferred-consts.stderr
+++ b/tests/ui/const-generics/infer/uninferred-consts.stderr
@@ -2,7 +2,7 @@ error[E0282]: type annotations needed
--> $DIR/uninferred-consts.rs:9:9
|
LL | Foo.foo();
- | ^^^ cannot infer the value of the const parameter `A` declared on the associated function `foo`
+ | ^^^ cannot infer the value of the const parameter `A` declared on the method `foo`
|
help: consider specifying the generic arguments
|
diff --git a/tests/ui/const-generics/invalid-const-arg-for-type-param.rs b/tests/ui/const-generics/invalid-const-arg-for-type-param.rs
index 7d4dc98f3..bf10f471d 100644
--- a/tests/ui/const-generics/invalid-const-arg-for-type-param.rs
+++ b/tests/ui/const-generics/invalid-const-arg-for-type-param.rs
@@ -4,11 +4,11 @@ struct S;
fn main() {
let _: u32 = 5i32.try_into::<32>().unwrap();
- //~^ ERROR this associated function takes
+ //~^ ERROR method takes
S.f::<0>();
//~^ ERROR no method named `f`
S::<0>;
- //~^ ERROR this struct takes 0
+ //~^ ERROR struct takes 0
}
diff --git a/tests/ui/const-generics/invalid-const-arg-for-type-param.stderr b/tests/ui/const-generics/invalid-const-arg-for-type-param.stderr
index 8c76ca690..4a649d8a7 100644
--- a/tests/ui/const-generics/invalid-const-arg-for-type-param.stderr
+++ b/tests/ui/const-generics/invalid-const-arg-for-type-param.stderr
@@ -1,4 +1,4 @@
-error[E0107]: this associated function takes 0 generic arguments but 1 generic argument was supplied
+error[E0107]: method takes 0 generic arguments but 1 generic argument was supplied
--> $DIR/invalid-const-arg-for-type-param.rs:6:23
|
LL | let _: u32 = 5i32.try_into::<32>().unwrap();
@@ -23,7 +23,7 @@ LL | struct S;
LL | S.f::<0>();
| ^ method not found in `S`
-error[E0107]: this struct takes 0 generic arguments but 1 generic argument was supplied
+error[E0107]: struct takes 0 generic arguments but 1 generic argument was supplied
--> $DIR/invalid-const-arg-for-type-param.rs:12:5
|
LL | S::<0>;
diff --git a/tests/ui/const-generics/invalid-constant-in-args.rs b/tests/ui/const-generics/invalid-constant-in-args.rs
index 7419d4a25..fd259197d 100644
--- a/tests/ui/const-generics/invalid-constant-in-args.rs
+++ b/tests/ui/const-generics/invalid-constant-in-args.rs
@@ -2,5 +2,5 @@ use std::cell::Cell;
fn main() {
let _: Cell<&str, "a"> = Cell::new("");
- //~^ ERROR this struct takes 1 generic argument but 2 generic arguments were supplied
+ //~^ ERROR struct takes 1 generic argument but 2 generic arguments were supplied
}
diff --git a/tests/ui/const-generics/invalid-constant-in-args.stderr b/tests/ui/const-generics/invalid-constant-in-args.stderr
index 993b63518..2545cc6f3 100644
--- a/tests/ui/const-generics/invalid-constant-in-args.stderr
+++ b/tests/ui/const-generics/invalid-constant-in-args.stderr
@@ -1,4 +1,4 @@
-error[E0107]: this struct takes 1 generic argument but 2 generic arguments were supplied
+error[E0107]: struct takes 1 generic argument but 2 generic arguments were supplied
--> $DIR/invalid-constant-in-args.rs:4:12
|
LL | let _: Cell<&str, "a"> = Cell::new("");
diff --git a/tests/ui/const-generics/issues/issue-105821.rs b/tests/ui/const-generics/issues/issue-105821.rs
new file mode 100644
index 000000000..cba2e22c4
--- /dev/null
+++ b/tests/ui/const-generics/issues/issue-105821.rs
@@ -0,0 +1,23 @@
+// check-pass
+
+#![allow(incomplete_features)]
+#![feature(adt_const_params, const_ptr_read, generic_const_exprs)]
+#![allow(dead_code)]
+
+const fn catone<const M: usize>(_a: &[u8; M]) -> [u8; M + 1]
+where
+ [(); M + 1]:,
+{
+ unimplemented!()
+}
+
+struct Catter<const A: &'static [u8]>;
+impl<const A: &'static [u8]> Catter<A>
+where
+ [(); A.len() + 1]:,
+{
+ const ZEROS: &'static [u8; A.len()] = &[0_u8; A.len()];
+ const R: &'static [u8] = &catone(Self::ZEROS);
+}
+
+fn main() {}
diff --git a/tests/ui/const-generics/issues/issue-56445-1.min.stderr b/tests/ui/const-generics/issues/issue-56445-1.min.stderr
index 43a5df117..9f8801341 100644
--- a/tests/ui/const-generics/issues/issue-56445-1.min.stderr
+++ b/tests/ui/const-generics/issues/issue-56445-1.min.stderr
@@ -6,7 +6,7 @@ LL | struct Bug<'a, const S: &'a str>(PhantomData<&'a ()>);
|
= note: for more information, see issue #74052 <https://github.com/rust-lang/rust/issues/74052>
-error: `&'static str` is forbidden as the type of a const generic parameter
+error: `&str` is forbidden as the type of a const generic parameter
--> $DIR/issue-56445-1.rs:9:25
|
LL | struct Bug<'a, const S: &'a str>(PhantomData<&'a ()>);
diff --git a/tests/ui/const-generics/issues/issue-56445-1.rs b/tests/ui/const-generics/issues/issue-56445-1.rs
index 13eb2ea9f..0741c3796 100644
--- a/tests/ui/const-generics/issues/issue-56445-1.rs
+++ b/tests/ui/const-generics/issues/issue-56445-1.rs
@@ -8,6 +8,6 @@ use std::marker::PhantomData;
struct Bug<'a, const S: &'a str>(PhantomData<&'a ()>);
//~^ ERROR: use of non-static lifetime `'a` in const generic
-//[min]~| ERROR: `&'static str` is forbidden as the type of a const generic parameter
+//[min]~| ERROR: `&str` is forbidden as the type of a const generic parameter
impl Bug<'_, ""> {}
diff --git a/tests/ui/const-generics/issues/issue-67185-2.stderr b/tests/ui/const-generics/issues/issue-67185-2.stderr
index c7be8e14a..032b0c410 100644
--- a/tests/ui/const-generics/issues/issue-67185-2.stderr
+++ b/tests/ui/const-generics/issues/issue-67185-2.stderr
@@ -35,7 +35,7 @@ note: required by a bound in `Foo`
--> $DIR/issue-67185-2.rs:15:25
|
LL | trait Foo
- | --- required by a bound in this
+ | --- required by a bound in this trait
...
LL | <u8 as Baz>::Quaks: Bar,
| ^^^ required by this bound in `Foo`
@@ -53,7 +53,7 @@ note: required by a bound in `Foo`
--> $DIR/issue-67185-2.rs:14:30
|
LL | trait Foo
- | --- required by a bound in this
+ | --- required by a bound in this trait
LL | where
LL | [<u8 as Baz>::Quaks; 2]: Bar,
| ^^^ required by this bound in `Foo`
@@ -71,7 +71,7 @@ note: required by a bound in `Foo`
--> $DIR/issue-67185-2.rs:14:30
|
LL | trait Foo
- | --- required by a bound in this
+ | --- required by a bound in this trait
LL | where
LL | [<u8 as Baz>::Quaks; 2]: Bar,
| ^^^ required by this bound in `Foo`
@@ -89,7 +89,7 @@ note: required by a bound in `Foo`
--> $DIR/issue-67185-2.rs:15:25
|
LL | trait Foo
- | --- required by a bound in this
+ | --- required by a bound in this trait
...
LL | <u8 as Baz>::Quaks: Bar,
| ^^^ required by this bound in `Foo`
diff --git a/tests/ui/const-generics/issues/issue-67945-1.full.stderr b/tests/ui/const-generics/issues/issue-67945-1.full.stderr
index 8e18fcdff..8879aec35 100644
--- a/tests/ui/const-generics/issues/issue-67945-1.full.stderr
+++ b/tests/ui/const-generics/issues/issue-67945-1.full.stderr
@@ -5,7 +5,7 @@ LL | struct Bug<S> {
| - this type parameter
...
LL | let x: S = MaybeUninit::uninit();
- | - ^^^^^^^^^^^^^^^^^^^^^ expected type parameter `S`, found union `MaybeUninit`
+ | - ^^^^^^^^^^^^^^^^^^^^^ expected type parameter `S`, found `MaybeUninit<_>`
| |
| expected due to this
|
diff --git a/tests/ui/const-generics/issues/issue-73260.rs b/tests/ui/const-generics/issues/issue-73260.rs
index d762f9c8b..aa7ae90a3 100644
--- a/tests/ui/const-generics/issues/issue-73260.rs
+++ b/tests/ui/const-generics/issues/issue-73260.rs
@@ -1,4 +1,3 @@
-// compile-flags: -Zsave-analysis
#![feature(generic_const_exprs)]
#![allow(incomplete_features)]
struct Arr<const N: usize>
diff --git a/tests/ui/const-generics/issues/issue-73260.stderr b/tests/ui/const-generics/issues/issue-73260.stderr
index 7670032e5..c56b45cc8 100644
--- a/tests/ui/const-generics/issues/issue-73260.stderr
+++ b/tests/ui/const-generics/issues/issue-73260.stderr
@@ -1,5 +1,5 @@
error[E0308]: mismatched types
- --> $DIR/issue-73260.rs:16:12
+ --> $DIR/issue-73260.rs:15:12
|
LL | let x: Arr<{usize::MAX}> = Arr {};
| ^^^^^^^^^^^^^^^^^ expected `false`, found `true`
@@ -7,16 +7,16 @@ LL | let x: Arr<{usize::MAX}> = Arr {};
= note: expected constant `false`
found constant `true`
note: required by a bound in `Arr`
- --> $DIR/issue-73260.rs:6:37
+ --> $DIR/issue-73260.rs:5:37
|
LL | struct Arr<const N: usize>
- | --- required by a bound in this
+ | --- required by a bound in this struct
LL | where
LL | Assert::<{N < usize::MAX / 2}>: IsTrue,
| ^^^^^^ required by this bound in `Arr`
error[E0308]: mismatched types
- --> $DIR/issue-73260.rs:16:32
+ --> $DIR/issue-73260.rs:15:32
|
LL | let x: Arr<{usize::MAX}> = Arr {};
| ^^^ expected `false`, found `true`
@@ -24,10 +24,10 @@ LL | let x: Arr<{usize::MAX}> = Arr {};
= note: expected constant `false`
found constant `true`
note: required by a bound in `Arr`
- --> $DIR/issue-73260.rs:6:37
+ --> $DIR/issue-73260.rs:5:37
|
LL | struct Arr<const N: usize>
- | --- required by a bound in this
+ | --- required by a bound in this struct
LL | where
LL | Assert::<{N < usize::MAX / 2}>: IsTrue,
| ^^^^^^ required by this bound in `Arr`
diff --git a/tests/ui/const-generics/issues/issue-79674.stderr b/tests/ui/const-generics/issues/issue-79674.stderr
index 02b48b55f..ba7fd2ca3 100644
--- a/tests/ui/const-generics/issues/issue-79674.stderr
+++ b/tests/ui/const-generics/issues/issue-79674.stderr
@@ -10,7 +10,7 @@ note: required by a bound in `requires_distinct`
--> $DIR/issue-79674.rs:23:37
|
LL | fn requires_distinct<A, B>(_a: A, _b: B) where
- | ----------------- required by a bound in this
+ | ----------------- required by a bound in this function
LL | A: MiniTypeId, B: MiniTypeId,
LL | Lift<{is_same_type::<A, B>()}>: IsFalse {}
| ^^^^^^^ required by this bound in `requires_distinct`
diff --git a/tests/ui/const-generics/issues/issue-86530.stderr b/tests/ui/const-generics/issues/issue-86530.stderr
index c63857b23..620ed4f0f 100644
--- a/tests/ui/const-generics/issues/issue-86530.stderr
+++ b/tests/ui/const-generics/issues/issue-86530.stderr
@@ -10,7 +10,7 @@ note: required by a bound in `z`
--> $DIR/issue-86530.rs:10:8
|
LL | fn z<T>(t: T)
- | - required by a bound in this
+ | - required by a bound in this function
LL | where
LL | T: X,
| ^ required by this bound in `z`
diff --git a/tests/ui/const-generics/issues/issue-87493.rs b/tests/ui/const-generics/issues/issue-87493.rs
index d8599ab22..80472e6bd 100644
--- a/tests/ui/const-generics/issues/issue-87493.rs
+++ b/tests/ui/const-generics/issues/issue-87493.rs
@@ -7,7 +7,7 @@ where
S: MyTrait,
T: MyTrait<Assoc == S::Assoc>,
//~^ ERROR: expected one of `,` or `>`, found `==`
- //~| ERROR: this trait takes 0 generic arguments but 1 generic argument was supplied
+ //~| ERROR: trait takes 0 generic arguments but 1 generic argument was supplied
{
}
diff --git a/tests/ui/const-generics/issues/issue-87493.stderr b/tests/ui/const-generics/issues/issue-87493.stderr
index 653afae21..73bd6ed73 100644
--- a/tests/ui/const-generics/issues/issue-87493.stderr
+++ b/tests/ui/const-generics/issues/issue-87493.stderr
@@ -9,7 +9,7 @@ help: if you meant to use an associated type binding, replace `==` with `=`
LL | T: MyTrait<Assoc = S::Assoc>,
| ~
-error[E0107]: this trait takes 0 generic arguments but 1 generic argument was supplied
+error[E0107]: trait takes 0 generic arguments but 1 generic argument was supplied
--> $DIR/issue-87493.rs:8:8
|
LL | T: MyTrait<Assoc == S::Assoc>,
diff --git a/tests/ui/const-generics/min_const_generics/macro-fail.stderr b/tests/ui/const-generics/min_const_generics/macro-fail.stderr
index 9f73b91aa..cc629fd92 100644
--- a/tests/ui/const-generics/min_const_generics/macro-fail.stderr
+++ b/tests/ui/const-generics/min_const_generics/macro-fail.stderr
@@ -8,7 +8,7 @@ LL | fn make_marker() -> impl Marker<gimme_a_const!(marker)> {
| in this macro invocation
...
LL | ($rusty: ident) => {{ let $rusty = 3; *&$rusty }}
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected type
+ | ^ expected type
|
= note: this error originates in the macro `gimme_a_const` (in Nightly builds, run with -Z macro-backtrace for more info)
@@ -22,26 +22,21 @@ LL | Example::<gimme_a_const!(marker)>
| in this macro invocation
...
LL | ($rusty: ident) => {{ let $rusty = 3; *&$rusty }}
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected type
+ | ^ expected type
|
= note: this error originates in the macro `gimme_a_const` (in Nightly builds, run with -Z macro-backtrace for more info)
error: expected type, found `{`
--> $DIR/macro-fail.rs:4:10
|
-LL | () => {{
- | __________^
-LL | |
-LL | | const X: usize = 1337;
-LL | | X
-LL | | }}
- | |___^ expected type
+LL | () => {{
+ | ^ expected type
...
-LL | let _fail = Example::<external_macro!()>;
- | -----------------
- | |
- | this macro call doesn't expand to a type
- | in this macro invocation
+LL | let _fail = Example::<external_macro!()>;
+ | -----------------
+ | |
+ | this macro call doesn't expand to a type
+ | in this macro invocation
|
= note: this error originates in the macro `external_macro` (in Nightly builds, run with -Z macro-backtrace for more info)
diff --git a/tests/ui/const-generics/nested-type.min.stderr b/tests/ui/const-generics/nested-type.min.stderr
index cff02b0d4..257a9e31e 100644
--- a/tests/ui/const-generics/nested-type.min.stderr
+++ b/tests/ui/const-generics/nested-type.min.stderr
@@ -1,3 +1,11 @@
+error[E0015]: cannot call non-const fn `Foo::{constant#0}::Foo::<17>::value` in constants
+ --> $DIR/nested-type.rs:15:5
+ |
+LL | Foo::<17>::value()
+ | ^^^^^^^^^^^^^^^^^^
+ |
+ = note: calls in constants are limited to constant functions, tuple structs and tuple variants
+
error: `[u8; {
struct Foo<const N: usize>;
@@ -24,5 +32,6 @@ LL | | }]>;
= note: the only supported types are integers, `bool` and `char`
= help: more complex types are supported with `#![feature(adt_const_params)]`
-error: aborting due to previous error
+error: aborting due to 2 previous errors
+For more information about this error, try `rustc --explain E0015`.
diff --git a/tests/ui/const-generics/nested-type.rs b/tests/ui/const-generics/nested-type.rs
index 742340f43..5240f5c3b 100644
--- a/tests/ui/const-generics/nested-type.rs
+++ b/tests/ui/const-generics/nested-type.rs
@@ -13,7 +13,7 @@ struct Foo<const N: [u8; { //[min]~ ERROR `[u8; _]` is forbidden
}
Foo::<17>::value()
- //[full]~^ ERROR cannot call non-const fn
+ //~^ ERROR cannot call non-const fn
}]>;
fn main() {}
diff --git a/tests/ui/const-generics/occurs-check/unused-substs-1.stderr b/tests/ui/const-generics/occurs-check/unused-substs-1.stderr
index a3c011d92..51ef354e3 100644
--- a/tests/ui/const-generics/occurs-check/unused-substs-1.stderr
+++ b/tests/ui/const-generics/occurs-check/unused-substs-1.stderr
@@ -9,7 +9,7 @@ note: required by a bound in `A`
--> $DIR/unused-substs-1.rs:9:11
|
LL | struct A<const N: usize>
- | - required by a bound in this
+ | - required by a bound in this unit struct
LL | where
LL | A<N>: Bar<N>;
| ^^^^^^ required by this bound in `A`
diff --git a/tests/ui/const-generics/parser-error-recovery/issue-89013-no-kw.rs b/tests/ui/const-generics/parser-error-recovery/issue-89013-no-kw.rs
index b126b2485..79743abe4 100644
--- a/tests/ui/const-generics/parser-error-recovery/issue-89013-no-kw.rs
+++ b/tests/ui/const-generics/parser-error-recovery/issue-89013-no-kw.rs
@@ -7,7 +7,7 @@ struct Bar;
const T: usize = 42;
impl Foo<N = 3> for Bar {
-//~^ ERROR this trait takes 1 generic argument but 0 generic arguments were supplied
+//~^ ERROR trait takes 1 generic argument but 0 generic arguments were supplied
//~| ERROR associated type bindings are not allowed here
//~| ERROR associated const equality is incomplete
fn do_x(&self) -> [u8; 3] {
diff --git a/tests/ui/const-generics/parser-error-recovery/issue-89013-no-kw.stderr b/tests/ui/const-generics/parser-error-recovery/issue-89013-no-kw.stderr
index acfdde8e1..4f4e1aa3a 100644
--- a/tests/ui/const-generics/parser-error-recovery/issue-89013-no-kw.stderr
+++ b/tests/ui/const-generics/parser-error-recovery/issue-89013-no-kw.stderr
@@ -7,7 +7,7 @@ LL | impl Foo<N = 3> for Bar {
= note: see issue #92827 <https://github.com/rust-lang/rust/issues/92827> for more information
= help: add `#![feature(associated_const_equality)]` to the crate attributes to enable
-error[E0107]: this trait takes 1 generic argument but 0 generic arguments were supplied
+error[E0107]: trait takes 1 generic argument but 0 generic arguments were supplied
--> $DIR/issue-89013-no-kw.rs:9:6
|
LL | impl Foo<N = 3> for Bar {
diff --git a/tests/ui/const-generics/parser-error-recovery/issue-89013.rs b/tests/ui/const-generics/parser-error-recovery/issue-89013.rs
index 9431779fa..335d0d94e 100644
--- a/tests/ui/const-generics/parser-error-recovery/issue-89013.rs
+++ b/tests/ui/const-generics/parser-error-recovery/issue-89013.rs
@@ -8,7 +8,7 @@ const T: usize = 42;
impl Foo<N = const 3> for Bar {
//~^ ERROR expected lifetime, type, or constant, found keyword `const`
-//~| ERROR this trait takes 1 generic
+//~| ERROR trait takes 1 generic
//~| ERROR associated type bindings are not allowed here
//~| ERROR associated const equality is incomplete
fn do_x(&self) -> [u8; 3] {
diff --git a/tests/ui/const-generics/parser-error-recovery/issue-89013.stderr b/tests/ui/const-generics/parser-error-recovery/issue-89013.stderr
index 583749a85..3d2b98feb 100644
--- a/tests/ui/const-generics/parser-error-recovery/issue-89013.stderr
+++ b/tests/ui/const-generics/parser-error-recovery/issue-89013.stderr
@@ -19,7 +19,7 @@ LL | impl Foo<N = const 3> for Bar {
= note: see issue #92827 <https://github.com/rust-lang/rust/issues/92827> for more information
= help: add `#![feature(associated_const_equality)]` to the crate attributes to enable
-error[E0107]: this trait takes 1 generic argument but 0 generic arguments were supplied
+error[E0107]: trait takes 1 generic argument but 0 generic arguments were supplied
--> $DIR/issue-89013.rs:9:6
|
LL | impl Foo<N = const 3> for Bar {
diff --git a/tests/ui/const-generics/type_mismatch.stderr b/tests/ui/const-generics/type_mismatch.stderr
index 8d779bee2..b28ae8f7e 100644
--- a/tests/ui/const-generics/type_mismatch.stderr
+++ b/tests/ui/const-generics/type_mismatch.stderr
@@ -8,7 +8,7 @@ error[E0308]: mismatched types
--> $DIR/type_mismatch.rs:5:26
|
LL | fn bar<const N: u8>() -> [u8; N] {}
- | --- ^^^^^^^ expected array `[u8; N]`, found `()`
+ | --- ^^^^^^^ expected `[u8; N]`, found `()`
| |
| implicitly returns `()` as its body has no tail or `return` expression
diff --git a/tests/ui/const-generics/type_not_in_scope.stderr b/tests/ui/const-generics/type_not_in_scope.stderr
index 16796acb3..5f45550a6 100644
--- a/tests/ui/const-generics/type_not_in_scope.stderr
+++ b/tests/ui/const-generics/type_not_in_scope.stderr
@@ -14,7 +14,7 @@ error[E0308]: mismatched types
--> $DIR/type_not_in_scope.rs:7:33
|
LL | fn getn<const N: cfg_attr>() -> [u8; N] {}
- | ---- ^^^^^^^ expected array `[u8; N]`, found `()`
+ | ---- ^^^^^^^ expected `[u8; N]`, found `()`
| |
| implicitly returns `()` as its body has no tail or `return` expression
diff --git a/tests/ui/const-generics/types-mismatch-const-args.full.stderr b/tests/ui/const-generics/types-mismatch-const-args.full.stderr
index b6a22df74..13cd5d17d 100644
--- a/tests/ui/const-generics/types-mismatch-const-args.full.stderr
+++ b/tests/ui/const-generics/types-mismatch-const-args.full.stderr
@@ -11,7 +11,7 @@ error[E0308]: mismatched types
--> $DIR/types-mismatch-const-args.rs:16:41
|
LL | let _: A<'a, u16, {2u32}, {3u32}> = A::<'b, u32, {2u32}, {3u32}> { data: PhantomData };
- | -------------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `u16`, found `u32`
+ | -------------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `A<'_, u16, 2, 3>`, found `A<'_, u32, 2, 3>`
| |
| expected due to this
|
@@ -22,7 +22,7 @@ error[E0308]: mismatched types
--> $DIR/types-mismatch-const-args.rs:18:41
|
LL | let _: A<'a, u16, {4u32}, {3u32}> = A::<'b, u32, {2u32}, {3u32}> { data: PhantomData };
- | -------------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `u16`, found `u32`
+ | -------------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `A<'_, u16, 4, 3>`, found `A<'_, u32, 2, 3>`
| |
| expected due to this
|
diff --git a/tests/ui/const-generics/types-mismatch-const-args.min.stderr b/tests/ui/const-generics/types-mismatch-const-args.min.stderr
index 6ac93a08d..cae3adfa1 100644
--- a/tests/ui/const-generics/types-mismatch-const-args.min.stderr
+++ b/tests/ui/const-generics/types-mismatch-const-args.min.stderr
@@ -13,7 +13,7 @@ error[E0308]: mismatched types
--> $DIR/types-mismatch-const-args.rs:16:41
|
LL | let _: A<'a, u16, {2u32}, {3u32}> = A::<'b, u32, {2u32}, {3u32}> { data: PhantomData };
- | -------------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `u16`, found `u32`
+ | -------------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `A<'_, u16, 2, 3>`, found `A<'_, u32, 2, 3>`
| |
| expected due to this
|
@@ -24,7 +24,7 @@ error[E0308]: mismatched types
--> $DIR/types-mismatch-const-args.rs:18:41
|
LL | let _: A<'a, u16, {4u32}, {3u32}> = A::<'b, u32, {2u32}, {3u32}> { data: PhantomData };
- | -------------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `u16`, found `u32`
+ | -------------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `A<'_, u16, 4, 3>`, found `A<'_, u32, 2, 3>`
| |
| expected due to this
|
diff --git a/tests/ui/const-generics/unify_with_nested_expr.stderr b/tests/ui/const-generics/unify_with_nested_expr.stderr
index 8bab0dff7..d4d78b596 100644
--- a/tests/ui/const-generics/unify_with_nested_expr.stderr
+++ b/tests/ui/const-generics/unify_with_nested_expr.stderr
@@ -8,7 +8,7 @@ note: required by a bound in `bar`
--> $DIR/unify_with_nested_expr.rs:14:10
|
LL | fn bar<const N: usize>()
- | --- required by a bound in this
+ | --- required by a bound in this function
LL | where
LL | [(); N + 1]:,
| ^^^^^ required by this bound in `bar`
diff --git a/tests/ui/const-generics/wrong-normalization.rs b/tests/ui/const-generics/wrong-normalization.rs
new file mode 100644
index 000000000..f1ce317b3
--- /dev/null
+++ b/tests/ui/const-generics/wrong-normalization.rs
@@ -0,0 +1,19 @@
+// This test ensures that if implementation on projections is supported,
+// it doesn't end in very weird cycle error.
+
+#![crate_type = "lib"]
+
+pub trait Identity {
+ type Identity: ?Sized;
+}
+
+impl<T: ?Sized> Identity for T {
+ type Identity = Self;
+}
+
+pub struct I8<const F: i8>;
+
+impl <I8<{i8::MIN}> as Identity>::Identity {
+//~^ ERROR no nominal type found for inherent implementation
+ pub fn foo(&self) {}
+}
diff --git a/tests/ui/const-generics/wrong-normalization.stderr b/tests/ui/const-generics/wrong-normalization.stderr
new file mode 100644
index 000000000..658a84066
--- /dev/null
+++ b/tests/ui/const-generics/wrong-normalization.stderr
@@ -0,0 +1,11 @@
+error[E0118]: no nominal type found for inherent implementation
+ --> $DIR/wrong-normalization.rs:16:1
+ |
+LL | impl <I8<{i8::MIN}> as Identity>::Identity {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl requires a nominal type
+ |
+ = note: either implement a trait on it or create a newtype to wrap it instead
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0118`.
diff --git a/tests/ui/constructor-lifetime-args.rs b/tests/ui/constructor-lifetime-args.rs
index a824a44c9..f5802e7d8 100644
--- a/tests/ui/constructor-lifetime-args.rs
+++ b/tests/ui/constructor-lifetime-args.rs
@@ -15,12 +15,12 @@ enum E<'a, 'b> {
fn main() {
S(&0, &0); // OK
S::<'static>(&0, &0);
- //~^ ERROR this struct takes 2 lifetime arguments
+ //~^ ERROR struct takes 2 lifetime arguments
S::<'static, 'static, 'static>(&0, &0);
- //~^ ERROR this struct takes 2 lifetime arguments
+ //~^ ERROR struct takes 2 lifetime arguments
E::V(&0); // OK
E::V::<'static>(&0);
- //~^ ERROR this enum takes 2 lifetime arguments
+ //~^ ERROR enum takes 2 lifetime arguments
E::V::<'static, 'static, 'static>(&0);
- //~^ ERROR this enum takes 2 lifetime arguments
+ //~^ ERROR enum takes 2 lifetime arguments
}
diff --git a/tests/ui/constructor-lifetime-args.stderr b/tests/ui/constructor-lifetime-args.stderr
index bc1141b16..a18123fe1 100644
--- a/tests/ui/constructor-lifetime-args.stderr
+++ b/tests/ui/constructor-lifetime-args.stderr
@@ -1,4 +1,4 @@
-error[E0107]: this struct takes 2 lifetime arguments but 1 lifetime argument was supplied
+error[E0107]: struct takes 2 lifetime arguments but 1 lifetime argument was supplied
--> $DIR/constructor-lifetime-args.rs:17:5
|
LL | S::<'static>(&0, &0);
@@ -16,7 +16,7 @@ help: add missing lifetime argument
LL | S::<'static, 'static>(&0, &0);
| +++++++++
-error[E0107]: this struct takes 2 lifetime arguments but 3 lifetime arguments were supplied
+error[E0107]: struct takes 2 lifetime arguments but 3 lifetime arguments were supplied
--> $DIR/constructor-lifetime-args.rs:19:5
|
LL | S::<'static, 'static, 'static>(&0, &0);
@@ -30,7 +30,7 @@ note: struct defined here, with 2 lifetime parameters: `'a`, `'b`
LL | struct S<'a, 'b>(&'a u8, &'b u8);
| ^ -- --
-error[E0107]: this enum takes 2 lifetime arguments but 1 lifetime argument was supplied
+error[E0107]: enum takes 2 lifetime arguments but 1 lifetime argument was supplied
--> $DIR/constructor-lifetime-args.rs:22:8
|
LL | E::V::<'static>(&0);
@@ -48,7 +48,7 @@ help: add missing lifetime argument
LL | E::V::<'static, 'static>(&0);
| +++++++++
-error[E0107]: this enum takes 2 lifetime arguments but 3 lifetime arguments were supplied
+error[E0107]: enum takes 2 lifetime arguments but 3 lifetime arguments were supplied
--> $DIR/constructor-lifetime-args.rs:24:8
|
LL | E::V::<'static, 'static, 'static>(&0);
diff --git a/tests/ui/consts/array-literal-len-mismatch.rs b/tests/ui/consts/array-literal-len-mismatch.rs
new file mode 100644
index 000000000..b30ff61a9
--- /dev/null
+++ b/tests/ui/consts/array-literal-len-mismatch.rs
@@ -0,0 +1,4 @@
+const NUMBERS: [u8; 3] = [10, 20];
+//~^ ERROR mismatched types
+//~^^ HELP consider specifying the actual array length
+fn main() {}
diff --git a/tests/ui/consts/array-literal-len-mismatch.stderr b/tests/ui/consts/array-literal-len-mismatch.stderr
new file mode 100644
index 000000000..22fec6389
--- /dev/null
+++ b/tests/ui/consts/array-literal-len-mismatch.stderr
@@ -0,0 +1,11 @@
+error[E0308]: mismatched types
+ --> $DIR/array-literal-len-mismatch.rs:1:26
+ |
+LL | const NUMBERS: [u8; 3] = [10, 20];
+ | - ^^^^^^^^ expected an array with a fixed size of 3 elements, found one with 2 elements
+ | |
+ | help: consider specifying the actual array length: `2`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/consts/const-array-oob-arith.stderr b/tests/ui/consts/const-array-oob-arith.stderr
index f7a55d3ca..029d94273 100644
--- a/tests/ui/consts/const-array-oob-arith.stderr
+++ b/tests/ui/consts/const-array-oob-arith.stderr
@@ -2,13 +2,17 @@ error[E0308]: mismatched types
--> $DIR/const-array-oob-arith.rs:5:45
|
LL | const BLUB: [i32; (ARR[0] - 40) as usize] = [5];
- | ^^^ expected an array with a fixed size of 2 elements, found one with 1 element
+ | ---------------------- ^^^ expected an array with a fixed size of 2 elements, found one with 1 element
+ | |
+ | help: consider specifying the actual array length: `1`
error[E0308]: mismatched types
--> $DIR/const-array-oob-arith.rs:8:44
|
LL | const BOO: [i32; (ARR[0] - 41) as usize] = [5, 99];
- | ^^^^^^^ expected an array with a fixed size of 1 element, found one with 2 elements
+ | ---------------------- ^^^^^^^ expected an array with a fixed size of 1 element, found one with 2 elements
+ | |
+ | help: consider specifying the actual array length: `2`
error: aborting due to 2 previous errors
diff --git a/tests/ui/consts/const-err-late.stderr b/tests/ui/consts/const-err-late.stderr
index c5c668189..cb0cab244 100644
--- a/tests/ui/consts/const-err-late.stderr
+++ b/tests/ui/consts/const-err-late.stderr
@@ -29,23 +29,11 @@ LL | black_box((S::<i32>::FOO, S::<u32>::FOO));
| ^^^^^^^^^^^^^
note: erroneous constant used
- --> $DIR/const-err-late.rs:19:31
- |
-LL | black_box((S::<i32>::FOO, S::<u32>::FOO));
- | ^^^^^^^^^^^^^
-
-note: erroneous constant used
--> $DIR/const-err-late.rs:19:16
|
LL | black_box((S::<i32>::FOO, S::<u32>::FOO));
| ^^^^^^^^^^^^^
-note: erroneous constant used
- --> $DIR/const-err-late.rs:19:31
- |
-LL | black_box((S::<i32>::FOO, S::<u32>::FOO));
- | ^^^^^^^^^^^^^
-
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0080`.
diff --git a/tests/ui/consts/const-eval/const-eval-query-stack.rs b/tests/ui/consts/const-eval/const-eval-query-stack.rs
index 8f8a8cee3..81f28c175 100644
--- a/tests/ui/consts/const-eval/const-eval-query-stack.rs
+++ b/tests/ui/consts/const-eval/const-eval-query-stack.rs
@@ -1,8 +1,7 @@
// compile-flags: -Ztreat-err-as-bug=1
// failure-status: 101
// rustc-env:RUST_BACKTRACE=1
-// normalize-stderr-test "\nerror: internal compiler error.*\n\n" -> ""
-// normalize-stderr-test "note:.*unexpectedly panicked.*\n\n" -> ""
+// normalize-stderr-test "\nerror: .*unexpectedly panicked.*\n\n" -> ""
// normalize-stderr-test "note: we would appreciate a bug report.*\n\n" -> ""
// normalize-stderr-test "note: compiler flags.*\n\n" -> ""
// normalize-stderr-test "note: rustc.*running on.*\n\n" -> ""
diff --git a/tests/ui/consts/const-eval/const-eval-query-stack.stderr b/tests/ui/consts/const-eval/const-eval-query-stack.stderr
index b97975c4c..01fb8153c 100644
--- a/tests/ui/consts/const-eval/const-eval-query-stack.stderr
+++ b/tests/ui/consts/const-eval/const-eval-query-stack.stderr
@@ -1,5 +1,5 @@
error[E0080]: evaluation of constant value failed
- --> $DIR/const-eval-query-stack.rs:17:16
+ --> $DIR/const-eval-query-stack.rs:16:16
|
LL | const X: i32 = 1 / 0;
| ^^^^^ attempt to divide `1_i32` by zero
diff --git a/tests/ui/consts/const-eval/const-eval-span.rs b/tests/ui/consts/const-eval/const-eval-span.rs
index 82f101b47..1667c77d1 100644
--- a/tests/ui/consts/const-eval/const-eval-span.rs
+++ b/tests/ui/consts/const-eval/const-eval-span.rs
@@ -8,7 +8,7 @@ const CONSTANT: S = S(0);
enum E {
V = CONSTANT,
//~^ ERROR mismatched types
- //~| expected `isize`, found struct `S`
+ //~| expected `isize`, found `S`
}
fn main() {}
diff --git a/tests/ui/consts/const-eval/const-eval-span.stderr b/tests/ui/consts/const-eval/const-eval-span.stderr
index c5b001899..fe33ad490 100644
--- a/tests/ui/consts/const-eval/const-eval-span.stderr
+++ b/tests/ui/consts/const-eval/const-eval-span.stderr
@@ -2,7 +2,7 @@ error[E0308]: mismatched types
--> $DIR/const-eval-span.rs:9:9
|
LL | V = CONSTANT,
- | ^^^^^^^^ expected `isize`, found struct `S`
+ | ^^^^^^^^ expected `isize`, found `S`
error: aborting due to previous error
diff --git a/tests/ui/consts/const-eval/infinite_loop.stderr b/tests/ui/consts/const-eval/infinite_loop.stderr
index 8b58cb279..f30bfaf3f 100644
--- a/tests/ui/consts/const-eval/infinite_loop.stderr
+++ b/tests/ui/consts/const-eval/infinite_loop.stderr
@@ -1,8 +1,11 @@
error[E0080]: evaluation of constant value failed
- --> $DIR/infinite_loop.rs:6:15
+ --> $DIR/infinite_loop.rs:6:9
|
-LL | while n != 0 {
- | ^^^^^^ exceeded interpreter step limit (see `#[const_eval_limit]`)
+LL | / while n != 0 {
+LL | |
+LL | | n = if n % 2 == 0 { n/2 } else { 3*n + 1 };
+LL | | }
+ | |_________^ exceeded interpreter step limit (see `#[const_eval_limit]`)
error: aborting due to previous error
diff --git a/tests/ui/consts/const-eval/issue-52475.rs b/tests/ui/consts/const-eval/issue-52475.rs
index ce65407bb..307c1a668 100644
--- a/tests/ui/consts/const-eval/issue-52475.rs
+++ b/tests/ui/consts/const-eval/issue-52475.rs
@@ -2,8 +2,8 @@ fn main() {
let _ = [(); {
let mut x = &0;
let mut n = 0;
- while n < 5 {
- n = (n + 1) % 5; //~ ERROR evaluation of constant value failed
+ while n < 5 { //~ ERROR evaluation of constant value failed [E0080]
+ n = (n + 1) % 5;
x = &0; // Materialize a new AllocId
}
0
diff --git a/tests/ui/consts/const-eval/issue-52475.stderr b/tests/ui/consts/const-eval/issue-52475.stderr
index 8536ff02c..3aa6bd277 100644
--- a/tests/ui/consts/const-eval/issue-52475.stderr
+++ b/tests/ui/consts/const-eval/issue-52475.stderr
@@ -1,8 +1,11 @@
error[E0080]: evaluation of constant value failed
- --> $DIR/issue-52475.rs:6:17
+ --> $DIR/issue-52475.rs:5:9
|
-LL | n = (n + 1) % 5;
- | ^^^^^^^^^^^ exceeded interpreter step limit (see `#[const_eval_limit]`)
+LL | / while n < 5 {
+LL | | n = (n + 1) % 5;
+LL | | x = &0; // Materialize a new AllocId
+LL | | }
+ | |_________^ exceeded interpreter step limit (see `#[const_eval_limit]`)
error: aborting due to previous error
diff --git a/tests/ui/consts/const-eval/issue-91827-extern-types.rs b/tests/ui/consts/const-eval/issue-91827-extern-types.rs
index 43c99799f..c9aaa6e55 100644
--- a/tests/ui/consts/const-eval/issue-91827-extern-types.rs
+++ b/tests/ui/consts/const-eval/issue-91827-extern-types.rs
@@ -28,7 +28,10 @@ pub struct ListImpl<T, const N: usize> {
impl<T> List<T> {
const fn as_slice(&self) -> &[T] {
- unsafe { std::slice::from_raw_parts(self.data.as_ptr(), self.len) }
+ unsafe {
+ let ptr = addr_of!(self.tail) as *const T;
+ std::slice::from_raw_parts(ptr, self.len)
+ }
}
}
diff --git a/tests/ui/consts/const-eval/raw-bytes.32bit.stderr b/tests/ui/consts/const-eval/raw-bytes.32bit.stderr
index 91a426580..a0f8dd097 100644
--- a/tests/ui/consts/const-eval/raw-bytes.32bit.stderr
+++ b/tests/ui/consts/const-eval/raw-bytes.32bit.stderr
@@ -167,7 +167,7 @@ error[E0080]: it is undefined behavior to use this value
--> $DIR/raw-bytes.rs:96:1
|
LL | const USIZE_AS_REF: &'static u8 = unsafe { mem::transmute(1337usize) };
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a dangling reference (address 0x539 is unallocated)
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a dangling reference (0x539[noalloc] has no provenance)
|
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
= note: the raw bytes of the constant (size: 4, align: 4) {
@@ -178,7 +178,7 @@ error[E0080]: it is undefined behavior to use this value
--> $DIR/raw-bytes.rs:99:1
|
LL | const USIZE_AS_BOX: Box<u8> = unsafe { mem::transmute(1337usize) };
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a dangling box (address 0x539 is unallocated)
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a dangling box (0x539[noalloc] has no provenance)
|
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
= note: the raw bytes of the constant (size: 4, align: 4) {
diff --git a/tests/ui/consts/const-eval/raw-bytes.64bit.stderr b/tests/ui/consts/const-eval/raw-bytes.64bit.stderr
index e4c5e62f6..9706f3ec2 100644
--- a/tests/ui/consts/const-eval/raw-bytes.64bit.stderr
+++ b/tests/ui/consts/const-eval/raw-bytes.64bit.stderr
@@ -167,7 +167,7 @@ error[E0080]: it is undefined behavior to use this value
--> $DIR/raw-bytes.rs:96:1
|
LL | const USIZE_AS_REF: &'static u8 = unsafe { mem::transmute(1337usize) };
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a dangling reference (address 0x539 is unallocated)
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a dangling reference (0x539[noalloc] has no provenance)
|
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
= note: the raw bytes of the constant (size: 8, align: 8) {
@@ -178,7 +178,7 @@ error[E0080]: it is undefined behavior to use this value
--> $DIR/raw-bytes.rs:99:1
|
LL | const USIZE_AS_BOX: Box<u8> = unsafe { mem::transmute(1337usize) };
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a dangling box (address 0x539 is unallocated)
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a dangling box (0x539[noalloc] has no provenance)
|
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
= note: the raw bytes of the constant (size: 8, align: 8) {
diff --git a/tests/ui/consts/const-eval/stable-metric/ctfe-fn-call.rs b/tests/ui/consts/const-eval/stable-metric/ctfe-fn-call.rs
new file mode 100644
index 000000000..c59596238
--- /dev/null
+++ b/tests/ui/consts/const-eval/stable-metric/ctfe-fn-call.rs
@@ -0,0 +1,36 @@
+// check-fail
+// compile-flags: -Z tiny-const-eval-limit
+
+const fn foo() {}
+
+const fn call_foo() -> u32 {
+ foo();
+ foo();
+ foo();
+ foo();
+ foo();
+
+ foo();
+ foo();
+ foo();
+ foo();
+ foo();
+
+ foo();
+ foo();
+ foo();
+ foo();
+ foo();
+
+ foo();
+ foo();
+ foo();
+ foo(); //~ ERROR evaluation of constant value failed [E0080]
+ 0
+}
+
+const X: u32 = call_foo();
+
+fn main() {
+ println!("{X}");
+}
diff --git a/tests/ui/consts/const-eval/stable-metric/ctfe-fn-call.stderr b/tests/ui/consts/const-eval/stable-metric/ctfe-fn-call.stderr
new file mode 100644
index 000000000..ed70975af
--- /dev/null
+++ b/tests/ui/consts/const-eval/stable-metric/ctfe-fn-call.stderr
@@ -0,0 +1,20 @@
+error[E0080]: evaluation of constant value failed
+ --> $DIR/ctfe-fn-call.rs:28:5
+ |
+LL | foo();
+ | ^^^^^ exceeded interpreter step limit (see `#[const_eval_limit]`)
+ |
+note: inside `call_foo`
+ --> $DIR/ctfe-fn-call.rs:28:5
+ |
+LL | foo();
+ | ^^^^^
+note: inside `X`
+ --> $DIR/ctfe-fn-call.rs:32:16
+ |
+LL | const X: u32 = call_foo();
+ | ^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0080`.
diff --git a/tests/ui/consts/const-eval/stable-metric/ctfe-labelled-loop.rs b/tests/ui/consts/const-eval/stable-metric/ctfe-labelled-loop.rs
new file mode 100644
index 000000000..c10b8d837
--- /dev/null
+++ b/tests/ui/consts/const-eval/stable-metric/ctfe-labelled-loop.rs
@@ -0,0 +1,19 @@
+// check-fail
+// compile-flags: -Z tiny-const-eval-limit
+
+const fn labelled_loop(n: u32) -> u32 {
+ let mut i = 0;
+ 'mylabel: loop { //~ ERROR evaluation of constant value failed [E0080]
+ if i > n {
+ break 'mylabel
+ }
+ i += 1;
+ }
+ 0
+}
+
+const X: u32 = labelled_loop(19);
+
+fn main() {
+ println!("{X}");
+}
diff --git a/tests/ui/consts/const-eval/stable-metric/ctfe-labelled-loop.stderr b/tests/ui/consts/const-eval/stable-metric/ctfe-labelled-loop.stderr
new file mode 100644
index 000000000..d9404edd5
--- /dev/null
+++ b/tests/ui/consts/const-eval/stable-metric/ctfe-labelled-loop.stderr
@@ -0,0 +1,30 @@
+error[E0080]: evaluation of constant value failed
+ --> $DIR/ctfe-labelled-loop.rs:6:5
+ |
+LL | / 'mylabel: loop {
+LL | | if i > n {
+LL | | break 'mylabel
+LL | | }
+LL | | i += 1;
+LL | | }
+ | |_____^ exceeded interpreter step limit (see `#[const_eval_limit]`)
+ |
+note: inside `labelled_loop`
+ --> $DIR/ctfe-labelled-loop.rs:6:5
+ |
+LL | / 'mylabel: loop {
+LL | | if i > n {
+LL | | break 'mylabel
+LL | | }
+LL | | i += 1;
+LL | | }
+ | |_____^
+note: inside `X`
+ --> $DIR/ctfe-labelled-loop.rs:15:16
+ |
+LL | const X: u32 = labelled_loop(19);
+ | ^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0080`.
diff --git a/tests/ui/consts/const-eval/stable-metric/ctfe-recursion.rs b/tests/ui/consts/const-eval/stable-metric/ctfe-recursion.rs
new file mode 100644
index 000000000..80ff835f3
--- /dev/null
+++ b/tests/ui/consts/const-eval/stable-metric/ctfe-recursion.rs
@@ -0,0 +1,16 @@
+// check-fail
+// compile-flags: -Z tiny-const-eval-limit
+
+const fn recurse(n: u32) -> u32 {
+ if n == 0 {
+ n
+ } else {
+ recurse(n - 1) //~ ERROR evaluation of constant value failed [E0080]
+ }
+}
+
+const X: u32 = recurse(19);
+
+fn main() {
+ println!("{X}");
+}
diff --git a/tests/ui/consts/const-eval/stable-metric/ctfe-recursion.stderr b/tests/ui/consts/const-eval/stable-metric/ctfe-recursion.stderr
new file mode 100644
index 000000000..ed9a31119
--- /dev/null
+++ b/tests/ui/consts/const-eval/stable-metric/ctfe-recursion.stderr
@@ -0,0 +1,25 @@
+error[E0080]: evaluation of constant value failed
+ --> $DIR/ctfe-recursion.rs:8:9
+ |
+LL | recurse(n - 1)
+ | ^^^^^^^^^^^^^^ exceeded interpreter step limit (see `#[const_eval_limit]`)
+ |
+note: inside `recurse`
+ --> $DIR/ctfe-recursion.rs:8:9
+ |
+LL | recurse(n - 1)
+ | ^^^^^^^^^^^^^^
+note: [... 18 additional calls inside `recurse` ...]
+ --> $DIR/ctfe-recursion.rs:8:9
+ |
+LL | recurse(n - 1)
+ | ^^^^^^^^^^^^^^
+note: inside `X`
+ --> $DIR/ctfe-recursion.rs:12:16
+ |
+LL | const X: u32 = recurse(19);
+ | ^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0080`.
diff --git a/tests/ui/consts/const-eval/stable-metric/ctfe-simple-loop.rs b/tests/ui/consts/const-eval/stable-metric/ctfe-simple-loop.rs
new file mode 100644
index 000000000..ca0eec93c
--- /dev/null
+++ b/tests/ui/consts/const-eval/stable-metric/ctfe-simple-loop.rs
@@ -0,0 +1,15 @@
+// check-fail
+// compile-flags: -Z tiny-const-eval-limit
+const fn simple_loop(n: u32) -> u32 {
+ let mut index = 0;
+ while index < n { //~ ERROR evaluation of constant value failed [E0080]
+ index = index + 1;
+ }
+ 0
+}
+
+const X: u32 = simple_loop(19);
+
+fn main() {
+ println!("{X}");
+}
diff --git a/tests/ui/consts/const-eval/stable-metric/ctfe-simple-loop.stderr b/tests/ui/consts/const-eval/stable-metric/ctfe-simple-loop.stderr
new file mode 100644
index 000000000..83ff275de
--- /dev/null
+++ b/tests/ui/consts/const-eval/stable-metric/ctfe-simple-loop.stderr
@@ -0,0 +1,24 @@
+error[E0080]: evaluation of constant value failed
+ --> $DIR/ctfe-simple-loop.rs:5:5
+ |
+LL | / while index < n {
+LL | | index = index + 1;
+LL | | }
+ | |_____^ exceeded interpreter step limit (see `#[const_eval_limit]`)
+ |
+note: inside `simple_loop`
+ --> $DIR/ctfe-simple-loop.rs:5:5
+ |
+LL | / while index < n {
+LL | | index = index + 1;
+LL | | }
+ | |_____^
+note: inside `X`
+ --> $DIR/ctfe-simple-loop.rs:11:16
+ |
+LL | const X: u32 = simple_loop(19);
+ | ^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0080`.
diff --git a/tests/ui/consts/const-eval/stable-metric/dominators-edge-case.rs b/tests/ui/consts/const-eval/stable-metric/dominators-edge-case.rs
new file mode 100644
index 000000000..0b0f36180
--- /dev/null
+++ b/tests/ui/consts/const-eval/stable-metric/dominators-edge-case.rs
@@ -0,0 +1,19 @@
+// check-pass
+//
+// Exercising an edge case which was found during Stage 2 compilation.
+// Compilation would fail for this code when running the `CtfeLimit`
+// MirPass (specifically when looking up the dominators).
+#![crate_type="lib"]
+
+const DUMMY: Expr = Expr::Path(ExprPath {
+ attrs: Vec::new(),
+ path: Vec::new(),
+});
+
+pub enum Expr {
+ Path(ExprPath),
+}
+pub struct ExprPath {
+ pub attrs: Vec<()>,
+ pub path: Vec<()>,
+}
diff --git a/tests/ui/consts/const-eval/ub-ref-ptr.stderr b/tests/ui/consts/const-eval/ub-ref-ptr.stderr
index ce618802b..6bd367b64 100644
--- a/tests/ui/consts/const-eval/ub-ref-ptr.stderr
+++ b/tests/ui/consts/const-eval/ub-ref-ptr.stderr
@@ -85,7 +85,7 @@ error[E0080]: it is undefined behavior to use this value
--> $DIR/ub-ref-ptr.rs:43:1
|
LL | const USIZE_AS_REF: &'static u8 = unsafe { mem::transmute(1337usize) };
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a dangling reference (address 0x539 is unallocated)
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a dangling reference (0x539[noalloc] has no provenance)
|
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
= note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) {
@@ -96,7 +96,7 @@ error[E0080]: it is undefined behavior to use this value
--> $DIR/ub-ref-ptr.rs:46:1
|
LL | const USIZE_AS_BOX: Box<u8> = unsafe { mem::transmute(1337usize) };
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a dangling box (address 0x539 is unallocated)
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a dangling box (0x539[noalloc] has no provenance)
|
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
= note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) {
diff --git a/tests/ui/consts/const-eval/validate_uninhabited_zsts.32bit.stderr b/tests/ui/consts/const-eval/validate_uninhabited_zsts.32bit.stderr
index 9710bf476..69fb1a59d 100644
--- a/tests/ui/consts/const-eval/validate_uninhabited_zsts.32bit.stderr
+++ b/tests/ui/consts/const-eval/validate_uninhabited_zsts.32bit.stderr
@@ -2,10 +2,7 @@ warning: the type `!` does not permit zero-initialization
--> $DIR/validate_uninhabited_zsts.rs:4:14
|
LL | unsafe { std::mem::transmute(()) }
- | ^^^^^^^^^^^^^^^^^^^^^^^
- | |
- | this code causes undefined behavior when executed
- | help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done
+ | ^^^^^^^^^^^^^^^^^^^^^^^ this code causes undefined behavior when executed
|
= note: the `!` type has no valid value
= note: `#[warn(invalid_value)]` on by default
@@ -40,10 +37,7 @@ warning: the type `empty::Empty` does not permit zero-initialization
--> $DIR/validate_uninhabited_zsts.rs:21:42
|
LL | const BAR: [empty::Empty; 3] = [unsafe { std::mem::transmute(()) }; 3];
- | ^^^^^^^^^^^^^^^^^^^^^^^
- | |
- | this code causes undefined behavior when executed
- | help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done
+ | ^^^^^^^^^^^^^^^^^^^^^^^ this code causes undefined behavior when executed
|
note: in this struct field
--> $DIR/validate_uninhabited_zsts.rs:16:22
diff --git a/tests/ui/consts/const-eval/validate_uninhabited_zsts.64bit.stderr b/tests/ui/consts/const-eval/validate_uninhabited_zsts.64bit.stderr
index 9710bf476..69fb1a59d 100644
--- a/tests/ui/consts/const-eval/validate_uninhabited_zsts.64bit.stderr
+++ b/tests/ui/consts/const-eval/validate_uninhabited_zsts.64bit.stderr
@@ -2,10 +2,7 @@ warning: the type `!` does not permit zero-initialization
--> $DIR/validate_uninhabited_zsts.rs:4:14
|
LL | unsafe { std::mem::transmute(()) }
- | ^^^^^^^^^^^^^^^^^^^^^^^
- | |
- | this code causes undefined behavior when executed
- | help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done
+ | ^^^^^^^^^^^^^^^^^^^^^^^ this code causes undefined behavior when executed
|
= note: the `!` type has no valid value
= note: `#[warn(invalid_value)]` on by default
@@ -40,10 +37,7 @@ warning: the type `empty::Empty` does not permit zero-initialization
--> $DIR/validate_uninhabited_zsts.rs:21:42
|
LL | const BAR: [empty::Empty; 3] = [unsafe { std::mem::transmute(()) }; 3];
- | ^^^^^^^^^^^^^^^^^^^^^^^
- | |
- | this code causes undefined behavior when executed
- | help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done
+ | ^^^^^^^^^^^^^^^^^^^^^^^ this code causes undefined behavior when executed
|
note: in this struct field
--> $DIR/validate_uninhabited_zsts.rs:16:22
diff --git a/tests/ui/consts/const-tup-index-span.rs b/tests/ui/consts/const-tup-index-span.rs
index 778a21224..18f4f59d3 100644
--- a/tests/ui/consts/const-tup-index-span.rs
+++ b/tests/ui/consts/const-tup-index-span.rs
@@ -2,7 +2,7 @@
const TUP: (usize,) = 5usize << 64;
//~^ ERROR mismatched types
-//~| expected tuple, found `usize`
+//~| expected `(usize,)`, found `usize`
const ARR: [i32; TUP.0] = [];
//~^ constant
diff --git a/tests/ui/consts/const-tup-index-span.stderr b/tests/ui/consts/const-tup-index-span.stderr
index ad8468056..65f0520f8 100644
--- a/tests/ui/consts/const-tup-index-span.stderr
+++ b/tests/ui/consts/const-tup-index-span.stderr
@@ -2,7 +2,7 @@ error[E0308]: mismatched types
--> $DIR/const-tup-index-span.rs:3:23
|
LL | const TUP: (usize,) = 5usize << 64;
- | ^^^^^^^^^^^^ expected tuple, found `usize`
+ | ^^^^^^^^^^^^ expected `(usize,)`, found `usize`
|
= note: expected tuple `(usize,)`
found type `usize`
diff --git a/tests/ui/consts/const_limit/const_eval_limit_reached.stderr b/tests/ui/consts/const_limit/const_eval_limit_reached.stderr
index 850aebdfb..a8e8ae9bb 100644
--- a/tests/ui/consts/const_limit/const_eval_limit_reached.stderr
+++ b/tests/ui/consts/const_limit/const_eval_limit_reached.stderr
@@ -1,8 +1,11 @@
error[E0080]: evaluation of constant value failed
- --> $DIR/const_eval_limit_reached.rs:6:11
+ --> $DIR/const_eval_limit_reached.rs:6:5
|
-LL | while x != 1000 {
- | ^^^^^^^^^ exceeded interpreter step limit (see `#[const_eval_limit]`)
+LL | / while x != 1000 {
+LL | |
+LL | | x += 1;
+LL | | }
+ | |_____^ exceeded interpreter step limit (see `#[const_eval_limit]`)
error: aborting due to previous error
diff --git a/tests/ui/consts/ct-var-in-collect_all_mismatches.stderr b/tests/ui/consts/ct-var-in-collect_all_mismatches.stderr
index 43fba2573..fa20077da 100644
--- a/tests/ui/consts/ct-var-in-collect_all_mismatches.stderr
+++ b/tests/ui/consts/ct-var-in-collect_all_mismatches.stderr
@@ -8,7 +8,7 @@ note: required by a bound in `Foo::<T, N>::unsatisfied`
--> $DIR/ct-var-in-collect_all_mismatches.rs:15:12
|
LL | fn unsatisfied(self)
- | ----------- required by a bound in this
+ | ----------- required by a bound in this associated function
LL | where
LL | T: Bar<N>,
| ^^^^^^ required by this bound in `Foo::<T, N>::unsatisfied`
diff --git a/tests/ui/consts/gate-do-not-const-check.rs b/tests/ui/consts/gate-do-not-const-check.rs
new file mode 100644
index 000000000..be7e70dfa
--- /dev/null
+++ b/tests/ui/consts/gate-do-not-const-check.rs
@@ -0,0 +1,5 @@
+#[rustc_do_not_const_check]
+//~^ ERROR this is an internal attribute that will never be stable
+const fn foo() {}
+
+fn main() {}
diff --git a/tests/ui/consts/gate-do-not-const-check.stderr b/tests/ui/consts/gate-do-not-const-check.stderr
new file mode 100644
index 000000000..3bb136016
--- /dev/null
+++ b/tests/ui/consts/gate-do-not-const-check.stderr
@@ -0,0 +1,11 @@
+error[E0658]: this is an internal attribute that will never be stable
+ --> $DIR/gate-do-not-const-check.rs:1:1
+ |
+LL | #[rustc_do_not_const_check]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = help: add `#![feature(rustc_attrs)]` 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/tests/ui/issues/issue-33903.rs b/tests/ui/consts/issue-33903.rs
index 613aa121a..613aa121a 100644
--- a/tests/ui/issues/issue-33903.rs
+++ b/tests/ui/consts/issue-33903.rs
diff --git a/tests/ui/issues/issue-54582.rs b/tests/ui/consts/issue-54582.rs
index 8c50cac67..8c50cac67 100644
--- a/tests/ui/issues/issue-54582.rs
+++ b/tests/ui/consts/issue-54582.rs
diff --git a/tests/ui/consts/nested_erroneous_ctfe.stderr b/tests/ui/consts/nested_erroneous_ctfe.stderr
index d579a54e9..b6a172507 100644
--- a/tests/ui/consts/nested_erroneous_ctfe.stderr
+++ b/tests/ui/consts/nested_erroneous_ctfe.stderr
@@ -2,7 +2,7 @@ error[E0308]: mismatched types
--> $DIR/nested_erroneous_ctfe.rs:2:16
|
LL | [9; || [9; []]];
- | ^^ expected `usize`, found array of 0 elements
+ | ^^ expected `usize`, found `[_; 0]`
|
= note: expected type `usize`
found array `[_; 0]`
diff --git a/tests/ui/consts/promote_const_let.stderr b/tests/ui/consts/promote_const_let.stderr
index 975a235a6..6e0349a47 100644
--- a/tests/ui/consts/promote_const_let.stderr
+++ b/tests/ui/consts/promote_const_let.stderr
@@ -4,6 +4,7 @@ error[E0597]: `y` does not live long enough
LL | let x: &'static u32 = {
| ------------ type annotation requires that `y` is borrowed for `'static`
LL | let y = 42;
+ | - binding `y` declared here
LL | &y
| ^^ borrowed value does not live long enough
LL | };
diff --git a/tests/ui/cross/cross-borrow-trait.stderr b/tests/ui/cross/cross-borrow-trait.stderr
index 81f309eae..4f5af1066 100644
--- a/tests/ui/cross/cross-borrow-trait.stderr
+++ b/tests/ui/cross/cross-borrow-trait.stderr
@@ -2,7 +2,7 @@ error[E0308]: mismatched types
--> $DIR/cross-borrow-trait.rs:10:26
|
LL | let _y: &dyn Trait = x;
- | ---------- ^ expected `&dyn Trait`, found struct `Box`
+ | ---------- ^ expected `&dyn Trait`, found `Box<dyn Trait>`
| |
| expected due to this
|
diff --git a/tests/ui/deprecation/deprecation-lint.rs b/tests/ui/deprecation/deprecation-lint.rs
index 0417e952e..83056feaf 100644
--- a/tests/ui/deprecation/deprecation-lint.rs
+++ b/tests/ui/deprecation/deprecation-lint.rs
@@ -14,22 +14,22 @@ mod cross_crate {
let foo = MethodTester;
deprecated(); //~ ERROR use of deprecated function `deprecation_lint::deprecated`
- foo.method_deprecated(); //~ ERROR use of deprecated associated function `deprecation_lint::MethodTester::method_deprecated`
- Foo::method_deprecated(&foo); //~ ERROR use of deprecated associated function `deprecation_lint::MethodTester::method_deprecated`
- <Foo>::method_deprecated(&foo); //~ ERROR use of deprecated associated function `deprecation_lint::MethodTester::method_deprecated`
- foo.trait_deprecated(); //~ ERROR use of deprecated associated function `deprecation_lint::Trait::trait_deprecated`
- Trait::trait_deprecated(&foo); //~ ERROR use of deprecated associated function `deprecation_lint::Trait::trait_deprecated`
- <Foo>::trait_deprecated(&foo); //~ ERROR use of deprecated associated function `deprecation_lint::Trait::trait_deprecated`
- <Foo as Trait>::trait_deprecated(&foo); //~ ERROR use of deprecated associated function `deprecation_lint::Trait::trait_deprecated`
+ foo.method_deprecated(); //~ ERROR use of deprecated method `deprecation_lint::MethodTester::method_deprecated`
+ Foo::method_deprecated(&foo); //~ ERROR use of deprecated method `deprecation_lint::MethodTester::method_deprecated`
+ <Foo>::method_deprecated(&foo); //~ ERROR use of deprecated method `deprecation_lint::MethodTester::method_deprecated`
+ foo.trait_deprecated(); //~ ERROR use of deprecated method `deprecation_lint::Trait::trait_deprecated`
+ Trait::trait_deprecated(&foo); //~ ERROR use of deprecated method `deprecation_lint::Trait::trait_deprecated`
+ <Foo>::trait_deprecated(&foo); //~ ERROR use of deprecated method `deprecation_lint::Trait::trait_deprecated`
+ <Foo as Trait>::trait_deprecated(&foo); //~ ERROR use of deprecated method `deprecation_lint::Trait::trait_deprecated`
deprecated_text(); //~ ERROR use of deprecated function `deprecation_lint::deprecated_text`: text
- foo.method_deprecated_text(); //~ ERROR use of deprecated associated function `deprecation_lint::MethodTester::method_deprecated_text`: text
- Foo::method_deprecated_text(&foo); //~ ERROR use of deprecated associated function `deprecation_lint::MethodTester::method_deprecated_text`: text
- <Foo>::method_deprecated_text(&foo); //~ ERROR use of deprecated associated function `deprecation_lint::MethodTester::method_deprecated_text`: text
- foo.trait_deprecated_text(); //~ ERROR use of deprecated associated function `deprecation_lint::Trait::trait_deprecated_text`: text
- Trait::trait_deprecated_text(&foo); //~ ERROR use of deprecated associated function `deprecation_lint::Trait::trait_deprecated_text`: text
- <Foo>::trait_deprecated_text(&foo); //~ ERROR use of deprecated associated function `deprecation_lint::Trait::trait_deprecated_text`: text
- <Foo as Trait>::trait_deprecated_text(&foo); //~ ERROR use of deprecated associated function `deprecation_lint::Trait::trait_deprecated_text`: text
+ foo.method_deprecated_text(); //~ ERROR use of deprecated method `deprecation_lint::MethodTester::method_deprecated_text`: text
+ Foo::method_deprecated_text(&foo); //~ ERROR use of deprecated method `deprecation_lint::MethodTester::method_deprecated_text`: text
+ <Foo>::method_deprecated_text(&foo); //~ ERROR use of deprecated method `deprecation_lint::MethodTester::method_deprecated_text`: text
+ foo.trait_deprecated_text(); //~ ERROR use of deprecated method `deprecation_lint::Trait::trait_deprecated_text`: text
+ Trait::trait_deprecated_text(&foo); //~ ERROR use of deprecated method `deprecation_lint::Trait::trait_deprecated_text`: text
+ <Foo>::trait_deprecated_text(&foo); //~ ERROR use of deprecated method `deprecation_lint::Trait::trait_deprecated_text`: text
+ <Foo as Trait>::trait_deprecated_text(&foo); //~ ERROR use of deprecated method `deprecation_lint::Trait::trait_deprecated_text`: text
let _ = DeprecatedStruct { //~ ERROR use of deprecated struct `deprecation_lint::DeprecatedStruct`: text
i: 0 //~ ERROR use of deprecated field `deprecation_lint::DeprecatedStruct::i`: text
@@ -61,19 +61,19 @@ mod cross_crate {
}
fn test_method_param<Foo: Trait>(foo: Foo) {
- foo.trait_deprecated(); //~ ERROR use of deprecated associated function `deprecation_lint::Trait::trait_deprecated`
- Trait::trait_deprecated(&foo); //~ ERROR use of deprecated associated function `deprecation_lint::Trait::trait_deprecated`
- <Foo>::trait_deprecated(&foo); //~ ERROR use of deprecated associated function `deprecation_lint::Trait::trait_deprecated`
- <Foo as Trait>::trait_deprecated(&foo); //~ ERROR use of deprecated associated function `deprecation_lint::Trait::trait_deprecated`
- foo.trait_deprecated_text(); //~ ERROR use of deprecated associated function `deprecation_lint::Trait::trait_deprecated_text`: text
- Trait::trait_deprecated_text(&foo); //~ ERROR use of deprecated associated function `deprecation_lint::Trait::trait_deprecated_text`: text
- <Foo>::trait_deprecated_text(&foo); //~ ERROR use of deprecated associated function `deprecation_lint::Trait::trait_deprecated_text`: text
- <Foo as Trait>::trait_deprecated_text(&foo); //~ ERROR use of deprecated associated function `deprecation_lint::Trait::trait_deprecated_text`: text
+ foo.trait_deprecated(); //~ ERROR use of deprecated method `deprecation_lint::Trait::trait_deprecated`
+ Trait::trait_deprecated(&foo); //~ ERROR use of deprecated method `deprecation_lint::Trait::trait_deprecated`
+ <Foo>::trait_deprecated(&foo); //~ ERROR use of deprecated method `deprecation_lint::Trait::trait_deprecated`
+ <Foo as Trait>::trait_deprecated(&foo); //~ ERROR use of deprecated method `deprecation_lint::Trait::trait_deprecated`
+ foo.trait_deprecated_text(); //~ ERROR use of deprecated method `deprecation_lint::Trait::trait_deprecated_text`: text
+ Trait::trait_deprecated_text(&foo); //~ ERROR use of deprecated method `deprecation_lint::Trait::trait_deprecated_text`: text
+ <Foo>::trait_deprecated_text(&foo); //~ ERROR use of deprecated method `deprecation_lint::Trait::trait_deprecated_text`: text
+ <Foo as Trait>::trait_deprecated_text(&foo); //~ ERROR use of deprecated method `deprecation_lint::Trait::trait_deprecated_text`: text
}
fn test_method_object(foo: &Trait) {
- foo.trait_deprecated(); //~ ERROR use of deprecated associated function `deprecation_lint::Trait::trait_deprecated`
- foo.trait_deprecated_text(); //~ ERROR use of deprecated associated function `deprecation_lint::Trait::trait_deprecated_text`: text
+ foo.trait_deprecated(); //~ ERROR use of deprecated method `deprecation_lint::Trait::trait_deprecated`
+ foo.trait_deprecated_text(); //~ ERROR use of deprecated method `deprecation_lint::Trait::trait_deprecated_text`: text
}
struct S;
@@ -243,22 +243,22 @@ mod this_crate {
let foo = MethodTester;
deprecated(); //~ ERROR use of deprecated function `this_crate::deprecated`
- foo.method_deprecated(); //~ ERROR use of deprecated associated function `this_crate::MethodTester::method_deprecated`
- Foo::method_deprecated(&foo); //~ ERROR use of deprecated associated function `this_crate::MethodTester::method_deprecated`
- <Foo>::method_deprecated(&foo); //~ ERROR use of deprecated associated function `this_crate::MethodTester::method_deprecated`
- foo.trait_deprecated(); //~ ERROR use of deprecated associated function `this_crate::Trait::trait_deprecated`
- Trait::trait_deprecated(&foo); //~ ERROR use of deprecated associated function `this_crate::Trait::trait_deprecated`
- <Foo>::trait_deprecated(&foo); //~ ERROR use of deprecated associated function `this_crate::Trait::trait_deprecated`
- <Foo as Trait>::trait_deprecated(&foo); //~ ERROR use of deprecated associated function `this_crate::Trait::trait_deprecated`
+ foo.method_deprecated(); //~ ERROR use of deprecated method `this_crate::MethodTester::method_deprecated`
+ Foo::method_deprecated(&foo); //~ ERROR use of deprecated method `this_crate::MethodTester::method_deprecated`
+ <Foo>::method_deprecated(&foo); //~ ERROR use of deprecated method `this_crate::MethodTester::method_deprecated`
+ foo.trait_deprecated(); //~ ERROR use of deprecated method `this_crate::Trait::trait_deprecated`
+ Trait::trait_deprecated(&foo); //~ ERROR use of deprecated method `this_crate::Trait::trait_deprecated`
+ <Foo>::trait_deprecated(&foo); //~ ERROR use of deprecated method `this_crate::Trait::trait_deprecated`
+ <Foo as Trait>::trait_deprecated(&foo); //~ ERROR use of deprecated method `this_crate::Trait::trait_deprecated`
deprecated_text(); //~ ERROR use of deprecated function `this_crate::deprecated_text`: text
- foo.method_deprecated_text(); //~ ERROR use of deprecated associated function `this_crate::MethodTester::method_deprecated_text`: text
- Foo::method_deprecated_text(&foo); //~ ERROR use of deprecated associated function `this_crate::MethodTester::method_deprecated_text`: text
- <Foo>::method_deprecated_text(&foo); //~ ERROR use of deprecated associated function `this_crate::MethodTester::method_deprecated_text`: text
- foo.trait_deprecated_text(); //~ ERROR use of deprecated associated function `this_crate::Trait::trait_deprecated_text`: text
- Trait::trait_deprecated_text(&foo); //~ ERROR use of deprecated associated function `this_crate::Trait::trait_deprecated_text`: text
- <Foo>::trait_deprecated_text(&foo); //~ ERROR use of deprecated associated function `this_crate::Trait::trait_deprecated_text`: text
- <Foo as Trait>::trait_deprecated_text(&foo); //~ ERROR use of deprecated associated function `this_crate::Trait::trait_deprecated_text`: text
+ foo.method_deprecated_text(); //~ ERROR use of deprecated method `this_crate::MethodTester::method_deprecated_text`: text
+ Foo::method_deprecated_text(&foo); //~ ERROR use of deprecated method `this_crate::MethodTester::method_deprecated_text`: text
+ <Foo>::method_deprecated_text(&foo); //~ ERROR use of deprecated method `this_crate::MethodTester::method_deprecated_text`: text
+ foo.trait_deprecated_text(); //~ ERROR use of deprecated method `this_crate::Trait::trait_deprecated_text`: text
+ Trait::trait_deprecated_text(&foo); //~ ERROR use of deprecated method `this_crate::Trait::trait_deprecated_text`: text
+ <Foo>::trait_deprecated_text(&foo); //~ ERROR use of deprecated method `this_crate::Trait::trait_deprecated_text`: text
+ <Foo as Trait>::trait_deprecated_text(&foo); //~ ERROR use of deprecated method `this_crate::Trait::trait_deprecated_text`: text
// Future deprecations are only permitted with `#![feature(staged_api)]`
deprecated_future(); //~ ERROR use of deprecated function
@@ -289,19 +289,19 @@ mod this_crate {
}
fn test_method_param<Foo: Trait>(foo: Foo) {
- foo.trait_deprecated(); //~ ERROR use of deprecated associated function `this_crate::Trait::trait_deprecated`
- Trait::trait_deprecated(&foo); //~ ERROR use of deprecated associated function `this_crate::Trait::trait_deprecated`
- <Foo>::trait_deprecated(&foo); //~ ERROR use of deprecated associated function `this_crate::Trait::trait_deprecated`
- <Foo as Trait>::trait_deprecated(&foo); //~ ERROR use of deprecated associated function `this_crate::Trait::trait_deprecated`
- foo.trait_deprecated_text(); //~ ERROR use of deprecated associated function `this_crate::Trait::trait_deprecated_text`: text
- Trait::trait_deprecated_text(&foo); //~ ERROR use of deprecated associated function `this_crate::Trait::trait_deprecated_text`: text
- <Foo>::trait_deprecated_text(&foo); //~ ERROR use of deprecated associated function `this_crate::Trait::trait_deprecated_text`: text
- <Foo as Trait>::trait_deprecated_text(&foo); //~ ERROR use of deprecated associated function `this_crate::Trait::trait_deprecated_text`: text
+ foo.trait_deprecated(); //~ ERROR use of deprecated method `this_crate::Trait::trait_deprecated`
+ Trait::trait_deprecated(&foo); //~ ERROR use of deprecated method `this_crate::Trait::trait_deprecated`
+ <Foo>::trait_deprecated(&foo); //~ ERROR use of deprecated method `this_crate::Trait::trait_deprecated`
+ <Foo as Trait>::trait_deprecated(&foo); //~ ERROR use of deprecated method `this_crate::Trait::trait_deprecated`
+ foo.trait_deprecated_text(); //~ ERROR use of deprecated method `this_crate::Trait::trait_deprecated_text`: text
+ Trait::trait_deprecated_text(&foo); //~ ERROR use of deprecated method `this_crate::Trait::trait_deprecated_text`: text
+ <Foo>::trait_deprecated_text(&foo); //~ ERROR use of deprecated method `this_crate::Trait::trait_deprecated_text`: text
+ <Foo as Trait>::trait_deprecated_text(&foo); //~ ERROR use of deprecated method `this_crate::Trait::trait_deprecated_text`: text
}
fn test_method_object(foo: &Trait) {
- foo.trait_deprecated(); //~ ERROR use of deprecated associated function `this_crate::Trait::trait_deprecated`
- foo.trait_deprecated_text(); //~ ERROR use of deprecated associated function `this_crate::Trait::trait_deprecated_text`: text
+ foo.trait_deprecated(); //~ ERROR use of deprecated method `this_crate::Trait::trait_deprecated`
+ foo.trait_deprecated_text(); //~ ERROR use of deprecated method `this_crate::Trait::trait_deprecated_text`: text
}
#[deprecated(since = "1.0.0", note = "text")]
diff --git a/tests/ui/deprecation/deprecation-lint.stderr b/tests/ui/deprecation/deprecation-lint.stderr
index 3842f8492..209807340 100644
--- a/tests/ui/deprecation/deprecation-lint.stderr
+++ b/tests/ui/deprecation/deprecation-lint.stderr
@@ -10,13 +10,13 @@ note: the lint level is defined here
LL | #![deny(deprecated)]
| ^^^^^^^^^^
-error: use of deprecated associated function `deprecation_lint::Trait::trait_deprecated`: text
+error: use of deprecated method `deprecation_lint::Trait::trait_deprecated`: text
--> $DIR/deprecation-lint.rs:21:16
|
LL | Trait::trait_deprecated(&foo);
| ^^^^^^^^^^^^^^^^
-error: use of deprecated associated function `deprecation_lint::Trait::trait_deprecated`: text
+error: use of deprecated method `deprecation_lint::Trait::trait_deprecated`: text
--> $DIR/deprecation-lint.rs:23:25
|
LL | <Foo as Trait>::trait_deprecated(&foo);
@@ -28,13 +28,13 @@ error: use of deprecated function `deprecation_lint::deprecated_text`: text
LL | deprecated_text();
| ^^^^^^^^^^^^^^^
-error: use of deprecated associated function `deprecation_lint::Trait::trait_deprecated_text`: text
+error: use of deprecated method `deprecation_lint::Trait::trait_deprecated_text`: text
--> $DIR/deprecation-lint.rs:30:16
|
-LL | ... Trait::trait_deprecated_text(&foo);
- | ^^^^^^^^^^^^^^^^^^^^^
+LL | Trait::trait_deprecated_text(&foo);
+ | ^^^^^^^^^^^^^^^^^^^^^
-error: use of deprecated associated function `deprecation_lint::Trait::trait_deprecated_text`: text
+error: use of deprecated method `deprecation_lint::Trait::trait_deprecated_text`: text
--> $DIR/deprecation-lint.rs:32:25
|
LL | ... <Foo as Trait>::trait_deprecated_text(&foo);
@@ -100,25 +100,25 @@ error: use of deprecated function `deprecation_lint::deprecated_text`: text
LL | macro_test_arg!(macro_test_arg!(deprecated_text()));
| ^^^^^^^^^^^^^^^
-error: use of deprecated associated function `deprecation_lint::Trait::trait_deprecated`: text
+error: use of deprecated method `deprecation_lint::Trait::trait_deprecated`: text
--> $DIR/deprecation-lint.rs:65:16
|
LL | Trait::trait_deprecated(&foo);
| ^^^^^^^^^^^^^^^^
-error: use of deprecated associated function `deprecation_lint::Trait::trait_deprecated`: text
+error: use of deprecated method `deprecation_lint::Trait::trait_deprecated`: text
--> $DIR/deprecation-lint.rs:67:25
|
LL | <Foo as Trait>::trait_deprecated(&foo);
| ^^^^^^^^^^^^^^^^
-error: use of deprecated associated function `deprecation_lint::Trait::trait_deprecated_text`: text
+error: use of deprecated method `deprecation_lint::Trait::trait_deprecated_text`: text
--> $DIR/deprecation-lint.rs:69:16
|
-LL | ... Trait::trait_deprecated_text(&foo);
- | ^^^^^^^^^^^^^^^^^^^^^
+LL | Trait::trait_deprecated_text(&foo);
+ | ^^^^^^^^^^^^^^^^^^^^^
-error: use of deprecated associated function `deprecation_lint::Trait::trait_deprecated_text`: text
+error: use of deprecated method `deprecation_lint::Trait::trait_deprecated_text`: text
--> $DIR/deprecation-lint.rs:71:25
|
LL | ... <Foo as Trait>::trait_deprecated_text(&foo);
@@ -184,13 +184,13 @@ error: use of deprecated function `this_crate::deprecated`: text
LL | deprecated();
| ^^^^^^^^^^
-error: use of deprecated associated function `this_crate::Trait::trait_deprecated`: text
+error: use of deprecated method `this_crate::Trait::trait_deprecated`: text
--> $DIR/deprecation-lint.rs:250:16
|
LL | Trait::trait_deprecated(&foo);
| ^^^^^^^^^^^^^^^^
-error: use of deprecated associated function `this_crate::Trait::trait_deprecated`: text
+error: use of deprecated method `this_crate::Trait::trait_deprecated`: text
--> $DIR/deprecation-lint.rs:252:25
|
LL | <Foo as Trait>::trait_deprecated(&foo);
@@ -202,17 +202,17 @@ error: use of deprecated function `this_crate::deprecated_text`: text
LL | deprecated_text();
| ^^^^^^^^^^^^^^^
-error: use of deprecated associated function `this_crate::Trait::trait_deprecated_text`: text
+error: use of deprecated method `this_crate::Trait::trait_deprecated_text`: text
--> $DIR/deprecation-lint.rs:259:16
|
LL | Trait::trait_deprecated_text(&foo);
| ^^^^^^^^^^^^^^^^^^^^^
-error: use of deprecated associated function `this_crate::Trait::trait_deprecated_text`: text
+error: use of deprecated method `this_crate::Trait::trait_deprecated_text`: text
--> $DIR/deprecation-lint.rs:261:25
|
-LL | ... <Foo as Trait>::trait_deprecated_text(&foo);
- | ^^^^^^^^^^^^^^^^^^^^^
+LL | <Foo as Trait>::trait_deprecated_text(&foo);
+ | ^^^^^^^^^^^^^^^^^^^^^
error: use of deprecated function `this_crate::deprecated_future`: text
--> $DIR/deprecation-lint.rs:264:9
@@ -274,29 +274,29 @@ error: use of deprecated tuple struct `this_crate::nested::DeprecatedTupleStruct
LL | ... let _ = nested::DeprecatedTupleStruct (1);
| ^^^^^^^^^^^^^^^^^^^^^
-error: use of deprecated associated function `this_crate::Trait::trait_deprecated`: text
+error: use of deprecated method `this_crate::Trait::trait_deprecated`: text
--> $DIR/deprecation-lint.rs:293:16
|
LL | Trait::trait_deprecated(&foo);
| ^^^^^^^^^^^^^^^^
-error: use of deprecated associated function `this_crate::Trait::trait_deprecated`: text
+error: use of deprecated method `this_crate::Trait::trait_deprecated`: text
--> $DIR/deprecation-lint.rs:295:25
|
LL | <Foo as Trait>::trait_deprecated(&foo);
| ^^^^^^^^^^^^^^^^
-error: use of deprecated associated function `this_crate::Trait::trait_deprecated_text`: text
+error: use of deprecated method `this_crate::Trait::trait_deprecated_text`: text
--> $DIR/deprecation-lint.rs:297:16
|
LL | Trait::trait_deprecated_text(&foo);
| ^^^^^^^^^^^^^^^^^^^^^
-error: use of deprecated associated function `this_crate::Trait::trait_deprecated_text`: text
+error: use of deprecated method `this_crate::Trait::trait_deprecated_text`: text
--> $DIR/deprecation-lint.rs:299:25
|
-LL | ... <Foo as Trait>::trait_deprecated_text(&foo);
- | ^^^^^^^^^^^^^^^^^^^^^
+LL | <Foo as Trait>::trait_deprecated_text(&foo);
+ | ^^^^^^^^^^^^^^^^^^^^^
error: use of deprecated function `this_crate::test_fn_closure_body::{closure#0}::bar`
--> $DIR/deprecation-lint.rs:317:13
@@ -352,65 +352,65 @@ error: use of deprecated tuple struct `this_crate2::Deprecated2`: text
LL | let Deprecated2
| ^^^^^^^^^^^
-error: use of deprecated associated function `deprecation_lint::MethodTester::method_deprecated`: text
+error: use of deprecated method `deprecation_lint::MethodTester::method_deprecated`: text
--> $DIR/deprecation-lint.rs:17:13
|
LL | foo.method_deprecated();
| ^^^^^^^^^^^^^^^^^
-error: use of deprecated associated function `deprecation_lint::MethodTester::method_deprecated`: text
+error: use of deprecated method `deprecation_lint::MethodTester::method_deprecated`: text
--> $DIR/deprecation-lint.rs:18:14
|
LL | Foo::method_deprecated(&foo);
| ^^^^^^^^^^^^^^^^^
-error: use of deprecated associated function `deprecation_lint::MethodTester::method_deprecated`: text
+error: use of deprecated method `deprecation_lint::MethodTester::method_deprecated`: text
--> $DIR/deprecation-lint.rs:19:16
|
LL | <Foo>::method_deprecated(&foo);
| ^^^^^^^^^^^^^^^^^
-error: use of deprecated associated function `deprecation_lint::Trait::trait_deprecated`: text
+error: use of deprecated method `deprecation_lint::Trait::trait_deprecated`: text
--> $DIR/deprecation-lint.rs:20:13
|
LL | foo.trait_deprecated();
| ^^^^^^^^^^^^^^^^
-error: use of deprecated associated function `deprecation_lint::Trait::trait_deprecated`: text
+error: use of deprecated method `deprecation_lint::Trait::trait_deprecated`: text
--> $DIR/deprecation-lint.rs:22:16
|
LL | <Foo>::trait_deprecated(&foo);
| ^^^^^^^^^^^^^^^^
-error: use of deprecated associated function `deprecation_lint::MethodTester::method_deprecated_text`: text
+error: use of deprecated method `deprecation_lint::MethodTester::method_deprecated_text`: text
--> $DIR/deprecation-lint.rs:26:13
|
-LL | ... foo.method_deprecated_text();
- | ^^^^^^^^^^^^^^^^^^^^^^
+LL | foo.method_deprecated_text();
+ | ^^^^^^^^^^^^^^^^^^^^^^
-error: use of deprecated associated function `deprecation_lint::MethodTester::method_deprecated_text`: text
+error: use of deprecated method `deprecation_lint::MethodTester::method_deprecated_text`: text
--> $DIR/deprecation-lint.rs:27:14
|
-LL | ... Foo::method_deprecated_text(&foo);
- | ^^^^^^^^^^^^^^^^^^^^^^
+LL | Foo::method_deprecated_text(&foo);
+ | ^^^^^^^^^^^^^^^^^^^^^^
-error: use of deprecated associated function `deprecation_lint::MethodTester::method_deprecated_text`: text
+error: use of deprecated method `deprecation_lint::MethodTester::method_deprecated_text`: text
--> $DIR/deprecation-lint.rs:28:16
|
LL | ... <Foo>::method_deprecated_text(&foo);
| ^^^^^^^^^^^^^^^^^^^^^^
-error: use of deprecated associated function `deprecation_lint::Trait::trait_deprecated_text`: text
+error: use of deprecated method `deprecation_lint::Trait::trait_deprecated_text`: text
--> $DIR/deprecation-lint.rs:29:13
|
LL | foo.trait_deprecated_text();
| ^^^^^^^^^^^^^^^^^^^^^
-error: use of deprecated associated function `deprecation_lint::Trait::trait_deprecated_text`: text
+error: use of deprecated method `deprecation_lint::Trait::trait_deprecated_text`: text
--> $DIR/deprecation-lint.rs:31:16
|
-LL | ... <Foo>::trait_deprecated_text(&foo);
- | ^^^^^^^^^^^^^^^^^^^^^
+LL | <Foo>::trait_deprecated_text(&foo);
+ | ^^^^^^^^^^^^^^^^^^^^^
error: use of deprecated field `deprecation_lint::DeprecatedStruct::i`: text
--> $DIR/deprecation-lint.rs:35:13
@@ -424,37 +424,37 @@ error: use of deprecated field `deprecation_lint::nested::DeprecatedStruct::i`:
LL | i: 0
| ^^^^
-error: use of deprecated associated function `deprecation_lint::Trait::trait_deprecated`: text
+error: use of deprecated method `deprecation_lint::Trait::trait_deprecated`: text
--> $DIR/deprecation-lint.rs:64:13
|
LL | foo.trait_deprecated();
| ^^^^^^^^^^^^^^^^
-error: use of deprecated associated function `deprecation_lint::Trait::trait_deprecated`: text
+error: use of deprecated method `deprecation_lint::Trait::trait_deprecated`: text
--> $DIR/deprecation-lint.rs:66:16
|
LL | <Foo>::trait_deprecated(&foo);
| ^^^^^^^^^^^^^^^^
-error: use of deprecated associated function `deprecation_lint::Trait::trait_deprecated_text`: text
+error: use of deprecated method `deprecation_lint::Trait::trait_deprecated_text`: text
--> $DIR/deprecation-lint.rs:68:13
|
LL | foo.trait_deprecated_text();
| ^^^^^^^^^^^^^^^^^^^^^
-error: use of deprecated associated function `deprecation_lint::Trait::trait_deprecated_text`: text
+error: use of deprecated method `deprecation_lint::Trait::trait_deprecated_text`: text
--> $DIR/deprecation-lint.rs:70:16
|
-LL | ... <Foo>::trait_deprecated_text(&foo);
- | ^^^^^^^^^^^^^^^^^^^^^
+LL | <Foo>::trait_deprecated_text(&foo);
+ | ^^^^^^^^^^^^^^^^^^^^^
-error: use of deprecated associated function `deprecation_lint::Trait::trait_deprecated`: text
+error: use of deprecated method `deprecation_lint::Trait::trait_deprecated`: text
--> $DIR/deprecation-lint.rs:75:13
|
LL | foo.trait_deprecated();
| ^^^^^^^^^^^^^^^^
-error: use of deprecated associated function `deprecation_lint::Trait::trait_deprecated_text`: text
+error: use of deprecated method `deprecation_lint::Trait::trait_deprecated_text`: text
--> $DIR/deprecation-lint.rs:76:13
|
LL | foo.trait_deprecated_text();
@@ -544,61 +544,61 @@ error: use of deprecated field `deprecation_lint::Deprecated2::2`: text
LL | _)
| ^
-error: use of deprecated associated function `this_crate::MethodTester::method_deprecated`: text
+error: use of deprecated method `this_crate::MethodTester::method_deprecated`: text
--> $DIR/deprecation-lint.rs:246:13
|
LL | foo.method_deprecated();
| ^^^^^^^^^^^^^^^^^
-error: use of deprecated associated function `this_crate::MethodTester::method_deprecated`: text
+error: use of deprecated method `this_crate::MethodTester::method_deprecated`: text
--> $DIR/deprecation-lint.rs:247:14
|
LL | Foo::method_deprecated(&foo);
| ^^^^^^^^^^^^^^^^^
-error: use of deprecated associated function `this_crate::MethodTester::method_deprecated`: text
+error: use of deprecated method `this_crate::MethodTester::method_deprecated`: text
--> $DIR/deprecation-lint.rs:248:16
|
LL | <Foo>::method_deprecated(&foo);
| ^^^^^^^^^^^^^^^^^
-error: use of deprecated associated function `this_crate::Trait::trait_deprecated`: text
+error: use of deprecated method `this_crate::Trait::trait_deprecated`: text
--> $DIR/deprecation-lint.rs:249:13
|
LL | foo.trait_deprecated();
| ^^^^^^^^^^^^^^^^
-error: use of deprecated associated function `this_crate::Trait::trait_deprecated`: text
+error: use of deprecated method `this_crate::Trait::trait_deprecated`: text
--> $DIR/deprecation-lint.rs:251:16
|
LL | <Foo>::trait_deprecated(&foo);
| ^^^^^^^^^^^^^^^^
-error: use of deprecated associated function `this_crate::MethodTester::method_deprecated_text`: text
+error: use of deprecated method `this_crate::MethodTester::method_deprecated_text`: text
--> $DIR/deprecation-lint.rs:255:13
|
-LL | ... foo.method_deprecated_text();
- | ^^^^^^^^^^^^^^^^^^^^^^
+LL | foo.method_deprecated_text();
+ | ^^^^^^^^^^^^^^^^^^^^^^
-error: use of deprecated associated function `this_crate::MethodTester::method_deprecated_text`: text
+error: use of deprecated method `this_crate::MethodTester::method_deprecated_text`: text
--> $DIR/deprecation-lint.rs:256:14
|
-LL | ... Foo::method_deprecated_text(&foo);
- | ^^^^^^^^^^^^^^^^^^^^^^
+LL | Foo::method_deprecated_text(&foo);
+ | ^^^^^^^^^^^^^^^^^^^^^^
-error: use of deprecated associated function `this_crate::MethodTester::method_deprecated_text`: text
+error: use of deprecated method `this_crate::MethodTester::method_deprecated_text`: text
--> $DIR/deprecation-lint.rs:257:16
|
-LL | ... <Foo>::method_deprecated_text(&foo);
- | ^^^^^^^^^^^^^^^^^^^^^^
+LL | <Foo>::method_deprecated_text(&foo);
+ | ^^^^^^^^^^^^^^^^^^^^^^
-error: use of deprecated associated function `this_crate::Trait::trait_deprecated_text`: text
+error: use of deprecated method `this_crate::Trait::trait_deprecated_text`: text
--> $DIR/deprecation-lint.rs:258:13
|
LL | foo.trait_deprecated_text();
| ^^^^^^^^^^^^^^^^^^^^^
-error: use of deprecated associated function `this_crate::Trait::trait_deprecated_text`: text
+error: use of deprecated method `this_crate::Trait::trait_deprecated_text`: text
--> $DIR/deprecation-lint.rs:260:16
|
LL | <Foo>::trait_deprecated_text(&foo);
@@ -616,37 +616,37 @@ error: use of deprecated field `this_crate::nested::DeprecatedStruct::i`: text
LL | i: 0
| ^^^^
-error: use of deprecated associated function `this_crate::Trait::trait_deprecated`: text
+error: use of deprecated method `this_crate::Trait::trait_deprecated`: text
--> $DIR/deprecation-lint.rs:292:13
|
LL | foo.trait_deprecated();
| ^^^^^^^^^^^^^^^^
-error: use of deprecated associated function `this_crate::Trait::trait_deprecated`: text
+error: use of deprecated method `this_crate::Trait::trait_deprecated`: text
--> $DIR/deprecation-lint.rs:294:16
|
LL | <Foo>::trait_deprecated(&foo);
| ^^^^^^^^^^^^^^^^
-error: use of deprecated associated function `this_crate::Trait::trait_deprecated_text`: text
+error: use of deprecated method `this_crate::Trait::trait_deprecated_text`: text
--> $DIR/deprecation-lint.rs:296:13
|
LL | foo.trait_deprecated_text();
| ^^^^^^^^^^^^^^^^^^^^^
-error: use of deprecated associated function `this_crate::Trait::trait_deprecated_text`: text
+error: use of deprecated method `this_crate::Trait::trait_deprecated_text`: text
--> $DIR/deprecation-lint.rs:298:16
|
LL | <Foo>::trait_deprecated_text(&foo);
| ^^^^^^^^^^^^^^^^^^^^^
-error: use of deprecated associated function `this_crate::Trait::trait_deprecated`: text
+error: use of deprecated method `this_crate::Trait::trait_deprecated`: text
--> $DIR/deprecation-lint.rs:303:13
|
LL | foo.trait_deprecated();
| ^^^^^^^^^^^^^^^^
-error: use of deprecated associated function `this_crate::Trait::trait_deprecated_text`: text
+error: use of deprecated method `this_crate::Trait::trait_deprecated_text`: text
--> $DIR/deprecation-lint.rs:304:13
|
LL | foo.trait_deprecated_text();
diff --git a/tests/ui/deprecation/issue-84637-deprecated-associated-function.fixed b/tests/ui/deprecation/issue-84637-deprecated-associated-function.fixed
index 99a2b0961..85e882870 100644
--- a/tests/ui/deprecation/issue-84637-deprecated-associated-function.fixed
+++ b/tests/ui/deprecation/issue-84637-deprecated-associated-function.fixed
@@ -3,7 +3,7 @@
#![deny(deprecated)]
fn main() {
- let _foo = str::trim_start(" aoeu"); //~ ERROR use of deprecated associated function `core::str::<impl str>::trim_left`: superseded by `trim_start` [deprecated]
+ let _foo = str::trim_start(" aoeu"); //~ ERROR use of deprecated method `core::str::<impl str>::trim_left`: superseded by `trim_start` [deprecated]
- let _bar = " aoeu".trim_start(); //~ ERROR use of deprecated associated function `core::str::<impl str>::trim_left`: superseded by `trim_start` [deprecated]
+ let _bar = " aoeu".trim_start(); //~ ERROR use of deprecated method `core::str::<impl str>::trim_left`: superseded by `trim_start` [deprecated]
}
diff --git a/tests/ui/deprecation/issue-84637-deprecated-associated-function.rs b/tests/ui/deprecation/issue-84637-deprecated-associated-function.rs
index 62bf84aa3..246de2f5e 100644
--- a/tests/ui/deprecation/issue-84637-deprecated-associated-function.rs
+++ b/tests/ui/deprecation/issue-84637-deprecated-associated-function.rs
@@ -3,7 +3,7 @@
#![deny(deprecated)]
fn main() {
- let _foo = str::trim_left(" aoeu"); //~ ERROR use of deprecated associated function `core::str::<impl str>::trim_left`: superseded by `trim_start` [deprecated]
+ let _foo = str::trim_left(" aoeu"); //~ ERROR use of deprecated method `core::str::<impl str>::trim_left`: superseded by `trim_start` [deprecated]
- let _bar = " aoeu".trim_left(); //~ ERROR use of deprecated associated function `core::str::<impl str>::trim_left`: superseded by `trim_start` [deprecated]
+ let _bar = " aoeu".trim_left(); //~ ERROR use of deprecated method `core::str::<impl str>::trim_left`: superseded by `trim_start` [deprecated]
}
diff --git a/tests/ui/deprecation/issue-84637-deprecated-associated-function.stderr b/tests/ui/deprecation/issue-84637-deprecated-associated-function.stderr
index 8d4529526..3b518d180 100644
--- a/tests/ui/deprecation/issue-84637-deprecated-associated-function.stderr
+++ b/tests/ui/deprecation/issue-84637-deprecated-associated-function.stderr
@@ -1,4 +1,4 @@
-error: use of deprecated associated function `core::str::<impl str>::trim_left`: superseded by `trim_start`
+error: use of deprecated method `core::str::<impl str>::trim_left`: superseded by `trim_start`
--> $DIR/issue-84637-deprecated-associated-function.rs:6:21
|
LL | let _foo = str::trim_left(" aoeu");
@@ -9,18 +9,18 @@ note: the lint level is defined here
|
LL | #![deny(deprecated)]
| ^^^^^^^^^^
-help: replace the use of the deprecated associated function
+help: replace the use of the deprecated method
|
LL | let _foo = str::trim_start(" aoeu");
| ~~~~~~~~~~
-error: use of deprecated associated function `core::str::<impl str>::trim_left`: superseded by `trim_start`
+error: use of deprecated method `core::str::<impl str>::trim_left`: superseded by `trim_start`
--> $DIR/issue-84637-deprecated-associated-function.rs:8:26
|
LL | let _bar = " aoeu".trim_left();
| ^^^^^^^^^
|
-help: replace the use of the deprecated associated function
+help: replace the use of the deprecated method
|
LL | let _bar = " aoeu".trim_start();
| ~~~~~~~~~~
diff --git a/tests/ui/deprecation/suggestion.stderr b/tests/ui/deprecation/suggestion.stderr
index c5f2fc091..5584b6d2f 100644
--- a/tests/ui/deprecation/suggestion.stderr
+++ b/tests/ui/deprecation/suggestion.stderr
@@ -14,13 +14,13 @@ help: replace the use of the deprecated function
LL | bar::replacement();
| ~~~~~~~~~~~
-error: use of deprecated associated function `Foo::deprecated`: replaced by `replacement`
+error: use of deprecated method `Foo::deprecated`: replaced by `replacement`
--> $DIR/suggestion.rs:40:9
|
LL | foo.deprecated();
| ^^^^^^^^^^
|
-help: replace the use of the deprecated associated function
+help: replace the use of the deprecated method
|
LL | foo.replacement();
| ~~~~~~~~~~~
diff --git a/tests/ui/deref-patterns/gate.stderr b/tests/ui/deref-patterns/gate.stderr
index 993468b5e..b5b79ed37 100644
--- a/tests/ui/deref-patterns/gate.stderr
+++ b/tests/ui/deref-patterns/gate.stderr
@@ -4,7 +4,7 @@ error[E0308]: mismatched types
LL | match String::new() {
| ------------- this expression has type `String`
LL | "" | _ => {}
- | ^^ expected struct `String`, found `&str`
+ | ^^ expected `String`, found `&str`
error: aborting due to previous error
diff --git a/tests/ui/derives/deriving-copyclone.stderr b/tests/ui/derives/deriving-copyclone.stderr
index 9c4ca01ff..c0c2215c0 100644
--- a/tests/ui/derives/deriving-copyclone.stderr
+++ b/tests/ui/derives/deriving-copyclone.stderr
@@ -1,8 +1,8 @@
error[E0277]: the trait bound `B<C>: Copy` is not satisfied
- --> $DIR/deriving-copyclone.rs:31:13
+ --> $DIR/deriving-copyclone.rs:31:26
|
LL | is_copy(B { a: 1, b: C });
- | ------- ^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `B<C>`
+ | ------- ^ the trait `Copy` is not implemented for `B<C>`
| |
| required by a bound introduced by this call
|
@@ -19,14 +19,14 @@ LL | fn is_copy<T: Copy>(_: T) {}
= 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 });
- | +
+LL | is_copy(B { a: 1, b: &C });
+ | +
error[E0277]: the trait bound `B<C>: Clone` is not satisfied
- --> $DIR/deriving-copyclone.rs:32:14
+ --> $DIR/deriving-copyclone.rs:32:27
|
LL | is_clone(B { a: 1, b: C });
- | -------- ^^^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `B<C>`
+ | -------- ^ the trait `Clone` is not implemented for `B<C>`
| |
| required by a bound introduced by this call
|
@@ -43,14 +43,14 @@ LL | fn is_clone<T: Clone>(_: T) {}
= 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 });
- | +
+LL | is_clone(B { a: 1, b: &C });
+ | +
error[E0277]: the trait bound `B<D>: Copy` is not satisfied
- --> $DIR/deriving-copyclone.rs:35:13
+ --> $DIR/deriving-copyclone.rs:35:26
|
LL | is_copy(B { a: 1, b: D });
- | ------- ^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `B<D>`
+ | ------- ^ the trait `Copy` is not implemented for `B<D>`
| |
| required by a bound introduced by this call
|
@@ -67,8 +67,8 @@ LL | fn is_copy<T: Copy>(_: T) {}
= 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 });
- | +
+LL | is_copy(B { a: 1, b: &D });
+ | +
error: aborting due to 3 previous errors
diff --git a/tests/ui/derives/deriving-with-repr-packed-2.rs b/tests/ui/derives/deriving-with-repr-packed-2.rs
new file mode 100644
index 000000000..79aca74df
--- /dev/null
+++ b/tests/ui/derives/deriving-with-repr-packed-2.rs
@@ -0,0 +1,20 @@
+// Check that deriving certain builtin traits on certain packed structs cause
+// errors. To avoid potentially misaligned references, field copies must be
+// used, which involves adding `T: Copy` bounds.
+
+#[derive(Copy, Clone, Default, PartialEq, Eq)]
+#[repr(packed)]
+pub struct Foo<T>(T, T, T);
+
+struct NonCopy;
+
+fn main() {
+ // This one is fine because `u32` impls `Copy`.
+ let x: Foo<u32> = Foo(1, 2, 3);
+ _ = x.clone();
+
+ // This one is an error because `NonCopy` doesn't impl `Copy`.
+ let x: Foo<NonCopy> = Foo(NonCopy, NonCopy, NonCopy);
+ _ = x.clone();
+ //~^ ERROR the method `clone` exists for struct `Foo<NonCopy>`, but its trait bounds were not satisfied
+}
diff --git a/tests/ui/derives/deriving-with-repr-packed-2.stderr b/tests/ui/derives/deriving-with-repr-packed-2.stderr
new file mode 100644
index 000000000..ab3646057
--- /dev/null
+++ b/tests/ui/derives/deriving-with-repr-packed-2.stderr
@@ -0,0 +1,33 @@
+error[E0599]: the method `clone` exists for struct `Foo<NonCopy>`, but its trait bounds were not satisfied
+ --> $DIR/deriving-with-repr-packed-2.rs:18:11
+ |
+LL | pub struct Foo<T>(T, T, T);
+ | -----------------
+ | |
+ | method `clone` not found for this struct
+ | doesn't satisfy `Foo<NonCopy>: Clone`
+LL |
+LL | struct NonCopy;
+ | --------------
+ | |
+ | doesn't satisfy `NonCopy: Clone`
+ | doesn't satisfy `NonCopy: Copy`
+...
+LL | _ = x.clone();
+ | ^^^^^ method cannot be called on `Foo<NonCopy>` due to unsatisfied trait bounds
+ |
+note: the following trait bounds were not satisfied:
+ `NonCopy: Clone`
+ `NonCopy: Copy`
+ --> $DIR/deriving-with-repr-packed-2.rs:5:16
+ |
+LL | #[derive(Copy, Clone, Default, PartialEq, Eq)]
+ | ^^^^^ unsatisfied trait bound introduced in this `derive` macro
+help: consider annotating `NonCopy` with `#[derive(Clone, Copy)]`
+ |
+LL | #[derive(Clone, Copy)]
+ |
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0599`.
diff --git a/tests/ui/derives/deriving-with-repr-packed.rs b/tests/ui/derives/deriving-with-repr-packed.rs
index 3884e3977..58be45197 100644
--- a/tests/ui/derives/deriving-with-repr-packed.rs
+++ b/tests/ui/derives/deriving-with-repr-packed.rs
@@ -1,45 +1,46 @@
-#![deny(unaligned_references)]
-
// Check that deriving certain builtin traits on certain packed structs cause
-// errors. This happens when the derived trait would need to use a potentially
-// misaligned reference. But there are two cases that are allowed:
-// - If all the fields within the struct meet the required alignment: 1 for
-// `repr(packed)`, or `N` for `repr(packed(N))`.
-// - If `Default` is the only trait derived, because it doesn't involve any
-// references.
+// errors. To avoid potentially misaligned references, field copies must be
+// used, which involves adding `T: Copy` bounds.
#[derive(Copy, Clone, Default, PartialEq, Eq)]
-//~^ ERROR `Clone` can't be derived on this `#[repr(packed)]` struct with type or const parameters
-//~| hard error
-//~^^^ ERROR `PartialEq` can't be derived on this `#[repr(packed)]` struct with type or const parameters
-//~| hard error
#[repr(packed)]
pub struct Foo<T>(T, T, T);
+// This one is fine because the fields all impl `Copy`.
#[derive(Default, Hash)]
-//~^ ERROR `Hash` can't be derived on this `#[repr(packed)]` struct that does not derive `Copy`
-//~| hard error
#[repr(packed)]
pub struct Bar(u32, u32, u32);
-// This one is fine because the field alignment is 1.
-#[derive(Default, Hash)]
-#[repr(packed)]
-pub struct Bar2(u8, i8, bool);
-
-// This one is fine because the field alignment is 2, matching `packed(2)`.
-#[derive(Default, Hash)]
-#[repr(packed(2))]
-pub struct Bar3(u16, i16, bool);
-
// This one is fine because it's not packed.
#[derive(Debug, Default)]
struct Y(usize);
+// This one has an error because `Y` doesn't impl `Copy`.
+// Note: there is room for improvement in the error message.
#[derive(Debug, Default)]
-//~^ ERROR `Debug` can't be derived on this `#[repr(packed)]` struct that does not derive `Copy`
-//~| hard error
#[repr(packed)]
struct X(Y);
+//~^ ERROR cannot move out of `self` which is behind a shared reference
+
+// This is currently allowed, but will be phased out at some point. From
+// `zerovec` within icu4x-0.9.0.
+#[derive(Debug)]
+#[repr(packed)]
+struct FlexZeroSlice {
+ width: u8,
+ data: [u8],
+ //~^ WARNING byte slice in a packed struct that derives a built-in trait
+ //~^^ this was previously accepted
+}
+
+// Again, currently allowed, but will be phased out.
+#[derive(Debug)]
+#[repr(packed)]
+struct WithStr {
+ width: u8,
+ data: str,
+ //~^ WARNING string slice in a packed struct that derives a built-in trait
+ //~^^ this was previously accepted
+}
fn main() {}
diff --git a/tests/ui/derives/deriving-with-repr-packed.stderr b/tests/ui/derives/deriving-with-repr-packed.stderr
index 0ad800c39..0cfe03869 100644
--- a/tests/ui/derives/deriving-with-repr-packed.stderr
+++ b/tests/ui/derives/deriving-with-repr-packed.stderr
@@ -1,111 +1,75 @@
-error: `Clone` can't be derived on this `#[repr(packed)]` struct with type or const parameters
- --> $DIR/deriving-with-repr-packed.rs:11:16
+warning: byte slice in a packed struct that derives a built-in trait
+ --> $DIR/deriving-with-repr-packed.rs:31:5
|
-LL | #[derive(Copy, Clone, Default, PartialEq, Eq)]
- | ^^^^^
+LL | #[derive(Debug)]
+ | ----- in this derive macro expansion
+...
+LL | data: [u8],
+ | ^^^^^^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523>
-note: the lint level is defined here
- --> $DIR/deriving-with-repr-packed.rs:1:9
- |
-LL | #![deny(unaligned_references)]
- | ^^^^^^^^^^^^^^^^^^^^
- = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info)
-
-error: `PartialEq` can't be derived on this `#[repr(packed)]` struct with type or const parameters
- --> $DIR/deriving-with-repr-packed.rs:11:32
- |
-LL | #[derive(Copy, Clone, Default, PartialEq, Eq)]
- | ^^^^^^^^^
- |
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523>
- = note: this error originates in the derive macro `PartialEq` (in Nightly builds, run with -Z macro-backtrace for more info)
+ = note: for more information, see issue #107457 <https://github.com/rust-lang/rust/issues/107457>
+ = help: consider implementing the trait by hand, or remove the `packed` attribute
+ = note: `#[warn(byte_slice_in_packed_struct_with_derive)]` on by default
+ = note: this warning originates in the derive macro `Debug` (in Nightly builds, run with -Z macro-backtrace for more info)
-error: `Hash` can't be derived on this `#[repr(packed)]` struct that does not derive `Copy`
- --> $DIR/deriving-with-repr-packed.rs:19:19
+warning: string slice in a packed struct that derives a built-in trait
+ --> $DIR/deriving-with-repr-packed.rs:41:5
|
-LL | #[derive(Default, Hash)]
- | ^^^^
+LL | #[derive(Debug)]
+ | ----- in this derive macro expansion
+...
+LL | data: str,
+ | ^^^^^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523>
- = note: this error originates in the derive macro `Hash` (in Nightly builds, run with -Z macro-backtrace for more info)
+ = note: for more information, see issue #107457 <https://github.com/rust-lang/rust/issues/107457>
+ = help: consider implementing the trait by hand, or remove the `packed` attribute
+ = note: this warning originates in the derive macro `Debug` (in Nightly builds, run with -Z macro-backtrace for more info)
-error: `Debug` can't be derived on this `#[repr(packed)]` struct that does not derive `Copy`
- --> $DIR/deriving-with-repr-packed.rs:39:10
+error[E0507]: cannot move out of `self` which is behind a shared reference
+ --> $DIR/deriving-with-repr-packed.rs:22:10
|
LL | #[derive(Debug, Default)]
- | ^^^^^
+ | ----- in this derive macro expansion
+LL | #[repr(packed)]
+LL | struct X(Y);
+ | ^ move occurs because `self.0` has type `Y`, which does not implement the `Copy` trait
|
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523>
= note: this error originates in the derive macro `Debug` (in Nightly builds, run with -Z macro-backtrace for more info)
-error: aborting due to 4 previous errors
+error: aborting due to previous error; 2 warnings emitted
+For more information about this error, try `rustc --explain E0507`.
Future incompatibility report: Future breakage diagnostic:
-error: `Clone` can't be derived on this `#[repr(packed)]` struct with type or const parameters
- --> $DIR/deriving-with-repr-packed.rs:11:16
- |
-LL | #[derive(Copy, Clone, Default, PartialEq, Eq)]
- | ^^^^^
- |
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523>
-note: the lint level is defined here
- --> $DIR/deriving-with-repr-packed.rs:1:9
- |
-LL | #![deny(unaligned_references)]
- | ^^^^^^^^^^^^^^^^^^^^
- = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info)
-
-Future breakage diagnostic:
-error: `PartialEq` can't be derived on this `#[repr(packed)]` struct with type or const parameters
- --> $DIR/deriving-with-repr-packed.rs:11:32
+warning: byte slice in a packed struct that derives a built-in trait
+ --> $DIR/deriving-with-repr-packed.rs:31:5
|
-LL | #[derive(Copy, Clone, Default, PartialEq, Eq)]
- | ^^^^^^^^^
+LL | #[derive(Debug)]
+ | ----- in this derive macro expansion
+...
+LL | data: [u8],
+ | ^^^^^^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523>
-note: the lint level is defined here
- --> $DIR/deriving-with-repr-packed.rs:1:9
- |
-LL | #![deny(unaligned_references)]
- | ^^^^^^^^^^^^^^^^^^^^
- = note: this error originates in the derive macro `PartialEq` (in Nightly builds, run with -Z macro-backtrace for more info)
+ = note: for more information, see issue #107457 <https://github.com/rust-lang/rust/issues/107457>
+ = help: consider implementing the trait by hand, or remove the `packed` attribute
+ = note: `#[warn(byte_slice_in_packed_struct_with_derive)]` on by default
+ = note: this warning originates in the derive macro `Debug` (in Nightly builds, run with -Z macro-backtrace for more info)
Future breakage diagnostic:
-error: `Hash` can't be derived on this `#[repr(packed)]` struct that does not derive `Copy`
- --> $DIR/deriving-with-repr-packed.rs:19:19
+warning: string slice in a packed struct that derives a built-in trait
+ --> $DIR/deriving-with-repr-packed.rs:41:5
|
-LL | #[derive(Default, Hash)]
- | ^^^^
+LL | #[derive(Debug)]
+ | ----- in this derive macro expansion
+...
+LL | data: str,
+ | ^^^^^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523>
-note: the lint level is defined here
- --> $DIR/deriving-with-repr-packed.rs:1:9
- |
-LL | #![deny(unaligned_references)]
- | ^^^^^^^^^^^^^^^^^^^^
- = note: this error originates in the derive macro `Hash` (in Nightly builds, run with -Z macro-backtrace for more info)
-
-Future breakage diagnostic:
-error: `Debug` can't be derived on this `#[repr(packed)]` struct that does not derive `Copy`
- --> $DIR/deriving-with-repr-packed.rs:39:10
- |
-LL | #[derive(Debug, Default)]
- | ^^^^^
- |
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523>
-note: the lint level is defined here
- --> $DIR/deriving-with-repr-packed.rs:1:9
- |
-LL | #![deny(unaligned_references)]
- | ^^^^^^^^^^^^^^^^^^^^
- = note: this error originates in the derive macro `Debug` (in Nightly builds, run with -Z macro-backtrace for more info)
+ = note: for more information, see issue #107457 <https://github.com/rust-lang/rust/issues/107457>
+ = help: consider implementing the trait by hand, or remove the `packed` attribute
+ = note: `#[warn(byte_slice_in_packed_struct_with_derive)]` on by default
+ = note: this warning originates in the derive macro `Debug` (in Nightly builds, run with -Z macro-backtrace for more info)
diff --git a/tests/ui/deriving/deriving-all-codegen.rs b/tests/ui/deriving/deriving-all-codegen.rs
index ba7809413..51f9708d3 100644
--- a/tests/ui/deriving/deriving-all-codegen.rs
+++ b/tests/ui/deriving/deriving-all-codegen.rs
@@ -21,36 +21,88 @@
#[derive(Clone, Copy, Debug, Default, Hash, PartialEq, Eq, PartialOrd, Ord)]
struct Empty;
-// A basic struct.
+// A basic struct. Note: because this derives `Copy`, it gets the simple
+// `clone` implemention that just does `*self`.
#[derive(Clone, Copy, Debug, Default, Hash, PartialEq, Eq, PartialOrd, Ord)]
struct Point {
x: u32,
y: u32,
}
-// A large struct.
-#[derive(Clone, Debug, Default, Hash, PartialEq, Eq, PartialOrd, Ord)]
+// A basic packed struct. Note: because this derives `Copy`, it gets the simple
+// `clone` implemention that just does `*self`.
+#[derive(Clone, Copy, Debug, Default, Hash, PartialEq, Eq, PartialOrd, Ord)]
+#[repr(packed)]
+struct PackedPoint {
+ x: u32,
+ y: u32,
+}
+
+// A large struct. Note: because this derives `Copy`, it gets the simple
+// `clone` implemention that just does `*self`.
+#[derive(Clone, Copy, Debug, Default, Hash, PartialEq, Eq, PartialOrd, Ord)]
struct Big {
b1: u32, b2: u32, b3: u32, b4: u32, b5: u32, b6: u32, b7: u32, b8: u32,
}
+// A struct that doesn't impl `Copy`, which means it gets the non-simple
+// `clone` implemention that clones the fields individually.
+#[derive(Clone)]
+struct NonCopy(u32);
+
+// A packed struct that doesn't impl `Copy`, which means it gets the non-simple
+// `clone` implemention that clones the fields individually.
+#[derive(Clone)]
+#[repr(packed)]
+struct PackedNonCopy(u32);
+
+// A struct that impls `Copy` manually, which means it gets the non-simple
+// `clone` implemention that clones the fields individually.
+#[derive(Clone)]
+struct ManualCopy(u32);
+impl Copy for ManualCopy {}
+
+// A packed struct that impls `Copy` manually, which means it gets the
+// non-simple `clone` implemention that clones the fields individually.
+#[derive(Clone)]
+#[repr(packed)]
+struct PackedManualCopy(u32);
+impl Copy for PackedManualCopy {}
+
// A struct with an unsized field. Some derives are not usable in this case.
#[derive(Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
struct Unsized([u32]);
-// A packed tuple struct that impls `Copy`.
-#[derive(Clone, Copy, Debug, Default, Hash, PartialEq, Eq, PartialOrd, Ord)]
+// A packed struct with an unsized `[u8]` field. This is currently allowed, but
+// causes a warning and will be phased out at some point.
+#[derive(Debug, Hash)]
#[repr(packed)]
-struct PackedCopy(u32);
+struct PackedUnsizedU8([u8]);
+//~^ WARNING byte slice in a packed struct that derives a built-in trait
+//~^^ WARNING byte slice in a packed struct that derives a built-in trait
+//~^^^ this was previously accepted
+//~^^^^ this was previously accepted
-// A packed tuple struct that does not impl `Copy`. Note that the alignment of
-// the field must be 1 for this code to be valid. Otherwise it triggers an
-// error "`#[derive]` can't be used on a `#[repr(packed)]` struct that does not
-// derive Copy (error E0133)" at MIR building time. This is a weird case and
-// it's possible that this struct is not supposed to work, but for now it does.
-#[derive(Clone, Debug, Default, Hash, PartialEq, Eq, PartialOrd, Ord)]
+trait Trait {
+ type A;
+}
+
+// A generic struct involving an associated type.
+#[derive(Clone, Copy, Debug, Default, Hash, PartialEq, Eq, PartialOrd, Ord)]
+struct Generic<T: Trait, U> {
+ t: T,
+ ta: T::A,
+ u: U,
+}
+
+// A packed, generic tuple struct involving an associated type. Because it is
+// packed, a `T: Copy` bound is added to all impls (and where clauses within
+// them) except for `Default`. This is because we must access fields using
+// copies (e.g. `&{self.0}`), instead of using direct references (e.g.
+// `&self.0`) which may be misaligned in a packed struct.
+#[derive(Clone, Copy, Debug, Default, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[repr(packed)]
-struct PackedNonCopy(u8);
+struct PackedGeneric<T: Trait, U>(T, T::A, U);
// An empty enum.
#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
@@ -97,6 +149,13 @@ enum Fielded {
Z(Option<i32>),
}
+// A generic enum. Note that `Default` cannot be derived for this enum.
+#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
+enum EnumGeneric<T, U> {
+ One(T),
+ Two(U),
+}
+
// A union. Most builtin traits are not derivable for unions.
#[derive(Clone, Copy)]
pub union Union {
diff --git a/tests/ui/deriving/deriving-all-codegen.stderr b/tests/ui/deriving/deriving-all-codegen.stderr
new file mode 100644
index 000000000..503f0cae7
--- /dev/null
+++ b/tests/ui/deriving/deriving-all-codegen.stderr
@@ -0,0 +1,63 @@
+warning: byte slice in a packed struct that derives a built-in trait
+ --> $DIR/deriving-all-codegen.rs:80:24
+ |
+LL | #[derive(Debug, Hash)]
+ | ----- in this derive macro expansion
+LL | #[repr(packed)]
+LL | struct PackedUnsizedU8([u8]);
+ | ^^^^
+ |
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #107457 <https://github.com/rust-lang/rust/issues/107457>
+ = help: consider implementing the trait by hand, or remove the `packed` attribute
+ = note: `#[warn(byte_slice_in_packed_struct_with_derive)]` on by default
+ = note: this warning originates in the derive macro `Debug` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+warning: byte slice in a packed struct that derives a built-in trait
+ --> $DIR/deriving-all-codegen.rs:80:24
+ |
+LL | #[derive(Debug, Hash)]
+ | ---- in this derive macro expansion
+LL | #[repr(packed)]
+LL | struct PackedUnsizedU8([u8]);
+ | ^^^^
+ |
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #107457 <https://github.com/rust-lang/rust/issues/107457>
+ = help: consider implementing the trait by hand, or remove the `packed` attribute
+ = note: this warning originates in the derive macro `Hash` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+warning: 2 warnings emitted
+
+Future incompatibility report: Future breakage diagnostic:
+warning: byte slice in a packed struct that derives a built-in trait
+ --> $DIR/deriving-all-codegen.rs:80:24
+ |
+LL | #[derive(Debug, Hash)]
+ | ----- in this derive macro expansion
+LL | #[repr(packed)]
+LL | struct PackedUnsizedU8([u8]);
+ | ^^^^
+ |
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #107457 <https://github.com/rust-lang/rust/issues/107457>
+ = help: consider implementing the trait by hand, or remove the `packed` attribute
+ = note: `#[warn(byte_slice_in_packed_struct_with_derive)]` on by default
+ = note: this warning originates in the derive macro `Debug` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+Future breakage diagnostic:
+warning: byte slice in a packed struct that derives a built-in trait
+ --> $DIR/deriving-all-codegen.rs:80:24
+ |
+LL | #[derive(Debug, Hash)]
+ | ---- in this derive macro expansion
+LL | #[repr(packed)]
+LL | struct PackedUnsizedU8([u8]);
+ | ^^^^
+ |
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #107457 <https://github.com/rust-lang/rust/issues/107457>
+ = help: consider implementing the trait by hand, or remove the `packed` attribute
+ = note: `#[warn(byte_slice_in_packed_struct_with_derive)]` on by default
+ = note: this warning originates in the derive macro `Hash` (in Nightly builds, run with -Z macro-backtrace for more info)
+
diff --git a/tests/ui/deriving/deriving-all-codegen.stdout b/tests/ui/deriving/deriving-all-codegen.stdout
index e6ee11a78..5bca83e87 100644
--- a/tests/ui/deriving/deriving-all-codegen.stdout
+++ b/tests/ui/deriving/deriving-all-codegen.stdout
@@ -78,7 +78,8 @@ impl ::core::cmp::Ord for Empty {
}
}
-// A basic struct.
+// A basic struct. Note: because this derives `Copy`, it gets the simple
+// `clone` implemention that just does `*self`.
struct Point {
x: u32,
y: u32,
@@ -97,7 +98,7 @@ impl ::core::marker::Copy for Point { }
impl ::core::fmt::Debug for Point {
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::debug_struct_field2_finish(f, "Point", "x",
- &&self.x, "y", &&self.y)
+ &self.x, "y", &&self.y)
}
}
#[automatically_derived]
@@ -161,7 +162,95 @@ impl ::core::cmp::Ord for Point {
}
}
-// A large struct.
+// A basic packed struct. Note: because this derives `Copy`, it gets the simple
+// `clone` implemention that just does `*self`.
+#[repr(packed)]
+struct PackedPoint {
+ x: u32,
+ y: u32,
+}
+#[automatically_derived]
+impl ::core::clone::Clone for PackedPoint {
+ #[inline]
+ fn clone(&self) -> PackedPoint {
+ let _: ::core::clone::AssertParamIsClone<u32>;
+ *self
+ }
+}
+#[automatically_derived]
+impl ::core::marker::Copy for PackedPoint { }
+#[automatically_derived]
+impl ::core::fmt::Debug for PackedPoint {
+ fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
+ ::core::fmt::Formatter::debug_struct_field2_finish(f, "PackedPoint",
+ "x", &{ self.x }, "y", &&{ self.y })
+ }
+}
+#[automatically_derived]
+impl ::core::default::Default for PackedPoint {
+ #[inline]
+ fn default() -> PackedPoint {
+ PackedPoint {
+ x: ::core::default::Default::default(),
+ y: ::core::default::Default::default(),
+ }
+ }
+}
+#[automatically_derived]
+impl ::core::hash::Hash for PackedPoint {
+ fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) -> () {
+ ::core::hash::Hash::hash(&{ self.x }, state);
+ ::core::hash::Hash::hash(&{ self.y }, state)
+ }
+}
+#[automatically_derived]
+impl ::core::marker::StructuralPartialEq for PackedPoint { }
+#[automatically_derived]
+impl ::core::cmp::PartialEq for PackedPoint {
+ #[inline]
+ fn eq(&self, other: &PackedPoint) -> bool {
+ ({ self.x }) == ({ other.x }) && ({ self.y }) == ({ other.y })
+ }
+}
+#[automatically_derived]
+impl ::core::marker::StructuralEq for PackedPoint { }
+#[automatically_derived]
+impl ::core::cmp::Eq for PackedPoint {
+ #[inline]
+ #[doc(hidden)]
+ #[no_coverage]
+ fn assert_receiver_is_total_eq(&self) -> () {
+ let _: ::core::cmp::AssertParamIsEq<u32>;
+ }
+}
+#[automatically_derived]
+impl ::core::cmp::PartialOrd for PackedPoint {
+ #[inline]
+ fn partial_cmp(&self, other: &PackedPoint)
+ -> ::core::option::Option<::core::cmp::Ordering> {
+ match ::core::cmp::PartialOrd::partial_cmp(&{ self.x }, &{ other.x })
+ {
+ ::core::option::Option::Some(::core::cmp::Ordering::Equal) =>
+ ::core::cmp::PartialOrd::partial_cmp(&{ self.y },
+ &{ other.y }),
+ cmp => cmp,
+ }
+ }
+}
+#[automatically_derived]
+impl ::core::cmp::Ord for PackedPoint {
+ #[inline]
+ fn cmp(&self, other: &PackedPoint) -> ::core::cmp::Ordering {
+ match ::core::cmp::Ord::cmp(&{ self.x }, &{ other.x }) {
+ ::core::cmp::Ordering::Equal =>
+ ::core::cmp::Ord::cmp(&{ self.y }, &{ other.y }),
+ cmp => cmp,
+ }
+ }
+}
+
+// A large struct. Note: because this derives `Copy`, it gets the simple
+// `clone` implemention that just does `*self`.
struct Big {
b1: u32,
b2: u32,
@@ -176,26 +265,20 @@ struct Big {
impl ::core::clone::Clone for Big {
#[inline]
fn clone(&self) -> Big {
- Big {
- b1: ::core::clone::Clone::clone(&self.b1),
- b2: ::core::clone::Clone::clone(&self.b2),
- b3: ::core::clone::Clone::clone(&self.b3),
- b4: ::core::clone::Clone::clone(&self.b4),
- b5: ::core::clone::Clone::clone(&self.b5),
- b6: ::core::clone::Clone::clone(&self.b6),
- b7: ::core::clone::Clone::clone(&self.b7),
- b8: ::core::clone::Clone::clone(&self.b8),
- }
+ let _: ::core::clone::AssertParamIsClone<u32>;
+ *self
}
}
#[automatically_derived]
+impl ::core::marker::Copy for Big { }
+#[automatically_derived]
impl ::core::fmt::Debug for Big {
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
let names: &'static _ =
&["b1", "b2", "b3", "b4", "b5", "b6", "b7", "b8"];
let values: &[&dyn ::core::fmt::Debug] =
- &[&&self.b1, &&self.b2, &&self.b3, &&self.b4, &&self.b5,
- &&self.b6, &&self.b7, &&self.b8];
+ &[&self.b1, &self.b2, &self.b3, &self.b4, &self.b5, &self.b6,
+ &self.b7, &&self.b8];
::core::fmt::Formatter::debug_struct_fields_finish(f, "Big", names,
values)
}
@@ -336,6 +419,54 @@ impl ::core::cmp::Ord for Big {
}
}
+// A struct that doesn't impl `Copy`, which means it gets the non-simple
+// `clone` implemention that clones the fields individually.
+struct NonCopy(u32);
+#[automatically_derived]
+impl ::core::clone::Clone for NonCopy {
+ #[inline]
+ fn clone(&self) -> NonCopy {
+ NonCopy(::core::clone::Clone::clone(&self.0))
+ }
+}
+
+// A packed struct that doesn't impl `Copy`, which means it gets the non-simple
+// `clone` implemention that clones the fields individually.
+#[repr(packed)]
+struct PackedNonCopy(u32);
+#[automatically_derived]
+impl ::core::clone::Clone for PackedNonCopy {
+ #[inline]
+ fn clone(&self) -> PackedNonCopy {
+ PackedNonCopy(::core::clone::Clone::clone(&{ self.0 }))
+ }
+}
+
+// A struct that impls `Copy` manually, which means it gets the non-simple
+// `clone` implemention that clones the fields individually.
+struct ManualCopy(u32);
+#[automatically_derived]
+impl ::core::clone::Clone for ManualCopy {
+ #[inline]
+ fn clone(&self) -> ManualCopy {
+ ManualCopy(::core::clone::Clone::clone(&self.0))
+ }
+}
+impl Copy for ManualCopy {}
+
+// A packed struct that impls `Copy` manually, which means it gets the
+// non-simple `clone` implemention that clones the fields individually.
+#[repr(packed)]
+struct PackedManualCopy(u32);
+#[automatically_derived]
+impl ::core::clone::Clone for PackedManualCopy {
+ #[inline]
+ fn clone(&self) -> PackedManualCopy {
+ PackedManualCopy(::core::clone::Clone::clone(&{ self.0 }))
+ }
+}
+impl Copy for PackedManualCopy {}
+
// A struct with an unsized field. Some derives are not usable in this case.
struct Unsized([u32]);
#[automatically_derived]
@@ -385,138 +516,265 @@ impl ::core::cmp::Ord for Unsized {
}
}
-// A packed tuple struct that impls `Copy`.
+// A packed struct with an unsized `[u8]` field. This is currently allowed, but
+// causes a warning and will be phased out at some point.
#[repr(packed)]
-struct PackedCopy(u32);
+struct PackedUnsizedU8([u8]);
#[automatically_derived]
-impl ::core::clone::Clone for PackedCopy {
+impl ::core::fmt::Debug for PackedUnsizedU8 {
+ fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
+ ::core::fmt::Formatter::debug_tuple_field1_finish(f,
+ "PackedUnsizedU8", &&self.0)
+ }
+}
+#[automatically_derived]
+impl ::core::hash::Hash for PackedUnsizedU8 {
+ fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) -> () {
+ ::core::hash::Hash::hash(&self.0, state)
+ }
+}
+
+trait Trait {
+ type A;
+}
+
+// A generic struct involving an associated type.
+struct Generic<T: Trait, U> {
+ t: T,
+ ta: T::A,
+ u: U,
+}
+#[automatically_derived]
+impl<T: ::core::clone::Clone + Trait, U: ::core::clone::Clone>
+ ::core::clone::Clone for Generic<T, U> where T::A: ::core::clone::Clone {
#[inline]
- fn clone(&self) -> PackedCopy {
- let _: ::core::clone::AssertParamIsClone<u32>;
- *self
+ fn clone(&self) -> Generic<T, U> {
+ Generic {
+ t: ::core::clone::Clone::clone(&self.t),
+ ta: ::core::clone::Clone::clone(&self.ta),
+ u: ::core::clone::Clone::clone(&self.u),
+ }
}
}
#[automatically_derived]
-impl ::core::marker::Copy for PackedCopy { }
+impl<T: ::core::marker::Copy + Trait, U: ::core::marker::Copy>
+ ::core::marker::Copy for Generic<T, U> where T::A: ::core::marker::Copy {
+}
#[automatically_derived]
-impl ::core::fmt::Debug for PackedCopy {
+impl<T: ::core::fmt::Debug + Trait, U: ::core::fmt::Debug> ::core::fmt::Debug
+ for Generic<T, U> where T::A: ::core::fmt::Debug {
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
- ::core::fmt::Formatter::debug_tuple_field1_finish(f, "PackedCopy",
- &&{ self.0 })
+ ::core::fmt::Formatter::debug_struct_field3_finish(f, "Generic", "t",
+ &self.t, "ta", &self.ta, "u", &&self.u)
}
}
#[automatically_derived]
-impl ::core::default::Default for PackedCopy {
+impl<T: ::core::default::Default + Trait, U: ::core::default::Default>
+ ::core::default::Default for Generic<T, U> where
+ T::A: ::core::default::Default {
#[inline]
- fn default() -> PackedCopy {
- PackedCopy(::core::default::Default::default())
+ fn default() -> Generic<T, U> {
+ Generic {
+ t: ::core::default::Default::default(),
+ ta: ::core::default::Default::default(),
+ u: ::core::default::Default::default(),
+ }
}
}
#[automatically_derived]
-impl ::core::hash::Hash for PackedCopy {
+impl<T: ::core::hash::Hash + Trait, U: ::core::hash::Hash> ::core::hash::Hash
+ for Generic<T, U> where T::A: ::core::hash::Hash {
fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) -> () {
- ::core::hash::Hash::hash(&{ self.0 }, state)
+ ::core::hash::Hash::hash(&self.t, state);
+ ::core::hash::Hash::hash(&self.ta, state);
+ ::core::hash::Hash::hash(&self.u, state)
}
}
#[automatically_derived]
-impl ::core::marker::StructuralPartialEq for PackedCopy { }
+impl<T: Trait, U> ::core::marker::StructuralPartialEq for Generic<T, U> { }
#[automatically_derived]
-impl ::core::cmp::PartialEq for PackedCopy {
+impl<T: ::core::cmp::PartialEq + Trait, U: ::core::cmp::PartialEq>
+ ::core::cmp::PartialEq for Generic<T, U> where
+ T::A: ::core::cmp::PartialEq {
#[inline]
- fn eq(&self, other: &PackedCopy) -> bool { { self.0 } == { other.0 } }
+ fn eq(&self, other: &Generic<T, U>) -> bool {
+ self.t == other.t && self.ta == other.ta && self.u == other.u
+ }
}
#[automatically_derived]
-impl ::core::marker::StructuralEq for PackedCopy { }
+impl<T: Trait, U> ::core::marker::StructuralEq for Generic<T, U> { }
#[automatically_derived]
-impl ::core::cmp::Eq for PackedCopy {
+impl<T: ::core::cmp::Eq + Trait, U: ::core::cmp::Eq> ::core::cmp::Eq for
+ Generic<T, U> where T::A: ::core::cmp::Eq {
#[inline]
#[doc(hidden)]
#[no_coverage]
fn assert_receiver_is_total_eq(&self) -> () {
- let _: ::core::cmp::AssertParamIsEq<u32>;
+ let _: ::core::cmp::AssertParamIsEq<T>;
+ let _: ::core::cmp::AssertParamIsEq<T::A>;
+ let _: ::core::cmp::AssertParamIsEq<U>;
}
}
#[automatically_derived]
-impl ::core::cmp::PartialOrd for PackedCopy {
+impl<T: ::core::cmp::PartialOrd + Trait, U: ::core::cmp::PartialOrd>
+ ::core::cmp::PartialOrd for Generic<T, U> where
+ T::A: ::core::cmp::PartialOrd {
#[inline]
- fn partial_cmp(&self, other: &PackedCopy)
+ fn partial_cmp(&self, other: &Generic<T, U>)
-> ::core::option::Option<::core::cmp::Ordering> {
- ::core::cmp::PartialOrd::partial_cmp(&{ self.0 }, &{ other.0 })
+ match ::core::cmp::PartialOrd::partial_cmp(&self.t, &other.t) {
+ ::core::option::Option::Some(::core::cmp::Ordering::Equal) =>
+ match ::core::cmp::PartialOrd::partial_cmp(&self.ta,
+ &other.ta) {
+ ::core::option::Option::Some(::core::cmp::Ordering::Equal)
+ => ::core::cmp::PartialOrd::partial_cmp(&self.u, &other.u),
+ cmp => cmp,
+ },
+ cmp => cmp,
+ }
}
}
#[automatically_derived]
-impl ::core::cmp::Ord for PackedCopy {
+impl<T: ::core::cmp::Ord + Trait, U: ::core::cmp::Ord> ::core::cmp::Ord for
+ Generic<T, U> where T::A: ::core::cmp::Ord {
#[inline]
- fn cmp(&self, other: &PackedCopy) -> ::core::cmp::Ordering {
- ::core::cmp::Ord::cmp(&{ self.0 }, &{ other.0 })
+ fn cmp(&self, other: &Generic<T, U>) -> ::core::cmp::Ordering {
+ match ::core::cmp::Ord::cmp(&self.t, &other.t) {
+ ::core::cmp::Ordering::Equal =>
+ match ::core::cmp::Ord::cmp(&self.ta, &other.ta) {
+ ::core::cmp::Ordering::Equal =>
+ ::core::cmp::Ord::cmp(&self.u, &other.u),
+ cmp => cmp,
+ },
+ cmp => cmp,
+ }
}
}
-// A packed tuple struct that does not impl `Copy`. Note that the alignment of
-// the field must be 1 for this code to be valid. Otherwise it triggers an
-// error "`#[derive]` can't be used on a `#[repr(packed)]` struct that does not
-// derive Copy (error E0133)" at MIR building time. This is a weird case and
-// it's possible that this struct is not supposed to work, but for now it does.
+// A packed, generic tuple struct involving an associated type. Because it is
+// packed, a `T: Copy` bound is added to all impls (and where clauses within
+// them) except for `Default`. This is because we must access fields using
+// copies (e.g. `&{self.0}`), instead of using direct references (e.g.
+// `&self.0`) which may be misaligned in a packed struct.
#[repr(packed)]
-struct PackedNonCopy(u8);
+struct PackedGeneric<T: Trait, U>(T, T::A, U);
#[automatically_derived]
-impl ::core::clone::Clone for PackedNonCopy {
+impl<T: ::core::clone::Clone + ::core::marker::Copy + Trait,
+ U: ::core::clone::Clone + ::core::marker::Copy> ::core::clone::Clone for
+ PackedGeneric<T, U> where T::A: ::core::clone::Clone +
+ ::core::marker::Copy {
#[inline]
- fn clone(&self) -> PackedNonCopy {
- PackedNonCopy(::core::clone::Clone::clone(&self.0))
+ fn clone(&self) -> PackedGeneric<T, U> {
+ PackedGeneric(::core::clone::Clone::clone(&{ self.0 }),
+ ::core::clone::Clone::clone(&{ self.1 }),
+ ::core::clone::Clone::clone(&{ self.2 }))
}
}
#[automatically_derived]
-impl ::core::fmt::Debug for PackedNonCopy {
+impl<T: ::core::marker::Copy + Trait, U: ::core::marker::Copy>
+ ::core::marker::Copy for PackedGeneric<T, U> where
+ T::A: ::core::marker::Copy {
+}
+#[automatically_derived]
+impl<T: ::core::fmt::Debug + ::core::marker::Copy + Trait,
+ U: ::core::fmt::Debug + ::core::marker::Copy> ::core::fmt::Debug for
+ PackedGeneric<T, U> where T::A: ::core::fmt::Debug + ::core::marker::Copy
+ {
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
- ::core::fmt::Formatter::debug_tuple_field1_finish(f, "PackedNonCopy",
- &&self.0)
+ ::core::fmt::Formatter::debug_tuple_field3_finish(f, "PackedGeneric",
+ &{ self.0 }, &{ self.1 }, &&{ self.2 })
}
}
#[automatically_derived]
-impl ::core::default::Default for PackedNonCopy {
+impl<T: ::core::default::Default + Trait, U: ::core::default::Default>
+ ::core::default::Default for PackedGeneric<T, U> where
+ T::A: ::core::default::Default {
#[inline]
- fn default() -> PackedNonCopy {
- PackedNonCopy(::core::default::Default::default())
+ fn default() -> PackedGeneric<T, U> {
+ PackedGeneric(::core::default::Default::default(),
+ ::core::default::Default::default(),
+ ::core::default::Default::default())
}
}
#[automatically_derived]
-impl ::core::hash::Hash for PackedNonCopy {
+impl<T: ::core::hash::Hash + ::core::marker::Copy + Trait,
+ U: ::core::hash::Hash + ::core::marker::Copy> ::core::hash::Hash for
+ PackedGeneric<T, U> where T::A: ::core::hash::Hash + ::core::marker::Copy
+ {
fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) -> () {
- ::core::hash::Hash::hash(&self.0, state)
+ ::core::hash::Hash::hash(&{ self.0 }, state);
+ ::core::hash::Hash::hash(&{ self.1 }, state);
+ ::core::hash::Hash::hash(&{ self.2 }, state)
}
}
#[automatically_derived]
-impl ::core::marker::StructuralPartialEq for PackedNonCopy { }
+impl<T: Trait, U> ::core::marker::StructuralPartialEq for PackedGeneric<T, U>
+ {
+}
#[automatically_derived]
-impl ::core::cmp::PartialEq for PackedNonCopy {
+impl<T: ::core::cmp::PartialEq + ::core::marker::Copy + Trait,
+ U: ::core::cmp::PartialEq + ::core::marker::Copy> ::core::cmp::PartialEq
+ for PackedGeneric<T, U> where T::A: ::core::cmp::PartialEq +
+ ::core::marker::Copy {
#[inline]
- fn eq(&self, other: &PackedNonCopy) -> bool { self.0 == other.0 }
+ fn eq(&self, other: &PackedGeneric<T, U>) -> bool {
+ ({ self.0 }) == ({ other.0 }) && ({ self.1 }) == ({ other.1 }) &&
+ ({ self.2 }) == ({ other.2 })
+ }
}
#[automatically_derived]
-impl ::core::marker::StructuralEq for PackedNonCopy { }
+impl<T: Trait, U> ::core::marker::StructuralEq for PackedGeneric<T, U> { }
#[automatically_derived]
-impl ::core::cmp::Eq for PackedNonCopy {
+impl<T: ::core::cmp::Eq + ::core::marker::Copy + Trait, U: ::core::cmp::Eq +
+ ::core::marker::Copy> ::core::cmp::Eq for PackedGeneric<T, U> where
+ T::A: ::core::cmp::Eq + ::core::marker::Copy {
#[inline]
#[doc(hidden)]
#[no_coverage]
fn assert_receiver_is_total_eq(&self) -> () {
- let _: ::core::cmp::AssertParamIsEq<u8>;
+ let _: ::core::cmp::AssertParamIsEq<T>;
+ let _: ::core::cmp::AssertParamIsEq<T::A>;
+ let _: ::core::cmp::AssertParamIsEq<U>;
}
}
#[automatically_derived]
-impl ::core::cmp::PartialOrd for PackedNonCopy {
+impl<T: ::core::cmp::PartialOrd + ::core::marker::Copy + Trait,
+ U: ::core::cmp::PartialOrd + ::core::marker::Copy> ::core::cmp::PartialOrd
+ for PackedGeneric<T, U> where T::A: ::core::cmp::PartialOrd +
+ ::core::marker::Copy {
#[inline]
- fn partial_cmp(&self, other: &PackedNonCopy)
+ fn partial_cmp(&self, other: &PackedGeneric<T, U>)
-> ::core::option::Option<::core::cmp::Ordering> {
- ::core::cmp::PartialOrd::partial_cmp(&self.0, &other.0)
+ match ::core::cmp::PartialOrd::partial_cmp(&{ self.0 }, &{ other.0 })
+ {
+ ::core::option::Option::Some(::core::cmp::Ordering::Equal) =>
+ match ::core::cmp::PartialOrd::partial_cmp(&{ self.1 },
+ &{ other.1 }) {
+ ::core::option::Option::Some(::core::cmp::Ordering::Equal)
+ =>
+ ::core::cmp::PartialOrd::partial_cmp(&{ self.2 },
+ &{ other.2 }),
+ cmp => cmp,
+ },
+ cmp => cmp,
+ }
}
}
#[automatically_derived]
-impl ::core::cmp::Ord for PackedNonCopy {
+impl<T: ::core::cmp::Ord + ::core::marker::Copy + Trait, U: ::core::cmp::Ord +
+ ::core::marker::Copy> ::core::cmp::Ord for PackedGeneric<T, U> where
+ T::A: ::core::cmp::Ord + ::core::marker::Copy {
#[inline]
- fn cmp(&self, other: &PackedNonCopy) -> ::core::cmp::Ordering {
- ::core::cmp::Ord::cmp(&self.0, &other.0)
+ fn cmp(&self, other: &PackedGeneric<T, U>) -> ::core::cmp::Ordering {
+ match ::core::cmp::Ord::cmp(&{ self.0 }, &{ other.0 }) {
+ ::core::cmp::Ordering::Equal =>
+ match ::core::cmp::Ord::cmp(&{ self.1 }, &{ other.1 }) {
+ ::core::cmp::Ordering::Equal =>
+ ::core::cmp::Ord::cmp(&{ self.2 }, &{ other.2 }),
+ cmp => cmp,
+ },
+ cmp => cmp,
+ }
}
}
@@ -826,7 +1084,7 @@ impl ::core::fmt::Debug for Mixed {
&__self_0),
Mixed::S { d1: __self_0, d2: __self_1 } =>
::core::fmt::Formatter::debug_struct_field2_finish(f, "S",
- "d1", &__self_0, "d2", &__self_1),
+ "d1", __self_0, "d2", &__self_1),
}
}
}
@@ -889,23 +1147,20 @@ impl ::core::cmp::PartialOrd for Mixed {
-> ::core::option::Option<::core::cmp::Ordering> {
let __self_tag = ::core::intrinsics::discriminant_value(self);
let __arg1_tag = ::core::intrinsics::discriminant_value(other);
- match ::core::cmp::PartialOrd::partial_cmp(&__self_tag, &__arg1_tag) {
- ::core::option::Option::Some(::core::cmp::Ordering::Equal) =>
- match (self, other) {
- (Mixed::R(__self_0), Mixed::R(__arg1_0)) =>
- ::core::cmp::PartialOrd::partial_cmp(__self_0, __arg1_0),
- (Mixed::S { d1: __self_0, d2: __self_1 }, Mixed::S {
- d1: __arg1_0, d2: __arg1_1 }) =>
- match ::core::cmp::PartialOrd::partial_cmp(__self_0,
- __arg1_0) {
- ::core::option::Option::Some(::core::cmp::Ordering::Equal)
- => ::core::cmp::PartialOrd::partial_cmp(__self_1, __arg1_1),
- cmp => cmp,
- },
- _ =>
- ::core::option::Option::Some(::core::cmp::Ordering::Equal),
+ match (self, other) {
+ (Mixed::R(__self_0), Mixed::R(__arg1_0)) =>
+ ::core::cmp::PartialOrd::partial_cmp(__self_0, __arg1_0),
+ (Mixed::S { d1: __self_0, d2: __self_1 }, Mixed::S {
+ d1: __arg1_0, d2: __arg1_1 }) =>
+ match ::core::cmp::PartialOrd::partial_cmp(__self_0, __arg1_0)
+ {
+ ::core::option::Option::Some(::core::cmp::Ordering::Equal)
+ => ::core::cmp::PartialOrd::partial_cmp(__self_1, __arg1_1),
+ cmp => cmp,
},
- cmp => cmp,
+ _ =>
+ ::core::cmp::PartialOrd::partial_cmp(&__self_tag,
+ &__arg1_tag),
}
}
}
@@ -1019,35 +1274,152 @@ impl ::core::cmp::PartialOrd for Fielded {
-> ::core::option::Option<::core::cmp::Ordering> {
let __self_tag = ::core::intrinsics::discriminant_value(self);
let __arg1_tag = ::core::intrinsics::discriminant_value(other);
- match ::core::cmp::PartialOrd::partial_cmp(&__self_tag, &__arg1_tag) {
- ::core::option::Option::Some(::core::cmp::Ordering::Equal) =>
+ match (self, other) {
+ (Fielded::X(__self_0), Fielded::X(__arg1_0)) =>
+ ::core::cmp::PartialOrd::partial_cmp(__self_0, __arg1_0),
+ (Fielded::Y(__self_0), Fielded::Y(__arg1_0)) =>
+ ::core::cmp::PartialOrd::partial_cmp(__self_0, __arg1_0),
+ (Fielded::Z(__self_0), Fielded::Z(__arg1_0)) =>
+ ::core::cmp::PartialOrd::partial_cmp(__self_0, __arg1_0),
+ _ =>
+ ::core::cmp::PartialOrd::partial_cmp(&__self_tag,
+ &__arg1_tag),
+ }
+ }
+}
+#[automatically_derived]
+impl ::core::cmp::Ord for Fielded {
+ #[inline]
+ fn cmp(&self, other: &Fielded) -> ::core::cmp::Ordering {
+ let __self_tag = ::core::intrinsics::discriminant_value(self);
+ let __arg1_tag = ::core::intrinsics::discriminant_value(other);
+ match ::core::cmp::Ord::cmp(&__self_tag, &__arg1_tag) {
+ ::core::cmp::Ordering::Equal =>
match (self, other) {
(Fielded::X(__self_0), Fielded::X(__arg1_0)) =>
- ::core::cmp::PartialOrd::partial_cmp(__self_0, __arg1_0),
+ ::core::cmp::Ord::cmp(__self_0, __arg1_0),
(Fielded::Y(__self_0), Fielded::Y(__arg1_0)) =>
- ::core::cmp::PartialOrd::partial_cmp(__self_0, __arg1_0),
+ ::core::cmp::Ord::cmp(__self_0, __arg1_0),
(Fielded::Z(__self_0), Fielded::Z(__arg1_0)) =>
- ::core::cmp::PartialOrd::partial_cmp(__self_0, __arg1_0),
+ ::core::cmp::Ord::cmp(__self_0, __arg1_0),
_ => unsafe { ::core::intrinsics::unreachable() }
},
cmp => cmp,
}
}
}
+
+// A generic enum. Note that `Default` cannot be derived for this enum.
+enum EnumGeneric<T, U> { One(T), Two(U), }
#[automatically_derived]
-impl ::core::cmp::Ord for Fielded {
+impl<T: ::core::clone::Clone, U: ::core::clone::Clone> ::core::clone::Clone
+ for EnumGeneric<T, U> {
#[inline]
- fn cmp(&self, other: &Fielded) -> ::core::cmp::Ordering {
+ fn clone(&self) -> EnumGeneric<T, U> {
+ match self {
+ EnumGeneric::One(__self_0) =>
+ EnumGeneric::One(::core::clone::Clone::clone(__self_0)),
+ EnumGeneric::Two(__self_0) =>
+ EnumGeneric::Two(::core::clone::Clone::clone(__self_0)),
+ }
+ }
+}
+#[automatically_derived]
+impl<T: ::core::marker::Copy, U: ::core::marker::Copy> ::core::marker::Copy
+ for EnumGeneric<T, U> {
+}
+#[automatically_derived]
+impl<T: ::core::fmt::Debug, U: ::core::fmt::Debug> ::core::fmt::Debug for
+ EnumGeneric<T, U> {
+ fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
+ match self {
+ EnumGeneric::One(__self_0) =>
+ ::core::fmt::Formatter::debug_tuple_field1_finish(f, "One",
+ &__self_0),
+ EnumGeneric::Two(__self_0) =>
+ ::core::fmt::Formatter::debug_tuple_field1_finish(f, "Two",
+ &__self_0),
+ }
+ }
+}
+#[automatically_derived]
+impl<T: ::core::hash::Hash, U: ::core::hash::Hash> ::core::hash::Hash for
+ EnumGeneric<T, U> {
+ fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) -> () {
+ let __self_tag = ::core::intrinsics::discriminant_value(self);
+ ::core::hash::Hash::hash(&__self_tag, state);
+ match self {
+ EnumGeneric::One(__self_0) =>
+ ::core::hash::Hash::hash(__self_0, state),
+ EnumGeneric::Two(__self_0) =>
+ ::core::hash::Hash::hash(__self_0, state),
+ }
+ }
+}
+#[automatically_derived]
+impl<T, U> ::core::marker::StructuralPartialEq for EnumGeneric<T, U> { }
+#[automatically_derived]
+impl<T: ::core::cmp::PartialEq, U: ::core::cmp::PartialEq>
+ ::core::cmp::PartialEq for EnumGeneric<T, U> {
+ #[inline]
+ fn eq(&self, other: &EnumGeneric<T, U>) -> bool {
+ let __self_tag = ::core::intrinsics::discriminant_value(self);
+ let __arg1_tag = ::core::intrinsics::discriminant_value(other);
+ __self_tag == __arg1_tag &&
+ match (self, other) {
+ (EnumGeneric::One(__self_0), EnumGeneric::One(__arg1_0)) =>
+ *__self_0 == *__arg1_0,
+ (EnumGeneric::Two(__self_0), EnumGeneric::Two(__arg1_0)) =>
+ *__self_0 == *__arg1_0,
+ _ => unsafe { ::core::intrinsics::unreachable() }
+ }
+ }
+}
+#[automatically_derived]
+impl<T, U> ::core::marker::StructuralEq for EnumGeneric<T, U> { }
+#[automatically_derived]
+impl<T: ::core::cmp::Eq, U: ::core::cmp::Eq> ::core::cmp::Eq for
+ EnumGeneric<T, U> {
+ #[inline]
+ #[doc(hidden)]
+ #[no_coverage]
+ fn assert_receiver_is_total_eq(&self) -> () {
+ let _: ::core::cmp::AssertParamIsEq<T>;
+ let _: ::core::cmp::AssertParamIsEq<U>;
+ }
+}
+#[automatically_derived]
+impl<T: ::core::cmp::PartialOrd, U: ::core::cmp::PartialOrd>
+ ::core::cmp::PartialOrd for EnumGeneric<T, U> {
+ #[inline]
+ fn partial_cmp(&self, other: &EnumGeneric<T, U>)
+ -> ::core::option::Option<::core::cmp::Ordering> {
+ let __self_tag = ::core::intrinsics::discriminant_value(self);
+ let __arg1_tag = ::core::intrinsics::discriminant_value(other);
+ match (self, other) {
+ (EnumGeneric::One(__self_0), EnumGeneric::One(__arg1_0)) =>
+ ::core::cmp::PartialOrd::partial_cmp(__self_0, __arg1_0),
+ (EnumGeneric::Two(__self_0), EnumGeneric::Two(__arg1_0)) =>
+ ::core::cmp::PartialOrd::partial_cmp(__self_0, __arg1_0),
+ _ =>
+ ::core::cmp::PartialOrd::partial_cmp(&__self_tag,
+ &__arg1_tag),
+ }
+ }
+}
+#[automatically_derived]
+impl<T: ::core::cmp::Ord, U: ::core::cmp::Ord> ::core::cmp::Ord for
+ EnumGeneric<T, U> {
+ #[inline]
+ fn cmp(&self, other: &EnumGeneric<T, U>) -> ::core::cmp::Ordering {
let __self_tag = ::core::intrinsics::discriminant_value(self);
let __arg1_tag = ::core::intrinsics::discriminant_value(other);
match ::core::cmp::Ord::cmp(&__self_tag, &__arg1_tag) {
::core::cmp::Ordering::Equal =>
match (self, other) {
- (Fielded::X(__self_0), Fielded::X(__arg1_0)) =>
+ (EnumGeneric::One(__self_0), EnumGeneric::One(__arg1_0)) =>
::core::cmp::Ord::cmp(__self_0, __arg1_0),
- (Fielded::Y(__self_0), Fielded::Y(__arg1_0)) =>
- ::core::cmp::Ord::cmp(__self_0, __arg1_0),
- (Fielded::Z(__self_0), Fielded::Z(__arg1_0)) =>
+ (EnumGeneric::Two(__self_0), EnumGeneric::Two(__arg1_0)) =>
::core::cmp::Ord::cmp(__self_0, __arg1_0),
_ => unsafe { ::core::intrinsics::unreachable() }
},
diff --git a/tests/ui/destructure-trait-ref.stderr b/tests/ui/destructure-trait-ref.stderr
index 18a889837..38d201888 100644
--- a/tests/ui/destructure-trait-ref.stderr
+++ b/tests/ui/destructure-trait-ref.stderr
@@ -22,7 +22,7 @@ error[E0308]: mismatched types
LL | let &&x = &1isize as &dyn T;
| ^^ ----------------- this expression has type `&dyn T`
| |
- | expected trait object `dyn T`, found reference
+ | expected `dyn T`, found `&_`
|
= note: expected trait object `dyn T`
found reference `&_`
@@ -38,7 +38,7 @@ error[E0308]: mismatched types
LL | let &&&x = &(&1isize as &dyn T);
| ^^ -------------------- this expression has type `&&dyn T`
| |
- | expected trait object `dyn T`, found reference
+ | expected `dyn T`, found `&_`
|
= note: expected trait object `dyn T`
found reference `&_`
@@ -54,7 +54,7 @@ error[E0308]: mismatched types
LL | let box box x = Box::new(1isize) as Box<dyn T>;
| ^^^^^ ------------------------------ this expression has type `Box<dyn T>`
| |
- | expected trait object `dyn T`, found struct `Box`
+ | expected `dyn T`, found `Box<_>`
|
= note: expected trait object `dyn T`
found struct `Box<_>`
diff --git a/tests/ui/destructuring-assignment/default-match-bindings-forbidden.stderr b/tests/ui/destructuring-assignment/default-match-bindings-forbidden.stderr
index 950e0223e..b285ee1f3 100644
--- a/tests/ui/destructuring-assignment/default-match-bindings-forbidden.stderr
+++ b/tests/ui/destructuring-assignment/default-match-bindings-forbidden.stderr
@@ -4,7 +4,7 @@ error[E0308]: mismatched types
LL | (x, y) = &(1, 2);
| ^^^^^^ ------- this expression has type `&({integer}, {integer})`
| |
- | expected reference, found tuple
+ | expected `&({integer}, {integer})`, found `(_, _)`
|
= note: expected reference `&({integer}, {integer})`
found tuple `(_, _)`
diff --git a/tests/ui/diagnostic-flags/terminal_urls.rs b/tests/ui/diagnostic-flags/terminal_urls.rs
new file mode 100644
index 000000000..1f04e2aad
--- /dev/null
+++ b/tests/ui/diagnostic-flags/terminal_urls.rs
@@ -0,0 +1,4 @@
+// compile-flags: -Zterminal-urls=yes
+fn main() {
+ let () = 4; //~ ERROR
+}
diff --git a/tests/ui/diagnostic-flags/terminal_urls.stderr b/tests/ui/diagnostic-flags/terminal_urls.stderr
new file mode 100644
index 000000000..7f7e69c5d
--- /dev/null
+++ b/tests/ui/diagnostic-flags/terminal_urls.stderr
@@ -0,0 +1,11 @@
+error[]8;;https://doc.rust-lang.org/error_codes/E0308.htmlE0308]8;;]: mismatched types
+ --> $DIR/terminal_urls.rs:3:9
+ |
+LL | let () = 4;
+ | ^^ - this expression has type `{integer}`
+ | |
+ | expected integer, found `()`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/diagnostic-width/long-E0308.stderr b/tests/ui/diagnostic-width/long-E0308.stderr
index 1c99898bc..20b018b9f 100644
--- a/tests/ui/diagnostic-width/long-E0308.stderr
+++ b/tests/ui/diagnostic-width/long-E0308.stderr
@@ -16,7 +16,7 @@ LL | | Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok...
LL | | Ok("")
LL | | ))))))))))))))))))))))))))))))
LL | | ))))))))))))))))))))))))))))));
- | |__________________________________^ expected struct `Atype`, found enum `Result`
+ | |__________________________________^ expected `Atype<Btype<..., ...>, ...>`, found `Result<Result<..., ...>, ...>`
|
= note: expected struct `Atype<Btype<..., ...>, ...>`
the full type name has been written to '$TEST_BUILD_DIR/diagnostic-width/long-E0308/long-E0308.long-type-hash.txt'
@@ -32,7 +32,7 @@ LL | | Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(...
LL | | Ok(Ok(Ok(Ok(Ok(Ok(Ok("")))))))
LL | | ))))))))))))))))))))))))))))))
LL | | ))))))))))))))))))))))));
- | |____________________________^ expected enum `Option`, found enum `Result`
+ | |____________________________^ expected `Option<Result<..., ...>>`, found `Result<Result<..., ...>, ...>`
|
= note: expected enum `Option<Result<..., ...>>`
the full type name has been written to '$TEST_BUILD_DIR/diagnostic-width/long-E0308/long-E0308.long-type-hash.txt'
@@ -50,7 +50,7 @@ LL | | Atype<
... |
LL | | i32
LL | | > = ();
- | | - ^^ expected struct `Atype`, found `()`
+ | | - ^^ expected `Atype<Btype<..., ...>, ...>`, found `()`
| |_____|
| expected due to this
|
@@ -69,7 +69,7 @@ LL | | Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(...
LL | | Ok(Ok(Ok(Ok(Ok(Ok(Ok("")))))))
LL | | ))))))))))))))))))))))))))))))
LL | | ))))))))))))))))))))))));
- | |____________________________^ expected `()`, found enum `Result`
+ | |____________________________^ expected `()`, found `Result<Result<..., ...>, ...>`
|
= note: expected unit type `()`
found enum `Result<Result<..., ...>, ...>`
diff --git a/tests/ui/did_you_mean/brackets-to-braces-single-element.stderr b/tests/ui/did_you_mean/brackets-to-braces-single-element.stderr
index 6ded03e45..a7ec19259 100644
--- a/tests/ui/did_you_mean/brackets-to-braces-single-element.stderr
+++ b/tests/ui/did_you_mean/brackets-to-braces-single-element.stderr
@@ -2,7 +2,7 @@ error[E0308]: mismatched types
--> $DIR/brackets-to-braces-single-element.rs:1:24
|
LL | const A: [&str; 1] = { "hello" };
- | ^^^^^^^ expected array `[&'static str; 1]`, found `&str`
+ | ^^^^^^^ expected `[&str; 1]`, found `&str`
|
help: to create an array, use square brackets instead of curly braces
|
@@ -13,7 +13,7 @@ error[E0308]: mismatched types
--> $DIR/brackets-to-braces-single-element.rs:4:19
|
LL | const B: &[u32] = &{ 1 };
- | ^^^^^^ expected slice `[u32]`, found integer
+ | ^^^^^^ expected `&[u32]`, found `&{integer}`
|
= note: expected reference `&'static [u32]`
found reference `&{integer}`
@@ -26,7 +26,7 @@ error[E0308]: mismatched types
--> $DIR/brackets-to-braces-single-element.rs:7:27
|
LL | const C: &&[u32; 1] = &&{ 1 };
- | ^ expected array `[u32; 1]`, found integer
+ | ^ expected `[u32; 1]`, found integer
|
help: to create an array, use square brackets instead of curly braces
|
diff --git a/tests/ui/did_you_mean/compatible-variants-in-pat.stderr b/tests/ui/did_you_mean/compatible-variants-in-pat.stderr
index 473468af6..5e48871bb 100644
--- a/tests/ui/did_you_mean/compatible-variants-in-pat.stderr
+++ b/tests/ui/did_you_mean/compatible-variants-in-pat.stderr
@@ -4,7 +4,7 @@ error[E0308]: mismatched types
LL | match f {
| - this expression has type `Foo`
LL | Bar { x } => {
- | ^^^^^^^^^ expected enum `Foo`, found struct `Bar`
+ | ^^^^^^^^^ expected `Foo`, found `Bar`
|
help: try wrapping the pattern in `Foo::Bar`
|
@@ -22,7 +22,7 @@ LL | match s {
LL | S => {
| ^
| |
- | expected enum `Option`, found struct `S`
+ | expected `Option<S>`, found `S`
| `S` is interpreted as a unit struct, not a new binding
|
= note: expected enum `Option<S>`
@@ -47,7 +47,7 @@ LL | match s {
LL | S => {
| ^
| |
- | expected enum `Result`, found struct `S`
+ | expected `Result<S, S>`, found `S`
| `S` is interpreted as a unit struct, not a new binding
|
= note: expected enum `Result<S, S>`
diff --git a/tests/ui/did_you_mean/compatible-variants.stderr b/tests/ui/did_you_mean/compatible-variants.stderr
index fe81da198..7b88d93ea 100644
--- a/tests/ui/did_you_mean/compatible-variants.stderr
+++ b/tests/ui/did_you_mean/compatible-variants.stderr
@@ -7,7 +7,7 @@ LL | / while false {
LL | |
LL | | f();
LL | | }
- | |_____^ expected enum `Option`, found `()`
+ | |_____^ expected `Option<()>`, found `()`
|
= note: expected enum `Option<()>`
found unit type `()`
@@ -26,7 +26,7 @@ error[E0308]: mismatched types
LL | fn b() -> Result<(), ()> {
| -------------- expected `Result<(), ()>` because of return type
LL | f()
- | ^^^ expected enum `Result`, found `()`
+ | ^^^ expected `Result<(), ()>`, found `()`
|
= note: expected enum `Result<(), ()>`
found unit type `()`
@@ -45,7 +45,7 @@ LL | / for _ in [1, 2] {
LL | |
LL | | f();
LL | | }
- | |_____^ expected enum `Option`, found `()`
+ | |_____^ expected `Option<()>`, found `()`
|
= note: expected enum `Option<()>`
found unit type `()`
@@ -62,7 +62,7 @@ error[E0308]: `?` operator has incompatible types
--> $DIR/compatible-variants.rs:35:5
|
LL | c()?
- | ^^^^ expected enum `Option`, found `()`
+ | ^^^^ expected `Option<()>`, found `()`
|
= note: `?` operator cannot convert from `()` to `Option<()>`
= note: expected enum `Option<()>`
@@ -85,7 +85,7 @@ error[E0308]: mismatched types
--> $DIR/compatible-variants.rs:42:25
|
LL | let _: Option<()> = while false {};
- | ---------- ^^^^^^^^^^^^^^ expected enum `Option`, found `()`
+ | ---------- ^^^^^^^^^^^^^^ expected `Option<()>`, found `()`
| |
| expected due to this
|
@@ -100,7 +100,7 @@ error[E0308]: mismatched types
--> $DIR/compatible-variants.rs:46:9
|
LL | while false {}
- | ^^^^^^^^^^^^^^ expected enum `Option`, found `()`
+ | ^^^^^^^^^^^^^^ expected `Option<()>`, found `()`
|
= note: expected enum `Option<()>`
found unit type `()`
@@ -117,7 +117,7 @@ error[E0308]: mismatched types
--> $DIR/compatible-variants.rs:50:31
|
LL | let _: Result<i32, i32> = 1;
- | ---------------- ^ expected enum `Result`, found integer
+ | ---------------- ^ expected `Result<i32, i32>`, found integer
| |
| expected due to this
|
@@ -134,7 +134,7 @@ error[E0308]: mismatched types
--> $DIR/compatible-variants.rs:53:26
|
LL | let _: Option<i32> = 1;
- | ----------- ^ expected enum `Option`, found integer
+ | ----------- ^ expected `Option<i32>`, found integer
| |
| expected due to this
|
@@ -149,7 +149,7 @@ error[E0308]: mismatched types
--> $DIR/compatible-variants.rs:56:28
|
LL | let _: Hey<i32, i32> = 1;
- | ------------- ^ expected enum `Hey`, found integer
+ | ------------- ^ expected `Hey<i32, i32>`, found integer
| |
| expected due to this
|
@@ -166,7 +166,7 @@ error[E0308]: mismatched types
--> $DIR/compatible-variants.rs:59:29
|
LL | let _: Hey<i32, bool> = false;
- | -------------- ^^^^^ expected enum `Hey`, found `bool`
+ | -------------- ^^^^^ expected `Hey<i32, bool>`, found `bool`
| |
| expected due to this
|
@@ -181,7 +181,7 @@ error[E0308]: mismatched types
--> $DIR/compatible-variants.rs:63:19
|
LL | let _ = Foo { bar };
- | ^^^ expected enum `Option`, found `i32`
+ | ^^^ expected `Option<i32>`, found `i32`
|
= note: expected enum `Option<i32>`
found type `i32`
@@ -194,7 +194,7 @@ error[E0308]: mismatched types
--> $DIR/compatible-variants.rs:80:16
|
LL | let a: A = B::Fst;
- | - ^^^^^^ expected enum `A`, found enum `B`
+ | - ^^^^^^ expected `A`, found `B`
| |
| expected due to this
|
@@ -207,7 +207,7 @@ error[E0308]: mismatched types
--> $DIR/compatible-variants.rs:86:17
|
LL | let a: A2 = B::Fst;
- | -- ^^^^^^ expected struct `A2`, found enum `B`
+ | -- ^^^^^^ expected `A2`, found `B`
| |
| expected due to this
|
diff --git a/tests/ui/did_you_mean/issue-42764.stderr b/tests/ui/did_you_mean/issue-42764.stderr
index 6a7fd8fe2..3819a5a18 100644
--- a/tests/ui/did_you_mean/issue-42764.stderr
+++ b/tests/ui/did_you_mean/issue-42764.stderr
@@ -2,7 +2,7 @@ error[E0308]: mismatched types
--> $DIR/issue-42764.rs:11:43
|
LL | this_function_expects_a_double_option(n);
- | ------------------------------------- ^ expected enum `DoubleOption`, found `usize`
+ | ------------------------------------- ^ expected `DoubleOption<_>`, found `usize`
| |
| arguments to this function are incorrect
|
@@ -24,7 +24,7 @@ error[E0308]: mismatched types
--> $DIR/issue-42764.rs:27:33
|
LL | let _c = Context { wrapper: Payload{} };
- | ^^^^^^^^^ expected struct `Wrapper`, found struct `Payload`
+ | ^^^^^^^^^ expected `Wrapper`, found `Payload`
|
help: try wrapping the expression in `Wrapper`
|
diff --git a/tests/ui/did_you_mean/issue-46718-struct-pattern-dotdotdot.stderr b/tests/ui/did_you_mean/issue-46718-struct-pattern-dotdotdot.stderr
index bfe1ed328..589b2c378 100644
--- a/tests/ui/did_you_mean/issue-46718-struct-pattern-dotdotdot.stderr
+++ b/tests/ui/did_you_mean/issue-46718-struct-pattern-dotdotdot.stderr
@@ -2,7 +2,12 @@ error: expected field pattern, found `...`
--> $DIR/issue-46718-struct-pattern-dotdotdot.rs:11:55
|
LL | PersonalityInventory { expressivity: exp, ... } => exp
- | ^^^ help: to omit remaining fields, use one fewer `.`: `..`
+ | ^^^
+ |
+help: to omit remaining fields, use `..`
+ |
+LL | PersonalityInventory { expressivity: exp, .. } => exp
+ | ~~
error: aborting due to previous error
diff --git a/tests/ui/did_you_mean/println-typo.rs b/tests/ui/did_you_mean/println-typo.rs
new file mode 100644
index 000000000..685b5e1f2
--- /dev/null
+++ b/tests/ui/did_you_mean/println-typo.rs
@@ -0,0 +1,6 @@
+// https://internals.rust-lang.org/t/18227
+
+fn main() {
+ prinltn!(); //~ ERROR cannot find macro `prinltn` in this scope
+ //^ a macro with a similar name exists: `println`
+}
diff --git a/tests/ui/did_you_mean/println-typo.stderr b/tests/ui/did_you_mean/println-typo.stderr
new file mode 100644
index 000000000..43b7b1894
--- /dev/null
+++ b/tests/ui/did_you_mean/println-typo.stderr
@@ -0,0 +1,11 @@
+error: cannot find macro `prinltn` in this scope
+ --> $DIR/println-typo.rs:4:5
+ |
+LL | prinltn!();
+ | ^^^^^^^ help: a macro with a similar name exists: `println`
+ --> $SRC_DIR/std/src/macros.rs:LL:COL
+ |
+ = note: similarly named macro `println` defined here
+
+error: aborting due to previous error
+
diff --git a/tests/ui/did_you_mean/recursion_limit_deref.stderr b/tests/ui/did_you_mean/recursion_limit_deref.stderr
index a6b5681a6..32fb628c4 100644
--- a/tests/ui/did_you_mean/recursion_limit_deref.stderr
+++ b/tests/ui/did_you_mean/recursion_limit_deref.stderr
@@ -10,7 +10,7 @@ error[E0308]: mismatched types
--> $DIR/recursion_limit_deref.rs:51:22
|
LL | let x: &Bottom = &t;
- | ------- ^^ expected struct `Bottom`, found struct `Top`
+ | ------- ^^ expected `&Bottom`, found `&Top`
| |
| expected due to this
|
diff --git a/tests/ui/disambiguate-identical-names.stderr b/tests/ui/disambiguate-identical-names.stderr
index 87560c4c7..7d8293018 100644
--- a/tests/ui/disambiguate-identical-names.stderr
+++ b/tests/ui/disambiguate-identical-names.stderr
@@ -2,7 +2,7 @@ error[E0308]: mismatched types
--> $DIR/disambiguate-identical-names.rs:13:10
|
LL | test(&v);
- | ---- ^^ expected struct `Vec`, found struct `HashMap`
+ | ---- ^^ expected `&Vec<Vec<u32>>`, found `&HashMap<u8, u8>`
| |
| arguments to this function are incorrect
|
diff --git a/tests/ui/diverging-fn-tail-35849.stderr b/tests/ui/diverging-fn-tail-35849.stderr
index 21361489a..f5b5a4ccc 100644
--- a/tests/ui/diverging-fn-tail-35849.stderr
+++ b/tests/ui/diverging-fn-tail-35849.stderr
@@ -5,7 +5,7 @@ LL | fn assert_sizeof() -> ! {
| - expected `!` because of return type
LL | unsafe {
LL | ::std::mem::transmute::<f64, [u8; 8]>(panic!())
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `!`, found array `[u8; 8]`
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `!`, found `[u8; 8]`
|
= note: expected type `!`
found array `[u8; 8]`
diff --git a/tests/ui/issues/issue-2735-2.rs b/tests/ui/drop/issue-2735-2.rs
index 70ebce9d3..70ebce9d3 100644
--- a/tests/ui/issues/issue-2735-2.rs
+++ b/tests/ui/drop/issue-2735-2.rs
diff --git a/tests/ui/issues/issue-2735-3.rs b/tests/ui/drop/issue-2735-3.rs
index 233015378..233015378 100644
--- a/tests/ui/issues/issue-2735-3.rs
+++ b/tests/ui/drop/issue-2735-3.rs
diff --git a/tests/ui/issues/issue-2735.rs b/tests/ui/drop/issue-2735.rs
index 20d3949a9..20d3949a9 100644
--- a/tests/ui/issues/issue-2735.rs
+++ b/tests/ui/drop/issue-2735.rs
diff --git a/tests/ui/dropck/drop-with-active-borrows-1.stderr b/tests/ui/dropck/drop-with-active-borrows-1.stderr
index 8d6a7f372..4585b2297 100644
--- a/tests/ui/dropck/drop-with-active-borrows-1.stderr
+++ b/tests/ui/dropck/drop-with-active-borrows-1.stderr
@@ -1,6 +1,8 @@
error[E0505]: cannot move out of `a` because it is borrowed
--> $DIR/drop-with-active-borrows-1.rs:4:10
|
+LL | let a = "".to_string();
+ | - binding `a` declared here
LL | let b: Vec<&str> = a.lines().collect();
| --------- borrow of `a` occurs here
LL | drop(a);
diff --git a/tests/ui/dropck/dropck-eyepatch-extern-crate.stderr b/tests/ui/dropck/dropck-eyepatch-extern-crate.stderr
index 5d5340557..23d57634e 100644
--- a/tests/ui/dropck/dropck-eyepatch-extern-crate.stderr
+++ b/tests/ui/dropck/dropck-eyepatch-extern-crate.stderr
@@ -1,6 +1,9 @@
error[E0597]: `c_shortest` does not live long enough
--> $DIR/dropck-eyepatch-extern-crate.rs:46:23
|
+LL | let (mut dt, mut dr, c_shortest): (Dt<_>, Dr<_>, Cell<_>);
+ | ---------- binding `c_shortest` declared here
+...
LL | dt = Dt("dt", &c_shortest);
| ^^^^^^^^^^^ borrowed value does not live long enough
...
@@ -15,6 +18,9 @@ LL | }
error[E0597]: `c_shortest` does not live long enough
--> $DIR/dropck-eyepatch-extern-crate.rs:68:32
|
+LL | let (mut pt, mut pr, c_shortest): (Pt<_, _>, Pr<_>, Cell<_>);
+ | ---------- binding `c_shortest` declared here
+...
LL | pt = Pt("pt", &c_long, &c_shortest);
| ^^^^^^^^^^^ borrowed value does not live long enough
...
diff --git a/tests/ui/dropck/dropck-eyepatch-reorder.stderr b/tests/ui/dropck/dropck-eyepatch-reorder.stderr
index 5055cdd8b..a5d5136b5 100644
--- a/tests/ui/dropck/dropck-eyepatch-reorder.stderr
+++ b/tests/ui/dropck/dropck-eyepatch-reorder.stderr
@@ -1,6 +1,9 @@
error[E0597]: `c_shortest` does not live long enough
--> $DIR/dropck-eyepatch-reorder.rs:64:23
|
+LL | let (mut dt, mut dr, c_shortest): (Dt<_>, Dr<_>, Cell<_>);
+ | ---------- binding `c_shortest` declared here
+...
LL | dt = Dt("dt", &c_shortest);
| ^^^^^^^^^^^ borrowed value does not live long enough
...
@@ -15,6 +18,9 @@ LL | }
error[E0597]: `c_shortest` does not live long enough
--> $DIR/dropck-eyepatch-reorder.rs:86:32
|
+LL | let (mut pt, mut pr, c_shortest): (Pt<_, _>, Pr<_>, Cell<_>);
+ | ---------- binding `c_shortest` declared here
+...
LL | pt = Pt("pt", &c_long, &c_shortest);
| ^^^^^^^^^^^ borrowed value does not live long enough
...
diff --git a/tests/ui/dropck/dropck-eyepatch.stderr b/tests/ui/dropck/dropck-eyepatch.stderr
index 21295e6c6..dc3f8c05e 100644
--- a/tests/ui/dropck/dropck-eyepatch.stderr
+++ b/tests/ui/dropck/dropck-eyepatch.stderr
@@ -1,6 +1,9 @@
error[E0597]: `c_shortest` does not live long enough
--> $DIR/dropck-eyepatch.rs:88:23
|
+LL | let (mut dt, mut dr, c_shortest): (Dt<_>, Dr<_>, Cell<_>);
+ | ---------- binding `c_shortest` declared here
+...
LL | dt = Dt("dt", &c_shortest);
| ^^^^^^^^^^^ borrowed value does not live long enough
...
@@ -15,6 +18,9 @@ LL | }
error[E0597]: `c_shortest` does not live long enough
--> $DIR/dropck-eyepatch.rs:110:32
|
+LL | let (mut pt, mut pr, c_shortest): (Pt<_, _>, Pr<_>, Cell<_>);
+ | ---------- binding `c_shortest` declared here
+...
LL | pt = Pt("pt", &c_long, &c_shortest);
| ^^^^^^^^^^^ borrowed value does not live long enough
...
diff --git a/tests/ui/dropck/dropck-union.stderr b/tests/ui/dropck/dropck-union.stderr
index 854e29385..7d48e9fdc 100644
--- a/tests/ui/dropck/dropck-union.stderr
+++ b/tests/ui/dropck/dropck-union.stderr
@@ -1,6 +1,8 @@
error[E0597]: `v` does not live long enough
--> $DIR/dropck-union.rs:37:18
|
+LL | let v : Wrap<C> = Wrap::new(C(Cell::new(None)));
+ | - binding `v` declared here
LL | v.0.set(Some(&v));
| ^^ borrowed value does not live long enough
LL | }
diff --git a/tests/ui/dropck/dropck_trait_cycle_checked.stderr b/tests/ui/dropck/dropck_trait_cycle_checked.stderr
index dc3fbed59..4d4f7b9df 100644
--- a/tests/ui/dropck/dropck_trait_cycle_checked.stderr
+++ b/tests/ui/dropck/dropck_trait_cycle_checked.stderr
@@ -2,7 +2,7 @@ error[E0597]: `o2` does not live long enough
--> $DIR/dropck_trait_cycle_checked.rs:111:13
|
LL | let (o1, o2, o3): (Box<dyn Obj>, Box<dyn Obj>, Box<dyn Obj>) = (O::new(), O::new(), O::new());
- | -------- cast requires that `o2` is borrowed for `'static`
+ | -- binding `o2` declared here -------- cast requires that `o2` is borrowed for `'static`
LL | o1.set0(&o2);
| ^^^ borrowed value does not live long enough
...
@@ -13,7 +13,7 @@ error[E0597]: `o3` does not live long enough
--> $DIR/dropck_trait_cycle_checked.rs:112:13
|
LL | let (o1, o2, o3): (Box<dyn Obj>, Box<dyn Obj>, Box<dyn Obj>) = (O::new(), O::new(), O::new());
- | -------- cast requires that `o3` is borrowed for `'static`
+ | -- binding `o3` declared here -------- cast requires that `o3` is borrowed for `'static`
LL | o1.set0(&o2);
LL | o1.set1(&o3);
| ^^^ borrowed value does not live long enough
@@ -25,7 +25,7 @@ error[E0597]: `o2` does not live long enough
--> $DIR/dropck_trait_cycle_checked.rs:113:13
|
LL | let (o1, o2, o3): (Box<dyn Obj>, Box<dyn Obj>, Box<dyn Obj>) = (O::new(), O::new(), O::new());
- | -------- cast requires that `o2` is borrowed for `'static`
+ | -- binding `o2` declared here -------- cast requires that `o2` is borrowed for `'static`
...
LL | o2.set0(&o2);
| ^^^ borrowed value does not live long enough
@@ -37,7 +37,7 @@ error[E0597]: `o3` does not live long enough
--> $DIR/dropck_trait_cycle_checked.rs:114:13
|
LL | let (o1, o2, o3): (Box<dyn Obj>, Box<dyn Obj>, Box<dyn Obj>) = (O::new(), O::new(), O::new());
- | -------- cast requires that `o3` is borrowed for `'static`
+ | -- binding `o3` declared here -------- cast requires that `o3` is borrowed for `'static`
...
LL | o2.set1(&o3);
| ^^^ borrowed value does not live long enough
@@ -49,7 +49,7 @@ error[E0597]: `o1` does not live long enough
--> $DIR/dropck_trait_cycle_checked.rs:115:13
|
LL | let (o1, o2, o3): (Box<dyn Obj>, Box<dyn Obj>, Box<dyn Obj>) = (O::new(), O::new(), O::new());
- | -------- cast requires that `o1` is borrowed for `'static`
+ | -- binding `o1` declared here -------- cast requires that `o1` is borrowed for `'static`
...
LL | o3.set0(&o1);
| ^^^ borrowed value does not live long enough
@@ -61,7 +61,7 @@ error[E0597]: `o2` does not live long enough
--> $DIR/dropck_trait_cycle_checked.rs:116:13
|
LL | let (o1, o2, o3): (Box<dyn Obj>, Box<dyn Obj>, Box<dyn Obj>) = (O::new(), O::new(), O::new());
- | -------- cast requires that `o2` is borrowed for `'static`
+ | -- binding `o2` declared here -------- cast requires that `o2` is borrowed for `'static`
...
LL | o3.set1(&o2);
| ^^^ borrowed value does not live long enough
diff --git a/tests/ui/dst/dst-bad-assign-3.rs b/tests/ui/dst/dst-bad-assign-3.rs
index d05b3937c..d199864d9 100644
--- a/tests/ui/dst/dst-bad-assign-3.rs
+++ b/tests/ui/dst/dst-bad-assign-3.rs
@@ -32,7 +32,7 @@ pub fn main() {
let z: Box<dyn ToBar> = Box::new(Bar1 {f: 36});
f5.2 = Bar1 {f: 36};
//~^ ERROR mismatched types
- //~| expected trait object `dyn ToBar`, found struct `Bar1`
+ //~| expected `dyn ToBar`, found `Bar1`
//~| expected trait object `dyn ToBar`
//~| found struct `Bar1`
//~| ERROR the size for values of type
diff --git a/tests/ui/dst/dst-bad-assign-3.stderr b/tests/ui/dst/dst-bad-assign-3.stderr
index b326dbbbc..6dd3434fd 100644
--- a/tests/ui/dst/dst-bad-assign-3.stderr
+++ b/tests/ui/dst/dst-bad-assign-3.stderr
@@ -2,7 +2,7 @@ error[E0308]: mismatched types
--> $DIR/dst-bad-assign-3.rs:33:12
|
LL | f5.2 = Bar1 {f: 36};
- | ---- ^^^^^^^^^^^^ expected trait object `dyn ToBar`, found struct `Bar1`
+ | ---- ^^^^^^^^^^^^ expected `dyn ToBar`, found `Bar1`
| |
| expected due to the type of this binding
|
diff --git a/tests/ui/dst/dst-bad-assign.rs b/tests/ui/dst/dst-bad-assign.rs
index 496e01ae0..c55fb2c3e 100644
--- a/tests/ui/dst/dst-bad-assign.rs
+++ b/tests/ui/dst/dst-bad-assign.rs
@@ -34,7 +34,7 @@ pub fn main() {
let z: Box<dyn ToBar> = Box::new(Bar1 {f: 36});
f5.ptr = Bar1 {f: 36};
//~^ ERROR mismatched types
- //~| expected trait object `dyn ToBar`, found struct `Bar1`
+ //~| expected `dyn ToBar`, found `Bar1`
//~| expected trait object `dyn ToBar`
//~| found struct `Bar1`
//~| ERROR the size for values of type
diff --git a/tests/ui/dst/dst-bad-assign.stderr b/tests/ui/dst/dst-bad-assign.stderr
index 614f21387..d8d105787 100644
--- a/tests/ui/dst/dst-bad-assign.stderr
+++ b/tests/ui/dst/dst-bad-assign.stderr
@@ -2,7 +2,7 @@ error[E0308]: mismatched types
--> $DIR/dst-bad-assign.rs:35:14
|
LL | f5.ptr = Bar1 {f: 36};
- | ------ ^^^^^^^^^^^^ expected trait object `dyn ToBar`, found struct `Bar1`
+ | ------ ^^^^^^^^^^^^ expected `dyn ToBar`, found `Bar1`
| |
| expected due to the type of this binding
|
diff --git a/tests/ui/dst/dst-bad-coerce1.stderr b/tests/ui/dst/dst-bad-coerce1.stderr
index 594acff85..ff77bd4ce 100644
--- a/tests/ui/dst/dst-bad-coerce1.stderr
+++ b/tests/ui/dst/dst-bad-coerce1.stderr
@@ -2,7 +2,7 @@ error[E0308]: mismatched types
--> $DIR/dst-bad-coerce1.rs:16:29
|
LL | let f3: &Fat<[usize]> = f2;
- | ------------- ^^ expected slice `[usize]`, found array `[isize; 3]`
+ | ------------- ^^ expected `&Fat<[usize]>`, found `&Fat<[isize; 3]>`
| |
| expected due to this
|
@@ -21,7 +21,7 @@ error[E0308]: mismatched types
--> $DIR/dst-bad-coerce1.rs:28:27
|
LL | let f3: &([usize],) = f2;
- | ----------- ^^ expected slice `[usize]`, found array `[isize; 3]`
+ | ----------- ^^ expected `&([usize],)`, found `&([isize; 3],)`
| |
| expected due to this
|
diff --git a/tests/ui/dst/dst-bad-coerce3.stderr b/tests/ui/dst/dst-bad-coerce3.stderr
index 957e98bbe..1254250bc 100644
--- a/tests/ui/dst/dst-bad-coerce3.stderr
+++ b/tests/ui/dst/dst-bad-coerce3.stderr
@@ -3,7 +3,9 @@ error[E0597]: `f1` does not live long enough
|
LL | fn baz<'a>() {
| -- lifetime `'a` defined here
-...
+LL | // With a vec of ints.
+LL | let f1 = Fat { ptr: [1, 2, 3] };
+ | -- binding `f1` declared here
LL | let f2: &Fat<[isize; 3]> = &f1;
| ^^^ borrowed value does not live long enough
LL | let f3: &'a Fat<[isize]> = f2;
@@ -18,6 +20,8 @@ error[E0597]: `f1` does not live long enough
LL | fn baz<'a>() {
| -- lifetime `'a` defined here
...
+LL | let f1 = Fat { ptr: Foo };
+ | -- binding `f1` declared here
LL | let f2: &Fat<Foo> = &f1;
| ^^^ borrowed value does not live long enough
LL | let f3: &'a Fat<dyn Bar> = f2;
@@ -32,6 +36,8 @@ error[E0597]: `f1` does not live long enough
LL | fn baz<'a>() {
| -- lifetime `'a` defined here
...
+LL | let f1 = ([1, 2, 3],);
+ | -- binding `f1` declared here
LL | let f2: &([isize; 3],) = &f1;
| ^^^ borrowed value does not live long enough
LL | let f3: &'a ([isize],) = f2;
@@ -46,6 +52,8 @@ error[E0597]: `f1` does not live long enough
LL | fn baz<'a>() {
| -- lifetime `'a` defined here
...
+LL | let f1 = (Foo,);
+ | -- binding `f1` declared here
LL | let f2: &(Foo,) = &f1;
| ^^^ borrowed value does not live long enough
LL | let f3: &'a (dyn Bar,) = f2;
diff --git a/tests/ui/dst/dst-bad-coerce4.rs b/tests/ui/dst/dst-bad-coerce4.rs
index f63da60d2..9f297915e 100644
--- a/tests/ui/dst/dst-bad-coerce4.rs
+++ b/tests/ui/dst/dst-bad-coerce4.rs
@@ -11,7 +11,7 @@ pub fn main() {
let f1: &Fat<[isize]> = &Fat { ptr: [1, 2, 3] };
let f2: &Fat<[isize; 3]> = f1;
//~^ ERROR mismatched types
- //~| expected array `[isize; 3]`, found slice `[isize]`
+ //~| expected `&Fat<[isize; 3]>`, found `&Fat<[isize]>`
//~| expected reference `&Fat<[isize; 3]>`
//~| found reference `&Fat<[isize]>`
@@ -19,7 +19,7 @@ pub fn main() {
let f1: &([isize],) = &([1, 2, 3],);
let f2: &([isize; 3],) = f1;
//~^ ERROR mismatched types
- //~| expected array `[isize; 3]`, found slice `[isize]`
+ //~| expected `&([isize; 3],)`, found `&([isize],)`
//~| expected reference `&([isize; 3],)`
//~| found reference `&([isize],)`
}
diff --git a/tests/ui/dst/dst-bad-coerce4.stderr b/tests/ui/dst/dst-bad-coerce4.stderr
index 4c9954f35..46e7dba81 100644
--- a/tests/ui/dst/dst-bad-coerce4.stderr
+++ b/tests/ui/dst/dst-bad-coerce4.stderr
@@ -2,7 +2,7 @@ error[E0308]: mismatched types
--> $DIR/dst-bad-coerce4.rs:12:32
|
LL | let f2: &Fat<[isize; 3]> = f1;
- | ---------------- ^^ expected array `[isize; 3]`, found slice `[isize]`
+ | ---------------- ^^ expected `&Fat<[isize; 3]>`, found `&Fat<[isize]>`
| |
| expected due to this
|
@@ -13,7 +13,7 @@ error[E0308]: mismatched types
--> $DIR/dst-bad-coerce4.rs:20:30
|
LL | let f2: &([isize; 3],) = f1;
- | -------------- ^^ expected array `[isize; 3]`, found slice `[isize]`
+ | -------------- ^^ expected `&([isize; 3],)`, found `&([isize],)`
| |
| expected due to this
|
diff --git a/tests/ui/dyn-star/align.over_aligned.stderr b/tests/ui/dyn-star/align.over_aligned.stderr
index 62e28efab..0365d87a6 100644
--- a/tests/ui/dyn-star/align.over_aligned.stderr
+++ b/tests/ui/dyn-star/align.over_aligned.stderr
@@ -7,13 +7,13 @@ LL | #![feature(dyn_star)]
= note: see issue #102425 <https://github.com/rust-lang/rust/issues/102425> for more information
= note: `#[warn(incomplete_features)]` on by default
-error[E0277]: `AlignedUsize` needs to be a pointer-sized type
+error[E0277]: `AlignedUsize` needs to have the same alignment and size as a pointer
--> $DIR/align.rs:15:13
|
LL | let x = AlignedUsize(12) as dyn* Debug;
- | ^^^^^^^^^^^^^^^^ `AlignedUsize` needs to be a pointer-sized type
+ | ^^^^^^^^^^^^^^^^ `AlignedUsize` needs to be a pointer-like type
|
- = help: the trait `PointerSized` is not implemented for `AlignedUsize`
+ = help: the trait `PointerLike` is not implemented for `AlignedUsize`
error: aborting due to previous error; 1 warning emitted
diff --git a/tests/ui/dyn-star/align.rs b/tests/ui/dyn-star/align.rs
index fb41a05a0..6679997a9 100644
--- a/tests/ui/dyn-star/align.rs
+++ b/tests/ui/dyn-star/align.rs
@@ -13,5 +13,5 @@ struct AlignedUsize(usize);
fn main() {
let x = AlignedUsize(12) as dyn* Debug;
- //[over_aligned]~^ ERROR `AlignedUsize` needs to be a pointer-sized type
+ //[over_aligned]~^ ERROR `AlignedUsize` needs to have the same alignment and size as a pointer
}
diff --git a/tests/ui/dyn-star/check-size-at-cast-polymorphic-bad.rs b/tests/ui/dyn-star/check-size-at-cast-polymorphic-bad.rs
index e19e36cc7..85749aa7b 100644
--- a/tests/ui/dyn-star/check-size-at-cast-polymorphic-bad.rs
+++ b/tests/ui/dyn-star/check-size-at-cast-polymorphic-bad.rs
@@ -9,7 +9,7 @@ fn dyn_debug(_: (dyn* Debug + '_)) {
fn polymorphic<T: Debug + ?Sized>(t: &T) {
dyn_debug(t);
- //~^ ERROR `&T` needs to be a pointer-sized type
+ //~^ ERROR `&T` needs to have the same alignment and size as a pointer
}
fn main() {}
diff --git a/tests/ui/dyn-star/check-size-at-cast-polymorphic-bad.stderr b/tests/ui/dyn-star/check-size-at-cast-polymorphic-bad.stderr
index 53ccbe43d..350630f79 100644
--- a/tests/ui/dyn-star/check-size-at-cast-polymorphic-bad.stderr
+++ b/tests/ui/dyn-star/check-size-at-cast-polymorphic-bad.stderr
@@ -1,14 +1,14 @@
-error[E0277]: `&T` needs to be a pointer-sized type
+error[E0277]: `&T` needs to have the same alignment and size as a pointer
--> $DIR/check-size-at-cast-polymorphic-bad.rs:11:15
|
LL | dyn_debug(t);
- | ^ `&T` needs to be a pointer-sized type
+ | ^ `&T` needs to be a pointer-like type
|
- = help: the trait `PointerSized` is not implemented for `&T`
+ = help: the trait `PointerLike` is not implemented for `&T`
help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement
|
-LL | fn polymorphic<T: Debug + ?Sized>(t: &T) where &T: PointerSized {
- | ++++++++++++++++++++++
+LL | fn polymorphic<T: Debug + ?Sized>(t: &T) where &T: PointerLike {
+ | +++++++++++++++++++++
error: aborting due to previous error
diff --git a/tests/ui/dyn-star/check-size-at-cast.rs b/tests/ui/dyn-star/check-size-at-cast.rs
index 1f22f7983..17bc4f303 100644
--- a/tests/ui/dyn-star/check-size-at-cast.rs
+++ b/tests/ui/dyn-star/check-size-at-cast.rs
@@ -5,6 +5,6 @@ use std::fmt::Debug;
fn main() {
let i = [1, 2, 3, 4] as dyn* Debug;
- //~^ ERROR `[i32; 4]` needs to be a pointer-sized type
+ //~^ ERROR `[i32; 4]` needs to have the same alignment and size as a pointer
dbg!(i);
}
diff --git a/tests/ui/dyn-star/check-size-at-cast.stderr b/tests/ui/dyn-star/check-size-at-cast.stderr
index af2a1ccf7..19700b406 100644
--- a/tests/ui/dyn-star/check-size-at-cast.stderr
+++ b/tests/ui/dyn-star/check-size-at-cast.stderr
@@ -1,10 +1,10 @@
-error[E0277]: `[i32; 4]` needs to be a pointer-sized type
+error[E0277]: `[i32; 4]` needs to have the same alignment and size as a pointer
--> $DIR/check-size-at-cast.rs:7:13
|
LL | let i = [1, 2, 3, 4] as dyn* Debug;
- | ^^^^^^^^^^^^ `[i32; 4]` needs to be a pointer-sized type
+ | ^^^^^^^^^^^^ `[i32; 4]` needs to be a pointer-like type
|
- = help: the trait `PointerSized` is not implemented for `[i32; 4]`
+ = help: the trait `PointerLike` is not implemented for `[i32; 4]`
error: aborting due to previous error
diff --git a/tests/ui/dyn-star/dyn-star-to-dyn.rs b/tests/ui/dyn-star/dyn-star-to-dyn.rs
index a6d9df952..1d974b7ec 100644
--- a/tests/ui/dyn-star/dyn-star-to-dyn.rs
+++ b/tests/ui/dyn-star/dyn-star-to-dyn.rs
@@ -1,9 +1,17 @@
-// build-pass
+// run-pass
#![feature(dyn_star)]
//~^ WARN the feature `dyn_star` is incomplete and may not be safe to use and/or cause compiler crashes
+use std::fmt::Debug;
+
fn main() {
- let x: dyn* Send = &();
- let x = Box::new(x) as Box<dyn Send>;
+ let x: dyn* Debug = &42;
+ let x = Box::new(x) as Box<dyn Debug>;
+ assert_eq!("42", format!("{x:?}"));
+
+ // Also test opposite direction.
+ let x: Box<dyn Debug> = Box::new(42);
+ let x = &x as dyn* Debug;
+ assert_eq!("42", format!("{x:?}"));
}
diff --git a/tests/ui/dyn-star/llvm-old-style-ptrs.rs b/tests/ui/dyn-star/llvm-old-style-ptrs.rs
new file mode 100644
index 000000000..d35519632
--- /dev/null
+++ b/tests/ui/dyn-star/llvm-old-style-ptrs.rs
@@ -0,0 +1,23 @@
+// run-pass
+// compile-flags: -Copt-level=0 -Cllvm-args=-opaque-pointers=0
+
+// (opaque-pointers flag is called force-opaque-pointers in LLVM 13...)
+// min-llvm-version: 14.0
+
+// This test can be removed once non-opaque pointers are gone from LLVM, maybe.
+
+#![feature(dyn_star, pointer_like_trait)]
+#![allow(incomplete_features)]
+
+use std::fmt::Debug;
+use std::marker::PointerLike;
+
+fn make_dyn_star<'a>(t: impl PointerLike + Debug + 'a) -> dyn* Debug + 'a {
+ t as _
+}
+
+fn main() {
+ println!("{:?}", make_dyn_star(Box::new(1i32)));
+ println!("{:?}", make_dyn_star(2usize));
+ println!("{:?}", make_dyn_star((3usize,)));
+}
diff --git a/tests/ui/dyn-star/no-implicit-dyn-star.stderr b/tests/ui/dyn-star/no-implicit-dyn-star.stderr
index a3f4d21ca..66e1b9a09 100644
--- a/tests/ui/dyn-star/no-implicit-dyn-star.stderr
+++ b/tests/ui/dyn-star/no-implicit-dyn-star.stderr
@@ -2,7 +2,7 @@ error[E0308]: mismatched types
--> $DIR/no-implicit-dyn-star.rs:6:48
|
LL | dyn_star_foreign::require_dyn_star_display(1usize);
- | ------------------------------------------ ^^^^^^ expected trait object `dyn Display`, found `usize`
+ | ------------------------------------------ ^^^^^^ expected `dyn Display`, found `usize`
| |
| arguments to this function are incorrect
|
diff --git a/tests/ui/dyn-star/upcast.stderr b/tests/ui/dyn-star/upcast.stderr
index 74ccd6a18..e60144fea 100644
--- a/tests/ui/dyn-star/upcast.stderr
+++ b/tests/ui/dyn-star/upcast.stderr
@@ -7,13 +7,13 @@ LL | #![feature(dyn_star, trait_upcasting)]
= note: see issue #102425 <https://github.com/rust-lang/rust/issues/102425> for more information
= note: `#[warn(incomplete_features)]` on by default
-error[E0277]: `dyn* Foo` needs to be a pointer-sized type
+error[E0277]: `dyn* Foo` needs to have the same alignment and size as a pointer
--> $DIR/upcast.rs:30:23
|
LL | let w: dyn* Bar = w;
- | ^ `dyn* Foo` needs to be a pointer-sized type
+ | ^ `dyn* Foo` needs to be a pointer-like type
|
- = help: the trait `PointerSized` is not implemented for `dyn* Foo`
+ = help: the trait `PointerLike` is not implemented for `dyn* Foo`
error: aborting due to previous error; 1 warning emitted
diff --git a/tests/ui/empty/empty-struct-braces-expr.stderr b/tests/ui/empty/empty-struct-braces-expr.stderr
index 0e580aede..4604ebeaa 100644
--- a/tests/ui/empty/empty-struct-braces-expr.stderr
+++ b/tests/ui/empty/empty-struct-braces-expr.stderr
@@ -100,7 +100,7 @@ help: a unit struct with a similar name exists
LL | let xe1 = XEmpty2();
| ~~~~~~~
-error[E0599]: no variant or associated item named `Empty3` found for enum `XE` in the current scope
+error[E0599]: no variant or associated item named `Empty3` found for enum `empty_struct::XE` in the current scope
--> $DIR/empty-struct-braces-expr.rs:25:19
|
LL | let xe3 = XE::Empty3;
@@ -109,7 +109,7 @@ LL | let xe3 = XE::Empty3;
| variant or associated item not found in `XE`
| help: there is a variant with a similar name: `XEmpty3`
-error[E0599]: no variant or associated item named `Empty3` found for enum `XE` in the current scope
+error[E0599]: no variant or associated item named `Empty3` found for enum `empty_struct::XE` in the current scope
--> $DIR/empty-struct-braces-expr.rs:26:19
|
LL | let xe3 = XE::Empty3();
diff --git a/tests/ui/empty/issue-37026.stderr b/tests/ui/empty/issue-37026.stderr
index 48a4a5bca..75c3ab13c 100644
--- a/tests/ui/empty/issue-37026.stderr
+++ b/tests/ui/empty/issue-37026.stderr
@@ -4,7 +4,7 @@ error[E0308]: mismatched types
LL | let empty_struct::XEmpty2 = ();
| ^^^^^^^^^^^^^^^^^^^^^ -- this expression has type `()`
| |
- | expected `()`, found struct `XEmpty2`
+ | expected `()`, found `XEmpty2`
error[E0308]: mismatched types
--> $DIR/issue-37026.rs:7:9
@@ -12,7 +12,7 @@ error[E0308]: mismatched types
LL | let empty_struct::XEmpty6(..) = ();
| ^^^^^^^^^^^^^^^^^^^^^^^^^ -- this expression has type `()`
| |
- | expected `()`, found struct `XEmpty6`
+ | expected `()`, found `XEmpty6`
error: aborting due to 2 previous errors
diff --git a/tests/ui/error-codes/E0057.stderr b/tests/ui/error-codes/E0057.stderr
index 163737895..9b0cf0698 100644
--- a/tests/ui/error-codes/E0057.stderr
+++ b/tests/ui/error-codes/E0057.stderr
@@ -18,17 +18,16 @@ error[E0057]: this function takes 1 argument but 2 arguments were supplied
--> $DIR/E0057.rs:5:13
|
LL | let c = f(2, 3);
- | ^ - argument of type `{integer}` unexpected
+ | ^ ---
+ | | |
+ | | unexpected argument of type `{integer}`
+ | help: remove the extra argument
|
note: closure defined here
--> $DIR/E0057.rs:2:13
|
LL | let f = |x| x * 3;
| ^^^
-help: remove the extra argument
- |
-LL | let c = f(2);
- | ~~~
error: aborting due to 2 previous errors
diff --git a/tests/ui/error-codes/E0071.rs b/tests/ui/error-codes/E0071.rs
index bd8469de7..678502ba3 100644
--- a/tests/ui/error-codes/E0071.rs
+++ b/tests/ui/error-codes/E0071.rs
@@ -3,5 +3,5 @@ type FooAlias = Foo;
fn main() {
let u = FooAlias { value: 0 };
- //~^ ERROR expected struct, variant or union type, found enum `Foo` [E0071]
+ //~^ ERROR expected struct, variant or union type, found `Foo` [E0071]
}
diff --git a/tests/ui/error-codes/E0071.stderr b/tests/ui/error-codes/E0071.stderr
index ae312fc40..7bd4ddaf2 100644
--- a/tests/ui/error-codes/E0071.stderr
+++ b/tests/ui/error-codes/E0071.stderr
@@ -1,4 +1,4 @@
-error[E0071]: expected struct, variant or union type, found enum `Foo`
+error[E0071]: expected struct, variant or union type, found `Foo`
--> $DIR/E0071.rs:5:13
|
LL | let u = FooAlias { value: 0 };
diff --git a/tests/ui/error-codes/E0107.rs b/tests/ui/error-codes/E0107.rs
index d369fc2a5..fd23e7c00 100644
--- a/tests/ui/error-codes/E0107.rs
+++ b/tests/ui/error-codes/E0107.rs
@@ -11,39 +11,39 @@ enum Bar {
struct Baz<'a, 'b, 'c> {
buzz: Buzz<'a>,
- //~^ ERROR this struct takes 2 lifetime arguments
+ //~^ ERROR struct takes 2 lifetime arguments
//~| HELP add missing lifetime argument
bar: Bar<'a>,
- //~^ ERROR this enum takes 0 lifetime arguments
+ //~^ ERROR enum takes 0 lifetime arguments
//~| HELP remove these generics
foo2: Foo<'a, 'b, 'c>,
- //~^ ERROR this struct takes 1 lifetime argument
+ //~^ ERROR struct takes 1 lifetime argument
//~| HELP remove these lifetime arguments
qux1: Qux<'a, 'b, i32>,
- //~^ ERROR this struct takes 1 lifetime argument
+ //~^ ERROR struct takes 1 lifetime argument
//~| HELP remove this lifetime argument
qux2: Qux<'a, i32, 'b>,
- //~^ ERROR this struct takes 1 lifetime argument
+ //~^ ERROR struct takes 1 lifetime argument
//~| HELP remove this lifetime argument
qux3: Qux<'a, 'b, 'c, i32>,
- //~^ ERROR this struct takes 1 lifetime argument
+ //~^ ERROR struct takes 1 lifetime argument
//~| HELP remove these lifetime arguments
qux4: Qux<'a, i32, 'b, 'c>,
- //~^ ERROR this struct takes 1 lifetime argument
+ //~^ ERROR struct takes 1 lifetime argument
//~| HELP remove these lifetime arguments
qux5: Qux<'a, 'b, i32, 'c>,
- //~^ ERROR this struct takes 1 lifetime argument
+ //~^ ERROR struct takes 1 lifetime argument
//~| HELP remove this lifetime argument
quux: Quux<'a, i32, 'b>,
- //~^ ERROR this struct takes 0 lifetime arguments
+ //~^ ERROR struct takes 0 lifetime arguments
//~| HELP remove this lifetime argument
}
@@ -53,7 +53,7 @@ pub trait T {
}
fn trait_bound_generic<I: T<u8, u16>>(_i: I) {
- //~^ ERROR this trait takes 0 generic arguments
+ //~^ ERROR trait takes 0 generic arguments
//~| HELP replace the generic bounds with the associated types
}
diff --git a/tests/ui/error-codes/E0107.stderr b/tests/ui/error-codes/E0107.stderr
index 03430f8fa..3f540eb08 100644
--- a/tests/ui/error-codes/E0107.stderr
+++ b/tests/ui/error-codes/E0107.stderr
@@ -1,4 +1,4 @@
-error[E0107]: this struct takes 2 lifetime arguments but 1 lifetime argument was supplied
+error[E0107]: struct takes 2 lifetime arguments but 1 lifetime argument was supplied
--> $DIR/E0107.rs:13:11
|
LL | buzz: Buzz<'a>,
@@ -16,7 +16,7 @@ help: add missing lifetime argument
LL | buzz: Buzz<'a, 'a>,
| ++++
-error[E0107]: this enum takes 0 lifetime arguments but 1 lifetime argument was supplied
+error[E0107]: enum takes 0 lifetime arguments but 1 lifetime argument was supplied
--> $DIR/E0107.rs:17:10
|
LL | bar: Bar<'a>,
@@ -30,7 +30,7 @@ note: enum defined here, with 0 lifetime parameters
LL | enum Bar {
| ^^^
-error[E0107]: this struct takes 1 lifetime argument but 3 lifetime arguments were supplied
+error[E0107]: struct takes 1 lifetime argument but 3 lifetime arguments were supplied
--> $DIR/E0107.rs:21:11
|
LL | foo2: Foo<'a, 'b, 'c>,
@@ -44,7 +44,7 @@ note: struct defined here, with 1 lifetime parameter: `'a`
LL | struct Foo<'a>(&'a str);
| ^^^ --
-error[E0107]: this struct takes 1 lifetime argument but 2 lifetime arguments were supplied
+error[E0107]: struct takes 1 lifetime argument but 2 lifetime arguments were supplied
--> $DIR/E0107.rs:25:11
|
LL | qux1: Qux<'a, 'b, i32>,
@@ -58,7 +58,7 @@ note: struct defined here, with 1 lifetime parameter: `'a`
LL | struct Qux<'a, T>(&'a T);
| ^^^ --
-error[E0107]: this struct takes 1 lifetime argument but 2 lifetime arguments were supplied
+error[E0107]: struct takes 1 lifetime argument but 2 lifetime arguments were supplied
--> $DIR/E0107.rs:29:11
|
LL | qux2: Qux<'a, i32, 'b>,
@@ -72,7 +72,7 @@ note: struct defined here, with 1 lifetime parameter: `'a`
LL | struct Qux<'a, T>(&'a T);
| ^^^ --
-error[E0107]: this struct takes 1 lifetime argument but 3 lifetime arguments were supplied
+error[E0107]: struct takes 1 lifetime argument but 3 lifetime arguments were supplied
--> $DIR/E0107.rs:33:11
|
LL | qux3: Qux<'a, 'b, 'c, i32>,
@@ -86,7 +86,7 @@ note: struct defined here, with 1 lifetime parameter: `'a`
LL | struct Qux<'a, T>(&'a T);
| ^^^ --
-error[E0107]: this struct takes 1 lifetime argument but 3 lifetime arguments were supplied
+error[E0107]: struct takes 1 lifetime argument but 3 lifetime arguments were supplied
--> $DIR/E0107.rs:37:11
|
LL | qux4: Qux<'a, i32, 'b, 'c>,
@@ -100,7 +100,7 @@ note: struct defined here, with 1 lifetime parameter: `'a`
LL | struct Qux<'a, T>(&'a T);
| ^^^ --
-error[E0107]: this struct takes 1 lifetime argument but 3 lifetime arguments were supplied
+error[E0107]: struct takes 1 lifetime argument but 3 lifetime arguments were supplied
--> $DIR/E0107.rs:41:11
|
LL | qux5: Qux<'a, 'b, i32, 'c>,
@@ -114,7 +114,7 @@ note: struct defined here, with 1 lifetime parameter: `'a`
LL | struct Qux<'a, T>(&'a T);
| ^^^ --
-error[E0107]: this struct takes 0 lifetime arguments but 2 lifetime arguments were supplied
+error[E0107]: struct takes 0 lifetime arguments but 2 lifetime arguments were supplied
--> $DIR/E0107.rs:45:11
|
LL | quux: Quux<'a, i32, 'b>,
@@ -128,7 +128,7 @@ note: struct defined here, with 0 lifetime parameters
LL | struct Quux<T>(T);
| ^^^^
-error[E0107]: this trait takes 0 generic arguments but 2 generic arguments were supplied
+error[E0107]: trait takes 0 generic arguments but 2 generic arguments were supplied
--> $DIR/E0107.rs:55:27
|
LL | fn trait_bound_generic<I: T<u8, u16>>(_i: I) {
diff --git a/tests/ui/error-codes/E0116.stderr b/tests/ui/error-codes/E0116.stderr
index a5ceeb4a5..8a0276867 100644
--- a/tests/ui/error-codes/E0116.stderr
+++ b/tests/ui/error-codes/E0116.stderr
@@ -2,7 +2,7 @@ error[E0116]: cannot define inherent `impl` for a type outside of the crate wher
--> $DIR/E0116.rs:1:1
|
LL | impl Vec<u8> {}
- | ^^^^^^^^^^^^^^^ impl for type defined outside of crate.
+ | ^^^^^^^^^^^^ impl for type defined outside of crate.
|
= note: define and implement a trait or new type instead
diff --git a/tests/ui/error-codes/E0118.stderr b/tests/ui/error-codes/E0118.stderr
index 8c6fa7947..442f8a4f8 100644
--- a/tests/ui/error-codes/E0118.stderr
+++ b/tests/ui/error-codes/E0118.stderr
@@ -1,8 +1,8 @@
error[E0118]: no nominal type found for inherent implementation
- --> $DIR/E0118.rs:1:9
+ --> $DIR/E0118.rs:1:1
|
LL | impl<T> T {
- | ^ impl requires a nominal type
+ | ^^^^^^^^^ impl requires a nominal type
|
= note: either implement a trait on it or create a newtype to wrap it instead
diff --git a/tests/ui/error-codes/E0208.rs b/tests/ui/error-codes/E0208.rs
index c67d42889..74c138af4 100644
--- a/tests/ui/error-codes/E0208.rs
+++ b/tests/ui/error-codes/E0208.rs
@@ -1,7 +1,7 @@
#![feature(rustc_attrs)]
#[rustc_variance]
-struct Foo<'a, T> { //~ ERROR [-, o]
+struct Foo<'a, T> { //~ ERROR [+, o]
t: &'a mut T,
}
diff --git a/tests/ui/error-codes/E0208.stderr b/tests/ui/error-codes/E0208.stderr
index dbbb41e79..2c7072a7e 100644
--- a/tests/ui/error-codes/E0208.stderr
+++ b/tests/ui/error-codes/E0208.stderr
@@ -1,4 +1,4 @@
-error: [-, o]
+error: [+, o]
--> $DIR/E0208.rs:4:1
|
LL | struct Foo<'a, T> {
diff --git a/tests/ui/error-codes/E0390.stderr b/tests/ui/error-codes/E0390.stderr
index 0e5a9ca76..ec4b5758c 100644
--- a/tests/ui/error-codes/E0390.stderr
+++ b/tests/ui/error-codes/E0390.stderr
@@ -1,16 +1,16 @@
error[E0390]: cannot define inherent `impl` for primitive types
- --> $DIR/E0390.rs:5:6
+ --> $DIR/E0390.rs:5:1
|
LL | impl *mut Foo {}
- | ^^^^^^^^
+ | ^^^^^^^^^^^^^
|
= help: consider using an extension trait instead
error[E0390]: cannot define inherent `impl` for primitive types
- --> $DIR/E0390.rs:7:6
+ --> $DIR/E0390.rs:7:1
|
LL | impl fn(Foo) {}
- | ^^^^^^^
+ | ^^^^^^^^^^^^
|
= help: consider using an extension trait instead
diff --git a/tests/ui/error-codes/E0476.rs b/tests/ui/error-codes/E0476.rs
new file mode 100644
index 000000000..d5e4b8d23
--- /dev/null
+++ b/tests/ui/error-codes/E0476.rs
@@ -0,0 +1,13 @@
+#![feature(coerce_unsized)]
+#![feature(unsize)]
+
+use std::marker::Unsize;
+use std::ops::CoerceUnsized;
+
+struct Wrapper<T>(T);
+
+impl<'a, 'b, T, S> CoerceUnsized<&'a Wrapper<T>> for &'b Wrapper<S> where S: Unsize<T> {}
+//~^ ERROR lifetime of the source pointer does not outlive lifetime bound of the object type [E0476]
+//~^^ ERROR E0119
+
+fn main() {}
diff --git a/tests/ui/error-codes/E0476.stderr b/tests/ui/error-codes/E0476.stderr
new file mode 100644
index 000000000..a4bb26532
--- /dev/null
+++ b/tests/ui/error-codes/E0476.stderr
@@ -0,0 +1,31 @@
+error[E0119]: conflicting implementations of trait `CoerceUnsized<&Wrapper<_>>` for type `&Wrapper<_>`
+ --> $DIR/E0476.rs:9:1
+ |
+LL | impl<'a, 'b, T, S> CoerceUnsized<&'a Wrapper<T>> for &'b Wrapper<S> where S: Unsize<T> {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: conflicting implementation in crate `core`:
+ - impl<'a, 'b, T, U> CoerceUnsized<&'a U> for &'b T
+ where 'b: 'a, T: Unsize<U>, T: ?Sized, U: ?Sized;
+
+error[E0476]: lifetime of the source pointer does not outlive lifetime bound of the object type
+ --> $DIR/E0476.rs:9:1
+ |
+LL | impl<'a, 'b, T, S> CoerceUnsized<&'a Wrapper<T>> for &'b Wrapper<S> where S: Unsize<T> {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+note: object type is valid for the lifetime `'a` as defined here
+ --> $DIR/E0476.rs:9:6
+ |
+LL | impl<'a, 'b, T, S> CoerceUnsized<&'a Wrapper<T>> for &'b Wrapper<S> where S: Unsize<T> {}
+ | ^^
+note: source pointer is only valid for the lifetime `'b` as defined here
+ --> $DIR/E0476.rs:9:10
+ |
+LL | impl<'a, 'b, T, S> CoerceUnsized<&'a Wrapper<T>> for &'b Wrapper<S> where S: Unsize<T> {}
+ | ^^
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0119, E0476.
+For more information about an error, try `rustc --explain E0119`.
diff --git a/tests/ui/error-codes/E0503.stderr b/tests/ui/error-codes/E0503.stderr
index fafe363eb..2f02e3b1a 100644
--- a/tests/ui/error-codes/E0503.stderr
+++ b/tests/ui/error-codes/E0503.stderr
@@ -2,7 +2,7 @@ error[E0503]: cannot use `value` because it was mutably borrowed
--> $DIR/E0503.rs:4:16
|
LL | let _borrow = &mut value;
- | ---------- borrow of `value` occurs here
+ | ---------- `value` is borrowed here
LL | let _sum = value + 1;
| ^^^^^ use of borrowed `value`
LL | _borrow.use_mut();
diff --git a/tests/ui/error-codes/E0504.stderr b/tests/ui/error-codes/E0504.stderr
index e677e8916..20e16a538 100644
--- a/tests/ui/error-codes/E0504.stderr
+++ b/tests/ui/error-codes/E0504.stderr
@@ -1,6 +1,8 @@
error[E0505]: cannot move out of `fancy_num` because it is borrowed
--> $DIR/E0504.rs:9:13
|
+LL | let fancy_num = FancyNum { num: 5 };
+ | --------- binding `fancy_num` declared here
LL | let fancy_ref = &fancy_num;
| ---------- borrow of `fancy_num` occurs here
LL |
diff --git a/tests/ui/error-codes/E0505.stderr b/tests/ui/error-codes/E0505.stderr
index bd3f37f54..2ecb4a75c 100644
--- a/tests/ui/error-codes/E0505.stderr
+++ b/tests/ui/error-codes/E0505.stderr
@@ -1,6 +1,9 @@
error[E0505]: cannot move out of `x` because it is borrowed
--> $DIR/E0505.rs:9:13
|
+LL | let x = Value{};
+ | - binding `x` declared here
+LL | {
LL | let _ref_to_val: &Value = &x;
| -- borrow of `x` occurs here
LL | eat(x);
diff --git a/tests/ui/error-codes/E0506.stderr b/tests/ui/error-codes/E0506.stderr
index d70406b75..17ad7c611 100644
--- a/tests/ui/error-codes/E0506.stderr
+++ b/tests/ui/error-codes/E0506.stderr
@@ -2,9 +2,9 @@ error[E0506]: cannot assign to `fancy_num` because it is borrowed
--> $DIR/E0506.rs:8:5
|
LL | let fancy_ref = &fancy_num;
- | ---------- borrow of `fancy_num` occurs here
+ | ---------- `fancy_num` is borrowed here
LL | fancy_num = FancyNum { num: 6 };
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ assignment to borrowed `fancy_num` occurs here
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `fancy_num` is assigned to here but it was already borrowed
LL |
LL | println!("Num: {}, Ref: {}", fancy_num.num, fancy_ref.num);
| ------------- borrow later used here
diff --git a/tests/ui/error-codes/E0520.stderr b/tests/ui/error-codes/E0520.stderr
index 12ecead13..06658a49b 100644
--- a/tests/ui/error-codes/E0520.stderr
+++ b/tests/ui/error-codes/E0520.stderr
@@ -15,7 +15,7 @@ LL | impl<T: Clone> SpaceLlama for T {
| ------------------------------- parent `impl` is here
...
LL | default fn fly(&self) {}
- | ^^^^^^^^^^^^^^^^^^^^^^^^ cannot specialize default item `fly`
+ | ^^^^^^^^^^^^^^^^^^^^^ cannot specialize default item `fly`
|
= note: to specialize, `fly` in the parent `impl` must be marked `default`
diff --git a/tests/ui/error-codes/E0523.rs b/tests/ui/error-codes/E0523.rs
new file mode 100644
index 000000000..47717fbd5
--- /dev/null
+++ b/tests/ui/error-codes/E0523.rs
@@ -0,0 +1,14 @@
+// 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 `tests/ui/crate-loading/crateresolve1.rs`.
+
+extern crate crateresolve1;
+//~^ ERROR multiple candidates for `rlib` dependency `crateresolve1` found
+
+fn main() {}
diff --git a/tests/ui/error-codes/E0523.stderr b/tests/ui/error-codes/E0523.stderr
new file mode 100644
index 000000000..8e3eb2159
--- /dev/null
+++ b/tests/ui/error-codes/E0523.stderr
@@ -0,0 +1,13 @@
+error[E0464]: multiple candidates for `rlib` dependency `crateresolve1` found
+ --> $DIR/E0523.rs:11:1
+ |
+LL | extern crate crateresolve1;
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: candidate #1: $TEST_BUILD_DIR/error-codes/E0523/auxiliary/libcrateresolve1-1.somelib
+ = note: candidate #2: $TEST_BUILD_DIR/error-codes/E0523/auxiliary/libcrateresolve1-2.somelib
+ = note: candidate #3: $TEST_BUILD_DIR/error-codes/E0523/auxiliary/libcrateresolve1-3.somelib
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0464`.
diff --git a/tests/ui/error-codes/E0597.stderr b/tests/ui/error-codes/E0597.stderr
index b4a1180ad..82e3481b6 100644
--- a/tests/ui/error-codes/E0597.stderr
+++ b/tests/ui/error-codes/E0597.stderr
@@ -1,6 +1,8 @@
error[E0597]: `y` does not live long enough
--> $DIR/E0597.rs:8:16
|
+LL | let y = 0;
+ | - binding `y` declared here
LL | x.x = Some(&y);
| ^^ borrowed value does not live long enough
LL |
diff --git a/tests/ui/error-codes/E0624.rs b/tests/ui/error-codes/E0624.rs
index 4c68b70fb..45f72a565 100644
--- a/tests/ui/error-codes/E0624.rs
+++ b/tests/ui/error-codes/E0624.rs
@@ -8,5 +8,5 @@ mod inner {
fn main() {
let foo = inner::Foo;
- foo.method(); //~ ERROR associated function `method` is private [E0624]
+ foo.method(); //~ ERROR method `method` is private [E0624]
}
diff --git a/tests/ui/error-codes/E0624.stderr b/tests/ui/error-codes/E0624.stderr
index e59b8a8ae..23a8ea8a8 100644
--- a/tests/ui/error-codes/E0624.stderr
+++ b/tests/ui/error-codes/E0624.stderr
@@ -1,11 +1,11 @@
-error[E0624]: associated function `method` is private
+error[E0624]: method `method` is private
--> $DIR/E0624.rs:11:9
|
LL | fn method(&self) {}
- | ---------------- private associated function defined here
+ | ---------------- private method defined here
...
LL | foo.method();
- | ^^^^^^ private associated function
+ | ^^^^^^ private method
error: aborting due to previous error
diff --git a/tests/ui/error-codes/E0789.rs b/tests/ui/error-codes/E0789.rs
new file mode 100644
index 000000000..c0cbbcc9d
--- /dev/null
+++ b/tests/ui/error-codes/E0789.rs
@@ -0,0 +1,12 @@
+// compile-flags: --crate-type lib
+
+#![feature(rustc_attrs)]
+#![feature(staged_api)]
+#![unstable(feature = "foo_module", reason = "...", issue = "123")]
+
+#[rustc_allowed_through_unstable_modules]
+// #[stable(feature = "foo", since = "1.0")]
+struct Foo;
+//~^ ERROR `rustc_allowed_through_unstable_modules` attribute must be paired with a `stable` attribute
+//~^^ ERROR `rustc_allowed_through_unstable_modules` attribute must be paired with a `stable` attribute
+// FIXME: we shouldn't have two errors here, only occurs when using `-Zdeduplicate-diagnostics=no`
diff --git a/tests/ui/error-codes/E0789.stderr b/tests/ui/error-codes/E0789.stderr
new file mode 100644
index 000000000..faab92bae
--- /dev/null
+++ b/tests/ui/error-codes/E0789.stderr
@@ -0,0 +1,15 @@
+error[E0789]: `rustc_allowed_through_unstable_modules` attribute must be paired with a `stable` attribute
+ --> $DIR/E0789.rs:9:1
+ |
+LL | struct Foo;
+ | ^^^^^^^^^^^
+
+error[E0789]: `rustc_allowed_through_unstable_modules` attribute must be paired with a `stable` attribute
+ --> $DIR/E0789.rs:9:1
+ |
+LL | struct Foo;
+ | ^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0789`.
diff --git a/tests/ui/errors/trait-bound-error-spans/blame-trait-error.rs b/tests/ui/errors/trait-bound-error-spans/blame-trait-error.rs
new file mode 100644
index 000000000..0fbd85143
--- /dev/null
+++ b/tests/ui/errors/trait-bound-error-spans/blame-trait-error.rs
@@ -0,0 +1,102 @@
+trait T1 {}
+trait T2 {}
+trait T3 {}
+trait T4 {}
+
+impl<B: T2> T1 for Wrapper<B> {}
+
+impl T2 for i32 {}
+impl T3 for i32 {}
+
+impl<A: T3> T2 for Burrito<A> {}
+
+struct Wrapper<W> {
+ value: W,
+}
+
+struct Burrito<F> {
+ filling: F,
+}
+
+impl<It: Iterator> T1 for Option<It> {}
+
+impl<'a, A: T1> T1 for &'a A {}
+
+fn want<V: T1>(_x: V) {}
+
+enum ExampleTuple<T> {
+ ExampleTupleVariant(T),
+}
+use ExampleDifferentTupleVariantName as ExampleYetAnotherTupleVariantName;
+use ExampleTuple as ExampleOtherTuple;
+use ExampleTuple::ExampleTupleVariant as ExampleDifferentTupleVariantName;
+use ExampleTuple::*;
+
+impl<A> T1 for ExampleTuple<A> where A: T3 {}
+
+enum ExampleStruct<T> {
+ ExampleStructVariant { field: T },
+}
+use ExampleDifferentStructVariantName as ExampleYetAnotherStructVariantName;
+use ExampleStruct as ExampleOtherStruct;
+use ExampleStruct::ExampleStructVariant as ExampleDifferentStructVariantName;
+use ExampleStruct::*;
+
+impl<A> T1 for ExampleStruct<A> where A: T3 {}
+
+struct ExampleActuallyTupleStruct<T>(T, i32);
+use ExampleActuallyTupleStruct as ExampleActuallyTupleStructOther;
+
+impl<A> T1 for ExampleActuallyTupleStruct<A> where A: T3 {}
+
+fn example<Q>(q: Q) {
+ want(Wrapper { value: Burrito { filling: q } });
+ //~^ ERROR the trait bound `Q: T3` is not satisfied [E0277]
+
+ want(Some(()));
+ //~^ ERROR `()` is not an iterator [E0277]
+
+ want(Some(q));
+ //~^ ERROR `Q` is not an iterator [E0277]
+
+ want(&Some(q));
+ //~^ ERROR `Q` is not an iterator [E0277]
+
+ want(&ExampleTuple::ExampleTupleVariant(q));
+ //~^ ERROR `Q: T3` is not satisfied [E0277]
+
+ want(&ExampleTupleVariant(q));
+ //~^ ERROR `Q: T3` is not satisfied [E0277]
+
+ want(&ExampleOtherTuple::ExampleTupleVariant(q));
+ //~^ ERROR `Q: T3` is not satisfied [E0277]
+
+ want(&ExampleDifferentTupleVariantName(q));
+ //~^ ERROR `Q: T3` is not satisfied [E0277]
+
+ want(&ExampleYetAnotherTupleVariantName(q));
+ //~^ ERROR `Q: T3` is not satisfied [E0277]
+
+ want(&ExampleStruct::ExampleStructVariant { field: q });
+ //~^ ERROR `Q: T3` is not satisfied [E0277]
+
+ want(&ExampleStructVariant { field: q });
+ //~^ ERROR `Q: T3` is not satisfied [E0277]
+
+ want(&ExampleOtherStruct::ExampleStructVariant { field: q });
+ //~^ ERROR `Q: T3` is not satisfied [E0277]
+
+ want(&ExampleDifferentStructVariantName { field: q });
+ //~^ ERROR `Q: T3` is not satisfied [E0277]
+
+ want(&ExampleYetAnotherStructVariantName { field: q });
+ //~^ ERROR `Q: T3` is not satisfied [E0277]
+
+ want(&ExampleActuallyTupleStruct(q, 0));
+ //~^ ERROR `Q: T3` is not satisfied [E0277]
+
+ want(&ExampleActuallyTupleStructOther(q, 0));
+ //~^ ERROR `Q: T3` is not satisfied [E0277]
+}
+
+fn main() {}
diff --git a/tests/ui/errors/trait-bound-error-spans/blame-trait-error.stderr b/tests/ui/errors/trait-bound-error-spans/blame-trait-error.stderr
new file mode 100644
index 000000000..9228a047e
--- /dev/null
+++ b/tests/ui/errors/trait-bound-error-spans/blame-trait-error.stderr
@@ -0,0 +1,402 @@
+error[E0277]: the trait bound `Q: T3` is not satisfied
+ --> $DIR/blame-trait-error.rs:53:46
+ |
+LL | want(Wrapper { value: Burrito { filling: q } });
+ | ---- ^ the trait `T3` is not implemented for `Q`
+ | |
+ | required by a bound introduced by this call
+ |
+note: required for `Burrito<Q>` to implement `T2`
+ --> $DIR/blame-trait-error.rs:11:13
+ |
+LL | impl<A: T3> T2 for Burrito<A> {}
+ | -- ^^ ^^^^^^^^^^
+ | |
+ | unsatisfied trait bound introduced here
+note: required for `Wrapper<Burrito<Q>>` to implement `T1`
+ --> $DIR/blame-trait-error.rs:6:13
+ |
+LL | impl<B: T2> T1 for Wrapper<B> {}
+ | -- ^^ ^^^^^^^^^^
+ | |
+ | unsatisfied trait bound introduced here
+note: required by a bound in `want`
+ --> $DIR/blame-trait-error.rs:25:12
+ |
+LL | fn want<V: T1>(_x: V) {}
+ | ^^ required by this bound in `want`
+help: consider restricting type parameter `Q`
+ |
+LL | fn example<Q: T3>(q: Q) {
+ | ++++
+
+error[E0277]: `()` is not an iterator
+ --> $DIR/blame-trait-error.rs:56:15
+ |
+LL | want(Some(()));
+ | ---- ^^ `()` is not an iterator
+ | |
+ | required by a bound introduced by this call
+ |
+ = help: the trait `Iterator` is not implemented for `()`
+ = help: the trait `T1` is implemented for `Option<It>`
+note: required for `Option<()>` to implement `T1`
+ --> $DIR/blame-trait-error.rs:21:20
+ |
+LL | impl<It: Iterator> T1 for Option<It> {}
+ | -------- ^^ ^^^^^^^^^^
+ | |
+ | unsatisfied trait bound introduced here
+note: required by a bound in `want`
+ --> $DIR/blame-trait-error.rs:25:12
+ |
+LL | fn want<V: T1>(_x: V) {}
+ | ^^ required by this bound in `want`
+
+error[E0277]: `Q` is not an iterator
+ --> $DIR/blame-trait-error.rs:59:15
+ |
+LL | want(Some(q));
+ | ---- ^ `Q` is not an iterator
+ | |
+ | required by a bound introduced by this call
+ |
+note: required for `Option<Q>` to implement `T1`
+ --> $DIR/blame-trait-error.rs:21:20
+ |
+LL | impl<It: Iterator> T1 for Option<It> {}
+ | -------- ^^ ^^^^^^^^^^
+ | |
+ | unsatisfied trait bound introduced here
+note: required by a bound in `want`
+ --> $DIR/blame-trait-error.rs:25:12
+ |
+LL | fn want<V: T1>(_x: V) {}
+ | ^^ required by this bound in `want`
+help: consider restricting type parameter `Q`
+ |
+LL | fn example<Q: std::iter::Iterator>(q: Q) {
+ | +++++++++++++++++++++
+
+error[E0277]: `Q` is not an iterator
+ --> $DIR/blame-trait-error.rs:62:16
+ |
+LL | want(&Some(q));
+ | ---- ^ `Q` is not an iterator
+ | |
+ | required by a bound introduced by this call
+ |
+note: required for `Option<Q>` to implement `T1`
+ --> $DIR/blame-trait-error.rs:21:20
+ |
+LL | impl<It: Iterator> T1 for Option<It> {}
+ | -------- ^^ ^^^^^^^^^^
+ | |
+ | unsatisfied trait bound introduced here
+ = note: 1 redundant requirement hidden
+ = note: required for `&Option<Q>` to implement `T1`
+note: required by a bound in `want`
+ --> $DIR/blame-trait-error.rs:25:12
+ |
+LL | fn want<V: T1>(_x: V) {}
+ | ^^ required by this bound in `want`
+help: consider restricting type parameter `Q`
+ |
+LL | fn example<Q: std::iter::Iterator>(q: Q) {
+ | +++++++++++++++++++++
+
+error[E0277]: the trait bound `Q: T3` is not satisfied
+ --> $DIR/blame-trait-error.rs:65:45
+ |
+LL | want(&ExampleTuple::ExampleTupleVariant(q));
+ | ---- ^ the trait `T3` is not implemented for `Q`
+ | |
+ | required by a bound introduced by this call
+ |
+note: required for `ExampleTuple<Q>` to implement `T1`
+ --> $DIR/blame-trait-error.rs:35:9
+ |
+LL | impl<A> T1 for ExampleTuple<A> where A: T3 {}
+ | ^^ ^^^^^^^^^^^^^^^ -- unsatisfied trait bound introduced here
+ = note: 1 redundant requirement hidden
+ = note: required for `&ExampleTuple<Q>` to implement `T1`
+note: required by a bound in `want`
+ --> $DIR/blame-trait-error.rs:25:12
+ |
+LL | fn want<V: T1>(_x: V) {}
+ | ^^ required by this bound in `want`
+help: consider restricting type parameter `Q`
+ |
+LL | fn example<Q: T3>(q: Q) {
+ | ++++
+
+error[E0277]: the trait bound `Q: T3` is not satisfied
+ --> $DIR/blame-trait-error.rs:68:31
+ |
+LL | want(&ExampleTupleVariant(q));
+ | ---- ^ the trait `T3` is not implemented for `Q`
+ | |
+ | required by a bound introduced by this call
+ |
+note: required for `ExampleTuple<Q>` to implement `T1`
+ --> $DIR/blame-trait-error.rs:35:9
+ |
+LL | impl<A> T1 for ExampleTuple<A> where A: T3 {}
+ | ^^ ^^^^^^^^^^^^^^^ -- unsatisfied trait bound introduced here
+ = note: 1 redundant requirement hidden
+ = note: required for `&ExampleTuple<Q>` to implement `T1`
+note: required by a bound in `want`
+ --> $DIR/blame-trait-error.rs:25:12
+ |
+LL | fn want<V: T1>(_x: V) {}
+ | ^^ required by this bound in `want`
+help: consider restricting type parameter `Q`
+ |
+LL | fn example<Q: T3>(q: Q) {
+ | ++++
+
+error[E0277]: the trait bound `Q: T3` is not satisfied
+ --> $DIR/blame-trait-error.rs:71:50
+ |
+LL | want(&ExampleOtherTuple::ExampleTupleVariant(q));
+ | ---- ^ the trait `T3` is not implemented for `Q`
+ | |
+ | required by a bound introduced by this call
+ |
+note: required for `ExampleTuple<Q>` to implement `T1`
+ --> $DIR/blame-trait-error.rs:35:9
+ |
+LL | impl<A> T1 for ExampleTuple<A> where A: T3 {}
+ | ^^ ^^^^^^^^^^^^^^^ -- unsatisfied trait bound introduced here
+ = note: 1 redundant requirement hidden
+ = note: required for `&ExampleTuple<Q>` to implement `T1`
+note: required by a bound in `want`
+ --> $DIR/blame-trait-error.rs:25:12
+ |
+LL | fn want<V: T1>(_x: V) {}
+ | ^^ required by this bound in `want`
+help: consider restricting type parameter `Q`
+ |
+LL | fn example<Q: T3>(q: Q) {
+ | ++++
+
+error[E0277]: the trait bound `Q: T3` is not satisfied
+ --> $DIR/blame-trait-error.rs:74:44
+ |
+LL | want(&ExampleDifferentTupleVariantName(q));
+ | ---- ^ the trait `T3` is not implemented for `Q`
+ | |
+ | required by a bound introduced by this call
+ |
+note: required for `ExampleTuple<Q>` to implement `T1`
+ --> $DIR/blame-trait-error.rs:35:9
+ |
+LL | impl<A> T1 for ExampleTuple<A> where A: T3 {}
+ | ^^ ^^^^^^^^^^^^^^^ -- unsatisfied trait bound introduced here
+ = note: 1 redundant requirement hidden
+ = note: required for `&ExampleTuple<Q>` to implement `T1`
+note: required by a bound in `want`
+ --> $DIR/blame-trait-error.rs:25:12
+ |
+LL | fn want<V: T1>(_x: V) {}
+ | ^^ required by this bound in `want`
+help: consider restricting type parameter `Q`
+ |
+LL | fn example<Q: T3>(q: Q) {
+ | ++++
+
+error[E0277]: the trait bound `Q: T3` is not satisfied
+ --> $DIR/blame-trait-error.rs:77:45
+ |
+LL | want(&ExampleYetAnotherTupleVariantName(q));
+ | ---- ^ the trait `T3` is not implemented for `Q`
+ | |
+ | required by a bound introduced by this call
+ |
+note: required for `ExampleTuple<Q>` to implement `T1`
+ --> $DIR/blame-trait-error.rs:35:9
+ |
+LL | impl<A> T1 for ExampleTuple<A> where A: T3 {}
+ | ^^ ^^^^^^^^^^^^^^^ -- unsatisfied trait bound introduced here
+ = note: 1 redundant requirement hidden
+ = note: required for `&ExampleTuple<Q>` to implement `T1`
+note: required by a bound in `want`
+ --> $DIR/blame-trait-error.rs:25:12
+ |
+LL | fn want<V: T1>(_x: V) {}
+ | ^^ required by this bound in `want`
+help: consider restricting type parameter `Q`
+ |
+LL | fn example<Q: T3>(q: Q) {
+ | ++++
+
+error[E0277]: the trait bound `Q: T3` is not satisfied
+ --> $DIR/blame-trait-error.rs:80:56
+ |
+LL | want(&ExampleStruct::ExampleStructVariant { field: q });
+ | ---- required by a bound introduced by this call ^ the trait `T3` is not implemented for `Q`
+ |
+note: required for `ExampleStruct<Q>` to implement `T1`
+ --> $DIR/blame-trait-error.rs:45:9
+ |
+LL | impl<A> T1 for ExampleStruct<A> where A: T3 {}
+ | ^^ ^^^^^^^^^^^^^^^^ -- unsatisfied trait bound introduced here
+ = note: 1 redundant requirement hidden
+ = note: required for `&ExampleStruct<Q>` to implement `T1`
+note: required by a bound in `want`
+ --> $DIR/blame-trait-error.rs:25:12
+ |
+LL | fn want<V: T1>(_x: V) {}
+ | ^^ required by this bound in `want`
+help: consider restricting type parameter `Q`
+ |
+LL | fn example<Q: T3>(q: Q) {
+ | ++++
+
+error[E0277]: the trait bound `Q: T3` is not satisfied
+ --> $DIR/blame-trait-error.rs:83:41
+ |
+LL | want(&ExampleStructVariant { field: q });
+ | ---- ^ the trait `T3` is not implemented for `Q`
+ | |
+ | required by a bound introduced by this call
+ |
+note: required for `ExampleStruct<Q>` to implement `T1`
+ --> $DIR/blame-trait-error.rs:45:9
+ |
+LL | impl<A> T1 for ExampleStruct<A> where A: T3 {}
+ | ^^ ^^^^^^^^^^^^^^^^ -- unsatisfied trait bound introduced here
+ = note: 1 redundant requirement hidden
+ = note: required for `&ExampleStruct<Q>` to implement `T1`
+note: required by a bound in `want`
+ --> $DIR/blame-trait-error.rs:25:12
+ |
+LL | fn want<V: T1>(_x: V) {}
+ | ^^ required by this bound in `want`
+help: consider restricting type parameter `Q`
+ |
+LL | fn example<Q: T3>(q: Q) {
+ | ++++
+
+error[E0277]: the trait bound `Q: T3` is not satisfied
+ --> $DIR/blame-trait-error.rs:86:61
+ |
+LL | want(&ExampleOtherStruct::ExampleStructVariant { field: q });
+ | ---- required by a bound introduced by this call ^ the trait `T3` is not implemented for `Q`
+ |
+note: required for `ExampleStruct<Q>` to implement `T1`
+ --> $DIR/blame-trait-error.rs:45:9
+ |
+LL | impl<A> T1 for ExampleStruct<A> where A: T3 {}
+ | ^^ ^^^^^^^^^^^^^^^^ -- unsatisfied trait bound introduced here
+ = note: 1 redundant requirement hidden
+ = note: required for `&ExampleStruct<Q>` to implement `T1`
+note: required by a bound in `want`
+ --> $DIR/blame-trait-error.rs:25:12
+ |
+LL | fn want<V: T1>(_x: V) {}
+ | ^^ required by this bound in `want`
+help: consider restricting type parameter `Q`
+ |
+LL | fn example<Q: T3>(q: Q) {
+ | ++++
+
+error[E0277]: the trait bound `Q: T3` is not satisfied
+ --> $DIR/blame-trait-error.rs:89:54
+ |
+LL | want(&ExampleDifferentStructVariantName { field: q });
+ | ---- required by a bound introduced by this call ^ the trait `T3` is not implemented for `Q`
+ |
+note: required for `ExampleStruct<Q>` to implement `T1`
+ --> $DIR/blame-trait-error.rs:45:9
+ |
+LL | impl<A> T1 for ExampleStruct<A> where A: T3 {}
+ | ^^ ^^^^^^^^^^^^^^^^ -- unsatisfied trait bound introduced here
+ = note: 1 redundant requirement hidden
+ = note: required for `&ExampleStruct<Q>` to implement `T1`
+note: required by a bound in `want`
+ --> $DIR/blame-trait-error.rs:25:12
+ |
+LL | fn want<V: T1>(_x: V) {}
+ | ^^ required by this bound in `want`
+help: consider restricting type parameter `Q`
+ |
+LL | fn example<Q: T3>(q: Q) {
+ | ++++
+
+error[E0277]: the trait bound `Q: T3` is not satisfied
+ --> $DIR/blame-trait-error.rs:92:55
+ |
+LL | want(&ExampleYetAnotherStructVariantName { field: q });
+ | ---- required by a bound introduced by this call ^ the trait `T3` is not implemented for `Q`
+ |
+note: required for `ExampleStruct<Q>` to implement `T1`
+ --> $DIR/blame-trait-error.rs:45:9
+ |
+LL | impl<A> T1 for ExampleStruct<A> where A: T3 {}
+ | ^^ ^^^^^^^^^^^^^^^^ -- unsatisfied trait bound introduced here
+ = note: 1 redundant requirement hidden
+ = note: required for `&ExampleStruct<Q>` to implement `T1`
+note: required by a bound in `want`
+ --> $DIR/blame-trait-error.rs:25:12
+ |
+LL | fn want<V: T1>(_x: V) {}
+ | ^^ required by this bound in `want`
+help: consider restricting type parameter `Q`
+ |
+LL | fn example<Q: T3>(q: Q) {
+ | ++++
+
+error[E0277]: the trait bound `Q: T3` is not satisfied
+ --> $DIR/blame-trait-error.rs:95:38
+ |
+LL | want(&ExampleActuallyTupleStruct(q, 0));
+ | ---- ^ the trait `T3` is not implemented for `Q`
+ | |
+ | required by a bound introduced by this call
+ |
+note: required for `ExampleActuallyTupleStruct<Q>` to implement `T1`
+ --> $DIR/blame-trait-error.rs:50:9
+ |
+LL | impl<A> T1 for ExampleActuallyTupleStruct<A> where A: T3 {}
+ | ^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -- unsatisfied trait bound introduced here
+ = note: 1 redundant requirement hidden
+ = note: required for `&ExampleActuallyTupleStruct<Q>` to implement `T1`
+note: required by a bound in `want`
+ --> $DIR/blame-trait-error.rs:25:12
+ |
+LL | fn want<V: T1>(_x: V) {}
+ | ^^ required by this bound in `want`
+help: consider restricting type parameter `Q`
+ |
+LL | fn example<Q: T3>(q: Q) {
+ | ++++
+
+error[E0277]: the trait bound `Q: T3` is not satisfied
+ --> $DIR/blame-trait-error.rs:98:43
+ |
+LL | want(&ExampleActuallyTupleStructOther(q, 0));
+ | ---- ^ the trait `T3` is not implemented for `Q`
+ | |
+ | required by a bound introduced by this call
+ |
+note: required for `ExampleActuallyTupleStruct<Q>` to implement `T1`
+ --> $DIR/blame-trait-error.rs:50:9
+ |
+LL | impl<A> T1 for ExampleActuallyTupleStruct<A> where A: T3 {}
+ | ^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -- unsatisfied trait bound introduced here
+ = note: 1 redundant requirement hidden
+ = note: required for `&ExampleActuallyTupleStruct<Q>` to implement `T1`
+note: required by a bound in `want`
+ --> $DIR/blame-trait-error.rs:25:12
+ |
+LL | fn want<V: T1>(_x: V) {}
+ | ^^ required by this bound in `want`
+help: consider restricting type parameter `Q`
+ |
+LL | fn example<Q: T3>(q: Q) {
+ | ++++
+
+error: aborting due to 16 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/errors/traits/blame-trait-error-spans-on-exprs.rs b/tests/ui/errors/traits/blame-trait-error-spans-on-exprs.rs
new file mode 100644
index 000000000..6fea409ed
--- /dev/null
+++ b/tests/ui/errors/traits/blame-trait-error-spans-on-exprs.rs
@@ -0,0 +1,137 @@
+// This test examines the error spans reported when a generic `impl` fails.
+// For example, if a function wants an `Option<T>` where `T: Copy` but you pass `Some(vec![1, 2])`,
+// then we want to point at the `vec![1, 2]` and not the `Some( ... )` expression.
+
+trait T1 {}
+trait T2 {}
+trait T3 {}
+trait T4 {}
+
+impl T2 for i32 {}
+impl T3 for i32 {}
+
+struct Wrapper<W> {
+ value: W,
+}
+impl<B: T2> T1 for Wrapper<B> {}
+
+struct Burrito<F> {
+ spicy: bool,
+ filling: F,
+}
+impl<A: T3> T2 for Burrito<A> {}
+
+struct BurritoTuple<F>(F);
+impl<C: T3> T2 for BurritoTuple<C> {}
+
+enum BurritoKinds<G> {
+ SmallBurrito { spicy: bool, small_filling: G },
+ LargeBurrito { spicy: bool, large_filling: G },
+ MultiBurrito { first_filling: G, second_filling: G },
+}
+impl<D: T3> T2 for BurritoKinds<D> {}
+
+struct Taco<H>(bool, H);
+impl<E: T3> T2 for Taco<E> {}
+
+enum TacoKinds<H> {
+ OneTaco(bool, H),
+ TwoTacos(bool, H, H),
+}
+impl<F: T3> T2 for TacoKinds<F> {}
+
+struct GenericBurrito<Spiciness, Filling> {
+ spiciness: Spiciness,
+ filling: Filling,
+}
+impl<X, Y: T3> T2 for GenericBurrito<X, Y> {}
+struct NotSpicy;
+
+impl<A: T3, B: T3> T2 for (A, B) {}
+impl<A: T2, B: T2> T1 for (A, B) {}
+
+fn want<V: T1>(_x: V) {}
+
+// Some more-complex examples:
+type AliasBurrito<T> = GenericBurrito<T, T>;
+
+// The following example is fairly confusing. The idea is that we want to "misdirect" the location
+// of the error.
+
+struct Two<A, B> {
+ a: A,
+ b: B,
+}
+
+impl<X, Y: T1, Z> T1 for Two<Two<X, Y>, Z> {}
+
+struct DoubleWrapper<T> {
+ item: Wrapper<T>,
+}
+
+impl<T: T1> T1 for DoubleWrapper<T> {}
+
+impl<'a, T: T2> T1 for &'a T {}
+
+fn example<Q>(q: Q) {
+ // In each of the following examples, we expect the error span to point at the 'q' variable,
+ // since the missing constraint is `Q: T3`.
+
+ // Verifies for struct:
+ want(Wrapper { value: Burrito { spicy: false, filling: q } });
+ //~^ ERROR the trait bound `Q: T3` is not satisfied [E0277]
+
+ // Verifies for enum with named fields in variant:
+ want(Wrapper { value: BurritoKinds::SmallBurrito { spicy: true, small_filling: q } });
+ //~^ ERROR the trait bound `Q: T3` is not satisfied [E0277]
+
+ // Verifies for tuple struct:
+ want(Wrapper { value: Taco(false, q) });
+ //~^ ERROR the trait bound `Q: T3` is not satisfied [E0277]
+
+ // Verifies for tuple enum variant:
+ want(Wrapper { value: TacoKinds::OneTaco(false, q) });
+ //~^ ERROR the trait bound `Q: T3` is not satisfied [E0277]
+
+ // Verifies for generic type with multiple parameters:
+ want(Wrapper { value: GenericBurrito { spiciness: NotSpicy, filling: q } });
+ //~^ ERROR the trait bound `Q: T3` is not satisfied [E0277]
+
+ // Verifies for tuple:
+ want((3, q));
+ //~^ ERROR the trait bound `Q: T2` is not satisfied [E0277]
+
+ // Verifies for nested tuple:
+ want(Wrapper { value: (3, q) });
+ //~^ ERROR the trait bound `Q: T3` is not satisfied [E0277]
+
+ // Verifies for nested tuple:
+ want(((3, q), 5));
+ //~^ ERROR the trait bound `Q: T3` is not satisfied [E0277]
+
+ want(DoubleWrapper { item: Wrapper { value: q } });
+ //~^ ERROR the trait bound `Q: T1` is not satisfied [E0277]
+
+ want(DoubleWrapper { item: Wrapper { value: DoubleWrapper { item: Wrapper { value: q } } } });
+ //~^ ERROR the trait bound `Q: T1` is not satisfied [E0277]
+
+ // Verifies for type alias to struct:
+ want(Wrapper { value: AliasBurrito { spiciness: q, filling: q } });
+ //~^ ERROR the trait bound `Q: T3` is not satisfied [E0277]
+
+ want(Two { a: Two { a: (), b: q }, b: () });
+ //~^ ERROR the trait bound `Q: T1` is not satisfied [E0277]
+
+ // We *should* blame the 'q'.
+ // FIXME: Right now, the wrong field is blamed.
+ want(
+ Two { a: Two { a: (), b: Two { a: Two { a: (), b: q }, b: () } }, b: () },
+ //~^ ERROR the trait bound `Q: T1` is not satisfied [E0277]
+ );
+
+ // Verifies for reference:
+ want(&Burrito { spicy: false, filling: q });
+ //~^ ERROR the trait bound `Q: T3` is not satisfied [E0277]
+}
+
+fn main() {}
diff --git a/tests/ui/errors/traits/blame-trait-error-spans-on-exprs.stderr b/tests/ui/errors/traits/blame-trait-error-spans-on-exprs.stderr
new file mode 100644
index 000000000..b6a24e12b
--- /dev/null
+++ b/tests/ui/errors/traits/blame-trait-error-spans-on-exprs.stderr
@@ -0,0 +1,412 @@
+error[E0277]: the trait bound `Q: T3` is not satisfied
+ --> $DIR/blame-trait-error-spans-on-exprs.rs:81:60
+ |
+LL | want(Wrapper { value: Burrito { spicy: false, filling: q } });
+ | ---- required by a bound introduced by this call ^ the trait `T3` is not implemented for `Q`
+ |
+note: required for `Burrito<Q>` to implement `T2`
+ --> $DIR/blame-trait-error-spans-on-exprs.rs:22:13
+ |
+LL | impl<A: T3> T2 for Burrito<A> {}
+ | -- ^^ ^^^^^^^^^^
+ | |
+ | unsatisfied trait bound introduced here
+note: required for `Wrapper<Burrito<Q>>` to implement `T1`
+ --> $DIR/blame-trait-error-spans-on-exprs.rs:16:13
+ |
+LL | impl<B: T2> T1 for Wrapper<B> {}
+ | -- ^^ ^^^^^^^^^^
+ | |
+ | unsatisfied trait bound introduced here
+note: required by a bound in `want`
+ --> $DIR/blame-trait-error-spans-on-exprs.rs:53:12
+ |
+LL | fn want<V: T1>(_x: V) {}
+ | ^^ required by this bound in `want`
+help: consider restricting type parameter `Q`
+ |
+LL | fn example<Q: T3>(q: Q) {
+ | ++++
+
+error[E0277]: the trait bound `Q: T3` is not satisfied
+ --> $DIR/blame-trait-error-spans-on-exprs.rs:85:84
+ |
+LL | want(Wrapper { value: BurritoKinds::SmallBurrito { spicy: true, small_filling: q } });
+ | ---- required by a bound introduced by this call ^ the trait `T3` is not implemented for `Q`
+ |
+note: required for `BurritoKinds<Q>` to implement `T2`
+ --> $DIR/blame-trait-error-spans-on-exprs.rs:32:13
+ |
+LL | impl<D: T3> T2 for BurritoKinds<D> {}
+ | -- ^^ ^^^^^^^^^^^^^^^
+ | |
+ | unsatisfied trait bound introduced here
+note: required for `Wrapper<BurritoKinds<Q>>` to implement `T1`
+ --> $DIR/blame-trait-error-spans-on-exprs.rs:16:13
+ |
+LL | impl<B: T2> T1 for Wrapper<B> {}
+ | -- ^^ ^^^^^^^^^^
+ | |
+ | unsatisfied trait bound introduced here
+note: required by a bound in `want`
+ --> $DIR/blame-trait-error-spans-on-exprs.rs:53:12
+ |
+LL | fn want<V: T1>(_x: V) {}
+ | ^^ required by this bound in `want`
+help: consider restricting type parameter `Q`
+ |
+LL | fn example<Q: T3>(q: Q) {
+ | ++++
+
+error[E0277]: the trait bound `Q: T3` is not satisfied
+ --> $DIR/blame-trait-error-spans-on-exprs.rs:89:39
+ |
+LL | want(Wrapper { value: Taco(false, q) });
+ | ---- ^ the trait `T3` is not implemented for `Q`
+ | |
+ | required by a bound introduced by this call
+ |
+note: required for `Taco<Q>` to implement `T2`
+ --> $DIR/blame-trait-error-spans-on-exprs.rs:35:13
+ |
+LL | impl<E: T3> T2 for Taco<E> {}
+ | -- ^^ ^^^^^^^
+ | |
+ | unsatisfied trait bound introduced here
+note: required for `Wrapper<Taco<Q>>` to implement `T1`
+ --> $DIR/blame-trait-error-spans-on-exprs.rs:16:13
+ |
+LL | impl<B: T2> T1 for Wrapper<B> {}
+ | -- ^^ ^^^^^^^^^^
+ | |
+ | unsatisfied trait bound introduced here
+note: required by a bound in `want`
+ --> $DIR/blame-trait-error-spans-on-exprs.rs:53:12
+ |
+LL | fn want<V: T1>(_x: V) {}
+ | ^^ required by this bound in `want`
+help: consider restricting type parameter `Q`
+ |
+LL | fn example<Q: T3>(q: Q) {
+ | ++++
+
+error[E0277]: the trait bound `Q: T3` is not satisfied
+ --> $DIR/blame-trait-error-spans-on-exprs.rs:93:53
+ |
+LL | want(Wrapper { value: TacoKinds::OneTaco(false, q) });
+ | ---- ^ the trait `T3` is not implemented for `Q`
+ | |
+ | required by a bound introduced by this call
+ |
+note: required for `TacoKinds<Q>` to implement `T2`
+ --> $DIR/blame-trait-error-spans-on-exprs.rs:41:13
+ |
+LL | impl<F: T3> T2 for TacoKinds<F> {}
+ | -- ^^ ^^^^^^^^^^^^
+ | |
+ | unsatisfied trait bound introduced here
+note: required for `Wrapper<TacoKinds<Q>>` to implement `T1`
+ --> $DIR/blame-trait-error-spans-on-exprs.rs:16:13
+ |
+LL | impl<B: T2> T1 for Wrapper<B> {}
+ | -- ^^ ^^^^^^^^^^
+ | |
+ | unsatisfied trait bound introduced here
+note: required by a bound in `want`
+ --> $DIR/blame-trait-error-spans-on-exprs.rs:53:12
+ |
+LL | fn want<V: T1>(_x: V) {}
+ | ^^ required by this bound in `want`
+help: consider restricting type parameter `Q`
+ |
+LL | fn example<Q: T3>(q: Q) {
+ | ++++
+
+error[E0277]: the trait bound `Q: T3` is not satisfied
+ --> $DIR/blame-trait-error-spans-on-exprs.rs:97:74
+ |
+LL | want(Wrapper { value: GenericBurrito { spiciness: NotSpicy, filling: q } });
+ | ---- required by a bound introduced by this call ^ the trait `T3` is not implemented for `Q`
+ |
+note: required for `GenericBurrito<NotSpicy, Q>` to implement `T2`
+ --> $DIR/blame-trait-error-spans-on-exprs.rs:47:16
+ |
+LL | impl<X, Y: T3> T2 for GenericBurrito<X, Y> {}
+ | -- ^^ ^^^^^^^^^^^^^^^^^^^^
+ | |
+ | unsatisfied trait bound introduced here
+note: required for `Wrapper<GenericBurrito<NotSpicy, Q>>` to implement `T1`
+ --> $DIR/blame-trait-error-spans-on-exprs.rs:16:13
+ |
+LL | impl<B: T2> T1 for Wrapper<B> {}
+ | -- ^^ ^^^^^^^^^^
+ | |
+ | unsatisfied trait bound introduced here
+note: required by a bound in `want`
+ --> $DIR/blame-trait-error-spans-on-exprs.rs:53:12
+ |
+LL | fn want<V: T1>(_x: V) {}
+ | ^^ required by this bound in `want`
+help: consider restricting type parameter `Q`
+ |
+LL | fn example<Q: T3>(q: Q) {
+ | ++++
+
+error[E0277]: the trait bound `Q: T2` is not satisfied
+ --> $DIR/blame-trait-error-spans-on-exprs.rs:101:14
+ |
+LL | want((3, q));
+ | ---- ^ the trait `T2` is not implemented for `Q`
+ | |
+ | required by a bound introduced by this call
+ |
+note: required for `(i32, Q)` to implement `T1`
+ --> $DIR/blame-trait-error-spans-on-exprs.rs:51:20
+ |
+LL | impl<A: T2, B: T2> T1 for (A, B) {}
+ | -- ^^ ^^^^^^
+ | |
+ | unsatisfied trait bound introduced here
+note: required by a bound in `want`
+ --> $DIR/blame-trait-error-spans-on-exprs.rs:53:12
+ |
+LL | fn want<V: T1>(_x: V) {}
+ | ^^ required by this bound in `want`
+help: consider restricting type parameter `Q`
+ |
+LL | fn example<Q: T2>(q: Q) {
+ | ++++
+
+error[E0277]: the trait bound `Q: T3` is not satisfied
+ --> $DIR/blame-trait-error-spans-on-exprs.rs:105:31
+ |
+LL | want(Wrapper { value: (3, q) });
+ | ---- ^ the trait `T3` is not implemented for `Q`
+ | |
+ | required by a bound introduced by this call
+ |
+note: required for `(i32, Q)` to implement `T2`
+ --> $DIR/blame-trait-error-spans-on-exprs.rs:50:20
+ |
+LL | impl<A: T3, B: T3> T2 for (A, B) {}
+ | -- ^^ ^^^^^^
+ | |
+ | unsatisfied trait bound introduced here
+note: required for `Wrapper<(i32, Q)>` to implement `T1`
+ --> $DIR/blame-trait-error-spans-on-exprs.rs:16:13
+ |
+LL | impl<B: T2> T1 for Wrapper<B> {}
+ | -- ^^ ^^^^^^^^^^
+ | |
+ | unsatisfied trait bound introduced here
+note: required by a bound in `want`
+ --> $DIR/blame-trait-error-spans-on-exprs.rs:53:12
+ |
+LL | fn want<V: T1>(_x: V) {}
+ | ^^ required by this bound in `want`
+help: consider restricting type parameter `Q`
+ |
+LL | fn example<Q: T3>(q: Q) {
+ | ++++
+
+error[E0277]: the trait bound `Q: T3` is not satisfied
+ --> $DIR/blame-trait-error-spans-on-exprs.rs:109:15
+ |
+LL | want(((3, q), 5));
+ | ---- ^ the trait `T3` is not implemented for `Q`
+ | |
+ | required by a bound introduced by this call
+ |
+note: required for `(i32, Q)` to implement `T2`
+ --> $DIR/blame-trait-error-spans-on-exprs.rs:50:20
+ |
+LL | impl<A: T3, B: T3> T2 for (A, B) {}
+ | -- ^^ ^^^^^^
+ | |
+ | unsatisfied trait bound introduced here
+note: required for `((i32, Q), i32)` to implement `T1`
+ --> $DIR/blame-trait-error-spans-on-exprs.rs:51:20
+ |
+LL | impl<A: T2, B: T2> T1 for (A, B) {}
+ | -- ^^ ^^^^^^
+ | |
+ | unsatisfied trait bound introduced here
+note: required by a bound in `want`
+ --> $DIR/blame-trait-error-spans-on-exprs.rs:53:12
+ |
+LL | fn want<V: T1>(_x: V) {}
+ | ^^ required by this bound in `want`
+help: consider restricting type parameter `Q`
+ |
+LL | fn example<Q: T3>(q: Q) {
+ | ++++
+
+error[E0277]: the trait bound `Q: T1` is not satisfied
+ --> $DIR/blame-trait-error-spans-on-exprs.rs:112:49
+ |
+LL | want(DoubleWrapper { item: Wrapper { value: q } });
+ | ---- ^ the trait `T1` is not implemented for `Q`
+ | |
+ | required by a bound introduced by this call
+ |
+note: required for `DoubleWrapper<Q>` to implement `T1`
+ --> $DIR/blame-trait-error-spans-on-exprs.rs:72:13
+ |
+LL | impl<T: T1> T1 for DoubleWrapper<T> {}
+ | -- ^^ ^^^^^^^^^^^^^^^^
+ | |
+ | unsatisfied trait bound introduced here
+note: required by a bound in `want`
+ --> $DIR/blame-trait-error-spans-on-exprs.rs:53:12
+ |
+LL | fn want<V: T1>(_x: V) {}
+ | ^^ required by this bound in `want`
+help: consider restricting type parameter `Q`
+ |
+LL | fn example<Q: T1>(q: Q) {
+ | ++++
+
+error[E0277]: the trait bound `Q: T1` is not satisfied
+ --> $DIR/blame-trait-error-spans-on-exprs.rs:115:88
+ |
+LL | want(DoubleWrapper { item: Wrapper { value: DoubleWrapper { item: Wrapper { value: q } } } });
+ | ---- required by a bound introduced by this call ^ the trait `T1` is not implemented for `Q`
+ |
+note: required for `DoubleWrapper<Q>` to implement `T1`
+ --> $DIR/blame-trait-error-spans-on-exprs.rs:72:13
+ |
+LL | impl<T: T1> T1 for DoubleWrapper<T> {}
+ | -- ^^ ^^^^^^^^^^^^^^^^
+ | |
+ | unsatisfied trait bound introduced here
+ = note: 1 redundant requirement hidden
+ = note: required for `DoubleWrapper<DoubleWrapper<Q>>` to implement `T1`
+note: required by a bound in `want`
+ --> $DIR/blame-trait-error-spans-on-exprs.rs:53:12
+ |
+LL | fn want<V: T1>(_x: V) {}
+ | ^^ required by this bound in `want`
+help: consider restricting type parameter `Q`
+ |
+LL | fn example<Q: T1>(q: Q) {
+ | ++++
+
+error[E0277]: the trait bound `Q: T3` is not satisfied
+ --> $DIR/blame-trait-error-spans-on-exprs.rs:119:27
+ |
+LL | want(Wrapper { value: AliasBurrito { spiciness: q, filling: q } });
+ | ---- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `T3` is not implemented for `Q`
+ | |
+ | required by a bound introduced by this call
+ |
+note: required for `GenericBurrito<Q, Q>` to implement `T2`
+ --> $DIR/blame-trait-error-spans-on-exprs.rs:47:16
+ |
+LL | impl<X, Y: T3> T2 for GenericBurrito<X, Y> {}
+ | -- ^^ ^^^^^^^^^^^^^^^^^^^^
+ | |
+ | unsatisfied trait bound introduced here
+note: required for `Wrapper<GenericBurrito<Q, Q>>` to implement `T1`
+ --> $DIR/blame-trait-error-spans-on-exprs.rs:16:13
+ |
+LL | impl<B: T2> T1 for Wrapper<B> {}
+ | -- ^^ ^^^^^^^^^^
+ | |
+ | unsatisfied trait bound introduced here
+note: required by a bound in `want`
+ --> $DIR/blame-trait-error-spans-on-exprs.rs:53:12
+ |
+LL | fn want<V: T1>(_x: V) {}
+ | ^^ required by this bound in `want`
+help: consider restricting type parameter `Q`
+ |
+LL | fn example<Q: T3>(q: Q) {
+ | ++++
+
+error[E0277]: the trait bound `Q: T1` is not satisfied
+ --> $DIR/blame-trait-error-spans-on-exprs.rs:122:35
+ |
+LL | want(Two { a: Two { a: (), b: q }, b: () });
+ | ---- ^ the trait `T1` is not implemented for `Q`
+ | |
+ | required by a bound introduced by this call
+ |
+note: required for `Two<Two<(), Q>, ()>` to implement `T1`
+ --> $DIR/blame-trait-error-spans-on-exprs.rs:66:19
+ |
+LL | impl<X, Y: T1, Z> T1 for Two<Two<X, Y>, Z> {}
+ | -- ^^ ^^^^^^^^^^^^^^^^^
+ | |
+ | unsatisfied trait bound introduced here
+note: required by a bound in `want`
+ --> $DIR/blame-trait-error-spans-on-exprs.rs:53:12
+ |
+LL | fn want<V: T1>(_x: V) {}
+ | ^^ required by this bound in `want`
+help: consider restricting type parameter `Q`
+ |
+LL | fn example<Q: T1>(q: Q) {
+ | ++++
+
+error[E0277]: the trait bound `Q: T1` is not satisfied
+ --> $DIR/blame-trait-error-spans-on-exprs.rs:128:59
+ |
+LL | want(
+ | ---- required by a bound introduced by this call
+LL | Two { a: Two { a: (), b: Two { a: Two { a: (), b: q }, b: () } }, b: () },
+ | ^ the trait `T1` is not implemented for `Q`
+ |
+note: required for `Two<Two<(), Q>, ()>` to implement `T1`
+ --> $DIR/blame-trait-error-spans-on-exprs.rs:66:19
+ |
+LL | impl<X, Y: T1, Z> T1 for Two<Two<X, Y>, Z> {}
+ | -- ^^ ^^^^^^^^^^^^^^^^^
+ | |
+ | unsatisfied trait bound introduced here
+ = note: 1 redundant requirement hidden
+ = note: required for `Two<Two<(), Two<Two<(), Q>, ()>>, ()>` to implement `T1`
+note: required by a bound in `want`
+ --> $DIR/blame-trait-error-spans-on-exprs.rs:53:12
+ |
+LL | fn want<V: T1>(_x: V) {}
+ | ^^ required by this bound in `want`
+help: consider restricting type parameter `Q`
+ |
+LL | fn example<Q: T1>(q: Q) {
+ | ++++
+
+error[E0277]: the trait bound `Q: T3` is not satisfied
+ --> $DIR/blame-trait-error-spans-on-exprs.rs:133:44
+ |
+LL | want(&Burrito { spicy: false, filling: q });
+ | ---- ^ the trait `T3` is not implemented for `Q`
+ | |
+ | required by a bound introduced by this call
+ |
+note: required for `Burrito<Q>` to implement `T2`
+ --> $DIR/blame-trait-error-spans-on-exprs.rs:22:13
+ |
+LL | impl<A: T3> T2 for Burrito<A> {}
+ | -- ^^ ^^^^^^^^^^
+ | |
+ | unsatisfied trait bound introduced here
+note: required for `&Burrito<Q>` to implement `T1`
+ --> $DIR/blame-trait-error-spans-on-exprs.rs:74:17
+ |
+LL | impl<'a, T: T2> T1 for &'a T {}
+ | -- ^^ ^^^^^
+ | |
+ | unsatisfied trait bound introduced here
+note: required by a bound in `want`
+ --> $DIR/blame-trait-error-spans-on-exprs.rs:53:12
+ |
+LL | fn want<V: T1>(_x: V) {}
+ | ^^ required by this bound in `want`
+help: consider restricting type parameter `Q`
+ |
+LL | fn example<Q: T3>(q: Q) {
+ | ++++
+
+error: aborting due to 14 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/explore-issue-38412.stderr b/tests/ui/explore-issue-38412.stderr
index 08dadb4db..d8b485c9d 100644
--- a/tests/ui/explore-issue-38412.stderr
+++ b/tests/ui/explore-issue-38412.stderr
@@ -79,38 +79,38 @@ LL | r.unstable_undeclared();
= note: see issue #38412 <https://github.com/rust-lang/rust/issues/38412> for more information
= help: add `#![feature(unstable_undeclared)]` to the crate attributes to enable
-error[E0624]: associated function `pub_crate` is private
+error[E0624]: method `pub_crate` is private
--> $DIR/explore-issue-38412.rs:48:7
|
LL | r.pub_crate();
- | ^^^^^^^^^ private associated function
+ | ^^^^^^^^^ private method
|
::: $DIR/auxiliary/pub-and-stability.rs:114:9
|
LL | pub(crate) fn pub_crate(&self) -> i32 { self.d_priv }
- | ------------------------------------- private associated function defined here
+ | ------------------------------------- private method defined here
-error[E0624]: associated function `pub_mod` is private
+error[E0624]: method `pub_mod` is private
--> $DIR/explore-issue-38412.rs:49:7
|
LL | r.pub_mod();
- | ^^^^^^^ private associated function
+ | ^^^^^^^ private method
|
::: $DIR/auxiliary/pub-and-stability.rs:116:9
|
LL | pub(in m) fn pub_mod(&self) -> i32 { self.d_priv }
- | ---------------------------------- private associated function defined here
+ | ---------------------------------- private method defined here
-error[E0624]: associated function `private` is private
+error[E0624]: method `private` is private
--> $DIR/explore-issue-38412.rs:50:7
|
LL | r.private();
- | ^^^^^^^ private associated function
+ | ^^^^^^^ private method
|
::: $DIR/auxiliary/pub-and-stability.rs:118:9
|
LL | fn private(&self) -> i32 { self.d_priv }
- | ------------------------ private associated function defined here
+ | ------------------------ private method defined here
error[E0658]: use of unstable library feature 'unstable_undeclared'
--> $DIR/explore-issue-38412.rs:55:7
@@ -130,38 +130,38 @@ LL | t.unstable_undeclared();
= note: see issue #38412 <https://github.com/rust-lang/rust/issues/38412> for more information
= help: add `#![feature(unstable_undeclared)]` to the crate attributes to enable
-error[E0624]: associated function `pub_crate` is private
+error[E0624]: method `pub_crate` is private
--> $DIR/explore-issue-38412.rs:61:7
|
LL | t.pub_crate();
- | ^^^^^^^^^ private associated function
+ | ^^^^^^^^^ private method
|
::: $DIR/auxiliary/pub-and-stability.rs:129:9
|
LL | pub(crate) fn pub_crate(&self) -> i32 { self.0 }
- | ------------------------------------- private associated function defined here
+ | ------------------------------------- private method defined here
-error[E0624]: associated function `pub_mod` is private
+error[E0624]: method `pub_mod` is private
--> $DIR/explore-issue-38412.rs:62:7
|
LL | t.pub_mod();
- | ^^^^^^^ private associated function
+ | ^^^^^^^ private method
|
::: $DIR/auxiliary/pub-and-stability.rs:130:9
|
LL | pub(in m) fn pub_mod(&self) -> i32 { self.0 }
- | ---------------------------------- private associated function defined here
+ | ---------------------------------- private method defined here
-error[E0624]: associated function `private` is private
+error[E0624]: method `private` is private
--> $DIR/explore-issue-38412.rs:63:7
|
LL | t.private();
- | ^^^^^^^ private associated function
+ | ^^^^^^^ private method
|
::: $DIR/auxiliary/pub-and-stability.rs:131:9
|
LL | fn private(&self) -> i32 { self.0 }
- | ------------------------ private associated function defined here
+ | ------------------------ private method defined here
error: aborting due to 19 previous errors
diff --git a/tests/ui/expr/malformed_closure/missing_braces_around_block.fixed b/tests/ui/expr/malformed_closure/missing_braces_around_block.fixed
index c50b9a12b..a7a9db7d9 100644
--- a/tests/ui/expr/malformed_closure/missing_braces_around_block.fixed
+++ b/tests/ui/expr/malformed_closure/missing_braces_around_block.fixed
@@ -4,16 +4,23 @@
// If this recovery happens, then plenty of errors are emitted. Here, we expect
// only one error.
//
-// This is part of issue #88065:
+// This is part of the following issues:
// https://github.com/rust-lang/rust/issues/88065
+// https://github.com/rust-lang/rust/issues/107959
// run-rustfix
fn main() {
+ // Closure with multiple expressions delimited by semicolon.
let num = 5;
(1..num).reduce(|a, b| {
//~^ ERROR: closure bodies that contain statements must be surrounded by braces
println!("{}", a);
a * b
}).unwrap();
+
+ // Closure with a single expression ended by a semicolon.
+ let mut v = vec![1, 2, 3];
+ v.iter_mut().for_each(|x| {*x = *x+1;});
+ //~^ ERROR: closure bodies that contain statements must be surrounded by braces
}
diff --git a/tests/ui/expr/malformed_closure/missing_braces_around_block.rs b/tests/ui/expr/malformed_closure/missing_braces_around_block.rs
index 58c81f3a6..b5690b2ec 100644
--- a/tests/ui/expr/malformed_closure/missing_braces_around_block.rs
+++ b/tests/ui/expr/malformed_closure/missing_braces_around_block.rs
@@ -4,16 +4,23 @@
// If this recovery happens, then plenty of errors are emitted. Here, we expect
// only one error.
//
-// This is part of issue #88065:
+// This is part of the following issues:
// https://github.com/rust-lang/rust/issues/88065
+// https://github.com/rust-lang/rust/issues/107959
// run-rustfix
fn main() {
+ // Closure with multiple expressions delimited by semicolon.
let num = 5;
(1..num).reduce(|a, b|
//~^ ERROR: closure bodies that contain statements must be surrounded by braces
println!("{}", a);
a * b
).unwrap();
+
+ // Closure with a single expression ended by a semicolon.
+ let mut v = vec![1, 2, 3];
+ v.iter_mut().for_each(|x|*x = *x+1;);
+ //~^ ERROR: closure bodies that contain statements must be surrounded by braces
}
diff --git a/tests/ui/expr/malformed_closure/missing_braces_around_block.stderr b/tests/ui/expr/malformed_closure/missing_braces_around_block.stderr
index dac9a8cfc..039eef909 100644
--- a/tests/ui/expr/malformed_closure/missing_braces_around_block.stderr
+++ b/tests/ui/expr/malformed_closure/missing_braces_around_block.stderr
@@ -1,5 +1,5 @@
error: closure bodies that contain statements must be surrounded by braces
- --> $DIR/missing_braces_around_block.rs:14:26
+ --> $DIR/missing_braces_around_block.rs:16:26
|
LL | (1..num).reduce(|a, b|
| ^
@@ -8,14 +8,14 @@ LL | ).unwrap();
| ^
|
note: statement found outside of a block
- --> $DIR/missing_braces_around_block.rs:16:26
+ --> $DIR/missing_braces_around_block.rs:18: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
+ --> $DIR/missing_braces_around_block.rs:16:21
|
LL | (1..num).reduce(|a, b|
| _____________________^
@@ -34,5 +34,30 @@ LL | a * b
LL ~ }).unwrap();
|
-error: aborting due to previous error
+error: closure bodies that contain statements must be surrounded by braces
+ --> $DIR/missing_braces_around_block.rs:24:29
+ |
+LL | v.iter_mut().for_each(|x|*x = *x+1;);
+ | ^ ^
+ |
+note: statement found outside of a block
+ --> $DIR/missing_braces_around_block.rs:24:39
+ |
+LL | v.iter_mut().for_each(|x|*x = *x+1;);
+ | ---------^ 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:24:27
+ |
+LL | v.iter_mut().for_each(|x|*x = *x+1;);
+ | ^^^^^^^^^^^^ - ...but likely you meant the closure to end here
+ | |
+ | this is the parsed closure...
+help: try adding braces
+ |
+LL | v.iter_mut().for_each(|x| {*x = *x+1;});
+ | + +
+
+error: aborting due to 2 previous errors
diff --git a/tests/ui/extenv/extenv-not-defined-default.rs b/tests/ui/extenv/extenv-not-defined-default.rs
index 30a06a254..1fb046c78 100644
--- a/tests/ui/extenv/extenv-not-defined-default.rs
+++ b/tests/ui/extenv/extenv-not-defined-default.rs
@@ -1,4 +1,4 @@
fn main() {
- env!("__HOPEFULLY_NOT_DEFINED__");
- //~^ ERROR: environment variable `__HOPEFULLY_NOT_DEFINED__` not defined
+ env!("CARGO__HOPEFULLY_NOT_DEFINED__");
+ //~^ ERROR: environment variable `CARGO__HOPEFULLY_NOT_DEFINED__` not defined
}
diff --git a/tests/ui/extenv/extenv-not-defined-default.stderr b/tests/ui/extenv/extenv-not-defined-default.stderr
index 884875dca..e3dce0005 100644
--- a/tests/ui/extenv/extenv-not-defined-default.stderr
+++ b/tests/ui/extenv/extenv-not-defined-default.stderr
@@ -1,9 +1,10 @@
-error: environment variable `__HOPEFULLY_NOT_DEFINED__` not defined
+error: environment variable `CARGO__HOPEFULLY_NOT_DEFINED__` not defined at compile time
--> $DIR/extenv-not-defined-default.rs:2:5
|
-LL | env!("__HOPEFULLY_NOT_DEFINED__");
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | env!("CARGO__HOPEFULLY_NOT_DEFINED__");
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
+ = help: Cargo sets build script variables at run time. Use `std::env::var("CARGO__HOPEFULLY_NOT_DEFINED__")` instead
= note: this error originates in the macro `env` (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to previous error
diff --git a/tests/ui/extenv/issue-55897.stderr b/tests/ui/extenv/issue-55897.stderr
index 92e8a44b5..5752a965e 100644
--- a/tests/ui/extenv/issue-55897.stderr
+++ b/tests/ui/extenv/issue-55897.stderr
@@ -1,9 +1,10 @@
-error: environment variable `NON_EXISTENT` not defined
+error: environment variable `NON_EXISTENT` not defined at compile time
--> $DIR/issue-55897.rs:11:22
|
LL | include!(concat!(env!("NON_EXISTENT"), "/data.rs"));
| ^^^^^^^^^^^^^^^^^^^^
|
+ = help: Use `std::env::var("NON_EXISTENT")` to read the variable at run time
= note: this error originates in the macro `env` (in Nightly builds, run with -Z macro-backtrace for more info)
error: suffixes on string literals are invalid
diff --git a/tests/ui/extern/extern-types-distinct-types.stderr b/tests/ui/extern/extern-types-distinct-types.stderr
index ca25aa64e..3e6dc5cef 100644
--- a/tests/ui/extern/extern-types-distinct-types.stderr
+++ b/tests/ui/extern/extern-types-distinct-types.stderr
@@ -9,7 +9,7 @@ LL | type B;
LL | fn foo(r: &A) -> &B {
| -- expected `&B` because of return type
LL | r
- | ^ expected extern type `B`, found extern type `A`
+ | ^ expected `&B`, found `&A`
|
= note: expected reference `&B`
found reference `&A`
diff --git a/tests/ui/feature-gates/feature-gate-associated_type_bounds.rs b/tests/ui/feature-gates/feature-gate-associated_type_bounds.rs
index 4e0203274..49fb10e60 100644
--- a/tests/ui/feature-gates/feature-gate-associated_type_bounds.rs
+++ b/tests/ui/feature-gates/feature-gate-associated_type_bounds.rs
@@ -1,6 +1,3 @@
-// compile-flags: -Zsave-analysis
-// This is also a regression test for #69415 and the above flag is needed.
-
use std::mem::ManuallyDrop;
trait Tr1 { type As1: Copy; }
diff --git a/tests/ui/feature-gates/feature-gate-associated_type_bounds.stderr b/tests/ui/feature-gates/feature-gate-associated_type_bounds.stderr
index 5be1d97a0..4233a8af9 100644
--- a/tests/ui/feature-gates/feature-gate-associated_type_bounds.stderr
+++ b/tests/ui/feature-gates/feature-gate-associated_type_bounds.stderr
@@ -1,5 +1,5 @@
error[E0658]: associated type bounds are unstable
- --> $DIR/feature-gate-associated_type_bounds.rs:15:22
+ --> $DIR/feature-gate-associated_type_bounds.rs:12:22
|
LL | type A: Iterator<Item: Copy>;
| ^^^^^^^^^^
@@ -8,7 +8,7 @@ LL | type A: Iterator<Item: Copy>;
= help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable
error[E0658]: associated type bounds are unstable
- --> $DIR/feature-gate-associated_type_bounds.rs:19:22
+ --> $DIR/feature-gate-associated_type_bounds.rs:16:22
|
LL | type B: Iterator<Item: 'static>;
| ^^^^^^^^^^^^^
@@ -17,7 +17,7 @@ LL | type B: Iterator<Item: 'static>;
= help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable
error[E0658]: associated type bounds are unstable
- --> $DIR/feature-gate-associated_type_bounds.rs:23:20
+ --> $DIR/feature-gate-associated_type_bounds.rs:20:20
|
LL | struct _St1<T: Tr1<As1: Tr2>> {
| ^^^^^^^^
@@ -26,7 +26,7 @@ LL | struct _St1<T: Tr1<As1: Tr2>> {
= help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable
error[E0658]: associated type bounds are unstable
- --> $DIR/feature-gate-associated_type_bounds.rs:30:18
+ --> $DIR/feature-gate-associated_type_bounds.rs:27:18
|
LL | enum _En1<T: Tr1<As1: Tr2>> {
| ^^^^^^^^
@@ -35,7 +35,7 @@ LL | enum _En1<T: Tr1<As1: Tr2>> {
= help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable
error[E0658]: associated type bounds are unstable
- --> $DIR/feature-gate-associated_type_bounds.rs:37:19
+ --> $DIR/feature-gate-associated_type_bounds.rs:34:19
|
LL | union _Un1<T: Tr1<As1: Tr2>> {
| ^^^^^^^^
@@ -44,7 +44,7 @@ LL | union _Un1<T: Tr1<As1: Tr2>> {
= help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable
error[E0658]: associated type bounds are unstable
- --> $DIR/feature-gate-associated_type_bounds.rs:44:37
+ --> $DIR/feature-gate-associated_type_bounds.rs:41:37
|
LL | type _TaWhere1<T> where T: Iterator<Item: Copy> = T;
| ^^^^^^^^^^
@@ -53,7 +53,7 @@ LL | type _TaWhere1<T> where T: Iterator<Item: Copy> = T;
= help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable
error[E0658]: associated type bounds are unstable
- --> $DIR/feature-gate-associated_type_bounds.rs:47:22
+ --> $DIR/feature-gate-associated_type_bounds.rs:44:22
|
LL | fn _apit(_: impl Tr1<As1: Copy>) {}
| ^^^^^^^^^
@@ -62,7 +62,7 @@ LL | fn _apit(_: impl Tr1<As1: Copy>) {}
= help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable
error[E0658]: associated type bounds are unstable
- --> $DIR/feature-gate-associated_type_bounds.rs:49:26
+ --> $DIR/feature-gate-associated_type_bounds.rs:46:26
|
LL | fn _apit_dyn(_: &dyn Tr1<As1: Copy>) {}
| ^^^^^^^^^
@@ -71,7 +71,7 @@ LL | fn _apit_dyn(_: &dyn Tr1<As1: Copy>) {}
= help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable
error[E0658]: associated type bounds are unstable
- --> $DIR/feature-gate-associated_type_bounds.rs:52:24
+ --> $DIR/feature-gate-associated_type_bounds.rs:49:24
|
LL | fn _rpit() -> impl Tr1<As1: Copy> { S1 }
| ^^^^^^^^^
@@ -80,7 +80,7 @@ LL | fn _rpit() -> impl Tr1<As1: Copy> { S1 }
= help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable
error[E0658]: associated type bounds are unstable
- --> $DIR/feature-gate-associated_type_bounds.rs:55:31
+ --> $DIR/feature-gate-associated_type_bounds.rs:52:31
|
LL | fn _rpit_dyn() -> Box<dyn Tr1<As1: Copy>> { Box::new(S1) }
| ^^^^^^^^^
@@ -89,7 +89,7 @@ LL | fn _rpit_dyn() -> Box<dyn Tr1<As1: Copy>> { Box::new(S1) }
= help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable
error[E0658]: associated type bounds are unstable
- --> $DIR/feature-gate-associated_type_bounds.rs:58:23
+ --> $DIR/feature-gate-associated_type_bounds.rs:55:23
|
LL | const _cdef: impl Tr1<As1: Copy> = S1;
| ^^^^^^^^^
@@ -98,7 +98,7 @@ LL | const _cdef: impl Tr1<As1: Copy> = S1;
= help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable
error[E0658]: associated type bounds are unstable
- --> $DIR/feature-gate-associated_type_bounds.rs:64:24
+ --> $DIR/feature-gate-associated_type_bounds.rs:61:24
|
LL | static _sdef: impl Tr1<As1: Copy> = S1;
| ^^^^^^^^^
@@ -107,7 +107,7 @@ LL | static _sdef: impl Tr1<As1: Copy> = S1;
= help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable
error[E0658]: associated type bounds are unstable
- --> $DIR/feature-gate-associated_type_bounds.rs:71:21
+ --> $DIR/feature-gate-associated_type_bounds.rs:68:21
|
LL | let _: impl Tr1<As1: Copy> = S1;
| ^^^^^^^^^
@@ -115,26 +115,26 @@ LL | let _: impl Tr1<As1: Copy> = S1;
= note: see issue #52662 <https://github.com/rust-lang/rust/issues/52662> for more information
= help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable
-error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in type
- --> $DIR/feature-gate-associated_type_bounds.rs:58:14
+error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in const types
+ --> $DIR/feature-gate-associated_type_bounds.rs:55:14
|
LL | const _cdef: impl Tr1<As1: Copy> = S1;
| ^^^^^^^^^^^^^^^^^^^
-error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in type
- --> $DIR/feature-gate-associated_type_bounds.rs:64:15
+error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in const types
+ --> $DIR/feature-gate-associated_type_bounds.rs:61:15
|
LL | static _sdef: impl Tr1<As1: Copy> = S1;
| ^^^^^^^^^^^^^^^^^^^
-error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in variable binding
- --> $DIR/feature-gate-associated_type_bounds.rs:71:12
+error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in variable bindings
+ --> $DIR/feature-gate-associated_type_bounds.rs:68:12
|
LL | let _: impl Tr1<As1: Copy> = S1;
| ^^^^^^^^^^^^^^^^^^^
error[E0277]: the trait bound `<<Self as _Tr3>::A as Iterator>::Item: Copy` is not satisfied
- --> $DIR/feature-gate-associated_type_bounds.rs:15:28
+ --> $DIR/feature-gate-associated_type_bounds.rs:12:28
|
LL | type A: Iterator<Item: Copy>;
| ^^^^ the trait `Copy` is not implemented for `<<Self as _Tr3>::A as Iterator>::Item`
diff --git a/tests/ui/feature-gates/feature-gate-dispatch-from-dyn-cell.rs b/tests/ui/feature-gates/feature-gate-dispatch-from-dyn-cell.rs
new file mode 100644
index 000000000..83366ea02
--- /dev/null
+++ b/tests/ui/feature-gates/feature-gate-dispatch-from-dyn-cell.rs
@@ -0,0 +1,9 @@
+// Check that even though Cell: DispatchFromDyn it remains an invalid self parameter type
+
+use std::cell::Cell;
+
+trait Trait{
+ fn cell(self: Cell<&Self>); //~ ERROR invalid `self` parameter type: Cell<&Self>
+}
+
+fn main() {}
diff --git a/tests/ui/feature-gates/feature-gate-dispatch-from-dyn-cell.stderr b/tests/ui/feature-gates/feature-gate-dispatch-from-dyn-cell.stderr
new file mode 100644
index 000000000..ce06ce916
--- /dev/null
+++ b/tests/ui/feature-gates/feature-gate-dispatch-from-dyn-cell.stderr
@@ -0,0 +1,12 @@
+error[E0307]: invalid `self` parameter type: Cell<&Self>
+ --> $DIR/feature-gate-dispatch-from-dyn-cell.rs:6:19
+ |
+LL | fn cell(self: Cell<&Self>);
+ | ^^^^^^^^^^^
+ |
+ = note: type of `self` must be `Self` or a type that dereferences to it
+ = help: consider changing to `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`)
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0307`.
diff --git a/tests/ui/feature-gates/feature-gate-dispatch-from-dyn-missing-impl.rs b/tests/ui/feature-gates/feature-gate-dispatch-from-dyn-missing-impl.rs
new file mode 100644
index 000000000..23857cbac
--- /dev/null
+++ b/tests/ui/feature-gates/feature-gate-dispatch-from-dyn-missing-impl.rs
@@ -0,0 +1,35 @@
+// Check that a self parameter type requires a DispatchFromDyn impl to be object safe
+
+#![feature(arbitrary_self_types, unsize, coerce_unsized)]
+
+use std::{
+ marker::Unsize,
+ ops::{CoerceUnsized, Deref},
+};
+
+struct Ptr<T: ?Sized>(Box<T>);
+
+impl<T: ?Sized> Deref for Ptr<T> {
+ type Target = T;
+
+ fn deref(&self) -> &T {
+ &*self.0
+ }
+}
+
+impl<T: Unsize<U> + ?Sized, U: ?Sized> CoerceUnsized<Ptr<U>> for Ptr<T> {}
+// Because this impl is missing the coercion below fails.
+// impl<T: Unsize<U> + ?Sized, U: ?Sized> DispatchFromDyn<Ptr<U>> for Ptr<T> {}
+
+trait Trait {
+ fn ptr(self: Ptr<Self>);
+}
+impl Trait for i32 {
+ fn ptr(self: Ptr<Self>) {}
+}
+
+fn main() {
+ Ptr(Box::new(4)) as Ptr<dyn Trait>;
+ //~^ ERROR the trait `Trait` cannot be made into an object
+ //~^^ ERROR the trait `Trait` cannot be made into an object
+}
diff --git a/tests/ui/feature-gates/feature-gate-dispatch-from-dyn-missing-impl.stderr b/tests/ui/feature-gates/feature-gate-dispatch-from-dyn-missing-impl.stderr
new file mode 100644
index 000000000..d81eade8e
--- /dev/null
+++ b/tests/ui/feature-gates/feature-gate-dispatch-from-dyn-missing-impl.stderr
@@ -0,0 +1,45 @@
+error[E0038]: the trait `Trait` cannot be made into an object
+ --> $DIR/feature-gate-dispatch-from-dyn-missing-impl.rs:32:25
+ |
+LL | fn ptr(self: Ptr<Self>);
+ | --------- help: consider changing method `ptr`'s `self` parameter to be `&self`: `&Self`
+...
+LL | Ptr(Box::new(4)) as Ptr<dyn Trait>;
+ | ^^^^^^^^^^^^^^ `Trait` cannot be made into an object
+ |
+note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+ --> $DIR/feature-gate-dispatch-from-dyn-missing-impl.rs:25:18
+ |
+LL | trait Trait {
+ | ----- this trait cannot be made into an object...
+LL | fn ptr(self: Ptr<Self>);
+ | ^^^^^^^^^ ...because method `ptr`'s `self` parameter cannot be dispatched on
+
+error[E0038]: the trait `Trait` cannot be made into an object
+ --> $DIR/feature-gate-dispatch-from-dyn-missing-impl.rs:32:5
+ |
+LL | fn ptr(self: Ptr<Self>);
+ | --------- help: consider changing method `ptr`'s `self` parameter to be `&self`: `&Self`
+...
+LL | Ptr(Box::new(4)) as Ptr<dyn Trait>;
+ | ^^^^^^^^^^^^^^^^ `Trait` cannot be made into an object
+ |
+note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+ --> $DIR/feature-gate-dispatch-from-dyn-missing-impl.rs:25:18
+ |
+LL | trait Trait {
+ | ----- this trait cannot be made into an object...
+LL | fn ptr(self: Ptr<Self>);
+ | ^^^^^^^^^ ...because method `ptr`'s `self` parameter cannot be dispatched on
+note: required for `Ptr<{integer}>` to implement `CoerceUnsized<Ptr<dyn Trait>>`
+ --> $DIR/feature-gate-dispatch-from-dyn-missing-impl.rs:20:40
+ |
+LL | impl<T: Unsize<U> + ?Sized, U: ?Sized> CoerceUnsized<Ptr<U>> for Ptr<T> {}
+ | --------- ^^^^^^^^^^^^^^^^^^^^^ ^^^^^^
+ | |
+ | unsatisfied trait bound introduced here
+ = note: required by cast to type `Ptr<dyn Trait>`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0038`.
diff --git a/tests/ui/feature-gates/feature-gate-impl_trait_in_fn_trait_return.stderr b/tests/ui/feature-gates/feature-gate-impl_trait_in_fn_trait_return.stderr
index 760dcb615..c8c3e13d7 100644
--- a/tests/ui/feature-gates/feature-gate-impl_trait_in_fn_trait_return.stderr
+++ b/tests/ui/feature-gates/feature-gate-impl_trait_in_fn_trait_return.stderr
@@ -1,4 +1,4 @@
-error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `Fn` trait return
+error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `Fn` trait return types
--> $DIR/feature-gate-impl_trait_in_fn_trait_return.rs:1:24
|
LL | fn f() -> impl Fn() -> impl Sized { || () }
@@ -7,7 +7,7 @@ LL | fn f() -> impl Fn() -> impl Sized { || () }
= note: see issue #99697 <https://github.com/rust-lang/rust/issues/99697> for more information
= help: add `#![feature(impl_trait_in_fn_trait_return)]` to the crate attributes to enable
-error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `Fn` trait return
+error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `Fn` trait return types
--> $DIR/feature-gate-impl_trait_in_fn_trait_return.rs:3:32
|
LL | fn g() -> &'static dyn Fn() -> impl Sized { &|| () }
diff --git a/tests/ui/feature-gates/feature-gate-multiple_supertrait_upcastable.rs b/tests/ui/feature-gates/feature-gate-multiple_supertrait_upcastable.rs
new file mode 100644
index 000000000..0467dea62
--- /dev/null
+++ b/tests/ui/feature-gates/feature-gate-multiple_supertrait_upcastable.rs
@@ -0,0 +1,12 @@
+// check-pass
+
+#![deny(multiple_supertrait_upcastable)]
+//~^ WARNING unknown lint: `multiple_supertrait_upcastable`
+//~| WARNING unknown lint: `multiple_supertrait_upcastable`
+//~| WARNING unknown lint: `multiple_supertrait_upcastable`
+#![warn(multiple_supertrait_upcastable)]
+//~^ WARNING unknown lint: `multiple_supertrait_upcastable`
+//~| WARNING unknown lint: `multiple_supertrait_upcastable`
+//~| WARNING unknown lint: `multiple_supertrait_upcastable`
+
+fn main() {}
diff --git a/tests/ui/feature-gates/feature-gate-multiple_supertrait_upcastable.stderr b/tests/ui/feature-gates/feature-gate-multiple_supertrait_upcastable.stderr
new file mode 100644
index 000000000..1f725f354
--- /dev/null
+++ b/tests/ui/feature-gates/feature-gate-multiple_supertrait_upcastable.stderr
@@ -0,0 +1,57 @@
+warning: unknown lint: `multiple_supertrait_upcastable`
+ --> $DIR/feature-gate-multiple_supertrait_upcastable.rs:3:1
+ |
+LL | #![deny(multiple_supertrait_upcastable)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: the `multiple_supertrait_upcastable` lint is unstable
+ = help: add `#![feature(multiple_supertrait_upcastable)]` to the crate attributes to enable
+ = note: `#[warn(unknown_lints)]` on by default
+
+warning: unknown lint: `multiple_supertrait_upcastable`
+ --> $DIR/feature-gate-multiple_supertrait_upcastable.rs:7:1
+ |
+LL | #![warn(multiple_supertrait_upcastable)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: the `multiple_supertrait_upcastable` lint is unstable
+ = help: add `#![feature(multiple_supertrait_upcastable)]` to the crate attributes to enable
+
+warning: unknown lint: `multiple_supertrait_upcastable`
+ --> $DIR/feature-gate-multiple_supertrait_upcastable.rs:3:1
+ |
+LL | #![deny(multiple_supertrait_upcastable)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: the `multiple_supertrait_upcastable` lint is unstable
+ = help: add `#![feature(multiple_supertrait_upcastable)]` to the crate attributes to enable
+
+warning: unknown lint: `multiple_supertrait_upcastable`
+ --> $DIR/feature-gate-multiple_supertrait_upcastable.rs:7:1
+ |
+LL | #![warn(multiple_supertrait_upcastable)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: the `multiple_supertrait_upcastable` lint is unstable
+ = help: add `#![feature(multiple_supertrait_upcastable)]` to the crate attributes to enable
+
+warning: unknown lint: `multiple_supertrait_upcastable`
+ --> $DIR/feature-gate-multiple_supertrait_upcastable.rs:3:1
+ |
+LL | #![deny(multiple_supertrait_upcastable)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: the `multiple_supertrait_upcastable` lint is unstable
+ = help: add `#![feature(multiple_supertrait_upcastable)]` to the crate attributes to enable
+
+warning: unknown lint: `multiple_supertrait_upcastable`
+ --> $DIR/feature-gate-multiple_supertrait_upcastable.rs:7:1
+ |
+LL | #![warn(multiple_supertrait_upcastable)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: the `multiple_supertrait_upcastable` lint is unstable
+ = help: add `#![feature(multiple_supertrait_upcastable)]` to the crate attributes to enable
+
+warning: 6 warnings emitted
+
diff --git a/tests/ui/feature-gates/feature-gate-non_lifetime_binders.rs b/tests/ui/feature-gates/feature-gate-non_lifetime_binders.rs
new file mode 100644
index 000000000..221e9133f
--- /dev/null
+++ b/tests/ui/feature-gates/feature-gate-non_lifetime_binders.rs
@@ -0,0 +1,4 @@
+fn foo() where for<T> T:, {}
+//~^ ERROR only lifetime parameters can be used in this context
+
+fn main() {}
diff --git a/tests/ui/feature-gates/feature-gate-non_lifetime_binders.stderr b/tests/ui/feature-gates/feature-gate-non_lifetime_binders.stderr
new file mode 100644
index 000000000..01c8ee30c
--- /dev/null
+++ b/tests/ui/feature-gates/feature-gate-non_lifetime_binders.stderr
@@ -0,0 +1,12 @@
+error[E0658]: only lifetime parameters can be used in this context
+ --> $DIR/feature-gate-non_lifetime_binders.rs:1:20
+ |
+LL | fn foo() where for<T> T:, {}
+ | ^
+ |
+ = note: see issue #108185 <https://github.com/rust-lang/rust/issues/108185> for more information
+ = help: add `#![feature(non_lifetime_binders)]` 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/tests/ui/feature-gates/feature-gate-return_position_impl_trait_in_trait.stderr b/tests/ui/feature-gates/feature-gate-return_position_impl_trait_in_trait.stderr
index aeabed4a6..0082b6faf 100644
--- a/tests/ui/feature-gates/feature-gate-return_position_impl_trait_in_trait.stderr
+++ b/tests/ui/feature-gates/feature-gate-return_position_impl_trait_in_trait.stderr
@@ -1,4 +1,4 @@
-error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in trait method return
+error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in trait method return types
--> $DIR/feature-gate-return_position_impl_trait_in_trait.rs:8:17
|
LL | fn bar() -> impl Sized;
@@ -7,7 +7,7 @@ LL | fn bar() -> impl Sized;
= note: see issue #91611 <https://github.com/rust-lang/rust/issues/91611> for more information
= help: add `#![feature(return_position_impl_trait_in_trait)]` to the crate attributes to enable
-error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in trait method return
+error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in trait method return types
--> $DIR/feature-gate-return_position_impl_trait_in_trait.rs:9:21
|
LL | fn baz() -> Box<impl std::fmt::Display>;
@@ -16,7 +16,7 @@ LL | fn baz() -> Box<impl std::fmt::Display>;
= note: see issue #91611 <https://github.com/rust-lang/rust/issues/91611> for more information
= help: add `#![feature(return_position_impl_trait_in_trait)]` to the crate attributes to enable
-error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in trait method return
+error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in trait method return types
--> $DIR/feature-gate-return_position_impl_trait_in_trait.rs:15:23
|
LL | async fn bar() -> impl Sized;
diff --git a/tests/ui/feature-gates/feature-gate-trivial_bounds.stderr b/tests/ui/feature-gates/feature-gate-trivial_bounds.stderr
index 1b87ebd9f..d2ad372df 100644
--- a/tests/ui/feature-gates/feature-gate-trivial_bounds.stderr
+++ b/tests/ui/feature-gates/feature-gate-trivial_bounds.stderr
@@ -95,7 +95,7 @@ LL | fn unsized_local() where Dst<dyn A>: Sized {
| ^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
|
= help: within `Dst<(dyn A + 'static)>`, the trait `Sized` is not implemented for `(dyn A + 'static)`
-note: required because it appears within the type `Dst<(dyn A + 'static)>`
+note: required because it appears within the type `Dst<dyn A>`
--> $DIR/feature-gate-trivial_bounds.rs:48:8
|
LL | struct Dst<X: ?Sized> {
diff --git a/tests/ui/ffi_const.rs b/tests/ui/ffi_const.rs
index 7aeb5a49a..aa20a4d4c 100644
--- a/tests/ui/ffi_const.rs
+++ b/tests/ui/ffi_const.rs
@@ -3,3 +3,13 @@
#[ffi_const] //~ ERROR `#[ffi_const]` may only be used on foreign functions
pub fn foo() {}
+
+#[ffi_const] //~ ERROR `#[ffi_const]` may only be used on foreign functions
+macro_rules! bar {
+ () => ()
+}
+
+extern "C" {
+ #[ffi_const] //~ ERROR `#[ffi_const]` may only be used on foreign functions
+ static INT: i32;
+}
diff --git a/tests/ui/ffi_const.stderr b/tests/ui/ffi_const.stderr
index bc3c12eaf..394b98f89 100644
--- a/tests/ui/ffi_const.stderr
+++ b/tests/ui/ffi_const.stderr
@@ -4,6 +4,18 @@ error[E0756]: `#[ffi_const]` may only be used on foreign functions
LL | #[ffi_const]
| ^^^^^^^^^^^^
-error: aborting due to previous error
+error[E0756]: `#[ffi_const]` may only be used on foreign functions
+ --> $DIR/ffi_const.rs:7:1
+ |
+LL | #[ffi_const]
+ | ^^^^^^^^^^^^
+
+error[E0756]: `#[ffi_const]` may only be used on foreign functions
+ --> $DIR/ffi_const.rs:13:5
+ |
+LL | #[ffi_const]
+ | ^^^^^^^^^^^^
+
+error: aborting due to 3 previous errors
For more information about this error, try `rustc --explain E0756`.
diff --git a/tests/ui/ffi_pure.rs b/tests/ui/ffi_pure.rs
index c37d34c87..6d2f3a614 100644
--- a/tests/ui/ffi_pure.rs
+++ b/tests/ui/ffi_pure.rs
@@ -3,3 +3,13 @@
#[ffi_pure] //~ ERROR `#[ffi_pure]` may only be used on foreign functions
pub fn foo() {}
+
+#[ffi_pure] //~ ERROR `#[ffi_pure]` may only be used on foreign functions
+macro_rules! bar {
+ () => ()
+}
+
+extern "C" {
+ #[ffi_pure] //~ ERROR `#[ffi_pure]` may only be used on foreign functions
+ static INT: i32;
+}
diff --git a/tests/ui/ffi_pure.stderr b/tests/ui/ffi_pure.stderr
index bc911c85d..8b61a4b60 100644
--- a/tests/ui/ffi_pure.stderr
+++ b/tests/ui/ffi_pure.stderr
@@ -4,6 +4,18 @@ error[E0755]: `#[ffi_pure]` may only be used on foreign functions
LL | #[ffi_pure]
| ^^^^^^^^^^^
-error: aborting due to previous error
+error[E0755]: `#[ffi_pure]` may only be used on foreign functions
+ --> $DIR/ffi_pure.rs:7:1
+ |
+LL | #[ffi_pure]
+ | ^^^^^^^^^^^
+
+error[E0755]: `#[ffi_pure]` may only be used on foreign functions
+ --> $DIR/ffi_pure.rs:13:5
+ |
+LL | #[ffi_pure]
+ | ^^^^^^^^^^^
+
+error: aborting due to 3 previous errors
For more information about this error, try `rustc --explain E0755`.
diff --git a/tests/ui/ffi_returns_twice.rs b/tests/ui/ffi_returns_twice.rs
index 845e18df1..8195d0e48 100644
--- a/tests/ui/ffi_returns_twice.rs
+++ b/tests/ui/ffi_returns_twice.rs
@@ -3,3 +3,13 @@
#[ffi_returns_twice] //~ ERROR `#[ffi_returns_twice]` may only be used on foreign functions
pub fn foo() {}
+
+#[ffi_returns_twice] //~ ERROR `#[ffi_returns_twice]` may only be used on foreign functions
+macro_rules! bar {
+ () => ()
+}
+
+extern "C" {
+ #[ffi_returns_twice] //~ ERROR `#[ffi_returns_twice]` may only be used on foreign functions
+ static INT: i32;
+}
diff --git a/tests/ui/ffi_returns_twice.stderr b/tests/ui/ffi_returns_twice.stderr
index 2b7f5694f..0abe7613f 100644
--- a/tests/ui/ffi_returns_twice.stderr
+++ b/tests/ui/ffi_returns_twice.stderr
@@ -4,6 +4,18 @@ error[E0724]: `#[ffi_returns_twice]` may only be used on foreign functions
LL | #[ffi_returns_twice]
| ^^^^^^^^^^^^^^^^^^^^
-error: aborting due to previous error
+error[E0724]: `#[ffi_returns_twice]` may only be used on foreign functions
+ --> $DIR/ffi_returns_twice.rs:7:1
+ |
+LL | #[ffi_returns_twice]
+ | ^^^^^^^^^^^^^^^^^^^^
+
+error[E0724]: `#[ffi_returns_twice]` may only be used on foreign functions
+ --> $DIR/ffi_returns_twice.rs:13:5
+ |
+LL | #[ffi_returns_twice]
+ | ^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 3 previous errors
For more information about this error, try `rustc --explain E0724`.
diff --git a/tests/ui/fmt/format-string-wrong-order.rs b/tests/ui/fmt/format-string-wrong-order.rs
new file mode 100644
index 000000000..0bad54023
--- /dev/null
+++ b/tests/ui/fmt/format-string-wrong-order.rs
@@ -0,0 +1,15 @@
+fn main() {
+ let bar = 3;
+ format!("{?:}", bar);
+ //~^ ERROR invalid format string: expected format parameter to occur after `:`
+ format!("{?:bar}");
+ //~^ ERROR invalid format string: expected format parameter to occur after `:`
+ format!("{?:?}", bar);
+ //~^ ERROR invalid format string: expected format parameter to occur after `:`
+ format!("{??}", bar);
+ //~^ ERROR invalid format string: expected `'}'`, found `'?'`
+ format!("{?;bar}");
+ //~^ ERROR invalid format string: expected `'}'`, found `'?'`
+ format!("{?:#?}", bar);
+ //~^ ERROR invalid format string: expected format parameter to occur after `:`
+}
diff --git a/tests/ui/fmt/format-string-wrong-order.stderr b/tests/ui/fmt/format-string-wrong-order.stderr
new file mode 100644
index 000000000..461af354a
--- /dev/null
+++ b/tests/ui/fmt/format-string-wrong-order.stderr
@@ -0,0 +1,54 @@
+error: invalid format string: expected format parameter to occur after `:`
+ --> $DIR/format-string-wrong-order.rs:3:15
+ |
+LL | format!("{?:}", bar);
+ | ^ expected `?` to occur after `:` in format string
+ |
+ = note: `?` comes after `:`, try `:?` instead
+
+error: invalid format string: expected format parameter to occur after `:`
+ --> $DIR/format-string-wrong-order.rs:5:15
+ |
+LL | format!("{?:bar}");
+ | ^ expected `?` to occur after `:` in format string
+ |
+ = note: `?` comes after `:`, try `bar:?` instead
+
+error: invalid format string: expected format parameter to occur after `:`
+ --> $DIR/format-string-wrong-order.rs:7:15
+ |
+LL | format!("{?:?}", bar);
+ | ^ expected `?` to occur after `:` in format string
+ |
+ = note: `?` comes after `:`, try `:?` instead
+
+error: invalid format string: expected `'}'`, found `'?'`
+ --> $DIR/format-string-wrong-order.rs:9:15
+ |
+LL | format!("{??}", bar);
+ | -^ expected `}` in format string
+ | |
+ | because of this opening brace
+ |
+ = note: if you intended to print `{`, you can escape it using `{{`
+
+error: invalid format string: expected `'}'`, found `'?'`
+ --> $DIR/format-string-wrong-order.rs:11:15
+ |
+LL | format!("{?;bar}");
+ | -^ expected `}` in format string
+ | |
+ | because of this opening brace
+ |
+ = note: if you intended to print `{`, you can escape it using `{{`
+
+error: invalid format string: expected format parameter to occur after `:`
+ --> $DIR/format-string-wrong-order.rs:13:15
+ |
+LL | format!("{?:#?}", bar);
+ | ^ expected `?` to occur after `:` in format string
+ |
+ = note: `?` comes after `:`, try `:?` instead
+
+error: aborting due to 6 previous errors
+
diff --git a/tests/ui/fmt/ifmt-bad-arg.stderr b/tests/ui/fmt/ifmt-bad-arg.stderr
index c2619d6df..d716bbe51 100644
--- a/tests/ui/fmt/ifmt-bad-arg.stderr
+++ b/tests/ui/fmt/ifmt-bad-arg.stderr
@@ -302,7 +302,7 @@ error[E0308]: mismatched types
LL | println!("{} {:.*} {}", 1, 3.2, 4);
| ^^^
| |
- | expected `usize`, found floating-point number
+ | expected `&usize`, found `&{float}`
| arguments to this function are incorrect
|
= note: expected reference `&usize`
@@ -317,7 +317,7 @@ error[E0308]: mismatched types
LL | println!("{} {:07$.*} {}", 1, 3.2, 4);
| ^^^
| |
- | expected `usize`, found floating-point number
+ | expected `&usize`, found `&{float}`
| arguments to this function are incorrect
|
= note: expected reference `&usize`
diff --git a/tests/ui/fmt/ifmt-unimpl.stderr b/tests/ui/fmt/ifmt-unimpl.stderr
index be321c3c5..3480a2ec8 100644
--- a/tests/ui/fmt/ifmt-unimpl.stderr
+++ b/tests/ui/fmt/ifmt-unimpl.stderr
@@ -15,7 +15,7 @@ LL | format!("{:X}", "3");
NonZeroIsize
and 21 others
= note: required for `&str` to implement `UpperHex`
-note: required by a bound in `ArgumentV1::<'a>::new_upper_hex`
+note: required by a bound in `core::fmt::ArgumentV1::<'a>::new_upper_hex`
--> $SRC_DIR/core/src/fmt/mod.rs:LL:COL
= note: this error originates in the macro `$crate::__export::format_args` which comes from the expansion of the macro `arg_new` (in Nightly builds, run with -Z macro-backtrace for more info)
diff --git a/tests/ui/issues/issue-75307.rs b/tests/ui/fmt/issue-75307.rs
index cffa6bea8..cffa6bea8 100644
--- a/tests/ui/issues/issue-75307.rs
+++ b/tests/ui/fmt/issue-75307.rs
diff --git a/tests/ui/issues/issue-75307.stderr b/tests/ui/fmt/issue-75307.stderr
index c5b0b11e7..c5b0b11e7 100644
--- a/tests/ui/issues/issue-75307.stderr
+++ b/tests/ui/fmt/issue-75307.stderr
diff --git a/tests/ui/fmt/respanned-literal-issue-106191.rs b/tests/ui/fmt/respanned-literal-issue-106191.rs
index bb741c0ef..5a18983a3 100644
--- a/tests/ui/fmt/respanned-literal-issue-106191.rs
+++ b/tests/ui/fmt/respanned-literal-issue-106191.rs
@@ -3,7 +3,7 @@
// known-bug: #106191
// unset-rustc-env:RUST_BACKTRACE
// had to be reverted
-// error-pattern:internal compiler error
+// error-pattern:unexpectedly panicked
// failure-status:101
// dont-check-compiler-stderr
diff --git a/tests/ui/fmt/send-sync.stderr b/tests/ui/fmt/send-sync.stderr
index 3ed040c3a..d43f4f0d9 100644
--- a/tests/ui/fmt/send-sync.stderr
+++ b/tests/ui/fmt/send-sync.stderr
@@ -6,11 +6,11 @@ LL | send(format_args!("{:?}", c));
| |
| required by a bound introduced by this call
|
- = help: within `[ArgumentV1<'_>]`, the trait `Sync` is not implemented for `core::fmt::Opaque`
+ = help: within `[core::fmt::ArgumentV1<'_>]`, the trait `Sync` is not implemented for `core::fmt::Opaque`
= note: required because it appears within the type `&core::fmt::Opaque`
= note: required because it appears within the type `ArgumentV1<'_>`
= note: required because it appears within the type `[ArgumentV1<'_>]`
- = note: required for `&[ArgumentV1<'_>]` to implement `Send`
+ = note: required for `&[core::fmt::ArgumentV1<'_>]` to implement `Send`
= note: required because it appears within the type `Arguments<'_>`
note: required by a bound in `send`
--> $DIR/send-sync.rs:1:12
diff --git a/tests/ui/fn/fn-compare-mismatch.stderr b/tests/ui/fn/fn-compare-mismatch.stderr
index df838cb11..b4e71e75f 100644
--- a/tests/ui/fn/fn-compare-mismatch.stderr
+++ b/tests/ui/fn/fn-compare-mismatch.stderr
@@ -19,6 +19,8 @@ LL | let x = f == g;
|
= note: expected fn item `fn() {f}`
found fn item `fn() {g}`
+ = note: different fn items have unique types, even if their signatures are the same
+ = help: consider casting both fn items to fn pointers using `as fn()`
error: aborting due to 2 previous errors
diff --git a/tests/ui/fn/fn-item-type.rs b/tests/ui/fn/fn-item-type.rs
index 1831e6cbf..c094a34b2 100644
--- a/tests/ui/fn/fn-item-type.rs
+++ b/tests/ui/fn/fn-item-type.rs
@@ -1,13 +1,22 @@
// Test that the types of distinct fn items are not compatible by
// default. See also `run-pass/fn-item-type-*.rs`.
-fn foo<T>(x: isize) -> isize { x * 2 }
-fn bar<T>(x: isize) -> isize { x * 4 }
+fn foo<T>(x: isize) -> isize {
+ x * 2
+}
+fn bar<T>(x: isize) -> isize {
+ x * 4
+}
-fn eq<T>(x: T, y: T) { }
+fn eq<T>(x: T, y: T) {}
-trait Foo { fn foo() { /* this is a default fn */ } }
-impl<T> Foo for T { /* `foo` is still default here */ }
+trait Foo {
+ fn foo() { /* this is a default fn */
+ }
+}
+impl<T> Foo for T {
+ /* `foo` is still default here */
+}
fn main() {
eq(foo::<u8>, bar::<u8>);
@@ -15,39 +24,28 @@ fn main() {
//~| expected fn item `fn(_) -> _ {foo::<u8>}`
//~| found fn item `fn(_) -> _ {bar::<u8>}`
//~| expected fn item, found a different fn item
- //~| different `fn` items always have unique types, even if their signatures are the same
- //~| change the expected type to be function pointer
- //~| if the expected type is due to type inference, cast the expected `fn` to a function pointer
+ //~| different fn items have unique types, even if their signatures are the same
eq(foo::<u8>, foo::<i8>);
//~^ ERROR mismatched types
//~| expected `u8`, found `i8`
- //~| different `fn` items always have unique types, even if their signatures are the same
- //~| change the expected type to be function pointer
- //~| if the expected type is due to type inference, cast the expected `fn` to a function pointer
+ //~| different fn items have unique types, even if their signatures are the same
eq(bar::<String>, bar::<Vec<u8>>);
//~^ ERROR mismatched types
//~| found fn item `fn(_) -> _ {bar::<Vec<u8>>}`
- //~| expected struct `String`, found struct `Vec`
- //~| different `fn` items always have unique types, even if their signatures are the same
- //~| change the expected type to be function pointer
- //~| if the expected type is due to type inference, cast the expected `fn` to a function pointer
+ //~| expected `String`, found `Vec<u8>`
// Make sure we distinguish between trait methods correctly.
eq(<u8 as Foo>::foo, <u16 as Foo>::foo);
//~^ ERROR mismatched types
//~| expected `u8`, found `u16`
- //~| different `fn` items always have unique types, even if their signatures are the same
- //~| change the expected type to be function pointer
- //~| if the expected type is due to type inference, cast the expected `fn` to a function pointer
+ //~| different fn items have unique types, even if their signatures are the same
eq(foo::<u8>, bar::<u8> as fn(isize) -> isize);
//~^ ERROR mismatched types
//~| found fn pointer `fn(_) -> _`
//~| expected fn item, found fn pointer
- //~| change the expected type to be function pointer
- //~| if the expected type is due to type inference, cast the expected `fn` to a function pointer
eq(foo::<u8> as fn(isize) -> isize, bar::<u8>); // ok!
}
diff --git a/tests/ui/fn/fn-item-type.stderr b/tests/ui/fn/fn-item-type.stderr
index f03a47d5c..da90b8b81 100644
--- a/tests/ui/fn/fn-item-type.stderr
+++ b/tests/ui/fn/fn-item-type.stderr
@@ -1,5 +1,5 @@
error[E0308]: mismatched types
- --> $DIR/fn-item-type.rs:13:19
+ --> $DIR/fn-item-type.rs:22:19
|
LL | eq(foo::<u8>, bar::<u8>);
| -- ^^^^^^^^^ expected fn item, found a different fn item
@@ -8,17 +8,16 @@ LL | eq(foo::<u8>, bar::<u8>);
|
= note: expected fn item `fn(_) -> _ {foo::<u8>}`
found fn item `fn(_) -> _ {bar::<u8>}`
- = note: different `fn` items always have unique types, even if their signatures are the same
- = help: change the expected type to be function pointer `fn(isize) -> isize`
- = help: if the expected type is due to type inference, cast the expected `fn` to a function pointer: `foo::<u8> as fn(isize) -> isize`
+ = note: different fn items have unique types, even if their signatures are the same
note: function defined here
- --> $DIR/fn-item-type.rs:7:4
+ --> $DIR/fn-item-type.rs:11:4
|
-LL | fn eq<T>(x: T, y: T) { }
+LL | fn eq<T>(x: T, y: T) {}
| ^^ ----
+ = help: consider casting both fn items to fn pointers using `as fn(isize) -> isize`
error[E0308]: mismatched types
- --> $DIR/fn-item-type.rs:22:19
+ --> $DIR/fn-item-type.rs:29:19
|
LL | eq(foo::<u8>, foo::<i8>);
| -- ^^^^^^^^^ expected `u8`, found `i8`
@@ -27,36 +26,34 @@ LL | eq(foo::<u8>, foo::<i8>);
|
= note: expected fn item `fn(_) -> _ {foo::<u8>}`
found fn item `fn(_) -> _ {foo::<i8>}`
- = note: different `fn` items always have unique types, even if their signatures are the same
- = help: change the expected type to be function pointer `fn(isize) -> isize`
- = help: if the expected type is due to type inference, cast the expected `fn` to a function pointer: `foo::<u8> as fn(isize) -> isize`
+ = note: different fn items have unique types, even if their signatures are the same
note: function defined here
- --> $DIR/fn-item-type.rs:7:4
+ --> $DIR/fn-item-type.rs:11:4
|
-LL | fn eq<T>(x: T, y: T) { }
+LL | fn eq<T>(x: T, y: T) {}
| ^^ ----
+ = help: consider casting both fn items to fn pointers using `as fn(isize) -> isize`
error[E0308]: mismatched types
- --> $DIR/fn-item-type.rs:29:23
+ --> $DIR/fn-item-type.rs:34:23
|
LL | eq(bar::<String>, bar::<Vec<u8>>);
- | -- ^^^^^^^^^^^^^^ expected struct `String`, found struct `Vec`
+ | -- ^^^^^^^^^^^^^^ expected `String`, found `Vec<u8>`
| |
| arguments to this function are incorrect
|
= note: expected fn item `fn(_) -> _ {bar::<String>}`
found fn item `fn(_) -> _ {bar::<Vec<u8>>}`
- = note: different `fn` items always have unique types, even if their signatures are the same
- = help: change the expected type to be function pointer `fn(isize) -> isize`
- = help: if the expected type is due to type inference, cast the expected `fn` to a function pointer: `bar::<String> as fn(isize) -> isize`
+ = note: different fn items have unique types, even if their signatures are the same
note: function defined here
- --> $DIR/fn-item-type.rs:7:4
+ --> $DIR/fn-item-type.rs:11:4
|
-LL | fn eq<T>(x: T, y: T) { }
+LL | fn eq<T>(x: T, y: T) {}
| ^^ ----
+ = help: consider casting both fn items to fn pointers using `as fn(isize) -> isize`
error[E0308]: mismatched types
- --> $DIR/fn-item-type.rs:38:26
+ --> $DIR/fn-item-type.rs:40:26
|
LL | eq(<u8 as Foo>::foo, <u16 as Foo>::foo);
| -- ^^^^^^^^^^^^^^^^^ expected `u8`, found `u16`
@@ -65,14 +62,13 @@ LL | eq(<u8 as Foo>::foo, <u16 as Foo>::foo);
|
= note: expected fn item `fn() {<u8 as Foo>::foo}`
found fn item `fn() {<u16 as Foo>::foo}`
- = note: different `fn` items always have unique types, even if their signatures are the same
- = help: change the expected type to be function pointer `fn()`
- = help: if the expected type is due to type inference, cast the expected `fn` to a function pointer: `<u8 as Foo>::foo as fn()`
+ = note: different fn items have unique types, even if their signatures are the same
note: function defined here
- --> $DIR/fn-item-type.rs:7:4
+ --> $DIR/fn-item-type.rs:11:4
|
-LL | fn eq<T>(x: T, y: T) { }
+LL | fn eq<T>(x: T, y: T) {}
| ^^ ----
+ = help: consider casting both fn items to fn pointers using `as fn()`
error[E0308]: mismatched types
--> $DIR/fn-item-type.rs:45:19
@@ -84,12 +80,11 @@ LL | eq(foo::<u8>, bar::<u8> as fn(isize) -> isize);
|
= note: expected fn item `fn(_) -> _ {foo::<u8>}`
found fn pointer `fn(_) -> _`
- = help: change the expected type to be function pointer `fn(isize) -> isize`
- = help: if the expected type is due to type inference, cast the expected `fn` to a function pointer: `foo::<u8> as fn(isize) -> isize`
+ = help: consider casting the fn item to a fn pointer: `foo::<u8> as fn(isize) -> isize`
note: function defined here
- --> $DIR/fn-item-type.rs:7:4
+ --> $DIR/fn-item-type.rs:11:4
|
-LL | fn eq<T>(x: T, y: T) { }
+LL | fn eq<T>(x: T, y: T) {}
| ^^ ----
error: aborting due to 5 previous errors
diff --git a/tests/ui/fn/fn-pointer-mismatch.rs b/tests/ui/fn/fn-pointer-mismatch.rs
new file mode 100644
index 000000000..0597478cb
--- /dev/null
+++ b/tests/ui/fn/fn-pointer-mismatch.rs
@@ -0,0 +1,56 @@
+fn foo(x: u32) -> u32 {
+ x * 2
+}
+
+fn bar(x: u32) -> u32 {
+ x * 3
+}
+
+// original example from Issue #102608
+fn foobar(n: u32) -> u32 {
+ let g = if n % 2 == 0 { &foo } else { &bar };
+ //~^ ERROR `if` and `else` have incompatible types
+ //~| different fn items have unique types, even if their signatures are the same
+ g(n)
+}
+
+fn main() {
+ assert_eq!(foobar(7), 21);
+ assert_eq!(foobar(8), 16);
+
+ // general mismatch of fn item types
+ let mut a = foo;
+ a = bar;
+ //~^ ERROR mismatched types
+ //~| expected fn item `fn(_) -> _ {foo}`
+ //~| found fn item `fn(_) -> _ {bar}`
+ //~| different fn items have unique types, even if their signatures are the same
+
+ // display note even when boxed
+ let mut b = Box::new(foo);
+ b = Box::new(bar);
+ //~^ ERROR mismatched types
+ //~| different fn items have unique types, even if their signatures are the same
+
+ // suggest removing reference
+ let c: fn(u32) -> u32 = &foo;
+ //~^ ERROR mismatched types
+ //~| expected fn pointer `fn(u32) -> u32`
+ //~| found reference `&fn(u32) -> u32 {foo}`
+
+ // suggest using reference
+ let d: &fn(u32) -> u32 = foo;
+ //~^ ERROR mismatched types
+ //~| expected reference `&fn(u32) -> u32`
+ //~| found fn item `fn(u32) -> u32 {foo}`
+
+ // suggest casting with reference
+ let e: &fn(u32) -> u32 = &foo;
+ //~^ ERROR mismatched types
+ //~| expected reference `&fn(u32) -> u32`
+ //~| found reference `&fn(u32) -> u32 {foo}`
+
+ // OK
+ let mut z: fn(u32) -> u32 = foo as fn(u32) -> u32;
+ z = bar;
+}
diff --git a/tests/ui/fn/fn-pointer-mismatch.stderr b/tests/ui/fn/fn-pointer-mismatch.stderr
new file mode 100644
index 000000000..a674babcb
--- /dev/null
+++ b/tests/ui/fn/fn-pointer-mismatch.stderr
@@ -0,0 +1,91 @@
+error[E0308]: `if` and `else` have incompatible types
+ --> $DIR/fn-pointer-mismatch.rs:11:43
+ |
+LL | let g = if n % 2 == 0 { &foo } else { &bar };
+ | ---- ^^^^ expected `&fn(u32) -> u32 {foo}`, found `&fn(u32) -> u32 {bar}`
+ | |
+ | expected because of this
+ |
+ = note: expected reference `&fn(u32) -> u32 {foo}`
+ found reference `&fn(u32) -> u32 {bar}`
+ = note: different fn items have unique types, even if their signatures are the same
+ = help: consider casting both fn items to fn pointers using `as fn(u32) -> u32`
+
+error[E0308]: mismatched types
+ --> $DIR/fn-pointer-mismatch.rs:23:9
+ |
+LL | let mut a = foo;
+ | --- expected due to this value
+LL | a = bar;
+ | ^^^ expected fn item, found a different fn item
+ |
+ = note: expected fn item `fn(_) -> _ {foo}`
+ found fn item `fn(_) -> _ {bar}`
+ = note: different fn items have unique types, even if their signatures are the same
+ = help: consider casting both fn items to fn pointers using `as fn(u32) -> u32`
+
+error[E0308]: mismatched types
+ --> $DIR/fn-pointer-mismatch.rs:31:18
+ |
+LL | b = Box::new(bar);
+ | -------- ^^^ expected fn item, found a different fn item
+ | |
+ | arguments to this function are incorrect
+ |
+ = note: expected fn item `fn(_) -> _ {foo}`
+ found fn item `fn(_) -> _ {bar}`
+ = note: different fn items have unique types, even if their signatures are the same
+note: associated function defined here
+ --> $SRC_DIR/alloc/src/boxed.rs:LL:COL
+ = help: consider casting both fn items to fn pointers using `as fn(u32) -> u32`
+
+error[E0308]: mismatched types
+ --> $DIR/fn-pointer-mismatch.rs:36:29
+ |
+LL | let c: fn(u32) -> u32 = &foo;
+ | -------------- ^^^^ expected fn pointer, found `&fn(u32) -> u32 {foo}`
+ | |
+ | expected due to this
+ |
+ = note: expected fn pointer `fn(u32) -> u32`
+ found reference `&fn(u32) -> u32 {foo}`
+help: consider removing the reference
+ |
+LL | let c: fn(u32) -> u32 = foo;
+ | ~~~
+
+error[E0308]: mismatched types
+ --> $DIR/fn-pointer-mismatch.rs:42:30
+ |
+LL | let d: &fn(u32) -> u32 = foo;
+ | --------------- ^^^ expected `&fn(u32) -> u32`, found fn item
+ | |
+ | expected due to this
+ |
+ = note: expected reference `&fn(u32) -> u32`
+ found fn item `fn(u32) -> u32 {foo}`
+help: consider using a reference
+ |
+LL | let d: &fn(u32) -> u32 = &foo;
+ | ~~~~
+
+error[E0308]: mismatched types
+ --> $DIR/fn-pointer-mismatch.rs:48:30
+ |
+LL | let e: &fn(u32) -> u32 = &foo;
+ | --------------- ^^^^ expected `&fn(u32) -> u32`, found `&fn(u32) -> u32 {foo}`
+ | |
+ | expected due to this
+ |
+ = note: expected reference `&fn(u32) -> u32`
+ found reference `&fn(u32) -> u32 {foo}`
+ = note: fn items are distinct from fn pointers
+ = note: when the arguments and return types match, functions can be coerced to function pointers
+help: consider casting to a fn pointer
+ |
+LL | let e: &fn(u32) -> u32 = &(foo as fn(u32) -> u32);
+ | ~~~~~~~~~~~~~~~~~~~~~~~~
+
+error: aborting due to 6 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/fn/fn-trait-formatting.stderr b/tests/ui/fn/fn-trait-formatting.stderr
index 2a674d3c1..45d543bda 100644
--- a/tests/ui/fn/fn-trait-formatting.stderr
+++ b/tests/ui/fn/fn-trait-formatting.stderr
@@ -2,7 +2,7 @@ error[E0308]: mismatched types
--> $DIR/fn-trait-formatting.rs:6:17
|
LL | let _: () = Box::new(|_: isize| {}) as Box<dyn FnOnce(isize)>;
- | -- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found struct `Box`
+ | -- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found `Box<dyn FnOnce(isize)>`
| |
| expected due to this
|
@@ -17,7 +17,7 @@ error[E0308]: mismatched types
--> $DIR/fn-trait-formatting.rs:10:17
|
LL | let _: () = Box::new(|_: isize, isize| {}) as Box<dyn Fn(isize, isize)>;
- | -- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found struct `Box`
+ | -- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found `Box<dyn Fn(isize, isize)>`
| |
| expected due to this
|
@@ -32,7 +32,7 @@ error[E0308]: mismatched types
--> $DIR/fn-trait-formatting.rs:14:17
|
LL | let _: () = Box::new(|| -> isize { unimplemented!() }) as Box<dyn FnMut() -> isize>;
- | -- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found struct `Box`
+ | -- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found `Box<dyn FnMut() -> isize>`
| |
| expected due to this
|
diff --git a/tests/ui/fn/implied-bounds-unnorm-associated-type-4.stderr b/tests/ui/fn/implied-bounds-unnorm-associated-type-4.stderr
index fcbaa91d1..4df639232 100644
--- a/tests/ui/fn/implied-bounds-unnorm-associated-type-4.stderr
+++ b/tests/ui/fn/implied-bounds-unnorm-associated-type-4.stderr
@@ -1,6 +1,8 @@
error[E0505]: cannot move out of `x` because it is borrowed
--> $DIR/implied-bounds-unnorm-associated-type-4.rs:21:10
|
+LL | let x = String::from("Hello World!");
+ | - binding `x` declared here
LL | let y = f(&x, ());
| -- borrow of `x` occurs here
LL | drop(x);
diff --git a/tests/ui/fn/implied-bounds-unnorm-associated-type.stderr b/tests/ui/fn/implied-bounds-unnorm-associated-type.stderr
index e35f46e44..d417f2883 100644
--- a/tests/ui/fn/implied-bounds-unnorm-associated-type.stderr
+++ b/tests/ui/fn/implied-bounds-unnorm-associated-type.stderr
@@ -1,6 +1,8 @@
error[E0505]: cannot move out of `x` because it is borrowed
--> $DIR/implied-bounds-unnorm-associated-type.rs:20:10
|
+LL | let x = String::from("Hello World!");
+ | - binding `x` declared here
LL | let y = f(&x, ());
| -- borrow of `x` occurs here
LL | drop(x);
diff --git a/tests/ui/fn/issue-3044.stderr b/tests/ui/fn/issue-3044.stderr
index 2690ad711..219029e2a 100644
--- a/tests/ui/fn/issue-3044.stderr
+++ b/tests/ui/fn/issue-3044.stderr
@@ -7,7 +7,7 @@ LL | |
LL | | });
| |______- an argument is missing
|
-note: associated function defined here
+note: method defined here
--> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
help: provide the argument
|
diff --git a/tests/ui/fn/signature-error-reporting-under-verbose.rs b/tests/ui/fn/signature-error-reporting-under-verbose.rs
index d7a8c95e8..12ff113c9 100644
--- a/tests/ui/fn/signature-error-reporting-under-verbose.rs
+++ b/tests/ui/fn/signature-error-reporting-under-verbose.rs
@@ -9,7 +9,8 @@ fn needs_ptr(_: fn(i32, u32)) {}
fn main() {
needs_ptr(foo);
//~^ ERROR mismatched types
- //~| NOTE expected `u32`, found `i32`
+ //~| NOTE expected fn pointer, found fn item
//~| NOTE expected fn pointer `fn(i32, u32)`
//~| NOTE arguments to this function are incorrect
+ //~| NOTE when the arguments and return types match, functions can be coerced to function pointers
}
diff --git a/tests/ui/fn/signature-error-reporting-under-verbose.stderr b/tests/ui/fn/signature-error-reporting-under-verbose.stderr
index 6260fc8dc..f4498db72 100644
--- a/tests/ui/fn/signature-error-reporting-under-verbose.stderr
+++ b/tests/ui/fn/signature-error-reporting-under-verbose.stderr
@@ -2,12 +2,13 @@ error[E0308]: mismatched types
--> $DIR/signature-error-reporting-under-verbose.rs:10:15
|
LL | needs_ptr(foo);
- | --------- ^^^ expected `u32`, found `i32`
+ | --------- ^^^ expected fn pointer, found fn item
| |
| arguments to this function are incorrect
|
= note: expected fn pointer `fn(i32, u32)`
found fn item `fn(i32, i32) {foo}`
+ = note: when the arguments and return types match, functions can be coerced to function pointers
note: function defined here
--> $DIR/signature-error-reporting-under-verbose.rs:5:4
|
diff --git a/tests/ui/for/for-else-err.rs b/tests/ui/for/for-else-err.rs
new file mode 100644
index 000000000..16252e980
--- /dev/null
+++ b/tests/ui/for/for-else-err.rs
@@ -0,0 +1,8 @@
+fn main() {
+ for _ in 0..1 {
+ //~^ NOTE `else` is attached to this loop
+ } else {
+ //~^ ERROR `for...else` loops are not supported
+ //~| NOTE consider moving this `else` clause to a separate `if` statement and use a `bool` variable to control if it should run
+ }
+}
diff --git a/tests/ui/for/for-else-err.stderr b/tests/ui/for/for-else-err.stderr
new file mode 100644
index 000000000..b330d1076
--- /dev/null
+++ b/tests/ui/for/for-else-err.stderr
@@ -0,0 +1,17 @@
+error: `for...else` loops are not supported
+ --> $DIR/for-else-err.rs:4:7
+ |
+LL | for _ in 0..1 {
+ | --- `else` is attached to this loop
+LL |
+LL | } else {
+ | _______^
+LL | |
+LL | |
+LL | | }
+ | |_____^
+ |
+ = note: consider moving this `else` clause to a separate `if` statement and use a `bool` variable to control if it should run
+
+error: aborting due to previous error
+
diff --git a/tests/ui/for/for-else-let-else-err.rs b/tests/ui/for/for-else-let-else-err.rs
new file mode 100644
index 000000000..c0b96f972
--- /dev/null
+++ b/tests/ui/for/for-else-let-else-err.rs
@@ -0,0 +1,8 @@
+fn main() {
+ let _ = for _ in 0..1 {
+ //~^ NOTE `else` is attached to this loop
+ } else {
+ //~^ ERROR `for...else` loops are not supported
+ //~| NOTE consider moving this `else` clause to a separate `if` statement and use a `bool` variable to control if it should run
+ };
+}
diff --git a/tests/ui/for/for-else-let-else-err.stderr b/tests/ui/for/for-else-let-else-err.stderr
new file mode 100644
index 000000000..a2396a8fb
--- /dev/null
+++ b/tests/ui/for/for-else-let-else-err.stderr
@@ -0,0 +1,17 @@
+error: `for...else` loops are not supported
+ --> $DIR/for-else-let-else-err.rs:4:7
+ |
+LL | let _ = for _ in 0..1 {
+ | --- `else` is attached to this loop
+LL |
+LL | } else {
+ | _______^
+LL | |
+LL | |
+LL | | };
+ | |_____^
+ |
+ = note: consider moving this `else` clause to a separate `if` statement and use a `bool` variable to control if it should run
+
+error: aborting due to previous error
+
diff --git a/tests/ui/fully-qualified-type/fully-qualified-type-name1.rs b/tests/ui/fully-qualified-type/fully-qualified-type-name1.rs
index 229c174da..bbca22ad2 100644
--- a/tests/ui/fully-qualified-type/fully-qualified-type-name1.rs
+++ b/tests/ui/fully-qualified-type/fully-qualified-type-name1.rs
@@ -6,5 +6,5 @@ fn main() {
x = 5;
//~^ ERROR mismatched types
//~| NOTE expected enum `Option<usize>`
- //~| NOTE expected enum `Option`, found integer
+ //~| NOTE expected `Option<usize>`, found integer
}
diff --git a/tests/ui/fully-qualified-type/fully-qualified-type-name1.stderr b/tests/ui/fully-qualified-type/fully-qualified-type-name1.stderr
index 4750c5ccd..258a8d163 100644
--- a/tests/ui/fully-qualified-type/fully-qualified-type-name1.stderr
+++ b/tests/ui/fully-qualified-type/fully-qualified-type-name1.stderr
@@ -6,7 +6,7 @@ LL | let x:
LL | Option<usize>;
| ------------- expected due to this type
LL | x = 5;
- | ^ expected enum `Option`, found integer
+ | ^ expected `Option<usize>`, found integer
|
= note: expected enum `Option<usize>`
found type `{integer}`
diff --git a/tests/ui/fully-qualified-type/fully-qualified-type-name2.rs b/tests/ui/fully-qualified-type/fully-qualified-type-name2.rs
index 94a9f4e56..f26d3be66 100644
--- a/tests/ui/fully-qualified-type/fully-qualified-type-name2.rs
+++ b/tests/ui/fully-qualified-type/fully-qualified-type-name2.rs
@@ -11,7 +11,7 @@ mod y {
fn bar(x: x::Foo) -> y::Foo {
return x;
//~^ ERROR mismatched types
- //~| expected enum `y::Foo`, found enum `x::Foo`
+ //~| expected `y::Foo`, found `x::Foo`
}
fn main() {
diff --git a/tests/ui/fully-qualified-type/fully-qualified-type-name2.stderr b/tests/ui/fully-qualified-type/fully-qualified-type-name2.stderr
index a8f23f81d..c7c084659 100644
--- a/tests/ui/fully-qualified-type/fully-qualified-type-name2.stderr
+++ b/tests/ui/fully-qualified-type/fully-qualified-type-name2.stderr
@@ -4,15 +4,15 @@ error[E0308]: mismatched types
LL | fn bar(x: x::Foo) -> y::Foo {
| ------ expected `y::Foo` because of return type
LL | return x;
- | ^ expected enum `y::Foo`, found enum `x::Foo`
+ | ^ expected `y::Foo`, found `x::Foo`
|
- = note: enum `x::Foo` and enum `y::Foo` have similar names, but are actually distinct types
-note: enum `x::Foo` is defined in module `crate::x` of the current crate
+ = note: `x::Foo` and `y::Foo` have similar names, but are actually distinct types
+note: `x::Foo` is defined in module `crate::x` of the current crate
--> $DIR/fully-qualified-type-name2.rs:4:5
|
LL | pub enum Foo { }
| ^^^^^^^^^^^^
-note: enum `y::Foo` is defined in module `crate::y` of the current crate
+note: `y::Foo` is defined in module `crate::y` of the current crate
--> $DIR/fully-qualified-type-name2.rs:8:5
|
LL | pub enum Foo { }
diff --git a/tests/ui/fully-qualified-type/fully-qualified-type-name4.rs b/tests/ui/fully-qualified-type/fully-qualified-type-name4.rs
index 2486ae009..41f07bab8 100644
--- a/tests/ui/fully-qualified-type/fully-qualified-type-name4.rs
+++ b/tests/ui/fully-qualified-type/fully-qualified-type-name4.rs
@@ -7,7 +7,7 @@ fn bar(x: usize) -> Option<usize> {
//~^ ERROR mismatched types
//~| expected enum `Option<usize>`
//~| found type `usize`
- //~| expected enum `Option`, found `usize`
+ //~| expected `Option<usize>`, found `usize`
}
fn main() {
diff --git a/tests/ui/fully-qualified-type/fully-qualified-type-name4.stderr b/tests/ui/fully-qualified-type/fully-qualified-type-name4.stderr
index 778b13f24..6b312202b 100644
--- a/tests/ui/fully-qualified-type/fully-qualified-type-name4.stderr
+++ b/tests/ui/fully-qualified-type/fully-qualified-type-name4.stderr
@@ -4,7 +4,7 @@ error[E0308]: mismatched types
LL | fn bar(x: usize) -> Option<usize> {
| ------------- expected `Option<usize>` because of return type
LL | return x;
- | ^ expected enum `Option`, found `usize`
+ | ^ expected `Option<usize>`, found `usize`
|
= note: expected enum `Option<usize>`
found type `usize`
diff --git a/tests/ui/function-pointer/unsized-ret.stderr b/tests/ui/function-pointer/unsized-ret.stderr
index 6f430687e..870f1805b 100644
--- a/tests/ui/function-pointer/unsized-ret.stderr
+++ b/tests/ui/function-pointer/unsized-ret.stderr
@@ -23,7 +23,7 @@ LL | foo::<for<'a> fn(&'a ()) -> (dyn std::fmt::Display + 'a), _>(None, (&()
| required by a bound introduced by this call
|
= help: within `for<'a> fn(&'a ()) -> (dyn std::fmt::Display + 'a)`, the trait `for<'a> Sized` is not implemented for `(dyn std::fmt::Display + 'a)`
- = note: required because it appears within the type `for<'a> fn(&'a ()) -> (dyn Display + 'a)`
+ = note: required because it appears within the type `fn(&()) -> dyn Display`
note: required by a bound in `foo`
--> $DIR/unsized-ret.rs:5:11
|
diff --git a/tests/ui/functions-closures/fn-help-with-err.stderr b/tests/ui/functions-closures/fn-help-with-err.stderr
index 83a2b1f58..da081eb43 100644
--- a/tests/ui/functions-closures/fn-help-with-err.stderr
+++ b/tests/ui/functions-closures/fn-help-with-err.stderr
@@ -4,7 +4,7 @@ error[E0425]: cannot find value `oops` in this scope
LL | let arc = std::sync::Arc::new(oops);
| ^^^^ not found in this scope
-error[E0599]: no method named `bar` found for struct `Arc<[closure@fn-help-with-err.rs:18:36]>` in the current scope
+error[E0599]: no method named `bar` found for struct `Arc<[closure@$DIR/fn-help-with-err.rs:18:36: 18:38]>` in the current scope
--> $DIR/fn-help-with-err.rs:19:10
|
LL | arc2.bar();
diff --git a/tests/ui/generator/addassign-yield.rs b/tests/ui/generator/addassign-yield.rs
index 66f22bf31..7211367af 100644
--- a/tests/ui/generator/addassign-yield.rs
+++ b/tests/ui/generator/addassign-yield.rs
@@ -1,3 +1,6 @@
+// revisions: no_drop_tracking drop_tracking drop_tracking_mir
+// [drop_tracking] compile-flags: -Zdrop-tracking
+// [drop_tracking_mir] compile-flags: -Zdrop-tracking-mir
// run-pass
// Regression test for broken MIR error (#61442)
// Due to the two possible evaluation orders for
diff --git a/tests/ui/generator/auto-trait-regions.drop_tracking.stderr b/tests/ui/generator/auto-trait-regions.drop_tracking.stderr
new file mode 100644
index 000000000..165748d44
--- /dev/null
+++ b/tests/ui/generator/auto-trait-regions.drop_tracking.stderr
@@ -0,0 +1,47 @@
+error[E0716]: temporary value dropped while borrowed
+ --> $DIR/auto-trait-regions.rs:48:24
+ |
+LL | let a = A(&mut true, &mut true, No);
+ | ^^^^ - temporary value is freed at the end of this statement
+ | |
+ | creates a temporary value which is freed while still in use
+...
+LL | assert_foo(a);
+ | - borrow later used here
+ |
+ = note: consider using a `let` binding to create a longer lived value
+
+error[E0716]: temporary value dropped while borrowed
+ --> $DIR/auto-trait-regions.rs:48:35
+ |
+LL | let a = A(&mut true, &mut true, No);
+ | ^^^^ - temporary value is freed at the end of this statement
+ | |
+ | creates a temporary value which is freed while still in use
+...
+LL | assert_foo(a);
+ | - borrow later used here
+ |
+ = note: consider using a `let` binding to create a longer lived value
+
+error: implementation of `Foo` is not general enough
+ --> $DIR/auto-trait-regions.rs:34:5
+ |
+LL | assert_foo(gen);
+ | ^^^^^^^^^^^^^^^ implementation of `Foo` is not general enough
+ |
+ = note: `&'0 OnlyFooIfStaticRef` must implement `Foo`, for any lifetime `'0`...
+ = note: ...but `Foo` is actually implemented for the type `&'static OnlyFooIfStaticRef`
+
+error: implementation of `Foo` is not general enough
+ --> $DIR/auto-trait-regions.rs:54:5
+ |
+LL | assert_foo(gen);
+ | ^^^^^^^^^^^^^^^ implementation of `Foo` is not general enough
+ |
+ = note: `Foo` would have to be implemented for the type `A<'0, '1>`, for any two lifetimes `'0` and `'1`...
+ = note: ...but `Foo` is actually implemented for the type `A<'_, '2>`, for some specific lifetime `'2`
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0716`.
diff --git a/tests/ui/generator/auto-trait-regions.drop_tracking_mir.stderr b/tests/ui/generator/auto-trait-regions.drop_tracking_mir.stderr
new file mode 100644
index 000000000..165748d44
--- /dev/null
+++ b/tests/ui/generator/auto-trait-regions.drop_tracking_mir.stderr
@@ -0,0 +1,47 @@
+error[E0716]: temporary value dropped while borrowed
+ --> $DIR/auto-trait-regions.rs:48:24
+ |
+LL | let a = A(&mut true, &mut true, No);
+ | ^^^^ - temporary value is freed at the end of this statement
+ | |
+ | creates a temporary value which is freed while still in use
+...
+LL | assert_foo(a);
+ | - borrow later used here
+ |
+ = note: consider using a `let` binding to create a longer lived value
+
+error[E0716]: temporary value dropped while borrowed
+ --> $DIR/auto-trait-regions.rs:48:35
+ |
+LL | let a = A(&mut true, &mut true, No);
+ | ^^^^ - temporary value is freed at the end of this statement
+ | |
+ | creates a temporary value which is freed while still in use
+...
+LL | assert_foo(a);
+ | - borrow later used here
+ |
+ = note: consider using a `let` binding to create a longer lived value
+
+error: implementation of `Foo` is not general enough
+ --> $DIR/auto-trait-regions.rs:34:5
+ |
+LL | assert_foo(gen);
+ | ^^^^^^^^^^^^^^^ implementation of `Foo` is not general enough
+ |
+ = note: `&'0 OnlyFooIfStaticRef` must implement `Foo`, for any lifetime `'0`...
+ = note: ...but `Foo` is actually implemented for the type `&'static OnlyFooIfStaticRef`
+
+error: implementation of `Foo` is not general enough
+ --> $DIR/auto-trait-regions.rs:54:5
+ |
+LL | assert_foo(gen);
+ | ^^^^^^^^^^^^^^^ implementation of `Foo` is not general enough
+ |
+ = note: `Foo` would have to be implemented for the type `A<'0, '1>`, for any two lifetimes `'0` and `'1`...
+ = note: ...but `Foo` is actually implemented for the type `A<'_, '2>`, for some specific lifetime `'2`
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0716`.
diff --git a/tests/ui/generator/auto-trait-regions.no_drop_tracking.stderr b/tests/ui/generator/auto-trait-regions.no_drop_tracking.stderr
new file mode 100644
index 000000000..165748d44
--- /dev/null
+++ b/tests/ui/generator/auto-trait-regions.no_drop_tracking.stderr
@@ -0,0 +1,47 @@
+error[E0716]: temporary value dropped while borrowed
+ --> $DIR/auto-trait-regions.rs:48:24
+ |
+LL | let a = A(&mut true, &mut true, No);
+ | ^^^^ - temporary value is freed at the end of this statement
+ | |
+ | creates a temporary value which is freed while still in use
+...
+LL | assert_foo(a);
+ | - borrow later used here
+ |
+ = note: consider using a `let` binding to create a longer lived value
+
+error[E0716]: temporary value dropped while borrowed
+ --> $DIR/auto-trait-regions.rs:48:35
+ |
+LL | let a = A(&mut true, &mut true, No);
+ | ^^^^ - temporary value is freed at the end of this statement
+ | |
+ | creates a temporary value which is freed while still in use
+...
+LL | assert_foo(a);
+ | - borrow later used here
+ |
+ = note: consider using a `let` binding to create a longer lived value
+
+error: implementation of `Foo` is not general enough
+ --> $DIR/auto-trait-regions.rs:34:5
+ |
+LL | assert_foo(gen);
+ | ^^^^^^^^^^^^^^^ implementation of `Foo` is not general enough
+ |
+ = note: `&'0 OnlyFooIfStaticRef` must implement `Foo`, for any lifetime `'0`...
+ = note: ...but `Foo` is actually implemented for the type `&'static OnlyFooIfStaticRef`
+
+error: implementation of `Foo` is not general enough
+ --> $DIR/auto-trait-regions.rs:54:5
+ |
+LL | assert_foo(gen);
+ | ^^^^^^^^^^^^^^^ implementation of `Foo` is not general enough
+ |
+ = note: `Foo` would have to be implemented for the type `A<'0, '1>`, for any two lifetimes `'0` and `'1`...
+ = note: ...but `Foo` is actually implemented for the type `A<'_, '2>`, for some specific lifetime `'2`
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0716`.
diff --git a/tests/ui/generator/auto-trait-regions.rs b/tests/ui/generator/auto-trait-regions.rs
index ea4b0d554..fd13e4131 100644
--- a/tests/ui/generator/auto-trait-regions.rs
+++ b/tests/ui/generator/auto-trait-regions.rs
@@ -1,3 +1,6 @@
+// revisions: no_drop_tracking drop_tracking drop_tracking_mir
+// [drop_tracking] compile-flags: -Zdrop-tracking
+// [drop_tracking_mir] compile-flags: -Zdrop-tracking-mir
#![feature(generators)]
#![feature(auto_traits)]
#![feature(negative_impls)]
diff --git a/tests/ui/generator/auto-trait-regions.stderr b/tests/ui/generator/auto-trait-regions.stderr
index 0b1f34aeb..165748d44 100644
--- a/tests/ui/generator/auto-trait-regions.stderr
+++ b/tests/ui/generator/auto-trait-regions.stderr
@@ -1,5 +1,5 @@
error[E0716]: temporary value dropped while borrowed
- --> $DIR/auto-trait-regions.rs:45:24
+ --> $DIR/auto-trait-regions.rs:48:24
|
LL | let a = A(&mut true, &mut true, No);
| ^^^^ - temporary value is freed at the end of this statement
@@ -12,7 +12,7 @@ LL | assert_foo(a);
= note: consider using a `let` binding to create a longer lived value
error[E0716]: temporary value dropped while borrowed
- --> $DIR/auto-trait-regions.rs:45:35
+ --> $DIR/auto-trait-regions.rs:48:35
|
LL | let a = A(&mut true, &mut true, No);
| ^^^^ - temporary value is freed at the end of this statement
@@ -25,7 +25,7 @@ LL | assert_foo(a);
= note: consider using a `let` binding to create a longer lived value
error: implementation of `Foo` is not general enough
- --> $DIR/auto-trait-regions.rs:31:5
+ --> $DIR/auto-trait-regions.rs:34:5
|
LL | assert_foo(gen);
| ^^^^^^^^^^^^^^^ implementation of `Foo` is not general enough
@@ -34,7 +34,7 @@ LL | assert_foo(gen);
= note: ...but `Foo` is actually implemented for the type `&'static OnlyFooIfStaticRef`
error: implementation of `Foo` is not general enough
- --> $DIR/auto-trait-regions.rs:51:5
+ --> $DIR/auto-trait-regions.rs:54:5
|
LL | assert_foo(gen);
| ^^^^^^^^^^^^^^^ implementation of `Foo` is not general enough
diff --git a/tests/ui/generator/borrowing.drop_tracking.stderr b/tests/ui/generator/borrowing.drop_tracking.stderr
new file mode 100644
index 000000000..96e3c327f
--- /dev/null
+++ b/tests/ui/generator/borrowing.drop_tracking.stderr
@@ -0,0 +1,31 @@
+error[E0597]: `a` does not live long enough
+ --> $DIR/borrowing.rs:13:33
+ |
+LL | let _b = {
+ | -- borrow later stored here
+LL | let a = 3;
+LL | Pin::new(&mut || yield &a).resume(())
+ | -- ^ borrowed value does not live long enough
+ | |
+ | value captured here by generator
+LL |
+LL | };
+ | - `a` dropped here while still borrowed
+
+error[E0597]: `a` does not live long enough
+ --> $DIR/borrowing.rs:20:20
+ |
+LL | let _b = {
+ | -- borrow later stored here
+LL | let a = 3;
+LL | || {
+ | -- value captured here by generator
+LL | yield &a
+ | ^ borrowed value does not live long enough
+...
+LL | };
+ | - `a` dropped here while still borrowed
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/tests/ui/generator/borrowing.drop_tracking_mir.stderr b/tests/ui/generator/borrowing.drop_tracking_mir.stderr
new file mode 100644
index 000000000..8fbad276d
--- /dev/null
+++ b/tests/ui/generator/borrowing.drop_tracking_mir.stderr
@@ -0,0 +1,39 @@
+error[E0597]: `a` does not live long enough
+ --> $DIR/borrowing.rs:13:33
+ |
+LL | Pin::new(&mut || yield &a).resume(())
+ | ----------^
+ | | |
+ | | borrowed value does not live long enough
+ | value captured here by generator
+ | a temporary with access to the borrow is created here ...
+LL |
+LL | };
+ | -- ... and the borrow might be used here, when that temporary is dropped and runs the destructor for generator
+ | |
+ | `a` dropped here while still borrowed
+ |
+ = note: the temporary is part of an expression at the end of a block;
+ consider forcing this temporary to be dropped sooner, before the block's local variables are dropped
+help: for example, you could save the expression's value in a new local variable `x` and then make `x` be the expression at the end of the block
+ |
+LL | let x = Pin::new(&mut || yield &a).resume(()); x
+ | +++++++ +++
+
+error[E0597]: `a` does not live long enough
+ --> $DIR/borrowing.rs:20:20
+ |
+LL | let _b = {
+ | -- borrow later stored here
+LL | let a = 3;
+LL | || {
+ | -- value captured here by generator
+LL | yield &a
+ | ^ borrowed value does not live long enough
+...
+LL | };
+ | - `a` dropped here while still borrowed
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/tests/ui/generator/borrowing.no_drop_tracking.stderr b/tests/ui/generator/borrowing.no_drop_tracking.stderr
new file mode 100644
index 000000000..96e3c327f
--- /dev/null
+++ b/tests/ui/generator/borrowing.no_drop_tracking.stderr
@@ -0,0 +1,31 @@
+error[E0597]: `a` does not live long enough
+ --> $DIR/borrowing.rs:13:33
+ |
+LL | let _b = {
+ | -- borrow later stored here
+LL | let a = 3;
+LL | Pin::new(&mut || yield &a).resume(())
+ | -- ^ borrowed value does not live long enough
+ | |
+ | value captured here by generator
+LL |
+LL | };
+ | - `a` dropped here while still borrowed
+
+error[E0597]: `a` does not live long enough
+ --> $DIR/borrowing.rs:20:20
+ |
+LL | let _b = {
+ | -- borrow later stored here
+LL | let a = 3;
+LL | || {
+ | -- value captured here by generator
+LL | yield &a
+ | ^ borrowed value does not live long enough
+...
+LL | };
+ | - `a` dropped here while still borrowed
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/tests/ui/generator/borrowing.rs b/tests/ui/generator/borrowing.rs
index d36592583..29f39437f 100644
--- a/tests/ui/generator/borrowing.rs
+++ b/tests/ui/generator/borrowing.rs
@@ -1,3 +1,7 @@
+// revisions: no_drop_tracking drop_tracking drop_tracking_mir
+// [drop_tracking] compile-flags: -Zdrop-tracking
+// [drop_tracking_mir] compile-flags: -Zdrop-tracking-mir
+
#![feature(generators, generator_trait)]
use std::ops::Generator;
diff --git a/tests/ui/generator/borrowing.stderr b/tests/ui/generator/borrowing.stderr
index 38e1ace8c..96e3c327f 100644
--- a/tests/ui/generator/borrowing.stderr
+++ b/tests/ui/generator/borrowing.stderr
@@ -1,5 +1,5 @@
error[E0597]: `a` does not live long enough
- --> $DIR/borrowing.rs:9:33
+ --> $DIR/borrowing.rs:13:33
|
LL | let _b = {
| -- borrow later stored here
@@ -13,7 +13,7 @@ LL | };
| - `a` dropped here while still borrowed
error[E0597]: `a` does not live long enough
- --> $DIR/borrowing.rs:16:20
+ --> $DIR/borrowing.rs:20:20
|
LL | let _b = {
| -- borrow later stored here
diff --git a/tests/ui/generator/drop-tracking-parent-expression.stderr b/tests/ui/generator/drop-tracking-parent-expression.drop_tracking.stderr
index fbf5d6e07..c07906ec3 100644
--- a/tests/ui/generator/drop-tracking-parent-expression.stderr
+++ b/tests/ui/generator/drop-tracking-parent-expression.drop_tracking.stderr
@@ -1,5 +1,5 @@
error: generator cannot be sent between threads safely
- --> $DIR/drop-tracking-parent-expression.rs:24:25
+ --> $DIR/drop-tracking-parent-expression.rs:27:25
|
LL | assert_send(g);
| ^ generator is not `Send`
@@ -13,9 +13,9 @@ LL | | };
LL | | );
| |_____- in this macro invocation
|
- = help: within `[generator@$DIR/drop-tracking-parent-expression.rs:18:21: 18:28]`, the trait `Send` is not implemented for `derived_drop::Client`
+ = help: within `[generator@$DIR/drop-tracking-parent-expression.rs:21:21: 21:28]`, the trait `Send` is not implemented for `derived_drop::Client`
note: generator is not `Send` as this value is used across a yield
- --> $DIR/drop-tracking-parent-expression.rs:22:22
+ --> $DIR/drop-tracking-parent-expression.rs:25:22
|
LL | let g = move || match drop($name::Client { ..$name::Client::default() }) {
| ------------------------ has type `derived_drop::Client` which is not `Send`
@@ -34,14 +34,14 @@ LL | | };
LL | | );
| |_____- in this macro invocation
note: required by a bound in `assert_send`
- --> $DIR/drop-tracking-parent-expression.rs:41:19
+ --> $DIR/drop-tracking-parent-expression.rs:49:19
|
LL | fn assert_send<T: Send>(_thing: T) {}
| ^^^^ required by this bound in `assert_send`
= note: this error originates in the macro `type_combinations` (in Nightly builds, run with -Z macro-backtrace for more info)
error: generator cannot be sent between threads safely
- --> $DIR/drop-tracking-parent-expression.rs:24:25
+ --> $DIR/drop-tracking-parent-expression.rs:27:25
|
LL | assert_send(g);
| ^ generator is not `Send`
@@ -55,9 +55,9 @@ LL | | };
LL | | );
| |_____- in this macro invocation
|
- = help: within `[generator@$DIR/drop-tracking-parent-expression.rs:18:21: 18:28]`, the trait `Send` is not implemented for `significant_drop::Client`
+ = help: within `[generator@$DIR/drop-tracking-parent-expression.rs:21:21: 21:28]`, the trait `Send` is not implemented for `significant_drop::Client`
note: generator is not `Send` as this value is used across a yield
- --> $DIR/drop-tracking-parent-expression.rs:22:22
+ --> $DIR/drop-tracking-parent-expression.rs:25:22
|
LL | let g = move || match drop($name::Client { ..$name::Client::default() }) {
| ------------------------ has type `significant_drop::Client` which is not `Send`
@@ -76,14 +76,14 @@ LL | | };
LL | | );
| |_____- in this macro invocation
note: required by a bound in `assert_send`
- --> $DIR/drop-tracking-parent-expression.rs:41:19
+ --> $DIR/drop-tracking-parent-expression.rs:49:19
|
LL | fn assert_send<T: Send>(_thing: T) {}
| ^^^^ required by this bound in `assert_send`
= note: this error originates in the macro `type_combinations` (in Nightly builds, run with -Z macro-backtrace for more info)
error: generator cannot be sent between threads safely
- --> $DIR/drop-tracking-parent-expression.rs:24:25
+ --> $DIR/drop-tracking-parent-expression.rs:27:25
|
LL | assert_send(g);
| ^ generator is not `Send`
@@ -97,9 +97,9 @@ LL | | };
LL | | );
| |_____- in this macro invocation
|
- = help: within `[generator@$DIR/drop-tracking-parent-expression.rs:18:21: 18:28]`, the trait `Send` is not implemented for `insignificant_dtor::Client`
+ = help: within `[generator@$DIR/drop-tracking-parent-expression.rs:21:21: 21:28]`, the trait `Send` is not implemented for `insignificant_dtor::Client`
note: generator is not `Send` as this value is used across a yield
- --> $DIR/drop-tracking-parent-expression.rs:22:22
+ --> $DIR/drop-tracking-parent-expression.rs:25:22
|
LL | let g = move || match drop($name::Client { ..$name::Client::default() }) {
| ------------------------ has type `insignificant_dtor::Client` which is not `Send`
@@ -118,7 +118,7 @@ LL | | };
LL | | );
| |_____- in this macro invocation
note: required by a bound in `assert_send`
- --> $DIR/drop-tracking-parent-expression.rs:41:19
+ --> $DIR/drop-tracking-parent-expression.rs:49:19
|
LL | fn assert_send<T: Send>(_thing: T) {}
| ^^^^ required by this bound in `assert_send`
diff --git a/tests/ui/generator/drop-tracking-parent-expression.drop_tracking_mir.stderr b/tests/ui/generator/drop-tracking-parent-expression.drop_tracking_mir.stderr
new file mode 100644
index 000000000..35698a98d
--- /dev/null
+++ b/tests/ui/generator/drop-tracking-parent-expression.drop_tracking_mir.stderr
@@ -0,0 +1,122 @@
+error: generator cannot be sent between threads safely
+ --> $DIR/drop-tracking-parent-expression.rs:27:13
+ |
+LL | assert_send(g);
+ | ^^^^^^^^^^^ generator is not `Send`
+...
+LL | / type_combinations!(
+LL | | // OK
+LL | | copy => { #[derive(Copy, Clone, Default)] pub struct Client; };
+LL | | // NOT OK: MIR borrowck thinks that this is used after the yield, even though
+... |
+LL | | };
+LL | | );
+ | |_____- in this macro invocation
+ |
+ = help: within `[generator@$DIR/drop-tracking-parent-expression.rs:21:21: 21:28]`, the trait `Send` is not implemented for `derived_drop::Client`
+note: generator is not `Send` as this value is used across a yield
+ --> $DIR/drop-tracking-parent-expression.rs:25:22
+ |
+LL | let g = move || match drop($name::Client { ..$name::Client::default() }) {
+ | ------------------------ has type `derived_drop::Client` which is not `Send`
+...
+LL | _ => yield,
+ | ^^^^^ yield occurs here, with `$name::Client::default()` maybe used later
+...
+LL | / type_combinations!(
+LL | | // OK
+LL | | copy => { #[derive(Copy, Clone, Default)] pub struct Client; };
+LL | | // NOT OK: MIR borrowck thinks that this is used after the yield, even though
+... |
+LL | | };
+LL | | );
+ | |_____- in this macro invocation
+note: required by a bound in `assert_send`
+ --> $DIR/drop-tracking-parent-expression.rs:49:19
+ |
+LL | fn assert_send<T: Send>(_thing: T) {}
+ | ^^^^ required by this bound in `assert_send`
+ = note: this error originates in the macro `type_combinations` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: generator cannot be sent between threads safely
+ --> $DIR/drop-tracking-parent-expression.rs:27:13
+ |
+LL | assert_send(g);
+ | ^^^^^^^^^^^ generator is not `Send`
+...
+LL | / type_combinations!(
+LL | | // OK
+LL | | copy => { #[derive(Copy, Clone, Default)] pub struct Client; };
+LL | | // NOT OK: MIR borrowck thinks that this is used after the yield, even though
+... |
+LL | | };
+LL | | );
+ | |_____- in this macro invocation
+ |
+ = help: within `[generator@$DIR/drop-tracking-parent-expression.rs:21:21: 21:28]`, the trait `Send` is not implemented for `significant_drop::Client`
+note: generator is not `Send` as this value is used across a yield
+ --> $DIR/drop-tracking-parent-expression.rs:25:22
+ |
+LL | let g = move || match drop($name::Client { ..$name::Client::default() }) {
+ | ------------------------ has type `significant_drop::Client` which is not `Send`
+...
+LL | _ => yield,
+ | ^^^^^ yield occurs here, with `$name::Client::default()` maybe used later
+...
+LL | / type_combinations!(
+LL | | // OK
+LL | | copy => { #[derive(Copy, Clone, Default)] pub struct Client; };
+LL | | // NOT OK: MIR borrowck thinks that this is used after the yield, even though
+... |
+LL | | };
+LL | | );
+ | |_____- in this macro invocation
+note: required by a bound in `assert_send`
+ --> $DIR/drop-tracking-parent-expression.rs:49:19
+ |
+LL | fn assert_send<T: Send>(_thing: T) {}
+ | ^^^^ required by this bound in `assert_send`
+ = note: this error originates in the macro `type_combinations` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: generator cannot be sent between threads safely
+ --> $DIR/drop-tracking-parent-expression.rs:27:13
+ |
+LL | assert_send(g);
+ | ^^^^^^^^^^^ generator is not `Send`
+...
+LL | / type_combinations!(
+LL | | // OK
+LL | | copy => { #[derive(Copy, Clone, Default)] pub struct Client; };
+LL | | // NOT OK: MIR borrowck thinks that this is used after the yield, even though
+... |
+LL | | };
+LL | | );
+ | |_____- in this macro invocation
+ |
+ = help: within `[generator@$DIR/drop-tracking-parent-expression.rs:21:21: 21:28]`, the trait `Send` is not implemented for `insignificant_dtor::Client`
+note: generator is not `Send` as this value is used across a yield
+ --> $DIR/drop-tracking-parent-expression.rs:25:22
+ |
+LL | let g = move || match drop($name::Client { ..$name::Client::default() }) {
+ | ------------------------ has type `insignificant_dtor::Client` which is not `Send`
+...
+LL | _ => yield,
+ | ^^^^^ yield occurs here, with `$name::Client::default()` maybe used later
+...
+LL | / type_combinations!(
+LL | | // OK
+LL | | copy => { #[derive(Copy, Clone, Default)] pub struct Client; };
+LL | | // NOT OK: MIR borrowck thinks that this is used after the yield, even though
+... |
+LL | | };
+LL | | );
+ | |_____- in this macro invocation
+note: required by a bound in `assert_send`
+ --> $DIR/drop-tracking-parent-expression.rs:49:19
+ |
+LL | fn assert_send<T: Send>(_thing: T) {}
+ | ^^^^ required by this bound in `assert_send`
+ = note: this error originates in the macro `type_combinations` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to 3 previous errors
+
diff --git a/tests/ui/generator/drop-tracking-parent-expression.no_drop_tracking.stderr b/tests/ui/generator/drop-tracking-parent-expression.no_drop_tracking.stderr
new file mode 100644
index 000000000..1a05bfe4f
--- /dev/null
+++ b/tests/ui/generator/drop-tracking-parent-expression.no_drop_tracking.stderr
@@ -0,0 +1,334 @@
+error: generator cannot be sent between threads safely
+ --> $DIR/drop-tracking-parent-expression.rs:27:25
+ |
+LL | assert_send(g);
+ | ^ generator is not `Send`
+...
+LL | / type_combinations!(
+LL | | // OK
+LL | | copy => { #[derive(Copy, Clone, Default)] pub struct Client; };
+LL | | // NOT OK: MIR borrowck thinks that this is used after the yield, even though
+... |
+LL | | };
+LL | | );
+ | |_____- in this macro invocation
+ |
+ = help: within `[generator@$DIR/drop-tracking-parent-expression.rs:21:21: 21:28]`, the trait `Send` is not implemented for `copy::Client`
+note: generator is not `Send` as this value is used across a yield
+ --> $DIR/drop-tracking-parent-expression.rs:25:22
+ |
+LL | let g = move || match drop($name::Client { ..$name::Client::default() }) {
+ | ------------------------ has type `copy::Client` which is not `Send`
+...
+LL | _ => yield,
+ | ^^^^^ yield occurs here, with `$name::Client::default()` maybe used later
+LL | };
+ | - `$name::Client::default()` is later dropped here
+...
+LL | / type_combinations!(
+LL | | // OK
+LL | | copy => { #[derive(Copy, Clone, Default)] pub struct Client; };
+LL | | // NOT OK: MIR borrowck thinks that this is used after the yield, even though
+... |
+LL | | };
+LL | | );
+ | |_____- in this macro invocation
+note: required by a bound in `assert_send`
+ --> $DIR/drop-tracking-parent-expression.rs:49:19
+ |
+LL | fn assert_send<T: Send>(_thing: T) {}
+ | ^^^^ required by this bound in `assert_send`
+ = note: this error originates in the macro `type_combinations` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: generator cannot be sent between threads safely
+ --> $DIR/drop-tracking-parent-expression.rs:40:25
+ |
+LL | assert_send(g);
+ | ^ generator is not `Send`
+...
+LL | / type_combinations!(
+LL | | // OK
+LL | | copy => { #[derive(Copy, Clone, Default)] pub struct Client; };
+LL | | // NOT OK: MIR borrowck thinks that this is used after the yield, even though
+... |
+LL | | };
+LL | | );
+ | |_____- in this macro invocation
+ |
+ = help: within `[generator@$DIR/drop-tracking-parent-expression.rs:37:21: 37:28]`, the trait `Send` is not implemented for `copy::Client`
+note: generator is not `Send` as this value is used across a yield
+ --> $DIR/drop-tracking-parent-expression.rs:38:22
+ |
+LL | let g = move || match drop($name::Client::default()) {
+ | ------------------------ has type `copy::Client` which is not `Send`
+LL | _ => yield,
+ | ^^^^^ yield occurs here, with `$name::Client::default()` maybe used later
+LL | };
+ | - `$name::Client::default()` is later dropped here
+...
+LL | / type_combinations!(
+LL | | // OK
+LL | | copy => { #[derive(Copy, Clone, Default)] pub struct Client; };
+LL | | // NOT OK: MIR borrowck thinks that this is used after the yield, even though
+... |
+LL | | };
+LL | | );
+ | |_____- in this macro invocation
+note: required by a bound in `assert_send`
+ --> $DIR/drop-tracking-parent-expression.rs:49:19
+ |
+LL | fn assert_send<T: Send>(_thing: T) {}
+ | ^^^^ required by this bound in `assert_send`
+ = note: this error originates in the macro `type_combinations` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: generator cannot be sent between threads safely
+ --> $DIR/drop-tracking-parent-expression.rs:27:25
+ |
+LL | assert_send(g);
+ | ^ generator is not `Send`
+...
+LL | / type_combinations!(
+LL | | // OK
+LL | | copy => { #[derive(Copy, Clone, Default)] pub struct Client; };
+LL | | // NOT OK: MIR borrowck thinks that this is used after the yield, even though
+... |
+LL | | };
+LL | | );
+ | |_____- in this macro invocation
+ |
+ = help: within `[generator@$DIR/drop-tracking-parent-expression.rs:21:21: 21:28]`, the trait `Send` is not implemented for `derived_drop::Client`
+note: generator is not `Send` as this value is used across a yield
+ --> $DIR/drop-tracking-parent-expression.rs:25:22
+ |
+LL | let g = move || match drop($name::Client { ..$name::Client::default() }) {
+ | ------------------------ has type `derived_drop::Client` which is not `Send`
+...
+LL | _ => yield,
+ | ^^^^^ yield occurs here, with `$name::Client::default()` maybe used later
+LL | };
+ | - `$name::Client::default()` is later dropped here
+...
+LL | / type_combinations!(
+LL | | // OK
+LL | | copy => { #[derive(Copy, Clone, Default)] pub struct Client; };
+LL | | // NOT OK: MIR borrowck thinks that this is used after the yield, even though
+... |
+LL | | };
+LL | | );
+ | |_____- in this macro invocation
+note: required by a bound in `assert_send`
+ --> $DIR/drop-tracking-parent-expression.rs:49:19
+ |
+LL | fn assert_send<T: Send>(_thing: T) {}
+ | ^^^^ required by this bound in `assert_send`
+ = note: this error originates in the macro `type_combinations` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: generator cannot be sent between threads safely
+ --> $DIR/drop-tracking-parent-expression.rs:40:25
+ |
+LL | assert_send(g);
+ | ^ generator is not `Send`
+...
+LL | / type_combinations!(
+LL | | // OK
+LL | | copy => { #[derive(Copy, Clone, Default)] pub struct Client; };
+LL | | // NOT OK: MIR borrowck thinks that this is used after the yield, even though
+... |
+LL | | };
+LL | | );
+ | |_____- in this macro invocation
+ |
+ = help: within `[generator@$DIR/drop-tracking-parent-expression.rs:37:21: 37:28]`, the trait `Send` is not implemented for `derived_drop::Client`
+note: generator is not `Send` as this value is used across a yield
+ --> $DIR/drop-tracking-parent-expression.rs:38:22
+ |
+LL | let g = move || match drop($name::Client::default()) {
+ | ------------------------ has type `derived_drop::Client` which is not `Send`
+LL | _ => yield,
+ | ^^^^^ yield occurs here, with `$name::Client::default()` maybe used later
+LL | };
+ | - `$name::Client::default()` is later dropped here
+...
+LL | / type_combinations!(
+LL | | // OK
+LL | | copy => { #[derive(Copy, Clone, Default)] pub struct Client; };
+LL | | // NOT OK: MIR borrowck thinks that this is used after the yield, even though
+... |
+LL | | };
+LL | | );
+ | |_____- in this macro invocation
+note: required by a bound in `assert_send`
+ --> $DIR/drop-tracking-parent-expression.rs:49:19
+ |
+LL | fn assert_send<T: Send>(_thing: T) {}
+ | ^^^^ required by this bound in `assert_send`
+ = note: this error originates in the macro `type_combinations` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: generator cannot be sent between threads safely
+ --> $DIR/drop-tracking-parent-expression.rs:27:25
+ |
+LL | assert_send(g);
+ | ^ generator is not `Send`
+...
+LL | / type_combinations!(
+LL | | // OK
+LL | | copy => { #[derive(Copy, Clone, Default)] pub struct Client; };
+LL | | // NOT OK: MIR borrowck thinks that this is used after the yield, even though
+... |
+LL | | };
+LL | | );
+ | |_____- in this macro invocation
+ |
+ = help: within `[generator@$DIR/drop-tracking-parent-expression.rs:21:21: 21:28]`, the trait `Send` is not implemented for `significant_drop::Client`
+note: generator is not `Send` as this value is used across a yield
+ --> $DIR/drop-tracking-parent-expression.rs:25:22
+ |
+LL | let g = move || match drop($name::Client { ..$name::Client::default() }) {
+ | ------------------------ has type `significant_drop::Client` which is not `Send`
+...
+LL | _ => yield,
+ | ^^^^^ yield occurs here, with `$name::Client::default()` maybe used later
+LL | };
+ | - `$name::Client::default()` is later dropped here
+...
+LL | / type_combinations!(
+LL | | // OK
+LL | | copy => { #[derive(Copy, Clone, Default)] pub struct Client; };
+LL | | // NOT OK: MIR borrowck thinks that this is used after the yield, even though
+... |
+LL | | };
+LL | | );
+ | |_____- in this macro invocation
+note: required by a bound in `assert_send`
+ --> $DIR/drop-tracking-parent-expression.rs:49:19
+ |
+LL | fn assert_send<T: Send>(_thing: T) {}
+ | ^^^^ required by this bound in `assert_send`
+ = note: this error originates in the macro `type_combinations` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: generator cannot be sent between threads safely
+ --> $DIR/drop-tracking-parent-expression.rs:40:25
+ |
+LL | assert_send(g);
+ | ^ generator is not `Send`
+...
+LL | / type_combinations!(
+LL | | // OK
+LL | | copy => { #[derive(Copy, Clone, Default)] pub struct Client; };
+LL | | // NOT OK: MIR borrowck thinks that this is used after the yield, even though
+... |
+LL | | };
+LL | | );
+ | |_____- in this macro invocation
+ |
+ = help: within `[generator@$DIR/drop-tracking-parent-expression.rs:37:21: 37:28]`, the trait `Send` is not implemented for `significant_drop::Client`
+note: generator is not `Send` as this value is used across a yield
+ --> $DIR/drop-tracking-parent-expression.rs:38:22
+ |
+LL | let g = move || match drop($name::Client::default()) {
+ | ------------------------ has type `significant_drop::Client` which is not `Send`
+LL | _ => yield,
+ | ^^^^^ yield occurs here, with `$name::Client::default()` maybe used later
+LL | };
+ | - `$name::Client::default()` is later dropped here
+...
+LL | / type_combinations!(
+LL | | // OK
+LL | | copy => { #[derive(Copy, Clone, Default)] pub struct Client; };
+LL | | // NOT OK: MIR borrowck thinks that this is used after the yield, even though
+... |
+LL | | };
+LL | | );
+ | |_____- in this macro invocation
+note: required by a bound in `assert_send`
+ --> $DIR/drop-tracking-parent-expression.rs:49:19
+ |
+LL | fn assert_send<T: Send>(_thing: T) {}
+ | ^^^^ required by this bound in `assert_send`
+ = note: this error originates in the macro `type_combinations` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: generator cannot be sent between threads safely
+ --> $DIR/drop-tracking-parent-expression.rs:27:25
+ |
+LL | assert_send(g);
+ | ^ generator is not `Send`
+...
+LL | / type_combinations!(
+LL | | // OK
+LL | | copy => { #[derive(Copy, Clone, Default)] pub struct Client; };
+LL | | // NOT OK: MIR borrowck thinks that this is used after the yield, even though
+... |
+LL | | };
+LL | | );
+ | |_____- in this macro invocation
+ |
+ = help: within `[generator@$DIR/drop-tracking-parent-expression.rs:21:21: 21:28]`, the trait `Send` is not implemented for `insignificant_dtor::Client`
+note: generator is not `Send` as this value is used across a yield
+ --> $DIR/drop-tracking-parent-expression.rs:25:22
+ |
+LL | let g = move || match drop($name::Client { ..$name::Client::default() }) {
+ | ------------------------ has type `insignificant_dtor::Client` which is not `Send`
+...
+LL | _ => yield,
+ | ^^^^^ yield occurs here, with `$name::Client::default()` maybe used later
+LL | };
+ | - `$name::Client::default()` is later dropped here
+...
+LL | / type_combinations!(
+LL | | // OK
+LL | | copy => { #[derive(Copy, Clone, Default)] pub struct Client; };
+LL | | // NOT OK: MIR borrowck thinks that this is used after the yield, even though
+... |
+LL | | };
+LL | | );
+ | |_____- in this macro invocation
+note: required by a bound in `assert_send`
+ --> $DIR/drop-tracking-parent-expression.rs:49:19
+ |
+LL | fn assert_send<T: Send>(_thing: T) {}
+ | ^^^^ required by this bound in `assert_send`
+ = note: this error originates in the macro `type_combinations` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: generator cannot be sent between threads safely
+ --> $DIR/drop-tracking-parent-expression.rs:40:25
+ |
+LL | assert_send(g);
+ | ^ generator is not `Send`
+...
+LL | / type_combinations!(
+LL | | // OK
+LL | | copy => { #[derive(Copy, Clone, Default)] pub struct Client; };
+LL | | // NOT OK: MIR borrowck thinks that this is used after the yield, even though
+... |
+LL | | };
+LL | | );
+ | |_____- in this macro invocation
+ |
+ = help: within `[generator@$DIR/drop-tracking-parent-expression.rs:37:21: 37:28]`, the trait `Send` is not implemented for `insignificant_dtor::Client`
+note: generator is not `Send` as this value is used across a yield
+ --> $DIR/drop-tracking-parent-expression.rs:38:22
+ |
+LL | let g = move || match drop($name::Client::default()) {
+ | ------------------------ has type `insignificant_dtor::Client` which is not `Send`
+LL | _ => yield,
+ | ^^^^^ yield occurs here, with `$name::Client::default()` maybe used later
+LL | };
+ | - `$name::Client::default()` is later dropped here
+...
+LL | / type_combinations!(
+LL | | // OK
+LL | | copy => { #[derive(Copy, Clone, Default)] pub struct Client; };
+LL | | // NOT OK: MIR borrowck thinks that this is used after the yield, even though
+... |
+LL | | };
+LL | | );
+ | |_____- in this macro invocation
+note: required by a bound in `assert_send`
+ --> $DIR/drop-tracking-parent-expression.rs:49:19
+ |
+LL | fn assert_send<T: Send>(_thing: T) {}
+ | ^^^^ required by this bound in `assert_send`
+ = note: this error originates in the macro `type_combinations` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to 8 previous errors
+
diff --git a/tests/ui/generator/drop-tracking-parent-expression.rs b/tests/ui/generator/drop-tracking-parent-expression.rs
index d40f1b8f6..ed9ac6d11 100644
--- a/tests/ui/generator/drop-tracking-parent-expression.rs
+++ b/tests/ui/generator/drop-tracking-parent-expression.rs
@@ -1,4 +1,7 @@
-// compile-flags: -Zdrop-tracking
+// revisions: no_drop_tracking drop_tracking drop_tracking_mir
+// [drop_tracking] compile-flags: -Zdrop-tracking
+// [drop_tracking_mir] compile-flags: -Zdrop-tracking-mir
+
#![feature(generators, negative_impls, rustc_attrs)]
macro_rules! type_combinations {
@@ -18,13 +21,14 @@ macro_rules! type_combinations {
let g = move || match drop($name::Client { ..$name::Client::default() }) {
//~^ `significant_drop::Client` which is not `Send`
//~| `insignificant_dtor::Client` which is not `Send`
- //~| `derived_drop::Client` which is not `Send`
+ //[no_drop_tracking,drop_tracking]~| `derived_drop::Client` which is not `Send`
_ => yield,
};
assert_send(g);
//~^ ERROR cannot be sent between threads
//~| ERROR cannot be sent between threads
//~| ERROR cannot be sent between threads
+ //[no_drop_tracking]~| ERROR cannot be sent between threads
}
// Simple owned value. This works because the Client is considered moved into `drop`,
@@ -34,6 +38,10 @@ macro_rules! type_combinations {
_ => yield,
};
assert_send(g);
+ //[no_drop_tracking]~^ ERROR cannot be sent between threads
+ //[no_drop_tracking]~| ERROR cannot be sent between threads
+ //[no_drop_tracking]~| ERROR cannot be sent between threads
+ //[no_drop_tracking]~| ERROR cannot be sent between threads
}
)* }
}
diff --git a/tests/ui/generator/drop-tracking-yielding-in-match-guards.rs b/tests/ui/generator/drop-tracking-yielding-in-match-guards.rs
index 646365e43..cbc291701 100644
--- a/tests/ui/generator/drop-tracking-yielding-in-match-guards.rs
+++ b/tests/ui/generator/drop-tracking-yielding-in-match-guards.rs
@@ -1,6 +1,8 @@
// build-pass
// edition:2018
-// compile-flags: -Zdrop-tracking
+// revisions: no_drop_tracking drop_tracking drop_tracking_mir
+// [drop_tracking] compile-flags: -Zdrop-tracking
+// [drop_tracking_mir] compile-flags: -Zdrop-tracking-mir
#![feature(generators)]
diff --git a/tests/ui/generator/dropck.stderr b/tests/ui/generator/dropck.stderr
index 7bb188352..b9a3a124a 100644
--- a/tests/ui/generator/dropck.stderr
+++ b/tests/ui/generator/dropck.stderr
@@ -1,6 +1,9 @@
error[E0597]: `*cell` does not live long enough
--> $DIR/dropck.rs:10:40
|
+LL | let (mut gen, cell);
+ | ---- binding `cell` declared here
+LL | cell = Box::new(RefCell::new(0));
LL | let ref_ = Box::leak(Box::new(Some(cell.borrow_mut())));
| ^^^^^^^^^^^^^^^^^ borrowed value does not live long enough
...
diff --git a/tests/ui/generator/generator-yielding-or-returning-itself.stderr b/tests/ui/generator/generator-yielding-or-returning-itself.stderr
index 8f5d2429a..a26dbf3f2 100644
--- a/tests/ui/generator/generator-yielding-or-returning-itself.stderr
+++ b/tests/ui/generator/generator-yielding-or-returning-itself.stderr
@@ -19,7 +19,7 @@ note: required by a bound in `want_cyclic_generator_return`
--> $DIR/generator-yielding-or-returning-itself.rs:10:36
|
LL | pub fn want_cyclic_generator_return<T>(_: T)
- | ---------------------------- required by a bound in this
+ | ---------------------------- required by a bound in this function
LL | where T: Generator<Yield = (), Return = T>
| ^^^^^^^^^^ required by this bound in `want_cyclic_generator_return`
@@ -44,7 +44,7 @@ note: required by a bound in `want_cyclic_generator_yield`
--> $DIR/generator-yielding-or-returning-itself.rs:23:24
|
LL | pub fn want_cyclic_generator_yield<T>(_: T)
- | --------------------------- required by a bound in this
+ | --------------------------- required by a bound in this function
LL | where T: Generator<Yield = T, Return = ()>
| ^^^^^^^^^ required by this bound in `want_cyclic_generator_yield`
diff --git a/tests/ui/generator/issue-102645.stderr b/tests/ui/generator/issue-102645.stderr
index f6d244029..3f9a4c2f3 100644
--- a/tests/ui/generator/issue-102645.stderr
+++ b/tests/ui/generator/issue-102645.stderr
@@ -4,7 +4,7 @@ error[E0061]: this method takes 1 argument but 0 arguments were supplied
LL | Pin::new(&mut b).resume();
| ^^^^^^-- an argument of type `()` is missing
|
-note: associated function defined here
+note: method defined here
--> $SRC_DIR/core/src/ops/generator.rs:LL:COL
help: provide the argument
|
diff --git a/tests/ui/generator/issue-105084.drop_tracking_mir.stderr b/tests/ui/generator/issue-105084.drop_tracking_mir.stderr
new file mode 100644
index 000000000..cfc0cf7cd
--- /dev/null
+++ b/tests/ui/generator/issue-105084.drop_tracking_mir.stderr
@@ -0,0 +1,51 @@
+error[E0382]: borrow of moved value: `g`
+ --> $DIR/issue-105084.rs:44:14
+ |
+LL | let mut g = || {
+ | ----- move occurs because `g` has type `[generator@$DIR/issue-105084.rs:22:17: 22:19]`, which does not implement the `Copy` trait
+...
+LL | let mut h = copy(g);
+ | - value moved here
+...
+LL | Pin::new(&mut g).resume(());
+ | ^^^^^^ value borrowed here after move
+ |
+note: consider changing this parameter type in function `copy` to borrow instead if owning the value isn't necessary
+ --> $DIR/issue-105084.rs:17:21
+ |
+LL | fn copy<T: Copy>(x: T) -> T {
+ | ---- ^ this parameter takes ownership of the value
+ | |
+ | in this function
+help: consider cloning the value if the performance cost is acceptable
+ |
+LL | let mut h = copy(g.clone());
+ | ++++++++
+
+error[E0277]: the trait bound `Box<(i32, ())>: Copy` is not satisfied in `[generator@$DIR/issue-105084.rs:22:17: 22:19]`
+ --> $DIR/issue-105084.rs:38:17
+ |
+LL | let mut g = || {
+ | -- within this `[generator@$DIR/issue-105084.rs:22:17: 22:19]`
+...
+LL | let mut h = copy(g);
+ | ^^^^ within `[generator@$DIR/issue-105084.rs:22:17: 22:19]`, the trait `Copy` is not implemented for `Box<(i32, ())>`
+ |
+note: generator does not implement `Copy` as this value is used across a yield
+ --> $DIR/issue-105084.rs:28:25
+ |
+LL | let t = box (5, yield);
+ | --------^^^^^-
+ | | |
+ | | yield occurs here, with `box (5, yield)` maybe used later
+ | has type `Box<(i32, ())>` which does not implement `Copy`
+note: required by a bound in `copy`
+ --> $DIR/issue-105084.rs:17:12
+ |
+LL | fn copy<T: Copy>(x: T) -> T {
+ | ^^^^ required by this bound in `copy`
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0277, E0382.
+For more information about an error, try `rustc --explain E0277`.
diff --git a/tests/ui/generator/issue-105084.rs b/tests/ui/generator/issue-105084.rs
new file mode 100644
index 000000000..7c9a97b40
--- /dev/null
+++ b/tests/ui/generator/issue-105084.rs
@@ -0,0 +1,49 @@
+// revisions: no_drop_tracking drop_tracking drop_tracking_mir
+// [drop_tracking] compile-flags: -Zdrop-tracking
+// [drop_tracking_mir] compile-flags: -Zdrop-tracking-mir
+// [no_drop_tracking] known-bug: #105084
+// [no_drop_tracking] check-pass
+// [drop_tracking] known-bug: #105084
+// [drop_tracking] check-pass
+
+#![feature(generators)]
+#![feature(generator_clone)]
+#![feature(generator_trait)]
+#![feature(box_syntax)]
+
+use std::ops::Generator;
+use std::pin::Pin;
+
+fn copy<T: Copy>(x: T) -> T {
+ x
+}
+
+fn main() {
+ let mut g = || {
+ // This is desuraged as 4 stages:
+ // - allocate a `*mut u8` with `exchange_malloc`;
+ // - create a Box that is ignored for trait computations;
+ // - compute fields (and yields);
+ // - assign to `t`.
+ let t = box (5, yield);
+ drop(t);
+ };
+
+ // Allocate the temporary box.
+ Pin::new(&mut g).resume(());
+
+ // The temporary box is in generator locals.
+ // As it is not taken into account for trait computation,
+ // the generator is `Copy`.
+ let mut h = copy(g);
+ //[drop_tracking_mir]~^ ERROR the trait bound `Box<(i32, ())>: Copy` is not satisfied in
+
+ // We now have 2 boxes with the same backing allocation:
+ // one inside `g` and one inside `h`.
+ // Proceed and drop `t` in `g`.
+ Pin::new(&mut g).resume(());
+ //[drop_tracking_mir]~^ ERROR borrow of moved value: `g`
+
+ // Proceed and drop `t` in `h` -> double free!
+ Pin::new(&mut h).resume(());
+}
diff --git a/tests/ui/generator/issue-57017.no_drop_tracking.stderr b/tests/ui/generator/issue-57017.no_drop_tracking.stderr
new file mode 100644
index 000000000..06d2d23b9
--- /dev/null
+++ b/tests/ui/generator/issue-57017.no_drop_tracking.stderr
@@ -0,0 +1,248 @@
+error: generator cannot be sent between threads safely
+ --> $DIR/issue-57017.rs:31:25
+ |
+LL | assert_send(g);
+ | ^ generator is not `Send`
+...
+LL | / type_combinations!(
+LL | | copy => { #[derive(Copy, Clone, Default)] pub struct Client; };
+LL | | derived_drop => { #[derive(Default)] pub struct Client { pub nickname: String } };
+LL | | significant_drop => {
+... |
+LL | | }
+LL | | );
+ | |_____- in this macro invocation
+ |
+ = help: the trait `Sync` is not implemented for `copy::unsync::Client`
+note: generator is not `Send` as this value is used across a yield
+ --> $DIR/issue-57017.rs:29:28
+ |
+LL | let g = move || match drop(&$name::unsync::Client::default()) {
+ | --------------------------------- has type `&copy::unsync::Client` which is not `Send`
+LL | _status => yield,
+ | ^^^^^ yield occurs here, with `&$name::unsync::Client::default()` maybe used later
+LL | };
+ | - `&$name::unsync::Client::default()` is later dropped here
+...
+LL | / type_combinations!(
+LL | | copy => { #[derive(Copy, Clone, Default)] pub struct Client; };
+LL | | derived_drop => { #[derive(Default)] pub struct Client { pub nickname: String } };
+LL | | significant_drop => {
+... |
+LL | | }
+LL | | );
+ | |_____- in this macro invocation
+note: required by a bound in `assert_send`
+ --> $DIR/issue-57017.rs:51:19
+ |
+LL | fn assert_send<T: Send>(_thing: T) {}
+ | ^^^^ required by this bound in `assert_send`
+ = note: this error originates in the macro `type_combinations` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: generator cannot be sent between threads safely
+ --> $DIR/issue-57017.rs:43:25
+ |
+LL | assert_send(g);
+ | ^ generator is not `Send`
+...
+LL | / type_combinations!(
+LL | | copy => { #[derive(Copy, Clone, Default)] pub struct Client; };
+LL | | derived_drop => { #[derive(Default)] pub struct Client { pub nickname: String } };
+LL | | significant_drop => {
+... |
+LL | | }
+LL | | );
+ | |_____- in this macro invocation
+ |
+ = help: within `[generator@$DIR/issue-57017.rs:40:21: 40:28]`, the trait `Send` is not implemented for `copy::unsend::Client`
+note: generator is not `Send` as this value is used across a yield
+ --> $DIR/issue-57017.rs:41:28
+ |
+LL | let g = move || match drop($name::unsend::Client::default()) {
+ | -------------------------------- has type `copy::unsend::Client` which is not `Send`
+LL | _status => yield,
+ | ^^^^^ yield occurs here, with `$name::unsend::Client::default()` maybe used later
+LL | };
+ | - `$name::unsend::Client::default()` is later dropped here
+...
+LL | / type_combinations!(
+LL | | copy => { #[derive(Copy, Clone, Default)] pub struct Client; };
+LL | | derived_drop => { #[derive(Default)] pub struct Client { pub nickname: String } };
+LL | | significant_drop => {
+... |
+LL | | }
+LL | | );
+ | |_____- in this macro invocation
+note: required by a bound in `assert_send`
+ --> $DIR/issue-57017.rs:51:19
+ |
+LL | fn assert_send<T: Send>(_thing: T) {}
+ | ^^^^ required by this bound in `assert_send`
+ = note: this error originates in the macro `type_combinations` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: generator cannot be sent between threads safely
+ --> $DIR/issue-57017.rs:31:25
+ |
+LL | assert_send(g);
+ | ^ generator is not `Send`
+...
+LL | / type_combinations!(
+LL | | copy => { #[derive(Copy, Clone, Default)] pub struct Client; };
+LL | | derived_drop => { #[derive(Default)] pub struct Client { pub nickname: String } };
+LL | | significant_drop => {
+... |
+LL | | }
+LL | | );
+ | |_____- in this macro invocation
+ |
+ = help: the trait `Sync` is not implemented for `derived_drop::unsync::Client`
+note: generator is not `Send` as this value is used across a yield
+ --> $DIR/issue-57017.rs:29:28
+ |
+LL | let g = move || match drop(&$name::unsync::Client::default()) {
+ | --------------------------------- has type `&derived_drop::unsync::Client` which is not `Send`
+LL | _status => yield,
+ | ^^^^^ yield occurs here, with `&$name::unsync::Client::default()` maybe used later
+LL | };
+ | - `&$name::unsync::Client::default()` is later dropped here
+...
+LL | / type_combinations!(
+LL | | copy => { #[derive(Copy, Clone, Default)] pub struct Client; };
+LL | | derived_drop => { #[derive(Default)] pub struct Client { pub nickname: String } };
+LL | | significant_drop => {
+... |
+LL | | }
+LL | | );
+ | |_____- in this macro invocation
+note: required by a bound in `assert_send`
+ --> $DIR/issue-57017.rs:51:19
+ |
+LL | fn assert_send<T: Send>(_thing: T) {}
+ | ^^^^ required by this bound in `assert_send`
+ = note: this error originates in the macro `type_combinations` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: generator cannot be sent between threads safely
+ --> $DIR/issue-57017.rs:43:25
+ |
+LL | assert_send(g);
+ | ^ generator is not `Send`
+...
+LL | / type_combinations!(
+LL | | copy => { #[derive(Copy, Clone, Default)] pub struct Client; };
+LL | | derived_drop => { #[derive(Default)] pub struct Client { pub nickname: String } };
+LL | | significant_drop => {
+... |
+LL | | }
+LL | | );
+ | |_____- in this macro invocation
+ |
+ = help: within `[generator@$DIR/issue-57017.rs:40:21: 40:28]`, the trait `Send` is not implemented for `derived_drop::unsend::Client`
+note: generator is not `Send` as this value is used across a yield
+ --> $DIR/issue-57017.rs:41:28
+ |
+LL | let g = move || match drop($name::unsend::Client::default()) {
+ | -------------------------------- has type `derived_drop::unsend::Client` which is not `Send`
+LL | _status => yield,
+ | ^^^^^ yield occurs here, with `$name::unsend::Client::default()` maybe used later
+LL | };
+ | - `$name::unsend::Client::default()` is later dropped here
+...
+LL | / type_combinations!(
+LL | | copy => { #[derive(Copy, Clone, Default)] pub struct Client; };
+LL | | derived_drop => { #[derive(Default)] pub struct Client { pub nickname: String } };
+LL | | significant_drop => {
+... |
+LL | | }
+LL | | );
+ | |_____- in this macro invocation
+note: required by a bound in `assert_send`
+ --> $DIR/issue-57017.rs:51:19
+ |
+LL | fn assert_send<T: Send>(_thing: T) {}
+ | ^^^^ required by this bound in `assert_send`
+ = note: this error originates in the macro `type_combinations` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: generator cannot be sent between threads safely
+ --> $DIR/issue-57017.rs:31:25
+ |
+LL | assert_send(g);
+ | ^ generator is not `Send`
+...
+LL | / type_combinations!(
+LL | | copy => { #[derive(Copy, Clone, Default)] pub struct Client; };
+LL | | derived_drop => { #[derive(Default)] pub struct Client { pub nickname: String } };
+LL | | significant_drop => {
+... |
+LL | | }
+LL | | );
+ | |_____- in this macro invocation
+ |
+ = help: the trait `Sync` is not implemented for `significant_drop::unsync::Client`
+note: generator is not `Send` as this value is used across a yield
+ --> $DIR/issue-57017.rs:29:28
+ |
+LL | let g = move || match drop(&$name::unsync::Client::default()) {
+ | --------------------------------- has type `&significant_drop::unsync::Client` which is not `Send`
+LL | _status => yield,
+ | ^^^^^ yield occurs here, with `&$name::unsync::Client::default()` maybe used later
+LL | };
+ | - `&$name::unsync::Client::default()` is later dropped here
+...
+LL | / type_combinations!(
+LL | | copy => { #[derive(Copy, Clone, Default)] pub struct Client; };
+LL | | derived_drop => { #[derive(Default)] pub struct Client { pub nickname: String } };
+LL | | significant_drop => {
+... |
+LL | | }
+LL | | );
+ | |_____- in this macro invocation
+note: required by a bound in `assert_send`
+ --> $DIR/issue-57017.rs:51:19
+ |
+LL | fn assert_send<T: Send>(_thing: T) {}
+ | ^^^^ required by this bound in `assert_send`
+ = note: this error originates in the macro `type_combinations` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: generator cannot be sent between threads safely
+ --> $DIR/issue-57017.rs:43:25
+ |
+LL | assert_send(g);
+ | ^ generator is not `Send`
+...
+LL | / type_combinations!(
+LL | | copy => { #[derive(Copy, Clone, Default)] pub struct Client; };
+LL | | derived_drop => { #[derive(Default)] pub struct Client { pub nickname: String } };
+LL | | significant_drop => {
+... |
+LL | | }
+LL | | );
+ | |_____- in this macro invocation
+ |
+ = help: within `[generator@$DIR/issue-57017.rs:40:21: 40:28]`, the trait `Send` is not implemented for `significant_drop::unsend::Client`
+note: generator is not `Send` as this value is used across a yield
+ --> $DIR/issue-57017.rs:41:28
+ |
+LL | let g = move || match drop($name::unsend::Client::default()) {
+ | -------------------------------- has type `significant_drop::unsend::Client` which is not `Send`
+LL | _status => yield,
+ | ^^^^^ yield occurs here, with `$name::unsend::Client::default()` maybe used later
+LL | };
+ | - `$name::unsend::Client::default()` is later dropped here
+...
+LL | / type_combinations!(
+LL | | copy => { #[derive(Copy, Clone, Default)] pub struct Client; };
+LL | | derived_drop => { #[derive(Default)] pub struct Client { pub nickname: String } };
+LL | | significant_drop => {
+... |
+LL | | }
+LL | | );
+ | |_____- in this macro invocation
+note: required by a bound in `assert_send`
+ --> $DIR/issue-57017.rs:51:19
+ |
+LL | fn assert_send<T: Send>(_thing: T) {}
+ | ^^^^ required by this bound in `assert_send`
+ = note: this error originates in the macro `type_combinations` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to 6 previous errors
+
diff --git a/tests/ui/generator/issue-57017.rs b/tests/ui/generator/issue-57017.rs
index c0bde3b44..03b00ac99 100644
--- a/tests/ui/generator/issue-57017.rs
+++ b/tests/ui/generator/issue-57017.rs
@@ -1,5 +1,9 @@
-// build-pass
-// compile-flags: -Zdrop-tracking
+// revisions: no_drop_tracking drop_tracking drop_tracking_mir
+// [drop_tracking] compile-flags: -Zdrop-tracking
+// [drop_tracking_mir] compile-flags: -Zdrop-tracking-mir
+// [drop_tracking] build-pass
+// [drop_tracking_mir] build-pass
+
#![feature(generators, negative_impls)]
macro_rules! type_combinations {
@@ -25,6 +29,9 @@ macro_rules! type_combinations {
_status => yield,
};
assert_send(g);
+ //[no_drop_tracking]~^ ERROR generator cannot be sent between threads safely
+ //[no_drop_tracking]~| ERROR generator cannot be sent between threads safely
+ //[no_drop_tracking]~| ERROR generator cannot be sent between threads safely
}
// This tests that `Client` is properly considered to be dropped after moving it into the
@@ -34,6 +41,9 @@ macro_rules! type_combinations {
_status => yield,
};
assert_send(g);
+ //[no_drop_tracking]~^ ERROR generator cannot be sent between threads safely
+ //[no_drop_tracking]~| ERROR generator cannot be sent between threads safely
+ //[no_drop_tracking]~| ERROR generator cannot be sent between threads safely
}
)* }
}
diff --git a/tests/ui/generator/issue-57478.no_drop_tracking.stderr b/tests/ui/generator/issue-57478.no_drop_tracking.stderr
new file mode 100644
index 000000000..612dd9c37
--- /dev/null
+++ b/tests/ui/generator/issue-57478.no_drop_tracking.stderr
@@ -0,0 +1,31 @@
+error: generator cannot be sent between threads safely
+ --> $DIR/issue-57478.rs:13:17
+ |
+LL | assert_send(|| {
+ | _________________^
+LL | |
+LL | | let guard = Foo;
+LL | | drop(guard);
+LL | | yield;
+LL | | })
+ | |_____^ generator is not `Send`
+ |
+ = help: within `[generator@$DIR/issue-57478.rs:13:17: 13:19]`, the trait `Send` is not implemented for `Foo`
+note: generator is not `Send` as this value is used across a yield
+ --> $DIR/issue-57478.rs:17:9
+ |
+LL | let guard = Foo;
+ | ----- has type `Foo` which is not `Send`
+LL | drop(guard);
+LL | yield;
+ | ^^^^^ yield occurs here, with `guard` maybe used later
+LL | })
+ | - `guard` is later dropped here
+note: required by a bound in `assert_send`
+ --> $DIR/issue-57478.rs:21:19
+ |
+LL | fn assert_send<T: Send>(_: T) {}
+ | ^^^^ required by this bound in `assert_send`
+
+error: aborting due to previous error
+
diff --git a/tests/ui/generator/issue-57478.rs b/tests/ui/generator/issue-57478.rs
index 91407ea18..3c23b5992 100644
--- a/tests/ui/generator/issue-57478.rs
+++ b/tests/ui/generator/issue-57478.rs
@@ -1,5 +1,8 @@
-// check-pass
-// compile-flags: -Zdrop-tracking
+// revisions: no_drop_tracking drop_tracking drop_tracking_mir
+// [drop_tracking] compile-flags: -Zdrop-tracking
+// [drop_tracking_mir] compile-flags: -Zdrop-tracking-mir
+// [drop_tracking] check-pass
+// [drop_tracking_mir] check-pass
#![feature(negative_impls, generators)]
@@ -8,6 +11,7 @@ impl !Send for Foo {}
fn main() {
assert_send(|| {
+ //[no_drop_tracking]~^ ERROR generator cannot be sent between threads safely
let guard = Foo;
drop(guard);
yield;
diff --git a/tests/ui/generator/issue-68112.stderr b/tests/ui/generator/issue-68112.drop_tracking.stderr
index eb99d42c9..282eac1b6 100644
--- a/tests/ui/generator/issue-68112.stderr
+++ b/tests/ui/generator/issue-68112.drop_tracking.stderr
@@ -1,12 +1,13 @@
error: generator cannot be sent between threads safely
- --> $DIR/issue-68112.rs:40:18
+ --> $DIR/issue-68112.rs:43:18
|
LL | require_send(send_gen);
| ^^^^^^^^ generator is not `Send`
|
= help: the trait `Sync` is not implemented for `RefCell<i32>`
+ = note: if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` instead
note: generator is not `Send` as this value is used across a yield
- --> $DIR/issue-68112.rs:36:9
+ --> $DIR/issue-68112.rs:39:9
|
LL | let _non_send_gen = make_non_send_generator();
| ------------- has type `impl Generator<Return = Arc<RefCell<i32>>>` which is not `Send`
@@ -17,13 +18,13 @@ LL | yield;
LL | };
| - `_non_send_gen` is later dropped here
note: required by a bound in `require_send`
- --> $DIR/issue-68112.rs:22:25
+ --> $DIR/issue-68112.rs:25:25
|
LL | fn require_send(_: impl Send) {}
| ^^^^ required by this bound in `require_send`
error[E0277]: `RefCell<i32>` cannot be shared between threads safely
- --> $DIR/issue-68112.rs:63:18
+ --> $DIR/issue-68112.rs:67:18
|
LL | require_send(send_gen);
| ------------ ^^^^^^^^ `RefCell<i32>` cannot be shared between threads safely
@@ -31,30 +32,31 @@ LL | require_send(send_gen);
| required by a bound introduced by this call
|
= help: the trait `Sync` is not implemented for `RefCell<i32>`
+ = note: if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` instead
= note: required for `Arc<RefCell<i32>>` to implement `Send`
note: required because it's used within this generator
- --> $DIR/issue-68112.rs:48:5
+ --> $DIR/issue-68112.rs:52:5
|
LL | || {
| ^^
note: required because it appears within the type `impl Generator<Return = Arc<RefCell<i32>>>`
- --> $DIR/issue-68112.rs:45:30
+ --> $DIR/issue-68112.rs:49:30
|
LL | pub fn make_gen2<T>(t: T) -> impl Generator<Return = T> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
note: required because it appears within the type `impl Generator<Return = Arc<RefCell<i32>>>`
- --> $DIR/issue-68112.rs:53:34
+ --> $DIR/issue-68112.rs:57:34
|
LL | fn make_non_send_generator2() -> impl Generator<Return = Arc<RefCell<i32>>> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: required because it captures the following types: `impl Generator<Return = Arc<RefCell<i32>>>`, `()`
note: required because it's used within this generator
- --> $DIR/issue-68112.rs:59:20
+ --> $DIR/issue-68112.rs:63:20
|
LL | let send_gen = || {
| ^^
note: required by a bound in `require_send`
- --> $DIR/issue-68112.rs:22:25
+ --> $DIR/issue-68112.rs:25:25
|
LL | fn require_send(_: impl Send) {}
| ^^^^ required by this bound in `require_send`
diff --git a/tests/ui/generator/issue-68112.drop_tracking_mir.stderr b/tests/ui/generator/issue-68112.drop_tracking_mir.stderr
new file mode 100644
index 000000000..a83522b71
--- /dev/null
+++ b/tests/ui/generator/issue-68112.drop_tracking_mir.stderr
@@ -0,0 +1,61 @@
+error: generator cannot be sent between threads safely
+ --> $DIR/issue-68112.rs:43:5
+ |
+LL | require_send(send_gen);
+ | ^^^^^^^^^^^^ generator is not `Send`
+ |
+ = help: the trait `Sync` is not implemented for `RefCell<i32>`
+ = note: if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` instead
+note: generator is not `Send` as this value is used across a yield
+ --> $DIR/issue-68112.rs:39:9
+ |
+LL | let _non_send_gen = make_non_send_generator();
+ | ------------- has type `impl Generator<Return = Arc<RefCell<i32>>>` which is not `Send`
+LL |
+LL | yield;
+ | ^^^^^ yield occurs here, with `_non_send_gen` maybe used later
+note: required by a bound in `require_send`
+ --> $DIR/issue-68112.rs:25:25
+ |
+LL | fn require_send(_: impl Send) {}
+ | ^^^^ required by this bound in `require_send`
+
+error[E0277]: `RefCell<i32>` cannot be shared between threads safely
+ --> $DIR/issue-68112.rs:67:5
+ |
+LL | require_send(send_gen);
+ | ^^^^^^^^^^^^ `RefCell<i32>` cannot be shared between threads safely
+ |
+ = help: the trait `Sync` is not implemented for `RefCell<i32>`
+ = note: if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` instead
+ = note: required for `Arc<RefCell<i32>>` to implement `Send`
+note: required because it's used within this generator
+ --> $DIR/issue-68112.rs:52:5
+ |
+LL | || {
+ | ^^
+note: required because it appears within the type `impl Generator<Return = Arc<RefCell<i32>>>`
+ --> $DIR/issue-68112.rs:49:30
+ |
+LL | pub fn make_gen2<T>(t: T) -> impl Generator<Return = T> {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+note: required because it appears within the type `impl Generator<Return = Arc<RefCell<i32>>>`
+ --> $DIR/issue-68112.rs:57:34
+ |
+LL | fn make_non_send_generator2() -> impl Generator<Return = Arc<RefCell<i32>>> {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ = note: required because it captures the following types: `impl Generator<Return = Arc<RefCell<i32>>>`
+note: required because it's used within this generator
+ --> $DIR/issue-68112.rs:63:20
+ |
+LL | let send_gen = || {
+ | ^^
+note: required by a bound in `require_send`
+ --> $DIR/issue-68112.rs:25:25
+ |
+LL | fn require_send(_: impl Send) {}
+ | ^^^^ required by this bound in `require_send`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/generator/issue-68112.no_drop_tracking.stderr b/tests/ui/generator/issue-68112.no_drop_tracking.stderr
new file mode 100644
index 000000000..282eac1b6
--- /dev/null
+++ b/tests/ui/generator/issue-68112.no_drop_tracking.stderr
@@ -0,0 +1,66 @@
+error: generator cannot be sent between threads safely
+ --> $DIR/issue-68112.rs:43:18
+ |
+LL | require_send(send_gen);
+ | ^^^^^^^^ generator is not `Send`
+ |
+ = help: the trait `Sync` is not implemented for `RefCell<i32>`
+ = note: if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` instead
+note: generator is not `Send` as this value is used across a yield
+ --> $DIR/issue-68112.rs:39:9
+ |
+LL | let _non_send_gen = make_non_send_generator();
+ | ------------- has type `impl Generator<Return = Arc<RefCell<i32>>>` which is not `Send`
+LL |
+LL | yield;
+ | ^^^^^ yield occurs here, with `_non_send_gen` maybe used later
+...
+LL | };
+ | - `_non_send_gen` is later dropped here
+note: required by a bound in `require_send`
+ --> $DIR/issue-68112.rs:25:25
+ |
+LL | fn require_send(_: impl Send) {}
+ | ^^^^ required by this bound in `require_send`
+
+error[E0277]: `RefCell<i32>` cannot be shared between threads safely
+ --> $DIR/issue-68112.rs:67:18
+ |
+LL | require_send(send_gen);
+ | ------------ ^^^^^^^^ `RefCell<i32>` cannot be shared between threads safely
+ | |
+ | required by a bound introduced by this call
+ |
+ = help: the trait `Sync` is not implemented for `RefCell<i32>`
+ = note: if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` instead
+ = note: required for `Arc<RefCell<i32>>` to implement `Send`
+note: required because it's used within this generator
+ --> $DIR/issue-68112.rs:52:5
+ |
+LL | || {
+ | ^^
+note: required because it appears within the type `impl Generator<Return = Arc<RefCell<i32>>>`
+ --> $DIR/issue-68112.rs:49:30
+ |
+LL | pub fn make_gen2<T>(t: T) -> impl Generator<Return = T> {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+note: required because it appears within the type `impl Generator<Return = Arc<RefCell<i32>>>`
+ --> $DIR/issue-68112.rs:57:34
+ |
+LL | fn make_non_send_generator2() -> impl Generator<Return = Arc<RefCell<i32>>> {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ = note: required because it captures the following types: `impl Generator<Return = Arc<RefCell<i32>>>`, `()`
+note: required because it's used within this generator
+ --> $DIR/issue-68112.rs:63:20
+ |
+LL | let send_gen = || {
+ | ^^
+note: required by a bound in `require_send`
+ --> $DIR/issue-68112.rs:25:25
+ |
+LL | fn require_send(_: impl Send) {}
+ | ^^^^ required by this bound in `require_send`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/generator/issue-68112.rs b/tests/ui/generator/issue-68112.rs
index 21026f45c..48b53b769 100644
--- a/tests/ui/generator/issue-68112.rs
+++ b/tests/ui/generator/issue-68112.rs
@@ -1,3 +1,6 @@
+// revisions: no_drop_tracking drop_tracking drop_tracking_mir
+// [drop_tracking] compile-flags: -Zdrop-tracking
+// [drop_tracking_mir] compile-flags: -Zdrop-tracking-mir
#![feature(generators, generator_trait)]
use std::{
@@ -8,7 +11,7 @@ use std::{
};
pub struct Ready<T>(Option<T>);
-impl<T> Generator<()> for Ready<T> {
+impl<T: Unpin> Generator<()> for Ready<T> {
type Return = T;
type Yield = ();
fn resume(mut self: Pin<&mut Self>, _args: ()) -> GeneratorState<(), T> {
@@ -36,10 +39,11 @@ fn test1() {
yield;
//~^ NOTE yield occurs here
//~| NOTE value is used across a yield
- }; //~ NOTE later dropped here
+ }; //[no_drop_tracking,drop_tracking]~ NOTE later dropped here
require_send(send_gen);
//~^ ERROR generator cannot be sent between threads
//~| NOTE not `Send`
+ //~| NOTE use `std::sync::RwLock` instead
}
pub fn make_gen2<T>(t: T) -> impl Generator<Return = T> {
@@ -64,8 +68,9 @@ fn test2() {
//~^ ERROR `RefCell<i32>` cannot be shared between threads safely
//~| NOTE `RefCell<i32>` cannot be shared between threads safely
//~| NOTE required for
- //~| NOTE required by a bound introduced by this call
+ //[no_drop_tracking,drop_tracking]~| NOTE required by a bound introduced by this call
//~| NOTE captures the following types
+ //~| NOTE use `std::sync::RwLock` instead
}
fn main() {}
diff --git a/tests/ui/generator/issue-93161.rs b/tests/ui/generator/issue-93161.rs
index 92305609c..8d3f7c62f 100644
--- a/tests/ui/generator/issue-93161.rs
+++ b/tests/ui/generator/issue-93161.rs
@@ -1,6 +1,8 @@
+// revisions: no_drop_tracking drop_tracking drop_tracking_mir
+// [drop_tracking] compile-flags: -Zdrop-tracking
+// [drop_tracking_mir] compile-flags: -Zdrop-tracking-mir
// edition:2021
// run-pass
-// compile-flags: -Zdrop-tracking
#![feature(never_type)]
diff --git a/tests/ui/generator/not-send-sync.drop_tracking.stderr b/tests/ui/generator/not-send-sync.drop_tracking.stderr
new file mode 100644
index 000000000..718fd4224
--- /dev/null
+++ b/tests/ui/generator/not-send-sync.drop_tracking.stderr
@@ -0,0 +1,60 @@
+error: generator cannot be shared between threads safely
+ --> $DIR/not-send-sync.rs:17:17
+ |
+LL | assert_sync(|| {
+ | _________________^
+LL | |
+LL | | let a = NotSync;
+LL | | yield;
+LL | | drop(a);
+LL | | });
+ | |_____^ generator is not `Sync`
+ |
+ = help: within `[generator@$DIR/not-send-sync.rs:17:17: 17:19]`, the trait `Sync` is not implemented for `NotSync`
+note: generator is not `Sync` as this value is used across a yield
+ --> $DIR/not-send-sync.rs:20:9
+ |
+LL | let a = NotSync;
+ | - has type `NotSync` which is not `Sync`
+LL | yield;
+ | ^^^^^ yield occurs here, with `a` maybe used later
+LL | drop(a);
+LL | });
+ | - `a` is later dropped here
+note: required by a bound in `assert_sync`
+ --> $DIR/not-send-sync.rs:14:23
+ |
+LL | fn assert_sync<T: Sync>(_: T) {}
+ | ^^^^ required by this bound in `assert_sync`
+
+error: generator cannot be sent between threads safely
+ --> $DIR/not-send-sync.rs:24:17
+ |
+LL | assert_send(|| {
+ | _________________^
+LL | |
+LL | | let a = NotSend;
+LL | | yield;
+LL | | drop(a);
+LL | | });
+ | |_____^ generator is not `Send`
+ |
+ = help: within `[generator@$DIR/not-send-sync.rs:24:17: 24:19]`, the trait `Send` is not implemented for `NotSend`
+note: generator is not `Send` as this value is used across a yield
+ --> $DIR/not-send-sync.rs:27:9
+ |
+LL | let a = NotSend;
+ | - has type `NotSend` which is not `Send`
+LL | yield;
+ | ^^^^^ yield occurs here, with `a` maybe used later
+LL | drop(a);
+LL | });
+ | - `a` is later dropped here
+note: required by a bound in `assert_send`
+ --> $DIR/not-send-sync.rs:15:23
+ |
+LL | fn assert_send<T: Send>(_: T) {}
+ | ^^^^ required by this bound in `assert_send`
+
+error: aborting due to 2 previous errors
+
diff --git a/tests/ui/generator/not-send-sync.drop_tracking_mir.stderr b/tests/ui/generator/not-send-sync.drop_tracking_mir.stderr
new file mode 100644
index 000000000..66f01ae37
--- /dev/null
+++ b/tests/ui/generator/not-send-sync.drop_tracking_mir.stderr
@@ -0,0 +1,42 @@
+error: generator cannot be shared between threads safely
+ --> $DIR/not-send-sync.rs:17:5
+ |
+LL | assert_sync(|| {
+ | ^^^^^^^^^^^ generator is not `Sync`
+ |
+ = help: within `[generator@$DIR/not-send-sync.rs:17:17: 17:19]`, the trait `Sync` is not implemented for `NotSync`
+note: generator is not `Sync` as this value is used across a yield
+ --> $DIR/not-send-sync.rs:20:9
+ |
+LL | let a = NotSync;
+ | - has type `NotSync` which is not `Sync`
+LL | yield;
+ | ^^^^^ yield occurs here, with `a` maybe used later
+note: required by a bound in `assert_sync`
+ --> $DIR/not-send-sync.rs:14:23
+ |
+LL | fn assert_sync<T: Sync>(_: T) {}
+ | ^^^^ required by this bound in `assert_sync`
+
+error: generator cannot be sent between threads safely
+ --> $DIR/not-send-sync.rs:24:5
+ |
+LL | assert_send(|| {
+ | ^^^^^^^^^^^ generator is not `Send`
+ |
+ = help: within `[generator@$DIR/not-send-sync.rs:24:17: 24:19]`, the trait `Send` is not implemented for `NotSend`
+note: generator is not `Send` as this value is used across a yield
+ --> $DIR/not-send-sync.rs:27:9
+ |
+LL | let a = NotSend;
+ | - has type `NotSend` which is not `Send`
+LL | yield;
+ | ^^^^^ yield occurs here, with `a` maybe used later
+note: required by a bound in `assert_send`
+ --> $DIR/not-send-sync.rs:15:23
+ |
+LL | fn assert_send<T: Send>(_: T) {}
+ | ^^^^ required by this bound in `assert_send`
+
+error: aborting due to 2 previous errors
+
diff --git a/tests/ui/generator/not-send-sync.no_drop_tracking.stderr b/tests/ui/generator/not-send-sync.no_drop_tracking.stderr
new file mode 100644
index 000000000..718fd4224
--- /dev/null
+++ b/tests/ui/generator/not-send-sync.no_drop_tracking.stderr
@@ -0,0 +1,60 @@
+error: generator cannot be shared between threads safely
+ --> $DIR/not-send-sync.rs:17:17
+ |
+LL | assert_sync(|| {
+ | _________________^
+LL | |
+LL | | let a = NotSync;
+LL | | yield;
+LL | | drop(a);
+LL | | });
+ | |_____^ generator is not `Sync`
+ |
+ = help: within `[generator@$DIR/not-send-sync.rs:17:17: 17:19]`, the trait `Sync` is not implemented for `NotSync`
+note: generator is not `Sync` as this value is used across a yield
+ --> $DIR/not-send-sync.rs:20:9
+ |
+LL | let a = NotSync;
+ | - has type `NotSync` which is not `Sync`
+LL | yield;
+ | ^^^^^ yield occurs here, with `a` maybe used later
+LL | drop(a);
+LL | });
+ | - `a` is later dropped here
+note: required by a bound in `assert_sync`
+ --> $DIR/not-send-sync.rs:14:23
+ |
+LL | fn assert_sync<T: Sync>(_: T) {}
+ | ^^^^ required by this bound in `assert_sync`
+
+error: generator cannot be sent between threads safely
+ --> $DIR/not-send-sync.rs:24:17
+ |
+LL | assert_send(|| {
+ | _________________^
+LL | |
+LL | | let a = NotSend;
+LL | | yield;
+LL | | drop(a);
+LL | | });
+ | |_____^ generator is not `Send`
+ |
+ = help: within `[generator@$DIR/not-send-sync.rs:24:17: 24:19]`, the trait `Send` is not implemented for `NotSend`
+note: generator is not `Send` as this value is used across a yield
+ --> $DIR/not-send-sync.rs:27:9
+ |
+LL | let a = NotSend;
+ | - has type `NotSend` which is not `Send`
+LL | yield;
+ | ^^^^^ yield occurs here, with `a` maybe used later
+LL | drop(a);
+LL | });
+ | - `a` is later dropped here
+note: required by a bound in `assert_send`
+ --> $DIR/not-send-sync.rs:15:23
+ |
+LL | fn assert_send<T: Send>(_: T) {}
+ | ^^^^ required by this bound in `assert_send`
+
+error: aborting due to 2 previous errors
+
diff --git a/tests/ui/generator/not-send-sync.rs b/tests/ui/generator/not-send-sync.rs
index 8ca5565fb..8794db452 100644
--- a/tests/ui/generator/not-send-sync.rs
+++ b/tests/ui/generator/not-send-sync.rs
@@ -1,6 +1,14 @@
+// revisions: no_drop_tracking drop_tracking drop_tracking_mir
+// [drop_tracking] compile-flags: -Zdrop-tracking
+// [drop_tracking_mir] compile-flags: -Zdrop-tracking-mir
#![feature(generators)]
+#![feature(negative_impls)]
-use std::cell::Cell;
+struct NotSend;
+struct NotSync;
+
+impl !Send for NotSend {}
+impl !Sync for NotSync {}
fn main() {
fn assert_sync<T: Sync>(_: T) {}
@@ -8,14 +16,15 @@ fn main() {
assert_sync(|| {
//~^ ERROR: generator cannot be shared between threads safely
- let a = Cell::new(2);
+ let a = NotSync;
yield;
+ drop(a);
});
- let a = Cell::new(2);
assert_send(|| {
- //~^ ERROR: E0277
- drop(&a);
+ //~^ ERROR: generator cannot be sent between threads safely
+ let a = NotSend;
yield;
+ drop(a);
});
}
diff --git a/tests/ui/generator/not-send-sync.stderr b/tests/ui/generator/not-send-sync.stderr
deleted file mode 100644
index a821c57b9..000000000
--- a/tests/ui/generator/not-send-sync.stderr
+++ /dev/null
@@ -1,56 +0,0 @@
-error[E0277]: `Cell<i32>` cannot be shared between threads safely
- --> $DIR/not-send-sync.rs:16:17
- |
-LL | assert_send(|| {
- | _____-----------_^
- | | |
- | | required by a bound introduced by this call
-LL | |
-LL | | drop(&a);
-LL | | yield;
-LL | | });
- | |_____^ `Cell<i32>` cannot be shared between threads safely
- |
- = help: the trait `Sync` is not implemented for `Cell<i32>`
- = note: required for `&Cell<i32>` to implement `Send`
-note: required because it's used within this generator
- --> $DIR/not-send-sync.rs:16:17
- |
-LL | assert_send(|| {
- | ^^
-note: required by a bound in `assert_send`
- --> $DIR/not-send-sync.rs:7:23
- |
-LL | fn assert_send<T: Send>(_: T) {}
- | ^^^^ required by this bound in `assert_send`
-
-error: generator cannot be shared between threads safely
- --> $DIR/not-send-sync.rs:9:17
- |
-LL | assert_sync(|| {
- | _________________^
-LL | |
-LL | | let a = Cell::new(2);
-LL | | yield;
-LL | | });
- | |_____^ generator is not `Sync`
- |
- = help: within `[generator@$DIR/not-send-sync.rs:9:17: 9:19]`, the trait `Sync` is not implemented for `Cell<i32>`
-note: generator is not `Sync` as this value is used across a yield
- --> $DIR/not-send-sync.rs:12:9
- |
-LL | let a = Cell::new(2);
- | - has type `Cell<i32>` which is not `Sync`
-LL | yield;
- | ^^^^^ yield occurs here, with `a` maybe used later
-LL | });
- | - `a` is later dropped here
-note: required by a bound in `assert_sync`
- --> $DIR/not-send-sync.rs:6:23
- |
-LL | fn assert_sync<T: Sync>(_: T) {}
- | ^^^^ required by this bound in `assert_sync`
-
-error: aborting due to 2 previous errors
-
-For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/generator/parent-expression.drop_tracking.stderr b/tests/ui/generator/parent-expression.drop_tracking.stderr
new file mode 100644
index 000000000..ef489088b
--- /dev/null
+++ b/tests/ui/generator/parent-expression.drop_tracking.stderr
@@ -0,0 +1,128 @@
+error: generator cannot be sent between threads safely
+ --> $DIR/parent-expression.rs:27:25
+ |
+LL | assert_send(g);
+ | ^ generator is not `Send`
+...
+LL | / type_combinations!(
+LL | | // OK
+LL | | copy => { #[derive(Copy, Clone, Default)] pub struct Client; };
+LL | | // NOT OK: MIR borrowck thinks that this is used after the yield, even though
+... |
+LL | | };
+LL | | );
+ | |_____- in this macro invocation
+ |
+ = help: within `[generator@$DIR/parent-expression.rs:21:21: 21:28]`, the trait `Send` is not implemented for `derived_drop::Client`
+note: generator is not `Send` as this value is used across a yield
+ --> $DIR/parent-expression.rs:25:22
+ |
+LL | let g = move || match drop($name::Client { ..$name::Client::default() }) {
+ | ------------------------ has type `derived_drop::Client` which is not `Send`
+...
+LL | _ => yield,
+ | ^^^^^ yield occurs here, with `$name::Client::default()` maybe used later
+LL | };
+ | - `$name::Client::default()` is later dropped here
+...
+LL | / type_combinations!(
+LL | | // OK
+LL | | copy => { #[derive(Copy, Clone, Default)] pub struct Client; };
+LL | | // NOT OK: MIR borrowck thinks that this is used after the yield, even though
+... |
+LL | | };
+LL | | );
+ | |_____- in this macro invocation
+note: required by a bound in `assert_send`
+ --> $DIR/parent-expression.rs:49:19
+ |
+LL | fn assert_send<T: Send>(_thing: T) {}
+ | ^^^^ required by this bound in `assert_send`
+ = note: this error originates in the macro `type_combinations` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: generator cannot be sent between threads safely
+ --> $DIR/parent-expression.rs:27:25
+ |
+LL | assert_send(g);
+ | ^ generator is not `Send`
+...
+LL | / type_combinations!(
+LL | | // OK
+LL | | copy => { #[derive(Copy, Clone, Default)] pub struct Client; };
+LL | | // NOT OK: MIR borrowck thinks that this is used after the yield, even though
+... |
+LL | | };
+LL | | );
+ | |_____- in this macro invocation
+ |
+ = help: within `[generator@$DIR/parent-expression.rs:21:21: 21:28]`, the trait `Send` is not implemented for `significant_drop::Client`
+note: generator is not `Send` as this value is used across a yield
+ --> $DIR/parent-expression.rs:25:22
+ |
+LL | let g = move || match drop($name::Client { ..$name::Client::default() }) {
+ | ------------------------ has type `significant_drop::Client` which is not `Send`
+...
+LL | _ => yield,
+ | ^^^^^ yield occurs here, with `$name::Client::default()` maybe used later
+LL | };
+ | - `$name::Client::default()` is later dropped here
+...
+LL | / type_combinations!(
+LL | | // OK
+LL | | copy => { #[derive(Copy, Clone, Default)] pub struct Client; };
+LL | | // NOT OK: MIR borrowck thinks that this is used after the yield, even though
+... |
+LL | | };
+LL | | );
+ | |_____- in this macro invocation
+note: required by a bound in `assert_send`
+ --> $DIR/parent-expression.rs:49:19
+ |
+LL | fn assert_send<T: Send>(_thing: T) {}
+ | ^^^^ required by this bound in `assert_send`
+ = note: this error originates in the macro `type_combinations` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: generator cannot be sent between threads safely
+ --> $DIR/parent-expression.rs:27:25
+ |
+LL | assert_send(g);
+ | ^ generator is not `Send`
+...
+LL | / type_combinations!(
+LL | | // OK
+LL | | copy => { #[derive(Copy, Clone, Default)] pub struct Client; };
+LL | | // NOT OK: MIR borrowck thinks that this is used after the yield, even though
+... |
+LL | | };
+LL | | );
+ | |_____- in this macro invocation
+ |
+ = help: within `[generator@$DIR/parent-expression.rs:21:21: 21:28]`, the trait `Send` is not implemented for `insignificant_dtor::Client`
+note: generator is not `Send` as this value is used across a yield
+ --> $DIR/parent-expression.rs:25:22
+ |
+LL | let g = move || match drop($name::Client { ..$name::Client::default() }) {
+ | ------------------------ has type `insignificant_dtor::Client` which is not `Send`
+...
+LL | _ => yield,
+ | ^^^^^ yield occurs here, with `$name::Client::default()` maybe used later
+LL | };
+ | - `$name::Client::default()` is later dropped here
+...
+LL | / type_combinations!(
+LL | | // OK
+LL | | copy => { #[derive(Copy, Clone, Default)] pub struct Client; };
+LL | | // NOT OK: MIR borrowck thinks that this is used after the yield, even though
+... |
+LL | | };
+LL | | );
+ | |_____- in this macro invocation
+note: required by a bound in `assert_send`
+ --> $DIR/parent-expression.rs:49:19
+ |
+LL | fn assert_send<T: Send>(_thing: T) {}
+ | ^^^^ required by this bound in `assert_send`
+ = note: this error originates in the macro `type_combinations` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to 3 previous errors
+
diff --git a/tests/ui/generator/parent-expression.drop_tracking_mir.stderr b/tests/ui/generator/parent-expression.drop_tracking_mir.stderr
new file mode 100644
index 000000000..bf8144564
--- /dev/null
+++ b/tests/ui/generator/parent-expression.drop_tracking_mir.stderr
@@ -0,0 +1,122 @@
+error: generator cannot be sent between threads safely
+ --> $DIR/parent-expression.rs:27:13
+ |
+LL | assert_send(g);
+ | ^^^^^^^^^^^ generator is not `Send`
+...
+LL | / type_combinations!(
+LL | | // OK
+LL | | copy => { #[derive(Copy, Clone, Default)] pub struct Client; };
+LL | | // NOT OK: MIR borrowck thinks that this is used after the yield, even though
+... |
+LL | | };
+LL | | );
+ | |_____- in this macro invocation
+ |
+ = help: within `[generator@$DIR/parent-expression.rs:21:21: 21:28]`, the trait `Send` is not implemented for `derived_drop::Client`
+note: generator is not `Send` as this value is used across a yield
+ --> $DIR/parent-expression.rs:25:22
+ |
+LL | let g = move || match drop($name::Client { ..$name::Client::default() }) {
+ | ------------------------ has type `derived_drop::Client` which is not `Send`
+...
+LL | _ => yield,
+ | ^^^^^ yield occurs here, with `$name::Client::default()` maybe used later
+...
+LL | / type_combinations!(
+LL | | // OK
+LL | | copy => { #[derive(Copy, Clone, Default)] pub struct Client; };
+LL | | // NOT OK: MIR borrowck thinks that this is used after the yield, even though
+... |
+LL | | };
+LL | | );
+ | |_____- in this macro invocation
+note: required by a bound in `assert_send`
+ --> $DIR/parent-expression.rs:49:19
+ |
+LL | fn assert_send<T: Send>(_thing: T) {}
+ | ^^^^ required by this bound in `assert_send`
+ = note: this error originates in the macro `type_combinations` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: generator cannot be sent between threads safely
+ --> $DIR/parent-expression.rs:27:13
+ |
+LL | assert_send(g);
+ | ^^^^^^^^^^^ generator is not `Send`
+...
+LL | / type_combinations!(
+LL | | // OK
+LL | | copy => { #[derive(Copy, Clone, Default)] pub struct Client; };
+LL | | // NOT OK: MIR borrowck thinks that this is used after the yield, even though
+... |
+LL | | };
+LL | | );
+ | |_____- in this macro invocation
+ |
+ = help: within `[generator@$DIR/parent-expression.rs:21:21: 21:28]`, the trait `Send` is not implemented for `significant_drop::Client`
+note: generator is not `Send` as this value is used across a yield
+ --> $DIR/parent-expression.rs:25:22
+ |
+LL | let g = move || match drop($name::Client { ..$name::Client::default() }) {
+ | ------------------------ has type `significant_drop::Client` which is not `Send`
+...
+LL | _ => yield,
+ | ^^^^^ yield occurs here, with `$name::Client::default()` maybe used later
+...
+LL | / type_combinations!(
+LL | | // OK
+LL | | copy => { #[derive(Copy, Clone, Default)] pub struct Client; };
+LL | | // NOT OK: MIR borrowck thinks that this is used after the yield, even though
+... |
+LL | | };
+LL | | );
+ | |_____- in this macro invocation
+note: required by a bound in `assert_send`
+ --> $DIR/parent-expression.rs:49:19
+ |
+LL | fn assert_send<T: Send>(_thing: T) {}
+ | ^^^^ required by this bound in `assert_send`
+ = note: this error originates in the macro `type_combinations` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: generator cannot be sent between threads safely
+ --> $DIR/parent-expression.rs:27:13
+ |
+LL | assert_send(g);
+ | ^^^^^^^^^^^ generator is not `Send`
+...
+LL | / type_combinations!(
+LL | | // OK
+LL | | copy => { #[derive(Copy, Clone, Default)] pub struct Client; };
+LL | | // NOT OK: MIR borrowck thinks that this is used after the yield, even though
+... |
+LL | | };
+LL | | );
+ | |_____- in this macro invocation
+ |
+ = help: within `[generator@$DIR/parent-expression.rs:21:21: 21:28]`, the trait `Send` is not implemented for `insignificant_dtor::Client`
+note: generator is not `Send` as this value is used across a yield
+ --> $DIR/parent-expression.rs:25:22
+ |
+LL | let g = move || match drop($name::Client { ..$name::Client::default() }) {
+ | ------------------------ has type `insignificant_dtor::Client` which is not `Send`
+...
+LL | _ => yield,
+ | ^^^^^ yield occurs here, with `$name::Client::default()` maybe used later
+...
+LL | / type_combinations!(
+LL | | // OK
+LL | | copy => { #[derive(Copy, Clone, Default)] pub struct Client; };
+LL | | // NOT OK: MIR borrowck thinks that this is used after the yield, even though
+... |
+LL | | };
+LL | | );
+ | |_____- in this macro invocation
+note: required by a bound in `assert_send`
+ --> $DIR/parent-expression.rs:49:19
+ |
+LL | fn assert_send<T: Send>(_thing: T) {}
+ | ^^^^ required by this bound in `assert_send`
+ = note: this error originates in the macro `type_combinations` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to 3 previous errors
+
diff --git a/tests/ui/generator/parent-expression.no_drop_tracking.stderr b/tests/ui/generator/parent-expression.no_drop_tracking.stderr
new file mode 100644
index 000000000..2e1313a80
--- /dev/null
+++ b/tests/ui/generator/parent-expression.no_drop_tracking.stderr
@@ -0,0 +1,334 @@
+error: generator cannot be sent between threads safely
+ --> $DIR/parent-expression.rs:27:25
+ |
+LL | assert_send(g);
+ | ^ generator is not `Send`
+...
+LL | / type_combinations!(
+LL | | // OK
+LL | | copy => { #[derive(Copy, Clone, Default)] pub struct Client; };
+LL | | // NOT OK: MIR borrowck thinks that this is used after the yield, even though
+... |
+LL | | };
+LL | | );
+ | |_____- in this macro invocation
+ |
+ = help: within `[generator@$DIR/parent-expression.rs:21:21: 21:28]`, the trait `Send` is not implemented for `copy::Client`
+note: generator is not `Send` as this value is used across a yield
+ --> $DIR/parent-expression.rs:25:22
+ |
+LL | let g = move || match drop($name::Client { ..$name::Client::default() }) {
+ | ------------------------ has type `copy::Client` which is not `Send`
+...
+LL | _ => yield,
+ | ^^^^^ yield occurs here, with `$name::Client::default()` maybe used later
+LL | };
+ | - `$name::Client::default()` is later dropped here
+...
+LL | / type_combinations!(
+LL | | // OK
+LL | | copy => { #[derive(Copy, Clone, Default)] pub struct Client; };
+LL | | // NOT OK: MIR borrowck thinks that this is used after the yield, even though
+... |
+LL | | };
+LL | | );
+ | |_____- in this macro invocation
+note: required by a bound in `assert_send`
+ --> $DIR/parent-expression.rs:49:19
+ |
+LL | fn assert_send<T: Send>(_thing: T) {}
+ | ^^^^ required by this bound in `assert_send`
+ = note: this error originates in the macro `type_combinations` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: generator cannot be sent between threads safely
+ --> $DIR/parent-expression.rs:40:25
+ |
+LL | assert_send(g);
+ | ^ generator is not `Send`
+...
+LL | / type_combinations!(
+LL | | // OK
+LL | | copy => { #[derive(Copy, Clone, Default)] pub struct Client; };
+LL | | // NOT OK: MIR borrowck thinks that this is used after the yield, even though
+... |
+LL | | };
+LL | | );
+ | |_____- in this macro invocation
+ |
+ = help: within `[generator@$DIR/parent-expression.rs:37:21: 37:28]`, the trait `Send` is not implemented for `copy::Client`
+note: generator is not `Send` as this value is used across a yield
+ --> $DIR/parent-expression.rs:38:22
+ |
+LL | let g = move || match drop($name::Client::default()) {
+ | ------------------------ has type `copy::Client` which is not `Send`
+LL | _ => yield,
+ | ^^^^^ yield occurs here, with `$name::Client::default()` maybe used later
+LL | };
+ | - `$name::Client::default()` is later dropped here
+...
+LL | / type_combinations!(
+LL | | // OK
+LL | | copy => { #[derive(Copy, Clone, Default)] pub struct Client; };
+LL | | // NOT OK: MIR borrowck thinks that this is used after the yield, even though
+... |
+LL | | };
+LL | | );
+ | |_____- in this macro invocation
+note: required by a bound in `assert_send`
+ --> $DIR/parent-expression.rs:49:19
+ |
+LL | fn assert_send<T: Send>(_thing: T) {}
+ | ^^^^ required by this bound in `assert_send`
+ = note: this error originates in the macro `type_combinations` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: generator cannot be sent between threads safely
+ --> $DIR/parent-expression.rs:27:25
+ |
+LL | assert_send(g);
+ | ^ generator is not `Send`
+...
+LL | / type_combinations!(
+LL | | // OK
+LL | | copy => { #[derive(Copy, Clone, Default)] pub struct Client; };
+LL | | // NOT OK: MIR borrowck thinks that this is used after the yield, even though
+... |
+LL | | };
+LL | | );
+ | |_____- in this macro invocation
+ |
+ = help: within `[generator@$DIR/parent-expression.rs:21:21: 21:28]`, the trait `Send` is not implemented for `derived_drop::Client`
+note: generator is not `Send` as this value is used across a yield
+ --> $DIR/parent-expression.rs:25:22
+ |
+LL | let g = move || match drop($name::Client { ..$name::Client::default() }) {
+ | ------------------------ has type `derived_drop::Client` which is not `Send`
+...
+LL | _ => yield,
+ | ^^^^^ yield occurs here, with `$name::Client::default()` maybe used later
+LL | };
+ | - `$name::Client::default()` is later dropped here
+...
+LL | / type_combinations!(
+LL | | // OK
+LL | | copy => { #[derive(Copy, Clone, Default)] pub struct Client; };
+LL | | // NOT OK: MIR borrowck thinks that this is used after the yield, even though
+... |
+LL | | };
+LL | | );
+ | |_____- in this macro invocation
+note: required by a bound in `assert_send`
+ --> $DIR/parent-expression.rs:49:19
+ |
+LL | fn assert_send<T: Send>(_thing: T) {}
+ | ^^^^ required by this bound in `assert_send`
+ = note: this error originates in the macro `type_combinations` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: generator cannot be sent between threads safely
+ --> $DIR/parent-expression.rs:40:25
+ |
+LL | assert_send(g);
+ | ^ generator is not `Send`
+...
+LL | / type_combinations!(
+LL | | // OK
+LL | | copy => { #[derive(Copy, Clone, Default)] pub struct Client; };
+LL | | // NOT OK: MIR borrowck thinks that this is used after the yield, even though
+... |
+LL | | };
+LL | | );
+ | |_____- in this macro invocation
+ |
+ = help: within `[generator@$DIR/parent-expression.rs:37:21: 37:28]`, the trait `Send` is not implemented for `derived_drop::Client`
+note: generator is not `Send` as this value is used across a yield
+ --> $DIR/parent-expression.rs:38:22
+ |
+LL | let g = move || match drop($name::Client::default()) {
+ | ------------------------ has type `derived_drop::Client` which is not `Send`
+LL | _ => yield,
+ | ^^^^^ yield occurs here, with `$name::Client::default()` maybe used later
+LL | };
+ | - `$name::Client::default()` is later dropped here
+...
+LL | / type_combinations!(
+LL | | // OK
+LL | | copy => { #[derive(Copy, Clone, Default)] pub struct Client; };
+LL | | // NOT OK: MIR borrowck thinks that this is used after the yield, even though
+... |
+LL | | };
+LL | | );
+ | |_____- in this macro invocation
+note: required by a bound in `assert_send`
+ --> $DIR/parent-expression.rs:49:19
+ |
+LL | fn assert_send<T: Send>(_thing: T) {}
+ | ^^^^ required by this bound in `assert_send`
+ = note: this error originates in the macro `type_combinations` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: generator cannot be sent between threads safely
+ --> $DIR/parent-expression.rs:27:25
+ |
+LL | assert_send(g);
+ | ^ generator is not `Send`
+...
+LL | / type_combinations!(
+LL | | // OK
+LL | | copy => { #[derive(Copy, Clone, Default)] pub struct Client; };
+LL | | // NOT OK: MIR borrowck thinks that this is used after the yield, even though
+... |
+LL | | };
+LL | | );
+ | |_____- in this macro invocation
+ |
+ = help: within `[generator@$DIR/parent-expression.rs:21:21: 21:28]`, the trait `Send` is not implemented for `significant_drop::Client`
+note: generator is not `Send` as this value is used across a yield
+ --> $DIR/parent-expression.rs:25:22
+ |
+LL | let g = move || match drop($name::Client { ..$name::Client::default() }) {
+ | ------------------------ has type `significant_drop::Client` which is not `Send`
+...
+LL | _ => yield,
+ | ^^^^^ yield occurs here, with `$name::Client::default()` maybe used later
+LL | };
+ | - `$name::Client::default()` is later dropped here
+...
+LL | / type_combinations!(
+LL | | // OK
+LL | | copy => { #[derive(Copy, Clone, Default)] pub struct Client; };
+LL | | // NOT OK: MIR borrowck thinks that this is used after the yield, even though
+... |
+LL | | };
+LL | | );
+ | |_____- in this macro invocation
+note: required by a bound in `assert_send`
+ --> $DIR/parent-expression.rs:49:19
+ |
+LL | fn assert_send<T: Send>(_thing: T) {}
+ | ^^^^ required by this bound in `assert_send`
+ = note: this error originates in the macro `type_combinations` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: generator cannot be sent between threads safely
+ --> $DIR/parent-expression.rs:40:25
+ |
+LL | assert_send(g);
+ | ^ generator is not `Send`
+...
+LL | / type_combinations!(
+LL | | // OK
+LL | | copy => { #[derive(Copy, Clone, Default)] pub struct Client; };
+LL | | // NOT OK: MIR borrowck thinks that this is used after the yield, even though
+... |
+LL | | };
+LL | | );
+ | |_____- in this macro invocation
+ |
+ = help: within `[generator@$DIR/parent-expression.rs:37:21: 37:28]`, the trait `Send` is not implemented for `significant_drop::Client`
+note: generator is not `Send` as this value is used across a yield
+ --> $DIR/parent-expression.rs:38:22
+ |
+LL | let g = move || match drop($name::Client::default()) {
+ | ------------------------ has type `significant_drop::Client` which is not `Send`
+LL | _ => yield,
+ | ^^^^^ yield occurs here, with `$name::Client::default()` maybe used later
+LL | };
+ | - `$name::Client::default()` is later dropped here
+...
+LL | / type_combinations!(
+LL | | // OK
+LL | | copy => { #[derive(Copy, Clone, Default)] pub struct Client; };
+LL | | // NOT OK: MIR borrowck thinks that this is used after the yield, even though
+... |
+LL | | };
+LL | | );
+ | |_____- in this macro invocation
+note: required by a bound in `assert_send`
+ --> $DIR/parent-expression.rs:49:19
+ |
+LL | fn assert_send<T: Send>(_thing: T) {}
+ | ^^^^ required by this bound in `assert_send`
+ = note: this error originates in the macro `type_combinations` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: generator cannot be sent between threads safely
+ --> $DIR/parent-expression.rs:27:25
+ |
+LL | assert_send(g);
+ | ^ generator is not `Send`
+...
+LL | / type_combinations!(
+LL | | // OK
+LL | | copy => { #[derive(Copy, Clone, Default)] pub struct Client; };
+LL | | // NOT OK: MIR borrowck thinks that this is used after the yield, even though
+... |
+LL | | };
+LL | | );
+ | |_____- in this macro invocation
+ |
+ = help: within `[generator@$DIR/parent-expression.rs:21:21: 21:28]`, the trait `Send` is not implemented for `insignificant_dtor::Client`
+note: generator is not `Send` as this value is used across a yield
+ --> $DIR/parent-expression.rs:25:22
+ |
+LL | let g = move || match drop($name::Client { ..$name::Client::default() }) {
+ | ------------------------ has type `insignificant_dtor::Client` which is not `Send`
+...
+LL | _ => yield,
+ | ^^^^^ yield occurs here, with `$name::Client::default()` maybe used later
+LL | };
+ | - `$name::Client::default()` is later dropped here
+...
+LL | / type_combinations!(
+LL | | // OK
+LL | | copy => { #[derive(Copy, Clone, Default)] pub struct Client; };
+LL | | // NOT OK: MIR borrowck thinks that this is used after the yield, even though
+... |
+LL | | };
+LL | | );
+ | |_____- in this macro invocation
+note: required by a bound in `assert_send`
+ --> $DIR/parent-expression.rs:49:19
+ |
+LL | fn assert_send<T: Send>(_thing: T) {}
+ | ^^^^ required by this bound in `assert_send`
+ = note: this error originates in the macro `type_combinations` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: generator cannot be sent between threads safely
+ --> $DIR/parent-expression.rs:40:25
+ |
+LL | assert_send(g);
+ | ^ generator is not `Send`
+...
+LL | / type_combinations!(
+LL | | // OK
+LL | | copy => { #[derive(Copy, Clone, Default)] pub struct Client; };
+LL | | // NOT OK: MIR borrowck thinks that this is used after the yield, even though
+... |
+LL | | };
+LL | | );
+ | |_____- in this macro invocation
+ |
+ = help: within `[generator@$DIR/parent-expression.rs:37:21: 37:28]`, the trait `Send` is not implemented for `insignificant_dtor::Client`
+note: generator is not `Send` as this value is used across a yield
+ --> $DIR/parent-expression.rs:38:22
+ |
+LL | let g = move || match drop($name::Client::default()) {
+ | ------------------------ has type `insignificant_dtor::Client` which is not `Send`
+LL | _ => yield,
+ | ^^^^^ yield occurs here, with `$name::Client::default()` maybe used later
+LL | };
+ | - `$name::Client::default()` is later dropped here
+...
+LL | / type_combinations!(
+LL | | // OK
+LL | | copy => { #[derive(Copy, Clone, Default)] pub struct Client; };
+LL | | // NOT OK: MIR borrowck thinks that this is used after the yield, even though
+... |
+LL | | };
+LL | | );
+ | |_____- in this macro invocation
+note: required by a bound in `assert_send`
+ --> $DIR/parent-expression.rs:49:19
+ |
+LL | fn assert_send<T: Send>(_thing: T) {}
+ | ^^^^ required by this bound in `assert_send`
+ = note: this error originates in the macro `type_combinations` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to 8 previous errors
+
diff --git a/tests/ui/generator/parent-expression.rs b/tests/ui/generator/parent-expression.rs
new file mode 100644
index 000000000..239034e3d
--- /dev/null
+++ b/tests/ui/generator/parent-expression.rs
@@ -0,0 +1,77 @@
+// revisions: no_drop_tracking drop_tracking drop_tracking_mir
+// [drop_tracking] compile-flags: -Zdrop-tracking
+// [drop_tracking_mir] compile-flags: -Zdrop-tracking-mir
+
+#![feature(generators, negative_impls, rustc_attrs)]
+
+macro_rules! type_combinations {
+ (
+ $( $name:ident => { $( $tt:tt )* } );* $(;)?
+ ) => { $(
+ mod $name {
+ $( $tt )*
+
+ impl !Sync for Client {}
+ impl !Send for Client {}
+ }
+
+ // Struct update syntax. This fails because the Client used in the update is considered
+ // dropped *after* the yield.
+ {
+ let g = move || match drop($name::Client { ..$name::Client::default() }) {
+ //~^ `significant_drop::Client` which is not `Send`
+ //~| `insignificant_dtor::Client` which is not `Send`
+ //~| `derived_drop::Client` which is not `Send`
+ _ => yield,
+ };
+ assert_send(g);
+ //~^ ERROR cannot be sent between threads
+ //~| ERROR cannot be sent between threads
+ //~| ERROR cannot be sent between threads
+ //[no_drop_tracking]~^^^^ ERROR cannot be sent between threads
+ }
+
+ // Simple owned value. This works because the Client is considered moved into `drop`,
+ // even though the temporary expression doesn't end until after the yield.
+ {
+ let g = move || match drop($name::Client::default()) {
+ _ => yield,
+ };
+ assert_send(g);
+ //[no_drop_tracking]~^ ERROR cannot be sent between threads
+ //[no_drop_tracking]~| ERROR cannot be sent between threads
+ //[no_drop_tracking]~| ERROR cannot be sent between threads
+ //[no_drop_tracking]~| ERROR cannot be sent between threads
+ }
+ )* }
+}
+
+fn assert_send<T: Send>(_thing: T) {}
+
+fn main() {
+ type_combinations!(
+ // OK
+ copy => { #[derive(Copy, Clone, Default)] pub struct Client; };
+ // NOT OK: MIR borrowck thinks that this is used after the yield, even though
+ // this has no `Drop` impl and only the drops of the fields are observable.
+ // FIXME: this should compile.
+ derived_drop => { #[derive(Default)] pub struct Client { pub nickname: String } };
+ // NOT OK
+ significant_drop => {
+ #[derive(Default)]
+ pub struct Client;
+ impl Drop for Client {
+ fn drop(&mut self) {}
+ }
+ };
+ // NOT OK (we need to agree with MIR borrowck)
+ insignificant_dtor => {
+ #[derive(Default)]
+ #[rustc_insignificant_dtor]
+ pub struct Client;
+ impl Drop for Client {
+ fn drop(&mut self) {}
+ }
+ };
+ );
+}
diff --git a/tests/ui/generator/partial-drop.stderr b/tests/ui/generator/partial-drop.drop_tracking.stderr
index 9baafe54e..f1b25cb8c 100644
--- a/tests/ui/generator/partial-drop.stderr
+++ b/tests/ui/generator/partial-drop.drop_tracking.stderr
@@ -1,19 +1,18 @@
error: generator cannot be sent between threads safely
- --> $DIR/partial-drop.rs:14:17
+ --> $DIR/partial-drop.rs:17:17
|
LL | assert_send(|| {
| _________________^
LL | |
-LL | | // FIXME: it would be nice to make this work.
LL | | let guard = Bar { foo: Foo, x: 42 };
LL | | drop(guard.foo);
LL | | yield;
LL | | });
| |_____^ generator is not `Send`
|
- = help: within `[generator@$DIR/partial-drop.rs:14:17: 14:19]`, the trait `Send` is not implemented for `Foo`
+ = help: within `[generator@$DIR/partial-drop.rs:17:17: 17:19]`, the trait `Send` is not implemented for `Foo`
note: generator is not `Send` as this value is used across a yield
- --> $DIR/partial-drop.rs:19:9
+ --> $DIR/partial-drop.rs:21:9
|
LL | let guard = Bar { foo: Foo, x: 42 };
| ----- has type `Bar` which is not `Send`
@@ -23,25 +22,25 @@ LL | yield;
LL | });
| - `guard` is later dropped here
note: required by a bound in `assert_send`
- --> $DIR/partial-drop.rs:42:19
+ --> $DIR/partial-drop.rs:33:19
|
LL | fn assert_send<T: Send>(_: T) {}
| ^^^^ required by this bound in `assert_send`
error: generator cannot be sent between threads safely
- --> $DIR/partial-drop.rs:22:17
+ --> $DIR/partial-drop.rs:24:17
|
LL | assert_send(|| {
| _________________^
LL | |
-LL | | // FIXME: it would be nice to make this work.
LL | | let guard = Bar { foo: Foo, x: 42 };
-... |
+LL | | let Bar { foo, x } = guard;
+LL | | drop(foo);
LL | | yield;
LL | | });
| |_____^ generator is not `Send`
|
- = help: within `[generator@$DIR/partial-drop.rs:22:17: 22:19]`, the trait `Send` is not implemented for `Foo`
+ = help: within `[generator@$DIR/partial-drop.rs:24:17: 24:19]`, the trait `Send` is not implemented for `Foo`
note: generator is not `Send` as this value is used across a yield
--> $DIR/partial-drop.rs:29:9
|
@@ -53,40 +52,10 @@ LL | yield;
LL | });
| - `guard` is later dropped here
note: required by a bound in `assert_send`
- --> $DIR/partial-drop.rs:42:19
+ --> $DIR/partial-drop.rs:33:19
|
LL | fn assert_send<T: Send>(_: T) {}
| ^^^^ required by this bound in `assert_send`
-error: generator cannot be sent between threads safely
- --> $DIR/partial-drop.rs:32:17
- |
-LL | assert_send(|| {
- | _________________^
-LL | |
-LL | | // FIXME: it would be nice to make this work.
-LL | | let guard = Bar { foo: Foo, x: 42 };
-... |
-LL | | yield;
-LL | | });
- | |_____^ generator is not `Send`
- |
- = help: within `[generator@$DIR/partial-drop.rs:32:17: 32:19]`, the trait `Send` is not implemented for `Foo`
-note: generator is not `Send` as this value is used across a yield
- --> $DIR/partial-drop.rs:38:9
- |
-LL | let guard = Bar { foo: Foo, x: 42 };
- | ----- has type `Bar` which is not `Send`
-...
-LL | yield;
- | ^^^^^ yield occurs here, with `guard` maybe used later
-LL | });
- | - `guard` is later dropped here
-note: required by a bound in `assert_send`
- --> $DIR/partial-drop.rs:42:19
- |
-LL | fn assert_send<T: Send>(_: T) {}
- | ^^^^ required by this bound in `assert_send`
-
-error: aborting due to 3 previous errors
+error: aborting due to 2 previous errors
diff --git a/tests/ui/generator/partial-drop.no_drop_tracking.stderr b/tests/ui/generator/partial-drop.no_drop_tracking.stderr
new file mode 100644
index 000000000..91152b5ea
--- /dev/null
+++ b/tests/ui/generator/partial-drop.no_drop_tracking.stderr
@@ -0,0 +1,61 @@
+error: generator cannot be sent between threads safely
+ --> $DIR/partial-drop.rs:17:17
+ |
+LL | assert_send(|| {
+ | _________________^
+LL | |
+LL | | let guard = Bar { foo: Foo, x: 42 };
+LL | | drop(guard.foo);
+LL | | yield;
+LL | | });
+ | |_____^ generator is not `Send`
+ |
+ = help: within `[generator@$DIR/partial-drop.rs:17:17: 17:19]`, the trait `Send` is not implemented for `Foo`
+note: generator is not `Send` as this value is used across a yield
+ --> $DIR/partial-drop.rs:21:9
+ |
+LL | let guard = Bar { foo: Foo, x: 42 };
+ | ----- has type `Bar` which is not `Send`
+LL | drop(guard.foo);
+LL | yield;
+ | ^^^^^ yield occurs here, with `guard` maybe used later
+LL | });
+ | - `guard` is later dropped here
+note: required by a bound in `assert_send`
+ --> $DIR/partial-drop.rs:33:19
+ |
+LL | fn assert_send<T: Send>(_: T) {}
+ | ^^^^ required by this bound in `assert_send`
+
+error: generator cannot be sent between threads safely
+ --> $DIR/partial-drop.rs:24:17
+ |
+LL | assert_send(|| {
+ | _________________^
+LL | |
+LL | | let guard = Bar { foo: Foo, x: 42 };
+LL | | let Bar { foo, x } = guard;
+LL | | drop(foo);
+LL | | yield;
+LL | | });
+ | |_____^ generator is not `Send`
+ |
+ = help: within `[generator@$DIR/partial-drop.rs:24:17: 24:19]`, the trait `Send` is not implemented for `Foo`
+note: generator is not `Send` as this value is used across a yield
+ --> $DIR/partial-drop.rs:29:9
+ |
+LL | let Bar { foo, x } = guard;
+ | --- has type `Foo` which is not `Send`
+LL | drop(foo);
+LL | yield;
+ | ^^^^^ yield occurs here, with `foo` maybe used later
+LL | });
+ | - `foo` is later dropped here
+note: required by a bound in `assert_send`
+ --> $DIR/partial-drop.rs:33:19
+ |
+LL | fn assert_send<T: Send>(_: T) {}
+ | ^^^^ required by this bound in `assert_send`
+
+error: aborting due to 2 previous errors
+
diff --git a/tests/ui/generator/partial-drop.rs b/tests/ui/generator/partial-drop.rs
index c872fb7f3..1d3ae075d 100644
--- a/tests/ui/generator/partial-drop.rs
+++ b/tests/ui/generator/partial-drop.rs
@@ -1,4 +1,7 @@
-// compile-flags: -Zdrop-tracking
+// revisions: no_drop_tracking drop_tracking drop_tracking_mir
+// [drop_tracking] compile-flags: -Zdrop-tracking
+// [drop_tracking_mir] compile-flags: -Zdrop-tracking-mir
+// [drop_tracking_mir] check-pass
#![feature(negative_impls, generators)]
@@ -12,26 +15,14 @@ struct Bar {
fn main() {
assert_send(|| {
- //~^ ERROR generator cannot be sent between threads safely
- // FIXME: it would be nice to make this work.
+ //[no_drop_tracking,drop_tracking]~^ ERROR generator cannot be sent between threads safely
let guard = Bar { foo: Foo, x: 42 };
drop(guard.foo);
yield;
});
assert_send(|| {
- //~^ ERROR generator cannot be sent between threads safely
- // FIXME: it would be nice to make this work.
- let guard = Bar { foo: Foo, x: 42 };
- drop(guard);
- guard.foo = Foo;
- guard.x = 23;
- yield;
- });
-
- assert_send(|| {
- //~^ ERROR generator cannot be sent between threads safely
- // FIXME: it would be nice to make this work.
+ //[no_drop_tracking,drop_tracking]~^ ERROR generator cannot be sent between threads safely
let guard = Bar { foo: Foo, x: 42 };
let Bar { foo, x } = guard;
drop(foo);
diff --git a/tests/ui/generator/print/generator-print-verbose-1.stderr b/tests/ui/generator/print/generator-print-verbose-1.drop_tracking.stderr
index ebf35be58..7d0a20169 100644
--- a/tests/ui/generator/print/generator-print-verbose-1.stderr
+++ b/tests/ui/generator/print/generator-print-verbose-1.drop_tracking.stderr
@@ -1,12 +1,13 @@
error: generator cannot be sent between threads safely
- --> $DIR/generator-print-verbose-1.rs:37:18
+ --> $DIR/generator-print-verbose-1.rs:40:18
|
LL | require_send(send_gen);
| ^^^^^^^^ generator is not `Send`
|
= help: the trait `Sync` is not implemented for `RefCell<i32>`
+ = note: if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` instead
note: generator is not `Send` as this value is used across a yield
- --> $DIR/generator-print-verbose-1.rs:35:9
+ --> $DIR/generator-print-verbose-1.rs:38:9
|
LL | let _non_send_gen = make_non_send_generator();
| ------------- has type `Opaque(DefId(0:34 ~ generator_print_verbose_1[749a]::make_non_send_generator::{opaque#0}), [])` which is not `Send`
@@ -15,13 +16,13 @@ LL | yield;
LL | };
| - `_non_send_gen` is later dropped here
note: required by a bound in `require_send`
- --> $DIR/generator-print-verbose-1.rs:26:25
+ --> $DIR/generator-print-verbose-1.rs:29:25
|
LL | fn require_send(_: impl Send) {}
| ^^^^ required by this bound in `require_send`
error[E0277]: `RefCell<i32>` cannot be shared between threads safely
- --> $DIR/generator-print-verbose-1.rs:56:18
+ --> $DIR/generator-print-verbose-1.rs:59:18
|
LL | require_send(send_gen);
| ------------ ^^^^^^^^ `RefCell<i32>` cannot be shared between threads safely
@@ -29,30 +30,31 @@ LL | require_send(send_gen);
| required by a bound introduced by this call
|
= help: the trait `Sync` is not implemented for `RefCell<i32>`
+ = note: if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` instead
= note: required for `Arc<RefCell<i32>>` to implement `Send`
note: required because it's used within this generator
- --> $DIR/generator-print-verbose-1.rs:42:5
+ --> $DIR/generator-print-verbose-1.rs:45:5
|
LL | || {
| ^^
note: required because it appears within the type `Opaque(DefId(0:35 ~ generator_print_verbose_1[749a]::make_gen2::{opaque#0}), [Arc<RefCell<i32>>])`
- --> $DIR/generator-print-verbose-1.rs:41:30
+ --> $DIR/generator-print-verbose-1.rs:44:30
|
LL | pub fn make_gen2<T>(t: T) -> impl Generator<Return = T> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
note: required because it appears within the type `Opaque(DefId(0:36 ~ generator_print_verbose_1[749a]::make_non_send_generator2::{opaque#0}), [])`
- --> $DIR/generator-print-verbose-1.rs:47:34
+ --> $DIR/generator-print-verbose-1.rs:50:34
|
LL | fn make_non_send_generator2() -> impl Generator<Return = Arc<RefCell<i32>>> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: required because it captures the following types: `Opaque(DefId(0:36 ~ generator_print_verbose_1[749a]::make_non_send_generator2::{opaque#0}), [])`, `()`
note: required because it's used within this generator
- --> $DIR/generator-print-verbose-1.rs:52:20
+ --> $DIR/generator-print-verbose-1.rs:55:20
|
LL | let send_gen = || {
| ^^
note: required by a bound in `require_send`
- --> $DIR/generator-print-verbose-1.rs:26:25
+ --> $DIR/generator-print-verbose-1.rs:29:25
|
LL | fn require_send(_: impl Send) {}
| ^^^^ required by this bound in `require_send`
diff --git a/tests/ui/generator/print/generator-print-verbose-1.drop_tracking_mir.stderr b/tests/ui/generator/print/generator-print-verbose-1.drop_tracking_mir.stderr
new file mode 100644
index 000000000..c045b1441
--- /dev/null
+++ b/tests/ui/generator/print/generator-print-verbose-1.drop_tracking_mir.stderr
@@ -0,0 +1,60 @@
+error: generator cannot be sent between threads safely
+ --> $DIR/generator-print-verbose-1.rs:40:5
+ |
+LL | require_send(send_gen);
+ | ^^^^^^^^^^^^ generator is not `Send`
+ |
+ = help: the trait `Sync` is not implemented for `RefCell<i32>`
+ = note: if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` instead
+note: generator is not `Send` as this value is used across a yield
+ --> $DIR/generator-print-verbose-1.rs:38:9
+ |
+LL | let _non_send_gen = make_non_send_generator();
+ | ------------- has type `Opaque(DefId(0:34 ~ generator_print_verbose_1[749a]::make_non_send_generator::{opaque#0}), [])` which is not `Send`
+LL | yield;
+ | ^^^^^ yield occurs here, with `_non_send_gen` maybe used later
+note: required by a bound in `require_send`
+ --> $DIR/generator-print-verbose-1.rs:29:25
+ |
+LL | fn require_send(_: impl Send) {}
+ | ^^^^ required by this bound in `require_send`
+
+error[E0277]: `RefCell<i32>` cannot be shared between threads safely
+ --> $DIR/generator-print-verbose-1.rs:59:5
+ |
+LL | require_send(send_gen);
+ | ^^^^^^^^^^^^ `RefCell<i32>` cannot be shared between threads safely
+ |
+ = help: the trait `Sync` is not implemented for `RefCell<i32>`
+ = note: if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` instead
+ = note: required for `Arc<RefCell<i32>>` to implement `Send`
+note: required because it's used within this generator
+ --> $DIR/generator-print-verbose-1.rs:45:5
+ |
+LL | || {
+ | ^^
+note: required because it appears within the type `Opaque(DefId(0:35 ~ generator_print_verbose_1[749a]::make_gen2::{opaque#0}), [Arc<RefCell<i32>>])`
+ --> $DIR/generator-print-verbose-1.rs:44:30
+ |
+LL | pub fn make_gen2<T>(t: T) -> impl Generator<Return = T> {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+note: required because it appears within the type `Opaque(DefId(0:36 ~ generator_print_verbose_1[749a]::make_non_send_generator2::{opaque#0}), [])`
+ --> $DIR/generator-print-verbose-1.rs:50:34
+ |
+LL | fn make_non_send_generator2() -> impl Generator<Return = Arc<RefCell<i32>>> {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ = note: required because it captures the following types: `Opaque(DefId(0:36 ~ generator_print_verbose_1[749a]::make_non_send_generator2::{opaque#0}), [])`
+note: required because it's used within this generator
+ --> $DIR/generator-print-verbose-1.rs:55:20
+ |
+LL | let send_gen = || {
+ | ^^
+note: required by a bound in `require_send`
+ --> $DIR/generator-print-verbose-1.rs:29:25
+ |
+LL | fn require_send(_: impl Send) {}
+ | ^^^^ required by this bound in `require_send`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/generator/print/generator-print-verbose-1.no_drop_tracking.stderr b/tests/ui/generator/print/generator-print-verbose-1.no_drop_tracking.stderr
new file mode 100644
index 000000000..7d0a20169
--- /dev/null
+++ b/tests/ui/generator/print/generator-print-verbose-1.no_drop_tracking.stderr
@@ -0,0 +1,64 @@
+error: generator cannot be sent between threads safely
+ --> $DIR/generator-print-verbose-1.rs:40:18
+ |
+LL | require_send(send_gen);
+ | ^^^^^^^^ generator is not `Send`
+ |
+ = help: the trait `Sync` is not implemented for `RefCell<i32>`
+ = note: if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` instead
+note: generator is not `Send` as this value is used across a yield
+ --> $DIR/generator-print-verbose-1.rs:38:9
+ |
+LL | let _non_send_gen = make_non_send_generator();
+ | ------------- has type `Opaque(DefId(0:34 ~ generator_print_verbose_1[749a]::make_non_send_generator::{opaque#0}), [])` which is not `Send`
+LL | yield;
+ | ^^^^^ yield occurs here, with `_non_send_gen` maybe used later
+LL | };
+ | - `_non_send_gen` is later dropped here
+note: required by a bound in `require_send`
+ --> $DIR/generator-print-verbose-1.rs:29:25
+ |
+LL | fn require_send(_: impl Send) {}
+ | ^^^^ required by this bound in `require_send`
+
+error[E0277]: `RefCell<i32>` cannot be shared between threads safely
+ --> $DIR/generator-print-verbose-1.rs:59:18
+ |
+LL | require_send(send_gen);
+ | ------------ ^^^^^^^^ `RefCell<i32>` cannot be shared between threads safely
+ | |
+ | required by a bound introduced by this call
+ |
+ = help: the trait `Sync` is not implemented for `RefCell<i32>`
+ = note: if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` instead
+ = note: required for `Arc<RefCell<i32>>` to implement `Send`
+note: required because it's used within this generator
+ --> $DIR/generator-print-verbose-1.rs:45:5
+ |
+LL | || {
+ | ^^
+note: required because it appears within the type `Opaque(DefId(0:35 ~ generator_print_verbose_1[749a]::make_gen2::{opaque#0}), [Arc<RefCell<i32>>])`
+ --> $DIR/generator-print-verbose-1.rs:44:30
+ |
+LL | pub fn make_gen2<T>(t: T) -> impl Generator<Return = T> {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+note: required because it appears within the type `Opaque(DefId(0:36 ~ generator_print_verbose_1[749a]::make_non_send_generator2::{opaque#0}), [])`
+ --> $DIR/generator-print-verbose-1.rs:50:34
+ |
+LL | fn make_non_send_generator2() -> impl Generator<Return = Arc<RefCell<i32>>> {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ = note: required because it captures the following types: `Opaque(DefId(0:36 ~ generator_print_verbose_1[749a]::make_non_send_generator2::{opaque#0}), [])`, `()`
+note: required because it's used within this generator
+ --> $DIR/generator-print-verbose-1.rs:55:20
+ |
+LL | let send_gen = || {
+ | ^^
+note: required by a bound in `require_send`
+ --> $DIR/generator-print-verbose-1.rs:29:25
+ |
+LL | fn require_send(_: impl Send) {}
+ | ^^^^ required by this bound in `require_send`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/generator/print/generator-print-verbose-1.rs b/tests/ui/generator/print/generator-print-verbose-1.rs
index 89124ad72..c7052c7d1 100644
--- a/tests/ui/generator/print/generator-print-verbose-1.rs
+++ b/tests/ui/generator/print/generator-print-verbose-1.rs
@@ -1,3 +1,6 @@
+// revisions: no_drop_tracking drop_tracking drop_tracking_mir
+// [drop_tracking] compile-flags: -Zdrop-tracking
+// [drop_tracking_mir] compile-flags: -Zdrop-tracking-mir
// compile-flags: -Zverbose
// Same as: tests/ui/generator/issue-68112.stderr
@@ -12,7 +15,7 @@ use std::{
};
pub struct Ready<T>(Option<T>);
-impl<T> Generator<()> for Ready<T> {
+impl<T: Unpin> Generator<()> for Ready<T> {
type Return = T;
type Yield = ();
fn resume(mut self: Pin<&mut Self>, _args: ()) -> GeneratorState<(), T> {
diff --git a/tests/ui/generator/print/generator-print-verbose-2.drop_tracking.stderr b/tests/ui/generator/print/generator-print-verbose-2.drop_tracking.stderr
new file mode 100644
index 000000000..1f2e530f6
--- /dev/null
+++ b/tests/ui/generator/print/generator-print-verbose-2.drop_tracking.stderr
@@ -0,0 +1,60 @@
+error: generator cannot be shared between threads safely
+ --> $DIR/generator-print-verbose-2.rs:20:17
+ |
+LL | assert_sync(|| {
+ | _________________^
+LL | |
+LL | | let a = NotSync;
+LL | | yield;
+LL | | drop(a);
+LL | | });
+ | |_____^ generator is not `Sync`
+ |
+ = help: within `[main::{closure#0} upvar_tys=() {NotSync, ()}]`, the trait `Sync` is not implemented for `NotSync`
+note: generator is not `Sync` as this value is used across a yield
+ --> $DIR/generator-print-verbose-2.rs:23:9
+ |
+LL | let a = NotSync;
+ | - has type `NotSync` which is not `Sync`
+LL | yield;
+ | ^^^^^ yield occurs here, with `a` maybe used later
+LL | drop(a);
+LL | });
+ | - `a` is later dropped here
+note: required by a bound in `assert_sync`
+ --> $DIR/generator-print-verbose-2.rs:17:23
+ |
+LL | fn assert_sync<T: Sync>(_: T) {}
+ | ^^^^ required by this bound in `assert_sync`
+
+error: generator cannot be sent between threads safely
+ --> $DIR/generator-print-verbose-2.rs:27:17
+ |
+LL | assert_send(|| {
+ | _________________^
+LL | |
+LL | | let a = NotSend;
+LL | | yield;
+LL | | drop(a);
+LL | | });
+ | |_____^ generator is not `Send`
+ |
+ = help: within `[main::{closure#1} upvar_tys=() {NotSend, ()}]`, the trait `Send` is not implemented for `NotSend`
+note: generator is not `Send` as this value is used across a yield
+ --> $DIR/generator-print-verbose-2.rs:30:9
+ |
+LL | let a = NotSend;
+ | - has type `NotSend` which is not `Send`
+LL | yield;
+ | ^^^^^ yield occurs here, with `a` maybe used later
+LL | drop(a);
+LL | });
+ | - `a` is later dropped here
+note: required by a bound in `assert_send`
+ --> $DIR/generator-print-verbose-2.rs:18:23
+ |
+LL | fn assert_send<T: Send>(_: T) {}
+ | ^^^^ required by this bound in `assert_send`
+
+error: aborting due to 2 previous errors
+
diff --git a/tests/ui/generator/print/generator-print-verbose-2.drop_tracking_mir.stderr b/tests/ui/generator/print/generator-print-verbose-2.drop_tracking_mir.stderr
new file mode 100644
index 000000000..354369f19
--- /dev/null
+++ b/tests/ui/generator/print/generator-print-verbose-2.drop_tracking_mir.stderr
@@ -0,0 +1,42 @@
+error: generator cannot be shared between threads safely
+ --> $DIR/generator-print-verbose-2.rs:20:5
+ |
+LL | assert_sync(|| {
+ | ^^^^^^^^^^^ generator is not `Sync`
+ |
+ = help: within `[main::{closure#0} upvar_tys=() [main::{closure#0}]]`, the trait `Sync` is not implemented for `NotSync`
+note: generator is not `Sync` as this value is used across a yield
+ --> $DIR/generator-print-verbose-2.rs:23:9
+ |
+LL | let a = NotSync;
+ | - has type `NotSync` which is not `Sync`
+LL | yield;
+ | ^^^^^ yield occurs here, with `a` maybe used later
+note: required by a bound in `assert_sync`
+ --> $DIR/generator-print-verbose-2.rs:17:23
+ |
+LL | fn assert_sync<T: Sync>(_: T) {}
+ | ^^^^ required by this bound in `assert_sync`
+
+error: generator cannot be sent between threads safely
+ --> $DIR/generator-print-verbose-2.rs:27:5
+ |
+LL | assert_send(|| {
+ | ^^^^^^^^^^^ generator is not `Send`
+ |
+ = help: within `[main::{closure#1} upvar_tys=() [main::{closure#1}]]`, the trait `Send` is not implemented for `NotSend`
+note: generator is not `Send` as this value is used across a yield
+ --> $DIR/generator-print-verbose-2.rs:30:9
+ |
+LL | let a = NotSend;
+ | - has type `NotSend` which is not `Send`
+LL | yield;
+ | ^^^^^ yield occurs here, with `a` maybe used later
+note: required by a bound in `assert_send`
+ --> $DIR/generator-print-verbose-2.rs:18:23
+ |
+LL | fn assert_send<T: Send>(_: T) {}
+ | ^^^^ required by this bound in `assert_send`
+
+error: aborting due to 2 previous errors
+
diff --git a/tests/ui/generator/print/generator-print-verbose-2.no_drop_tracking.stderr b/tests/ui/generator/print/generator-print-verbose-2.no_drop_tracking.stderr
new file mode 100644
index 000000000..1f2e530f6
--- /dev/null
+++ b/tests/ui/generator/print/generator-print-verbose-2.no_drop_tracking.stderr
@@ -0,0 +1,60 @@
+error: generator cannot be shared between threads safely
+ --> $DIR/generator-print-verbose-2.rs:20:17
+ |
+LL | assert_sync(|| {
+ | _________________^
+LL | |
+LL | | let a = NotSync;
+LL | | yield;
+LL | | drop(a);
+LL | | });
+ | |_____^ generator is not `Sync`
+ |
+ = help: within `[main::{closure#0} upvar_tys=() {NotSync, ()}]`, the trait `Sync` is not implemented for `NotSync`
+note: generator is not `Sync` as this value is used across a yield
+ --> $DIR/generator-print-verbose-2.rs:23:9
+ |
+LL | let a = NotSync;
+ | - has type `NotSync` which is not `Sync`
+LL | yield;
+ | ^^^^^ yield occurs here, with `a` maybe used later
+LL | drop(a);
+LL | });
+ | - `a` is later dropped here
+note: required by a bound in `assert_sync`
+ --> $DIR/generator-print-verbose-2.rs:17:23
+ |
+LL | fn assert_sync<T: Sync>(_: T) {}
+ | ^^^^ required by this bound in `assert_sync`
+
+error: generator cannot be sent between threads safely
+ --> $DIR/generator-print-verbose-2.rs:27:17
+ |
+LL | assert_send(|| {
+ | _________________^
+LL | |
+LL | | let a = NotSend;
+LL | | yield;
+LL | | drop(a);
+LL | | });
+ | |_____^ generator is not `Send`
+ |
+ = help: within `[main::{closure#1} upvar_tys=() {NotSend, ()}]`, the trait `Send` is not implemented for `NotSend`
+note: generator is not `Send` as this value is used across a yield
+ --> $DIR/generator-print-verbose-2.rs:30:9
+ |
+LL | let a = NotSend;
+ | - has type `NotSend` which is not `Send`
+LL | yield;
+ | ^^^^^ yield occurs here, with `a` maybe used later
+LL | drop(a);
+LL | });
+ | - `a` is later dropped here
+note: required by a bound in `assert_send`
+ --> $DIR/generator-print-verbose-2.rs:18:23
+ |
+LL | fn assert_send<T: Send>(_: T) {}
+ | ^^^^ required by this bound in `assert_send`
+
+error: aborting due to 2 previous errors
+
diff --git a/tests/ui/generator/print/generator-print-verbose-2.rs b/tests/ui/generator/print/generator-print-verbose-2.rs
index d914719cb..ab29db6e0 100644
--- a/tests/ui/generator/print/generator-print-verbose-2.rs
+++ b/tests/ui/generator/print/generator-print-verbose-2.rs
@@ -1,9 +1,17 @@
+// revisions: no_drop_tracking drop_tracking drop_tracking_mir
+// [drop_tracking] compile-flags: -Zdrop-tracking
+// [drop_tracking_mir] compile-flags: -Zdrop-tracking-mir
// compile-flags: -Zverbose
// Same as test/ui/generator/not-send-sync.rs
#![feature(generators)]
+#![feature(negative_impls)]
-use std::cell::Cell;
+struct NotSend;
+struct NotSync;
+
+impl !Send for NotSend {}
+impl !Sync for NotSync {}
fn main() {
fn assert_sync<T: Sync>(_: T) {}
@@ -11,14 +19,15 @@ fn main() {
assert_sync(|| {
//~^ ERROR: generator cannot be shared between threads safely
- let a = Cell::new(2);
+ let a = NotSync;
yield;
+ drop(a);
});
- let a = Cell::new(2);
assert_send(|| {
- //~^ ERROR: E0277
- drop(&a);
+ //~^ ERROR: generator cannot be sent between threads safely
+ let a = NotSend;
yield;
+ drop(a);
});
}
diff --git a/tests/ui/generator/print/generator-print-verbose-2.stderr b/tests/ui/generator/print/generator-print-verbose-2.stderr
deleted file mode 100644
index 909e49c38..000000000
--- a/tests/ui/generator/print/generator-print-verbose-2.stderr
+++ /dev/null
@@ -1,56 +0,0 @@
-error[E0277]: `Cell<i32>` cannot be shared between threads safely
- --> $DIR/generator-print-verbose-2.rs:19:17
- |
-LL | assert_send(|| {
- | _____-----------_^
- | | |
- | | required by a bound introduced by this call
-LL | |
-LL | | drop(&a);
-LL | | yield;
-LL | | });
- | |_____^ `Cell<i32>` cannot be shared between threads safely
- |
- = help: the trait `Sync` is not implemented for `Cell<i32>`
- = note: required for `&'_#4r Cell<i32>` to implement `Send`
-note: required because it's used within this generator
- --> $DIR/generator-print-verbose-2.rs:19:17
- |
-LL | assert_send(|| {
- | ^^
-note: required by a bound in `assert_send`
- --> $DIR/generator-print-verbose-2.rs:10:23
- |
-LL | fn assert_send<T: Send>(_: T) {}
- | ^^^^ required by this bound in `assert_send`
-
-error: generator cannot be shared between threads safely
- --> $DIR/generator-print-verbose-2.rs:12:17
- |
-LL | assert_sync(|| {
- | _________________^
-LL | |
-LL | | let a = Cell::new(2);
-LL | | yield;
-LL | | });
- | |_____^ generator is not `Sync`
- |
- = help: within `[main::{closure#0} upvar_tys=() {Cell<i32>, ()}]`, the trait `Sync` is not implemented for `Cell<i32>`
-note: generator is not `Sync` as this value is used across a yield
- --> $DIR/generator-print-verbose-2.rs:15:9
- |
-LL | let a = Cell::new(2);
- | - has type `Cell<i32>` which is not `Sync`
-LL | yield;
- | ^^^^^ yield occurs here, with `a` maybe used later
-LL | });
- | - `a` is later dropped here
-note: required by a bound in `assert_sync`
- --> $DIR/generator-print-verbose-2.rs:9:23
- |
-LL | fn assert_sync<T: Sync>(_: T) {}
- | ^^^^ required by this bound in `assert_sync`
-
-error: aborting due to 2 previous errors
-
-For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/generator/retain-resume-ref.drop_tracking.stderr b/tests/ui/generator/retain-resume-ref.drop_tracking.stderr
new file mode 100644
index 000000000..7122a951e
--- /dev/null
+++ b/tests/ui/generator/retain-resume-ref.drop_tracking.stderr
@@ -0,0 +1,13 @@
+error[E0499]: cannot borrow `thing` as mutable more than once at a time
+ --> $DIR/retain-resume-ref.rs:27:25
+ |
+LL | gen.as_mut().resume(&mut thing);
+ | ---------- first mutable borrow occurs here
+LL | gen.as_mut().resume(&mut thing);
+ | ------ ^^^^^^^^^^ second mutable borrow occurs here
+ | |
+ | first borrow later used by call
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0499`.
diff --git a/tests/ui/generator/retain-resume-ref.drop_tracking_mir.stderr b/tests/ui/generator/retain-resume-ref.drop_tracking_mir.stderr
new file mode 100644
index 000000000..736ed1fb6
--- /dev/null
+++ b/tests/ui/generator/retain-resume-ref.drop_tracking_mir.stderr
@@ -0,0 +1,14 @@
+error[E0499]: cannot borrow `thing` as mutable more than once at a time
+ --> $DIR/retain-resume-ref.rs:27:25
+ |
+LL | gen.as_mut().resume(&mut thing);
+ | ---------- first mutable borrow occurs here
+LL | gen.as_mut().resume(&mut thing);
+ | ^^^^^^^^^^ second mutable borrow occurs here
+LL |
+LL | }
+ | - first borrow might be used here, when `gen` is dropped and runs the destructor for generator
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0499`.
diff --git a/tests/ui/generator/retain-resume-ref.no_drop_tracking.stderr b/tests/ui/generator/retain-resume-ref.no_drop_tracking.stderr
new file mode 100644
index 000000000..7122a951e
--- /dev/null
+++ b/tests/ui/generator/retain-resume-ref.no_drop_tracking.stderr
@@ -0,0 +1,13 @@
+error[E0499]: cannot borrow `thing` as mutable more than once at a time
+ --> $DIR/retain-resume-ref.rs:27:25
+ |
+LL | gen.as_mut().resume(&mut thing);
+ | ---------- first mutable borrow occurs here
+LL | gen.as_mut().resume(&mut thing);
+ | ------ ^^^^^^^^^^ second mutable borrow occurs here
+ | |
+ | first borrow later used by call
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0499`.
diff --git a/tests/ui/generator/retain-resume-ref.rs b/tests/ui/generator/retain-resume-ref.rs
index 0606ea71c..0050d98d0 100644
--- a/tests/ui/generator/retain-resume-ref.rs
+++ b/tests/ui/generator/retain-resume-ref.rs
@@ -1,3 +1,7 @@
+// revisions: no_drop_tracking drop_tracking drop_tracking_mir
+// [drop_tracking] compile-flags: -Zdrop-tracking
+// [drop_tracking_mir] compile-flags: -Zdrop-tracking-mir
+
//! This test ensures that a mutable reference cannot be passed as a resume argument twice.
#![feature(generators, generator_trait)]
diff --git a/tests/ui/generator/retain-resume-ref.stderr b/tests/ui/generator/retain-resume-ref.stderr
index e33310d12..7122a951e 100644
--- a/tests/ui/generator/retain-resume-ref.stderr
+++ b/tests/ui/generator/retain-resume-ref.stderr
@@ -1,5 +1,5 @@
error[E0499]: cannot borrow `thing` as mutable more than once at a time
- --> $DIR/retain-resume-ref.rs:23:25
+ --> $DIR/retain-resume-ref.rs:27:25
|
LL | gen.as_mut().resume(&mut thing);
| ---------- first mutable borrow occurs here
diff --git a/tests/ui/generator/static-mut-reference-across-yield.rs b/tests/ui/generator/static-mut-reference-across-yield.rs
index 0fa6d9cdc..4784ff49b 100644
--- a/tests/ui/generator/static-mut-reference-across-yield.rs
+++ b/tests/ui/generator/static-mut-reference-across-yield.rs
@@ -1,6 +1,8 @@
// build-pass
-// revisions: mir thir
+// revisions: mir thir drop_tracking drop_tracking_mir
// [thir]compile-flags: -Zthir-unsafeck
+// [drop_tracking] compile-flags: -Zdrop-tracking
+// [drop_tracking_mir] compile-flags: -Zdrop-tracking-mir
#![feature(generators)]
diff --git a/tests/ui/generator/type-mismatch-signature-deduction.stderr b/tests/ui/generator/type-mismatch-signature-deduction.stderr
index b98da1ed8..ef6d896f8 100644
--- a/tests/ui/generator/type-mismatch-signature-deduction.stderr
+++ b/tests/ui/generator/type-mismatch-signature-deduction.stderr
@@ -2,7 +2,7 @@ error[E0308]: mismatched types
--> $DIR/type-mismatch-signature-deduction.rs:14:9
|
LL | 5
- | ^ expected enum `Result`, found integer
+ | ^ expected `Result<{integer}, _>`, found integer
|
= note: expected enum `Result<{integer}, _>`
found type `{integer}`
@@ -22,7 +22,7 @@ error[E0271]: type mismatch resolving `<[generator@$DIR/type-mismatch-signature-
--> $DIR/type-mismatch-signature-deduction.rs:5:13
|
LL | fn foo() -> impl Generator<Return = i32> {
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected enum `Result`, found `i32`
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `Result<{integer}, _>`, found `i32`
|
= note: expected enum `Result<{integer}, _>`
found type `i32`
diff --git a/tests/ui/generic-associated-types/bugs/issue-88460.stderr b/tests/ui/generic-associated-types/bugs/issue-88460.stderr
index 6612c4b49..a2047f103 100644
--- a/tests/ui/generic-associated-types/bugs/issue-88460.stderr
+++ b/tests/ui/generic-associated-types/bugs/issue-88460.stderr
@@ -11,7 +11,7 @@ note: required by a bound in `test`
--> $DIR/issue-88460.rs:15:27
|
LL | fn test<T>(value: T)
- | ---- required by a bound in this
+ | ---- required by a bound in this function
...
LL | for<'a> T::Assoc<'a>: Marker,
| ^^^^^^ required by this bound in `test`
diff --git a/tests/ui/generic-associated-types/collections-project-default.stderr b/tests/ui/generic-associated-types/collections-project-default.stderr
index 5701017dc..3c3ae24dd 100644
--- a/tests/ui/generic-associated-types/collections-project-default.stderr
+++ b/tests/ui/generic-associated-types/collections-project-default.stderr
@@ -5,10 +5,11 @@ LL | fn floatify_sibling<C>(ints: &C) -> <C as Collection<i32>>::Sibling<f32>
| ------------------------------------ expected `<C as Collection<i32>>::Sibling<f32>` because of return type
...
LL | res
- | ^^^ expected Collection::Sibling, found CollectionFamily::Member
+ | ^^^ expected `Collection::Sibling`, found `CollectionFamily::Member`
|
= note: expected associated type `<C as Collection<i32>>::Sibling<f32>`
found associated type `<<C as Collection<i32>>::Family as CollectionFamily>::Member<f32>`
+ = note: an associated type was expected, but a different one was found
error: aborting due to previous error
diff --git a/tests/ui/generic-associated-types/constraint-assoc-type-suggestion.stderr b/tests/ui/generic-associated-types/constraint-assoc-type-suggestion.stderr
index 96c4330fe..3b65b32f4 100644
--- a/tests/ui/generic-associated-types/constraint-assoc-type-suggestion.stderr
+++ b/tests/ui/generic-associated-types/constraint-assoc-type-suggestion.stderr
@@ -2,7 +2,7 @@ error[E0308]: mismatched types
--> $DIR/constraint-assoc-type-suggestion.rs:10:23
|
LL | let b: Vec<i32> = a;
- | -------- ^ expected struct `Vec`, found associated type
+ | -------- ^ expected `Vec<i32>`, found associated type
| |
| expected due to this
|
diff --git a/tests/ui/generic-associated-types/gat-trait-path-parenthesised-args.rs b/tests/ui/generic-associated-types/gat-trait-path-parenthesised-args.rs
index 9eb069637..5738dfa83 100644
--- a/tests/ui/generic-associated-types/gat-trait-path-parenthesised-args.rs
+++ b/tests/ui/generic-associated-types/gat-trait-path-parenthesised-args.rs
@@ -5,12 +5,12 @@ trait X {
fn foo<'a>(arg: Box<dyn X<Y('a) = &'a ()>>) {}
//~^ ERROR: lifetime in trait object type must be followed by `+`
//~| ERROR: parenthesized generic arguments cannot be used
- //~| ERROR this associated type takes 0 generic arguments but 1 generic argument
- //~| ERROR this associated type takes 1 lifetime argument but 0 lifetime arguments
+ //~| ERROR associated type takes 0 generic arguments but 1 generic argument
+ //~| ERROR associated type takes 1 lifetime argument but 0 lifetime arguments
fn bar<'a>(arg: Box<dyn X<Y() = ()>>) {}
//~^ ERROR: parenthesized generic arguments cannot be used
- //~| ERROR this associated type takes 1 lifetime argument but 0 lifetime arguments
+ //~| ERROR associated type takes 1 lifetime argument but 0 lifetime arguments
fn main() {}
diff --git a/tests/ui/generic-associated-types/gat-trait-path-parenthesised-args.stderr b/tests/ui/generic-associated-types/gat-trait-path-parenthesised-args.stderr
index 165779796..461853379 100644
--- a/tests/ui/generic-associated-types/gat-trait-path-parenthesised-args.stderr
+++ b/tests/ui/generic-associated-types/gat-trait-path-parenthesised-args.stderr
@@ -23,7 +23,7 @@ LL | fn bar<'a>(arg: Box<dyn X<Y() = ()>>) {}
| |
| help: remove these parentheses
-error[E0107]: this associated type takes 1 lifetime argument but 0 lifetime arguments were supplied
+error[E0107]: associated type takes 1 lifetime argument but 0 lifetime arguments were supplied
--> $DIR/gat-trait-path-parenthesised-args.rs:5:27
|
LL | fn foo<'a>(arg: Box<dyn X<Y('a) = &'a ()>>) {}
@@ -39,7 +39,7 @@ help: add missing lifetime argument
LL | fn foo<'a>(arg: Box<dyn X<Y('_, 'a) = &'a ()>>) {}
| +++
-error[E0107]: this associated type takes 0 generic arguments but 1 generic argument was supplied
+error[E0107]: associated type takes 0 generic arguments but 1 generic argument was supplied
--> $DIR/gat-trait-path-parenthesised-args.rs:5:27
|
LL | fn foo<'a>(arg: Box<dyn X<Y('a) = &'a ()>>) {}
@@ -53,7 +53,7 @@ note: associated type defined here, with 0 generic parameters
LL | type Y<'a>;
| ^
-error[E0107]: this associated type takes 1 lifetime argument but 0 lifetime arguments were supplied
+error[E0107]: associated type takes 1 lifetime argument but 0 lifetime arguments were supplied
--> $DIR/gat-trait-path-parenthesised-args.rs:12:27
|
LL | fn bar<'a>(arg: Box<dyn X<Y() = ()>>) {}
diff --git a/tests/ui/generic-associated-types/issue-101020.stderr b/tests/ui/generic-associated-types/issue-101020.stderr
index 1f9273a8c..5c8db617c 100644
--- a/tests/ui/generic-associated-types/issue-101020.stderr
+++ b/tests/ui/generic-associated-types/issue-101020.stderr
@@ -13,7 +13,7 @@ note: required by a bound in `LendingIterator::consume`
--> $DIR/issue-101020.rs:9:33
|
LL | fn consume<F>(self, _f: F)
- | ------- required by a bound in this
+ | ------- required by a bound in this associated function
...
LL | for<'a> Self::Item<'a>: FuncInput<'a, Self::Item<'a>>,
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `LendingIterator::consume`
diff --git a/tests/ui/generic-associated-types/issue-68656-unsized-values.stderr b/tests/ui/generic-associated-types/issue-68656-unsized-values.stderr
index e8770aedf..f0212e985 100644
--- a/tests/ui/generic-associated-types/issue-68656-unsized-values.stderr
+++ b/tests/ui/generic-associated-types/issue-68656-unsized-values.stderr
@@ -15,8 +15,8 @@ LL | type Item<'a>: std::ops::Deref<Target = T>;
| ^^^^^^^^^^ required by this bound in `UnsafeCopy::Item`
help: consider further restricting this bound
|
-LL | impl<T: Copy + std::ops::Deref + Deref<Target = T>> UnsafeCopy<T> for T {
- | +++++++++++++++++++
+LL | impl<T: Copy + std::ops::Deref<Target = T>> UnsafeCopy<T> for T {
+ | ++++++++++++
error: aborting due to previous error
diff --git a/tests/ui/generic-associated-types/issue-74684-1.stderr b/tests/ui/generic-associated-types/issue-74684-1.stderr
index cacc97307..b93ee3798 100644
--- a/tests/ui/generic-associated-types/issue-74684-1.stderr
+++ b/tests/ui/generic-associated-types/issue-74684-1.stderr
@@ -4,6 +4,7 @@ error[E0597]: `a` does not live long enough
LL | fn bug<'a, T: ?Sized + Fun<F<'a> = [u8]>>(_ : Box<T>) -> &'static T::F<'a> {
| -- lifetime `'a` defined here
LL | let a = [0; 1];
+ | - binding `a` declared here
LL | let _x = T::identity(&a);
| ------------^^-
| | |
diff --git a/tests/ui/generic-associated-types/issue-79422.extended.stderr b/tests/ui/generic-associated-types/issue-79422.extended.stderr
index d79de0ca6..04184fce9 100644
--- a/tests/ui/generic-associated-types/issue-79422.extended.stderr
+++ b/tests/ui/generic-associated-types/issue-79422.extended.stderr
@@ -14,11 +14,11 @@ help: add missing lifetime argument
LL | as Box<dyn MapLike<u8, u8, VRefCont<'a> = dyn RefCont<'_, u8>>>;
| ++++
-error[E0271]: type mismatch resolving `<BTreeMap<u8, u8> as MapLike<u8, u8>>::VRefCont<'_> == (dyn RefCont<'_, u8> + 'static)`
+error[E0271]: type mismatch resolving `<BTreeMap<u8, u8> as MapLike<u8, u8>>::VRefCont<'_> == dyn RefCont<'_, u8>`
--> $DIR/issue-79422.rs:44:13
|
LL | let m = Box::new(std::collections::BTreeMap::<u8, u8>::new())
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type mismatch resolving `<BTreeMap<u8, u8> as MapLike<u8, u8>>::VRefCont<'_> == (dyn RefCont<'_, u8> + 'static)`
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type mismatch resolving `<BTreeMap<u8, u8> as MapLike<u8, u8>>::VRefCont<'_> == dyn RefCont<'_, u8>`
|
note: expected this to be `(dyn RefCont<'_, u8> + 'static)`
--> $DIR/issue-79422.rs:28:25
diff --git a/tests/ui/generic-associated-types/issue-88360.fixed b/tests/ui/generic-associated-types/issue-88360.fixed
new file mode 100644
index 000000000..3dea8bf7a
--- /dev/null
+++ b/tests/ui/generic-associated-types/issue-88360.fixed
@@ -0,0 +1,20 @@
+// run-rustfix
+
+trait GatTrait {
+ type Gat<'a> where Self: 'a;
+
+ fn test(&self) -> Self::Gat<'_>;
+}
+
+trait SuperTrait<T>
+where
+ Self: 'static,
+ for<'a> Self: GatTrait<Gat<'a> = &'a T>,
+{
+ fn copy(&self) -> Self::Gat<'_> where T: Copy {
+ self.test()
+ //~^ mismatched types
+ }
+}
+
+fn main() {}
diff --git a/tests/ui/generic-associated-types/issue-88360.rs b/tests/ui/generic-associated-types/issue-88360.rs
index c02690618..4d4c7ea31 100644
--- a/tests/ui/generic-associated-types/issue-88360.rs
+++ b/tests/ui/generic-associated-types/issue-88360.rs
@@ -1,3 +1,5 @@
+// run-rustfix
+
trait GatTrait {
type Gat<'a> where Self: 'a;
diff --git a/tests/ui/generic-associated-types/issue-88360.stderr b/tests/ui/generic-associated-types/issue-88360.stderr
index cd3750344..520aeff18 100644
--- a/tests/ui/generic-associated-types/issue-88360.stderr
+++ b/tests/ui/generic-associated-types/issue-88360.stderr
@@ -1,5 +1,5 @@
error[E0308]: mismatched types
- --> $DIR/issue-88360.rs:13:9
+ --> $DIR/issue-88360.rs:15:9
|
LL | trait SuperTrait<T>
| - this type parameter
@@ -7,13 +7,15 @@ LL | trait SuperTrait<T>
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()`
+ | ^^^^^^^^^^^^ expected `&T`, found type parameter `T`
|
= note: expected reference `&T`
found type parameter `T`
+help: consider removing deref here
+ |
+LL - *self.test()
+LL + self.test()
+ |
error: aborting due to previous error
diff --git a/tests/ui/generic-associated-types/method-unsatified-assoc-type-predicate.rs b/tests/ui/generic-associated-types/method-unsatisfied-assoc-type-predicate.rs
index 83655341d..83655341d 100644
--- a/tests/ui/generic-associated-types/method-unsatified-assoc-type-predicate.rs
+++ b/tests/ui/generic-associated-types/method-unsatisfied-assoc-type-predicate.rs
diff --git a/tests/ui/generic-associated-types/method-unsatified-assoc-type-predicate.stderr b/tests/ui/generic-associated-types/method-unsatisfied-assoc-type-predicate.stderr
index baef38f6b..4246f8c06 100644
--- a/tests/ui/generic-associated-types/method-unsatified-assoc-type-predicate.stderr
+++ b/tests/ui/generic-associated-types/method-unsatisfied-assoc-type-predicate.stderr
@@ -1,5 +1,5 @@
error[E0599]: the method `f` exists for struct `S`, but its trait bounds were not satisfied
- --> $DIR/method-unsatified-assoc-type-predicate.rs:28:7
+ --> $DIR/method-unsatisfied-assoc-type-predicate.rs:28:7
|
LL | struct S;
| --------
@@ -12,7 +12,7 @@ LL | a.f();
| ^ method cannot be called on `S` due to unsatisfied trait bounds
|
note: trait bound `<S as X>::Y<i32> = i32` was not satisfied
- --> $DIR/method-unsatified-assoc-type-predicate.rs:12:11
+ --> $DIR/method-unsatisfied-assoc-type-predicate.rs:12:11
|
LL | impl<T: X<Y<i32> = i32>> M for T {}
| ^^^^^^^^^^^^ - -
diff --git a/tests/ui/generic-associated-types/missing-bounds.fixed b/tests/ui/generic-associated-types/missing-bounds.fixed
index ee758f19e..054adbffb 100644
--- a/tests/ui/generic-associated-types/missing-bounds.fixed
+++ b/tests/ui/generic-associated-types/missing-bounds.fixed
@@ -4,7 +4,7 @@ use std::ops::Add;
struct A<B>(B);
-impl<B> Add for A<B> where B: Add + Add<Output = B> {
+impl<B> Add for A<B> where B: Add<Output = B> {
type Output = Self;
fn add(self, rhs: Self) -> Self {
@@ -14,7 +14,7 @@ impl<B> Add for A<B> where B: Add + Add<Output = B> {
struct C<B>(B);
-impl<B: Add + Add<Output = B>> Add for C<B> {
+impl<B: Add<Output = B>> Add for C<B> {
type Output = Self;
fn add(self, rhs: Self) -> Self {
@@ -34,7 +34,7 @@ impl<B: std::ops::Add<Output = B>> Add for D<B> {
struct E<B>(B);
-impl<B: Add + Add<Output = B>> Add for E<B> where B: Add<Output = B> {
+impl<B: Add<Output = B>> Add for E<B> where B: Add<Output = B> {
//~^ ERROR equality constraints are not yet supported in `where` clauses
type Output = Self;
diff --git a/tests/ui/generic-associated-types/missing-bounds.stderr b/tests/ui/generic-associated-types/missing-bounds.stderr
index 9f669b9a5..535edec57 100644
--- a/tests/ui/generic-associated-types/missing-bounds.stderr
+++ b/tests/ui/generic-associated-types/missing-bounds.stderr
@@ -37,8 +37,8 @@ LL | struct A<B>(B);
| ^
help: consider further restricting this bound
|
-LL | impl<B> Add for A<B> where B: Add + Add<Output = B> {
- | +++++++++++++++++
+LL | impl<B> Add for A<B> where B: Add<Output = B> {
+ | ++++++++++++
error[E0308]: mismatched types
--> $DIR/missing-bounds.rs:21:14
@@ -60,8 +60,8 @@ LL | struct C<B>(B);
| ^
help: consider further restricting this bound
|
-LL | impl<B: Add + Add<Output = B>> Add for C<B> {
- | +++++++++++++++++
+LL | impl<B: Add<Output = B>> Add for C<B> {
+ | ++++++++++++
error[E0369]: cannot add `B` to `B`
--> $DIR/missing-bounds.rs:31:21
@@ -96,8 +96,8 @@ LL | struct E<B>(B);
| ^
help: consider further restricting this bound
|
-LL | impl<B: Add + Add<Output = B>> Add for E<B> where <B as Add>::Output = B {
- | +++++++++++++++++
+LL | impl<B: Add<Output = B>> Add for E<B> where <B as Add>::Output = B {
+ | ++++++++++++
error: aborting due to 5 previous errors
diff --git a/tests/ui/generic-associated-types/missing_lifetime_args.rs b/tests/ui/generic-associated-types/missing_lifetime_args.rs
index 78def8092..331511ba6 100644
--- a/tests/ui/generic-associated-types/missing_lifetime_args.rs
+++ b/tests/ui/generic-associated-types/missing_lifetime_args.rs
@@ -12,9 +12,9 @@ fn foo<'c, 'd>(_arg: Box<dyn X<Y = (&'c u32, &'d u32)>>) {}
//~^ ERROR missing generics for associated type
fn bar<'a, 'b, 'c>(_arg: Foo<'a, 'b>) {}
-//~^ ERROR this struct takes 3 lifetime arguments but 2 lifetime
+//~^ ERROR struct takes 3 lifetime arguments but 2 lifetime
fn f<'a>(_arg: Foo<'a>) {}
-//~^ ERROR this struct takes 3 lifetime arguments but 1 lifetime
+//~^ ERROR struct takes 3 lifetime arguments but 1 lifetime
fn main() {}
diff --git a/tests/ui/generic-associated-types/missing_lifetime_args.stderr b/tests/ui/generic-associated-types/missing_lifetime_args.stderr
index 8f74b12c0..1a7a2e787 100644
--- a/tests/ui/generic-associated-types/missing_lifetime_args.stderr
+++ b/tests/ui/generic-associated-types/missing_lifetime_args.stderr
@@ -14,7 +14,7 @@ help: add missing lifetime arguments
LL | fn foo<'c, 'd>(_arg: Box<dyn X<Y<'_, '_> = (&'c u32, &'d u32)>>) {}
| ++++++++
-error[E0107]: this struct takes 3 lifetime arguments but 2 lifetime arguments were supplied
+error[E0107]: struct takes 3 lifetime arguments but 2 lifetime arguments were supplied
--> $DIR/missing_lifetime_args.rs:14:26
|
LL | fn bar<'a, 'b, 'c>(_arg: Foo<'a, 'b>) {}
@@ -32,7 +32,7 @@ help: add missing lifetime argument
LL | fn bar<'a, 'b, 'c>(_arg: Foo<'a, 'b, 'a>) {}
| ++++
-error[E0107]: this struct takes 3 lifetime arguments but 1 lifetime argument was supplied
+error[E0107]: struct takes 3 lifetime arguments but 1 lifetime argument was supplied
--> $DIR/missing_lifetime_args.rs:17:16
|
LL | fn f<'a>(_arg: Foo<'a>) {}
diff --git a/tests/ui/generic-associated-types/missing_lifetime_const.rs b/tests/ui/generic-associated-types/missing_lifetime_const.rs
index 8b174b9e9..6e395dfde 100644
--- a/tests/ui/generic-associated-types/missing_lifetime_const.rs
+++ b/tests/ui/generic-associated-types/missing_lifetime_const.rs
@@ -4,7 +4,7 @@ trait Foo {
fn foo<T: Foo>() {
let _: <T as Foo>::Assoc<3>;
- //~^ ERROR this associated type
+ //~^ ERROR associated type
}
fn main() {}
diff --git a/tests/ui/generic-associated-types/missing_lifetime_const.stderr b/tests/ui/generic-associated-types/missing_lifetime_const.stderr
index 62d2e9f49..41945aabf 100644
--- a/tests/ui/generic-associated-types/missing_lifetime_const.stderr
+++ b/tests/ui/generic-associated-types/missing_lifetime_const.stderr
@@ -1,4 +1,4 @@
-error[E0107]: this associated type takes 1 lifetime argument but 0 lifetime arguments were supplied
+error[E0107]: associated type takes 1 lifetime argument but 0 lifetime arguments were supplied
--> $DIR/missing_lifetime_const.rs:6:24
|
LL | let _: <T as Foo>::Assoc<3>;
diff --git a/tests/ui/generic-associated-types/parameter_number_and_kind.rs b/tests/ui/generic-associated-types/parameter_number_and_kind.rs
index 8428e7763..ae2f7c00e 100644
--- a/tests/ui/generic-associated-types/parameter_number_and_kind.rs
+++ b/tests/ui/generic-associated-types/parameter_number_and_kind.rs
@@ -9,10 +9,10 @@ trait Foo {
// Test parameters in default values
type FOk<T> = Self::E<'static, T>;
type FErr1 = Self::E<'static, 'static>;
- //~^ ERROR this associated type takes 1 lifetime argument but 2 lifetime arguments were supplied
- //~| ERROR this associated type takes 1
+ //~^ ERROR associated type takes 1 lifetime argument but 2 lifetime arguments were supplied
+ //~| ERROR associated type takes 1
type FErr2<T> = Self::E<'static, T, u32>;
- //~^ ERROR this associated type takes 1
+ //~^ ERROR associated type takes 1
}
fn main() {}
diff --git a/tests/ui/generic-associated-types/parameter_number_and_kind.stderr b/tests/ui/generic-associated-types/parameter_number_and_kind.stderr
index c20b9669e..4523044b5 100644
--- a/tests/ui/generic-associated-types/parameter_number_and_kind.stderr
+++ b/tests/ui/generic-associated-types/parameter_number_and_kind.stderr
@@ -1,4 +1,4 @@
-error[E0107]: this associated type takes 1 lifetime argument but 2 lifetime arguments were supplied
+error[E0107]: associated type takes 1 lifetime argument but 2 lifetime arguments were supplied
--> $DIR/parameter_number_and_kind.rs:11:24
|
LL | type FErr1 = Self::E<'static, 'static>;
@@ -12,7 +12,7 @@ note: associated type defined here, with 1 lifetime parameter: `'a`
LL | type E<'a, T>;
| ^ --
-error[E0107]: this associated type takes 1 generic argument but 0 generic arguments were supplied
+error[E0107]: associated type takes 1 generic argument but 0 generic arguments were supplied
--> $DIR/parameter_number_and_kind.rs:11:24
|
LL | type FErr1 = Self::E<'static, 'static>;
@@ -28,7 +28,7 @@ help: add missing generic argument
LL | type FErr1 = Self::E<'static, 'static, T>;
| +++
-error[E0107]: this associated type takes 1 generic argument but 2 generic arguments were supplied
+error[E0107]: associated type takes 1 generic argument but 2 generic arguments were supplied
--> $DIR/parameter_number_and_kind.rs:14:27
|
LL | type FErr2<T> = Self::E<'static, T, u32>;
diff --git a/tests/ui/generic-associated-types/parse/trait-path-type-error-once-implemented.rs b/tests/ui/generic-associated-types/parse/trait-path-type-error-once-implemented.rs
index 1622b92aa..c58f9cf1d 100644
--- a/tests/ui/generic-associated-types/parse/trait-path-type-error-once-implemented.rs
+++ b/tests/ui/generic-associated-types/parse/trait-path-type-error-once-implemented.rs
@@ -4,8 +4,8 @@ trait X {
const _: () = {
fn f2<'a>(arg : Box<dyn X<Y<1> = &'a ()>>) {}
- //~^ ERROR this associated type takes 1 lifetime argument but 0 lifetime arguments
- //~| ERROR this associated type takes 0 generic arguments but 1 generic argument
+ //~^ ERROR associated type takes 1 lifetime argument but 0 lifetime arguments
+ //~| ERROR associated type takes 0 generic arguments but 1 generic argument
};
fn main() {}
diff --git a/tests/ui/generic-associated-types/parse/trait-path-type-error-once-implemented.stderr b/tests/ui/generic-associated-types/parse/trait-path-type-error-once-implemented.stderr
index 0a09ec5dc..fab5b474d 100644
--- a/tests/ui/generic-associated-types/parse/trait-path-type-error-once-implemented.stderr
+++ b/tests/ui/generic-associated-types/parse/trait-path-type-error-once-implemented.stderr
@@ -1,4 +1,4 @@
-error[E0107]: this associated type takes 1 lifetime argument but 0 lifetime arguments were supplied
+error[E0107]: associated type takes 1 lifetime argument but 0 lifetime arguments were supplied
--> $DIR/trait-path-type-error-once-implemented.rs:6:29
|
LL | fn f2<'a>(arg : Box<dyn X<Y<1> = &'a ()>>) {}
@@ -14,7 +14,7 @@ help: add missing lifetime argument
LL | fn f2<'a>(arg : Box<dyn X<Y<'_, 1> = &'a ()>>) {}
| +++
-error[E0107]: this associated type takes 0 generic arguments but 1 generic argument was supplied
+error[E0107]: associated type takes 0 generic arguments but 1 generic argument was supplied
--> $DIR/trait-path-type-error-once-implemented.rs:6:29
|
LL | fn f2<'a>(arg : Box<dyn X<Y<1> = &'a ()>>) {}
diff --git a/tests/ui/generic-associated-types/unsatified-item-lifetime-bound.rs b/tests/ui/generic-associated-types/unsatisfied-item-lifetime-bound.rs
index 1cc09aa6d..060ee8821 100644
--- a/tests/ui/generic-associated-types/unsatified-item-lifetime-bound.rs
+++ b/tests/ui/generic-associated-types/unsatisfied-item-lifetime-bound.rs
@@ -1,3 +1,5 @@
+#![warn(unused_lifetimes)]
+
pub trait X {
type Y<'a: 'static>;
//~^ WARNING unnecessary lifetime parameter
diff --git a/tests/ui/generic-associated-types/unsatified-item-lifetime-bound.stderr b/tests/ui/generic-associated-types/unsatisfied-item-lifetime-bound.stderr
index fbd79879d..a69cd0028 100644
--- a/tests/ui/generic-associated-types/unsatified-item-lifetime-bound.stderr
+++ b/tests/ui/generic-associated-types/unsatisfied-item-lifetime-bound.stderr
@@ -1,45 +1,50 @@
warning: unnecessary lifetime parameter `'a`
- --> $DIR/unsatified-item-lifetime-bound.rs:2:12
+ --> $DIR/unsatisfied-item-lifetime-bound.rs:4:12
|
LL | type Y<'a: 'static>;
| ^^
|
= help: you can use the `'static` lifetime directly, in place of `'a`
+note: the lint level is defined here
+ --> $DIR/unsatisfied-item-lifetime-bound.rs:1:9
+ |
+LL | #![warn(unused_lifetimes)]
+ | ^^^^^^^^^^^^^^^^
error[E0478]: lifetime bound not satisfied
- --> $DIR/unsatified-item-lifetime-bound.rs:11:8
+ --> $DIR/unsatisfied-item-lifetime-bound.rs:13:8
|
LL | f: <T as X>::Y<'a>,
| ^^^^^^^^^^^^^^^
|
note: lifetime parameter instantiated with the lifetime `'a` as defined here
- --> $DIR/unsatified-item-lifetime-bound.rs:10:10
+ --> $DIR/unsatisfied-item-lifetime-bound.rs:12:10
|
LL | struct B<'a, T: for<'r> X<Y<'r> = &'r ()>> {
| ^^
= note: but lifetime parameter must outlive the static lifetime
error[E0478]: lifetime bound not satisfied
- --> $DIR/unsatified-item-lifetime-bound.rs:16:8
+ --> $DIR/unsatisfied-item-lifetime-bound.rs:18:8
|
LL | f: <T as X>::Y<'a>,
| ^^^^^^^^^^^^^^^
|
note: lifetime parameter instantiated with the lifetime `'a` as defined here
- --> $DIR/unsatified-item-lifetime-bound.rs:15:10
+ --> $DIR/unsatisfied-item-lifetime-bound.rs:17:10
|
LL | struct C<'a, T: X> {
| ^^
= note: but lifetime parameter must outlive the static lifetime
error[E0478]: lifetime bound not satisfied
- --> $DIR/unsatified-item-lifetime-bound.rs:21:8
+ --> $DIR/unsatisfied-item-lifetime-bound.rs:23:8
|
LL | f: <() as X>::Y<'a>,
| ^^^^^^^^^^^^^^^^
|
note: lifetime parameter instantiated with the lifetime `'a` as defined here
- --> $DIR/unsatified-item-lifetime-bound.rs:20:10
+ --> $DIR/unsatisfied-item-lifetime-bound.rs:22:10
|
LL | struct D<'a> {
| ^^
diff --git a/tests/ui/generics/bad-mid-path-type-params.rs b/tests/ui/generics/bad-mid-path-type-params.rs
index 23a5d1525..37d484cba 100644
--- a/tests/ui/generics/bad-mid-path-type-params.rs
+++ b/tests/ui/generics/bad-mid-path-type-params.rs
@@ -28,17 +28,17 @@ impl Trait<isize> for S2 {
fn foo<'a>() {
let _ = S::new::<isize,f64>(1, 1.0);
- //~^ ERROR this associated function takes 1
+ //~^ ERROR associated function takes 1
let _ = S::<'a,isize>::new::<f64>(1, 1.0);
- //~^ ERROR this struct takes 0 lifetime arguments but 1 lifetime argument was supplied
+ //~^ ERROR struct takes 0 lifetime arguments but 1 lifetime argument was supplied
let _: S2 = Trait::new::<isize,f64>(1, 1.0);
- //~^ ERROR this associated function takes 1
+ //~^ ERROR associated function takes 1
let _: S2 = Trait::<'a,isize>::new::<f64,f64>(1, 1.0);
- //~^ ERROR this trait takes 0 lifetime arguments but 1 lifetime argument was supplied
- //~| ERROR this associated function takes 1
+ //~^ ERROR trait takes 0 lifetime arguments but 1 lifetime argument was supplied
+ //~| ERROR associated function takes 1
}
fn main() {}
diff --git a/tests/ui/generics/bad-mid-path-type-params.stderr b/tests/ui/generics/bad-mid-path-type-params.stderr
index aee2b6015..71e15dd4c 100644
--- a/tests/ui/generics/bad-mid-path-type-params.stderr
+++ b/tests/ui/generics/bad-mid-path-type-params.stderr
@@ -1,4 +1,4 @@
-error[E0107]: this associated function takes 1 generic argument but 2 generic arguments were supplied
+error[E0107]: associated function takes 1 generic argument but 2 generic arguments were supplied
--> $DIR/bad-mid-path-type-params.rs:30:16
|
LL | let _ = S::new::<isize,f64>(1, 1.0);
@@ -12,7 +12,7 @@ note: associated function defined here, with 1 generic parameter: `U`
LL | fn new<U>(x: T, _: U) -> S<T> {
| ^^^ -
-error[E0107]: this struct takes 0 lifetime arguments but 1 lifetime argument was supplied
+error[E0107]: struct takes 0 lifetime arguments but 1 lifetime argument was supplied
--> $DIR/bad-mid-path-type-params.rs:33:13
|
LL | let _ = S::<'a,isize>::new::<f64>(1, 1.0);
@@ -26,7 +26,7 @@ note: struct defined here, with 0 lifetime parameters
LL | struct S<T> {
| ^
-error[E0107]: this associated function takes 1 generic argument but 2 generic arguments were supplied
+error[E0107]: associated function takes 1 generic argument but 2 generic arguments were supplied
--> $DIR/bad-mid-path-type-params.rs:36:24
|
LL | let _: S2 = Trait::new::<isize,f64>(1, 1.0);
@@ -40,7 +40,7 @@ note: associated function defined here, with 1 generic parameter: `U`
LL | fn new<U>(x: T, y: U) -> Self;
| ^^^ -
-error[E0107]: this trait takes 0 lifetime arguments but 1 lifetime argument was supplied
+error[E0107]: trait takes 0 lifetime arguments but 1 lifetime argument was supplied
--> $DIR/bad-mid-path-type-params.rs:39:17
|
LL | let _: S2 = Trait::<'a,isize>::new::<f64,f64>(1, 1.0);
@@ -54,7 +54,7 @@ note: trait defined here, with 0 lifetime parameters
LL | trait Trait<T> {
| ^^^^^
-error[E0107]: this associated function takes 1 generic argument but 2 generic arguments were supplied
+error[E0107]: associated function takes 1 generic argument but 2 generic arguments were supplied
--> $DIR/bad-mid-path-type-params.rs:39:36
|
LL | let _: S2 = Trait::<'a,isize>::new::<f64,f64>(1, 1.0);
diff --git a/tests/ui/generics/generic-arg-mismatch-recover.rs b/tests/ui/generics/generic-arg-mismatch-recover.rs
index 2cf7f1d65..947f33414 100644
--- a/tests/ui/generics/generic-arg-mismatch-recover.rs
+++ b/tests/ui/generics/generic-arg-mismatch-recover.rs
@@ -4,9 +4,9 @@ struct Bar<'a>(&'a ());
fn main() {
Foo::<'static, 'static, ()>(&0);
- //~^ ERROR this struct takes 1 lifetime argument but 2 lifetime arguments were supplied
+ //~^ ERROR struct takes 1 lifetime argument but 2 lifetime arguments were supplied
Bar::<'static, 'static, ()>(&());
- //~^ ERROR this struct takes 1 lifetime argument but 2 lifetime arguments were supplied
- //~| ERROR this struct takes 0
+ //~^ ERROR struct takes 1 lifetime argument but 2 lifetime arguments were supplied
+ //~| ERROR struct takes 0
}
diff --git a/tests/ui/generics/generic-arg-mismatch-recover.stderr b/tests/ui/generics/generic-arg-mismatch-recover.stderr
index 45fea925f..f549a7180 100644
--- a/tests/ui/generics/generic-arg-mismatch-recover.stderr
+++ b/tests/ui/generics/generic-arg-mismatch-recover.stderr
@@ -1,4 +1,4 @@
-error[E0107]: this struct takes 1 lifetime argument but 2 lifetime arguments were supplied
+error[E0107]: struct takes 1 lifetime argument but 2 lifetime arguments were supplied
--> $DIR/generic-arg-mismatch-recover.rs:6:5
|
LL | Foo::<'static, 'static, ()>(&0);
@@ -12,7 +12,7 @@ note: struct defined here, with 1 lifetime parameter: `'a`
LL | struct Foo<'a, T: 'a>(&'a T);
| ^^^ --
-error[E0107]: this struct takes 1 lifetime argument but 2 lifetime arguments were supplied
+error[E0107]: struct takes 1 lifetime argument but 2 lifetime arguments were supplied
--> $DIR/generic-arg-mismatch-recover.rs:9:5
|
LL | Bar::<'static, 'static, ()>(&());
@@ -26,7 +26,7 @@ note: struct defined here, with 1 lifetime parameter: `'a`
LL | struct Bar<'a>(&'a ());
| ^^^ --
-error[E0107]: this struct takes 0 generic arguments but 1 generic argument was supplied
+error[E0107]: struct takes 0 generic arguments but 1 generic argument was supplied
--> $DIR/generic-arg-mismatch-recover.rs:9:5
|
LL | Bar::<'static, 'static, ()>(&());
diff --git a/tests/ui/generics/generic-impl-less-params-with-defaults.rs b/tests/ui/generics/generic-impl-less-params-with-defaults.rs
index 66afbb58a..6c0041156 100644
--- a/tests/ui/generics/generic-impl-less-params-with-defaults.rs
+++ b/tests/ui/generics/generic-impl-less-params-with-defaults.rs
@@ -9,5 +9,5 @@ impl<A, B, C> Foo<A, B, C> {
fn main() {
Foo::<isize>::new();
- //~^ ERROR this struct takes at least 2 generic arguments but 1 generic argument
+ //~^ ERROR struct takes at least 2 generic arguments but 1 generic argument
}
diff --git a/tests/ui/generics/generic-impl-less-params-with-defaults.stderr b/tests/ui/generics/generic-impl-less-params-with-defaults.stderr
index cdbb57902..262561fa8 100644
--- a/tests/ui/generics/generic-impl-less-params-with-defaults.stderr
+++ b/tests/ui/generics/generic-impl-less-params-with-defaults.stderr
@@ -1,4 +1,4 @@
-error[E0107]: this struct takes at least 2 generic arguments but 1 generic argument was supplied
+error[E0107]: struct takes at least 2 generic arguments but 1 generic argument was supplied
--> $DIR/generic-impl-less-params-with-defaults.rs:11:5
|
LL | Foo::<isize>::new();
diff --git a/tests/ui/generics/generic-impl-more-params-with-defaults.rs b/tests/ui/generics/generic-impl-more-params-with-defaults.rs
index a28332374..be633ec46 100644
--- a/tests/ui/generics/generic-impl-more-params-with-defaults.rs
+++ b/tests/ui/generics/generic-impl-more-params-with-defaults.rs
@@ -11,5 +11,5 @@ impl<T, A> Vec<T, A> {
fn main() {
Vec::<isize, Heap, bool>::new();
- //~^ ERROR this struct takes at most 2 generic arguments but 3 generic arguments were supplied
+ //~^ ERROR struct takes at most 2 generic arguments but 3 generic arguments were supplied
}
diff --git a/tests/ui/generics/generic-impl-more-params-with-defaults.stderr b/tests/ui/generics/generic-impl-more-params-with-defaults.stderr
index fe9b670da..2f4682c4e 100644
--- a/tests/ui/generics/generic-impl-more-params-with-defaults.stderr
+++ b/tests/ui/generics/generic-impl-more-params-with-defaults.stderr
@@ -1,4 +1,4 @@
-error[E0107]: this struct takes at most 2 generic arguments but 3 generic arguments were supplied
+error[E0107]: struct takes at most 2 generic arguments but 3 generic arguments were supplied
--> $DIR/generic-impl-more-params-with-defaults.rs:13:5
|
LL | Vec::<isize, Heap, bool>::new();
diff --git a/tests/ui/generics/generic-type-more-params-with-defaults.rs b/tests/ui/generics/generic-type-more-params-with-defaults.rs
index 3dab03297..b83fdb5c4 100644
--- a/tests/ui/generics/generic-type-more-params-with-defaults.rs
+++ b/tests/ui/generics/generic-type-more-params-with-defaults.rs
@@ -7,5 +7,5 @@ struct Vec<T, A = Heap>(
fn main() {
let _: Vec<isize, Heap, bool>;
- //~^ ERROR this struct takes at most 2 generic arguments but 3 generic arguments
+ //~^ ERROR struct takes at most 2 generic arguments but 3 generic arguments
}
diff --git a/tests/ui/generics/generic-type-more-params-with-defaults.stderr b/tests/ui/generics/generic-type-more-params-with-defaults.stderr
index 7f0198f0e..4d01ba1f4 100644
--- a/tests/ui/generics/generic-type-more-params-with-defaults.stderr
+++ b/tests/ui/generics/generic-type-more-params-with-defaults.stderr
@@ -1,4 +1,4 @@
-error[E0107]: this struct takes at most 2 generic arguments but 3 generic arguments were supplied
+error[E0107]: struct takes at most 2 generic arguments but 3 generic arguments were supplied
--> $DIR/generic-type-more-params-with-defaults.rs:9:12
|
LL | let _: Vec<isize, Heap, bool>;
diff --git a/tests/ui/generics/generic-type-params-name-repr.rs b/tests/ui/generics/generic-type-params-name-repr.rs
index 6e0beec66..d60856b89 100644
--- a/tests/ui/generics/generic-type-params-name-repr.rs
+++ b/tests/ui/generics/generic-type-params-name-repr.rs
@@ -12,40 +12,40 @@ fn main() {
// Ensure that the printed type doesn't include the default type params...
let _: Foo<isize> = ();
//~^ ERROR mismatched types
- //~| expected struct `Foo`, found `()`
+ //~| expected `Foo<isize>`, found `()`
//~| expected struct `Foo<isize>`
//~| found unit type `()`
// ...even when they're present, but the same types as the defaults.
let _: Foo<isize, B, C> = ();
//~^ ERROR mismatched types
- //~| expected struct `Foo`, found `()`
+ //~| expected `Foo<isize>`, found `()`
//~| expected struct `Foo<isize>`
//~| found unit type `()`
// Including cases where the default is using previous type params.
let _: HashMap<String, isize> = ();
//~^ ERROR mismatched types
- //~| expected struct `HashMap`, found `()`
+ //~| expected `HashMap<String, isize>`, found `()`
//~| expected struct `HashMap<String, isize>`
//~| found unit type `()`
let _: HashMap<String, isize, Hash<String>> = ();
//~^ ERROR mismatched types
- //~| expected struct `HashMap`, found `()`
+ //~| expected `HashMap<String, isize>`, found `()`
//~| expected struct `HashMap<String, isize>`
//~| found unit type `()`
// But not when there's a different type in between.
let _: Foo<A, isize, C> = ();
//~^ ERROR mismatched types
- //~| expected struct `Foo`, found `()`
+ //~| expected `Foo<A, isize>`, found `()`
//~| expected struct `Foo<A, isize>`
//~| found unit type `()`
// And don't print <> at all when there's just defaults.
let _: Foo<A, B, C> = ();
//~^ ERROR mismatched types
- //~| expected struct `Foo`, found `()`
+ //~| expected `Foo`, found `()`
//~| expected struct `Foo`
//~| found unit type `()`
}
diff --git a/tests/ui/generics/generic-type-params-name-repr.stderr b/tests/ui/generics/generic-type-params-name-repr.stderr
index 4c3c00396..946f14cc1 100644
--- a/tests/ui/generics/generic-type-params-name-repr.stderr
+++ b/tests/ui/generics/generic-type-params-name-repr.stderr
@@ -2,7 +2,7 @@ error[E0308]: mismatched types
--> $DIR/generic-type-params-name-repr.rs:13:25
|
LL | let _: Foo<isize> = ();
- | ---------- ^^ expected struct `Foo`, found `()`
+ | ---------- ^^ expected `Foo<isize>`, found `()`
| |
| expected due to this
|
@@ -13,7 +13,7 @@ error[E0308]: mismatched types
--> $DIR/generic-type-params-name-repr.rs:20:31
|
LL | let _: Foo<isize, B, C> = ();
- | ---------------- ^^ expected struct `Foo`, found `()`
+ | ---------------- ^^ expected `Foo<isize>`, found `()`
| |
| expected due to this
|
@@ -24,7 +24,7 @@ error[E0308]: mismatched types
--> $DIR/generic-type-params-name-repr.rs:27:37
|
LL | let _: HashMap<String, isize> = ();
- | ---------------------- ^^ expected struct `HashMap`, found `()`
+ | ---------------------- ^^ expected `HashMap<String, isize>`, found `()`
| |
| expected due to this
|
@@ -35,7 +35,7 @@ error[E0308]: mismatched types
--> $DIR/generic-type-params-name-repr.rs:32:51
|
LL | let _: HashMap<String, isize, Hash<String>> = ();
- | ------------------------------------ ^^ expected struct `HashMap`, found `()`
+ | ------------------------------------ ^^ expected `HashMap<String, isize>`, found `()`
| |
| expected due to this
|
@@ -46,7 +46,7 @@ error[E0308]: mismatched types
--> $DIR/generic-type-params-name-repr.rs:39:31
|
LL | let _: Foo<A, isize, C> = ();
- | ---------------- ^^ expected struct `Foo`, found `()`
+ | ---------------- ^^ expected `Foo<A, isize>`, found `()`
| |
| expected due to this
|
@@ -57,7 +57,7 @@ error[E0308]: mismatched types
--> $DIR/generic-type-params-name-repr.rs:46:27
|
LL | let _: Foo<A, B, C> = ();
- | ------------ ^^ expected struct `Foo`, found `()`
+ | ------------ ^^ expected `Foo`, found `()`
| |
| expected due to this
|
diff --git a/tests/ui/generics/issue-65285-incorrect-explicit-lifetime-name-needed.rs b/tests/ui/generics/issue-65285-incorrect-explicit-lifetime-name-needed.rs
index 9ea9fc71b..54b483f53 100644
--- a/tests/ui/generics/issue-65285-incorrect-explicit-lifetime-name-needed.rs
+++ b/tests/ui/generics/issue-65285-incorrect-explicit-lifetime-name-needed.rs
@@ -8,7 +8,6 @@ fn should_error<T>() where T : Into<&u32> {}
trait X<'a, K: 'a> {
fn foo<'b, L: X<&'b Nested<K>>>();
//~^ ERROR missing lifetime specifier [E0106]
- //~| ERROR the type `&'b Nested<K>` does not fulfill the required lifetime
}
fn bar<'b, L: X<&'b Nested<i32>>>(){}
diff --git a/tests/ui/generics/issue-65285-incorrect-explicit-lifetime-name-needed.stderr b/tests/ui/generics/issue-65285-incorrect-explicit-lifetime-name-needed.stderr
index 9d859fddf..faf4c9eb8 100644
--- a/tests/ui/generics/issue-65285-incorrect-explicit-lifetime-name-needed.stderr
+++ b/tests/ui/generics/issue-65285-incorrect-explicit-lifetime-name-needed.stderr
@@ -29,7 +29,7 @@ LL | fn foo<'b, L: X<'lifetime, &'b Nested<K>>>();
| ++++++++++
error[E0106]: missing lifetime specifier
- --> $DIR/issue-65285-incorrect-explicit-lifetime-name-needed.rs:14:16
+ --> $DIR/issue-65285-incorrect-explicit-lifetime-name-needed.rs:13:16
|
LL | fn bar<'b, L: X<&'b Nested<i32>>>(){}
| ^ expected named lifetime parameter
@@ -39,19 +39,7 @@ help: consider using the `'b` lifetime
LL | fn bar<'b, L: X<'b, &'b Nested<i32>>>(){}
| +++
-error[E0477]: the type `&'b Nested<K>` does not fulfill the required lifetime
- --> $DIR/issue-65285-incorrect-explicit-lifetime-name-needed.rs:9:19
- |
-LL | fn foo<'b, L: X<&'b Nested<K>>>();
- | ^^^^^^^^^^^^^^^^
- |
-note: type must satisfy the static lifetime as required by this binding
- --> $DIR/issue-65285-incorrect-explicit-lifetime-name-needed.rs:8:16
- |
-LL | trait X<'a, K: 'a> {
- | ^^
-
-error: aborting due to 4 previous errors
+error: aborting due to 3 previous errors
-Some errors have detailed explanations: E0106, E0477, E0637.
+Some errors have detailed explanations: E0106, E0637.
For more information about an error, try `rustc --explain E0106`.
diff --git a/tests/ui/generics/wrong-number-of-args.rs b/tests/ui/generics/wrong-number-of-args.rs
index cd2f96a18..e4eaff21a 100644
--- a/tests/ui/generics/wrong-number-of-args.rs
+++ b/tests/ui/generics/wrong-number-of-args.rs
@@ -4,18 +4,18 @@ mod no_generics {
type A = Ty;
type B = Ty<'static>;
- //~^ ERROR this struct takes 0 lifetime arguments but 1 lifetime argument
+ //~^ ERROR struct takes 0 lifetime arguments but 1 lifetime argument
//~| HELP remove these generics
type C = Ty<'static, usize>;
- //~^ ERROR this struct takes 0 lifetime arguments but 1 lifetime argument
- //~| ERROR this struct takes 0 generic arguments but 1 generic argument
+ //~^ ERROR struct takes 0 lifetime arguments but 1 lifetime argument
+ //~| ERROR struct takes 0 generic arguments but 1 generic argument
//~| HELP remove this lifetime argument
//~| HELP remove this generic argument
type D = Ty<'static, usize, { 0 }>;
- //~^ ERROR this struct takes 0 lifetime arguments but 1 lifetime argument
- //~| ERROR this struct takes 0 generic arguments but 2 generic arguments
+ //~^ ERROR struct takes 0 lifetime arguments but 1 lifetime argument
+ //~| ERROR struct takes 0 generic arguments but 2 generic arguments
//~| HELP remove this lifetime argument
//~| HELP remove these generic arguments
}
@@ -28,17 +28,17 @@ mod type_and_type {
//~| HELP add missing
type B = Ty<usize>;
- //~^ ERROR this struct takes 2 generic arguments but 1 generic argument
+ //~^ ERROR struct takes 2 generic arguments but 1 generic argument
//~| HELP add missing
type C = Ty<usize, String>;
type D = Ty<usize, String, char>;
- //~^ ERROR this struct takes 2 generic arguments but 3 generic arguments
+ //~^ ERROR struct takes 2 generic arguments but 3 generic arguments
//~| HELP remove this
type E = Ty<>;
- //~^ ERROR this struct takes 2 generic arguments but 0 generic arguments were supplied
+ //~^ ERROR struct takes 2 generic arguments but 0 generic arguments were supplied
//~| HELP add missing
}
@@ -52,7 +52,7 @@ mod lifetime_and_type {
//~| HELP consider introducing
type B = Ty<'static>;
- //~^ ERROR this struct takes 1 generic argument but 0 generic arguments
+ //~^ ERROR struct takes 1 generic argument but 0 generic arguments
//~| HELP add missing
type C = Ty<usize>;
@@ -62,14 +62,14 @@ mod lifetime_and_type {
type D = Ty<'static, usize>;
type E = Ty<>;
- //~^ ERROR this struct takes 1 generic argument but 0 generic arguments
+ //~^ ERROR struct takes 1 generic argument but 0 generic arguments
//~| ERROR missing lifetime specifier
//~| HELP consider introducing
//~| HELP add missing
type F = Ty<'static, usize, 'static, usize>;
- //~^ ERROR this struct takes 1 lifetime argument but 2 lifetime arguments
- //~| ERROR this struct takes 1 generic argument but 2 generic arguments
+ //~^ ERROR struct takes 1 lifetime argument but 2 lifetime arguments
+ //~| ERROR struct takes 1 generic argument but 2 generic arguments
//~| HELP remove this lifetime argument
//~| HELP remove this generic argument
}
@@ -82,7 +82,7 @@ mod type_and_type_and_type {
//~| HELP add missing
type B = Ty<usize>;
- //~^ ERROR this struct takes at least 2
+ //~^ ERROR struct takes at least 2
//~| HELP add missing
type C = Ty<usize, String>;
@@ -90,11 +90,11 @@ mod type_and_type_and_type {
type D = Ty<usize, String, char>;
type E = Ty<usize, String, char, f64>;
- //~^ ERROR this struct takes at most 3
+ //~^ ERROR struct takes at most 3
//~| HELP remove
type F = Ty<>;
- //~^ ERROR this struct takes at least 2 generic arguments but 0 generic arguments
+ //~^ ERROR struct takes at least 2 generic arguments but 0 generic arguments
//~| HELP add missing
}
@@ -114,7 +114,7 @@ mod r#trait {
}
type A = Box<dyn NonGeneric<usize>>;
- //~^ ERROR this trait takes 0 generic arguments but 1 generic argument
+ //~^ ERROR trait takes 0 generic arguments but 1 generic argument
//~| HELP remove
type B = Box<dyn GenericLifetime>;
@@ -123,7 +123,7 @@ mod r#trait {
//~| HELP consider making the bound lifetime-generic
type C = Box<dyn GenericLifetime<'static, 'static>>;
- //~^ ERROR this trait takes 1 lifetime argument but 2 lifetime arguments were supplied
+ //~^ ERROR trait takes 1 lifetime argument but 2 lifetime arguments were supplied
//~| HELP remove
type D = Box<dyn GenericType>;
@@ -131,7 +131,7 @@ mod r#trait {
//~| HELP add missing
type E = Box<dyn GenericType<String, usize>>;
- //~^ ERROR this trait takes 1 generic argument but 2 generic arguments
+ //~^ ERROR trait takes 1 generic argument but 2 generic arguments
//~| HELP remove
type F = Box<dyn GenericLifetime<>>;
@@ -140,7 +140,7 @@ mod r#trait {
//~| HELP consider making the bound lifetime-generic
type G = Box<dyn GenericType<>>;
- //~^ ERROR this trait takes 1 generic argument but 0 generic arguments
+ //~^ ERROR trait takes 1 generic argument but 0 generic arguments
//~| HELP add missing
}
@@ -151,7 +151,7 @@ mod associated_item {
}
type A = Box<dyn NonGenericAT<usize, AssocTy=()>>;
- //~^ ERROR this trait takes 0 generic arguments but 1 generic argument
+ //~^ ERROR trait takes 0 generic arguments but 1 generic argument
//~| HELP remove
}
@@ -166,14 +166,14 @@ mod associated_item {
//~| HELP consider making the bound lifetime-generic
type B = Box<dyn GenericLifetimeAT<'static, 'static, AssocTy=()>>;
- //~^ ERROR this trait takes 1 lifetime argument but 2 lifetime arguments were supplied
+ //~^ ERROR trait takes 1 lifetime argument but 2 lifetime arguments were supplied
//~| HELP remove
type C = Box<dyn GenericLifetimeAT<(), AssocTy=()>>;
//~^ ERROR missing lifetime specifier
//~| HELP consider introducing
//~| HELP consider making the bound lifetime-generic
- //~| ERROR this trait takes 0 generic arguments but 1 generic argument
+ //~| ERROR trait takes 0 generic arguments but 1 generic argument
//~| HELP remove
}
@@ -183,17 +183,17 @@ mod associated_item {
}
type A = Box<dyn GenericTypeAT<AssocTy=()>>;
- //~^ ERROR this trait takes 1 generic argument but 0 generic arguments
+ //~^ ERROR trait takes 1 generic argument but 0 generic arguments
//~| HELP add missing
type B = Box<dyn GenericTypeAT<(), (), AssocTy=()>>;
- //~^ ERROR this trait takes 1 generic argument but 2 generic arguments
+ //~^ ERROR trait takes 1 generic argument but 2 generic arguments
//~| HELP remove
type C = Box<dyn GenericTypeAT<'static, AssocTy=()>>;
- //~^ ERROR this trait takes 1 generic argument but 0 generic arguments
+ //~^ ERROR trait takes 1 generic argument but 0 generic arguments
//~| HELP add missing
- //~| ERROR this trait takes 0 lifetime arguments but 1 lifetime argument was supplied
+ //~| ERROR trait takes 0 lifetime arguments but 1 lifetime argument was supplied
//~| HELP remove
}
@@ -203,20 +203,20 @@ mod associated_item {
}
type A = Box<dyn GenericLifetimeTypeAT<AssocTy=()>>;
- //~^ ERROR this trait takes 1 generic argument but 0 generic arguments
+ //~^ ERROR trait takes 1 generic argument but 0 generic arguments
//~| HELP add missing
//~| ERROR missing lifetime specifier
//~| HELP consider introducing
//~| HELP consider making the bound lifetime-generic
type B = Box<dyn GenericLifetimeTypeAT<'static, AssocTy=()>>;
- //~^ ERROR this trait takes 1 generic argument but 0 generic arguments were supplied
+ //~^ ERROR trait takes 1 generic argument but 0 generic arguments were supplied
//~| HELP add missing
type C = Box<dyn GenericLifetimeTypeAT<'static, 'static, AssocTy=()>>;
- //~^ ERROR this trait takes 1 lifetime argument but 2 lifetime arguments were supplied
+ //~^ ERROR trait takes 1 lifetime argument but 2 lifetime arguments were supplied
//~| HELP remove
- //~| ERROR this trait takes 1 generic argument but 0 generic arguments
+ //~| ERROR trait takes 1 generic argument but 0 generic arguments
//~| HELP add missing
type D = Box<dyn GenericLifetimeTypeAT<(), AssocTy=()>>;
@@ -228,21 +228,21 @@ mod associated_item {
//~^ ERROR missing lifetime specifier
//~| HELP consider introducing
//~| HELP consider making the bound lifetime-generic
- //~| ERROR this trait takes 1 generic argument but 2 generic arguments
+ //~| ERROR trait takes 1 generic argument but 2 generic arguments
//~| HELP remove
type F = Box<dyn GenericLifetimeTypeAT<'static, 'static, (), AssocTy=()>>;
- //~^ ERROR this trait takes 1 lifetime argument but 2 lifetime arguments were supplied
+ //~^ ERROR trait takes 1 lifetime argument but 2 lifetime arguments were supplied
//~| HELP remove
type G = Box<dyn GenericLifetimeTypeAT<'static, (), (), AssocTy=()>>;
- //~^ ERROR this trait takes 1 generic argument but 2 generic arguments
+ //~^ ERROR trait takes 1 generic argument but 2 generic arguments
//~| HELP remove
type H = Box<dyn GenericLifetimeTypeAT<'static, 'static, (), (), AssocTy=()>>;
- //~^ ERROR this trait takes 1 lifetime argument but 2 lifetime arguments were supplied
+ //~^ ERROR trait takes 1 lifetime argument but 2 lifetime arguments were supplied
//~| HELP remove
- //~| ERROR this trait takes 1 generic argument but 2 generic arguments
+ //~| ERROR trait takes 1 generic argument but 2 generic arguments
//~| HELP remove
}
@@ -252,15 +252,15 @@ mod associated_item {
}
type A = Box<dyn GenericTypeTypeAT<AssocTy=()>>;
- //~^ ERROR this trait takes 2 generic arguments but 0 generic arguments
+ //~^ ERROR trait takes 2 generic arguments but 0 generic arguments
//~| HELP add missing
type B = Box<dyn GenericTypeTypeAT<(), AssocTy=()>>;
- //~^ ERROR this trait takes 2 generic arguments but 1 generic argument
+ //~^ ERROR trait takes 2 generic arguments but 1 generic argument
//~| HELP add missing
type C = Box<dyn GenericTypeTypeAT<(), (), (), AssocTy=()>>;
- //~^ ERROR this trait takes 2 generic arguments but 3 generic arguments
+ //~^ ERROR trait takes 2 generic arguments but 3 generic arguments
//~| HELP remove
}
@@ -275,7 +275,7 @@ mod associated_item {
//~| HELP consider making the bound lifetime-generic
type B = Box<dyn GenericLifetimeLifetimeAT<'static, AssocTy=()>>;
- //~^ ERROR this trait takes 2 lifetime arguments but 1 lifetime argument was supplied
+ //~^ ERROR trait takes 2 lifetime arguments but 1 lifetime argument was supplied
//~| HELP add missing lifetime argument
}
@@ -288,17 +288,17 @@ mod associated_item {
//~^ ERROR missing lifetime specifier
//~| HELP consider introducing
//~| HELP consider making the bound lifetime-generic
- //~| ERROR this trait takes 1 generic argument but 0 generic arguments
+ //~| ERROR trait takes 1 generic argument but 0 generic arguments
//~| HELP add missing
type B = Box<dyn GenericLifetimeLifetimeTypeAT<'static, AssocTy=()>>;
- //~^ ERROR this trait takes 2 lifetime arguments but 1 lifetime argument was supplied
+ //~^ ERROR trait takes 2 lifetime arguments but 1 lifetime argument was supplied
//~| HELP add missing lifetime argument
- //~| ERROR this trait takes 1 generic argument but 0 generic arguments
+ //~| ERROR trait takes 1 generic argument but 0 generic arguments
//~| HELP add missing
type C = Box<dyn GenericLifetimeLifetimeTypeAT<'static, (), AssocTy=()>>;
- //~^ ERROR this trait takes 2 lifetime arguments but 1 lifetime argument was supplied
+ //~^ ERROR trait takes 2 lifetime arguments but 1 lifetime argument was supplied
//~| HELP add missing lifetime argument
}
}
@@ -312,21 +312,21 @@ mod stdlib {
//~| HELP add missing
type B = HashMap<String>;
- //~^ ERROR this struct takes at least
+ //~^ ERROR struct takes at least
//~| HELP add missing
type C = HashMap<'static>;
- //~^ ERROR this struct takes 0 lifetime arguments but 1 lifetime argument
+ //~^ ERROR struct takes 0 lifetime arguments but 1 lifetime argument
//~| HELP remove these generics
- //~| ERROR this struct takes at least 2
+ //~| ERROR struct takes at least 2
//~| HELP add missing
type D = HashMap<usize, String, char, f64>;
- //~^ ERROR this struct takes at most 3
+ //~^ ERROR struct takes at most 3
//~| HELP remove this
type E = HashMap<>;
- //~^ ERROR this struct takes at least 2 generic arguments but 0 generic arguments
+ //~^ ERROR struct takes at least 2 generic arguments but 0 generic arguments
//~| HELP add missing
}
@@ -336,21 +336,21 @@ mod stdlib {
//~| HELP add missing
type B = Result<String>;
- //~^ ERROR this enum takes 2 generic arguments but 1 generic argument
+ //~^ ERROR enum takes 2 generic arguments but 1 generic argument
//~| HELP add missing
type C = Result<'static>;
- //~^ ERROR this enum takes 0 lifetime arguments but 1 lifetime argument
+ //~^ ERROR enum takes 0 lifetime arguments but 1 lifetime argument
//~| HELP remove these generics
- //~| ERROR this enum takes 2 generic arguments but 0 generic arguments
+ //~| ERROR enum takes 2 generic arguments but 0 generic arguments
//~| HELP add missing
type D = Result<usize, String, char>;
- //~^ ERROR this enum takes 2 generic arguments but 3 generic arguments
+ //~^ ERROR enum takes 2 generic arguments but 3 generic arguments
//~| HELP remove
type E = Result<>;
- //~^ ERROR this enum takes 2 generic arguments but 0 generic arguments
+ //~^ ERROR enum takes 2 generic arguments but 0 generic arguments
//~| HELP add missing
}
}
diff --git a/tests/ui/generics/wrong-number-of-args.stderr b/tests/ui/generics/wrong-number-of-args.stderr
index 75e33f680..9006fb10b 100644
--- a/tests/ui/generics/wrong-number-of-args.stderr
+++ b/tests/ui/generics/wrong-number-of-args.stderr
@@ -167,7 +167,7 @@ help: consider introducing a named lifetime parameter
LL | type A<'a> = Box<dyn GenericLifetimeLifetimeTypeAT<'a, 'a, AssocTy=()>>;
| ++++ +++++++
-error[E0107]: this struct takes 0 lifetime arguments but 1 lifetime argument was supplied
+error[E0107]: struct takes 0 lifetime arguments but 1 lifetime argument was supplied
--> $DIR/wrong-number-of-args.rs:6:14
|
LL | type B = Ty<'static>;
@@ -181,7 +181,7 @@ note: struct defined here, with 0 lifetime parameters
LL | struct Ty;
| ^^
-error[E0107]: this struct takes 0 lifetime arguments but 1 lifetime argument was supplied
+error[E0107]: struct takes 0 lifetime arguments but 1 lifetime argument was supplied
--> $DIR/wrong-number-of-args.rs:10:14
|
LL | type C = Ty<'static, usize>;
@@ -195,7 +195,7 @@ note: struct defined here, with 0 lifetime parameters
LL | struct Ty;
| ^^
-error[E0107]: this struct takes 0 generic arguments but 1 generic argument was supplied
+error[E0107]: struct takes 0 generic arguments but 1 generic argument was supplied
--> $DIR/wrong-number-of-args.rs:10:14
|
LL | type C = Ty<'static, usize>;
@@ -209,7 +209,7 @@ note: struct defined here, with 0 generic parameters
LL | struct Ty;
| ^^
-error[E0107]: this struct takes 0 lifetime arguments but 1 lifetime argument was supplied
+error[E0107]: struct takes 0 lifetime arguments but 1 lifetime argument was supplied
--> $DIR/wrong-number-of-args.rs:16:14
|
LL | type D = Ty<'static, usize, { 0 }>;
@@ -223,7 +223,7 @@ note: struct defined here, with 0 lifetime parameters
LL | struct Ty;
| ^^
-error[E0107]: this struct takes 0 generic arguments but 2 generic arguments were supplied
+error[E0107]: struct takes 0 generic arguments but 2 generic arguments were supplied
--> $DIR/wrong-number-of-args.rs:16:14
|
LL | type D = Ty<'static, usize, { 0 }>;
@@ -253,7 +253,7 @@ help: add missing generic arguments
LL | type A = Ty<A, B>;
| ++++++
-error[E0107]: this struct takes 2 generic arguments but 1 generic argument was supplied
+error[E0107]: struct takes 2 generic arguments but 1 generic argument was supplied
--> $DIR/wrong-number-of-args.rs:30:14
|
LL | type B = Ty<usize>;
@@ -271,7 +271,7 @@ help: add missing generic argument
LL | type B = Ty<usize, B>;
| +++
-error[E0107]: this struct takes 2 generic arguments but 3 generic arguments were supplied
+error[E0107]: struct takes 2 generic arguments but 3 generic arguments were supplied
--> $DIR/wrong-number-of-args.rs:36:14
|
LL | type D = Ty<usize, String, char>;
@@ -285,7 +285,7 @@ note: struct defined here, with 2 generic parameters: `A`, `B`
LL | struct Ty<A, B>;
| ^^ - -
-error[E0107]: this struct takes 2 generic arguments but 0 generic arguments were supplied
+error[E0107]: struct takes 2 generic arguments but 0 generic arguments were supplied
--> $DIR/wrong-number-of-args.rs:40:14
|
LL | type E = Ty<>;
@@ -317,7 +317,7 @@ help: add missing generic argument
LL | type A = Ty<T>;
| +++
-error[E0107]: this struct takes 1 generic argument but 0 generic arguments were supplied
+error[E0107]: struct takes 1 generic argument but 0 generic arguments were supplied
--> $DIR/wrong-number-of-args.rs:54:14
|
LL | type B = Ty<'static>;
@@ -333,7 +333,7 @@ help: add missing generic argument
LL | type B = Ty<'static, T>;
| +++
-error[E0107]: this struct takes 1 generic argument but 0 generic arguments were supplied
+error[E0107]: struct takes 1 generic argument but 0 generic arguments were supplied
--> $DIR/wrong-number-of-args.rs:64:14
|
LL | type E = Ty<>;
@@ -349,7 +349,7 @@ help: add missing generic argument
LL | type E = Ty<T>;
| +
-error[E0107]: this struct takes 1 lifetime argument but 2 lifetime arguments were supplied
+error[E0107]: struct takes 1 lifetime argument but 2 lifetime arguments were supplied
--> $DIR/wrong-number-of-args.rs:70:14
|
LL | type F = Ty<'static, usize, 'static, usize>;
@@ -363,7 +363,7 @@ note: struct defined here, with 1 lifetime parameter: `'a`
LL | struct Ty<'a, T>;
| ^^ --
-error[E0107]: this struct takes 1 generic argument but 2 generic arguments were supplied
+error[E0107]: struct takes 1 generic argument but 2 generic arguments were supplied
--> $DIR/wrong-number-of-args.rs:70:14
|
LL | type F = Ty<'static, usize, 'static, usize>;
@@ -393,7 +393,7 @@ help: add missing generic arguments
LL | type A = Ty<A, B>;
| ++++++
-error[E0107]: this struct takes at least 2 generic arguments but 1 generic argument was supplied
+error[E0107]: struct takes at least 2 generic arguments but 1 generic argument was supplied
--> $DIR/wrong-number-of-args.rs:84:14
|
LL | type B = Ty<usize>;
@@ -411,7 +411,7 @@ help: add missing generic argument
LL | type B = Ty<usize, B>;
| +++
-error[E0107]: this struct takes at most 3 generic arguments but 4 generic arguments were supplied
+error[E0107]: struct takes at most 3 generic arguments but 4 generic arguments were supplied
--> $DIR/wrong-number-of-args.rs:92:14
|
LL | type E = Ty<usize, String, char, f64>;
@@ -425,7 +425,7 @@ note: struct defined here, with at most 3 generic parameters: `A`, `B`, `C`
LL | struct Ty<A, B, C = &'static str>;
| ^^ - - ----------------
-error[E0107]: this struct takes at least 2 generic arguments but 0 generic arguments were supplied
+error[E0107]: struct takes at least 2 generic arguments but 0 generic arguments were supplied
--> $DIR/wrong-number-of-args.rs:96:14
|
LL | type F = Ty<>;
@@ -441,7 +441,7 @@ help: add missing generic arguments
LL | type F = Ty<A, B>;
| ++++
-error[E0107]: this trait takes 0 generic arguments but 1 generic argument was supplied
+error[E0107]: trait takes 0 generic arguments but 1 generic argument was supplied
--> $DIR/wrong-number-of-args.rs:116:22
|
LL | type A = Box<dyn NonGeneric<usize>>;
@@ -455,7 +455,7 @@ note: trait defined here, with 0 generic parameters
LL | trait NonGeneric {
| ^^^^^^^^^^
-error[E0107]: this trait takes 1 lifetime argument but 2 lifetime arguments were supplied
+error[E0107]: trait takes 1 lifetime argument but 2 lifetime arguments were supplied
--> $DIR/wrong-number-of-args.rs:125:22
|
LL | type C = Box<dyn GenericLifetime<'static, 'static>>;
@@ -485,7 +485,7 @@ help: add missing generic argument
LL | type D = Box<dyn GenericType<A>>;
| +++
-error[E0107]: this trait takes 1 generic argument but 2 generic arguments were supplied
+error[E0107]: trait takes 1 generic argument but 2 generic arguments were supplied
--> $DIR/wrong-number-of-args.rs:133:22
|
LL | type E = Box<dyn GenericType<String, usize>>;
@@ -499,7 +499,7 @@ note: trait defined here, with 1 generic parameter: `A`
LL | trait GenericType<A> {
| ^^^^^^^^^^^ -
-error[E0107]: this trait takes 1 generic argument but 0 generic arguments were supplied
+error[E0107]: trait takes 1 generic argument but 0 generic arguments were supplied
--> $DIR/wrong-number-of-args.rs:142:22
|
LL | type G = Box<dyn GenericType<>>;
@@ -515,7 +515,7 @@ help: add missing generic argument
LL | type G = Box<dyn GenericType<A>>;
| +
-error[E0107]: this trait takes 0 generic arguments but 1 generic argument was supplied
+error[E0107]: trait takes 0 generic arguments but 1 generic argument was supplied
--> $DIR/wrong-number-of-args.rs:153:26
|
LL | type A = Box<dyn NonGenericAT<usize, AssocTy=()>>;
@@ -529,7 +529,7 @@ note: trait defined here, with 0 generic parameters
LL | trait NonGenericAT {
| ^^^^^^^^^^^^
-error[E0107]: this trait takes 1 lifetime argument but 2 lifetime arguments were supplied
+error[E0107]: trait takes 1 lifetime argument but 2 lifetime arguments were supplied
--> $DIR/wrong-number-of-args.rs:168:26
|
LL | type B = Box<dyn GenericLifetimeAT<'static, 'static, AssocTy=()>>;
@@ -543,7 +543,7 @@ note: trait defined here, with 1 lifetime parameter: `'a`
LL | trait GenericLifetimeAT<'a> {
| ^^^^^^^^^^^^^^^^^ --
-error[E0107]: this trait takes 0 generic arguments but 1 generic argument was supplied
+error[E0107]: trait takes 0 generic arguments but 1 generic argument was supplied
--> $DIR/wrong-number-of-args.rs:172:26
|
LL | type C = Box<dyn GenericLifetimeAT<(), AssocTy=()>>;
@@ -557,7 +557,7 @@ note: trait defined here, with 0 generic parameters
LL | trait GenericLifetimeAT<'a> {
| ^^^^^^^^^^^^^^^^^
-error[E0107]: this trait takes 1 generic argument but 0 generic arguments were supplied
+error[E0107]: trait takes 1 generic argument but 0 generic arguments were supplied
--> $DIR/wrong-number-of-args.rs:185:26
|
LL | type A = Box<dyn GenericTypeAT<AssocTy=()>>;
@@ -573,7 +573,7 @@ help: add missing generic argument
LL | type A = Box<dyn GenericTypeAT<A, AssocTy=()>>;
| ++
-error[E0107]: this trait takes 1 generic argument but 2 generic arguments were supplied
+error[E0107]: trait takes 1 generic argument but 2 generic arguments were supplied
--> $DIR/wrong-number-of-args.rs:189:26
|
LL | type B = Box<dyn GenericTypeAT<(), (), AssocTy=()>>;
@@ -587,7 +587,7 @@ note: trait defined here, with 1 generic parameter: `A`
LL | trait GenericTypeAT<A> {
| ^^^^^^^^^^^^^ -
-error[E0107]: this trait takes 0 lifetime arguments but 1 lifetime argument was supplied
+error[E0107]: trait takes 0 lifetime arguments but 1 lifetime argument was supplied
--> $DIR/wrong-number-of-args.rs:193:26
|
LL | type C = Box<dyn GenericTypeAT<'static, AssocTy=()>>;
@@ -601,7 +601,7 @@ note: trait defined here, with 0 lifetime parameters
LL | trait GenericTypeAT<A> {
| ^^^^^^^^^^^^^
-error[E0107]: this trait takes 1 generic argument but 0 generic arguments were supplied
+error[E0107]: trait takes 1 generic argument but 0 generic arguments were supplied
--> $DIR/wrong-number-of-args.rs:193:26
|
LL | type C = Box<dyn GenericTypeAT<'static, AssocTy=()>>;
@@ -617,7 +617,7 @@ help: add missing generic argument
LL | type C = Box<dyn GenericTypeAT<'static, A, AssocTy=()>>;
| +++
-error[E0107]: this trait takes 1 generic argument but 0 generic arguments were supplied
+error[E0107]: trait takes 1 generic argument but 0 generic arguments were supplied
--> $DIR/wrong-number-of-args.rs:205:26
|
LL | type A = Box<dyn GenericLifetimeTypeAT<AssocTy=()>>;
@@ -633,7 +633,7 @@ help: add missing generic argument
LL | type A = Box<dyn GenericLifetimeTypeAT<A, AssocTy=()>>;
| ++
-error[E0107]: this trait takes 1 generic argument but 0 generic arguments were supplied
+error[E0107]: trait takes 1 generic argument but 0 generic arguments were supplied
--> $DIR/wrong-number-of-args.rs:212:26
|
LL | type B = Box<dyn GenericLifetimeTypeAT<'static, AssocTy=()>>;
@@ -649,7 +649,7 @@ help: add missing generic argument
LL | type B = Box<dyn GenericLifetimeTypeAT<'static, A, AssocTy=()>>;
| +++
-error[E0107]: this trait takes 1 lifetime argument but 2 lifetime arguments were supplied
+error[E0107]: trait takes 1 lifetime argument but 2 lifetime arguments were supplied
--> $DIR/wrong-number-of-args.rs:216:26
|
LL | type C = Box<dyn GenericLifetimeTypeAT<'static, 'static, AssocTy=()>>;
@@ -663,7 +663,7 @@ note: trait defined here, with 1 lifetime parameter: `'a`
LL | trait GenericLifetimeTypeAT<'a, A> {
| ^^^^^^^^^^^^^^^^^^^^^ --
-error[E0107]: this trait takes 1 generic argument but 0 generic arguments were supplied
+error[E0107]: trait takes 1 generic argument but 0 generic arguments were supplied
--> $DIR/wrong-number-of-args.rs:216:26
|
LL | type C = Box<dyn GenericLifetimeTypeAT<'static, 'static, AssocTy=()>>;
@@ -679,7 +679,7 @@ help: add missing generic argument
LL | type C = Box<dyn GenericLifetimeTypeAT<'static, 'static, A, AssocTy=()>>;
| +++
-error[E0107]: this trait takes 1 generic argument but 2 generic arguments were supplied
+error[E0107]: trait takes 1 generic argument but 2 generic arguments were supplied
--> $DIR/wrong-number-of-args.rs:227:26
|
LL | type E = Box<dyn GenericLifetimeTypeAT<(), (), AssocTy=()>>;
@@ -693,7 +693,7 @@ note: trait defined here, with 1 generic parameter: `A`
LL | trait GenericLifetimeTypeAT<'a, A> {
| ^^^^^^^^^^^^^^^^^^^^^ -
-error[E0107]: this trait takes 1 lifetime argument but 2 lifetime arguments were supplied
+error[E0107]: trait takes 1 lifetime argument but 2 lifetime arguments were supplied
--> $DIR/wrong-number-of-args.rs:234:26
|
LL | type F = Box<dyn GenericLifetimeTypeAT<'static, 'static, (), AssocTy=()>>;
@@ -707,7 +707,7 @@ note: trait defined here, with 1 lifetime parameter: `'a`
LL | trait GenericLifetimeTypeAT<'a, A> {
| ^^^^^^^^^^^^^^^^^^^^^ --
-error[E0107]: this trait takes 1 generic argument but 2 generic arguments were supplied
+error[E0107]: trait takes 1 generic argument but 2 generic arguments were supplied
--> $DIR/wrong-number-of-args.rs:238:26
|
LL | type G = Box<dyn GenericLifetimeTypeAT<'static, (), (), AssocTy=()>>;
@@ -721,7 +721,7 @@ note: trait defined here, with 1 generic parameter: `A`
LL | trait GenericLifetimeTypeAT<'a, A> {
| ^^^^^^^^^^^^^^^^^^^^^ -
-error[E0107]: this trait takes 1 lifetime argument but 2 lifetime arguments were supplied
+error[E0107]: trait takes 1 lifetime argument but 2 lifetime arguments were supplied
--> $DIR/wrong-number-of-args.rs:242:26
|
LL | type H = Box<dyn GenericLifetimeTypeAT<'static, 'static, (), (), AssocTy=()>>;
@@ -735,7 +735,7 @@ note: trait defined here, with 1 lifetime parameter: `'a`
LL | trait GenericLifetimeTypeAT<'a, A> {
| ^^^^^^^^^^^^^^^^^^^^^ --
-error[E0107]: this trait takes 1 generic argument but 2 generic arguments were supplied
+error[E0107]: trait takes 1 generic argument but 2 generic arguments were supplied
--> $DIR/wrong-number-of-args.rs:242:26
|
LL | type H = Box<dyn GenericLifetimeTypeAT<'static, 'static, (), (), AssocTy=()>>;
@@ -749,7 +749,7 @@ note: trait defined here, with 1 generic parameter: `A`
LL | trait GenericLifetimeTypeAT<'a, A> {
| ^^^^^^^^^^^^^^^^^^^^^ -
-error[E0107]: this trait takes 2 generic arguments but 0 generic arguments were supplied
+error[E0107]: trait takes 2 generic arguments but 0 generic arguments were supplied
--> $DIR/wrong-number-of-args.rs:254:26
|
LL | type A = Box<dyn GenericTypeTypeAT<AssocTy=()>>;
@@ -765,7 +765,7 @@ help: add missing generic arguments
LL | type A = Box<dyn GenericTypeTypeAT<A, B, AssocTy=()>>;
| +++++
-error[E0107]: this trait takes 2 generic arguments but 1 generic argument was supplied
+error[E0107]: trait takes 2 generic arguments but 1 generic argument was supplied
--> $DIR/wrong-number-of-args.rs:258:26
|
LL | type B = Box<dyn GenericTypeTypeAT<(), AssocTy=()>>;
@@ -783,7 +783,7 @@ help: add missing generic argument
LL | type B = Box<dyn GenericTypeTypeAT<(), B, AssocTy=()>>;
| +++
-error[E0107]: this trait takes 2 generic arguments but 3 generic arguments were supplied
+error[E0107]: trait takes 2 generic arguments but 3 generic arguments were supplied
--> $DIR/wrong-number-of-args.rs:262:26
|
LL | type C = Box<dyn GenericTypeTypeAT<(), (), (), AssocTy=()>>;
@@ -797,7 +797,7 @@ note: trait defined here, with 2 generic parameters: `A`, `B`
LL | trait GenericTypeTypeAT<A, B> {
| ^^^^^^^^^^^^^^^^^ - -
-error[E0107]: this trait takes 2 lifetime arguments but 1 lifetime argument was supplied
+error[E0107]: trait takes 2 lifetime arguments but 1 lifetime argument was supplied
--> $DIR/wrong-number-of-args.rs:277:26
|
LL | type B = Box<dyn GenericLifetimeLifetimeAT<'static, AssocTy=()>>;
@@ -815,7 +815,7 @@ help: add missing lifetime argument
LL | type B = Box<dyn GenericLifetimeLifetimeAT<'static, 'static, AssocTy=()>>;
| +++++++++
-error[E0107]: this trait takes 1 generic argument but 0 generic arguments were supplied
+error[E0107]: trait takes 1 generic argument but 0 generic arguments were supplied
--> $DIR/wrong-number-of-args.rs:287:26
|
LL | type A = Box<dyn GenericLifetimeLifetimeTypeAT<AssocTy=()>>;
@@ -831,7 +831,7 @@ help: add missing generic argument
LL | type A = Box<dyn GenericLifetimeLifetimeTypeAT<A, AssocTy=()>>;
| ++
-error[E0107]: this trait takes 2 lifetime arguments but 1 lifetime argument was supplied
+error[E0107]: trait takes 2 lifetime arguments but 1 lifetime argument was supplied
--> $DIR/wrong-number-of-args.rs:294:26
|
LL | type B = Box<dyn GenericLifetimeLifetimeTypeAT<'static, AssocTy=()>>;
@@ -849,7 +849,7 @@ help: add missing lifetime argument
LL | type B = Box<dyn GenericLifetimeLifetimeTypeAT<'static, 'static, AssocTy=()>>;
| +++++++++
-error[E0107]: this trait takes 1 generic argument but 0 generic arguments were supplied
+error[E0107]: trait takes 1 generic argument but 0 generic arguments were supplied
--> $DIR/wrong-number-of-args.rs:294:26
|
LL | type B = Box<dyn GenericLifetimeLifetimeTypeAT<'static, AssocTy=()>>;
@@ -865,7 +865,7 @@ help: add missing generic argument
LL | type B = Box<dyn GenericLifetimeLifetimeTypeAT<'static, A, AssocTy=()>>;
| +++
-error[E0107]: this trait takes 2 lifetime arguments but 1 lifetime argument was supplied
+error[E0107]: trait takes 2 lifetime arguments but 1 lifetime argument was supplied
--> $DIR/wrong-number-of-args.rs:300:26
|
LL | type C = Box<dyn GenericLifetimeLifetimeTypeAT<'static, (), AssocTy=()>>;
@@ -894,7 +894,7 @@ help: add missing generic arguments
LL | type A = HashMap<K, V>;
| ++++++
-error[E0107]: this struct takes at least 2 generic arguments but 1 generic argument was supplied
+error[E0107]: struct takes at least 2 generic arguments but 1 generic argument was supplied
--> $DIR/wrong-number-of-args.rs:314:18
|
LL | type B = HashMap<String>;
@@ -907,7 +907,7 @@ help: add missing generic argument
LL | type B = HashMap<String, V>;
| +++
-error[E0107]: this struct takes 0 lifetime arguments but 1 lifetime argument was supplied
+error[E0107]: struct takes 0 lifetime arguments but 1 lifetime argument was supplied
--> $DIR/wrong-number-of-args.rs:318:18
|
LL | type C = HashMap<'static>;
@@ -915,7 +915,7 @@ LL | type C = HashMap<'static>;
| |
| expected 0 lifetime arguments
-error[E0107]: this struct takes at least 2 generic arguments but 0 generic arguments were supplied
+error[E0107]: struct takes at least 2 generic arguments but 0 generic arguments were supplied
--> $DIR/wrong-number-of-args.rs:318:18
|
LL | type C = HashMap<'static>;
@@ -926,7 +926,7 @@ help: add missing generic arguments
LL | type C = HashMap<'static, K, V>;
| ++++++
-error[E0107]: this struct takes at most 3 generic arguments but 4 generic arguments were supplied
+error[E0107]: struct takes at most 3 generic arguments but 4 generic arguments were supplied
--> $DIR/wrong-number-of-args.rs:324:18
|
LL | type D = HashMap<usize, String, char, f64>;
@@ -934,7 +934,7 @@ LL | type D = HashMap<usize, String, char, f64>;
| |
| expected at most 3 generic arguments
-error[E0107]: this struct takes at least 2 generic arguments but 0 generic arguments were supplied
+error[E0107]: struct takes at least 2 generic arguments but 0 generic arguments were supplied
--> $DIR/wrong-number-of-args.rs:328:18
|
LL | type E = HashMap<>;
@@ -956,7 +956,7 @@ help: add missing generic arguments
LL | type A = Result<T, E>;
| ++++++
-error[E0107]: this enum takes 2 generic arguments but 1 generic argument was supplied
+error[E0107]: enum takes 2 generic arguments but 1 generic argument was supplied
--> $DIR/wrong-number-of-args.rs:338:18
|
LL | type B = Result<String>;
@@ -969,7 +969,7 @@ help: add missing generic argument
LL | type B = Result<String, E>;
| +++
-error[E0107]: this enum takes 0 lifetime arguments but 1 lifetime argument was supplied
+error[E0107]: enum takes 0 lifetime arguments but 1 lifetime argument was supplied
--> $DIR/wrong-number-of-args.rs:342:18
|
LL | type C = Result<'static>;
@@ -977,7 +977,7 @@ LL | type C = Result<'static>;
| |
| expected 0 lifetime arguments
-error[E0107]: this enum takes 2 generic arguments but 0 generic arguments were supplied
+error[E0107]: enum takes 2 generic arguments but 0 generic arguments were supplied
--> $DIR/wrong-number-of-args.rs:342:18
|
LL | type C = Result<'static>;
@@ -988,7 +988,7 @@ help: add missing generic arguments
LL | type C = Result<'static, T, E>;
| ++++++
-error[E0107]: this enum takes 2 generic arguments but 3 generic arguments were supplied
+error[E0107]: enum takes 2 generic arguments but 3 generic arguments were supplied
--> $DIR/wrong-number-of-args.rs:348:18
|
LL | type D = Result<usize, String, char>;
@@ -996,7 +996,7 @@ LL | type D = Result<usize, String, char>;
| |
| expected 2 generic arguments
-error[E0107]: this enum takes 2 generic arguments but 0 generic arguments were supplied
+error[E0107]: enum takes 2 generic arguments but 0 generic arguments were supplied
--> $DIR/wrong-number-of-args.rs:352:18
|
LL | type E = Result<>;
diff --git a/tests/ui/half-open-range-patterns/exclusive_range_pattern_syntax_collision.stderr b/tests/ui/half-open-range-patterns/exclusive_range_pattern_syntax_collision.stderr
index 095a1c6af..6ce56ba4b 100644
--- a/tests/ui/half-open-range-patterns/exclusive_range_pattern_syntax_collision.stderr
+++ b/tests/ui/half-open-range-patterns/exclusive_range_pattern_syntax_collision.stderr
@@ -4,7 +4,7 @@ error[E0308]: mismatched types
LL | match [5..4, 99..105, 43..44] {
| ----------------------- this expression has type `[std::ops::Range<{integer}>; 3]`
LL | [_, 99.., _] => {},
- | ^^ expected struct `Range`, found integer
+ | ^^ expected `Range<{integer}>`, found integer
|
= note: expected struct `std::ops::Range<{integer}>`
found type `{integer}`
diff --git a/tests/ui/half-open-range-patterns/exclusive_range_pattern_syntax_collision2.stderr b/tests/ui/half-open-range-patterns/exclusive_range_pattern_syntax_collision2.stderr
index 2ea3205dc..6f56ecd4c 100644
--- a/tests/ui/half-open-range-patterns/exclusive_range_pattern_syntax_collision2.stderr
+++ b/tests/ui/half-open-range-patterns/exclusive_range_pattern_syntax_collision2.stderr
@@ -10,7 +10,7 @@ error[E0308]: mismatched types
LL | match [5..4, 99..105, 43..44] {
| ----------------------- this expression has type `[std::ops::Range<{integer}>; 3]`
LL | [_, 99..] => {},
- | ^^ expected struct `Range`, found integer
+ | ^^ expected `Range<{integer}>`, found integer
|
= note: expected struct `std::ops::Range<{integer}>`
found type `{integer}`
diff --git a/tests/ui/half-open-range-patterns/exclusive_range_pattern_syntax_collision3.stderr b/tests/ui/half-open-range-patterns/exclusive_range_pattern_syntax_collision3.stderr
index bbdf0c83f..b9b272c4c 100644
--- a/tests/ui/half-open-range-patterns/exclusive_range_pattern_syntax_collision3.stderr
+++ b/tests/ui/half-open-range-patterns/exclusive_range_pattern_syntax_collision3.stderr
@@ -4,7 +4,7 @@ error[E0308]: mismatched types
LL | match [5..4, 99..105, 43..44] {
| ----------------------- this expression has type `[std::ops::Range<{integer}>; 3]`
LL | [..9, 99..100, _] => {},
- | ^ expected struct `Range`, found integer
+ | ^ expected `Range<{integer}>`, found integer
|
= note: expected struct `std::ops::Range<{integer}>`
found type `{integer}`
@@ -17,7 +17,7 @@ LL | match [5..4, 99..105, 43..44] {
LL | [..9, 99..100, _] => {},
| ^^ --- this is of type `{integer}`
| |
- | expected struct `Range`, found integer
+ | expected `Range<{integer}>`, found integer
|
= note: expected struct `std::ops::Range<{integer}>`
found type `{integer}`
@@ -28,7 +28,7 @@ error[E0308]: mismatched types
LL | match [5..4, 99..105, 43..44] {
| ----------------------- this expression has type `[std::ops::Range<{integer}>; 3]`
LL | [..9, 99..100, _] => {},
- | -- ^^^ expected struct `Range`, found integer
+ | -- ^^^ expected `Range<{integer}>`, found integer
| |
| this is of type `{integer}`
|
diff --git a/tests/ui/half-open-range-patterns/half-open-range-pats-inclusive-match-arrow.rs b/tests/ui/half-open-range-patterns/half-open-range-pats-inclusive-match-arrow.rs
new file mode 100644
index 000000000..30173b1b4
--- /dev/null
+++ b/tests/ui/half-open-range-patterns/half-open-range-pats-inclusive-match-arrow.rs
@@ -0,0 +1,9 @@
+fn main() {
+ let x = 42;
+ match x {
+ 0..=73 => {},
+ 74..=> {},
+ //~^ ERROR unexpected `>` after inclusive range
+ //~| NOTE this is parsed as an inclusive range `..=`
+ }
+}
diff --git a/tests/ui/half-open-range-patterns/half-open-range-pats-inclusive-match-arrow.stderr b/tests/ui/half-open-range-patterns/half-open-range-pats-inclusive-match-arrow.stderr
new file mode 100644
index 000000000..cb7f998df
--- /dev/null
+++ b/tests/ui/half-open-range-patterns/half-open-range-pats-inclusive-match-arrow.stderr
@@ -0,0 +1,15 @@
+error: unexpected `>` after inclusive range
+ --> $DIR/half-open-range-pats-inclusive-match-arrow.rs:5:14
+ |
+LL | 74..=> {},
+ | ---^
+ | |
+ | this is parsed as an inclusive range `..=`
+ |
+help: add a space between the pattern and `=>`
+ |
+LL | 74.. => {},
+ | +
+
+error: aborting due to previous error
+
diff --git a/tests/ui/half-open-range-patterns/pat-tuple-5.stderr b/tests/ui/half-open-range-patterns/pat-tuple-5.stderr
index c60842638..43e7f03b8 100644
--- a/tests/ui/half-open-range-patterns/pat-tuple-5.stderr
+++ b/tests/ui/half-open-range-patterns/pat-tuple-5.stderr
@@ -4,7 +4,7 @@ error[E0308]: mismatched types
LL | match (0, 1) {
| ------ this expression has type `({integer}, {integer})`
LL | (PAT ..) => {}
- | ^^^ expected tuple, found `u8`
+ | ^^^ expected `({integer}, {integer})`, found `u8`
|
= note: expected tuple `({integer}, {integer})`
found type `u8`
diff --git a/tests/ui/higher-rank-trait-bounds/hang-on-deeply-nested-dyn.stderr b/tests/ui/higher-rank-trait-bounds/hang-on-deeply-nested-dyn.stderr
index 71e196c32..3662cbfb9 100644
--- a/tests/ui/higher-rank-trait-bounds/hang-on-deeply-nested-dyn.stderr
+++ b/tests/ui/higher-rank-trait-bounds/hang-on-deeply-nested-dyn.stderr
@@ -11,9 +11,9 @@ LL | | ),
LL | | ) {
| |_- expected `&dyn for<'a> Fn(&'a (dyn for<'a> Fn(&'a (dyn for<'a> Fn(&'a (dyn for<'a> Fn(&'a (dyn for<'a> Fn(&'a (dyn for<'a> Fn(&'a (dyn for<'a> Fn(&'a (dyn for<'a> Fn(&'a (dyn for<'a> Fn(&'a (dyn for<'a> Fn(&'a (dyn for<'a> Fn(&'a (dyn Fn(u32) + 'a)) + 'a)) + 'a)) + 'a)) + 'a)) + 'a)) + 'a)) + 'a)) + 'a)) + 'a)) + 'a))` because of return type
LL | f
- | ^ expected reference, found `u32`
+ | ^ expected `&dyn Fn(&dyn Fn(&dyn Fn(&...)))`, found `&dyn Fn(u32)`
|
- = note: expected reference `&dyn for<'a> Fn(&'a (dyn for<'a> Fn(&'a (dyn for<'a> Fn(&'a (dyn for<'a> Fn(&'a ...) + 'a)) + 'a)) + 'a))`
+ = note: expected reference `&dyn Fn(&dyn Fn(&dyn Fn(&dyn Fn(&dyn Fn(&dyn Fn(&dyn Fn(&dyn Fn(&dyn Fn(&dyn Fn(&dyn Fn(&...)))))))))))`
the full type name has been written to '$TEST_BUILD_DIR/higher-rank-trait-bounds/hang-on-deeply-nested-dyn/hang-on-deeply-nested-dyn.long-type-hash.txt'
found reference `&dyn Fn(u32)`
diff --git a/tests/ui/higher-rank-trait-bounds/hrtb-higher-ranker-supertraits-transitive.stderr b/tests/ui/higher-rank-trait-bounds/hrtb-higher-ranker-supertraits-transitive.stderr
index 8cda76b94..b1b8ffa8c 100644
--- a/tests/ui/higher-rank-trait-bounds/hrtb-higher-ranker-supertraits-transitive.stderr
+++ b/tests/ui/higher-rank-trait-bounds/hrtb-higher-ranker-supertraits-transitive.stderr
@@ -10,7 +10,7 @@ note: required by a bound in `want_bar_for_any_ccx`
--> $DIR/hrtb-higher-ranker-supertraits-transitive.rs:32:15
|
LL | fn want_bar_for_any_ccx<B>(b: &B)
- | -------------------- required by a bound in this
+ | -------------------- required by a bound in this function
LL | where B : for<'ccx> Bar<'ccx>
| ^^^^^^^^^^^^^^^^^^^ required by this bound in `want_bar_for_any_ccx`
help: consider further restricting this bound
diff --git a/tests/ui/higher-rank-trait-bounds/hrtb-higher-ranker-supertraits.stderr b/tests/ui/higher-rank-trait-bounds/hrtb-higher-ranker-supertraits.stderr
index 88793a152..7f96909b6 100644
--- a/tests/ui/higher-rank-trait-bounds/hrtb-higher-ranker-supertraits.stderr
+++ b/tests/ui/higher-rank-trait-bounds/hrtb-higher-ranker-supertraits.stderr
@@ -10,7 +10,7 @@ note: required by a bound in `want_foo_for_any_tcx`
--> $DIR/hrtb-higher-ranker-supertraits.rs:22:15
|
LL | fn want_foo_for_any_tcx<F>(f: &F)
- | -------------------- required by a bound in this
+ | -------------------- required by a bound in this function
LL | where F : for<'tcx> Foo<'tcx>
| ^^^^^^^^^^^^^^^^^^^ required by this bound in `want_foo_for_any_tcx`
help: consider further restricting this bound
@@ -30,7 +30,7 @@ note: required by a bound in `want_bar_for_any_ccx`
--> $DIR/hrtb-higher-ranker-supertraits.rs:39:15
|
LL | fn want_bar_for_any_ccx<B>(b: &B)
- | -------------------- required by a bound in this
+ | -------------------- required by a bound in this function
LL | where B : for<'ccx> Bar<'ccx>
| ^^^^^^^^^^^^^^^^^^^ required by this bound in `want_bar_for_any_ccx`
help: consider further restricting this bound
diff --git a/tests/ui/higher-rank-trait-bounds/hrtb-identity-fn-borrows.stderr b/tests/ui/higher-rank-trait-bounds/hrtb-identity-fn-borrows.stderr
index 4886a3c8b..25af011e3 100644
--- a/tests/ui/higher-rank-trait-bounds/hrtb-identity-fn-borrows.stderr
+++ b/tests/ui/higher-rank-trait-bounds/hrtb-identity-fn-borrows.stderr
@@ -2,9 +2,9 @@ error[E0506]: cannot assign to `x` because it is borrowed
--> $DIR/hrtb-identity-fn-borrows.rs:14:5
|
LL | let y = f.call(&x);
- | -- borrow of `x` occurs here
+ | -- `x` is borrowed here
LL | x = 5;
- | ^^^^^ assignment to borrowed `x` occurs here
+ | ^^^^^ `x` is assigned to here but it was already borrowed
...
LL | drop(y);
| - borrow later used here
diff --git a/tests/ui/higher-rank-trait-bounds/hrtb-wrong-kind.stderr b/tests/ui/higher-rank-trait-bounds/hrtb-wrong-kind.stderr
index f31aa5546..765ea9f78 100644
--- a/tests/ui/higher-rank-trait-bounds/hrtb-wrong-kind.stderr
+++ b/tests/ui/higher-rank-trait-bounds/hrtb-wrong-kind.stderr
@@ -1,14 +1,21 @@
-error: only lifetime parameters can be used in this context
+error[E0658]: only lifetime parameters can be used in this context
--> $DIR/hrtb-wrong-kind.rs:1:18
|
LL | fn a() where for<T> T: Copy {}
| ^
+ |
+ = note: see issue #108185 <https://github.com/rust-lang/rust/issues/108185> for more information
+ = help: add `#![feature(non_lifetime_binders)]` to the crate attributes to enable
-error: only lifetime parameters can be used in this context
+error[E0658]: only lifetime parameters can be used in this context
--> $DIR/hrtb-wrong-kind.rs:4:24
|
LL | fn b() where for<const C: usize> [(); C]: Copy {}
| ^
+ |
+ = note: see issue #108185 <https://github.com/rust-lang/rust/issues/108185> for more information
+ = help: add `#![feature(non_lifetime_binders)]` 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/tests/ui/higher-rank-trait-bounds/issue-30786.rs b/tests/ui/higher-rank-trait-bounds/issue-30786.rs
index e5f46f711..4a6399c8f 100644
--- a/tests/ui/higher-rank-trait-bounds/issue-30786.rs
+++ b/tests/ui/higher-rank-trait-bounds/issue-30786.rs
@@ -1,3 +1,5 @@
+// normalize-stderr-test: "long-type-\d+" -> "long-type-hash"
+
// rust-lang/rust#30786: the use of `for<'b> &'b mut A: Stream<Item=T`
// should act as assertion that item does not borrow from its stream;
// but an earlier buggy rustc allowed `.map(|x: &_| x)` which does
diff --git a/tests/ui/higher-rank-trait-bounds/issue-30786.stderr b/tests/ui/higher-rank-trait-bounds/issue-30786.stderr
index 0458d2535..6ec34d11a 100644
--- a/tests/ui/higher-rank-trait-bounds/issue-30786.stderr
+++ b/tests/ui/higher-rank-trait-bounds/issue-30786.stderr
@@ -1,5 +1,5 @@
-error[E0599]: the method `filterx` exists for struct `Map<Repeat, [closure@issue-30786.rs:117:27]>`, but its trait bounds were not satisfied
- --> $DIR/issue-30786.rs:118:22
+error[E0599]: the method `filterx` exists for struct `Map<Repeat, [closure@issue-30786.rs:119:27]>`, but its trait bounds were not satisfied
+ --> $DIR/issue-30786.rs:120:22
|
LL | pub struct Map<S, F> {
| --------------------
@@ -8,19 +8,19 @@ LL | pub struct Map<S, F> {
| doesn't satisfy `_: StreamExt`
...
LL | let filter = map.filterx(|x: &_| true);
- | ^^^^^^^ method cannot be called on `Map<Repeat, [closure@issue-30786.rs:117:27]>` due to unsatisfied trait bounds
+ | ^^^^^^^ method cannot be called on `Map<Repeat, [closure@issue-30786.rs:119:27]>` due to unsatisfied trait bounds
|
note: the following trait bounds were not satisfied:
- `&'a mut &Map<Repeat, [closure@$DIR/issue-30786.rs:117:27: 117:34]>: Stream`
- `&'a mut &mut Map<Repeat, [closure@$DIR/issue-30786.rs:117:27: 117:34]>: Stream`
- `&'a mut Map<Repeat, [closure@$DIR/issue-30786.rs:117:27: 117:34]>: Stream`
- --> $DIR/issue-30786.rs:96:50
+ `&'a mut &Map<Repeat, [closure@$DIR/issue-30786.rs:119:27: 119:34]>: Stream`
+ `&'a mut &mut Map<Repeat, [closure@$DIR/issue-30786.rs:119:27: 119:34]>: Stream`
+ `&'a mut Map<Repeat, [closure@$DIR/issue-30786.rs:119:27: 119:34]>: Stream`
+ --> $DIR/issue-30786.rs:98:50
|
LL | impl<T> StreamExt for T where for<'a> &'a mut T: Stream {}
| --------- - ^^^^^^ unsatisfied trait bound introduced here
-error[E0599]: the method `countx` exists for struct `Filter<Map<Repeat, for<'a> fn(&'a u64) -> &'a u64 {identity::<u64>}>, [closure@issue-30786.rs:129:30]>`, but its trait bounds were not satisfied
- --> $DIR/issue-30786.rs:130:24
+error[E0599]: the method `countx` exists for struct `Filter<Map<Repeat, fn(&u64) -> &u64 {identity::<u64>}>, [closure@issue-30786.rs:131:30]>`, but its trait bounds were not satisfied
+ --> $DIR/issue-30786.rs:132:24
|
LL | pub struct Filter<S, F> {
| -----------------------
@@ -31,11 +31,12 @@ LL | pub struct Filter<S, F> {
LL | let count = filter.countx();
| ^^^^^^ method cannot be called due to unsatisfied trait bounds
|
+ = note: the full type name has been written to '$TEST_BUILD_DIR/higher-rank-trait-bounds/issue-30786/issue-30786.long-type-hash.txt'
note: the following trait bounds were not satisfied:
- `&'a mut &Filter<Map<Repeat, for<'a> fn(&'a u64) -> &'a u64 {identity::<u64>}>, [closure@$DIR/issue-30786.rs:129:30: 129:37]>: Stream`
- `&'a mut &mut Filter<Map<Repeat, for<'a> fn(&'a u64) -> &'a u64 {identity::<u64>}>, [closure@$DIR/issue-30786.rs:129:30: 129:37]>: Stream`
- `&'a mut Filter<Map<Repeat, for<'a> fn(&'a u64) -> &'a u64 {identity::<u64>}>, [closure@$DIR/issue-30786.rs:129:30: 129:37]>: Stream`
- --> $DIR/issue-30786.rs:96:50
+ `&'a mut &Filter<Map<Repeat, for<'a> fn(&'a u64) -> &'a u64 {identity::<u64>}>, [closure@$DIR/issue-30786.rs:131:30: 131:37]>: Stream`
+ `&'a mut &mut Filter<Map<Repeat, for<'a> fn(&'a u64) -> &'a u64 {identity::<u64>}>, [closure@$DIR/issue-30786.rs:131:30: 131:37]>: Stream`
+ `&'a mut Filter<Map<Repeat, for<'a> fn(&'a u64) -> &'a u64 {identity::<u64>}>, [closure@$DIR/issue-30786.rs:131:30: 131:37]>: Stream`
+ --> $DIR/issue-30786.rs:98:50
|
LL | impl<T> StreamExt for T where for<'a> &'a mut T: Stream {}
| --------- - ^^^^^^ unsatisfied trait bound introduced here
diff --git a/tests/ui/issues/issue-39292.rs b/tests/ui/higher-rank-trait-bounds/issue-39292.rs
index 968cf0891..968cf0891 100644
--- a/tests/ui/issues/issue-39292.rs
+++ b/tests/ui/higher-rank-trait-bounds/issue-39292.rs
diff --git a/tests/ui/higher-rank-trait-bounds/issue-62203-hrtb-ice.stderr b/tests/ui/higher-rank-trait-bounds/issue-62203-hrtb-ice.stderr
index 810f7c28c..4d470ae70 100644
--- a/tests/ui/higher-rank-trait-bounds/issue-62203-hrtb-ice.stderr
+++ b/tests/ui/higher-rank-trait-bounds/issue-62203-hrtb-ice.stderr
@@ -1,4 +1,4 @@
-error[E0271]: type mismatch resolving `for<'r> <L<[closure@issue-62203-hrtb-ice.rs:42:16]> as T0<'r, (&'r u8,)>>::O == <_ as Ty<'r>>::V`
+error[E0271]: type mismatch resolving `<L<[closure@issue-62203-hrtb-ice.rs:42:16]> as T0<'r, (&u8,)>>::O == <_ as Ty<'r>>::V`
--> $DIR/issue-62203-hrtb-ice.rs:39:9
|
LL | let v = Unit2.m(
@@ -10,7 +10,7 @@ LL | | f: |x| {
... |
LL | | },
LL | | },
- | |_________^ type mismatch resolving `for<'r> <L<[closure@issue-62203-hrtb-ice.rs:42:16]> as T0<'r, (&'r u8,)>>::O == <_ as Ty<'r>>::V`
+ | |_________^ type mismatch resolving `<L<[closure@issue-62203-hrtb-ice.rs:42:16]> as T0<'r, (&u8,)>>::O == <_ as Ty<'r>>::V`
|
note: expected this to be `<_ as Ty<'_>>::V`
--> $DIR/issue-62203-hrtb-ice.rs:21:14
@@ -25,7 +25,7 @@ note: required by a bound in `T1::m`
--> $DIR/issue-62203-hrtb-ice.rs:27:51
|
LL | fn m<'a, B: Ty<'a>, F>(&self, f: F) -> Unit1
- | - required by a bound in this
+ | - required by a bound in this associated function
LL | where
LL | F: for<'r> T0<'r, (<Self as Ty<'r>>::V,), O = <B as Ty<'r>>::V>,
| ^^^^^^^^^^^^^^^^^^^^ required by this bound in `T1::m`
@@ -42,7 +42,7 @@ LL | | f: |x| {
... |
LL | | },
LL | | },
- | |_________^ expected struct `Unit3`, found struct `Unit4`
+ | |_________^ expected `Unit3`, found `Unit4`
|
note: required for `L<[closure@$DIR/issue-62203-hrtb-ice.rs:42:16: 42:19]>` to implement `for<'r> T0<'r, (&'r u8,)>`
--> $DIR/issue-62203-hrtb-ice.rs:17:16
@@ -56,7 +56,7 @@ note: required by a bound in `T1::m`
--> $DIR/issue-62203-hrtb-ice.rs:27:12
|
LL | fn m<'a, B: Ty<'a>, F>(&self, f: F) -> Unit1
- | - required by a bound in this
+ | - required by a bound in this associated function
LL | where
LL | F: for<'r> T0<'r, (<Self as Ty<'r>>::V,), O = <B as Ty<'r>>::V>,
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `T1::m`
diff --git a/tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-89118.stderr b/tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-89118.stderr
index 62d0128fd..edef6ccd3 100644
--- a/tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-89118.stderr
+++ b/tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-89118.stderr
@@ -15,7 +15,7 @@ note: required by a bound in `StackContext`
--> $DIR/issue-89118.rs:9:14
|
LL | trait StackContext
- | ------------ required by a bound in this
+ | ------------ required by a bound in this trait
LL | where
LL | Ctx<()>: for<'a> BufferUdpStateContext<&'a ()>,
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `StackContext`
@@ -37,7 +37,7 @@ note: required by a bound in `EthernetWorker`
--> $DIR/issue-89118.rs:28:14
|
LL | struct EthernetWorker<C>(C)
- | -------------- required by a bound in this
+ | -------------- required by a bound in this struct
LL | where
LL | Ctx<()>: for<'a> BufferUdpStateContext<&'a ()>;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `EthernetWorker`
@@ -59,7 +59,7 @@ note: required by a bound in `StackContext`
--> $DIR/issue-89118.rs:9:14
|
LL | trait StackContext
- | ------------ required by a bound in this
+ | ------------ required by a bound in this trait
LL | where
LL | Ctx<()>: for<'a> BufferUdpStateContext<&'a ()>,
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `StackContext`
diff --git a/tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-90950.stderr b/tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-90950.stderr
index 6206b167b..5be33bccd 100644
--- a/tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-90950.stderr
+++ b/tests/ui/higher-rank-trait-bounds/normalize-under-binder/issue-90950.stderr
@@ -11,7 +11,7 @@ note: required by a bound in `upcast`
--> $DIR/issue-90950.rs:27:42
|
LL | fn upcast<Y>(x: Yoke<Y>) -> Yoke<Box<dyn IsCovariant<'static> + 'static>> where
- | ------ required by a bound in this
+ | ------ required by a bound in this function
LL | Y: for<'a> Yokeable<'a>,
LL | for<'a> <Y as Yokeable<'a>>::Output: IsCovariant<'a>
| ^^^^^^^^^^^^^^^ required by this bound in `upcast`
diff --git a/tests/ui/higher-rank-trait-bounds/normalize-under-binder/norm-before-method-resolution.stderr b/tests/ui/higher-rank-trait-bounds/normalize-under-binder/norm-before-method-resolution.stderr
index 51c964600..73388a725 100644
--- a/tests/ui/higher-rank-trait-bounds/normalize-under-binder/norm-before-method-resolution.stderr
+++ b/tests/ui/higher-rank-trait-bounds/normalize-under-binder/norm-before-method-resolution.stderr
@@ -8,7 +8,7 @@ note: required by a bound in `weird_bound`
--> $DIR/norm-before-method-resolution.rs:18:40
|
LL | fn weird_bound<X>() -> X
- | ----------- required by a bound in this
+ | ----------- required by a bound in this function
...
LL | for<'a> <X as Trait<'a>>::Out: Copy
| ^^^^ required by this bound in `weird_bound`
diff --git a/tests/ui/hygiene/panic-location.run.stderr b/tests/ui/hygiene/panic-location.run.stderr
index 0b23b1cc2..1c6a7b02f 100644
--- a/tests/ui/hygiene/panic-location.run.stderr
+++ b/tests/ui/hygiene/panic-location.run.stderr
@@ -1,2 +1,2 @@
-thread 'main' panicked at 'capacity overflow', library/alloc/src/raw_vec.rs:518:5
+thread 'main' panicked at 'capacity overflow', library/alloc/src/raw_vec.rs:525:5
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
diff --git a/tests/ui/impl-header-lifetime-elision/path-elided.stderr b/tests/ui/impl-header-lifetime-elision/path-elided.stderr
index 0b7d3f1e8..18e4c618d 100644
--- a/tests/ui/impl-header-lifetime-elision/path-elided.stderr
+++ b/tests/ui/impl-header-lifetime-elision/path-elided.stderr
@@ -4,7 +4,6 @@ error[E0726]: implicit elided lifetime not allowed here
LL | impl MyTrait for Foo {
| ^^^ expected lifetime parameter
|
- = note: assuming a `'static` lifetime...
help: indicate the anonymous lifetime
|
LL | impl MyTrait for Foo<'_> {
diff --git a/tests/ui/impl-header-lifetime-elision/trait-elided.stderr b/tests/ui/impl-header-lifetime-elision/trait-elided.stderr
index 412bba6be..74631a037 100644
--- a/tests/ui/impl-header-lifetime-elision/trait-elided.stderr
+++ b/tests/ui/impl-header-lifetime-elision/trait-elided.stderr
@@ -4,7 +4,6 @@ error[E0726]: implicit elided lifetime not allowed here
LL | impl MyTrait for u32 {}
| ^^^^^^^ expected lifetime parameter
|
- = note: assuming a `'static` lifetime...
help: indicate the anonymous lifetime
|
LL | impl MyTrait<'_> for u32 {}
diff --git a/tests/ui/impl-trait/auto-trait-leak.stderr b/tests/ui/impl-trait/auto-trait-leak.stderr
index feedfc40a..fd0358421 100644
--- a/tests/ui/impl-trait/auto-trait-leak.stderr
+++ b/tests/ui/impl-trait/auto-trait-leak.stderr
@@ -39,7 +39,7 @@ note: ...which requires type-checking `cycle1`...
|
LL | send(cycle2().clone());
| ^^^^
- = note: ...which requires evaluating trait selection obligation `impl core::clone::Clone: core::marker::Send`...
+ = note: ...which requires evaluating trait selection obligation `cycle2::{opaque#0}: core::marker::Send`...
note: ...which requires computing type of `cycle2::{opaque#0}`...
--> $DIR/auto-trait-leak.rs:19:16
|
@@ -80,7 +80,7 @@ note: ...which requires type-checking `cycle2`...
|
LL | send(cycle1().clone());
| ^^^^
- = note: ...which requires evaluating trait selection obligation `impl core::clone::Clone: core::marker::Send`...
+ = note: ...which requires evaluating trait selection obligation `cycle1::{opaque#0}: 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/tests/ui/impl-trait/bound-normalization-pass.rs b/tests/ui/impl-trait/bound-normalization-pass.rs
index 51718079d..5613c1916 100644
--- a/tests/ui/impl-trait/bound-normalization-pass.rs
+++ b/tests/ui/impl-trait/bound-normalization-pass.rs
@@ -1,8 +1,6 @@
// check-pass
// edition:2018
// revisions: default sa
-//[sa] compile-flags: -Z save-analysis
-//-^ To make this the regression test for #75962.
#![feature(type_alias_impl_trait)]
diff --git a/tests/ui/impl-trait/dyn-trait-return-should-be-impl-trait.stderr b/tests/ui/impl-trait/dyn-trait-return-should-be-impl-trait.stderr
index 7f73d5e12..dc1e40ea5 100644
--- a/tests/ui/impl-trait/dyn-trait-return-should-be-impl-trait.stderr
+++ b/tests/ui/impl-trait/dyn-trait-return-should-be-impl-trait.stderr
@@ -2,7 +2,7 @@ error[E0308]: mismatched types
--> $DIR/dyn-trait-return-should-be-impl-trait.rs:7:35
|
LL | fn fuz() -> (usize, Trait) { (42, Struct) }
- | ^^^^^^ expected trait object `dyn Trait`, found struct `Struct`
+ | ^^^^^^ expected `dyn Trait`, found `Struct`
|
= note: expected trait object `(dyn Trait + 'static)`
found struct `Struct`
@@ -16,14 +16,14 @@ LL | fn fuz() -> (usize, Trait) { (42, Struct) }
| doesn't have a size known at compile-time
|
= help: within `(usize, (dyn Trait + 'static))`, the trait `Sized` is not implemented for `(dyn Trait + 'static)`
- = note: required because it appears within the type `(usize, (dyn Trait + 'static))`
+ = note: required because it appears within the type `(usize, dyn Trait)`
= note: the return type of a function must have a statically known size
error[E0308]: mismatched types
--> $DIR/dyn-trait-return-should-be-impl-trait.rs:10:39
|
LL | fn bar() -> (usize, dyn Trait) { (42, Struct) }
- | ^^^^^^ expected trait object `dyn Trait`, found struct `Struct`
+ | ^^^^^^ expected `dyn Trait`, found `Struct`
|
= note: expected trait object `(dyn Trait + 'static)`
found struct `Struct`
@@ -37,7 +37,7 @@ LL | fn bar() -> (usize, dyn Trait) { (42, Struct) }
| doesn't have a size known at compile-time
|
= help: within `(usize, (dyn Trait + 'static))`, the trait `Sized` is not implemented for `(dyn Trait + 'static)`
- = note: required because it appears within the type `(usize, (dyn Trait + 'static))`
+ = note: required because it appears within the type `(usize, dyn Trait)`
= note: the return type of a function must have a statically known size
error[E0746]: return type cannot have an unboxed trait object
@@ -110,7 +110,7 @@ LL | | Struct
| | ------ expected because of this
LL | | } else {
LL | | 42
- | | ^^ expected struct `Struct`, found integer
+ | | ^^ expected `Struct`, found integer
LL | | }
| |_____- `if` and `else` have incompatible types
@@ -144,7 +144,7 @@ LL | fn bam() -> Box<dyn Trait> {
| -------------- expected `Box<(dyn Trait + 'static)>` because of return type
LL | if true {
LL | return Struct;
- | ^^^^^^ expected struct `Box`, found struct `Struct`
+ | ^^^^^^ expected `Box<dyn Trait>`, found `Struct`
|
= note: expected struct `Box<(dyn Trait + 'static)>`
found struct `Struct`
@@ -161,7 +161,7 @@ LL | fn bam() -> Box<dyn Trait> {
| -------------- expected `Box<(dyn Trait + 'static)>` because of return type
...
LL | 42
- | ^^ expected struct `Box`, found integer
+ | ^^ expected `Box<dyn Trait>`, found integer
|
= note: expected struct `Box<(dyn Trait + 'static)>`
found type `{integer}`
@@ -178,7 +178,7 @@ LL | fn baq() -> Box<dyn Trait> {
| -------------- expected `Box<(dyn Trait + 'static)>` because of return type
LL | if true {
LL | return 0;
- | ^ expected struct `Box`, found integer
+ | ^ expected `Box<dyn Trait>`, found integer
|
= note: expected struct `Box<(dyn Trait + 'static)>`
found type `{integer}`
@@ -195,7 +195,7 @@ LL | fn baq() -> Box<dyn Trait> {
| -------------- expected `Box<(dyn Trait + 'static)>` because of return type
...
LL | 42
- | ^^ expected struct `Box`, found integer
+ | ^^ expected `Box<dyn Trait>`, found integer
|
= note: expected struct `Box<(dyn Trait + 'static)>`
found type `{integer}`
@@ -212,7 +212,7 @@ LL | fn baz() -> Box<dyn Trait> {
| -------------- expected `Box<(dyn Trait + 'static)>` because of return type
LL | if true {
LL | Struct
- | ^^^^^^ expected struct `Box`, found struct `Struct`
+ | ^^^^^^ expected `Box<dyn Trait>`, found `Struct`
|
= note: expected struct `Box<(dyn Trait + 'static)>`
found struct `Struct`
@@ -229,7 +229,7 @@ LL | fn baz() -> Box<dyn Trait> {
| -------------- expected `Box<(dyn Trait + 'static)>` because of return type
...
LL | 42
- | ^^ expected struct `Box`, found integer
+ | ^^ expected `Box<dyn Trait>`, found integer
|
= note: expected struct `Box<(dyn Trait + 'static)>`
found type `{integer}`
@@ -246,7 +246,7 @@ LL | fn baw() -> Box<dyn Trait> {
| -------------- expected `Box<(dyn Trait + 'static)>` because of return type
LL | if true {
LL | 0
- | ^ expected struct `Box`, found integer
+ | ^ expected `Box<dyn Trait>`, found integer
|
= note: expected struct `Box<(dyn Trait + 'static)>`
found type `{integer}`
@@ -263,7 +263,7 @@ LL | fn baw() -> Box<dyn Trait> {
| -------------- expected `Box<(dyn Trait + 'static)>` because of return type
...
LL | 42
- | ^^ expected struct `Box`, found integer
+ | ^^ expected `Box<dyn Trait>`, found integer
|
= note: expected struct `Box<(dyn Trait + 'static)>`
found type `{integer}`
diff --git a/tests/ui/impl-trait/equal-hidden-lifetimes.rs b/tests/ui/impl-trait/equal-hidden-lifetimes.rs
index 79db88828..a6dbf3f08 100644
--- a/tests/ui/impl-trait/equal-hidden-lifetimes.rs
+++ b/tests/ui/impl-trait/equal-hidden-lifetimes.rs
@@ -5,7 +5,6 @@
// `'a == 'static` so `&'a i32` is fine as the return type
fn equal_regions_static<'a: 'static>(x: &'a i32) -> impl Sized {
- //~^ WARNING unnecessary lifetime parameter `'a`
x
}
diff --git a/tests/ui/impl-trait/equal-hidden-lifetimes.stderr b/tests/ui/impl-trait/equal-hidden-lifetimes.stderr
deleted file mode 100644
index 3e48aef55..000000000
--- a/tests/ui/impl-trait/equal-hidden-lifetimes.stderr
+++ /dev/null
@@ -1,10 +0,0 @@
-warning: unnecessary lifetime parameter `'a`
- --> $DIR/equal-hidden-lifetimes.rs:7:25
- |
-LL | fn equal_regions_static<'a: 'static>(x: &'a i32) -> impl Sized {
- | ^^
- |
- = help: you can use the `'static` lifetime directly, in place of `'a`
-
-warning: 1 warning emitted
-
diff --git a/tests/ui/impl-trait/equality2.stderr b/tests/ui/impl-trait/equality2.stderr
index e399a6102..52f25d245 100644
--- a/tests/ui/impl-trait/equality2.stderr
+++ b/tests/ui/impl-trait/equality2.stderr
@@ -54,6 +54,7 @@ LL | x = (x.1,
|
= note: expected opaque type `impl Foo` (`u32`)
found opaque type `impl Foo` (`i32`)
+ = note: distinct uses of `impl Trait` result in different opaque types
error[E0308]: mismatched types
--> $DIR/equality2.rs:41:10
@@ -69,6 +70,7 @@ LL | x.0);
|
= note: expected opaque type `impl Foo` (`i32`)
found opaque type `impl Foo` (`u32`)
+ = note: distinct uses of `impl Trait` result in different opaque types
error: aborting due to 4 previous errors; 1 warning emitted
diff --git a/tests/ui/impl-trait/explicit-generic-args-with-impl-trait/explicit-generic-args-for-impl.stderr b/tests/ui/impl-trait/explicit-generic-args-with-impl-trait/explicit-generic-args-for-impl.stderr
index c8b82783e..9c1011018 100644
--- a/tests/ui/impl-trait/explicit-generic-args-with-impl-trait/explicit-generic-args-for-impl.stderr
+++ b/tests/ui/impl-trait/explicit-generic-args-with-impl-trait/explicit-generic-args-for-impl.stderr
@@ -1,4 +1,4 @@
-error[E0107]: this function takes 1 generic argument but 2 generic arguments were supplied
+error[E0107]: function takes 1 generic argument but 2 generic arguments were supplied
--> $DIR/explicit-generic-args-for-impl.rs:4:5
|
LL | foo::<str, String>("".to_string());
diff --git a/tests/ui/impl-trait/explicit-generic-args-with-impl-trait/not-enough-args.stderr b/tests/ui/impl-trait/explicit-generic-args-with-impl-trait/not-enough-args.stderr
index 9d6db88d3..a26460c8e 100644
--- a/tests/ui/impl-trait/explicit-generic-args-with-impl-trait/not-enough-args.stderr
+++ b/tests/ui/impl-trait/explicit-generic-args-with-impl-trait/not-enough-args.stderr
@@ -1,4 +1,4 @@
-error[E0107]: this function takes 2 generic arguments but 1 generic argument was supplied
+error[E0107]: function takes 2 generic arguments but 1 generic argument was supplied
--> $DIR/not-enough-args.rs:4:5
|
LL | f::<[u8]>("a", b"a");
diff --git a/tests/ui/impl-trait/feature-self-return-type.stderr b/tests/ui/impl-trait/feature-self-return-type.stderr
index 601e53b76..b9b8d00ce 100644
--- a/tests/ui/impl-trait/feature-self-return-type.stderr
+++ b/tests/ui/impl-trait/feature-self-return-type.stderr
@@ -4,6 +4,7 @@ error[E0597]: `bar` does not live long enough
LL | let x = {
| - borrow later stored here
LL | let bar = 22;
+ | --- binding `bar` declared here
LL | Foo::new(&bar).into()
| ^^^^ borrowed value does not live long enough
LL |
@@ -16,6 +17,7 @@ error[E0597]: `y` does not live long enough
LL | let x = {
| - borrow later stored here
LL | let y = ();
+ | - binding `y` declared here
LL | foo(&y)
| ^^ borrowed value does not live long enough
LL |
@@ -28,6 +30,7 @@ error[E0597]: `y` does not live long enough
LL | let x = {
| - borrow later stored here
LL | let y = ();
+ | - binding `y` declared here
LL | foo(&y)
| ^^ borrowed value does not live long enough
LL |
diff --git a/tests/ui/impl-trait/hidden-lifetimes.stderr b/tests/ui/impl-trait/hidden-lifetimes.stderr
index 3cc47e1e8..bc8f559fd 100644
--- a/tests/ui/impl-trait/hidden-lifetimes.stderr
+++ b/tests/ui/impl-trait/hidden-lifetimes.stderr
@@ -2,7 +2,9 @@ error[E0700]: hidden type for `impl Swap + 'a` captures lifetime that does not a
--> $DIR/hidden-lifetimes.rs:29:5
|
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
+ | -- -------------- opaque type defined here
+ | |
+ | hidden type `&'a mut &'b T` captures the lifetime `'b` as defined here
LL | x
| ^
|
@@ -15,7 +17,9 @@ error[E0700]: hidden type for `impl Swap + 'a` captures lifetime that does not a
--> $DIR/hidden-lifetimes.rs:46:5
|
LL | fn hide_rc_refcell<'a, 'b: 'a, T: 'static>(x: Rc<RefCell<&'b T>>) -> impl Swap + 'a {
- | -- hidden type `Rc<RefCell<&'b T>>` captures the lifetime `'b` as defined here
+ | -- -------------- opaque type defined here
+ | |
+ | hidden type `Rc<RefCell<&'b T>>` captures the lifetime `'b` as defined here
LL | x
| ^
|
diff --git a/tests/ui/impl-trait/impl-fn-hrtb-bounds-2.stderr b/tests/ui/impl-trait/impl-fn-hrtb-bounds-2.stderr
index 433b76b7a..d56e1273f 100644
--- a/tests/ui/impl-trait/impl-fn-hrtb-bounds-2.stderr
+++ b/tests/ui/impl-trait/impl-fn-hrtb-bounds-2.stderr
@@ -1,6 +1,8 @@
error[E0700]: hidden type for `impl Debug` captures lifetime that does not appear in bounds
--> $DIR/impl-fn-hrtb-bounds-2.rs:5:9
|
+LL | fn a() -> impl Fn(&u8) -> impl Debug {
+ | ---------- opaque type defined here
LL | |x| x
| --- ^
| |
diff --git a/tests/ui/impl-trait/in-trait/deep-match.stderr b/tests/ui/impl-trait/in-trait/deep-match.stderr
index 034ee5ea4..3eba419c0 100644
--- a/tests/ui/impl-trait/in-trait/deep-match.stderr
+++ b/tests/ui/impl-trait/in-trait/deep-match.stderr
@@ -4,7 +4,7 @@ error[E0053]: method `bar` has an incompatible return type for trait
LL | fn bar() -> i32 { 0 }
| ^^^
| |
- | expected struct `Wrapper`, found `i32`
+ | expected `Wrapper<_>`, found `i32`
| return type in trait
|
= note: expected struct `Wrapper<_>`
diff --git a/tests/ui/impl-trait/in-trait/default-body-type-err-2.stderr b/tests/ui/impl-trait/in-trait/default-body-type-err-2.stderr
index 142b1bff1..cc3bdf0e5 100644
--- a/tests/ui/impl-trait/in-trait/default-body-type-err-2.stderr
+++ b/tests/ui/impl-trait/in-trait/default-body-type-err-2.stderr
@@ -4,7 +4,7 @@ error[E0308]: mismatched types
LL | 42
| ^^- help: try using a conversion method: `.to_string()`
| |
- | expected struct `String`, found integer
+ | expected `String`, found integer
error: aborting due to previous error
diff --git a/tests/ui/impl-trait/in-trait/default-body-type-err.stderr b/tests/ui/impl-trait/in-trait/default-body-type-err.stderr
index 461247a3e..4742eb37d 100644
--- a/tests/ui/impl-trait/in-trait/default-body-type-err.stderr
+++ b/tests/ui/impl-trait/in-trait/default-body-type-err.stderr
@@ -2,7 +2,7 @@ error[E0271]: type mismatch resolving `<&i32 as Deref>::Target == String`
--> $DIR/default-body-type-err.rs:7:22
|
LL | fn lol(&self) -> impl Deref<Target = String> {
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `i32`, found struct `String`
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `i32`, found `String`
LL |
LL | &1i32
| ----- return type was inferred to be `&i32` here
diff --git a/tests/ui/impl-trait/in-trait/default-method-constraint.rs b/tests/ui/impl-trait/in-trait/default-method-constraint.rs
new file mode 100644
index 000000000..8c50cc295
--- /dev/null
+++ b/tests/ui/impl-trait/in-trait/default-method-constraint.rs
@@ -0,0 +1,17 @@
+// check-pass
+
+// This didn't work in the previous default RPITIT method hack attempt
+
+#![feature(return_position_impl_trait_in_trait)]
+//~^ WARN the feature `return_position_impl_trait_in_trait` is incomplete
+
+trait Foo {
+ fn bar(x: bool) -> impl Sized {
+ if x {
+ let _: u32 = Self::bar(!x);
+ }
+ Default::default()
+ }
+}
+
+fn main() {}
diff --git a/tests/ui/impl-trait/in-trait/default-method-constraint.stderr b/tests/ui/impl-trait/in-trait/default-method-constraint.stderr
new file mode 100644
index 000000000..5e18605aa
--- /dev/null
+++ b/tests/ui/impl-trait/in-trait/default-method-constraint.stderr
@@ -0,0 +1,11 @@
+warning: the feature `return_position_impl_trait_in_trait` is incomplete and may not be safe to use and/or cause compiler crashes
+ --> $DIR/default-method-constraint.rs:5:12
+ |
+LL | #![feature(return_position_impl_trait_in_trait)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: see issue #91611 <https://github.com/rust-lang/rust/issues/91611> for more information
+ = note: `#[warn(incomplete_features)]` on by default
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/impl-trait/in-trait/method-signature-matches.stderr b/tests/ui/impl-trait/in-trait/method-signature-matches.stderr
index 4dfd77222..3ec62020e 100644
--- a/tests/ui/impl-trait/in-trait/method-signature-matches.stderr
+++ b/tests/ui/impl-trait/in-trait/method-signature-matches.stderr
@@ -24,16 +24,6 @@ LL | async fn owo(_: u8) {}
| expected `()`, found `u8`
| help: change the parameter type to match the trait: `()`
|
-note: while checking the return type of the `async fn`
- --> $DIR/method-signature-matches.rs:20:25
- |
-LL | async fn owo(_: u8) {}
- | ^ checked the `Output` of this `async fn`, expected opaque type
-note: while checking the return type of the `async fn`
- --> $DIR/method-signature-matches.rs:20:25
- |
-LL | async fn owo(_: u8) {}
- | ^ checked the `Output` of this `async fn`, found opaque type
note: type in trait
--> $DIR/method-signature-matches.rs:16:21
|
diff --git a/tests/ui/impl-trait/in-trait/new-lowering-strategy/simple-trait.rs b/tests/ui/impl-trait/in-trait/new-lowering-strategy/simple-trait.rs
new file mode 100644
index 000000000..dfce973d7
--- /dev/null
+++ b/tests/ui/impl-trait/in-trait/new-lowering-strategy/simple-trait.rs
@@ -0,0 +1,11 @@
+// check-pass
+// compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty
+
+#![feature(return_position_impl_trait_in_trait)]
+#![allow(incomplete_features)]
+
+trait Foo {
+ fn foo() -> impl Sized;
+}
+
+fn main() {}
diff --git a/tests/ui/impl-trait/in-trait/signature-mismatch.stderr b/tests/ui/impl-trait/in-trait/signature-mismatch.stderr
index e10566017..c4fcaabe4 100644
--- a/tests/ui/impl-trait/in-trait/signature-mismatch.stderr
+++ b/tests/ui/impl-trait/in-trait/signature-mismatch.stderr
@@ -2,12 +2,12 @@ error: `impl` item signature doesn't match `trait` item signature
--> $DIR/signature-mismatch.rs:15:5
|
LL | fn async_fn(&self, buff: &[u8]) -> impl Future<Output = Vec<u8>>;
- | ----------------------------------------------------------------- expected `fn(&'1 Struct, &'2 [u8]) -> impl Future<Output = Vec<u8>> + 'static`
+ | ----------------------------------------------------------------- expected `fn(&'1 Struct, &'2 [u8]) -> impl Future<Output = Vec<u8>> + '3`
...
LL | fn async_fn<'a>(&self, buff: &'a [u8]) -> impl Future<Output = Vec<u8>> + 'a {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ found `fn(&'1 Struct, &'2 [u8]) -> impl Future<Output = Vec<u8>> + '2`
|
- = note: expected signature `fn(&'1 Struct, &'2 [u8]) -> impl Future<Output = Vec<u8>> + 'static`
+ = note: expected signature `fn(&'1 Struct, &'2 [u8]) -> impl Future<Output = Vec<u8>> + '3`
found signature `fn(&'1 Struct, &'2 [u8]) -> impl Future<Output = Vec<u8>> + '2`
= help: the lifetime requirements from the `impl` do not correspond to the requirements in the `trait`
= help: verify the lifetime relationships in the `trait` and `impl` between the `self` argument, the other inputs and its output
diff --git a/tests/ui/impl-trait/in-trait/specialization-broken.rs b/tests/ui/impl-trait/in-trait/specialization-broken.rs
index 9d27d3710..2fcffdf3f 100644
--- a/tests/ui/impl-trait/in-trait/specialization-broken.rs
+++ b/tests/ui/impl-trait/in-trait/specialization-broken.rs
@@ -15,6 +15,7 @@ where
{
fn bar(&self) -> U {
//~^ ERROR method `bar` has an incompatible type for trait
+ //~| ERROR method with return-position `impl Trait` in trait cannot be specialized
*self
}
}
diff --git a/tests/ui/impl-trait/in-trait/specialization-broken.stderr b/tests/ui/impl-trait/in-trait/specialization-broken.stderr
index 37cfd7449..dc621d6b8 100644
--- a/tests/ui/impl-trait/in-trait/specialization-broken.stderr
+++ b/tests/ui/impl-trait/in-trait/specialization-broken.stderr
@@ -18,6 +18,14 @@ LL | fn bar(&self) -> impl Sized;
= note: expected signature `fn(&U) -> impl Sized`
found signature `fn(&U) -> U`
-error: aborting due to previous error
+error: method with return-position `impl Trait` in trait cannot be specialized
+ --> $DIR/specialization-broken.rs:16:5
+ |
+LL | fn bar(&self) -> U {
+ | ^^^^^^^^^^^^^^^^^^
+ |
+ = note: specialization behaves in inconsistent and surprising ways with `#![feature(return_position_impl_trait_in_trait)]`, and for now is disallowed
+
+error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0053`.
diff --git a/tests/ui/impl-trait/issue-102605.stderr b/tests/ui/impl-trait/issue-102605.stderr
index d4aba9149..dfe18e43e 100644
--- a/tests/ui/impl-trait/issue-102605.stderr
+++ b/tests/ui/impl-trait/issue-102605.stderr
@@ -2,17 +2,15 @@ error[E0308]: mismatched types
--> $DIR/issue-102605.rs:13:20
|
LL | convert_result(foo())
- | -------------- ^^^^^ expected enum `Result`, found opaque type
+ | -------------- ^^^^^ expected `Result<(), _>`, found future
| |
| arguments to this function are incorrect
|
-note: while checking the return type of the `async fn`
- --> $DIR/issue-102605.rs:3:19
+note: calling an async function returns a future
+ --> $DIR/issue-102605.rs:13:20
|
-LL | async fn foo() -> Result<(), String> {
- | ^^^^^^^^^^^^^^^^^^ checked the `Output` of this `async fn`, found opaque type
- = note: expected enum `Result<(), _>`
- found opaque type `impl Future<Output = Result<(), String>>`
+LL | convert_result(foo())
+ | ^^^^^
note: function defined here
--> $DIR/issue-102605.rs:7:4
|
diff --git a/tests/ui/impl-trait/issue-55872-2.drop_tracking.stderr b/tests/ui/impl-trait/issue-55872-2.drop_tracking.stderr
new file mode 100644
index 000000000..477c964bd
--- /dev/null
+++ b/tests/ui/impl-trait/issue-55872-2.drop_tracking.stderr
@@ -0,0 +1,8 @@
+error: type parameter `T` is part of concrete type but not used in parameter list for the `impl Trait` type alias
+ --> $DIR/issue-55872-2.rs:17:9
+ |
+LL | async {}
+ | ^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/tests/ui/impl-trait/issue-55872-2.drop_tracking_mir.stderr b/tests/ui/impl-trait/issue-55872-2.drop_tracking_mir.stderr
new file mode 100644
index 000000000..c14bb5cc9
--- /dev/null
+++ b/tests/ui/impl-trait/issue-55872-2.drop_tracking_mir.stderr
@@ -0,0 +1,14 @@
+error: type parameter `T` is part of concrete type but not used in parameter list for the `impl Trait` type alias
+ --> $DIR/issue-55872-2.rs:17:9
+ |
+LL | async {}
+ | ^^^^^^^^
+
+error: type parameter `T` is part of concrete type but not used in parameter list for the `impl Trait` type alias
+ --> $DIR/issue-55872-2.rs:17:9
+ |
+LL | async {}
+ | ^^^^^^^^
+
+error: aborting due to 2 previous errors
+
diff --git a/tests/ui/impl-trait/issue-55872-2.no_drop_tracking.stderr b/tests/ui/impl-trait/issue-55872-2.no_drop_tracking.stderr
new file mode 100644
index 000000000..477c964bd
--- /dev/null
+++ b/tests/ui/impl-trait/issue-55872-2.no_drop_tracking.stderr
@@ -0,0 +1,8 @@
+error: type parameter `T` is part of concrete type but not used in parameter list for the `impl Trait` type alias
+ --> $DIR/issue-55872-2.rs:17:9
+ |
+LL | async {}
+ | ^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/tests/ui/impl-trait/issue-55872-2.rs b/tests/ui/impl-trait/issue-55872-2.rs
index 4443d3c4d..cbc7b5d62 100644
--- a/tests/ui/impl-trait/issue-55872-2.rs
+++ b/tests/ui/impl-trait/issue-55872-2.rs
@@ -1,3 +1,6 @@
+// revisions: no_drop_tracking drop_tracking drop_tracking_mir
+// [drop_tracking] compile-flags: -Zdrop-tracking
+// [drop_tracking_mir] compile-flags: -Zdrop-tracking-mir
// edition:2018
#![feature(type_alias_impl_trait)]
@@ -13,6 +16,7 @@ impl<S> Bar for S {
fn foo<T>() -> Self::E {
async {}
//~^ ERROR type parameter `T` is part of concrete type but not used in parameter list for the `impl Trait` type alias
+ //[drop_tracking_mir]~^^ ERROR type parameter `T` is part of concrete type but not used in parameter list for the `impl Trait` type alias
}
}
diff --git a/tests/ui/impl-trait/issue-55872-2.stderr b/tests/ui/impl-trait/issue-55872-2.stderr
index 11b8485c8..477c964bd 100644
--- a/tests/ui/impl-trait/issue-55872-2.stderr
+++ b/tests/ui/impl-trait/issue-55872-2.stderr
@@ -1,5 +1,5 @@
error: type parameter `T` is part of concrete type but not used in parameter list for the `impl Trait` type alias
- --> $DIR/issue-55872-2.rs:14:9
+ --> $DIR/issue-55872-2.rs:17:9
|
LL | async {}
| ^^^^^^^^
diff --git a/tests/ui/impl-trait/issue-99914.stderr b/tests/ui/impl-trait/issue-99914.stderr
index 074d5d58d..c86e9eadc 100644
--- a/tests/ui/impl-trait/issue-99914.stderr
+++ b/tests/ui/impl-trait/issue-99914.stderr
@@ -2,15 +2,8 @@ error[E0308]: mismatched types
--> $DIR/issue-99914.rs:9:27
|
LL | t.and_then(|t| -> _ { bar(t) });
- | ^^^^^^ expected enum `Result`, found opaque type
+ | ^^^^^^ expected `Result<_, Error>`, found future
|
-note: while checking the return type of the `async fn`
- --> $DIR/issue-99914.rs:13:23
- |
-LL | async fn bar(t: Okay) {}
- | ^ checked the `Output` of this `async fn`, found opaque type
- = note: expected enum `Result<_, Error>`
- found opaque type `impl Future<Output = ()>`
help: try wrapping the expression in `Ok`
|
LL | t.and_then(|t| -> _ { Ok(bar(t)) });
diff --git a/tests/ui/impl-trait/issues/infinite-impl-trait-issue-38064.stderr b/tests/ui/impl-trait/issues/infinite-impl-trait-issue-38064.stderr
index 16a1262ec..92a329062 100644
--- a/tests/ui/impl-trait/issues/infinite-impl-trait-issue-38064.stderr
+++ b/tests/ui/impl-trait/issues/infinite-impl-trait-issue-38064.stderr
@@ -8,13 +8,13 @@ LL | Foo(bar())
| ---------- returning here with type `Foo<impl Quux>`
...
LL | fn bar() -> impl Quux {
- | --------- returning this opaque type `Foo<impl Quux>`
+ | --------- returning this type `Foo<impl Quux>`
error[E0720]: cannot resolve opaque type
--> $DIR/infinite-impl-trait-issue-38064.rs:14:13
|
LL | fn foo() -> impl Quux {
- | --------- returning this opaque type `Bar<impl Quux>`
+ | --------- returning this type `Bar<impl Quux>`
...
LL | fn bar() -> impl Quux {
| ^^^^^^^^^ recursive opaque type
diff --git a/tests/ui/impl-trait/issues/issue-54600.stderr b/tests/ui/impl-trait/issues/issue-54600.stderr
index 316566a57..7ef063af9 100644
--- a/tests/ui/impl-trait/issues/issue-54600.stderr
+++ b/tests/ui/impl-trait/issues/issue-54600.stderr
@@ -1,4 +1,4 @@
-error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in variable binding
+error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in variable bindings
--> $DIR/issue-54600.rs:4:19
|
LL | let x: Option<impl Debug> = Some(44_u32);
diff --git a/tests/ui/impl-trait/issues/issue-54840.stderr b/tests/ui/impl-trait/issues/issue-54840.stderr
index 8d82133ac..1d1316f0e 100644
--- a/tests/ui/impl-trait/issues/issue-54840.stderr
+++ b/tests/ui/impl-trait/issues/issue-54840.stderr
@@ -1,4 +1,4 @@
-error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in variable binding
+error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in variable bindings
--> $DIR/issue-54840.rs:5:13
|
LL | let j: &impl Add = &i;
diff --git a/tests/ui/impl-trait/issues/issue-58504.stderr b/tests/ui/impl-trait/issues/issue-58504.stderr
index 6656e9fc3..26ec2a4f9 100644
--- a/tests/ui/impl-trait/issues/issue-58504.stderr
+++ b/tests/ui/impl-trait/issues/issue-58504.stderr
@@ -1,4 +1,4 @@
-error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in variable binding
+error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in variable bindings
--> $DIR/issue-58504.rs:10:16
|
LL | let gens: [impl Generator<Return=!, Yield=()>;2] = [ mk_gen(), mk_gen() ];
diff --git a/tests/ui/impl-trait/issues/issue-58956.stderr b/tests/ui/impl-trait/issues/issue-58956.stderr
index 123fb4df4..2b4d0abdf 100644
--- a/tests/ui/impl-trait/issues/issue-58956.stderr
+++ b/tests/ui/impl-trait/issues/issue-58956.stderr
@@ -1,10 +1,10 @@
-error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in type
+error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in const types
--> $DIR/issue-58956.rs:7:11
|
LL | const _A: impl Lam = {
| ^^^^^^^^
-error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in variable binding
+error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in variable bindings
--> $DIR/issue-58956.rs:9:17
|
LL | let x: Wrap<impl Lam> = Wrap(B);
diff --git a/tests/ui/impl-trait/issues/issue-70971.stderr b/tests/ui/impl-trait/issues/issue-70971.stderr
index 4dda4c22a..d066256bf 100644
--- a/tests/ui/impl-trait/issues/issue-70971.stderr
+++ b/tests/ui/impl-trait/issues/issue-70971.stderr
@@ -1,4 +1,4 @@
-error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in variable binding
+error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in variable bindings
--> $DIR/issue-70971.rs:2:14
|
LL | let x : (impl Copy,) = (true,);
diff --git a/tests/ui/impl-trait/issues/issue-74282.stderr b/tests/ui/impl-trait/issues/issue-74282.stderr
index 5b05fb281..724f3c5d6 100644
--- a/tests/ui/impl-trait/issues/issue-74282.stderr
+++ b/tests/ui/impl-trait/issues/issue-74282.stderr
@@ -10,7 +10,7 @@ LL | Anonymous(|| {
| | arguments to this struct are incorrect
LL | | 3
LL | | })
- | |_____^ expected closure, found a different closure
+ | |_____^ expected opaque type, found closure
|
= note: expected opaque type `Closure`
found closure `[closure@$DIR/issue-74282.rs:8:15: 8:17]`
@@ -33,7 +33,7 @@ LL | | 3
LL | | })
| | ^- help: consider using a semicolon here: `;`
| |______|
- | expected `()`, found struct `Anonymous`
+ | expected `()`, found `Anonymous`
error: aborting due to 2 previous errors
diff --git a/tests/ui/impl-trait/issues/issue-79099.stderr b/tests/ui/impl-trait/issues/issue-79099.stderr
index 362c67daf..580250a62 100644
--- a/tests/ui/impl-trait/issues/issue-79099.stderr
+++ b/tests/ui/impl-trait/issues/issue-79099.stderr
@@ -9,7 +9,7 @@ LL | let f: impl core::future::Future<Output = u8> = async { 1 };
= help: pass `--edition 2021` to `rustc`
= note: for more on editions, read https://doc.rust-lang.org/edition-guide
-error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in variable binding
+error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in variable bindings
--> $DIR/issue-79099.rs:3:16
|
LL | let f: impl core::future::Future<Output = u8> = async { 1 };
diff --git a/tests/ui/impl-trait/issues/issue-83929-impl-trait-in-generic-default.stderr b/tests/ui/impl-trait/issues/issue-83929-impl-trait-in-generic-default.stderr
index e635e554e..656bd0470 100644
--- a/tests/ui/impl-trait/issues/issue-83929-impl-trait-in-generic-default.stderr
+++ b/tests/ui/impl-trait/issues/issue-83929-impl-trait-in-generic-default.stderr
@@ -1,10 +1,10 @@
-error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in type
+error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in generic parameter defaults
--> $DIR/issue-83929-impl-trait-in-generic-default.rs:1:16
|
LL | struct Foo<T = impl Copy>(T);
| ^^^^^^^^^
-error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in type
+error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in generic parameter defaults
--> $DIR/issue-83929-impl-trait-in-generic-default.rs:4:20
|
LL | type Result<T, E = impl std::error::Error> = std::result::Result<T, E>;
diff --git a/tests/ui/impl-trait/issues/issue-84919.stderr b/tests/ui/impl-trait/issues/issue-84919.stderr
index 5abe1bd87..36010fdef 100644
--- a/tests/ui/impl-trait/issues/issue-84919.stderr
+++ b/tests/ui/impl-trait/issues/issue-84919.stderr
@@ -1,4 +1,4 @@
-error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in variable binding
+error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in variable bindings
--> $DIR/issue-84919.rs:5:13
|
LL | let _x: impl Trait = ();
diff --git a/tests/ui/impl-trait/issues/issue-86642.stderr b/tests/ui/impl-trait/issues/issue-86642.stderr
index 0ec118d5b..b6f8a54f3 100644
--- a/tests/ui/impl-trait/issues/issue-86642.stderr
+++ b/tests/ui/impl-trait/issues/issue-86642.stderr
@@ -1,4 +1,4 @@
-error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in type
+error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in const types
--> $DIR/issue-86642.rs:1:11
|
LL | static x: impl Fn(&str) -> Result<&str, ()> = move |source| {
diff --git a/tests/ui/impl-trait/issues/issue-86800.stderr b/tests/ui/impl-trait/issues/issue-86800.stderr
index 6c4aa3567..f3a773837 100644
--- a/tests/ui/impl-trait/issues/issue-86800.stderr
+++ b/tests/ui/impl-trait/issues/issue-86800.stderr
@@ -9,9 +9,7 @@ LL | type TransactionFuture<'__, O> = impl '__ + Future<Output = TransactionResu
stack backtrace:
-error: internal compiler error: unexpected panic
-
-
+error: the compiler unexpectedly panicked. this is a bug.
diff --git a/tests/ui/impl-trait/issues/issue-87295.stderr b/tests/ui/impl-trait/issues/issue-87295.stderr
index 0b043056b..ec59b719c 100644
--- a/tests/ui/impl-trait/issues/issue-87295.stderr
+++ b/tests/ui/impl-trait/issues/issue-87295.stderr
@@ -1,4 +1,4 @@
-error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in variable binding
+error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in variable bindings
--> $DIR/issue-87295.rs:16:31
|
LL | let _do_not_waste: Struct<impl Trait<Output = i32>> = Struct::new(());
diff --git a/tests/ui/impl-trait/multiple-lifetimes/error-handling-2.stderr b/tests/ui/impl-trait/multiple-lifetimes/error-handling-2.stderr
index 908757080..5b0b1cc5e 100644
--- a/tests/ui/impl-trait/multiple-lifetimes/error-handling-2.stderr
+++ b/tests/ui/impl-trait/multiple-lifetimes/error-handling-2.stderr
@@ -1,6 +1,9 @@
error[E0700]: hidden type for `E<'b, 'c>` captures lifetime that does not appear in bounds
--> $DIR/error-handling-2.rs:22:5
|
+LL | type E<'a, 'b> = impl Sized;
+ | ---------- opaque type defined here
+LL |
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
...
diff --git a/tests/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unrelated.stderr b/tests/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unrelated.stderr
index ec49a6179..68ac22a05 100644
--- a/tests/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unrelated.stderr
+++ b/tests/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unrelated.stderr
@@ -2,7 +2,9 @@ error[E0700]: hidden type for `impl Trait<'d, 'e>` captures lifetime that does n
--> $DIR/ordinary-bounds-unrelated.rs:28:33
|
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
+ | -- ------------------ opaque type defined here
+ | |
+ | hidden type `Ordinary<'b>` captures the lifetime `'b` as defined here
...
LL | if condition() { a } else { b }
| ^
diff --git a/tests/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unsuited.stderr b/tests/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unsuited.stderr
index c36f9bc69..493a9e66e 100644
--- a/tests/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unsuited.stderr
+++ b/tests/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unsuited.stderr
@@ -2,7 +2,9 @@ error[E0700]: hidden type for `impl Trait<'a, 'b>` captures lifetime that does n
--> $DIR/ordinary-bounds-unsuited.rs:31:33
|
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
+ | -- ------------------ opaque type defined here
+ | |
+ | hidden type `Ordinary<'b>` captures the lifetime `'b` as defined here
...
LL | if condition() { a } else { b }
| ^
diff --git a/tests/ui/impl-trait/must_outlive_least_region_or_bound.stderr b/tests/ui/impl-trait/must_outlive_least_region_or_bound.stderr
index 9c81791fb..55e3cd950 100644
--- a/tests/ui/impl-trait/must_outlive_least_region_or_bound.stderr
+++ b/tests/ui/impl-trait/must_outlive_least_region_or_bound.stderr
@@ -2,8 +2,9 @@ error[E0700]: hidden type for `impl Copy` captures lifetime that does not appear
--> $DIR/must_outlive_least_region_or_bound.rs:3:35
|
LL | fn elided(x: &i32) -> impl Copy { x }
- | ---- ^
- | |
+ | ---- --------- ^
+ | | |
+ | | opaque type defined here
| hidden type `&i32` captures the anonymous lifetime defined here
|
help: to declare that `impl Copy` captures `'_`, you can add an explicit `'_` lifetime bound
@@ -15,8 +16,9 @@ error[E0700]: hidden type for `impl Copy` captures lifetime that does not appear
--> $DIR/must_outlive_least_region_or_bound.rs:6:44
|
LL | fn explicit<'a>(x: &'a i32) -> impl Copy { x }
- | -- ^
- | |
+ | -- --------- ^
+ | | |
+ | | opaque type defined here
| hidden type `&'a i32` captures the lifetime `'a` as defined here
|
help: to declare that `impl Copy` captures `'a`, you can add an explicit `'a` lifetime bound
@@ -100,7 +102,9 @@ error[E0700]: hidden type for `impl Fn(&'a u32)` captures lifetime that does not
--> $DIR/must_outlive_least_region_or_bound.rs:38:5
|
LL | fn move_lifetime_into_fn<'a, 'b>(x: &'a u32, y: &'b u32) -> impl Fn(&'a u32) {
- | -- hidden type `[closure@$DIR/must_outlive_least_region_or_bound.rs:38:5: 38:13]` captures the lifetime `'b` as defined here
+ | -- ---------------- opaque type defined here
+ | |
+ | hidden type `[closure@$DIR/must_outlive_least_region_or_bound.rs:38:5: 38:13]` captures the lifetime `'b` as defined here
LL | move |_| println!("{}", y)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
diff --git a/tests/ui/impl-trait/nested-return-type2.rs b/tests/ui/impl-trait/nested-return-type2.rs
index cc1f1f4ec..fe883ce6f 100644
--- a/tests/ui/impl-trait/nested-return-type2.rs
+++ b/tests/ui/impl-trait/nested-return-type2.rs
@@ -1,4 +1,7 @@
// check-pass
+// compile-flags: -Zvalidate-mir
+
+// Using -Zvalidate-mir as a regression test for #107346.
trait Duh {}
diff --git a/tests/ui/impl-trait/nested-return-type2.stderr b/tests/ui/impl-trait/nested-return-type2.stderr
index 3aed05ca1..09ad3bd05 100644
--- a/tests/ui/impl-trait/nested-return-type2.stderr
+++ b/tests/ui/impl-trait/nested-return-type2.stderr
@@ -1,5 +1,5 @@
warning: opaque type `impl Trait<Assoc = impl Send>` does not satisfy its associated type bounds
- --> $DIR/nested-return-type2.rs:25:24
+ --> $DIR/nested-return-type2.rs:28:24
|
LL | type Assoc: Duh;
| --- this associated type bound is unsatisfied for `impl Send`
diff --git a/tests/ui/impl-trait/nested-return-type4.stderr b/tests/ui/impl-trait/nested-return-type4.stderr
index e761a60e7..907822ebb 100644
--- a/tests/ui/impl-trait/nested-return-type4.stderr
+++ b/tests/ui/impl-trait/nested-return-type4.stderr
@@ -2,7 +2,9 @@ error[E0700]: hidden type for `impl Future<Output = impl Sized>` captures lifeti
--> $DIR/nested-return-type4.rs:4:5
|
LL | fn test<'s: 's>(s: &'s str) -> impl std::future::Future<Output = impl Sized> {
- | -- hidden type `[async block@$DIR/nested-return-type4.rs:4:5: 4:31]` captures the lifetime `'s` as defined here
+ | -- --------------------------------------------- opaque type defined here
+ | |
+ | hidden type `[async block@$DIR/nested-return-type4.rs:4:5: 4:31]` captures the lifetime `'s` as defined here
LL | async move { let _s = s; }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
diff --git a/tests/ui/impl-trait/nested_impl_trait.stderr b/tests/ui/impl-trait/nested_impl_trait.stderr
index 9a8f5a340..ffe84b8e8 100644
--- a/tests/ui/impl-trait/nested_impl_trait.stderr
+++ b/tests/ui/impl-trait/nested_impl_trait.stderr
@@ -34,7 +34,7 @@ LL | fn bad(x: impl Into<u32>) -> impl Into<impl Debug> { x }
| | nested `impl Trait` here
| outer `impl Trait`
-error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `fn` pointer return
+error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `fn` pointer return types
--> $DIR/nested_impl_trait.rs:10:32
|
LL | fn bad_in_fn_syntax(x: fn() -> impl Into<impl Debug>) {}
diff --git a/tests/ui/impl-trait/no-method-suggested-traits.stderr b/tests/ui/impl-trait/no-method-suggested-traits.stderr
index 548c89d0a..3c2c01dc2 100644
--- a/tests/ui/impl-trait/no-method-suggested-traits.stderr
+++ b/tests/ui/impl-trait/no-method-suggested-traits.stderr
@@ -145,7 +145,7 @@ note: `foo::Bar` defines an item `method2`, perhaps you need to implement it
LL | pub trait Bar {
| ^^^^^^^^^^^^^
-error[E0599]: no method named `method2` found for struct `Foo` in the current scope
+error[E0599]: no method named `method2` found for struct `no_method_suggested_traits::Foo` in the current scope
--> $DIR/no-method-suggested-traits.rs:50:37
|
LL | no_method_suggested_traits::Foo.method2();
@@ -158,7 +158,7 @@ note: `foo::Bar` defines an item `method2`, perhaps you need to implement it
LL | pub trait Bar {
| ^^^^^^^^^^^^^
-error[E0599]: no method named `method2` found for struct `Rc<&mut Box<&Foo>>` in the current scope
+error[E0599]: no method named `method2` found for struct `Rc<&mut Box<&no_method_suggested_traits::Foo>>` in the current scope
--> $DIR/no-method-suggested-traits.rs:52:71
|
LL | std::rc::Rc::new(&mut Box::new(&no_method_suggested_traits::Foo)).method2();
@@ -171,7 +171,7 @@ note: `foo::Bar` defines an item `method2`, perhaps you need to implement it
LL | pub trait Bar {
| ^^^^^^^^^^^^^
-error[E0599]: no method named `method2` found for enum `Bar` in the current scope
+error[E0599]: no method named `method2` found for enum `no_method_suggested_traits::Bar` in the current scope
--> $DIR/no-method-suggested-traits.rs:54:40
|
LL | no_method_suggested_traits::Bar::X.method2();
@@ -184,7 +184,7 @@ note: `foo::Bar` defines an item `method2`, perhaps you need to implement it
LL | pub trait Bar {
| ^^^^^^^^^^^^^
-error[E0599]: no method named `method2` found for struct `Rc<&mut Box<&Bar>>` in the current scope
+error[E0599]: no method named `method2` found for struct `Rc<&mut Box<&no_method_suggested_traits::Bar>>` in the current scope
--> $DIR/no-method-suggested-traits.rs:56:74
|
LL | std::rc::Rc::new(&mut Box::new(&no_method_suggested_traits::Bar::X)).method2();
@@ -255,25 +255,25 @@ error[E0599]: no method named `method3` found for struct `Rc<&mut Box<&usize>>`
LL | std::rc::Rc::new(&mut Box::new(&1_usize)).method3();
| ^^^^^^^ method not found in `Rc<&mut Box<&usize>>`
-error[E0599]: no method named `method3` found for struct `Foo` in the current scope
+error[E0599]: no method named `method3` found for struct `no_method_suggested_traits::Foo` in the current scope
--> $DIR/no-method-suggested-traits.rs:71:37
|
LL | no_method_suggested_traits::Foo.method3();
| ^^^^^^^ method not found in `Foo`
-error[E0599]: no method named `method3` found for struct `Rc<&mut Box<&Foo>>` in the current scope
+error[E0599]: no method named `method3` found for struct `Rc<&mut Box<&no_method_suggested_traits::Foo>>` in the current scope
--> $DIR/no-method-suggested-traits.rs:72:71
|
LL | std::rc::Rc::new(&mut Box::new(&no_method_suggested_traits::Foo)).method3();
| ^^^^^^^ method not found in `Rc<&mut Box<&Foo>>`
-error[E0599]: no method named `method3` found for enum `Bar` in the current scope
+error[E0599]: no method named `method3` found for enum `no_method_suggested_traits::Bar` in the current scope
--> $DIR/no-method-suggested-traits.rs:74:40
|
LL | no_method_suggested_traits::Bar::X.method3();
| ^^^^^^^ method not found in `Bar`
-error[E0599]: no method named `method3` found for struct `Rc<&mut Box<&Bar>>` in the current scope
+error[E0599]: no method named `method3` found for struct `Rc<&mut Box<&no_method_suggested_traits::Bar>>` in the current scope
--> $DIR/no-method-suggested-traits.rs:75:74
|
LL | std::rc::Rc::new(&mut Box::new(&no_method_suggested_traits::Bar::X)).method3();
diff --git a/tests/ui/impl-trait/normalize-tait-in-const.rs b/tests/ui/impl-trait/normalize-tait-in-const.rs
index 020bcbb83..d2e34c00b 100644
--- a/tests/ui/impl-trait/normalize-tait-in-const.rs
+++ b/tests/ui/impl-trait/normalize-tait-in-const.rs
@@ -2,6 +2,7 @@
// failure-status: 101
// normalize-stderr-test "note: .*\n\n" -> ""
// normalize-stderr-test "thread 'rustc' panicked.*\n" -> ""
+// normalize-stderr-test "(error: internal compiler error: [^:]+):\d+:\d+: " -> "$1:LL:CC: "
// rustc-env:RUST_BACKTRACE=0
#![feature(type_alias_impl_trait)]
diff --git a/tests/ui/impl-trait/normalize-tait-in-const.stderr b/tests/ui/impl-trait/normalize-tait-in-const.stderr
index b9fc8726f..84b009187 100644
--- a/tests/ui/impl-trait/normalize-tait-in-const.stderr
+++ b/tests/ui/impl-trait/normalize-tait-in-const.stderr
@@ -1,4 +1,4 @@
-error: internal compiler error: compiler/rustc_middle/src/ty/normalize_erasing_regions.rs:198:90: Failed to normalize <for<'a, 'b> fn(&'a Alias<'b>) {foo} as std::ops::FnOnce<(&&S,)>>::Output, maybe try to call `try_normalize_erasing_regions` instead
+error: internal compiler error: compiler/rustc_middle/src/ty/normalize_erasing_regions.rs:LL:CC: Failed to normalize <for<'a, 'b> fn(&'a Alias<'b>) {foo} as std::ops::FnOnce<(&&S,)>>::Output, maybe try to call `try_normalize_erasing_regions` instead
query stack during panic:
#0 [eval_to_allocation_raw] const-evaluating + checking `BAR`
diff --git a/tests/ui/impl-trait/object-unsafe-trait-in-return-position-impl-trait.stderr b/tests/ui/impl-trait/object-unsafe-trait-in-return-position-impl-trait.stderr
index d6f5a1ac2..e5147bcea 100644
--- a/tests/ui/impl-trait/object-unsafe-trait-in-return-position-impl-trait.stderr
+++ b/tests/ui/impl-trait/object-unsafe-trait-in-return-position-impl-trait.stderr
@@ -5,7 +5,7 @@ LL | fn can() -> impl NotObjectSafe {
| ------------------ expected `A` because of return type
...
LL | B
- | ^ expected struct `A`, found struct `B`
+ | ^ expected `A`, found `B`
error[E0308]: mismatched types
--> $DIR/object-unsafe-trait-in-return-position-impl-trait.rs:43:5
@@ -14,7 +14,7 @@ LL | fn cat() -> impl ObjectSafe {
| --------------- expected `A` because of return type
...
LL | B
- | ^ expected struct `A`, found struct `B`
+ | ^ expected `A`, found `B`
error: aborting due to 2 previous errors
diff --git a/tests/ui/impl-trait/recursive-impl-trait-type-indirect.stderr b/tests/ui/impl-trait/recursive-impl-trait-type-indirect.drop_tracking.stderr
index ebb231ae1..43118ae38 100644
--- a/tests/ui/impl-trait/recursive-impl-trait-type-indirect.stderr
+++ b/tests/ui/impl-trait/recursive-impl-trait-type-indirect.drop_tracking.stderr
@@ -1,5 +1,5 @@
error[E0720]: cannot resolve opaque type
- --> $DIR/recursive-impl-trait-type-indirect.rs:7:22
+ --> $DIR/recursive-impl-trait-type-indirect.rs:11:22
|
LL | fn option(i: i32) -> impl Sized {
| ^^^^^^^^^^ recursive opaque type
@@ -10,7 +10,7 @@ LL | if i < 0 { None } else { Some((option(i - 1), i)) }
| returning here with type `Option<(impl Sized, i32)>`
error[E0720]: cannot resolve opaque type
- --> $DIR/recursive-impl-trait-type-indirect.rs:12:15
+ --> $DIR/recursive-impl-trait-type-indirect.rs:16:15
|
LL | fn tuple() -> impl Sized {
| ^^^^^^^^^^ recursive opaque type
@@ -19,7 +19,7 @@ LL | (tuple(),)
| ---------- returning here with type `(impl Sized,)`
error[E0720]: cannot resolve opaque type
- --> $DIR/recursive-impl-trait-type-indirect.rs:17:15
+ --> $DIR/recursive-impl-trait-type-indirect.rs:21:15
|
LL | fn array() -> impl Sized {
| ^^^^^^^^^^ recursive opaque type
@@ -28,7 +28,7 @@ LL | [array()]
| --------- returning here with type `[impl Sized; 1]`
error[E0720]: cannot resolve opaque type
- --> $DIR/recursive-impl-trait-type-indirect.rs:22:13
+ --> $DIR/recursive-impl-trait-type-indirect.rs:26:13
|
LL | fn ptr() -> impl Sized {
| ^^^^^^^^^^ recursive opaque type
@@ -37,7 +37,7 @@ LL | &ptr() as *const _
| ------------------ returning here with type `*const impl Sized`
error[E0720]: cannot resolve opaque type
- --> $DIR/recursive-impl-trait-type-indirect.rs:27:16
+ --> $DIR/recursive-impl-trait-type-indirect.rs:31:16
|
LL | fn fn_ptr() -> impl Sized {
| ^^^^^^^^^^ recursive opaque type
@@ -46,7 +46,7 @@ LL | fn_ptr as fn() -> _
| ------------------- returning here with type `fn() -> impl Sized`
error[E0720]: cannot resolve opaque type
- --> $DIR/recursive-impl-trait-type-indirect.rs:32:25
+ --> $DIR/recursive-impl-trait-type-indirect.rs:36:25
|
LL | fn closure_capture() -> impl Sized {
| ^^^^^^^^^^ recursive opaque type
@@ -55,10 +55,10 @@ LL | / move || {
LL | | x;
| | - closure captures itself here
LL | | }
- | |_____- returning here with type `[closure@$DIR/recursive-impl-trait-type-indirect.rs:35:5: 35:12]`
+ | |_____- returning here with type `[closure@$DIR/recursive-impl-trait-type-indirect.rs:39:5: 39:12]`
error[E0720]: cannot resolve opaque type
- --> $DIR/recursive-impl-trait-type-indirect.rs:40:29
+ --> $DIR/recursive-impl-trait-type-indirect.rs:44:29
|
LL | fn closure_ref_capture() -> impl Sized {
| ^^^^^^^^^^ recursive opaque type
@@ -67,28 +67,28 @@ LL | / move || {
LL | | &x;
| | - closure captures itself here
LL | | }
- | |_____- returning here with type `[closure@$DIR/recursive-impl-trait-type-indirect.rs:43:5: 43:12]`
+ | |_____- returning here with type `[closure@$DIR/recursive-impl-trait-type-indirect.rs:47:5: 47:12]`
error[E0720]: cannot resolve opaque type
- --> $DIR/recursive-impl-trait-type-indirect.rs:48:21
+ --> $DIR/recursive-impl-trait-type-indirect.rs:52:21
|
LL | fn closure_sig() -> impl Sized {
| ^^^^^^^^^^ recursive opaque type
LL |
LL | || closure_sig()
- | ---------------- returning here with type `[closure@$DIR/recursive-impl-trait-type-indirect.rs:50:5: 50:7]`
+ | ---------------- returning here with type `[closure@$DIR/recursive-impl-trait-type-indirect.rs:54:5: 54:7]`
error[E0720]: cannot resolve opaque type
- --> $DIR/recursive-impl-trait-type-indirect.rs:53:23
+ --> $DIR/recursive-impl-trait-type-indirect.rs:57:23
|
LL | fn generator_sig() -> impl Sized {
| ^^^^^^^^^^ recursive opaque type
LL |
LL | || generator_sig()
- | ------------------ returning here with type `[closure@$DIR/recursive-impl-trait-type-indirect.rs:55:5: 55:7]`
+ | ------------------ returning here with type `[closure@$DIR/recursive-impl-trait-type-indirect.rs:59:5: 59:7]`
error[E0720]: cannot resolve opaque type
- --> $DIR/recursive-impl-trait-type-indirect.rs:58:27
+ --> $DIR/recursive-impl-trait-type-indirect.rs:62:27
|
LL | fn generator_capture() -> impl Sized {
| ^^^^^^^^^^ recursive opaque type
@@ -98,10 +98,10 @@ LL | | yield;
LL | | x;
| | - generator captures itself here
LL | | }
- | |_____- returning here with type `[generator@$DIR/recursive-impl-trait-type-indirect.rs:61:5: 61:12]`
+ | |_____- returning here with type `[generator@$DIR/recursive-impl-trait-type-indirect.rs:65:5: 65:12]`
error[E0720]: cannot resolve opaque type
- --> $DIR/recursive-impl-trait-type-indirect.rs:67:35
+ --> $DIR/recursive-impl-trait-type-indirect.rs:71:35
|
LL | fn substs_change<T: 'static>() -> impl Sized {
| ^^^^^^^^^^ recursive opaque type
@@ -110,7 +110,7 @@ LL | (substs_change::<&T>(),)
| ------------------------ returning here with type `(impl Sized,)`
error[E0720]: cannot resolve opaque type
- --> $DIR/recursive-impl-trait-type-indirect.rs:72:24
+ --> $DIR/recursive-impl-trait-type-indirect.rs:76:24
|
LL | fn generator_hold() -> impl Sized {
| ^^^^^^^^^^ recursive opaque type
@@ -121,10 +121,10 @@ LL | | let x = generator_hold();
LL | | yield;
LL | | x;
LL | | }
- | |_____- returning here with type `[generator@$DIR/recursive-impl-trait-type-indirect.rs:74:5: 74:12]`
+ | |_____- returning here with type `[generator@$DIR/recursive-impl-trait-type-indirect.rs:78:5: 78:12]`
error[E0720]: cannot resolve opaque type
- --> $DIR/recursive-impl-trait-type-indirect.rs:86:26
+ --> $DIR/recursive-impl-trait-type-indirect.rs:90:26
|
LL | fn mutual_recursion() -> impl Sync {
| ^^^^^^^^^ recursive opaque type
@@ -136,7 +136,7 @@ LL | fn mutual_recursion_b() -> impl Sized {
| ---------- returning this opaque type `impl Sized`
error[E0720]: cannot resolve opaque type
- --> $DIR/recursive-impl-trait-type-indirect.rs:91:28
+ --> $DIR/recursive-impl-trait-type-indirect.rs:95:28
|
LL | fn mutual_recursion() -> impl Sync {
| --------- returning this opaque type `impl Sync`
diff --git a/tests/ui/impl-trait/recursive-impl-trait-type-indirect.drop_tracking_mir.stderr b/tests/ui/impl-trait/recursive-impl-trait-type-indirect.drop_tracking_mir.stderr
new file mode 100644
index 000000000..662c74bcd
--- /dev/null
+++ b/tests/ui/impl-trait/recursive-impl-trait-type-indirect.drop_tracking_mir.stderr
@@ -0,0 +1,144 @@
+error[E0720]: cannot resolve opaque type
+ --> $DIR/recursive-impl-trait-type-indirect.rs:11:22
+ |
+LL | fn option(i: i32) -> impl Sized {
+ | ^^^^^^^^^^ recursive opaque type
+LL |
+LL | if i < 0 { None } else { Some((option(i - 1), i)) }
+ | ---- ------------------------ returning here with type `Option<(impl Sized, i32)>`
+ | |
+ | returning here with type `Option<(impl Sized, i32)>`
+
+error[E0720]: cannot resolve opaque type
+ --> $DIR/recursive-impl-trait-type-indirect.rs:16:15
+ |
+LL | fn tuple() -> impl Sized {
+ | ^^^^^^^^^^ recursive opaque type
+LL |
+LL | (tuple(),)
+ | ---------- returning here with type `(impl Sized,)`
+
+error[E0720]: cannot resolve opaque type
+ --> $DIR/recursive-impl-trait-type-indirect.rs:21:15
+ |
+LL | fn array() -> impl Sized {
+ | ^^^^^^^^^^ recursive opaque type
+LL |
+LL | [array()]
+ | --------- returning here with type `[impl Sized; 1]`
+
+error[E0720]: cannot resolve opaque type
+ --> $DIR/recursive-impl-trait-type-indirect.rs:26:13
+ |
+LL | fn ptr() -> impl Sized {
+ | ^^^^^^^^^^ recursive opaque type
+LL |
+LL | &ptr() as *const _
+ | ------------------ returning here with type `*const impl Sized`
+
+error[E0720]: cannot resolve opaque type
+ --> $DIR/recursive-impl-trait-type-indirect.rs:31:16
+ |
+LL | fn fn_ptr() -> impl Sized {
+ | ^^^^^^^^^^ recursive opaque type
+LL |
+LL | fn_ptr as fn() -> _
+ | ------------------- returning here with type `fn() -> impl Sized`
+
+error[E0720]: cannot resolve opaque type
+ --> $DIR/recursive-impl-trait-type-indirect.rs:36:25
+ |
+LL | fn closure_capture() -> impl Sized {
+ | ^^^^^^^^^^ recursive opaque type
+...
+LL | / move || {
+LL | | x;
+ | | - closure captures itself here
+LL | | }
+ | |_____- returning here with type `[closure@$DIR/recursive-impl-trait-type-indirect.rs:39:5: 39:12]`
+
+error[E0720]: cannot resolve opaque type
+ --> $DIR/recursive-impl-trait-type-indirect.rs:44:29
+ |
+LL | fn closure_ref_capture() -> impl Sized {
+ | ^^^^^^^^^^ recursive opaque type
+...
+LL | / move || {
+LL | | &x;
+ | | - closure captures itself here
+LL | | }
+ | |_____- returning here with type `[closure@$DIR/recursive-impl-trait-type-indirect.rs:47:5: 47:12]`
+
+error[E0720]: cannot resolve opaque type
+ --> $DIR/recursive-impl-trait-type-indirect.rs:52:21
+ |
+LL | fn closure_sig() -> impl Sized {
+ | ^^^^^^^^^^ recursive opaque type
+LL |
+LL | || closure_sig()
+ | ---------------- returning here with type `[closure@$DIR/recursive-impl-trait-type-indirect.rs:54:5: 54:7]`
+
+error[E0720]: cannot resolve opaque type
+ --> $DIR/recursive-impl-trait-type-indirect.rs:57:23
+ |
+LL | fn generator_sig() -> impl Sized {
+ | ^^^^^^^^^^ recursive opaque type
+LL |
+LL | || generator_sig()
+ | ------------------ returning here with type `[closure@$DIR/recursive-impl-trait-type-indirect.rs:59:5: 59:7]`
+
+error[E0720]: cannot resolve opaque type
+ --> $DIR/recursive-impl-trait-type-indirect.rs:62:27
+ |
+LL | fn generator_capture() -> impl Sized {
+ | ^^^^^^^^^^ recursive opaque type
+...
+LL | / move || {
+LL | | yield;
+LL | | x;
+ | | - generator captures itself here
+LL | | }
+ | |_____- returning here with type `[generator@$DIR/recursive-impl-trait-type-indirect.rs:65:5: 65:12]`
+
+error[E0720]: cannot resolve opaque type
+ --> $DIR/recursive-impl-trait-type-indirect.rs:71:35
+ |
+LL | fn substs_change<T: 'static>() -> impl Sized {
+ | ^^^^^^^^^^ recursive opaque type
+LL |
+LL | (substs_change::<&T>(),)
+ | ------------------------ returning here with type `(impl Sized,)`
+
+error[E0720]: cannot resolve opaque type
+ --> $DIR/recursive-impl-trait-type-indirect.rs:76:24
+ |
+LL | fn generator_hold() -> impl Sized {
+ | ^^^^^^^^^^ recursive opaque type
+
+error[E0720]: cannot resolve opaque type
+ --> $DIR/recursive-impl-trait-type-indirect.rs:90:26
+ |
+LL | fn mutual_recursion() -> impl Sync {
+ | ^^^^^^^^^ recursive opaque type
+LL |
+LL | mutual_recursion_b()
+ | -------------------- returning here with type `impl Sized`
+...
+LL | fn mutual_recursion_b() -> impl Sized {
+ | ---------- returning this opaque type `impl Sized`
+
+error[E0720]: cannot resolve opaque type
+ --> $DIR/recursive-impl-trait-type-indirect.rs:95:28
+ |
+LL | fn mutual_recursion() -> impl Sync {
+ | --------- returning this opaque type `impl Sync`
+...
+LL | fn mutual_recursion_b() -> impl Sized {
+ | ^^^^^^^^^^ recursive opaque type
+LL |
+LL | mutual_recursion()
+ | ------------------ returning here with type `impl Sync`
+
+error: aborting due to 14 previous errors
+
+For more information about this error, try `rustc --explain E0720`.
diff --git a/tests/ui/impl-trait/recursive-impl-trait-type-indirect.no_drop_tracking.stderr b/tests/ui/impl-trait/recursive-impl-trait-type-indirect.no_drop_tracking.stderr
new file mode 100644
index 000000000..43118ae38
--- /dev/null
+++ b/tests/ui/impl-trait/recursive-impl-trait-type-indirect.no_drop_tracking.stderr
@@ -0,0 +1,152 @@
+error[E0720]: cannot resolve opaque type
+ --> $DIR/recursive-impl-trait-type-indirect.rs:11:22
+ |
+LL | fn option(i: i32) -> impl Sized {
+ | ^^^^^^^^^^ recursive opaque type
+LL |
+LL | if i < 0 { None } else { Some((option(i - 1), i)) }
+ | ---- ------------------------ returning here with type `Option<(impl Sized, i32)>`
+ | |
+ | returning here with type `Option<(impl Sized, i32)>`
+
+error[E0720]: cannot resolve opaque type
+ --> $DIR/recursive-impl-trait-type-indirect.rs:16:15
+ |
+LL | fn tuple() -> impl Sized {
+ | ^^^^^^^^^^ recursive opaque type
+LL |
+LL | (tuple(),)
+ | ---------- returning here with type `(impl Sized,)`
+
+error[E0720]: cannot resolve opaque type
+ --> $DIR/recursive-impl-trait-type-indirect.rs:21:15
+ |
+LL | fn array() -> impl Sized {
+ | ^^^^^^^^^^ recursive opaque type
+LL |
+LL | [array()]
+ | --------- returning here with type `[impl Sized; 1]`
+
+error[E0720]: cannot resolve opaque type
+ --> $DIR/recursive-impl-trait-type-indirect.rs:26:13
+ |
+LL | fn ptr() -> impl Sized {
+ | ^^^^^^^^^^ recursive opaque type
+LL |
+LL | &ptr() as *const _
+ | ------------------ returning here with type `*const impl Sized`
+
+error[E0720]: cannot resolve opaque type
+ --> $DIR/recursive-impl-trait-type-indirect.rs:31:16
+ |
+LL | fn fn_ptr() -> impl Sized {
+ | ^^^^^^^^^^ recursive opaque type
+LL |
+LL | fn_ptr as fn() -> _
+ | ------------------- returning here with type `fn() -> impl Sized`
+
+error[E0720]: cannot resolve opaque type
+ --> $DIR/recursive-impl-trait-type-indirect.rs:36:25
+ |
+LL | fn closure_capture() -> impl Sized {
+ | ^^^^^^^^^^ recursive opaque type
+...
+LL | / move || {
+LL | | x;
+ | | - closure captures itself here
+LL | | }
+ | |_____- returning here with type `[closure@$DIR/recursive-impl-trait-type-indirect.rs:39:5: 39:12]`
+
+error[E0720]: cannot resolve opaque type
+ --> $DIR/recursive-impl-trait-type-indirect.rs:44:29
+ |
+LL | fn closure_ref_capture() -> impl Sized {
+ | ^^^^^^^^^^ recursive opaque type
+...
+LL | / move || {
+LL | | &x;
+ | | - closure captures itself here
+LL | | }
+ | |_____- returning here with type `[closure@$DIR/recursive-impl-trait-type-indirect.rs:47:5: 47:12]`
+
+error[E0720]: cannot resolve opaque type
+ --> $DIR/recursive-impl-trait-type-indirect.rs:52:21
+ |
+LL | fn closure_sig() -> impl Sized {
+ | ^^^^^^^^^^ recursive opaque type
+LL |
+LL | || closure_sig()
+ | ---------------- returning here with type `[closure@$DIR/recursive-impl-trait-type-indirect.rs:54:5: 54:7]`
+
+error[E0720]: cannot resolve opaque type
+ --> $DIR/recursive-impl-trait-type-indirect.rs:57:23
+ |
+LL | fn generator_sig() -> impl Sized {
+ | ^^^^^^^^^^ recursive opaque type
+LL |
+LL | || generator_sig()
+ | ------------------ returning here with type `[closure@$DIR/recursive-impl-trait-type-indirect.rs:59:5: 59:7]`
+
+error[E0720]: cannot resolve opaque type
+ --> $DIR/recursive-impl-trait-type-indirect.rs:62:27
+ |
+LL | fn generator_capture() -> impl Sized {
+ | ^^^^^^^^^^ recursive opaque type
+...
+LL | / move || {
+LL | | yield;
+LL | | x;
+ | | - generator captures itself here
+LL | | }
+ | |_____- returning here with type `[generator@$DIR/recursive-impl-trait-type-indirect.rs:65:5: 65:12]`
+
+error[E0720]: cannot resolve opaque type
+ --> $DIR/recursive-impl-trait-type-indirect.rs:71:35
+ |
+LL | fn substs_change<T: 'static>() -> impl Sized {
+ | ^^^^^^^^^^ recursive opaque type
+LL |
+LL | (substs_change::<&T>(),)
+ | ------------------------ returning here with type `(impl Sized,)`
+
+error[E0720]: cannot resolve opaque type
+ --> $DIR/recursive-impl-trait-type-indirect.rs:76:24
+ |
+LL | fn generator_hold() -> impl Sized {
+ | ^^^^^^^^^^ recursive opaque type
+LL |
+LL | / move || {
+LL | | let x = generator_hold();
+ | | - generator captures itself here
+LL | | yield;
+LL | | x;
+LL | | }
+ | |_____- returning here with type `[generator@$DIR/recursive-impl-trait-type-indirect.rs:78:5: 78:12]`
+
+error[E0720]: cannot resolve opaque type
+ --> $DIR/recursive-impl-trait-type-indirect.rs:90:26
+ |
+LL | fn mutual_recursion() -> impl Sync {
+ | ^^^^^^^^^ recursive opaque type
+LL |
+LL | mutual_recursion_b()
+ | -------------------- returning here with type `impl Sized`
+...
+LL | fn mutual_recursion_b() -> impl Sized {
+ | ---------- returning this opaque type `impl Sized`
+
+error[E0720]: cannot resolve opaque type
+ --> $DIR/recursive-impl-trait-type-indirect.rs:95:28
+ |
+LL | fn mutual_recursion() -> impl Sync {
+ | --------- returning this opaque type `impl Sync`
+...
+LL | fn mutual_recursion_b() -> impl Sized {
+ | ^^^^^^^^^^ recursive opaque type
+LL |
+LL | mutual_recursion()
+ | ------------------ returning here with type `impl Sync`
+
+error: aborting due to 14 previous errors
+
+For more information about this error, try `rustc --explain E0720`.
diff --git a/tests/ui/impl-trait/recursive-impl-trait-type-indirect.rs b/tests/ui/impl-trait/recursive-impl-trait-type-indirect.rs
index ffc0cd9d1..630372e13 100644
--- a/tests/ui/impl-trait/recursive-impl-trait-type-indirect.rs
+++ b/tests/ui/impl-trait/recursive-impl-trait-type-indirect.rs
@@ -1,3 +1,7 @@
+// revisions: no_drop_tracking drop_tracking drop_tracking_mir
+// [drop_tracking] compile-flags: -Zdrop-tracking
+// [drop_tracking_mir] compile-flags: -Zdrop-tracking-mir
+
// Test that impl trait does not allow creating recursive types that are
// otherwise forbidden.
diff --git a/tests/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle.stderr b/tests/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle.stderr
index c7c6ca440..f7aff4195 100644
--- a/tests/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle.stderr
+++ b/tests/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle.stderr
@@ -15,7 +15,7 @@ LL | type Foo = impl PartialEq<(Foo, i32)>;
LL | fn eq(&self, _other: &(Foo, i32)) -> bool {
| ^^^^^^^^^^^
| |
- | expected struct `Bar`, found opaque type
+ | expected `a::Bar`, found opaque type
| help: change the parameter type to match the trait: `&(a::Bar, i32)`
|
= note: expected signature `fn(&a::Bar, &(a::Bar, i32)) -> _`
@@ -38,7 +38,7 @@ LL | type Foo = impl PartialEq<(Foo, i32)>;
LL | fn eq(&self, _other: &(Bar, i32)) -> bool {
| ^^^^^^^^^^^
| |
- | expected opaque type, found struct `Bar`
+ | expected opaque type, found `b::Bar`
| help: change the parameter type to match the trait: `&(b::Foo, i32)`
|
= note: expected signature `fn(&b::Bar, &(b::Foo, i32)) -> _`
diff --git a/tests/ui/impl-trait/region-escape-via-bound.stderr b/tests/ui/impl-trait/region-escape-via-bound.stderr
index 44a790cb1..e4556bc21 100644
--- a/tests/ui/impl-trait/region-escape-via-bound.stderr
+++ b/tests/ui/impl-trait/region-escape-via-bound.stderr
@@ -2,7 +2,9 @@ error[E0700]: hidden type for `impl Trait<'y>` captures lifetime that does not a
--> $DIR/region-escape-via-bound.rs:17:5
|
LL | fn foo<'x, 'y>(x: Cell<&'x u32>) -> impl Trait<'y>
- | -- hidden type `Cell<&'x u32>` captures the lifetime `'x` as defined here
+ | -- -------------- opaque type defined here
+ | |
+ | hidden type `Cell<&'x u32>` captures the lifetime `'x` as defined here
...
LL | x
| ^
diff --git a/tests/ui/impl-trait/static-return-lifetime-infered.stderr b/tests/ui/impl-trait/static-return-lifetime-infered.stderr
index c451f8e37..488cb821c 100644
--- a/tests/ui/impl-trait/static-return-lifetime-infered.stderr
+++ b/tests/ui/impl-trait/static-return-lifetime-infered.stderr
@@ -2,7 +2,9 @@ error[E0700]: hidden type for `impl Iterator<Item = u32>` captures lifetime that
--> $DIR/static-return-lifetime-infered.rs:7:9
|
LL | fn iter_values_anon(&self) -> impl Iterator<Item=u32> {
- | ----- hidden type `Map<std::slice::Iter<'_, (u32, u32)>, [closure@$DIR/static-return-lifetime-infered.rs:7:27: 7:30]>` captures the anonymous lifetime defined here
+ | ----- ----------------------- opaque type defined here
+ | |
+ | hidden type `Map<std::slice::Iter<'_, (u32, u32)>, [closure@$DIR/static-return-lifetime-infered.rs:7:27: 7:30]>` captures the anonymous lifetime defined here
LL | self.x.iter().map(|a| a.0)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
@@ -15,7 +17,9 @@ error[E0700]: hidden type for `impl Iterator<Item = u32>` captures lifetime that
--> $DIR/static-return-lifetime-infered.rs:11:9
|
LL | fn iter_values<'a>(&'a self) -> impl Iterator<Item=u32> {
- | -- hidden type `Map<std::slice::Iter<'a, (u32, u32)>, [closure@$DIR/static-return-lifetime-infered.rs:11:27: 11:30]>` captures the lifetime `'a` as defined here
+ | -- ----------------------- opaque type defined here
+ | |
+ | hidden type `Map<std::slice::Iter<'a, (u32, u32)>, [closure@$DIR/static-return-lifetime-infered.rs:11:27: 11:30]>` captures the lifetime `'a` as defined here
LL | self.x.iter().map(|a| a.0)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
diff --git a/tests/ui/impl-trait/universal-mismatched-type.stderr b/tests/ui/impl-trait/universal-mismatched-type.stderr
index 817c573c0..a56e542d8 100644
--- a/tests/ui/impl-trait/universal-mismatched-type.stderr
+++ b/tests/ui/impl-trait/universal-mismatched-type.stderr
@@ -6,7 +6,7 @@ LL | fn foo(x: impl Debug) -> String {
| |
| this type parameter
LL | x
- | ^ expected struct `String`, found type parameter `impl Debug`
+ | ^ expected `String`, found type parameter `impl Debug`
|
= note: expected struct `String`
found type parameter `impl Debug`
diff --git a/tests/ui/impl-trait/where-allowed.stderr b/tests/ui/impl-trait/where-allowed.stderr
index 3ad0a9f9d..1cae3f77c 100644
--- a/tests/ui/impl-trait/where-allowed.stderr
+++ b/tests/ui/impl-trait/where-allowed.stderr
@@ -43,109 +43,109 @@ LL | type InReturnInTypeAlias<R> = fn() -> impl Debug;
= note: see issue #63063 <https://github.com/rust-lang/rust/issues/63063> for more information
= help: add `#![feature(type_alias_impl_trait)]` to the crate attributes to enable
-error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `fn` pointer param
+error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `fn` pointer params
--> $DIR/where-allowed.rs:16:40
|
LL | fn in_fn_parameter_in_parameters(_: fn(impl Debug)) { panic!() }
| ^^^^^^^^^^
-error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `fn` pointer return
+error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `fn` pointer return types
--> $DIR/where-allowed.rs:20:42
|
LL | fn in_fn_return_in_parameters(_: fn() -> impl Debug) { panic!() }
| ^^^^^^^^^^
-error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `fn` pointer param
+error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `fn` pointer params
--> $DIR/where-allowed.rs:24:38
|
LL | fn in_fn_parameter_in_return() -> fn(impl Debug) { panic!() }
| ^^^^^^^^^^
-error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `fn` pointer return
+error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `fn` pointer return types
--> $DIR/where-allowed.rs:28:40
|
LL | fn in_fn_return_in_return() -> fn() -> impl Debug { panic!() }
| ^^^^^^^^^^
-error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `Fn` trait param
+error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `Fn` trait params
--> $DIR/where-allowed.rs:32:49
|
LL | fn in_dyn_Fn_parameter_in_parameters(_: &dyn Fn(impl Debug)) { panic!() }
| ^^^^^^^^^^
-error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `Fn` trait return
+error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `Fn` trait return types
--> $DIR/where-allowed.rs:36:51
|
LL | fn in_dyn_Fn_return_in_parameters(_: &dyn Fn() -> impl Debug) { panic!() }
| ^^^^^^^^^^
-error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `Fn` trait param
+error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `Fn` trait params
--> $DIR/where-allowed.rs:40:55
|
LL | fn in_dyn_Fn_parameter_in_return() -> &'static dyn Fn(impl Debug) { panic!() }
| ^^^^^^^^^^
-error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `Fn` trait param
+error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `Fn` trait params
--> $DIR/where-allowed.rs:47:51
|
LL | fn in_impl_Fn_parameter_in_parameters(_: &impl Fn(impl Debug)) { panic!() }
| ^^^^^^^^^^
-error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `Fn` trait return
+error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `Fn` trait return types
--> $DIR/where-allowed.rs:52:53
|
LL | fn in_impl_Fn_return_in_parameters(_: &impl Fn() -> impl Debug) { panic!() }
| ^^^^^^^^^^
-error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `Fn` trait param
+error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `Fn` trait params
--> $DIR/where-allowed.rs:56:57
|
LL | fn in_impl_Fn_parameter_in_return() -> &'static impl Fn(impl Debug) { panic!() }
| ^^^^^^^^^^
-error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `Fn` trait param
+error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `Fn` trait params
--> $DIR/where-allowed.rs:64:38
|
LL | fn in_Fn_parameter_in_generics<F: Fn(impl Debug)> (_: F) { panic!() }
| ^^^^^^^^^^
-error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `Fn` trait return
+error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `Fn` trait return types
--> $DIR/where-allowed.rs:68:40
|
LL | fn in_Fn_return_in_generics<F: Fn() -> impl Debug> (_: F) { panic!() }
| ^^^^^^^^^^
-error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in type
+error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in field types
--> $DIR/where-allowed.rs:81:32
|
LL | struct InBraceStructField { x: impl Debug }
| ^^^^^^^^^^
-error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in path
+error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in field types
--> $DIR/where-allowed.rs:85:41
|
LL | struct InAdtInBraceStructField { x: Vec<impl Debug> }
| ^^^^^^^^^^
-error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in type
+error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in field types
--> $DIR/where-allowed.rs:89:27
|
LL | struct InTupleStructField(impl Debug);
| ^^^^^^^^^^
-error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in type
+error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in field types
--> $DIR/where-allowed.rs:94:25
|
LL | InBraceVariant { x: impl Debug },
| ^^^^^^^^^^
-error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in type
+error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in field types
--> $DIR/where-allowed.rs:96:20
|
LL | InTupleVariant(impl Debug),
| ^^^^^^^^^^
-error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in trait method return
+error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in trait method return types
--> $DIR/where-allowed.rs:107:23
|
LL | fn in_return() -> impl Debug;
@@ -154,7 +154,7 @@ LL | fn in_return() -> impl Debug;
= note: see issue #91611 <https://github.com/rust-lang/rust/issues/91611> for more information
= help: add `#![feature(return_position_impl_trait_in_trait)]` to the crate attributes to enable
-error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `impl` method return
+error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `impl` method return types
--> $DIR/where-allowed.rs:124:34
|
LL | fn in_trait_impl_return() -> impl Debug { () }
@@ -163,121 +163,121 @@ LL | fn in_trait_impl_return() -> impl Debug { () }
= note: see issue #91611 <https://github.com/rust-lang/rust/issues/91611> for more information
= help: add `#![feature(return_position_impl_trait_in_trait)]` to the crate attributes to enable
-error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `extern fn` param
+error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `extern fn` params
--> $DIR/where-allowed.rs:137:33
|
LL | fn in_foreign_parameters(_: impl Debug);
| ^^^^^^^^^^
-error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `extern fn` return
+error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `extern fn` return types
--> $DIR/where-allowed.rs:140:31
|
LL | fn in_foreign_return() -> impl Debug;
| ^^^^^^^^^^
-error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `fn` pointer return
+error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `fn` pointer return types
--> $DIR/where-allowed.rs:156:39
|
LL | type InReturnInTypeAlias<R> = fn() -> impl Debug;
| ^^^^^^^^^^
-error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in trait
+error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in traits
--> $DIR/where-allowed.rs:161:16
|
LL | impl PartialEq<impl Debug> for () {
| ^^^^^^^^^^
-error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in type
+error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in impl headers
--> $DIR/where-allowed.rs:166:24
|
LL | impl PartialEq<()> for impl Debug {
| ^^^^^^^^^^
-error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in type
+error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in impl headers
--> $DIR/where-allowed.rs:171:6
|
LL | impl impl Debug {
| ^^^^^^^^^^
-error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in type
+error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in impl headers
--> $DIR/where-allowed.rs:177:24
|
LL | impl InInherentImplAdt<impl Debug> {
| ^^^^^^^^^^
-error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in type
+error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in bounds
--> $DIR/where-allowed.rs:183:11
|
LL | where impl Debug: Debug
| ^^^^^^^^^^
-error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in type
+error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in bounds
--> $DIR/where-allowed.rs:190:15
|
LL | where Vec<impl Debug>: Debug
| ^^^^^^^^^^
-error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in bound
+error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in bounds
--> $DIR/where-allowed.rs:197:24
|
LL | where T: PartialEq<impl Debug>
| ^^^^^^^^^^
-error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `Fn` trait param
+error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `Fn` trait params
--> $DIR/where-allowed.rs:204:17
|
LL | where T: Fn(impl Debug)
| ^^^^^^^^^^
-error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `Fn` trait return
+error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `Fn` trait return types
--> $DIR/where-allowed.rs:211:22
|
LL | where T: Fn() -> impl Debug
| ^^^^^^^^^^
-error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in type
+error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in generic parameter defaults
--> $DIR/where-allowed.rs:217:40
|
LL | struct InStructGenericParamDefault<T = impl Debug>(T);
| ^^^^^^^^^^
-error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in type
+error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in generic parameter defaults
--> $DIR/where-allowed.rs:221:36
|
LL | enum InEnumGenericParamDefault<T = impl Debug> { Variant(T) }
| ^^^^^^^^^^
-error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in type
+error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in generic parameter defaults
--> $DIR/where-allowed.rs:225:38
|
LL | trait InTraitGenericParamDefault<T = impl Debug> {}
| ^^^^^^^^^^
-error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in type
+error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in generic parameter defaults
--> $DIR/where-allowed.rs:229:41
|
LL | type InTypeAliasGenericParamDefault<T = impl Debug> = T;
| ^^^^^^^^^^
-error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in type
+error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in generic parameter defaults
--> $DIR/where-allowed.rs:233:11
|
LL | impl <T = impl Debug> T {}
| ^^^^^^^^^^
-error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in type
+error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in generic parameter defaults
--> $DIR/where-allowed.rs:240:40
|
LL | fn in_method_generic_param_default<T = impl Debug>(_: T) {}
| ^^^^^^^^^^
-error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in variable binding
+error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in variable bindings
--> $DIR/where-allowed.rs:246:29
|
LL | let _in_local_variable: impl Fn() = || {};
| ^^^^^^^^^
-error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in closure return
+error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in closure return types
--> $DIR/where-allowed.rs:248:46
|
LL | let _in_return_in_local_variable = || -> impl Fn() { || {} };
@@ -303,10 +303,10 @@ LL | fn in_method_generic_param_default<T = impl Debug>(_: T) {}
= note: for more information, see issue #36887 <https://github.com/rust-lang/rust/issues/36887>
error[E0118]: no nominal type found for inherent implementation
- --> $DIR/where-allowed.rs:233:23
+ --> $DIR/where-allowed.rs:233:1
|
LL | impl <T = impl Debug> T {}
- | ^ impl requires a nominal type
+ | ^^^^^^^^^^^^^^^^^^^^^^^ impl requires a nominal type
|
= note: either implement a trait on it or create a newtype to wrap it instead
diff --git a/tests/ui/implied-bounds/assoc-ty-wf-used-to-get-assoc-ty.stderr b/tests/ui/implied-bounds/assoc-ty-wf-used-to-get-assoc-ty.stderr
index d0249e74f..307899297 100644
--- a/tests/ui/implied-bounds/assoc-ty-wf-used-to-get-assoc-ty.stderr
+++ b/tests/ui/implied-bounds/assoc-ty-wf-used-to-get-assoc-ty.stderr
@@ -1,6 +1,8 @@
error[E0597]: `x` does not live long enough
--> $DIR/assoc-ty-wf-used-to-get-assoc-ty.rs:24:31
|
+LL | let x: u8 = 3;
+ | - binding `x` declared here
LL | let _: &'static u8 = test(&x, &&3);
| -----^^------
| | |
diff --git a/tests/ui/implied-bounds/issue-100690.stderr b/tests/ui/implied-bounds/issue-100690.stderr
index 3f6af70d8..dba035337 100644
--- a/tests/ui/implied-bounds/issue-100690.stderr
+++ b/tests/ui/implied-bounds/issue-100690.stderr
@@ -12,7 +12,7 @@ note: required by a bound in `real_dispatch`
--> $DIR/issue-100690.rs:9:8
|
LL | fn real_dispatch<T, F>(f: F) -> Result<(), io::Error>
- | ------------- required by a bound in this
+ | ------------- required by a bound in this function
...
LL | F: FnOnce(&mut UIView<T>) -> Result<(), io::Error> + Send + 'static,
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `real_dispatch`
diff --git a/tests/ui/imports/import-prefix-macro-1.stderr b/tests/ui/imports/import-prefix-macro-1.stderr
index 8868ee3ae..a6a5b1393 100644
--- a/tests/ui/imports/import-prefix-macro-1.stderr
+++ b/tests/ui/imports/import-prefix-macro-1.stderr
@@ -2,7 +2,7 @@ error: expected one of `::`, `;`, or `as`, found `{`
--> $DIR/import-prefix-macro-1.rs:11:27
|
LL | ($p: path) => (use $p {S, Z});
- | ^^^^^^ expected one of `::`, `;`, or `as`
+ | ^ expected one of `::`, `;`, or `as`
...
LL | import! { a::b::c }
| ------------------- in this macro invocation
diff --git a/tests/ui/include-macros/mismatched-types.stderr b/tests/ui/include-macros/mismatched-types.stderr
index a408877af..4f2880e2f 100644
--- a/tests/ui/include-macros/mismatched-types.stderr
+++ b/tests/ui/include-macros/mismatched-types.stderr
@@ -2,7 +2,7 @@ error[E0308]: mismatched types
--> $DIR/mismatched-types.rs:2:20
|
LL | let b: &[u8] = include_str!("file.txt");
- | ----- ^^^^^^^^^^^^^^^^^^^^^^^^ expected slice `[u8]`, found `str`
+ | ----- ^^^^^^^^^^^^^^^^^^^^^^^^ expected `&[u8]`, found `&str`
| |
| expected due to this
|
@@ -14,7 +14,7 @@ error[E0308]: mismatched types
--> $DIR/mismatched-types.rs:3:19
|
LL | let s: &str = include_bytes!("file.txt");
- | ---- ^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `str`, found array `[u8; 0]`
+ | ---- ^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `&str`, found `&[u8; 0]`
| |
| expected due to this
|
diff --git a/tests/ui/incoherent-inherent-impls/needs-has-incoherent-impls.stderr b/tests/ui/incoherent-inherent-impls/needs-has-incoherent-impls.stderr
index 8f7082511..f5900afe2 100644
--- a/tests/ui/incoherent-inherent-impls/needs-has-incoherent-impls.stderr
+++ b/tests/ui/incoherent-inherent-impls/needs-has-incoherent-impls.stderr
@@ -1,114 +1,80 @@
error[E0390]: cannot define inherent `impl` for a type outside of the crate where the type is defined
--> $DIR/needs-has-incoherent-impls.rs:5:1
|
-LL | / impl extern_crate::StructWithAttr {
-LL | |
-LL | | fn foo() {}
-LL | | }
- | |_^
+LL | impl extern_crate::StructWithAttr {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= help: consider moving this inherent impl into the crate defining the type if possible
help: alternatively add `#[rustc_allow_incoherent_impl]` to the relevant impl items
--> $DIR/needs-has-incoherent-impls.rs:7:5
|
LL | fn foo() {}
- | ^^^^^^^^^^^
+ | ^^^^^^^^
error[E0390]: cannot define inherent `impl` for a type outside of the crate where the type is defined
--> $DIR/needs-has-incoherent-impls.rs:13:1
|
-LL | / impl extern_crate::StructNoAttr {
-LL | |
-LL | | fn foo() {}
-LL | | }
- | |_^
+LL | impl extern_crate::StructNoAttr {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= help: consider moving this inherent impl into the crate defining the type if possible
help: alternatively add `#[rustc_has_incoherent_inherent_impls]` to the type and `#[rustc_allow_incoherent_impl]` to the relevant impl items
--> $DIR/needs-has-incoherent-impls.rs:13:1
|
-LL | / impl extern_crate::StructNoAttr {
-LL | |
-LL | | fn foo() {}
-LL | | }
- | |_^
+LL | impl extern_crate::StructNoAttr {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0390]: cannot define inherent `impl` for a type outside of the crate where the type is defined
--> $DIR/needs-has-incoherent-impls.rs:17:1
|
-LL | / impl extern_crate::StructNoAttr {
-LL | |
-LL | | #[rustc_allow_incoherent_impl]
-LL | | fn bar() {}
-LL | | }
- | |_^
+LL | impl extern_crate::StructNoAttr {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= help: consider moving this inherent impl into the crate defining the type if possible
help: alternatively add `#[rustc_has_incoherent_inherent_impls]` to the type and `#[rustc_allow_incoherent_impl]` to the relevant impl items
--> $DIR/needs-has-incoherent-impls.rs:17:1
|
-LL | / impl extern_crate::StructNoAttr {
-LL | |
-LL | | #[rustc_allow_incoherent_impl]
-LL | | fn bar() {}
-LL | | }
- | |_^
+LL | impl extern_crate::StructNoAttr {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0390]: cannot define inherent `impl` for a type outside of the crate where the type is defined
--> $DIR/needs-has-incoherent-impls.rs:22:1
|
-LL | / impl extern_crate::EnumWithAttr {
-LL | |
-LL | | fn foo() {}
-LL | | }
- | |_^
+LL | impl extern_crate::EnumWithAttr {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= help: consider moving this inherent impl into the crate defining the type if possible
help: alternatively add `#[rustc_allow_incoherent_impl]` to the relevant impl items
--> $DIR/needs-has-incoherent-impls.rs:24:5
|
LL | fn foo() {}
- | ^^^^^^^^^^^
+ | ^^^^^^^^
error[E0390]: cannot define inherent `impl` for a type outside of the crate where the type is defined
--> $DIR/needs-has-incoherent-impls.rs:30:1
|
-LL | / impl extern_crate::EnumNoAttr {
-LL | |
-LL | | fn foo() {}
-LL | | }
- | |_^
+LL | impl extern_crate::EnumNoAttr {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= help: consider moving this inherent impl into the crate defining the type if possible
help: alternatively add `#[rustc_has_incoherent_inherent_impls]` to the type and `#[rustc_allow_incoherent_impl]` to the relevant impl items
--> $DIR/needs-has-incoherent-impls.rs:30:1
|
-LL | / impl extern_crate::EnumNoAttr {
-LL | |
-LL | | fn foo() {}
-LL | | }
- | |_^
+LL | impl extern_crate::EnumNoAttr {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0390]: cannot define inherent `impl` for a type outside of the crate where the type is defined
--> $DIR/needs-has-incoherent-impls.rs:34:1
|
-LL | / impl extern_crate::EnumNoAttr {
-LL | |
-LL | | #[rustc_allow_incoherent_impl]
-LL | | fn bar() {}
-LL | | }
- | |_^
+LL | impl extern_crate::EnumNoAttr {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= help: consider moving this inherent impl into the crate defining the type if possible
help: alternatively add `#[rustc_has_incoherent_inherent_impls]` to the type and `#[rustc_allow_incoherent_impl]` to the relevant impl items
--> $DIR/needs-has-incoherent-impls.rs:34:1
|
-LL | / impl extern_crate::EnumNoAttr {
-LL | |
-LL | | #[rustc_allow_incoherent_impl]
-LL | | fn bar() {}
-LL | | }
- | |_^
+LL | impl extern_crate::EnumNoAttr {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: aborting due to 6 previous errors
diff --git a/tests/ui/incoherent-inherent-impls/no-attr-empty-impl.stderr b/tests/ui/incoherent-inherent-impls/no-attr-empty-impl.stderr
index b3f8b51d0..6dc1680cf 100644
--- a/tests/ui/incoherent-inherent-impls/no-attr-empty-impl.stderr
+++ b/tests/ui/incoherent-inherent-impls/no-attr-empty-impl.stderr
@@ -2,7 +2,7 @@ error[E0116]: cannot define inherent `impl` for a type outside of the crate wher
--> $DIR/no-attr-empty-impl.rs:4:1
|
LL | impl extern_crate::StructWithAttr {}
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl for type defined outside of crate.
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl for type defined outside of crate.
|
= note: define and implement a trait or new type instead
@@ -10,7 +10,7 @@ error[E0116]: cannot define inherent `impl` for a type outside of the crate wher
--> $DIR/no-attr-empty-impl.rs:7:1
|
LL | impl extern_crate::StructNoAttr {}
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl for type defined outside of crate.
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl for type defined outside of crate.
|
= note: define and implement a trait or new type instead
@@ -18,7 +18,7 @@ error[E0116]: cannot define inherent `impl` for a type outside of the crate wher
--> $DIR/no-attr-empty-impl.rs:10:1
|
LL | impl extern_crate::EnumWithAttr {}
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl for type defined outside of crate.
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl for type defined outside of crate.
|
= note: define and implement a trait or new type instead
@@ -26,15 +26,15 @@ error[E0116]: cannot define inherent `impl` for a type outside of the crate wher
--> $DIR/no-attr-empty-impl.rs:13:1
|
LL | impl extern_crate::EnumNoAttr {}
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl for type defined outside of crate.
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl for type defined outside of crate.
|
= note: define and implement a trait or new type instead
error[E0390]: cannot define inherent `impl` for primitive types
- --> $DIR/no-attr-empty-impl.rs:16:6
+ --> $DIR/no-attr-empty-impl.rs:16:1
|
LL | impl f32 {}
- | ^^^
+ | ^^^^^^^^
|
= help: consider using an extension trait instead
diff --git a/tests/ui/inference/array-len-mismatch.rs b/tests/ui/inference/array-len-mismatch.rs
new file mode 100644
index 000000000..149d06102
--- /dev/null
+++ b/tests/ui/inference/array-len-mismatch.rs
@@ -0,0 +1,12 @@
+fn returns_arr() -> [u8; 2] {
+ [1, 2]
+}
+
+fn main() {
+ let wrong: [u8; 3] = [10, 20];
+ //~^ ERROR mismatched types
+ //~^^ HELP consider specifying the actual array length
+ let wrong: [u8; 3] = returns_arr();
+ //~^ ERROR mismatched types
+ //~^^ HELP consider specifying the actual array length
+}
diff --git a/tests/ui/inference/array-len-mismatch.stderr b/tests/ui/inference/array-len-mismatch.stderr
new file mode 100644
index 000000000..7358e4783
--- /dev/null
+++ b/tests/ui/inference/array-len-mismatch.stderr
@@ -0,0 +1,21 @@
+error[E0308]: mismatched types
+ --> $DIR/array-len-mismatch.rs:6:26
+ |
+LL | let wrong: [u8; 3] = [10, 20];
+ | ------- ^^^^^^^^ expected an array with a fixed size of 3 elements, found one with 2 elements
+ | | |
+ | | help: consider specifying the actual array length: `2`
+ | expected due to this
+
+error[E0308]: mismatched types
+ --> $DIR/array-len-mismatch.rs:9:26
+ |
+LL | let wrong: [u8; 3] = returns_arr();
+ | ------- ^^^^^^^^^^^^^ expected an array with a fixed size of 3 elements, found one with 2 elements
+ | | |
+ | | help: consider specifying the actual array length: `2`
+ | expected due to this
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/inference/deref-suggestion.stderr b/tests/ui/inference/deref-suggestion.stderr
index 3db67cdb5..1626032ae 100644
--- a/tests/ui/inference/deref-suggestion.stderr
+++ b/tests/ui/inference/deref-suggestion.stderr
@@ -4,7 +4,7 @@ error[E0308]: mismatched types
LL | foo(s);
| --- ^- help: try using a conversion method: `.to_string()`
| | |
- | | expected struct `String`, found `&String`
+ | | expected `String`, found `&String`
| arguments to this function are incorrect
|
note: function defined here
@@ -35,7 +35,7 @@ error[E0308]: mismatched types
--> $DIR/deref-suggestion.rs:30:9
|
LL | foo(&"aaa".to_owned());
- | --- ^^^^^^^^^^^^^^^^^ expected struct `String`, found `&String`
+ | --- ^^^^^^^^^^^^^^^^^ expected `String`, found `&String`
| |
| arguments to this function are incorrect
|
@@ -54,7 +54,7 @@ error[E0308]: mismatched types
--> $DIR/deref-suggestion.rs:32:9
|
LL | foo(&mut "aaa".to_owned());
- | --- ^^^^^^^^^^^^^^^^^^^^^ expected struct `String`, found `&mut String`
+ | --- ^^^^^^^^^^^^^^^^^^^^^ expected `String`, found `&mut String`
| |
| arguments to this function are incorrect
|
diff --git a/tests/ui/inference/inference_unstable.rs b/tests/ui/inference/inference_unstable.rs
index daf0cf042..ad7649959 100644
--- a/tests/ui/inference/inference_unstable.rs
+++ b/tests/ui/inference/inference_unstable.rs
@@ -14,16 +14,16 @@ use inference_unstable_itertools::IpuItertools;
fn main() {
assert_eq!('x'.ipu_flatten(), 1);
-//~^ WARN an associated function with this name may be added to the standard library in the future
+//~^ WARN a method with this name may be added to the standard library in the future
//~| WARN once this associated item is added to the standard library, the ambiguity may cause an
assert_eq!('x'.ipu_by_value_vs_by_ref(), 1);
-//~^ WARN an associated function with this name may be added to the standard library in the future
+//~^ WARN a method with this name may be added to the standard library in the future
//~| WARN once this associated item is added to the standard library, the ambiguity may cause an
assert_eq!('x'.ipu_by_ref_vs_by_ref_mut(), 1);
-//~^ WARN an associated function with this name may be added to the standard library in the future
+//~^ WARN a method with this name may be added to the standard library in the future
//~| WARN once this associated item is added to the standard library, the ambiguity may cause an
assert_eq!((&mut 'x' as *mut char).ipu_by_mut_ptr_vs_by_const_ptr(), 1);
-//~^ WARN an associated function with this name may be added to the standard library in the future
+//~^ WARN a method with this name may be added to the standard library in the future
//~| WARN once this associated item is added to the standard library, the ambiguity may cause an
assert_eq!(char::C, 1);
//~^ WARN an associated constant with this name may be added to the standard library in the future
diff --git a/tests/ui/inference/inference_unstable.stderr b/tests/ui/inference/inference_unstable.stderr
index ecbf2641b..c48aaf9f4 100644
--- a/tests/ui/inference/inference_unstable.stderr
+++ b/tests/ui/inference/inference_unstable.stderr
@@ -1,4 +1,4 @@
-warning: an associated function with this name may be added to the standard library in the future
+warning: a method with this name may be added to the standard library in the future
--> $DIR/inference_unstable.rs:16:20
|
LL | assert_eq!('x'.ipu_flatten(), 1);
@@ -10,7 +10,7 @@ LL | assert_eq!('x'.ipu_flatten(), 1);
= help: add `#![feature(ipu_flatten)]` to the crate attributes to enable `inference_unstable_iterator::IpuIterator::ipu_flatten`
= note: `#[warn(unstable_name_collisions)]` on by default
-warning: an associated function with this name may be added to the standard library in the future
+warning: a method with this name may be added to the standard library in the future
--> $DIR/inference_unstable.rs:19:20
|
LL | assert_eq!('x'.ipu_by_value_vs_by_ref(), 1);
@@ -21,7 +21,7 @@ LL | assert_eq!('x'.ipu_by_value_vs_by_ref(), 1);
= help: call with fully qualified syntax `inference_unstable_itertools::IpuItertools::ipu_by_value_vs_by_ref(...)` to keep using the current method
= help: add `#![feature(ipu_flatten)]` to the crate attributes to enable `inference_unstable_iterator::IpuIterator::ipu_by_value_vs_by_ref`
-warning: an associated function with this name may be added to the standard library in the future
+warning: a method with this name may be added to the standard library in the future
--> $DIR/inference_unstable.rs:22:20
|
LL | assert_eq!('x'.ipu_by_ref_vs_by_ref_mut(), 1);
@@ -32,7 +32,7 @@ LL | assert_eq!('x'.ipu_by_ref_vs_by_ref_mut(), 1);
= help: call with fully qualified syntax `inference_unstable_itertools::IpuItertools::ipu_by_ref_vs_by_ref_mut(...)` to keep using the current method
= help: add `#![feature(ipu_flatten)]` to the crate attributes to enable `inference_unstable_iterator::IpuIterator::ipu_by_ref_vs_by_ref_mut`
-warning: an associated function with this name may be added to the standard library in the future
+warning: a method with this name may be added to the standard library in the future
--> $DIR/inference_unstable.rs:25:40
|
LL | assert_eq!((&mut 'x' as *mut char).ipu_by_mut_ptr_vs_by_const_ptr(), 1);
diff --git a/tests/ui/inference/inference_unstable_featured.stderr b/tests/ui/inference/inference_unstable_featured.stderr
index 4ddede29c..dc43abf52 100644
--- a/tests/ui/inference/inference_unstable_featured.stderr
+++ b/tests/ui/inference/inference_unstable_featured.stderr
@@ -6,11 +6,11 @@ LL | assert_eq!('x'.ipu_flatten(), 0);
|
= note: candidate #1 is defined in an impl of the trait `IpuIterator` for the type `char`
= note: candidate #2 is defined in an impl of the trait `IpuItertools` for the type `char`
-help: disambiguate the associated function for candidate #1
+help: disambiguate the method for candidate #1
|
LL | assert_eq!(IpuIterator::ipu_flatten(&'x'), 0);
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-help: disambiguate the associated function for candidate #2
+help: disambiguate the method for candidate #2
|
LL | assert_eq!(IpuItertools::ipu_flatten(&'x'), 0);
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
diff --git a/tests/ui/inference/issue-107090.rs b/tests/ui/inference/issue-107090.rs
new file mode 100644
index 000000000..a22e12c6d
--- /dev/null
+++ b/tests/ui/inference/issue-107090.rs
@@ -0,0 +1,25 @@
+use std::marker::PhantomData;
+struct Foo<'a, 'b, T>(PhantomData<(&'a (), &'b (), T)>)
+where
+ Foo<'short, 'out, T>: Convert<'a, 'b>;
+ //~^ ERROR use of undeclared lifetime name
+ //~| ERROR use of undeclared lifetime name `'out`
+
+trait Convert<'a, 'b>: Sized {
+ fn cast(&'a self) -> &'b Self;
+}
+impl<'long: 'short, 'short, T> Convert<'long, 'b> for Foo<'short, 'out, T> {
+ //~^ ERROR use of undeclared lifetime name
+ //~^^ ERROR use of undeclared lifetime name `'out`
+ fn cast(&'long self) -> &'short Foo<'short, 'out, T> {
+ //~^ ERROR use of undeclared lifetime name
+ self
+ }
+}
+
+fn badboi<'in_, 'out, T>(x: Foo<'in_, 'out, T>, sadness: &'in_ Foo<'short, 'out, T>) -> &'out T {
+ //~^ ERROR use of undeclared lifetime name
+ sadness.cast() //~ ERROR mismatched types
+}
+
+fn main() {}
diff --git a/tests/ui/inference/issue-107090.stderr b/tests/ui/inference/issue-107090.stderr
new file mode 100644
index 000000000..6233b629a
--- /dev/null
+++ b/tests/ui/inference/issue-107090.stderr
@@ -0,0 +1,84 @@
+error[E0261]: use of undeclared lifetime name `'short`
+ --> $DIR/issue-107090.rs:4:9
+ |
+LL | Foo<'short, 'out, T>: Convert<'a, 'b>;
+ | ^^^^^^ undeclared lifetime
+ |
+ = note: for more information on higher-ranked polymorphism, visit https://doc.rust-lang.org/nomicon/hrtb.html
+help: consider making the bound lifetime-generic with a new `'short` lifetime
+ |
+LL | for<'short> Foo<'short, 'out, T>: Convert<'a, 'b>;
+ | +++++++++++
+help: consider introducing lifetime `'short` here
+ |
+LL | struct Foo<'short, 'a, 'b, T>(PhantomData<(&'a (), &'b (), T)>)
+ | +++++++
+
+error[E0261]: use of undeclared lifetime name `'out`
+ --> $DIR/issue-107090.rs:4:17
+ |
+LL | Foo<'short, 'out, T>: Convert<'a, 'b>;
+ | ^^^^ undeclared lifetime
+ |
+help: consider making the bound lifetime-generic with a new `'out` lifetime
+ |
+LL | for<'out> Foo<'short, 'out, T>: Convert<'a, 'b>;
+ | +++++++++
+help: consider introducing lifetime `'out` here
+ |
+LL | struct Foo<'out, 'a, 'b, T>(PhantomData<(&'a (), &'b (), T)>)
+ | +++++
+
+error[E0261]: use of undeclared lifetime name `'b`
+ --> $DIR/issue-107090.rs:11:47
+ |
+LL | impl<'long: 'short, 'short, T> Convert<'long, 'b> for Foo<'short, 'out, T> {
+ | - ^^ undeclared lifetime
+ | |
+ | help: consider introducing lifetime `'b` here: `'b,`
+
+error[E0261]: use of undeclared lifetime name `'out`
+ --> $DIR/issue-107090.rs:11:67
+ |
+LL | impl<'long: 'short, 'short, T> Convert<'long, 'b> for Foo<'short, 'out, T> {
+ | - help: consider introducing lifetime `'out` here: `'out,` ^^^^ undeclared lifetime
+
+error[E0261]: use of undeclared lifetime name `'out`
+ --> $DIR/issue-107090.rs:14:49
+ |
+LL | fn cast(&'long self) -> &'short Foo<'short, 'out, T> {
+ | ^^^^ undeclared lifetime
+ |
+help: consider introducing lifetime `'out` here
+ |
+LL | fn cast<'out>(&'long self) -> &'short Foo<'short, 'out, T> {
+ | ++++++
+help: consider introducing lifetime `'out` here
+ |
+LL | impl<'out, 'long: 'short, 'short, T> Convert<'long, 'b> for Foo<'short, 'out, T> {
+ | +++++
+
+error[E0261]: use of undeclared lifetime name `'short`
+ --> $DIR/issue-107090.rs:20:68
+ |
+LL | fn badboi<'in_, 'out, T>(x: Foo<'in_, 'out, T>, sadness: &'in_ Foo<'short, 'out, T>) -> &'out T {
+ | - ^^^^^^ undeclared lifetime
+ | |
+ | help: consider introducing lifetime `'short` here: `'short,`
+
+error[E0308]: mismatched types
+ --> $DIR/issue-107090.rs:22:5
+ |
+LL | fn badboi<'in_, 'out, T>(x: Foo<'in_, 'out, T>, sadness: &'in_ Foo<'short, 'out, T>) -> &'out T {
+ | - this type parameter ------- expected `&'out T` because of return type
+LL |
+LL | sadness.cast()
+ | ^^^^^^^^^^^^^^ expected `&T`, found `&Foo<'_, '_, T>`
+ |
+ = note: expected reference `&'out T`
+ found reference `&Foo<'_, '_, T>`
+
+error: aborting due to 7 previous errors
+
+Some errors have detailed explanations: E0261, E0308.
+For more information about an error, try `rustc --explain E0261`.
diff --git a/tests/ui/inference/issue-71732.stderr b/tests/ui/inference/issue-71732.stderr
index 01b37f2ac..e89e4dca6 100644
--- a/tests/ui/inference/issue-71732.stderr
+++ b/tests/ui/inference/issue-71732.stderr
@@ -4,7 +4,7 @@ error[E0283]: type annotations needed
LL | .get(&"key".into())
| ^^^ ------------- type must be known at this point
| |
- | cannot infer type of the type parameter `Q` declared on the associated function `get`
+ | cannot infer type of the type parameter `Q` declared on the method `get`
|
= note: multiple `impl`s satisfying `String: Borrow<_>` found in the following crates: `alloc`, `core`:
- impl Borrow<str> for String;
diff --git a/tests/ui/inference/need_type_info/issue-107745-avoid-expr-from-macro-expansion.rs b/tests/ui/inference/need_type_info/issue-107745-avoid-expr-from-macro-expansion.rs
new file mode 100644
index 000000000..7f6758f47
--- /dev/null
+++ b/tests/ui/inference/need_type_info/issue-107745-avoid-expr-from-macro-expansion.rs
@@ -0,0 +1,19 @@
+// ignore-tidy-linelength
+
+// Regression test for #107745.
+// Previously need_type_info::update_infer_source will consider expressions originating from
+// macro expressions as candiate "previous sources". This unfortunately can mean that
+// for macros expansions such as `format!()` internal implementation details can leak, such as:
+//
+// ```
+// error[E0282]: type annotations needed
+// --> src/main.rs:2:22
+// |
+//2 | println!("{:?}", []);
+// | ^^ cannot infer type of the type parameter `T` declared on the associated function `new_debug`
+// ```
+
+fn main() {
+ println!("{:?}", []);
+ //~^ ERROR type annotations needed
+}
diff --git a/tests/ui/inference/need_type_info/issue-107745-avoid-expr-from-macro-expansion.stderr b/tests/ui/inference/need_type_info/issue-107745-avoid-expr-from-macro-expansion.stderr
new file mode 100644
index 000000000..464655bbc
--- /dev/null
+++ b/tests/ui/inference/need_type_info/issue-107745-avoid-expr-from-macro-expansion.stderr
@@ -0,0 +1,11 @@
+error[E0282]: type annotations needed
+ --> $DIR/issue-107745-avoid-expr-from-macro-expansion.rs:17:22
+ |
+LL | println!("{:?}", []);
+ | ^^ cannot infer type
+ |
+ = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (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 E0282`.
diff --git a/tests/ui/inference/question-mark-type-infer.stderr b/tests/ui/inference/question-mark-type-infer.stderr
index a9cb7e525..7a1e850d1 100644
--- a/tests/ui/inference/question-mark-type-infer.stderr
+++ b/tests/ui/inference/question-mark-type-infer.stderr
@@ -2,7 +2,7 @@ error[E0282]: type annotations needed
--> $DIR/question-mark-type-infer.rs:10:21
|
LL | l.iter().map(f).collect()?
- | ^^^^^^^ cannot infer type of the type parameter `B` declared on the associated function `collect`
+ | ^^^^^^^ cannot infer type of the type parameter `B` declared on the method `collect`
|
help: consider specifying the generic argument
|
diff --git a/tests/ui/infinite/auxiliary/alias.rs b/tests/ui/infinite/auxiliary/alias.rs
new file mode 100644
index 000000000..59add7eb1
--- /dev/null
+++ b/tests/ui/infinite/auxiliary/alias.rs
@@ -0,0 +1,2 @@
+pub struct W<T>(T);
+pub type Wrapper<T> = W<T>;
diff --git a/tests/ui/infinite/infinite-alias.rs b/tests/ui/infinite/infinite-alias.rs
new file mode 100644
index 000000000..45356f359
--- /dev/null
+++ b/tests/ui/infinite/infinite-alias.rs
@@ -0,0 +1,9 @@
+// aux-build: alias.rs
+// regression test for 108160
+
+extern crate alias;
+
+use alias::Wrapper;
+struct Rec(Wrapper<Rec>); //~ ERROR recursive type `Rec` has infinite
+
+fn main() {}
diff --git a/tests/ui/infinite/infinite-alias.stderr b/tests/ui/infinite/infinite-alias.stderr
new file mode 100644
index 000000000..9d9265f8c
--- /dev/null
+++ b/tests/ui/infinite/infinite-alias.stderr
@@ -0,0 +1,14 @@
+error[E0072]: recursive type `Rec` has infinite size
+ --> $DIR/infinite-alias.rs:7:1
+ |
+LL | struct Rec(Wrapper<Rec>);
+ | ^^^^^^^^^^ ------------ recursive without indirection
+ |
+help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to break the cycle
+ |
+LL | struct Rec(Box<Wrapper<Rec>>);
+ | ++++ +
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0072`.
diff --git a/tests/ui/inline-const/const-expr-lifetime-err.stderr b/tests/ui/inline-const/const-expr-lifetime-err.stderr
index a23f7c9a7..443fcf89c 100644
--- a/tests/ui/inline-const/const-expr-lifetime-err.stderr
+++ b/tests/ui/inline-const/const-expr-lifetime-err.stderr
@@ -4,6 +4,7 @@ error[E0597]: `y` does not live long enough
LL | fn foo<'a>() {
| -- lifetime `'a` defined here
LL | let y = ();
+ | - binding `y` declared here
LL | equate(InvariantRef::new(&y), const { InvariantRef::<'a>::NEW });
| ------------------^^-
| | |
diff --git a/tests/ui/instrument-xray/flags-always-never-1.rs b/tests/ui/instrument-xray/flags-always-never-1.rs
new file mode 100644
index 000000000..4dd43439e
--- /dev/null
+++ b/tests/ui/instrument-xray/flags-always-never-1.rs
@@ -0,0 +1,7 @@
+// Checks that `-Z instrument-xray` does not allow `always` and `never` simultaneously.
+//
+// needs-xray
+// compile-flags: -Z instrument-xray=always,never
+// error-pattern: incorrect value `always,never` for unstable option `instrument-xray`
+
+fn main() {}
diff --git a/tests/ui/instrument-xray/flags-always-never-1.stderr b/tests/ui/instrument-xray/flags-always-never-1.stderr
new file mode 100644
index 000000000..e211c6f60
--- /dev/null
+++ b/tests/ui/instrument-xray/flags-always-never-1.stderr
@@ -0,0 +1,2 @@
+error: incorrect value `always,never` for unstable option `instrument-xray` - either a boolean (`yes`, `no`, `on`, `off`, etc), or a comma separated list of settings: `always` or `never` (mutually exclusive), `ignore-loops`, `instruction-threshold=N`, `skip-entry`, `skip-exit` was expected
+
diff --git a/tests/ui/instrument-xray/flags-always-never-2.rs b/tests/ui/instrument-xray/flags-always-never-2.rs
new file mode 100644
index 000000000..7310aa0a0
--- /dev/null
+++ b/tests/ui/instrument-xray/flags-always-never-2.rs
@@ -0,0 +1,9 @@
+// Checks that `-Z instrument-xray` allows `always` and `never` sequentially.
+// (The last specified setting wins, like `-Z instrument-xray=no` as well.)
+//
+// needs-xray
+// compile-flags: -Z instrument-xray=always
+// compile-flags: -Z instrument-xray=never
+// check-pass
+
+fn main() {}
diff --git a/tests/ui/instrument-xray/flags-basic.rs b/tests/ui/instrument-xray/flags-basic.rs
new file mode 100644
index 000000000..b97f0dd8a
--- /dev/null
+++ b/tests/ui/instrument-xray/flags-basic.rs
@@ -0,0 +1,9 @@
+// Verifies basic `-Z instrument-xray` flags.
+//
+// needs-xray
+// compile-flags: -Z instrument-xray
+// compile-flags: -Z instrument-xray=skip-exit
+// compile-flags: -Z instrument-xray=ignore-loops,instruction-threshold=300
+// check-pass
+
+fn main() {}
diff --git a/tests/ui/instrument-xray/flags-dupe-always.rs b/tests/ui/instrument-xray/flags-dupe-always.rs
new file mode 100644
index 000000000..407f3e2aa
--- /dev/null
+++ b/tests/ui/instrument-xray/flags-dupe-always.rs
@@ -0,0 +1,7 @@
+// Checks that `-Z instrument-xray` does not allow duplicates.
+//
+// needs-xray
+// compile-flags: -Z instrument-xray=always,always
+// error-pattern: incorrect value `always,always` for unstable option `instrument-xray`
+
+fn main() {}
diff --git a/tests/ui/instrument-xray/flags-dupe-always.stderr b/tests/ui/instrument-xray/flags-dupe-always.stderr
new file mode 100644
index 000000000..d1ac113fa
--- /dev/null
+++ b/tests/ui/instrument-xray/flags-dupe-always.stderr
@@ -0,0 +1,2 @@
+error: incorrect value `always,always` for unstable option `instrument-xray` - either a boolean (`yes`, `no`, `on`, `off`, etc), or a comma separated list of settings: `always` or `never` (mutually exclusive), `ignore-loops`, `instruction-threshold=N`, `skip-entry`, `skip-exit` was expected
+
diff --git a/tests/ui/instrument-xray/flags-dupe-ignore-loops.rs b/tests/ui/instrument-xray/flags-dupe-ignore-loops.rs
new file mode 100644
index 000000000..75b210a65
--- /dev/null
+++ b/tests/ui/instrument-xray/flags-dupe-ignore-loops.rs
@@ -0,0 +1,7 @@
+// Checks that `-Z instrument-xray` does not allow duplicates.
+//
+// needs-xray
+// compile-flags: -Z instrument-xray=ignore-loops,ignore-loops
+// error-pattern: incorrect value `ignore-loops,ignore-loops` for unstable option `instrument-xray`
+
+fn main() {}
diff --git a/tests/ui/instrument-xray/flags-dupe-ignore-loops.stderr b/tests/ui/instrument-xray/flags-dupe-ignore-loops.stderr
new file mode 100644
index 000000000..52f6b3307
--- /dev/null
+++ b/tests/ui/instrument-xray/flags-dupe-ignore-loops.stderr
@@ -0,0 +1,2 @@
+error: incorrect value `ignore-loops,ignore-loops` for unstable option `instrument-xray` - either a boolean (`yes`, `no`, `on`, `off`, etc), or a comma separated list of settings: `always` or `never` (mutually exclusive), `ignore-loops`, `instruction-threshold=N`, `skip-entry`, `skip-exit` was expected
+
diff --git a/tests/ui/instrument-xray/target-not-supported.rs b/tests/ui/instrument-xray/target-not-supported.rs
new file mode 100644
index 000000000..e6bdd23e8
--- /dev/null
+++ b/tests/ui/instrument-xray/target-not-supported.rs
@@ -0,0 +1,9 @@
+// Verifies that `-Z instrument-xray` cannot be used with unsupported targets,
+//
+// needs-llvm-components: x86
+// compile-flags: -Z instrument-xray --target x86_64-apple-darwin
+// error-pattern: error: XRay instrumentation is not supported for this target
+
+#![feature(no_core)]
+#![no_core]
+#![no_main]
diff --git a/tests/ui/instrument-xray/target-not-supported.stderr b/tests/ui/instrument-xray/target-not-supported.stderr
new file mode 100644
index 000000000..6e3b0c8a3
--- /dev/null
+++ b/tests/ui/instrument-xray/target-not-supported.stderr
@@ -0,0 +1,4 @@
+error: XRay instrumentation is not supported for this target
+
+error: aborting due to previous error
+
diff --git a/tests/ui/intrinsics/const-eval-select-bad.rs b/tests/ui/intrinsics/const-eval-select-bad.rs
index fa14efad7..991d1450a 100644
--- a/tests/ui/intrinsics/const-eval-select-bad.rs
+++ b/tests/ui/intrinsics/const-eval-select-bad.rs
@@ -30,7 +30,7 @@ fn baz(n: bool) -> i32 {
const fn return_ty_mismatch() {
const_eval_select((1,), foo, bar);
- //~^ ERROR expected `fn(i32) -> bool {bar}` to be a fn item that returns `i32`, but it returns `bool`
+ //~^ ERROR expected `bar` to be a fn item that returns `i32`, but it returns `bool`
}
const fn args_ty_mismatch() {
diff --git a/tests/ui/intrinsics/const-eval-select-bad.stderr b/tests/ui/intrinsics/const-eval-select-bad.stderr
index fd7d061b6..d4507a27a 100644
--- a/tests/ui/intrinsics/const-eval-select-bad.stderr
+++ b/tests/ui/intrinsics/const-eval-select-bad.stderr
@@ -60,7 +60,7 @@ LL | const_eval_select((), 42, 0xDEADBEEF);
note: required by a bound in `const_eval_select`
--> $SRC_DIR/core/src/intrinsics.rs:LL:COL
-error[E0271]: expected `fn(i32) -> bool {bar}` to be a fn item that returns `i32`, but it returns `bool`
+error[E0271]: expected `bar` to be a fn item that returns `i32`, but it returns `bool`
--> $DIR/const-eval-select-bad.rs:32:34
|
LL | const_eval_select((1,), foo, bar);
diff --git a/tests/ui/intrinsics/intrinsic-alignment.rs b/tests/ui/intrinsics/intrinsic-alignment.rs
index c8b1ff1db..b99bb39d0 100644
--- a/tests/ui/intrinsics/intrinsic-alignment.rs
+++ b/tests/ui/intrinsics/intrinsic-alignment.rs
@@ -22,7 +22,9 @@ mod rusti {
target_os = "netbsd",
target_os = "openbsd",
target_os = "solaris",
- target_os = "vxworks"))]
+ target_os = "vxworks",
+ target_os = "nto",
+))]
mod m {
#[cfg(target_arch = "x86")]
pub fn main() {
diff --git a/tests/ui/io-checks/inaccessbile-temp-dir.rs b/tests/ui/io-checks/inaccessbile-temp-dir.rs
new file mode 100644
index 000000000..9c0aa0135
--- /dev/null
+++ b/tests/ui/io-checks/inaccessbile-temp-dir.rs
@@ -0,0 +1,39 @@
+// Issue #66530: We would ICE if someone compiled with `-o /dev/null`,
+// because we would try to generate auxiliary files in `/dev/` (which
+// at least the OS X file system rejects).
+//
+// An attempt to `-o` into a directory we cannot write into should indeed
+// be an error; but not an ICE.
+//
+// However, some folks run tests as root, which can write `/dev/` and end
+// up clobbering `/dev/null`. Instead we'll use a non-existent path, which
+// also used to ICE, but even root can't magically write there.
+
+// compile-flags: -Z temps-dir=/does-not-exist/output
+
+// The error-pattern check occurs *before* normalization, and the error patterns
+// are wildly different between build environments. So this is a cop-out (and we
+// rely on the checking of the normalized stderr output as our actual
+// "verification" of the diagnostic).
+
+// error-pattern: error
+
+// On Mac OS X, we get an error like the below
+// normalize-stderr-test "failed to write bytecode to /does-not-exist/output.non_ice_error_on_worker_io_fail.*" -> "io error modifying /does-not-exist/"
+
+// On Linux, we get an error like the below
+// normalize-stderr-test "couldn't create a temp dir.*" -> "io error modifying /does-not-exist/"
+
+// ignore-windows - this is a unix-specific test
+// ignore-emscripten - the file-system issues do not replicate here
+// ignore-wasm - the file-system issues do not replicate here
+// ignore-arm - the file-system issues do not replicate here, at least on armhf-gnu
+
+#![crate_type = "lib"]
+#![cfg_attr(not(feature = "std"), no_std)]
+pub mod task {
+ pub mod __internal {
+ use crate::task::Waker;
+ }
+ pub use core::task::Waker;
+}
diff --git a/tests/ui/io-checks/inaccessbile-temp-dir.stderr b/tests/ui/io-checks/inaccessbile-temp-dir.stderr
new file mode 100644
index 000000000..2fc5f93ef
--- /dev/null
+++ b/tests/ui/io-checks/inaccessbile-temp-dir.stderr
@@ -0,0 +1,4 @@
+error: failed to find or create the directory specified by `--temps-dir`
+
+error: aborting due to previous error
+
diff --git a/tests/ui/non-ice-error-on-worker-io-fail.rs b/tests/ui/io-checks/non-ice-error-on-worker-io-fail.rs
index 134e7d420..134e7d420 100644
--- a/tests/ui/non-ice-error-on-worker-io-fail.rs
+++ b/tests/ui/io-checks/non-ice-error-on-worker-io-fail.rs
diff --git a/tests/ui/non-ice-error-on-worker-io-fail.stderr b/tests/ui/io-checks/non-ice-error-on-worker-io-fail.stderr
index edadecf27..edadecf27 100644
--- a/tests/ui/non-ice-error-on-worker-io-fail.stderr
+++ b/tests/ui/io-checks/non-ice-error-on-worker-io-fail.stderr
diff --git a/tests/ui/issues/issue-100605.stderr b/tests/ui/issues/issue-100605.stderr
index 886e3cd6b..be30eef2a 100644
--- a/tests/ui/issues/issue-100605.stderr
+++ b/tests/ui/issues/issue-100605.stderr
@@ -2,7 +2,7 @@ error[E0308]: mismatched types
--> $DIR/issue-100605.rs:4:18
|
LL | takes_option(&None);
- | ------------ ^^^^^ expected enum `Option`, found `&Option<_>`
+ | ------------ ^^^^^ expected `Option<&String>`, found `&Option<_>`
| |
| arguments to this function are incorrect
|
@@ -29,7 +29,7 @@ error[E0308]: mismatched types
LL | takes_option(&res);
| ------------ ^^^^
| | |
- | | expected enum `Option`, found `&Option<String>`
+ | | expected `Option<&String>`, found `&Option<String>`
| | help: you can convert from `&Option<T>` to `Option<&T>` using `.as_ref()`: `res.as_ref()`
| arguments to this function are incorrect
|
diff --git a/tests/ui/issues/issue-102964.stderr b/tests/ui/issues/issue-102964.stderr
index 450403909..c0766480a 100644
--- a/tests/ui/issues/issue-102964.stderr
+++ b/tests/ui/issues/issue-102964.stderr
@@ -2,7 +2,7 @@ error[E0308]: mismatched types
--> $DIR/issue-102964.rs:5:41
|
LL | fn bar_function<T>(function: Foo<T>) -> RcFoo<T> {
- | ------------ ^^^^^^^^ expected struct `Rc`, found `()`
+ | ------------ ^^^^^^^^ expected `Rc<&dyn Fn(&T)>`, found `()`
| |
| implicitly returns `()` as its body has no tail or `return` expression
|
diff --git a/tests/ui/issues/issue-10412.stderr b/tests/ui/issues/issue-10412.stderr
index 46b9fd541..26666782d 100644
--- a/tests/ui/issues/issue-10412.stderr
+++ b/tests/ui/issues/issue-10412.stderr
@@ -46,7 +46,6 @@ error[E0726]: implicit elided lifetime not allowed here
LL | impl<'self> Serializable<str> for &'self str {
| ^^^^^^^^^^^^^^^^^ expected lifetime parameter
|
- = note: assuming a `'static` lifetime...
help: indicate the anonymous lifetime
|
LL | impl<'self> Serializable<'_, str> for &'self str {
diff --git a/tests/ui/issues/issue-106755.rs b/tests/ui/issues/issue-106755.rs
new file mode 100644
index 000000000..46ece725f
--- /dev/null
+++ b/tests/ui/issues/issue-106755.rs
@@ -0,0 +1,19 @@
+// compile-flags:-Ztranslate-lang=en_US
+
+#![feature(negative_impls)]
+#![feature(marker_trait_attr)]
+
+#[marker]
+trait MyTrait {}
+
+struct TestType<T>(::std::marker::PhantomData<T>);
+
+unsafe impl<T: MyTrait + 'static> Send for TestType<T> {}
+
+impl<T: MyTrait> !Send for TestType<T> {} //~ ERROR found both positive and negative implementation
+
+unsafe impl<T: 'static> Send for TestType<T> {} //~ ERROR conflicting implementations
+
+impl !Send for TestType<i32> {}
+
+fn main() {}
diff --git a/tests/ui/issues/issue-106755.stderr b/tests/ui/issues/issue-106755.stderr
new file mode 100644
index 000000000..543970340
--- /dev/null
+++ b/tests/ui/issues/issue-106755.stderr
@@ -0,0 +1,22 @@
+error[E0751]: found both positive and negative implementation of trait `Send` for type `TestType<_>`:
+ --> $DIR/issue-106755.rs:13:1
+ |
+LL | unsafe impl<T: MyTrait + 'static> Send for TestType<T> {}
+ | ------------------------------------------------------ positive implementation here
+LL |
+LL | impl<T: MyTrait> !Send for TestType<T> {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ negative implementation here
+
+error[E0119]: conflicting implementations of trait `Send` for type `TestType<_>`
+ --> $DIR/issue-106755.rs:15:1
+ |
+LL | unsafe impl<T: MyTrait + 'static> Send for TestType<T> {}
+ | ------------------------------------------------------ first implementation here
+...
+LL | unsafe impl<T: 'static> Send for TestType<T> {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `TestType<_>`
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0119, E0751.
+For more information about an error, try `rustc --explain E0119`.
diff --git a/tests/ui/issues/issue-10764.stderr b/tests/ui/issues/issue-10764.stderr
index 4d8a85a13..fcb45affe 100644
--- a/tests/ui/issues/issue-10764.stderr
+++ b/tests/ui/issues/issue-10764.stderr
@@ -8,6 +8,7 @@ LL | fn main() { f(bar) }
|
= note: expected fn pointer `fn()`
found fn item `extern "C" fn() {bar}`
+ = note: when the arguments and return types match, functions can be coerced to function pointers
note: function defined here
--> $DIR/issue-10764.rs:1:4
|
diff --git a/tests/ui/issues/issue-11374.stderr b/tests/ui/issues/issue-11374.stderr
index ace77814a..6e1fb1540 100644
--- a/tests/ui/issues/issue-11374.stderr
+++ b/tests/ui/issues/issue-11374.stderr
@@ -4,13 +4,13 @@ error[E0308]: mismatched types
LL | c.read_to(v);
| ------- ^
| | |
- | | expected `&mut [u8]`, found struct `Vec`
+ | | expected `&mut [u8]`, found `Vec<_>`
| | help: consider mutably borrowing here: `&mut v`
| arguments to this method are incorrect
|
= note: expected mutable reference `&mut [u8]`
found struct `Vec<_>`
-note: associated function defined here
+note: method defined here
--> $DIR/issue-11374.rs:13:12
|
LL | pub fn read_to(&mut self, vec: &mut [u8]) {
diff --git a/tests/ui/issues/issue-11844.stderr b/tests/ui/issues/issue-11844.stderr
index 81cf918a1..9afd20977 100644
--- a/tests/ui/issues/issue-11844.stderr
+++ b/tests/ui/issues/issue-11844.stderr
@@ -4,7 +4,7 @@ error[E0308]: mismatched types
LL | match a {
| - this expression has type `Option<Box<{integer}>>`
LL | Ok(a) =>
- | ^^^^^ expected enum `Option`, found enum `Result`
+ | ^^^^^ expected `Option<Box<{integer}>>`, found `Result<_, _>`
|
= note: expected enum `Option<Box<{integer}>>`
found enum `Result<_, _>`
diff --git a/tests/ui/issues/issue-13446.stderr b/tests/ui/issues/issue-13446.stderr
index 30fb73dd3..139c34c88 100644
--- a/tests/ui/issues/issue-13446.stderr
+++ b/tests/ui/issues/issue-13446.stderr
@@ -2,7 +2,7 @@ error[E0308]: mismatched types
--> $DIR/issue-13446.rs:3:26
|
LL | static VEC: [u32; 256] = vec![];
- | ^^^^^^ expected array `[u32; 256]`, found struct `Vec`
+ | ^^^^^^ expected `[u32; 256]`, found `Vec<_>`
|
= note: expected array `[u32; 256]`
found struct `Vec<_>`
diff --git a/tests/ui/issues/issue-13466.rs b/tests/ui/issues/issue-13466.rs
index a420c7704..52d4d75d2 100644
--- a/tests/ui/issues/issue-13466.rs
+++ b/tests/ui/issues/issue-13466.rs
@@ -9,12 +9,12 @@ pub fn main() {
//~^ ERROR mismatched types
//~| expected enum `Option<{integer}>`
//~| found enum `Result<_, _>`
- //~| expected enum `Option`, found enum `Result`
+ //~| expected `Option<{integer}>`, found `Result<_, _>`
Err(e) => panic!(e)
//~^ ERROR mismatched types
//~| expected enum `Option<{integer}>`
//~| found enum `Result<_, _>`
- //~| expected enum `Option`, found enum `Result`
+ //~| expected `Option<{integer}>`, found `Result<_, _>`
};
}
diff --git a/tests/ui/issues/issue-13466.stderr b/tests/ui/issues/issue-13466.stderr
index c78466f4e..fd928e458 100644
--- a/tests/ui/issues/issue-13466.stderr
+++ b/tests/ui/issues/issue-13466.stderr
@@ -4,7 +4,7 @@ error[E0308]: mismatched types
LL | let _x: usize = match Some(1) {
| ------- this expression has type `Option<{integer}>`
LL | Ok(u) => u,
- | ^^^^^ expected enum `Option`, found enum `Result`
+ | ^^^^^ expected `Option<{integer}>`, found `Result<_, _>`
|
= note: expected enum `Option<{integer}>`
found enum `Result<_, _>`
@@ -16,7 +16,7 @@ LL | let _x: usize = match Some(1) {
| ------- this expression has type `Option<{integer}>`
...
LL | Err(e) => panic!(e)
- | ^^^^^^ expected enum `Option`, found enum `Result`
+ | ^^^^^^ expected `Option<{integer}>`, found `Result<_, _>`
|
= note: expected enum `Option<{integer}>`
found enum `Result<_, _>`
diff --git a/tests/ui/issues/issue-14541.rs b/tests/ui/issues/issue-14541.rs
index 555ec9f98..2ff1c1f88 100644
--- a/tests/ui/issues/issue-14541.rs
+++ b/tests/ui/issues/issue-14541.rs
@@ -4,7 +4,7 @@ struct Vec3 { y: f32, z: f32 }
fn make(v: Vec2) {
let Vec3 { y: _, z: _ } = v;
//~^ ERROR mismatched types
- //~| expected struct `Vec2`, found struct `Vec3`
+ //~| expected `Vec2`, found `Vec3`
}
fn main() { }
diff --git a/tests/ui/issues/issue-14541.stderr b/tests/ui/issues/issue-14541.stderr
index cf155f428..b80c68ce4 100644
--- a/tests/ui/issues/issue-14541.stderr
+++ b/tests/ui/issues/issue-14541.stderr
@@ -4,7 +4,7 @@ error[E0308]: mismatched types
LL | let Vec3 { y: _, z: _ } = v;
| ^^^^^^^^^^^^^^^^^^^ - this expression has type `Vec2`
| |
- | expected struct `Vec2`, found struct `Vec3`
+ | expected `Vec2`, found `Vec3`
error: aborting due to previous error
diff --git a/tests/ui/issues/issue-15783.rs b/tests/ui/issues/issue-15783.rs
index 0b1f4545e..ceb37a20e 100644
--- a/tests/ui/issues/issue-15783.rs
+++ b/tests/ui/issues/issue-15783.rs
@@ -9,6 +9,6 @@ fn main() {
//~^ ERROR mismatched types
//~| expected enum `Option<&[&str]>`
//~| found enum `Option<&[&str; 1]>`
- //~| expected slice `[&str]`, found array `[&str; 1]`
+ //~| expected `Option<&[&str]>`, found `Option<&[&str; 1]>`
assert_eq!(msg, 3);
}
diff --git a/tests/ui/issues/issue-15783.stderr b/tests/ui/issues/issue-15783.stderr
index 660dfe9ed..598ec7e60 100644
--- a/tests/ui/issues/issue-15783.stderr
+++ b/tests/ui/issues/issue-15783.stderr
@@ -2,7 +2,7 @@ error[E0308]: mismatched types
--> $DIR/issue-15783.rs:8:19
|
LL | let msg = foo(x);
- | --- ^ expected slice `[&str]`, found array `[&str; 1]`
+ | --- ^ expected `Option<&[&str]>`, found `Option<&[&str; 1]>`
| |
| arguments to this function are incorrect
|
diff --git a/tests/ui/issues/issue-15896.stderr b/tests/ui/issues/issue-15896.stderr
index 038337f5a..ec0d74596 100644
--- a/tests/ui/issues/issue-15896.stderr
+++ b/tests/ui/issues/issue-15896.stderr
@@ -5,7 +5,7 @@ LL | let u = match e {
| - this expression has type `E`
LL | E::B(
LL | Tau{t: x},
- | ^^^^^^^^^ expected enum `R`, found struct `Tau`
+ | ^^^^^^^^^ expected `R`, found `Tau`
error: aborting due to previous error
diff --git a/tests/ui/issues/issue-16338.stderr b/tests/ui/issues/issue-16338.stderr
index 6878600b0..0f08485e5 100644
--- a/tests/ui/issues/issue-16338.stderr
+++ b/tests/ui/issues/issue-16338.stderr
@@ -4,7 +4,7 @@ error[E0308]: mismatched types
LL | let Slice { data: data, len: len } = "foo";
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ----- this expression has type `&str`
| |
- | expected `str`, found struct `Slice`
+ | expected `str`, found `Slice<_>`
|
= note: expected type `str`
found struct `Slice<_>`
diff --git a/tests/ui/issues/issue-16401.rs b/tests/ui/issues/issue-16401.rs
index 332352ca7..19ae7da10 100644
--- a/tests/ui/issues/issue-16401.rs
+++ b/tests/ui/issues/issue-16401.rs
@@ -9,7 +9,7 @@ fn main() {
//~^ ERROR mismatched types
//~| expected unit type `()`
//~| found struct `Slice<_>`
- //~| expected `()`, found struct `Slice`
+ //~| expected `()`, found `Slice<_>`
_ => unreachable!()
}
}
diff --git a/tests/ui/issues/issue-16401.stderr b/tests/ui/issues/issue-16401.stderr
index f8ea09070..02f9f3ea8 100644
--- a/tests/ui/issues/issue-16401.stderr
+++ b/tests/ui/issues/issue-16401.stderr
@@ -4,7 +4,7 @@ error[E0308]: mismatched types
LL | match () {
| -- this expression has type `()`
LL | Slice { data: data, len: len } => (),
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found struct `Slice`
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found `Slice<_>`
|
= note: expected unit type `()`
found struct `Slice<_>`
diff --git a/tests/ui/issues/issue-16939.stderr b/tests/ui/issues/issue-16939.stderr
index 766456454..6db29bc61 100644
--- a/tests/ui/issues/issue-16939.stderr
+++ b/tests/ui/issues/issue-16939.stderr
@@ -2,17 +2,16 @@ error[E0057]: this function takes 0 arguments but 1 argument was supplied
--> $DIR/issue-16939.rs:5:9
|
LL | |t| f(t);
- | ^ - argument unexpected
+ | ^ -
+ | |
+ | unexpected argument
+ | help: remove the extra argument
|
note: callable defined here
--> $DIR/issue-16939.rs:4:12
|
LL | fn _foo<F: Fn()> (f: F) {
| ^^^^
-help: remove the extra argument
- |
-LL | |t| f();
- | ~~
error: aborting due to previous error
diff --git a/tests/ui/issues/issue-16966.stderr b/tests/ui/issues/issue-16966.stderr
index 60f5190db..8c92505b5 100644
--- a/tests/ui/issues/issue-16966.stderr
+++ b/tests/ui/issues/issue-16966.stderr
@@ -1,10 +1,8 @@
error[E0282]: type annotations needed
- --> $DIR/issue-16966.rs:2:5
+ --> $DIR/issue-16966.rs:2:12
|
LL | panic!(std::default::Default::default());
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type of the type parameter `M` declared on the function `begin_panic`
- |
- = note: this error originates in the macro `$crate::panic::panic_2015` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info)
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type
error: aborting due to previous error
diff --git a/tests/ui/issues/issue-17337.stderr b/tests/ui/issues/issue-17337.stderr
index 34c2eb05f..55e51e566 100644
--- a/tests/ui/issues/issue-17337.stderr
+++ b/tests/ui/issues/issue-17337.stderr
@@ -1,4 +1,4 @@
-error: use of deprecated associated function `Foo::foo`: text
+error: use of deprecated method `Foo::foo`: text
--> $DIR/issue-17337.rs:16:6
|
LL | .foo();
diff --git a/tests/ui/issues/issue-18423.rs b/tests/ui/issues/issue-18423.rs
index a81b32f05..675fd0411 100644
--- a/tests/ui/issues/issue-18423.rs
+++ b/tests/ui/issues/issue-18423.rs
@@ -2,7 +2,7 @@
struct Foo<'a> {
x: Box<'a, isize>
- //~^ ERROR this struct takes 0 lifetime arguments but 1 lifetime argument was supplied
+ //~^ ERROR struct takes 0 lifetime arguments but 1 lifetime argument was supplied
}
fn main() { }
diff --git a/tests/ui/issues/issue-18423.stderr b/tests/ui/issues/issue-18423.stderr
index bbf793662..5d154dbbb 100644
--- a/tests/ui/issues/issue-18423.stderr
+++ b/tests/ui/issues/issue-18423.stderr
@@ -1,4 +1,4 @@
-error[E0107]: this struct takes 0 lifetime arguments but 1 lifetime argument was supplied
+error[E0107]: struct takes 0 lifetime arguments but 1 lifetime argument was supplied
--> $DIR/issue-18423.rs:4:8
|
LL | x: Box<'a, isize>
diff --git a/tests/ui/issues/issue-18446.stderr b/tests/ui/issues/issue-18446.stderr
index 939cf0292..602b80c68 100644
--- a/tests/ui/issues/issue-18446.stderr
+++ b/tests/ui/issues/issue-18446.stderr
@@ -14,7 +14,7 @@ note: candidate #2 is defined in the trait `T`
|
LL | fn foo(&self);
| ^^^^^^^^^^^^^^
-help: disambiguate the associated function for candidate #2
+help: disambiguate the method for candidate #2
|
LL | T::foo(&x);
| ~~~~~~~~~~
diff --git a/tests/ui/issues/issue-18819.stderr b/tests/ui/issues/issue-18819.stderr
index 767fdd5ca..1fc974b60 100644
--- a/tests/ui/issues/issue-18819.stderr
+++ b/tests/ui/issues/issue-18819.stderr
@@ -4,7 +4,7 @@ error[E0061]: this function takes 2 arguments but 1 argument was supplied
LL | print_x(X);
| ^^^^^^^--- an argument of type `&str` is missing
|
-note: expected reference, found struct `X`
+note: expected `&dyn Foo<Item = bool>`, found `X`
--> $DIR/issue-18819.rs:16:13
|
LL | print_x(X);
diff --git a/tests/ui/issues/issue-19521.stderr b/tests/ui/issues/issue-19521.stderr
index b6847cd75..13a12acb3 100644
--- a/tests/ui/issues/issue-19521.stderr
+++ b/tests/ui/issues/issue-19521.stderr
@@ -2,7 +2,7 @@ error[E0599]: no method named `homura` found for reference `&'static str` in the
--> $DIR/issue-19521.rs:2:8
|
LL | "".homura()();
- | ^^^^^^ method not found in `&'static str`
+ | ^^^^^^ method not found in `&str`
error: aborting due to previous error
diff --git a/tests/ui/issues/issue-20225.stderr b/tests/ui/issues/issue-20225.stderr
index 582216010..b1c156720 100644
--- a/tests/ui/issues/issue-20225.stderr
+++ b/tests/ui/issues/issue-20225.stderr
@@ -6,7 +6,7 @@ LL | impl<'a, T> Fn<(&'a T,)> for Foo {
LL | extern "rust-call" fn call(&self, (_,): (T,)) {}
| ^^^^
| |
- | expected `&T`, found type parameter `T`
+ | expected `&'a T`, found type parameter `T`
| help: change the parameter type to match the trait: `(&'a T,)`
|
= note: expected signature `extern "rust-call" fn(&Foo, (&'a T,))`
@@ -20,7 +20,7 @@ LL | impl<'a, T> FnMut<(&'a T,)> for Foo {
LL | extern "rust-call" fn call_mut(&mut self, (_,): (T,)) {}
| ^^^^
| |
- | expected `&T`, found type parameter `T`
+ | expected `&'a T`, found type parameter `T`
| help: change the parameter type to match the trait: `(&'a T,)`
|
= note: expected signature `extern "rust-call" fn(&mut Foo, (&'a T,))`
@@ -35,7 +35,7 @@ LL | impl<'a, T> FnOnce<(&'a T,)> for Foo {
LL | extern "rust-call" fn call_once(self, (_,): (T,)) {}
| ^^^^
| |
- | expected `&T`, found type parameter `T`
+ | expected `&'a T`, found type parameter `T`
| help: change the parameter type to match the trait: `(&'a T,)`
|
= note: expected signature `extern "rust-call" fn(Foo, (&'a T,))`
diff --git a/tests/ui/issues/issue-21202.rs b/tests/ui/issues/issue-21202.rs
index f62de7ce7..2c5f13944 100644
--- a/tests/ui/issues/issue-21202.rs
+++ b/tests/ui/issues/issue-21202.rs
@@ -8,7 +8,7 @@ mod B {
use crate1::A::Foo;
fn bar(f: Foo) {
Foo::foo(&f);
- //~^ ERROR: associated function `foo` is private
+ //~^ ERROR: method `foo` is private
}
}
diff --git a/tests/ui/issues/issue-21202.stderr b/tests/ui/issues/issue-21202.stderr
index 1d2816fed..e7c3f2f9a 100644
--- a/tests/ui/issues/issue-21202.stderr
+++ b/tests/ui/issues/issue-21202.stderr
@@ -1,13 +1,13 @@
-error[E0624]: associated function `foo` is private
+error[E0624]: method `foo` is private
--> $DIR/issue-21202.rs:10:14
|
LL | Foo::foo(&f);
- | ^^^ private associated function
+ | ^^^ private method
|
::: $DIR/auxiliary/issue-21202.rs:4:9
|
LL | fn foo(&self) { }
- | ------------- private associated function defined here
+ | ------------- private method defined here
error: aborting due to previous error
diff --git a/tests/ui/issues/issue-21332.rs b/tests/ui/issues/issue-21332.rs
index 6547f3a9b..4473d00fd 100644
--- a/tests/ui/issues/issue-21332.rs
+++ b/tests/ui/issues/issue-21332.rs
@@ -4,7 +4,7 @@ impl Iterator for S {
type Item = i32;
fn next(&mut self) -> Result<i32, i32> { Ok(7) }
//~^ ERROR method `next` has an incompatible type for trait
- //~| expected enum `Option`, found enum `Result`
+ //~| expected `Option<i32>`, found `Result<i32, i32>`
}
fn main() {}
diff --git a/tests/ui/issues/issue-21332.stderr b/tests/ui/issues/issue-21332.stderr
index 0e1beebf2..825492880 100644
--- a/tests/ui/issues/issue-21332.stderr
+++ b/tests/ui/issues/issue-21332.stderr
@@ -4,7 +4,7 @@ error[E0053]: method `next` has an incompatible type for trait
LL | fn next(&mut self) -> Result<i32, i32> { Ok(7) }
| ^^^^^^^^^^^^^^^^
| |
- | expected enum `Option`, found enum `Result`
+ | expected `Option<i32>`, found `Result<i32, i32>`
| help: change the output type to match the trait: `Option<i32>`
|
= note: expected signature `fn(&mut S) -> Option<i32>`
diff --git a/tests/ui/issues/issue-23041.stderr b/tests/ui/issues/issue-23041.stderr
index 6592b76a3..4271c67c3 100644
--- a/tests/ui/issues/issue-23041.stderr
+++ b/tests/ui/issues/issue-23041.stderr
@@ -2,7 +2,7 @@ error[E0282]: type annotations needed
--> $DIR/issue-23041.rs:6:7
|
LL | b.downcast_ref::<fn(_)->_>();
- | ^^^^^^^^^^^^ cannot infer type of the type parameter `T` declared on the associated function `downcast_ref`
+ | ^^^^^^^^^^^^ cannot infer type of the type parameter `T` declared on the method `downcast_ref`
|
help: consider specifying the generic argument
|
diff --git a/tests/ui/issues/issue-24322.stderr b/tests/ui/issues/issue-24322.stderr
index 1e4c8ac7c..954fd4928 100644
--- a/tests/ui/issues/issue-24322.stderr
+++ b/tests/ui/issues/issue-24322.stderr
@@ -2,7 +2,7 @@ error[E0308]: mismatched types
--> $DIR/issue-24322.rs:8:29
|
LL | let x: &fn(&B) -> u32 = &B::func;
- | -------------- ^^^^^^^^ expected fn pointer, found fn item
+ | -------------- ^^^^^^^^ expected `&fn(&B) -> u32`, found `&fn(&B) -> u32 {B::func}`
| |
| expected due to this
|
diff --git a/tests/ui/issues/issue-24819.rs b/tests/ui/issues/issue-24819.rs
index 59c3f2cd1..fb4cfb7b2 100644
--- a/tests/ui/issues/issue-24819.rs
+++ b/tests/ui/issues/issue-24819.rs
@@ -4,7 +4,7 @@ fn main() {
let mut v = Vec::new();
foo(&mut v);
//~^ ERROR mismatched types
- //~| expected struct `HashSet`, found struct `Vec`
+ //~| expected `&mut HashSet<u32>`, found `&mut Vec<_>`
}
fn foo(h: &mut HashSet<u32>) {
diff --git a/tests/ui/issues/issue-24819.stderr b/tests/ui/issues/issue-24819.stderr
index 982a11fef..8b4f1dbce 100644
--- a/tests/ui/issues/issue-24819.stderr
+++ b/tests/ui/issues/issue-24819.stderr
@@ -2,7 +2,7 @@ error[E0308]: mismatched types
--> $DIR/issue-24819.rs:5:9
|
LL | foo(&mut v);
- | --- ^^^^^^ expected struct `HashSet`, found struct `Vec`
+ | --- ^^^^^^ expected `&mut HashSet<u32>`, found `&mut Vec<_>`
| |
| arguments to this function are incorrect
|
diff --git a/tests/ui/issues/issue-26094.rs b/tests/ui/issues/issue-26094.rs
index d3d670aa9..2742529ed 100644
--- a/tests/ui/issues/issue-26094.rs
+++ b/tests/ui/issues/issue-26094.rs
@@ -1,7 +1,7 @@
macro_rules! some_macro {
- ($other: expr) => ({
- $other(None) //~ NOTE argument of type `Option<_>` unexpected
- })
+ ($other: expr) => {{
+ $other(None) //~ NOTE unexpected argument of type `Option<_>`
+ }};
}
fn some_function() {} //~ NOTE defined here
@@ -9,5 +9,4 @@ fn some_function() {} //~ NOTE defined here
fn main() {
some_macro!(some_function);
//~^ ERROR function takes 0 arguments but 1 argument was supplied
- //~| NOTE in this expansion of some_macro!
}
diff --git a/tests/ui/issues/issue-26094.stderr b/tests/ui/issues/issue-26094.stderr
index 881a6e538..ecdf48470 100644
--- a/tests/ui/issues/issue-26094.stderr
+++ b/tests/ui/issues/issue-26094.stderr
@@ -2,7 +2,7 @@ error[E0061]: this function takes 0 arguments but 1 argument was supplied
--> $DIR/issue-26094.rs:10:17
|
LL | $other(None)
- | ---- argument of type `Option<_>` unexpected
+ | ---- unexpected argument of type `Option<_>`
...
LL | some_macro!(some_function);
| ^^^^^^^^^^^^^
@@ -12,10 +12,6 @@ note: function defined here
|
LL | fn some_function() {}
| ^^^^^^^^^^^^^
-help: remove the extra argument
- |
-LL | some_function()
- | ~~~~~~~~~~~~~~~
error: aborting due to previous error
diff --git a/tests/ui/issues/issue-27008.rs b/tests/ui/issues/issue-27008.rs
index e04de33f6..adf8e779e 100644
--- a/tests/ui/issues/issue-27008.rs
+++ b/tests/ui/issues/issue-27008.rs
@@ -3,5 +3,5 @@ struct S;
fn main() {
let b = [0; S];
//~^ ERROR mismatched types
- //~| expected `usize`, found struct `S`
+ //~| expected `usize`, found `S`
}
diff --git a/tests/ui/issues/issue-27008.stderr b/tests/ui/issues/issue-27008.stderr
index 5b7e74c1c..9d18045aa 100644
--- a/tests/ui/issues/issue-27008.stderr
+++ b/tests/ui/issues/issue-27008.stderr
@@ -2,7 +2,7 @@ error[E0308]: mismatched types
--> $DIR/issue-27008.rs:4:17
|
LL | let b = [0; S];
- | ^ expected `usize`, found struct `S`
+ | ^ expected `usize`, found `S`
error: aborting due to previous error
diff --git a/tests/ui/issues/issue-30123.stderr b/tests/ui/issues/issue-30123.stderr
index 7808cbf8a..a00a1dbb8 100644
--- a/tests/ui/issues/issue-30123.stderr
+++ b/tests/ui/issues/issue-30123.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no function or associated item named `new_undirected` found for struct `Graph<i32, i32>` in the current scope
+error[E0599]: no function or associated item named `new_undirected` found for struct `issue_30123_aux::Graph<i32, i32>` in the current scope
--> $DIR/issue-30123.rs:7:33
|
LL | let ug = Graph::<i32, i32>::new_undirected();
diff --git a/tests/ui/issues/issue-30438-c.rs b/tests/ui/issues/issue-30438-c.rs
index 4cf634245..813c1d3e2 100644
--- a/tests/ui/issues/issue-30438-c.rs
+++ b/tests/ui/issues/issue-30438-c.rs
@@ -5,7 +5,6 @@ trait Trait { type Out; }
struct Test<'a> { s: &'a str }
fn silly<'y, 'z>(_s: &'y Test<'z>) -> &'y <Test<'z> as Trait>::Out where 'z: 'static {
- //~^ WARN unnecessary lifetime parameter `'z`
let x = Test { s: "this cannot last" };
&x
//~^ ERROR: cannot return reference to local variable `x`
diff --git a/tests/ui/issues/issue-30438-c.stderr b/tests/ui/issues/issue-30438-c.stderr
index a7a5c0500..7c0010880 100644
--- a/tests/ui/issues/issue-30438-c.stderr
+++ b/tests/ui/issues/issue-30438-c.stderr
@@ -1,17 +1,9 @@
-warning: unnecessary lifetime parameter `'z`
- --> $DIR/issue-30438-c.rs:7:74
- |
-LL | fn silly<'y, 'z>(_s: &'y Test<'z>) -> &'y <Test<'z> as Trait>::Out where 'z: 'static {
- | ^^
- |
- = help: you can use the `'static` lifetime directly, in place of `'z`
-
error[E0515]: cannot return reference to local variable `x`
- --> $DIR/issue-30438-c.rs:10:5
+ --> $DIR/issue-30438-c.rs:9:5
|
LL | &x
| ^^ returns a reference to data owned by the current function
-error: aborting due to previous error; 1 warning emitted
+error: aborting due to previous error
For more information about this error, try `rustc --explain E0515`.
diff --git a/tests/ui/issues/issue-32122-1.stderr b/tests/ui/issues/issue-32122-1.stderr
index 10b0c0967..b4f5b1296 100644
--- a/tests/ui/issues/issue-32122-1.stderr
+++ b/tests/ui/issues/issue-32122-1.stderr
@@ -2,7 +2,7 @@ error[E0308]: mismatched types
--> $DIR/issue-32122-1.rs:16:24
|
LL | let _: *const u8 = &a;
- | --------- ^^ expected `u8`, found struct `Foo`
+ | --------- ^^ expected `*const u8`, found `&Foo`
| |
| expected due to this
|
diff --git a/tests/ui/issues/issue-32122-2.stderr b/tests/ui/issues/issue-32122-2.stderr
index 5c3dade8e..02c335c15 100644
--- a/tests/ui/issues/issue-32122-2.stderr
+++ b/tests/ui/issues/issue-32122-2.stderr
@@ -2,7 +2,7 @@ error[E0308]: mismatched types
--> $DIR/issue-32122-2.rs:27:24
|
LL | let _: *const u8 = &a;
- | --------- ^^ expected `u8`, found struct `Emm`
+ | --------- ^^ expected `*const u8`, found `&Emm`
| |
| expected due to this
|
diff --git a/tests/ui/issues/issue-3214.rs b/tests/ui/issues/issue-3214.rs
index 928a65938..e3c07bb3f 100644
--- a/tests/ui/issues/issue-3214.rs
+++ b/tests/ui/issues/issue-3214.rs
@@ -4,7 +4,7 @@ fn foo<T>() {
}
impl<T> Drop for Foo<T> {
- //~^ ERROR this struct takes 0 generic arguments but 1 generic argument
+ //~^ ERROR struct takes 0 generic arguments but 1 generic argument
fn drop(&mut self) {}
}
}
diff --git a/tests/ui/issues/issue-3214.stderr b/tests/ui/issues/issue-3214.stderr
index aa0b5ce64..7a2d772f0 100644
--- a/tests/ui/issues/issue-3214.stderr
+++ b/tests/ui/issues/issue-3214.stderr
@@ -8,7 +8,7 @@ LL | struct Foo {
LL | x: T,
| ^ use of generic parameter from outer function
-error[E0107]: this struct takes 0 generic arguments but 1 generic argument was supplied
+error[E0107]: struct takes 0 generic arguments but 1 generic argument was supplied
--> $DIR/issue-3214.rs:6:22
|
LL | impl<T> Drop for Foo<T> {
diff --git a/tests/ui/issues/issue-33504.stderr b/tests/ui/issues/issue-33504.stderr
index d9e7c3b16..a831cf585 100644
--- a/tests/ui/issues/issue-33504.stderr
+++ b/tests/ui/issues/issue-33504.stderr
@@ -7,7 +7,7 @@ LL | struct Test;
LL | let Test = 1;
| ^^^^ - this expression has type `{integer}`
| |
- | expected integer, found struct `Test`
+ | expected integer, found `Test`
| `Test` is interpreted as a unit struct, not a new binding
| help: introduce a new binding instead: `other_test`
diff --git a/tests/ui/issues/issue-33941.stderr b/tests/ui/issues/issue-33941.stderr
index 668eaabca..e7f4a4fa0 100644
--- a/tests/ui/issues/issue-33941.stderr
+++ b/tests/ui/issues/issue-33941.stderr
@@ -2,7 +2,7 @@ error[E0271]: expected `Iter<'_, _, _>` to be an iterator that yields `&_`, but
--> $DIR/issue-33941.rs:6:36
|
LL | for _ in HashMap::new().iter().cloned() {}
- | ^^^^^^ expected reference, found tuple
+ | ^^^^^^ expected `&_`, found `(&_, &_)`
|
= note: expected reference `&_`
found tuple `(&_, &_)`
@@ -20,7 +20,7 @@ error[E0271]: expected `Iter<'_, _, _>` to be an iterator that yields `&_`, but
--> $DIR/issue-33941.rs:6:14
|
LL | for _ in HashMap::new().iter().cloned() {}
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected tuple, found reference
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `(&_, &_)`, found `&_`
|
= note: expected tuple `(&_, &_)`
found reference `&_`
@@ -31,7 +31,7 @@ error[E0271]: expected `Iter<'_, _, _>` to be an iterator that yields `&_`, but
--> $DIR/issue-33941.rs:6:14
|
LL | for _ in HashMap::new().iter().cloned() {}
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected tuple, found reference
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `(&_, &_)`, found `&_`
|
= note: expected tuple `(&_, &_)`
found reference `&_`
diff --git a/tests/ui/issues/issue-35241.stderr b/tests/ui/issues/issue-35241.stderr
index d600e934b..4a2c15511 100644
--- a/tests/ui/issues/issue-35241.stderr
+++ b/tests/ui/issues/issue-35241.stderr
@@ -5,7 +5,7 @@ LL | struct Foo(u32);
| ---------- `Foo` defines a struct constructor here, which should be called
LL |
LL | fn test() -> Foo { Foo }
- | --- ^^^ expected struct `Foo`, found struct constructor
+ | --- ^^^ expected `Foo`, found struct constructor
| |
| expected `Foo` because of return type
|
diff --git a/tests/ui/issues/issue-3680.rs b/tests/ui/issues/issue-3680.rs
index 37c9000c0..a0e527981 100644
--- a/tests/ui/issues/issue-3680.rs
+++ b/tests/ui/issues/issue-3680.rs
@@ -4,6 +4,6 @@ fn main() {
//~^ ERROR mismatched types
//~| expected enum `Option<_>`
//~| found enum `Result<_, _>`
- //~| expected enum `Option`, found enum `Result`
+ //~| expected `Option<_>`, found `Result<_, _>`
}
}
diff --git a/tests/ui/issues/issue-3680.stderr b/tests/ui/issues/issue-3680.stderr
index 29ba44f13..0b0ae419e 100644
--- a/tests/ui/issues/issue-3680.stderr
+++ b/tests/ui/issues/issue-3680.stderr
@@ -4,7 +4,7 @@ error[E0308]: mismatched types
LL | match None {
| ---- this expression has type `Option<_>`
LL | Err(_) => ()
- | ^^^^^^ expected enum `Option`, found enum `Result`
+ | ^^^^^^ expected `Option<_>`, found `Result<_, _>`
|
= note: expected enum `Option<_>`
found enum `Result<_, _>`
diff --git a/tests/ui/issues/issue-3702-2.stderr b/tests/ui/issues/issue-3702-2.stderr
index 1fd64ca90..0b94c3135 100644
--- a/tests/ui/issues/issue-3702-2.stderr
+++ b/tests/ui/issues/issue-3702-2.stderr
@@ -14,11 +14,11 @@ note: candidate #2 is defined in an impl of the trait `Add` for the type `isize`
|
LL | fn to_int(&self) -> isize { *self }
| ^^^^^^^^^^^^^^^^^^^^^^^^^
-help: disambiguate the associated function for candidate #1
+help: disambiguate the method for candidate #1
|
LL | ToPrimitive::to_int(&self) + other.to_int()
| ~~~~~~~~~~~~~~~~~~~~~~~~~~
-help: disambiguate the associated function for candidate #2
+help: disambiguate the method for candidate #2
|
LL | Add::to_int(&self) + other.to_int()
| ~~~~~~~~~~~~~~~~~~
diff --git a/tests/ui/issues/issue-3763.rs b/tests/ui/issues/issue-3763.rs
index 25ad6b319..893009a2c 100644
--- a/tests/ui/issues/issue-3763.rs
+++ b/tests/ui/issues/issue-3763.rs
@@ -1,5 +1,4 @@
-// compile-flags: -Zsave-analysis
-// Also regression test for #69416
+// Regression test for #3763
mod my_mod {
pub struct MyStruct {
@@ -21,9 +20,9 @@ fn main() {
let _woohoo = (Box::new(my_struct)).priv_field;
//~^ ERROR field `priv_field` of struct `MyStruct` is private
- (&my_struct).happyfun(); //~ ERROR associated function `happyfun` is private
+ (&my_struct).happyfun(); //~ ERROR method `happyfun` is private
- (Box::new(my_struct)).happyfun(); //~ ERROR associated function `happyfun` is private
+ (Box::new(my_struct)).happyfun(); //~ ERROR method `happyfun` is private
let nope = my_struct.priv_field;
//~^ ERROR field `priv_field` of struct `MyStruct` is private
}
diff --git a/tests/ui/issues/issue-3763.stderr b/tests/ui/issues/issue-3763.stderr
index 6f4567546..d101e4c33 100644
--- a/tests/ui/issues/issue-3763.stderr
+++ b/tests/ui/issues/issue-3763.stderr
@@ -1,35 +1,35 @@
error[E0616]: field `priv_field` of struct `MyStruct` is private
- --> $DIR/issue-3763.rs:18:32
+ --> $DIR/issue-3763.rs:17:32
|
LL | let _woohoo = (&my_struct).priv_field;
| ^^^^^^^^^^ private field
error[E0616]: field `priv_field` of struct `MyStruct` is private
- --> $DIR/issue-3763.rs:21:41
+ --> $DIR/issue-3763.rs:20:41
|
LL | let _woohoo = (Box::new(my_struct)).priv_field;
| ^^^^^^^^^^ private field
-error[E0624]: associated function `happyfun` is private
- --> $DIR/issue-3763.rs:24:18
+error[E0624]: method `happyfun` is private
+ --> $DIR/issue-3763.rs:23:18
|
LL | fn happyfun(&self) {}
- | ------------------ private associated function defined here
+ | ------------------ private method defined here
...
LL | (&my_struct).happyfun();
- | ^^^^^^^^ private associated function
+ | ^^^^^^^^ private method
-error[E0624]: associated function `happyfun` is private
- --> $DIR/issue-3763.rs:26:27
+error[E0624]: method `happyfun` is private
+ --> $DIR/issue-3763.rs:25:27
|
LL | fn happyfun(&self) {}
- | ------------------ private associated function defined here
+ | ------------------ private method defined here
...
LL | (Box::new(my_struct)).happyfun();
- | ^^^^^^^^ private associated function
+ | ^^^^^^^^ private method
error[E0616]: field `priv_field` of struct `MyStruct` is private
- --> $DIR/issue-3763.rs:27:26
+ --> $DIR/issue-3763.rs:26:26
|
LL | let nope = my_struct.priv_field;
| ^^^^^^^^^^ private field
diff --git a/tests/ui/issues/issue-39970.rs b/tests/ui/issues/issue-39970.rs
index f51e3b522..40d3ae30a 100644
--- a/tests/ui/issues/issue-39970.rs
+++ b/tests/ui/issues/issue-39970.rs
@@ -17,5 +17,5 @@ impl Visit for () where
fn main() {
<() as Visit>::visit();
- //~^ ERROR type mismatch resolving `for<'a> <() as Array<'a>>::Element == ()`
+ //~^ ERROR type mismatch resolving `<() as Array<'a>>::Element == ()`
}
diff --git a/tests/ui/issues/issue-39970.stderr b/tests/ui/issues/issue-39970.stderr
index 0cabdf7f2..8344b88c3 100644
--- a/tests/ui/issues/issue-39970.stderr
+++ b/tests/ui/issues/issue-39970.stderr
@@ -1,8 +1,8 @@
-error[E0271]: type mismatch resolving `for<'a> <() as Array<'a>>::Element == ()`
+error[E0271]: type mismatch resolving `<() as Array<'a>>::Element == ()`
--> $DIR/issue-39970.rs:19:5
|
LL | <() as Visit>::visit();
- | ^^^^^^^^^^^^^^^^^^^^ type mismatch resolving `for<'a> <() as Array<'a>>::Element == ()`
+ | ^^^^^^^^^^^^^^^^^^^^ type mismatch resolving `<() as Array<'a>>::Element == ()`
|
note: expected this to be `()`
--> $DIR/issue-39970.rs:10:20
diff --git a/tests/ui/issues/issue-40288.stderr b/tests/ui/issues/issue-40288.stderr
index fb4ecab36..db5d06437 100644
--- a/tests/ui/issues/issue-40288.stderr
+++ b/tests/ui/issues/issue-40288.stderr
@@ -2,10 +2,10 @@ error[E0506]: cannot assign to `*refr` because it is borrowed
--> $DIR/issue-40288.rs:16:5
|
LL | save_ref(&*refr, &mut out);
- | ------ borrow of `*refr` occurs here
+ | ------ `*refr` is borrowed here
...
LL | *refr = 3;
- | ^^^^^^^^^ assignment to borrowed `*refr` occurs here
+ | ^^^^^^^^^ `*refr` is assigned to here but it was already borrowed
...
LL | println!("{:?}", out[0]);
| ------ borrow later used here
diff --git a/tests/ui/issues/issue-40749.stderr b/tests/ui/issues/issue-40749.stderr
index fa239f744..afc39adec 100644
--- a/tests/ui/issues/issue-40749.stderr
+++ b/tests/ui/issues/issue-40749.stderr
@@ -2,7 +2,7 @@ error[E0308]: mismatched types
--> $DIR/issue-40749.rs:2:9
|
LL | [0; ..10];
- | ^^^^ expected `usize`, found struct `RangeTo`
+ | ^^^^ expected `usize`, found `RangeTo<{integer}>`
|
= note: expected type `usize`
found struct `RangeTo<{integer}>`
diff --git a/tests/ui/issues/issue-43420-no-over-suggest.stderr b/tests/ui/issues/issue-43420-no-over-suggest.stderr
index 58fd1121a..9b141e2bf 100644
--- a/tests/ui/issues/issue-43420-no-over-suggest.stderr
+++ b/tests/ui/issues/issue-43420-no-over-suggest.stderr
@@ -2,7 +2,7 @@ error[E0308]: mismatched types
--> $DIR/issue-43420-no-over-suggest.rs:8:9
|
LL | foo(&a);
- | --- ^^ expected slice `[u16]`, found struct `Vec`
+ | --- ^^ expected `&[u16]`, found `&Vec<u8>`
| |
| arguments to this function are incorrect
|
diff --git a/tests/ui/issues/issue-4517.rs b/tests/ui/issues/issue-4517.rs
index caf85d44a..469304e2c 100644
--- a/tests/ui/issues/issue-4517.rs
+++ b/tests/ui/issues/issue-4517.rs
@@ -4,5 +4,5 @@ fn main() {
let foo: [u8; 4] = [1; 4];
bar(foo);
//~^ ERROR mismatched types
- //~| expected `usize`, found array `[u8; 4]`
+ //~| expected `usize`, found `[u8; 4]`
}
diff --git a/tests/ui/issues/issue-4517.stderr b/tests/ui/issues/issue-4517.stderr
index 70b4ca5ec..78ee336f1 100644
--- a/tests/ui/issues/issue-4517.stderr
+++ b/tests/ui/issues/issue-4517.stderr
@@ -2,7 +2,7 @@ error[E0308]: mismatched types
--> $DIR/issue-4517.rs:5:9
|
LL | bar(foo);
- | --- ^^^ expected `usize`, found array `[u8; 4]`
+ | --- ^^^ expected `usize`, found `[u8; 4]`
| |
| arguments to this function are incorrect
|
diff --git a/tests/ui/issues/issue-45697-1.stderr b/tests/ui/issues/issue-45697-1.stderr
index 30c69f196..474313398 100644
--- a/tests/ui/issues/issue-45697-1.stderr
+++ b/tests/ui/issues/issue-45697-1.stderr
@@ -2,7 +2,7 @@ error[E0503]: cannot use `*y.pointer` because it was mutably borrowed
--> $DIR/issue-45697-1.rs:20:9
|
LL | let z = copy_borrowed_ptr(&mut y);
- | ------ borrow of `y` occurs here
+ | ------ `y` is borrowed here
LL | *y.pointer += 1;
| ^^^^^^^^^^^^^^^ use of borrowed `y`
...
@@ -13,9 +13,9 @@ error[E0506]: cannot assign to `*y.pointer` because it is borrowed
--> $DIR/issue-45697-1.rs:20:9
|
LL | let z = copy_borrowed_ptr(&mut y);
- | ------ borrow of `*y.pointer` occurs here
+ | ------ `*y.pointer` is borrowed here
LL | *y.pointer += 1;
- | ^^^^^^^^^^^^^^^ assignment to borrowed `*y.pointer` occurs here
+ | ^^^^^^^^^^^^^^^ `*y.pointer` is assigned to here but it was already borrowed
...
LL | *z.pointer += 1;
| --------------- borrow later used here
diff --git a/tests/ui/issues/issue-45697.stderr b/tests/ui/issues/issue-45697.stderr
index 26749d36f..7986fd5c9 100644
--- a/tests/ui/issues/issue-45697.stderr
+++ b/tests/ui/issues/issue-45697.stderr
@@ -2,7 +2,7 @@ error[E0503]: cannot use `*y.pointer` because it was mutably borrowed
--> $DIR/issue-45697.rs:20:9
|
LL | let z = copy_borrowed_ptr(&mut y);
- | ------ borrow of `y` occurs here
+ | ------ `y` is borrowed here
LL | *y.pointer += 1;
| ^^^^^^^^^^^^^^^ use of borrowed `y`
...
@@ -13,9 +13,9 @@ error[E0506]: cannot assign to `*y.pointer` because it is borrowed
--> $DIR/issue-45697.rs:20:9
|
LL | let z = copy_borrowed_ptr(&mut y);
- | ------ borrow of `*y.pointer` occurs here
+ | ------ `*y.pointer` is borrowed here
LL | *y.pointer += 1;
- | ^^^^^^^^^^^^^^^ assignment to borrowed `*y.pointer` occurs here
+ | ^^^^^^^^^^^^^^^ `*y.pointer` is assigned to here but it was already borrowed
...
LL | *z.pointer += 1;
| --------------- borrow later used here
diff --git a/tests/ui/issues/issue-46471-1.stderr b/tests/ui/issues/issue-46471-1.stderr
index b09f31729..2ae6e709d 100644
--- a/tests/ui/issues/issue-46471-1.stderr
+++ b/tests/ui/issues/issue-46471-1.stderr
@@ -1,11 +1,10 @@
error[E0597]: `z` does not live long enough
--> $DIR/issue-46471-1.rs:4:9
|
+LL | let mut z = 0;
+ | ----- binding `z` declared here
LL | &mut z
- | ^^^^^^
- | |
- | borrowed value does not live long enough
- | borrow later used here
+ | ^^^^^^ borrowed value does not live long enough
LL | };
| - `z` dropped here while still borrowed
diff --git a/tests/ui/issues/issue-47715.stderr b/tests/ui/issues/issue-47715.stderr
index 0ee9388bf..dadea34b6 100644
--- a/tests/ui/issues/issue-47715.stderr
+++ b/tests/ui/issues/issue-47715.stderr
@@ -1,22 +1,22 @@
-error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in generic
+error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in generics
--> $DIR/issue-47715.rs:9:37
|
LL | struct Container<T: Iterable<Item = impl Foo>> {
| ^^^^^^^^
-error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in generic
+error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in generics
--> $DIR/issue-47715.rs:14:30
|
LL | enum Enum<T: Iterable<Item = impl Foo>> {
| ^^^^^^^^
-error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in generic
+error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in generics
--> $DIR/issue-47715.rs:19:32
|
LL | union Union<T: Iterable<Item = impl Foo> + Copy> {
| ^^^^^^^^
-error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in generic
+error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in generics
--> $DIR/issue-47715.rs:24:30
|
LL | type Type<T: Iterable<Item = impl Foo>> = T;
diff --git a/tests/ui/issues/issue-48364.stderr b/tests/ui/issues/issue-48364.stderr
index 60bbfc0c6..cac4af6a7 100644
--- a/tests/ui/issues/issue-48364.stderr
+++ b/tests/ui/issues/issue-48364.stderr
@@ -2,13 +2,13 @@ error[E0308]: mismatched types
--> $DIR/issue-48364.rs:2:21
|
LL | b"".starts_with(stringify!(foo))
- | ----------- ^^^^^^^^^^^^^^^ expected slice `[u8]`, found `str`
+ | ----------- ^^^^^^^^^^^^^^^ expected `&[u8]`, found `&str`
| |
| arguments to this method are incorrect
|
= note: expected reference `&[u8]`
found reference `&'static str`
-note: associated function defined here
+note: method defined here
--> $SRC_DIR/core/src/slice/mod.rs:LL:COL
= note: this error originates in the macro `stringify` (in Nightly builds, run with -Z macro-backtrace for more info)
diff --git a/tests/ui/issues/issue-4935.stderr b/tests/ui/issues/issue-4935.stderr
index bb45fa083..e544e4244 100644
--- a/tests/ui/issues/issue-4935.stderr
+++ b/tests/ui/issues/issue-4935.stderr
@@ -2,17 +2,16 @@ error[E0061]: this function takes 1 argument but 2 arguments were supplied
--> $DIR/issue-4935.rs:5:13
|
LL | fn main() { foo(5, 6) }
- | ^^^ - argument of type `{integer}` unexpected
+ | ^^^ ---
+ | | |
+ | | unexpected argument of type `{integer}`
+ | help: remove the extra argument
|
note: function defined here
--> $DIR/issue-4935.rs:3:4
|
LL | fn foo(a: usize) {}
| ^^^ --------
-help: remove the extra argument
- |
-LL | fn main() { foo(5) }
- | ~~~
error: aborting due to previous error
diff --git a/tests/ui/issues/issue-4968.rs b/tests/ui/issues/issue-4968.rs
index 634bd698d..c8df46dc2 100644
--- a/tests/ui/issues/issue-4968.rs
+++ b/tests/ui/issues/issue-4968.rs
@@ -6,5 +6,5 @@ fn main() {
//~^ ERROR mismatched types
//~| expected type `{integer}`
//~| found tuple `(isize, isize)`
- //~| expected integer, found tuple
+ //~| expected integer, found `(isize, isize)`
}
diff --git a/tests/ui/issues/issue-4968.stderr b/tests/ui/issues/issue-4968.stderr
index bbaca4ed2..1ce033384 100644
--- a/tests/ui/issues/issue-4968.stderr
+++ b/tests/ui/issues/issue-4968.stderr
@@ -7,7 +7,7 @@ LL | fn main() {
LL | match 42 { A => () }
| -- ^
| | |
- | | expected integer, found tuple
+ | | expected integer, found `(isize, isize)`
| | `A` is interpreted as a constant, not a new binding
| | help: introduce a new binding instead: `other_a`
| this expression has type `{integer}`
diff --git a/tests/ui/issues/issue-5100.rs b/tests/ui/issues/issue-5100.rs
index 69ed4b0e4..53ebdec81 100644
--- a/tests/ui/issues/issue-5100.rs
+++ b/tests/ui/issues/issue-5100.rs
@@ -7,7 +7,7 @@ fn main() {
match (true, false) {
A::B => (),
//~^ ERROR mismatched types
-//~| expected tuple, found enum `A`
+//~| expected `(bool, bool)`, found `A`
//~| expected tuple `(bool, bool)`
//~| found enum `A`
_ => ()
@@ -39,7 +39,7 @@ fn main() {
match (true, false) {
&(true, false) => ()
//~^ ERROR mismatched types
-//~| expected tuple, found reference
+//~| expected `(bool, bool)`, found `&_`
//~| expected tuple `(bool, bool)`
//~| found reference `&_`
}
diff --git a/tests/ui/issues/issue-5100.stderr b/tests/ui/issues/issue-5100.stderr
index c87a3e348..b1680aacd 100644
--- a/tests/ui/issues/issue-5100.stderr
+++ b/tests/ui/issues/issue-5100.stderr
@@ -7,7 +7,7 @@ LL | enum A { B, C }
LL | match (true, false) {
| ------------- this expression has type `(bool, bool)`
LL | A::B => (),
- | ^^^^ expected tuple, found enum `A`
+ | ^^^^ expected `(bool, bool)`, found `A`
|
= note: expected tuple `(bool, bool)`
found enum `A`
@@ -40,7 +40,7 @@ error[E0308]: mismatched types
LL | match (true, false) {
| ------------- this expression has type `(bool, bool)`
LL | box (true, false) => ()
- | ^^^^^^^^^^^^^^^^^ expected tuple, found struct `Box`
+ | ^^^^^^^^^^^^^^^^^ expected `(bool, bool)`, found `Box<_>`
|
= note: expected tuple `(bool, bool)`
found struct `Box<_>`
@@ -51,7 +51,7 @@ error[E0308]: mismatched types
LL | match (true, false) {
| ------------- this expression has type `(bool, bool)`
LL | &(true, false) => ()
- | ^^^^^^^^^^^^^^ expected tuple, found reference
+ | ^^^^^^^^^^^^^^ expected `(bool, bool)`, found `&_`
|
= note: expected tuple `(bool, bool)`
found reference `&_`
diff --git a/tests/ui/issues/issue-51515.rs b/tests/ui/issues/issue-51515.rs
index 797c1085d..84e09afac 100644
--- a/tests/ui/issues/issue-51515.rs
+++ b/tests/ui/issues/issue-51515.rs
@@ -5,6 +5,7 @@ fn main() {
*foo = 32;
//~^ ERROR cannot assign to `*foo`, which is behind a `&` reference
let bar = foo;
+ //~^ HELP consider specifying this binding's type
*bar = 64;
//~^ ERROR cannot assign to `*bar`, which is behind a `&` reference
}
diff --git a/tests/ui/issues/issue-51515.stderr b/tests/ui/issues/issue-51515.stderr
index c4e61e719..94e5c9f1b 100644
--- a/tests/ui/issues/issue-51515.stderr
+++ b/tests/ui/issues/issue-51515.stderr
@@ -10,12 +10,15 @@ LL | let foo = &mut 16;
| ~~~~~~~
error[E0594]: cannot assign to `*bar`, which is behind a `&` reference
- --> $DIR/issue-51515.rs:8:5
+ --> $DIR/issue-51515.rs:9:5
|
-LL | let bar = foo;
- | --- consider changing this binding's type to be: `&mut i32`
LL | *bar = 64;
| ^^^^^^^^^ `bar` is a `&` reference, so the data it refers to cannot be written
+ |
+help: consider specifying this binding's type
+ |
+LL | let bar: &mut i32 = foo;
+ | ++++++++++
error: aborting due to 2 previous errors
diff --git a/tests/ui/issues/issue-51632-try-desugar-incompatible-types.stderr b/tests/ui/issues/issue-51632-try-desugar-incompatible-types.stderr
index cc0726bca..7180a3d24 100644
--- a/tests/ui/issues/issue-51632-try-desugar-incompatible-types.stderr
+++ b/tests/ui/issues/issue-51632-try-desugar-incompatible-types.stderr
@@ -2,7 +2,7 @@ error[E0308]: `?` operator has incompatible types
--> $DIR/issue-51632-try-desugar-incompatible-types.rs:8:5
|
LL | missing_discourses()?
- | ^^^^^^^^^^^^^^^^^^^^^ expected enum `Result`, found `isize`
+ | ^^^^^^^^^^^^^^^^^^^^^ expected `Result<isize, ()>`, found `isize`
|
= note: `?` operator cannot convert from `isize` to `Result<isize, ()>`
= note: expected enum `Result<isize, ()>`
diff --git a/tests/ui/issues/issue-52126-assign-op-invariance.stderr b/tests/ui/issues/issue-52126-assign-op-invariance.stderr
index d45067577..2d3b48832 100644
--- a/tests/ui/issues/issue-52126-assign-op-invariance.stderr
+++ b/tests/ui/issues/issue-52126-assign-op-invariance.stderr
@@ -1,6 +1,8 @@
error[E0597]: `line` does not live long enough
--> $DIR/issue-52126-assign-op-invariance.rs:34:28
|
+LL | for line in vec!["123456789".to_string(), "12345678".to_string()] {
+ | ---- binding `line` declared here
LL | let v: Vec<&str> = line.split_whitespace().collect();
| ^^^^^^^^^^^^^^^^^^^^^^^ borrowed value does not live long enough
...
diff --git a/tests/ui/issues/issue-53251.rs b/tests/ui/issues/issue-53251.rs
index 240826a16..da3ba63ef 100644
--- a/tests/ui/issues/issue-53251.rs
+++ b/tests/ui/issues/issue-53251.rs
@@ -9,8 +9,8 @@ macro_rules! impl_add {
$(
fn $n() {
S::f::<i64>();
- //~^ ERROR this associated function takes 0 generic
- //~| ERROR this associated function takes 0 generic
+ //~^ ERROR associated function takes 0 generic
+ //~| ERROR associated function takes 0 generic
}
)*
}
diff --git a/tests/ui/issues/issue-53251.stderr b/tests/ui/issues/issue-53251.stderr
index cee9a5deb..d5f14e8de 100644
--- a/tests/ui/issues/issue-53251.stderr
+++ b/tests/ui/issues/issue-53251.stderr
@@ -1,4 +1,4 @@
-error[E0107]: this associated function takes 0 generic arguments but 1 generic argument was supplied
+error[E0107]: associated function takes 0 generic arguments but 1 generic argument was supplied
--> $DIR/issue-53251.rs:11:20
|
LL | S::f::<i64>();
@@ -16,7 +16,7 @@ LL | fn f() {}
| ^
= note: this error originates in the macro `impl_add` (in Nightly builds, run with -Z macro-backtrace for more info)
-error[E0107]: this associated function takes 0 generic arguments but 1 generic argument was supplied
+error[E0107]: associated function takes 0 generic arguments but 1 generic argument was supplied
--> $DIR/issue-53251.rs:11:20
|
LL | S::f::<i64>();
diff --git a/tests/ui/issues/issue-53348.rs b/tests/ui/issues/issue-53348.rs
index d2f8c77c0..66800d9e9 100644
--- a/tests/ui/issues/issue-53348.rs
+++ b/tests/ui/issues/issue-53348.rs
@@ -9,7 +9,7 @@ fn main() {
for i in v {
a = *i.to_string();
//~^ ERROR mismatched types
- //~| NOTE expected struct `String`, found `str`
+ //~| NOTE expected `String`, found `str`
v2.push(a);
}
}
diff --git a/tests/ui/issues/issue-53348.stderr b/tests/ui/issues/issue-53348.stderr
index 71d9f5b3d..e4cdb7e88 100644
--- a/tests/ui/issues/issue-53348.stderr
+++ b/tests/ui/issues/issue-53348.stderr
@@ -5,7 +5,7 @@ LL | let mut a = String::new();
| ------------- expected due to this value
LL | for i in v {
LL | a = *i.to_string();
- | ^^^^^^^^^^^^^^ expected struct `String`, found `str`
+ | ^^^^^^^^^^^^^^ expected `String`, found `str`
error: aborting due to previous error
diff --git a/tests/ui/issues/issue-5358-1.rs b/tests/ui/issues/issue-5358-1.rs
index f5e32e78d..14ee962b7 100644
--- a/tests/ui/issues/issue-5358-1.rs
+++ b/tests/ui/issues/issue-5358-1.rs
@@ -5,7 +5,7 @@ fn main() {
match S(Either::Left(5)) {
Either::Right(_) => {}
//~^ ERROR mismatched types
- //~| expected struct `S`, found enum `Either`
+ //~| expected `S`, found `Either<_, _>`
//~| expected struct `S`
//~| found enum `Either<_, _>`
_ => {}
diff --git a/tests/ui/issues/issue-5358-1.stderr b/tests/ui/issues/issue-5358-1.stderr
index 9d5b8d9d3..059462a36 100644
--- a/tests/ui/issues/issue-5358-1.stderr
+++ b/tests/ui/issues/issue-5358-1.stderr
@@ -4,7 +4,7 @@ error[E0308]: mismatched types
LL | match S(Either::Left(5)) {
| ------------------ this expression has type `S`
LL | Either::Right(_) => {}
- | ^^^^^^^^^^^^^^^^ expected struct `S`, found enum `Either`
+ | ^^^^^^^^^^^^^^^^ expected `S`, found `Either<_, _>`
|
= note: expected struct `S`
found enum `Either<_, _>`
diff --git a/tests/ui/issues/issue-56943.stderr b/tests/ui/issues/issue-56943.stderr
index 74ed5ec0f..c394e620b 100644
--- a/tests/ui/issues/issue-56943.stderr
+++ b/tests/ui/issues/issue-56943.stderr
@@ -2,7 +2,7 @@ error[E0308]: mismatched types
--> $DIR/issue-56943.rs:6:29
|
LL | let _: issue_56943::S = issue_56943::S2;
- | -------------- ^^^^^^^^^^^^^^^ expected struct `S`, found struct `S2`
+ | -------------- ^^^^^^^^^^^^^^^ expected `S`, found `S2`
| |
| expected due to this
diff --git a/tests/ui/issues/issue-57362-2.stderr b/tests/ui/issues/issue-57362-2.stderr
index 7d08c4643..37beb587d 100644
--- a/tests/ui/issues/issue-57362-2.stderr
+++ b/tests/ui/issues/issue-57362-2.stderr
@@ -1,8 +1,8 @@
-error[E0599]: the function or associated item `make_g` exists for fn pointer `for<'a> fn(&'a ())`, but its trait bounds were not satisfied
+error[E0599]: the function or associated item `make_g` exists for fn pointer `fn(&())`, but its trait bounds were not satisfied
--> $DIR/issue-57362-2.rs:22:25
|
LL | let x = <fn (&())>::make_g();
- | ^^^^^^ function or associated item cannot be called on `for<'a> fn(&'a ())` due to unsatisfied trait bounds
+ | ^^^^^^ function or associated item cannot be called on `fn(&())` due to unsatisfied trait bounds
|
= note: the following trait bounds were not satisfied:
`for<'a> fn(&'a ()): X`
diff --git a/tests/ui/issues/issue-57741-1.stderr b/tests/ui/issues/issue-57741-1.stderr
index 789a1f44d..76f03bab6 100644
--- a/tests/ui/issues/issue-57741-1.stderr
+++ b/tests/ui/issues/issue-57741-1.stderr
@@ -4,7 +4,7 @@ error[E0308]: mismatched types
LL | let y = match x {
| - this expression has type `Box<u32>`
LL | S::A { a } | S::B { b: a } => a,
- | ^^^^^^^^^^ expected struct `Box`, found enum `S`
+ | ^^^^^^^^^^ expected `Box<u32>`, found `S`
|
= note: expected struct `Box<u32>`
found enum `S`
@@ -15,7 +15,7 @@ error[E0308]: mismatched types
LL | let y = match x {
| - this expression has type `Box<u32>`
LL | S::A { a } | S::B { b: a } => a,
- | ^^^^^^^^^^^^^ expected struct `Box`, found enum `S`
+ | ^^^^^^^^^^^^^ expected `Box<u32>`, found `S`
|
= note: expected struct `Box<u32>`
found enum `S`
diff --git a/tests/ui/issues/issue-57741.stderr b/tests/ui/issues/issue-57741.stderr
index cd277f20e..38014ecce 100644
--- a/tests/ui/issues/issue-57741.stderr
+++ b/tests/ui/issues/issue-57741.stderr
@@ -7,7 +7,7 @@ LL | let y = match x {
| this expression has type `Box<T>`
| help: consider dereferencing the boxed value: `*x`
LL | T::A(a) | T::B(a) => a,
- | ^^^^^^^ expected struct `Box`, found enum `T`
+ | ^^^^^^^ expected `Box<T>`, found `T`
|
= note: expected struct `Box<T>`
found enum `T`
@@ -21,7 +21,7 @@ LL | let y = match x {
| this expression has type `Box<T>`
| help: consider dereferencing the boxed value: `*x`
LL | T::A(a) | T::B(a) => a,
- | ^^^^^^^ expected struct `Box`, found enum `T`
+ | ^^^^^^^ expected `Box<T>`, found `T`
|
= note: expected struct `Box<T>`
found enum `T`
@@ -35,7 +35,7 @@ LL | let y = match x {
| this expression has type `Box<S>`
| help: consider dereferencing the boxed value: `*x`
LL | S::A { a } | S::B { b: a } => a,
- | ^^^^^^^^^^ expected struct `Box`, found enum `S`
+ | ^^^^^^^^^^ expected `Box<S>`, found `S`
|
= note: expected struct `Box<S>`
found enum `S`
@@ -49,7 +49,7 @@ LL | let y = match x {
| this expression has type `Box<S>`
| help: consider dereferencing the boxed value: `*x`
LL | S::A { a } | S::B { b: a } => a,
- | ^^^^^^^^^^^^^ expected struct `Box`, found enum `S`
+ | ^^^^^^^^^^^^^ expected `Box<S>`, found `S`
|
= note: expected struct `Box<S>`
found enum `S`
diff --git a/tests/ui/issues/issue-59488.stderr b/tests/ui/issues/issue-59488.stderr
index f9846b62a..d45beefa4 100644
--- a/tests/ui/issues/issue-59488.stderr
+++ b/tests/ui/issues/issue-59488.stderr
@@ -15,7 +15,7 @@ error[E0308]: mismatched types
--> $DIR/issue-59488.rs:14:11
|
LL | foo > 12;
- | ^^ expected fn item, found integer
+ | ^^ expected fn item, found `i32`
|
= note: expected fn item `fn() -> i32 {foo}`
found type `i32`
@@ -37,7 +37,7 @@ error[E0308]: mismatched types
--> $DIR/issue-59488.rs:18:11
|
LL | bar > 13;
- | ^^ expected fn item, found integer
+ | ^^ expected fn item, found `i64`
|
= note: expected fn item `fn(i64) -> i64 {bar}`
found type `i64`
diff --git a/tests/ui/issues/issue-60218.stderr b/tests/ui/issues/issue-60218.stderr
index dd72b6515..563690c9a 100644
--- a/tests/ui/issues/issue-60218.stderr
+++ b/tests/ui/issues/issue-60218.stderr
@@ -10,7 +10,7 @@ note: required by a bound in `trigger_error`
--> $DIR/issue-60218.rs:13:72
|
LL | pub fn trigger_error<I, F>(iterable: I, functor: F)
- | ------------- required by a bound in this
+ | ------------- required by a bound in this function
...
LL | for<'t> <Map<<&'t I as IntoIterator>::IntoIter, F> as Iterator>::Item: Foo,
| ^^^ required by this bound in `trigger_error`
diff --git a/tests/ui/issues/issue-60622.rs b/tests/ui/issues/issue-60622.rs
index 8e230c615..7b9443eee 100644
--- a/tests/ui/issues/issue-60622.rs
+++ b/tests/ui/issues/issue-60622.rs
@@ -9,7 +9,7 @@ impl Borked {
fn run_wild<T>(b: &Borked) {
b.a::<'_, T>();
//~^ ERROR cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
- //~| ERROR this associated function takes 0 generic arguments but 1 generic argument
+ //~| ERROR method takes 0 generic arguments but 1 generic argument
//~| WARN 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/tests/ui/issues/issue-60622.stderr b/tests/ui/issues/issue-60622.stderr
index ecf1ae758..43da27739 100644
--- a/tests/ui/issues/issue-60622.stderr
+++ b/tests/ui/issues/issue-60622.stderr
@@ -16,7 +16,7 @@ LL | #![deny(warnings)]
| ^^^^^^^^
= note: `#[deny(late_bound_lifetime_arguments)]` implied by `#[deny(warnings)]`
-error[E0107]: this associated function takes 0 generic arguments but 1 generic argument was supplied
+error[E0107]: method takes 0 generic arguments but 1 generic argument was supplied
--> $DIR/issue-60622.rs:10:7
|
LL | b.a::<'_, T>();
@@ -24,7 +24,7 @@ LL | b.a::<'_, T>();
| |
| expected 0 generic arguments
|
-note: associated function defined here, with 0 generic parameters
+note: method defined here, with 0 generic parameters
--> $DIR/issue-60622.rs:6:8
|
LL | fn a(&self) {}
diff --git a/tests/ui/issues/issue-61106.stderr b/tests/ui/issues/issue-61106.stderr
index 2bc092341..eff3e6e78 100644
--- a/tests/ui/issues/issue-61106.stderr
+++ b/tests/ui/issues/issue-61106.stderr
@@ -4,7 +4,7 @@ error[E0308]: mismatched types
LL | foo(x.clone());
| --- ^^^^^^^^^
| | |
- | | expected `&str`, found struct `String`
+ | | expected `&str`, found `String`
| | help: consider borrowing here: `&x`
| arguments to this function are incorrect
|
diff --git a/tests/ui/issues/issue-6458-4.stderr b/tests/ui/issues/issue-6458-4.stderr
index 168ececac..66ccfdff2 100644
--- a/tests/ui/issues/issue-6458-4.stderr
+++ b/tests/ui/issues/issue-6458-4.stderr
@@ -2,7 +2,7 @@ error[E0308]: mismatched types
--> $DIR/issue-6458-4.rs:1:20
|
LL | fn foo(b: bool) -> Result<bool,String> {
- | --- ^^^^^^^^^^^^^^^^^^^ expected enum `Result`, found `()`
+ | --- ^^^^^^^^^^^^^^^^^^^ expected `Result<bool, String>`, found `()`
| |
| implicitly returns `()` as its body has no tail or `return` expression
LL | Err("bar".to_string());
diff --git a/tests/ui/issues/issue-65634-raw-ident-suggestion.edition2015.stderr b/tests/ui/issues/issue-65634-raw-ident-suggestion.edition2015.stderr
index d0cb16995..4af3672ef 100644
--- a/tests/ui/issues/issue-65634-raw-ident-suggestion.edition2015.stderr
+++ b/tests/ui/issues/issue-65634-raw-ident-suggestion.edition2015.stderr
@@ -14,11 +14,11 @@ note: candidate #2 is defined in an impl of the trait `await` for the type `r#fn
|
LL | fn r#struct(&self) {
| ^^^^^^^^^^^^^^^^^^
-help: disambiguate the associated function for candidate #1
+help: disambiguate the method for candidate #1
|
LL | async::r#struct(&r#fn {});
| ~~~~~~~~~~~~~~~~~~~~~~~~~
-help: disambiguate the associated function for candidate #2
+help: disambiguate the method for candidate #2
|
LL | await::r#struct(&r#fn {});
| ~~~~~~~~~~~~~~~~~~~~~~~~~
diff --git a/tests/ui/issues/issue-65634-raw-ident-suggestion.edition2018.stderr b/tests/ui/issues/issue-65634-raw-ident-suggestion.edition2018.stderr
index a75c1c413..2b96a0fb5 100644
--- a/tests/ui/issues/issue-65634-raw-ident-suggestion.edition2018.stderr
+++ b/tests/ui/issues/issue-65634-raw-ident-suggestion.edition2018.stderr
@@ -14,11 +14,11 @@ note: candidate #2 is defined in an impl of the trait `r#await` for the type `r#
|
LL | fn r#struct(&self) {
| ^^^^^^^^^^^^^^^^^^
-help: disambiguate the associated function for candidate #1
+help: disambiguate the method for candidate #1
|
LL | r#async::r#struct(&r#fn {});
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~
-help: disambiguate the associated function for candidate #2
+help: disambiguate the method for candidate #2
|
LL | r#await::r#struct(&r#fn {});
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~
diff --git a/tests/ui/issues/issue-67039-unsound-pin-partialeq.stderr b/tests/ui/issues/issue-67039-unsound-pin-partialeq.stderr
index 37e2c3bdd..6fde44eaf 100644
--- a/tests/ui/issues/issue-67039-unsound-pin-partialeq.stderr
+++ b/tests/ui/issues/issue-67039-unsound-pin-partialeq.stderr
@@ -2,7 +2,7 @@ error[E0271]: type mismatch resolving `<Rc<Apple> as Deref>::Target == Rc<Apple>
--> $DIR/issue-67039-unsound-pin-partialeq.rs:25:29
|
LL | let _ = Pin::new(Apple) == Rc::pin(Apple);
- | ^^ expected struct `Apple`, found struct `Rc`
+ | ^^ expected `Apple`, found `Rc<Apple>`
|
= note: expected struct `Apple`
found struct `Rc<Apple>`
diff --git a/tests/ui/issues/issue-69306.stderr b/tests/ui/issues/issue-69306.stderr
index 61ec5d318..570677298 100644
--- a/tests/ui/issues/issue-69306.stderr
+++ b/tests/ui/issues/issue-69306.stderr
@@ -22,7 +22,7 @@ error[E0308]: mismatched types
LL | impl<T> S0<T> {
| - this type parameter
LL | const C: S0<u8> = Self(0);
- | ^^^^^^^ expected `u8`, found type parameter `T`
+ | ^^^^^^^ expected `S0<u8>`, found `S0<T>`
|
= note: expected struct `S0<u8>`
found struct `S0<T>`
@@ -89,7 +89,7 @@ error[E0308]: mismatched types
LL | impl<T> S1<T, u8> {
| - this type parameter
LL | const C: S1<u8, u8> = Self(0, 1);
- | ^^^^^^^^^^ expected `u8`, found type parameter `T`
+ | ^^^^^^^^^^ expected `S1<u8, u8>`, found `S1<T, u8>`
|
= note: expected struct `S1<u8, _>`
found struct `S1<T, _>`
@@ -126,7 +126,7 @@ LL | fn map<U>(x: U) -> S2<U> {
| |
| expected type parameter
LL | Self(x)
- | ^^^^^^^ expected type parameter `U`, found type parameter `T`
+ | ^^^^^^^ expected `S2<U>`, found `S2<T>`
|
= note: expected struct `S2<U>`
found struct `S2<T>`
diff --git a/tests/ui/issues/issue-69455.stderr b/tests/ui/issues/issue-69455.stderr
index fc343bb54..d3e307fba 100644
--- a/tests/ui/issues/issue-69455.stderr
+++ b/tests/ui/issues/issue-69455.stderr
@@ -2,7 +2,7 @@ error[E0284]: type annotations needed
--> $DIR/issue-69455.rs:29:41
|
LL | println!("{}", 23u64.test(xs.iter().sum()));
- | ---- ^^^ cannot infer type of the type parameter `S` declared on the associated function `sum`
+ | ---- ^^^ cannot infer type of the type parameter `S` declared on the method `sum`
| |
| type must be known at this point
|
@@ -16,7 +16,7 @@ error[E0283]: type annotations needed
--> $DIR/issue-69455.rs:29:41
|
LL | println!("{}", 23u64.test(xs.iter().sum()));
- | ---- ^^^ cannot infer type of the type parameter `S` declared on the associated function `sum`
+ | ---- ^^^ cannot infer type of the type parameter `S` declared on the method `sum`
| |
| required by a bound introduced by this call
|
diff --git a/tests/ui/issues/issue-69683.stderr b/tests/ui/issues/issue-69683.stderr
index 193de1a35..c428ea9ea 100644
--- a/tests/ui/issues/issue-69683.stderr
+++ b/tests/ui/issues/issue-69683.stderr
@@ -31,7 +31,7 @@ LL | u8: Element<I>,
| ^^^^^^^^^^ required by this bound in `Foo::foo`
LL | {
LL | fn foo(self, x: <u8 as Element<I>>::Array);
- | --- required by a bound in this
+ | --- required by a bound in this associated function
help: try using a fully qualified path to specify the expected types
|
LL | <u16 as Foo<I>>::foo(0u16, b);
diff --git a/tests/ui/issues/issue-70093/issue-70093-link-directives.rs b/tests/ui/issues/issue-70093/issue-70093-link-directives.rs
new file mode 100644
index 000000000..83f9b16c4
--- /dev/null
+++ b/tests/ui/issues/issue-70093/issue-70093-link-directives.rs
@@ -0,0 +1,10 @@
+// run-pass
+// compile-flags: -Zlink-directives=no
+// ignore-windows - this will probably only work on unixish systems
+// ignore-fuchsia - missing __libc_start_main for some reason (#84733)
+// ignore-cross-compile - default-linker-libraries=yes doesn't play well with cross compiling
+
+#[link(name = "some-random-non-existent-library", kind = "static")]
+extern "C" {}
+
+fn main() {}
diff --git a/tests/ui/issues/issue-70093.rs b/tests/ui/issues/issue-70093/issue-70093.rs
index 86459dc90..86459dc90 100644
--- a/tests/ui/issues/issue-70093.rs
+++ b/tests/ui/issues/issue-70093/issue-70093.rs
diff --git a/tests/ui/issues/issue-7061.stderr b/tests/ui/issues/issue-7061.stderr
index 27034378d..a209f8a42 100644
--- a/tests/ui/issues/issue-7061.stderr
+++ b/tests/ui/issues/issue-7061.stderr
@@ -2,7 +2,7 @@ error[E0308]: mismatched types
--> $DIR/issue-7061.rs:4:46
|
LL | fn foo(&'a mut self) -> Box<BarStruct> { self }
- | -------------- ^^^^ expected struct `Box`, found `&mut BarStruct`
+ | -------------- ^^^^ expected `Box<BarStruct>`, found `&mut BarStruct`
| |
| expected `Box<BarStruct>` because of return type
|
diff --git a/tests/ui/issues/issue-7092.rs b/tests/ui/issues/issue-7092.rs
index 85bfbf90d..c3c96c7d3 100644
--- a/tests/ui/issues/issue-7092.rs
+++ b/tests/ui/issues/issue-7092.rs
@@ -5,7 +5,7 @@ fn foo(x: Whatever) {
match x {
Some(field) =>
//~^ ERROR mismatched types
-//~| expected enum `Whatever`, found enum `Option`
+//~| expected `Whatever`, found `Option<_>`
//~| expected enum `Whatever`
//~| found enum `Option<_>`
field.access(),
diff --git a/tests/ui/issues/issue-7092.stderr b/tests/ui/issues/issue-7092.stderr
index 59e8d75e2..e35379fd1 100644
--- a/tests/ui/issues/issue-7092.stderr
+++ b/tests/ui/issues/issue-7092.stderr
@@ -4,7 +4,7 @@ error[E0308]: mismatched types
LL | match x {
| - this expression has type `Whatever`
LL | Some(field) =>
- | ^^^^^^^^^^^ expected enum `Whatever`, found enum `Option`
+ | ^^^^^^^^^^^ expected `Whatever`, found `Option<_>`
|
= note: expected enum `Whatever`
found enum `Option<_>`
diff --git a/tests/ui/issues/issue-71676-1.stderr b/tests/ui/issues/issue-71676-1.stderr
index 2104634eb..164641ff7 100644
--- a/tests/ui/issues/issue-71676-1.stderr
+++ b/tests/ui/issues/issue-71676-1.stderr
@@ -2,7 +2,7 @@ error[E0308]: mismatched types
--> $DIR/issue-71676-1.rs:43:24
|
LL | let _: *const u8 = &a;
- | --------- ^^ expected `u8`, found struct `Emm`
+ | --------- ^^ expected `*const u8`, found `&Emm`
| |
| expected due to this
|
@@ -32,7 +32,7 @@ error[E0308]: mismatched types
--> $DIR/issue-71676-1.rs:49:24
|
LL | let _: *const u8 = &mut a;
- | --------- ^^^^^^ expected `u8`, found struct `Emm`
+ | --------- ^^^^^^ expected `*const u8`, found `&mut Emm`
| |
| expected due to this
|
@@ -47,7 +47,7 @@ error[E0308]: mismatched types
--> $DIR/issue-71676-1.rs:52:22
|
LL | let _: *mut u8 = &mut a;
- | ------- ^^^^^^ expected `u8`, found struct `Emm`
+ | ------- ^^^^^^ expected `*mut u8`, found `&mut Emm`
| |
| expected due to this
|
diff --git a/tests/ui/issues/issue-7364.stderr b/tests/ui/issues/issue-7364.stderr
index 5dc8c2b60..aee73380f 100644
--- a/tests/ui/issues/issue-7364.stderr
+++ b/tests/ui/issues/issue-7364.stderr
@@ -5,6 +5,7 @@ LL | static boxed: Box<RefCell<isize>> = Box::new(RefCell::new(0));
| ^^^^^^^^^^^^^^^^^^^ `RefCell<isize>` cannot be shared between threads safely
|
= help: the trait `Sync` is not implemented for `RefCell<isize>`
+ = note: if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` instead
= note: required for `Unique<RefCell<isize>>` to implement `Sync`
= note: required because it appears within the type `Box<RefCell<isize>>`
= note: shared static variables must have a type that implements `Sync`
diff --git a/tests/ui/issues/issue-74236/main.stderr b/tests/ui/issues/issue-74236/main.stderr
index 55e94ae72..5cd64e48a 100644
--- a/tests/ui/issues/issue-74236/main.stderr
+++ b/tests/ui/issues/issue-74236/main.stderr
@@ -4,7 +4,7 @@ error[E0308]: mismatched types
LL | let () = dep::Renamed;
| ^^ ------------ this expression has type `Renamed`
| |
- | expected struct `Renamed`, found `()`
+ | expected `Renamed`, found `()`
error: aborting due to previous error
diff --git a/tests/ui/issues/issue-76191.stderr b/tests/ui/issues/issue-76191.stderr
index 137498047..32d9105b2 100644
--- a/tests/ui/issues/issue-76191.stderr
+++ b/tests/ui/issues/issue-76191.stderr
@@ -9,7 +9,7 @@ LL | match n {
LL | RANGE => {}
| ^^^^^
| |
- | expected `i32`, found struct `RangeInclusive`
+ | expected `i32`, found `RangeInclusive<i32>`
| `RANGE` is interpreted as a constant, not a new binding
|
= note: expected type `i32`
@@ -31,7 +31,7 @@ LL | match n {
LL | RANGE2 => {}
| ^^^^^^
| |
- | expected `i32`, found struct `RangeInclusive`
+ | expected `i32`, found `RangeInclusive<i32>`
| `RANGE2` is interpreted as a constant, not a new binding
|
= note: expected type `i32`
diff --git a/tests/ui/issues/issue-7867.rs b/tests/ui/issues/issue-7867.rs
index 3074052f1..e9fd10c66 100644
--- a/tests/ui/issues/issue-7867.rs
+++ b/tests/ui/issues/issue-7867.rs
@@ -6,7 +6,7 @@ fn main() {
match (true, false) {
A::B => (),
//~^ ERROR mismatched types
- //~| expected tuple, found enum `A`
+ //~| expected `(bool, bool)`, found `A`
//~| expected tuple `(bool, bool)`
//~| found enum `A`
_ => ()
diff --git a/tests/ui/issues/issue-7867.stderr b/tests/ui/issues/issue-7867.stderr
index 0d3121d60..4fb1af344 100644
--- a/tests/ui/issues/issue-7867.stderr
+++ b/tests/ui/issues/issue-7867.stderr
@@ -7,7 +7,7 @@ LL | enum A { B, C }
LL | match (true, false) {
| ------------- this expression has type `(bool, bool)`
LL | A::B => (),
- | ^^^^ expected tuple, found enum `A`
+ | ^^^^ expected `(bool, bool)`, found `A`
|
= note: expected tuple `(bool, bool)`
found enum `A`
diff --git a/tests/ui/issues/issue-92741.fixed b/tests/ui/issues/issue-92741.fixed
new file mode 100644
index 000000000..d07aeb6c0
--- /dev/null
+++ b/tests/ui/issues/issue-92741.fixed
@@ -0,0 +1,13 @@
+// run-rustfix
+fn main() {}
+fn _foo() -> bool {
+ if true { true } else { false }
+}
+
+fn _bar() -> bool {
+ if true { true } else { false }
+}
+
+fn _baz() -> bool {
+ if true { true } else { false }
+}
diff --git a/tests/ui/issues/issue-92741.rs b/tests/ui/issues/issue-92741.rs
new file mode 100644
index 000000000..413d5bf04
--- /dev/null
+++ b/tests/ui/issues/issue-92741.rs
@@ -0,0 +1,17 @@
+// run-rustfix
+fn main() {}
+fn _foo() -> bool {
+ & //~ ERROR 4:5: 6:36: mismatched types [E0308]
+ mut
+ if true { true } else { false }
+}
+
+fn _bar() -> bool {
+ & //~ ERROR 10:5: 11:40: mismatched types [E0308]
+ mut if true { true } else { false }
+}
+
+fn _baz() -> bool {
+ & mut //~ ERROR 15:5: 16:36: mismatched types [E0308]
+ if true { true } else { false }
+}
diff --git a/tests/ui/issues/issue-92741.stderr b/tests/ui/issues/issue-92741.stderr
new file mode 100644
index 000000000..49315e7a8
--- /dev/null
+++ b/tests/ui/issues/issue-92741.stderr
@@ -0,0 +1,49 @@
+error[E0308]: mismatched types
+ --> $DIR/issue-92741.rs:4:5
+ |
+LL | fn _foo() -> bool {
+ | ---- expected `bool` because of return type
+LL | / &
+LL | | mut
+LL | | if true { true } else { false }
+ | |___________________________________^ expected `bool`, found `&mut bool`
+ |
+help: consider removing the borrow
+ |
+LL - &
+LL - mut
+ |
+
+error[E0308]: mismatched types
+ --> $DIR/issue-92741.rs:10:5
+ |
+LL | fn _bar() -> bool {
+ | ---- expected `bool` because of return type
+LL | / &
+LL | | mut if true { true } else { false }
+ | |_______________________________________^ expected `bool`, found `&mut bool`
+ |
+help: consider removing the borrow
+ |
+LL - &
+LL - mut if true { true } else { false }
+LL + if true { true } else { false }
+ |
+
+error[E0308]: mismatched types
+ --> $DIR/issue-92741.rs:15:5
+ |
+LL | fn _baz() -> bool {
+ | ---- expected `bool` because of return type
+LL | / & mut
+LL | | if true { true } else { false }
+ | |___________________________________^ expected `bool`, found `&mut bool`
+ |
+help: consider removing the borrow
+ |
+LL - & mut
+ |
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/json/json-bom-plus-crlf-multifile.stderr b/tests/ui/json/json-bom-plus-crlf-multifile.stderr
index 02f3bc687..84040e805 100644
--- a/tests/ui/json/json-bom-plus-crlf-multifile.stderr
+++ b/tests/ui/json/json-bom-plus-crlf-multifile.stderr
@@ -24,7 +24,7 @@ This error occurs when an expression was used in a place where the compiler
expected an expression of a different type. It can occur in several cases, the
most common being when calling a function and passing an argument which has a
different type than the matching type in the function declaration.
-"},"level":"error","spans":[{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":621,"byte_end":622,"line_start":17,"line_end":17,"column_start":22,"column_end":23,"is_primary":true,"text":[{"text":" let s : String = 1; // Error in the middle of line.","highlight_start":22,"highlight_end":23}],"label":"expected struct `String`, found integer","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":612,"byte_end":618,"line_start":17,"line_end":17,"column_start":13,"column_end":19,"is_primary":false,"text":[{"text":" let s : String = 1; // Error in the middle of line.","highlight_start":13,"highlight_end":19}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"try using a conversion method","code":null,"level":"help","spans":[{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":622,"byte_end":622,"line_start":17,"line_end":17,"column_start":23,"column_end":23,"is_primary":true,"text":[{"text":" let s : String = 1; // Error in the middle of line.","highlight_start":23,"highlight_end":23}],"label":null,"suggested_replacement":".to_string()","suggestion_applicability":"MaybeIncorrect","expansion":null}],"children":[],"rendered":null}],"rendered":"$DIR/json-bom-plus-crlf-multifile-aux.rs:17:22: error[E0308]: mismatched types
+"},"level":"error","spans":[{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":621,"byte_end":622,"line_start":17,"line_end":17,"column_start":22,"column_end":23,"is_primary":true,"text":[{"text":" let s : String = 1; // Error in the middle of line.","highlight_start":22,"highlight_end":23}],"label":"expected `String`, found integer","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":612,"byte_end":618,"line_start":17,"line_end":17,"column_start":13,"column_end":19,"is_primary":false,"text":[{"text":" let s : String = 1; // Error in the middle of line.","highlight_start":13,"highlight_end":19}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"try using a conversion method","code":null,"level":"help","spans":[{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":622,"byte_end":622,"line_start":17,"line_end":17,"column_start":23,"column_end":23,"is_primary":true,"text":[{"text":" let s : String = 1; // Error in the middle of line.","highlight_start":23,"highlight_end":23}],"label":null,"suggested_replacement":".to_string()","suggestion_applicability":"MaybeIncorrect","expansion":null}],"children":[],"rendered":null}],"rendered":"$DIR/json-bom-plus-crlf-multifile-aux.rs:17:22: error[E0308]: mismatched types
"}
{"message":"mismatched types","code":{"code":"E0308","explanation":"Expected type did not match the received type.
@@ -52,7 +52,7 @@ This error occurs when an expression was used in a place where the compiler
expected an expression of a different type. It can occur in several cases, the
most common being when calling a function and passing an argument which has a
different type than the matching type in the function declaration.
-"},"level":"error","spans":[{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":681,"byte_end":682,"line_start":19,"line_end":19,"column_start":22,"column_end":23,"is_primary":true,"text":[{"text":" let s : String = 1","highlight_start":22,"highlight_end":23}],"label":"expected struct `String`, found integer","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":672,"byte_end":678,"line_start":19,"line_end":19,"column_start":13,"column_end":19,"is_primary":false,"text":[{"text":" let s : String = 1","highlight_start":13,"highlight_end":19}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"try using a conversion method","code":null,"level":"help","spans":[{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":682,"byte_end":682,"line_start":19,"line_end":19,"column_start":23,"column_end":23,"is_primary":true,"text":[{"text":" let s : String = 1","highlight_start":23,"highlight_end":23}],"label":null,"suggested_replacement":".to_string()","suggestion_applicability":"MaybeIncorrect","expansion":null}],"children":[],"rendered":null}],"rendered":"$DIR/json-bom-plus-crlf-multifile-aux.rs:19:22: error[E0308]: mismatched types
+"},"level":"error","spans":[{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":681,"byte_end":682,"line_start":19,"line_end":19,"column_start":22,"column_end":23,"is_primary":true,"text":[{"text":" let s : String = 1","highlight_start":22,"highlight_end":23}],"label":"expected `String`, found integer","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":672,"byte_end":678,"line_start":19,"line_end":19,"column_start":13,"column_end":19,"is_primary":false,"text":[{"text":" let s : String = 1","highlight_start":13,"highlight_end":19}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"try using a conversion method","code":null,"level":"help","spans":[{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":682,"byte_end":682,"line_start":19,"line_end":19,"column_start":23,"column_end":23,"is_primary":true,"text":[{"text":" let s : String = 1","highlight_start":23,"highlight_end":23}],"label":null,"suggested_replacement":".to_string()","suggestion_applicability":"MaybeIncorrect","expansion":null}],"children":[],"rendered":null}],"rendered":"$DIR/json-bom-plus-crlf-multifile-aux.rs:19:22: error[E0308]: mismatched types
"}
{"message":"mismatched types","code":{"code":"E0308","explanation":"Expected type did not match the received type.
@@ -80,7 +80,7 @@ This error occurs when an expression was used in a place where the compiler
expected an expression of a different type. It can occur in several cases, the
most common being when calling a function and passing an argument which has a
different type than the matching type in the function declaration.
-"},"level":"error","spans":[{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":745,"byte_end":746,"line_start":23,"line_end":23,"column_start":1,"column_end":2,"is_primary":true,"text":[{"text":"1; // Error after the newline.","highlight_start":1,"highlight_end":2}],"label":"expected struct `String`, found integer","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":735,"byte_end":741,"line_start":22,"line_end":22,"column_start":13,"column_end":19,"is_primary":false,"text":[{"text":" let s : String =","highlight_start":13,"highlight_end":19}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"try using a conversion method","code":null,"level":"help","spans":[{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":746,"byte_end":746,"line_start":23,"line_end":23,"column_start":2,"column_end":2,"is_primary":true,"text":[{"text":"1; // Error after the newline.","highlight_start":2,"highlight_end":2}],"label":null,"suggested_replacement":".to_string()","suggestion_applicability":"MaybeIncorrect","expansion":null}],"children":[],"rendered":null}],"rendered":"$DIR/json-bom-plus-crlf-multifile-aux.rs:23:1: error[E0308]: mismatched types
+"},"level":"error","spans":[{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":745,"byte_end":746,"line_start":23,"line_end":23,"column_start":1,"column_end":2,"is_primary":true,"text":[{"text":"1; // Error after the newline.","highlight_start":1,"highlight_end":2}],"label":"expected `String`, found integer","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":735,"byte_end":741,"line_start":22,"line_end":22,"column_start":13,"column_end":19,"is_primary":false,"text":[{"text":" let s : String =","highlight_start":13,"highlight_end":19}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"try using a conversion method","code":null,"level":"help","spans":[{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":746,"byte_end":746,"line_start":23,"line_end":23,"column_start":2,"column_end":2,"is_primary":true,"text":[{"text":"1; // Error after the newline.","highlight_start":2,"highlight_end":2}],"label":null,"suggested_replacement":".to_string()","suggestion_applicability":"MaybeIncorrect","expansion":null}],"children":[],"rendered":null}],"rendered":"$DIR/json-bom-plus-crlf-multifile-aux.rs:23:1: error[E0308]: mismatched types
"}
{"message":"mismatched types","code":{"code":"E0308","explanation":"Expected type did not match the received type.
@@ -108,7 +108,7 @@ This error occurs when an expression was used in a place where the compiler
expected an expression of a different type. It can occur in several cases, the
most common being when calling a function and passing an argument which has a
different type than the matching type in the function declaration.
-"},"level":"error","spans":[{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":801,"byte_end":809,"line_start":25,"line_end":26,"column_start":22,"column_end":6,"is_primary":true,"text":[{"text":" let s : String = (","highlight_start":22,"highlight_end":23},{"text":" ); // Error spanning the newline.","highlight_start":1,"highlight_end":6}],"label":"expected struct `String`, found `()`","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":792,"byte_end":798,"line_start":25,"line_end":25,"column_start":13,"column_end":19,"is_primary":false,"text":[{"text":" let s : String = (","highlight_start":13,"highlight_end":19}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[],"rendered":"$DIR/json-bom-plus-crlf-multifile-aux.rs:25:22: error[E0308]: mismatched types
+"},"level":"error","spans":[{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":801,"byte_end":809,"line_start":25,"line_end":26,"column_start":22,"column_end":6,"is_primary":true,"text":[{"text":" let s : String = (","highlight_start":22,"highlight_end":23},{"text":" ); // Error spanning the newline.","highlight_start":1,"highlight_end":6}],"label":"expected `String`, found `()`","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":792,"byte_end":798,"line_start":25,"line_end":25,"column_start":13,"column_end":19,"is_primary":false,"text":[{"text":" let s : String = (","highlight_start":13,"highlight_end":19}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[],"rendered":"$DIR/json-bom-plus-crlf-multifile-aux.rs:25:22: error[E0308]: mismatched types
"}
{"message":"aborting due to 4 previous errors","code":null,"level":"error","spans":[],"children":[],"rendered":"error: aborting due to 4 previous errors
"}
diff --git a/tests/ui/json/json-bom-plus-crlf.stderr b/tests/ui/json/json-bom-plus-crlf.stderr
index df6bd7286..b0f450e9e 100644
--- a/tests/ui/json/json-bom-plus-crlf.stderr
+++ b/tests/ui/json/json-bom-plus-crlf.stderr
@@ -24,7 +24,7 @@ This error occurs when an expression was used in a place where the compiler
expected an expression of a different type. It can occur in several cases, the
most common being when calling a function and passing an argument which has a
different type than the matching type in the function declaration.
-"},"level":"error","spans":[{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":606,"byte_end":607,"line_start":16,"line_end":16,"column_start":22,"column_end":23,"is_primary":true,"text":[{"text":" let s : String = 1; // Error in the middle of line.","highlight_start":22,"highlight_end":23}],"label":"expected struct `String`, found integer","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":597,"byte_end":603,"line_start":16,"line_end":16,"column_start":13,"column_end":19,"is_primary":false,"text":[{"text":" let s : String = 1; // Error in the middle of line.","highlight_start":13,"highlight_end":19}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"try using a conversion method","code":null,"level":"help","spans":[{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":607,"byte_end":607,"line_start":16,"line_end":16,"column_start":23,"column_end":23,"is_primary":true,"text":[{"text":" let s : String = 1; // Error in the middle of line.","highlight_start":23,"highlight_end":23}],"label":null,"suggested_replacement":".to_string()","suggestion_applicability":"MaybeIncorrect","expansion":null}],"children":[],"rendered":null}],"rendered":"$DIR/json-bom-plus-crlf.rs:16:22: error[E0308]: mismatched types
+"},"level":"error","spans":[{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":606,"byte_end":607,"line_start":16,"line_end":16,"column_start":22,"column_end":23,"is_primary":true,"text":[{"text":" let s : String = 1; // Error in the middle of line.","highlight_start":22,"highlight_end":23}],"label":"expected `String`, found integer","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":597,"byte_end":603,"line_start":16,"line_end":16,"column_start":13,"column_end":19,"is_primary":false,"text":[{"text":" let s : String = 1; // Error in the middle of line.","highlight_start":13,"highlight_end":19}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"try using a conversion method","code":null,"level":"help","spans":[{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":607,"byte_end":607,"line_start":16,"line_end":16,"column_start":23,"column_end":23,"is_primary":true,"text":[{"text":" let s : String = 1; // Error in the middle of line.","highlight_start":23,"highlight_end":23}],"label":null,"suggested_replacement":".to_string()","suggestion_applicability":"MaybeIncorrect","expansion":null}],"children":[],"rendered":null}],"rendered":"$DIR/json-bom-plus-crlf.rs:16:22: error[E0308]: mismatched types
"}
{"message":"mismatched types","code":{"code":"E0308","explanation":"Expected type did not match the received type.
@@ -52,7 +52,7 @@ This error occurs when an expression was used in a place where the compiler
expected an expression of a different type. It can occur in several cases, the
most common being when calling a function and passing an argument which has a
different type than the matching type in the function declaration.
-"},"level":"error","spans":[{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":666,"byte_end":667,"line_start":18,"line_end":18,"column_start":22,"column_end":23,"is_primary":true,"text":[{"text":" let s : String = 1","highlight_start":22,"highlight_end":23}],"label":"expected struct `String`, found integer","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":657,"byte_end":663,"line_start":18,"line_end":18,"column_start":13,"column_end":19,"is_primary":false,"text":[{"text":" let s : String = 1","highlight_start":13,"highlight_end":19}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"try using a conversion method","code":null,"level":"help","spans":[{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":667,"byte_end":667,"line_start":18,"line_end":18,"column_start":23,"column_end":23,"is_primary":true,"text":[{"text":" let s : String = 1","highlight_start":23,"highlight_end":23}],"label":null,"suggested_replacement":".to_string()","suggestion_applicability":"MaybeIncorrect","expansion":null}],"children":[],"rendered":null}],"rendered":"$DIR/json-bom-plus-crlf.rs:18:22: error[E0308]: mismatched types
+"},"level":"error","spans":[{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":666,"byte_end":667,"line_start":18,"line_end":18,"column_start":22,"column_end":23,"is_primary":true,"text":[{"text":" let s : String = 1","highlight_start":22,"highlight_end":23}],"label":"expected `String`, found integer","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":657,"byte_end":663,"line_start":18,"line_end":18,"column_start":13,"column_end":19,"is_primary":false,"text":[{"text":" let s : String = 1","highlight_start":13,"highlight_end":19}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"try using a conversion method","code":null,"level":"help","spans":[{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":667,"byte_end":667,"line_start":18,"line_end":18,"column_start":23,"column_end":23,"is_primary":true,"text":[{"text":" let s : String = 1","highlight_start":23,"highlight_end":23}],"label":null,"suggested_replacement":".to_string()","suggestion_applicability":"MaybeIncorrect","expansion":null}],"children":[],"rendered":null}],"rendered":"$DIR/json-bom-plus-crlf.rs:18:22: error[E0308]: mismatched types
"}
{"message":"mismatched types","code":{"code":"E0308","explanation":"Expected type did not match the received type.
@@ -80,7 +80,7 @@ This error occurs when an expression was used in a place where the compiler
expected an expression of a different type. It can occur in several cases, the
most common being when calling a function and passing an argument which has a
different type than the matching type in the function declaration.
-"},"level":"error","spans":[{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":730,"byte_end":731,"line_start":22,"line_end":22,"column_start":1,"column_end":2,"is_primary":true,"text":[{"text":"1; // Error after the newline.","highlight_start":1,"highlight_end":2}],"label":"expected struct `String`, found integer","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":720,"byte_end":726,"line_start":21,"line_end":21,"column_start":13,"column_end":19,"is_primary":false,"text":[{"text":" let s : String =","highlight_start":13,"highlight_end":19}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"try using a conversion method","code":null,"level":"help","spans":[{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":731,"byte_end":731,"line_start":22,"line_end":22,"column_start":2,"column_end":2,"is_primary":true,"text":[{"text":"1; // Error after the newline.","highlight_start":2,"highlight_end":2}],"label":null,"suggested_replacement":".to_string()","suggestion_applicability":"MaybeIncorrect","expansion":null}],"children":[],"rendered":null}],"rendered":"$DIR/json-bom-plus-crlf.rs:22:1: error[E0308]: mismatched types
+"},"level":"error","spans":[{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":730,"byte_end":731,"line_start":22,"line_end":22,"column_start":1,"column_end":2,"is_primary":true,"text":[{"text":"1; // Error after the newline.","highlight_start":1,"highlight_end":2}],"label":"expected `String`, found integer","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":720,"byte_end":726,"line_start":21,"line_end":21,"column_start":13,"column_end":19,"is_primary":false,"text":[{"text":" let s : String =","highlight_start":13,"highlight_end":19}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"try using a conversion method","code":null,"level":"help","spans":[{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":731,"byte_end":731,"line_start":22,"line_end":22,"column_start":2,"column_end":2,"is_primary":true,"text":[{"text":"1; // Error after the newline.","highlight_start":2,"highlight_end":2}],"label":null,"suggested_replacement":".to_string()","suggestion_applicability":"MaybeIncorrect","expansion":null}],"children":[],"rendered":null}],"rendered":"$DIR/json-bom-plus-crlf.rs:22:1: error[E0308]: mismatched types
"}
{"message":"mismatched types","code":{"code":"E0308","explanation":"Expected type did not match the received type.
@@ -108,7 +108,7 @@ This error occurs when an expression was used in a place where the compiler
expected an expression of a different type. It can occur in several cases, the
most common being when calling a function and passing an argument which has a
different type than the matching type in the function declaration.
-"},"level":"error","spans":[{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":786,"byte_end":794,"line_start":24,"line_end":25,"column_start":22,"column_end":6,"is_primary":true,"text":[{"text":" let s : String = (","highlight_start":22,"highlight_end":23},{"text":" ); // Error spanning the newline.","highlight_start":1,"highlight_end":6}],"label":"expected struct `String`, found `()`","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":777,"byte_end":783,"line_start":24,"line_end":24,"column_start":13,"column_end":19,"is_primary":false,"text":[{"text":" let s : String = (","highlight_start":13,"highlight_end":19}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[],"rendered":"$DIR/json-bom-plus-crlf.rs:24:22: error[E0308]: mismatched types
+"},"level":"error","spans":[{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":786,"byte_end":794,"line_start":24,"line_end":25,"column_start":22,"column_end":6,"is_primary":true,"text":[{"text":" let s : String = (","highlight_start":22,"highlight_end":23},{"text":" ); // Error spanning the newline.","highlight_start":1,"highlight_end":6}],"label":"expected `String`, found `()`","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":777,"byte_end":783,"line_start":24,"line_end":24,"column_start":13,"column_end":19,"is_primary":false,"text":[{"text":" let s : String = (","highlight_start":13,"highlight_end":19}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[],"rendered":"$DIR/json-bom-plus-crlf.rs:24:22: error[E0308]: mismatched types
"}
{"message":"aborting due to 4 previous errors","code":null,"level":"error","spans":[],"children":[],"rendered":"error: aborting due to 4 previous errors
"}
diff --git a/tests/ui/kindck/kindck-send-object1.stderr b/tests/ui/kindck/kindck-send-object1.stderr
index 11f597fee..19ef4f6fc 100644
--- a/tests/ui/kindck/kindck-send-object1.stderr
+++ b/tests/ui/kindck/kindck-send-object1.stderr
@@ -20,7 +20,7 @@ LL | assert_send::<Box<dyn Dummy + 'a>>();
|
= help: the trait `Send` is not implemented for `(dyn Dummy + 'a)`
= note: required for `Unique<(dyn Dummy + 'a)>` to implement `Send`
- = note: required because it appears within the type `Box<(dyn Dummy + 'a)>`
+ = note: required because it appears within the type `Box<dyn Dummy>`
note: required by a bound in `assert_send`
--> $DIR/kindck-send-object1.rs:5:18
|
diff --git a/tests/ui/kinds-of-primitive-impl.stderr b/tests/ui/kinds-of-primitive-impl.stderr
index f4dbd1c40..21aac58f1 100644
--- a/tests/ui/kinds-of-primitive-impl.stderr
+++ b/tests/ui/kinds-of-primitive-impl.stderr
@@ -1,32 +1,32 @@
error[E0390]: cannot define inherent `impl` for primitive types
- --> $DIR/kinds-of-primitive-impl.rs:1:6
+ --> $DIR/kinds-of-primitive-impl.rs:1:1
|
LL | impl u8 {
- | ^^
+ | ^^^^^^^
|
= help: consider using an extension trait instead
error[E0390]: cannot define inherent `impl` for primitive types
- --> $DIR/kinds-of-primitive-impl.rs:6:6
+ --> $DIR/kinds-of-primitive-impl.rs:6:1
|
LL | impl str {
- | ^^^
+ | ^^^^^^^^
|
= help: consider using an extension trait instead
error[E0390]: cannot define inherent `impl` for primitive types
- --> $DIR/kinds-of-primitive-impl.rs:12:6
+ --> $DIR/kinds-of-primitive-impl.rs:12:1
|
LL | impl char {
- | ^^^^
+ | ^^^^^^^^^
|
= help: consider using an extension trait instead
error[E0390]: cannot define inherent `impl` for primitive types
- --> $DIR/kinds-of-primitive-impl.rs:21:6
+ --> $DIR/kinds-of-primitive-impl.rs:21:1
|
LL | impl &MyType {
- | ^^^^^^^
+ | ^^^^^^^^^^^^
|
= help: consider using an extension trait instead
= note: you could also try moving the reference to uses of `MyType` (such as `self`) within the implementation
diff --git a/tests/ui/lang-items/bad-add-impl.rs b/tests/ui/lang-items/bad-add-impl.rs
new file mode 100644
index 000000000..0c44edbe5
--- /dev/null
+++ b/tests/ui/lang-items/bad-add-impl.rs
@@ -0,0 +1,18 @@
+#![feature(no_core)]
+#![feature(lang_items)]
+#![no_core]
+
+#[lang = "sized"]
+trait Sized {}
+
+#[lang = "add"]
+trait Add<T> {
+ const add: u32 = 1u32;
+}
+
+impl Add<u32> for u32 {}
+
+fn main() {
+ 1u32 + 1u32;
+ //~^ ERROR cannot add `u32` to `u32`
+}
diff --git a/tests/ui/lang-items/bad-add-impl.stderr b/tests/ui/lang-items/bad-add-impl.stderr
new file mode 100644
index 000000000..3143729f9
--- /dev/null
+++ b/tests/ui/lang-items/bad-add-impl.stderr
@@ -0,0 +1,11 @@
+error[E0369]: cannot add `u32` to `u32`
+ --> $DIR/bad-add-impl.rs:16:10
+ |
+LL | 1u32 + 1u32;
+ | ---- ^ ---- u32
+ | |
+ | u32
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0369`.
diff --git a/tests/ui/lang-items/fn-fn_mut-call-ill-formed.bad_item.stderr b/tests/ui/lang-items/fn-fn_mut-call-ill-formed.bad_item.stderr
new file mode 100644
index 000000000..ff603111e
--- /dev/null
+++ b/tests/ui/lang-items/fn-fn_mut-call-ill-formed.bad_item.stderr
@@ -0,0 +1,18 @@
+error: failed to find an overloaded call trait for closure call
+ --> $DIR/fn-fn_mut-call-ill-formed.rs:39:5
+ |
+LL | a();
+ | ^^^
+ |
+ = help: make sure the `fn`/`fn_mut`/`fn_once` lang items are defined and have correctly defined `call`/`call_mut`/`call_once` methods
+
+error: failed to find an overloaded call trait for closure call
+ --> $DIR/fn-fn_mut-call-ill-formed.rs:43:5
+ |
+LL | b();
+ | ^^^
+ |
+ = help: make sure the `fn`/`fn_mut`/`fn_once` lang items are defined and have correctly defined `call`/`call_mut`/`call_once` methods
+
+error: aborting due to 2 previous errors
+
diff --git a/tests/ui/lang-items/fn-fn_mut-call-ill-formed.bad_sig.stderr b/tests/ui/lang-items/fn-fn_mut-call-ill-formed.bad_sig.stderr
new file mode 100644
index 000000000..ff603111e
--- /dev/null
+++ b/tests/ui/lang-items/fn-fn_mut-call-ill-formed.bad_sig.stderr
@@ -0,0 +1,18 @@
+error: failed to find an overloaded call trait for closure call
+ --> $DIR/fn-fn_mut-call-ill-formed.rs:39:5
+ |
+LL | a();
+ | ^^^
+ |
+ = help: make sure the `fn`/`fn_mut`/`fn_once` lang items are defined and have correctly defined `call`/`call_mut`/`call_once` methods
+
+error: failed to find an overloaded call trait for closure call
+ --> $DIR/fn-fn_mut-call-ill-formed.rs:43:5
+ |
+LL | b();
+ | ^^^
+ |
+ = help: make sure the `fn`/`fn_mut`/`fn_once` lang items are defined and have correctly defined `call`/`call_mut`/`call_once` methods
+
+error: aborting due to 2 previous errors
+
diff --git a/tests/ui/lang-items/fn-fn_mut-call-ill-formed.fn_bad_item.stderr b/tests/ui/lang-items/fn-fn_mut-call-ill-formed.fn_bad_item.stderr
new file mode 100644
index 000000000..02e33c597
--- /dev/null
+++ b/tests/ui/lang-items/fn-fn_mut-call-ill-formed.fn_bad_item.stderr
@@ -0,0 +1,18 @@
+error: failed to find an overloaded call trait for closure call
+ --> $DIR/fn-fn_mut-call-ill-formed.rs:42:5
+ |
+LL | a();
+ | ^^^
+ |
+ = help: make sure the `fn`/`fn_mut`/`fn_once` lang items are defined and have correctly defined `call`/`call_mut`/`call_once` methods
+
+error: failed to find an overloaded call trait for closure call
+ --> $DIR/fn-fn_mut-call-ill-formed.rs:47:5
+ |
+LL | b();
+ | ^^^
+ |
+ = help: make sure the `fn`/`fn_mut`/`fn_once` lang items are defined and have correctly defined `call`/`call_mut`/`call_once` methods
+
+error: aborting due to 2 previous errors
+
diff --git a/tests/ui/lang-items/fn-fn_mut-call-ill-formed.fn_bad_sig.stderr b/tests/ui/lang-items/fn-fn_mut-call-ill-formed.fn_bad_sig.stderr
new file mode 100644
index 000000000..02e33c597
--- /dev/null
+++ b/tests/ui/lang-items/fn-fn_mut-call-ill-formed.fn_bad_sig.stderr
@@ -0,0 +1,18 @@
+error: failed to find an overloaded call trait for closure call
+ --> $DIR/fn-fn_mut-call-ill-formed.rs:42:5
+ |
+LL | a();
+ | ^^^
+ |
+ = help: make sure the `fn`/`fn_mut`/`fn_once` lang items are defined and have correctly defined `call`/`call_mut`/`call_once` methods
+
+error: failed to find an overloaded call trait for closure call
+ --> $DIR/fn-fn_mut-call-ill-formed.rs:47:5
+ |
+LL | b();
+ | ^^^
+ |
+ = help: make sure the `fn`/`fn_mut`/`fn_once` lang items are defined and have correctly defined `call`/`call_mut`/`call_once` methods
+
+error: aborting due to 2 previous errors
+
diff --git a/tests/ui/lang-items/fn-fn_mut-call-ill-formed.fn_mut_bad_item.stderr b/tests/ui/lang-items/fn-fn_mut-call-ill-formed.fn_mut_bad_item.stderr
new file mode 100644
index 000000000..02e33c597
--- /dev/null
+++ b/tests/ui/lang-items/fn-fn_mut-call-ill-formed.fn_mut_bad_item.stderr
@@ -0,0 +1,18 @@
+error: failed to find an overloaded call trait for closure call
+ --> $DIR/fn-fn_mut-call-ill-formed.rs:42:5
+ |
+LL | a();
+ | ^^^
+ |
+ = help: make sure the `fn`/`fn_mut`/`fn_once` lang items are defined and have correctly defined `call`/`call_mut`/`call_once` methods
+
+error: failed to find an overloaded call trait for closure call
+ --> $DIR/fn-fn_mut-call-ill-formed.rs:47:5
+ |
+LL | b();
+ | ^^^
+ |
+ = help: make sure the `fn`/`fn_mut`/`fn_once` lang items are defined and have correctly defined `call`/`call_mut`/`call_once` methods
+
+error: aborting due to 2 previous errors
+
diff --git a/tests/ui/lang-items/fn-fn_mut-call-ill-formed.fn_mut_bad_sig.stderr b/tests/ui/lang-items/fn-fn_mut-call-ill-formed.fn_mut_bad_sig.stderr
new file mode 100644
index 000000000..02e33c597
--- /dev/null
+++ b/tests/ui/lang-items/fn-fn_mut-call-ill-formed.fn_mut_bad_sig.stderr
@@ -0,0 +1,18 @@
+error: failed to find an overloaded call trait for closure call
+ --> $DIR/fn-fn_mut-call-ill-formed.rs:42:5
+ |
+LL | a();
+ | ^^^
+ |
+ = help: make sure the `fn`/`fn_mut`/`fn_once` lang items are defined and have correctly defined `call`/`call_mut`/`call_once` methods
+
+error: failed to find an overloaded call trait for closure call
+ --> $DIR/fn-fn_mut-call-ill-formed.rs:47:5
+ |
+LL | b();
+ | ^^^
+ |
+ = help: make sure the `fn`/`fn_mut`/`fn_once` lang items are defined and have correctly defined `call`/`call_mut`/`call_once` methods
+
+error: aborting due to 2 previous errors
+
diff --git a/tests/ui/lang-items/fn-fn_mut-call-ill-formed.fn_once_bad_item.stderr b/tests/ui/lang-items/fn-fn_mut-call-ill-formed.fn_once_bad_item.stderr
new file mode 100644
index 000000000..02e33c597
--- /dev/null
+++ b/tests/ui/lang-items/fn-fn_mut-call-ill-formed.fn_once_bad_item.stderr
@@ -0,0 +1,18 @@
+error: failed to find an overloaded call trait for closure call
+ --> $DIR/fn-fn_mut-call-ill-formed.rs:42:5
+ |
+LL | a();
+ | ^^^
+ |
+ = help: make sure the `fn`/`fn_mut`/`fn_once` lang items are defined and have correctly defined `call`/`call_mut`/`call_once` methods
+
+error: failed to find an overloaded call trait for closure call
+ --> $DIR/fn-fn_mut-call-ill-formed.rs:47:5
+ |
+LL | b();
+ | ^^^
+ |
+ = help: make sure the `fn`/`fn_mut`/`fn_once` lang items are defined and have correctly defined `call`/`call_mut`/`call_once` methods
+
+error: aborting due to 2 previous errors
+
diff --git a/tests/ui/lang-items/fn-fn_mut-call-ill-formed.fn_once_bad_sig.stderr b/tests/ui/lang-items/fn-fn_mut-call-ill-formed.fn_once_bad_sig.stderr
new file mode 100644
index 000000000..02e33c597
--- /dev/null
+++ b/tests/ui/lang-items/fn-fn_mut-call-ill-formed.fn_once_bad_sig.stderr
@@ -0,0 +1,18 @@
+error: failed to find an overloaded call trait for closure call
+ --> $DIR/fn-fn_mut-call-ill-formed.rs:42:5
+ |
+LL | a();
+ | ^^^
+ |
+ = help: make sure the `fn`/`fn_mut`/`fn_once` lang items are defined and have correctly defined `call`/`call_mut`/`call_once` methods
+
+error: failed to find an overloaded call trait for closure call
+ --> $DIR/fn-fn_mut-call-ill-formed.rs:47:5
+ |
+LL | b();
+ | ^^^
+ |
+ = help: make sure the `fn`/`fn_mut`/`fn_once` lang items are defined and have correctly defined `call`/`call_mut`/`call_once` methods
+
+error: aborting due to 2 previous errors
+
diff --git a/tests/ui/lang-items/fn-fn_mut-call-ill-formed.rs b/tests/ui/lang-items/fn-fn_mut-call-ill-formed.rs
index 52bd8136d..757c6538d 100644
--- a/tests/ui/lang-items/fn-fn_mut-call-ill-formed.rs
+++ b/tests/ui/lang-items/fn-fn_mut-call-ill-formed.rs
@@ -1,27 +1,49 @@
-// Make sure that an error is reported if the `call` function of the
-// `fn`/`fn_mut` lang item is grossly ill-formed.
+// revisions: fn_once_bad_item fn_once_bad_sig fn_mut_bad_item fn_mut_bad_sig fn_bad_item fn_bad_sig
#![feature(lang_items)]
#![feature(no_core)]
#![no_core]
+#[lang = "sized"]
+trait Sized {}
+
+#[cfg(any(fn_bad_item, fn_bad_sig))]
#[lang = "fn"]
trait MyFn<T> {
+ #[cfg(fn_bad_sig)]
+ fn call(i: i32) -> i32 { 0 }
+
+ #[cfg(fn_bad_item)]
const call: i32 = 42;
- //~^ ERROR: `call` trait item in `fn` lang item must be a function
}
+#[cfg(any(fn_mut_bad_item, fn_mut_bad_sig))]
#[lang = "fn_mut"]
trait MyFnMut<T> {
- fn call(i: i32, j: i32) -> i32 { i + j }
- //~^ ERROR: first argument of `call` in `fn_mut` lang item must be a reference
+ #[cfg(fn_mut_bad_sig)]
+ fn call_mut(i: i32) -> i32 { 0 }
+
+ #[cfg(fn_mut_bad_item)]
+ const call_mut: i32 = 42;
+}
+
+#[cfg(any(fn_once_bad_item, fn_once_bad_sig))]
+#[lang = "fn_once"]
+trait MyFnOnce<T> {
+ #[cfg(fn_once_bad_sig)]
+ fn call_once(i: i32) -> i32 { 0 }
+
+ #[cfg(fn_once_bad_item)]
+ const call_once: i32 = 42;
}
fn main() {
let a = || 42;
a();
+ //~^ ERROR failed to find an overloaded call trait for closure call
let mut i = 0;
- let mut b = || { i += 1; };
+ let mut b = || { };
b();
+ //~^ ERROR failed to find an overloaded call trait for closure call
}
diff --git a/tests/ui/lang-items/fn-fn_mut-call-ill-formed.stderr b/tests/ui/lang-items/fn-fn_mut-call-ill-formed.stderr
deleted file mode 100644
index 82bdae270..000000000
--- a/tests/ui/lang-items/fn-fn_mut-call-ill-formed.stderr
+++ /dev/null
@@ -1,14 +0,0 @@
-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/tests/ui/lang-items/issue-86238.stderr b/tests/ui/lang-items/issue-86238.stderr
index 767e6de22..c6e811a94 100644
--- a/tests/ui/lang-items/issue-86238.stderr
+++ b/tests/ui/lang-items/issue-86238.stderr
@@ -4,7 +4,7 @@ error: failed to find an overloaded call trait for closure call
LL | one()
| ^^^^^
|
- = help: make sure the `fn`/`fn_mut`/`fn_once` lang items are defined and have associated `call`/`call_mut`/`call_once` functions
+ = help: make sure the `fn`/`fn_mut`/`fn_once` lang items are defined and have correctly defined `call`/`call_mut`/`call_once` methods
error: aborting due to previous error
diff --git a/tests/ui/lang-items/lang-item-missing-generator.rs b/tests/ui/lang-items/lang-item-missing-generator.rs
deleted file mode 100644
index 9b9aff38e..000000000
--- a/tests/ui/lang-items/lang-item-missing-generator.rs
+++ /dev/null
@@ -1,21 +0,0 @@
-// error-pattern: requires `generator` lang_item
-#![feature(no_core, lang_items, unboxed_closures, tuple_trait)]
-#![no_core]
-
-#[lang = "sized"] pub trait Sized { }
-
-#[lang = "tuple_trait"] pub trait Tuple { }
-
-#[lang = "fn_once"]
-#[rustc_paren_sugar]
-pub trait FnOnce<Args: Tuple> {
- type Output;
-
- extern "rust-call" fn call_once(self, args: Args) -> Self::Output;
-}
-
-pub fn abc() -> impl FnOnce(f32) {
- |_| {}
-}
-
-fn main() {}
diff --git a/tests/ui/lang-items/lang-item-missing-generator.stderr b/tests/ui/lang-items/lang-item-missing-generator.stderr
deleted file mode 100644
index a24fdb5fb..000000000
--- a/tests/ui/lang-items/lang-item-missing-generator.stderr
+++ /dev/null
@@ -1,15 +0,0 @@
-error[E0635]: unknown feature `tuple_trait`
- --> $DIR/lang-item-missing-generator.rs:2:51
- |
-LL | #![feature(no_core, lang_items, unboxed_closures, tuple_trait)]
- | ^^^^^^^^^^^
-
-error: requires `generator` lang_item
- --> $DIR/lang-item-missing-generator.rs:17:17
- |
-LL | pub fn abc() -> impl FnOnce(f32) {
- | ^^^^^^^^^^^^^^^^
-
-error: aborting due to 2 previous errors
-
-For more information about this error, try `rustc --explain E0635`.
diff --git a/tests/ui/late-bound-lifetimes/mismatched_arg_count.rs b/tests/ui/late-bound-lifetimes/mismatched_arg_count.rs
index 0b331e203..792563fd8 100644
--- a/tests/ui/late-bound-lifetimes/mismatched_arg_count.rs
+++ b/tests/ui/late-bound-lifetimes/mismatched_arg_count.rs
@@ -7,6 +7,6 @@ trait Trait<'a> {
type Alias<'a, T> = <T as Trait<'a>>::Assoc;
fn bar<'a, T: Trait<'a>>(_: Alias<'a, 'a, T>) {}
-//~^ error: this type alias takes 1 lifetime argument but 2 lifetime arguments were supplied
+//~^ error: type alias takes 1 lifetime argument but 2 lifetime arguments were supplied
fn main() {}
diff --git a/tests/ui/late-bound-lifetimes/mismatched_arg_count.stderr b/tests/ui/late-bound-lifetimes/mismatched_arg_count.stderr
index 3704d9bb9..de58a014e 100644
--- a/tests/ui/late-bound-lifetimes/mismatched_arg_count.stderr
+++ b/tests/ui/late-bound-lifetimes/mismatched_arg_count.stderr
@@ -1,4 +1,4 @@
-error[E0107]: this type alias takes 1 lifetime argument but 2 lifetime arguments were supplied
+error[E0107]: type alias takes 1 lifetime argument but 2 lifetime arguments were supplied
--> $DIR/mismatched_arg_count.rs:9:29
|
LL | fn bar<'a, T: Trait<'a>>(_: Alias<'a, 'a, T>) {}
diff --git a/tests/ui/layout/valid_range_oob.stderr b/tests/ui/layout/valid_range_oob.stderr
index 7398f0164..a3a514fb8 100644
--- a/tests/ui/layout/valid_range_oob.stderr
+++ b/tests/ui/layout/valid_range_oob.stderr
@@ -1,4 +1,4 @@
-error: internal compiler error: unexpected panic
+error: the compiler unexpectedly panicked. this is a bug.
query stack during panic:
#0 [layout_of] computing layout of `Foo`
diff --git a/tests/ui/let-else/accidental-if.rs b/tests/ui/let-else/accidental-if.rs
new file mode 100644
index 000000000..3fba63043
--- /dev/null
+++ b/tests/ui/let-else/accidental-if.rs
@@ -0,0 +1,6 @@
+fn main() {
+ let x = Some(123);
+ if let Some(y) = x else { //~ ERROR this `if` expression is missing a block
+ return;
+ };
+}
diff --git a/tests/ui/let-else/accidental-if.stderr b/tests/ui/let-else/accidental-if.stderr
new file mode 100644
index 000000000..57e525917
--- /dev/null
+++ b/tests/ui/let-else/accidental-if.stderr
@@ -0,0 +1,19 @@
+error: this `if` expression is missing a block after the condition
+ --> $DIR/accidental-if.rs:3:5
+ |
+LL | if let Some(y) = x else {
+ | ^^
+ |
+help: add a block here
+ --> $DIR/accidental-if.rs:3:23
+ |
+LL | if let Some(y) = x else {
+ | ^
+help: remove the `if` if you meant to write a `let...else` statement
+ |
+LL - if let Some(y) = x else {
+LL + let Some(y) = x else {
+ |
+
+error: aborting due to previous error
+
diff --git a/tests/ui/let-else/issue-94176.stderr b/tests/ui/let-else/issue-94176.stderr
index 0cb97acee..6a015aced 100644
--- a/tests/ui/let-else/issue-94176.stderr
+++ b/tests/ui/let-else/issue-94176.stderr
@@ -2,7 +2,7 @@ error[E0308]: mismatched types
--> $DIR/issue-94176.rs:5:32
|
LL | pub fn test(a: Option<u32>) -> Option<u32> {
- | ---- ^^^^^^^^^^^ expected enum `Option`, found `()`
+ | ---- ^^^^^^^^^^^ expected `Option<u32>`, found `()`
| |
| implicitly returns `()` as its body has no tail or `return` expression
|
diff --git a/tests/ui/let-else/let-else-brace-before-else.fixed b/tests/ui/let-else/let-else-brace-before-else.fixed
index a75c770dd..2d85e3878 100644
--- a/tests/ui/let-else/let-else-brace-before-else.fixed
+++ b/tests/ui/let-else/let-else-brace-before-else.fixed
@@ -7,10 +7,6 @@ fn main() {
//~^ ERROR right curly brace `}` before `else` in a `let...else` statement not allowed
return;
};
- let Some(1) = (loop { break Some(1) }) else {
- //~^ ERROR right curly brace `}` before `else` in a `let...else` statement not allowed
- return;
- };
let 2 = 1 + (match 1 { n => n }) else {
//~^ ERROR right curly brace `}` before `else` in a `let...else` statement not allowed
return;
diff --git a/tests/ui/let-else/let-else-brace-before-else.rs b/tests/ui/let-else/let-else-brace-before-else.rs
index 5603b946f..5c3375b3f 100644
--- a/tests/ui/let-else/let-else-brace-before-else.rs
+++ b/tests/ui/let-else/let-else-brace-before-else.rs
@@ -7,10 +7,6 @@ fn main() {
//~^ ERROR right curly brace `}` before `else` in a `let...else` statement not allowed
return;
};
- let Some(1) = loop { break Some(1) } else {
- //~^ ERROR right curly brace `}` before `else` in a `let...else` statement not allowed
- return;
- };
let 2 = 1 + match 1 { n => n } else {
//~^ ERROR right curly brace `}` before `else` in a `let...else` statement not allowed
return;
diff --git a/tests/ui/let-else/let-else-brace-before-else.stderr b/tests/ui/let-else/let-else-brace-before-else.stderr
index cb01e4c18..ee53213d8 100644
--- a/tests/ui/let-else/let-else-brace-before-else.stderr
+++ b/tests/ui/let-else/let-else-brace-before-else.stderr
@@ -10,18 +10,7 @@ LL | let Some(1) = ({ Some(1) }) else {
| + +
error: right curly brace `}` before `else` in a `let...else` statement not allowed
- --> $DIR/let-else-brace-before-else.rs:10:40
- |
-LL | let Some(1) = loop { break Some(1) } else {
- | ^
- |
-help: wrap the expression in parentheses
- |
-LL | let Some(1) = (loop { break Some(1) }) else {
- | + +
-
-error: right curly brace `}` before `else` in a `let...else` statement not allowed
- --> $DIR/let-else-brace-before-else.rs:14:34
+ --> $DIR/let-else-brace-before-else.rs:10:34
|
LL | let 2 = 1 + match 1 { n => n } else {
| ^
@@ -32,7 +21,7 @@ LL | let 2 = 1 + (match 1 { n => n }) else {
| + +
error: right curly brace `}` before `else` in a `let...else` statement not allowed
- --> $DIR/let-else-brace-before-else.rs:18:40
+ --> $DIR/let-else-brace-before-else.rs:14:40
|
LL | let Some(1) = unsafe { unsafe_fn() } else {
| ^
@@ -42,5 +31,5 @@ help: wrap the expression in parentheses
LL | let Some(1) = (unsafe { unsafe_fn() }) else {
| + +
-error: aborting due to 4 previous errors
+error: aborting due to 3 previous errors
diff --git a/tests/ui/let-else/let-else-deref-coercion.stderr b/tests/ui/let-else/let-else-deref-coercion.stderr
index bf78a079c..143b838ba 100644
--- a/tests/ui/let-else/let-else-deref-coercion.stderr
+++ b/tests/ui/let-else/let-else-deref-coercion.stderr
@@ -4,7 +4,7 @@ error[E0308]: mismatched types
LL | let Bar::Present(z) = self else {
| ^^^^^^^^^^^^^^^ ---- this expression has type `&mut Foo`
| |
- | expected struct `Foo`, found enum `Bar`
+ | expected `Foo`, found `Bar`
error[E0308]: mismatched types
--> $DIR/let-else-deref-coercion.rs:68:13
@@ -12,7 +12,7 @@ error[E0308]: mismatched types
LL | let Bar(z) = x;
| ^^^^^^ - this expression has type `&mut irrefutable::Foo`
| |
- | expected struct `Foo`, found struct `Bar`
+ | expected `Foo`, found `Bar`
error: aborting due to 2 previous errors
diff --git a/tests/ui/let-else/let-else-non-diverging.stderr b/tests/ui/let-else/let-else-non-diverging.stderr
index 78551fcc4..661d905cd 100644
--- a/tests/ui/let-else/let-else-non-diverging.stderr
+++ b/tests/ui/let-else/let-else-non-diverging.stderr
@@ -5,7 +5,7 @@ LL | let Some(x) = Some(1) else {
| ________________________________^
LL | | Some(2)
LL | | };
- | |_____^ expected `!`, found enum `Option`
+ | |_____^ expected `!`, found `Option<{integer}>`
|
= note: expected type `!`
found enum `Option<{integer}>`
@@ -32,7 +32,7 @@ error[E0308]: `else` clause of `let...else` does not diverge
--> $DIR/let-else-non-diverging.rs:10:32
|
LL | let Some(x) = Some(1) else { Some(2) };
- | ^^^^^^^^^^^ expected `!`, found enum `Option`
+ | ^^^^^^^^^^^ expected `!`, found `Option<{integer}>`
|
= note: expected type `!`
found enum `Option<{integer}>`
@@ -43,7 +43,7 @@ error[E0308]: `else` clause of `let...else` does not diverge
--> $DIR/let-else-non-diverging.rs:15:32
|
LL | let Some(x) = Some(1) else { foo::<Uninhabited>() };
- | ^^^^^^^^^^^^^^^^^^^^^^^^ expected `!`, found enum `Uninhabited`
+ | ^^^^^^^^^^^^^^^^^^^^^^^^ expected `!`, found `Uninhabited`
|
= note: expected type `!`
found enum `Uninhabited`
diff --git a/tests/ui/let-else/let-else-ref-bindings.stderr b/tests/ui/let-else/let-else-ref-bindings.stderr
index 56b9e0733..ada1805e7 100644
--- a/tests/ui/let-else/let-else-ref-bindings.stderr
+++ b/tests/ui/let-else/let-else-ref-bindings.stderr
@@ -2,7 +2,7 @@ error[E0308]: mismatched types
--> $DIR/let-else-ref-bindings.rs:16:38
|
LL | let Some(ref a): Option<&[u8]> = some else { return };
- | ^^^^ expected `&[u8]`, found struct `Vec`
+ | ^^^^ expected `Option<&[u8]>`, found `Option<Vec<u8>>`
|
= note: expected enum `Option<&[u8]>`
found enum `Option<Vec<u8>>`
@@ -11,7 +11,7 @@ error[E0308]: mismatched types
--> $DIR/let-else-ref-bindings.rs:20:38
|
LL | let Some(ref a): Option<&[u8]> = &some else { return };
- | ^^^^^ expected enum `Option`, found `&Option<Vec<u8>>`
+ | ^^^^^ expected `Option<&[u8]>`, found `&Option<Vec<u8>>`
|
= note: expected enum `Option<&[u8]>`
found reference `&Option<Vec<u8>>`
@@ -20,7 +20,7 @@ error[E0308]: mismatched types
--> $DIR/let-else-ref-bindings.rs:24:34
|
LL | let Some(a): Option<&[u8]> = some else { return };
- | ------------- ^^^^ expected `&[u8]`, found struct `Vec`
+ | ------------- ^^^^ expected `Option<&[u8]>`, found `Option<Vec<u8>>`
| |
| expected due to this
|
@@ -31,7 +31,7 @@ error[E0308]: mismatched types
--> $DIR/let-else-ref-bindings.rs:27:34
|
LL | let Some(a): Option<&[u8]> = &some else { return };
- | ------------- ^^^^^ expected enum `Option`, found `&Option<Vec<u8>>`
+ | ------------- ^^^^^ expected `Option<&[u8]>`, found `&Option<Vec<u8>>`
| |
| expected due to this
|
@@ -42,7 +42,7 @@ error[E0308]: mismatched types
--> $DIR/let-else-ref-bindings.rs:44:46
|
LL | let Some(ref mut a): Option<&mut [u8]> = some else { return };
- | ^^^^ expected `&mut [u8]`, found struct `Vec`
+ | ^^^^ expected `Option<&mut [u8]>`, found `Option<Vec<u8>>`
|
= note: expected enum `Option<&mut [u8]>`
found enum `Option<Vec<u8>>`
@@ -51,7 +51,7 @@ error[E0308]: mismatched types
--> $DIR/let-else-ref-bindings.rs:48:46
|
LL | let Some(ref mut a): Option<&mut [u8]> = &mut some else { return };
- | ^^^^^^^^^ expected enum `Option`, found mutable reference
+ | ^^^^^^^^^ expected `Option<&mut [u8]>`, found `&mut Option<Vec<u8>>`
|
= note: expected enum `Option<&mut [u8]>`
found mutable reference `&mut Option<Vec<u8>>`
@@ -60,7 +60,7 @@ error[E0308]: mismatched types
--> $DIR/let-else-ref-bindings.rs:52:38
|
LL | let Some(a): Option<&mut [u8]> = some else { return };
- | ----------------- ^^^^ expected `&mut [u8]`, found struct `Vec`
+ | ----------------- ^^^^ expected `Option<&mut [u8]>`, found `Option<Vec<u8>>`
| |
| expected due to this
|
@@ -71,7 +71,7 @@ error[E0308]: mismatched types
--> $DIR/let-else-ref-bindings.rs:55:38
|
LL | let Some(a): Option<&mut [u8]> = &mut some else { return };
- | ----------------- ^^^^^^^^^ expected enum `Option`, found mutable reference
+ | ----------------- ^^^^^^^^^ expected `Option<&mut [u8]>`, found `&mut Option<Vec<u8>>`
| |
| expected due to this
|
diff --git a/tests/ui/lifetimes/issue-103582-hint-for-missing-lifetime-bound-on-trait-object-using-type-alias.fixed b/tests/ui/lifetimes/issue-103582-hint-for-missing-lifetime-bound-on-trait-object-using-type-alias.fixed
new file mode 100644
index 000000000..aa3bce294
--- /dev/null
+++ b/tests/ui/lifetimes/issue-103582-hint-for-missing-lifetime-bound-on-trait-object-using-type-alias.fixed
@@ -0,0 +1,45 @@
+// run-rustfix
+
+trait Greeter0 {
+ fn greet(&self);
+}
+
+trait Greeter1 {
+ fn greet(&self);
+}
+
+type BoxedGreeter<'a> = (Box<dyn Greeter0 + 'a>, Box<dyn Greeter1 + 'a>);
+//~^ HELP to declare that the trait object captures data from argument `self`, you can add a lifetime parameter `'a` in the type alias
+
+struct FixedGreeter<'a>(pub &'a str);
+
+impl Greeter0 for FixedGreeter<'_> {
+ fn greet(&self) {
+ println!("0 {}", self.0)
+ }
+}
+
+impl Greeter1 for FixedGreeter<'_> {
+ fn greet(&self) {
+ println!("1 {}", self.0)
+ }
+}
+
+struct Greetings(pub Vec<String>);
+
+impl Greetings {
+ pub fn get(&self, i: usize) -> BoxedGreeter {
+ (Box::new(FixedGreeter(&self.0[i])), Box::new(FixedGreeter(&self.0[i])))
+ //~^ ERROR lifetime may not live long enough
+ }
+}
+
+fn main() {
+ let mut g = Greetings {0 : vec!()};
+ g.0.push("a".to_string());
+ g.0.push("b".to_string());
+ g.get(0).0.greet();
+ g.get(0).1.greet();
+ g.get(1).0.greet();
+ g.get(1).1.greet();
+}
diff --git a/tests/ui/lifetimes/issue-103582-hint-for-missing-lifetime-bound-on-trait-object-using-type-alias.rs b/tests/ui/lifetimes/issue-103582-hint-for-missing-lifetime-bound-on-trait-object-using-type-alias.rs
new file mode 100644
index 000000000..20c88ec69
--- /dev/null
+++ b/tests/ui/lifetimes/issue-103582-hint-for-missing-lifetime-bound-on-trait-object-using-type-alias.rs
@@ -0,0 +1,45 @@
+// run-rustfix
+
+trait Greeter0 {
+ fn greet(&self);
+}
+
+trait Greeter1 {
+ fn greet(&self);
+}
+
+type BoxedGreeter = (Box<dyn Greeter0>, Box<dyn Greeter1>);
+//~^ HELP to declare that the trait object captures data from argument `self`, you can add a lifetime parameter `'a` in the type alias
+
+struct FixedGreeter<'a>(pub &'a str);
+
+impl Greeter0 for FixedGreeter<'_> {
+ fn greet(&self) {
+ println!("0 {}", self.0)
+ }
+}
+
+impl Greeter1 for FixedGreeter<'_> {
+ fn greet(&self) {
+ println!("1 {}", self.0)
+ }
+}
+
+struct Greetings(pub Vec<String>);
+
+impl Greetings {
+ pub fn get(&self, i: usize) -> BoxedGreeter {
+ (Box::new(FixedGreeter(&self.0[i])), Box::new(FixedGreeter(&self.0[i])))
+ //~^ ERROR lifetime may not live long enough
+ }
+}
+
+fn main() {
+ let mut g = Greetings {0 : vec!()};
+ g.0.push("a".to_string());
+ g.0.push("b".to_string());
+ g.get(0).0.greet();
+ g.get(0).1.greet();
+ g.get(1).0.greet();
+ g.get(1).1.greet();
+}
diff --git a/tests/ui/lifetimes/issue-103582-hint-for-missing-lifetime-bound-on-trait-object-using-type-alias.stderr b/tests/ui/lifetimes/issue-103582-hint-for-missing-lifetime-bound-on-trait-object-using-type-alias.stderr
new file mode 100644
index 000000000..808d8bb90
--- /dev/null
+++ b/tests/ui/lifetimes/issue-103582-hint-for-missing-lifetime-bound-on-trait-object-using-type-alias.stderr
@@ -0,0 +1,15 @@
+error: lifetime may not live long enough
+ --> $DIR/issue-103582-hint-for-missing-lifetime-bound-on-trait-object-using-type-alias.rs:32:9
+ |
+LL | pub fn get(&self, i: usize) -> BoxedGreeter {
+ | - let's call the lifetime of this reference `'1`
+LL | (Box::new(FixedGreeter(&self.0[i])), Box::new(FixedGreeter(&self.0[i])))
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ returning this value requires that `'1` must outlive `'static`
+ |
+help: to declare that the trait object captures data from argument `self`, you can add a lifetime parameter `'a` in the type alias
+ |
+LL | type BoxedGreeter<'a> = (Box<dyn Greeter0 + 'a>, Box<dyn Greeter1 + 'a>);
+ | ++++ ++++ ++++
+
+error: aborting due to previous error
+
diff --git a/tests/ui/lifetimes/issue-104432-unused-lifetimes-in-expansion.rs b/tests/ui/lifetimes/issue-104432-unused-lifetimes-in-expansion.rs
new file mode 100644
index 000000000..5d5429ec8
--- /dev/null
+++ b/tests/ui/lifetimes/issue-104432-unused-lifetimes-in-expansion.rs
@@ -0,0 +1,12 @@
+// check-pass
+
+#![deny(unused_lifetimes)]
+trait Trait2 {
+ type As;
+}
+
+// we should not warn about an unused lifetime about code generated from this proc macro here
+#[derive(Clone)]
+struct ShimMethod4<T: Trait2 + 'static>(pub &'static dyn for<'s> Fn(&'s mut T::As));
+
+pub fn main() {}
diff --git a/tests/ui/lifetimes/issue-105227.stderr b/tests/ui/lifetimes/issue-105227.stderr
index d21145937..b514db461 100644
--- a/tests/ui/lifetimes/issue-105227.stderr
+++ b/tests/ui/lifetimes/issue-105227.stderr
@@ -2,7 +2,9 @@ error[E0700]: hidden type for `impl Iterator<Item = char>` captures lifetime tha
--> $DIR/issue-105227.rs:7:5
|
LL | fn chars0(v :(& str, &str)) -> impl Iterator<Item = char> {
- | ----- hidden type `std::iter::Chain<Chars<'_>, Chars<'_>>` captures the anonymous lifetime defined here
+ | ----- -------------------------- opaque type defined here
+ | |
+ | hidden type `std::iter::Chain<Chars<'_>, Chars<'_>>` captures the anonymous lifetime defined here
LL |
LL | v.0.chars().chain(v.1.chars())
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -16,7 +18,9 @@ error[E0700]: hidden type for `impl Iterator<Item = char>` captures lifetime tha
--> $DIR/issue-105227.rs:13:5
|
LL | fn chars1(v0 : & str, v1 : &str) -> impl Iterator<Item = char> {
- | ----- hidden type `std::iter::Chain<Chars<'_>, Chars<'_>>` captures the anonymous lifetime defined here
+ | ----- -------------------------- opaque type defined here
+ | |
+ | hidden type `std::iter::Chain<Chars<'_>, Chars<'_>>` captures the anonymous lifetime defined here
LL |
LL | v0.chars().chain(v1.chars())
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -31,7 +35,10 @@ error[E0700]: hidden type for `impl Iterator<Item = char>` captures lifetime tha
|
LL | fn chars2<'b>(v0 : &str, v1 : &'_ str, v2 : &'b str) ->
| ---- hidden type `std::iter::Chain<Chars<'_>, Chars<'_>>` captures the anonymous lifetime defined here
-...
+LL |
+LL | (impl Iterator<Item = char>, &'b str)
+ | -------------------------- opaque type defined here
+LL | {
LL | (v0.chars().chain(v1.chars()), v2)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
diff --git a/tests/ui/lifetimes/issue-107492-default-value-for-lifetime.rs b/tests/ui/lifetimes/issue-107492-default-value-for-lifetime.rs
new file mode 100644
index 000000000..f129035d0
--- /dev/null
+++ b/tests/ui/lifetimes/issue-107492-default-value-for-lifetime.rs
@@ -0,0 +1,6 @@
+pub struct DefaultLifetime<'a, 'b = 'static> {
+ //~^ ERROR unexpected default lifetime parameter
+ _marker: std::marker::PhantomData<&'a &'b ()>,
+}
+
+fn main(){}
diff --git a/tests/ui/lifetimes/issue-107492-default-value-for-lifetime.stderr b/tests/ui/lifetimes/issue-107492-default-value-for-lifetime.stderr
new file mode 100644
index 000000000..c235c3180
--- /dev/null
+++ b/tests/ui/lifetimes/issue-107492-default-value-for-lifetime.stderr
@@ -0,0 +1,8 @@
+error: unexpected default lifetime parameter
+ --> $DIR/issue-107492-default-value-for-lifetime.rs:1:35
+ |
+LL | pub struct DefaultLifetime<'a, 'b = 'static> {
+ | ^^^^^^^^^ lifetime parameters cannot have default values
+
+error: aborting due to previous error
+
diff --git a/tests/ui/lifetimes/issue-107988.rs b/tests/ui/lifetimes/issue-107988.rs
new file mode 100644
index 000000000..92cb60a06
--- /dev/null
+++ b/tests/ui/lifetimes/issue-107988.rs
@@ -0,0 +1,13 @@
+pub trait TraitEngine<'tcx>: 'tcx {}
+
+pub trait TraitEngineExt<'tcx> {
+ fn register_predicate_obligations(&mut self);
+}
+
+impl<T: ?Sized + TraitEngine<'tcx>> TraitEngineExt<'tcx> for T {
+ //~^ ERROR use of undeclared lifetime name `'tcx`
+ //~| ERROR use of undeclared lifetime name `'tcx`
+ fn register_predicate_obligations(&mut self) {}
+}
+
+fn main() {}
diff --git a/tests/ui/lifetimes/issue-107988.stderr b/tests/ui/lifetimes/issue-107988.stderr
new file mode 100644
index 000000000..c2d8c7050
--- /dev/null
+++ b/tests/ui/lifetimes/issue-107988.stderr
@@ -0,0 +1,27 @@
+error[E0261]: use of undeclared lifetime name `'tcx`
+ --> $DIR/issue-107988.rs:7:52
+ |
+LL | impl<T: ?Sized + TraitEngine<'tcx>> TraitEngineExt<'tcx> for T {
+ | - ^^^^ undeclared lifetime
+ | |
+ | help: consider introducing lifetime `'tcx` here: `'tcx,`
+
+error[E0261]: use of undeclared lifetime name `'tcx`
+ --> $DIR/issue-107988.rs:7:30
+ |
+LL | impl<T: ?Sized + TraitEngine<'tcx>> TraitEngineExt<'tcx> for T {
+ | ^^^^ undeclared lifetime
+ |
+ = note: for more information on higher-ranked polymorphism, visit https://doc.rust-lang.org/nomicon/hrtb.html
+help: consider making the bound lifetime-generic with a new `'tcx` lifetime
+ |
+LL | impl<T: ?Sized + for<'tcx> TraitEngine<'tcx>> TraitEngineExt<'tcx> for T {
+ | +++++++++
+help: consider introducing lifetime `'tcx` here
+ |
+LL | impl<'tcx, T: ?Sized + TraitEngine<'tcx>> TraitEngineExt<'tcx> for T {
+ | +++++
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0261`.
diff --git a/tests/ui/lifetimes/issue-17728.stderr b/tests/ui/lifetimes/issue-17728.stderr
index 3b25902d7..535073d6e 100644
--- a/tests/ui/lifetimes/issue-17728.stderr
+++ b/tests/ui/lifetimes/issue-17728.stderr
@@ -9,7 +9,7 @@ LL | | "n" | "north" => RoomDirection::North,
LL | | "down" => RoomDirection::Down,
| | ------------------- this and all prior arms are found to be of type `RoomDirection`
LL | | _ => None
- | | ^^^^ expected enum `RoomDirection`, found enum `Option`
+ | | ^^^^ expected `RoomDirection`, found `Option<_>`
LL | | }
| |_____- `match` arms have incompatible types
|
diff --git a/tests/ui/lifetimes/issue-26638.stderr b/tests/ui/lifetimes/issue-26638.stderr
index 98d39d614..30afcecf8 100644
--- a/tests/ui/lifetimes/issue-26638.stderr
+++ b/tests/ui/lifetimes/issue-26638.stderr
@@ -38,11 +38,11 @@ error[E0308]: mismatched types
--> $DIR/issue-26638.rs:1:69
|
LL | fn parse_type(iter: Box<dyn Iterator<Item=&str>+'static>) -> &str { iter.next() }
- | ---- ^^^^^^^^^^^ expected `&str`, found enum `Option`
+ | ---- ^^^^^^^^^^^ expected `&str`, found `Option<&str>`
| |
- | expected `&'static str` because of return type
+ | expected `&str` because of return type
|
- = note: expected reference `&'static str`
+ = note: expected reference `&str`
found enum `Option<&str>`
error[E0061]: this function takes 1 argument but 0 arguments were supplied
@@ -60,7 +60,7 @@ error[E0308]: mismatched types
--> $DIR/issue-26638.rs:5:47
|
LL | fn parse_type_2(iter: fn(&u8)->&u8) -> &str { iter() }
- | ---- ^^^^^^ expected `str`, found `u8`
+ | ---- ^^^^^^ expected `&str`, found `&u8`
| |
| expected `&'static str` because of return type
|
diff --git a/tests/ui/lifetimes/issue-69314.fixed b/tests/ui/lifetimes/issue-69314.fixed
new file mode 100644
index 000000000..41116d4ea
--- /dev/null
+++ b/tests/ui/lifetimes/issue-69314.fixed
@@ -0,0 +1,22 @@
+// run-rustfix
+// edition:2021
+#![allow(dead_code, unused_mut, unused_variables)]
+struct A {}
+struct Msg<'a> {
+ s: &'a [i32],
+}
+impl A {
+ async fn g(buf: &[i32]) -> Msg<'_> {
+ Msg { s: &buf[0..1] }
+ }
+ async fn f() {
+ let mut buf = [0; 512];
+ let m2 = &buf[..]; //~ ERROR `buf` does not live long enough
+ let m = Self::g(m2).await;
+ Self::f2(m).await;
+ }
+ async fn f2(m: Msg<'_>) {}
+ //~^ ERROR implicit elided lifetime not allowed here
+}
+
+fn main() {}
diff --git a/tests/ui/lifetimes/issue-69314.rs b/tests/ui/lifetimes/issue-69314.rs
new file mode 100644
index 000000000..17445341e
--- /dev/null
+++ b/tests/ui/lifetimes/issue-69314.rs
@@ -0,0 +1,22 @@
+// run-rustfix
+// edition:2021
+#![allow(dead_code, unused_mut, unused_variables)]
+struct A {}
+struct Msg<'a> {
+ s: &'a [i32],
+}
+impl A {
+ async fn g(buf: &[i32]) -> Msg<'_> {
+ Msg { s: &buf[0..1] }
+ }
+ async fn f() {
+ let mut buf = [0; 512];
+ let m2 = &buf[..]; //~ ERROR `buf` does not live long enough
+ let m = Self::g(m2).await;
+ Self::f2(m).await;
+ }
+ async fn f2(m: Msg) {}
+ //~^ ERROR implicit elided lifetime not allowed here
+}
+
+fn main() {}
diff --git a/tests/ui/lifetimes/issue-69314.stderr b/tests/ui/lifetimes/issue-69314.stderr
new file mode 100644
index 000000000..7ae678928
--- /dev/null
+++ b/tests/ui/lifetimes/issue-69314.stderr
@@ -0,0 +1,26 @@
+error[E0726]: implicit elided lifetime not allowed here
+ --> $DIR/issue-69314.rs:18:20
+ |
+LL | async fn f2(m: Msg) {}
+ | ^^^ expected lifetime parameter
+ |
+help: indicate the anonymous lifetime
+ |
+LL | async fn f2(m: Msg<'_>) {}
+ | ++++
+
+error[E0597]: `buf` does not live long enough
+ --> $DIR/issue-69314.rs:14:19
+ |
+LL | let m2 = &buf[..];
+ | ^^^ borrowed value does not live long enough
+LL | let m = Self::g(m2).await;
+ | ----------- argument requires that `buf` is borrowed for `'static`
+LL | Self::f2(m).await;
+LL | }
+ | - `buf` dropped here while still borrowed
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0597, E0726.
+For more information about an error, try `rustc --explain E0597`.
diff --git a/tests/ui/lifetimes/issue-90600-expected-return-static-indirect.stderr b/tests/ui/lifetimes/issue-90600-expected-return-static-indirect.stderr
index 99e1e7217..3602de8dd 100644
--- a/tests/ui/lifetimes/issue-90600-expected-return-static-indirect.stderr
+++ b/tests/ui/lifetimes/issue-90600-expected-return-static-indirect.stderr
@@ -1,6 +1,8 @@
error[E0597]: `foo` does not live long enough
--> $DIR/issue-90600-expected-return-static-indirect.rs:7:32
|
+LL | fn inner(mut foo: &[u8]) {
+ | ------- binding `foo` declared here
LL | let refcell = RefCell::new(&mut foo);
| ^^^^^^^^ borrowed value does not live long enough
LL |
diff --git a/tests/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-return-type-is-anon.stderr b/tests/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-return-type-is-anon.stderr
index 4bcd7cf95..6fd7f67d1 100644
--- a/tests/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-return-type-is-anon.stderr
+++ b/tests/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-return-type-is-anon.stderr
@@ -7,7 +7,7 @@ LL | fn foo<'a>(&self, x: &'a i32) -> &i32 {
| lifetime `'a` defined here
LL |
LL | x
- | ^ associated function was supposed to return data with lifetime `'1` but it is returning data with lifetime `'a`
+ | ^ method was supposed to return data with lifetime `'1` but it is returning data with lifetime `'a`
error: aborting due to previous error
diff --git a/tests/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-self-is-anon.stderr b/tests/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-self-is-anon.stderr
index 34a64f8a6..2687266e0 100644
--- a/tests/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-self-is-anon.stderr
+++ b/tests/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-self-is-anon.stderr
@@ -7,7 +7,7 @@ LL | fn foo<'a>(&self, x: &'a Foo) -> &'a Foo {
| lifetime `'a` defined here
LL |
LL | if true { x } else { self }
- | ^^^^ associated function was supposed to return data with lifetime `'a` but it is returning data with lifetime `'1`
+ | ^^^^ method was supposed to return data with lifetime `'a` but it is returning data with lifetime `'1`
error: aborting due to previous error
diff --git a/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-return-type-is-anon.stderr b/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-return-type-is-anon.stderr
index 5601335d2..9ff5e42d7 100644
--- a/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-return-type-is-anon.stderr
+++ b/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-return-type-is-anon.stderr
@@ -6,7 +6,7 @@ LL | fn foo<'a>(&self, x: &i32) -> &i32 {
| |
| let's call the lifetime of this reference `'2`
LL | x
- | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+ | ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
|
help: consider introducing a named lifetime parameter and update trait if needed
|
diff --git a/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-self-is-anon.stderr b/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-self-is-anon.stderr
index e221902c4..e4c855e11 100644
--- a/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-self-is-anon.stderr
+++ b/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-self-is-anon.stderr
@@ -6,7 +6,7 @@ LL | fn foo<'a>(&self, x: &Foo) -> &Foo {
| |
| let's call the lifetime of this reference `'2`
LL | if true { x } else { self }
- | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+ | ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
|
help: consider introducing a named lifetime parameter and update trait if needed
|
diff --git a/tests/ui/lifetimes/unusual-rib-combinations.rs b/tests/ui/lifetimes/unusual-rib-combinations.rs
index b4c86aab8..1c122f42e 100644
--- a/tests/ui/lifetimes/unusual-rib-combinations.rs
+++ b/tests/ui/lifetimes/unusual-rib-combinations.rs
@@ -23,6 +23,6 @@ fn c<T = u8()>() {}
// Elided lifetime in path in ConstGeneric
fn d<const C: S>() {}
//~^ ERROR missing lifetime specifier
-//~| ERROR `S<'static>` is forbidden as the type of a const generic parameter
+//~| ERROR `S<'_>` is forbidden as the type of a const generic parameter
fn main() {}
diff --git a/tests/ui/lifetimes/unusual-rib-combinations.stderr b/tests/ui/lifetimes/unusual-rib-combinations.stderr
index 6d7b42506..68f4fce01 100644
--- a/tests/ui/lifetimes/unusual-rib-combinations.stderr
+++ b/tests/ui/lifetimes/unusual-rib-combinations.stderr
@@ -46,7 +46,7 @@ LL | fn a() -> [u8; foo::()] {
= note: expected type `usize`
found fn item `fn() {foo}`
-error: `S<'static>` is forbidden as the type of a const generic parameter
+error: `S<'_>` is forbidden as the type of a const generic parameter
--> $DIR/unusual-rib-combinations.rs:24:15
|
LL | fn d<const C: S>() {}
diff --git a/tests/ui/lint/dead-code/in-closure.rs b/tests/ui/lint/dead-code/in-closure.rs
new file mode 100644
index 000000000..c55634405
--- /dev/null
+++ b/tests/ui/lint/dead-code/in-closure.rs
@@ -0,0 +1,16 @@
+// edition: 2021
+
+#![deny(dead_code)]
+
+pub fn foo() {
+ let closure = || {
+ fn a() {} //~ ERROR function `a` is never used
+ };
+ closure()
+}
+
+pub async fn async_foo() {
+ const A: usize = 1; //~ ERROR constant `A` is never used
+}
+
+fn main() {}
diff --git a/tests/ui/lint/dead-code/in-closure.stderr b/tests/ui/lint/dead-code/in-closure.stderr
new file mode 100644
index 000000000..deb276be7
--- /dev/null
+++ b/tests/ui/lint/dead-code/in-closure.stderr
@@ -0,0 +1,20 @@
+error: function `a` is never used
+ --> $DIR/in-closure.rs:7:12
+ |
+LL | fn a() {}
+ | ^
+ |
+note: the lint level is defined here
+ --> $DIR/in-closure.rs:3:9
+ |
+LL | #![deny(dead_code)]
+ | ^^^^^^^^^
+
+error: constant `A` is never used
+ --> $DIR/in-closure.rs:13:11
+ |
+LL | const A: usize = 1;
+ | ^
+
+error: aborting due to 2 previous errors
+
diff --git a/tests/ui/lint/dead-code/issue-85255.rs b/tests/ui/lint/dead-code/issue-85255.rs
index 043f68137..1978bd4e8 100644
--- a/tests/ui/lint/dead-code/issue-85255.rs
+++ b/tests/ui/lint/dead-code/issue-85255.rs
@@ -11,8 +11,8 @@ struct Foo {
struct Bar;
impl Bar {
- fn a(&self) -> i32 { 5 } //~ WARNING: associated function `a` is never used
- pub fn b(&self) -> i32 { 6 } //~ WARNING: associated function `b` is never used
+ fn a(&self) -> i32 { 5 } //~ WARNING: method `a` is never used
+ pub fn b(&self) -> i32 { 6 } //~ WARNING: method `b` is never used
}
pub(crate) struct Foo1 {
@@ -23,8 +23,8 @@ pub(crate) struct Foo1 {
pub(crate) struct Bar1;
impl Bar1 {
- fn a(&self) -> i32 { 5 } //~ WARNING: associated function `a` is never used
- pub fn b(&self) -> i32 { 6 } //~ WARNING: associated function `b` is never used
+ fn a(&self) -> i32 { 5 } //~ WARNING: method `a` is never used
+ pub fn b(&self) -> i32 { 6 } //~ WARNING: method `b` is never used
}
pub(crate) struct Foo2 {
@@ -35,8 +35,8 @@ pub(crate) struct Foo2 {
pub(crate) struct Bar2;
impl Bar2 {
- fn a(&self) -> i32 { 5 } //~ WARNING: associated function `a` is never used
- pub fn b(&self) -> i32 { 6 } //~ WARNING: associated function `b` is never used
+ fn a(&self) -> i32 { 5 } //~ WARNING: method `a` is never used
+ pub fn b(&self) -> i32 { 6 } //~ WARNING: method `b` is never used
}
diff --git a/tests/ui/lint/dead-code/issue-85255.stderr b/tests/ui/lint/dead-code/issue-85255.stderr
index 3497b952f..58a19cf3c 100644
--- a/tests/ui/lint/dead-code/issue-85255.stderr
+++ b/tests/ui/lint/dead-code/issue-85255.stderr
@@ -34,37 +34,37 @@ LL | a: i32,
LL | pub b: i32,
| ^
-warning: associated function `a` is never used
+warning: method `a` is never used
--> $DIR/issue-85255.rs:14:8
|
LL | fn a(&self) -> i32 { 5 }
| ^
-warning: associated function `b` is never used
+warning: method `b` is never used
--> $DIR/issue-85255.rs:15:12
|
LL | pub fn b(&self) -> i32 { 6 }
| ^
-warning: associated function `a` is never used
+warning: method `a` is never used
--> $DIR/issue-85255.rs:26:8
|
LL | fn a(&self) -> i32 { 5 }
| ^
-warning: associated function `b` is never used
+warning: method `b` is never used
--> $DIR/issue-85255.rs:27:12
|
LL | pub fn b(&self) -> i32 { 6 }
| ^
-warning: associated function `a` is never used
+warning: method `a` is never used
--> $DIR/issue-85255.rs:38:8
|
LL | fn a(&self) -> i32 { 5 }
| ^
-warning: associated function `b` is never used
+warning: method `b` is never used
--> $DIR/issue-85255.rs:39:12
|
LL | pub fn b(&self) -> i32 { 6 }
diff --git a/tests/ui/lint/dead-code/lint-dead-code-3.rs b/tests/ui/lint/dead-code/lint-dead-code-3.rs
index 293fcdbc5..20b568054 100644
--- a/tests/ui/lint/dead-code/lint-dead-code-3.rs
+++ b/tests/ui/lint/dead-code/lint-dead-code-3.rs
@@ -13,7 +13,7 @@ extern "C" {
struct Foo; //~ ERROR: struct `Foo` is never constructed
impl Foo {
- fn foo(&self) { //~ ERROR: associated function `foo` is never used
+ fn foo(&self) { //~ ERROR: method `foo` is never used
bar()
}
}
diff --git a/tests/ui/lint/dead-code/lint-dead-code-3.stderr b/tests/ui/lint/dead-code/lint-dead-code-3.stderr
index 26fc13bae..797b7559c 100644
--- a/tests/ui/lint/dead-code/lint-dead-code-3.stderr
+++ b/tests/ui/lint/dead-code/lint-dead-code-3.stderr
@@ -34,7 +34,7 @@ error: function `blah` is never used
LL | fn blah() {}
| ^^^^
-error: associated function `foo` is never used
+error: method `foo` is never used
--> $DIR/lint-dead-code-3.rs:16:8
|
LL | fn foo(&self) {
diff --git a/tests/ui/lint/invalid_value-polymorphic.rs b/tests/ui/lint/invalid_value-polymorphic.rs
new file mode 100644
index 000000000..055173e98
--- /dev/null
+++ b/tests/ui/lint/invalid_value-polymorphic.rs
@@ -0,0 +1,8 @@
+// compile-flags: --crate-type=lib -Zmir-enable-passes=+InstCombine
+// build-pass
+
+#![feature(core_intrinsics)]
+
+pub fn generic<T>() {
+ core::intrinsics::assert_mem_uninitialized_valid::<&T>();
+}
diff --git a/tests/ui/lint/invalid_value.stderr b/tests/ui/lint/invalid_value.stderr
index 48fd4169d..57531b096 100644
--- a/tests/ui/lint/invalid_value.stderr
+++ b/tests/ui/lint/invalid_value.stderr
@@ -61,10 +61,7 @@ error: the type `!` does not permit zero-initialization
--> $DIR/invalid_value.rs:65:23
|
LL | let _val: ! = mem::zeroed();
- | ^^^^^^^^^^^^^
- | |
- | this code causes undefined behavior when executed
- | help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done
+ | ^^^^^^^^^^^^^ this code causes undefined behavior when executed
|
= note: the `!` type has no valid value
@@ -72,10 +69,7 @@ error: the type `!` does not permit being left uninitialized
--> $DIR/invalid_value.rs:66:23
|
LL | let _val: ! = mem::uninitialized();
- | ^^^^^^^^^^^^^^^^^^^^
- | |
- | this code causes undefined behavior when executed
- | help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done
+ | ^^^^^^^^^^^^^^^^^^^^ this code causes undefined behavior when executed
|
= note: the `!` type has no valid value
@@ -83,10 +77,7 @@ error: the type `(i32, !)` does not permit zero-initialization
--> $DIR/invalid_value.rs:68:30
|
LL | let _val: (i32, !) = mem::zeroed();
- | ^^^^^^^^^^^^^
- | |
- | this code causes undefined behavior when executed
- | help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done
+ | ^^^^^^^^^^^^^ this code causes undefined behavior when executed
|
= note: the `!` type has no valid value
@@ -94,10 +85,7 @@ error: the type `(i32, !)` does not permit being left uninitialized
--> $DIR/invalid_value.rs:69:30
|
LL | let _val: (i32, !) = mem::uninitialized();
- | ^^^^^^^^^^^^^^^^^^^^
- | |
- | this code causes undefined behavior when executed
- | help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done
+ | ^^^^^^^^^^^^^^^^^^^^ this code causes undefined behavior when executed
|
= note: integers must be initialized
@@ -105,10 +93,7 @@ error: the type `Void` does not permit zero-initialization
--> $DIR/invalid_value.rs:71:26
|
LL | let _val: Void = mem::zeroed();
- | ^^^^^^^^^^^^^
- | |
- | this code causes undefined behavior when executed
- | help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done
+ | ^^^^^^^^^^^^^ this code causes undefined behavior when executed
|
note: enums with no inhabited variants have no valid value
--> $DIR/invalid_value.rs:12:1
@@ -120,10 +105,7 @@ error: the type `Void` does not permit being left uninitialized
--> $DIR/invalid_value.rs:72:26
|
LL | let _val: Void = mem::uninitialized();
- | ^^^^^^^^^^^^^^^^^^^^
- | |
- | this code causes undefined behavior when executed
- | help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done
+ | ^^^^^^^^^^^^^^^^^^^^ this code causes undefined behavior when executed
|
note: enums with no inhabited variants have no valid value
--> $DIR/invalid_value.rs:12:1
@@ -405,10 +387,7 @@ error: the type `TwoUninhabited` does not permit zero-initialization
--> $DIR/invalid_value.rs:104:36
|
LL | let _val: TwoUninhabited = mem::zeroed();
- | ^^^^^^^^^^^^^
- | |
- | this code causes undefined behavior when executed
- | help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done
+ | ^^^^^^^^^^^^^ this code causes undefined behavior when executed
|
note: enums with no inhabited variants have no valid value
--> $DIR/invalid_value.rs:42:1
@@ -420,10 +399,7 @@ error: the type `TwoUninhabited` does not permit being left uninitialized
--> $DIR/invalid_value.rs:105:36
|
LL | let _val: TwoUninhabited = mem::uninitialized();
- | ^^^^^^^^^^^^^^^^^^^^
- | |
- | this code causes undefined behavior when executed
- | help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done
+ | ^^^^^^^^^^^^^^^^^^^^ this code causes undefined behavior when executed
|
note: enums with no inhabited variants have no valid value
--> $DIR/invalid_value.rs:42:1
diff --git a/tests/ui/lint/issue-104897.rs b/tests/ui/lint/issue-104897.rs
index 5fbc658f1..2d298aff9 100644
--- a/tests/ui/lint/issue-104897.rs
+++ b/tests/ui/lint/issue-104897.rs
@@ -1,6 +1,5 @@
// error-pattern: this file contains an unclosed delimiter
// error-pattern: this file contains an unclosed delimiter
// error-pattern: this file contains an unclosed delimiter
-// error-pattern: format argument must be a string literal
fn f(){(print!(á
diff --git a/tests/ui/lint/issue-104897.stderr b/tests/ui/lint/issue-104897.stderr
index 817a93c2f..728d51f34 100644
--- a/tests/ui/lint/issue-104897.stderr
+++ b/tests/ui/lint/issue-104897.stderr
@@ -1,5 +1,5 @@
error: this file contains an unclosed delimiter
- --> $DIR/issue-104897.rs:6:18
+ --> $DIR/issue-104897.rs:5:18
|
LL | fn f(){(print!(á
| -- - ^
@@ -8,36 +8,5 @@ LL | fn f(){(print!(á
| |unclosed delimiter
| unclosed delimiter
-error: this file contains an unclosed delimiter
- --> $DIR/issue-104897.rs:6:18
- |
-LL | fn f(){(print!(á
- | -- - ^
- | || |
- | || unclosed delimiter
- | |unclosed delimiter
- | unclosed delimiter
-
-error: this file contains an unclosed delimiter
- --> $DIR/issue-104897.rs:6:18
- |
-LL | fn f(){(print!(á
- | -- - ^
- | || |
- | || unclosed delimiter
- | |unclosed delimiter
- | unclosed delimiter
-
-error: format argument must be a string literal
- --> $DIR/issue-104897.rs:6:16
- |
-LL | fn f(){(print!(á
- | ^
- |
-help: you might be missing a string literal to format with
- |
-LL | fn f(){(print!("{}", á
- | +++++
-
-error: aborting due to 4 previous errors
+error: aborting due to previous error
diff --git a/tests/ui/lint/issue-106991.rs b/tests/ui/lint/issue-106991.rs
new file mode 100644
index 000000000..e4d7f765b
--- /dev/null
+++ b/tests/ui/lint/issue-106991.rs
@@ -0,0 +1,13 @@
+fn foo(items: &mut Vec<u8>) {
+ items.sort();
+}
+
+fn bar() -> impl Iterator<Item = i32> {
+ //~^ ERROR expected `foo` to be a fn item that returns `i32`, but it returns `()` [E0271]
+ let mut x: Vec<Vec<u8>> = vec![vec![0, 2, 1], vec![5, 4, 3]];
+ x.iter_mut().map(foo)
+}
+
+fn main() {
+ bar();
+}
diff --git a/tests/ui/lint/issue-106991.stderr b/tests/ui/lint/issue-106991.stderr
new file mode 100644
index 000000000..7b43f0b2c
--- /dev/null
+++ b/tests/ui/lint/issue-106991.stderr
@@ -0,0 +1,11 @@
+error[E0271]: expected `foo` to be a fn item that returns `i32`, but it returns `()`
+ --> $DIR/issue-106991.rs:5:13
+ |
+LL | fn bar() -> impl Iterator<Item = i32> {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found `i32`
+ |
+ = note: required for `Map<std::slice::IterMut<'_, Vec<u8>>, for<'a> fn(&'a mut Vec<u8>) {foo}>` to implement `Iterator`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0271`.
diff --git a/tests/ui/lint/lint-missing-doc.rs b/tests/ui/lint/lint-missing-doc.rs
index 229725791..4a234d265 100644
--- a/tests/ui/lint/lint-missing-doc.rs
+++ b/tests/ui/lint/lint-missing-doc.rs
@@ -50,8 +50,10 @@ trait B {
}
pub trait C { //~ ERROR: missing documentation for a trait
- fn foo(&self); //~ ERROR: missing documentation for an associated function
- fn foo_with_impl(&self) {} //~ ERROR: missing documentation for an associated function
+ fn foo(&self); //~ ERROR: missing documentation for a method
+ fn foo_with_impl(&self) {} //~ ERROR: missing documentation for a method
+ fn foo_no_self(); //~ ERROR: missing documentation for an associated function
+ fn foo_no_self_with_impl() {} //~ ERROR: missing documentation for an associated function
}
#[allow(missing_docs)]
diff --git a/tests/ui/lint/lint-missing-doc.stderr b/tests/ui/lint/lint-missing-doc.stderr
index d68472d4b..733d062a0 100644
--- a/tests/ui/lint/lint-missing-doc.stderr
+++ b/tests/ui/lint/lint-missing-doc.stderr
@@ -40,101 +40,113 @@ error: missing documentation for a trait
LL | pub trait C {
| ^^^^^^^^^^^
-error: missing documentation for an associated function
+error: missing documentation for a method
--> $DIR/lint-missing-doc.rs:53:5
|
LL | fn foo(&self);
| ^^^^^^^^^^^^^^
-error: missing documentation for an associated function
+error: missing documentation for a method
--> $DIR/lint-missing-doc.rs:54:5
|
LL | fn foo_with_impl(&self) {}
| ^^^^^^^^^^^^^^^^^^^^^^^
+error: missing documentation for an associated function
+ --> $DIR/lint-missing-doc.rs:55:5
+ |
+LL | fn foo_no_self();
+ | ^^^^^^^^^^^^^^^^^
+
+error: missing documentation for an associated function
+ --> $DIR/lint-missing-doc.rs:56:5
+ |
+LL | fn foo_no_self_with_impl() {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+
error: missing documentation for an associated type
- --> $DIR/lint-missing-doc.rs:64:5
+ --> $DIR/lint-missing-doc.rs:66:5
|
LL | type AssociatedType;
| ^^^^^^^^^^^^^^^^^^^
error: missing documentation for an associated type
- --> $DIR/lint-missing-doc.rs:65:5
+ --> $DIR/lint-missing-doc.rs:67:5
|
LL | type AssociatedTypeDef = Self;
| ^^^^^^^^^^^^^^^^^^^^^^
error: missing documentation for an associated function
- --> $DIR/lint-missing-doc.rs:81:5
+ --> $DIR/lint-missing-doc.rs:83:5
|
LL | pub fn foo() {}
| ^^^^^^^^^^^^
error: missing documentation for an enum
- --> $DIR/lint-missing-doc.rs:118:1
+ --> $DIR/lint-missing-doc.rs:120:1
|
LL | pub enum PubBaz {
| ^^^^^^^^^^^^^^^
error: missing documentation for a variant
- --> $DIR/lint-missing-doc.rs:119:5
+ --> $DIR/lint-missing-doc.rs:121:5
|
LL | PubBazA {
| ^^^^^^^
error: missing documentation for a struct field
- --> $DIR/lint-missing-doc.rs:120:9
+ --> $DIR/lint-missing-doc.rs:122:9
|
LL | a: isize,
| ^^^^^^^^
error: missing documentation for a constant
- --> $DIR/lint-missing-doc.rs:151:1
+ --> $DIR/lint-missing-doc.rs:153:1
|
LL | pub const FOO4: u32 = 0;
| ^^^^^^^^^^^^^^^^^^^
error: missing documentation for a static
- --> $DIR/lint-missing-doc.rs:161:1
+ --> $DIR/lint-missing-doc.rs:163:1
|
LL | pub static BAR4: u32 = 0;
| ^^^^^^^^^^^^^^^^^^^^
error: missing documentation for a function
- --> $DIR/lint-missing-doc.rs:167:5
+ --> $DIR/lint-missing-doc.rs:169:5
|
LL | pub fn undocumented1() {}
| ^^^^^^^^^^^^^^^^^^^^^^
error: missing documentation for a function
- --> $DIR/lint-missing-doc.rs:168:5
+ --> $DIR/lint-missing-doc.rs:170:5
|
LL | pub fn undocumented2() {}
| ^^^^^^^^^^^^^^^^^^^^^^
error: missing documentation for a function
- --> $DIR/lint-missing-doc.rs:174:9
+ --> $DIR/lint-missing-doc.rs:176:9
|
LL | pub fn also_undocumented1() {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: missing documentation for a function
- --> $DIR/lint-missing-doc.rs:189:5
+ --> $DIR/lint-missing-doc.rs:191:5
|
LL | pub fn extern_fn_undocumented(f: f32) -> f32;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: missing documentation for a static
- --> $DIR/lint-missing-doc.rs:194:5
+ --> $DIR/lint-missing-doc.rs:196:5
|
LL | pub static EXTERN_STATIC_UNDOCUMENTED: u8;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: missing documentation for a foreign type
- --> $DIR/lint-missing-doc.rs:199:5
+ --> $DIR/lint-missing-doc.rs:201:5
|
LL | pub type ExternTyUndocumented;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-error: aborting due to 22 previous errors
+error: aborting due to 24 previous errors
diff --git a/tests/ui/lint/lint-stability-deprecated.rs b/tests/ui/lint/lint-stability-deprecated.rs
index 74c35083e..a56a37228 100644
--- a/tests/ui/lint/lint-stability-deprecated.rs
+++ b/tests/ui/lint/lint-stability-deprecated.rs
@@ -22,40 +22,40 @@ mod cross_crate {
let foo = MethodTester;
deprecated(); //~ WARN use of deprecated function `lint_stability::deprecated`
- foo.method_deprecated(); //~ WARN use of deprecated associated function `lint_stability::MethodTester::method_deprecated`
- Foo::method_deprecated(&foo); //~ WARN use of deprecated associated function `lint_stability::MethodTester::method_deprecated`
- <Foo>::method_deprecated(&foo); //~ WARN use of deprecated associated function `lint_stability::MethodTester::method_deprecated`
- foo.trait_deprecated(); //~ WARN use of deprecated associated function `lint_stability::Trait::trait_deprecated`
- Trait::trait_deprecated(&foo); //~ WARN use of deprecated associated function `lint_stability::Trait::trait_deprecated`
- <Foo>::trait_deprecated(&foo); //~ WARN use of deprecated associated function `lint_stability::Trait::trait_deprecated`
- <Foo as Trait>::trait_deprecated(&foo); //~ WARN use of deprecated associated function `lint_stability::Trait::trait_deprecated`
+ foo.method_deprecated(); //~ WARN use of deprecated method `lint_stability::MethodTester::method_deprecated`
+ Foo::method_deprecated(&foo); //~ WARN use of deprecated method `lint_stability::MethodTester::method_deprecated`
+ <Foo>::method_deprecated(&foo); //~ WARN use of deprecated method `lint_stability::MethodTester::method_deprecated`
+ foo.trait_deprecated(); //~ WARN use of deprecated method `lint_stability::Trait::trait_deprecated`
+ Trait::trait_deprecated(&foo); //~ WARN use of deprecated method `lint_stability::Trait::trait_deprecated`
+ <Foo>::trait_deprecated(&foo); //~ WARN use of deprecated method `lint_stability::Trait::trait_deprecated`
+ <Foo as Trait>::trait_deprecated(&foo); //~ WARN use of deprecated method `lint_stability::Trait::trait_deprecated`
deprecated_text(); //~ WARN use of deprecated function `lint_stability::deprecated_text`: text
- foo.method_deprecated_text(); //~ WARN use of deprecated associated function `lint_stability::MethodTester::method_deprecated_text`: text
- Foo::method_deprecated_text(&foo); //~ WARN use of deprecated associated function `lint_stability::MethodTester::method_deprecated_text`: text
- <Foo>::method_deprecated_text(&foo); //~ WARN use of deprecated associated function `lint_stability::MethodTester::method_deprecated_text`: text
- foo.trait_deprecated_text(); //~ WARN use of deprecated associated function `lint_stability::Trait::trait_deprecated_text`: text
- Trait::trait_deprecated_text(&foo); //~ WARN use of deprecated associated function `lint_stability::Trait::trait_deprecated_text`: text
- <Foo>::trait_deprecated_text(&foo); //~ WARN use of deprecated associated function `lint_stability::Trait::trait_deprecated_text`: text
- <Foo as Trait>::trait_deprecated_text(&foo); //~ WARN use of deprecated associated function `lint_stability::Trait::trait_deprecated_text`: text
+ foo.method_deprecated_text(); //~ WARN use of deprecated method `lint_stability::MethodTester::method_deprecated_text`: text
+ Foo::method_deprecated_text(&foo); //~ WARN use of deprecated method `lint_stability::MethodTester::method_deprecated_text`: text
+ <Foo>::method_deprecated_text(&foo); //~ WARN use of deprecated method `lint_stability::MethodTester::method_deprecated_text`: text
+ foo.trait_deprecated_text(); //~ WARN use of deprecated method `lint_stability::Trait::trait_deprecated_text`: text
+ Trait::trait_deprecated_text(&foo); //~ WARN use of deprecated method `lint_stability::Trait::trait_deprecated_text`: text
+ <Foo>::trait_deprecated_text(&foo); //~ WARN use of deprecated method `lint_stability::Trait::trait_deprecated_text`: text
+ <Foo as Trait>::trait_deprecated_text(&foo); //~ WARN use of deprecated method `lint_stability::Trait::trait_deprecated_text`: text
deprecated_unstable(); //~ WARN use of deprecated function `lint_stability::deprecated_unstable`
- foo.method_deprecated_unstable(); //~ WARN use of deprecated associated function `lint_stability::MethodTester::method_deprecated_unstable`
- Foo::method_deprecated_unstable(&foo); //~ WARN use of deprecated associated function `lint_stability::MethodTester::method_deprecated_unstable`
- <Foo>::method_deprecated_unstable(&foo); //~ WARN use of deprecated associated function `lint_stability::MethodTester::method_deprecated_unstable`
- foo.trait_deprecated_unstable(); //~ WARN use of deprecated associated function `lint_stability::Trait::trait_deprecated_unstable`
- Trait::trait_deprecated_unstable(&foo); //~ WARN use of deprecated associated function `lint_stability::Trait::trait_deprecated_unstable`
- <Foo>::trait_deprecated_unstable(&foo); //~ WARN use of deprecated associated function `lint_stability::Trait::trait_deprecated_unstable`
- <Foo as Trait>::trait_deprecated_unstable(&foo); //~ WARN use of deprecated associated function `lint_stability::Trait::trait_deprecated_unstable`
+ foo.method_deprecated_unstable(); //~ WARN use of deprecated method `lint_stability::MethodTester::method_deprecated_unstable`
+ Foo::method_deprecated_unstable(&foo); //~ WARN use of deprecated method `lint_stability::MethodTester::method_deprecated_unstable`
+ <Foo>::method_deprecated_unstable(&foo); //~ WARN use of deprecated method `lint_stability::MethodTester::method_deprecated_unstable`
+ foo.trait_deprecated_unstable(); //~ WARN use of deprecated method `lint_stability::Trait::trait_deprecated_unstable`
+ Trait::trait_deprecated_unstable(&foo); //~ WARN use of deprecated method `lint_stability::Trait::trait_deprecated_unstable`
+ <Foo>::trait_deprecated_unstable(&foo); //~ WARN use of deprecated method `lint_stability::Trait::trait_deprecated_unstable`
+ <Foo as Trait>::trait_deprecated_unstable(&foo); //~ WARN use of deprecated method `lint_stability::Trait::trait_deprecated_unstable`
deprecated_unstable_text(); //~ WARN use of deprecated function `lint_stability::deprecated_unstable_text`: text
- foo.method_deprecated_unstable_text(); //~ WARN use of deprecated associated function `lint_stability::MethodTester::method_deprecated_unstable_text`: text
- Foo::method_deprecated_unstable_text(&foo); //~ WARN use of deprecated associated function `lint_stability::MethodTester::method_deprecated_unstable_text`: text
- <Foo>::method_deprecated_unstable_text(&foo); //~ WARN use of deprecated associated function `lint_stability::MethodTester::method_deprecated_unstable_text`: text
- foo.trait_deprecated_unstable_text(); //~ WARN use of deprecated associated function `lint_stability::Trait::trait_deprecated_unstable_text`: text
- Trait::trait_deprecated_unstable_text(&foo); //~ WARN use of deprecated associated function `lint_stability::Trait::trait_deprecated_unstable_text`: text
- <Foo>::trait_deprecated_unstable_text(&foo); //~ WARN use of deprecated associated function `lint_stability::Trait::trait_deprecated_unstable_text`: text
- <Foo as Trait>::trait_deprecated_unstable_text(&foo); //~ WARN use of deprecated associated function `lint_stability::Trait::trait_deprecated_unstable_text`: text
+ foo.method_deprecated_unstable_text(); //~ WARN use of deprecated method `lint_stability::MethodTester::method_deprecated_unstable_text`: text
+ Foo::method_deprecated_unstable_text(&foo); //~ WARN use of deprecated method `lint_stability::MethodTester::method_deprecated_unstable_text`: text
+ <Foo>::method_deprecated_unstable_text(&foo); //~ WARN use of deprecated method `lint_stability::MethodTester::method_deprecated_unstable_text`: text
+ foo.trait_deprecated_unstable_text(); //~ WARN use of deprecated method `lint_stability::Trait::trait_deprecated_unstable_text`: text
+ Trait::trait_deprecated_unstable_text(&foo); //~ WARN use of deprecated method `lint_stability::Trait::trait_deprecated_unstable_text`: text
+ <Foo>::trait_deprecated_unstable_text(&foo); //~ WARN use of deprecated method `lint_stability::Trait::trait_deprecated_unstable_text`: text
+ <Foo as Trait>::trait_deprecated_unstable_text(&foo); //~ WARN use of deprecated method `lint_stability::Trait::trait_deprecated_unstable_text`: text
unstable();
foo.method_unstable();
@@ -141,22 +141,22 @@ mod cross_crate {
}
fn test_method_param<Foo: Trait>(foo: Foo) {
- foo.trait_deprecated(); //~ WARN use of deprecated associated function `lint_stability::Trait::trait_deprecated`
- Trait::trait_deprecated(&foo); //~ WARN use of deprecated associated function `lint_stability::Trait::trait_deprecated`
- <Foo>::trait_deprecated(&foo); //~ WARN use of deprecated associated function `lint_stability::Trait::trait_deprecated`
- <Foo as Trait>::trait_deprecated(&foo); //~ WARN use of deprecated associated function `lint_stability::Trait::trait_deprecated`
- foo.trait_deprecated_text(); //~ WARN use of deprecated associated function `lint_stability::Trait::trait_deprecated_text`: text
- Trait::trait_deprecated_text(&foo); //~ WARN use of deprecated associated function `lint_stability::Trait::trait_deprecated_text`: text
- <Foo>::trait_deprecated_text(&foo); //~ WARN use of deprecated associated function `lint_stability::Trait::trait_deprecated_text`: text
- <Foo as Trait>::trait_deprecated_text(&foo); //~ WARN use of deprecated associated function `lint_stability::Trait::trait_deprecated_text`: text
- foo.trait_deprecated_unstable(); //~ WARN use of deprecated associated function `lint_stability::Trait::trait_deprecated_unstable`
- Trait::trait_deprecated_unstable(&foo); //~ WARN use of deprecated associated function `lint_stability::Trait::trait_deprecated_unstable`
- <Foo>::trait_deprecated_unstable(&foo); //~ WARN use of deprecated associated function `lint_stability::Trait::trait_deprecated_unstable`
- <Foo as Trait>::trait_deprecated_unstable(&foo); //~ WARN use of deprecated associated function `lint_stability::Trait::trait_deprecated_unstable`
- foo.trait_deprecated_unstable_text(); //~ WARN use of deprecated associated function `lint_stability::Trait::trait_deprecated_unstable_text`: text
- Trait::trait_deprecated_unstable_text(&foo); //~ WARN use of deprecated associated function `lint_stability::Trait::trait_deprecated_unstable_text`: text
- <Foo>::trait_deprecated_unstable_text(&foo); //~ WARN use of deprecated associated function `lint_stability::Trait::trait_deprecated_unstable_text`: text
- <Foo as Trait>::trait_deprecated_unstable_text(&foo); //~ WARN use of deprecated associated function `lint_stability::Trait::trait_deprecated_unstable_text`: text
+ foo.trait_deprecated(); //~ WARN use of deprecated method `lint_stability::Trait::trait_deprecated`
+ Trait::trait_deprecated(&foo); //~ WARN use of deprecated method `lint_stability::Trait::trait_deprecated`
+ <Foo>::trait_deprecated(&foo); //~ WARN use of deprecated method `lint_stability::Trait::trait_deprecated`
+ <Foo as Trait>::trait_deprecated(&foo); //~ WARN use of deprecated method `lint_stability::Trait::trait_deprecated`
+ foo.trait_deprecated_text(); //~ WARN use of deprecated method `lint_stability::Trait::trait_deprecated_text`: text
+ Trait::trait_deprecated_text(&foo); //~ WARN use of deprecated method `lint_stability::Trait::trait_deprecated_text`: text
+ <Foo>::trait_deprecated_text(&foo); //~ WARN use of deprecated method `lint_stability::Trait::trait_deprecated_text`: text
+ <Foo as Trait>::trait_deprecated_text(&foo); //~ WARN use of deprecated method `lint_stability::Trait::trait_deprecated_text`: text
+ foo.trait_deprecated_unstable(); //~ WARN use of deprecated method `lint_stability::Trait::trait_deprecated_unstable`
+ Trait::trait_deprecated_unstable(&foo); //~ WARN use of deprecated method `lint_stability::Trait::trait_deprecated_unstable`
+ <Foo>::trait_deprecated_unstable(&foo); //~ WARN use of deprecated method `lint_stability::Trait::trait_deprecated_unstable`
+ <Foo as Trait>::trait_deprecated_unstable(&foo); //~ WARN use of deprecated method `lint_stability::Trait::trait_deprecated_unstable`
+ foo.trait_deprecated_unstable_text(); //~ WARN use of deprecated method `lint_stability::Trait::trait_deprecated_unstable_text`: text
+ Trait::trait_deprecated_unstable_text(&foo); //~ WARN use of deprecated method `lint_stability::Trait::trait_deprecated_unstable_text`: text
+ <Foo>::trait_deprecated_unstable_text(&foo); //~ WARN use of deprecated method `lint_stability::Trait::trait_deprecated_unstable_text`: text
+ <Foo as Trait>::trait_deprecated_unstable_text(&foo); //~ WARN use of deprecated method `lint_stability::Trait::trait_deprecated_unstable_text`: text
foo.trait_unstable();
Trait::trait_unstable(&foo);
<Foo>::trait_unstable(&foo);
@@ -172,10 +172,10 @@ mod cross_crate {
}
fn test_method_object(foo: &dyn Trait) {
- foo.trait_deprecated(); //~ WARN use of deprecated associated function `lint_stability::Trait::trait_deprecated`
- foo.trait_deprecated_text(); //~ WARN use of deprecated associated function `lint_stability::Trait::trait_deprecated_text`: text
- foo.trait_deprecated_unstable(); //~ WARN use of deprecated associated function `lint_stability::Trait::trait_deprecated_unstable`
- foo.trait_deprecated_unstable_text(); //~ WARN use of deprecated associated function `lint_stability::Trait::trait_deprecated_unstable_text`: text
+ foo.trait_deprecated(); //~ WARN use of deprecated method `lint_stability::Trait::trait_deprecated`
+ foo.trait_deprecated_text(); //~ WARN use of deprecated method `lint_stability::Trait::trait_deprecated_text`: text
+ foo.trait_deprecated_unstable(); //~ WARN use of deprecated method `lint_stability::Trait::trait_deprecated_unstable`
+ foo.trait_deprecated_unstable_text(); //~ WARN use of deprecated method `lint_stability::Trait::trait_deprecated_unstable_text`: text
foo.trait_unstable();
foo.trait_unstable_text();
foo.trait_stable();
@@ -328,22 +328,22 @@ mod this_crate {
let foo = MethodTester;
deprecated(); //~ WARN use of deprecated function `this_crate::deprecated`
- foo.method_deprecated(); //~ WARN use of deprecated associated function `this_crate::MethodTester::method_deprecated`
- Foo::method_deprecated(&foo); //~ WARN use of deprecated associated function `this_crate::MethodTester::method_deprecated`
- <Foo>::method_deprecated(&foo); //~ WARN use of deprecated associated function `this_crate::MethodTester::method_deprecated`
- foo.trait_deprecated(); //~ WARN use of deprecated associated function `this_crate::Trait::trait_deprecated`
- Trait::trait_deprecated(&foo); //~ WARN use of deprecated associated function `this_crate::Trait::trait_deprecated`
- <Foo>::trait_deprecated(&foo); //~ WARN use of deprecated associated function `this_crate::Trait::trait_deprecated`
- <Foo as Trait>::trait_deprecated(&foo); //~ WARN use of deprecated associated function `this_crate::Trait::trait_deprecated`
+ foo.method_deprecated(); //~ WARN use of deprecated method `this_crate::MethodTester::method_deprecated`
+ Foo::method_deprecated(&foo); //~ WARN use of deprecated method `this_crate::MethodTester::method_deprecated`
+ <Foo>::method_deprecated(&foo); //~ WARN use of deprecated method `this_crate::MethodTester::method_deprecated`
+ foo.trait_deprecated(); //~ WARN use of deprecated method `this_crate::Trait::trait_deprecated`
+ Trait::trait_deprecated(&foo); //~ WARN use of deprecated method `this_crate::Trait::trait_deprecated`
+ <Foo>::trait_deprecated(&foo); //~ WARN use of deprecated method `this_crate::Trait::trait_deprecated`
+ <Foo as Trait>::trait_deprecated(&foo); //~ WARN use of deprecated method `this_crate::Trait::trait_deprecated`
deprecated_text(); //~ WARN use of deprecated function `this_crate::deprecated_text`: text
- foo.method_deprecated_text(); //~ WARN use of deprecated associated function `this_crate::MethodTester::method_deprecated_text`: text
- Foo::method_deprecated_text(&foo); //~ WARN use of deprecated associated function `this_crate::MethodTester::method_deprecated_text`: text
- <Foo>::method_deprecated_text(&foo); //~ WARN use of deprecated associated function `this_crate::MethodTester::method_deprecated_text`: text
- foo.trait_deprecated_text(); //~ WARN use of deprecated associated function `this_crate::Trait::trait_deprecated_text`: text
- Trait::trait_deprecated_text(&foo); //~ WARN use of deprecated associated function `this_crate::Trait::trait_deprecated_text`: text
- <Foo>::trait_deprecated_text(&foo); //~ WARN use of deprecated associated function `this_crate::Trait::trait_deprecated_text`: text
- <Foo as Trait>::trait_deprecated_text(&foo); //~ WARN use of deprecated associated function `this_crate::Trait::trait_deprecated_text`: text
+ foo.method_deprecated_text(); //~ WARN use of deprecated method `this_crate::MethodTester::method_deprecated_text`: text
+ Foo::method_deprecated_text(&foo); //~ WARN use of deprecated method `this_crate::MethodTester::method_deprecated_text`: text
+ <Foo>::method_deprecated_text(&foo); //~ WARN use of deprecated method `this_crate::MethodTester::method_deprecated_text`: text
+ foo.trait_deprecated_text(); //~ WARN use of deprecated method `this_crate::Trait::trait_deprecated_text`: text
+ Trait::trait_deprecated_text(&foo); //~ WARN use of deprecated method `this_crate::Trait::trait_deprecated_text`: text
+ <Foo>::trait_deprecated_text(&foo); //~ WARN use of deprecated method `this_crate::Trait::trait_deprecated_text`: text
+ <Foo as Trait>::trait_deprecated_text(&foo); //~ WARN use of deprecated method `this_crate::Trait::trait_deprecated_text`: text
unstable();
foo.method_unstable();
@@ -402,14 +402,14 @@ mod this_crate {
}
fn test_method_param<Foo: Trait>(foo: Foo) {
- foo.trait_deprecated(); //~ WARN use of deprecated associated function `this_crate::Trait::trait_deprecated`
- Trait::trait_deprecated(&foo); //~ WARN use of deprecated associated function `this_crate::Trait::trait_deprecated`
- <Foo>::trait_deprecated(&foo); //~ WARN use of deprecated associated function `this_crate::Trait::trait_deprecated`
- <Foo as Trait>::trait_deprecated(&foo); //~ WARN use of deprecated associated function `this_crate::Trait::trait_deprecated`
- foo.trait_deprecated_text(); //~ WARN use of deprecated associated function `this_crate::Trait::trait_deprecated_text`: text
- Trait::trait_deprecated_text(&foo); //~ WARN use of deprecated associated function `this_crate::Trait::trait_deprecated_text`: text
- <Foo>::trait_deprecated_text(&foo); //~ WARN use of deprecated associated function `this_crate::Trait::trait_deprecated_text`: text
- <Foo as Trait>::trait_deprecated_text(&foo); //~ WARN use of deprecated associated function `this_crate::Trait::trait_deprecated_text`: text
+ foo.trait_deprecated(); //~ WARN use of deprecated method `this_crate::Trait::trait_deprecated`
+ Trait::trait_deprecated(&foo); //~ WARN use of deprecated method `this_crate::Trait::trait_deprecated`
+ <Foo>::trait_deprecated(&foo); //~ WARN use of deprecated method `this_crate::Trait::trait_deprecated`
+ <Foo as Trait>::trait_deprecated(&foo); //~ WARN use of deprecated method `this_crate::Trait::trait_deprecated`
+ foo.trait_deprecated_text(); //~ WARN use of deprecated method `this_crate::Trait::trait_deprecated_text`: text
+ Trait::trait_deprecated_text(&foo); //~ WARN use of deprecated method `this_crate::Trait::trait_deprecated_text`: text
+ <Foo>::trait_deprecated_text(&foo); //~ WARN use of deprecated method `this_crate::Trait::trait_deprecated_text`: text
+ <Foo as Trait>::trait_deprecated_text(&foo); //~ WARN use of deprecated method `this_crate::Trait::trait_deprecated_text`: text
foo.trait_unstable();
Trait::trait_unstable(&foo);
<Foo>::trait_unstable(&foo);
@@ -425,8 +425,8 @@ mod this_crate {
}
fn test_method_object(foo: &dyn Trait) {
- foo.trait_deprecated(); //~ WARN use of deprecated associated function `this_crate::Trait::trait_deprecated`
- foo.trait_deprecated_text(); //~ WARN use of deprecated associated function `this_crate::Trait::trait_deprecated_text`: text
+ foo.trait_deprecated(); //~ WARN use of deprecated method `this_crate::Trait::trait_deprecated`
+ foo.trait_deprecated_text(); //~ WARN use of deprecated method `this_crate::Trait::trait_deprecated_text`: text
foo.trait_unstable();
foo.trait_unstable_text();
foo.trait_stable();
diff --git a/tests/ui/lint/lint-stability-deprecated.stderr b/tests/ui/lint/lint-stability-deprecated.stderr
index 9f1e7b281..19a4649e1 100644
--- a/tests/ui/lint/lint-stability-deprecated.stderr
+++ b/tests/ui/lint/lint-stability-deprecated.stderr
@@ -10,13 +10,13 @@ note: the lint level is defined here
LL | #![warn(deprecated)]
| ^^^^^^^^^^
-warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated`: text
+warning: use of deprecated method `lint_stability::Trait::trait_deprecated`: text
--> $DIR/lint-stability-deprecated.rs:29:16
|
LL | Trait::trait_deprecated(&foo);
| ^^^^^^^^^^^^^^^^
-warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated`: text
+warning: use of deprecated method `lint_stability::Trait::trait_deprecated`: text
--> $DIR/lint-stability-deprecated.rs:31:25
|
LL | <Foo as Trait>::trait_deprecated(&foo);
@@ -28,17 +28,17 @@ warning: use of deprecated function `lint_stability::deprecated_text`: text
LL | deprecated_text();
| ^^^^^^^^^^^^^^^
-warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated_text`: text
+warning: use of deprecated method `lint_stability::Trait::trait_deprecated_text`: text
--> $DIR/lint-stability-deprecated.rs:38:16
|
-LL | ... Trait::trait_deprecated_text(&foo);
- | ^^^^^^^^^^^^^^^^^^^^^
+LL | Trait::trait_deprecated_text(&foo);
+ | ^^^^^^^^^^^^^^^^^^^^^
-warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated_text`: text
+warning: use of deprecated method `lint_stability::Trait::trait_deprecated_text`: text
--> $DIR/lint-stability-deprecated.rs:40:25
|
-LL | ... <Foo as Trait>::trait_deprecated_text(&foo);
- | ^^^^^^^^^^^^^^^^^^^^^
+LL | <Foo as Trait>::trait_deprecated_text(&foo);
+ | ^^^^^^^^^^^^^^^^^^^^^
warning: use of deprecated function `lint_stability::deprecated_unstable`: text
--> $DIR/lint-stability-deprecated.rs:42:9
@@ -46,13 +46,13 @@ warning: use of deprecated function `lint_stability::deprecated_unstable`: text
LL | deprecated_unstable();
| ^^^^^^^^^^^^^^^^^^^
-warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated_unstable`: text
+warning: use of deprecated method `lint_stability::Trait::trait_deprecated_unstable`: text
--> $DIR/lint-stability-deprecated.rs:47:16
|
-LL | ... Trait::trait_deprecated_unstable(&foo);
- | ^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | Trait::trait_deprecated_unstable(&foo);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^
-warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated_unstable`: text
+warning: use of deprecated method `lint_stability::Trait::trait_deprecated_unstable`: text
--> $DIR/lint-stability-deprecated.rs:49:25
|
LL | ... <Foo as Trait>::trait_deprecated_unstable(&foo);
@@ -64,13 +64,13 @@ warning: use of deprecated function `lint_stability::deprecated_unstable_text`:
LL | deprecated_unstable_text();
| ^^^^^^^^^^^^^^^^^^^^^^^^
-warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated_unstable_text`: text
+warning: use of deprecated method `lint_stability::Trait::trait_deprecated_unstable_text`: text
--> $DIR/lint-stability-deprecated.rs:56:16
|
LL | ... Trait::trait_deprecated_unstable_text(&foo);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated_unstable_text`: text
+warning: use of deprecated method `lint_stability::Trait::trait_deprecated_unstable_text`: text
--> $DIR/lint-stability-deprecated.rs:58:25
|
LL | ... <Foo as Trait>::trait_deprecated_unstable_text(&foo);
@@ -142,49 +142,49 @@ warning: use of deprecated function `lint_stability::deprecated_text`: text
LL | macro_test_arg!(macro_test_arg!(deprecated_text()));
| ^^^^^^^^^^^^^^^
-warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated`: text
+warning: use of deprecated method `lint_stability::Trait::trait_deprecated`: text
--> $DIR/lint-stability-deprecated.rs:145:16
|
LL | Trait::trait_deprecated(&foo);
| ^^^^^^^^^^^^^^^^
-warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated`: text
+warning: use of deprecated method `lint_stability::Trait::trait_deprecated`: text
--> $DIR/lint-stability-deprecated.rs:147:25
|
LL | <Foo as Trait>::trait_deprecated(&foo);
| ^^^^^^^^^^^^^^^^
-warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated_text`: text
+warning: use of deprecated method `lint_stability::Trait::trait_deprecated_text`: text
--> $DIR/lint-stability-deprecated.rs:149:16
|
-LL | ... Trait::trait_deprecated_text(&foo);
- | ^^^^^^^^^^^^^^^^^^^^^
+LL | Trait::trait_deprecated_text(&foo);
+ | ^^^^^^^^^^^^^^^^^^^^^
-warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated_text`: text
+warning: use of deprecated method `lint_stability::Trait::trait_deprecated_text`: text
--> $DIR/lint-stability-deprecated.rs:151:25
|
-LL | ... <Foo as Trait>::trait_deprecated_text(&foo);
- | ^^^^^^^^^^^^^^^^^^^^^
+LL | <Foo as Trait>::trait_deprecated_text(&foo);
+ | ^^^^^^^^^^^^^^^^^^^^^
-warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated_unstable`: text
+warning: use of deprecated method `lint_stability::Trait::trait_deprecated_unstable`: text
--> $DIR/lint-stability-deprecated.rs:153:16
|
-LL | ... Trait::trait_deprecated_unstable(&foo);
- | ^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | Trait::trait_deprecated_unstable(&foo);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^
-warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated_unstable`: text
+warning: use of deprecated method `lint_stability::Trait::trait_deprecated_unstable`: text
--> $DIR/lint-stability-deprecated.rs:155:25
|
LL | ... <Foo as Trait>::trait_deprecated_unstable(&foo);
| ^^^^^^^^^^^^^^^^^^^^^^^^^
-warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated_unstable_text`: text
+warning: use of deprecated method `lint_stability::Trait::trait_deprecated_unstable_text`: text
--> $DIR/lint-stability-deprecated.rs:157:16
|
LL | ... Trait::trait_deprecated_unstable_text(&foo);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated_unstable_text`: text
+warning: use of deprecated method `lint_stability::Trait::trait_deprecated_unstable_text`: text
--> $DIR/lint-stability-deprecated.rs:159:25
|
LL | ... <Foo as Trait>::trait_deprecated_unstable_text(&foo);
@@ -214,13 +214,13 @@ warning: use of deprecated function `this_crate::deprecated`: text
LL | deprecated();
| ^^^^^^^^^^
-warning: use of deprecated associated function `this_crate::Trait::trait_deprecated`: text
+warning: use of deprecated method `this_crate::Trait::trait_deprecated`: text
--> $DIR/lint-stability-deprecated.rs:335:16
|
LL | Trait::trait_deprecated(&foo);
| ^^^^^^^^^^^^^^^^
-warning: use of deprecated associated function `this_crate::Trait::trait_deprecated`: text
+warning: use of deprecated method `this_crate::Trait::trait_deprecated`: text
--> $DIR/lint-stability-deprecated.rs:337:25
|
LL | <Foo as Trait>::trait_deprecated(&foo);
@@ -232,17 +232,17 @@ warning: use of deprecated function `this_crate::deprecated_text`: text
LL | deprecated_text();
| ^^^^^^^^^^^^^^^
-warning: use of deprecated associated function `this_crate::Trait::trait_deprecated_text`: text
+warning: use of deprecated method `this_crate::Trait::trait_deprecated_text`: text
--> $DIR/lint-stability-deprecated.rs:344:16
|
LL | Trait::trait_deprecated_text(&foo);
| ^^^^^^^^^^^^^^^^^^^^^
-warning: use of deprecated associated function `this_crate::Trait::trait_deprecated_text`: text
+warning: use of deprecated method `this_crate::Trait::trait_deprecated_text`: text
--> $DIR/lint-stability-deprecated.rs:346:25
|
-LL | ... <Foo as Trait>::trait_deprecated_text(&foo);
- | ^^^^^^^^^^^^^^^^^^^^^
+LL | <Foo as Trait>::trait_deprecated_text(&foo);
+ | ^^^^^^^^^^^^^^^^^^^^^
warning: use of deprecated struct `this_crate::DeprecatedStruct`: text
--> $DIR/lint-stability-deprecated.rs:384:17
@@ -268,29 +268,29 @@ warning: use of deprecated tuple struct `this_crate::DeprecatedTupleStruct`: tex
LL | let _ = DeprecatedTupleStruct (1);
| ^^^^^^^^^^^^^^^^^^^^^
-warning: use of deprecated associated function `this_crate::Trait::trait_deprecated`: text
+warning: use of deprecated method `this_crate::Trait::trait_deprecated`: text
--> $DIR/lint-stability-deprecated.rs:406:16
|
LL | Trait::trait_deprecated(&foo);
| ^^^^^^^^^^^^^^^^
-warning: use of deprecated associated function `this_crate::Trait::trait_deprecated`: text
+warning: use of deprecated method `this_crate::Trait::trait_deprecated`: text
--> $DIR/lint-stability-deprecated.rs:408:25
|
LL | <Foo as Trait>::trait_deprecated(&foo);
| ^^^^^^^^^^^^^^^^
-warning: use of deprecated associated function `this_crate::Trait::trait_deprecated_text`: text
+warning: use of deprecated method `this_crate::Trait::trait_deprecated_text`: text
--> $DIR/lint-stability-deprecated.rs:410:16
|
LL | Trait::trait_deprecated_text(&foo);
| ^^^^^^^^^^^^^^^^^^^^^
-warning: use of deprecated associated function `this_crate::Trait::trait_deprecated_text`: text
+warning: use of deprecated method `this_crate::Trait::trait_deprecated_text`: text
--> $DIR/lint-stability-deprecated.rs:412:25
|
-LL | ... <Foo as Trait>::trait_deprecated_text(&foo);
- | ^^^^^^^^^^^^^^^^^^^^^
+LL | <Foo as Trait>::trait_deprecated_text(&foo);
+ | ^^^^^^^^^^^^^^^^^^^^^
warning: use of deprecated function `this_crate::test_fn_body::fn_in_body`: text
--> $DIR/lint-stability-deprecated.rs:439:9
@@ -328,121 +328,121 @@ warning: use of deprecated associated type `lint_stability::TraitWithAssociatedT
LL | TypeDeprecated = u16,
| ^^^^^^^^^^^^^^^^^^^^
-warning: use of deprecated associated function `lint_stability::MethodTester::method_deprecated`: text
+warning: use of deprecated method `lint_stability::MethodTester::method_deprecated`: text
--> $DIR/lint-stability-deprecated.rs:25:13
|
LL | foo.method_deprecated();
| ^^^^^^^^^^^^^^^^^
-warning: use of deprecated associated function `lint_stability::MethodTester::method_deprecated`: text
+warning: use of deprecated method `lint_stability::MethodTester::method_deprecated`: text
--> $DIR/lint-stability-deprecated.rs:26:14
|
LL | Foo::method_deprecated(&foo);
| ^^^^^^^^^^^^^^^^^
-warning: use of deprecated associated function `lint_stability::MethodTester::method_deprecated`: text
+warning: use of deprecated method `lint_stability::MethodTester::method_deprecated`: text
--> $DIR/lint-stability-deprecated.rs:27:16
|
LL | <Foo>::method_deprecated(&foo);
| ^^^^^^^^^^^^^^^^^
-warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated`: text
+warning: use of deprecated method `lint_stability::Trait::trait_deprecated`: text
--> $DIR/lint-stability-deprecated.rs:28:13
|
LL | foo.trait_deprecated();
| ^^^^^^^^^^^^^^^^
-warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated`: text
+warning: use of deprecated method `lint_stability::Trait::trait_deprecated`: text
--> $DIR/lint-stability-deprecated.rs:30:16
|
LL | <Foo>::trait_deprecated(&foo);
| ^^^^^^^^^^^^^^^^
-warning: use of deprecated associated function `lint_stability::MethodTester::method_deprecated_text`: text
+warning: use of deprecated method `lint_stability::MethodTester::method_deprecated_text`: text
--> $DIR/lint-stability-deprecated.rs:34:13
|
-LL | ... foo.method_deprecated_text();
- | ^^^^^^^^^^^^^^^^^^^^^^
+LL | foo.method_deprecated_text();
+ | ^^^^^^^^^^^^^^^^^^^^^^
-warning: use of deprecated associated function `lint_stability::MethodTester::method_deprecated_text`: text
+warning: use of deprecated method `lint_stability::MethodTester::method_deprecated_text`: text
--> $DIR/lint-stability-deprecated.rs:35:14
|
-LL | ... Foo::method_deprecated_text(&foo);
- | ^^^^^^^^^^^^^^^^^^^^^^
+LL | Foo::method_deprecated_text(&foo);
+ | ^^^^^^^^^^^^^^^^^^^^^^
-warning: use of deprecated associated function `lint_stability::MethodTester::method_deprecated_text`: text
+warning: use of deprecated method `lint_stability::MethodTester::method_deprecated_text`: text
--> $DIR/lint-stability-deprecated.rs:36:16
|
-LL | ... <Foo>::method_deprecated_text(&foo);
- | ^^^^^^^^^^^^^^^^^^^^^^
+LL | <Foo>::method_deprecated_text(&foo);
+ | ^^^^^^^^^^^^^^^^^^^^^^
-warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated_text`: text
+warning: use of deprecated method `lint_stability::Trait::trait_deprecated_text`: text
--> $DIR/lint-stability-deprecated.rs:37:13
|
LL | foo.trait_deprecated_text();
| ^^^^^^^^^^^^^^^^^^^^^
-warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated_text`: text
+warning: use of deprecated method `lint_stability::Trait::trait_deprecated_text`: text
--> $DIR/lint-stability-deprecated.rs:39:16
|
-LL | ... <Foo>::trait_deprecated_text(&foo);
- | ^^^^^^^^^^^^^^^^^^^^^
+LL | <Foo>::trait_deprecated_text(&foo);
+ | ^^^^^^^^^^^^^^^^^^^^^
-warning: use of deprecated associated function `lint_stability::MethodTester::method_deprecated_unstable`: text
+warning: use of deprecated method `lint_stability::MethodTester::method_deprecated_unstable`: text
--> $DIR/lint-stability-deprecated.rs:43:13
|
-LL | ... foo.method_deprecated_unstable();
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | foo.method_deprecated_unstable();
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^
-warning: use of deprecated associated function `lint_stability::MethodTester::method_deprecated_unstable`: text
+warning: use of deprecated method `lint_stability::MethodTester::method_deprecated_unstable`: text
--> $DIR/lint-stability-deprecated.rs:44:14
|
-LL | ... Foo::method_deprecated_unstable(&foo);
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | Foo::method_deprecated_unstable(&foo);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^
-warning: use of deprecated associated function `lint_stability::MethodTester::method_deprecated_unstable`: text
+warning: use of deprecated method `lint_stability::MethodTester::method_deprecated_unstable`: text
--> $DIR/lint-stability-deprecated.rs:45:16
|
LL | ... <Foo>::method_deprecated_unstable(&foo);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
-warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated_unstable`: text
+warning: use of deprecated method `lint_stability::Trait::trait_deprecated_unstable`: text
--> $DIR/lint-stability-deprecated.rs:46:13
|
LL | foo.trait_deprecated_unstable();
| ^^^^^^^^^^^^^^^^^^^^^^^^^
-warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated_unstable`: text
+warning: use of deprecated method `lint_stability::Trait::trait_deprecated_unstable`: text
--> $DIR/lint-stability-deprecated.rs:48:16
|
-LL | ... <Foo>::trait_deprecated_unstable(&foo);
- | ^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | <Foo>::trait_deprecated_unstable(&foo);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^
-warning: use of deprecated associated function `lint_stability::MethodTester::method_deprecated_unstable_text`: text
+warning: use of deprecated method `lint_stability::MethodTester::method_deprecated_unstable_text`: text
--> $DIR/lint-stability-deprecated.rs:52:13
|
LL | ... foo.method_deprecated_unstable_text();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-warning: use of deprecated associated function `lint_stability::MethodTester::method_deprecated_unstable_text`: text
+warning: use of deprecated method `lint_stability::MethodTester::method_deprecated_unstable_text`: text
--> $DIR/lint-stability-deprecated.rs:53:14
|
LL | ... Foo::method_deprecated_unstable_text(&foo);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-warning: use of deprecated associated function `lint_stability::MethodTester::method_deprecated_unstable_text`: text
+warning: use of deprecated method `lint_stability::MethodTester::method_deprecated_unstable_text`: text
--> $DIR/lint-stability-deprecated.rs:54:16
|
LL | ... <Foo>::method_deprecated_unstable_text(&foo);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated_unstable_text`: text
+warning: use of deprecated method `lint_stability::Trait::trait_deprecated_unstable_text`: text
--> $DIR/lint-stability-deprecated.rs:55:13
|
LL | ... foo.trait_deprecated_unstable_text();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated_unstable_text`: text
+warning: use of deprecated method `lint_stability::Trait::trait_deprecated_unstable_text`: text
--> $DIR/lint-stability-deprecated.rs:57:16
|
LL | ... <Foo>::trait_deprecated_unstable_text(&foo);
@@ -460,133 +460,133 @@ warning: use of deprecated field `lint_stability::DeprecatedUnstableStruct::i`:
LL | i: 0
| ^^^^
-warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated`: text
+warning: use of deprecated method `lint_stability::Trait::trait_deprecated`: text
--> $DIR/lint-stability-deprecated.rs:144:13
|
LL | foo.trait_deprecated();
| ^^^^^^^^^^^^^^^^
-warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated`: text
+warning: use of deprecated method `lint_stability::Trait::trait_deprecated`: text
--> $DIR/lint-stability-deprecated.rs:146:16
|
LL | <Foo>::trait_deprecated(&foo);
| ^^^^^^^^^^^^^^^^
-warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated_text`: text
+warning: use of deprecated method `lint_stability::Trait::trait_deprecated_text`: text
--> $DIR/lint-stability-deprecated.rs:148:13
|
LL | foo.trait_deprecated_text();
| ^^^^^^^^^^^^^^^^^^^^^
-warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated_text`: text
+warning: use of deprecated method `lint_stability::Trait::trait_deprecated_text`: text
--> $DIR/lint-stability-deprecated.rs:150:16
|
-LL | ... <Foo>::trait_deprecated_text(&foo);
- | ^^^^^^^^^^^^^^^^^^^^^
+LL | <Foo>::trait_deprecated_text(&foo);
+ | ^^^^^^^^^^^^^^^^^^^^^
-warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated_unstable`: text
+warning: use of deprecated method `lint_stability::Trait::trait_deprecated_unstable`: text
--> $DIR/lint-stability-deprecated.rs:152:13
|
LL | foo.trait_deprecated_unstable();
| ^^^^^^^^^^^^^^^^^^^^^^^^^
-warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated_unstable`: text
+warning: use of deprecated method `lint_stability::Trait::trait_deprecated_unstable`: text
--> $DIR/lint-stability-deprecated.rs:154:16
|
-LL | ... <Foo>::trait_deprecated_unstable(&foo);
- | ^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | <Foo>::trait_deprecated_unstable(&foo);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^
-warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated_unstable_text`: text
+warning: use of deprecated method `lint_stability::Trait::trait_deprecated_unstable_text`: text
--> $DIR/lint-stability-deprecated.rs:156:13
|
LL | ... foo.trait_deprecated_unstable_text();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated_unstable_text`: text
+warning: use of deprecated method `lint_stability::Trait::trait_deprecated_unstable_text`: text
--> $DIR/lint-stability-deprecated.rs:158:16
|
LL | ... <Foo>::trait_deprecated_unstable_text(&foo);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated`: text
+warning: use of deprecated method `lint_stability::Trait::trait_deprecated`: text
--> $DIR/lint-stability-deprecated.rs:175:13
|
LL | foo.trait_deprecated();
| ^^^^^^^^^^^^^^^^
-warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated_text`: text
+warning: use of deprecated method `lint_stability::Trait::trait_deprecated_text`: text
--> $DIR/lint-stability-deprecated.rs:176:13
|
LL | foo.trait_deprecated_text();
| ^^^^^^^^^^^^^^^^^^^^^
-warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated_unstable`: text
+warning: use of deprecated method `lint_stability::Trait::trait_deprecated_unstable`: text
--> $DIR/lint-stability-deprecated.rs:177:13
|
LL | foo.trait_deprecated_unstable();
| ^^^^^^^^^^^^^^^^^^^^^^^^^
-warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated_unstable_text`: text
+warning: use of deprecated method `lint_stability::Trait::trait_deprecated_unstable_text`: text
--> $DIR/lint-stability-deprecated.rs:178:13
|
LL | ... foo.trait_deprecated_unstable_text();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-warning: use of deprecated associated function `this_crate::MethodTester::method_deprecated`: text
+warning: use of deprecated method `this_crate::MethodTester::method_deprecated`: text
--> $DIR/lint-stability-deprecated.rs:331:13
|
LL | foo.method_deprecated();
| ^^^^^^^^^^^^^^^^^
-warning: use of deprecated associated function `this_crate::MethodTester::method_deprecated`: text
+warning: use of deprecated method `this_crate::MethodTester::method_deprecated`: text
--> $DIR/lint-stability-deprecated.rs:332:14
|
LL | Foo::method_deprecated(&foo);
| ^^^^^^^^^^^^^^^^^
-warning: use of deprecated associated function `this_crate::MethodTester::method_deprecated`: text
+warning: use of deprecated method `this_crate::MethodTester::method_deprecated`: text
--> $DIR/lint-stability-deprecated.rs:333:16
|
LL | <Foo>::method_deprecated(&foo);
| ^^^^^^^^^^^^^^^^^
-warning: use of deprecated associated function `this_crate::Trait::trait_deprecated`: text
+warning: use of deprecated method `this_crate::Trait::trait_deprecated`: text
--> $DIR/lint-stability-deprecated.rs:334:13
|
LL | foo.trait_deprecated();
| ^^^^^^^^^^^^^^^^
-warning: use of deprecated associated function `this_crate::Trait::trait_deprecated`: text
+warning: use of deprecated method `this_crate::Trait::trait_deprecated`: text
--> $DIR/lint-stability-deprecated.rs:336:16
|
LL | <Foo>::trait_deprecated(&foo);
| ^^^^^^^^^^^^^^^^
-warning: use of deprecated associated function `this_crate::MethodTester::method_deprecated_text`: text
+warning: use of deprecated method `this_crate::MethodTester::method_deprecated_text`: text
--> $DIR/lint-stability-deprecated.rs:340:13
|
-LL | ... foo.method_deprecated_text();
- | ^^^^^^^^^^^^^^^^^^^^^^
+LL | foo.method_deprecated_text();
+ | ^^^^^^^^^^^^^^^^^^^^^^
-warning: use of deprecated associated function `this_crate::MethodTester::method_deprecated_text`: text
+warning: use of deprecated method `this_crate::MethodTester::method_deprecated_text`: text
--> $DIR/lint-stability-deprecated.rs:341:14
|
-LL | ... Foo::method_deprecated_text(&foo);
- | ^^^^^^^^^^^^^^^^^^^^^^
+LL | Foo::method_deprecated_text(&foo);
+ | ^^^^^^^^^^^^^^^^^^^^^^
-warning: use of deprecated associated function `this_crate::MethodTester::method_deprecated_text`: text
+warning: use of deprecated method `this_crate::MethodTester::method_deprecated_text`: text
--> $DIR/lint-stability-deprecated.rs:342:16
|
-LL | ... <Foo>::method_deprecated_text(&foo);
- | ^^^^^^^^^^^^^^^^^^^^^^
+LL | <Foo>::method_deprecated_text(&foo);
+ | ^^^^^^^^^^^^^^^^^^^^^^
-warning: use of deprecated associated function `this_crate::Trait::trait_deprecated_text`: text
+warning: use of deprecated method `this_crate::Trait::trait_deprecated_text`: text
--> $DIR/lint-stability-deprecated.rs:343:13
|
LL | foo.trait_deprecated_text();
| ^^^^^^^^^^^^^^^^^^^^^
-warning: use of deprecated associated function `this_crate::Trait::trait_deprecated_text`: text
+warning: use of deprecated method `this_crate::Trait::trait_deprecated_text`: text
--> $DIR/lint-stability-deprecated.rs:345:16
|
LL | <Foo>::trait_deprecated_text(&foo);
@@ -598,37 +598,37 @@ warning: use of deprecated field `this_crate::DeprecatedStruct::i`: text
LL | i: 0
| ^^^^
-warning: use of deprecated associated function `this_crate::Trait::trait_deprecated`: text
+warning: use of deprecated method `this_crate::Trait::trait_deprecated`: text
--> $DIR/lint-stability-deprecated.rs:405:13
|
LL | foo.trait_deprecated();
| ^^^^^^^^^^^^^^^^
-warning: use of deprecated associated function `this_crate::Trait::trait_deprecated`: text
+warning: use of deprecated method `this_crate::Trait::trait_deprecated`: text
--> $DIR/lint-stability-deprecated.rs:407:16
|
LL | <Foo>::trait_deprecated(&foo);
| ^^^^^^^^^^^^^^^^
-warning: use of deprecated associated function `this_crate::Trait::trait_deprecated_text`: text
+warning: use of deprecated method `this_crate::Trait::trait_deprecated_text`: text
--> $DIR/lint-stability-deprecated.rs:409:13
|
LL | foo.trait_deprecated_text();
| ^^^^^^^^^^^^^^^^^^^^^
-warning: use of deprecated associated function `this_crate::Trait::trait_deprecated_text`: text
+warning: use of deprecated method `this_crate::Trait::trait_deprecated_text`: text
--> $DIR/lint-stability-deprecated.rs:411:16
|
LL | <Foo>::trait_deprecated_text(&foo);
| ^^^^^^^^^^^^^^^^^^^^^
-warning: use of deprecated associated function `this_crate::Trait::trait_deprecated`: text
+warning: use of deprecated method `this_crate::Trait::trait_deprecated`: text
--> $DIR/lint-stability-deprecated.rs:428:13
|
LL | foo.trait_deprecated();
| ^^^^^^^^^^^^^^^^
-warning: use of deprecated associated function `this_crate::Trait::trait_deprecated_text`: text
+warning: use of deprecated method `this_crate::Trait::trait_deprecated_text`: text
--> $DIR/lint-stability-deprecated.rs:429:13
|
LL | foo.trait_deprecated_text();
diff --git a/tests/ui/lint/lint_map_unit_fn.rs b/tests/ui/lint/lint_map_unit_fn.rs
new file mode 100644
index 000000000..dc1ecbf84
--- /dev/null
+++ b/tests/ui/lint/lint_map_unit_fn.rs
@@ -0,0 +1,20 @@
+#![deny(map_unit_fn)]
+
+fn foo(items: &mut Vec<u8>) {
+ items.sort();
+}
+
+fn main() {
+ let mut x: Vec<Vec<u8>> = vec![vec![0, 2, 1], vec![5, 4, 3]];
+ x.iter_mut().map(foo);
+ //~^ ERROR `Iterator::map` call that discard the iterator's values
+ x.iter_mut().map(|items| {
+ //~^ ERROR `Iterator::map` call that discard the iterator's values
+ items.sort();
+ });
+ let f = |items: &mut Vec<u8>| {
+ items.sort();
+ };
+ x.iter_mut().map(f);
+ //~^ ERROR `Iterator::map` call that discard the iterator's values
+}
diff --git a/tests/ui/lint/lint_map_unit_fn.stderr b/tests/ui/lint/lint_map_unit_fn.stderr
new file mode 100644
index 000000000..fbf689c54
--- /dev/null
+++ b/tests/ui/lint/lint_map_unit_fn.stderr
@@ -0,0 +1,66 @@
+error: `Iterator::map` call that discard the iterator's values
+ --> $DIR/lint_map_unit_fn.rs:9:18
+ |
+LL | fn foo(items: &mut Vec<u8>) {
+ | --------------------------- this function returns `()`, which is likely not what you wanted
+...
+LL | x.iter_mut().map(foo);
+ | ^^^^---^
+ | | |
+ | | called `Iterator::map` with callable that returns `()`
+ | after this call to map, the resulting iterator is `impl Iterator<Item = ()>`, which means the only information carried by the iterator is the number of items
+ |
+ = note: `Iterator::map`, like many of the methods on `Iterator`, gets executed lazily, meaning that its effects won't be visible until it is iterated
+note: the lint level is defined here
+ --> $DIR/lint_map_unit_fn.rs:1:9
+ |
+LL | #![deny(map_unit_fn)]
+ | ^^^^^^^^^^^
+help: you might have meant to use `Iterator::for_each`
+ |
+LL | x.iter_mut().for_each(foo);
+ | ~~~~~~~~
+
+error: `Iterator::map` call that discard the iterator's values
+ --> $DIR/lint_map_unit_fn.rs:11:18
+ |
+LL | x.iter_mut().map(|items| {
+ | ^ -------
+ | | |
+ | ____________________|___this function returns `()`, which is likely not what you wanted
+ | | __________________|
+ | | |
+LL | | |
+LL | | | items.sort();
+LL | | | });
+ | | | -^ after this call to map, the resulting iterator is `impl Iterator<Item = ()>`, which means the only information carried by the iterator is the number of items
+ | | |_____||
+ | |_______|
+ | called `Iterator::map` with callable that returns `()`
+ |
+ = note: `Iterator::map`, like many of the methods on `Iterator`, gets executed lazily, meaning that its effects won't be visible until it is iterated
+help: you might have meant to use `Iterator::for_each`
+ |
+LL | x.iter_mut().for_each(|items| {
+ | ~~~~~~~~
+
+error: `Iterator::map` call that discard the iterator's values
+ --> $DIR/lint_map_unit_fn.rs:18:18
+ |
+LL | let f = |items: &mut Vec<u8>| {
+ | --------------------- this function returns `()`, which is likely not what you wanted
+...
+LL | x.iter_mut().map(f);
+ | ^^^^-^
+ | | |
+ | | called `Iterator::map` with callable that returns `()`
+ | after this call to map, the resulting iterator is `impl Iterator<Item = ()>`, which means the only information carried by the iterator is the number of items
+ |
+ = note: `Iterator::map`, like many of the methods on `Iterator`, gets executed lazily, meaning that its effects won't be visible until it is iterated
+help: you might have meant to use `Iterator::for_each`
+ |
+LL | x.iter_mut().for_each(f);
+ | ~~~~~~~~
+
+error: aborting due to 3 previous errors
+
diff --git a/tests/ui/lint/must_not_suspend/dedup.drop_tracking.stderr b/tests/ui/lint/must_not_suspend/dedup.drop_tracking.stderr
new file mode 100644
index 000000000..262657da5
--- /dev/null
+++ b/tests/ui/lint/must_not_suspend/dedup.drop_tracking.stderr
@@ -0,0 +1,21 @@
+error: `No` held across a suspend point, but should not be
+ --> $DIR/dedup.rs:19:9
+ |
+LL | let no = No {};
+ | ^^
+LL | wheeee(&no).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/dedup.rs:19:9
+ |
+LL | let no = No {};
+ | ^^
+note: the lint level is defined here
+ --> $DIR/dedup.rs:6:9
+ |
+LL | #![deny(must_not_suspend)]
+ | ^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/tests/ui/lint/must_not_suspend/dedup.drop_tracking_mir.stderr b/tests/ui/lint/must_not_suspend/dedup.drop_tracking_mir.stderr
new file mode 100644
index 000000000..262657da5
--- /dev/null
+++ b/tests/ui/lint/must_not_suspend/dedup.drop_tracking_mir.stderr
@@ -0,0 +1,21 @@
+error: `No` held across a suspend point, but should not be
+ --> $DIR/dedup.rs:19:9
+ |
+LL | let no = No {};
+ | ^^
+LL | wheeee(&no).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/dedup.rs:19:9
+ |
+LL | let no = No {};
+ | ^^
+note: the lint level is defined here
+ --> $DIR/dedup.rs:6:9
+ |
+LL | #![deny(must_not_suspend)]
+ | ^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/tests/ui/lint/must_not_suspend/dedup.no_drop_tracking.stderr b/tests/ui/lint/must_not_suspend/dedup.no_drop_tracking.stderr
new file mode 100644
index 000000000..7ed43d257
--- /dev/null
+++ b/tests/ui/lint/must_not_suspend/dedup.no_drop_tracking.stderr
@@ -0,0 +1,33 @@
+error: `No` held across a suspend point, but should not be
+ --> $DIR/dedup.rs:19:9
+ |
+LL | let no = No {};
+ | ^^
+LL | wheeee(&no).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/dedup.rs:19:9
+ |
+LL | let no = No {};
+ | ^^
+note: the lint level is defined here
+ --> $DIR/dedup.rs:6:9
+ |
+LL | #![deny(must_not_suspend)]
+ | ^^^^^^^^^^^^^^^^
+
+error: `No` held across a suspend point, but should not be
+ --> $DIR/dedup.rs:20:13
+ |
+LL | wheeee(&no).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/dedup.rs:20:13
+ |
+LL | wheeee(&no).await;
+ | ^^
+
+error: aborting due to 2 previous errors
+
diff --git a/tests/ui/lint/must_not_suspend/dedup.rs b/tests/ui/lint/must_not_suspend/dedup.rs
index 81a08579b..96bdb7715 100644
--- a/tests/ui/lint/must_not_suspend/dedup.rs
+++ b/tests/ui/lint/must_not_suspend/dedup.rs
@@ -1,3 +1,6 @@
+// revisions: no_drop_tracking drop_tracking drop_tracking_mir
+// [drop_tracking] compile-flags: -Zdrop-tracking
+// [drop_tracking_mir] compile-flags: -Zdrop-tracking-mir
// edition:2018
#![feature(must_not_suspend)]
#![deny(must_not_suspend)]
@@ -13,7 +16,9 @@ async fn wheeee<T>(t: T) {
}
async fn yes() {
- wheeee(&No {}).await; //~ ERROR `No` held across
+ let no = No {}; //~ ERROR `No` held across
+ wheeee(&no).await; //[no_drop_tracking]~ ERROR `No` held across
+ drop(no);
}
fn main() {
diff --git a/tests/ui/lint/must_not_suspend/dedup.stderr b/tests/ui/lint/must_not_suspend/dedup.stderr
index f8978ba57..18880f5a7 100644
--- a/tests/ui/lint/must_not_suspend/dedup.stderr
+++ b/tests/ui/lint/must_not_suspend/dedup.stderr
@@ -1,16 +1,16 @@
error: `No` held across a suspend point, but should not be
- --> $DIR/dedup.rs:16:13
+ --> $DIR/dedup.rs:19:13
|
LL | wheeee(&No {}).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/dedup.rs:16:13
+ --> $DIR/dedup.rs:19:13
|
LL | wheeee(&No {}).await;
| ^^^^^
note: the lint level is defined here
- --> $DIR/dedup.rs:3:9
+ --> $DIR/dedup.rs:6:9
|
LL | #![deny(must_not_suspend)]
| ^^^^^^^^^^^^^^^^
diff --git a/tests/ui/lint/must_not_suspend/ref.drop_tracking.stderr b/tests/ui/lint/must_not_suspend/ref.drop_tracking.stderr
index abf76711b..e3628ca5e 100644
--- a/tests/ui/lint/must_not_suspend/ref.drop_tracking.stderr
+++ b/tests/ui/lint/must_not_suspend/ref.drop_tracking.stderr
@@ -1,5 +1,5 @@
error: reference to `Umm` held across a suspend point, but should not be
- --> $DIR/ref.rs:21:13
+ --> $DIR/ref.rs:22:13
|
LL | let guard = &mut self.u;
| ^^^^^
@@ -8,17 +8,17 @@ LL | other().await;
| ------ the value is held across this suspend point
|
note: You gotta use Umm's, ya know?
- --> $DIR/ref.rs:21:13
+ --> $DIR/ref.rs:22:13
|
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:21:13
+ --> $DIR/ref.rs:22:13
|
LL | let guard = &mut self.u;
| ^^^^^
note: the lint level is defined here
- --> $DIR/ref.rs:6:9
+ --> $DIR/ref.rs:7:9
|
LL | #![deny(must_not_suspend)]
| ^^^^^^^^^^^^^^^^
diff --git a/tests/ui/lint/must_not_suspend/ref.drop_tracking_mir.stderr b/tests/ui/lint/must_not_suspend/ref.drop_tracking_mir.stderr
new file mode 100644
index 000000000..e3628ca5e
--- /dev/null
+++ b/tests/ui/lint/must_not_suspend/ref.drop_tracking_mir.stderr
@@ -0,0 +1,27 @@
+error: reference to `Umm` held across a suspend point, but should not be
+ --> $DIR/ref.rs:22:13
+ |
+LL | let guard = &mut self.u;
+ | ^^^^^
+LL |
+LL | other().await;
+ | ------ the value is held across this suspend point
+ |
+note: You gotta use Umm's, ya know?
+ --> $DIR/ref.rs:22:13
+ |
+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:22:13
+ |
+LL | let guard = &mut self.u;
+ | ^^^^^
+note: the lint level is defined here
+ --> $DIR/ref.rs:7:9
+ |
+LL | #![deny(must_not_suspend)]
+ | ^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/tests/ui/lint/must_not_suspend/ref.no_drop_tracking.stderr b/tests/ui/lint/must_not_suspend/ref.no_drop_tracking.stderr
index 41ac09ea7..e9bfa08b5 100644
--- a/tests/ui/lint/must_not_suspend/ref.no_drop_tracking.stderr
+++ b/tests/ui/lint/must_not_suspend/ref.no_drop_tracking.stderr
@@ -1,5 +1,5 @@
error: `Umm` held across a suspend point, but should not be
- --> $DIR/ref.rs:21:26
+ --> $DIR/ref.rs:22:26
|
LL | let guard = &mut self.u;
| ^^^^^^
@@ -8,17 +8,17 @@ LL | other().await;
| ------ the value is held across this suspend point
|
note: You gotta use Umm's, ya know?
- --> $DIR/ref.rs:21:26
+ --> $DIR/ref.rs:22: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:21:26
+ --> $DIR/ref.rs:22:26
|
LL | let guard = &mut self.u;
| ^^^^^^
note: the lint level is defined here
- --> $DIR/ref.rs:6:9
+ --> $DIR/ref.rs:7:9
|
LL | #![deny(must_not_suspend)]
| ^^^^^^^^^^^^^^^^
diff --git a/tests/ui/lint/must_not_suspend/ref.rs b/tests/ui/lint/must_not_suspend/ref.rs
index f6b23746f..d05dcb83a 100644
--- a/tests/ui/lint/must_not_suspend/ref.rs
+++ b/tests/ui/lint/must_not_suspend/ref.rs
@@ -1,7 +1,8 @@
// edition:2018
-// revisions: no_drop_tracking drop_tracking
-// [drop_tracking] compile-flags: -Zdrop-tracking=yes
-// [no_drop_tracking] compile-flags: -Zdrop-tracking=no
+// revisions: no_drop_tracking drop_tracking drop_tracking_mir
+// [drop_tracking] compile-flags: -Zdrop-tracking
+// [drop_tracking_mir] compile-flags: -Zdrop-tracking-mir
+
#![feature(must_not_suspend)]
#![deny(must_not_suspend)]
@@ -22,6 +23,7 @@ impl Bar {
other().await;
+ let _g = &*guard;
*guard = Umm { i: 2 }
}
}
diff --git a/tests/ui/lint/must_not_suspend/trait.drop_tracking.stderr b/tests/ui/lint/must_not_suspend/trait.drop_tracking.stderr
new file mode 100644
index 000000000..6e62a228a
--- /dev/null
+++ b/tests/ui/lint/must_not_suspend/trait.drop_tracking.stderr
@@ -0,0 +1,37 @@
+error: implementer of `Wow` held across a suspend point, but should not be
+ --> $DIR/trait.rs:24:9
+ |
+LL | let _guard1 = r#impl();
+ | ^^^^^^^
+...
+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:24:9
+ |
+LL | let _guard1 = r#impl();
+ | ^^^^^^^
+note: the lint level is defined here
+ --> $DIR/trait.rs:6:9
+ |
+LL | #![deny(must_not_suspend)]
+ | ^^^^^^^^^^^^^^^^
+
+error: boxed `Wow` trait object held across a suspend point, but should not be
+ --> $DIR/trait.rs:25: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:25:9
+ |
+LL | let _guard2 = r#dyn();
+ | ^^^^^^^
+
+error: aborting due to 2 previous errors
+
diff --git a/tests/ui/lint/must_not_suspend/trait.drop_tracking_mir.stderr b/tests/ui/lint/must_not_suspend/trait.drop_tracking_mir.stderr
new file mode 100644
index 000000000..6e62a228a
--- /dev/null
+++ b/tests/ui/lint/must_not_suspend/trait.drop_tracking_mir.stderr
@@ -0,0 +1,37 @@
+error: implementer of `Wow` held across a suspend point, but should not be
+ --> $DIR/trait.rs:24:9
+ |
+LL | let _guard1 = r#impl();
+ | ^^^^^^^
+...
+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:24:9
+ |
+LL | let _guard1 = r#impl();
+ | ^^^^^^^
+note: the lint level is defined here
+ --> $DIR/trait.rs:6:9
+ |
+LL | #![deny(must_not_suspend)]
+ | ^^^^^^^^^^^^^^^^
+
+error: boxed `Wow` trait object held across a suspend point, but should not be
+ --> $DIR/trait.rs:25: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:25:9
+ |
+LL | let _guard2 = r#dyn();
+ | ^^^^^^^
+
+error: aborting due to 2 previous errors
+
diff --git a/tests/ui/lint/must_not_suspend/trait.no_drop_tracking.stderr b/tests/ui/lint/must_not_suspend/trait.no_drop_tracking.stderr
new file mode 100644
index 000000000..6e62a228a
--- /dev/null
+++ b/tests/ui/lint/must_not_suspend/trait.no_drop_tracking.stderr
@@ -0,0 +1,37 @@
+error: implementer of `Wow` held across a suspend point, but should not be
+ --> $DIR/trait.rs:24:9
+ |
+LL | let _guard1 = r#impl();
+ | ^^^^^^^
+...
+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:24:9
+ |
+LL | let _guard1 = r#impl();
+ | ^^^^^^^
+note: the lint level is defined here
+ --> $DIR/trait.rs:6:9
+ |
+LL | #![deny(must_not_suspend)]
+ | ^^^^^^^^^^^^^^^^
+
+error: boxed `Wow` trait object held across a suspend point, but should not be
+ --> $DIR/trait.rs:25: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:25:9
+ |
+LL | let _guard2 = r#dyn();
+ | ^^^^^^^
+
+error: aborting due to 2 previous errors
+
diff --git a/tests/ui/lint/must_not_suspend/trait.rs b/tests/ui/lint/must_not_suspend/trait.rs
index 6c911cb4b..cc3ae298d 100644
--- a/tests/ui/lint/must_not_suspend/trait.rs
+++ b/tests/ui/lint/must_not_suspend/trait.rs
@@ -1,3 +1,6 @@
+// revisions: no_drop_tracking drop_tracking drop_tracking_mir
+// [drop_tracking] compile-flags: -Zdrop-tracking
+// [drop_tracking_mir] compile-flags: -Zdrop-tracking-mir
// edition:2018
#![feature(must_not_suspend)]
#![deny(must_not_suspend)]
@@ -22,6 +25,9 @@ pub async fn uhoh() {
let _guard2 = r#dyn(); //~ ERROR boxed `Wow` trait object held across
other().await;
+
+ drop(_guard1);
+ drop(_guard2);
}
fn main() {
diff --git a/tests/ui/lint/must_not_suspend/trait.stderr b/tests/ui/lint/must_not_suspend/trait.stderr
index d64d25aae..6e62a228a 100644
--- a/tests/ui/lint/must_not_suspend/trait.stderr
+++ b/tests/ui/lint/must_not_suspend/trait.stderr
@@ -1,5 +1,5 @@
error: implementer of `Wow` held across a suspend point, but should not be
- --> $DIR/trait.rs:21:9
+ --> $DIR/trait.rs:24:9
|
LL | let _guard1 = r#impl();
| ^^^^^^^
@@ -8,18 +8,18 @@ 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:21:9
+ --> $DIR/trait.rs:24:9
|
LL | let _guard1 = r#impl();
| ^^^^^^^
note: the lint level is defined here
- --> $DIR/trait.rs:3:9
+ --> $DIR/trait.rs:6:9
|
LL | #![deny(must_not_suspend)]
| ^^^^^^^^^^^^^^^^
error: boxed `Wow` trait object held across a suspend point, but should not be
- --> $DIR/trait.rs:22:9
+ --> $DIR/trait.rs:25:9
|
LL | let _guard2 = r#dyn();
| ^^^^^^^
@@ -28,7 +28,7 @@ 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
+ --> $DIR/trait.rs:25:9
|
LL | let _guard2 = r#dyn();
| ^^^^^^^
diff --git a/tests/ui/lint/must_not_suspend/tuple-mismatch.stderr b/tests/ui/lint/must_not_suspend/tuple-mismatch.stderr
index cca8cd9bd..294476107 100644
--- a/tests/ui/lint/must_not_suspend/tuple-mismatch.stderr
+++ b/tests/ui/lint/must_not_suspend/tuple-mismatch.stderr
@@ -2,7 +2,7 @@ error[E0308]: mismatched types
--> $DIR/tuple-mismatch.rs:6:20
|
LL | yield ((), ());
- | ^^ expected tuple, found `()`
+ | ^^ expected `((), ())`, found `()`
|
= note: expected tuple `((), ())`
found unit type `()`
diff --git a/tests/ui/lint/must_not_suspend/unit.drop_tracking.stderr b/tests/ui/lint/must_not_suspend/unit.drop_tracking.stderr
new file mode 100644
index 000000000..f89b3e341
--- /dev/null
+++ b/tests/ui/lint/must_not_suspend/unit.drop_tracking.stderr
@@ -0,0 +1,26 @@
+error: `Umm` held across a suspend point, but should not be
+ --> $DIR/unit.rs:22:9
+ |
+LL | let _guard = bar();
+ | ^^^^^^
+LL | other().await;
+ | ------ the value is held across this suspend point
+ |
+note: You gotta use Umm's, ya know?
+ --> $DIR/unit.rs:22:9
+ |
+LL | let _guard = bar();
+ | ^^^^^^
+help: consider using a block (`{ ... }`) to shrink the value's scope, ending before the suspend point
+ --> $DIR/unit.rs:22:9
+ |
+LL | let _guard = bar();
+ | ^^^^^^
+note: the lint level is defined here
+ --> $DIR/unit.rs:6:9
+ |
+LL | #![deny(must_not_suspend)]
+ | ^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/tests/ui/lint/must_not_suspend/unit.drop_tracking_mir.stderr b/tests/ui/lint/must_not_suspend/unit.drop_tracking_mir.stderr
new file mode 100644
index 000000000..f89b3e341
--- /dev/null
+++ b/tests/ui/lint/must_not_suspend/unit.drop_tracking_mir.stderr
@@ -0,0 +1,26 @@
+error: `Umm` held across a suspend point, but should not be
+ --> $DIR/unit.rs:22:9
+ |
+LL | let _guard = bar();
+ | ^^^^^^
+LL | other().await;
+ | ------ the value is held across this suspend point
+ |
+note: You gotta use Umm's, ya know?
+ --> $DIR/unit.rs:22:9
+ |
+LL | let _guard = bar();
+ | ^^^^^^
+help: consider using a block (`{ ... }`) to shrink the value's scope, ending before the suspend point
+ --> $DIR/unit.rs:22:9
+ |
+LL | let _guard = bar();
+ | ^^^^^^
+note: the lint level is defined here
+ --> $DIR/unit.rs:6:9
+ |
+LL | #![deny(must_not_suspend)]
+ | ^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/tests/ui/lint/must_not_suspend/unit.no_drop_tracking.stderr b/tests/ui/lint/must_not_suspend/unit.no_drop_tracking.stderr
new file mode 100644
index 000000000..f89b3e341
--- /dev/null
+++ b/tests/ui/lint/must_not_suspend/unit.no_drop_tracking.stderr
@@ -0,0 +1,26 @@
+error: `Umm` held across a suspend point, but should not be
+ --> $DIR/unit.rs:22:9
+ |
+LL | let _guard = bar();
+ | ^^^^^^
+LL | other().await;
+ | ------ the value is held across this suspend point
+ |
+note: You gotta use Umm's, ya know?
+ --> $DIR/unit.rs:22:9
+ |
+LL | let _guard = bar();
+ | ^^^^^^
+help: consider using a block (`{ ... }`) to shrink the value's scope, ending before the suspend point
+ --> $DIR/unit.rs:22:9
+ |
+LL | let _guard = bar();
+ | ^^^^^^
+note: the lint level is defined here
+ --> $DIR/unit.rs:6:9
+ |
+LL | #![deny(must_not_suspend)]
+ | ^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/tests/ui/lint/must_not_suspend/unit.rs b/tests/ui/lint/must_not_suspend/unit.rs
index d3a19f704..fbc51b366 100644
--- a/tests/ui/lint/must_not_suspend/unit.rs
+++ b/tests/ui/lint/must_not_suspend/unit.rs
@@ -1,3 +1,6 @@
+// revisions: no_drop_tracking drop_tracking drop_tracking_mir
+// [drop_tracking] compile-flags: -Zdrop-tracking
+// [drop_tracking_mir] compile-flags: -Zdrop-tracking-mir
// edition:2018
#![feature(must_not_suspend)]
#![deny(must_not_suspend)]
@@ -7,7 +10,6 @@ struct Umm {
i: i64
}
-
fn bar() -> Umm {
Umm {
i: 1
@@ -19,6 +21,7 @@ async fn other() {}
pub async fn uhoh() {
let _guard = bar(); //~ ERROR `Umm` held across
other().await;
+ drop(_guard);
}
fn main() {
diff --git a/tests/ui/lint/must_not_suspend/unit.stderr b/tests/ui/lint/must_not_suspend/unit.stderr
index c967dbac5..50ca292c2 100644
--- a/tests/ui/lint/must_not_suspend/unit.stderr
+++ b/tests/ui/lint/must_not_suspend/unit.stderr
@@ -1,5 +1,5 @@
error: `Umm` held across a suspend point, but should not be
- --> $DIR/unit.rs:20:9
+ --> $DIR/unit.rs:23:9
|
LL | let _guard = bar();
| ^^^^^^
@@ -7,17 +7,17 @@ LL | other().await;
| ------ the value is held across this suspend point
|
note: You gotta use Umm's, ya know?
- --> $DIR/unit.rs:20:9
+ --> $DIR/unit.rs:23: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
+ --> $DIR/unit.rs:23:9
|
LL | let _guard = bar();
| ^^^^^^
note: the lint level is defined here
- --> $DIR/unit.rs:3:9
+ --> $DIR/unit.rs:6:9
|
LL | #![deny(must_not_suspend)]
| ^^^^^^^^^^^^^^^^
diff --git a/tests/ui/lint/must_not_suspend/warn.drop_tracking.stderr b/tests/ui/lint/must_not_suspend/warn.drop_tracking.stderr
new file mode 100644
index 000000000..7a422891a
--- /dev/null
+++ b/tests/ui/lint/must_not_suspend/warn.drop_tracking.stderr
@@ -0,0 +1,26 @@
+warning: `Umm` held across a suspend point, but should not be
+ --> $DIR/warn.rs:24:9
+ |
+LL | let _guard = bar();
+ | ^^^^^^
+LL | other().await;
+ | ------ the value is held across this suspend point
+ |
+note: You gotta use Umm's, ya know?
+ --> $DIR/warn.rs:24:9
+ |
+LL | let _guard = bar();
+ | ^^^^^^
+help: consider using a block (`{ ... }`) to shrink the value's scope, ending before the suspend point
+ --> $DIR/warn.rs:24:9
+ |
+LL | let _guard = bar();
+ | ^^^^^^
+note: the lint level is defined here
+ --> $DIR/warn.rs:7:9
+ |
+LL | #![warn(must_not_suspend)]
+ | ^^^^^^^^^^^^^^^^
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/lint/must_not_suspend/warn.drop_tracking_mir.stderr b/tests/ui/lint/must_not_suspend/warn.drop_tracking_mir.stderr
new file mode 100644
index 000000000..7a422891a
--- /dev/null
+++ b/tests/ui/lint/must_not_suspend/warn.drop_tracking_mir.stderr
@@ -0,0 +1,26 @@
+warning: `Umm` held across a suspend point, but should not be
+ --> $DIR/warn.rs:24:9
+ |
+LL | let _guard = bar();
+ | ^^^^^^
+LL | other().await;
+ | ------ the value is held across this suspend point
+ |
+note: You gotta use Umm's, ya know?
+ --> $DIR/warn.rs:24:9
+ |
+LL | let _guard = bar();
+ | ^^^^^^
+help: consider using a block (`{ ... }`) to shrink the value's scope, ending before the suspend point
+ --> $DIR/warn.rs:24:9
+ |
+LL | let _guard = bar();
+ | ^^^^^^
+note: the lint level is defined here
+ --> $DIR/warn.rs:7:9
+ |
+LL | #![warn(must_not_suspend)]
+ | ^^^^^^^^^^^^^^^^
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/lint/must_not_suspend/warn.no_drop_tracking.stderr b/tests/ui/lint/must_not_suspend/warn.no_drop_tracking.stderr
new file mode 100644
index 000000000..7a422891a
--- /dev/null
+++ b/tests/ui/lint/must_not_suspend/warn.no_drop_tracking.stderr
@@ -0,0 +1,26 @@
+warning: `Umm` held across a suspend point, but should not be
+ --> $DIR/warn.rs:24:9
+ |
+LL | let _guard = bar();
+ | ^^^^^^
+LL | other().await;
+ | ------ the value is held across this suspend point
+ |
+note: You gotta use Umm's, ya know?
+ --> $DIR/warn.rs:24:9
+ |
+LL | let _guard = bar();
+ | ^^^^^^
+help: consider using a block (`{ ... }`) to shrink the value's scope, ending before the suspend point
+ --> $DIR/warn.rs:24:9
+ |
+LL | let _guard = bar();
+ | ^^^^^^
+note: the lint level is defined here
+ --> $DIR/warn.rs:7:9
+ |
+LL | #![warn(must_not_suspend)]
+ | ^^^^^^^^^^^^^^^^
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/lint/must_not_suspend/warn.rs b/tests/ui/lint/must_not_suspend/warn.rs
index 7fdea66a2..5a4863169 100644
--- a/tests/ui/lint/must_not_suspend/warn.rs
+++ b/tests/ui/lint/must_not_suspend/warn.rs
@@ -1,3 +1,6 @@
+// revisions: no_drop_tracking drop_tracking drop_tracking_mir
+// [drop_tracking] compile-flags: -Zdrop-tracking
+// [drop_tracking_mir] compile-flags: -Zdrop-tracking-mir
// edition:2018
// run-pass
#![feature(must_not_suspend)]
@@ -20,6 +23,7 @@ async fn other() {}
pub async fn uhoh() {
let _guard = bar(); //~ WARNING `Umm` held across
other().await;
+ drop(_guard);
}
fn main() {
diff --git a/tests/ui/lint/must_not_suspend/warn.stderr b/tests/ui/lint/must_not_suspend/warn.stderr
index fe551c652..7a422891a 100644
--- a/tests/ui/lint/must_not_suspend/warn.stderr
+++ b/tests/ui/lint/must_not_suspend/warn.stderr
@@ -1,5 +1,5 @@
warning: `Umm` held across a suspend point, but should not be
- --> $DIR/warn.rs:21:9
+ --> $DIR/warn.rs:24:9
|
LL | let _guard = bar();
| ^^^^^^
@@ -7,17 +7,17 @@ LL | other().await;
| ------ the value is held across this suspend point
|
note: You gotta use Umm's, ya know?
- --> $DIR/warn.rs:21:9
+ --> $DIR/warn.rs:24: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
+ --> $DIR/warn.rs:24:9
|
LL | let _guard = bar();
| ^^^^^^
note: the lint level is defined here
- --> $DIR/warn.rs:4:9
+ --> $DIR/warn.rs:7:9
|
LL | #![warn(must_not_suspend)]
| ^^^^^^^^^^^^^^^^
diff --git a/tests/ui/lint/reasons-forbidden.rs b/tests/ui/lint/reasons-forbidden.rs
index 9c2edec4d..947099fdd 100644
--- a/tests/ui/lint/reasons-forbidden.rs
+++ b/tests/ui/lint/reasons-forbidden.rs
@@ -8,7 +8,7 @@
//
// The test is much cleaner if we deduplicate, though.
-// compile-flags: -Z deduplicate-diagnostics=yes
+// compile-flags: -Z deduplicate-diagnostics=true
#![forbid(
unsafe_code,
diff --git a/tests/ui/lint/unaligned_references.rs b/tests/ui/lint/unaligned_references.rs
index e547f031a..0c9c79c08 100644
--- a/tests/ui/lint/unaligned_references.rs
+++ b/tests/ui/lint/unaligned_references.rs
@@ -1,5 +1,3 @@
-#![deny(unaligned_references)]
-
#[repr(packed)]
pub struct Good {
data: u64,
@@ -15,25 +13,33 @@ pub struct Packed2 {
z: u8,
}
+trait Foo {
+ fn evil(&self);
+}
+
+// Test for #108122
+#[automatically_derived]
+impl Foo for Packed2 {
+ fn evil(&self) {
+ unsafe {
+ &self.x; //~ ERROR reference to packed field
+ }
+ }
+}
+
fn main() {
unsafe {
let good = Good { data: 0, ptr: &0, data2: [0, 0], aligned: [0; 32] };
let _ = &good.ptr; //~ ERROR reference to packed field
- //~^ previously accepted
let _ = &good.data; //~ ERROR reference to packed field
- //~^ previously accepted
// Error even when turned into raw pointer immediately.
let _ = &good.data as *const _; //~ ERROR reference to packed field
- //~^ previously accepted
let _: *const _ = &good.data; //~ ERROR reference to packed field
- //~^ previously accepted
// Error on method call.
let _ = good.data.clone(); //~ ERROR reference to packed field
- //~^ previously accepted
// Error for nested fields.
let _ = &good.data2[0]; //~ ERROR reference to packed field
- //~^ previously accepted
let _ = &*good.ptr; // ok, behind a pointer
let _ = &good.aligned; // ok, has align 1
@@ -43,9 +49,9 @@ fn main() {
unsafe {
let packed2 = Packed2 { x: 0, y: 0, z: 0 };
let _ = &packed2.x; //~ ERROR reference to packed field
- //~^ previously accepted
let _ = &packed2.y; // ok, has align 2 in packed(2) struct
let _ = &packed2.z; // ok, has align 1
+ packed2.evil();
}
unsafe {
@@ -80,24 +86,10 @@ fn main() {
#[repr(packed)]
struct Misalign<T>(u8, T);
- let m1 = Misalign(
- 0,
- Wrapper {
- a: U16(10),
- b: HasDrop,
- },
- );
+ let m1 = Misalign(0, Wrapper { a: U16(10), b: HasDrop });
let _ref = &m1.1.a; //~ ERROR reference to packed field
- //~^ previously accepted
- let m2 = Misalign(
- 0,
- Wrapper2 {
- a: U16(10),
- b: HasDrop,
- },
- );
+ let m2 = Misalign(0, Wrapper2 { a: U16(10), b: HasDrop });
let _ref = &m2.1.a; //~ ERROR reference to packed field
- //~^ previously accepted
}
}
diff --git a/tests/ui/lint/unaligned_references.stderr b/tests/ui/lint/unaligned_references.stderr
index 346f49b92..775dcac67 100644
--- a/tests/ui/lint/unaligned_references.stderr
+++ b/tests/ui/lint/unaligned_references.stderr
@@ -1,259 +1,93 @@
-error: reference to packed field is unaligned
- --> $DIR/unaligned_references.rs:22:17
+error[E0793]: reference to packed field is unaligned
+ --> $DIR/unaligned_references.rs:25:13
|
-LL | let _ = &good.ptr;
- | ^^^^^^^^^
- |
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523>
- = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
- = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
-note: the lint level is defined here
- --> $DIR/unaligned_references.rs:1:9
- |
-LL | #![deny(unaligned_references)]
- | ^^^^^^^^^^^^^^^^^^^^
-
-error: reference to packed field is unaligned
- --> $DIR/unaligned_references.rs:24:17
- |
-LL | let _ = &good.data;
- | ^^^^^^^^^^
- |
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523>
- = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
- = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
-
-error: reference to packed field is unaligned
- --> $DIR/unaligned_references.rs:27:17
- |
-LL | let _ = &good.data as *const _;
- | ^^^^^^^^^^
- |
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523>
- = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
- = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
-
-error: reference to packed field is unaligned
- --> $DIR/unaligned_references.rs:29:27
- |
-LL | let _: *const _ = &good.data;
- | ^^^^^^^^^^
- |
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523>
- = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
- = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
-
-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 <https://github.com/rust-lang/rust/issues/82523>
- = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
- = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
-
-error: reference to packed field is unaligned
- --> $DIR/unaligned_references.rs:35:17
- |
-LL | let _ = &good.data2[0];
- | ^^^^^^^^^^^^^^
- |
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523>
- = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
- = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
-
-error: reference to packed field is unaligned
- --> $DIR/unaligned_references.rs:45:17
+LL | &self.x;
+ | ^^^^^^^
|
-LL | let _ = &packed2.x;
- | ^^^^^^^^^^
- |
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523>
= note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
= help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
-error: reference to packed field is unaligned
- --> $DIR/unaligned_references.rs:90:20
- |
-LL | let _ref = &m1.1.a;
- | ^^^^^^^
- |
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523>
- = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
- = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
-
-error: reference to packed field is unaligned
- --> $DIR/unaligned_references.rs:100:20
- |
-LL | let _ref = &m2.1.a;
- | ^^^^^^^
- |
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523>
- = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
- = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
-
-error: aborting due to 9 previous errors
-
-Future incompatibility report: Future breakage diagnostic:
-error: reference to packed field is unaligned
- --> $DIR/unaligned_references.rs:22:17
+error[E0793]: reference to packed field is unaligned
+ --> $DIR/unaligned_references.rs:34:17
|
LL | let _ = &good.ptr;
| ^^^^^^^^^
|
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523>
= note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
= help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
-note: the lint level is defined here
- --> $DIR/unaligned_references.rs:1:9
- |
-LL | #![deny(unaligned_references)]
- | ^^^^^^^^^^^^^^^^^^^^
-Future breakage diagnostic:
-error: reference to packed field is unaligned
- --> $DIR/unaligned_references.rs:24:17
+error[E0793]: reference to packed field is unaligned
+ --> $DIR/unaligned_references.rs:35:17
|
LL | let _ = &good.data;
| ^^^^^^^^^^
|
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523>
= note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
= help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
-note: the lint level is defined here
- --> $DIR/unaligned_references.rs:1:9
- |
-LL | #![deny(unaligned_references)]
- | ^^^^^^^^^^^^^^^^^^^^
-Future breakage diagnostic:
-error: reference to packed field is unaligned
- --> $DIR/unaligned_references.rs:27:17
+error[E0793]: reference to packed field is unaligned
+ --> $DIR/unaligned_references.rs:37:17
|
LL | let _ = &good.data as *const _;
| ^^^^^^^^^^
|
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523>
= note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
= help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
-note: the lint level is defined here
- --> $DIR/unaligned_references.rs:1:9
- |
-LL | #![deny(unaligned_references)]
- | ^^^^^^^^^^^^^^^^^^^^
-Future breakage diagnostic:
-error: reference to packed field is unaligned
- --> $DIR/unaligned_references.rs:29:27
+error[E0793]: reference to packed field is unaligned
+ --> $DIR/unaligned_references.rs:38:27
|
LL | let _: *const _ = &good.data;
| ^^^^^^^^^^
|
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523>
= note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
= help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
-note: the lint level is defined here
- --> $DIR/unaligned_references.rs:1:9
- |
-LL | #![deny(unaligned_references)]
- | ^^^^^^^^^^^^^^^^^^^^
-Future breakage diagnostic:
-error: reference to packed field is unaligned
- --> $DIR/unaligned_references.rs:32:17
+error[E0793]: reference to packed field is unaligned
+ --> $DIR/unaligned_references.rs:40:17
|
LL | let _ = good.data.clone();
| ^^^^^^^^^^^^^^^^^
|
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523>
= note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
= help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
-note: the lint level is defined here
- --> $DIR/unaligned_references.rs:1:9
- |
-LL | #![deny(unaligned_references)]
- | ^^^^^^^^^^^^^^^^^^^^
-Future breakage diagnostic:
-error: reference to packed field is unaligned
- --> $DIR/unaligned_references.rs:35:17
+error[E0793]: reference to packed field is unaligned
+ --> $DIR/unaligned_references.rs:42:17
|
LL | let _ = &good.data2[0];
| ^^^^^^^^^^^^^^
|
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523>
= note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
= help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
-note: the lint level is defined here
- --> $DIR/unaligned_references.rs:1:9
- |
-LL | #![deny(unaligned_references)]
- | ^^^^^^^^^^^^^^^^^^^^
-Future breakage diagnostic:
-error: reference to packed field is unaligned
- --> $DIR/unaligned_references.rs:45:17
+error[E0793]: reference to packed field is unaligned
+ --> $DIR/unaligned_references.rs:51:17
|
LL | let _ = &packed2.x;
| ^^^^^^^^^^
|
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523>
= note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
= help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
-note: the lint level is defined here
- --> $DIR/unaligned_references.rs:1:9
- |
-LL | #![deny(unaligned_references)]
- | ^^^^^^^^^^^^^^^^^^^^
-Future breakage diagnostic:
-error: reference to packed field is unaligned
+error[E0793]: reference to packed field is unaligned
--> $DIR/unaligned_references.rs:90:20
|
LL | let _ref = &m1.1.a;
| ^^^^^^^
|
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523>
= note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
= help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
-note: the lint level is defined here
- --> $DIR/unaligned_references.rs:1:9
- |
-LL | #![deny(unaligned_references)]
- | ^^^^^^^^^^^^^^^^^^^^
-Future breakage diagnostic:
-error: reference to packed field is unaligned
- --> $DIR/unaligned_references.rs:100:20
+error[E0793]: reference to packed field is unaligned
+ --> $DIR/unaligned_references.rs:93:20
|
LL | let _ref = &m2.1.a;
| ^^^^^^^
|
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523>
= note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
= help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
-note: the lint level is defined here
- --> $DIR/unaligned_references.rs:1:9
- |
-LL | #![deny(unaligned_references)]
- | ^^^^^^^^^^^^^^^^^^^^
+error: aborting due to 10 previous errors
+
+For more information about this error, try `rustc --explain E0793`.
diff --git a/tests/ui/lint/unaligned_references_external_macro.rs b/tests/ui/lint/unaligned_references_external_macro.rs
index cb597c38e..b655a2a8f 100644
--- a/tests/ui/lint/unaligned_references_external_macro.rs
+++ b/tests/ui/lint/unaligned_references_external_macro.rs
@@ -3,7 +3,6 @@
extern crate unaligned_references_external_crate;
unaligned_references_external_crate::mac! { //~ERROR reference to packed field is unaligned
- //~^ previously accepted
#[repr(packed)]
pub struct X {
pub field: u16
diff --git a/tests/ui/lint/unaligned_references_external_macro.stderr b/tests/ui/lint/unaligned_references_external_macro.stderr
index c46ca6742..5b08f433e 100644
--- a/tests/ui/lint/unaligned_references_external_macro.stderr
+++ b/tests/ui/lint/unaligned_references_external_macro.stderr
@@ -1,8 +1,7 @@
-error: reference to packed field is unaligned
+error[E0793]: reference to packed field is unaligned
--> $DIR/unaligned_references_external_macro.rs:5:1
|
LL | / unaligned_references_external_crate::mac! {
-LL | |
LL | | #[repr(packed)]
LL | | pub struct X {
LL | | pub field: u16
@@ -10,52 +9,10 @@ LL | | }
LL | | }
| |_^
|
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523>
= note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
= help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
-note: the lint level is defined here
- --> $DIR/unaligned_references_external_macro.rs:5:1
- |
-LL | / unaligned_references_external_crate::mac! {
-LL | |
-LL | | #[repr(packed)]
-LL | | pub struct X {
-LL | | pub field: u16
-LL | | }
-LL | | }
- | |_^
= note: this error originates in the macro `unaligned_references_external_crate::mac` (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to previous error
-Future incompatibility report: Future breakage diagnostic:
-error: reference to packed field is unaligned
- --> $DIR/unaligned_references_external_macro.rs:5:1
- |
-LL | / unaligned_references_external_crate::mac! {
-LL | |
-LL | | #[repr(packed)]
-LL | | pub struct X {
-LL | | pub field: u16
-LL | | }
-LL | | }
- | |_^
- |
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523>
- = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
- = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
-note: the lint level is defined here
- --> $DIR/unaligned_references_external_macro.rs:5:1
- |
-LL | / unaligned_references_external_crate::mac! {
-LL | |
-LL | | #[repr(packed)]
-LL | | pub struct X {
-LL | | pub field: u16
-LL | | }
-LL | | }
- | |_^
- = note: this error originates in the macro `unaligned_references_external_crate::mac` (in Nightly builds, run with -Z macro-backtrace for more info)
-
+For more information about this error, try `rustc --explain E0793`.
diff --git a/tests/ui/lint/unused/issue-103320-must-use-ops.rs b/tests/ui/lint/unused/issue-103320-must-use-ops.rs
new file mode 100644
index 000000000..597d312fa
--- /dev/null
+++ b/tests/ui/lint/unused/issue-103320-must-use-ops.rs
@@ -0,0 +1,27 @@
+// check-pass
+
+#![warn(unused_must_use)]
+#![feature(never_type)]
+
+use std::ops::Add;
+use std::ops::Sub;
+use std::ops::Mul;
+use std::ops::Div;
+use std::ops::Rem;
+
+fn main() {
+ let x = 2_u32;
+ (x.add(4), x.sub(4), x.mul(4), x.div(4), x.rem(4));
+
+ x.add(4); //~ WARN unused return value of `add` that must be used
+
+ x.sub(4); //~ WARN unused return value of `sub` that must be used
+
+ x.mul(4); //~ WARN unused return value of `mul` that must be used
+
+ x.div(4); //~ WARN unused return value of `div` that must be used
+
+ x.rem(4); //~ WARN unused return value of `rem` that must be used
+
+ println!("{}", x);
+}
diff --git a/tests/ui/lint/unused/issue-103320-must-use-ops.stderr b/tests/ui/lint/unused/issue-103320-must-use-ops.stderr
new file mode 100644
index 000000000..57439ec6a
--- /dev/null
+++ b/tests/ui/lint/unused/issue-103320-must-use-ops.stderr
@@ -0,0 +1,67 @@
+warning: unused return value of `add` that must be used
+ --> $DIR/issue-103320-must-use-ops.rs:16:5
+ |
+LL | x.add(4);
+ | ^^^^^^^^
+ |
+ = note: this returns the result of the operation, without modifying the original
+note: the lint level is defined here
+ --> $DIR/issue-103320-must-use-ops.rs:3:9
+ |
+LL | #![warn(unused_must_use)]
+ | ^^^^^^^^^^^^^^^
+help: use `let _ = ...` to ignore the resulting value
+ |
+LL | let _ = x.add(4);
+ | +++++++
+
+warning: unused return value of `sub` that must be used
+ --> $DIR/issue-103320-must-use-ops.rs:18:5
+ |
+LL | x.sub(4);
+ | ^^^^^^^^
+ |
+ = note: this returns the result of the operation, without modifying the original
+help: use `let _ = ...` to ignore the resulting value
+ |
+LL | let _ = x.sub(4);
+ | +++++++
+
+warning: unused return value of `mul` that must be used
+ --> $DIR/issue-103320-must-use-ops.rs:20:5
+ |
+LL | x.mul(4);
+ | ^^^^^^^^
+ |
+ = note: this returns the result of the operation, without modifying the original
+help: use `let _ = ...` to ignore the resulting value
+ |
+LL | let _ = x.mul(4);
+ | +++++++
+
+warning: unused return value of `div` that must be used
+ --> $DIR/issue-103320-must-use-ops.rs:22:5
+ |
+LL | x.div(4);
+ | ^^^^^^^^
+ |
+ = note: this returns the result of the operation, without modifying the original
+help: use `let _ = ...` to ignore the resulting value
+ |
+LL | let _ = x.div(4);
+ | +++++++
+
+warning: unused return value of `rem` that must be used
+ --> $DIR/issue-103320-must-use-ops.rs:24:5
+ |
+LL | x.rem(4);
+ | ^^^^^^^^
+ |
+ = note: this returns the result of the operation, without modifying the original
+help: use `let _ = ...` to ignore the resulting value
+ |
+LL | let _ = x.rem(4);
+ | +++++++
+
+warning: 5 warnings emitted
+
diff --git a/tests/ui/lint/unused/issue-96606.rs b/tests/ui/lint/unused/issue-96606.rs
new file mode 100644
index 000000000..4e7c290fa
--- /dev/null
+++ b/tests/ui/lint/unused/issue-96606.rs
@@ -0,0 +1,8 @@
+#[deny(unused)]
+fn main() {
+ let arr = [0; 10];
+ let _ = arr[(0)]; //~ ERROR unnecessary parentheses around index expression
+ let _ = arr[{0}]; //~ ERROR unnecessary braces around index expression
+ let _ = arr[1 + (0)];
+ let _ = arr[{ let x = 0; x }];
+}
diff --git a/tests/ui/lint/unused/issue-96606.stderr b/tests/ui/lint/unused/issue-96606.stderr
new file mode 100644
index 000000000..e36277181
--- /dev/null
+++ b/tests/ui/lint/unused/issue-96606.stderr
@@ -0,0 +1,33 @@
+error: unnecessary parentheses around index expression
+ --> $DIR/issue-96606.rs:4:17
+ |
+LL | let _ = arr[(0)];
+ | ^ ^
+ |
+note: the lint level is defined here
+ --> $DIR/issue-96606.rs:1:8
+ |
+LL | #[deny(unused)]
+ | ^^^^^^
+ = note: `#[deny(unused_parens)]` implied by `#[deny(unused)]`
+help: remove these parentheses
+ |
+LL - let _ = arr[(0)];
+LL + let _ = arr[0];
+ |
+
+error: unnecessary braces around index expression
+ --> $DIR/issue-96606.rs:5:17
+ |
+LL | let _ = arr[{0}];
+ | ^ ^
+ |
+ = note: `#[deny(unused_braces)]` implied by `#[deny(unused)]`
+help: remove these braces
+ |
+LL - let _ = arr[{0}];
+LL + let _ = arr[0];
+ |
+
+error: aborting due to 2 previous errors
+
diff --git a/tests/ui/lint/unused_parens_multibyte_recovery.rs b/tests/ui/lint/unused_parens_multibyte_recovery.rs
index 8fcfae22a..bc03faf3f 100644
--- a/tests/ui/lint/unused_parens_multibyte_recovery.rs
+++ b/tests/ui/lint/unused_parens_multibyte_recovery.rs
@@ -3,7 +3,6 @@
// error-pattern: this file contains an unclosed delimiter
// error-pattern: this file contains an unclosed delimiter
// error-pattern: this file contains an unclosed delimiter
-// error-pattern: format argument must be a string literal
//
// Verify that unused parens lint does not try to create a span
// which points in the middle of a multibyte character.
diff --git a/tests/ui/lint/unused_parens_multibyte_recovery.stderr b/tests/ui/lint/unused_parens_multibyte_recovery.stderr
index a0302b17e..adbf27fcc 100644
--- a/tests/ui/lint/unused_parens_multibyte_recovery.stderr
+++ b/tests/ui/lint/unused_parens_multibyte_recovery.stderr
@@ -1,5 +1,5 @@
error: this file contains an unclosed delimiter
- --> $DIR/unused_parens_multibyte_recovery.rs:11:17
+ --> $DIR/unused_parens_multibyte_recovery.rs:10:17
|
LL | fn f(){(print!(á
| -- - ^
@@ -8,36 +8,5 @@ LL | fn f(){(print!(á
| |unclosed delimiter
| unclosed delimiter
-error: this file contains an unclosed delimiter
- --> $DIR/unused_parens_multibyte_recovery.rs:11:17
- |
-LL | fn f(){(print!(á
- | -- - ^
- | || |
- | || unclosed delimiter
- | |unclosed delimiter
- | unclosed delimiter
-
-error: this file contains an unclosed delimiter
- --> $DIR/unused_parens_multibyte_recovery.rs:11:17
- |
-LL | fn f(){(print!(á
- | -- - ^
- | || |
- | || unclosed delimiter
- | |unclosed delimiter
- | unclosed delimiter
-
-error: format argument must be a string literal
- --> $DIR/unused_parens_multibyte_recovery.rs:11:16
- |
-LL | fn f(){(print!(á
- | ^
- |
-help: you might be missing a string literal to format with
- |
-LL | fn f(){(print!("{}", á
- | +++++
-
-error: aborting due to 4 previous errors
+error: aborting due to previous error
diff --git a/tests/ui/issues/issue-50576.rs b/tests/ui/loops/issue-50576.rs
index e0c36b827..e0c36b827 100644
--- a/tests/ui/issues/issue-50576.rs
+++ b/tests/ui/loops/issue-50576.rs
diff --git a/tests/ui/issues/issue-50576.stderr b/tests/ui/loops/issue-50576.stderr
index 4ec22fde9..4ec22fde9 100644
--- a/tests/ui/issues/issue-50576.stderr
+++ b/tests/ui/loops/issue-50576.stderr
diff --git a/tests/ui/loops/loop-break-value.stderr b/tests/ui/loops/loop-break-value.stderr
index ccb27c350..5525dbb90 100644
--- a/tests/ui/loops/loop-break-value.stderr
+++ b/tests/ui/loops/loop-break-value.stderr
@@ -167,7 +167,7 @@ error[E0308]: mismatched types
--> $DIR/loop-break-value.rs:80:15
|
LL | break (break, break);
- | ^^^^^^^^^^^^^^ expected `()`, found tuple
+ | ^^^^^^^^^^^^^^ expected `()`, found `(!, !)`
|
= note: expected unit type `()`
found tuple `(!, !)`
diff --git a/tests/ui/loops/loop-else-break-with-value.rs b/tests/ui/loops/loop-else-break-with-value.rs
new file mode 100644
index 000000000..670d8a145
--- /dev/null
+++ b/tests/ui/loops/loop-else-break-with-value.rs
@@ -0,0 +1,10 @@
+fn main() {
+ let Some(1) = loop {
+ //~^ NOTE `else` is attached to this loop
+ break Some(1)
+ } else {
+ //~^ ERROR `loop...else` loops are not supported
+ //~| NOTE consider moving this `else` clause to a separate `if` statement and use a `bool` variable to control if it should run
+ return;
+ };
+}
diff --git a/tests/ui/loops/loop-else-break-with-value.stderr b/tests/ui/loops/loop-else-break-with-value.stderr
new file mode 100644
index 000000000..972e2d341
--- /dev/null
+++ b/tests/ui/loops/loop-else-break-with-value.stderr
@@ -0,0 +1,18 @@
+error: `loop...else` loops are not supported
+ --> $DIR/loop-else-break-with-value.rs:5:7
+ |
+LL | let Some(1) = loop {
+ | ---- `else` is attached to this loop
+...
+LL | } else {
+ | _______^
+LL | |
+LL | |
+LL | | return;
+LL | | };
+ | |_____^
+ |
+ = note: consider moving this `else` clause to a separate `if` statement and use a `bool` variable to control if it should run
+
+error: aborting due to previous error
+
diff --git a/tests/ui/loops/loop-else-err.rs b/tests/ui/loops/loop-else-err.rs
new file mode 100644
index 000000000..202a09c25
--- /dev/null
+++ b/tests/ui/loops/loop-else-err.rs
@@ -0,0 +1,8 @@
+fn main() {
+ loop {
+ //~^ NOTE `else` is attached to this loop
+ } else {
+ //~^ ERROR `loop...else` loops are not supported
+ //~| NOTE consider moving this `else` clause to a separate `if` statement and use a `bool` variable to control if it should run
+ }
+}
diff --git a/tests/ui/loops/loop-else-err.stderr b/tests/ui/loops/loop-else-err.stderr
new file mode 100644
index 000000000..c2c5c84cd
--- /dev/null
+++ b/tests/ui/loops/loop-else-err.stderr
@@ -0,0 +1,17 @@
+error: `loop...else` loops are not supported
+ --> $DIR/loop-else-err.rs:4:7
+ |
+LL | loop {
+ | ---- `else` is attached to this loop
+LL |
+LL | } else {
+ | _______^
+LL | |
+LL | |
+LL | | }
+ | |_____^
+ |
+ = note: consider moving this `else` clause to a separate `if` statement and use a `bool` variable to control if it should run
+
+error: aborting due to previous error
+
diff --git a/tests/ui/loops/loop-else-let-else-err.rs b/tests/ui/loops/loop-else-let-else-err.rs
new file mode 100644
index 000000000..e828ffef5
--- /dev/null
+++ b/tests/ui/loops/loop-else-let-else-err.rs
@@ -0,0 +1,8 @@
+fn main() {
+ let _ = loop {
+ //~^ NOTE `else` is attached to this loop
+ } else {
+ //~^ ERROR `loop...else` loops are not supported
+ //~| NOTE consider moving this `else` clause to a separate `if` statement and use a `bool` variable to control if it should run
+ };
+}
diff --git a/tests/ui/loops/loop-else-let-else-err.stderr b/tests/ui/loops/loop-else-let-else-err.stderr
new file mode 100644
index 000000000..a57c784ff
--- /dev/null
+++ b/tests/ui/loops/loop-else-let-else-err.stderr
@@ -0,0 +1,17 @@
+error: `loop...else` loops are not supported
+ --> $DIR/loop-else-let-else-err.rs:4:7
+ |
+LL | let _ = loop {
+ | ---- `else` is attached to this loop
+LL |
+LL | } else {
+ | _______^
+LL | |
+LL | |
+LL | | };
+ | |_____^
+ |
+ = note: consider moving this `else` clause to a separate `if` statement and use a `bool` variable to control if it should run
+
+error: aborting due to previous error
+
diff --git a/tests/ui/macros/format-args-temporaries-in-write.stderr b/tests/ui/macros/format-args-temporaries-in-write.stderr
index 287cd7d67..520b2ce50 100644
--- a/tests/ui/macros/format-args-temporaries-in-write.stderr
+++ b/tests/ui/macros/format-args-temporaries-in-write.stderr
@@ -1,6 +1,8 @@
error[E0597]: `mutex` does not live long enough
--> $DIR/format-args-temporaries-in-write.rs:41:27
|
+LL | let mutex = Mutex;
+ | ----- binding `mutex` declared here
LL | write!(Out, "{}", mutex.lock()) /* no semicolon */
| ^^^^^^^^^^^^
| |
@@ -16,6 +18,8 @@ LL | };
error[E0597]: `mutex` does not live long enough
--> $DIR/format-args-temporaries-in-write.rs:47:29
|
+LL | let mutex = Mutex;
+ | ----- binding `mutex` declared here
LL | writeln!(Out, "{}", mutex.lock()) /* no semicolon */
| ^^^^^^^^^^^^
| |
diff --git a/tests/ui/macros/issue-102878.rs b/tests/ui/macros/issue-102878.rs
index aac589193..bdd9c2569 100644
--- a/tests/ui/macros/issue-102878.rs
+++ b/tests/ui/macros/issue-102878.rs
@@ -1,9 +1,5 @@
macro_rules!test{($l:expr,$_:r)=>({const:y y)}
//~^ ERROR mismatched closing delimiter: `)`
-//~| ERROR invalid fragment specifier `r`
-//~| ERROR expected identifier, found keyword `const`
-//~| ERROR expected identifier, found keyword `const`
-//~| ERROR expected identifier, found `:`
fn s(){test!(1,i)}
diff --git a/tests/ui/macros/issue-102878.stderr b/tests/ui/macros/issue-102878.stderr
index e0b8855a3..034e3731b 100644
--- a/tests/ui/macros/issue-102878.stderr
+++ b/tests/ui/macros/issue-102878.stderr
@@ -7,54 +7,5 @@ LL | macro_rules!test{($l:expr,$_:r)=>({const:y y)}
| |unclosed delimiter
| closing delimiter possibly meant for this
-error: invalid fragment specifier `r`
- --> $DIR/issue-102878.rs:1:27
- |
-LL | macro_rules!test{($l:expr,$_:r)=>({const:y y)}
- | ^^^^
- |
- = help: valid fragment specifiers are `ident`, `block`, `stmt`, `expr`, `pat`, `ty`, `lifetime`, `literal`, `path`, `meta`, `tt`, `item` and `vis`
-
-error: expected identifier, found keyword `const`
- --> $DIR/issue-102878.rs:1:36
- |
-LL | macro_rules!test{($l:expr,$_:r)=>({const:y y)}
- | ^^^^^ expected identifier, found keyword
-...
-LL | fn s(){test!(1,i)}
- | ---------- in this macro invocation
- |
- = note: this error originates in the macro `test` (in Nightly builds, run with -Z macro-backtrace for more info)
-help: escape `const` to use it as an identifier
- |
-LL | macro_rules!test{($l:expr,$_:r)=>({r#const:y y)}
- | ++
-
-error: expected identifier, found keyword `const`
- --> $DIR/issue-102878.rs:1:36
- |
-LL | macro_rules!test{($l:expr,$_:r)=>({const:y y)}
- | ^^^^^ expected identifier, found keyword
-...
-LL | fn s(){test!(1,i)}
- | ---------- in this macro invocation
- |
- = note: this error originates in the macro `test` (in Nightly builds, run with -Z macro-backtrace for more info)
-help: escape `const` to use it as an identifier
- |
-LL | macro_rules!test{($l:expr,$_:r)=>({r#const:y y)}
- | ++
-
-error: expected identifier, found `:`
- --> $DIR/issue-102878.rs:1:41
- |
-LL | macro_rules!test{($l:expr,$_:r)=>({const:y y)}
- | ^ expected identifier
-...
-LL | fn s(){test!(1,i)}
- | ---------- in this macro invocation
- |
- = note: this error originates in the macro `test` (in Nightly builds, run with -Z macro-backtrace for more info)
-
-error: aborting due to 5 previous errors
+error: aborting due to previous error
diff --git a/tests/ui/macros/macros-nonfatal-errors.stderr b/tests/ui/macros/macros-nonfatal-errors.stderr
index d42f6c179..93fbc9c8a 100644
--- a/tests/ui/macros/macros-nonfatal-errors.stderr
+++ b/tests/ui/macros/macros-nonfatal-errors.stderr
@@ -150,18 +150,19 @@ error: expected string literal
LL | env!(invalid);
| ^^^^^^^
-error: expected string literal
- --> $DIR/macros-nonfatal-errors.rs:105:10
+error: env! takes 1 or 2 arguments
+ --> $DIR/macros-nonfatal-errors.rs:105:5
|
LL | env!(foo, abr, baz);
- | ^^^
+ | ^^^^^^^^^^^^^^^^^^^
-error: environment variable `RUST_HOPEFULLY_THIS_DOESNT_EXIST` not defined
+error: environment variable `RUST_HOPEFULLY_THIS_DOESNT_EXIST` not defined at compile time
--> $DIR/macros-nonfatal-errors.rs:106:5
|
LL | env!("RUST_HOPEFULLY_THIS_DOESNT_EXIST");
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
+ = help: Use `std::env::var("RUST_HOPEFULLY_THIS_DOESNT_EXIST")` to read the variable at run time
= note: this error originates in the macro `env` (in Nightly builds, run with -Z macro-backtrace for more info)
error: format argument must be a string literal
diff --git a/tests/ui/macros/rfc-2011-nicer-assert-messages/non-consuming-methods-have-optimized-codegen.stdout b/tests/ui/macros/rfc-2011-nicer-assert-messages/non-consuming-methods-have-optimized-codegen.stdout
index 90f858f80..ad97f7a4a 100644
--- a/tests/ui/macros/rfc-2011-nicer-assert-messages/non-consuming-methods-have-optimized-codegen.stdout
+++ b/tests/ui/macros/rfc-2011-nicer-assert-messages/non-consuming-methods-have-optimized-codegen.stdout
@@ -25,8 +25,8 @@ fn arbitrary_consuming_method_for_demonstration_purposes() {
{
- ::std::rt::panic_fmt(::core::fmt::Arguments::new_v1(&["Assertion failed: elem as usize\nWith captures:\n elem = ",
- "\n"], &[::core::fmt::ArgumentV1::new_debug(&__capture0)]))
+ ::std::rt::panic_fmt(format_args!("Assertion failed: elem as usize\nWith captures:\n elem = {0:?}\n",
+ __capture0))
}
}
};
@@ -41,8 +41,8 @@ fn addr_of() {
if ::core::intrinsics::unlikely(!&*__local_bind0) {
(&::core::asserting::Wrapper(__local_bind0)).try_capture(&mut __capture0);
{
- ::std::rt::panic_fmt(::core::fmt::Arguments::new_v1(&["Assertion failed: &elem\nWith captures:\n elem = ",
- "\n"], &[::core::fmt::ArgumentV1::new_debug(&__capture0)]))
+ ::std::rt::panic_fmt(format_args!("Assertion failed: &elem\nWith captures:\n elem = {0:?}\n",
+ __capture0))
}
}
};
@@ -57,8 +57,8 @@ fn binary() {
if ::core::intrinsics::unlikely(!(*__local_bind0 == 1)) {
(&::core::asserting::Wrapper(__local_bind0)).try_capture(&mut __capture0);
{
- ::std::rt::panic_fmt(::core::fmt::Arguments::new_v1(&["Assertion failed: elem == 1\nWith captures:\n elem = ",
- "\n"], &[::core::fmt::ArgumentV1::new_debug(&__capture0)]))
+ ::std::rt::panic_fmt(format_args!("Assertion failed: elem == 1\nWith captures:\n elem = {0:?}\n",
+ __capture0))
}
}
};
@@ -70,8 +70,8 @@ fn binary() {
if ::core::intrinsics::unlikely(!(*__local_bind0 >= 1)) {
(&::core::asserting::Wrapper(__local_bind0)).try_capture(&mut __capture0);
{
- ::std::rt::panic_fmt(::core::fmt::Arguments::new_v1(&["Assertion failed: elem >= 1\nWith captures:\n elem = ",
- "\n"], &[::core::fmt::ArgumentV1::new_debug(&__capture0)]))
+ ::std::rt::panic_fmt(format_args!("Assertion failed: elem >= 1\nWith captures:\n elem = {0:?}\n",
+ __capture0))
}
}
};
@@ -83,8 +83,8 @@ fn binary() {
if ::core::intrinsics::unlikely(!(*__local_bind0 > 0)) {
(&::core::asserting::Wrapper(__local_bind0)).try_capture(&mut __capture0);
{
- ::std::rt::panic_fmt(::core::fmt::Arguments::new_v1(&["Assertion failed: elem > 0\nWith captures:\n elem = ",
- "\n"], &[::core::fmt::ArgumentV1::new_debug(&__capture0)]))
+ ::std::rt::panic_fmt(format_args!("Assertion failed: elem > 0\nWith captures:\n elem = {0:?}\n",
+ __capture0))
}
}
};
@@ -96,8 +96,8 @@ fn binary() {
if ::core::intrinsics::unlikely(!(*__local_bind0 < 3)) {
(&::core::asserting::Wrapper(__local_bind0)).try_capture(&mut __capture0);
{
- ::std::rt::panic_fmt(::core::fmt::Arguments::new_v1(&["Assertion failed: elem < 3\nWith captures:\n elem = ",
- "\n"], &[::core::fmt::ArgumentV1::new_debug(&__capture0)]))
+ ::std::rt::panic_fmt(format_args!("Assertion failed: elem < 3\nWith captures:\n elem = {0:?}\n",
+ __capture0))
}
}
};
@@ -109,8 +109,8 @@ fn binary() {
if ::core::intrinsics::unlikely(!(*__local_bind0 <= 3)) {
(&::core::asserting::Wrapper(__local_bind0)).try_capture(&mut __capture0);
{
- ::std::rt::panic_fmt(::core::fmt::Arguments::new_v1(&["Assertion failed: elem <= 3\nWith captures:\n elem = ",
- "\n"], &[::core::fmt::ArgumentV1::new_debug(&__capture0)]))
+ ::std::rt::panic_fmt(format_args!("Assertion failed: elem <= 3\nWith captures:\n elem = {0:?}\n",
+ __capture0))
}
}
};
@@ -122,8 +122,8 @@ fn binary() {
if ::core::intrinsics::unlikely(!(*__local_bind0 != 3)) {
(&::core::asserting::Wrapper(__local_bind0)).try_capture(&mut __capture0);
{
- ::std::rt::panic_fmt(::core::fmt::Arguments::new_v1(&["Assertion failed: elem != 3\nWith captures:\n elem = ",
- "\n"], &[::core::fmt::ArgumentV1::new_debug(&__capture0)]))
+ ::std::rt::panic_fmt(format_args!("Assertion failed: elem != 3\nWith captures:\n elem = {0:?}\n",
+ __capture0))
}
}
};
@@ -138,8 +138,8 @@ fn unary() {
if ::core::intrinsics::unlikely(!**__local_bind0) {
(&::core::asserting::Wrapper(__local_bind0)).try_capture(&mut __capture0);
{
- ::std::rt::panic_fmt(::core::fmt::Arguments::new_v1(&["Assertion failed: *elem\nWith captures:\n elem = ",
- "\n"], &[::core::fmt::ArgumentV1::new_debug(&__capture0)]))
+ ::std::rt::panic_fmt(format_args!("Assertion failed: *elem\nWith captures:\n elem = {0:?}\n",
+ __capture0))
}
}
};
diff --git a/tests/ui/macros/stringify.rs b/tests/ui/macros/stringify.rs
index 5cd217df6..fdc2a7666 100644
--- a/tests/ui/macros/stringify.rs
+++ b/tests/ui/macros/stringify.rs
@@ -626,7 +626,7 @@ fn test_item() {
stringify_item!(
impl ~const Struct {}
),
- "impl Struct {}", // FIXME
+ "impl ~const Struct {}",
);
// ItemKind::MacCall
@@ -838,7 +838,7 @@ fn test_ty() {
assert_eq!(stringify_ty!(dyn Send + 'a), "dyn Send + 'a");
assert_eq!(stringify_ty!(dyn 'a + Send), "dyn 'a + Send");
assert_eq!(stringify_ty!(dyn ?Sized), "dyn ?Sized");
- assert_eq!(stringify_ty!(dyn ~const Clone), "dyn Clone"); // FIXME
+ assert_eq!(stringify_ty!(dyn ~const Clone), "dyn ~const Clone");
assert_eq!(stringify_ty!(dyn for<'a> Send), "dyn for<'a> Send");
// TyKind::ImplTrait
@@ -846,7 +846,7 @@ fn test_ty() {
assert_eq!(stringify_ty!(impl Send + 'a), "impl Send + 'a");
assert_eq!(stringify_ty!(impl 'a + Send), "impl 'a + Send");
assert_eq!(stringify_ty!(impl ?Sized), "impl ?Sized");
- assert_eq!(stringify_ty!(impl ~const Clone), "impl Clone"); // FIXME
+ assert_eq!(stringify_ty!(impl ~const Clone), "impl ~const Clone");
assert_eq!(stringify_ty!(impl for<'a> Send), "impl for<'a> Send");
// TyKind::Paren
diff --git a/tests/ui/malformed/issue-107423-unused-delim-only-one-no-pair.rs b/tests/ui/malformed/issue-107423-unused-delim-only-one-no-pair.rs
new file mode 100644
index 000000000..4003ee37c
--- /dev/null
+++ b/tests/ui/malformed/issue-107423-unused-delim-only-one-no-pair.rs
@@ -0,0 +1,7 @@
+// check that we don't generate a span that points beyond EOF
+
+// error-pattern: unclosed delimiter
+// error-pattern: unclosed delimiter
+// error-pattern: unclosed delimiter
+
+fn a(){{{
diff --git a/tests/ui/malformed/issue-107423-unused-delim-only-one-no-pair.stderr b/tests/ui/malformed/issue-107423-unused-delim-only-one-no-pair.stderr
new file mode 100644
index 000000000..89e0d982e
--- /dev/null
+++ b/tests/ui/malformed/issue-107423-unused-delim-only-one-no-pair.stderr
@@ -0,0 +1,12 @@
+error: this file contains an unclosed delimiter
+ --> $DIR/issue-107423-unused-delim-only-one-no-pair.rs:7:11
+ |
+LL | fn a(){{{
+ | --- ^
+ | |||
+ | ||unclosed delimiter
+ | |unclosed delimiter
+ | unclosed delimiter
+
+error: aborting due to previous error
+
diff --git a/tests/ui/match/issue-12552.stderr b/tests/ui/match/issue-12552.stderr
index 4b027eba2..195192fbd 100644
--- a/tests/ui/match/issue-12552.stderr
+++ b/tests/ui/match/issue-12552.stderr
@@ -4,7 +4,7 @@ error[E0308]: mismatched types
LL | match t {
| - this expression has type `Result<_, {integer}>`
LL | Some(k) => match k {
- | ^^^^^^^ expected enum `Result`, found enum `Option`
+ | ^^^^^^^ expected `Result<_, {integer}>`, found `Option<_>`
|
= note: expected enum `Result<_, {integer}>`
found enum `Option<_>`
@@ -20,7 +20,7 @@ LL | match t {
| - this expression has type `Result<_, {integer}>`
...
LL | None => ()
- | ^^^^ expected enum `Result`, found enum `Option`
+ | ^^^^ expected `Result<_, {integer}>`, found `Option<_>`
|
= note: expected enum `Result<_, {integer}>`
found enum `Option<_>`
diff --git a/tests/ui/match/issue-74050-end-span.stderr b/tests/ui/match/issue-74050-end-span.stderr
index 59c091e44..0b3425f2b 100644
--- a/tests/ui/match/issue-74050-end-span.stderr
+++ b/tests/ui/match/issue-74050-end-span.stderr
@@ -4,6 +4,7 @@ error[E0597]: `arg` does not live long enough
LL | let _arg = match args.next() {
| ---- borrow later stored here
LL | Some(arg) => {
+ | --- binding `arg` declared here
LL | match arg.to_str() {
| ^^^^^^^^^^^^ borrowed value does not live long enough
...
diff --git a/tests/ui/match/issue-91058.stderr b/tests/ui/match/issue-91058.stderr
index ec1d7e21f..12f37274b 100644
--- a/tests/ui/match/issue-91058.stderr
+++ b/tests/ui/match/issue-91058.stderr
@@ -4,7 +4,7 @@ error[E0308]: mismatched types
LL | match array {
| ----- this expression has type `[S; 1]`
LL | [()] => {}
- | ^^ expected struct `S`, found `()`
+ | ^^ expected `S`, found `()`
error: aborting due to previous error
diff --git a/tests/ui/match/match-ref-mut-invariance.stderr b/tests/ui/match/match-ref-mut-invariance.stderr
index 3b7e53cd5..b353d3514 100644
--- a/tests/ui/match/match-ref-mut-invariance.stderr
+++ b/tests/ui/match/match-ref-mut-invariance.stderr
@@ -6,7 +6,7 @@ LL | impl<'b> S<'b> {
LL | fn bar<'a>(&'a mut self) -> &'a mut &'a i32 {
| -- lifetime `'a` defined here
LL | match self.0 { ref mut x => x }
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ associated function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a`
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ method was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a`
|
= help: consider adding the following bound: `'a: 'b`
= note: requirement occurs because of a mutable reference to `&i32`
diff --git a/tests/ui/match/match-ref-mut-let-invariance.stderr b/tests/ui/match/match-ref-mut-let-invariance.stderr
index f4d1cea67..bb0fcdb99 100644
--- a/tests/ui/match/match-ref-mut-let-invariance.stderr
+++ b/tests/ui/match/match-ref-mut-let-invariance.stderr
@@ -7,7 +7,7 @@ LL | fn bar<'a>(&'a mut self) -> &'a mut &'a i32 {
| -- lifetime `'a` defined here
LL | let ref mut x = self.0;
LL | x
- | ^ associated function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a`
+ | ^ method was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a`
|
= help: consider adding the following bound: `'a: 'b`
= note: requirement occurs because of a mutable reference to `&i32`
diff --git a/tests/ui/match/match-struct.rs b/tests/ui/match/match-struct.rs
index 7a54c54b9..4da7b436b 100644
--- a/tests/ui/match/match-struct.rs
+++ b/tests/ui/match/match-struct.rs
@@ -5,7 +5,7 @@ fn main() {
match (S { a: 1 }) {
E::C(_) => (),
//~^ ERROR mismatched types
- //~| expected struct `S`, found enum `E`
+ //~| expected `S`, found `E`
_ => ()
}
}
diff --git a/tests/ui/match/match-struct.stderr b/tests/ui/match/match-struct.stderr
index a475bd5e5..fdc6fd770 100644
--- a/tests/ui/match/match-struct.stderr
+++ b/tests/ui/match/match-struct.stderr
@@ -4,7 +4,7 @@ error[E0308]: mismatched types
LL | match (S { a: 1 }) {
| ------------ this expression has type `S`
LL | E::C(_) => (),
- | ^^^^^^^ expected struct `S`, found enum `E`
+ | ^^^^^^^ expected `S`, found `E`
error: aborting due to previous error
diff --git a/tests/ui/match/match-tag-nullary.stderr b/tests/ui/match/match-tag-nullary.stderr
index a6add31d1..aac873c76 100644
--- a/tests/ui/match/match-tag-nullary.stderr
+++ b/tests/ui/match/match-tag-nullary.stderr
@@ -5,7 +5,7 @@ LL | enum B { B }
| - unit variant defined here
LL |
LL | fn main() { let x: A = A::A; match x { B::B => { } } }
- | - ^^^^ expected enum `A`, found enum `B`
+ | - ^^^^ expected `A`, found `B`
| |
| this expression has type `A`
diff --git a/tests/ui/match/match-tag-unary.stderr b/tests/ui/match/match-tag-unary.stderr
index 31f77bdff..25e8152d8 100644
--- a/tests/ui/match/match-tag-unary.stderr
+++ b/tests/ui/match/match-tag-unary.stderr
@@ -2,7 +2,7 @@ error[E0308]: mismatched types
--> $DIR/match-tag-unary.rs:4:43
|
LL | fn main() { let x: A = A::A(0); match x { B::B(y) => { } } }
- | - ^^^^^^^ expected enum `A`, found enum `B`
+ | - ^^^^^^^ expected `A`, found `B`
| |
| this expression has type `A`
diff --git a/tests/ui/methods/assign-to-method.rs b/tests/ui/methods/assign-to-method.rs
index 85beaee8d..71e40759c 100644
--- a/tests/ui/methods/assign-to-method.rs
+++ b/tests/ui/methods/assign-to-method.rs
@@ -1,5 +1,4 @@
-// compile-flags: -Zsave-analysis
-// Also regression test for #69409
+// Regression test for #69409
struct Cat {
meows : usize,
diff --git a/tests/ui/methods/assign-to-method.stderr b/tests/ui/methods/assign-to-method.stderr
index cafe9abae..a1fc57cae 100644
--- a/tests/ui/methods/assign-to-method.stderr
+++ b/tests/ui/methods/assign-to-method.stderr
@@ -1,5 +1,5 @@
error[E0615]: attempted to take value of method `speak` on type `Cat`
- --> $DIR/assign-to-method.rs:22:10
+ --> $DIR/assign-to-method.rs:21:10
|
LL | nyan.speak = || println!("meow");
| ^^^^^ method, not a field
@@ -7,7 +7,7 @@ LL | nyan.speak = || println!("meow");
= help: methods are immutable and cannot be assigned to
error[E0615]: attempted to take value of method `speak` on type `Cat`
- --> $DIR/assign-to-method.rs:23:10
+ --> $DIR/assign-to-method.rs:22:10
|
LL | nyan.speak += || println!("meow");
| ^^^^^ method, not a field
diff --git a/tests/ui/methods/issues/issue-105732.stderr b/tests/ui/methods/issues/issue-105732.stderr
index 769664254..19ccd2de6 100644
--- a/tests/ui/methods/issues/issue-105732.stderr
+++ b/tests/ui/methods/issues/issue-105732.stderr
@@ -2,7 +2,7 @@ error[E0380]: auto traits cannot have associated items
--> $DIR/issue-105732.rs:4:8
|
LL | auto trait Foo {
- | --- auto trait cannot have associated items
+ | --- auto traits cannot have associated items
LL | fn g(&self);
| ---^-------- help: remove these associated items
diff --git a/tests/ui/methods/issues/issue-61525.stderr b/tests/ui/methods/issues/issue-61525.stderr
index 3e73b950a..a8afdeb84 100644
--- a/tests/ui/methods/issues/issue-61525.stderr
+++ b/tests/ui/methods/issues/issue-61525.stderr
@@ -21,13 +21,13 @@ error[E0308]: mismatched types
--> $DIR/issue-61525.rs:14:33
|
LL | 1.query::<dyn ToString>("")
- | --------------------- ^^ expected trait object `dyn ToString`, found `&str`
+ | --------------------- ^^ expected `dyn ToString`, found `&str`
| |
| arguments to this method are incorrect
|
= note: expected trait object `dyn ToString`
found reference `&'static str`
-note: associated function defined here
+note: method defined here
--> $DIR/issue-61525.rs:2:8
|
LL | fn query<Q>(self, q: Q);
diff --git a/tests/ui/methods/issues/issue-90315.stderr b/tests/ui/methods/issues/issue-90315.stderr
index 4d3c086ff..0466bb0a0 100644
--- a/tests/ui/methods/issues/issue-90315.stderr
+++ b/tests/ui/methods/issues/issue-90315.stderr
@@ -57,7 +57,7 @@ error[E0308]: mismatched types
--> $DIR/issue-90315.rs:28:8
|
LL | if 1..(end + 1).is_empty() {
- | ^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found struct `Range`
+ | ^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found `Range<{integer}>`
|
= note: expected type `bool`
found struct `std::ops::Range<{integer}>`
@@ -77,7 +77,7 @@ error[E0308]: mismatched types
--> $DIR/issue-90315.rs:34:8
|
LL | if 1..(end + 1).is_sorted() {
- | ^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found struct `Range`
+ | ^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found `Range<{integer}>`
|
= note: expected type `bool`
found struct `std::ops::Range<{integer}>`
@@ -97,7 +97,7 @@ error[E0308]: mismatched types
--> $DIR/issue-90315.rs:40:21
|
LL | let _res: i32 = 3..6.take(2).sum();
- | --- ^^^^^^^^^^^^^^^^^^ expected `i32`, found struct `Range`
+ | --- ^^^^^^^^^^^^^^^^^^ expected `i32`, found `Range<{integer}>`
| |
| expected due to this
|
@@ -119,7 +119,7 @@ error[E0308]: mismatched types
--> $DIR/issue-90315.rs:45:21
|
LL | let _sum: i32 = 3..6.sum();
- | --- ^^^^^^^^^^ expected `i32`, found struct `Range`
+ | --- ^^^^^^^^^^ expected `i32`, found `Range<{integer}>`
| |
| expected due to this
|
@@ -158,7 +158,7 @@ error[E0308]: mismatched types
--> $DIR/issue-90315.rs:62:8
|
LL | if 1..end.error_method() {
- | ^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found struct `Range`
+ | ^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found `Range<{integer}>`
|
= note: expected type `bool`
found struct `std::ops::Range<{integer}>`
diff --git a/tests/ui/methods/method-ambig-two-traits-cross-crate.stderr b/tests/ui/methods/method-ambig-two-traits-cross-crate.stderr
index 4b2597eed..5132d9277 100644
--- a/tests/ui/methods/method-ambig-two-traits-cross-crate.stderr
+++ b/tests/ui/methods/method-ambig-two-traits-cross-crate.stderr
@@ -10,11 +10,11 @@ note: candidate #2 is defined in an impl of the trait `Me2` for the type `usize`
|
LL | impl Me2 for usize { fn me(&self) -> usize { *self } }
| ^^^^^^^^^^^^^^^^^^^^^
-help: disambiguate the associated function for candidate #1
+help: disambiguate the method for candidate #1
|
LL | fn main() { Me::me(&1_usize); }
| ~~~~~~~~~~~~~~~~
-help: disambiguate the associated function for candidate #2
+help: disambiguate the method for candidate #2
|
LL | fn main() { Me2::me(&1_usize); }
| ~~~~~~~~~~~~~~~~~
diff --git a/tests/ui/methods/method-ambig-two-traits-from-bounds.stderr b/tests/ui/methods/method-ambig-two-traits-from-bounds.stderr
index 1feaa2c73..601e6bbb0 100644
--- a/tests/ui/methods/method-ambig-two-traits-from-bounds.stderr
+++ b/tests/ui/methods/method-ambig-two-traits-from-bounds.stderr
@@ -14,11 +14,11 @@ note: candidate #2 is defined in the trait `B`
|
LL | trait B { fn foo(&self); }
| ^^^^^^^^^^^^^^
-help: disambiguate the associated function for candidate #1
+help: disambiguate the method for candidate #1
|
LL | A::foo(t);
| ~~~~~~~~~
-help: disambiguate the associated function for candidate #2
+help: disambiguate the method for candidate #2
|
LL | B::foo(t);
| ~~~~~~~~~
diff --git a/tests/ui/methods/method-ambig-two-traits-from-impls.stderr b/tests/ui/methods/method-ambig-two-traits-from-impls.stderr
index f69b56892..313591433 100644
--- a/tests/ui/methods/method-ambig-two-traits-from-impls.stderr
+++ b/tests/ui/methods/method-ambig-two-traits-from-impls.stderr
@@ -14,11 +14,11 @@ note: candidate #2 is defined in an impl of the trait `B` for the type `AB`
|
LL | fn foo(self) {}
| ^^^^^^^^^^^^
-help: disambiguate the associated function for candidate #1
+help: disambiguate the method for candidate #1
|
LL | A::foo(AB {});
| ~~~~~~~~~~~~~
-help: disambiguate the associated function for candidate #2
+help: disambiguate the method for candidate #2
|
LL | B::foo(AB {});
| ~~~~~~~~~~~~~
diff --git a/tests/ui/methods/method-ambig-two-traits-with-default-method.stderr b/tests/ui/methods/method-ambig-two-traits-with-default-method.stderr
index e84dff8ba..df01966b3 100644
--- a/tests/ui/methods/method-ambig-two-traits-with-default-method.stderr
+++ b/tests/ui/methods/method-ambig-two-traits-with-default-method.stderr
@@ -14,11 +14,11 @@ note: candidate #2 is defined in an impl of the trait `Bar` for the type `usize`
|
LL | trait Bar { fn method(&self) {} }
| ^^^^^^^^^^^^^^^^
-help: disambiguate the associated function for candidate #1
+help: disambiguate the method for candidate #1
|
LL | Foo::method(&1_usize);
| ~~~~~~~~~~~~~~~~~~~~~
-help: disambiguate the associated function for candidate #2
+help: disambiguate the method for candidate #2
|
LL | Bar::method(&1_usize);
| ~~~~~~~~~~~~~~~~~~~~~
diff --git a/tests/ui/methods/method-call-err-msg.stderr b/tests/ui/methods/method-call-err-msg.stderr
index 81269b73b..bd51378cf 100644
--- a/tests/ui/methods/method-call-err-msg.stderr
+++ b/tests/ui/methods/method-call-err-msg.stderr
@@ -2,17 +2,16 @@ error[E0061]: this method takes 0 arguments but 1 argument was supplied
--> $DIR/method-call-err-msg.rs:13:7
|
LL | x.zero(0)
- | ^^^^ - argument of type `{integer}` unexpected
+ | ^^^^ -
+ | |
+ | unexpected argument of type `{integer}`
+ | help: remove the extra argument
|
-note: associated function defined here
+note: method defined here
--> $DIR/method-call-err-msg.rs:5:8
|
LL | fn zero(self) -> Foo { self }
| ^^^^
-help: remove the extra argument
- |
-LL | x.zero()
- | ~~
error[E0061]: this method takes 1 argument but 0 arguments were supplied
--> $DIR/method-call-err-msg.rs:14:7
@@ -20,7 +19,7 @@ error[E0061]: this method takes 1 argument but 0 arguments were supplied
LL | .one()
| ^^^-- an argument of type `isize` is missing
|
-note: associated function defined here
+note: method defined here
--> $DIR/method-call-err-msg.rs:6:8
|
LL | fn one(self, _: isize) -> Foo { self }
@@ -36,7 +35,7 @@ error[E0061]: this method takes 2 arguments but 1 argument was supplied
LL | .two(0);
| ^^^--- an argument of type `isize` is missing
|
-note: associated function defined here
+note: method defined here
--> $DIR/method-call-err-msg.rs:7:8
|
LL | fn two(self, _: isize, _: isize) -> Foo { self }
@@ -49,14 +48,17 @@ LL | .two(0, /* isize */);
error[E0599]: `Foo` is not an iterator
--> $DIR/method-call-err-msg.rs:19:7
|
-LL | pub struct Foo;
- | --------------
- | |
- | method `take` not found for this struct
- | doesn't satisfy `Foo: Iterator`
+LL | pub struct Foo;
+ | --------------
+ | |
+ | method `take` not found for this struct
+ | doesn't satisfy `Foo: Iterator`
...
-LL | .take()
- | ^^^^ `Foo` is not an iterator
+LL | / y.zero()
+LL | | .take()
+ | | -^^^^ `Foo` is not an iterator
+ | |______|
+ |
|
= note: the following trait bounds were not satisfied:
`Foo: Iterator`
@@ -73,7 +75,7 @@ error[E0061]: this method takes 3 arguments but 0 arguments were supplied
LL | y.three::<usize>();
| ^^^^^^^^^^^^^^-- three arguments of type `usize`, `usize`, and `usize` are missing
|
-note: associated function defined here
+note: method defined here
--> $DIR/method-call-err-msg.rs:8:8
|
LL | fn three<T>(self, _: T, _: T, _: T) -> Foo { self }
diff --git a/tests/ui/methods/method-call-lifetime-args-fail.rs b/tests/ui/methods/method-call-lifetime-args-fail.rs
index 6bf55844d..1f13de094 100644
--- a/tests/ui/methods/method-call-lifetime-args-fail.rs
+++ b/tests/ui/methods/method-call-lifetime-args-fail.rs
@@ -14,9 +14,9 @@ impl S {
fn method_call() {
S.early(); // OK
S.early::<'static>();
- //~^ ERROR this associated function takes 2 lifetime arguments but 1 lifetime argument
+ //~^ ERROR method takes 2 lifetime arguments but 1 lifetime argument
S.early::<'static, 'static, 'static>();
- //~^ ERROR this associated function takes 2 lifetime arguments but 3 lifetime arguments were supplied
+ //~^ ERROR method takes 2 lifetime arguments but 3 lifetime arguments were supplied
let _: &u8 = S.life_and_type::<'static>();
S.life_and_type::<u8>();
S.life_and_type::<'static, u8>();
@@ -61,9 +61,9 @@ fn ufcs() {
S::early(S); // OK
S::early::<'static>(S);
- //~^ ERROR this associated function takes 2 lifetime arguments but 1 lifetime argument
+ //~^ ERROR method takes 2 lifetime arguments but 1 lifetime argument
S::early::<'static, 'static, 'static>(S);
- //~^ ERROR this associated function takes 2 lifetime arguments but 3 lifetime arguments were supplied
+ //~^ ERROR method takes 2 lifetime arguments but 3 lifetime arguments were supplied
let _: &u8 = S::life_and_type::<'static>(S);
S::life_and_type::<u8>(S);
S::life_and_type::<'static, u8>(S);
diff --git a/tests/ui/methods/method-call-lifetime-args-fail.stderr b/tests/ui/methods/method-call-lifetime-args-fail.stderr
index 249b48ab1..34526256f 100644
--- a/tests/ui/methods/method-call-lifetime-args-fail.stderr
+++ b/tests/ui/methods/method-call-lifetime-args-fail.stderr
@@ -1,4 +1,4 @@
-error[E0107]: this associated function takes 2 lifetime arguments but 1 lifetime argument was supplied
+error[E0107]: method takes 2 lifetime arguments but 1 lifetime argument was supplied
--> $DIR/method-call-lifetime-args-fail.rs:16:7
|
LL | S.early::<'static>();
@@ -6,7 +6,7 @@ LL | S.early::<'static>();
| |
| expected 2 lifetime arguments
|
-note: associated function defined here, with 2 lifetime parameters: `'a`, `'b`
+note: method defined here, with 2 lifetime parameters: `'a`, `'b`
--> $DIR/method-call-lifetime-args-fail.rs:6:8
|
LL | fn early<'a, 'b>(self) -> (&'a u8, &'b u8) { loop {} }
@@ -16,7 +16,7 @@ help: add missing lifetime argument
LL | S.early::<'static, 'static>();
| +++++++++
-error[E0107]: this associated function takes 2 lifetime arguments but 3 lifetime arguments were supplied
+error[E0107]: method takes 2 lifetime arguments but 3 lifetime arguments were supplied
--> $DIR/method-call-lifetime-args-fail.rs:18:7
|
LL | S.early::<'static, 'static, 'static>();
@@ -24,7 +24,7 @@ LL | S.early::<'static, 'static, 'static>();
| |
| expected 2 lifetime arguments
|
-note: associated function defined here, with 2 lifetime parameters: `'a`, `'b`
+note: method defined here, with 2 lifetime parameters: `'a`, `'b`
--> $DIR/method-call-lifetime-args-fail.rs:6:8
|
LL | fn early<'a, 'b>(self) -> (&'a u8, &'b u8) { loop {} }
@@ -198,7 +198,7 @@ note: the late bound lifetime parameter is introduced here
LL | fn late_unused_early<'a, 'b>(self) -> &'b u8 { loop {} }
| ^^
-error[E0107]: this associated function takes 2 lifetime arguments but 1 lifetime argument was supplied
+error[E0107]: method takes 2 lifetime arguments but 1 lifetime argument was supplied
--> $DIR/method-call-lifetime-args-fail.rs:63:8
|
LL | S::early::<'static>(S);
@@ -206,7 +206,7 @@ LL | S::early::<'static>(S);
| |
| expected 2 lifetime arguments
|
-note: associated function defined here, with 2 lifetime parameters: `'a`, `'b`
+note: method defined here, with 2 lifetime parameters: `'a`, `'b`
--> $DIR/method-call-lifetime-args-fail.rs:6:8
|
LL | fn early<'a, 'b>(self) -> (&'a u8, &'b u8) { loop {} }
@@ -216,7 +216,7 @@ help: add missing lifetime argument
LL | S::early::<'static, 'static>(S);
| +++++++++
-error[E0107]: this associated function takes 2 lifetime arguments but 3 lifetime arguments were supplied
+error[E0107]: method takes 2 lifetime arguments but 3 lifetime arguments were supplied
--> $DIR/method-call-lifetime-args-fail.rs:65:8
|
LL | S::early::<'static, 'static, 'static>(S);
@@ -224,7 +224,7 @@ LL | S::early::<'static, 'static, 'static>(S);
| |
| expected 2 lifetime arguments
|
-note: associated function defined here, with 2 lifetime parameters: `'a`, `'b`
+note: method defined here, with 2 lifetime parameters: `'a`, `'b`
--> $DIR/method-call-lifetime-args-fail.rs:6:8
|
LL | fn early<'a, 'b>(self) -> (&'a u8, &'b u8) { loop {} }
diff --git a/tests/ui/methods/method-deref-to-same-trait-object-with-separate-params.stderr b/tests/ui/methods/method-deref-to-same-trait-object-with-separate-params.stderr
index 82addab94..4e83e4b77 100644
--- a/tests/ui/methods/method-deref-to-same-trait-object-with-separate-params.stderr
+++ b/tests/ui/methods/method-deref-to-same-trait-object-with-separate-params.stderr
@@ -44,15 +44,15 @@ note: candidate #3 is defined in the trait `FinalFoo`
|
LL | fn foo(&self) -> u8;
| ^^^^^^^^^^^^^^^^^^^^
-help: disambiguate the associated function for candidate #1
+help: disambiguate the method for candidate #1
|
LL | let z = X::foo(x);
| ~~~~~~~~~
-help: disambiguate the associated function for candidate #2
+help: disambiguate the method for candidate #2
|
LL | let z = NuisanceFoo::foo(x);
| ~~~~~~~~~~~~~~~~~~~
-help: disambiguate the associated function for candidate #3
+help: disambiguate the method for candidate #3
|
LL | let z = FinalFoo::foo(x);
| ~~~~~~~~~~~~~~~~
diff --git a/tests/ui/methods/method-not-found-but-doc-alias.rs b/tests/ui/methods/method-not-found-but-doc-alias.rs
new file mode 100644
index 000000000..9c6d10029
--- /dev/null
+++ b/tests/ui/methods/method-not-found-but-doc-alias.rs
@@ -0,0 +1,11 @@
+struct Foo;
+
+impl Foo {
+ #[doc(alias = "quux")]
+ fn bar(&self) {}
+}
+
+fn main() {
+ Foo.quux();
+ //~^ ERROR no method named `quux` found for struct `Foo` in the current scope
+}
diff --git a/tests/ui/methods/method-not-found-but-doc-alias.stderr b/tests/ui/methods/method-not-found-but-doc-alias.stderr
new file mode 100644
index 000000000..5102a452f
--- /dev/null
+++ b/tests/ui/methods/method-not-found-but-doc-alias.stderr
@@ -0,0 +1,12 @@
+error[E0599]: no method named `quux` found for struct `Foo` in the current scope
+ --> $DIR/method-not-found-but-doc-alias.rs:9:9
+ |
+LL | struct Foo;
+ | ---------- method `quux` not found for this struct
+...
+LL | Foo.quux();
+ | ^^^^ help: there is a method with a similar name: `bar`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0599`.
diff --git a/tests/ui/methods/method-self-arg-1.rs b/tests/ui/methods/method-self-arg-1.rs
index f589f20d8..5912b4ec2 100644
--- a/tests/ui/methods/method-self-arg-1.rs
+++ b/tests/ui/methods/method-self-arg-1.rs
@@ -9,9 +9,9 @@ impl Foo {
fn main() {
let x = Foo;
Foo::bar(x); //~ ERROR mismatched types
- //~| expected `&Foo`, found struct `Foo`
+ //~| expected `&Foo`, found `Foo`
Foo::bar(&42); //~ ERROR mismatched types
- //~| expected struct `Foo`, found integer
+ //~| expected `&Foo`, found `&{integer}`
//~| expected reference `&Foo`
//~| found reference `&{integer}`
}
diff --git a/tests/ui/methods/method-self-arg-1.stderr b/tests/ui/methods/method-self-arg-1.stderr
index 01fec6fca..9241a8be5 100644
--- a/tests/ui/methods/method-self-arg-1.stderr
+++ b/tests/ui/methods/method-self-arg-1.stderr
@@ -4,11 +4,11 @@ error[E0308]: mismatched types
LL | Foo::bar(x);
| -------- ^
| | |
- | | expected `&Foo`, found struct `Foo`
+ | | expected `&Foo`, found `Foo`
| | help: consider borrowing here: `&x`
| arguments to this function are incorrect
|
-note: associated function defined here
+note: method defined here
--> $DIR/method-self-arg-1.rs:6:8
|
LL | fn bar(&self) {}
@@ -18,13 +18,13 @@ error[E0308]: mismatched types
--> $DIR/method-self-arg-1.rs:13:14
|
LL | Foo::bar(&42);
- | -------- ^^^ expected struct `Foo`, found integer
+ | -------- ^^^ expected `&Foo`, found `&{integer}`
| |
| arguments to this function are incorrect
|
= note: expected reference `&Foo`
found reference `&{integer}`
-note: associated function defined here
+note: method defined here
--> $DIR/method-self-arg-1.rs:6:8
|
LL | fn bar(&self) {}
diff --git a/tests/ui/mir/field-projection-invariant.rs b/tests/ui/mir/field-projection-invariant.rs
new file mode 100644
index 000000000..b5d6add04
--- /dev/null
+++ b/tests/ui/mir/field-projection-invariant.rs
@@ -0,0 +1,24 @@
+// build-pass
+struct Inv<'a>(&'a mut &'a ());
+enum Foo<T> {
+ Bar,
+ Var(T),
+}
+type Supertype = Foo<for<'a> fn(Inv<'a>, Inv<'a>)>;
+
+fn foo(x: Foo<for<'a, 'b> fn(Inv<'a>, Inv<'b>)>) {
+ match x {
+ Supertype::Bar => {}
+ Supertype::Var(x) => {}
+ }
+}
+
+fn foo_nested(x: Foo<Foo<for<'a, 'b> fn(Inv<'a>, Inv<'b>)>>) {
+ match x {
+ Foo::Bar => {}
+ Foo::Var(Supertype::Bar) => {}
+ Foo::Var(Supertype::Var(x)) => {}
+ }
+}
+
+fn main() {}
diff --git a/tests/ui/mir/field-projection-mutating-context.rs b/tests/ui/mir/field-projection-mutating-context.rs
new file mode 100644
index 000000000..a1002c088
--- /dev/null
+++ b/tests/ui/mir/field-projection-mutating-context.rs
@@ -0,0 +1,19 @@
+use std::sync::Mutex;
+
+static GLOBAL: Mutex<&'static str> = Mutex::new("global str");
+
+struct Foo<T>(T); // `T` is covariant.
+
+fn foo() {
+ let mut x: Foo<for<'a> fn(&'a str)> = Foo(|_| ());
+ let Foo(ref mut y): Foo<fn(&'static str)> = x;
+ //~^ ERROR mismatched types
+ *y = |s| *GLOBAL.lock().unwrap() = s;
+ let string = String::from("i am shortlived");
+ (x.0)(&string);
+}
+
+fn main() {
+ foo();
+ println!("{}", GLOBAL.lock().unwrap());
+}
diff --git a/tests/ui/mir/field-projection-mutating-context.stderr b/tests/ui/mir/field-projection-mutating-context.stderr
new file mode 100644
index 000000000..9b18b3427
--- /dev/null
+++ b/tests/ui/mir/field-projection-mutating-context.stderr
@@ -0,0 +1,12 @@
+error[E0308]: mismatched types
+ --> $DIR/field-projection-mutating-context.rs:9:13
+ |
+LL | let Foo(ref mut y): Foo<fn(&'static str)> = x;
+ | ^^^^^^^^^ one type is more general than the other
+ |
+ = note: expected fn pointer `for<'a> fn(&'a str)`
+ found fn pointer `fn(&str)`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/mir/field-projection-mutating-context2.rs b/tests/ui/mir/field-projection-mutating-context2.rs
new file mode 100644
index 000000000..dd9c44a16
--- /dev/null
+++ b/tests/ui/mir/field-projection-mutating-context2.rs
@@ -0,0 +1,17 @@
+use std::sync::Mutex;
+
+static GLOBAL: Mutex<&'static str> = Mutex::new("global str");
+
+struct Foo<T>(T); // `T` is covariant.
+
+fn foo<'a>(mut x: Foo<fn(&'a str)>, string: &'a str) {
+ let Foo(ref mut y): Foo<fn(&'static str)> = x;
+ //~^ ERROR lifetime may not live long enough
+ *y = |s| *GLOBAL.lock().unwrap() = s;
+ (x.0)(&string);
+}
+
+fn main() {
+ foo(Foo(|_| ()), &String::from("i am shortlived"));
+ println!("{}", GLOBAL.lock().unwrap());
+}
diff --git a/tests/ui/mir/field-projection-mutating-context2.stderr b/tests/ui/mir/field-projection-mutating-context2.stderr
new file mode 100644
index 000000000..a7b66fe10
--- /dev/null
+++ b/tests/ui/mir/field-projection-mutating-context2.stderr
@@ -0,0 +1,10 @@
+error: lifetime may not live long enough
+ --> $DIR/field-projection-mutating-context2.rs:8:25
+ |
+LL | fn foo<'a>(mut x: Foo<fn(&'a str)>, string: &'a str) {
+ | -- lifetime `'a` defined here
+LL | let Foo(ref mut y): Foo<fn(&'static str)> = x;
+ | ^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'static`
+
+error: aborting due to previous error
+
diff --git a/tests/ui/mir/field-ty-ascription-enums.rs b/tests/ui/mir/field-ty-ascription-enums.rs
new file mode 100644
index 000000000..179af6170
--- /dev/null
+++ b/tests/ui/mir/field-ty-ascription-enums.rs
@@ -0,0 +1,15 @@
+// build-pass
+
+enum Foo<T> {
+ Var(T),
+} // `T` is covariant.
+
+fn foo<'b>(x: Foo<for<'a> fn(&'a ())>) {
+ let Foo::Var(x): Foo<fn(&'b ())> = x;
+}
+
+fn foo_nested<'b>(x: Foo<Foo<for<'a> fn(&'a ())>>) {
+ let Foo::Var(Foo::Var(x)): Foo<Foo<fn(&'b ())>> = x;
+}
+
+fn main() {}
diff --git a/tests/ui/mir/field-ty-ascription.rs b/tests/ui/mir/field-ty-ascription.rs
new file mode 100644
index 000000000..178c7916b
--- /dev/null
+++ b/tests/ui/mir/field-ty-ascription.rs
@@ -0,0 +1,37 @@
+// build-pass
+
+struct Foo<T>(T); // `T` is covariant.
+
+struct Bar<T> {
+ x: T,
+} // `T` is covariant.
+
+fn bar<'b>(x: Bar<for<'a> fn(&'a ())>) {
+ let Bar { x }: Bar<fn(&'b ())> = x;
+}
+
+fn bar_nested<'b>(x: Bar<Bar<for<'a> fn(&'a ())>>) {
+ let Bar { x: Bar { x } }: Bar<Bar<fn(&'b ())>> = x;
+}
+
+fn bar_foo_nested<'b>(x: Bar<Foo<for<'a> fn(&'a ())>>) {
+ let Bar { x: Foo ( x ) }: Bar<Foo<fn(&'b ())>> = x;
+}
+
+fn foo<'b>(x: Foo<for<'a> fn(&'a ())>) {
+ let Foo(y): Foo<fn(&'b ())> = x;
+}
+
+fn foo_nested<'b>(x: Foo<Foo<for<'a> fn(&'a ())>>) {
+ let Foo(Foo(y)): Foo<Foo<fn(&'b ())>> = x;
+}
+
+fn tuple<'b>(x: (u32, for<'a> fn(&'a ()))) {
+ let (_, y): (u32, fn(&'b ())) = x;
+}
+
+fn tuple_nested<'b>(x: (u32, (u32, for<'a> fn(&'a ())))) {
+ let (_, (_, y)): (u32, (u32, fn(&'b ()))) = x;
+}
+
+fn main() {}
diff --git a/tests/ui/mir/issue-107678-projection-with-lifetime.rs b/tests/ui/mir/issue-107678-projection-with-lifetime.rs
new file mode 100644
index 000000000..14a456878
--- /dev/null
+++ b/tests/ui/mir/issue-107678-projection-with-lifetime.rs
@@ -0,0 +1,20 @@
+// build-pass
+
+#![crate_type = "lib"]
+
+pub trait StreamOnce {
+ type Error;
+}
+
+pub trait ResetStream: StreamOnce {
+ fn reset(&mut self) -> Result<(), Self::Error>;
+}
+
+impl<'a> ResetStream for &'a str
+ where Self: StreamOnce
+{
+ #[inline]
+ fn reset(&mut self) -> Result<(), Self::Error> {
+ Ok(())
+ }
+}
diff --git a/tests/ui/mir/issue-107691.rs b/tests/ui/mir/issue-107691.rs
new file mode 100644
index 000000000..517a17208
--- /dev/null
+++ b/tests/ui/mir/issue-107691.rs
@@ -0,0 +1,42 @@
+// build-pass
+// compile-flags: -C opt-level=3
+
+#![crate_type = "lib"]
+
+pub trait Archive {
+ type Archived;
+ type Resolver;
+
+ fn resolve(resolver: Self::Resolver, out: *mut Self::Archived);
+}
+
+pub type Archived<T> = <T as Archive>::Archived;
+pub type Resolver<T> = <T as Archive>::Resolver;
+
+pub struct Record<'a> {
+ _payload: &'a [u8],
+}
+
+pub struct ArchivedRecord<'a>
+where
+ &'a [u8]: Archive,
+{
+ _payload: Archived<&'a [u8]>,
+}
+
+pub struct RecordResolver<'a>
+where
+ &'a [u8]: Archive,
+{
+ _payload: Resolver<&'a [u8]>,
+}
+
+impl<'a> Archive for Record<'a>
+where
+ &'a [u8]: Archive,
+{
+ type Archived = ArchivedRecord<'a>;
+ type Resolver = RecordResolver<'a>;
+
+ fn resolve(_resolver: Self::Resolver, _out: *mut Self::Archived) {}
+}
diff --git a/tests/ui/mir/issue-109743.rs b/tests/ui/mir/issue-109743.rs
new file mode 100644
index 000000000..73f3405e3
--- /dev/null
+++ b/tests/ui/mir/issue-109743.rs
@@ -0,0 +1,51 @@
+// build-pass
+// compile-flags: --crate-type=lib
+
+use std::marker::PhantomData;
+
+pub trait StreamOnce {
+ type Token;
+}
+
+impl StreamOnce for &str {
+ type Token = ();
+}
+
+pub trait Parser<Input: StreamOnce> {
+ type PartialState: Default;
+ fn parse_mode(&self, _state: &Self::PartialState) {}
+ fn parse_mode_impl() {}
+}
+
+pub fn parse_bool<'a>() -> impl Parser<&'a str> {
+ pub struct TokensCmp<C, Input>
+ where
+ Input: StreamOnce,
+ {
+ _cmp: C,
+ _marker: PhantomData<Input>,
+ }
+
+ impl<Input, C> Parser<Input> for TokensCmp<C, Input>
+ where
+ C: FnMut(Input::Token),
+ Input: StreamOnce,
+ {
+ type PartialState = ();
+ }
+
+ TokensCmp { _cmp: |_| (), _marker: PhantomData }
+}
+
+pub struct ParseBool;
+
+impl<'a> Parser<&'a str> for ParseBool
+where
+ &'a str: StreamOnce,
+{
+ type PartialState = ();
+
+ fn parse_mode_impl() {
+ parse_bool().parse_mode(&Default::default())
+ }
+}
diff --git a/tests/ui/mir/mir_codegen_ssa.rs b/tests/ui/mir/mir_codegen_ssa.rs
new file mode 100644
index 000000000..5e2f10cef
--- /dev/null
+++ b/tests/ui/mir/mir_codegen_ssa.rs
@@ -0,0 +1,19 @@
+// build-pass
+// compile-flags: --crate-type=lib
+#![feature(custom_mir, core_intrinsics)]
+use std::intrinsics::mir::*;
+
+#[custom_mir(dialect = "runtime", phase = "optimized")]
+pub fn f(a: u32) -> u32 {
+ mir!(
+ let x: u32;
+ {
+ // Previously code generation failed with ICE "use of .. before def ..." because the
+ // definition of x was incorrectly identified as dominating the use of x located in the
+ // same statement:
+ x = x + a;
+ RET = x;
+ Return()
+ }
+ )
+}
diff --git a/tests/ui/mir/validate/storage-live.rs b/tests/ui/mir/validate/storage-live.rs
new file mode 100644
index 000000000..ed3c26ed6
--- /dev/null
+++ b/tests/ui/mir/validate/storage-live.rs
@@ -0,0 +1,30 @@
+// compile-flags: -Zvalidate-mir -Ztreat-err-as-bug
+// failure-status: 101
+// error-pattern: broken MIR in
+// error-pattern: StorageLive(_1) which already has storage here
+// normalize-stderr-test "note: .*\n\n" -> ""
+// normalize-stderr-test "thread 'rustc' panicked.*\n" -> ""
+// normalize-stderr-test "storage_live\[....\]" -> "storage_live[HASH]"
+// rustc-env:RUST_BACKTRACE=0
+
+#![feature(custom_mir, core_intrinsics)]
+
+extern crate core;
+use core::intrinsics::mir::*;
+use core::ptr::{addr_of, addr_of_mut};
+
+#[custom_mir(dialect = "built")]
+fn multiple_storage() {
+ mir!(
+ let a: usize;
+ {
+ StorageLive(a);
+ StorageLive(a);
+ Return()
+ }
+ )
+}
+
+fn main() {
+ multiple_storage()
+}
diff --git a/tests/ui/mir/validate/storage-live.stderr b/tests/ui/mir/validate/storage-live.stderr
new file mode 100644
index 000000000..b586a8658
--- /dev/null
+++ b/tests/ui/mir/validate/storage-live.stderr
@@ -0,0 +1,13 @@
+error: internal compiler error: broken MIR in Item(WithOptConstParam { did: DefId(0:8 ~ storage_live[HASH]::multiple_storage), const_param_did: None }) (before pass CheckPackedRef) at bb0[1]:
+ StorageLive(_1) which already has storage here
+ --> $DIR/storage-live.rs:22:13
+ |
+LL | StorageLive(a);
+ | ^^^^^^^^^^^^^^
+
+error: the compiler unexpectedly panicked. this is a bug.
+
+query stack during panic:
+#0 [mir_const] preparing `multiple_storage` for borrow checking
+#1 [mir_promoted] processing MIR for `multiple_storage`
+end of query stack
diff --git a/tests/ui/mismatched_types/abridged.stderr b/tests/ui/mismatched_types/abridged.stderr
index ff1a836c9..6d2fb1ce9 100644
--- a/tests/ui/mismatched_types/abridged.stderr
+++ b/tests/ui/mismatched_types/abridged.stderr
@@ -4,7 +4,7 @@ error[E0308]: mismatched types
LL | fn a() -> Foo {
| --- expected `Foo` because of return type
LL | Some(Foo { bar: 1 })
- | ^^^^^^^^^^^^^^^^^^^^ expected struct `Foo`, found enum `Option`
+ | ^^^^^^^^^^^^^^^^^^^^ expected `Foo`, found `Option<Foo>`
|
= note: expected struct `Foo`
found enum `Option<Foo>`
@@ -15,7 +15,7 @@ error[E0308]: mismatched types
LL | fn a2() -> Foo {
| --- expected `Foo` because of return type
LL | Ok(Foo { bar: 1})
- | ^^^^^^^^^^^^^^^^^ expected struct `Foo`, found enum `Result`
+ | ^^^^^^^^^^^^^^^^^ expected `Foo`, found `Result<Foo, _>`
|
= note: expected struct `Foo`
found enum `Result<Foo, _>`
@@ -26,7 +26,7 @@ error[E0308]: mismatched types
LL | fn b() -> Option<Foo> {
| ----------- expected `Option<Foo>` because of return type
LL | Foo { bar: 1 }
- | ^^^^^^^^^^^^^^ expected enum `Option`, found struct `Foo`
+ | ^^^^^^^^^^^^^^ expected `Option<Foo>`, found `Foo`
|
= note: expected enum `Option<Foo>`
found struct `Foo`
@@ -41,7 +41,7 @@ error[E0308]: mismatched types
LL | fn c() -> Result<Foo, Bar> {
| ---------------- expected `Result<Foo, Bar>` because of return type
LL | Foo { bar: 1 }
- | ^^^^^^^^^^^^^^ expected enum `Result`, found struct `Foo`
+ | ^^^^^^^^^^^^^^ expected `Result<Foo, Bar>`, found `Foo`
|
= note: expected enum `Result<Foo, Bar>`
found struct `Foo`
@@ -57,7 +57,7 @@ LL | fn d() -> X<X<String, String>, String> {
| ---------------------------- expected `X<X<String, String>, String>` because of return type
...
LL | x
- | ^ expected struct `String`, found integer
+ | ^ expected `X<X<String, String>, String>`, found `X<X<String, {integer}>, {integer}>`
|
= note: expected struct `X<X<_, String>, String>`
found struct `X<X<_, {integer}>, {integer}>`
@@ -69,7 +69,7 @@ LL | fn e() -> X<X<String, String>, String> {
| ---------------------------- expected `X<X<String, String>, String>` because of return type
...
LL | x
- | ^ expected struct `String`, found integer
+ | ^ expected `X<X<String, String>, String>`, found `X<X<String, {integer}>, String>`
|
= note: expected struct `X<X<_, String>, _>`
found struct `X<X<_, {integer}>, _>`
@@ -80,7 +80,7 @@ error[E0308]: mismatched types
LL | fn f() -> String {
| ------ expected `String` because of return type
LL | 1+2
- | ^^^ expected struct `String`, found integer
+ | ^^^ expected `String`, found integer
|
help: try using a conversion method
|
@@ -93,7 +93,7 @@ error[E0308]: mismatched types
LL | fn g() -> String {
| ------ expected `String` because of return type
LL | -2
- | ^^ expected struct `String`, found integer
+ | ^^ expected `String`, found integer
|
help: try using a conversion method
|
diff --git a/tests/ui/mismatched_types/do-not-suggest-boxed-trait-objects-instead-of-impl-trait.stderr b/tests/ui/mismatched_types/do-not-suggest-boxed-trait-objects-instead-of-impl-trait.stderr
index 2f814445b..54abb50d6 100644
--- a/tests/ui/mismatched_types/do-not-suggest-boxed-trait-objects-instead-of-impl-trait.stderr
+++ b/tests/ui/mismatched_types/do-not-suggest-boxed-trait-objects-instead-of-impl-trait.stderr
@@ -6,7 +6,7 @@ LL | | S
| | - expected because of this
LL | | } else {
LL | | Y
- | | ^ expected struct `S`, found struct `Y`
+ | | ^ expected `S`, found `Y`
LL | | }
| |_____- `if` and `else` have incompatible types
@@ -17,7 +17,7 @@ LL | / match true {
LL | | true => S,
| | - this is found to be of type `S`
LL | | false => Y,
- | | ^ expected struct `S`, found struct `Y`
+ | | ^ expected `S`, found `Y`
LL | | }
| |_____- `match` arms have incompatible types
diff --git a/tests/ui/mismatched_types/issue-106182.stderr b/tests/ui/mismatched_types/issue-106182.stderr
index ac3ab8e98..96ab3a029 100644
--- a/tests/ui/mismatched_types/issue-106182.stderr
+++ b/tests/ui/mismatched_types/issue-106182.stderr
@@ -4,7 +4,7 @@ error[E0308]: mismatched types
LL | match x {
| - this expression has type `&_S`
LL | _S(& (mut _y), _v) => {
- | ^^^^^^^^^^ expected `u32`, found reference
+ | ^^^^^^^^^^ expected `u32`, found `&_`
|
= note: expected type `u32`
found reference `&_`
diff --git a/tests/ui/mismatched_types/issue-38371-unfixable.stderr b/tests/ui/mismatched_types/issue-38371-unfixable.stderr
index 3c5e765ab..318285598 100644
--- a/tests/ui/mismatched_types/issue-38371-unfixable.stderr
+++ b/tests/ui/mismatched_types/issue-38371-unfixable.stderr
@@ -10,7 +10,7 @@ error[E0308]: mismatched types
LL | fn bgh(&&bar: u32) {}
| ^^^^^ --- expected due to this
| |
- | expected `u32`, found reference
+ | expected `u32`, found `&_`
|
= note: expected type `u32`
found reference `&_`
diff --git a/tests/ui/mismatched_types/issue-38371.stderr b/tests/ui/mismatched_types/issue-38371.stderr
index f43427f98..19335c446 100644
--- a/tests/ui/mismatched_types/issue-38371.stderr
+++ b/tests/ui/mismatched_types/issue-38371.stderr
@@ -4,7 +4,7 @@ error[E0308]: mismatched types
LL | fn foo(&_a: Foo) {}
| ^^^ --- expected due to this
| |
- | expected struct `Foo`, found reference
+ | expected `Foo`, found `&_`
|
= note: expected struct `Foo`
found reference `&_`
@@ -20,7 +20,7 @@ error[E0308]: mismatched types
LL | fn agh(&&_a: &u32) {}
| ^^^ ---- expected due to this
| |
- | expected `u32`, found reference
+ | expected `u32`, found `&_`
|
= note: expected type `u32`
found reference `&_`
diff --git a/tests/ui/mismatched_types/issue-47706.stderr b/tests/ui/mismatched_types/issue-47706.stderr
index d9d408844..69d6ee5cb 100644
--- a/tests/ui/mismatched_types/issue-47706.stderr
+++ b/tests/ui/mismatched_types/issue-47706.stderr
@@ -27,7 +27,7 @@ note: required by a bound in `foo`
--> $DIR/issue-47706.rs:22:8
|
LL | fn foo<F>(f: F)
- | --- required by a bound in this
+ | --- required by a bound in this function
LL | where
LL | F: Fn(),
| ^^^^ required by this bound in `foo`
diff --git a/tests/ui/mismatched_types/issue-74918-missing-lifetime.stderr b/tests/ui/mismatched_types/issue-74918-missing-lifetime.stderr
index 9ddea1629..b52318230 100644
--- a/tests/ui/mismatched_types/issue-74918-missing-lifetime.stderr
+++ b/tests/ui/mismatched_types/issue-74918-missing-lifetime.stderr
@@ -16,9 +16,9 @@ LL | fn next(&mut self) -> Option<IteratorChunk<T, S>> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ found `fn(&'1 mut ChunkingIterator<T, S>) -> Option<IteratorChunk<'1, T, S>>`
--> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
|
- = note: expected `fn(&'1 mut ChunkingIterator<T, S>) -> Option<IteratorChunk<'static, T, S>>`
+ = note: expected `fn(&'1 mut ChunkingIterator<T, S>) -> Option<IteratorChunk<'2, T, S>>`
|
- = note: expected signature `fn(&'1 mut ChunkingIterator<T, S>) -> Option<IteratorChunk<'static, T, S>>`
+ = note: expected signature `fn(&'1 mut ChunkingIterator<T, S>) -> Option<IteratorChunk<'2, T, S>>`
found signature `fn(&'1 mut ChunkingIterator<T, S>) -> Option<IteratorChunk<'1, T, S>>`
= help: the lifetime requirements from the `impl` do not correspond to the requirements in the `trait`
= help: verify the lifetime relationships in the `trait` and `impl` between the `self` argument, the other inputs and its output
diff --git a/tests/ui/mismatched_types/non_zero_assigned_something.stderr b/tests/ui/mismatched_types/non_zero_assigned_something.stderr
index d4b2c902f..57db71f88 100644
--- a/tests/ui/mismatched_types/non_zero_assigned_something.stderr
+++ b/tests/ui/mismatched_types/non_zero_assigned_something.stderr
@@ -2,7 +2,7 @@ error[E0308]: mismatched types
--> $DIR/non_zero_assigned_something.rs:2:35
|
LL | let _: std::num::NonZeroU64 = 1;
- | -------------------- ^ expected struct `NonZeroU64`, found integer
+ | -------------------- ^ expected `NonZeroU64`, found integer
| |
| expected due to this
|
@@ -15,7 +15,7 @@ error[E0308]: mismatched types
--> $DIR/non_zero_assigned_something.rs:6:43
|
LL | let _: Option<std::num::NonZeroU64> = 1;
- | ---------------------------- ^ expected enum `Option`, found integer
+ | ---------------------------- ^ expected `Option<NonZeroU64>`, found integer
| |
| expected due to this
|
diff --git a/tests/ui/mismatched_types/normalize-fn-sig.stderr b/tests/ui/mismatched_types/normalize-fn-sig.stderr
index 6c55f29c5..e3a064655 100644
--- a/tests/ui/mismatched_types/normalize-fn-sig.stderr
+++ b/tests/ui/mismatched_types/normalize-fn-sig.stderr
@@ -2,12 +2,13 @@ error[E0308]: mismatched types
--> $DIR/normalize-fn-sig.rs:14:22
|
LL | needs_i32_ref_fn(foo::<()>);
- | ---------------- ^^^^^^^^^ expected `&i32`, found `i32`
+ | ---------------- ^^^^^^^^^ expected fn pointer, found fn item
| |
| arguments to this function are incorrect
|
= note: expected fn pointer `fn(&'static i32, i32)`
found fn item `fn(i32, &'static i32) {foo::<()>}`
+ = note: when the arguments and return types match, functions can be coerced to function pointers
note: function defined here
--> $DIR/normalize-fn-sig.rs:11:4
|
diff --git a/tests/ui/mismatched_types/overloaded-calls-bad.stderr b/tests/ui/mismatched_types/overloaded-calls-bad.stderr
index 3a895acbd..cd483e7ad 100644
--- a/tests/ui/mismatched_types/overloaded-calls-bad.stderr
+++ b/tests/ui/mismatched_types/overloaded-calls-bad.stderr
@@ -32,7 +32,7 @@ error[E0057]: this function takes 1 argument but 2 arguments were supplied
--> $DIR/overloaded-calls-bad.rs:37:15
|
LL | let ans = s("burma", "shave");
- | ^ ------- ------- argument of type `&'static str` unexpected
+ | ^ ------- ------- unexpected argument of type `&'static str`
| |
| expected `isize`, found `&str`
|
@@ -43,8 +43,9 @@ LL | impl FnMut<(isize,)> for S {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
help: remove the extra argument
|
-LL | let ans = s(/* isize */);
- | ~~~~~~~~~~~~~
+LL - let ans = s("burma", "shave");
+LL + let ans = s(/* isize */);
+ |
error[E0308]: mismatched types
--> $DIR/overloaded-calls-bad.rs:40:7
diff --git a/tests/ui/mismatched_types/ref-pat-suggestions.stderr b/tests/ui/mismatched_types/ref-pat-suggestions.stderr
index 63eaa3930..62824004d 100644
--- a/tests/ui/mismatched_types/ref-pat-suggestions.stderr
+++ b/tests/ui/mismatched_types/ref-pat-suggestions.stderr
@@ -4,7 +4,7 @@ error[E0308]: mismatched types
LL | fn _f0(&_a: u32) {}
| ^^^ --- expected due to this
| |
- | expected `u32`, found reference
+ | expected `u32`, found `&_`
|
= note: expected type `u32`
found reference `&_`
@@ -41,7 +41,7 @@ error[E0308]: mismatched types
LL | fn _f2(&&_a: &u32) {}
| ^^^ ---- expected due to this
| |
- | expected `u32`, found reference
+ | expected `u32`, found `&_`
|
= note: expected type `u32`
found reference `&_`
@@ -57,7 +57,7 @@ error[E0308]: mismatched types
LL | fn _f3(&mut &_a: &mut u32) {}
| ^^^ -------- expected due to this
| |
- | expected `u32`, found reference
+ | expected `u32`, found `&_`
|
= note: expected type `u32`
found reference `&_`
@@ -106,7 +106,7 @@ LL | let _: fn(u32) = |&_a| ();
| ^--
| ||
| |expected due to this
- | expected `u32`, found reference
+ | expected `u32`, found `&_`
|
= note: expected type `u32`
found reference `&_`
@@ -145,7 +145,7 @@ LL | let _: fn(&u32) = |&&_a| ();
| ^--
| ||
| |expected due to this
- | expected `u32`, found reference
+ | expected `u32`, found `&_`
|
= note: expected type `u32`
found reference `&_`
@@ -162,7 +162,7 @@ LL | let _: fn(&mut u32) = |&mut &_a| ();
| ^--
| ||
| |expected due to this
- | expected `u32`, found reference
+ | expected `u32`, found `&_`
|
= note: expected type `u32`
found reference `&_`
@@ -212,7 +212,7 @@ error[E0308]: mismatched types
LL | let _ = |&_a: u32| ();
| ^^^ --- expected due to this
| |
- | expected `u32`, found reference
+ | expected `u32`, found `&_`
|
= note: expected type `u32`
found reference `&_`
@@ -249,7 +249,7 @@ error[E0308]: mismatched types
LL | let _ = |&&_a: &u32| ();
| ^^^ ---- expected due to this
| |
- | expected `u32`, found reference
+ | expected `u32`, found `&_`
|
= note: expected type `u32`
found reference `&_`
@@ -265,7 +265,7 @@ error[E0308]: mismatched types
LL | let _ = |&mut &_a: &mut u32| ();
| ^^^ -------- expected due to this
| |
- | expected `u32`, found reference
+ | expected `u32`, found `&_`
|
= note: expected type `u32`
found reference `&_`
diff --git a/tests/ui/mismatched_types/show_module.stderr b/tests/ui/mismatched_types/show_module.stderr
index 5e48e0955..4bbeaaab9 100644
--- a/tests/ui/mismatched_types/show_module.stderr
+++ b/tests/ui/mismatched_types/show_module.stderr
@@ -4,15 +4,15 @@ error[E0308]: mismatched types
LL | fn foo() -> Foo {
| --- expected `baz::Foo` because of return type
LL | meh::Foo
- | ^^^^^^^^ expected struct `baz::Foo`, found struct `meh::Foo`
+ | ^^^^^^^^ expected `baz::Foo`, found `meh::Foo`
|
- = note: struct `meh::Foo` and struct `baz::Foo` have similar names, but are actually distinct types
-note: struct `meh::Foo` is defined in module `crate::meh` of the current crate
+ = note: `meh::Foo` and `baz::Foo` have similar names, but are actually distinct types
+note: `meh::Foo` is defined in module `crate::meh` of the current crate
--> $DIR/show_module.rs:8:5
|
LL | pub struct Foo;
| ^^^^^^^^^^^^^^
-note: struct `baz::Foo` is defined in module `crate::blah::baz` of the current crate
+note: `baz::Foo` is defined in module `crate::blah::baz` of the current crate
--> $DIR/show_module.rs:3:9
|
LL | pub struct Foo;
diff --git a/tests/ui/mismatched_types/similar_paths.stderr b/tests/ui/mismatched_types/similar_paths.stderr
index 46a383325..3e44fb759 100644
--- a/tests/ui/mismatched_types/similar_paths.stderr
+++ b/tests/ui/mismatched_types/similar_paths.stderr
@@ -4,12 +4,12 @@ error[E0308]: mismatched types
LL | pub fn foo() -> Option<u8> {
| ---------- expected `Option<u8>` because of return type
LL | Some(42_u8)
- | ^^^^^^^^^^^ expected enum `Option`, found enum `std::option::Option`
+ | ^^^^^^^^^^^ expected `Option<u8>`, found `std::option::Option<u8>`
|
- = note: enum `std::option::Option` and enum `Option` have similar names, but are actually distinct types
-note: enum `std::option::Option` is defined in crate `core`
+ = note: `std::option::Option<u8>` and `Option<u8>` have similar names, but are actually distinct types
+note: `std::option::Option<u8>` is defined in crate `core`
--> $SRC_DIR/core/src/option.rs:LL:COL
-note: enum `Option` is defined in the current crate
+note: `Option<u8>` is defined in the current crate
--> $DIR/similar_paths.rs:1:1
|
LL | enum Option<T> {
diff --git a/tests/ui/mismatched_types/similar_paths_primitive.stderr b/tests/ui/mismatched_types/similar_paths_primitive.stderr
index 8a2f73945..80e78a4e4 100644
--- a/tests/ui/mismatched_types/similar_paths_primitive.stderr
+++ b/tests/ui/mismatched_types/similar_paths_primitive.stderr
@@ -2,13 +2,13 @@ error[E0308]: mismatched types
--> $DIR/similar_paths_primitive.rs:8:9
|
LL | foo(true);
- | --- ^^^^ expected struct `bool`, found `bool`
+ | --- ^^^^ expected `bool`, found a different `bool`
| |
| arguments to this function are incorrect
|
- = note: bool and struct `bool` have similar names, but are actually distinct types
+ = note: bool and `bool` have similar names, but are actually distinct types
= note: bool is a primitive defined by the language
-note: struct `bool` is defined in the current crate
+note: `bool` is defined in the current crate
--> $DIR/similar_paths_primitive.rs:3:1
|
LL | struct bool;
diff --git a/tests/ui/mismatched_types/suggest-boxed-trait-objects-instead-of-impl-trait.stderr b/tests/ui/mismatched_types/suggest-boxed-trait-objects-instead-of-impl-trait.stderr
index f58b9c3ec..40182a75a 100644
--- a/tests/ui/mismatched_types/suggest-boxed-trait-objects-instead-of-impl-trait.stderr
+++ b/tests/ui/mismatched_types/suggest-boxed-trait-objects-instead-of-impl-trait.stderr
@@ -6,7 +6,7 @@ LL | | S
| | - expected because of this
LL | | } else {
LL | | Y
- | | ^ expected struct `S`, found struct `Y`
+ | | ^ expected `S`, found `Y`
LL | | }
| |_____- `if` and `else` have incompatible types
|
@@ -28,7 +28,7 @@ LL | / match true {
LL | | true => S,
| | - this is found to be of type `S`
LL | | false => Y,
- | | ^ expected struct `S`, found struct `Y`
+ | | ^ expected `S`, found `Y`
LL | | }
| |_____- `match` arms have incompatible types
|
diff --git a/tests/ui/mismatched_types/suggest-removing-tuple-struct-field.stderr b/tests/ui/mismatched_types/suggest-removing-tuple-struct-field.stderr
index 35871afb5..c5d0eef10 100644
--- a/tests/ui/mismatched_types/suggest-removing-tuple-struct-field.stderr
+++ b/tests/ui/mismatched_types/suggest-removing-tuple-struct-field.stderr
@@ -2,7 +2,7 @@ error[E0308]: mismatched types
--> $DIR/suggest-removing-tuple-struct-field.rs:11:13
|
LL | some_fn(value.0);
- | ------- ^^^^^^^ expected struct `MyWrapper`, found `u32`
+ | ------- ^^^^^^^ expected `MyWrapper`, found `u32`
| |
| arguments to this function are incorrect
|
@@ -21,7 +21,7 @@ error[E0308]: mismatched types
--> $DIR/suggest-removing-tuple-struct-field.rs:12:13
|
LL | some_fn(my_wrapper!(123).0);
- | ------- ^^^^^^^^^^^^^^^^^^ expected struct `MyWrapper`, found `u32`
+ | ------- ^^^^^^^^^^^^^^^^^^ expected `MyWrapper`, found `u32`
| |
| arguments to this function are incorrect
|
diff --git a/tests/ui/mismatched_types/wrap-suggestion-privacy.stderr b/tests/ui/mismatched_types/wrap-suggestion-privacy.stderr
index fdd92cbfc..e20a0aa0e 100644
--- a/tests/ui/mismatched_types/wrap-suggestion-privacy.stderr
+++ b/tests/ui/mismatched_types/wrap-suggestion-privacy.stderr
@@ -2,7 +2,7 @@ error[E0308]: mismatched types
--> $DIR/wrap-suggestion-privacy.rs:12:19
|
LL | needs_wrapper(0);
- | ------------- ^ expected struct `Wrapper`, found integer
+ | ------------- ^ expected `Wrapper<i32>`, found integer
| |
| arguments to this function are incorrect
|
@@ -22,7 +22,7 @@ error[E0308]: mismatched types
--> $DIR/wrap-suggestion-privacy.rs:17:20
|
LL | needs_wrapping(0);
- | -------------- ^ expected struct `Wrapping`, found integer
+ | -------------- ^ expected `Wrapping<i32>`, found integer
| |
| arguments to this function are incorrect
|
@@ -42,7 +42,7 @@ error[E0308]: mismatched types
--> $DIR/wrap-suggestion-privacy.rs:22:17
|
LL | needs_ready(Some(0));
- | ----------- ^^^^^^^ expected struct `Ready`, found enum `Option`
+ | ----------- ^^^^^^^ expected `Ready<i32>`, found `Option<{integer}>`
| |
| arguments to this function are incorrect
|
diff --git a/tests/ui/modules/issue-107649.rs b/tests/ui/modules/issue-107649.rs
new file mode 100644
index 000000000..71b84cd30
--- /dev/null
+++ b/tests/ui/modules/issue-107649.rs
@@ -0,0 +1,106 @@
+// compile-flags: -Z ui-testing=no
+#[path = "auxiliary/dummy_lib.rs"]
+mod lib;
+
+/// The function needs to be long enough to
+/// ensure `max_line_num_len` to be large enough
+/// for no-ui-testing
+fn main() {
+ ();
+ ();
+ ();
+ ();
+ ();
+ ();
+ ();
+ ();
+ ();
+ ();
+ ();
+ ();
+ ();
+ ();
+ ();
+ ();
+ ();
+ ();
+ ();
+ ();
+ ();
+ ();
+ ();
+ ();
+ ();
+ ();
+ ();
+ ();
+ ();
+ ();
+ ();
+ ();
+ ();
+ ();
+ ();
+ ();
+ ();
+ ();
+ ();
+ ();
+ ();
+ ();
+ ();
+ ();
+ ();
+ ();
+ ();
+ ();
+ ();
+ ();
+ ();
+ ();
+ ();
+ ();
+ ();
+ ();
+ ();
+ ();
+ ();
+ ();
+ ();
+ ();
+ ();
+ ();
+ ();
+ ();
+ ();
+ ();
+ ();
+ ();
+ ();
+ ();
+ ();
+ ();
+ ();
+ ();
+ ();
+ ();
+ ();
+ ();
+ ();
+ ();
+ ();
+ ();
+ ();
+ ();
+ ();
+ ();
+ ();
+ ();
+ ();
+ ();
+ ();
+ ();
+ ();
+ ();
+ dbg!(lib::Dummy); //~ Error: `Dummy` doesn't implement `Debug`
+}
diff --git a/tests/ui/modules/issue-107649.stderr b/tests/ui/modules/issue-107649.stderr
new file mode 100644
index 000000000..1cea71f28
--- /dev/null
+++ b/tests/ui/modules/issue-107649.stderr
@@ -0,0 +1,18 @@
+error[E0277]: `Dummy` doesn't implement `Debug`
+ --> $DIR/issue-107649.rs:105:5
+ |
+105 | dbg!(lib::Dummy);
+ | ^^^^^^^^^^^^^^^^ `Dummy` cannot be formatted using `{:?}`
+ |
+ = help: the trait `Debug` is not implemented for `Dummy`
+ = note: add `#[derive(Debug)]` to `Dummy` or manually `impl Debug for Dummy`
+ = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `dbg` (in Nightly builds, run with -Z macro-backtrace for more info)
+help: consider annotating `Dummy` with `#[derive(Debug)]`
+ --> $DIR/auxiliary/dummy_lib.rs:2:1
+ |
+2 | #[derive(Debug)]
+ |
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/issues/issue-22536-copy-mustnt-zero.rs b/tests/ui/moves/issue-22536-copy-mustnt-zero.rs
index 017f36484..017f36484 100644
--- a/tests/ui/issues/issue-22536-copy-mustnt-zero.rs
+++ b/tests/ui/moves/issue-22536-copy-mustnt-zero.rs
diff --git a/tests/ui/moves/move-fn-self-receiver.stderr b/tests/ui/moves/move-fn-self-receiver.stderr
index 7f69e5dcf..91d237b1d 100644
--- a/tests/ui/moves/move-fn-self-receiver.stderr
+++ b/tests/ui/moves/move-fn-self-receiver.stderr
@@ -75,6 +75,8 @@ LL | fn use_pin_box_self(self: Pin<Box<Self>>) {}
error[E0505]: cannot move out of `mut_foo` because it is borrowed
--> $DIR/move-fn-self-receiver.rs:50:5
|
+LL | let mut mut_foo = Foo;
+ | ----------- binding `mut_foo` declared here
LL | let ret = mut_foo.use_mut_self();
| ---------------------- borrow of `mut_foo` occurs here
LL | mut_foo;
diff --git a/tests/ui/moves/pin-mut-reborrow-infer-var-issue-107419.fixed b/tests/ui/moves/pin-mut-reborrow-infer-var-issue-107419.fixed
new file mode 100644
index 000000000..0b9a3bae9
--- /dev/null
+++ b/tests/ui/moves/pin-mut-reborrow-infer-var-issue-107419.fixed
@@ -0,0 +1,11 @@
+// run-rustfix
+use std::pin::Pin;
+
+fn foo(_: &mut ()) {}
+
+fn main() {
+ let mut uwu = ();
+ let mut r = Pin::new(&mut uwu);
+ foo(r.as_mut().get_mut());
+ foo(r.get_mut()); //~ ERROR use of moved value
+}
diff --git a/tests/ui/moves/pin-mut-reborrow-infer-var-issue-107419.rs b/tests/ui/moves/pin-mut-reborrow-infer-var-issue-107419.rs
new file mode 100644
index 000000000..0e952b06e
--- /dev/null
+++ b/tests/ui/moves/pin-mut-reborrow-infer-var-issue-107419.rs
@@ -0,0 +1,11 @@
+// run-rustfix
+use std::pin::Pin;
+
+fn foo(_: &mut ()) {}
+
+fn main() {
+ let mut uwu = ();
+ let mut r = Pin::new(&mut uwu);
+ foo(r.get_mut());
+ foo(r.get_mut()); //~ ERROR use of moved value
+}
diff --git a/tests/ui/moves/pin-mut-reborrow-infer-var-issue-107419.stderr b/tests/ui/moves/pin-mut-reborrow-infer-var-issue-107419.stderr
new file mode 100644
index 000000000..7e513b73c
--- /dev/null
+++ b/tests/ui/moves/pin-mut-reborrow-infer-var-issue-107419.stderr
@@ -0,0 +1,20 @@
+error[E0382]: use of moved value: `r`
+ --> $DIR/pin-mut-reborrow-infer-var-issue-107419.rs:10:9
+ |
+LL | let mut r = Pin::new(&mut uwu);
+ | ----- move occurs because `r` has type `Pin<&mut ()>`, which does not implement the `Copy` trait
+LL | foo(r.get_mut());
+ | --------- `r` moved due to this method call
+LL | foo(r.get_mut());
+ | ^ value used here after move
+ |
+note: `Pin::<&'a mut T>::get_mut` takes ownership of the receiver `self`, which moves `r`
+ --> $SRC_DIR/core/src/pin.rs:LL:COL
+help: consider reborrowing the `Pin` instead of moving it
+ |
+LL | foo(r.as_mut().get_mut());
+ | +++++++++
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0382`.
diff --git a/tests/ui/mut/mut-cross-borrowing.stderr b/tests/ui/mut/mut-cross-borrowing.stderr
index ee739d628..8401827e5 100644
--- a/tests/ui/mut/mut-cross-borrowing.stderr
+++ b/tests/ui/mut/mut-cross-borrowing.stderr
@@ -4,7 +4,7 @@ error[E0308]: mismatched types
LL | f(x)
| - ^
| | |
- | | expected `&mut isize`, found struct `Box`
+ | | expected `&mut isize`, found `Box<{integer}>`
| | help: consider mutably borrowing here: `&mut x`
| arguments to this function are incorrect
|
diff --git a/tests/ui/mut/mut-pattern-internal-mutability.stderr b/tests/ui/mut/mut-pattern-internal-mutability.stderr
index 6583546aa..5f2074edb 100644
--- a/tests/ui/mut/mut-pattern-internal-mutability.stderr
+++ b/tests/ui/mut/mut-pattern-internal-mutability.stderr
@@ -13,9 +13,9 @@ error[E0506]: cannot assign to `*foo` because it is borrowed
--> $DIR/mut-pattern-internal-mutability.rs:13:5
|
LL | let &mut ref x = foo;
- | ----- borrow of `*foo` occurs here
+ | ----- `*foo` is borrowed here
LL | *foo += 1;
- | ^^^^^^^^^ assignment to borrowed `*foo` occurs here
+ | ^^^^^^^^^ `*foo` is assigned to here but it was already borrowed
LL | drop(x);
| - borrow later used here
diff --git a/tests/ui/native-library-link-flags/mix-bundle-and-whole-archive-link-attr.rs b/tests/ui/native-library-link-flags/mix-bundle-and-whole-archive-link-attr.rs
index 066048795..0ccd441cc 100644
--- a/tests/ui/native-library-link-flags/mix-bundle-and-whole-archive-link-attr.rs
+++ b/tests/ui/native-library-link-flags/mix-bundle-and-whole-archive-link-attr.rs
@@ -1,8 +1,11 @@
-// compile-flags: -Zunstable-options --crate-type rlib
+// gate-test-packed_bundled_libs
+
+// ignore-wasm32-bare
+// compile-flags: --crate-type rlib
+// error-pattern: link modifiers combination `+bundle,+whole-archive` is unstable when generating rlibs
// build-fail
-// error-pattern: the linking modifiers `+bundle` and `+whole-archive` are not compatible with each other when generating rlibs
-#[link(name = "mylib", kind = "static", modifiers = "+bundle,+whole-archive")]
-extern "C" { }
+#[link(name = "rust_test_helpers", kind = "static", modifiers = "+bundle,+whole-archive")]
+extern "C" {}
-fn main() { }
+fn main() {}
diff --git a/tests/ui/native-library-link-flags/mix-bundle-and-whole-archive-link-attr.stderr b/tests/ui/native-library-link-flags/mix-bundle-and-whole-archive-link-attr.stderr
index 246efb8d6..8a9fed740 100644
--- a/tests/ui/native-library-link-flags/mix-bundle-and-whole-archive-link-attr.stderr
+++ b/tests/ui/native-library-link-flags/mix-bundle-and-whole-archive-link-attr.stderr
@@ -1,6 +1,4 @@
-error: the linking modifiers `+bundle` and `+whole-archive` are not compatible with each other when generating rlibs
+error: link modifiers combination `+bundle,+whole-archive` is unstable when generating rlibs
-error: could not find native static library `mylib`, perhaps an -L flag is missing?
-
-error: aborting due to 2 previous errors
+error: aborting due to previous error
diff --git a/tests/ui/native-library-link-flags/mix-bundle-and-whole-archive.rs b/tests/ui/native-library-link-flags/mix-bundle-and-whole-archive.rs
index 1d0768d99..18d4b52a3 100644
--- a/tests/ui/native-library-link-flags/mix-bundle-and-whole-archive.rs
+++ b/tests/ui/native-library-link-flags/mix-bundle-and-whole-archive.rs
@@ -1,7 +1,8 @@
-// Mixing +bundle and +whole-archive is not allowed
+// gate-test-packed_bundled_libs
-// compile-flags: -l static:+bundle,+whole-archive=mylib -Zunstable-options --crate-type rlib
+// ignore-wasm32-bare
+// compile-flags: -l static:+bundle,+whole-archive=rust_test_helpers --crate-type rlib
+// error-pattern: link modifiers combination `+bundle,+whole-archive` is unstable when generating rlibs
// build-fail
-// error-pattern: the linking modifiers `+bundle` and `+whole-archive` are not compatible with each other when generating rlibs
-fn main() { }
+fn main() {}
diff --git a/tests/ui/native-library-link-flags/mix-bundle-and-whole-archive.stderr b/tests/ui/native-library-link-flags/mix-bundle-and-whole-archive.stderr
index 246efb8d6..8a9fed740 100644
--- a/tests/ui/native-library-link-flags/mix-bundle-and-whole-archive.stderr
+++ b/tests/ui/native-library-link-flags/mix-bundle-and-whole-archive.stderr
@@ -1,6 +1,4 @@
-error: the linking modifiers `+bundle` and `+whole-archive` are not compatible with each other when generating rlibs
+error: link modifiers combination `+bundle,+whole-archive` is unstable when generating rlibs
-error: could not find native static library `mylib`, perhaps an -L flag is missing?
-
-error: aborting due to 2 previous errors
+error: aborting due to previous error
diff --git a/tests/ui/never_type/diverging-tuple-parts-39485.stderr b/tests/ui/never_type/diverging-tuple-parts-39485.stderr
index 52d07ae17..ded13e270 100644
--- a/tests/ui/never_type/diverging-tuple-parts-39485.stderr
+++ b/tests/ui/never_type/diverging-tuple-parts-39485.stderr
@@ -2,7 +2,7 @@ error[E0308]: mismatched types
--> $DIR/diverging-tuple-parts-39485.rs:8:5
|
LL | &panic!()
- | ^^^^^^^^^ expected `()`, found reference
+ | ^^^^^^^^^ expected `()`, found `&_`
|
= note: expected unit type `()`
found reference `&_`
@@ -22,7 +22,7 @@ error[E0308]: mismatched types
LL | fn f() -> isize {
| ----- expected `isize` because of return type
LL | (return 1, return 2)
- | ^^^^^^^^^^^^^^^^^^^^ expected `isize`, found tuple
+ | ^^^^^^^^^^^^^^^^^^^^ expected `isize`, found `(!, !)`
|
= note: expected type `isize`
found tuple `(!, !)`
diff --git a/tests/ui/never_type/issue-10176.rs b/tests/ui/never_type/issue-10176.rs
index 6277aa05e..5ac4359c5 100644
--- a/tests/ui/never_type/issue-10176.rs
+++ b/tests/ui/never_type/issue-10176.rs
@@ -3,7 +3,7 @@ fn f() -> isize {
//~^ ERROR mismatched types
//~| expected type `isize`
//~| found tuple `(!, !)`
-//~| expected `isize`, found tuple
+//~| expected `isize`, found `(!, !)`
}
fn main() {}
diff --git a/tests/ui/never_type/issue-10176.stderr b/tests/ui/never_type/issue-10176.stderr
index cd5361ffa..3f381b9ae 100644
--- a/tests/ui/never_type/issue-10176.stderr
+++ b/tests/ui/never_type/issue-10176.stderr
@@ -4,7 +4,7 @@ error[E0308]: mismatched types
LL | fn f() -> isize {
| ----- expected `isize` because of return type
LL | (return 1, return 2)
- | ^^^^^^^^^^^^^^^^^^^^ expected `isize`, found tuple
+ | ^^^^^^^^^^^^^^^^^^^^ expected `isize`, found `(!, !)`
|
= note: expected type `isize`
found tuple `(!, !)`
diff --git a/tests/ui/never_type/issue-52443.stderr b/tests/ui/never_type/issue-52443.stderr
index 33b7a9185..99dfce869 100644
--- a/tests/ui/never_type/issue-52443.stderr
+++ b/tests/ui/never_type/issue-52443.stderr
@@ -19,7 +19,7 @@ error[E0308]: mismatched types
--> $DIR/issue-52443.rs:2:10
|
LL | [(); & { loop { continue } } ];
- | ^^^^^^^^^^^^^^^^^^^^^^^ expected `usize`, found reference
+ | ^^^^^^^^^^^^^^^^^^^^^^^ expected `usize`, found `&_`
|
= note: expected type `usize`
found reference `&_`
diff --git a/tests/ui/never_type/issue-96335.stderr b/tests/ui/never_type/issue-96335.stderr
index e148b983e..c3d80a425 100644
--- a/tests/ui/never_type/issue-96335.stderr
+++ b/tests/ui/never_type/issue-96335.stderr
@@ -19,7 +19,7 @@ error[E0308]: mismatched types
LL | 0.....{loop{}1};
| ----^^^^^^^^^^^
| | |
- | | expected integer, found struct `RangeTo`
+ | | expected integer, found `RangeTo<{integer}>`
| arguments to this function are incorrect
|
= note: expected type `{integer}`
diff --git a/tests/ui/nll/borrowed-local-error.stderr b/tests/ui/nll/borrowed-local-error.stderr
index d629caa43..1cca4077d 100644
--- a/tests/ui/nll/borrowed-local-error.stderr
+++ b/tests/ui/nll/borrowed-local-error.stderr
@@ -4,6 +4,7 @@ error[E0597]: `v` does not live long enough
LL | let x = gimme({
| ----- borrow later used by call
LL | let v = (22,);
+ | - binding `v` declared here
LL | &v
| ^^ borrowed value does not live long enough
LL |
diff --git a/tests/ui/nll/borrowed-match-issue-45045.stderr b/tests/ui/nll/borrowed-match-issue-45045.stderr
index 9d4682667..33e3eb797 100644
--- a/tests/ui/nll/borrowed-match-issue-45045.stderr
+++ b/tests/ui/nll/borrowed-match-issue-45045.stderr
@@ -2,7 +2,7 @@ error[E0503]: cannot use `e` because it was mutably borrowed
--> $DIR/borrowed-match-issue-45045.rs:12:11
|
LL | let f = &mut e;
- | ------ borrow of `e` occurs here
+ | ------ `e` is borrowed here
LL | let g = f;
LL | match e {
| ^ use of borrowed `e`
diff --git a/tests/ui/nll/capture-ref-in-struct.stderr b/tests/ui/nll/capture-ref-in-struct.stderr
index cdfe7f6db..84b7ecf2f 100644
--- a/tests/ui/nll/capture-ref-in-struct.stderr
+++ b/tests/ui/nll/capture-ref-in-struct.stderr
@@ -1,6 +1,9 @@
error[E0597]: `y` does not live long enough
--> $DIR/capture-ref-in-struct.rs:18:16
|
+LL | let y = 22;
+ | - binding `y` declared here
+...
LL | y: &y,
| ^^ borrowed value does not live long enough
...
diff --git a/tests/ui/nll/closure-access-spans.stderr b/tests/ui/nll/closure-access-spans.stderr
index 0a09353b8..035dd5a56 100644
--- a/tests/ui/nll/closure-access-spans.stderr
+++ b/tests/ui/nll/closure-access-spans.stderr
@@ -38,7 +38,7 @@ error[E0503]: cannot use `x` because it was mutably borrowed
--> $DIR/closure-access-spans.rs:23:13
|
LL | let r = &mut x;
- | ------ borrow of `x` occurs here
+ | ------ `x` is borrowed here
LL | move || x;
| ^ use of borrowed `x`
LL | r.use_ref();
@@ -47,6 +47,8 @@ LL | r.use_ref();
error[E0505]: cannot move out of `x` because it is borrowed
--> $DIR/closure-access-spans.rs:29:5
|
+LL | fn closure_move_capture_conflict(mut x: String) {
+ | ----- binding `x` declared here
LL | let r = &x;
| -- borrow of `x` occurs here
LL | || x;
diff --git a/tests/ui/nll/closure-borrow-spans.stderr b/tests/ui/nll/closure-borrow-spans.stderr
index bada4e1b8..cf0df5834 100644
--- a/tests/ui/nll/closure-borrow-spans.stderr
+++ b/tests/ui/nll/closure-borrow-spans.stderr
@@ -40,9 +40,9 @@ error[E0506]: cannot assign to `x` because it is borrowed
LL | let f = || x;
| -- - borrow occurs due to use in closure
| |
- | borrow of `x` occurs here
+ | `x` is borrowed here
LL | x = 1;
- | ^^^^^ assignment to borrowed `x` occurs here
+ | ^^^^^ `x` is assigned to here but it was already borrowed
LL | f.use_ref();
| ----------- borrow later used here
@@ -52,7 +52,7 @@ error[E0503]: cannot use `x` because it was mutably borrowed
LL | let f = || x = 0;
| -- - borrow occurs due to use of `x` in closure
| |
- | borrow of `x` occurs here
+ | `x` is borrowed here
LL | let y = x;
| ^ use of borrowed `x`
LL | f.use_ref();
@@ -100,9 +100,9 @@ error[E0506]: cannot assign to `x` because it is borrowed
LL | let f = || x = 0;
| -- - borrow occurs due to use in closure
| |
- | borrow of `x` occurs here
+ | `x` is borrowed here
LL | x = 1;
- | ^^^^^ assignment to borrowed `x` occurs here
+ | ^^^^^ `x` is assigned to here but it was already borrowed
LL | f.use_ref();
| ----------- borrow later used here
@@ -160,9 +160,9 @@ error[E0506]: cannot assign to `*x` because it is borrowed
LL | let f = || *x = 0;
| -- -- borrow occurs due to use in closure
| |
- | borrow of `*x` occurs here
+ | `*x` is borrowed here
LL | *x = 1;
- | ^^^^^^ assignment to borrowed `*x` occurs here
+ | ^^^^^^ `*x` is assigned to here but it was already borrowed
LL | f.use_ref();
| ----------- borrow later used here
diff --git a/tests/ui/nll/closure-requirements/escape-argument.stderr b/tests/ui/nll/closure-requirements/escape-argument.stderr
index f67c312b9..5a8462d4d 100644
--- a/tests/ui/nll/closure-requirements/escape-argument.stderr
+++ b/tests/ui/nll/closure-requirements/escape-argument.stderr
@@ -21,6 +21,9 @@ LL | fn test() {
error[E0597]: `y` does not live long enough
--> $DIR/escape-argument.rs:27:25
|
+LL | let y = 22;
+ | - binding `y` declared here
+LL | let mut closure = expect_sig(|p, y| *p = y);
LL | closure(&mut p, &y);
| ^^ borrowed value does not live long enough
LL |
diff --git a/tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-comparing-against-free.stderr b/tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-comparing-against-free.stderr
index 7991abeb7..721cd45de 100644
--- a/tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-comparing-against-free.stderr
+++ b/tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-comparing-against-free.stderr
@@ -53,6 +53,8 @@ LL | fn case2() {
error[E0597]: `a` does not live long enough
--> $DIR/propagate-approximated-shorter-to-static-comparing-against-free.rs:30:26
|
+LL | let a = 0;
+ | - binding `a` declared here
LL | let cell = Cell::new(&a);
| ^^ borrowed value does not live long enough
...
diff --git a/tests/ui/nll/closure-requirements/type-test-subject-non-trivial-region.rs b/tests/ui/nll/closure-requirements/type-test-subject-non-trivial-region.rs
new file mode 100644
index 000000000..d8772e868
--- /dev/null
+++ b/tests/ui/nll/closure-requirements/type-test-subject-non-trivial-region.rs
@@ -0,0 +1,19 @@
+// See #108639 for description.
+// check-pass
+
+trait Trait {
+ type Item<'a>: 'a;
+}
+
+fn assert_static<T: 'static>(_: T) {}
+fn relate<T>(_: T, _: T) {}
+
+fn test_args<I: Trait>() {
+ let closure = |a, b| {
+ relate(&a, b);
+ assert_static(a);
+ };
+ closure(None::<I::Item<'_>>, &None::<I::Item<'_>>);
+}
+
+fn main() {}
diff --git a/tests/ui/nll/closure-requirements/type-test-subject-opaque-1.rs b/tests/ui/nll/closure-requirements/type-test-subject-opaque-1.rs
new file mode 100644
index 000000000..fce6f2fee
--- /dev/null
+++ b/tests/ui/nll/closure-requirements/type-test-subject-opaque-1.rs
@@ -0,0 +1,18 @@
+// Regression test for #107426.
+// check-pass
+
+use std::marker::PhantomData;
+#[derive(Clone, Copy)]
+pub struct Scope<'a>(&'a PhantomData<&'a mut &'a ()>);
+fn event<'a, F: FnMut() + 'a>(_: Scope<'a>, _: F) {}
+fn make_fn<'a>(_: Scope<'a>) -> impl Fn() + Copy + 'a {
+ || {}
+}
+
+fn foo(cx: Scope) {
+ let open_toggle = make_fn(cx);
+
+ || event(cx, open_toggle);
+}
+
+fn main() {}
diff --git a/tests/ui/nll/closure-requirements/type-test-subject-opaque-2.rs b/tests/ui/nll/closure-requirements/type-test-subject-opaque-2.rs
new file mode 100644
index 000000000..55905850f
--- /dev/null
+++ b/tests/ui/nll/closure-requirements/type-test-subject-opaque-2.rs
@@ -0,0 +1,17 @@
+// Resgression test for #107516.
+// check-pass
+
+fn iter1<'a: 'a>() -> impl Iterator<Item = &'static str> {
+ None.into_iter()
+}
+
+fn iter2<'a>() -> impl Iterator<Item = &'a str> {
+ None.into_iter()
+}
+
+struct Bivar<'a, I: Iterator<Item = &'a str> + 'a>(I);
+
+fn main() {
+ let _ = || Bivar(iter1());
+ let _ = || Bivar(iter2());
+}
diff --git a/tests/ui/nll/closure-requirements/type-test-subject-unnamed-region.rs b/tests/ui/nll/closure-requirements/type-test-subject-unnamed-region.rs
new file mode 100644
index 000000000..b5a95c170
--- /dev/null
+++ b/tests/ui/nll/closure-requirements/type-test-subject-unnamed-region.rs
@@ -0,0 +1,24 @@
+// See #108635 for description.
+// check-pass
+
+trait Trait {
+ type Item<'a>: 'a;
+}
+
+fn assert_static<T: 'static>(_: T) {}
+
+fn test_args<I: Trait>() {
+ let closure = |a, _b| assert_static(a);
+
+ closure(None::<I::Item<'_>>, &None::<I::Item<'_>>);
+}
+
+fn test_upvars<I: Trait>() {
+ let upvars = (None::<I::Item<'_>>, &None::<I::Item<'_>>);
+ let _closure = || {
+ let (a, _b) = upvars;
+ assert_static(a);
+ };
+}
+
+fn main() {}
diff --git a/tests/ui/nll/closure-use-spans.stderr b/tests/ui/nll/closure-use-spans.stderr
index ad928f1bb..0e27e5f5f 100644
--- a/tests/ui/nll/closure-use-spans.stderr
+++ b/tests/ui/nll/closure-use-spans.stderr
@@ -2,9 +2,9 @@ error[E0506]: cannot assign to `x` because it is borrowed
--> $DIR/closure-use-spans.rs:5:5
|
LL | let y = &x;
- | -- borrow of `x` occurs here
+ | -- `x` is borrowed here
LL | x = 0;
- | ^^^^^ assignment to borrowed `x` occurs here
+ | ^^^^^ `x` is assigned to here but it was already borrowed
LL | || *y;
| -- borrow later captured here by closure
@@ -12,9 +12,9 @@ error[E0506]: cannot assign to `x` because it is borrowed
--> $DIR/closure-use-spans.rs:11:5
|
LL | let y = &mut x;
- | ------ borrow of `x` occurs here
+ | ------ `x` is borrowed here
LL | x = 0;
- | ^^^^^ assignment to borrowed `x` occurs here
+ | ^^^^^ `x` is assigned to here but it was already borrowed
LL | || *y = 1;
| -- borrow later captured here by closure
@@ -22,9 +22,9 @@ error[E0506]: cannot assign to `x` because it is borrowed
--> $DIR/closure-use-spans.rs:17:5
|
LL | let y = &x;
- | -- borrow of `x` occurs here
+ | -- `x` is borrowed here
LL | x = 0;
- | ^^^^^ assignment to borrowed `x` occurs here
+ | ^^^^^ `x` is assigned to here but it was already borrowed
LL | move || *y;
| -- borrow later captured here by closure
diff --git a/tests/ui/nll/do-not-ignore-lifetime-bounds-in-copy-proj.stderr b/tests/ui/nll/do-not-ignore-lifetime-bounds-in-copy-proj.stderr
index 65be3b37e..862c925b4 100644
--- a/tests/ui/nll/do-not-ignore-lifetime-bounds-in-copy-proj.stderr
+++ b/tests/ui/nll/do-not-ignore-lifetime-bounds-in-copy-proj.stderr
@@ -1,6 +1,8 @@
error[E0597]: `s` does not live long enough
--> $DIR/do-not-ignore-lifetime-bounds-in-copy-proj.rs:9:18
|
+LL | let s = 2;
+ | - binding `s` declared here
LL | let a = (Foo(&s),);
| ^^ borrowed value does not live long enough
LL | drop(a.0);
diff --git a/tests/ui/nll/do-not-ignore-lifetime-bounds-in-copy.stderr b/tests/ui/nll/do-not-ignore-lifetime-bounds-in-copy.stderr
index b811ba4fd..ebaf6d124 100644
--- a/tests/ui/nll/do-not-ignore-lifetime-bounds-in-copy.stderr
+++ b/tests/ui/nll/do-not-ignore-lifetime-bounds-in-copy.stderr
@@ -1,6 +1,8 @@
error[E0597]: `s` does not live long enough
--> $DIR/do-not-ignore-lifetime-bounds-in-copy.rs:8:17
|
+LL | let s = 2;
+ | - binding `s` declared here
LL | let a = Foo(&s);
| ^^ borrowed value does not live long enough
LL | drop(a);
diff --git a/tests/ui/nll/dont-print-desugared.stderr b/tests/ui/nll/dont-print-desugared.stderr
index fad6121cb..289b246e6 100644
--- a/tests/ui/nll/dont-print-desugared.stderr
+++ b/tests/ui/nll/dont-print-desugared.stderr
@@ -10,6 +10,7 @@ error[E0597]: `y` does not live long enough
LL | for ref mut d in v {
| - a temporary with access to the borrow is created here ...
LL | let y = ();
+ | - binding `y` declared here
LL | *d = D(&y);
| ^^ borrowed value does not live long enough
LL | }
diff --git a/tests/ui/nll/drop-no-may-dangle.stderr b/tests/ui/nll/drop-no-may-dangle.stderr
index cb2808809..0ddb7adbb 100644
--- a/tests/ui/nll/drop-no-may-dangle.stderr
+++ b/tests/ui/nll/drop-no-may-dangle.stderr
@@ -2,10 +2,10 @@ error[E0506]: cannot assign to `v[_]` because it is borrowed
--> $DIR/drop-no-may-dangle.rs:18:9
|
LL | let p: WrapMayNotDangle<&usize> = WrapMayNotDangle { value: &v[0] };
- | ----- borrow of `v[_]` occurs here
+ | ----- `v[_]` is borrowed here
...
LL | v[0] += 1;
- | ^^^^^^^^^ assignment to borrowed `v[_]` occurs here
+ | ^^^^^^^^^ `v[_]` is assigned to here but it was already borrowed
...
LL | }
| - borrow might be used here, when `p` is dropped and runs the `Drop` code for type `WrapMayNotDangle`
@@ -14,10 +14,10 @@ error[E0506]: cannot assign to `v[_]` because it is borrowed
--> $DIR/drop-no-may-dangle.rs:21:5
|
LL | let p: WrapMayNotDangle<&usize> = WrapMayNotDangle { value: &v[0] };
- | ----- borrow of `v[_]` occurs here
+ | ----- `v[_]` is borrowed here
...
LL | v[0] += 1;
- | ^^^^^^^^^ assignment to borrowed `v[_]` occurs here
+ | ^^^^^^^^^ `v[_]` is assigned to here but it was already borrowed
LL | }
| - borrow might be used here, when `p` is dropped and runs the `Drop` code for type `WrapMayNotDangle`
diff --git a/tests/ui/nll/guarantor-issue-46974.stderr b/tests/ui/nll/guarantor-issue-46974.stderr
index 8854dd8d6..7edc3dcc5 100644
--- a/tests/ui/nll/guarantor-issue-46974.stderr
+++ b/tests/ui/nll/guarantor-issue-46974.stderr
@@ -2,10 +2,10 @@ error[E0506]: cannot assign to `*s` because it is borrowed
--> $DIR/guarantor-issue-46974.rs:7:5
|
LL | let t = &mut *s; // this borrow should last for the entire function
- | ------- borrow of `*s` occurs here
+ | ------- `*s` is borrowed here
LL | let x = &t.0;
LL | *s = (2,);
- | ^^^^^^^^^ assignment to borrowed `*s` occurs here
+ | ^^^^^^^^^ `*s` is assigned to here but it was already borrowed
LL | *x
| -- borrow later used here
diff --git a/tests/ui/nll/issue-27282-move-ref-mut-into-guard.stderr b/tests/ui/nll/issue-27282-move-ref-mut-into-guard.stderr
index 45119018d..4a512560c 100644
--- a/tests/ui/nll/issue-27282-move-ref-mut-into-guard.stderr
+++ b/tests/ui/nll/issue-27282-move-ref-mut-into-guard.stderr
@@ -4,7 +4,7 @@ error[E0507]: cannot move out of `foo` in pattern guard
LL | if { (|| { let bar = foo; bar.take() })(); false } => {},
| ^^ --- move occurs because `foo` has type `&mut Option<&i32>`, which does not implement the `Copy` trait
| |
- | move out of `foo` occurs here
+ | `foo` is moved here
|
= note: variables bound in patterns cannot be moved from until after the end of the pattern guard
@@ -14,7 +14,7 @@ error[E0507]: cannot move out of `foo` in pattern guard
LL | if let Some(()) = { (|| { let bar = foo; bar.take() })(); None } => {},
| ^^ --- move occurs because `foo` has type `&mut Option<&i32>`, which does not implement the `Copy` trait
| |
- | move out of `foo` occurs here
+ | `foo` is moved here
|
= note: variables bound in patterns cannot be moved from until after the end of the pattern guard
diff --git a/tests/ui/nll/issue-27282-mutation-in-guard.stderr b/tests/ui/nll/issue-27282-mutation-in-guard.stderr
index 1ba696593..0b5d72317 100644
--- a/tests/ui/nll/issue-27282-mutation-in-guard.stderr
+++ b/tests/ui/nll/issue-27282-mutation-in-guard.stderr
@@ -4,7 +4,7 @@ error[E0507]: cannot move out of `foo` in pattern guard
LL | (|| { let bar = foo; bar.take() })();
| ^^ --- move occurs because `foo` has type `&mut Option<&i32>`, which does not implement the `Copy` trait
| |
- | move out of `foo` occurs here
+ | `foo` is moved here
|
= note: variables bound in patterns cannot be moved from until after the end of the pattern guard
@@ -14,7 +14,7 @@ error[E0507]: cannot move out of `foo` in pattern guard
LL | (|| { let bar = foo; bar.take() })();
| ^^ --- move occurs because `foo` has type `&mut Option<&i32>`, which does not implement the `Copy` trait
| |
- | move out of `foo` occurs here
+ | `foo` is moved here
|
= note: variables bound in patterns cannot be moved from until after the end of the pattern guard
diff --git a/tests/ui/issues/issue-27583.rs b/tests/ui/nll/issue-27583.rs
index 84c94c7c9..84c94c7c9 100644
--- a/tests/ui/issues/issue-27583.rs
+++ b/tests/ui/nll/issue-27583.rs
diff --git a/tests/ui/nll/issue-27868.stderr b/tests/ui/nll/issue-27868.stderr
index e0b3b5494..204eda3d2 100644
--- a/tests/ui/nll/issue-27868.stderr
+++ b/tests/ui/nll/issue-27868.stderr
@@ -4,10 +4,10 @@ error[E0506]: cannot assign to `vecvec` because it is borrowed
LL | vecvec[0] += {
| ------
| |
- | _____borrow of `vecvec` occurs here
+ | _____`vecvec` is borrowed here
| |
LL | | vecvec = vec![];
- | | ^^^^^^ assignment to borrowed `vecvec` occurs here
+ | | ^^^^^^ `vecvec` is assigned to here but it was already borrowed
LL | |
LL | | 0
LL | | };
diff --git a/tests/ui/nll/issue-46036.stderr b/tests/ui/nll/issue-46036.stderr
index e6e95ee61..f337e2345 100644
--- a/tests/ui/nll/issue-46036.stderr
+++ b/tests/ui/nll/issue-46036.stderr
@@ -1,6 +1,8 @@
error[E0597]: `a` does not live long enough
--> $DIR/issue-46036.rs:8:24
|
+LL | let a = 3;
+ | - binding `a` declared here
LL | let foo = Foo { x: &a };
| ^^
| |
diff --git a/tests/ui/issues/issue-48179.rs b/tests/ui/nll/issue-48179.rs
index f81203dc4..f81203dc4 100644
--- a/tests/ui/issues/issue-48179.rs
+++ b/tests/ui/nll/issue-48179.rs
diff --git a/tests/ui/nll/issue-48803.stderr b/tests/ui/nll/issue-48803.stderr
index 2f94039c0..e24606e0b 100644
--- a/tests/ui/nll/issue-48803.stderr
+++ b/tests/ui/nll/issue-48803.stderr
@@ -2,10 +2,10 @@ error[E0506]: cannot assign to `x` because it is borrowed
--> $DIR/issue-48803.rs:10:5
|
LL | let y = &x;
- | -- borrow of `x` occurs here
+ | -- `x` is borrowed here
...
LL | x = "modified";
- | ^^^^^^^^^^^^^^ assignment to borrowed `x` occurs here
+ | ^^^^^^^^^^^^^^ `x` is assigned to here but it was already borrowed
LL |
LL | println!("{}", w); // prints "modified"
| - borrow later used here
diff --git a/tests/ui/nll/issue-52057.rs b/tests/ui/nll/issue-52057.rs
index 98f49fe8f..5991c1104 100644
--- a/tests/ui/nll/issue-52057.rs
+++ b/tests/ui/nll/issue-52057.rs
@@ -1,6 +1,6 @@
// Regression test for #52057. There is an implied bound
-// that `I: 'a` where `'a` is the lifetime of `self` in `parse_first`;
-// but to observe that, one must normalize first.
+// that `I: 'x` where `'x` is the lifetime of the reference `&mut Self::Input`
+// in `parse_first`; but to observe that, one must normalize first.
//
// run-pass
diff --git a/tests/ui/nll/issue-52534-2.stderr b/tests/ui/nll/issue-52534-2.stderr
index ac385e056..35d39bb6e 100644
--- a/tests/ui/nll/issue-52534-2.stderr
+++ b/tests/ui/nll/issue-52534-2.stderr
@@ -1,6 +1,8 @@
error[E0597]: `x` does not live long enough
--> $DIR/issue-52534-2.rs:6:13
|
+LL | let x = 32;
+ | - binding `x` declared here
LL | y = &x
| ^^ borrowed value does not live long enough
LL |
diff --git a/tests/ui/nll/issue-52663-trait-object.stderr b/tests/ui/nll/issue-52663-trait-object.stderr
index 5cedea6e6..338f64841 100644
--- a/tests/ui/nll/issue-52663-trait-object.stderr
+++ b/tests/ui/nll/issue-52663-trait-object.stderr
@@ -1,6 +1,8 @@
error[E0597]: `tmp0` does not live long enough
--> $DIR/issue-52663-trait-object.rs:12:20
|
+LL | let tmp0 = 3;
+ | ---- binding `tmp0` declared here
LL | let tmp1 = &tmp0;
| ^^^^^ borrowed value does not live long enough
LL | Box::new(tmp1) as Box<dyn Foo + '_>
diff --git a/tests/ui/nll/issue-54382-use-span-of-tail-of-block.stderr b/tests/ui/nll/issue-54382-use-span-of-tail-of-block.stderr
index d8f43cbc9..4a32c777a 100644
--- a/tests/ui/nll/issue-54382-use-span-of-tail-of-block.stderr
+++ b/tests/ui/nll/issue-54382-use-span-of-tail-of-block.stderr
@@ -1,6 +1,9 @@
error[E0597]: `_thing1` does not live long enough
--> $DIR/issue-54382-use-span-of-tail-of-block.rs:7:29
|
+LL | let mut _thing1 = D(Box::new("thing1"));
+ | ----------- binding `_thing1` declared here
+...
LL | D("other").next(&_thing1)
| ----------------^^^^^^^^-
| | |
diff --git a/tests/ui/nll/issue-54556-niconii.stderr b/tests/ui/nll/issue-54556-niconii.stderr
index a8e1edc54..d41d462f2 100644
--- a/tests/ui/nll/issue-54556-niconii.stderr
+++ b/tests/ui/nll/issue-54556-niconii.stderr
@@ -1,6 +1,9 @@
error[E0597]: `counter` does not live long enough
--> $DIR/issue-54556-niconii.rs:22:20
|
+LL | let counter = Mutex;
+ | ------- binding `counter` declared here
+LL |
LL | if let Ok(_) = counter.lock() { }
| ^^^^^^^^^^^^^^
| |
diff --git a/tests/ui/nll/issue-54556-stephaneyfx.stderr b/tests/ui/nll/issue-54556-stephaneyfx.stderr
index 036a7a0ab..f9e82cb00 100644
--- a/tests/ui/nll/issue-54556-stephaneyfx.stderr
+++ b/tests/ui/nll/issue-54556-stephaneyfx.stderr
@@ -1,6 +1,8 @@
error[E0597]: `stmt` does not live long enough
--> $DIR/issue-54556-stephaneyfx.rs:27:21
|
+LL | let stmt = Statement;
+ | ---- binding `stmt` declared here
LL | let rows = Rows(&stmt);
| ^^^^^ borrowed value does not live long enough
LL | rows.map(|row| row).next()
diff --git a/tests/ui/nll/issue-54556-temps-in-tail-diagnostic.stderr b/tests/ui/nll/issue-54556-temps-in-tail-diagnostic.stderr
index 92f5ffdf3..4eae9fdcd 100644
--- a/tests/ui/nll/issue-54556-temps-in-tail-diagnostic.stderr
+++ b/tests/ui/nll/issue-54556-temps-in-tail-diagnostic.stderr
@@ -1,6 +1,9 @@
error[E0597]: `_thing1` does not live long enough
--> $DIR/issue-54556-temps-in-tail-diagnostic.rs:5:11
|
+LL | let mut _thing1 = D(Box::new("thing1"));
+ | ----------- binding `_thing1` declared here
+LL | // D("other").next(&_thing1).end()
LL | D(&_thing1).end()
| --^^^^^^^^-
| | |
diff --git a/tests/ui/nll/issue-54556-used-vs-unused-tails.stderr b/tests/ui/nll/issue-54556-used-vs-unused-tails.stderr
index 25226e296..a2a7a8486 100644
--- a/tests/ui/nll/issue-54556-used-vs-unused-tails.stderr
+++ b/tests/ui/nll/issue-54556-used-vs-unused-tails.stderr
@@ -2,11 +2,12 @@ error[E0597]: `_t1` does not live long enough
--> $DIR/issue-54556-used-vs-unused-tails.rs:10:55
|
LL | { let mut _t1 = D(Box::new("t1")); D(&_t1).end() } ; // suggest `;`
- | --^^^^- - - ... and the borrow might be used here, when that temporary is dropped and runs the `Drop` code for type `D`
- | | | |
- | | | `_t1` dropped here while still borrowed
- | | borrowed value does not live long enough
- | a temporary with access to the borrow is created here ...
+ | ------- --^^^^- - - ... and the borrow might be used here, when that temporary is dropped and runs the `Drop` code for type `D`
+ | | | | |
+ | | | | `_t1` dropped here while still borrowed
+ | | | borrowed value does not live long enough
+ | | a temporary with access to the borrow is created here ...
+ | binding `_t1` declared here
|
help: consider adding semicolon after the expression so its temporaries are dropped sooner, before the local variables declared by the block are dropped
|
@@ -17,11 +18,12 @@ error[E0597]: `_t1` does not live long enough
--> $DIR/issue-54556-used-vs-unused-tails.rs:13:55
|
LL | { { let mut _t1 = D(Box::new("t1")); D(&_t1).end() } } ; // suggest `;`
- | --^^^^- - - ... and the borrow might be used here, when that temporary is dropped and runs the `Drop` code for type `D`
- | | | |
- | | | `_t1` dropped here while still borrowed
- | | borrowed value does not live long enough
- | a temporary with access to the borrow is created here ...
+ | ------- --^^^^- - - ... and the borrow might be used here, when that temporary is dropped and runs the `Drop` code for type `D`
+ | | | | |
+ | | | | `_t1` dropped here while still borrowed
+ | | | borrowed value does not live long enough
+ | | a temporary with access to the borrow is created here ...
+ | binding `_t1` declared here
|
help: consider adding semicolon after the expression so its temporaries are dropped sooner, before the local variables declared by the block are dropped
|
@@ -32,11 +34,12 @@ error[E0597]: `_t1` does not live long enough
--> $DIR/issue-54556-used-vs-unused-tails.rs:16:55
|
LL | { { let mut _t1 = D(Box::new("t1")); D(&_t1).end() }; } // suggest `;`
- | --^^^^- -- ... and the borrow might be used here, when that temporary is dropped and runs the `Drop` code for type `D`
- | | | |
- | | | `_t1` dropped here while still borrowed
- | | borrowed value does not live long enough
- | a temporary with access to the borrow is created here ...
+ | ------- --^^^^- -- ... and the borrow might be used here, when that temporary is dropped and runs the `Drop` code for type `D`
+ | | | | |
+ | | | | `_t1` dropped here while still borrowed
+ | | | borrowed value does not live long enough
+ | | a temporary with access to the borrow is created here ...
+ | binding `_t1` declared here
|
help: consider adding semicolon after the expression so its temporaries are dropped sooner, before the local variables declared by the block are dropped
|
@@ -47,11 +50,12 @@ error[E0597]: `_t1` does not live long enough
--> $DIR/issue-54556-used-vs-unused-tails.rs:19:55
|
LL | let _ = { let mut _t1 = D(Box::new("t1")); D(&_t1).end() } ; // suggest `;`
- | --^^^^- - - ... and the borrow might be used here, when that temporary is dropped and runs the `Drop` code for type `D`
- | | | |
- | | | `_t1` dropped here while still borrowed
- | | borrowed value does not live long enough
- | a temporary with access to the borrow is created here ...
+ | ------- --^^^^- - - ... and the borrow might be used here, when that temporary is dropped and runs the `Drop` code for type `D`
+ | | | | |
+ | | | | `_t1` dropped here while still borrowed
+ | | | borrowed value does not live long enough
+ | | a temporary with access to the borrow is created here ...
+ | binding `_t1` declared here
|
help: consider adding semicolon after the expression so its temporaries are dropped sooner, before the local variables declared by the block are dropped
|
@@ -62,11 +66,12 @@ error[E0597]: `_t1` does not live long enough
--> $DIR/issue-54556-used-vs-unused-tails.rs:22:55
|
LL | let _u = { let mut _t1 = D(Box::new("t1")); D(&_t1).unit() } ; // suggest `;`
- | --^^^^- - - ... and the borrow might be used here, when that temporary is dropped and runs the `Drop` code for type `D`
- | | | |
- | | | `_t1` dropped here while still borrowed
- | | borrowed value does not live long enough
- | a temporary with access to the borrow is created here ...
+ | ------- --^^^^- - - ... and the borrow might be used here, when that temporary is dropped and runs the `Drop` code for type `D`
+ | | | | |
+ | | | | `_t1` dropped here while still borrowed
+ | | | borrowed value does not live long enough
+ | | a temporary with access to the borrow is created here ...
+ | binding `_t1` declared here
|
help: consider adding semicolon after the expression so its temporaries are dropped sooner, before the local variables declared by the block are dropped
|
@@ -77,11 +82,12 @@ error[E0597]: `_t1` does not live long enough
--> $DIR/issue-54556-used-vs-unused-tails.rs:25:55
|
LL | let _x = { let mut _t1 = D(Box::new("t1")); D(&_t1).end() } ; // `let x = ...; x`
- | --^^^^- - - ... and the borrow might be used here, when that temporary is dropped and runs the `Drop` code for type `D`
- | | | |
- | | | `_t1` dropped here while still borrowed
- | | borrowed value does not live long enough
- | a temporary with access to the borrow is created here ...
+ | ------- --^^^^- - - ... and the borrow might be used here, when that temporary is dropped and runs the `Drop` code for type `D`
+ | | | | |
+ | | | | `_t1` dropped here while still borrowed
+ | | | borrowed value does not live long enough
+ | | a temporary with access to the borrow is created here ...
+ | binding `_t1` declared here
|
= note: the temporary is part of an expression at the end of a block;
consider forcing this temporary to be dropped sooner, before the block's local variables are dropped
@@ -94,11 +100,12 @@ error[E0597]: `_t1` does not live long enough
--> $DIR/issue-54556-used-vs-unused-tails.rs:30:55
|
LL | _y = { let mut _t1 = D(Box::new("t1")); D(&_t1).end() } ; // `let x = ...; x`
- | --^^^^- - - ... and the borrow might be used here, when that temporary is dropped and runs the `Drop` code for type `D`
- | | | |
- | | | `_t1` dropped here while still borrowed
- | | borrowed value does not live long enough
- | a temporary with access to the borrow is created here ...
+ | ------- --^^^^- - - ... and the borrow might be used here, when that temporary is dropped and runs the `Drop` code for type `D`
+ | | | | |
+ | | | | `_t1` dropped here while still borrowed
+ | | | borrowed value does not live long enough
+ | | a temporary with access to the borrow is created here ...
+ | binding `_t1` declared here
|
= note: the temporary is part of an expression at the end of a block;
consider forcing this temporary to be dropped sooner, before the block's local variables are dropped
@@ -111,12 +118,13 @@ error[E0597]: `_t1` does not live long enough
--> $DIR/issue-54556-used-vs-unused-tails.rs:37:55
|
LL | fn f_local_ref() { let mut _t1 = D(Box::new("t1")); D(&_t1).unit() } // suggest `;`
- | --^^^^- -
- | | | |
- | | | `_t1` dropped here while still borrowed
- | | | ... and the borrow might be used here, when that temporary is dropped and runs the `Drop` code for type `D`
- | | borrowed value does not live long enough
- | a temporary with access to the borrow is created here ...
+ | ------- --^^^^- -
+ | | | | |
+ | | | | `_t1` dropped here while still borrowed
+ | | | | ... and the borrow might be used here, when that temporary is dropped and runs the `Drop` code for type `D`
+ | | | borrowed value does not live long enough
+ | | a temporary with access to the borrow is created here ...
+ | binding `_t1` declared here
|
help: consider adding semicolon after the expression so its temporaries are dropped sooner, before the local variables declared by the block are dropped
|
@@ -127,12 +135,13 @@ error[E0597]: `_t1` does not live long enough
--> $DIR/issue-54556-used-vs-unused-tails.rs:40:55
|
LL | fn f() -> String { let mut _t1 = D(Box::new("t1")); D(&_t1).end() } // `let x = ...; x`
- | --^^^^- -
- | | | |
- | | | `_t1` dropped here while still borrowed
- | | | ... and the borrow might be used here, when that temporary is dropped and runs the `Drop` code for type `D`
- | | borrowed value does not live long enough
- | a temporary with access to the borrow is created here ...
+ | ------- --^^^^- -
+ | | | | |
+ | | | | `_t1` dropped here while still borrowed
+ | | | | ... and the borrow might be used here, when that temporary is dropped and runs the `Drop` code for type `D`
+ | | | borrowed value does not live long enough
+ | | a temporary with access to the borrow is created here ...
+ | binding `_t1` declared here
|
= note: the temporary is part of an expression at the end of a block;
consider forcing this temporary to be dropped sooner, before the block's local variables are dropped
diff --git a/tests/ui/nll/issue-54556-wrap-it-up.stderr b/tests/ui/nll/issue-54556-wrap-it-up.stderr
index 9f27fac15..adc419ae5 100644
--- a/tests/ui/nll/issue-54556-wrap-it-up.stderr
+++ b/tests/ui/nll/issue-54556-wrap-it-up.stderr
@@ -2,10 +2,10 @@ error[E0506]: cannot assign to `x` because it is borrowed
--> $DIR/issue-54556-wrap-it-up.rs:27:5
|
LL | let wrap = Wrap { p: &mut x };
- | ------ borrow of `x` occurs here
+ | ------ `x` is borrowed here
...
LL | x = 1;
- | ^^^^^ assignment to borrowed `x` occurs here
+ | ^^^^^ `x` is assigned to here but it was already borrowed
LL | }
| - borrow might be used here, when `foo` is dropped and runs the destructor for type `Foo<'_>`
diff --git a/tests/ui/nll/issue-55511.stderr b/tests/ui/nll/issue-55511.stderr
index bf3e58e8c..ecb9ef0ae 100644
--- a/tests/ui/nll/issue-55511.stderr
+++ b/tests/ui/nll/issue-55511.stderr
@@ -1,6 +1,8 @@
error[E0597]: `a` does not live long enough
--> $DIR/issue-55511.rs:13:28
|
+LL | let a = 22;
+ | - binding `a` declared here
LL | let b = Some(Cell::new(&a));
| ^^ borrowed value does not live long enough
...
diff --git a/tests/ui/nll/issue-57642-higher-ranked-subtype.stderr b/tests/ui/nll/issue-57642-higher-ranked-subtype.stderr
index 6e96f40c0..d1e94bc70 100644
--- a/tests/ui/nll/issue-57642-higher-ranked-subtype.stderr
+++ b/tests/ui/nll/issue-57642-higher-ranked-subtype.stderr
@@ -1,8 +1,8 @@
-error[E0599]: the function or associated item `make_g` exists for fn pointer `for<'a> fn(&'a ())`, but its trait bounds were not satisfied
+error[E0599]: the function or associated item `make_g` exists for fn pointer `fn(&())`, but its trait bounds were not satisfied
--> $DIR/issue-57642-higher-ranked-subtype.rs:31:25
|
LL | let x = <fn (&())>::make_g();
- | ^^^^^^ function or associated item cannot be called on `for<'a> fn(&'a ())` due to unsatisfied trait bounds
+ | ^^^^^^ function or associated item cannot be called on `fn(&())` due to unsatisfied trait bounds
|
= note: the following trait bounds were not satisfied:
`for<'a> fn(&'a ()): X`
@@ -17,7 +17,7 @@ error[E0599]: no function or associated item named `make_f` found for fn pointer
--> $DIR/issue-57642-higher-ranked-subtype.rs:35:25
|
LL | let x = <fn (&())>::make_f();
- | ^^^^^^ function or associated item not found in `for<'a> fn(&'a ())`
+ | ^^^^^^ function or associated item not found in `fn(&())`
|
= help: items from traits can only be used if the trait is implemented and in scope
note: `Y` defines an item `make_f`, perhaps you need to implement it
diff --git a/tests/ui/nll/issue-57989.stderr b/tests/ui/nll/issue-57989.stderr
index 31f40d825..d5effd6f3 100644
--- a/tests/ui/nll/issue-57989.stderr
+++ b/tests/ui/nll/issue-57989.stderr
@@ -13,9 +13,9 @@ error[E0506]: cannot assign to `*x` because it is borrowed
--> $DIR/issue-57989.rs:5:5
|
LL | let g = &x;
- | -- borrow of `*x` occurs here
+ | -- `*x` is borrowed here
LL | *x = 0;
- | ^^^^^^ assignment to borrowed `*x` occurs here
+ | ^^^^^^ `*x` is assigned to here but it was already borrowed
LL |
LL | g;
| - borrow later used here
diff --git a/tests/ui/nll/issue-68550.stderr b/tests/ui/nll/issue-68550.stderr
index e234ebb04..851e36287 100644
--- a/tests/ui/nll/issue-68550.stderr
+++ b/tests/ui/nll/issue-68550.stderr
@@ -2,7 +2,9 @@ error[E0597]: `x` does not live long enough
--> $DIR/issue-68550.rs:12:20
|
LL | fn run<'a, A>(x: A)
- | -- lifetime `'a` defined here
+ | -- - binding `x` declared here
+ | |
+ | lifetime `'a` defined here
...
LL | let _: &'a A = &x;
| ----- ^^ borrowed value does not live long enough
diff --git a/tests/ui/nll/issue-69114-static-mut-ty.stderr b/tests/ui/nll/issue-69114-static-mut-ty.stderr
index 5e55cb502..1b41230d7 100644
--- a/tests/ui/nll/issue-69114-static-mut-ty.stderr
+++ b/tests/ui/nll/issue-69114-static-mut-ty.stderr
@@ -1,6 +1,9 @@
error[E0597]: `n` does not live long enough
--> $DIR/issue-69114-static-mut-ty.rs:19:15
|
+LL | let n = 42;
+ | - binding `n` declared here
+LL | unsafe {
LL | BAR = &n;
| ------^^
| | |
@@ -13,6 +16,9 @@ LL | }
error[E0597]: `n` does not live long enough
--> $DIR/issue-69114-static-mut-ty.rs:27:22
|
+LL | let n = 42;
+ | - binding `n` declared here
+LL | unsafe {
LL | BAR_ELIDED = &n;
| -------------^^
| | |
diff --git a/tests/ui/nll/issue-69114-static-ty.stderr b/tests/ui/nll/issue-69114-static-ty.stderr
index 0815e74b5..9215e850f 100644
--- a/tests/ui/nll/issue-69114-static-ty.stderr
+++ b/tests/ui/nll/issue-69114-static-ty.stderr
@@ -1,6 +1,8 @@
error[E0597]: `n` does not live long enough
--> $DIR/issue-69114-static-ty.rs:7:9
|
+LL | let n = 42;
+ | - binding `n` declared here
LL | FOO(&n);
| ----^^-
| | |
diff --git a/tests/ui/nll/issue-73159-rpit-static.stderr b/tests/ui/nll/issue-73159-rpit-static.stderr
index 260b9b597..4d3a90153 100644
--- a/tests/ui/nll/issue-73159-rpit-static.stderr
+++ b/tests/ui/nll/issue-73159-rpit-static.stderr
@@ -4,6 +4,7 @@ error[E0700]: hidden type for `impl Iterator<Item = u8>` captures lifetime that
LL | impl<'a> Foo<'a> {
| -- hidden type `Copied<std::slice::Iter<'a, u8>>` captures the lifetime `'a` as defined here
LL | fn make_it(&self) -> impl Iterator<Item = u8> {
+ | ------------------------ opaque type defined here
LL | self.0.iter().copied()
| ^^^^^^^^^^^^^^^^^^^^^^
diff --git a/tests/ui/issues/issue-75777.rs b/tests/ui/nll/issue-75777.rs
index a1e438bc6..a1e438bc6 100644
--- a/tests/ui/issues/issue-75777.rs
+++ b/tests/ui/nll/issue-75777.rs
diff --git a/tests/ui/issues/issue-75777.stderr b/tests/ui/nll/issue-75777.stderr
index 370cd72fd..370cd72fd 100644
--- a/tests/ui/issues/issue-75777.stderr
+++ b/tests/ui/nll/issue-75777.stderr
diff --git a/tests/ui/nll/loan_ends_mid_block_pair.stderr b/tests/ui/nll/loan_ends_mid_block_pair.stderr
index eb8442b31..58e378ab0 100644
--- a/tests/ui/nll/loan_ends_mid_block_pair.stderr
+++ b/tests/ui/nll/loan_ends_mid_block_pair.stderr
@@ -2,10 +2,10 @@ error[E0506]: cannot assign to `data.0` because it is borrowed
--> $DIR/loan_ends_mid_block_pair.rs:12:5
|
LL | let c = &mut data.0;
- | ----------- borrow of `data.0` occurs here
+ | ----------- `data.0` is borrowed here
LL | capitalize(c);
LL | data.0 = 'e';
- | ^^^^^^^^^^^^ assignment to borrowed `data.0` occurs here
+ | ^^^^^^^^^^^^ `data.0` is assigned to here but it was already borrowed
...
LL | capitalize(c);
| - borrow later used here
diff --git a/tests/ui/nll/local-outlives-static-via-hrtb.stderr b/tests/ui/nll/local-outlives-static-via-hrtb.stderr
index f5c10f3dd..a6b3328b5 100644
--- a/tests/ui/nll/local-outlives-static-via-hrtb.stderr
+++ b/tests/ui/nll/local-outlives-static-via-hrtb.stderr
@@ -1,6 +1,8 @@
error[E0597]: `local` does not live long enough
--> $DIR/local-outlives-static-via-hrtb.rs:24:28
|
+LL | let local = 0;
+ | ----- binding `local` declared here
LL | assert_static_via_hrtb(&local);
| -----------------------^^^^^^-
| | |
@@ -19,6 +21,9 @@ LL | fn assert_static_via_hrtb<G>(_: G) where for<'a> G: Outlives<'a> {}
error[E0597]: `local` does not live long enough
--> $DIR/local-outlives-static-via-hrtb.rs:25:45
|
+LL | let local = 0;
+ | ----- binding `local` declared here
+LL | assert_static_via_hrtb(&local);
LL | assert_static_via_hrtb_with_assoc_type(&&local);
| ----------------------------------------^^^^^^-
| | |
diff --git a/tests/ui/nll/match-cfg-fake-edges2.stderr b/tests/ui/nll/match-cfg-fake-edges2.stderr
index c6d15a936..36f2cd0b8 100644
--- a/tests/ui/nll/match-cfg-fake-edges2.stderr
+++ b/tests/ui/nll/match-cfg-fake-edges2.stderr
@@ -2,7 +2,7 @@ error[E0503]: cannot use `y.1` because it was mutably borrowed
--> $DIR/match-cfg-fake-edges2.rs:8:5
|
LL | let r = &mut y.1;
- | -------- borrow of `y.1` occurs here
+ | -------- `y.1` is borrowed here
...
LL | match y {
| ^^^^^^^ use of borrowed `y.1`
diff --git a/tests/ui/nll/match-guards-always-borrow.stderr b/tests/ui/nll/match-guards-always-borrow.stderr
index fa01d3a6f..afd853c40 100644
--- a/tests/ui/nll/match-guards-always-borrow.stderr
+++ b/tests/ui/nll/match-guards-always-borrow.stderr
@@ -4,7 +4,7 @@ error[E0507]: cannot move out of `foo` in pattern guard
LL | (|| { let bar = foo; bar.take() })();
| ^^ --- move occurs because `foo` has type `&mut Option<&i32>`, which does not implement the `Copy` trait
| |
- | move out of `foo` occurs here
+ | `foo` is moved here
|
= note: variables bound in patterns cannot be moved from until after the end of the pattern guard
@@ -14,7 +14,7 @@ error[E0507]: cannot move out of `foo` in pattern guard
LL | (|| { let bar = foo; bar.take() })();
| ^^ --- move occurs because `foo` has type `&mut Option<&i32>`, which does not implement the `Copy` trait
| |
- | move out of `foo` occurs here
+ | `foo` is moved here
|
= note: variables bound in patterns cannot be moved from until after the end of the pattern guard
diff --git a/tests/ui/nll/match-guards-partially-borrow.stderr b/tests/ui/nll/match-guards-partially-borrow.stderr
index 60b8dee71..7bdcbcb9c 100644
--- a/tests/ui/nll/match-guards-partially-borrow.stderr
+++ b/tests/ui/nll/match-guards-partially-borrow.stderr
@@ -74,9 +74,9 @@ error[E0506]: cannot assign to `t` because it is borrowed
--> $DIR/match-guards-partially-borrow.rs:225:13
|
LL | s if {
- | - borrow of `t` occurs here
+ | - `t` is borrowed here
LL | t = !t;
- | ^^^^^^ assignment to borrowed `t` occurs here
+ | ^^^^^^ `t` is assigned to here but it was already borrowed
LL | false
LL | } => (), // What value should `s` have in the arm?
| - borrow later used here
@@ -85,9 +85,9 @@ error[E0506]: cannot assign to `t` because it is borrowed
--> $DIR/match-guards-partially-borrow.rs:235:13
|
LL | s if let Some(()) = {
- | - borrow of `t` occurs here
+ | - `t` is borrowed here
LL | t = !t;
- | ^^^^^^ assignment to borrowed `t` occurs here
+ | ^^^^^^ `t` is assigned to here but it was already borrowed
LL | None
LL | } => (), // What value should `s` have in the arm?
| - borrow later used here
diff --git a/tests/ui/nll/match-on-borrowed.stderr b/tests/ui/nll/match-on-borrowed.stderr
index 32666529f..927348456 100644
--- a/tests/ui/nll/match-on-borrowed.stderr
+++ b/tests/ui/nll/match-on-borrowed.stderr
@@ -2,7 +2,7 @@ error[E0503]: cannot use `e` because it was mutably borrowed
--> $DIR/match-on-borrowed.rs:47:11
|
LL | E::V(ref mut x, _) => x,
- | --------- borrow of `e.0` occurs here
+ | --------- `e.0` is borrowed here
...
LL | match e { // Don't know that E uses a tag for its discriminant
| ^ use of borrowed `e.0`
@@ -14,7 +14,7 @@ error[E0503]: cannot use `*f` because it was mutably borrowed
--> $DIR/match-on-borrowed.rs:61:11
|
LL | E::V(ref mut x, _) => x,
- | --------- borrow of `f.0` occurs here
+ | --------- `f.0` is borrowed here
...
LL | match f { // Don't know that E uses a tag for its discriminant
| ^ use of borrowed `f.0`
@@ -26,7 +26,7 @@ error[E0503]: cannot use `t` because it was mutably borrowed
--> $DIR/match-on-borrowed.rs:81:5
|
LL | let x = &mut t;
- | ------ borrow of `t` occurs here
+ | ------ `t` is borrowed here
LL | match t {
| ^^^^^^^ use of borrowed `t`
...
diff --git a/tests/ui/nll/maybe-initialized-drop-implicit-fragment-drop.stderr b/tests/ui/nll/maybe-initialized-drop-implicit-fragment-drop.stderr
index 80e297807..55646b9dc 100644
--- a/tests/ui/nll/maybe-initialized-drop-implicit-fragment-drop.stderr
+++ b/tests/ui/nll/maybe-initialized-drop-implicit-fragment-drop.stderr
@@ -2,10 +2,10 @@ error[E0506]: cannot assign to `x` because it is borrowed
--> $DIR/maybe-initialized-drop-implicit-fragment-drop.rs:17:5
|
LL | let wrap = Wrap { p: &mut x };
- | ------ borrow of `x` occurs here
+ | ------ `x` is borrowed here
...
LL | x = 1;
- | ^^^^^ assignment to borrowed `x` occurs here
+ | ^^^^^ `x` is assigned to here but it was already borrowed
LL | // FIXME ^ Should not error in the future with implicit dtors, only manually implemented ones
LL | }
| - borrow might be used here, when `foo` is dropped and runs the destructor for type `Foo<'_>`
diff --git a/tests/ui/nll/maybe-initialized-drop-with-fragment.stderr b/tests/ui/nll/maybe-initialized-drop-with-fragment.stderr
index 14074472e..c89f94a78 100644
--- a/tests/ui/nll/maybe-initialized-drop-with-fragment.stderr
+++ b/tests/ui/nll/maybe-initialized-drop-with-fragment.stderr
@@ -2,10 +2,10 @@ error[E0506]: cannot assign to `x` because it is borrowed
--> $DIR/maybe-initialized-drop-with-fragment.rs:19:5
|
LL | let wrap = Wrap { p: &mut x };
- | ------ borrow of `x` occurs here
+ | ------ `x` is borrowed here
...
LL | x = 1;
- | ^^^^^ assignment to borrowed `x` occurs here
+ | ^^^^^ `x` is assigned to here but it was already borrowed
LL | }
| - borrow might be used here, when `foo` is dropped and runs the destructor for type `Foo<'_>`
diff --git a/tests/ui/nll/maybe-initialized-drop-with-uninitialized-fragments.stderr b/tests/ui/nll/maybe-initialized-drop-with-uninitialized-fragments.stderr
index 91c0afc1d..90db13bc5 100644
--- a/tests/ui/nll/maybe-initialized-drop-with-uninitialized-fragments.stderr
+++ b/tests/ui/nll/maybe-initialized-drop-with-uninitialized-fragments.stderr
@@ -2,10 +2,10 @@ error[E0506]: cannot assign to `x` because it is borrowed
--> $DIR/maybe-initialized-drop-with-uninitialized-fragments.rs:20:5
|
LL | let wrap = Wrap { p: &mut x };
- | ------ borrow of `x` occurs here
+ | ------ `x` is borrowed here
...
LL | x = 1;
- | ^^^^^ assignment to borrowed `x` occurs here
+ | ^^^^^ `x` is assigned to here but it was already borrowed
LL | // FIXME ^ This currently errors and it should not.
LL | }
| - borrow might be used here, when `foo` is dropped and runs the destructor for type `Foo<'_>`
diff --git a/tests/ui/nll/maybe-initialized-drop.stderr b/tests/ui/nll/maybe-initialized-drop.stderr
index 9825ba461..15a53a09a 100644
--- a/tests/ui/nll/maybe-initialized-drop.stderr
+++ b/tests/ui/nll/maybe-initialized-drop.stderr
@@ -2,9 +2,9 @@ error[E0506]: cannot assign to `x` because it is borrowed
--> $DIR/maybe-initialized-drop.rs:14:5
|
LL | let wrap = Wrap { p: &mut x };
- | ------ borrow of `x` occurs here
+ | ------ `x` is borrowed here
LL | x = 1;
- | ^^^^^ assignment to borrowed `x` occurs here
+ | ^^^^^ `x` is assigned to here but it was already borrowed
LL | }
| - borrow might be used here, when `wrap` is dropped and runs the `Drop` code for type `Wrap`
diff --git a/tests/ui/nll/member-constraints/min-choice-reject-ambiguous.rs b/tests/ui/nll/member-constraints/min-choice-reject-ambiguous.rs
new file mode 100644
index 000000000..52ea0f28d
--- /dev/null
+++ b/tests/ui/nll/member-constraints/min-choice-reject-ambiguous.rs
@@ -0,0 +1,43 @@
+// ... continued from ./min-choice.rs
+
+// check-fail
+
+trait Cap<'a> {}
+impl<T> Cap<'_> for T {}
+
+fn type_test<'a, T: 'a>() -> &'a u8 { &0 }
+
+// Make sure we don't pick `'b`.
+fn test_b<'a, 'b, 'c, T>() -> impl Cap<'a> + Cap<'b> + Cap<'c>
+where
+ 'a: 'b,
+ 'a: 'c,
+ T: 'b,
+{
+ type_test::<'_, T>() // This should pass if we pick 'b.
+ //~^ ERROR the parameter type `T` may not live long enough
+}
+
+// Make sure we don't pick `'c`.
+fn test_c<'a, 'b, 'c, T>() -> impl Cap<'a> + Cap<'b> + Cap<'c>
+where
+ 'a: 'b,
+ 'a: 'c,
+ T: 'c,
+{
+ type_test::<'_, T>() // This should pass if we pick 'c.
+ //~^ ERROR the parameter type `T` may not live long enough
+}
+
+// We need to pick min_choice from `['b, 'c]`, but it's ambiguous which one to pick because
+// they're incomparable.
+fn test_ambiguous<'a, 'b, 'c>(s: &'a u8) -> impl Cap<'b> + Cap<'c>
+where
+ 'a: 'b,
+ 'a: 'c,
+{
+ s
+ //~^ ERROR captures lifetime that does not appear in bounds
+}
+
+fn main() {}
diff --git a/tests/ui/nll/member-constraints/min-choice-reject-ambiguous.stderr b/tests/ui/nll/member-constraints/min-choice-reject-ambiguous.stderr
new file mode 100644
index 000000000..e0d476a33
--- /dev/null
+++ b/tests/ui/nll/member-constraints/min-choice-reject-ambiguous.stderr
@@ -0,0 +1,42 @@
+error[E0309]: the parameter type `T` may not live long enough
+ --> $DIR/min-choice-reject-ambiguous.rs:17:5
+ |
+LL | type_test::<'_, T>() // This should pass if we pick 'b.
+ | ^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
+ |
+help: consider adding an explicit lifetime bound...
+ |
+LL | T: 'b + 'a,
+ | ++++
+
+error[E0309]: the parameter type `T` may not live long enough
+ --> $DIR/min-choice-reject-ambiguous.rs:28:5
+ |
+LL | type_test::<'_, T>() // This should pass if we pick 'c.
+ | ^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
+ |
+help: consider adding an explicit lifetime bound...
+ |
+LL | T: 'c + 'a,
+ | ++++
+
+error[E0700]: hidden type for `impl Cap<'b> + Cap<'c>` captures lifetime that does not appear in bounds
+ --> $DIR/min-choice-reject-ambiguous.rs:39:5
+ |
+LL | fn test_ambiguous<'a, 'b, 'c>(s: &'a u8) -> impl Cap<'b> + Cap<'c>
+ | -- ---------------------- opaque type defined here
+ | |
+ | hidden type `&'a u8` captures the lifetime `'a` as defined here
+...
+LL | s
+ | ^
+ |
+help: to declare that `impl Cap<'b> + Cap<'c>` captures `'a`, you can add an explicit `'a` lifetime bound
+ |
+LL | fn test_ambiguous<'a, 'b, 'c>(s: &'a u8) -> impl Cap<'b> + Cap<'c> + 'a
+ | ++++
+
+error: aborting due to 3 previous errors
+
+Some errors have detailed explanations: E0309, E0700.
+For more information about an error, try `rustc --explain E0309`.
diff --git a/tests/ui/nll/member-constraints/min-choice.rs b/tests/ui/nll/member-constraints/min-choice.rs
new file mode 100644
index 000000000..14b4dae7a
--- /dev/null
+++ b/tests/ui/nll/member-constraints/min-choice.rs
@@ -0,0 +1,34 @@
+// Assuming that the hidden type in these tests is `&'_#15r u8`,
+// we have a member constraint: `'_#15r member ['static, 'a, 'b, 'c]`.
+//
+// Make sure we pick up the minimum non-ambiguous region among them.
+// We will have to exclude `['b, 'c]` because they're incomparable,
+// and then we should pick `'a` because we know `'static: 'a`.
+
+// check-pass
+
+trait Cap<'a> {}
+impl<T> Cap<'_> for T {}
+
+fn type_test<'a, T: 'a>() -> &'a u8 { &0 }
+
+// Basic test: make sure we don't bail out because 'b and 'c are incomparable.
+fn basic<'a, 'b, 'c>() -> impl Cap<'a> + Cap<'b> + Cap<'c>
+where
+ 'a: 'b,
+ 'a: 'c,
+{
+ &0
+}
+
+// Make sure we don't pick `'static`.
+fn test_static<'a, 'b, 'c, T>() -> impl Cap<'a> + Cap<'b> + Cap<'c>
+where
+ 'a: 'b,
+ 'a: 'c,
+ T: 'a,
+{
+ type_test::<'_, T>() // This will fail if we pick 'static
+}
+
+fn main() {}
diff --git a/tests/ui/nll/member-constraints/nested-impl-trait-fail.rs b/tests/ui/nll/member-constraints/nested-impl-trait-fail.rs
new file mode 100644
index 000000000..66ff828a8
--- /dev/null
+++ b/tests/ui/nll/member-constraints/nested-impl-trait-fail.rs
@@ -0,0 +1,33 @@
+// Nested impl-traits can impose different member constraints on the same region variable.
+
+// check-fail
+
+trait Cap<'a> {}
+impl<T> Cap<'_> for T {}
+
+// Assuming the hidden type is `[&'_#15r u8; 1]`, we have two distinct member constraints:
+// - '_#15r member ['static, 'a, 'b] // from outer impl-trait
+// - '_#15r member ['static, 'a, 'b] // from inner impl-trait
+// To satisfy both we can choose 'a or 'b, so it's a failure due to ambiguity.
+fn fail_early_bound<'s, 'a, 'b>(a: &'s u8) -> impl IntoIterator<Item = impl Cap<'a> + Cap<'b>>
+where
+ 's: 'a,
+ 's: 'b,
+{
+ [a]
+ //~^ E0700
+ //~| E0700
+}
+
+// Same as the above but with late-bound regions.
+fn fail_late_bound<'s, 'a, 'b>(
+ a: &'s u8,
+ _: &'a &'s u8,
+ _: &'b &'s u8,
+) -> impl IntoIterator<Item = impl Cap<'a> + Cap<'b>> {
+ [a]
+ //~^ E0700
+ //~| E0700
+}
+
+fn main() {}
diff --git a/tests/ui/nll/member-constraints/nested-impl-trait-fail.stderr b/tests/ui/nll/member-constraints/nested-impl-trait-fail.stderr
new file mode 100644
index 000000000..483b5822b
--- /dev/null
+++ b/tests/ui/nll/member-constraints/nested-impl-trait-fail.stderr
@@ -0,0 +1,83 @@
+error[E0700]: hidden type for `impl IntoIterator<Item = impl Cap<'a> + Cap<'b>>` captures lifetime that does not appear in bounds
+ --> $DIR/nested-impl-trait-fail.rs:17:5
+ |
+LL | fn fail_early_bound<'s, 'a, 'b>(a: &'s u8) -> impl IntoIterator<Item = impl Cap<'a> + Cap<'b>>
+ | -- ------------------------------------------------ opaque type defined here
+ | |
+ | hidden type `[&'s u8; 1]` captures the lifetime `'s` as defined here
+...
+LL | [a]
+ | ^^^
+ |
+help: to declare that `impl IntoIterator<Item = impl Cap<'a> + Cap<'b>>` captures `'s`, you can add an explicit `'s` lifetime bound
+ |
+LL | fn fail_early_bound<'s, 'a, 'b>(a: &'s u8) -> impl IntoIterator<Item = impl Cap<'a> + Cap<'b>> + 's
+ | ++++
+help: to declare that `impl Cap<'a> + Cap<'b>` captures `'s`, you can add an explicit `'s` lifetime bound
+ |
+LL | fn fail_early_bound<'s, 'a, 'b>(a: &'s u8) -> impl IntoIterator<Item = impl Cap<'a> + Cap<'b> + 's>
+ | ++++
+
+error[E0700]: hidden type for `impl Cap<'a> + Cap<'b>` captures lifetime that does not appear in bounds
+ --> $DIR/nested-impl-trait-fail.rs:17:5
+ |
+LL | fn fail_early_bound<'s, 'a, 'b>(a: &'s u8) -> impl IntoIterator<Item = impl Cap<'a> + Cap<'b>>
+ | -- ---------------------- opaque type defined here
+ | |
+ | hidden type `&'s u8` captures the lifetime `'s` as defined here
+...
+LL | [a]
+ | ^^^
+ |
+help: to declare that `impl IntoIterator<Item = impl Cap<'a> + Cap<'b>>` captures `'s`, you can add an explicit `'s` lifetime bound
+ |
+LL | fn fail_early_bound<'s, 'a, 'b>(a: &'s u8) -> impl IntoIterator<Item = impl Cap<'a> + Cap<'b>> + 's
+ | ++++
+help: to declare that `impl Cap<'a> + Cap<'b>` captures `'s`, you can add an explicit `'s` lifetime bound
+ |
+LL | fn fail_early_bound<'s, 'a, 'b>(a: &'s u8) -> impl IntoIterator<Item = impl Cap<'a> + Cap<'b> + 's>
+ | ++++
+
+error[E0700]: hidden type for `impl IntoIterator<Item = impl Cap<'a> + Cap<'b>>` captures lifetime that does not appear in bounds
+ --> $DIR/nested-impl-trait-fail.rs:28:5
+ |
+LL | fn fail_late_bound<'s, 'a, 'b>(
+ | -- hidden type `[&'s u8; 1]` captures the lifetime `'s` as defined here
+...
+LL | ) -> impl IntoIterator<Item = impl Cap<'a> + Cap<'b>> {
+ | ------------------------------------------------ opaque type defined here
+LL | [a]
+ | ^^^
+ |
+help: to declare that `impl IntoIterator<Item = impl Cap<'a> + Cap<'b>>` captures `'s`, you can add an explicit `'s` lifetime bound
+ |
+LL | ) -> impl IntoIterator<Item = impl Cap<'a> + Cap<'b>> + 's {
+ | ++++
+help: to declare that `impl Cap<'a> + Cap<'b>` captures `'s`, you can add an explicit `'s` lifetime bound
+ |
+LL | ) -> impl IntoIterator<Item = impl Cap<'a> + Cap<'b> + 's> {
+ | ++++
+
+error[E0700]: hidden type for `impl Cap<'a> + Cap<'b>` captures lifetime that does not appear in bounds
+ --> $DIR/nested-impl-trait-fail.rs:28:5
+ |
+LL | fn fail_late_bound<'s, 'a, 'b>(
+ | -- hidden type `&'s u8` captures the lifetime `'s` as defined here
+...
+LL | ) -> impl IntoIterator<Item = impl Cap<'a> + Cap<'b>> {
+ | ---------------------- opaque type defined here
+LL | [a]
+ | ^^^
+ |
+help: to declare that `impl IntoIterator<Item = impl Cap<'a> + Cap<'b>>` captures `'s`, you can add an explicit `'s` lifetime bound
+ |
+LL | ) -> impl IntoIterator<Item = impl Cap<'a> + Cap<'b>> + 's {
+ | ++++
+help: to declare that `impl Cap<'a> + Cap<'b>` captures `'s`, you can add an explicit `'s` lifetime bound
+ |
+LL | ) -> impl IntoIterator<Item = impl Cap<'a> + Cap<'b> + 's> {
+ | ++++
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0700`.
diff --git a/tests/ui/nll/member-constraints/nested-impl-trait-pass.rs b/tests/ui/nll/member-constraints/nested-impl-trait-pass.rs
new file mode 100644
index 000000000..15540cb46
--- /dev/null
+++ b/tests/ui/nll/member-constraints/nested-impl-trait-pass.rs
@@ -0,0 +1,29 @@
+// Nested impl-traits can impose different member constraints on the same region variable.
+
+// check-pass
+
+trait Cap<'a> {}
+impl<T> Cap<'_> for T {}
+
+// Assuming the hidden type is `[&'_#15r u8; 1]`, we have two distinct member constraints:
+// - '_#15r member ['static, 'a, 'b] // from outer impl-trait
+// - '_#15r member ['static, 'a] // from inner impl-trait
+// To satisfy both we can only choose 'a.
+fn pass_early_bound<'s, 'a, 'b>(a: &'s u8) -> impl IntoIterator<Item = impl Cap<'a>> + Cap<'b>
+where
+ 's: 'a,
+ 's: 'b,
+{
+ [a]
+}
+
+// Same as the above but with late-bound regions.
+fn pass_late_bound<'s, 'a, 'b>(
+ a: &'s u8,
+ _: &'a &'s u8,
+ _: &'b &'s u8,
+) -> impl IntoIterator<Item = impl Cap<'a>> + Cap<'b> {
+ [a]
+}
+
+fn main() {}
diff --git a/tests/ui/nll/outlives-suggestion-simple.stderr b/tests/ui/nll/outlives-suggestion-simple.stderr
index a8368c494..bcffd575a 100644
--- a/tests/ui/nll/outlives-suggestion-simple.stderr
+++ b/tests/ui/nll/outlives-suggestion-simple.stderr
@@ -73,7 +73,7 @@ LL | impl<'a> Bar<'a> {
LL | pub fn get<'b>(&self) -> &'b usize {
| -- lifetime `'b` defined here
LL | self.x
- | ^^^^^^ associated function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a`
+ | ^^^^^^ method was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a`
|
= help: consider adding the following bound: `'a: 'b`
@@ -85,7 +85,7 @@ LL | impl<'a> Baz<'a> {
LL | fn get<'b>(&'b self) -> &'a i32 {
| -- lifetime `'b` defined here
LL | self.x
- | ^^^^^^ associated function was supposed to return data with lifetime `'a` but it is returning data with lifetime `'b`
+ | ^^^^^^ method was supposed to return data with lifetime `'a` but it is returning data with lifetime `'b`
|
= help: consider adding the following bound: `'b: 'a`
diff --git a/tests/ui/nll/polonius/polonius-smoke-test.stderr b/tests/ui/nll/polonius/polonius-smoke-test.stderr
index fa1a6a9c9..534813b2d 100644
--- a/tests/ui/nll/polonius/polonius-smoke-test.stderr
+++ b/tests/ui/nll/polonius/polonius-smoke-test.stderr
@@ -8,7 +8,7 @@ error[E0503]: cannot use `x` because it was mutably borrowed
--> $DIR/polonius-smoke-test.rs:12:13
|
LL | let y = &mut x;
- | ------ borrow of `x` occurs here
+ | ------ `x` is borrowed here
LL | let z = x;
| ^ use of borrowed `x`
LL | let w = y;
@@ -18,7 +18,9 @@ error[E0505]: cannot move out of `x` because it is borrowed
--> $DIR/polonius-smoke-test.rs:18:13
|
LL | pub fn use_while_mut_fr(x: &mut i32) -> &mut i32 {
- | - let's call the lifetime of this reference `'1`
+ | - - let's call the lifetime of this reference `'1`
+ | |
+ | binding `x` declared here
LL | let y = &mut *x;
| ------- borrow of `*x` occurs here
LL | let z = x;
@@ -29,6 +31,8 @@ LL | y
error[E0505]: cannot move out of `s` because it is borrowed
--> $DIR/polonius-smoke-test.rs:42:5
|
+LL | let s = &mut 1;
+ | - binding `s` declared here
LL | let r = &mut *s;
| ------- borrow of `*s` occurs here
LL | let tmp = foo(&r);
diff --git a/tests/ui/nll/promoted-bounds.stderr b/tests/ui/nll/promoted-bounds.stderr
index df347f4e7..d111256b8 100644
--- a/tests/ui/nll/promoted-bounds.stderr
+++ b/tests/ui/nll/promoted-bounds.stderr
@@ -4,6 +4,7 @@ error[E0597]: `l` does not live long enough
LL | let ptr = {
| --- borrow later stored here
LL | let l = 3;
+ | - binding `l` declared here
LL | let b = &l;
| ^^ borrowed value does not live long enough
...
diff --git a/tests/ui/nll/reference-carried-through-struct-field.stderr b/tests/ui/nll/reference-carried-through-struct-field.stderr
index 56d878e43..5672b9cd7 100644
--- a/tests/ui/nll/reference-carried-through-struct-field.stderr
+++ b/tests/ui/nll/reference-carried-through-struct-field.stderr
@@ -2,7 +2,7 @@ error[E0503]: cannot use `x` because it was mutably borrowed
--> $DIR/reference-carried-through-struct-field.rs:6:5
|
LL | let wrapper = Wrap { w: &mut x };
- | ------ borrow of `x` occurs here
+ | ------ `x` is borrowed here
LL | x += 1;
| ^^^^^^ use of borrowed `x`
LL | *wrapper.w += 1;
diff --git a/tests/ui/nll/relate_tys/var-appears-twice.stderr b/tests/ui/nll/relate_tys/var-appears-twice.stderr
index d032ce6f2..ff6ea598f 100644
--- a/tests/ui/nll/relate_tys/var-appears-twice.stderr
+++ b/tests/ui/nll/relate_tys/var-appears-twice.stderr
@@ -1,6 +1,9 @@
error[E0597]: `b` does not live long enough
--> $DIR/var-appears-twice.rs:20:38
|
+LL | let b = 44;
+ | - binding `b` declared here
+...
LL | let x: DoubleCell<_> = make_cell(&b);
| ------------- ^^ borrowed value does not live long enough
| |
diff --git a/tests/ui/nll/ty-outlives/impl-trait-captures.stderr b/tests/ui/nll/ty-outlives/impl-trait-captures.stderr
index 7b9ed171d..7fcb68252 100644
--- a/tests/ui/nll/ty-outlives/impl-trait-captures.stderr
+++ b/tests/ui/nll/ty-outlives/impl-trait-captures.stderr
@@ -2,7 +2,9 @@ error[E0700]: hidden type for `Opaque(DefId(0:13 ~ impl_trait_captures[1afc]::fo
--> $DIR/impl-trait-captures.rs:11:5
|
LL | fn foo<'a, T>(x: &T) -> impl Foo<'a> {
- | -- hidden type `&ReFree(DefId(0:8 ~ impl_trait_captures[1afc]::foo), BrNamed(DefId(0:12 ~ impl_trait_captures[1afc]::foo::'_), '_)) T` captures the anonymous lifetime defined here
+ | -- ------------ opaque type defined here
+ | |
+ | hidden type `&ReFree(DefId(0:8 ~ impl_trait_captures[1afc]::foo), BrNamed(DefId(0:12 ~ impl_trait_captures[1afc]::foo::'_), '_)) T` captures the anonymous lifetime defined here
LL | x
| ^
|
diff --git a/tests/ui/nll/ty-outlives/projection-one-region-closure.stderr b/tests/ui/nll/ty-outlives/projection-one-region-closure.stderr
index dbda04c42..11ada59c0 100644
--- a/tests/ui/nll/ty-outlives/projection-one-region-closure.stderr
+++ b/tests/ui/nll/ty-outlives/projection-one-region-closure.stderr
@@ -110,7 +110,7 @@ LL | with_signature(cell, t, |cell, t| require(cell, t));
(),
]
= note: number of external vids: 4
- = note: where <T as Anything<ReEarlyBound(1, 'b)>>::AssocType: '_#3r
+ = note: where <T as Anything<'_#2r>>::AssocType: '_#3r
note: no external requirements
--> $DIR/projection-one-region-closure.rs:62:1
diff --git a/tests/ui/nll/ty-outlives/projection-one-region-trait-bound-closure.stderr b/tests/ui/nll/ty-outlives/projection-one-region-trait-bound-closure.stderr
index 250c796e2..47d4f2e46 100644
--- a/tests/ui/nll/ty-outlives/projection-one-region-trait-bound-closure.stderr
+++ b/tests/ui/nll/ty-outlives/projection-one-region-trait-bound-closure.stderr
@@ -86,7 +86,7 @@ LL | with_signature(cell, t, |cell, t| require(cell, t));
(),
]
= note: number of external vids: 4
- = note: where <T as Anything<ReEarlyBound(1, 'b)>>::AssocType: '_#3r
+ = note: where <T as Anything<'_#2r>>::AssocType: '_#3r
note: no external requirements
--> $DIR/projection-one-region-trait-bound-closure.rs:52:1
diff --git a/tests/ui/nll/ty-outlives/projection-two-region-trait-bound-closure.stderr b/tests/ui/nll/ty-outlives/projection-two-region-trait-bound-closure.stderr
index 90f049142..530dd8681 100644
--- a/tests/ui/nll/ty-outlives/projection-two-region-trait-bound-closure.stderr
+++ b/tests/ui/nll/ty-outlives/projection-two-region-trait-bound-closure.stderr
@@ -11,7 +11,7 @@ LL | with_signature(cell, t, |cell, t| require(cell, t));
]
= note: late-bound region is '_#4r
= note: number of external vids: 5
- = note: where <T as Anything<ReEarlyBound(0, 'b), ReEarlyBound(1, 'c)>>::AssocType: '_#3r
+ = note: where <T as Anything<'_#1r, '_#2r>>::AssocType: '_#3r
note: no external requirements
--> $DIR/projection-two-region-trait-bound-closure.rs:34:1
@@ -23,14 +23,14 @@ LL | | T: Anything<'b, 'c>,
|
= note: defining type: no_relationships_late::<'_#1r, '_#2r, T>
-error[E0309]: the associated type `<T as Anything<ReEarlyBound(0, 'b), ReEarlyBound(1, 'c)>>::AssocType` may not live long enough
+error[E0309]: the associated type `<T as Anything<'_#5r, '_#6r>>::AssocType` may not live long enough
--> $DIR/projection-two-region-trait-bound-closure.rs:38:39
|
LL | with_signature(cell, t, |cell, t| require(cell, t));
| ^^^^^^^^^^^^^^^^
|
- = help: consider adding an explicit lifetime bound `<T as Anything<ReEarlyBound(0, 'b), ReEarlyBound(1, 'c)>>::AssocType: 'a`...
- = note: ...so that the type `<T as Anything<ReEarlyBound(0, 'b), ReEarlyBound(1, 'c)>>::AssocType` will meet its required lifetime bounds
+ = help: consider adding an explicit lifetime bound `<T as Anything<'_#5r, '_#6r>>::AssocType: 'a`...
+ = note: ...so that the type `<T as Anything<'_#5r, '_#6r>>::AssocType` will meet its required lifetime bounds
note: external requirements
--> $DIR/projection-two-region-trait-bound-closure.rs:48:29
@@ -44,7 +44,7 @@ LL | with_signature(cell, t, |cell, t| require(cell, t));
(),
]
= note: number of external vids: 5
- = note: where <T as Anything<ReEarlyBound(1, 'b), ReEarlyBound(2, 'c)>>::AssocType: '_#4r
+ = note: where <T as Anything<'_#2r, '_#3r>>::AssocType: '_#4r
note: no external requirements
--> $DIR/projection-two-region-trait-bound-closure.rs:43:1
@@ -57,14 +57,14 @@ LL | | 'a: 'a,
|
= note: defining type: no_relationships_early::<'_#1r, '_#2r, '_#3r, T>
-error[E0309]: the associated type `<T as Anything<ReEarlyBound(1, 'b), ReEarlyBound(2, 'c)>>::AssocType` may not live long enough
+error[E0309]: the associated type `<T as Anything<'_#6r, '_#7r>>::AssocType` may not live long enough
--> $DIR/projection-two-region-trait-bound-closure.rs:48:39
|
LL | with_signature(cell, t, |cell, t| require(cell, t));
| ^^^^^^^^^^^^^^^^
|
- = help: consider adding an explicit lifetime bound `<T as Anything<ReEarlyBound(1, 'b), ReEarlyBound(2, 'c)>>::AssocType: 'a`...
- = note: ...so that the type `<T as Anything<ReEarlyBound(1, 'b), ReEarlyBound(2, 'c)>>::AssocType` will meet its required lifetime bounds
+ = help: consider adding an explicit lifetime bound `<T as Anything<'_#6r, '_#7r>>::AssocType: 'a`...
+ = note: ...so that the type `<T as Anything<'_#6r, '_#7r>>::AssocType` will meet its required lifetime bounds
note: external requirements
--> $DIR/projection-two-region-trait-bound-closure.rs:61:29
@@ -78,7 +78,7 @@ LL | with_signature(cell, t, |cell, t| require(cell, t));
(),
]
= note: number of external vids: 5
- = note: where <T as Anything<ReEarlyBound(1, 'b), ReEarlyBound(2, 'c)>>::AssocType: '_#4r
+ = note: where <T as Anything<'_#2r, '_#3r>>::AssocType: '_#4r
note: no external requirements
--> $DIR/projection-two-region-trait-bound-closure.rs:53:1
@@ -103,7 +103,7 @@ LL | with_signature(cell, t, |cell, t| require(cell, t));
(),
]
= note: number of external vids: 5
- = note: where <T as Anything<ReEarlyBound(1, 'b), ReEarlyBound(2, 'c)>>::AssocType: '_#4r
+ = note: where <T as Anything<'_#2r, '_#3r>>::AssocType: '_#4r
note: no external requirements
--> $DIR/projection-two-region-trait-bound-closure.rs:65:1
@@ -128,7 +128,7 @@ LL | with_signature(cell, t, |cell, t| require(cell, t));
(),
]
= note: number of external vids: 5
- = note: where <T as Anything<ReEarlyBound(1, 'b), ReEarlyBound(2, 'c)>>::AssocType: '_#4r
+ = note: where <T as Anything<'_#2r, '_#3r>>::AssocType: '_#4r
note: no external requirements
--> $DIR/projection-two-region-trait-bound-closure.rs:74:1
@@ -154,7 +154,7 @@ LL | with_signature(cell, t, |cell, t| require(cell, t));
]
= note: late-bound region is '_#3r
= note: number of external vids: 4
- = note: where <T as Anything<ReEarlyBound(0, 'b), ReEarlyBound(0, 'b)>>::AssocType: '_#2r
+ = note: where <T as Anything<'_#1r, '_#1r>>::AssocType: '_#2r
note: no external requirements
--> $DIR/projection-two-region-trait-bound-closure.rs:83:1
@@ -194,7 +194,7 @@ LL | with_signature(cell, t, |cell, t| require(cell, t));
(),
]
= note: number of external vids: 4
- = note: where <T as Anything<ReEarlyBound(1, 'b), ReEarlyBound(1, 'b)>>::AssocType: '_#3r
+ = note: where <T as Anything<'_#2r, '_#2r>>::AssocType: '_#3r
note: no external requirements
--> $DIR/projection-two-region-trait-bound-closure.rs:92:1
@@ -219,7 +219,7 @@ LL | with_signature(cell, t, |cell, t| require(cell, t));
(),
]
= note: number of external vids: 3
- = note: where <T as Anything<ReEarlyBound(0, 'a), ReEarlyBound(0, 'a)>>::AssocType: '_#2r
+ = note: where <T as Anything<'_#1r, '_#1r>>::AssocType: '_#2r
note: no external requirements
--> $DIR/projection-two-region-trait-bound-closure.rs:101:1
diff --git a/tests/ui/nll/user-annotations/adt-brace-enums.stderr b/tests/ui/nll/user-annotations/adt-brace-enums.stderr
index 253e38251..9e94fd5a7 100644
--- a/tests/ui/nll/user-annotations/adt-brace-enums.stderr
+++ b/tests/ui/nll/user-annotations/adt-brace-enums.stderr
@@ -1,6 +1,8 @@
error[E0597]: `c` does not live long enough
--> $DIR/adt-brace-enums.rs:25:48
|
+LL | let c = 66;
+ | - binding `c` declared here
LL | SomeEnum::SomeVariant::<&'static u32> { t: &c };
| ^^
| |
@@ -15,6 +17,7 @@ error[E0597]: `c` does not live long enough
LL | fn annot_reference_named_lifetime<'a>(_d: &'a u32) {
| -- lifetime `'a` defined here
LL | let c = 66;
+ | - binding `c` declared here
LL | SomeEnum::SomeVariant::<&'a u32> { t: &c };
| ^^
| |
diff --git a/tests/ui/nll/user-annotations/adt-brace-structs.stderr b/tests/ui/nll/user-annotations/adt-brace-structs.stderr
index 8b9d1705d..cbb7f6a55 100644
--- a/tests/ui/nll/user-annotations/adt-brace-structs.stderr
+++ b/tests/ui/nll/user-annotations/adt-brace-structs.stderr
@@ -1,6 +1,8 @@
error[E0597]: `c` does not live long enough
--> $DIR/adt-brace-structs.rs:23:37
|
+LL | let c = 66;
+ | - binding `c` declared here
LL | SomeStruct::<&'static u32> { t: &c };
| ^^
| |
@@ -15,6 +17,7 @@ error[E0597]: `c` does not live long enough
LL | fn annot_reference_named_lifetime<'a>(_d: &'a u32) {
| -- lifetime `'a` defined here
LL | let c = 66;
+ | - binding `c` declared here
LL | SomeStruct::<&'a u32> { t: &c };
| ^^
| |
diff --git a/tests/ui/nll/user-annotations/adt-nullary-enums.stderr b/tests/ui/nll/user-annotations/adt-nullary-enums.stderr
index 3326fa521..bca85a90d 100644
--- a/tests/ui/nll/user-annotations/adt-nullary-enums.stderr
+++ b/tests/ui/nll/user-annotations/adt-nullary-enums.stderr
@@ -1,6 +1,8 @@
error[E0597]: `c` does not live long enough
--> $DIR/adt-nullary-enums.rs:33:41
|
+LL | let c = 66;
+ | - binding `c` declared here
LL | / combine(
LL | | SomeEnum::SomeVariant(Cell::new(&c)),
| | ^^ borrowed value does not live long enough
@@ -15,7 +17,9 @@ error[E0597]: `c` does not live long enough
|
LL | fn annot_reference_named_lifetime<'a>(_d: &'a u32) {
| -- lifetime `'a` defined here
-...
+LL | let c = 66;
+ | - binding `c` declared here
+LL | combine(
LL | SomeEnum::SomeVariant(Cell::new(&c)),
| ----------^^-
| | |
diff --git a/tests/ui/nll/user-annotations/adt-tuple-enums.stderr b/tests/ui/nll/user-annotations/adt-tuple-enums.stderr
index 2fa704263..d2d85ec2b 100644
--- a/tests/ui/nll/user-annotations/adt-tuple-enums.stderr
+++ b/tests/ui/nll/user-annotations/adt-tuple-enums.stderr
@@ -1,6 +1,8 @@
error[E0597]: `c` does not live long enough
--> $DIR/adt-tuple-enums.rs:28:43
|
+LL | let c = 66;
+ | - binding `c` declared here
LL | SomeEnum::SomeVariant::<&'static u32>(&c);
| ^^
| |
@@ -15,6 +17,7 @@ error[E0597]: `c` does not live long enough
LL | fn annot_reference_named_lifetime<'a>(_d: &'a u32) {
| -- lifetime `'a` defined here
LL | let c = 66;
+ | - binding `c` declared here
LL | SomeEnum::SomeVariant::<&'a u32>(&c);
| ^^
| |
diff --git a/tests/ui/nll/user-annotations/adt-tuple-struct-calls.stderr b/tests/ui/nll/user-annotations/adt-tuple-struct-calls.stderr
index 9664fb9f5..b7bc2a10b 100644
--- a/tests/ui/nll/user-annotations/adt-tuple-struct-calls.stderr
+++ b/tests/ui/nll/user-annotations/adt-tuple-struct-calls.stderr
@@ -1,6 +1,9 @@
error[E0597]: `c` does not live long enough
--> $DIR/adt-tuple-struct-calls.rs:27:7
|
+LL | let c = 66;
+ | - binding `c` declared here
+LL | let f = SomeStruct::<&'static u32>;
LL | f(&c);
| --^^-
| | |
@@ -14,7 +17,9 @@ error[E0597]: `c` does not live long enough
|
LL | fn annot_reference_named_lifetime<'a>(_d: &'a u32) {
| -- lifetime `'a` defined here
-...
+LL | let c = 66;
+ | - binding `c` declared here
+LL | let f = SomeStruct::<&'a u32>;
LL | f(&c);
| --^^-
| | |
diff --git a/tests/ui/nll/user-annotations/adt-tuple-struct.stderr b/tests/ui/nll/user-annotations/adt-tuple-struct.stderr
index 76b525225..97d39da26 100644
--- a/tests/ui/nll/user-annotations/adt-tuple-struct.stderr
+++ b/tests/ui/nll/user-annotations/adt-tuple-struct.stderr
@@ -1,6 +1,8 @@
error[E0597]: `c` does not live long enough
--> $DIR/adt-tuple-struct.rs:23:32
|
+LL | let c = 66;
+ | - binding `c` declared here
LL | SomeStruct::<&'static u32>(&c);
| ^^
| |
@@ -15,6 +17,7 @@ error[E0597]: `c` does not live long enough
LL | fn annot_reference_named_lifetime<'a>(_d: &'a u32) {
| -- lifetime `'a` defined here
LL | let c = 66;
+ | - binding `c` declared here
LL | SomeStruct::<&'a u32>(&c);
| ^^
| |
diff --git a/tests/ui/nll/user-annotations/cast_static_lifetime.stderr b/tests/ui/nll/user-annotations/cast_static_lifetime.stderr
index 4599d04e7..3b9363c41 100644
--- a/tests/ui/nll/user-annotations/cast_static_lifetime.stderr
+++ b/tests/ui/nll/user-annotations/cast_static_lifetime.stderr
@@ -1,6 +1,8 @@
error[E0597]: `x` does not live long enough
--> $DIR/cast_static_lifetime.rs:5:19
|
+LL | let x = 22_u32;
+ | - binding `x` declared here
LL | let y: &u32 = (&x) as &'static u32;
| ^^^^----------------
| |
diff --git a/tests/ui/nll/user-annotations/constant-in-expr-inherent-2.stderr b/tests/ui/nll/user-annotations/constant-in-expr-inherent-2.stderr
index 12065a85a..f164255ef 100644
--- a/tests/ui/nll/user-annotations/constant-in-expr-inherent-2.stderr
+++ b/tests/ui/nll/user-annotations/constant-in-expr-inherent-2.stderr
@@ -1,6 +1,8 @@
error[E0597]: `x` does not live long enough
--> $DIR/constant-in-expr-inherent-2.rs:23:9
|
+LL | let x = ();
+ | - binding `x` declared here
LL | FUN(&x);
| ----^^-
| | |
@@ -13,6 +15,9 @@ LL | }
error[E0597]: `x` does not live long enough
--> $DIR/constant-in-expr-inherent-2.rs:24:23
|
+LL | let x = ();
+ | - binding `x` declared here
+LL | FUN(&x);
LL | A::ASSOCIATED_FUN(&x);
| ------------------^^-
| | |
@@ -25,6 +30,9 @@ LL | }
error[E0597]: `x` does not live long enough
--> $DIR/constant-in-expr-inherent-2.rs:25:28
|
+LL | let x = ();
+ | - binding `x` declared here
+...
LL | B::ALSO_ASSOCIATED_FUN(&x);
| -----------------------^^-
| | |
@@ -37,6 +45,9 @@ LL | }
error[E0597]: `x` does not live long enough
--> $DIR/constant-in-expr-inherent-2.rs:26:31
|
+LL | let x = ();
+ | - binding `x` declared here
+...
LL | <_>::TRAIT_ASSOCIATED_FUN(&x);
| --------------------------^^-
| | |
diff --git a/tests/ui/nll/user-annotations/fns.stderr b/tests/ui/nll/user-annotations/fns.stderr
index e0640da39..8b53e138d 100644
--- a/tests/ui/nll/user-annotations/fns.stderr
+++ b/tests/ui/nll/user-annotations/fns.stderr
@@ -1,6 +1,8 @@
error[E0597]: `c` does not live long enough
--> $DIR/fns.rs:23:29
|
+LL | let c = 66;
+ | - binding `c` declared here
LL | some_fn::<&'static u32>(&c);
| ------------------------^^-
| | |
@@ -15,6 +17,7 @@ error[E0597]: `c` does not live long enough
LL | fn annot_reference_named_lifetime<'a>(_d: &'a u32) {
| -- lifetime `'a` defined here
LL | let c = 66;
+ | - binding `c` declared here
LL | some_fn::<&'a u32>(&c);
| -------------------^^-
| | |
diff --git a/tests/ui/nll/user-annotations/method-call.stderr b/tests/ui/nll/user-annotations/method-call.stderr
index 10447e45a..3803cbf77 100644
--- a/tests/ui/nll/user-annotations/method-call.stderr
+++ b/tests/ui/nll/user-annotations/method-call.stderr
@@ -1,6 +1,8 @@
error[E0597]: `c` does not live long enough
--> $DIR/method-call.rs:36:34
|
+LL | let c = 66;
+ | - binding `c` declared here
LL | a.method::<&'static u32>(b, &c);
| -----------------------------^^-
| | |
@@ -15,6 +17,8 @@ error[E0597]: `c` does not live long enough
LL | fn annot_reference_named_lifetime<'a>(_d: &'a u32) {
| -- lifetime `'a` defined here
...
+LL | let c = 66;
+ | - binding `c` declared here
LL | a.method::<&'a u32>(b, &c);
| ------------------------^^-
| | |
diff --git a/tests/ui/nll/user-annotations/method-ufcs-1.stderr b/tests/ui/nll/user-annotations/method-ufcs-1.stderr
index 962ddfd2b..c7c08c948 100644
--- a/tests/ui/nll/user-annotations/method-ufcs-1.stderr
+++ b/tests/ui/nll/user-annotations/method-ufcs-1.stderr
@@ -1,6 +1,9 @@
error[E0597]: `a` does not live long enough
--> $DIR/method-ufcs-1.rs:30:7
|
+LL | let a = 22;
+ | - binding `a` declared here
+...
LL | x(&a, b, c);
| --^^-------
| | |
@@ -14,6 +17,8 @@ error[E0597]: `a` does not live long enough
|
LL | fn annot_reference_named_lifetime<'a>(_d: &'a u32) {
| -- lifetime `'a` defined here
+LL | let a = 22;
+ | - binding `a` declared here
...
LL | <&'a u32 as Bazoom<_>>::method(&a, b, c);
| -------------------------------^^-------
diff --git a/tests/ui/nll/user-annotations/method-ufcs-2.stderr b/tests/ui/nll/user-annotations/method-ufcs-2.stderr
index 63d59905e..b7861a3bd 100644
--- a/tests/ui/nll/user-annotations/method-ufcs-2.stderr
+++ b/tests/ui/nll/user-annotations/method-ufcs-2.stderr
@@ -1,6 +1,9 @@
error[E0597]: `a` does not live long enough
--> $DIR/method-ufcs-2.rs:30:7
|
+LL | let a = 22;
+ | - binding `a` declared here
+...
LL | x(&a, b, c);
| --^^-------
| | |
@@ -14,7 +17,10 @@ error[E0597]: `b` does not live long enough
|
LL | fn annot_reference_named_lifetime<'a>(_d: &'a u32) {
| -- lifetime `'a` defined here
-...
+LL | let a = 22;
+LL | let b = 44;
+ | - binding `b` declared here
+LL | let c = 66;
LL | <_ as Bazoom<&'a u32>>::method(a, &b, c);
| ----------------------------------^^----
| | |
diff --git a/tests/ui/nll/user-annotations/method-ufcs-3.stderr b/tests/ui/nll/user-annotations/method-ufcs-3.stderr
index e7851833e..8cb995a03 100644
--- a/tests/ui/nll/user-annotations/method-ufcs-3.stderr
+++ b/tests/ui/nll/user-annotations/method-ufcs-3.stderr
@@ -1,6 +1,8 @@
error[E0597]: `c` does not live long enough
--> $DIR/method-ufcs-3.rs:36:53
|
+LL | let c = 66;
+ | - binding `c` declared here
LL | <_ as Bazoom<_>>::method::<&'static u32>(&a, b, &c);
| ------------------------------------------------^^-
| | |
@@ -15,6 +17,8 @@ error[E0597]: `c` does not live long enough
LL | fn annot_reference_named_lifetime<'a>(_d: &'a u32) {
| -- lifetime `'a` defined here
...
+LL | let c = 66;
+ | - binding `c` declared here
LL | <_ as Bazoom<_>>::method::<&'a u32>(&a, b, &c);
| -------------------------------------------^^-
| | |
diff --git a/tests/ui/nll/user-annotations/method-ufcs-inherent-1.stderr b/tests/ui/nll/user-annotations/method-ufcs-inherent-1.stderr
index 94861babd..fb26b8d09 100644
--- a/tests/ui/nll/user-annotations/method-ufcs-inherent-1.stderr
+++ b/tests/ui/nll/user-annotations/method-ufcs-inherent-1.stderr
@@ -4,6 +4,7 @@ error[E0597]: `v` does not live long enough
LL | fn foo<'a>() {
| -- lifetime `'a` defined here
LL | let v = 22;
+ | - binding `v` declared here
LL | let x = A::<'a>::new(&v, 22);
| -------------^^-----
| | |
diff --git a/tests/ui/nll/user-annotations/method-ufcs-inherent-2.stderr b/tests/ui/nll/user-annotations/method-ufcs-inherent-2.stderr
index 06f20d9b2..03b97447e 100644
--- a/tests/ui/nll/user-annotations/method-ufcs-inherent-2.stderr
+++ b/tests/ui/nll/user-annotations/method-ufcs-inherent-2.stderr
@@ -4,6 +4,7 @@ error[E0597]: `v` does not live long enough
LL | fn foo<'a>() {
| -- lifetime `'a` defined here
LL | let v = 22;
+ | - binding `v` declared here
LL | let x = A::<'a>::new::<&'a u32>(&v, &v);
| ------------------------^^-----
| | |
@@ -19,6 +20,7 @@ error[E0597]: `v` does not live long enough
LL | fn foo<'a>() {
| -- lifetime `'a` defined here
LL | let v = 22;
+ | - binding `v` declared here
LL | let x = A::<'a>::new::<&'a u32>(&v, &v);
| ----------------------------^^-
| | |
diff --git a/tests/ui/nll/user-annotations/method-ufcs-inherent-3.stderr b/tests/ui/nll/user-annotations/method-ufcs-inherent-3.stderr
index 4ad61dc81..69dd1d1aa 100644
--- a/tests/ui/nll/user-annotations/method-ufcs-inherent-3.stderr
+++ b/tests/ui/nll/user-annotations/method-ufcs-inherent-3.stderr
@@ -4,6 +4,7 @@ error[E0597]: `v` does not live long enough
LL | fn foo<'a>() {
| -- lifetime `'a` defined here
LL | let v = 22;
+ | - binding `v` declared here
LL | let x = <A<'a>>::new(&v, 22);
| -------------^^-----
| | |
diff --git a/tests/ui/nll/user-annotations/method-ufcs-inherent-4.stderr b/tests/ui/nll/user-annotations/method-ufcs-inherent-4.stderr
index 0f83e99cd..66d82bb49 100644
--- a/tests/ui/nll/user-annotations/method-ufcs-inherent-4.stderr
+++ b/tests/ui/nll/user-annotations/method-ufcs-inherent-4.stderr
@@ -4,6 +4,7 @@ error[E0597]: `v` does not live long enough
LL | fn foo<'a>() {
| -- lifetime `'a` defined here
LL | let v = 22;
+ | - binding `v` declared here
LL | let x = <A<'a>>::new::<&'a u32>(&v, &v);
| ------------------------^^-----
| | |
@@ -19,6 +20,7 @@ error[E0597]: `v` does not live long enough
LL | fn foo<'a>() {
| -- lifetime `'a` defined here
LL | let v = 22;
+ | - binding `v` declared here
LL | let x = <A<'a>>::new::<&'a u32>(&v, &v);
| ----------------------------^^-
| | |
diff --git a/tests/ui/nll/user-annotations/normalization.stderr b/tests/ui/nll/user-annotations/normalization.stderr
index 975cb4b66..acc3a1800 100644
--- a/tests/ui/nll/user-annotations/normalization.stderr
+++ b/tests/ui/nll/user-annotations/normalization.stderr
@@ -1,6 +1,8 @@
error[E0597]: `a` does not live long enough
--> $DIR/normalization.rs:10:31
|
+LL | let a = 22;
+ | - binding `a` declared here
LL | let _: <() as Foo>::Out = &a;
| ---------------- ^^ borrowed value does not live long enough
| |
@@ -12,6 +14,8 @@ LL | }
error[E0597]: `a` does not live long enough
--> $DIR/normalization.rs:13:40
|
+LL | let a = 22;
+ | - binding `a` declared here
LL | let _: <&'static () as Foo>::Out = &a;
| ------------------------- ^^ borrowed value does not live long enough
| |
diff --git a/tests/ui/nll/user-annotations/pattern_substs_on_brace_enum_variant.stderr b/tests/ui/nll/user-annotations/pattern_substs_on_brace_enum_variant.stderr
index a97e7a9fd..3e7969e11 100644
--- a/tests/ui/nll/user-annotations/pattern_substs_on_brace_enum_variant.stderr
+++ b/tests/ui/nll/user-annotations/pattern_substs_on_brace_enum_variant.stderr
@@ -1,6 +1,8 @@
error[E0597]: `y` does not live long enough
--> $DIR/pattern_substs_on_brace_enum_variant.rs:7:33
|
+LL | let y = 22;
+ | - binding `y` declared here
LL | let foo = Foo::Bar { field: &y };
| ^^ borrowed value does not live long enough
LL |
@@ -12,6 +14,8 @@ LL | }
error[E0597]: `y` does not live long enough
--> $DIR/pattern_substs_on_brace_enum_variant.rs:14:33
|
+LL | let y = 22;
+ | - binding `y` declared here
LL | let foo = Foo::Bar { field: &y };
| ^^ borrowed value does not live long enough
...
diff --git a/tests/ui/nll/user-annotations/pattern_substs_on_brace_struct.stderr b/tests/ui/nll/user-annotations/pattern_substs_on_brace_struct.stderr
index 408d7c2a5..89a1e9545 100644
--- a/tests/ui/nll/user-annotations/pattern_substs_on_brace_struct.stderr
+++ b/tests/ui/nll/user-annotations/pattern_substs_on_brace_struct.stderr
@@ -1,6 +1,8 @@
error[E0597]: `y` does not live long enough
--> $DIR/pattern_substs_on_brace_struct.rs:5:28
|
+LL | let y = 22;
+ | - binding `y` declared here
LL | let foo = Foo { field: &y };
| ^^ borrowed value does not live long enough
LL |
@@ -12,6 +14,8 @@ LL | }
error[E0597]: `y` does not live long enough
--> $DIR/pattern_substs_on_brace_struct.rs:12:28
|
+LL | let y = 22;
+ | - binding `y` declared here
LL | let foo = Foo { field: &y };
| ^^ borrowed value does not live long enough
...
diff --git a/tests/ui/nll/user-annotations/pattern_substs_on_tuple_enum_variant.stderr b/tests/ui/nll/user-annotations/pattern_substs_on_tuple_enum_variant.stderr
index 920c906f6..8efeecc77 100644
--- a/tests/ui/nll/user-annotations/pattern_substs_on_tuple_enum_variant.stderr
+++ b/tests/ui/nll/user-annotations/pattern_substs_on_tuple_enum_variant.stderr
@@ -1,6 +1,8 @@
error[E0597]: `y` does not live long enough
--> $DIR/pattern_substs_on_tuple_enum_variant.rs:7:24
|
+LL | let y = 22;
+ | - binding `y` declared here
LL | let foo = Foo::Bar(&y);
| ^^ borrowed value does not live long enough
LL |
@@ -12,6 +14,8 @@ LL | }
error[E0597]: `y` does not live long enough
--> $DIR/pattern_substs_on_tuple_enum_variant.rs:14:24
|
+LL | let y = 22;
+ | - binding `y` declared here
LL | let foo = Foo::Bar(&y);
| ^^ borrowed value does not live long enough
...
diff --git a/tests/ui/nll/user-annotations/pattern_substs_on_tuple_struct.stderr b/tests/ui/nll/user-annotations/pattern_substs_on_tuple_struct.stderr
index 3f01638d8..d7f1dac88 100644
--- a/tests/ui/nll/user-annotations/pattern_substs_on_tuple_struct.stderr
+++ b/tests/ui/nll/user-annotations/pattern_substs_on_tuple_struct.stderr
@@ -1,6 +1,8 @@
error[E0597]: `y` does not live long enough
--> $DIR/pattern_substs_on_tuple_struct.rs:5:19
|
+LL | let y = 22;
+ | - binding `y` declared here
LL | let foo = Foo(&y);
| ^^ borrowed value does not live long enough
LL |
@@ -12,6 +14,8 @@ LL | }
error[E0597]: `y` does not live long enough
--> $DIR/pattern_substs_on_tuple_struct.rs:12:19
|
+LL | let y = 22;
+ | - binding `y` declared here
LL | let foo = Foo(&y);
| ^^ borrowed value does not live long enough
...
diff --git a/tests/ui/nll/user-annotations/patterns.stderr b/tests/ui/nll/user-annotations/patterns.stderr
index de6f8f80f..8bb714f1d 100644
--- a/tests/ui/nll/user-annotations/patterns.stderr
+++ b/tests/ui/nll/user-annotations/patterns.stderr
@@ -1,6 +1,8 @@
error[E0597]: `x` does not live long enough
--> $DIR/patterns.rs:6:9
|
+LL | let x = 22;
+ | - binding `x` declared here
LL | let y: &'static u32;
| ------------ type annotation requires that `x` is borrowed for `'static`
LL | y = &x;
@@ -11,6 +13,8 @@ LL | }
error[E0597]: `x` does not live long enough
--> $DIR/patterns.rs:14:9
|
+LL | let x = 22;
+ | - binding `x` declared here
LL | let (y, z): (&'static u32, &'static u32);
| ---------------------------- type annotation requires that `x` is borrowed for `'static`
LL | y = &x;
@@ -21,6 +25,8 @@ LL | }
error[E0597]: `x` does not live long enough
--> $DIR/patterns.rs:20:13
|
+LL | let x = 22;
+ | - binding `x` declared here
LL | let y = &x;
| ^^ borrowed value does not live long enough
LL | let ref z: &'static u32 = y;
@@ -32,6 +38,8 @@ LL | }
error[E0597]: `x` does not live long enough
--> $DIR/patterns.rs:39:9
|
+LL | let x = 22;
+ | - binding `x` declared here
LL | let Single { value: y }: Single<&'static u32>;
| -------------------- type annotation requires that `x` is borrowed for `'static`
LL | y = &x;
@@ -42,6 +50,8 @@ LL | }
error[E0597]: `x` does not live long enough
--> $DIR/patterns.rs:51:10
|
+LL | let x = 22;
+ | - binding `x` declared here
LL | let Single2 { value: mut _y }: Single2<StaticU32>;
| ------------------ type annotation requires that `x` is borrowed for `'static`
LL | _y = &x;
@@ -52,6 +62,8 @@ LL | }
error[E0597]: `x` does not live long enough
--> $DIR/patterns.rs:56:27
|
+LL | let x = 22;
+ | - binding `x` declared here
LL | let y: &'static u32 = &x;
| ------------ ^^ borrowed value does not live long enough
| |
@@ -62,6 +74,8 @@ LL | }
error[E0597]: `x` does not live long enough
--> $DIR/patterns.rs:61:27
|
+LL | let x = 22;
+ | - binding `x` declared here
LL | let _: &'static u32 = &x;
| ------------ ^^ borrowed value does not live long enough
| |
@@ -100,6 +114,8 @@ LL | let (_a, b): (Vec<&'static String>, _) = (vec![&String::new()], 44);
error[E0597]: `x` does not live long enough
--> $DIR/patterns.rs:75:40
|
+LL | let x = 22;
+ | - binding `x` declared here
LL | let (_, _): (&'static u32, u32) = (&x, 44);
| ------------------- ^^ borrowed value does not live long enough
| |
@@ -110,6 +126,8 @@ LL | }
error[E0597]: `x` does not live long enough
--> $DIR/patterns.rs:80:40
|
+LL | let x = 22;
+ | - binding `x` declared here
LL | let (y, _): (&'static u32, u32) = (&x, 44);
| ------------------- ^^ borrowed value does not live long enough
| |
@@ -120,6 +138,8 @@ LL | }
error[E0597]: `x` does not live long enough
--> $DIR/patterns.rs:85:69
|
+LL | let x = 22;
+ | - binding `x` declared here
LL | let Single { value: y }: Single<&'static u32> = Single { value: &x };
| -------------------- ^^ borrowed value does not live long enough
| |
@@ -130,6 +150,8 @@ LL | }
error[E0597]: `x` does not live long enough
--> $DIR/patterns.rs:90:69
|
+LL | let x = 22;
+ | - binding `x` declared here
LL | let Single { value: _ }: Single<&'static u32> = Single { value: &x };
| -------------------- ^^ borrowed value does not live long enough
| |
@@ -140,6 +162,8 @@ LL | }
error[E0597]: `x` does not live long enough
--> $DIR/patterns.rs:98:17
|
+LL | let x = 22;
+ | - binding `x` declared here
LL | let Double { value1: _, value2: _ }: Double<&'static u32> = Double {
| -------------------- type annotation requires that `x` is borrowed for `'static`
LL | value1: &x,
diff --git a/tests/ui/nll/user-annotations/promoted-annotation.stderr b/tests/ui/nll/user-annotations/promoted-annotation.stderr
index cb99a6a36..132a00ba4 100644
--- a/tests/ui/nll/user-annotations/promoted-annotation.stderr
+++ b/tests/ui/nll/user-annotations/promoted-annotation.stderr
@@ -4,6 +4,7 @@ error[E0597]: `x` does not live long enough
LL | fn foo<'a>() {
| -- lifetime `'a` defined here
LL | let x = 0;
+ | - binding `x` declared here
LL | let f = &drop::<&'a i32>;
| ---------------- assignment requires that `x` is borrowed for `'a`
LL | f(&x);
diff --git a/tests/ui/nll/user-annotations/type_ascription_static_lifetime.stderr b/tests/ui/nll/user-annotations/type_ascription_static_lifetime.stderr
index ccbf3c1d9..766877f88 100644
--- a/tests/ui/nll/user-annotations/type_ascription_static_lifetime.stderr
+++ b/tests/ui/nll/user-annotations/type_ascription_static_lifetime.stderr
@@ -1,6 +1,8 @@
error[E0597]: `x` does not live long enough
--> $DIR/type_ascription_static_lifetime.rs:6:33
|
+LL | let x = 22_u32;
+ | - binding `x` declared here
LL | let y: &u32 = type_ascribe!(&x, &'static u32);
| --------------^^---------------
| | |
diff --git a/tests/ui/noexporttypeexe.rs b/tests/ui/noexporttypeexe.rs
index 964ac9a30..d473ad6c9 100644
--- a/tests/ui/noexporttypeexe.rs
+++ b/tests/ui/noexporttypeexe.rs
@@ -11,5 +11,5 @@ fn main() {
//~^ ERROR mismatched types
//~| expected type `isize`
//~| found enum `Option<isize>`
- //~| expected `isize`, found enum `Option`
+ //~| expected `isize`, found `Option<isize>`
}
diff --git a/tests/ui/noexporttypeexe.stderr b/tests/ui/noexporttypeexe.stderr
index 7fc239613..26bafd31d 100644
--- a/tests/ui/noexporttypeexe.stderr
+++ b/tests/ui/noexporttypeexe.stderr
@@ -2,7 +2,7 @@ error[E0308]: mismatched types
--> $DIR/noexporttypeexe.rs:10:18
|
LL | let x: isize = noexporttypelib::foo();
- | ----- ^^^^^^^^^^^^^^^^^^^^^^ expected `isize`, found enum `Option`
+ | ----- ^^^^^^^^^^^^^^^^^^^^^^ expected `isize`, found `Option<isize>`
| |
| expected due to this
|
diff --git a/tests/ui/numbers-arithmetic/issue-105626.rs b/tests/ui/numbers-arithmetic/issue-105626.rs
new file mode 100644
index 000000000..f97edd510
--- /dev/null
+++ b/tests/ui/numbers-arithmetic/issue-105626.rs
@@ -0,0 +1,17 @@
+// run-pass
+// only-x86
+// min-system-llvm-version: 16
+// compile-flags: -Ctarget-feature=+sse2
+
+use std::hint::black_box;
+
+fn main() {
+ let n: i64 = black_box(0x3fffffdfffffff);
+ let r = f32::from_bits(0x5a7fffff);
+
+ assert_ne!((n as f64) as f32, n as f32);
+
+ // FIXME: these assertions fail if only x87 is enabled
+ assert_eq!(n as i64 as f32, r);
+ assert_eq!(n as u64 as f32, r);
+}
diff --git a/tests/ui/numbers-arithmetic/next-power-of-two-overflow-debug.rs b/tests/ui/numbers-arithmetic/next-power-of-two-overflow-debug.rs
index 79d78da33..0e487a700 100644
--- a/tests/ui/numbers-arithmetic/next-power-of-two-overflow-debug.rs
+++ b/tests/ui/numbers-arithmetic/next-power-of-two-overflow-debug.rs
@@ -1,5 +1,5 @@
// run-pass
-// compile-flags: -C debug_assertions=yes
+// compile-flags: -C debug_assertions=true
// needs-unwind
// ignore-emscripten dies with an LLVM error
diff --git a/tests/ui/object-pointer-types.stderr b/tests/ui/object-pointer-types.stderr
index a477425ed..2c8df3b61 100644
--- a/tests/ui/object-pointer-types.stderr
+++ b/tests/ui/object-pointer-types.stderr
@@ -20,7 +20,7 @@ error[E0599]: no method named `managed` found for struct `Box<(dyn Foo + 'static
--> $DIR/object-pointer-types.rs:23:7
|
LL | x.managed();
- | ^^^^^^^ method not found in `Box<(dyn Foo + 'static)>`
+ | ^^^^^^^ method not found in `Box<dyn Foo>`
error: aborting due to 3 previous errors
diff --git a/tests/ui/object-safety/object-safety-supertrait-mentions-GAT.stderr b/tests/ui/object-safety/object-safety-supertrait-mentions-GAT.stderr
index f05b0cd65..40429fe75 100644
--- a/tests/ui/object-safety/object-safety-supertrait-mentions-GAT.stderr
+++ b/tests/ui/object-safety/object-safety-supertrait-mentions-GAT.stderr
@@ -1,5 +1,10 @@
error[E0311]: the parameter type `Self` may not live long enough
|
+note: the parameter type `Self` must be valid for the lifetime `'a` as defined here...
+ --> $DIR/object-safety-supertrait-mentions-GAT.rs:9:26
+ |
+LL | trait SuperTrait<T>: for<'a> GatTrait<Gat<'a> = T> {
+ | ^^
= help: consider adding an explicit lifetime bound `Self: 'a`...
= note: ...so that the type `Self` will meet its required lifetime bounds...
note: ...that is required by this bound
diff --git a/tests/ui/optimization-remark.rs b/tests/ui/optimization-remark.rs
index d4b39c670..4f651b1dc 100644
--- a/tests/ui/optimization-remark.rs
+++ b/tests/ui/optimization-remark.rs
@@ -1,6 +1,5 @@
// build-pass
// ignore-pass
-// min-llvm-version: 14.0.0
// revisions: all inline merge1 merge2
// compile-flags: --crate-type=lib -Cdebuginfo=1 -Copt-level=2
//
diff --git a/tests/ui/or-patterns/already-bound-name.stderr b/tests/ui/or-patterns/already-bound-name.stderr
index 368782c1e..795c46acb 100644
--- a/tests/ui/or-patterns/already-bound-name.stderr
+++ b/tests/ui/or-patterns/already-bound-name.stderr
@@ -88,7 +88,7 @@ error[E0308]: mismatched types
LL | let (B(A(a, _) | B(a)) | A(a, A(a, _) | B(a))) = B(B(1));
| - ^ ------- this expression has type `E<E<{integer}>>`
| | |
- | | expected integer, found enum `E`
+ | | expected integer, found `E<{integer}>`
| first introduced with type `{integer}` here
|
= note: expected type `{integer}`
diff --git a/tests/ui/or-patterns/nested-undelimited-precedence.stderr b/tests/ui/or-patterns/nested-undelimited-precedence.stderr
index 2e25d8b3e..5a63e621f 100644
--- a/tests/ui/or-patterns/nested-undelimited-precedence.stderr
+++ b/tests/ui/or-patterns/nested-undelimited-precedence.stderr
@@ -42,7 +42,7 @@ error[E0308]: mismatched types
LL | let &A(_) | B(_): F = A(3);
| ^^^^^ - expected due to this
| |
- | expected enum `F`, found reference
+ | expected `F`, found `&_`
|
= note: expected enum `F`
found reference `&_`
@@ -53,7 +53,7 @@ error[E0308]: mismatched types
LL | let &&A(_) | B(_): F = A(3);
| ^^^^^^ - expected due to this
| |
- | expected enum `F`, found reference
+ | expected `F`, found `&_`
|
= note: expected enum `F`
found reference `&_`
@@ -64,7 +64,7 @@ error[E0308]: mismatched types
LL | let &mut A(_) | B(_): F = A(3);
| ^^^^^^^^^ - expected due to this
| |
- | expected enum `F`, found `&mut _`
+ | expected `F`, found `&mut _`
|
= note: expected enum `F`
found mutable reference `&mut _`
@@ -75,7 +75,7 @@ error[E0308]: mismatched types
LL | let &&mut A(_) | B(_): F = A(3);
| ^^^^^^^^^^ - expected due to this
| |
- | expected enum `F`, found reference
+ | expected `F`, found `&_`
|
= note: expected enum `F`
found reference `&_`
diff --git a/tests/ui/packed/issue-27060-rpass.rs b/tests/ui/packed/issue-27060-rpass.rs
deleted file mode 100644
index d9159f666..000000000
--- a/tests/ui/packed/issue-27060-rpass.rs
+++ /dev/null
@@ -1,23 +0,0 @@
-// run-pass
-#![allow(dead_code)]
-#[repr(packed)]
-pub struct Good {
- data: &'static u32,
- data2: [&'static u32; 2],
- aligned: [u8; 32],
-}
-
-// kill this test when that turns to a hard error
-#[allow(unaligned_references)]
-fn main() {
- let good = Good { data: &0, data2: [&0, &0], aligned: [0; 32] };
-
- let _ = &good.data; // ok
- let _ = &good.data2[0]; // ok
-
- let _ = &good.data;
- let _ = &good.data2[0];
- let _ = &*good.data; // ok, behind a pointer
- let _ = &good.aligned; // ok, has align 1
- let _ = &good.aligned[2]; // ok, has align 1
-}
diff --git a/tests/ui/packed/issue-27060-rpass.stderr b/tests/ui/packed/issue-27060-rpass.stderr
deleted file mode 100644
index adf9ae9f5..000000000
--- a/tests/ui/packed/issue-27060-rpass.stderr
+++ /dev/null
@@ -1,68 +0,0 @@
-Future incompatibility report: Future breakage diagnostic:
-warning: reference to packed field is unaligned
- --> $DIR/issue-27060-rpass.rs:15:13
- |
-LL | let _ = &good.data; // ok
- | ^^^^^^^^^^
- |
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523>
- = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
- = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
-note: the lint level is defined here
- --> $DIR/issue-27060-rpass.rs:11:9
- |
-LL | #[allow(unaligned_references)]
- | ^^^^^^^^^^^^^^^^^^^^
-
-Future breakage diagnostic:
-warning: reference to packed field is unaligned
- --> $DIR/issue-27060-rpass.rs:16:13
- |
-LL | let _ = &good.data2[0]; // ok
- | ^^^^^^^^^^^^^^
- |
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523>
- = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
- = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
-note: the lint level is defined here
- --> $DIR/issue-27060-rpass.rs:11:9
- |
-LL | #[allow(unaligned_references)]
- | ^^^^^^^^^^^^^^^^^^^^
-
-Future breakage diagnostic:
-warning: reference to packed field is unaligned
- --> $DIR/issue-27060-rpass.rs:18:13
- |
-LL | let _ = &good.data;
- | ^^^^^^^^^^
- |
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523>
- = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
- = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
-note: the lint level is defined here
- --> $DIR/issue-27060-rpass.rs:11:9
- |
-LL | #[allow(unaligned_references)]
- | ^^^^^^^^^^^^^^^^^^^^
-
-Future breakage diagnostic:
-warning: reference to packed field is unaligned
- --> $DIR/issue-27060-rpass.rs:19:13
- |
-LL | let _ = &good.data2[0];
- | ^^^^^^^^^^^^^^
- |
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523>
- = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
- = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
-note: the lint level is defined here
- --> $DIR/issue-27060-rpass.rs:11:9
- |
-LL | #[allow(unaligned_references)]
- | ^^^^^^^^^^^^^^^^^^^^
-
diff --git a/tests/ui/packed/issue-27060.rs b/tests/ui/packed/issue-27060.rs
index 886a00239..a0e944caa 100644
--- a/tests/ui/packed/issue-27060.rs
+++ b/tests/ui/packed/issue-27060.rs
@@ -13,14 +13,10 @@ fn main() {
};
let _ = &good.data; //~ ERROR reference to packed field
- //~| hard error
let _ = &good.data2[0]; //~ ERROR reference to packed field
- //~| hard error
let _ = &good.data; //~ ERROR reference to packed field
- //~| hard error
let _ = &good.data2[0]; //~ ERROR reference to packed field
- //~| hard error
let _ = &*good.data; // ok, behind a pointer
let _ = &good.aligned; // ok, has align 1
let _ = &good.aligned[2]; // ok, has align 1
diff --git a/tests/ui/packed/issue-27060.stderr b/tests/ui/packed/issue-27060.stderr
index 85e08fa02..b4753284f 100644
--- a/tests/ui/packed/issue-27060.stderr
+++ b/tests/ui/packed/issue-27060.stderr
@@ -1,99 +1,39 @@
-error: reference to packed field is unaligned
+error[E0793]: reference to packed field is unaligned
--> $DIR/issue-27060.rs:15:13
|
LL | let _ = &good.data;
| ^^^^^^^^^^
|
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523>
= note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
= help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
- = note: `#[deny(unaligned_references)]` on by default
-error: reference to packed field is unaligned
- --> $DIR/issue-27060.rs:17:13
+error[E0793]: reference to packed field is unaligned
+ --> $DIR/issue-27060.rs:16:13
|
LL | let _ = &good.data2[0];
| ^^^^^^^^^^^^^^
|
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523>
= note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
= help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
-error: reference to packed field is unaligned
- --> $DIR/issue-27060.rs:20:13
+error[E0793]: reference to packed field is unaligned
+ --> $DIR/issue-27060.rs:18:13
|
LL | let _ = &good.data;
| ^^^^^^^^^^
|
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523>
= note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
= help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
-error: reference to packed field is unaligned
- --> $DIR/issue-27060.rs:22:13
+error[E0793]: reference to packed field is unaligned
+ --> $DIR/issue-27060.rs:19:13
|
LL | let _ = &good.data2[0];
| ^^^^^^^^^^^^^^
|
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523>
= note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
= help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
error: aborting due to 4 previous errors
-Future incompatibility report: Future breakage diagnostic:
-error: reference to packed field is unaligned
- --> $DIR/issue-27060.rs:15:13
- |
-LL | let _ = &good.data;
- | ^^^^^^^^^^
- |
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523>
- = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
- = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
- = note: `#[deny(unaligned_references)]` on by default
-
-Future breakage diagnostic:
-error: reference to packed field is unaligned
- --> $DIR/issue-27060.rs:17:13
- |
-LL | let _ = &good.data2[0];
- | ^^^^^^^^^^^^^^
- |
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523>
- = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
- = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
- = note: `#[deny(unaligned_references)]` on by default
-
-Future breakage diagnostic:
-error: reference to packed field is unaligned
- --> $DIR/issue-27060.rs:20:13
- |
-LL | let _ = &good.data;
- | ^^^^^^^^^^
- |
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523>
- = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
- = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
- = note: `#[deny(unaligned_references)]` on by default
-
-Future breakage diagnostic:
-error: reference to packed field is unaligned
- --> $DIR/issue-27060.rs:22:13
- |
-LL | let _ = &good.data2[0];
- | ^^^^^^^^^^^^^^
- |
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523>
- = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
- = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
- = note: `#[deny(unaligned_references)]` on by default
-
+For more information about this error, try `rustc --explain E0793`.
diff --git a/tests/ui/packed/packed-struct-borrow-element-64bit.rs b/tests/ui/packed/packed-struct-borrow-element-64bit.rs
index 00bddfe40..63315ea66 100644
--- a/tests/ui/packed/packed-struct-borrow-element-64bit.rs
+++ b/tests/ui/packed/packed-struct-borrow-element-64bit.rs
@@ -1,4 +1,3 @@
-// run-pass (note: this is spec-UB, but it works for now)
// ignore-32bit (needs `usize` to be 8-aligned to reproduce all the errors below)
#![allow(dead_code)]
// ignore-emscripten weird assertion?
@@ -9,10 +8,8 @@ struct Foo4C {
baz: usize
}
-#[warn(unaligned_references)]
pub fn main() {
let foo = Foo4C { bar: 1, baz: 2 };
- let brw = &foo.baz; //~WARN reference to packed field is unaligned
- //~^ previously accepted
+ let brw = &foo.baz; //~ERROR reference to packed field is unaligned
assert_eq!(*brw, 2);
}
diff --git a/tests/ui/packed/packed-struct-borrow-element-64bit.stderr b/tests/ui/packed/packed-struct-borrow-element-64bit.stderr
index fb2f5615c..32943b0f0 100644
--- a/tests/ui/packed/packed-struct-borrow-element-64bit.stderr
+++ b/tests/ui/packed/packed-struct-borrow-element-64bit.stderr
@@ -1,35 +1,12 @@
-warning: reference to packed field is unaligned
- --> $DIR/packed-struct-borrow-element-64bit.rs:15:15
+error[E0793]: reference to packed field is unaligned
+ --> $DIR/packed-struct-borrow-element-64bit.rs:13:15
|
LL | let brw = &foo.baz;
| ^^^^^^^^
|
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523>
= note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
= help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
-note: the lint level is defined here
- --> $DIR/packed-struct-borrow-element-64bit.rs:12:8
- |
-LL | #[warn(unaligned_references)]
- | ^^^^^^^^^^^^^^^^^^^^
-
-warning: 1 warning emitted
-Future incompatibility report: Future breakage diagnostic:
-warning: reference to packed field is unaligned
- --> $DIR/packed-struct-borrow-element-64bit.rs:15:15
- |
-LL | let brw = &foo.baz;
- | ^^^^^^^^
- |
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523>
- = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
- = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
-note: the lint level is defined here
- --> $DIR/packed-struct-borrow-element-64bit.rs:12:8
- |
-LL | #[warn(unaligned_references)]
- | ^^^^^^^^^^^^^^^^^^^^
+error: aborting due to previous error
+For more information about this error, try `rustc --explain E0793`.
diff --git a/tests/ui/packed/packed-struct-borrow-element.rs b/tests/ui/packed/packed-struct-borrow-element.rs
index a6ee90cef..6cbeca44b 100644
--- a/tests/ui/packed/packed-struct-borrow-element.rs
+++ b/tests/ui/packed/packed-struct-borrow-element.rs
@@ -1,4 +1,3 @@
-// run-pass (note: this is spec-UB, but it works for now)
#![allow(dead_code)]
// ignore-emscripten weird assertion?
@@ -20,15 +19,12 @@ struct Foo4C {
baz: usize
}
-#[warn(unaligned_references)]
pub fn main() {
let foo = Foo1 { bar: 1, baz: 2 };
- let brw = &foo.baz; //~WARN reference to packed field is unaligned
- //~^ previously accepted
+ let brw = &foo.baz; //~ERROR reference to packed field is unaligned
assert_eq!(*brw, 2);
let foo = Foo2 { bar: 1, baz: 2 };
- let brw = &foo.baz; //~WARN reference to packed field is unaligned
- //~^ previously accepted
+ let brw = &foo.baz; //~ERROR reference to packed field is unaligned
assert_eq!(*brw, 2);
}
diff --git a/tests/ui/packed/packed-struct-borrow-element.stderr b/tests/ui/packed/packed-struct-borrow-element.stderr
index 75d55c4f6..29d867fc5 100644
--- a/tests/ui/packed/packed-struct-borrow-element.stderr
+++ b/tests/ui/packed/packed-struct-borrow-element.stderr
@@ -1,63 +1,21 @@
-warning: reference to packed field is unaligned
- --> $DIR/packed-struct-borrow-element.rs:26:15
+error[E0793]: reference to packed field is unaligned
+ --> $DIR/packed-struct-borrow-element.rs:24:15
|
LL | let brw = &foo.baz;
| ^^^^^^^^
|
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523>
= note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
= help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
-note: the lint level is defined here
- --> $DIR/packed-struct-borrow-element.rs:23:8
- |
-LL | #[warn(unaligned_references)]
- | ^^^^^^^^^^^^^^^^^^^^
-warning: reference to packed field is unaligned
- --> $DIR/packed-struct-borrow-element.rs:31:15
+error[E0793]: reference to packed field is unaligned
+ --> $DIR/packed-struct-borrow-element.rs:28:15
|
LL | let brw = &foo.baz;
| ^^^^^^^^
|
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523>
= note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
= help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
-warning: 2 warnings emitted
-
-Future incompatibility report: Future breakage diagnostic:
-warning: reference to packed field is unaligned
- --> $DIR/packed-struct-borrow-element.rs:26:15
- |
-LL | let brw = &foo.baz;
- | ^^^^^^^^
- |
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523>
- = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
- = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
-note: the lint level is defined here
- --> $DIR/packed-struct-borrow-element.rs:23:8
- |
-LL | #[warn(unaligned_references)]
- | ^^^^^^^^^^^^^^^^^^^^
-
-Future breakage diagnostic:
-warning: reference to packed field is unaligned
- --> $DIR/packed-struct-borrow-element.rs:31:15
- |
-LL | let brw = &foo.baz;
- | ^^^^^^^^
- |
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523>
- = note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
- = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
-note: the lint level is defined here
- --> $DIR/packed-struct-borrow-element.rs:23:8
- |
-LL | #[warn(unaligned_references)]
- | ^^^^^^^^^^^^^^^^^^^^
+error: aborting due to 2 previous errors
+For more information about this error, try `rustc --explain E0793`.
diff --git a/tests/ui/panics/default-backtrace-ice.stderr b/tests/ui/panics/default-backtrace-ice.stderr
index a0025d7e2..4bd4780e2 100644
--- a/tests/ui/panics/default-backtrace-ice.stderr
+++ b/tests/ui/panics/default-backtrace-ice.stderr
@@ -4,9 +4,7 @@ LL | fn main() { missing_ident; }
stack backtrace:
-error: internal compiler error: unexpected panic
-
-
+error: the compiler unexpectedly panicked. this is a bug.
@@ -15,4 +13,5 @@ error: internal compiler error: unexpected panic
query stack during panic:
+#0 [resolver_for_lowering] getting the resolver for lowering
end of query stack
diff --git a/tests/ui/parser/anon-enums-are-ambiguous.rs b/tests/ui/parser/anon-enums-are-ambiguous.rs
new file mode 100644
index 000000000..b0173cf98
--- /dev/null
+++ b/tests/ui/parser/anon-enums-are-ambiguous.rs
@@ -0,0 +1,26 @@
+// check-pass
+
+macro_rules! test_expr {
+ ($expr:expr) => {};
+}
+
+macro_rules! test_ty {
+ ($a:ty | $b:ty) => {};
+}
+
+fn main() {
+ test_expr!(a as fn() -> B | C);
+ // Do not break the `|` operator.
+
+ test_expr!(|_: fn() -> B| C | D);
+ // Do not break `-> Ret` in closure args.
+
+ test_ty!(A | B);
+ // We can't support anon enums in arbitrary positions.
+
+ test_ty!(fn() -> A | B);
+ // Don't break fn ptrs.
+
+ test_ty!(impl Fn() -> A | B);
+ // Don't break parenthesized generics.
+}
diff --git a/tests/ui/parser/bastion-of-the-turbofish.rs b/tests/ui/parser/bastion-of-the-turbofish.rs
index e12857008..7ceea676d 100644
--- a/tests/ui/parser/bastion-of-the-turbofish.rs
+++ b/tests/ui/parser/bastion-of-the-turbofish.rs
@@ -34,7 +34,7 @@
// See https://github.com/rust-lang/rust/pull/53562
// and https://github.com/rust-lang/rfcs/pull/2527
-// and https://twitter.com/garblefart/status/1393236602856611843
+// and https://web.archive.org/web/20211010063452/https://twitter.com/garblefart/status/1393236602856611843
// for context.
fn main() {
diff --git a/tests/ui/parser/deli-ident-issue-1.rs b/tests/ui/parser/deli-ident-issue-1.rs
new file mode 100644
index 000000000..224ee6c09
--- /dev/null
+++ b/tests/ui/parser/deli-ident-issue-1.rs
@@ -0,0 +1,22 @@
+#![feature(let_chains)]
+trait Demo {}
+
+impl dyn Demo {
+ pub fn report(&self) -> u32 {
+ let sum = |a: u32,
+ b: u32,
+ c: u32| {
+ a + b + c
+ };
+ sum(1, 2, 3)
+ }
+
+ fn check(&self, val: Option<u32>, num: Option<u32>) {
+ if let Some(b) = val
+ && let Some(c) = num {
+ && b == c {
+ }
+ }
+}
+
+fn main() { } //~ ERROR this file contains an unclosed delimiter
diff --git a/tests/ui/parser/deli-ident-issue-1.stderr b/tests/ui/parser/deli-ident-issue-1.stderr
new file mode 100644
index 000000000..eb5073e14
--- /dev/null
+++ b/tests/ui/parser/deli-ident-issue-1.stderr
@@ -0,0 +1,17 @@
+error: this file contains an unclosed delimiter
+ --> $DIR/deli-ident-issue-1.rs:22:66
+ |
+LL | impl dyn Demo {
+ | - unclosed delimiter
+...
+LL | && let Some(c) = num {
+ | - this delimiter might not be properly closed...
+...
+LL | }
+ | - ...as it matches this but it has different indentation
+...
+LL | fn main() { }
+ | ^
+
+error: aborting due to previous error
+
diff --git a/tests/ui/parser/deli-ident-issue-2.rs b/tests/ui/parser/deli-ident-issue-2.rs
new file mode 100644
index 000000000..5394760df
--- /dev/null
+++ b/tests/ui/parser/deli-ident-issue-2.rs
@@ -0,0 +1,7 @@
+fn main() {
+ if 1 < 2 {
+ let _a = vec!]; //~ ERROR mismatched closing delimiter
+ }
+} //~ ERROR unexpected closing delimiter
+
+fn main() {}
diff --git a/tests/ui/parser/deli-ident-issue-2.stderr b/tests/ui/parser/deli-ident-issue-2.stderr
new file mode 100644
index 000000000..e0188cdfb
--- /dev/null
+++ b/tests/ui/parser/deli-ident-issue-2.stderr
@@ -0,0 +1,19 @@
+error: mismatched closing delimiter: `]`
+ --> $DIR/deli-ident-issue-2.rs:2:14
+ |
+LL | if 1 < 2 {
+ | ^ unclosed delimiter
+LL | let _a = vec!];
+ | ^ mismatched closing delimiter
+
+error: unexpected closing delimiter: `}`
+ --> $DIR/deli-ident-issue-2.rs:5:1
+ |
+LL | let _a = vec!];
+ | - missing open `[` for this delimiter
+LL | }
+LL | }
+ | ^ unexpected closing delimiter
+
+error: aborting due to 2 previous errors
+
diff --git a/tests/ui/parser/do-not-suggest-semicolon-before-array.rs b/tests/ui/parser/do-not-suggest-semicolon-before-array.rs
index 7ebf3f6b0..7eff7f431 100644
--- a/tests/ui/parser/do-not-suggest-semicolon-before-array.rs
+++ b/tests/ui/parser/do-not-suggest-semicolon-before-array.rs
@@ -2,7 +2,7 @@ fn foo() {}
fn bar() -> [u8; 2] {
foo()
- [1, 3) //~ ERROR expected one of `.`, `?`, `]`, or an operator, found `,`
+ [1, 3) //~ ERROR mismatched closing delimiter
}
fn main() {}
diff --git a/tests/ui/parser/do-not-suggest-semicolon-before-array.stderr b/tests/ui/parser/do-not-suggest-semicolon-before-array.stderr
index a9dd52632..7b43c7700 100644
--- a/tests/ui/parser/do-not-suggest-semicolon-before-array.stderr
+++ b/tests/ui/parser/do-not-suggest-semicolon-before-array.stderr
@@ -1,8 +1,8 @@
-error: expected one of `.`, `?`, `]`, or an operator, found `,`
+error: mismatched closing delimiter: `)`
--> $DIR/do-not-suggest-semicolon-before-array.rs:5:5
|
LL | [1, 3)
- | ^ ^ help: `]` may belong here
+ | ^ ^ mismatched closing delimiter
| |
| unclosed delimiter
diff --git a/tests/ui/parser/fn-header-semantic-fail.stderr b/tests/ui/parser/fn-header-semantic-fail.stderr
index 038fdfb2d..2d8bd19a7 100644
--- a/tests/ui/parser/fn-header-semantic-fail.stderr
+++ b/tests/ui/parser/fn-header-semantic-fail.stderr
@@ -209,8 +209,8 @@ note: ...which requires const checking `main::ff5`...
|
LL | const async unsafe extern "C" fn ff5() {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- = note: ...which requires computing whether `impl core::future::future::Future<Output = ()>` is freeze...
- = note: ...which requires evaluating trait selection obligation `impl core::future::future::Future<Output = ()>: core::marker::Freeze`...
+ = note: ...which requires computing whether `main::ff5::{opaque#0}` is freeze...
+ = note: ...which requires evaluating trait selection obligation `main::ff5::{opaque#0}: core::marker::Freeze`...
= note: ...which again requires computing type of `main::ff5::{opaque#0}`, completing the cycle
note: cycle used when checking item types in top-level module
--> $DIR/fn-header-semantic-fail.rs:5:1
@@ -245,8 +245,8 @@ note: ...which requires const checking `main::<impl at $DIR/fn-header-semantic-f
|
LL | const async unsafe extern "C" fn ft5() {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- = note: ...which requires computing whether `impl core::future::future::Future<Output = ()>` is freeze...
- = note: ...which requires evaluating trait selection obligation `impl core::future::future::Future<Output = ()>: core::marker::Freeze`...
+ = note: ...which requires computing whether `main::<impl at $DIR/fn-header-semantic-fail.rs:28:5: 28:17>::ft5::{opaque#0}` is freeze...
+ = note: ...which requires evaluating trait selection obligation `main::<impl at $DIR/fn-header-semantic-fail.rs:28:5: 28:17>::ft5::{opaque#0}: core::marker::Freeze`...
= note: ...which again requires computing type of `main::<impl at $DIR/fn-header-semantic-fail.rs:28:5: 28:17>::ft5::{opaque#0}`, completing the cycle
note: cycle used when checking item types in top-level module
--> $DIR/fn-header-semantic-fail.rs:5:1
@@ -281,8 +281,8 @@ note: ...which requires const checking `main::<impl at $DIR/fn-header-semantic-f
|
LL | const async unsafe extern "C" fn fi5() {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- = note: ...which requires computing whether `impl core::future::future::Future<Output = ()>` is freeze...
- = note: ...which requires evaluating trait selection obligation `impl core::future::future::Future<Output = ()>: core::marker::Freeze`...
+ = note: ...which requires computing whether `main::<impl at $DIR/fn-header-semantic-fail.rs:40:5: 40:11>::fi5::{opaque#0}` is freeze...
+ = note: ...which requires evaluating trait selection obligation `main::<impl at $DIR/fn-header-semantic-fail.rs:40:5: 40:11>::fi5::{opaque#0}: core::marker::Freeze`...
= note: ...which again requires computing type of `main::<impl at $DIR/fn-header-semantic-fail.rs:40:5: 40:11>::fi5::{opaque#0}`, completing the cycle
note: cycle used when checking item types in top-level module
--> $DIR/fn-header-semantic-fail.rs:5:1
diff --git a/tests/ui/parser/issue-102806.stderr b/tests/ui/parser/issue-102806.stderr
index 6872b8bc0..ba8174a82 100644
--- a/tests/ui/parser/issue-102806.stderr
+++ b/tests/ui/parser/issue-102806.stderr
@@ -32,7 +32,12 @@ error: expected field pattern, found `...`
--> $DIR/issue-102806.rs:21:22
|
LL | let V3 { z: val, ... } = v;
- | ^^^ help: to omit remaining fields, use one fewer `.`: `..`
+ | ^^^
+ |
+help: to omit remaining fields, use `..`
+ |
+LL | let V3 { z: val, .. } = v;
+ | ~~
error[E0063]: missing fields `x` and `y` in initializer of `V3`
--> $DIR/issue-102806.rs:17:13
diff --git a/tests/ui/parser/issue-103451.rs b/tests/ui/parser/issue-103451.rs
index 1fdb00148..be33213f3 100644
--- a/tests/ui/parser/issue-103451.rs
+++ b/tests/ui/parser/issue-103451.rs
@@ -1,5 +1,4 @@
// error-pattern: this file contains an unclosed delimiter
-// error-pattern: expected value, found struct `R`
struct R { }
struct S {
x: [u8; R
diff --git a/tests/ui/parser/issue-103451.stderr b/tests/ui/parser/issue-103451.stderr
index eb3c92fb4..6aacd5012 100644
--- a/tests/ui/parser/issue-103451.stderr
+++ b/tests/ui/parser/issue-103451.stderr
@@ -1,5 +1,5 @@
error: this file contains an unclosed delimiter
- --> $DIR/issue-103451.rs:5:15
+ --> $DIR/issue-103451.rs:4:15
|
LL | struct S {
| - unclosed delimiter
@@ -8,25 +8,5 @@ LL | x: [u8; R
| |
| unclosed delimiter
-error: this file contains an unclosed delimiter
- --> $DIR/issue-103451.rs:5:15
- |
-LL | struct S {
- | - unclosed delimiter
-LL | x: [u8; R
- | - ^
- | |
- | unclosed delimiter
-
-error[E0423]: expected value, found struct `R`
- --> $DIR/issue-103451.rs:5:13
- |
-LL | struct R { }
- | ------------ `R` defined here
-LL | struct S {
-LL | x: [u8; R
- | ^ help: use struct literal syntax instead: `R {}`
-
-error: aborting due to 3 previous errors
+error: aborting due to previous error
-For more information about this error, try `rustc --explain E0423`.
diff --git a/tests/ui/parser/issue-107705.rs b/tests/ui/parser/issue-107705.rs
new file mode 100644
index 000000000..b80984fcd
--- /dev/null
+++ b/tests/ui/parser/issue-107705.rs
@@ -0,0 +1,3 @@
+// compile-flags: -C debug-assertions
+
+fn f() {a(b:&, //~ ERROR this file contains an unclosed delimiter
diff --git a/tests/ui/parser/issue-107705.stderr b/tests/ui/parser/issue-107705.stderr
new file mode 100644
index 000000000..d2d613461
--- /dev/null
+++ b/tests/ui/parser/issue-107705.stderr
@@ -0,0 +1,10 @@
+error: this file contains an unclosed delimiter
+ --> $DIR/issue-107705.rs:3:67
+ |
+LL | fn f() {a(b:&,
+ | - - unclosed delimiter ^
+ | |
+ | unclosed delimiter
+
+error: aborting due to previous error
+
diff --git a/tests/ui/parser/issue-108495-dec.rs b/tests/ui/parser/issue-108495-dec.rs
new file mode 100644
index 000000000..e0816f84e
--- /dev/null
+++ b/tests/ui/parser/issue-108495-dec.rs
@@ -0,0 +1,39 @@
+fn test0() {
+ let mut i = 0;
+ let _ = i + i--; //~ ERROR Rust has no postfix decrement operator
+ // won't suggest since we can not handle the precedences
+}
+
+fn test1() {
+ let mut i = 0;
+ let _ = i-- + i--; //~ ERROR Rust has no postfix decrement operator
+}
+
+fn test2() {
+ let mut i = 0;
+ let _ = --i + i--; //~ ERROR Rust has no postfix decrement operator
+}
+
+fn test3() {
+ let mut i = 0;
+ let _ = i-- + --i; //~ ERROR Rust has no postfix decrement operator
+}
+
+fn test4() {
+ let mut i = 0;
+ let _ = (1 + 2 + i)--; //~ ERROR Rust has no postfix decrement operator
+}
+
+fn test5() {
+ let mut i = 0;
+ let _ = (i-- + 1) + 2; //~ ERROR Rust has no postfix decrement operator
+}
+
+fn test6(){
+ let i=10;
+ while i != 0 {
+ i--; //~ ERROR Rust has no postfix decrement operator
+ }
+}
+
+fn main() {}
diff --git a/tests/ui/parser/issue-108495-dec.stderr b/tests/ui/parser/issue-108495-dec.stderr
new file mode 100644
index 000000000..85b29038f
--- /dev/null
+++ b/tests/ui/parser/issue-108495-dec.stderr
@@ -0,0 +1,69 @@
+error: Rust has no postfix decrement operator
+ --> $DIR/issue-108495-dec.rs:3:18
+ |
+LL | let _ = i + i--;
+ | ^^ not a valid postfix operator
+
+error: Rust has no postfix decrement operator
+ --> $DIR/issue-108495-dec.rs:9:14
+ |
+LL | let _ = i-- + i--;
+ | ^^ not a valid postfix operator
+ |
+help: use `-= 1` instead
+ |
+LL | let _ = { let tmp = i; i -= 1; tmp } + i--;
+ | +++++++++++ ~~~~~~~~~~~~~~~
+
+error: Rust has no postfix decrement operator
+ --> $DIR/issue-108495-dec.rs:14:20
+ |
+LL | let _ = --i + i--;
+ | ^^ not a valid postfix operator
+
+error: Rust has no postfix decrement operator
+ --> $DIR/issue-108495-dec.rs:19:14
+ |
+LL | let _ = i-- + --i;
+ | ^^ not a valid postfix operator
+ |
+help: use `-= 1` instead
+ |
+LL | let _ = { let tmp = i; i -= 1; tmp } + --i;
+ | +++++++++++ ~~~~~~~~~~~~~~~
+
+error: Rust has no postfix decrement operator
+ --> $DIR/issue-108495-dec.rs:24:24
+ |
+LL | let _ = (1 + 2 + i)--;
+ | ^^ not a valid postfix operator
+ |
+help: use `-= 1` instead
+ |
+LL | let _ = { let tmp = (1 + 2 + i); (1 + 2 + i) -= 1; tmp };
+ | +++++++++++ ~~~~~~~~~~~~~~~~~~~~~~~~~
+
+error: Rust has no postfix decrement operator
+ --> $DIR/issue-108495-dec.rs:29:15
+ |
+LL | let _ = (i-- + 1) + 2;
+ | ^^ not a valid postfix operator
+ |
+help: use `-= 1` instead
+ |
+LL | let _ = ({ let tmp = i; i -= 1; tmp } + 1) + 2;
+ | +++++++++++ ~~~~~~~~~~~~~~~
+
+error: Rust has no postfix decrement operator
+ --> $DIR/issue-108495-dec.rs:35:10
+ |
+LL | i--;
+ | ^^ not a valid postfix operator
+ |
+help: use `-= 1` instead
+ |
+LL | i -= 1;
+ | ~~~~
+
+error: aborting due to 7 previous errors
+
diff --git a/tests/ui/parser/issue-68987-unmatch-issue-1.rs b/tests/ui/parser/issue-68987-unmatch-issue-1.rs
new file mode 100644
index 000000000..30e7ef467
--- /dev/null
+++ b/tests/ui/parser/issue-68987-unmatch-issue-1.rs
@@ -0,0 +1,12 @@
+// This file has unexpected closing delimiter,
+
+fn func(o: Option<u32>) {
+ match o {
+ Some(_x) => {} // Extra '}'
+ let _ = if true {};
+ }
+ None => {}
+ }
+} //~ ERROR unexpected closing delimiter
+
+fn main() {}
diff --git a/tests/ui/parser/issue-68987-unmatch-issue-1.stderr b/tests/ui/parser/issue-68987-unmatch-issue-1.stderr
new file mode 100644
index 000000000..2d873b461
--- /dev/null
+++ b/tests/ui/parser/issue-68987-unmatch-issue-1.stderr
@@ -0,0 +1,16 @@
+error: unexpected closing delimiter: `}`
+ --> $DIR/issue-68987-unmatch-issue-1.rs:10:1
+ |
+LL | match o {
+ | - this delimiter might not be properly closed...
+LL | Some(_x) => {} // Extra '}'
+ | -- block is empty, you might have not meant to close it
+LL | let _ = if true {};
+LL | }
+ | - ...as it matches this but it has different indentation
+...
+LL | }
+ | ^ unexpected closing delimiter
+
+error: aborting due to previous error
+
diff --git a/tests/ui/parser/issue-68987-unmatch-issue-2.rs b/tests/ui/parser/issue-68987-unmatch-issue-2.rs
new file mode 100644
index 000000000..89aaa68ba
--- /dev/null
+++ b/tests/ui/parser/issue-68987-unmatch-issue-2.rs
@@ -0,0 +1,14 @@
+// FIXME: this case need more work to fix
+// currently the TokenTree matching ')' with '{', which is not user friendly for diagnostics
+async fn obstest() -> Result<> {
+ let obs_connect = || -> Result<(), MyError) { //~ ERROR mismatched closing delimiter
+ async {
+ }
+ }
+
+ if let Ok(version, scene_list) = obs_connect() {
+
+ } else {
+
+ }
+} //~ ERROR unexpected closing delimiter
diff --git a/tests/ui/parser/issue-68987-unmatch-issue-2.stderr b/tests/ui/parser/issue-68987-unmatch-issue-2.stderr
new file mode 100644
index 000000000..0ecb748a0
--- /dev/null
+++ b/tests/ui/parser/issue-68987-unmatch-issue-2.stderr
@@ -0,0 +1,19 @@
+error: mismatched closing delimiter: `)`
+ --> $DIR/issue-68987-unmatch-issue-2.rs:3:32
+ |
+LL | async fn obstest() -> Result<> {
+ | ^ unclosed delimiter
+LL | let obs_connect = || -> Result<(), MyError) {
+ | ^ mismatched closing delimiter
+
+error: unexpected closing delimiter: `}`
+ --> $DIR/issue-68987-unmatch-issue-2.rs:14:1
+ |
+LL | let obs_connect = || -> Result<(), MyError) {
+ | - missing open `(` for this delimiter
+...
+LL | }
+ | ^ unexpected closing delimiter
+
+error: aborting due to 2 previous errors
+
diff --git a/tests/ui/parser/issue-68987-unmatch-issue-3.rs b/tests/ui/parser/issue-68987-unmatch-issue-3.rs
new file mode 100644
index 000000000..e98df8d7c
--- /dev/null
+++ b/tests/ui/parser/issue-68987-unmatch-issue-3.rs
@@ -0,0 +1,8 @@
+// the `{` is closed with `)`, there is a missing `(`
+fn f(i: u32, j: u32) {
+ let res = String::new();
+ let mut cnt = i;
+ while cnt < j {
+ write!&mut res, " "); //~ ERROR mismatched closing delimiter
+ }
+} //~ ERROR unexpected closing delimiter
diff --git a/tests/ui/parser/issue-68987-unmatch-issue-3.stderr b/tests/ui/parser/issue-68987-unmatch-issue-3.stderr
new file mode 100644
index 000000000..dfc4407ed
--- /dev/null
+++ b/tests/ui/parser/issue-68987-unmatch-issue-3.stderr
@@ -0,0 +1,19 @@
+error: mismatched closing delimiter: `)`
+ --> $DIR/issue-68987-unmatch-issue-3.rs:5:19
+ |
+LL | while cnt < j {
+ | ^ unclosed delimiter
+LL | write!&mut res, " ");
+ | ^ mismatched closing delimiter
+
+error: unexpected closing delimiter: `}`
+ --> $DIR/issue-68987-unmatch-issue-3.rs:8:1
+ |
+LL | write!&mut res, " ");
+ | - missing open `(` for this delimiter
+LL | }
+LL | }
+ | ^ unexpected closing delimiter
+
+error: aborting due to 2 previous errors
+
diff --git a/tests/ui/parser/issue-68987-unmatch-issue.rs b/tests/ui/parser/issue-68987-unmatch-issue.rs
new file mode 100644
index 000000000..5a3620bf2
--- /dev/null
+++ b/tests/ui/parser/issue-68987-unmatch-issue.rs
@@ -0,0 +1,12 @@
+// This file has unexpected closing delimiter,
+
+fn func(o: Option<u32>) {
+ match o {
+ Some(_x) => // Missing '{'
+ let _ = if true {};
+ }
+ None => {}
+ }
+} //~ ERROR unexpected closing delimiter
+
+fn main() {}
diff --git a/tests/ui/parser/issue-68987-unmatch-issue.stderr b/tests/ui/parser/issue-68987-unmatch-issue.stderr
new file mode 100644
index 000000000..cabd13324
--- /dev/null
+++ b/tests/ui/parser/issue-68987-unmatch-issue.stderr
@@ -0,0 +1,16 @@
+error: unexpected closing delimiter: `}`
+ --> $DIR/issue-68987-unmatch-issue.rs:10:1
+ |
+LL | match o {
+ | - this delimiter might not be properly closed...
+LL | Some(_x) => // Missing '{'
+LL | let _ = if true {};
+ | -- block is empty, you might have not meant to close it
+LL | }
+ | - ...as it matches this but it has different indentation
+...
+LL | }
+ | ^ unexpected closing delimiter
+
+error: aborting due to previous error
+
diff --git a/tests/ui/parser/issue-81804.rs b/tests/ui/parser/issue-81804.rs
index 803bde11e..ebc4752a1 100644
--- a/tests/ui/parser/issue-81804.rs
+++ b/tests/ui/parser/issue-81804.rs
@@ -1,8 +1,5 @@
// error-pattern: this file contains an unclosed delimiter
// error-pattern: this file contains an unclosed delimiter
-// error-pattern: expected pattern, found `=`
-// error-pattern: expected one of `)`, `,`, `->`, `where`, or `{`, found `]`
-// error-pattern: expected item, found `]`
fn main() {}
diff --git a/tests/ui/parser/issue-81804.stderr b/tests/ui/parser/issue-81804.stderr
index 19c4422c6..de3b33ecd 100644
--- a/tests/ui/parser/issue-81804.stderr
+++ b/tests/ui/parser/issue-81804.stderr
@@ -1,14 +1,13 @@
-error: this file contains an unclosed delimiter
- --> $DIR/issue-81804.rs:9:11
+error: mismatched closing delimiter: `}`
+ --> $DIR/issue-81804.rs:6:8
|
LL | fn p([=(}
- | -- ^
- | ||
- | |unclosed delimiter
- | unclosed delimiter
+ | ^^ mismatched closing delimiter
+ | |
+ | unclosed delimiter
error: this file contains an unclosed delimiter
- --> $DIR/issue-81804.rs:9:11
+ --> $DIR/issue-81804.rs:6:11
|
LL | fn p([=(}
| -- ^
@@ -16,26 +15,5 @@ LL | fn p([=(}
| |unclosed delimiter
| unclosed delimiter
-error: expected pattern, found `=`
- --> $DIR/issue-81804.rs:9:7
- |
-LL | fn p([=(}
- | ^ expected pattern
-
-error: expected one of `)`, `,`, `->`, `where`, or `{`, found `]`
- --> $DIR/issue-81804.rs:9:8
- |
-LL | fn p([=(}
- | ^ -^
- | | |
- | | help: `)` may belong here
- | unclosed delimiter
-
-error: expected item, found `]`
- --> $DIR/issue-81804.rs:9:11
- |
-LL | fn p([=(}
- | ^ expected item
-
-error: aborting due to 5 previous errors
+error: aborting due to 2 previous errors
diff --git a/tests/ui/parser/issue-81827.rs b/tests/ui/parser/issue-81827.rs
index 7ec581594..91defd12a 100644
--- a/tests/ui/parser/issue-81827.rs
+++ b/tests/ui/parser/issue-81827.rs
@@ -1,6 +1,5 @@
// error-pattern: this file contains an unclosed delimiter
// error-pattern: mismatched closing delimiter: `]`
-// error-pattern: expected one of `)` or `,`, found `{`
#![crate_name="0"]
diff --git a/tests/ui/parser/issue-81827.stderr b/tests/ui/parser/issue-81827.stderr
index 069de3391..63d135f73 100644
--- a/tests/ui/parser/issue-81827.stderr
+++ b/tests/ui/parser/issue-81827.stderr
@@ -1,23 +1,5 @@
-error: this file contains an unclosed delimiter
- --> $DIR/issue-81827.rs:11:27
- |
-LL | fn r()->i{0|{#[cfg(r(0{]0
- | - - ^
- | | |
- | | unclosed delimiter
- | unclosed delimiter
-
-error: this file contains an unclosed delimiter
- --> $DIR/issue-81827.rs:11:27
- |
-LL | fn r()->i{0|{#[cfg(r(0{]0
- | - - ^
- | | |
- | | unclosed delimiter
- | unclosed delimiter
-
error: mismatched closing delimiter: `]`
- --> $DIR/issue-81827.rs:11:23
+ --> $DIR/issue-81827.rs:10:23
|
LL | fn r()->i{0|{#[cfg(r(0{]0
| - ^^ mismatched closing delimiter
@@ -25,11 +7,15 @@ LL | fn r()->i{0|{#[cfg(r(0{]0
| | unclosed delimiter
| closing delimiter possibly meant for this
-error: expected one of `)` or `,`, found `{`
- --> $DIR/issue-81827.rs:11:23
+error: this file contains an unclosed delimiter
+ --> $DIR/issue-81827.rs:10:27
|
LL | fn r()->i{0|{#[cfg(r(0{]0
- | ^ expected one of `)` or `,`
+ | - - - ^
+ | | | |
+ | | | missing open `[` for this delimiter
+ | | unclosed delimiter
+ | unclosed delimiter
-error: aborting due to 4 previous errors
+error: aborting due to 2 previous errors
diff --git a/tests/ui/parser/issues/issue-104367.rs b/tests/ui/parser/issues/issue-104367.rs
new file mode 100644
index 000000000..861761b64
--- /dev/null
+++ b/tests/ui/parser/issues/issue-104367.rs
@@ -0,0 +1,6 @@
+#[derive(A)]
+struct S {
+ d: [u32; {
+ #![cfg] {
+ #![w,) //~ ERROR mismatched closing delimiter
+ //~ ERROR this file contains an unclosed delimiter
diff --git a/tests/ui/parser/issues/issue-104367.stderr b/tests/ui/parser/issues/issue-104367.stderr
new file mode 100644
index 000000000..e6e765357
--- /dev/null
+++ b/tests/ui/parser/issues/issue-104367.stderr
@@ -0,0 +1,26 @@
+error: mismatched closing delimiter: `)`
+ --> $DIR/issue-104367.rs:5:15
+ |
+LL | #![w,)
+ | ^ ^ mismatched closing delimiter
+ | |
+ | unclosed delimiter
+
+error: this file contains an unclosed delimiter
+ --> $DIR/issue-104367.rs:6:71
+ |
+LL | struct S {
+ | - unclosed delimiter
+LL | d: [u32; {
+ | - - unclosed delimiter
+ | |
+ | unclosed delimiter
+LL | #![cfg] {
+ | - unclosed delimiter
+LL | #![w,)
+ | - missing open `(` for this delimiter
+LL |
+ | ^
+
+error: aborting due to 2 previous errors
+
diff --git a/tests/ui/parser/issues/issue-105209.rs b/tests/ui/parser/issues/issue-105209.rs
new file mode 100644
index 000000000..6146b795d
--- /dev/null
+++ b/tests/ui/parser/issues/issue-105209.rs
@@ -0,0 +1,3 @@
+// compile-flags: -Zunpretty=ast-tree
+#![c={#![c[)x //~ ERROR mismatched closing delimiter
+ //~ ERROR this file contains an unclosed delimiter
diff --git a/tests/ui/parser/issues/issue-105209.stderr b/tests/ui/parser/issues/issue-105209.stderr
new file mode 100644
index 000000000..c75eafa18
--- /dev/null
+++ b/tests/ui/parser/issues/issue-105209.stderr
@@ -0,0 +1,22 @@
+error: mismatched closing delimiter: `)`
+ --> $DIR/issue-105209.rs:2:11
+ |
+LL | #![c={#![c[)x
+ | ^^ mismatched closing delimiter
+ | |
+ | unclosed delimiter
+
+error: this file contains an unclosed delimiter
+ --> $DIR/issue-105209.rs:3:68
+ |
+LL | #![c={#![c[)x
+ | - - - - missing open `(` for this delimiter
+ | | | |
+ | | | unclosed delimiter
+ | | unclosed delimiter
+ | unclosed delimiter
+LL |
+ | ^
+
+error: aborting due to 2 previous errors
+
diff --git a/tests/ui/parser/issues/issue-10636-2.rs b/tests/ui/parser/issues/issue-10636-2.rs
index 6fb63639d..80d8ef65a 100644
--- a/tests/ui/parser/issues/issue-10636-2.rs
+++ b/tests/ui/parser/issues/issue-10636-2.rs
@@ -1,11 +1,11 @@
+// error-pattern: mismatched closing delimiter: `}`
// FIXME(31528) we emit a bunch of silly errors here due to continuing past the
// first one. This would be easy-ish to address by better recovery in tokenisation.
pub fn trace_option(option: Option<isize>) {
option.map(|some| 42;
- //~^ ERROR: expected one of
+
}
-//~^ ERROR: expected expression, found `)`
fn main() {}
diff --git a/tests/ui/parser/issues/issue-10636-2.stderr b/tests/ui/parser/issues/issue-10636-2.stderr
index d4f2da9e3..4cd4be180 100644
--- a/tests/ui/parser/issues/issue-10636-2.stderr
+++ b/tests/ui/parser/issues/issue-10636-2.stderr
@@ -1,16 +1,13 @@
-error: expected one of `)`, `,`, `.`, `?`, or an operator, found `;`
- --> $DIR/issue-10636-2.rs:5:15
+error: mismatched closing delimiter: `}`
+ --> $DIR/issue-10636-2.rs:6:15
|
+LL | pub fn trace_option(option: Option<isize>) {
+ | - closing delimiter possibly meant for this
LL | option.map(|some| 42;
- | ^ ^ help: `)` may belong here
- | |
- | unclosed delimiter
-
-error: expected expression, found `)`
- --> $DIR/issue-10636-2.rs:8:1
- |
+ | ^ unclosed delimiter
+...
LL | }
- | ^ expected expression
+ | ^ mismatched closing delimiter
-error: aborting due to 2 previous errors
+error: aborting due to previous error
diff --git a/tests/ui/parser/issues/issue-44406.stderr b/tests/ui/parser/issues/issue-44406.stderr
index 1f0c1ea4c..de02ea85b 100644
--- a/tests/ui/parser/issues/issue-44406.stderr
+++ b/tests/ui/parser/issues/issue-44406.stderr
@@ -21,8 +21,8 @@ LL | foo!(true);
= 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 { }
- | ~
+LL | bar { baz: $rest }
+ | ~ ~
help: if `bar` is a function, use the arguments directly
|
LL - bar(baz: $rest)
diff --git a/tests/ui/parser/issues/issue-58094-missing-right-square-bracket.rs b/tests/ui/parser/issues/issue-58094-missing-right-square-bracket.rs
index 25699f9fe..a596a9f2d 100644
--- a/tests/ui/parser/issues/issue-58094-missing-right-square-bracket.rs
+++ b/tests/ui/parser/issues/issue-58094-missing-right-square-bracket.rs
@@ -1,4 +1,5 @@
// Fixed in #66054.
// ignore-tidy-trailing-newlines
-// error-pattern: aborting due to 2 previous errors
+// error-pattern: this file contains an unclosed delimiter
+// error-pattern: aborting due to previous error
#[Ѕ \ No newline at end of file
diff --git a/tests/ui/parser/issues/issue-58094-missing-right-square-bracket.stderr b/tests/ui/parser/issues/issue-58094-missing-right-square-bracket.stderr
index 8a44ee761..c79e8b4fb 100644
--- a/tests/ui/parser/issues/issue-58094-missing-right-square-bracket.stderr
+++ b/tests/ui/parser/issues/issue-58094-missing-right-square-bracket.stderr
@@ -1,16 +1,10 @@
error: this file contains an unclosed delimiter
- --> $DIR/issue-58094-missing-right-square-bracket.rs:4:4
+ --> $DIR/issue-58094-missing-right-square-bracket.rs:5:4
|
LL | #[Ѕ
| - ^
| |
| unclosed delimiter
-error: expected item after attributes
- --> $DIR/issue-58094-missing-right-square-bracket.rs:4:1
- |
-LL | #[Ѕ
- | ^^^
-
-error: aborting due to 2 previous errors
+error: aborting due to previous error
diff --git a/tests/ui/parser/issues/issue-58856-1.rs b/tests/ui/parser/issues/issue-58856-1.rs
index ea80eb871..799243d54 100644
--- a/tests/ui/parser/issues/issue-58856-1.rs
+++ b/tests/ui/parser/issues/issue-58856-1.rs
@@ -1,8 +1,5 @@
impl A {
- //~^ ERROR cannot find type `A` in this scope
fn b(self>
- //~^ ERROR expected one of `)`, `,`, or `:`, found `>`
- //~| ERROR expected one of `->`, `where`, or `{`, found `>`
-}
+} //~ ERROR mismatched closing delimiter
fn main() {}
diff --git a/tests/ui/parser/issues/issue-58856-1.stderr b/tests/ui/parser/issues/issue-58856-1.stderr
index 96151f3fe..77ad8acbd 100644
--- a/tests/ui/parser/issues/issue-58856-1.stderr
+++ b/tests/ui/parser/issues/issue-58856-1.stderr
@@ -1,29 +1,12 @@
-error: expected one of `)`, `,`, or `:`, found `>`
- --> $DIR/issue-58856-1.rs:3:9
- |
-LL | fn b(self>
- | ^ ^ help: `)` may belong here
- | |
- | unclosed delimiter
-
-error: expected one of `->`, `where`, or `{`, found `>`
- --> $DIR/issue-58856-1.rs:3:14
+error: mismatched closing delimiter: `}`
+ --> $DIR/issue-58856-1.rs:2:9
|
LL | impl A {
- | - while parsing this item list starting here
-LL |
+ | - closing delimiter possibly meant for this
LL | fn b(self>
- | ^ expected one of `->`, `where`, or `{`
-...
+ | ^ unclosed delimiter
LL | }
- | - the item list ends here
-
-error[E0412]: cannot find type `A` in this scope
- --> $DIR/issue-58856-1.rs:1:6
- |
-LL | impl A {
- | ^ not found in this scope
+ | ^ mismatched closing delimiter
-error: aborting due to 3 previous errors
+error: aborting due to previous error
-For more information about this error, try `rustc --explain E0412`.
diff --git a/tests/ui/parser/issues/issue-58856-2.rs b/tests/ui/parser/issues/issue-58856-2.rs
index 9356d57b0..5edd72639 100644
--- a/tests/ui/parser/issues/issue-58856-2.rs
+++ b/tests/ui/parser/issues/issue-58856-2.rs
@@ -4,11 +4,8 @@ trait Howness {}
impl Howness for () {
fn how_are_you(&self -> Empty {
- //~^ ERROR expected one of `)` or `,`, found `->`
- //~| ERROR method `how_are_you` is not a member of trait `Howness`
Empty
}
-}
-//~^ ERROR non-item in item list
+} //~ ERROR mismatched closing delimiter
fn main() {}
diff --git a/tests/ui/parser/issues/issue-58856-2.stderr b/tests/ui/parser/issues/issue-58856-2.stderr
index 627dd3890..5fcf5bcc1 100644
--- a/tests/ui/parser/issues/issue-58856-2.stderr
+++ b/tests/ui/parser/issues/issue-58856-2.stderr
@@ -1,34 +1,13 @@
-error: expected one of `)` or `,`, found `->`
+error: mismatched closing delimiter: `}`
--> $DIR/issue-58856-2.rs:6:19
|
-LL | fn how_are_you(&self -> Empty {
- | ^ -^^
- | | |
- | | help: `)` may belong here
- | unclosed delimiter
-
-error: non-item in item list
- --> $DIR/issue-58856-2.rs:11:1
- |
LL | impl Howness for () {
- | - item list starts here
+ | - closing delimiter possibly meant for this
+LL | fn how_are_you(&self -> Empty {
+ | ^ unclosed delimiter
...
LL | }
- | ^
- | |
- | non-item starts here
- | item list ends here
-
-error[E0407]: method `how_are_you` is not a member of trait `Howness`
- --> $DIR/issue-58856-2.rs:6:5
- |
-LL | / fn how_are_you(&self -> Empty {
-LL | |
-LL | |
-LL | | Empty
-LL | | }
- | |_____^ not a member of trait `Howness`
+ | ^ mismatched closing delimiter
-error: aborting due to 3 previous errors
+error: aborting due to previous error
-For more information about this error, try `rustc --explain E0407`.
diff --git a/tests/ui/parser/issues/issue-60075.rs b/tests/ui/parser/issues/issue-60075.rs
index e89d78ee8..3c36e4d3e 100644
--- a/tests/ui/parser/issues/issue-60075.rs
+++ b/tests/ui/parser/issues/issue-60075.rs
@@ -3,9 +3,6 @@ fn main() {}
trait T {
fn qux() -> Option<usize> {
let _ = if true {
- });
-//~^ ERROR non-item in item list
-//~| ERROR mismatched closing delimiter: `)`
-//~| ERROR expected one of `.`, `;`
+ }); //~ ERROR mismatched closing delimiter
Some(4)
}
diff --git a/tests/ui/parser/issues/issue-60075.stderr b/tests/ui/parser/issues/issue-60075.stderr
index 210ef700c..cd8f1231f 100644
--- a/tests/ui/parser/issues/issue-60075.stderr
+++ b/tests/ui/parser/issues/issue-60075.stderr
@@ -1,21 +1,3 @@
-error: expected one of `.`, `;`, `?`, `else`, or an operator, found `}`
- --> $DIR/issue-60075.rs:6:10
- |
-LL | });
- | ^ expected one of `.`, `;`, `?`, `else`, or an operator
-
-error: non-item in item list
- --> $DIR/issue-60075.rs:6:11
- |
-LL | trait T {
- | - item list starts here
-...
-LL | });
- | ^ non-item starts here
-...
-LL | }
- | - item list ends here
-
error: mismatched closing delimiter: `)`
--> $DIR/issue-60075.rs:4:31
|
@@ -25,5 +7,5 @@ LL | let _ = if true {
LL | });
| ^ mismatched closing delimiter
-error: aborting due to 3 previous errors
+error: aborting due to previous error
diff --git a/tests/ui/parser/issues/issue-62524.rs b/tests/ui/parser/issues/issue-62524.rs
index 5259dfe2e..fa7c626f5 100644
--- a/tests/ui/parser/issues/issue-62524.rs
+++ b/tests/ui/parser/issues/issue-62524.rs
@@ -1,5 +1,5 @@
// ignore-tidy-trailing-newlines
-// error-pattern: aborting due to 3 previous errors
+// error-pattern: aborting due to previous error
#![allow(uncommon_codepoints)]
y![
diff --git a/tests/ui/parser/issues/issue-62524.stderr b/tests/ui/parser/issues/issue-62524.stderr
index 55eed0402..0cbaacd4c 100644
--- a/tests/ui/parser/issues/issue-62524.stderr
+++ b/tests/ui/parser/issues/issue-62524.stderr
@@ -6,28 +6,5 @@ LL | y![
LL | Ϥ,
| ^
-error: macros that expand to items must be delimited with braces or followed by a semicolon
- --> $DIR/issue-62524.rs:5:3
- |
-LL | y![
- | ___^
-LL | | Ϥ,
- | |__^
- |
-help: change the delimiters to curly braces
- |
-LL | y! { /* items */ }
- | ~~~~~~~~~~~~~~~
-help: add a semicolon
- |
-LL | Ϥ,;
- | +
-
-error: cannot find macro `y` in this scope
- --> $DIR/issue-62524.rs:5:1
- |
-LL | y![
- | ^
-
-error: aborting due to 3 previous errors
+error: aborting due to previous error
diff --git a/tests/ui/parser/issues/issue-62546.rs b/tests/ui/parser/issues/issue-62546.rs
index f06b65058..bb30d68ea 100644
--- a/tests/ui/parser/issues/issue-62546.rs
+++ b/tests/ui/parser/issues/issue-62546.rs
@@ -1,3 +1 @@
-pub t(#
-//~^ ERROR missing `fn` or `struct` for function or struct definition
-//~ ERROR this file contains an unclosed delimiter
+pub t(# //~ ERROR this file contains an unclosed delimiter
diff --git a/tests/ui/parser/issues/issue-62546.stderr b/tests/ui/parser/issues/issue-62546.stderr
index 32c61391e..80c1c7168 100644
--- a/tests/ui/parser/issues/issue-62546.stderr
+++ b/tests/ui/parser/issues/issue-62546.stderr
@@ -1,17 +1,8 @@
error: this file contains an unclosed delimiter
- --> $DIR/issue-62546.rs:3:52
+ --> $DIR/issue-62546.rs:1:60
|
LL | pub t(#
- | - unclosed delimiter
-LL |
-LL |
- | ^
+ | - unclosed delimiter ^
-error: missing `fn` or `struct` for function or struct definition
- --> $DIR/issue-62546.rs:1:4
- |
-LL | pub t(#
- | ---^- help: if you meant to call a macro, try: `t!`
-
-error: aborting due to 2 previous errors
+error: aborting due to previous error
diff --git a/tests/ui/parser/issues/issue-62554.rs b/tests/ui/parser/issues/issue-62554.rs
index cfd02183c..4b463a173 100644
--- a/tests/ui/parser/issues/issue-62554.rs
+++ b/tests/ui/parser/issues/issue-62554.rs
@@ -1,5 +1,4 @@
// error-pattern:this file contains an unclosed delimiter
-// error-pattern:xpected `{`, found `macro_rules`
fn main() {}
diff --git a/tests/ui/parser/issues/issue-62554.stderr b/tests/ui/parser/issues/issue-62554.stderr
index 9e62572e3..4637c795a 100644
--- a/tests/ui/parser/issues/issue-62554.stderr
+++ b/tests/ui/parser/issues/issue-62554.stderr
@@ -1,5 +1,5 @@
error: this file contains an unclosed delimiter
- --> $DIR/issue-62554.rs:6:89
+ --> $DIR/issue-62554.rs:5:89
|
LL | fn foo(u: u8) { if u8 macro_rules! u8 { (u6) => { fn uuuuuuuuuuu() { use s loo mod u8 {
| - - - - - ^
@@ -9,65 +9,5 @@ LL | fn foo(u: u8) { if u8 macro_rules! u8 { (u6) => { fn uuuuuuuuuuu() { use s
| | | unclosed delimiter
| unclosed delimiter unclosed delimiter
-error: this file contains an unclosed delimiter
- --> $DIR/issue-62554.rs:6:89
- |
-LL | fn foo(u: u8) { if u8 macro_rules! u8 { (u6) => { fn uuuuuuuuuuu() { use s loo mod u8 {
- | - - - - - ^
- | | | | | |
- | | | | | unclosed delimiter
- | | | | unclosed delimiter
- | | | unclosed delimiter
- | unclosed delimiter unclosed delimiter
-
-error: this file contains an unclosed delimiter
- --> $DIR/issue-62554.rs:6:89
- |
-LL | fn foo(u: u8) { if u8 macro_rules! u8 { (u6) => { fn uuuuuuuuuuu() { use s loo mod u8 {
- | - - - - - ^
- | | | | | |
- | | | | | unclosed delimiter
- | | | | unclosed delimiter
- | | | unclosed delimiter
- | unclosed delimiter unclosed delimiter
-
-error: this file contains an unclosed delimiter
- --> $DIR/issue-62554.rs:6:89
- |
-LL | fn foo(u: u8) { if u8 macro_rules! u8 { (u6) => { fn uuuuuuuuuuu() { use s loo mod u8 {
- | - - - - - ^
- | | | | | |
- | | | | | unclosed delimiter
- | | | | unclosed delimiter
- | | | unclosed delimiter
- | unclosed delimiter unclosed delimiter
-
-error: this file contains an unclosed delimiter
- --> $DIR/issue-62554.rs:6:89
- |
-LL | fn foo(u: u8) { if u8 macro_rules! u8 { (u6) => { fn uuuuuuuuuuu() { use s loo mod u8 {
- | - - - - - ^
- | | | | | |
- | | | | | unclosed delimiter
- | | | | unclosed delimiter
- | | | unclosed delimiter
- | unclosed delimiter unclosed delimiter
-
-error: expected `{`, found `macro_rules`
- --> $DIR/issue-62554.rs:6:23
- |
-LL | fn foo(u: u8) { if u8 macro_rules! u8 { (u6) => { fn uuuuuuuuuuu() { use s loo mod u8 {
- | ^^^^^^^^^^^ expected `{`
- |
-note: the `if` expression is missing a block after this condition
- --> $DIR/issue-62554.rs:6:20
- |
-LL | fn foo(u: u8) { if u8 macro_rules! u8 { (u6) => { fn uuuuuuuuuuu() { use s loo mod u8 {
- | ^^
-help: try placing this code inside a block
- |
-LL | fn foo(u: u8) { if u8 { macro_rules! u8 { (u6) => { fn uuuuuuuuuuu() { use s loo mod u8 { }
- | + +
-
-error: aborting due to 6 previous errors
+error: aborting due to previous error
diff --git a/tests/ui/parser/issues/issue-62881.rs b/tests/ui/parser/issues/issue-62881.rs
index b9204595f..cc80d4499 100644
--- a/tests/ui/parser/issues/issue-62881.rs
+++ b/tests/ui/parser/issues/issue-62881.rs
@@ -1,6 +1,3 @@
fn main() {}
-fn f() -> isize { fn f() -> isize {} pub f<
-//~^ ERROR missing `fn` or `struct` for function or struct definition
-//~| ERROR mismatched types
-//~ ERROR this file contains an unclosed delimiter
+fn f() -> isize { fn f() -> isize {} pub f< //~ ERROR this file contains an unclosed delimiter
diff --git a/tests/ui/parser/issues/issue-62881.stderr b/tests/ui/parser/issues/issue-62881.stderr
index 87be69baa..e57cbd181 100644
--- a/tests/ui/parser/issues/issue-62881.stderr
+++ b/tests/ui/parser/issues/issue-62881.stderr
@@ -1,26 +1,8 @@
error: this file contains an unclosed delimiter
- --> $DIR/issue-62881.rs:6:52
+ --> $DIR/issue-62881.rs:3:96
|
LL | fn f() -> isize { fn f() -> isize {} pub f<
- | - unclosed delimiter
-...
-LL |
- | ^
+ | - unclosed delimiter ^
-error: missing `fn` or `struct` for function or struct definition
- --> $DIR/issue-62881.rs:3:41
- |
-LL | fn f() -> isize { fn f() -> isize {} pub f<
- | ^
-
-error[E0308]: mismatched types
- --> $DIR/issue-62881.rs:3:29
- |
-LL | fn f() -> isize { fn f() -> isize {} pub f<
- | - ^^^^^ expected `isize`, found `()`
- | |
- | implicitly returns `()` as its body has no tail or `return` expression
-
-error: aborting due to 3 previous errors
+error: aborting due to previous error
-For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/parser/issues/issue-62894.rs b/tests/ui/parser/issues/issue-62894.rs
index b9c0bf834..4dfa406ea 100644
--- a/tests/ui/parser/issues/issue-62894.rs
+++ b/tests/ui/parser/issues/issue-62894.rs
@@ -1,6 +1,5 @@
// Regression test for #62894, shouldn't crash.
// error-pattern: this file contains an unclosed delimiter
-// error-pattern: expected one of `(`, `[`, or `{`, found keyword `fn`
fn f() { assert_eq!(f(), (), assert_eq!(assert_eq!
diff --git a/tests/ui/parser/issues/issue-62894.stderr b/tests/ui/parser/issues/issue-62894.stderr
index 07a203bf4..700479076 100644
--- a/tests/ui/parser/issues/issue-62894.stderr
+++ b/tests/ui/parser/issues/issue-62894.stderr
@@ -1,5 +1,5 @@
error: this file contains an unclosed delimiter
- --> $DIR/issue-62894.rs:7:14
+ --> $DIR/issue-62894.rs:6:14
|
LL | fn f() { assert_eq!(f(), (), assert_eq!(assert_eq!
| - - - unclosed delimiter
@@ -10,41 +10,5 @@ LL |
LL | fn main() {}
| ^
-error: this file contains an unclosed delimiter
- --> $DIR/issue-62894.rs:7:14
- |
-LL | fn f() { assert_eq!(f(), (), assert_eq!(assert_eq!
- | - - - unclosed delimiter
- | | |
- | | unclosed delimiter
- | unclosed delimiter
-LL |
-LL | fn main() {}
- | ^
-
-error: this file contains an unclosed delimiter
- --> $DIR/issue-62894.rs:7:14
- |
-LL | fn f() { assert_eq!(f(), (), assert_eq!(assert_eq!
- | - - - unclosed delimiter
- | | |
- | | unclosed delimiter
- | unclosed delimiter
-LL |
-LL | fn main() {}
- | ^
-
-error: expected one of `(`, `[`, or `{`, found keyword `fn`
- --> $DIR/issue-62894.rs:7:1
- |
-LL | fn f() { assert_eq!(f(), (), assert_eq!(assert_eq!
- | - expected one of `(`, `[`, or `{`
-LL |
-LL | fn main() {}
- | ^^ unexpected token
- --> $SRC_DIR/core/src/macros/mod.rs:LL:COL
- |
- = note: while parsing argument for this `expr` macro fragment
-
-error: aborting due to 4 previous errors
+error: aborting due to previous error
diff --git a/tests/ui/parser/issues/issue-62895.rs b/tests/ui/parser/issues/issue-62895.rs
index 53f17405d..33511dee9 100644
--- a/tests/ui/parser/issues/issue-62895.rs
+++ b/tests/ui/parser/issues/issue-62895.rs
@@ -1,11 +1,11 @@
fn main() {}
-fn v() -> isize { //~ ERROR mismatched types
-mod _ { //~ ERROR expected identifier
-pub fn g() -> isizee { //~ ERROR cannot find type `isizee` in this scope
-mod _ { //~ ERROR expected identifier
-pub g() -> is //~ ERROR missing `fn` for function definition
-(), w20);
+fn v() -> isize {
+mod _ {
+pub fn g() -> isizee {
+mod _ {
+pub g() -> is
+(), w20); //~ ERROR mismatched closing delimiter
}
-(), w20); //~ ERROR expected item, found `;`
+(), w20); //~ ERROR mismatched closing delimiter
}
diff --git a/tests/ui/parser/issues/issue-62895.stderr b/tests/ui/parser/issues/issue-62895.stderr
index 2e7e500f4..0ad9ac63e 100644
--- a/tests/ui/parser/issues/issue-62895.stderr
+++ b/tests/ui/parser/issues/issue-62895.stderr
@@ -1,47 +1,20 @@
-error: expected identifier, found reserved identifier `_`
- --> $DIR/issue-62895.rs:4:5
+error: mismatched closing delimiter: `)`
+ --> $DIR/issue-62895.rs:6:7
|
LL | mod _ {
- | ^ expected identifier, found reserved identifier
-
-error: expected identifier, found reserved identifier `_`
- --> $DIR/issue-62895.rs:6:5
- |
-LL | mod _ {
- | ^ expected identifier, found reserved identifier
-
-error: missing `fn` for function definition
- --> $DIR/issue-62895.rs:7:4
- |
+ | ^ unclosed delimiter
LL | pub g() -> is
- | ^^^^
- |
-help: add `fn` here to parse `g` as a public function
- |
-LL | pub fn g() -> is
- | ++
-
-error: expected item, found `;`
- --> $DIR/issue-62895.rs:10:9
- |
LL | (), w20);
- | ^ help: remove this semicolon
-
-error[E0412]: cannot find type `isizee` in this scope
- --> $DIR/issue-62895.rs:5:15
- |
-LL | pub fn g() -> isizee {
- | ^^^^^^ help: a builtin type with a similar name exists: `isize`
+ | ^ mismatched closing delimiter
-error[E0308]: mismatched types
- --> $DIR/issue-62895.rs:3:11
+error: mismatched closing delimiter: `)`
+ --> $DIR/issue-62895.rs:4:7
|
-LL | fn v() -> isize {
- | - ^^^^^ expected `isize`, found `()`
- | |
- | implicitly returns `()` as its body has no tail or `return` expression
+LL | mod _ {
+ | ^ unclosed delimiter
+...
+LL | (), w20);
+ | ^ mismatched closing delimiter
-error: aborting due to 6 previous errors
+error: aborting due to 2 previous errors
-Some errors have detailed explanations: E0308, E0412.
-For more information about an error, try `rustc --explain E0308`.
diff --git a/tests/ui/parser/issues/issue-62973.rs b/tests/ui/parser/issues/issue-62973.rs
index 1c5d0c6f8..22d754577 100644
--- a/tests/ui/parser/issues/issue-62973.rs
+++ b/tests/ui/parser/issues/issue-62973.rs
@@ -1,5 +1,5 @@
// ignore-tidy-trailing-newlines
-// error-pattern: aborting due to 7 previous errors
+// error-pattern: aborting due to 3 previous errors
fn main() {}
diff --git a/tests/ui/parser/issues/issue-62973.stderr b/tests/ui/parser/issues/issue-62973.stderr
index 4737bc718..14411a8cb 100644
--- a/tests/ui/parser/issues/issue-62973.stderr
+++ b/tests/ui/parser/issues/issue-62973.stderr
@@ -1,68 +1,3 @@
-error: this file contains an unclosed delimiter
- --> $DIR/issue-62973.rs:8:2
- |
-LL | fn p() { match s { v, E { [) {) }
- | - - unclosed delimiter
- | |
- | unclosed delimiter
-LL |
-LL |
- | ^
-
-error: this file contains an unclosed delimiter
- --> $DIR/issue-62973.rs:8:2
- |
-LL | fn p() { match s { v, E { [) {) }
- | - - unclosed delimiter
- | |
- | unclosed delimiter
-LL |
-LL |
- | ^
-
-error: expected one of `,`, `:`, or `}`, found `{`
- --> $DIR/issue-62973.rs:6:8
- |
-LL | fn p() { match s { v, E { [) {) }
- | ^ - ^ expected one of `,`, `:`, or `}`
- | | |
- | | while parsing this struct
- | unclosed delimiter
- |
-help: `}` may belong here
- |
-LL | fn p() { match s { v, E} { [) {) }
- | +
-help: try naming a field
- |
-LL | fn p() { match s { v, E: E { [) {) }
- | ++
-
-error: struct literals are not allowed here
- --> $DIR/issue-62973.rs:6:16
- |
-LL | fn p() { match s { v, E { [) {) }
- | ________________^
-LL | |
-LL | |
- | |_^
- |
-help: surround the struct literal with parentheses
- |
-LL ~ fn p() { match (s { v, E { [) {) }
-LL |
-LL ~ )
- |
-
-error: expected one of `.`, `?`, `{`, or an operator, found `}`
- --> $DIR/issue-62973.rs:8:2
- |
-LL | fn p() { match s { v, E { [) {) }
- | ----- while parsing this `match` expression
-LL |
-LL |
- | ^ expected one of `.`, `?`, `{`, or an operator
-
error: mismatched closing delimiter: `)`
--> $DIR/issue-62973.rs:6:27
|
@@ -79,5 +14,18 @@ LL | fn p() { match s { v, E { [) {) }
| |
| unclosed delimiter
-error: aborting due to 7 previous errors
+error: this file contains an unclosed delimiter
+ --> $DIR/issue-62973.rs:8:2
+ |
+LL | fn p() { match s { v, E { [) {) }
+ | - - - - missing open `(` for this delimiter
+ | | | |
+ | | | missing open `(` for this delimiter
+ | | unclosed delimiter
+ | unclosed delimiter
+LL |
+LL |
+ | ^
+
+error: aborting due to 3 previous errors
diff --git a/tests/ui/parser/issues/issue-63116.rs b/tests/ui/parser/issues/issue-63116.rs
index 430bc1d71..6b9d9cdbe 100644
--- a/tests/ui/parser/issues/issue-63116.rs
+++ b/tests/ui/parser/issues/issue-63116.rs
@@ -1,3 +1,3 @@
// fixed by #66361
-// error-pattern: aborting due to 3 previous errors
+// error-pattern: aborting due to 2 previous errors
impl W <s(f;Y(;]
diff --git a/tests/ui/parser/issues/issue-63116.stderr b/tests/ui/parser/issues/issue-63116.stderr
index cfdd99d14..27c94f337 100644
--- a/tests/ui/parser/issues/issue-63116.stderr
+++ b/tests/ui/parser/issues/issue-63116.stderr
@@ -1,17 +1,3 @@
-error: this file contains an unclosed delimiter
- --> $DIR/issue-63116.rs:3:18
- |
-LL | impl W <s(f;Y(;]
- | - ^
- | |
- | unclosed delimiter
-
-error: expected one of `!`, `(`, `)`, `+`, `,`, `::`, or `<`, found `;`
- --> $DIR/issue-63116.rs:3:12
- |
-LL | impl W <s(f;Y(;]
- | ^ expected one of 7 possible tokens
-
error: mismatched closing delimiter: `]`
--> $DIR/issue-63116.rs:3:14
|
@@ -20,5 +6,14 @@ LL | impl W <s(f;Y(;]
| |
| unclosed delimiter
-error: aborting due to 3 previous errors
+error: this file contains an unclosed delimiter
+ --> $DIR/issue-63116.rs:3:18
+ |
+LL | impl W <s(f;Y(;]
+ | - - ^
+ | | |
+ | | missing open `[` for this delimiter
+ | unclosed delimiter
+
+error: aborting due to 2 previous errors
diff --git a/tests/ui/parser/issues/issue-63135.rs b/tests/ui/parser/issues/issue-63135.rs
index a5a8de854..d61197dc5 100644
--- a/tests/ui/parser/issues/issue-63135.rs
+++ b/tests/ui/parser/issues/issue-63135.rs
@@ -1,3 +1,3 @@
-// error-pattern: aborting due to 5 previous errors
-
+// error-pattern: this file contains an unclosed delimiter
+// error-pattern: aborting due to previous error
fn i(n{...,f #
diff --git a/tests/ui/parser/issues/issue-63135.stderr b/tests/ui/parser/issues/issue-63135.stderr
index 80e9ac5be..ff9d99c28 100644
--- a/tests/ui/parser/issues/issue-63135.stderr
+++ b/tests/ui/parser/issues/issue-63135.stderr
@@ -7,37 +7,5 @@ LL | fn i(n{...,f #
| | unclosed delimiter
| unclosed delimiter
-error: this file contains an unclosed delimiter
- --> $DIR/issue-63135.rs:3:16
- |
-LL | fn i(n{...,f #
- | - - ^
- | | |
- | | unclosed delimiter
- | unclosed delimiter
-
-error: expected field pattern, found `...`
- --> $DIR/issue-63135.rs:3:8
- |
-LL | fn i(n{...,f #
- | ^^^ help: to omit remaining fields, use one fewer `.`: `..`
-
-error: expected `}`, found `,`
- --> $DIR/issue-63135.rs:3:11
- |
-LL | fn i(n{...,f #
- | ---^
- | | |
- | | expected `}`
- | `..` must be at the end and cannot have a trailing comma
-
-error: expected one of `!` or `[`, found `}`
- --> $DIR/issue-63135.rs:3:16
- |
-LL | fn i(n{...,f #
- | - ^ expected one of `!` or `[`
- | |
- | while parsing the fields for this pattern
-
-error: aborting due to 5 previous errors
+error: aborting due to previous error
diff --git a/tests/ui/parser/issues/issue-66357-unexpected-unreachable.rs b/tests/ui/parser/issues/issue-66357-unexpected-unreachable.rs
index aed428bfc..69a2dfe6c 100644
--- a/tests/ui/parser/issues/issue-66357-unexpected-unreachable.rs
+++ b/tests/ui/parser/issues/issue-66357-unexpected-unreachable.rs
@@ -9,6 +9,4 @@
//
// ended up bubbling up `Ok(true)` to `unexpected` which then used `unreachable!()`.
-fn f() { |[](* }
-//~^ ERROR expected one of `,` or `:`, found `(`
-//~| ERROR expected one of `&`, `(`, `)`, `-`, `...`, `..=`, `..`, `[`, `_`, `box`, `mut`, `ref`, `|`, identifier, or path, found `*`
+fn f() { |[](* } //~ ERROR mismatched closing delimiter
diff --git a/tests/ui/parser/issues/issue-66357-unexpected-unreachable.stderr b/tests/ui/parser/issues/issue-66357-unexpected-unreachable.stderr
index 6cbab855c..079fff37e 100644
--- a/tests/ui/parser/issues/issue-66357-unexpected-unreachable.stderr
+++ b/tests/ui/parser/issues/issue-66357-unexpected-unreachable.stderr
@@ -1,16 +1,11 @@
-error: expected one of `,` or `:`, found `(`
+error: mismatched closing delimiter: `}`
--> $DIR/issue-66357-unexpected-unreachable.rs:12:13
|
LL | fn f() { |[](* }
- | ^ expected one of `,` or `:`
+ | - ^ ^ mismatched closing delimiter
+ | | |
+ | | unclosed delimiter
+ | closing delimiter possibly meant for this
-error: expected one of `&`, `(`, `)`, `-`, `...`, `..=`, `..`, `[`, `_`, `box`, `mut`, `ref`, `|`, identifier, or path, found `*`
- --> $DIR/issue-66357-unexpected-unreachable.rs:12:13
- |
-LL | fn f() { |[](* }
- | ^^ help: `)` may belong here
- | |
- | unclosed delimiter
-
-error: aborting due to 2 previous errors
+error: aborting due to previous error
diff --git a/tests/ui/parser/issues/issue-67377-invalid-syntax-in-enum-discriminant.rs b/tests/ui/parser/issues/issue-67377-invalid-syntax-in-enum-discriminant.rs
index 87222ef4b..e712160fc 100644
--- a/tests/ui/parser/issues/issue-67377-invalid-syntax-in-enum-discriminant.rs
+++ b/tests/ui/parser/issues/issue-67377-invalid-syntax-in-enum-discriminant.rs
@@ -4,9 +4,6 @@ mod a {
enum Bug {
V = [PhantomData; { [ () ].len() ].len() as isize,
//~^ ERROR mismatched closing delimiter: `]`
- //~| ERROR mismatched closing delimiter: `]`
- //~| ERROR mismatched closing delimiter: `]`
- //~| ERROR mismatched closing delimiter: `]`
}
}
@@ -14,10 +11,6 @@ mod b {
enum Bug {
V = [Vec::new; { [].len() ].len() as isize,
//~^ ERROR mismatched closing delimiter: `]`
- //~| ERROR mismatched closing delimiter: `]`
- //~| ERROR mismatched closing delimiter: `]`
- //~| ERROR mismatched closing delimiter: `]`
- //~| ERROR type annotations needed
}
}
@@ -25,11 +18,6 @@ mod c {
enum Bug {
V = [Vec::new; { [0].len() ].len() as isize,
//~^ ERROR mismatched closing delimiter: `]`
- //~| ERROR mismatched closing delimiter: `]`
- //~| ERROR mismatched closing delimiter: `]`
- //~| ERROR mismatched closing delimiter: `]`
- //~| ERROR type annotations needed
- }
}
-fn main() {}
+fn main() {} //~ ERROR this file contains an unclosed delimiter
diff --git a/tests/ui/parser/issues/issue-67377-invalid-syntax-in-enum-discriminant.stderr b/tests/ui/parser/issues/issue-67377-invalid-syntax-in-enum-discriminant.stderr
index a00f37ed6..9f631edf6 100644
--- a/tests/ui/parser/issues/issue-67377-invalid-syntax-in-enum-discriminant.stderr
+++ b/tests/ui/parser/issues/issue-67377-invalid-syntax-in-enum-discriminant.stderr
@@ -8,7 +8,7 @@ LL | V = [PhantomData; { [ () ].len() ].len() as isize,
| closing delimiter possibly meant for this
error: mismatched closing delimiter: `]`
- --> $DIR/issue-67377-invalid-syntax-in-enum-discriminant.rs:15:24
+ --> $DIR/issue-67377-invalid-syntax-in-enum-discriminant.rs:12:24
|
LL | V = [Vec::new; { [].len() ].len() as isize,
| - ^ ^ mismatched closing delimiter
@@ -17,7 +17,7 @@ LL | V = [Vec::new; { [].len() ].len() as isize,
| closing delimiter possibly meant for this
error: mismatched closing delimiter: `]`
- --> $DIR/issue-67377-invalid-syntax-in-enum-discriminant.rs:26:24
+ --> $DIR/issue-67377-invalid-syntax-in-enum-discriminant.rs:19:24
|
LL | V = [Vec::new; { [0].len() ].len() as isize,
| - ^ ^ mismatched closing delimiter
@@ -25,104 +25,23 @@ LL | V = [Vec::new; { [0].len() ].len() as isize,
| | unclosed delimiter
| closing delimiter possibly meant for this
-error: mismatched closing delimiter: `]`
- --> $DIR/issue-67377-invalid-syntax-in-enum-discriminant.rs:5:27
- |
-LL | V = [PhantomData; { [ () ].len() ].len() as isize,
- | - ^ ^ mismatched closing delimiter
- | | |
- | | unclosed delimiter
- | closing delimiter possibly meant for this
-
-error: mismatched closing delimiter: `]`
- --> $DIR/issue-67377-invalid-syntax-in-enum-discriminant.rs:15:24
- |
-LL | V = [Vec::new; { [].len() ].len() as isize,
- | - ^ ^ mismatched closing delimiter
- | | |
- | | unclosed delimiter
- | closing delimiter possibly meant for this
-
-error: mismatched closing delimiter: `]`
- --> $DIR/issue-67377-invalid-syntax-in-enum-discriminant.rs:26:24
- |
-LL | V = [Vec::new; { [0].len() ].len() as isize,
- | - ^ ^ mismatched closing delimiter
- | | |
- | | unclosed delimiter
- | closing delimiter possibly meant for this
-
-error: mismatched closing delimiter: `]`
- --> $DIR/issue-67377-invalid-syntax-in-enum-discriminant.rs:5:27
- |
-LL | V = [PhantomData; { [ () ].len() ].len() as isize,
- | - ^ ^ mismatched closing delimiter
- | | |
- | | unclosed delimiter
- | closing delimiter possibly meant for this
-
-error: mismatched closing delimiter: `]`
- --> $DIR/issue-67377-invalid-syntax-in-enum-discriminant.rs:15:24
- |
-LL | V = [Vec::new; { [].len() ].len() as isize,
- | - ^ ^ mismatched closing delimiter
- | | |
- | | unclosed delimiter
- | closing delimiter possibly meant for this
-
-error: mismatched closing delimiter: `]`
- --> $DIR/issue-67377-invalid-syntax-in-enum-discriminant.rs:26:24
- |
-LL | V = [Vec::new; { [0].len() ].len() as isize,
- | - ^ ^ mismatched closing delimiter
- | | |
- | | unclosed delimiter
- | closing delimiter possibly meant for this
-
-error: mismatched closing delimiter: `]`
- --> $DIR/issue-67377-invalid-syntax-in-enum-discriminant.rs:5:27
+error: this file contains an unclosed delimiter
+ --> $DIR/issue-67377-invalid-syntax-in-enum-discriminant.rs:23:65
|
LL | V = [PhantomData; { [ () ].len() ].len() as isize,
- | - ^ ^ mismatched closing delimiter
- | | |
- | | unclosed delimiter
- | closing delimiter possibly meant for this
-
-error: mismatched closing delimiter: `]`
- --> $DIR/issue-67377-invalid-syntax-in-enum-discriminant.rs:15:24
- |
+ | - missing open `[` for this delimiter
+...
LL | V = [Vec::new; { [].len() ].len() as isize,
- | - ^ ^ mismatched closing delimiter
- | | |
- | | unclosed delimiter
- | closing delimiter possibly meant for this
-
-error: mismatched closing delimiter: `]`
- --> $DIR/issue-67377-invalid-syntax-in-enum-discriminant.rs:26:24
- |
+ | - missing open `[` for this delimiter
+...
+LL | mod c {
+ | - unclosed delimiter
+LL | enum Bug {
LL | V = [Vec::new; { [0].len() ].len() as isize,
- | - ^ ^ mismatched closing delimiter
- | | |
- | | unclosed delimiter
- | closing delimiter possibly meant for this
-
-error[E0282]: type annotations needed
- --> $DIR/issue-67377-invalid-syntax-in-enum-discriminant.rs:15:26
- |
-LL | V = [Vec::new; { [].len() ].len() as isize,
- | ^^ cannot infer type for type parameter `T`
-
-error[E0282]: type annotations needed
- --> $DIR/issue-67377-invalid-syntax-in-enum-discriminant.rs:26:14
- |
-LL | V = [Vec::new; { [0].len() ].len() as isize,
- | ^^^^^^^^ cannot infer type of the type parameter `T` declared on the struct `Vec`
- |
-help: consider specifying the generic argument
- |
-LL | V = [Vec::<T>::new; { [0].len() ].len() as isize,
- | +++++
+ | - missing open `[` for this delimiter
+...
+LL | fn main() {}
+ | ^
-error: aborting due to 14 previous errors
+error: aborting due to 4 previous errors
-For more information about this error, try `rustc --explain E0282`.
diff --git a/tests/ui/parser/issues/issue-68629.rs b/tests/ui/parser/issues/issue-68629.rs
index 672a31f12..af89bb586 100644
--- a/tests/ui/parser/issues/issue-68629.rs
+++ b/tests/ui/parser/issues/issue-68629.rs
Binary files differ
diff --git a/tests/ui/parser/issues/issue-68629.stderr b/tests/ui/parser/issues/issue-68629.stderr
index 43a903e6c..2562baa1c 100644
--- a/tests/ui/parser/issues/issue-68629.stderr
+++ b/tests/ui/parser/issues/issue-68629.stderr
Binary files differ
diff --git a/tests/ui/parser/issues/issue-69259.rs b/tests/ui/parser/issues/issue-69259.rs
new file mode 100644
index 000000000..01fc2c085
--- /dev/null
+++ b/tests/ui/parser/issues/issue-69259.rs
@@ -0,0 +1,3 @@
+fn main() {}
+
+fn f) {} //~ ERROR unexpected closing delimiter
diff --git a/tests/ui/parser/issues/issue-69259.stderr b/tests/ui/parser/issues/issue-69259.stderr
new file mode 100644
index 000000000..604b7de33
--- /dev/null
+++ b/tests/ui/parser/issues/issue-69259.stderr
@@ -0,0 +1,8 @@
+error: unexpected closing delimiter: `)`
+ --> $DIR/issue-69259.rs:3:5
+ |
+LL | fn f) {}
+ | ^ unexpected closing delimiter
+
+error: aborting due to previous error
+
diff --git a/tests/ui/parser/issues/issue-70583-block-is-empty-1.stderr b/tests/ui/parser/issues/issue-70583-block-is-empty-1.stderr
index 39bf113ef..46cbb056d 100644
--- a/tests/ui/parser/issues/issue-70583-block-is-empty-1.stderr
+++ b/tests/ui/parser/issues/issue-70583-block-is-empty-1.stderr
@@ -2,10 +2,10 @@ error: unexpected closing delimiter: `}`
--> $DIR/issue-70583-block-is-empty-1.rs:20:1
|
LL | fn struct_generic(x: Vec<i32>) {
- | - this opening brace...
+ | - this delimiter might not be properly closed...
...
LL | }
- | - ...matches this closing brace
+ | - ...as it matches this but it has different indentation
LL | }
| ^ unexpected closing delimiter
diff --git a/tests/ui/parser/issues/issue-70583-block-is-empty-2.stderr b/tests/ui/parser/issues/issue-70583-block-is-empty-2.stderr
index 5d37b2164..9ae94c701 100644
--- a/tests/ui/parser/issues/issue-70583-block-is-empty-2.stderr
+++ b/tests/ui/parser/issues/issue-70583-block-is-empty-2.stderr
@@ -1,8 +1,12 @@
error: unexpected closing delimiter: `}`
--> $DIR/issue-70583-block-is-empty-2.rs:14:1
|
+LL | match self {
+ | - this delimiter might not be properly closed...
LL | ErrorHandled::Reported => {}}
- | -- block is empty, you might have not meant to close it
+ | --- ...as it matches this but it has different indentation
+ | |
+ | block is empty, you might have not meant to close it
...
LL | }
| ^ unexpected closing delimiter
diff --git a/tests/ui/parser/issues/issue-84104.rs b/tests/ui/parser/issues/issue-84104.rs
index 998949b94..962eb69bd 100644
--- a/tests/ui/parser/issues/issue-84104.rs
+++ b/tests/ui/parser/issues/issue-84104.rs
@@ -1,3 +1,2 @@
// error-pattern: this file contains an unclosed delimiter
-// error-pattern: expected one of
#[i=i::<ښܖ<
diff --git a/tests/ui/parser/issues/issue-84104.stderr b/tests/ui/parser/issues/issue-84104.stderr
index aff31f2c9..7ad59f845 100644
--- a/tests/ui/parser/issues/issue-84104.stderr
+++ b/tests/ui/parser/issues/issue-84104.stderr
@@ -1,16 +1,10 @@
error: this file contains an unclosed delimiter
- --> $DIR/issue-84104.rs:3:13
+ --> $DIR/issue-84104.rs:2:13
|
LL | #[i=i::<ښܖ<
| - ^
| |
| unclosed delimiter
-error: expected one of `>`, a const expression, lifetime, or type, found `]`
- --> $DIR/issue-84104.rs:3:13
- |
-LL | #[i=i::<ښܖ<
- | ^ expected one of `>`, a const expression, lifetime, or type
-
-error: aborting due to 2 previous errors
+error: aborting due to previous error
diff --git a/tests/ui/parser/issues/issue-84148-2.rs b/tests/ui/parser/issues/issue-84148-2.rs
index 2f6a7facf..e677abde5 100644
--- a/tests/ui/parser/issues/issue-84148-2.rs
+++ b/tests/ui/parser/issues/issue-84148-2.rs
@@ -1,3 +1,2 @@
// error-pattern: this file contains an unclosed delimiter
-// error-pattern: invalid `?` in type
fn f(t:for<>t?
diff --git a/tests/ui/parser/issues/issue-84148-2.stderr b/tests/ui/parser/issues/issue-84148-2.stderr
index 71d543f9b..20761180e 100644
--- a/tests/ui/parser/issues/issue-84148-2.stderr
+++ b/tests/ui/parser/issues/issue-84148-2.stderr
@@ -1,27 +1,10 @@
error: this file contains an unclosed delimiter
- --> $DIR/issue-84148-2.rs:3:16
+ --> $DIR/issue-84148-2.rs:2:16
|
LL | fn f(t:for<>t?
| - ^
| |
| unclosed delimiter
-error: invalid `?` in type
- --> $DIR/issue-84148-2.rs:3:14
- |
-LL | fn f(t:for<>t?
- | ^ `?` is only allowed on expressions, not types
- |
-help: if you meant to express that the type might not contain a value, use the `Option` wrapper type
- |
-LL | fn f(t:Option<for<>t>
- | +++++++ ~
-
-error: expected one of `->`, `where`, or `{`, found `<eof>`
- --> $DIR/issue-84148-2.rs:3:16
- |
-LL | fn f(t:for<>t?
- | ^ expected one of `->`, `where`, or `{`
-
-error: aborting due to 3 previous errors
+error: aborting due to previous error
diff --git a/tests/ui/parser/issues/issue-87086-colon-path-sep.rs b/tests/ui/parser/issues/issue-87086-colon-path-sep.rs
index 0b7b67496..e1ea38f27 100644
--- a/tests/ui/parser/issues/issue-87086-colon-path-sep.rs
+++ b/tests/ui/parser/issues/issue-87086-colon-path-sep.rs
@@ -68,7 +68,6 @@ fn main() {
Foo:Bar::Baz => {}
//~^ ERROR: expected one of
//~| HELP: maybe write a path separator here
- //~| ERROR: failed to resolve: `Bar` is a variant, not a module
}
match myfoo {
Foo::Bar => {}
diff --git a/tests/ui/parser/issues/issue-87086-colon-path-sep.stderr b/tests/ui/parser/issues/issue-87086-colon-path-sep.stderr
index 2050a16be..63b072ac4 100644
--- a/tests/ui/parser/issues/issue-87086-colon-path-sep.stderr
+++ b/tests/ui/parser/issues/issue-87086-colon-path-sep.stderr
@@ -2,89 +2,118 @@ error: expected one of `@` or `|`, found `:`
--> $DIR/issue-87086-colon-path-sep.rs:17:12
|
LL | Foo:Bar => {}
- | ^
+ | ^--- specifying the type of a pattern isn't supported
| |
| expected one of `@` or `|`
- | help: maybe write a path separator here: `::`
+ |
+help: maybe write a path separator here
+ |
+LL | Foo::Bar => {}
+ | ~~
error: expected one of `!`, `(`, `...`, `..=`, `..`, `::`, `{`, or `|`, found `:`
--> $DIR/issue-87086-colon-path-sep.rs:23:17
|
LL | qux::Foo:Bar => {}
- | ^
+ | ^--- specifying the type of a pattern isn't supported
| |
| expected one of 8 possible tokens
- | help: maybe write a path separator here: `::`
+ |
+help: maybe write a path separator here
+ |
+LL | qux::Foo::Bar => {}
+ | ~~
error: expected one of `@` or `|`, found `:`
--> $DIR/issue-87086-colon-path-sep.rs:29:12
|
LL | qux:Foo::Baz => {}
- | ^
+ | ^-------- specifying the type of a pattern isn't supported
| |
| expected one of `@` or `|`
- | help: maybe write a path separator here: `::`
+ |
+help: maybe write a path separator here
+ |
+LL | qux::Foo::Baz => {}
+ | ~~
error: expected one of `@` or `|`, found `:`
--> $DIR/issue-87086-colon-path-sep.rs:35:12
|
LL | qux: Foo::Baz if true => {}
- | ^
+ | ^ -------- specifying the type of a pattern isn't supported
| |
| expected one of `@` or `|`
- | help: maybe write a path separator here: `::`
+ |
+help: maybe write a path separator here
+ |
+LL | qux::Foo::Baz if true => {}
+ | ~~
error: expected one of `@` or `|`, found `:`
--> $DIR/issue-87086-colon-path-sep.rs:40:15
|
LL | if let Foo:Bar = f() {
- | ^
+ | ^--- specifying the type of a pattern isn't supported
| |
| expected one of `@` or `|`
- | help: maybe write a path separator here: `::`
+ |
+help: maybe write a path separator here
+ |
+LL | if let Foo::Bar = f() {
+ | ~~
error: expected one of `@` or `|`, found `:`
--> $DIR/issue-87086-colon-path-sep.rs:48:16
|
LL | ref qux: Foo::Baz => {}
- | ^
+ | ^ -------- specifying the type of a pattern isn't supported
| |
| expected one of `@` or `|`
- | help: maybe write a path separator here: `::`
+ |
+help: maybe write a path separator here
+ |
+LL | ref qux::Foo::Baz => {}
+ | ~~
error: expected one of `@` or `|`, found `:`
--> $DIR/issue-87086-colon-path-sep.rs:57:16
|
LL | mut qux: Foo::Baz => {}
- | ^
+ | ^ -------- specifying the type of a pattern isn't supported
| |
| expected one of `@` or `|`
- | help: maybe write a path separator here: `::`
+ |
+help: maybe write a path separator here
+ |
+LL | mut qux::Foo::Baz => {}
+ | ~~
error: expected one of `@` or `|`, found `:`
--> $DIR/issue-87086-colon-path-sep.rs:68:12
|
LL | Foo:Bar::Baz => {}
- | ^
+ | ^-------- specifying the type of a pattern isn't supported
| |
| expected one of `@` or `|`
- | help: maybe write a path separator here: `::`
+ |
+help: maybe write a path separator here
+ |
+LL | Foo::Bar::Baz => {}
+ | ~~
error: expected one of `@` or `|`, found `:`
- --> $DIR/issue-87086-colon-path-sep.rs:75:12
+ --> $DIR/issue-87086-colon-path-sep.rs:74:12
|
LL | Foo:Bar => {}
- | ^
+ | ^--- specifying the type of a pattern isn't supported
| |
| expected one of `@` or `|`
- | help: maybe write a path separator here: `::`
-
-error[E0433]: failed to resolve: `Bar` is a variant, not a module
- --> $DIR/issue-87086-colon-path-sep.rs:68:13
|
-LL | Foo:Bar::Baz => {}
- | ^^^ `Bar` is a variant, not a module
+help: maybe write a path separator here
+ |
+LL | Foo::Bar => {}
+ | ~~
-error: aborting due to 10 previous errors
+error: aborting due to 9 previous errors
-For more information about this error, try `rustc --explain E0433`.
diff --git a/tests/ui/parser/issues/issue-87812-path.stderr b/tests/ui/parser/issues/issue-87812-path.stderr
index f8ee05175..d045f4821 100644
--- a/tests/ui/parser/issues/issue-87812-path.stderr
+++ b/tests/ui/parser/issues/issue-87812-path.stderr
@@ -2,7 +2,7 @@ error[E0308]: mismatched types
--> $DIR/issue-87812-path.rs:3:24
|
LL | let _: usize = $f;
- | ----- ^^ expected `usize`, found struct `Baz`
+ | ----- ^^ expected `usize`, found `Baz`
| |
| expected due to this
...
diff --git a/tests/ui/parser/issues/issue-88770.rs b/tests/ui/parser/issues/issue-88770.rs
index bb69951c7..9341415b2 100644
--- a/tests/ui/parser/issues/issue-88770.rs
+++ b/tests/ui/parser/issues/issue-88770.rs
@@ -1,9 +1,6 @@
// 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 one of `!`, `)`, `,`, `.`, `::`, `;`, `?`, `{`, or an operator, found `e`
fn m(){print!("",(c for&g
u
diff --git a/tests/ui/parser/issues/issue-88770.stderr b/tests/ui/parser/issues/issue-88770.stderr
index 4e3a21613..836f44953 100644
--- a/tests/ui/parser/issues/issue-88770.stderr
+++ b/tests/ui/parser/issues/issue-88770.stderr
@@ -1,5 +1,5 @@
error: this file contains an unclosed delimiter
- --> $DIR/issue-88770.rs:11:3
+ --> $DIR/issue-88770.rs:8:3
|
LL | fn m(){print!("",(c for&g
| - - - unclosed delimiter
@@ -10,51 +10,5 @@ LL | fn m(){print!("",(c for&g
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 one of `!`, `)`, `,`, `.`, `::`, `;`, `?`, `{`, or an operator, found `e`
- --> $DIR/issue-88770.rs:11:1
- |
-LL | e
- | - expected one of 9 possible tokens
-LL | e
- | ^ unexpected token
-
-error: aborting due to 6 previous errors
+error: aborting due to previous error
diff --git a/tests/ui/parser/macro-mismatched-delim-paren-brace.stderr b/tests/ui/parser/macro-mismatched-delim-paren-brace.stderr
index 967a3e6fd..34217e21a 100644
--- a/tests/ui/parser/macro-mismatched-delim-paren-brace.stderr
+++ b/tests/ui/parser/macro-mismatched-delim-paren-brace.stderr
@@ -1,14 +1,3 @@
-error: unexpected closing delimiter: `}`
- --> $DIR/macro-mismatched-delim-paren-brace.rs:5:1
- |
-LL | fn main() {
- | - this opening brace...
-...
-LL | }
- | - ...matches this closing brace
-LL | }
- | ^ unexpected closing delimiter
-
error: mismatched closing delimiter: `}`
--> $DIR/macro-mismatched-delim-paren-brace.rs:2:10
|
@@ -18,5 +7,16 @@ LL | bar, "baz", 1, 2.0
LL | }
| ^ mismatched closing delimiter
+error: unexpected closing delimiter: `}`
+ --> $DIR/macro-mismatched-delim-paren-brace.rs:5:1
+ |
+LL | fn main() {
+ | - this delimiter might not be properly closed...
+...
+LL | }
+ | - ...as it matches this but it has different indentation
+LL | }
+ | ^ unexpected closing delimiter
+
error: aborting due to 2 previous errors
diff --git a/tests/ui/parser/match-arm-without-braces.stderr b/tests/ui/parser/match-arm-without-braces.stderr
index 37d55aa53..ee1c8e562 100644
--- a/tests/ui/parser/match-arm-without-braces.stderr
+++ b/tests/ui/parser/match-arm-without-braces.stderr
@@ -2,10 +2,14 @@ error: `match` arm body without braces
--> $DIR/match-arm-without-braces.rs:26:27
|
LL | Some(Val::Foo) => 3;
- | -- ^- help: use a comma to end a `match` arm expression: `,`
- | | |
- | | this statement is not surrounded by a body
+ | -- ^ this statement is not surrounded by a body
+ | |
| while parsing the `match` arm starting here
+ |
+help: replace `;` with `,` to end a `match` arm expression
+ |
+LL | Some(Val::Foo) => 3,
+ | ~
error: `match` arm body without braces
--> $DIR/match-arm-without-braces.rs:31:11
diff --git a/tests/ui/parser/mbe_missing_right_paren.rs b/tests/ui/parser/mbe_missing_right_paren.rs
index 689176b3e..9a92e67da 100644
--- a/tests/ui/parser/mbe_missing_right_paren.rs
+++ b/tests/ui/parser/mbe_missing_right_paren.rs
@@ -1,3 +1,3 @@
// ignore-tidy-trailing-newlines
-// error-pattern: aborting due to 3 previous errors
+// error-pattern: this file contains an unclosed delimiter
macro_rules! abc(ؼ \ No newline at end of file
diff --git a/tests/ui/parser/mbe_missing_right_paren.stderr b/tests/ui/parser/mbe_missing_right_paren.stderr
index ccaf77d39..d2af94683 100644
--- a/tests/ui/parser/mbe_missing_right_paren.stderr
+++ b/tests/ui/parser/mbe_missing_right_paren.stderr
@@ -6,26 +6,5 @@ LL | macro_rules! abc(ؼ
| |
| unclosed delimiter
-error: macros that expand to items must be delimited with braces or followed by a semicolon
- --> $DIR/mbe_missing_right_paren.rs:3:17
- |
-LL | macro_rules! abc(ؼ
- | ^^
- |
-help: change the delimiters to curly braces
- |
-LL | macro_rules! abc { /* items */ }
- | ~~~~~~~~~~~~~~~
-help: add a semicolon
- |
-LL | macro_rules! abc(ؼ;
- | +
-
-error: unexpected end of macro invocation
- --> $DIR/mbe_missing_right_paren.rs:3:19
- |
-LL | macro_rules! abc(ؼ
- | ^ missing tokens in macro arguments
-
-error: aborting due to 3 previous errors
+error: aborting due to previous error
diff --git a/tests/ui/parser/mismatched-braces/missing-close-brace-in-impl-trait.rs b/tests/ui/parser/mismatched-braces/missing-close-brace-in-impl-trait.rs
index 8f46970b1..79de98d8b 100644
--- a/tests/ui/parser/mismatched-braces/missing-close-brace-in-impl-trait.rs
+++ b/tests/ui/parser/mismatched-braces/missing-close-brace-in-impl-trait.rs
@@ -1,13 +1,13 @@
fn main() {}
-impl T for () { //~ ERROR cannot find trait `T` in this scope
+impl T for () {
fn foo(&self) {}
-trait T { //~ ERROR trait is not supported in `trait`s or `impl`s
+trait T {
fn foo(&self);
}
-pub(crate) struct Bar<T>(); //~ ERROR struct is not supported in `trait`s or `impl`s
+pub(crate) struct Bar<T>();
//~ ERROR this file contains an unclosed delimiter
diff --git a/tests/ui/parser/mismatched-braces/missing-close-brace-in-impl-trait.stderr b/tests/ui/parser/mismatched-braces/missing-close-brace-in-impl-trait.stderr
index cc7cc0c55..d91a7f054 100644
--- a/tests/ui/parser/mismatched-braces/missing-close-brace-in-impl-trait.stderr
+++ b/tests/ui/parser/mismatched-braces/missing-close-brace-in-impl-trait.stderr
@@ -7,28 +7,5 @@ LL | impl T for () {
LL |
| ^
-error: trait is not supported in `trait`s or `impl`s
- --> $DIR/missing-close-brace-in-impl-trait.rs:7:1
- |
-LL | trait T {
- | ^^^^^^^
- |
- = help: consider moving the trait out to a nearby module scope
-
-error: struct is not supported in `trait`s or `impl`s
- --> $DIR/missing-close-brace-in-impl-trait.rs:11:1
- |
-LL | pub(crate) struct Bar<T>();
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
- |
- = help: consider moving the struct out to a nearby module scope
-
-error[E0405]: cannot find trait `T` in this scope
- --> $DIR/missing-close-brace-in-impl-trait.rs:3:6
- |
-LL | impl T for () {
- | ^ not found in this scope
-
-error: aborting due to 4 previous errors
+error: aborting due to previous error
-For more information about this error, try `rustc --explain E0405`.
diff --git a/tests/ui/parser/mismatched-braces/missing-close-brace-in-struct.rs b/tests/ui/parser/mismatched-braces/missing-close-brace-in-struct.rs
index 090a17b41..88bc72576 100644
--- a/tests/ui/parser/mismatched-braces/missing-close-brace-in-struct.rs
+++ b/tests/ui/parser/mismatched-braces/missing-close-brace-in-struct.rs
@@ -1,7 +1,7 @@
pub(crate) struct Bar<T> {
foo: T,
-trait T { //~ ERROR expected identifier, found keyword `trait`
+trait T {
fn foo(&self);
}
diff --git a/tests/ui/parser/mismatched-braces/missing-close-brace-in-struct.stderr b/tests/ui/parser/mismatched-braces/missing-close-brace-in-struct.stderr
index ad1e90e43..d01d9ed60 100644
--- a/tests/ui/parser/mismatched-braces/missing-close-brace-in-struct.stderr
+++ b/tests/ui/parser/mismatched-braces/missing-close-brace-in-struct.stderr
@@ -7,14 +7,5 @@ LL | pub(crate) struct Bar<T> {
LL | fn main() {}
| ^
-error: expected identifier, found keyword `trait`
- --> $DIR/missing-close-brace-in-struct.rs:4:1
- |
-LL | pub(crate) struct Bar<T> {
- | --- while parsing this struct
-...
-LL | trait T {
- | ^^^^^ expected identifier, found keyword
-
-error: aborting due to 2 previous errors
+error: aborting due to previous error
diff --git a/tests/ui/parser/mismatched-braces/missing-close-brace-in-trait.rs b/tests/ui/parser/mismatched-braces/missing-close-brace-in-trait.rs
index b6932deb5..a05d6aa8e 100644
--- a/tests/ui/parser/mismatched-braces/missing-close-brace-in-trait.rs
+++ b/tests/ui/parser/mismatched-braces/missing-close-brace-in-trait.rs
@@ -2,10 +2,9 @@ trait T {
fn foo(&self);
pub(crate) struct Bar<T>();
-//~^ ERROR struct is not supported in `trait`s or `impl`s
impl T for Bar<usize> {
-//~^ ERROR implementation is not supported in `trait`s or `impl`s
+
fn foo(&self) {}
}
diff --git a/tests/ui/parser/mismatched-braces/missing-close-brace-in-trait.stderr b/tests/ui/parser/mismatched-braces/missing-close-brace-in-trait.stderr
index 7c6254356..7418dd64c 100644
--- a/tests/ui/parser/mismatched-braces/missing-close-brace-in-trait.stderr
+++ b/tests/ui/parser/mismatched-braces/missing-close-brace-in-trait.stderr
@@ -1,5 +1,5 @@
error: this file contains an unclosed delimiter
- --> $DIR/missing-close-brace-in-trait.rs:12:65
+ --> $DIR/missing-close-brace-in-trait.rs:11:65
|
LL | trait T {
| - unclosed delimiter
@@ -7,21 +7,5 @@ LL | trait T {
LL | fn main() {}
| ^
-error: struct is not supported in `trait`s or `impl`s
- --> $DIR/missing-close-brace-in-trait.rs:4:1
- |
-LL | pub(crate) struct Bar<T>();
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
- |
- = help: consider moving the struct out to a nearby module scope
-
-error: implementation is not supported in `trait`s or `impl`s
- --> $DIR/missing-close-brace-in-trait.rs:7:1
- |
-LL | impl T for Bar<usize> {
- | ^^^^^^^^^^^^^^^^^^^^^
- |
- = help: consider moving the implementation out to a nearby module scope
-
-error: aborting due to 3 previous errors
+error: aborting due to previous error
diff --git a/tests/ui/parser/missing-closing-angle-bracket-eq-constraint.rs b/tests/ui/parser/missing-closing-angle-bracket-eq-constraint.rs
index da95c1bfa..a56cd1777 100644
--- a/tests/ui/parser/missing-closing-angle-bracket-eq-constraint.rs
+++ b/tests/ui/parser/missing-closing-angle-bracket-eq-constraint.rs
@@ -17,7 +17,7 @@ fn test2<T1, T2>(arg1 : T1, arg2 : T2) {
fn test3<'a>(arg : &'a u32) {
let v : Vec<'a = vec![];
//~^ ERROR: expected one of
- //~| ERROR: type annotations needed for `Vec<T>`
+ //~| ERROR: type annotations needed for `Vec<_>`
}
fn main() {}
diff --git a/tests/ui/parser/missing-closing-angle-bracket-eq-constraint.stderr b/tests/ui/parser/missing-closing-angle-bracket-eq-constraint.stderr
index bad241634..b2448774a 100644
--- a/tests/ui/parser/missing-closing-angle-bracket-eq-constraint.stderr
+++ b/tests/ui/parser/missing-closing-angle-bracket-eq-constraint.stderr
@@ -39,26 +39,26 @@ help: you might have meant to end the type parameters here
LL | let v : Vec<'a> = vec![];
| +
-error[E0282]: type annotations needed for `Vec<T>`
+error[E0282]: type annotations needed for `Vec<_>`
--> $DIR/missing-closing-angle-bracket-eq-constraint.rs:7:7
|
LL | let v : Vec<(u32,_) = vec![];
| ^
|
-help: consider giving `v` an explicit type, where the type for type parameter `T` is specified
+help: consider giving `v` an explicit type, where the placeholders `_` are specified
|
-LL | let v: Vec<T> : Vec<(u32,_) = vec![];
+LL | let v: Vec<_> : Vec<(u32,_) = vec![];
| ++++++++
-error[E0282]: type annotations needed for `Vec<T>`
+error[E0282]: type annotations needed for `Vec<_>`
--> $DIR/missing-closing-angle-bracket-eq-constraint.rs:18:7
|
LL | let v : Vec<'a = vec![];
| ^
|
-help: consider giving `v` an explicit type, where the type for type parameter `T` is specified
+help: consider giving `v` an explicit type, where the placeholders `_` are specified
|
-LL | let v: Vec<T> : Vec<'a = vec![];
+LL | let v: Vec<_> : Vec<'a = vec![];
| ++++++++
error: aborting due to 5 previous errors
diff --git a/tests/ui/parser/missing-expression-in-for-loop.rs b/tests/ui/parser/missing-expression-in-for-loop.rs
new file mode 100644
index 000000000..518a89a0e
--- /dev/null
+++ b/tests/ui/parser/missing-expression-in-for-loop.rs
@@ -0,0 +1,5 @@
+fn main() {
+ for i in {
+ //~^ ERROR missing expression to iterate on in `for` loop
+ }
+}
diff --git a/tests/ui/parser/missing-expression-in-for-loop.stderr b/tests/ui/parser/missing-expression-in-for-loop.stderr
new file mode 100644
index 000000000..74a7c4224
--- /dev/null
+++ b/tests/ui/parser/missing-expression-in-for-loop.stderr
@@ -0,0 +1,13 @@
+error: missing expression to iterate on in `for` loop
+ --> $DIR/missing-expression-in-for-loop.rs:2:14
+ |
+LL | for i in {
+ | ^
+ |
+help: try adding an expression to the `for` loop
+ |
+LL | for i in /* expression */ {
+ | ++++++++++++++++
+
+error: aborting due to previous error
+
diff --git a/tests/ui/parser/missing_right_paren.rs b/tests/ui/parser/missing_right_paren.rs
index 810dee957..e240f8c67 100644
--- a/tests/ui/parser/missing_right_paren.rs
+++ b/tests/ui/parser/missing_right_paren.rs
@@ -1,3 +1,4 @@
// ignore-tidy-trailing-newlines
-// error-pattern: aborting due to 4 previous errors
+// error-pattern: this file contains an unclosed delimiter
+// error-pattern: aborting due to previous error
fn main((ؼ \ No newline at end of file
diff --git a/tests/ui/parser/missing_right_paren.stderr b/tests/ui/parser/missing_right_paren.stderr
index 3fe0d0f42..994ce4d85 100644
--- a/tests/ui/parser/missing_right_paren.stderr
+++ b/tests/ui/parser/missing_right_paren.stderr
@@ -1,5 +1,5 @@
error: this file contains an unclosed delimiter
- --> $DIR/missing_right_paren.rs:3:11
+ --> $DIR/missing_right_paren.rs:4:11
|
LL | fn main((ؼ
| -- ^
@@ -7,26 +7,5 @@ LL | fn main((ؼ
| |unclosed delimiter
| unclosed delimiter
-error: this file contains an unclosed delimiter
- --> $DIR/missing_right_paren.rs:3:11
- |
-LL | fn main((ؼ
- | -- ^
- | ||
- | |unclosed delimiter
- | unclosed delimiter
-
-error: expected one of `:` or `|`, found `)`
- --> $DIR/missing_right_paren.rs:3:11
- |
-LL | fn main((ؼ
- | ^ expected one of `:` or `|`
-
-error: expected one of `->`, `where`, or `{`, found `<eof>`
- --> $DIR/missing_right_paren.rs:3:11
- |
-LL | fn main((ؼ
- | ^ expected one of `->`, `where`, or `{`
-
-error: aborting due to 4 previous errors
+error: aborting due to previous error
diff --git a/tests/ui/parser/parser-recovery-1.rs b/tests/ui/parser/parser-recovery-1.rs
index 7e26b4f2b..5f729665c 100644
--- a/tests/ui/parser/parser-recovery-1.rs
+++ b/tests/ui/parser/parser-recovery-1.rs
@@ -3,11 +3,8 @@
trait Foo {
fn bar() {
let x = foo();
- //~^ ERROR cannot find function `foo` in this scope
}
fn main() {
let x = y.;
- //~^ ERROR unexpected token
- //~| ERROR cannot find value `y` in this scope
} //~ ERROR this file contains an unclosed delimiter
diff --git a/tests/ui/parser/parser-recovery-1.stderr b/tests/ui/parser/parser-recovery-1.stderr
index 0cb771ea3..7045b6f5b 100644
--- a/tests/ui/parser/parser-recovery-1.stderr
+++ b/tests/ui/parser/parser-recovery-1.stderr
@@ -1,35 +1,16 @@
error: this file contains an unclosed delimiter
- --> $DIR/parser-recovery-1.rs:13:54
+ --> $DIR/parser-recovery-1.rs:10:54
|
LL | trait Foo {
| - unclosed delimiter
LL | fn bar() {
| - this delimiter might not be properly closed...
-...
+LL | let x = foo();
LL | }
| - ...as it matches this but it has different indentation
...
LL | }
| ^
-error: unexpected token: `;`
- --> $DIR/parser-recovery-1.rs:10:15
- |
-LL | let x = y.;
- | ^
-
-error[E0425]: cannot find value `y` in this scope
- --> $DIR/parser-recovery-1.rs:10:13
- |
-LL | let x = y.;
- | ^ not found in this scope
-
-error[E0425]: cannot find function `foo` in this scope
- --> $DIR/parser-recovery-1.rs:5:17
- |
-LL | let x = foo();
- | ^^^ not found in this scope
-
-error: aborting due to 4 previous errors
+error: aborting due to previous error
-For more information about this error, try `rustc --explain E0425`.
diff --git a/tests/ui/parser/parser-recovery-2.rs b/tests/ui/parser/parser-recovery-2.rs
index 48b22afff..203d8aac6 100644
--- a/tests/ui/parser/parser-recovery-2.rs
+++ b/tests/ui/parser/parser-recovery-2.rs
@@ -2,11 +2,10 @@
trait Foo {
fn bar() {
- let x = foo(); //~ ERROR cannot find function `foo` in this scope
+ let x = foo();
) //~ ERROR mismatched closing delimiter: `)`
}
fn main() {
- let x = y.; //~ ERROR unexpected token
- //~^ ERROR cannot find value `y` in this scope
+ let x = y.;
}
diff --git a/tests/ui/parser/parser-recovery-2.stderr b/tests/ui/parser/parser-recovery-2.stderr
index 8829cf4c1..f396e5fde 100644
--- a/tests/ui/parser/parser-recovery-2.stderr
+++ b/tests/ui/parser/parser-recovery-2.stderr
@@ -1,9 +1,3 @@
-error: unexpected token: `;`
- --> $DIR/parser-recovery-2.rs:10:15
- |
-LL | let x = y.;
- | ^
-
error: mismatched closing delimiter: `)`
--> $DIR/parser-recovery-2.rs:4:14
|
@@ -13,18 +7,5 @@ LL | let x = foo();
LL | )
| ^ mismatched closing delimiter
-error[E0425]: cannot find value `y` in this scope
- --> $DIR/parser-recovery-2.rs:10:13
- |
-LL | let x = y.;
- | ^ not found in this scope
-
-error[E0425]: cannot find function `foo` in this scope
- --> $DIR/parser-recovery-2.rs:5:17
- |
-LL | let x = foo();
- | ^^^ not found in this scope
-
-error: aborting due to 4 previous errors
+error: aborting due to previous error
-For more information about this error, try `rustc --explain E0425`.
diff --git a/tests/ui/parser/raw/too-many-hash.rs b/tests/ui/parser/raw/too-many-hash.rs
new file mode 100644
index 000000000..f3d3b207f
--- /dev/null
+++ b/tests/ui/parser/raw/too-many-hash.rs
@@ -0,0 +1,6 @@
+// ignore-tidy-linelength
+
+fn main() {
+ let s: &str = r################################################################################################################################################################################################################################################################"very raw"################################################################################################################################################################################################################################################################;
+ //~^ ERROR too many `#` symbols: raw strings may be delimited by up to 255 `#` symbols, but found 256
+}
diff --git a/tests/ui/parser/raw/too-many-hash.stderr b/tests/ui/parser/raw/too-many-hash.stderr
new file mode 100644
index 000000000..29ec17842
--- /dev/null
+++ b/tests/ui/parser/raw/too-many-hash.stderr
@@ -0,0 +1,8 @@
+error: too many `#` symbols: raw strings may be delimited by up to 255 `#` symbols, but found 256
+ --> $DIR/too-many-hash.rs:4:19
+ |
+LL | ... = r################################################################################################################################################################################################################################################################"very raw"##############################################################################################################################################################################################################################################################...
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/tests/ui/parser/recover-fn-ptr-with-generics.stderr b/tests/ui/parser/recover-fn-ptr-with-generics.stderr
index 1da9c1857..069fcffe9 100644
--- a/tests/ui/parser/recover-fn-ptr-with-generics.stderr
+++ b/tests/ui/parser/recover-fn-ptr-with-generics.stderr
@@ -88,12 +88,6 @@ error: expected identifier, found `>`
LL | type QuiteBroken = fn<const>();
| ^ expected identifier
-error: lifetime bounds cannot be used in this context
- --> $DIR/recover-fn-ptr-with-generics.rs:22:26
- |
-LL | let _: extern fn<'a: 'static>();
- | ^^^^^^^
-
error[E0412]: cannot find type `T` in this scope
--> $DIR/recover-fn-ptr-with-generics.rs:5:27
|
@@ -106,6 +100,12 @@ error[E0412]: cannot find type `T` in this scope
LL | type Identity = fn<T>(T) -> T;
| ^ not found in this scope
+error: lifetime bounds cannot be used in this context
+ --> $DIR/recover-fn-ptr-with-generics.rs:22:26
+ |
+LL | let _: extern fn<'a: 'static>();
+ | ^^^^^^^
+
error: aborting due to 12 previous errors
For more information about this error, try `rustc --explain E0412`.
diff --git a/tests/ui/parser/recover-quantified-closure.rs b/tests/ui/parser/recover-quantified-closure.rs
index df22f5e06..10af39b70 100644
--- a/tests/ui/parser/recover-quantified-closure.rs
+++ b/tests/ui/parser/recover-quantified-closure.rs
@@ -7,6 +7,6 @@ fn main() {
enum Foo { Bar }
fn foo(x: impl Iterator<Item = Foo>) {
for <Foo>::Bar in x {}
- //~^ ERROR expected one of `const`, `move`, `static`, `|`
+ //~^ ERROR expected one of `move`, `static`, `|`
//~^^ ERROR `for<...>` binders for closures are experimental
}
diff --git a/tests/ui/parser/recover-quantified-closure.stderr b/tests/ui/parser/recover-quantified-closure.stderr
index 9ec4d2c03..39eec80f6 100644
--- a/tests/ui/parser/recover-quantified-closure.stderr
+++ b/tests/ui/parser/recover-quantified-closure.stderr
@@ -1,8 +1,8 @@
-error: expected one of `const`, `move`, `static`, `|`, or `||`, found `::`
+error: expected one of `move`, `static`, `|`, or `||`, found `::`
--> $DIR/recover-quantified-closure.rs:9:14
|
LL | for <Foo>::Bar in x {}
- | ^^ expected one of `const`, `move`, `static`, `|`, or `||`
+ | ^^ expected one of `move`, `static`, `|`, or `||`
error[E0658]: `for<...>` binders for closures are experimental
--> $DIR/recover-quantified-closure.rs:2:5
diff --git a/tests/ui/parser/recover-range-pats.stderr b/tests/ui/parser/recover-range-pats.stderr
index c54f13e01..5b69ca5cd 100644
--- a/tests/ui/parser/recover-range-pats.stderr
+++ b/tests/ui/parser/recover-range-pats.stderr
@@ -314,7 +314,7 @@ error[E0308]: mismatched types
LL | if let X.. .0 = 0 {}
| - ^^ - this expression has type `u8`
| | |
- | | expected integer, found floating-point number
+ | | expected `u8`, found floating-point number
| this is of type `u8`
|
= note: expected type `u8`
@@ -351,7 +351,7 @@ error[E0308]: mismatched types
LL | if let X..=.0 = 0 {}
| - ^^ - this expression has type `u8`
| | |
- | | expected integer, found floating-point number
+ | | expected `u8`, found floating-point number
| this is of type `u8`
|
= note: expected type `u8`
@@ -388,7 +388,7 @@ error[E0308]: mismatched types
LL | if let X... .0 = 0 {}
| - ^^ - this expression has type `u8`
| | |
- | | expected integer, found floating-point number
+ | | expected `u8`, found floating-point number
| this is of type `u8`
|
= note: expected type `u8`
diff --git a/tests/ui/parser/suggest_misplaced_generics/enum.fixed b/tests/ui/parser/suggest_misplaced_generics/enum.fixed
new file mode 100644
index 000000000..3332118a1
--- /dev/null
+++ b/tests/ui/parser/suggest_misplaced_generics/enum.fixed
@@ -0,0 +1,9 @@
+// Issue: 103366 , Suggest fix for misplaced generic params
+// run-rustfix
+
+#[allow(unused)]
+enum Foo<T> { Variant(T) }
+//~^ ERROR expected identifier, found `<`
+//~| HELP place the generic parameter name after the enum name
+
+fn main() {}
diff --git a/tests/ui/parser/suggest_misplaced_generics/enum.rs b/tests/ui/parser/suggest_misplaced_generics/enum.rs
new file mode 100644
index 000000000..5a2289c5c
--- /dev/null
+++ b/tests/ui/parser/suggest_misplaced_generics/enum.rs
@@ -0,0 +1,9 @@
+// Issue: 103366 , Suggest fix for misplaced generic params
+// run-rustfix
+
+#[allow(unused)]
+enum<T> Foo { Variant(T) }
+//~^ ERROR expected identifier, found `<`
+//~| HELP place the generic parameter name after the enum name
+
+fn main() {}
diff --git a/tests/ui/parser/suggest_misplaced_generics/enum.stderr b/tests/ui/parser/suggest_misplaced_generics/enum.stderr
new file mode 100644
index 000000000..5f5947627
--- /dev/null
+++ b/tests/ui/parser/suggest_misplaced_generics/enum.stderr
@@ -0,0 +1,14 @@
+error: expected identifier, found `<`
+ --> $DIR/enum.rs:5:5
+ |
+LL | enum<T> Foo { Variant(T) }
+ | ^ expected identifier
+ |
+help: place the generic parameter name after the enum name
+ |
+LL - enum<T> Foo { Variant(T) }
+LL + enum Foo<T> { Variant(T) }
+ |
+
+error: aborting due to previous error
+
diff --git a/tests/ui/parser/suggest_misplaced_generics/existing_generics.rs b/tests/ui/parser/suggest_misplaced_generics/existing_generics.rs
new file mode 100644
index 000000000..1dc182398
--- /dev/null
+++ b/tests/ui/parser/suggest_misplaced_generics/existing_generics.rs
@@ -0,0 +1,9 @@
+// Issue: 103366
+// there is already an existing generic on f, so don't show a suggestion
+
+#[allow(unused)]
+fn<'a, B: 'a + std::ops::Add<Output = u32>> f<T>(_x: B) { }
+//~^ ERROR expected identifier, found `<`
+//~| HELP place the generic parameter name after the fn name
+
+fn main() {}
diff --git a/tests/ui/parser/suggest_misplaced_generics/existing_generics.stderr b/tests/ui/parser/suggest_misplaced_generics/existing_generics.stderr
new file mode 100644
index 000000000..89716e6f1
--- /dev/null
+++ b/tests/ui/parser/suggest_misplaced_generics/existing_generics.stderr
@@ -0,0 +1,10 @@
+error: expected identifier, found `<`
+ --> $DIR/existing_generics.rs:5:3
+ |
+LL | fn<'a, B: 'a + std::ops::Add<Output = u32>> f<T>(_x: B) { }
+ | ^ expected identifier
+ |
+ = help: place the generic parameter name after the fn name
+
+error: aborting due to previous error
+
diff --git a/tests/ui/parser/suggest_misplaced_generics/fn-complex-generics.fixed b/tests/ui/parser/suggest_misplaced_generics/fn-complex-generics.fixed
new file mode 100644
index 000000000..84bf64bd6
--- /dev/null
+++ b/tests/ui/parser/suggest_misplaced_generics/fn-complex-generics.fixed
@@ -0,0 +1,9 @@
+// Issue: 103366 , Suggest fix for misplaced generic params
+// run-rustfix
+
+#[allow(unused)]
+fn f<'a, B: 'a + std::ops::Add<Output = u32>>(_x: B) { }
+//~^ ERROR expected identifier, found `<`
+//~| HELP place the generic parameter name after the fn name
+
+fn main() {}
diff --git a/tests/ui/parser/suggest_misplaced_generics/fn-complex-generics.rs b/tests/ui/parser/suggest_misplaced_generics/fn-complex-generics.rs
new file mode 100644
index 000000000..d0684397e
--- /dev/null
+++ b/tests/ui/parser/suggest_misplaced_generics/fn-complex-generics.rs
@@ -0,0 +1,9 @@
+// Issue: 103366 , Suggest fix for misplaced generic params
+// run-rustfix
+
+#[allow(unused)]
+fn<'a, B: 'a + std::ops::Add<Output = u32>> f(_x: B) { }
+//~^ ERROR expected identifier, found `<`
+//~| HELP place the generic parameter name after the fn name
+
+fn main() {}
diff --git a/tests/ui/parser/suggest_misplaced_generics/fn-complex-generics.stderr b/tests/ui/parser/suggest_misplaced_generics/fn-complex-generics.stderr
new file mode 100644
index 000000000..061d0910a
--- /dev/null
+++ b/tests/ui/parser/suggest_misplaced_generics/fn-complex-generics.stderr
@@ -0,0 +1,14 @@
+error: expected identifier, found `<`
+ --> $DIR/fn-complex-generics.rs:5:3
+ |
+LL | fn<'a, B: 'a + std::ops::Add<Output = u32>> f(_x: B) { }
+ | ^ expected identifier
+ |
+help: place the generic parameter name after the fn name
+ |
+LL - fn<'a, B: 'a + std::ops::Add<Output = u32>> f(_x: B) { }
+LL + fn f<'a, B: 'a + std::ops::Add<Output = u32>>(_x: B) { }
+ |
+
+error: aborting due to previous error
+
diff --git a/tests/ui/parser/suggest_misplaced_generics/fn-invalid-generics.rs b/tests/ui/parser/suggest_misplaced_generics/fn-invalid-generics.rs
new file mode 100644
index 000000000..7fcb6a82c
--- /dev/null
+++ b/tests/ui/parser/suggest_misplaced_generics/fn-invalid-generics.rs
@@ -0,0 +1,8 @@
+// Issue: 103366 , Suggest fix for misplaced generic params
+// The generics fail to parse here, so don't make any suggestions/help
+
+#[allow(unused)]
+fn<~>()> id(x: T) -> T { x }
+//~^ ERROR expected identifier, found `<`
+
+fn main() {}
diff --git a/tests/ui/parser/suggest_misplaced_generics/fn-invalid-generics.stderr b/tests/ui/parser/suggest_misplaced_generics/fn-invalid-generics.stderr
new file mode 100644
index 000000000..47e120169
--- /dev/null
+++ b/tests/ui/parser/suggest_misplaced_generics/fn-invalid-generics.stderr
@@ -0,0 +1,8 @@
+error: expected identifier, found `<`
+ --> $DIR/fn-invalid-generics.rs:5:3
+ |
+LL | fn<~>()> id(x: T) -> T { x }
+ | ^ expected identifier
+
+error: aborting due to previous error
+
diff --git a/tests/ui/parser/suggest_misplaced_generics/fn-simple.fixed b/tests/ui/parser/suggest_misplaced_generics/fn-simple.fixed
new file mode 100644
index 000000000..cbfd5f2d3
--- /dev/null
+++ b/tests/ui/parser/suggest_misplaced_generics/fn-simple.fixed
@@ -0,0 +1,9 @@
+// Issue: 103366 , Suggest fix for misplaced generic params
+// run-rustfix
+
+#[allow(unused)]
+fn id<T>(x: T) -> T { x }
+//~^ ERROR expected identifier, found `<`
+//~| HELP place the generic parameter name after the fn name
+
+fn main() {}
diff --git a/tests/ui/parser/suggest_misplaced_generics/fn-simple.rs b/tests/ui/parser/suggest_misplaced_generics/fn-simple.rs
new file mode 100644
index 000000000..b207cf70d
--- /dev/null
+++ b/tests/ui/parser/suggest_misplaced_generics/fn-simple.rs
@@ -0,0 +1,9 @@
+// Issue: 103366 , Suggest fix for misplaced generic params
+// run-rustfix
+
+#[allow(unused)]
+fn<T> id(x: T) -> T { x }
+//~^ ERROR expected identifier, found `<`
+//~| HELP place the generic parameter name after the fn name
+
+fn main() {}
diff --git a/tests/ui/parser/suggest_misplaced_generics/fn-simple.stderr b/tests/ui/parser/suggest_misplaced_generics/fn-simple.stderr
new file mode 100644
index 000000000..e749f1a0d
--- /dev/null
+++ b/tests/ui/parser/suggest_misplaced_generics/fn-simple.stderr
@@ -0,0 +1,14 @@
+error: expected identifier, found `<`
+ --> $DIR/fn-simple.rs:5:3
+ |
+LL | fn<T> id(x: T) -> T { x }
+ | ^ expected identifier
+ |
+help: place the generic parameter name after the fn name
+ |
+LL - fn<T> id(x: T) -> T { x }
+LL + fn id<T>(x: T) -> T { x }
+ |
+
+error: aborting due to previous error
+
diff --git a/tests/ui/parser/suggest_misplaced_generics/struct.fixed b/tests/ui/parser/suggest_misplaced_generics/struct.fixed
new file mode 100644
index 000000000..fec05bdec
--- /dev/null
+++ b/tests/ui/parser/suggest_misplaced_generics/struct.fixed
@@ -0,0 +1,9 @@
+// Issue: 103366 , Suggest fix for misplaced generic params
+// run-rustfix
+
+#[allow(unused)]
+struct Foo<T> { x: T }
+//~^ ERROR expected identifier, found `<`
+//~| HELP place the generic parameter name after the struct name
+
+fn main() {}
diff --git a/tests/ui/parser/suggest_misplaced_generics/struct.rs b/tests/ui/parser/suggest_misplaced_generics/struct.rs
new file mode 100644
index 000000000..6b80150d5
--- /dev/null
+++ b/tests/ui/parser/suggest_misplaced_generics/struct.rs
@@ -0,0 +1,9 @@
+// Issue: 103366 , Suggest fix for misplaced generic params
+// run-rustfix
+
+#[allow(unused)]
+struct<T> Foo { x: T }
+//~^ ERROR expected identifier, found `<`
+//~| HELP place the generic parameter name after the struct name
+
+fn main() {}
diff --git a/tests/ui/parser/suggest_misplaced_generics/struct.stderr b/tests/ui/parser/suggest_misplaced_generics/struct.stderr
new file mode 100644
index 000000000..2b6509070
--- /dev/null
+++ b/tests/ui/parser/suggest_misplaced_generics/struct.stderr
@@ -0,0 +1,14 @@
+error: expected identifier, found `<`
+ --> $DIR/struct.rs:5:7
+ |
+LL | struct<T> Foo { x: T }
+ | ^ expected identifier
+ |
+help: place the generic parameter name after the struct name
+ |
+LL - struct<T> Foo { x: T }
+LL + struct Foo<T> { x: T }
+ |
+
+error: aborting due to previous error
+
diff --git a/tests/ui/parser/suggest_misplaced_generics/trait.fixed b/tests/ui/parser/suggest_misplaced_generics/trait.fixed
new file mode 100644
index 000000000..a471a078a
--- /dev/null
+++ b/tests/ui/parser/suggest_misplaced_generics/trait.fixed
@@ -0,0 +1,11 @@
+// Issue: 103366 , Suggest fix for misplaced generic params
+// run-rustfix
+
+#[allow(unused)]
+trait Foo<T> {
+ //~^ ERROR expected identifier, found `<`
+ //~| HELP place the generic parameter name after the trait name
+}
+
+
+fn main() {}
diff --git a/tests/ui/parser/suggest_misplaced_generics/trait.rs b/tests/ui/parser/suggest_misplaced_generics/trait.rs
new file mode 100644
index 000000000..55355f451
--- /dev/null
+++ b/tests/ui/parser/suggest_misplaced_generics/trait.rs
@@ -0,0 +1,11 @@
+// Issue: 103366 , Suggest fix for misplaced generic params
+// run-rustfix
+
+#[allow(unused)]
+trait<T> Foo {
+ //~^ ERROR expected identifier, found `<`
+ //~| HELP place the generic parameter name after the trait name
+}
+
+
+fn main() {}
diff --git a/tests/ui/parser/suggest_misplaced_generics/trait.stderr b/tests/ui/parser/suggest_misplaced_generics/trait.stderr
new file mode 100644
index 000000000..ac86cfa46
--- /dev/null
+++ b/tests/ui/parser/suggest_misplaced_generics/trait.stderr
@@ -0,0 +1,14 @@
+error: expected identifier, found `<`
+ --> $DIR/trait.rs:5:6
+ |
+LL | trait<T> Foo {
+ | ^ expected identifier
+ |
+help: place the generic parameter name after the trait name
+ |
+LL - trait<T> Foo {
+LL + trait Foo<T> {
+ |
+
+error: aborting due to previous error
+
diff --git a/tests/ui/parser/suggest_misplaced_generics/type.fixed b/tests/ui/parser/suggest_misplaced_generics/type.fixed
new file mode 100644
index 000000000..a97b9e66d
--- /dev/null
+++ b/tests/ui/parser/suggest_misplaced_generics/type.fixed
@@ -0,0 +1,9 @@
+// Issue: 103366 , Suggest fix for misplaced generic params
+// run-rustfix
+
+#[allow(unused)]
+type Foo<T> = T;
+//~^ ERROR expected identifier, found `<`
+//~| HELP place the generic parameter name after the type name
+
+fn main() {}
diff --git a/tests/ui/parser/suggest_misplaced_generics/type.rs b/tests/ui/parser/suggest_misplaced_generics/type.rs
new file mode 100644
index 000000000..17e200536
--- /dev/null
+++ b/tests/ui/parser/suggest_misplaced_generics/type.rs
@@ -0,0 +1,9 @@
+// Issue: 103366 , Suggest fix for misplaced generic params
+// run-rustfix
+
+#[allow(unused)]
+type<T> Foo = T;
+//~^ ERROR expected identifier, found `<`
+//~| HELP place the generic parameter name after the type name
+
+fn main() {}
diff --git a/tests/ui/parser/suggest_misplaced_generics/type.stderr b/tests/ui/parser/suggest_misplaced_generics/type.stderr
new file mode 100644
index 000000000..22744f6cf
--- /dev/null
+++ b/tests/ui/parser/suggest_misplaced_generics/type.stderr
@@ -0,0 +1,14 @@
+error: expected identifier, found `<`
+ --> $DIR/type.rs:5:5
+ |
+LL | type<T> Foo = T;
+ | ^ expected identifier
+ |
+help: place the generic parameter name after the type name
+ |
+LL - type<T> Foo = T;
+LL + type Foo<T> = T;
+ |
+
+error: aborting due to previous error
+
diff --git a/tests/ui/parser/trait-object-delimiters.rs b/tests/ui/parser/trait-object-delimiters.rs
index cc04ac052..c41cda187 100644
--- a/tests/ui/parser/trait-object-delimiters.rs
+++ b/tests/ui/parser/trait-object-delimiters.rs
@@ -5,6 +5,8 @@ fn foo1(_: &dyn Drop + AsRef<str>) {} //~ ERROR ambiguous `+` in a type
fn foo2(_: &dyn (Drop + AsRef<str>)) {} //~ ERROR incorrect braces around trait bounds
+fn foo2_no_space(_: &dyn(Drop + AsRef<str>)) {} //~ ERROR incorrect braces around trait bounds
+
fn foo3(_: &dyn {Drop + AsRef<str>}) {} //~ ERROR expected parameter name, found `{`
//~^ ERROR expected one of `!`, `(`, `)`, `*`, `,`, `?`, `for`, `~`, lifetime, or path, found `{`
//~| ERROR at least one trait is required for an object type
diff --git a/tests/ui/parser/trait-object-delimiters.stderr b/tests/ui/parser/trait-object-delimiters.stderr
index 99c451545..ccce3a805 100644
--- a/tests/ui/parser/trait-object-delimiters.stderr
+++ b/tests/ui/parser/trait-object-delimiters.stderr
@@ -13,17 +13,29 @@ LL | fn foo2(_: &dyn (Drop + AsRef<str>)) {}
help: remove the parentheses
|
LL - fn foo2(_: &dyn (Drop + AsRef<str>)) {}
-LL + fn foo2(_: &dyn Drop + AsRef<str>) {}
+LL + fn foo2(_: &dyn Drop + AsRef<str>) {}
+ |
+
+error: incorrect braces around trait bounds
+ --> $DIR/trait-object-delimiters.rs:8:25
+ |
+LL | fn foo2_no_space(_: &dyn(Drop + AsRef<str>)) {}
+ | ^ ^
+ |
+help: remove the parentheses
+ |
+LL - fn foo2_no_space(_: &dyn(Drop + AsRef<str>)) {}
+LL + fn foo2_no_space(_: &dyn Drop + AsRef<str>) {}
|
error: expected parameter name, found `{`
- --> $DIR/trait-object-delimiters.rs:8:17
+ --> $DIR/trait-object-delimiters.rs:10:17
|
LL | fn foo3(_: &dyn {Drop + AsRef<str>}) {}
| ^ expected parameter name
error: expected one of `!`, `(`, `)`, `*`, `,`, `?`, `for`, `~`, lifetime, or path, found `{`
- --> $DIR/trait-object-delimiters.rs:8:17
+ --> $DIR/trait-object-delimiters.rs:10:17
|
LL | fn foo3(_: &dyn {Drop + AsRef<str>}) {}
| -^ expected one of 10 possible tokens
@@ -31,13 +43,13 @@ LL | fn foo3(_: &dyn {Drop + AsRef<str>}) {}
| help: missing `,`
error: expected identifier, found `<`
- --> $DIR/trait-object-delimiters.rs:12:17
+ --> $DIR/trait-object-delimiters.rs:14:17
|
LL | fn foo4(_: &dyn <Drop + AsRef<str>>) {}
| ^ expected identifier
error: invalid `dyn` keyword
- --> $DIR/trait-object-delimiters.rs:14:25
+ --> $DIR/trait-object-delimiters.rs:16:25
|
LL | fn foo5(_: &(dyn Drop + dyn AsRef<str>)) {}
| ^^^ help: remove this keyword
@@ -56,13 +68,13 @@ LL | fn foo1(_: &dyn Drop + AsRef<str>) {}
= note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
error[E0224]: at least one trait is required for an object type
- --> $DIR/trait-object-delimiters.rs:8:13
+ --> $DIR/trait-object-delimiters.rs:10:13
|
LL | fn foo3(_: &dyn {Drop + AsRef<str>}) {}
| ^^^
error[E0225]: only auto traits can be used as additional traits in a trait object
- --> $DIR/trait-object-delimiters.rs:14:29
+ --> $DIR/trait-object-delimiters.rs:16:29
|
LL | fn foo5(_: &(dyn Drop + dyn AsRef<str>)) {}
| ---- ^^^^^^^^^^ additional non-auto trait
@@ -72,7 +84,7 @@ LL | fn foo5(_: &(dyn Drop + dyn AsRef<str>)) {}
= help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: Drop + AsRef<str> {}`
= note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
-error: aborting due to 9 previous errors
+error: aborting due to 10 previous errors
Some errors have detailed explanations: E0224, E0225.
For more information about an error, try `rustc --explain E0224`.
diff --git a/tests/ui/parser/type-ascription-in-pattern.rs b/tests/ui/parser/type-ascription-in-pattern.rs
new file mode 100644
index 000000000..fec168afb
--- /dev/null
+++ b/tests/ui/parser/type-ascription-in-pattern.rs
@@ -0,0 +1,16 @@
+fn foo(x: bool) -> i32 {
+ match x {
+ x: i32 => x, //~ ERROR expected
+ //~^ ERROR mismatched types
+ true => 42.,
+ false => 0.333,
+ }
+}
+
+fn main() {
+ match foo(true) {
+ 42: i32 => (), //~ ERROR expected
+ _: f64 => (), //~ ERROR expected
+ x: i32 => (), //~ ERROR expected
+ }
+}
diff --git a/tests/ui/parser/type-ascription-in-pattern.stderr b/tests/ui/parser/type-ascription-in-pattern.stderr
new file mode 100644
index 000000000..091907549
--- /dev/null
+++ b/tests/ui/parser/type-ascription-in-pattern.stderr
@@ -0,0 +1,54 @@
+error: expected one of `@` or `|`, found `:`
+ --> $DIR/type-ascription-in-pattern.rs:3:10
+ |
+LL | x: i32 => x,
+ | ^ --- specifying the type of a pattern isn't supported
+ | |
+ | expected one of `@` or `|`
+ |
+help: maybe write a path separator here
+ |
+LL | x::i32 => x,
+ | ~~
+
+error: expected one of `...`, `..=`, `..`, or `|`, found `:`
+ --> $DIR/type-ascription-in-pattern.rs:12:11
+ |
+LL | 42: i32 => (),
+ | ^ --- specifying the type of a pattern isn't supported
+ | |
+ | expected one of `...`, `..=`, `..`, or `|`
+
+error: expected `|`, found `:`
+ --> $DIR/type-ascription-in-pattern.rs:13:10
+ |
+LL | _: f64 => (),
+ | ^ --- specifying the type of a pattern isn't supported
+ | |
+ | expected `|`
+
+error: expected one of `@` or `|`, found `:`
+ --> $DIR/type-ascription-in-pattern.rs:14:10
+ |
+LL | x: i32 => (),
+ | ^ --- specifying the type of a pattern isn't supported
+ | |
+ | expected one of `@` or `|`
+ |
+help: maybe write a path separator here
+ |
+LL | x::i32 => (),
+ | ~~
+
+error[E0308]: mismatched types
+ --> $DIR/type-ascription-in-pattern.rs:3:19
+ |
+LL | fn foo(x: bool) -> i32 {
+ | --- expected `i32` because of return type
+LL | match x {
+LL | x: i32 => x,
+ | ^ expected `i32`, found `bool`
+
+error: aborting due to 5 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/parser/unclosed-delimiter-in-dep.rs b/tests/ui/parser/unclosed-delimiter-in-dep.rs
index 6db1b66e9..4de83ee64 100644
--- a/tests/ui/parser/unclosed-delimiter-in-dep.rs
+++ b/tests/ui/parser/unclosed-delimiter-in-dep.rs
@@ -2,5 +2,4 @@ mod unclosed_delim_mod;
fn main() {
let _: usize = unclosed_delim_mod::new();
- //~^ ERROR mismatched types
}
diff --git a/tests/ui/parser/unclosed-delimiter-in-dep.stderr b/tests/ui/parser/unclosed-delimiter-in-dep.stderr
index 1366ef1bb..a46d020b9 100644
--- a/tests/ui/parser/unclosed-delimiter-in-dep.stderr
+++ b/tests/ui/parser/unclosed-delimiter-in-dep.stderr
@@ -9,17 +9,5 @@ LL | }
LL | }
| ^ mismatched closing delimiter
-error[E0308]: mismatched types
- --> $DIR/unclosed-delimiter-in-dep.rs:4:20
- |
-LL | let _: usize = unclosed_delim_mod::new();
- | ----- ^^^^^^^^^^^^^^^^^^^^^^^^^ expected `usize`, found enum `Result`
- | |
- | expected due to this
- |
- = note: expected type `usize`
- found enum `Result<Value, ()>`
-
-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/tests/ui/parser/use-unclosed-brace.rs b/tests/ui/parser/use-unclosed-brace.rs
index 41742f37f..fcfe95b26 100644
--- a/tests/ui/parser/use-unclosed-brace.rs
+++ b/tests/ui/parser/use-unclosed-brace.rs
@@ -1,6 +1,4 @@
-// error-pattern: expected one of `,`, `::`, `as`, or `}`, found `;`
// error-pattern: this file contains an unclosed delimiter
-// error-pattern: expected item, found `}`
use foo::{bar, baz;
use std::fmt::Display;
diff --git a/tests/ui/parser/use-unclosed-brace.stderr b/tests/ui/parser/use-unclosed-brace.stderr
index 438fe9c47..ad5bb2de1 100644
--- a/tests/ui/parser/use-unclosed-brace.stderr
+++ b/tests/ui/parser/use-unclosed-brace.stderr
@@ -1,5 +1,5 @@
error: this file contains an unclosed delimiter
- --> $DIR/use-unclosed-brace.rs:12:14
+ --> $DIR/use-unclosed-brace.rs:10:14
|
LL | use foo::{bar, baz;
| - unclosed delimiter
@@ -7,21 +7,5 @@ LL | use foo::{bar, baz;
LL | fn main() {}
| ^
-error: expected one of `,`, `::`, `as`, or `}`, found `;`
- --> $DIR/use-unclosed-brace.rs:4:10
- |
-LL | use foo::{bar, baz;
- | ^ ^
- | | |
- | | expected one of `,`, `::`, `as`, or `}`
- | | help: `}` may belong here
- | unclosed delimiter
-
-error: expected item, found `}`
- --> $DIR/use-unclosed-brace.rs:12:14
- |
-LL | fn main() {}
- | ^ expected item
-
-error: aborting due to 3 previous errors
+error: aborting due to previous error
diff --git a/tests/ui/pattern/bindings-after-at/bind-by-move-neither-can-live-while-the-other-survives-1.stderr b/tests/ui/pattern/bindings-after-at/bind-by-move-neither-can-live-while-the-other-survives-1.stderr
index c8b45fd24..29cd6c45c 100644
--- a/tests/ui/pattern/bindings-after-at/bind-by-move-neither-can-live-while-the-other-survives-1.stderr
+++ b/tests/ui/pattern/bindings-after-at/bind-by-move-neither-can-live-while-the-other-survives-1.stderr
@@ -4,8 +4,8 @@ error: cannot move out of value because it is borrowed
LL | Some(ref _y @ _z) => {}
| ------^^^--
| | |
- | | value moved into `_z` here
- | value borrowed, by `_y`, here
+ | | value is moved into `_z` here
+ | value is borrowed by `_y` here
error: borrow of moved value
--> $DIR/bind-by-move-neither-can-live-while-the-other-survives-1.rs:19:14
@@ -28,8 +28,8 @@ error: cannot move out of value because it is borrowed
LL | Some(ref mut _y @ _z) => {}
| ----------^^^--
| | |
- | | value moved into `_z` here
- | value borrowed, by `_y`, here
+ | | value is moved into `_z` here
+ | value is mutably borrowed by `_y` here
error: borrow of moved value
--> $DIR/bind-by-move-neither-can-live-while-the-other-survives-1.rs:33:14
diff --git a/tests/ui/pattern/bindings-after-at/borrowck-pat-at-and-box.stderr b/tests/ui/pattern/bindings-after-at/borrowck-pat-at-and-box.stderr
index f27df32cc..2c123b01e 100644
--- a/tests/ui/pattern/bindings-after-at/borrowck-pat-at-and-box.stderr
+++ b/tests/ui/pattern/bindings-after-at/borrowck-pat-at-and-box.stderr
@@ -4,8 +4,8 @@ error: cannot move out of value because it is borrowed
LL | let ref a @ box b = Box::new(NC);
| -----^^^^^^^-
| | |
- | | value moved into `b` here
- | value borrowed, by `a`, here
+ | | value is moved into `b` here
+ | value is borrowed by `a` here
error: cannot borrow value as mutable because it is also borrowed as immutable
--> $DIR/borrowck-pat-at-and-box.rs:34:9
@@ -13,8 +13,8 @@ error: cannot borrow value as mutable because it is also borrowed as immutable
LL | let ref a @ box ref mut b = Box::new(nc());
| -----^^^^^^^---------
| | |
- | | mutable borrow, by `b`, occurs here
- | immutable borrow, by `a`, occurs here
+ | | value is mutably borrowed by `b` here
+ | value is borrowed by `a` here
error: cannot borrow value as mutable because it is also borrowed as immutable
--> $DIR/borrowck-pat-at-and-box.rs:36:9
@@ -22,8 +22,8 @@ error: cannot borrow value as mutable because it is also borrowed as immutable
LL | let ref a @ box ref mut b = Box::new(NC);
| -----^^^^^^^---------
| | |
- | | mutable borrow, by `b`, occurs here
- | immutable borrow, by `a`, occurs here
+ | | value is mutably borrowed by `b` here
+ | value is borrowed by `a` here
error: cannot borrow value as mutable because it is also borrowed as immutable
--> $DIR/borrowck-pat-at-and-box.rs:38:9
@@ -31,8 +31,8 @@ error: cannot borrow value as mutable because it is also borrowed as immutable
LL | let ref a @ box ref mut b = Box::new(NC);
| -----^^^^^^^---------
| | |
- | | mutable borrow, by `b`, occurs here
- | immutable borrow, by `a`, occurs here
+ | | value is mutably borrowed by `b` here
+ | value is borrowed by `a` here
error: cannot borrow value as mutable because it is also borrowed as immutable
--> $DIR/borrowck-pat-at-and-box.rs:42:9
@@ -40,8 +40,8 @@ error: cannot borrow value as mutable because it is also borrowed as immutable
LL | let ref a @ box ref mut b = Box::new(NC);
| -----^^^^^^^---------
| | |
- | | mutable borrow, by `b`, occurs here
- | immutable borrow, by `a`, occurs here
+ | | value is mutably borrowed by `b` here
+ | value is borrowed by `a` here
error: cannot borrow value as immutable because it is also borrowed as mutable
--> $DIR/borrowck-pat-at-and-box.rs:48:9
@@ -49,8 +49,8 @@ error: cannot borrow value as immutable because it is also borrowed as mutable
LL | let ref mut a @ box ref b = Box::new(NC);
| ---------^^^^^^^-----
| | |
- | | immutable borrow, by `b`, occurs here
- | mutable borrow, by `a`, occurs here
+ | | value is borrowed by `b` here
+ | value is mutably borrowed by `a` here
error: cannot borrow value as immutable because it is also borrowed as mutable
--> $DIR/borrowck-pat-at-and-box.rs:62:9
@@ -58,8 +58,8 @@ error: cannot borrow value as immutable because it is also borrowed as mutable
LL | ref mut a @ box ref b => {
| ---------^^^^^^^-----
| | |
- | | immutable borrow, by `b`, occurs here
- | mutable borrow, by `a`, occurs here
+ | | value is borrowed by `b` here
+ | value is mutably borrowed by `a` here
error: cannot borrow value as immutable because it is also borrowed as mutable
--> $DIR/borrowck-pat-at-and-box.rs:54:11
@@ -67,8 +67,8 @@ error: cannot borrow value as immutable because it is also borrowed as mutable
LL | fn f5(ref mut a @ box ref b: Box<NC>) {
| ---------^^^^^^^-----
| | |
- | | immutable borrow, by `b`, occurs here
- | mutable borrow, by `a`, occurs here
+ | | value is borrowed by `b` here
+ | value is mutably borrowed by `a` here
error[E0382]: borrow of moved value
--> $DIR/borrowck-pat-at-and-box.rs:31:9
diff --git a/tests/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref.stderr b/tests/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref.stderr
index 770bb8953..4f7fbc9e0 100644
--- a/tests/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref.stderr
+++ b/tests/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref.stderr
@@ -4,8 +4,8 @@ error: cannot move out of value because it is borrowed
LL | let ref a @ b = U;
| -----^^^-
| | |
- | | value moved into `b` here
- | value borrowed, by `a`, here
+ | | value is moved into `b` here
+ | value is borrowed by `a` here
error: cannot move out of value because it is borrowed
--> $DIR/borrowck-pat-by-move-and-ref.rs:26:9
@@ -13,9 +13,9 @@ error: cannot move out of value because it is borrowed
LL | let ref a @ (ref b @ mut c, ref d @ e) = (U, U);
| -----^^^^^^^^^^^^-----^^^^^^^^^^-^
| | | |
- | | | value moved into `e` here
- | | value moved into `c` here
- | value borrowed, by `a`, here
+ | | | value is moved into `e` here
+ | | value is moved into `c` here
+ | value is borrowed by `a` here
error: cannot move out of value because it is borrowed
--> $DIR/borrowck-pat-by-move-and-ref.rs:26:18
@@ -23,8 +23,8 @@ error: cannot move out of value because it is borrowed
LL | let ref a @ (ref b @ mut c, ref d @ e) = (U, U);
| -----^^^-----
| | |
- | | value moved into `c` here
- | value borrowed, by `b`, here
+ | | value is moved into `c` here
+ | value is borrowed by `b` here
error: cannot move out of value because it is borrowed
--> $DIR/borrowck-pat-by-move-and-ref.rs:26:33
@@ -32,8 +32,8 @@ error: cannot move out of value because it is borrowed
LL | let ref a @ (ref b @ mut c, ref d @ e) = (U, U);
| -----^^^-
| | |
- | | value moved into `e` here
- | value borrowed, by `d`, here
+ | | value is moved into `e` here
+ | value is borrowed by `d` here
error: cannot move out of value because it is borrowed
--> $DIR/borrowck-pat-by-move-and-ref.rs:30:9
@@ -41,9 +41,9 @@ error: cannot move out of value because it is borrowed
LL | let ref mut a @ [b, mut c] = [U, U];
| ---------^^^^-^^-----^
| | | |
- | | | value moved into `c` here
- | | value moved into `b` here
- | value borrowed, by `a`, here
+ | | | value is moved into `c` here
+ | | value is moved into `b` here
+ | value is mutably borrowed by `a` here
error: cannot move out of value because it is borrowed
--> $DIR/borrowck-pat-by-move-and-ref.rs:33:9
@@ -51,8 +51,8 @@ error: cannot move out of value because it is borrowed
LL | let ref a @ b = u();
| -----^^^-
| | |
- | | value moved into `b` here
- | value borrowed, by `a`, here
+ | | value is moved into `b` here
+ | value is borrowed by `a` here
error: cannot move out of value because it is borrowed
--> $DIR/borrowck-pat-by-move-and-ref.rs:36:9
@@ -60,9 +60,9 @@ error: cannot move out of value because it is borrowed
LL | let ref a @ (ref b @ mut c, ref d @ e) = (u(), u());
| -----^^^^^^^^^^^^-----^^^^^^^^^^-^
| | | |
- | | | value moved into `e` here
- | | value moved into `c` here
- | value borrowed, by `a`, here
+ | | | value is moved into `e` here
+ | | value is moved into `c` here
+ | value is borrowed by `a` here
error: cannot move out of value because it is borrowed
--> $DIR/borrowck-pat-by-move-and-ref.rs:36:18
@@ -70,8 +70,8 @@ error: cannot move out of value because it is borrowed
LL | let ref a @ (ref b @ mut c, ref d @ e) = (u(), u());
| -----^^^-----
| | |
- | | value moved into `c` here
- | value borrowed, by `b`, here
+ | | value is moved into `c` here
+ | value is borrowed by `b` here
error: cannot move out of value because it is borrowed
--> $DIR/borrowck-pat-by-move-and-ref.rs:36:33
@@ -79,8 +79,8 @@ error: cannot move out of value because it is borrowed
LL | let ref a @ (ref b @ mut c, ref d @ e) = (u(), u());
| -----^^^-
| | |
- | | value moved into `e` here
- | value borrowed, by `d`, here
+ | | value is moved into `e` here
+ | value is borrowed by `d` here
error: cannot move out of value because it is borrowed
--> $DIR/borrowck-pat-by-move-and-ref.rs:42:9
@@ -88,9 +88,9 @@ error: cannot move out of value because it is borrowed
LL | let ref mut a @ [b, mut c] = [u(), u()];
| ---------^^^^-^^-----^
| | | |
- | | | value moved into `c` here
- | | value moved into `b` here
- | value borrowed, by `a`, here
+ | | | value is moved into `c` here
+ | | value is moved into `b` here
+ | value is mutably borrowed by `a` here
error: cannot move out of value because it is borrowed
--> $DIR/borrowck-pat-by-move-and-ref.rs:47:9
@@ -98,8 +98,8 @@ error: cannot move out of value because it is borrowed
LL | ref a @ Some(b) => {}
| -----^^^^^^^^-^
| | |
- | | value moved into `b` here
- | value borrowed, by `a`, here
+ | | value is moved into `b` here
+ | value is borrowed by `a` here
error: cannot move out of value because it is borrowed
--> $DIR/borrowck-pat-by-move-and-ref.rs:52:9
@@ -107,9 +107,9 @@ error: cannot move out of value because it is borrowed
LL | ref a @ Some((ref b @ mut c, ref d @ e)) => {}
| -----^^^^^^^^^^^^^^^^^-----^^^^^^^^^^-^^
| | | |
- | | | value moved into `e` here
- | | value moved into `c` here
- | value borrowed, by `a`, here
+ | | | value is moved into `e` here
+ | | value is moved into `c` here
+ | value is borrowed by `a` here
error: cannot move out of value because it is borrowed
--> $DIR/borrowck-pat-by-move-and-ref.rs:52:23
@@ -117,8 +117,8 @@ error: cannot move out of value because it is borrowed
LL | ref a @ Some((ref b @ mut c, ref d @ e)) => {}
| -----^^^-----
| | |
- | | value moved into `c` here
- | value borrowed, by `b`, here
+ | | value is moved into `c` here
+ | value is borrowed by `b` here
error: cannot move out of value because it is borrowed
--> $DIR/borrowck-pat-by-move-and-ref.rs:52:38
@@ -126,8 +126,8 @@ error: cannot move out of value because it is borrowed
LL | ref a @ Some((ref b @ mut c, ref d @ e)) => {}
| -----^^^-
| | |
- | | value moved into `e` here
- | value borrowed, by `d`, here
+ | | value is moved into `e` here
+ | value is borrowed by `d` here
error: cannot move out of value because it is borrowed
--> $DIR/borrowck-pat-by-move-and-ref.rs:59:9
@@ -135,9 +135,9 @@ error: cannot move out of value because it is borrowed
LL | ref mut a @ Some([b, mut c]) => {}
| ---------^^^^^^^^^-^^-----^^
| | | |
- | | | value moved into `c` here
- | | value moved into `b` here
- | value borrowed, by `a`, here
+ | | | value is moved into `c` here
+ | | value is moved into `b` here
+ | value is mutably borrowed by `a` here
error: cannot move out of value because it is borrowed
--> $DIR/borrowck-pat-by-move-and-ref.rs:64:9
@@ -145,8 +145,8 @@ error: cannot move out of value because it is borrowed
LL | ref a @ Some(b) => {}
| -----^^^^^^^^-^
| | |
- | | value moved into `b` here
- | value borrowed, by `a`, here
+ | | value is moved into `b` here
+ | value is borrowed by `a` here
error: cannot move out of value because it is borrowed
--> $DIR/borrowck-pat-by-move-and-ref.rs:69:9
@@ -154,9 +154,9 @@ error: cannot move out of value because it is borrowed
LL | ref a @ Some((ref b @ mut c, ref d @ e)) => {}
| -----^^^^^^^^^^^^^^^^^-----^^^^^^^^^^-^^
| | | |
- | | | value moved into `e` here
- | | value moved into `c` here
- | value borrowed, by `a`, here
+ | | | value is moved into `e` here
+ | | value is moved into `c` here
+ | value is borrowed by `a` here
error: cannot move out of value because it is borrowed
--> $DIR/borrowck-pat-by-move-and-ref.rs:69:23
@@ -164,8 +164,8 @@ error: cannot move out of value because it is borrowed
LL | ref a @ Some((ref b @ mut c, ref d @ e)) => {}
| -----^^^-----
| | |
- | | value moved into `c` here
- | value borrowed, by `b`, here
+ | | value is moved into `c` here
+ | value is borrowed by `b` here
error: cannot move out of value because it is borrowed
--> $DIR/borrowck-pat-by-move-and-ref.rs:69:38
@@ -173,8 +173,8 @@ error: cannot move out of value because it is borrowed
LL | ref a @ Some((ref b @ mut c, ref d @ e)) => {}
| -----^^^-
| | |
- | | value moved into `e` here
- | value borrowed, by `d`, here
+ | | value is moved into `e` here
+ | value is borrowed by `d` here
error: cannot move out of value because it is borrowed
--> $DIR/borrowck-pat-by-move-and-ref.rs:78:9
@@ -182,9 +182,9 @@ error: cannot move out of value because it is borrowed
LL | ref mut a @ Some([b, mut c]) => {}
| ---------^^^^^^^^^-^^-----^^
| | | |
- | | | value moved into `c` here
- | | value moved into `b` here
- | value borrowed, by `a`, here
+ | | | value is moved into `c` here
+ | | value is moved into `b` here
+ | value is mutably borrowed by `a` here
error: cannot move out of value because it is borrowed
--> $DIR/borrowck-pat-by-move-and-ref.rs:11:11
@@ -192,8 +192,8 @@ error: cannot move out of value because it is borrowed
LL | fn f1(ref a @ b: U) {}
| -----^^^-
| | |
- | | value moved into `b` here
- | value borrowed, by `a`, here
+ | | value is moved into `b` here
+ | value is borrowed by `a` here
error: cannot move out of value because it is borrowed
--> $DIR/borrowck-pat-by-move-and-ref.rs:14:11
@@ -201,9 +201,9 @@ error: cannot move out of value because it is borrowed
LL | fn f2(ref a @ (ref b @ mut c, ref d @ e): (U, U)) {}
| -----^^^^^^^^^^^^-----^^^^^^^^^^-^
| | | |
- | | | value moved into `e` here
- | | value moved into `c` here
- | value borrowed, by `a`, here
+ | | | value is moved into `e` here
+ | | value is moved into `c` here
+ | value is borrowed by `a` here
error: cannot move out of value because it is borrowed
--> $DIR/borrowck-pat-by-move-and-ref.rs:14:20
@@ -211,8 +211,8 @@ error: cannot move out of value because it is borrowed
LL | fn f2(ref a @ (ref b @ mut c, ref d @ e): (U, U)) {}
| -----^^^-----
| | |
- | | value moved into `c` here
- | value borrowed, by `b`, here
+ | | value is moved into `c` here
+ | value is borrowed by `b` here
error: cannot move out of value because it is borrowed
--> $DIR/borrowck-pat-by-move-and-ref.rs:14:35
@@ -220,8 +220,8 @@ error: cannot move out of value because it is borrowed
LL | fn f2(ref a @ (ref b @ mut c, ref d @ e): (U, U)) {}
| -----^^^-
| | |
- | | value moved into `e` here
- | value borrowed, by `d`, here
+ | | value is moved into `e` here
+ | value is borrowed by `d` here
error: cannot move out of value because it is borrowed
--> $DIR/borrowck-pat-by-move-and-ref.rs:20:11
@@ -229,9 +229,9 @@ error: cannot move out of value because it is borrowed
LL | fn f3(ref mut a @ [b, mut c]: [U; 2]) {}
| ---------^^^^-^^-----^
| | | |
- | | | value moved into `c` here
- | | value moved into `b` here
- | value borrowed, by `a`, here
+ | | | value is moved into `c` here
+ | | value is moved into `b` here
+ | value is mutably borrowed by `a` here
error[E0382]: borrow of partially moved value
--> $DIR/borrowck-pat-by-move-and-ref.rs:30:9
diff --git a/tests/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-and-ref.stderr b/tests/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-and-ref.stderr
index 8546b4bb4..f51b50418 100644
--- a/tests/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-and-ref.stderr
+++ b/tests/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-and-ref.stderr
@@ -4,8 +4,8 @@ error: cannot borrow value as immutable because it is also borrowed as mutable
LL | ref mut z @ &mut Some(ref a) => {
| ---------^^^^^^^^^^^^^-----^
| | |
- | | immutable borrow, by `a`, occurs here
- | mutable borrow, by `z`, occurs here
+ | | value is borrowed by `a` here
+ | value is mutably borrowed by `z` here
error: cannot borrow value as mutable more than once at a time
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:33:9
@@ -13,9 +13,9 @@ error: cannot borrow value as mutable more than once at a time
LL | let ref mut a @ (ref b @ ref mut c) = u(); // sub-in-sub
| ---------^^^^-----------------^
| | | |
- | | | another mutable borrow, by `c`, occurs here
- | | also borrowed as immutable, by `b`, here
- | first mutable borrow, by `a`, occurs here
+ | | | value is mutably borrowed by `c` here
+ | | value is borrowed by `b` here
+ | value is mutably borrowed by `a` here
error: cannot borrow value as mutable because it is also borrowed as immutable
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:33:22
@@ -23,8 +23,8 @@ error: cannot borrow value as mutable because it is also borrowed as immutable
LL | let ref mut a @ (ref b @ ref mut c) = u(); // sub-in-sub
| -----^^^---------
| | |
- | | mutable borrow, by `c`, occurs here
- | immutable borrow, by `b`, occurs here
+ | | value is mutably borrowed by `c` here
+ | value is borrowed by `b` here
error: cannot borrow value as mutable because it is also borrowed as immutable
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:37:9
@@ -32,8 +32,8 @@ error: cannot borrow value as mutable because it is also borrowed as immutable
LL | let ref a @ ref mut b = U;
| -----^^^---------
| | |
- | | mutable borrow, by `b`, occurs here
- | immutable borrow, by `a`, occurs here
+ | | value is mutably borrowed by `b` here
+ | value is borrowed by `a` here
error: cannot borrow value as immutable because it is also borrowed as mutable
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:39:9
@@ -41,8 +41,8 @@ error: cannot borrow value as immutable because it is also borrowed as mutable
LL | let ref mut a @ ref b = U;
| ---------^^^-----
| | |
- | | immutable borrow, by `b`, occurs here
- | mutable borrow, by `a`, occurs here
+ | | value is borrowed by `b` here
+ | value is mutably borrowed by `a` here
error: cannot borrow value as mutable because it is also borrowed as immutable
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:41:9
@@ -50,9 +50,9 @@ error: cannot borrow value as mutable because it is also borrowed as immutable
LL | let ref a @ (ref mut b, ref mut c) = (U, U);
| -----^^^^---------^^---------^
| | | |
- | | | mutable borrow, by `c`, occurs here
- | | mutable borrow, by `b`, occurs here
- | immutable borrow, by `a`, occurs here
+ | | | value is mutably borrowed by `c` here
+ | | value is mutably borrowed by `b` here
+ | value is borrowed by `a` here
error: cannot borrow value as immutable because it is also borrowed as mutable
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:43:9
@@ -60,9 +60,9 @@ error: cannot borrow value as immutable because it is also borrowed as mutable
LL | let ref mut a @ (ref b, ref c) = (U, U);
| ---------^^^^-----^^-----^
| | | |
- | | | immutable borrow, by `c`, occurs here
- | | immutable borrow, by `b`, occurs here
- | mutable borrow, by `a`, occurs here
+ | | | value is borrowed by `c` here
+ | | value is borrowed by `b` here
+ | value is mutably borrowed by `a` here
error: cannot borrow value as immutable because it is also borrowed as mutable
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:46:9
@@ -70,8 +70,8 @@ error: cannot borrow value as immutable because it is also borrowed as mutable
LL | let ref mut a @ ref b = u();
| ---------^^^-----
| | |
- | | immutable borrow, by `b`, occurs here
- | mutable borrow, by `a`, occurs here
+ | | value is borrowed by `b` here
+ | value is mutably borrowed by `a` here
error: cannot borrow value as mutable because it is also borrowed as immutable
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:51:9
@@ -79,8 +79,8 @@ error: cannot borrow value as mutable because it is also borrowed as immutable
LL | let ref a @ ref mut b = u();
| -----^^^---------
| | |
- | | mutable borrow, by `b`, occurs here
- | immutable borrow, by `a`, occurs here
+ | | value is mutably borrowed by `b` here
+ | value is borrowed by `a` here
error: cannot borrow value as immutable because it is also borrowed as mutable
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:57:9
@@ -88,8 +88,8 @@ error: cannot borrow value as immutable because it is also borrowed as mutable
LL | let ref mut a @ ref b = U;
| ---------^^^-----
| | |
- | | immutable borrow, by `b`, occurs here
- | mutable borrow, by `a`, occurs here
+ | | value is borrowed by `b` here
+ | value is mutably borrowed by `a` here
error: cannot borrow value as mutable because it is also borrowed as immutable
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:61:9
@@ -97,8 +97,8 @@ error: cannot borrow value as mutable because it is also borrowed as immutable
LL | let ref a @ ref mut b = U;
| -----^^^---------
| | |
- | | mutable borrow, by `b`, occurs here
- | immutable borrow, by `a`, occurs here
+ | | value is mutably borrowed by `b` here
+ | value is borrowed by `a` here
error: cannot borrow value as immutable because it is also borrowed as mutable
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:67:9
@@ -106,8 +106,8 @@ error: cannot borrow value as immutable because it is also borrowed as mutable
LL | ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) => {
| ---------^^^^^^-----^
| | |
- | | immutable borrow, by `b`, occurs here
- | mutable borrow, by `a`, occurs here
+ | | value is borrowed by `b` here
+ | value is mutably borrowed by `a` here
error: cannot borrow value as immutable because it is also borrowed as mutable
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:67:33
@@ -115,8 +115,8 @@ error: cannot borrow value as immutable because it is also borrowed as mutable
LL | ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) => {
| ---------^^^^^^^-----^
| | |
- | | immutable borrow, by `b`, occurs here
- | mutable borrow, by `a`, occurs here
+ | | value is borrowed by `b` here
+ | value is mutably borrowed by `a` here
error: cannot borrow value as mutable because it is also borrowed as immutable
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:76:9
@@ -124,8 +124,8 @@ error: cannot borrow value as mutable because it is also borrowed as immutable
LL | ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) => {
| -----^^^^^^---------^
| | |
- | | mutable borrow, by `b`, occurs here
- | immutable borrow, by `a`, occurs here
+ | | value is mutably borrowed by `b` here
+ | value is borrowed by `a` here
error: cannot borrow value as mutable because it is also borrowed as immutable
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:76:33
@@ -133,8 +133,8 @@ error: cannot borrow value as mutable because it is also borrowed as immutable
LL | ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) => {
| -----^^^^^^^---------^
| | |
- | | mutable borrow, by `b`, occurs here
- | immutable borrow, by `a`, occurs here
+ | | value is mutably borrowed by `b` here
+ | value is borrowed by `a` here
error: cannot borrow value as mutable because it is also borrowed as immutable
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:87:9
@@ -142,8 +142,8 @@ error: cannot borrow value as mutable because it is also borrowed as immutable
LL | ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { *b = U; false } => {}
| -----^^^^^^---------^
| | |
- | | mutable borrow, by `b`, occurs here
- | immutable borrow, by `a`, occurs here
+ | | value is mutably borrowed by `b` here
+ | value is borrowed by `a` here
error: cannot borrow value as mutable because it is also borrowed as immutable
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:87:33
@@ -151,8 +151,8 @@ error: cannot borrow value as mutable because it is also borrowed as immutable
LL | ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { *b = U; false } => {}
| -----^^^^^^^---------^
| | |
- | | mutable borrow, by `b`, occurs here
- | immutable borrow, by `a`, occurs here
+ | | value is mutably borrowed by `b` here
+ | value is borrowed by `a` here
error: cannot borrow value as immutable because it is also borrowed as mutable
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:94:9
@@ -160,8 +160,8 @@ error: cannot borrow value as immutable because it is also borrowed as mutable
LL | ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) if { *a = Err(U); false } => {}
| ---------^^^^^^-----^
| | |
- | | immutable borrow, by `b`, occurs here
- | mutable borrow, by `a`, occurs here
+ | | value is borrowed by `b` here
+ | value is mutably borrowed by `a` here
error: cannot borrow value as immutable because it is also borrowed as mutable
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:94:33
@@ -169,8 +169,8 @@ error: cannot borrow value as immutable because it is also borrowed as mutable
LL | ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) if { *a = Err(U); false } => {}
| ---------^^^^^^^-----^
| | |
- | | immutable borrow, by `b`, occurs here
- | mutable borrow, by `a`, occurs here
+ | | value is borrowed by `b` here
+ | value is mutably borrowed by `a` here
error: cannot borrow value as mutable because it is also borrowed as immutable
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:101:9
@@ -178,8 +178,8 @@ error: cannot borrow value as mutable because it is also borrowed as immutable
LL | ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { drop(b); false } => {}
| -----^^^^^^---------^
| | |
- | | mutable borrow, by `b`, occurs here
- | immutable borrow, by `a`, occurs here
+ | | value is mutably borrowed by `b` here
+ | value is borrowed by `a` here
error: cannot borrow value as mutable because it is also borrowed as immutable
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:101:33
@@ -187,8 +187,8 @@ error: cannot borrow value as mutable because it is also borrowed as immutable
LL | ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { drop(b); false } => {}
| -----^^^^^^^---------^
| | |
- | | mutable borrow, by `b`, occurs here
- | immutable borrow, by `a`, occurs here
+ | | value is mutably borrowed by `b` here
+ | value is borrowed by `a` here
error: cannot borrow value as immutable because it is also borrowed as mutable
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:109:9
@@ -196,8 +196,8 @@ error: cannot borrow value as immutable because it is also borrowed as mutable
LL | ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) if { drop(a); false } => {}
| ---------^^^^^^-----^
| | |
- | | immutable borrow, by `b`, occurs here
- | mutable borrow, by `a`, occurs here
+ | | value is borrowed by `b` here
+ | value is mutably borrowed by `a` here
error: cannot borrow value as immutable because it is also borrowed as mutable
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:109:33
@@ -205,8 +205,8 @@ error: cannot borrow value as immutable because it is also borrowed as mutable
LL | ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) if { drop(a); false } => {}
| ---------^^^^^^^-----^
| | |
- | | immutable borrow, by `b`, occurs here
- | mutable borrow, by `a`, occurs here
+ | | value is borrowed by `b` here
+ | value is mutably borrowed by `a` here
error: cannot borrow value as mutable because it is also borrowed as immutable
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:117:9
@@ -214,9 +214,9 @@ error: cannot borrow value as mutable because it is also borrowed as immutable
LL | let ref a @ (ref mut b, ref mut c) = (U, U);
| -----^^^^---------^^---------^
| | | |
- | | | mutable borrow, by `c`, occurs here
- | | mutable borrow, by `b`, occurs here
- | immutable borrow, by `a`, occurs here
+ | | | value is mutably borrowed by `c` here
+ | | value is mutably borrowed by `b` here
+ | value is borrowed by `a` here
error: cannot borrow value as mutable because it is also borrowed as immutable
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:123:9
@@ -224,9 +224,9 @@ error: cannot borrow value as mutable because it is also borrowed as immutable
LL | let ref a @ (ref mut b, ref mut c) = (U, U);
| -----^^^^---------^^---------^
| | | |
- | | | mutable borrow, by `c`, occurs here
- | | mutable borrow, by `b`, occurs here
- | immutable borrow, by `a`, occurs here
+ | | | value is mutably borrowed by `c` here
+ | | value is mutably borrowed by `b` here
+ | value is borrowed by `a` here
error: cannot borrow value as mutable because it is also borrowed as immutable
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:129:9
@@ -234,9 +234,9 @@ error: cannot borrow value as mutable because it is also borrowed as immutable
LL | let ref a @ (ref mut b, ref mut c) = (U, U);
| -----^^^^---------^^---------^
| | | |
- | | | mutable borrow, by `c`, occurs here
- | | mutable borrow, by `b`, occurs here
- | immutable borrow, by `a`, occurs here
+ | | | value is mutably borrowed by `c` here
+ | | value is mutably borrowed by `b` here
+ | value is borrowed by `a` here
error: cannot borrow value as immutable because it is also borrowed as mutable
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:134:9
@@ -244,9 +244,9 @@ error: cannot borrow value as immutable because it is also borrowed as mutable
LL | let ref mut a @ (ref b, ref c) = (U, U);
| ---------^^^^-----^^-----^
| | | |
- | | | immutable borrow, by `c`, occurs here
- | | immutable borrow, by `b`, occurs here
- | mutable borrow, by `a`, occurs here
+ | | | value is borrowed by `c` here
+ | | value is borrowed by `b` here
+ | value is mutably borrowed by `a` here
error: cannot borrow value as mutable because it is also borrowed as immutable
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:22:11
@@ -254,8 +254,8 @@ error: cannot borrow value as mutable because it is also borrowed as immutable
LL | fn f1(ref a @ ref mut b: U) {}
| -----^^^---------
| | |
- | | mutable borrow, by `b`, occurs here
- | immutable borrow, by `a`, occurs here
+ | | value is mutably borrowed by `b` here
+ | value is borrowed by `a` here
error: cannot borrow value as immutable because it is also borrowed as mutable
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:24:11
@@ -263,8 +263,8 @@ error: cannot borrow value as immutable because it is also borrowed as mutable
LL | fn f2(ref mut a @ ref b: U) {}
| ---------^^^-----
| | |
- | | immutable borrow, by `b`, occurs here
- | mutable borrow, by `a`, occurs here
+ | | value is borrowed by `b` here
+ | value is mutably borrowed by `a` here
error: cannot borrow value as mutable because it is also borrowed as immutable
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:26:11
@@ -272,8 +272,8 @@ error: cannot borrow value as mutable because it is also borrowed as immutable
LL | fn f3(ref a @ [ref b, ref mut mid @ .., ref c]: [U; 4]) {}
| -----^^^^^^^^^^^----------------^^^^^^^^
| | |
- | | mutable borrow, by `mid`, occurs here
- | immutable borrow, by `a`, occurs here
+ | | value is mutably borrowed by `mid` here
+ | value is borrowed by `a` here
error: cannot borrow value as mutable because it is also borrowed as immutable
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:28:22
@@ -281,9 +281,9 @@ error: cannot borrow value as mutable because it is also borrowed as immutable
LL | fn f4_also_moved(ref a @ ref mut b @ c: U) {}
| -----^^^-------------
| | | |
- | | | also moved into `c` here
- | | mutable borrow, by `b`, occurs here
- | immutable borrow, by `a`, occurs here
+ | | | value is moved into `c` here
+ | | value is mutably borrowed by `b` here
+ | value is borrowed by `a` here
error: cannot move out of value because it is borrowed
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:28:30
@@ -291,8 +291,8 @@ error: cannot move out of value because it is borrowed
LL | fn f4_also_moved(ref a @ ref mut b @ c: U) {}
| ---------^^^-
| | |
- | | value moved into `c` here
- | value borrowed, by `b`, here
+ | | value is moved into `c` here
+ | value is mutably borrowed by `b` here
error[E0502]: cannot borrow value as immutable because it is also borrowed as mutable
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:8:31
diff --git a/tests/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-twice.stderr b/tests/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-twice.stderr
index ad4ce7952..a0cb04a06 100644
--- a/tests/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-twice.stderr
+++ b/tests/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-twice.stderr
@@ -4,8 +4,8 @@ error: cannot borrow value as mutable more than once at a time
LL | let ref mut a @ ref mut b = U;
| ---------^^^---------
| | |
- | | another mutable borrow, by `b`, occurs here
- | first mutable borrow, by `a`, occurs here
+ | | value is mutably borrowed by `b` here
+ | value is mutably borrowed by `a` here
error: cannot borrow value as mutable more than once at a time
--> $DIR/borrowck-pat-ref-mut-twice.rs:29:9
@@ -13,8 +13,8 @@ error: cannot borrow value as mutable more than once at a time
LL | let ref mut a @ ref mut b = U;
| ---------^^^---------
| | |
- | | another mutable borrow, by `b`, occurs here
- | first mutable borrow, by `a`, occurs here
+ | | value is mutably borrowed by `b` here
+ | value is mutably borrowed by `a` here
error: cannot borrow value as mutable more than once at a time
--> $DIR/borrowck-pat-ref-mut-twice.rs:33:9
@@ -22,8 +22,8 @@ error: cannot borrow value as mutable more than once at a time
LL | let ref mut a @ ref mut b = U;
| ---------^^^---------
| | |
- | | another mutable borrow, by `b`, occurs here
- | first mutable borrow, by `a`, occurs here
+ | | value is mutably borrowed by `b` here
+ | value is mutably borrowed by `a` here
error: cannot borrow value as mutable more than once at a time
--> $DIR/borrowck-pat-ref-mut-twice.rs:36:9
@@ -31,8 +31,8 @@ error: cannot borrow value as mutable more than once at a time
LL | let ref mut a @ ref mut b = U;
| ---------^^^---------
| | |
- | | another mutable borrow, by `b`, occurs here
- | first mutable borrow, by `a`, occurs here
+ | | value is mutably borrowed by `b` here
+ | value is mutably borrowed by `a` here
error: cannot borrow value as mutable more than once at a time
--> $DIR/borrowck-pat-ref-mut-twice.rs:39:9
@@ -40,8 +40,8 @@ error: cannot borrow value as mutable more than once at a time
LL | let ref mut a @ ref mut b = U;
| ---------^^^---------
| | |
- | | another mutable borrow, by `b`, occurs here
- | first mutable borrow, by `a`, occurs here
+ | | value is mutably borrowed by `b` here
+ | value is mutably borrowed by `a` here
error: cannot borrow value as mutable more than once at a time
--> $DIR/borrowck-pat-ref-mut-twice.rs:44:9
@@ -49,18 +49,18 @@ error: cannot borrow value as mutable more than once at a time
LL | let ref mut a @ (
| ^--------
| |
- | _________first mutable borrow, by `a`, occurs here
+ | _________value is mutably borrowed by `a` here
| |
LL | |
LL | | ref mut b,
- | | --------- another mutable borrow, by `b`, occurs here
+ | | --------- value is mutably borrowed by `b` here
LL | | [
LL | | ref mut c,
- | | --------- another mutable borrow, by `c`, occurs here
+ | | --------- value is mutably borrowed by `c` here
LL | | ref mut d,
- | | --------- another mutable borrow, by `d`, occurs here
+ | | --------- value is mutably borrowed by `d` here
LL | | ref e,
- | | ----- also borrowed as immutable, by `e`, here
+ | | ----- value is borrowed by `e` here
LL | | ]
LL | | ) = (U, [U, U, U]);
| |_____^
@@ -71,18 +71,18 @@ error: cannot borrow value as mutable more than once at a time
LL | let ref mut a @ (
| ^--------
| |
- | _________first mutable borrow, by `a`, occurs here
+ | _________value is mutably borrowed by `a` here
| |
LL | |
LL | | ref mut b,
- | | --------- another mutable borrow, by `b`, occurs here
+ | | --------- value is mutably borrowed by `b` here
LL | | [
LL | | ref mut c,
- | | --------- another mutable borrow, by `c`, occurs here
+ | | --------- value is mutably borrowed by `c` here
LL | | ref mut d,
- | | --------- another mutable borrow, by `d`, occurs here
+ | | --------- value is mutably borrowed by `d` here
LL | | ref e,
- | | ----- also borrowed as immutable, by `e`, here
+ | | ----- value is borrowed by `e` here
LL | | ]
LL | | ) = (u(), [u(), u(), u()]);
| |_________^
@@ -157,8 +157,8 @@ error: cannot borrow value as mutable more than once at a time
LL | ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => {
| ---------^^^^^^---------^
| | |
- | | another mutable borrow, by `b`, occurs here
- | first mutable borrow, by `a`, occurs here
+ | | value is mutably borrowed by `b` here
+ | value is mutably borrowed by `a` here
error: cannot borrow value as mutable more than once at a time
--> $DIR/borrowck-pat-ref-mut-twice.rs:76:37
@@ -166,8 +166,8 @@ error: cannot borrow value as mutable more than once at a time
LL | ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => {
| ---------^^^^^^^---------^
| | |
- | | another mutable borrow, by `b`, occurs here
- | first mutable borrow, by `a`, occurs here
+ | | value is mutably borrowed by `b` here
+ | value is mutably borrowed by `a` here
error: cannot borrow value as mutable more than once at a time
--> $DIR/borrowck-pat-ref-mut-twice.rs:82:9
@@ -175,8 +175,8 @@ error: cannot borrow value as mutable more than once at a time
LL | ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => {
| ---------^^^^^^---------^
| | |
- | | another mutable borrow, by `b`, occurs here
- | first mutable borrow, by `a`, occurs here
+ | | value is mutably borrowed by `b` here
+ | value is mutably borrowed by `a` here
error: cannot borrow value as mutable more than once at a time
--> $DIR/borrowck-pat-ref-mut-twice.rs:82:37
@@ -184,8 +184,8 @@ error: cannot borrow value as mutable more than once at a time
LL | ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => {
| ---------^^^^^^^---------^
| | |
- | | another mutable borrow, by `b`, occurs here
- | first mutable borrow, by `a`, occurs here
+ | | value is mutably borrowed by `b` here
+ | value is mutably borrowed by `a` here
error: cannot borrow value as mutable more than once at a time
--> $DIR/borrowck-pat-ref-mut-twice.rs:89:9
@@ -193,8 +193,8 @@ error: cannot borrow value as mutable more than once at a time
LL | ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => {
| ---------^^^^^^---------^
| | |
- | | another mutable borrow, by `b`, occurs here
- | first mutable borrow, by `a`, occurs here
+ | | value is mutably borrowed by `b` here
+ | value is mutably borrowed by `a` here
error: cannot borrow value as mutable more than once at a time
--> $DIR/borrowck-pat-ref-mut-twice.rs:89:37
@@ -202,8 +202,8 @@ error: cannot borrow value as mutable more than once at a time
LL | ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => {
| ---------^^^^^^^---------^
| | |
- | | another mutable borrow, by `b`, occurs here
- | first mutable borrow, by `a`, occurs here
+ | | value is mutably borrowed by `b` here
+ | value is mutably borrowed by `a` here
error: cannot borrow value as mutable more than once at a time
--> $DIR/borrowck-pat-ref-mut-twice.rs:101:9
@@ -211,8 +211,8 @@ error: cannot borrow value as mutable more than once at a time
LL | ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => {
| ---------^^^^^^---------^
| | |
- | | another mutable borrow, by `b`, occurs here
- | first mutable borrow, by `a`, occurs here
+ | | value is mutably borrowed by `b` here
+ | value is mutably borrowed by `a` here
error: cannot borrow value as mutable more than once at a time
--> $DIR/borrowck-pat-ref-mut-twice.rs:101:37
@@ -220,8 +220,8 @@ error: cannot borrow value as mutable more than once at a time
LL | ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => {
| ---------^^^^^^^---------^
| | |
- | | another mutable borrow, by `b`, occurs here
- | first mutable borrow, by `a`, occurs here
+ | | value is mutably borrowed by `b` here
+ | value is mutably borrowed by `a` here
error: cannot borrow value as mutable more than once at a time
--> $DIR/borrowck-pat-ref-mut-twice.rs:8:11
@@ -229,8 +229,8 @@ error: cannot borrow value as mutable more than once at a time
LL | fn f1(ref mut a @ ref mut b: U) {}
| ---------^^^---------
| | |
- | | another mutable borrow, by `b`, occurs here
- | first mutable borrow, by `a`, occurs here
+ | | value is mutably borrowed by `b` here
+ | value is mutably borrowed by `a` here
error: cannot borrow value as mutable more than once at a time
--> $DIR/borrowck-pat-ref-mut-twice.rs:10:11
@@ -238,8 +238,8 @@ error: cannot borrow value as mutable more than once at a time
LL | fn f2(ref mut a @ ref mut b: U) {}
| ---------^^^---------
| | |
- | | another mutable borrow, by `b`, occurs here
- | first mutable borrow, by `a`, occurs here
+ | | value is mutably borrowed by `b` here
+ | value is mutably borrowed by `a` here
error: cannot borrow value as mutable more than once at a time
--> $DIR/borrowck-pat-ref-mut-twice.rs:13:9
@@ -247,13 +247,13 @@ error: cannot borrow value as mutable more than once at a time
LL | ref mut a @ [
| ^--------
| |
- | _________first mutable borrow, by `a`, occurs here
+ | _________value is mutably borrowed by `a` here
| |
LL | |
LL | | [ref b @ .., _],
- | | ---------- also borrowed as immutable, by `b`, here
+ | | ---------- value is borrowed by `b` here
LL | | [_, ref mut mid @ ..],
- | | ---------------- another mutable borrow, by `mid`, occurs here
+ | | ---------------- value is mutably borrowed by `mid` here
LL | | ..,
LL | | [..],
LL | | ] : [[U; 4]; 5]
@@ -265,9 +265,9 @@ error: cannot borrow value as mutable more than once at a time
LL | fn f4_also_moved(ref mut a @ ref mut b @ c: U) {}
| ---------^^^-------------
| | | |
- | | | also moved into `c` here
- | | another mutable borrow, by `b`, occurs here
- | first mutable borrow, by `a`, occurs here
+ | | | value is moved into `c` here
+ | | value is mutably borrowed by `b` here
+ | value is mutably borrowed by `a` here
error: cannot move out of value because it is borrowed
--> $DIR/borrowck-pat-ref-mut-twice.rs:21:34
@@ -275,8 +275,8 @@ error: cannot move out of value because it is borrowed
LL | fn f4_also_moved(ref mut a @ ref mut b @ c: U) {}
| ---------^^^-
| | |
- | | value moved into `c` here
- | value borrowed, by `b`, here
+ | | value is moved into `c` here
+ | value is mutably borrowed by `b` here
error[E0499]: cannot borrow value as mutable more than once at a time
--> $DIR/borrowck-pat-ref-mut-twice.rs:29:9
diff --git a/tests/ui/pattern/bindings-after-at/default-binding-modes-both-sides-independent.stderr b/tests/ui/pattern/bindings-after-at/default-binding-modes-both-sides-independent.stderr
index 638bdd6db..73ebbf481 100644
--- a/tests/ui/pattern/bindings-after-at/default-binding-modes-both-sides-independent.stderr
+++ b/tests/ui/pattern/bindings-after-at/default-binding-modes-both-sides-independent.stderr
@@ -4,8 +4,8 @@ error: cannot move out of value because it is borrowed
LL | let ref a @ b = NotCopy;
| -----^^^-
| | |
- | | value moved into `b` here
- | value borrowed, by `a`, here
+ | | value is moved into `b` here
+ | value is borrowed by `a` here
error: cannot move out of value because it is borrowed
--> $DIR/default-binding-modes-both-sides-independent.rs:29:9
@@ -13,8 +13,8 @@ error: cannot move out of value because it is borrowed
LL | let ref mut a @ b = NotCopy;
| ---------^^^-
| | |
- | | value moved into `b` here
- | value borrowed, by `a`, here
+ | | value is moved into `b` here
+ | value is mutably borrowed by `a` here
error: cannot move out of value because it is borrowed
--> $DIR/default-binding-modes-both-sides-independent.rs:34:12
@@ -22,8 +22,8 @@ error: cannot move out of value because it is borrowed
LL | Ok(ref a @ b) | Err(b @ ref a) => {
| -----^^^-
| | |
- | | value moved into `b` here
- | value borrowed, by `a`, here
+ | | value is moved into `b` here
+ | value is borrowed by `a` here
error: borrow of moved value
--> $DIR/default-binding-modes-both-sides-independent.rs:34:29
@@ -46,8 +46,8 @@ error: cannot move out of value because it is borrowed
LL | ref a @ b => {
| -----^^^-
| | |
- | | value moved into `b` here
- | value borrowed, by `a`, here
+ | | value is moved into `b` here
+ | value is borrowed by `a` here
error[E0382]: borrow of moved value
--> $DIR/default-binding-modes-both-sides-independent.rs:29:9
diff --git a/tests/ui/pattern/for-loop-bad-item.stderr b/tests/ui/pattern/for-loop-bad-item.stderr
index f064a25a9..67c6d6f01 100644
--- a/tests/ui/pattern/for-loop-bad-item.stderr
+++ b/tests/ui/pattern/for-loop-bad-item.stderr
@@ -25,7 +25,7 @@ error[E0308]: mismatched types
LL | for Some(Qux(_)) | None in [Some(""), None] {
| ^^^^^^ ---------------- this is an iterator with items of type `Option<&str>`
| |
- | expected `str`, found struct `Qux`
+ | expected `str`, found `Qux`
error: aborting due to 2 previous errors
diff --git a/tests/ui/pattern/issue-67037-pat-tup-scrut-ty-diff-less-fields.stderr b/tests/ui/pattern/issue-67037-pat-tup-scrut-ty-diff-less-fields.stderr
index 75a231f6b..daab3a862 100644
--- a/tests/ui/pattern/issue-67037-pat-tup-scrut-ty-diff-less-fields.stderr
+++ b/tests/ui/pattern/issue-67037-pat-tup-scrut-ty-diff-less-fields.stderr
@@ -4,7 +4,7 @@ error[E0308]: mismatched types
LL | let P() = U {};
| ^^^ ---- this expression has type `U`
| |
- | expected struct `U`, found struct `P`
+ | expected `U`, found `P<_>`
|
= note: expected struct `U`
found struct `P<_>`
diff --git a/tests/ui/pattern/move-ref-patterns/borrowck-move-ref-pattern.stderr b/tests/ui/pattern/move-ref-patterns/borrowck-move-ref-pattern.stderr
index 1b93267b3..c7c7c074f 100644
--- a/tests/ui/pattern/move-ref-patterns/borrowck-move-ref-pattern.stderr
+++ b/tests/ui/pattern/move-ref-patterns/borrowck-move-ref-pattern.stderr
@@ -1,6 +1,8 @@
error[E0505]: cannot move out of `arr[..]` because it is borrowed
--> $DIR/borrowck-move-ref-pattern.rs:8:24
|
+LL | let mut arr = [U, U, U, U, U];
+ | ------- binding `arr` declared here
LL | let hold_all = &arr;
| ---- borrow of `arr` occurs here
LL | let [ref _x0_hold, _x1, ref xs_hold @ ..] = arr;
diff --git a/tests/ui/pattern/pat-struct-field-expr-has-type.stderr b/tests/ui/pattern/pat-struct-field-expr-has-type.stderr
index 3a61d4293..029075293 100644
--- a/tests/ui/pattern/pat-struct-field-expr-has-type.stderr
+++ b/tests/ui/pattern/pat-struct-field-expr-has-type.stderr
@@ -4,7 +4,7 @@ error[E0308]: mismatched types
LL | match (S { f: 42 }) {
| ------------- this expression has type `S`
LL | S { f: Ok(_) } => {}
- | ^^^^^ expected `u8`, found enum `Result`
+ | ^^^^^ expected `u8`, found `Result<_, _>`
|
= note: expected type `u8`
found enum `Result<_, _>`
diff --git a/tests/ui/pattern/pat-type-err-formal-param.stderr b/tests/ui/pattern/pat-type-err-formal-param.stderr
index 206713a4b..4f482c52a 100644
--- a/tests/ui/pattern/pat-type-err-formal-param.stderr
+++ b/tests/ui/pattern/pat-type-err-formal-param.stderr
@@ -4,7 +4,7 @@ error[E0308]: mismatched types
LL | fn foo(Tuple(_): String) {}
| ^^^^^^^^ ------ expected due to this
| |
- | expected struct `String`, found struct `Tuple`
+ | expected `String`, found `Tuple`
error: aborting due to previous error
diff --git a/tests/ui/pattern/pat-type-err-let-stmt.stderr b/tests/ui/pattern/pat-type-err-let-stmt.stderr
index 090bd6711..b68b69a78 100644
--- a/tests/ui/pattern/pat-type-err-let-stmt.stderr
+++ b/tests/ui/pattern/pat-type-err-let-stmt.stderr
@@ -2,7 +2,7 @@ error[E0308]: mismatched types
--> $DIR/pat-type-err-let-stmt.rs:6:29
|
LL | let Ok(0): Option<u8> = 42u8;
- | ---------- ^^^^ expected enum `Option`, found `u8`
+ | ---------- ^^^^ expected `Option<u8>`, found `u8`
| |
| expected due to this
|
@@ -19,7 +19,7 @@ error[E0308]: mismatched types
LL | let Ok(0): Option<u8> = 42u8;
| ^^^^^ ---------- expected due to this
| |
- | expected enum `Option`, found enum `Result`
+ | expected `Option<u8>`, found `Result<_, _>`
|
= note: expected enum `Option<u8>`
found enum `Result<_, _>`
@@ -30,7 +30,7 @@ error[E0308]: mismatched types
LL | let Ok(0): Option<u8>;
| ^^^^^ ---------- expected due to this
| |
- | expected enum `Option`, found enum `Result`
+ | expected `Option<u8>`, found `Result<_, _>`
|
= note: expected enum `Option<u8>`
found enum `Result<_, _>`
@@ -41,7 +41,7 @@ error[E0308]: mismatched types
LL | let Ok(0) = 42u8;
| ^^^^^ ---- this expression has type `u8`
| |
- | expected `u8`, found enum `Result`
+ | expected `u8`, found `Result<_, _>`
|
= note: expected type `u8`
found enum `Result<_, _>`
diff --git a/tests/ui/pattern/pattern-error-continue.rs b/tests/ui/pattern/pattern-error-continue.rs
index 0702a9986..bed949439 100644
--- a/tests/ui/pattern/pattern-error-continue.rs
+++ b/tests/ui/pattern/pattern-error-continue.rs
@@ -21,7 +21,7 @@ fn main() {
match 'c' {
S { .. } => (),
//~^ ERROR mismatched types
- //~| expected `char`, found struct `S`
+ //~| expected `char`, found `S`
_ => ()
}
diff --git a/tests/ui/pattern/pattern-error-continue.stderr b/tests/ui/pattern/pattern-error-continue.stderr
index 4c2eff63a..e1349fb02 100644
--- a/tests/ui/pattern/pattern-error-continue.stderr
+++ b/tests/ui/pattern/pattern-error-continue.stderr
@@ -40,7 +40,7 @@ error[E0308]: mismatched types
LL | match 'c' {
| --- this expression has type `char`
LL | S { .. } => (),
- | ^^^^^^^^ expected `char`, found struct `S`
+ | ^^^^^^^^ expected `char`, found `S`
error[E0308]: mismatched types
--> $DIR/pattern-error-continue.rs:28:7
diff --git a/tests/ui/pattern/pattern-ident-path-generics.stderr b/tests/ui/pattern/pattern-ident-path-generics.stderr
index 01b082bd3..62283dfe9 100644
--- a/tests/ui/pattern/pattern-ident-path-generics.stderr
+++ b/tests/ui/pattern/pattern-ident-path-generics.stderr
@@ -4,7 +4,7 @@ error[E0308]: mismatched types
LL | match Some("foo") {
| ----------- this expression has type `Option<&str>`
LL | None::<isize> => {}
- | ^^^^^^^^^^^^^ expected `&str`, found `isize`
+ | ^^^^^^^^^^^^^ expected `Option<&str>`, found `Option<isize>`
|
= note: expected enum `Option<&str>`
found enum `Option<isize>`
diff --git a/tests/ui/pattern/pattern-tyvar.stderr b/tests/ui/pattern/pattern-tyvar.stderr
index f1e2a9d72..4eb002548 100644
--- a/tests/ui/pattern/pattern-tyvar.stderr
+++ b/tests/ui/pattern/pattern-tyvar.stderr
@@ -4,7 +4,7 @@ error[E0308]: mismatched types
LL | match t {
| - this expression has type `Bar`
LL | Bar::T1(_, Some::<isize>(x)) => {
- | ^^^^^^^^^^^^^^^^ expected struct `Vec`, found `isize`
+ | ^^^^^^^^^^^^^^^^ expected `Option<Vec<isize>>`, found `Option<isize>`
|
= note: expected enum `Option<Vec<isize>>`
found enum `Option<isize>`
diff --git a/tests/ui/point-to-type-err-cause-on-impl-trait-return-2.stderr b/tests/ui/point-to-type-err-cause-on-impl-trait-return-2.stderr
index f5a5f1ab3..a8d0d6236 100644
--- a/tests/ui/point-to-type-err-cause-on-impl-trait-return-2.stderr
+++ b/tests/ui/point-to-type-err-cause-on-impl-trait-return-2.stderr
@@ -2,7 +2,7 @@ error[E0308]: mismatched types
--> $DIR/point-to-type-err-cause-on-impl-trait-return-2.rs:9:41
|
LL | let value: &bool = unsafe { &42 };
- | ^^^ expected `bool`, found integer
+ | ^^^ expected `&bool`, found `&{integer}`
|
= note: expected reference `&bool`
found reference `&{integer}`
diff --git a/tests/ui/print_type_sizes/async.stdout b/tests/ui/print_type_sizes/async.stdout
index 6e47bb493..8fe936efc 100644
--- a/tests/ui/print_type_sizes/async.stdout
+++ b/tests/ui/print_type_sizes/async.stdout
@@ -1,15 +1,15 @@
print-type-size type: `[async fn body@$DIR/async.rs:8:36: 11:2]`: 16386 bytes, alignment: 1 bytes
print-type-size discriminant: 1 bytes
-print-type-size variant `Suspend0`: 16385 bytes
-print-type-size field `.arg`: 8192 bytes, offset: 0 bytes, alignment: 1 bytes
-print-type-size field `.arg`: 8192 bytes
-print-type-size field `.__awaitee`: 1 bytes
print-type-size variant `Unresumed`: 8192 bytes
-print-type-size field `.arg`: 8192 bytes, offset: 0 bytes, alignment: 1 bytes
+print-type-size upvar `.arg`: 8192 bytes, offset: 0 bytes, alignment: 1 bytes
+print-type-size variant `Suspend0`: 16385 bytes
+print-type-size upvar `.arg`: 8192 bytes, offset: 0 bytes, alignment: 1 bytes
+print-type-size local `.arg`: 8192 bytes
+print-type-size local `.__awaitee`: 1 bytes
print-type-size variant `Returned`: 8192 bytes
-print-type-size field `.arg`: 8192 bytes, offset: 0 bytes, alignment: 1 bytes
+print-type-size upvar `.arg`: 8192 bytes, offset: 0 bytes, alignment: 1 bytes
print-type-size variant `Panicked`: 8192 bytes
-print-type-size field `.arg`: 8192 bytes, offset: 0 bytes, alignment: 1 bytes
+print-type-size upvar `.arg`: 8192 bytes, offset: 0 bytes, alignment: 1 bytes
print-type-size type: `std::mem::ManuallyDrop<[u8; 8192]>`: 8192 bytes, alignment: 1 bytes
print-type-size field `.value`: 8192 bytes
print-type-size type: `std::mem::MaybeUninit<[u8; 8192]>`: 8192 bytes, alignment: 1 bytes
diff --git a/tests/ui/print_type_sizes/generator.stdout b/tests/ui/print_type_sizes/generator.stdout
index 28d4a6e6c..7c58d6ce5 100644
--- a/tests/ui/print_type_sizes/generator.stdout
+++ b/tests/ui/print_type_sizes/generator.stdout
@@ -1,10 +1,10 @@
print-type-size type: `[generator@$DIR/generator.rs:10:5: 10:14]`: 8193 bytes, alignment: 1 bytes
print-type-size discriminant: 1 bytes
print-type-size variant `Unresumed`: 8192 bytes
-print-type-size field `.array`: 8192 bytes, offset: 0 bytes, alignment: 1 bytes
+print-type-size upvar `.array`: 8192 bytes, offset: 0 bytes, alignment: 1 bytes
+print-type-size variant `Suspend0`: 8192 bytes
+print-type-size upvar `.array`: 8192 bytes, offset: 0 bytes, alignment: 1 bytes
print-type-size variant `Returned`: 8192 bytes
-print-type-size field `.array`: 8192 bytes, offset: 0 bytes, alignment: 1 bytes
+print-type-size upvar `.array`: 8192 bytes, offset: 0 bytes, alignment: 1 bytes
print-type-size variant `Panicked`: 8192 bytes
-print-type-size field `.array`: 8192 bytes, offset: 0 bytes, alignment: 1 bytes
-print-type-size variant `Suspend0`: 8192 bytes
-print-type-size field `.array`: 8192 bytes, offset: 0 bytes, alignment: 1 bytes
+print-type-size upvar `.array`: 8192 bytes, offset: 0 bytes, alignment: 1 bytes
diff --git a/tests/ui/print_type_sizes/generator_discr_placement.stdout b/tests/ui/print_type_sizes/generator_discr_placement.stdout
index 7f8f4ccae..f2a11c7a3 100644
--- a/tests/ui/print_type_sizes/generator_discr_placement.stdout
+++ b/tests/ui/print_type_sizes/generator_discr_placement.stdout
@@ -1,11 +1,11 @@
print-type-size type: `[generator@$DIR/generator_discr_placement.rs:11:13: 11:15]`: 8 bytes, alignment: 4 bytes
print-type-size discriminant: 1 bytes
+print-type-size variant `Unresumed`: 0 bytes
print-type-size variant `Suspend0`: 7 bytes
print-type-size padding: 3 bytes
-print-type-size field `.w`: 4 bytes, alignment: 4 bytes
+print-type-size local `.w`: 4 bytes, alignment: 4 bytes
print-type-size variant `Suspend1`: 7 bytes
print-type-size padding: 3 bytes
-print-type-size field `.z`: 4 bytes, alignment: 4 bytes
-print-type-size variant `Unresumed`: 0 bytes
+print-type-size local `.z`: 4 bytes, alignment: 4 bytes
print-type-size variant `Returned`: 0 bytes
print-type-size variant `Panicked`: 0 bytes
diff --git a/tests/ui/privacy/privacy1.rs b/tests/ui/privacy/privacy1.rs
index 3c9fa983d..fcb2108ab 100644
--- a/tests/ui/privacy/privacy1.rs
+++ b/tests/ui/privacy/privacy1.rs
@@ -106,7 +106,7 @@ mod foo {
//~^ ERROR: associated function `bar` is private
::bar::baz::A.foo2(); //~ ERROR: module `baz` is private
::bar::baz::A.bar2(); //~ ERROR: module `baz` is private
- //~^ ERROR: associated function `bar2` is private
+ //~^ ERROR: method `bar2` is private
let _: isize =
::bar::B::foo(); //~ ERROR: trait `B` is private
diff --git a/tests/ui/privacy/privacy1.stderr b/tests/ui/privacy/privacy1.stderr
index 70e6fcb7a..6ebed8ee0 100644
--- a/tests/ui/privacy/privacy1.stderr
+++ b/tests/ui/privacy/privacy1.stderr
@@ -190,14 +190,14 @@ LL | fn bar() {}
LL | ::bar::baz::A::bar();
| ^^^ private associated function
-error[E0624]: associated function `bar2` is private
+error[E0624]: method `bar2` is private
--> $DIR/privacy1.rs:108:23
|
LL | fn bar2(&self) {}
- | -------------- private associated function defined here
+ | -------------- private method defined here
...
LL | ::bar::baz::A.bar2();
- | ^^^^ private associated function
+ | ^^^^ private method
error: aborting due to 18 previous errors
diff --git a/tests/ui/privacy/private-impl-method.rs b/tests/ui/privacy/private-impl-method.rs
index f7be6726c..b5587920f 100644
--- a/tests/ui/privacy/private-impl-method.rs
+++ b/tests/ui/privacy/private-impl-method.rs
@@ -17,5 +17,5 @@ fn f() {
fn main() {
let s = a::Foo { x: 1 };
s.bar();
- s.foo(); //~ ERROR associated function `foo` is private
+ s.foo(); //~ ERROR method `foo` is private
}
diff --git a/tests/ui/privacy/private-impl-method.stderr b/tests/ui/privacy/private-impl-method.stderr
index bb54dce7e..18e4531d1 100644
--- a/tests/ui/privacy/private-impl-method.stderr
+++ b/tests/ui/privacy/private-impl-method.stderr
@@ -1,11 +1,11 @@
-error[E0624]: associated function `foo` is private
+error[E0624]: method `foo` is private
--> $DIR/private-impl-method.rs:20:7
|
LL | fn foo(&self) {}
- | ------------- private associated function defined here
+ | ------------- private method defined here
...
LL | s.foo();
- | ^^^ private associated function
+ | ^^^ private method
error: aborting due to previous error
diff --git a/tests/ui/privacy/private-in-public-ill-formed.stderr b/tests/ui/privacy/private-in-public-ill-formed.stderr
index e7c94bc30..abc8538e5 100644
--- a/tests/ui/privacy/private-in-public-ill-formed.stderr
+++ b/tests/ui/privacy/private-in-public-ill-formed.stderr
@@ -1,16 +1,16 @@
error[E0118]: no nominal type found for inherent implementation
- --> $DIR/private-in-public-ill-formed.rs:14:10
+ --> $DIR/private-in-public-ill-formed.rs:14:5
|
LL | impl <Priv as PrivTr>::AssocAlias {
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl requires a nominal type
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl requires a nominal type
|
= note: either implement a trait on it or create a newtype to wrap it instead
error[E0118]: no nominal type found for inherent implementation
- --> $DIR/private-in-public-ill-formed.rs:31:10
+ --> $DIR/private-in-public-ill-formed.rs:31:5
|
LL | impl <Priv as PrivTr>::AssocAlias {
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl requires a nominal type
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl requires a nominal type
|
= note: either implement a trait on it or create a newtype to wrap it instead
diff --git a/tests/ui/privacy/private-method-cross-crate.rs b/tests/ui/privacy/private-method-cross-crate.rs
index ab3bbdfe4..4da44e068 100644
--- a/tests/ui/privacy/private-method-cross-crate.rs
+++ b/tests/ui/privacy/private-method-cross-crate.rs
@@ -4,5 +4,5 @@ use cci_class_5::kitties::cat;
fn main() {
let nyan : cat = cat(52, 99);
- nyan.nap(); //~ ERROR associated function `nap` is private
+ nyan.nap(); //~ ERROR method `nap` is private
}
diff --git a/tests/ui/privacy/private-method-cross-crate.stderr b/tests/ui/privacy/private-method-cross-crate.stderr
index 93f6a7f2f..e644440c8 100644
--- a/tests/ui/privacy/private-method-cross-crate.stderr
+++ b/tests/ui/privacy/private-method-cross-crate.stderr
@@ -1,13 +1,13 @@
-error[E0624]: associated function `nap` is private
+error[E0624]: method `nap` is private
--> $DIR/private-method-cross-crate.rs:7:8
|
LL | nyan.nap();
- | ^^^ private associated function
+ | ^^^ private method
|
::: $DIR/auxiliary/cci_class_5.rs:8:9
|
LL | fn nap(&self) {}
- | ------------- private associated function defined here
+ | ------------- private method defined here
error: aborting due to previous error
diff --git a/tests/ui/privacy/private-method-inherited.rs b/tests/ui/privacy/private-method-inherited.rs
index 2f6454288..bc27027e8 100644
--- a/tests/ui/privacy/private-method-inherited.rs
+++ b/tests/ui/privacy/private-method-inherited.rs
@@ -10,5 +10,5 @@ mod a {
fn main() {
let x = a::Foo;
- x.f(); //~ ERROR associated function `f` is private
+ x.f(); //~ ERROR method `f` is private
}
diff --git a/tests/ui/privacy/private-method-inherited.stderr b/tests/ui/privacy/private-method-inherited.stderr
index 011a7fee4..0104a1b27 100644
--- a/tests/ui/privacy/private-method-inherited.stderr
+++ b/tests/ui/privacy/private-method-inherited.stderr
@@ -1,11 +1,11 @@
-error[E0624]: associated function `f` is private
+error[E0624]: method `f` is private
--> $DIR/private-method-inherited.rs:13:7
|
LL | fn f(self) {}
- | ---------- private associated function defined here
+ | ---------- private method defined here
...
LL | x.f();
- | ^ private associated function
+ | ^ private method
error: aborting due to previous error
diff --git a/tests/ui/privacy/private-method.rs b/tests/ui/privacy/private-method.rs
index 76a642cde..a9bea520e 100644
--- a/tests/ui/privacy/private-method.rs
+++ b/tests/ui/privacy/private-method.rs
@@ -19,5 +19,5 @@ mod kitties {
fn main() {
let nyan : kitties::Cat = kitties::cat(52, 99);
- nyan.nap(); //~ ERROR associated function `nap` is private
+ nyan.nap(); //~ ERROR method `nap` is private
}
diff --git a/tests/ui/privacy/private-method.stderr b/tests/ui/privacy/private-method.stderr
index 17c7179dc..42fec7622 100644
--- a/tests/ui/privacy/private-method.stderr
+++ b/tests/ui/privacy/private-method.stderr
@@ -1,11 +1,11 @@
-error[E0624]: associated function `nap` is private
+error[E0624]: method `nap` is private
--> $DIR/private-method.rs:22:8
|
LL | fn nap(&self) {}
- | ------------- private associated function defined here
+ | ------------- private method defined here
...
LL | nyan.nap();
- | ^^^ private associated function
+ | ^^^ private method
error: aborting due to previous error
diff --git a/tests/ui/privacy/restricted/test.stderr b/tests/ui/privacy/restricted/test.stderr
index 1acd221b4..76f19525d 100644
--- a/tests/ui/privacy/restricted/test.stderr
+++ b/tests/ui/privacy/restricted/test.stderr
@@ -54,14 +54,14 @@ error[E0616]: field `x` of struct `S` is private
LL | S::default().x;
| ^ private field
-error[E0624]: associated function `f` is private
+error[E0624]: method `f` is private
--> $DIR/test.rs:32:18
|
LL | pub(super) fn f(&self) {}
- | ---------------------- private associated function defined here
+ | ---------------------- private method defined here
...
LL | S::default().f();
- | ^ private associated function
+ | ^ private method
error[E0624]: associated function `g` is private
--> $DIR/test.rs:33:8
@@ -84,27 +84,27 @@ error[E0616]: field `z` of struct `Universe` is private
LL | let _ = u.z;
| ^ private field
-error[E0624]: associated function `g` is private
+error[E0624]: method `g` is private
--> $DIR/test.rs:45:7
|
LL | u.g();
- | ^ private associated function
+ | ^ private method
|
::: $DIR/auxiliary/pub_restricted.rs:12:5
|
LL | pub(crate) fn g(&self) {}
- | ---------------------- private associated function defined here
+ | ---------------------- private method defined here
-error[E0624]: associated function `h` is private
+error[E0624]: method `h` is private
--> $DIR/test.rs:46:7
|
LL | u.h();
- | ^ private associated function
+ | ^ private method
|
::: $DIR/auxiliary/pub_restricted.rs:13:5
|
LL | pub(crate) fn h(&self) {}
- | ---------------------- private associated function defined here
+ | ---------------------- private method defined here
error: aborting due to 12 previous errors
diff --git a/tests/ui/proc-macro/allowed-signatures.rs b/tests/ui/proc-macro/allowed-signatures.rs
new file mode 100644
index 000000000..868508761
--- /dev/null
+++ b/tests/ui/proc-macro/allowed-signatures.rs
@@ -0,0 +1,26 @@
+// check-pass
+// force-host
+// no-prefer-dynamic
+
+#![crate_type = "proc-macro"]
+#![allow(private_in_public)]
+extern crate proc_macro;
+use proc_macro::TokenStream;
+
+#[proc_macro]
+pub fn foo<T>(t: T) -> TokenStream {
+ TokenStream::new()
+}
+
+trait Project {
+ type Assoc;
+}
+
+impl Project for () {
+ type Assoc = TokenStream;
+}
+
+#[proc_macro]
+pub fn uwu(_input: <() as Project>::Assoc) -> <() as Project>::Assoc {
+ TokenStream::new()
+}
diff --git a/tests/ui/proc-macro/break-token-spans.stderr b/tests/ui/proc-macro/break-token-spans.stderr
index 0a0322b8a..e69cc3b8c 100644
--- a/tests/ui/proc-macro/break-token-spans.stderr
+++ b/tests/ui/proc-macro/break-token-spans.stderr
@@ -8,7 +8,7 @@ error[E0308]: mismatched types
--> $DIR/break-token-spans.rs:14:32
|
LL | let a: Option<Option<u8>>= true;
- | ------------------ ^^^^ expected enum `Option`, found `bool`
+ | ------------------ ^^^^ expected `Option<Option<u8>>`, found `bool`
| |
| expected due to this
|
diff --git a/tests/ui/proc-macro/crt-static.rs b/tests/ui/proc-macro/crt-static.rs
index 6103acb7b..020128fa2 100644
--- a/tests/ui/proc-macro/crt-static.rs
+++ b/tests/ui/proc-macro/crt-static.rs
@@ -5,6 +5,9 @@
// ignore-wasm32
// ignore-sgx no support for proc-macro crate type
// build-pass
+// force-host
+// no-prefer-dynamic
+
#![crate_type = "proc-macro"]
// FIXME: This don't work when crate-type is specified by attribute
diff --git a/tests/ui/proc-macro/issue-37788.stderr b/tests/ui/proc-macro/issue-37788.stderr
index 345520d48..e437bb90b 100644
--- a/tests/ui/proc-macro/issue-37788.stderr
+++ b/tests/ui/proc-macro/issue-37788.stderr
@@ -7,7 +7,7 @@ LL | // Test that constructing the `visible_parent_map` (in `cstore_impl.rs`
LL | std::cell::Cell::new(0)
| ^^^^^^^^^^^^^^^^^^^^^^^- help: consider using a semicolon here: `;`
| |
- | expected `()`, found struct `Cell`
+ | expected `()`, found `Cell<{integer}>`
|
= note: expected unit type `()`
found struct `Cell<{integer}>`
diff --git a/tests/ui/proc-macro/proc-macro-abi.rs b/tests/ui/proc-macro/proc-macro-abi.rs
new file mode 100644
index 000000000..873660a5b
--- /dev/null
+++ b/tests/ui/proc-macro/proc-macro-abi.rs
@@ -0,0 +1,31 @@
+// force-host
+// no-prefer-dynamic
+
+#![crate_type = "proc-macro"]
+#![allow(warnings)]
+
+extern crate proc_macro;
+use proc_macro::TokenStream;
+
+#[proc_macro]
+pub extern "C" fn abi(a: TokenStream) -> TokenStream {
+ //~^ ERROR proc macro functions may not be `extern "C"`
+ a
+}
+
+#[proc_macro]
+pub extern "system" fn abi2(a: TokenStream) -> TokenStream {
+ //~^ ERROR proc macro functions may not be `extern "system"`
+ a
+}
+
+#[proc_macro]
+pub extern fn abi3(a: TokenStream) -> TokenStream {
+ //~^ ERROR proc macro functions may not be `extern "C"`
+ a
+}
+
+#[proc_macro]
+pub extern "Rust" fn abi4(a: TokenStream) -> TokenStream {
+ a
+}
diff --git a/tests/ui/proc-macro/proc-macro-abi.stderr b/tests/ui/proc-macro/proc-macro-abi.stderr
new file mode 100644
index 000000000..9a781be09
--- /dev/null
+++ b/tests/ui/proc-macro/proc-macro-abi.stderr
@@ -0,0 +1,20 @@
+error: proc macro functions may not be `extern "C"`
+ --> $DIR/proc-macro-abi.rs:11:1
+ |
+LL | pub extern "C" fn abi(a: TokenStream) -> TokenStream {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: proc macro functions may not be `extern "system"`
+ --> $DIR/proc-macro-abi.rs:17:1
+ |
+LL | pub extern "system" fn abi2(a: TokenStream) -> TokenStream {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: proc macro functions may not be `extern "C"`
+ --> $DIR/proc-macro-abi.rs:23:1
+ |
+LL | pub extern fn abi3(a: TokenStream) -> TokenStream {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 3 previous errors
+
diff --git a/tests/ui/proc-macro/resolved-located-at.stderr b/tests/ui/proc-macro/resolved-located-at.stderr
index 422820e9d..0b4dbcba6 100644
--- a/tests/ui/proc-macro/resolved-located-at.stderr
+++ b/tests/ui/proc-macro/resolved-located-at.stderr
@@ -12,7 +12,7 @@ error[E0308]: mismatched types
LL | fn main() {
| - expected `()` because of default return type
LL | resolve_located_at!(a b)
- | ^ expected `()`, found struct `S`
+ | ^ expected `()`, found `S`
|
= note: this error originates in the macro `resolve_located_at` (in Nightly builds, run with -Z macro-backtrace for more info)
diff --git a/tests/ui/proc-macro/signature-proc-macro-attribute.rs b/tests/ui/proc-macro/signature-proc-macro-attribute.rs
new file mode 100644
index 000000000..51abc8e7d
--- /dev/null
+++ b/tests/ui/proc-macro/signature-proc-macro-attribute.rs
@@ -0,0 +1,32 @@
+// force-host
+// no-prefer-dynamic
+
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+use proc_macro::TokenStream;
+
+#[proc_macro_attribute]
+pub fn bad_input(input: String) -> TokenStream {
+ //~^ ERROR mismatched attribute proc macro signature
+ ::proc_macro::TokenStream::new()
+}
+
+#[proc_macro_attribute]
+pub fn bad_output(input: TokenStream) -> String {
+ //~^ ERROR mismatched attribute proc macro signature
+ //~| ERROR mismatched attribute proc macro signature
+ String::from("blah")
+}
+
+#[proc_macro_attribute]
+pub fn bad_everything(input: String) -> String {
+ //~^ ERROR mismatched attribute proc macro signature
+ //~| ERROR mismatched attribute proc macro signature
+ input
+}
+
+#[proc_macro_attribute]
+pub fn too_many(a: TokenStream, b: TokenStream, c: String) -> TokenStream {
+ //~^ ERROR mismatched attribute proc macro signature
+}
diff --git a/tests/ui/proc-macro/signature-proc-macro-attribute.stderr b/tests/ui/proc-macro/signature-proc-macro-attribute.stderr
new file mode 100644
index 000000000..abf7a6f3c
--- /dev/null
+++ b/tests/ui/proc-macro/signature-proc-macro-attribute.stderr
@@ -0,0 +1,42 @@
+error: mismatched attribute proc macro signature
+ --> $DIR/signature-proc-macro-attribute.rs:10:1
+ |
+LL | pub fn bad_input(input: String) -> TokenStream {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ attribute proc macro must have two arguments of type `proc_macro::TokenStream`
+
+error: mismatched attribute proc macro signature
+ --> $DIR/signature-proc-macro-attribute.rs:16:42
+ |
+LL | pub fn bad_output(input: TokenStream) -> String {
+ | ^^^^^^ found std::string::String, expected type `proc_macro::TokenStream`
+ |
+ = note: attribute proc macros must have a signature of `fn(TokenStream, TokenStream) -> TokenStream`
+
+error: mismatched attribute proc macro signature
+ --> $DIR/signature-proc-macro-attribute.rs:16:1
+ |
+LL | pub fn bad_output(input: TokenStream) -> String {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ attribute proc macro must have two arguments of type `proc_macro::TokenStream`
+
+error: mismatched attribute proc macro signature
+ --> $DIR/signature-proc-macro-attribute.rs:23:41
+ |
+LL | pub fn bad_everything(input: String) -> String {
+ | ^^^^^^ found std::string::String, expected type `proc_macro::TokenStream`
+ |
+ = note: attribute proc macros must have a signature of `fn(TokenStream, TokenStream) -> TokenStream`
+
+error: mismatched attribute proc macro signature
+ --> $DIR/signature-proc-macro-attribute.rs:23:1
+ |
+LL | pub fn bad_everything(input: String) -> String {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ attribute proc macro must have two arguments of type `proc_macro::TokenStream`
+
+error: mismatched attribute proc macro signature
+ --> $DIR/signature-proc-macro-attribute.rs:30:49
+ |
+LL | pub fn too_many(a: TokenStream, b: TokenStream, c: String) -> TokenStream {
+ | ^^^^^^^^^ found unexpected argument
+
+error: aborting due to 6 previous errors
+
diff --git a/tests/ui/proc-macro/signature-proc-macro-derive.rs b/tests/ui/proc-macro/signature-proc-macro-derive.rs
new file mode 100644
index 000000000..f2fd824b6
--- /dev/null
+++ b/tests/ui/proc-macro/signature-proc-macro-derive.rs
@@ -0,0 +1,31 @@
+// force-host
+// no-prefer-dynamic
+
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+use proc_macro::TokenStream;
+
+#[proc_macro_derive(Blah)]
+pub fn bad_input(input: String) -> TokenStream {
+ //~^ ERROR mismatched derive proc macro signature
+ TokenStream::new()
+}
+
+#[proc_macro_derive(Bleh)]
+pub fn bad_output(input: TokenStream) -> String {
+ //~^ ERROR mismatched derive proc macro signature
+ String::from("blah")
+}
+
+#[proc_macro_derive(Bluh)]
+pub fn bad_everything(input: String) -> String {
+ //~^ ERROR mismatched derive proc macro signature
+ //~| ERROR mismatched derive proc macro signature
+ input
+}
+
+#[proc_macro_derive(Blih)]
+pub fn too_many(a: TokenStream, b: TokenStream, c: String) -> TokenStream {
+ //~^ ERROR mismatched derive proc macro signature
+}
diff --git a/tests/ui/proc-macro/signature-proc-macro-derive.stderr b/tests/ui/proc-macro/signature-proc-macro-derive.stderr
new file mode 100644
index 000000000..a358ae277
--- /dev/null
+++ b/tests/ui/proc-macro/signature-proc-macro-derive.stderr
@@ -0,0 +1,40 @@
+error: mismatched derive proc macro signature
+ --> $DIR/signature-proc-macro-derive.rs:10:25
+ |
+LL | pub fn bad_input(input: String) -> TokenStream {
+ | ^^^^^^ found std::string::String, expected type `proc_macro::TokenStream`
+ |
+ = note: derive proc macros must have a signature of `fn(TokenStream) -> TokenStream`
+
+error: mismatched derive proc macro signature
+ --> $DIR/signature-proc-macro-derive.rs:16:42
+ |
+LL | pub fn bad_output(input: TokenStream) -> String {
+ | ^^^^^^ found std::string::String, expected type `proc_macro::TokenStream`
+ |
+ = note: derive proc macros must have a signature of `fn(TokenStream) -> TokenStream`
+
+error: mismatched derive proc macro signature
+ --> $DIR/signature-proc-macro-derive.rs:22:41
+ |
+LL | pub fn bad_everything(input: String) -> String {
+ | ^^^^^^ found std::string::String, expected type `proc_macro::TokenStream`
+ |
+ = note: derive proc macros must have a signature of `fn(TokenStream) -> TokenStream`
+
+error: mismatched derive proc macro signature
+ --> $DIR/signature-proc-macro-derive.rs:22:30
+ |
+LL | pub fn bad_everything(input: String) -> String {
+ | ^^^^^^ found std::string::String, expected type `proc_macro::TokenStream`
+ |
+ = note: derive proc macros must have a signature of `fn(TokenStream) -> TokenStream`
+
+error: mismatched derive proc macro signature
+ --> $DIR/signature-proc-macro-derive.rs:29:33
+ |
+LL | pub fn too_many(a: TokenStream, b: TokenStream, c: String) -> TokenStream {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^ found unexpected arguments
+
+error: aborting due to 5 previous errors
+
diff --git a/tests/ui/proc-macro/signature-proc-macro.rs b/tests/ui/proc-macro/signature-proc-macro.rs
new file mode 100644
index 000000000..54770aacd
--- /dev/null
+++ b/tests/ui/proc-macro/signature-proc-macro.rs
@@ -0,0 +1,31 @@
+// force-host
+// no-prefer-dynamic
+
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+use proc_macro::TokenStream;
+
+#[proc_macro]
+pub fn bad_input(input: String) -> TokenStream {
+ //~^ ERROR mismatched function-like proc macro signature
+ ::proc_macro::TokenStream::new()
+}
+
+#[proc_macro]
+pub fn bad_output(input: TokenStream) -> String {
+ //~^ ERROR mismatched function-like proc macro signature
+ String::from("blah")
+}
+
+#[proc_macro]
+pub fn bad_everything(input: String) -> String {
+ //~^ ERROR mismatched function-like proc macro signature
+ //~| ERROR mismatched function-like proc macro signature
+ input
+}
+
+#[proc_macro]
+pub fn too_many(a: TokenStream, b: TokenStream, c: String) -> TokenStream {
+ //~^ ERROR mismatched function-like proc macro signature
+}
diff --git a/tests/ui/proc-macro/signature-proc-macro.stderr b/tests/ui/proc-macro/signature-proc-macro.stderr
new file mode 100644
index 000000000..4b14a54e6
--- /dev/null
+++ b/tests/ui/proc-macro/signature-proc-macro.stderr
@@ -0,0 +1,40 @@
+error: mismatched function-like proc macro signature
+ --> $DIR/signature-proc-macro.rs:10:25
+ |
+LL | pub fn bad_input(input: String) -> TokenStream {
+ | ^^^^^^ found std::string::String, expected type `proc_macro::TokenStream`
+ |
+ = note: function-like proc macros must have a signature of `fn(TokenStream) -> TokenStream`
+
+error: mismatched function-like proc macro signature
+ --> $DIR/signature-proc-macro.rs:16:42
+ |
+LL | pub fn bad_output(input: TokenStream) -> String {
+ | ^^^^^^ found std::string::String, expected type `proc_macro::TokenStream`
+ |
+ = note: function-like proc macros must have a signature of `fn(TokenStream) -> TokenStream`
+
+error: mismatched function-like proc macro signature
+ --> $DIR/signature-proc-macro.rs:22:41
+ |
+LL | pub fn bad_everything(input: String) -> String {
+ | ^^^^^^ found std::string::String, expected type `proc_macro::TokenStream`
+ |
+ = note: function-like proc macros must have a signature of `fn(TokenStream) -> TokenStream`
+
+error: mismatched function-like proc macro signature
+ --> $DIR/signature-proc-macro.rs:22:30
+ |
+LL | pub fn bad_everything(input: String) -> String {
+ | ^^^^^^ found std::string::String, expected type `proc_macro::TokenStream`
+ |
+ = note: function-like proc macros must have a signature of `fn(TokenStream) -> TokenStream`
+
+error: mismatched function-like proc macro signature
+ --> $DIR/signature-proc-macro.rs:29:33
+ |
+LL | pub fn too_many(a: TokenStream, b: TokenStream, c: String) -> TokenStream {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^ found unexpected arguments
+
+error: aborting due to 5 previous errors
+
diff --git a/tests/ui/proc-macro/signature.rs b/tests/ui/proc-macro/signature.rs
index 230223825..11187aa31 100644
--- a/tests/ui/proc-macro/signature.rs
+++ b/tests/ui/proc-macro/signature.rs
@@ -8,6 +8,10 @@ extern crate proc_macro;
#[proc_macro_derive(A)]
pub unsafe extern "C" fn foo(a: i32, b: u32) -> u32 {
- //~^ ERROR: expected a `Fn<(proc_macro::TokenStream,)>` closure, found `unsafe extern "C" fn
+ //~^ ERROR: mismatched derive proc macro signature
+ //~| mismatched derive proc macro signature
+ //~| mismatched derive proc macro signature
+ //~| proc macro functions may not be `extern
+ //~| proc macro functions may not be `unsafe
loop {}
}
diff --git a/tests/ui/proc-macro/signature.stderr b/tests/ui/proc-macro/signature.stderr
index 79f2001da..3dbe3f22a 100644
--- a/tests/ui/proc-macro/signature.stderr
+++ b/tests/ui/proc-macro/signature.stderr
@@ -1,20 +1,36 @@
-error[E0277]: expected a `Fn<(proc_macro::TokenStream,)>` closure, found `unsafe extern "C" fn(i32, u32) -> u32 {foo}`
+error: proc macro functions may not be `extern "C"`
--> $DIR/signature.rs:10:1
|
-LL | / pub unsafe extern "C" fn foo(a: i32, b: u32) -> u32 {
-LL | |
-LL | | loop {}
-LL | | }
- | | ^
- | | |
- | |_call the function in a closure: `|| unsafe { /* code */ }`
- | required by a bound introduced by this call
+LL | pub unsafe extern "C" fn foo(a: i32, b: u32) -> u32 {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: proc macro functions may not be `unsafe`
+ --> $DIR/signature.rs:10:1
+ |
+LL | pub unsafe extern "C" fn foo(a: i32, b: u32) -> u32 {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: mismatched derive proc macro signature
+ --> $DIR/signature.rs:10:49
+ |
+LL | pub unsafe extern "C" fn foo(a: i32, b: u32) -> u32 {
+ | ^^^ found u32, expected type `proc_macro::TokenStream`
+ |
+ = note: derive proc macros must have a signature of `fn(TokenStream) -> TokenStream`
+
+error: mismatched derive proc macro signature
+ --> $DIR/signature.rs:10:33
+ |
+LL | pub unsafe extern "C" fn foo(a: i32, b: u32) -> u32 {
+ | ^^^ found i32, expected type `proc_macro::TokenStream`
+ |
+ = note: derive proc macros must have a signature of `fn(TokenStream) -> TokenStream`
+
+error: mismatched derive proc macro signature
+ --> $DIR/signature.rs:10:38
|
- = help: the trait `Fn<(proc_macro::TokenStream,)>` is not implemented for fn item `unsafe extern "C" fn(i32, u32) -> u32 {foo}`
- = note: unsafe function cannot be called generically without an unsafe block
-note: required by a bound in `ProcMacro::custom_derive`
- --> $SRC_DIR/proc_macro/src/bridge/client.rs:LL:COL
+LL | pub unsafe extern "C" fn foo(a: i32, b: u32) -> u32 {
+ | ^^^^^^ found unexpected argument
-error: aborting due to previous error
+error: aborting due to 5 previous errors
-For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/process/process-sigpipe.rs b/tests/ui/process/process-sigpipe.rs
index 107eba45d..7ae14c6b8 100644
--- a/tests/ui/process/process-sigpipe.rs
+++ b/tests/ui/process/process-sigpipe.rs
@@ -15,6 +15,7 @@
// ignore-emscripten no threads support
// ignore-vxworks no 'sh'
// ignore-fuchsia no 'sh'
+// ignore-nto no 'yes'
use std::process;
use std::thread;
diff --git a/tests/ui/pub/pub-ident-fn-3.rs b/tests/ui/pub/pub-ident-fn-3.rs
deleted file mode 100644
index fdbea7cf4..000000000
--- a/tests/ui/pub/pub-ident-fn-3.rs
+++ /dev/null
@@ -1,8 +0,0 @@
-// #60115
-
-mod foo {
- pub bar();
- //~^ ERROR missing `fn` or `struct` for function or struct definition
-}
-
-fn main() {}
diff --git a/tests/ui/pub/pub-ident-fn-3.stderr b/tests/ui/pub/pub-ident-fn-3.stderr
deleted file mode 100644
index 6d3d4e592..000000000
--- a/tests/ui/pub/pub-ident-fn-3.stderr
+++ /dev/null
@@ -1,8 +0,0 @@
-error: missing `fn` or `struct` for function or struct definition
- --> $DIR/pub-ident-fn-3.rs:4:8
- |
-LL | pub bar();
- | ---^--- help: if you meant to call a macro, try: `bar!`
-
-error: aborting due to previous error
-
diff --git a/tests/ui/pub/pub-ident-fn-or-struct-2.rs b/tests/ui/pub/pub-ident-fn-or-struct-2.rs
deleted file mode 100644
index 8f67cdd29..000000000
--- a/tests/ui/pub/pub-ident-fn-or-struct-2.rs
+++ /dev/null
@@ -1,4 +0,0 @@
-pub S();
-//~^ ERROR missing `fn` or `struct` for function or struct definition
-
-fn main() {}
diff --git a/tests/ui/pub/pub-ident-fn-or-struct-2.stderr b/tests/ui/pub/pub-ident-fn-or-struct-2.stderr
deleted file mode 100644
index 047e66b18..000000000
--- a/tests/ui/pub/pub-ident-fn-or-struct-2.stderr
+++ /dev/null
@@ -1,8 +0,0 @@
-error: missing `fn` or `struct` for function or struct definition
- --> $DIR/pub-ident-fn-or-struct-2.rs:1:4
- |
-LL | pub S();
- | ---^- help: if you meant to call a macro, try: `S!`
-
-error: aborting due to previous error
-
diff --git a/tests/ui/pub/pub-ident-struct-2.rs b/tests/ui/pub/pub-ident-struct-2.rs
new file mode 100644
index 000000000..50db4039d
--- /dev/null
+++ b/tests/ui/pub/pub-ident-struct-2.rs
@@ -0,0 +1,8 @@
+// #60115
+
+mod foo {
+ pub bar();
+ //~^ ERROR missing `struct` for struct definition
+}
+
+fn main() {}
diff --git a/tests/ui/pub/pub-ident-struct-2.stderr b/tests/ui/pub/pub-ident-struct-2.stderr
new file mode 100644
index 000000000..6969a376a
--- /dev/null
+++ b/tests/ui/pub/pub-ident-struct-2.stderr
@@ -0,0 +1,13 @@
+error: missing `struct` for struct definition
+ --> $DIR/pub-ident-struct-2.rs:4:8
+ |
+LL | pub bar();
+ | ^
+ |
+help: add `struct` here to parse `bar` as a public struct
+ |
+LL | pub struct bar();
+ | ++++++
+
+error: aborting due to previous error
+
diff --git a/tests/ui/pub/pub-ident-struct-3.rs b/tests/ui/pub/pub-ident-struct-3.rs
new file mode 100644
index 000000000..dfa6cf2ee
--- /dev/null
+++ b/tests/ui/pub/pub-ident-struct-3.rs
@@ -0,0 +1,4 @@
+pub S();
+//~^ ERROR missing `struct` for struct definition
+
+fn main() {}
diff --git a/tests/ui/pub/pub-ident-struct-3.stderr b/tests/ui/pub/pub-ident-struct-3.stderr
new file mode 100644
index 000000000..d94198a6b
--- /dev/null
+++ b/tests/ui/pub/pub-ident-struct-3.stderr
@@ -0,0 +1,13 @@
+error: missing `struct` for struct definition
+ --> $DIR/pub-ident-struct-3.rs:1:4
+ |
+LL | pub S();
+ | ^
+ |
+help: add `struct` here to parse `S` as a public struct
+ |
+LL | pub struct S();
+ | ++++++
+
+error: aborting due to previous error
+
diff --git a/tests/ui/pub/pub-ident-struct-4.fixed b/tests/ui/pub/pub-ident-struct-4.fixed
new file mode 100644
index 000000000..b49fa678e
--- /dev/null
+++ b/tests/ui/pub/pub-ident-struct-4.fixed
@@ -0,0 +1,6 @@
+// run-rustfix
+
+pub struct T(String);
+//~^ ERROR missing `struct` for struct definition
+
+fn main() {}
diff --git a/tests/ui/pub/pub-ident-struct-4.rs b/tests/ui/pub/pub-ident-struct-4.rs
new file mode 100644
index 000000000..20bc94b0a
--- /dev/null
+++ b/tests/ui/pub/pub-ident-struct-4.rs
@@ -0,0 +1,6 @@
+// run-rustfix
+
+pub T(String);
+//~^ ERROR missing `struct` for struct definition
+
+fn main() {}
diff --git a/tests/ui/pub/pub-ident-struct-4.stderr b/tests/ui/pub/pub-ident-struct-4.stderr
new file mode 100644
index 000000000..90c7138e5
--- /dev/null
+++ b/tests/ui/pub/pub-ident-struct-4.stderr
@@ -0,0 +1,13 @@
+error: missing `struct` for struct definition
+ --> $DIR/pub-ident-struct-4.rs:3:4
+ |
+LL | pub T(String);
+ | ^
+ |
+help: add `struct` here to parse `T` as a public struct
+ |
+LL | pub struct T(String);
+ | ++++++
+
+error: aborting due to previous error
+
diff --git a/tests/ui/query-system/no-query-in-printing-during-query-descr.rs b/tests/ui/query-system/no-query-in-printing-during-query-descr.rs
new file mode 100644
index 000000000..45b7043e2
--- /dev/null
+++ b/tests/ui/query-system/no-query-in-printing-during-query-descr.rs
@@ -0,0 +1,6 @@
+fn a() -> _ {
+ //~^ ERROR the placeholder `_` is not allowed within types on item signatures for return types
+ &a
+}
+
+fn main() {}
diff --git a/tests/ui/query-system/no-query-in-printing-during-query-descr.stderr b/tests/ui/query-system/no-query-in-printing-during-query-descr.stderr
new file mode 100644
index 000000000..35e608b6b
--- /dev/null
+++ b/tests/ui/query-system/no-query-in-printing-during-query-descr.stderr
@@ -0,0 +1,9 @@
+error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types
+ --> $DIR/no-query-in-printing-during-query-descr.rs:1:11
+ |
+LL | fn a() -> _ {
+ | ^ not allowed in type signatures
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0121`.
diff --git a/tests/ui/range/issue-54505-no-literals.stderr b/tests/ui/range/issue-54505-no-literals.stderr
index 070dc8445..d11298384 100644
--- a/tests/ui/range/issue-54505-no-literals.stderr
+++ b/tests/ui/range/issue-54505-no-literals.stderr
@@ -4,7 +4,7 @@ error[E0308]: mismatched types
LL | take_range(std::ops::Range { start: 0, end: 1 });
| ---------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| | |
- | | expected reference, found struct `Range`
+ | | expected `&_`, found `Range<{integer}>`
| | help: consider borrowing here: `&std::ops::Range { start: 0, end: 1 }`
| arguments to this function are incorrect
|
@@ -22,7 +22,7 @@ error[E0308]: mismatched types
LL | take_range(::std::ops::Range { start: 0, end: 1 });
| ---------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| | |
- | | expected reference, found struct `Range`
+ | | expected `&_`, found `Range<{integer}>`
| | help: consider borrowing here: `&::std::ops::Range { start: 0, end: 1 }`
| arguments to this function are incorrect
|
@@ -40,7 +40,7 @@ error[E0308]: mismatched types
LL | take_range(std::ops::RangeFrom { start: 1 });
| ---------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| | |
- | | expected reference, found struct `RangeFrom`
+ | | expected `&_`, found `RangeFrom<{integer}>`
| | help: consider borrowing here: `&std::ops::RangeFrom { start: 1 }`
| arguments to this function are incorrect
|
@@ -58,7 +58,7 @@ error[E0308]: mismatched types
LL | take_range(::std::ops::RangeFrom { start: 1 });
| ---------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| | |
- | | expected reference, found struct `RangeFrom`
+ | | expected `&_`, found `RangeFrom<{integer}>`
| | help: consider borrowing here: `&::std::ops::RangeFrom { start: 1 }`
| arguments to this function are incorrect
|
@@ -76,7 +76,7 @@ error[E0308]: mismatched types
LL | take_range(std::ops::RangeFull {});
| ---------- ^^^^^^^^^^^^^^^^^^^^^^
| | |
- | | expected reference, found struct `RangeFull`
+ | | expected `&_`, found `RangeFull`
| | help: consider borrowing here: `&std::ops::RangeFull {}`
| arguments to this function are incorrect
|
@@ -94,7 +94,7 @@ error[E0308]: mismatched types
LL | take_range(::std::ops::RangeFull {});
| ---------- ^^^^^^^^^^^^^^^^^^^^^^^^
| | |
- | | expected reference, found struct `RangeFull`
+ | | expected `&_`, found `RangeFull`
| | help: consider borrowing here: `&::std::ops::RangeFull {}`
| arguments to this function are incorrect
|
@@ -112,7 +112,7 @@ error[E0308]: mismatched types
LL | take_range(std::ops::RangeInclusive::new(0, 1));
| ---------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| | |
- | | expected reference, found struct `RangeInclusive`
+ | | expected `&_`, found `RangeInclusive<{integer}>`
| | help: consider borrowing here: `&std::ops::RangeInclusive::new(0, 1)`
| arguments to this function are incorrect
|
@@ -130,7 +130,7 @@ error[E0308]: mismatched types
LL | take_range(::std::ops::RangeInclusive::new(0, 1));
| ---------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| | |
- | | expected reference, found struct `RangeInclusive`
+ | | expected `&_`, found `RangeInclusive<{integer}>`
| | help: consider borrowing here: `&::std::ops::RangeInclusive::new(0, 1)`
| arguments to this function are incorrect
|
@@ -148,7 +148,7 @@ error[E0308]: mismatched types
LL | take_range(std::ops::RangeTo { end: 5 });
| ---------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| | |
- | | expected reference, found struct `RangeTo`
+ | | expected `&_`, found `RangeTo<{integer}>`
| | help: consider borrowing here: `&std::ops::RangeTo { end: 5 }`
| arguments to this function are incorrect
|
@@ -166,7 +166,7 @@ error[E0308]: mismatched types
LL | take_range(::std::ops::RangeTo { end: 5 });
| ---------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| | |
- | | expected reference, found struct `RangeTo`
+ | | expected `&_`, found `RangeTo<{integer}>`
| | help: consider borrowing here: `&::std::ops::RangeTo { end: 5 }`
| arguments to this function are incorrect
|
@@ -184,7 +184,7 @@ error[E0308]: mismatched types
LL | take_range(std::ops::RangeToInclusive { end: 5 });
| ---------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| | |
- | | expected reference, found struct `RangeToInclusive`
+ | | expected `&_`, found `RangeToInclusive<{integer}>`
| | help: consider borrowing here: `&std::ops::RangeToInclusive { end: 5 }`
| arguments to this function are incorrect
|
@@ -202,7 +202,7 @@ error[E0308]: mismatched types
LL | take_range(::std::ops::RangeToInclusive { end: 5 });
| ---------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| | |
- | | expected reference, found struct `RangeToInclusive`
+ | | expected `&_`, found `RangeToInclusive<{integer}>`
| | help: consider borrowing here: `&::std::ops::RangeToInclusive { end: 5 }`
| arguments to this function are incorrect
|
diff --git a/tests/ui/range/issue-54505-no-std.stderr b/tests/ui/range/issue-54505-no-std.stderr
index 9fb0e54a8..a6a9f89da 100644
--- a/tests/ui/range/issue-54505-no-std.stderr
+++ b/tests/ui/range/issue-54505-no-std.stderr
@@ -16,7 +16,7 @@ error[E0308]: mismatched types
LL | take_range(0..1);
| ---------- ^^^^
| | |
- | | expected reference, found struct `Range`
+ | | expected `&_`, found `Range<{integer}>`
| | help: consider borrowing here: `&(0..1)`
| arguments to this function are incorrect
|
@@ -34,7 +34,7 @@ error[E0308]: mismatched types
LL | take_range(1..);
| ---------- ^^^
| | |
- | | expected reference, found struct `RangeFrom`
+ | | expected `&_`, found `RangeFrom<{integer}>`
| | help: consider borrowing here: `&(1..)`
| arguments to this function are incorrect
|
@@ -52,7 +52,7 @@ error[E0308]: mismatched types
LL | take_range(..);
| ---------- ^^
| | |
- | | expected reference, found struct `RangeFull`
+ | | expected `&_`, found `RangeFull`
| | help: consider borrowing here: `&(..)`
| arguments to this function are incorrect
|
@@ -70,7 +70,7 @@ error[E0308]: mismatched types
LL | take_range(0..=1);
| ---------- ^^^^^
| | |
- | | expected reference, found struct `RangeInclusive`
+ | | expected `&_`, found `RangeInclusive<{integer}>`
| | help: consider borrowing here: `&(0..=1)`
| arguments to this function are incorrect
|
@@ -88,7 +88,7 @@ error[E0308]: mismatched types
LL | take_range(..5);
| ---------- ^^^
| | |
- | | expected reference, found struct `RangeTo`
+ | | expected `&_`, found `RangeTo<{integer}>`
| | help: consider borrowing here: `&(..5)`
| arguments to this function are incorrect
|
@@ -106,7 +106,7 @@ error[E0308]: mismatched types
LL | take_range(..=42);
| ---------- ^^^^^
| | |
- | | expected reference, found struct `RangeToInclusive`
+ | | expected `&_`, found `RangeToInclusive<{integer}>`
| | help: consider borrowing here: `&(..=42)`
| arguments to this function are incorrect
|
diff --git a/tests/ui/range/issue-54505.stderr b/tests/ui/range/issue-54505.stderr
index 9eec16940..eda047b50 100644
--- a/tests/ui/range/issue-54505.stderr
+++ b/tests/ui/range/issue-54505.stderr
@@ -4,7 +4,7 @@ error[E0308]: mismatched types
LL | take_range(0..1);
| ---------- ^^^^
| | |
- | | expected reference, found struct `Range`
+ | | expected `&_`, found `Range<{integer}>`
| | help: consider borrowing here: `&(0..1)`
| arguments to this function are incorrect
|
@@ -22,7 +22,7 @@ error[E0308]: mismatched types
LL | take_range(1..);
| ---------- ^^^
| | |
- | | expected reference, found struct `RangeFrom`
+ | | expected `&_`, found `RangeFrom<{integer}>`
| | help: consider borrowing here: `&(1..)`
| arguments to this function are incorrect
|
@@ -40,7 +40,7 @@ error[E0308]: mismatched types
LL | take_range(..);
| ---------- ^^
| | |
- | | expected reference, found struct `RangeFull`
+ | | expected `&_`, found `RangeFull`
| | help: consider borrowing here: `&(..)`
| arguments to this function are incorrect
|
@@ -58,7 +58,7 @@ error[E0308]: mismatched types
LL | take_range(0..=1);
| ---------- ^^^^^
| | |
- | | expected reference, found struct `RangeInclusive`
+ | | expected `&_`, found `RangeInclusive<{integer}>`
| | help: consider borrowing here: `&(0..=1)`
| arguments to this function are incorrect
|
@@ -76,7 +76,7 @@ error[E0308]: mismatched types
LL | take_range(..5);
| ---------- ^^^
| | |
- | | expected reference, found struct `RangeTo`
+ | | expected `&_`, found `RangeTo<{integer}>`
| | help: consider borrowing here: `&(..5)`
| arguments to this function are incorrect
|
@@ -94,7 +94,7 @@ error[E0308]: mismatched types
LL | take_range(..=42);
| ---------- ^^^^^
| | |
- | | expected reference, found struct `RangeToInclusive`
+ | | expected `&_`, found `RangeToInclusive<{integer}>`
| | help: consider borrowing here: `&(..=42)`
| arguments to this function are incorrect
|
diff --git a/tests/ui/range/issue-73553-misinterp-range-literal.stderr b/tests/ui/range/issue-73553-misinterp-range-literal.stderr
index d08d9b134..77595b367 100644
--- a/tests/ui/range/issue-73553-misinterp-range-literal.stderr
+++ b/tests/ui/range/issue-73553-misinterp-range-literal.stderr
@@ -4,7 +4,7 @@ error[E0308]: mismatched types
LL | demo(tell(1)..tell(10));
| ---- ^^^^^^^^^^^^^^^^^
| | |
- | | expected `&Range<usize>`, found struct `Range`
+ | | expected `&Range<usize>`, found `Range<usize>`
| | help: consider borrowing here: `&(tell(1)..tell(10))`
| arguments to this function are incorrect
|
@@ -22,7 +22,7 @@ error[E0308]: mismatched types
LL | demo(1..10);
| ---- ^^^^^
| | |
- | | expected `&Range<usize>`, found struct `Range`
+ | | expected `&Range<usize>`, found `Range<{integer}>`
| | help: consider borrowing here: `&(1..10)`
| arguments to this function are incorrect
|
diff --git a/tests/ui/recursion/issue-83150.stderr b/tests/ui/recursion/issue-83150.stderr
index dde8ad1b6..64683ae3a 100644
--- a/tests/ui/recursion/issue-83150.stderr
+++ b/tests/ui/recursion/issue-83150.stderr
@@ -9,9 +9,11 @@ LL | func(&mut iter.map(|x| x + 1))
= help: a `loop` may express intention better if this is on purpose
= note: `#[warn(unconditional_recursion)]` on by default
-error[E0275]: overflow evaluating the requirement `Map<&mut Map<&mut Map<&mut Map<..., ...>, ...>, ...>, ...>: Iterator`
+error[E0275]: overflow evaluating the requirement `Map<&mut std::ops::Range<u8>, [closure@$DIR/issue-83150.rs:12:24: 12:27]>: Iterator`
|
= help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`issue_83150`)
+ = note: required for `&mut Map<&mut std::ops::Range<u8>, [closure@$DIR/issue-83150.rs:12:24: 12:27]>` to implement `Iterator`
+ = note: 65 redundant requirements hidden
= note: required for `&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<..., ...>, ...>, ...>, ...>, ...>, ...>, ...>` to implement `Iterator`
= note: the full type name has been written to '$TEST_BUILD_DIR/recursion/issue-83150/issue-83150.long-type-hash.txt'
diff --git a/tests/ui/recursion_limit/issue-105700.rs b/tests/ui/recursion_limit/issue-105700.rs
new file mode 100644
index 000000000..e1fee4631
--- /dev/null
+++ b/tests/ui/recursion_limit/issue-105700.rs
@@ -0,0 +1,9 @@
+#![recursion_limit="4"]
+#![invalid_attribute]
+#![invalid_attribute]
+#![invalid_attribute]
+#![invalid_attribute]
+#![invalid_attribute]
+//~^ERROR recursion limit reached while expanding
+
+fn main() {}
diff --git a/tests/ui/recursion_limit/issue-105700.stderr b/tests/ui/recursion_limit/issue-105700.stderr
new file mode 100644
index 000000000..9b1114e9c
--- /dev/null
+++ b/tests/ui/recursion_limit/issue-105700.stderr
@@ -0,0 +1,10 @@
+error: recursion limit reached while expanding `#[invalid_attribute]`
+ --> $DIR/issue-105700.rs:6:1
+ |
+LL | #![invalid_attribute]
+ | ^^^^^^^^^^^^^^^^^^^^^
+ |
+ = help: consider increasing the recursion limit by adding a `#![recursion_limit = "8"]` attribute to your crate (`issue_105700`)
+
+error: aborting due to previous error
+
diff --git a/tests/ui/issues/issue-40003.rs b/tests/ui/recursion_limit/issue-40003.rs
index 5e61361f9..5e61361f9 100644
--- a/tests/ui/issues/issue-40003.rs
+++ b/tests/ui/recursion_limit/issue-40003.rs
diff --git a/tests/ui/regions/do-not-suggest-adding-bound-to-opaque-type.stderr b/tests/ui/regions/do-not-suggest-adding-bound-to-opaque-type.stderr
index 6ea238f30..d76a83b02 100644
--- a/tests/ui/regions/do-not-suggest-adding-bound-to-opaque-type.stderr
+++ b/tests/ui/regions/do-not-suggest-adding-bound-to-opaque-type.stderr
@@ -1,6 +1,8 @@
error[E0597]: `x` does not live long enough
--> $DIR/do-not-suggest-adding-bound-to-opaque-type.rs:9:7
|
+LL | let x = ();
+ | - binding `x` declared here
LL | S(&x)
| --^^-
| | |
diff --git a/tests/ui/regions/higher-ranked-implied.rs b/tests/ui/regions/higher-ranked-implied.rs
new file mode 100644
index 000000000..103884c50
--- /dev/null
+++ b/tests/ui/regions/higher-ranked-implied.rs
@@ -0,0 +1,14 @@
+// FIXME: This test should pass as the first two fields add implied bounds that
+// `'a` is equal to `'b` while the last one should simply use that fact. With
+// the current implementation this errors. We have to be careful as implied bounds
+// are only sound if they're also correctly checked.
+
+struct Inv<T>(*mut T); // `T` is invariant.
+type A = for<'a, 'b> fn(Inv<&'a &'b ()>, Inv<&'b &'a ()>, Inv<&'a ()>);
+type B = for<'a, 'b> fn(Inv<&'a &'b ()>, Inv<&'b &'a ()>, Inv<&'b ()>);
+
+fn main() {
+ let x: A = |_, _, _| ();
+ let y: B = x; //~ ERROR mismatched types
+ let _: A = y; //~ ERROR mismatched types
+}
diff --git a/tests/ui/regions/higher-ranked-implied.stderr b/tests/ui/regions/higher-ranked-implied.stderr
new file mode 100644
index 000000000..9d80eacd7
--- /dev/null
+++ b/tests/ui/regions/higher-ranked-implied.stderr
@@ -0,0 +1,21 @@
+error[E0308]: mismatched types
+ --> $DIR/higher-ranked-implied.rs:12:16
+ |
+LL | let y: B = x;
+ | ^ one type is more general than the other
+ |
+ = note: expected fn pointer `for<'a, 'b> fn(Inv<&'a &'b ()>, Inv<&'b &'a ()>, Inv<&'b ()>)`
+ found fn pointer `for<'a, 'b> fn(Inv<&'a &'b ()>, Inv<&'b &'a ()>, Inv<&'a ()>)`
+
+error[E0308]: mismatched types
+ --> $DIR/higher-ranked-implied.rs:13:16
+ |
+LL | let _: A = y;
+ | ^ one type is more general than the other
+ |
+ = note: expected fn pointer `for<'a, 'b> fn(Inv<&'a &'b ()>, Inv<&'b &'a ()>, Inv<&'a ()>)`
+ found fn pointer `for<'a, 'b> fn(Inv<&'a &'b ()>, Inv<&'b &'a ()>, Inv<&'b ()>)`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/regions/issue-102374.stderr b/tests/ui/regions/issue-102374.stderr
index 157850693..af64b6867 100644
--- a/tests/ui/regions/issue-102374.stderr
+++ b/tests/ui/regions/issue-102374.stderr
@@ -7,7 +7,7 @@ LL | f
| ^ expected `i32`, found fn pointer
|
= note: expected type `i32`
- found fn pointer `for<'z1, 'a, 'b, 'c, 'd, 'e, 'f, 'g, 'h, 'i, 'j, 'k, 'l, 'm, 'n, 'o, 'p, 'q, 'r, 's, 't, 'u, 'v, 'w, 'x, 'y, 'z, 'z0> fn(Cell<...>)`
+ found fn pointer `fn(Cell<...>)`
the full type name has been written to '$TEST_BUILD_DIR/regions/issue-102374/issue-102374.long-type-hash.txt'
error: aborting due to previous error
diff --git a/tests/ui/regions/region-lifetime-bounds-on-fns-where-clause.stderr b/tests/ui/regions/region-lifetime-bounds-on-fns-where-clause.stderr
index 3b62c7b61..bb5bc6f66 100644
--- a/tests/ui/regions/region-lifetime-bounds-on-fns-where-clause.stderr
+++ b/tests/ui/regions/region-lifetime-bounds-on-fns-where-clause.stderr
@@ -6,6 +6,7 @@ LL | let _: fn(&mut &isize, &mut &isize) = a;
|
= note: expected fn pointer `for<'a, 'b, 'c, 'd> fn(&'a mut &'b isize, &'c mut &'d isize)`
found fn item `for<'a, 'b> fn(&'a mut &isize, &'b mut &isize) {a::<'_, '_>}`
+ = note: when the arguments and return types match, functions can be coerced to function pointers
error: aborting due to previous error
diff --git a/tests/ui/regions/region-multiple-lifetime-bounds-on-fns-where-clause.stderr b/tests/ui/regions/region-multiple-lifetime-bounds-on-fns-where-clause.stderr
index 8a18a234b..dbe9e9b1a 100644
--- a/tests/ui/regions/region-multiple-lifetime-bounds-on-fns-where-clause.stderr
+++ b/tests/ui/regions/region-multiple-lifetime-bounds-on-fns-where-clause.stderr
@@ -6,6 +6,7 @@ LL | let _: fn(&mut &isize, &mut &isize, &mut &isize) = a;
|
= note: expected fn pointer `for<'a, 'b, 'c, 'd, 'e, 'f> fn(&'a mut &'b isize, &'c mut &'d isize, &'e mut &'f isize)`
found fn item `for<'a, 'b, 'c> fn(&'a mut &isize, &'b mut &isize, &'c mut &isize) {a::<'_, '_, '_>}`
+ = note: when the arguments and return types match, functions can be coerced to function pointers
error: aborting due to previous error
diff --git a/tests/ui/regions/regions-addr-of-arg.stderr b/tests/ui/regions/regions-addr-of-arg.stderr
index e77289287..99060a9c7 100644
--- a/tests/ui/regions/regions-addr-of-arg.stderr
+++ b/tests/ui/regions/regions-addr-of-arg.stderr
@@ -1,6 +1,8 @@
error[E0597]: `a` does not live long enough
--> $DIR/regions-addr-of-arg.rs:5:30
|
+LL | fn foo(a: isize) {
+ | - binding `a` declared here
LL | let _p: &'static isize = &a;
| -------------- ^^ borrowed value does not live long enough
| |
diff --git a/tests/ui/regions/regions-early-bound-error-method.stderr b/tests/ui/regions/regions-early-bound-error-method.stderr
index 7f10c051f..a7746d898 100644
--- a/tests/ui/regions/regions-early-bound-error-method.stderr
+++ b/tests/ui/regions/regions-early-bound-error-method.stderr
@@ -6,7 +6,7 @@ LL | impl<'a> Box<'a> {
LL | fn or<'b,G:GetRef<'b>>(&self, g2: G) -> &'a isize {
| -- lifetime `'b` defined here
LL | g2.get()
- | ^^^^^^^^ associated function was supposed to return data with lifetime `'a` but it is returning data with lifetime `'b`
+ | ^^^^^^^^ method was supposed to return data with lifetime `'a` but it is returning data with lifetime `'b`
|
= help: consider adding the following bound: `'b: 'a`
diff --git a/tests/ui/regions/regions-fn-subtyping-return-static-fail.stderr b/tests/ui/regions/regions-fn-subtyping-return-static-fail.stderr
index 8d82ff958..766a3d033 100644
--- a/tests/ui/regions/regions-fn-subtyping-return-static-fail.stderr
+++ b/tests/ui/regions/regions-fn-subtyping-return-static-fail.stderr
@@ -8,6 +8,7 @@ LL | want_G(baz);
|
= note: expected fn pointer `for<'cx> fn(&'cx S) -> &'static S`
found fn item `for<'a> fn(&'a S) -> &'a S {baz}`
+ = note: when the arguments and return types match, functions can be coerced to function pointers
note: function defined here
--> $DIR/regions-fn-subtyping-return-static-fail.rs:20:4
|
diff --git a/tests/ui/regions/regions-free-region-ordering-caller1.stderr b/tests/ui/regions/regions-free-region-ordering-caller1.stderr
index 8ef7e2253..c83cfc1c9 100644
--- a/tests/ui/regions/regions-free-region-ordering-caller1.stderr
+++ b/tests/ui/regions/regions-free-region-ordering-caller1.stderr
@@ -18,6 +18,8 @@ error[E0597]: `y` does not live long enough
LL | fn call1<'a>(x: &'a usize) {
| -- lifetime `'a` defined here
...
+LL | let y: usize = 3;
+ | - binding `y` declared here
LL | let z: &'a & usize = &(&y);
| ----------- ^^^^ borrowed value does not live long enough
| |
diff --git a/tests/ui/regions/regions-free-region-ordering-incorrect.stderr b/tests/ui/regions/regions-free-region-ordering-incorrect.stderr
index f7c75033c..d0ceaec3b 100644
--- a/tests/ui/regions/regions-free-region-ordering-incorrect.stderr
+++ b/tests/ui/regions/regions-free-region-ordering-incorrect.stderr
@@ -9,7 +9,7 @@ LL | / match self.next {
LL | | Some(ref next) => next.get(),
LL | | None => &self.val
LL | | }
- | |_________^ associated function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a`
+ | |_________^ method was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a`
|
= help: consider adding the following bound: `'a: 'b`
diff --git a/tests/ui/regions/regions-free-region-outlives-static-outlives-free-region.rs b/tests/ui/regions/regions-free-region-outlives-static-outlives-free-region.rs
index 7c2e1aeee..46462c432 100644
--- a/tests/ui/regions/regions-free-region-outlives-static-outlives-free-region.rs
+++ b/tests/ui/regions/regions-free-region-outlives-static-outlives-free-region.rs
@@ -8,6 +8,8 @@
//
// 'a : 'b
+#![warn(unused_lifetimes)]
+
fn test<'a,'b>(x: &'a i32) -> &'b i32
where 'a: 'static //~ WARN unnecessary lifetime parameter `'a`
{
diff --git a/tests/ui/regions/regions-free-region-outlives-static-outlives-free-region.stderr b/tests/ui/regions/regions-free-region-outlives-static-outlives-free-region.stderr
index 70ed418d5..9f03a6553 100644
--- a/tests/ui/regions/regions-free-region-outlives-static-outlives-free-region.stderr
+++ b/tests/ui/regions/regions-free-region-outlives-static-outlives-free-region.stderr
@@ -1,10 +1,15 @@
warning: unnecessary lifetime parameter `'a`
- --> $DIR/regions-free-region-outlives-static-outlives-free-region.rs:12:11
+ --> $DIR/regions-free-region-outlives-static-outlives-free-region.rs:14:11
|
LL | where 'a: 'static
| ^^
|
= help: you can use the `'static` lifetime directly, in place of `'a`
+note: the lint level is defined here
+ --> $DIR/regions-free-region-outlives-static-outlives-free-region.rs:11:9
+ |
+LL | #![warn(unused_lifetimes)]
+ | ^^^^^^^^^^^^^^^^
warning: 1 warning emitted
diff --git a/tests/ui/regions/regions-infer-proc-static-upvar.stderr b/tests/ui/regions/regions-infer-proc-static-upvar.stderr
index 803d0d744..c8a33bbc5 100644
--- a/tests/ui/regions/regions-infer-proc-static-upvar.stderr
+++ b/tests/ui/regions/regions-infer-proc-static-upvar.stderr
@@ -1,6 +1,8 @@
error[E0597]: `x` does not live long enough
--> $DIR/regions-infer-proc-static-upvar.rs:10:13
|
+LL | let x = 3;
+ | - binding `x` declared here
LL | let y = &x;
| ^^ borrowed value does not live long enough
LL | / foo(move|| {
diff --git a/tests/ui/regions/regions-lifetime-bounds-on-fns.stderr b/tests/ui/regions/regions-lifetime-bounds-on-fns.stderr
index 17a901943..df0fd069e 100644
--- a/tests/ui/regions/regions-lifetime-bounds-on-fns.stderr
+++ b/tests/ui/regions/regions-lifetime-bounds-on-fns.stderr
@@ -6,6 +6,7 @@ LL | let _: fn(&mut &isize, &mut &isize) = a;
|
= note: expected fn pointer `for<'a, 'b, 'c, 'd> fn(&'a mut &'b isize, &'c mut &'d isize)`
found fn item `for<'a, 'b> fn(&'a mut &isize, &'b mut &isize) {a::<'_, '_>}`
+ = note: when the arguments and return types match, functions can be coerced to function pointers
error: aborting due to previous error
diff --git a/tests/ui/regions/regions-mock-codegen.rs b/tests/ui/regions/regions-mock-codegen.rs
index 9d0ca76e4..d5c93f81f 100644
--- a/tests/ui/regions/regions-mock-codegen.rs
+++ b/tests/ui/regions/regions-mock-codegen.rs
@@ -22,15 +22,15 @@ struct Ccx {
x: isize,
}
-fn allocate(_bcx: &arena) -> &Bcx<'_> {
+fn allocate(_bcx: &arena) -> &mut Bcx<'_> {
unsafe {
let layout = Layout::new::<Bcx>();
let ptr = Global.allocate(layout).unwrap_or_else(|_| handle_alloc_error(layout));
- &*(ptr.as_ptr() as *const _)
+ &mut *ptr.as_ptr().cast()
}
}
-fn h<'a>(bcx: &'a Bcx<'a>) -> &'a Bcx<'a> {
+fn h<'a>(bcx: &'a Bcx<'a>) -> &'a mut Bcx<'a> {
return allocate(bcx.fcx.arena);
}
@@ -38,7 +38,7 @@ fn g(fcx: &Fcx) {
let bcx = Bcx { fcx };
let bcx2 = h(&bcx);
unsafe {
- Global.deallocate(NonNull::new_unchecked(bcx2 as *const _ as *mut _), Layout::new::<Bcx>());
+ Global.deallocate(NonNull::new_unchecked(bcx2 as *mut _ as *mut _), Layout::new::<Bcx>());
}
}
diff --git a/tests/ui/regions/regions-nested-fns.stderr b/tests/ui/regions/regions-nested-fns.stderr
index bb2740310..ee43f9fa5 100644
--- a/tests/ui/regions/regions-nested-fns.stderr
+++ b/tests/ui/regions/regions-nested-fns.stderr
@@ -13,6 +13,8 @@ LL | ay = z;
error[E0597]: `y` does not live long enough
--> $DIR/regions-nested-fns.rs:5:18
|
+LL | let y = 3;
+ | - binding `y` declared here
LL | let mut ay = &y;
| ^^ borrowed value does not live long enough
...
diff --git a/tests/ui/regions/regions-pattern-typing-issue-19552.stderr b/tests/ui/regions/regions-pattern-typing-issue-19552.stderr
index f77d94a24..18aec29ad 100644
--- a/tests/ui/regions/regions-pattern-typing-issue-19552.stderr
+++ b/tests/ui/regions/regions-pattern-typing-issue-19552.stderr
@@ -1,6 +1,8 @@
error[E0597]: `line` does not live long enough
--> $DIR/regions-pattern-typing-issue-19552.rs:5:14
|
+LL | let line = String::new();
+ | ---- binding `line` declared here
LL | match [&*line] {
| ^^^^ borrowed value does not live long enough
LL | [ word ] => { assert_static(word); }
diff --git a/tests/ui/regions/regions-pattern-typing-issue-19997.stderr b/tests/ui/regions/regions-pattern-typing-issue-19997.stderr
index ae60e3c0d..0abe77a86 100644
--- a/tests/ui/regions/regions-pattern-typing-issue-19997.stderr
+++ b/tests/ui/regions/regions-pattern-typing-issue-19997.stderr
@@ -2,10 +2,10 @@ error[E0506]: cannot assign to `a1` because it is borrowed
--> $DIR/regions-pattern-typing-issue-19997.rs:7:13
|
LL | match (&a1,) {
- | --- borrow of `a1` occurs here
+ | --- `a1` is borrowed here
LL | (&ref b0,) => {
LL | a1 = &f;
- | ^^^^^^^ assignment to borrowed `a1` occurs here
+ | ^^^^^^^ `a1` is assigned to here but it was already borrowed
LL | drop(b0);
| -- borrow later used here
diff --git a/tests/ui/regions/regions-static-bound-rpass.rs b/tests/ui/regions/regions-static-bound-rpass.rs
index 25232b455..e2ebb394d 100644
--- a/tests/ui/regions/regions-static-bound-rpass.rs
+++ b/tests/ui/regions/regions-static-bound-rpass.rs
@@ -1,5 +1,7 @@
// run-pass
+#![warn(unused_lifetimes)]
+
fn invariant_id<'a,'b>(t: &'b mut &'static ()) -> &'b mut &'a ()
where 'a: 'static { t }
//~^ WARN unnecessary lifetime parameter `'a`
diff --git a/tests/ui/regions/regions-static-bound-rpass.stderr b/tests/ui/regions/regions-static-bound-rpass.stderr
index 9355a409d..f0f3a4c52 100644
--- a/tests/ui/regions/regions-static-bound-rpass.stderr
+++ b/tests/ui/regions/regions-static-bound-rpass.stderr
@@ -1,13 +1,18 @@
warning: unnecessary lifetime parameter `'a`
- --> $DIR/regions-static-bound-rpass.rs:4:11
+ --> $DIR/regions-static-bound-rpass.rs:6:11
|
LL | where 'a: 'static { t }
| ^^
|
= help: you can use the `'static` lifetime directly, in place of `'a`
+note: the lint level is defined here
+ --> $DIR/regions-static-bound-rpass.rs:3:9
+ |
+LL | #![warn(unused_lifetimes)]
+ | ^^^^^^^^^^^^^^^^
warning: unnecessary lifetime parameter `'a`
- --> $DIR/regions-static-bound-rpass.rs:8:11
+ --> $DIR/regions-static-bound-rpass.rs:10:11
|
LL | where 'a: 'static { t }
| ^^
@@ -15,7 +20,7 @@ LL | where 'a: 'static { t }
= help: you can use the `'static` lifetime directly, in place of `'a`
warning: unnecessary lifetime parameter `'b`
- --> $DIR/regions-static-bound-rpass.rs:12:19
+ --> $DIR/regions-static-bound-rpass.rs:14:19
|
LL | where 'a: 'b, 'b: 'static { t }
| ^^
diff --git a/tests/ui/regions/regions-static-bound.rs b/tests/ui/regions/regions-static-bound.rs
index 4d2455470..e7aa8795f 100644
--- a/tests/ui/regions/regions-static-bound.rs
+++ b/tests/ui/regions/regions-static-bound.rs
@@ -1,6 +1,8 @@
-fn static_id<'a,'b>(t: &'a ()) -> &'static ()
- where 'a: 'static { t }
-//~^ WARN unnecessary lifetime parameter `'a`
+#![warn(unused_lifetimes)]
+
+fn static_id<'a,'b>(t: &'a ()) -> &'static () where 'a: 'static { t }
+//~^ WARN lifetime parameter `'b` never used
+//~| WARN unnecessary lifetime parameter `'a`
fn static_id_indirect<'a,'b>(t: &'a ()) -> &'static ()
where 'a: 'b, 'b: 'static { t }
diff --git a/tests/ui/regions/regions-static-bound.stderr b/tests/ui/regions/regions-static-bound.stderr
index 2886ec3ea..b314e9fe8 100644
--- a/tests/ui/regions/regions-static-bound.stderr
+++ b/tests/ui/regions/regions-static-bound.stderr
@@ -1,13 +1,27 @@
+warning: lifetime parameter `'b` never used
+ --> $DIR/regions-static-bound.rs:3:17
+ |
+LL | fn static_id<'a,'b>(t: &'a ()) -> &'static () where 'a: 'static { t }
+ | -^^
+ | |
+ | help: elide the unused lifetime
+ |
+note: the lint level is defined here
+ --> $DIR/regions-static-bound.rs:1:9
+ |
+LL | #![warn(unused_lifetimes)]
+ | ^^^^^^^^^^^^^^^^
+
warning: unnecessary lifetime parameter `'a`
- --> $DIR/regions-static-bound.rs:2:11
+ --> $DIR/regions-static-bound.rs:3:53
|
-LL | where 'a: 'static { t }
- | ^^
+LL | fn static_id<'a,'b>(t: &'a ()) -> &'static () where 'a: 'static { t }
+ | ^^
|
= help: you can use the `'static` lifetime directly, in place of `'a`
warning: unnecessary lifetime parameter `'b`
- --> $DIR/regions-static-bound.rs:6:19
+ --> $DIR/regions-static-bound.rs:8:19
|
LL | where 'a: 'b, 'b: 'static { t }
| ^^
@@ -15,7 +29,7 @@ LL | where 'a: 'b, 'b: 'static { t }
= help: you can use the `'static` lifetime directly, in place of `'b`
error: lifetime may not live long enough
- --> $DIR/regions-static-bound.rs:10:5
+ --> $DIR/regions-static-bound.rs:12:5
|
LL | fn static_id_wrong_way<'a>(t: &'a ()) -> &'static () where 'static: 'a {
| -- lifetime `'a` defined here
@@ -23,7 +37,7 @@ LL | t
| ^ returning this value requires that `'a` must outlive `'static`
error[E0521]: borrowed data escapes outside of function
- --> $DIR/regions-static-bound.rs:15:5
+ --> $DIR/regions-static-bound.rs:17:5
|
LL | fn error(u: &(), v: &()) {
| - - let's call the lifetime of this reference `'1`
@@ -36,7 +50,7 @@ LL | static_id(&u);
| argument requires that `'1` must outlive `'static`
error[E0521]: borrowed data escapes outside of function
- --> $DIR/regions-static-bound.rs:17:5
+ --> $DIR/regions-static-bound.rs:19:5
|
LL | fn error(u: &(), v: &()) {
| - - let's call the lifetime of this reference `'2`
@@ -49,6 +63,6 @@ LL | static_id_indirect(&v);
| `v` escapes the function body here
| argument requires that `'2` must outlive `'static`
-error: aborting due to 3 previous errors; 2 warnings emitted
+error: aborting due to 3 previous errors; 3 warnings emitted
For more information about this error, try `rustc --explain E0521`.
diff --git a/tests/ui/regions/resolve-re-error-ice.rs b/tests/ui/regions/resolve-re-error-ice.rs
new file mode 100644
index 000000000..f37b27a82
--- /dev/null
+++ b/tests/ui/regions/resolve-re-error-ice.rs
@@ -0,0 +1,22 @@
+// check-pass
+
+// Allow this for now, can remove this UI test when this becomes a hard error.
+#![allow(implied_bounds_entailment)]
+
+use std::collections::hash_map::{Keys, HashMap};
+use std::marker::PhantomData;
+
+trait MapAssertion<'a, K, V, R> {
+ fn key_set(&self) -> Subject<Keys<K, V>, (), R>;
+}
+
+struct Subject<'a, T, V, R>(PhantomData<(&'a T, V, R)>);
+
+impl<'a, K, V, R> MapAssertion<'a, K, V, R> for Subject<'a, HashMap<K, V>, (), R>
+{
+ fn key_set(&self) -> Subject<'a, Keys<K, V>, (), R> {
+ todo!()
+ }
+}
+
+fn main() {}
diff --git a/tests/ui/regions/resolve-re-error-ice.stderr b/tests/ui/regions/resolve-re-error-ice.stderr
new file mode 100644
index 000000000..e7003e1c3
--- /dev/null
+++ b/tests/ui/regions/resolve-re-error-ice.stderr
@@ -0,0 +1,15 @@
+Future incompatibility report: Future breakage diagnostic:
+warning: impl method assumes more implied bounds than the corresponding trait method
+ --> $DIR/resolve-re-error-ice.rs:17:16
+ |
+LL | fn key_set(&self) -> Subject<'a, Keys<K, V>, (), R> {
+ | ^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace this type to make the impl signature compatible: `Subject<'_, std::collections::hash_map::Keys<'_, K, V>, (), R>`
+ |
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #105572 <https://github.com/rust-lang/rust/issues/105572>
+note: the lint level is defined here
+ --> $DIR/resolve-re-error-ice.rs:4:10
+ |
+LL | #![allow(implied_bounds_entailment)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^
+
diff --git a/tests/ui/reify-intrinsic.stderr b/tests/ui/reify-intrinsic.stderr
index f78f1d822..9f9034a30 100644
--- a/tests/ui/reify-intrinsic.stderr
+++ b/tests/ui/reify-intrinsic.stderr
@@ -8,6 +8,7 @@ LL | let _: unsafe extern "rust-intrinsic" fn(isize) -> usize = std::mem::tr
|
= note: expected fn pointer `unsafe extern "rust-intrinsic" fn(isize) -> usize`
found fn item `unsafe extern "rust-intrinsic" fn(_) -> _ {transmute::<_, _>}`
+ = note: when the arguments and return types match, functions can be coerced to function pointers
error[E0606]: casting `unsafe extern "rust-intrinsic" fn(_) -> _ {transmute::<_, _>}` as `unsafe extern "rust-intrinsic" fn(isize) -> usize` is invalid
--> $DIR/reify-intrinsic.rs:11:13
@@ -23,9 +24,7 @@ LL | std::intrinsics::unlikely,
|
= note: expected fn item `extern "rust-intrinsic" fn(_) -> _ {likely}`
found fn item `extern "rust-intrinsic" fn(_) -> _ {unlikely}`
- = note: different `fn` items always have unique types, even if their signatures are the same
- = help: change the expected type to be function pointer `extern "rust-intrinsic" fn(bool) -> bool`
- = help: if the expected type is due to type inference, cast the expected `fn` to a function pointer: `likely as extern "rust-intrinsic" fn(bool) -> bool`
+ = note: different fn items have unique types, even if their signatures are the same
error: aborting due to 3 previous errors
diff --git a/tests/ui/repeat-expr/repeat_count.rs b/tests/ui/repeat-expr/repeat_count.rs
index 96abff4ab..18610bc5b 100644
--- a/tests/ui/repeat-expr/repeat_count.rs
+++ b/tests/ui/repeat-expr/repeat_count.rs
@@ -30,5 +30,5 @@ fn main() {
}
let g = [0; G { g: () }];
//~^ ERROR mismatched types
- //~| expected `usize`, found struct `G`
+ //~| expected `usize`, found `G`
}
diff --git a/tests/ui/repeat-expr/repeat_count.stderr b/tests/ui/repeat-expr/repeat_count.stderr
index e222c141f..8a1ed8f3b 100644
--- a/tests/ui/repeat-expr/repeat_count.stderr
+++ b/tests/ui/repeat-expr/repeat_count.stderr
@@ -34,7 +34,7 @@ error[E0308]: mismatched types
--> $DIR/repeat_count.rs:31:17
|
LL | let g = [0; G { g: () }];
- | ^^^^^^^^^^^ expected `usize`, found struct `G`
+ | ^^^^^^^^^^^ expected `usize`, found `G`
error[E0308]: mismatched types
--> $DIR/repeat_count.rs:19:17
diff --git a/tests/ui/repr/16-bit-repr-c-enum.rs b/tests/ui/repr/16-bit-repr-c-enum.rs
new file mode 100644
index 000000000..2acfde4be
--- /dev/null
+++ b/tests/ui/repr/16-bit-repr-c-enum.rs
@@ -0,0 +1,52 @@
+// build-pass
+// revisions: avr msp430
+//
+// [avr] needs-llvm-components: avr
+// [avr] compile-flags: --target=avr-unknown-gnu-atmega328 --crate-type=rlib
+// [msp430] needs-llvm-components: msp430
+// [msp430] compile-flags: --target=msp430-none-elf --crate-type=rlib
+#![feature(no_core, lang_items, intrinsics, staged_api)]
+#![no_core]
+#![crate_type = "lib"]
+#![stable(feature = "", since = "")]
+#![allow(dead_code)]
+
+// Test that the repr(C) attribute doesn't break compilation
+// Previous bad assumption was that 32-bit enum default width is fine on msp430, avr
+// But the width of the C int on these platforms is 16 bits, and C enums <= C int range
+// so we want no more than that, usually. This resulted in errors like
+// "layout decided on a larger discriminant type (I32) than typeck (I16)"
+#[repr(C)]
+enum Foo {
+ Bar,
+}
+
+extern "rust-intrinsic" {
+ #[stable(feature = "", since = "")]
+ #[rustc_const_stable(feature = "", since = "")]
+ #[rustc_safe_intrinsic]
+ fn size_of<T>() -> usize;
+}
+
+#[lang="sized"]
+trait Sized {}
+#[lang="copy"]
+trait Copy {}
+
+const EXPECTED: usize = 2;
+const ACTUAL: usize = size_of::<Foo>();
+// Validate that the size is indeed 16 bits, to match this C static_assert:
+/**
+```c
+#include <assert.h>
+enum foo {
+ BAR
+};
+int main(void)
+{
+ /* passes on msp430-elf-gcc */
+ static_assert(sizeof(enum foo) == 2);
+}
+```
+*/
+const _: [(); EXPECTED] = [(); ACTUAL];
diff --git a/tests/ui/resolve/issue-108529.rs b/tests/ui/resolve/issue-108529.rs
new file mode 100644
index 000000000..8e3aafab6
--- /dev/null
+++ b/tests/ui/resolve/issue-108529.rs
@@ -0,0 +1,8 @@
+#![allow(nonstandard_style)]
+use f::f::f; //~ ERROR
+
+trait f {
+ extern "C" fn f();
+}
+
+fn main() {}
diff --git a/tests/ui/resolve/issue-108529.stderr b/tests/ui/resolve/issue-108529.stderr
new file mode 100644
index 000000000..cf4e4759c
--- /dev/null
+++ b/tests/ui/resolve/issue-108529.stderr
@@ -0,0 +1,9 @@
+error[E0432]: unresolved import `f::f`
+ --> $DIR/issue-108529.rs:2:8
+ |
+LL | use f::f::f;
+ | ^ expected type, found associated function `f` in `f`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0432`.
diff --git a/tests/ui/resolve/name-clash-nullary.stderr b/tests/ui/resolve/name-clash-nullary.stderr
index 76c4b5914..fffd3027a 100644
--- a/tests/ui/resolve/name-clash-nullary.stderr
+++ b/tests/ui/resolve/name-clash-nullary.stderr
@@ -4,7 +4,7 @@ error[E0308]: mismatched types
LL | let None: isize = 42;
| ^^^^ ----- expected due to this
| |
- | expected `isize`, found enum `Option`
+ | expected `isize`, found `Option<_>`
|
= note: expected type `isize`
found enum `Option<_>`
diff --git a/tests/ui/resolve/privacy-enum-ctor.stderr b/tests/ui/resolve/privacy-enum-ctor.stderr
index a24fe4d23..3c051429f 100644
--- a/tests/ui/resolve/privacy-enum-ctor.stderr
+++ b/tests/ui/resolve/privacy-enum-ctor.stderr
@@ -267,7 +267,7 @@ LL | Fn(u8),
| -- `Fn` defines an enum variant constructor here, which should be called
...
LL | let _: Z = Z::Fn;
- | - ^^^^^ expected enum `Z`, found enum constructor
+ | - ^^^^^ expected `Z`, found enum constructor
| |
| expected due to this
|
@@ -308,7 +308,7 @@ LL | Fn(u8),
| -- `Fn` defines an enum variant constructor here, which should be called
...
LL | let _: E = m::E::Fn;
- | - ^^^^^^^^ expected enum `E`, found enum constructor
+ | - ^^^^^^^^ expected `E`, found enum constructor
| |
| expected due to this
|
@@ -349,7 +349,7 @@ LL | Fn(u8),
| -- `Fn` defines an enum variant constructor here, which should be called
...
LL | let _: E = E::Fn;
- | - ^^^^^ expected enum `E`, found enum constructor
+ | - ^^^^^ expected `E`, found enum constructor
| |
| expected due to this
|
diff --git a/tests/ui/resolve/resolve-inconsistent-names.stderr b/tests/ui/resolve/resolve-inconsistent-names.stderr
index 773c9f6cd..023db303d 100644
--- a/tests/ui/resolve/resolve-inconsistent-names.stderr
+++ b/tests/ui/resolve/resolve-inconsistent-names.stderr
@@ -87,7 +87,7 @@ error[E0308]: mismatched types
LL | match x {
| - this expression has type `(E, E)`
LL | (A, B) | (ref B, c) | (c, A) => ()
- | - ^^^^^ expected enum `E`, found `&E`
+ | - ^^^^^ expected `E`, found `&E`
| |
| first introduced with type `E` here
|
diff --git a/tests/ui/resolve/resolve-primitive-fallback.stderr b/tests/ui/resolve/resolve-primitive-fallback.stderr
index 964302e92..f803f9da2 100644
--- a/tests/ui/resolve/resolve-primitive-fallback.stderr
+++ b/tests/ui/resolve/resolve-primitive-fallback.stderr
@@ -24,14 +24,13 @@ error[E0061]: this function takes 0 arguments but 1 argument was supplied
--> $DIR/resolve-primitive-fallback.rs:3:5
|
LL | std::mem::size_of(u16);
- | ^^^^^^^^^^^^^^^^^ --- argument unexpected
+ | ^^^^^^^^^^^^^^^^^ ---
+ | |
+ | unexpected argument
+ | help: remove the extra argument
|
note: function defined here
--> $SRC_DIR/core/src/mem/mod.rs:LL:COL
-help: remove the extra argument
- |
-LL | std::mem::size_of();
- | ~~
error: aborting due to 3 previous errors
diff --git a/tests/ui/resolve/token-error-correct-2.rs b/tests/ui/resolve/token-error-correct-2.rs
index f7c7d908c..a38755dae 100644
--- a/tests/ui/resolve/token-error-correct-2.rs
+++ b/tests/ui/resolve/token-error-correct-2.rs
@@ -2,6 +2,5 @@
fn main() {
if foo {
- //~^ ERROR: cannot find value `foo`
) //~ ERROR: mismatched closing delimiter: `)`
}
diff --git a/tests/ui/resolve/token-error-correct-2.stderr b/tests/ui/resolve/token-error-correct-2.stderr
index cca9f2dc8..be5fb18a5 100644
--- a/tests/ui/resolve/token-error-correct-2.stderr
+++ b/tests/ui/resolve/token-error-correct-2.stderr
@@ -3,16 +3,8 @@ error: mismatched closing delimiter: `)`
|
LL | if foo {
| ^ unclosed delimiter
-LL |
LL | )
| ^ mismatched closing delimiter
-error[E0425]: cannot find value `foo` in this scope
- --> $DIR/token-error-correct-2.rs:4:8
- |
-LL | if foo {
- | ^^^ not found in this scope
-
-error: aborting due to 2 previous errors
+error: aborting due to previous error
-For more information about this error, try `rustc --explain E0425`.
diff --git a/tests/ui/resolve/token-error-correct-3.rs b/tests/ui/resolve/token-error-correct-3.rs
index 52934085f..2793f1b90 100644
--- a/tests/ui/resolve/token-error-correct-3.rs
+++ b/tests/ui/resolve/token-error-correct-3.rs
@@ -9,12 +9,9 @@ pub mod raw {
callback: F)
-> io::Result<bool> {
if !is_directory(path.as_ref()) {
- //~^ ERROR cannot find function `is_directory`
callback(path.as_ref();
- //~^ ERROR expected one of
fs::create_dir_all(path.as_ref()).map(|()| true)
- } else {
- //~^ ERROR expected one of `.`, `;`, `?`, `}`, or an operator, found `)`
+ } else { //~ ERROR mismatched closing delimiter
Ok(false);
}
diff --git a/tests/ui/resolve/token-error-correct-3.stderr b/tests/ui/resolve/token-error-correct-3.stderr
index 77c87c784..79d1d4883 100644
--- a/tests/ui/resolve/token-error-correct-3.stderr
+++ b/tests/ui/resolve/token-error-correct-3.stderr
@@ -1,25 +1,13 @@
-error: expected one of `)`, `,`, `.`, `?`, or an operator, found `;`
- --> $DIR/token-error-correct-3.rs:13:21
+error: mismatched closing delimiter: `}`
+ --> $DIR/token-error-correct-3.rs:12:21
|
+LL | if !is_directory(path.as_ref()) {
+ | - closing delimiter possibly meant for this
LL | callback(path.as_ref();
- | ^ ^ help: `)` may belong here
- | |
- | unclosed delimiter
-
-error: expected one of `.`, `;`, `?`, `}`, or an operator, found `)`
- --> $DIR/token-error-correct-3.rs:16:9
- |
+ | ^ unclosed delimiter
LL | fs::create_dir_all(path.as_ref()).map(|()| true)
- | - expected one of `.`, `;`, `?`, `}`, or an operator
LL | } else {
- | ^ unexpected token
-
-error[E0425]: cannot find function `is_directory` in this scope
- --> $DIR/token-error-correct-3.rs:11:13
- |
-LL | if !is_directory(path.as_ref()) {
- | ^^^^^^^^^^^^ not found in this scope
+ | ^ mismatched closing delimiter
-error: aborting due to 3 previous errors
+error: aborting due to previous error
-For more information about this error, try `rustc --explain E0425`.
diff --git a/tests/ui/resolve/token-error-correct-4.fixed b/tests/ui/resolve/token-error-correct-4.fixed
deleted file mode 100644
index 064b9e74e..000000000
--- a/tests/ui/resolve/token-error-correct-4.fixed
+++ /dev/null
@@ -1,10 +0,0 @@
-// run-rustfix
-// Test that we do some basic error correction in the tokeniser and apply suggestions.
-
-fn setsuna(_: ()) {}
-
-fn kazusa() {}
-
-fn main() {
- setsuna(kazusa()); //~ ERROR: expected one of
-} //~ ERROR: expected expression
diff --git a/tests/ui/resolve/token-error-correct-4.rs b/tests/ui/resolve/token-error-correct-4.rs
index 5e31d71e7..49fad4bd9 100644
--- a/tests/ui/resolve/token-error-correct-4.rs
+++ b/tests/ui/resolve/token-error-correct-4.rs
@@ -1,4 +1,3 @@
-// run-rustfix
// Test that we do some basic error correction in the tokeniser and apply suggestions.
fn setsuna(_: ()) {}
@@ -6,5 +5,5 @@ fn setsuna(_: ()) {}
fn kazusa() {}
fn main() {
- setsuna(kazusa(); //~ ERROR: expected one of
-} //~ ERROR: expected expression
+ setsuna(kazusa();
+} //~ ERROR mismatched closing delimiter
diff --git a/tests/ui/resolve/token-error-correct-4.stderr b/tests/ui/resolve/token-error-correct-4.stderr
index 81e5a1336..3ec97171f 100644
--- a/tests/ui/resolve/token-error-correct-4.stderr
+++ b/tests/ui/resolve/token-error-correct-4.stderr
@@ -1,16 +1,12 @@
-error: expected one of `)`, `,`, `.`, `?`, or an operator, found `;`
- --> $DIR/token-error-correct-4.rs:9:12
+error: mismatched closing delimiter: `}`
+ --> $DIR/token-error-correct-4.rs:8:12
|
+LL | fn main() {
+ | - closing delimiter possibly meant for this
LL | setsuna(kazusa();
- | ^ ^ help: `)` may belong here
- | |
- | unclosed delimiter
-
-error: expected expression, found `)`
- --> $DIR/token-error-correct-4.rs:10:1
- |
+ | ^ unclosed delimiter
LL | }
- | ^ expected expression
+ | ^ mismatched closing delimiter
-error: aborting due to 2 previous errors
+error: aborting due to previous error
diff --git a/tests/ui/resolve/token-error-correct.rs b/tests/ui/resolve/token-error-correct.rs
index 4f74df0bf..84ee90e36 100644
--- a/tests/ui/resolve/token-error-correct.rs
+++ b/tests/ui/resolve/token-error-correct.rs
@@ -2,7 +2,6 @@
fn main() {
foo(bar(;
- //~^ ERROR cannot find function `bar` in this scope
}
//~^ ERROR: mismatched closing delimiter: `}`
diff --git a/tests/ui/resolve/token-error-correct.stderr b/tests/ui/resolve/token-error-correct.stderr
index ca0c4c18a..35b2d0b32 100644
--- a/tests/ui/resolve/token-error-correct.stderr
+++ b/tests/ui/resolve/token-error-correct.stderr
@@ -5,16 +5,8 @@ LL | fn main() {
| - closing delimiter possibly meant for this
LL | foo(bar(;
| ^ unclosed delimiter
-LL |
LL | }
| ^ mismatched closing delimiter
-error[E0425]: cannot find function `bar` in this scope
- --> $DIR/token-error-correct.rs:4:9
- |
-LL | foo(bar(;
- | ^^^ not found in this scope
-
-error: aborting due to 2 previous errors
+error: aborting due to previous error
-For more information about this error, try `rustc --explain E0425`.
diff --git a/tests/ui/return/return-type.stderr b/tests/ui/return/return-type.stderr
index 5af136e60..60d538eba 100644
--- a/tests/ui/return/return-type.stderr
+++ b/tests/ui/return/return-type.stderr
@@ -2,7 +2,7 @@ error[E0308]: mismatched types
--> $DIR/return-type.rs:10:5
|
LL | foo(4 as usize)
- | ^^^^^^^^^^^^^^^ expected `()`, found struct `S`
+ | ^^^^^^^^^^^^^^^ expected `()`, found `S<usize>`
|
= note: expected unit type `()`
found struct `S<usize>`
diff --git a/tests/ui/return/tail-expr-as-potential-return.stderr b/tests/ui/return/tail-expr-as-potential-return.stderr
index 9183b4599..ccb208fc6 100644
--- a/tests/ui/return/tail-expr-as-potential-return.stderr
+++ b/tests/ui/return/tail-expr-as-potential-return.stderr
@@ -3,7 +3,7 @@ error[E0308]: mismatched types
|
LL | / if x {
LL | | Err(42)
- | | ^^^^^^^ expected `()`, found enum `Result`
+ | | ^^^^^^^ expected `()`, found `Result<_, {integer}>`
LL | | //| HELP you might have meant to return this value
LL | | }
| |_____- expected this to be `()`
@@ -35,7 +35,7 @@ error[E0308]: mismatched types
|
LL | / if x {
LL | | Err(42)
- | | ^^^^^^^ expected `()`, found enum `Result`
+ | | ^^^^^^^ expected `()`, found `Result<_, {integer}>`
LL | | //| HELP you might have meant to return this value
LL | | }
| |_____- expected this to be `()`
diff --git a/tests/ui/rfc-2005-default-binding-mode/const.stderr b/tests/ui/rfc-2005-default-binding-mode/const.stderr
index 0f5671254..fc06de90a 100644
--- a/tests/ui/rfc-2005-default-binding-mode/const.stderr
+++ b/tests/ui/rfc-2005-default-binding-mode/const.stderr
@@ -9,7 +9,7 @@ LL | match &f {
LL | FOO => {},
| ^^^
| |
- | expected `&Foo`, found struct `Foo`
+ | expected `&Foo`, found `Foo`
| `FOO` is interpreted as a constant, not a new binding
| help: introduce a new binding instead: `other_foo`
diff --git a/tests/ui/rfc-2005-default-binding-mode/lit.stderr b/tests/ui/rfc-2005-default-binding-mode/lit.stderr
index 11bc170cd..181f57899 100644
--- a/tests/ui/rfc-2005-default-binding-mode/lit.stderr
+++ b/tests/ui/rfc-2005-default-binding-mode/lit.stderr
@@ -4,7 +4,7 @@ error[E0308]: mismatched types
LL | match &s {
| -- this expression has type `&&str`
LL | "abc" => true,
- | ^^^^^ expected `&str`, found `str`
+ | ^^^^^ expected `&&str`, found `&str`
|
= note: expected reference `&&str`
found reference `&'static str`
@@ -15,7 +15,7 @@ error[E0308]: mismatched types
LL | match &s {
| -- this expression has type `&&[u8]`
LL | b"abc" => true,
- | ^^^^^^ expected `&[u8]`, found array `[u8; 3]`
+ | ^^^^^^ expected `&&[u8]`, found `&[u8; 3]`
|
= note: expected reference `&&[u8]`
found reference `&'static [u8; 3]`
diff --git a/tests/ui/rfc-2008-non-exhaustive/borrowck-non-exhaustive.stderr b/tests/ui/rfc-2008-non-exhaustive/borrowck-non-exhaustive.stderr
index de730ce10..ad84ebe3a 100644
--- a/tests/ui/rfc-2008-non-exhaustive/borrowck-non-exhaustive.stderr
+++ b/tests/ui/rfc-2008-non-exhaustive/borrowck-non-exhaustive.stderr
@@ -2,7 +2,7 @@ error[E0503]: cannot use `x` because it was mutably borrowed
--> $DIR/borrowck-non-exhaustive.rs:12:11
|
LL | let y = &mut x;
- | ------ borrow of `x` occurs here
+ | ------ `x` is borrowed here
LL | match x {
| ^ use of borrowed `x`
...
diff --git a/tests/ui/rfc-2008-non-exhaustive/uninhabited/coercions.stderr b/tests/ui/rfc-2008-non-exhaustive/uninhabited/coercions.stderr
index f8ed156b5..c209caab5 100644
--- a/tests/ui/rfc-2008-non-exhaustive/uninhabited/coercions.stderr
+++ b/tests/ui/rfc-2008-non-exhaustive/uninhabited/coercions.stderr
@@ -4,7 +4,7 @@ error[E0308]: mismatched types
LL | fn cannot_coerce_empty_enum_to_anything(x: UninhabitedEnum) -> A {
| - expected `A` because of return type
LL | x
- | ^ expected struct `A`, found enum `UninhabitedEnum`
+ | ^ expected `A`, found `UninhabitedEnum`
error[E0308]: mismatched types
--> $DIR/coercions.rs:27:5
@@ -12,7 +12,7 @@ error[E0308]: mismatched types
LL | fn cannot_coerce_empty_tuple_struct_to_anything(x: UninhabitedTupleStruct) -> A {
| - expected `A` because of return type
LL | x
- | ^ expected struct `A`, found struct `UninhabitedTupleStruct`
+ | ^ expected `A`, found `UninhabitedTupleStruct`
error[E0308]: mismatched types
--> $DIR/coercions.rs:31:5
@@ -20,7 +20,7 @@ error[E0308]: mismatched types
LL | fn cannot_coerce_empty_struct_to_anything(x: UninhabitedStruct) -> A {
| - expected `A` because of return type
LL | x
- | ^ expected struct `A`, found struct `UninhabitedStruct`
+ | ^ expected `A`, found `UninhabitedStruct`
error[E0308]: mismatched types
--> $DIR/coercions.rs:35:5
@@ -28,7 +28,7 @@ error[E0308]: mismatched types
LL | fn cannot_coerce_enum_with_empty_variants_to_anything(x: UninhabitedVariants) -> A {
| - expected `A` because of return type
LL | x
- | ^ expected struct `A`, found enum `UninhabitedVariants`
+ | ^ expected `A`, found `UninhabitedVariants`
error: aborting due to 4 previous errors
diff --git a/tests/ui/rfc-2008-non-exhaustive/uninhabited/coercions_same_crate.stderr b/tests/ui/rfc-2008-non-exhaustive/uninhabited/coercions_same_crate.stderr
index fd2c56974..289433edf 100644
--- a/tests/ui/rfc-2008-non-exhaustive/uninhabited/coercions_same_crate.stderr
+++ b/tests/ui/rfc-2008-non-exhaustive/uninhabited/coercions_same_crate.stderr
@@ -4,7 +4,7 @@ error[E0308]: mismatched types
LL | fn cannot_coerce_empty_enum_to_anything(x: UninhabitedEnum) -> A {
| - expected `A` because of return type
LL | x
- | ^ expected struct `A`, found enum `UninhabitedEnum`
+ | ^ expected `A`, found `UninhabitedEnum`
error[E0308]: mismatched types
--> $DIR/coercions_same_crate.rs:34:5
@@ -12,7 +12,7 @@ error[E0308]: mismatched types
LL | fn cannot_coerce_empty_tuple_struct_to_anything(x: UninhabitedTupleStruct) -> A {
| - expected `A` because of return type
LL | x
- | ^ expected struct `A`, found struct `UninhabitedTupleStruct`
+ | ^ expected `A`, found `UninhabitedTupleStruct`
error[E0308]: mismatched types
--> $DIR/coercions_same_crate.rs:38:5
@@ -20,7 +20,7 @@ error[E0308]: mismatched types
LL | fn cannot_coerce_empty_struct_to_anything(x: UninhabitedStruct) -> A {
| - expected `A` because of return type
LL | x
- | ^ expected struct `A`, found struct `UninhabitedStruct`
+ | ^ expected `A`, found `UninhabitedStruct`
error[E0308]: mismatched types
--> $DIR/coercions_same_crate.rs:42:5
@@ -28,7 +28,7 @@ error[E0308]: mismatched types
LL | fn cannot_coerce_enum_with_empty_variants_to_anything(x: UninhabitedVariants) -> A {
| - expected `A` because of return type
LL | x
- | ^ expected struct `A`, found enum `UninhabitedVariants`
+ | ^ expected `A`, found `UninhabitedVariants`
error: aborting due to 4 previous errors
diff --git a/tests/ui/rfc-2091-track-caller/call-chain.rs b/tests/ui/rfc-2091-track-caller/call-chain.rs
index 28b3f76c9..a8814ce28 100644
--- a/tests/ui/rfc-2091-track-caller/call-chain.rs
+++ b/tests/ui/rfc-2091-track-caller/call-chain.rs
@@ -1,6 +1,6 @@
// run-pass
// revisions: default mir-opt
-//[default] compile-flags: -Zinline-mir=no
+//[default] compile-flags: -Zinline-mir=false
//[mir-opt] compile-flags: -Zmir-opt-level=4
use std::panic::Location;
diff --git a/tests/ui/rfc-2091-track-caller/error-with-main.stderr b/tests/ui/rfc-2091-track-caller/error-with-main.stderr
index 7e2ec3524..6d6562dae 100644
--- a/tests/ui/rfc-2091-track-caller/error-with-main.stderr
+++ b/tests/ui/rfc-2091-track-caller/error-with-main.stderr
@@ -2,7 +2,7 @@ error: `main` function is not allowed to be `#[track_caller]`
--> $DIR/error-with-main.rs:1:1
|
LL | #[track_caller]
- | ^^^^^^^^^^^^^^^
+ | ^^^^^^^^^^^^^^^ help: remove this annotation
LL | fn main() {
| --------- `main` function is not allowed to be `#[track_caller]`
diff --git a/tests/ui/rfc-2294-if-let-guard/typeck.stderr b/tests/ui/rfc-2294-if-let-guard/typeck.stderr
index dd1f4826f..4ce97a68a 100644
--- a/tests/ui/rfc-2294-if-let-guard/typeck.stderr
+++ b/tests/ui/rfc-2294-if-let-guard/typeck.stderr
@@ -4,7 +4,7 @@ error[E0308]: mismatched types
LL | Ok(x) if let Err(_) = x => {},
| ^^^^^^ - this expression has type `Option<bool>`
| |
- | expected enum `Option`, found enum `Result`
+ | expected `Option<bool>`, found `Result<_, _>`
|
= note: expected enum `Option<bool>`
found enum `Result<_, _>`
@@ -15,7 +15,7 @@ error[E0308]: mismatched types
LL | Ok(x) if let 0 = x => {},
| ^ - this expression has type `Option<bool>`
| |
- | expected enum `Option`, found integer
+ | expected `Option<bool>`, found integer
|
= note: expected enum `Option<bool>`
found type `{integer}`
diff --git a/tests/ui/rfc-2457/mod_file_nonascii_forbidden.stderr b/tests/ui/rfc-2457/mod_file_nonascii_forbidden.stderr
index dd0dac95e..7639ae9f6 100644
--- a/tests/ui/rfc-2457/mod_file_nonascii_forbidden.stderr
+++ b/tests/ui/rfc-2457/mod_file_nonascii_forbidden.stderr
@@ -12,7 +12,7 @@ error[E0754]: trying to load file for module `řųśť` with non-ascii identifie
LL | mod řųśť;
| ^^^^
|
- = help: consider using `#[path]` attribute to specify filesystem path
+ = help: consider using the `#[path]` attribute to specify filesystem path
error: aborting due to 2 previous errors
diff --git a/tests/ui/rfc-2497-if-let-chains/disallowed-positions.stderr b/tests/ui/rfc-2497-if-let-chains/disallowed-positions.stderr
index 3028f8dbd..81933173c 100644
--- a/tests/ui/rfc-2497-if-let-chains/disallowed-positions.stderr
+++ b/tests/ui/rfc-2497-if-let-chains/disallowed-positions.stderr
@@ -1516,7 +1516,7 @@ error[E0308]: mismatched types
--> $DIR/disallowed-positions.rs:157:8
|
LL | if true..(let 0 = 0) {}
- | ^^^^^^^^^^^^^^^^^ expected `bool`, found struct `Range`
+ | ^^^^^^^^^^^^^^^^^ expected `bool`, found `Range<bool>`
|
= note: expected type `bool`
found struct `std::ops::Range<bool>`
@@ -1525,7 +1525,7 @@ error[E0308]: mismatched types
--> $DIR/disallowed-positions.rs:161:8
|
LL | if ..(let 0 = 0) {}
- | ^^^^^^^^^^^^^ expected `bool`, found struct `RangeTo`
+ | ^^^^^^^^^^^^^ expected `bool`, found `RangeTo<bool>`
|
= note: expected type `bool`
found struct `RangeTo<bool>`
@@ -1534,7 +1534,7 @@ error[E0308]: mismatched types
--> $DIR/disallowed-positions.rs:165:8
|
LL | if (let 0 = 0).. {}
- | ^^^^^^^^^^^^^ expected `bool`, found struct `RangeFrom`
+ | ^^^^^^^^^^^^^ expected `bool`, found `RangeFrom<bool>`
|
= note: expected type `bool`
found struct `RangeFrom<bool>`
@@ -1545,7 +1545,7 @@ error[E0308]: mismatched types
LL | if let Range { start: _, end: _ } = true..true && false {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ ---- this expression has type `bool`
| |
- | expected `bool`, found struct `Range`
+ | expected `bool`, found `Range<_>`
|
= note: expected type `bool`
found struct `std::ops::Range<_>`
@@ -1554,7 +1554,7 @@ error[E0308]: mismatched types
--> $DIR/disallowed-positions.rs:171:8
|
LL | if let Range { start: _, end: _ } = true..true && false {}
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found struct `Range`
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found `Range<bool>`
|
= note: expected type `bool`
found struct `std::ops::Range<bool>`
@@ -1565,7 +1565,7 @@ error[E0308]: mismatched types
LL | if let Range { start: _, end: _ } = true..true || false {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ ---- this expression has type `bool`
| |
- | expected `bool`, found struct `Range`
+ | expected `bool`, found `Range<_>`
|
= note: expected type `bool`
found struct `std::ops::Range<_>`
@@ -1574,7 +1574,7 @@ error[E0308]: mismatched types
--> $DIR/disallowed-positions.rs:175:8
|
LL | if let Range { start: _, end: _ } = true..true || false {}
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found struct `Range`
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found `Range<bool>`
|
= note: expected type `bool`
found struct `std::ops::Range<bool>`
@@ -1585,7 +1585,7 @@ error[E0308]: mismatched types
LL | if let Range { start: F, end } = F..|| true {}
| ^^^^^^^^^^^^^^^^^^^^^^^ - this expression has type `fn() -> bool`
| |
- | expected fn pointer, found struct `Range`
+ | expected fn pointer, found `Range<_>`
|
= note: expected fn pointer `fn() -> bool`
found struct `std::ops::Range<_>`
@@ -1607,7 +1607,7 @@ error[E0308]: mismatched types
--> $DIR/disallowed-positions.rs:182:8
|
LL | if let Range { start: F, end } = F..|| true {}
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found struct `Range`
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found `Range<bool>`
|
= note: expected type `bool`
found struct `std::ops::Range<bool>`
@@ -1618,7 +1618,7 @@ error[E0308]: mismatched types
LL | if let Range { start: true, end } = t..&&false {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ - this expression has type `&&bool`
| |
- | expected `bool`, found struct `Range`
+ | expected `bool`, found `Range<_>`
|
= note: expected type `bool`
found struct `std::ops::Range<_>`
@@ -1639,7 +1639,7 @@ error[E0308]: mismatched types
--> $DIR/disallowed-positions.rs:190:8
|
LL | if let Range { start: true, end } = t..&&false {}
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found struct `Range`
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found `Range<bool>`
|
= note: expected type `bool`
found struct `std::ops::Range<bool>`
@@ -1710,7 +1710,7 @@ error[E0308]: mismatched types
--> $DIR/disallowed-positions.rs:249:11
|
LL | while true..(let 0 = 0) {}
- | ^^^^^^^^^^^^^^^^^ expected `bool`, found struct `Range`
+ | ^^^^^^^^^^^^^^^^^ expected `bool`, found `Range<bool>`
|
= note: expected type `bool`
found struct `std::ops::Range<bool>`
@@ -1719,7 +1719,7 @@ error[E0308]: mismatched types
--> $DIR/disallowed-positions.rs:253:11
|
LL | while ..(let 0 = 0) {}
- | ^^^^^^^^^^^^^ expected `bool`, found struct `RangeTo`
+ | ^^^^^^^^^^^^^ expected `bool`, found `RangeTo<bool>`
|
= note: expected type `bool`
found struct `RangeTo<bool>`
@@ -1728,7 +1728,7 @@ error[E0308]: mismatched types
--> $DIR/disallowed-positions.rs:257:11
|
LL | while (let 0 = 0).. {}
- | ^^^^^^^^^^^^^ expected `bool`, found struct `RangeFrom`
+ | ^^^^^^^^^^^^^ expected `bool`, found `RangeFrom<bool>`
|
= note: expected type `bool`
found struct `RangeFrom<bool>`
@@ -1739,7 +1739,7 @@ error[E0308]: mismatched types
LL | while let Range { start: _, end: _ } = true..true && false {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ ---- this expression has type `bool`
| |
- | expected `bool`, found struct `Range`
+ | expected `bool`, found `Range<_>`
|
= note: expected type `bool`
found struct `std::ops::Range<_>`
@@ -1748,7 +1748,7 @@ error[E0308]: mismatched types
--> $DIR/disallowed-positions.rs:263:11
|
LL | while let Range { start: _, end: _ } = true..true && false {}
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found struct `Range`
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found `Range<bool>`
|
= note: expected type `bool`
found struct `std::ops::Range<bool>`
@@ -1759,7 +1759,7 @@ error[E0308]: mismatched types
LL | while let Range { start: _, end: _ } = true..true || false {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ ---- this expression has type `bool`
| |
- | expected `bool`, found struct `Range`
+ | expected `bool`, found `Range<_>`
|
= note: expected type `bool`
found struct `std::ops::Range<_>`
@@ -1768,7 +1768,7 @@ error[E0308]: mismatched types
--> $DIR/disallowed-positions.rs:267:11
|
LL | while let Range { start: _, end: _ } = true..true || false {}
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found struct `Range`
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found `Range<bool>`
|
= note: expected type `bool`
found struct `std::ops::Range<bool>`
@@ -1779,7 +1779,7 @@ error[E0308]: mismatched types
LL | while let Range { start: F, end } = F..|| true {}
| ^^^^^^^^^^^^^^^^^^^^^^^ - this expression has type `fn() -> bool`
| |
- | expected fn pointer, found struct `Range`
+ | expected fn pointer, found `Range<_>`
|
= note: expected fn pointer `fn() -> bool`
found struct `std::ops::Range<_>`
@@ -1801,7 +1801,7 @@ error[E0308]: mismatched types
--> $DIR/disallowed-positions.rs:274:11
|
LL | while let Range { start: F, end } = F..|| true {}
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found struct `Range`
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found `Range<bool>`
|
= note: expected type `bool`
found struct `std::ops::Range<bool>`
@@ -1812,7 +1812,7 @@ error[E0308]: mismatched types
LL | while let Range { start: true, end } = t..&&false {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ - this expression has type `&&bool`
| |
- | expected `bool`, found struct `Range`
+ | expected `bool`, found `Range<_>`
|
= note: expected type `bool`
found struct `std::ops::Range<_>`
@@ -1833,7 +1833,7 @@ error[E0308]: mismatched types
--> $DIR/disallowed-positions.rs:282:11
|
LL | while let Range { start: true, end } = t..&&false {}
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found struct `Range`
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found `Range<bool>`
|
= note: expected type `bool`
found struct `std::ops::Range<bool>`
@@ -1883,7 +1883,7 @@ error[E0308]: mismatched types
LL | (let Range { start: _, end: _ } = true..true || false);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ ---- this expression has type `bool`
| |
- | expected `bool`, found struct `Range`
+ | expected `bool`, found `Range<_>`
|
= note: expected type `bool`
found struct `std::ops::Range<_>`
diff --git a/tests/ui/rfc-2497-if-let-chains/ensure-that-let-else-does-not-interact-with-let-chains.stderr b/tests/ui/rfc-2497-if-let-chains/ensure-that-let-else-does-not-interact-with-let-chains.stderr
index 498a112fa..9bc3e7541 100644
--- a/tests/ui/rfc-2497-if-let-chains/ensure-that-let-else-does-not-interact-with-let-chains.stderr
+++ b/tests/ui/rfc-2497-if-let-chains/ensure-that-let-else-does-not-interact-with-let-chains.stderr
@@ -37,6 +37,11 @@ help: add a block here
|
LL | if let Some(n) = opt else {
| ^
+help: remove the `if` if you meant to write a `let...else` statement
+ |
+LL - if let Some(n) = opt else {
+LL + let Some(n) = opt else {
+ |
error: this `if` expression is missing a block after the condition
--> $DIR/ensure-that-let-else-does-not-interact-with-let-chains.rs:28:5
@@ -101,7 +106,7 @@ error[E0308]: mismatched types
--> $DIR/ensure-that-let-else-does-not-interact-with-let-chains.rs:9:19
|
LL | let Some(n) = opt && n == 1 else {
- | ^^^ expected `bool`, found enum `Option`
+ | ^^^ expected `bool`, found `Option<i32>`
|
= note: expected type `bool`
found enum `Option<i32>`
@@ -112,7 +117,7 @@ error[E0308]: mismatched types
LL | let Some(n) = opt && n == 1 else {
| ^^^^^^^ ------------- this expression has type `bool`
| |
- | expected `bool`, found enum `Option`
+ | expected `bool`, found `Option<_>`
|
= note: expected type `bool`
found enum `Option<_>`
@@ -121,7 +126,7 @@ error[E0308]: mismatched types
--> $DIR/ensure-that-let-else-does-not-interact-with-let-chains.rs:15:19
|
LL | let Some(n) = opt && let another = n else {
- | ^^^ expected `bool`, found enum `Option`
+ | ^^^ expected `bool`, found `Option<i32>`
|
= note: expected type `bool`
found enum `Option<i32>`
@@ -132,7 +137,7 @@ error[E0308]: mismatched types
LL | let Some(n) = opt && let another = n else {
| ^^^^^^^ ---------------------- this expression has type `bool`
| |
- | expected `bool`, found enum `Option`
+ | expected `bool`, found `Option<_>`
|
= note: expected type `bool`
found enum `Option<_>`
diff --git a/tests/ui/rfc-2632-const-trait-impl/const-closure-parse-not-item.rs b/tests/ui/rfc-2632-const-trait-impl/const-closure-parse-not-item.rs
new file mode 100644
index 000000000..2c99d8bf1
--- /dev/null
+++ b/tests/ui/rfc-2632-const-trait-impl/const-closure-parse-not-item.rs
@@ -0,0 +1,10 @@
+// check-pass
+
+#![feature(const_trait_impl, const_closures)]
+#![allow(incomplete_features)]
+
+const fn test() -> impl ~const Fn() {
+ const move || {}
+}
+
+fn main() {}
diff --git a/tests/ui/rfc-2632-const-trait-impl/const_derives/derive-const-with-params.rs b/tests/ui/rfc-2632-const-trait-impl/const_derives/derive-const-with-params.rs
new file mode 100644
index 000000000..72edfbc97
--- /dev/null
+++ b/tests/ui/rfc-2632-const-trait-impl/const_derives/derive-const-with-params.rs
@@ -0,0 +1,13 @@
+// check-pass
+
+#![feature(derive_const)]
+#![feature(const_trait_impl)]
+
+#[derive_const(PartialEq)]
+pub struct Reverse<T>(T);
+
+const fn foo(a: Reverse<i32>, b: Reverse<i32>) -> bool {
+ a == b
+}
+
+fn main() {}
diff --git a/tests/ui/rfc-2632-const-trait-impl/do-not-const-check-override.rs b/tests/ui/rfc-2632-const-trait-impl/do-not-const-check-override.rs
new file mode 100644
index 000000000..730e268c0
--- /dev/null
+++ b/tests/ui/rfc-2632-const-trait-impl/do-not-const-check-override.rs
@@ -0,0 +1,19 @@
+// check-pass
+#![feature(const_trait_impl, rustc_attrs)]
+
+#[const_trait]
+trait Foo {
+ #[rustc_do_not_const_check]
+ fn into_iter(&self) { println!("FEAR ME!") }
+}
+
+
+impl const Foo for () {
+ fn into_iter(&self) {
+ // ^_^
+ }
+}
+
+const _: () = Foo::into_iter(&());
+
+fn main() {}
diff --git a/tests/ui/rfc-2632-const-trait-impl/do-not-const-check.rs b/tests/ui/rfc-2632-const-trait-impl/do-not-const-check.rs
new file mode 100644
index 000000000..3c39c53de
--- /dev/null
+++ b/tests/ui/rfc-2632-const-trait-impl/do-not-const-check.rs
@@ -0,0 +1,18 @@
+// check-pass
+#![feature(const_trait_impl, rustc_attrs)]
+
+#[const_trait]
+trait IntoIter {
+ fn into_iter(self);
+}
+
+#[const_trait]
+trait Hmm: Sized {
+ #[rustc_do_not_const_check]
+ fn chain<U>(self, other: U) where U: IntoIter,
+ {
+ other.into_iter()
+ }
+}
+
+fn main() {}
diff --git a/tests/ui/rfc-2632-const-trait-impl/function-pointer-does-not-require-const.rs b/tests/ui/rfc-2632-const-trait-impl/function-pointer-does-not-require-const.rs
new file mode 100644
index 000000000..1726cf82e
--- /dev/null
+++ b/tests/ui/rfc-2632-const-trait-impl/function-pointer-does-not-require-const.rs
@@ -0,0 +1,8 @@
+// check-pass
+
+type I32Cmp = fn(&i32, &i32) -> core::cmp::Ordering;
+pub const fn min_by_i32() -> fn(i32, i32, I32Cmp) -> i32 {
+ core::cmp::min_by
+}
+
+fn main() {}
diff --git a/tests/ui/rfcs/rfc-2396-target_feature-11/fn-ptr.mir.stderr b/tests/ui/rfcs/rfc-2396-target_feature-11/fn-ptr.mir.stderr
index cf5815df5..b0ac5dc44 100644
--- a/tests/ui/rfcs/rfc-2396-target_feature-11/fn-ptr.mir.stderr
+++ b/tests/ui/rfcs/rfc-2396-target_feature-11/fn-ptr.mir.stderr
@@ -11,7 +11,13 @@ LL | let foo: fn() = foo;
|
= note: expected fn pointer `fn()`
found fn item `fn() {foo}`
+ = note: fn items are distinct from fn pointers
= note: functions with `#[target_feature]` can only be coerced to `unsafe` function pointers
+ = note: when the arguments and return types match, functions can be coerced to function pointers
+help: consider casting to a fn pointer
+ |
+LL | let foo: fn() = foo as fn();
+ | ~~~~~~~~~~~
error: aborting due to previous error
diff --git a/tests/ui/rfcs/rfc-2396-target_feature-11/fn-ptr.thir.stderr b/tests/ui/rfcs/rfc-2396-target_feature-11/fn-ptr.thir.stderr
index cf5815df5..b0ac5dc44 100644
--- a/tests/ui/rfcs/rfc-2396-target_feature-11/fn-ptr.thir.stderr
+++ b/tests/ui/rfcs/rfc-2396-target_feature-11/fn-ptr.thir.stderr
@@ -11,7 +11,13 @@ LL | let foo: fn() = foo;
|
= note: expected fn pointer `fn()`
found fn item `fn() {foo}`
+ = note: fn items are distinct from fn pointers
= note: functions with `#[target_feature]` can only be coerced to `unsafe` function pointers
+ = note: when the arguments and return types match, functions can be coerced to function pointers
+help: consider casting to a fn pointer
+ |
+LL | let foo: fn() = foo as fn();
+ | ~~~~~~~~~~~
error: aborting due to previous error
diff --git a/tests/ui/rfcs/rfc-2528-type-changing-struct-update/feature-gate.stderr b/tests/ui/rfcs/rfc-2528-type-changing-struct-update/feature-gate.stderr
index 2217b8c04..48e46d3d1 100644
--- a/tests/ui/rfcs/rfc-2528-type-changing-struct-update/feature-gate.stderr
+++ b/tests/ui/rfcs/rfc-2528-type-changing-struct-update/feature-gate.stderr
@@ -11,7 +11,7 @@ error[E0308]: mismatched types
--> $DIR/feature-gate.rs:22:11
|
LL | ..m1
- | ^^ expected struct `State2`, found struct `State1`
+ | ^^ expected `Machine<State2>`, found `Machine<State1>`
|
= note: expected struct `Machine<State2>`
found struct `Machine<State1>`
diff --git a/tests/ui/rfcs/rfc-2528-type-changing-struct-update/issue-92010-trait-bound-not-satisfied.stderr b/tests/ui/rfcs/rfc-2528-type-changing-struct-update/issue-92010-trait-bound-not-satisfied.stderr
index 5957ea7c9..831731ba4 100644
--- a/tests/ui/rfcs/rfc-2528-type-changing-struct-update/issue-92010-trait-bound-not-satisfied.stderr
+++ b/tests/ui/rfcs/rfc-2528-type-changing-struct-update/issue-92010-trait-bound-not-satisfied.stderr
@@ -2,7 +2,7 @@ error[E0308]: mismatched types
--> $DIR/issue-92010-trait-bound-not-satisfied.rs:8:43
|
LL | fn y(&self, y: f64) -> Self { P{y, .. self.clone() } }
- | ^^^^^^^^^^^^ expected struct `P`, found `&P<T>`
+ | ^^^^^^^^^^^^ expected `P<T>`, found `&P<T>`
|
= note: expected struct `P<T>`
found reference `&P<T>`
diff --git a/tests/ui/rfcs/rfc-2528-type-changing-struct-update/lifetime-update.stderr b/tests/ui/rfcs/rfc-2528-type-changing-struct-update/lifetime-update.stderr
index 5f93ad6e0..1c26eb880 100644
--- a/tests/ui/rfcs/rfc-2528-type-changing-struct-update/lifetime-update.stderr
+++ b/tests/ui/rfcs/rfc-2528-type-changing-struct-update/lifetime-update.stderr
@@ -1,6 +1,9 @@
error[E0597]: `s` does not live long enough
--> $DIR/lifetime-update.rs:20:17
|
+LL | let s = String::from("hello");
+ | - binding `s` declared here
+...
LL | lt_str: &s,
| ^^ borrowed value does not live long enough
...
diff --git a/tests/ui/rfcs/rfc-2528-type-changing-struct-update/type-generic-update.stderr b/tests/ui/rfcs/rfc-2528-type-changing-struct-update/type-generic-update.stderr
index 6f31b1a96..f31b311c7 100644
--- a/tests/ui/rfcs/rfc-2528-type-changing-struct-update/type-generic-update.stderr
+++ b/tests/ui/rfcs/rfc-2528-type-changing-struct-update/type-generic-update.stderr
@@ -2,7 +2,7 @@ error[E0308]: mismatched types
--> $DIR/type-generic-update.rs:46:11
|
LL | ..m1
- | ^^ expected `i32`, found `f64`
+ | ^^ expected `Machine<'_, i32, f64>`, found `Machine<'_, f64, f64>`
|
= note: expected struct `Machine<'_, i32, _>`
found struct `Machine<'_, f64, _>`
@@ -11,7 +11,7 @@ error[E0308]: mismatched types
--> $DIR/type-generic-update.rs:51:11
|
LL | ..m1
- | ^^ expected `i32`, found `f64`
+ | ^^ expected `Machine<'_, i32, i32>`, found `Machine<'_, f64, f64>`
|
= note: expected struct `Machine<'_, i32, i32>`
found struct `Machine<'_, f64, f64>`
diff --git a/tests/ui/runtime/out-of-stack.rs b/tests/ui/runtime/out-of-stack.rs
index 6873abc49..ff45ace78 100644
--- a/tests/ui/runtime/out-of-stack.rs
+++ b/tests/ui/runtime/out-of-stack.rs
@@ -6,6 +6,7 @@
// ignore-emscripten no processes
// ignore-sgx no processes
// ignore-fuchsia must translate zircon signal to SIGABRT, FIXME (#58590)
+// ignore-nto no stack overflow handler used (no alternate stack available)
#![feature(core_intrinsics)]
#![feature(rustc_private)]
diff --git a/tests/ui/runtime/signal-alternate-stack-cleanup.rs b/tests/ui/runtime/signal-alternate-stack-cleanup.rs
index 8a6d73895..37c602ae0 100644
--- a/tests/ui/runtime/signal-alternate-stack-cleanup.rs
+++ b/tests/ui/runtime/signal-alternate-stack-cleanup.rs
@@ -7,6 +7,7 @@
// ignore-windows
// ignore-sgx no libc
// ignore-vxworks no SIGWINCH in user space
+// ignore-nto no SA_ONSTACK
#![feature(rustc_private)]
extern crate libc;
diff --git a/tests/ui/rust-2018/edition-lint-infer-outlives-multispan.rs b/tests/ui/rust-2018/edition-lint-infer-outlives-multispan.rs
index 0b3de0df2..d2254acb3 100644
--- a/tests/ui/rust-2018/edition-lint-infer-outlives-multispan.rs
+++ b/tests/ui/rust-2018/edition-lint-infer-outlives-multispan.rs
@@ -365,4 +365,24 @@ mod unions {
}
}
+// https://github.com/rust-lang/rust/issues/106870
+mod multiple_predicates_with_same_span {
+ macro_rules! m {
+ ($($name:ident)+) => {
+ struct Inline<'a, $($name: 'a,)+>(&'a ($($name,)+));
+ //~^ ERROR: outlives requirements can be inferred
+ struct FullWhere<'a, $($name,)+>(&'a ($($name,)+)) where $($name: 'a,)+;
+ //~^ ERROR: outlives requirements can be inferred
+ struct PartialWhere<'a, $($name,)+>(&'a ($($name,)+)) where (): Sized, $($name: 'a,)+;
+ //~^ ERROR: outlives requirements can be inferred
+ struct Interleaved<'a, $($name,)+>(&'a ($($name,)+))
+ where
+ (): Sized,
+ $($name: 'a, $name: 'a, )+ //~ ERROR: outlives requirements can be inferred
+ $($name: 'a, $name: 'a, )+;
+ }
+ }
+ m!(T0 T1 T2 T3 T4 T5 T6 T7 T8 T9 T10 T11 T12 T13 T14 T15);
+}
+
fn main() {}
diff --git a/tests/ui/rust-2018/edition-lint-infer-outlives-multispan.stderr b/tests/ui/rust-2018/edition-lint-infer-outlives-multispan.stderr
index 251d74094..f5ec287d2 100644
--- a/tests/ui/rust-2018/edition-lint-infer-outlives-multispan.stderr
+++ b/tests/ui/rust-2018/edition-lint-infer-outlives-multispan.stderr
@@ -819,5 +819,61 @@ LL - union BeeWhereAyTeeYooWhereOutlivesAyIsDebugBee<'a, 'b, T, U> where U:
LL + union BeeWhereAyTeeYooWhereOutlivesAyIsDebugBee<'a, 'b, T, U> where U: Debug, {
|
-error: aborting due to 68 previous errors
+error: outlives requirements can be inferred
+ --> $DIR/edition-lint-infer-outlives-multispan.rs:372:38
+ |
+LL | struct Inline<'a, $($name: 'a,)+>(&'a ($($name,)+));
+ | ^^^^ help: remove these bounds
+...
+LL | m!(T0 T1 T2 T3 T4 T5 T6 T7 T8 T9 T10 T11 T12 T13 T14 T15);
+ | --------------------------------------------------------- in this macro invocation
+ |
+ = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: outlives requirements can be inferred
+ --> $DIR/edition-lint-infer-outlives-multispan.rs:374:64
+ |
+LL | struct FullWhere<'a, $($name,)+>(&'a ($($name,)+)) where $($name: 'a,)+;
+ | ^^^^^^^^^^^^^^^^^^ help: remove these bounds
+...
+LL | m!(T0 T1 T2 T3 T4 T5 T6 T7 T8 T9 T10 T11 T12 T13 T14 T15);
+ | --------------------------------------------------------- in this macro invocation
+ |
+ = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: outlives requirements can be inferred
+ --> $DIR/edition-lint-infer-outlives-multispan.rs:376:86
+ |
+LL | struct PartialWhere<'a, $($name,)+>(&'a ($($name,)+)) where (): Sized, $($name: 'a,)+;
+ | ^^^^^^^^^ help: remove these bounds
+...
+LL | m!(T0 T1 T2 T3 T4 T5 T6 T7 T8 T9 T10 T11 T12 T13 T14 T15);
+ | --------------------------------------------------------- in this macro invocation
+ |
+ = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: outlives requirements can be inferred
+ --> $DIR/edition-lint-infer-outlives-multispan.rs:381:19
+ |
+LL | $($name: 'a, $name: 'a, )+
+ | ^^^^^^^^^ ^^^^^^^^^
+LL | $($name: 'a, $name: 'a, )+;
+ | ^^^^^^^^^ ^^^^^^^^^
+...
+LL | m!(T0 T1 T2 T3 T4 T5 T6 T7 T8 T9 T10 T11 T12 T13 T14 T15);
+ | ---------------------------------------------------------
+ | |
+ | 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)
+help: remove these bounds
+ |
+LL ~ $(, , )+
+LL ~ $(, , )+;
+ |
+
+error: aborting due to 72 previous errors
diff --git a/tests/ui/rust-2018/edition-lint-infer-outlives.fixed b/tests/ui/rust-2018/edition-lint-infer-outlives.fixed
index 13645244d..868bdf2e0 100644
--- a/tests/ui/rust-2018/edition-lint-infer-outlives.fixed
+++ b/tests/ui/rust-2018/edition-lint-infer-outlives.fixed
@@ -791,5 +791,14 @@ struct StaticRef<T: 'static> {
field: &'static T
}
+struct TrailingCommaInWhereClause<'a, T, U>
+where
+ T: 'a,
+
+ //~^ ERROR outlives requirements can be inferred
+{
+ tee: T,
+ yoo: &'a U
+}
fn main() {}
diff --git a/tests/ui/rust-2018/edition-lint-infer-outlives.rs b/tests/ui/rust-2018/edition-lint-infer-outlives.rs
index d9486ba66..75783764a 100644
--- a/tests/ui/rust-2018/edition-lint-infer-outlives.rs
+++ b/tests/ui/rust-2018/edition-lint-infer-outlives.rs
@@ -791,5 +791,14 @@ struct StaticRef<T: 'static> {
field: &'static T
}
+struct TrailingCommaInWhereClause<'a, T, U>
+where
+ T: 'a,
+ U: 'a,
+ //~^ ERROR outlives requirements can be inferred
+{
+ tee: T,
+ yoo: &'a U
+}
fn main() {}
diff --git a/tests/ui/rust-2018/edition-lint-infer-outlives.stderr b/tests/ui/rust-2018/edition-lint-infer-outlives.stderr
index faa9f21e3..e655fb484 100644
--- a/tests/ui/rust-2018/edition-lint-infer-outlives.stderr
+++ b/tests/ui/rust-2018/edition-lint-infer-outlives.stderr
@@ -1,8 +1,8 @@
error: outlives requirements can be inferred
- --> $DIR/edition-lint-infer-outlives.rs:26:31
+ --> $DIR/edition-lint-infer-outlives.rs:797:5
|
-LL | struct TeeOutlivesAy<'a, T: 'a> {
- | ^^^^ help: remove this bound
+LL | U: 'a,
+ | ^^^^^^ help: remove this bound
|
note: the lint level is defined here
--> $DIR/edition-lint-infer-outlives.rs:4:9
@@ -11,6 +11,12 @@ LL | #![deny(explicit_outlives_requirements)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: outlives requirements can be inferred
+ --> $DIR/edition-lint-infer-outlives.rs:26:31
+ |
+LL | struct TeeOutlivesAy<'a, T: 'a> {
+ | ^^^^ help: remove this bound
+
+error: outlives requirements can be inferred
--> $DIR/edition-lint-infer-outlives.rs:31:40
|
LL | struct TeeOutlivesAyIsDebug<'a, T: 'a + Debug> {
@@ -916,5 +922,5 @@ error: outlives requirements can be inferred
LL | union BeeWhereOutlivesAyTeeWhereDebug<'a, 'b, T> where 'b: 'a, T: Debug {
| ^^^^^^^^ help: remove this bound
-error: aborting due to 152 previous errors
+error: aborting due to 153 previous errors
diff --git a/tests/ui/rust-2018/remove-extern-crate.fixed b/tests/ui/rust-2018/remove-extern-crate.fixed
index 832632268..15e0ccc52 100644
--- a/tests/ui/rust-2018/remove-extern-crate.fixed
+++ b/tests/ui/rust-2018/remove-extern-crate.fixed
@@ -23,6 +23,7 @@ extern crate alloc;
fn main() {
another_name::mem::drop(3);
another::foo();
+ with_visibility::foo();
remove_extern_crate::foo!();
bar!();
alloc::vec![5];
@@ -37,3 +38,12 @@ mod another {
remove_extern_crate::foo!();
}
}
+
+mod with_visibility {
+ pub use core; //~ WARNING `extern crate` is not idiomatic
+
+ pub fn foo() {
+ core::mem::drop(4);
+ remove_extern_crate::foo!();
+ }
+}
diff --git a/tests/ui/rust-2018/remove-extern-crate.rs b/tests/ui/rust-2018/remove-extern-crate.rs
index bbb84cd46..aec0bc7c3 100644
--- a/tests/ui/rust-2018/remove-extern-crate.rs
+++ b/tests/ui/rust-2018/remove-extern-crate.rs
@@ -23,6 +23,7 @@ extern crate alloc;
fn main() {
another_name::mem::drop(3);
another::foo();
+ with_visibility::foo();
remove_extern_crate::foo!();
bar!();
alloc::vec![5];
@@ -37,3 +38,12 @@ mod another {
remove_extern_crate::foo!();
}
}
+
+mod with_visibility {
+ pub extern crate core; //~ WARNING `extern crate` is not idiomatic
+
+ pub fn foo() {
+ core::mem::drop(4);
+ remove_extern_crate::foo!();
+ }
+}
diff --git a/tests/ui/rust-2018/remove-extern-crate.stderr b/tests/ui/rust-2018/remove-extern-crate.stderr
index bde4c1808..d07358e47 100644
--- a/tests/ui/rust-2018/remove-extern-crate.stderr
+++ b/tests/ui/rust-2018/remove-extern-crate.stderr
@@ -12,10 +12,26 @@ LL | #![warn(rust_2018_idioms)]
= note: `#[warn(unused_extern_crates)]` implied by `#[warn(rust_2018_idioms)]`
warning: `extern crate` is not idiomatic in the new edition
- --> $DIR/remove-extern-crate.rs:32:5
+ --> $DIR/remove-extern-crate.rs:33:5
|
LL | extern crate core;
- | ^^^^^^^^^^^^^^^^^^ help: convert it to a `use`
+ | ^^^^^^^^^^^^^^^^^^
+ |
+help: convert it to a `use`
+ |
+LL | use core;
+ | ~~~
+
+warning: `extern crate` is not idiomatic in the new edition
+ --> $DIR/remove-extern-crate.rs:43:5
+ |
+LL | pub extern crate core;
+ | ^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: convert it to a `use`
+ |
+LL | pub use core;
+ | ~~~
-warning: 2 warnings emitted
+warning: 3 warnings emitted
diff --git a/tests/ui/sanitize/cfg-kasan.rs b/tests/ui/sanitize/cfg-kasan.rs
new file mode 100644
index 000000000..d721011f3
--- /dev/null
+++ b/tests/ui/sanitize/cfg-kasan.rs
@@ -0,0 +1,28 @@
+// Verifies that when compiling with -Zsanitizer=kernel-address,
+// the `#[cfg(sanitize = "address")]` attribute is configured.
+
+// check-pass
+// compile-flags: -Zsanitizer=kernel-address --cfg kernel_address
+// revisions: aarch64 riscv64imac riscv64gc x86_64
+//[aarch64] compile-flags: --target aarch64-unknown-none
+//[aarch64] needs-llvm-components: aarch64
+//[riscv64imac] compile-flags: --target riscv64imac-unknown-none-elf
+//[riscv64imac] needs-llvm-components: riscv
+//[riscv64imac] min-llvm-version: 16
+//[riscv64gc] compile-flags: --target riscv64gc-unknown-none-elf
+//[riscv64gc] needs-llvm-components: riscv
+//[riscv64gc] min-llvm-version: 16
+//[x86_64] compile-flags: --target x86_64-unknown-none
+//[x86_64] needs-llvm-components: x86
+
+#![crate_type = "rlib"]
+#![feature(cfg_sanitize, no_core, lang_items)]
+#![no_core]
+
+#[lang = "sized"]
+trait Sized {}
+
+const _: fn() -> () = main;
+
+#[cfg(all(sanitize = "address", kernel_address))]
+fn main() {}
diff --git a/tests/ui/sanitize/memory-eager.rs b/tests/ui/sanitize/memory-eager.rs
index 0018c2f75..0e992b4a5 100644
--- a/tests/ui/sanitize/memory-eager.rs
+++ b/tests/ui/sanitize/memory-eager.rs
@@ -1,6 +1,5 @@
// needs-sanitizer-support
// needs-sanitizer-memory
-// min-llvm-version: 14.0.0
//
// revisions: unoptimized optimized
//
diff --git a/tests/ui/save-analysis/emit-notifications.polonius.stderr b/tests/ui/save-analysis/emit-notifications.polonius.stderr
deleted file mode 100644
index a1a1b8c63..000000000
--- a/tests/ui/save-analysis/emit-notifications.polonius.stderr
+++ /dev/null
@@ -1,2 +0,0 @@
-{"artifact":"$TEST_BUILD_DIR/save-analysis/emit-notifications.polonius/save-analysis/libemit_notifications.json","emit":"save-analysis"}
-{"artifact":"$TEST_BUILD_DIR/save-analysis/emit-notifications.polonius/libemit_notifications.rlib","emit":"link"}
diff --git a/tests/ui/save-analysis/emit-notifications.rs b/tests/ui/save-analysis/emit-notifications.rs
deleted file mode 100644
index 9179944a6..000000000
--- a/tests/ui/save-analysis/emit-notifications.rs
+++ /dev/null
@@ -1,7 +0,0 @@
-// build-pass (FIXME(62277): could be check-pass?)
-// compile-flags: -Zsave-analysis --json artifacts
-// compile-flags: --crate-type rlib --error-format=json
-// ignore-pass
-// ^-- needed because otherwise, the .stderr file changes with --pass check
-
-pub fn foo() {}
diff --git a/tests/ui/save-analysis/emit-notifications.stderr b/tests/ui/save-analysis/emit-notifications.stderr
deleted file mode 100644
index e16f60f8b..000000000
--- a/tests/ui/save-analysis/emit-notifications.stderr
+++ /dev/null
@@ -1,2 +0,0 @@
-{"artifact":"$TEST_BUILD_DIR/save-analysis/emit-notifications/save-analysis/libemit_notifications.json","emit":"save-analysis"}
-{"artifact":"$TEST_BUILD_DIR/save-analysis/emit-notifications/libemit_notifications.rlib","emit":"link"}
diff --git a/tests/ui/save-analysis/issue-26459.rs b/tests/ui/save-analysis/issue-26459.rs
deleted file mode 100644
index 2ba05a0a4..000000000
--- a/tests/ui/save-analysis/issue-26459.rs
+++ /dev/null
@@ -1,8 +0,0 @@
-// compile-flags: -Zsave-analysis
-
-fn main() {
- match 'a' {
- char{ch} => true
- //~^ ERROR expected struct, variant or union type, found builtin type `char`
- };
-}
diff --git a/tests/ui/save-analysis/issue-26459.stderr b/tests/ui/save-analysis/issue-26459.stderr
deleted file mode 100644
index 9f594990c..000000000
--- a/tests/ui/save-analysis/issue-26459.stderr
+++ /dev/null
@@ -1,9 +0,0 @@
-error[E0574]: expected struct, variant or union type, found builtin type `char`
- --> $DIR/issue-26459.rs:5:9
- |
-LL | char{ch} => true
- | ^^^^ not a struct, variant or union type
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0574`.
diff --git a/tests/ui/save-analysis/issue-37323.rs b/tests/ui/save-analysis/issue-37323.rs
deleted file mode 100644
index 55f5c5a95..000000000
--- a/tests/ui/save-analysis/issue-37323.rs
+++ /dev/null
@@ -1,20 +0,0 @@
-// check-pass
-// compile-flags: -Zsave-analysis
-
-#![feature(rustc_attrs)]
-#![allow(warnings)]
-
-#[derive(Debug)]
-struct Point {
-}
-
-struct NestedA<'a, 'b> {
- x: &'a NestedB<'b>
-}
-
-struct NestedB<'a> {
- x: &'a i32,
-}
-
-fn main() {
-}
diff --git a/tests/ui/save-analysis/issue-59134-0.rs b/tests/ui/save-analysis/issue-59134-0.rs
deleted file mode 100644
index a0871ca18..000000000
--- a/tests/ui/save-analysis/issue-59134-0.rs
+++ /dev/null
@@ -1,12 +0,0 @@
-// compile-flags: -Zsave-analysis
-
-// Check that this doesn't ICE when processing associated const (field expr).
-
-pub fn f() {
- trait Trait {}
- impl dyn Trait {
- const FLAG: u32 = bogus.field; //~ ERROR cannot find value `bogus`
- }
-}
-
-fn main() {}
diff --git a/tests/ui/save-analysis/issue-59134-0.stderr b/tests/ui/save-analysis/issue-59134-0.stderr
deleted file mode 100644
index 4e9b2e6fd..000000000
--- a/tests/ui/save-analysis/issue-59134-0.stderr
+++ /dev/null
@@ -1,9 +0,0 @@
-error[E0425]: cannot find value `bogus` in this scope
- --> $DIR/issue-59134-0.rs:8:27
- |
-LL | const FLAG: u32 = bogus.field;
- | ^^^^^ not found in this scope
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0425`.
diff --git a/tests/ui/save-analysis/issue-59134-1.rs b/tests/ui/save-analysis/issue-59134-1.rs
deleted file mode 100644
index 3cb629777..000000000
--- a/tests/ui/save-analysis/issue-59134-1.rs
+++ /dev/null
@@ -1,12 +0,0 @@
-// compile-flags: -Zsave-analysis
-
-// Check that this doesn't ICE when processing associated const (type).
-
-fn func() {
- trait Trait {
- type MyType;
- const CONST: Self::MyType = bogus.field; //~ ERROR cannot find value `bogus`
- }
-}
-
-fn main() {}
diff --git a/tests/ui/save-analysis/issue-59134-1.stderr b/tests/ui/save-analysis/issue-59134-1.stderr
deleted file mode 100644
index bdc335eaa..000000000
--- a/tests/ui/save-analysis/issue-59134-1.stderr
+++ /dev/null
@@ -1,9 +0,0 @@
-error[E0425]: cannot find value `bogus` in this scope
- --> $DIR/issue-59134-1.rs:8:37
- |
-LL | const CONST: Self::MyType = bogus.field;
- | ^^^^^ not found in this scope
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0425`.
diff --git a/tests/ui/save-analysis/issue-63663.rs b/tests/ui/save-analysis/issue-63663.rs
deleted file mode 100644
index 92e85884f..000000000
--- a/tests/ui/save-analysis/issue-63663.rs
+++ /dev/null
@@ -1,28 +0,0 @@
-// check-pass
-// compile-flags: -Zsave-analysis
-
-pub trait Trait {
- type Assoc;
-}
-
-pub struct A;
-
-trait Generic<T> {}
-impl<T> Generic<T> for () {}
-
-// Don't ICE when resolving type paths in return type `impl Trait`
-fn assoc_in_opaque_type_bounds<U: Trait>() -> impl Generic<U::Assoc> {}
-
-// Check that this doesn't ICE when processing associated const in formal
-// argument and return type of functions defined inside function/method scope.
-pub fn func() {
- fn _inner1<U: Trait>(_: U::Assoc) {}
- fn _inner2<U: Trait>() -> U::Assoc { unimplemented!() }
-
- impl A {
- fn _inner1<U: Trait>(self, _: U::Assoc) {}
- fn _inner2<U: Trait>(self) -> U::Assoc { unimplemented!() }
- }
-}
-
-fn main() {}
diff --git a/tests/ui/save-analysis/issue-64659.rs b/tests/ui/save-analysis/issue-64659.rs
deleted file mode 100644
index a3d88a203..000000000
--- a/tests/ui/save-analysis/issue-64659.rs
+++ /dev/null
@@ -1,10 +0,0 @@
-// check-pass
-// compile-flags: -Zsave-analysis
-
-trait Trait { type Assoc; }
-
-fn main() {
- struct Data<T: Trait> {
- x: T::Assoc,
- }
-}
diff --git a/tests/ui/save-analysis/issue-65411.rs b/tests/ui/save-analysis/issue-65411.rs
deleted file mode 100644
index 9e58b8da5..000000000
--- a/tests/ui/save-analysis/issue-65411.rs
+++ /dev/null
@@ -1,15 +0,0 @@
-// check-pass
-// compile-flags: -Zsave-analysis
-
-trait Trait { type Assoc; }
-trait GenericTrait<T> {}
-struct Wrapper<B> { b: B }
-
-fn func() {
- // Processing associated path in impl block definition inside a function
- // body does not ICE
- impl<B: Trait> GenericTrait<B::Assoc> for Wrapper<B> {}
-}
-
-
-fn main() {}
diff --git a/tests/ui/save-analysis/issue-65590.rs b/tests/ui/save-analysis/issue-65590.rs
deleted file mode 100644
index 27874f865..000000000
--- a/tests/ui/save-analysis/issue-65590.rs
+++ /dev/null
@@ -1,21 +0,0 @@
-// check-pass
-// compile-flags: -Zsave-analysis
-// edition:2018
-
-// Async desugaring for return types in (associated) functions introduces a
-// separate definition internally, which we need to take into account
-// (or else we ICE).
-trait Trait { type Assoc; }
-struct Struct;
-
-async fn foobar<T: Trait>() -> T::Assoc {
- unimplemented!()
-}
-
-impl Struct {
- async fn foo<T: Trait>(&self) -> T::Assoc {
- unimplemented!()
- }
-}
-
-fn main() {}
diff --git a/tests/ui/save-analysis/issue-68621.rs b/tests/ui/save-analysis/issue-68621.rs
deleted file mode 100644
index 30479580f..000000000
--- a/tests/ui/save-analysis/issue-68621.rs
+++ /dev/null
@@ -1,17 +0,0 @@
-// compile-flags: -Zsave-analysis
-
-#![feature(type_alias_impl_trait)]
-
-trait Trait {}
-
-trait Service {
- type Future: Trait;
-}
-
-struct Struct;
-
-impl Service for Struct {
- type Future = impl Trait; //~ ERROR: unconstrained opaque type
-}
-
-fn main() {}
diff --git a/tests/ui/save-analysis/issue-68621.stderr b/tests/ui/save-analysis/issue-68621.stderr
deleted file mode 100644
index 4452ee791..000000000
--- a/tests/ui/save-analysis/issue-68621.stderr
+++ /dev/null
@@ -1,10 +0,0 @@
-error: unconstrained opaque type
- --> $DIR/issue-68621.rs:14:19
- |
-LL | type Future = impl Trait;
- | ^^^^^^^^^^
- |
- = note: `Future` must be used in combination with a concrete type within the same impl
-
-error: aborting due to previous error
-
diff --git a/tests/ui/save-analysis/issue-72267.rs b/tests/ui/save-analysis/issue-72267.rs
deleted file mode 100644
index eea0a7fea..000000000
--- a/tests/ui/save-analysis/issue-72267.rs
+++ /dev/null
@@ -1,7 +0,0 @@
-// compile-flags: -Z save-analysis
-
-fn main() {
- let _: Box<(dyn ?Sized)>;
- //~^ ERROR `?Trait` is not permitted in trait object types
- //~| ERROR at least one trait is required for an object type
-}
diff --git a/tests/ui/save-analysis/issue-72267.stderr b/tests/ui/save-analysis/issue-72267.stderr
deleted file mode 100644
index 76fc6c57c..000000000
--- a/tests/ui/save-analysis/issue-72267.stderr
+++ /dev/null
@@ -1,15 +0,0 @@
-error: `?Trait` is not permitted in trait object types
- --> $DIR/issue-72267.rs:4:21
- |
-LL | let _: Box<(dyn ?Sized)>;
- | ^^^^^^
-
-error[E0224]: at least one trait is required for an object type
- --> $DIR/issue-72267.rs:4:17
- |
-LL | let _: Box<(dyn ?Sized)>;
- | ^^^^^^^^^^
-
-error: aborting due to 2 previous errors
-
-For more information about this error, try `rustc --explain E0224`.
diff --git a/tests/ui/save-analysis/issue-73020.rs b/tests/ui/save-analysis/issue-73020.rs
deleted file mode 100644
index 87ce09336..000000000
--- a/tests/ui/save-analysis/issue-73020.rs
+++ /dev/null
@@ -1,5 +0,0 @@
-// compile-flags: -Zsave-analysis
-use {self}; //~ ERROR E0431
-
-fn main () {
-}
diff --git a/tests/ui/save-analysis/issue-73020.stderr b/tests/ui/save-analysis/issue-73020.stderr
deleted file mode 100644
index 5bb3aae99..000000000
--- a/tests/ui/save-analysis/issue-73020.stderr
+++ /dev/null
@@ -1,9 +0,0 @@
-error[E0431]: `self` import can only appear in an import list with a non-empty prefix
- --> $DIR/issue-73020.rs:2:6
- |
-LL | use {self};
- | ^^^^ can only appear in an import list with a non-empty prefix
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0431`.
diff --git a/tests/ui/save-analysis/issue-73022.rs b/tests/ui/save-analysis/issue-73022.rs
deleted file mode 100644
index 9ad89a319..000000000
--- a/tests/ui/save-analysis/issue-73022.rs
+++ /dev/null
@@ -1,13 +0,0 @@
-// build-pass
-// compile-flags: -Zsave-analysis
-enum Enum2 {
- Variant8 { _field: bool },
-}
-
-impl Enum2 {
- fn new_variant8() -> Enum2 {
- Self::Variant8 { _field: true }
- }
-}
-
-fn main() {}
diff --git a/tests/ui/save-analysis/issue-89066.rs b/tests/ui/save-analysis/issue-89066.rs
deleted file mode 100644
index c65e2d73f..000000000
--- a/tests/ui/save-analysis/issue-89066.rs
+++ /dev/null
@@ -1,28 +0,0 @@
-// compile-flags: -Zsave-analysis
-
-// Check that this does not ICE.
-// Stolen from tests/ui/const-generics/generic_arg_infer/infer-arg-test.rs
-
-#![feature(generic_arg_infer)]
-
-struct All<'a, T, const N: usize> {
- v: &'a T,
-}
-
-struct BadInfer<_>;
-//~^ ERROR expected identifier
-//~| ERROR parameter `_` is never used
-
-fn all_fn<'a, T, const N: usize>() {}
-
-fn bad_infer_fn<_>() {}
-//~^ ERROR expected identifier
-
-
-fn main() {
- let a: All<_, _, _>;
- //~^ ERROR this struct takes 2 generic arguments but 3 generic arguments were supplied
- all_fn();
- let v: [u8; _];
- let v: [u8; 10] = [0; _];
-}
diff --git a/tests/ui/save-analysis/issue-89066.stderr b/tests/ui/save-analysis/issue-89066.stderr
deleted file mode 100644
index 5ef04936e..000000000
--- a/tests/ui/save-analysis/issue-89066.stderr
+++ /dev/null
@@ -1,39 +0,0 @@
-error: expected identifier, found reserved identifier `_`
- --> $DIR/issue-89066.rs:12:17
- |
-LL | struct BadInfer<_>;
- | ^ expected identifier, found reserved identifier
-
-error: expected identifier, found reserved identifier `_`
- --> $DIR/issue-89066.rs:18:17
- |
-LL | fn bad_infer_fn<_>() {}
- | ^ expected identifier, found reserved identifier
-
-error[E0392]: parameter `_` is never used
- --> $DIR/issue-89066.rs:12:17
- |
-LL | struct BadInfer<_>;
- | ^ unused parameter
- |
- = help: consider removing `_`, referring to it in a field, or using a marker such as `PhantomData`
- = help: if you intended `_` to be a const parameter, use `const _: usize` instead
-
-error[E0107]: this struct takes 2 generic arguments but 3 generic arguments were supplied
- --> $DIR/issue-89066.rs:23:10
- |
-LL | let a: All<_, _, _>;
- | ^^^ - help: remove this generic argument
- | |
- | expected 2 generic arguments
- |
-note: struct defined here, with 2 generic parameters: `T`, `N`
- --> $DIR/issue-89066.rs:8:8
- |
-LL | struct All<'a, T, const N: usize> {
- | ^^^ - --------------
-
-error: aborting due to 4 previous errors
-
-Some errors have detailed explanations: E0107, E0392.
-For more information about an error, try `rustc --explain E0107`.
diff --git a/tests/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.stderr b/tests/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.stderr
index eb3d3e4a6..944cdc5f5 100644
--- a/tests/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.stderr
+++ b/tests/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.stderr
@@ -2,8 +2,9 @@ error[E0700]: hidden type for `impl Clone` captures lifetime that does not appea
--> $DIR/arbitrary_self_types_pin_lifetime_impl_trait-async.rs:8:48
|
LL | async fn f(self: Pin<&Self>) -> impl Clone { self }
- | ----- ^^^^^^^^
- | |
+ | ----- ---------- ^^^^^^^^
+ | | |
+ | | opaque type defined here
| hidden type `Pin<&Foo>` captures the anonymous lifetime defined here
|
help: to declare that `impl Clone` captures `'_`, you can add an explicit `'_` lifetime bound
diff --git a/tests/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.stderr b/tests/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.stderr
index 2c0b2a0d9..8a9b397ca 100644
--- a/tests/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.stderr
+++ b/tests/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.stderr
@@ -2,8 +2,9 @@ error[E0700]: hidden type for `impl Clone` captures lifetime that does not appea
--> $DIR/arbitrary_self_types_pin_lifetime_impl_trait.rs:6:44
|
LL | fn f(self: Pin<&Self>) -> impl Clone { self }
- | ----- ^^^^
- | |
+ | ----- ---------- ^^^^
+ | | |
+ | | opaque type defined here
| hidden type `Pin<&Foo>` captures the anonymous lifetime defined here
|
help: to declare that `impl Clone` captures `'_`, you can add an explicit `'_` lifetime bound
diff --git a/tests/ui/self/arbitrary_self_types_pin_lifetime_mismatch-async.stderr b/tests/ui/self/arbitrary_self_types_pin_lifetime_mismatch-async.stderr
index 6180e1e0f..0b4c0a7fe 100644
--- a/tests/ui/self/arbitrary_self_types_pin_lifetime_mismatch-async.stderr
+++ b/tests/ui/self/arbitrary_self_types_pin_lifetime_mismatch-async.stderr
@@ -2,7 +2,7 @@ error: lifetime may not live long enough
--> $DIR/arbitrary_self_types_pin_lifetime_mismatch-async.rs:8:52
|
LL | async fn a(self: Pin<&Foo>, f: &Foo) -> &Foo { f }
- | - - ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+ | - - ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
| | |
| | let's call the lifetime of this reference `'1`
| let's call the lifetime of this reference `'2`
@@ -16,7 +16,7 @@ error: lifetime may not live long enough
--> $DIR/arbitrary_self_types_pin_lifetime_mismatch-async.rs:11:75
|
LL | async fn c(self: Pin<&Self>, f: &Foo, g: &Foo) -> (Pin<&Foo>, &Foo) { (self, f) }
- | - - ^^^^^^^^^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+ | - - ^^^^^^^^^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
| | |
| | let's call the lifetime of this reference `'1`
| let's call the lifetime of this reference `'2`
@@ -30,7 +30,7 @@ error: lifetime may not live long enough
--> $DIR/arbitrary_self_types_pin_lifetime_mismatch-async.rs:17:64
|
LL | async fn bar<'a>(self: Alias<&Self>, arg: &'a ()) -> &() { arg }
- | -- - ^^^ associated function was supposed to return data with lifetime `'1` but it is returning data with lifetime `'a`
+ | -- - ^^^ method was supposed to return data with lifetime `'1` but it is returning data with lifetime `'a`
| | |
| | let's call the lifetime of this reference `'1`
| lifetime `'a` defined here
diff --git a/tests/ui/self/arbitrary_self_types_pin_lifetime_mismatch.stderr b/tests/ui/self/arbitrary_self_types_pin_lifetime_mismatch.stderr
index fccee5d43..209dae9c1 100644
--- a/tests/ui/self/arbitrary_self_types_pin_lifetime_mismatch.stderr
+++ b/tests/ui/self/arbitrary_self_types_pin_lifetime_mismatch.stderr
@@ -2,7 +2,7 @@ error: lifetime may not live long enough
--> $DIR/arbitrary_self_types_pin_lifetime_mismatch.rs:6:46
|
LL | fn a(self: Pin<&Foo>, f: &Foo) -> &Foo { f }
- | - - ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+ | - - ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
| | |
| | let's call the lifetime of this reference `'1`
| let's call the lifetime of this reference `'2`
@@ -16,7 +16,7 @@ error: lifetime may not live long enough
--> $DIR/arbitrary_self_types_pin_lifetime_mismatch.rs:9:69
|
LL | fn c(self: Pin<&Self>, f: &Foo, g: &Foo) -> (Pin<&Foo>, &Foo) { (self, f) }
- | - - ^^^^^^^^^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+ | - - ^^^^^^^^^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
| | |
| | let's call the lifetime of this reference `'1`
| let's call the lifetime of this reference `'2`
@@ -30,7 +30,7 @@ error: lifetime may not live long enough
--> $DIR/arbitrary_self_types_pin_lifetime_mismatch.rs:15:58
|
LL | fn bar<'a>(self: Alias<&Self>, arg: &'a ()) -> &() { arg }
- | -- ---- has type `Pin<&'1 Foo>` ^^^ associated function was supposed to return data with lifetime `'1` but it is returning data with lifetime `'a`
+ | -- ---- has type `Pin<&'1 Foo>` ^^^ method was supposed to return data with lifetime `'1` but it is returning data with lifetime `'a`
| |
| lifetime `'a` defined here
diff --git a/tests/ui/self/arbitrary_self_types_pointers_and_wrappers.rs b/tests/ui/self/arbitrary_self_types_pointers_and_wrappers.rs
index 65fec3bec..91aacedfc 100644
--- a/tests/ui/self/arbitrary_self_types_pointers_and_wrappers.rs
+++ b/tests/ui/self/arbitrary_self_types_pointers_and_wrappers.rs
@@ -3,6 +3,7 @@
#![feature(rustc_attrs)]
use std::{
+ cell::Cell,
ops::{Deref, CoerceUnsized, DispatchFromDyn},
marker::Unsize,
};
@@ -20,6 +21,20 @@ impl<T: ?Sized> Deref for Ptr<T> {
impl<T: Unsize<U> + ?Sized, U: ?Sized> CoerceUnsized<Ptr<U>> for Ptr<T> {}
impl<T: Unsize<U> + ?Sized, U: ?Sized> DispatchFromDyn<Ptr<U>> for Ptr<T> {}
+
+struct CellPtr<'a, T: ?Sized>(Cell<&'a T>);
+
+impl<'a, T: ?Sized> Deref for CellPtr<'a, T> {
+ type Target = T;
+
+ fn deref(&self) -> &T {
+ self.0.get()
+ }
+}
+
+impl<'a, T: Unsize<U> + ?Sized, U: ?Sized> CoerceUnsized<CellPtr<'a, U>> for CellPtr<'a, T> {}
+impl<'a, T: Unsize<U> + ?Sized, U: ?Sized> DispatchFromDyn<CellPtr<'a, U>> for CellPtr<'a, T> {}
+
struct Wrapper<T: ?Sized>(T);
impl<T: ?Sized> Deref for Wrapper<T> {
@@ -42,6 +57,7 @@ trait Trait {
fn ptr_wrapper(self: Ptr<Wrapper<Self>>) -> i32;
fn wrapper_ptr(self: Wrapper<Ptr<Self>>) -> i32;
fn wrapper_ptr_wrapper(self: Wrapper<Ptr<Wrapper<Self>>>) -> i32;
+ fn cell(self: CellPtr<Self>) -> i32;
}
impl Trait for i32 {
@@ -54,6 +70,9 @@ impl Trait for i32 {
fn wrapper_ptr_wrapper(self: Wrapper<Ptr<Wrapper<Self>>>) -> i32 {
***self
}
+ fn cell(self: CellPtr<Self>) -> i32 {
+ *self
+ }
}
fn main() {
@@ -65,4 +84,7 @@ fn main() {
let wpw = Wrapper(Ptr(Box::new(Wrapper(7)))) as Wrapper<Ptr<Wrapper<dyn Trait>>>;
assert_eq!(wpw.wrapper_ptr_wrapper(), 7);
+
+ let c = CellPtr(Cell::new(&8)) as CellPtr<dyn Trait>;
+ assert_eq!(c.cell(), 8);
}
diff --git a/tests/ui/self/elision/lt-ref-self-async.stderr b/tests/ui/self/elision/lt-ref-self-async.stderr
index 787afd4dc..29d60ed66 100644
--- a/tests/ui/self/elision/lt-ref-self-async.stderr
+++ b/tests/ui/self/elision/lt-ref-self-async.stderr
@@ -6,7 +6,7 @@ LL | async fn ref_self(&self, f: &u32) -> &u32 {
| |
| let's call the lifetime of this reference `'2`
LL | f
- | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+ | ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
|
help: consider introducing a named lifetime parameter and update trait if needed
|
@@ -21,7 +21,7 @@ LL | async fn ref_Self(self: &Self, f: &u32) -> &u32 {
| |
| let's call the lifetime of this reference `'2`
LL | f
- | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+ | ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
|
help: consider introducing a named lifetime parameter and update trait if needed
|
@@ -36,7 +36,7 @@ LL | async fn box_ref_Self(self: Box<&Self>, f: &u32) -> &u32 {
| |
| let's call the lifetime of this reference `'2`
LL | f
- | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+ | ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
|
help: consider introducing a named lifetime parameter and update trait if needed
|
@@ -51,7 +51,7 @@ LL | async fn pin_ref_Self(self: Pin<&Self>, f: &u32) -> &u32 {
| |
| let's call the lifetime of this reference `'2`
LL | f
- | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+ | ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
|
help: consider introducing a named lifetime parameter and update trait if needed
|
@@ -66,7 +66,7 @@ LL | async fn box_box_ref_Self(self: Box<Box<&Self>>, f: &u32) -> &u32 {
| |
| let's call the lifetime of this reference `'2`
LL | f
- | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+ | ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
|
help: consider introducing a named lifetime parameter and update trait if needed
|
@@ -81,7 +81,7 @@ LL | async fn box_pin_Self(self: Box<Pin<&Self>>, f: &u32) -> &u32 {
| |
| let's call the lifetime of this reference `'2`
LL | f
- | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+ | ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
|
help: consider introducing a named lifetime parameter and update trait if needed
|
diff --git a/tests/ui/self/elision/lt-ref-self.stderr b/tests/ui/self/elision/lt-ref-self.stderr
index 49af638e4..216737a2c 100644
--- a/tests/ui/self/elision/lt-ref-self.stderr
+++ b/tests/ui/self/elision/lt-ref-self.stderr
@@ -6,7 +6,7 @@ LL | fn ref_self(&self, f: &u32) -> &u32 {
| |
| let's call the lifetime of this reference `'2`
LL | f
- | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+ | ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
|
help: consider introducing a named lifetime parameter and update trait if needed
|
@@ -21,7 +21,7 @@ LL | fn ref_Self(self: &Self, f: &u32) -> &u32 {
| |
| let's call the lifetime of this reference `'2`
LL | f
- | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+ | ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
|
help: consider introducing a named lifetime parameter and update trait if needed
|
@@ -36,7 +36,7 @@ LL | fn box_ref_Self(self: Box<&Self>, f: &u32) -> &u32 {
| |
| let's call the lifetime of this reference `'2`
LL | f
- | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+ | ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
|
help: consider introducing a named lifetime parameter and update trait if needed
|
@@ -51,7 +51,7 @@ LL | fn pin_ref_Self(self: Pin<&Self>, f: &u32) -> &u32 {
| |
| let's call the lifetime of this reference `'2`
LL | f
- | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+ | ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
|
help: consider introducing a named lifetime parameter and update trait if needed
|
@@ -66,7 +66,7 @@ LL | fn box_box_ref_Self(self: Box<Box<&Self>>, f: &u32) -> &u32 {
| |
| let's call the lifetime of this reference `'2`
LL | f
- | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+ | ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
|
help: consider introducing a named lifetime parameter and update trait if needed
|
@@ -81,7 +81,7 @@ LL | fn box_pin_Self(self: Box<Pin<&Self>>, f: &u32) -> &u32 {
| |
| let's call the lifetime of this reference `'2`
LL | f
- | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+ | ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
|
help: consider introducing a named lifetime parameter and update trait if needed
|
diff --git a/tests/ui/self/elision/ref-mut-self-async.stderr b/tests/ui/self/elision/ref-mut-self-async.stderr
index dff50aee9..62543ba53 100644
--- a/tests/ui/self/elision/ref-mut-self-async.stderr
+++ b/tests/ui/self/elision/ref-mut-self-async.stderr
@@ -6,7 +6,7 @@ LL | async fn ref_self(&mut self, f: &u32) -> &u32 {
| |
| let's call the lifetime of this reference `'2`
LL | f
- | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+ | ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
|
help: consider introducing a named lifetime parameter and update trait if needed
|
@@ -21,7 +21,7 @@ LL | async fn ref_Self(self: &mut Self, f: &u32) -> &u32 {
| |
| let's call the lifetime of this reference `'2`
LL | f
- | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+ | ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
|
help: consider introducing a named lifetime parameter and update trait if needed
|
@@ -36,7 +36,7 @@ LL | async fn box_ref_Self(self: Box<&mut Self>, f: &u32) -> &u32 {
| |
| let's call the lifetime of this reference `'2`
LL | f
- | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+ | ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
|
help: consider introducing a named lifetime parameter and update trait if needed
|
@@ -51,7 +51,7 @@ LL | async fn pin_ref_Self(self: Pin<&mut Self>, f: &u32) -> &u32 {
| |
| let's call the lifetime of this reference `'2`
LL | f
- | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+ | ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
|
help: consider introducing a named lifetime parameter and update trait if needed
|
@@ -66,7 +66,7 @@ LL | async fn box_box_ref_Self(self: Box<Box<&mut Self>>, f: &u32) -> &u32 {
| |
| let's call the lifetime of this reference `'2`
LL | f
- | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+ | ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
|
help: consider introducing a named lifetime parameter and update trait if needed
|
@@ -81,7 +81,7 @@ LL | async fn box_pin_ref_Self(self: Box<Pin<&mut Self>>, f: &u32) -> &u32 {
| |
| let's call the lifetime of this reference `'2`
LL | f
- | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+ | ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
|
help: consider introducing a named lifetime parameter and update trait if needed
|
diff --git a/tests/ui/self/elision/ref-mut-self.stderr b/tests/ui/self/elision/ref-mut-self.stderr
index ccf183016..12b64a3f6 100644
--- a/tests/ui/self/elision/ref-mut-self.stderr
+++ b/tests/ui/self/elision/ref-mut-self.stderr
@@ -6,7 +6,7 @@ LL | fn ref_self(&mut self, f: &u32) -> &u32 {
| |
| let's call the lifetime of this reference `'2`
LL | f
- | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+ | ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
|
help: consider introducing a named lifetime parameter and update trait if needed
|
@@ -21,7 +21,7 @@ LL | fn ref_Self(self: &mut Self, f: &u32) -> &u32 {
| |
| let's call the lifetime of this reference `'2`
LL | f
- | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+ | ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
|
help: consider introducing a named lifetime parameter and update trait if needed
|
@@ -36,7 +36,7 @@ LL | fn box_ref_Self(self: Box<&mut Self>, f: &u32) -> &u32 {
| |
| let's call the lifetime of this reference `'2`
LL | f
- | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+ | ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
|
help: consider introducing a named lifetime parameter and update trait if needed
|
@@ -51,7 +51,7 @@ LL | fn pin_ref_Self(self: Pin<&mut Self>, f: &u32) -> &u32 {
| |
| let's call the lifetime of this reference `'2`
LL | f
- | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+ | ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
|
help: consider introducing a named lifetime parameter and update trait if needed
|
@@ -66,7 +66,7 @@ LL | fn box_box_ref_Self(self: Box<Box<&mut Self>>, f: &u32) -> &u32 {
| |
| let's call the lifetime of this reference `'2`
LL | f
- | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+ | ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
|
help: consider introducing a named lifetime parameter and update trait if needed
|
@@ -81,7 +81,7 @@ LL | fn box_pin_ref_Self(self: Box<Pin<&mut Self>>, f: &u32) -> &u32 {
| |
| let's call the lifetime of this reference `'2`
LL | f
- | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+ | ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
|
help: consider introducing a named lifetime parameter and update trait if needed
|
diff --git a/tests/ui/self/elision/ref-mut-struct-async.stderr b/tests/ui/self/elision/ref-mut-struct-async.stderr
index 5b7ad026f..f8fb2e4a1 100644
--- a/tests/ui/self/elision/ref-mut-struct-async.stderr
+++ b/tests/ui/self/elision/ref-mut-struct-async.stderr
@@ -6,7 +6,7 @@ LL | async fn ref_Struct(self: &mut Struct, f: &u32) -> &u32 {
| |
| let's call the lifetime of this reference `'2`
LL | f
- | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+ | ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
|
help: consider introducing a named lifetime parameter and update trait if needed
|
@@ -21,7 +21,7 @@ LL | async fn box_ref_Struct(self: Box<&mut Struct>, f: &u32) -> &u32 {
| |
| let's call the lifetime of this reference `'2`
LL | f
- | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+ | ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
|
help: consider introducing a named lifetime parameter and update trait if needed
|
@@ -36,7 +36,7 @@ LL | async fn pin_ref_Struct(self: Pin<&mut Struct>, f: &u32) -> &u32 {
| |
| let's call the lifetime of this reference `'2`
LL | f
- | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+ | ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
|
help: consider introducing a named lifetime parameter and update trait if needed
|
@@ -51,7 +51,7 @@ LL | async fn box_box_ref_Struct(self: Box<Box<&mut Struct>>, f: &u32) -> &u
| |
| let's call the lifetime of this reference `'2`
LL | f
- | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+ | ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
|
help: consider introducing a named lifetime parameter and update trait if needed
|
@@ -66,7 +66,7 @@ LL | async fn box_pin_ref_Struct(self: Box<Pin<&mut Struct>>, f: &u32) -> &u
| |
| let's call the lifetime of this reference `'2`
LL | f
- | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+ | ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
|
help: consider introducing a named lifetime parameter and update trait if needed
|
diff --git a/tests/ui/self/elision/ref-mut-struct.stderr b/tests/ui/self/elision/ref-mut-struct.stderr
index b9c71e843..cde16ce8b 100644
--- a/tests/ui/self/elision/ref-mut-struct.stderr
+++ b/tests/ui/self/elision/ref-mut-struct.stderr
@@ -6,7 +6,7 @@ LL | fn ref_Struct(self: &mut Struct, f: &u32) -> &u32 {
| |
| let's call the lifetime of this reference `'2`
LL | f
- | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+ | ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
|
help: consider introducing a named lifetime parameter and update trait if needed
|
@@ -21,7 +21,7 @@ LL | fn box_ref_Struct(self: Box<&mut Struct>, f: &u32) -> &u32 {
| |
| let's call the lifetime of this reference `'2`
LL | f
- | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+ | ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
|
help: consider introducing a named lifetime parameter and update trait if needed
|
@@ -36,7 +36,7 @@ LL | fn pin_ref_Struct(self: Pin<&mut Struct>, f: &u32) -> &u32 {
| |
| let's call the lifetime of this reference `'2`
LL | f
- | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+ | ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
|
help: consider introducing a named lifetime parameter and update trait if needed
|
@@ -51,7 +51,7 @@ LL | fn box_box_ref_Struct(self: Box<Box<&mut Struct>>, f: &u32) -> &u32 {
| |
| let's call the lifetime of this reference `'2`
LL | f
- | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+ | ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
|
help: consider introducing a named lifetime parameter and update trait if needed
|
@@ -66,7 +66,7 @@ LL | fn box_pin_ref_Struct(self: Box<Pin<&mut Struct>>, f: &u32) -> &u32 {
| |
| let's call the lifetime of this reference `'2`
LL | f
- | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+ | ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
|
help: consider introducing a named lifetime parameter and update trait if needed
|
diff --git a/tests/ui/self/elision/ref-self-async.stderr b/tests/ui/self/elision/ref-self-async.stderr
index 26ef9779b..010d281b0 100644
--- a/tests/ui/self/elision/ref-self-async.stderr
+++ b/tests/ui/self/elision/ref-self-async.stderr
@@ -6,7 +6,7 @@ LL | async fn ref_self(&self, f: &u32) -> &u32 {
| |
| let's call the lifetime of this reference `'2`
LL | f
- | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+ | ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
|
help: consider introducing a named lifetime parameter and update trait if needed
|
@@ -21,7 +21,7 @@ LL | async fn ref_Self(self: &Self, f: &u32) -> &u32 {
| |
| let's call the lifetime of this reference `'2`
LL | f
- | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+ | ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
|
help: consider introducing a named lifetime parameter and update trait if needed
|
@@ -36,7 +36,7 @@ LL | async fn box_ref_Self(self: Box<&Self>, f: &u32) -> &u32 {
| |
| let's call the lifetime of this reference `'2`
LL | f
- | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+ | ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
|
help: consider introducing a named lifetime parameter and update trait if needed
|
@@ -51,7 +51,7 @@ LL | async fn pin_ref_Self(self: Pin<&Self>, f: &u32) -> &u32 {
| |
| let's call the lifetime of this reference `'2`
LL | f
- | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+ | ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
|
help: consider introducing a named lifetime parameter and update trait if needed
|
@@ -66,7 +66,7 @@ LL | async fn box_box_ref_Self(self: Box<Box<&Self>>, f: &u32) -> &u32 {
| |
| let's call the lifetime of this reference `'2`
LL | f
- | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+ | ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
|
help: consider introducing a named lifetime parameter and update trait if needed
|
@@ -81,7 +81,7 @@ LL | async fn box_pin_ref_Self(self: Box<Pin<&Self>>, f: &u32) -> &u32 {
| |
| let's call the lifetime of this reference `'2`
LL | f
- | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+ | ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
|
help: consider introducing a named lifetime parameter and update trait if needed
|
@@ -96,7 +96,7 @@ LL | async fn wrap_ref_Self_Self(self: Wrap<&Self, Self>, f: &u8) -> &u8 {
| |
| let's call the lifetime of this reference `'2`
LL | f
- | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+ | ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
|
help: consider introducing a named lifetime parameter and update trait if needed
|
diff --git a/tests/ui/self/elision/ref-self.stderr b/tests/ui/self/elision/ref-self.stderr
index 32448f3a6..35693257c 100644
--- a/tests/ui/self/elision/ref-self.stderr
+++ b/tests/ui/self/elision/ref-self.stderr
@@ -6,7 +6,7 @@ LL | fn ref_self(&self, f: &u32) -> &u32 {
| |
| let's call the lifetime of this reference `'2`
LL | f
- | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+ | ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
|
help: consider introducing a named lifetime parameter and update trait if needed
|
@@ -21,7 +21,7 @@ LL | fn ref_Self(self: &Self, f: &u32) -> &u32 {
| |
| let's call the lifetime of this reference `'2`
LL | f
- | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+ | ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
|
help: consider introducing a named lifetime parameter and update trait if needed
|
@@ -36,7 +36,7 @@ LL | fn box_ref_Self(self: Box<&Self>, f: &u32) -> &u32 {
| |
| let's call the lifetime of this reference `'2`
LL | f
- | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+ | ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
|
help: consider introducing a named lifetime parameter and update trait if needed
|
@@ -51,7 +51,7 @@ LL | fn pin_ref_Self(self: Pin<&Self>, f: &u32) -> &u32 {
| |
| let's call the lifetime of this reference `'2`
LL | f
- | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+ | ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
|
help: consider introducing a named lifetime parameter and update trait if needed
|
@@ -66,7 +66,7 @@ LL | fn box_box_ref_Self(self: Box<Box<&Self>>, f: &u32) -> &u32 {
| |
| let's call the lifetime of this reference `'2`
LL | f
- | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+ | ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
|
help: consider introducing a named lifetime parameter and update trait if needed
|
@@ -81,7 +81,7 @@ LL | fn box_pin_ref_Self(self: Box<Pin<&Self>>, f: &u32) -> &u32 {
| |
| let's call the lifetime of this reference `'2`
LL | f
- | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+ | ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
|
help: consider introducing a named lifetime parameter and update trait if needed
|
@@ -96,7 +96,7 @@ LL | fn wrap_ref_Self_Self(self: Wrap<&Self, Self>, f: &u8) -> &u8 {
| |
| let's call the lifetime of this reference `'2`
LL | f
- | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+ | ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
|
help: consider introducing a named lifetime parameter and update trait if needed
|
diff --git a/tests/ui/self/elision/ref-struct-async.stderr b/tests/ui/self/elision/ref-struct-async.stderr
index edb5c54ab..c9376d58f 100644
--- a/tests/ui/self/elision/ref-struct-async.stderr
+++ b/tests/ui/self/elision/ref-struct-async.stderr
@@ -6,7 +6,7 @@ LL | async fn ref_Struct(self: &Struct, f: &u32) -> &u32 {
| |
| let's call the lifetime of this reference `'2`
LL | f
- | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+ | ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
|
help: consider introducing a named lifetime parameter and update trait if needed
|
@@ -21,7 +21,7 @@ LL | async fn box_ref_Struct(self: Box<&Struct>, f: &u32) -> &u32 {
| |
| let's call the lifetime of this reference `'2`
LL | f
- | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+ | ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
|
help: consider introducing a named lifetime parameter and update trait if needed
|
@@ -36,7 +36,7 @@ LL | async fn pin_ref_Struct(self: Pin<&Struct>, f: &u32) -> &u32 {
| |
| let's call the lifetime of this reference `'2`
LL | f
- | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+ | ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
|
help: consider introducing a named lifetime parameter and update trait if needed
|
@@ -51,7 +51,7 @@ LL | async fn box_box_ref_Struct(self: Box<Box<&Struct>>, f: &u32) -> &u32 {
| |
| let's call the lifetime of this reference `'2`
LL | f
- | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+ | ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
|
help: consider introducing a named lifetime parameter and update trait if needed
|
@@ -66,7 +66,7 @@ LL | async fn box_pin_Struct(self: Box<Pin<&Struct>>, f: &u32) -> &u32 {
| |
| let's call the lifetime of this reference `'2`
LL | f
- | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+ | ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
|
help: consider introducing a named lifetime parameter and update trait if needed
|
diff --git a/tests/ui/self/elision/ref-struct.stderr b/tests/ui/self/elision/ref-struct.stderr
index 4492ed4aa..a3d3cebeb 100644
--- a/tests/ui/self/elision/ref-struct.stderr
+++ b/tests/ui/self/elision/ref-struct.stderr
@@ -6,7 +6,7 @@ LL | fn ref_Struct(self: &Struct, f: &u32) -> &u32 {
| |
| let's call the lifetime of this reference `'2`
LL | f
- | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+ | ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
|
help: consider introducing a named lifetime parameter and update trait if needed
|
@@ -21,7 +21,7 @@ LL | fn box_ref_Struct(self: Box<&Struct>, f: &u32) -> &u32 {
| |
| let's call the lifetime of this reference `'2`
LL | f
- | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+ | ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
|
help: consider introducing a named lifetime parameter and update trait if needed
|
@@ -36,7 +36,7 @@ LL | fn pin_ref_Struct(self: Pin<&Struct>, f: &u32) -> &u32 {
| |
| let's call the lifetime of this reference `'2`
LL | f
- | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+ | ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
|
help: consider introducing a named lifetime parameter and update trait if needed
|
@@ -51,7 +51,7 @@ LL | fn box_box_ref_Struct(self: Box<Box<&Struct>>, f: &u32) -> &u32 {
| |
| let's call the lifetime of this reference `'2`
LL | f
- | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+ | ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
|
help: consider introducing a named lifetime parameter and update trait if needed
|
@@ -66,7 +66,7 @@ LL | fn box_pin_Struct(self: Box<Pin<&Struct>>, f: &u32) -> &u32 {
| |
| let's call the lifetime of this reference `'2`
LL | f
- | ^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+ | ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
|
help: consider introducing a named lifetime parameter and update trait if needed
|
diff --git a/tests/ui/self/issue-61882-2.stderr b/tests/ui/self/issue-61882-2.stderr
index 0b8e134c9..6faa4477d 100644
--- a/tests/ui/self/issue-61882-2.stderr
+++ b/tests/ui/self/issue-61882-2.stderr
@@ -1,6 +1,8 @@
error[E0597]: `x` does not live long enough
--> $DIR/issue-61882-2.rs:6:14
|
+LL | let x = 0;
+ | - binding `x` declared here
LL | Self(&x);
| ^^
| |
diff --git a/tests/ui/self/issue-61882.stderr b/tests/ui/self/issue-61882.stderr
index dd7194dc2..96f4e41de 100644
--- a/tests/ui/self/issue-61882.stderr
+++ b/tests/ui/self/issue-61882.stderr
@@ -16,7 +16,7 @@ error[E0308]: mismatched types
--> $DIR/issue-61882.rs:4:22
|
LL | const B: A<u8> = Self(0);
- | ^^^^^^^ expected `u8`, found `bool`
+ | ^^^^^^^ expected `A<u8>`, found `A<bool>`
|
= note: expected struct `A<u8>`
found struct `A<bool>`
diff --git a/tests/ui/seq-args.rs b/tests/ui/seq-args.rs
index a5ebeecd3..627dfcc31 100644
--- a/tests/ui/seq-args.rs
+++ b/tests/ui/seq-args.rs
@@ -2,12 +2,12 @@ fn main() {
trait Seq { }
impl<T> Seq<T> for Vec<T> {
- //~^ ERROR this trait takes 0 generic arguments but 1 generic argument
+ //~^ ERROR trait takes 0 generic arguments but 1 generic argument
/* ... */
}
impl Seq<bool> for u32 {
- //~^ ERROR this trait takes 0 generic arguments but 1 generic argument
+ //~^ ERROR trait takes 0 generic arguments but 1 generic argument
/* Treat the integer as a sequence of bits */
}
}
diff --git a/tests/ui/seq-args.stderr b/tests/ui/seq-args.stderr
index c404d9574..a5b0f8e98 100644
--- a/tests/ui/seq-args.stderr
+++ b/tests/ui/seq-args.stderr
@@ -1,4 +1,4 @@
-error[E0107]: this trait takes 0 generic arguments but 1 generic argument was supplied
+error[E0107]: trait takes 0 generic arguments but 1 generic argument was supplied
--> $DIR/seq-args.rs:4:13
|
LL | impl<T> Seq<T> for Vec<T> {
@@ -12,7 +12,7 @@ note: trait defined here, with 0 generic parameters
LL | trait Seq { }
| ^^^
-error[E0107]: this trait takes 0 generic arguments but 1 generic argument was supplied
+error[E0107]: trait takes 0 generic arguments but 1 generic argument was supplied
--> $DIR/seq-args.rs:9:10
|
LL | impl Seq<bool> for u32 {
diff --git a/tests/ui/simd/intrinsic/generic-cast-pass.rs b/tests/ui/simd/intrinsic/generic-cast-pass.rs
index 15f232e2c..89436c83e 100644
--- a/tests/ui/simd/intrinsic/generic-cast-pass.rs
+++ b/tests/ui/simd/intrinsic/generic-cast-pass.rs
@@ -1,121 +1,59 @@
// run-pass
-#![allow(unused_must_use)]
// ignore-emscripten FIXME(#45351) hits an LLVM assert
-#![feature(repr_simd, platform_intrinsics, concat_idents, test)]
-#![allow(non_camel_case_types)]
-
-extern crate test;
-
-#[repr(simd)]
-#[derive(PartialEq, Debug)]
-struct i32x4(i32, i32, i32, i32);
-#[repr(simd)]
-#[derive(PartialEq, Debug)]
-struct i8x4(i8, i8, i8, i8);
-
-#[repr(simd)]
-#[derive(PartialEq, Debug)]
-struct u32x4(u32, u32, u32, u32);
-#[repr(simd)]
-#[derive(PartialEq, Debug)]
-struct u8x4(u8, u8, u8, u8);
-
-#[repr(simd)]
-#[derive(PartialEq, Debug)]
-struct f32x4(f32, f32, f32, f32);
-
-#[repr(simd)]
-#[derive(PartialEq, Debug)]
-struct f64x4(f64, f64, f64, f64);
-
+#![feature(repr_simd, platform_intrinsics)]
extern "platform-intrinsic" {
fn simd_cast<T, U>(x: T) -> U;
}
-const A: i32 = -1234567;
-const B: i32 = 12345678;
-const C: i32 = -123456789;
-const D: i32 = 1234567890;
+use std::cmp::{max, min};
-trait Foo {
- fn is_float() -> bool { false }
- fn in_range(x: i32) -> bool;
-}
-impl Foo for i32 {
- fn in_range(_: i32) -> bool { true }
-}
-impl Foo for i8 {
- fn in_range(x: i32) -> bool { -128 <= x && x < 128 }
-}
-impl Foo for u32 {
- fn in_range(x: i32) -> bool { 0 <= x }
-}
-impl Foo for u8 {
- fn in_range(x: i32) -> bool { 0 <= x && x < 128 }
-}
-impl Foo for f32 {
- fn is_float() -> bool { true }
- fn in_range(_: i32) -> bool { true }
-}
-impl Foo for f64 {
- fn is_float() -> bool { true }
- fn in_range(_: i32) -> bool { true }
-}
+#[derive(Copy, Clone)]
+#[repr(simd)]
+struct V<T>([T; 2]);
fn main() {
- macro_rules! test {
- ($from: ident, $to: ident) => {{
- // force the casts to actually happen, or else LLVM/rustc
- // may fold them and get slightly different results.
- let (a, b, c, d) = test::black_box((A as $from, B as $from, C as $from, D as $from));
- // the SIMD vectors are all FOOx4, so we can concat_idents
- // so we don't have to pass in the extra args to the macro
- let mut from = simd_cast(concat_idents!($from, x4)(a, b, c, d));
- let mut to = concat_idents!($to, x4)(a as $to,
- b as $to,
- c as $to,
- d as $to);
- // assist type inference, it needs to know what `from` is
- // for the `if` statements.
- to == from;
+ unsafe {
+ let u = V::<u32>([i16::MIN as u32, i16::MAX as u32]);
+ let i: V<i16> = simd_cast(u);
+ assert_eq!(i.0[0], u.0[0] as i16);
+ assert_eq!(i.0[1], u.0[1] as i16);
+ }
- // there are platform differences for some out of range
- // casts, so we just normalize such things: it's OK for
- // "invalid" calculations to result in nonsense answers.
- // (e.g., negative float to unsigned integer goes through a
- // library routine on the default i686 platforms, and the
- // implementation of that routine differs on e.g., Linux
- // vs. macOS, resulting in different answers.)
- if $from::is_float() {
- if !$to::in_range(A) { from.0 = 0 as $to; to.0 = 0 as $to; }
- if !$to::in_range(B) { from.1 = 0 as $to; to.1 = 0 as $to; }
- if !$to::in_range(C) { from.2 = 0 as $to; to.2 = 0 as $to; }
- if !$to::in_range(D) { from.3 = 0 as $to; to.3 = 0 as $to; }
- }
+ unsafe {
+ let f = V::<f32>([i16::MIN as f32, i16::MAX as f32]);
+ let i: V<i16> = simd_cast(f);
+ assert_eq!(i.0[0], f.0[0] as i16);
+ assert_eq!(i.0[1], f.0[1] as i16);
+ }
- assert!(to == from,
- "{} -> {} ({:?} != {:?})", stringify!($from), stringify!($to),
- from, to);
- }}
+ unsafe {
+ let f = V::<f32>([u8::MIN as f32, u8::MAX as f32]);
+ let u: V<u8> = simd_cast(f);
+ assert_eq!(u.0[0], f.0[0] as u8);
+ assert_eq!(u.0[1], f.0[1] as u8);
}
- macro_rules! tests {
- (: $($to: ident),*) => { () };
- // repeating the list twice is easier than writing a cartesian
- // product macro
- ($from: ident $(, $from_: ident)*: $($to: ident),*) => {
- fn $from() { unsafe { $( test!($from, $to); )* } }
- tests!($($from_),*: $($to),*)
- };
- ($($types: ident),*) => {{
- tests!($($types),* : $($types),*);
- $($types();)*
- }}
+
+ unsafe {
+ // We would like to do isize::MIN..=isize::MAX, but those values are not representable in
+ // an f64, so we clamp to the range of an i32 to prevent running into UB.
+ let f = V::<f64>([
+ max(isize::MIN, i32::MIN as isize) as f64,
+ min(isize::MAX, i32::MAX as isize) as f64,
+ ]);
+ let i: V<isize> = simd_cast(f);
+ assert_eq!(i.0[0], f.0[0] as isize);
+ assert_eq!(i.0[1], f.0[1] as isize);
}
- // test various combinations, including truncation,
- // signed/unsigned extension, and floating point casts.
- tests!(i32, i8, u32, u8, f32);
- tests!(i32, u32, f32, f64)
+ unsafe {
+ let f = V::<f64>([
+ max(usize::MIN, u32::MIN as usize) as f64,
+ min(usize::MAX, u32::MAX as usize) as f64,
+ ]);
+ let u: V<usize> = simd_cast(f);
+ assert_eq!(u.0[0], f.0[0] as usize);
+ assert_eq!(u.0[1], f.0[1] as usize);
+ }
}
diff --git a/tests/ui/simd/intrinsic/generic-gather-pass.rs b/tests/ui/simd/intrinsic/generic-gather-pass.rs
index 805caebe5..7d4b3dbd7 100644
--- a/tests/ui/simd/intrinsic/generic-gather-pass.rs
+++ b/tests/ui/simd/intrinsic/generic-gather-pass.rs
@@ -24,9 +24,9 @@ fn main() {
// reading from *const
unsafe {
- let pointer = &x[0] as *const f32;
+ let pointer = x.as_ptr();
let pointers = x4(
- pointer.offset(0) as *const f32,
+ pointer.offset(0),
pointer.offset(2),
pointer.offset(4),
pointer.offset(6)
@@ -39,9 +39,9 @@ fn main() {
// reading from *mut
unsafe {
- let pointer = &mut x[0] as *mut f32;
+ let pointer = x.as_mut_ptr();
let pointers = x4(
- pointer.offset(0) as *mut f32,
+ pointer.offset(0),
pointer.offset(2),
pointer.offset(4),
pointer.offset(6)
@@ -54,9 +54,9 @@ fn main() {
// writing to *mut
unsafe {
- let pointer = &mut x[0] as *mut f32;
+ let pointer = x.as_mut_ptr();
let pointers = x4(
- pointer.offset(0) as *mut f32,
+ pointer.offset(0),
pointer.offset(2),
pointer.offset(4),
pointer.offset(6)
@@ -85,9 +85,9 @@ fn main() {
// reading from *const
unsafe {
- let pointer = &y[0] as *const *const f32;
+ let pointer = y.as_ptr();
let pointers = x4(
- pointer.offset(0) as *const *const f32,
+ pointer.offset(0),
pointer.offset(2),
pointer.offset(4),
pointer.offset(6)
@@ -100,9 +100,9 @@ fn main() {
// reading from *mut
unsafe {
- let pointer = &mut y[0] as *mut *const f32;
+ let pointer = y.as_mut_ptr();
let pointers = x4(
- pointer.offset(0) as *mut *const f32,
+ pointer.offset(0),
pointer.offset(2),
pointer.offset(4),
pointer.offset(6)
@@ -115,9 +115,9 @@ fn main() {
// writing to *mut
unsafe {
- let pointer = &mut y[0] as *mut *const f32;
+ let pointer = y.as_mut_ptr();
let pointers = x4(
- pointer.offset(0) as *mut *const f32,
+ pointer.offset(0),
pointer.offset(2),
pointer.offset(4),
pointer.offset(6)
diff --git a/tests/ui/simd/issue-89193.rs b/tests/ui/simd/issue-89193.rs
index 79c4e6a31..cd24d6675 100644
--- a/tests/ui/simd/issue-89193.rs
+++ b/tests/ui/simd/issue-89193.rs
@@ -17,13 +17,14 @@ extern "platform-intrinsic" {
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 all_set = u8::MAX as i8; // aka -1
+ let mask = x4(all_set, all_set, all_set, all_set);
let expected = x4(10_usize, 11, 12, 13);
unsafe {
- let pointer = &x[0] as *const usize;
+ let pointer = x.as_ptr();
let pointers = x4(
- pointer.offset(0) as *const usize,
+ pointer.offset(0),
pointer.offset(1),
pointer.offset(2),
pointer.offset(3)
@@ -38,9 +39,9 @@ fn main() {
let expected = x4(10_isize, 11, 12, 13);
unsafe {
- let pointer = &x[0] as *const isize;
+ let pointer = x.as_ptr();
let pointers = x4(
- pointer.offset(0) as *const isize,
+ pointer.offset(0),
pointer.offset(1),
pointer.offset(2),
pointer.offset(3)
diff --git a/tests/ui/single-use-lifetime/issue-107998.rs b/tests/ui/single-use-lifetime/issue-107998.rs
new file mode 100644
index 000000000..f32688d20
--- /dev/null
+++ b/tests/ui/single-use-lifetime/issue-107998.rs
@@ -0,0 +1,9 @@
+#![deny(single_use_lifetimes)]
+
+fn with<R>(f: &fn<'a>(x: &'a i32) -> R) -> R {
+ //~^ ERROR function pointer types may not have generic parameters
+ //~| ERROR lifetime parameter `'a` only used once
+ f(&3)
+}
+
+fn main() {}
diff --git a/tests/ui/single-use-lifetime/issue-107998.stderr b/tests/ui/single-use-lifetime/issue-107998.stderr
new file mode 100644
index 000000000..e870351de
--- /dev/null
+++ b/tests/ui/single-use-lifetime/issue-107998.stderr
@@ -0,0 +1,30 @@
+error: function pointer types may not have generic parameters
+ --> $DIR/issue-107998.rs:3:18
+ |
+LL | fn with<R>(f: &fn<'a>(x: &'a i32) -> R) -> R {
+ | ^^^^
+ |
+help: consider moving the lifetime parameter to a `for` parameter list
+ |
+LL - fn with<R>(f: &fn<'a>(x: &'a i32) -> R) -> R {
+LL + fn with<R>(f: &for<'a> fn(x: &'a i32) -> R) -> R {
+ |
+
+error: lifetime parameter `'a` only used once
+ --> $DIR/issue-107998.rs:3:19
+ |
+LL | fn with<R>(f: &fn<'a>(x: &'a i32) -> R) -> R {
+ | ^^ ---
+ | | |
+ | | ...is used only here
+ | | help: elide the single-use lifetime
+ | this lifetime...
+ |
+note: the lint level is defined here
+ --> $DIR/issue-107998.rs:1:9
+ |
+LL | #![deny(single_use_lifetimes)]
+ | ^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
diff --git a/tests/ui/slightly-nice-generic-literal-messages.rs b/tests/ui/slightly-nice-generic-literal-messages.rs
index a48598ce8..268009f65 100644
--- a/tests/ui/slightly-nice-generic-literal-messages.rs
+++ b/tests/ui/slightly-nice-generic-literal-messages.rs
@@ -8,7 +8,7 @@ fn main() {
//~^ ERROR mismatched types
//~| expected struct `Foo<{float}, _>`
//~| found type `{integer}`
- //~| expected struct `Foo`, found integer
+ //~| expected `Foo<{float}, _>`, found integer
}
}
diff --git a/tests/ui/slightly-nice-generic-literal-messages.stderr b/tests/ui/slightly-nice-generic-literal-messages.stderr
index 14f01f0eb..83ef522ab 100644
--- a/tests/ui/slightly-nice-generic-literal-messages.stderr
+++ b/tests/ui/slightly-nice-generic-literal-messages.stderr
@@ -4,7 +4,7 @@ error[E0308]: mismatched types
LL | match Foo(1.1, marker::PhantomData) {
| ----------------------------- this expression has type `Foo<{float}, _>`
LL | 1 => {}
- | ^ expected struct `Foo`, found integer
+ | ^ expected `Foo<{float}, _>`, found integer
|
= note: expected struct `Foo<{float}, _>`
found type `{integer}`
diff --git a/tests/ui/span/borrowck-call-is-borrow-issue-12224.stderr b/tests/ui/span/borrowck-call-is-borrow-issue-12224.stderr
index 48b42bc78..9711dad80 100644
--- a/tests/ui/span/borrowck-call-is-borrow-issue-12224.stderr
+++ b/tests/ui/span/borrowck-call-is-borrow-issue-12224.stderr
@@ -47,6 +47,9 @@ LL | foo(f);
error[E0505]: cannot move out of `f` because it is borrowed
--> $DIR/borrowck-call-is-borrow-issue-12224.rs:55:16
|
+LL | let mut f = move |g: Box<dyn FnMut(isize)>, b: isize| {
+ | ----- binding `f` declared here
+...
LL | f(Box::new(|a| {
| - ^^^ move out of `f` occurs here
| |
diff --git a/tests/ui/span/borrowck-let-suggestion-suffixes.rs b/tests/ui/span/borrowck-let-suggestion-suffixes.rs
index 18abfb5c3..ad556f281 100644
--- a/tests/ui/span/borrowck-let-suggestion-suffixes.rs
+++ b/tests/ui/span/borrowck-let-suggestion-suffixes.rs
@@ -8,6 +8,7 @@ fn f() {
{
let young = ['y']; // statement 3
+ //~^ NOTE binding `young` declared here
v2.push(&young[0]); // statement 4
//~^ ERROR `young[_]` does not live long enough
diff --git a/tests/ui/span/borrowck-let-suggestion-suffixes.stderr b/tests/ui/span/borrowck-let-suggestion-suffixes.stderr
index 2dc29a78d..545b235a5 100644
--- a/tests/ui/span/borrowck-let-suggestion-suffixes.stderr
+++ b/tests/ui/span/borrowck-let-suggestion-suffixes.stderr
@@ -1,6 +1,9 @@
error[E0597]: `young[_]` does not live long enough
- --> $DIR/borrowck-let-suggestion-suffixes.rs:12:17
+ --> $DIR/borrowck-let-suggestion-suffixes.rs:13:17
|
+LL | let young = ['y']; // statement 3
+ | ----- binding `young` declared here
+...
LL | v2.push(&young[0]); // statement 4
| ^^^^^^^^^ borrowed value does not live long enough
...
@@ -11,7 +14,7 @@ LL | (v1, v2, v3, /* v4 is above. */ v5).use_ref();
| -- borrow later used here
error[E0716]: temporary value dropped while borrowed
- --> $DIR/borrowck-let-suggestion-suffixes.rs:19:14
+ --> $DIR/borrowck-let-suggestion-suffixes.rs:20:14
|
LL | v3.push(&id('x')); // statement 6
| ^^^^^^^ - temporary value is freed at the end of this statement
@@ -28,7 +31,7 @@ LL ~ v3.push(&binding); // statement 6
|
error[E0716]: temporary value dropped while borrowed
- --> $DIR/borrowck-let-suggestion-suffixes.rs:29:18
+ --> $DIR/borrowck-let-suggestion-suffixes.rs:30:18
|
LL | v4.push(&id('y'));
| ^^^^^^^ - temporary value is freed at the end of this statement
@@ -41,7 +44,7 @@ LL | v4.use_ref();
= note: consider using a `let` binding to create a longer lived value
error[E0716]: temporary value dropped while borrowed
- --> $DIR/borrowck-let-suggestion-suffixes.rs:40:14
+ --> $DIR/borrowck-let-suggestion-suffixes.rs:41:14
|
LL | v5.push(&id('z'));
| ^^^^^^^ - temporary value is freed at the end of this statement
diff --git a/tests/ui/span/coerce-suggestions.stderr b/tests/ui/span/coerce-suggestions.stderr
index db784d5fe..bb30f000e 100644
--- a/tests/ui/span/coerce-suggestions.stderr
+++ b/tests/ui/span/coerce-suggestions.stderr
@@ -2,7 +2,7 @@ error[E0308]: mismatched types
--> $DIR/coerce-suggestions.rs:7:20
|
LL | let x: usize = String::new();
- | ----- ^^^^^^^^^^^^^ expected `usize`, found struct `String`
+ | ----- ^^^^^^^^^^^^^ expected `usize`, found `String`
| |
| expected due to this
@@ -12,7 +12,7 @@ error[E0308]: mismatched types
LL | let x: &str = String::new();
| ---- ^^^^^^^^^^^^^
| | |
- | | expected `&str`, found struct `String`
+ | | expected `&str`, found `String`
| | help: consider borrowing here: `&String::new()`
| expected due to this
@@ -63,7 +63,7 @@ error[E0308]: mismatched types
--> $DIR/coerce-suggestions.rs:21:9
|
LL | s = format!("foo");
- | ^^^^^^^^^^^^^^ expected `&mut String`, found struct `String`
+ | ^^^^^^^^^^^^^^ expected `&mut String`, found `String`
|
= note: this error originates in the macro `format` (in Nightly builds, run with -Z macro-backtrace for more info)
diff --git a/tests/ui/span/destructor-restrictions.stderr b/tests/ui/span/destructor-restrictions.stderr
index 53c940462..281248626 100644
--- a/tests/ui/span/destructor-restrictions.stderr
+++ b/tests/ui/span/destructor-restrictions.stderr
@@ -1,6 +1,8 @@
error[E0597]: `*a` does not live long enough
--> $DIR/destructor-restrictions.rs:8:10
|
+LL | let a = Box::new(RefCell::new(4));
+ | - binding `a` declared here
LL | *a.borrow() + 1
| ^^^^^^^^^^
| |
diff --git a/tests/ui/span/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.rs b/tests/ui/span/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.rs
index 4559da91e..f20024e75 100644
--- a/tests/ui/span/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.rs
+++ b/tests/ui/span/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.rs
@@ -3,16 +3,10 @@
pub struct A {}
impl A {
- async fn create(path: impl AsRef<std::path::Path>) { //~ ERROR `async fn` is not permitted in Rust 2015
- //~^ WARN changes to closure capture in Rust 2021 will affect drop order [rust_2021_incompatible_closure_captures]
+ async fn create(path: impl AsRef<std::path::Path>) {
;
- crate(move || {} ).await //~ ERROR expected function, found module `crate`
+ crate(move || {} ).await
}
}
-trait C{async fn new(val: T) {} //~ ERROR `async fn` is not permitted in Rust 2015
-//~^ ERROR functions in traits cannot be declared `async`
-//~| ERROR cannot find type `T` in this scope
-//~| WARN changes to closure capture in Rust 2021 will affect drop order [rust_2021_incompatible_closure_captures]
-
-//~ ERROR this file contains an unclosed delimiter
+trait C{async fn new(val: T) {} //~ ERROR this file contains an unclosed delimiter
diff --git a/tests/ui/span/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.stderr b/tests/ui/span/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.stderr
index df1cafdb7..1ec8ca427 100644
--- a/tests/ui/span/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.stderr
+++ b/tests/ui/span/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.stderr
@@ -1,95 +1,8 @@
error: this file contains an unclosed delimiter
- --> $DIR/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.rs:18:53
+ --> $DIR/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.rs:12:85
|
LL | trait C{async fn new(val: T) {}
- | - unclosed delimiter
-...
-LL |
- | ^
+ | - unclosed delimiter ^
-error[E0670]: `async fn` is not permitted in Rust 2015
- --> $DIR/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.rs:6:5
- |
-LL | async fn create(path: impl AsRef<std::path::Path>) {
- | ^^^^^ to use `async fn`, switch to Rust 2018 or later
- |
- = help: pass `--edition 2021` to `rustc`
- = note: for more on editions, read https://doc.rust-lang.org/edition-guide
-
-error[E0670]: `async fn` is not permitted in Rust 2015
- --> $DIR/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.rs:13:9
- |
-LL | trait C{async fn new(val: T) {}
- | ^^^^^ to use `async fn`, switch to Rust 2018 or later
- |
- = help: pass `--edition 2021` to `rustc`
- = note: for more on editions, read https://doc.rust-lang.org/edition-guide
-
-error[E0412]: cannot find type `T` in this scope
- --> $DIR/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.rs:13:27
- |
-LL | pub struct A {}
- | ------------ similarly named struct `A` defined here
-...
-LL | trait C{async fn new(val: T) {}
- | ^ help: a struct with a similar name exists: `A`
-
-error[E0706]: functions in traits cannot be declared `async`
- --> $DIR/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.rs:13:9
- |
-LL | trait C{async fn new(val: T) {}
- | -----^^^^^^^^^^^^^^^
- | |
- | `async` because of this
- |
- = note: `async` trait functions are not currently supported
- = note: consider using the `async-trait` crate: https://crates.io/crates/async-trait
- = note: see issue #91611 <https://github.com/rust-lang/rust/issues/91611> for more information
- = help: add `#![feature(async_fn_in_trait)]` to the crate attributes to enable
-
-error[E0423]: expected function, found module `crate`
- --> $DIR/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.rs:9:5
- |
-LL | crate(move || {} ).await
- | ^^^^^ not a function
-
-warning: changes to closure capture in Rust 2021 will affect drop order
- --> $DIR/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.rs:6:57
- |
-LL | async fn create(path: impl AsRef<std::path::Path>) {
- | _____________________----_____________________________-__^
- | | | |
- | | | in Rust 2018, `path` is dropped here along with the closure, but in Rust 2021 `path` is not part of the closure
- | | in Rust 2018, this causes the closure to capture `path`, but in Rust 2021, it has no effect
-LL | |
-LL | | ;
-LL | | crate(move || {} ).await
-LL | | }
- | |_____^
- |
- = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html>
- = note: requested on the command line with `-W rust-2021-incompatible-closure-captures`
-help: add a dummy let to cause `path` to be fully captured
- |
-LL | async fn create(path: impl AsRef<std::path::Path>) { let _ = &path;
- | ++++++++++++++
-
-warning: changes to closure capture in Rust 2021 will affect drop order
- --> $DIR/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.rs:13:30
- |
-LL | trait C{async fn new(val: T) {}
- | --- - ^^
- | | |
- | | in Rust 2018, `val` is dropped here along with the closure, but in Rust 2021 `val` is not part of the closure
- | in Rust 2018, this causes the closure to capture `val`, but in Rust 2021, it has no effect
- |
- = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html>
-help: add a dummy let to cause `val` to be fully captured
- |
-LL | trait C{async fn new(val: T) { let _ = &val;}
- | +++++++++++++
-
-error: aborting due to 6 previous errors; 2 warnings emitted
+error: aborting due to previous error
-Some errors have detailed explanations: E0412, E0423, E0670, E0706.
-For more information about an error, try `rustc --explain E0412`.
diff --git a/tests/ui/span/dropck-object-cycle.stderr b/tests/ui/span/dropck-object-cycle.stderr
index 229d17e1c..097fb6219 100644
--- a/tests/ui/span/dropck-object-cycle.stderr
+++ b/tests/ui/span/dropck-object-cycle.stderr
@@ -1,6 +1,8 @@
error[E0597]: `*m` does not live long enough
--> $DIR/dropck-object-cycle.rs:27:31
|
+LL | let m : Box<dyn Trait+'static> = make_val();
+ | - binding `m` declared here
LL | assert_eq!(object_invoke1(&*m), (4,5));
| ^^^ borrowed value does not live long enough
...
diff --git a/tests/ui/span/dropck_arr_cycle_checked.stderr b/tests/ui/span/dropck_arr_cycle_checked.stderr
index 068c779ae..23ebc8d59 100644
--- a/tests/ui/span/dropck_arr_cycle_checked.stderr
+++ b/tests/ui/span/dropck_arr_cycle_checked.stderr
@@ -1,6 +1,9 @@
error[E0597]: `b2` does not live long enough
--> $DIR/dropck_arr_cycle_checked.rs:93:24
|
+LL | let (b1, b2, b3);
+ | -- binding `b2` declared here
+...
LL | b1.a[0].v.set(Some(&b2));
| ^^^ borrowed value does not live long enough
...
@@ -15,6 +18,9 @@ LL | }
error[E0597]: `b3` does not live long enough
--> $DIR/dropck_arr_cycle_checked.rs:95:24
|
+LL | let (b1, b2, b3);
+ | -- binding `b3` declared here
+...
LL | b1.a[1].v.set(Some(&b3));
| ^^^ borrowed value does not live long enough
...
@@ -29,6 +35,9 @@ LL | }
error[E0597]: `b1` does not live long enough
--> $DIR/dropck_arr_cycle_checked.rs:99:24
|
+LL | let (b1, b2, b3);
+ | -- binding `b1` declared here
+...
LL | b3.a[0].v.set(Some(&b1));
| ^^^ borrowed value does not live long enough
...
diff --git a/tests/ui/span/dropck_direct_cycle_with_drop.stderr b/tests/ui/span/dropck_direct_cycle_with_drop.stderr
index 07ae138ac..1e75e3b2f 100644
--- a/tests/ui/span/dropck_direct_cycle_with_drop.stderr
+++ b/tests/ui/span/dropck_direct_cycle_with_drop.stderr
@@ -1,6 +1,8 @@
error[E0597]: `d2` does not live long enough
--> $DIR/dropck_direct_cycle_with_drop.rs:36:19
|
+LL | let (d1, d2) = (D::new(format!("d1")), D::new(format!("d2")));
+ | -- binding `d2` declared here
LL | d1.p.set(Some(&d2));
| ^^^ borrowed value does not live long enough
...
@@ -15,6 +17,9 @@ LL | }
error[E0597]: `d1` does not live long enough
--> $DIR/dropck_direct_cycle_with_drop.rs:38:19
|
+LL | let (d1, d2) = (D::new(format!("d1")), D::new(format!("d2")));
+ | -- binding `d1` declared here
+...
LL | d2.p.set(Some(&d1));
| ^^^ borrowed value does not live long enough
LL |
diff --git a/tests/ui/span/dropck_misc_variants.stderr b/tests/ui/span/dropck_misc_variants.stderr
index 76e90574c..24a2c9089 100644
--- a/tests/ui/span/dropck_misc_variants.stderr
+++ b/tests/ui/span/dropck_misc_variants.stderr
@@ -1,6 +1,9 @@
error[E0597]: `bomb` does not live long enough
--> $DIR/dropck_misc_variants.rs:23:36
|
+LL | let (_w, bomb);
+ | ---- binding `bomb` declared here
+LL | bomb = vec![""];
LL | _w = Wrap::<&[&str]>(NoisyDrop(&bomb));
| ^^^^^ borrowed value does not live long enough
LL | }
@@ -14,6 +17,9 @@ LL | }
error[E0597]: `v` does not live long enough
--> $DIR/dropck_misc_variants.rs:31:27
|
+LL | let (_w,v);
+ | - binding `v` declared here
+...
LL | let u = NoisyDrop(&v);
| ^^ borrowed value does not live long enough
...
diff --git a/tests/ui/span/dropck_vec_cycle_checked.stderr b/tests/ui/span/dropck_vec_cycle_checked.stderr
index 7ff991c0c..5817439c0 100644
--- a/tests/ui/span/dropck_vec_cycle_checked.stderr
+++ b/tests/ui/span/dropck_vec_cycle_checked.stderr
@@ -1,6 +1,9 @@
error[E0597]: `c2` does not live long enough
--> $DIR/dropck_vec_cycle_checked.rs:98:24
|
+LL | let (mut c1, mut c2, mut c3);
+ | ------ binding `c2` declared here
+...
LL | c1.v[0].v.set(Some(&c2));
| ^^^ borrowed value does not live long enough
...
@@ -15,6 +18,9 @@ LL | }
error[E0597]: `c3` does not live long enough
--> $DIR/dropck_vec_cycle_checked.rs:100:24
|
+LL | let (mut c1, mut c2, mut c3);
+ | ------ binding `c3` declared here
+...
LL | c1.v[1].v.set(Some(&c3));
| ^^^ borrowed value does not live long enough
...
@@ -29,6 +35,9 @@ LL | }
error[E0597]: `c1` does not live long enough
--> $DIR/dropck_vec_cycle_checked.rs:104:24
|
+LL | let (mut c1, mut c2, mut c3);
+ | ------ binding `c1` declared here
+...
LL | c3.v[0].v.set(Some(&c1));
| ^^^ borrowed value does not live long enough
...
diff --git a/tests/ui/span/issue-107353.rs b/tests/ui/span/issue-107353.rs
new file mode 100644
index 000000000..943f7f0eb
--- /dev/null
+++ b/tests/ui/span/issue-107353.rs
@@ -0,0 +1,9 @@
+// ignore-tidy-linelength
+// Verify that span interning correctly handles having a span of exactly MAX_LEN length.
+// compile-flags: --crate-type=lib
+// check-pass
+
+#![allow(dead_code)]
+fn a<'a, T>() -> &'a T {
+todo!()////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+}
diff --git a/tests/ui/span/issue-23338-locals-die-before-temps-of-body.stderr b/tests/ui/span/issue-23338-locals-die-before-temps-of-body.stderr
index 3c2022748..e1a377203 100644
--- a/tests/ui/span/issue-23338-locals-die-before-temps-of-body.stderr
+++ b/tests/ui/span/issue-23338-locals-die-before-temps-of-body.stderr
@@ -1,6 +1,8 @@
error[E0597]: `y` does not live long enough
--> $DIR/issue-23338-locals-die-before-temps-of-body.rs:10:5
|
+LL | let y = x;
+ | - binding `y` declared here
LL | y.borrow().clone()
| ^^^^^^^^^^
| |
@@ -22,6 +24,8 @@ LL | let x = y.borrow().clone(); x
error[E0597]: `y` does not live long enough
--> $DIR/issue-23338-locals-die-before-temps-of-body.rs:17:9
|
+LL | let y = x;
+ | - binding `y` declared here
LL | y.borrow().clone()
| ^^^^^^^^^^
| |
diff --git a/tests/ui/span/issue-24805-dropck-child-has-items-via-parent.stderr b/tests/ui/span/issue-24805-dropck-child-has-items-via-parent.stderr
index 809e60a8c..c3b6d7580 100644
--- a/tests/ui/span/issue-24805-dropck-child-has-items-via-parent.stderr
+++ b/tests/ui/span/issue-24805-dropck-child-has-items-via-parent.stderr
@@ -1,6 +1,9 @@
error[E0597]: `d1` does not live long enough
--> $DIR/issue-24805-dropck-child-has-items-via-parent.rs:28:18
|
+LL | let (_d, d1);
+ | -- binding `d1` declared here
+...
LL | _d = D_Child(&d1);
| ^^^ borrowed value does not live long enough
...
diff --git a/tests/ui/span/issue-24805-dropck-trait-has-items.stderr b/tests/ui/span/issue-24805-dropck-trait-has-items.stderr
index 2e2170669..e52c57d9a 100644
--- a/tests/ui/span/issue-24805-dropck-trait-has-items.stderr
+++ b/tests/ui/span/issue-24805-dropck-trait-has-items.stderr
@@ -1,6 +1,9 @@
error[E0597]: `d1` does not live long enough
--> $DIR/issue-24805-dropck-trait-has-items.rs:37:26
|
+LL | let (_d, d1);
+ | -- binding `d1` declared here
+LL | d1 = D_HasSelfMethod(1);
LL | _d = D_HasSelfMethod(&d1);
| ^^^ borrowed value does not live long enough
LL | }
@@ -14,6 +17,9 @@ LL | }
error[E0597]: `d1` does not live long enough
--> $DIR/issue-24805-dropck-trait-has-items.rs:43:33
|
+LL | let (_d, d1);
+ | -- binding `d1` declared here
+LL | d1 = D_HasMethodWithSelfArg(1);
LL | _d = D_HasMethodWithSelfArg(&d1);
| ^^^ borrowed value does not live long enough
LL | }
@@ -27,6 +33,9 @@ LL | }
error[E0597]: `d1` does not live long enough
--> $DIR/issue-24805-dropck-trait-has-items.rs:49:20
|
+LL | let (_d, d1);
+ | -- binding `d1` declared here
+LL | d1 = D_HasType(1);
LL | _d = D_HasType(&d1);
| ^^^ borrowed value does not live long enough
LL | }
diff --git a/tests/ui/span/issue-24895-copy-clone-dropck.stderr b/tests/ui/span/issue-24895-copy-clone-dropck.stderr
index 18a3dc9e6..83db4d509 100644
--- a/tests/ui/span/issue-24895-copy-clone-dropck.stderr
+++ b/tests/ui/span/issue-24895-copy-clone-dropck.stderr
@@ -1,6 +1,9 @@
error[E0597]: `d1` does not live long enough
--> $DIR/issue-24895-copy-clone-dropck.rs:27:14
|
+LL | let (d2, d1);
+ | -- binding `d1` declared here
+LL | d1 = D(34, "d1");
LL | d2 = D(S(&d1, "inner"), "d2");
| ^^^ borrowed value does not live long enough
LL | }
diff --git a/tests/ui/span/issue-25199.stderr b/tests/ui/span/issue-25199.stderr
index d70a4afc1..1e0276f0c 100644
--- a/tests/ui/span/issue-25199.stderr
+++ b/tests/ui/span/issue-25199.stderr
@@ -1,6 +1,8 @@
error[E0597]: `container` does not live long enough
--> $DIR/issue-25199.rs:70:27
|
+LL | let container = Container::new();
+ | --------- binding `container` declared here
LL | let test = Test{test: &container};
| ^^^^^^^^^^ borrowed value does not live long enough
...
diff --git a/tests/ui/span/issue-26656.stderr b/tests/ui/span/issue-26656.stderr
index 1e939c484..fea6e0012 100644
--- a/tests/ui/span/issue-26656.stderr
+++ b/tests/ui/span/issue-26656.stderr
@@ -1,6 +1,9 @@
error[E0597]: `ticking` does not live long enough
--> $DIR/issue-26656.rs:40:35
|
+LL | let (mut zook, ticking);
+ | ------- binding `ticking` declared here
+...
LL | zook.button = B::BigRedButton(&ticking);
| ^^^^^^^^ borrowed value does not live long enough
LL | }
diff --git a/tests/ui/span/issue-29106.stderr b/tests/ui/span/issue-29106.stderr
index 71fbd60ee..28ee7acd9 100644
--- a/tests/ui/span/issue-29106.stderr
+++ b/tests/ui/span/issue-29106.stderr
@@ -1,6 +1,9 @@
error[E0597]: `x` does not live long enough
--> $DIR/issue-29106.rs:16:26
|
+LL | let (y, x);
+ | - binding `x` declared here
+LL | x = "alive".to_string();
LL | y = Arc::new(Foo(&x));
| ^^ borrowed value does not live long enough
LL | }
@@ -14,6 +17,9 @@ LL | }
error[E0597]: `x` does not live long enough
--> $DIR/issue-29106.rs:23:25
|
+LL | let (y, x);
+ | - binding `x` declared here
+LL | x = "alive".to_string();
LL | y = Rc::new(Foo(&x));
| ^^ borrowed value does not live long enough
LL | }
diff --git a/tests/ui/span/issue-33884.stderr b/tests/ui/span/issue-33884.stderr
index aee153085..8cece07cd 100644
--- a/tests/ui/span/issue-33884.stderr
+++ b/tests/ui/span/issue-33884.stderr
@@ -2,7 +2,7 @@ error[E0308]: mismatched types
--> $DIR/issue-33884.rs:6:22
|
LL | stream.write_fmt(format!("message received"))
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected struct `Arguments`, found struct `String`
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `Arguments<'_>`, found `String`
|
= note: this error originates in the macro `format` (in Nightly builds, run with -Z macro-backtrace for more info)
diff --git a/tests/ui/span/issue-34264.stderr b/tests/ui/span/issue-34264.stderr
index 15179954a..f0dea66f6 100644
--- a/tests/ui/span/issue-34264.stderr
+++ b/tests/ui/span/issue-34264.stderr
@@ -54,17 +54,16 @@ error[E0061]: this function takes 2 arguments but 3 arguments were supplied
--> $DIR/issue-34264.rs:7:5
|
LL | foo(Some(42), 2, "");
- | ^^^ -- argument of type `&'static str` unexpected
+ | ^^^ ----
+ | | |
+ | | unexpected argument of type `&'static str`
+ | help: remove the extra argument
|
note: function defined here
--> $DIR/issue-34264.rs:1:4
|
LL | fn foo(Option<i32>, String) {}
| ^^^ ----------- ------
-help: remove the extra argument
- |
-LL | foo(Some(42), 2);
- | ~~~~~~~~~~~~~
error[E0308]: mismatched types
--> $DIR/issue-34264.rs:8:13
@@ -84,17 +83,16 @@ error[E0061]: this function takes 2 arguments but 3 arguments were supplied
--> $DIR/issue-34264.rs:10:5
|
LL | bar(1, 2, 3);
- | ^^^ - argument of type `{integer}` unexpected
+ | ^^^ ---
+ | | |
+ | | unexpected argument of type `{integer}`
+ | help: remove the extra argument
|
note: function defined here
--> $DIR/issue-34264.rs:3:4
|
LL | fn bar(x, y: usize) {}
| ^^^ - --------
-help: remove the extra argument
- |
-LL | bar(1, 2);
- | ~~~~~~
error: aborting due to 6 previous errors
diff --git a/tests/ui/span/issue-36537.stderr b/tests/ui/span/issue-36537.stderr
index 79a0ebaeb..6c330c1a0 100644
--- a/tests/ui/span/issue-36537.stderr
+++ b/tests/ui/span/issue-36537.stderr
@@ -1,6 +1,8 @@
error[E0597]: `a` does not live long enough
--> $DIR/issue-36537.rs:5:13
|
+LL | let a = 42;
+ | - binding `a` declared here
LL | p = &a;
| ^^ borrowed value does not live long enough
...
diff --git a/tests/ui/span/issue-37767.stderr b/tests/ui/span/issue-37767.stderr
index f7732847a..b612fdf16 100644
--- a/tests/ui/span/issue-37767.stderr
+++ b/tests/ui/span/issue-37767.stderr
@@ -14,11 +14,11 @@ note: candidate #2 is defined in the trait `B`
|
LL | fn foo(&mut self) {}
| ^^^^^^^^^^^^^^^^^
-help: disambiguate the associated function for candidate #1
+help: disambiguate the method for candidate #1
|
LL | A::foo(&a)
| ~~~~~~~~~~
-help: disambiguate the associated function for candidate #2
+help: disambiguate the method for candidate #2
|
LL | B::foo(&a)
| ~~~~~~~~~~
@@ -39,11 +39,11 @@ note: candidate #2 is defined in the trait `D`
|
LL | fn foo(&self) {}
| ^^^^^^^^^^^^^
-help: disambiguate the associated function for candidate #1
+help: disambiguate the method for candidate #1
|
LL | C::foo(&a)
| ~~~~~~~~~~
-help: disambiguate the associated function for candidate #2
+help: disambiguate the method for candidate #2
|
LL | D::foo(&a)
| ~~~~~~~~~~
@@ -64,11 +64,11 @@ note: candidate #2 is defined in the trait `F`
|
LL | fn foo(self) {}
| ^^^^^^^^^^^^
-help: disambiguate the associated function for candidate #1
+help: disambiguate the method for candidate #1
|
LL | E::foo(a)
| ~~~~~~~~~
-help: disambiguate the associated function for candidate #2
+help: disambiguate the method for candidate #2
|
LL | F::foo(a)
| ~~~~~~~~~
diff --git a/tests/ui/span/issue-39018.stderr b/tests/ui/span/issue-39018.stderr
index 5d4d692b2..771f21c45 100644
--- a/tests/ui/span/issue-39018.stderr
+++ b/tests/ui/span/issue-39018.stderr
@@ -80,7 +80,7 @@ error[E0308]: mismatched types
LL | let _ = a + b;
| ^
| |
- | expected `&str`, found struct `String`
+ | expected `&str`, found `String`
| help: consider borrowing here: `&b`
error[E0369]: cannot add `String` to `&String`
diff --git a/tests/ui/span/issue-40157.stderr b/tests/ui/span/issue-40157.stderr
index 57f80214a..a0afd33f7 100644
--- a/tests/ui/span/issue-40157.stderr
+++ b/tests/ui/span/issue-40157.stderr
@@ -2,11 +2,10 @@ 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
- | borrow later used here
+ | --- ^^^^^^^^^^ - `foo` dropped here while still borrowed
+ | | |
+ | | borrowed value does not live long enough
+ | binding `foo` declared here
error: aborting due to previous error
diff --git a/tests/ui/span/issue-42234-unknown-receiver-type.full.stderr b/tests/ui/span/issue-42234-unknown-receiver-type.full.stderr
index 2b1789908..e01e1edab 100644
--- a/tests/ui/span/issue-42234-unknown-receiver-type.full.stderr
+++ b/tests/ui/span/issue-42234-unknown-receiver-type.full.stderr
@@ -15,7 +15,7 @@ error[E0282]: type annotations needed
--> $DIR/issue-42234-unknown-receiver-type.rs:15:10
|
LL | .sum::<_>()
- | ^^^ cannot infer type of the type parameter `S` declared on the associated function `sum`
+ | ^^^ cannot infer type of the type parameter `S` declared on the method `sum`
|
help: consider specifying the generic argument
|
diff --git a/tests/ui/span/issue-42234-unknown-receiver-type.generic_arg.stderr b/tests/ui/span/issue-42234-unknown-receiver-type.generic_arg.stderr
index d93d54e87..a4b652565 100644
--- a/tests/ui/span/issue-42234-unknown-receiver-type.generic_arg.stderr
+++ b/tests/ui/span/issue-42234-unknown-receiver-type.generic_arg.stderr
@@ -15,7 +15,7 @@ error[E0282]: type annotations needed
--> $DIR/issue-42234-unknown-receiver-type.rs:15:10
|
LL | .sum::<_>()
- | ^^^ cannot infer type of the type parameter `S` declared on the associated function `sum`
+ | ^^^ cannot infer type of the type parameter `S` declared on the method `sum`
|
help: consider specifying the generic argument
|
diff --git a/tests/ui/span/issue28498-reject-lifetime-param.stderr b/tests/ui/span/issue28498-reject-lifetime-param.stderr
index 3119ddd03..94c450c7b 100644
--- a/tests/ui/span/issue28498-reject-lifetime-param.stderr
+++ b/tests/ui/span/issue28498-reject-lifetime-param.stderr
@@ -1,6 +1,9 @@
error[E0597]: `first_dropped` does not live long enough
--> $DIR/issue28498-reject-lifetime-param.rs:32:19
|
+LL | let (foo1, first_dropped);
+ | ------------- binding `first_dropped` declared here
+...
LL | foo1 = Foo(1, &first_dropped);
| ^^^^^^^^^^^^^^ borrowed value does not live long enough
...
diff --git a/tests/ui/span/issue28498-reject-passed-to-fn.stderr b/tests/ui/span/issue28498-reject-passed-to-fn.stderr
index 60e8a648c..e133f75d5 100644
--- a/tests/ui/span/issue28498-reject-passed-to-fn.stderr
+++ b/tests/ui/span/issue28498-reject-passed-to-fn.stderr
@@ -1,6 +1,9 @@
error[E0597]: `first_dropped` does not live long enough
--> $DIR/issue28498-reject-passed-to-fn.rs:34:19
|
+LL | let (foo1, first_dropped);
+ | ------------- binding `first_dropped` declared here
+...
LL | foo1 = Foo(1, &first_dropped, Box::new(callback));
| ^^^^^^^^^^^^^^ borrowed value does not live long enough
...
diff --git a/tests/ui/span/issue28498-reject-trait-bound.stderr b/tests/ui/span/issue28498-reject-trait-bound.stderr
index 22e4a8205..9ab3cdd13 100644
--- a/tests/ui/span/issue28498-reject-trait-bound.stderr
+++ b/tests/ui/span/issue28498-reject-trait-bound.stderr
@@ -1,6 +1,9 @@
error[E0597]: `first_dropped` does not live long enough
--> $DIR/issue28498-reject-trait-bound.rs:34:19
|
+LL | let (foo1, first_dropped);
+ | ------------- binding `first_dropped` declared here
+...
LL | foo1 = Foo(1, &first_dropped);
| ^^^^^^^^^^^^^^ borrowed value does not live long enough
...
diff --git a/tests/ui/span/missing-unit-argument.stderr b/tests/ui/span/missing-unit-argument.stderr
index ef4d732b5..ff89f7753 100644
--- a/tests/ui/span/missing-unit-argument.stderr
+++ b/tests/ui/span/missing-unit-argument.stderr
@@ -65,7 +65,7 @@ error[E0061]: this method takes 1 argument but 0 arguments were supplied
LL | S.baz();
| ^^^-- an argument of type `()` is missing
|
-note: associated function defined here
+note: method defined here
--> $DIR/missing-unit-argument.rs:6:8
|
LL | fn baz(self, (): ()) { }
@@ -81,7 +81,7 @@ error[E0061]: this method takes 1 argument but 0 arguments were supplied
LL | S.generic::<()>();
| ^^^^^^^^^^^^^-- an argument of type `()` is missing
|
-note: associated function defined here
+note: method defined here
--> $DIR/missing-unit-argument.rs:7:8
|
LL | fn generic<T>(self, _: T) { }
diff --git a/tests/ui/span/mut-ptr-cant-outlive-ref.stderr b/tests/ui/span/mut-ptr-cant-outlive-ref.stderr
index 4d976a7bb..be56f9489 100644
--- a/tests/ui/span/mut-ptr-cant-outlive-ref.stderr
+++ b/tests/ui/span/mut-ptr-cant-outlive-ref.stderr
@@ -1,6 +1,8 @@
error[E0597]: `b` does not live long enough
--> $DIR/mut-ptr-cant-outlive-ref.rs:8:15
|
+LL | let b = m.borrow();
+ | - binding `b` declared here
LL | p = &*b;
| ^ borrowed value does not live long enough
LL | }
diff --git a/tests/ui/span/range-2.stderr b/tests/ui/span/range-2.stderr
index 8ca8156b0..d7084b00b 100644
--- a/tests/ui/span/range-2.stderr
+++ b/tests/ui/span/range-2.stderr
@@ -3,7 +3,9 @@ error[E0597]: `a` does not live long enough
|
LL | let r = {
| - borrow later stored here
-...
+LL | let a = 42;
+ | - binding `a` declared here
+LL | let b = 42;
LL | &a..&b
| ^^ borrowed value does not live long enough
LL | };
@@ -14,7 +16,9 @@ error[E0597]: `b` does not live long enough
|
LL | let r = {
| - borrow later stored here
-...
+LL | let a = 42;
+LL | let b = 42;
+ | - binding `b` declared here
LL | &a..&b
| ^^ borrowed value does not live long enough
LL | };
diff --git a/tests/ui/span/regionck-unboxed-closure-lifetimes.stderr b/tests/ui/span/regionck-unboxed-closure-lifetimes.stderr
index 0b985de60..fb3fad6ae 100644
--- a/tests/ui/span/regionck-unboxed-closure-lifetimes.stderr
+++ b/tests/ui/span/regionck-unboxed-closure-lifetimes.stderr
@@ -1,6 +1,8 @@
error[E0597]: `c` does not live long enough
--> $DIR/regionck-unboxed-closure-lifetimes.rs:8:21
|
+LL | let c = 1;
+ | - binding `c` declared here
LL | let c_ref = &c;
| ^^ borrowed value does not live long enough
...
diff --git a/tests/ui/span/regions-close-over-type-parameter-2.stderr b/tests/ui/span/regions-close-over-type-parameter-2.stderr
index 2e584d9a8..fed40a4fd 100644
--- a/tests/ui/span/regions-close-over-type-parameter-2.stderr
+++ b/tests/ui/span/regions-close-over-type-parameter-2.stderr
@@ -1,6 +1,8 @@
error[E0597]: `tmp0` does not live long enough
--> $DIR/regions-close-over-type-parameter-2.rs:23:20
|
+LL | let tmp0 = 3;
+ | ---- binding `tmp0` declared here
LL | let tmp1 = &tmp0;
| ^^^^^ borrowed value does not live long enough
LL | repeater3(tmp1)
diff --git a/tests/ui/span/regions-escape-loop-via-variable.stderr b/tests/ui/span/regions-escape-loop-via-variable.stderr
index 42df66852..e5c7d8b26 100644
--- a/tests/ui/span/regions-escape-loop-via-variable.stderr
+++ b/tests/ui/span/regions-escape-loop-via-variable.stderr
@@ -2,7 +2,9 @@ error[E0597]: `x` does not live long enough
--> $DIR/regions-escape-loop-via-variable.rs:11:13
|
LL | let x = 1 + *p;
- | -- borrow later used here
+ | - -- borrow later used here
+ | |
+ | binding `x` declared here
LL | p = &x;
| ^^ borrowed value does not live long enough
LL | }
diff --git a/tests/ui/span/regions-escape-loop-via-vec.stderr b/tests/ui/span/regions-escape-loop-via-vec.stderr
index 2b6493077..532ac3606 100644
--- a/tests/ui/span/regions-escape-loop-via-vec.stderr
+++ b/tests/ui/span/regions-escape-loop-via-vec.stderr
@@ -2,7 +2,7 @@ error[E0503]: cannot use `x` because it was mutably borrowed
--> $DIR/regions-escape-loop-via-vec.rs:5:11
|
LL | let mut _y = vec![&mut x];
- | ------ borrow of `x` occurs here
+ | ------ `x` is borrowed here
LL | while x < 10 {
| ^ use of borrowed `x`
LL | let mut z = x;
@@ -13,7 +13,7 @@ error[E0503]: cannot use `x` because it was mutably borrowed
--> $DIR/regions-escape-loop-via-vec.rs:6:21
|
LL | let mut _y = vec![&mut x];
- | ------ borrow of `x` occurs here
+ | ------ `x` is borrowed here
LL | while x < 10 {
LL | let mut z = x;
| ^ use of borrowed `x`
@@ -23,11 +23,10 @@ LL | _y.push(&mut z);
error[E0597]: `z` does not live long enough
--> $DIR/regions-escape-loop-via-vec.rs:7:17
|
+LL | let mut z = x;
+ | ----- binding `z` declared here
LL | _y.push(&mut z);
- | --------^^^^^^-
- | | |
- | | borrowed value does not live long enough
- | borrow later used here
+ | ^^^^^^ borrowed value does not live long enough
...
LL | }
| - `z` dropped here while still borrowed
@@ -36,7 +35,7 @@ error[E0503]: cannot use `x` because it was mutably borrowed
--> $DIR/regions-escape-loop-via-vec.rs:9:9
|
LL | let mut _y = vec![&mut x];
- | ------ borrow of `x` occurs here
+ | ------ `x` is borrowed here
...
LL | _y.push(&mut z);
| --------------- borrow later used here
diff --git a/tests/ui/span/regions-infer-borrow-scope-within-loop.stderr b/tests/ui/span/regions-infer-borrow-scope-within-loop.stderr
index fd67c65c4..47931db84 100644
--- a/tests/ui/span/regions-infer-borrow-scope-within-loop.stderr
+++ b/tests/ui/span/regions-infer-borrow-scope-within-loop.stderr
@@ -1,6 +1,9 @@
error[E0597]: `*x` does not live long enough
--> $DIR/regions-infer-borrow-scope-within-loop.rs:13:20
|
+LL | let x = make_box();
+ | - binding `x` declared here
+...
LL | y = borrow(&*x);
| ^^^ borrowed value does not live long enough
...
diff --git a/tests/ui/span/send-is-not-static-ensures-scoping.stderr b/tests/ui/span/send-is-not-static-ensures-scoping.stderr
index 65d10c130..bae0befca 100644
--- a/tests/ui/span/send-is-not-static-ensures-scoping.stderr
+++ b/tests/ui/span/send-is-not-static-ensures-scoping.stderr
@@ -4,6 +4,7 @@ error[E0597]: `x` does not live long enough
LL | let bad = {
| --- borrow later stored here
LL | let x = 1;
+ | - binding `x` declared here
LL | let y = &x;
| ^^ borrowed value does not live long enough
...
diff --git a/tests/ui/span/send-is-not-static-std-sync-2.stderr b/tests/ui/span/send-is-not-static-std-sync-2.stderr
index bcd07e116..b0267fa6f 100644
--- a/tests/ui/span/send-is-not-static-std-sync-2.stderr
+++ b/tests/ui/span/send-is-not-static-std-sync-2.stderr
@@ -4,6 +4,7 @@ error[E0597]: `x` does not live long enough
LL | let lock = {
| ---- borrow later stored here
LL | let x = 1;
+ | - binding `x` declared here
LL | Mutex::new(&x)
| ^^ borrowed value does not live long enough
LL | };
@@ -15,6 +16,7 @@ error[E0597]: `x` does not live long enough
LL | let lock = {
| ---- borrow later stored here
LL | let x = 1;
+ | - binding `x` declared here
LL | RwLock::new(&x)
| ^^ borrowed value does not live long enough
LL | };
@@ -25,7 +27,9 @@ error[E0597]: `x` does not live long enough
|
LL | let (_tx, rx) = {
| --- borrow later used here
-...
+LL | let x = 1;
+ | - binding `x` declared here
+LL | let (tx, rx) = mpsc::channel();
LL | let _ = tx.send(&x);
| ^^ borrowed value does not live long enough
LL | (tx, rx)
diff --git a/tests/ui/span/send-is-not-static-std-sync.stderr b/tests/ui/span/send-is-not-static-std-sync.stderr
index 5d493a3e4..7dfe94bca 100644
--- a/tests/ui/span/send-is-not-static-std-sync.stderr
+++ b/tests/ui/span/send-is-not-static-std-sync.stderr
@@ -1,6 +1,9 @@
error[E0505]: cannot move out of `y` because it is borrowed
--> $DIR/send-is-not-static-std-sync.rs:13:10
|
+LL | let y = Box::new(1);
+ | - binding `y` declared here
+LL | let lock = Mutex::new(&x);
LL | *lock.lock().unwrap() = &*y;
| --- borrow of `*y` occurs here
LL | drop(y);
@@ -12,6 +15,8 @@ LL | *lock.lock().unwrap() = &z;
error[E0597]: `z` does not live long enough
--> $DIR/send-is-not-static-std-sync.rs:16:33
|
+LL | let z = 2;
+ | - binding `z` declared here
LL | *lock.lock().unwrap() = &z;
| ^^ borrowed value does not live long enough
LL | }
@@ -23,6 +28,9 @@ LL | lock.use_ref(); // (Mutex is #[may_dangle] so its dtor does not use `z`
error[E0505]: cannot move out of `y` because it is borrowed
--> $DIR/send-is-not-static-std-sync.rs:27:10
|
+LL | let y = Box::new(1);
+ | - binding `y` declared here
+LL | let lock = RwLock::new(&x);
LL | *lock.write().unwrap() = &*y;
| --- borrow of `*y` occurs here
LL | drop(y);
@@ -34,6 +42,8 @@ LL | *lock.write().unwrap() = &z;
error[E0597]: `z` does not live long enough
--> $DIR/send-is-not-static-std-sync.rs:30:34
|
+LL | let z = 2;
+ | - binding `z` declared here
LL | *lock.write().unwrap() = &z;
| ^^ borrowed value does not live long enough
LL | }
@@ -45,6 +55,9 @@ LL | lock.use_ref(); // (RwLock is #[may_dangle] so its dtor does not use `z
error[E0505]: cannot move out of `y` because it is borrowed
--> $DIR/send-is-not-static-std-sync.rs:43:10
|
+LL | let y = Box::new(1);
+ | - binding `y` declared here
+...
LL | tx.send(&*y);
| --- borrow of `*y` occurs here
LL | drop(y);
@@ -56,6 +69,8 @@ LL | tx.send(&z).unwrap();
error[E0597]: `z` does not live long enough
--> $DIR/send-is-not-static-std-sync.rs:46:17
|
+LL | let z = 2;
+ | - binding `z` declared here
LL | tx.send(&z).unwrap();
| ^^ borrowed value does not live long enough
LL | }
diff --git a/tests/ui/span/type-annotations-needed-expr.stderr b/tests/ui/span/type-annotations-needed-expr.stderr
index 9dff6c64d..65a90318a 100644
--- a/tests/ui/span/type-annotations-needed-expr.stderr
+++ b/tests/ui/span/type-annotations-needed-expr.stderr
@@ -2,7 +2,7 @@ error[E0282]: type annotations needed
--> $DIR/type-annotations-needed-expr.rs:2:39
|
LL | let _ = (vec![1,2,3]).into_iter().sum() as f64;
- | ^^^ cannot infer type of the type parameter `S` declared on the associated function `sum`
+ | ^^^ cannot infer type of the type parameter `S` declared on the method `sum`
|
help: consider specifying the generic argument
|
diff --git a/tests/ui/span/vec-must-not-hide-type-from-dropck.stderr b/tests/ui/span/vec-must-not-hide-type-from-dropck.stderr
index f87c32d1a..f2fefca41 100644
--- a/tests/ui/span/vec-must-not-hide-type-from-dropck.stderr
+++ b/tests/ui/span/vec-must-not-hide-type-from-dropck.stderr
@@ -1,6 +1,9 @@
error[E0597]: `c2` does not live long enough
--> $DIR/vec-must-not-hide-type-from-dropck.rs:117:24
|
+LL | let (mut c1, mut c2);
+ | ------ binding `c2` declared here
+...
LL | c1.v[0].v.set(Some(&c2));
| ^^^ borrowed value does not live long enough
...
@@ -15,6 +18,9 @@ LL | }
error[E0597]: `c1` does not live long enough
--> $DIR/vec-must-not-hide-type-from-dropck.rs:119:24
|
+LL | let (mut c1, mut c2);
+ | ------ binding `c1` declared here
+...
LL | c2.v[0].v.set(Some(&c1));
| ^^^ borrowed value does not live long enough
LL |
diff --git a/tests/ui/span/vec_refs_data_with_early_death.stderr b/tests/ui/span/vec_refs_data_with_early_death.stderr
index 684e78453..73f27144a 100644
--- a/tests/ui/span/vec_refs_data_with_early_death.stderr
+++ b/tests/ui/span/vec_refs_data_with_early_death.stderr
@@ -1,6 +1,9 @@
error[E0597]: `x` does not live long enough
--> $DIR/vec_refs_data_with_early_death.rs:17:12
|
+LL | let x: i8 = 3;
+ | - binding `x` declared here
+...
LL | v.push(&x);
| ^^ borrowed value does not live long enough
...
@@ -15,6 +18,9 @@ LL | }
error[E0597]: `y` does not live long enough
--> $DIR/vec_refs_data_with_early_death.rs:19:12
|
+LL | let y: i8 = 4;
+ | - binding `y` declared here
+...
LL | v.push(&y);
| ^^ borrowed value does not live long enough
...
diff --git a/tests/ui/span/wf-method-late-bound-regions.stderr b/tests/ui/span/wf-method-late-bound-regions.stderr
index 6b0b00820..64c2d0f16 100644
--- a/tests/ui/span/wf-method-late-bound-regions.stderr
+++ b/tests/ui/span/wf-method-late-bound-regions.stderr
@@ -4,6 +4,7 @@ error[E0597]: `pointer` does not live long enough
LL | let dangling = {
| -------- borrow later stored here
LL | let pointer = Box::new(42);
+ | ------- binding `pointer` declared here
LL | f2.xmute(&pointer)
| ^^^^^^^^ borrowed value does not live long enough
LL | };
diff --git a/tests/ui/specialization/defaultimpl/specialization-no-default.stderr b/tests/ui/specialization/defaultimpl/specialization-no-default.stderr
index 770be2af2..f9e62a99b 100644
--- a/tests/ui/specialization/defaultimpl/specialization-no-default.stderr
+++ b/tests/ui/specialization/defaultimpl/specialization-no-default.stderr
@@ -15,7 +15,7 @@ LL | impl<T> Foo for T {
| ----------------- parent `impl` is here
...
LL | fn foo(&self) {}
- | ^^^^^^^^^^^^^^^^ cannot specialize default item `foo`
+ | ^^^^^^^^^^^^^ cannot specialize default item `foo`
|
= note: to specialize, `foo` in the parent `impl` must be marked `default`
@@ -26,7 +26,7 @@ LL | impl<T> Foo for T {
| ----------------- parent `impl` is here
...
LL | fn bar(&self) {}
- | ^^^^^^^^^^^^^^^^ cannot specialize default item `bar`
+ | ^^^^^^^^^^^^^ cannot specialize default item `bar`
|
= note: to specialize, `bar` in the parent `impl` must be marked `default`
@@ -37,7 +37,7 @@ LL | impl<T> Bar for T {
| ----------------- parent `impl` is here
...
LL | type T = ();
- | ^^^^^^^^^^^^ cannot specialize default item `T`
+ | ^^^^^^ cannot specialize default item `T`
|
= note: to specialize, `T` in the parent `impl` must be marked `default`
@@ -48,7 +48,7 @@ LL | impl<T: Clone> Baz for T {
| ------------------------ parent `impl` is here
...
LL | fn baz(&self) {}
- | ^^^^^^^^^^^^^^^^ cannot specialize default item `baz`
+ | ^^^^^^^^^^^^^ cannot specialize default item `baz`
|
= note: to specialize, `baz` in the parent `impl` must be marked `default`
@@ -59,7 +59,7 @@ LL | impl<T: Clone> Redundant for T {
| ------------------------------ parent `impl` is here
...
LL | fn redundant(&self) {}
- | ^^^^^^^^^^^^^^^^^^^^^^ cannot specialize default item `redundant`
+ | ^^^^^^^^^^^^^^^^^^^ cannot specialize default item `redundant`
|
= note: to specialize, `redundant` in the parent `impl` must be marked `default`
diff --git a/tests/ui/specialization/issue-50452-fail.stderr b/tests/ui/specialization/issue-50452-fail.stderr
index 5c136adc4..3fc29fff2 100644
--- a/tests/ui/specialization/issue-50452-fail.stderr
+++ b/tests/ui/specialization/issue-50452-fail.stderr
@@ -12,7 +12,7 @@ error[E0520]: `foo` specializes an item from a parent `impl`, but that item is n
--> $DIR/issue-50452-fail.rs:10:5
|
LL | fn foo() {}
- | ^^^^^^^^^^^ cannot specialize default item `foo`
+ | ^^^^^^^^ cannot specialize default item `foo`
...
LL | impl<T> Foo for T {
| ----------------- parent `impl` is here
diff --git a/tests/ui/specialization/non-defaulted-item-fail.stderr b/tests/ui/specialization/non-defaulted-item-fail.stderr
index faa14555a..9d62a353d 100644
--- a/tests/ui/specialization/non-defaulted-item-fail.stderr
+++ b/tests/ui/specialization/non-defaulted-item-fail.stderr
@@ -15,7 +15,7 @@ LL | impl<T> Foo for Box<T> {
| ---------------------- parent `impl` is here
...
LL | type Ty = Vec<()>;
- | ^^^^^^^^^^^^^^^^^^ cannot specialize default item `Ty`
+ | ^^^^^^^ cannot specialize default item `Ty`
|
= note: to specialize, `Ty` in the parent `impl` must be marked `default`
@@ -26,7 +26,7 @@ LL | impl<T> Foo for Box<T> {
| ---------------------- parent `impl` is here
...
LL | const CONST: u8 = 42;
- | ^^^^^^^^^^^^^^^^^^^^^ cannot specialize default item `CONST`
+ | ^^^^^^^^^^^^^^^ cannot specialize default item `CONST`
|
= note: to specialize, `CONST` in the parent `impl` must be marked `default`
@@ -37,7 +37,7 @@ LL | impl<T> Foo for Box<T> {
| ---------------------- parent `impl` is here
...
LL | fn foo(&self) -> bool { true }
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot specialize default item `foo`
+ | ^^^^^^^^^^^^^^^^^^^^^ cannot specialize default item `foo`
|
= note: to specialize, `foo` in the parent `impl` must be marked `default`
@@ -48,7 +48,7 @@ LL | impl<T> Foo for Vec<T> {}
| ---------------------- parent `impl` is here
...
LL | type Ty = Vec<()>;
- | ^^^^^^^^^^^^^^^^^^ cannot specialize default item `Ty`
+ | ^^^^^^^ cannot specialize default item `Ty`
|
= note: to specialize, `Ty` in the parent `impl` must be marked `default`
@@ -59,7 +59,7 @@ LL | impl<T> Foo for Vec<T> {}
| ---------------------- parent `impl` is here
...
LL | const CONST: u8 = 42;
- | ^^^^^^^^^^^^^^^^^^^^^ cannot specialize default item `CONST`
+ | ^^^^^^^^^^^^^^^ cannot specialize default item `CONST`
|
= note: to specialize, `CONST` in the parent `impl` must be marked `default`
@@ -70,7 +70,7 @@ LL | impl<T> Foo for Vec<T> {}
| ---------------------- parent `impl` is here
...
LL | fn foo(&self) -> bool { true }
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot specialize default item `foo`
+ | ^^^^^^^^^^^^^^^^^^^^^ cannot specialize default item `foo`
|
= note: to specialize, `foo` in the parent `impl` must be marked `default`
diff --git a/tests/ui/specialization/specialization-default-types.stderr b/tests/ui/specialization/specialization-default-types.stderr
index 61a556a93..ecccf29a1 100644
--- a/tests/ui/specialization/specialization-default-types.stderr
+++ b/tests/ui/specialization/specialization-default-types.stderr
@@ -16,7 +16,7 @@ LL | default type Output = Box<T>;
LL | default fn generate(self) -> Self::Output {
| ------------ expected `<T as Example>::Output` because of return type
LL | Box::new(self)
- | ^^^^^^^^^^^^^^ expected associated type, found struct `Box`
+ | ^^^^^^^^^^^^^^ expected associated type, found `Box<T>`
|
= note: expected associated type `<T as Example>::Output`
found struct `Box<T>`
@@ -27,7 +27,7 @@ error[E0308]: mismatched types
LL | fn trouble<T>(t: T) -> Box<T> {
| ------ expected `Box<T>` because of return type
LL | Example::generate(t)
- | ^^^^^^^^^^^^^^^^^^^^ expected struct `Box`, found associated type
+ | ^^^^^^^^^^^^^^^^^^^^ expected `Box<T>`, found associated type
|
= note: expected struct `Box<T>`
found associated type `<T as Example>::Output`
diff --git a/tests/ui/specialization/specialization-no-default.stderr b/tests/ui/specialization/specialization-no-default.stderr
index 842cec9c7..695a3f6cc 100644
--- a/tests/ui/specialization/specialization-no-default.stderr
+++ b/tests/ui/specialization/specialization-no-default.stderr
@@ -15,7 +15,7 @@ LL | impl<T> Foo for T {
| ----------------- parent `impl` is here
...
LL | fn foo(&self) {}
- | ^^^^^^^^^^^^^^^^ cannot specialize default item `foo`
+ | ^^^^^^^^^^^^^ cannot specialize default item `foo`
|
= note: to specialize, `foo` in the parent `impl` must be marked `default`
@@ -26,7 +26,7 @@ LL | impl<T> Foo for T {
| ----------------- parent `impl` is here
...
LL | fn bar(&self) {}
- | ^^^^^^^^^^^^^^^^ cannot specialize default item `bar`
+ | ^^^^^^^^^^^^^ cannot specialize default item `bar`
|
= note: to specialize, `bar` in the parent `impl` must be marked `default`
@@ -37,7 +37,7 @@ LL | impl<T> Bar for T {
| ----------------- parent `impl` is here
...
LL | type T = ();
- | ^^^^^^^^^^^^ cannot specialize default item `T`
+ | ^^^^^^ cannot specialize default item `T`
|
= note: to specialize, `T` in the parent `impl` must be marked `default`
@@ -48,7 +48,7 @@ LL | impl<T: Clone> Baz for T {
| ------------------------ parent `impl` is here
...
LL | fn baz(&self) {}
- | ^^^^^^^^^^^^^^^^ cannot specialize default item `baz`
+ | ^^^^^^^^^^^^^ cannot specialize default item `baz`
|
= note: to specialize, `baz` in the parent `impl` must be marked `default`
@@ -59,7 +59,7 @@ LL | impl<T: Clone> Redundant for T {
| ------------------------------ parent `impl` is here
...
LL | default fn redundant(&self) {}
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot specialize default item `redundant`
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot specialize default item `redundant`
|
= note: to specialize, `redundant` in the parent `impl` must be marked `default`
diff --git a/tests/ui/stability-attribute/unresolved_stability_lint.rs b/tests/ui/stability-attribute/unresolved_stability_lint.rs
new file mode 100644
index 000000000..818d228bc
--- /dev/null
+++ b/tests/ui/stability-attribute/unresolved_stability_lint.rs
@@ -0,0 +1,8 @@
+#![feature(staged_api)]
+#![stable(feature = "uwu", since = "1.0.0")]
+
+#[unstable(feature = "foo", issue = "none")]
+impl Foo for () {}
+//~^ ERROR cannot find trait `Foo` in this scope
+
+fn main() {}
diff --git a/tests/ui/stability-attribute/unresolved_stability_lint.stderr b/tests/ui/stability-attribute/unresolved_stability_lint.stderr
new file mode 100644
index 000000000..11d6abcaf
--- /dev/null
+++ b/tests/ui/stability-attribute/unresolved_stability_lint.stderr
@@ -0,0 +1,9 @@
+error[E0405]: cannot find trait `Foo` in this scope
+ --> $DIR/unresolved_stability_lint.rs:5:6
+ |
+LL | impl Foo for () {}
+ | ^^^ not found in this scope
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0405`.
diff --git a/tests/ui/static/bad-const-type.rs b/tests/ui/static/bad-const-type.rs
index 934ee353d..24fd67ecb 100644
--- a/tests/ui/static/bad-const-type.rs
+++ b/tests/ui/static/bad-const-type.rs
@@ -1,4 +1,4 @@
static i: String = 10;
//~^ ERROR mismatched types
-//~| expected struct `String`, found integer
+//~| expected `String`, found integer
fn main() { println!("{}", i); }
diff --git a/tests/ui/static/bad-const-type.stderr b/tests/ui/static/bad-const-type.stderr
index dcc1ee07c..2e930f459 100644
--- a/tests/ui/static/bad-const-type.stderr
+++ b/tests/ui/static/bad-const-type.stderr
@@ -4,7 +4,7 @@ error[E0308]: mismatched types
LL | static i: String = 10;
| ^^- help: try using a conversion method: `.to_string()`
| |
- | expected struct `String`, found integer
+ | expected `String`, found integer
error: aborting due to previous error
diff --git a/tests/ui/static/issue-5216.stderr b/tests/ui/static/issue-5216.stderr
index 1afff28f0..99c8b1aa1 100644
--- a/tests/ui/static/issue-5216.stderr
+++ b/tests/ui/static/issue-5216.stderr
@@ -2,7 +2,7 @@ error[E0308]: mismatched types
--> $DIR/issue-5216.rs:3:21
|
LL | pub static C: S = S(f);
- | - ^ expected struct `Box`, found fn item
+ | - ^ expected `Box<dyn FnMut() + Sync>`, found fn item
| |
| arguments to this struct are incorrect
|
@@ -18,7 +18,7 @@ error[E0308]: mismatched types
--> $DIR/issue-5216.rs:8:19
|
LL | pub static D: T = g;
- | ^ expected struct `Box`, found fn item
+ | ^ expected `Box<dyn FnMut() + Sync>`, found fn item
|
= note: expected struct `Box<(dyn FnMut() + Sync + 'static)>`
found fn item `fn() {g}`
diff --git a/tests/ui/static/static-lifetime-bound.rs b/tests/ui/static/static-lifetime-bound.rs
index b5da91ec3..847fe87b2 100644
--- a/tests/ui/static/static-lifetime-bound.rs
+++ b/tests/ui/static/static-lifetime-bound.rs
@@ -1,4 +1,4 @@
-fn f<'a: 'static>(_: &'a i32) {} //~WARN unnecessary lifetime parameter `'a`
+fn f<'a: 'static>(_: &'a i32) {}
fn main() {
let x = 0;
diff --git a/tests/ui/static/static-lifetime-bound.stderr b/tests/ui/static/static-lifetime-bound.stderr
index ef07a8931..19e55a658 100644
--- a/tests/ui/static/static-lifetime-bound.stderr
+++ b/tests/ui/static/static-lifetime-bound.stderr
@@ -1,14 +1,8 @@
-warning: unnecessary lifetime parameter `'a`
- --> $DIR/static-lifetime-bound.rs:1:6
- |
-LL | fn f<'a: 'static>(_: &'a i32) {}
- | ^^
- |
- = help: you can use the `'static` lifetime directly, in place of `'a`
-
error[E0597]: `x` does not live long enough
--> $DIR/static-lifetime-bound.rs:5:7
|
+LL | let x = 0;
+ | - binding `x` declared here
LL | f(&x);
| --^^-
| | |
@@ -17,6 +11,6 @@ LL | f(&x);
LL | }
| - `x` dropped here while still borrowed
-error: aborting due to previous error; 1 warning emitted
+error: aborting due to previous error
For more information about this error, try `rustc --explain E0597`.
diff --git a/tests/ui/static/static-reference-to-fn-1.stderr b/tests/ui/static/static-reference-to-fn-1.stderr
index 67b478bdb..b68352b51 100644
--- a/tests/ui/static/static-reference-to-fn-1.stderr
+++ b/tests/ui/static/static-reference-to-fn-1.stderr
@@ -2,10 +2,16 @@ error[E0308]: mismatched types
--> $DIR/static-reference-to-fn-1.rs:17:15
|
LL | func: &foo,
- | ^^^^ expected fn pointer, found fn item
+ | ^^^^ expected `&fn() -> Option<isize>`, found `&fn() -> Option<isize> {foo}`
|
= note: expected reference `&fn() -> Option<isize>`
found reference `&fn() -> Option<isize> {foo}`
+ = note: fn items are distinct from fn pointers
+ = note: when the arguments and return types match, functions can be coerced to function pointers
+help: consider casting to a fn pointer
+ |
+LL | func: &(foo as fn() -> Option<isize>),
+ | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
error: aborting due to previous error
diff --git a/tests/ui/statics/uninhabited-static.stderr b/tests/ui/statics/uninhabited-static.stderr
index ef794bb36..437053a44 100644
--- a/tests/ui/statics/uninhabited-static.stderr
+++ b/tests/ui/statics/uninhabited-static.stderr
@@ -53,10 +53,7 @@ warning: the type `Void` does not permit zero-initialization
--> $DIR/uninhabited-static.rs:12:31
|
LL | static VOID2: Void = unsafe { std::mem::transmute(()) };
- | ^^^^^^^^^^^^^^^^^^^^^^^
- | |
- | this code causes undefined behavior when executed
- | help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done
+ | ^^^^^^^^^^^^^^^^^^^^^^^ this code causes undefined behavior when executed
|
note: enums with no inhabited variants have no valid value
--> $DIR/uninhabited-static.rs:4:1
@@ -75,10 +72,7 @@ warning: the type `Void` does not permit zero-initialization
--> $DIR/uninhabited-static.rs:16:32
|
LL | static NEVER2: Void = unsafe { std::mem::transmute(()) };
- | ^^^^^^^^^^^^^^^^^^^^^^^
- | |
- | this code causes undefined behavior when executed
- | help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done
+ | ^^^^^^^^^^^^^^^^^^^^^^^ this code causes undefined behavior when executed
|
note: enums with no inhabited variants have no valid value
--> $DIR/uninhabited-static.rs:4:1
diff --git a/tests/ui/stats/hir-stats.rs b/tests/ui/stats/hir-stats.rs
index 0b89d0b16..9bb87026b 100644
--- a/tests/ui/stats/hir-stats.rs
+++ b/tests/ui/stats/hir-stats.rs
@@ -1,7 +1,11 @@
// check-pass
// compile-flags: -Zhir-stats
// only-x86_64
-// ignore-stage1 FIXME: remove after next bootstrap bump
+
+// Type layouts sometimes change. When that happens, until the next bootstrap
+// bump occurs, stage1 and stage2 will give different outputs for this test.
+// Add an `ignore-stage1` comment marker to work around that problem during
+// that time.
// The aim here is to include at least one of every different type of top-level
// AST/HIR node reported by `-Zhir-stats`.
diff --git a/tests/ui/stats/hir-stats.stderr b/tests/ui/stats/hir-stats.stderr
index 7d9ff2dfb..ee62d8f2d 100644
--- a/tests/ui/stats/hir-stats.stderr
+++ b/tests/ui/stats/hir-stats.stderr
@@ -1,119 +1,119 @@
ast-stats-1 PRE EXPANSION AST STATS
ast-stats-1 Name Accumulated Size Count Item Size
ast-stats-1 ----------------------------------------------------------------
-ast-stats-1 ExprField 48 ( 0.6%) 1 48
-ast-stats-1 GenericArgs 56 ( 0.8%) 1 56
-ast-stats-1 - AngleBracketed 56 ( 0.8%) 1
-ast-stats-1 Crate 56 ( 0.8%) 1 56
-ast-stats-1 Attribute 64 ( 0.9%) 2 32
-ast-stats-1 - Normal 32 ( 0.4%) 1
-ast-stats-1 - DocComment 32 ( 0.4%) 1
-ast-stats-1 Local 72 ( 1.0%) 1 72
-ast-stats-1 WherePredicate 72 ( 1.0%) 1 72
-ast-stats-1 - BoundPredicate 72 ( 1.0%) 1
-ast-stats-1 Arm 96 ( 1.3%) 2 48
-ast-stats-1 ForeignItem 96 ( 1.3%) 1 96
-ast-stats-1 - Fn 96 ( 1.3%) 1
-ast-stats-1 FieldDef 160 ( 2.2%) 2 80
-ast-stats-1 Stmt 160 ( 2.2%) 5 32
-ast-stats-1 - Local 32 ( 0.4%) 1
-ast-stats-1 - MacCall 32 ( 0.4%) 1
-ast-stats-1 - Expr 96 ( 1.3%) 3
-ast-stats-1 Param 160 ( 2.2%) 4 40
-ast-stats-1 FnDecl 200 ( 2.7%) 5 40
-ast-stats-1 Variant 240 ( 3.2%) 2 120
-ast-stats-1 GenericBound 288 ( 3.9%) 4 72
-ast-stats-1 - Trait 288 ( 3.9%) 4
-ast-stats-1 Block 288 ( 3.9%) 6 48
-ast-stats-1 AssocItem 416 ( 5.6%) 4 104
-ast-stats-1 - Type 208 ( 2.8%) 2
-ast-stats-1 - Fn 208 ( 2.8%) 2
-ast-stats-1 GenericParam 480 ( 6.5%) 5 96
-ast-stats-1 Expr 576 ( 7.8%) 8 72
-ast-stats-1 - Path 72 ( 1.0%) 1
-ast-stats-1 - Match 72 ( 1.0%) 1
-ast-stats-1 - Struct 72 ( 1.0%) 1
-ast-stats-1 - Lit 144 ( 1.9%) 2
-ast-stats-1 - Block 216 ( 2.9%) 3
-ast-stats-1 Pat 616 ( 8.3%) 7 88
-ast-stats-1 - Struct 88 ( 1.2%) 1
-ast-stats-1 - Wild 88 ( 1.2%) 1
-ast-stats-1 - Ident 440 ( 5.9%) 5
-ast-stats-1 PathSegment 720 ( 9.7%) 30 24
-ast-stats-1 Ty 896 (12.1%) 14 64
-ast-stats-1 - Ptr 64 ( 0.9%) 1
-ast-stats-1 - Ref 64 ( 0.9%) 1
-ast-stats-1 - ImplicitSelf 128 ( 1.7%) 2
-ast-stats-1 - Path 640 ( 8.6%) 10
-ast-stats-1 Item 1_656 (22.3%) 9 184
-ast-stats-1 - Trait 184 ( 2.5%) 1
-ast-stats-1 - Enum 184 ( 2.5%) 1
-ast-stats-1 - ForeignMod 184 ( 2.5%) 1
-ast-stats-1 - Impl 184 ( 2.5%) 1
-ast-stats-1 - Fn 368 ( 5.0%) 2
-ast-stats-1 - Use 552 ( 7.4%) 3
+ast-stats-1 GenericArgs 40 ( 0.6%) 1 40
+ast-stats-1 - AngleBracketed 40 ( 0.6%) 1
+ast-stats-1 Crate 40 ( 0.6%) 1 40
+ast-stats-1 ExprField 48 ( 0.7%) 1 48
+ast-stats-1 WherePredicate 56 ( 0.9%) 1 56
+ast-stats-1 - BoundPredicate 56 ( 0.9%) 1
+ast-stats-1 Attribute 64 ( 1.0%) 2 32
+ast-stats-1 - Normal 32 ( 0.5%) 1
+ast-stats-1 - DocComment 32 ( 0.5%) 1
+ast-stats-1 Local 72 ( 1.1%) 1 72
+ast-stats-1 Arm 96 ( 1.5%) 2 48
+ast-stats-1 ForeignItem 96 ( 1.5%) 1 96
+ast-stats-1 - Fn 96 ( 1.5%) 1
+ast-stats-1 FnDecl 120 ( 1.8%) 5 24
+ast-stats-1 FieldDef 160 ( 2.4%) 2 80
+ast-stats-1 Stmt 160 ( 2.4%) 5 32
+ast-stats-1 - Local 32 ( 0.5%) 1
+ast-stats-1 - MacCall 32 ( 0.5%) 1
+ast-stats-1 - Expr 96 ( 1.5%) 3
+ast-stats-1 Param 160 ( 2.4%) 4 40
+ast-stats-1 Block 192 ( 2.9%) 6 32
+ast-stats-1 Variant 208 ( 3.2%) 2 104
+ast-stats-1 GenericBound 224 ( 3.4%) 4 56
+ast-stats-1 - Trait 224 ( 3.4%) 4
+ast-stats-1 AssocItem 416 ( 6.3%) 4 104
+ast-stats-1 - Type 208 ( 3.2%) 2
+ast-stats-1 - Fn 208 ( 3.2%) 2
+ast-stats-1 GenericParam 480 ( 7.3%) 5 96
+ast-stats-1 Pat 504 ( 7.7%) 7 72
+ast-stats-1 - Struct 72 ( 1.1%) 1
+ast-stats-1 - Wild 72 ( 1.1%) 1
+ast-stats-1 - Ident 360 ( 5.5%) 5
+ast-stats-1 Expr 576 ( 8.8%) 8 72
+ast-stats-1 - Path 72 ( 1.1%) 1
+ast-stats-1 - Match 72 ( 1.1%) 1
+ast-stats-1 - Struct 72 ( 1.1%) 1
+ast-stats-1 - Lit 144 ( 2.2%) 2
+ast-stats-1 - Block 216 ( 3.3%) 3
+ast-stats-1 PathSegment 720 (11.0%) 30 24
+ast-stats-1 Ty 896 (13.7%) 14 64
+ast-stats-1 - Ptr 64 ( 1.0%) 1
+ast-stats-1 - Ref 64 ( 1.0%) 1
+ast-stats-1 - ImplicitSelf 128 ( 2.0%) 2
+ast-stats-1 - Path 640 ( 9.8%) 10
+ast-stats-1 Item 1_224 (18.7%) 9 136
+ast-stats-1 - Trait 136 ( 2.1%) 1
+ast-stats-1 - Enum 136 ( 2.1%) 1
+ast-stats-1 - ForeignMod 136 ( 2.1%) 1
+ast-stats-1 - Impl 136 ( 2.1%) 1
+ast-stats-1 - Fn 272 ( 4.2%) 2
+ast-stats-1 - Use 408 ( 6.2%) 3
ast-stats-1 ----------------------------------------------------------------
-ast-stats-1 Total 7_416
+ast-stats-1 Total 6_552
ast-stats-1
ast-stats-2 POST EXPANSION AST STATS
ast-stats-2 Name Accumulated Size Count Item Size
ast-stats-2 ----------------------------------------------------------------
-ast-stats-2 ExprField 48 ( 0.6%) 1 48
-ast-stats-2 GenericArgs 56 ( 0.7%) 1 56
-ast-stats-2 - AngleBracketed 56 ( 0.7%) 1
-ast-stats-2 Crate 56 ( 0.7%) 1 56
-ast-stats-2 Local 72 ( 0.9%) 1 72
-ast-stats-2 WherePredicate 72 ( 0.9%) 1 72
-ast-stats-2 - BoundPredicate 72 ( 0.9%) 1
-ast-stats-2 Arm 96 ( 1.2%) 2 48
-ast-stats-2 ForeignItem 96 ( 1.2%) 1 96
-ast-stats-2 - Fn 96 ( 1.2%) 1
-ast-stats-2 InlineAsm 120 ( 1.5%) 1 120
-ast-stats-2 Attribute 128 ( 1.6%) 4 32
+ast-stats-2 GenericArgs 40 ( 0.6%) 1 40
+ast-stats-2 - AngleBracketed 40 ( 0.6%) 1
+ast-stats-2 Crate 40 ( 0.6%) 1 40
+ast-stats-2 ExprField 48 ( 0.7%) 1 48
+ast-stats-2 WherePredicate 56 ( 0.8%) 1 56
+ast-stats-2 - BoundPredicate 56 ( 0.8%) 1
+ast-stats-2 Local 72 ( 1.0%) 1 72
+ast-stats-2 Arm 96 ( 1.3%) 2 48
+ast-stats-2 ForeignItem 96 ( 1.3%) 1 96
+ast-stats-2 - Fn 96 ( 1.3%) 1
+ast-stats-2 InlineAsm 120 ( 1.7%) 1 120
+ast-stats-2 FnDecl 120 ( 1.7%) 5 24
+ast-stats-2 Attribute 128 ( 1.8%) 4 32
ast-stats-2 - DocComment 32 ( 0.4%) 1
-ast-stats-2 - Normal 96 ( 1.2%) 3
-ast-stats-2 FieldDef 160 ( 2.0%) 2 80
-ast-stats-2 Stmt 160 ( 2.0%) 5 32
+ast-stats-2 - Normal 96 ( 1.3%) 3
+ast-stats-2 FieldDef 160 ( 2.2%) 2 80
+ast-stats-2 Stmt 160 ( 2.2%) 5 32
ast-stats-2 - Local 32 ( 0.4%) 1
ast-stats-2 - Semi 32 ( 0.4%) 1
-ast-stats-2 - Expr 96 ( 1.2%) 3
-ast-stats-2 Param 160 ( 2.0%) 4 40
-ast-stats-2 FnDecl 200 ( 2.5%) 5 40
-ast-stats-2 Variant 240 ( 3.0%) 2 120
-ast-stats-2 GenericBound 288 ( 3.6%) 4 72
-ast-stats-2 - Trait 288 ( 3.6%) 4
-ast-stats-2 Block 288 ( 3.6%) 6 48
-ast-stats-2 AssocItem 416 ( 5.1%) 4 104
-ast-stats-2 - Type 208 ( 2.6%) 2
-ast-stats-2 - Fn 208 ( 2.6%) 2
-ast-stats-2 GenericParam 480 ( 5.9%) 5 96
-ast-stats-2 Pat 616 ( 7.6%) 7 88
-ast-stats-2 - Struct 88 ( 1.1%) 1
-ast-stats-2 - Wild 88 ( 1.1%) 1
-ast-stats-2 - Ident 440 ( 5.4%) 5
-ast-stats-2 Expr 648 ( 8.0%) 9 72
-ast-stats-2 - Path 72 ( 0.9%) 1
-ast-stats-2 - Match 72 ( 0.9%) 1
-ast-stats-2 - Struct 72 ( 0.9%) 1
-ast-stats-2 - InlineAsm 72 ( 0.9%) 1
-ast-stats-2 - Lit 144 ( 1.8%) 2
-ast-stats-2 - Block 216 ( 2.7%) 3
-ast-stats-2 PathSegment 792 ( 9.8%) 33 24
-ast-stats-2 Ty 896 (11.0%) 14 64
-ast-stats-2 - Ptr 64 ( 0.8%) 1
-ast-stats-2 - Ref 64 ( 0.8%) 1
-ast-stats-2 - ImplicitSelf 128 ( 1.6%) 2
-ast-stats-2 - Path 640 ( 7.9%) 10
-ast-stats-2 Item 2_024 (25.0%) 11 184
-ast-stats-2 - Trait 184 ( 2.3%) 1
-ast-stats-2 - Enum 184 ( 2.3%) 1
-ast-stats-2 - ExternCrate 184 ( 2.3%) 1
-ast-stats-2 - ForeignMod 184 ( 2.3%) 1
-ast-stats-2 - Impl 184 ( 2.3%) 1
-ast-stats-2 - Fn 368 ( 4.5%) 2
-ast-stats-2 - Use 736 ( 9.1%) 4
+ast-stats-2 - Expr 96 ( 1.3%) 3
+ast-stats-2 Param 160 ( 2.2%) 4 40
+ast-stats-2 Block 192 ( 2.7%) 6 32
+ast-stats-2 Variant 208 ( 2.9%) 2 104
+ast-stats-2 GenericBound 224 ( 3.1%) 4 56
+ast-stats-2 - Trait 224 ( 3.1%) 4
+ast-stats-2 AssocItem 416 ( 5.8%) 4 104
+ast-stats-2 - Type 208 ( 2.9%) 2
+ast-stats-2 - Fn 208 ( 2.9%) 2
+ast-stats-2 GenericParam 480 ( 6.7%) 5 96
+ast-stats-2 Pat 504 ( 7.0%) 7 72
+ast-stats-2 - Struct 72 ( 1.0%) 1
+ast-stats-2 - Wild 72 ( 1.0%) 1
+ast-stats-2 - Ident 360 ( 5.0%) 5
+ast-stats-2 Expr 648 ( 9.1%) 9 72
+ast-stats-2 - Path 72 ( 1.0%) 1
+ast-stats-2 - Match 72 ( 1.0%) 1
+ast-stats-2 - Struct 72 ( 1.0%) 1
+ast-stats-2 - InlineAsm 72 ( 1.0%) 1
+ast-stats-2 - Lit 144 ( 2.0%) 2
+ast-stats-2 - Block 216 ( 3.0%) 3
+ast-stats-2 PathSegment 792 (11.1%) 33 24
+ast-stats-2 Ty 896 (12.5%) 14 64
+ast-stats-2 - Ptr 64 ( 0.9%) 1
+ast-stats-2 - Ref 64 ( 0.9%) 1
+ast-stats-2 - ImplicitSelf 128 ( 1.8%) 2
+ast-stats-2 - Path 640 ( 8.9%) 10
+ast-stats-2 Item 1_496 (20.9%) 11 136
+ast-stats-2 - Trait 136 ( 1.9%) 1
+ast-stats-2 - Enum 136 ( 1.9%) 1
+ast-stats-2 - ExternCrate 136 ( 1.9%) 1
+ast-stats-2 - ForeignMod 136 ( 1.9%) 1
+ast-stats-2 - Impl 136 ( 1.9%) 1
+ast-stats-2 - Fn 272 ( 3.8%) 2
+ast-stats-2 - Use 544 ( 7.6%) 4
ast-stats-2 ----------------------------------------------------------------
-ast-stats-2 Total 8_112
+ast-stats-2 Total 7_152
ast-stats-2
hir-stats HIR STATS
hir-stats Name Accumulated Size Count Item Size
diff --git a/tests/ui/stdlib-unit-tests/not-sync.stderr b/tests/ui/stdlib-unit-tests/not-sync.stderr
index 1ee358ba8..4e34e10e3 100644
--- a/tests/ui/stdlib-unit-tests/not-sync.stderr
+++ b/tests/ui/stdlib-unit-tests/not-sync.stderr
@@ -5,6 +5,7 @@ LL | test::<Cell<i32>>();
| ^^^^^^^^^ `Cell<i32>` cannot be shared between threads safely
|
= help: the trait `Sync` is not implemented for `Cell<i32>`
+ = note: if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` or `std::sync::atomic::AtomicI32` instead
note: required by a bound in `test`
--> $DIR/not-sync.rs:5:12
|
@@ -18,6 +19,7 @@ LL | test::<RefCell<i32>>();
| ^^^^^^^^^^^^ `RefCell<i32>` cannot be shared between threads safely
|
= help: the trait `Sync` is not implemented for `RefCell<i32>`
+ = note: if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` instead
note: required by a bound in `test`
--> $DIR/not-sync.rs:5:12
|
diff --git a/tests/ui/str/str-lit-type-mismatch.stderr b/tests/ui/str/str-lit-type-mismatch.stderr
index 6b56cd6f3..5ae7df5a2 100644
--- a/tests/ui/str/str-lit-type-mismatch.stderr
+++ b/tests/ui/str/str-lit-type-mismatch.stderr
@@ -2,7 +2,7 @@ error[E0308]: mismatched types
--> $DIR/str-lit-type-mismatch.rs:2:20
|
LL | let x: &[u8] = "foo";
- | ----- ^^^^^ expected slice `[u8]`, found `str`
+ | ----- ^^^^^ expected `&[u8]`, found `&str`
| |
| expected due to this
|
@@ -17,7 +17,7 @@ error[E0308]: mismatched types
--> $DIR/str-lit-type-mismatch.rs:3:23
|
LL | let y: &[u8; 4] = "baaa";
- | -------- ^^^^^^ expected array `[u8; 4]`, found `str`
+ | -------- ^^^^^^ expected `&[u8; 4]`, found `&str`
| |
| expected due to this
|
@@ -32,7 +32,7 @@ error[E0308]: mismatched types
--> $DIR/str-lit-type-mismatch.rs:4:19
|
LL | let z: &str = b"foo";
- | ---- ^^^^^^ expected `str`, found array `[u8; 3]`
+ | ---- ^^^^^^ expected `&str`, found `&[u8; 3]`
| |
| expected due to this
|
diff --git a/tests/ui/structs-enums/rec-align-u64.rs b/tests/ui/structs-enums/rec-align-u64.rs
index 40ede9705..f21c9b2c8 100644
--- a/tests/ui/structs-enums/rec-align-u64.rs
+++ b/tests/ui/structs-enums/rec-align-u64.rs
@@ -43,7 +43,9 @@ struct Outer {
target_os = "netbsd",
target_os = "openbsd",
target_os = "solaris",
- target_os = "vxworks"))]
+ target_os = "vxworks",
+ target_os = "nto",
+))]
mod m {
#[cfg(target_arch = "x86")]
pub mod m {
diff --git a/tests/ui/structs-enums/struct-enum-ignoring-field-with-underscore.rs b/tests/ui/structs-enums/struct-enum-ignoring-field-with-underscore.rs
index c30b8a1e1..b569993c6 100644
--- a/tests/ui/structs-enums/struct-enum-ignoring-field-with-underscore.rs
+++ b/tests/ui/structs-enums/struct-enum-ignoring-field-with-underscore.rs
@@ -7,6 +7,5 @@ fn main() {
let foo = Some(Foo::Other);
if let Some(Foo::Bar {_}) = foo {}
- //~^ ERROR expected identifier, found reserved identifier `_`
- //~| ERROR pattern does not mention field `bar` [E0027]
+ //~^ ERROR expected field pattern, found `_`
}
diff --git a/tests/ui/structs-enums/struct-enum-ignoring-field-with-underscore.stderr b/tests/ui/structs-enums/struct-enum-ignoring-field-with-underscore.stderr
index 16f751444..2f3a150e5 100644
--- a/tests/ui/structs-enums/struct-enum-ignoring-field-with-underscore.stderr
+++ b/tests/ui/structs-enums/struct-enum-ignoring-field-with-underscore.stderr
@@ -1,24 +1,13 @@
-error: expected identifier, found reserved identifier `_`
+error: expected field pattern, found `_`
--> $DIR/struct-enum-ignoring-field-with-underscore.rs:9:27
|
LL | if let Some(Foo::Bar {_}) = foo {}
- | ^ expected identifier, found reserved identifier
-
-error[E0027]: pattern does not mention field `bar`
- --> $DIR/struct-enum-ignoring-field-with-underscore.rs:9:17
- |
-LL | if let Some(Foo::Bar {_}) = foo {}
- | ^^^^^^^^^^^^ missing field `bar`
- |
-help: include the missing field in the pattern
+ | ^
|
-LL | if let Some(Foo::Bar {_, bar }) = foo {}
- | ~~~~~~~
-help: if you don't care about this missing field, you can explicitly ignore it
+help: to omit remaining fields, use `..`
|
-LL | if let Some(Foo::Bar {_, .. }) = foo {}
- | ~~~~~~
+LL | if let Some(Foo::Bar {..}) = foo {}
+ | ~~
-error: aborting due to 2 previous errors
+error: aborting due to previous error
-For more information about this error, try `rustc --explain E0027`.
diff --git a/tests/ui/structs/struct-base-wrong-type.stderr b/tests/ui/structs/struct-base-wrong-type.stderr
index b039ce2cc..1299af72b 100644
--- a/tests/ui/structs/struct-base-wrong-type.stderr
+++ b/tests/ui/structs/struct-base-wrong-type.stderr
@@ -2,25 +2,25 @@ error[E0308]: mismatched types
--> $DIR/struct-base-wrong-type.rs:7:33
|
LL | static foo: Foo = Foo { a: 2, ..bar };
- | ^^^ expected struct `Foo`, found struct `Bar`
+ | ^^^ expected `Foo`, found `Bar`
error[E0308]: mismatched types
--> $DIR/struct-base-wrong-type.rs:8:35
|
LL | static foo_i: Foo = Foo { a: 2, ..4 };
- | ^ expected struct `Foo`, found integer
+ | ^ expected `Foo`, found integer
error[E0308]: mismatched types
--> $DIR/struct-base-wrong-type.rs:12:27
|
LL | let f = Foo { a: 2, ..b };
- | ^ expected struct `Foo`, found struct `Bar`
+ | ^ expected `Foo`, found `Bar`
error[E0308]: mismatched types
--> $DIR/struct-base-wrong-type.rs:13:34
|
LL | let f__isize = Foo { a: 2, ..4 };
- | ^ expected struct `Foo`, found integer
+ | ^ expected `Foo`, found integer
error: aborting due to 4 previous errors
diff --git a/tests/ui/structs/struct-path-associated-type.rs b/tests/ui/structs/struct-path-associated-type.rs
index 2dd7174a9..74d9705d4 100644
--- a/tests/ui/structs/struct-path-associated-type.rs
+++ b/tests/ui/structs/struct-path-associated-type.rs
@@ -13,7 +13,7 @@ fn f<T: Tr>() {
//~^ ERROR expected struct, variant or union type, found associated type
let z = T::A::<u8> {};
//~^ ERROR expected struct, variant or union type, found associated type
- //~| ERROR this associated type takes 0 generic arguments but 1 generic argument was supplied
+ //~| ERROR associated type takes 0 generic arguments but 1 generic argument was supplied
match S {
T::A {} => {}
//~^ ERROR expected struct, variant or union type, found associated type
@@ -22,7 +22,7 @@ fn f<T: Tr>() {
fn g<T: Tr<A = S>>() {
let s = T::A {}; // OK
- let z = T::A::<u8> {}; //~ ERROR this associated type takes 0 generic arguments but 1 generic argument was supplied
+ let z = T::A::<u8> {}; //~ ERROR associated type takes 0 generic arguments but 1 generic argument was supplied
match S {
T::A {} => {} // OK
}
diff --git a/tests/ui/structs/struct-path-associated-type.stderr b/tests/ui/structs/struct-path-associated-type.stderr
index ca5f0b7e2..acfddaf37 100644
--- a/tests/ui/structs/struct-path-associated-type.stderr
+++ b/tests/ui/structs/struct-path-associated-type.stderr
@@ -4,7 +4,7 @@ error[E0071]: expected struct, variant or union type, found associated type
LL | let s = T::A {};
| ^^^^ not a struct
-error[E0107]: this associated type takes 0 generic arguments but 1 generic argument was supplied
+error[E0107]: associated type takes 0 generic arguments but 1 generic argument was supplied
--> $DIR/struct-path-associated-type.rs:14:16
|
LL | let z = T::A::<u8> {};
@@ -30,7 +30,7 @@ error[E0071]: expected struct, variant or union type, found associated type
LL | T::A {} => {}
| ^^^^ not a struct
-error[E0107]: this associated type takes 0 generic arguments but 1 generic argument was supplied
+error[E0107]: associated type takes 0 generic arguments but 1 generic argument was supplied
--> $DIR/struct-path-associated-type.rs:25:16
|
LL | let z = T::A::<u8> {};
diff --git a/tests/ui/structs/struct-path-self-type-mismatch.stderr b/tests/ui/structs/struct-path-self-type-mismatch.stderr
index b55a2cbf7..cddc13561 100644
--- a/tests/ui/structs/struct-path-self-type-mismatch.stderr
+++ b/tests/ui/structs/struct-path-self-type-mismatch.stderr
@@ -34,7 +34,7 @@ LL | |
LL | | inner: u
LL | |
LL | | }
- | |_________^ expected type parameter `U`, found type parameter `T`
+ | |_________^ expected `Foo<U>`, found `Foo<T>`
|
= note: expected struct `Foo<U>`
found struct `Foo<T>`
diff --git a/tests/ui/structs/struct-record-suggestion.stderr b/tests/ui/structs/struct-record-suggestion.stderr
index 9b751d1b6..38274f8d9 100644
--- a/tests/ui/structs/struct-record-suggestion.stderr
+++ b/tests/ui/structs/struct-record-suggestion.stderr
@@ -18,7 +18,7 @@ error[E0308]: mismatched types
--> $DIR/struct-record-suggestion.rs:23:20
|
LL | let q = B { b: 1..Default::default() };
- | ^^^^^^^^^^^^^^^^^^^^^ expected `u32`, found struct `Range`
+ | ^^^^^^^^^^^^^^^^^^^^^ expected `u32`, found `Range<{integer}>`
|
= note: expected type `u32`
found struct `std::ops::Range<{integer}>`
diff --git a/tests/ui/structs/structure-constructor-type-mismatch.rs b/tests/ui/structs/structure-constructor-type-mismatch.rs
index a03ef590c..21cd9d08b 100644
--- a/tests/ui/structs/structure-constructor-type-mismatch.rs
+++ b/tests/ui/structs/structure-constructor-type-mismatch.rs
@@ -45,13 +45,13 @@ fn main() {
y: 8,
};
- let pt3 = PointF::<i32> { //~ ERROR this type alias takes 0 generic arguments but 1 generic argument
+ let pt3 = PointF::<i32> { //~ ERROR type alias takes 0 generic arguments but 1 generic argument
x: 9, //~ ERROR mismatched types
y: 10, //~ ERROR mismatched types
};
match (Point { x: 1, y: 2 }) {
- PointF::<u32> { .. } => {} //~ ERROR this type alias takes 0 generic arguments but 1 generic argument
+ PointF::<u32> { .. } => {} //~ ERROR type alias takes 0 generic arguments but 1 generic argument
//~^ ERROR mismatched types
}
diff --git a/tests/ui/structs/structure-constructor-type-mismatch.stderr b/tests/ui/structs/structure-constructor-type-mismatch.stderr
index 3d64fc601..63dda4593 100644
--- a/tests/ui/structs/structure-constructor-type-mismatch.stderr
+++ b/tests/ui/structs/structure-constructor-type-mismatch.stderr
@@ -52,7 +52,7 @@ LL | x: 7,
| expected `f32`, found integer
| help: use a float literal: `7.0`
-error[E0107]: this type alias takes 0 generic arguments but 1 generic argument was supplied
+error[E0107]: type alias takes 0 generic arguments but 1 generic argument was supplied
--> $DIR/structure-constructor-type-mismatch.rs:48:15
|
LL | let pt3 = PointF::<i32> {
@@ -84,7 +84,7 @@ LL | y: 10,
| expected `f32`, found integer
| help: use a float literal: `10.0`
-error[E0107]: this type alias takes 0 generic arguments but 1 generic argument was supplied
+error[E0107]: type alias takes 0 generic arguments but 1 generic argument was supplied
--> $DIR/structure-constructor-type-mismatch.rs:54:9
|
LL | PointF::<u32> { .. } => {}
@@ -104,7 +104,7 @@ error[E0308]: mismatched types
LL | match (Point { x: 1, y: 2 }) {
| ---------------------- this expression has type `Point<{integer}>`
LL | PointF::<u32> { .. } => {}
- | ^^^^^^^^^^^^^^^^^^^^ expected integer, found `f32`
+ | ^^^^^^^^^^^^^^^^^^^^ expected `Point<{integer}>`, found `Point<f32>`
|
= note: expected struct `Point<{integer}>`
found struct `Point<f32>`
@@ -115,7 +115,7 @@ error[E0308]: mismatched types
LL | match (Point { x: 1, y: 2 }) {
| ---------------------- this expression has type `Point<{integer}>`
LL | PointF { .. } => {}
- | ^^^^^^^^^^^^^ expected integer, found `f32`
+ | ^^^^^^^^^^^^^ expected `Point<{integer}>`, found `Point<f32>`
|
= note: expected struct `Point<{integer}>`
found struct `Point<f32>`
@@ -126,7 +126,7 @@ error[E0308]: mismatched types
LL | match (Pair { x: 1, y: 2 }) {
| --------------------- this expression has type `Pair<{integer}, {integer}>`
LL | PairF::<u32> { .. } => {}
- | ^^^^^^^^^^^^^^^^^^^ expected integer, found `f32`
+ | ^^^^^^^^^^^^^^^^^^^ expected `Pair<{integer}, {integer}>`, found `Pair<f32, u32>`
|
= note: expected struct `Pair<{integer}, {integer}>`
found struct `Pair<f32, u32>`
diff --git a/tests/ui/suggest-null-ptr.fixed b/tests/ui/suggest-null-ptr.fixed
new file mode 100644
index 000000000..40f900c7d
--- /dev/null
+++ b/tests/ui/suggest-null-ptr.fixed
@@ -0,0 +1,31 @@
+// run-rustfix
+
+// Suggest providing a std::ptr::null{,_mut}() to a function that takes in a raw
+// pointer if a literal 0 was provided by the user.
+
+extern "C" {
+ fn foo(ptr: *const u8);
+
+ fn foo_mut(ptr: *mut u8);
+
+ fn usize(ptr: *const usize);
+
+ fn usize_mut(ptr: *mut usize);
+}
+
+fn main() {
+ unsafe {
+ foo(std::ptr::null());
+ //~^ mismatched types [E0308]
+ //~| if you meant to create a null pointer, use `std::ptr::null()`
+ foo_mut(std::ptr::null_mut());
+ //~^ mismatched types [E0308]
+ //~| if you meant to create a null pointer, use `std::ptr::null_mut()`
+ usize(std::ptr::null());
+ //~^ mismatched types [E0308]
+ //~| if you meant to create a null pointer, use `std::ptr::null()`
+ usize_mut(std::ptr::null_mut());
+ //~^ mismatched types [E0308]
+ //~| if you meant to create a null pointer, use `std::ptr::null_mut()`
+ }
+}
diff --git a/tests/ui/suggest-null-ptr.rs b/tests/ui/suggest-null-ptr.rs
new file mode 100644
index 000000000..19b595bf7
--- /dev/null
+++ b/tests/ui/suggest-null-ptr.rs
@@ -0,0 +1,31 @@
+// run-rustfix
+
+// Suggest providing a std::ptr::null{,_mut}() to a function that takes in a raw
+// pointer if a literal 0 was provided by the user.
+
+extern "C" {
+ fn foo(ptr: *const u8);
+
+ fn foo_mut(ptr: *mut u8);
+
+ fn usize(ptr: *const usize);
+
+ fn usize_mut(ptr: *mut usize);
+}
+
+fn main() {
+ unsafe {
+ foo(0);
+ //~^ mismatched types [E0308]
+ //~| if you meant to create a null pointer, use `std::ptr::null()`
+ foo_mut(0);
+ //~^ mismatched types [E0308]
+ //~| if you meant to create a null pointer, use `std::ptr::null_mut()`
+ usize(0);
+ //~^ mismatched types [E0308]
+ //~| if you meant to create a null pointer, use `std::ptr::null()`
+ usize_mut(0);
+ //~^ mismatched types [E0308]
+ //~| if you meant to create a null pointer, use `std::ptr::null_mut()`
+ }
+}
diff --git a/tests/ui/suggest-null-ptr.stderr b/tests/ui/suggest-null-ptr.stderr
new file mode 100644
index 000000000..66a79d074
--- /dev/null
+++ b/tests/ui/suggest-null-ptr.stderr
@@ -0,0 +1,83 @@
+error[E0308]: mismatched types
+ --> $DIR/suggest-null-ptr.rs:18:13
+ |
+LL | foo(0);
+ | --- ^ expected `*const u8`, found `usize`
+ | |
+ | arguments to this function are incorrect
+ |
+ = note: expected raw pointer `*const u8`
+ found type `usize`
+note: function defined here
+ --> $DIR/suggest-null-ptr.rs:7:8
+ |
+LL | fn foo(ptr: *const u8);
+ | ^^^
+help: if you meant to create a null pointer, use `std::ptr::null()`
+ |
+LL | foo(std::ptr::null());
+ | ~~~~~~~~~~~~~~~~
+
+error[E0308]: mismatched types
+ --> $DIR/suggest-null-ptr.rs:21:17
+ |
+LL | foo_mut(0);
+ | ------- ^ expected `*mut u8`, found `usize`
+ | |
+ | arguments to this function are incorrect
+ |
+ = note: expected raw pointer `*mut u8`
+ found type `usize`
+note: function defined here
+ --> $DIR/suggest-null-ptr.rs:9:8
+ |
+LL | fn foo_mut(ptr: *mut u8);
+ | ^^^^^^^
+help: if you meant to create a null pointer, use `std::ptr::null_mut()`
+ |
+LL | foo_mut(std::ptr::null_mut());
+ | ~~~~~~~~~~~~~~~~~~~~
+
+error[E0308]: mismatched types
+ --> $DIR/suggest-null-ptr.rs:24:15
+ |
+LL | usize(0);
+ | ----- ^ expected `*const usize`, found `usize`
+ | |
+ | arguments to this function are incorrect
+ |
+ = note: expected raw pointer `*const usize`
+ found type `usize`
+note: function defined here
+ --> $DIR/suggest-null-ptr.rs:11:8
+ |
+LL | fn usize(ptr: *const usize);
+ | ^^^^^
+help: if you meant to create a null pointer, use `std::ptr::null()`
+ |
+LL | usize(std::ptr::null());
+ | ~~~~~~~~~~~~~~~~
+
+error[E0308]: mismatched types
+ --> $DIR/suggest-null-ptr.rs:27:19
+ |
+LL | usize_mut(0);
+ | --------- ^ expected `*mut usize`, found `usize`
+ | |
+ | arguments to this function are incorrect
+ |
+ = note: expected raw pointer `*mut usize`
+ found type `usize`
+note: function defined here
+ --> $DIR/suggest-null-ptr.rs:13:8
+ |
+LL | fn usize_mut(ptr: *mut usize);
+ | ^^^^^^^^^
+help: if you meant to create a null pointer, use `std::ptr::null_mut()`
+ |
+LL | usize_mut(std::ptr::null_mut());
+ | ~~~~~~~~~~~~~~~~~~~~
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/suggestions/args-instead-of-tuple-errors.stderr b/tests/ui/suggestions/args-instead-of-tuple-errors.stderr
index bc097bf6e..510b99bb5 100644
--- a/tests/ui/suggestions/args-instead-of-tuple-errors.stderr
+++ b/tests/ui/suggestions/args-instead-of-tuple-errors.stderr
@@ -2,9 +2,9 @@ error[E0061]: this enum variant takes 1 argument but 2 arguments were supplied
--> $DIR/args-instead-of-tuple-errors.rs:6:34
|
LL | let _: Option<(i32, bool)> = Some(1, 2);
- | ^^^^ - argument of type `{integer}` unexpected
+ | ^^^^ - unexpected argument of type `{integer}`
|
-note: expected tuple, found integer
+note: expected `(i32, bool)`, found integer
--> $DIR/args-instead-of-tuple-errors.rs:6:39
|
LL | let _: Option<(i32, bool)> = Some(1, 2);
@@ -22,16 +22,17 @@ note: tuple variant defined here
--> $SRC_DIR/core/src/option.rs:LL:COL
help: remove the extra argument
|
-LL | let _: Option<(i32, bool)> = Some(/* (i32, bool) */);
- | ~~~~~~~~~~~~~~~~~~~
+LL - let _: Option<(i32, bool)> = Some(1, 2);
+LL + let _: Option<(i32, bool)> = Some(/* (i32, bool) */);
+ |
error[E0061]: this function takes 1 argument but 2 arguments were supplied
--> $DIR/args-instead-of-tuple-errors.rs:8:5
|
LL | int_bool(1, 2);
- | ^^^^^^^^ - argument of type `{integer}` unexpected
+ | ^^^^^^^^ - unexpected argument of type `{integer}`
|
-note: expected tuple, found integer
+note: expected `(i32, bool)`, found integer
--> $DIR/args-instead-of-tuple-errors.rs:8:14
|
LL | int_bool(1, 2);
@@ -45,8 +46,9 @@ LL | fn int_bool(_: (i32, bool)) {
| ^^^^^^^^ --------------
help: remove the extra argument
|
-LL | int_bool(/* (i32, bool) */);
- | ~~~~~~~~~~~~~~~~~~~
+LL - int_bool(1, 2);
+LL + int_bool(/* (i32, bool) */);
+ |
error[E0061]: this enum variant takes 1 argument but 0 arguments were supplied
--> $DIR/args-instead-of-tuple-errors.rs:11:28
@@ -65,7 +67,7 @@ error[E0308]: mismatched types
--> $DIR/args-instead-of-tuple-errors.rs:14:34
|
LL | let _: Option<(i32,)> = Some(5_usize);
- | ---- ^^^^^^^ expected tuple, found `usize`
+ | ---- ^^^^^^^ expected `(i32,)`, found `usize`
| |
| arguments to this enum variant are incorrect
|
@@ -85,7 +87,7 @@ error[E0308]: mismatched types
--> $DIR/args-instead-of-tuple-errors.rs:17:34
|
LL | let _: Option<(i32,)> = Some((5_usize));
- | ---- ^^^^^^^^^ expected tuple, found `usize`
+ | ---- ^^^^^^^^^ expected `(i32,)`, found `usize`
| |
| arguments to this enum variant are incorrect
|
diff --git a/tests/ui/suggestions/args-instead-of-tuple.stderr b/tests/ui/suggestions/args-instead-of-tuple.stderr
index 3ed9dbf4a..0bdf10b0d 100644
--- a/tests/ui/suggestions/args-instead-of-tuple.stderr
+++ b/tests/ui/suggestions/args-instead-of-tuple.stderr
@@ -41,7 +41,7 @@ error[E0308]: mismatched types
--> $DIR/args-instead-of-tuple.rs:14:34
|
LL | let _: Option<(i32,)> = Some(3);
- | ---- ^ expected tuple, found integer
+ | ---- ^ expected `(i32,)`, found integer
| |
| arguments to this enum variant are incorrect
|
@@ -58,7 +58,7 @@ error[E0308]: mismatched types
--> $DIR/args-instead-of-tuple.rs:17:34
|
LL | let _: Option<(i32,)> = Some((3));
- | ---- ^^^ expected tuple, found integer
+ | ---- ^^^ expected `(i32,)`, found integer
| |
| arguments to this enum variant are incorrect
|
diff --git a/tests/ui/suggestions/as-ref.stderr b/tests/ui/suggestions/as-ref.stderr
index deafa9f48..0ee343ebf 100644
--- a/tests/ui/suggestions/as-ref.stderr
+++ b/tests/ui/suggestions/as-ref.stderr
@@ -2,7 +2,7 @@ error[E0308]: mismatched types
--> $DIR/as-ref.rs:7:29
|
LL | opt.map(|arg| takes_ref(arg));
- | --- --------- ^^^ expected `&Foo`, found struct `Foo`
+ | --- --------- ^^^ expected `&Foo`, found `Foo`
| | |
| | arguments to this function are incorrect
| help: consider using `as_ref` instead: `as_ref().map`
@@ -17,7 +17,7 @@ error[E0308]: mismatched types
--> $DIR/as-ref.rs:8:39
|
LL | opt.and_then(|arg| Some(takes_ref(arg)));
- | -------- --------- ^^^ expected `&Foo`, found struct `Foo`
+ | -------- --------- ^^^ expected `&Foo`, found `Foo`
| | |
| | arguments to this function are incorrect
| help: consider using `as_ref` instead: `as_ref().and_then`
@@ -32,7 +32,7 @@ error[E0308]: mismatched types
--> $DIR/as-ref.rs:10:29
|
LL | opt.map(|arg| takes_ref(arg));
- | --- --------- ^^^ expected `&Foo`, found struct `Foo`
+ | --- --------- ^^^ expected `&Foo`, found `Foo`
| | |
| | arguments to this function are incorrect
| help: consider using `as_ref` instead: `as_ref().map`
@@ -47,7 +47,7 @@ error[E0308]: mismatched types
--> $DIR/as-ref.rs:11:37
|
LL | opt.and_then(|arg| Ok(takes_ref(arg)));
- | -------- --------- ^^^ expected `&Foo`, found struct `Foo`
+ | -------- --------- ^^^ expected `&Foo`, found `Foo`
| | |
| | arguments to this function are incorrect
| help: consider using `as_ref` instead: `as_ref().and_then`
@@ -64,7 +64,7 @@ error[E0308]: mismatched types
LL | let y: Option<&usize> = x;
| -------------- ^
| | |
- | | expected enum `Option`, found `&Option<usize>`
+ | | expected `Option<&usize>`, found `&Option<usize>`
| | help: you can convert from `&Option<T>` to `Option<&T>` using `.as_ref()`: `x.as_ref()`
| expected due to this
|
@@ -75,7 +75,7 @@ error[E0308]: mismatched types
--> $DIR/as-ref.rs:15:37
|
LL | let y: Result<&usize, &usize> = x;
- | ---------------------- ^ expected enum `Result`, found reference
+ | ---------------------- ^ expected `Result<&usize, &usize>`, found `&Result<usize, usize>`
| |
| expected due to this
|
@@ -90,7 +90,7 @@ error[E0308]: mismatched types
--> $DIR/as-ref.rs:19:36
|
LL | let y: Result<&usize, usize> = x;
- | --------------------- ^ expected enum `Result`, found reference
+ | --------------------- ^ expected `Result<&usize, usize>`, found `&Result<usize, usize>`
| |
| expected due to this
|
@@ -101,7 +101,7 @@ error[E0308]: mismatched types
--> $DIR/as-ref.rs:22:42
|
LL | multiple_ref_opt.map(|arg| takes_ref(arg));
- | --- --------- ^^^ expected `&Foo`, found struct `Foo`
+ | --- --------- ^^^ expected `&Foo`, found `Foo`
| | |
| | arguments to this function are incorrect
| help: consider using `as_ref` instead: `as_ref().map`
@@ -116,7 +116,7 @@ error[E0308]: mismatched types
--> $DIR/as-ref.rs:23:52
|
LL | multiple_ref_opt.and_then(|arg| Some(takes_ref(arg)));
- | -------- --------- ^^^ expected `&Foo`, found struct `Foo`
+ | -------- --------- ^^^ expected `&Foo`, found `Foo`
| | |
| | arguments to this function are incorrect
| help: consider using `as_ref` instead: `as_ref().and_then`
@@ -131,7 +131,7 @@ error[E0308]: mismatched types
--> $DIR/as-ref.rs:25:45
|
LL | multiple_ref_result.map(|arg| takes_ref(arg));
- | --- --------- ^^^ expected `&Foo`, found struct `Foo`
+ | --- --------- ^^^ expected `&Foo`, found `Foo`
| | |
| | arguments to this function are incorrect
| help: consider using `as_ref` instead: `as_ref().map`
@@ -146,7 +146,7 @@ error[E0308]: mismatched types
--> $DIR/as-ref.rs:26:53
|
LL | multiple_ref_result.and_then(|arg| Ok(takes_ref(arg)));
- | -------- --------- ^^^ expected `&Foo`, found struct `Foo`
+ | -------- --------- ^^^ expected `&Foo`, found `Foo`
| | |
| | arguments to this function are incorrect
| help: consider using `as_ref` instead: `as_ref().and_then`
diff --git a/tests/ui/suggestions/assoc-const-without-self.rs b/tests/ui/suggestions/assoc-const-without-self.rs
new file mode 100644
index 000000000..95070ec60
--- /dev/null
+++ b/tests/ui/suggestions/assoc-const-without-self.rs
@@ -0,0 +1,11 @@
+struct Foo;
+
+impl Foo {
+ const A_CONST: usize = 1;
+
+ fn foo() -> usize {
+ A_CONST //~ ERROR cannot find value `A_CONST` in this scope
+ }
+}
+
+fn main() {}
diff --git a/tests/ui/suggestions/assoc-const-without-self.stderr b/tests/ui/suggestions/assoc-const-without-self.stderr
new file mode 100644
index 000000000..88d72da70
--- /dev/null
+++ b/tests/ui/suggestions/assoc-const-without-self.stderr
@@ -0,0 +1,14 @@
+error[E0425]: cannot find value `A_CONST` in this scope
+ --> $DIR/assoc-const-without-self.rs:7:9
+ |
+LL | A_CONST
+ | ^^^^^^^ not found in this scope
+ |
+help: consider using the associated constant
+ |
+LL | Self::A_CONST
+ | ++++++
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0425`.
diff --git a/tests/ui/suggestions/assoc-ct-for-assoc-method.stderr b/tests/ui/suggestions/assoc-ct-for-assoc-method.stderr
index afef38f12..211cb1584 100644
--- a/tests/ui/suggestions/assoc-ct-for-assoc-method.stderr
+++ b/tests/ui/suggestions/assoc-ct-for-assoc-method.stderr
@@ -36,7 +36,7 @@ LL | let y: i32 = i32::max - 42;
| |
| fn(i32, i32) -> i32 {<i32 as Ord>::max}
|
-help: use parentheses to call this associated function
+help: use parentheses to call this method
|
LL | let y: i32 = i32::max(/* i32 */, /* i32 */) - 42;
| ++++++++++++++++++++++
diff --git a/tests/ui/suggestions/borrow-for-loop-head.stderr b/tests/ui/suggestions/borrow-for-loop-head.stderr
index cbdb94877..0f179438a 100644
--- a/tests/ui/suggestions/borrow-for-loop-head.stderr
+++ b/tests/ui/suggestions/borrow-for-loop-head.stderr
@@ -1,6 +1,8 @@
error[E0505]: cannot move out of `a` because it is borrowed
--> $DIR/borrow-for-loop-head.rs:4:18
|
+LL | let a = vec![1, 2, 3];
+ | - binding `a` declared here
LL | for i in &a {
| -- borrow of `a` occurs here
LL | for j in a {
diff --git a/tests/ui/suggestions/boxed-variant-field.stderr b/tests/ui/suggestions/boxed-variant-field.stderr
index 9ae36a06a..1adbc0540 100644
--- a/tests/ui/suggestions/boxed-variant-field.stderr
+++ b/tests/ui/suggestions/boxed-variant-field.stderr
@@ -2,7 +2,7 @@ error[E0308]: mismatched types
--> $DIR/boxed-variant-field.rs:9:31
|
LL | Ty::List(elem) => foo(elem),
- | --- ^^^^ expected enum `Ty`, found struct `Box`
+ | --- ^^^^ expected `Ty`, found `Box<Ty>`
| |
| arguments to this function are incorrect
|
diff --git a/tests/ui/suggestions/call-boxed.stderr b/tests/ui/suggestions/call-boxed.stderr
index 9b619ac9a..9b31ee07c 100644
--- a/tests/ui/suggestions/call-boxed.stderr
+++ b/tests/ui/suggestions/call-boxed.stderr
@@ -6,7 +6,7 @@ LL | let mut x = 1i32;
LL | let y = Box::new(|| 1);
| -- the found closure
LL | x = y;
- | ^ expected `i32`, found struct `Box`
+ | ^ expected `i32`, found `Box<[closure@call-boxed.rs:3:22]>`
|
= note: expected type `i32`
found struct `Box<[closure@$DIR/call-boxed.rs:3:22: 3:24]>`
diff --git a/tests/ui/suggestions/chain-method-call-mutation-in-place.stderr b/tests/ui/suggestions/chain-method-call-mutation-in-place.stderr
index 965dbb967..11d9b8391 100644
--- a/tests/ui/suggestions/chain-method-call-mutation-in-place.stderr
+++ b/tests/ui/suggestions/chain-method-call-mutation-in-place.stderr
@@ -4,7 +4,7 @@ error[E0308]: mismatched types
LL | fn foo(mut s: String) -> String {
| ------ expected `String` because of return type
LL | s.push_str("asdf")
- | ^^^^^^^^^^^^^^^^^^ expected struct `String`, found `()`
+ | ^^^^^^^^^^^^^^^^^^ expected `String`, found `()`
|
note: method `push_str` modifies its receiver in-place
--> $DIR/chain-method-call-mutation-in-place.rs:3:7
diff --git a/tests/ui/suggestions/clone-on-unconstrained-borrowed-type-param.stderr b/tests/ui/suggestions/clone-on-unconstrained-borrowed-type-param.stderr
index 26ab515d9..45593035b 100644
--- a/tests/ui/suggestions/clone-on-unconstrained-borrowed-type-param.stderr
+++ b/tests/ui/suggestions/clone-on-unconstrained-borrowed-type-param.stderr
@@ -26,7 +26,7 @@ error[E0308]: mismatched types
LL | fn wut(t: &Foo) -> Foo {
| --- expected `Foo` because of return type
LL | t.clone()
- | ^^^^^^^^^ expected struct `Foo`, found `&Foo`
+ | ^^^^^^^^^ expected `Foo`, found `&Foo`
|
note: `Foo` does not implement `Clone`, so `&Foo` was cloned instead
--> $DIR/clone-on-unconstrained-borrowed-type-param.rs:9:5
diff --git a/tests/ui/suggestions/const-in-struct-pat.stderr b/tests/ui/suggestions/const-in-struct-pat.stderr
index c8b93f3dc..f344ac06d 100644
--- a/tests/ui/suggestions/const-in-struct-pat.stderr
+++ b/tests/ui/suggestions/const-in-struct-pat.stderr
@@ -7,7 +7,7 @@ LL | struct foo;
LL | let Thing { foo } = t;
| ^^^ - this expression has type `Thing`
| |
- | expected struct `String`, found struct `foo`
+ | expected `String`, found `foo`
| `foo` is interpreted as a unit struct, not a new binding
|
help: bind the struct field to a different name instead
diff --git a/tests/ui/suggestions/constrain-suggest-ice.rs b/tests/ui/suggestions/constrain-suggest-ice.rs
index 69b874bed..d6e5263ff 100644
--- a/tests/ui/suggestions/constrain-suggest-ice.rs
+++ b/tests/ui/suggestions/constrain-suggest-ice.rs
@@ -1,11 +1,9 @@
-struct Bug<S>{ //~ ERROR parameter `S` is never used [E0392]
+struct Bug<S>{
A: [(); {
- let x: [u8; Self::W] = [0; Self::W]; //~ ERROR generic `Self` types are currently not permitted in anonymous constants
- //~^ ERROR generic `Self` types are currently not permitted in anonymous constants
- //~^^ ERROR the size for values of type `S` cannot be known at compilation time [E0277]
- F //~ ERROR cannot find value `F` in this scope [E0425]
+ let x: [u8; Self::W] = [0; Self::W];
+ F
}
-} //~ ERROR mismatched closing delimiter: `}`
+}
//~^ ERROR mismatched closing delimiter: `}`
fn main() {}
diff --git a/tests/ui/suggestions/constrain-suggest-ice.stderr b/tests/ui/suggestions/constrain-suggest-ice.stderr
index 2af7c2f69..9b92091de 100644
--- a/tests/ui/suggestions/constrain-suggest-ice.stderr
+++ b/tests/ui/suggestions/constrain-suggest-ice.stderr
@@ -9,64 +9,5 @@ LL | A: [(); {
LL | }
| ^ mismatched closing delimiter
-error: mismatched closing delimiter: `}`
- --> $DIR/constrain-suggest-ice.rs:2:8
- |
-LL | struct Bug<S>{
- | - closing delimiter possibly meant for this
-LL | A: [(); {
- | ^ unclosed delimiter
-...
-LL | }
- | ^ mismatched closing delimiter
-
-error[E0425]: cannot find value `F` in this scope
- --> $DIR/constrain-suggest-ice.rs:6:9
- |
-LL | F
- | ^ help: a local variable with a similar name exists: `x`
-
-error: generic `Self` types are currently not permitted in anonymous constants
- --> $DIR/constrain-suggest-ice.rs:3:21
- |
-LL | let x: [u8; Self::W] = [0; Self::W];
- | ^^^^
-
-error: generic `Self` types are currently not permitted in anonymous constants
- --> $DIR/constrain-suggest-ice.rs:3:36
- |
-LL | let x: [u8; Self::W] = [0; Self::W];
- | ^^^^
-
-error[E0277]: the size for values of type `S` cannot be known at compilation time
- --> $DIR/constrain-suggest-ice.rs:3:36
- |
-LL | struct Bug<S>{
- | - this type parameter needs to be `std::marker::Sized`
-LL | A: [(); {
-LL | let x: [u8; Self::W] = [0; Self::W];
- | ^^^^^^^ doesn't have a size known at compile-time
- |
-note: required by a bound in `Bug`
- --> $DIR/constrain-suggest-ice.rs:1:12
- |
-LL | struct Bug<S>{
- | ^ required by this bound in `Bug`
-help: consider relaxing the implicit `Sized` restriction
- |
-LL | struct Bug<S: ?Sized>{
- | ++++++++
-
-error[E0392]: parameter `S` is never used
- --> $DIR/constrain-suggest-ice.rs:1:12
- |
-LL | struct Bug<S>{
- | ^ unused parameter
- |
- = help: consider removing `S`, referring to it in a field, or using a marker such as `PhantomData`
- = help: if you intended `S` to be a const parameter, use `const S: usize` instead
-
-error: aborting due to 7 previous errors
+error: aborting due to previous error
-Some errors have detailed explanations: E0277, E0392, E0425.
-For more information about an error, try `rustc --explain E0277`.
diff --git a/tests/ui/suggestions/copied-and-cloned.stderr b/tests/ui/suggestions/copied-and-cloned.stderr
index a6336281b..067808141 100644
--- a/tests/ui/suggestions/copied-and-cloned.stderr
+++ b/tests/ui/suggestions/copied-and-cloned.stderr
@@ -2,7 +2,7 @@ error[E0308]: mismatched types
--> $DIR/copied-and-cloned.rs:7:26
|
LL | expect::<Option<()>>(x);
- | -------------------- ^ expected `()`, found `&()`
+ | -------------------- ^ expected `Option<()>`, found `Option<&()>`
| |
| arguments to this function are incorrect
|
@@ -22,7 +22,7 @@ error[E0308]: mismatched types
--> $DIR/copied-and-cloned.rs:11:30
|
LL | expect::<Result<(), ()>>(x);
- | ------------------------ ^ expected `()`, found `&()`
+ | ------------------------ ^ expected `Result<(), ()>`, found `Result<&(), _>`
| |
| arguments to this function are incorrect
|
@@ -42,7 +42,7 @@ error[E0308]: mismatched types
--> $DIR/copied-and-cloned.rs:16:30
|
LL | expect::<Option<String>>(x);
- | ------------------------ ^ expected struct `String`, found `&String`
+ | ------------------------ ^ expected `Option<String>`, found `Option<&String>`
| |
| arguments to this function are incorrect
|
@@ -62,7 +62,7 @@ error[E0308]: mismatched types
--> $DIR/copied-and-cloned.rs:20:34
|
LL | expect::<Result<String, ()>>(x);
- | ---------------------------- ^ expected struct `String`, found `&String`
+ | ---------------------------- ^ expected `Result<String, ()>`, found `Result<&String, _>`
| |
| arguments to this function are incorrect
|
diff --git a/tests/ui/suggestions/dont-suggest-deref-inside-macro-issue-58298.stderr b/tests/ui/suggestions/dont-suggest-deref-inside-macro-issue-58298.stderr
index 5dc4e6444..c6867270a 100644
--- a/tests/ui/suggestions/dont-suggest-deref-inside-macro-issue-58298.stderr
+++ b/tests/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 `String`
|
= note: this error originates in the macro `format` which comes from the expansion of the macro `intrinsic_match` (in Nightly builds, run with -Z macro-backtrace for more info)
diff --git a/tests/ui/suggestions/dont-suggest-doc-hidden-variant-for-enum/hidden-child.stderr b/tests/ui/suggestions/dont-suggest-doc-hidden-variant-for-enum/hidden-child.stderr
index 67f4ac08d..866d3fab4 100644
--- a/tests/ui/suggestions/dont-suggest-doc-hidden-variant-for-enum/hidden-child.stderr
+++ b/tests/ui/suggestions/dont-suggest-doc-hidden-variant-for-enum/hidden-child.stderr
@@ -2,7 +2,7 @@ error[E0308]: mismatched types
--> $DIR/hidden-child.rs:9:26
|
LL | let x: Option<i32> = 1i32;
- | ----------- ^^^^ expected enum `Option`, found `i32`
+ | ----------- ^^^^ expected `Option<i32>`, found `i32`
| |
| expected due to this
|
diff --git a/tests/ui/suggestions/dont-suggest-doc-hidden-variant-for-enum/hidden-parent.stderr b/tests/ui/suggestions/dont-suggest-doc-hidden-variant-for-enum/hidden-parent.stderr
index d92b81279..f8029e452 100644
--- a/tests/ui/suggestions/dont-suggest-doc-hidden-variant-for-enum/hidden-parent.stderr
+++ b/tests/ui/suggestions/dont-suggest-doc-hidden-variant-for-enum/hidden-parent.stderr
@@ -2,7 +2,7 @@ error[E0308]: mismatched types
--> $DIR/hidden-parent.rs:6:26
|
LL | let x: Option<i32> = 1i32;
- | ----------- ^^^^ expected enum `Option`, found `i32`
+ | ----------- ^^^^ expected `Option<i32>`, found `i32`
| |
| expected due to this
|
diff --git a/tests/ui/suggestions/expected-boxed-future-isnt-pinned.stderr b/tests/ui/suggestions/expected-boxed-future-isnt-pinned.stderr
index b1e04dab8..90ea06239 100644
--- a/tests/ui/suggestions/expected-boxed-future-isnt-pinned.stderr
+++ b/tests/ui/suggestions/expected-boxed-future-isnt-pinned.stderr
@@ -5,7 +5,7 @@ LL | fn foo<F: Future<Output=i32> + Send + 'static>(x: F) -> BoxFuture<'static,
| - this type parameter ----------------------- expected `Pin<Box<(dyn Future<Output = i32> + Send + 'static)>>` because of return type
LL | // We could instead use an `async` block, but this way we have no std spans.
LL | x
- | ^ expected struct `Pin`, found type parameter `F`
+ | ^ expected `Pin<Box<...>>`, found type parameter `F`
|
= note: expected struct `Pin<Box<(dyn Future<Output = i32> + Send + 'static)>>`
found type parameter `F`
@@ -20,7 +20,7 @@ error[E0308]: mismatched types
LL | fn bar<F: Future<Output=i32> + Send + 'static>(x: F) -> BoxFuture<'static, i32> {
| ----------------------- expected `Pin<Box<(dyn Future<Output = i32> + Send + 'static)>>` because of return type
LL | Box::new(x)
- | ^^^^^^^^^^^ expected struct `Pin`, found struct `Box`
+ | ^^^^^^^^^^^ expected `Pin<Box<...>>`, found `Box<F>`
|
= note: expected struct `Pin<Box<(dyn Future<Output = i32> + Send + 'static)>>`
found struct `Box<F>`
@@ -32,7 +32,7 @@ error[E0308]: mismatched types
LL | fn baz<F: Future<Output=i32> + Send + 'static>(x: F) -> BoxFuture<'static, i32> {
| - this type parameter
LL | Pin::new(x)
- | -------- ^ expected struct `Box`, found type parameter `F`
+ | -------- ^ expected `Box<dyn Future<Output = ...> + Send>`, found type parameter `F`
| |
| arguments to this function are incorrect
| help: use `Box::pin` to pin and box this expression: `Box::pin`
@@ -74,7 +74,7 @@ LL | | 42
LL | | }
| | ^
| | |
- | |_____expected struct `Pin`, found `async` block
+ | |_____expected `Pin<Box<...>>`, found `async` block
| arguments to this function are incorrect
|
= note: expected struct `Pin<Box<dyn Future<Output = i32> + Send>>`
diff --git a/tests/ui/suggestions/field-access.stderr b/tests/ui/suggestions/field-access.stderr
index b9f0f788b..007bc6ecf 100644
--- a/tests/ui/suggestions/field-access.stderr
+++ b/tests/ui/suggestions/field-access.stderr
@@ -7,7 +7,7 @@ LL | Fst,
LL | if let B::Fst = a {};
| ^^^^^^ - this expression has type `A`
| |
- | expected struct `A`, found enum `B`
+ | expected `A`, found `B`
|
help: you might have meant to use field `b` whose type is `B`
|
@@ -24,7 +24,7 @@ LL | match a {
| - this expression has type `A`
...
LL | B::Fst => (),
- | ^^^^^^ expected struct `A`, found enum `B`
+ | ^^^^^^ expected `A`, found `B`
|
help: you might have meant to use field `b` whose type is `B`
|
@@ -41,7 +41,7 @@ LL | match a {
| - this expression has type `A`
...
LL | B::Snd => (),
- | ^^^^^^ expected struct `A`, found enum `B`
+ | ^^^^^^ expected `A`, found `B`
|
help: you might have meant to use field `b` whose type is `B`
|
@@ -55,7 +55,7 @@ LL | match foo {
| --- this expression has type `Foo`
LL |
LL | 1u32 => (),
- | ^^^^ expected union `Foo`, found `u32`
+ | ^^^^ expected `Foo`, found `u32`
|
help: you might have meant to use field `bar` whose type is `u32`
|
diff --git a/tests/ui/suggestions/fn-or-tuple-struct-without-args.stderr b/tests/ui/suggestions/fn-or-tuple-struct-without-args.stderr
index 4cbcd31fa..a137db8cd 100644
--- a/tests/ui/suggestions/fn-or-tuple-struct-without-args.stderr
+++ b/tests/ui/suggestions/fn-or-tuple-struct-without-args.stderr
@@ -23,7 +23,7 @@ LL | struct S(usize, usize);
| -------- `S` defines a struct constructor here, which should be called
...
LL | let _: S = S;
- | - ^ expected struct `S`, found struct constructor
+ | - ^ expected `S`, found struct constructor
| |
| expected due to this
|
@@ -59,7 +59,7 @@ LL | struct V();
| -------- `V` defines a struct constructor here, which should be called
...
LL | let _: V = V;
- | - ^ expected struct `V`, found struct constructor
+ | - ^ expected `V`, found struct constructor
| |
| expected due to this
|
@@ -113,7 +113,7 @@ LL | A(usize),
| - `A` defines an enum variant constructor here, which should be called
...
LL | let _: E = E::A;
- | - ^^^^ expected enum `E`, found enum constructor
+ | - ^^^^ expected `E`, found enum constructor
| |
| expected due to this
|
@@ -206,7 +206,7 @@ error[E0308]: mismatched types
--> $DIR/fn-or-tuple-struct-without-args.rs:41:20
|
LL | fn ban(&self) -> usize { 42 }
- | ---------------------- associated function `ban` defined here
+ | ---------------------- method `ban` defined here
...
LL | let _: usize = X::ban;
| ----- ^^^^^^ expected `usize`, found fn item
@@ -215,7 +215,7 @@ LL | let _: usize = X::ban;
|
= note: expected type `usize`
found fn item `for<'a> fn(&'a X) -> usize {<X as T>::ban}`
-help: use parentheses to call this associated function
+help: use parentheses to call this method
|
LL | let _: usize = X::ban(/* &X */);
| ++++++++++
@@ -224,7 +224,7 @@ error[E0308]: mismatched types
--> $DIR/fn-or-tuple-struct-without-args.rs:42:20
|
LL | fn bal(&self) -> usize;
- | ----------------------- associated function `bal` defined here
+ | ----------------------- method `bal` defined here
...
LL | let _: usize = X::bal;
| ----- ^^^^^^ expected `usize`, found fn item
@@ -233,7 +233,7 @@ LL | let _: usize = X::bal;
|
= note: expected type `usize`
found fn item `for<'a> fn(&'a X) -> usize {<X as T>::bal}`
-help: use parentheses to call this associated function
+help: use parentheses to call this method
|
LL | let _: usize = X::bal(/* &X */);
| ++++++++++
diff --git a/tests/ui/suggestions/format-borrow.stderr b/tests/ui/suggestions/format-borrow.stderr
index 8ed2b9c9a..3ea0d208c 100644
--- a/tests/ui/suggestions/format-borrow.stderr
+++ b/tests/ui/suggestions/format-borrow.stderr
@@ -2,7 +2,7 @@ error[E0308]: mismatched types
--> $DIR/format-borrow.rs:2:21
|
LL | let a: String = &String::from("a");
- | ------ ^^^^^^^^^^^^^^^^^^ expected struct `String`, found `&String`
+ | ------ ^^^^^^^^^^^^^^^^^^ expected `String`, found `&String`
| |
| expected due to this
|
@@ -20,7 +20,7 @@ error[E0308]: mismatched types
--> $DIR/format-borrow.rs:4:21
|
LL | let b: String = &format!("b");
- | ------ ^^^^^^^^^^^^^ expected struct `String`, found `&String`
+ | ------ ^^^^^^^^^^^^^ expected `String`, found `&String`
| |
| expected due to this
|
@@ -38,7 +38,7 @@ error[E0308]: mismatched types
--> $DIR/format-borrow.rs:6:21
|
LL | let c: String = &mut format!("c");
- | ------ ^^^^^^^^^^^^^^^^^ expected struct `String`, found `&mut String`
+ | ------ ^^^^^^^^^^^^^^^^^ expected `String`, found `&mut String`
| |
| expected due to this
|
@@ -56,7 +56,7 @@ error[E0308]: mismatched types
--> $DIR/format-borrow.rs:8:21
|
LL | let d: String = &mut (format!("d"));
- | ------ ^^^^^^^^^^^^^^^^^^^ expected struct `String`, found `&mut String`
+ | ------ ^^^^^^^^^^^^^^^^^^^ expected `String`, found `&mut String`
| |
| expected due to this
|
diff --git a/tests/ui/suggestions/if-then-neeing-semi.rs b/tests/ui/suggestions/if-then-neeing-semi.rs
index b487f013d..a4eefb415 100644
--- a/tests/ui/suggestions/if-then-neeing-semi.rs
+++ b/tests/ui/suggestions/if-then-neeing-semi.rs
@@ -15,18 +15,9 @@ fn extra_semicolon() {
};
}
-async fn async_dummy() {} //~ NOTE checked the `Output` of this `async fn`, found opaque type
-//~| NOTE while checking the return type of the `async fn`
-//~| NOTE in this expansion of desugaring of `async` block or function
-//~| NOTE checked the `Output` of this `async fn`, expected opaque type
-//~| NOTE while checking the return type of the `async fn`
-//~| NOTE in this expansion of desugaring of `async` block or function
-async fn async_dummy2() {} //~ NOTE checked the `Output` of this `async fn`, found opaque type
-//~| NOTE checked the `Output` of this `async fn`, found opaque type
-//~| NOTE while checking the return type of the `async fn`
-//~| NOTE in this expansion of desugaring of `async` block or function
-//~| NOTE while checking the return type of the `async fn`
-//~| NOTE in this expansion of desugaring of `async` block or function
+async fn async_dummy() {}
+
+async fn async_dummy2() {}
async fn async_extra_semicolon_same() {
let _ = if true {
@@ -35,8 +26,8 @@ async fn async_extra_semicolon_same() {
//~^ HELP consider removing this semicolon
} else {
async_dummy() //~ ERROR `if` and `else` have incompatible types
- //~^ NOTE expected `()`, found opaque type
- //~| NOTE expected unit type `()`
+ //~^ NOTE expected `()`, found future
+ //~| NOTE calling an async function returns a future
//~| HELP consider `await`ing on the `Future`
};
}
@@ -48,8 +39,8 @@ async fn async_extra_semicolon_different() {
//~^ HELP consider removing this semicolon
} else {
async_dummy2() //~ ERROR `if` and `else` have incompatible types
- //~^ NOTE expected `()`, found opaque type
- //~| NOTE expected unit type `()`
+ //~^ NOTE expected `()`, found future
+ //~| NOTE calling an async function returns a future
//~| HELP consider `await`ing on the `Future`
};
}
@@ -61,8 +52,7 @@ async fn async_different_futures() {
//~| HELP consider `await`ing on both `Future`s
} else {
async_dummy2() //~ ERROR `if` and `else` have incompatible types
- //~^ NOTE expected opaque type, found a different opaque type
- //~| NOTE expected opaque type `impl Future<Output = ()>`
+ //~^ NOTE expected future, found a different future
//~| NOTE distinct uses of `impl Trait` result in different opaque types
};
}
diff --git a/tests/ui/suggestions/if-then-neeing-semi.stderr b/tests/ui/suggestions/if-then-neeing-semi.stderr
index d7c5818ab..6833e0bab 100644
--- a/tests/ui/suggestions/if-then-neeing-semi.stderr
+++ b/tests/ui/suggestions/if-then-neeing-semi.stderr
@@ -1,5 +1,5 @@
error[E0308]: `if` and `else` have incompatible types
- --> $DIR/if-then-neeing-semi.rs:37:9
+ --> $DIR/if-then-neeing-semi.rs:28:9
|
LL | let _ = if true {
| _____________-
@@ -9,19 +9,17 @@ LL | | async_dummy();
LL | |
LL | | } else {
LL | | async_dummy()
- | | ^^^^^^^^^^^^^ expected `()`, found opaque type
+ | | ^^^^^^^^^^^^^ expected `()`, found future
... |
LL | |
LL | | };
| |_____- `if` and `else` have incompatible types
|
-note: while checking the return type of the `async fn`
- --> $DIR/if-then-neeing-semi.rs:18:24
+note: calling an async function returns a future
+ --> $DIR/if-then-neeing-semi.rs:28:9
|
-LL | async fn async_dummy() {}
- | ^ checked the `Output` of this `async fn`, found opaque type
- = note: expected unit type `()`
- found opaque type `impl Future<Output = ()>`
+LL | async_dummy()
+ | ^^^^^^^^^^^^^
help: consider `await`ing on the `Future`
|
LL | async_dummy().await
@@ -33,7 +31,7 @@ LL + async_dummy()
|
error[E0308]: `if` and `else` have incompatible types
- --> $DIR/if-then-neeing-semi.rs:50:9
+ --> $DIR/if-then-neeing-semi.rs:41:9
|
LL | let _ = if true {
| _____________-
@@ -43,19 +41,17 @@ LL | | async_dummy();
LL | |
LL | | } else {
LL | | async_dummy2()
- | | ^^^^^^^^^^^^^^ expected `()`, found opaque type
+ | | ^^^^^^^^^^^^^^ expected `()`, found future
... |
LL | |
LL | | };
| |_____- `if` and `else` have incompatible types
|
-note: while checking the return type of the `async fn`
- --> $DIR/if-then-neeing-semi.rs:24:25
+note: calling an async function returns a future
+ --> $DIR/if-then-neeing-semi.rs:41:9
|
-LL | async fn async_dummy2() {}
- | ^ checked the `Output` of this `async fn`, found opaque type
- = note: expected unit type `()`
- found opaque type `impl Future<Output = ()>`
+LL | async_dummy2()
+ | ^^^^^^^^^^^^^^
help: consider `await`ing on the `Future`
|
LL | async_dummy2().await
@@ -69,7 +65,7 @@ LL ~ Box::new(async_dummy2())
|
error[E0308]: `if` and `else` have incompatible types
- --> $DIR/if-then-neeing-semi.rs:63:9
+ --> $DIR/if-then-neeing-semi.rs:54:9
|
LL | let _ = if true {
| _____________-
@@ -79,24 +75,12 @@ LL | | async_dummy()
LL | |
LL | | } else {
LL | | async_dummy2()
- | | ^^^^^^^^^^^^^^ expected opaque type, found a different opaque type
-... |
+ | | ^^^^^^^^^^^^^^ expected future, found a different future
+LL | |
LL | |
LL | | };
| |_____- `if` and `else` have incompatible types
|
-note: while checking the return type of the `async fn`
- --> $DIR/if-then-neeing-semi.rs:18:24
- |
-LL | async fn async_dummy() {}
- | ^ checked the `Output` of this `async fn`, expected opaque type
-note: while checking the return type of the `async fn`
- --> $DIR/if-then-neeing-semi.rs:24:25
- |
-LL | async fn async_dummy2() {}
- | ^ checked the `Output` of this `async fn`, found opaque type
- = note: expected opaque type `impl Future<Output = ()>` (opaque type at <$DIR/if-then-neeing-semi.rs:18:24>)
- found opaque type `impl Future<Output = ()>` (opaque type at <$DIR/if-then-neeing-semi.rs:24:25>)
= note: distinct uses of `impl Trait` result in different opaque types
help: consider `await`ing on both `Future`s
|
diff --git a/tests/ui/suggestions/imm-ref-trait-object-literal-bound-regions.stderr b/tests/ui/suggestions/imm-ref-trait-object-literal-bound-regions.stderr
index 864ab0535..fc5a52174 100644
--- a/tests/ui/suggestions/imm-ref-trait-object-literal-bound-regions.stderr
+++ b/tests/ui/suggestions/imm-ref-trait-object-literal-bound-regions.stderr
@@ -12,7 +12,7 @@ note: required by a bound in `foo`
--> $DIR/imm-ref-trait-object-literal-bound-regions.rs:11:20
|
LL | fn foo<X>(_: X)
- | --- required by a bound in this
+ | --- required by a bound in this function
LL | where
LL | for<'b> &'b X: Trait,
| ^^^^^ required by this bound in `foo`
diff --git a/tests/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.stderr b/tests/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.stderr
index 679ebd61e..da72c8ebf 100644
--- a/tests/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.stderr
+++ b/tests/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.stderr
@@ -17,7 +17,7 @@ note: the used `impl` has a `'static` requirement
LL | impl<T> MyTrait<T> for dyn ObjectTrait<T> {
| ^^^^^^^^^^^^^^ this has an implicit `'static` lifetime requirement
LL | fn use_self<K>(&self) -> &() { panic!() }
- | -------- calling this method introduces the `impl`'s 'static` requirement
+ | -------- calling this method introduces the `impl`'s `'static` requirement
help: consider relaxing the implicit `'static` requirement
|
LL | impl<T> MyTrait<T> for dyn ObjectTrait<T> + '_ {
@@ -42,7 +42,7 @@ note: the used `impl` has a `'static` requirement
LL | impl dyn ObjectTrait {
| ^^^^^^^^^^^ this has an implicit `'static` lifetime requirement
LL | fn use_self(&self) -> &() { panic!() }
- | -------- calling this method introduces the `impl`'s 'static` requirement
+ | -------- calling this method introduces the `impl`'s `'static` requirement
help: consider relaxing the implicit `'static` requirement
|
LL | impl dyn ObjectTrait + '_ {
@@ -65,7 +65,7 @@ note: the used `impl` has a `'static` requirement
--> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:87:26
|
LL | fn use_self(&self) -> &() { panic!() }
- | -------- calling this method introduces the `impl`'s 'static` requirement
+ | -------- calling this method introduces the `impl`'s `'static` requirement
...
LL | impl MyTrait for dyn ObjectTrait {}
| ^^^^^^^^^^^ this has an implicit `'static` lifetime requirement
@@ -91,7 +91,7 @@ note: the used `impl` has a `'static` requirement
--> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:106:26
|
LL | fn use_self(&self) -> &() { panic!() }
- | -------- calling this method introduces the `impl`'s 'static` requirement
+ | -------- calling this method introduces the `impl`'s `'static` requirement
...
LL | impl MyTrait for dyn ObjectTrait {}
| ^^^^^^^^^^^ this has an implicit `'static` lifetime requirement
diff --git a/tests/ui/suggestions/into-convert.stderr b/tests/ui/suggestions/into-convert.stderr
index d43104a21..704b280a9 100644
--- a/tests/ui/suggestions/into-convert.stderr
+++ b/tests/ui/suggestions/into-convert.stderr
@@ -2,7 +2,7 @@ error[E0308]: mismatched types
--> $DIR/into-convert.rs:6:16
|
LL | let x: A = B;
- | - ^ expected struct `A`, found struct `B`
+ | - ^ expected `A`, found `B`
| |
| expected due to this
|
@@ -15,7 +15,7 @@ error[E0308]: mismatched types
--> $DIR/into-convert.rs:10:24
|
LL | let y: Arc<Path> = PathBuf::new();
- | --------- ^^^^^^^^^^^^^^ expected struct `Arc`, found struct `PathBuf`
+ | --------- ^^^^^^^^^^^^^^ expected `Arc<Path>`, found `PathBuf`
| |
| expected due to this
|
@@ -30,7 +30,7 @@ error[E0308]: mismatched types
--> $DIR/into-convert.rs:14:24
|
LL | let z: AtomicU32 = 1;
- | --------- ^ expected struct `AtomicU32`, found integer
+ | --------- ^ expected `AtomicU32`, found integer
| |
| expected due to this
|
diff --git a/tests/ui/suggestions/issue-101065.stderr b/tests/ui/suggestions/issue-101065.stderr
index 6f7ecd24c..9f77ead42 100644
--- a/tests/ui/suggestions/issue-101065.stderr
+++ b/tests/ui/suggestions/issue-101065.stderr
@@ -7,7 +7,7 @@ LL | | FakeResult::Ok(FakeResult::Ok(()))
| | ---------------------------------- expected because of this
LL | | } else {
LL | | FakeResult::Ok(())
- | | ^^^^^^^^^^^^^^^^^^ expected enum `FakeResult`, found `()`
+ | | ^^^^^^^^^^^^^^^^^^ expected `FakeResult<FakeResult<()>>`, found `FakeResult<()>`
LL | | };
| |_____- `if` and `else` have incompatible types
|
diff --git a/tests/ui/suggestions/issue-101421.rs b/tests/ui/suggestions/issue-101421.rs
index b615997d1..1407ebd27 100644
--- a/tests/ui/suggestions/issue-101421.rs
+++ b/tests/ui/suggestions/issue-101421.rs
@@ -8,5 +8,5 @@ impl Ice for () {
fn main() {
().f::<()>(());
- //~^ ERROR this associated function takes 0 generic arguments but 1 generic argument was supplied
+ //~^ ERROR method takes 0 generic arguments but 1 generic argument was supplied
}
diff --git a/tests/ui/suggestions/issue-101421.stderr b/tests/ui/suggestions/issue-101421.stderr
index f8e1efb88..2656ab3db 100644
--- a/tests/ui/suggestions/issue-101421.stderr
+++ b/tests/ui/suggestions/issue-101421.stderr
@@ -1,4 +1,4 @@
-error[E0107]: this associated function takes 0 generic arguments but 1 generic argument was supplied
+error[E0107]: method takes 0 generic arguments but 1 generic argument was supplied
--> $DIR/issue-101421.rs:10:8
|
LL | ().f::<()>(());
@@ -6,7 +6,7 @@ LL | ().f::<()>(());
| |
| expected 0 generic arguments
|
-note: associated function defined here, with 0 generic parameters
+note: method defined here, with 0 generic parameters
--> $DIR/issue-101421.rs:2:8
|
LL | fn f(&self, _: ());
diff --git a/tests/ui/suggestions/issue-101465.stderr b/tests/ui/suggestions/issue-101465.stderr
index e2ca77712..2aec3c863 100644
--- a/tests/ui/suggestions/issue-101465.stderr
+++ b/tests/ui/suggestions/issue-101465.stderr
@@ -5,7 +5,7 @@ LL | / match true {
LL | | true => B,
| | - this is found to be of type `B`
LL | | false => C,
- | | ^ expected struct `B`, found struct `C`
+ | | ^ expected `B`, found `C`
LL | |
LL | | }
| |_____- `match` arms have incompatible types
diff --git a/tests/ui/suggestions/issue-101984.stderr b/tests/ui/suggestions/issue-101984.stderr
index 81758a700..151587d42 100644
--- a/tests/ui/suggestions/issue-101984.stderr
+++ b/tests/ui/suggestions/issue-101984.stderr
@@ -4,7 +4,7 @@ error[E0308]: mismatched types
LL | let (cmp, router) = self.router.at()?;
| ^^^^^^^^^^^^^ ----------------- this expression has type `Match<&(for<'a> fn(&'a ()), Box<Wrapper>)>`
| |
- | expected struct `Match`, found tuple
+ | expected `Match<&(fn(&()), Box<Wrapper>)>`, found `(_, _)`
|
= note: expected struct `Match<&(for<'a> fn(&'a ()), Box<Wrapper>)>`
found tuple `(_, _)`
diff --git a/tests/ui/suggestions/issue-102892.stderr b/tests/ui/suggestions/issue-102892.stderr
index a3dbc7cb8..e64a89ffe 100644
--- a/tests/ui/suggestions/issue-102892.stderr
+++ b/tests/ui/suggestions/issue-102892.stderr
@@ -2,7 +2,7 @@ error[E0308]: mismatched types
--> $DIR/issue-102892.rs:15:26
|
LL | let (a, b): (A, B) = &**arc; // suggests putting `&**arc` here too
- | ------ ^^^^^^ expected tuple, found `&(A, B)`
+ | ------ ^^^^^^ expected `(A, B)`, found `&(A, B)`
| |
| expected due to this
|
@@ -22,7 +22,7 @@ error[E0308]: mismatched types
--> $DIR/issue-102892.rs:20:32
|
LL | let (a, b): ((A, B), A) = (&mut *mutation, &(**arc).0); // suggests putting `&**arc` here too
- | ^^^^^^^^^^^^^^ expected tuple, found `&mut (A, B)`
+ | ^^^^^^^^^^^^^^ expected `(A, B)`, found `&mut (A, B)`
|
= note: expected tuple `(A, B)`
found mutable reference `&mut (A, B)`
@@ -40,7 +40,7 @@ error[E0308]: mismatched types
--> $DIR/issue-102892.rs:20:48
|
LL | let (a, b): ((A, B), A) = (&mut *mutation, &(**arc).0); // suggests putting `&**arc` here too
- | ^^^^^^^^^^ expected struct `A`, found `&A`
+ | ^^^^^^^^^^ expected `A`, found `&A`
|
help: consider removing the borrow
|
diff --git a/tests/ui/suggestions/issue-104287.rs b/tests/ui/suggestions/issue-104287.rs
index e3fa22a8f..37b3339fa 100644
--- a/tests/ui/suggestions/issue-104287.rs
+++ b/tests/ui/suggestions/issue-104287.rs
@@ -8,6 +8,6 @@ impl S {
fn main() {
let x = S;
foo::<()>(x);
- //~^ ERROR this associated function takes 0 generic arguments but 1 generic argument was supplied
+ //~^ ERROR method takes 0 generic arguments but 1 generic argument was supplied
//~| ERROR cannot find function `foo` in this scope
}
diff --git a/tests/ui/suggestions/issue-104287.stderr b/tests/ui/suggestions/issue-104287.stderr
index 602a01828..ed59b2e7a 100644
--- a/tests/ui/suggestions/issue-104287.stderr
+++ b/tests/ui/suggestions/issue-104287.stderr
@@ -1,4 +1,4 @@
-error[E0107]: this associated function takes 0 generic arguments but 1 generic argument was supplied
+error[E0107]: method takes 0 generic arguments but 1 generic argument was supplied
--> $DIR/issue-104287.rs:10:5
|
LL | foo::<()>(x);
@@ -6,7 +6,7 @@ LL | foo::<()>(x);
| |
| expected 0 generic arguments
|
-note: associated function defined here, with 0 generic parameters
+note: method defined here, with 0 generic parameters
--> $DIR/issue-104287.rs:6:8
|
LL | fn foo(&self) {}
diff --git a/tests/ui/suggestions/issue-104961.fixed b/tests/ui/suggestions/issue-104961.fixed
new file mode 100644
index 000000000..520d638b1
--- /dev/null
+++ b/tests/ui/suggestions/issue-104961.fixed
@@ -0,0 +1,16 @@
+// run-rustfix
+
+fn foo(x: &str) -> bool {
+ x.starts_with(&("hi".to_string() + " you"))
+ //~^ ERROR expected a `FnMut<(char,)>` closure, found `String`
+}
+
+fn foo2(x: &str) -> bool {
+ x.starts_with(&"hi".to_string())
+ //~^ ERROR expected a `FnMut<(char,)>` closure, found `String`
+}
+
+fn main() {
+ foo("hi you");
+ foo2("hi");
+}
diff --git a/tests/ui/suggestions/issue-104961.rs b/tests/ui/suggestions/issue-104961.rs
new file mode 100644
index 000000000..aeb787abb
--- /dev/null
+++ b/tests/ui/suggestions/issue-104961.rs
@@ -0,0 +1,16 @@
+// run-rustfix
+
+fn foo(x: &str) -> bool {
+ x.starts_with("hi".to_string() + " you")
+ //~^ ERROR expected a `FnMut<(char,)>` closure, found `String`
+}
+
+fn foo2(x: &str) -> bool {
+ x.starts_with("hi".to_string())
+ //~^ ERROR expected a `FnMut<(char,)>` closure, found `String`
+}
+
+fn main() {
+ foo("hi you");
+ foo2("hi");
+}
diff --git a/tests/ui/suggestions/issue-104961.stderr b/tests/ui/suggestions/issue-104961.stderr
new file mode 100644
index 000000000..8cec6a3f8
--- /dev/null
+++ b/tests/ui/suggestions/issue-104961.stderr
@@ -0,0 +1,37 @@
+error[E0277]: expected a `FnMut<(char,)>` closure, found `String`
+ --> $DIR/issue-104961.rs:4:19
+ |
+LL | x.starts_with("hi".to_string() + " you")
+ | ----------- ^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Pattern<'_>` is not implemented for `String`
+ | |
+ | required by a bound introduced by this call
+ |
+ = note: the trait bound `String: Pattern<'_>` is not satisfied
+ = note: required for `String` to implement `Pattern<'_>`
+note: required by a bound in `core::str::<impl str>::starts_with`
+ --> $SRC_DIR/core/src/str/mod.rs:LL:COL
+help: consider borrowing here
+ |
+LL | x.starts_with(&("hi".to_string() + " you"))
+ | ++ +
+
+error[E0277]: expected a `FnMut<(char,)>` closure, found `String`
+ --> $DIR/issue-104961.rs:9:19
+ |
+LL | x.starts_with("hi".to_string())
+ | ----------- ^^^^^^^^^^^^^^^^ the trait `Pattern<'_>` is not implemented for `String`
+ | |
+ | required by a bound introduced by this call
+ |
+ = note: the trait bound `String: Pattern<'_>` is not satisfied
+ = note: required for `String` to implement `Pattern<'_>`
+note: required by a bound in `core::str::<impl str>::starts_with`
+ --> $SRC_DIR/core/src/str/mod.rs:LL:COL
+help: consider borrowing here
+ |
+LL | x.starts_with(&"hi".to_string())
+ | +
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/suggestions/issue-105494.stderr b/tests/ui/suggestions/issue-105494.stderr
index 5aa3f2af7..4cb4a399a 100644
--- a/tests/ui/suggestions/issue-105494.stderr
+++ b/tests/ui/suggestions/issue-105494.stderr
@@ -2,7 +2,7 @@ error[E0308]: mismatched types
--> $DIR/issue-105494.rs:2:19
|
LL | let _v: i32 = (1 as i32).to_string();
- | --- ^^^^^^^^^^^^^^^^^^^^^^ expected `i32`, found struct `String`
+ | --- ^^^^^^^^^^^^^^^^^^^^^^ expected `i32`, found `String`
| |
| expected due to this
|
@@ -16,7 +16,7 @@ error[E0308]: mismatched types
--> $DIR/issue-105494.rs:5:19
|
LL | let _v: i32 = (1 as i128).to_string();
- | --- ^^^^^^^^^^^^^^^^^^^^^^^ expected `i32`, found struct `String`
+ | --- ^^^^^^^^^^^^^^^^^^^^^^^ expected `i32`, found `String`
| |
| expected due to this
@@ -24,7 +24,7 @@ error[E0308]: mismatched types
--> $DIR/issue-105494.rs:7:20
|
LL | let _v: &str = "foo".to_string();
- | ---- ^^^^^^^^^^^^^^^^^ expected `&str`, found struct `String`
+ | ---- ^^^^^^^^^^^^^^^^^ expected `&str`, found `String`
| |
| expected due to this
|
@@ -41,7 +41,7 @@ LL | let mut path: String = "/usr".to_string();
| ------ expected due to this type
...
LL | path = format!("{}/{}", path, folder).as_str();
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected struct `String`, found `&str`
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `String`, found `&str`
|
help: try removing the method call
|
diff --git a/tests/ui/suggestions/issue-106443-sugg-clone-for-arg.stderr b/tests/ui/suggestions/issue-106443-sugg-clone-for-arg.stderr
index 1e66fe3af..4e91dfc82 100644
--- a/tests/ui/suggestions/issue-106443-sugg-clone-for-arg.stderr
+++ b/tests/ui/suggestions/issue-106443-sugg-clone-for-arg.stderr
@@ -2,7 +2,7 @@ error[E0308]: mismatched types
--> $DIR/issue-106443-sugg-clone-for-arg.rs:11:9
|
LL | foo(s);
- | --- ^ expected struct `S`, found `&S`
+ | --- ^ expected `S`, found `&S`
| |
| arguments to this function are incorrect
|
@@ -20,7 +20,7 @@ error[E0308]: mismatched types
--> $DIR/issue-106443-sugg-clone-for-arg.rs:17:9
|
LL | bar(t);
- | --- ^ expected struct `T`, found `&T`
+ | --- ^ expected `T`, found `&T`
| |
| arguments to this function are incorrect
|
diff --git a/tests/ui/suggestions/issue-52820.stderr b/tests/ui/suggestions/issue-52820.stderr
index 09269ed4e..a67d75014 100644
--- a/tests/ui/suggestions/issue-52820.stderr
+++ b/tests/ui/suggestions/issue-52820.stderr
@@ -2,7 +2,7 @@ error[E0308]: mismatched types
--> $DIR/issue-52820.rs:12:9
|
LL | guts,
- | ^^^^ expected struct `String`, found `&str`
+ | ^^^^ expected `String`, found `&str`
|
help: try using a conversion method
|
@@ -16,7 +16,7 @@ LL | brains: guts.clone(),
| ^^^^^-----^^
| | |
| | help: try using a conversion method: `to_string`
- | expected struct `String`, found `&str`
+ | expected `String`, found `&str`
error: aborting due to 2 previous errors
diff --git a/tests/ui/suggestions/issue-53692.stderr b/tests/ui/suggestions/issue-53692.stderr
index 3a1b624f4..469a53841 100644
--- a/tests/ui/suggestions/issue-53692.stderr
+++ b/tests/ui/suggestions/issue-53692.stderr
@@ -5,7 +5,7 @@ LL | let items_clone: Vec<i32> = ref_items.clone();
| -------- ^^^^^^^^^^-----^^
| | | |
| | | help: try using a conversion method: `to_vec`
- | | expected struct `Vec`, found `&[i32]`
+ | | expected `Vec<i32>`, found `&[i32]`
| expected due to this
|
= note: expected struct `Vec<i32>`
@@ -18,7 +18,7 @@ LL | let string: String = s.clone();
| ------ ^^-----^^
| | | |
| | | help: try using a conversion method: `to_string`
- | | expected struct `String`, found `&str`
+ | | expected `String`, found `&str`
| expected due to this
error: aborting due to 2 previous errors
diff --git a/tests/ui/suggestions/issue-59819.stderr b/tests/ui/suggestions/issue-59819.stderr
index 40e4c7b78..43acf9549 100644
--- a/tests/ui/suggestions/issue-59819.stderr
+++ b/tests/ui/suggestions/issue-59819.stderr
@@ -2,7 +2,7 @@ error[E0308]: mismatched types
--> $DIR/issue-59819.rs:28:18
|
LL | let y: i32 = x;
- | --- ^ expected `i32`, found struct `Foo`
+ | --- ^ expected `i32`, found `Foo`
| |
| expected due to this
|
@@ -30,7 +30,7 @@ error[E0308]: mismatched types
LL | let g: String = f;
| ------ ^- help: try using a conversion method: `.to_string()`
| | |
- | | expected struct `String`, found struct `Bar`
+ | | expected `String`, found `Bar`
| expected due to this
error: aborting due to 3 previous errors
diff --git a/tests/ui/suggestions/issue-81839.stderr b/tests/ui/suggestions/issue-81839.stderr
index fae474ced..6d0a0c7b3 100644
--- a/tests/ui/suggestions/issue-81839.stderr
+++ b/tests/ui/suggestions/issue-81839.stderr
@@ -10,17 +10,9 @@ LL | | cx.answer_str("hi");
| | this is found to be of type `()`
LL | | }
LL | | _ => cx.answer_str("hi"),
- | | ^^^^^^^^^^^^^^^^^^^ expected `()`, found opaque type
+ | | ^^^^^^^^^^^^^^^^^^^ expected `()`, found future
LL | | }
| |_____- `match` arms have incompatible types
- |
-note: while checking the return type of the `async fn`
- --> $DIR/auxiliary/issue-81839.rs:6:49
- |
-LL | pub async fn answer_str(&self, _s: &str) -> Test {
- | ^^^^ checked the `Output` of this `async fn`, found opaque type
- = note: expected unit type `()`
- found opaque type `impl Future<Output = Test>`
error: aborting due to previous error
diff --git a/tests/ui/suggestions/issue-83943.stderr b/tests/ui/suggestions/issue-83943.stderr
index 885106e84..c73667f09 100644
--- a/tests/ui/suggestions/issue-83943.stderr
+++ b/tests/ui/suggestions/issue-83943.stderr
@@ -8,7 +8,7 @@ LL | | } else {
LL | | "B"
| | ^^^- help: try using a conversion method: `.to_string()`
| | |
- | | expected struct `String`, found `&str`
+ | | expected `String`, found `&str`
LL | | };
| |_____- `if` and `else` have incompatible types
diff --git a/tests/ui/suggestions/issue-84973.stderr b/tests/ui/suggestions/issue-84973.stderr
index ae2bf5aac..55c89884a 100644
--- a/tests/ui/suggestions/issue-84973.stderr
+++ b/tests/ui/suggestions/issue-84973.stderr
@@ -13,7 +13,7 @@ LL | G: SomeTrait,
| ^^^^^^^^^ required by this bound in `Other::<'a, G>::new`
LL | {
LL | pub fn new(g: G) -> Self {
- | --- required by a bound in this
+ | --- required by a bound in this associated function
help: consider borrowing here
|
LL | let o = Other::new(&f);
diff --git a/tests/ui/suggestions/issue-85347.rs b/tests/ui/suggestions/issue-85347.rs
index 02b5fb618..04d4c47d8 100644
--- a/tests/ui/suggestions/issue-85347.rs
+++ b/tests/ui/suggestions/issue-85347.rs
@@ -1,7 +1,7 @@
use std::ops::Deref;
trait Foo {
type Bar<'a>: Deref<Target = <Self>::Bar<Target = Self>>;
- //~^ ERROR this associated type takes 1 lifetime argument but 0 lifetime arguments were supplied
+ //~^ ERROR associated type takes 1 lifetime argument but 0 lifetime arguments were supplied
//~| ERROR associated type bindings are not allowed here
//~| HELP add missing
}
diff --git a/tests/ui/suggestions/issue-85347.stderr b/tests/ui/suggestions/issue-85347.stderr
index 17c1b7dc4..f330b3c1f 100644
--- a/tests/ui/suggestions/issue-85347.stderr
+++ b/tests/ui/suggestions/issue-85347.stderr
@@ -1,4 +1,4 @@
-error[E0107]: this associated type takes 1 lifetime argument but 0 lifetime arguments were supplied
+error[E0107]: associated type takes 1 lifetime argument but 0 lifetime arguments were supplied
--> $DIR/issue-85347.rs:3:42
|
LL | type Bar<'a>: Deref<Target = <Self>::Bar<Target = Self>>;
diff --git a/tests/ui/suggestions/issue-86100-tuple-paren-comma.stderr b/tests/ui/suggestions/issue-86100-tuple-paren-comma.stderr
index 8c9a41a20..da6f7641b 100644
--- a/tests/ui/suggestions/issue-86100-tuple-paren-comma.stderr
+++ b/tests/ui/suggestions/issue-86100-tuple-paren-comma.stderr
@@ -2,7 +2,7 @@ error[E0308]: mismatched types
--> $DIR/issue-86100-tuple-paren-comma.rs:9:22
|
LL | let _x: (i32,) = (5);
- | ------ ^^^ expected tuple, found integer
+ | ------ ^^^ expected `(i32,)`, found integer
| |
| expected due to this
|
@@ -17,7 +17,7 @@ error[E0308]: mismatched types
--> $DIR/issue-86100-tuple-paren-comma.rs:13:9
|
LL | foo((Some(3)));
- | --- ^^^^^^^^^ expected tuple, found enum `Option`
+ | --- ^^^^^^^^^ expected `(_,)`, found `Option<{integer}>`
| |
| arguments to this function are incorrect
|
@@ -37,7 +37,7 @@ error[E0308]: mismatched types
--> $DIR/issue-86100-tuple-paren-comma.rs:17:22
|
LL | let _s = S { _s: ("abc".to_string()) };
- | ^^^^^^^^^^^^^^^^^^^ expected tuple, found struct `String`
+ | ^^^^^^^^^^^^^^^^^^^ expected `(String,)`, found `String`
|
= note: expected tuple `(String,)`
found struct `String`
diff --git a/tests/ui/suggestions/issue-89064.stderr b/tests/ui/suggestions/issue-89064.stderr
index 93d8da226..be09dd895 100644
--- a/tests/ui/suggestions/issue-89064.stderr
+++ b/tests/ui/suggestions/issue-89064.stderr
@@ -1,4 +1,4 @@
-error[E0107]: this associated function takes 0 generic arguments but 1 generic argument was supplied
+error[E0107]: associated function takes 0 generic arguments but 1 generic argument was supplied
--> $DIR/issue-89064.rs:17:16
|
LL | let _ = A::foo::<S>();
@@ -20,7 +20,7 @@ LL - let _ = A::foo::<S>();
LL + let _ = A::foo();
|
-error[E0107]: this associated function takes 0 generic arguments but 2 generic arguments were supplied
+error[E0107]: associated function takes 0 generic arguments but 2 generic arguments were supplied
--> $DIR/issue-89064.rs:22:16
|
LL | let _ = B::bar::<S, S>();
@@ -42,7 +42,7 @@ LL - let _ = B::bar::<S, S>();
LL + let _ = B::bar();
|
-error[E0107]: this associated function takes 0 generic arguments but 1 generic argument was supplied
+error[E0107]: associated function takes 0 generic arguments but 1 generic argument was supplied
--> $DIR/issue-89064.rs:27:21
|
LL | let _ = A::<S>::foo::<S>();
@@ -56,7 +56,7 @@ note: associated function defined here, with 0 generic parameters
LL | fn foo() {}
| ^^^
-error[E0107]: this associated function takes 0 generic arguments but 1 generic argument was supplied
+error[E0107]: method takes 0 generic arguments but 1 generic argument was supplied
--> $DIR/issue-89064.rs:31:16
|
LL | let _ = 42.into::<Option<_>>();
diff --git a/tests/ui/suggestions/issue-90213-expected-boxfuture-self-ice.stderr b/tests/ui/suggestions/issue-90213-expected-boxfuture-self-ice.stderr
index 611f7d5dd..7d1da7d24 100644
--- a/tests/ui/suggestions/issue-90213-expected-boxfuture-self-ice.stderr
+++ b/tests/ui/suggestions/issue-90213-expected-boxfuture-self-ice.stderr
@@ -2,7 +2,7 @@ error[E0308]: mismatched types
--> $DIR/issue-90213-expected-boxfuture-self-ice.rs:9:19
|
LL | Self::foo(None)
- | --------- ^^^^ expected struct `Box`, found enum `Option`
+ | --------- ^^^^ expected `Box<Option<S>>`, found `Option<_>`
| |
| arguments to this function are incorrect
|
diff --git a/tests/ui/suggestions/late-bound-in-borrow-closure-sugg.rs b/tests/ui/suggestions/late-bound-in-borrow-closure-sugg.rs
new file mode 100644
index 000000000..3bf6b7bb9
--- /dev/null
+++ b/tests/ui/suggestions/late-bound-in-borrow-closure-sugg.rs
@@ -0,0 +1,28 @@
+use std::cell::RefCell;
+use std::collections::HashMap;
+use std::rc::Rc;
+
+pub struct Trader<'a> {
+ closure: Box<dyn Fn(&mut Trader) + 'a>,
+}
+
+impl<'a> Trader<'a> {
+ pub fn new() -> Self {
+ Trader {
+ closure: Box::new(|_| {}),
+ }
+ }
+ pub fn set_closure(&mut self, function: impl Fn(&mut Trader) + 'a) {
+ //foo
+ }
+}
+
+fn main() {
+ let closure = |trader : Trader| {
+ println!("Woooosh!");
+ };
+
+ let mut trader = Trader::new();
+ trader.set_closure(closure);
+ //~^ ERROR type mismatch in closure arguments
+}
diff --git a/tests/ui/suggestions/late-bound-in-borrow-closure-sugg.stderr b/tests/ui/suggestions/late-bound-in-borrow-closure-sugg.stderr
new file mode 100644
index 000000000..6820af1fd
--- /dev/null
+++ b/tests/ui/suggestions/late-bound-in-borrow-closure-sugg.stderr
@@ -0,0 +1,26 @@
+error[E0631]: type mismatch in closure arguments
+ --> $DIR/late-bound-in-borrow-closure-sugg.rs:26:24
+ |
+LL | let closure = |trader : Trader| {
+ | ----------------- found signature defined here
+...
+LL | trader.set_closure(closure);
+ | ----------- ^^^^^^^ expected due to this
+ | |
+ | required by a bound introduced by this call
+ |
+ = note: expected closure signature `for<'a, 'b> fn(&'a mut Trader<'b>) -> _`
+ found closure signature `for<'a> fn(Trader<'a>) -> _`
+note: required by a bound in `Trader::<'a>::set_closure`
+ --> $DIR/late-bound-in-borrow-closure-sugg.rs:15:50
+ |
+LL | pub fn set_closure(&mut self, function: impl Fn(&mut Trader) + 'a) {
+ | ^^^^^^^^^^^^^^^ required by this bound in `Trader::<'a>::set_closure`
+help: consider borrowing the argument
+ |
+LL | let closure = |trader : &mut Trader| {
+ | ++++
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0631`.
diff --git a/tests/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr b/tests/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr
index c5c3f7b46..93cfa60b5 100644
--- a/tests/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr
+++ b/tests/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr
@@ -10,7 +10,9 @@ error[E0700]: hidden type for `impl FnOnce()` captures lifetime that does not ap
--> $DIR/missing-lifetimes-in-signature.rs:19:5
|
LL | fn foo<G, T>(g: G, dest: &mut T) -> impl FnOnce()
- | ------ hidden type `[closure@$DIR/missing-lifetimes-in-signature.rs:19:5: 19:12]` captures the anonymous lifetime defined here
+ | ------ ------------- opaque type defined here
+ | |
+ | hidden type `[closure@$DIR/missing-lifetimes-in-signature.rs:19:5: 19:12]` captures the anonymous lifetime defined here
...
LL | / move || {
LL | |
diff --git a/tests/ui/suggestions/match-ergonomics.stderr b/tests/ui/suggestions/match-ergonomics.stderr
index aa2b407bf..a3e059e8a 100644
--- a/tests/ui/suggestions/match-ergonomics.stderr
+++ b/tests/ui/suggestions/match-ergonomics.stderr
@@ -4,7 +4,7 @@ error[E0308]: mismatched types
LL | match &x[..] {
| ------ this expression has type `&[i32]`
LL | [&v] => {},
- | ^^ expected `i32`, found reference
+ | ^^ expected `i32`, found `&_`
|
= note: expected type `i32`
found reference `&_`
@@ -36,7 +36,7 @@ error[E0308]: mismatched types
LL | match y {
| - this expression has type `i32`
LL | &v => {},
- | ^^ expected `i32`, found reference
+ | ^^ expected `i32`, found `&_`
|
= note: expected type `i32`
found reference `&_`
@@ -52,7 +52,7 @@ error[E0308]: mismatched types
LL | if let [&v] = &x[..] {}
| ^^ ------ this expression has type `&[i32]`
| |
- | expected `i32`, found reference
+ | expected `i32`, found `&_`
|
= note: expected type `i32`
found reference `&_`
diff --git a/tests/ui/suggestions/match-prev-arm-needing-semi.rs b/tests/ui/suggestions/match-prev-arm-needing-semi.rs
index 8c8abe047..11463c453 100644
--- a/tests/ui/suggestions/match-prev-arm-needing-semi.rs
+++ b/tests/ui/suggestions/match-prev-arm-needing-semi.rs
@@ -13,18 +13,9 @@ fn extra_semicolon() {
};
}
-async fn async_dummy() {} //~ NOTE checked the `Output` of this `async fn`, found opaque type
-//~| NOTE while checking the return type of the `async fn`
-//~| NOTE in this expansion of desugaring of `async` block or function
-//~| NOTE checked the `Output` of this `async fn`, expected opaque type
-//~| NOTE while checking the return type of the `async fn`
-//~| NOTE in this expansion of desugaring of `async` block or function
-async fn async_dummy2() {} //~ NOTE checked the `Output` of this `async fn`, found opaque type
-//~| NOTE checked the `Output` of this `async fn`, found opaque type
-//~| NOTE while checking the return type of the `async fn`
-//~| NOTE in this expansion of desugaring of `async` block or function
-//~| NOTE while checking the return type of the `async fn`
-//~| NOTE in this expansion of desugaring of `async` block or function
+async fn async_dummy() {}
+
+async fn async_dummy2() {}
async fn async_extra_semicolon_same() {
let _ = match true { //~ NOTE `match` arms have incompatible types
@@ -33,8 +24,8 @@ async fn async_extra_semicolon_same() {
//~^ HELP consider removing this semicolon
}
false => async_dummy(), //~ ERROR `match` arms have incompatible types
- //~^ NOTE expected `()`, found opaque type
- //~| NOTE expected unit type `()`
+ //~^ NOTE expected `()`, found future
+ //~| NOTE calling an async function returns a future
//~| HELP consider `await`ing on the `Future`
};
}
@@ -46,8 +37,8 @@ async fn async_extra_semicolon_different() {
//~^ HELP consider removing this semicolon
}
false => async_dummy2(), //~ ERROR `match` arms have incompatible types
- //~^ NOTE expected `()`, found opaque type
- //~| NOTE expected unit type `()`
+ //~^ NOTE expected `()`, found future
+ //~| NOTE calling an async function returns a future
//~| HELP consider `await`ing on the `Future`
};
}
@@ -57,8 +48,7 @@ async fn async_different_futures() {
true => async_dummy(), //~ NOTE this is found to be
//~| HELP consider `await`ing on both `Future`s
false => async_dummy2(), //~ ERROR `match` arms have incompatible types
- //~^ NOTE expected opaque type, found a different opaque type
- //~| NOTE expected opaque type `impl Future<Output = ()>`
+ //~^ NOTE expected future, found a different future
//~| NOTE distinct uses of `impl Trait` result in different opaque types
};
}
diff --git a/tests/ui/suggestions/match-prev-arm-needing-semi.stderr b/tests/ui/suggestions/match-prev-arm-needing-semi.stderr
index 8d735b71f..cf3cf45ef 100644
--- a/tests/ui/suggestions/match-prev-arm-needing-semi.stderr
+++ b/tests/ui/suggestions/match-prev-arm-needing-semi.stderr
@@ -1,5 +1,5 @@
error[E0308]: `match` arms have incompatible types
- --> $DIR/match-prev-arm-needing-semi.rs:35:18
+ --> $DIR/match-prev-arm-needing-semi.rs:26:18
|
LL | let _ = match true {
| _____________-
@@ -9,19 +9,17 @@ LL | | async_dummy();
LL | |
LL | | }
LL | | false => async_dummy(),
- | | ^^^^^^^^^^^^^ expected `()`, found opaque type
+ | | ^^^^^^^^^^^^^ expected `()`, found future
... |
LL | |
LL | | };
| |_____- `match` arms have incompatible types
|
-note: while checking the return type of the `async fn`
- --> $DIR/match-prev-arm-needing-semi.rs:16:24
+note: calling an async function returns a future
+ --> $DIR/match-prev-arm-needing-semi.rs:26:18
|
-LL | async fn async_dummy() {}
- | ^ checked the `Output` of this `async fn`, found opaque type
- = note: expected unit type `()`
- found opaque type `impl Future<Output = ()>`
+LL | false => async_dummy(),
+ | ^^^^^^^^^^^^^
help: consider `await`ing on the `Future`
|
LL | false => async_dummy().await,
@@ -33,7 +31,7 @@ LL + async_dummy()
|
error[E0308]: `match` arms have incompatible types
- --> $DIR/match-prev-arm-needing-semi.rs:48:18
+ --> $DIR/match-prev-arm-needing-semi.rs:39:18
|
LL | let _ = match true {
| _____________-
@@ -43,19 +41,17 @@ LL | | async_dummy();
LL | |
LL | | }
LL | | false => async_dummy2(),
- | | ^^^^^^^^^^^^^^ expected `()`, found opaque type
+ | | ^^^^^^^^^^^^^^ expected `()`, found future
... |
LL | |
LL | | };
| |_____- `match` arms have incompatible types
|
-note: while checking the return type of the `async fn`
- --> $DIR/match-prev-arm-needing-semi.rs:22:25
+note: calling an async function returns a future
+ --> $DIR/match-prev-arm-needing-semi.rs:39:18
|
-LL | async fn async_dummy2() {}
- | ^ checked the `Output` of this `async fn`, found opaque type
- = note: expected unit type `()`
- found opaque type `impl Future<Output = ()>`
+LL | false => async_dummy2(),
+ | ^^^^^^^^^^^^^^
help: consider `await`ing on the `Future`
|
LL | false => async_dummy2().await,
@@ -69,7 +65,7 @@ LL ~ false => Box::new(async_dummy2()),
|
error[E0308]: `match` arms have incompatible types
- --> $DIR/match-prev-arm-needing-semi.rs:59:18
+ --> $DIR/match-prev-arm-needing-semi.rs:50:18
|
LL | let _ = match true {
| _____________-
@@ -77,24 +73,12 @@ LL | | true => async_dummy(),
| | ------------- this is found to be of type `impl Future<Output = ()>`
LL | |
LL | | false => async_dummy2(),
- | | ^^^^^^^^^^^^^^ expected opaque type, found a different opaque type
-... |
+ | | ^^^^^^^^^^^^^^ expected future, found a different future
+LL | |
LL | |
LL | | };
| |_____- `match` arms have incompatible types
|
-note: while checking the return type of the `async fn`
- --> $DIR/match-prev-arm-needing-semi.rs:16:24
- |
-LL | async fn async_dummy() {}
- | ^ checked the `Output` of this `async fn`, expected opaque type
-note: while checking the return type of the `async fn`
- --> $DIR/match-prev-arm-needing-semi.rs:22:25
- |
-LL | async fn async_dummy2() {}
- | ^ checked the `Output` of this `async fn`, found opaque type
- = note: expected opaque type `impl Future<Output = ()>` (opaque type at <$DIR/match-prev-arm-needing-semi.rs:16:24>)
- found opaque type `impl Future<Output = ()>` (opaque type at <$DIR/match-prev-arm-needing-semi.rs:22:25>)
= note: distinct uses of `impl Trait` result in different opaque types
help: consider `await`ing on both `Future`s
|
diff --git a/tests/ui/suggestions/match-with-different-arm-types-as-stmt-instead-of-expr.stderr b/tests/ui/suggestions/match-with-different-arm-types-as-stmt-instead-of-expr.stderr
index 00aa7d18a..51ea5b35a 100644
--- a/tests/ui/suggestions/match-with-different-arm-types-as-stmt-instead-of-expr.stderr
+++ b/tests/ui/suggestions/match-with-different-arm-types-as-stmt-instead-of-expr.stderr
@@ -16,7 +16,7 @@ LL | / match c {
LL | | "baz" => Box::new(Baz),
| | ------------- this is found to be of type `Box<Baz>`
LL | | _ => Box::new(Bar),
- | | ^^^^^^^^^^^^^ expected struct `Baz`, found struct `Bar`
+ | | ^^^^^^^^^^^^^ expected `Box<Baz>`, found `Box<Bar>`
LL | | };
| |_____- `match` arms have incompatible types
|
@@ -39,7 +39,7 @@ error[E0308]: mismatched types
--> $DIR/match-with-different-arm-types-as-stmt-instead-of-expr.rs:23:22
|
LL | fn wrong(c: &str) -> Box<dyn Foo> {
- | ----- ^^^^^^^^^^^^ expected struct `Box`, found `()`
+ | ----- ^^^^^^^^^^^^ expected `Box<dyn Foo>`, found `()`
| |
| implicitly returns `()` as its body has no tail or `return` expression
|
diff --git a/tests/ui/suggestions/method-access-to-range-literal-typo.stderr b/tests/ui/suggestions/method-access-to-range-literal-typo.stderr
index f42140894..54a16b8ef 100644
--- a/tests/ui/suggestions/method-access-to-range-literal-typo.stderr
+++ b/tests/ui/suggestions/method-access-to-range-literal-typo.stderr
@@ -16,7 +16,7 @@ error[E0308]: mismatched types
LL | fn method(&self) -> Option<&Vec<u8>> {
| ---------------- expected `Option<&Vec<u8>>` because of return type
LL | self.option..as_ref().map(|x| x)
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected enum `Option`, found struct `Range`
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `Option<&Vec<u8>>`, found `Range<Option<Vec<u8>>>`
|
= note: expected enum `Option<&Vec<u8>>`
found struct `std::ops::Range<Option<Vec<u8>>>`
@@ -32,7 +32,7 @@ error[E0308]: mismatched types
LL | fn method2(&self) -> Option<&u8> {
| ----------- expected `Option<&u8>` because of return type
LL | self.option..foo().get(0)
- | ^^^^^^^^^^^^^^^^^^^^^^^^^ expected enum `Option`, found struct `Range`
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^ expected `Option<&u8>`, found `Range<Option<Vec<u8>>>`
|
= note: expected enum `Option<&u8>`
found struct `std::ops::Range<Option<Vec<u8>>>`
diff --git a/tests/ui/suggestions/missing-lifetime-specifier.rs b/tests/ui/suggestions/missing-lifetime-specifier.rs
index 24f5f782f..cb734e8ba 100644
--- a/tests/ui/suggestions/missing-lifetime-specifier.rs
+++ b/tests/ui/suggestions/missing-lifetime-specifier.rs
@@ -37,19 +37,19 @@ thread_local! {
thread_local! {
static e: RefCell<HashMap<i32, Vec<Vec<Qux<'static, i32>>>>> = RefCell::new(HashMap::new());
- //~^ ERROR this union takes 2 lifetime arguments but 1 lifetime argument
- //~| ERROR this union takes 2 lifetime arguments but 1 lifetime argument was supplied
- //~| ERROR this union takes 2 lifetime arguments but 1 lifetime argument was supplied
- //~| ERROR this union takes 2 lifetime arguments but 1 lifetime argument was supplied
- //~| ERROR this union takes 2 lifetime arguments but 1 lifetime argument was supplied
+ //~^ ERROR union takes 2 lifetime arguments but 1 lifetime argument
+ //~| ERROR union takes 2 lifetime arguments but 1 lifetime argument was supplied
+ //~| ERROR union takes 2 lifetime arguments but 1 lifetime argument was supplied
+ //~| ERROR union takes 2 lifetime arguments but 1 lifetime argument was supplied
+ //~| ERROR union takes 2 lifetime arguments but 1 lifetime argument was supplied
}
thread_local! {
static f: RefCell<HashMap<i32, Vec<Vec<&Tar<'static, i32>>>>> = RefCell::new(HashMap::new());
- //~^ ERROR this trait takes 2 lifetime arguments but 1 lifetime argument was supplied
- //~| ERROR this trait takes 2 lifetime arguments but 1 lifetime argument was supplied
- //~| ERROR this trait takes 2 lifetime arguments but 1 lifetime argument was supplied
- //~| ERROR this trait takes 2 lifetime arguments but 1 lifetime argument was supplied
- //~| ERROR this trait takes 2 lifetime arguments but 1 lifetime argument was supplied
+ //~^ ERROR trait takes 2 lifetime arguments but 1 lifetime argument was supplied
+ //~| ERROR trait takes 2 lifetime arguments but 1 lifetime argument was supplied
+ //~| ERROR trait takes 2 lifetime arguments but 1 lifetime argument was supplied
+ //~| ERROR trait takes 2 lifetime arguments but 1 lifetime argument was supplied
+ //~| ERROR trait takes 2 lifetime arguments but 1 lifetime argument was supplied
//~| ERROR missing lifetime
//~| ERROR missing lifetime
}
diff --git a/tests/ui/suggestions/missing-lifetime-specifier.stderr b/tests/ui/suggestions/missing-lifetime-specifier.stderr
index 997bbb5e9..21d237838 100644
--- a/tests/ui/suggestions/missing-lifetime-specifier.stderr
+++ b/tests/ui/suggestions/missing-lifetime-specifier.stderr
@@ -133,7 +133,7 @@ LL | | }
|
= help: this function's return type contains a borrowed value, but the signature does not say which one of `init`'s 3 lifetimes it is borrowed from
-error[E0107]: this union takes 2 lifetime arguments but 1 lifetime argument was supplied
+error[E0107]: union takes 2 lifetime arguments but 1 lifetime argument was supplied
--> $DIR/missing-lifetime-specifier.rs:39:44
|
LL | static e: RefCell<HashMap<i32, Vec<Vec<Qux<'static, i32>>>>> = RefCell::new(HashMap::new());
@@ -151,7 +151,7 @@ help: add missing lifetime argument
LL | static e: RefCell<HashMap<i32, Vec<Vec<Qux<'static, 'static, i32>>>>> = RefCell::new(HashMap::new());
| +++++++++
-error[E0107]: this union takes 2 lifetime arguments but 1 lifetime argument was supplied
+error[E0107]: union takes 2 lifetime arguments but 1 lifetime argument was supplied
--> $DIR/missing-lifetime-specifier.rs:39:44
|
LL | static e: RefCell<HashMap<i32, Vec<Vec<Qux<'static, i32>>>>> = RefCell::new(HashMap::new());
@@ -169,7 +169,7 @@ help: add missing lifetime argument
LL | static e: RefCell<HashMap<i32, Vec<Vec<Qux<'static, 'static, i32>>>>> = RefCell::new(HashMap::new());
| +++++++++
-error[E0107]: this union takes 2 lifetime arguments but 1 lifetime argument was supplied
+error[E0107]: union takes 2 lifetime arguments but 1 lifetime argument was supplied
--> $DIR/missing-lifetime-specifier.rs:39:44
|
LL | static e: RefCell<HashMap<i32, Vec<Vec<Qux<'static, i32>>>>> = RefCell::new(HashMap::new());
@@ -187,7 +187,7 @@ help: add missing lifetime argument
LL | static e: RefCell<HashMap<i32, Vec<Vec<Qux<'static, 'static, i32>>>>> = RefCell::new(HashMap::new());
| +++++++++
-error[E0107]: this union takes 2 lifetime arguments but 1 lifetime argument was supplied
+error[E0107]: union takes 2 lifetime arguments but 1 lifetime argument was supplied
--> $DIR/missing-lifetime-specifier.rs:39:44
|
LL | static e: RefCell<HashMap<i32, Vec<Vec<Qux<'static, i32>>>>> = RefCell::new(HashMap::new());
@@ -205,7 +205,7 @@ help: add missing lifetime argument
LL | static e: RefCell<HashMap<i32, Vec<Vec<Qux<'static, 'static, i32>>>>> = RefCell::new(HashMap::new());
| +++++++++
-error[E0107]: this union takes 2 lifetime arguments but 1 lifetime argument was supplied
+error[E0107]: union takes 2 lifetime arguments but 1 lifetime argument was supplied
--> $DIR/missing-lifetime-specifier.rs:39:44
|
LL | static e: RefCell<HashMap<i32, Vec<Vec<Qux<'static, i32>>>>> = RefCell::new(HashMap::new());
@@ -223,7 +223,7 @@ help: add missing lifetime argument
LL | static e: RefCell<HashMap<i32, Vec<Vec<Qux<'static, 'static, i32>>>>> = RefCell::new(HashMap::new());
| +++++++++
-error[E0107]: this trait takes 2 lifetime arguments but 1 lifetime argument was supplied
+error[E0107]: trait takes 2 lifetime arguments but 1 lifetime argument was supplied
--> $DIR/missing-lifetime-specifier.rs:47:45
|
LL | static f: RefCell<HashMap<i32, Vec<Vec<&Tar<'static, i32>>>>> = RefCell::new(HashMap::new());
@@ -241,7 +241,7 @@ help: add missing lifetime argument
LL | static f: RefCell<HashMap<i32, Vec<Vec<&Tar<'static, 'static, i32>>>>> = RefCell::new(HashMap::new());
| +++++++++
-error[E0107]: this trait takes 2 lifetime arguments but 1 lifetime argument was supplied
+error[E0107]: trait takes 2 lifetime arguments but 1 lifetime argument was supplied
--> $DIR/missing-lifetime-specifier.rs:47:45
|
LL | static f: RefCell<HashMap<i32, Vec<Vec<&Tar<'static, i32>>>>> = RefCell::new(HashMap::new());
@@ -259,7 +259,7 @@ help: add missing lifetime argument
LL | static f: RefCell<HashMap<i32, Vec<Vec<&Tar<'static, 'static, i32>>>>> = RefCell::new(HashMap::new());
| +++++++++
-error[E0107]: this trait takes 2 lifetime arguments but 1 lifetime argument was supplied
+error[E0107]: trait takes 2 lifetime arguments but 1 lifetime argument was supplied
--> $DIR/missing-lifetime-specifier.rs:47:45
|
LL | static f: RefCell<HashMap<i32, Vec<Vec<&Tar<'static, i32>>>>> = RefCell::new(HashMap::new());
@@ -277,7 +277,7 @@ help: add missing lifetime argument
LL | static f: RefCell<HashMap<i32, Vec<Vec<&Tar<'static, 'static, i32>>>>> = RefCell::new(HashMap::new());
| +++++++++
-error[E0107]: this trait takes 2 lifetime arguments but 1 lifetime argument was supplied
+error[E0107]: trait takes 2 lifetime arguments but 1 lifetime argument was supplied
--> $DIR/missing-lifetime-specifier.rs:47:45
|
LL | static f: RefCell<HashMap<i32, Vec<Vec<&Tar<'static, i32>>>>> = RefCell::new(HashMap::new());
@@ -295,7 +295,7 @@ help: add missing lifetime argument
LL | static f: RefCell<HashMap<i32, Vec<Vec<&Tar<'static, 'static, i32>>>>> = RefCell::new(HashMap::new());
| +++++++++
-error[E0107]: this trait takes 2 lifetime arguments but 1 lifetime argument was supplied
+error[E0107]: trait takes 2 lifetime arguments but 1 lifetime argument was supplied
--> $DIR/missing-lifetime-specifier.rs:47:45
|
LL | static f: RefCell<HashMap<i32, Vec<Vec<&Tar<'static, i32>>>>> = RefCell::new(HashMap::new());
diff --git a/tests/ui/suggestions/missing-type-param-used-in-param.stderr b/tests/ui/suggestions/missing-type-param-used-in-param.stderr
index 4f7058a64..3116c5a0a 100644
--- a/tests/ui/suggestions/missing-type-param-used-in-param.stderr
+++ b/tests/ui/suggestions/missing-type-param-used-in-param.stderr
@@ -1,4 +1,4 @@
-error[E0107]: this function takes 2 generic arguments but 1 generic argument was supplied
+error[E0107]: 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::<String>(100);
diff --git a/tests/ui/suggestions/move-generic-to-trait-in-method-with-params.rs b/tests/ui/suggestions/move-generic-to-trait-in-method-with-params.rs
index 2f540060a..4066cd3b1 100644
--- a/tests/ui/suggestions/move-generic-to-trait-in-method-with-params.rs
+++ b/tests/ui/suggestions/move-generic-to-trait-in-method-with-params.rs
@@ -12,7 +12,7 @@ impl Foo<i32> for i32 {
fn main() {
1.bar::<i32>(0);
- //~^ ERROR this associated function takes 0 generic arguments but 1 generic argument was supplied
+ //~^ ERROR method takes 0 generic arguments but 1 generic argument was supplied
//~| HELP consider moving this generic argument to the `Foo` trait, which takes up to 1 argument
//~| HELP remove these generics
}
diff --git a/tests/ui/suggestions/move-generic-to-trait-in-method-with-params.stderr b/tests/ui/suggestions/move-generic-to-trait-in-method-with-params.stderr
index 9557220f6..bfdb35947 100644
--- a/tests/ui/suggestions/move-generic-to-trait-in-method-with-params.stderr
+++ b/tests/ui/suggestions/move-generic-to-trait-in-method-with-params.stderr
@@ -1,10 +1,10 @@
-error[E0107]: this associated function takes 0 generic arguments but 1 generic argument was supplied
+error[E0107]: method takes 0 generic arguments but 1 generic argument was supplied
--> $DIR/move-generic-to-trait-in-method-with-params.rs:14:7
|
LL | 1.bar::<i32>(0);
| ^^^ expected 0 generic arguments
|
-note: associated function defined here, with 0 generic parameters
+note: method defined here, with 0 generic parameters
--> $DIR/move-generic-to-trait-in-method-with-params.rs:4:8
|
LL | fn bar(&self, _: T);
diff --git a/tests/ui/suggestions/mut-ref-reassignment.stderr b/tests/ui/suggestions/mut-ref-reassignment.stderr
index b3cb6dd06..b86a04c7c 100644
--- a/tests/ui/suggestions/mut-ref-reassignment.stderr
+++ b/tests/ui/suggestions/mut-ref-reassignment.stderr
@@ -4,7 +4,7 @@ error[E0308]: mismatched types
LL | fn suggestion(opt: &mut Option<String>) {
| ------------------- expected due to this parameter type
LL | opt = None;
- | ^^^^ expected mutable reference, found enum `Option`
+ | ^^^^ expected `&mut Option<String>`, found `Option<_>`
|
= note: expected mutable reference `&mut Option<String>`
found enum `Option<_>`
@@ -19,7 +19,7 @@ error[E0308]: mismatched types
LL | fn no_suggestion(opt: &mut Result<String, ()>) {
| ----------------------- expected due to this parameter type
LL | opt = None
- | ^^^^ expected mutable reference, found enum `Option`
+ | ^^^^ expected `&mut Result<String, ()>`, found `Option<_>`
|
= note: expected mutable reference `&mut Result<String, ()>`
found enum `Option<_>`
@@ -30,7 +30,7 @@ error[E0308]: mismatched types
LL | fn suggestion2(opt: &mut Option<String>) {
| ------------------- expected due to this parameter type
LL | opt = Some(String::new())
- | ^^^^^^^^^^^^^^^^^^^ expected mutable reference, found enum `Option`
+ | ^^^^^^^^^^^^^^^^^^^ expected `&mut Option<String>`, found `Option<String>`
|
= note: expected mutable reference `&mut Option<String>`
found enum `Option<String>`
@@ -45,7 +45,7 @@ error[E0308]: mismatched types
LL | fn no_suggestion2(opt: &mut Option<String>) {
| ------------------- expected due to this parameter type
LL | opt = Some(42)
- | ^^^^^^^^ expected mutable reference, found enum `Option`
+ | ^^^^^^^^ expected `&mut Option<String>`, found `Option<{integer}>`
|
= note: expected mutable reference `&mut Option<String>`
found enum `Option<{integer}>`
diff --git a/tests/ui/suggestions/opaque-type-error.stderr b/tests/ui/suggestions/opaque-type-error.stderr
index 133ffb058..5c90d3012 100644
--- a/tests/ui/suggestions/opaque-type-error.stderr
+++ b/tests/ui/suggestions/opaque-type-error.stderr
@@ -2,22 +2,20 @@ error[E0308]: `if` and `else` have incompatible types
--> $DIR/opaque-type-error.rs:20:9
|
LL | fn thing_one() -> impl Future<Output = Result<(), ()>> {
- | ------------------------------------ the expected opaque type
+ | ------------------------------------ the expected future
...
LL | fn thing_two() -> impl Future<Output = Result<(), ()>> {
- | ------------------------------------ the found opaque type
+ | ------------------------------------ the found future
...
LL | / if true {
LL | | thing_one()
| | ----------- expected because of this
LL | | } else {
LL | | thing_two()
- | | ^^^^^^^^^^^ expected opaque type, found a different opaque type
+ | | ^^^^^^^^^^^ expected future, found a different future
LL | | }.await
| |_____- `if` and `else` have incompatible types
|
- = note: expected opaque type `impl Future<Output = Result<(), ()>>` (opaque type at <$DIR/opaque-type-error.rs:8:19>)
- found opaque type `impl Future<Output = Result<(), ()>>` (opaque type at <$DIR/opaque-type-error.rs:12:19>)
= note: distinct uses of `impl Trait` result in different opaque types
help: consider `await`ing on both `Future`s
|
diff --git a/tests/ui/suggestions/option-content-move2.stderr b/tests/ui/suggestions/option-content-move2.stderr
index 1d3dff3be..94acda73c 100644
--- a/tests/ui/suggestions/option-content-move2.stderr
+++ b/tests/ui/suggestions/option-content-move2.stderr
@@ -7,7 +7,7 @@ LL | func(|| {
| -- captured by this `FnMut` closure
LL | // Shouldn't suggest `move ||.as_ref()` here
LL | move || {
- | ^^^^^^^ move out of `var` occurs here
+ | ^^^^^^^ `var` is moved here
LL |
LL | var = Some(NotCopyable);
| ---
diff --git a/tests/ui/suggestions/option-to-bool.stderr b/tests/ui/suggestions/option-to-bool.stderr
index 4050c7be8..e042f07da 100644
--- a/tests/ui/suggestions/option-to-bool.stderr
+++ b/tests/ui/suggestions/option-to-bool.stderr
@@ -2,7 +2,7 @@ error[E0308]: mismatched types
--> $DIR/option-to-bool.rs:4:16
|
LL | if true && x {}
- | ---- ^ expected `bool`, found enum `Option`
+ | ---- ^ expected `bool`, found `Option<i32>`
| |
| expected because this is `bool`
|
diff --git a/tests/ui/suggestions/recover-from-semicolon-trailing-item.stderr b/tests/ui/suggestions/recover-from-semicolon-trailing-item.stderr
index 9588eedc9..fee83eb5c 100644
--- a/tests/ui/suggestions/recover-from-semicolon-trailing-item.stderr
+++ b/tests/ui/suggestions/recover-from-semicolon-trailing-item.stderr
@@ -22,7 +22,7 @@ error[E0308]: mismatched types
--> $DIR/recover-from-semicolon-trailing-item.rs:10:20
|
LL | let _: usize = S {};
- | ----- ^^^^ expected `usize`, found struct `S`
+ | ----- ^^^^ expected `usize`, found `S`
| |
| expected due to this
@@ -30,7 +30,7 @@ error[E0308]: mismatched types
--> $DIR/recover-from-semicolon-trailing-item.rs:12:20
|
LL | let _: usize = X {};
- | ----- ^^^^ expected `usize`, found struct `X`
+ | ----- ^^^^ expected `usize`, found `X`
| |
| expected due to this
diff --git a/tests/ui/suggestions/recover-invalid-float-invalid.rs b/tests/ui/suggestions/recover-invalid-float-invalid.rs
new file mode 100644
index 000000000..79430d8c0
--- /dev/null
+++ b/tests/ui/suggestions/recover-invalid-float-invalid.rs
@@ -0,0 +1,24 @@
+// Check that suggestions to add a zero to integers with a preceding dot only appear when the change
+// will result in a valid floating point literal.
+
+fn main() {}
+
+fn a() {
+ _ = .3u32;
+ //~^ ERROR expected expression, found `.`
+}
+
+fn b() {
+ _ = .0b0;
+ //~^ ERROR expected expression, found `.`
+}
+
+fn c() {
+ _ = .0o07;
+ //~^ ERROR expected expression, found `.`
+}
+
+fn d() {
+ _ = .0x0ABC;
+ //~^ ERROR expected expression, found `.`
+}
diff --git a/tests/ui/suggestions/recover-invalid-float-invalid.stderr b/tests/ui/suggestions/recover-invalid-float-invalid.stderr
new file mode 100644
index 000000000..5764afc1a
--- /dev/null
+++ b/tests/ui/suggestions/recover-invalid-float-invalid.stderr
@@ -0,0 +1,26 @@
+error: expected expression, found `.`
+ --> $DIR/recover-invalid-float-invalid.rs:7:9
+ |
+LL | _ = .3u32;
+ | ^ expected expression
+
+error: expected expression, found `.`
+ --> $DIR/recover-invalid-float-invalid.rs:12:9
+ |
+LL | _ = .0b0;
+ | ^ expected expression
+
+error: expected expression, found `.`
+ --> $DIR/recover-invalid-float-invalid.rs:17:9
+ |
+LL | _ = .0o07;
+ | ^ expected expression
+
+error: expected expression, found `.`
+ --> $DIR/recover-invalid-float-invalid.rs:22:9
+ |
+LL | _ = .0x0ABC;
+ | ^ expected expression
+
+error: aborting due to 4 previous errors
+
diff --git a/tests/ui/suggestions/ref-pattern-binding.stderr b/tests/ui/suggestions/ref-pattern-binding.stderr
index 10447ba70..7b1942593 100644
--- a/tests/ui/suggestions/ref-pattern-binding.stderr
+++ b/tests/ui/suggestions/ref-pattern-binding.stderr
@@ -19,8 +19,8 @@ error: cannot move out of value because it is borrowed
LL | let ref _moved @ _from = String::from("foo");
| ----------^^^-----
| | |
- | | value moved into `_from` here
- | value borrowed, by `_moved`, here
+ | | value is moved into `_from` here
+ | value is borrowed by `_moved` here
error: cannot move out of value because it is borrowed
--> $DIR/ref-pattern-binding.rs:15:9
@@ -28,8 +28,8 @@ error: cannot move out of value because it is borrowed
LL | let ref _moved @ S { f } = S { f: String::from("foo") };
| ----------^^^^^^^-^^
| | |
- | | value moved into `f` here
- | value borrowed, by `_moved`, here
+ | | value is moved into `f` here
+ | value is borrowed by `_moved` here
error: borrow of moved value
--> $DIR/ref-pattern-binding.rs:18:9
diff --git a/tests/ui/suggestions/restrict-existing-type-bounds.rs b/tests/ui/suggestions/restrict-existing-type-bounds.rs
new file mode 100644
index 000000000..07712ce0d
--- /dev/null
+++ b/tests/ui/suggestions/restrict-existing-type-bounds.rs
@@ -0,0 +1,30 @@
+pub trait TryAdd<Rhs = Self> {
+ type Error;
+ type Output;
+
+ fn try_add(self, rhs: Rhs) -> Result<Self::Output, Self::Error>;
+}
+
+impl<T: TryAdd> TryAdd for Option<T> {
+ type Error = <T as TryAdd>::Error;
+ type Output = Option<<T as TryAdd>::Output>;
+
+ fn try_add(self, rhs: Self) -> Result<Self::Output, Self::Error> {
+ Ok(self) //~ ERROR mismatched types
+ }
+}
+
+struct Other<A>(A);
+
+struct X;
+
+impl<T: TryAdd<Error = X>> TryAdd for Other<T> {
+ type Error = <T as TryAdd>::Error;
+ type Output = Other<<T as TryAdd>::Output>;
+
+ fn try_add(self, rhs: Self) -> Result<Self::Output, Self::Error> {
+ Ok(self) //~ ERROR mismatched types
+ }
+}
+
+fn main() {}
diff --git a/tests/ui/suggestions/restrict-existing-type-bounds.stderr b/tests/ui/suggestions/restrict-existing-type-bounds.stderr
new file mode 100644
index 000000000..14a244b79
--- /dev/null
+++ b/tests/ui/suggestions/restrict-existing-type-bounds.stderr
@@ -0,0 +1,57 @@
+error[E0308]: mismatched types
+ --> $DIR/restrict-existing-type-bounds.rs:13:12
+ |
+LL | impl<T: TryAdd> TryAdd for Option<T> {
+ | - this type parameter
+...
+LL | Ok(self)
+ | -- ^^^^ expected `Option<<T as TryAdd>::Output>`, found `Option<T>`
+ | |
+ | arguments to this enum variant are incorrect
+ |
+ = note: expected enum `Option<<T as TryAdd>::Output>`
+ found enum `Option<T>`
+help: the type constructed contains `Option<T>` due to the type of the argument passed
+ --> $DIR/restrict-existing-type-bounds.rs:13:9
+ |
+LL | Ok(self)
+ | ^^^----^
+ | |
+ | this argument influences the type of `Ok`
+note: tuple variant defined here
+ --> $SRC_DIR/core/src/result.rs:LL:COL
+help: consider further restricting this bound
+ |
+LL | impl<T: TryAdd<Output = T>> TryAdd for Option<T> {
+ | ++++++++++++
+
+error[E0308]: mismatched types
+ --> $DIR/restrict-existing-type-bounds.rs:26:12
+ |
+LL | impl<T: TryAdd<Error = X>> TryAdd for Other<T> {
+ | - this type parameter
+...
+LL | Ok(self)
+ | -- ^^^^ expected `Other<<T as TryAdd>::Output>`, found `Other<T>`
+ | |
+ | arguments to this enum variant are incorrect
+ |
+ = note: expected struct `Other<<T as TryAdd>::Output>`
+ found struct `Other<T>`
+help: the type constructed contains `Other<T>` due to the type of the argument passed
+ --> $DIR/restrict-existing-type-bounds.rs:26:9
+ |
+LL | Ok(self)
+ | ^^^----^
+ | |
+ | this argument influences the type of `Ok`
+note: tuple variant defined here
+ --> $SRC_DIR/core/src/result.rs:LL:COL
+help: consider further restricting this bound
+ |
+LL | impl<T: TryAdd<Error = X, Output = T>> TryAdd for Other<T> {
+ | ++++++++++++
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/suggestions/return-bindings.stderr b/tests/ui/suggestions/return-bindings.stderr
index c14fb3367..6f906c27b 100644
--- a/tests/ui/suggestions/return-bindings.stderr
+++ b/tests/ui/suggestions/return-bindings.stderr
@@ -18,7 +18,7 @@ LL | let s: String = if let Some(s) = opt_str {
| ______________________________________________^
LL | |
LL | | } else {
- | |_____^ expected struct `String`, found `()`
+ | |_____^ expected `String`, found `()`
|
help: consider returning the local binding `s`
|
@@ -31,7 +31,7 @@ error[E0308]: mismatched types
--> $DIR/return-bindings.rs:14:11
|
LL | fn c() -> Option<i32> {
- | - ^^^^^^^^^^^ expected enum `Option`, found `()`
+ | - ^^^^^^^^^^^ expected `Option<i32>`, found `()`
| |
| implicitly returns `()` as its body has no tail or `return` expression
|
@@ -50,7 +50,7 @@ LL | let s: String = if let Some(s) = opt_str {
| ______________________________________________^
LL | |
LL | | } else {
- | |_____^ expected struct `String`, found `()`
+ | |_____^ expected `String`, found `()`
|
help: consider returning the local binding `s`
|
@@ -67,7 +67,7 @@ LL | let s = if let Some(s) = opt_str {
LL | | } else {
| |_____- expected because of this
LL | String::new()
- | ^^^^^^^^^^^^^ expected `()`, found struct `String`
+ | ^^^^^^^^^^^^^ expected `()`, found `String`
|
help: consider returning the local binding `s`
|
@@ -80,7 +80,7 @@ error[E0308]: mismatched types
--> $DIR/return-bindings.rs:37:20
|
LL | Some(s) => {}
- | ^^ expected struct `String`, found `()`
+ | ^^ expected `String`, found `()`
|
help: consider returning the local binding `s`
|
@@ -95,7 +95,7 @@ LL | let s = match opt_str {
LL | | Some(s) => {}
| | -- this is found to be of type `()`
LL | | None => String::new(),
- | | ^^^^^^^^^^^^^ expected `()`, found struct `String`
+ | | ^^^^^^^^^^^^^ expected `()`, found `String`
LL | |
LL | | };
| |_____- `match` arms have incompatible types
diff --git a/tests/ui/suggestions/shadowed-lplace-method-2.stderr b/tests/ui/suggestions/shadowed-lplace-method-2.stderr
index 94eef15f3..295636098 100644
--- a/tests/ui/suggestions/shadowed-lplace-method-2.stderr
+++ b/tests/ui/suggestions/shadowed-lplace-method-2.stderr
@@ -2,7 +2,7 @@ error[E0308]: mismatched types
--> $DIR/shadowed-lplace-method-2.rs:22:17
|
LL | *x.foo(0) = ();
- | --------- ^^ expected struct `X`, found `()`
+ | --------- ^^ expected `X`, found `()`
| |
| expected due to the type of this binding
|
diff --git a/tests/ui/suggestions/shadowed-lplace-method.stderr b/tests/ui/suggestions/shadowed-lplace-method.stderr
index 91d0d1200..33824c4cb 100644
--- a/tests/ui/suggestions/shadowed-lplace-method.stderr
+++ b/tests/ui/suggestions/shadowed-lplace-method.stderr
@@ -2,7 +2,7 @@ error[E0308]: mismatched types
--> $DIR/shadowed-lplace-method.rs:9:24
|
LL | *rc.borrow_mut() = false;
- | ---------------- ^^^^^ expected struct `Rc`, found `bool`
+ | ---------------- ^^^^^ expected `Rc<RefCell<bool>>`, found `bool`
| |
| expected due to the type of this binding
|
diff --git a/tests/ui/suggestions/sugg-else-for-closure.stderr b/tests/ui/suggestions/sugg-else-for-closure.stderr
index 7f05832bc..09553b93c 100644
--- a/tests/ui/suggestions/sugg-else-for-closure.stderr
+++ b/tests/ui/suggestions/sugg-else-for-closure.stderr
@@ -15,7 +15,7 @@ LL | let _s = y.unwrap_or(|| x.split('.').nth(1).unwrap());
| ^^^^^^^^^^^^-------------------------------^
| |
| this argument influences the return type of `unwrap_or`
-note: associated function defined here
+note: method defined here
--> $SRC_DIR/core/src/option.rs:LL:COL
help: try calling `unwrap_or_else` instead
|
diff --git a/tests/ui/suggestions/suggest-box.stderr b/tests/ui/suggestions/suggest-box.stderr
index 2bdaa4e97..9a4e9fef4 100644
--- a/tests/ui/suggestions/suggest-box.stderr
+++ b/tests/ui/suggestions/suggest-box.stderr
@@ -8,7 +8,7 @@ LL | let _x: Box<dyn Fn() -> Result<(), ()>> = || {
LL | | Err(())?;
LL | | Ok(())
LL | | };
- | |_____^ expected struct `Box`, found closure
+ | |_____^ expected `Box<dyn Fn() -> Result<(), ()>>`, found closure
|
= note: expected struct `Box<dyn Fn() -> Result<(), ()>>`
found closure `[closure@$DIR/suggest-box.rs:4:47: 4:49]`
diff --git a/tests/ui/suggestions/suggest-call-on-pat-mismatch.rs b/tests/ui/suggestions/suggest-call-on-pat-mismatch.rs
new file mode 100644
index 000000000..657dd9c22
--- /dev/null
+++ b/tests/ui/suggestions/suggest-call-on-pat-mismatch.rs
@@ -0,0 +1,16 @@
+enum E {
+ One(i32, i32),
+}
+
+fn main() {
+ let var = E::One;
+ if let E::One(var1, var2) = var {
+ //~^ ERROR mismatched types
+ //~| HELP use parentheses to construct this tuple variant
+ println!("{var1} {var2}");
+ }
+
+ let Some(x) = Some;
+ //~^ ERROR mismatched types
+ //~| HELP use parentheses to construct this tuple variant
+}
diff --git a/tests/ui/suggestions/suggest-call-on-pat-mismatch.stderr b/tests/ui/suggestions/suggest-call-on-pat-mismatch.stderr
new file mode 100644
index 000000000..7338312ba
--- /dev/null
+++ b/tests/ui/suggestions/suggest-call-on-pat-mismatch.stderr
@@ -0,0 +1,33 @@
+error[E0308]: mismatched types
+ --> $DIR/suggest-call-on-pat-mismatch.rs:7:12
+ |
+LL | if let E::One(var1, var2) = var {
+ | ^^^^^^^^^^^^^^^^^^ --- this expression has type `fn(i32, i32) -> E {E::One}`
+ | |
+ | expected enum constructor, found `E`
+ |
+ = note: expected enum constructor `fn(i32, i32) -> E {E::One}`
+ found enum `E`
+help: use parentheses to construct this tuple variant
+ |
+LL | if let E::One(var1, var2) = var(/* i32 */, /* i32 */) {
+ | ++++++++++++++++++++++
+
+error[E0308]: mismatched types
+ --> $DIR/suggest-call-on-pat-mismatch.rs:13:9
+ |
+LL | let Some(x) = Some;
+ | ^^^^^^^ ---- this expression has type `fn(_) -> Option<_> {Option::<_>::Some}`
+ | |
+ | expected enum constructor, found `Option<_>`
+ |
+ = note: expected enum constructor `fn(_) -> Option<_> {Option::<_>::Some}`
+ found enum `Option<_>`
+help: use parentheses to construct this tuple variant
+ |
+LL | let Some(x) = Some(/* value */);
+ | +++++++++++++
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/suggestions/suggest-fn-ptr-for-fn-item-in-fn-ret.fixed b/tests/ui/suggestions/suggest-fn-ptr-for-fn-item-in-fn-ret.fixed
new file mode 100644
index 000000000..abb9ef917
--- /dev/null
+++ b/tests/ui/suggestions/suggest-fn-ptr-for-fn-item-in-fn-ret.fixed
@@ -0,0 +1,12 @@
+// run-rustfix
+
+#![allow(unused)]
+
+struct Wrapper<T>(T);
+
+fn bar() -> Wrapper<fn()> { Wrapper(foo) }
+//~^ ERROR the placeholder `_` is not allowed within types on item signatures for return types
+
+fn foo() {}
+
+fn main() {}
diff --git a/tests/ui/suggestions/suggest-fn-ptr-for-fn-item-in-fn-ret.rs b/tests/ui/suggestions/suggest-fn-ptr-for-fn-item-in-fn-ret.rs
new file mode 100644
index 000000000..d2a79c386
--- /dev/null
+++ b/tests/ui/suggestions/suggest-fn-ptr-for-fn-item-in-fn-ret.rs
@@ -0,0 +1,12 @@
+// run-rustfix
+
+#![allow(unused)]
+
+struct Wrapper<T>(T);
+
+fn bar() -> _ { Wrapper(foo) }
+//~^ ERROR the placeholder `_` is not allowed within types on item signatures for return types
+
+fn foo() {}
+
+fn main() {}
diff --git a/tests/ui/suggestions/suggest-fn-ptr-for-fn-item-in-fn-ret.stderr b/tests/ui/suggestions/suggest-fn-ptr-for-fn-item-in-fn-ret.stderr
new file mode 100644
index 000000000..347a03852
--- /dev/null
+++ b/tests/ui/suggestions/suggest-fn-ptr-for-fn-item-in-fn-ret.stderr
@@ -0,0 +1,12 @@
+error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types
+ --> $DIR/suggest-fn-ptr-for-fn-item-in-fn-ret.rs:7:13
+ |
+LL | fn bar() -> _ { Wrapper(foo) }
+ | ^
+ | |
+ | not allowed in type signatures
+ | help: replace with the correct return type: `Wrapper<fn()>`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0121`.
diff --git a/tests/ui/suggestions/suggest-full-enum-variant-for-local-module.stderr b/tests/ui/suggestions/suggest-full-enum-variant-for-local-module.stderr
index 9b6dba7e9..3fb3047d8 100644
--- a/tests/ui/suggestions/suggest-full-enum-variant-for-local-module.stderr
+++ b/tests/ui/suggestions/suggest-full-enum-variant-for-local-module.stderr
@@ -2,7 +2,7 @@ error[E0308]: mismatched types
--> $DIR/suggest-full-enum-variant-for-local-module.rs:9:28
|
LL | let _: option::O<()> = ();
- | ------------- ^^ expected enum `O`, found `()`
+ | ------------- ^^ expected `O<()>`, found `()`
| |
| expected due to this
|
diff --git a/tests/ui/suggestions/suggest-remove-deref.fixed b/tests/ui/suggestions/suggest-remove-deref.fixed
new file mode 100644
index 000000000..4dc12da03
--- /dev/null
+++ b/tests/ui/suggestions/suggest-remove-deref.fixed
@@ -0,0 +1,28 @@
+// run-rustfix
+
+//issue #106496
+
+struct S;
+
+trait X {}
+impl X for S {}
+
+fn foo<T: X>(_: &T) {}
+fn test_foo() {
+ let hello = &S;
+ foo(hello);
+ //~^ ERROR mismatched types
+}
+
+fn bar(_: &String) {}
+fn test_bar() {
+ let v = String::from("hello");
+ let s = &v;
+ bar(s);
+ //~^ ERROR mismatched types
+}
+
+fn main() {
+ test_foo();
+ test_bar();
+}
diff --git a/tests/ui/suggestions/suggest-remove-deref.rs b/tests/ui/suggestions/suggest-remove-deref.rs
new file mode 100644
index 000000000..c2d385cbd
--- /dev/null
+++ b/tests/ui/suggestions/suggest-remove-deref.rs
@@ -0,0 +1,28 @@
+// run-rustfix
+
+//issue #106496
+
+struct S;
+
+trait X {}
+impl X for S {}
+
+fn foo<T: X>(_: &T) {}
+fn test_foo() {
+ let hello = &S;
+ foo(*hello);
+ //~^ ERROR mismatched types
+}
+
+fn bar(_: &String) {}
+fn test_bar() {
+ let v = String::from("hello");
+ let s = &v;
+ bar(*s);
+ //~^ ERROR mismatched types
+}
+
+fn main() {
+ test_foo();
+ test_bar();
+}
diff --git a/tests/ui/suggestions/suggest-remove-deref.stderr b/tests/ui/suggestions/suggest-remove-deref.stderr
new file mode 100644
index 000000000..4253838eb
--- /dev/null
+++ b/tests/ui/suggestions/suggest-remove-deref.stderr
@@ -0,0 +1,43 @@
+error[E0308]: mismatched types
+ --> $DIR/suggest-remove-deref.rs:13:9
+ |
+LL | foo(*hello);
+ | --- ^^^^^^ expected `&_`, found `S`
+ | |
+ | arguments to this function are incorrect
+ |
+ = note: expected reference `&_`
+ found struct `S`
+note: function defined here
+ --> $DIR/suggest-remove-deref.rs:10:4
+ |
+LL | fn foo<T: X>(_: &T) {}
+ | ^^^ -----
+help: consider removing deref here
+ |
+LL - foo(*hello);
+LL + foo(hello);
+ |
+
+error[E0308]: mismatched types
+ --> $DIR/suggest-remove-deref.rs:21:9
+ |
+LL | bar(*s);
+ | --- ^^ expected `&String`, found `String`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/suggest-remove-deref.rs:17:4
+ |
+LL | fn bar(_: &String) {}
+ | ^^^ ----------
+help: consider removing deref here
+ |
+LL - bar(*s);
+LL + bar(s);
+ |
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/suggestions/suggest-trait-in-ufcs-in-hrtb.rs b/tests/ui/suggestions/suggest-trait-in-ufcs-in-hrtb.rs
new file mode 100644
index 000000000..fbaf41245
--- /dev/null
+++ b/tests/ui/suggestions/suggest-trait-in-ufcs-in-hrtb.rs
@@ -0,0 +1,8 @@
+pub struct Bar<S>(S);
+
+pub trait Foo {}
+
+impl<S> Foo for Bar<S> where for<'a> <&'a S>::Item: Foo {}
+//~^ ERROR ambiguous associated type
+
+fn main() {}
diff --git a/tests/ui/suggestions/suggest-trait-in-ufcs-in-hrtb.stderr b/tests/ui/suggestions/suggest-trait-in-ufcs-in-hrtb.stderr
new file mode 100644
index 000000000..0ca5b9b92
--- /dev/null
+++ b/tests/ui/suggestions/suggest-trait-in-ufcs-in-hrtb.stderr
@@ -0,0 +1,9 @@
+error[E0223]: ambiguous associated type
+ --> $DIR/suggest-trait-in-ufcs-in-hrtb.rs:5:38
+ |
+LL | impl<S> Foo for Bar<S> where for<'a> <&'a S>::Item: Foo {}
+ | ^^^^^^^^^^^^^ help: use the fully-qualified path: `<&'a S as IntoIterator>::Item`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0223`.
diff --git a/tests/ui/suggestions/suggest-using-chars.stderr b/tests/ui/suggestions/suggest-using-chars.stderr
index 99bcfb08a..ba80ec6a2 100644
--- a/tests/ui/suggestions/suggest-using-chars.stderr
+++ b/tests/ui/suggestions/suggest-using-chars.stderr
@@ -2,7 +2,7 @@ error[E0599]: no method named `iter` found for reference `&'static str` in the c
--> $DIR/suggest-using-chars.rs:2:19
|
LL | let _ = "foo".iter();
- | ^^^^ method not found in `&'static str`
+ | ^^^^ method not found in `&str`
|
help: because of the in-memory representation of `&str`, to obtain an `Iterator` over each of its codepoint use method `chars`
|
@@ -13,7 +13,7 @@ error[E0599]: no method named `foo` found for reference `&'static str` in the cu
--> $DIR/suggest-using-chars.rs:3:19
|
LL | let _ = "foo".foo();
- | ^^^ method not found in `&'static str`
+ | ^^^ method not found in `&str`
error[E0599]: no method named `iter` found for struct `String` in the current scope
--> $DIR/suggest-using-chars.rs:4:33
diff --git a/tests/ui/suggestions/trait-hidden-method.rs b/tests/ui/suggestions/trait-hidden-method.rs
new file mode 100644
index 000000000..ae7ef47e1
--- /dev/null
+++ b/tests/ui/suggestions/trait-hidden-method.rs
@@ -0,0 +1,11 @@
+// #107983 - testing that `__iterator_get_unchecked` isn't suggested
+// HELP included so that compiletest errors on the bad suggestion
+pub fn i_can_has_iterator() -> impl Iterator<Item = u32> {
+ //~^ ERROR expected `Box<dyn Iterator>`
+ //~| HELP consider constraining the associated type
+ Box::new(1..=10) as Box<dyn Iterator>
+ //~^ ERROR the value of the associated type `Item`
+ //~| HELP specify the associated type
+}
+
+fn main() {}
diff --git a/tests/ui/suggestions/trait-hidden-method.stderr b/tests/ui/suggestions/trait-hidden-method.stderr
new file mode 100644
index 000000000..a5a65d193
--- /dev/null
+++ b/tests/ui/suggestions/trait-hidden-method.stderr
@@ -0,0 +1,24 @@
+error[E0191]: the value of the associated type `Item` (from trait `Iterator`) must be specified
+ --> $DIR/trait-hidden-method.rs:6:33
+ |
+LL | Box::new(1..=10) as Box<dyn Iterator>
+ | ^^^^^^^^ help: specify the associated type: `Iterator<Item = Type>`
+
+error[E0271]: expected `Box<dyn Iterator>` to be an iterator that yields `u32`, but it yields `<dyn Iterator as Iterator>::Item`
+ --> $DIR/trait-hidden-method.rs:3:32
+ |
+LL | pub fn i_can_has_iterator() -> impl Iterator<Item = u32> {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^ expected associated type, found `u32`
+...
+LL | Box::new(1..=10) as Box<dyn Iterator>
+ | ------------------------------------- return type was inferred to be `Box<dyn Iterator>` here
+ |
+ = note: expected associated type `<dyn Iterator as Iterator>::Item`
+ found type `u32`
+ = help: consider constraining the associated type `<dyn Iterator as Iterator>::Item` to `u32` or calling a method that returns `<dyn Iterator as Iterator>::Item`
+ = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0191, E0271.
+For more information about an error, try `rustc --explain E0191`.
diff --git a/tests/ui/suggestions/trait-with-missing-associated-type-restriction.stderr b/tests/ui/suggestions/trait-with-missing-associated-type-restriction.stderr
index f520d88c6..7deb9a434 100644
--- a/tests/ui/suggestions/trait-with-missing-associated-type-restriction.stderr
+++ b/tests/ui/suggestions/trait-with-missing-associated-type-restriction.stderr
@@ -90,7 +90,7 @@ LL | fn func(&self) -> Self::A;
LL | fn funk(&self, _: Self::A);
LL | fn funq(&self) -> Self::A {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^ consider calling `Trait::funq`
-note: associated function defined here
+note: method defined here
--> $DIR/trait-with-missing-associated-type-restriction.rs:9:8
|
LL | fn funk(&self, _: Self::A);
diff --git a/tests/ui/suggestions/type-ascription-instead-of-path-in-type.stderr b/tests/ui/suggestions/type-ascription-instead-of-path-in-type.stderr
index fcff02e09..4e3180e84 100644
--- a/tests/ui/suggestions/type-ascription-instead-of-path-in-type.stderr
+++ b/tests/ui/suggestions/type-ascription-instead-of-path-in-type.stderr
@@ -18,7 +18,7 @@ LL | let _: Vec<A:B> = A::B;
= note: see issue #52662 <https://github.com/rust-lang/rust/issues/52662> for more information
= help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable
-error[E0107]: this struct takes at least 1 generic argument but 0 generic arguments were supplied
+error[E0107]: struct takes at least 1 generic argument but 0 generic arguments were supplied
--> $DIR/type-ascription-instead-of-path-in-type.rs:6:12
|
LL | let _: Vec<A:B> = A::B;
diff --git a/tests/ui/suggestions/type-mismatch-byte-literal.rs b/tests/ui/suggestions/type-mismatch-byte-literal.rs
index 34199f8c3..80cd2ca7d 100644
--- a/tests/ui/suggestions/type-mismatch-byte-literal.rs
+++ b/tests/ui/suggestions/type-mismatch-byte-literal.rs
@@ -12,7 +12,19 @@ fn main() {
//~^ ERROR: mismatched types [E0308]
//~| HELP: if you meant to write a byte literal, prefix with `b`
+ let _a: u8 = '\x20';
+ //~^ ERROR: mismatched types [E0308]
+ //~| HELP: if you meant to write a byte literal, prefix with `b`
+
+ // Do not issue the suggestion if the char literal is a Unicode escape
+ foo('\u{0080}');
+ //~^ ERROR: mismatched types [E0308]
+
// Do not issue the suggestion if the char literal isn't ASCII
let _t: u8 = '€';
//~^ ERROR: mismatched types [E0308]
+
+ // Do not issue the suggestion if the char literal isn't ASCII
+ foo('\u{1f980}');
+ //~^ ERROR: mismatched types [E0308]
}
diff --git a/tests/ui/suggestions/type-mismatch-byte-literal.stderr b/tests/ui/suggestions/type-mismatch-byte-literal.stderr
index c9c2e7498..3d27149f0 100644
--- a/tests/ui/suggestions/type-mismatch-byte-literal.stderr
+++ b/tests/ui/suggestions/type-mismatch-byte-literal.stderr
@@ -30,13 +30,54 @@ LL | foo(b'#');
| ~~~~
error[E0308]: mismatched types
- --> $DIR/type-mismatch-byte-literal.rs:16:18
+ --> $DIR/type-mismatch-byte-literal.rs:15:18
+ |
+LL | let _a: u8 = '\x20';
+ | -- ^^^^^^ expected `u8`, found `char`
+ | |
+ | expected due to this
+ |
+help: if you meant to write a byte literal, prefix with `b`
+ |
+LL | let _a: u8 = b'\x20';
+ | ~~~~~~~
+
+error[E0308]: mismatched types
+ --> $DIR/type-mismatch-byte-literal.rs:20:9
+ |
+LL | foo('\u{0080}');
+ | --- ^^^^^^^^^^ expected `u8`, found `char`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/type-mismatch-byte-literal.rs:4:4
+ |
+LL | fn foo(_t: u8) {}
+ | ^^^ ------
+
+error[E0308]: mismatched types
+ --> $DIR/type-mismatch-byte-literal.rs:24:18
|
LL | let _t: u8 = '€';
| -- ^^^ expected `u8`, found `char`
| |
| expected due to this
-error: aborting due to 3 previous errors
+error[E0308]: mismatched types
+ --> $DIR/type-mismatch-byte-literal.rs:28:9
+ |
+LL | foo('\u{1f980}');
+ | --- ^^^^^^^^^^^ expected `u8`, found `char`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/type-mismatch-byte-literal.rs:4:4
+ |
+LL | fn foo(_t: u8) {}
+ | ^^^ ------
+
+error: aborting due to 6 previous errors
For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/suggestions/unnecessary_dot_for_floating_point_literal.stderr b/tests/ui/suggestions/unnecessary_dot_for_floating_point_literal.stderr
index 34eaa8322..8b48ee9f1 100644
--- a/tests/ui/suggestions/unnecessary_dot_for_floating_point_literal.stderr
+++ b/tests/ui/suggestions/unnecessary_dot_for_floating_point_literal.stderr
@@ -2,7 +2,7 @@ error[E0308]: mismatched types
--> $DIR/unnecessary_dot_for_floating_point_literal.rs:2:18
|
LL | let _: f64 = 0..10;
- | --- ^^^^^ expected `f64`, found struct `Range`
+ | --- ^^^^^ expected `f64`, found `Range<{integer}>`
| |
| expected due to this
|
@@ -17,7 +17,7 @@ error[E0308]: mismatched types
--> $DIR/unnecessary_dot_for_floating_point_literal.rs:3:18
|
LL | let _: f64 = 1..;
- | --- ^^^ expected `f64`, found struct `RangeFrom`
+ | --- ^^^ expected `f64`, found `RangeFrom<{integer}>`
| |
| expected due to this
|
@@ -32,7 +32,7 @@ error[E0308]: mismatched types
--> $DIR/unnecessary_dot_for_floating_point_literal.rs:4:18
|
LL | let _: f64 = ..10;
- | --- ^^^^ expected `f64`, found struct `RangeTo`
+ | --- ^^^^ expected `f64`, found `RangeTo<{integer}>`
| |
| expected due to this
|
@@ -47,7 +47,7 @@ error[E0308]: mismatched types
--> $DIR/unnecessary_dot_for_floating_point_literal.rs:5:18
|
LL | let _: f64 = std::ops::Range { start: 0, end: 1 };
- | --- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `f64`, found struct `Range`
+ | --- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `f64`, found `Range<{integer}>`
| |
| expected due to this
|
diff --git a/tests/ui/suggestions/use-type-argument-instead-of-assoc-type.rs b/tests/ui/suggestions/use-type-argument-instead-of-assoc-type.rs
index 8b6e8cfd7..ed262fd39 100644
--- a/tests/ui/suggestions/use-type-argument-instead-of-assoc-type.rs
+++ b/tests/ui/suggestions/use-type-argument-instead-of-assoc-type.rs
@@ -6,7 +6,7 @@ pub trait T<X, Y> {
pub struct Foo {
i: Box<dyn T<usize, usize, usize, usize, B=usize>>,
//~^ ERROR must be specified
- //~| ERROR this trait takes 2 generic arguments but 4 generic arguments were supplied
+ //~| ERROR trait takes 2 generic arguments but 4 generic arguments were supplied
}
diff --git a/tests/ui/suggestions/use-type-argument-instead-of-assoc-type.stderr b/tests/ui/suggestions/use-type-argument-instead-of-assoc-type.stderr
index 75b919232..175a5fbba 100644
--- a/tests/ui/suggestions/use-type-argument-instead-of-assoc-type.stderr
+++ b/tests/ui/suggestions/use-type-argument-instead-of-assoc-type.stderr
@@ -1,4 +1,4 @@
-error[E0107]: this trait takes 2 generic arguments but 4 generic arguments were supplied
+error[E0107]: trait takes 2 generic arguments but 4 generic arguments were supplied
--> $DIR/use-type-argument-instead-of-assoc-type.rs:7:16
|
LL | i: Box<dyn T<usize, usize, usize, usize, B=usize>>,
diff --git a/tests/ui/suppressed-error.rs b/tests/ui/suppressed-error.rs
index 256ec1713..1e39be460 100644
--- a/tests/ui/suppressed-error.rs
+++ b/tests/ui/suppressed-error.rs
@@ -3,6 +3,6 @@ fn main() {
//~^ ERROR mismatched types
//~| expected unit type `()`
//~| found tuple `(_, _)`
-//~| expected `()`, found tuple
+//~| expected `()`, found
return x;
}
diff --git a/tests/ui/suppressed-error.stderr b/tests/ui/suppressed-error.stderr
index c2874ae9a..11d70f8a4 100644
--- a/tests/ui/suppressed-error.stderr
+++ b/tests/ui/suppressed-error.stderr
@@ -4,7 +4,7 @@ error[E0308]: mismatched types
LL | let (x, y) = ();
| ^^^^^^ -- this expression has type `()`
| |
- | expected `()`, found tuple
+ | expected `()`, found `(_, _)`
|
= note: expected unit type `()`
found tuple `(_, _)`
diff --git a/tests/ui/switched-expectations.stderr b/tests/ui/switched-expectations.stderr
index 82fea0f14..744d8483b 100644
--- a/tests/ui/switched-expectations.stderr
+++ b/tests/ui/switched-expectations.stderr
@@ -2,7 +2,7 @@ error[E0308]: mismatched types
--> $DIR/switched-expectations.rs:3:30
|
LL | let ref string: String = var;
- | ^^^ expected struct `String`, found `i32`
+ | ^^^ expected `String`, found `i32`
error: aborting due to previous error
diff --git a/tests/ui/symbol-names/basic.legacy.stderr b/tests/ui/symbol-names/basic.legacy.stderr
index 3ad4ed24c..fe490a600 100644
--- a/tests/ui/symbol-names/basic.legacy.stderr
+++ b/tests/ui/symbol-names/basic.legacy.stderr
@@ -1,10 +1,10 @@
-error: symbol-name(_ZN5basic4main17hcbad207c0eeb0b3bE)
+error: symbol-name(_ZN5basic4main17he9f658e438f1cac0E)
--> $DIR/basic.rs:8:1
|
LL | #[rustc_symbol_name]
| ^^^^^^^^^^^^^^^^^^^^
-error: demangling(basic::main::hcbad207c0eeb0b3b)
+error: demangling(basic::main::he9f658e438f1cac0)
--> $DIR/basic.rs:8:1
|
LL | #[rustc_symbol_name]
diff --git a/tests/ui/symbol-names/issue-60925.legacy.stderr b/tests/ui/symbol-names/issue-60925.legacy.stderr
index 21bf21ee7..29b42f48d 100644
--- a/tests/ui/symbol-names/issue-60925.legacy.stderr
+++ b/tests/ui/symbol-names/issue-60925.legacy.stderr
@@ -1,10 +1,10 @@
-error: symbol-name(_ZN11issue_609253foo37Foo$LT$issue_60925..llv$u6d$..Foo$GT$3foo17h2f2efcf580c9b1eeE)
+error: symbol-name(_ZN11issue_609253foo37Foo$LT$issue_60925..llv$u6d$..Foo$GT$3foo17h13209029be24b923E)
--> $DIR/issue-60925.rs:21:9
|
LL | #[rustc_symbol_name]
| ^^^^^^^^^^^^^^^^^^^^
-error: demangling(issue_60925::foo::Foo<issue_60925::llvm::Foo>::foo::h2f2efcf580c9b1ee)
+error: demangling(issue_60925::foo::Foo<issue_60925::llvm::Foo>::foo::h13209029be24b923)
--> $DIR/issue-60925.rs:21:9
|
LL | #[rustc_symbol_name]
diff --git a/tests/ui/mutexguard-sync.rs b/tests/ui/sync/mutexguard-sync.rs
index b56418383..b56418383 100644
--- a/tests/ui/mutexguard-sync.rs
+++ b/tests/ui/sync/mutexguard-sync.rs
diff --git a/tests/ui/mutexguard-sync.stderr b/tests/ui/sync/mutexguard-sync.stderr
index 3fbb2ddf1..4dc557119 100644
--- a/tests/ui/mutexguard-sync.stderr
+++ b/tests/ui/sync/mutexguard-sync.stderr
@@ -7,6 +7,7 @@ LL | test_sync(guard);
| required by a bound introduced by this call
|
= help: the trait `Sync` is not implemented for `Cell<i32>`
+ = note: if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` or `std::sync::atomic::AtomicI32` instead
= note: required for `MutexGuard<'_, Cell<i32>>` to implement `Sync`
note: required by a bound in `test_sync`
--> $DIR/mutexguard-sync.rs:5:17
diff --git a/tests/ui/sync/suggest-cell.rs b/tests/ui/sync/suggest-cell.rs
new file mode 100644
index 000000000..3284eae7b
--- /dev/null
+++ b/tests/ui/sync/suggest-cell.rs
@@ -0,0 +1,31 @@
+fn require_sync<T: Sync>() {}
+//~^ NOTE required by this bound in `require_sync`
+//~| NOTE required by this bound in `require_sync`
+//~| NOTE required by this bound in `require_sync`
+//~| NOTE required by this bound in `require_sync`
+//~| NOTE required by a bound in `require_sync`
+//~| NOTE required by a bound in `require_sync`
+//~| NOTE required by a bound in `require_sync`
+//~| NOTE required by a bound in `require_sync`
+
+fn main() {
+ require_sync::<std::cell::Cell<()>>();
+ //~^ ERROR `Cell<()>` cannot be shared between threads safely
+ //~| NOTE `Cell<()>` cannot be shared between threads safely
+ //~| NOTE if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock`
+
+ require_sync::<std::cell::Cell<u8>>();
+ //~^ ERROR `Cell<u8>` cannot be shared between threads safely
+ //~| NOTE `Cell<u8>` cannot be shared between threads safely
+ //~| NOTE if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` or `std::sync::atomic::AtomicU8` instead
+
+ require_sync::<std::cell::Cell<i32>>();
+ //~^ ERROR `Cell<i32>` cannot be shared between threads safely
+ //~| NOTE `Cell<i32>` cannot be shared between threads safely
+ //~| NOTE if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` or `std::sync::atomic::AtomicI32` instead
+
+ require_sync::<std::cell::Cell<bool>>();
+ //~^ ERROR `Cell<bool>` cannot be shared between threads safely
+ //~| NOTE `Cell<bool>` cannot be shared between threads safely
+ //~| NOTE if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` or `std::sync::atomic::AtomicBool` instead
+}
diff --git a/tests/ui/sync/suggest-cell.stderr b/tests/ui/sync/suggest-cell.stderr
new file mode 100644
index 000000000..c232c1ccd
--- /dev/null
+++ b/tests/ui/sync/suggest-cell.stderr
@@ -0,0 +1,59 @@
+error[E0277]: `Cell<()>` cannot be shared between threads safely
+ --> $DIR/suggest-cell.rs:12:20
+ |
+LL | require_sync::<std::cell::Cell<()>>();
+ | ^^^^^^^^^^^^^^^^^^^ `Cell<()>` cannot be shared between threads safely
+ |
+ = help: the trait `Sync` is not implemented for `Cell<()>`
+ = note: if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock`
+note: required by a bound in `require_sync`
+ --> $DIR/suggest-cell.rs:1:20
+ |
+LL | fn require_sync<T: Sync>() {}
+ | ^^^^ required by this bound in `require_sync`
+
+error[E0277]: `Cell<u8>` cannot be shared between threads safely
+ --> $DIR/suggest-cell.rs:17:20
+ |
+LL | require_sync::<std::cell::Cell<u8>>();
+ | ^^^^^^^^^^^^^^^^^^^ `Cell<u8>` cannot be shared between threads safely
+ |
+ = help: the trait `Sync` is not implemented for `Cell<u8>`
+ = note: if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` or `std::sync::atomic::AtomicU8` instead
+note: required by a bound in `require_sync`
+ --> $DIR/suggest-cell.rs:1:20
+ |
+LL | fn require_sync<T: Sync>() {}
+ | ^^^^ required by this bound in `require_sync`
+
+error[E0277]: `Cell<i32>` cannot be shared between threads safely
+ --> $DIR/suggest-cell.rs:22:20
+ |
+LL | require_sync::<std::cell::Cell<i32>>();
+ | ^^^^^^^^^^^^^^^^^^^^ `Cell<i32>` cannot be shared between threads safely
+ |
+ = help: the trait `Sync` is not implemented for `Cell<i32>`
+ = note: if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` or `std::sync::atomic::AtomicI32` instead
+note: required by a bound in `require_sync`
+ --> $DIR/suggest-cell.rs:1:20
+ |
+LL | fn require_sync<T: Sync>() {}
+ | ^^^^ required by this bound in `require_sync`
+
+error[E0277]: `Cell<bool>` cannot be shared between threads safely
+ --> $DIR/suggest-cell.rs:27:20
+ |
+LL | require_sync::<std::cell::Cell<bool>>();
+ | ^^^^^^^^^^^^^^^^^^^^^ `Cell<bool>` cannot be shared between threads safely
+ |
+ = help: the trait `Sync` is not implemented for `Cell<bool>`
+ = note: if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` or `std::sync::atomic::AtomicBool` instead
+note: required by a bound in `require_sync`
+ --> $DIR/suggest-cell.rs:1:20
+ |
+LL | fn require_sync<T: Sync>() {}
+ | ^^^^ required by this bound in `require_sync`
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/sync/suggest-once-cell.rs b/tests/ui/sync/suggest-once-cell.rs
new file mode 100644
index 000000000..82fca45b1
--- /dev/null
+++ b/tests/ui/sync/suggest-once-cell.rs
@@ -0,0 +1,12 @@
+#![feature(once_cell)]
+
+fn require_sync<T: Sync>() {}
+//~^ NOTE required by this bound in `require_sync`
+//~| NOTE required by a bound in `require_sync`
+
+fn main() {
+ require_sync::<std::cell::OnceCell<()>>();
+ //~^ ERROR `OnceCell<()>` cannot be shared between threads safely
+ //~| NOTE `OnceCell<()>` cannot be shared between threads safely
+ //~| NOTE use `std::sync::OnceLock` instead
+}
diff --git a/tests/ui/sync/suggest-once-cell.stderr b/tests/ui/sync/suggest-once-cell.stderr
new file mode 100644
index 000000000..fadf05374
--- /dev/null
+++ b/tests/ui/sync/suggest-once-cell.stderr
@@ -0,0 +1,17 @@
+error[E0277]: `OnceCell<()>` cannot be shared between threads safely
+ --> $DIR/suggest-once-cell.rs:8:20
+ |
+LL | require_sync::<std::cell::OnceCell<()>>();
+ | ^^^^^^^^^^^^^^^^^^^^^^^ `OnceCell<()>` cannot be shared between threads safely
+ |
+ = help: the trait `Sync` is not implemented for `OnceCell<()>`
+ = note: if you want to do aliasing and mutation between multiple threads, use `std::sync::OnceLock` instead
+note: required by a bound in `require_sync`
+ --> $DIR/suggest-once-cell.rs:3:20
+ |
+LL | fn require_sync<T: Sync>() {}
+ | ^^^^ required by this bound in `require_sync`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/sync/suggest-ref-cell.rs b/tests/ui/sync/suggest-ref-cell.rs
new file mode 100644
index 000000000..6b972ae09
--- /dev/null
+++ b/tests/ui/sync/suggest-ref-cell.rs
@@ -0,0 +1,12 @@
+#![feature(once_cell)]
+
+fn require_sync<T: Sync>() {}
+//~^ NOTE required by this bound in `require_sync`
+//~| NOTE required by a bound in `require_sync`
+
+fn main() {
+ require_sync::<std::cell::RefCell<()>>();
+ //~^ ERROR `RefCell<()>` cannot be shared between threads safely
+ //~| NOTE `RefCell<()>` cannot be shared between threads safely
+ //~| NOTE use `std::sync::RwLock` instead
+}
diff --git a/tests/ui/sync/suggest-ref-cell.stderr b/tests/ui/sync/suggest-ref-cell.stderr
new file mode 100644
index 000000000..9e8b8fcb4
--- /dev/null
+++ b/tests/ui/sync/suggest-ref-cell.stderr
@@ -0,0 +1,17 @@
+error[E0277]: `RefCell<()>` cannot be shared between threads safely
+ --> $DIR/suggest-ref-cell.rs:8:20
+ |
+LL | require_sync::<std::cell::RefCell<()>>();
+ | ^^^^^^^^^^^^^^^^^^^^^^ `RefCell<()>` cannot be shared between threads safely
+ |
+ = help: the trait `Sync` is not implemented for `RefCell<()>`
+ = note: if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` instead
+note: required by a bound in `require_sync`
+ --> $DIR/suggest-ref-cell.rs:3:20
+ |
+LL | fn require_sync<T: Sync>() {}
+ | ^^^^ required by this bound in `require_sync`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/tag-that-dare-not-speak-its-name.rs b/tests/ui/tag-that-dare-not-speak-its-name.rs
index 36e22f0b5..0e76ec246 100644
--- a/tests/ui/tag-that-dare-not-speak-its-name.rs
+++ b/tests/ui/tag-that-dare-not-speak-its-name.rs
@@ -12,5 +12,5 @@ fn main() {
//~^ ERROR mismatched types
//~| expected type `char`
//~| found enum `Option<_>`
- //~| expected `char`, found enum `Option`
+ //~| expected `char`, found `Option<_>`
}
diff --git a/tests/ui/tag-that-dare-not-speak-its-name.stderr b/tests/ui/tag-that-dare-not-speak-its-name.stderr
index 96bab1526..f53abe53b 100644
--- a/tests/ui/tag-that-dare-not-speak-its-name.stderr
+++ b/tests/ui/tag-that-dare-not-speak-its-name.stderr
@@ -2,7 +2,7 @@ error[E0308]: mismatched types
--> $DIR/tag-that-dare-not-speak-its-name.rs:11:20
|
LL | let x : char = last(y);
- | ---- ^^^^^^^ expected `char`, found enum `Option`
+ | ---- ^^^^^^^ expected `char`, found `Option<_>`
| |
| expected due to this
|
diff --git a/tests/ui/terr-in-field.rs b/tests/ui/terr-in-field.rs
index aa801fd0a..cfe350ef8 100644
--- a/tests/ui/terr-in-field.rs
+++ b/tests/ui/terr-in-field.rs
@@ -11,7 +11,7 @@ struct Bar {
fn want_foo(f: Foo) {}
fn have_bar(b: Bar) {
want_foo(b); //~ ERROR mismatched types
- //~| expected struct `Foo`, found struct `Bar`
+ //~| expected `Foo`, found `Bar`
}
fn main() {}
diff --git a/tests/ui/terr-in-field.stderr b/tests/ui/terr-in-field.stderr
index d2fda09c0..09df4b34b 100644
--- a/tests/ui/terr-in-field.stderr
+++ b/tests/ui/terr-in-field.stderr
@@ -2,7 +2,7 @@ error[E0308]: mismatched types
--> $DIR/terr-in-field.rs:13:14
|
LL | want_foo(b);
- | -------- ^ expected struct `Foo`, found struct `Bar`
+ | -------- ^ expected `Foo`, found `Bar`
| |
| arguments to this function are incorrect
|
diff --git a/tests/ui/terr-sorts.stderr b/tests/ui/terr-sorts.stderr
index 5a61a2fab..8f1975374 100644
--- a/tests/ui/terr-sorts.stderr
+++ b/tests/ui/terr-sorts.stderr
@@ -2,7 +2,7 @@ error[E0308]: mismatched types
--> $DIR/terr-sorts.rs:10:14
|
LL | want_foo(b);
- | -------- ^ expected struct `Foo`, found struct `Box`
+ | -------- ^ expected `Foo`, found `Box<Foo>`
| |
| arguments to this function are incorrect
|
diff --git a/tests/ui/thir-print/thir-flat.rs b/tests/ui/thir-print/thir-flat.rs
new file mode 100644
index 000000000..8fa95ce62
--- /dev/null
+++ b/tests/ui/thir-print/thir-flat.rs
@@ -0,0 +1,4 @@
+// compile-flags: -Z unpretty=thir-flat
+// check-pass
+
+pub fn main() {}
diff --git a/tests/ui/thir-tree.stdout b/tests/ui/thir-print/thir-flat.stdout
index 4b6915f77..910c0da27 100644
--- a/tests/ui/thir-tree.stdout
+++ b/tests/ui/thir-print/thir-flat.stdout
@@ -1,12 +1,15 @@
-DefId(0:3 ~ thir_tree[8f1d]::main):
+DefId(0:3 ~ thir_flat[45a6]::main):
Thir {
+ body_type: Fn(
+ ([]; c_variadic: false)->(),
+ ),
arms: [],
blocks: [
Block {
targeted_by_break: false,
region_scope: Node(1),
opt_destruction_scope: None,
- span: $DIR/thir-tree.rs:4:15: 4:17 (#0),
+ span: $DIR/thir-flat.rs:4:15: 4:17 (#0),
stmts: [],
expr: None,
safety_mode: Safe,
@@ -14,40 +17,40 @@ Thir {
],
exprs: [
Expr {
- ty: (),
- temp_lifetime: Some(
- Node(2),
- ),
- span: $DIR/thir-tree.rs:4:15: 4:17 (#0),
kind: Block {
block: b0,
},
- },
- Expr {
ty: (),
temp_lifetime: Some(
Node(2),
),
- span: $DIR/thir-tree.rs:4:15: 4:17 (#0),
+ span: $DIR/thir-flat.rs:4:15: 4:17 (#0),
+ },
+ Expr {
kind: Scope {
region_scope: Node(2),
lint_level: Explicit(
- HirId(DefId(0:3 ~ thir_tree[8f1d]::main).2),
+ HirId(DefId(0:3 ~ thir_flat[45a6]::main).2),
),
value: e0,
},
- },
- Expr {
ty: (),
temp_lifetime: Some(
Node(2),
),
- span: $DIR/thir-tree.rs:4:15: 4:17 (#0),
+ span: $DIR/thir-flat.rs:4:15: 4:17 (#0),
+ },
+ Expr {
kind: Scope {
region_scope: Destruction(2),
lint_level: Inherited,
value: e1,
},
+ ty: (),
+ temp_lifetime: Some(
+ Node(2),
+ ),
+ span: $DIR/thir-flat.rs:4:15: 4:17 (#0),
},
],
stmts: [],
diff --git a/tests/ui/thir-print/thir-tree-match.rs b/tests/ui/thir-print/thir-tree-match.rs
new file mode 100644
index 000000000..a5511ec95
--- /dev/null
+++ b/tests/ui/thir-print/thir-tree-match.rs
@@ -0,0 +1,23 @@
+// check-pass
+// compile-flags: -Zunpretty=thir-tree
+
+enum Bar {
+ First,
+ Second,
+ Third,
+}
+
+enum Foo {
+ FooOne(Bar),
+ FooTwo,
+}
+
+fn has_match(foo: Foo) -> bool {
+ match foo {
+ Foo::FooOne(Bar::First) => true,
+ Foo::FooOne(_) => false,
+ Foo::FooTwo => true,
+ }
+}
+
+fn main() {}
diff --git a/tests/ui/thir-print/thir-tree-match.stdout b/tests/ui/thir-print/thir-tree-match.stdout
new file mode 100644
index 000000000..d6174ec26
--- /dev/null
+++ b/tests/ui/thir-print/thir-tree-match.stdout
@@ -0,0 +1,342 @@
+DefId(0:16 ~ thir_tree_match[3c9a]::has_match):
+params: [
+ Param {
+ ty: Foo
+ ty_span: Some($DIR/thir-tree-match.rs:15:19: 15:22 (#0))
+ self_kind: None
+ hir_id: Some(HirId(DefId(0:16 ~ thir_tree_match[3c9a]::has_match).1))
+ param: Some(
+ Pat: {
+ ty: Foo
+ span: $DIR/thir-tree-match.rs:15:14: 15:17 (#0)
+ kind: PatKind {
+ Binding {
+ mutability: Not
+ name: "foo"
+ mode: ByValue
+ var: LocalVarId(HirId(DefId(0:16 ~ thir_tree_match[3c9a]::has_match).2))
+ ty: Foo
+ is_primary: true
+ subpattern: None
+ }
+ }
+ }
+ )
+ }
+]
+body:
+ Expr {
+ ty: bool
+ temp_lifetime: Some(Node(26))
+ span: $DIR/thir-tree-match.rs:15:32: 21:2 (#0)
+ kind:
+ Scope {
+ region_scope: Destruction(26)
+ lint_level: Inherited
+ value:
+ Expr {
+ ty: bool
+ temp_lifetime: Some(Node(26))
+ span: $DIR/thir-tree-match.rs:15:32: 21:2 (#0)
+ kind:
+ Scope {
+ region_scope: Node(26)
+ lint_level: Explicit(HirId(DefId(0:16 ~ thir_tree_match[3c9a]::has_match).26))
+ value:
+ Expr {
+ ty: bool
+ temp_lifetime: Some(Node(26))
+ span: $DIR/thir-tree-match.rs:15:32: 21:2 (#0)
+ kind:
+ Block {
+ targeted_by_break: false
+ opt_destruction_scope: None
+ span: $DIR/thir-tree-match.rs:15:32: 21:2 (#0)
+ region_scope: Node(25)
+ safety_mode: Safe
+ stmts: []
+ expr:
+ Expr {
+ ty: bool
+ temp_lifetime: Some(Node(26))
+ span: $DIR/thir-tree-match.rs:16:5: 20:6 (#0)
+ kind:
+ Scope {
+ region_scope: Node(3)
+ lint_level: Explicit(HirId(DefId(0:16 ~ thir_tree_match[3c9a]::has_match).3))
+ value:
+ Expr {
+ ty: bool
+ temp_lifetime: Some(Node(26))
+ span: $DIR/thir-tree-match.rs:16:5: 20:6 (#0)
+ kind:
+ Match {
+ scrutinee:
+ Expr {
+ ty: Foo
+ temp_lifetime: Some(Node(26))
+ span: $DIR/thir-tree-match.rs:16:11: 16:14 (#0)
+ kind:
+ Scope {
+ region_scope: Node(4)
+ lint_level: Explicit(HirId(DefId(0:16 ~ thir_tree_match[3c9a]::has_match).4))
+ value:
+ Expr {
+ ty: Foo
+ temp_lifetime: Some(Node(26))
+ span: $DIR/thir-tree-match.rs:16:11: 16:14 (#0)
+ kind:
+ VarRef {
+ id: LocalVarId(HirId(DefId(0:16 ~ thir_tree_match[3c9a]::has_match).2))
+ }
+ }
+ }
+ }
+ arms: [
+ Arm {
+ pattern:
+ Pat: {
+ ty: Foo
+ span: $DIR/thir-tree-match.rs:17:9: 17:32 (#0)
+ kind: PatKind {
+ Variant {
+ adt_def:
+ AdtDef {
+ did: DefId(0:10 ~ thir_tree_match[3c9a]::Foo)
+ variants: [VariantDef { def_id: DefId(0:11 ~ thir_tree_match[3c9a]::Foo::FooOne), ctor: Some((Fn, DefId(0:12 ~ thir_tree_match[3c9a]::Foo::FooOne::{constructor#0}))), name: "FooOne", discr: Relative(0), fields: [FieldDef { did: DefId(0:13 ~ thir_tree_match[3c9a]::Foo::FooOne::0), name: "0", vis: Restricted(DefId(0:0 ~ thir_tree_match[3c9a])) }], flags: NO_VARIANT_FLAGS }, VariantDef { def_id: DefId(0:14 ~ thir_tree_match[3c9a]::Foo::FooTwo), ctor: Some((Const, DefId(0:15 ~ thir_tree_match[3c9a]::Foo::FooTwo::{constructor#0}))), name: "FooTwo", discr: Relative(1), fields: [], flags: NO_VARIANT_FLAGS }]
+ flags: IS_ENUM
+ repr: ReprOptions { int: None, align: None, pack: None, flags: (empty), field_shuffle_seed: 11573694388057581 }
+ substs: []
+ variant_index: 0
+ subpatterns: [
+ Pat: {
+ ty: Bar
+ span: $DIR/thir-tree-match.rs:17:21: 17:31 (#0)
+ kind: PatKind {
+ Variant {
+ adt_def:
+ AdtDef {
+ did: DefId(0:3 ~ thir_tree_match[3c9a]::Bar)
+ variants: [VariantDef { def_id: DefId(0:4 ~ thir_tree_match[3c9a]::Bar::First), ctor: Some((Const, DefId(0:5 ~ thir_tree_match[3c9a]::Bar::First::{constructor#0}))), name: "First", discr: Relative(0), fields: [], flags: NO_VARIANT_FLAGS }, VariantDef { def_id: DefId(0:6 ~ thir_tree_match[3c9a]::Bar::Second), ctor: Some((Const, DefId(0:7 ~ thir_tree_match[3c9a]::Bar::Second::{constructor#0}))), name: "Second", discr: Relative(1), fields: [], flags: NO_VARIANT_FLAGS }, VariantDef { def_id: DefId(0:8 ~ thir_tree_match[3c9a]::Bar::Third), ctor: Some((Const, DefId(0:9 ~ thir_tree_match[3c9a]::Bar::Third::{constructor#0}))), name: "Third", discr: Relative(2), fields: [], flags: NO_VARIANT_FLAGS }]
+ flags: IS_ENUM
+ repr: ReprOptions { int: None, align: None, pack: None, flags: (empty), field_shuffle_seed: 3125160937860410723 }
+ substs: []
+ variant_index: 0
+ subpatterns: []
+ }
+ }
+ }
+ ]
+ }
+ }
+ }
+ guard: None
+ body:
+ Expr {
+ ty: bool
+ temp_lifetime: Some(Node(13))
+ span: $DIR/thir-tree-match.rs:17:36: 17:40 (#0)
+ kind:
+ Scope {
+ region_scope: Destruction(13)
+ lint_level: Inherited
+ value:
+ Expr {
+ ty: bool
+ temp_lifetime: Some(Node(13))
+ span: $DIR/thir-tree-match.rs:17:36: 17:40 (#0)
+ kind:
+ Scope {
+ region_scope: Node(13)
+ lint_level: Explicit(HirId(DefId(0:16 ~ thir_tree_match[3c9a]::has_match).13))
+ value:
+ Expr {
+ ty: bool
+ temp_lifetime: Some(Node(13))
+ span: $DIR/thir-tree-match.rs:17:36: 17:40 (#0)
+ kind:
+ Literal( lit: Spanned { node: Bool(true), span: $DIR/thir-tree-match.rs:17:36: 17:40 (#0) }, neg: false)
+
+ }
+ }
+ }
+ }
+ }
+ lint_level: Explicit(HirId(DefId(0:16 ~ thir_tree_match[3c9a]::has_match).12))
+ scope: Node(12)
+ span: $DIR/thir-tree-match.rs:17:9: 17:40 (#0)
+ }
+ Arm {
+ pattern:
+ Pat: {
+ ty: Foo
+ span: $DIR/thir-tree-match.rs:18:9: 18:23 (#0)
+ kind: PatKind {
+ Variant {
+ adt_def:
+ AdtDef {
+ did: DefId(0:10 ~ thir_tree_match[3c9a]::Foo)
+ variants: [VariantDef { def_id: DefId(0:11 ~ thir_tree_match[3c9a]::Foo::FooOne), ctor: Some((Fn, DefId(0:12 ~ thir_tree_match[3c9a]::Foo::FooOne::{constructor#0}))), name: "FooOne", discr: Relative(0), fields: [FieldDef { did: DefId(0:13 ~ thir_tree_match[3c9a]::Foo::FooOne::0), name: "0", vis: Restricted(DefId(0:0 ~ thir_tree_match[3c9a])) }], flags: NO_VARIANT_FLAGS }, VariantDef { def_id: DefId(0:14 ~ thir_tree_match[3c9a]::Foo::FooTwo), ctor: Some((Const, DefId(0:15 ~ thir_tree_match[3c9a]::Foo::FooTwo::{constructor#0}))), name: "FooTwo", discr: Relative(1), fields: [], flags: NO_VARIANT_FLAGS }]
+ flags: IS_ENUM
+ repr: ReprOptions { int: None, align: None, pack: None, flags: (empty), field_shuffle_seed: 11573694388057581 }
+ substs: []
+ variant_index: 0
+ subpatterns: [
+ Pat: {
+ ty: Bar
+ span: $DIR/thir-tree-match.rs:18:21: 18:22 (#0)
+ kind: PatKind {
+ Wild
+ }
+ }
+ ]
+ }
+ }
+ }
+ guard: None
+ body:
+ Expr {
+ ty: bool
+ temp_lifetime: Some(Node(19))
+ span: $DIR/thir-tree-match.rs:18:27: 18:32 (#0)
+ kind:
+ Scope {
+ region_scope: Destruction(19)
+ lint_level: Inherited
+ value:
+ Expr {
+ ty: bool
+ temp_lifetime: Some(Node(19))
+ span: $DIR/thir-tree-match.rs:18:27: 18:32 (#0)
+ kind:
+ Scope {
+ region_scope: Node(19)
+ lint_level: Explicit(HirId(DefId(0:16 ~ thir_tree_match[3c9a]::has_match).19))
+ value:
+ Expr {
+ ty: bool
+ temp_lifetime: Some(Node(19))
+ span: $DIR/thir-tree-match.rs:18:27: 18:32 (#0)
+ kind:
+ Literal( lit: Spanned { node: Bool(false), span: $DIR/thir-tree-match.rs:18:27: 18:32 (#0) }, neg: false)
+
+ }
+ }
+ }
+ }
+ }
+ lint_level: Explicit(HirId(DefId(0:16 ~ thir_tree_match[3c9a]::has_match).18))
+ scope: Node(18)
+ span: $DIR/thir-tree-match.rs:18:9: 18:32 (#0)
+ }
+ Arm {
+ pattern:
+ Pat: {
+ ty: Foo
+ span: $DIR/thir-tree-match.rs:19:9: 19:20 (#0)
+ kind: PatKind {
+ Variant {
+ adt_def:
+ AdtDef {
+ did: DefId(0:10 ~ thir_tree_match[3c9a]::Foo)
+ variants: [VariantDef { def_id: DefId(0:11 ~ thir_tree_match[3c9a]::Foo::FooOne), ctor: Some((Fn, DefId(0:12 ~ thir_tree_match[3c9a]::Foo::FooOne::{constructor#0}))), name: "FooOne", discr: Relative(0), fields: [FieldDef { did: DefId(0:13 ~ thir_tree_match[3c9a]::Foo::FooOne::0), name: "0", vis: Restricted(DefId(0:0 ~ thir_tree_match[3c9a])) }], flags: NO_VARIANT_FLAGS }, VariantDef { def_id: DefId(0:14 ~ thir_tree_match[3c9a]::Foo::FooTwo), ctor: Some((Const, DefId(0:15 ~ thir_tree_match[3c9a]::Foo::FooTwo::{constructor#0}))), name: "FooTwo", discr: Relative(1), fields: [], flags: NO_VARIANT_FLAGS }]
+ flags: IS_ENUM
+ repr: ReprOptions { int: None, align: None, pack: None, flags: (empty), field_shuffle_seed: 11573694388057581 }
+ substs: []
+ variant_index: 1
+ subpatterns: []
+ }
+ }
+ }
+ guard: None
+ body:
+ Expr {
+ ty: bool
+ temp_lifetime: Some(Node(24))
+ span: $DIR/thir-tree-match.rs:19:24: 19:28 (#0)
+ kind:
+ Scope {
+ region_scope: Destruction(24)
+ lint_level: Inherited
+ value:
+ Expr {
+ ty: bool
+ temp_lifetime: Some(Node(24))
+ span: $DIR/thir-tree-match.rs:19:24: 19:28 (#0)
+ kind:
+ Scope {
+ region_scope: Node(24)
+ lint_level: Explicit(HirId(DefId(0:16 ~ thir_tree_match[3c9a]::has_match).24))
+ value:
+ Expr {
+ ty: bool
+ temp_lifetime: Some(Node(24))
+ span: $DIR/thir-tree-match.rs:19:24: 19:28 (#0)
+ kind:
+ Literal( lit: Spanned { node: Bool(true), span: $DIR/thir-tree-match.rs:19:24: 19:28 (#0) }, neg: false)
+
+ }
+ }
+ }
+ }
+ }
+ lint_level: Explicit(HirId(DefId(0:16 ~ thir_tree_match[3c9a]::has_match).23))
+ scope: Node(23)
+ span: $DIR/thir-tree-match.rs:19:9: 19:28 (#0)
+ }
+ ]
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+
+DefId(0:17 ~ thir_tree_match[3c9a]::main):
+params: [
+]
+body:
+ Expr {
+ ty: ()
+ temp_lifetime: Some(Node(2))
+ span: $DIR/thir-tree-match.rs:23:11: 23:13 (#0)
+ kind:
+ Scope {
+ region_scope: Destruction(2)
+ lint_level: Inherited
+ value:
+ Expr {
+ ty: ()
+ temp_lifetime: Some(Node(2))
+ span: $DIR/thir-tree-match.rs:23:11: 23:13 (#0)
+ kind:
+ Scope {
+ region_scope: Node(2)
+ lint_level: Explicit(HirId(DefId(0:17 ~ thir_tree_match[3c9a]::main).2))
+ value:
+ Expr {
+ ty: ()
+ temp_lifetime: Some(Node(2))
+ span: $DIR/thir-tree-match.rs:23:11: 23:13 (#0)
+ kind:
+ Block {
+ targeted_by_break: false
+ opt_destruction_scope: None
+ span: $DIR/thir-tree-match.rs:23:11: 23:13 (#0)
+ region_scope: Node(1)
+ safety_mode: Safe
+ stmts: []
+ expr: []
+ }
+ }
+ }
+ }
+ }
+ }
+
+
diff --git a/tests/ui/thir-tree.rs b/tests/ui/thir-print/thir-tree.rs
index 32df7905a..32df7905a 100644
--- a/tests/ui/thir-tree.rs
+++ b/tests/ui/thir-print/thir-tree.rs
diff --git a/tests/ui/thir-print/thir-tree.stdout b/tests/ui/thir-print/thir-tree.stdout
new file mode 100644
index 000000000..0a35d9fb7
--- /dev/null
+++ b/tests/ui/thir-print/thir-tree.stdout
@@ -0,0 +1,43 @@
+DefId(0:3 ~ thir_tree[8f1d]::main):
+params: [
+]
+body:
+ Expr {
+ ty: ()
+ temp_lifetime: Some(Node(2))
+ span: $DIR/thir-tree.rs:4:15: 4:17 (#0)
+ kind:
+ Scope {
+ region_scope: Destruction(2)
+ lint_level: Inherited
+ value:
+ Expr {
+ ty: ()
+ temp_lifetime: Some(Node(2))
+ span: $DIR/thir-tree.rs:4:15: 4:17 (#0)
+ kind:
+ Scope {
+ region_scope: Node(2)
+ lint_level: Explicit(HirId(DefId(0:3 ~ thir_tree[8f1d]::main).2))
+ value:
+ Expr {
+ ty: ()
+ temp_lifetime: Some(Node(2))
+ span: $DIR/thir-tree.rs:4:15: 4:17 (#0)
+ kind:
+ Block {
+ targeted_by_break: false
+ opt_destruction_scope: None
+ span: $DIR/thir-tree.rs:4:15: 4:17 (#0)
+ region_scope: Node(1)
+ safety_mode: Safe
+ stmts: []
+ expr: []
+ }
+ }
+ }
+ }
+ }
+ }
+
+
diff --git a/tests/ui/thread-local/tls.rs b/tests/ui/thread-local/tls.rs
index fbd341388..f03bd3f99 100644
--- a/tests/ui/thread-local/tls.rs
+++ b/tests/ui/thread-local/tls.rs
@@ -1,6 +1,7 @@
// run-pass
// ignore-emscripten no threads support
// compile-flags: -O
+// ignore-nto Doesn't work without emulated TLS enabled (in LLVM)
#![feature(thread_local)]
diff --git a/tests/ui/tool-attributes/auxiliary/p1.rs b/tests/ui/tool-attributes/auxiliary/p1.rs
new file mode 100644
index 000000000..47195c7e9
--- /dev/null
+++ b/tests/ui/tool-attributes/auxiliary/p1.rs
@@ -0,0 +1,3 @@
+#![feature(rustc_attrs)]
+#[rustc_diagnostic_item = "Foo"]
+pub struct Foo {}
diff --git a/tests/ui/tool-attributes/auxiliary/p2.rs b/tests/ui/tool-attributes/auxiliary/p2.rs
new file mode 100644
index 000000000..47195c7e9
--- /dev/null
+++ b/tests/ui/tool-attributes/auxiliary/p2.rs
@@ -0,0 +1,3 @@
+#![feature(rustc_attrs)]
+#[rustc_diagnostic_item = "Foo"]
+pub struct Foo {}
diff --git a/tests/ui/tool-attributes/duplicate-diagnostic.rs b/tests/ui/tool-attributes/duplicate-diagnostic.rs
new file mode 100644
index 000000000..e2cf95087
--- /dev/null
+++ b/tests/ui/tool-attributes/duplicate-diagnostic.rs
@@ -0,0 +1,13 @@
+// aux-build: p1.rs
+// aux-build: p2.rs
+
+// error-pattern: duplicate diagnostic item in crate `p2`
+// error-pattern: note: the diagnostic item is first defined in crate `p1`
+
+#![feature(rustc_attrs)]
+extern crate p1;
+extern crate p2;
+
+#[rustc_diagnostic_item = "Foo"]
+pub struct Foo {} //~ ERROR duplicate diagnostic item in crate `duplicate_diagnostic`: `Foo`
+fn main() {}
diff --git a/tests/ui/tool-attributes/duplicate-diagnostic.stderr b/tests/ui/tool-attributes/duplicate-diagnostic.stderr
new file mode 100644
index 000000000..26bd6a82e
--- /dev/null
+++ b/tests/ui/tool-attributes/duplicate-diagnostic.stderr
@@ -0,0 +1,14 @@
+error: duplicate diagnostic item in crate `p2`: `Foo`.
+ |
+ = note: the diagnostic item is first defined in crate `p1`.
+
+error: duplicate diagnostic item in crate `duplicate_diagnostic`: `Foo`.
+ --> $DIR/duplicate-diagnostic.rs:12:1
+ |
+LL | pub struct Foo {}
+ | ^^^^^^^^^^^^^^
+ |
+ = note: the diagnostic item is first defined in crate `p2`.
+
+error: aborting due to 2 previous errors
+
diff --git a/tests/ui/track-diagnostics/track4.stderr b/tests/ui/track-diagnostics/track4.stderr
index c4668444c..9ebf222ee 100644
--- a/tests/ui/track-diagnostics/track4.stderr
+++ b/tests/ui/track-diagnostics/track4.stderr
@@ -3,7 +3,7 @@ error: missing `struct` for struct definition
|
LL | pub onion {
| ^
--Ztrack-diagnostics: created at compiler/rustc_parse/src/parser/diagnostics.rs:LL:CC
+-Ztrack-diagnostics: created at compiler/rustc_parse/src/parser/item.rs:LL:CC
|
help: add `struct` here to parse `onion` as a public struct
|
diff --git a/tests/ui/traits/alias/ambiguous.stderr b/tests/ui/traits/alias/ambiguous.stderr
index 0fe1a7967..203bdc526 100644
--- a/tests/ui/traits/alias/ambiguous.stderr
+++ b/tests/ui/traits/alias/ambiguous.stderr
@@ -14,11 +14,11 @@ note: candidate #2 is defined in an impl of the trait `B` for the type `u8`
|
LL | fn foo(&self) {}
| ^^^^^^^^^^^^^
-help: disambiguate the associated function for candidate #1
+help: disambiguate the method for candidate #1
|
LL | A::foo(&t);
| ~~~~~~~~~~
-help: disambiguate the associated function for candidate #2
+help: disambiguate the method for candidate #2
|
LL | B::foo(&t);
| ~~~~~~~~~~
diff --git a/tests/ui/traits/alias/issue-107747-do-not-assemble-supertraits.rs b/tests/ui/traits/alias/issue-107747-do-not-assemble-supertraits.rs
new file mode 100644
index 000000000..9b41a8096
--- /dev/null
+++ b/tests/ui/traits/alias/issue-107747-do-not-assemble-supertraits.rs
@@ -0,0 +1,21 @@
+// Regression test for #107747: methods from trait alias supertraits were brought into scope
+//
+// check-pass
+
+#![feature(trait_alias)]
+
+use std::fmt;
+
+trait Foo: fmt::Debug {}
+trait Bar = Foo;
+
+#[derive(Debug)]
+struct Qux(bool);
+
+impl fmt::Display for Qux {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ self.0.fmt(f)
+ }
+}
+
+fn main() {}
diff --git a/tests/ui/traits/alias/issue-108072-unmet-trait-alias-bound.rs b/tests/ui/traits/alias/issue-108072-unmet-trait-alias-bound.rs
new file mode 100644
index 000000000..d254c0ae3
--- /dev/null
+++ b/tests/ui/traits/alias/issue-108072-unmet-trait-alias-bound.rs
@@ -0,0 +1,11 @@
+// Regression test for #108072: do not ICE upon unmet trait alias constraint
+
+#![feature(trait_alias)]
+
+trait IteratorAlias = Iterator;
+
+fn f(_: impl IteratorAlias) {}
+
+fn main() {
+ f(()) //~ `()` is not an iterator
+}
diff --git a/tests/ui/traits/alias/issue-108072-unmet-trait-alias-bound.stderr b/tests/ui/traits/alias/issue-108072-unmet-trait-alias-bound.stderr
new file mode 100644
index 000000000..39f974f96
--- /dev/null
+++ b/tests/ui/traits/alias/issue-108072-unmet-trait-alias-bound.stderr
@@ -0,0 +1,19 @@
+error[E0277]: `()` is not an iterator
+ --> $DIR/issue-108072-unmet-trait-alias-bound.rs:10:7
+ |
+LL | f(())
+ | - ^^ `()` is not an iterator
+ | |
+ | required by a bound introduced by this call
+ |
+ = help: the trait `Iterator` is not implemented for `()`
+ = note: required for `()` to implement `IteratorAlias`
+note: required by a bound in `f`
+ --> $DIR/issue-108072-unmet-trait-alias-bound.rs:7:14
+ |
+LL | fn f(_: impl IteratorAlias) {}
+ | ^^^^^^^^^^^^^ required by this bound in `f`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/traits/alias/issue-108132-unmet-trait-alias-bound-on-generic-impl.rs b/tests/ui/traits/alias/issue-108132-unmet-trait-alias-bound-on-generic-impl.rs
new file mode 100644
index 000000000..0b1f9ab57
--- /dev/null
+++ b/tests/ui/traits/alias/issue-108132-unmet-trait-alias-bound-on-generic-impl.rs
@@ -0,0 +1,15 @@
+// Regression test for #108132: do not ICE upon unmet trait alias constraint in generic impl
+
+#![feature(trait_alias)]
+
+trait IteratorAlias = Iterator;
+
+struct Foo<I>(I);
+
+impl<I: IteratorAlias> Foo<I> {
+ fn f() {}
+}
+
+fn main() {
+ Foo::<()>::f() //~ trait bounds were not satisfied
+}
diff --git a/tests/ui/traits/alias/issue-108132-unmet-trait-alias-bound-on-generic-impl.stderr b/tests/ui/traits/alias/issue-108132-unmet-trait-alias-bound-on-generic-impl.stderr
new file mode 100644
index 000000000..f1b259d5a
--- /dev/null
+++ b/tests/ui/traits/alias/issue-108132-unmet-trait-alias-bound-on-generic-impl.stderr
@@ -0,0 +1,25 @@
+error[E0599]: the function or associated item `f` exists for struct `Foo<()>`, but its trait bounds were not satisfied
+ --> $DIR/issue-108132-unmet-trait-alias-bound-on-generic-impl.rs:14:16
+ |
+LL | struct Foo<I>(I);
+ | ------------- function or associated item `f` not found for this struct
+...
+LL | Foo::<()>::f()
+ | ^ function or associated item cannot be called on `Foo<()>` due to unsatisfied trait bounds
+ |
+note: trait bound `(): Iterator` was not satisfied
+ --> $DIR/issue-108132-unmet-trait-alias-bound-on-generic-impl.rs:5:23
+ |
+LL | trait IteratorAlias = Iterator;
+ | ------------- ^^^^^^^^ unsatisfied trait bound introduced here
+note: trait bound `(): IteratorAlias` was not satisfied
+ --> $DIR/issue-108132-unmet-trait-alias-bound-on-generic-impl.rs:9:9
+ |
+LL | impl<I: IteratorAlias> Foo<I> {
+ | ^^^^^^^^^^^^^ ------
+ | |
+ | unsatisfied trait bound introduced here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0599`.
diff --git a/tests/ui/traits/alias/issue-60755.rs b/tests/ui/traits/alias/issue-60755.rs
new file mode 100644
index 000000000..6b955a752
--- /dev/null
+++ b/tests/ui/traits/alias/issue-60755.rs
@@ -0,0 +1,12 @@
+// check-pass
+
+#![feature(trait_alias)]
+
+struct MyStruct {}
+trait MyFn = Fn(&MyStruct);
+
+fn foo(_: impl MyFn) {}
+
+fn main() {
+ foo(|_| {});
+}
diff --git a/tests/ui/traits/alias/self-in-generics.rs b/tests/ui/traits/alias/self-in-generics.rs
index 0bb6335f9..dcb33b7a9 100644
--- a/tests/ui/traits/alias/self-in-generics.rs
+++ b/tests/ui/traits/alias/self-in-generics.rs
@@ -1,9 +1,5 @@
// astconv uses `FreshTy(0)` as a dummy `Self` type when instanciating trait objects.
// This `FreshTy(0)` can leak into substs, causing ICEs in several places.
-// Using `save-analysis` triggers type-checking `f` that would be normally skipped
-// as `type_of` emitted an error.
-//
-// compile-flags: -Zsave-analysis
#![feature(trait_alias)]
diff --git a/tests/ui/traits/alias/self-in-generics.stderr b/tests/ui/traits/alias/self-in-generics.stderr
index 110d60e6e..80af4e5aa 100644
--- a/tests/ui/traits/alias/self-in-generics.stderr
+++ b/tests/ui/traits/alias/self-in-generics.stderr
@@ -1,5 +1,5 @@
error[E0038]: the trait alias `SelfInput` cannot be made into an object
- --> $DIR/self-in-generics.rs:12:19
+ --> $DIR/self-in-generics.rs:8:19
|
LL | pub fn f(_f: &dyn SelfInput) {}
| ^^^^^^^^^
diff --git a/tests/ui/traits/associated_type_bound/check-trait-object-bounds-3.stderr b/tests/ui/traits/associated_type_bound/check-trait-object-bounds-3.stderr
index ade552c4b..c7af71a42 100644
--- a/tests/ui/traits/associated_type_bound/check-trait-object-bounds-3.stderr
+++ b/tests/ui/traits/associated_type_bound/check-trait-object-bounds-3.stderr
@@ -1,6 +1,8 @@
error[E0597]: `s` does not live long enough
--> $DIR/check-trait-object-bounds-3.rs:15:34
|
+LL | let s = String::from("abcdef");
+ | - binding `s` declared here
LL | z = f::<dyn X<Y = &str>>(&s);
| ---------------------^^-
| | |
diff --git a/tests/ui/traits/coercion-generic-regions.stderr b/tests/ui/traits/coercion-generic-regions.stderr
index 5cfb64901..ae70202ab 100644
--- a/tests/ui/traits/coercion-generic-regions.stderr
+++ b/tests/ui/traits/coercion-generic-regions.stderr
@@ -1,6 +1,8 @@
error[E0597]: `person` does not live long enough
--> $DIR/coercion-generic-regions.rs:17:24
|
+LL | let person = "Fred".to_string();
+ | ------ binding `person` declared here
LL | let person: &str = &person;
| ^^^^^^^
| |
diff --git a/tests/ui/traits/inductive-overflow/supertrait-auto-trait.stderr b/tests/ui/traits/inductive-overflow/supertrait-auto-trait.stderr
index 3ec288d13..dc967d512 100644
--- a/tests/ui/traits/inductive-overflow/supertrait-auto-trait.stderr
+++ b/tests/ui/traits/inductive-overflow/supertrait-auto-trait.stderr
@@ -4,7 +4,7 @@ error[E0568]: auto traits cannot have super traits or lifetime bounds
LL | auto trait Magic: Copy {}
| -----^^^^^^ help: remove the super traits or lifetime bounds
| |
- | auto trait cannot have super traits or lifetime bounds
+ | auto traits cannot have super traits or lifetime bounds
error[E0277]: the trait bound `NoClone: Copy` is not satisfied
--> $DIR/supertrait-auto-trait.rs:16:23
diff --git a/tests/ui/traits/issue-103563.rs b/tests/ui/traits/issue-103563.rs
new file mode 100644
index 000000000..cd3eea09b
--- /dev/null
+++ b/tests/ui/traits/issue-103563.rs
@@ -0,0 +1,75 @@
+// build-pass
+
+fn main() {
+ let mut log_service = LogService { inner: Inner };
+ log_service.call(());
+}
+
+pub trait Service<Request> {
+ type Response;
+
+ fn call(&mut self, req: Request) -> Self::Response;
+}
+
+pub struct LogService<S> {
+ inner: S,
+}
+
+impl<T, U, S> Service<T> for LogService<S>
+where
+ S: Service<T, Response = U>,
+ U: Extension + 'static,
+ for<'a> U::Item<'a>: std::fmt::Debug,
+{
+ type Response = S::Response;
+
+ fn call(&mut self, req: T) -> Self::Response {
+ self.inner.call(req)
+ }
+}
+
+pub struct Inner;
+
+impl Service<()> for Inner {
+ type Response = Resp;
+
+ fn call(&mut self, req: ()) -> Self::Response {
+ Resp::A(req)
+ }
+}
+
+pub trait Extension {
+ type Item<'a>;
+
+ fn touch<F>(self, f: F) -> Self
+ where
+ for<'a> F: Fn(Self::Item<'a>);
+}
+
+pub enum Resp {
+ A(()),
+}
+
+impl Extension for Resp {
+ type Item<'a> = RespItem<'a>;
+ fn touch<F>(self, _f: F) -> Self
+ where
+ for<'a> F: Fn(Self::Item<'a>),
+ {
+ match self {
+ Self::A(a) => Self::A(a),
+ }
+ }
+}
+
+pub enum RespItem<'a> {
+ A(&'a ()),
+}
+
+impl<'a> std::fmt::Debug for RespItem<'a> {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ match self {
+ Self::A(arg0) => f.debug_tuple("A").field(arg0).finish(),
+ }
+ }
+}
diff --git a/tests/ui/traits/issue-52893.stderr b/tests/ui/traits/issue-52893.stderr
index a11867c03..db807a388 100644
--- a/tests/ui/traits/issue-52893.stderr
+++ b/tests/ui/traits/issue-52893.stderr
@@ -5,7 +5,7 @@ LL | impl<F, Name, P> AddClass<Name, F> for Class<P>
| - this type parameter
...
LL | builder.push(output);
- | ---- ^^^^^^ expected type parameter `F`, found struct `Class`
+ | ---- ^^^^^^ expected type parameter `F`, found `Class<P>`
| |
| arguments to this method are incorrect
|
@@ -18,7 +18,7 @@ LL | builder.push(output);
| ^^^^^^^^^^^^^------^
| |
| this argument influences the return type of `push`
-note: associated function defined here
+note: method defined here
--> $DIR/issue-52893.rs:11:8
|
LL | fn push(self, other: T) -> Self::PushRes;
diff --git a/tests/ui/traits/issue-68295.stderr b/tests/ui/traits/issue-68295.stderr
index cb6e6e076..671a97666 100644
--- a/tests/ui/traits/issue-68295.stderr
+++ b/tests/ui/traits/issue-68295.stderr
@@ -5,7 +5,7 @@ LL | fn crash<R, C>(input: Matrix<R, C, ()>) -> Matrix<R, C, u32>
| ----------------- expected `Matrix<R, C, u32>` because of return type
...
LL | input.into_owned()
- | ^^^^^^^^^^^^^^^^^^ expected `u32`, found associated type
+ | ^^^^^^^^^^^^^^^^^^ expected `Matrix<R, C, u32>`, found `Matrix<R, C, ...>`
|
= note: expected struct `Matrix<_, _, u32>`
found struct `Matrix<_, _, <() as Allocator<R, C>>::Buffer>`
diff --git a/tests/ui/traits/issue-77982.stderr b/tests/ui/traits/issue-77982.stderr
index 0b57a8212..d4fea05fe 100644
--- a/tests/ui/traits/issue-77982.stderr
+++ b/tests/ui/traits/issue-77982.stderr
@@ -4,7 +4,7 @@ error[E0283]: type annotations needed
LL | opts.get(opt.as_ref());
| ^^^ ------------ type must be known at this point
| |
- | cannot infer type of the type parameter `Q` declared on the associated function `get`
+ | cannot infer type of the type parameter `Q` declared on the method `get`
|
= note: multiple `impl`s satisfying `String: Borrow<_>` found in the following crates: `alloc`, `core`:
- impl Borrow<str> for String;
@@ -23,7 +23,7 @@ error[E0283]: type annotations needed
LL | opts.get(opt.as_ref());
| ^^^ ------ type must be known at this point
| |
- | cannot infer type of the type parameter `Q` declared on the associated function `get`
+ | cannot infer type of the type parameter `Q` declared on the method `get`
|
= note: multiple `impl`s satisfying `String: AsRef<_>` found in the following crates: `alloc`, `std`:
- impl AsRef<OsStr> for String;
@@ -43,7 +43,7 @@ LL | let ips: Vec<_> = (0..100_000).map(|_| u32::from(0u32.into())).collect(
| |
| required by a bound introduced by this call
|
- = note: multiple `impl`s satisfying `u32: From<_>` found in the following crates: `core`, `std`:
+ = note: multiple `impl`s satisfying `u32: From<_>` found in the `core` crate:
- impl From<Ipv4Addr> for u32;
- impl From<NonZeroU32> for u32;
- impl From<bool> for u32;
diff --git a/tests/ui/traits/item-privacy.rs b/tests/ui/traits/item-privacy.rs
index 38d06b967..a3e1a22e7 100644
--- a/tests/ui/traits/item-privacy.rs
+++ b/tests/ui/traits/item-privacy.rs
@@ -69,7 +69,7 @@ fn check_method() {
S.c(); // OK
// a, b, c are resolved as inherent items, their traits don't need to be in scope
let c = &S as &dyn C;
- c.a(); //~ ERROR associated function `a` is private
+ c.a(); //~ ERROR method `a` is private
c.b(); // OK
c.c(); // OK
@@ -81,7 +81,7 @@ fn check_method() {
//~^ ERROR no function or associated item named `b` found
S::c(&S); // OK
// a, b, c are resolved as inherent items, their traits don't need to be in scope
- <dyn C>::a(&S); //~ ERROR associated function `a` is private
+ <dyn C>::a(&S); //~ ERROR method `a` is private
<dyn C>::b(&S); // OK
C::c(&S); // OK
}
diff --git a/tests/ui/traits/item-privacy.stderr b/tests/ui/traits/item-privacy.stderr
index 293cfbda8..04995b3a1 100644
--- a/tests/ui/traits/item-privacy.stderr
+++ b/tests/ui/traits/item-privacy.stderr
@@ -32,14 +32,14 @@ help: the following trait is implemented but not in scope; perhaps add a `use` f
LL | use method::B;
|
-error[E0624]: associated function `a` is private
+error[E0624]: method `a` is private
--> $DIR/item-privacy.rs:72:7
|
LL | fn a(&self) { }
- | ----------- private associated function defined here
+ | ----------- private method defined here
...
LL | c.a();
- | ^ private associated function
+ | ^ private method
error[E0599]: no function or associated item named `a` found for struct `S` in the current scope
--> $DIR/item-privacy.rs:78:8
@@ -72,14 +72,14 @@ help: the following trait is implemented but not in scope; perhaps add a `use` f
LL | use method::B;
|
-error[E0624]: associated function `a` is private
+error[E0624]: method `a` is private
--> $DIR/item-privacy.rs:84:14
|
LL | fn a(&self) { }
- | ----------- private associated function defined here
+ | ----------- private method defined here
...
LL | <dyn C>::a(&S);
- | ^ private associated function
+ | ^ private method
error[E0599]: no associated item named `A` found for struct `S` in the current scope
--> $DIR/item-privacy.rs:97:8
diff --git a/tests/ui/traits/method-private.stderr b/tests/ui/traits/method-private.stderr
index 8e991ec01..55656f21e 100644
--- a/tests/ui/traits/method-private.stderr
+++ b/tests/ui/traits/method-private.stderr
@@ -1,11 +1,11 @@
-error[E0624]: associated function `method` is private
+error[E0624]: method `method` is private
--> $DIR/method-private.rs:19:9
|
LL | fn method(&self) {}
- | ---------------- private associated function defined here
+ | ---------------- private method defined here
...
LL | foo.method();
- | ^^^^^^ private associated function
+ | ^^^^^^ private method
|
= help: items from traits can only be used if the trait is in scope
help: the following trait is implemented but not in scope; perhaps add a `use` for it:
diff --git a/tests/ui/traits/multidispatch-convert-ambig-dest.stderr b/tests/ui/traits/multidispatch-convert-ambig-dest.stderr
index 6e6172eea..e927f26e9 100644
--- a/tests/ui/traits/multidispatch-convert-ambig-dest.stderr
+++ b/tests/ui/traits/multidispatch-convert-ambig-dest.stderr
@@ -29,7 +29,7 @@ note: required by a bound in `test`
--> $DIR/multidispatch-convert-ambig-dest.rs:21:11
|
LL | fn test<T,U>(_: T, _: U)
- | ---- required by a bound in this
+ | ---- required by a bound in this function
LL | where T : Convert<U>
| ^^^^^^^^^^ required by this bound in `test`
help: consider specifying the generic arguments
diff --git a/tests/ui/traits/negative-impls/negated-auto-traits-error.stderr b/tests/ui/traits/negative-impls/negated-auto-traits-error.stderr
index ce690b749..b680ce7f9 100644
--- a/tests/ui/traits/negative-impls/negated-auto-traits-error.stderr
+++ b/tests/ui/traits/negative-impls/negated-auto-traits-error.stderr
@@ -101,10 +101,10 @@ LL | fn is_send<T: Send>(_: T) {}
| ^^^^ required by this bound in `is_send`
error[E0277]: `main::TestType` cannot be sent between threads safely
- --> $DIR/negated-auto-traits-error.rs:66:13
+ --> $DIR/negated-auto-traits-error.rs:66:20
|
LL | is_sync(Outer2(TestType));
- | ------- ^^^^^^^^^^^^^^^^ `main::TestType` cannot be sent between threads safely
+ | ------- ^^^^^^^^ `main::TestType` cannot be sent between threads safely
| |
| required by a bound introduced by this call
|
diff --git a/tests/ui/traits/negative-impls/no-items.stderr b/tests/ui/traits/negative-impls/no-items.stderr
index 67b94bba1..040d9d145 100644
--- a/tests/ui/traits/negative-impls/no-items.stderr
+++ b/tests/ui/traits/negative-impls/no-items.stderr
@@ -2,7 +2,7 @@ error[E0749]: negative impls cannot have any items
--> $DIR/no-items.rs:8:5
|
LL | type Foo = i32;
- | ^^^^^^^^^^^^^^^
+ | ^^^^^^^^
error: aborting due to previous error
diff --git a/tests/ui/traits/new-solver/alias_eq_cant_be_furthur_normalized.rs b/tests/ui/traits/new-solver/alias_eq_cant_be_furthur_normalized.rs
new file mode 100644
index 000000000..dc726ba51
--- /dev/null
+++ b/tests/ui/traits/new-solver/alias_eq_cant_be_furthur_normalized.rs
@@ -0,0 +1,29 @@
+// check-pass
+// compile-flags: -Ztrait-solver=next
+
+// check that a goal such as `alias-eq(<T as TraitB>::Assoc<bool>, <T as TraitB>::Assoc<?0>)`
+// succeeds with a constraint that `?0 = bool`
+
+// FIXME(deferred_projection_equality): add a test that this is true during coherence
+
+trait TraitA {}
+
+trait TraitB {
+ type Assoc<T: ?Sized>;
+}
+
+impl<T: TraitB> TraitA for (T, T::Assoc<bool>) {}
+
+impl TraitB for i32 {
+ type Assoc<T: ?Sized> = u32;
+}
+
+fn needs_a<T: TraitA>() {}
+
+fn bar<T: TraitB>() {
+ needs_a::<(T, <T as TraitB>::Assoc<_>)>();
+}
+
+fn main() {
+ bar::<i32>();
+}
diff --git a/tests/ui/traits/new-solver/alias_eq_dont_use_normalizes_to_if_substs_eq.rs b/tests/ui/traits/new-solver/alias_eq_dont_use_normalizes_to_if_substs_eq.rs
new file mode 100644
index 000000000..fd5d0e3b1
--- /dev/null
+++ b/tests/ui/traits/new-solver/alias_eq_dont_use_normalizes_to_if_substs_eq.rs
@@ -0,0 +1,45 @@
+// compile-flags: -Ztrait-solver=next
+
+// check that when computing `alias-eq(<() as Foo<u16, T>>::Assoc, <() as Foo<?0, T>>::Assoc)`
+// we do not infer `?0 = u8` via the `for<STOP> (): Foo<u8, STOP>` impl or `?0 = u16` by
+// relating substs as either could be a valid solution.
+
+trait Foo<T, STOP> {
+ type Assoc;
+}
+
+impl<STOP> Foo<u8, STOP> for ()
+where
+ (): Foo<u16, STOP>,
+{
+ type Assoc = <() as Foo<u16, STOP>>::Assoc;
+}
+
+impl Foo<u16, i8> for () {
+ type Assoc = u8;
+}
+
+impl Foo<u16, i16> for () {
+ type Assoc = u16;
+}
+
+fn output<T, U>() -> <() as Foo<T, U>>::Assoc
+where
+ (): Foo<T, U>,
+{
+ todo!()
+}
+
+fn incomplete<T>()
+where
+ (): Foo<u16, T>,
+{
+ // `<() as Foo<u16, STOP>>::Assoc == <() as Foo<_, STOP>>::Assoc`
+ let _: <() as Foo<u16, T>>::Assoc = output::<_, T>();
+ //~^ error: type annotations needed
+
+ // let _: <() as Foo<u16, T>>::Assoc = output::<u8, T>(); // OK
+ // let _: <() as Foo<u16, T>>::Assoc = output::<u16, T>(); // OK
+}
+
+fn main() {}
diff --git a/tests/ui/traits/new-solver/alias_eq_dont_use_normalizes_to_if_substs_eq.stderr b/tests/ui/traits/new-solver/alias_eq_dont_use_normalizes_to_if_substs_eq.stderr
new file mode 100644
index 000000000..a6712332c
--- /dev/null
+++ b/tests/ui/traits/new-solver/alias_eq_dont_use_normalizes_to_if_substs_eq.stderr
@@ -0,0 +1,9 @@
+error[E0282]: type annotations needed
+ --> $DIR/alias_eq_dont_use_normalizes_to_if_substs_eq.rs:38:41
+ |
+LL | let _: <() as Foo<u16, T>>::Assoc = output::<_, T>();
+ | ^^^^^^^^^^^^^^ cannot infer type of the type parameter `T` declared on the function `output`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0282`.
diff --git a/tests/ui/traits/new-solver/alias_eq_simple.rs b/tests/ui/traits/new-solver/alias_eq_simple.rs
new file mode 100644
index 000000000..6792cf3ce
--- /dev/null
+++ b/tests/ui/traits/new-solver/alias_eq_simple.rs
@@ -0,0 +1,22 @@
+// check-pass
+// compile-flags: -Ztrait-solver=next
+
+// test that the new solver can handle `alias-eq(<i32 as TraitB>::Assoc, u32)`
+
+trait TraitA {}
+
+trait TraitB {
+ type Assoc;
+}
+
+impl<T: TraitB> TraitA for (T, T::Assoc) {}
+
+impl TraitB for i32 {
+ type Assoc = u32;
+}
+
+fn needs_a<T: TraitA>() {}
+
+fn main() {
+ needs_a::<(i32, u32)>();
+}
diff --git a/tests/ui/traits/new-solver/alias_eq_substs_eq_not_intercrate.rs b/tests/ui/traits/new-solver/alias_eq_substs_eq_not_intercrate.rs
new file mode 100644
index 000000000..d4cc380fa
--- /dev/null
+++ b/tests/ui/traits/new-solver/alias_eq_substs_eq_not_intercrate.rs
@@ -0,0 +1,20 @@
+// compile-flags: -Ztrait-solver=next
+
+// check that a `alias-eq(<?0 as TraitB>::Assoc, <T as TraitB>::Assoc)` goal fails.
+
+// FIXME(deferred_projection_equality): add a test that this is true during coherence
+
+trait TraitB {
+ type Assoc;
+}
+
+fn needs_a<T: TraitB>() -> T::Assoc {
+ unimplemented!()
+}
+
+fn bar<T: TraitB>() {
+ let _: <_ as TraitB>::Assoc = needs_a::<T>();
+ //~^ error: type annotations needed
+}
+
+fn main() {}
diff --git a/tests/ui/traits/new-solver/alias_eq_substs_eq_not_intercrate.stderr b/tests/ui/traits/new-solver/alias_eq_substs_eq_not_intercrate.stderr
new file mode 100644
index 000000000..d063d8fce
--- /dev/null
+++ b/tests/ui/traits/new-solver/alias_eq_substs_eq_not_intercrate.stderr
@@ -0,0 +1,9 @@
+error[E0282]: type annotations needed
+ --> $DIR/alias_eq_substs_eq_not_intercrate.rs:16:12
+ |
+LL | let _: <_ as TraitB>::Assoc = needs_a::<T>();
+ | ^^^^^^^^^^^^^^^^^^^^ cannot infer type for associated type `<_ as TraitB>::Assoc`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0282`.
diff --git a/tests/ui/traits/new-solver/async.fail.stderr b/tests/ui/traits/new-solver/async.fail.stderr
new file mode 100644
index 000000000..b395c23ae
--- /dev/null
+++ b/tests/ui/traits/new-solver/async.fail.stderr
@@ -0,0 +1,17 @@
+error[E0271]: expected `[async block@$DIR/async.rs:12:17: 12:25]` to be a future that resolves to `i32`, but it resolves to `()`
+ --> $DIR/async.rs:12:17
+ |
+LL | needs_async(async {});
+ | ----------- ^^^^^^^^ expected `i32`, found `()`
+ | |
+ | required by a bound introduced by this call
+ |
+note: required by a bound in `needs_async`
+ --> $DIR/async.rs:8:31
+ |
+LL | fn needs_async(_: impl Future<Output = i32>) {}
+ | ^^^^^^^^^^^^ required by this bound in `needs_async`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0271`.
diff --git a/tests/ui/traits/new-solver/async.rs b/tests/ui/traits/new-solver/async.rs
new file mode 100644
index 000000000..195cc35ca
--- /dev/null
+++ b/tests/ui/traits/new-solver/async.rs
@@ -0,0 +1,19 @@
+// compile-flags: -Ztrait-solver=next
+// edition: 2021
+// revisions: pass fail
+//[pass] check-pass
+
+use std::future::Future;
+
+fn needs_async(_: impl Future<Output = i32>) {}
+
+#[cfg(fail)]
+fn main() {
+ needs_async(async {});
+ //[fail]~^ ERROR to be a future that resolves to `i32`, but it resolves to `()`
+}
+
+#[cfg(pass)]
+fn main() {
+ needs_async(async { 1i32 });
+}
diff --git a/tests/ui/traits/new-solver/builtin-fn-must-return-sized.rs b/tests/ui/traits/new-solver/builtin-fn-must-return-sized.rs
new file mode 100644
index 000000000..ba473653e
--- /dev/null
+++ b/tests/ui/traits/new-solver/builtin-fn-must-return-sized.rs
@@ -0,0 +1,17 @@
+// compile-flags: -Ztrait-solver=next
+
+#![feature(fn_traits)]
+#![feature(unboxed_closures)]
+#![feature(tuple_trait)]
+
+use std::ops::Fn;
+use std::marker::Tuple;
+
+fn foo<F: Fn<T>, T: Tuple>(f: Option<F>, t: T) {
+ let y = (f.unwrap()).call(t);
+}
+
+fn main() {
+ foo::<fn() -> str, _>(None, ());
+ //~^ expected a `Fn<_>` closure, found `fn() -> str`
+}
diff --git a/tests/ui/traits/new-solver/builtin-fn-must-return-sized.stderr b/tests/ui/traits/new-solver/builtin-fn-must-return-sized.stderr
new file mode 100644
index 000000000..f7551739b
--- /dev/null
+++ b/tests/ui/traits/new-solver/builtin-fn-must-return-sized.stderr
@@ -0,0 +1,18 @@
+error[E0277]: expected a `Fn<_>` closure, found `fn() -> str`
+ --> $DIR/builtin-fn-must-return-sized.rs:15:27
+ |
+LL | foo::<fn() -> str, _>(None, ());
+ | --------------------- ^^^^ expected an `Fn<_>` closure, found `fn() -> str`
+ | |
+ | required by a bound introduced by this call
+ |
+ = help: the trait `Fn<_>` is not implemented for `fn() -> str`
+note: required by a bound in `foo`
+ --> $DIR/builtin-fn-must-return-sized.rs:10:11
+ |
+LL | fn foo<F: Fn<T>, T: Tuple>(f: Option<F>, t: T) {
+ | ^^^^^ required by this bound in `foo`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/traits/new-solver/elaborate-item-bounds.rs b/tests/ui/traits/new-solver/elaborate-item-bounds.rs
new file mode 100644
index 000000000..076aefcf8
--- /dev/null
+++ b/tests/ui/traits/new-solver/elaborate-item-bounds.rs
@@ -0,0 +1,12 @@
+// compile-flags: -Ztrait-solver=next
+// check-pass
+
+trait Foo {
+ type Bar: Bar;
+}
+
+trait Bar: Baz {}
+
+trait Baz {}
+
+fn main() {}
diff --git a/tests/ui/traits/new-solver/fn-trait-closure.rs b/tests/ui/traits/new-solver/fn-trait-closure.rs
index c0ecf1c91..bd65737ee 100644
--- a/tests/ui/traits/new-solver/fn-trait-closure.rs
+++ b/tests/ui/traits/new-solver/fn-trait-closure.rs
@@ -1,12 +1,5 @@
// compile-flags: -Ztrait-solver=next
-// known-bug: unknown
-// failure-status: 101
-// dont-check-compiler-stderr
-
-// This test will fail until we fix `FulfillmentCtxt::relationships`. That's
-// because we create a type variable for closure upvar types, which is not
-// constrained until after we try to do fallback on diverging type variables.
-// Thus, we will call that function, which is unimplemented.
+// check-pass
fn require_fn(_: impl Fn() -> i32) {}
diff --git a/tests/ui/traits/new-solver/generator.fail.stderr b/tests/ui/traits/new-solver/generator.fail.stderr
new file mode 100644
index 000000000..d94d41e35
--- /dev/null
+++ b/tests/ui/traits/new-solver/generator.fail.stderr
@@ -0,0 +1,64 @@
+error[E0277]: the trait bound `[generator@$DIR/generator.rs:18:21: 18:23]: Generator<A>` is not satisfied
+ --> $DIR/generator.rs:18:21
+ |
+LL | needs_generator(|| {
+ | _____---------------_^
+ | | |
+ | | required by a bound introduced by this call
+LL | |
+LL | |
+LL | |
+LL | | yield ();
+LL | | });
+ | |_____^ the trait `Generator<A>` is not implemented for `[generator@$DIR/generator.rs:18:21: 18:23]`
+ |
+note: required by a bound in `needs_generator`
+ --> $DIR/generator.rs:14:28
+ |
+LL | fn needs_generator(_: impl Generator<A, Yield = B, Return = C>) {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `needs_generator`
+
+error[E0271]: type mismatch resolving `<[generator@$DIR/generator.rs:18:21: 18:23] as Generator<A>>::Yield == B`
+ --> $DIR/generator.rs:18:21
+ |
+LL | needs_generator(|| {
+ | _____---------------_^
+ | | |
+ | | required by a bound introduced by this call
+LL | |
+LL | |
+LL | |
+LL | | yield ();
+LL | | });
+ | |_____^ types differ
+ |
+note: required by a bound in `needs_generator`
+ --> $DIR/generator.rs:14:41
+ |
+LL | fn needs_generator(_: impl Generator<A, Yield = B, Return = C>) {}
+ | ^^^^^^^^^ required by this bound in `needs_generator`
+
+error[E0271]: type mismatch resolving `<[generator@$DIR/generator.rs:18:21: 18:23] as Generator<A>>::Return == C`
+ --> $DIR/generator.rs:18:21
+ |
+LL | needs_generator(|| {
+ | _____---------------_^
+ | | |
+ | | required by a bound introduced by this call
+LL | |
+LL | |
+LL | |
+LL | | yield ();
+LL | | });
+ | |_____^ types differ
+ |
+note: required by a bound in `needs_generator`
+ --> $DIR/generator.rs:14:52
+ |
+LL | fn needs_generator(_: impl Generator<A, Yield = B, Return = C>) {}
+ | ^^^^^^^^^^ required by this bound in `needs_generator`
+
+error: aborting due to 3 previous errors
+
+Some errors have detailed explanations: E0271, E0277.
+For more information about an error, try `rustc --explain E0271`.
diff --git a/tests/ui/traits/new-solver/generator.rs b/tests/ui/traits/new-solver/generator.rs
new file mode 100644
index 000000000..364373ca8
--- /dev/null
+++ b/tests/ui/traits/new-solver/generator.rs
@@ -0,0 +1,32 @@
+// compile-flags: -Ztrait-solver=next
+// edition: 2021
+// revisions: pass fail
+//[pass] check-pass
+
+#![feature(generator_trait, generators)]
+
+use std::ops::Generator;
+
+struct A;
+struct B;
+struct C;
+
+fn needs_generator(_: impl Generator<A, Yield = B, Return = C>) {}
+
+#[cfg(fail)]
+fn main() {
+ needs_generator(|| {
+ //[fail]~^ ERROR Generator<A>` is not satisfied
+ //[fail]~| ERROR as Generator<A>>::Yield == B`
+ //[fail]~| ERROR as Generator<A>>::Return == C`
+ yield ();
+ });
+}
+
+#[cfg(pass)]
+fn main() {
+ needs_generator(|_: A| {
+ let _: A = yield B;
+ C
+ })
+}
diff --git a/tests/ui/traits/new-solver/higher-ranked-dyn-bounds.rs b/tests/ui/traits/new-solver/higher-ranked-dyn-bounds.rs
new file mode 100644
index 000000000..c886aeeda
--- /dev/null
+++ b/tests/ui/traits/new-solver/higher-ranked-dyn-bounds.rs
@@ -0,0 +1,17 @@
+// compile-flags: -Ztrait-solver=next
+// check-pass
+
+trait Trait<'a> {
+ type Item: for<'b> Trait2<'b>;
+}
+
+trait Trait2<'a> {}
+impl Trait2<'_> for () {}
+
+fn needs_trait(_: Box<impl for<'a> Trait<'a> + ?Sized>) {}
+
+fn foo(x: Box<dyn for<'a> Trait<'a, Item = ()>>) {
+ needs_trait(x);
+}
+
+fn main() {}
diff --git a/tests/ui/traits/new-solver/more-object-bound.rs b/tests/ui/traits/new-solver/more-object-bound.rs
new file mode 100644
index 000000000..712759ef0
--- /dev/null
+++ b/tests/ui/traits/new-solver/more-object-bound.rs
@@ -0,0 +1,27 @@
+// compile-flags: -Ztrait-solver=next
+// From #80800
+
+trait SuperTrait {
+ type A;
+ type B;
+}
+
+trait Trait: SuperTrait<A = <Self as SuperTrait>::B> {}
+
+fn transmute<A, B>(x: A) -> B {
+ foo::<A, B, dyn Trait<A = A, B = B>>(x)
+ //~^ ERROR type annotations needed: cannot satisfy `dyn Trait<A = A, B = B>: Trait`
+}
+
+fn foo<A, B, T: ?Sized>(x: T::A) -> B
+where
+ T: Trait<B = B>,
+{
+ x
+}
+
+static X: u8 = 0;
+fn main() {
+ let x = transmute::<&u8, &[u8; 1_000_000]>(&X);
+ println!("{:?}", x[100_000]);
+}
diff --git a/tests/ui/traits/new-solver/more-object-bound.stderr b/tests/ui/traits/new-solver/more-object-bound.stderr
new file mode 100644
index 000000000..208fdecb0
--- /dev/null
+++ b/tests/ui/traits/new-solver/more-object-bound.stderr
@@ -0,0 +1,19 @@
+error[E0283]: type annotations needed: cannot satisfy `dyn Trait<A = A, B = B>: Trait`
+ --> $DIR/more-object-bound.rs:12:5
+ |
+LL | foo::<A, B, dyn Trait<A = A, B = B>>(x)
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: cannot satisfy `dyn Trait<A = A, B = B>: Trait`
+note: required by a bound in `foo`
+ --> $DIR/more-object-bound.rs:18:8
+ |
+LL | fn foo<A, B, T: ?Sized>(x: T::A) -> B
+ | --- required by a bound in this function
+LL | where
+LL | T: Trait<B = B>,
+ | ^^^^^^^^^^^^ required by this bound in `foo`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0283`.
diff --git a/tests/ui/traits/new-solver/normalizes_to_ignores_unnormalizable_candidate.rs b/tests/ui/traits/new-solver/normalizes_to_ignores_unnormalizable_candidate.rs
new file mode 100644
index 000000000..46343241b
--- /dev/null
+++ b/tests/ui/traits/new-solver/normalizes_to_ignores_unnormalizable_candidate.rs
@@ -0,0 +1,40 @@
+// [no_self_infer] check-pass
+// compile-flags: -Ztrait-solver=next
+// revisions: self_infer no_self_infer
+
+// checks that the new solver is smart enough to infer `?0 = U` when solving:
+// `normalizes-to(<Vec<?0> as Trait>::Assoc, u8)`
+// with `normalizes-to(<Vec<U> as Trait>::Assoc, u8)` in the paramenv even when
+// there is a separate `Vec<T>: Trait` bound in the paramenv.
+//
+// FIXME(-Ztrait-solver=next)
+// This could also compile for `normalizes-to(<?0 as Trait>::Assoc, u8)` but
+// we currently immediately consider a goal ambiguous if the self type is an
+// inference variable.
+
+trait Trait {
+ type Assoc;
+}
+
+fn foo<T: Trait<Assoc = u8>>(x: T) {}
+
+#[cfg(self_infer)]
+fn unconstrained<T>() -> T {
+ todo!()
+}
+
+#[cfg(no_self_infer)]
+fn unconstrained<T>() -> Vec<T> {
+ todo!()
+}
+
+fn bar<T, U>()
+where
+ Vec<T>: Trait,
+ Vec<U>: Trait<Assoc = u8>,
+{
+ foo(unconstrained())
+ //[self_infer]~^ ERROR type annotations needed
+}
+
+fn main() {}
diff --git a/tests/ui/traits/new-solver/normalizes_to_ignores_unnormalizable_candidate.self_infer.stderr b/tests/ui/traits/new-solver/normalizes_to_ignores_unnormalizable_candidate.self_infer.stderr
new file mode 100644
index 000000000..062832012
--- /dev/null
+++ b/tests/ui/traits/new-solver/normalizes_to_ignores_unnormalizable_candidate.self_infer.stderr
@@ -0,0 +1,14 @@
+error[E0282]: type annotations needed
+ --> $DIR/normalizes_to_ignores_unnormalizable_candidate.rs:36:5
+ |
+LL | foo(unconstrained())
+ | ^^^ cannot infer type of the type parameter `T` declared on the function `foo`
+ |
+help: consider specifying the generic argument
+ |
+LL | foo::<T>(unconstrained())
+ | +++++
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0282`.
diff --git a/tests/ui/traits/new-solver/object-unsafety.rs b/tests/ui/traits/new-solver/object-unsafety.rs
new file mode 100644
index 000000000..7bdd863a7
--- /dev/null
+++ b/tests/ui/traits/new-solver/object-unsafety.rs
@@ -0,0 +1,20 @@
+// compile-flags: -Ztrait-solver=next
+
+trait Setup {
+ type From: Copy;
+}
+
+fn copy<U: Setup + ?Sized>(from: &U::From) -> U::From {
+ *from
+}
+
+pub fn copy_any<T>(t: &T) -> T {
+ copy::<dyn Setup<From=T>>(t)
+ //~^ ERROR the trait bound `dyn Setup<From = T>: Setup` is not satisfied
+}
+
+fn main() {
+ let x = String::from("Hello, world");
+ let y = copy_any(&x);
+ println!("{y}");
+}
diff --git a/tests/ui/traits/new-solver/object-unsafety.stderr b/tests/ui/traits/new-solver/object-unsafety.stderr
new file mode 100644
index 000000000..198ac623d
--- /dev/null
+++ b/tests/ui/traits/new-solver/object-unsafety.stderr
@@ -0,0 +1,19 @@
+error[E0277]: the trait bound `dyn Setup<From = T>: Setup` is not satisfied
+ --> $DIR/object-unsafety.rs:12:12
+ |
+LL | copy::<dyn Setup<From=T>>(t)
+ | ^^^^^^^^^^^^^^^^^ the trait `Setup` is not implemented for `dyn Setup<From = T>`
+ |
+note: required by a bound in `copy`
+ --> $DIR/object-unsafety.rs:7:12
+ |
+LL | fn copy<U: Setup + ?Sized>(from: &U::From) -> U::From {
+ | ^^^^^ required by this bound in `copy`
+help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement
+ |
+LL | pub fn copy_any<T>(t: &T) -> T where dyn Setup<From = T>: Setup {
+ | ++++++++++++++++++++++++++++++++
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/traits/new-solver/param-candidate-doesnt-shadow-project.rs b/tests/ui/traits/new-solver/param-candidate-doesnt-shadow-project.rs
new file mode 100644
index 000000000..bdf999ec5
--- /dev/null
+++ b/tests/ui/traits/new-solver/param-candidate-doesnt-shadow-project.rs
@@ -0,0 +1,25 @@
+// compile-flags: -Ztrait-solver=next
+// check-pass
+
+trait Foo {
+ type Assoc;
+}
+
+trait Bar {}
+
+impl<T> Foo for T {
+ type Assoc = i32;
+}
+
+impl<T> Bar for T where T: Foo<Assoc = i32> {}
+
+fn require_bar<T: Bar>() {}
+
+fn foo<T: Foo>() {
+ // Unlike the classic solver, `<T as Foo>::Assoc = _` will still project
+ // down to `i32` even though there's a param-env candidate here, since we
+ // don't assemble any param-env projection candidates for `T: Foo` alone.
+ require_bar::<T>();
+}
+
+fn main() {}
diff --git a/tests/ui/traits/new-solver/pointee.rs b/tests/ui/traits/new-solver/pointee.rs
new file mode 100644
index 000000000..fa6ee2e2d
--- /dev/null
+++ b/tests/ui/traits/new-solver/pointee.rs
@@ -0,0 +1,23 @@
+// compile-flags: -Ztrait-solver=next
+// check-pass
+#![feature(ptr_metadata)]
+
+use std::ptr::{DynMetadata, Pointee};
+
+trait Trait<U> {}
+struct MyDst<T: ?Sized>(T);
+
+fn works<T>() {
+ let _: <T as Pointee>::Metadata = ();
+ let _: <[T] as Pointee>::Metadata = 1_usize;
+ let _: <str as Pointee>::Metadata = 1_usize;
+ let _: <dyn Trait<T> as Pointee>::Metadata = give::<DynMetadata<dyn Trait<T>>>();
+ let _: <MyDst<T> as Pointee>::Metadata = ();
+ let _: <((((([u8],),),),),) as Pointee>::Metadata = 1_usize;
+}
+
+fn give<U>() -> U {
+ loop {}
+}
+
+fn main() {}
diff --git a/tests/ui/traits/new-solver/pointer-like.rs b/tests/ui/traits/new-solver/pointer-like.rs
new file mode 100644
index 000000000..3745a075e
--- /dev/null
+++ b/tests/ui/traits/new-solver/pointer-like.rs
@@ -0,0 +1,14 @@
+// compile-flags: -Ztrait-solver=next
+
+#![feature(pointer_like_trait)]
+
+use std::marker::PointerLike;
+
+fn require_(_: impl PointerLike) {}
+
+fn main() {
+ require_(1usize);
+ require_(1u16);
+ //~^ ERROR `u16` needs to have the same alignment and size as a pointer
+ require_(&1i16);
+}
diff --git a/tests/ui/traits/new-solver/pointer-like.stderr b/tests/ui/traits/new-solver/pointer-like.stderr
new file mode 100644
index 000000000..f695e6418
--- /dev/null
+++ b/tests/ui/traits/new-solver/pointer-like.stderr
@@ -0,0 +1,24 @@
+error[E0277]: `u16` needs to have the same alignment and size as a pointer
+ --> $DIR/pointer-like.rs:11:14
+ |
+LL | require_(1u16);
+ | -------- ^^^^ the trait `PointerLike` is not implemented for `u16`
+ | |
+ | required by a bound introduced by this call
+ |
+ = note: the trait bound `u16: PointerLike` is not satisfied
+note: required by a bound in `require_`
+ --> $DIR/pointer-like.rs:7:21
+ |
+LL | fn require_(_: impl PointerLike) {}
+ | ^^^^^^^^^^^ required by this bound in `require_`
+help: consider borrowing here
+ |
+LL | require_(&1u16);
+ | +
+LL | require_(&mut 1u16);
+ | ++++
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/traits/new-solver/pointer-sized.rs b/tests/ui/traits/new-solver/pointer-sized.rs
deleted file mode 100644
index 15681cd13..000000000
--- a/tests/ui/traits/new-solver/pointer-sized.rs
+++ /dev/null
@@ -1,12 +0,0 @@
-#![feature(pointer_sized_trait)]
-
-use std::marker::PointerSized;
-
-fn require_pointer_sized(_: impl PointerSized) {}
-
-fn main() {
- require_pointer_sized(1usize);
- require_pointer_sized(1u16);
- //~^ ERROR `u16` needs to be a pointer-sized type
- require_pointer_sized(&1i16);
-}
diff --git a/tests/ui/traits/new-solver/pointer-sized.stderr b/tests/ui/traits/new-solver/pointer-sized.stderr
deleted file mode 100644
index b250b1331..000000000
--- a/tests/ui/traits/new-solver/pointer-sized.stderr
+++ /dev/null
@@ -1,24 +0,0 @@
-error[E0277]: `u16` needs to be a pointer-sized type
- --> $DIR/pointer-sized.rs:9:27
- |
-LL | require_pointer_sized(1u16);
- | --------------------- ^^^^ the trait `PointerSized` is not implemented for `u16`
- | |
- | required by a bound introduced by this call
- |
- = note: the trait bound `u16: PointerSized` is not satisfied
-note: required by a bound in `require_pointer_sized`
- --> $DIR/pointer-sized.rs:5:34
- |
-LL | fn require_pointer_sized(_: impl PointerSized) {}
- | ^^^^^^^^^^^^ required by this bound in `require_pointer_sized`
-help: consider borrowing here
- |
-LL | require_pointer_sized(&1u16);
- | +
-LL | require_pointer_sized(&mut 1u16);
- | ++++
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/traits/new-solver/provisional-result-done.rs b/tests/ui/traits/new-solver/provisional-result-done.rs
new file mode 100644
index 000000000..589d34dd7
--- /dev/null
+++ b/tests/ui/traits/new-solver/provisional-result-done.rs
@@ -0,0 +1,33 @@
+// compile-flags: -Ztrait-solver=next
+// check-pass
+
+// This tests checks that we update results in the provisional cache when
+// we pop a goal from the stack.
+#![feature(auto_traits)]
+auto trait Coinductive {}
+struct Foo<T>(T);
+struct Bar<T>(T);
+
+impl<T> Coinductive for Foo<T>
+where
+ Bar<T>: Coinductive
+{}
+
+impl<T> Coinductive for Bar<T>
+where
+ Foo<T>: Coinductive,
+ Bar<T>: ConstrainInfer,
+{}
+
+trait ConstrainInfer {}
+impl ConstrainInfer for Bar<u8> {}
+impl ConstrainInfer for Foo<u16> {}
+
+fn impls<T: Coinductive>() -> T { todo!() }
+
+fn constrain<T: ConstrainInfer>(_: T) {}
+
+fn main() {
+ // This should constrain `_` to `u8`.
+ impls::<Foo<_>>();
+}
diff --git a/tests/ui/traits/new-solver/temporary-ambiguity.rs b/tests/ui/traits/new-solver/temporary-ambiguity.rs
new file mode 100644
index 000000000..18ee05457
--- /dev/null
+++ b/tests/ui/traits/new-solver/temporary-ambiguity.rs
@@ -0,0 +1,22 @@
+// compile-flags: -Ztrait-solver=next
+// check-pass
+
+// Checks that we don't explode when we assemble >1 candidate for a goal.
+
+struct Wrapper<T>(T);
+
+trait Foo {}
+
+impl Foo for Wrapper<i32> {}
+
+impl Foo for Wrapper<()> {}
+
+fn needs_foo(_: impl Foo) {}
+
+fn main() {
+ let mut x = Default::default();
+ let w = Wrapper(x);
+ needs_foo(w);
+ x = 1;
+ drop(x);
+}
diff --git a/tests/ui/traits/new-solver/try-example.rs b/tests/ui/traits/new-solver/try-example.rs
new file mode 100644
index 000000000..e826f3a00
--- /dev/null
+++ b/tests/ui/traits/new-solver/try-example.rs
@@ -0,0 +1,28 @@
+// check-pass
+// compile-flags: -Ztrait-solver=next
+
+use std::error::Error;
+
+fn main() -> Result<(), Box<dyn Error>> {
+ let x: i32 = parse()?;
+ Ok(())
+}
+
+trait Parse {}
+
+impl Parse for i32 {}
+
+#[derive(Debug)]
+struct ParseError;
+
+impl std::fmt::Display for ParseError {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ write!(f, "ParseError")
+ }
+}
+
+impl Error for ParseError {}
+
+fn parse<T: Parse>() -> Result<T, ParseError> {
+ todo!()
+}
diff --git a/tests/ui/traits/new-solver/two-projection-param-candidates-are-ambiguous.rs b/tests/ui/traits/new-solver/two-projection-param-candidates-are-ambiguous.rs
new file mode 100644
index 000000000..cde2059ca
--- /dev/null
+++ b/tests/ui/traits/new-solver/two-projection-param-candidates-are-ambiguous.rs
@@ -0,0 +1,30 @@
+// compile-flags: -Ztrait-solver=next
+
+// When we're solving `<T as Foo>::Assoc = i32`, we actually first solve
+// `<T as Foo>::Assoc = _#1t`, then unify `_#1t` with `i32`. That goal
+// with the inference variable is ambiguous when there are >1 param-env
+// candidates.
+
+// We don't unify the RHS of a projection goal eagerly when solving, both
+// for caching reasons and partly to make sure that we don't make the new
+// trait solver smarter than it should be.
+
+// This is (as far as I can tell) a forwards-compatible decision, but if you
+// make this test go from fail to pass, be sure you understand the implications!
+
+trait Foo {
+ type Assoc;
+}
+
+trait Bar {}
+
+impl<T> Bar for T where T: Foo<Assoc = i32> {}
+
+fn needs_bar<T: Bar>() {}
+
+fn foo<T: Foo<Assoc = i32> + Foo<Assoc = u32>>() {
+ needs_bar::<T>();
+ //~^ ERROR type annotations needed: cannot satisfy `T: Bar`
+}
+
+fn main() {}
diff --git a/tests/ui/traits/new-solver/two-projection-param-candidates-are-ambiguous.stderr b/tests/ui/traits/new-solver/two-projection-param-candidates-are-ambiguous.stderr
new file mode 100644
index 000000000..fa5e780ee
--- /dev/null
+++ b/tests/ui/traits/new-solver/two-projection-param-candidates-are-ambiguous.stderr
@@ -0,0 +1,16 @@
+error[E0283]: type annotations needed: cannot satisfy `T: Bar`
+ --> $DIR/two-projection-param-candidates-are-ambiguous.rs:26:5
+ |
+LL | needs_bar::<T>();
+ | ^^^^^^^^^^^^^^
+ |
+ = note: cannot satisfy `T: Bar`
+note: required by a bound in `needs_bar`
+ --> $DIR/two-projection-param-candidates-are-ambiguous.rs:23:17
+ |
+LL | fn needs_bar<T: Bar>() {}
+ | ^^^ required by this bound in `needs_bar`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0283`.
diff --git a/tests/ui/traits/new-solver/unsafe-auto-trait-impl.rs b/tests/ui/traits/new-solver/unsafe-auto-trait-impl.rs
new file mode 100644
index 000000000..bcfc747eb
--- /dev/null
+++ b/tests/ui/traits/new-solver/unsafe-auto-trait-impl.rs
@@ -0,0 +1,8 @@
+// compile-flags: -Ztrait-solver=next
+// check-pass
+
+struct Foo(*mut ());
+
+unsafe impl Sync for Foo {}
+
+fn main() {}
diff --git a/tests/ui/traits/new-solver/unsize-good.rs b/tests/ui/traits/new-solver/unsize-good.rs
new file mode 100644
index 000000000..87ed9cfd1
--- /dev/null
+++ b/tests/ui/traits/new-solver/unsize-good.rs
@@ -0,0 +1,25 @@
+// compile-flags: -Ztrait-solver=next
+// check-pass
+
+#![feature(unsized_tuple_coercion)]
+
+trait Foo {}
+
+impl Foo for i32 {}
+
+fn main() {
+ // Unsizing via struct
+ let _: Box<dyn Foo> = Box::new(1i32);
+
+ // Slice unsizing
+ let y = [1, 2, 3];
+ let _: &[i32] = &y;
+
+ // Tuple unsizing
+ let hi = (1i32,);
+ let _: &(dyn Foo,) = &hi;
+
+ // Dropping auto traits
+ let a: &(dyn Foo + Send) = &1;
+ let _: &dyn Foo = a;
+}
diff --git a/tests/ui/traits/new-solver/upcast-right-substs.rs b/tests/ui/traits/new-solver/upcast-right-substs.rs
new file mode 100644
index 000000000..c19c82acf
--- /dev/null
+++ b/tests/ui/traits/new-solver/upcast-right-substs.rs
@@ -0,0 +1,14 @@
+// compile-flags: -Ztrait-solver=next
+// check-pass
+
+#![feature(trait_upcasting)]
+
+trait Foo: Bar<i32> + Bar<u32> {}
+
+trait Bar<T> {}
+
+fn main() {
+ let x: &dyn Foo = todo!();
+ let y: &dyn Bar<i32> = x;
+ let z: &dyn Bar<u32> = x;
+}
diff --git a/tests/ui/traits/new-solver/upcast-wrong-substs.rs b/tests/ui/traits/new-solver/upcast-wrong-substs.rs
new file mode 100644
index 000000000..f2d04d932
--- /dev/null
+++ b/tests/ui/traits/new-solver/upcast-wrong-substs.rs
@@ -0,0 +1,13 @@
+// compile-flags: -Ztrait-solver=next
+
+#![feature(trait_upcasting)]
+
+trait Foo: Bar<i32> + Bar<u32> {}
+
+trait Bar<T> {}
+
+fn main() {
+ let x: &dyn Foo = todo!();
+ let y: &dyn Bar<usize> = x;
+ //~^ ERROR mismatched types
+}
diff --git a/tests/ui/traits/new-solver/upcast-wrong-substs.stderr b/tests/ui/traits/new-solver/upcast-wrong-substs.stderr
new file mode 100644
index 000000000..8623f395f
--- /dev/null
+++ b/tests/ui/traits/new-solver/upcast-wrong-substs.stderr
@@ -0,0 +1,14 @@
+error[E0308]: mismatched types
+ --> $DIR/upcast-wrong-substs.rs:11:30
+ |
+LL | let y: &dyn Bar<usize> = x;
+ | --------------- ^ expected trait `Bar`, found trait `Foo`
+ | |
+ | expected due to this
+ |
+ = note: expected reference `&dyn Bar<usize>`
+ found reference `&dyn Foo`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/traits/non_lifetime_binders/bad-sized-cond.rs b/tests/ui/traits/non_lifetime_binders/bad-sized-cond.rs
new file mode 100644
index 000000000..dfc800c8e
--- /dev/null
+++ b/tests/ui/traits/non_lifetime_binders/bad-sized-cond.rs
@@ -0,0 +1,23 @@
+#![feature(non_lifetime_binders)]
+//~^ WARN is incomplete and may not be safe
+
+pub fn foo()
+where
+ for<V> V: Sized,
+{
+}
+
+pub fn bar()
+where
+ for<V> V: IntoIterator,
+{
+}
+
+fn main() {
+ foo();
+ //~^ ERROR the size for values of type `V` cannot be known at compilation time
+
+ bar();
+ //~^ ERROR the size for values of type `V` cannot be known at compilation time
+ //~| ERROR `V` is not an iterator
+}
diff --git a/tests/ui/traits/non_lifetime_binders/bad-sized-cond.stderr b/tests/ui/traits/non_lifetime_binders/bad-sized-cond.stderr
new file mode 100644
index 000000000..ed9b57cb1
--- /dev/null
+++ b/tests/ui/traits/non_lifetime_binders/bad-sized-cond.stderr
@@ -0,0 +1,62 @@
+warning: the feature `non_lifetime_binders` is incomplete and may not be safe to use and/or cause compiler crashes
+ --> $DIR/bad-sized-cond.rs:1:12
+ |
+LL | #![feature(non_lifetime_binders)]
+ | ^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: see issue #108185 <https://github.com/rust-lang/rust/issues/108185> for more information
+ = note: `#[warn(incomplete_features)]` on by default
+
+error[E0277]: the size for values of type `V` cannot be known at compilation time
+ --> $DIR/bad-sized-cond.rs:17:5
+ |
+LL | foo();
+ | ^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `V`
+note: required by a bound in `foo`
+ --> $DIR/bad-sized-cond.rs:6:15
+ |
+LL | pub fn foo()
+ | --- required by a bound in this function
+LL | where
+LL | for<V> V: Sized,
+ | ^^^^^ required by this bound in `foo`
+
+error[E0277]: the size for values of type `V` cannot be known at compilation time
+ --> $DIR/bad-sized-cond.rs:20:5
+ |
+LL | bar();
+ | ^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `V`
+ = note: required for `V` to implement `IntoIterator`
+note: required by a bound in `bar`
+ --> $DIR/bad-sized-cond.rs:12:15
+ |
+LL | pub fn bar()
+ | --- required by a bound in this function
+LL | where
+LL | for<V> V: IntoIterator,
+ | ^^^^^^^^^^^^ required by this bound in `bar`
+
+error[E0277]: `V` is not an iterator
+ --> $DIR/bad-sized-cond.rs:20:5
+ |
+LL | bar();
+ | ^^^ `V` is not an iterator
+ |
+ = help: the trait `Iterator` is not implemented for `V`
+ = note: required for `V` to implement `IntoIterator`
+note: required by a bound in `bar`
+ --> $DIR/bad-sized-cond.rs:12:15
+ |
+LL | pub fn bar()
+ | --- required by a bound in this function
+LL | where
+LL | for<V> V: IntoIterator,
+ | ^^^^^^^^^^^^ required by this bound in `bar`
+
+error: aborting due to 3 previous errors; 1 warning emitted
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/traits/non_lifetime_binders/basic.rs b/tests/ui/traits/non_lifetime_binders/basic.rs
new file mode 100644
index 000000000..a797aae65
--- /dev/null
+++ b/tests/ui/traits/non_lifetime_binders/basic.rs
@@ -0,0 +1,19 @@
+// check-pass
+// Basic test that show's we can succesfully typeck a `for<T>` where clause.
+
+#![feature(non_lifetime_binders)]
+//~^ WARN the feature `non_lifetime_binders` is incomplete
+
+trait Trait {}
+
+impl<T: ?Sized> Trait for T {}
+
+fn foo()
+where
+ for<T> T: Trait,
+{
+}
+
+fn main() {
+ foo();
+}
diff --git a/tests/ui/traits/non_lifetime_binders/basic.stderr b/tests/ui/traits/non_lifetime_binders/basic.stderr
new file mode 100644
index 000000000..0fd16c5d0
--- /dev/null
+++ b/tests/ui/traits/non_lifetime_binders/basic.stderr
@@ -0,0 +1,11 @@
+warning: the feature `non_lifetime_binders` is incomplete and may not be safe to use and/or cause compiler crashes
+ --> $DIR/basic.rs:4:12
+ |
+LL | #![feature(non_lifetime_binders)]
+ | ^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: see issue #108185 <https://github.com/rust-lang/rust/issues/108185> for more information
+ = note: `#[warn(incomplete_features)]` on by default
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/traits/non_lifetime_binders/fail.rs b/tests/ui/traits/non_lifetime_binders/fail.rs
new file mode 100644
index 000000000..460f68907
--- /dev/null
+++ b/tests/ui/traits/non_lifetime_binders/fail.rs
@@ -0,0 +1,23 @@
+// Error reporting for where `for<T> T: Trait` doesn't hold
+
+#![feature(non_lifetime_binders)]
+//~^ WARN the feature `non_lifetime_binders` is incomplete
+
+trait Trait {}
+
+fn fail()
+where
+ for<T> T: Trait,
+{}
+
+fn auto_trait()
+where
+ for<T> T: Send,
+{}
+
+fn main() {
+ fail();
+ //~^ ERROR the trait bound `T: Trait` is not satisfied
+ auto_trait();
+ //~^ ERROR `T` cannot be sent between threads safely
+}
diff --git a/tests/ui/traits/non_lifetime_binders/fail.stderr b/tests/ui/traits/non_lifetime_binders/fail.stderr
new file mode 100644
index 000000000..7bd02550f
--- /dev/null
+++ b/tests/ui/traits/non_lifetime_binders/fail.stderr
@@ -0,0 +1,43 @@
+warning: the feature `non_lifetime_binders` is incomplete and may not be safe to use and/or cause compiler crashes
+ --> $DIR/fail.rs:3:12
+ |
+LL | #![feature(non_lifetime_binders)]
+ | ^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: see issue #108185 <https://github.com/rust-lang/rust/issues/108185> for more information
+ = note: `#[warn(incomplete_features)]` on by default
+
+error[E0277]: the trait bound `T: Trait` is not satisfied
+ --> $DIR/fail.rs:19:5
+ |
+LL | fail();
+ | ^^^^ the trait `Trait` is not implemented for `T`
+ |
+note: required by a bound in `fail`
+ --> $DIR/fail.rs:10:15
+ |
+LL | fn fail()
+ | ---- required by a bound in this function
+LL | where
+LL | for<T> T: Trait,
+ | ^^^^^ required by this bound in `fail`
+
+error[E0277]: `T` cannot be sent between threads safely
+ --> $DIR/fail.rs:21:5
+ |
+LL | auto_trait();
+ | ^^^^^^^^^^ `T` cannot be sent between threads safely
+ |
+ = help: the trait `Send` is not implemented for `T`
+note: required by a bound in `auto_trait`
+ --> $DIR/fail.rs:15:15
+ |
+LL | fn auto_trait()
+ | ---------- required by a bound in this function
+LL | where
+LL | for<T> T: Send,
+ | ^^^^ required by this bound in `auto_trait`
+
+error: aborting due to 2 previous errors; 1 warning emitted
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/traits/non_lifetime_binders/late-bound-in-anon-ct.rs b/tests/ui/traits/non_lifetime_binders/late-bound-in-anon-ct.rs
new file mode 100644
index 000000000..3903bfe9b
--- /dev/null
+++ b/tests/ui/traits/non_lifetime_binders/late-bound-in-anon-ct.rs
@@ -0,0 +1,11 @@
+#![feature(non_lifetime_binders, generic_const_exprs)]
+//~^ WARN the feature `non_lifetime_binders` is incomplete
+//~| WARN the feature `generic_const_exprs` is incomplete
+
+fn foo() -> usize
+where
+ for<T> [i32; { let _: T = todo!(); 0 }]:,
+ //~^ ERROR cannot capture late-bound type parameter in a constant
+{}
+
+fn main() {}
diff --git a/tests/ui/traits/non_lifetime_binders/late-bound-in-anon-ct.stderr b/tests/ui/traits/non_lifetime_binders/late-bound-in-anon-ct.stderr
new file mode 100644
index 000000000..fafff02de
--- /dev/null
+++ b/tests/ui/traits/non_lifetime_binders/late-bound-in-anon-ct.stderr
@@ -0,0 +1,27 @@
+warning: the feature `non_lifetime_binders` is incomplete and may not be safe to use and/or cause compiler crashes
+ --> $DIR/late-bound-in-anon-ct.rs:1:12
+ |
+LL | #![feature(non_lifetime_binders, generic_const_exprs)]
+ | ^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: see issue #108185 <https://github.com/rust-lang/rust/issues/108185> for more information
+ = note: `#[warn(incomplete_features)]` on by default
+
+warning: the feature `generic_const_exprs` is incomplete and may not be safe to use and/or cause compiler crashes
+ --> $DIR/late-bound-in-anon-ct.rs:1:34
+ |
+LL | #![feature(non_lifetime_binders, generic_const_exprs)]
+ | ^^^^^^^^^^^^^^^^^^^
+ |
+ = note: see issue #76560 <https://github.com/rust-lang/rust/issues/76560> for more information
+
+error: cannot capture late-bound type parameter in a constant
+ --> $DIR/late-bound-in-anon-ct.rs:7:27
+ |
+LL | for<T> [i32; { let _: T = todo!(); 0 }]:,
+ | - ^
+ | |
+ | parameter defined here
+
+error: aborting due to previous error; 2 warnings emitted
+
diff --git a/tests/ui/traits/non_lifetime_binders/object-lifetime-default-for-late.rs b/tests/ui/traits/non_lifetime_binders/object-lifetime-default-for-late.rs
new file mode 100644
index 000000000..9830241c3
--- /dev/null
+++ b/tests/ui/traits/non_lifetime_binders/object-lifetime-default-for-late.rs
@@ -0,0 +1,7 @@
+// check-pass
+// compile-flags: --crate-type=lib
+
+#![feature(non_lifetime_binders)]
+//~^ WARN the feature `non_lifetime_binders` is incomplete
+
+pub fn f<T>() where for<U> (T, U): Copy {}
diff --git a/tests/ui/traits/non_lifetime_binders/object-lifetime-default-for-late.stderr b/tests/ui/traits/non_lifetime_binders/object-lifetime-default-for-late.stderr
new file mode 100644
index 000000000..667575b72
--- /dev/null
+++ b/tests/ui/traits/non_lifetime_binders/object-lifetime-default-for-late.stderr
@@ -0,0 +1,11 @@
+warning: the feature `non_lifetime_binders` is incomplete and may not be safe to use and/or cause compiler crashes
+ --> $DIR/object-lifetime-default-for-late.rs:4:12
+ |
+LL | #![feature(non_lifetime_binders)]
+ | ^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: see issue #108185 <https://github.com/rust-lang/rust/issues/108185> for more information
+ = note: `#[warn(incomplete_features)]` on by default
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/traits/non_lifetime_binders/on-dyn.rs b/tests/ui/traits/non_lifetime_binders/on-dyn.rs
new file mode 100644
index 000000000..8fb7dd276
--- /dev/null
+++ b/tests/ui/traits/non_lifetime_binders/on-dyn.rs
@@ -0,0 +1,13 @@
+// Tests to make sure that we reject polymorphic dyn trait.
+
+#![feature(non_lifetime_binders)]
+//~^ WARN the feature `non_lifetime_binders` is incomplete
+
+trait Test<T> {}
+
+fn foo() -> &'static dyn for<T> Test<T> {
+ //~^ ERROR late-bound type parameter not allowed on trait object types
+ todo!()
+}
+
+fn main() {}
diff --git a/tests/ui/traits/non_lifetime_binders/on-dyn.stderr b/tests/ui/traits/non_lifetime_binders/on-dyn.stderr
new file mode 100644
index 000000000..95656f999
--- /dev/null
+++ b/tests/ui/traits/non_lifetime_binders/on-dyn.stderr
@@ -0,0 +1,17 @@
+warning: the feature `non_lifetime_binders` is incomplete and may not be safe to use and/or cause compiler crashes
+ --> $DIR/on-dyn.rs:3:12
+ |
+LL | #![feature(non_lifetime_binders)]
+ | ^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: see issue #108185 <https://github.com/rust-lang/rust/issues/108185> for more information
+ = note: `#[warn(incomplete_features)]` on by default
+
+error: late-bound type parameter not allowed on trait object types
+ --> $DIR/on-dyn.rs:8:30
+ |
+LL | fn foo() -> &'static dyn for<T> Test<T> {
+ | ^
+
+error: aborting due to previous error; 1 warning emitted
+
diff --git a/tests/ui/traits/non_lifetime_binders/on-ptr.rs b/tests/ui/traits/non_lifetime_binders/on-ptr.rs
new file mode 100644
index 000000000..0aaff52b6
--- /dev/null
+++ b/tests/ui/traits/non_lifetime_binders/on-ptr.rs
@@ -0,0 +1,13 @@
+// Tests to make sure that we reject polymorphic fn ptrs.
+
+#![feature(non_lifetime_binders)]
+//~^ WARN the feature `non_lifetime_binders` is incomplete
+
+fn foo() -> for<T> fn(T) {
+ //~^ ERROR late-bound type parameter not allowed on function pointer types
+ todo!()
+}
+
+fn main() {
+ foo()(1i32);
+}
diff --git a/tests/ui/traits/non_lifetime_binders/on-ptr.stderr b/tests/ui/traits/non_lifetime_binders/on-ptr.stderr
new file mode 100644
index 000000000..3b17f7697
--- /dev/null
+++ b/tests/ui/traits/non_lifetime_binders/on-ptr.stderr
@@ -0,0 +1,17 @@
+warning: the feature `non_lifetime_binders` is incomplete and may not be safe to use and/or cause compiler crashes
+ --> $DIR/on-ptr.rs:3:12
+ |
+LL | #![feature(non_lifetime_binders)]
+ | ^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: see issue #108185 <https://github.com/rust-lang/rust/issues/108185> for more information
+ = note: `#[warn(incomplete_features)]` on by default
+
+error: late-bound type parameter not allowed on function pointer types
+ --> $DIR/on-ptr.rs:6:17
+ |
+LL | fn foo() -> for<T> fn(T) {
+ | ^
+
+error: aborting due to previous error; 1 warning emitted
+
diff --git a/tests/ui/traits/non_lifetime_binders/type-match-with-late-bound.rs b/tests/ui/traits/non_lifetime_binders/type-match-with-late-bound.rs
new file mode 100644
index 000000000..5ff7089b9
--- /dev/null
+++ b/tests/ui/traits/non_lifetime_binders/type-match-with-late-bound.rs
@@ -0,0 +1,14 @@
+// edition:2021
+// check-pass
+
+// Checks that test_type_match code doesn't ICE when predicates have late-bound types
+
+#![feature(non_lifetime_binders)]
+//~^ WARN is incomplete and may not be safe to use
+
+async fn walk2<'a, T: 'a>(_: T)
+where
+ for<F> F: 'a,
+{}
+
+fn main() {}
diff --git a/tests/ui/traits/non_lifetime_binders/type-match-with-late-bound.stderr b/tests/ui/traits/non_lifetime_binders/type-match-with-late-bound.stderr
new file mode 100644
index 000000000..3609bed28
--- /dev/null
+++ b/tests/ui/traits/non_lifetime_binders/type-match-with-late-bound.stderr
@@ -0,0 +1,11 @@
+warning: the feature `non_lifetime_binders` is incomplete and may not be safe to use and/or cause compiler crashes
+ --> $DIR/type-match-with-late-bound.rs:6:12
+ |
+LL | #![feature(non_lifetime_binders)]
+ | ^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: see issue #108185 <https://github.com/rust-lang/rust/issues/108185> for more information
+ = note: `#[warn(incomplete_features)]` on by default
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/traits/object/enforce-supertrait-projection.stderr b/tests/ui/traits/object/enforce-supertrait-projection.stderr
index cbf093866..848b4e69a 100644
--- a/tests/ui/traits/object/enforce-supertrait-projection.stderr
+++ b/tests/ui/traits/object/enforce-supertrait-projection.stderr
@@ -16,7 +16,7 @@ note: required by a bound in `foo`
--> $DIR/enforce-supertrait-projection.rs:15:8
|
LL | fn foo<A, B, T: ?Sized>(x: T::A) -> B
- | --- required by a bound in this
+ | --- required by a bound in this function
LL | where
LL | T: Trait<B = B>,
| ^^^^^^^^^^^^ required by this bound in `foo`
diff --git a/tests/ui/traits/object/vs-lifetime.rs b/tests/ui/traits/object/vs-lifetime.rs
index 14ae67cff..d3e6c0b21 100644
--- a/tests/ui/traits/object/vs-lifetime.rs
+++ b/tests/ui/traits/object/vs-lifetime.rs
@@ -9,8 +9,8 @@ fn main() {
let _: S<'static, dyn 'static +>;
//~^ at least one trait is required for an object type
let _: S<'static, 'static>;
- //~^ ERROR this struct takes 1 lifetime argument but 2 lifetime arguments were supplied
- //~| ERROR this struct takes 1 generic argument but 0 generic arguments were supplied
+ //~^ ERROR struct takes 1 lifetime argument but 2 lifetime arguments were supplied
+ //~| ERROR struct takes 1 generic argument but 0 generic arguments were supplied
let _: S<dyn 'static +, 'static>;
//~^ ERROR type provided when a lifetime was expected
//~| ERROR at least one trait is required for an object type
diff --git a/tests/ui/traits/object/vs-lifetime.stderr b/tests/ui/traits/object/vs-lifetime.stderr
index 224465228..a69cd1408 100644
--- a/tests/ui/traits/object/vs-lifetime.stderr
+++ b/tests/ui/traits/object/vs-lifetime.stderr
@@ -4,7 +4,7 @@ error[E0224]: at least one trait is required for an object type
LL | let _: S<'static, dyn 'static +>;
| ^^^^^^^^^^^^^
-error[E0107]: this struct takes 1 lifetime argument but 2 lifetime arguments were supplied
+error[E0107]: struct takes 1 lifetime argument but 2 lifetime arguments were supplied
--> $DIR/vs-lifetime.rs:11:12
|
LL | let _: S<'static, 'static>;
@@ -18,7 +18,7 @@ note: struct defined here, with 1 lifetime parameter: `'a`
LL | struct S<'a, T>(&'a u8, T);
| ^ --
-error[E0107]: this struct takes 1 generic argument but 0 generic arguments were supplied
+error[E0107]: struct takes 1 generic argument but 0 generic arguments were supplied
--> $DIR/vs-lifetime.rs:11:12
|
LL | let _: S<'static, 'static>;
diff --git a/tests/ui/traits/suggest-deferences/issue-39029.stderr b/tests/ui/traits/suggest-deferences/issue-39029.stderr
index 49e20c6a7..49105de3d 100644
--- a/tests/ui/traits/suggest-deferences/issue-39029.stderr
+++ b/tests/ui/traits/suggest-deferences/issue-39029.stderr
@@ -1,8 +1,8 @@
error[E0277]: the trait bound `NoToSocketAddrs: ToSocketAddrs` is not satisfied
- --> $DIR/issue-39029.rs:16:37
+ --> $DIR/issue-39029.rs:16:38
|
LL | let _errors = TcpListener::bind(&bad);
- | ----------------- ^^^^ the trait `ToSocketAddrs` is not implemented for `NoToSocketAddrs`
+ | ----------------- ^^^ the trait `ToSocketAddrs` is not implemented for `NoToSocketAddrs`
| |
| required by a bound introduced by this call
|
diff --git a/tests/ui/traits/test-2.rs b/tests/ui/traits/test-2.rs
index 342928e88..ffb778a01 100644
--- a/tests/ui/traits/test-2.rs
+++ b/tests/ui/traits/test-2.rs
@@ -7,9 +7,9 @@ impl bar for u32 { fn dup(&self) -> u32 { *self } fn blah<X>(&self) {} }
fn main() {
10.dup::<i32>();
- //~^ ERROR this associated function takes 0 generic arguments but 1
+ //~^ ERROR method takes 0 generic arguments but 1
10.blah::<i32, i32>();
- //~^ ERROR this associated function takes 1 generic argument but 2
+ //~^ ERROR method takes 1 generic argument but 2
(Box::new(10) as Box<dyn bar>).dup();
//~^ ERROR E0038
//~| ERROR E0038
diff --git a/tests/ui/traits/test-2.stderr b/tests/ui/traits/test-2.stderr
index eaa20b0b4..6c0e8b8af 100644
--- a/tests/ui/traits/test-2.stderr
+++ b/tests/ui/traits/test-2.stderr
@@ -1,4 +1,4 @@
-error[E0107]: this associated function takes 0 generic arguments but 1 generic argument was supplied
+error[E0107]: method takes 0 generic arguments but 1 generic argument was supplied
--> $DIR/test-2.rs:9:8
|
LL | 10.dup::<i32>();
@@ -6,13 +6,13 @@ LL | 10.dup::<i32>();
| |
| expected 0 generic arguments
|
-note: associated function defined here, with 0 generic parameters
+note: method defined here, with 0 generic parameters
--> $DIR/test-2.rs:4:16
|
LL | trait bar { fn dup(&self) -> Self; fn blah<X>(&self); }
| ^^^
-error[E0107]: this associated function takes 1 generic argument but 2 generic arguments were supplied
+error[E0107]: method takes 1 generic argument but 2 generic arguments were supplied
--> $DIR/test-2.rs:11:8
|
LL | 10.blah::<i32, i32>();
@@ -20,7 +20,7 @@ LL | 10.blah::<i32, i32>();
| |
| expected 1 generic argument
|
-note: associated function defined here, with 1 generic parameter: `X`
+note: method defined here, with 1 generic parameter: `X`
--> $DIR/test-2.rs:4:39
|
LL | trait bar { fn dup(&self) -> Self; fn blah<X>(&self); }
diff --git a/tests/ui/traits/trait-or-new-type-instead.stderr b/tests/ui/traits/trait-or-new-type-instead.stderr
index 4726b0668..6fd8a03fd 100644
--- a/tests/ui/traits/trait-or-new-type-instead.stderr
+++ b/tests/ui/traits/trait-or-new-type-instead.stderr
@@ -1,11 +1,8 @@
error[E0116]: cannot define inherent `impl` for a type outside of the crate where the type is defined
--> $DIR/trait-or-new-type-instead.rs:1:1
|
-LL | / impl<T> Option<T> {
-LL | |
-LL | | pub fn foo(&self) { }
-LL | | }
- | |_^ impl for type defined outside of crate.
+LL | impl<T> Option<T> {
+ | ^^^^^^^^^^^^^^^^^ impl for type defined outside of crate.
|
= note: define and implement a trait or new type instead
diff --git a/tests/ui/traits/trait-upcasting/multiple_supertrait_upcastable.rs b/tests/ui/traits/trait-upcasting/multiple_supertrait_upcastable.rs
new file mode 100644
index 000000000..3c6ab86e4
--- /dev/null
+++ b/tests/ui/traits/trait-upcasting/multiple_supertrait_upcastable.rs
@@ -0,0 +1,10 @@
+#![feature(multiple_supertrait_upcastable)]
+#![deny(multiple_supertrait_upcastable)]
+
+trait A {}
+trait B {}
+
+trait C: A + B {}
+//~^ ERROR `C` is object-safe and has multiple supertraits
+
+fn main() {}
diff --git a/tests/ui/traits/trait-upcasting/multiple_supertrait_upcastable.stderr b/tests/ui/traits/trait-upcasting/multiple_supertrait_upcastable.stderr
new file mode 100644
index 000000000..ad80a009e
--- /dev/null
+++ b/tests/ui/traits/trait-upcasting/multiple_supertrait_upcastable.stderr
@@ -0,0 +1,14 @@
+error: `C` is object-safe and has multiple supertraits
+ --> $DIR/multiple_supertrait_upcastable.rs:7:1
+ |
+LL | trait C: A + B {}
+ | ^^^^^^^^^^^^^^
+ |
+note: the lint level is defined here
+ --> $DIR/multiple_supertrait_upcastable.rs:2:9
+ |
+LL | #![deny(multiple_supertrait_upcastable)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/tests/ui/traits/unsend-future.rs b/tests/ui/traits/unsend-future.rs
new file mode 100644
index 000000000..fbbc07b11
--- /dev/null
+++ b/tests/ui/traits/unsend-future.rs
@@ -0,0 +1,21 @@
+// edition:2021
+
+// issue 108897
+trait Handler {}
+impl<F, Fut> Handler for F
+where
+ Fut: Send,
+ F: FnOnce() -> Fut,
+{}
+
+fn require_handler<H: Handler>(h: H) {}
+
+async fn handler() {
+ let a = &1 as *const i32;
+ async {}.await;
+}
+
+fn main() {
+ require_handler(handler)
+ //~^ ERROR future cannot be sent between threads safely
+}
diff --git a/tests/ui/traits/unsend-future.stderr b/tests/ui/traits/unsend-future.stderr
new file mode 100644
index 000000000..4aaa7c4a9
--- /dev/null
+++ b/tests/ui/traits/unsend-future.stderr
@@ -0,0 +1,24 @@
+error: future cannot be sent between threads safely
+ --> $DIR/unsend-future.rs:19:21
+ |
+LL | require_handler(handler)
+ | ^^^^^^^ future returned by `handler` is not `Send`
+ |
+ = help: within `impl Future<Output = ()>`, the trait `Send` is not implemented for `*const i32`
+note: future is not `Send` as this value is used across an await
+ --> $DIR/unsend-future.rs:15:13
+ |
+LL | let a = &1 as *const i32;
+ | - has type `*const i32` which is not `Send`
+LL | async {}.await;
+ | ^^^^^^ await occurs here, with `a` maybe used later
+LL | }
+ | - `a` is later dropped here
+note: required by a bound in `require_handler`
+ --> $DIR/unsend-future.rs:11:23
+ |
+LL | fn require_handler<H: Handler>(h: H) {}
+ | ^^^^^^^ required by this bound in `require_handler`
+
+error: aborting due to previous error
+
diff --git a/tests/ui/traits/vtable/issue-97381.stderr b/tests/ui/traits/vtable/issue-97381.stderr
index c4f8294e2..89360c44e 100644
--- a/tests/ui/traits/vtable/issue-97381.stderr
+++ b/tests/ui/traits/vtable/issue-97381.stderr
@@ -1,6 +1,9 @@
error[E0505]: cannot move out of `v` because it is borrowed
--> $DIR/issue-97381.rs:26:14
|
+LL | let v = [1, 2, 3]
+ | - binding `v` declared here
+...
LL | let el = &v[0];
| - borrow of `v` occurs here
LL |
diff --git a/tests/ui/transmutability/arrays/should_require_well_defined_layout.stderr b/tests/ui/transmutability/arrays/should_require_well_defined_layout.stderr
index 96a2fdc54..164e88ede 100644
--- a/tests/ui/transmutability/arrays/should_require_well_defined_layout.stderr
+++ b/tests/ui/transmutability/arrays/should_require_well_defined_layout.stderr
@@ -9,7 +9,7 @@ note: required by a bound in `is_maybe_transmutable`
--> $DIR/should_require_well_defined_layout.rs:13:14
|
LL | pub fn is_maybe_transmutable<Src, Dst>()
- | --------------------- required by a bound in this
+ | --------------------- required by a bound in this function
LL | where
LL | Dst: BikeshedIntrinsicFrom<Src, Context, {
| ______________^
@@ -31,7 +31,7 @@ note: required by a bound in `is_maybe_transmutable`
--> $DIR/should_require_well_defined_layout.rs:13:14
|
LL | pub fn is_maybe_transmutable<Src, Dst>()
- | --------------------- required by a bound in this
+ | --------------------- required by a bound in this function
LL | where
LL | Dst: BikeshedIntrinsicFrom<Src, Context, {
| ______________^
@@ -53,7 +53,7 @@ note: required by a bound in `is_maybe_transmutable`
--> $DIR/should_require_well_defined_layout.rs:13:14
|
LL | pub fn is_maybe_transmutable<Src, Dst>()
- | --------------------- required by a bound in this
+ | --------------------- required by a bound in this function
LL | where
LL | Dst: BikeshedIntrinsicFrom<Src, Context, {
| ______________^
@@ -75,7 +75,7 @@ note: required by a bound in `is_maybe_transmutable`
--> $DIR/should_require_well_defined_layout.rs:13:14
|
LL | pub fn is_maybe_transmutable<Src, Dst>()
- | --------------------- required by a bound in this
+ | --------------------- required by a bound in this function
LL | where
LL | Dst: BikeshedIntrinsicFrom<Src, Context, {
| ______________^
@@ -97,7 +97,7 @@ note: required by a bound in `is_maybe_transmutable`
--> $DIR/should_require_well_defined_layout.rs:13:14
|
LL | pub fn is_maybe_transmutable<Src, Dst>()
- | --------------------- required by a bound in this
+ | --------------------- required by a bound in this function
LL | where
LL | Dst: BikeshedIntrinsicFrom<Src, Context, {
| ______________^
@@ -119,7 +119,7 @@ note: required by a bound in `is_maybe_transmutable`
--> $DIR/should_require_well_defined_layout.rs:13:14
|
LL | pub fn is_maybe_transmutable<Src, Dst>()
- | --------------------- required by a bound in this
+ | --------------------- required by a bound in this function
LL | where
LL | Dst: BikeshedIntrinsicFrom<Src, Context, {
| ______________^
diff --git a/tests/ui/transmutability/enums/repr/primitive_reprs_should_have_correct_length.stderr b/tests/ui/transmutability/enums/repr/primitive_reprs_should_have_correct_length.stderr
index 4da5fcea3..0f0f77f16 100644
--- a/tests/ui/transmutability/enums/repr/primitive_reprs_should_have_correct_length.stderr
+++ b/tests/ui/transmutability/enums/repr/primitive_reprs_should_have_correct_length.stderr
@@ -9,7 +9,7 @@ note: required by a bound in `is_transmutable`
--> $DIR/primitive_reprs_should_have_correct_length.rs:12:14
|
LL | pub fn is_transmutable<Src, Dst, Context>()
- | --------------- required by a bound in this
+ | --------------- required by a bound in this function
LL | where
LL | Dst: BikeshedIntrinsicFrom<Src, Context, {
| ______________^
@@ -32,7 +32,7 @@ note: required by a bound in `is_transmutable`
--> $DIR/primitive_reprs_should_have_correct_length.rs:12:14
|
LL | pub fn is_transmutable<Src, Dst, Context>()
- | --------------- required by a bound in this
+ | --------------- required by a bound in this function
LL | where
LL | Dst: BikeshedIntrinsicFrom<Src, Context, {
| ______________^
@@ -55,7 +55,7 @@ note: required by a bound in `is_transmutable`
--> $DIR/primitive_reprs_should_have_correct_length.rs:12:14
|
LL | pub fn is_transmutable<Src, Dst, Context>()
- | --------------- required by a bound in this
+ | --------------- required by a bound in this function
LL | where
LL | Dst: BikeshedIntrinsicFrom<Src, Context, {
| ______________^
@@ -78,7 +78,7 @@ note: required by a bound in `is_transmutable`
--> $DIR/primitive_reprs_should_have_correct_length.rs:12:14
|
LL | pub fn is_transmutable<Src, Dst, Context>()
- | --------------- required by a bound in this
+ | --------------- required by a bound in this function
LL | where
LL | Dst: BikeshedIntrinsicFrom<Src, Context, {
| ______________^
@@ -101,7 +101,7 @@ note: required by a bound in `is_transmutable`
--> $DIR/primitive_reprs_should_have_correct_length.rs:12:14
|
LL | pub fn is_transmutable<Src, Dst, Context>()
- | --------------- required by a bound in this
+ | --------------- required by a bound in this function
LL | where
LL | Dst: BikeshedIntrinsicFrom<Src, Context, {
| ______________^
@@ -124,7 +124,7 @@ note: required by a bound in `is_transmutable`
--> $DIR/primitive_reprs_should_have_correct_length.rs:12:14
|
LL | pub fn is_transmutable<Src, Dst, Context>()
- | --------------- required by a bound in this
+ | --------------- required by a bound in this function
LL | where
LL | Dst: BikeshedIntrinsicFrom<Src, Context, {
| ______________^
@@ -147,7 +147,7 @@ note: required by a bound in `is_transmutable`
--> $DIR/primitive_reprs_should_have_correct_length.rs:12:14
|
LL | pub fn is_transmutable<Src, Dst, Context>()
- | --------------- required by a bound in this
+ | --------------- required by a bound in this function
LL | where
LL | Dst: BikeshedIntrinsicFrom<Src, Context, {
| ______________^
@@ -170,7 +170,7 @@ note: required by a bound in `is_transmutable`
--> $DIR/primitive_reprs_should_have_correct_length.rs:12:14
|
LL | pub fn is_transmutable<Src, Dst, Context>()
- | --------------- required by a bound in this
+ | --------------- required by a bound in this function
LL | where
LL | Dst: BikeshedIntrinsicFrom<Src, Context, {
| ______________^
@@ -193,7 +193,7 @@ note: required by a bound in `is_transmutable`
--> $DIR/primitive_reprs_should_have_correct_length.rs:12:14
|
LL | pub fn is_transmutable<Src, Dst, Context>()
- | --------------- required by a bound in this
+ | --------------- required by a bound in this function
LL | where
LL | Dst: BikeshedIntrinsicFrom<Src, Context, {
| ______________^
@@ -216,7 +216,7 @@ note: required by a bound in `is_transmutable`
--> $DIR/primitive_reprs_should_have_correct_length.rs:12:14
|
LL | pub fn is_transmutable<Src, Dst, Context>()
- | --------------- required by a bound in this
+ | --------------- required by a bound in this function
LL | where
LL | Dst: BikeshedIntrinsicFrom<Src, Context, {
| ______________^
@@ -239,7 +239,7 @@ note: required by a bound in `is_transmutable`
--> $DIR/primitive_reprs_should_have_correct_length.rs:12:14
|
LL | pub fn is_transmutable<Src, Dst, Context>()
- | --------------- required by a bound in this
+ | --------------- required by a bound in this function
LL | where
LL | Dst: BikeshedIntrinsicFrom<Src, Context, {
| ______________^
@@ -262,7 +262,7 @@ note: required by a bound in `is_transmutable`
--> $DIR/primitive_reprs_should_have_correct_length.rs:12:14
|
LL | pub fn is_transmutable<Src, Dst, Context>()
- | --------------- required by a bound in this
+ | --------------- required by a bound in this function
LL | where
LL | Dst: BikeshedIntrinsicFrom<Src, Context, {
| ______________^
@@ -285,7 +285,7 @@ note: required by a bound in `is_transmutable`
--> $DIR/primitive_reprs_should_have_correct_length.rs:12:14
|
LL | pub fn is_transmutable<Src, Dst, Context>()
- | --------------- required by a bound in this
+ | --------------- required by a bound in this function
LL | where
LL | Dst: BikeshedIntrinsicFrom<Src, Context, {
| ______________^
@@ -308,7 +308,7 @@ note: required by a bound in `is_transmutable`
--> $DIR/primitive_reprs_should_have_correct_length.rs:12:14
|
LL | pub fn is_transmutable<Src, Dst, Context>()
- | --------------- required by a bound in this
+ | --------------- required by a bound in this function
LL | where
LL | Dst: BikeshedIntrinsicFrom<Src, Context, {
| ______________^
@@ -331,7 +331,7 @@ note: required by a bound in `is_transmutable`
--> $DIR/primitive_reprs_should_have_correct_length.rs:12:14
|
LL | pub fn is_transmutable<Src, Dst, Context>()
- | --------------- required by a bound in this
+ | --------------- required by a bound in this function
LL | where
LL | Dst: BikeshedIntrinsicFrom<Src, Context, {
| ______________^
@@ -354,7 +354,7 @@ note: required by a bound in `is_transmutable`
--> $DIR/primitive_reprs_should_have_correct_length.rs:12:14
|
LL | pub fn is_transmutable<Src, Dst, Context>()
- | --------------- required by a bound in this
+ | --------------- required by a bound in this function
LL | where
LL | Dst: BikeshedIntrinsicFrom<Src, Context, {
| ______________^
@@ -377,7 +377,7 @@ note: required by a bound in `is_transmutable`
--> $DIR/primitive_reprs_should_have_correct_length.rs:12:14
|
LL | pub fn is_transmutable<Src, Dst, Context>()
- | --------------- required by a bound in this
+ | --------------- required by a bound in this function
LL | where
LL | Dst: BikeshedIntrinsicFrom<Src, Context, {
| ______________^
@@ -400,7 +400,7 @@ note: required by a bound in `is_transmutable`
--> $DIR/primitive_reprs_should_have_correct_length.rs:12:14
|
LL | pub fn is_transmutable<Src, Dst, Context>()
- | --------------- required by a bound in this
+ | --------------- required by a bound in this function
LL | where
LL | Dst: BikeshedIntrinsicFrom<Src, Context, {
| ______________^
@@ -423,7 +423,7 @@ note: required by a bound in `is_transmutable`
--> $DIR/primitive_reprs_should_have_correct_length.rs:12:14
|
LL | pub fn is_transmutable<Src, Dst, Context>()
- | --------------- required by a bound in this
+ | --------------- required by a bound in this function
LL | where
LL | Dst: BikeshedIntrinsicFrom<Src, Context, {
| ______________^
@@ -446,7 +446,7 @@ note: required by a bound in `is_transmutable`
--> $DIR/primitive_reprs_should_have_correct_length.rs:12:14
|
LL | pub fn is_transmutable<Src, Dst, Context>()
- | --------------- required by a bound in this
+ | --------------- required by a bound in this function
LL | where
LL | Dst: BikeshedIntrinsicFrom<Src, Context, {
| ______________^
diff --git a/tests/ui/transmutability/enums/repr/should_require_well_defined_layout.stderr b/tests/ui/transmutability/enums/repr/should_require_well_defined_layout.stderr
index 510b8c56e..d456a746f 100644
--- a/tests/ui/transmutability/enums/repr/should_require_well_defined_layout.stderr
+++ b/tests/ui/transmutability/enums/repr/should_require_well_defined_layout.stderr
@@ -9,7 +9,7 @@ note: required by a bound in `is_maybe_transmutable`
--> $DIR/should_require_well_defined_layout.rs:14:14
|
LL | pub fn is_maybe_transmutable<Src, Dst>()
- | --------------------- required by a bound in this
+ | --------------------- required by a bound in this function
LL | where
LL | Dst: BikeshedIntrinsicFrom<Src, Context, {
| ______________^
@@ -32,7 +32,7 @@ note: required by a bound in `is_maybe_transmutable`
--> $DIR/should_require_well_defined_layout.rs:14:14
|
LL | pub fn is_maybe_transmutable<Src, Dst>()
- | --------------------- required by a bound in this
+ | --------------------- required by a bound in this function
LL | where
LL | Dst: BikeshedIntrinsicFrom<Src, Context, {
| ______________^
@@ -55,7 +55,7 @@ note: required by a bound in `is_maybe_transmutable`
--> $DIR/should_require_well_defined_layout.rs:14:14
|
LL | pub fn is_maybe_transmutable<Src, Dst>()
- | --------------------- required by a bound in this
+ | --------------------- required by a bound in this function
LL | where
LL | Dst: BikeshedIntrinsicFrom<Src, Context, {
| ______________^
@@ -78,7 +78,7 @@ note: required by a bound in `is_maybe_transmutable`
--> $DIR/should_require_well_defined_layout.rs:14:14
|
LL | pub fn is_maybe_transmutable<Src, Dst>()
- | --------------------- required by a bound in this
+ | --------------------- required by a bound in this function
LL | where
LL | Dst: BikeshedIntrinsicFrom<Src, Context, {
| ______________^
@@ -101,7 +101,7 @@ note: required by a bound in `is_maybe_transmutable`
--> $DIR/should_require_well_defined_layout.rs:14:14
|
LL | pub fn is_maybe_transmutable<Src, Dst>()
- | --------------------- required by a bound in this
+ | --------------------- required by a bound in this function
LL | where
LL | Dst: BikeshedIntrinsicFrom<Src, Context, {
| ______________^
@@ -124,7 +124,7 @@ note: required by a bound in `is_maybe_transmutable`
--> $DIR/should_require_well_defined_layout.rs:14:14
|
LL | pub fn is_maybe_transmutable<Src, Dst>()
- | --------------------- required by a bound in this
+ | --------------------- required by a bound in this function
LL | where
LL | Dst: BikeshedIntrinsicFrom<Src, Context, {
| ______________^
diff --git a/tests/ui/transmutability/enums/should_pad_variants.stderr b/tests/ui/transmutability/enums/should_pad_variants.stderr
index a823503d5..f4988239d 100644
--- a/tests/ui/transmutability/enums/should_pad_variants.stderr
+++ b/tests/ui/transmutability/enums/should_pad_variants.stderr
@@ -9,7 +9,7 @@ note: required by a bound in `is_transmutable`
--> $DIR/should_pad_variants.rs:13:14
|
LL | pub fn is_transmutable<Src, Dst, Context>()
- | --------------- required by a bound in this
+ | --------------- required by a bound in this function
LL | where
LL | Dst: BikeshedIntrinsicFrom<Src, Context, {
| ______________^
diff --git a/tests/ui/transmutability/enums/should_respect_endianness.stderr b/tests/ui/transmutability/enums/should_respect_endianness.stderr
index 0845a5edf..350583b0b 100644
--- a/tests/ui/transmutability/enums/should_respect_endianness.stderr
+++ b/tests/ui/transmutability/enums/should_respect_endianness.stderr
@@ -9,7 +9,7 @@ note: required by a bound in `is_transmutable`
--> $DIR/should_respect_endianness.rs:14:14
|
LL | pub fn is_transmutable<Src, Dst>()
- | --------------- required by a bound in this
+ | --------------- required by a bound in this function
LL | where
LL | Dst: BikeshedIntrinsicFrom<Src, Context, {
| ______________^
diff --git a/tests/ui/transmutability/issue-101739-1.stderr b/tests/ui/transmutability/issue-101739-1.stderr
index 5fa741f26..7c6b533ef 100644
--- a/tests/ui/transmutability/issue-101739-1.stderr
+++ b/tests/ui/transmutability/issue-101739-1.stderr
@@ -8,7 +8,7 @@ error[E0308]: mismatched types
--> $DIR/issue-101739-1.rs:8:50
|
LL | Dst: BikeshedIntrinsicFrom<Src, Context, ASSUME_ALIGNMENT>,
- | ^^^^^^^^^^^^^^^^ expected struct `Assume`, found `bool`
+ | ^^^^^^^^^^^^^^^^ expected `Assume`, found `bool`
error: aborting due to 2 previous errors
diff --git a/tests/ui/transmutability/issue-101739-2.rs b/tests/ui/transmutability/issue-101739-2.rs
index 964a7e49e..e5a56ccc9 100644
--- a/tests/ui/transmutability/issue-101739-2.rs
+++ b/tests/ui/transmutability/issue-101739-2.rs
@@ -15,7 +15,7 @@ mod assert {
const ASSUME_VISIBILITY: bool,
>()
where
- Dst: BikeshedIntrinsicFrom< //~ ERROR this trait takes at most 3 generic arguments but 6 generic arguments were supplied
+ Dst: BikeshedIntrinsicFrom< //~ ERROR trait takes at most 3 generic arguments but 6 generic arguments were supplied
Src,
Context,
ASSUME_ALIGNMENT,
diff --git a/tests/ui/transmutability/issue-101739-2.stderr b/tests/ui/transmutability/issue-101739-2.stderr
index 1b3d20259..420a9f330 100644
--- a/tests/ui/transmutability/issue-101739-2.stderr
+++ b/tests/ui/transmutability/issue-101739-2.stderr
@@ -1,4 +1,4 @@
-error[E0107]: this trait takes at most 3 generic arguments but 6 generic arguments were supplied
+error[E0107]: trait takes at most 3 generic arguments but 6 generic arguments were supplied
--> $DIR/issue-101739-2.rs:18:14
|
LL | Dst: BikeshedIntrinsicFrom<
diff --git a/tests/ui/transmutability/primitives/bool.stderr b/tests/ui/transmutability/primitives/bool.stderr
index 214b5e150..22decf15e 100644
--- a/tests/ui/transmutability/primitives/bool.stderr
+++ b/tests/ui/transmutability/primitives/bool.stderr
@@ -9,7 +9,7 @@ note: required by a bound in `is_transmutable`
--> $DIR/bool.rs:12:14
|
LL | pub fn is_transmutable<Src, Dst>()
- | --------------- required by a bound in this
+ | --------------- required by a bound in this function
LL | where
LL | Dst: BikeshedIntrinsicFrom<Src, Context, { Assume::SAFETY }>
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
diff --git a/tests/ui/transmutability/primitives/numbers.stderr b/tests/ui/transmutability/primitives/numbers.stderr
index 7cb7ca8e6..c04a0e82a 100644
--- a/tests/ui/transmutability/primitives/numbers.stderr
+++ b/tests/ui/transmutability/primitives/numbers.stderr
@@ -9,7 +9,7 @@ note: required by a bound in `is_transmutable`
--> $DIR/numbers.rs:12:14
|
LL | pub fn is_transmutable<Src, Dst>()
- | --------------- required by a bound in this
+ | --------------- required by a bound in this function
LL | where
LL | Dst: BikeshedIntrinsicFrom<Src, Context>
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
@@ -25,7 +25,7 @@ note: required by a bound in `is_transmutable`
--> $DIR/numbers.rs:12:14
|
LL | pub fn is_transmutable<Src, Dst>()
- | --------------- required by a bound in this
+ | --------------- required by a bound in this function
LL | where
LL | Dst: BikeshedIntrinsicFrom<Src, Context>
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
@@ -41,7 +41,7 @@ note: required by a bound in `is_transmutable`
--> $DIR/numbers.rs:12:14
|
LL | pub fn is_transmutable<Src, Dst>()
- | --------------- required by a bound in this
+ | --------------- required by a bound in this function
LL | where
LL | Dst: BikeshedIntrinsicFrom<Src, Context>
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
@@ -57,7 +57,7 @@ note: required by a bound in `is_transmutable`
--> $DIR/numbers.rs:12:14
|
LL | pub fn is_transmutable<Src, Dst>()
- | --------------- required by a bound in this
+ | --------------- required by a bound in this function
LL | where
LL | Dst: BikeshedIntrinsicFrom<Src, Context>
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
@@ -73,7 +73,7 @@ note: required by a bound in `is_transmutable`
--> $DIR/numbers.rs:12:14
|
LL | pub fn is_transmutable<Src, Dst>()
- | --------------- required by a bound in this
+ | --------------- required by a bound in this function
LL | where
LL | Dst: BikeshedIntrinsicFrom<Src, Context>
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
@@ -89,7 +89,7 @@ note: required by a bound in `is_transmutable`
--> $DIR/numbers.rs:12:14
|
LL | pub fn is_transmutable<Src, Dst>()
- | --------------- required by a bound in this
+ | --------------- required by a bound in this function
LL | where
LL | Dst: BikeshedIntrinsicFrom<Src, Context>
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
@@ -105,7 +105,7 @@ note: required by a bound in `is_transmutable`
--> $DIR/numbers.rs:12:14
|
LL | pub fn is_transmutable<Src, Dst>()
- | --------------- required by a bound in this
+ | --------------- required by a bound in this function
LL | where
LL | Dst: BikeshedIntrinsicFrom<Src, Context>
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
@@ -121,7 +121,7 @@ note: required by a bound in `is_transmutable`
--> $DIR/numbers.rs:12:14
|
LL | pub fn is_transmutable<Src, Dst>()
- | --------------- required by a bound in this
+ | --------------- required by a bound in this function
LL | where
LL | Dst: BikeshedIntrinsicFrom<Src, Context>
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
@@ -137,7 +137,7 @@ note: required by a bound in `is_transmutable`
--> $DIR/numbers.rs:12:14
|
LL | pub fn is_transmutable<Src, Dst>()
- | --------------- required by a bound in this
+ | --------------- required by a bound in this function
LL | where
LL | Dst: BikeshedIntrinsicFrom<Src, Context>
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
@@ -153,7 +153,7 @@ note: required by a bound in `is_transmutable`
--> $DIR/numbers.rs:12:14
|
LL | pub fn is_transmutable<Src, Dst>()
- | --------------- required by a bound in this
+ | --------------- required by a bound in this function
LL | where
LL | Dst: BikeshedIntrinsicFrom<Src, Context>
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
@@ -169,7 +169,7 @@ note: required by a bound in `is_transmutable`
--> $DIR/numbers.rs:12:14
|
LL | pub fn is_transmutable<Src, Dst>()
- | --------------- required by a bound in this
+ | --------------- required by a bound in this function
LL | where
LL | Dst: BikeshedIntrinsicFrom<Src, Context>
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
@@ -185,7 +185,7 @@ note: required by a bound in `is_transmutable`
--> $DIR/numbers.rs:12:14
|
LL | pub fn is_transmutable<Src, Dst>()
- | --------------- required by a bound in this
+ | --------------- required by a bound in this function
LL | where
LL | Dst: BikeshedIntrinsicFrom<Src, Context>
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
@@ -201,7 +201,7 @@ note: required by a bound in `is_transmutable`
--> $DIR/numbers.rs:12:14
|
LL | pub fn is_transmutable<Src, Dst>()
- | --------------- required by a bound in this
+ | --------------- required by a bound in this function
LL | where
LL | Dst: BikeshedIntrinsicFrom<Src, Context>
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
@@ -217,7 +217,7 @@ note: required by a bound in `is_transmutable`
--> $DIR/numbers.rs:12:14
|
LL | pub fn is_transmutable<Src, Dst>()
- | --------------- required by a bound in this
+ | --------------- required by a bound in this function
LL | where
LL | Dst: BikeshedIntrinsicFrom<Src, Context>
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
@@ -233,7 +233,7 @@ note: required by a bound in `is_transmutable`
--> $DIR/numbers.rs:12:14
|
LL | pub fn is_transmutable<Src, Dst>()
- | --------------- required by a bound in this
+ | --------------- required by a bound in this function
LL | where
LL | Dst: BikeshedIntrinsicFrom<Src, Context>
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
@@ -249,7 +249,7 @@ note: required by a bound in `is_transmutable`
--> $DIR/numbers.rs:12:14
|
LL | pub fn is_transmutable<Src, Dst>()
- | --------------- required by a bound in this
+ | --------------- required by a bound in this function
LL | where
LL | Dst: BikeshedIntrinsicFrom<Src, Context>
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
@@ -265,7 +265,7 @@ note: required by a bound in `is_transmutable`
--> $DIR/numbers.rs:12:14
|
LL | pub fn is_transmutable<Src, Dst>()
- | --------------- required by a bound in this
+ | --------------- required by a bound in this function
LL | where
LL | Dst: BikeshedIntrinsicFrom<Src, Context>
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
@@ -281,7 +281,7 @@ note: required by a bound in `is_transmutable`
--> $DIR/numbers.rs:12:14
|
LL | pub fn is_transmutable<Src, Dst>()
- | --------------- required by a bound in this
+ | --------------- required by a bound in this function
LL | where
LL | Dst: BikeshedIntrinsicFrom<Src, Context>
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
@@ -297,7 +297,7 @@ note: required by a bound in `is_transmutable`
--> $DIR/numbers.rs:12:14
|
LL | pub fn is_transmutable<Src, Dst>()
- | --------------- required by a bound in this
+ | --------------- required by a bound in this function
LL | where
LL | Dst: BikeshedIntrinsicFrom<Src, Context>
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
@@ -313,7 +313,7 @@ note: required by a bound in `is_transmutable`
--> $DIR/numbers.rs:12:14
|
LL | pub fn is_transmutable<Src, Dst>()
- | --------------- required by a bound in this
+ | --------------- required by a bound in this function
LL | where
LL | Dst: BikeshedIntrinsicFrom<Src, Context>
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
@@ -329,7 +329,7 @@ note: required by a bound in `is_transmutable`
--> $DIR/numbers.rs:12:14
|
LL | pub fn is_transmutable<Src, Dst>()
- | --------------- required by a bound in this
+ | --------------- required by a bound in this function
LL | where
LL | Dst: BikeshedIntrinsicFrom<Src, Context>
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
@@ -345,7 +345,7 @@ note: required by a bound in `is_transmutable`
--> $DIR/numbers.rs:12:14
|
LL | pub fn is_transmutable<Src, Dst>()
- | --------------- required by a bound in this
+ | --------------- required by a bound in this function
LL | where
LL | Dst: BikeshedIntrinsicFrom<Src, Context>
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
@@ -361,7 +361,7 @@ note: required by a bound in `is_transmutable`
--> $DIR/numbers.rs:12:14
|
LL | pub fn is_transmutable<Src, Dst>()
- | --------------- required by a bound in this
+ | --------------- required by a bound in this function
LL | where
LL | Dst: BikeshedIntrinsicFrom<Src, Context>
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
@@ -377,7 +377,7 @@ note: required by a bound in `is_transmutable`
--> $DIR/numbers.rs:12:14
|
LL | pub fn is_transmutable<Src, Dst>()
- | --------------- required by a bound in this
+ | --------------- required by a bound in this function
LL | where
LL | Dst: BikeshedIntrinsicFrom<Src, Context>
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
@@ -393,7 +393,7 @@ note: required by a bound in `is_transmutable`
--> $DIR/numbers.rs:12:14
|
LL | pub fn is_transmutable<Src, Dst>()
- | --------------- required by a bound in this
+ | --------------- required by a bound in this function
LL | where
LL | Dst: BikeshedIntrinsicFrom<Src, Context>
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
@@ -409,7 +409,7 @@ note: required by a bound in `is_transmutable`
--> $DIR/numbers.rs:12:14
|
LL | pub fn is_transmutable<Src, Dst>()
- | --------------- required by a bound in this
+ | --------------- required by a bound in this function
LL | where
LL | Dst: BikeshedIntrinsicFrom<Src, Context>
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
@@ -425,7 +425,7 @@ note: required by a bound in `is_transmutable`
--> $DIR/numbers.rs:12:14
|
LL | pub fn is_transmutable<Src, Dst>()
- | --------------- required by a bound in this
+ | --------------- required by a bound in this function
LL | where
LL | Dst: BikeshedIntrinsicFrom<Src, Context>
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
@@ -441,7 +441,7 @@ note: required by a bound in `is_transmutable`
--> $DIR/numbers.rs:12:14
|
LL | pub fn is_transmutable<Src, Dst>()
- | --------------- required by a bound in this
+ | --------------- required by a bound in this function
LL | where
LL | Dst: BikeshedIntrinsicFrom<Src, Context>
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
@@ -457,7 +457,7 @@ note: required by a bound in `is_transmutable`
--> $DIR/numbers.rs:12:14
|
LL | pub fn is_transmutable<Src, Dst>()
- | --------------- required by a bound in this
+ | --------------- required by a bound in this function
LL | where
LL | Dst: BikeshedIntrinsicFrom<Src, Context>
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
@@ -473,7 +473,7 @@ note: required by a bound in `is_transmutable`
--> $DIR/numbers.rs:12:14
|
LL | pub fn is_transmutable<Src, Dst>()
- | --------------- required by a bound in this
+ | --------------- required by a bound in this function
LL | where
LL | Dst: BikeshedIntrinsicFrom<Src, Context>
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
@@ -489,7 +489,7 @@ note: required by a bound in `is_transmutable`
--> $DIR/numbers.rs:12:14
|
LL | pub fn is_transmutable<Src, Dst>()
- | --------------- required by a bound in this
+ | --------------- required by a bound in this function
LL | where
LL | Dst: BikeshedIntrinsicFrom<Src, Context>
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
@@ -505,7 +505,7 @@ note: required by a bound in `is_transmutable`
--> $DIR/numbers.rs:12:14
|
LL | pub fn is_transmutable<Src, Dst>()
- | --------------- required by a bound in this
+ | --------------- required by a bound in this function
LL | where
LL | Dst: BikeshedIntrinsicFrom<Src, Context>
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
@@ -521,7 +521,7 @@ note: required by a bound in `is_transmutable`
--> $DIR/numbers.rs:12:14
|
LL | pub fn is_transmutable<Src, Dst>()
- | --------------- required by a bound in this
+ | --------------- required by a bound in this function
LL | where
LL | Dst: BikeshedIntrinsicFrom<Src, Context>
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
@@ -537,7 +537,7 @@ note: required by a bound in `is_transmutable`
--> $DIR/numbers.rs:12:14
|
LL | pub fn is_transmutable<Src, Dst>()
- | --------------- required by a bound in this
+ | --------------- required by a bound in this function
LL | where
LL | Dst: BikeshedIntrinsicFrom<Src, Context>
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
@@ -553,7 +553,7 @@ note: required by a bound in `is_transmutable`
--> $DIR/numbers.rs:12:14
|
LL | pub fn is_transmutable<Src, Dst>()
- | --------------- required by a bound in this
+ | --------------- required by a bound in this function
LL | where
LL | Dst: BikeshedIntrinsicFrom<Src, Context>
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
@@ -569,7 +569,7 @@ note: required by a bound in `is_transmutable`
--> $DIR/numbers.rs:12:14
|
LL | pub fn is_transmutable<Src, Dst>()
- | --------------- required by a bound in this
+ | --------------- required by a bound in this function
LL | where
LL | Dst: BikeshedIntrinsicFrom<Src, Context>
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
@@ -585,7 +585,7 @@ note: required by a bound in `is_transmutable`
--> $DIR/numbers.rs:12:14
|
LL | pub fn is_transmutable<Src, Dst>()
- | --------------- required by a bound in this
+ | --------------- required by a bound in this function
LL | where
LL | Dst: BikeshedIntrinsicFrom<Src, Context>
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
@@ -601,7 +601,7 @@ note: required by a bound in `is_transmutable`
--> $DIR/numbers.rs:12:14
|
LL | pub fn is_transmutable<Src, Dst>()
- | --------------- required by a bound in this
+ | --------------- required by a bound in this function
LL | where
LL | Dst: BikeshedIntrinsicFrom<Src, Context>
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
@@ -617,7 +617,7 @@ note: required by a bound in `is_transmutable`
--> $DIR/numbers.rs:12:14
|
LL | pub fn is_transmutable<Src, Dst>()
- | --------------- required by a bound in this
+ | --------------- required by a bound in this function
LL | where
LL | Dst: BikeshedIntrinsicFrom<Src, Context>
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
@@ -633,7 +633,7 @@ note: required by a bound in `is_transmutable`
--> $DIR/numbers.rs:12:14
|
LL | pub fn is_transmutable<Src, Dst>()
- | --------------- required by a bound in this
+ | --------------- required by a bound in this function
LL | where
LL | Dst: BikeshedIntrinsicFrom<Src, Context>
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
@@ -649,7 +649,7 @@ note: required by a bound in `is_transmutable`
--> $DIR/numbers.rs:12:14
|
LL | pub fn is_transmutable<Src, Dst>()
- | --------------- required by a bound in this
+ | --------------- required by a bound in this function
LL | where
LL | Dst: BikeshedIntrinsicFrom<Src, Context>
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
@@ -665,7 +665,7 @@ note: required by a bound in `is_transmutable`
--> $DIR/numbers.rs:12:14
|
LL | pub fn is_transmutable<Src, Dst>()
- | --------------- required by a bound in this
+ | --------------- required by a bound in this function
LL | where
LL | Dst: BikeshedIntrinsicFrom<Src, Context>
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
@@ -681,7 +681,7 @@ note: required by a bound in `is_transmutable`
--> $DIR/numbers.rs:12:14
|
LL | pub fn is_transmutable<Src, Dst>()
- | --------------- required by a bound in this
+ | --------------- required by a bound in this function
LL | where
LL | Dst: BikeshedIntrinsicFrom<Src, Context>
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
@@ -697,7 +697,7 @@ note: required by a bound in `is_transmutable`
--> $DIR/numbers.rs:12:14
|
LL | pub fn is_transmutable<Src, Dst>()
- | --------------- required by a bound in this
+ | --------------- required by a bound in this function
LL | where
LL | Dst: BikeshedIntrinsicFrom<Src, Context>
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
@@ -713,7 +713,7 @@ note: required by a bound in `is_transmutable`
--> $DIR/numbers.rs:12:14
|
LL | pub fn is_transmutable<Src, Dst>()
- | --------------- required by a bound in this
+ | --------------- required by a bound in this function
LL | where
LL | Dst: BikeshedIntrinsicFrom<Src, Context>
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
@@ -729,7 +729,7 @@ note: required by a bound in `is_transmutable`
--> $DIR/numbers.rs:12:14
|
LL | pub fn is_transmutable<Src, Dst>()
- | --------------- required by a bound in this
+ | --------------- required by a bound in this function
LL | where
LL | Dst: BikeshedIntrinsicFrom<Src, Context>
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
@@ -745,7 +745,7 @@ note: required by a bound in `is_transmutable`
--> $DIR/numbers.rs:12:14
|
LL | pub fn is_transmutable<Src, Dst>()
- | --------------- required by a bound in this
+ | --------------- required by a bound in this function
LL | where
LL | Dst: BikeshedIntrinsicFrom<Src, Context>
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
@@ -761,7 +761,7 @@ note: required by a bound in `is_transmutable`
--> $DIR/numbers.rs:12:14
|
LL | pub fn is_transmutable<Src, Dst>()
- | --------------- required by a bound in this
+ | --------------- required by a bound in this function
LL | where
LL | Dst: BikeshedIntrinsicFrom<Src, Context>
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
@@ -777,7 +777,7 @@ note: required by a bound in `is_transmutable`
--> $DIR/numbers.rs:12:14
|
LL | pub fn is_transmutable<Src, Dst>()
- | --------------- required by a bound in this
+ | --------------- required by a bound in this function
LL | where
LL | Dst: BikeshedIntrinsicFrom<Src, Context>
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
@@ -793,7 +793,7 @@ note: required by a bound in `is_transmutable`
--> $DIR/numbers.rs:12:14
|
LL | pub fn is_transmutable<Src, Dst>()
- | --------------- required by a bound in this
+ | --------------- required by a bound in this function
LL | where
LL | Dst: BikeshedIntrinsicFrom<Src, Context>
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
@@ -809,7 +809,7 @@ note: required by a bound in `is_transmutable`
--> $DIR/numbers.rs:12:14
|
LL | pub fn is_transmutable<Src, Dst>()
- | --------------- required by a bound in this
+ | --------------- required by a bound in this function
LL | where
LL | Dst: BikeshedIntrinsicFrom<Src, Context>
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
@@ -825,7 +825,7 @@ note: required by a bound in `is_transmutable`
--> $DIR/numbers.rs:12:14
|
LL | pub fn is_transmutable<Src, Dst>()
- | --------------- required by a bound in this
+ | --------------- required by a bound in this function
LL | where
LL | Dst: BikeshedIntrinsicFrom<Src, Context>
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
@@ -841,7 +841,7 @@ note: required by a bound in `is_transmutable`
--> $DIR/numbers.rs:12:14
|
LL | pub fn is_transmutable<Src, Dst>()
- | --------------- required by a bound in this
+ | --------------- required by a bound in this function
LL | where
LL | Dst: BikeshedIntrinsicFrom<Src, Context>
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
@@ -857,7 +857,7 @@ note: required by a bound in `is_transmutable`
--> $DIR/numbers.rs:12:14
|
LL | pub fn is_transmutable<Src, Dst>()
- | --------------- required by a bound in this
+ | --------------- required by a bound in this function
LL | where
LL | Dst: BikeshedIntrinsicFrom<Src, Context>
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
@@ -873,7 +873,7 @@ note: required by a bound in `is_transmutable`
--> $DIR/numbers.rs:12:14
|
LL | pub fn is_transmutable<Src, Dst>()
- | --------------- required by a bound in this
+ | --------------- required by a bound in this function
LL | where
LL | Dst: BikeshedIntrinsicFrom<Src, Context>
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
@@ -889,7 +889,7 @@ note: required by a bound in `is_transmutable`
--> $DIR/numbers.rs:12:14
|
LL | pub fn is_transmutable<Src, Dst>()
- | --------------- required by a bound in this
+ | --------------- required by a bound in this function
LL | where
LL | Dst: BikeshedIntrinsicFrom<Src, Context>
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
@@ -905,7 +905,7 @@ note: required by a bound in `is_transmutable`
--> $DIR/numbers.rs:12:14
|
LL | pub fn is_transmutable<Src, Dst>()
- | --------------- required by a bound in this
+ | --------------- required by a bound in this function
LL | where
LL | Dst: BikeshedIntrinsicFrom<Src, Context>
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
diff --git a/tests/ui/transmutability/primitives/unit.stderr b/tests/ui/transmutability/primitives/unit.stderr
index 8cabe44a0..988cd33b3 100644
--- a/tests/ui/transmutability/primitives/unit.stderr
+++ b/tests/ui/transmutability/primitives/unit.stderr
@@ -9,7 +9,7 @@ note: required by a bound in `is_transmutable`
--> $DIR/unit.rs:12:14
|
LL | pub fn is_transmutable<Src, Dst, Context>()
- | --------------- required by a bound in this
+ | --------------- required by a bound in this function
LL | where
LL | Dst: BikeshedIntrinsicFrom<Src, Context, {
| ______________^
diff --git a/tests/ui/transmutability/references.stderr b/tests/ui/transmutability/references.stderr
index e9c7b144a..eb3bd03fd 100644
--- a/tests/ui/transmutability/references.stderr
+++ b/tests/ui/transmutability/references.stderr
@@ -9,7 +9,7 @@ note: required by a bound in `is_maybe_transmutable`
--> $DIR/references.rs:13:14
|
LL | pub fn is_maybe_transmutable<Src, Dst>()
- | --------------------- required by a bound in this
+ | --------------------- required by a bound in this function
LL | where
LL | Dst: BikeshedIntrinsicFrom<Src, Context, {
| ______________^
diff --git a/tests/ui/transmutability/structs/repr/should_require_well_defined_layout.stderr b/tests/ui/transmutability/structs/repr/should_require_well_defined_layout.stderr
index 621dbee84..d9aebac64 100644
--- a/tests/ui/transmutability/structs/repr/should_require_well_defined_layout.stderr
+++ b/tests/ui/transmutability/structs/repr/should_require_well_defined_layout.stderr
@@ -9,7 +9,7 @@ note: required by a bound in `is_maybe_transmutable`
--> $DIR/should_require_well_defined_layout.rs:13:14
|
LL | pub fn is_maybe_transmutable<Src, Dst>()
- | --------------------- required by a bound in this
+ | --------------------- required by a bound in this function
LL | where
LL | Dst: BikeshedIntrinsicFrom<Src, Context, {
| ______________^
@@ -32,7 +32,7 @@ note: required by a bound in `is_maybe_transmutable`
--> $DIR/should_require_well_defined_layout.rs:13:14
|
LL | pub fn is_maybe_transmutable<Src, Dst>()
- | --------------------- required by a bound in this
+ | --------------------- required by a bound in this function
LL | where
LL | Dst: BikeshedIntrinsicFrom<Src, Context, {
| ______________^
@@ -55,7 +55,7 @@ note: required by a bound in `is_maybe_transmutable`
--> $DIR/should_require_well_defined_layout.rs:13:14
|
LL | pub fn is_maybe_transmutable<Src, Dst>()
- | --------------------- required by a bound in this
+ | --------------------- required by a bound in this function
LL | where
LL | Dst: BikeshedIntrinsicFrom<Src, Context, {
| ______________^
@@ -78,7 +78,7 @@ note: required by a bound in `is_maybe_transmutable`
--> $DIR/should_require_well_defined_layout.rs:13:14
|
LL | pub fn is_maybe_transmutable<Src, Dst>()
- | --------------------- required by a bound in this
+ | --------------------- required by a bound in this function
LL | where
LL | Dst: BikeshedIntrinsicFrom<Src, Context, {
| ______________^
@@ -101,7 +101,7 @@ note: required by a bound in `is_maybe_transmutable`
--> $DIR/should_require_well_defined_layout.rs:13:14
|
LL | pub fn is_maybe_transmutable<Src, Dst>()
- | --------------------- required by a bound in this
+ | --------------------- required by a bound in this function
LL | where
LL | Dst: BikeshedIntrinsicFrom<Src, Context, {
| ______________^
@@ -124,7 +124,7 @@ note: required by a bound in `is_maybe_transmutable`
--> $DIR/should_require_well_defined_layout.rs:13:14
|
LL | pub fn is_maybe_transmutable<Src, Dst>()
- | --------------------- required by a bound in this
+ | --------------------- required by a bound in this function
LL | where
LL | Dst: BikeshedIntrinsicFrom<Src, Context, {
| ______________^
@@ -147,7 +147,7 @@ note: required by a bound in `is_maybe_transmutable`
--> $DIR/should_require_well_defined_layout.rs:13:14
|
LL | pub fn is_maybe_transmutable<Src, Dst>()
- | --------------------- required by a bound in this
+ | --------------------- required by a bound in this function
LL | where
LL | Dst: BikeshedIntrinsicFrom<Src, Context, {
| ______________^
@@ -170,7 +170,7 @@ note: required by a bound in `is_maybe_transmutable`
--> $DIR/should_require_well_defined_layout.rs:13:14
|
LL | pub fn is_maybe_transmutable<Src, Dst>()
- | --------------------- required by a bound in this
+ | --------------------- required by a bound in this function
LL | where
LL | Dst: BikeshedIntrinsicFrom<Src, Context, {
| ______________^
@@ -193,7 +193,7 @@ note: required by a bound in `is_maybe_transmutable`
--> $DIR/should_require_well_defined_layout.rs:13:14
|
LL | pub fn is_maybe_transmutable<Src, Dst>()
- | --------------------- required by a bound in this
+ | --------------------- required by a bound in this function
LL | where
LL | Dst: BikeshedIntrinsicFrom<Src, Context, {
| ______________^
@@ -216,7 +216,7 @@ note: required by a bound in `is_maybe_transmutable`
--> $DIR/should_require_well_defined_layout.rs:13:14
|
LL | pub fn is_maybe_transmutable<Src, Dst>()
- | --------------------- required by a bound in this
+ | --------------------- required by a bound in this function
LL | where
LL | Dst: BikeshedIntrinsicFrom<Src, Context, {
| ______________^
@@ -239,7 +239,7 @@ note: required by a bound in `is_maybe_transmutable`
--> $DIR/should_require_well_defined_layout.rs:13:14
|
LL | pub fn is_maybe_transmutable<Src, Dst>()
- | --------------------- required by a bound in this
+ | --------------------- required by a bound in this function
LL | where
LL | Dst: BikeshedIntrinsicFrom<Src, Context, {
| ______________^
@@ -262,7 +262,7 @@ note: required by a bound in `is_maybe_transmutable`
--> $DIR/should_require_well_defined_layout.rs:13:14
|
LL | pub fn is_maybe_transmutable<Src, Dst>()
- | --------------------- required by a bound in this
+ | --------------------- required by a bound in this function
LL | where
LL | Dst: BikeshedIntrinsicFrom<Src, Context, {
| ______________^
diff --git a/tests/ui/transmutability/unions/repr/should_require_well_defined_layout.stderr b/tests/ui/transmutability/unions/repr/should_require_well_defined_layout.stderr
index 523bde85a..aa0cbc51b 100644
--- a/tests/ui/transmutability/unions/repr/should_require_well_defined_layout.stderr
+++ b/tests/ui/transmutability/unions/repr/should_require_well_defined_layout.stderr
@@ -9,7 +9,7 @@ note: required by a bound in `is_maybe_transmutable`
--> $DIR/should_require_well_defined_layout.rs:13:14
|
LL | pub fn is_maybe_transmutable<Src, Dst>()
- | --------------------- required by a bound in this
+ | --------------------- required by a bound in this function
LL | where
LL | Dst: BikeshedIntrinsicFrom<Src, Context, {
| ______________^
@@ -32,7 +32,7 @@ note: required by a bound in `is_maybe_transmutable`
--> $DIR/should_require_well_defined_layout.rs:13:14
|
LL | pub fn is_maybe_transmutable<Src, Dst>()
- | --------------------- required by a bound in this
+ | --------------------- required by a bound in this function
LL | where
LL | Dst: BikeshedIntrinsicFrom<Src, Context, {
| ______________^
diff --git a/tests/ui/transmutability/unions/should_pad_variants.stderr b/tests/ui/transmutability/unions/should_pad_variants.stderr
index a823503d5..f4988239d 100644
--- a/tests/ui/transmutability/unions/should_pad_variants.stderr
+++ b/tests/ui/transmutability/unions/should_pad_variants.stderr
@@ -9,7 +9,7 @@ note: required by a bound in `is_transmutable`
--> $DIR/should_pad_variants.rs:13:14
|
LL | pub fn is_transmutable<Src, Dst, Context>()
- | --------------- required by a bound in this
+ | --------------- required by a bound in this function
LL | where
LL | Dst: BikeshedIntrinsicFrom<Src, Context, {
| ______________^
diff --git a/tests/ui/transmutability/unions/should_reject_contraction.stderr b/tests/ui/transmutability/unions/should_reject_contraction.stderr
index 41f0cedc3..fa7dcc3d2 100644
--- a/tests/ui/transmutability/unions/should_reject_contraction.stderr
+++ b/tests/ui/transmutability/unions/should_reject_contraction.stderr
@@ -9,7 +9,7 @@ note: required by a bound in `is_transmutable`
--> $DIR/should_reject_contraction.rs:13:14
|
LL | pub fn is_transmutable<Src, Dst>()
- | --------------- required by a bound in this
+ | --------------- required by a bound in this function
LL | where
LL | Dst: BikeshedIntrinsicFrom<Src, Context, { Assume::SAFETY }>
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
diff --git a/tests/ui/transmutability/unions/should_reject_disjoint.stderr b/tests/ui/transmutability/unions/should_reject_disjoint.stderr
index 4323f9740..880e4cd89 100644
--- a/tests/ui/transmutability/unions/should_reject_disjoint.stderr
+++ b/tests/ui/transmutability/unions/should_reject_disjoint.stderr
@@ -9,7 +9,7 @@ note: required by a bound in `is_maybe_transmutable`
--> $DIR/should_reject_disjoint.rs:13:14
|
LL | pub fn is_maybe_transmutable<Src, Dst>()
- | --------------------- required by a bound in this
+ | --------------------- required by a bound in this function
LL | where
LL | Dst: BikeshedIntrinsicFrom<Src, Context, { Assume::SAFETY.and(Assume::VALIDITY) }>
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_maybe_transmutable`
@@ -25,7 +25,7 @@ note: required by a bound in `is_maybe_transmutable`
--> $DIR/should_reject_disjoint.rs:13:14
|
LL | pub fn is_maybe_transmutable<Src, Dst>()
- | --------------------- required by a bound in this
+ | --------------------- required by a bound in this function
LL | where
LL | Dst: BikeshedIntrinsicFrom<Src, Context, { Assume::SAFETY.and(Assume::VALIDITY) }>
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_maybe_transmutable`
diff --git a/tests/ui/transmutability/unions/should_reject_intersecting.stderr b/tests/ui/transmutability/unions/should_reject_intersecting.stderr
index e009888ae..501760b08 100644
--- a/tests/ui/transmutability/unions/should_reject_intersecting.stderr
+++ b/tests/ui/transmutability/unions/should_reject_intersecting.stderr
@@ -9,7 +9,7 @@ note: required by a bound in `is_transmutable`
--> $DIR/should_reject_intersecting.rs:14:14
|
LL | pub fn is_transmutable<Src, Dst>()
- | --------------- required by a bound in this
+ | --------------- required by a bound in this function
LL | where
LL | Dst: BikeshedIntrinsicFrom<Src, Context, { Assume::SAFETY }>
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
@@ -25,7 +25,7 @@ note: required by a bound in `is_transmutable`
--> $DIR/should_reject_intersecting.rs:14:14
|
LL | pub fn is_transmutable<Src, Dst>()
- | --------------- required by a bound in this
+ | --------------- required by a bound in this function
LL | where
LL | Dst: BikeshedIntrinsicFrom<Src, Context, { Assume::SAFETY }>
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
diff --git a/tests/ui/transmutability/visibility/should_reject_if_dst_has_private_field.stderr b/tests/ui/transmutability/visibility/should_reject_if_dst_has_private_field.stderr
index d5d6d431b..afbba653b 100644
--- a/tests/ui/transmutability/visibility/should_reject_if_dst_has_private_field.stderr
+++ b/tests/ui/transmutability/visibility/should_reject_if_dst_has_private_field.stderr
@@ -9,7 +9,7 @@ note: required by a bound in `is_transmutable`
--> $DIR/should_reject_if_dst_has_private_field.rs:13:14
|
LL | pub fn is_transmutable<Src, Dst, Context>()
- | --------------- required by a bound in this
+ | --------------- required by a bound in this function
LL | where
LL | Dst: BikeshedIntrinsicFrom<Src, Context> // safety is NOT assumed
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
diff --git a/tests/ui/transmutability/visibility/should_reject_if_dst_has_private_variant.stderr b/tests/ui/transmutability/visibility/should_reject_if_dst_has_private_variant.stderr
index a1ca2ced5..f14b5d8b2 100644
--- a/tests/ui/transmutability/visibility/should_reject_if_dst_has_private_variant.stderr
+++ b/tests/ui/transmutability/visibility/should_reject_if_dst_has_private_variant.stderr
@@ -9,7 +9,7 @@ note: required by a bound in `is_transmutable`
--> $DIR/should_reject_if_dst_has_private_variant.rs:13:14
|
LL | pub fn is_transmutable<Src, Dst, Context>()
- | --------------- required by a bound in this
+ | --------------- required by a bound in this function
LL | where
LL | Dst: BikeshedIntrinsicFrom<Src, Context> // safety is NOT assumed
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
diff --git a/tests/ui/transmutability/visibility/should_reject_if_dst_has_unreachable_field.stderr b/tests/ui/transmutability/visibility/should_reject_if_dst_has_unreachable_field.stderr
index 4e648664d..01ae8bea2 100644
--- a/tests/ui/transmutability/visibility/should_reject_if_dst_has_unreachable_field.stderr
+++ b/tests/ui/transmutability/visibility/should_reject_if_dst_has_unreachable_field.stderr
@@ -9,7 +9,7 @@ note: required by a bound in `is_transmutable`
--> $DIR/should_reject_if_dst_has_unreachable_field.rs:15:14
|
LL | pub fn is_transmutable<Src, Dst, Context>()
- | --------------- required by a bound in this
+ | --------------- required by a bound in this function
LL | where
LL | Dst: BikeshedIntrinsicFrom<Src, Context> // safety is NOT assumed
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
diff --git a/tests/ui/transmutability/visibility/should_reject_if_dst_has_unreachable_ty.stderr b/tests/ui/transmutability/visibility/should_reject_if_dst_has_unreachable_ty.stderr
index bd72d64cc..20a680a74 100644
--- a/tests/ui/transmutability/visibility/should_reject_if_dst_has_unreachable_ty.stderr
+++ b/tests/ui/transmutability/visibility/should_reject_if_dst_has_unreachable_ty.stderr
@@ -21,7 +21,7 @@ note: required by a bound in `is_transmutable`
--> $DIR/should_reject_if_dst_has_unreachable_ty.rs:15:14
|
LL | pub fn is_transmutable<Src, Dst, Context>()
- | --------------- required by a bound in this
+ | --------------- required by a bound in this function
LL | where
LL | Dst: BikeshedIntrinsicFrom<Src, Context> // safety is NOT assumed
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
diff --git a/tests/ui/transmute/transmute-padding-ice.stderr b/tests/ui/transmute/transmute-padding-ice.stderr
index c9233890f..87fd4fb66 100644
--- a/tests/ui/transmute/transmute-padding-ice.stderr
+++ b/tests/ui/transmute/transmute-padding-ice.stderr
@@ -9,7 +9,7 @@ note: required by a bound in `is_maybe_transmutable`
--> $DIR/transmute-padding-ice.rs:11:14
|
LL | pub fn is_maybe_transmutable<Src, Dst>()
- | --------------------- required by a bound in this
+ | --------------------- required by a bound in this function
LL | where
LL | Dst: BikeshedIntrinsicFrom<
| ______________^
diff --git a/tests/ui/treat-err-as-bug/delay_span_bug.stderr b/tests/ui/treat-err-as-bug/delay_span_bug.stderr
index e9457c8fa..22c617504 100644
--- a/tests/ui/treat-err-as-bug/delay_span_bug.stderr
+++ b/tests/ui/treat-err-as-bug/delay_span_bug.stderr
@@ -4,7 +4,7 @@ error: internal compiler error: delayed span bug triggered by #[rustc_error(dela
LL | fn main() {}
| ^^^^^^^^^
-error: internal compiler error: unexpected panic
+error: the compiler unexpectedly panicked. this is a bug.
query stack during panic:
#0 [trigger_delay_span_bug] triggering a delay span bug
diff --git a/tests/ui/treat-err-as-bug/err.stderr b/tests/ui/treat-err-as-bug/err.stderr
index 8f67571c2..3a56445a2 100644
--- a/tests/ui/treat-err-as-bug/err.stderr
+++ b/tests/ui/treat-err-as-bug/err.stderr
@@ -4,7 +4,7 @@ error[E0080]: could not evaluate static initializer
LL | pub static C: u32 = 0 - 1;
| ^^^^^ attempt to compute `0_u32 - 1_u32`, which would overflow
-error: internal compiler error: unexpected panic
+error: the compiler unexpectedly panicked. this is a bug.
query stack during panic:
#0 [eval_to_allocation_raw] const-evaluating + checking `C`
diff --git a/tests/ui/try-block/try-block-bad-lifetime.stderr b/tests/ui/try-block/try-block-bad-lifetime.stderr
index ea079e30d..28941cb0a 100644
--- a/tests/ui/try-block/try-block-bad-lifetime.stderr
+++ b/tests/ui/try-block/try-block-bad-lifetime.stderr
@@ -4,6 +4,7 @@ error[E0597]: `my_string` does not live long enough
LL | let result: Result<(), &str> = try {
| ------ borrow later stored here
LL | let my_string = String::from("");
+ | --------- binding `my_string` declared here
LL | let my_str: & str = & my_string;
| ^^^^^^^^^^^ borrowed value does not live long enough
...
@@ -14,10 +15,10 @@ error[E0506]: cannot assign to `i` because it is borrowed
--> $DIR/try-block-bad-lifetime.rs:29:13
|
LL | let k = &mut i;
- | ------ borrow of `i` occurs here
+ | ------ `i` is borrowed here
...
LL | i = 10;
- | ^^^^^^ assignment to borrowed `i` occurs here
+ | ^^^^^^ `i` is assigned to here but it was already borrowed
LL | };
LL | ::std::mem::drop(k);
| - borrow later used here
@@ -38,10 +39,10 @@ error[E0506]: cannot assign to `i` because it is borrowed
--> $DIR/try-block-bad-lifetime.rs:32:9
|
LL | let k = &mut i;
- | ------ borrow of `i` occurs here
+ | ------ `i` is borrowed here
...
LL | i = 40;
- | ^^^^^^ assignment to borrowed `i` occurs here
+ | ^^^^^^ `i` is assigned to here but it was already borrowed
LL |
LL | let i_ptr = if let Err(i_ptr) = j { i_ptr } else { panic ! ("") };
| - borrow later used here
diff --git a/tests/ui/try-block/try-block-maybe-bad-lifetime.stderr b/tests/ui/try-block/try-block-maybe-bad-lifetime.stderr
index f738b03ee..71c7e460c 100644
--- a/tests/ui/try-block/try-block-maybe-bad-lifetime.stderr
+++ b/tests/ui/try-block/try-block-maybe-bad-lifetime.stderr
@@ -2,10 +2,10 @@ error[E0506]: cannot assign to `i` because it is borrowed
--> $DIR/try-block-maybe-bad-lifetime.rs:17:9
|
LL | &i
- | -- borrow of `i` occurs here
+ | -- `i` is borrowed here
LL | };
LL | i = 0;
- | ^^^^^ assignment to borrowed `i` occurs here
+ | ^^^^^ `i` is assigned to here but it was already borrowed
LL | let _ = i;
LL | do_something_with(x);
| - borrow later used here
@@ -32,10 +32,10 @@ error[E0506]: cannot assign to `i` because it is borrowed
--> $DIR/try-block-maybe-bad-lifetime.rs:40:9
|
LL | j = &i;
- | -- borrow of `i` occurs here
+ | -- `i` is borrowed here
LL | };
LL | i = 0;
- | ^^^^^ assignment to borrowed `i` occurs here
+ | ^^^^^ `i` is assigned to here but it was already borrowed
LL | let _ = i;
LL | do_something_with(j);
| - borrow later used here
diff --git a/tests/ui/tuple/add-tuple-within-arguments.stderr b/tests/ui/tuple/add-tuple-within-arguments.stderr
index 2e20a4cca..6849128ea 100644
--- a/tests/ui/tuple/add-tuple-within-arguments.stderr
+++ b/tests/ui/tuple/add-tuple-within-arguments.stderr
@@ -18,7 +18,7 @@ error[E0308]: mismatched types
--> $DIR/add-tuple-within-arguments.rs:8:15
|
LL | bar("hi", "hi", "hi");
- | --- ^^^^ expected tuple, found `&str`
+ | --- ^^^^ expected `(&str,)`, found `&str`
| |
| arguments to this function are incorrect
|
diff --git a/tests/ui/tuple/wrong_argument_ice-3.stderr b/tests/ui/tuple/wrong_argument_ice-3.stderr
index 0a503e1fe..8b9dac6e2 100644
--- a/tests/ui/tuple/wrong_argument_ice-3.stderr
+++ b/tests/ui/tuple/wrong_argument_ice-3.stderr
@@ -2,21 +2,22 @@ error[E0061]: this method takes 1 argument but 2 arguments were supplied
--> $DIR/wrong_argument_ice-3.rs:9:16
|
LL | groups.push(new_group, vec![process]);
- | ^^^^ ------------- argument of type `Vec<&Process>` unexpected
+ | ^^^^ ------------- unexpected argument of type `Vec<&Process>`
|
-note: expected tuple, found struct `Vec`
+note: expected `(Vec<String>, Vec<Process>)`, found `Vec<String>`
--> $DIR/wrong_argument_ice-3.rs:9:21
|
LL | groups.push(new_group, vec![process]);
| ^^^^^^^^^
= note: expected tuple `(Vec<String>, Vec<Process>)`
found struct `Vec<String>`
-note: associated function defined here
+note: method defined here
--> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
help: remove the extra argument
|
-LL | groups.push(/* (Vec<String>, Vec<Process>) */);
- | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+LL - groups.push(new_group, vec![process]);
+LL + groups.push(/* (Vec<String>, Vec<Process>) */);
+ |
error: aborting due to previous error
diff --git a/tests/ui/tuple/wrong_argument_ice-4.stderr b/tests/ui/tuple/wrong_argument_ice-4.stderr
index a2686ab94..d8569ebf6 100644
--- a/tests/ui/tuple/wrong_argument_ice-4.stderr
+++ b/tests/ui/tuple/wrong_argument_ice-4.stderr
@@ -6,17 +6,16 @@ LL | (|| {})(|| {
LL | |
LL | | let b = 1;
LL | | });
- | |_____- argument of type `[closure@$DIR/wrong_argument_ice-4.rs:2:13: 2:15]` unexpected
+ | | -
+ | | |
+ | |_____unexpected argument of type `[closure@$DIR/wrong_argument_ice-4.rs:2:13: 2:15]`
+ | help: remove the extra argument
|
note: closure defined here
--> $DIR/wrong_argument_ice-4.rs:2:6
|
LL | (|| {})(|| {
| ^^
-help: remove the extra argument
- |
-LL | (|| {})();
- | ~~
error: aborting due to previous error
diff --git a/tests/ui/tuple/wrong_argument_ice.stderr b/tests/ui/tuple/wrong_argument_ice.stderr
index f1b00ae0b..213ca8f88 100644
--- a/tests/ui/tuple/wrong_argument_ice.stderr
+++ b/tests/ui/tuple/wrong_argument_ice.stderr
@@ -4,7 +4,7 @@ error[E0061]: method takes 1 argument but 2 arguments were supplied
LL | self.acc.push_back(self.current_provides, self.current_requires);
| ^^^^^^^^^
|
-note: associated function defined here
+note: method defined here
--> $SRC_DIR/alloc/src/collections/vec_deque/mod.rs:LL:COL
help: wrap these arguments in parentheses to construct a tuple
|
diff --git a/tests/ui/type-alias-enum-variants/enum-variant-generic-args.rs b/tests/ui/type-alias-enum-variants/enum-variant-generic-args.rs
index 0031a4665..759a7fd7e 100644
--- a/tests/ui/type-alias-enum-variants/enum-variant-generic-args.rs
+++ b/tests/ui/type-alias-enum-variants/enum-variant-generic-args.rs
@@ -62,10 +62,10 @@ fn main() {
AliasFixed::TSVariant::<()>(());
//~^ ERROR type arguments are not allowed on this type [E0109]
AliasFixed::<()>::TSVariant(());
- //~^ ERROR this type alias takes 0 generic arguments but 1 generic argument was supplied [E0107]
+ //~^ ERROR type alias takes 0 generic arguments but 1 generic argument was supplied [E0107]
AliasFixed::<()>::TSVariant::<()>(());
//~^ ERROR type arguments are not allowed on this type [E0109]
- //~| ERROR this type alias takes 0 generic arguments but 1 generic argument was supplied [E0107]
+ //~| ERROR type alias takes 0 generic arguments but 1 generic argument was supplied [E0107]
// Struct variant
@@ -80,10 +80,10 @@ fn main() {
AliasFixed::SVariant::<()> { v: () };
//~^ ERROR type arguments are not allowed on this type [E0109]
AliasFixed::<()>::SVariant { v: () };
- //~^ ERROR this type alias takes 0 generic arguments but 1 generic argument was supplied [E0107]
+ //~^ ERROR type alias takes 0 generic arguments but 1 generic argument was supplied [E0107]
AliasFixed::<()>::SVariant::<()> { v: () };
//~^ ERROR type arguments are not allowed on this type [E0109]
- //~| ERROR this type alias takes 0 generic arguments but 1 generic argument was supplied [E0107]
+ //~| ERROR type alias takes 0 generic arguments but 1 generic argument was supplied [E0107]
// Unit variant
@@ -98,8 +98,8 @@ fn main() {
AliasFixed::UVariant::<()>;
//~^ ERROR type arguments are not allowed on this type [E0109]
AliasFixed::<()>::UVariant;
- //~^ ERROR this type alias takes 0 generic arguments but 1 generic argument was supplied [E0107]
+ //~^ ERROR type alias takes 0 generic arguments but 1 generic argument was supplied [E0107]
AliasFixed::<()>::UVariant::<()>;
//~^ ERROR type arguments are not allowed on this type [E0109]
- //~| ERROR this type alias takes 0 generic arguments but 1 generic argument was supplied [E0107]
+ //~| ERROR type alias takes 0 generic arguments but 1 generic argument was supplied [E0107]
}
diff --git a/tests/ui/type-alias-enum-variants/enum-variant-generic-args.stderr b/tests/ui/type-alias-enum-variants/enum-variant-generic-args.stderr
index a922d7a5e..758ff31ff 100644
--- a/tests/ui/type-alias-enum-variants/enum-variant-generic-args.stderr
+++ b/tests/ui/type-alias-enum-variants/enum-variant-generic-args.stderr
@@ -304,7 +304,7 @@ LL | AliasFixed::TSVariant::<()>(());
| |
| not allowed on this type
-error[E0107]: this type alias takes 0 generic arguments but 1 generic argument was supplied
+error[E0107]: type alias takes 0 generic arguments but 1 generic argument was supplied
--> $DIR/enum-variant-generic-args.rs:64:5
|
LL | AliasFixed::<()>::TSVariant(());
@@ -318,7 +318,7 @@ note: type alias defined here, with 0 generic parameters
LL | type AliasFixed = Enum<()>;
| ^^^^^^^^^^
-error[E0107]: this type alias takes 0 generic arguments but 1 generic argument was supplied
+error[E0107]: type alias takes 0 generic arguments but 1 generic argument was supplied
--> $DIR/enum-variant-generic-args.rs:66:5
|
LL | AliasFixed::<()>::TSVariant::<()>(());
@@ -395,7 +395,7 @@ LL - AliasFixed::SVariant::<()> { v: () };
LL + AliasFixed::<()>::SVariant { v: () };
|
-error[E0107]: this type alias takes 0 generic arguments but 1 generic argument was supplied
+error[E0107]: type alias takes 0 generic arguments but 1 generic argument was supplied
--> $DIR/enum-variant-generic-args.rs:82:5
|
LL | AliasFixed::<()>::SVariant { v: () };
@@ -409,7 +409,7 @@ note: type alias defined here, with 0 generic parameters
LL | type AliasFixed = Enum<()>;
| ^^^^^^^^^^
-error[E0107]: this type alias takes 0 generic arguments but 1 generic argument was supplied
+error[E0107]: type alias takes 0 generic arguments but 1 generic argument was supplied
--> $DIR/enum-variant-generic-args.rs:84:5
|
LL | AliasFixed::<()>::SVariant::<()> { v: () };
@@ -470,7 +470,7 @@ LL | AliasFixed::UVariant::<()>;
| |
| not allowed on this type
-error[E0107]: this type alias takes 0 generic arguments but 1 generic argument was supplied
+error[E0107]: type alias takes 0 generic arguments but 1 generic argument was supplied
--> $DIR/enum-variant-generic-args.rs:100:5
|
LL | AliasFixed::<()>::UVariant;
@@ -484,7 +484,7 @@ note: type alias defined here, with 0 generic parameters
LL | type AliasFixed = Enum<()>;
| ^^^^^^^^^^
-error[E0107]: this type alias takes 0 generic arguments but 1 generic argument was supplied
+error[E0107]: type alias takes 0 generic arguments but 1 generic argument was supplied
--> $DIR/enum-variant-generic-args.rs:102:5
|
LL | AliasFixed::<()>::UVariant::<()>;
diff --git a/tests/ui/type-alias-enum-variants/enum-variant-priority-higher-than-other-inherent.stderr b/tests/ui/type-alias-enum-variants/enum-variant-priority-higher-than-other-inherent.stderr
index eb58ee73c..db75a520c 100644
--- a/tests/ui/type-alias-enum-variants/enum-variant-priority-higher-than-other-inherent.stderr
+++ b/tests/ui/type-alias-enum-variants/enum-variant-priority-higher-than-other-inherent.stderr
@@ -18,7 +18,7 @@ error[E0308]: mismatched types
--> $DIR/enum-variant-priority-higher-than-other-inherent.rs:22:17
|
LL | let _: u8 = <E2>::V;
- | -- ^^^^^^^ expected `u8`, found enum `E2`
+ | -- ^^^^^^^ expected `u8`, found `E2`
| |
| expected due to this
diff --git a/tests/ui/type-alias-impl-trait/bounds-are-checked.rs b/tests/ui/type-alias-impl-trait/bounds-are-checked.rs
index 83d22161e..7c3a3a844 100644
--- a/tests/ui/type-alias-impl-trait/bounds-are-checked.rs
+++ b/tests/ui/type-alias-impl-trait/bounds-are-checked.rs
@@ -6,9 +6,8 @@
type X<'a> = impl Into<&'static str> + From<&'a str>;
fn f<'a: 'static>(t: &'a str) -> X<'a> {
- //~^ WARNING unnecessary lifetime parameter
t
- //~^ ERROR non-defining opaque type use
+ //~^ ERROR expected generic lifetime parameter, found `'static`
}
fn extend_lt<'a>(o: &'a str) -> &'static str {
diff --git a/tests/ui/type-alias-impl-trait/bounds-are-checked.stderr b/tests/ui/type-alias-impl-trait/bounds-are-checked.stderr
index 920eef11d..962dedde0 100644
--- a/tests/ui/type-alias-impl-trait/bounds-are-checked.stderr
+++ b/tests/ui/type-alias-impl-trait/bounds-are-checked.stderr
@@ -1,13 +1,5 @@
-warning: unnecessary lifetime parameter `'a`
- --> $DIR/bounds-are-checked.rs:8:6
- |
-LL | fn f<'a: 'static>(t: &'a str) -> X<'a> {
- | ^^
- |
- = help: you can use the `'static` lifetime directly, in place of `'a`
-
-error: non-defining opaque type use in defining scope
- --> $DIR/bounds-are-checked.rs:10:5
+error[E0792]: expected generic lifetime parameter, found `'static`
+ --> $DIR/bounds-are-checked.rs:9:5
|
LL | type X<'a> = impl Into<&'static str> + From<&'a str>;
| -- cannot use static lifetime; use a bound lifetime instead or remove the lifetime parameter from the opaque type
@@ -15,5 +7,6 @@ LL | type X<'a> = impl Into<&'static str> + From<&'a str>;
LL | t
| ^
-error: aborting due to previous error; 1 warning emitted
+error: aborting due to previous error
+For more information about this error, try `rustc --explain E0792`.
diff --git a/tests/ui/type-alias-impl-trait/generic_nondefining_use.rs b/tests/ui/type-alias-impl-trait/generic_nondefining_use.rs
index f5045d382..e7b8567b9 100644
--- a/tests/ui/type-alias-impl-trait/generic_nondefining_use.rs
+++ b/tests/ui/type-alias-impl-trait/generic_nondefining_use.rs
@@ -19,7 +19,7 @@ fn concrete_ty() -> OneTy<u32> {
fn concrete_lifetime() -> OneLifetime<'static> {
6u32
- //~^ ERROR non-defining opaque type use in defining scope
+ //~^ ERROR expected generic lifetime parameter, found `'static`
}
fn concrete_const() -> OneConst<{ 123 }> {
diff --git a/tests/ui/type-alias-impl-trait/generic_nondefining_use.stderr b/tests/ui/type-alias-impl-trait/generic_nondefining_use.stderr
index 564648630..966fe823f 100644
--- a/tests/ui/type-alias-impl-trait/generic_nondefining_use.stderr
+++ b/tests/ui/type-alias-impl-trait/generic_nondefining_use.stderr
@@ -7,7 +7,7 @@ LL | type OneTy<T> = impl Debug;
LL | 5u32
| ^^^^
-error: non-defining opaque type use in defining scope
+error[E0792]: expected generic lifetime parameter, found `'static`
--> $DIR/generic_nondefining_use.rs:21:5
|
LL | type OneLifetime<'a> = impl Debug;
diff --git a/tests/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.rs b/tests/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.rs
index d3e169a70..cdd8f6f19 100644
--- a/tests/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.rs
+++ b/tests/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.rs
@@ -4,7 +4,7 @@ fn main() {
let y = 42;
let x = wrong_generic(&y);
let z: i32 = x;
- //~^ ERROR expected generic type parameter, found `&'static i32
+ //~^ ERROR expected generic type parameter, found `&i32`
}
type WrongGeneric<T> = impl 'static;
diff --git a/tests/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.stderr b/tests/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.stderr
index 19115fd28..fa79e51e9 100644
--- a/tests/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.stderr
+++ b/tests/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.stderr
@@ -4,7 +4,7 @@ error: at least one trait must be specified
LL | type WrongGeneric<T> = impl 'static;
| ^^^^^^^^^^^^
-error[E0792]: expected generic type parameter, found `&'static i32`
+error[E0792]: expected generic type parameter, found `&i32`
--> $DIR/generic_type_does_not_live_long_enough.rs:6:18
|
LL | let z: i32 = x;
diff --git a/tests/ui/type-alias-impl-trait/implied_lifetime_wf_check3.rs b/tests/ui/type-alias-impl-trait/implied_lifetime_wf_check3.rs
index 07f825aea..6f9434255 100644
--- a/tests/ui/type-alias-impl-trait/implied_lifetime_wf_check3.rs
+++ b/tests/ui/type-alias-impl-trait/implied_lifetime_wf_check3.rs
@@ -4,7 +4,6 @@ mod test_lifetime_param {
type Ty<'a> = impl Sized + 'a;
fn defining(a: &str) -> Ty<'_> { a }
fn assert_static<'a: 'static>() {}
- //~^ WARN: unnecessary lifetime parameter `'a`
fn test<'a>() where Ty<'a>: 'static { assert_static::<'a>() }
//~^ ERROR: lifetime may not live long enough
}
@@ -13,14 +12,12 @@ mod test_higher_kinded_lifetime_param {
type Ty<'a> = impl Sized + 'a;
fn defining(a: &str) -> Ty<'_> { a }
fn assert_static<'a: 'static>() {}
- //~^ WARN: unnecessary lifetime parameter `'a`
fn test<'a>() where for<'b> Ty<'b>: 'a { assert_static::<'a>() }
//~^ ERROR: lifetime may not live long enough
}
mod test_higher_kinded_lifetime_param2 {
fn assert_static<'a: 'static>() {}
- //~^ WARN: unnecessary lifetime parameter `'a`
fn test<'a>() { assert_static::<'a>() }
//~^ ERROR: lifetime may not live long enough
}
diff --git a/tests/ui/type-alias-impl-trait/implied_lifetime_wf_check3.stderr b/tests/ui/type-alias-impl-trait/implied_lifetime_wf_check3.stderr
index 887620a4d..399775641 100644
--- a/tests/ui/type-alias-impl-trait/implied_lifetime_wf_check3.stderr
+++ b/tests/ui/type-alias-impl-trait/implied_lifetime_wf_check3.stderr
@@ -1,41 +1,17 @@
-warning: unnecessary lifetime parameter `'a`
- --> $DIR/implied_lifetime_wf_check3.rs:6:22
- |
-LL | fn assert_static<'a: 'static>() {}
- | ^^
- |
- = help: you can use the `'static` lifetime directly, in place of `'a`
-
-warning: unnecessary lifetime parameter `'a`
- --> $DIR/implied_lifetime_wf_check3.rs:15:22
- |
-LL | fn assert_static<'a: 'static>() {}
- | ^^
- |
- = help: you can use the `'static` lifetime directly, in place of `'a`
-
-warning: unnecessary lifetime parameter `'a`
- --> $DIR/implied_lifetime_wf_check3.rs:22:22
- |
-LL | fn assert_static<'a: 'static>() {}
- | ^^
- |
- = help: you can use the `'static` lifetime directly, in place of `'a`
-
error: lifetime may not live long enough
- --> $DIR/implied_lifetime_wf_check3.rs:8:43
+ --> $DIR/implied_lifetime_wf_check3.rs:7:43
|
LL | fn test<'a>() where Ty<'a>: 'static { assert_static::<'a>() }
| -- lifetime `'a` defined here ^^^^^^^^^^^^^^^^^^^ requires that `'a` must outlive `'static`
error: lifetime may not live long enough
- --> $DIR/implied_lifetime_wf_check3.rs:17:46
+ --> $DIR/implied_lifetime_wf_check3.rs:15:46
|
LL | fn test<'a>() where for<'b> Ty<'b>: 'a { assert_static::<'a>() }
| -- lifetime `'a` defined here ^^^^^^^^^^^^^^^^^^^ requires that `'a` must outlive `'static`
error: lifetime may not live long enough
- --> $DIR/implied_lifetime_wf_check3.rs:24:21
+ --> $DIR/implied_lifetime_wf_check3.rs:21:21
|
LL | fn test<'a>() { assert_static::<'a>() }
| -- ^^^^^^^^^^^^^^^^^^^ requires that `'a` must outlive `'static`
@@ -43,7 +19,7 @@ LL | fn test<'a>() { assert_static::<'a>() }
| lifetime `'a` defined here
error[E0310]: the parameter type `A` may not live long enough
- --> $DIR/implied_lifetime_wf_check3.rs:32:41
+ --> $DIR/implied_lifetime_wf_check3.rs:29:41
|
LL | fn test<A>() where Ty<A>: 'static { assert_static::<A>() }
| ^^^^^^^^^^^^^^^^^^ ...so that the type `A` will meet its required lifetime bounds
@@ -53,6 +29,6 @@ help: consider adding an explicit lifetime bound...
LL | fn test<A: 'static>() where Ty<A>: 'static { assert_static::<A>() }
| +++++++++
-error: aborting due to 4 previous errors; 3 warnings emitted
+error: aborting due to 4 previous errors
For more information about this error, try `rustc --explain E0310`.
diff --git a/tests/ui/type-alias-impl-trait/imply_bounds_from_bounds_param.stderr b/tests/ui/type-alias-impl-trait/imply_bounds_from_bounds_param.stderr
index 0ed8a703b..e52d5f9de 100644
--- a/tests/ui/type-alias-impl-trait/imply_bounds_from_bounds_param.stderr
+++ b/tests/ui/type-alias-impl-trait/imply_bounds_from_bounds_param.stderr
@@ -2,7 +2,9 @@ error[E0700]: hidden type for `impl PlusOne` captures lifetime that does not app
--> $DIR/imply_bounds_from_bounds_param.rs:24:5
|
LL | fn test<'a>(y: &'a mut i32) -> impl PlusOne {
- | -- hidden type `<&'a mut i32 as Callable>::Output` captures the lifetime `'a` as defined here
+ | -- ------------ opaque type defined here
+ | |
+ | hidden type `<&'a mut i32 as Callable>::Output` captures the lifetime `'a` as defined here
LL | <&'a mut i32 as Callable>::call(y)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
diff --git a/tests/ui/type-alias-impl-trait/issue-63279.rs b/tests/ui/type-alias-impl-trait/issue-63279.rs
index 97332e16d..0e46745c6 100644
--- a/tests/ui/type-alias-impl-trait/issue-63279.rs
+++ b/tests/ui/type-alias-impl-trait/issue-63279.rs
@@ -1,5 +1,3 @@
-// compile-flags: -Zsave-analysis
-
#![feature(type_alias_impl_trait)]
type Closure = impl FnOnce();
diff --git a/tests/ui/type-alias-impl-trait/issue-63279.stderr b/tests/ui/type-alias-impl-trait/issue-63279.stderr
index 110b8d1ee..a4f6359b9 100644
--- a/tests/ui/type-alias-impl-trait/issue-63279.stderr
+++ b/tests/ui/type-alias-impl-trait/issue-63279.stderr
@@ -1,5 +1,5 @@
error[E0277]: expected a `FnOnce<()>` closure, found `()`
- --> $DIR/issue-63279.rs:7:11
+ --> $DIR/issue-63279.rs:5:11
|
LL | fn c() -> Closure {
| ^^^^^^^ expected an `FnOnce<()>` closure, found `()`
@@ -8,7 +8,7 @@ LL | fn c() -> Closure {
= note: wrap the `()` in a closure with no arguments: `|| { /* code */ }`
error[E0277]: expected a `FnOnce<()>` closure, found `()`
- --> $DIR/issue-63279.rs:9:11
+ --> $DIR/issue-63279.rs:7:11
|
LL | || -> Closure { || () }
| ^^^^^^^ expected an `FnOnce<()>` closure, found `()`
@@ -17,26 +17,26 @@ LL | || -> Closure { || () }
= note: wrap the `()` in a closure with no arguments: `|| { /* code */ }`
error[E0308]: mismatched types
- --> $DIR/issue-63279.rs:9:21
+ --> $DIR/issue-63279.rs:7:21
|
LL | || -> Closure { || () }
| ^^^^^ expected `()`, found closure
|
= note: expected unit type `()`
- found closure `[closure@$DIR/issue-63279.rs:9:21: 9:23]`
+ found closure `[closure@$DIR/issue-63279.rs:7:21: 7:23]`
help: use parentheses to call this closure
|
LL | || -> Closure { (|| ())() }
| + +++
error[E0308]: mismatched types
- --> $DIR/issue-63279.rs:9:5
+ --> $DIR/issue-63279.rs:7:5
|
LL | || -> Closure { || () }
| ^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found closure
|
= note: expected unit type `()`
- found closure `[closure@$DIR/issue-63279.rs:9:5: 9:18]`
+ found closure `[closure@$DIR/issue-63279.rs:7:5: 7:18]`
help: use parentheses to call this closure
|
LL | (|| -> Closure { || () })()
diff --git a/tests/ui/type-alias-impl-trait/issue-65679-inst-opaque-ty-from-val-twice.rs b/tests/ui/type-alias-impl-trait/issue-65679-inst-opaque-ty-from-val-twice.rs
index 72c22827f..b91cbce37 100644
--- a/tests/ui/type-alias-impl-trait/issue-65679-inst-opaque-ty-from-val-twice.rs
+++ b/tests/ui/type-alias-impl-trait/issue-65679-inst-opaque-ty-from-val-twice.rs
@@ -1,4 +1,3 @@
-// compile-flags: -Zsave-analysis
// check-pass
#![feature(type_alias_impl_trait, rustc_attrs)]
diff --git a/tests/ui/type-alias-impl-trait/issue-98604.rs b/tests/ui/type-alias-impl-trait/issue-98604.rs
index 32c2f9ed5..d07fc9822 100644
--- a/tests/ui/type-alias-impl-trait/issue-98604.rs
+++ b/tests/ui/type-alias-impl-trait/issue-98604.rs
@@ -7,5 +7,5 @@ async fn test() {}
#[allow(unused_must_use)]
fn main() {
Box::new(test) as AsyncFnPtr;
- //~^ ERROR expected `fn() -> impl Future<Output = ()> {test}` to be a fn item that returns `Pin<Box<(dyn Future<Output = ()> + 'static)>>`, but it returns `impl Future<Output = ()>`
+ //~^ ERROR expected `test` to be a fn item that returns `Pin<Box<dyn Future<Output = ()>>>`, but it returns `impl Future<Output = ()>
}
diff --git a/tests/ui/type-alias-impl-trait/issue-98604.stderr b/tests/ui/type-alias-impl-trait/issue-98604.stderr
index 92d01eb0d..fa16d3218 100644
--- a/tests/ui/type-alias-impl-trait/issue-98604.stderr
+++ b/tests/ui/type-alias-impl-trait/issue-98604.stderr
@@ -1,16 +1,9 @@
-error[E0271]: expected `fn() -> impl Future<Output = ()> {test}` to be a fn item that returns `Pin<Box<(dyn Future<Output = ()> + 'static)>>`, but it returns `impl Future<Output = ()>`
+error[E0271]: expected `test` to be a fn item that returns `Pin<Box<dyn Future<Output = ()>>>`, but it returns `impl Future<Output = ()>`
--> $DIR/issue-98604.rs:9:5
|
LL | Box::new(test) as AsyncFnPtr;
- | ^^^^^^^^^^^^^^ expected struct `Pin`, found opaque type
+ | ^^^^^^^^^^^^^^ expected `Pin<Box<dyn Future<Output = ()>>>`, found future
|
-note: while checking the return type of the `async fn`
- --> $DIR/issue-98604.rs:5:17
- |
-LL | async fn test() {}
- | ^ checked the `Output` of this `async fn`, found opaque type
- = note: expected struct `Pin<Box<(dyn Future<Output = ()> + 'static)>>`
- found opaque type `impl Future<Output = ()>`
= note: required for the cast from `fn() -> impl Future<Output = ()> {test}` to the object type `dyn Fn() -> Pin<Box<(dyn Future<Output = ()> + 'static)>>`
error: aborting due to previous error
diff --git a/tests/ui/type-alias-impl-trait/issue-98608.rs b/tests/ui/type-alias-impl-trait/issue-98608.rs
index 1f89af045..5e026ea40 100644
--- a/tests/ui/type-alias-impl-trait/issue-98608.rs
+++ b/tests/ui/type-alias-impl-trait/issue-98608.rs
@@ -4,7 +4,7 @@ fn hi() -> impl Sized {
fn main() {
let b: Box<dyn Fn() -> Box<u8>> = Box::new(hi);
- //~^ ERROR expected `fn() -> impl Sized {hi}` to be a fn item that returns `Box<u8>`, but it returns `impl Sized`
+ //~^ ERROR expected `hi` to be a fn item that returns `Box<u8>`, but it returns `impl Sized`
let boxed = b();
let null = *boxed;
println!("{null:?}");
diff --git a/tests/ui/type-alias-impl-trait/issue-98608.stderr b/tests/ui/type-alias-impl-trait/issue-98608.stderr
index 916a58451..506d40cb7 100644
--- a/tests/ui/type-alias-impl-trait/issue-98608.stderr
+++ b/tests/ui/type-alias-impl-trait/issue-98608.stderr
@@ -1,11 +1,11 @@
-error[E0271]: expected `fn() -> impl Sized {hi}` to be a fn item that returns `Box<u8>`, but it returns `impl Sized`
+error[E0271]: expected `hi` to be a fn item that returns `Box<u8>`, but it returns `impl Sized`
--> $DIR/issue-98608.rs:6:39
|
LL | fn hi() -> impl Sized {
| ---------- the found opaque type
...
LL | let b: Box<dyn Fn() -> Box<u8>> = Box::new(hi);
- | ^^^^^^^^^^^^ expected struct `Box`, found opaque type
+ | ^^^^^^^^^^^^ expected `Box<u8>`, found opaque type
|
= note: expected struct `Box<u8>`
found opaque type `impl Sized`
diff --git a/tests/ui/type-alias-impl-trait/match-unification.rs b/tests/ui/type-alias-impl-trait/match-unification.rs
new file mode 100644
index 000000000..f5c2abc0e
--- /dev/null
+++ b/tests/ui/type-alias-impl-trait/match-unification.rs
@@ -0,0 +1,14 @@
+use std::fmt::Debug;
+
+// check-pass
+
+fn bar() -> impl Debug {}
+
+fn baz(b: bool) -> Option<impl Debug> {
+ match b {
+ true => baz(false),
+ false => Some(bar()),
+ }
+}
+
+fn main() {}
diff --git a/tests/ui/type-alias-impl-trait/missing_lifetime_bound.stderr b/tests/ui/type-alias-impl-trait/missing_lifetime_bound.stderr
index 65a0af0d2..d666e668d 100644
--- a/tests/ui/type-alias-impl-trait/missing_lifetime_bound.stderr
+++ b/tests/ui/type-alias-impl-trait/missing_lifetime_bound.stderr
@@ -1,6 +1,8 @@
error[E0700]: hidden type for `Opaque<'a, T>` captures lifetime that does not appear in bounds
--> $DIR/missing_lifetime_bound.rs:4:47
|
+LL | type Opaque<'a, T> = impl Sized;
+ | ---------- opaque type defined here
LL | fn defining<'a, T>(x: &'a i32) -> Opaque<T> { x }
| -- ^
| |
diff --git a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-fn-type.stderr b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-fn-type.stderr
index a31cf1a51..ff375b2ff 100644
--- a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-fn-type.stderr
+++ b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-fn-type.stderr
@@ -1,4 +1,4 @@
-error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `fn` pointer return
+error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `fn` pointer return types
--> $DIR/type-alias-impl-trait-fn-type.rs:6:20
|
LL | type Foo = fn() -> impl Send;
diff --git a/tests/ui/type-alias-impl-trait/unnameable_type.stderr b/tests/ui/type-alias-impl-trait/unnameable_type.stderr
index 7dc6efc4b..e90324334 100644
--- a/tests/ui/type-alias-impl-trait/unnameable_type.stderr
+++ b/tests/ui/type-alias-impl-trait/unnameable_type.stderr
@@ -15,7 +15,7 @@ LL | type MyPrivate = impl Sized;
LL | fn dont_define_this(_private: MyPrivate) {}
| ^^^^^^^^^
| |
- | expected struct `Private`, found opaque type
+ | expected `Private`, found opaque type
| help: change the parameter type to match the trait: `Private`
|
note: type in trait
diff --git a/tests/ui/type-inference/issue-30225.stderr b/tests/ui/type-inference/issue-30225.stderr
index ccd05fa6b..72c33d16c 100644
--- a/tests/ui/type-inference/issue-30225.stderr
+++ b/tests/ui/type-inference/issue-30225.stderr
@@ -2,7 +2,7 @@ error[E0308]: mismatched types
--> $DIR/issue-30225.rs:31:9
|
LL | u = v; // mark $0 and $1 in a subtype relationship
- | ^ expected struct `A`, found struct `B`
+ | ^ expected `A`, found `B`
error: aborting due to previous error
diff --git a/tests/ui/type-inference/sort_by_key.stderr b/tests/ui/type-inference/sort_by_key.stderr
index 0a48d5756..de7b4b248 100644
--- a/tests/ui/type-inference/sort_by_key.stderr
+++ b/tests/ui/type-inference/sort_by_key.stderr
@@ -2,7 +2,7 @@ error[E0282]: type annotations needed
--> $DIR/sort_by_key.rs:3:40
|
LL | lst.sort_by_key(|&(v, _)| v.iter().sum());
- | ^^^ cannot infer type of the type parameter `S` declared on the associated function `sum`
+ | ^^^ cannot infer type of the type parameter `S` declared on the method `sum`
|
help: consider specifying the generic argument
|
diff --git a/tests/ui/type/issue-91268.rs b/tests/ui/type/issue-91268.rs
index f1e16bc7b..274ea839e 100644
--- a/tests/ui/type/issue-91268.rs
+++ b/tests/ui/type/issue-91268.rs
@@ -1,8 +1,4 @@
// error-pattern: this file contains an unclosed delimiter
-// error-pattern: cannot find type `ţ` in this scope
-// error-pattern: parenthesized type parameters may only be used with a `Fn` trait
-// error-pattern: type arguments are not allowed on builtin type `u8`
-// error-pattern: mismatched types
// ignore-tidy-trailing-newlines
// `ţ` must be the last character in this file, it cannot be followed by a newline
fn main() {
diff --git a/tests/ui/type/issue-91268.stderr b/tests/ui/type/issue-91268.stderr
index 6c9ee9945..a3619d863 100644
--- a/tests/ui/type/issue-91268.stderr
+++ b/tests/ui/type/issue-91268.stderr
@@ -1,5 +1,5 @@
error: this file contains an unclosed delimiter
- --> $DIR/issue-91268.rs:9:12
+ --> $DIR/issue-91268.rs:5:12
|
LL | fn main() {
| - unclosed delimiter
@@ -8,56 +8,5 @@ LL | 0: u8(ţ
| |
| unclosed delimiter
-error: this file contains an unclosed delimiter
- --> $DIR/issue-91268.rs:9:12
- |
-LL | fn main() {
- | - unclosed delimiter
-LL | 0: u8(ţ
- | - ^
- | |
- | unclosed delimiter
-
-error[E0412]: cannot find type `ţ` in this scope
- --> $DIR/issue-91268.rs:9:11
- |
-LL | 0: u8(ţ
- | ^ expecting a type here because of type ascription
-
-error[E0214]: parenthesized type parameters may only be used with a `Fn` trait
- --> $DIR/issue-91268.rs:9:8
- |
-LL | 0: u8(ţ
- | ^^^^ only `Fn` traits may use parentheses
- |
-help: use angle brackets instead
- |
-LL | 0: u8<ţ>
- | ~ +
-
-error[E0109]: type arguments are not allowed on builtin type `u8`
- --> $DIR/issue-91268.rs:9:11
- |
-LL | 0: u8(ţ
- | -- ^ type argument not allowed
- | |
- | not allowed on builtin type `u8`
- |
-help: primitive type `u8` doesn't have generic parameters
- |
-LL - 0: u8(ţ
-LL + 0: u8
- |
-
-error[E0308]: mismatched types
- --> $DIR/issue-91268.rs:9:5
- |
-LL | fn main() {
- | - expected `()` because of default return type
-LL | 0: u8(ţ
- | ^^^^^^^ expected `()`, found `u8`
-
-error: aborting due to 6 previous errors
+error: aborting due to previous error
-Some errors have detailed explanations: E0109, E0214, E0308, E0412.
-For more information about an error, try `rustc --explain E0109`.
diff --git a/tests/ui/type/type-ascription-instead-of-initializer.stderr b/tests/ui/type/type-ascription-instead-of-initializer.stderr
index ba8d15d0b..429501c27 100644
--- a/tests/ui/type/type-ascription-instead-of-initializer.stderr
+++ b/tests/ui/type/type-ascription-instead-of-initializer.stderr
@@ -11,14 +11,13 @@ error[E0061]: this function takes 1 argument but 2 arguments were supplied
--> $DIR/type-ascription-instead-of-initializer.rs:2:12
|
LL | let x: Vec::with_capacity(10, 20);
- | ^^^^^^^^^^^^^^^^^^ -- argument of type `{integer}` unexpected
+ | ^^^^^^^^^^^^^^^^^^ ----
+ | | |
+ | | unexpected argument of type `{integer}`
+ | help: remove the extra argument
|
note: associated function defined here
--> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
-help: remove the extra argument
- |
-LL | let x: Vec::with_capacity(10);
- | ~~~~
error: aborting due to 2 previous errors
diff --git a/tests/ui/type/type-ascription-precedence.stderr b/tests/ui/type/type-ascription-precedence.stderr
index edc5aeffd..d6d1e1d7d 100644
--- a/tests/ui/type/type-ascription-precedence.stderr
+++ b/tests/ui/type/type-ascription-precedence.stderr
@@ -2,13 +2,13 @@ error[E0308]: mismatched types
--> $DIR/type-ascription-precedence.rs:31:7
|
LL | &(S: &S);
- | ^ expected `&S`, found struct `S`
+ | ^ expected `&S`, found `S`
error[E0308]: mismatched types
--> $DIR/type-ascription-precedence.rs:35:7
|
LL | *(S: Z);
- | ^ expected struct `Z`, found struct `S`
+ | ^ expected `Z`, found `S`
error[E0614]: type `Z` cannot be dereferenced
--> $DIR/type-ascription-precedence.rs:35:5
@@ -20,7 +20,7 @@ error[E0308]: mismatched types
--> $DIR/type-ascription-precedence.rs:40:7
|
LL | -(S: Z);
- | ^ expected struct `Z`, found struct `S`
+ | ^ expected `Z`, found `S`
error[E0600]: cannot apply unary operator `-` to type `Z`
--> $DIR/type-ascription-precedence.rs:40:5
@@ -40,19 +40,19 @@ error[E0308]: mismatched types
--> $DIR/type-ascription-precedence.rs:45:5
|
LL | (S + Z): Z;
- | ^^^^^^^ expected struct `Z`, found struct `S`
+ | ^^^^^^^ expected `Z`, found `S`
error[E0308]: mismatched types
--> $DIR/type-ascription-precedence.rs:49:5
|
LL | (S * Z): Z;
- | ^^^^^^^ expected struct `Z`, found struct `S`
+ | ^^^^^^^ expected `Z`, found `S`
error[E0308]: mismatched types
--> $DIR/type-ascription-precedence.rs:53:5
|
LL | (S .. S): S;
- | ^^^^^^^^ expected struct `S`, found struct `Range`
+ | ^^^^^^^^ expected `S`, found `Range<S>`
|
= note: expected struct `S`
found struct `std::ops::Range<S>`
diff --git a/tests/ui/type/type-ascription-soundness.stderr b/tests/ui/type/type-ascription-soundness.stderr
index 522d5b2e3..778836a2e 100644
--- a/tests/ui/type/type-ascription-soundness.stderr
+++ b/tests/ui/type/type-ascription-soundness.stderr
@@ -2,7 +2,7 @@ error[E0308]: mismatched types
--> $DIR/type-ascription-soundness.rs:7:31
|
LL | let ref x = type_ascribe!(arr, &[u8]);
- | ^^^ expected slice `[u8]`, found array `[u8; 3]`
+ | ^^^ expected `&[u8]`, found `&[u8; 3]`
|
= note: expected reference `&[u8]`
found reference `&[u8; 3]`
@@ -11,7 +11,7 @@ error[E0308]: mismatched types
--> $DIR/type-ascription-soundness.rs:8:35
|
LL | let ref mut x = type_ascribe!(arr, &[u8]);
- | ^^^ expected slice `[u8]`, found array `[u8; 3]`
+ | ^^^ expected `&[u8]`, found `&[u8; 3]`
|
= note: expected reference `&[u8]`
found reference `&[u8; 3]`
@@ -20,7 +20,7 @@ error[E0308]: mismatched types
--> $DIR/type-ascription-soundness.rs:9:25
|
LL | match type_ascribe!(arr, &[u8]) {
- | ^^^ expected slice `[u8]`, found array `[u8; 3]`
+ | ^^^ expected `&[u8]`, found `&[u8; 3]`
|
= note: expected reference `&[u8]`
found reference `&[u8; 3]`
@@ -29,7 +29,7 @@ error[E0308]: mismatched types
--> $DIR/type-ascription-soundness.rs:12:30
|
LL | let _len = type_ascribe!(arr, &[u8]).len();
- | ^^^ expected slice `[u8]`, found array `[u8; 3]`
+ | ^^^ expected `&[u8]`, found `&[u8; 3]`
|
= note: expected reference `&[u8]`
found reference `&[u8; 3]`
diff --git a/tests/ui/type/type-check/assignment-in-if.stderr b/tests/ui/type/type-check/assignment-in-if.stderr
index 9f4558ada..de133e559 100644
--- a/tests/ui/type/type-check/assignment-in-if.stderr
+++ b/tests/ui/type/type-check/assignment-in-if.stderr
@@ -67,6 +67,9 @@ LL | x == 5
error[E0308]: mismatched types
--> $DIR/assignment-in-if.rs:44:18
|
+LL | if y = (Foo { foo: x }) {
+ | - here the type of `x` is inferred to be `usize`
+...
LL | if x == x && x = x && x == x {
| ------ ^ expected `bool`, found `usize`
| |
@@ -75,6 +78,9 @@ LL | if x == x && x = x && x == x {
error[E0308]: mismatched types
--> $DIR/assignment-in-if.rs:44:22
|
+LL | if y = (Foo { foo: x }) {
+ | - here the type of `x` is inferred to be `usize`
+...
LL | if x == x && x = x && x == x {
| ^ expected `bool`, found `usize`
@@ -92,6 +98,9 @@ LL | if x == x && x == x && x == x {
error[E0308]: mismatched types
--> $DIR/assignment-in-if.rs:51:28
|
+LL | if y = (Foo { foo: x }) {
+ | - here the type of `x` is inferred to be `usize`
+...
LL | if x == x && x == x && x = x {
| ---------------- ^ expected `bool`, found `usize`
| |
diff --git a/tests/ui/type/type-check/cannot_infer_local_or_vec.stderr b/tests/ui/type/type-check/cannot_infer_local_or_vec.stderr
index b63d2a3b6..09c4b2053 100644
--- a/tests/ui/type/type-check/cannot_infer_local_or_vec.stderr
+++ b/tests/ui/type/type-check/cannot_infer_local_or_vec.stderr
@@ -1,12 +1,12 @@
-error[E0282]: type annotations needed for `Vec<T>`
+error[E0282]: type annotations needed for `Vec<_>`
--> $DIR/cannot_infer_local_or_vec.rs:2:9
|
LL | let x = vec![];
| ^
|
-help: consider giving `x` an explicit type, where the type for type parameter `T` is specified
+help: consider giving `x` an explicit type, where the placeholders `_` are specified
|
-LL | let x: Vec<T> = vec![];
+LL | let x: Vec<_> = vec![];
| ++++++++
error: aborting due to previous error
diff --git a/tests/ui/type/type-check/cannot_infer_local_or_vec_in_tuples.stderr b/tests/ui/type/type-check/cannot_infer_local_or_vec_in_tuples.stderr
index e544b3695..1fa253052 100644
--- a/tests/ui/type/type-check/cannot_infer_local_or_vec_in_tuples.stderr
+++ b/tests/ui/type/type-check/cannot_infer_local_or_vec_in_tuples.stderr
@@ -1,12 +1,12 @@
-error[E0282]: type annotations needed for `(Vec<T>,)`
+error[E0282]: type annotations needed for `(Vec<_>,)`
--> $DIR/cannot_infer_local_or_vec_in_tuples.rs:2:9
|
LL | let (x, ) = (vec![], );
| ^^^^^ ---------- type must be known at this point
|
-help: consider giving this pattern a type, where the type for type parameter `T` is specified
+help: consider giving this pattern a type, where the placeholders `_` are specified
|
-LL | let (x, ): (Vec<T>,) = (vec![], );
+LL | let (x, ): (Vec<_>,) = (vec![], );
| +++++++++++
error: aborting due to previous error
diff --git a/tests/ui/type/type-check/coerce-result-return-value-2.rs b/tests/ui/type/type-check/coerce-result-return-value-2.rs
new file mode 100644
index 000000000..23bafa6c5
--- /dev/null
+++ b/tests/ui/type/type-check/coerce-result-return-value-2.rs
@@ -0,0 +1,24 @@
+struct A;
+struct B;
+impl From<A> for B {
+ fn from(_: A) -> Self { B }
+}
+fn foo4(x: Result<(), A>) -> Result<(), B> {
+ match true {
+ true => x, //~ ERROR mismatched types
+ false => x,
+ }
+}
+fn foo5(x: Result<(), A>) -> Result<(), B> {
+ match true {
+ true => return x, //~ ERROR mismatched types
+ false => return x,
+ }
+}
+fn main() {
+ let _ = foo4(Ok(()));
+ let _ = foo5(Ok(()));
+ let _: Result<(), B> = { //~ ERROR mismatched types
+ Err(A);
+ };
+}
diff --git a/tests/ui/type/type-check/coerce-result-return-value-2.stderr b/tests/ui/type/type-check/coerce-result-return-value-2.stderr
new file mode 100644
index 000000000..b2c409e07
--- /dev/null
+++ b/tests/ui/type/type-check/coerce-result-return-value-2.stderr
@@ -0,0 +1,47 @@
+error[E0308]: mismatched types
+ --> $DIR/coerce-result-return-value-2.rs:8:17
+ |
+LL | fn foo4(x: Result<(), A>) -> Result<(), B> {
+ | ------------- expected `Result<(), B>` because of return type
+LL | match true {
+LL | true => x,
+ | ^ expected `Result<(), B>`, found `Result<(), A>`
+ |
+ = note: expected enum `Result<_, B>`
+ found enum `Result<_, A>`
+help: use `?` to coerce and return an appropriate `Err`, and wrap the resulting value in `Ok` so the expression remains of type `Result`
+ |
+LL | true => Ok(x?),
+ | +++ ++
+
+error[E0308]: mismatched types
+ --> $DIR/coerce-result-return-value-2.rs:14:24
+ |
+LL | fn foo5(x: Result<(), A>) -> Result<(), B> {
+ | ------------- expected `Result<(), B>` because of return type
+LL | match true {
+LL | true => return x,
+ | ^ expected `Result<(), B>`, found `Result<(), A>`
+ |
+ = note: expected enum `Result<_, B>`
+ found enum `Result<_, A>`
+help: use `?` to coerce and return an appropriate `Err`, and wrap the resulting value in `Ok` so the expression remains of type `Result`
+ |
+LL | true => return Ok(x?),
+ | +++ ++
+
+error[E0308]: mismatched types
+ --> $DIR/coerce-result-return-value-2.rs:21:28
+ |
+LL | let _: Result<(), B> = {
+ | ____________________________^
+LL | | Err(A);
+LL | | };
+ | |_____^ expected `Result<(), B>`, found `()`
+ |
+ = note: expected enum `Result<(), B>`
+ found unit type `()`
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/type/type-check/coerce-result-return-value.fixed b/tests/ui/type/type-check/coerce-result-return-value.fixed
new file mode 100644
index 000000000..8a0540707
--- /dev/null
+++ b/tests/ui/type/type-check/coerce-result-return-value.fixed
@@ -0,0 +1,24 @@
+// run-rustfix
+struct A;
+struct B;
+impl From<A> for B {
+ fn from(_: A) -> Self { B }
+}
+fn foo1(x: Result<(), A>) -> Result<(), B> {
+ Ok(x?) //~ ERROR mismatched types
+}
+fn foo2(x: Result<(), A>) -> Result<(), B> {
+ return Ok(x?); //~ ERROR mismatched types
+}
+fn foo3(x: Result<(), A>) -> Result<(), B> {
+ if true {
+ Ok(x?) //~ ERROR mismatched types
+ } else {
+ Ok(x?) //~ ERROR mismatched types
+ }
+}
+fn main() {
+ let _ = foo1(Ok(()));
+ let _ = foo2(Ok(()));
+ let _ = foo3(Ok(()));
+}
diff --git a/tests/ui/type/type-check/coerce-result-return-value.rs b/tests/ui/type/type-check/coerce-result-return-value.rs
new file mode 100644
index 000000000..442203add
--- /dev/null
+++ b/tests/ui/type/type-check/coerce-result-return-value.rs
@@ -0,0 +1,24 @@
+// run-rustfix
+struct A;
+struct B;
+impl From<A> for B {
+ fn from(_: A) -> Self { B }
+}
+fn foo1(x: Result<(), A>) -> Result<(), B> {
+ x //~ ERROR mismatched types
+}
+fn foo2(x: Result<(), A>) -> Result<(), B> {
+ return x; //~ ERROR mismatched types
+}
+fn foo3(x: Result<(), A>) -> Result<(), B> {
+ if true {
+ x //~ ERROR mismatched types
+ } else {
+ x //~ ERROR mismatched types
+ }
+}
+fn main() {
+ let _ = foo1(Ok(()));
+ let _ = foo2(Ok(()));
+ let _ = foo3(Ok(()));
+}
diff --git a/tests/ui/type/type-check/coerce-result-return-value.stderr b/tests/ui/type/type-check/coerce-result-return-value.stderr
new file mode 100644
index 000000000..adec2f612
--- /dev/null
+++ b/tests/ui/type/type-check/coerce-result-return-value.stderr
@@ -0,0 +1,65 @@
+error[E0308]: mismatched types
+ --> $DIR/coerce-result-return-value.rs:8:5
+ |
+LL | fn foo1(x: Result<(), A>) -> Result<(), B> {
+ | ------------- expected `Result<(), B>` because of return type
+LL | x
+ | ^ expected `Result<(), B>`, found `Result<(), A>`
+ |
+ = note: expected enum `Result<_, B>`
+ found enum `Result<_, A>`
+help: use `?` to coerce and return an appropriate `Err`, and wrap the resulting value in `Ok` so the expression remains of type `Result`
+ |
+LL | Ok(x?)
+ | +++ ++
+
+error[E0308]: mismatched types
+ --> $DIR/coerce-result-return-value.rs:11:12
+ |
+LL | fn foo2(x: Result<(), A>) -> Result<(), B> {
+ | ------------- expected `Result<(), B>` because of return type
+LL | return x;
+ | ^ expected `Result<(), B>`, found `Result<(), A>`
+ |
+ = note: expected enum `Result<_, B>`
+ found enum `Result<_, A>`
+help: use `?` to coerce and return an appropriate `Err`, and wrap the resulting value in `Ok` so the expression remains of type `Result`
+ |
+LL | return Ok(x?);
+ | +++ ++
+
+error[E0308]: mismatched types
+ --> $DIR/coerce-result-return-value.rs:15:9
+ |
+LL | fn foo3(x: Result<(), A>) -> Result<(), B> {
+ | ------------- expected `Result<(), B>` because of return type
+LL | if true {
+LL | x
+ | ^ expected `Result<(), B>`, found `Result<(), A>`
+ |
+ = note: expected enum `Result<_, B>`
+ found enum `Result<_, A>`
+help: use `?` to coerce and return an appropriate `Err`, and wrap the resulting value in `Ok` so the expression remains of type `Result`
+ |
+LL | Ok(x?)
+ | +++ ++
+
+error[E0308]: mismatched types
+ --> $DIR/coerce-result-return-value.rs:17:9
+ |
+LL | fn foo3(x: Result<(), A>) -> Result<(), B> {
+ | ------------- expected `Result<(), B>` because of return type
+...
+LL | x
+ | ^ expected `Result<(), B>`, found `Result<(), A>`
+ |
+ = note: expected enum `Result<_, B>`
+ found enum `Result<_, A>`
+help: use `?` to coerce and return an appropriate `Err`, and wrap the resulting value in `Ok` so the expression remains of type `Result`
+ |
+LL | Ok(x?)
+ | +++ ++
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/type/type-check/point-at-inference-2.stderr b/tests/ui/type/type-check/point-at-inference-2.stderr
index 1368aba0d..1d2777ad6 100644
--- a/tests/ui/type/type-check/point-at-inference-2.stderr
+++ b/tests/ui/type/type-check/point-at-inference-2.stderr
@@ -2,7 +2,7 @@ error[E0308]: mismatched types
--> $DIR/point-at-inference-2.rs:5:9
|
LL | bar(v);
- | --- ^ expected `i32`, found `&{integer}`
+ | --- ^ expected `Vec<i32>`, found `Vec<&{integer}>`
| |
| arguments to this function are incorrect
|
@@ -17,8 +17,11 @@ LL | fn bar(_: Vec<i32>) {}
error[E0308]: mismatched types
--> $DIR/point-at-inference-2.rs:9:9
|
+LL | baz(&v);
+ | - here the type of `v` is inferred to be `Vec<&i32>`
+LL | baz(&v);
LL | bar(v);
- | --- ^ expected `i32`, found `&i32`
+ | --- ^ expected `Vec<i32>`, found `Vec<&i32>`
| |
| arguments to this function are incorrect
|
@@ -33,8 +36,10 @@ LL | fn bar(_: Vec<i32>) {}
error[E0308]: mismatched types
--> $DIR/point-at-inference-2.rs:12:9
|
+LL | baz(&v);
+ | - here the type of `v` is inferred to be `Vec<&i32>`
LL | bar(v);
- | --- ^ expected `i32`, found `&i32`
+ | --- ^ expected `Vec<i32>`, found `Vec<&i32>`
| |
| arguments to this function are incorrect
|
diff --git a/tests/ui/type/type-check/point-at-inference-3.fixed b/tests/ui/type/type-check/point-at-inference-3.fixed
index 44c057c0d..edd4adf8b 100644
--- a/tests/ui/type/type-check/point-at-inference-3.fixed
+++ b/tests/ui/type/type-check/point-at-inference-3.fixed
@@ -2,10 +2,11 @@
fn main() {
let mut v = Vec::new();
v.push(0i32);
+ //~^ NOTE this is of type `i32`, which causes `v` to be inferred as `Vec<i32>`
v.push(0);
v.push(1i32); //~ ERROR mismatched types
//~^ NOTE expected `i32`, found `u32`
//~| NOTE arguments to this method are incorrect
- //~| NOTE associated function defined here
+ //~| NOTE method defined here
//~| HELP change the type of the numeric literal from `u32` to `i32`
}
diff --git a/tests/ui/type/type-check/point-at-inference-3.rs b/tests/ui/type/type-check/point-at-inference-3.rs
index e7ae54384..49d7b5007 100644
--- a/tests/ui/type/type-check/point-at-inference-3.rs
+++ b/tests/ui/type/type-check/point-at-inference-3.rs
@@ -2,10 +2,11 @@
fn main() {
let mut v = Vec::new();
v.push(0i32);
+ //~^ NOTE this is of type `i32`, which causes `v` to be inferred as `Vec<i32>`
v.push(0);
v.push(1u32); //~ ERROR mismatched types
//~^ NOTE expected `i32`, found `u32`
//~| NOTE arguments to this method are incorrect
- //~| NOTE associated function defined here
+ //~| NOTE method defined here
//~| HELP change the type of the numeric literal from `u32` to `i32`
}
diff --git a/tests/ui/type/type-check/point-at-inference-3.stderr b/tests/ui/type/type-check/point-at-inference-3.stderr
index d7936e39c..2c4907ed2 100644
--- a/tests/ui/type/type-check/point-at-inference-3.stderr
+++ b/tests/ui/type/type-check/point-at-inference-3.stderr
@@ -1,12 +1,15 @@
error[E0308]: mismatched types
- --> $DIR/point-at-inference-3.rs:6:12
+ --> $DIR/point-at-inference-3.rs:7:12
|
+LL | v.push(0i32);
+ | ---- this is of type `i32`, which causes `v` to be inferred as `Vec<i32>`
+...
LL | v.push(1u32);
| ---- ^^^^ expected `i32`, found `u32`
| |
| arguments to this method are incorrect
|
-note: associated function defined here
+note: method defined here
--> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
help: change the type of the numeric literal from `u32` to `i32`
|
diff --git a/tests/ui/type/type-check/point-at-inference-4.rs b/tests/ui/type/type-check/point-at-inference-4.rs
new file mode 100644
index 000000000..aea9b2c6c
--- /dev/null
+++ b/tests/ui/type/type-check/point-at-inference-4.rs
@@ -0,0 +1,21 @@
+struct S<A, B>(Option<(A, B)>);
+
+impl<A, B> S<A, B> {
+ fn infer(&self, a: A, b: B) {}
+ //~^ NOTE method defined here
+ //~| NOTE
+ //~| NOTE
+}
+
+fn main() {
+ let s = S(None);
+ s.infer(0i32);
+ //~^ ERROR this method takes 2 arguments but 1 argument was supplied
+ //~| NOTE an argument is missing
+ //~| HELP provide the argument
+ let t: S<u32, _> = s;
+ //~^ ERROR mismatched types
+ //~| NOTE expected `S<u32, _>`, found `S<i32, _>`
+ //~| NOTE expected due to this
+ //~| NOTE expected struct `S<u32, _>`
+}
diff --git a/tests/ui/type/type-check/point-at-inference-4.stderr b/tests/ui/type/type-check/point-at-inference-4.stderr
new file mode 100644
index 000000000..28833d2ed
--- /dev/null
+++ b/tests/ui/type/type-check/point-at-inference-4.stderr
@@ -0,0 +1,31 @@
+error[E0061]: this method takes 2 arguments but 1 argument was supplied
+ --> $DIR/point-at-inference-4.rs:12:7
+ |
+LL | s.infer(0i32);
+ | ^^^^^------ an argument is missing
+ |
+note: method defined here
+ --> $DIR/point-at-inference-4.rs:4:8
+ |
+LL | fn infer(&self, a: A, b: B) {}
+ | ^^^^^ ---- ----
+help: provide the argument
+ |
+LL | s.infer(0i32, /* b */);
+ | ~~~~~~~~~~~~~~~
+
+error[E0308]: mismatched types
+ --> $DIR/point-at-inference-4.rs:16:24
+ |
+LL | let t: S<u32, _> = s;
+ | --------- ^ expected `S<u32, _>`, found `S<i32, _>`
+ | |
+ | expected due to this
+ |
+ = note: expected struct `S<u32, _>`
+ found struct `S<i32, _>`
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0061, E0308.
+For more information about an error, try `rustc --explain E0061`.
diff --git a/tests/ui/type/type-check/point-at-inference.fixed b/tests/ui/type/type-check/point-at-inference.fixed
new file mode 100644
index 000000000..f41fbe59f
--- /dev/null
+++ b/tests/ui/type/type-check/point-at-inference.fixed
@@ -0,0 +1,13 @@
+// run-rustfix
+fn bar(_: Vec<i32>) {}
+fn baz(_: &impl std::any::Any) {}
+fn main() {
+ let v = vec![1, 2, 3, 4, 5];
+ let mut foo = vec![];
+ baz(&foo);
+ for i in &v {
+ foo.push(*i);
+ }
+ baz(&foo);
+ bar(foo); //~ ERROR E0308
+}
diff --git a/tests/ui/type/type-check/point-at-inference.rs b/tests/ui/type/type-check/point-at-inference.rs
index 5c46dd4ed..6419e42e7 100644
--- a/tests/ui/type/type-check/point-at-inference.rs
+++ b/tests/ui/type/type-check/point-at-inference.rs
@@ -1,3 +1,4 @@
+// run-rustfix
fn bar(_: Vec<i32>) {}
fn baz(_: &impl std::any::Any) {}
fn main() {
diff --git a/tests/ui/type/type-check/point-at-inference.stderr b/tests/ui/type/type-check/point-at-inference.stderr
index 2e17e5c5f..a76b4f90c 100644
--- a/tests/ui/type/type-check/point-at-inference.stderr
+++ b/tests/ui/type/type-check/point-at-inference.stderr
@@ -1,18 +1,25 @@
error[E0308]: mismatched types
- --> $DIR/point-at-inference.rs:11:9
+ --> $DIR/point-at-inference.rs:12:9
|
+LL | foo.push(i);
+ | - this is of type `&{integer}`, which causes `foo` to be inferred as `Vec<&{integer}>`
+...
LL | bar(foo);
- | --- ^^^ expected `i32`, found `&{integer}`
+ | --- ^^^ expected `Vec<i32>`, found `Vec<&{integer}>`
| |
| arguments to this function are incorrect
|
= note: expected struct `Vec<i32>`
found struct `Vec<&{integer}>`
note: function defined here
- --> $DIR/point-at-inference.rs:1:4
+ --> $DIR/point-at-inference.rs:2:4
|
LL | fn bar(_: Vec<i32>) {}
| ^^^ -----------
+help: consider dereferencing the borrow
+ |
+LL | foo.push(*i);
+ | +
error: aborting due to previous error
diff --git a/tests/ui/type/type-mismatch-same-crate-name.rs b/tests/ui/type/type-mismatch-same-crate-name.rs
index c9cdc874c..2a59bd994 100644
--- a/tests/ui/type/type-mismatch-same-crate-name.rs
+++ b/tests/ui/type/type-mismatch-same-crate-name.rs
@@ -16,7 +16,7 @@ fn main() {
a::try_foo(foo2);
//~^ ERROR mismatched types
//~| perhaps two different versions of crate `crate_a1`
- //~| expected struct `main::a::Foo`
+ //~| expected `main::a::Foo`, found a different `main::a::Foo`
a::try_bar(bar2);
//~^ ERROR mismatched types
//~| perhaps two different versions of crate `crate_a1`
diff --git a/tests/ui/type/type-mismatch-same-crate-name.stderr b/tests/ui/type/type-mismatch-same-crate-name.stderr
index fcafd315e..504812f58 100644
--- a/tests/ui/type/type-mismatch-same-crate-name.stderr
+++ b/tests/ui/type/type-mismatch-same-crate-name.stderr
@@ -2,17 +2,17 @@ error[E0308]: mismatched types
--> $DIR/type-mismatch-same-crate-name.rs:16:20
|
LL | a::try_foo(foo2);
- | ---------- ^^^^ expected struct `main::a::Foo`, found a different struct `main::a::Foo`
+ | ---------- ^^^^ expected `main::a::Foo`, found a different `main::a::Foo`
| |
| arguments to this function are incorrect
|
- = note: struct `main::a::Foo` and struct `main::a::Foo` have similar names, but are actually distinct types
-note: struct `main::a::Foo` is defined in crate `crate_a2`
+ = note: `main::a::Foo` and `main::a::Foo` have similar names, but are actually distinct types
+note: `main::a::Foo` is defined in crate `crate_a2`
--> $DIR/auxiliary/crate_a2.rs:1:1
|
LL | pub struct Foo;
| ^^^^^^^^^^^^^^
-note: struct `main::a::Foo` is defined in crate `crate_a1`
+note: `main::a::Foo` is defined in crate `crate_a1`
--> $DIR/auxiliary/crate_a1.rs:1:1
|
LL | pub struct Foo;
diff --git a/tests/ui/type/type-mismatch.stderr b/tests/ui/type/type-mismatch.stderr
index 6c187bad0..67a1f8930 100644
--- a/tests/ui/type/type-mismatch.stderr
+++ b/tests/ui/type/type-mismatch.stderr
@@ -2,7 +2,7 @@ error[E0308]: mismatched types
--> $DIR/type-mismatch.rs:17:17
|
LL | want::<foo>(f);
- | ----------- ^ expected struct `foo`, found `usize`
+ | ----------- ^ expected `foo`, found `usize`
| |
| arguments to this function are incorrect
|
@@ -16,7 +16,7 @@ error[E0308]: mismatched types
--> $DIR/type-mismatch.rs:18:17
|
LL | want::<bar>(f);
- | ----------- ^ expected struct `bar`, found `usize`
+ | ----------- ^ expected `bar`, found `usize`
| |
| arguments to this function are incorrect
|
@@ -30,7 +30,7 @@ error[E0308]: mismatched types
--> $DIR/type-mismatch.rs:19:24
|
LL | want::<Foo<usize>>(f);
- | ------------------ ^ expected struct `Foo`, found `usize`
+ | ------------------ ^ expected `Foo<usize>`, found `usize`
| |
| arguments to this function are incorrect
|
@@ -46,7 +46,7 @@ error[E0308]: mismatched types
--> $DIR/type-mismatch.rs:20:27
|
LL | want::<Foo<usize, B>>(f);
- | --------------------- ^ expected struct `Foo`, found `usize`
+ | --------------------- ^ expected `Foo<usize, B>`, found `usize`
| |
| arguments to this function are incorrect
|
@@ -62,7 +62,7 @@ error[E0308]: mismatched types
--> $DIR/type-mismatch.rs:21:22
|
LL | want::<Foo<foo>>(f);
- | ---------------- ^ expected struct `Foo`, found `usize`
+ | ---------------- ^ expected `Foo<foo>`, found `usize`
| |
| arguments to this function are incorrect
|
@@ -78,7 +78,7 @@ error[E0308]: mismatched types
--> $DIR/type-mismatch.rs:22:25
|
LL | want::<Foo<foo, B>>(f);
- | ------------------- ^ expected struct `Foo`, found `usize`
+ | ------------------- ^ expected `Foo<foo, B>`, found `usize`
| |
| arguments to this function are incorrect
|
@@ -94,7 +94,7 @@ error[E0308]: mismatched types
--> $DIR/type-mismatch.rs:23:22
|
LL | want::<Foo<bar>>(f);
- | ---------------- ^ expected struct `Foo`, found `usize`
+ | ---------------- ^ expected `Foo<bar>`, found `usize`
| |
| arguments to this function are incorrect
|
@@ -110,7 +110,7 @@ error[E0308]: mismatched types
--> $DIR/type-mismatch.rs:24:25
|
LL | want::<Foo<bar, B>>(f);
- | ------------------- ^ expected struct `Foo`, found `usize`
+ | ------------------- ^ expected `Foo<bar, B>`, found `usize`
| |
| arguments to this function are incorrect
|
@@ -126,7 +126,7 @@ error[E0308]: mismatched types
--> $DIR/type-mismatch.rs:28:19
|
LL | want::<usize>(f);
- | ------------- ^ expected `usize`, found struct `foo`
+ | ------------- ^ expected `usize`, found `foo`
| |
| arguments to this function are incorrect
|
@@ -140,7 +140,7 @@ error[E0308]: mismatched types
--> $DIR/type-mismatch.rs:29:17
|
LL | want::<bar>(f);
- | ----------- ^ expected struct `bar`, found struct `foo`
+ | ----------- ^ expected `bar`, found `foo`
| |
| arguments to this function are incorrect
|
@@ -154,7 +154,7 @@ error[E0308]: mismatched types
--> $DIR/type-mismatch.rs:30:24
|
LL | want::<Foo<usize>>(f);
- | ------------------ ^ expected struct `Foo`, found struct `foo`
+ | ------------------ ^ expected `Foo<usize>`, found `foo`
| |
| arguments to this function are incorrect
|
@@ -170,7 +170,7 @@ error[E0308]: mismatched types
--> $DIR/type-mismatch.rs:31:27
|
LL | want::<Foo<usize, B>>(f);
- | --------------------- ^ expected struct `Foo`, found struct `foo`
+ | --------------------- ^ expected `Foo<usize, B>`, found `foo`
| |
| arguments to this function are incorrect
|
@@ -186,7 +186,7 @@ error[E0308]: mismatched types
--> $DIR/type-mismatch.rs:32:22
|
LL | want::<Foo<foo>>(f);
- | ---------------- ^ expected struct `Foo`, found struct `foo`
+ | ---------------- ^ expected `Foo<foo>`, found `foo`
| |
| arguments to this function are incorrect
|
@@ -202,7 +202,7 @@ error[E0308]: mismatched types
--> $DIR/type-mismatch.rs:33:25
|
LL | want::<Foo<foo, B>>(f);
- | ------------------- ^ expected struct `Foo`, found struct `foo`
+ | ------------------- ^ expected `Foo<foo, B>`, found `foo`
| |
| arguments to this function are incorrect
|
@@ -218,7 +218,7 @@ error[E0308]: mismatched types
--> $DIR/type-mismatch.rs:34:22
|
LL | want::<Foo<bar>>(f);
- | ---------------- ^ expected struct `Foo`, found struct `foo`
+ | ---------------- ^ expected `Foo<bar>`, found `foo`
| |
| arguments to this function are incorrect
|
@@ -234,7 +234,7 @@ error[E0308]: mismatched types
--> $DIR/type-mismatch.rs:35:25
|
LL | want::<Foo<bar, B>>(f);
- | ------------------- ^ expected struct `Foo`, found struct `foo`
+ | ------------------- ^ expected `Foo<bar, B>`, found `foo`
| |
| arguments to this function are incorrect
|
@@ -250,7 +250,7 @@ error[E0308]: mismatched types
--> $DIR/type-mismatch.rs:39:19
|
LL | want::<usize>(f);
- | ------------- ^ expected `usize`, found struct `Foo`
+ | ------------- ^ expected `usize`, found `Foo<foo>`
| |
| arguments to this function are incorrect
|
@@ -266,7 +266,7 @@ error[E0308]: mismatched types
--> $DIR/type-mismatch.rs:40:17
|
LL | want::<foo>(f);
- | ----------- ^ expected struct `foo`, found struct `Foo`
+ | ----------- ^ expected `foo`, found `Foo<foo>`
| |
| arguments to this function are incorrect
|
@@ -282,7 +282,7 @@ error[E0308]: mismatched types
--> $DIR/type-mismatch.rs:41:17
|
LL | want::<bar>(f);
- | ----------- ^ expected struct `bar`, found struct `Foo`
+ | ----------- ^ expected `bar`, found `Foo<foo>`
| |
| arguments to this function are incorrect
|
@@ -298,7 +298,7 @@ error[E0308]: mismatched types
--> $DIR/type-mismatch.rs:42:24
|
LL | want::<Foo<usize>>(f);
- | ------------------ ^ expected `usize`, found struct `foo`
+ | ------------------ ^ expected `Foo<usize>`, found `Foo<foo>`
| |
| arguments to this function are incorrect
|
@@ -314,7 +314,7 @@ error[E0308]: mismatched types
--> $DIR/type-mismatch.rs:43:27
|
LL | want::<Foo<usize, B>>(f);
- | --------------------- ^ expected `usize`, found struct `foo`
+ | --------------------- ^ expected `Foo<usize, B>`, found `Foo<foo>`
| |
| arguments to this function are incorrect
|
@@ -330,7 +330,7 @@ error[E0308]: mismatched types
--> $DIR/type-mismatch.rs:44:25
|
LL | want::<Foo<foo, B>>(f);
- | ------------------- ^ expected struct `B`, found struct `A`
+ | ------------------- ^ expected `Foo<foo, B>`, found `Foo<foo>`
| |
| arguments to this function are incorrect
|
@@ -346,7 +346,7 @@ error[E0308]: mismatched types
--> $DIR/type-mismatch.rs:45:22
|
LL | want::<Foo<bar>>(f);
- | ---------------- ^ expected struct `bar`, found struct `foo`
+ | ---------------- ^ expected `Foo<bar>`, found `Foo<foo>`
| |
| arguments to this function are incorrect
|
@@ -362,7 +362,7 @@ error[E0308]: mismatched types
--> $DIR/type-mismatch.rs:46:25
|
LL | want::<Foo<bar, B>>(f);
- | ------------------- ^ expected struct `bar`, found struct `foo`
+ | ------------------- ^ expected `Foo<bar, B>`, found `Foo<foo>`
| |
| arguments to this function are incorrect
|
@@ -380,7 +380,7 @@ error[E0308]: mismatched types
LL | want::<&Foo<foo>>(f);
| ----------------- ^
| | |
- | | expected `&Foo<foo>`, found struct `Foo`
+ | | expected `&Foo<foo>`, found `Foo<foo>`
| | help: consider borrowing here: `&f`
| arguments to this function are incorrect
|
@@ -396,7 +396,7 @@ error[E0308]: mismatched types
--> $DIR/type-mismatch.rs:48:26
|
LL | want::<&Foo<foo, B>>(f);
- | -------------------- ^ expected `&Foo<foo, B>`, found struct `Foo`
+ | -------------------- ^ expected `&Foo<foo, B>`, found `Foo<foo>`
| |
| arguments to this function are incorrect
|
@@ -412,7 +412,7 @@ error[E0308]: mismatched types
--> $DIR/type-mismatch.rs:52:19
|
LL | want::<usize>(f);
- | ------------- ^ expected `usize`, found struct `Foo`
+ | ------------- ^ expected `usize`, found `Foo<foo, B>`
| |
| arguments to this function are incorrect
|
@@ -428,7 +428,7 @@ error[E0308]: mismatched types
--> $DIR/type-mismatch.rs:53:17
|
LL | want::<foo>(f);
- | ----------- ^ expected struct `foo`, found struct `Foo`
+ | ----------- ^ expected `foo`, found `Foo<foo, B>`
| |
| arguments to this function are incorrect
|
@@ -444,7 +444,7 @@ error[E0308]: mismatched types
--> $DIR/type-mismatch.rs:54:17
|
LL | want::<bar>(f);
- | ----------- ^ expected struct `bar`, found struct `Foo`
+ | ----------- ^ expected `bar`, found `Foo<foo, B>`
| |
| arguments to this function are incorrect
|
@@ -460,7 +460,7 @@ error[E0308]: mismatched types
--> $DIR/type-mismatch.rs:55:24
|
LL | want::<Foo<usize>>(f);
- | ------------------ ^ expected `usize`, found struct `foo`
+ | ------------------ ^ expected `Foo<usize>`, found `Foo<foo, B>`
| |
| arguments to this function are incorrect
|
@@ -476,7 +476,7 @@ error[E0308]: mismatched types
--> $DIR/type-mismatch.rs:56:27
|
LL | want::<Foo<usize, B>>(f);
- | --------------------- ^ expected `usize`, found struct `foo`
+ | --------------------- ^ expected `Foo<usize, B>`, found `Foo<foo, B>`
| |
| arguments to this function are incorrect
|
@@ -492,7 +492,7 @@ error[E0308]: mismatched types
--> $DIR/type-mismatch.rs:57:22
|
LL | want::<Foo<foo>>(f);
- | ---------------- ^ expected struct `A`, found struct `B`
+ | ---------------- ^ expected `Foo<foo>`, found `Foo<foo, B>`
| |
| arguments to this function are incorrect
|
@@ -508,7 +508,7 @@ error[E0308]: mismatched types
--> $DIR/type-mismatch.rs:58:22
|
LL | want::<Foo<bar>>(f);
- | ---------------- ^ expected struct `bar`, found struct `foo`
+ | ---------------- ^ expected `Foo<bar>`, found `Foo<foo, B>`
| |
| arguments to this function are incorrect
|
@@ -524,7 +524,7 @@ error[E0308]: mismatched types
--> $DIR/type-mismatch.rs:59:25
|
LL | want::<Foo<bar, B>>(f);
- | ------------------- ^ expected struct `bar`, found struct `foo`
+ | ------------------- ^ expected `Foo<bar, B>`, found `Foo<foo, B>`
| |
| arguments to this function are incorrect
|
@@ -540,7 +540,7 @@ error[E0308]: mismatched types
--> $DIR/type-mismatch.rs:60:23
|
LL | want::<&Foo<foo>>(f);
- | ----------------- ^ expected `&Foo<foo>`, found struct `Foo`
+ | ----------------- ^ expected `&Foo<foo>`, found `Foo<foo, B>`
| |
| arguments to this function are incorrect
|
@@ -558,7 +558,7 @@ error[E0308]: mismatched types
LL | want::<&Foo<foo, B>>(f);
| -------------------- ^
| | |
- | | expected `&Foo<foo, B>`, found struct `Foo`
+ | | expected `&Foo<foo, B>`, found `Foo<foo, B>`
| | help: consider borrowing here: `&f`
| arguments to this function are incorrect
|
@@ -574,7 +574,7 @@ error[E0308]: mismatched types
--> $DIR/type-mismatch.rs:65:19
|
LL | want::<usize>(f);
- | ------------- ^ expected `usize`, found struct `Foo`
+ | ------------- ^ expected `usize`, found `Foo<foo, B, A>`
| |
| arguments to this function are incorrect
|
@@ -590,7 +590,7 @@ error[E0308]: mismatched types
--> $DIR/type-mismatch.rs:66:17
|
LL | want::<foo>(f);
- | ----------- ^ expected struct `foo`, found struct `Foo`
+ | ----------- ^ expected `foo`, found `Foo<foo, B, A>`
| |
| arguments to this function are incorrect
|
@@ -606,7 +606,7 @@ error[E0308]: mismatched types
--> $DIR/type-mismatch.rs:67:17
|
LL | want::<bar>(f);
- | ----------- ^ expected struct `bar`, found struct `Foo`
+ | ----------- ^ expected `bar`, found `Foo<foo, B, A>`
| |
| arguments to this function are incorrect
|
@@ -622,7 +622,7 @@ error[E0308]: mismatched types
--> $DIR/type-mismatch.rs:68:24
|
LL | want::<Foo<usize>>(f);
- | ------------------ ^ expected `usize`, found struct `foo`
+ | ------------------ ^ expected `Foo<usize>`, found `Foo<foo, B, A>`
| |
| arguments to this function are incorrect
|
@@ -638,7 +638,7 @@ error[E0308]: mismatched types
--> $DIR/type-mismatch.rs:69:27
|
LL | want::<Foo<usize, B>>(f);
- | --------------------- ^ expected `usize`, found struct `foo`
+ | --------------------- ^ expected `Foo<usize, B>`, found `Foo<foo, B, A>`
| |
| arguments to this function are incorrect
|
@@ -654,7 +654,7 @@ error[E0308]: mismatched types
--> $DIR/type-mismatch.rs:70:22
|
LL | want::<Foo<foo>>(f);
- | ---------------- ^ expected struct `A`, found struct `B`
+ | ---------------- ^ expected `Foo<foo>`, found `Foo<foo, B, A>`
| |
| arguments to this function are incorrect
|
@@ -670,7 +670,7 @@ error[E0308]: mismatched types
--> $DIR/type-mismatch.rs:71:25
|
LL | want::<Foo<foo, B>>(f);
- | ------------------- ^ expected struct `B`, found struct `A`
+ | ------------------- ^ expected `Foo<foo, B>`, found `Foo<foo, B, A>`
| |
| arguments to this function are incorrect
|
@@ -686,7 +686,7 @@ error[E0308]: mismatched types
--> $DIR/type-mismatch.rs:72:22
|
LL | want::<Foo<bar>>(f);
- | ---------------- ^ expected struct `bar`, found struct `foo`
+ | ---------------- ^ expected `Foo<bar>`, found `Foo<foo, B, A>`
| |
| arguments to this function are incorrect
|
@@ -702,7 +702,7 @@ error[E0308]: mismatched types
--> $DIR/type-mismatch.rs:73:25
|
LL | want::<Foo<bar, B>>(f);
- | ------------------- ^ expected struct `bar`, found struct `foo`
+ | ------------------- ^ expected `Foo<bar, B>`, found `Foo<foo, B, A>`
| |
| arguments to this function are incorrect
|
@@ -718,7 +718,7 @@ error[E0308]: mismatched types
--> $DIR/type-mismatch.rs:74:23
|
LL | want::<&Foo<foo>>(f);
- | ----------------- ^ expected `&Foo<foo>`, found struct `Foo`
+ | ----------------- ^ expected `&Foo<foo>`, found `Foo<foo, B, A>`
| |
| arguments to this function are incorrect
|
@@ -734,7 +734,7 @@ error[E0308]: mismatched types
--> $DIR/type-mismatch.rs:75:26
|
LL | want::<&Foo<foo, B>>(f);
- | -------------------- ^ expected `&Foo<foo, B>`, found struct `Foo`
+ | -------------------- ^ expected `&Foo<foo, B>`, found `Foo<foo, B, A>`
| |
| arguments to this function are incorrect
|
diff --git a/tests/ui/type/wrong-call-return-type-due-to-generic-arg.stderr b/tests/ui/type/wrong-call-return-type-due-to-generic-arg.stderr
index 4d012cb15..fbe6bfeeb 100644
--- a/tests/ui/type/wrong-call-return-type-due-to-generic-arg.stderr
+++ b/tests/ui/type/wrong-call-return-type-due-to-generic-arg.stderr
@@ -95,7 +95,7 @@ LL | let x: u16 = (S {}).method(0u32);
| ^^^^^^^^^^^^^^----^
| |
| this argument influences the return type of `method`
-note: associated function defined here
+note: method defined here
--> $DIR/wrong-call-return-type-due-to-generic-arg.rs:7:8
|
LL | fn method<T>(&self, x: T) -> T {
diff --git a/tests/ui/typeck/assign-non-lval-derefmut.stderr b/tests/ui/typeck/assign-non-lval-derefmut.stderr
index e394cf820..b26d16da0 100644
--- a/tests/ui/typeck/assign-non-lval-derefmut.stderr
+++ b/tests/ui/typeck/assign-non-lval-derefmut.stderr
@@ -30,7 +30,7 @@ error[E0308]: mismatched types
LL | let mut y = x.lock().unwrap();
| ----------------- expected due to this value
LL | y = 2;
- | ^ expected struct `MutexGuard`, found integer
+ | ^ expected `MutexGuard<'_, usize>`, found integer
|
= note: expected struct `MutexGuard<'_, usize>`
found type `{integer}`
diff --git a/tests/ui/typeck/bad-type-in-vec-contains.rs b/tests/ui/typeck/bad-type-in-vec-contains.rs
new file mode 100644
index 000000000..4433047b7
--- /dev/null
+++ b/tests/ui/typeck/bad-type-in-vec-contains.rs
@@ -0,0 +1,7 @@
+// The error message here still is pretty confusing.
+
+fn main() {
+ let primes = Vec::new();
+ primes.contains(3);
+ //~^ ERROR mismatched types
+}
diff --git a/tests/ui/typeck/bad-type-in-vec-contains.stderr b/tests/ui/typeck/bad-type-in-vec-contains.stderr
new file mode 100644
index 000000000..0e03388d2
--- /dev/null
+++ b/tests/ui/typeck/bad-type-in-vec-contains.stderr
@@ -0,0 +1,19 @@
+error[E0308]: mismatched types
+ --> $DIR/bad-type-in-vec-contains.rs:5:21
+ |
+LL | primes.contains(3);
+ | -------- ^
+ | | |
+ | | expected `&_`, found integer
+ | | help: consider borrowing here: `&3`
+ | arguments to this method are incorrect
+ | here the type of `primes` is inferred to be `[_]`
+ |
+ = note: expected reference `&_`
+ found type `{integer}`
+note: method defined here
+ --> $SRC_DIR/core/src/slice/mod.rs:LL:COL
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/typeck/bad-type-in-vec-push.rs b/tests/ui/typeck/bad-type-in-vec-push.rs
new file mode 100644
index 000000000..a807f030c
--- /dev/null
+++ b/tests/ui/typeck/bad-type-in-vec-push.rs
@@ -0,0 +1,20 @@
+// The error message here still is pretty confusing.
+
+fn main() {
+ let mut result = vec![1];
+ // The type of `result` is constrained to be `Vec<{integer}>` here.
+ // But the logic we use to find what expression constrains a type
+ // is not sophisticated enough to know this.
+
+ let mut vector = Vec::new();
+ vector.sort();
+ result.push(vector);
+ //~^ ERROR mismatched types
+ // So it thinks that the type of `result` is constrained here.
+}
+
+fn example2() {
+ let mut x = vec![1];
+ x.push("");
+ //~^ ERROR mismatched types
+}
diff --git a/tests/ui/typeck/bad-type-in-vec-push.stderr b/tests/ui/typeck/bad-type-in-vec-push.stderr
new file mode 100644
index 000000000..ae46050c9
--- /dev/null
+++ b/tests/ui/typeck/bad-type-in-vec-push.stderr
@@ -0,0 +1,29 @@
+error[E0308]: mismatched types
+ --> $DIR/bad-type-in-vec-push.rs:11:17
+ |
+LL | vector.sort();
+ | ------ here the type of `vector` is inferred to be `Vec<_>`
+LL | result.push(vector);
+ | ---- ^^^^^^ expected integer, found `Vec<_>`
+ | |
+ | arguments to this method are incorrect
+ |
+ = note: expected type `{integer}`
+ found struct `Vec<_>`
+note: method defined here
+ --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
+
+error[E0308]: mismatched types
+ --> $DIR/bad-type-in-vec-push.rs:18:12
+ |
+LL | x.push("");
+ | ---- ^^ expected integer, found `&str`
+ | |
+ | arguments to this method are incorrect
+ |
+note: method defined here
+ --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/typeck/conversion-methods.stderr b/tests/ui/typeck/conversion-methods.stderr
index 091502bdd..a9b5078cc 100644
--- a/tests/ui/typeck/conversion-methods.stderr
+++ b/tests/ui/typeck/conversion-methods.stderr
@@ -4,7 +4,7 @@ error[E0308]: mismatched types
LL | let _tis_an_instants_play: String = "'Tis a fond Ambush—";
| ------ ^^^^^^^^^^^^^^^^^^^^^- help: try using a conversion method: `.to_string()`
| | |
- | | expected struct `String`, found `&str`
+ | | expected `String`, found `&str`
| expected due to this
error[E0308]: mismatched types
@@ -13,7 +13,7 @@ error[E0308]: mismatched types
LL | let _just_to_make_bliss: PathBuf = Path::new("/ern/her/own/surprise");
| ------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- help: try using a conversion method: `.to_path_buf()`
| | |
- | | expected struct `PathBuf`, found `&Path`
+ | | expected `PathBuf`, found `&Path`
| expected due to this
error[E0308]: mismatched types
@@ -22,14 +22,14 @@ error[E0308]: mismatched types
LL | let _but_should_the_play: String = 2; // Perhaps surprisingly, we suggest .to_string() here
| ------ ^- help: try using a conversion method: `.to_string()`
| | |
- | | expected struct `String`, found integer
+ | | expected `String`, found integer
| expected due to this
error[E0308]: mismatched types
--> $DIR/conversion-methods.rs:12:47
|
LL | let _prove_piercing_earnest: Vec<usize> = &[1, 2, 3];
- | ---------- ^^^^^^^^^^ expected struct `Vec`, found `&[{integer}; 3]`
+ | ---------- ^^^^^^^^^^ expected `Vec<usize>`, found `&[{integer}; 3]`
| |
| expected due to this
|
diff --git a/tests/ui/typeck/deref-multi.stderr b/tests/ui/typeck/deref-multi.stderr
index bd6575c73..4346e273d 100644
--- a/tests/ui/typeck/deref-multi.stderr
+++ b/tests/ui/typeck/deref-multi.stderr
@@ -58,7 +58,7 @@ error[E0308]: mismatched types
LL | fn d(x: std::sync::Mutex<&i32>) -> i32 {
| --- expected `i32` because of return type
LL | x.lock().unwrap()
- | ^^^^^^^^^^^^^^^^^ expected `i32`, found struct `MutexGuard`
+ | ^^^^^^^^^^^^^^^^^ expected `i32`, found `MutexGuard<'_, &i32>`
|
= note: expected type `i32`
found struct `MutexGuard<'_, &i32>`
diff --git a/tests/ui/typeck/explain_clone_autoref.rs b/tests/ui/typeck/explain_clone_autoref.rs
index 9279e4c39..4d2157470 100644
--- a/tests/ui/typeck/explain_clone_autoref.rs
+++ b/tests/ui/typeck/explain_clone_autoref.rs
@@ -9,5 +9,5 @@ fn clone_thing(nc: &NotClone) -> NotClone {
nc.clone()
//~^ ERROR mismatched type
//~| NOTE `NotClone` does not implement `Clone`, so `&NotClone` was cloned instead
- //~| NOTE expected struct `NotClone`, found `&NotClone`
+ //~| NOTE expected `NotClone`, found `&NotClone`
}
diff --git a/tests/ui/typeck/explain_clone_autoref.stderr b/tests/ui/typeck/explain_clone_autoref.stderr
index ff36e18d2..4539da438 100644
--- a/tests/ui/typeck/explain_clone_autoref.stderr
+++ b/tests/ui/typeck/explain_clone_autoref.stderr
@@ -5,7 +5,7 @@ LL | fn clone_thing(nc: &NotClone) -> NotClone {
| -------- expected `NotClone` because of return type
LL |
LL | nc.clone()
- | ^^^^^^^^^^ expected struct `NotClone`, found `&NotClone`
+ | ^^^^^^^^^^ expected `NotClone`, found `&NotClone`
|
note: `NotClone` does not implement `Clone`, so `&NotClone` was cloned instead
--> $DIR/explain_clone_autoref.rs:9:5
diff --git a/tests/ui/typeck/issue-100246.stderr b/tests/ui/typeck/issue-100246.stderr
index 8b77de94e..428a07920 100644
--- a/tests/ui/typeck/issue-100246.stderr
+++ b/tests/ui/typeck/issue-100246.stderr
@@ -2,7 +2,7 @@ error[E0308]: `?` operator has incompatible types
--> $DIR/issue-100246.rs:28:24
|
LL | let other: Other = downcast()?;
- | ^^^^^^^^^^^ expected struct `Other`, found reference
+ | ^^^^^^^^^^^ expected `Other`, found `&_`
|
= note: `?` operator cannot convert from `&_` to `Other`
= note: expected struct `Other`
diff --git a/tests/ui/typeck/issue-104513-ice.stderr b/tests/ui/typeck/issue-104513-ice.stderr
index 42cfe38ae..09187d786 100644
--- a/tests/ui/typeck/issue-104513-ice.stderr
+++ b/tests/ui/typeck/issue-104513-ice.stderr
@@ -4,7 +4,7 @@ error[E0405]: cannot find trait `Oops` in this scope
LL | let _: S<impl Oops> = S;
| ^^^^ not found in this scope
-error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in variable binding
+error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in variable bindings
--> $DIR/issue-104513-ice.rs:3:14
|
LL | let _: S<impl Oops> = S;
diff --git a/tests/ui/typeck/issue-107087.rs b/tests/ui/typeck/issue-107087.rs
new file mode 100644
index 000000000..135cdf19e
--- /dev/null
+++ b/tests/ui/typeck/issue-107087.rs
@@ -0,0 +1,18 @@
+struct A<T>(T);
+
+trait Foo {
+ type B;
+}
+
+impl Foo for A<u32> {
+ type B = i32;
+}
+
+impl Foo for A<i32> {
+ type B = i32;
+}
+
+fn main() {
+ A::B::<>::C
+ //~^ ERROR ambiguous associated type
+}
diff --git a/tests/ui/typeck/issue-107087.stderr b/tests/ui/typeck/issue-107087.stderr
new file mode 100644
index 000000000..70f193208
--- /dev/null
+++ b/tests/ui/typeck/issue-107087.stderr
@@ -0,0 +1,9 @@
+error[E0223]: ambiguous associated type
+ --> $DIR/issue-107087.rs:16:5
+ |
+LL | A::B::<>::C
+ | ^^^^^^^^ help: use the fully-qualified path: `<A<_> as Foo>::B`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0223`.
diff --git a/tests/ui/typeck/issue-107775.rs b/tests/ui/typeck/issue-107775.rs
new file mode 100644
index 000000000..6fbac2ee9
--- /dev/null
+++ b/tests/ui/typeck/issue-107775.rs
@@ -0,0 +1,40 @@
+// edition: 2021
+
+use std::collections::HashMap;
+use std::future::Future;
+use std::pin::Pin;
+
+pub trait Trait {
+ fn do_something<'async_trait>(byte: u8)
+ ->
+ Pin<Box<dyn Future<Output = ()> +
+ Send + 'async_trait>>;
+}
+
+pub struct Struct;
+
+impl Trait for Struct {
+ fn do_something<'async_trait>(byte: u8)
+ ->
+ Pin<Box<dyn Future<Output = ()> +
+ Send + 'async_trait>> {
+ Box::pin(
+
+ async move { let byte = byte; let _: () = {}; })
+ }
+}
+
+pub struct Map {
+ map: HashMap<u16, fn(u8) -> Pin<Box<dyn Future<Output = ()> + Send>>>,
+}
+
+impl Map {
+ pub fn new() -> Self {
+ let mut map = HashMap::new();
+ map.insert(1, Struct::do_something);
+ Self { map }
+ //~^ ERROR mismatched types
+ }
+}
+
+fn main() {}
diff --git a/tests/ui/typeck/issue-107775.stderr b/tests/ui/typeck/issue-107775.stderr
new file mode 100644
index 000000000..9ee9c022c
--- /dev/null
+++ b/tests/ui/typeck/issue-107775.stderr
@@ -0,0 +1,16 @@
+error[E0308]: mismatched types
+ --> $DIR/issue-107775.rs:35:16
+ |
+LL | map.insert(1, Struct::do_something);
+ | - -------------------- this is of type `fn(u8) -> Pin<Box<dyn Future<Output = ()> + Send>> {<Struct as Trait>::do_something::<'_>}`, which causes `map` to be inferred as `HashMap<{integer}, fn(u8) -> Pin<Box<dyn Future<Output = ()> + Send>> {<Struct as Trait>::do_something::<'_>}>`
+ | |
+ | this is of type `{integer}`, which causes `map` to be inferred as `HashMap<{integer}, fn(u8) -> Pin<Box<dyn Future<Output = ()> + Send>> {<Struct as Trait>::do_something::<'_>}>`
+LL | Self { map }
+ | ^^^ expected `HashMap<u16, fn(u8) -> Pin<...>>`, found `HashMap<{integer}, ...>`
+ |
+ = note: expected struct `HashMap<u16, fn(_) -> Pin<Box<(dyn Future<Output = ()> + Send + 'static)>>>`
+ found struct `HashMap<{integer}, fn(_) -> Pin<Box<dyn Future<Output = ()> + Send>> {<Struct as Trait>::do_something::<'_>}>`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/typeck/issue-13853.stderr b/tests/ui/typeck/issue-13853.stderr
index 876ac2c67..11d34f5b9 100644
--- a/tests/ui/typeck/issue-13853.stderr
+++ b/tests/ui/typeck/issue-13853.stderr
@@ -5,7 +5,7 @@ LL | fn nodes<'a, I: Iterator<Item=&'a N>>(&self) -> I
| - this type parameter - expected `I` because of return type
...
LL | self.iter()
- | ^^^^^^^^^^^ expected type parameter `I`, found struct `Iter`
+ | ^^^^^^^^^^^ expected type parameter `I`, found `Iter<'_, N>`
|
= note: expected type parameter `I`
found struct `std::slice::Iter<'_, N>`
@@ -22,7 +22,7 @@ error[E0308]: mismatched types
LL | iterate(graph);
| ------- ^^^^^
| | |
- | | expected reference, found struct `Vec`
+ | | expected `&_`, found `Vec<Stuff>`
| | help: consider borrowing here: `&graph`
| arguments to this function are incorrect
|
diff --git a/tests/ui/typeck/issue-31173.stderr b/tests/ui/typeck/issue-31173.stderr
index f3be99f9b..b622122f3 100644
--- a/tests/ui/typeck/issue-31173.stderr
+++ b/tests/ui/typeck/issue-31173.stderr
@@ -2,7 +2,7 @@ error[E0271]: expected `TakeWhile<&mut IntoIter<u8>, [closure@issue-31173.rs:7:2
--> $DIR/issue-31173.rs:11:10
|
LL | .cloned()
- | ^^^^^^ expected reference, found `u8`
+ | ^^^^^^ expected `&_`, found `u8`
|
= note: expected reference `&_`
found type `u8`
@@ -24,8 +24,17 @@ note: required by a bound in `cloned`
error[E0599]: the method `collect` exists for struct `Cloned<TakeWhile<&mut IntoIter<u8>, [closure@issue-31173.rs:7:21]>>`, but its trait bounds were not satisfied
--> $DIR/issue-31173.rs:12:10
|
-LL | .collect();
- | ^^^^^^^ method cannot be called due to unsatisfied trait bounds
+LL | let temp: Vec<u8> = it
+ | _________________________-
+LL | | .take_while(|&x| {
+LL | | found_e = true;
+LL | | false
+LL | | })
+LL | | .cloned()
+LL | | .collect();
+ | | -^^^^^^^ method cannot be called due to unsatisfied trait bounds
+ | |_________|
+ |
--> $SRC_DIR/core/src/iter/adapters/take_while.rs:LL:COL
|
= note: doesn't satisfy `<_ as Iterator>::Item = &_`
diff --git a/tests/ui/typeck/issue-46112.stderr b/tests/ui/typeck/issue-46112.stderr
index 8f5ff51fb..26fc21dda 100644
--- a/tests/ui/typeck/issue-46112.stderr
+++ b/tests/ui/typeck/issue-46112.stderr
@@ -2,7 +2,7 @@ error[E0308]: mismatched types
--> $DIR/issue-46112.rs:9:21
|
LL | fn main() { test(Ok(())); }
- | -- ^^ expected enum `Option`, found `()`
+ | -- ^^ expected `Option<()>`, found `()`
| |
| arguments to this enum variant are incorrect
|
diff --git a/tests/ui/typeck/issue-50687-ice-on-borrow.stderr b/tests/ui/typeck/issue-50687-ice-on-borrow.stderr
index e6a0edac4..9e48ccefd 100644
--- a/tests/ui/typeck/issue-50687-ice-on-borrow.stderr
+++ b/tests/ui/typeck/issue-50687-ice-on-borrow.stderr
@@ -2,7 +2,7 @@ error[E0308]: mismatched types
--> $DIR/issue-50687-ice-on-borrow.rs:40:17
|
LL | let _: () = Borrow::borrow(&owned);
- | -- ^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found reference
+ | -- ^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found `&_`
| |
| expected due to this
|
diff --git a/tests/ui/issues/issue-53712.rs b/tests/ui/typeck/issue-53712.rs
index 2353904d7..2353904d7 100644
--- a/tests/ui/issues/issue-53712.rs
+++ b/tests/ui/typeck/issue-53712.rs
diff --git a/tests/ui/issues/issue-53712.stderr b/tests/ui/typeck/issue-53712.stderr
index db85919af..db85919af 100644
--- a/tests/ui/issues/issue-53712.stderr
+++ b/tests/ui/typeck/issue-53712.stderr
diff --git a/tests/ui/typeck/issue-57673-ice-on-deref-of-boxed-trait.stderr b/tests/ui/typeck/issue-57673-ice-on-deref-of-boxed-trait.stderr
index b92a6f2ec..dc4bc5b5f 100644
--- a/tests/ui/typeck/issue-57673-ice-on-deref-of-boxed-trait.stderr
+++ b/tests/ui/typeck/issue-57673-ice-on-deref-of-boxed-trait.stderr
@@ -4,7 +4,7 @@ error[E0308]: mismatched types
LL | fn ice(x: Box<dyn Iterator<Item=()>>) {
| - help: try adding a return type: `-> (dyn Iterator<Item = ()> + 'static)`
LL | *x
- | ^^ expected `()`, found trait object `dyn Iterator`
+ | ^^ expected `()`, found `dyn Iterator`
|
= note: expected unit type `()`
found trait object `(dyn Iterator<Item = ()> + 'static)`
diff --git a/tests/ui/typeck/issue-67971.stderr b/tests/ui/typeck/issue-67971.stderr
index 5d07f9cc7..d50ed9cf1 100644
--- a/tests/ui/typeck/issue-67971.stderr
+++ b/tests/ui/typeck/issue-67971.stderr
@@ -8,7 +8,7 @@ error[E0308]: mismatched types
--> $DIR/issue-67971.rs:3:24
|
LL | fn foo(ctx: &mut S) -> String {
- | --- ^^^^^^ expected struct `String`, found `()`
+ | --- ^^^^^^ expected `String`, found `()`
| |
| implicitly returns `()` as its body has no tail or `return` expression
diff --git a/tests/ui/typeck/issue-75883.rs b/tests/ui/typeck/issue-75883.rs
index 885acc482..c50ea0a08 100644
--- a/tests/ui/typeck/issue-75883.rs
+++ b/tests/ui/typeck/issue-75883.rs
@@ -4,7 +4,7 @@ pub struct UI {}
impl UI {
pub fn run() -> Result<_> {
- //~^ ERROR: this enum takes 2 generic arguments but 1 generic argument was supplied
+ //~^ ERROR: enum takes 2 generic arguments but 1 generic argument was supplied
//~| ERROR: the placeholder `_` is not allowed within types on item signatures for return types
let mut ui = UI {};
ui.interact();
@@ -13,7 +13,7 @@ impl UI {
}
pub fn interact(&mut self) -> Result<_> {
- //~^ ERROR: this enum takes 2 generic arguments but 1 generic argument was supplied
+ //~^ ERROR: enum takes 2 generic arguments but 1 generic argument was supplied
//~| ERROR: the placeholder `_` is not allowed within types on item signatures for return types
unimplemented!();
}
diff --git a/tests/ui/typeck/issue-75883.stderr b/tests/ui/typeck/issue-75883.stderr
index f5adcabe3..a1ed08406 100644
--- a/tests/ui/typeck/issue-75883.stderr
+++ b/tests/ui/typeck/issue-75883.stderr
@@ -1,4 +1,4 @@
-error[E0107]: this enum takes 2 generic arguments but 1 generic argument was supplied
+error[E0107]: enum takes 2 generic arguments but 1 generic argument was supplied
--> $DIR/issue-75883.rs:6:21
|
LL | pub fn run() -> Result<_> {
@@ -11,7 +11,7 @@ help: add missing generic argument
LL | pub fn run() -> Result<_, E> {
| +++
-error[E0107]: this enum takes 2 generic arguments but 1 generic argument was supplied
+error[E0107]: enum takes 2 generic arguments but 1 generic argument was supplied
--> $DIR/issue-75883.rs:15:35
|
LL | pub fn interact(&mut self) -> Result<_> {
diff --git a/tests/ui/issues/issue-7813.rs b/tests/ui/typeck/issue-7813.rs
index ce549bde6..ce549bde6 100644
--- a/tests/ui/issues/issue-7813.rs
+++ b/tests/ui/typeck/issue-7813.rs
diff --git a/tests/ui/issues/issue-7813.stderr b/tests/ui/typeck/issue-7813.stderr
index 2a747f679..2a747f679 100644
--- a/tests/ui/issues/issue-7813.stderr
+++ b/tests/ui/typeck/issue-7813.stderr
diff --git a/tests/ui/typeck/issue-84160.stderr b/tests/ui/typeck/issue-84160.stderr
index 24c188b3f..4d456ae84 100644
--- a/tests/ui/typeck/issue-84160.stderr
+++ b/tests/ui/typeck/issue-84160.stderr
@@ -5,7 +5,7 @@ LL | fn mismatched_types_with_reference(x: &u32) -> &u32 {
| ---- expected `&u32` because of return type
...
LL | return "test";
- | ^^^^^^ expected `u32`, found `str`
+ | ^^^^^^ expected `&u32`, found `&str`
|
= note: expected reference `&u32`
found reference `&'static str`
diff --git a/tests/ui/typeck/issue-84768.stderr b/tests/ui/typeck/issue-84768.stderr
index 09f3aee2d..3d2d53f5c 100644
--- a/tests/ui/typeck/issue-84768.stderr
+++ b/tests/ui/typeck/issue-84768.stderr
@@ -8,7 +8,7 @@ error[E0308]: mismatched types
--> $DIR/issue-84768.rs:7:42
|
LL | <F as FnOnce(&mut u8)>::call_once(f, 1)
- | --------------------------------- ^ expected tuple, found integer
+ | --------------------------------- ^ expected `(&mut u8,)`, found integer
| |
| arguments to this function are incorrect
|
@@ -21,7 +21,7 @@ LL | <F as FnOnce(&mut u8)>::call_once(f, 1)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-^
| |
| this argument influences the return type of `FnOnce`
-note: associated function defined here
+note: method defined here
--> $SRC_DIR/core/src/ops/function.rs:LL:COL
error: aborting due to 2 previous errors
diff --git a/tests/ui/typeck/issue-89856.fixed b/tests/ui/typeck/issue-89856.fixed
new file mode 100644
index 000000000..3e1a006ef
--- /dev/null
+++ b/tests/ui/typeck/issue-89856.fixed
@@ -0,0 +1,18 @@
+// run-rustfix
+
+fn take_str_maybe(_: Option<&str>) { }
+fn main() {
+ let string = String::from("Hello, world");
+
+ let option: Option<String> = Some(string.clone());
+ take_str_maybe(option.as_deref());
+ //~^ ERROR: mismatched types [E0308]
+
+ let option_ref = Some(&string);
+ take_str_maybe(option_ref.map(|x| x.as_str()));
+ //~^ ERROR: mismatched types [E0308]
+
+ let option_ref_ref = option_ref.as_ref();
+ take_str_maybe(option_ref_ref.map(|x| x.as_str()));
+ //~^ ERROR: mismatched types [E0308]
+}
diff --git a/tests/ui/typeck/issue-89856.rs b/tests/ui/typeck/issue-89856.rs
index b021e349e..cfe6e19b3 100644
--- a/tests/ui/typeck/issue-89856.rs
+++ b/tests/ui/typeck/issue-89856.rs
@@ -1,8 +1,18 @@
-fn take_str_maybe(x: Option<&str>) -> Option<&str> { None }
+// run-rustfix
+fn take_str_maybe(_: Option<&str>) { }
fn main() {
let string = String::from("Hello, world");
- let option = Some(&string);
+
+ let option: Option<String> = Some(string.clone());
take_str_maybe(option);
//~^ ERROR: mismatched types [E0308]
+
+ let option_ref = Some(&string);
+ take_str_maybe(option_ref);
+ //~^ ERROR: mismatched types [E0308]
+
+ let option_ref_ref = option_ref.as_ref();
+ take_str_maybe(option_ref_ref);
+ //~^ ERROR: mismatched types [E0308]
}
diff --git a/tests/ui/typeck/issue-89856.stderr b/tests/ui/typeck/issue-89856.stderr
index 5fa1ae1a5..bd76f1724 100644
--- a/tests/ui/typeck/issue-89856.stderr
+++ b/tests/ui/typeck/issue-89856.stderr
@@ -1,23 +1,63 @@
error[E0308]: mismatched types
- --> $DIR/issue-89856.rs:6:20
+ --> $DIR/issue-89856.rs:8:20
|
LL | take_str_maybe(option);
- | -------------- ^^^^^^ expected `str`, found struct `String`
+ | -------------- ^^^^^^ expected `Option<&str>`, found `Option<String>`
+ | |
+ | arguments to this function are incorrect
+ |
+ = note: expected enum `Option<&str>`
+ found enum `Option<String>`
+note: function defined here
+ --> $DIR/issue-89856.rs:3:4
+ |
+LL | fn take_str_maybe(_: Option<&str>) { }
+ | ^^^^^^^^^^^^^^ ---------------
+help: try converting the passed type into a `&str`
+ |
+LL | take_str_maybe(option.as_deref());
+ | +++++++++++
+
+error[E0308]: mismatched types
+ --> $DIR/issue-89856.rs:12:20
+ |
+LL | take_str_maybe(option_ref);
+ | -------------- ^^^^^^^^^^ expected `Option<&str>`, found `Option<&String>`
| |
| arguments to this function are incorrect
|
= note: expected enum `Option<&str>`
found enum `Option<&String>`
note: function defined here
- --> $DIR/issue-89856.rs:1:4
+ --> $DIR/issue-89856.rs:3:4
+ |
+LL | fn take_str_maybe(_: Option<&str>) { }
+ | ^^^^^^^^^^^^^^ ---------------
+help: try converting the passed type into a `&str`
+ |
+LL | take_str_maybe(option_ref.map(|x| x.as_str()));
+ | ++++++++++++++++++++
+
+error[E0308]: mismatched types
+ --> $DIR/issue-89856.rs:16:20
+ |
+LL | take_str_maybe(option_ref_ref);
+ | -------------- ^^^^^^^^^^^^^^ expected `Option<&str>`, found `Option<&&String>`
+ | |
+ | arguments to this function are incorrect
+ |
+ = note: expected enum `Option<&str>`
+ found enum `Option<&&String>`
+note: function defined here
+ --> $DIR/issue-89856.rs:3:4
|
-LL | fn take_str_maybe(x: Option<&str>) -> Option<&str> { None }
+LL | fn take_str_maybe(_: Option<&str>) { }
| ^^^^^^^^^^^^^^ ---------------
help: try converting the passed type into a `&str`
|
-LL | take_str_maybe(option.map(|x| &**x));
- | ++++++++++++++
+LL | take_str_maybe(option_ref_ref.map(|x| x.as_str()));
+ | ++++++++++++++++++++
-error: aborting due to previous error
+error: aborting due to 3 previous errors
For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/typeck/issue-90027-async-fn-return-suggestion.rs b/tests/ui/typeck/issue-90027-async-fn-return-suggestion.rs
new file mode 100644
index 000000000..8ccb15ca4
--- /dev/null
+++ b/tests/ui/typeck/issue-90027-async-fn-return-suggestion.rs
@@ -0,0 +1,21 @@
+// edition:2018
+
+async fn hello() { //~ HELP try adding a return type
+ 0
+ //~^ ERROR [E0308]
+}
+
+async fn world() -> () {
+ 0
+ //~^ ERROR [E0308]
+}
+
+async fn suggest_await_in_async_fn_return() {
+ hello()
+ //~^ ERROR mismatched types [E0308]
+ //~| HELP consider `await`ing on the `Future`
+ //~| HELP consider using a semicolon here
+ //~| SUGGESTION .await
+}
+
+fn main() {}
diff --git a/tests/ui/typeck/issue-90027-async-fn-return-suggestion.stderr b/tests/ui/typeck/issue-90027-async-fn-return-suggestion.stderr
new file mode 100644
index 000000000..0d72ae118
--- /dev/null
+++ b/tests/ui/typeck/issue-90027-async-fn-return-suggestion.stderr
@@ -0,0 +1,39 @@
+error[E0308]: mismatched types
+ --> $DIR/issue-90027-async-fn-return-suggestion.rs:4:5
+ |
+LL | async fn hello() {
+ | - help: try adding a return type: `-> i32`
+LL | 0
+ | ^ expected `()`, found integer
+
+error[E0308]: mismatched types
+ --> $DIR/issue-90027-async-fn-return-suggestion.rs:9:5
+ |
+LL | async fn world() -> () {
+ | -- expected `()` because of return type
+LL | 0
+ | ^ expected `()`, found integer
+
+error[E0308]: mismatched types
+ --> $DIR/issue-90027-async-fn-return-suggestion.rs:14:5
+ |
+LL | hello()
+ | ^^^^^^^ expected `()`, found future
+ |
+note: calling an async function returns a future
+ --> $DIR/issue-90027-async-fn-return-suggestion.rs:14:5
+ |
+LL | hello()
+ | ^^^^^^^
+help: consider `await`ing on the `Future`
+ |
+LL | hello().await
+ | ++++++
+help: consider using a semicolon here
+ |
+LL | hello();
+ | +
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/typeck/issue-91334.rs b/tests/ui/typeck/issue-91334.rs
index bf9a5a626..29204276b 100644
--- a/tests/ui/typeck/issue-91334.rs
+++ b/tests/ui/typeck/issue-91334.rs
@@ -1,9 +1,6 @@
// Regression test for the ICE described in issue #91334.
// error-pattern: this file contains an unclosed delimiter
-// error-pattern: expected one of
-// error-pattern: mismatched closing delimiter
-// error-pattern: mismatched types
#![feature(generators)]
diff --git a/tests/ui/typeck/issue-91334.stderr b/tests/ui/typeck/issue-91334.stderr
index 8508f7a38..7cb30eea5 100644
--- a/tests/ui/typeck/issue-91334.stderr
+++ b/tests/ui/typeck/issue-91334.stderr
@@ -1,32 +1,5 @@
-error: this file contains an unclosed delimiter
- --> $DIR/issue-91334.rs:10:23
- |
-LL | fn f(){||yield(((){),
- | - - ^
- | | |
- | | unclosed delimiter
- | unclosed delimiter
-
-error: this file contains an unclosed delimiter
- --> $DIR/issue-91334.rs:10:23
- |
-LL | fn f(){||yield(((){),
- | - - ^
- | | |
- | | unclosed delimiter
- | unclosed delimiter
-
-error: expected one of `)`, `,`, `.`, `?`, or an operator, found `{`
- --> $DIR/issue-91334.rs:10:19
- |
-LL | fn f(){||yield(((){),
- | ^
- | |
- | expected one of `)`, `,`, `.`, `?`, or an operator
- | help: missing `,`
-
error: mismatched closing delimiter: `)`
- --> $DIR/issue-91334.rs:10:19
+ --> $DIR/issue-91334.rs:7:19
|
LL | fn f(){||yield(((){),
| - ^^ mismatched closing delimiter
@@ -34,17 +7,15 @@ LL | fn f(){||yield(((){),
| | unclosed delimiter
| closing delimiter possibly meant for this
-error[E0308]: mismatched types
- --> $DIR/issue-91334.rs:10:8
+error: this file contains an unclosed delimiter
+ --> $DIR/issue-91334.rs:7:23
|
LL | fn f(){||yield(((){),
- | -^^^^^^^^^^^^^^^ expected `()`, found generator
- | |
- | help: a return type might be missing here: `-> _`
- |
- = note: expected unit type `()`
- found generator `[generator@$DIR/issue-91334.rs:10:8: 10:10]`
+ | - - - ^
+ | | | |
+ | | | missing open `(` for this delimiter
+ | | unclosed delimiter
+ | unclosed delimiter
-error: aborting due to 5 previous errors
+error: aborting due to 2 previous errors
-For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/typeck/issue-91450-inner-ty-error.stderr b/tests/ui/typeck/issue-91450-inner-ty-error.stderr
index 32f4c8f6f..7ca5446c2 100644
--- a/tests/ui/typeck/issue-91450-inner-ty-error.stderr
+++ b/tests/ui/typeck/issue-91450-inner-ty-error.stderr
@@ -2,7 +2,7 @@ error[E0308]: mismatched types
--> $DIR/issue-91450-inner-ty-error.rs:4:13
|
LL | fn foo() -> Option<_> {}
- | --- ^^^^^^^^^ expected enum `Option`, found `()`
+ | --- ^^^^^^^^^ expected `Option<_>`, found `()`
| |
| implicitly returns `()` as its body has no tail or `return` expression
|
diff --git a/tests/ui/typeck/issue-92481.rs b/tests/ui/typeck/issue-92481.rs
index 0a6b1843d..f752400bb 100644
--- a/tests/ui/typeck/issue-92481.rs
+++ b/tests/ui/typeck/issue-92481.rs
@@ -2,13 +2,8 @@
#![crate_type="lib"]
-fn r({) {
- Ok { //~ ERROR mismatched types [E0308]
+fn r({) { //~ ERROR mismatched closing delimiter
+ Ok {
d..||_=m
}
}
-//~^^^^^ ERROR expected parameter name, found `{`
-//~| ERROR expected one of `,`, `:`, or `}`, found `..`
-//~^^^^^ ERROR cannot find value `d` in this scope [E0425]
-//~| ERROR cannot find value `m` in this scope [E0425]
-//~| ERROR variant `Result<_, _>::Ok` has no field named `d` [E0559]
diff --git a/tests/ui/typeck/issue-92481.stderr b/tests/ui/typeck/issue-92481.stderr
index cd778a649..d87d3277d 100644
--- a/tests/ui/typeck/issue-92481.stderr
+++ b/tests/ui/typeck/issue-92481.stderr
@@ -1,60 +1,11 @@
-error: expected parameter name, found `{`
+error: mismatched closing delimiter: `)`
--> $DIR/issue-92481.rs:5:6
|
LL | fn r({) {
- | ^ expected parameter name
+ | -^^ mismatched closing delimiter
+ | ||
+ | |unclosed delimiter
+ | closing delimiter possibly meant for this
-error: expected one of `,`, `:`, or `}`, found `..`
- --> $DIR/issue-92481.rs:5:6
- |
-LL | fn r({) {
- | ^ unclosed delimiter
-LL | Ok {
-LL | d..||_=m
- | -^
- | |
- | help: `}` may belong here
-
-error[E0425]: cannot find value `d` in this scope
- --> $DIR/issue-92481.rs:7:9
- |
-LL | d..||_=m
- | ^ not found in this scope
-
-error[E0425]: cannot find value `m` in this scope
- --> $DIR/issue-92481.rs:7:16
- |
-LL | d..||_=m
- | ^ not found in this scope
-
-error[E0559]: variant `Result<_, _>::Ok` has no field named `d`
- --> $DIR/issue-92481.rs:7:9
- |
-LL | d..||_=m
- | ^ field does not exist
- --> $SRC_DIR/core/src/result.rs:LL:COL
- |
- = note: `Result<_, _>::Ok` defined here
- |
-help: `Result<_, _>::Ok` is a tuple variant, use the appropriate syntax
- |
-LL | Result<_, _>::Ok(/* fields */)
- |
-
-error[E0308]: mismatched types
- --> $DIR/issue-92481.rs:6:5
- |
-LL | fn r({) {
- | - help: a return type might be missing here: `-> _`
-LL | / Ok {
-LL | | d..||_=m
-LL | | }
- | |_____^ expected `()`, found enum `Result`
- |
- = note: expected unit type `()`
- found enum `Result<_, _>`
-
-error: aborting due to 6 previous errors
+error: aborting due to previous error
-Some errors have detailed explanations: E0308, E0425, E0559.
-For more information about an error, try `rustc --explain E0308`.
diff --git a/tests/ui/typeck/issue-96530.stderr b/tests/ui/typeck/issue-96530.stderr
index 4b4568b1d..3a67ef026 100644
--- a/tests/ui/typeck/issue-96530.stderr
+++ b/tests/ui/typeck/issue-96530.stderr
@@ -2,7 +2,7 @@ error[E0308]: mismatched types
--> $DIR/issue-96530.rs:9:11
|
LL | ..man.clone()
- | ^^^^^^^^^^^ expected struct `Person`, found `&Person`
+ | ^^^^^^^^^^^ expected `Person`, found `&Person`
error: aborting due to previous error
diff --git a/tests/ui/typeck/lazy-norm/cast-checks-handling-projections.rs b/tests/ui/typeck/lazy-norm/cast-checks-handling-projections.rs
new file mode 100644
index 000000000..5ff567cd0
--- /dev/null
+++ b/tests/ui/typeck/lazy-norm/cast-checks-handling-projections.rs
@@ -0,0 +1,6 @@
+// compile-flags: -Ztrait-solver=next
+// known-bug: unknown
+
+fn main() {
+ (0u8 + 0u8) as char;
+}
diff --git a/tests/ui/typeck/lazy-norm/cast-checks-handling-projections.stderr b/tests/ui/typeck/lazy-norm/cast-checks-handling-projections.stderr
new file mode 100644
index 000000000..6b09ccd52
--- /dev/null
+++ b/tests/ui/typeck/lazy-norm/cast-checks-handling-projections.stderr
@@ -0,0 +1,9 @@
+error[E0271]: type mismatch resolving `char == <u8 as Add>::Output`
+ --> $DIR/cast-checks-handling-projections.rs:5:5
+ |
+LL | (0u8 + 0u8) as char;
+ | ^^^^^^^^^^^ types differ
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0271`.
diff --git a/tests/ui/typeck/lazy-norm/equating-projection-cyclically.rs b/tests/ui/typeck/lazy-norm/equating-projection-cyclically.rs
new file mode 100644
index 000000000..019c6e81c
--- /dev/null
+++ b/tests/ui/typeck/lazy-norm/equating-projection-cyclically.rs
@@ -0,0 +1,24 @@
+// compile-flags: -Ztrait-solver=next
+// known-bug: unknown
+
+trait Test {
+ type Assoc;
+}
+
+fn transform<T: Test>(x: T) -> T::Assoc {
+ todo!()
+}
+
+impl Test for i32 {
+ type Assoc = i32;
+}
+
+impl Test for String {
+ type Assoc = String;
+}
+
+fn main() {
+ let mut x = Default::default();
+ x = transform(x);
+ x = 1i32;
+}
diff --git a/tests/ui/typeck/lazy-norm/equating-projection-cyclically.stderr b/tests/ui/typeck/lazy-norm/equating-projection-cyclically.stderr
new file mode 100644
index 000000000..57cbc65a1
--- /dev/null
+++ b/tests/ui/typeck/lazy-norm/equating-projection-cyclically.stderr
@@ -0,0 +1,14 @@
+error[E0308]: mismatched types
+ --> $DIR/equating-projection-cyclically.rs:22:19
+ |
+LL | x = transform(x);
+ | ^ expected inferred type, found associated type
+ |
+ = note: expected type `_`
+ found associated type `<_ as Test>::Assoc`
+ = help: consider constraining the associated type `<_ as Test>::Assoc` to `_`
+ = 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/tests/ui/typeck/remove-extra-argument.stderr b/tests/ui/typeck/remove-extra-argument.stderr
index b734bcd4e..72ddebab4 100644
--- a/tests/ui/typeck/remove-extra-argument.stderr
+++ b/tests/ui/typeck/remove-extra-argument.stderr
@@ -2,17 +2,16 @@ error[E0061]: this function takes 1 argument but 2 arguments were supplied
--> $DIR/remove-extra-argument.rs:6:5
|
LL | l(vec![], vec![])
- | ^ ------ argument of type `Vec<_>` unexpected
+ | ^ --------
+ | | |
+ | | unexpected argument of type `Vec<_>`
+ | help: remove the extra argument
|
note: function defined here
--> $DIR/remove-extra-argument.rs:3:4
|
LL | fn l(_a: Vec<u8>) {}
| ^ -----------
-help: remove the extra argument
- |
-LL | l(vec![])
- | ~~~~~~~~
error: aborting due to previous error
diff --git a/tests/ui/typeck/return_type_containing_closure.rs b/tests/ui/typeck/return_type_containing_closure.rs
index 29624e08a..8b826daee 100644
--- a/tests/ui/typeck/return_type_containing_closure.rs
+++ b/tests/ui/typeck/return_type_containing_closure.rs
@@ -2,7 +2,7 @@
fn foo() { //~ HELP a return type might be missing here
vec!['a'].iter().map(|c| c)
//~^ ERROR mismatched types [E0308]
- //~| NOTE expected `()`, found struct `Map`
+ //~| NOTE expected `()`, found `Map<Iter<'_, char>, ...>`
//~| NOTE expected unit type `()`
//~| HELP consider using a semicolon here
}
diff --git a/tests/ui/typeck/return_type_containing_closure.stderr b/tests/ui/typeck/return_type_containing_closure.stderr
index 101aee395..f9a240963 100644
--- a/tests/ui/typeck/return_type_containing_closure.stderr
+++ b/tests/ui/typeck/return_type_containing_closure.stderr
@@ -2,7 +2,7 @@ error[E0308]: mismatched types
--> $DIR/return_type_containing_closure.rs:3:5
|
LL | vec!['a'].iter().map(|c| c)
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found struct `Map`
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found `Map<Iter<'_, char>, ...>`
|
= note: expected unit type `()`
found struct `Map<std::slice::Iter<'_, char>, [closure@$DIR/return_type_containing_closure.rs:3:26: 3:29]>`
diff --git a/tests/ui/typeck/struct-enum-wrong-args.stderr b/tests/ui/typeck/struct-enum-wrong-args.stderr
index fbced928a..57cbd1d20 100644
--- a/tests/ui/typeck/struct-enum-wrong-args.stderr
+++ b/tests/ui/typeck/struct-enum-wrong-args.stderr
@@ -2,29 +2,29 @@ error[E0061]: this enum variant takes 1 argument but 2 arguments were supplied
--> $DIR/struct-enum-wrong-args.rs:6:13
|
LL | let _ = Some(3, 2);
- | ^^^^ - argument of type `{integer}` unexpected
+ | ^^^^ ---
+ | | |
+ | | unexpected argument of type `{integer}`
+ | help: remove the extra argument
|
note: tuple variant defined here
--> $SRC_DIR/core/src/option.rs:LL:COL
-help: remove the extra argument
- |
-LL | let _ = Some(3);
- | ~~~
error[E0061]: this enum variant takes 1 argument but 3 arguments were supplied
--> $DIR/struct-enum-wrong-args.rs:7:13
|
LL | let _ = Ok(3, 6, 2);
- | ^^ - - argument of type `{integer}` unexpected
+ | ^^ - - unexpected argument of type `{integer}`
| |
- | argument of type `{integer}` unexpected
+ | unexpected argument of type `{integer}`
|
note: tuple variant defined here
--> $SRC_DIR/core/src/result.rs:LL:COL
help: remove the extra arguments
|
-LL | let _ = Ok(3);
- | ~~~
+LL - let _ = Ok(3, 6, 2);
+LL + let _ = Ok(3);
+ |
error[E0061]: this enum variant takes 1 argument but 0 arguments were supplied
--> $DIR/struct-enum-wrong-args.rs:8:13
@@ -59,17 +59,16 @@ error[E0061]: this struct takes 1 argument but 2 arguments were supplied
--> $DIR/struct-enum-wrong-args.rs:10:13
|
LL | let _ = Wrapper(5, 2);
- | ^^^^^^^ - argument of type `{integer}` unexpected
+ | ^^^^^^^ ---
+ | | |
+ | | unexpected argument of type `{integer}`
+ | help: remove the extra argument
|
note: tuple struct defined here
--> $DIR/struct-enum-wrong-args.rs:2:8
|
LL | struct Wrapper(i32);
| ^^^^^^^
-help: remove the extra argument
- |
-LL | let _ = Wrapper(5);
- | ~~~
error[E0061]: this struct takes 2 arguments but 0 arguments were supplied
--> $DIR/struct-enum-wrong-args.rs:11:13
@@ -107,17 +106,16 @@ error[E0061]: this struct takes 2 arguments but 3 arguments were supplied
--> $DIR/struct-enum-wrong-args.rs:13:13
|
LL | let _ = DoubleWrapper(5, 2, 7);
- | ^^^^^^^^^^^^^ - argument of type `{integer}` unexpected
+ | ^^^^^^^^^^^^^ ---
+ | | |
+ | | unexpected argument of type `{integer}`
+ | help: remove the extra argument
|
note: tuple struct defined here
--> $DIR/struct-enum-wrong-args.rs:3:8
|
LL | struct DoubleWrapper(i32, i32);
| ^^^^^^^^^^^^^
-help: remove the extra argument
- |
-LL | let _ = DoubleWrapper(5, 2);
- | ~~~~~~
error: aborting due to 8 previous errors
diff --git a/tests/ui/typeck/typeck-builtin-bound-type-parameters.rs b/tests/ui/typeck/typeck-builtin-bound-type-parameters.rs
index c463a8ad0..7ff9199f6 100644
--- a/tests/ui/typeck/typeck-builtin-bound-type-parameters.rs
+++ b/tests/ui/typeck/typeck-builtin-bound-type-parameters.rs
@@ -1,17 +1,17 @@
fn foo1<T:Copy<U>, U>(x: T) {}
-//~^ ERROR this trait takes 0 generic arguments but 1 generic argument was supplied
+//~^ ERROR trait takes 0 generic arguments but 1 generic argument was supplied
trait Trait: Copy<dyn Send> {}
-//~^ ERROR this trait takes 0 generic arguments but 1 generic argument was supplied
+//~^ ERROR trait takes 0 generic arguments but 1 generic argument was supplied
struct MyStruct1<T: Copy<T>>;
-//~^ ERROR this trait takes 0 generic arguments but 1 generic argument was supplied
+//~^ ERROR trait takes 0 generic arguments but 1 generic argument was supplied
struct MyStruct2<'a, T: Copy<'a>>;
-//~^ ERROR this trait takes 0 lifetime arguments but 1 lifetime argument was supplied
+//~^ ERROR trait takes 0 lifetime arguments but 1 lifetime argument was supplied
fn foo2<'a, T:Copy<'a, U>, U>(x: T) {}
-//~^ ERROR this trait takes 0 lifetime arguments but 1 lifetime argument was supplied
-//~| ERROR this trait takes 0 generic arguments but 1 generic argument was supplied
+//~^ ERROR trait takes 0 lifetime arguments but 1 lifetime argument was supplied
+//~| ERROR trait takes 0 generic arguments but 1 generic argument was supplied
fn main() { }
diff --git a/tests/ui/typeck/typeck-builtin-bound-type-parameters.stderr b/tests/ui/typeck/typeck-builtin-bound-type-parameters.stderr
index 331540d1e..a71fd9536 100644
--- a/tests/ui/typeck/typeck-builtin-bound-type-parameters.stderr
+++ b/tests/ui/typeck/typeck-builtin-bound-type-parameters.stderr
@@ -1,4 +1,4 @@
-error[E0107]: this trait takes 0 generic arguments but 1 generic argument was supplied
+error[E0107]: trait takes 0 generic arguments but 1 generic argument was supplied
--> $DIR/typeck-builtin-bound-type-parameters.rs:1:11
|
LL | fn foo1<T:Copy<U>, U>(x: T) {}
@@ -6,7 +6,7 @@ LL | fn foo1<T:Copy<U>, U>(x: T) {}
| |
| expected 0 generic arguments
-error[E0107]: this trait takes 0 generic arguments but 1 generic argument was supplied
+error[E0107]: trait takes 0 generic arguments but 1 generic argument was supplied
--> $DIR/typeck-builtin-bound-type-parameters.rs:4:14
|
LL | trait Trait: Copy<dyn Send> {}
@@ -14,7 +14,7 @@ LL | trait Trait: Copy<dyn Send> {}
| |
| expected 0 generic arguments
-error[E0107]: this trait takes 0 generic arguments but 1 generic argument was supplied
+error[E0107]: trait takes 0 generic arguments but 1 generic argument was supplied
--> $DIR/typeck-builtin-bound-type-parameters.rs:7:21
|
LL | struct MyStruct1<T: Copy<T>>;
@@ -22,7 +22,7 @@ LL | struct MyStruct1<T: Copy<T>>;
| |
| expected 0 generic arguments
-error[E0107]: this trait takes 0 lifetime arguments but 1 lifetime argument was supplied
+error[E0107]: trait takes 0 lifetime arguments but 1 lifetime argument was supplied
--> $DIR/typeck-builtin-bound-type-parameters.rs:10:25
|
LL | struct MyStruct2<'a, T: Copy<'a>>;
@@ -30,7 +30,7 @@ LL | struct MyStruct2<'a, T: Copy<'a>>;
| |
| expected 0 lifetime arguments
-error[E0107]: this trait takes 0 lifetime arguments but 1 lifetime argument was supplied
+error[E0107]: trait takes 0 lifetime arguments but 1 lifetime argument was supplied
--> $DIR/typeck-builtin-bound-type-parameters.rs:13:15
|
LL | fn foo2<'a, T:Copy<'a, U>, U>(x: T) {}
@@ -38,7 +38,7 @@ LL | fn foo2<'a, T:Copy<'a, U>, U>(x: T) {}
| |
| expected 0 lifetime arguments
-error[E0107]: this trait takes 0 generic arguments but 1 generic argument was supplied
+error[E0107]: trait takes 0 generic arguments but 1 generic argument was supplied
--> $DIR/typeck-builtin-bound-type-parameters.rs:13:15
|
LL | fn foo2<'a, T:Copy<'a, U>, U>(x: T) {}
diff --git a/tests/ui/typeck/typeck_type_placeholder_item.rs b/tests/ui/typeck/typeck_type_placeholder_item.rs
index b96c52713..a450dbb82 100644
--- a/tests/ui/typeck/typeck_type_placeholder_item.rs
+++ b/tests/ui/typeck/typeck_type_placeholder_item.rs
@@ -227,4 +227,6 @@ fn evens_squared(n: usize) -> _ {
}
const _: _ = (1..10).filter(|x| x % 2 == 0).map(|x| x * x);
-//~^ ERROR the placeholder `_` is not allowed within types on item signatures for constants
+//~^ ERROR the trait bound
+//~| ERROR the trait bound
+//~| ERROR the placeholder
diff --git a/tests/ui/typeck/typeck_type_placeholder_item.stderr b/tests/ui/typeck/typeck_type_placeholder_item.stderr
index bc02547c6..bc6c9fd07 100644
--- a/tests/ui/typeck/typeck_type_placeholder_item.stderr
+++ b/tests/ui/typeck/typeck_type_placeholder_item.stderr
@@ -437,17 +437,37 @@ LL | fn evens_squared(n: usize) -> _ {
| not allowed in type signatures
| help: replace with an appropriate return type: `impl Iterator<Item = usize>`
-error[E0121]: the placeholder `_` is not allowed within types on item signatures for constants
- --> $DIR/typeck_type_placeholder_item.rs:229:10
+error[E0277]: the trait bound `std::ops::Range<{integer}>: Iterator` is not satisfied
+ --> $DIR/typeck_type_placeholder_item.rs:229:22
|
LL | const _: _ = (1..10).filter(|x| x % 2 == 0).map(|x| x * x);
- | ^ not allowed in type signatures
+ | ^^^^^^ `std::ops::Range<{integer}>` is not an iterator
+ |
+ = help: the trait `~const Iterator` is not implemented for `std::ops::Range<{integer}>`
+note: the trait `Iterator` is implemented for `std::ops::Range<{integer}>`, but that implementation is not `const`
+ --> $DIR/typeck_type_placeholder_item.rs:229:14
+ |
+LL | const _: _ = (1..10).filter(|x| x % 2 == 0).map(|x| x * x);
+ | ^^^^^^^
+
+error[E0277]: the trait bound `Filter<std::ops::Range<{integer}>, [closure@$DIR/typeck_type_placeholder_item.rs:229:29: 229:32]>: Iterator` is not satisfied
+ --> $DIR/typeck_type_placeholder_item.rs:229:45
|
-note: however, the inferred type `Map<Filter<Range<i32>, [closure@typeck_type_placeholder_item.rs:229:29]>, [closure@typeck_type_placeholder_item.rs:229:49]>` cannot be named
+LL | const _: _ = (1..10).filter(|x| x % 2 == 0).map(|x| x * x);
+ | ^^^ `Filter<std::ops::Range<{integer}>, [closure@$DIR/typeck_type_placeholder_item.rs:229:29: 229:32]>` is not an iterator
+ |
+ = help: the trait `~const Iterator` is not implemented for `Filter<std::ops::Range<{integer}>, [closure@$DIR/typeck_type_placeholder_item.rs:229:29: 229:32]>`
+note: the trait `Iterator` is implemented for `Filter<std::ops::Range<{integer}>, [closure@$DIR/typeck_type_placeholder_item.rs:229:29: 229:32]>`, but that implementation is not `const`
--> $DIR/typeck_type_placeholder_item.rs:229:14
|
LL | const _: _ = (1..10).filter(|x| x % 2 == 0).map(|x| x * x);
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0121]: the placeholder `_` is not allowed within types on item signatures for constants
+ --> $DIR/typeck_type_placeholder_item.rs:229:10
+ |
+LL | const _: _ = (1..10).filter(|x| x % 2 == 0).map(|x| x * x);
+ | ^ not allowed in type signatures
error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions
--> $DIR/typeck_type_placeholder_item.rs:140:31
@@ -657,7 +677,7 @@ LL | const D: _ = 42;
| not allowed in type signatures
| help: replace with the correct type: `i32`
-error: aborting due to 71 previous errors
+error: aborting due to 73 previous errors
-Some errors have detailed explanations: E0121, E0282, E0403.
+Some errors have detailed explanations: E0121, E0277, E0282, E0403.
For more information about an error, try `rustc --explain E0121`.
diff --git a/tests/ui/typeck/typeck_type_placeholder_lifetime_1.rs b/tests/ui/typeck/typeck_type_placeholder_lifetime_1.rs
index 43e46c5b6..90b12ffdf 100644
--- a/tests/ui/typeck/typeck_type_placeholder_lifetime_1.rs
+++ b/tests/ui/typeck/typeck_type_placeholder_lifetime_1.rs
@@ -7,5 +7,5 @@ struct Foo<'a, T:'a> {
pub fn main() {
let c: Foo<_, _> = Foo { r: &5 };
- //~^ ERROR this struct takes 1 generic argument but 2 generic arguments were supplied
+ //~^ ERROR struct takes 1 generic argument but 2 generic arguments were supplied
}
diff --git a/tests/ui/typeck/typeck_type_placeholder_lifetime_1.stderr b/tests/ui/typeck/typeck_type_placeholder_lifetime_1.stderr
index a89c6b85c..c4e4aed20 100644
--- a/tests/ui/typeck/typeck_type_placeholder_lifetime_1.stderr
+++ b/tests/ui/typeck/typeck_type_placeholder_lifetime_1.stderr
@@ -1,4 +1,4 @@
-error[E0107]: this struct takes 1 generic argument but 2 generic arguments were supplied
+error[E0107]: struct takes 1 generic argument but 2 generic arguments were supplied
--> $DIR/typeck_type_placeholder_lifetime_1.rs:9:12
|
LL | let c: Foo<_, _> = Foo { r: &5 };
diff --git a/tests/ui/typeck/typeck_type_placeholder_lifetime_2.rs b/tests/ui/typeck/typeck_type_placeholder_lifetime_2.rs
index 178b8b122..e361312dd 100644
--- a/tests/ui/typeck/typeck_type_placeholder_lifetime_2.rs
+++ b/tests/ui/typeck/typeck_type_placeholder_lifetime_2.rs
@@ -7,5 +7,5 @@ struct Foo<'a, T:'a> {
pub fn main() {
let c: Foo<_, usize> = Foo { r: &5 };
- //~^ ERROR this struct takes 1 generic argument but 2 generic arguments were supplied
+ //~^ ERROR struct takes 1 generic argument but 2 generic arguments were supplied
}
diff --git a/tests/ui/typeck/typeck_type_placeholder_lifetime_2.stderr b/tests/ui/typeck/typeck_type_placeholder_lifetime_2.stderr
index f30766bdf..302231777 100644
--- a/tests/ui/typeck/typeck_type_placeholder_lifetime_2.stderr
+++ b/tests/ui/typeck/typeck_type_placeholder_lifetime_2.stderr
@@ -1,4 +1,4 @@
-error[E0107]: this struct takes 1 generic argument but 2 generic arguments were supplied
+error[E0107]: struct takes 1 generic argument but 2 generic arguments were supplied
--> $DIR/typeck_type_placeholder_lifetime_2.rs:9:12
|
LL | let c: Foo<_, usize> = Foo { r: &5 };
diff --git a/tests/ui/typeck/typeck_type_placeholder_mismatch.rs b/tests/ui/typeck/typeck_type_placeholder_mismatch.rs
index 2f9cfcf8d..718b6deed 100644
--- a/tests/ui/typeck/typeck_type_placeholder_mismatch.rs
+++ b/tests/ui/typeck/typeck_type_placeholder_mismatch.rs
@@ -14,7 +14,7 @@ fn test1() {
//~^ ERROR mismatched types
//~| expected struct `Foo<_>`
//~| found struct `Bar<usize>`
- //~| expected struct `Foo`, found struct `Bar`
+ //~| expected `Foo<_>`, found `Bar<usize>`
let y: Foo<usize> = x;
}
@@ -23,5 +23,5 @@ fn test2() {
//~^ ERROR mismatched types
//~| expected struct `Foo<_>`
//~| found struct `Bar<usize>`
- //~| expected struct `Foo`, found struct `Bar`
+ //~| expected `Foo<_>`, found `Bar<usize>`
}
diff --git a/tests/ui/typeck/typeck_type_placeholder_mismatch.stderr b/tests/ui/typeck/typeck_type_placeholder_mismatch.stderr
index 867412a24..bf8e0bbb5 100644
--- a/tests/ui/typeck/typeck_type_placeholder_mismatch.stderr
+++ b/tests/ui/typeck/typeck_type_placeholder_mismatch.stderr
@@ -2,7 +2,7 @@ error[E0308]: mismatched types
--> $DIR/typeck_type_placeholder_mismatch.rs:13:21
|
LL | let x: Foo<_> = Bar::<usize>(PhantomData);
- | ------ ^^^^^^^^^^^^^^^^^^^^^^^^^ expected struct `Foo`, found struct `Bar`
+ | ------ ^^^^^^^^^^^^^^^^^^^^^^^^^ expected `Foo<_>`, found `Bar<usize>`
| |
| expected due to this
|
@@ -13,7 +13,7 @@ error[E0308]: mismatched types
--> $DIR/typeck_type_placeholder_mismatch.rs:22:21
|
LL | let x: Foo<_> = Bar::<usize>(PhantomData);
- | ------ ^^^^^^^^^^^^^^^^^^^^^^^^^ expected struct `Foo`, found struct `Bar`
+ | ------ ^^^^^^^^^^^^^^^^^^^^^^^^^ expected `Foo<_>`, found `Bar<usize>`
| |
| expected due to this
|
diff --git a/tests/ui/ufcs/ufcs-qpath-missing-params.rs b/tests/ui/ufcs/ufcs-qpath-missing-params.rs
index 766351634..6ab6580c0 100644
--- a/tests/ui/ufcs/ufcs-qpath-missing-params.rs
+++ b/tests/ui/ufcs/ufcs-qpath-missing-params.rs
@@ -15,6 +15,6 @@ fn main() {
//~^ ERROR missing generics for
<String as IntoCow>::into_cow::<str>("foo".to_string());
- //~^ ERROR this associated function takes 0 generic arguments but 1
+ //~^ ERROR method takes 0 generic arguments but 1
//~| ERROR missing generics for
}
diff --git a/tests/ui/ufcs/ufcs-qpath-missing-params.stderr b/tests/ui/ufcs/ufcs-qpath-missing-params.stderr
index d0ec47d61..233887121 100644
--- a/tests/ui/ufcs/ufcs-qpath-missing-params.stderr
+++ b/tests/ui/ufcs/ufcs-qpath-missing-params.stderr
@@ -30,7 +30,7 @@ help: add missing generic argument
LL | <String as IntoCow<B>>::into_cow::<str>("foo".to_string());
| +++
-error[E0107]: this associated function takes 0 generic arguments but 1 generic argument was supplied
+error[E0107]: method takes 0 generic arguments but 1 generic argument was supplied
--> $DIR/ufcs-qpath-missing-params.rs:17:26
|
LL | <String as IntoCow>::into_cow::<str>("foo".to_string());
@@ -38,7 +38,7 @@ LL | <String as IntoCow>::into_cow::<str>("foo".to_string());
| |
| expected 0 generic arguments
|
-note: associated function defined here, with 0 generic parameters
+note: method defined here, with 0 generic parameters
--> $DIR/ufcs-qpath-missing-params.rs:4:8
|
LL | fn into_cow(self) -> Cow<'a, B>;
diff --git a/tests/ui/ufcs/ufcs-qpath-self-mismatch.stderr b/tests/ui/ufcs/ufcs-qpath-self-mismatch.stderr
index e85144a31..96ac43216 100644
--- a/tests/ui/ufcs/ufcs-qpath-self-mismatch.stderr
+++ b/tests/ui/ufcs/ufcs-qpath-self-mismatch.stderr
@@ -28,7 +28,7 @@ LL | <i32 as Add<i32>>::add(1u32, 2);
| ^^^^^^^^^^^^^^^^^^^^^^^----^^^^
| |
| this argument influences the return type of `Add`
-note: associated function defined here
+note: method defined here
--> $SRC_DIR/core/src/ops/arith.rs:LL:COL
help: change the type of the numeric literal from `u32` to `i32`
|
@@ -50,7 +50,7 @@ LL | <i32 as Add<i32>>::add(1, 2u32);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^----^
| |
| this argument influences the return type of `Add`
-note: associated function defined here
+note: method defined here
--> $SRC_DIR/core/src/ops/arith.rs:LL:COL
help: change the type of the numeric literal from `u32` to `i32`
|
diff --git a/tests/ui/unboxed-closures/unboxed-closure-sugar-region.rs b/tests/ui/unboxed-closures/unboxed-closure-sugar-region.rs
index 65f40075b..c575f5077 100644
--- a/tests/ui/unboxed-closures/unboxed-closure-sugar-region.rs
+++ b/tests/ui/unboxed-closures/unboxed-closure-sugar-region.rs
@@ -28,7 +28,7 @@ fn test<'a,'b>() {
}
fn test2(x: &dyn Foo<(isize,),Output=()>, y: &dyn Foo(isize)) {
- //~^ ERROR this trait takes 1 lifetime argument but 0 lifetime arguments were supplied
+ //~^ ERROR trait takes 1 lifetime argument but 0 lifetime arguments were supplied
// Here, the omitted lifetimes are expanded to distinct things.
same_type(x, y)
}
diff --git a/tests/ui/unboxed-closures/unboxed-closure-sugar-region.stderr b/tests/ui/unboxed-closures/unboxed-closure-sugar-region.stderr
index 016fc4dfb..881461781 100644
--- a/tests/ui/unboxed-closures/unboxed-closure-sugar-region.stderr
+++ b/tests/ui/unboxed-closures/unboxed-closure-sugar-region.stderr
@@ -1,4 +1,4 @@
-error[E0107]: this trait takes 1 lifetime argument but 0 lifetime arguments were supplied
+error[E0107]: trait takes 1 lifetime argument but 0 lifetime arguments were supplied
--> $DIR/unboxed-closure-sugar-region.rs:30:51
|
LL | fn test2(x: &dyn Foo<(isize,),Output=()>, y: &dyn Foo(isize)) {
diff --git a/tests/ui/unboxed-closures/unboxed-closure-sugar-used-on-struct-1.rs b/tests/ui/unboxed-closures/unboxed-closure-sugar-used-on-struct-1.rs
index 462f6fb7b..14d5646b5 100644
--- a/tests/ui/unboxed-closures/unboxed-closure-sugar-used-on-struct-1.rs
+++ b/tests/ui/unboxed-closures/unboxed-closure-sugar-used-on-struct-1.rs
@@ -7,7 +7,7 @@ struct Bar<A> {
fn bar() {
let x: Box<Bar()> = panic!();
//~^ ERROR parenthesized type parameters may only be used with a `Fn` trait
- //~| ERROR this struct takes 1 generic argument but 0 generic arguments
+ //~| ERROR struct takes 1 generic argument but 0 generic arguments
}
fn main() { }
diff --git a/tests/ui/unboxed-closures/unboxed-closure-sugar-used-on-struct-1.stderr b/tests/ui/unboxed-closures/unboxed-closure-sugar-used-on-struct-1.stderr
index 29ea5735c..27b22c212 100644
--- a/tests/ui/unboxed-closures/unboxed-closure-sugar-used-on-struct-1.stderr
+++ b/tests/ui/unboxed-closures/unboxed-closure-sugar-used-on-struct-1.stderr
@@ -4,7 +4,7 @@ error[E0214]: parenthesized type parameters may only be used with a `Fn` trait
LL | let x: Box<Bar()> = panic!();
| ^^^^^ only `Fn` traits may use parentheses
-error[E0107]: this struct takes 1 generic argument but 0 generic arguments were supplied
+error[E0107]: struct takes 1 generic argument but 0 generic arguments were supplied
--> $DIR/unboxed-closure-sugar-used-on-struct-1.rs:8:16
|
LL | let x: Box<Bar()> = panic!();
diff --git a/tests/ui/unboxed-closures/unboxed-closure-sugar-used-on-struct.rs b/tests/ui/unboxed-closures/unboxed-closure-sugar-used-on-struct.rs
index bd61cbd80..657b29204 100644
--- a/tests/ui/unboxed-closures/unboxed-closure-sugar-used-on-struct.rs
+++ b/tests/ui/unboxed-closures/unboxed-closure-sugar-used-on-struct.rs
@@ -6,7 +6,7 @@ struct Bar<A> {
fn foo(b: Box<Bar()>) {
//~^ ERROR parenthesized type parameters may only be used with a `Fn` trait
- //~| ERROR this struct takes 1 generic argument but 0 generic arguments
+ //~| ERROR struct takes 1 generic argument but 0 generic arguments
}
fn main() { }
diff --git a/tests/ui/unboxed-closures/unboxed-closure-sugar-used-on-struct.stderr b/tests/ui/unboxed-closures/unboxed-closure-sugar-used-on-struct.stderr
index 427ba3414..94e42a66c 100644
--- a/tests/ui/unboxed-closures/unboxed-closure-sugar-used-on-struct.stderr
+++ b/tests/ui/unboxed-closures/unboxed-closure-sugar-used-on-struct.stderr
@@ -4,7 +4,7 @@ error[E0214]: parenthesized type parameters may only be used with a `Fn` trait
LL | fn foo(b: Box<Bar()>) {
| ^^^^^ only `Fn` traits may use parentheses
-error[E0107]: this struct takes 1 generic argument but 0 generic arguments were supplied
+error[E0107]: struct takes 1 generic argument but 0 generic arguments were supplied
--> $DIR/unboxed-closure-sugar-used-on-struct.rs:7:15
|
LL | fn foo(b: Box<Bar()>) {
diff --git a/tests/ui/unboxed-closures/unboxed-closure-sugar-wrong-number-number-type-parameters-3.rs b/tests/ui/unboxed-closures/unboxed-closure-sugar-wrong-number-number-type-parameters-3.rs
index f26ad8e93..dd47ae73a 100644
--- a/tests/ui/unboxed-closures/unboxed-closure-sugar-wrong-number-number-type-parameters-3.rs
+++ b/tests/ui/unboxed-closures/unboxed-closure-sugar-wrong-number-number-type-parameters-3.rs
@@ -3,7 +3,7 @@
trait Three<A,B,C> { fn dummy(&self) -> (A,B,C); }
fn foo(_: &dyn Three())
-//~^ ERROR this trait takes 3 generic arguments but 1 generic argument
+//~^ ERROR trait takes 3 generic arguments but 1 generic argument
//~| ERROR associated type `Output` not found
{}
diff --git a/tests/ui/unboxed-closures/unboxed-closure-sugar-wrong-number-number-type-parameters-3.stderr b/tests/ui/unboxed-closures/unboxed-closure-sugar-wrong-number-number-type-parameters-3.stderr
index ebaacf0a6..5d7fe3fa5 100644
--- a/tests/ui/unboxed-closures/unboxed-closure-sugar-wrong-number-number-type-parameters-3.stderr
+++ b/tests/ui/unboxed-closures/unboxed-closure-sugar-wrong-number-number-type-parameters-3.stderr
@@ -1,4 +1,4 @@
-error[E0107]: this trait takes 3 generic arguments but 1 generic argument was supplied
+error[E0107]: trait takes 3 generic arguments but 1 generic argument was supplied
--> $DIR/unboxed-closure-sugar-wrong-number-number-type-parameters-3.rs:5:16
|
LL | fn foo(_: &dyn Three())
diff --git a/tests/ui/unboxed-closures/unboxed-closure-sugar-wrong-number-number-type-parameters.rs b/tests/ui/unboxed-closures/unboxed-closure-sugar-wrong-number-number-type-parameters.rs
index 4465b43a7..2c7e12f32 100644
--- a/tests/ui/unboxed-closures/unboxed-closure-sugar-wrong-number-number-type-parameters.rs
+++ b/tests/ui/unboxed-closures/unboxed-closure-sugar-wrong-number-number-type-parameters.rs
@@ -3,25 +3,25 @@
trait Zero { fn dummy(&self); }
fn foo1(_: dyn Zero()) {
- //~^ ERROR this trait takes 0 generic arguments but 1 generic argument
+ //~^ ERROR trait takes 0 generic arguments but 1 generic argument
//~| ERROR associated type `Output` not found for `Zero`
}
fn foo2(_: dyn Zero<usize>) {
- //~^ ERROR this trait takes 0 generic arguments but 1 generic argument
+ //~^ ERROR trait takes 0 generic arguments but 1 generic argument
}
fn foo3(_: dyn Zero < usize >) {
- //~^ ERROR this trait takes 0 generic arguments but 1 generic argument
+ //~^ ERROR trait takes 0 generic arguments but 1 generic argument
}
fn foo4(_: dyn Zero(usize)) {
- //~^ ERROR this trait takes 0 generic arguments but 1 generic argument
+ //~^ ERROR trait takes 0 generic arguments but 1 generic argument
//~| ERROR associated type `Output` not found for `Zero`
}
fn foo5(_: dyn Zero ( usize )) {
- //~^ ERROR this trait takes 0 generic arguments but 1 generic argument
+ //~^ ERROR trait takes 0 generic arguments but 1 generic argument
//~| ERROR associated type `Output` not found for `Zero`
}
diff --git a/tests/ui/unboxed-closures/unboxed-closure-sugar-wrong-number-number-type-parameters.stderr b/tests/ui/unboxed-closures/unboxed-closure-sugar-wrong-number-number-type-parameters.stderr
index 9601e64c1..50b90553a 100644
--- a/tests/ui/unboxed-closures/unboxed-closure-sugar-wrong-number-number-type-parameters.stderr
+++ b/tests/ui/unboxed-closures/unboxed-closure-sugar-wrong-number-number-type-parameters.stderr
@@ -1,4 +1,4 @@
-error[E0107]: this trait takes 0 generic arguments but 1 generic argument was supplied
+error[E0107]: trait takes 0 generic arguments but 1 generic argument was supplied
--> $DIR/unboxed-closure-sugar-wrong-number-number-type-parameters.rs:5:16
|
LL | fn foo1(_: dyn Zero()) {
@@ -18,7 +18,7 @@ error[E0220]: associated type `Output` not found for `Zero`
LL | fn foo1(_: dyn Zero()) {
| ^^^^^^ associated type `Output` not found
-error[E0107]: this trait takes 0 generic arguments but 1 generic argument was supplied
+error[E0107]: trait takes 0 generic arguments but 1 generic argument was supplied
--> $DIR/unboxed-closure-sugar-wrong-number-number-type-parameters.rs:10:16
|
LL | fn foo2(_: dyn Zero<usize>) {
@@ -32,7 +32,7 @@ note: trait defined here, with 0 generic parameters
LL | trait Zero { fn dummy(&self); }
| ^^^^
-error[E0107]: this trait takes 0 generic arguments but 1 generic argument was supplied
+error[E0107]: trait takes 0 generic arguments but 1 generic argument was supplied
--> $DIR/unboxed-closure-sugar-wrong-number-number-type-parameters.rs:14:16
|
LL | fn foo3(_: dyn Zero < usize >) {
@@ -46,7 +46,7 @@ note: trait defined here, with 0 generic parameters
LL | trait Zero { fn dummy(&self); }
| ^^^^
-error[E0107]: this trait takes 0 generic arguments but 1 generic argument was supplied
+error[E0107]: trait takes 0 generic arguments but 1 generic argument was supplied
--> $DIR/unboxed-closure-sugar-wrong-number-number-type-parameters.rs:18:16
|
LL | fn foo4(_: dyn Zero(usize)) {
@@ -66,7 +66,7 @@ error[E0220]: associated type `Output` not found for `Zero`
LL | fn foo4(_: dyn Zero(usize)) {
| ^^^^^^^^^^^ associated type `Output` not found
-error[E0107]: this trait takes 0 generic arguments but 1 generic argument was supplied
+error[E0107]: trait takes 0 generic arguments but 1 generic argument was supplied
--> $DIR/unboxed-closure-sugar-wrong-number-number-type-parameters.rs:23:16
|
LL | fn foo5(_: dyn Zero ( usize )) {
diff --git a/tests/ui/unboxed-closures/unboxed-closure-sugar-wrong-trait.rs b/tests/ui/unboxed-closures/unboxed-closure-sugar-wrong-trait.rs
index 4bcf90552..ad60b0a0c 100644
--- a/tests/ui/unboxed-closures/unboxed-closure-sugar-wrong-trait.rs
+++ b/tests/ui/unboxed-closures/unboxed-closure-sugar-wrong-trait.rs
@@ -3,7 +3,7 @@
trait Trait {}
fn f<F:Trait(isize) -> isize>(x: F) {}
-//~^ ERROR this trait takes 0 generic arguments but 1 generic argument
+//~^ ERROR trait takes 0 generic arguments but 1 generic argument
//~| ERROR associated type `Output` not found for `Trait`
fn main() {}
diff --git a/tests/ui/unboxed-closures/unboxed-closure-sugar-wrong-trait.stderr b/tests/ui/unboxed-closures/unboxed-closure-sugar-wrong-trait.stderr
index 3ff05fb23..130b193d6 100644
--- a/tests/ui/unboxed-closures/unboxed-closure-sugar-wrong-trait.stderr
+++ b/tests/ui/unboxed-closures/unboxed-closure-sugar-wrong-trait.stderr
@@ -1,4 +1,4 @@
-error[E0107]: this trait takes 0 generic arguments but 1 generic argument was supplied
+error[E0107]: trait takes 0 generic arguments but 1 generic argument was supplied
--> $DIR/unboxed-closure-sugar-wrong-trait.rs:5:8
|
LL | fn f<F:Trait(isize) -> isize>(x: F) {}
diff --git a/tests/ui/unboxed-closures/unboxed-closures-borrow-conflict.stderr b/tests/ui/unboxed-closures/unboxed-closures-borrow-conflict.stderr
index 21d6b4fde..98fe97c5c 100644
--- a/tests/ui/unboxed-closures/unboxed-closures-borrow-conflict.stderr
+++ b/tests/ui/unboxed-closures/unboxed-closures-borrow-conflict.stderr
@@ -4,7 +4,7 @@ error[E0503]: cannot use `x` because it was mutably borrowed
LL | let f = || x += 1;
| -- - borrow occurs due to use of `x` in closure
| |
- | borrow of `x` occurs here
+ | `x` is borrowed here
LL | let _y = x;
| ^ use of borrowed `x`
LL | f;
diff --git a/tests/ui/unboxed-closures/unboxed-closures-failed-recursive-fn-1.stderr b/tests/ui/unboxed-closures/unboxed-closures-failed-recursive-fn-1.stderr
index cbdb4dd0f..23aa18d71 100644
--- a/tests/ui/unboxed-closures/unboxed-closures-failed-recursive-fn-1.stderr
+++ b/tests/ui/unboxed-closures/unboxed-closures-failed-recursive-fn-1.stderr
@@ -16,14 +16,14 @@ error[E0506]: cannot assign to `factorial` because it is borrowed
--> $DIR/unboxed-closures-failed-recursive-fn-1.rs:20:5
|
LL | let f = |x: u32| -> u32 {
- | --------------- borrow of `factorial` occurs here
+ | --------------- `factorial` is borrowed here
LL | let g = factorial.as_ref().unwrap();
| --------- borrow occurs due to use in closure
...
LL | factorial = Some(Box::new(f));
| ^^^^^^^^^
| |
- | assignment to borrowed `factorial` occurs here
+ | `factorial` is assigned to here but it was already borrowed
| borrow later used here
error[E0597]: `factorial` does not live long enough
@@ -47,12 +47,12 @@ LL | let mut factorial: Option<Box<dyn Fn(u32) -> u32 + 'static>> = None;
| ----------------------------------------- type annotation requires that `factorial` is borrowed for `'static`
LL |
LL | let f = |x: u32| -> u32 {
- | --------------- borrow of `factorial` occurs here
+ | --------------- `factorial` is borrowed here
LL | let g = factorial.as_ref().unwrap();
| --------- borrow occurs due to use in closure
...
LL | factorial = Some(Box::new(f));
- | ^^^^^^^^^ assignment to borrowed `factorial` occurs here
+ | ^^^^^^^^^ `factorial` is assigned to here but it was already borrowed
error: aborting due to 4 previous errors
diff --git a/tests/ui/unboxed-closures/unboxed-closures-infer-fn-once-move-from-projection.stderr b/tests/ui/unboxed-closures/unboxed-closures-infer-fn-once-move-from-projection.stderr
index 635ebbb71..846a44ce4 100644
--- a/tests/ui/unboxed-closures/unboxed-closures-infer-fn-once-move-from-projection.stderr
+++ b/tests/ui/unboxed-closures/unboxed-closures-infer-fn-once-move-from-projection.stderr
@@ -14,7 +14,7 @@ note: required by a bound in `foo`
--> $DIR/unboxed-closures-infer-fn-once-move-from-projection.rs:4:14
|
LL | fn foo<F>(f: F)
- | --- required by a bound in this
+ | --- required by a bound in this function
LL | where F: Fn()
| ^^^^ required by this bound in `foo`
diff --git a/tests/ui/unboxed-closures/unboxed-closures-static-call-wrong-trait.stderr b/tests/ui/unboxed-closures/unboxed-closures-static-call-wrong-trait.stderr
index 99ec51783..482fd3cb4 100644
--- a/tests/ui/unboxed-closures/unboxed-closures-static-call-wrong-trait.stderr
+++ b/tests/ui/unboxed-closures/unboxed-closures-static-call-wrong-trait.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no method named `call` found for closure `[closure@unboxed-closures-static-call-wrong-trait.rs:6:26]` in the current scope
+error[E0599]: no method named `call` found for closure `[closure@$DIR/unboxed-closures-static-call-wrong-trait.rs:6:26: 6:29]` in the current scope
--> $DIR/unboxed-closures-static-call-wrong-trait.rs:7:10
|
LL | mut_.call((0, ));
diff --git a/tests/ui/uninhabited/issue-107505.rs b/tests/ui/uninhabited/issue-107505.rs
new file mode 100644
index 000000000..61598541d
--- /dev/null
+++ b/tests/ui/uninhabited/issue-107505.rs
@@ -0,0 +1,18 @@
+// compile-flags: --crate-type=lib
+// check-pass
+
+// Make sure we don't pass inference variables to uninhabitedness checks in borrowck
+
+struct Command<'s> {
+ session: &'s (),
+ imp: std::convert::Infallible,
+}
+
+fn command(_: &()) -> Command<'_> {
+ unreachable!()
+}
+
+fn with_session<'s>(a: &std::process::Command, b: &'s ()) -> Command<'s> {
+ a.get_program();
+ command(b)
+}
diff --git a/tests/ui/union/projection-as-union-type-error-2.rs b/tests/ui/union/projection-as-union-type-error-2.rs
new file mode 100644
index 000000000..b88167b3b
--- /dev/null
+++ b/tests/ui/union/projection-as-union-type-error-2.rs
@@ -0,0 +1,20 @@
+// Test to ensure that there is no ICE when normalizing a projection
+// which is invalid (from <https://github.com/rust-lang/rust/pull/106938>).
+
+#![crate_type = "lib"]
+
+trait Identity {
+ type Identity;
+}
+trait NotImplemented {}
+
+impl<T: NotImplemented> Identity for T {
+ type Identity = Self;
+}
+
+type Foo = u8;
+
+union Bar {
+ a: <Foo as Identity>::Identity, //~ ERROR
+ b: u8,
+}
diff --git a/tests/ui/union/projection-as-union-type-error-2.stderr b/tests/ui/union/projection-as-union-type-error-2.stderr
new file mode 100644
index 000000000..bab226f27
--- /dev/null
+++ b/tests/ui/union/projection-as-union-type-error-2.stderr
@@ -0,0 +1,17 @@
+error[E0277]: the trait bound `u8: NotImplemented` is not satisfied
+ --> $DIR/projection-as-union-type-error-2.rs:18:8
+ |
+LL | a: <Foo as Identity>::Identity,
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `NotImplemented` is not implemented for `u8`
+ |
+note: required for `u8` to implement `Identity`
+ --> $DIR/projection-as-union-type-error-2.rs:11:25
+ |
+LL | impl<T: NotImplemented> Identity for T {
+ | -------------- ^^^^^^^^ ^
+ | |
+ | unsatisfied trait bound introduced here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/union/projection-as-union-type-error.rs b/tests/ui/union/projection-as-union-type-error.rs
new file mode 100644
index 000000000..17091c35f
--- /dev/null
+++ b/tests/ui/union/projection-as-union-type-error.rs
@@ -0,0 +1,15 @@
+// Test to ensure that there is no ICE when normalizing a projection
+// which is invalid (from <https://github.com/rust-lang/rust/pull/106938>).
+
+#![crate_type = "lib"]
+
+pub trait Identity {
+ type Identity;
+}
+
+pub type Foo = u8;
+
+pub union Bar {
+ a: <Foo as Identity>::Identity, //~ ERROR
+ b: u8,
+}
diff --git a/tests/ui/union/projection-as-union-type-error.stderr b/tests/ui/union/projection-as-union-type-error.stderr
new file mode 100644
index 000000000..e4fbe9603
--- /dev/null
+++ b/tests/ui/union/projection-as-union-type-error.stderr
@@ -0,0 +1,9 @@
+error[E0277]: the trait bound `u8: Identity` is not satisfied
+ --> $DIR/projection-as-union-type-error.rs:13:9
+ |
+LL | a: <Foo as Identity>::Identity,
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Identity` is not implemented for `u8`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/union/projection-as-union-type.rs b/tests/ui/union/projection-as-union-type.rs
new file mode 100644
index 000000000..143434c96
--- /dev/null
+++ b/tests/ui/union/projection-as-union-type.rs
@@ -0,0 +1,19 @@
+// Ensures that we can use projections as union field's type.
+// check-pass
+
+#![crate_type = "lib"]
+
+pub trait Identity {
+ type Identity;
+}
+
+impl<T> Identity for T {
+ type Identity = Self;
+}
+
+pub type Foo = u8;
+
+pub union Bar {
+ pub a: <Foo as Identity>::Identity,
+ pub b: u8,
+}
diff --git a/tests/ui/unop-move-semantics.stderr b/tests/ui/unop-move-semantics.stderr
index 2a3ca1443..e47785c46 100644
--- a/tests/ui/unop-move-semantics.stderr
+++ b/tests/ui/unop-move-semantics.stderr
@@ -23,6 +23,8 @@ LL | fn move_then_borrow<T: Not<Output=T> + Clone + Copy>(x: T) {
error[E0505]: cannot move out of `x` because it is borrowed
--> $DIR/unop-move-semantics.rs:15:6
|
+LL | fn move_borrowed<T: Not<Output=T>>(x: T, mut y: T) {
+ | - binding `x` declared here
LL | let m = &x;
| -- borrow of `x` occurs here
...
@@ -35,6 +37,9 @@ LL | use_mut(n); use_imm(m);
error[E0505]: cannot move out of `y` because it is borrowed
--> $DIR/unop-move-semantics.rs:17:6
|
+LL | fn move_borrowed<T: Not<Output=T>>(x: T, mut y: T) {
+ | ----- binding `y` declared here
+LL | let m = &x;
LL | let n = &mut y;
| ------ borrow of `y` occurs here
...
diff --git a/tests/ui/unpretty/ast-const-trait-bound.rs b/tests/ui/unpretty/ast-const-trait-bound.rs
new file mode 100644
index 000000000..dbcba7871
--- /dev/null
+++ b/tests/ui/unpretty/ast-const-trait-bound.rs
@@ -0,0 +1,4 @@
+// compile-flags: -Zunpretty=normal
+// check-pass
+
+fn foo() where T: ~const Bar {}
diff --git a/tests/ui/unpretty/ast-const-trait-bound.stdout b/tests/ui/unpretty/ast-const-trait-bound.stdout
new file mode 100644
index 000000000..dbcba7871
--- /dev/null
+++ b/tests/ui/unpretty/ast-const-trait-bound.stdout
@@ -0,0 +1,4 @@
+// compile-flags: -Zunpretty=normal
+// check-pass
+
+fn foo() where T: ~const Bar {}
diff --git a/tests/ui/unsized-locals/suggest-borrow.stderr b/tests/ui/unsized-locals/suggest-borrow.stderr
index 08745eab2..d456c16de 100644
--- a/tests/ui/unsized-locals/suggest-borrow.stderr
+++ b/tests/ui/unsized-locals/suggest-borrow.stderr
@@ -18,7 +18,7 @@ error[E0308]: mismatched types
LL | let x: &[u8] = vec!(1, 2, 3)[..];
| ----- ^^^^^^^^^^^^^^^^^
| | |
- | | expected `&[u8]`, found slice `[{integer}]`
+ | | expected `&[u8]`, found `[{integer}]`
| | help: consider borrowing here: `&vec!(1, 2, 3)[..]`
| expected due to this
@@ -26,7 +26,7 @@ error[E0308]: mismatched types
--> $DIR/suggest-borrow.rs:4:19
|
LL | let x: [u8] = &vec!(1, 2, 3)[..];
- | ---- ^^^^^^^^^^^^^^^^^^ expected slice `[u8]`, found `&[{integer}]`
+ | ---- ^^^^^^^^^^^^^^^^^^ expected `[u8]`, found `&[{integer}]`
| |
| expected due to this
|
diff --git a/tests/ui/unsized/box-instead-of-dyn-fn.stderr b/tests/ui/unsized/box-instead-of-dyn-fn.stderr
index c96c59afc..bfb7c3957 100644
--- a/tests/ui/unsized/box-instead-of-dyn-fn.stderr
+++ b/tests/ui/unsized/box-instead-of-dyn-fn.stderr
@@ -9,7 +9,7 @@ LL | | move || println!("{a}")
| | expected because of this
LL | | } else {
LL | | Box::new(move || println!("{}", b))
- | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected closure, found struct `Box`
+ | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected closure, found `Box<[closure@box-instead-of-dyn-fn.rs:10:18]>`
LL | |
LL | | }
| |_____- `if` and `else` have incompatible types
diff --git a/tests/ui/unsized/issue-71659.stderr b/tests/ui/unsized/issue-71659.stderr
index d7b95f557..b57b3015e 100644
--- a/tests/ui/unsized/issue-71659.stderr
+++ b/tests/ui/unsized/issue-71659.stderr
@@ -8,7 +8,7 @@ note: required by a bound in `Cast::cast`
--> $DIR/issue-71659.rs:19:15
|
LL | fn cast<T: ?Sized>(&self) -> &T
- | ---- required by a bound in this
+ | ---- required by a bound in this associated function
LL | where
LL | Self: CastTo<T>,
| ^^^^^^^^^ required by this bound in `Cast::cast`
diff --git a/tests/ui/unsized/param-mentioned-by-different-field.stderr b/tests/ui/unsized/param-mentioned-by-different-field.stderr
index d18fa6456..b1ad0cb5b 100644
--- a/tests/ui/unsized/param-mentioned-by-different-field.stderr
+++ b/tests/ui/unsized/param-mentioned-by-different-field.stderr
@@ -2,7 +2,7 @@ error[E0308]: mismatched types
--> $DIR/param-mentioned-by-different-field.rs:8:25
|
LL | let y: &Foo<[u8]> = &x;
- | ---------- ^^ expected slice `[u8]`, found array `[u8; 1]`
+ | ---------- ^^ expected `&Foo<[u8]>`, found `&Foo<[u8; 1]>`
| |
| expected due to this
|
diff --git a/tests/ui/unsized/unsized3-rpass.rs b/tests/ui/unsized/unsized3-rpass.rs
index 4d5e89575..a3f92be6c 100644
--- a/tests/ui/unsized/unsized3-rpass.rs
+++ b/tests/ui/unsized/unsized3-rpass.rs
@@ -59,7 +59,7 @@ pub fn main() {
}
let data: Box<Foo_<i32>> = Box::new(Foo_ { f: [1, 2, 3] });
- let x: &Foo<i32> = mem::transmute(slice::from_raw_parts(&*data, 3));
+ let x: &Foo<i32> = mem::transmute(ptr::slice_from_raw_parts(&*data, 3));
assert_eq!(x.f.len(), 3);
assert_eq!(x.f[0], 1);
@@ -70,7 +70,7 @@ pub fn main() {
let data: Box<_> =
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));
+ let x: &Baz = mem::transmute(ptr::slice_from_raw_parts(&*data, 5));
assert_eq!(x.f1, 42);
let chs: Vec<char> = x.f2.chars().collect();
assert_eq!(chs.len(), 5);
diff --git a/tests/ui/variance/variance-associated-types.rs b/tests/ui/variance/variance-associated-types.rs
index 1165fb53c..ecb082182 100644
--- a/tests/ui/variance/variance-associated-types.rs
+++ b/tests/ui/variance/variance-associated-types.rs
@@ -10,7 +10,7 @@ trait Trait<'a> {
}
#[rustc_variance]
-struct Foo<'a, T : Trait<'a>> { //~ ERROR [-, +]
+struct Foo<'a, T : Trait<'a>> { //~ ERROR [+, +]
field: (T, &'a ())
}
diff --git a/tests/ui/variance/variance-associated-types.stderr b/tests/ui/variance/variance-associated-types.stderr
index 51f17c7c2..70cb246f6 100644
--- a/tests/ui/variance/variance-associated-types.stderr
+++ b/tests/ui/variance/variance-associated-types.stderr
@@ -1,4 +1,4 @@
-error: [-, +]
+error: [+, +]
--> $DIR/variance-associated-types.rs:13:1
|
LL | struct Foo<'a, T : Trait<'a>> {
diff --git a/tests/ui/variance/variance-issue-20533.stderr b/tests/ui/variance/variance-issue-20533.stderr
index 008e2a002..258f67db5 100644
--- a/tests/ui/variance/variance-issue-20533.stderr
+++ b/tests/ui/variance/variance-issue-20533.stderr
@@ -1,6 +1,8 @@
error[E0505]: cannot move out of `a` because it is borrowed
--> $DIR/variance-issue-20533.rs:28:14
|
+LL | let a = AffineU32(1);
+ | - binding `a` declared here
LL | let x = foo(&a);
| -- borrow of `a` occurs here
LL | drop(a);
@@ -11,6 +13,8 @@ LL | drop(x);
error[E0505]: cannot move out of `a` because it is borrowed
--> $DIR/variance-issue-20533.rs:34:14
|
+LL | let a = AffineU32(1);
+ | - binding `a` declared here
LL | let x = bar(&a);
| -- borrow of `a` occurs here
LL | drop(a);
@@ -21,6 +25,8 @@ LL | drop(x);
error[E0505]: cannot move out of `a` because it is borrowed
--> $DIR/variance-issue-20533.rs:40:14
|
+LL | let a = AffineU32(1);
+ | - binding `a` declared here
LL | let x = baz(&a);
| -- borrow of `a` occurs here
LL | drop(a);
diff --git a/tests/ui/variance/variance-regions-direct.rs b/tests/ui/variance/variance-regions-direct.rs
index 3f34e7655..39ea77a8a 100644
--- a/tests/ui/variance/variance-regions-direct.rs
+++ b/tests/ui/variance/variance-regions-direct.rs
@@ -6,7 +6,7 @@
// Regions that just appear in normal spots are contravariant:
#[rustc_variance]
-struct Test2<'a, 'b, 'c> { //~ ERROR [-, -, -]
+struct Test2<'a, 'b, 'c> { //~ ERROR [+, +, +]
x: &'a isize,
y: &'b [isize],
c: &'c str
@@ -15,7 +15,7 @@ struct Test2<'a, 'b, 'c> { //~ ERROR [-, -, -]
// Those same annotations in function arguments become covariant:
#[rustc_variance]
-struct Test3<'a, 'b, 'c> { //~ ERROR [+, +, +]
+struct Test3<'a, 'b, 'c> { //~ ERROR [-, -, -]
x: extern "Rust" fn(&'a isize),
y: extern "Rust" fn(&'b [isize]),
c: extern "Rust" fn(&'c str),
@@ -24,7 +24,7 @@ struct Test3<'a, 'b, 'c> { //~ ERROR [+, +, +]
// Mutability induces invariance:
#[rustc_variance]
-struct Test4<'a, 'b:'a> { //~ ERROR [-, o]
+struct Test4<'a, 'b:'a> { //~ ERROR [+, o]
x: &'a mut &'b isize,
}
@@ -32,7 +32,7 @@ struct Test4<'a, 'b:'a> { //~ ERROR [-, o]
// contravariant context:
#[rustc_variance]
-struct Test5<'a, 'b:'a> { //~ ERROR [+, o]
+struct Test5<'a, 'b:'a> { //~ ERROR [-, o]
x: extern "Rust" fn(&'a mut &'b isize),
}
@@ -42,7 +42,7 @@ struct Test5<'a, 'b:'a> { //~ ERROR [+, o]
// argument list occurs in an invariant context.
#[rustc_variance]
-struct Test6<'a, 'b:'a> { //~ ERROR [-, o]
+struct Test6<'a, 'b:'a> { //~ ERROR [+, o]
x: &'a mut extern "Rust" fn(&'b isize),
}
@@ -56,7 +56,7 @@ struct Test7<'a> { //~ ERROR [*]
// Try enums too.
#[rustc_variance]
-enum Test8<'a, 'b, 'c:'b> { //~ ERROR [+, -, o]
+enum Test8<'a, 'b, 'c:'b> { //~ ERROR [-, +, o]
Test8A(extern "Rust" fn(&'a isize)),
Test8B(&'b [isize]),
Test8C(&'b mut &'c str),
diff --git a/tests/ui/variance/variance-regions-direct.stderr b/tests/ui/variance/variance-regions-direct.stderr
index eda02e9b0..c55730296 100644
--- a/tests/ui/variance/variance-regions-direct.stderr
+++ b/tests/ui/variance/variance-regions-direct.stderr
@@ -1,28 +1,28 @@
-error: [-, -, -]
+error: [+, +, +]
--> $DIR/variance-regions-direct.rs:9:1
|
LL | struct Test2<'a, 'b, 'c> {
| ^^^^^^^^^^^^^^^^^^^^^^^^
-error: [+, +, +]
+error: [-, -, -]
--> $DIR/variance-regions-direct.rs:18:1
|
LL | struct Test3<'a, 'b, 'c> {
| ^^^^^^^^^^^^^^^^^^^^^^^^
-error: [-, o]
+error: [+, o]
--> $DIR/variance-regions-direct.rs:27:1
|
LL | struct Test4<'a, 'b:'a> {
| ^^^^^^^^^^^^^^^^^^^^^^^
-error: [+, o]
+error: [-, o]
--> $DIR/variance-regions-direct.rs:35:1
|
LL | struct Test5<'a, 'b:'a> {
| ^^^^^^^^^^^^^^^^^^^^^^^
-error: [-, o]
+error: [+, o]
--> $DIR/variance-regions-direct.rs:45:1
|
LL | struct Test6<'a, 'b:'a> {
@@ -34,7 +34,7 @@ error: [*]
LL | struct Test7<'a> {
| ^^^^^^^^^^^^^^^^
-error: [+, -, o]
+error: [-, +, o]
--> $DIR/variance-regions-direct.rs:59:1
|
LL | enum Test8<'a, 'b, 'c:'b> {
diff --git a/tests/ui/variance/variance-regions-indirect.rs b/tests/ui/variance/variance-regions-indirect.rs
index f84f25ada..0d00535fe 100644
--- a/tests/ui/variance/variance-regions-indirect.rs
+++ b/tests/ui/variance/variance-regions-indirect.rs
@@ -5,14 +5,14 @@
#![feature(rustc_attrs)]
#[rustc_variance]
-enum Base<'a, 'b, 'c:'b, 'd> { //~ ERROR [+, -, o, *]
+enum Base<'a, 'b, 'c:'b, 'd> { //~ ERROR [-, +, o, *]
Test8A(extern "Rust" fn(&'a isize)),
Test8B(&'b [isize]),
Test8C(&'b mut &'c str),
}
#[rustc_variance]
-struct Derived1<'w, 'x:'y, 'y, 'z> { //~ ERROR [*, o, -, +]
+struct Derived1<'w, 'x:'y, 'y, 'z> { //~ ERROR [*, o, +, -]
f: Base<'z, 'y, 'x, 'w>
}
@@ -22,12 +22,12 @@ struct Derived2<'a, 'b:'a, 'c> { //~ ERROR [o, o, *]
}
#[rustc_variance] // Combine + and o to yield o (just pay attention to 'a here)
-struct Derived3<'a:'b, 'b, 'c> { //~ ERROR [o, -, *]
+struct Derived3<'a:'b, 'b, 'c> { //~ ERROR [o, +, *]
f: Base<'a, 'b, 'a, 'c>
}
#[rustc_variance] // Combine + and * to yield + (just pay attention to 'a here)
-struct Derived4<'a, 'b, 'c:'b> { //~ ERROR [+, -, o]
+struct Derived4<'a, 'b, 'c:'b> { //~ ERROR [-, +, o]
f: Base<'a, 'b, 'c, 'a>
}
diff --git a/tests/ui/variance/variance-regions-indirect.stderr b/tests/ui/variance/variance-regions-indirect.stderr
index fa2f4d507..edf2626d5 100644
--- a/tests/ui/variance/variance-regions-indirect.stderr
+++ b/tests/ui/variance/variance-regions-indirect.stderr
@@ -1,10 +1,10 @@
-error: [+, -, o, *]
+error: [-, +, o, *]
--> $DIR/variance-regions-indirect.rs:8:1
|
LL | enum Base<'a, 'b, 'c:'b, 'd> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-error: [*, o, -, +]
+error: [*, o, +, -]
--> $DIR/variance-regions-indirect.rs:15:1
|
LL | struct Derived1<'w, 'x:'y, 'y, 'z> {
@@ -16,13 +16,13 @@ error: [o, o, *]
LL | struct Derived2<'a, 'b:'a, 'c> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-error: [o, -, *]
+error: [o, +, *]
--> $DIR/variance-regions-indirect.rs:25:1
|
LL | struct Derived3<'a:'b, 'b, 'c> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-error: [+, -, o]
+error: [-, +, o]
--> $DIR/variance-regions-indirect.rs:30:1
|
LL | struct Derived4<'a, 'b, 'c:'b> {
diff --git a/tests/ui/variance/variance-trait-object-bound.rs b/tests/ui/variance/variance-trait-object-bound.rs
index ec3c973bc..11303c465 100644
--- a/tests/ui/variance/variance-trait-object-bound.rs
+++ b/tests/ui/variance/variance-trait-object-bound.rs
@@ -11,7 +11,7 @@ use std::mem;
trait T { fn foo(&self); }
#[rustc_variance]
-struct TOption<'a> { //~ ERROR [-]
+struct TOption<'a> { //~ ERROR [+]
v: Option<Box<dyn T + 'a>>,
}
diff --git a/tests/ui/variance/variance-trait-object-bound.stderr b/tests/ui/variance/variance-trait-object-bound.stderr
index 7c46b553f..bfcc8d4a1 100644
--- a/tests/ui/variance/variance-trait-object-bound.stderr
+++ b/tests/ui/variance/variance-trait-object-bound.stderr
@@ -1,4 +1,4 @@
-error: [-]
+error: [+]
--> $DIR/variance-trait-object-bound.rs:14:1
|
LL | struct TOption<'a> {
diff --git a/tests/ui/variance/variance-types.rs b/tests/ui/variance/variance-types.rs
index b9b6d9c9b..cfc03b754 100644
--- a/tests/ui/variance/variance-types.rs
+++ b/tests/ui/variance/variance-types.rs
@@ -7,7 +7,7 @@ use std::cell::Cell;
// not considered bivariant.
#[rustc_variance]
-struct InvariantMut<'a,A:'a,B:'a> { //~ ERROR [-, o, o]
+struct InvariantMut<'a,A:'a,B:'a> { //~ ERROR [+, o, o]
t: &'a mut (A,B)
}
diff --git a/tests/ui/variance/variance-types.stderr b/tests/ui/variance/variance-types.stderr
index 9f7f1d9b0..0fda4b803 100644
--- a/tests/ui/variance/variance-types.stderr
+++ b/tests/ui/variance/variance-types.stderr
@@ -1,4 +1,4 @@
-error: [-, o, o]
+error: [+, o, o]
--> $DIR/variance-types.rs:10:1
|
LL | struct InvariantMut<'a,A:'a,B:'a> {
diff --git a/tests/ui/wait-forked-but-failed-child.rs b/tests/ui/wait-forked-but-failed-child.rs
index 674c26a43..82a1dd637 100644
--- a/tests/ui/wait-forked-but-failed-child.rs
+++ b/tests/ui/wait-forked-but-failed-child.rs
@@ -3,6 +3,7 @@
// ignore-sgx no processes
// ignore-vxworks no 'ps'
// ignore-fuchsia no 'ps'
+// ignore-nto no 'ps'
#![feature(rustc_private)]
diff --git a/tests/ui/wf/wf-in-foreign-fn-decls-issue-80468.rs b/tests/ui/wf/wf-in-foreign-fn-decls-issue-80468.rs
index 4fcf8f403..0be5127dc 100644
--- a/tests/ui/wf/wf-in-foreign-fn-decls-issue-80468.rs
+++ b/tests/ui/wf/wf-in-foreign-fn-decls-issue-80468.rs
@@ -13,5 +13,5 @@ pub struct Ref<'a>(&'a u8);
impl Trait for Ref {} //~ ERROR: implicit elided lifetime not allowed here
extern "C" {
- pub fn repro(_: Wrapper<Ref>); //~ ERROR: incompatible lifetime on type
+ pub fn repro(_: Wrapper<Ref>);
}
diff --git a/tests/ui/wf/wf-in-foreign-fn-decls-issue-80468.stderr b/tests/ui/wf/wf-in-foreign-fn-decls-issue-80468.stderr
index 94f6dc266..b10856571 100644
--- a/tests/ui/wf/wf-in-foreign-fn-decls-issue-80468.stderr
+++ b/tests/ui/wf/wf-in-foreign-fn-decls-issue-80468.stderr
@@ -4,34 +4,11 @@ error[E0726]: implicit elided lifetime not allowed here
LL | impl Trait for Ref {}
| ^^^ expected lifetime parameter
|
- = note: assuming a `'static` lifetime...
help: indicate the anonymous lifetime
|
LL | impl Trait for Ref<'_> {}
| ++++
-error: incompatible lifetime on type
- --> $DIR/wf-in-foreign-fn-decls-issue-80468.rs:16:21
- |
-LL | pub fn repro(_: Wrapper<Ref>);
- | ^^^^^^^^^^^^
- |
-note: because this has an unmet lifetime requirement
- --> $DIR/wf-in-foreign-fn-decls-issue-80468.rs:8:23
- |
-LL | pub struct Wrapper<T: Trait>(T);
- | ^^^^^ introduces a `'static` lifetime requirement
-note: the anonymous lifetime as defined here...
- --> $DIR/wf-in-foreign-fn-decls-issue-80468.rs:16:29
- |
-LL | pub fn repro(_: Wrapper<Ref>);
- | ^^^
-note: ...does not necessarily outlive the static lifetime introduced by the compatible `impl`
- --> $DIR/wf-in-foreign-fn-decls-issue-80468.rs:13:1
- |
-LL | impl Trait for Ref {}
- | ^^^^^^^^^^^^^^^^^^
-
-error: aborting due to 2 previous errors
+error: aborting due to previous error
For more information about this error, try `rustc --explain E0726`.
diff --git a/tests/ui/wf/wf-unsafe-trait-obj-match.stderr b/tests/ui/wf/wf-unsafe-trait-obj-match.stderr
index 96fc1d36b..d2b416309 100644
--- a/tests/ui/wf/wf-unsafe-trait-obj-match.stderr
+++ b/tests/ui/wf/wf-unsafe-trait-obj-match.stderr
@@ -5,7 +5,7 @@ LL | / match opt() {
LL | | Some(()) => &S,
| | -- this is found to be of type `&S`
LL | | None => &R,
- | | ^^ expected struct `S`, found struct `R`
+ | | ^^ expected `&S`, found `&R`
LL | | }
| |_____- `match` arms have incompatible types
|
diff --git a/tests/ui/where-clauses/higher-ranked-fn-type.quiet.stderr b/tests/ui/where-clauses/higher-ranked-fn-type.quiet.stderr
index 30248a7a3..191a8ca8e 100644
--- a/tests/ui/where-clauses/higher-ranked-fn-type.quiet.stderr
+++ b/tests/ui/where-clauses/higher-ranked-fn-type.quiet.stderr
@@ -8,7 +8,7 @@ note: required by a bound in `called`
--> $DIR/higher-ranked-fn-type.rs:12:25
|
LL | fn called()
- | ------ required by a bound in this
+ | ------ required by a bound in this function
LL | where
LL | for<'b> fn(&'b ()): Foo,
| ^^^ required by this bound in `called`
diff --git a/tests/ui/where-clauses/higher-ranked-fn-type.verbose.stderr b/tests/ui/where-clauses/higher-ranked-fn-type.verbose.stderr
index 268cef6e2..f4c7acd5c 100644
--- a/tests/ui/where-clauses/higher-ranked-fn-type.verbose.stderr
+++ b/tests/ui/where-clauses/higher-ranked-fn-type.verbose.stderr
@@ -8,7 +8,7 @@ note: required by a bound in `called`
--> $DIR/higher-ranked-fn-type.rs:12:25
|
LL | fn called()
- | ------ required by a bound in this
+ | ------ required by a bound in this function
LL | where
LL | for<'b> fn(&'b ()): Foo,
| ^^^ required by this bound in `called`
diff --git a/tests/ui/where-clauses/self-in-where-clause-allowed.rs b/tests/ui/where-clauses/self-in-where-clause-allowed.rs
new file mode 100644
index 000000000..6cf5ed2e4
--- /dev/null
+++ b/tests/ui/where-clauses/self-in-where-clause-allowed.rs
@@ -0,0 +1,23 @@
+// check-fail
+
+#![feature(auto_traits)]
+#![deny(where_clauses_object_safety)]
+
+auto trait AutoTrait {}
+
+trait Trait {
+ fn static_lifetime_bound(&self) where Self: 'static {}
+
+ fn arg_lifetime_bound<'a>(&self, _arg: &'a ()) where Self: 'a {}
+
+ fn autotrait_bound(&self) where Self: AutoTrait {}
+}
+
+impl Trait for () {}
+
+fn main() {
+ let trait_object = &() as &dyn Trait;
+ trait_object.static_lifetime_bound();
+ trait_object.arg_lifetime_bound(&());
+ trait_object.autotrait_bound(); //~ ERROR: the trait bound `dyn Trait: AutoTrait` is not satisfied
+}
diff --git a/tests/ui/where-clauses/self-in-where-clause-allowed.stderr b/tests/ui/where-clauses/self-in-where-clause-allowed.stderr
new file mode 100644
index 000000000..ea51f5084
--- /dev/null
+++ b/tests/ui/where-clauses/self-in-where-clause-allowed.stderr
@@ -0,0 +1,15 @@
+error[E0277]: the trait bound `dyn Trait: AutoTrait` is not satisfied
+ --> $DIR/self-in-where-clause-allowed.rs:22:18
+ |
+LL | trait_object.autotrait_bound();
+ | ^^^^^^^^^^^^^^^ the trait `AutoTrait` is not implemented for `dyn Trait`
+ |
+note: required by a bound in `Trait::autotrait_bound`
+ --> $DIR/self-in-where-clause-allowed.rs:13:43
+ |
+LL | fn autotrait_bound(&self) where Self: AutoTrait {}
+ | ^^^^^^^^^ required by this bound in `Trait::autotrait_bound`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/while/while-else-err.rs b/tests/ui/while/while-else-err.rs
new file mode 100644
index 000000000..36b60fbd4
--- /dev/null
+++ b/tests/ui/while/while-else-err.rs
@@ -0,0 +1,8 @@
+fn main() {
+ while false {
+ //~^ NOTE `else` is attached to this loop
+ } else {
+ //~^ ERROR `while...else` loops are not supported
+ //~| NOTE consider moving this `else` clause to a separate `if` statement and use a `bool` variable to control if it should run
+ };
+}
diff --git a/tests/ui/while/while-else-err.stderr b/tests/ui/while/while-else-err.stderr
new file mode 100644
index 000000000..88f715d56
--- /dev/null
+++ b/tests/ui/while/while-else-err.stderr
@@ -0,0 +1,17 @@
+error: `while...else` loops are not supported
+ --> $DIR/while-else-err.rs:4:7
+ |
+LL | while false {
+ | ----- `else` is attached to this loop
+LL |
+LL | } else {
+ | _______^
+LL | |
+LL | |
+LL | | };
+ | |_____^
+ |
+ = note: consider moving this `else` clause to a separate `if` statement and use a `bool` variable to control if it should run
+
+error: aborting due to previous error
+
diff --git a/tests/ui/while/while-else-let-else-err.rs b/tests/ui/while/while-else-let-else-err.rs
new file mode 100644
index 000000000..6d9909347
--- /dev/null
+++ b/tests/ui/while/while-else-let-else-err.rs
@@ -0,0 +1,8 @@
+fn main() {
+ let _ = while false {
+ //~^ NOTE `else` is attached to this loop
+ } else {
+ //~^ ERROR `while...else` loops are not supported
+ //~| NOTE consider moving this `else` clause to a separate `if` statement and use a `bool` variable to control if it should run
+ };
+}
diff --git a/tests/ui/while/while-else-let-else-err.stderr b/tests/ui/while/while-else-let-else-err.stderr
new file mode 100644
index 000000000..431d37c00
--- /dev/null
+++ b/tests/ui/while/while-else-let-else-err.stderr
@@ -0,0 +1,17 @@
+error: `while...else` loops are not supported
+ --> $DIR/while-else-let-else-err.rs:4:7
+ |
+LL | let _ = while false {
+ | ----- `else` is attached to this loop
+LL |
+LL | } else {
+ | _______^
+LL | |
+LL | |
+LL | | };
+ | |_____^
+ |
+ = note: consider moving this `else` clause to a separate `if` statement and use a `bool` variable to control if it should run
+
+error: aborting due to previous error
+
diff --git a/tests/ui/wrong-mul-method-signature.stderr b/tests/ui/wrong-mul-method-signature.stderr
index 504a6032b..25a92f5ec 100644
--- a/tests/ui/wrong-mul-method-signature.stderr
+++ b/tests/ui/wrong-mul-method-signature.stderr
@@ -16,7 +16,7 @@ error[E0053]: method `mul` has an incompatible type for trait
LL | fn mul(self, s: f64) -> Vec2 {
| ^^^
| |
- | expected struct `Vec2`, found `f64`
+ | expected `Vec2`, found `f64`
| help: change the parameter type to match the trait: `Vec2`
|
= note: expected signature `fn(Vec2, Vec2) -> f64`
@@ -38,7 +38,7 @@ error[E0308]: mismatched types
--> $DIR/wrong-mul-method-signature.rs:63:45
|
LL | let x: Vec2 = Vec2 { x: 1.0, y: 2.0 } * 2.0; // trait had reversed order
- | ----------------------- ^^^ expected struct `Vec2`, found floating-point number
+ | ----------------------- ^^^ expected `Vec2`, found floating-point number
| |
| expected because this is `Vec2`
@@ -46,7 +46,7 @@ error[E0308]: mismatched types
--> $DIR/wrong-mul-method-signature.rs:63:19
|
LL | let x: Vec2 = Vec2 { x: 1.0, y: 2.0 } * 2.0; // trait had reversed order
- | ---- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected struct `Vec2`, found `f64`
+ | ---- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `Vec2`, found `f64`
| |
| expected due to this
diff --git a/tests/ui/xc-private-method2.rs b/tests/ui/xc-private-method2.rs
index 92946923f..f11b25108 100644
--- a/tests/ui/xc-private-method2.rs
+++ b/tests/ui/xc-private-method2.rs
@@ -4,8 +4,8 @@ extern crate xc_private_method_lib;
fn main() {
let _ = xc_private_method_lib::Struct{ x: 10 }.meth_struct();
- //~^ ERROR associated function `meth_struct` is private
+ //~^ ERROR method `meth_struct` is private
let _ = xc_private_method_lib::Enum::Variant1(20).meth_enum();
- //~^ ERROR associated function `meth_enum` is private
+ //~^ ERROR method `meth_enum` is private
}
diff --git a/tests/ui/xc-private-method2.stderr b/tests/ui/xc-private-method2.stderr
index b569882f8..af0c3cfcb 100644
--- a/tests/ui/xc-private-method2.stderr
+++ b/tests/ui/xc-private-method2.stderr
@@ -1,24 +1,24 @@
-error[E0624]: associated function `meth_struct` is private
+error[E0624]: method `meth_struct` is private
--> $DIR/xc-private-method2.rs:6:52
|
LL | let _ = xc_private_method_lib::Struct{ x: 10 }.meth_struct();
- | ^^^^^^^^^^^ private associated function
+ | ^^^^^^^^^^^ private method
|
::: $DIR/auxiliary/xc-private-method-lib.rs:12:5
|
LL | fn meth_struct(&self) -> isize {
- | ------------------------------ private associated function defined here
+ | ------------------------------ private method defined here
-error[E0624]: associated function `meth_enum` is private
+error[E0624]: method `meth_enum` is private
--> $DIR/xc-private-method2.rs:9:55
|
LL | let _ = xc_private_method_lib::Enum::Variant1(20).meth_enum();
- | ^^^^^^^^^ private associated function
+ | ^^^^^^^^^ private method
|
::: $DIR/auxiliary/xc-private-method-lib.rs:27:5
|
LL | fn meth_enum(&self) -> isize {
- | ---------------------------- private associated function defined here
+ | ---------------------------- private method defined here
error: aborting due to 2 previous errors
diff --git a/vendor/addr2line-0.17.0/.cargo-checksum.json b/vendor/addr2line-0.17.0/.cargo-checksum.json
new file mode 100644
index 000000000..b43ad3bbf
--- /dev/null
+++ b/vendor/addr2line-0.17.0/.cargo-checksum.json
@@ -0,0 +1 @@
+{"files":{"CHANGELOG.md":"d4ef249a0a4eff26a34a1f847a3c367dfd9988b4da972ac9c16b1d258b62ad87","Cargo.lock":"290a48d58d1ebfef0f5eaec66191f6c1a41080b89e10e931c6984052008479ab","Cargo.toml":"68243a813e2e6ba40d3e939b9ade5489b3f39a58d7dc391ae447a60591315f4a","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"e99d88d232bf57d70f0fb87f6b496d44b6653f99f8a63d250a54c61ea4bcde40","README.md":"76d28502bd2e83f6a9e3576bd45e9a7fe5308448c4b5384b0d249515b5f67a5c","bench.plot.r":"6a5d7a4d36ed6b3d9919be703a479bef47698bf947818b483ff03951df2d4e01","benchmark.sh":"b35f89b1ca2c1dc0476cdd07f0284b72d41920d1c7b6054072f50ffba296d78d","coverage.sh":"4677e81922d08a82e83068a911717a247c66af12e559f37b78b6be3337ac9f07","examples/addr2line.rs":"75ef29e1d07d49d247990ad970892d64f629766bafa36afddff5a88976e58060","rustfmt.toml":"01ba4719c80b6fe911b091a7c05124b64eeece964e09c058ef8f9805daca546b","src/function.rs":"395f37cdf03201d416d66bc11abeea627be0abb4585104acd927224a26cb9369","src/lazy.rs":"14ec61761369c21d426673f549c21394221533f444b68cd2a8370952eb19f345","src/lib.rs":"5696c0aee67df576f78935c66bb124f4e5fa19cbc9b25faf8f750e7e8dda113c","tests/correctness.rs":"c9325ffdec577bf5e56f5dd72fdff4927153d0a4c34c0fda5aefaeb44a8d26fd","tests/output_equivalence.rs":"38d7b585b7a2ca43b07eef6b34c11f489d1deae138a010123c33188dfb881c11","tests/parse.rs":"9e421ea9d9348721f6c6533cdba1db5b84287fc685f870c7905dea06b596b4db"},"package":"b9ecd88a8c8378ca913a680cd98f0f13ac67383d35993f86c90a70e3f137816b"} \ No newline at end of file
diff --git a/vendor/addr2line-0.17.0/CHANGELOG.md b/vendor/addr2line-0.17.0/CHANGELOG.md
new file mode 100644
index 000000000..914139400
--- /dev/null
+++ b/vendor/addr2line-0.17.0/CHANGELOG.md
@@ -0,0 +1,260 @@
+## 0.17.0 (2021/10/24)
+
+### Breaking changes
+
+* Updated `gimli` and `object` dependencies.
+
+### Changed
+
+* Use `skip_attributes` to improve performance.
+ [#236](https://github.com/gimli-rs/addr2line/pull/236)
+
+--------------------------------------------------------------------------------
+
+## 0.16.0 (2021/07/26)
+
+### Breaking changes
+
+* Updated `gimli` and `object` dependencies.
+
+--------------------------------------------------------------------------------
+
+## 0.15.2 (2021/06/04)
+
+### Fixed
+
+* Allow `Context` to be `Send`.
+ [#219](https://github.com/gimli-rs/addr2line/pull/219)
+
+--------------------------------------------------------------------------------
+
+## 0.15.1 (2021/05/02)
+
+### Fixed
+
+* Don't ignore aranges with address 0.
+ [#217](https://github.com/gimli-rs/addr2line/pull/217)
+
+--------------------------------------------------------------------------------
+
+## 0.15.0 (2021/05/02)
+
+### Breaking changes
+
+* Updated `gimli` and `object` dependencies.
+ [#215](https://github.com/gimli-rs/addr2line/pull/215)
+
+* Added `debug_aranges` parameter to `Context::from_sections`.
+ [#200](https://github.com/gimli-rs/addr2line/pull/200)
+
+### Added
+
+* Added `.debug_aranges` support.
+ [#200](https://github.com/gimli-rs/addr2line/pull/200)
+
+* Added supplementary object file support.
+ [#208](https://github.com/gimli-rs/addr2line/pull/208)
+
+### Fixed
+
+* Fixed handling of Windows paths in locations.
+ [#209](https://github.com/gimli-rs/addr2line/pull/209)
+
+* examples/addr2line: Flush stdout after each response.
+ [#210](https://github.com/gimli-rs/addr2line/pull/210)
+
+* examples/addr2line: Avoid copying every section.
+ [#213](https://github.com/gimli-rs/addr2line/pull/213)
+
+--------------------------------------------------------------------------------
+
+## 0.14.1 (2020/12/31)
+
+### Fixed
+
+* Fix location lookup for skeleton units.
+ [#201](https://github.com/gimli-rs/addr2line/pull/201)
+
+### Added
+
+* Added `Context::find_location_range`.
+ [#196](https://github.com/gimli-rs/addr2line/pull/196)
+ [#199](https://github.com/gimli-rs/addr2line/pull/199)
+
+--------------------------------------------------------------------------------
+
+## 0.14.0 (2020/10/27)
+
+### Breaking changes
+
+* Updated `gimli` and `object` dependencies.
+
+### Fixed
+
+* Handle units that only have line information.
+ [#188](https://github.com/gimli-rs/addr2line/pull/188)
+
+* Handle DWARF units with version <= 4 and no `DW_AT_name`.
+ [#191](https://github.com/gimli-rs/addr2line/pull/191)
+
+* Fix handling of `DW_FORM_ref_addr`.
+ [#193](https://github.com/gimli-rs/addr2line/pull/193)
+
+--------------------------------------------------------------------------------
+
+## 0.13.0 (2020/07/07)
+
+### Breaking changes
+
+* Updated `gimli` and `object` dependencies.
+
+* Added `rustc-dep-of-std` feature.
+ [#166](https://github.com/gimli-rs/addr2line/pull/166)
+
+### Changed
+
+* Improve performance by parsing function contents lazily.
+ [#178](https://github.com/gimli-rs/addr2line/pull/178)
+
+* Don't skip `.debug_info` and `.debug_line` entries with a zero address.
+ [#182](https://github.com/gimli-rs/addr2line/pull/182)
+
+--------------------------------------------------------------------------------
+
+## 0.12.2 (2020/06/21)
+
+### Fixed
+
+* Avoid linear search for `DW_FORM_ref_addr`.
+ [#175](https://github.com/gimli-rs/addr2line/pull/175)
+
+--------------------------------------------------------------------------------
+
+## 0.12.1 (2020/05/19)
+
+### Fixed
+
+* Handle units with overlapping address ranges.
+ [#163](https://github.com/gimli-rs/addr2line/pull/163)
+
+* Don't assert for functions with overlapping address ranges.
+ [#168](https://github.com/gimli-rs/addr2line/pull/168)
+
+--------------------------------------------------------------------------------
+
+## 0.12.0 (2020/05/12)
+
+### Breaking changes
+
+* Updated `gimli` and `object` dependencies.
+
+* Added more optional features: `smallvec` and `fallible-iterator`.
+ [#160](https://github.com/gimli-rs/addr2line/pull/160)
+
+### Added
+
+* Added `Context::dwarf` and `Context::find_dwarf_unit`.
+ [#159](https://github.com/gimli-rs/addr2line/pull/159)
+
+### Changed
+
+* Removed `lazycell` dependency.
+ [#160](https://github.com/gimli-rs/addr2line/pull/160)
+
+--------------------------------------------------------------------------------
+
+## 0.11.0 (2020/01/11)
+
+### Breaking changes
+
+* Updated `gimli` and `object` dependencies.
+
+* [#130](https://github.com/gimli-rs/addr2line/pull/130)
+ Changed `Location::file` from `Option<String>` to `Option<&str>`.
+ This required adding lifetime parameters to `Location` and other structs that
+ contain it.
+
+* [#152](https://github.com/gimli-rs/addr2line/pull/152)
+ Changed `Location::line` and `Location::column` from `Option<u64>`to `Option<u32>`.
+
+* [#156](https://github.com/gimli-rs/addr2line/pull/156)
+ Deleted `alloc` feature, and fixed `no-std` builds with stable rust.
+ Removed default `Reader` parameter for `Context`, and added `ObjectContext` instead.
+
+### Added
+
+* [#134](https://github.com/gimli-rs/addr2line/pull/134)
+ Added `Context::from_dwarf`.
+
+### Changed
+
+* [#133](https://github.com/gimli-rs/addr2line/pull/133)
+ Fixed handling of units that can't be parsed.
+
+* [#155](https://github.com/gimli-rs/addr2line/pull/155)
+ Fixed `addr2line` output to match binutils.
+
+* [#130](https://github.com/gimli-rs/addr2line/pull/130)
+ Improved `.debug_line` parsing performance.
+
+* [#148](https://github.com/gimli-rs/addr2line/pull/148)
+ [#150](https://github.com/gimli-rs/addr2line/pull/150)
+ [#151](https://github.com/gimli-rs/addr2line/pull/151)
+ [#152](https://github.com/gimli-rs/addr2line/pull/152)
+ Improved `.debug_info` parsing performance.
+
+* [#137](https://github.com/gimli-rs/addr2line/pull/137)
+ [#138](https://github.com/gimli-rs/addr2line/pull/138)
+ [#139](https://github.com/gimli-rs/addr2line/pull/139)
+ [#140](https://github.com/gimli-rs/addr2line/pull/140)
+ [#146](https://github.com/gimli-rs/addr2line/pull/146)
+ Improved benchmarks.
+
+--------------------------------------------------------------------------------
+
+## 0.10.0 (2019/07/07)
+
+### Breaking changes
+
+* [#127](https://github.com/gimli-rs/addr2line/pull/127)
+ Update `gimli`.
+
+--------------------------------------------------------------------------------
+
+## 0.9.0 (2019/05/02)
+
+### Breaking changes
+
+* [#121](https://github.com/gimli-rs/addr2line/pull/121)
+ Update `gimli`, `object`, and `fallible-iterator` dependencies.
+
+### Added
+
+* [#121](https://github.com/gimli-rs/addr2line/pull/121)
+ Reexport `gimli`, `object`, and `fallible-iterator`.
+
+--------------------------------------------------------------------------------
+
+## 0.8.0 (2019/02/06)
+
+### Breaking changes
+
+* [#107](https://github.com/gimli-rs/addr2line/pull/107)
+ Update `object` dependency to 0.11. This is part of the public API.
+
+### Added
+
+* [#101](https://github.com/gimli-rs/addr2line/pull/101)
+ Add `object` feature (enabled by default). Disable this feature to remove
+ the `object` dependency and `Context::new` API.
+
+* [#102](https://github.com/gimli-rs/addr2line/pull/102)
+ Add `std` (enabled by default) and `alloc` features.
+
+### Changed
+
+* [#108](https://github.com/gimli-rs/addr2line/issues/108)
+ `demangle` no longer ouputs the hash for rust symbols.
+
+* [#109](https://github.com/gimli-rs/addr2line/issues/109)
+ Set default `R` for `Context<R>`.
diff --git a/vendor/addr2line-0.17.0/Cargo.lock b/vendor/addr2line-0.17.0/Cargo.lock
new file mode 100644
index 000000000..630d72438
--- /dev/null
+++ b/vendor/addr2line-0.17.0/Cargo.lock
@@ -0,0 +1,430 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+version = 3
+
+[[package]]
+name = "addr2line"
+version = "0.16.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3e61f2b7f93d2c7d2b08263acaa4a363b3e276806c68af6134c44f523bf1aacd"
+dependencies = [
+ "gimli 0.25.0",
+]
+
+[[package]]
+name = "addr2line"
+version = "0.17.0"
+dependencies = [
+ "backtrace",
+ "clap",
+ "compiler_builtins",
+ "cpp_demangle",
+ "fallible-iterator",
+ "findshlibs",
+ "gimli 0.26.0",
+ "memmap",
+ "object",
+ "rustc-demangle",
+ "rustc-std-workspace-alloc",
+ "rustc-std-workspace-core",
+ "rustc-test",
+ "smallvec",
+ "typed-arena",
+]
+
+[[package]]
+name = "adler"
+version = "1.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
+
+[[package]]
+name = "ansi_term"
+version = "0.11.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b"
+dependencies = [
+ "winapi 0.3.9",
+]
+
+[[package]]
+name = "atty"
+version = "0.2.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
+dependencies = [
+ "hermit-abi",
+ "libc",
+ "winapi 0.3.9",
+]
+
+[[package]]
+name = "autocfg"
+version = "1.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a"
+
+[[package]]
+name = "backtrace"
+version = "0.3.62"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "091bcdf2da9950f96aa522681ce805e6857f6ca8df73833d35736ab2dc78e152"
+dependencies = [
+ "addr2line 0.16.0",
+ "cc",
+ "cfg-if",
+ "libc",
+ "miniz_oxide",
+ "object",
+ "rustc-demangle",
+]
+
+[[package]]
+name = "bitflags"
+version = "1.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
+
+[[package]]
+name = "cc"
+version = "1.0.71"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "79c2681d6594606957bbb8631c4b90a7fcaaa72cdb714743a437b156d6a7eedd"
+
+[[package]]
+name = "cfg-if"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
+
+[[package]]
+name = "clap"
+version = "2.33.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "37e58ac78573c40708d45522f0d80fa2f01cc4f9b4e2bf749807255454312002"
+dependencies = [
+ "ansi_term",
+ "atty",
+ "bitflags",
+ "strsim",
+ "textwrap",
+ "unicode-width",
+ "vec_map",
+]
+
+[[package]]
+name = "compiler_builtins"
+version = "0.1.51"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3587b3669d6f2c1cfd34c475272dabcfef29d52703933f6f72ebb36d6bd81a97"
+
+[[package]]
+name = "cpp_demangle"
+version = "0.3.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8ea47428dc9d2237f3c6bc134472edfd63ebba0af932e783506dcfd66f10d18a"
+dependencies = [
+ "cfg-if",
+]
+
+[[package]]
+name = "crc32fast"
+version = "1.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "81156fece84ab6a9f2afdb109ce3ae577e42b1228441eded99bd77f627953b1a"
+dependencies = [
+ "cfg-if",
+]
+
+[[package]]
+name = "fallible-iterator"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4443176a9f2c162692bd3d352d745ef9413eec5782a80d8fd6f8a1ac692a07f7"
+
+[[package]]
+name = "findshlibs"
+version = "0.10.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d691fdb3f817632d259d09220d4cf0991dbb2c9e59e044a02a59194bf6e14484"
+dependencies = [
+ "cc",
+ "lazy_static",
+ "libc",
+ "winapi 0.3.9",
+]
+
+[[package]]
+name = "flate2"
+version = "1.0.22"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1e6988e897c1c9c485f43b47a529cef42fde0547f9d8d41a7062518f1d8fc53f"
+dependencies = [
+ "cfg-if",
+ "crc32fast",
+ "libc",
+ "miniz_oxide",
+]
+
+[[package]]
+name = "getopts"
+version = "0.2.21"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "14dbbfd5c71d70241ecf9e6f13737f7b5ce823821063188d7e46c41d371eebd5"
+dependencies = [
+ "unicode-width",
+]
+
+[[package]]
+name = "gimli"
+version = "0.25.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f0a01e0497841a3b2db4f8afa483cce65f7e96a3498bd6c541734792aeac8fe7"
+
+[[package]]
+name = "gimli"
+version = "0.26.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "81a03ce013ffccead76c11a15751231f777d9295b845cc1266ed4d34fcbd7977"
+dependencies = [
+ "compiler_builtins",
+ "fallible-iterator",
+ "rustc-std-workspace-alloc",
+ "rustc-std-workspace-core",
+ "stable_deref_trait",
+]
+
+[[package]]
+name = "hermit-abi"
+version = "0.1.19"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33"
+dependencies = [
+ "libc",
+]
+
+[[package]]
+name = "kernel32-sys"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d"
+dependencies = [
+ "winapi 0.2.8",
+ "winapi-build",
+]
+
+[[package]]
+name = "lazy_static"
+version = "1.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
+
+[[package]]
+name = "libc"
+version = "0.2.105"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "869d572136620d55835903746bcb5cdc54cb2851fd0aeec53220b4bb65ef3013"
+
+[[package]]
+name = "memchr"
+version = "2.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a"
+
+[[package]]
+name = "memmap"
+version = "0.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6585fd95e7bb50d6cc31e20d4cf9afb4e2ba16c5846fc76793f11218da9c475b"
+dependencies = [
+ "libc",
+ "winapi 0.3.9",
+]
+
+[[package]]
+name = "miniz_oxide"
+version = "0.4.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a92518e98c078586bc6c934028adcca4c92a53d6a958196de835170a01d84e4b"
+dependencies = [
+ "adler",
+ "autocfg",
+]
+
+[[package]]
+name = "object"
+version = "0.27.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "67ac1d3f9a1d3616fd9a60c8d74296f22406a238b6a72f5cc1e6f314df4ffbf9"
+dependencies = [
+ "flate2",
+ "memchr",
+]
+
+[[package]]
+name = "rustc-demangle"
+version = "0.1.21"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7ef03e0a2b150c7a90d01faf6254c9c48a41e95fb2a8c2ac1c6f0d2b9aefc342"
+
+[[package]]
+name = "rustc-serialize"
+version = "0.3.24"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda"
+
+[[package]]
+name = "rustc-std-workspace-alloc"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ff66d57013a5686e1917ed6a025d54dd591fcda71a41fe07edf4d16726aefa86"
+
+[[package]]
+name = "rustc-std-workspace-core"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1956f5517128a2b6f23ab2dadf1a976f4f5b27962e7724c2bf3d45e539ec098c"
+
+[[package]]
+name = "rustc-test"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "aacc7967b0ae83af208c8caf2781cbf96f01dac0157cd89f7f05324d6d4e59bb"
+dependencies = [
+ "getopts",
+ "libc",
+ "rustc-serialize",
+ "rustc_version",
+ "term",
+ "time",
+]
+
+[[package]]
+name = "rustc_version"
+version = "0.2.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a"
+dependencies = [
+ "semver",
+]
+
+[[package]]
+name = "semver"
+version = "0.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403"
+dependencies = [
+ "semver-parser",
+]
+
+[[package]]
+name = "semver-parser"
+version = "0.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
+
+[[package]]
+name = "smallvec"
+version = "1.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1ecab6c735a6bb4139c0caafd0cc3635748bbb3acf4550e8138122099251f309"
+
+[[package]]
+name = "stable_deref_trait"
+version = "1.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3"
+
+[[package]]
+name = "strsim"
+version = "0.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
+
+[[package]]
+name = "term"
+version = "0.4.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fa63644f74ce96fbeb9b794f66aff2a52d601cbd5e80f4b97123e3899f4570f1"
+dependencies = [
+ "kernel32-sys",
+ "winapi 0.2.8",
+]
+
+[[package]]
+name = "textwrap"
+version = "0.11.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060"
+dependencies = [
+ "unicode-width",
+]
+
+[[package]]
+name = "time"
+version = "0.1.44"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6db9e6914ab8b1ae1c260a4ae7a49b6c5611b40328a735b21862567685e73255"
+dependencies = [
+ "libc",
+ "wasi",
+ "winapi 0.3.9",
+]
+
+[[package]]
+name = "typed-arena"
+version = "2.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0685c84d5d54d1c26f7d3eb96cd41550adb97baed141a761cf335d3d33bcd0ae"
+
+[[package]]
+name = "unicode-width"
+version = "0.1.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3ed742d4ea2bd1176e236172c8429aaf54486e7ac098db29ffe6529e0ce50973"
+
+[[package]]
+name = "vec_map"
+version = "0.8.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191"
+
+[[package]]
+name = "wasi"
+version = "0.10.0+wasi-snapshot-preview1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f"
+
+[[package]]
+name = "winapi"
+version = "0.2.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a"
+
+[[package]]
+name = "winapi"
+version = "0.3.9"
+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-build"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc"
+
+[[package]]
+name = "winapi-i686-pc-windows-gnu"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
+
+[[package]]
+name = "winapi-x86_64-pc-windows-gnu"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
diff --git a/vendor/addr2line-0.17.0/Cargo.toml b/vendor/addr2line-0.17.0/Cargo.toml
new file mode 100644
index 000000000..358995e53
--- /dev/null
+++ b/vendor/addr2line-0.17.0/Cargo.toml
@@ -0,0 +1,120 @@
+# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
+#
+# When uploading crates to the registry Cargo will automatically
+# "normalize" Cargo.toml files for maximal compatibility
+# with all versions of Cargo and also rewrite `path` dependencies
+# to registry (e.g., crates.io) dependencies
+#
+# If you believe there's an error in this file please file an
+# issue against the rust-lang/cargo repository. If you're
+# editing this file be aware that the upstream Cargo.toml
+# will likely look very different (and much more reasonable)
+
+[package]
+name = "addr2line"
+version = "0.17.0"
+exclude = ["/benches/*", "/fixtures/*", ".github"]
+description = "A cross-platform symbolication library written in Rust, using `gimli`"
+documentation = "https://docs.rs/addr2line"
+readme = "./README.md"
+keywords = ["DWARF", "debug", "elf", "symbolicate", "atos"]
+categories = ["development-tools::debugging"]
+license = "Apache-2.0 OR MIT"
+repository = "https://github.com/gimli-rs/addr2line"
+[profile.bench]
+codegen-units = 1
+debug = true
+split-debuginfo = "packed"
+
+[profile.dev]
+split-debuginfo = "packed"
+
+[profile.release]
+debug = true
+split-debuginfo = "packed"
+
+[profile.test]
+split-debuginfo = "packed"
+
+[[example]]
+name = "addr2line"
+required-features = ["std-object"]
+
+[[test]]
+name = "output_equivalence"
+harness = false
+required-features = ["std-object"]
+
+[[test]]
+name = "correctness"
+required-features = ["default"]
+
+[[test]]
+name = "parse"
+required-features = ["std-object"]
+[dependencies.alloc]
+version = "1.0.0"
+optional = true
+package = "rustc-std-workspace-alloc"
+
+[dependencies.compiler_builtins]
+version = "0.1.2"
+optional = true
+
+[dependencies.core]
+version = "1.0.0"
+optional = true
+package = "rustc-std-workspace-core"
+
+[dependencies.cpp_demangle]
+version = "0.3"
+optional = true
+default-features = false
+
+[dependencies.fallible-iterator]
+version = "0.2"
+optional = true
+default-features = false
+
+[dependencies.gimli]
+version = "0.26"
+features = ["read"]
+default-features = false
+
+[dependencies.object]
+version = "0.27.1"
+features = ["read"]
+optional = true
+default-features = false
+
+[dependencies.rustc-demangle]
+version = "0.1"
+optional = true
+
+[dependencies.smallvec]
+version = "1"
+optional = true
+default-features = false
+[dev-dependencies.backtrace]
+version = "0.3.13"
+
+[dev-dependencies.clap]
+version = "2"
+
+[dev-dependencies.findshlibs]
+version = "0.10"
+
+[dev-dependencies.memmap]
+version = "0.7"
+
+[dev-dependencies.rustc-test]
+version = "0.3"
+
+[dev-dependencies.typed-arena]
+version = "2"
+
+[features]
+default = ["rustc-demangle", "cpp_demangle", "std-object", "fallible-iterator", "smallvec"]
+rustc-dep-of-std = ["core", "alloc", "compiler_builtins", "gimli/rustc-dep-of-std"]
+std = ["gimli/std"]
+std-object = ["std", "object", "object/std", "object/compression", "gimli/endian-reader"]
diff --git a/vendor/parking_lot_core-0.8.5/LICENSE-APACHE b/vendor/addr2line-0.17.0/LICENSE-APACHE
index 16fe87b06..16fe87b06 100644
--- a/vendor/parking_lot_core-0.8.5/LICENSE-APACHE
+++ b/vendor/addr2line-0.17.0/LICENSE-APACHE
diff --git a/vendor/addr2line-0.17.0/LICENSE-MIT b/vendor/addr2line-0.17.0/LICENSE-MIT
new file mode 100644
index 000000000..3a03f1f85
--- /dev/null
+++ b/vendor/addr2line-0.17.0/LICENSE-MIT
@@ -0,0 +1,25 @@
+Copyright (c) 2016-2018 The gimli Developers
+
+Permission is hereby granted, free of charge, to any
+person obtaining a copy of this software and associated
+documentation files (the "Software"), to deal in the
+Software without restriction, including without
+limitation the rights to use, copy, modify, merge,
+publish, distribute, sublicense, and/or sell copies of
+the Software, and to permit persons to whom the Software
+is furnished to do so, subject to the following
+conditions:
+
+The above copyright notice and this permission notice
+shall be included in all copies or substantial portions
+of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
+ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
+TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
+SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
+IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
diff --git a/vendor/addr2line-0.17.0/README.md b/vendor/addr2line-0.17.0/README.md
new file mode 100644
index 000000000..dc6cb9344
--- /dev/null
+++ b/vendor/addr2line-0.17.0/README.md
@@ -0,0 +1,48 @@
+# addr2line
+
+[![](https://img.shields.io/crates/v/addr2line.svg)](https://crates.io/crates/addr2line)
+[![](https://img.shields.io/docsrs/addr2line.svg)](https://docs.rs/addr2line)
+[![Coverage Status](https://coveralls.io/repos/github/gimli-rs/addr2line/badge.svg?branch=master)](https://coveralls.io/github/gimli-rs/addr2line?branch=master)
+
+A cross-platform library for retrieving per-address debug information
+from files with DWARF debug information.
+
+`addr2line` uses [`gimli`](https://github.com/gimli-rs/gimli) to parse
+the debug information, and exposes an interface for finding
+the source file, line number, and wrapping function for instruction
+addresses within the target program. These lookups can either be
+performed programmatically through `Context::find_location` and
+`Context::find_frames`, or via the included example binary,
+`addr2line` (named and modelled after the equivalent utility from
+[GNU binutils](https://sourceware.org/binutils/docs/binutils/addr2line.html)).
+
+# Quickstart
+ - Add the [`addr2line` crate](https://crates.io/crates/addr2line) to your `Cargo.toml`
+ - Load the file and parse it with [`addr2line::object::read::File::parse`](https://docs.rs/object/*/object/read/struct.File.html#method.parse)
+ - Pass the parsed file to [`addr2line::Context::new` ](https://docs.rs/addr2line/*/addr2line/struct.Context.html#method.new)
+ - Use [`addr2line::Context::find_location`](https://docs.rs/addr2line/*/addr2line/struct.Context.html#method.find_location)
+ or [`addr2line::Context::find_frames`](https://docs.rs/addr2line/*/addr2line/struct.Context.html#method.find_frames)
+ to look up debug information for an address
+
+# Performance
+
+`addr2line` optimizes for speed over memory by caching parsed information.
+The DWARF information is parsed lazily where possible.
+
+The library aims to perform similarly to equivalent existing tools such
+as `addr2line` from binutils, `eu-addr2line` from elfutils, and
+`llvm-symbolize` from the llvm project, and in the past some benchmarking
+was done that indicates a comparable performance.
+
+## License
+
+Licensed under either of
+
+ * Apache License, Version 2.0 ([`LICENSE-APACHE`](./LICENSE-APACHE) or https://www.apache.org/licenses/LICENSE-2.0)
+ * MIT license ([`LICENSE-MIT`](./LICENSE-MIT) or https://opensource.org/licenses/MIT)
+
+at your option.
+
+Unless you explicitly state otherwise, any contribution intentionally submitted
+for inclusion in the work by you, as defined in the Apache-2.0 license, shall be
+dual licensed as above, without any additional terms or conditions.
diff --git a/vendor/addr2line-0.17.0/bench.plot.r b/vendor/addr2line-0.17.0/bench.plot.r
new file mode 100644
index 000000000..ecbf24893
--- /dev/null
+++ b/vendor/addr2line-0.17.0/bench.plot.r
@@ -0,0 +1,23 @@
+v <- read.table(file("stdin"))
+t <- data.frame(prog=v[,1], funcs=(v[,2]=="func"), time=v[,3], mem=v[,4], stringsAsFactors=FALSE)
+
+t$prog <- as.character(t$prog)
+t$prog[t$prog == "master"] <- "gimli-rs/addr2line"
+t$funcs[t$funcs == TRUE] <- "With functions"
+t$funcs[t$funcs == FALSE] <- "File/line only"
+t$mem = t$mem / 1024.0
+
+library(ggplot2)
+p <- ggplot(data=t, aes(x=prog, y=time, fill=prog))
+p <- p + geom_bar(stat = "identity")
+p <- p + facet_wrap(~ funcs)
+p <- p + theme(axis.title.x=element_blank(), axis.text.x=element_blank(), axis.ticks.x=element_blank())
+p <- p + ylab("time (s)") + ggtitle("addr2line runtime")
+ggsave('time.png',plot=p,width=10,height=6)
+
+p <- ggplot(data=t, aes(x=prog, y=mem, fill=prog))
+p <- p + geom_bar(stat = "identity")
+p <- p + facet_wrap(~ funcs)
+p <- p + theme(axis.title.x=element_blank(), axis.text.x=element_blank(), axis.ticks.x=element_blank())
+p <- p + ylab("memory (kB)") + ggtitle("addr2line memory usage")
+ggsave('memory.png',plot=p,width=10,height=6)
diff --git a/vendor/addr2line-0.17.0/benchmark.sh b/vendor/addr2line-0.17.0/benchmark.sh
new file mode 100755
index 000000000..ca4c4f6ec
--- /dev/null
+++ b/vendor/addr2line-0.17.0/benchmark.sh
@@ -0,0 +1,112 @@
+#!/bin/bash
+if [[ $# -le 1 ]]; then
+ echo "Usage: $0 <executable> [<addresses>] REFS..."
+ exit 1
+fi
+target="$1"
+shift
+
+addresses=""
+if [[ -e "$1" ]]; then
+ addresses="$1"
+ shift
+fi
+
+# path to "us"
+# readlink -f, but more portable:
+dirname=$(perl -e 'use Cwd "abs_path";print abs_path(shift)' "$(dirname "$0")")
+
+# https://stackoverflow.com/a/2358432/472927
+{
+ # compile all refs
+ pushd "$dirname" > /dev/null
+ # if the user has some local changes, preserve them
+ nstashed=$(git stash list | wc -l)
+ echo "==> Stashing any local modifications"
+ git stash --keep-index > /dev/null
+ popstash() {
+ # https://stackoverflow.com/q/24520791/472927
+ if [[ "$(git stash list | wc -l)" -ne "$nstashed" ]]; then
+ echo "==> Restoring stashed state"
+ git stash pop > /dev/null
+ fi
+ }
+ # if the user has added stuff to the index, abort
+ if ! git diff-index --quiet HEAD --; then
+ echo "Refusing to overwrite outstanding git changes"
+ popstash
+ exit 2
+ fi
+ current=$(git symbolic-ref --short HEAD)
+ for ref in "$@"; do
+ echo "==> Compiling $ref"
+ git checkout -q "$ref"
+ commit=$(git rev-parse HEAD)
+ fn="target/release/addr2line-$commit"
+ if [[ ! -e "$fn" ]]; then
+ cargo build --release --example addr2line
+ cp target/release/examples/addr2line "$fn"
+ fi
+ if [[ "$ref" != "$commit" ]]; then
+ ln -sfn "addr2line-$commit" target/release/addr2line-"$ref"
+ fi
+ done
+ git checkout -q "$current"
+ popstash
+ popd > /dev/null
+
+ # get us some addresses to look up
+ if [[ -z "$addresses" ]]; then
+ echo "==> Looking for benchmarking addresses (this may take a while)"
+ addresses=$(mktemp tmp.XXXXXXXXXX)
+ objdump -C -x --disassemble -l "$target" \
+ | grep -P '0[048]:' \
+ | awk '{print $1}' \
+ | sed 's/:$//' \
+ > "$addresses"
+ echo " -> Addresses stored in $addresses; you should re-use it next time"
+ fi
+
+ run() {
+ func="$1"
+ name="$2"
+ cmd="$3"
+ args="$4"
+ printf "%s\t%s\t" "$name" "$func"
+ if [[ "$cmd" =~ llvm-symbolizer ]]; then
+ /usr/bin/time -f '%e\t%M' "$cmd" $args -obj="$target" < "$addresses" 2>&1 >/dev/null
+ else
+ /usr/bin/time -f '%e\t%M' "$cmd" $args -e "$target" < "$addresses" 2>&1 >/dev/null
+ fi
+ }
+
+ # run without functions
+ log1=$(mktemp tmp.XXXXXXXXXX)
+ echo "==> Benchmarking"
+ run nofunc binutils addr2line >> "$log1"
+ #run nofunc elfutils eu-addr2line >> "$log1"
+ run nofunc llvm-sym llvm-symbolizer -functions=none >> "$log1"
+ for ref in "$@"; do
+ run nofunc "$ref" "$dirname/target/release/addr2line-$ref" >> "$log1"
+ done
+ cat "$log1" | column -t
+
+ # run with functions
+ log2=$(mktemp tmp.XXXXXXXXXX)
+ echo "==> Benchmarking with -f"
+ run func binutils addr2line "-f -i" >> "$log2"
+ #run func elfutils eu-addr2line "-f -i" >> "$log2"
+ run func llvm-sym llvm-symbolizer "-functions=linkage -demangle=0" >> "$log2"
+ for ref in "$@"; do
+ run func "$ref" "$dirname/target/release/addr2line-$ref" "-f -i" >> "$log2"
+ done
+ cat "$log2" | column -t
+ cat "$log2" >> "$log1"; rm "$log2"
+
+ echo "==> Plotting"
+ Rscript --no-readline --no-restore --no-save "$dirname/bench.plot.r" < "$log1"
+
+ echo "==> Cleaning up"
+ rm "$log1"
+ exit 0
+}
diff --git a/vendor/addr2line-0.17.0/coverage.sh b/vendor/addr2line-0.17.0/coverage.sh
new file mode 100644
index 000000000..892c0b7fa
--- /dev/null
+++ b/vendor/addr2line-0.17.0/coverage.sh
@@ -0,0 +1,5 @@
+#!/bin/sh
+# Run tarpaulin and pycobertura to generate coverage.html.
+
+cargo tarpaulin --skip-clean --out Xml
+pycobertura show --format html --output coverage.html cobertura.xml
diff --git a/vendor/addr2line-0.17.0/examples/addr2line.rs b/vendor/addr2line-0.17.0/examples/addr2line.rs
new file mode 100644
index 000000000..4b228a706
--- /dev/null
+++ b/vendor/addr2line-0.17.0/examples/addr2line.rs
@@ -0,0 +1,299 @@
+extern crate addr2line;
+extern crate clap;
+extern crate fallible_iterator;
+extern crate gimli;
+extern crate memmap;
+extern crate object;
+extern crate typed_arena;
+
+use std::borrow::Cow;
+use std::fs::File;
+use std::io::{BufRead, Lines, StdinLock, Write};
+use std::path::Path;
+
+use clap::{App, Arg, Values};
+use fallible_iterator::FallibleIterator;
+use object::{Object, ObjectSection};
+use typed_arena::Arena;
+
+use addr2line::{Context, Location};
+
+fn parse_uint_from_hex_string(string: &str) -> u64 {
+ if string.len() > 2 && string.starts_with("0x") {
+ u64::from_str_radix(&string[2..], 16).expect("Failed to parse address")
+ } else {
+ u64::from_str_radix(string, 16).expect("Failed to parse address")
+ }
+}
+
+enum Addrs<'a> {
+ Args(Values<'a>),
+ Stdin(Lines<StdinLock<'a>>),
+}
+
+impl<'a> Iterator for Addrs<'a> {
+ type Item = u64;
+
+ fn next(&mut self) -> Option<u64> {
+ let text = match *self {
+ Addrs::Args(ref mut vals) => vals.next().map(Cow::from),
+ Addrs::Stdin(ref mut lines) => lines.next().map(Result::unwrap).map(Cow::from),
+ };
+ text.as_ref()
+ .map(Cow::as_ref)
+ .map(parse_uint_from_hex_string)
+ }
+}
+
+fn print_loc(loc: &Option<Location>, basenames: bool, llvm: bool) {
+ if let Some(ref loc) = *loc {
+ let file = loc.file.as_ref().unwrap();
+ let path = if basenames {
+ Path::new(Path::new(file).file_name().unwrap())
+ } else {
+ Path::new(file)
+ };
+ print!("{}:", path.display());
+ if llvm {
+ print!("{}:{}", loc.line.unwrap_or(0), loc.column.unwrap_or(0));
+ } else if let Some(line) = loc.line {
+ print!("{}", line);
+ } else {
+ print!("?");
+ }
+ println!();
+ } else if llvm {
+ println!("??:0:0");
+ } else {
+ println!("??:?");
+ }
+}
+
+fn print_function(name: &str, language: Option<gimli::DwLang>, demangle: bool) {
+ if demangle {
+ print!("{}", addr2line::demangle_auto(Cow::from(name), language));
+ } else {
+ print!("{}", name);
+ }
+}
+
+fn load_file_section<'input, 'arena, Endian: gimli::Endianity>(
+ id: gimli::SectionId,
+ file: &object::File<'input>,
+ endian: Endian,
+ arena_data: &'arena Arena<Cow<'input, [u8]>>,
+) -> Result<gimli::EndianSlice<'arena, Endian>, ()> {
+ // TODO: Unify with dwarfdump.rs in gimli.
+ let name = id.name();
+ match file.section_by_name(name) {
+ Some(section) => match section.uncompressed_data().unwrap() {
+ Cow::Borrowed(b) => Ok(gimli::EndianSlice::new(b, endian)),
+ Cow::Owned(b) => Ok(gimli::EndianSlice::new(arena_data.alloc(b.into()), endian)),
+ },
+ None => Ok(gimli::EndianSlice::new(&[][..], endian)),
+ }
+}
+
+fn main() {
+ let matches = App::new("hardliner")
+ .version("0.1")
+ .about("A fast addr2line clone")
+ .arg(
+ Arg::with_name("exe")
+ .short("e")
+ .long("exe")
+ .value_name("filename")
+ .help(
+ "Specify the name of the executable for which addresses should be translated.",
+ )
+ .required(true),
+ )
+ .arg(
+ Arg::with_name("sup")
+ .long("sup")
+ .value_name("filename")
+ .help("Path to supplementary object file."),
+ )
+ .arg(
+ Arg::with_name("functions")
+ .short("f")
+ .long("functions")
+ .help("Display function names as well as file and line number information."),
+ )
+ .arg(
+ Arg::with_name("pretty")
+ .short("p")
+ .long("pretty-print")
+ .help(
+ "Make the output more human friendly: each location are printed on \
+ one line.",
+ ),
+ )
+ .arg(Arg::with_name("inlines").short("i").long("inlines").help(
+ "If the address belongs to a function that was inlined, the source \
+ information for all enclosing scopes back to the first non-inlined \
+ function will also be printed.",
+ ))
+ .arg(
+ Arg::with_name("addresses")
+ .short("a")
+ .long("addresses")
+ .help(
+ "Display the address before the function name, file and line \
+ number information.",
+ ),
+ )
+ .arg(
+ Arg::with_name("basenames")
+ .short("s")
+ .long("basenames")
+ .help("Display only the base of each file name."),
+ )
+ .arg(Arg::with_name("demangle").short("C").long("demangle").help(
+ "Demangle function names. \
+ Specifying a specific demangling style (like GNU addr2line) \
+ is not supported. (TODO)",
+ ))
+ .arg(
+ Arg::with_name("llvm")
+ .long("llvm")
+ .help("Display output in the same format as llvm-symbolizer."),
+ )
+ .arg(
+ Arg::with_name("addrs")
+ .takes_value(true)
+ .multiple(true)
+ .help("Addresses to use instead of reading from stdin."),
+ )
+ .get_matches();
+
+ let arena_data = Arena::new();
+
+ let do_functions = matches.is_present("functions");
+ let do_inlines = matches.is_present("inlines");
+ let pretty = matches.is_present("pretty");
+ let print_addrs = matches.is_present("addresses");
+ let basenames = matches.is_present("basenames");
+ let demangle = matches.is_present("demangle");
+ let llvm = matches.is_present("llvm");
+ let path = matches.value_of("exe").unwrap();
+
+ let file = File::open(path).unwrap();
+ let map = unsafe { memmap::Mmap::map(&file).unwrap() };
+ let object = &object::File::parse(&*map).unwrap();
+
+ let endian = if object.is_little_endian() {
+ gimli::RunTimeEndian::Little
+ } else {
+ gimli::RunTimeEndian::Big
+ };
+
+ let mut load_section = |id: gimli::SectionId| -> Result<_, _> {
+ load_file_section(id, object, endian, &arena_data)
+ };
+
+ let sup_map;
+ let sup_object = if let Some(sup_path) = matches.value_of("sup") {
+ let sup_file = File::open(sup_path).unwrap();
+ sup_map = unsafe { memmap::Mmap::map(&sup_file).unwrap() };
+ Some(object::File::parse(&*sup_map).unwrap())
+ } else {
+ None
+ };
+
+ let symbols = object.symbol_map();
+ let mut dwarf = gimli::Dwarf::load(&mut load_section).unwrap();
+ if let Some(ref sup_object) = sup_object {
+ let mut load_sup_section = |id: gimli::SectionId| -> Result<_, _> {
+ load_file_section(id, sup_object, endian, &arena_data)
+ };
+ dwarf.load_sup(&mut load_sup_section).unwrap();
+ }
+
+ let ctx = Context::from_dwarf(dwarf).unwrap();
+
+ let stdin = std::io::stdin();
+ let addrs = matches
+ .values_of("addrs")
+ .map(Addrs::Args)
+ .unwrap_or_else(|| Addrs::Stdin(stdin.lock().lines()));
+
+ for probe in addrs {
+ if print_addrs {
+ if llvm {
+ print!("0x{:x}", probe);
+ } else {
+ print!("0x{:016x}", probe);
+ }
+ if pretty {
+ print!(": ");
+ } else {
+ println!();
+ }
+ }
+
+ if do_functions || do_inlines {
+ let mut printed_anything = false;
+ let mut frames = ctx.find_frames(probe).unwrap().enumerate();
+ while let Some((i, frame)) = frames.next().unwrap() {
+ if pretty && i != 0 {
+ print!(" (inlined by) ");
+ }
+
+ if do_functions {
+ if let Some(func) = frame.function {
+ print_function(&func.raw_name().unwrap(), func.language, demangle);
+ } else if let Some(name) = symbols.get(probe).map(|x| x.name()) {
+ print_function(name, None, demangle);
+ } else {
+ print!("??");
+ }
+
+ if pretty {
+ print!(" at ");
+ } else {
+ println!();
+ }
+ }
+
+ print_loc(&frame.location, basenames, llvm);
+
+ printed_anything = true;
+
+ if !do_inlines {
+ break;
+ }
+ }
+
+ if !printed_anything {
+ if do_functions {
+ if let Some(name) = symbols.get(probe).map(|x| x.name()) {
+ print_function(name, None, demangle);
+ } else {
+ print!("??");
+ }
+
+ if pretty {
+ print!(" at ");
+ } else {
+ println!();
+ }
+ }
+
+ if llvm {
+ println!("??:0:0");
+ } else {
+ println!("??:?");
+ }
+ }
+ } else {
+ let loc = ctx.find_location(probe).unwrap();
+ print_loc(&loc, basenames, llvm);
+ }
+
+ if llvm {
+ println!();
+ }
+ std::io::stdout().flush().unwrap();
+ }
+}
diff --git a/vendor/addr2line-0.17.0/rustfmt.toml b/vendor/addr2line-0.17.0/rustfmt.toml
new file mode 100644
index 000000000..8b1378917
--- /dev/null
+++ b/vendor/addr2line-0.17.0/rustfmt.toml
@@ -0,0 +1 @@
+
diff --git a/vendor/addr2line-0.17.0/src/function.rs b/vendor/addr2line-0.17.0/src/function.rs
new file mode 100644
index 000000000..1589acdbe
--- /dev/null
+++ b/vendor/addr2line-0.17.0/src/function.rs
@@ -0,0 +1,520 @@
+use alloc::boxed::Box;
+use alloc::vec::Vec;
+use core::cmp::Ordering;
+use core::iter;
+
+use crate::lazy::LazyCell;
+use crate::maybe_small;
+use crate::{Error, RangeAttributes, ResDwarf};
+
+pub(crate) struct Functions<R: gimli::Reader> {
+ /// List of all `DW_TAG_subprogram` details in the unit.
+ pub(crate) functions: Box<
+ [(
+ gimli::UnitOffset<R::Offset>,
+ LazyCell<Result<Function<R>, Error>>,
+ )],
+ >,
+ /// List of `DW_TAG_subprogram` address ranges in the unit.
+ pub(crate) addresses: Box<[FunctionAddress]>,
+}
+
+/// A single address range for a function.
+///
+/// It is possible for a function to have multiple address ranges; this
+/// is handled by having multiple `FunctionAddress` entries with the same
+/// `function` field.
+pub(crate) struct FunctionAddress {
+ range: gimli::Range,
+ /// An index into `Functions::functions`.
+ pub(crate) function: usize,
+}
+
+pub(crate) struct Function<R: gimli::Reader> {
+ pub(crate) dw_die_offset: gimli::UnitOffset<R::Offset>,
+ pub(crate) name: Option<R>,
+ /// List of all `DW_TAG_inlined_subroutine` details in this function.
+ inlined_functions: Box<[InlinedFunction<R>]>,
+ /// List of `DW_TAG_inlined_subroutine` address ranges in this function.
+ inlined_addresses: Box<[InlinedFunctionAddress]>,
+}
+
+pub(crate) struct InlinedFunctionAddress {
+ range: gimli::Range,
+ call_depth: usize,
+ /// An index into `Function::inlined_functions`.
+ function: usize,
+}
+
+pub(crate) struct InlinedFunction<R: gimli::Reader> {
+ pub(crate) dw_die_offset: gimli::UnitOffset<R::Offset>,
+ pub(crate) name: Option<R>,
+ pub(crate) call_file: u64,
+ pub(crate) call_line: u32,
+ pub(crate) call_column: u32,
+}
+
+impl<R: gimli::Reader> Functions<R> {
+ pub(crate) fn parse(unit: &gimli::Unit<R>, dwarf: &ResDwarf<R>) -> Result<Functions<R>, Error> {
+ let mut functions = Vec::new();
+ let mut addresses = Vec::new();
+ let mut entries = unit.entries_raw(None)?;
+ while !entries.is_empty() {
+ let dw_die_offset = entries.next_offset();
+ if let Some(abbrev) = entries.read_abbreviation()? {
+ if abbrev.tag() == gimli::DW_TAG_subprogram {
+ let mut ranges = RangeAttributes::default();
+ for spec in abbrev.attributes() {
+ match entries.read_attribute(*spec) {
+ Ok(ref attr) => {
+ match attr.name() {
+ gimli::DW_AT_low_pc => {
+ if let gimli::AttributeValue::Addr(val) = attr.value() {
+ ranges.low_pc = Some(val);
+ }
+ }
+ gimli::DW_AT_high_pc => match attr.value() {
+ gimli::AttributeValue::Addr(val) => {
+ ranges.high_pc = Some(val)
+ }
+ gimli::AttributeValue::Udata(val) => {
+ ranges.size = Some(val)
+ }
+ _ => {}
+ },
+ gimli::DW_AT_ranges => {
+ ranges.ranges_offset = dwarf
+ .sections
+ .attr_ranges_offset(unit, attr.value())?;
+ }
+ _ => {}
+ };
+ }
+ Err(e) => return Err(e),
+ }
+ }
+
+ let function_index = functions.len();
+ if ranges.for_each_range(&dwarf.sections, unit, |range| {
+ addresses.push(FunctionAddress {
+ range,
+ function: function_index,
+ });
+ })? {
+ functions.push((dw_die_offset, LazyCell::new()));
+ }
+ } else {
+ entries.skip_attributes(abbrev.attributes())?;
+ }
+ }
+ }
+
+ // The binary search requires the addresses to be sorted.
+ //
+ // It also requires them to be non-overlapping. In practice, overlapping
+ // function ranges are unlikely, so we don't try to handle that yet.
+ //
+ // It's possible for multiple functions to have the same address range if the
+ // compiler can detect and remove functions with identical code. In that case
+ // we'll nondeterministically return one of them.
+ addresses.sort_by_key(|x| x.range.begin);
+
+ Ok(Functions {
+ functions: functions.into_boxed_slice(),
+ addresses: addresses.into_boxed_slice(),
+ })
+ }
+
+ pub(crate) fn find_address(&self, probe: u64) -> Option<usize> {
+ self.addresses
+ .binary_search_by(|address| {
+ if probe < address.range.begin {
+ Ordering::Greater
+ } else if probe >= address.range.end {
+ Ordering::Less
+ } else {
+ Ordering::Equal
+ }
+ })
+ .ok()
+ }
+
+ pub(crate) fn parse_inlined_functions(
+ &self,
+ unit: &gimli::Unit<R>,
+ dwarf: &ResDwarf<R>,
+ ) -> Result<(), Error> {
+ for function in &*self.functions {
+ function
+ .1
+ .borrow_with(|| Function::parse(function.0, unit, dwarf))
+ .as_ref()
+ .map_err(Error::clone)?;
+ }
+ Ok(())
+ }
+}
+
+impl<R: gimli::Reader> Function<R> {
+ pub(crate) fn parse(
+ dw_die_offset: gimli::UnitOffset<R::Offset>,
+ unit: &gimli::Unit<R>,
+ dwarf: &ResDwarf<R>,
+ ) -> Result<Self, Error> {
+ let mut entries = unit.entries_raw(Some(dw_die_offset))?;
+ let depth = entries.next_depth();
+ let abbrev = entries.read_abbreviation()?.unwrap();
+ debug_assert_eq!(abbrev.tag(), gimli::DW_TAG_subprogram);
+
+ let mut name = None;
+ for spec in abbrev.attributes() {
+ match entries.read_attribute(*spec) {
+ Ok(ref attr) => {
+ match attr.name() {
+ gimli::DW_AT_linkage_name | gimli::DW_AT_MIPS_linkage_name => {
+ if let Ok(val) = dwarf.sections.attr_string(unit, attr.value()) {
+ name = Some(val);
+ }
+ }
+ gimli::DW_AT_name => {
+ if name.is_none() {
+ name = dwarf.sections.attr_string(unit, attr.value()).ok();
+ }
+ }
+ gimli::DW_AT_abstract_origin | gimli::DW_AT_specification => {
+ if name.is_none() {
+ name = name_attr(attr.value(), unit, dwarf, 16)?;
+ }
+ }
+ _ => {}
+ };
+ }
+ Err(e) => return Err(e),
+ }
+ }
+
+ let mut inlined_functions = Vec::new();
+ let mut inlined_addresses = Vec::new();
+ Function::parse_children(
+ &mut entries,
+ depth,
+ unit,
+ dwarf,
+ &mut inlined_functions,
+ &mut inlined_addresses,
+ 0,
+ )?;
+
+ // Sort ranges in "breadth-first traversal order", i.e. first by call_depth
+ // and then by range.begin. This allows finding the range containing an
+ // address at a certain depth using binary search.
+ // Note: Using DFS order, i.e. ordering by range.begin first and then by
+ // call_depth, would not work! Consider the two examples
+ // "[0..10 at depth 0], [0..2 at depth 1], [6..8 at depth 1]" and
+ // "[0..5 at depth 0], [0..2 at depth 1], [5..10 at depth 0], [6..8 at depth 1]".
+ // In this example, if you want to look up address 7 at depth 0, and you
+ // encounter [0..2 at depth 1], are you before or after the target range?
+ // You don't know.
+ inlined_addresses.sort_by(|r1, r2| {
+ if r1.call_depth < r2.call_depth {
+ Ordering::Less
+ } else if r1.call_depth > r2.call_depth {
+ Ordering::Greater
+ } else if r1.range.begin < r2.range.begin {
+ Ordering::Less
+ } else if r1.range.begin > r2.range.begin {
+ Ordering::Greater
+ } else {
+ Ordering::Equal
+ }
+ });
+
+ Ok(Function {
+ dw_die_offset,
+ name,
+ inlined_functions: inlined_functions.into_boxed_slice(),
+ inlined_addresses: inlined_addresses.into_boxed_slice(),
+ })
+ }
+
+ fn parse_children(
+ entries: &mut gimli::EntriesRaw<R>,
+ depth: isize,
+ unit: &gimli::Unit<R>,
+ dwarf: &ResDwarf<R>,
+ inlined_functions: &mut Vec<InlinedFunction<R>>,
+ inlined_addresses: &mut Vec<InlinedFunctionAddress>,
+ inlined_depth: usize,
+ ) -> Result<(), Error> {
+ loop {
+ let dw_die_offset = entries.next_offset();
+ let next_depth = entries.next_depth();
+ if next_depth <= depth {
+ return Ok(());
+ }
+ if let Some(abbrev) = entries.read_abbreviation()? {
+ match abbrev.tag() {
+ gimli::DW_TAG_subprogram => {
+ Function::skip(entries, abbrev, next_depth)?;
+ }
+ gimli::DW_TAG_inlined_subroutine => {
+ InlinedFunction::parse(
+ dw_die_offset,
+ entries,
+ abbrev,
+ next_depth,
+ unit,
+ dwarf,
+ inlined_functions,
+ inlined_addresses,
+ inlined_depth,
+ )?;
+ }
+ _ => {
+ entries.skip_attributes(abbrev.attributes())?;
+ }
+ }
+ }
+ }
+ }
+
+ fn skip(
+ entries: &mut gimli::EntriesRaw<R>,
+ abbrev: &gimli::Abbreviation,
+ depth: isize,
+ ) -> Result<(), Error> {
+ // TODO: use DW_AT_sibling
+ entries.skip_attributes(abbrev.attributes())?;
+ while entries.next_depth() > depth {
+ if let Some(abbrev) = entries.read_abbreviation()? {
+ entries.skip_attributes(abbrev.attributes())?;
+ }
+ }
+ Ok(())
+ }
+
+ /// Build the list of inlined functions that contain `probe`.
+ pub(crate) fn find_inlined_functions(
+ &self,
+ probe: u64,
+ ) -> iter::Rev<maybe_small::IntoIter<&InlinedFunction<R>>> {
+ // `inlined_functions` is ordered from outside to inside.
+ let mut inlined_functions = maybe_small::Vec::new();
+ let mut inlined_addresses = &self.inlined_addresses[..];
+ loop {
+ let current_depth = inlined_functions.len();
+ // Look up (probe, current_depth) in inline_ranges.
+ // `inlined_addresses` is sorted in "breadth-first traversal order", i.e.
+ // by `call_depth` first, and then by `range.begin`. See the comment at
+ // the sort call for more information about why.
+ let search = inlined_addresses.binary_search_by(|range| {
+ if range.call_depth > current_depth {
+ Ordering::Greater
+ } else if range.call_depth < current_depth {
+ Ordering::Less
+ } else if range.range.begin > probe {
+ Ordering::Greater
+ } else if range.range.end <= probe {
+ Ordering::Less
+ } else {
+ Ordering::Equal
+ }
+ });
+ if let Ok(index) = search {
+ let function_index = inlined_addresses[index].function;
+ inlined_functions.push(&self.inlined_functions[function_index]);
+ inlined_addresses = &inlined_addresses[index + 1..];
+ } else {
+ break;
+ }
+ }
+ inlined_functions.into_iter().rev()
+ }
+}
+
+impl<R: gimli::Reader> InlinedFunction<R> {
+ fn parse(
+ dw_die_offset: gimli::UnitOffset<R::Offset>,
+ entries: &mut gimli::EntriesRaw<R>,
+ abbrev: &gimli::Abbreviation,
+ depth: isize,
+ unit: &gimli::Unit<R>,
+ dwarf: &ResDwarf<R>,
+ inlined_functions: &mut Vec<InlinedFunction<R>>,
+ inlined_addresses: &mut Vec<InlinedFunctionAddress>,
+ inlined_depth: usize,
+ ) -> Result<(), Error> {
+ let mut ranges = RangeAttributes::default();
+ let mut name = None;
+ let mut call_file = 0;
+ let mut call_line = 0;
+ let mut call_column = 0;
+ for spec in abbrev.attributes() {
+ match entries.read_attribute(*spec) {
+ Ok(ref attr) => match attr.name() {
+ gimli::DW_AT_low_pc => {
+ if let gimli::AttributeValue::Addr(val) = attr.value() {
+ ranges.low_pc = Some(val);
+ }
+ }
+ gimli::DW_AT_high_pc => match attr.value() {
+ gimli::AttributeValue::Addr(val) => ranges.high_pc = Some(val),
+ gimli::AttributeValue::Udata(val) => ranges.size = Some(val),
+ _ => {}
+ },
+ gimli::DW_AT_ranges => {
+ ranges.ranges_offset =
+ dwarf.sections.attr_ranges_offset(unit, attr.value())?;
+ }
+ gimli::DW_AT_linkage_name | gimli::DW_AT_MIPS_linkage_name => {
+ if let Ok(val) = dwarf.sections.attr_string(unit, attr.value()) {
+ name = Some(val);
+ }
+ }
+ gimli::DW_AT_name => {
+ if name.is_none() {
+ name = dwarf.sections.attr_string(unit, attr.value()).ok();
+ }
+ }
+ gimli::DW_AT_abstract_origin | gimli::DW_AT_specification => {
+ if name.is_none() {
+ name = name_attr(attr.value(), unit, dwarf, 16)?;
+ }
+ }
+ gimli::DW_AT_call_file => {
+ if let gimli::AttributeValue::FileIndex(fi) = attr.value() {
+ call_file = fi;
+ }
+ }
+ gimli::DW_AT_call_line => {
+ call_line = attr.udata_value().unwrap_or(0) as u32;
+ }
+ gimli::DW_AT_call_column => {
+ call_column = attr.udata_value().unwrap_or(0) as u32;
+ }
+ _ => {}
+ },
+ Err(e) => return Err(e),
+ }
+ }
+
+ let function_index = inlined_functions.len();
+ inlined_functions.push(InlinedFunction {
+ dw_die_offset,
+ name,
+ call_file,
+ call_line,
+ call_column,
+ });
+
+ ranges.for_each_range(&dwarf.sections, unit, |range| {
+ inlined_addresses.push(InlinedFunctionAddress {
+ range,
+ call_depth: inlined_depth,
+ function: function_index,
+ });
+ })?;
+
+ Function::parse_children(
+ entries,
+ depth,
+ unit,
+ dwarf,
+ inlined_functions,
+ inlined_addresses,
+ inlined_depth + 1,
+ )
+ }
+}
+
+fn name_attr<R>(
+ attr: gimli::AttributeValue<R>,
+ unit: &gimli::Unit<R>,
+ dwarf: &ResDwarf<R>,
+ recursion_limit: usize,
+) -> Result<Option<R>, Error>
+where
+ R: gimli::Reader,
+{
+ if recursion_limit == 0 {
+ return Ok(None);
+ }
+
+ match attr {
+ gimli::AttributeValue::UnitRef(offset) => name_entry(unit, offset, dwarf, recursion_limit),
+ gimli::AttributeValue::DebugInfoRef(dr) => {
+ let res_unit = dwarf.find_unit(dr)?;
+ name_entry(
+ &res_unit.dw_unit,
+ gimli::UnitOffset(dr.0 - res_unit.offset.0),
+ dwarf,
+ recursion_limit,
+ )
+ }
+ gimli::AttributeValue::DebugInfoRefSup(dr) => {
+ if let Some(sup_dwarf) = dwarf.sup.as_ref() {
+ let res_unit = sup_dwarf.find_unit(dr)?;
+ name_entry(
+ &res_unit.dw_unit,
+ gimli::UnitOffset(dr.0 - res_unit.offset.0),
+ sup_dwarf,
+ recursion_limit,
+ )
+ } else {
+ Ok(None)
+ }
+ }
+ _ => Ok(None),
+ }
+}
+
+fn name_entry<R>(
+ unit: &gimli::Unit<R>,
+ offset: gimli::UnitOffset<R::Offset>,
+ dwarf: &ResDwarf<R>,
+ recursion_limit: usize,
+) -> Result<Option<R>, Error>
+where
+ R: gimli::Reader,
+{
+ let mut entries = unit.entries_raw(Some(offset))?;
+ let abbrev = if let Some(abbrev) = entries.read_abbreviation()? {
+ abbrev
+ } else {
+ return Err(gimli::Error::NoEntryAtGivenOffset);
+ };
+
+ let mut name = None;
+ let mut next = None;
+ for spec in abbrev.attributes() {
+ match entries.read_attribute(*spec) {
+ Ok(ref attr) => match attr.name() {
+ gimli::DW_AT_linkage_name | gimli::DW_AT_MIPS_linkage_name => {
+ if let Ok(val) = dwarf.sections.attr_string(unit, attr.value()) {
+ return Ok(Some(val));
+ }
+ }
+ gimli::DW_AT_name => {
+ if let Ok(val) = dwarf.sections.attr_string(unit, attr.value()) {
+ name = Some(val);
+ }
+ }
+ gimli::DW_AT_abstract_origin | gimli::DW_AT_specification => {
+ next = Some(attr.value());
+ }
+ _ => {}
+ },
+ Err(e) => return Err(e),
+ }
+ }
+
+ if name.is_some() {
+ return Ok(name);
+ }
+
+ if let Some(next) = next {
+ return name_attr(next, unit, dwarf, recursion_limit - 1);
+ }
+
+ Ok(None)
+}
diff --git a/vendor/addr2line-0.17.0/src/lazy.rs b/vendor/addr2line-0.17.0/src/lazy.rs
new file mode 100644
index 000000000..280c76b46
--- /dev/null
+++ b/vendor/addr2line-0.17.0/src/lazy.rs
@@ -0,0 +1,29 @@
+use core::cell::UnsafeCell;
+
+pub struct LazyCell<T> {
+ contents: UnsafeCell<Option<T>>,
+}
+impl<T> LazyCell<T> {
+ pub fn new() -> LazyCell<T> {
+ LazyCell {
+ contents: UnsafeCell::new(None),
+ }
+ }
+
+ pub fn borrow_with(&self, closure: impl FnOnce() -> T) -> &T {
+ unsafe {
+ // First check if we're already initialized...
+ let ptr = self.contents.get();
+ if let Some(val) = &*ptr {
+ return val;
+ }
+ // Note that while we're executing `closure` our `borrow_with` may
+ // be called recursively. This means we need to check again after
+ // the closure has executed. For that we use the `get_or_insert`
+ // method which will only perform mutation if we aren't already
+ // `Some`.
+ let val = closure();
+ (*ptr).get_or_insert(val)
+ }
+ }
+}
diff --git a/vendor/addr2line-0.17.0/src/lib.rs b/vendor/addr2line-0.17.0/src/lib.rs
new file mode 100644
index 000000000..b46a98393
--- /dev/null
+++ b/vendor/addr2line-0.17.0/src/lib.rs
@@ -0,0 +1,1192 @@
+//! This crate provides a cross-platform library and binary for translating addresses into
+//! function names, file names and line numbers. Given an address in an executable or an
+//! offset in a section of a relocatable object, it uses the debugging information to
+//! figure out which file name and line number are associated with it.
+//!
+//! When used as a library, files must first be loaded using the
+//! [`object`](https://github.com/gimli-rs/object) crate.
+//! A context can then be created with [`Context::new`](./struct.Context.html#method.new).
+//! The context caches some of the parsed information so that multiple lookups are
+//! efficient.
+//! Location information is obtained with
+//! [`Context::find_location`](./struct.Context.html#method.find_location) or
+//! [`Context::find_location_range`](./struct.Context.html#method.find_location_range).
+//! Function information is obtained with
+//! [`Context::find_frames`](./struct.Context.html#method.find_frames), which returns
+//! a frame for each inline function. Each frame contains both name and location.
+//!
+//! The crate has an example CLI wrapper around the library which provides some of
+//! the functionality of the `addr2line` command line tool distributed with [GNU
+//! binutils](https://www.gnu.org/software/binutils/).
+//!
+//! Currently this library only provides information from the DWARF debugging information,
+//! which is parsed using [`gimli`](https://github.com/gimli-rs/gimli). The example CLI
+//! wrapper also uses symbol table information provided by the `object` crate.
+#![deny(missing_docs)]
+#![no_std]
+
+#[allow(unused_imports)]
+#[macro_use]
+extern crate alloc;
+
+#[cfg(feature = "cpp_demangle")]
+extern crate cpp_demangle;
+#[cfg(feature = "fallible-iterator")]
+pub extern crate fallible_iterator;
+pub extern crate gimli;
+#[cfg(feature = "object")]
+pub extern crate object;
+#[cfg(feature = "rustc-demangle")]
+extern crate rustc_demangle;
+
+use alloc::borrow::Cow;
+use alloc::boxed::Box;
+#[cfg(feature = "object")]
+use alloc::rc::Rc;
+use alloc::string::{String, ToString};
+use alloc::sync::Arc;
+use alloc::vec::Vec;
+
+use core::cmp::{self, Ordering};
+use core::iter;
+use core::mem;
+use core::num::NonZeroU64;
+use core::u64;
+
+use crate::function::{Function, Functions, InlinedFunction};
+use crate::lazy::LazyCell;
+
+#[cfg(feature = "smallvec")]
+mod maybe_small {
+ pub type Vec<T> = smallvec::SmallVec<[T; 16]>;
+ pub type IntoIter<T> = smallvec::IntoIter<[T; 16]>;
+}
+#[cfg(not(feature = "smallvec"))]
+mod maybe_small {
+ pub type Vec<T> = alloc::vec::Vec<T>;
+ pub type IntoIter<T> = alloc::vec::IntoIter<T>;
+}
+
+mod function;
+mod lazy;
+
+type Error = gimli::Error;
+
+/// The state necessary to perform address to line translation.
+///
+/// Constructing a `Context` is somewhat costly, so users should aim to reuse `Context`s
+/// when performing lookups for many addresses in the same executable.
+pub struct Context<R: gimli::Reader> {
+ dwarf: ResDwarf<R>,
+}
+
+/// The type of `Context` that supports the `new` method.
+#[cfg(feature = "std-object")]
+pub type ObjectContext = Context<gimli::EndianRcSlice<gimli::RunTimeEndian>>;
+
+#[cfg(feature = "std-object")]
+impl Context<gimli::EndianRcSlice<gimli::RunTimeEndian>> {
+ /// Construct a new `Context`.
+ ///
+ /// The resulting `Context` uses `gimli::EndianRcSlice<gimli::RunTimeEndian>`.
+ /// This means it is not thread safe, has no lifetime constraints (since it copies
+ /// the input data), and works for any endianity.
+ ///
+ /// Performance sensitive applications may want to use `Context::from_dwarf`
+ /// with a more specialised `gimli::Reader` implementation.
+ #[inline]
+ pub fn new<'data: 'file, 'file, O: object::Object<'data, 'file>>(
+ file: &'file O,
+ ) -> Result<Self, Error> {
+ Self::new_with_sup(file, None)
+ }
+
+ /// Construct a new `Context`.
+ ///
+ /// Optionally also use a supplementary object file.
+ ///
+ /// The resulting `Context` uses `gimli::EndianRcSlice<gimli::RunTimeEndian>`.
+ /// This means it is not thread safe, has no lifetime constraints (since it copies
+ /// the input data), and works for any endianity.
+ ///
+ /// Performance sensitive applications may want to use `Context::from_dwarf_with_sup`
+ /// with a more specialised `gimli::Reader` implementation.
+ pub fn new_with_sup<'data: 'file, 'file, O: object::Object<'data, 'file>>(
+ file: &'file O,
+ sup_file: Option<&'file O>,
+ ) -> Result<Self, Error> {
+ let endian = if file.is_little_endian() {
+ gimli::RunTimeEndian::Little
+ } else {
+ gimli::RunTimeEndian::Big
+ };
+
+ fn load_section<'data: 'file, 'file, O, Endian>(
+ id: gimli::SectionId,
+ file: &'file O,
+ endian: Endian,
+ ) -> Result<gimli::EndianRcSlice<Endian>, Error>
+ where
+ O: object::Object<'data, 'file>,
+ Endian: gimli::Endianity,
+ {
+ use object::ObjectSection;
+
+ let data = file
+ .section_by_name(id.name())
+ .and_then(|section| section.uncompressed_data().ok())
+ .unwrap_or(Cow::Borrowed(&[]));
+ Ok(gimli::EndianRcSlice::new(Rc::from(&*data), endian))
+ }
+
+ let mut dwarf = gimli::Dwarf::load(|id| load_section(id, file, endian))?;
+ if let Some(sup_file) = sup_file {
+ dwarf.load_sup(|id| load_section(id, sup_file, endian))?;
+ }
+ Context::from_dwarf(dwarf)
+ }
+}
+
+impl<R: gimli::Reader> Context<R> {
+ /// Construct a new `Context` from DWARF sections.
+ ///
+ /// This method does not support using a supplementary object file.
+ pub fn from_sections(
+ debug_abbrev: gimli::DebugAbbrev<R>,
+ debug_addr: gimli::DebugAddr<R>,
+ debug_aranges: gimli::DebugAranges<R>,
+ debug_info: gimli::DebugInfo<R>,
+ debug_line: gimli::DebugLine<R>,
+ debug_line_str: gimli::DebugLineStr<R>,
+ debug_ranges: gimli::DebugRanges<R>,
+ debug_rnglists: gimli::DebugRngLists<R>,
+ debug_str: gimli::DebugStr<R>,
+ debug_str_offsets: gimli::DebugStrOffsets<R>,
+ default_section: R,
+ ) -> Result<Self, Error> {
+ Self::from_dwarf(gimli::Dwarf {
+ debug_abbrev,
+ debug_addr,
+ debug_aranges,
+ debug_info,
+ debug_line,
+ debug_line_str,
+ debug_str,
+ debug_str_offsets,
+ debug_types: default_section.clone().into(),
+ locations: gimli::LocationLists::new(
+ default_section.clone().into(),
+ default_section.clone().into(),
+ ),
+ ranges: gimli::RangeLists::new(debug_ranges, debug_rnglists),
+ file_type: gimli::DwarfFileType::Main,
+ sup: None,
+ })
+ }
+
+ /// Construct a new `Context` from an existing [`gimli::Dwarf`] object.
+ #[inline]
+ pub fn from_dwarf(sections: gimli::Dwarf<R>) -> Result<Self, Error> {
+ let mut dwarf = ResDwarf::parse(Arc::new(sections))?;
+ dwarf.sup = match dwarf.sections.sup.clone() {
+ Some(sup_sections) => Some(Box::new(ResDwarf::parse(sup_sections)?)),
+ None => None,
+ };
+ Ok(Context { dwarf })
+ }
+
+ /// The dwarf sections associated with this `Context`.
+ pub fn dwarf(&self) -> &gimli::Dwarf<R> {
+ &self.dwarf.sections
+ }
+
+ /// Finds the CUs for the function address given.
+ ///
+ /// There might be multiple CUs whose range contains this address.
+ /// Weak symbols have shown up in the wild which cause this to happen
+ /// but otherwise this can happen if the CU has non-contiguous functions
+ /// but only reports a single range.
+ ///
+ /// Consequently we return an iterator for all CUs which may contain the
+ /// address, and the caller must check if there is actually a function or
+ /// location in the CU for that address.
+ fn find_units(&self, probe: u64) -> impl Iterator<Item = &ResUnit<R>> {
+ self.find_units_range(probe, probe + 1)
+ .map(|(unit, _range)| unit)
+ }
+
+ /// Finds the CUs covering the range of addresses given.
+ ///
+ /// The range is [low, high) (ie, the upper bound is exclusive). This can return multiple
+ /// ranges for the same unit.
+ #[inline]
+ fn find_units_range(
+ &self,
+ probe_low: u64,
+ probe_high: u64,
+ ) -> impl Iterator<Item = (&ResUnit<R>, &gimli::Range)> {
+ // First up find the position in the array which could have our function
+ // address.
+ let pos = match self
+ .dwarf
+ .unit_ranges
+ .binary_search_by_key(&probe_high, |i| i.range.begin)
+ {
+ // Although unlikely, we could find an exact match.
+ Ok(i) => i + 1,
+ // No exact match was found, but this probe would fit at slot `i`.
+ // This means that slot `i` is bigger than `probe`, along with all
+ // indices greater than `i`, so we need to search all previous
+ // entries.
+ Err(i) => i,
+ };
+
+ // Once we have our index we iterate backwards from that position
+ // looking for a matching CU.
+ self.dwarf.unit_ranges[..pos]
+ .iter()
+ .rev()
+ .take_while(move |i| {
+ // We know that this CU's start is beneath the probe already because
+ // of our sorted array.
+ debug_assert!(i.range.begin <= probe_high);
+
+ // Each entry keeps track of the maximum end address seen so far,
+ // starting from the beginning of the array of unit ranges. We're
+ // iterating in reverse so if our probe is beyond the maximum range
+ // of this entry, then it's guaranteed to not fit in any prior
+ // entries, so we break out.
+ probe_low < i.max_end
+ })
+ .filter_map(move |i| {
+ // If this CU doesn't actually contain this address, move to the
+ // next CU.
+ if probe_low >= i.range.end || probe_high <= i.range.begin {
+ return None;
+ }
+ Some((&self.dwarf.units[i.unit_id], &i.range))
+ })
+ }
+
+ /// Find the DWARF unit corresponding to the given virtual memory address.
+ pub fn find_dwarf_unit(&self, probe: u64) -> Option<&gimli::Unit<R>> {
+ for unit in self.find_units(probe) {
+ match unit.find_function_or_location(probe, &self.dwarf) {
+ Ok((Some(_), _)) | Ok((_, Some(_))) => return Some(&unit.dw_unit),
+ _ => {}
+ }
+ }
+ None
+ }
+
+ /// Find the source file and line corresponding to the given virtual memory address.
+ pub fn find_location(&self, probe: u64) -> Result<Option<Location<'_>>, Error> {
+ for unit in self.find_units(probe) {
+ if let Some(location) = unit.find_location(probe, &self.dwarf.sections)? {
+ return Ok(Some(location));
+ }
+ }
+ Ok(None)
+ }
+
+ /// Return source file and lines for a range of addresses. For each location it also
+ /// returns the address and size of the range of the underlying instructions.
+ pub fn find_location_range(
+ &self,
+ probe_low: u64,
+ probe_high: u64,
+ ) -> Result<LocationRangeIter<'_, R>, Error> {
+ LocationRangeIter::new(self, probe_low, probe_high)
+ }
+
+ /// Return an iterator for the function frames corresponding to the given virtual
+ /// memory address.
+ ///
+ /// If the probe address is not for an inline function then only one frame is
+ /// returned.
+ ///
+ /// If the probe address is for an inline function then the first frame corresponds
+ /// to the innermost inline function. Subsequent frames contain the caller and call
+ /// location, until an non-inline caller is reached.
+ pub fn find_frames(&self, probe: u64) -> Result<FrameIter<R>, Error> {
+ for unit in self.find_units(probe) {
+ match unit.find_function_or_location(probe, &self.dwarf)? {
+ (Some(function), location) => {
+ let inlined_functions = function.find_inlined_functions(probe);
+ return Ok(FrameIter(FrameIterState::Frames(FrameIterFrames {
+ unit,
+ sections: &self.dwarf.sections,
+ function,
+ inlined_functions,
+ next: location,
+ })));
+ }
+ (None, Some(location)) => {
+ return Ok(FrameIter(FrameIterState::Location(Some(location))));
+ }
+ _ => {}
+ }
+ }
+ Ok(FrameIter(FrameIterState::Empty))
+ }
+
+ /// Initialize all line data structures. This is used for benchmarks.
+ #[doc(hidden)]
+ pub fn parse_lines(&self) -> Result<(), Error> {
+ for unit in &self.dwarf.units {
+ unit.parse_lines(&self.dwarf.sections)?;
+ }
+ Ok(())
+ }
+
+ /// Initialize all function data structures. This is used for benchmarks.
+ #[doc(hidden)]
+ pub fn parse_functions(&self) -> Result<(), Error> {
+ for unit in &self.dwarf.units {
+ unit.parse_functions(&self.dwarf)?;
+ }
+ Ok(())
+ }
+
+ /// Initialize all inlined function data structures. This is used for benchmarks.
+ #[doc(hidden)]
+ pub fn parse_inlined_functions(&self) -> Result<(), Error> {
+ for unit in &self.dwarf.units {
+ unit.parse_inlined_functions(&self.dwarf)?;
+ }
+ Ok(())
+ }
+}
+
+struct UnitRange {
+ unit_id: usize,
+ max_end: u64,
+ range: gimli::Range,
+}
+
+struct ResDwarf<R: gimli::Reader> {
+ unit_ranges: Vec<UnitRange>,
+ units: Vec<ResUnit<R>>,
+ sections: Arc<gimli::Dwarf<R>>,
+ sup: Option<Box<ResDwarf<R>>>,
+}
+
+impl<R: gimli::Reader> ResDwarf<R> {
+ fn parse(sections: Arc<gimli::Dwarf<R>>) -> Result<Self, Error> {
+ // Find all the references to compilation units in .debug_aranges.
+ // Note that we always also iterate through all of .debug_info to
+ // find compilation units, because .debug_aranges may be missing some.
+ let mut aranges = Vec::new();
+ let mut headers = sections.debug_aranges.headers();
+ while let Some(header) = headers.next()? {
+ aranges.push((header.debug_info_offset(), header.offset()));
+ }
+ aranges.sort_by_key(|i| i.0);
+
+ let mut unit_ranges = Vec::new();
+ let mut res_units = Vec::new();
+ let mut units = sections.units();
+ while let Some(header) = units.next()? {
+ let unit_id = res_units.len();
+ let offset = match header.offset().as_debug_info_offset() {
+ Some(offset) => offset,
+ None => continue,
+ };
+ // We mainly want compile units, but we may need to follow references to entries
+ // within other units for function names. We don't need anything from type units.
+ match header.type_() {
+ gimli::UnitType::Type { .. } | gimli::UnitType::SplitType { .. } => continue,
+ _ => {}
+ }
+ let dw_unit = match sections.unit(header) {
+ Ok(dw_unit) => dw_unit,
+ Err(_) => continue,
+ };
+
+ let mut lang = None;
+ {
+ let mut entries = dw_unit.entries_raw(None)?;
+
+ let abbrev = match entries.read_abbreviation()? {
+ Some(abbrev) => abbrev,
+ None => continue,
+ };
+
+ let mut ranges = RangeAttributes::default();
+ for spec in abbrev.attributes() {
+ let attr = entries.read_attribute(*spec)?;
+ match attr.name() {
+ gimli::DW_AT_low_pc => {
+ if let gimli::AttributeValue::Addr(val) = attr.value() {
+ ranges.low_pc = Some(val);
+ }
+ }
+ gimli::DW_AT_high_pc => match attr.value() {
+ gimli::AttributeValue::Addr(val) => ranges.high_pc = Some(val),
+ gimli::AttributeValue::Udata(val) => ranges.size = Some(val),
+ _ => {}
+ },
+ gimli::DW_AT_ranges => {
+ ranges.ranges_offset =
+ sections.attr_ranges_offset(&dw_unit, attr.value())?;
+ }
+ gimli::DW_AT_language => {
+ if let gimli::AttributeValue::Language(val) = attr.value() {
+ lang = Some(val);
+ }
+ }
+ _ => {}
+ }
+ }
+
+ // Find the address ranges for the CU, using in order of preference:
+ // - DW_AT_ranges
+ // - .debug_aranges
+ // - DW_AT_low_pc/DW_AT_high_pc
+ //
+ // Using DW_AT_ranges before .debug_aranges is possibly an arbitrary choice,
+ // but the feeling is that DW_AT_ranges is more likely to be reliable or complete
+ // if it is present.
+ //
+ // .debug_aranges must be used before DW_AT_low_pc/DW_AT_high_pc because
+ // it has been observed on macOS that DW_AT_ranges was not emitted even for
+ // discontiguous CUs.
+ let i = match ranges.ranges_offset {
+ Some(_) => None,
+ None => aranges.binary_search_by_key(&offset, |x| x.0).ok(),
+ };
+ if let Some(mut i) = i {
+ // There should be only one set per CU, but in practice multiple
+ // sets have been observed. This is probably a compiler bug, but
+ // either way we need to handle it.
+ while i > 0 && aranges[i - 1].0 == offset {
+ i -= 1;
+ }
+ for (_, aranges_offset) in aranges[i..].iter().take_while(|x| x.0 == offset) {
+ let aranges_header = sections.debug_aranges.header(*aranges_offset)?;
+ let mut aranges = aranges_header.entries();
+ while let Some(arange) = aranges.next()? {
+ if arange.length() != 0 {
+ unit_ranges.push(UnitRange {
+ range: arange.range(),
+ unit_id,
+ max_end: 0,
+ });
+ }
+ }
+ }
+ } else {
+ ranges.for_each_range(&sections, &dw_unit, |range| {
+ unit_ranges.push(UnitRange {
+ range,
+ unit_id,
+ max_end: 0,
+ });
+ })?;
+ }
+ }
+
+ res_units.push(ResUnit {
+ offset,
+ dw_unit,
+ lang,
+ lines: LazyCell::new(),
+ funcs: LazyCell::new(),
+ });
+ }
+
+ // Sort this for faster lookup in `find_unit_and_address` below.
+ unit_ranges.sort_by_key(|i| i.range.begin);
+
+ // Calculate the `max_end` field now that we've determined the order of
+ // CUs.
+ let mut max = 0;
+ for i in unit_ranges.iter_mut() {
+ max = max.max(i.range.end);
+ i.max_end = max;
+ }
+
+ Ok(ResDwarf {
+ units: res_units,
+ unit_ranges,
+ sections,
+ sup: None,
+ })
+ }
+
+ fn find_unit(&self, offset: gimli::DebugInfoOffset<R::Offset>) -> Result<&ResUnit<R>, Error> {
+ match self
+ .units
+ .binary_search_by_key(&offset.0, |unit| unit.offset.0)
+ {
+ // There is never a DIE at the unit offset or before the first unit.
+ Ok(_) | Err(0) => Err(gimli::Error::NoEntryAtGivenOffset),
+ Err(i) => Ok(&self.units[i - 1]),
+ }
+ }
+}
+
+struct Lines {
+ files: Box<[String]>,
+ sequences: Box<[LineSequence]>,
+}
+
+struct LineSequence {
+ start: u64,
+ end: u64,
+ rows: Box<[LineRow]>,
+}
+
+struct LineRow {
+ address: u64,
+ file_index: u64,
+ line: u32,
+ column: u32,
+}
+
+struct ResUnit<R: gimli::Reader> {
+ offset: gimli::DebugInfoOffset<R::Offset>,
+ dw_unit: gimli::Unit<R>,
+ lang: Option<gimli::DwLang>,
+ lines: LazyCell<Result<Lines, Error>>,
+ funcs: LazyCell<Result<Functions<R>, Error>>,
+}
+
+impl<R: gimli::Reader> ResUnit<R> {
+ fn parse_lines(&self, sections: &gimli::Dwarf<R>) -> Result<Option<&Lines>, Error> {
+ let ilnp = match self.dw_unit.line_program {
+ Some(ref ilnp) => ilnp,
+ None => return Ok(None),
+ };
+ self.lines
+ .borrow_with(|| {
+ let mut sequences = Vec::new();
+ let mut sequence_rows = Vec::<LineRow>::new();
+ let mut rows = ilnp.clone().rows();
+ while let Some((_, row)) = rows.next_row()? {
+ if row.end_sequence() {
+ if let Some(start) = sequence_rows.first().map(|x| x.address) {
+ let end = row.address();
+ let mut rows = Vec::new();
+ mem::swap(&mut rows, &mut sequence_rows);
+ sequences.push(LineSequence {
+ start,
+ end,
+ rows: rows.into_boxed_slice(),
+ });
+ }
+ continue;
+ }
+
+ let address = row.address();
+ let file_index = row.file_index();
+ let line = row.line().map(NonZeroU64::get).unwrap_or(0) as u32;
+ let column = match row.column() {
+ gimli::ColumnType::LeftEdge => 0,
+ gimli::ColumnType::Column(x) => x.get() as u32,
+ };
+
+ if let Some(last_row) = sequence_rows.last_mut() {
+ if last_row.address == address {
+ last_row.file_index = file_index;
+ last_row.line = line;
+ last_row.column = column;
+ continue;
+ }
+ }
+
+ sequence_rows.push(LineRow {
+ address,
+ file_index,
+ line,
+ column,
+ });
+ }
+ sequences.sort_by_key(|x| x.start);
+
+ let mut files = Vec::new();
+ let header = ilnp.header();
+ match header.file(0) {
+ Some(file) => files.push(self.render_file(file, header, sections)?),
+ None => files.push(String::from("")), // DWARF version <= 4 may not have 0th index
+ }
+ let mut index = 1;
+ while let Some(file) = header.file(index) {
+ files.push(self.render_file(file, header, sections)?);
+ index += 1;
+ }
+
+ Ok(Lines {
+ files: files.into_boxed_slice(),
+ sequences: sequences.into_boxed_slice(),
+ })
+ })
+ .as_ref()
+ .map(Some)
+ .map_err(Error::clone)
+ }
+
+ fn parse_functions(&self, dwarf: &ResDwarf<R>) -> Result<&Functions<R>, Error> {
+ self.funcs
+ .borrow_with(|| Functions::parse(&self.dw_unit, dwarf))
+ .as_ref()
+ .map_err(Error::clone)
+ }
+
+ fn parse_inlined_functions(&self, dwarf: &ResDwarf<R>) -> Result<(), Error> {
+ self.funcs
+ .borrow_with(|| Functions::parse(&self.dw_unit, dwarf))
+ .as_ref()
+ .map_err(Error::clone)?
+ .parse_inlined_functions(&self.dw_unit, dwarf)
+ }
+
+ fn find_location(
+ &self,
+ probe: u64,
+ sections: &gimli::Dwarf<R>,
+ ) -> Result<Option<Location<'_>>, Error> {
+ if let Some(mut iter) = LocationRangeUnitIter::new(self, sections, probe, probe + 1)? {
+ match iter.next() {
+ None => Ok(None),
+ Some((_addr, _len, loc)) => Ok(Some(loc)),
+ }
+ } else {
+ Ok(None)
+ }
+ }
+
+ #[inline]
+ fn find_location_range(
+ &self,
+ probe_low: u64,
+ probe_high: u64,
+ sections: &gimli::Dwarf<R>,
+ ) -> Result<Option<LocationRangeUnitIter<'_>>, Error> {
+ LocationRangeUnitIter::new(self, sections, probe_low, probe_high)
+ }
+
+ fn find_function_or_location(
+ &self,
+ probe: u64,
+ dwarf: &ResDwarf<R>,
+ ) -> Result<(Option<&Function<R>>, Option<Location<'_>>), Error> {
+ let functions = self.parse_functions(dwarf)?;
+ let function = match functions.find_address(probe) {
+ Some(address) => {
+ let function_index = functions.addresses[address].function;
+ let (offset, ref function) = functions.functions[function_index];
+ Some(
+ function
+ .borrow_with(|| Function::parse(offset, &self.dw_unit, dwarf))
+ .as_ref()
+ .map_err(Error::clone)?,
+ )
+ }
+ None => None,
+ };
+ let location = self.find_location(probe, &dwarf.sections)?;
+ Ok((function, location))
+ }
+
+ fn render_file(
+ &self,
+ file: &gimli::FileEntry<R, R::Offset>,
+ header: &gimli::LineProgramHeader<R, R::Offset>,
+ sections: &gimli::Dwarf<R>,
+ ) -> Result<String, gimli::Error> {
+ let mut path = if let Some(ref comp_dir) = self.dw_unit.comp_dir {
+ comp_dir.to_string_lossy()?.into_owned()
+ } else {
+ String::new()
+ };
+
+ if let Some(directory) = file.directory(header) {
+ path_push(
+ &mut path,
+ sections
+ .attr_string(&self.dw_unit, directory)?
+ .to_string_lossy()?
+ .as_ref(),
+ );
+ }
+
+ path_push(
+ &mut path,
+ sections
+ .attr_string(&self.dw_unit, file.path_name())?
+ .to_string_lossy()?
+ .as_ref(),
+ );
+
+ Ok(path)
+ }
+}
+
+/// Iterator over `Location`s in a range of addresses, returned by `Context::find_location_range`.
+pub struct LocationRangeIter<'ctx, R: gimli::Reader> {
+ unit_iter: Box<dyn Iterator<Item = (&'ctx ResUnit<R>, &'ctx gimli::Range)> + 'ctx>,
+ iter: Option<LocationRangeUnitIter<'ctx>>,
+
+ probe_low: u64,
+ probe_high: u64,
+ sections: &'ctx gimli::Dwarf<R>,
+}
+
+impl<'ctx, R: gimli::Reader> LocationRangeIter<'ctx, R> {
+ #[inline]
+ fn new(ctx: &'ctx Context<R>, probe_low: u64, probe_high: u64) -> Result<Self, Error> {
+ let sections = &ctx.dwarf.sections;
+ let unit_iter = ctx.find_units_range(probe_low, probe_high);
+ Ok(Self {
+ unit_iter: Box::new(unit_iter),
+ iter: None,
+ probe_low,
+ probe_high,
+ sections,
+ })
+ }
+
+ fn next_loc(&mut self) -> Result<Option<(u64, u64, Location<'ctx>)>, Error> {
+ loop {
+ let iter = self.iter.take();
+ match iter {
+ None => match self.unit_iter.next() {
+ Some((unit, range)) => {
+ self.iter = unit.find_location_range(
+ cmp::max(self.probe_low, range.begin),
+ cmp::min(self.probe_high, range.end),
+ self.sections,
+ )?;
+ }
+ None => return Ok(None),
+ },
+ Some(mut iter) => {
+ if let item @ Some(_) = iter.next() {
+ self.iter = Some(iter);
+ return Ok(item);
+ }
+ }
+ }
+ }
+ }
+}
+
+impl<'ctx, R> Iterator for LocationRangeIter<'ctx, R>
+where
+ R: gimli::Reader + 'ctx,
+{
+ type Item = (u64, u64, Location<'ctx>);
+
+ #[inline]
+ fn next(&mut self) -> Option<Self::Item> {
+ match self.next_loc() {
+ Err(_) => None,
+ Ok(loc) => loc,
+ }
+ }
+}
+
+#[cfg(feature = "fallible-iterator")]
+impl<'ctx, R> fallible_iterator::FallibleIterator for LocationRangeIter<'ctx, R>
+where
+ R: gimli::Reader + 'ctx,
+{
+ type Item = (u64, u64, Location<'ctx>);
+ type Error = Error;
+
+ #[inline]
+ fn next(&mut self) -> Result<Option<Self::Item>, Self::Error> {
+ self.next_loc()
+ }
+}
+
+struct LocationRangeUnitIter<'ctx> {
+ lines: &'ctx Lines,
+ seqs: &'ctx [LineSequence],
+ seq_idx: usize,
+ row_idx: usize,
+ probe_high: u64,
+}
+
+impl<'ctx> LocationRangeUnitIter<'ctx> {
+ fn new<R: gimli::Reader>(
+ resunit: &'ctx ResUnit<R>,
+ sections: &gimli::Dwarf<R>,
+ probe_low: u64,
+ probe_high: u64,
+ ) -> Result<Option<Self>, Error> {
+ let lines = resunit.parse_lines(sections)?;
+
+ if let Some(lines) = lines {
+ // Find index for probe_low.
+ let seq_idx = lines.sequences.binary_search_by(|sequence| {
+ if probe_low < sequence.start {
+ Ordering::Greater
+ } else if probe_low >= sequence.end {
+ Ordering::Less
+ } else {
+ Ordering::Equal
+ }
+ });
+ let seq_idx = match seq_idx {
+ Ok(x) => x,
+ Err(0) => 0, // probe below sequence, but range could overlap
+ Err(_) => lines.sequences.len(),
+ };
+
+ let row_idx = if let Some(seq) = lines.sequences.get(seq_idx) {
+ let idx = seq.rows.binary_search_by(|row| row.address.cmp(&probe_low));
+ let idx = match idx {
+ Ok(x) => x,
+ Err(0) => 0, // probe below sequence, but range could overlap
+ Err(x) => x - 1,
+ };
+ idx
+ } else {
+ 0
+ };
+
+ Ok(Some(Self {
+ lines,
+ seqs: &*lines.sequences,
+ seq_idx,
+ row_idx,
+ probe_high,
+ }))
+ } else {
+ Ok(None)
+ }
+ }
+}
+
+impl<'ctx> Iterator for LocationRangeUnitIter<'ctx> {
+ type Item = (u64, u64, Location<'ctx>);
+
+ fn next(&mut self) -> Option<(u64, u64, Location<'ctx>)> {
+ loop {
+ let seq = match self.seqs.get(self.seq_idx) {
+ Some(seq) => seq,
+ None => break,
+ };
+
+ if seq.start >= self.probe_high {
+ break;
+ }
+
+ match seq.rows.get(self.row_idx) {
+ Some(row) => {
+ if row.address >= self.probe_high {
+ break;
+ }
+
+ let file = self
+ .lines
+ .files
+ .get(row.file_index as usize)
+ .map(String::as_str);
+ let nextaddr = seq
+ .rows
+ .get(self.row_idx + 1)
+ .map(|row| row.address)
+ .unwrap_or(seq.end);
+
+ let item = (
+ row.address,
+ nextaddr - row.address,
+ Location {
+ file,
+ line: if row.line != 0 { Some(row.line) } else { None },
+ column: if row.column != 0 {
+ Some(row.column)
+ } else {
+ None
+ },
+ },
+ );
+ self.row_idx += 1;
+
+ return Some(item);
+ }
+ None => {
+ self.seq_idx += 1;
+ self.row_idx = 0;
+ }
+ }
+ }
+ None
+ }
+}
+
+fn path_push(path: &mut String, p: &str) {
+ if has_unix_root(p) || has_windows_root(p) {
+ *path = p.to_string();
+ } else {
+ let dir_separator = if has_windows_root(path.as_str()) {
+ '\\'
+ } else {
+ '/'
+ };
+
+ if !path.ends_with(dir_separator) {
+ path.push(dir_separator);
+ }
+ *path += p;
+ }
+}
+
+/// Check if the path in the given string has a unix style root
+fn has_unix_root(p: &str) -> bool {
+ p.starts_with('/')
+}
+
+/// Check if the path in the given string has a windows style root
+fn has_windows_root(p: &str) -> bool {
+ p.starts_with('\\') || p.get(1..3) == Some(":\\")
+}
+struct RangeAttributes<R: gimli::Reader> {
+ low_pc: Option<u64>,
+ high_pc: Option<u64>,
+ size: Option<u64>,
+ ranges_offset: Option<gimli::RangeListsOffset<<R as gimli::Reader>::Offset>>,
+}
+
+impl<R: gimli::Reader> Default for RangeAttributes<R> {
+ fn default() -> Self {
+ RangeAttributes {
+ low_pc: None,
+ high_pc: None,
+ size: None,
+ ranges_offset: None,
+ }
+ }
+}
+
+impl<R: gimli::Reader> RangeAttributes<R> {
+ fn for_each_range<F: FnMut(gimli::Range)>(
+ &self,
+ sections: &gimli::Dwarf<R>,
+ unit: &gimli::Unit<R>,
+ mut f: F,
+ ) -> Result<bool, Error> {
+ let mut added_any = false;
+ let mut add_range = |range: gimli::Range| {
+ if range.begin < range.end {
+ f(range);
+ added_any = true
+ }
+ };
+ if let Some(ranges_offset) = self.ranges_offset {
+ let mut range_list = sections.ranges(unit, ranges_offset)?;
+ while let Some(range) = range_list.next()? {
+ add_range(range);
+ }
+ } else if let (Some(begin), Some(end)) = (self.low_pc, self.high_pc) {
+ add_range(gimli::Range { begin, end });
+ } else if let (Some(begin), Some(size)) = (self.low_pc, self.size) {
+ add_range(gimli::Range {
+ begin,
+ end: begin + size,
+ });
+ }
+ Ok(added_any)
+ }
+}
+
+/// An iterator over function frames.
+pub struct FrameIter<'ctx, R>(FrameIterState<'ctx, R>)
+where
+ R: gimli::Reader + 'ctx;
+
+enum FrameIterState<'ctx, R>
+where
+ R: gimli::Reader + 'ctx,
+{
+ Empty,
+ Location(Option<Location<'ctx>>),
+ Frames(FrameIterFrames<'ctx, R>),
+}
+
+struct FrameIterFrames<'ctx, R>
+where
+ R: gimli::Reader + 'ctx,
+{
+ unit: &'ctx ResUnit<R>,
+ sections: &'ctx gimli::Dwarf<R>,
+ function: &'ctx Function<R>,
+ inlined_functions: iter::Rev<maybe_small::IntoIter<&'ctx InlinedFunction<R>>>,
+ next: Option<Location<'ctx>>,
+}
+
+impl<'ctx, R> FrameIter<'ctx, R>
+where
+ R: gimli::Reader + 'ctx,
+{
+ /// Advances the iterator and returns the next frame.
+ pub fn next(&mut self) -> Result<Option<Frame<'ctx, R>>, Error> {
+ let frames = match &mut self.0 {
+ FrameIterState::Empty => return Ok(None),
+ FrameIterState::Location(location) => {
+ // We can't move out of a mutable reference, so use `take` instead.
+ let location = location.take();
+ self.0 = FrameIterState::Empty;
+ return Ok(Some(Frame {
+ dw_die_offset: None,
+ function: None,
+ location,
+ }));
+ }
+ FrameIterState::Frames(frames) => frames,
+ };
+
+ let loc = frames.next.take();
+ let func = match frames.inlined_functions.next() {
+ Some(func) => func,
+ None => {
+ let frame = Frame {
+ dw_die_offset: Some(frames.function.dw_die_offset),
+ function: frames.function.name.clone().map(|name| FunctionName {
+ name,
+ language: frames.unit.lang,
+ }),
+ location: loc,
+ };
+ self.0 = FrameIterState::Empty;
+ return Ok(Some(frame));
+ }
+ };
+
+ let mut next = Location {
+ file: None,
+ line: if func.call_line != 0 {
+ Some(func.call_line)
+ } else {
+ None
+ },
+ column: if func.call_column != 0 {
+ Some(func.call_column)
+ } else {
+ None
+ },
+ };
+ if func.call_file != 0 {
+ if let Some(lines) = frames.unit.parse_lines(frames.sections)? {
+ next.file = lines.files.get(func.call_file as usize).map(String::as_str);
+ }
+ }
+ frames.next = Some(next);
+
+ Ok(Some(Frame {
+ dw_die_offset: Some(func.dw_die_offset),
+ function: func.name.clone().map(|name| FunctionName {
+ name,
+ language: frames.unit.lang,
+ }),
+ location: loc,
+ }))
+ }
+}
+
+#[cfg(feature = "fallible-iterator")]
+impl<'ctx, R> fallible_iterator::FallibleIterator for FrameIter<'ctx, R>
+where
+ R: gimli::Reader + 'ctx,
+{
+ type Item = Frame<'ctx, R>;
+ type Error = Error;
+
+ #[inline]
+ fn next(&mut self) -> Result<Option<Frame<'ctx, R>>, Error> {
+ self.next()
+ }
+}
+
+/// A function frame.
+pub struct Frame<'ctx, R: gimli::Reader> {
+ /// The DWARF unit offset corresponding to the DIE of the function.
+ pub dw_die_offset: Option<gimli::UnitOffset<R::Offset>>,
+ /// The name of the function.
+ pub function: Option<FunctionName<R>>,
+ /// The source location corresponding to this frame.
+ pub location: Option<Location<'ctx>>,
+}
+
+/// A function name.
+pub struct FunctionName<R: gimli::Reader> {
+ /// The name of the function.
+ pub name: R,
+ /// The language of the compilation unit containing this function.
+ pub language: Option<gimli::DwLang>,
+}
+
+impl<R: gimli::Reader> FunctionName<R> {
+ /// The raw name of this function before demangling.
+ pub fn raw_name(&self) -> Result<Cow<str>, Error> {
+ self.name.to_string_lossy()
+ }
+
+ /// The name of this function after demangling (if applicable).
+ pub fn demangle(&self) -> Result<Cow<str>, Error> {
+ self.raw_name().map(|x| demangle_auto(x, self.language))
+ }
+}
+
+/// Demangle a symbol name using the demangling scheme for the given language.
+///
+/// Returns `None` if demangling failed or is not required.
+#[allow(unused_variables)]
+pub fn demangle(name: &str, language: gimli::DwLang) -> Option<String> {
+ match language {
+ #[cfg(feature = "rustc-demangle")]
+ gimli::DW_LANG_Rust => rustc_demangle::try_demangle(name)
+ .ok()
+ .as_ref()
+ .map(|x| format!("{:#}", x)),
+ #[cfg(feature = "cpp_demangle")]
+ gimli::DW_LANG_C_plus_plus
+ | gimli::DW_LANG_C_plus_plus_03
+ | gimli::DW_LANG_C_plus_plus_11
+ | gimli::DW_LANG_C_plus_plus_14 => cpp_demangle::Symbol::new(name)
+ .ok()
+ .and_then(|x| x.demangle(&Default::default()).ok()),
+ _ => None,
+ }
+}
+
+/// Apply 'best effort' demangling of a symbol name.
+///
+/// If `language` is given, then only the demangling scheme for that language
+/// is used.
+///
+/// If `language` is `None`, then heuristics are used to determine how to
+/// demangle the name. Currently, these heuristics are very basic.
+///
+/// If demangling fails or is not required, then `name` is returned unchanged.
+pub fn demangle_auto(name: Cow<str>, language: Option<gimli::DwLang>) -> Cow<str> {
+ match language {
+ Some(language) => demangle(name.as_ref(), language),
+ None => demangle(name.as_ref(), gimli::DW_LANG_Rust)
+ .or_else(|| demangle(name.as_ref(), gimli::DW_LANG_C_plus_plus)),
+ }
+ .map(Cow::from)
+ .unwrap_or(name)
+}
+
+/// A source location.
+pub struct Location<'a> {
+ /// The file name.
+ pub file: Option<&'a str>,
+ /// The line number.
+ pub line: Option<u32>,
+ /// The column number.
+ pub column: Option<u32>,
+}
+
+#[cfg(test)]
+mod tests {
+ #[test]
+ fn context_is_send() {
+ fn assert_is_send<T: Send>() {}
+ assert_is_send::<crate::Context<gimli::read::EndianSlice<gimli::LittleEndian>>>();
+ }
+}
diff --git a/vendor/addr2line-0.17.0/tests/correctness.rs b/vendor/addr2line-0.17.0/tests/correctness.rs
new file mode 100644
index 000000000..3f7b43373
--- /dev/null
+++ b/vendor/addr2line-0.17.0/tests/correctness.rs
@@ -0,0 +1,91 @@
+extern crate addr2line;
+extern crate fallible_iterator;
+extern crate findshlibs;
+extern crate gimli;
+extern crate memmap;
+extern crate object;
+
+use addr2line::Context;
+use fallible_iterator::FallibleIterator;
+use findshlibs::{IterationControl, SharedLibrary, TargetSharedLibrary};
+use object::Object;
+use std::fs::File;
+
+fn find_debuginfo() -> memmap::Mmap {
+ let path = std::env::current_exe().unwrap();
+ let file = File::open(&path).unwrap();
+ let map = unsafe { memmap::Mmap::map(&file).unwrap() };
+ let file = &object::File::parse(&*map).unwrap();
+ if let Ok(uuid) = file.mach_uuid() {
+ for candidate in path.parent().unwrap().read_dir().unwrap() {
+ let path = candidate.unwrap().path();
+ if !path.to_str().unwrap().ends_with(".dSYM") {
+ continue;
+ }
+ for candidate in path.join("Contents/Resources/DWARF").read_dir().unwrap() {
+ let path = candidate.unwrap().path();
+ let file = File::open(&path).unwrap();
+ let map = unsafe { memmap::Mmap::map(&file).unwrap() };
+ let file = &object::File::parse(&*map).unwrap();
+ if file.mach_uuid().unwrap() == uuid {
+ return map;
+ }
+ }
+ }
+ }
+
+ return map;
+}
+
+#[test]
+fn correctness() {
+ let map = find_debuginfo();
+ let file = &object::File::parse(&*map).unwrap();
+ let ctx = Context::new(file).unwrap();
+
+ let mut bias = None;
+ TargetSharedLibrary::each(|lib| {
+ bias = Some(lib.virtual_memory_bias().0 as u64);
+ IterationControl::Break
+ });
+
+ let test = |sym: u64, expected_prefix: &str| {
+ let ip = sym.wrapping_sub(bias.unwrap());
+
+ let frames = ctx.find_frames(ip).unwrap();
+ let frame = frames.last().unwrap().unwrap();
+ let name = frame.function.as_ref().unwrap().demangle().unwrap();
+ // Old rust versions generate DWARF with wrong linkage name,
+ // so only check the start.
+ if !name.starts_with(expected_prefix) {
+ panic!("incorrect name '{}', expected {:?}", name, expected_prefix);
+ }
+ };
+
+ test(test_function as u64, "correctness::test_function");
+ test(
+ small::test_function as u64,
+ "correctness::small::test_function",
+ );
+ test(auxiliary::foo as u64, "auxiliary::foo");
+}
+
+mod small {
+ pub fn test_function() {
+ println!("y");
+ }
+}
+
+fn test_function() {
+ println!("x");
+}
+
+#[test]
+fn zero_function() {
+ let map = find_debuginfo();
+ let file = &object::File::parse(&*map).unwrap();
+ let ctx = Context::new(file).unwrap();
+ for probe in 0..10 {
+ assert!(ctx.find_frames(probe).unwrap().count().unwrap() < 10);
+ }
+}
diff --git a/vendor/addr2line-0.17.0/tests/output_equivalence.rs b/vendor/addr2line-0.17.0/tests/output_equivalence.rs
new file mode 100644
index 000000000..9dc366672
--- /dev/null
+++ b/vendor/addr2line-0.17.0/tests/output_equivalence.rs
@@ -0,0 +1,145 @@
+extern crate backtrace;
+extern crate findshlibs;
+extern crate rustc_test as test;
+
+use std::env;
+use std::ffi::OsStr;
+use std::path::Path;
+use std::process::Command;
+
+use backtrace::Backtrace;
+use findshlibs::{IterationControl, SharedLibrary, TargetSharedLibrary};
+use test::{ShouldPanic, TestDesc, TestDescAndFn, TestFn, TestName};
+
+fn make_trace() -> Vec<String> {
+ fn foo() -> Backtrace {
+ bar()
+ }
+ #[inline(never)]
+ fn bar() -> Backtrace {
+ baz()
+ }
+ #[inline(always)]
+ fn baz() -> Backtrace {
+ Backtrace::new_unresolved()
+ }
+
+ let mut base_addr = None;
+ TargetSharedLibrary::each(|lib| {
+ base_addr = Some(lib.virtual_memory_bias().0 as isize);
+ IterationControl::Break
+ });
+ let addrfix = -base_addr.unwrap();
+
+ let trace = foo();
+ trace
+ .frames()
+ .iter()
+ .take(5)
+ .map(|x| format!("{:p}", (x.ip() as *const u8).wrapping_offset(addrfix)))
+ .collect()
+}
+
+fn run_cmd<P: AsRef<OsStr>>(exe: P, me: &Path, flags: Option<&str>, trace: &str) -> String {
+ let mut cmd = Command::new(exe);
+ cmd.env("LC_ALL", "C"); // GNU addr2line is localized, we aren't
+ cmd.env("RUST_BACKTRACE", "1"); // if a child crashes, we want to know why
+
+ if let Some(flags) = flags {
+ cmd.arg(flags);
+ }
+ cmd.arg("--exe").arg(me).arg(trace);
+
+ let output = cmd.output().unwrap();
+
+ assert!(output.status.success());
+ String::from_utf8(output.stdout).unwrap()
+}
+
+fn run_test(flags: Option<&str>) {
+ let me = env::current_exe().unwrap();
+ let mut exe = me.clone();
+ assert!(exe.pop());
+ if exe.file_name().unwrap().to_str().unwrap() == "deps" {
+ assert!(exe.pop());
+ }
+ exe.push("examples");
+ exe.push("addr2line");
+
+ assert!(exe.is_file());
+
+ let trace = make_trace();
+
+ // HACK: GNU addr2line has a bug where looking up multiple addresses can cause the second
+ // lookup to fail. Workaround by doing one address at a time.
+ for addr in &trace {
+ let theirs = run_cmd("addr2line", &me, flags, addr);
+ let ours = run_cmd(&exe, &me, flags, addr);
+
+ // HACK: GNU addr2line does not tidy up paths properly, causing double slashes to be printed.
+ // We consider our behavior to be correct, so we fix their output to match ours.
+ let theirs = theirs.replace("//", "/");
+
+ assert!(
+ theirs == ours,
+ "Output not equivalent:
+
+$ addr2line {0} --exe {1} {2}
+{4}
+$ {3} {0} --exe {1} {2}
+{5}
+
+
+",
+ flags.unwrap_or(""),
+ me.display(),
+ trace.join(" "),
+ exe.display(),
+ theirs,
+ ours
+ );
+ }
+}
+
+static FLAGS: &'static str = "aipsf";
+
+fn make_tests() -> Vec<TestDescAndFn> {
+ (0..(1 << FLAGS.len()))
+ .map(|bits| {
+ if bits == 0 {
+ None
+ } else {
+ let mut param = String::new();
+ param.push('-');
+ for (i, flag) in FLAGS.chars().enumerate() {
+ if (bits & (1 << i)) != 0 {
+ param.push(flag);
+ }
+ }
+ Some(param)
+ }
+ })
+ .map(|param| TestDescAndFn {
+ desc: TestDesc {
+ name: TestName::DynTestName(format!(
+ "addr2line {}",
+ param.as_ref().map_or("", String::as_str)
+ )),
+ ignore: false,
+ should_panic: ShouldPanic::No,
+ allow_fail: false,
+ },
+ testfn: TestFn::DynTestFn(Box::new(move || {
+ run_test(param.as_ref().map(String::as_str))
+ })),
+ })
+ .collect()
+}
+
+fn main() {
+ if !cfg!(target_os = "linux") {
+ return;
+ }
+ let args: Vec<_> = env::args().collect();
+ test::test_main(&args, make_tests());
+}
diff --git a/vendor/addr2line-0.17.0/tests/parse.rs b/vendor/addr2line-0.17.0/tests/parse.rs
new file mode 100644
index 000000000..91d66e382
--- /dev/null
+++ b/vendor/addr2line-0.17.0/tests/parse.rs
@@ -0,0 +1,118 @@
+extern crate addr2line;
+extern crate memmap;
+extern crate object;
+
+use std::borrow::Cow;
+use std::env;
+use std::fs::File;
+use std::path::{self, PathBuf};
+
+use object::Object;
+
+fn release_fixture_path() -> PathBuf {
+ if let Ok(p) = env::var("ADDR2LINE_FIXTURE_PATH") {
+ return p.into();
+ }
+
+ let mut path = PathBuf::new();
+ if let Ok(dir) = env::var("CARGO_MANIFEST_DIR") {
+ path.push(dir);
+ }
+ path.push("fixtures");
+ path.push("addr2line-release");
+ path
+}
+
+fn with_file<F: FnOnce(&object::File)>(target: &path::Path, f: F) {
+ let file = File::open(target).unwrap();
+ let map = unsafe { memmap::Mmap::map(&file).unwrap() };
+ let file = object::File::parse(&*map).unwrap();
+ f(&file)
+}
+
+fn dwarf_load<'a>(object: &object::File<'a>) -> gimli::Dwarf<Cow<'a, [u8]>> {
+ let load_section = |id: gimli::SectionId| -> Result<Cow<'a, [u8]>, gimli::Error> {
+ use object::ObjectSection;
+
+ let data = object
+ .section_by_name(id.name())
+ .and_then(|section| section.data().ok())
+ .unwrap_or(&[][..]);
+ Ok(Cow::Borrowed(data))
+ };
+ gimli::Dwarf::load(&load_section).unwrap()
+}
+
+fn dwarf_borrow<'a>(
+ dwarf: &'a gimli::Dwarf<Cow<[u8]>>,
+) -> gimli::Dwarf<gimli::EndianSlice<'a, gimli::LittleEndian>> {
+ let borrow_section: &dyn for<'b> Fn(
+ &'b Cow<[u8]>,
+ ) -> gimli::EndianSlice<'b, gimli::LittleEndian> =
+ &|section| gimli::EndianSlice::new(&*section, gimli::LittleEndian);
+ dwarf.borrow(&borrow_section)
+}
+
+#[test]
+fn parse_base_rc() {
+ let target = release_fixture_path();
+
+ with_file(&target, |file| {
+ addr2line::ObjectContext::new(file).unwrap();
+ });
+}
+
+#[test]
+fn parse_base_slice() {
+ let target = release_fixture_path();
+
+ with_file(&target, |file| {
+ let dwarf = dwarf_load(file);
+ let dwarf = dwarf_borrow(&dwarf);
+ addr2line::Context::from_dwarf(dwarf).unwrap();
+ });
+}
+
+#[test]
+fn parse_lines_rc() {
+ let target = release_fixture_path();
+
+ with_file(&target, |file| {
+ let context = addr2line::ObjectContext::new(file).unwrap();
+ context.parse_lines().unwrap();
+ });
+}
+
+#[test]
+fn parse_lines_slice() {
+ let target = release_fixture_path();
+
+ with_file(&target, |file| {
+ let dwarf = dwarf_load(file);
+ let dwarf = dwarf_borrow(&dwarf);
+ let context = addr2line::Context::from_dwarf(dwarf).unwrap();
+ context.parse_lines().unwrap();
+ });
+}
+
+#[test]
+fn parse_functions_rc() {
+ let target = release_fixture_path();
+
+ with_file(&target, |file| {
+ let context = addr2line::ObjectContext::new(file).unwrap();
+ context.parse_functions().unwrap();
+ });
+}
+
+#[test]
+fn parse_functions_slice() {
+ let target = release_fixture_path();
+
+ with_file(&target, |file| {
+ let dwarf = dwarf_load(file);
+ let dwarf = dwarf_borrow(&dwarf);
+ let context = addr2line::Context::from_dwarf(dwarf).unwrap();
+ context.parse_functions().unwrap();
+ });
+}
diff --git a/vendor/addr2line/.cargo-checksum.json b/vendor/addr2line/.cargo-checksum.json
index b43ad3bbf..43f25b3ba 100644
--- a/vendor/addr2line/.cargo-checksum.json
+++ b/vendor/addr2line/.cargo-checksum.json
@@ -1 +1 @@
-{"files":{"CHANGELOG.md":"d4ef249a0a4eff26a34a1f847a3c367dfd9988b4da972ac9c16b1d258b62ad87","Cargo.lock":"290a48d58d1ebfef0f5eaec66191f6c1a41080b89e10e931c6984052008479ab","Cargo.toml":"68243a813e2e6ba40d3e939b9ade5489b3f39a58d7dc391ae447a60591315f4a","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"e99d88d232bf57d70f0fb87f6b496d44b6653f99f8a63d250a54c61ea4bcde40","README.md":"76d28502bd2e83f6a9e3576bd45e9a7fe5308448c4b5384b0d249515b5f67a5c","bench.plot.r":"6a5d7a4d36ed6b3d9919be703a479bef47698bf947818b483ff03951df2d4e01","benchmark.sh":"b35f89b1ca2c1dc0476cdd07f0284b72d41920d1c7b6054072f50ffba296d78d","coverage.sh":"4677e81922d08a82e83068a911717a247c66af12e559f37b78b6be3337ac9f07","examples/addr2line.rs":"75ef29e1d07d49d247990ad970892d64f629766bafa36afddff5a88976e58060","rustfmt.toml":"01ba4719c80b6fe911b091a7c05124b64eeece964e09c058ef8f9805daca546b","src/function.rs":"395f37cdf03201d416d66bc11abeea627be0abb4585104acd927224a26cb9369","src/lazy.rs":"14ec61761369c21d426673f549c21394221533f444b68cd2a8370952eb19f345","src/lib.rs":"5696c0aee67df576f78935c66bb124f4e5fa19cbc9b25faf8f750e7e8dda113c","tests/correctness.rs":"c9325ffdec577bf5e56f5dd72fdff4927153d0a4c34c0fda5aefaeb44a8d26fd","tests/output_equivalence.rs":"38d7b585b7a2ca43b07eef6b34c11f489d1deae138a010123c33188dfb881c11","tests/parse.rs":"9e421ea9d9348721f6c6533cdba1db5b84287fc685f870c7905dea06b596b4db"},"package":"b9ecd88a8c8378ca913a680cd98f0f13ac67383d35993f86c90a70e3f137816b"} \ No newline at end of file
+{"files":{"CHANGELOG.md":"59733fc6186af0929ca4b6508e10ea1777f757c333a355d8154498332aee259f","Cargo.lock":"0b30594b7d3f093b44ca9c53366bbcb3f28a97ed24da65e56fe9961e7250c3c2","Cargo.toml":"c68ebf21efe63bb706716dd7b4bb7d33734629f13db36014d6be49fed6c8d731","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"e99d88d232bf57d70f0fb87f6b496d44b6653f99f8a63d250a54c61ea4bcde40","README.md":"76d28502bd2e83f6a9e3576bd45e9a7fe5308448c4b5384b0d249515b5f67a5c","bench.plot.r":"6a5d7a4d36ed6b3d9919be703a479bef47698bf947818b483ff03951df2d4e01","benchmark.sh":"b35f89b1ca2c1dc0476cdd07f0284b72d41920d1c7b6054072f50ffba296d78d","coverage.sh":"4677e81922d08a82e83068a911717a247c66af12e559f37b78b6be3337ac9f07","examples/addr2line.rs":"624548450eda1c8491fe4de60f0a96d20ef9c0d70770de2d76d803850319c876","rustfmt.toml":"01ba4719c80b6fe911b091a7c05124b64eeece964e09c058ef8f9805daca546b","src/function.rs":"caa2458f48509a0e0e2c4920719383997e9ccab44efceeabcf3019587f438a57","src/lazy.rs":"21bc1a7d8593c11e93577f1f17163705dbbadf752a007fae4401a4150ec9e473","src/lib.rs":"41d575590b9a683349552d7c4c845ef9a2739e7a4a9e01d53d4e0f4a4947fc45","tests/correctness.rs":"0bd7f9bc9d333cca0649d7bb85e07ebc14855ec2f2b9082f4ec752ccea77e1d6","tests/output_equivalence.rs":"9b637de957f4760ed8bdbfac9e1bacf57f0123c54ed0fbfeb8c2c3b7077f3d81","tests/parse.rs":"f0b2437d0c0b204f6527975b10015a62636a61e5b6e20661824c6ddbdfe3eefe"},"package":"a76fd60b23679b7d19bd066031410fb7e458ccc5e958eb5c325888ce4baedc97"} \ No newline at end of file
diff --git a/vendor/addr2line/CHANGELOG.md b/vendor/addr2line/CHANGELOG.md
index 914139400..ed47aa90d 100644
--- a/vendor/addr2line/CHANGELOG.md
+++ b/vendor/addr2line/CHANGELOG.md
@@ -1,3 +1,30 @@
+## 0.19.0 (2022/11/24)
+
+### Breaking changes
+
+* Updated `gimli` and `object` dependencies.
+
+--------------------------------------------------------------------------------
+
+## 0.18.0 (2022/07/16)
+
+### Breaking changes
+
+* Updated `object` dependency.
+
+### Changed
+
+* Fixed handling of relative path for `DW_AT_comp_dir`.
+ [#239](https://github.com/gimli-rs/addr2line/pull/239)
+
+* Fixed handling of `DW_FORM_addrx` for DWARF 5 support.
+ [#243](https://github.com/gimli-rs/addr2line/pull/243)
+
+* Fixed handling of units that are missing range information.
+ [#249](https://github.com/gimli-rs/addr2line/pull/249)
+
+--------------------------------------------------------------------------------
+
## 0.17.0 (2021/10/24)
### Breaking changes
diff --git a/vendor/addr2line/Cargo.lock b/vendor/addr2line/Cargo.lock
index 630d72438..330f3f544 100644
--- a/vendor/addr2line/Cargo.lock
+++ b/vendor/addr2line/Cargo.lock
@@ -4,16 +4,16 @@ version = 3
[[package]]
name = "addr2line"
-version = "0.16.0"
+version = "0.17.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3e61f2b7f93d2c7d2b08263acaa4a363b3e276806c68af6134c44f523bf1aacd"
+checksum = "b9ecd88a8c8378ca913a680cd98f0f13ac67383d35993f86c90a70e3f137816b"
dependencies = [
- "gimli 0.25.0",
+ "gimli 0.26.2",
]
[[package]]
name = "addr2line"
-version = "0.17.0"
+version = "0.19.0"
dependencies = [
"backtrace",
"clap",
@@ -21,9 +21,9 @@ dependencies = [
"cpp_demangle",
"fallible-iterator",
"findshlibs",
- "gimli 0.26.0",
- "memmap",
- "object",
+ "gimli 0.27.0",
+ "memmap2",
+ "object 0.30.0",
"rustc-demangle",
"rustc-std-workspace-alloc",
"rustc-std-workspace-core",
@@ -39,15 +39,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
[[package]]
-name = "ansi_term"
-version = "0.11.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b"
-dependencies = [
- "winapi 0.3.9",
-]
-
-[[package]]
name = "atty"
version = "0.2.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -60,22 +51,22 @@ dependencies = [
[[package]]
name = "autocfg"
-version = "1.0.1"
+version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a"
+checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
[[package]]
name = "backtrace"
-version = "0.3.62"
+version = "0.3.66"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "091bcdf2da9950f96aa522681ce805e6857f6ca8df73833d35736ab2dc78e152"
+checksum = "cab84319d616cfb654d03394f38ab7e6f0919e181b1b57e1fd15e7fb4077d9a7"
dependencies = [
- "addr2line 0.16.0",
+ "addr2line 0.17.0",
"cc",
"cfg-if",
"libc",
"miniz_oxide",
- "object",
+ "object 0.29.0",
"rustc-demangle",
]
@@ -87,9 +78,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]]
name = "cc"
-version = "1.0.71"
+version = "1.0.73"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "79c2681d6594606957bbb8631c4b90a7fcaaa72cdb714743a437b156d6a7eedd"
+checksum = "2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11"
[[package]]
name = "cfg-if"
@@ -99,39 +90,48 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "clap"
-version = "2.33.3"
+version = "3.2.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "37e58ac78573c40708d45522f0d80fa2f01cc4f9b4e2bf749807255454312002"
+checksum = "ab8b79fe3946ceb4a0b1c080b4018992b8d27e9ff363644c1c9b6387c854614d"
dependencies = [
- "ansi_term",
"atty",
"bitflags",
+ "clap_lex",
+ "indexmap",
"strsim",
+ "termcolor",
"textwrap",
- "unicode-width",
- "vec_map",
+]
+
+[[package]]
+name = "clap_lex"
+version = "0.2.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2850f2f5a82cbf437dd5af4d49848fbdfc27c157c3d010345776f952765261c5"
+dependencies = [
+ "os_str_bytes",
]
[[package]]
name = "compiler_builtins"
-version = "0.1.51"
+version = "0.1.75"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3587b3669d6f2c1cfd34c475272dabcfef29d52703933f6f72ebb36d6bd81a97"
+checksum = "c6e3183e88f659a862835db8f4b67dbeed3d93e44dd4927eef78edb1c149d784"
[[package]]
name = "cpp_demangle"
-version = "0.3.3"
+version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8ea47428dc9d2237f3c6bc134472edfd63ebba0af932e783506dcfd66f10d18a"
+checksum = "b446fd40bcc17eddd6a4a78f24315eb90afdb3334999ddfd4909985c47722442"
dependencies = [
"cfg-if",
]
[[package]]
name = "crc32fast"
-version = "1.2.1"
+version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "81156fece84ab6a9f2afdb109ce3ae577e42b1228441eded99bd77f627953b1a"
+checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d"
dependencies = [
"cfg-if",
]
@@ -144,9 +144,9 @@ checksum = "4443176a9f2c162692bd3d352d745ef9413eec5782a80d8fd6f8a1ac692a07f7"
[[package]]
name = "findshlibs"
-version = "0.10.1"
+version = "0.10.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d691fdb3f817632d259d09220d4cf0991dbb2c9e59e044a02a59194bf6e14484"
+checksum = "40b9e59cd0f7e0806cca4be089683ecb6434e602038df21fe6bf6711b2f07f64"
dependencies = [
"cc",
"lazy_static",
@@ -156,13 +156,11 @@ dependencies = [
[[package]]
name = "flate2"
-version = "1.0.22"
+version = "1.0.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1e6988e897c1c9c485f43b47a529cef42fde0547f9d8d41a7062518f1d8fc53f"
+checksum = "f82b0f4c27ad9f8bfd1f3208d882da2b09c301bc1c828fd3a00d0216d2fbbff6"
dependencies = [
- "cfg-if",
"crc32fast",
- "libc",
"miniz_oxide",
]
@@ -177,15 +175,15 @@ dependencies = [
[[package]]
name = "gimli"
-version = "0.25.0"
+version = "0.26.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f0a01e0497841a3b2db4f8afa483cce65f7e96a3498bd6c541734792aeac8fe7"
+checksum = "22030e2c5a68ec659fde1e949a745124b48e6fa8b045b7ed5bd1fe4ccc5c4e5d"
[[package]]
name = "gimli"
-version = "0.26.0"
+version = "0.27.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "81a03ce013ffccead76c11a15751231f777d9295b845cc1266ed4d34fcbd7977"
+checksum = "dec7af912d60cdbd3677c1af9352ebae6fb8394d165568a2234df0fa00f87793"
dependencies = [
"compiler_builtins",
"fallible-iterator",
@@ -195,6 +193,12 @@ dependencies = [
]
[[package]]
+name = "hashbrown"
+version = "0.12.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "607c8a29735385251a339424dd462993c0fed8fa09d378f259377df08c126022"
+
+[[package]]
name = "hermit-abi"
version = "0.1.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -204,6 +208,16 @@ dependencies = [
]
[[package]]
+name = "indexmap"
+version = "1.9.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "10a35a97730320ffe8e2d410b5d3b69279b98d2c14bdb8b70ea89ecf7888d41e"
+dependencies = [
+ "autocfg",
+ "hashbrown",
+]
+
+[[package]]
name = "kernel32-sys"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -221,47 +235,60 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
[[package]]
name = "libc"
-version = "0.2.105"
+version = "0.2.126"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "869d572136620d55835903746bcb5cdc54cb2851fd0aeec53220b4bb65ef3013"
+checksum = "349d5a591cd28b49e1d1037471617a32ddcda5731b99419008085f72d5a53836"
[[package]]
name = "memchr"
-version = "2.4.1"
+version = "2.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a"
+checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
[[package]]
-name = "memmap"
-version = "0.7.0"
+name = "memmap2"
+version = "0.5.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6585fd95e7bb50d6cc31e20d4cf9afb4e2ba16c5846fc76793f11218da9c475b"
+checksum = "3a79b39c93a7a5a27eeaf9a23b5ff43f1b9e0ad6b1cdd441140ae53c35613fc7"
dependencies = [
"libc",
- "winapi 0.3.9",
]
[[package]]
name = "miniz_oxide"
-version = "0.4.4"
+version = "0.5.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a92518e98c078586bc6c934028adcca4c92a53d6a958196de835170a01d84e4b"
+checksum = "6f5c75688da582b8ffc1f1799e9db273f32133c49e048f614d22ec3256773ccc"
dependencies = [
"adler",
- "autocfg",
]
[[package]]
name = "object"
-version = "0.27.1"
+version = "0.29.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "21158b2c33aa6d4561f1c0a6ea283ca92bc54802a93b263e910746d679a7eb53"
+dependencies = [
+ "memchr",
+]
+
+[[package]]
+name = "object"
+version = "0.30.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "67ac1d3f9a1d3616fd9a60c8d74296f22406a238b6a72f5cc1e6f314df4ffbf9"
+checksum = "239da7f290cfa979f43f85a8efeee9a8a76d0827c356d37f9d3d7254d6b537fb"
dependencies = [
"flate2",
"memchr",
]
[[package]]
+name = "os_str_bytes"
+version = "6.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "648001efe5d5c0102d8cea768e348da85d90af8ba91f0bea908f157951493cd4"
+
+[[package]]
name = "rustc-demangle"
version = "0.1.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -325,9 +352,9 @@ checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
[[package]]
name = "smallvec"
-version = "1.7.0"
+version = "1.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1ecab6c735a6bb4139c0caafd0cc3635748bbb3acf4550e8138122099251f309"
+checksum = "2fd0db749597d91ff862fd1d55ea87f7855a744a8425a64695b6fca237d1dad1"
[[package]]
name = "stable_deref_trait"
@@ -337,9 +364,9 @@ checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3"
[[package]]
name = "strsim"
-version = "0.8.0"
+version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
+checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
[[package]]
name = "term"
@@ -352,15 +379,21 @@ dependencies = [
]
[[package]]
-name = "textwrap"
-version = "0.11.0"
+name = "termcolor"
+version = "1.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060"
+checksum = "bab24d30b911b2376f3a13cc2cd443142f0c81dda04c118693e35b3835757755"
dependencies = [
- "unicode-width",
+ "winapi-util",
]
[[package]]
+name = "textwrap"
+version = "0.15.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b1141d4d61095b28419e22cb0bbf02755f5e54e0526f97f1e3d1d160e60885fb"
+
+[[package]]
name = "time"
version = "0.1.44"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -384,12 +417,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3ed742d4ea2bd1176e236172c8429aaf54486e7ac098db29ffe6529e0ce50973"
[[package]]
-name = "vec_map"
-version = "0.8.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191"
-
-[[package]]
name = "wasi"
version = "0.10.0+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -424,6 +451,15 @@ 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 0.3.9",
+]
+
+[[package]]
name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
diff --git a/vendor/addr2line/Cargo.toml b/vendor/addr2line/Cargo.toml
index 358995e53..2b51239b8 100644
--- a/vendor/addr2line/Cargo.toml
+++ b/vendor/addr2line/Cargo.toml
@@ -3,38 +3,40 @@
# When uploading crates to the registry Cargo will automatically
# "normalize" Cargo.toml files for maximal compatibility
# with all versions of Cargo and also rewrite `path` dependencies
-# to registry (e.g., crates.io) dependencies
+# to registry (e.g., crates.io) dependencies.
#
-# If you believe there's an error in this file please file an
-# issue against the rust-lang/cargo repository. If you're
-# editing this file be aware that the upstream Cargo.toml
-# will likely look very different (and much more reasonable)
+# If you are reading this file be aware that the original Cargo.toml
+# will likely look very different (and much more reasonable).
+# See Cargo.toml.orig for the original contents.
[package]
name = "addr2line"
-version = "0.17.0"
-exclude = ["/benches/*", "/fixtures/*", ".github"]
+version = "0.19.0"
+exclude = [
+ "/benches/*",
+ "/fixtures/*",
+ ".github",
+]
description = "A cross-platform symbolication library written in Rust, using `gimli`"
documentation = "https://docs.rs/addr2line"
readme = "./README.md"
-keywords = ["DWARF", "debug", "elf", "symbolicate", "atos"]
+keywords = [
+ "DWARF",
+ "debug",
+ "elf",
+ "symbolicate",
+ "atos",
+]
categories = ["development-tools::debugging"]
license = "Apache-2.0 OR MIT"
repository = "https://github.com/gimli-rs/addr2line"
+
[profile.bench]
codegen-units = 1
debug = true
-split-debuginfo = "packed"
-
-[profile.dev]
-split-debuginfo = "packed"
[profile.release]
debug = true
-split-debuginfo = "packed"
-
-[profile.test]
-split-debuginfo = "packed"
[[example]]
name = "addr2line"
@@ -52,6 +54,7 @@ required-features = ["default"]
[[test]]
name = "parse"
required-features = ["std-object"]
+
[dependencies.alloc]
version = "1.0.0"
optional = true
@@ -67,7 +70,8 @@ optional = true
package = "rustc-std-workspace-core"
[dependencies.cpp_demangle]
-version = "0.3"
+version = "0.4"
+features = ["alloc"]
optional = true
default-features = false
@@ -77,12 +81,12 @@ optional = true
default-features = false
[dependencies.gimli]
-version = "0.26"
+version = "0.27.0"
features = ["read"]
default-features = false
[dependencies.object]
-version = "0.27.1"
+version = "0.30.0"
features = ["read"]
optional = true
default-features = false
@@ -95,17 +99,18 @@ optional = true
version = "1"
optional = true
default-features = false
+
[dev-dependencies.backtrace]
version = "0.3.13"
[dev-dependencies.clap]
-version = "2"
+version = "3.1.6"
[dev-dependencies.findshlibs]
version = "0.10"
-[dev-dependencies.memmap]
-version = "0.7"
+[dev-dependencies.memmap2]
+version = "0.5.5"
[dev-dependencies.rustc-test]
version = "0.3"
@@ -114,7 +119,24 @@ version = "0.3"
version = "2"
[features]
-default = ["rustc-demangle", "cpp_demangle", "std-object", "fallible-iterator", "smallvec"]
-rustc-dep-of-std = ["core", "alloc", "compiler_builtins", "gimli/rustc-dep-of-std"]
+default = [
+ "rustc-demangle",
+ "cpp_demangle",
+ "std-object",
+ "fallible-iterator",
+ "smallvec",
+]
+rustc-dep-of-std = [
+ "core",
+ "alloc",
+ "compiler_builtins",
+ "gimli/rustc-dep-of-std",
+]
std = ["gimli/std"]
-std-object = ["std", "object", "object/std", "object/compression", "gimli/endian-reader"]
+std-object = [
+ "std",
+ "object",
+ "object/std",
+ "object/compression",
+ "gimli/endian-reader",
+]
diff --git a/vendor/addr2line/examples/addr2line.rs b/vendor/addr2line/examples/addr2line.rs
index 4b228a706..fa4d8e457 100644
--- a/vendor/addr2line/examples/addr2line.rs
+++ b/vendor/addr2line/examples/addr2line.rs
@@ -2,7 +2,7 @@ extern crate addr2line;
extern crate clap;
extern crate fallible_iterator;
extern crate gimli;
-extern crate memmap;
+extern crate memmap2;
extern crate object;
extern crate typed_arena;
@@ -11,18 +11,18 @@ use std::fs::File;
use std::io::{BufRead, Lines, StdinLock, Write};
use std::path::Path;
-use clap::{App, Arg, Values};
+use clap::{Arg, Command, Values};
use fallible_iterator::FallibleIterator;
-use object::{Object, ObjectSection};
+use object::{Object, ObjectSection, SymbolMap, SymbolMapName};
use typed_arena::Arena;
use addr2line::{Context, Location};
-fn parse_uint_from_hex_string(string: &str) -> u64 {
+fn parse_uint_from_hex_string(string: &str) -> Option<u64> {
if string.len() > 2 && string.starts_with("0x") {
- u64::from_str_radix(&string[2..], 16).expect("Failed to parse address")
+ u64::from_str_radix(&string[2..], 16).ok()
} else {
- u64::from_str_radix(string, 16).expect("Failed to parse address")
+ u64::from_str_radix(string, 16).ok()
}
}
@@ -32,9 +32,9 @@ enum Addrs<'a> {
}
impl<'a> Iterator for Addrs<'a> {
- type Item = u64;
+ type Item = Option<u64>;
- fn next(&mut self) -> Option<u64> {
+ fn next(&mut self) -> Option<Option<u64>> {
let text = match *self {
Addrs::Args(ref mut vals) => vals.next().map(Cow::from),
Addrs::Stdin(ref mut lines) => lines.next().map(Result::unwrap).map(Cow::from),
@@ -45,15 +45,18 @@ impl<'a> Iterator for Addrs<'a> {
}
}
-fn print_loc(loc: &Option<Location>, basenames: bool, llvm: bool) {
- if let Some(ref loc) = *loc {
- let file = loc.file.as_ref().unwrap();
- let path = if basenames {
- Path::new(Path::new(file).file_name().unwrap())
+fn print_loc(loc: Option<&Location>, basenames: bool, llvm: bool) {
+ if let Some(ref loc) = loc {
+ if let Some(ref file) = loc.file.as_ref() {
+ let path = if basenames {
+ Path::new(Path::new(file).file_name().unwrap())
+ } else {
+ Path::new(file)
+ };
+ print!("{}:", path.display());
} else {
- Path::new(file)
- };
- print!("{}:", path.display());
+ print!("??:");
+ }
if llvm {
print!("{}:{}", loc.line.unwrap_or(0), loc.column.unwrap_or(0));
} else if let Some(line) = loc.line {
@@ -65,15 +68,19 @@ fn print_loc(loc: &Option<Location>, basenames: bool, llvm: bool) {
} else if llvm {
println!("??:0:0");
} else {
- println!("??:?");
+ println!("??:0");
}
}
-fn print_function(name: &str, language: Option<gimli::DwLang>, demangle: bool) {
- if demangle {
- print!("{}", addr2line::demangle_auto(Cow::from(name), language));
+fn print_function(name: Option<&str>, language: Option<gimli::DwLang>, demangle: bool) {
+ if let Some(name) = name {
+ if demangle {
+ print!("{}", addr2line::demangle_auto(Cow::from(name), language));
+ } else {
+ print!("{}", name);
+ }
} else {
- print!("{}", name);
+ print!("??");
}
}
@@ -94,77 +101,61 @@ fn load_file_section<'input, 'arena, Endian: gimli::Endianity>(
}
}
+fn find_name_from_symbols<'a>(
+ symbols: &'a SymbolMap<SymbolMapName>,
+ probe: u64,
+) -> Option<&'a str> {
+ symbols.get(probe).map(|x| x.name())
+}
+
fn main() {
- let matches = App::new("hardliner")
+ let matches = Command::new("addr2line")
.version("0.1")
- .about("A fast addr2line clone")
- .arg(
- Arg::with_name("exe")
- .short("e")
+ .about("A fast addr2line Rust port")
+ .args(&[
+ Arg::new("exe")
+ .short('e')
.long("exe")
.value_name("filename")
.help(
"Specify the name of the executable for which addresses should be translated.",
)
.required(true),
- )
- .arg(
- Arg::with_name("sup")
+ Arg::new("sup")
.long("sup")
.value_name("filename")
.help("Path to supplementary object file."),
- )
- .arg(
- Arg::with_name("functions")
- .short("f")
+ Arg::new("functions")
+ .short('f')
.long("functions")
.help("Display function names as well as file and line number information."),
- )
- .arg(
- Arg::with_name("pretty")
- .short("p")
- .long("pretty-print")
- .help(
- "Make the output more human friendly: each location are printed on \
- one line.",
- ),
- )
- .arg(Arg::with_name("inlines").short("i").long("inlines").help(
- "If the address belongs to a function that was inlined, the source \
- information for all enclosing scopes back to the first non-inlined \
- function will also be printed.",
- ))
- .arg(
- Arg::with_name("addresses")
- .short("a")
- .long("addresses")
- .help(
- "Display the address before the function name, file and line \
- number information.",
- ),
- )
- .arg(
- Arg::with_name("basenames")
- .short("s")
+ Arg::new("pretty").short('p').long("pretty-print").help(
+ "Make the output more human friendly: each location are printed on one line.",
+ ),
+ Arg::new("inlines").short('i').long("inlines").help(
+ "If the address belongs to a function that was inlined, the source information for \
+ all enclosing scopes back to the first non-inlined function will also be printed.",
+ ),
+ Arg::new("addresses").short('a').long("addresses").help(
+ "Display the address before the function name, file and line number information.",
+ ),
+ Arg::new("basenames")
+ .short('s')
.long("basenames")
.help("Display only the base of each file name."),
- )
- .arg(Arg::with_name("demangle").short("C").long("demangle").help(
- "Demangle function names. \
- Specifying a specific demangling style (like GNU addr2line) \
- is not supported. (TODO)",
- ))
- .arg(
- Arg::with_name("llvm")
+ Arg::new("demangle").short('C').long("demangle").help(
+ "Demangle function names. \
+ Specifying a specific demangling style (like GNU addr2line) is not supported. \
+ (TODO)"
+ ),
+ Arg::new("llvm")
.long("llvm")
.help("Display output in the same format as llvm-symbolizer."),
- )
- .arg(
- Arg::with_name("addrs")
+ Arg::new("addrs")
.takes_value(true)
- .multiple(true)
+ .multiple_occurrences(true)
.help("Addresses to use instead of reading from stdin."),
- )
+ ])
.get_matches();
let arena_data = Arena::new();
@@ -179,7 +170,7 @@ fn main() {
let path = matches.value_of("exe").unwrap();
let file = File::open(path).unwrap();
- let map = unsafe { memmap::Mmap::map(&file).unwrap() };
+ let map = unsafe { memmap2::Mmap::map(&file).unwrap() };
let object = &object::File::parse(&*map).unwrap();
let endian = if object.is_little_endian() {
@@ -195,7 +186,7 @@ fn main() {
let sup_map;
let sup_object = if let Some(sup_path) = matches.value_of("sup") {
let sup_file = File::open(sup_path).unwrap();
- sup_map = unsafe { memmap::Mmap::map(&sup_file).unwrap() };
+ sup_map = unsafe { memmap2::Mmap::map(&sup_file).unwrap() };
Some(object::File::parse(&*sup_map).unwrap())
} else {
None
@@ -220,10 +211,11 @@ fn main() {
for probe in addrs {
if print_addrs {
+ let addr = probe.unwrap_or(0);
if llvm {
- print!("0x{:x}", probe);
+ print!("0x{:x}", addr);
} else {
- print!("0x{:016x}", probe);
+ print!("0x{:016x}", addr);
}
if pretty {
print!(": ");
@@ -234,44 +226,46 @@ fn main() {
if do_functions || do_inlines {
let mut printed_anything = false;
- let mut frames = ctx.find_frames(probe).unwrap().enumerate();
- while let Some((i, frame)) = frames.next().unwrap() {
- if pretty && i != 0 {
- print!(" (inlined by) ");
- }
-
- if do_functions {
- if let Some(func) = frame.function {
- print_function(&func.raw_name().unwrap(), func.language, demangle);
- } else if let Some(name) = symbols.get(probe).map(|x| x.name()) {
- print_function(name, None, demangle);
- } else {
- print!("??");
+ if let Some(probe) = probe {
+ let mut frames = ctx.find_frames(probe).unwrap().enumerate();
+ while let Some((i, frame)) = frames.next().unwrap() {
+ if pretty && i != 0 {
+ print!(" (inlined by) ");
}
- if pretty {
- print!(" at ");
- } else {
- println!();
+ if do_functions {
+ if let Some(func) = frame.function {
+ print_function(
+ func.raw_name().ok().as_ref().map(AsRef::as_ref),
+ func.language,
+ demangle,
+ );
+ } else {
+ let name = find_name_from_symbols(&symbols, probe);
+ print_function(name, None, demangle);
+ }
+
+ if pretty {
+ print!(" at ");
+ } else {
+ println!();
+ }
}
- }
- print_loc(&frame.location, basenames, llvm);
+ print_loc(frame.location.as_ref(), basenames, llvm);
- printed_anything = true;
+ printed_anything = true;
- if !do_inlines {
- break;
+ if !do_inlines {
+ break;
+ }
}
}
if !printed_anything {
if do_functions {
- if let Some(name) = symbols.get(probe).map(|x| x.name()) {
- print_function(name, None, demangle);
- } else {
- print!("??");
- }
+ let name = probe.and_then(|probe| find_name_from_symbols(&symbols, probe));
+ print_function(name, None, demangle);
if pretty {
print!(" at ");
@@ -280,15 +274,11 @@ fn main() {
}
}
- if llvm {
- println!("??:0:0");
- } else {
- println!("??:?");
- }
+ print_loc(None, basenames, llvm);
}
} else {
- let loc = ctx.find_location(probe).unwrap();
- print_loc(&loc, basenames, llvm);
+ let loc = probe.and_then(|probe| ctx.find_location(probe).unwrap());
+ print_loc(loc.as_ref(), basenames, llvm);
}
if llvm {
diff --git a/vendor/addr2line/src/function.rs b/vendor/addr2line/src/function.rs
index 1589acdbe..44dc73f24 100644
--- a/vendor/addr2line/src/function.rs
+++ b/vendor/addr2line/src/function.rs
@@ -68,15 +68,24 @@ impl<R: gimli::Reader> Functions<R> {
match entries.read_attribute(*spec) {
Ok(ref attr) => {
match attr.name() {
- gimli::DW_AT_low_pc => {
- if let gimli::AttributeValue::Addr(val) = attr.value() {
- ranges.low_pc = Some(val);
+ gimli::DW_AT_low_pc => match attr.value() {
+ gimli::AttributeValue::Addr(val) => {
+ ranges.low_pc = Some(val)
}
- }
+ gimli::AttributeValue::DebugAddrIndex(index) => {
+ ranges.low_pc =
+ Some(dwarf.sections.address(unit, index)?);
+ }
+ _ => {}
+ },
gimli::DW_AT_high_pc => match attr.value() {
gimli::AttributeValue::Addr(val) => {
ranges.high_pc = Some(val)
}
+ gimli::AttributeValue::DebugAddrIndex(index) => {
+ ranges.high_pc =
+ Some(dwarf.sections.address(unit, index)?);
+ }
gimli::AttributeValue::Udata(val) => {
ranges.size = Some(val)
}
@@ -352,13 +361,18 @@ impl<R: gimli::Reader> InlinedFunction<R> {
for spec in abbrev.attributes() {
match entries.read_attribute(*spec) {
Ok(ref attr) => match attr.name() {
- gimli::DW_AT_low_pc => {
- if let gimli::AttributeValue::Addr(val) = attr.value() {
- ranges.low_pc = Some(val);
+ gimli::DW_AT_low_pc => match attr.value() {
+ gimli::AttributeValue::Addr(val) => ranges.low_pc = Some(val),
+ gimli::AttributeValue::DebugAddrIndex(index) => {
+ ranges.low_pc = Some(dwarf.sections.address(unit, index)?);
}
- }
+ _ => {}
+ },
gimli::DW_AT_high_pc => match attr.value() {
gimli::AttributeValue::Addr(val) => ranges.high_pc = Some(val),
+ gimli::AttributeValue::DebugAddrIndex(index) => {
+ ranges.high_pc = Some(dwarf.sections.address(unit, index)?);
+ }
gimli::AttributeValue::Udata(val) => ranges.size = Some(val),
_ => {}
},
diff --git a/vendor/addr2line/src/lazy.rs b/vendor/addr2line/src/lazy.rs
index 280c76b46..a34ed176a 100644
--- a/vendor/addr2line/src/lazy.rs
+++ b/vendor/addr2line/src/lazy.rs
@@ -11,19 +11,17 @@ impl<T> LazyCell<T> {
}
pub fn borrow_with(&self, closure: impl FnOnce() -> T) -> &T {
- unsafe {
- // First check if we're already initialized...
- let ptr = self.contents.get();
- if let Some(val) = &*ptr {
- return val;
- }
- // Note that while we're executing `closure` our `borrow_with` may
- // be called recursively. This means we need to check again after
- // the closure has executed. For that we use the `get_or_insert`
- // method which will only perform mutation if we aren't already
- // `Some`.
- let val = closure();
- (*ptr).get_or_insert(val)
+ // First check if we're already initialized...
+ let ptr = self.contents.get();
+ if let Some(val) = unsafe { &*ptr } {
+ return val;
}
+ // Note that while we're executing `closure` our `borrow_with` may
+ // be called recursively. This means we need to check again after
+ // the closure has executed. For that we use the `get_or_insert`
+ // method which will only perform mutation if we aren't already
+ // `Some`.
+ let val = closure();
+ unsafe { (*ptr).get_or_insert(val) }
}
}
diff --git a/vendor/addr2line/src/lib.rs b/vendor/addr2line/src/lib.rs
index b46a98393..3afa37f8f 100644
--- a/vendor/addr2line/src/lib.rs
+++ b/vendor/addr2line/src/lib.rs
@@ -181,6 +181,7 @@ impl<R: gimli::Reader> Context<R> {
ranges: gimli::RangeLists::new(debug_ranges, debug_rnglists),
file_type: gimli::DwarfFileType::Main,
sup: None,
+ abbreviations_cache: gimli::AbbreviationsCache::new(),
})
}
@@ -404,6 +405,7 @@ impl<R: gimli::Reader> ResDwarf<R> {
};
let mut lang = None;
+ let mut have_unit_range = false;
{
let mut entries = dw_unit.entries_raw(None)?;
@@ -416,13 +418,18 @@ impl<R: gimli::Reader> ResDwarf<R> {
for spec in abbrev.attributes() {
let attr = entries.read_attribute(*spec)?;
match attr.name() {
- gimli::DW_AT_low_pc => {
- if let gimli::AttributeValue::Addr(val) = attr.value() {
- ranges.low_pc = Some(val);
+ gimli::DW_AT_low_pc => match attr.value() {
+ gimli::AttributeValue::Addr(val) => ranges.low_pc = Some(val),
+ gimli::AttributeValue::DebugAddrIndex(index) => {
+ ranges.low_pc = Some(sections.address(&dw_unit, index)?);
}
- }
+ _ => {}
+ },
gimli::DW_AT_high_pc => match attr.value() {
gimli::AttributeValue::Addr(val) => ranges.high_pc = Some(val),
+ gimli::AttributeValue::DebugAddrIndex(index) => {
+ ranges.high_pc = Some(sections.address(&dw_unit, index)?);
+ }
gimli::AttributeValue::Udata(val) => ranges.size = Some(val),
_ => {}
},
@@ -472,11 +479,12 @@ impl<R: gimli::Reader> ResDwarf<R> {
unit_id,
max_end: 0,
});
+ have_unit_range = true;
}
}
}
} else {
- ranges.for_each_range(&sections, &dw_unit, |range| {
+ have_unit_range |= ranges.for_each_range(&sections, &dw_unit, |range| {
unit_ranges.push(UnitRange {
range,
unit_id,
@@ -486,11 +494,34 @@ impl<R: gimli::Reader> ResDwarf<R> {
}
}
+ let lines = LazyCell::new();
+ if !have_unit_range {
+ // The unit did not declare any ranges.
+ // Try to get some ranges from the line program sequences.
+ if let Some(ref ilnp) = dw_unit.line_program {
+ if let Ok(lines) = lines
+ .borrow_with(|| Lines::parse(&dw_unit, ilnp.clone(), &*sections))
+ .as_ref()
+ {
+ for sequence in lines.sequences.iter() {
+ unit_ranges.push(UnitRange {
+ range: gimli::Range {
+ begin: sequence.start,
+ end: sequence.end,
+ },
+ unit_id,
+ max_end: 0,
+ })
+ }
+ }
+ }
+ }
+
res_units.push(ResUnit {
offset,
dw_unit,
lang,
- lines: LazyCell::new(),
+ lines,
funcs: LazyCell::new(),
});
}
@@ -531,6 +562,111 @@ struct Lines {
sequences: Box<[LineSequence]>,
}
+impl Lines {
+ fn parse<R: gimli::Reader>(
+ dw_unit: &gimli::Unit<R>,
+ ilnp: gimli::IncompleteLineProgram<R, R::Offset>,
+ sections: &gimli::Dwarf<R>,
+ ) -> Result<Self, Error> {
+ let mut sequences = Vec::new();
+ let mut sequence_rows = Vec::<LineRow>::new();
+ let mut rows = ilnp.rows();
+ while let Some((_, row)) = rows.next_row()? {
+ if row.end_sequence() {
+ if let Some(start) = sequence_rows.first().map(|x| x.address) {
+ let end = row.address();
+ let mut rows = Vec::new();
+ mem::swap(&mut rows, &mut sequence_rows);
+ sequences.push(LineSequence {
+ start,
+ end,
+ rows: rows.into_boxed_slice(),
+ });
+ }
+ continue;
+ }
+
+ let address = row.address();
+ let file_index = row.file_index();
+ let line = row.line().map(NonZeroU64::get).unwrap_or(0) as u32;
+ let column = match row.column() {
+ gimli::ColumnType::LeftEdge => 0,
+ gimli::ColumnType::Column(x) => x.get() as u32,
+ };
+
+ if let Some(last_row) = sequence_rows.last_mut() {
+ if last_row.address == address {
+ last_row.file_index = file_index;
+ last_row.line = line;
+ last_row.column = column;
+ continue;
+ }
+ }
+
+ sequence_rows.push(LineRow {
+ address,
+ file_index,
+ line,
+ column,
+ });
+ }
+ sequences.sort_by_key(|x| x.start);
+
+ let mut files = Vec::new();
+ let header = rows.header();
+ match header.file(0) {
+ Some(file) => files.push(render_file(dw_unit, file, header, sections)?),
+ None => files.push(String::from("")), // DWARF version <= 4 may not have 0th index
+ }
+ let mut index = 1;
+ while let Some(file) = header.file(index) {
+ files.push(render_file(dw_unit, file, header, sections)?);
+ index += 1;
+ }
+
+ Ok(Self {
+ files: files.into_boxed_slice(),
+ sequences: sequences.into_boxed_slice(),
+ })
+ }
+}
+
+fn render_file<R: gimli::Reader>(
+ dw_unit: &gimli::Unit<R>,
+ file: &gimli::FileEntry<R, R::Offset>,
+ header: &gimli::LineProgramHeader<R, R::Offset>,
+ sections: &gimli::Dwarf<R>,
+) -> Result<String, gimli::Error> {
+ let mut path = if let Some(ref comp_dir) = dw_unit.comp_dir {
+ comp_dir.to_string_lossy()?.into_owned()
+ } else {
+ String::new()
+ };
+
+ // The directory index 0 is defined to correspond to the compilation unit directory.
+ if file.directory_index() != 0 {
+ if let Some(directory) = file.directory(header) {
+ path_push(
+ &mut path,
+ sections
+ .attr_string(dw_unit, directory)?
+ .to_string_lossy()?
+ .as_ref(),
+ );
+ }
+ }
+
+ path_push(
+ &mut path,
+ sections
+ .attr_string(dw_unit, file.path_name())?
+ .to_string_lossy()?
+ .as_ref(),
+ );
+
+ Ok(path)
+}
+
struct LineSequence {
start: u64,
end: u64,
@@ -559,68 +695,7 @@ impl<R: gimli::Reader> ResUnit<R> {
None => return Ok(None),
};
self.lines
- .borrow_with(|| {
- let mut sequences = Vec::new();
- let mut sequence_rows = Vec::<LineRow>::new();
- let mut rows = ilnp.clone().rows();
- while let Some((_, row)) = rows.next_row()? {
- if row.end_sequence() {
- if let Some(start) = sequence_rows.first().map(|x| x.address) {
- let end = row.address();
- let mut rows = Vec::new();
- mem::swap(&mut rows, &mut sequence_rows);
- sequences.push(LineSequence {
- start,
- end,
- rows: rows.into_boxed_slice(),
- });
- }
- continue;
- }
-
- let address = row.address();
- let file_index = row.file_index();
- let line = row.line().map(NonZeroU64::get).unwrap_or(0) as u32;
- let column = match row.column() {
- gimli::ColumnType::LeftEdge => 0,
- gimli::ColumnType::Column(x) => x.get() as u32,
- };
-
- if let Some(last_row) = sequence_rows.last_mut() {
- if last_row.address == address {
- last_row.file_index = file_index;
- last_row.line = line;
- last_row.column = column;
- continue;
- }
- }
-
- sequence_rows.push(LineRow {
- address,
- file_index,
- line,
- column,
- });
- }
- sequences.sort_by_key(|x| x.start);
-
- let mut files = Vec::new();
- let header = ilnp.header();
- match header.file(0) {
- Some(file) => files.push(self.render_file(file, header, sections)?),
- None => files.push(String::from("")), // DWARF version <= 4 may not have 0th index
- }
- let mut index = 1;
- while let Some(file) = header.file(index) {
- files.push(self.render_file(file, header, sections)?);
- index += 1;
- }
-
- Ok(Lines {
- files: files.into_boxed_slice(),
- sequences: sequences.into_boxed_slice(),
- })
- })
+ .borrow_with(|| Lines::parse(&self.dw_unit, ilnp.clone(), sections))
.as_ref()
.map(Some)
.map_err(Error::clone)
@@ -688,39 +763,6 @@ impl<R: gimli::Reader> ResUnit<R> {
let location = self.find_location(probe, &dwarf.sections)?;
Ok((function, location))
}
-
- fn render_file(
- &self,
- file: &gimli::FileEntry<R, R::Offset>,
- header: &gimli::LineProgramHeader<R, R::Offset>,
- sections: &gimli::Dwarf<R>,
- ) -> Result<String, gimli::Error> {
- let mut path = if let Some(ref comp_dir) = self.dw_unit.comp_dir {
- comp_dir.to_string_lossy()?.into_owned()
- } else {
- String::new()
- };
-
- if let Some(directory) = file.directory(header) {
- path_push(
- &mut path,
- sections
- .attr_string(&self.dw_unit, directory)?
- .to_string_lossy()?
- .as_ref(),
- );
- }
-
- path_push(
- &mut path,
- sections
- .attr_string(&self.dw_unit, file.path_name())?
- .to_string_lossy()?
- .as_ref(),
- );
-
- Ok(path)
- }
}
/// Iterator over `Location`s in a range of addresses, returned by `Context::find_location_range`.
@@ -928,7 +970,7 @@ fn path_push(path: &mut String, p: &str) {
'/'
};
- if !path.ends_with(dir_separator) {
+ if !path.is_empty() && !path.ends_with(dir_separator) {
path.push(dir_separator);
}
*path += p;
diff --git a/vendor/addr2line/tests/correctness.rs b/vendor/addr2line/tests/correctness.rs
index 3f7b43373..955e2b831 100644
--- a/vendor/addr2line/tests/correctness.rs
+++ b/vendor/addr2line/tests/correctness.rs
@@ -2,7 +2,7 @@ extern crate addr2line;
extern crate fallible_iterator;
extern crate findshlibs;
extern crate gimli;
-extern crate memmap;
+extern crate memmap2;
extern crate object;
use addr2line::Context;
@@ -11,10 +11,10 @@ use findshlibs::{IterationControl, SharedLibrary, TargetSharedLibrary};
use object::Object;
use std::fs::File;
-fn find_debuginfo() -> memmap::Mmap {
+fn find_debuginfo() -> memmap2::Mmap {
let path = std::env::current_exe().unwrap();
let file = File::open(&path).unwrap();
- let map = unsafe { memmap::Mmap::map(&file).unwrap() };
+ let map = unsafe { memmap2::Mmap::map(&file).unwrap() };
let file = &object::File::parse(&*map).unwrap();
if let Ok(uuid) = file.mach_uuid() {
for candidate in path.parent().unwrap().read_dir().unwrap() {
@@ -25,7 +25,7 @@ fn find_debuginfo() -> memmap::Mmap {
for candidate in path.join("Contents/Resources/DWARF").read_dir().unwrap() {
let path = candidate.unwrap().path();
let file = File::open(&path).unwrap();
- let map = unsafe { memmap::Mmap::map(&file).unwrap() };
+ let map = unsafe { memmap2::Mmap::map(&file).unwrap() };
let file = &object::File::parse(&*map).unwrap();
if file.mach_uuid().unwrap() == uuid {
return map;
@@ -41,11 +41,12 @@ fn find_debuginfo() -> memmap::Mmap {
fn correctness() {
let map = find_debuginfo();
let file = &object::File::parse(&*map).unwrap();
+ let module_base = file.relative_address_base();
let ctx = Context::new(file).unwrap();
let mut bias = None;
TargetSharedLibrary::each(|lib| {
- bias = Some(lib.virtual_memory_bias().0 as u64);
+ bias = Some((lib.virtual_memory_bias().0 as u64).wrapping_sub(module_base));
IterationControl::Break
});
diff --git a/vendor/addr2line/tests/output_equivalence.rs b/vendor/addr2line/tests/output_equivalence.rs
index 9dc366672..c0e1f8335 100644
--- a/vendor/addr2line/tests/output_equivalence.rs
+++ b/vendor/addr2line/tests/output_equivalence.rs
@@ -11,6 +11,7 @@ use backtrace::Backtrace;
use findshlibs::{IterationControl, SharedLibrary, TargetSharedLibrary};
use test::{ShouldPanic, TestDesc, TestDescAndFn, TestFn, TestName};
+#[inline(never)]
fn make_trace() -> Vec<String> {
fn foo() -> Backtrace {
bar()
diff --git a/vendor/addr2line/tests/parse.rs b/vendor/addr2line/tests/parse.rs
index 91d66e382..60b2300b5 100644
--- a/vendor/addr2line/tests/parse.rs
+++ b/vendor/addr2line/tests/parse.rs
@@ -1,5 +1,5 @@
extern crate addr2line;
-extern crate memmap;
+extern crate memmap2;
extern crate object;
use std::borrow::Cow;
@@ -25,7 +25,7 @@ fn release_fixture_path() -> PathBuf {
fn with_file<F: FnOnce(&object::File)>(target: &path::Path, f: F) {
let file = File::open(target).unwrap();
- let map = unsafe { memmap::Mmap::map(&file).unwrap() };
+ let map = unsafe { memmap2::Mmap::map(&file).unwrap() };
let file = object::File::parse(&*map).unwrap();
f(&file)
}
diff --git a/vendor/ansi_term/.cargo-checksum.json b/vendor/ansi_term/.cargo-checksum.json
deleted file mode 100644
index ee41459db..000000000
--- a/vendor/ansi_term/.cargo-checksum.json
+++ /dev/null
@@ -1 +0,0 @@
-{"files":{"Cargo.lock":"31bb7b361278d99a00595cbd916c444e6fd193b5f0b1ea0cf2d9454440739501","Cargo.toml":"4ca681d6949661455ac88541ffa68ebc7db50cb2b6e9a2134e6d0687da4997c3","LICENCE":"2762990c7fbba9d550802a2593c1d857dcd52596bb0f9f192a97e9a7ac5f4f9e","README.md":"8d983e1bb3cc99724010d9073a5be6452cd49bd57a877525fd0a5dd41e6591d5","examples/256_colours.rs":"5f2845068bc2d93cff4a61f18ffa44fbbbc91be771dfd686d537d343f37041da","examples/basic_colours.rs":"d610795f3743d10d90ec4e5ab32cc09fb16640896cecd2f93fca434a0920397c","examples/rgb_colours.rs":"8399e5131e959a56c932036b790e601fb4ad658856112daf87f933889b443f2c","src/ansi.rs":"988fb87936064fa006fcc9474ac62099c8d6e98d38bb80cec2cd864066482a08","src/debug.rs":"61343f8bf13695020102c033aeaacd9ccd3ec830eacbf9011127e61829451d20","src/difference.rs":"9b4b8f91c72932bfda262abdceff0ec124a5a8dd27d07bd4d2e5e7889135c6c9","src/display.rs":"c04f2397d1d1d86a5e2188c2840c505cb0baeaf9706a88d4bbe56eadc67811b9","src/lib.rs":"b85df4b9b8832cda777db049efa2ec84b9847438fa3feaf8540e597ce2532a47","src/style.rs":"1042fc973f5ea8bbb2a2faec334aad530520b53edc9b3296174ae38c1060490b","src/util.rs":"07c127f732887573a1c9126fc0288e13e7a8f1f803513b95e50aac2905171b0d","src/windows.rs":"7ce7dd6738b9728fcd3908c284b6f29a9bdfb34af761b4c7385cf7e3e1b20e64","src/write.rs":"c9ec03764ad1ecea8b680243c9cafc5e70919fcea7500cc18246ffd8f6bb4b33"},"package":"d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2"} \ No newline at end of file
diff --git a/vendor/ansi_term/Cargo.lock b/vendor/ansi_term/Cargo.lock
deleted file mode 100644
index b21004554..000000000
--- a/vendor/ansi_term/Cargo.lock
+++ /dev/null
@@ -1,168 +0,0 @@
-# This file is automatically @generated by Cargo.
-# It is not intended for manual editing.
-[[package]]
-name = "aho-corasick"
-version = "0.7.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
-name = "ansi_term"
-version = "0.12.1"
-dependencies = [
- "doc-comment 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "regex 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde 1.0.94 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)",
- "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
-name = "doc-comment"
-version = "0.3.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-
-[[package]]
-name = "itoa"
-version = "0.4.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-
-[[package]]
-name = "lazy_static"
-version = "1.4.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-
-[[package]]
-name = "memchr"
-version = "2.2.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-
-[[package]]
-name = "proc-macro2"
-version = "0.4.30"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
-name = "quote"
-version = "0.6.13"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
-name = "regex"
-version = "1.2.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "aho-corasick 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)",
- "memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "regex-syntax 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)",
- "thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
-name = "regex-syntax"
-version = "0.6.11"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-
-[[package]]
-name = "ryu"
-version = "1.0.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-
-[[package]]
-name = "serde"
-version = "1.0.94"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "serde_derive 1.0.94 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
-name = "serde_derive"
-version = "1.0.94"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)",
- "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)",
- "syn 0.15.39 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
-name = "serde_json"
-version = "1.0.40"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
- "ryu 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde 1.0.94 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
-name = "syn"
-version = "0.15.39"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)",
- "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)",
- "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
-name = "thread_local"
-version = "0.3.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
-name = "unicode-xid"
-version = "0.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-
-[[package]]
-name = "winapi"
-version = "0.3.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
-name = "winapi-i686-pc-windows-gnu"
-version = "0.4.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-
-[[package]]
-name = "winapi-x86_64-pc-windows-gnu"
-version = "0.4.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-
-[metadata]
-"checksum aho-corasick 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)" = "58fb5e95d83b38284460a5fda7d6470aa0b8844d283a0b614b8535e880800d2d"
-"checksum doc-comment 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "923dea538cea0aa3025e8685b20d6ee21ef99c4f77e954a30febbaac5ec73a97"
-"checksum itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "501266b7edd0174f8530248f87f99c88fbe60ca4ef3dd486835b8d8d53136f7f"
-"checksum lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
-"checksum memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "88579771288728879b57485cc7d6b07d648c9f0141eb955f8ab7f9d45394468e"
-"checksum proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)" = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759"
-"checksum quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)" = "6ce23b6b870e8f94f81fb0a363d65d86675884b34a09043c81e5562f11c1f8e1"
-"checksum regex 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "88c3d9193984285d544df4a30c23a4e62ead42edf70a4452ceb76dac1ce05c26"
-"checksum regex-syntax 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)" = "b143cceb2ca5e56d5671988ef8b15615733e7ee16cd348e064333b251b89343f"
-"checksum ryu 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c92464b447c0ee8c4fb3824ecc8383b81717b9f1e74ba2e72540aef7b9f82997"
-"checksum serde 1.0.94 (registry+https://github.com/rust-lang/crates.io-index)" = "076a696fdea89c19d3baed462576b8f6d663064414b5c793642da8dfeb99475b"
-"checksum serde_derive 1.0.94 (registry+https://github.com/rust-lang/crates.io-index)" = "ef45eb79d6463b22f5f9e16d283798b7c0175ba6050bc25c1a946c122727fe7b"
-"checksum serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)" = "051c49229f282f7c6f3813f8286cc1e3323e8051823fce42c7ea80fe13521704"
-"checksum syn 0.15.39 (registry+https://github.com/rust-lang/crates.io-index)" = "b4d960b829a55e56db167e861ddb43602c003c7be0bee1d345021703fac2fb7c"
-"checksum thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b"
-"checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc"
-"checksum winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "92c1eb33641e276cfa214a0522acad57be5c56b10cb348b3c5117db75f3ac4b0"
-"checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
-"checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
diff --git a/vendor/ansi_term/Cargo.toml b/vendor/ansi_term/Cargo.toml
deleted file mode 100644
index 0e5febabd..000000000
--- a/vendor/ansi_term/Cargo.toml
+++ /dev/null
@@ -1,43 +0,0 @@
-# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
-#
-# When uploading crates to the registry Cargo will automatically
-# "normalize" Cargo.toml files for maximal compatibility
-# with all versions of Cargo and also rewrite `path` dependencies
-# to registry (e.g., crates.io) dependencies
-#
-# If you believe there's an error in this file please file an
-# issue against the rust-lang/cargo repository. If you're
-# editing this file be aware that the upstream Cargo.toml
-# will likely look very different (and much more reasonable)
-
-[package]
-name = "ansi_term"
-version = "0.12.1"
-authors = ["ogham@bsago.me", "Ryan Scheel (Havvy) <ryan.havvy@gmail.com>", "Josh Triplett <josh@joshtriplett.org>"]
-description = "Library for ANSI terminal colours and styles (bold, underline)"
-homepage = "https://github.com/ogham/rust-ansi-term"
-documentation = "https://docs.rs/ansi_term"
-readme = "README.md"
-license = "MIT"
-repository = "https://github.com/ogham/rust-ansi-term"
-
-[lib]
-name = "ansi_term"
-[dependencies.serde]
-version = "1.0.90"
-features = ["derive"]
-optional = true
-[dev-dependencies.doc-comment]
-version = "0.3"
-
-[dev-dependencies.regex]
-version = "1.1.9"
-
-[dev-dependencies.serde_json]
-version = "1.0.39"
-
-[features]
-derive_serde_style = ["serde"]
-[target."cfg(target_os=\"windows\")".dependencies.winapi]
-version = "0.3.4"
-features = ["consoleapi", "errhandlingapi", "fileapi", "handleapi", "processenv"]
diff --git a/vendor/ansi_term/examples/basic_colours.rs b/vendor/ansi_term/examples/basic_colours.rs
deleted file mode 100644
index ba8815621..000000000
--- a/vendor/ansi_term/examples/basic_colours.rs
+++ /dev/null
@@ -1,18 +0,0 @@
-extern crate ansi_term;
-use ansi_term::{Style, Colour::*};
-
-// This example prints out the 16 basic colours.
-
-fn main() {
- let normal = Style::default();
-
- println!("{} {}", normal.paint("Normal"), normal.bold().paint("bold"));
- println!("{} {}", Black.paint("Black"), Black.bold().paint("bold"));
- println!("{} {}", Red.paint("Red"), Red.bold().paint("bold"));
- println!("{} {}", Green.paint("Green"), Green.bold().paint("bold"));
- println!("{} {}", Yellow.paint("Yellow"), Yellow.bold().paint("bold"));
- println!("{} {}", Blue.paint("Blue"), Blue.bold().paint("bold"));
- println!("{} {}", Purple.paint("Purple"), Purple.bold().paint("bold"));
- println!("{} {}", Cyan.paint("Cyan"), Cyan.bold().paint("bold"));
- println!("{} {}", White.paint("White"), White.bold().paint("bold"));
-}
diff --git a/vendor/ansi_term/examples/rgb_colours.rs b/vendor/ansi_term/examples/rgb_colours.rs
deleted file mode 100644
index fd2cc7a85..000000000
--- a/vendor/ansi_term/examples/rgb_colours.rs
+++ /dev/null
@@ -1,23 +0,0 @@
-extern crate ansi_term;
-use ansi_term::{Style, Colour};
-
-// This example prints out a colour gradient in a grid by calculating each
-// character’s red, green, and blue components, and using 24-bit colour codes
-// to display them.
-
-const WIDTH: i32 = 80;
-const HEIGHT: i32 = 24;
-
-fn main() {
- for row in 0 .. HEIGHT {
- for col in 0 .. WIDTH {
- let r = (row * 255 / HEIGHT) as u8;
- let g = (col * 255 / WIDTH) as u8;
- let b = 128;
-
- print!("{}", Style::default().on(Colour::RGB(r, g, b)).paint(" "));
- }
-
- print!("\n");
- }
-}
diff --git a/vendor/ansi_term/src/style.rs b/vendor/ansi_term/src/style.rs
deleted file mode 100644
index 1bee4d91c..000000000
--- a/vendor/ansi_term/src/style.rs
+++ /dev/null
@@ -1,521 +0,0 @@
-/// A style is a collection of properties that can format a string
-/// using ANSI escape codes.
-///
-/// # Examples
-///
-/// ```
-/// use ansi_term::{Style, Colour};
-///
-/// let style = Style::new().bold().on(Colour::Black);
-/// println!("{}", style.paint("Bold on black"));
-/// ```
-#[derive(PartialEq, Clone, Copy)]
-#[cfg_attr(feature = "derive_serde_style", derive(serde::Deserialize, serde::Serialize))]
-pub struct Style {
-
- /// The style's foreground colour, if it has one.
- pub foreground: Option<Colour>,
-
- /// The style's background colour, if it has one.
- pub background: Option<Colour>,
-
- /// Whether this style is bold.
- pub is_bold: bool,
-
- /// Whether this style is dimmed.
- pub is_dimmed: bool,
-
- /// Whether this style is italic.
- pub is_italic: bool,
-
- /// Whether this style is underlined.
- pub is_underline: bool,
-
- /// Whether this style is blinking.
- pub is_blink: bool,
-
- /// Whether this style has reverse colours.
- pub is_reverse: bool,
-
- /// Whether this style is hidden.
- pub is_hidden: bool,
-
- /// Whether this style is struckthrough.
- pub is_strikethrough: bool
-}
-
-impl Style {
-
- /// Creates a new Style with no properties set.
- ///
- /// # Examples
- ///
- /// ```
- /// use ansi_term::Style;
- ///
- /// let style = Style::new();
- /// println!("{}", style.paint("hi"));
- /// ```
- pub fn new() -> Style {
- Style::default()
- }
-
- /// Returns a `Style` with the bold property set.
- ///
- /// # Examples
- ///
- /// ```
- /// use ansi_term::Style;
- ///
- /// let style = Style::new().bold();
- /// println!("{}", style.paint("hey"));
- /// ```
- pub fn bold(&self) -> Style {
- Style { is_bold: true, .. *self }
- }
-
- /// Returns a `Style` with the dimmed property set.
- ///
- /// # Examples
- ///
- /// ```
- /// use ansi_term::Style;
- ///
- /// let style = Style::new().dimmed();
- /// println!("{}", style.paint("sup"));
- /// ```
- pub fn dimmed(&self) -> Style {
- Style { is_dimmed: true, .. *self }
- }
-
- /// Returns a `Style` with the italic property set.
- ///
- /// # Examples
- ///
- /// ```
- /// use ansi_term::Style;
- ///
- /// let style = Style::new().italic();
- /// println!("{}", style.paint("greetings"));
- /// ```
- pub fn italic(&self) -> Style {
- Style { is_italic: true, .. *self }
- }
-
- /// Returns a `Style` with the underline property set.
- ///
- /// # Examples
- ///
- /// ```
- /// use ansi_term::Style;
- ///
- /// let style = Style::new().underline();
- /// println!("{}", style.paint("salutations"));
- /// ```
- pub fn underline(&self) -> Style {
- Style { is_underline: true, .. *self }
- }
-
- /// Returns a `Style` with the blink property set.
- /// # Examples
- ///
- /// ```
- /// use ansi_term::Style;
- ///
- /// let style = Style::new().blink();
- /// println!("{}", style.paint("wazzup"));
- /// ```
- pub fn blink(&self) -> Style {
- Style { is_blink: true, .. *self }
- }
-
- /// Returns a `Style` with the reverse property set.
- ///
- /// # Examples
- ///
- /// ```
- /// use ansi_term::Style;
- ///
- /// let style = Style::new().reverse();
- /// println!("{}", style.paint("aloha"));
- /// ```
- pub fn reverse(&self) -> Style {
- Style { is_reverse: true, .. *self }
- }
-
- /// Returns a `Style` with the hidden property set.
- ///
- /// # Examples
- ///
- /// ```
- /// use ansi_term::Style;
- ///
- /// let style = Style::new().hidden();
- /// println!("{}", style.paint("ahoy"));
- /// ```
- pub fn hidden(&self) -> Style {
- Style { is_hidden: true, .. *self }
- }
-
- /// Returns a `Style` with the strikethrough property set.
- ///
- /// # Examples
- ///
- /// ```
- /// use ansi_term::Style;
- ///
- /// let style = Style::new().strikethrough();
- /// println!("{}", style.paint("yo"));
- /// ```
- pub fn strikethrough(&self) -> Style {
- Style { is_strikethrough: true, .. *self }
- }
-
- /// Returns a `Style` with the foreground colour property set.
- ///
- /// # Examples
- ///
- /// ```
- /// use ansi_term::{Style, Colour};
- ///
- /// let style = Style::new().fg(Colour::Yellow);
- /// println!("{}", style.paint("hi"));
- /// ```
- pub fn fg(&self, foreground: Colour) -> Style {
- Style { foreground: Some(foreground), .. *self }
- }
-
- /// Returns a `Style` with the background colour property set.
- ///
- /// # Examples
- ///
- /// ```
- /// use ansi_term::{Style, Colour};
- ///
- /// let style = Style::new().on(Colour::Blue);
- /// println!("{}", style.paint("eyyyy"));
- /// ```
- pub fn on(&self, background: Colour) -> Style {
- Style { background: Some(background), .. *self }
- }
-
- /// Return true if this `Style` has no actual styles, and can be written
- /// without any control characters.
- ///
- /// # Examples
- ///
- /// ```
- /// use ansi_term::Style;
- ///
- /// assert_eq!(true, Style::default().is_plain());
- /// assert_eq!(false, Style::default().bold().is_plain());
- /// ```
- pub fn is_plain(self) -> bool {
- self == Style::default()
- }
-}
-
-impl Default for Style {
-
- /// Returns a style with *no* properties set. Formatting text using this
- /// style returns the exact same text.
- ///
- /// ```
- /// use ansi_term::Style;
- /// assert_eq!(None, Style::default().foreground);
- /// assert_eq!(None, Style::default().background);
- /// assert_eq!(false, Style::default().is_bold);
- /// assert_eq!("txt", Style::default().paint("txt").to_string());
- /// ```
- fn default() -> Style {
- Style {
- foreground: None,
- background: None,
- is_bold: false,
- is_dimmed: false,
- is_italic: false,
- is_underline: false,
- is_blink: false,
- is_reverse: false,
- is_hidden: false,
- is_strikethrough: false,
- }
- }
-}
-
-
-// ---- colours ----
-
-/// A colour is one specific type of ANSI escape code, and can refer
-/// to either the foreground or background colour.
-///
-/// These use the standard numeric sequences.
-/// See <http://invisible-island.net/xterm/ctlseqs/ctlseqs.html>
-#[derive(PartialEq, Clone, Copy, Debug)]
-#[cfg_attr(feature = "derive_serde_style", derive(serde::Deserialize, serde::Serialize))]
-pub enum Colour {
-
- /// Colour #0 (foreground code `30`, background code `40`).
- ///
- /// This is not necessarily the background colour, and using it as one may
- /// render the text hard to read on terminals with dark backgrounds.
- Black,
-
- /// Colour #1 (foreground code `31`, background code `41`).
- Red,
-
- /// Colour #2 (foreground code `32`, background code `42`).
- Green,
-
- /// Colour #3 (foreground code `33`, background code `43`).
- Yellow,
-
- /// Colour #4 (foreground code `34`, background code `44`).
- Blue,
-
- /// Colour #5 (foreground code `35`, background code `45`).
- Purple,
-
- /// Colour #6 (foreground code `36`, background code `46`).
- Cyan,
-
- /// Colour #7 (foreground code `37`, background code `47`).
- ///
- /// As above, this is not necessarily the foreground colour, and may be
- /// hard to read on terminals with light backgrounds.
- White,
-
- /// A colour number from 0 to 255, for use in 256-colour terminal
- /// environments.
- ///
- /// - Colours 0 to 7 are the `Black` to `White` variants respectively.
- /// These colours can usually be changed in the terminal emulator.
- /// - Colours 8 to 15 are brighter versions of the eight colours above.
- /// These can also usually be changed in the terminal emulator, or it
- /// could be configured to use the original colours and show the text in
- /// bold instead. It varies depending on the program.
- /// - Colours 16 to 231 contain several palettes of bright colours,
- /// arranged in six squares measuring six by six each.
- /// - Colours 232 to 255 are shades of grey from black to white.
- ///
- /// It might make more sense to look at a [colour chart][cc].
- ///
- /// [cc]: https://upload.wikimedia.org/wikipedia/commons/1/15/Xterm_256color_chart.svg
- Fixed(u8),
-
- /// A 24-bit RGB color, as specified by ISO-8613-3.
- RGB(u8, u8, u8),
-}
-
-
-impl Colour {
-
- /// Returns a `Style` with the foreground colour set to this colour.
- ///
- /// # Examples
- ///
- /// ```
- /// use ansi_term::Colour;
- ///
- /// let style = Colour::Red.normal();
- /// println!("{}", style.paint("hi"));
- /// ```
- pub fn normal(self) -> Style {
- Style { foreground: Some(self), .. Style::default() }
- }
-
- /// Returns a `Style` with the foreground colour set to this colour and the
- /// bold property set.
- ///
- /// # Examples
- ///
- /// ```
- /// use ansi_term::Colour;
- ///
- /// let style = Colour::Green.bold();
- /// println!("{}", style.paint("hey"));
- /// ```
- pub fn bold(self) -> Style {
- Style { foreground: Some(self), is_bold: true, .. Style::default() }
- }
-
- /// Returns a `Style` with the foreground colour set to this colour and the
- /// dimmed property set.
- ///
- /// # Examples
- ///
- /// ```
- /// use ansi_term::Colour;
- ///
- /// let style = Colour::Yellow.dimmed();
- /// println!("{}", style.paint("sup"));
- /// ```
- pub fn dimmed(self) -> Style {
- Style { foreground: Some(self), is_dimmed: true, .. Style::default() }
- }
-
- /// Returns a `Style` with the foreground colour set to this colour and the
- /// italic property set.
- ///
- /// # Examples
- ///
- /// ```
- /// use ansi_term::Colour;
- ///
- /// let style = Colour::Blue.italic();
- /// println!("{}", style.paint("greetings"));
- /// ```
- pub fn italic(self) -> Style {
- Style { foreground: Some(self), is_italic: true, .. Style::default() }
- }
-
- /// Returns a `Style` with the foreground colour set to this colour and the
- /// underline property set.
- ///
- /// # Examples
- ///
- /// ```
- /// use ansi_term::Colour;
- ///
- /// let style = Colour::Purple.underline();
- /// println!("{}", style.paint("salutations"));
- /// ```
- pub fn underline(self) -> Style {
- Style { foreground: Some(self), is_underline: true, .. Style::default() }
- }
-
- /// Returns a `Style` with the foreground colour set to this colour and the
- /// blink property set.
- ///
- /// # Examples
- ///
- /// ```
- /// use ansi_term::Colour;
- ///
- /// let style = Colour::Cyan.blink();
- /// println!("{}", style.paint("wazzup"));
- /// ```
- pub fn blink(self) -> Style {
- Style { foreground: Some(self), is_blink: true, .. Style::default() }
- }
-
- /// Returns a `Style` with the foreground colour set to this colour and the
- /// reverse property set.
- ///
- /// # Examples
- ///
- /// ```
- /// use ansi_term::Colour;
- ///
- /// let style = Colour::Black.reverse();
- /// println!("{}", style.paint("aloha"));
- /// ```
- pub fn reverse(self) -> Style {
- Style { foreground: Some(self), is_reverse: true, .. Style::default() }
- }
-
- /// Returns a `Style` with the foreground colour set to this colour and the
- /// hidden property set.
- ///
- /// # Examples
- ///
- /// ```
- /// use ansi_term::Colour;
- ///
- /// let style = Colour::White.hidden();
- /// println!("{}", style.paint("ahoy"));
- /// ```
- pub fn hidden(self) -> Style {
- Style { foreground: Some(self), is_hidden: true, .. Style::default() }
- }
-
- /// Returns a `Style` with the foreground colour set to this colour and the
- /// strikethrough property set.
- ///
- /// # Examples
- ///
- /// ```
- /// use ansi_term::Colour;
- ///
- /// let style = Colour::Fixed(244).strikethrough();
- /// println!("{}", style.paint("yo"));
- /// ```
- pub fn strikethrough(self) -> Style {
- Style { foreground: Some(self), is_strikethrough: true, .. Style::default() }
- }
-
- /// Returns a `Style` with the foreground colour set to this colour and the
- /// background colour property set to the given colour.
- ///
- /// # Examples
- ///
- /// ```
- /// use ansi_term::Colour;
- ///
- /// let style = Colour::RGB(31, 31, 31).on(Colour::White);
- /// println!("{}", style.paint("eyyyy"));
- /// ```
- pub fn on(self, background: Colour) -> Style {
- Style { foreground: Some(self), background: Some(background), .. Style::default() }
- }
-}
-
-impl From<Colour> for Style {
-
- /// You can turn a `Colour` into a `Style` with the foreground colour set
- /// with the `From` trait.
- ///
- /// ```
- /// use ansi_term::{Style, Colour};
- /// let green_foreground = Style::default().fg(Colour::Green);
- /// assert_eq!(green_foreground, Colour::Green.normal());
- /// assert_eq!(green_foreground, Colour::Green.into());
- /// assert_eq!(green_foreground, Style::from(Colour::Green));
- /// ```
- fn from(colour: Colour) -> Style {
- colour.normal()
- }
-}
-
-#[cfg(test)]
-#[cfg(feature = "derive_serde_style")]
-mod serde_json_tests {
- use super::{Style, Colour};
-
- #[test]
- fn colour_serialization() {
-
- let colours = &[
- Colour::Red,
- Colour::Blue,
- Colour::RGB(123, 123, 123),
- Colour::Fixed(255),
- ];
-
- assert_eq!(serde_json::to_string(&colours).unwrap(), String::from("[\"Red\",\"Blue\",{\"RGB\":[123,123,123]},{\"Fixed\":255}]"));
- }
-
- #[test]
- fn colour_deserialization() {
- let colours = &[
- Colour::Red,
- Colour::Blue,
- Colour::RGB(123, 123, 123),
- Colour::Fixed(255),
- ];
-
- for colour in colours.into_iter() {
- let serialized = serde_json::to_string(&colour).unwrap();
- let deserialized: Colour = serde_json::from_str(&serialized).unwrap();
-
- assert_eq!(colour, &deserialized);
- }
- }
-
- #[test]
- fn style_serialization() {
- let style = Style::default();
-
- assert_eq!(serde_json::to_string(&style).unwrap(), "{\"foreground\":null,\"background\":null,\"is_bold\":false,\"is_dimmed\":false,\"is_italic\":false,\"is_underline\":false,\"is_blink\":false,\"is_reverse\":false,\"is_hidden\":false,\"is_strikethrough\":false}".to_string());
- }
-}
diff --git a/vendor/anyhow/.cargo-checksum.json b/vendor/anyhow/.cargo-checksum.json
index e1190e628..7fef58ba8 100644
--- a/vendor/anyhow/.cargo-checksum.json
+++ b/vendor/anyhow/.cargo-checksum.json
@@ -1 +1 @@
-{"files":{"Cargo.toml":"c8e64a8ca00738e01d382e5ec9ce52e3869df34371a2f9bbf008fc8c23817200","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"23f18e03dc49df91622fe2a76176497404e46ced8a715d9d2b67a7446571cca3","README.md":"4bd4d352368ac0f5447031d82454490f6ac0c80d2fa4cb64ba0c23c614670d49","build.rs":"88bf7100143c79c0af683da7f28deaac031c9b9b213a6426560dc089b0ba45aa","rust-toolchain.toml":"6bbb61302978c736b2da03e4fb40e3beab908f85d533ab46fd541e637b5f3e0f","src/backtrace.rs":"5b4103a7d24d6f438a64b8cc0fafe28d55fc0ca090368174ce44d64e3940badd","src/chain.rs":"6edefc5f3c7d69683095862e54e3bb56faba5b3387bf2eeaed429da090007a0a","src/context.rs":"fe733dd36f34ee8d8fc26569cc94df0236a8c1600ed4c969a63afe06dcb7afeb","src/ensure.rs":"498bc9c7fb8b93168ed12f532cb97df6ccdda9ce25371586d7f5b1b1c98a14bf","src/error.rs":"e45d4dcfe64b1823b42fbf9bb260e6437987e8c2d51f92434db9d808b36e700a","src/fmt.rs":"c2d4aad6ce20625a70a7c091e3087b6a2c19a4a87c7a12edb4c98978307245ea","src/kind.rs":"332854c5eb07d44447c356a2e7dc585634b0da1ffbbfa81269c369deaefbc247","src/lib.rs":"dc32c43ef5a7d690f764af71198b7d14fefb0247ae43926aedecf605876c30dd","src/macros.rs":"dd35f2ec2a0a25e4504fb04bcd42f6d0963bc0035aaaefc412f5ee1d78945fe1","src/ptr.rs":"f4e28bc9feba1e84160ca9d185008a51b5d72e168e6546f3e942f4258c361e19","src/wrapper.rs":"ff3ad72065a30cc32e9acb0614a30703c49c57b941a335c348b6439af684316b","tests/common/mod.rs":"f9088c2d7afafa64ff730b629272045b776bfafc2f5957508242da630635f2e1","tests/compiletest.rs":"022a8e400ef813d7ea1875b944549cee5125f6a995dc33e93b48cba3e1b57bd1","tests/drop/mod.rs":"08c3e553c1cc0d2dbd936fc45f4b5b1105057186affd6865e8d261e05f0f0646","tests/test_autotrait.rs":"981e792db353be2f14c7a1cabe43b5f1329c168cb7679077cc2be786a0920d48","tests/test_backtrace.rs":"0e50edbb33b6bd07ba89ff3db72fb7c688ba2a4371fccdbbb20309ab02948b6a","tests/test_boxed.rs":"6b26db0e2eb72afe9af7352ea820837aab90f8d486294616dd5dc34c1b94038c","tests/test_chain.rs":"d5e90e3eba58abc60d241d3aade39e0b8d4006d9a14f3cf015d3d925160b5812","tests/test_context.rs":"8409c53b328562c11e822bd6c3cd17e0d4d50b9bbb8fc3617333fd77303a6a33","tests/test_convert.rs":"7e7a8b4772a427a911014ac4d1083f9519000e786177f898808980dd9bdfde61","tests/test_downcast.rs":"797e69a72d125758c4c4897e5dc776d549d52cc9a6a633e0a33193f588a62b88","tests/test_ensure.rs":"729ba5fb75959a511a0d1cda1b0f7f88af94aa88f8d251505af1c988e74ef8c6","tests/test_ffi.rs":"d0cb4c1d6d9154090982dee72ae3ebe05a5981f976058c3250f1c9da5a45edef","tests/test_fmt.rs":"17572596f257aac9aa2ec4620e292ca6a954128b94772bb948399fab53832e70","tests/test_macros.rs":"11f05010bc9b16319884c1286444100e30cddc2ecd1ffe5e0fd3fee5ffb32683","tests/test_repr.rs":"dbb9b04ddbe1ab31eb5331ea69f05bb3a147299da2275a3d4dcc92947b5591b9","tests/test_source.rs":"b80723cf635a4f8c4df21891b34bfab9ed2b2aa407e7a2f826d24e334cd5f88e","tests/ui/chained-comparison.rs":"6504b03d95b5acc232a7f4defc9f343b2be6733bf475fa0992e8e6545b912bd4","tests/ui/chained-comparison.stderr":"7f1d0a8c251b0ede2d30b3087ec157fc660945c97a642c4a5acf5a14ec58de34","tests/ui/empty-ensure.rs":"ab5bf37c846a0d689f26ce9257a27228411ed64154f9c950f1602d88a355d94b","tests/ui/empty-ensure.stderr":"345102cbef47310f2f4066a669199873a627ca4f1fcb885505c6e17d1fc95e88","tests/ui/must-use.rs":"fb59860b43f673bf4a430a6036ba463e95028844d8dd4243cfe5ebc7f2be582f","tests/ui/must-use.stderr":"c2848c5f254b4c061eea6714d9baf709924aba06619eaf2a8b3aee1266b75f9e","tests/ui/no-impl.rs":"fab6cbf2f6ea510b86f567dfb3b7c31250a9fd71ae5d110dbb9188be569ec593","tests/ui/no-impl.stderr":"d827fcf94a6ddc64f9ad3bfda8018276c2b91f5be4b833af81815e1b3a8a367c","tests/ui/temporary-value.rs":"4dcc96271b2403e6372cf4cfc813445e5ce4365fc6e156b6bc38274098499a70","tests/ui/temporary-value.stderr":"64e448b6759cf51d41b1360307a638452bbe53ffa706f93e4a503b712d7b89a8","tests/ui/wrong-interpolation.rs":"9c44d4674c2dccd27b9dedd03341346ec02d993b41793ee89b5755202e7e367e","tests/ui/wrong-interpolation.stderr":"301e60e2eb9401782c7dc0b3580613a4cb2aafd4cc8065734a630a62e1161aa5"},"package":"216261ddc8289130e551ddcd5ce8a064710c0d064a4d2895c67151c92b5443f6"} \ No newline at end of file
+{"files":{"Cargo.toml":"08309b6f7ceb1c1d34eef18cf248e38e752124505448f5d76505f0e0544c35eb","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"23f18e03dc49df91622fe2a76176497404e46ced8a715d9d2b67a7446571cca3","README.md":"62fc2a591c37e781f76fe4d89bcd964eca4fbde246bc43cd4e2fe9db2d30ee70","build.rs":"88bf7100143c79c0af683da7f28deaac031c9b9b213a6426560dc089b0ba45aa","rust-toolchain.toml":"6bbb61302978c736b2da03e4fb40e3beab908f85d533ab46fd541e637b5f3e0f","src/backtrace.rs":"5b4103a7d24d6f438a64b8cc0fafe28d55fc0ca090368174ce44d64e3940badd","src/chain.rs":"6edefc5f3c7d69683095862e54e3bb56faba5b3387bf2eeaed429da090007a0a","src/context.rs":"e129c580b5c2f3017dd977e4122a93f9fbc04b451e930d68f390f51e6be3bdcb","src/ensure.rs":"498bc9c7fb8b93168ed12f532cb97df6ccdda9ce25371586d7f5b1b1c98a14bf","src/error.rs":"e45d4dcfe64b1823b42fbf9bb260e6437987e8c2d51f92434db9d808b36e700a","src/fmt.rs":"c2d4aad6ce20625a70a7c091e3087b6a2c19a4a87c7a12edb4c98978307245ea","src/kind.rs":"332854c5eb07d44447c356a2e7dc585634b0da1ffbbfa81269c369deaefbc247","src/lib.rs":"ee210d5c7af74242360aa4651f9f58cf10784c2d77256bfed8ca6c796b0b54c2","src/macros.rs":"dd35f2ec2a0a25e4504fb04bcd42f6d0963bc0035aaaefc412f5ee1d78945fe1","src/ptr.rs":"f4e28bc9feba1e84160ca9d185008a51b5d72e168e6546f3e942f4258c361e19","src/wrapper.rs":"ff3ad72065a30cc32e9acb0614a30703c49c57b941a335c348b6439af684316b","tests/common/mod.rs":"f9088c2d7afafa64ff730b629272045b776bfafc2f5957508242da630635f2e1","tests/compiletest.rs":"022a8e400ef813d7ea1875b944549cee5125f6a995dc33e93b48cba3e1b57bd1","tests/drop/mod.rs":"08c3e553c1cc0d2dbd936fc45f4b5b1105057186affd6865e8d261e05f0f0646","tests/test_autotrait.rs":"981e792db353be2f14c7a1cabe43b5f1329c168cb7679077cc2be786a0920d48","tests/test_backtrace.rs":"0e50edbb33b6bd07ba89ff3db72fb7c688ba2a4371fccdbbb20309ab02948b6a","tests/test_boxed.rs":"6b26db0e2eb72afe9af7352ea820837aab90f8d486294616dd5dc34c1b94038c","tests/test_chain.rs":"d5e90e3eba58abc60d241d3aade39e0b8d4006d9a14f3cf015d3d925160b5812","tests/test_context.rs":"8409c53b328562c11e822bd6c3cd17e0d4d50b9bbb8fc3617333fd77303a6a33","tests/test_convert.rs":"7e7a8b4772a427a911014ac4d1083f9519000e786177f898808980dd9bdfde61","tests/test_downcast.rs":"797e69a72d125758c4c4897e5dc776d549d52cc9a6a633e0a33193f588a62b88","tests/test_ensure.rs":"c68ea8e3db9e887ce3a7314676e7ff5080aac0a37bc12cae9c6652dead93bcfa","tests/test_ffi.rs":"d0cb4c1d6d9154090982dee72ae3ebe05a5981f976058c3250f1c9da5a45edef","tests/test_fmt.rs":"17572596f257aac9aa2ec4620e292ca6a954128b94772bb948399fab53832e70","tests/test_macros.rs":"11f05010bc9b16319884c1286444100e30cddc2ecd1ffe5e0fd3fee5ffb32683","tests/test_repr.rs":"dbb9b04ddbe1ab31eb5331ea69f05bb3a147299da2275a3d4dcc92947b5591b9","tests/test_source.rs":"b80723cf635a4f8c4df21891b34bfab9ed2b2aa407e7a2f826d24e334cd5f88e","tests/ui/chained-comparison.rs":"6504b03d95b5acc232a7f4defc9f343b2be6733bf475fa0992e8e6545b912bd4","tests/ui/chained-comparison.stderr":"7f1d0a8c251b0ede2d30b3087ec157fc660945c97a642c4a5acf5a14ec58de34","tests/ui/empty-ensure.rs":"ab5bf37c846a0d689f26ce9257a27228411ed64154f9c950f1602d88a355d94b","tests/ui/empty-ensure.stderr":"315782f5f4246290fe190e3767b22c3dcaffaabc19c5ace0373537d53e765278","tests/ui/must-use.rs":"fb59860b43f673bf4a430a6036ba463e95028844d8dd4243cfe5ebc7f2be582f","tests/ui/must-use.stderr":"c2848c5f254b4c061eea6714d9baf709924aba06619eaf2a8b3aee1266b75f9e","tests/ui/no-impl.rs":"fab6cbf2f6ea510b86f567dfb3b7c31250a9fd71ae5d110dbb9188be569ec593","tests/ui/no-impl.stderr":"04415aeaa14995f47f06f35fb1f6971d332d2110aabca920c30ab0803d6a0a5e","tests/ui/temporary-value.rs":"4dcc96271b2403e6372cf4cfc813445e5ce4365fc6e156b6bc38274098499a70","tests/ui/temporary-value.stderr":"171f6c1c962503855480696e5d39e68946ec2a027b61a6f36ca1ad1b40265c5d","tests/ui/wrong-interpolation.rs":"9c44d4674c2dccd27b9dedd03341346ec02d993b41793ee89b5755202e7e367e","tests/ui/wrong-interpolation.stderr":"301e60e2eb9401782c7dc0b3580613a4cb2aafd4cc8065734a630a62e1161aa5"},"package":"2cb2f989d18dd141ab8ae82f64d1a8cdd37e0840f73a406896cf5e99502fab61"} \ No newline at end of file
diff --git a/vendor/anyhow/Cargo.toml b/vendor/anyhow/Cargo.toml
index b3d57a30f..6fca21780 100644
--- a/vendor/anyhow/Cargo.toml
+++ b/vendor/anyhow/Cargo.toml
@@ -11,9 +11,9 @@
[package]
edition = "2018"
-rust-version = "1.38"
+rust-version = "1.39"
name = "anyhow"
-version = "1.0.66"
+version = "1.0.68"
authors = ["David Tolnay <dtolnay@gmail.com>"]
description = "Flexible concrete Error type built on std::error::Error"
documentation = "https://docs.rs/anyhow"
@@ -36,6 +36,9 @@ rustdoc-args = [
"doc_cfg",
]
+[lib]
+doc-scrape-examples = false
+
[dependencies.backtrace]
version = "0.3.51"
optional = true
diff --git a/vendor/anyhow/README.md b/vendor/anyhow/README.md
index 77852792e..6380c1c04 100644
--- a/vendor/anyhow/README.md
+++ b/vendor/anyhow/README.md
@@ -4,7 +4,7 @@ Anyhow&ensp;¯\\\_(°ペ)\_/¯
[<img alt="github" src="https://img.shields.io/badge/github-dtolnay/anyhow-8da0cb?style=for-the-badge&labelColor=555555&logo=github" height="20">](https://github.com/dtolnay/anyhow)
[<img alt="crates.io" src="https://img.shields.io/crates/v/anyhow.svg?style=for-the-badge&color=fc8d62&logo=rust" height="20">](https://crates.io/crates/anyhow)
[<img alt="docs.rs" src="https://img.shields.io/badge/docs.rs-anyhow-66c2a5?style=for-the-badge&labelColor=555555&logo=docs.rs" height="20">](https://docs.rs/anyhow)
-[<img alt="build status" src="https://img.shields.io/github/workflow/status/dtolnay/anyhow/CI/master?style=for-the-badge" height="20">](https://github.com/dtolnay/anyhow/actions?query=branch%3Amaster)
+[<img alt="build status" src="https://img.shields.io/github/actions/workflow/status/dtolnay/anyhow/ci.yml?branch=master&style=for-the-badge" height="20">](https://github.com/dtolnay/anyhow/actions?query=branch%3Amaster)
This library provides [`anyhow::Error`][Error], a trait object based error type
for easy idiomatic error handling in Rust applications.
@@ -16,7 +16,7 @@ for easy idiomatic error handling in Rust applications.
anyhow = "1.0"
```
-*Compiler support: requires rustc 1.38+*
+*Compiler support: requires rustc 1.39+*
<br>
diff --git a/vendor/anyhow/src/context.rs b/vendor/anyhow/src/context.rs
index 238473e5c..9df86937b 100644
--- a/vendor/anyhow/src/context.rs
+++ b/vendor/anyhow/src/context.rs
@@ -4,7 +4,7 @@ use core::convert::Infallible;
use core::fmt::{self, Debug, Display, Write};
#[cfg(backtrace)]
-use std::any::Demand;
+use std::any::{Demand, Provider};
mod ext {
use super::*;
@@ -92,7 +92,12 @@ impl<T> Context<T, Infallible> for Option<T> {
where
C: Display + Send + Sync + 'static,
{
- self.ok_or_else(|| Error::from_display(context, backtrace!()))
+ // Not using ok_or_else to save 2 useless frames off the captured
+ // backtrace.
+ match self {
+ Some(ok) => Ok(ok),
+ None => Err(Error::from_display(context, backtrace!())),
+ }
}
fn with_context<C, F>(self, context: F) -> Result<T, Error>
@@ -100,7 +105,10 @@ impl<T> Context<T, Infallible> for Option<T> {
C: Display + Send + Sync + 'static,
F: FnOnce() -> C,
{
- self.ok_or_else(|| Error::from_display(context(), backtrace!()))
+ match self {
+ Some(ok) => Ok(ok),
+ None => Err(Error::from_display(context(), backtrace!())),
+ }
}
}
@@ -137,7 +145,7 @@ where
#[cfg(backtrace)]
fn provide<'a>(&'a self, demand: &mut Demand<'a>) {
- self.error.provide(demand);
+ StdError::provide(&self.error, demand);
}
}
@@ -151,8 +159,7 @@ where
#[cfg(backtrace)]
fn provide<'a>(&'a self, demand: &mut Demand<'a>) {
- demand.provide_ref(self.error.backtrace());
- self.error.provide(demand);
+ Provider::provide(&self.error, demand);
}
}
diff --git a/vendor/anyhow/src/lib.rs b/vendor/anyhow/src/lib.rs
index 583ab424e..3510d195e 100644
--- a/vendor/anyhow/src/lib.rs
+++ b/vendor/anyhow/src/lib.rs
@@ -210,7 +210,7 @@
//! will require an explicit `.map_err(Error::msg)` when working with a
//! non-Anyhow error type inside a function that returns Anyhow's error type.
-#![doc(html_root_url = "https://docs.rs/anyhow/1.0.66")]
+#![doc(html_root_url = "https://docs.rs/anyhow/1.0.68")]
#![cfg_attr(backtrace, feature(error_generic_member_access, provide_any))]
#![cfg_attr(doc_cfg, feature(doc_cfg))]
#![cfg_attr(not(feature = "std"), no_std)]
diff --git a/vendor/anyhow/tests/test_ensure.rs b/vendor/anyhow/tests/test_ensure.rs
index 6984c7d11..de867f7fe 100644
--- a/vendor/anyhow/tests/test_ensure.rs
+++ b/vendor/anyhow/tests/test_ensure.rs
@@ -5,7 +5,6 @@
clippy::ifs_same_cond,
clippy::items_after_statements,
clippy::let_and_return,
- clippy::let_underscore_drop,
clippy::match_bool,
clippy::never_loop,
clippy::overly_complex_bool_expr,
diff --git a/vendor/anyhow/tests/ui/empty-ensure.stderr b/vendor/anyhow/tests/ui/empty-ensure.stderr
index 91e0a9803..bf0229a2b 100644
--- a/vendor/anyhow/tests/ui/empty-ensure.stderr
+++ b/vendor/anyhow/tests/ui/empty-ensure.stderr
@@ -4,4 +4,9 @@ error: unexpected end of macro invocation
4 | ensure!();
| ^^^^^^^^^ missing tokens in macro arguments
|
+note: while trying to match meta-variable `$cond:expr`
+ --> src/ensure.rs
+ |
+ | ($cond:expr $(,)?) => {
+ | ^^^^^^^^^^
= note: this error originates in the macro `$crate::__parse_ensure` which comes from the expansion of the macro `ensure` (in Nightly builds, run with -Z macro-backtrace for more info)
diff --git a/vendor/anyhow/tests/ui/no-impl.stderr b/vendor/anyhow/tests/ui/no-impl.stderr
index dced9987e..1ddf76863 100644
--- a/vendor/anyhow/tests/ui/no-impl.stderr
+++ b/vendor/anyhow/tests/ui/no-impl.stderr
@@ -18,7 +18,7 @@ error[E0599]: the method `anyhow_kind` exists for reference `&Error`, but its tr
which is required by `&Error: anyhow::kind::AdhocKind`
`&Error: Into<anyhow::Error>`
which is required by `&Error: anyhow::kind::TraitKind`
-note: the following traits must be implemented
+note: the traits `Into` and `std::fmt::Display` must be implemented
--> $RUST/core/src/fmt/mod.rs
|
| pub trait Display {
diff --git a/vendor/anyhow/tests/ui/temporary-value.stderr b/vendor/anyhow/tests/ui/temporary-value.stderr
index 4e4115fc3..dc27c4981 100644
--- a/vendor/anyhow/tests/ui/temporary-value.stderr
+++ b/vendor/anyhow/tests/ui/temporary-value.stderr
@@ -4,6 +4,6 @@ error[E0716]: temporary value dropped while borrowed
4 | let _ = anyhow!(&String::new());
| ---------^^^^^^^^^^^^^-
| | |
- | | creates a temporary which is freed while still in use
+ | | creates a temporary value which is freed while still in use
| temporary value is freed at the end of this statement
| argument requires that borrow lasts for `'static`
diff --git a/vendor/backtrace/.cargo-checksum.json b/vendor/backtrace/.cargo-checksum.json
index 434618119..e94768666 100644
--- a/vendor/backtrace/.cargo-checksum.json
+++ b/vendor/backtrace/.cargo-checksum.json
@@ -1 +1 @@
-{"files":{"Cargo.lock":"b0096194daaeffd2e4c7577e0549b74f3d40183ef2abc83d29b9fe2faca882a7","Cargo.toml":"94e809a91c1cae05980cc022d6449db2e9029f18aa33c8151d7fb8a738f443a0","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"378f5840b258e2779c39418f3f2d7b2ba96f1c7917dd6be0713f88305dbda397","README.md":"6007ea91612793f8c77d499d2065acd2255fc5f3c3268fd8bd1ae5f7bb40d6de","benches/benchmarks.rs":"029b78bb79052ec940eecfd18067b743925189202fc16015d3c4c25b05eb6d67","build.rs":"8d5e860da109f86c67596b10b5613ff6d19f9d24c2970f491a55261fb1973692","ci/android-ndk.sh":"89fafa41d08ff477f949bfc163d04d1eb34fdee370f7a695cfba4ef34c164a55","ci/android-sdk.sh":"69a953f70f32064d1d2a57c7082a50336b90a12d10c75e5416dbb1d6d718016c","ci/debuglink-docker.sh":"3a16131df8c69fef37331cb6f01a6623d169177474f475159d05bab61df077a9","ci/debuglink.sh":"164a961b930de8c9aedf45a11076c3d41081846a8e6a9566ba2b6ad615179e0b","ci/docker/aarch64-linux-android/Dockerfile":"1058f2ee9cf74b4c51a489e62544bea94c6cd537ad5c1b056f3e4b262f7e09f2","ci/docker/aarch64-unknown-linux-gnu/Dockerfile":"a7b7aae0d8e2f826cf1c6c7c3160f8e5e9a30478b83c394b6575ce15b0ff0802","ci/docker/arm-linux-androideabi/Dockerfile":"12f8c62f0750d3581292b23309f5aef15492c946a73e55df13bc345de5ca576e","ci/docker/arm-unknown-linux-gnueabihf/Dockerfile":"5156382ff639b11801c1bd7ddc6e03e8834505a74ecf7160e92182603cd5d96f","ci/docker/armv7-linux-androideabi/Dockerfile":"7c582c2a4b162b147deada3194a30185ccb7a01215f97990cd1a5a3460c30fb9","ci/docker/armv7-unknown-linux-gnueabihf/Dockerfile":"4aaceef14ba700ea3719fe30fcb46f1bb154a47aa52cdb64fa6ed7eff96d6c85","ci/docker/i586-unknown-linux-gnu/Dockerfile":"0816c89b79a74be7ccfc34e95cd718ce29a8698a2ab56903b4b0712470f5c8bb","ci/docker/i686-linux-android/Dockerfile":"18957e8dad4c6d9c8ad561f846e20f6e2186ff7a8421f2a0089793b510f66fe2","ci/docker/i686-unknown-linux-gnu/Dockerfile":"0816c89b79a74be7ccfc34e95cd718ce29a8698a2ab56903b4b0712470f5c8bb","ci/docker/powerpc64-unknown-linux-gnu/Dockerfile":"270de99179c925e6284a8283fdb4e40a8c813a569b24930d6cfe79a4c470ab61","ci/docker/s390x-unknown-linux-gnu/Dockerfile":"4aa8ca641efd2f1937ef669eda2f3e357b2fb926911722b3afc6cf25ce4bcac2","ci/docker/x86_64-linux-android/Dockerfile":"e6d6fb37041a9d6fc6771be1ae8d1eaa506a1dc8796170c1ffcc3d6dd043bed2","ci/docker/x86_64-pc-windows-gnu/Dockerfile":"654988c5c008610f90d5159a8dd0ab6fd491e9c0d16ad65b03ef53f694a5400c","ci/docker/x86_64-unknown-linux-gnu/Dockerfile":"9f89f080551fff6678b1efcc0925fc8c16316f69cdd150e89f9e95cdab583510","ci/docker/x86_64-unknown-linux-musl/Dockerfile":"4db3cb7d315588f363eb9f377bf1c27d8e8886c07b6c0d0c5cf7ee91114a718b","ci/run-docker.sh":"70760696a608b0d89eb3dcc4b08f176d709dd9f98e50297f2b7e0bb9b0f3b458","ci/run.sh":"0bb5c8256019779f3e1db20fcc2c01416ffd4679428f3e395ef5f3e55d2d642c","ci/runtest-android.rs":"be2e49bb296b92a8e3643a6c0a70917fe7b130fa43b71a29c4e7514f45c00e7e","examples/backtrace.rs":"5da0c95ccebfaffbbe7b5a92b0e488017dc375cbb5b8fb2b7712dd65b2dfb2ba","examples/raw.rs":"575ec6037f597ba7ab0eaf9dd699fadfabef918ba2affea7dc20cdbde55de5ec","src/android-api.c":"b75f16de578451464f49b83dc817b76aa9a0be0d86ea71d1659cc78f99e94fbd","src/backtrace/dbghelp.rs":"ea2f175d6c62259d86e7e9bb04328e03657d7259d4459aab70734f1cf1cd9d72","src/backtrace/libunwind.rs":"65373ce7bd87abc411b4307bd41679f9176987170b3b627abe0f0bb1625ff685","src/backtrace/miri.rs":"630faf9919d3ced8d75095cea30fde6c1ed7f0ad135dee8c81a3d7614b55cc11","src/backtrace/mod.rs":"b301e6b7da4f3811c5255c2f1fdb83f4ab97acfa1647d998d8455614ae90ddaf","src/backtrace/noop.rs":"a8550b70b3c83f6852a1dba83cf97b1325238b5aa3ce7b35437e9382cdafd924","src/capture.rs":"8701657803f04ea9e0b9dd6a4ca619761edb8a42cfd2f7c9c9e4ee31d9357159","src/dbghelp.rs":"40891588891fe48c16263374a36092ac3e67ddf4f756b880839f31dfcb80b7c4","src/lib.rs":"03f2a0f2524cb2078e2f28959c3eb1625ff400d3e23eeb7d3b73d86c012979b2","src/print.rs":"766affbd9d2242a81d85067413dd95b807425a6df2fffb17a4eacc5f606d4200","src/print/fuchsia.rs":"de45f55032e05fdc1fd55224910158f8c64a705494103a29c7e2680536e76e40","src/symbolize/dbghelp.rs":"58aeda764a27702e0abb3af62bae8a162d8b6cb8c80ffd141ee794d81a8ace15","src/symbolize/gimli.rs":"062afb232fdd1550ae613de79385365b03aa50a721794666d7856401b7f44e5a","src/symbolize/gimli/coff.rs":"d3f4a274bd3b2ed81d114a9326630c019f682ca91aac6ec31e660f420c35b064","src/symbolize/gimli/elf.rs":"3445558fc1feed60165af55e07847c59c3eca5e4031f50b04329fc5be36eb057","src/symbolize/gimli/libs_dl_iterate_phdr.rs":"8f7dabbdff97e5a24f0d5b3670469840666a91e9971ac352abeb4e96d98a2a6c","src/symbolize/gimli/libs_haiku.rs":"0a0d4b37145e898f7068cadacccf362d8216e463e7026af2ce38d75ebfd74bea","src/symbolize/gimli/libs_illumos.rs":"523e96272b46bdaab2abb0dd0201cb8032bf86558cbed986a20d7e2cc02fa8be","src/symbolize/gimli/libs_libnx.rs":"4116eceadb2d9916d4f5602712eacec647f185d4c53c723aced8de5fc471b14d","src/symbolize/gimli/libs_macos.rs":"a0d6edf8f3af23523d1a63a12ef6a6dd9ad1057b2cb20cc405da0544daba5389","src/symbolize/gimli/libs_windows.rs":"6459f8610ca1a0fd7456539ec604f5276c94b3d0d7331357eaed338e49220a02","src/symbolize/gimli/macho.rs":"a725d85566438499ecfb0ac06193c3153a2fa1b533f360d55c63dea386d1920d","src/symbolize/gimli/mmap_fake.rs":"9564fcf47000e70d521b31518e205c8e6ee09b7410fb1eb1e452721757ff54ba","src/symbolize/gimli/mmap_unix.rs":"8159a4a807bd5692412ba1a280bb36ab942c06e904f37a92e2545f0b4211308a","src/symbolize/gimli/mmap_windows.rs":"1ca715317c1054968d92350438b293f800bae2174f395b20bc43a633d757fe8f","src/symbolize/gimli/stash.rs":"67d01016b17ca4c0adbb0827da9b83fde5f79ccc89db3e4fd769ab03c1248d8e","src/symbolize/miri.rs":"f5201cc8a7de24ad3424d2472cb0af59cd28563d09cc0c21e998f4cee4367ade","src/symbolize/mod.rs":"a7177603810aca1cd9cd4a59027a1dd2c792dc9d345435b5dc866eb7c8b66baf","src/symbolize/noop.rs":"5d4432079b8ae2b9382945a57ae43df57bb4b7ed2e5956d4167e051a44567388","src/types.rs":"f43c94b99d57ca66a5cfe939a46016c95b2d69d82695fb52480f7a3e5b344fd9","src/windows.rs":"46f02837a2e6b404a035993f2e1f03cdfc1a5a872c1feb92926566a31138d273","tests/accuracy/auxiliary.rs":"71d2238da401042e007ef5ee20336d6834724bae96d93c8c52d11a5a332d7d34","tests/accuracy/main.rs":"f8e42aeeb50b35fca380db2e9fe52820cc0bc3133167289c5710e3290701e78e","tests/concurrent-panics.rs":"7696676e46a1c50a3a88446fdc59c0dedfb81ded24d77ec725f7cc101a5d8fe6","tests/long_fn_name.rs":"ebef58e34543ed4d47048faa9b6525f68fc71e12255af734523a513c5d4baa6f","tests/skip_inner_frames.rs":"7560fe59e83e4b234789c448da5504d3dd9065f9ad1b2615f12606f9112df4e0","tests/smoke.rs":"33014495f9158aea2d0ee2ee3335ffe82105c7ed894f96eaf7d23845a60f7439"},"package":"cab84319d616cfb654d03394f38ab7e6f0919e181b1b57e1fd15e7fb4077d9a7"} \ No newline at end of file
+{"files":{"Cargo.lock":"7d3b2926febbfe2d3ae525bf139703fa9d614cad0836d0e88a176352787a8151","Cargo.toml":"01600b69a4b1967a6f307a698f576a86308d39c4e571ff398235a88204b7b220","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"378f5840b258e2779c39418f3f2d7b2ba96f1c7917dd6be0713f88305dbda397","README.md":"6007ea91612793f8c77d499d2065acd2255fc5f3c3268fd8bd1ae5f7bb40d6de","benches/benchmarks.rs":"029b78bb79052ec940eecfd18067b743925189202fc16015d3c4c25b05eb6d67","build.rs":"8d5e860da109f86c67596b10b5613ff6d19f9d24c2970f491a55261fb1973692","ci/android-ndk.sh":"89fafa41d08ff477f949bfc163d04d1eb34fdee370f7a695cfba4ef34c164a55","ci/android-sdk.sh":"69a953f70f32064d1d2a57c7082a50336b90a12d10c75e5416dbb1d6d718016c","ci/debuglink-docker.sh":"3a16131df8c69fef37331cb6f01a6623d169177474f475159d05bab61df077a9","ci/debuglink.sh":"164a961b930de8c9aedf45a11076c3d41081846a8e6a9566ba2b6ad615179e0b","ci/docker/aarch64-linux-android/Dockerfile":"1058f2ee9cf74b4c51a489e62544bea94c6cd537ad5c1b056f3e4b262f7e09f2","ci/docker/aarch64-unknown-linux-gnu/Dockerfile":"a7b7aae0d8e2f826cf1c6c7c3160f8e5e9a30478b83c394b6575ce15b0ff0802","ci/docker/arm-linux-androideabi/Dockerfile":"12f8c62f0750d3581292b23309f5aef15492c946a73e55df13bc345de5ca576e","ci/docker/arm-unknown-linux-gnueabihf/Dockerfile":"5156382ff639b11801c1bd7ddc6e03e8834505a74ecf7160e92182603cd5d96f","ci/docker/armv7-linux-androideabi/Dockerfile":"7c582c2a4b162b147deada3194a30185ccb7a01215f97990cd1a5a3460c30fb9","ci/docker/armv7-unknown-linux-gnueabihf/Dockerfile":"4aaceef14ba700ea3719fe30fcb46f1bb154a47aa52cdb64fa6ed7eff96d6c85","ci/docker/i586-unknown-linux-gnu/Dockerfile":"0816c89b79a74be7ccfc34e95cd718ce29a8698a2ab56903b4b0712470f5c8bb","ci/docker/i686-linux-android/Dockerfile":"18957e8dad4c6d9c8ad561f846e20f6e2186ff7a8421f2a0089793b510f66fe2","ci/docker/i686-unknown-linux-gnu/Dockerfile":"0816c89b79a74be7ccfc34e95cd718ce29a8698a2ab56903b4b0712470f5c8bb","ci/docker/powerpc64-unknown-linux-gnu/Dockerfile":"270de99179c925e6284a8283fdb4e40a8c813a569b24930d6cfe79a4c470ab61","ci/docker/s390x-unknown-linux-gnu/Dockerfile":"4aa8ca641efd2f1937ef669eda2f3e357b2fb926911722b3afc6cf25ce4bcac2","ci/docker/x86_64-linux-android/Dockerfile":"e6d6fb37041a9d6fc6771be1ae8d1eaa506a1dc8796170c1ffcc3d6dd043bed2","ci/docker/x86_64-pc-windows-gnu/Dockerfile":"654988c5c008610f90d5159a8dd0ab6fd491e9c0d16ad65b03ef53f694a5400c","ci/docker/x86_64-unknown-linux-gnu/Dockerfile":"9f89f080551fff6678b1efcc0925fc8c16316f69cdd150e89f9e95cdab583510","ci/docker/x86_64-unknown-linux-musl/Dockerfile":"4db3cb7d315588f363eb9f377bf1c27d8e8886c07b6c0d0c5cf7ee91114a718b","ci/run-docker.sh":"70760696a608b0d89eb3dcc4b08f176d709dd9f98e50297f2b7e0bb9b0f3b458","ci/run.sh":"0bb5c8256019779f3e1db20fcc2c01416ffd4679428f3e395ef5f3e55d2d642c","ci/runtest-android.rs":"be2e49bb296b92a8e3643a6c0a70917fe7b130fa43b71a29c4e7514f45c00e7e","examples/backtrace.rs":"5da0c95ccebfaffbbe7b5a92b0e488017dc375cbb5b8fb2b7712dd65b2dfb2ba","examples/raw.rs":"575ec6037f597ba7ab0eaf9dd699fadfabef918ba2affea7dc20cdbde55de5ec","src/android-api.c":"b75f16de578451464f49b83dc817b76aa9a0be0d86ea71d1659cc78f99e94fbd","src/backtrace/dbghelp.rs":"ea2f175d6c62259d86e7e9bb04328e03657d7259d4459aab70734f1cf1cd9d72","src/backtrace/libunwind.rs":"65373ce7bd87abc411b4307bd41679f9176987170b3b627abe0f0bb1625ff685","src/backtrace/miri.rs":"c0dcb1e430eea92fcbad3e293124010f39c1f8ff1bbbf1a0275c53b05880cd5f","src/backtrace/mod.rs":"b301e6b7da4f3811c5255c2f1fdb83f4ab97acfa1647d998d8455614ae90ddaf","src/backtrace/noop.rs":"a8550b70b3c83f6852a1dba83cf97b1325238b5aa3ce7b35437e9382cdafd924","src/capture.rs":"8701657803f04ea9e0b9dd6a4ca619761edb8a42cfd2f7c9c9e4ee31d9357159","src/dbghelp.rs":"40891588891fe48c16263374a36092ac3e67ddf4f756b880839f31dfcb80b7c4","src/lib.rs":"03f2a0f2524cb2078e2f28959c3eb1625ff400d3e23eeb7d3b73d86c012979b2","src/print.rs":"7bae8abae6947d6d0e57ff9c834d1d4d0b528a6d7e6424e7ad9a5ac557cf3e08","src/print/fuchsia.rs":"de45f55032e05fdc1fd55224910158f8c64a705494103a29c7e2680536e76e40","src/symbolize/dbghelp.rs":"58aeda764a27702e0abb3af62bae8a162d8b6cb8c80ffd141ee794d81a8ace15","src/symbolize/gimli.rs":"f43374c89f12095a99431de0f758a3414dfd2f1e84bfa35897ce8afdaf006041","src/symbolize/gimli/coff.rs":"d3f4a274bd3b2ed81d114a9326630c019f682ca91aac6ec31e660f420c35b064","src/symbolize/gimli/elf.rs":"3445558fc1feed60165af55e07847c59c3eca5e4031f50b04329fc5be36eb057","src/symbolize/gimli/libs_dl_iterate_phdr.rs":"bc64242857dd82288d6e7d6b183e651d05ab7bc4f037f19b9e42719f04fc2c83","src/symbolize/gimli/libs_haiku.rs":"0a0d4b37145e898f7068cadacccf362d8216e463e7026af2ce38d75ebfd74bea","src/symbolize/gimli/libs_illumos.rs":"523e96272b46bdaab2abb0dd0201cb8032bf86558cbed986a20d7e2cc02fa8be","src/symbolize/gimli/libs_libnx.rs":"4116eceadb2d9916d4f5602712eacec647f185d4c53c723aced8de5fc471b14d","src/symbolize/gimli/libs_macos.rs":"c24cb480ae029b350325873ac4358104e5943ad61b62eb22bb6b65b2f05bbd29","src/symbolize/gimli/libs_windows.rs":"6459f8610ca1a0fd7456539ec604f5276c94b3d0d7331357eaed338e49220a02","src/symbolize/gimli/macho.rs":"47a970c23443f322e79bf54cf7f11d9990516b17fbad7c893f20bd56a22083af","src/symbolize/gimli/mmap_fake.rs":"9564fcf47000e70d521b31518e205c8e6ee09b7410fb1eb1e452721757ff54ba","src/symbolize/gimli/mmap_unix.rs":"8159a4a807bd5692412ba1a280bb36ab942c06e904f37a92e2545f0b4211308a","src/symbolize/gimli/mmap_windows.rs":"1ca715317c1054968d92350438b293f800bae2174f395b20bc43a633d757fe8f","src/symbolize/gimli/parse_running_mmaps_unix.rs":"1e25b842b979b745bf3e22e8ce6f13b242f2fb52a75d8e865bad9538e44b76a3","src/symbolize/gimli/stash.rs":"67d01016b17ca4c0adbb0827da9b83fde5f79ccc89db3e4fd769ab03c1248d8e","src/symbolize/miri.rs":"f5201cc8a7de24ad3424d2472cb0af59cd28563d09cc0c21e998f4cee4367ade","src/symbolize/mod.rs":"a7177603810aca1cd9cd4a59027a1dd2c792dc9d345435b5dc866eb7c8b66baf","src/symbolize/noop.rs":"5d4432079b8ae2b9382945a57ae43df57bb4b7ed2e5956d4167e051a44567388","src/types.rs":"f43c94b99d57ca66a5cfe939a46016c95b2d69d82695fb52480f7a3e5b344fd9","src/windows.rs":"b0bbbf4088021fd646024ad01de1a60bf12bf62b6b744f0f5952681f77cd49e6","tests/accuracy/auxiliary.rs":"71d2238da401042e007ef5ee20336d6834724bae96d93c8c52d11a5a332d7d34","tests/accuracy/main.rs":"f8e42aeeb50b35fca380db2e9fe52820cc0bc3133167289c5710e3290701e78e","tests/common/mod.rs":"733101288a48cf94d5a87a1957724deaf2650c3e4e8aa0190a4a7db62aa90d01","tests/concurrent-panics.rs":"b60279ad5c4fb9b2754807f35179cbc8fbd7acbe6e92ac6d0f416ae75db38705","tests/current-exe-mismatch.rs":"b44a885a655f761eb15d4a47bdfff4332f9a1f88105b7aed9ea0b052e385615f","tests/long_fn_name.rs":"ebef58e34543ed4d47048faa9b6525f68fc71e12255af734523a513c5d4baa6f","tests/skip_inner_frames.rs":"6c03cd0ad9facf0aa81e59cf970504785b6ada9993a2dfc2aea0b18b79419aeb","tests/smoke.rs":"33014495f9158aea2d0ee2ee3335ffe82105c7ed894f96eaf7d23845a60f7439"},"package":"233d376d6d185f2a3093e58f283f60f880315b6c60075b01f36b3b85154564ca"} \ No newline at end of file
diff --git a/vendor/backtrace/Cargo.lock b/vendor/backtrace/Cargo.lock
index 6eee92255..14da4f7d5 100644
--- a/vendor/backtrace/Cargo.lock
+++ b/vendor/backtrace/Cargo.lock
@@ -4,9 +4,9 @@ version = 3
[[package]]
name = "addr2line"
-version = "0.17.0"
+version = "0.19.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b9ecd88a8c8378ca913a680cd98f0f13ac67383d35993f86c90a70e3f137816b"
+checksum = "a76fd60b23679b7d19bd066031410fb7e458ccc5e958eb5c325888ce4baedc97"
dependencies = [
"gimli",
]
@@ -19,7 +19,7 @@ checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
[[package]]
name = "backtrace"
-version = "0.3.66"
+version = "0.3.67"
dependencies = [
"addr2line",
"cc",
@@ -37,9 +37,9 @@ dependencies = [
[[package]]
name = "cc"
-version = "1.0.73"
+version = "1.0.77"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11"
+checksum = "e9f73505338f7d905b19d18738976aae232eb46b8efc15554ffc56deb5d9ebe4"
[[package]]
name = "cfg-if"
@@ -49,30 +49,30 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "cpp_demangle"
-version = "0.3.5"
+version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "eeaa953eaad386a53111e47172c2fedba671e5684c8dd601a5f474f4f118710f"
+checksum = "b446fd40bcc17eddd6a4a78f24315eb90afdb3334999ddfd4909985c47722442"
dependencies = [
"cfg-if",
]
[[package]]
name = "gimli"
-version = "0.26.1"
+version = "0.27.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "78cc372d058dcf6d5ecd98510e7fbc9e5aec4d21de70f65fea8fecebcd881bd4"
+checksum = "dec7af912d60cdbd3677c1af9352ebae6fb8394d165568a2234df0fa00f87793"
[[package]]
name = "libc"
-version = "0.2.126"
+version = "0.2.138"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "349d5a591cd28b49e1d1037471617a32ddcda5731b99419008085f72d5a53836"
+checksum = "db6d7e329c562c5dfab7a46a2afabc8b987ab9a4834c9d1ca04dc54c1546cef8"
[[package]]
name = "libloading"
-version = "0.7.3"
+version = "0.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "efbc0f03f9a775e9f6aed295c6a1ba2253c5757a9e03d55c6caa46a681abcddd"
+checksum = "b67380fd3b2fbe7527a606e18729d21c6f3951633d0500574c4dc22d2d638b9f"
dependencies = [
"cfg-if",
"winapi",
@@ -86,36 +86,36 @@ checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
[[package]]
name = "miniz_oxide"
-version = "0.5.3"
+version = "0.6.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6f5c75688da582b8ffc1f1799e9db273f32133c49e048f614d22ec3256773ccc"
+checksum = "b275950c28b37e794e8c55d88aeb5e139d0ce23fdbbeda68f8d7174abdf9e8fa"
dependencies = [
"adler",
]
[[package]]
name = "object"
-version = "0.29.0"
+version = "0.30.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "21158b2c33aa6d4561f1c0a6ea283ca92bc54802a93b263e910746d679a7eb53"
+checksum = "239da7f290cfa979f43f85a8efeee9a8a76d0827c356d37f9d3d7254d6b537fb"
dependencies = [
"memchr",
]
[[package]]
name = "proc-macro2"
-version = "1.0.40"
+version = "1.0.47"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dd96a1e8ed2596c337f8eae5f24924ec83f5ad5ab21ea8e455d3566c69fbcaf7"
+checksum = "5ea3d908b0e36316caf9e9e2c4625cdde190a7e6f440d794667ed17a1855e725"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
-version = "1.0.20"
+version = "1.0.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3bcdf212e9776fbcb2d23ab029360416bb1706b1aea2d1a5ba002727cbcab804"
+checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179"
dependencies = [
"proc-macro2",
]
@@ -134,18 +134,18 @@ checksum = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda"
[[package]]
name = "serde"
-version = "1.0.138"
+version = "1.0.150"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1578c6245786b9d168c5447eeacfb96856573ca56c9d68fdcf394be134882a47"
+checksum = "e326c9ec8042f1b5da33252c8a37e9ffbd2c9bef0155215b6e6c80c790e05f91"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
-version = "1.0.138"
+version = "1.0.150"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "023e9b1467aef8a10fb88f25611870ada9800ef7e22afce356bb0d2387b6f27c"
+checksum = "42a3df25b0713732468deadad63ab9da1f1fd75a48a15024b50363f128db627e"
dependencies = [
"proc-macro2",
"quote",
@@ -154,9 +154,9 @@ dependencies = [
[[package]]
name = "syn"
-version = "1.0.98"
+version = "1.0.105"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c50aef8a904de4c23c788f104b7dddc7d6f79c647c7c8ce4cc8f73eb0ca773dd"
+checksum = "60b9b43d45702de4c839cb9b51d9f529c5dd26a4aff255b42b1ebc03e88ee908"
dependencies = [
"proc-macro2",
"quote",
@@ -165,9 +165,9 @@ dependencies = [
[[package]]
name = "unicode-ident"
-version = "1.0.1"
+version = "1.0.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5bd2fe26506023ed7b5e1e315add59d6f584c621d037f9368fea9cfb988f368c"
+checksum = "6ceab39d59e4c9499d4e5a8ee0e2735b891bb7308ac83dfb4e80cad195c9f6f3"
[[package]]
name = "winapi"
diff --git a/vendor/backtrace/Cargo.toml b/vendor/backtrace/Cargo.toml
index 641181528..96f41466b 100644
--- a/vendor/backtrace/Cargo.toml
+++ b/vendor/backtrace/Cargo.toml
@@ -12,7 +12,7 @@
[package]
edition = "2018"
name = "backtrace"
-version = "0.3.66"
+version = "0.3.67"
authors = ["The Rust Project Developers"]
build = "build.rs"
autoexamples = true
@@ -23,7 +23,7 @@ A library to acquire a stack trace (backtrace) at runtime in a Rust program.
homepage = "https://github.com/rust-lang/backtrace-rs"
documentation = "https://docs.rs/backtrace"
readme = "README.md"
-license = "MIT/Apache-2.0"
+license = "MIT OR Apache-2.0"
repository = "https://github.com/rust-lang/backtrace-rs"
[[example]]
@@ -57,15 +57,21 @@ name = "concurrent-panics"
harness = false
required-features = ["std"]
+[[test]]
+name = "current-exe-mismatch"
+harness = false
+required-features = ["std"]
+
[dependencies.addr2line]
-version = "0.17.0"
+version = "0.19.0"
default-features = false
[dependencies.cfg-if]
version = "1.0"
[dependencies.cpp_demangle]
-version = "0.3.0"
+version = "0.4.0"
+features = ["alloc"]
optional = true
default-features = false
@@ -74,11 +80,11 @@ version = "0.2.94"
default-features = false
[dependencies.miniz_oxide]
-version = "0.5.0"
+version = "0.6.0"
default-features = false
[dependencies.object]
-version = "0.29.0"
+version = "0.30.0"
features = [
"read_core",
"elf",
diff --git a/vendor/backtrace/src/backtrace/miri.rs b/vendor/backtrace/src/backtrace/miri.rs
index 9a5f65b80..f8c496428 100644
--- a/vendor/backtrace/src/backtrace/miri.rs
+++ b/vendor/backtrace/src/backtrace/miri.rs
@@ -91,7 +91,7 @@ pub fn resolve_addr(ptr: *mut c_void) -> Frame {
}
}
-pub unsafe fn trace_unsynchronized<F: FnMut(&super::Frame) -> bool>(mut cb: F) {
+unsafe fn trace_unsynchronized<F: FnMut(&super::Frame) -> bool>(mut cb: F) {
let len = miri_backtrace_size(0);
let mut frames = Vec::with_capacity(len);
@@ -102,6 +102,8 @@ pub unsafe fn trace_unsynchronized<F: FnMut(&super::Frame) -> bool>(mut cb: F) {
for ptr in frames.iter() {
let frame = resolve_addr(*ptr as *mut c_void);
- cb(&super::Frame { inner: frame });
+ if !cb(&super::Frame { inner: frame }) {
+ return;
+ }
}
}
diff --git a/vendor/backtrace/src/print.rs b/vendor/backtrace/src/print.rs
index cc677122a..174d8ae5c 100644
--- a/vendor/backtrace/src/print.rs
+++ b/vendor/backtrace/src/print.rs
@@ -135,7 +135,7 @@ impl BacktraceFrameFmt<'_, '_, '_> {
symbol.name(),
// TODO: this isn't great that we don't end up printing anything
// with non-utf8 filenames. Thankfully almost everything is utf8 so
- // this shouldn't be too too bad.
+ // this shouldn't be too bad.
symbol
.filename()
.and_then(|p| Some(BytesOrWideString::Bytes(p.to_str()?.as_bytes()))),
diff --git a/vendor/backtrace/src/symbolize/gimli.rs b/vendor/backtrace/src/symbolize/gimli.rs
index 5f10122dd..cd4cec58c 100644
--- a/vendor/backtrace/src/symbolize/gimli.rs
+++ b/vendor/backtrace/src/symbolize/gimli.rs
@@ -184,6 +184,8 @@ cfg_if::cfg_if! {
))] {
mod libs_dl_iterate_phdr;
use libs_dl_iterate_phdr::native_libraries;
+ #[path = "gimli/parse_running_mmaps_unix.rs"]
+ mod parse_running_mmaps;
} else if #[cfg(target_env = "libnx")] {
mod libs_libnx;
use libs_libnx::native_libraries;
diff --git a/vendor/backtrace/src/symbolize/gimli/libs_dl_iterate_phdr.rs b/vendor/backtrace/src/symbolize/gimli/libs_dl_iterate_phdr.rs
index a011e6080..9f0304ce8 100644
--- a/vendor/backtrace/src/symbolize/gimli/libs_dl_iterate_phdr.rs
+++ b/vendor/backtrace/src/symbolize/gimli/libs_dl_iterate_phdr.rs
@@ -17,6 +17,20 @@ pub(super) fn native_libraries() -> Vec<Library> {
return ret;
}
+fn infer_current_exe(base_addr: usize) -> OsString {
+ if let Ok(entries) = super::parse_running_mmaps::parse_maps() {
+ let opt_path = entries
+ .iter()
+ .find(|e| e.ip_matches(base_addr) && e.pathname().len() > 0)
+ .map(|e| e.pathname())
+ .cloned();
+ if let Some(path) = opt_path {
+ return path;
+ }
+ }
+ env::current_exe().map(|e| e.into()).unwrap_or_default()
+}
+
// `info` should be a valid pointers.
// `vec` should be a valid pointer to a `std::Vec`.
unsafe extern "C" fn callback(
@@ -28,8 +42,12 @@ unsafe extern "C" fn callback(
let libs = &mut *(vec as *mut Vec<Library>);
let is_main_prog = info.dlpi_name.is_null() || *info.dlpi_name == 0;
let name = if is_main_prog {
+ // The man page for dl_iterate_phdr says that the first object visited by
+ // callback is the main program; so the first time we encounter a
+ // nameless entry, we can assume its the main program and try to infer its path.
+ // After that, we cannot continue that assumption, and we use an empty string.
if libs.is_empty() {
- env::current_exe().map(|e| e.into()).unwrap_or_default()
+ infer_current_exe(info.dlpi_addr as usize)
} else {
OsString::new()
}
diff --git a/vendor/backtrace/src/symbolize/gimli/libs_macos.rs b/vendor/backtrace/src/symbolize/gimli/libs_macos.rs
index 17703b88a..438bbff6f 100644
--- a/vendor/backtrace/src/symbolize/gimli/libs_macos.rs
+++ b/vendor/backtrace/src/symbolize/gimli/libs_macos.rs
@@ -113,8 +113,8 @@ fn native_library(i: u32) -> Option<Library> {
// file offset 0 with a nonzero size. For whatever reason when this
// is present it appears to mean that the symbol table is relative
// to just the vmaddr slide for the library. If it's *not* present
- // then the symbol table is relative to the the vmaddr slide plus
- // the segment's stated address.
+ // then the symbol table is relative to the vmaddr slide plus the
+ // segment's stated address.
//
// To handle this situation if we *don't* find a text section at
// file offset zero then we increase the bias by the first text
diff --git a/vendor/backtrace/src/symbolize/gimli/macho.rs b/vendor/backtrace/src/symbolize/gimli/macho.rs
index ec5673843..adea97a09 100644
--- a/vendor/backtrace/src/symbolize/gimli/macho.rs
+++ b/vendor/backtrace/src/symbolize/gimli/macho.rs
@@ -13,8 +13,8 @@ type MachSection = <Mach as MachHeader>::Section;
type MachNlist = <Mach as MachHeader>::Nlist;
impl Mapping {
- // The loading path for OSX is is so different we just have a completely
- // different implementation of the function here. On OSX we need to go
+ // The loading path for macOS is so different we just have a completely
+ // different implementation of the function here. On macOS we need to go
// probing the filesystem for a bunch of files.
pub fn new(path: &Path) -> Option<Mapping> {
// First up we need to load the unique UUID which is stored in the macho
diff --git a/vendor/backtrace/src/symbolize/gimli/parse_running_mmaps_unix.rs b/vendor/backtrace/src/symbolize/gimli/parse_running_mmaps_unix.rs
new file mode 100644
index 000000000..a196ffcfb
--- /dev/null
+++ b/vendor/backtrace/src/symbolize/gimli/parse_running_mmaps_unix.rs
@@ -0,0 +1,242 @@
+// Note: This file is only currently used on targets that call out to the code
+// in `mod libs_dl_iterate_phdr` (e.g. linux, freebsd, ...); it may be more
+// general purpose, but it hasn't been tested elsewhere.
+
+use super::mystd::fs::File;
+use super::mystd::io::Read;
+use super::mystd::str::FromStr;
+use super::{OsString, String, Vec};
+
+#[derive(PartialEq, Eq, Debug)]
+pub(super) struct MapsEntry {
+ /// start (inclusive) and limit (exclusive) of address range.
+ address: (usize, usize),
+ /// The perms field are the permissions for the entry
+ ///
+ /// r = read
+ /// w = write
+ /// x = execute
+ /// s = shared
+ /// p = private (copy on write)
+ perms: [char; 4],
+ /// Offset into the file (or "whatever").
+ offset: usize,
+ /// device (major, minor)
+ dev: (usize, usize),
+ /// inode on the device. 0 indicates that no inode is associated with the memory region (e.g. uninitalized data aka BSS).
+ inode: usize,
+ /// Usually the file backing the mapping.
+ ///
+ /// Note: The man page for proc includes a note about "coordination" by
+ /// using readelf to see the Offset field in ELF program headers. pnkfelix
+ /// is not yet sure if that is intended to be a comment on pathname, or what
+ /// form/purpose such coordination is meant to have.
+ ///
+ /// There are also some pseudo-paths:
+ /// "[stack]": The initial process's (aka main thread's) stack.
+ /// "[stack:<tid>]": a specific thread's stack. (This was only present for a limited range of Linux verisons; it was determined to be too expensive to provide.)
+ /// "[vdso]": Virtual dynamically linked shared object
+ /// "[heap]": The process's heap
+ ///
+ /// The pathname can be blank, which means it is an anonymous mapping
+ /// obtained via mmap.
+ ///
+ /// Newlines in pathname are replaced with an octal escape sequence.
+ ///
+ /// The pathname may have "(deleted)" appended onto it if the file-backed
+ /// path has been deleted.
+ ///
+ /// Note that modifications like the latter two indicated above imply that
+ /// in general the pathname may be ambiguous. (I.e. you cannot tell if the
+ /// denoted filename actually ended with the text "(deleted)", or if that
+ /// was added by the maps rendering.
+ pathname: OsString,
+}
+
+pub(super) fn parse_maps() -> Result<Vec<MapsEntry>, &'static str> {
+ let mut v = Vec::new();
+ let mut proc_self_maps =
+ File::open("/proc/self/maps").map_err(|_| "Couldn't open /proc/self/maps")?;
+ let mut buf = String::new();
+ let _bytes_read = proc_self_maps
+ .read_to_string(&mut buf)
+ .map_err(|_| "Couldn't read /proc/self/maps")?;
+ for line in buf.lines() {
+ v.push(line.parse()?);
+ }
+
+ Ok(v)
+}
+
+impl MapsEntry {
+ pub(super) fn pathname(&self) -> &OsString {
+ &self.pathname
+ }
+
+ pub(super) fn ip_matches(&self, ip: usize) -> bool {
+ self.address.0 <= ip && ip < self.address.1
+ }
+}
+
+impl FromStr for MapsEntry {
+ type Err = &'static str;
+
+ // Format: address perms offset dev inode pathname
+ // e.g.: "ffffffffff600000-ffffffffff601000 --xp 00000000 00:00 0 [vsyscall]"
+ // e.g.: "7f5985f46000-7f5985f48000 rw-p 00039000 103:06 76021795 /usr/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2"
+ // e.g.: "35b1a21000-35b1a22000 rw-p 00000000 00:00 0"
+ fn from_str(s: &str) -> Result<Self, Self::Err> {
+ let mut parts = s
+ .split(' ') // space-separated fields
+ .filter(|s| s.len() > 0); // multiple spaces implies empty strings that need to be skipped.
+ let range_str = parts.next().ok_or("Couldn't find address")?;
+ let perms_str = parts.next().ok_or("Couldn't find permissions")?;
+ let offset_str = parts.next().ok_or("Couldn't find offset")?;
+ let dev_str = parts.next().ok_or("Couldn't find dev")?;
+ let inode_str = parts.next().ok_or("Couldn't find inode")?;
+ let pathname_str = parts.next().unwrap_or(""); // pathname may be omitted.
+
+ let hex = |s| usize::from_str_radix(s, 16).map_err(|_| "Couldn't parse hex number");
+ let address = {
+ // This could use `range_str.split_once('-')` once the MSRV passes 1.52.
+ if let Some(idx) = range_str.find('-') {
+ let (start, rest) = range_str.split_at(idx);
+ let (_div, limit) = rest.split_at(1);
+ (hex(start)?, hex(limit)?)
+ } else {
+ return Err("Couldn't parse address range");
+ }
+ };
+ let perms: [char; 4] = {
+ let mut chars = perms_str.chars();
+ let mut c = || chars.next().ok_or("insufficient perms");
+ let perms = [c()?, c()?, c()?, c()?];
+ if chars.next().is_some() {
+ return Err("too many perms");
+ }
+ perms
+ };
+ let offset = hex(offset_str)?;
+ let dev = {
+ // This could use `dev_str.split_once(':')` once the MSRV passes 1.52.
+ if let Some(idx) = dev_str.find(':') {
+ let (major, rest) = dev_str.split_at(idx);
+ let (_div, minor) = rest.split_at(1);
+ (hex(major)?, hex(minor)?)
+ } else {
+ return Err("Couldn't parse dev")?;
+ }
+ };
+ let inode = hex(inode_str)?;
+ let pathname = pathname_str.into();
+
+ Ok(MapsEntry {
+ address,
+ perms,
+ offset,
+ dev,
+ inode,
+ pathname,
+ })
+ }
+}
+
+// Make sure we can parse 64-bit sample output if we're on a 64-bit target.
+#[cfg(target_pointer_width = "64")]
+#[test]
+fn check_maps_entry_parsing_64bit() {
+ assert_eq!(
+ "ffffffffff600000-ffffffffff601000 --xp 00000000 00:00 0 \
+ [vsyscall]"
+ .parse::<MapsEntry>()
+ .unwrap(),
+ MapsEntry {
+ address: (0xffffffffff600000, 0xffffffffff601000),
+ perms: ['-', '-', 'x', 'p'],
+ offset: 0x00000000,
+ dev: (0x00, 0x00),
+ inode: 0x0,
+ pathname: "[vsyscall]".into(),
+ }
+ );
+
+ assert_eq!(
+ "7f5985f46000-7f5985f48000 rw-p 00039000 103:06 76021795 \
+ /usr/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2"
+ .parse::<MapsEntry>()
+ .unwrap(),
+ MapsEntry {
+ address: (0x7f5985f46000, 0x7f5985f48000),
+ perms: ['r', 'w', '-', 'p'],
+ offset: 0x00039000,
+ dev: (0x103, 0x06),
+ inode: 0x76021795,
+ pathname: "/usr/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2".into(),
+ }
+ );
+ assert_eq!(
+ "35b1a21000-35b1a22000 rw-p 00000000 00:00 0"
+ .parse::<MapsEntry>()
+ .unwrap(),
+ MapsEntry {
+ address: (0x35b1a21000, 0x35b1a22000),
+ perms: ['r', 'w', '-', 'p'],
+ offset: 0x00000000,
+ dev: (0x00, 0x00),
+ inode: 0x0,
+ pathname: Default::default(),
+ }
+ );
+}
+
+// (This output was taken from a 32-bit machine, but will work on any target)
+#[test]
+fn check_maps_entry_parsing_32bit() {
+ /* Example snippet of output:
+ 08056000-08077000 rw-p 00000000 00:00 0 [heap]
+ b7c79000-b7e02000 r--p 00000000 08:01 60662705 /usr/lib/locale/locale-archive
+ b7e02000-b7e03000 rw-p 00000000 00:00 0
+ */
+ assert_eq!(
+ "08056000-08077000 rw-p 00000000 00:00 0 \
+ [heap]"
+ .parse::<MapsEntry>()
+ .unwrap(),
+ MapsEntry {
+ address: (0x08056000, 0x08077000),
+ perms: ['r', 'w', '-', 'p'],
+ offset: 0x00000000,
+ dev: (0x00, 0x00),
+ inode: 0x0,
+ pathname: "[heap]".into(),
+ }
+ );
+
+ assert_eq!(
+ "b7c79000-b7e02000 r--p 00000000 08:01 60662705 \
+ /usr/lib/locale/locale-archive"
+ .parse::<MapsEntry>()
+ .unwrap(),
+ MapsEntry {
+ address: (0xb7c79000, 0xb7e02000),
+ perms: ['r', '-', '-', 'p'],
+ offset: 0x00000000,
+ dev: (0x08, 0x01),
+ inode: 0x60662705,
+ pathname: "/usr/lib/locale/locale-archive".into(),
+ }
+ );
+ assert_eq!(
+ "b7e02000-b7e03000 rw-p 00000000 00:00 0"
+ .parse::<MapsEntry>()
+ .unwrap(),
+ MapsEntry {
+ address: (0xb7e02000, 0xb7e03000),
+ perms: ['r', 'w', '-', 'p'],
+ offset: 0x00000000,
+ dev: (0x00, 0x00),
+ inode: 0x0,
+ pathname: Default::default(),
+ }
+ );
+}
diff --git a/vendor/backtrace/src/windows.rs b/vendor/backtrace/src/windows.rs
index d091874f1..9ec3ba99b 100644
--- a/vendor/backtrace/src/windows.rs
+++ b/vendor/backtrace/src/windows.rs
@@ -162,8 +162,8 @@ macro_rules! ffi {
ffi!($($rest)*);
);
- (extern "system" { $(pub fn $name:ident($($args:tt)*) -> $ret:ty;)* } $($rest:tt)*) => (
- extern "system" {
+ ($(#[$meta:meta])* extern "system" { $(pub fn $name:ident($($args:tt)*) -> $ret:ty;)* } $($rest:tt)*) => (
+ $(#[$meta])* extern "system" {
$(pub fn $name($($args)*) -> $ret;)*
}
@@ -371,6 +371,7 @@ ffi! {
pub type LPCVOID = *const c_void;
pub type LPMODULEENTRY32W = *mut MODULEENTRY32W;
+ #[link(name = "kernel32")]
extern "system" {
pub fn GetCurrentProcess() -> HANDLE;
pub fn GetCurrentThread() -> HANDLE;
@@ -438,6 +439,7 @@ ffi! {
#[cfg(target_pointer_width = "64")]
ffi! {
+ #[link(name = "kernel32")]
extern "system" {
pub fn RtlLookupFunctionEntry(
ControlPc: DWORD64,
diff --git a/vendor/backtrace/tests/common/mod.rs b/vendor/backtrace/tests/common/mod.rs
new file mode 100644
index 000000000..3c07934fd
--- /dev/null
+++ b/vendor/backtrace/tests/common/mod.rs
@@ -0,0 +1,14 @@
+/// Some tests only make sense in contexts where they can re-exec the test
+/// itself. Not all contexts support this, so you can call this method to find
+/// out which case you are in.
+pub fn cannot_reexec_the_test() -> bool {
+ // These run in docker containers on CI where they can't re-exec the test,
+ // so just skip these for CI. No other reason this can't run on those
+ // platforms though.
+ // Miri does not have support for re-execing a file
+ cfg!(unix)
+ && (cfg!(target_arch = "arm")
+ || cfg!(target_arch = "aarch64")
+ || cfg!(target_arch = "s390x"))
+ || cfg!(miri)
+}
diff --git a/vendor/backtrace/tests/concurrent-panics.rs b/vendor/backtrace/tests/concurrent-panics.rs
index 470245cc9..a44a26771 100644
--- a/vendor/backtrace/tests/concurrent-panics.rs
+++ b/vendor/backtrace/tests/concurrent-panics.rs
@@ -9,17 +9,11 @@ const PANICS: usize = 100;
const THREADS: usize = 8;
const VAR: &str = "__THE_TEST_YOU_ARE_LUKE";
+mod common;
+
fn main() {
- // These run in docker containers on CI where they can't re-exec the test,
- // so just skip these for CI. No other reason this can't run on those
- // platforms though.
- // Miri does not have support for re-execing a file
- if cfg!(unix)
- && (cfg!(target_arch = "arm")
- || cfg!(target_arch = "aarch64")
- || cfg!(target_arch = "s390x"))
- || cfg!(miri)
- {
+ // If we cannot re-exec this test, there's no point in trying to do it.
+ if common::cannot_reexec_the_test() {
println!("test result: ok");
return;
}
diff --git a/vendor/backtrace/tests/current-exe-mismatch.rs b/vendor/backtrace/tests/current-exe-mismatch.rs
new file mode 100644
index 000000000..21c67bcbf
--- /dev/null
+++ b/vendor/backtrace/tests/current-exe-mismatch.rs
@@ -0,0 +1,137 @@
+// rust-lang/rust#101913: when you run your program explicitly via `ld.so`,
+// `std::env::current_exe` will return the path of *that* program, and not
+// the Rust program itself.
+
+use std::io::{BufRead, BufReader};
+use std::path::{Path, PathBuf};
+use std::process::Command;
+
+mod common;
+
+fn main() {
+ if std::env::var(VAR).is_err() {
+ // the parent waits for the child; then we then handle either printing
+ // "test result: ok", "test result: ignored", or panicking.
+ match parent() {
+ Ok(()) => {
+ println!("test result: ok");
+ }
+ Err(EarlyExit::IgnoreTest(_)) => {
+ println!("test result: ignored");
+ }
+ Err(EarlyExit::IoError(e)) => {
+ println!("{} parent encoutered IoError: {:?}", file!(), e);
+ panic!();
+ }
+ }
+ } else {
+ // println!("{} running child", file!());
+ child().unwrap();
+ }
+}
+
+const VAR: &str = "__THE_TEST_YOU_ARE_LUKE";
+
+#[derive(Debug)]
+enum EarlyExit {
+ IgnoreTest(String),
+ IoError(std::io::Error),
+}
+
+impl From<std::io::Error> for EarlyExit {
+ fn from(e: std::io::Error) -> Self {
+ EarlyExit::IoError(e)
+ }
+}
+
+fn parent() -> Result<(), EarlyExit> {
+ // If we cannot re-exec this test, there's no point in trying to do it.
+ if common::cannot_reexec_the_test() {
+ return Err(EarlyExit::IgnoreTest("(cannot reexec)".into()));
+ }
+
+ let me = std::env::current_exe().unwrap();
+ let ld_so = find_interpreter(&me)?;
+
+ // use interp to invoke current exe, yielding child test.
+ //
+ // (if you're curious what you might compare this against, you can try
+ // swapping in the below definition for `result`, which is the easy case of
+ // not using the ld.so interpreter directly that Rust handled fine even
+ // prior to resolution of rust-lang/rust#101913.)
+ //
+ // let result = Command::new(me).env(VAR, "1").output()?;
+ let result = Command::new(ld_so).env(VAR, "1").arg(&me).output().unwrap();
+
+ if result.status.success() {
+ return Ok(());
+ }
+ println!("stdout:\n{}", String::from_utf8_lossy(&result.stdout));
+ println!("stderr:\n{}", String::from_utf8_lossy(&result.stderr));
+ println!("code: {}", result.status);
+ panic!();
+}
+
+fn child() -> Result<(), EarlyExit> {
+ let bt = backtrace::Backtrace::new();
+ println!("{:?}", bt);
+
+ let mut found_my_name = false;
+
+ let my_filename = file!();
+ 'frames: for frame in bt.frames() {
+ let symbols = frame.symbols();
+ if symbols.is_empty() {
+ continue;
+ }
+
+ for sym in symbols {
+ if let Some(filename) = sym.filename() {
+ if filename.ends_with(my_filename) {
+ // huzzah!
+ found_my_name = true;
+ break 'frames;
+ }
+ }
+ }
+ }
+
+ assert!(found_my_name);
+
+ Ok(())
+}
+
+// we use the `readelf` command to extract the path to the interpreter requested
+// by our binary.
+//
+// if we cannot `readelf` for some reason, or if we fail to parse its output,
+// then we will just give up on this test (and not treat it as a test failure).
+fn find_interpreter(me: &Path) -> Result<PathBuf, EarlyExit> {
+ let result = Command::new("readelf")
+ .arg("-l")
+ .arg(me)
+ .output()
+ .map_err(|_err| EarlyExit::IgnoreTest("readelf invocation failed".into()))?;
+ if result.status.success() {
+ let r = BufReader::new(&result.stdout[..]);
+ for line in r.lines() {
+ let line = line?;
+ let line = line.trim();
+ let prefix = "[Requesting program interpreter: ";
+ // This could use `line.split_once` and `suffix.rsplit_once` once the MSRV passes 1.52
+ if let Some(idx) = line.find(prefix) {
+ let (_, suffix) = line.split_at(idx + prefix.len());
+ if let Some(idx) = suffix.rfind("]") {
+ let (found_path, _ignore_remainder) = suffix.split_at(idx);
+ return Ok(found_path.into());
+ }
+ }
+ }
+
+ Err(EarlyExit::IgnoreTest(
+ "could not find interpreter from readelf output".into(),
+ ))
+ } else {
+ Err(EarlyExit::IgnoreTest("readelf returned non-success".into()))
+ }
+}
diff --git a/vendor/backtrace/tests/skip_inner_frames.rs b/vendor/backtrace/tests/skip_inner_frames.rs
index 8b57bef52..60bba35e6 100644
--- a/vendor/backtrace/tests/skip_inner_frames.rs
+++ b/vendor/backtrace/tests/skip_inner_frames.rs
@@ -4,7 +4,7 @@ use backtrace::Backtrace;
// function for frames which reports the starting address of a symbol. As a
// result it's only enabled on a few platforms.
const ENABLED: bool = cfg!(all(
- // Windows hasn't really been tested, and OSX doesn't support actually
+ // Windows hasn't really been tested, and macOS doesn't support actually
// finding an enclosing frame, so disable this
target_os = "linux",
// On ARM finding the enclosing function is simply returning the ip itself.
diff --git a/vendor/camino/.cargo-checksum.json b/vendor/camino/.cargo-checksum.json
index 81a1f0f60..8686980ae 100644
--- a/vendor/camino/.cargo-checksum.json
+++ b/vendor/camino/.cargo-checksum.json
@@ -1 +1 @@
-{"files":{"CHANGELOG.md":"2530b12d7ddf3395bbc4c10557e57531498039ba28528b91ffc3f3deefc76f77","CODE_OF_CONDUCT.md":"f51e207c2961ec061cac5c8aa9dd3098c3437de2c106d740c2aae90771bc0f86","Cargo.toml":"7bf7de17ab10cd95aadf102f37c0b8a58f0c31f90cfeee81126ead8ad3cb0a26","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"23f18e03dc49df91622fe2a76176497404e46ced8a715d9d2b67a7446571cca3","README.md":"84762d717d0f2358c56f54ee46a6ca5f1582b7d3843f7a4d6e553ea04a57ca1b","build.rs":"ca6914ad35e69842b6fba6e436d0417f39dbe6ee18694d4dd89b372d31cbf715","clippy.toml":"818cba7332cc56b019d59e09805a3498f523da788f51454742905f1987c0b563","rustfmt.toml":"bf9776adb152b3fdc0d75c0929ede148c3e28c58f909a7d052865bc332e8958f","src/lib.rs":"3a744ca7df473bb8bd97e1f4a961d517cb7379b8756e38893dd9d53a169c41e1","src/proptest_impls.rs":"aa17bad810abe4a7b6c7a2c3163ae9749b03dd8bcef5043b0c4b9d00977f981c","src/serde_impls.rs":"eb7f00d1ceb7135506047dbefd7e6acee0364b5a9194111f49dbf2d1eb3661ac","src/tests.rs":"d6108c540dc93446b17d297b50372f799ef777c2cb0280fd37824a102ec24533","tests/integration_tests.rs":"b664a7555d2e5ac9ab71384e3ccfb73c01abe4c401f8de32e234c03b4d19d0f8"},"package":"88ad0e1e3e88dd237a156ab9f571021b8a158caa0ae44b1968a241efb5144c1e"} \ No newline at end of file
+{"files":{"CHANGELOG.md":"ea1979dff05f6bdd9e2c6c65b8fdb28395bf59f16e7e7fa2a9d398bdd6ae106f","CODE_OF_CONDUCT.md":"f51e207c2961ec061cac5c8aa9dd3098c3437de2c106d740c2aae90771bc0f86","Cargo.toml":"b024a45f39757c112132e6ae883c0052b8bd86bfc166b89b9615621744fd8583","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"23f18e03dc49df91622fe2a76176497404e46ced8a715d9d2b67a7446571cca3","README.md":"84762d717d0f2358c56f54ee46a6ca5f1582b7d3843f7a4d6e553ea04a57ca1b","build.rs":"ca6914ad35e69842b6fba6e436d0417f39dbe6ee18694d4dd89b372d31cbf715","clippy.toml":"818cba7332cc56b019d59e09805a3498f523da788f51454742905f1987c0b563","release.toml":"287514631fde7a1d29a8e8027bc37c585c7e30c173c8254f551b042e38f4bb81","rustfmt.toml":"bf9776adb152b3fdc0d75c0929ede148c3e28c58f909a7d052865bc332e8958f","src/lib.rs":"52da457eae1c189a1728df994b478fbf37baa85b630541b7a6cbb48670c1c329","src/proptest_impls.rs":"4f36f5804bd3cbbf65177db4b20d808ed56405388b552bad375aab308a535236","src/serde_impls.rs":"eb7f00d1ceb7135506047dbefd7e6acee0364b5a9194111f49dbf2d1eb3661ac","src/tests.rs":"d6108c540dc93446b17d297b50372f799ef777c2cb0280fd37824a102ec24533","tests/integration_tests.rs":"56aa396a173d0c255369159b57e4a7db294e607aa6cfb65efebd95d79cc51a04"},"package":"c77df041dc383319cc661b428b6961a005db4d6808d5e12536931b1ca9556055"} \ No newline at end of file
diff --git a/vendor/camino/CHANGELOG.md b/vendor/camino/CHANGELOG.md
index 67c2ea8d3..03d672242 100644
--- a/vendor/camino/CHANGELOG.md
+++ b/vendor/camino/CHANGELOG.md
@@ -3,6 +3,13 @@
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
+## [1.1.2] - 2022-08-12
+
+### Added
+
+- New convenience methods [`FromPathBufError::into_io_error`] and
+ [`FromPathError::into_io_error`].
+
## [1.1.1] - 2022-08-12
### Fixed
@@ -101,6 +108,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
Initial release.
+[1.1.2]: https://github.com/camino-rs/camino/releases/tag/camino-1.1.2
[1.1.1]: https://github.com/camino-rs/camino/releases/tag/camino-1.1.1
[1.1.0]: https://github.com/camino-rs/camino/releases/tag/camino-1.1.0
[1.0.9]: https://github.com/camino-rs/camino/releases/tag/camino-1.0.9
diff --git a/vendor/camino/Cargo.toml b/vendor/camino/Cargo.toml
index 28c007855..1b2eb24d8 100644
--- a/vendor/camino/Cargo.toml
+++ b/vendor/camino/Cargo.toml
@@ -12,7 +12,7 @@
[package]
edition = "2018"
name = "camino"
-version = "1.1.1"
+version = "1.1.2"
authors = [
"Without Boats <saoirse@without.boats>",
"Ashley Williams <ashley666ashley@gmail.com>",
diff --git a/vendor/camino/release.toml b/vendor/camino/release.toml
new file mode 100644
index 000000000..b7977bad5
--- /dev/null
+++ b/vendor/camino/release.toml
@@ -0,0 +1,8 @@
+sign-tag = true
+# Required for templates below to work
+consolidate-commits = false
+pre-release-commit-message = "[{{crate_name}}] version {{version}}"
+tag-message = "[{{crate_name}}] version {{version}}"
+tag-name = "camino-{{version}}"
+publish = false
+dependent-version = "upgrade"
diff --git a/vendor/camino/src/lib.rs b/vendor/camino/src/lib.rs
index fcfba3805..44684b096 100644
--- a/vendor/camino/src/lib.rs
+++ b/vendor/camino/src/lib.rs
@@ -222,7 +222,7 @@ impl Utf8PathBuf {
#[must_use]
pub fn as_path(&self) -> &Utf8Path {
// SAFETY: every Utf8PathBuf constructor ensures that self is valid UTF-8
- unsafe { Utf8Path::assume_utf8(&*self.0) }
+ unsafe { Utf8Path::assume_utf8(&self.0) }
}
/// Extends `self` with `path`.
@@ -1175,10 +1175,8 @@ impl Utf8Path {
/// assert_eq!(path.canonicalize_utf8().unwrap(), Utf8PathBuf::from("/foo/test/bar.rs"));
/// ```
pub fn canonicalize_utf8(&self) -> io::Result<Utf8PathBuf> {
- self.canonicalize().and_then(|path| {
- path.try_into()
- .map_err(|err| io::Error::new(io::ErrorKind::InvalidData, err))
- })
+ self.canonicalize()
+ .and_then(|path| path.try_into().map_err(FromPathBufError::into_io_error))
}
/// Reads a symbolic link, returning the file that the link points to.
@@ -1224,10 +1222,8 @@ impl Utf8Path {
/// let path_link = path.read_link_utf8().expect("read_link call failed");
/// ```
pub fn read_link_utf8(&self) -> io::Result<Utf8PathBuf> {
- self.read_link().and_then(|path| {
- path.try_into()
- .map_err(|err| io::Error::new(io::ErrorKind::InvalidData, err))
- })
+ self.read_link()
+ .and_then(|path| path.try_into().map_err(FromPathBufError::into_io_error))
}
/// Returns an iterator over the entries within a directory.
@@ -2488,13 +2484,24 @@ impl FromPathBufError {
self.path
}
- /// Fetch a [`FromPathError`] for more about the conversion failure.
+ /// Fetches a [`FromPathError`] for more about the conversion failure.
///
/// At the moment this struct does not contain any additional information, but is provided for
/// completeness.
pub fn from_path_error(&self) -> FromPathError {
self.error
}
+
+ /// Converts self into a [`std::io::Error`] with kind
+ /// [`InvalidData`](io::ErrorKind::InvalidData).
+ ///
+ /// Many users of `FromPathBufError` will want to convert it into an `io::Error`. This is a
+ /// convenience method to do that.
+ pub fn into_io_error(self) -> io::Error {
+ // NOTE: we don't currently implement `From<FromPathBufError> for io::Error` because we want
+ // to ensure the user actually desires that conversion.
+ io::Error::new(io::ErrorKind::InvalidData, self)
+ }
}
impl fmt::Display for FromPathBufError {
@@ -2539,6 +2546,19 @@ impl error::Error for FromPathBufError {
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub struct FromPathError(());
+impl FromPathError {
+ /// Converts self into a [`std::io::Error`] with kind
+ /// [`InvalidData`](io::ErrorKind::InvalidData).
+ ///
+ /// Many users of `FromPathError` will want to convert it into an `io::Error`. This is a
+ /// convenience method to do that.
+ pub fn into_io_error(self) -> io::Error {
+ // NOTE: we don't currently implement `From<FromPathBufError> for io::Error` because we want
+ // to ensure the user actually desires that conversion.
+ io::Error::new(io::ErrorKind::InvalidData, self)
+ }
+}
+
impl fmt::Display for FromPathError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "Path contains invalid UTF-8")
@@ -2587,7 +2607,7 @@ impl AsRef<Path> for Utf8Path {
impl AsRef<Path> for Utf8PathBuf {
fn as_ref(&self) -> &Path {
- &*self.0
+ &self.0
}
}
diff --git a/vendor/camino/src/proptest_impls.rs b/vendor/camino/src/proptest_impls.rs
index 997c88c8c..81776f226 100644
--- a/vendor/camino/src/proptest_impls.rs
+++ b/vendor/camino/src/proptest_impls.rs
@@ -8,9 +8,8 @@
// NOTE: #[cfg(feature = "proptest1")] is specified here to work with `doc_cfg`.
-use proptest::{arbitrary::StrategyFor, prelude::*, strategy::MapInto};
-
use crate::{Utf8Path, Utf8PathBuf};
+use proptest::{arbitrary::StrategyFor, prelude::*, strategy::MapInto};
/// The [`Arbitrary`] impl for `Utf8PathBuf` returns a path with between 0 and 8 components,
/// joined by the [`MAIN_SEPARATOR`](std::path::MAIN_SEPARATOR) for the platform. (Each component is
diff --git a/vendor/camino/tests/integration_tests.rs b/vendor/camino/tests/integration_tests.rs
index a8b00f2fe..190ba82ba 100644
--- a/vendor/camino/tests/integration_tests.rs
+++ b/vendor/camino/tests/integration_tests.rs
@@ -106,7 +106,7 @@ fn test_borrow_hash() {
let owned = Utf8PathBuf::from(path);
assert_eq!(
- hash_output(&owned),
+ hash_output(owned),
hash_output(borrowed),
"consistent Hash: {}",
borrowed
diff --git a/vendor/cargo_metadata/.cargo-checksum.json b/vendor/cargo_metadata/.cargo-checksum.json
index 2d183cd80..7838a4a29 100644
--- a/vendor/cargo_metadata/.cargo-checksum.json
+++ b/vendor/cargo_metadata/.cargo-checksum.json
@@ -1 +1 @@
-{"files":{"Cargo.toml":"1ea11e47024269503340c3764c13c6e0d47f45eb9f2eef3ea75eedee64c02e98","LICENSE-MIT":"23f18e03dc49df91622fe2a76176497404e46ced8a715d9d2b67a7446571cca3","README.md":"d51a5b3347bed2441b20986be81bfd4611ca2c5614f950116b273199a9bcf2de","src/dependency.rs":"c593ddc73d863c5712e2aba58b5f4d9bd915a5ac0bc17df71642aa79aa93bfdc","src/diagnostic.rs":"fee47d27390f1026ff99ffade5dfd2ab3e9b9839c3f33ce91a7dcde875551374","src/errors.rs":"2d67e46ef8f29a9ae2dd00ce39cc50e6ccae4dec9a09a9bad7c36bd8be4f62cc","src/lib.rs":"41b0d89ec02f698b8fdeab9c1f76536a4ba34c2a4361b2c921340a10288e002d","src/messages.rs":"caaa7c906595768587007c72fcc3ac32880bbb02293b004f498a296e078fbbff","tests/selftest.rs":"73afd494c1bf7dd4e1a99971e9ff66a0e21fc7bf3e327663df15d2350dcdfc70","tests/test_samples.rs":"3374f4a054d440f8fc567b233c9d680be98aa481c622845ae1dc5cb28aa5f804"},"package":"3abb7553d5b9b8421c6de7cb02606ff15e0c6eea7d8eadd75ef013fd636bec36"} \ No newline at end of file
+{"files":{"CHANGELOG.md":"8b3e29799cdedf02f169bb519072ace2e2b6b9413f4ce8fa0666c2d1d964084e","Cargo.toml":"57d432cd172cc87ee4c31b0e4c21c52d06ba1a48da9decd34581b2671c47d71d","LICENSE-MIT":"23f18e03dc49df91622fe2a76176497404e46ced8a715d9d2b67a7446571cca3","README.md":"d51a5b3347bed2441b20986be81bfd4611ca2c5614f950116b273199a9bcf2de","src/dependency.rs":"c593ddc73d863c5712e2aba58b5f4d9bd915a5ac0bc17df71642aa79aa93bfdc","src/diagnostic.rs":"fee47d27390f1026ff99ffade5dfd2ab3e9b9839c3f33ce91a7dcde875551374","src/errors.rs":"797afd61efdd843ae570d9e972dd2425d33823d4a78c0c488028493dffb45c7a","src/lib.rs":"5ec701f3589c5d71c152b5abe7ad5f222aee4d4a5f9992bced1d357bad36e227","src/messages.rs":"a8e3ee31dc8cce5762b4b085be29fe4d7189a789f3a149ef2b6c17604d94528b","tests/selftest.rs":"73afd494c1bf7dd4e1a99971e9ff66a0e21fc7bf3e327663df15d2350dcdfc70","tests/test_samples.rs":"ee2b4737adfa1930c1610bb3ec0fc94b7f1a3691bb09545da69044eef2f5ba6b"},"package":"08a1ec454bc3eead8719cb56e15dbbfecdbc14e4b3a3ae4936cc6e31f5fc0d07"} \ No newline at end of file
diff --git a/vendor/cargo_metadata/CHANGELOG.md b/vendor/cargo_metadata/CHANGELOG.md
new file mode 100644
index 000000000..fcc0b2642
--- /dev/null
+++ b/vendor/cargo_metadata/CHANGELOG.md
@@ -0,0 +1,38 @@
+# Changelog
+
+## Unreleased
+
+### Added
+
+- Re-exported `semver` crate directly.
+
+### Changed
+
+- Made `parse_stream` more versatile by accepting anything that implements `Read`.
+
+### Removed
+
+- Removed re-exports for `BuildMetadata` and `Prerelease` from `semver` crate.
+
+### Fixed
+
+- Added missing `manifest_path` field to `Artifact`. Fixes #187.
+
+## [0.15.0] - 2022-06-22
+
+### Added
+
+- Re-exported `BuildMetadata` and `Prerelease` from `semver` crate.
+- Added `workspace_packages` function.
+- Added `Edition` enum to better parse edition field.
+- Added `rust-version` field to Cargo manifest.
+
+### Changed
+
+- Bumped msrv from `1.40.0` to `1.42.0`.
+
+### Internal Changes
+
+- Updated `derive_builder` to the latest version.
+- Made use of `matches!` macros where possible.
+- Fixed some tests
diff --git a/vendor/cargo_metadata/Cargo.toml b/vendor/cargo_metadata/Cargo.toml
index 90f1b1ce0..25a28ef4f 100644
--- a/vendor/cargo_metadata/Cargo.toml
+++ b/vendor/cargo_metadata/Cargo.toml
@@ -13,7 +13,7 @@
edition = "2018"
rust-version = "1.42.0"
name = "cargo_metadata"
-version = "0.15.0"
+version = "0.15.3"
authors = ["Oliver Schneider <git-spam-no-reply9815368754983@oli-obk.de>"]
description = "structured access to the output of `cargo metadata`"
readme = "README.md"
@@ -47,6 +47,9 @@ features = ["derive"]
version = "1.0.79"
features = ["unbounded_depth"]
+[dependencies.thiserror]
+version = "1.0.31"
+
[features]
builder = ["derive_builder"]
default = []
diff --git a/vendor/cargo_metadata/src/errors.rs b/vendor/cargo_metadata/src/errors.rs
index 7172057e7..4d08200c8 100644
--- a/vendor/cargo_metadata/src/errors.rs
+++ b/vendor/cargo_metadata/src/errors.rs
@@ -1,7 +1,4 @@
-use std::fmt;
-use std::io;
-use std::str::Utf8Error;
-use std::string::FromUtf8Error;
+use std::{io, str::Utf8Error, string::FromUtf8Error};
/// Custom result type for `cargo_metadata::Error`
pub type Result<T> = ::std::result::Result<T, Error>;
@@ -24,87 +21,32 @@ pub type Result<T> = ::std::result::Result<T, Error>;
/// really want to. (Either through foreign_links or by making it a field
/// value of a `ErrorKind` variant).
///
-#[derive(Debug)]
+#[derive(Debug, thiserror::Error)]
pub enum Error {
/// Error during execution of `cargo metadata`
+ #[error("`cargo metadata` exited with an error: {stderr}")]
CargoMetadata {
/// stderr returned by the `cargo metadata` command
stderr: String,
},
/// IO Error during execution of `cargo metadata`
- Io(io::Error),
+ #[error("failed to start `cargo metadata`: {0}")]
+ Io(#[from] io::Error),
/// Output of `cargo metadata` was not valid utf8
- Utf8(Utf8Error),
+ #[error("cannot convert the stdout of `cargo metadata`: {0}")]
+ Utf8(#[from] Utf8Error),
/// Error output of `cargo metadata` was not valid utf8
- ErrUtf8(FromUtf8Error),
+ #[error("cannot convert the stderr of `cargo metadata`: {0}")]
+ ErrUtf8(#[from] FromUtf8Error),
/// Deserialization error (structure of json did not match expected structure)
- Json(::serde_json::Error),
+ #[error("failed to interpret `cargo metadata`'s json: {0}")]
+ Json(#[from] ::serde_json::Error),
/// The output did not contain any json
+ #[error("could not find any json in the output of `cargo metadata`")]
NoJson,
}
-
-impl From<io::Error> for Error {
- fn from(v: io::Error) -> Self {
- Error::Io(v)
- }
-}
-
-impl From<Utf8Error> for Error {
- fn from(v: Utf8Error) -> Self {
- Error::Utf8(v)
- }
-}
-
-impl From<FromUtf8Error> for Error {
- fn from(v: FromUtf8Error) -> Self {
- Error::ErrUtf8(v)
- }
-}
-
-impl From<::serde_json::Error> for Error {
- fn from(v: ::serde_json::Error) -> Self {
- Error::Json(v)
- }
-}
-
-impl fmt::Display for Error {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- match self {
- Error::CargoMetadata { stderr } => {
- write!(
- f,
- "`cargo metadata` exited with an error: {}",
- stderr.trim_end()
- )
- }
- Error::Io(err) => write!(f, "failed to start `cargo metadata`: {}", err),
- Error::Utf8(err) => write!(f, "cannot convert the stdout of `cargo metadata`: {}", err),
- Error::ErrUtf8(err) => {
- write!(f, "cannot convert the stderr of `cargo metadata`: {}", err)
- }
- Error::Json(err) => write!(f, "failed to interpret `cargo metadata`'s json: {}", err),
- Error::NoJson => write!(
- f,
- "could not find any json in the output of `cargo metadata`"
- ),
- }
- }
-}
-
-impl ::std::error::Error for Error {
- fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
- match self {
- Error::CargoMetadata { .. } => None,
- Error::Io(err) => Some(err),
- Error::Utf8(err) => Some(err),
- Error::ErrUtf8(err) => Some(err),
- Error::Json(err) => Some(err),
- Error::NoJson => None,
- }
- }
-}
diff --git a/vendor/cargo_metadata/src/lib.rs b/vendor/cargo_metadata/src/lib.rs
index a250aa176..27c72da0d 100644
--- a/vendor/cargo_metadata/src/lib.rs
+++ b/vendor/cargo_metadata/src/lib.rs
@@ -83,9 +83,11 @@ use camino::Utf8PathBuf;
use derive_builder::Builder;
use std::collections::HashMap;
use std::env;
+use std::ffi::OsString;
use std::fmt;
+use std::hash::Hash;
use std::path::PathBuf;
-use std::process::Command;
+use std::process::{Command, Stdio};
use std::str::from_utf8;
pub use camino;
@@ -154,10 +156,22 @@ pub struct Metadata {
}
impl Metadata {
- /// Get the root package of this metadata instance.
+ /// Get the workspace's root package of this metadata instance.
pub fn root_package(&self) -> Option<&Package> {
- let root = self.resolve.as_ref()?.root.as_ref()?;
- self.packages.iter().find(|pkg| &pkg.id == root)
+ match &self.resolve {
+ Some(resolve) => {
+ // if dependencies are resolved, use Cargo's answer
+ let root = resolve.root.as_ref()?;
+ self.packages.iter().find(|pkg| &pkg.id == root)
+ }
+ None => {
+ // if dependencies aren't resolved, check for a root package manually
+ let root_manifest_path = self.workspace_root.join("Cargo.toml");
+ self.packages
+ .iter()
+ .find(|pkg| pkg.manifest_path == root_manifest_path)
+ }
+ }
}
/// Get the workspace packages.
@@ -374,9 +388,12 @@ impl Package {
/// Full path to the readme file if one is present in the manifest
pub fn readme(&self) -> Option<Utf8PathBuf> {
- self.readme
- .as_ref()
- .map(|file| self.manifest_path.join(file))
+ self.readme.as_ref().map(|file| {
+ self.manifest_path
+ .parent()
+ .unwrap_or(&self.manifest_path)
+ .join(file)
+ })
}
}
@@ -409,7 +426,7 @@ impl std::fmt::Display for Source {
pub struct Target {
/// Name as given in the `Cargo.toml` or generated from the file name
pub name: String,
- /// Kind of target ("bin", "example", "test", "bench", "lib")
+ /// Kind of target ("bin", "example", "test", "bench", "lib", "custom-build")
pub kind: Vec<String>,
/// Almost the same as `kind`, except when an example is a library instead of an executable.
/// In that case `crate_types` contains things like `rlib` and `dylib` while `kind` is `example`
@@ -450,9 +467,47 @@ pub struct Target {
pub doc: bool,
}
-#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)]
+impl Target {
+ fn is_kind(&self, name: &str) -> bool {
+ self.kind.iter().any(|kind| kind == name)
+ }
+
+ /// Return true if this target is of kind "lib".
+ pub fn is_lib(&self) -> bool {
+ self.is_kind("lib")
+ }
+
+ /// Return true if this target is of kind "bin".
+ pub fn is_bin(&self) -> bool {
+ self.is_kind("bin")
+ }
+
+ /// Return true if this target is of kind "example".
+ pub fn is_example(&self) -> bool {
+ self.is_kind("example")
+ }
+
+ /// Return true if this target is of kind "test".
+ pub fn is_test(&self) -> bool {
+ self.is_kind("test")
+ }
+
+ /// Return true if this target is of kind "bench".
+ pub fn is_bench(&self) -> bool {
+ self.is_kind("bench")
+ }
+
+ /// Return true if this target is of kind "custom-build".
+ pub fn is_custom_build(&self) -> bool {
+ self.is_kind("custom-build")
+ }
+}
+
+/// The Rust edition
+///
+/// As of writing this comment rust editions 2024, 2027 and 2030 are not actually a thing yet but are parsed nonetheless for future proofing.
+#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[non_exhaustive]
-/// The rust edition
pub enum Edition {
/// Edition 2015
#[serde(rename = "2015")]
@@ -463,6 +518,36 @@ pub enum Edition {
/// Edition 2021
#[serde(rename = "2021")]
E2021,
+ #[doc(hidden)]
+ #[serde(rename = "2024")]
+ _E2024,
+ #[doc(hidden)]
+ #[serde(rename = "2027")]
+ _E2027,
+ #[doc(hidden)]
+ #[serde(rename = "2030")]
+ _E2030,
+}
+
+impl Edition {
+ /// Return the string representation of the edition
+ pub fn as_str(&self) -> &'static str {
+ use Edition::*;
+ match self {
+ E2015 => "2015",
+ E2018 => "2018",
+ E2021 => "2021",
+ _E2024 => "2024",
+ _E2027 => "2027",
+ _E2030 => "2030",
+ }
+ }
+}
+
+impl fmt::Display for Edition {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ f.write_str(self.as_str())
+ }
}
impl Default for Edition {
@@ -497,7 +582,7 @@ pub struct MetadataCommand {
manifest_path: Option<PathBuf>,
/// Current directory of the `cargo metadata` process.
current_dir: Option<PathBuf>,
- /// Output information only about the root package and don't fetch dependencies.
+ /// Output information only about workspace members and don't fetch dependencies.
no_deps: bool,
/// Collections of `CargoOpt::SomeFeatures(..)`
features: Vec<String>,
@@ -508,6 +593,11 @@ pub struct MetadataCommand {
/// Arbitrary command line flags to pass to `cargo`. These will be added
/// to the end of the command line invocation.
other_options: Vec<String>,
+ /// Arbitrary environment variables to set when running `cargo`. These will be merged into
+ /// the calling environment, overriding any which clash.
+ env: HashMap<OsString, OsString>,
+ /// Show stderr
+ verbose: bool,
}
impl MetadataCommand {
@@ -533,7 +623,7 @@ impl MetadataCommand {
self.current_dir = Some(path.into());
self
}
- /// Output information only about the root package and don't fetch dependencies.
+ /// Output information only about workspace members and don't fetch dependencies.
pub fn no_deps(&mut self) -> &mut MetadataCommand {
self.no_deps = true;
self
@@ -603,6 +693,38 @@ impl MetadataCommand {
self
}
+ /// Arbitrary environment variables to set when running `cargo`. These will be merged into
+ /// the calling environment, overriding any which clash.
+ ///
+ /// Some examples of when you may want to use this:
+ /// 1. Setting cargo config values without needing a .cargo/config.toml file, e.g. to set
+ /// `CARGO_NET_GIT_FETCH_WITH_CLI=true`
+ /// 2. To specify a custom path to RUSTC if your rust toolchain components aren't laid out in
+ /// the way cargo expects by default.
+ ///
+ /// ```no_run
+ /// # use cargo_metadata::{CargoOpt, MetadataCommand};
+ /// MetadataCommand::new()
+ /// .env("CARGO_NET_GIT_FETCH_WITH_CLI", "true")
+ /// .env("RUSTC", "/path/to/rustc")
+ /// // ...
+ /// # ;
+ /// ```
+ pub fn env<K: Into<OsString>, V: Into<OsString>>(
+ &mut self,
+ key: K,
+ val: V,
+ ) -> &mut MetadataCommand {
+ self.env.insert(key.into(), val.into());
+ self
+ }
+
+ /// Set whether to show stderr
+ pub fn verbose(&mut self, verbose: bool) -> &mut MetadataCommand {
+ self.verbose = verbose;
+ self
+ }
+
/// Builds a command for `cargo metadata`. This is the first
/// part of the work of `exec`.
pub fn cargo_command(&self) -> Command {
@@ -637,6 +759,8 @@ impl MetadataCommand {
}
cmd.args(&self.other_options);
+ cmd.envs(&self.env);
+
cmd
}
@@ -649,7 +773,11 @@ impl MetadataCommand {
/// Runs configured `cargo metadata` and returns parsed `Metadata`.
pub fn exec(&self) -> Result<Metadata> {
- let output = self.cargo_command().output()?;
+ let mut command = self.cargo_command();
+ if self.verbose {
+ command.stderr(Stdio::inherit());
+ }
+ let output = command.output()?;
if !output.status.success() {
return Err(Error::CargoMetadata {
stderr: String::from_utf8(output.stderr)?,
diff --git a/vendor/cargo_metadata/src/messages.rs b/vendor/cargo_metadata/src/messages.rs
index 0d086d3c3..ea2abd250 100644
--- a/vendor/cargo_metadata/src/messages.rs
+++ b/vendor/cargo_metadata/src/messages.rs
@@ -34,6 +34,9 @@ pub struct ArtifactProfile {
pub struct Artifact {
/// The package this artifact belongs to
pub package_id: PackageId,
+ /// Path to the `Cargo.toml` file
+ #[serde(default)]
+ pub manifest_path: Utf8PathBuf,
/// The target this artifact was compiled for
pub target: Target,
/// The profile this artifact was compiled with
diff --git a/vendor/cargo_metadata/tests/test_samples.rs b/vendor/cargo_metadata/tests/test_samples.rs
index 27a02f58f..3c747c595 100644
--- a/vendor/cargo_metadata/tests/test_samples.rs
+++ b/vendor/cargo_metadata/tests/test_samples.rs
@@ -344,6 +344,7 @@ fn all_the_fields() {
assert_eq!(all.categories, vec!["command-line-utilities"]);
assert_eq!(all.keywords, vec!["cli"]);
assert_eq!(all.readme, Some(Utf8PathBuf::from("README.md")));
+ assert!(all.readme().unwrap().ends_with("tests/all/README.md"));
assert_eq!(
all.repository,
Some("https://github.com/oli-obk/cargo_metadata/".to_string())
@@ -532,9 +533,9 @@ fn current_dir() {
fn parse_stream_is_robust() {
// Proc macros can print stuff to stdout, which naturally breaks JSON messages.
// Let's check that we don't die horribly in this case, and report an error.
- let json_output = r##"{"reason":"compiler-artifact","package_id":"chatty 0.1.0 (path+file:///chatty-macro/chatty)","target":{"kind":["proc-macro"],"crate_types":["proc-macro"],"name":"chatty","src_path":"/chatty-macro/chatty/src/lib.rs","edition":"2018","doctest":true},"profile":{"opt_level":"0","debuginfo":2,"debug_assertions":true,"overflow_checks":true,"test":false},"features":[],"filenames":["/chatty-macro/target/debug/deps/libchatty-f2adcff24cdf3bb2.so"],"executable":null,"fresh":false}
+ let json_output = r##"{"reason":"compiler-artifact","package_id":"chatty 0.1.0 (path+file:///chatty-macro/chatty)","manifest_path":"chatty-macro/Cargo.toml","target":{"kind":["proc-macro"],"crate_types":["proc-macro"],"name":"chatty","src_path":"/chatty-macro/chatty/src/lib.rs","edition":"2018","doctest":true},"profile":{"opt_level":"0","debuginfo":2,"debug_assertions":true,"overflow_checks":true,"test":false},"features":[],"filenames":["/chatty-macro/target/debug/deps/libchatty-f2adcff24cdf3bb2.so"],"executable":null,"fresh":false}
Evil proc macro was here!
-{"reason":"compiler-artifact","package_id":"chatty-macro 0.1.0 (path+file:///chatty-macro)","target":{"kind":["lib"],"crate_types":["lib"],"name":"chatty-macro","src_path":"/chatty-macro/src/lib.rs","edition":"2018","doctest":true},"profile":{"opt_level":"0","debuginfo":2,"debug_assertions":true,"overflow_checks":true,"test":false},"features":[],"filenames":["/chatty-macro/target/debug/libchatty_macro.rlib","/chatty-macro/target/debug/deps/libchatty_macro-cb5956ed52a11fb6.rmeta"],"executable":null,"fresh":false}
+{"reason":"compiler-artifact","package_id":"chatty-macro 0.1.0 (path+file:///chatty-macro)","manifest_path":"chatty-macro/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"chatty-macro","src_path":"/chatty-macro/src/lib.rs","edition":"2018","doctest":true},"profile":{"opt_level":"0","debuginfo":2,"debug_assertions":true,"overflow_checks":true,"test":false},"features":[],"filenames":["/chatty-macro/target/debug/libchatty_macro.rlib","/chatty-macro/target/debug/deps/libchatty_macro-cb5956ed52a11fb6.rmeta"],"executable":null,"fresh":false}
"##;
let mut n_messages = 0;
let mut text = String::new();
@@ -622,3 +623,25 @@ fn depkind_to_string() {
assert_eq!(DependencyKind::Build.to_string(), "build");
assert_eq!(DependencyKind::Unknown.to_string(), "Unknown");
}
+
+#[test]
+fn basic_workspace_root_package_exists() {
+ // First try with dependencies
+ let meta = MetadataCommand::new()
+ .manifest_path("tests/basic_workspace/Cargo.toml")
+ .exec()
+ .unwrap();
+ assert_eq!(meta.root_package().unwrap().name, "ex_bin");
+ // Now with no_deps, it should still work exactly the same
+ let meta = MetadataCommand::new()
+ .manifest_path("tests/basic_workspace/Cargo.toml")
+ .no_deps()
+ .exec()
+ .unwrap();
+ assert_eq!(
+ meta.root_package()
+ .expect("workspace root still exists when no_deps used")
+ .name,
+ "ex_bin"
+ );
+}
diff --git a/vendor/cc/.cargo-checksum.json b/vendor/cc/.cargo-checksum.json
index 1b81a54d2..4dc2fe239 100644
--- a/vendor/cc/.cargo-checksum.json
+++ b/vendor/cc/.cargo-checksum.json
@@ -1 +1 @@
-{"files":{"Cargo.lock":"35e9b5c9b3f3c70765a2749ea977aa0b2c8f5ce8872afbd4a5ba7cd59befba6a","Cargo.toml":"129464bf762db9e7db00f3e80d4b702b8c69a6e5fab070db0c8e66d4f693765e","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"378f5840b258e2779c39418f3f2d7b2ba96f1c7917dd6be0713f88305dbda397","README.md":"58af5106352aafa62175a90f8a5f25fa114028bf909220dc0735d79745999ec1","src/bin/gcc-shim.rs":"b77907875029494b6288841c3aed2e4939ed40708c7f597fca5c9e2570490ca6","src/com.rs":"29d0dee08a656ab1a4cc3e5fe24542e0fab5c1373cbc9b05059f7572cf9b8313","src/lib.rs":"2403bbe39ff511ea5a517c0841d825173a4fdc8a0899c64282bba49127f0dc33","src/registry.rs":"98ae2b71781acc49297e5544fa0cf059f735636f8f1338edef8dbf7232443945","src/setup_config.rs":"72deaf1927c0b713fd5c2b2d5b8f0ea3a303a00fda1579427895cac26a94122d","src/vs_instances.rs":"2d3f8278a803b0e7052f4eeb1979b29f963dd0143f4458e2cb5f33c4e5f0963b","src/winapi.rs":"e128e95b2d39ae7a02f54a7e25d33c488c14759b9f1a50a449e10545856950c3","src/windows_registry.rs":"c0340379c1f540cf96f45bbd4cf8fc28db555826f30ac937b75b87e4377b716b","tests/cc_env.rs":"e02b3b0824ad039b47e4462c5ef6dbe6c824c28e7953af94a0f28f7b5158042e","tests/cflags.rs":"57f06eb5ce1557e5b4a032d0c4673e18fbe6f8d26c1deb153126e368b96b41b3","tests/cxxflags.rs":"c2c6c6d8a0d7146616fa1caed26876ee7bc9fcfffd525eb4743593cade5f3371","tests/support/mod.rs":"a3c8d116973bb16066bf6ec4de5143183f97de7aad085d85f8118a2eaac3e1e0","tests/test.rs":"61fb35ae6dd5cf506ada000bdd82c92e9f8eac9cc053b63e83d3f897436fbf8f"},"package":"e9f73505338f7d905b19d18738976aae232eb46b8efc15554ffc56deb5d9ebe4"} \ No newline at end of file
+{"files":{"Cargo.lock":"23c26d62ba5114f5ac6e7ffa3ea233cea77e5cb7f98d9f056f40fe2c49971f67","Cargo.toml":"fd4b39488866b6717476fadc460ff91c89511628080769516eec452c0def8bc7","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"378f5840b258e2779c39418f3f2d7b2ba96f1c7917dd6be0713f88305dbda397","README.md":"58af5106352aafa62175a90f8a5f25fa114028bf909220dc0735d79745999ec1","src/bin/gcc-shim.rs":"b77907875029494b6288841c3aed2e4939ed40708c7f597fca5c9e2570490ca6","src/com.rs":"29d0dee08a656ab1a4cc3e5fe24542e0fab5c1373cbc9b05059f7572cf9b8313","src/lib.rs":"e0cc228db97675d6a0d86b219a20e9e48925a1ccbfd9e9fd038ccf6ef129957e","src/registry.rs":"98ae2b71781acc49297e5544fa0cf059f735636f8f1338edef8dbf7232443945","src/setup_config.rs":"72deaf1927c0b713fd5c2b2d5b8f0ea3a303a00fda1579427895cac26a94122d","src/vs_instances.rs":"2d3f8278a803b0e7052f4eeb1979b29f963dd0143f4458e2cb5f33c4e5f0963b","src/winapi.rs":"e128e95b2d39ae7a02f54a7e25d33c488c14759b9f1a50a449e10545856950c3","src/windows_registry.rs":"c0340379c1f540cf96f45bbd4cf8fc28db555826f30ac937b75b87e4377b716b","tests/cc_env.rs":"e02b3b0824ad039b47e4462c5ef6dbe6c824c28e7953af94a0f28f7b5158042e","tests/cflags.rs":"57f06eb5ce1557e5b4a032d0c4673e18fbe6f8d26c1deb153126e368b96b41b3","tests/cxxflags.rs":"c2c6c6d8a0d7146616fa1caed26876ee7bc9fcfffd525eb4743593cade5f3371","tests/support/mod.rs":"a3c8d116973bb16066bf6ec4de5143183f97de7aad085d85f8118a2eaac3e1e0","tests/test.rs":"61fb35ae6dd5cf506ada000bdd82c92e9f8eac9cc053b63e83d3f897436fbf8f"},"package":"a20104e2335ce8a659d6dd92a51a767a0c062599c73b343fd152cb401e828c3d"} \ No newline at end of file
diff --git a/vendor/cc/Cargo.lock b/vendor/cc/Cargo.lock
index c9564008e..2d065bc6a 100644
--- a/vendor/cc/Cargo.lock
+++ b/vendor/cc/Cargo.lock
@@ -10,7 +10,7 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]]
name = "cc"
-version = "1.0.77"
+version = "1.0.78"
dependencies = [
"jobserver",
"tempfile",
@@ -51,9 +51,9 @@ dependencies = [
[[package]]
name = "libc"
-version = "0.2.137"
+version = "0.2.138"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fc7fcc620a3bff7cdd7a365be3376c97191aeaccc2a603e600951e452615bf89"
+checksum = "db6d7e329c562c5dfab7a46a2afabc8b987ab9a4834c9d1ca04dc54c1546cef8"
[[package]]
name = "redox_syscall"
diff --git a/vendor/cc/Cargo.toml b/vendor/cc/Cargo.toml
index 4ec5fa658..c4ec0bf79 100644
--- a/vendor/cc/Cargo.toml
+++ b/vendor/cc/Cargo.toml
@@ -12,7 +12,7 @@
[package]
edition = "2018"
name = "cc"
-version = "1.0.77"
+version = "1.0.78"
authors = ["Alex Crichton <alex@alexcrichton.com>"]
exclude = ["/.github"]
description = """
diff --git a/vendor/cc/src/lib.rs b/vendor/cc/src/lib.rs
index 486d67e0b..1ebd2cc7a 100644
--- a/vendor/cc/src/lib.rs
+++ b/vendor/cc/src/lib.rs
@@ -56,11 +56,12 @@
#![allow(deprecated)]
#![deny(missing_docs)]
-use std::collections::HashMap;
+use std::collections::{hash_map, HashMap};
use std::env;
use std::ffi::{OsStr, OsString};
use std::fmt::{self, Display, Formatter};
use std::fs;
+use std::hash::Hasher;
use std::io::{self, BufRead, BufReader, Read, Write};
use std::path::{Component, Path, PathBuf};
use std::process::{Child, Command, Stdio};
@@ -1023,7 +1024,24 @@ impl Build {
let mut objects = Vec::new();
for file in self.files.iter() {
- let obj = dst.join(file).with_extension("o");
+ let obj = if file.has_root() {
+ // If `file` is an absolute path, prefix the `basename`
+ // with the `dirname`'s hash to ensure name uniqueness.
+ let basename = file
+ .file_name()
+ .ok_or_else(|| Error::new(ErrorKind::InvalidArgument, "file_name() failure"))?
+ .to_string_lossy();
+ let dirname = file
+ .parent()
+ .ok_or_else(|| Error::new(ErrorKind::InvalidArgument, "parent() failure"))?
+ .to_string_lossy();
+ let mut hasher = hash_map::DefaultHasher::new();
+ hasher.write(dirname.to_string().as_bytes());
+ dst.join(format!("{:016x}-{}", hasher.finish(), basename))
+ .with_extension("o")
+ } else {
+ dst.join(file).with_extension("o")
+ };
let obj = if !obj.starts_with(&dst) {
dst.join(obj.file_name().ok_or_else(|| {
Error::new(ErrorKind::IOError, "Getting object file details failed.")
@@ -1339,12 +1357,14 @@ impl Build {
}
fn compile_object(&self, obj: &Object) -> Result<(), Error> {
- let is_asm = is_asm(&obj.src);
+ let asm_ext = AsmFileExt::from_path(&obj.src);
+ let is_asm = asm_ext.is_some();
let target = self.get_target()?;
let msvc = target.contains("msvc");
let compiler = self.try_get_compiler()?;
let clang = compiler.family == ToolFamily::Clang;
- let (mut cmd, name) = if msvc && is_asm {
+
+ let (mut cmd, name) = if msvc && asm_ext == Some(AsmFileExt::DotAsm) {
self.msvc_macro_assembler()?
} else {
let mut cmd = compiler.to_command();
@@ -1367,7 +1387,7 @@ impl Build {
if !msvc || !is_asm || !is_arm {
cmd.arg("-c");
}
- if self.cuda && self.files.len() > 1 {
+ if self.cuda && self.cuda_file_count() > 1 {
cmd.arg("--device-c");
}
if is_asm {
@@ -1690,7 +1710,7 @@ impl Build {
cmd.args.push("--target=aarch64-unknown-windows-gnu".into())
}
} else {
- cmd.args.push(format!("--target={}", target).into());
+ cmd.push_cc_arg(format!("--target={}", target).into());
}
}
}
@@ -2035,7 +2055,7 @@ impl Build {
self.assemble_progressive(dst, chunk)?;
}
- if self.cuda {
+ if self.cuda && self.cuda_file_count() > 0 {
// Link the device-side code and add it to the target library,
// so that non-CUDA linker can link the final binary.
@@ -2645,10 +2665,29 @@ impl Build {
"emar".to_string()
} else if target.contains("msvc") {
- match windows_registry::find(&target, "lib.exe") {
- Some(t) => return Ok((t, "lib.exe".to_string())),
- None => "lib.exe".to_string(),
+ let compiler = self.get_base_compiler()?;
+ let mut lib = String::new();
+ if compiler.family == (ToolFamily::Msvc { clang_cl: true }) {
+ // See if there is 'llvm-lib' next to 'clang-cl'
+ // Another possibility could be to see if there is 'clang'
+ // next to 'clang-cl' and use 'search_programs()' to locate
+ // 'llvm-lib'. This is because 'clang-cl' doesn't support
+ // the -print-search-dirs option.
+ if let Some(mut cmd) = which(&compiler.path) {
+ cmd.pop();
+ cmd.push("llvm-lib.exe");
+ if let Some(llvm_lib) = which(&cmd) {
+ lib = llvm_lib.to_str().unwrap().to_owned();
+ }
+ }
+ }
+ if lib.is_empty() {
+ lib = match windows_registry::find(&target, "lib.exe") {
+ Some(t) => return Ok((t, "lib.exe".to_string())),
+ None => "lib.exe".to_string(),
+ }
}
+ lib
} else if target.contains("illumos") {
// The default 'ar' on illumos uses a non-standard flags,
// but the OS comes bundled with a GNU-compatible variant.
@@ -3010,6 +3049,13 @@ impl Build {
cache.insert(sdk.into(), ret.clone());
Ok(ret)
}
+
+ fn cuda_file_count(&self) -> usize {
+ self.files
+ .iter()
+ .filter(|file| file.extension() == Some(OsStr::new("cu")))
+ .count()
+ }
}
impl Default for Build {
@@ -3496,14 +3542,27 @@ fn which(tool: &Path) -> Option<PathBuf> {
})
}
-/// Check if the file's extension is either "asm" or "s", case insensitive.
-fn is_asm(file: &Path) -> bool {
- if let Some(ext) = file.extension() {
- if let Some(ext) = ext.to_str() {
- let ext = ext.to_lowercase();
- return ext == "asm" || ext == "s";
+#[derive(Clone, Copy, PartialEq)]
+enum AsmFileExt {
+ /// `.asm` files. On MSVC targets, we assume these should be passed to MASM
+ /// (`ml{,64}.exe`).
+ DotAsm,
+ /// `.s` or `.S` files, which do not have the special handling on MSVC targets.
+ DotS,
+}
+
+impl AsmFileExt {
+ fn from_path(file: &Path) -> Option<Self> {
+ if let Some(ext) = file.extension() {
+ if let Some(ext) = ext.to_str() {
+ let ext = ext.to_lowercase();
+ match &*ext {
+ "asm" => return Some(AsmFileExt::DotAsm),
+ "s" => return Some(AsmFileExt::DotS),
+ _ => return None,
+ }
+ }
}
+ None
}
-
- false
}
diff --git a/vendor/compiler_builtins/.cargo-checksum.json b/vendor/compiler_builtins/.cargo-checksum.json
index 54ae276f1..f32559335 100644
--- a/vendor/compiler_builtins/.cargo-checksum.json
+++ b/vendor/compiler_builtins/.cargo-checksum.json
@@ -1 +1 @@
-{"files":{"Cargo.lock":"a9e7ce22f7353779f9059b6b92112460a3918f153eac67f97ef4480422fdea47","Cargo.toml":"ac23c639d992d31e4aa00259623a3a1bf2e28c14ae6eec9bc2c6fe61d4249cda","LICENSE.txt":"0e13fed90654e0bc677d624a2d770833a09541fe0c0bdb3d051b3d081207393a","README.md":"5eb36fbab30693dbbe9f0de54749c95bd06fd6e42013b5b9eff3c062b9fdd34f","build.rs":"eea8b74d2b7ad2d3b51df7900d9af31b37ee00faacd9deff1a486d7b557e228a","examples/intrinsics.rs":"a7aa69c17af3aa8f6edff32c214e80827d3cbe3aea386a2be42244444752d253","libm/src/math/acos.rs":"fb066ba84aba1372d706425ec14f35ff8d971756d15eeebd22ecf42a716493bb","libm/src/math/acosf.rs":"a112b82309bba1d35c4e3d6ad4d6c21ef305343d9ab601ddf4bc61d43bc9f1af","libm/src/math/acosh.rs":"99de01ded7922bb93a882ad5ad8b472b5cae0059dea0bdca2077f65e94483150","libm/src/math/acoshf.rs":"10750c4d39ef6717b20a15ef1ce43e15eb851682d2f820f7e94501adec98b9a5","libm/src/math/asin.rs":"095a1e98996daff45df0b154ca0ec35bbf31db964ee9fdda0207308cb20df441","libm/src/math/asinf.rs":"49cccb4db2881982643a4a7d5453f4f8daf527711bbb67313607a3c178856d61","libm/src/math/asinh.rs":"4dd51affa71cce34a192ad66154e248f8d1c4b40fb497f29052333e425bb740f","libm/src/math/asinhf.rs":"914bfecf449f5e2bce786aa12c056d419073c6011d41c1bab7c39ba765fa4c53","libm/src/math/atan.rs":"d4fe46e1c5739dd09997869dcfbc3c85f03c534af52e700d6c6bcf9c3fedda07","libm/src/math/atan2.rs":"2623bc8ca707d13a7092ce49adf68e9cbf4452ad1bf4a861dc40ca858606a747","libm/src/math/atan2f.rs":"dd01943e0e1f1955912e5c3ffc9467529cf64bd02ac0a6ad5ab31dbe6657f05d","libm/src/math/atanf.rs":"e41b41569474a59c970ede3538e00bda4072cf4d90040017101cc79d7dc28caa","libm/src/math/atanh.rs":"57a8fb3f0f116fa4a966ac6bc2abd5f80236ead8e79013f468bd3786921f7110","libm/src/math/atanhf.rs":"6f2e57aaec1b5fc7609cb3938b3d155f51b4237dbda530739c34a0448cd9beb9","libm/src/math/cbrt.rs":"f2c45612d2eecd93cfcdd9ebf824c754fc8f8dfd6d16862c0b9c4ccea78c2a0f","libm/src/math/cbrtf.rs":"ad0b483854aa9f17a44d36c049bf0e8ebab34c27e90b787c05f45cc230ec7d19","libm/src/math/ceil.rs":"57ba5b6e207a0ccbd34190d1aa544389ca12126be23821dfb5746497f620ce03","libm/src/math/ceilf.rs":"c922a0475a599b9ea5473e615f74700b99707cebd6927f24ea59cb2a3cb3bbc3","libm/src/math/copysign.rs":"8b6440a251f0f1509d87f18122f74d0d5c03d0b60517e89e441434a3c5d84591","libm/src/math/copysignf.rs":"87d35436d224852ada93a2e93f6730cf1a727b808dd10e7d49ab4585866e336b","libm/src/math/cos.rs":"74babdc13ede78e400c5ca1854c3e22d2e08cbdc5618aefa5bba6f9303ef65b6","libm/src/math/cosf.rs":"09c40f93c445b741e22477ceedf163ca33b6a47f973f7c9876cfba2692edb29c","libm/src/math/cosh.rs":"0d0a7cef18577f321996b8b87561963139f754ad7f2ea0a3b3883811f3f0693a","libm/src/math/coshf.rs":"be8ca8739e4cf1978425b349f941cb4838bba8c10cb559c7940b9fd4fdde21ad","libm/src/math/erf.rs":"52cc9d9d54074a692001fb2d8215cd6903b645d4291ea20482455bc7f6947726","libm/src/math/erff.rs":"d37af67007fe4e9bce994c8c9805dd8af1b0ada68a10db8d8db13424dce65d09","libm/src/math/exp.rs":"ca7405ad0d1993fffcf9aae96f9256307bed3c4916545aaebd1cf1d2df1807fa","libm/src/math/exp10.rs":"2e136c6ecedd8e57a6c31796f57fae4546fcfd8bc6be66c836f553df9c74b907","libm/src/math/exp10f.rs":"9a3ce506ec587066a355ab74e0eb69a03a214ac405718087ae9772365050b20b","libm/src/math/exp2.rs":"94a9304a2ce3bc81f6d2aefd3cde6faa30f13260d46cb13692863cdea1c9a3a1","libm/src/math/exp2f.rs":"785f2630accd35118ec07bf60273e219ed91a215b956b1552eeea5bc2a708cc8","libm/src/math/expf.rs":"ec14c18f891a9e37735ec39e6fc2e9bf674a2c2e083f22e2533b481177359c98","libm/src/math/expm1.rs":"124069f456c8ad331f265c7509d9e223b2a300e461bbfd3d6adfdcdd2ee5b8ac","libm/src/math/expm1f.rs":"18e2116d31ea8410051cc709b9d04b754b0e3ba6758ee1bf0b48749f4999b840","libm/src/math/expo2.rs":"4f4f9fecfccb43f30c2784aa7c0bb656754a52b8ab431f7d1b551c673ab133f1","libm/src/math/fabs.rs":"e6c7db39f98508098cdf64ac0c2f53866c466149a7490afb9fe22b44c4dd81b3","libm/src/math/fabsf.rs":"83a1f5f4d9ca899ba2b701d7332e18b40258b83e111db4c5d8fab2cc1be58aa3","libm/src/math/fdim.rs":"8ec091996005207297c2389ae563e1b18dbc6a9eac951de29a976c5cd7bc32a7","libm/src/math/fdimf.rs":"c7f3f2269834d55be26b6580ddc07c42531577955fa4de35bad1e2a361085614","libm/src/math/fenv.rs":"916ae11e4763588518d64dee82afb41be9d1ee38ecc0679c821d4e7e22cd3dc5","libm/src/math/floor.rs":"5050804cae173af6775c0678d6c1aafb5ca2b744bc8a2f50d9d03b95dcee1fb0","libm/src/math/floorf.rs":"c903e0c57bc60a888c513eb7a873a87a4759ba68fc791b6b931652f8ee74cc03","libm/src/math/fma.rs":"d4995977bb2362efa5986002c904b28a63e0210c85758af37f9ef80278d46a07","libm/src/math/fmaf.rs":"1db6ee0d47ddbdb441cfe167edf89b431239f5805708fd0376cf5c01349a4bd6","libm/src/math/fmax.rs":"f6c8e96a8b1a170648d2fa3513e7b6b459085d708c839869f82e305fe58fac37","libm/src/math/fmaxf.rs":"dff0025433232e8a5ec7bd54d847ccf596d762ea4e35f5c54fbaac9404d732fd","libm/src/math/fmin.rs":"95b6cb66ca0e0e22276f0bf88dbe8fb69796a69a196a7491bd4802efbcf2e298","libm/src/math/fminf.rs":"304bc839b15ea3d84e68d2af9f40524ec120d30a36a667b22fcb98a6c258f4c7","libm/src/math/fmod.rs":"a1c0550fc7df8164733d914e222ff0966a2ab886d6e75a1098f24fe0283ae227","libm/src/math/fmodf.rs":"ee51ed092c0eeb8195f35735ff725cfd46612e0d689a7c483538bd92fbe61828","libm/src/math/frexp.rs":"28af70026922a8ab979744c7ad4d8faba6079c4743b7eeb6d14c983a982fbbcc","libm/src/math/frexpf.rs":"2e2593ae8002ba420809ebfaf737ef001cdc912354be3d978a8c0cb930350d4d","libm/src/math/hypot.rs":"841131c4a0cea75bc8a86e29f3f6d0815a61fc99731c9984651ce83d3050d218","libm/src/math/hypotf.rs":"5f317323edc2eb699580fe54b074b7e570a7734d51a0a149c0b49b54470a836c","libm/src/math/ilogb.rs":"d178ad7ca3439f82d565962b143f20448e45b2e2c51357b127abaec683297e32","libm/src/math/ilogbf.rs":"00f2b1b0496e21c6a42d68aea74d7156fa2ff0a735741b9051f3ca1cf0f57586","libm/src/math/j0.rs":"9572b6396c489927d332d0e717920e61ec0618e5e9c31f7eeeec70f5e4abab06","libm/src/math/j0f.rs":"802c8254bded9b3afb6eea8b9af240038a5a4a5d811396729f69ca509e3e7d87","libm/src/math/j1.rs":"97b1af1611fa3d110c2b349ee8e4176100132ea1391b619086b47ac063b81803","libm/src/math/j1f.rs":"9c9b128752e8ea2e7d81b637ba84907ab54a545e7602c49167b313743927930b","libm/src/math/jn.rs":"847d122334e5707ad9627146cddccc082a1f2f5bcd3e5ef54399013a7007ce88","libm/src/math/jnf.rs":"4045076f7d1a1b89882ed60d4dd60a4cbbc66b85cfb90491378c8015effcc476","libm/src/math/k_cos.rs":"f34a69e44d6b8901b03b578a75972f438ab20a7b98a0903fc1903d6fde3899be","libm/src/math/k_cosf.rs":"8f7117ff21cebf8e890a5bcfd7ea858a94172f4172b79a66d53824c2cb0888b1","libm/src/math/k_expo2.rs":"eb4ca9e6a525b7ea6da868c3cb136896682cc46f8396ba2a2ebc3ae9e9ba54b0","libm/src/math/k_expo2f.rs":"d51ad5df61cb5d1258bdb90c52bfed4572bb446a9337de9c04411ed9454ae0cb","libm/src/math/k_sin.rs":"14b2aba6ca07150c92768b5a72acaf5cde6a11d6619e14896512a7ba242e289a","libm/src/math/k_sinf.rs":"2775fcc710807164e6f37a4f8da3c8143cd5f16e19ce7c31c5591522151d7a96","libm/src/math/k_tan.rs":"a72beae4ccd9631eeeb61d6365bbeecae81c8411f3120a999c515cca0d5ea5c5","libm/src/math/k_tanf.rs":"6a794be56fa4b2f60452b9bab19af01c388f174560acbf829a351378ea39495d","libm/src/math/ldexp.rs":"b647f0096e80e4d926d8dd18d294c892ee2cb1778effe2c5e1b2664ae5cb1a4e","libm/src/math/ldexpf.rs":"98743fad2cd97a7be496f40ba3157ac1438fce0d0c25d5ab90c3b8c71c3fd0ed","libm/src/math/lgamma.rs":"0edd18e4f96bfcbe8b1b5af3eeca5208cd6d2d479dfa5ad117c9dfeccecf614f","libm/src/math/lgamma_r.rs":"f44a37aeccd56559ef784ae8edf217d14ad5cc2d910f0a65e70ffc86d7dc23dd","libm/src/math/lgammaf.rs":"967845357758b868a571857ec001f9f9154001110b8e97c08b6d10586bed9c49","libm/src/math/lgammaf_r.rs":"7143016d60e11fa235d53968125e57231b1104ce52149b5e1eed39629e0d1ff0","libm/src/math/log.rs":"b5e0c5f30d9e94351488732801be3107c12b854c3f95ad37e256dd88eeca408f","libm/src/math/log10.rs":"3425ff8be001fd1646ba15e254eb6ef4bdc6ccaf0cbee27ddf1fa84e04178b90","libm/src/math/log10f.rs":"fee4f71879bc4c99259e68c0c641364901629fb29a8ebddfcc0d090102cceddd","libm/src/math/log1p.rs":"9cf400852f165e6be19b97036ae9521fb9ca857d0a9a91c117d9123221622185","libm/src/math/log1pf.rs":"2716e6d2afa271996b7c8f47fd9e4952c88f4c1fd8c07c3e8ce8c62794bf71d8","libm/src/math/log2.rs":"dbbbfbaaa8aa6a4dbefea554ea3983090a9691228b011910c751f6adca912c40","libm/src/math/log2f.rs":"92a90350d8edce21c31c285c3e620fca7c62a2366008921715945c2c73b5b79f","libm/src/math/logf.rs":"845342cffc34d3db1f5ec12d8e5b773cd5a79056e28662fcb9bcd80207596f50","libm/src/math/mod.rs":"d694260529d51d0bc17f88ad557d852b9bb0bc3f7466cf7f62b679dc95ebba42","libm/src/math/modf.rs":"d012ed5a708ef52b6d1313c22a46cadaf5764dde1220816e3df2f03a0fcc60ae","libm/src/math/modff.rs":"f8f1e4c27a85d2cdb3c8e74439d59ef64aa543b948f22c23227d02d8388d61c2","libm/src/math/nextafter.rs":"3282e7eef214a32736fb6928d490198ad394b26b402b45495115b104839eebfe","libm/src/math/nextafterf.rs":"0937dc8a8155c19842c12181e741cec1f7df1f7a00cee81fcb2475e2842761b7","libm/src/math/pow.rs":"17c38297c5bf99accd915f292b777f8716ecf328916297c8bb9dfde6fd8ce522","libm/src/math/powf.rs":"2c423a0ea57fdc4e20f3533f744c6e6288c998b4de8f2914fafaa0e78be81b04","libm/src/math/rem_pio2.rs":"3e53234977daf61c89c29c940791714aad2f676a6f38188c7d17543a2aa8806f","libm/src/math/rem_pio2_large.rs":"482f31ff4e4eacf885f6130ae26a1d59f76b382059d6c742f30e5036811d3ca8","libm/src/math/rem_pio2f.rs":"07fb48f6d5cbadfd32ce4124b2b74af98b8391a2a6f36ce2a7d32e4500cb65ac","libm/src/math/remainder.rs":"63865f4370853c476b45bb27a5c54a4072146aa4a626835ae5263871a4e7e5dc","libm/src/math/remainderf.rs":"dd3fa432dbda8f2135428198be7bd69c57f8d13df3f365b12f52bf6a82352ac4","libm/src/math/remquo.rs":"3cc0bf55069f165c4843f2c358b3a27279c01e8cdd99f9057a3f7f31f45408f2","libm/src/math/remquof.rs":"cc749e18ecb7e766b8b8eeabdbf89ac99087d3d587e71e30f690676a3d2c1f9b","libm/src/math/rint.rs":"2c17047bcfd0ccdca8669f7cf70c628154ae4abc142660f30e37f9c073928706","libm/src/math/rintf.rs":"3b54af9eaa1bb6808159ca435246acf6a4e7aebbc344e3f4a4c5636345155897","libm/src/math/round.rs":"f10797ef15dd34a74e912ba8621d60bc0200c87b94308c9de3cc88d7aec4feb4","libm/src/math/roundf.rs":"27e37cfcf82373709e7debf9c0c18f7ed00ae0f5d97a214c388041f7a6996d35","libm/src/math/scalbn.rs":"b5c9d6d4177fe393cbfe1c634d75ce14b754f6cbce87c5bf979a9661491748a2","libm/src/math/scalbnf.rs":"4f198d06db1896386256fb9a5ac5b805b16b836226c18780a475cf18d7c1449c","libm/src/math/sin.rs":"bb483a2138ca779e03a191222636f0c60fd75a77a2a12f263bda4b6aa9136317","libm/src/math/sincos.rs":"1cf62a16c215e367f51078a3ba23a3f257682032a8f3c657293029a886b18d82","libm/src/math/sincosf.rs":"b0f589e6ada8215944d7784f420c6721c90387d799e349ce7676674f3c475e75","libm/src/math/sinf.rs":"dcddac1d56b084cbb8d0e019433c9c5fe2201d9b257a7dcf2f85c9a8f14b79cf","libm/src/math/sinh.rs":"d8ee4c7af883a526f36c1a6da13bb81fba9181b477e2f2538161a2bee97edc35","libm/src/math/sinhf.rs":"d06eb030ba9dbf7094df127262bfe99f149b4db49fa8ab8c15499660f1e46b26","libm/src/math/sqrt.rs":"824570a631c2542ccee68b65e3eb08fe79c037a29bbaaf54da5367e7b236124a","libm/src/math/sqrtf.rs":"4cf418d74f7751d522a642a9a8d6b86ee3472c6aaef44f0eb1bc26f4d8a90985","libm/src/math/tan.rs":"930ecedaadc60f704c2dfa4e15186f59713c1ba7d948529d215223b424827db5","libm/src/math/tanf.rs":"894156a3b107aee08461eb4e7e412fc049aa237d176ae705c6e3e2d7060d94e3","libm/src/math/tanh.rs":"f1f08eb98ed959a17370a7aaf0177be36e3764543424e78feb033ed3f5e8ec98","libm/src/math/tanhf.rs":"74027b0c672a4e64bdef6d7a3069b90caec50e1e7dbb2c12d2828f310502f41e","libm/src/math/tgamma.rs":"c889cfa49bbeb4dbb0941fe9fac3b4da7d5879dcf04a3b9bb6e56de529baf374","libm/src/math/tgammaf.rs":"0737b34777095d0e4d07fe533e8f105082dd4e8ece411bba6ae5993b45b9388c","libm/src/math/trunc.rs":"642264897cc1505e720c8cf313be81aa9fd53aae866644a2e988d01dbc77fd8a","libm/src/math/truncf.rs":"dee3607baf1af0f01deae46e429e097234c50b268eaefebbe716f19f38597900","src/arm.rs":"acf149932aa46a2755cf8cd2eb7d6ae249e46b1e10ad45ce5f924561945d1273","src/arm_linux.rs":"35a4cb7b75015543feb15b0c692da0faf0e6037d3b97a4a18067ba416eae1a70","src/float/add.rs":"3ec32ceaf470a89777b54f9cde61832fdadeade0f4894f268a949e968520bc57","src/float/cmp.rs":"79b1fdc8d5f943c4ad5ea4ad32623b18f63e17ac3852fbc64a4942228007e1fc","src/float/conv.rs":"e2b5e6fe398f35c7db4af62ba1fd79b39591fe1bfaf304ae825ed3c8cf902d9c","src/float/div.rs":"fe21115ecb1b3330569fd85cb51c650bf80683f152333db988d8e0d564a9ae11","src/float/extend.rs":"180b2e791c58e0526de0a798845c580ce3222c8a15c8665e6e6a4bf5cf1a34aa","src/float/mod.rs":"a91cf65abb6e715c5559e3e4bd87a69cd99a9552d54804d0b7137c02c513f158","src/float/mul.rs":"0d0c1f0c28c149ecadeafd459d3c4c9327e4cfcae2cba479957bb8010ef51a01","src/float/pow.rs":"2ada190738731eb6f24104f8fb8c4d6f03cfb16451536dbee32f2b33db0c4b19","src/float/sub.rs":"c2a87f4628f51d5d908d0f25b5d51ce0599dc559d5a72b20e131261f484d5848","src/float/trunc.rs":"d21d2a2f9a1918b4bbb594691e397972a7c04b74b2acf04016c55693abf6d24b","src/int/addsub.rs":"7ec45ce1ba15b56a5b7129d3e5722c4db764c6545306d3fa9090983bcabd6f17","src/int/leading_zeros.rs":"ccf5e9d098c80034dcf6e38437c9a2eb670fa8043558bbfb574f2293164729a6","src/int/mod.rs":"bab1b77535ceebdebb89fd4e59e7105f8c45347bb638351a626615b24544a0b1","src/int/mul.rs":"bb48d8fd42d8f9f5fe9271d8d0f7a92dbae320bf4346e19d1071eb2093cb8ed9","src/int/sdiv.rs":"ace4cb0ec388a38834e01cab2c5bc87182d31588dfc0b1ae117c11ed0c4781cf","src/int/shift.rs":"3967c28a8d61279546e91958d64745fec63f15aee9175eb0602cc6353830da6c","src/int/specialized_div_rem/asymmetric.rs":"27f5bf70a35109f9d4e4e1ad1e8003aa17da5a1e436bf3e63a493d7528a3a566","src/int/specialized_div_rem/binary_long.rs":"9f1ced81a394f000a21a329683144d68ee431a954136a3634eb55b1ee2cf6d51","src/int/specialized_div_rem/delegate.rs":"9df141af98e391361e25d71ae38d5e845a91d896edd2c041132fd46af8268e85","src/int/specialized_div_rem/mod.rs":"73c98b9f69cc9b101ae4c9081e82d66af1df4a58cf0c9bb2a8c8659265687f12","src/int/specialized_div_rem/norm_shift.rs":"3be7ee0dea545c1f702d9daf67dad2b624bf7b17b075c8b90d3d3f7b53df4c21","src/int/specialized_div_rem/trifecta.rs":"87eef69da255b809fd710b14f2eb3f9f59e3dac625f8564ebc8ba78f9763523b","src/int/udiv.rs":"3732b490a472505411577f008b92f489287745968ce6791665201201377d3475","src/lib.rs":"b1d55a4aa6ce37b086dd512060f380de4eb1944031eea4b4546403e007d38db2","src/macros.rs":"de690dffc59a5884ed06c67d38f06c41ed02fcd6318189397a0d4aafbd375ad8","src/math.rs":"3d7571ea68747f1e492e1fa5fe86512e0829654043f888892dbc0eb109fd0e69","src/mem/impls.rs":"a8d1c28a77d9b334872abbebfcba3fd1802175bef53c0b545e85242860698780","src/mem/mod.rs":"5034543d963149c14a6823bee32a1fb9dfd950c32153d37f97e9df1dc6c23129","src/mem/x86_64.rs":"9f740891f666acf384159128eef233d9e15c6120da8016370c6f9f05cc29d653","src/probestack.rs":"ef5c07e9b95de7b2b77a937789fcfefd9846274317489ad6d623e377c9888601","src/riscv.rs":"b43ede1713454c3e50b5a011964d336146155026cac6119767c96b70a165f10f","src/x86.rs":"117b50d6725ee0af0a7b3d197ea580655561f66a870ebc450d96af22bf7f39f6","src/x86_64.rs":"4f16bc9fad7757d48a6da3a078c715dd3a22154aadb4f1998d4c1b5d91396f9e"},"package":"13e81c6cd7ab79f51a0c927d22858d61ad12bd0b3865f0b13ece02a4486aeabb"} \ No newline at end of file
+{"files":{"Cargo.lock":"8875e3218be36f270df5da9194a8b49dd3762131ab5db87998fbf91a7e7a8ac7","Cargo.toml":"b7d74c9f0375b4ed4630c446b9a126e700821df6b4f4a2aa06054aea0d545269","LICENSE.txt":"0e13fed90654e0bc677d624a2d770833a09541fe0c0bdb3d051b3d081207393a","README.md":"5eb36fbab30693dbbe9f0de54749c95bd06fd6e42013b5b9eff3c062b9fdd34f","build.rs":"eea8b74d2b7ad2d3b51df7900d9af31b37ee00faacd9deff1a486d7b557e228a","examples/intrinsics.rs":"a7aa69c17af3aa8f6edff32c214e80827d3cbe3aea386a2be42244444752d253","libm/src/math/acos.rs":"fb066ba84aba1372d706425ec14f35ff8d971756d15eeebd22ecf42a716493bb","libm/src/math/acosf.rs":"a112b82309bba1d35c4e3d6ad4d6c21ef305343d9ab601ddf4bc61d43bc9f1af","libm/src/math/acosh.rs":"99de01ded7922bb93a882ad5ad8b472b5cae0059dea0bdca2077f65e94483150","libm/src/math/acoshf.rs":"10750c4d39ef6717b20a15ef1ce43e15eb851682d2f820f7e94501adec98b9a5","libm/src/math/asin.rs":"095a1e98996daff45df0b154ca0ec35bbf31db964ee9fdda0207308cb20df441","libm/src/math/asinf.rs":"49cccb4db2881982643a4a7d5453f4f8daf527711bbb67313607a3c178856d61","libm/src/math/asinh.rs":"4dd51affa71cce34a192ad66154e248f8d1c4b40fb497f29052333e425bb740f","libm/src/math/asinhf.rs":"914bfecf449f5e2bce786aa12c056d419073c6011d41c1bab7c39ba765fa4c53","libm/src/math/atan.rs":"d4fe46e1c5739dd09997869dcfbc3c85f03c534af52e700d6c6bcf9c3fedda07","libm/src/math/atan2.rs":"2623bc8ca707d13a7092ce49adf68e9cbf4452ad1bf4a861dc40ca858606a747","libm/src/math/atan2f.rs":"dd01943e0e1f1955912e5c3ffc9467529cf64bd02ac0a6ad5ab31dbe6657f05d","libm/src/math/atanf.rs":"e41b41569474a59c970ede3538e00bda4072cf4d90040017101cc79d7dc28caa","libm/src/math/atanh.rs":"57a8fb3f0f116fa4a966ac6bc2abd5f80236ead8e79013f468bd3786921f7110","libm/src/math/atanhf.rs":"6f2e57aaec1b5fc7609cb3938b3d155f51b4237dbda530739c34a0448cd9beb9","libm/src/math/cbrt.rs":"f2c45612d2eecd93cfcdd9ebf824c754fc8f8dfd6d16862c0b9c4ccea78c2a0f","libm/src/math/cbrtf.rs":"ad0b483854aa9f17a44d36c049bf0e8ebab34c27e90b787c05f45cc230ec7d19","libm/src/math/ceil.rs":"57ba5b6e207a0ccbd34190d1aa544389ca12126be23821dfb5746497f620ce03","libm/src/math/ceilf.rs":"c922a0475a599b9ea5473e615f74700b99707cebd6927f24ea59cb2a3cb3bbc3","libm/src/math/copysign.rs":"8b6440a251f0f1509d87f18122f74d0d5c03d0b60517e89e441434a3c5d84591","libm/src/math/copysignf.rs":"87d35436d224852ada93a2e93f6730cf1a727b808dd10e7d49ab4585866e336b","libm/src/math/cos.rs":"74babdc13ede78e400c5ca1854c3e22d2e08cbdc5618aefa5bba6f9303ef65b6","libm/src/math/cosf.rs":"09c40f93c445b741e22477ceedf163ca33b6a47f973f7c9876cfba2692edb29c","libm/src/math/cosh.rs":"0d0a7cef18577f321996b8b87561963139f754ad7f2ea0a3b3883811f3f0693a","libm/src/math/coshf.rs":"be8ca8739e4cf1978425b349f941cb4838bba8c10cb559c7940b9fd4fdde21ad","libm/src/math/erf.rs":"52cc9d9d54074a692001fb2d8215cd6903b645d4291ea20482455bc7f6947726","libm/src/math/erff.rs":"d37af67007fe4e9bce994c8c9805dd8af1b0ada68a10db8d8db13424dce65d09","libm/src/math/exp.rs":"ca7405ad0d1993fffcf9aae96f9256307bed3c4916545aaebd1cf1d2df1807fa","libm/src/math/exp10.rs":"2e136c6ecedd8e57a6c31796f57fae4546fcfd8bc6be66c836f553df9c74b907","libm/src/math/exp10f.rs":"9a3ce506ec587066a355ab74e0eb69a03a214ac405718087ae9772365050b20b","libm/src/math/exp2.rs":"94a9304a2ce3bc81f6d2aefd3cde6faa30f13260d46cb13692863cdea1c9a3a1","libm/src/math/exp2f.rs":"785f2630accd35118ec07bf60273e219ed91a215b956b1552eeea5bc2a708cc8","libm/src/math/expf.rs":"ec14c18f891a9e37735ec39e6fc2e9bf674a2c2e083f22e2533b481177359c98","libm/src/math/expm1.rs":"124069f456c8ad331f265c7509d9e223b2a300e461bbfd3d6adfdcdd2ee5b8ac","libm/src/math/expm1f.rs":"18e2116d31ea8410051cc709b9d04b754b0e3ba6758ee1bf0b48749f4999b840","libm/src/math/expo2.rs":"4f4f9fecfccb43f30c2784aa7c0bb656754a52b8ab431f7d1b551c673ab133f1","libm/src/math/fabs.rs":"e6c7db39f98508098cdf64ac0c2f53866c466149a7490afb9fe22b44c4dd81b3","libm/src/math/fabsf.rs":"83a1f5f4d9ca899ba2b701d7332e18b40258b83e111db4c5d8fab2cc1be58aa3","libm/src/math/fdim.rs":"8ec091996005207297c2389ae563e1b18dbc6a9eac951de29a976c5cd7bc32a7","libm/src/math/fdimf.rs":"c7f3f2269834d55be26b6580ddc07c42531577955fa4de35bad1e2a361085614","libm/src/math/fenv.rs":"916ae11e4763588518d64dee82afb41be9d1ee38ecc0679c821d4e7e22cd3dc5","libm/src/math/floor.rs":"5050804cae173af6775c0678d6c1aafb5ca2b744bc8a2f50d9d03b95dcee1fb0","libm/src/math/floorf.rs":"c903e0c57bc60a888c513eb7a873a87a4759ba68fc791b6b931652f8ee74cc03","libm/src/math/fma.rs":"d4995977bb2362efa5986002c904b28a63e0210c85758af37f9ef80278d46a07","libm/src/math/fmaf.rs":"1db6ee0d47ddbdb441cfe167edf89b431239f5805708fd0376cf5c01349a4bd6","libm/src/math/fmax.rs":"f6c8e96a8b1a170648d2fa3513e7b6b459085d708c839869f82e305fe58fac37","libm/src/math/fmaxf.rs":"dff0025433232e8a5ec7bd54d847ccf596d762ea4e35f5c54fbaac9404d732fd","libm/src/math/fmin.rs":"95b6cb66ca0e0e22276f0bf88dbe8fb69796a69a196a7491bd4802efbcf2e298","libm/src/math/fminf.rs":"304bc839b15ea3d84e68d2af9f40524ec120d30a36a667b22fcb98a6c258f4c7","libm/src/math/fmod.rs":"a1c0550fc7df8164733d914e222ff0966a2ab886d6e75a1098f24fe0283ae227","libm/src/math/fmodf.rs":"ee51ed092c0eeb8195f35735ff725cfd46612e0d689a7c483538bd92fbe61828","libm/src/math/frexp.rs":"28af70026922a8ab979744c7ad4d8faba6079c4743b7eeb6d14c983a982fbbcc","libm/src/math/frexpf.rs":"2e2593ae8002ba420809ebfaf737ef001cdc912354be3d978a8c0cb930350d4d","libm/src/math/hypot.rs":"841131c4a0cea75bc8a86e29f3f6d0815a61fc99731c9984651ce83d3050d218","libm/src/math/hypotf.rs":"5f317323edc2eb699580fe54b074b7e570a7734d51a0a149c0b49b54470a836c","libm/src/math/ilogb.rs":"d178ad7ca3439f82d565962b143f20448e45b2e2c51357b127abaec683297e32","libm/src/math/ilogbf.rs":"00f2b1b0496e21c6a42d68aea74d7156fa2ff0a735741b9051f3ca1cf0f57586","libm/src/math/j0.rs":"9572b6396c489927d332d0e717920e61ec0618e5e9c31f7eeeec70f5e4abab06","libm/src/math/j0f.rs":"802c8254bded9b3afb6eea8b9af240038a5a4a5d811396729f69ca509e3e7d87","libm/src/math/j1.rs":"97b1af1611fa3d110c2b349ee8e4176100132ea1391b619086b47ac063b81803","libm/src/math/j1f.rs":"9c9b128752e8ea2e7d81b637ba84907ab54a545e7602c49167b313743927930b","libm/src/math/jn.rs":"847d122334e5707ad9627146cddccc082a1f2f5bcd3e5ef54399013a7007ce88","libm/src/math/jnf.rs":"4045076f7d1a1b89882ed60d4dd60a4cbbc66b85cfb90491378c8015effcc476","libm/src/math/k_cos.rs":"f34a69e44d6b8901b03b578a75972f438ab20a7b98a0903fc1903d6fde3899be","libm/src/math/k_cosf.rs":"8f7117ff21cebf8e890a5bcfd7ea858a94172f4172b79a66d53824c2cb0888b1","libm/src/math/k_expo2.rs":"eb4ca9e6a525b7ea6da868c3cb136896682cc46f8396ba2a2ebc3ae9e9ba54b0","libm/src/math/k_expo2f.rs":"d51ad5df61cb5d1258bdb90c52bfed4572bb446a9337de9c04411ed9454ae0cb","libm/src/math/k_sin.rs":"14b2aba6ca07150c92768b5a72acaf5cde6a11d6619e14896512a7ba242e289a","libm/src/math/k_sinf.rs":"2775fcc710807164e6f37a4f8da3c8143cd5f16e19ce7c31c5591522151d7a96","libm/src/math/k_tan.rs":"a72beae4ccd9631eeeb61d6365bbeecae81c8411f3120a999c515cca0d5ea5c5","libm/src/math/k_tanf.rs":"6a794be56fa4b2f60452b9bab19af01c388f174560acbf829a351378ea39495d","libm/src/math/ldexp.rs":"b647f0096e80e4d926d8dd18d294c892ee2cb1778effe2c5e1b2664ae5cb1a4e","libm/src/math/ldexpf.rs":"98743fad2cd97a7be496f40ba3157ac1438fce0d0c25d5ab90c3b8c71c3fd0ed","libm/src/math/lgamma.rs":"0edd18e4f96bfcbe8b1b5af3eeca5208cd6d2d479dfa5ad117c9dfeccecf614f","libm/src/math/lgamma_r.rs":"f44a37aeccd56559ef784ae8edf217d14ad5cc2d910f0a65e70ffc86d7dc23dd","libm/src/math/lgammaf.rs":"967845357758b868a571857ec001f9f9154001110b8e97c08b6d10586bed9c49","libm/src/math/lgammaf_r.rs":"7143016d60e11fa235d53968125e57231b1104ce52149b5e1eed39629e0d1ff0","libm/src/math/log.rs":"b5e0c5f30d9e94351488732801be3107c12b854c3f95ad37e256dd88eeca408f","libm/src/math/log10.rs":"3425ff8be001fd1646ba15e254eb6ef4bdc6ccaf0cbee27ddf1fa84e04178b90","libm/src/math/log10f.rs":"fee4f71879bc4c99259e68c0c641364901629fb29a8ebddfcc0d090102cceddd","libm/src/math/log1p.rs":"9cf400852f165e6be19b97036ae9521fb9ca857d0a9a91c117d9123221622185","libm/src/math/log1pf.rs":"2716e6d2afa271996b7c8f47fd9e4952c88f4c1fd8c07c3e8ce8c62794bf71d8","libm/src/math/log2.rs":"dbbbfbaaa8aa6a4dbefea554ea3983090a9691228b011910c751f6adca912c40","libm/src/math/log2f.rs":"92a90350d8edce21c31c285c3e620fca7c62a2366008921715945c2c73b5b79f","libm/src/math/logf.rs":"845342cffc34d3db1f5ec12d8e5b773cd5a79056e28662fcb9bcd80207596f50","libm/src/math/mod.rs":"d694260529d51d0bc17f88ad557d852b9bb0bc3f7466cf7f62b679dc95ebba42","libm/src/math/modf.rs":"d012ed5a708ef52b6d1313c22a46cadaf5764dde1220816e3df2f03a0fcc60ae","libm/src/math/modff.rs":"f8f1e4c27a85d2cdb3c8e74439d59ef64aa543b948f22c23227d02d8388d61c2","libm/src/math/nextafter.rs":"3282e7eef214a32736fb6928d490198ad394b26b402b45495115b104839eebfe","libm/src/math/nextafterf.rs":"0937dc8a8155c19842c12181e741cec1f7df1f7a00cee81fcb2475e2842761b7","libm/src/math/pow.rs":"17c38297c5bf99accd915f292b777f8716ecf328916297c8bb9dfde6fd8ce522","libm/src/math/powf.rs":"2c423a0ea57fdc4e20f3533f744c6e6288c998b4de8f2914fafaa0e78be81b04","libm/src/math/rem_pio2.rs":"3e53234977daf61c89c29c940791714aad2f676a6f38188c7d17543a2aa8806f","libm/src/math/rem_pio2_large.rs":"482f31ff4e4eacf885f6130ae26a1d59f76b382059d6c742f30e5036811d3ca8","libm/src/math/rem_pio2f.rs":"07fb48f6d5cbadfd32ce4124b2b74af98b8391a2a6f36ce2a7d32e4500cb65ac","libm/src/math/remainder.rs":"63865f4370853c476b45bb27a5c54a4072146aa4a626835ae5263871a4e7e5dc","libm/src/math/remainderf.rs":"dd3fa432dbda8f2135428198be7bd69c57f8d13df3f365b12f52bf6a82352ac4","libm/src/math/remquo.rs":"3cc0bf55069f165c4843f2c358b3a27279c01e8cdd99f9057a3f7f31f45408f2","libm/src/math/remquof.rs":"cc749e18ecb7e766b8b8eeabdbf89ac99087d3d587e71e30f690676a3d2c1f9b","libm/src/math/rint.rs":"2c17047bcfd0ccdca8669f7cf70c628154ae4abc142660f30e37f9c073928706","libm/src/math/rintf.rs":"3b54af9eaa1bb6808159ca435246acf6a4e7aebbc344e3f4a4c5636345155897","libm/src/math/round.rs":"f10797ef15dd34a74e912ba8621d60bc0200c87b94308c9de3cc88d7aec4feb4","libm/src/math/roundf.rs":"27e37cfcf82373709e7debf9c0c18f7ed00ae0f5d97a214c388041f7a6996d35","libm/src/math/scalbn.rs":"b5c9d6d4177fe393cbfe1c634d75ce14b754f6cbce87c5bf979a9661491748a2","libm/src/math/scalbnf.rs":"4f198d06db1896386256fb9a5ac5b805b16b836226c18780a475cf18d7c1449c","libm/src/math/sin.rs":"bb483a2138ca779e03a191222636f0c60fd75a77a2a12f263bda4b6aa9136317","libm/src/math/sincos.rs":"1cf62a16c215e367f51078a3ba23a3f257682032a8f3c657293029a886b18d82","libm/src/math/sincosf.rs":"b0f589e6ada8215944d7784f420c6721c90387d799e349ce7676674f3c475e75","libm/src/math/sinf.rs":"dcddac1d56b084cbb8d0e019433c9c5fe2201d9b257a7dcf2f85c9a8f14b79cf","libm/src/math/sinh.rs":"d8ee4c7af883a526f36c1a6da13bb81fba9181b477e2f2538161a2bee97edc35","libm/src/math/sinhf.rs":"d06eb030ba9dbf7094df127262bfe99f149b4db49fa8ab8c15499660f1e46b26","libm/src/math/sqrt.rs":"824570a631c2542ccee68b65e3eb08fe79c037a29bbaaf54da5367e7b236124a","libm/src/math/sqrtf.rs":"4cf418d74f7751d522a642a9a8d6b86ee3472c6aaef44f0eb1bc26f4d8a90985","libm/src/math/tan.rs":"930ecedaadc60f704c2dfa4e15186f59713c1ba7d948529d215223b424827db5","libm/src/math/tanf.rs":"894156a3b107aee08461eb4e7e412fc049aa237d176ae705c6e3e2d7060d94e3","libm/src/math/tanh.rs":"f1f08eb98ed959a17370a7aaf0177be36e3764543424e78feb033ed3f5e8ec98","libm/src/math/tanhf.rs":"74027b0c672a4e64bdef6d7a3069b90caec50e1e7dbb2c12d2828f310502f41e","libm/src/math/tgamma.rs":"c889cfa49bbeb4dbb0941fe9fac3b4da7d5879dcf04a3b9bb6e56de529baf374","libm/src/math/tgammaf.rs":"0737b34777095d0e4d07fe533e8f105082dd4e8ece411bba6ae5993b45b9388c","libm/src/math/trunc.rs":"642264897cc1505e720c8cf313be81aa9fd53aae866644a2e988d01dbc77fd8a","libm/src/math/truncf.rs":"dee3607baf1af0f01deae46e429e097234c50b268eaefebbe716f19f38597900","src/arm.rs":"acf149932aa46a2755cf8cd2eb7d6ae249e46b1e10ad45ce5f924561945d1273","src/arm_linux.rs":"35a4cb7b75015543feb15b0c692da0faf0e6037d3b97a4a18067ba416eae1a70","src/float/add.rs":"3ec32ceaf470a89777b54f9cde61832fdadeade0f4894f268a949e968520bc57","src/float/cmp.rs":"79b1fdc8d5f943c4ad5ea4ad32623b18f63e17ac3852fbc64a4942228007e1fc","src/float/conv.rs":"d95b386e483d2bc77b2d5c41b62d01a8cc791fb3fb18ce97317947ecd5a3c02b","src/float/div.rs":"fe21115ecb1b3330569fd85cb51c650bf80683f152333db988d8e0d564a9ae11","src/float/extend.rs":"180b2e791c58e0526de0a798845c580ce3222c8a15c8665e6e6a4bf5cf1a34aa","src/float/mod.rs":"a91cf65abb6e715c5559e3e4bd87a69cd99a9552d54804d0b7137c02c513f158","src/float/mul.rs":"0d0c1f0c28c149ecadeafd459d3c4c9327e4cfcae2cba479957bb8010ef51a01","src/float/pow.rs":"2ada190738731eb6f24104f8fb8c4d6f03cfb16451536dbee32f2b33db0c4b19","src/float/sub.rs":"c2a87f4628f51d5d908d0f25b5d51ce0599dc559d5a72b20e131261f484d5848","src/float/trunc.rs":"d21d2a2f9a1918b4bbb594691e397972a7c04b74b2acf04016c55693abf6d24b","src/int/addsub.rs":"7ec45ce1ba15b56a5b7129d3e5722c4db764c6545306d3fa9090983bcabd6f17","src/int/leading_zeros.rs":"ccf5e9d098c80034dcf6e38437c9a2eb670fa8043558bbfb574f2293164729a6","src/int/mod.rs":"bab1b77535ceebdebb89fd4e59e7105f8c45347bb638351a626615b24544a0b1","src/int/mul.rs":"bb48d8fd42d8f9f5fe9271d8d0f7a92dbae320bf4346e19d1071eb2093cb8ed9","src/int/sdiv.rs":"ace4cb0ec388a38834e01cab2c5bc87182d31588dfc0b1ae117c11ed0c4781cf","src/int/shift.rs":"40e213fe382a7a1a469fdea85a26f1b0b4b681345f0f8ccaed3e423f19a73633","src/int/specialized_div_rem/asymmetric.rs":"27f5bf70a35109f9d4e4e1ad1e8003aa17da5a1e436bf3e63a493d7528a3a566","src/int/specialized_div_rem/binary_long.rs":"9f1ced81a394f000a21a329683144d68ee431a954136a3634eb55b1ee2cf6d51","src/int/specialized_div_rem/delegate.rs":"9df141af98e391361e25d71ae38d5e845a91d896edd2c041132fd46af8268e85","src/int/specialized_div_rem/mod.rs":"73c98b9f69cc9b101ae4c9081e82d66af1df4a58cf0c9bb2a8c8659265687f12","src/int/specialized_div_rem/norm_shift.rs":"3be7ee0dea545c1f702d9daf67dad2b624bf7b17b075c8b90d3d3f7b53df4c21","src/int/specialized_div_rem/trifecta.rs":"87eef69da255b809fd710b14f2eb3f9f59e3dac625f8564ebc8ba78f9763523b","src/int/udiv.rs":"3732b490a472505411577f008b92f489287745968ce6791665201201377d3475","src/lib.rs":"b1d55a4aa6ce37b086dd512060f380de4eb1944031eea4b4546403e007d38db2","src/macros.rs":"de690dffc59a5884ed06c67d38f06c41ed02fcd6318189397a0d4aafbd375ad8","src/math.rs":"3d7571ea68747f1e492e1fa5fe86512e0829654043f888892dbc0eb109fd0e69","src/mem/impls.rs":"a8d1c28a77d9b334872abbebfcba3fd1802175bef53c0b545e85242860698780","src/mem/mod.rs":"5034543d963149c14a6823bee32a1fb9dfd950c32153d37f97e9df1dc6c23129","src/mem/x86_64.rs":"9f740891f666acf384159128eef233d9e15c6120da8016370c6f9f05cc29d653","src/probestack.rs":"ef5c07e9b95de7b2b77a937789fcfefd9846274317489ad6d623e377c9888601","src/riscv.rs":"b43ede1713454c3e50b5a011964d336146155026cac6119767c96b70a165f10f","src/x86.rs":"117b50d6725ee0af0a7b3d197ea580655561f66a870ebc450d96af22bf7f39f6","src/x86_64.rs":"4f16bc9fad7757d48a6da3a078c715dd3a22154aadb4f1998d4c1b5d91396f9e"},"package":"f867ce54c09855ccd135ad4a50c777182a0c7af5ff20a8f537617bd648b10d50"} \ No newline at end of file
diff --git a/vendor/compiler_builtins/Cargo.lock b/vendor/compiler_builtins/Cargo.lock
index 4784f2917..4e415bc2c 100644
--- a/vendor/compiler_builtins/Cargo.lock
+++ b/vendor/compiler_builtins/Cargo.lock
@@ -10,7 +10,7 @@ checksum = "7db2f146208d7e0fbee761b09cd65a7f51ccc38705d4e7262dad4d73b12a76b1"
[[package]]
name = "compiler_builtins"
-version = "0.1.85"
+version = "0.1.87"
dependencies = [
"cc",
"rustc-std-workspace-core",
diff --git a/vendor/compiler_builtins/Cargo.toml b/vendor/compiler_builtins/Cargo.toml
index 0a3bb6df3..df7d4f8e7 100644
--- a/vendor/compiler_builtins/Cargo.toml
+++ b/vendor/compiler_builtins/Cargo.toml
@@ -11,7 +11,7 @@
[package]
name = "compiler_builtins"
-version = "0.1.85"
+version = "0.1.87"
authors = ["Jorge Aparicio <japaricious@gmail.com>"]
links = "compiler-rt"
include = [
diff --git a/vendor/compiler_builtins/src/float/conv.rs b/vendor/compiler_builtins/src/float/conv.rs
index 19fdc2fdc..a27d542fa 100644
--- a/vendor/compiler_builtins/src/float/conv.rs
+++ b/vendor/compiler_builtins/src/float/conv.rs
@@ -92,12 +92,12 @@ intrinsics! {
f64::from_bits(int_to_float::u64_to_f64_bits(i))
}
- #[cfg_attr(any(not(target_feature = "llvm14-builtins-abi"), target_os = "uefi"), unadjusted_on_win64)]
+ #[cfg_attr(target_os = "uefi", unadjusted_on_win64)]
pub extern "C" fn __floatuntisf(i: u128) -> f32 {
f32::from_bits(int_to_float::u128_to_f32_bits(i))
}
- #[cfg_attr(any(not(target_feature = "llvm14-builtins-abi"), target_os = "uefi"), unadjusted_on_win64)]
+ #[cfg_attr(target_os = "uefi", unadjusted_on_win64)]
pub extern "C" fn __floatuntidf(i: u128) -> f64 {
f64::from_bits(int_to_float::u128_to_f64_bits(i))
}
@@ -129,13 +129,13 @@ intrinsics! {
f64::from_bits(int_to_float::u64_to_f64_bits(i.unsigned_abs()) | sign_bit)
}
- #[cfg_attr(any(not(target_feature = "llvm14-builtins-abi"), target_os = "uefi"), unadjusted_on_win64)]
+ #[cfg_attr(target_os = "uefi", unadjusted_on_win64)]
pub extern "C" fn __floattisf(i: i128) -> f32 {
let sign_bit = ((i >> 127) as u32) << 31;
f32::from_bits(int_to_float::u128_to_f32_bits(i.unsigned_abs()) | sign_bit)
}
- #[cfg_attr(any(not(target_feature = "llvm14-builtins-abi"), target_os = "uefi"), unadjusted_on_win64)]
+ #[cfg_attr(target_os = "uefi", unadjusted_on_win64)]
pub extern "C" fn __floattidf(i: i128) -> f64 {
let sign_bit = ((i >> 127) as u64) << 63;
f64::from_bits(int_to_float::u128_to_f64_bits(i.unsigned_abs()) | sign_bit)
@@ -176,8 +176,7 @@ intrinsics! {
}
}
- #[cfg_attr(target_feature = "llvm14-builtins-abi", win64_128bit_abi_hack)]
- #[cfg_attr(not(target_feature = "llvm14-builtins-abi"), unadjusted_on_win64)]
+ #[win64_128bit_abi_hack]
pub extern "C" fn __fixunssfti(f: f32) -> u128 {
let fbits = f.to_bits();
if fbits < 127 << 23 { // >= 0, < 1
@@ -225,8 +224,7 @@ intrinsics! {
}
}
- #[cfg_attr(target_feature = "llvm14-builtins-abi", win64_128bit_abi_hack)]
- #[cfg_attr(not(target_feature = "llvm14-builtins-abi"), unadjusted_on_win64)]
+ #[win64_128bit_abi_hack]
pub extern "C" fn __fixunsdfti(f: f64) -> u128 {
let fbits = f.to_bits();
if fbits < 1023 << 52 { // >= 0, < 1
@@ -279,8 +277,7 @@ intrinsics! {
}
}
- #[cfg_attr(target_feature = "llvm14-builtins-abi", win64_128bit_abi_hack)]
- #[cfg_attr(not(target_feature = "llvm14-builtins-abi"), unadjusted_on_win64)]
+ #[win64_128bit_abi_hack]
pub extern "C" fn __fixsfti(f: f32) -> i128 {
let fbits = f.to_bits() & !0 >> 1; // Remove sign bit.
if fbits < 127 << 23 { // >= 0, < 1
@@ -331,8 +328,7 @@ intrinsics! {
}
}
- #[cfg_attr(target_feature = "llvm14-builtins-abi", win64_128bit_abi_hack)]
- #[cfg_attr(not(target_feature = "llvm14-builtins-abi"), unadjusted_on_win64)]
+ #[win64_128bit_abi_hack]
pub extern "C" fn __fixdfti(f: f64) -> i128 {
let fbits = f.to_bits() & !0 >> 1; // Remove sign bit.
if fbits < 1023 << 52 { // >= 0, < 1
diff --git a/vendor/compiler_builtins/src/int/shift.rs b/vendor/compiler_builtins/src/int/shift.rs
index 908e619e1..2d2c081a6 100644
--- a/vendor/compiler_builtins/src/int/shift.rs
+++ b/vendor/compiler_builtins/src/int/shift.rs
@@ -69,47 +69,56 @@ impl Lshr for u64 {}
impl Lshr for u128 {}
intrinsics! {
+ #[avr_skip]
#[maybe_use_optimized_c_shim]
pub extern "C" fn __ashlsi3(a: u32, b: u32) -> u32 {
a.ashl(b)
}
+ #[avr_skip]
#[maybe_use_optimized_c_shim]
#[arm_aeabi_alias = __aeabi_llsl]
pub extern "C" fn __ashldi3(a: u64, b: u32) -> u64 {
a.ashl(b)
}
+ #[avr_skip]
pub extern "C" fn __ashlti3(a: u128, b: u32) -> u128 {
a.ashl(b)
}
+ #[avr_skip]
#[maybe_use_optimized_c_shim]
pub extern "C" fn __ashrsi3(a: i32, b: u32) -> i32 {
a.ashr(b)
}
+ #[avr_skip]
#[maybe_use_optimized_c_shim]
#[arm_aeabi_alias = __aeabi_lasr]
pub extern "C" fn __ashrdi3(a: i64, b: u32) -> i64 {
a.ashr(b)
}
+ #[avr_skip]
pub extern "C" fn __ashrti3(a: i128, b: u32) -> i128 {
a.ashr(b)
}
+ #[avr_skip]
#[maybe_use_optimized_c_shim]
pub extern "C" fn __lshrsi3(a: u32, b: u32) -> u32 {
a.lshr(b)
}
+ #[avr_skip]
#[maybe_use_optimized_c_shim]
#[arm_aeabi_alias = __aeabi_llsr]
pub extern "C" fn __lshrdi3(a: u64, b: u32) -> u64 {
a.lshr(b)
}
+ #[avr_skip]
pub extern "C" fn __lshrti3(a: u128, b: u32) -> u128 {
a.lshr(b)
}
diff --git a/vendor/dissimilar/.cargo-checksum.json b/vendor/dissimilar/.cargo-checksum.json
index 889c53a44..cfb8c46ea 100644
--- a/vendor/dissimilar/.cargo-checksum.json
+++ b/vendor/dissimilar/.cargo-checksum.json
@@ -1 +1 @@
-{"files":{"Cargo.toml":"abe95bc027ce5fe4aae082e8560c12d43f015ea85453be0ca6df6ded8f29e4da","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"23f18e03dc49df91622fe2a76176497404e46ced8a715d9d2b67a7446571cca3","README.md":"a9480cd29fe4eefae782c5ec20a05f88ca28d3ca1573a893fa423b931e3ca392","benches/bench.rs":"e62b50ebe922590a7251197b50047a3924be98c6193e1f0fbca552d66fd05f9d","benches/document1.txt":"92a6f5c3992d98632eea7a6c6261cf1a26ae484b34358778b774a2d58fd356d3","benches/document2.txt":"8d106ddba8bd4a85a8bb4b59e481b88f536de98046dc8e4f76f7551c265c5dd3","src/find.rs":"32f68fa18bd547f5c716895bc580c12d6fe8503f86044fc0334f1b1e3cd3ac97","src/lib.rs":"7c1bf347cb87d22dde987da421931644dea3ed84e5e48b8dad44cb5579cb9f04","src/range.rs":"8652a374da1f7959ed912891e610a1e72026ba5315362cfb529bd2724ce69fc6","src/tests.rs":"e2a68e2b724ec65a062b634b86114e3a2e445c4693e312c08d9648f6621ea9d2","tests/test.rs":"4dcc2007359d6bf6a48590fcdab9cc81787a18aac8dc9c1c4be1019d95ca690e"},"package":"8c97b9233581d84b8e1e689cdd3a47b6f69770084fc246e86a7f78b0d9c1d4a5"} \ No newline at end of file
+{"files":{"Cargo.toml":"b5579f3eb0d811d6ad116c247138911fee4404c80f49bb6020df06394d0467ec","LICENSE-APACHE":"62c7a1e35f56406896d7aa7ca52d0cc0d272ac022b5d2796e7d6905db8a3636a","LICENSE-MIT":"23f18e03dc49df91622fe2a76176497404e46ced8a715d9d2b67a7446571cca3","README.md":"e081b60ac4ad261ee3c57f32131634017044193b94ce2ebd64d134d22185e79a","benches/bench.rs":"e62b50ebe922590a7251197b50047a3924be98c6193e1f0fbca552d66fd05f9d","benches/document1.txt":"92a6f5c3992d98632eea7a6c6261cf1a26ae484b34358778b774a2d58fd356d3","benches/document2.txt":"8d106ddba8bd4a85a8bb4b59e481b88f536de98046dc8e4f76f7551c265c5dd3","src/find.rs":"4587b9fc3fc32149898c6daf50624c41ab9de9ec4de5baa3a4d3644436dccf5f","src/lib.rs":"9749cf7915c3f5682144f3eb0ec3d1b5d9c3457b740a7ced8e91211be6a8549c","src/range.rs":"9b4f5f0125d927f985cf5c3a92452e4c28273842d9ff7debc2d3584db5d7d0f6","src/tests.rs":"222464295b0558fe505f9d2d53f315dd164cc85e323e32e523f738eec771cdbe","tests/test.rs":"2a4ccfea35304fa2fc2b2b38efe9da6a1b5fd5f6c1247ba01e85232d19b70206"},"package":"210ec60ae7d710bed8683e333e9d2855a8a56a3e9892b38bad3bb0d4d29b0d5e"} \ No newline at end of file
diff --git a/vendor/dissimilar/Cargo.toml b/vendor/dissimilar/Cargo.toml
index d657b1742..3fdb995a5 100644
--- a/vendor/dissimilar/Cargo.toml
+++ b/vendor/dissimilar/Cargo.toml
@@ -11,9 +11,9 @@
[package]
edition = "2018"
-rust-version = "1.31"
+rust-version = "1.36"
name = "dissimilar"
-version = "1.0.4"
+version = "1.0.6"
authors = ["David Tolnay <dtolnay@gmail.com>"]
description = "Diff library with semantic cleanup, based on Google's diff-match-patch"
documentation = "https://docs.rs/dissimilar"
@@ -28,3 +28,9 @@ repository = "https://github.com/dtolnay/dissimilar"
[package.metadata.docs.rs]
targets = ["x86_64-unknown-linux-gnu"]
+
+[lib]
+doc-scrape-examples = false
+
+[dev-dependencies.once_cell]
+version = "1"
diff --git a/vendor/dissimilar/LICENSE-APACHE b/vendor/dissimilar/LICENSE-APACHE
index 16fe87b06..1b5ec8b78 100644
--- a/vendor/dissimilar/LICENSE-APACHE
+++ b/vendor/dissimilar/LICENSE-APACHE
@@ -174,28 +174,3 @@ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
-
-APPENDIX: How to apply the Apache License to your work.
-
- To apply the Apache License to your work, attach the following
- boilerplate notice, with the fields enclosed by brackets "[]"
- replaced with your own identifying information. (Don't include
- the brackets!) The text should be enclosed in the appropriate
- comment syntax for the file format. We also recommend that a
- file or class name and description of purpose be included on the
- same "printed page" as the copyright notice for easier
- identification within third-party archives.
-
-Copyright [yyyy] [name of copyright owner]
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
diff --git a/vendor/dissimilar/README.md b/vendor/dissimilar/README.md
index 492bced22..82ce66995 100644
--- a/vendor/dissimilar/README.md
+++ b/vendor/dissimilar/README.md
@@ -3,8 +3,8 @@ Dissimilar: diff library with semantic cleanup
[<img alt="github" src="https://img.shields.io/badge/github-dtolnay/dissimilar-8da0cb?style=for-the-badge&labelColor=555555&logo=github" height="20">](https://github.com/dtolnay/dissimilar)
[<img alt="crates.io" src="https://img.shields.io/crates/v/dissimilar.svg?style=for-the-badge&color=fc8d62&logo=rust" height="20">](https://crates.io/crates/dissimilar)
-[<img alt="docs.rs" src="https://img.shields.io/badge/docs.rs-dissimilar-66c2a5?style=for-the-badge&labelColor=555555&logoColor=white&logo=data:image/svg+xml;base64,PHN2ZyByb2xlPSJpbWciIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgdmlld0JveD0iMCAwIDUxMiA1MTIiPjxwYXRoIGZpbGw9IiNmNWY1ZjUiIGQ9Ik00ODguNiAyNTAuMkwzOTIgMjE0VjEwNS41YzAtMTUtOS4zLTI4LjQtMjMuNC0zMy43bC0xMDAtMzcuNWMtOC4xLTMuMS0xNy4xLTMuMS0yNS4zIDBsLTEwMCAzNy41Yy0xNC4xIDUuMy0yMy40IDE4LjctMjMuNCAzMy43VjIxNGwtOTYuNiAzNi4yQzkuMyAyNTUuNSAwIDI2OC45IDAgMjgzLjlWMzk0YzAgMTMuNiA3LjcgMjYuMSAxOS45IDMyLjJsMTAwIDUwYzEwLjEgNS4xIDIyLjEgNS4xIDMyLjIgMGwxMDMuOS01MiAxMDMuOSA1MmMxMC4xIDUuMSAyMi4xIDUuMSAzMi4yIDBsMTAwLTUwYzEyLjItNi4xIDE5LjktMTguNiAxOS45LTMyLjJWMjgzLjljMC0xNS05LjMtMjguNC0yMy40LTMzLjd6TTM1OCAyMTQuOGwtODUgMzEuOXYtNjguMmw4NS0zN3Y3My4zek0xNTQgMTA0LjFsMTAyLTM4LjIgMTAyIDM4LjJ2LjZsLTEwMiA0MS40LTEwMi00MS40di0uNnptODQgMjkxLjFsLTg1IDQyLjV2LTc5LjFsODUtMzguOHY3NS40em0wLTExMmwtMTAyIDQxLjQtMTAyLTQxLjR2LS42bDEwMi0zOC4yIDEwMiAzOC4ydi42em0yNDAgMTEybC04NSA0Mi41di03OS4xbDg1LTM4Ljh2NzUuNHptMC0xMTJsLTEwMiA0MS40LTEwMi00MS40di0uNmwxMDItMzguMiAxMDIgMzguMnYuNnoiPjwvcGF0aD48L3N2Zz4K" height="20">](https://docs.rs/dissimilar)
-[<img alt="build status" src="https://img.shields.io/github/workflow/status/dtolnay/dissimilar/CI/master?style=for-the-badge" height="20">](https://github.com/dtolnay/dissimilar/actions?query=branch%3Amaster)
+[<img alt="docs.rs" src="https://img.shields.io/badge/docs.rs-dissimilar-66c2a5?style=for-the-badge&labelColor=555555&logo=docs.rs" height="20">](https://docs.rs/dissimilar)
+[<img alt="build status" src="https://img.shields.io/github/actions/workflow/status/dtolnay/dissimilar/ci.yml?branch=master&style=for-the-badge" height="20">](https://github.com/dtolnay/dissimilar/actions?query=branch%3Amaster)
This library is a port of the Diff component of [Diff Match Patch] to Rust. The
diff implementation is based on [Myers' diff algorithm] but includes some
@@ -22,7 +22,7 @@ Diff Match Patch was originally built in 2006 to power Google Docs.
dissimilar = "1.0"
```
-*Compiler support: requires rustc 1.31+*
+*Compiler support: requires rustc 1.36+*
<br>
diff --git a/vendor/dissimilar/src/find.rs b/vendor/dissimilar/src/find.rs
index 90ca2c6c5..4af3b8bee 100644
--- a/vendor/dissimilar/src/find.rs
+++ b/vendor/dissimilar/src/find.rs
@@ -1,5 +1,5 @@
// The strstr implementation in this file is extracted from the Rust standard
-// library's str::find. The algorithm works for arbitrary &[u8] haystack and
+// library's str::find. The algorithm works for arbitrary &[T] haystack and
// needle but is only exposed by the standard library on UTF-8 strings.
//
// https://github.com/rust-lang/rust/blob/1.40.0/src/libcore/str/pattern.rs
@@ -80,7 +80,7 @@
use std::cmp;
use std::usize;
-pub fn find(haystack: &[u8], needle: &[u8]) -> Option<usize> {
+pub fn find(haystack: &[char], needle: &[char]) -> Option<usize> {
assert!(!needle.is_empty());
// crit_pos: critical factorization index
@@ -177,12 +177,12 @@ pub fn find(haystack: &[u8], needle: &[u8]) -> Option<usize> {
}
}
-fn byteset_create(bytes: &[u8]) -> u64 {
- bytes.iter().fold(0, |a, &b| (1 << (b & 0x3f)) | a)
+fn byteset_create(chars: &[char]) -> u64 {
+ chars.iter().fold(0, |a, &ch| (1 << (ch as u8 & 0x3f)) | a)
}
-fn byteset_contains(byteset: u64, byte: u8) -> bool {
- (byteset >> ((byte & 0x3f) as usize)) & 1 != 0
+fn byteset_contains(byteset: u64, ch: char) -> bool {
+ (byteset >> ((ch as u8 & 0x3f) as usize)) & 1 != 0
}
// Compute the maximal suffix of `arr`.
@@ -197,7 +197,7 @@ fn byteset_contains(byteset: u64, byte: u8) -> bool {
// a critical factorization.
//
// For long period cases, the resulting period is not exact (it is too short).
-fn maximal_suffix(arr: &[u8], order_greater: bool) -> (usize, usize) {
+fn maximal_suffix(arr: &[char], order_greater: bool) -> (usize, usize) {
let mut left = 0; // Corresponds to i in the paper
let mut right = 1; // Corresponds to j in the paper
let mut offset = 0; // Corresponds to k in the paper, but starting at 0
diff --git a/vendor/dissimilar/src/lib.rs b/vendor/dissimilar/src/lib.rs
index 8ce9faad3..b66434ade 100644
--- a/vendor/dissimilar/src/lib.rs
+++ b/vendor/dissimilar/src/lib.rs
@@ -2,7 +2,7 @@
//!
//! [github]: https://img.shields.io/badge/github-8da0cb?style=for-the-badge&labelColor=555555&logo=github
//! [crates-io]: https://img.shields.io/badge/crates.io-fc8d62?style=for-the-badge&labelColor=555555&logo=rust
-//! [docs-rs]: https://img.shields.io/badge/docs.rs-66c2a5?style=for-the-badge&labelColor=555555&logoColor=white&logo=data:image/svg+xml;base64,PHN2ZyByb2xlPSJpbWciIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgdmlld0JveD0iMCAwIDUxMiA1MTIiPjxwYXRoIGZpbGw9IiNmNWY1ZjUiIGQ9Ik00ODguNiAyNTAuMkwzOTIgMjE0VjEwNS41YzAtMTUtOS4zLTI4LjQtMjMuNC0zMy43bC0xMDAtMzcuNWMtOC4xLTMuMS0xNy4xLTMuMS0yNS4zIDBsLTEwMCAzNy41Yy0xNC4xIDUuMy0yMy40IDE4LjctMjMuNCAzMy43VjIxNGwtOTYuNiAzNi4yQzkuMyAyNTUuNSAwIDI2OC45IDAgMjgzLjlWMzk0YzAgMTMuNiA3LjcgMjYuMSAxOS45IDMyLjJsMTAwIDUwYzEwLjEgNS4xIDIyLjEgNS4xIDMyLjIgMGwxMDMuOS01MiAxMDMuOSA1MmMxMC4xIDUuMSAyMi4xIDUuMSAzMi4yIDBsMTAwLTUwYzEyLjItNi4xIDE5LjktMTguNiAxOS45LTMyLjJWMjgzLjljMC0xNS05LjMtMjguNC0yMy40LTMzLjd6TTM1OCAyMTQuOGwtODUgMzEuOXYtNjguMmw4NS0zN3Y3My4zek0xNTQgMTA0LjFsMTAyLTM4LjIgMTAyIDM4LjJ2LjZsLTEwMiA0MS40LTEwMi00MS40di0uNnptODQgMjkxLjFsLTg1IDQyLjV2LTc5LjFsODUtMzguOHY3NS40em0wLTExMmwtMTAyIDQxLjQtMTAyLTQxLjR2LS42bDEwMi0zOC4yIDEwMiAzOC4ydi42em0yNDAgMTEybC04NSA0Mi41di03OS4xbDg1LTM4Ljh2NzUuNHptMC0xMTJsLTEwMiA0MS40LTEwMi00MS40di0uNmwxMDItMzguMiAxMDIgMzguMnYuNnoiPjwvcGF0aD48L3N2Zz4K
+//! [docs-rs]: https://img.shields.io/badge/docs.rs-66c2a5?style=for-the-badge&labelColor=555555&logo=docs.rs
//!
//! <br>
//!
@@ -37,9 +37,10 @@
//! [Myers' diff algorithm]: https://neil.fraser.name/writing/diff/myers.pdf
//! [semantic cleanups]: https://neil.fraser.name/writing/diff/
-#![doc(html_root_url = "https://docs.rs/dissimilar/1.0.4")]
+#![doc(html_root_url = "https://docs.rs/dissimilar/1.0.6")]
#![allow(
clippy::blocks_in_if_conditions,
+ clippy::bool_to_int_with_if,
clippy::cast_possible_wrap,
clippy::cast_sign_loss,
clippy::cloned_instead_of_copied, // https://github.com/rust-lang/rust-clippy/issues/7127
@@ -63,10 +64,10 @@ mod range;
#[cfg(test)]
mod tests;
-use crate::range::{bytes, str, Range};
+use crate::range::{slice, Range};
use std::cmp;
use std::collections::VecDeque;
-use std::fmt::{self, Debug};
+use std::fmt::{self, Debug, Display, Write};
#[derive(Copy, Clone, PartialEq, Eq)]
pub enum Chunk<'a> {
@@ -121,20 +122,49 @@ impl<'tmp, 'a: 'tmp, 'b: 'tmp> Diff<'a, 'b> {
}
pub fn diff<'a>(text1: &'a str, text2: &'a str) -> Vec<Chunk<'a>> {
- let text1 = Range::new(text1, ..);
- let text2 = Range::new(text2, ..);
- let mut solution = main(text1, text2);
+ let chars1: Vec<char> = text1.chars().collect();
+ let chars2: Vec<char> = text2.chars().collect();
+ let range1 = Range::new(&chars1, ..);
+ let range2 = Range::new(&chars2, ..);
+
+ let mut solution = main(range1, range2);
cleanup_char_boundary(&mut solution);
cleanup_semantic(&mut solution);
cleanup_merge(&mut solution);
- solution.diffs.into_iter().map(Chunk::from).collect()
+
+ let mut chunks = Vec::new();
+ let mut pos1 = 0;
+ let mut pos2 = 0;
+ for diff in solution.diffs {
+ chunks.push(match diff {
+ Diff::Equal(range, _) => {
+ let len = range.len_bytes();
+ let chunk = Chunk::Equal(&text1[pos1..pos1 + len]);
+ pos1 += len;
+ pos2 += len;
+ chunk
+ }
+ Diff::Delete(range) => {
+ let len = range.len_bytes();
+ let chunk = Chunk::Delete(&text1[pos1..pos1 + len]);
+ pos1 += len;
+ chunk
+ }
+ Diff::Insert(range) => {
+ let len = range.len_bytes();
+ let chunk = Chunk::Insert(&text2[pos2..pos2 + len]);
+ pos2 += len;
+ chunk
+ }
+ });
+ }
+ chunks
}
struct Solution<'a, 'b> {
text1: Range<'a>,
text2: Range<'b>,
diffs: Vec<Diff<'a, 'b>>,
- utf8: bool,
}
fn main<'a, 'b>(mut text1: Range<'a>, mut text2: Range<'b>) -> Solution<'a, 'b> {
@@ -142,7 +172,7 @@ fn main<'a, 'b>(mut text1: Range<'a>, mut text2: Range<'b>) -> Solution<'a, 'b>
let whole2 = text2;
// Trim off common prefix.
- let common_prefix_len = common_prefix_bytes(text1, text2);
+ let common_prefix_len = common_prefix(text1, text2);
let common_prefix = Diff::Equal(
text1.substring(..common_prefix_len),
text2.substring(..common_prefix_len),
@@ -151,7 +181,7 @@ fn main<'a, 'b>(mut text1: Range<'a>, mut text2: Range<'b>) -> Solution<'a, 'b>
text2 = text2.substring(common_prefix_len..);
// Trim off common suffix.
- let common_suffix_len = common_suffix_bytes(text1, text2);
+ let common_suffix_len = common_suffix(text1, text2);
let common_suffix = Diff::Equal(
text1.substring(text1.len - common_suffix_len..),
text2.substring(text2.len - common_suffix_len..),
@@ -164,7 +194,6 @@ fn main<'a, 'b>(mut text1: Range<'a>, mut text2: Range<'b>) -> Solution<'a, 'b>
text1: whole1,
text2: whole2,
diffs: compute(text1, text2),
- utf8: false,
};
// Restore the prefix and suffix.
@@ -252,7 +281,7 @@ fn bisect<'a, 'b>(text1: Range<'a>, text2: Range<'b>) -> Vec<Diff<'a, 'b>> {
} as usize;
let mut y1 = (x1 as isize - k1) as usize;
if let (Some(s1), Some(s2)) = (text1.get(x1..), text2.get(y1..)) {
- let advance = common_prefix_bytes(s1, s2);
+ let advance = common_prefix(s1, s2);
x1 += advance;
y1 += advance;
}
@@ -288,7 +317,7 @@ fn bisect<'a, 'b>(text1: Range<'a>, text2: Range<'b>) -> Vec<Diff<'a, 'b>> {
} as usize;
let mut y2 = (x2 as isize - k2) as usize;
if x2 < text1.len && y2 < text2.len {
- let advance = common_suffix_bytes(
+ let advance = common_suffix(
text1.substring(..text1.len - x2),
text2.substring(..text2.len - y2),
);
@@ -342,8 +371,8 @@ fn bisect_split<'a, 'b>(
// Determine the length of the common prefix of two strings.
fn common_prefix(text1: Range, text2: Range) -> usize {
- for ((i, ch1), ch2) in text1.char_indices().zip(text2.chars()) {
- if ch1 != ch2 {
+ for (i, (b1, b2)) in text1.chars().zip(text2.chars()).enumerate() {
+ if b1 != b2 {
return i;
}
}
@@ -352,25 +381,7 @@ fn common_prefix(text1: Range, text2: Range) -> usize {
// Determine the length of the common suffix of two strings.
fn common_suffix(text1: Range, text2: Range) -> usize {
- for ((i, ch1), ch2) in text1.char_indices().rev().zip(text2.chars().rev()) {
- if ch1 != ch2 {
- return text1.len - i - ch1.len_utf8();
- }
- }
- cmp::min(text1.len, text2.len)
-}
-
-fn common_prefix_bytes(text1: Range, text2: Range) -> usize {
- for (i, (b1, b2)) in text1.bytes().zip(text2.bytes()).enumerate() {
- if b1 != b2 {
- return i;
- }
- }
- cmp::min(text1.len, text2.len)
-}
-
-fn common_suffix_bytes(text1: Range, text2: Range) -> usize {
- for (i, (b1, b2)) in text1.bytes().rev().zip(text2.bytes().rev()).enumerate() {
+ for (i, (b1, b2)) in text1.chars().rev().zip(text2.chars().rev()).enumerate() {
if b1 != b2 {
return i;
}
@@ -394,7 +405,7 @@ fn common_overlap(mut text1: Range, mut text2: Range) -> usize {
text2 = text2.substring(..text1.len);
}
// Quick check for the worst case.
- if bytes(text1) == bytes(text2) {
+ if slice(text1) == slice(text2) {
return text1.len;
}
@@ -411,7 +422,7 @@ fn common_overlap(mut text1: Range, mut text2: Range) -> usize {
};
length += found;
if found == 0
- || bytes(text1.substring(text1.len - length..)) == bytes(text2.substring(..length))
+ || slice(text1.substring(text1.len - length..)) == slice(text2.substring(..length))
{
best = length;
length += 1;
@@ -420,17 +431,24 @@ fn common_overlap(mut text1: Range, mut text2: Range) -> usize {
}
fn cleanup_char_boundary(solution: &mut Solution) {
- fn boundary_down(doc: &str, pos: usize) -> usize {
+ fn is_segmentation_boundary(doc: &[char], pos: usize) -> bool {
+ // FIXME: use unicode-segmentation crate?
+ let _ = doc;
+ let _ = pos;
+ true
+ }
+
+ fn boundary_down(doc: &[char], pos: usize) -> usize {
let mut adjust = 0;
- while !doc.is_char_boundary(pos - adjust) {
+ while !is_segmentation_boundary(doc, pos - adjust) {
adjust += 1;
}
adjust
}
- fn boundary_up(doc: &str, pos: usize) -> usize {
+ fn boundary_up(doc: &[char], pos: usize) -> usize {
let mut adjust = 0;
- while !doc.is_char_boundary(pos + adjust) {
+ while !is_segmentation_boundary(doc, pos + adjust) {
adjust += 1;
}
adjust
@@ -498,7 +516,6 @@ fn cleanup_char_boundary(solution: &mut Solution) {
}
solution.diffs.truncate(retain);
- solution.utf8 = true;
}
// Reduce the number of edits by eliminating semantically trivial equalities.
@@ -658,14 +675,13 @@ fn cleanup_semantic_lossless(solution: &mut Solution) {
&& !next_equal1.is_empty()
&& edit.text().chars().next().unwrap() == next_equal1.chars().next().unwrap()
{
- let increment = edit.text().chars().next().unwrap().len_utf8();
- prev_equal1.len += increment;
- prev_equal2.len += increment;
- edit.shift_right(increment);
- next_equal1.offset += increment;
- next_equal1.len -= increment;
- next_equal2.offset += increment;
- next_equal2.len -= increment;
+ prev_equal1.len += 1;
+ prev_equal2.len += 1;
+ edit.shift_right(1);
+ next_equal1.offset += 1;
+ next_equal1.len -= 1;
+ next_equal2.offset += 1;
+ next_equal2.len -= 1;
let score = cleanup_semantic_score(prev_equal1, edit.text())
+ cleanup_semantic_score(edit.text(), next_equal1);
// The >= encourages trailing rather than leading whitespace on edits.
@@ -720,8 +736,10 @@ fn cleanup_semantic_score(one: Range, two: Range) -> usize {
let whitespace2 = non_alphanumeric2 && char2.is_ascii_whitespace();
let line_break1 = whitespace1 && char1.is_control();
let line_break2 = whitespace2 && char2.is_control();
- let blank_line1 = line_break1 && (one.ends_with("\n\n") || one.ends_with("\n\r\n"));
- let blank_line2 = line_break2 && (two.starts_with("\n\n") || two.starts_with("\r\n\r\n"));
+ let blank_line1 =
+ line_break1 && (one.ends_with(['\n', '\n']) || one.ends_with(['\n', '\r', '\n']));
+ let blank_line2 =
+ line_break2 && (two.starts_with(['\n', '\n']) || two.starts_with(['\r', '\n', '\r', '\n']));
if blank_line1 || blank_line2 {
// Five points for blank lines.
@@ -747,22 +765,7 @@ fn cleanup_semantic_score(one: Range, two: Range) -> usize {
// move as long as it doesn't cross an equality.
fn cleanup_merge(solution: &mut Solution) {
let diffs = &mut solution.diffs;
- let common_prefix = if solution.utf8 {
- common_prefix
- } else {
- common_prefix_bytes
- };
- let common_suffix = if solution.utf8 {
- common_suffix
- } else {
- common_suffix_bytes
- };
-
- loop {
- if diffs.is_empty() {
- return;
- }
-
+ while !diffs.is_empty() {
diffs.push(Diff::Equal(
solution.text1.substring(solution.text1.len..),
solution.text2.substring(solution.text2.len..),
@@ -911,22 +914,22 @@ impl Debug for Chunk<'_> {
impl Debug for Diff<'_, '_> {
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
- let (name, bytes) = match *self {
- Diff::Equal(range, _) => ("Equal", bytes(range)),
- Diff::Delete(range) => ("Delete", bytes(range)),
- Diff::Insert(range) => ("Insert", bytes(range)),
+ let (name, range) = match *self {
+ Diff::Equal(range, _) => ("Equal", range),
+ Diff::Delete(range) => ("Delete", range),
+ Diff::Insert(range) => ("Insert", range),
};
- let text = String::from_utf8_lossy(bytes);
- write!(formatter, "{}({:?})", name, text)
- }
-}
-
-impl<'a> From<Diff<'a, 'a>> for Chunk<'a> {
- fn from(diff: Diff<'a, 'a>) -> Self {
- match diff {
- Diff::Equal(range, _) => Chunk::Equal(str(range)),
- Diff::Delete(range) => Chunk::Delete(str(range)),
- Diff::Insert(range) => Chunk::Insert(str(range)),
+ formatter.write_str(name)?;
+ formatter.write_str("(\"")?;
+ for ch in range.chars() {
+ if ch == '\'' {
+ // escape_debug turns this into "\'" which is unnecessary.
+ formatter.write_char(ch)?;
+ } else {
+ Display::fmt(&ch.escape_debug(), formatter)?;
+ }
}
+ formatter.write_str("\")")?;
+ Ok(())
}
}
diff --git a/vendor/dissimilar/src/range.rs b/vendor/dissimilar/src/range.rs
index 565a94c06..55cbc448c 100644
--- a/vendor/dissimilar/src/range.rs
+++ b/vendor/dissimilar/src/range.rs
@@ -1,11 +1,10 @@
use crate::find::find;
use std::fmt::Debug;
use std::ops::{self, RangeFrom, RangeFull, RangeTo};
-use std::str::{CharIndices, Chars};
#[derive(Copy, Clone)]
pub struct Range<'a> {
- pub doc: &'a str,
+ pub doc: &'a [char],
pub offset: usize,
pub len: usize,
}
@@ -13,13 +12,13 @@ pub struct Range<'a> {
impl<'a> Range<'a> {
pub fn empty() -> Self {
Range {
- doc: "",
+ doc: &[],
offset: 0,
len: 0,
}
}
- pub fn new(doc: &'a str, bounds: impl RangeBounds) -> Self {
+ pub fn new(doc: &'a [char], bounds: impl RangeBounds) -> Self {
let (offset, len) = bounds.index(doc.len());
Range { doc, offset, len }
}
@@ -28,6 +27,10 @@ impl<'a> Range<'a> {
self.len == 0
}
+ pub fn len_bytes(&self) -> usize {
+ self.chars().map(char::len_utf8).sum()
+ }
+
pub fn substring(&self, bounds: impl RangeBounds) -> Self {
let (offset, len) = bounds.index(self.len);
Range {
@@ -50,32 +53,26 @@ impl<'a> Range<'a> {
(self.substring(..mid), self.substring(mid..))
}
- pub fn chars(&self) -> Chars<'a> {
- str(*self).chars()
- }
-
- pub fn char_indices(&self) -> CharIndices<'a> {
- str(*self).char_indices()
+ pub fn chars(
+ &self,
+ ) -> impl Iterator<Item = char> + DoubleEndedIterator + ExactSizeIterator + 'a {
+ slice(*self).iter().copied()
}
- pub fn bytes(&self) -> impl Iterator<Item = u8> + DoubleEndedIterator + ExactSizeIterator + 'a {
- bytes(*self).iter().cloned()
+ pub fn starts_with(&self, prefix: impl AsRef<[char]>) -> bool {
+ slice(*self).starts_with(prefix.as_ref())
}
- pub fn starts_with(&self, prefix: impl AsRef<[u8]>) -> bool {
- bytes(*self).starts_with(prefix.as_ref())
+ pub fn ends_with(&self, suffix: impl AsRef<[char]>) -> bool {
+ slice(*self).ends_with(suffix.as_ref())
}
- pub fn ends_with(&self, suffix: impl AsRef<[u8]>) -> bool {
- bytes(*self).ends_with(suffix.as_ref())
- }
-
- pub fn find(&self, needle: impl AsRef<[u8]>) -> Option<usize> {
- find(bytes(*self), needle.as_ref())
+ pub fn find(&self, needle: impl AsRef<[char]>) -> Option<usize> {
+ find(slice(*self), needle.as_ref())
}
}
-pub fn str(range: Range) -> &str {
+pub fn slice(range: Range) -> &[char] {
if cfg!(debug)
&& range
.doc
@@ -90,13 +87,9 @@ pub fn str(range: Range) -> &str {
&range.doc[range.offset..range.offset + range.len]
}
-pub fn bytes(range: Range) -> &[u8] {
- &range.doc.as_bytes()[range.offset..range.offset + range.len]
-}
-
-impl AsRef<[u8]> for Range<'_> {
- fn as_ref(&self) -> &[u8] {
- bytes(*self)
+impl AsRef<[char]> for Range<'_> {
+ fn as_ref(&self) -> &[char] {
+ slice(*self)
}
}
diff --git a/vendor/dissimilar/src/tests.rs b/vendor/dissimilar/src/tests.rs
index 450d7f7e4..d2e3fd643 100644
--- a/vendor/dissimilar/src/tests.rs
+++ b/vendor/dissimilar/src/tests.rs
@@ -1,4 +1,13 @@
use super::*;
+use once_cell::sync::OnceCell;
+
+macro_rules! range {
+ ($text:expr) => {{
+ static CHARS: OnceCell<Vec<char>> = OnceCell::new();
+ let chars = CHARS.get_or_init(|| $text.chars().collect());
+ Range::new(chars, ..)
+ }};
+}
macro_rules! diff_list {
() => {
@@ -6,50 +15,52 @@ macro_rules! diff_list {
text1: Range::empty(),
text2: Range::empty(),
diffs: Vec::new(),
- utf8: true,
}
};
($($kind:ident($text:literal)),+ $(,)?) => {{
+ #[allow(unused_macro_rules)]
macro_rules! text1 {
(Insert, $s:literal) => { "" };
(Delete, $s:literal) => { $s };
(Equal, $s:literal) => { $s };
}
+ #[allow(unused_macro_rules)]
macro_rules! text2 {
(Insert, $s:literal) => { $s };
(Delete, $s:literal) => { "" };
(Equal, $s:literal) => { $s };
}
- let text1 = concat!($(text1!($kind, $text)),*);
- let text2 = concat!($(text2!($kind, $text)),*);
+ let text1 = range!(concat!($(text1!($kind, $text)),*));
+ let text2 = range!(concat!($(text2!($kind, $text)),*));
let (_i, _j) = (&mut 0, &mut 0);
+ #[allow(unused_macro_rules)]
macro_rules! range {
(Insert, $s:literal) => {
- Diff::Insert(range(text2, _j, $s))
+ Diff::Insert(range(text2.doc, _j, $s))
};
(Delete, $s:literal) => {
- Diff::Delete(range(text1, _i, $s))
+ Diff::Delete(range(text1.doc, _i, $s))
};
(Equal, $s:literal) => {
- Diff::Equal(range(text1, _i, $s), range(text2, _j, $s))
+ Diff::Equal(range(text1.doc, _i, $s), range(text2.doc, _j, $s))
};
}
Solution {
- text1: Range::new(text1, ..),
- text2: Range::new(text2, ..),
+ text1,
+ text2,
diffs: vec![$(range!($kind, $text)),*],
- utf8: true,
}
}};
}
-fn range<'a>(doc: &'a str, offset: &mut usize, text: &str) -> Range<'a> {
+fn range<'a>(doc: &'a [char], offset: &mut usize, text: &str) -> Range<'a> {
+ let len = text.chars().count();
let range = Range {
doc,
offset: *offset,
- len: text.len(),
+ len,
};
- *offset += text.len();
+ *offset += len;
range
}
@@ -65,12 +76,16 @@ macro_rules! assert_diffs {
}
fn same_diffs(expected: &[Chunk], actual: &[Diff]) -> bool {
+ fn eq(expected: &str, actual: &Range) -> bool {
+ expected.chars().eq(slice(*actual).iter().copied())
+ }
+
expected.len() == actual.len()
&& expected.iter().zip(actual).all(|pair| match pair {
- (Chunk::Insert(expected), Diff::Insert(actual)) => *expected == str(*actual),
- (Chunk::Delete(expected), Diff::Delete(actual)) => *expected == str(*actual),
+ (Chunk::Insert(expected), Diff::Insert(actual)) => eq(expected, actual),
+ (Chunk::Delete(expected), Diff::Delete(actual)) => eq(expected, actual),
(Chunk::Equal(expected), Diff::Equal(actual1, actual2)) => {
- *expected == str(*actual1) && *expected == str(*actual2)
+ eq(expected, actual1) && eq(expected, actual2)
}
(_, _) => false,
})
@@ -78,59 +93,56 @@ fn same_diffs(expected: &[Chunk], actual: &[Diff]) -> bool {
#[test]
fn test_common_prefix() {
- let text1 = Range::new("abc", ..);
- let text2 = Range::new("xyz", ..);
- assert_eq!(0, common_prefix_bytes(text1, text2), "Null case");
+ let text1 = range!("abc");
+ let text2 = range!("xyz");
+ assert_eq!(0, common_prefix(text1, text2), "Null case");
- let text1 = Range::new("1234abcdef", ..);
- let text2 = Range::new("1234xyz", ..);
- assert_eq!(4, common_prefix_bytes(text1, text2), "Non-null case");
+ let text1 = range!("1234abcdef");
+ let text2 = range!("1234xyz");
+ assert_eq!(4, common_prefix(text1, text2), "Non-null case");
- let text1 = Range::new("1234", ..);
- let text2 = Range::new("1234xyz", ..);
- assert_eq!(4, common_prefix_bytes(text1, text2), "Whole case");
+ let text1 = range!("1234");
+ let text2 = range!("1234xyz");
+ assert_eq!(4, common_prefix(text1, text2), "Whole case");
}
#[test]
fn test_common_suffix() {
- let text1 = Range::new("abc", ..);
- let text2 = Range::new("xyz", ..);
+ let text1 = range!("abc");
+ let text2 = range!("xyz");
assert_eq!(0, common_suffix(text1, text2), "Null case");
- assert_eq!(0, common_suffix_bytes(text1, text2), "Null case");
- let text1 = Range::new("abcdef1234", ..);
- let text2 = Range::new("xyz1234", ..);
+ let text1 = range!("abcdef1234");
+ let text2 = range!("xyz1234");
assert_eq!(4, common_suffix(text1, text2), "Non-null case");
- assert_eq!(4, common_suffix_bytes(text1, text2), "Non-null case");
- let text1 = Range::new("1234", ..);
- let text2 = Range::new("xyz1234", ..);
+ let text1 = range!("1234");
+ let text2 = range!("xyz1234");
assert_eq!(4, common_suffix(text1, text2), "Whole case");
- assert_eq!(4, common_suffix_bytes(text1, text2), "Whole case");
}
#[test]
fn test_common_overlap() {
let text1 = Range::empty();
- let text2 = Range::new("abcd", ..);
+ let text2 = range!("abcd");
assert_eq!(0, common_overlap(text1, text2), "Null case");
- let text1 = Range::new("abc", ..);
- let text2 = Range::new("abcd", ..);
+ let text1 = range!("abc");
+ let text2 = range!("abcd");
assert_eq!(3, common_overlap(text1, text2), "Whole case");
- let text1 = Range::new("123456", ..);
- let text2 = Range::new("abcd", ..);
+ let text1 = range!("123456");
+ let text2 = range!("abcd");
assert_eq!(0, common_overlap(text1, text2), "No overlap");
- let text1 = Range::new("123456xxx", ..);
- let text2 = Range::new("xxxabcd", ..);
+ let text1 = range!("123456xxx");
+ let text2 = range!("xxxabcd");
assert_eq!(3, common_overlap(text1, text2), "Overlap");
// Some overly clever languages (C#) may treat ligatures as equal to their
// component letters. E.g. U+FB01 == 'fi'
- let text1 = Range::new("fi", ..);
- let text2 = Range::new("\u{fb01}i", ..);
+ let text1 = range!("fi");
+ let text2 = range!("\u{fb01}i");
assert_eq!(0, common_overlap(text1, text2), "Unicode");
}
@@ -420,13 +432,12 @@ fn test_cleanup_semantic() {
#[test]
fn test_bisect() {
- let text1 = Range::new("cat", ..);
- let text2 = Range::new("map", ..);
+ let text1 = range!("cat");
+ let text2 = range!("map");
let solution = Solution {
text1,
text2,
diffs: bisect(text1, text2),
- utf8: false,
};
assert_diffs!(
[
@@ -446,24 +457,24 @@ fn test_main() {
let solution = main(Range::empty(), Range::empty());
assert_diffs!([], solution, "Null case");
- let solution = main(Range::new("abc", ..), Range::new("abc", ..));
+ let solution = main(range!("abc"), range!("abc"));
assert_diffs!([Equal("abc")], solution, "Equality");
- let solution = main(Range::new("abc", ..), Range::new("ab123c", ..));
+ let solution = main(range!("abc"), range!("ab123c"));
assert_diffs!(
[Equal("ab"), Insert("123"), Equal("c")],
solution,
"Simple insertion",
);
- let solution = main(Range::new("a123bc", ..), Range::new("abc", ..));
+ let solution = main(range!("a123bc"), range!("abc"));
assert_diffs!(
[Equal("a"), Delete("123"), Equal("bc")],
solution,
"Simple deletion",
);
- let solution = main(Range::new("abc", ..), Range::new("a123b456c", ..));
+ let solution = main(range!("abc"), range!("a123b456c"));
assert_diffs!(
[
Equal("a"),
@@ -476,7 +487,7 @@ fn test_main() {
"Two insertions",
);
- let solution = main(Range::new("a123b456c", ..), Range::new("abc", ..));
+ let solution = main(range!("a123b456c"), range!("abc"));
assert_diffs!(
[
Equal("a"),
@@ -489,12 +500,12 @@ fn test_main() {
"Two deletions",
);
- let solution = main(Range::new("a", ..), Range::new("b", ..));
+ let solution = main(range!("a"), range!("b"));
assert_diffs!([Delete("a"), Insert("b")], solution, "Simple case #1");
let solution = main(
- Range::new("Apples are a fruit.", ..),
- Range::new("Bananas are also fruit.", ..),
+ range!("Apples are a fruit."),
+ range!("Bananas are also fruit."),
);
assert_diffs!(
[
@@ -508,7 +519,7 @@ fn test_main() {
"Simple case #2",
);
- let solution = main(Range::new("ax\t", ..), Range::new("\u{0680}x\000", ..));
+ let solution = main(range!("ax\t"), range!("\u{0680}x\000"));
assert_diffs!(
[
Delete("a"),
@@ -521,7 +532,7 @@ fn test_main() {
"Simple case #3",
);
- let solution = main(Range::new("1ayb2", ..), Range::new("abxab", ..));
+ let solution = main(range!("1ayb2"), range!("abxab"));
assert_diffs!(
[
Delete("1"),
@@ -535,7 +546,7 @@ fn test_main() {
"Overlap #1",
);
- let solution = main(Range::new("abcy", ..), Range::new("xaxcxabc", ..));
+ let solution = main(range!("abcy"), range!("xaxcxabc"));
assert_diffs!(
[Insert("xaxcx"), Equal("abc"), Delete("y")],
solution,
@@ -543,8 +554,8 @@ fn test_main() {
);
let solution = main(
- Range::new("ABCDa=bcd=efghijklmnopqrsEFGHIJKLMNOefg", ..),
- Range::new("a-bcd-efghijklmnopqrs", ..),
+ range!("ABCDa=bcd=efghijklmnopqrsEFGHIJKLMNOefg"),
+ range!("a-bcd-efghijklmnopqrs"),
);
assert_diffs!(
[
@@ -563,8 +574,8 @@ fn test_main() {
);
let solution = main(
- Range::new("a [[Pennsylvania]] and [[New", ..),
- Range::new(" and [[Pennsylvania]]", ..),
+ range!("a [[Pennsylvania]] and [[New"),
+ range!(" and [[Pennsylvania]]"),
);
assert_diffs!(
[
diff --git a/vendor/dissimilar/tests/test.rs b/vendor/dissimilar/tests/test.rs
index e68fd4f11..7debb0593 100644
--- a/vendor/dissimilar/tests/test.rs
+++ b/vendor/dissimilar/tests/test.rs
@@ -21,7 +21,7 @@ fn test_unicode() {
}
#[test]
-fn test_unicode2() {
+fn test_issue9() {
let a = "[乀丁abcd一]";
let b = "[一abcd丁]";
let d = diff(a, b);
@@ -35,6 +35,18 @@ fn test_unicode2() {
Chunk::Delete("一"),
Chunk::Insert("丁"),
Chunk::Equal("]"),
- ]
+ ],
+ );
+}
+
+#[test]
+fn test_issue15() {
+ let a = "A のダ";
+ let b = "A ダ";
+ let d = diff(a, b);
+
+ assert_eq!(
+ d,
+ vec![Chunk::Equal("A "), Chunk::Delete("の"), Chunk::Equal("ダ")],
);
}
diff --git a/vendor/elsa/.cargo-checksum.json b/vendor/elsa/.cargo-checksum.json
new file mode 100644
index 000000000..a43c1ffd2
--- /dev/null
+++ b/vendor/elsa/.cargo-checksum.json
@@ -0,0 +1 @@
+{"files":{"Cargo.lock":"436a38effb1bc439febdcf0235758d480258326fb87c19c5cd482194e37d19f3","Cargo.toml":"3f3f154070e2d096c40b6080e233e0f081cd8c67b033fb5150badf7cb3f97a7f","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"15656cc11a8331f28c0986b8ab97220d3e76f98e60ed388b5ffad37dfac4710c","README.md":"72ec631a7cc4907ab80d87776b8eb1929d7cbd76b260f2fdb913714787f30dac","examples/arena.rs":"dd44f11e4b4e8b1eedca5ce5205aef3efface3c8888daa16b735dd476362b335","examples/fluentresource.rs":"d2bc2a1b02e6c92819bc608d91214591d8dc7d52f7f524c24e39ba5fe28ee6fe","examples/mutable_arena.rs":"553541b20ac97339cf89e2ef60810490f8362520911f3279f4129a30c2af6eb6","examples/string_interner.rs":"d8b427b71e6c340bf8ee01bc1245c82839fa6efb3dde6b91aab8791f0dfebbf9","examples/sync.rs":"bf9f395c029129fac6247068874b9514e0a174d342174dc4c65716acdbce3741","src/index_map.rs":"c265730dc36a49c8e7966226ebab0aa74f6c828fa6a5b3779a8df4bd34981c19","src/index_set.rs":"2173479eb3cd1009ed4e6b54ebc8aab8e0869d076b7e270dc937657e49838e01","src/lib.rs":"d26839bf88764445d2ec453b269b4359761186afda947101ee42c344cb0ad940","src/map.rs":"8f663631d817081dc8eac50d5235cac28f11dac0f8ebef6f57676d495b1aaab3","src/sync.rs":"8bc2e17981f58c9773e90d5ef40f66ebb1a13ee0f794294133486e6b4f5b50a0","src/vec.rs":"c9f053f0e22dc40ff1137d60b87650bf521f09a41111c4b8329b37af59893697"},"package":"f74077c3c3aedb99a2683919698285596662518ea13e5eedcf8bdd43b0d0453b"} \ No newline at end of file
diff --git a/vendor/elsa/Cargo.lock b/vendor/elsa/Cargo.lock
new file mode 100644
index 000000000..a03e9a806
--- /dev/null
+++ b/vendor/elsa/Cargo.lock
@@ -0,0 +1,39 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+version = 3
+
+[[package]]
+name = "autocfg"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
+
+[[package]]
+name = "elsa"
+version = "1.8.0"
+dependencies = [
+ "indexmap",
+ "stable_deref_trait",
+]
+
+[[package]]
+name = "hashbrown"
+version = "0.11.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e"
+
+[[package]]
+name = "indexmap"
+version = "1.8.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0f647032dfaa1f8b6dc29bd3edb7bbef4861b8b8007ebb118d6db284fd59f6ee"
+dependencies = [
+ "autocfg",
+ "hashbrown",
+]
+
+[[package]]
+name = "stable_deref_trait"
+version = "1.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3"
diff --git a/vendor/elsa/Cargo.toml b/vendor/elsa/Cargo.toml
new file mode 100644
index 000000000..b9c473a20
--- /dev/null
+++ b/vendor/elsa/Cargo.toml
@@ -0,0 +1,47 @@
+# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
+#
+# When uploading crates to the registry Cargo will automatically
+# "normalize" Cargo.toml files for maximal compatibility
+# with all versions of Cargo and also rewrite `path` dependencies
+# to registry (e.g., crates.io) dependencies.
+#
+# If you are reading this file be aware that the original Cargo.toml
+# will likely look very different (and much more reasonable).
+# See Cargo.toml.orig for the original contents.
+
+[package]
+edition = "2018"
+name = "elsa"
+version = "1.8.0"
+authors = ["Manish Goregaokar <manishsmail@gmail.com>"]
+description = "Append-only collections for Rust where borrows to entries can outlive insertions"
+documentation = "https://docs.rs/elsa/"
+readme = "README.md"
+keywords = [
+ "data-structure",
+ "map",
+ "frozen",
+ "cache",
+ "arena",
+]
+categories = [
+ "data-structures",
+ "caching",
+]
+license = "MIT/Apache-2.0"
+repository = "https://github.com/manishearth/elsa"
+
+[package.metadata.docs.rs]
+features = ["indexmap"]
+
+[[example]]
+name = "string_interner"
+path = "examples/string_interner.rs"
+required-features = ["indexmap"]
+
+[dependencies.indexmap]
+version = "1.6"
+optional = true
+
+[dependencies.stable_deref_trait]
+version = "1.1.1"
diff --git a/vendor/toml/LICENSE-APACHE b/vendor/elsa/LICENSE-APACHE
index 16fe87b06..16fe87b06 100644
--- a/vendor/toml/LICENSE-APACHE
+++ b/vendor/elsa/LICENSE-APACHE
diff --git a/vendor/elsa/LICENSE-MIT b/vendor/elsa/LICENSE-MIT
new file mode 100644
index 000000000..d74f9e93d
--- /dev/null
+++ b/vendor/elsa/LICENSE-MIT
@@ -0,0 +1,27 @@
+MIT License
+
+Copyright (c) 2019 Manish Goregaokar
+
+Permission is hereby granted, free of charge, to any
+person obtaining a copy of this software and associated
+documentation files (the "Software"), to deal in the
+Software without restriction, including without
+limitation the rights to use, copy, modify, merge,
+publish, distribute, sublicense, and/or sell copies of
+the Software, and to permit persons to whom the Software
+is furnished to do so, subject to the following
+conditions:
+
+The above copyright notice and this permission notice
+shall be included in all copies or substantial portions
+of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
+ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
+TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
+SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
+IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
diff --git a/vendor/elsa/README.md b/vendor/elsa/README.md
new file mode 100644
index 000000000..cd4a5b94a
--- /dev/null
+++ b/vendor/elsa/README.md
@@ -0,0 +1,19 @@
+## elsa
+
+[![Build Status](https://travis-ci.org/Manishearth/elsa.svg?branch=master)](https://travis-ci.org/Manishearth/elsa)
+[![Current Version](https://img.shields.io/crates/v/elsa.svg)](https://crates.io/crates/elsa)
+[![License: MIT/Apache-2.0](https://img.shields.io/crates/l/elsa.svg)](#license)
+
+_🎵 Immutability never bothered me anyway 🎶_
+
+This crate provides various "frozen" collections.
+
+These are append-only collections where references to entries can be held on to even across insertions. This is safe because these collections only support storing data that's present behind some indirection -- i.e. `String`, `Vec<T>`, `Box<T>`, etc, and they only yield references to the data behind the allocation (`&str`, `&[T]`, and `&T` respectively)
+
+The typical use case is having a global cache of strings or other data which the rest of the program borrows from.
+
+### Running all examples
+
+```bash
+cargo test --examples --features indexmap
+```
diff --git a/vendor/elsa/examples/arena.rs b/vendor/elsa/examples/arena.rs
new file mode 100644
index 000000000..79913c2e7
--- /dev/null
+++ b/vendor/elsa/examples/arena.rs
@@ -0,0 +1,56 @@
+use elsa::FrozenVec;
+
+fn main() {
+ let arena = Arena::new();
+ let lonely = arena.add_thing("lonely", vec![]);
+ let best_friend = arena.add_thing("best friend", vec![lonely]);
+ let threes_a_crowd = arena.add_thing("threes a crowd", vec![lonely, best_friend]);
+ let rando = arena.add_thing("rando", vec![]);
+ let _facebook = arena.add_thing("facebook", vec![rando, threes_a_crowd, lonely, best_friend]);
+
+ assert!(cmp_ref(lonely, best_friend.friends[0]));
+ assert!(cmp_ref(best_friend, threes_a_crowd.friends[1]));
+ arena.dump();
+}
+
+struct Arena<'arena> {
+ things: FrozenVec<Box<Thing<'arena>>>,
+}
+
+struct Thing<'arena> {
+ pub friends: Vec<ThingRef<'arena>>,
+ pub name: &'static str,
+}
+
+type ThingRef<'arena> = &'arena Thing<'arena>;
+
+impl<'arena> Arena<'arena> {
+ fn new() -> Arena<'arena> {
+ Arena {
+ things: FrozenVec::new(),
+ }
+ }
+
+ fn add_thing(
+ &'arena self,
+ name: &'static str,
+ friends: Vec<ThingRef<'arena>>,
+ ) -> ThingRef<'arena> {
+ let idx = self.things.len();
+ self.things.push(Box::new(Thing { name, friends }));
+ &self.things[idx]
+ }
+
+ fn dump(&'arena self) {
+ for thing in &self.things {
+ println!("friends of {}:", thing.name);
+ for friend in &thing.friends {
+ println!("\t{}", friend.name);
+ }
+ }
+ }
+}
+
+fn cmp_ref<T>(x: &T, y: &T) -> bool {
+ x as *const T as usize == y as *const T as usize
+}
diff --git a/vendor/elsa/examples/fluentresource.rs b/vendor/elsa/examples/fluentresource.rs
new file mode 100644
index 000000000..dba4aaed8
--- /dev/null
+++ b/vendor/elsa/examples/fluentresource.rs
@@ -0,0 +1,50 @@
+use elsa::FrozenMap;
+
+/// Stores some parsed AST representation of the file
+#[derive(Debug)]
+pub struct FluentResource<'mgr>(&'mgr str);
+
+impl<'mgr> FluentResource<'mgr> {
+ pub fn new(s: &'mgr str) -> Self {
+ // very simple parse step
+ FluentResource(&s[0..1])
+ }
+}
+
+/// Stores loaded files and parsed ASTs
+///
+/// Parsed ASTs are zero-copy and
+/// contain references to the files
+pub struct ResourceManager<'mgr> {
+ strings: FrozenMap<String, String>,
+ resources: FrozenMap<String, Box<FluentResource<'mgr>>>,
+}
+
+impl<'mgr> ResourceManager<'mgr> {
+ pub fn new() -> Self {
+ ResourceManager {
+ strings: FrozenMap::new(),
+ resources: FrozenMap::new(),
+ }
+ }
+
+ pub fn get_resource(&'mgr self, path: &str) -> &'mgr FluentResource<'mgr> {
+ let strings = &self.strings;
+
+ if strings.get(path).is_some() {
+ return self.resources.get(path).unwrap();
+ } else {
+ // pretend to load a file
+ let string = format!("file for {}", path);
+ let val = self.strings.insert(path.to_string(), string);
+ let res = FluentResource::new(val);
+ self.resources.insert(path.to_string(), Box::new(res))
+ }
+ }
+}
+
+fn main() {
+ let manager = ResourceManager::new();
+ let resource = manager.get_resource("somefile.ftl");
+ println!("{:?}", resource);
+}
diff --git a/vendor/elsa/examples/mutable_arena.rs b/vendor/elsa/examples/mutable_arena.rs
new file mode 100644
index 000000000..d5db2d331
--- /dev/null
+++ b/vendor/elsa/examples/mutable_arena.rs
@@ -0,0 +1,79 @@
+use elsa::FrozenVec;
+
+fn main() {
+ let arena = Arena::new();
+ let lonely = arena.add_person("lonely", vec![]);
+ let best_friend = arena.add_person("best friend", vec![lonely]);
+ let threes_a_crowd = arena.add_person("threes a crowd", vec![lonely, best_friend]);
+ let rando = arena.add_person("rando", vec![]);
+ let _everyone = arena.add_person(
+ "follows everyone",
+ vec![rando, threes_a_crowd, lonely, best_friend],
+ );
+ arena.dump();
+}
+
+struct Arena<'arena> {
+ people: FrozenVec<Box<Person<'arena>>>,
+}
+
+struct Person<'arena> {
+ pub follows: FrozenVec<PersonRef<'arena>>,
+ pub reverse_follows: FrozenVec<PersonRef<'arena>>,
+ pub name: &'static str,
+}
+
+type PersonRef<'arena> = &'arena Person<'arena>;
+
+impl<'arena> Arena<'arena> {
+ fn new() -> Arena<'arena> {
+ Arena {
+ people: FrozenVec::new(),
+ }
+ }
+
+ fn add_person(
+ &'arena self,
+ name: &'static str,
+ follows: Vec<PersonRef<'arena>>,
+ ) -> PersonRef<'arena> {
+ let idx = self.people.len();
+ self.people.push(Box::new(Person {
+ name,
+ follows: follows.into(),
+ reverse_follows: Default::default(),
+ }));
+ let me = &self.people[idx];
+ for friend in &me.follows {
+ friend.reverse_follows.push(me)
+ }
+ me
+ }
+
+ fn dump(&'arena self) {
+ for thing in &self.people {
+ println!("{} network:", thing.name);
+ println!("\tfollowing:");
+ for friend in &thing.follows {
+ println!("\t\t{}", friend.name);
+ }
+ println!("\tfollowers:");
+ for friend in &thing.reverse_follows {
+ println!("\t\t{}", friend.name);
+ }
+ }
+ }
+}
+
+// Note that the following will cause the above code to stop compiling
+// since non-eyepatched custom destructors can potentially
+// read deallocated data.
+//
+// impl<'arena> Drop for Person<'arena> {
+// fn drop(&mut self) {
+// println!("goodbye {:?}", self.name);
+// for friend in &self.follows {
+// println!("\t\t{}", friend.name);
+// }
+// }
+// }
diff --git a/vendor/elsa/examples/string_interner.rs b/vendor/elsa/examples/string_interner.rs
new file mode 100644
index 000000000..fd039f7ba
--- /dev/null
+++ b/vendor/elsa/examples/string_interner.rs
@@ -0,0 +1,61 @@
+use std::collections::BTreeSet;
+use std::convert::AsRef;
+
+use elsa::FrozenIndexSet;
+
+struct StringInterner {
+ set: FrozenIndexSet<String>,
+}
+
+impl StringInterner {
+ fn new() -> Self {
+ StringInterner {
+ set: FrozenIndexSet::new(),
+ }
+ }
+
+ fn get_or_intern<T>(&self, value: T) -> usize
+ where
+ T: AsRef<str>,
+ {
+ // TODO use Entry in case the standard Entry API gets improved
+ // (here to avoid premature allocation or double lookup)
+ self.set.insert_full(value.as_ref().to_string()).0
+ }
+
+ fn get<T>(&self, value: T) -> Option<usize>
+ where
+ T: AsRef<str>,
+ {
+ self.set.get_full(value.as_ref()).map(|(i, _r)| i)
+ }
+
+ fn resolve(&self, index: usize) -> Option<&str> {
+ self.set.get_index(index)
+ }
+}
+
+fn main() {
+ let interner = StringInterner::new();
+ let lonely = interner.get_or_intern("lonely");
+ let best_friend = interner.get_or_intern("best friend");
+ let threes_a_crowd = interner.get_or_intern("threes a crowd");
+ let rando = interner.get_or_intern("rando");
+ let _facebook = interner.get_or_intern("facebook");
+
+ let best_friend_2 = interner.get_or_intern("best friend");
+ let best_friend_3 = interner.get("best friend").unwrap();
+
+ let best_friend_ref = interner.resolve(best_friend).unwrap();
+
+ let mut set = BTreeSet::new();
+ set.insert(lonely);
+ set.insert(best_friend);
+ set.insert(threes_a_crowd);
+ set.insert(rando);
+ set.insert(best_friend_2);
+ assert_eq!(set.len(), 4);
+ assert_eq!(best_friend, best_friend_2);
+ assert_eq!(best_friend_2, best_friend_3);
+ assert_eq!(best_friend_ref, "best friend");
+}
diff --git a/vendor/elsa/examples/sync.rs b/vendor/elsa/examples/sync.rs
new file mode 100644
index 000000000..c6d9eb3cc
--- /dev/null
+++ b/vendor/elsa/examples/sync.rs
@@ -0,0 +1,26 @@
+use elsa::sync::*;
+
+use std::sync::Arc;
+use std::thread;
+use std::time::Duration;
+
+fn main() {
+ let a = Arc::new(FrozenMap::new());
+ for i in 1..10 {
+ let b = a.clone();
+ thread::spawn(move || {
+ b.insert(i, i.to_string());
+ thread::sleep(Duration::from_millis(300));
+ loop {
+ if let Some(opposite) = b.get(&(10 - i)) {
+ assert!(opposite.parse::<i32>().unwrap() == 10 - i);
+ break;
+ } else {
+ thread::sleep(Duration::from_millis(200));
+ }
+ }
+ });
+ }
+
+ thread::sleep(Duration::from_millis(1000));
+}
diff --git a/vendor/elsa/src/index_map.rs b/vendor/elsa/src/index_map.rs
new file mode 100644
index 000000000..3c97dfbaa
--- /dev/null
+++ b/vendor/elsa/src/index_map.rs
@@ -0,0 +1,215 @@
+use std::borrow::Borrow;
+use std::cell::{Cell, UnsafeCell};
+use std::collections::hash_map::RandomState;
+use std::hash::{BuildHasher, Hash};
+use std::iter::FromIterator;
+use std::ops::Index;
+
+use indexmap::IndexMap;
+use stable_deref_trait::StableDeref;
+
+/// Append-only version of `indexmap::IndexMap` where
+/// insertion does not require mutable access
+pub struct FrozenIndexMap<K, V, S = RandomState> {
+ map: UnsafeCell<IndexMap<K, V, S>>,
+ /// Eq/Hash implementations can have side-effects, and using Rc it is possible
+ /// for FrozenIndexMap::insert to be called on a key that itself contains the same
+ /// `FrozenIndexMap`, whose `eq` implementation also calls FrozenIndexMap::insert
+ ///
+ /// We use this `in_use` flag to guard against any reentrancy.
+ in_use: Cell<bool>,
+}
+
+// safety: UnsafeCell implies !Sync
+
+impl<K: Eq + Hash, V> FrozenIndexMap<K, V> {
+ pub fn new() -> Self {
+ Self {
+ map: UnsafeCell::new(Default::default()),
+ in_use: Cell::new(false),
+ }
+ }
+}
+
+impl<K: Eq + Hash, V: StableDeref, S: BuildHasher> FrozenIndexMap<K, V, S> {
+ // these should never return &K or &V
+ // these should never delete any entries
+ pub fn insert(&self, k: K, v: V) -> &V::Target {
+ assert!(!self.in_use.get());
+ self.in_use.set(true);
+ let ret = unsafe {
+ let map = self.map.get();
+ &*(*map).entry(k).or_insert(v)
+ };
+ self.in_use.set(false);
+ ret
+ }
+
+ // these should never return &K or &V
+ // these should never delete any entries
+ pub fn insert_full(&self, k: K, v: V) -> (usize, &V::Target) {
+ assert!(!self.in_use.get());
+ self.in_use.set(true);
+ let ret = unsafe {
+ let map = self.map.get();
+ let entry = (*map).entry(k);
+ let index = entry.index();
+ (index, &**entry.or_insert(v))
+ };
+ self.in_use.set(false);
+ ret
+ }
+
+ /// Returns a reference to the value corresponding to the key.
+ ///
+ /// The key may be any borrowed form of the map's key type, but
+ /// [`Hash`] and [`Eq`] on the borrowed form *must* match those for
+ /// the key type.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use elsa::FrozenIndexMap;
+ ///
+ /// let map = FrozenIndexMap::new();
+ /// map.insert(1, Box::new("a"));
+ /// assert_eq!(map.get(&1), Some(&"a"));
+ /// assert_eq!(map.get(&2), None);
+ /// ```
+ pub fn get<Q: ?Sized>(&self, k: &Q) -> Option<&V::Target>
+ where
+ K: Borrow<Q>,
+ Q: Hash + Eq,
+ {
+ assert!(!self.in_use.get());
+ self.in_use.set(true);
+ let ret = unsafe {
+ let map = self.map.get();
+ (*map).get(k).map(|x| &**x)
+ };
+ self.in_use.set(false);
+ ret
+ }
+
+ pub fn get_index(&self, index: usize) -> Option<(&K::Target, &V::Target)>
+ where
+ K: StableDeref,
+ {
+ assert!(!self.in_use.get());
+ self.in_use.set(true);
+ let ret = unsafe {
+ let map = self.map.get();
+ (*map).get_index(index).map(|(k, v)| (&**k, &**v))
+ };
+ self.in_use.set(false);
+ ret
+ }
+
+ /// Applies a function to the owner of the value corresponding to the key (if any).
+ ///
+ /// The key may be any borrowed form of the map's key type, but
+ /// [`Hash`] and [`Eq`] on the borrowed form *must* match those for
+ /// the key type.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use elsa::FrozenIndexMap;
+ ///
+ /// let map = FrozenIndexMap::new();
+ /// map.insert(1, Box::new("a"));
+ /// assert_eq!(map.map_get(&1, Clone::clone), Some(Box::new("a")));
+ /// assert_eq!(map.map_get(&2, Clone::clone), None);
+ /// ```
+ pub fn map_get<Q: ?Sized, T, F>(&self, k: &Q, f: F) -> Option<T>
+ where
+ K: Borrow<Q>,
+ Q: Hash + Eq,
+ F: FnOnce(&V) -> T,
+ {
+ assert!(!self.in_use.get());
+ self.in_use.set(true);
+ let ret = unsafe {
+ let map = self.map.get();
+ (*map).get(k).map(f)
+ };
+ self.in_use.set(false);
+ ret
+ }
+
+ pub fn into_map(self) -> IndexMap<K, V, S> {
+ self.map.into_inner()
+ }
+
+ /// Get mutable access to the underlying [`IndexMap`].
+ ///
+ /// This is safe, as it requires a `&mut self`, ensuring nothing is using
+ /// the 'frozen' contents.
+ pub fn as_mut(&mut self) -> &mut IndexMap<K, V, S> {
+ unsafe { &mut *self.map.get() }
+ }
+
+ /// Returns true if the map contains no elements.
+ pub fn is_empty(&self) -> bool {
+ assert!(!self.in_use.get());
+ self.in_use.set(true);
+ let ret = unsafe {
+ let map = self.map.get();
+ (*map).is_empty()
+ };
+ self.in_use.set(false);
+ ret
+ }
+}
+
+impl<K, V, S> From<IndexMap<K, V, S>> for FrozenIndexMap<K, V, S> {
+ fn from(map: IndexMap<K, V, S>) -> Self {
+ Self {
+ map: UnsafeCell::new(map),
+ in_use: Cell::new(false),
+ }
+ }
+}
+
+impl<Q: ?Sized, K: Eq + Hash, V: StableDeref, S: BuildHasher> Index<&Q> for FrozenIndexMap<K, V, S>
+ where
+ Q: Eq + Hash,
+ K: Eq + Hash + Borrow<Q>,
+ V: StableDeref,
+ S: BuildHasher
+{
+ type Output = V::Target;
+
+ /// # Examples
+ ///
+ /// ```
+ /// use elsa::FrozenIndexMap;
+ ///
+ /// let map = FrozenIndexMap::new();
+ /// map.insert(1, Box::new("a"));
+ /// assert_eq!(map[&1], "a");
+ /// ```
+ fn index(&self, idx: &Q) -> &V::Target {
+ self.get(&idx)
+ .expect("attempted to index FrozenIndexMap with unknown key")
+ }
+}
+
+impl<K: Eq + Hash, V, S: BuildHasher + Default> FromIterator<(K, V)> for FrozenIndexMap<K, V, S> {
+ fn from_iter<T>(iter: T) -> Self
+ where
+ T: IntoIterator<Item = (K, V)>,
+ {
+ let map: IndexMap<_, _, _> = iter.into_iter().collect();
+ map.into()
+ }
+}
+
+impl<K: Eq + Hash, V, S: Default> Default for FrozenIndexMap<K, V, S> {
+ fn default() -> Self {
+ Self {
+ map: UnsafeCell::new(Default::default()),
+ in_use: Cell::new(false),
+ }
+ }
+}
diff --git a/vendor/elsa/src/index_set.rs b/vendor/elsa/src/index_set.rs
new file mode 100644
index 000000000..1222cde05
--- /dev/null
+++ b/vendor/elsa/src/index_set.rs
@@ -0,0 +1,180 @@
+use std::borrow::Borrow;
+use std::cell::{Cell, UnsafeCell};
+use std::collections::hash_map::RandomState;
+use std::hash::{BuildHasher, Hash};
+use std::iter::FromIterator;
+use std::ops::Index;
+
+use indexmap::IndexSet;
+use stable_deref_trait::StableDeref;
+
+/// Append-only version of `indexmap::IndexSet` where
+/// insertion does not require mutable access
+pub struct FrozenIndexSet<T, S = RandomState> {
+ set: UnsafeCell<IndexSet<T, S>>,
+ /// Eq/Hash implementations can have side-effects, and using Rc it is possible
+ /// for FrozenIndexSet::insert to be called on a key that itself contains the same
+ /// `FrozenIndexSet`, whose `eq` implementation also calls FrozenIndexSet::insert
+ ///
+ /// We use this `in_use` flag to guard against any reentrancy.
+ in_use: Cell<bool>,
+}
+
+// safety: UnsafeCell implies !Sync
+
+impl<T: Eq + Hash> FrozenIndexSet<T> {
+ pub fn new() -> Self {
+ Self::from(IndexSet::new())
+ }
+}
+
+impl<T: Eq + Hash + StableDeref, S: BuildHasher> FrozenIndexSet<T, S> {
+ // these should never return &T
+ // these should never delete any entries
+ pub fn insert(&self, value: T) -> &T::Target {
+ assert!(!self.in_use.get());
+ self.in_use.set(true);
+ let ret = unsafe {
+ let set = self.set.get();
+ let (index, _was_vacant) = (*set).insert_full(value);
+ &*(*set)[index]
+ };
+ self.in_use.set(false);
+ ret
+ }
+
+ // these should never return &T
+ // these should never delete any entries
+ pub fn insert_full(&self, value: T) -> (usize, &T::Target) {
+ assert!(!self.in_use.get());
+ self.in_use.set(true);
+ let ret = unsafe {
+ let set = self.set.get();
+ let (index, _was_vacant) = (*set).insert_full(value);
+ (index, &*(*set)[index])
+ };
+ self.in_use.set(false);
+ ret
+ }
+
+ // TODO implement in case the standard Entry API gets improved
+ // // TODO avoid double lookup
+ // pub fn entry<Q: ?Sized>(&self, value: &Q) -> Entry<T, Q>
+ // where Q: Hash + Equivalent<T> + ToOwned<Owned = T>
+ // {
+ // assert!(!self.in_use.get());
+ // self.in_use.set(true);
+ // unsafe {
+ // let set = self.set.get();
+ // match (*set).get_full(value) {
+ // Some((index, reference)) => {
+ // Entry::Occupied(OccupiedEntry {
+ // index,
+ // reference,
+ // set: &*set,
+ // })
+ // }
+ // None => {
+ // Entry::Vacant(VacantEntry {
+ // value: Cow::Borrowed(value),
+ // set: &*set,
+ // })
+ // }
+ // }
+ // }
+ // }
+
+ pub fn get<Q: ?Sized>(&self, k: &Q) -> Option<&T::Target>
+ where
+ T: Borrow<Q>,
+ Q: Hash + Eq,
+ {
+ assert!(!self.in_use.get());
+ self.in_use.set(true);
+ let ret = unsafe {
+ let set = self.set.get();
+ (*set).get(k).map(|x| &**x)
+ };
+ self.in_use.set(false);
+ ret
+ }
+
+ pub fn get_full<Q: ?Sized>(&self, k: &Q) -> Option<(usize, &T::Target)>
+ where
+ T: Borrow<Q>,
+ Q: Hash + Eq,
+ {
+ assert!(!self.in_use.get());
+ self.in_use.set(true);
+ let ret = unsafe {
+ let set = self.set.get();
+ (*set).get_full(k).map(|(i, x)| (i, &**x))
+ };
+ self.in_use.set(false);
+ ret
+ }
+
+ pub fn get_index(&self, index: usize) -> Option<&T::Target> {
+ assert!(!self.in_use.get());
+ self.in_use.set(true);
+ let ret = unsafe {
+ let set = self.set.get();
+ (*set).get_index(index).map(|r| &**r)
+ };
+ self.in_use.set(false);
+ ret
+ }
+
+ pub fn into_set(self) -> IndexSet<T, S> {
+ self.set.into_inner()
+ }
+
+ /// Get mutable access to the underlying [`IndexSet`].
+ ///
+ /// This is safe, as it requires a `&mut self`, ensuring nothing is using
+ /// the 'frozen' contents.
+ pub fn as_mut(&mut self) -> &mut IndexSet<T, S> {
+ unsafe { &mut *self.set.get() }
+ }
+
+ // TODO add more
+}
+
+impl<T, S> From<IndexSet<T, S>> for FrozenIndexSet<T, S> {
+ fn from(set: IndexSet<T, S>) -> Self {
+ Self {
+ set: UnsafeCell::new(set),
+ in_use: Cell::new(false),
+ }
+ }
+}
+
+impl<T: Eq + Hash + StableDeref, S> Index<usize> for FrozenIndexSet<T, S> {
+ type Output = T::Target;
+ fn index(&self, idx: usize) -> &T::Target {
+ assert!(!self.in_use.get());
+ self.in_use.set(true);
+ let ret = unsafe {
+ let set = self.set.get();
+ &*(*set)[idx]
+ };
+ self.in_use.set(false);
+ ret
+ }
+}
+
+impl<T: Eq + Hash, S: Default + BuildHasher> FromIterator<T> for FrozenIndexSet<T, S> {
+ fn from_iter<U>(iter: U) -> Self
+ where
+ U: IntoIterator<Item = T>,
+ {
+ let set: IndexSet<_, _> = iter.into_iter().collect();
+ set.into()
+ }
+}
+
+impl<T: Eq + Hash, S: Default> Default for FrozenIndexSet<T, S> {
+ fn default() -> Self {
+ Self::from(IndexSet::default())
+ }
+}
diff --git a/vendor/elsa/src/lib.rs b/vendor/elsa/src/lib.rs
new file mode 100644
index 000000000..848dceb34
--- /dev/null
+++ b/vendor/elsa/src/lib.rs
@@ -0,0 +1,29 @@
+//! _🎵 Immutability never bothered me anyway 🎶_
+//!
+//! This crate provides various "Frozen" collections.
+//!
+//! These are append-only collections where references to entries can be held
+//! on to even across insertions. This is safe because these collections only
+//! support storing data that's present behind some indirection -- i.e. `String`,
+//! `Vec<T>`, `Box<T>`, etc, and they only yield references to the data behind the
+//! allocation (`&str`, `&[T]`, and `&T` respectively)
+//!
+//! The typical use case is having a global cache of strings or other data which the rest of the program borrows from.
+
+pub mod map;
+pub mod vec;
+
+#[cfg(feature = "indexmap")]
+pub mod index_map;
+#[cfg(feature = "indexmap")]
+pub mod index_set;
+
+pub mod sync;
+
+pub use map::{FrozenBTreeMap, FrozenMap};
+pub use vec::FrozenVec;
+
+#[cfg(feature = "indexmap")]
+pub use index_map::FrozenIndexMap;
+#[cfg(feature = "indexmap")]
+pub use index_set::FrozenIndexSet;
diff --git a/vendor/elsa/src/map.rs b/vendor/elsa/src/map.rs
new file mode 100644
index 000000000..2faa19ce2
--- /dev/null
+++ b/vendor/elsa/src/map.rs
@@ -0,0 +1,451 @@
+use std::borrow::Borrow;
+use std::cell::{Cell, UnsafeCell};
+use std::collections::hash_map::RandomState;
+use std::collections::BTreeMap;
+use std::collections::HashMap;
+use std::hash::{BuildHasher, Hash};
+use std::iter::FromIterator;
+use std::ops::Index;
+
+use stable_deref_trait::StableDeref;
+
+/// Append-only version of `std::collections::HashMap` where
+/// insertion does not require mutable access
+pub struct FrozenMap<K, V, S = RandomState> {
+ map: UnsafeCell<HashMap<K, V, S>>,
+ /// Eq/Hash implementations can have side-effects, and using Rc it is possible
+ /// for FrozenMap::insert to be called on a key that itself contains the same
+ /// `FrozenMap`, whose `eq` implementation also calls FrozenMap::insert
+ ///
+ /// We use this `in_use` flag to guard against any reentrancy.
+ in_use: Cell<bool>,
+}
+
+// safety: UnsafeCell implies !Sync
+
+impl<K: Eq + Hash, V> FrozenMap<K, V> {
+ pub fn new() -> Self {
+ Self {
+ map: UnsafeCell::new(Default::default()),
+ in_use: Cell::new(false),
+ }
+ }
+
+ /// # Examples
+ ///
+ /// ```
+ /// use elsa::FrozenMap;
+ ///
+ /// let map = FrozenMap::new();
+ /// assert_eq!(map.len(), 0);
+ /// map.insert(1, Box::new("a"));
+ /// assert_eq!(map.len(), 1);
+ /// ```
+ pub fn len(&self) -> usize {
+ assert!(!self.in_use.get());
+ self.in_use.set(true);
+ let len = unsafe {
+ let map = self.map.get();
+ (*map).len()
+ };
+ self.in_use.set(false);
+ len
+ }
+
+ /// # Examples
+ ///
+ /// ```
+ /// use elsa::FrozenMap;
+ ///
+ /// let map = FrozenMap::new();
+ /// assert_eq!(map.is_empty(), true);
+ /// map.insert(1, Box::new("a"));
+ /// assert_eq!(map.is_empty(), false);
+ /// ```
+ pub fn is_empty(&self) -> bool {
+ self.len() == 0
+ }
+}
+
+impl<K: Eq + Hash, V: StableDeref, S: BuildHasher> FrozenMap<K, V, S> {
+ // these should never return &K or &V
+ // these should never delete any entries
+ pub fn insert(&self, k: K, v: V) -> &V::Target {
+ assert!(!self.in_use.get());
+ self.in_use.set(true);
+ let ret = unsafe {
+ let map = self.map.get();
+ &*(*map).entry(k).or_insert(v)
+ };
+ self.in_use.set(false);
+ ret
+ }
+
+ /// Returns a reference to the value corresponding to the key.
+ ///
+ /// The key may be any borrowed form of the map's key type, but
+ /// [`Hash`] and [`Eq`] on the borrowed form *must* match those for
+ /// the key type.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use elsa::FrozenMap;
+ ///
+ /// let map = FrozenMap::new();
+ /// map.insert(1, Box::new("a"));
+ /// assert_eq!(map.get(&1), Some(&"a"));
+ /// assert_eq!(map.get(&2), None);
+ /// ```
+ pub fn get<Q: ?Sized>(&self, k: &Q) -> Option<&V::Target>
+ where
+ K: Borrow<Q>,
+ Q: Hash + Eq,
+ {
+ assert!(!self.in_use.get());
+ self.in_use.set(true);
+ let ret = unsafe {
+ let map = self.map.get();
+ (*map).get(k).map(|x| &**x)
+ };
+ self.in_use.set(false);
+ ret
+ }
+
+ /// Applies a function to the owner of the value corresponding to the key (if any).
+ ///
+ /// The key may be any borrowed form of the map's key type, but
+ /// [`Hash`] and [`Eq`] on the borrowed form *must* match those for
+ /// the key type.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use elsa::FrozenMap;
+ ///
+ /// let map = FrozenMap::new();
+ /// map.insert(1, Box::new("a"));
+ /// assert_eq!(map.map_get(&1, Clone::clone), Some(Box::new("a")));
+ /// assert_eq!(map.map_get(&2, Clone::clone), None);
+ /// ```
+ pub fn map_get<Q: ?Sized, T, F>(&self, k: &Q, f: F) -> Option<T>
+ where
+ K: Borrow<Q>,
+ Q: Hash + Eq,
+ F: FnOnce(&V) -> T,
+ {
+ assert!(!self.in_use.get());
+ self.in_use.set(true);
+ let ret = unsafe {
+ let map = self.map.get();
+ (*map).get(k).map(f)
+ };
+ self.in_use.set(false);
+ ret
+ }
+
+ pub fn into_map(self) -> HashMap<K, V, S> {
+ self.map.into_inner()
+ }
+
+ // TODO add more
+}
+
+impl<K: Eq + Hash + StableDeref, V: StableDeref, S: BuildHasher> FrozenMap<K, V, S> {
+ /// Returns a reference to the key and value matching a borrowed
+ /// key.
+ ///
+ /// The key argument may be any borrowed form of the map's key type,
+ /// but [`Hash`] and [`Eq`] on the borrowed form *must* match those
+ /// for the key type.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use elsa::FrozenMap;
+ ///
+ /// let map = FrozenMap::new();
+ /// map.insert(Box::new("1"), Box::new("a"));
+ /// assert_eq!(map.get_key_value(&"1"), Some((&"1", &"a")));
+ /// assert_eq!(map.get_key_value(&"2"), None);
+ /// ```
+ pub fn get_key_value<Q: ?Sized>(&self, k: &Q) -> Option<(&K::Target, &V::Target)>
+ where
+ K: Borrow<Q>,
+ Q: Hash + Eq,
+ {
+ assert!(!self.in_use.get());
+ self.in_use.set(true);
+ let ret = unsafe {
+ let map = self.map.get();
+ (*map).get_key_value(k).map(|(k, v)| (&**k, &**v))
+ };
+ self.in_use.set(false);
+ ret
+ }
+}
+
+impl<K, V, S> std::convert::AsMut<HashMap<K, V, S>> for FrozenMap<K, V, S> {
+ /// Get mutable access to the underlying [`HashMap`].
+ ///
+ /// This is safe, as it requires a `&mut self`, ensuring nothing is using
+ /// the 'frozen' contents.
+ fn as_mut(&mut self) -> &mut HashMap<K, V, S> {
+ unsafe { &mut *self.map.get() }
+ }
+}
+
+impl<K, V, S> From<HashMap<K, V, S>> for FrozenMap<K, V, S> {
+ fn from(map: HashMap<K, V, S>) -> Self {
+ Self {
+ map: UnsafeCell::new(map),
+ in_use: Cell::new(false),
+ }
+ }
+}
+
+impl<Q: ?Sized, K, V, S> Index<&Q> for FrozenMap<K, V, S>
+where
+ Q: Eq + Hash,
+ K: Eq + Hash + Borrow<Q>,
+ V: StableDeref,
+ S: BuildHasher,
+{
+ type Output = V::Target;
+
+ /// # Examples
+ ///
+ /// ```
+ /// use elsa::FrozenMap;
+ ///
+ /// let map = FrozenMap::new();
+ /// map.insert(1, Box::new("a"));
+ /// assert_eq!(map[&1], "a");
+ /// ```
+ fn index(&self, idx: &Q) -> &V::Target {
+ self.get(idx)
+ .expect("attempted to index FrozenMap with unknown key")
+ }
+}
+
+impl<K: Eq + Hash, V, S: BuildHasher + Default> FromIterator<(K, V)> for FrozenMap<K, V, S> {
+ fn from_iter<T>(iter: T) -> Self
+ where
+ T: IntoIterator<Item = (K, V)>,
+ {
+ let map: HashMap<_, _, _> = iter.into_iter().collect();
+ map.into()
+ }
+}
+
+impl<K: Eq + Hash, V, S: Default> Default for FrozenMap<K, V, S> {
+ fn default() -> Self {
+ Self {
+ map: UnsafeCell::new(Default::default()),
+ in_use: Cell::new(false),
+ }
+ }
+}
+
+/// Append-only version of `std::collections::BTreeMap` where
+/// insertion does not require mutable access
+pub struct FrozenBTreeMap<K, V> {
+ map: UnsafeCell<BTreeMap<K, V>>,
+ /// Eq/Hash implementations can have side-effects, and using Rc it is possible
+ /// for FrozenBTreeMap::insert to be called on a key that itself contains the same
+ /// `FrozenBTreeMap`, whose `eq` implementation also calls FrozenBTreeMap::insert
+ ///
+ /// We use this `in_use` flag to guard against any reentrancy.
+ in_use: Cell<bool>,
+}
+
+// safety: UnsafeCell implies !Sync
+
+impl<K: Clone + Ord, V: StableDeref> FrozenBTreeMap<K, V> {
+ pub fn new() -> Self {
+ Self {
+ map: UnsafeCell::new(Default::default()),
+ in_use: Cell::new(false),
+ }
+ }
+
+ /// # Examples
+ ///
+ /// ```
+ /// use elsa::FrozenBTreeMap;
+ ///
+ /// let map = FrozenBTreeMap::new();
+ /// assert_eq!(map.len(), 0);
+ /// map.insert(1, Box::new("a"));
+ /// assert_eq!(map.len(), 1);
+ /// ```
+ pub fn len(&self) -> usize {
+ assert!(!self.in_use.get());
+ self.in_use.set(true);
+ let len = unsafe {
+ let map = self.map.get();
+ (*map).len()
+ };
+ self.in_use.set(false);
+ len
+ }
+
+ /// # Examples
+ ///
+ /// ```
+ /// use elsa::FrozenBTreeMap;
+ ///
+ /// let map = FrozenBTreeMap::new();
+ /// assert_eq!(map.is_empty(), true);
+ /// map.insert(1, Box::new("a"));
+ /// assert_eq!(map.is_empty(), false);
+ /// ```
+ pub fn is_empty(&self) -> bool {
+ self.len() == 0
+ }
+}
+
+impl<K: Clone + Ord, V: StableDeref> FrozenBTreeMap<K, V> {
+ // these should never return &K or &V
+ // these should never delete any entries
+ pub fn insert(&self, k: K, v: V) -> &V::Target {
+ assert!(!self.in_use.get());
+ self.in_use.set(true);
+ let ret = unsafe {
+ let map = self.map.get();
+ &*(*map).entry(k).or_insert(v)
+ };
+ self.in_use.set(false);
+ ret
+ }
+
+ /// Returns a reference to the value corresponding to the key.
+ ///
+ /// The key may be any borrowed form of the map's key type, but
+ /// [`Hash`] and [`Eq`] on the borrowed form *must* match those for
+ /// the key type.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use elsa::FrozenBTreeMap;
+ ///
+ /// let map = FrozenBTreeMap::new();
+ /// map.insert(1, Box::new("a"));
+ /// assert_eq!(map.get(&1), Some(&"a"));
+ /// assert_eq!(map.get(&2), None);
+ /// ```
+ pub fn get<Q: ?Sized>(&self, k: &Q) -> Option<&V::Target>
+ where
+ K: Borrow<Q>,
+ Q: Ord,
+ {
+ assert!(!self.in_use.get());
+ self.in_use.set(true);
+ let ret = unsafe {
+ let map = self.map.get();
+ (*map).get(k).map(|x| &**x)
+ };
+ self.in_use.set(false);
+ ret
+ }
+
+ /// Applies a function to the owner of the value corresponding to the key (if any).
+ ///
+ /// The key may be any borrowed form of the map's key type, but
+ /// [`Hash`] and [`Eq`] on the borrowed form *must* match those for
+ /// the key type.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use elsa::FrozenBTreeMap;
+ ///
+ /// let map = FrozenBTreeMap::new();
+ /// map.insert(1, Box::new("a"));
+ /// assert_eq!(map.map_get(&1, Clone::clone), Some(Box::new("a")));
+ /// assert_eq!(map.map_get(&2, Clone::clone), None);
+ /// ```
+ pub fn map_get<Q: ?Sized, T, F>(&self, k: &Q, f: F) -> Option<T>
+ where
+ K: Borrow<Q>,
+ Q: Ord,
+ F: FnOnce(&V) -> T,
+ {
+ assert!(!self.in_use.get());
+ self.in_use.set(true);
+ let ret = unsafe {
+ let map = self.map.get();
+ (*map).get(k).map(f)
+ };
+ self.in_use.set(false);
+ ret
+ }
+
+ pub fn into_map(self) -> BTreeMap<K, V> {
+ self.map.into_inner()
+ }
+
+ // TODO add more
+}
+
+impl<K, V> std::convert::AsMut<BTreeMap<K, V>> for FrozenBTreeMap<K, V> {
+ /// Get mutable access to the underlying [`HashMap`].
+ ///
+ /// This is safe, as it requires a `&mut self`, ensuring nothing is using
+ /// the 'frozen' contents.
+ fn as_mut(&mut self) -> &mut BTreeMap<K, V> {
+ unsafe { &mut *self.map.get() }
+ }
+}
+
+impl<K: Clone + Ord, V: StableDeref> From<BTreeMap<K, V>> for FrozenBTreeMap<K, V> {
+ fn from(map: BTreeMap<K, V>) -> Self {
+ Self {
+ map: UnsafeCell::new(map),
+ in_use: Cell::new(false),
+ }
+ }
+}
+
+impl<Q: ?Sized, K, V> Index<&Q> for FrozenBTreeMap<K, V>
+where
+ Q: Ord,
+ K: Clone + Ord + Borrow<Q>,
+ V: StableDeref,
+{
+ type Output = V::Target;
+
+ /// # Examples
+ ///
+ /// ```
+ /// use elsa::FrozenBTreeMap;
+ ///
+ /// let map = FrozenBTreeMap::new();
+ /// map.insert(1, Box::new("a"));
+ /// assert_eq!(map[&1], "a");
+ /// ```
+ fn index(&self, idx: &Q) -> &V::Target {
+ self.get(idx)
+ .expect("attempted to index FrozenBTreeMap with unknown key")
+ }
+}
+
+impl<K: Clone + Ord, V: StableDeref> FromIterator<(K, V)> for FrozenBTreeMap<K, V> {
+ fn from_iter<T>(iter: T) -> Self
+ where
+ T: IntoIterator<Item = (K, V)>,
+ {
+ let map: BTreeMap<_, _> = iter.into_iter().collect();
+ map.into()
+ }
+}
+
+impl<K: Clone + Ord, V: StableDeref> Default for FrozenBTreeMap<K, V> {
+ fn default() -> Self {
+ Self {
+ map: UnsafeCell::new(Default::default()),
+ in_use: Cell::new(false),
+ }
+ }
+}
diff --git a/vendor/elsa/src/sync.rs b/vendor/elsa/src/sync.rs
new file mode 100644
index 000000000..afa4bb7c7
--- /dev/null
+++ b/vendor/elsa/src/sync.rs
@@ -0,0 +1,624 @@
+//! **This module is experimental**
+//!
+//! This module provides threadsafe versions of FrozenMap and FrozenVec,
+//! ideal for use as a cache.
+//!
+//! These lock internally, however locks only last as long as the method calls
+//!
+
+use stable_deref_trait::StableDeref;
+use std::alloc::Layout;
+use std::borrow::Borrow;
+use std::collections::BTreeMap;
+use std::collections::HashMap;
+use std::hash::Hash;
+use std::iter::{FromIterator, IntoIterator};
+use std::mem::MaybeUninit;
+use std::ops::Index;
+
+use std::sync::atomic::AtomicPtr;
+use std::sync::atomic::AtomicUsize;
+use std::sync::atomic::Ordering;
+use std::sync::RwLock;
+
+/// Append-only threadsafe version of `std::collections::HashMap` where
+/// insertion does not require mutable access
+pub struct FrozenMap<K, V> {
+ map: RwLock<HashMap<K, V>>,
+}
+
+impl<K, V> Default for FrozenMap<K, V> {
+ fn default() -> Self {
+ Self {
+ map: Default::default(),
+ }
+ }
+}
+
+impl<K: Eq + Hash, V: StableDeref> FrozenMap<K, V> {
+ // these should never return &K or &V
+ // these should never delete any entries
+
+ pub fn new() -> Self {
+ Self::default()
+ }
+
+ /// If the key exists in the map, returns a reference
+ /// to the corresponding value, otherwise inserts a
+ /// new entry in the map for that key and returns a
+ /// reference to the given value.
+ ///
+ /// Existing values are never overwritten.
+ ///
+ /// The key may be any borrowed form of the map's key type, but
+ /// [`Hash`] and [`Eq`] on the borrowed form *must* match those for
+ /// the key type.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use elsa::sync::FrozenMap;
+ ///
+ /// let map = FrozenMap::new();
+ /// assert_eq!(map.insert(1, Box::new("a")), &"a");
+ /// assert_eq!(map.insert(1, Box::new("b")), &"a");
+ /// ```
+ pub fn insert(&self, k: K, v: V) -> &V::Target {
+ let mut map = self.map.write().unwrap();
+ let ret = unsafe {
+ let inserted = &**map.entry(k).or_insert(v);
+ &*(inserted as *const _)
+ };
+ ret
+ }
+
+ /// If the key exists in the map, returns a reference to the corresponding
+ /// value, otherwise inserts a new entry in the map for that key and the
+ /// value returned by the creation function, and returns a reference to the
+ /// generated value.
+ ///
+ /// Existing values are never overwritten.
+ ///
+ /// The key may be any borrowed form of the map's key type, but [`Hash`] and
+ /// [`Eq`] on the borrowed form *must* match those for the key type.
+ ///
+ /// **Note** that the write lock is held for the duration of this function’s
+ /// execution, even while the value creation function is executing (if
+ /// needed). This will block any concurrent `get` or `insert` calls.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use elsa::sync::FrozenMap;
+ ///
+ /// let map = FrozenMap::new();
+ /// assert_eq!(map.insert_with(1, || Box::new("a")), &"a");
+ /// assert_eq!(map.insert_with(1, || unreachable!()), &"a");
+ /// ```
+ pub fn insert_with(&self, k: K, f: impl FnOnce() -> V) -> &V::Target {
+ let mut map = self.map.write().unwrap();
+ let ret = unsafe {
+ let inserted = &**map.entry(k).or_insert_with(f);
+ &*(inserted as *const _)
+ };
+ ret
+ }
+
+ /// If the key exists in the map, returns a reference to the corresponding
+ /// value, otherwise inserts a new entry in the map for that key and the
+ /// value returned by the creation function, and returns a reference to the
+ /// generated value.
+ ///
+ /// Existing values are never overwritten.
+ ///
+ /// The key may be any borrowed form of the map's key type, but [`Hash`] and
+ /// [`Eq`] on the borrowed form *must* match those for the key type.
+ ///
+ /// **Note** that the write lock is held for the duration of this function’s
+ /// execution, even while the value creation function is executing (if
+ /// needed). This will block any concurrent `get` or `insert` calls.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use elsa::sync::FrozenMap;
+ ///
+ /// let map = FrozenMap::new();
+ /// assert_eq!(map.insert_with_key(1, |_| Box::new("a")), &"a");
+ /// assert_eq!(map.insert_with_key(1, |_| unreachable!()), &"a");
+ /// ```
+ pub fn insert_with_key(&self, k: K, f: impl FnOnce(&K) -> V) -> &V::Target {
+ let mut map = self.map.write().unwrap();
+ let ret = unsafe {
+ let inserted = &**map.entry(k).or_insert_with_key(f);
+ &*(inserted as *const _)
+ };
+ ret
+ }
+
+ /// Returns a reference to the value corresponding to the key.
+ ///
+ /// The key may be any borrowed form of the map's key type, but
+ /// [`Hash`] and [`Eq`] on the borrowed form *must* match those for
+ /// the key type.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use elsa::sync::FrozenMap;
+ ///
+ /// let map = FrozenMap::new();
+ /// map.insert(1, Box::new("a"));
+ /// assert_eq!(map.get(&1), Some(&"a"));
+ /// assert_eq!(map.get(&2), None);
+ /// ```
+ pub fn get<Q: ?Sized>(&self, k: &Q) -> Option<&V::Target>
+ where
+ K: Borrow<Q>,
+ Q: Hash + Eq,
+ {
+ let map = self.map.read().unwrap();
+ let ret = unsafe { map.get(k).map(|x| &*(&**x as *const V::Target)) };
+ ret
+ }
+
+ /// Applies a function to the owner of the value corresponding to the key (if any).
+ ///
+ /// The key may be any borrowed form of the map's key type, but
+ /// [`Hash`] and [`Eq`] on the borrowed form *must* match those for
+ /// the key type.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use elsa::sync::FrozenMap;
+ ///
+ /// let map = FrozenMap::new();
+ /// map.insert(1, Box::new("a"));
+ /// assert_eq!(map.map_get(&1, Clone::clone), Some(Box::new("a")));
+ /// assert_eq!(map.map_get(&2, Clone::clone), None);
+ /// ```
+ pub fn map_get<Q: ?Sized, T, F>(&self, k: &Q, f: F) -> Option<T>
+ where
+ K: Borrow<Q>,
+ Q: Hash + Eq,
+ F: FnOnce(&V) -> T,
+ {
+ let map = self.map.read().unwrap();
+ let ret = map.get(k).map(f);
+ ret
+ }
+
+ /// # Examples
+ ///
+ /// ```
+ /// use elsa::sync::FrozenMap;
+ ///
+ /// let map = FrozenMap::new();
+ /// assert_eq!(map.len(), 0);
+ /// map.insert(1, Box::new("a"));
+ /// assert_eq!(map.len(), 1);
+ /// ```
+ pub fn len(&self) -> usize {
+ let map = self.map.read().unwrap();
+ map.len()
+ }
+
+ /// # Examples
+ ///
+ /// ```
+ /// use elsa::sync::FrozenMap;
+ ///
+ /// let map = FrozenMap::new();
+ /// assert_eq!(map.is_empty(), true);
+ /// map.insert(1, Box::new("a"));
+ /// assert_eq!(map.is_empty(), false);
+ /// ```
+ pub fn is_empty(&self) -> bool {
+ let map = self.map.read().unwrap();
+ map.is_empty()
+ }
+
+ // TODO add more
+}
+
+/// Append-only threadsafe version of `std::vec::Vec` where
+/// insertion does not require mutable access
+pub struct FrozenVec<T> {
+ vec: RwLock<Vec<T>>,
+}
+
+impl<T> Default for FrozenVec<T> {
+ fn default() -> Self {
+ Self {
+ vec: Default::default(),
+ }
+ }
+}
+
+impl<T: StableDeref> FrozenVec<T> {
+ pub fn new() -> Self {
+ Default::default()
+ }
+
+ // these should never return &T
+ // these should never delete any entries
+
+ pub fn push(&self, val: T) {
+ let mut vec = self.vec.write().unwrap();
+ vec.push(val);
+ }
+
+ /// Push, immediately getting a reference to the element
+ pub fn push_get(&self, val: T) -> &T::Target {
+ let mut vec = self.vec.write().unwrap();
+ vec.push(val);
+ unsafe { &*(&**vec.get_unchecked(vec.len() - 1) as *const T::Target) }
+ }
+
+ /// Push, immediately getting a an index of the element
+ ///
+ /// Index can then be used with the `get` method
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use elsa::sync::FrozenVec;
+ ///
+ /// let map = FrozenVec::new();
+ /// let idx = map.push_get_index(String::from("a"));
+ /// assert_eq!(map.get(idx), Some("a"));
+ /// assert_eq!(idx, 0);
+ /// assert_eq!(map.push_get_index(String::from("b")), 1);
+ /// ```
+ pub fn push_get_index(&self, val: T) -> usize {
+ let mut vec = self.vec.write().unwrap();
+ let index = vec.len();
+ vec.push(val);
+ return index;
+ }
+
+ pub fn get(&self, index: usize) -> Option<&T::Target> {
+ let vec = self.vec.read().unwrap();
+ unsafe { vec.get(index).map(|x| &*(&**x as *const T::Target)) }
+ }
+
+ // TODO add more
+}
+
+/// Append-only threadsafe version of `std::vec::Vec` where
+/// insertion does not require mutable access.
+/// Does not have locks, only allows `Copy` types and will
+/// spinlock on contention. The spinlocks are really rare as
+/// they only happen on reallocation due to a push going over
+/// the capacity.
+pub struct LockFreeFrozenVec<T: Copy> {
+ data: AtomicPtr<T>,
+ len: AtomicUsize,
+ cap: AtomicUsize,
+}
+
+impl<T: Copy> Drop for LockFreeFrozenVec<T> {
+ fn drop(&mut self) {
+ let cap = *self.cap.get_mut();
+ let layout = self.layout(cap);
+ unsafe {
+ std::alloc::dealloc((*self.data.get_mut()).cast(), layout);
+ }
+ }
+}
+
+impl<T: Copy> Default for LockFreeFrozenVec<T> {
+ fn default() -> Self {
+ Self {
+ // FIXME: use `std::ptr::invalid_mut()` once that is stable.
+ data: AtomicPtr::new(std::mem::align_of::<T>() as *mut T),
+ len: AtomicUsize::new(0),
+ cap: AtomicUsize::new(0),
+ }
+ }
+}
+
+impl<T: Copy> LockFreeFrozenVec<T> {
+ pub fn new() -> Self {
+ Default::default()
+ }
+
+ pub fn with_capacity(cap: usize) -> Self {
+ Self {
+ data: AtomicPtr::new(
+ Box::into_raw(vec![MaybeUninit::<T>::uninit(); cap].into_boxed_slice()).cast(),
+ ),
+ len: AtomicUsize::new(0),
+ cap: AtomicUsize::new(cap),
+ }
+ }
+
+ fn lock<U>(&self, f: impl FnOnce(&mut *mut T) -> U) -> U {
+ let mut ptr;
+ loop {
+ ptr = self.data.swap(std::ptr::null_mut(), Ordering::Acquire);
+ if !ptr.is_null() {
+ // Wheeeee spinlock
+ break;
+ }
+ }
+
+ let ret = f(&mut ptr);
+ self.data.store(ptr, Ordering::Release);
+ ret
+ }
+
+ fn layout(&self, cap: usize) -> Layout {
+ let num_bytes = std::mem::size_of::<T>() * cap;
+ let align = std::mem::align_of::<T>();
+ Layout::from_size_align(num_bytes, align).unwrap()
+ }
+
+ // these should never return &T
+ // these should never delete any entries
+
+ const NOT_ZST: () = if std::mem::size_of::<T>() == 0 {
+ panic!("`LockFreeFrozenVec` cannot be used with ZSTs");
+ };
+
+ pub fn push(&self, val: T) -> usize {
+ // This statement actually does something: it evaluates a constant.
+ #[allow(path_statements)]
+ {
+ Self::NOT_ZST
+ }
+ self.lock(|ptr| {
+ // These values must be consistent with the pointer we got.
+ let len = self.len.load(Ordering::Acquire);
+ let cap = self.cap.load(Ordering::Acquire);
+ if len >= cap {
+ if cap == 0 {
+ // No memory allocated yet
+ let layout = self.layout(128);
+ // SAFETY: `LockFreeFrozenVec` statically rejects zsts
+ unsafe {
+ *ptr = std::alloc::alloc(layout).cast::<T>();
+ }
+ // This is written before the end of the `lock` closure, so no one will observe this
+ // until the data pointer has been updated anyway.
+ self.cap.store(128, Ordering::Release);
+ } else {
+ // Out of memory, realloc with double the capacity
+ let layout = self.layout(cap);
+ let new_size = layout.size() * 2;
+ // SAFETY: `LockFreeFrozenVec` statically rejects zsts and the input `ptr` has always been
+ // allocated at the size stated in `cap`.
+ unsafe {
+ *ptr = std::alloc::realloc((*ptr).cast(), layout, new_size).cast::<T>();
+ }
+ // This is written before the end of the `lock` closure, so no one will observe this
+ // until the data pointer has been updated anyway.
+ self.cap.store(cap * 2, Ordering::Release);
+ }
+ assert!(!ptr.is_null());
+ }
+ unsafe {
+ ptr.add(len).write(val);
+ }
+ // This is written before updating the data pointer. Other `push` calls cannot observe this,
+ // because they are blocked on aquiring the data pointer before they ever read the `len`.
+ // `get` may read the length before actually aquiring the data pointer lock, but that is fine,
+ // as once it is able to aquire the lock, there will be actually the right number of elements
+ // stored.
+ self.len.store(len + 1, Ordering::Release);
+ len
+ })
+ }
+
+ pub fn get(&self, index: usize) -> Option<T> {
+ // The length can only grow, so just doing the length check
+ // independently of the `lock` and read is fine. Worst case we
+ // read an old length value and end up returning `None` even if
+ // another thread already inserted the value.
+ let len = self.len.load(Ordering::Relaxed);
+ if index >= len {
+ return None;
+ }
+ self.lock(|ptr| Some(unsafe { ptr.add(index).read() }))
+ }
+}
+
+#[test]
+fn test_non_lockfree() {
+ #[derive(Copy, Clone, Debug, PartialEq, Eq)]
+ struct Moo(i32);
+
+ for vec in [
+ LockFreeFrozenVec::new(),
+ LockFreeFrozenVec::with_capacity(1),
+ LockFreeFrozenVec::with_capacity(2),
+ LockFreeFrozenVec::with_capacity(1000),
+ ] {
+ assert_eq!(vec.get(1), None);
+
+ vec.push(Moo(1));
+ let i = vec.push(Moo(2));
+ vec.push(Moo(3));
+
+ assert_eq!(vec.get(i), Some(Moo(2)));
+
+ std::thread::scope(|s| {
+ s.spawn(|| {
+ for i in 0..1000 {
+ vec.push(Moo(i));
+ }
+ });
+ s.spawn(|| {
+ for i in 0..1000 {
+ vec.push(Moo(i));
+ }
+ });
+ for i in 0..2000 {
+ while vec.get(i).is_none() {}
+ }
+ });
+ }
+}
+
+/// Append-only threadsafe version of `std::collections::BTreeMap` where
+/// insertion does not require mutable access
+#[derive(Debug)]
+pub struct FrozenBTreeMap<K, V>(RwLock<BTreeMap<K, V>>);
+
+impl<K: Clone + Ord, V: StableDeref> FrozenBTreeMap<K, V> {
+ pub fn new() -> Self {
+ Self(RwLock::new(BTreeMap::new()))
+ }
+
+ // these should never return &K or &V
+ // these should never delete any entries
+
+ /// Returns a reference to the value corresponding to the key.
+ ///
+ /// The key may be any borrowed form of the map's key type, but
+ /// [`Ord`] on the borrowed form *must* match those for
+ /// the key type.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use elsa::sync::FrozenBTreeMap;
+ ///
+ /// let map = FrozenBTreeMap::new();
+ /// map.insert(1, Box::new("a"));
+ /// assert_eq!(map.get(&1), Some(&"a"));
+ /// assert_eq!(map.get(&2), None);
+ /// ```
+ pub fn get<Q: ?Sized>(&self, k: &Q) -> Option<&V::Target>
+ where
+ K: Borrow<Q>,
+ Q: Ord,
+ {
+ let map = self.0.read().unwrap();
+ let ret = unsafe { map.get(k).map(|x| &*(&**x as *const V::Target)) };
+ ret
+ }
+
+ /// Insert a new value into the map. Does nothing if the key is already occupied.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use elsa::sync::FrozenBTreeMap;
+ ///
+ /// let map = FrozenBTreeMap::new();
+ /// map.insert(1, Box::new("a"));
+ /// assert_eq!(map.get(&1), Some(&"a"));
+ /// ```
+ pub fn insert(&self, k: K, v: V) -> &V::Target {
+ let mut map = self.0.write().unwrap();
+ let ret = unsafe {
+ let inserted = &**map.entry(k).or_insert(v);
+ &*(inserted as *const _)
+ };
+ ret
+ }
+
+ /// Applies a function to the owner of the value corresponding to the key (if any).
+ ///
+ /// The key may be any borrowed form of the map's key type, but
+ /// [`Ord`] on the borrowed form *must* match those for
+ /// the key type.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use elsa::sync::FrozenBTreeMap;
+ ///
+ /// let map = FrozenBTreeMap::new();
+ /// map.insert(1, Box::new("a"));
+ /// assert_eq!(map.map_get(&1, Clone::clone), Some(Box::new("a")));
+ /// assert_eq!(map.map_get(&2, Clone::clone), None);
+ /// ```
+ pub fn map_get<Q: ?Sized, T, F>(&self, k: &Q, f: F) -> Option<T>
+ where
+ K: Borrow<Q>,
+ Q: Ord,
+ F: FnOnce(&V) -> T,
+ {
+ let map = self.0.read().unwrap();
+ let ret = map.get(k).map(f);
+ ret
+ }
+
+ /// # Examples
+ ///
+ /// ```
+ /// use elsa::sync::FrozenBTreeMap;
+ ///
+ /// let map = FrozenBTreeMap::new();
+ /// assert_eq!(map.len(), 0);
+ /// map.insert(1, Box::new("a"));
+ /// assert_eq!(map.len(), 1);
+ /// ```
+ pub fn len(&self) -> usize {
+ let map = self.0.read().unwrap();
+ map.len()
+ }
+
+ /// # Examples
+ ///
+ /// ```
+ /// use elsa::sync::FrozenBTreeMap;
+ ///
+ /// let map = FrozenBTreeMap::new();
+ /// assert_eq!(map.is_empty(), true);
+ /// map.insert(1, Box::new("a"));
+ /// assert_eq!(map.is_empty(), false);
+ /// ```
+ pub fn is_empty(&self) -> bool {
+ let map = self.0.read().unwrap();
+ map.is_empty()
+ }
+}
+
+impl<K: Clone + Ord, V: StableDeref> From<BTreeMap<K, V>> for FrozenBTreeMap<K, V> {
+ fn from(map: BTreeMap<K, V>) -> Self {
+ Self(RwLock::new(map))
+ }
+}
+
+impl<Q: ?Sized, K, V> Index<&Q> for FrozenBTreeMap<K, V>
+where
+ Q: Ord,
+ K: Clone + Ord + Borrow<Q>,
+ V: StableDeref,
+{
+ type Output = V::Target;
+
+ /// # Examples
+ ///
+ /// ```
+ /// use elsa::sync::FrozenBTreeMap;
+ ///
+ /// let map = FrozenBTreeMap::new();
+ /// map.insert(1, Box::new("a"));
+ /// assert_eq!(map[&1], "a");
+ /// ```
+ fn index(&self, idx: &Q) -> &V::Target {
+ self.get(idx)
+ .expect("attempted to index FrozenBTreeMap with unknown key")
+ }
+}
+
+impl<K: Clone + Ord, V: StableDeref> FromIterator<(K, V)> for FrozenBTreeMap<K, V> {
+ fn from_iter<T>(iter: T) -> Self
+ where
+ T: IntoIterator<Item = (K, V)>,
+ {
+ let map: BTreeMap<_, _> = iter.into_iter().collect();
+ map.into()
+ }
+}
+
+impl<K: Clone + Ord, V: StableDeref> Default for FrozenBTreeMap<K, V> {
+ fn default() -> Self {
+ Self::new()
+ }
+}
diff --git a/vendor/elsa/src/vec.rs b/vendor/elsa/src/vec.rs
new file mode 100644
index 000000000..33b6e6a50
--- /dev/null
+++ b/vendor/elsa/src/vec.rs
@@ -0,0 +1,347 @@
+use std::cell::UnsafeCell;
+use std::cmp::Ordering;
+use std::iter::FromIterator;
+use std::ops::Index;
+
+use stable_deref_trait::StableDeref;
+
+/// Append-only version of `std::vec::Vec` where
+/// insertion does not require mutable access
+pub struct FrozenVec<T> {
+ vec: UnsafeCell<Vec<T>>,
+ // XXXManishearth do we need a reentrancy guard here as well?
+ // StableDeref may not guarantee that there are no side effects
+}
+
+// safety: UnsafeCell implies !Sync
+
+impl<T> FrozenVec<T> {
+ /// Constructs a new, empty vector.
+ pub fn new() -> Self {
+ Self {
+ vec: UnsafeCell::new(Default::default()),
+ }
+ }
+}
+
+impl<T> FrozenVec<T> {
+ // these should never return &T
+ // these should never delete any entries
+
+ /// Appends an element to the back of the vector.
+ pub fn push(&self, val: T) {
+ unsafe {
+ let vec = self.vec.get();
+ (*vec).push(val)
+ }
+ }
+}
+
+impl<T: StableDeref> FrozenVec<T> {
+ /// Push, immediately getting a reference to the element
+ pub fn push_get(&self, val: T) -> &T::Target {
+ unsafe {
+ let vec = self.vec.get();
+ (*vec).push(val);
+ &*(&**(*vec).get_unchecked((*vec).len() - 1) as *const T::Target)
+ }
+ }
+
+ /// Returns a reference to an element.
+ pub fn get(&self, index: usize) -> Option<&T::Target> {
+ unsafe {
+ let vec = self.vec.get();
+ (*vec).get(index).map(|x| &**x)
+ }
+ }
+
+ /// Returns a reference to an element, without doing bounds checking.
+ ///
+ /// ## Safety
+ ///
+ /// `index` must be in bounds, i.e. it must be less than `self.len()`
+ pub unsafe fn get_unchecked(&self, index: usize) -> &T::Target {
+ let vec = self.vec.get();
+ &**(*vec).get_unchecked(index)
+ }
+}
+
+impl<T: Copy> FrozenVec<T> {
+ /// Returns a copy of an element.
+ pub fn get_copy(&self, index: usize) -> Option<T> {
+ unsafe {
+ let vec = self.vec.get();
+ (*vec).get(index).copied()
+ }
+ }
+}
+
+impl<T> FrozenVec<T> {
+ /// Returns the number of elements in the vector.
+ pub fn len(&self) -> usize {
+ unsafe {
+ let vec = self.vec.get();
+ (*vec).len()
+ }
+ }
+
+ /// Returns `true` if the vector contains no elements.
+ pub fn is_empty(&self) -> bool {
+ self.len() == 0
+ }
+}
+
+impl<T: StableDeref> FrozenVec<T> {
+ /// Returns the first element of the vector, or `None` if empty.
+ pub fn first(&self) -> Option<&T::Target> {
+ unsafe {
+ let vec = self.vec.get();
+ (*vec).first().map(|x| &**x)
+ }
+ }
+
+ /// Returns the last element of the vector, or `None` if empty.
+ pub fn last(&self) -> Option<&T::Target> {
+ unsafe {
+ let vec = self.vec.get();
+ (*vec).last().map(|x| &**x)
+ }
+ }
+ /// Returns an iterator over the vector.
+ pub fn iter(&self) -> Iter<T> {
+ self.into_iter()
+ }
+}
+
+impl<T: StableDeref> FrozenVec<T> {
+ /// Converts the frozen vector into a plain vector.
+ pub fn into_vec(self) -> Vec<T> {
+ self.vec.into_inner()
+ }
+}
+
+impl<T: StableDeref> FrozenVec<T> {
+ // binary search functions: they need to be reimplemented here to be safe (instead of calling
+ // their equivalents directly on the underlying Vec), as they run user callbacks that could
+ // reentrantly call other functions on this vector
+
+ /// Binary searches this sorted vector for a given element, analogous to [slice::binary_search].
+ pub fn binary_search(&self, x: &T::Target) -> Result<usize, usize>
+ where
+ T::Target: Ord,
+ {
+ self.binary_search_by(|p| p.cmp(x))
+ }
+
+ /// Binary searches this sorted vector with a comparator function, analogous to
+ /// [slice::binary_search_by].
+ pub fn binary_search_by<'a, F>(&'a self, mut f: F) -> Result<usize, usize>
+ where
+ F: FnMut(&'a T::Target) -> Ordering,
+ {
+ let mut size = self.len();
+ let mut left = 0;
+ let mut right = size;
+ while left < right {
+ let mid = left + size / 2;
+
+ // safety: like the core algorithm, mid is always within original vector len; in
+ // pathlogical cases, user could push to the vector in the meantime, but this can only
+ // increase the length, keeping this safe
+ let cmp = f(unsafe { self.get_unchecked(mid) });
+
+ if cmp == Ordering::Less {
+ left = mid + 1;
+ } else if cmp == Ordering::Greater {
+ right = mid;
+ } else {
+ return Ok(mid);
+ }
+
+ size = right - left;
+ }
+ Err(left)
+ }
+
+ /// Binary searches this sorted vector with a key extraction function, analogous to
+ /// [slice::binary_search_by_key].
+ pub fn binary_search_by_key<'a, B, F>(&'a self, b: &B, mut f: F) -> Result<usize, usize>
+ where
+ F: FnMut(&'a T::Target) -> B,
+ B: Ord,
+ {
+ self.binary_search_by(|k| f(k).cmp(b))
+ }
+
+ /// Returns the index of the partition point according to the given predicate
+ /// (the index of the first element of the second partition), analogous to
+ /// [slice::partition_point].
+ pub fn partition_point<P>(&self, mut pred: P) -> usize
+ where
+ P: FnMut(&T::Target) -> bool,
+ {
+ let mut left = 0;
+ let mut right = self.len();
+
+ while left != right {
+ let mid = left + (right - left) / 2;
+ // safety: like in binary_search_by
+ let value = unsafe { self.get_unchecked(mid) };
+ if pred(value) {
+ left = mid + 1;
+ } else {
+ right = mid;
+ }
+ }
+
+ left
+ }
+
+ // TODO add more
+}
+
+impl<T> std::convert::AsMut<Vec<T>> for FrozenVec<T> {
+ /// Get mutable access to the underlying vector.
+ ///
+ /// This is safe, as it requires a `&mut self`, ensuring nothing is using
+ /// the 'frozen' contents.
+ fn as_mut(&mut self) -> &mut Vec<T> {
+ unsafe { &mut *self.vec.get() }
+ }
+}
+
+impl<T> Default for FrozenVec<T> {
+ fn default() -> Self {
+ FrozenVec::new()
+ }
+}
+
+impl<T> From<Vec<T>> for FrozenVec<T> {
+ fn from(vec: Vec<T>) -> Self {
+ Self {
+ vec: UnsafeCell::new(vec),
+ }
+ }
+}
+
+impl<T: StableDeref> Index<usize> for FrozenVec<T> {
+ type Output = T::Target;
+ fn index(&self, idx: usize) -> &T::Target {
+ self.get(idx).unwrap_or_else(|| {
+ panic!(
+ "index out of bounds: the len is {} but the index is {}",
+ self.len(),
+ idx
+ )
+ })
+ }
+}
+
+impl<A> FromIterator<A> for FrozenVec<A> {
+ fn from_iter<T>(iter: T) -> Self
+ where
+ T: IntoIterator<Item = A>,
+ {
+ let vec: Vec<_> = iter.into_iter().collect();
+ vec.into()
+ }
+}
+
+/// Iterator over FrozenVec, obtained via `.iter()`
+///
+/// It is safe to push to the vector during iteration
+pub struct Iter<'a, T> {
+ vec: &'a FrozenVec<T>,
+ idx: usize,
+}
+
+impl<'a, T: StableDeref> Iterator for Iter<'a, T> {
+ type Item = &'a T::Target;
+ fn next(&mut self) -> Option<&'a T::Target> {
+ if let Some(ret) = self.vec.get(self.idx) {
+ self.idx += 1;
+ Some(ret)
+ } else {
+ None
+ }
+ }
+}
+
+impl<'a, T: StableDeref> IntoIterator for &'a FrozenVec<T> {
+ type Item = &'a T::Target;
+ type IntoIter = Iter<'a, T>;
+ fn into_iter(self) -> Iter<'a, T> {
+ Iter { vec: self, idx: 0 }
+ }
+}
+
+#[test]
+fn test_iteration() {
+ let vec = vec!["a", "b", "c", "d"];
+ let frozen: FrozenVec<_> = vec.clone().into();
+
+ assert_eq!(vec, frozen.iter().collect::<Vec<_>>());
+ for (e1, e2) in vec.iter().zip(frozen.iter()) {
+ assert_eq!(*e1, e2);
+ }
+
+ assert_eq!(vec.len(), frozen.iter().count())
+}
+
+#[test]
+fn test_accessors() {
+ let vec: FrozenVec<String> = FrozenVec::new();
+
+ assert_eq!(vec.is_empty(), true);
+ assert_eq!(vec.len(), 0);
+ assert_eq!(vec.first(), None);
+ assert_eq!(vec.last(), None);
+ assert_eq!(vec.get(1), None);
+
+ vec.push("a".to_string());
+ vec.push("b".to_string());
+ vec.push("c".to_string());
+
+ assert_eq!(vec.is_empty(), false);
+ assert_eq!(vec.len(), 3);
+ assert_eq!(vec.first(), Some("a"));
+ assert_eq!(vec.last(), Some("c"));
+ assert_eq!(vec.get(1), Some("b"));
+}
+
+#[test]
+fn test_non_stable_deref() {
+ #[derive(Copy, Clone, Debug, PartialEq, Eq)]
+ struct Moo(i32);
+ let vec: FrozenVec<Moo> = FrozenVec::new();
+
+ assert_eq!(vec.is_empty(), true);
+ assert_eq!(vec.len(), 0);
+ assert_eq!(vec.get_copy(1), None);
+
+ vec.push(Moo(1));
+ vec.push(Moo(2));
+ vec.push(Moo(3));
+
+ assert_eq!(vec.is_empty(), false);
+ assert_eq!(vec.len(), 3);
+ assert_eq!(vec.get_copy(1), Some(Moo(2)));
+}
+
+#[test]
+fn test_binary_search() {
+ let vec: FrozenVec<_> = vec!["ab", "cde", "fghij"].into();
+
+ assert_eq!(vec.binary_search("cde"), Ok(1));
+ assert_eq!(vec.binary_search("cdf"), Err(2));
+ assert_eq!(vec.binary_search("a"), Err(0));
+ assert_eq!(vec.binary_search("g"), Err(3));
+
+ assert_eq!(vec.binary_search_by_key(&1, |x| x.len()), Err(0));
+ assert_eq!(vec.binary_search_by_key(&3, |x| x.len()), Ok(1));
+ assert_eq!(vec.binary_search_by_key(&4, |x| x.len()), Err(2));
+
+ assert_eq!(vec.partition_point(|x| x.len() < 4), 2);
+ assert_eq!(vec.partition_point(|_| false), 0);
+ assert_eq!(vec.partition_point(|_| true), 3);
+}
diff --git a/vendor/ena/.cargo-checksum.json b/vendor/ena/.cargo-checksum.json
index 246be2f1d..cce0ccf73 100644
--- a/vendor/ena/.cargo-checksum.json
+++ b/vendor/ena/.cargo-checksum.json
@@ -1 +1 @@
-{"files":{"Cargo.toml":"9cc278873c11103275c22c025d2170754767dc30ae109ddafd60b881b7d5a64b","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"0621878e61f0d0fda054bcbe02df75192c28bde1ecc8289cbd86aeba2dd72720","README.md":"c623c5a776782edc92b00e4934bd50b7754a861dc6cad02ee4c2a87f946a542f","measurements.txt":"b209f98f2bc696904a48829e86952f4f09b59e4e685f7c12087c59d05ed31829","src/bitvec.rs":"c6c66c348776ff480b7ff6e4a3e0f64554a4194266f614408b45b5e3c324ec0a","src/lib.rs":"9b94637cb53e882625d3fb714acac37bb5fe7762d2a583ad4fd43f276f849214","src/snapshot_vec.rs":"b9fce507e3eece42c742405aea870562f99fdea3a4e30a122cea64ef5634f197","src/undo_log.rs":"5c94971d95ae1dd2de04eae2ea1ec5b99c627fbe92b2ea40a4fa3c37d340e7b8","src/unify/backing_vec.rs":"97cc2cec917ad87bb59b9f08ab3e081758ab5632d4a2e35621ba68c175ab10e5","src/unify/mod.rs":"bffe4e412b7624cf67efb64e75ecb3f537050080c8aefa69e354c2d774906976","src/unify/tests.rs":"6ffe2de338f1c8014292fdc7e764451c7af3de344fd405a46b818447304bdd23","tests/external_undo_log.rs":"215645f44d90b22b6ff07f72157b285e9cc277b856c31a0b82526b1534bef240"},"package":"d7402b94a93c24e742487327a7cd839dc9d36fec9de9fb25b09f2dae459f36c3"} \ No newline at end of file
+{"files":{"Cargo.toml":"820aad545a6df3f8e1c17d0f4d3b9ad97b90c4d307dd7df17e4c375d378efcb2","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"0621878e61f0d0fda054bcbe02df75192c28bde1ecc8289cbd86aeba2dd72720","README.md":"1c15c9176a442a293a7fe046172e316f95b3acca6c01ee495162d4bc57e6841b","measurements.txt":"b209f98f2bc696904a48829e86952f4f09b59e4e685f7c12087c59d05ed31829","src/bitvec.rs":"c6c66c348776ff480b7ff6e4a3e0f64554a4194266f614408b45b5e3c324ec0a","src/lib.rs":"9b94637cb53e882625d3fb714acac37bb5fe7762d2a583ad4fd43f276f849214","src/snapshot_vec.rs":"b9fce507e3eece42c742405aea870562f99fdea3a4e30a122cea64ef5634f197","src/undo_log.rs":"5c94971d95ae1dd2de04eae2ea1ec5b99c627fbe92b2ea40a4fa3c37d340e7b8","src/unify/backing_vec.rs":"97cc2cec917ad87bb59b9f08ab3e081758ab5632d4a2e35621ba68c175ab10e5","src/unify/mod.rs":"986c502c11d0c921ef78916b0ccf17ffd18c5baf6e807be1295b237a2d3d87a1","src/unify/tests.rs":"6ffe2de338f1c8014292fdc7e764451c7af3de344fd405a46b818447304bdd23","tests/external_undo_log.rs":"215645f44d90b22b6ff07f72157b285e9cc277b856c31a0b82526b1534bef240"},"package":"b2e5d13ca2353ab7d0230988629def93914a8c4015f621f9b13ed2955614731d"} \ No newline at end of file
diff --git a/vendor/ena/Cargo.toml b/vendor/ena/Cargo.toml
index 620558398..d19260c80 100644
--- a/vendor/ena/Cargo.toml
+++ b/vendor/ena/Cargo.toml
@@ -3,23 +3,26 @@
# When uploading crates to the registry Cargo will automatically
# "normalize" Cargo.toml files for maximal compatibility
# with all versions of Cargo and also rewrite `path` dependencies
-# to registry (e.g., crates.io) dependencies
+# to registry (e.g., crates.io) dependencies.
#
-# If you believe there's an error in this file please file an
-# issue against the rust-lang/cargo repository. If you're
-# editing this file be aware that the upstream Cargo.toml
-# will likely look very different (and much more reasonable)
+# If you are reading this file be aware that the original Cargo.toml
+# will likely look very different (and much more reasonable).
+# See Cargo.toml.orig for the original contents.
[package]
name = "ena"
-version = "0.14.0"
+version = "0.14.1"
authors = ["Niko Matsakis <niko@alum.mit.edu>"]
description = "Union-find, congruence closure, and other unification code. Based on code from rustc."
-homepage = "https://github.com/rust-lang-nursery/ena"
+homepage = "https://github.com/rust-lang/ena"
readme = "README.md"
-keywords = ["unification", "union-find"]
-license = "MIT/Apache-2.0"
-repository = "https://github.com/rust-lang-nursery/ena"
+keywords = [
+ "unification",
+ "union-find",
+]
+license = "MIT OR Apache-2.0"
+repository = "https://github.com/rust-lang/ena"
+
[dependencies.dogged]
version = "0.2.0"
optional = true
diff --git a/vendor/ena/README.md b/vendor/ena/README.md
index afa6567c6..416598ba3 100644
--- a/vendor/ena/README.md
+++ b/vendor/ena/README.md
@@ -1,4 +1,4 @@
-[![Build Status](https://travis-ci.com/rust-lang-nursery/ena.svg?branch=master)](https://travis-ci.com/rust-lang-nursery/ena)
+[![Build Status](https://travis-ci.org/rust-lang/ena.svg?branch=master)](https://travis-ci.org/rust-lang/ena)
An implementation of union-find in Rust; extracted from (and used by)
rustc.
diff --git a/vendor/ena/src/unify/mod.rs b/vendor/ena/src/unify/mod.rs
index a26d699d8..5377177be 100644
--- a/vendor/ena/src/unify/mod.rs
+++ b/vendor/ena/src/unify/mod.rs
@@ -230,19 +230,8 @@ impl<K: UnifyKey> VarValue<K> {
self.rank = rank;
self.value = value;
}
-
- fn parent(&self, self_key: K) -> Option<K> {
- self.if_not_self(self.parent, self_key)
- }
-
- fn if_not_self(&self, key: K, self_key: K) -> Option<K> {
- if key == self_key {
- None
- } else {
- Some(key)
- }
- }
}
+
impl<K> UnificationTableStorage<K>
where
K: UnifyKey,
@@ -358,13 +347,12 @@ impl<S: UnificationStoreMut> UnificationTable<S> {
/// callsites. `uninlined_get_root_key` is the never-inlined version.
#[inline(always)]
fn inlined_get_root_key(&mut self, vid: S::Key) -> S::Key {
- let redirect = {
- match self.value(vid).parent(vid) {
- None => return vid,
- Some(redirect) => redirect,
- }
- };
+ let v = self.value(vid);
+ if v.parent == vid {
+ return vid;
+ }
+ let redirect = v.parent;
let root_key: S::Key = self.uninlined_get_root_key(redirect);
if root_key != redirect {
// Path compression
diff --git a/vendor/filetime/.cargo-checksum.json b/vendor/filetime/.cargo-checksum.json
index 8d7b7ce7d..7bc0e0ce1 100644
--- a/vendor/filetime/.cargo-checksum.json
+++ b/vendor/filetime/.cargo-checksum.json
@@ -1 +1 @@
-{"files":{"Cargo.toml":"c82074c47610281bf7c3de20e143b8795ac39543df6c52e86e96506f7747e93f","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"378f5840b258e2779c39418f3f2d7b2ba96f1c7917dd6be0713f88305dbda397","README.md":"6cd295d9f4efe412971b1855ecaf7b19ef3956006a652ea205c456a5d33550c1","src/lib.rs":"eec6b5e3be2c1d5e068a9724b503e729a1e11dae4cd1bc816110c94a0bc14fa0","src/redox.rs":"898997b73c20818cf4601a1f4bcdf1b7dbf3b5d9d071cdc9fce5d1652f6bfc43","src/unix/android.rs":"d929826a9a92003b7aaa6435adc220efbb70c15308f9eed5ee517d88451fcaf6","src/unix/linux.rs":"061f0f7bd7a41f29b9d24b6487e302d650e9399f0dcc54595211e20ae4945da6","src/unix/macos.rs":"1b19a24bee240aba8d564405991bb0ee36ba72217461c8ac6829144d28f7e046","src/unix/mod.rs":"d6a4ae02099c46874e13c9fe71103cdecc394467e6c443950d27488ce9ec927b","src/unix/utimensat.rs":"0876aa32393689fcb5eec913c5d34954956a715913d611749b04243a2dbcf897","src/unix/utimes.rs":"d2d8ca5daed3d1ec0a0aed1fc03450deb4b7f1fcdb96ed40b8d2cfefd0e827ee","src/wasm.rs":"a82734259846a3349d42da011c1065d21f3981bd20d6eb43495e34808b83af9a","src/windows.rs":"3314a0def8028d8f2a4bc01377d5874ab9ddf8684aad13573c89b427bf2d9911"},"package":"4b9663d381d07ae25dc88dbdf27df458faa83a9b25336bcac83d5e452b5fc9d3"} \ No newline at end of file
+{"files":{"Cargo.toml":"47fb14a283873b721e1cafb0b68f25c761b513927ee6e203426de090e2299251","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"378f5840b258e2779c39418f3f2d7b2ba96f1c7917dd6be0713f88305dbda397","README.md":"6cd295d9f4efe412971b1855ecaf7b19ef3956006a652ea205c456a5d33550c1","src/lib.rs":"eec6b5e3be2c1d5e068a9724b503e729a1e11dae4cd1bc816110c94a0bc14fa0","src/redox.rs":"898997b73c20818cf4601a1f4bcdf1b7dbf3b5d9d071cdc9fce5d1652f6bfc43","src/unix/android.rs":"d929826a9a92003b7aaa6435adc220efbb70c15308f9eed5ee517d88451fcaf6","src/unix/linux.rs":"648498bdf715766eeffdc2dff6a58db51cf6b244c431a6d53c33cbc73f1998d4","src/unix/macos.rs":"1b19a24bee240aba8d564405991bb0ee36ba72217461c8ac6829144d28f7e046","src/unix/mod.rs":"52512c922e1dbb47a6c7f0354c6198ca1ac61ea4d540bc0d73d3a3fd08908ba1","src/unix/utimensat.rs":"0876aa32393689fcb5eec913c5d34954956a715913d611749b04243a2dbcf897","src/unix/utimes.rs":"d2d8ca5daed3d1ec0a0aed1fc03450deb4b7f1fcdb96ed40b8d2cfefd0e827ee","src/wasm.rs":"a82734259846a3349d42da011c1065d21f3981bd20d6eb43495e34808b83af9a","src/windows.rs":"3314a0def8028d8f2a4bc01377d5874ab9ddf8684aad13573c89b427bf2d9911"},"package":"4e884668cd0c7480504233e951174ddc3b382f7c2666e3b7310b5c4e7b0c37f9"} \ No newline at end of file
diff --git a/vendor/filetime/Cargo.toml b/vendor/filetime/Cargo.toml
index ba219b3e5..2d41405ab 100644
--- a/vendor/filetime/Cargo.toml
+++ b/vendor/filetime/Cargo.toml
@@ -12,7 +12,7 @@
[package]
edition = "2018"
name = "filetime"
-version = "0.2.18"
+version = "0.2.19"
authors = ["Alex Crichton <alex@alexcrichton.com>"]
description = """
Platform-agnostic accessors of timestamps in File metadata
diff --git a/vendor/filetime/src/unix/linux.rs b/vendor/filetime/src/unix/linux.rs
index c803e0217..255fcfb61 100644
--- a/vendor/filetime/src/unix/linux.rs
+++ b/vendor/filetime/src/unix/linux.rs
@@ -34,6 +34,11 @@ pub fn set_file_handle_times(
static INVALID: AtomicBool = AtomicBool::new(false);
if !INVALID.load(SeqCst) {
let times = [super::to_timespec(&atime), super::to_timespec(&mtime)];
+
+ // We normally use a syscall because the `utimensat` function is documented
+ // as not accepting a file descriptor in the first argument (even though, on
+ // Linux, the syscall itself can accept a file descriptor there).
+ #[cfg(not(target_env = "musl"))]
let rc = unsafe {
libc::syscall(
libc::SYS_utimensat,
@@ -43,6 +48,24 @@ pub fn set_file_handle_times(
0,
)
};
+ // However, on musl, we call the musl libc function instead. This is because
+ // on newer musl versions starting with musl 1.2, `timespec` is always a 64-bit
+ // value even on 32-bit targets. As a result, musl internally converts their
+ // `timespec` values to the correct ABI before invoking the syscall. Since we
+ // use `timespec` from the libc crate, it matches musl's definition and not
+ // the Linux kernel's version (for some platforms) so we must use musl's
+ // `utimensat` function to properly convert the value. musl's `utimensat`
+ // function allows file descriptors in the path argument so this is fine.
+ #[cfg(target_env = "musl")]
+ let rc = unsafe {
+ libc::utimensat(
+ f.as_raw_fd(),
+ ptr::null::<libc::c_char>(),
+ times.as_ptr(),
+ 0,
+ )
+ };
+
if rc == 0 {
return Ok(());
}
@@ -78,15 +101,7 @@ fn set_times(
if !INVALID.load(SeqCst) {
let p = CString::new(p.as_os_str().as_bytes())?;
let times = [super::to_timespec(&atime), super::to_timespec(&mtime)];
- let rc = unsafe {
- libc::syscall(
- libc::SYS_utimensat,
- libc::AT_FDCWD,
- p.as_ptr(),
- times.as_ptr(),
- flags,
- )
- };
+ let rc = unsafe { libc::utimensat(libc::AT_FDCWD, p.as_ptr(), times.as_ptr(), flags) };
if rc == 0 {
return Ok(());
}
diff --git a/vendor/filetime/src/unix/mod.rs b/vendor/filetime/src/unix/mod.rs
index 8b7788837..df62de429 100644
--- a/vendor/filetime/src/unix/mod.rs
+++ b/vendor/filetime/src/unix/mod.rs
@@ -58,17 +58,16 @@ fn to_timespec(ft: &Option<FileTime>) -> timespec {
}
}
+ let mut ts: timespec = unsafe { std::mem::zeroed() };
if let &Some(ft) = ft {
- timespec {
- tv_sec: ft.seconds() as time_t,
- tv_nsec: ft.nanoseconds() as _,
- }
+ ts.tv_sec = ft.seconds() as time_t;
+ ts.tv_nsec = ft.nanoseconds() as _;
} else {
- timespec {
- tv_sec: 0,
- tv_nsec: UTIME_OMIT as _,
- }
+ ts.tv_sec = 0;
+ ts.tv_nsec = UTIME_OMIT as _;
}
+
+ ts
}
pub fn from_last_modification_time(meta: &fs::Metadata) -> FileTime {
diff --git a/vendor/flate2/.cargo-checksum.json b/vendor/flate2/.cargo-checksum.json
index 0cf4f26d8..287b01bdb 100644
--- a/vendor/flate2/.cargo-checksum.json
+++ b/vendor/flate2/.cargo-checksum.json
@@ -1 +1 @@
-{"files":{"Cargo.lock":"2a6c871e5e5001d23934ab7a2e1e936dc1265d912d384e10c07bede2c1163d31","Cargo.toml":"fb0c03843e790a49015855ebc71b0805ec3647b55093876709a2ed1b1437e263","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"378f5840b258e2779c39418f3f2d7b2ba96f1c7917dd6be0713f88305dbda397","README.md":"b9fa7ea44625cd15b942c9ae748f8f35197f9c19f5deb7087a5fc115064d19d3","examples/compress_file.rs":"65cac39f50420861cb86120b0e7edce4704eb5afd1e27f790a66b8138176fc4d","examples/deflatedecoder-bufread.rs":"59aaa1dcf999da7909ea0a01bef757b80e366f8adf60984cc2e2c70acc774e1a","examples/deflatedecoder-read.rs":"7784b03156600d9a0efadb830920439a8a8f7fe70250090ee8c637033c1338eb","examples/deflatedecoder-write.rs":"6e6952cef15adbf465d4985802d315a3b51f3137be36e62bbcaed0bb27a8d5a6","examples/deflateencoder-bufread.rs":"0cefcb1edef04834e684c9c3d4048a32c7831617e51a102a7bd6a7351d4799be","examples/deflateencoder-read.rs":"d1718c60bb527a2ca15fd208e22c1df51ed972ea48b9d506536635effdbc4847","examples/deflateencoder-write.rs":"79203d1db1128df2a3fa5cbd61d60776e02959c4da67a473f3b96dfb5f01f964","examples/gzbuilder.rs":"e7435090c86db3133d19f7a2bfb7d49bb60ebbd1e0acaf74c2d0d27375d0c41d","examples/gzdecoder-bufread.rs":"8ad927ad5761e4b31bec5c2b4e5429dd9370e25f35be6e60a29149ed834c97a1","examples/gzdecoder-read.rs":"e63ae23a6188ab9831758178a86a36b8693de27e291725d2d5274df4cb93566c","examples/gzdecoder-write.rs":"a8843c75fa725de84b8eb75b08525e61586f60f9f8bfd874fbfd44039d119c5f","examples/gzencoder-bufread.rs":"aaad311ad799c2e739b58fc4e570225d8f52d3bc407f9c71c28023b321e02100","examples/gzencoder-read.rs":"797522cd3d5815321bbb5c26fdfeae027807219e429e36a1b99fff50fcdf0a64","examples/gzencoder-write.rs":"2eea8a8c8bf22f060d8749d786835ce9454abe2cfd24bf0f7a23b5a8d1030121","examples/gzmultidecoder-bufread.rs":"1e4b31da4f1352e748b4516ba60dcd52e5d5e62733fa1c8e7da7bee4efcce1c4","examples/gzmultidecoder-read.rs":"3976274ac8b8190b3f7ed9fd855a193c38458bd40a2dba6a7de21986f78682f6","examples/hello_world.txt":"d2a84f4b8b650937ec8f73cd8be2c74add5a911ba64df27458ed8229da804a26","examples/zlibdecoder-bufread.rs":"e57a597030e6bd87e79329d87b3743b7fb0ff4c217846b0ba2c2d32264208ff1","examples/zlibdecoder-read.rs":"83b3abd1c12586f820d55e4d86c328fdccbdec963e90c44a44cd7d5f1caa4c8f","examples/zlibdecoder-write.rs":"e7cbec46414eb5d67fee95bf1e4a4e6a1ba2a41f4ce9542dd4481035d3f8070d","examples/zlibencoder-bufread.rs":"13d79baeffb6080b4b4f837e23092b52b92b85466ed9e42b0a33a864232e693f","examples/zlibencoder-read.rs":"7f95783b38e0005740f05dbcc03af3bbf28dfe7c9f0542d3fb015d09554163bd","examples/zlibencoder-write.rs":"47c25fb6711e22f95bdc89309c6e367d1060a0120d4259011e97908563e2b8bc","src/bufreader.rs":"2d6a59330e8f838eb6474d19104f21cb98236125c189f36bdff75a069a4cea8f","src/crc.rs":"bfc96a0df325e8fb0005b008a52f1227546c2a4f72f422d4dd40769a8317eb37","src/deflate/bufread.rs":"7dd1c1a5a74abbf32537285c286551c20b3ed62c99e28a67b7d4d7eaeee73570","src/deflate/mod.rs":"ebaa68e75d0c7470c7a2afd7af0f8cc5413654f7c35ac1cb6af3df0144eeb2cf","src/deflate/read.rs":"dc0d080b0a4ab3aa3f2870b69f7cb5380e49baab4eb5fdfe98f7a0a9fb6b32b9","src/deflate/write.rs":"fef4deebc0dc29d4ad481718613c694f6d1b733199e241a1f7f064e2707e4908","src/ffi/c.rs":"387bba48532bb90f13b38f685f68c0e0b3bb2b3a84e6e915abb2fd571ce9c1e9","src/ffi/mod.rs":"d90bfe6150d905c06755a3bf9355be69a7ffb664ca701d51ee1ffe93229abee1","src/ffi/rust.rs":"235cf72391d4077b569f88854b6468e371c19c417b4815468070e155268d83dd","src/gz/bufread.rs":"62881dd14a736cf5fc3d5006e83afd6e5462808f4e8eeb5844ae07d67ad28f16","src/gz/mod.rs":"77d10acd6e923f35cc6434e70cc33002006a8cf5923ebb3105531d4f05542327","src/gz/read.rs":"275150a42ae3a39cc56a83ef212bffce32c74eae1bc6ede33945370bb555ad4d","src/gz/write.rs":"41b9c738bcf64dec44cef591b42e1cb5ef0316aa33d621816fbdd5484e51037b","src/lib.rs":"a1cdcc834b6cc7e470c397578142eca0872840ceb594603264b0aa92b73b94fa","src/mem.rs":"e66a546c83c723dc13320f791de5f43f6683f5549e6d8d0e53fda6108762cc8a","src/zio.rs":"066238023d9c931498d996b6bcd135ba58bc9e916dbaaeddec26a20ad07c698e","src/zlib/bufread.rs":"2c6440dd8958469bb07644a50d3170988a5d75f17788d5bfbf03adfd30e50f4a","src/zlib/mod.rs":"fffaea011fc774756f5392cffb1d2d06c05767e7bbbe306fa5fbe95108b9b06b","src/zlib/read.rs":"11dc6a4072b5d99490f7e5ea8eca9da67b4e77981b05eb3ed56067caaffb3a27","src/zlib/write.rs":"330d6ebe93939c8a045c72fb2c8106bfad92e0ed80c60f729ebba40d11090338","tests/corrupt-gz-file.bin":"083dd284aa1621916a2d0f66ea048c8d3ba7a722b22d0d618722633f51e7d39c","tests/early-flush.rs":"5ed4b0f8e66cab9209e079d5636e5f1b780606cd553a182c809cf73a24e77e8e","tests/empty-read.rs":"45477d316f77a048d747e9d18292abfec0cac667768385c8a061e18fd1240238","tests/good-file.gz":"87296963e53024a74752179ce7e54087565d358a85d3e65c3b37ef36eaa3d4a6","tests/good-file.txt":"bc4e03658a441fe2ad2df7cd2197144b87e41696f01e327b380e869cd9b485a0","tests/gunzip.rs":"a67f2e2dc2e6fbdc42f9ea003eae70f862478a5226d961658b30c8c7928fb7f5","tests/multi.gz":"efa3341da052f95056314cc6920e02a3da15bdef30234b2552fb407812db5cc6","tests/multi.txt":"dbea9325179efe46ea2add94f7b6b745ca983fabb208dc6d34aa064623d7ee23","tests/zero-write.rs":"ff8d0349a540b54363c55807c5fd7fbbdc363d08a536d35a3a40f0ce92c16489"},"package":"f82b0f4c27ad9f8bfd1f3208d882da2b09c301bc1c828fd3a00d0216d2fbbff6"} \ No newline at end of file
+{"files":{"Cargo.lock":"a70316ff2059a2809363ab44ebe3e80f443b5127bc772750313869381e349863","Cargo.toml":"4e65bf00fbe95389960ae6b847fa84f600405c620b53fe5b51b5862330f326d0","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"378f5840b258e2779c39418f3f2d7b2ba96f1c7917dd6be0713f88305dbda397","README.md":"b9fa7ea44625cd15b942c9ae748f8f35197f9c19f5deb7087a5fc115064d19d3","examples/compress_file.rs":"65cac39f50420861cb86120b0e7edce4704eb5afd1e27f790a66b8138176fc4d","examples/deflatedecoder-bufread.rs":"59aaa1dcf999da7909ea0a01bef757b80e366f8adf60984cc2e2c70acc774e1a","examples/deflatedecoder-read.rs":"7784b03156600d9a0efadb830920439a8a8f7fe70250090ee8c637033c1338eb","examples/deflatedecoder-write.rs":"6e6952cef15adbf465d4985802d315a3b51f3137be36e62bbcaed0bb27a8d5a6","examples/deflateencoder-bufread.rs":"0cefcb1edef04834e684c9c3d4048a32c7831617e51a102a7bd6a7351d4799be","examples/deflateencoder-read.rs":"d1718c60bb527a2ca15fd208e22c1df51ed972ea48b9d506536635effdbc4847","examples/deflateencoder-write.rs":"79203d1db1128df2a3fa5cbd61d60776e02959c4da67a473f3b96dfb5f01f964","examples/gzbuilder.rs":"e7435090c86db3133d19f7a2bfb7d49bb60ebbd1e0acaf74c2d0d27375d0c41d","examples/gzdecoder-bufread.rs":"8ad927ad5761e4b31bec5c2b4e5429dd9370e25f35be6e60a29149ed834c97a1","examples/gzdecoder-read.rs":"e63ae23a6188ab9831758178a86a36b8693de27e291725d2d5274df4cb93566c","examples/gzdecoder-write.rs":"a8843c75fa725de84b8eb75b08525e61586f60f9f8bfd874fbfd44039d119c5f","examples/gzencoder-bufread.rs":"aaad311ad799c2e739b58fc4e570225d8f52d3bc407f9c71c28023b321e02100","examples/gzencoder-read.rs":"797522cd3d5815321bbb5c26fdfeae027807219e429e36a1b99fff50fcdf0a64","examples/gzencoder-write.rs":"2eea8a8c8bf22f060d8749d786835ce9454abe2cfd24bf0f7a23b5a8d1030121","examples/gzmultidecoder-bufread.rs":"1e4b31da4f1352e748b4516ba60dcd52e5d5e62733fa1c8e7da7bee4efcce1c4","examples/gzmultidecoder-read.rs":"3976274ac8b8190b3f7ed9fd855a193c38458bd40a2dba6a7de21986f78682f6","examples/hello_world.txt":"d2a84f4b8b650937ec8f73cd8be2c74add5a911ba64df27458ed8229da804a26","examples/zlibdecoder-bufread.rs":"e57a597030e6bd87e79329d87b3743b7fb0ff4c217846b0ba2c2d32264208ff1","examples/zlibdecoder-read.rs":"83b3abd1c12586f820d55e4d86c328fdccbdec963e90c44a44cd7d5f1caa4c8f","examples/zlibdecoder-write.rs":"e7cbec46414eb5d67fee95bf1e4a4e6a1ba2a41f4ce9542dd4481035d3f8070d","examples/zlibencoder-bufread.rs":"13d79baeffb6080b4b4f837e23092b52b92b85466ed9e42b0a33a864232e693f","examples/zlibencoder-read.rs":"7f95783b38e0005740f05dbcc03af3bbf28dfe7c9f0542d3fb015d09554163bd","examples/zlibencoder-write.rs":"47c25fb6711e22f95bdc89309c6e367d1060a0120d4259011e97908563e2b8bc","src/bufreader.rs":"2d6a59330e8f838eb6474d19104f21cb98236125c189f36bdff75a069a4cea8f","src/crc.rs":"bfc96a0df325e8fb0005b008a52f1227546c2a4f72f422d4dd40769a8317eb37","src/deflate/bufread.rs":"7dd1c1a5a74abbf32537285c286551c20b3ed62c99e28a67b7d4d7eaeee73570","src/deflate/mod.rs":"ebaa68e75d0c7470c7a2afd7af0f8cc5413654f7c35ac1cb6af3df0144eeb2cf","src/deflate/read.rs":"dc0d080b0a4ab3aa3f2870b69f7cb5380e49baab4eb5fdfe98f7a0a9fb6b32b9","src/deflate/write.rs":"fef4deebc0dc29d4ad481718613c694f6d1b733199e241a1f7f064e2707e4908","src/ffi/c.rs":"387bba48532bb90f13b38f685f68c0e0b3bb2b3a84e6e915abb2fd571ce9c1e9","src/ffi/mod.rs":"d90bfe6150d905c06755a3bf9355be69a7ffb664ca701d51ee1ffe93229abee1","src/ffi/rust.rs":"235cf72391d4077b569f88854b6468e371c19c417b4815468070e155268d83dd","src/gz/bufread.rs":"62881dd14a736cf5fc3d5006e83afd6e5462808f4e8eeb5844ae07d67ad28f16","src/gz/mod.rs":"77d10acd6e923f35cc6434e70cc33002006a8cf5923ebb3105531d4f05542327","src/gz/read.rs":"275150a42ae3a39cc56a83ef212bffce32c74eae1bc6ede33945370bb555ad4d","src/gz/write.rs":"41b9c738bcf64dec44cef591b42e1cb5ef0316aa33d621816fbdd5484e51037b","src/lib.rs":"a1cdcc834b6cc7e470c397578142eca0872840ceb594603264b0aa92b73b94fa","src/mem.rs":"e66a546c83c723dc13320f791de5f43f6683f5549e6d8d0e53fda6108762cc8a","src/zio.rs":"066238023d9c931498d996b6bcd135ba58bc9e916dbaaeddec26a20ad07c698e","src/zlib/bufread.rs":"2c6440dd8958469bb07644a50d3170988a5d75f17788d5bfbf03adfd30e50f4a","src/zlib/mod.rs":"fffaea011fc774756f5392cffb1d2d06c05767e7bbbe306fa5fbe95108b9b06b","src/zlib/read.rs":"11dc6a4072b5d99490f7e5ea8eca9da67b4e77981b05eb3ed56067caaffb3a27","src/zlib/write.rs":"330d6ebe93939c8a045c72fb2c8106bfad92e0ed80c60f729ebba40d11090338","tests/corrupt-gz-file.bin":"083dd284aa1621916a2d0f66ea048c8d3ba7a722b22d0d618722633f51e7d39c","tests/early-flush.rs":"5ed4b0f8e66cab9209e079d5636e5f1b780606cd553a182c809cf73a24e77e8e","tests/empty-read.rs":"45477d316f77a048d747e9d18292abfec0cac667768385c8a061e18fd1240238","tests/good-file.gz":"87296963e53024a74752179ce7e54087565d358a85d3e65c3b37ef36eaa3d4a6","tests/good-file.txt":"bc4e03658a441fe2ad2df7cd2197144b87e41696f01e327b380e869cd9b485a0","tests/gunzip.rs":"a67f2e2dc2e6fbdc42f9ea003eae70f862478a5226d961658b30c8c7928fb7f5","tests/multi.gz":"efa3341da052f95056314cc6920e02a3da15bdef30234b2552fb407812db5cc6","tests/multi.txt":"dbea9325179efe46ea2add94f7b6b745ca983fabb208dc6d34aa064623d7ee23","tests/zero-write.rs":"ff8d0349a540b54363c55807c5fd7fbbdc363d08a536d35a3a40f0ce92c16489"},"package":"a8a2db397cb1c8772f31494cb8917e48cd1e64f0fa7efac59fbd741a0a8ce841"} \ No newline at end of file
diff --git a/vendor/flate2/Cargo.lock b/vendor/flate2/Cargo.lock
index 732ee01f0..5389eecb0 100644
--- a/vendor/flate2/Cargo.lock
+++ b/vendor/flate2/Cargo.lock
@@ -10,9 +10,9 @@ checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
[[package]]
name = "cc"
-version = "1.0.73"
+version = "1.0.77"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11"
+checksum = "e9f73505338f7d905b19d18738976aae232eb46b8efc15554ffc56deb5d9ebe4"
[[package]]
name = "cfg-if"
@@ -31,9 +31,9 @@ dependencies = [
[[package]]
name = "cmake"
-version = "0.1.48"
+version = "0.1.49"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e8ad8cef104ac57b68b89df3208164d228503abbdce70f6880ffa3d970e7443a"
+checksum = "db34956e100b30725f2eb215f90d4871051239535632f84fea3bc92722c66b7c"
dependencies = [
"cc",
]
@@ -49,7 +49,7 @@ dependencies = [
[[package]]
name = "flate2"
-version = "1.0.24"
+version = "1.0.25"
dependencies = [
"cloudflare-zlib-sys",
"crc32fast",
@@ -62,9 +62,9 @@ dependencies = [
[[package]]
name = "getrandom"
-version = "0.2.6"
+version = "0.2.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9be70c98951c83b8d2f8f60d7065fa6d5146873094452a1008da8c2f1e4205ad"
+checksum = "c05aeb6a22b8f62540c194aac980f2115af067bfe15a0734d7277a768d396b31"
dependencies = [
"cfg-if",
"libc",
@@ -73,9 +73,9 @@ dependencies = [
[[package]]
name = "libc"
-version = "0.2.124"
+version = "0.2.137"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "21a41fed9d98f27ab1c6d161da622a4fa35e8a54a8adc24bbf3ddd0ef70b0e50"
+checksum = "fc7fcc620a3bff7cdd7a365be3376c97191aeaccc2a603e600951e452615bf89"
[[package]]
name = "libz-ng-sys"
@@ -102,24 +102,24 @@ dependencies = [
[[package]]
name = "miniz_oxide"
-version = "0.5.1"
+version = "0.6.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d2b29bd4bc3f33391105ebee3589c19197c4271e3e5a9ec9bfe8127eeff8f082"
+checksum = "b275950c28b37e794e8c55d88aeb5e139d0ce23fdbbeda68f8d7174abdf9e8fa"
dependencies = [
"adler",
]
[[package]]
name = "pkg-config"
-version = "0.3.25"
+version = "0.3.26"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1df8c4ec4b0627e53bdf214615ad287367e482558cf84b109250b37464dc03ae"
+checksum = "6ac9a59f73473f1b8d852421e59e64809f025994837ef743615c6d0c5b305160"
[[package]]
name = "ppv-lite86"
-version = "0.2.16"
+version = "0.2.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872"
+checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de"
[[package]]
name = "quickcheck"
@@ -153,9 +153,9 @@ dependencies = [
[[package]]
name = "rand_core"
-version = "0.6.3"
+version = "0.6.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7"
+checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
dependencies = [
"getrandom",
]
@@ -168,6 +168,6 @@ checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426"
[[package]]
name = "wasi"
-version = "0.10.2+wasi-snapshot-preview1"
+version = "0.11.0+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6"
+checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
diff --git a/vendor/flate2/Cargo.toml b/vendor/flate2/Cargo.toml
index 23b8b80d0..68516e5e7 100644
--- a/vendor/flate2/Cargo.toml
+++ b/vendor/flate2/Cargo.toml
@@ -12,7 +12,7 @@
[package]
edition = "2018"
name = "flate2"
-version = "1.0.24"
+version = "1.0.25"
authors = [
"Alex Crichton <alex@alexcrichton.com>",
"Josh Triplett <josh@joshtriplett.org>",
@@ -56,7 +56,8 @@ optional = true
default-features = false
[dependencies.miniz_oxide]
-version = "0.5.0"
+version = "0.6.0"
+features = ["with-alloc"]
optional = true
default-features = false
@@ -90,5 +91,6 @@ zlib-ng-compat = [
]
[target."cfg(all(target_arch = \"wasm32\", not(target_os = \"emscripten\")))".dependencies.miniz_oxide]
-version = "0.5.0"
+version = "0.6.0"
+features = ["with-alloc"]
default-features = false
diff --git a/vendor/gimli-0.26.2/.cargo-checksum.json b/vendor/gimli-0.26.2/.cargo-checksum.json
new file mode 100644
index 000000000..759ec93de
--- /dev/null
+++ b/vendor/gimli-0.26.2/.cargo-checksum.json
@@ -0,0 +1 @@
+{"files":{"CHANGELOG.md":"789a696803d3f1bed3ff3566cac8e7cf15c4bf9428242d637d0ce7f3a0ad57a3","CONTRIBUTING.md":"5f513ec06013e4f6f097e9c9492da5a47b9f25c94c6ecadfb655a77405fe912c","Cargo.lock":"284bff6b09ef0fd214c34492417778d6d5b9f75dc54557015af01a95696c752a","Cargo.toml":"92dccbeaa61bc8c65da53917fbf32900b3cb2549f90b67b67e1c67672bac205e","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"7b63ecd5f1902af1b63729947373683c32745c16a10e8e6292e2e2dcd7e90ae0","README.md":"57e36d344dabe1c52a9c81eafb28787c309b86c47437abf8589ef17bf383fc5f","benches/bench.rs":"e0045b989683794951563aa91b37069b2f6ae55f95e288d23f5c984b46e3a7eb","examples/dwarf-validate.rs":"4aac1045e3c08bf00878eeff75c0cfc30c06171c5eab2e71d757505786729687","examples/dwarfdump.rs":"d74323c037689b32825efa9bf69614ee26a444513b266e819ecf486956ee3299","examples/simple.rs":"4c3425e8bd1880d9522f5ed2581fb5ccd452d4be678eebc0e147c48722a7be1d","examples/simple_line.rs":"ac795f859a17650dde466b5b23b8c161b2e3b8eb57e32f5b6718a3072f6bfad0","fixtures/self/README.md":"7cfd76031ec5a4b38cc4eb56ccbfe1bb590fb54c333d037550bdeaaeacfc20cb","fixtures/self/debug_abbrev":"7c0faa940d9c68d196d03ad55a20e5c746040fa428ff323277fa381deff82bba","fixtures/self/debug_aranges":"8c2aeb2335f61d04ecb7b747070d24f83a6517cbee79dc5c96d97fb6c53d6b6d","fixtures/self/debug_info":"42028a5983006e0703f9ca9515cd27d891ae4af70279fae5011d547f581e2661","fixtures/self/debug_inlined":"89d9516f06ff835621936037f5884fc56712bf304c1dcde52251ddd510fe8710","fixtures/self/debug_line":"b29aebcca3b38bb2bb8aa708cbe74a0dce5a3b0c18916b63d6d17282c017bec7","fixtures/self/debug_loc":"8906ccb9c204f233eb74c1d069dee97a19d18c2051f9147795d7b5364a9266aa","fixtures/self/debug_pubnames":"cf58e237f89c68afba724597fa7e260448636b45f2e69dc6f1bfe34006e27c48","fixtures/self/debug_pubtypes":"d43c1bed71c9d14d1683294cdc1833f069cf131d6e95ee808547919b4f352d81","fixtures/self/debug_ranges":"6d765ac18d33accd89186d077eeb505cbdf97d990c9201d63d9463cd7787ce7a","fixtures/self/debug_str":"9ed904b68eee77b8558b80b3b7ca03e8527f6c64483e9d6d845f40270eb21183","fixtures/self/eh_frame":"6dc3d84351cac42cf73d03452fbb532470dd94d08715154c48417e3f62095f17","fixtures/self/eh_frame_hdr":"afba7a0aa233c9a8c81c986495bd2505164844adb93272d6bc0c9e592e684716","rustfmt.toml":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855","src/arch.rs":"1c4cb3e2a322f3f42fe0b82875c9d0ce060d9af2388990139bdce9a4487c32da","src/common.rs":"392f52a58db6101187ca5525bbeafca9bda2342debd058cabca37350cd9db619","src/constants.rs":"358cf7924c79bc72de59d23d1fa02b2047d6c763c8fbd8be263ab8cd3e3ba7ec","src/endianity.rs":"1f7e62ae34f540c06bedf1e7948739211556eea7dd83731a5ca52c7d687ed0fc","src/leb128.rs":"996d5c79d027f97c010ca487bc4ff5f8265f4b9e63d62b4e4fa291383c259ee9","src/lib.rs":"6863b9a9d1eddf34b4095dfe60318aae56914fbf515ba5601b29024cc963f27c","src/read/abbrev.rs":"a3f550c32f1eb880d82bdb5257d35e10d32cfd039050e8131cbeedac346cc1d9","src/read/addr.rs":"f63f289edf889e87107bb2090fb1c50b48af7015f31b7c39c3d6ea09630a38e9","src/read/aranges.rs":"ba3302f87cffb7ee15f48b0530ebd707f45ad056934223078d25ae2a1b034f1c","src/read/cfi.rs":"b1064ed9b4b87169a148cc86adc7443c5a771dc2d1799129f7883f1ef6adc165","src/read/dwarf.rs":"a39c24429b437ae3a1cd17bae2f01c973c9ce39f7b5f2b3435982d6860944e0e","src/read/endian_reader.rs":"320983a859c2bb0dd44a3e6fae55ff0a84dba3fa80c2edbc64aa8135c44eddf0","src/read/endian_slice.rs":"ae1c52499728f6a85648f1bf87c02dcf43bebecb5ad4e835a1246938ba4338bf","src/read/index.rs":"e79b8d591b8e2007a37f5ea85a6d71b69d56ca3739a85cf7bf361724c5b829fa","src/read/line.rs":"af7a1520777e56632970fc5fe7377fdcd12d078eb88eeb2b0f2cc95b73ff68a7","src/read/lists.rs":"67ca9e1a36a91feb4996d035211de845205212bfda02163685d217818567ff93","src/read/loclists.rs":"1b4ea85c0dd8c6eae492a60cb70810185d56ba579df7986cb8a36385031b10fd","src/read/lookup.rs":"0cf89ba12b9d48b1fe035dd3a497730323acb9427a9457abbc2f7c58c4c71165","src/read/mod.rs":"3bafc747c31a575bcc92d3e7d5ea5a15f5acc01918a4377cec1dced0f85b5d2b","src/read/op.rs":"e5dce6520dfc90ec74c3b070ca374b89fcf55ff23101471591458175a72c79e6","src/read/pubnames.rs":"ed752ee1a7017e6d3be42d81e4ddaaac960ef08081463a19106c9f041526d4a3","src/read/pubtypes.rs":"5e75b32c0923e827aff0bb2db456797a0e8d38ba46be992558a7990b3196bcf5","src/read/reader.rs":"b10ff3e77b54347e96b1f3cff30da104dfdd0c4d7a55b672950788f1f1ae3478","src/read/rnglists.rs":"af637d283d76514382ee0556463cccab4e6f0ea4d061db9a44a594b5d57d1fd7","src/read/str.rs":"4c2f50014451621fea45969cd313f6840fcd3a99d7a2d081bfa1f8e0e434133a","src/read/unit.rs":"6ed00ba004c329008bf295d9c7d724afe961750f0c7b08430fc213fd5d998003","src/read/util.rs":"0b7d0d2225a98618070dc472ccba49a5411aa8beed5ff6696da079d06156d363","src/read/value.rs":"5a91e03ad3d41f679b264753498434b91948c6b89955e4beb4522498386d9b1d","src/test_util.rs":"291eefa6b51c6d934ba2f4a4c9bc7c403046fc1cccf4d43487820f0154bb89e2","src/write/abbrev.rs":"fa02163389e92e804d139cf84f833ab6af932083f0eb2d74464b4a70bd3237ff","src/write/cfi.rs":"3b04b0ebd82363738199cc673f64e0ceb60506a67c4f18b435a109caa62840f3","src/write/dwarf.rs":"8a1a0893e31134ad68993994594f3024ad0c8af7c1188b29e0ffc26b42edef21","src/write/endian_vec.rs":"1d5811986648816a677580b22630f5059757a381487d73e9adbb3008c9ae0c58","src/write/line.rs":"df7d2082c71b5e523cd52745700aae3dcfa5800f0b280e831ef5d8eb8035d6a7","src/write/loc.rs":"bb5b750c04f6603e18225db72652ea00239234ba674a8a8627c99d4ab07b47a9","src/write/mod.rs":"d8aa1da854cdee629d470d00d87e00dc6998e4bec1ca951f8d2f277730ab9d69","src/write/op.rs":"7b1d49b10c8c92b2d5b259e83119ff7dc95bc552535bb7b1a82ca9556a35c589","src/write/range.rs":"5bac01e372c08e3cc19e1e07e40492d8214cdfa8881737920cb792f4aa2ba80b","src/write/section.rs":"3ce781d5e82ba365ff54fdd36e0ef58c58a2215b09a8861eb0b038efac82b77f","src/write/str.rs":"4850cc2fee55980f9cbb6b4169f9861ab9d05c2b28a85c2b790480b83a66f514","src/write/unit.rs":"213c881736f8c87fcb2f921e379791eaba2915e8d077139965a9c6211001fe44","src/write/writer.rs":"304181287f90445bbfb33349c26b34bd87002d6844fc5686bfc0756fd0a1ecd8","tests/convert_self.rs":"180909b562969e1691b64628ded8654e6e0b10b3357f39917bd8ac288c5826dd","tests/parse_self.rs":"f2da1c7daef7139545c9367c2f26199e8b4623b31d4ec6480ddd851e6980f2dc"},"package":"22030e2c5a68ec659fde1e949a745124b48e6fa8b045b7ed5bd1fe4ccc5c4e5d"} \ No newline at end of file
diff --git a/vendor/gimli-0.26.2/CHANGELOG.md b/vendor/gimli-0.26.2/CHANGELOG.md
new file mode 100644
index 000000000..9ca6d70a8
--- /dev/null
+++ b/vendor/gimli-0.26.2/CHANGELOG.md
@@ -0,0 +1,873 @@
+# `gimli` Change Log
+
+--------------------------------------------------------------------------------
+
+## 0.26.2
+
+Released 2022/07/16.
+
+### Changed
+
+* Fixed CFI personality encoding when writing.
+ [#609](https://github.com/gimli-rs/gimli/pull/609)
+
+* Fixed use of raw pointer for mutation, detected by Miri.
+ [#614](https://github.com/gimli-rs/gimli/pull/614)
+
+* Fixed `DW_OP_GNU_implicit_pointer` handling for DWARF version 2.
+ [#618](https://github.com/gimli-rs/gimli/pull/618)
+
+### Added
+
+* Added `read::EhHdrTable::iter`.
+ [#619](https://github.com/gimli-rs/gimli/pull/619)
+
+--------------------------------------------------------------------------------
+
+## 0.26.1
+
+Released 2021/11/02.
+
+### Changed
+
+* Fixed segmentation fault in `ArrayVec<Vec<T>>::into_vec`, which may be used by
+ `read::Evaluation::result`. This regression was introduced in 0.26.0.
+ [#601](https://github.com/gimli-rs/gimli/pull/601)
+
+--------------------------------------------------------------------------------
+
+## 0.26.0
+
+Released 2021/10/24.
+
+### Breaking changes
+
+* Removed `read::UninitializedUnwindContext`. Use `Box<UnwindContext>` instead.
+ [#593](https://github.com/gimli-rs/gimli/pull/593)
+
+* Renamed `read::Error::CfiStackFull` to `StackFull`.
+ [#595](https://github.com/gimli-rs/gimli/pull/595)
+
+* Added `UnwindContextStorage` type parameter to `read::UnwindContext`, `read::UnwindTable`,
+ `read::UnwindTableRow`, and `read::RegisterRuleMap`.
+ [#595](https://github.com/gimli-rs/gimli/pull/595)
+
+* Added `EvaluationStorage` type parameter to `read::Evaluation`.
+ [#595](https://github.com/gimli-rs/gimli/pull/595)
+
+* Added `read::SectionId::DebugCuIndex` and `read::SectionId::DebugTuIndex`.
+ [#588](https://github.com/gimli-rs/gimli/pull/588)
+
+### Changed
+
+* Fixed `DW_EH_PE_pcrel` handling in default `write::Writer::write_eh_pointer` implementation.
+ [#576](https://github.com/gimli-rs/gimli/pull/576)
+
+* Fixed `read::AttributeSpecification::size` for some forms.
+ [#597](https://github.com/gimli-rs/gimli/pull/597)
+
+* Display more unit details in dwarfdump.
+ [#584](https://github.com/gimli-rs/gimli/pull/584)
+
+### Added
+
+* Added `write::DebuggingInformationEntry::delete_child`.
+ [#570](https://github.com/gimli-rs/gimli/pull/570)
+
+* Added ARM and AArch64 register definitions.
+ [#574](https://github.com/gimli-rs/gimli/pull/574)
+ [#577](https://github.com/gimli-rs/gimli/pull/577)
+
+* Added RISC-V register definitions.
+ [#579](https://github.com/gimli-rs/gimli/pull/579)
+
+* Added `read::DwarfPackage`, `read::DebugCuIndex`, and `read::DebugTuIndex`.
+ [#588](https://github.com/gimli-rs/gimli/pull/588)
+
+* Added `read-core` feature to allow building without `liballoc`.
+ [#596](https://github.com/gimli-rs/gimli/pull/596)
+
+* Added `read::EntriesRaw::skip_attributes`.
+ [#597](https://github.com/gimli-rs/gimli/pull/597)
+
+--------------------------------------------------------------------------------
+
+## 0.25.0
+
+Released 2021/07/26.
+
+### Breaking changes
+
+* `read::FrameDescriptionEntry::unwind_info_for_address` now returns a reference
+ instead of cloning.
+ [#557](https://github.com/gimli-rs/gimli/pull/557)
+
+* `read::AttributeValue::RangeListsRef` now contains a `RawRangeListsOffset`
+ to allow handling of GNU split DWARF extensions.
+ Use `read::Dwarf::ranges_offset_from_raw` to handle it.
+ [#568](https://github.com/gimli-rs/gimli/pull/568)
+ [#569](https://github.com/gimli-rs/gimli/pull/569)
+
+* Added `read::Unit::dwo_id`.
+ [#569](https://github.com/gimli-rs/gimli/pull/569)
+
+### Changed
+
+* `.debug_aranges` parsing now accepts version 3.
+ [#560](https://github.com/gimli-rs/gimli/pull/560)
+
+* `read::Dwarf::attr_ranges_offset` and its callers now handle GNU split DWARF extensions.
+ [#568](https://github.com/gimli-rs/gimli/pull/568)
+ [#569](https://github.com/gimli-rs/gimli/pull/569)
+
+### Added
+
+* Added `read::DebugLineStr::new`.
+ [#556](https://github.com/gimli-rs/gimli/pull/556)
+
+* Added `read::UnwindTable::into_current_row`.
+ [#557](https://github.com/gimli-rs/gimli/pull/557)
+
+* Added more `DW_LANG` constants.
+ [#565](https://github.com/gimli-rs/gimli/pull/565)
+
+* dwarfdump: added DWO parent support.
+ [#568](https://github.com/gimli-rs/gimli/pull/568)
+
+* Added `read::Dwarf` methods: `ranges_offset_from_raw`, `raw_ranges`, and `raw_locations`.
+ [#568](https://github.com/gimli-rs/gimli/pull/568)
+ [#569](https://github.com/gimli-rs/gimli/pull/569)
+
+--------------------------------------------------------------------------------
+
+## 0.24.0
+
+Released 2021/05/01.
+
+### Breaking changes
+
+* Minimum Rust version increased to 1.42.0.
+
+* Added `read::Dwarf::debug_aranges`.
+ [#539](https://github.com/gimli-rs/gimli/pull/539)
+
+* Replaced `read::DebugAranges::items` with `read::DebugAranges::headers`.
+ [#539](https://github.com/gimli-rs/gimli/pull/539)
+
+* Added `read::Operation::Wasm*`.
+ [#546](https://github.com/gimli-rs/gimli/pull/546)
+
+* `read::LineRow::line` now returns `Option<NonZeroU64>`.
+ The `read::ColumnType::Column` variant now contains a `NonZeroU64`.
+ [#551](https://github.com/gimli-rs/gimli/pull/551)
+
+* Replaced `read::Dwarf::debug_str_sup` with `read::Dwarf::sup`.
+ Deleted `sup` parameter of `read::Dwarf::load`.
+ Added `read::Dwarf::load_sup`.
+ [#554](https://github.com/gimli-rs/gimli/pull/554)
+
+### Added
+
+* dwarfdump: Supplementary object file support.
+ [#552](https://github.com/gimli-rs/gimli/pull/552)
+
+### Changed
+
+* Support `DW_FORM_addrx*` for `DW_AT_low_pc`/`DW_AT_high_pc` in `read::Dwarf`.
+ [#541](https://github.com/gimli-rs/gimli/pull/541)
+
+* Performance improvement in `EndianReader`.
+ [#549](https://github.com/gimli-rs/gimli/pull/549)
+
+--------------------------------------------------------------------------------
+
+## 0.23.0
+
+Released 2020/10/27.
+
+### Breaking changes
+
+* Added more variants to `read::UnitType`.
+ Added `read::AttributeValue::DwoId`
+ [#521](https://github.com/gimli-rs/gimli/pull/521)
+
+* Replaced `CompilationUnitHeader` and `TypeUnitHeader` with `UnitHeader`.
+ Replaced `CompilationUnitHeadersIter` with `DebugInfoUnitHeadersIter`.
+ Replaced `TypeUnitHeadersIter` with `DebugTypesUnitHeadersIter`.
+ [#523](https://github.com/gimli-rs/gimli/pull/523)
+
+
+### Added
+
+* Added read support for split DWARF.
+ [#527](https://github.com/gimli-rs/gimli/pull/527)
+ [#529](https://github.com/gimli-rs/gimli/pull/529)
+
+* Added `read::Dwarf::attr_address`.
+ [#524](https://github.com/gimli-rs/gimli/pull/524)
+
+* Added read support for `DW_AT_GNU_addr_base` and `DW_AT_GNU_ranges_base`.
+ [#525](https://github.com/gimli-rs/gimli/pull/525)
+
+* dwarfdump: Display index values for attributes.
+ [#526](https://github.com/gimli-rs/gimli/pull/526)
+
+* Added `name_to_register`.
+ [#532](https://github.com/gimli-rs/gimli/pull/532)
+
+--------------------------------------------------------------------------------
+
+## 0.22.0
+
+Released 2020/07/03.
+
+### Breaking changes
+
+* Fixed `UnitHeader::size_of_header` for DWARF 5 units.
+ [#518](https://github.com/gimli-rs/gimli/pull/518)
+
+### Added
+
+* Added fuzz targets in CI.
+ [#512](https://github.com/gimli-rs/gimli/pull/512)
+
+* Added read support for `DW_OP_GNU_addr_index` and `DW_OP_GNU_const_index`.
+ [#516](https://github.com/gimli-rs/gimli/pull/516)
+
+* Added `.dwo` support to dwarfdump.
+ [#516](https://github.com/gimli-rs/gimli/pull/516)
+
+* Added `SectionId::dwo_name` and `Section::dwo_section_name`.
+ [#517](https://github.com/gimli-rs/gimli/pull/517)
+
+### Fixed
+
+* Fixed panic when reading `DW_FORM_indirect` combined with `DW_FORM_implicit_const`.
+ [#502](https://github.com/gimli-rs/gimli/pull/502)
+
+* Fixed panic for `read::Abbreviations::get(0)`.
+ [#505](https://github.com/gimli-rs/gimli/pull/505)
+
+* Fixed arithmetic overflow when reading `.debug_line`.
+ [#508](https://github.com/gimli-rs/gimli/pull/508)
+
+* Fixed arithmetic overflow when reading CFI.
+ [#509](https://github.com/gimli-rs/gimli/pull/509)
+
+* Fixed arithmetic overflow and division by zero when reading `.debug_aranges`.
+ [#510](https://github.com/gimli-rs/gimli/pull/510)
+
+* Don't return error from `read::Unit::new` when `DW_AT_name` or `DW_AT_comp_dir` is missing.
+ [#515](https://github.com/gimli-rs/gimli/pull/515)
+
+--------------------------------------------------------------------------------
+
+## 0.21.0
+
+Released 2020/05/12.
+
+### Breaking changes
+
+* Minimum Rust version increased to 1.38.0.
+
+* Replaced `read::Operation::Literal` with `Operation::UnsignedConstant` and `Operation::SignedConstant`.
+ Changed `read::Operation::Bra` and `read::Operation::Skip` to contain the target offset instead of the bytecode.
+ [#479](https://github.com/gimli-rs/gimli/pull/479)
+
+* Changed `write::Expression` to support references. Existing users can convert to use `Expression::raw`.
+ [#479](https://github.com/gimli-rs/gimli/pull/479)
+
+* Replaced `write::AttributeValue::AnyUnitEntryRef` with `DebugInfoRef`.
+ Renamed `write::AttributeValue::ThisUnitEntryRef` to `UnitRef`.
+ [#479](https://github.com/gimli-rs/gimli/pull/479)
+
+* Added more optional features: `endian-reader` and `fallible-iterator`.
+ [#495](https://github.com/gimli-rs/gimli/pull/495)
+ [#498](https://github.com/gimli-rs/gimli/pull/498)
+
+### Added
+
+* Added `read::Expression::operations`
+ [#479](https://github.com/gimli-rs/gimli/pull/479)
+
+### Fixed
+
+* Fixed newlines in `dwarfdump` example.
+ [#470](https://github.com/gimli-rs/gimli/pull/470)
+
+* Ignore zero terminators when reading `.debug_frame` sections.
+ [#486](https://github.com/gimli-rs/gimli/pull/486)
+
+* Increase the number of CFI register rules supported by `read::UnwindContext`.
+ [#487](https://github.com/gimli-rs/gimli/pull/487)
+
+* Fixed version handling and return register encoding when reading `.eh_frame` sections.
+ [#493](https://github.com/gimli-rs/gimli/pull/493)
+
+### Changed
+
+* Added `EhFrame` and `DebugFrame` to `write::Sections`.
+ [#492](https://github.com/gimli-rs/gimli/pull/492)
+
+* Improved performance of `write::LineProgram::generate_row`.
+ [#476](https://github.com/gimli-rs/gimli/pull/476)
+
+* Removed use of the `byteorder`, `arrayvec` and `smallvec` crates.
+ [#494](https://github.com/gimli-rs/gimli/pull/494)
+ [#496](https://github.com/gimli-rs/gimli/pull/496)
+ [#497](https://github.com/gimli-rs/gimli/pull/497)
+
+--------------------------------------------------------------------------------
+
+## 0.20.0
+
+Released 2020/01/11.
+
+### Breaking changes
+
+* Changed type of `DwTag`, `DwAt`, and `DwForm` constants.
+ [#451](https://github.com/gimli-rs/gimli/pull/451)
+
+* Added `read/write::AttributeValue::DebugMacroRef`, and returned where
+ required in `read::Attribute::value`. Added `SectionId::DebugMacro`.
+ [#454](https://github.com/gimli-rs/gimli/pull/454)
+
+* Deleted `alloc` feature, and fixed `no-std` builds with stable rust.
+ [#459](https://github.com/gimli-rs/gimli/pull/459)
+
+* Deleted `read::Error::description`, and changed `<read::Error as Display>`
+ to display what was previously the description.
+ [#462](https://github.com/gimli-rs/gimli/pull/462)
+
+### Added
+
+* Added GNU view constants.
+ [#434](https://github.com/gimli-rs/gimli/pull/434)
+
+* Added `read::EntriesRaw` for low level DIE parsing.
+ [#455](https://github.com/gimli-rs/gimli/pull/455)
+
+* Added `examples/simple-line.rs`.
+ [#460](https://github.com/gimli-rs/gimli/pull/460)
+
+### Fixed
+
+* Fixed handling of CFI augmentations without data.
+ [#438](https://github.com/gimli-rs/gimli/pull/438)
+
+* dwarfdump: fix panic for malformed expressions.
+ [#447](https://github.com/gimli-rs/gimli/pull/447)
+
+* dwarfdump: fix handling of Mach-O relocations.
+ [#449](https://github.com/gimli-rs/gimli/pull/449)
+
+### Changed
+
+* Improved abbreviation parsing performance.
+ [#451](https://github.com/gimli-rs/gimli/pull/451)
+
+--------------------------------------------------------------------------------
+
+## 0.19.0
+
+Released 2019/07/08.
+
+### Breaking changes
+
+* Small API changes related to `.debug_loc` and `.debug_loclists`:
+ added `read::RawLocListEntry::AddressOrOffsetPair` enum variant,
+ added `write::Sections::debug_loc/debug_loclists` public members,
+ and replaced `write::AttributeValue::LocationListsRef` with `LocationListRef`.
+ [#425](https://github.com/gimli-rs/gimli/pull/425)
+
+### Added
+
+* Added `read::Attribute::exprloc_value` and `read::AttributeValue::exprloc_value`.
+ [#422](https://github.com/gimli-rs/gimli/pull/422)
+
+* Added support for writing `.debug_loc` and `.debug_loclists` sections.
+ [#425](https://github.com/gimli-rs/gimli/pull/425)
+
+* Added `-G` flag to `dwarfdump` example to display global offsets.
+ [#427](https://github.com/gimli-rs/gimli/pull/427)
+
+* Added `examples/simple.rs`.
+ [#429](https://github.com/gimli-rs/gimli/pull/429)
+
+### Fixed
+
+* `write::LineProgram::from` no longer requires `DW_AT_name` or `DW_AT_comp_dir`
+ attributes to be present in the unit DIE.
+ [#430](https://github.com/gimli-rs/gimli/pull/430)
+
+--------------------------------------------------------------------------------
+
+## 0.18.0
+
+Released 2019/04/25.
+
+The focus of this release has been on improving support for reading CFI,
+and adding support for writing CFI.
+
+### Breaking changes
+
+* For types which have an `Offset` type parameter, the default `Offset`
+ has changed from `usize` to `R::Offset`.
+ [#392](https://github.com/gimli-rs/gimli/pull/392)
+
+* Added an `Offset` type parameter to the `read::Unit` type to allow variance.
+ [#393](https://github.com/gimli-rs/gimli/pull/393)
+
+* Changed the `UninitializedUnwindContext::initialize` method to borrow `self`,
+ and return `&mut UnwindContext`. Deleted the `InitializedUnwindContext` type.
+ [#395](https://github.com/gimli-rs/gimli/pull/395)
+
+* Deleted the `UnwindSection` type parameters from the `CommonInformationEntry`,
+ `FrameDescriptionEntry`, `UninitializedUnwindContext`,
+ `UnwindContext`, and `UnwindTable` types.
+ [#399](https://github.com/gimli-rs/gimli/pull/399)
+
+* Changed the signature of the `get_cie` callback parameter for various functions.
+ The signature now matches the `UnwindSection::cie_from_offset` method, so
+ that method can be used as the parameter.
+ [#400](https://github.com/gimli-rs/gimli/pull/400)
+
+* Reduced the number of lifetime parameters for the `UnwindTable` type.
+ [#400](https://github.com/gimli-rs/gimli/pull/400)
+
+* Updated `fallible-iterator` to version 0.2.0.
+ [#407](https://github.com/gimli-rs/gimli/pull/407)
+
+* Added a parameter to the `Error::UnexpectedEof` enum variant.
+ [#408](https://github.com/gimli-rs/gimli/pull/408)
+
+### Added
+
+* Update to 2018 edition.
+ [#391](https://github.com/gimli-rs/gimli/pull/391)
+
+* Added the `FrameDescriptionEntry::unwind_info_for_address` method.
+ [#396](https://github.com/gimli-rs/gimli/pull/396)
+
+* Added the `FrameDescriptionEntry::rows` method.
+ [#396](https://github.com/gimli-rs/gimli/pull/396)
+
+* Added the `EhHdrTable::unwind_info_for_address` method.
+ [#400](https://github.com/gimli-rs/gimli/pull/400)
+
+* Added the `EhHdrTable::fde_for_address` method and deprecated the
+ `EhHdrTable::lookup_and_parse` method.
+ [#400](https://github.com/gimli-rs/gimli/pull/400)
+
+* Added the `EhHdrTable::pointer_to_offset` method.
+ [#400](https://github.com/gimli-rs/gimli/pull/400)
+
+* Added the `UnwindSection::fde_for_address` method.
+ [#396](https://github.com/gimli-rs/gimli/pull/396)
+
+* Added the `UnwindSection::fde_from_offset` method.
+ [#400](https://github.com/gimli-rs/gimli/pull/400)
+
+* Added the `UnwindSection::partial_fde_from_offset` method.
+ [#400](https://github.com/gimli-rs/gimli/pull/400)
+
+* Added the `Section::id` method.
+ [#406](https://github.com/gimli-rs/gimli/pull/406)
+
+* Added the `Dwarf::load` method, and corresponding methods for individual sections.
+ [#406](https://github.com/gimli-rs/gimli/pull/406)
+
+* Added the `Dwarf::borrow` method, and corresponding methods for individual sections.
+ [#406](https://github.com/gimli-rs/gimli/pull/406)
+
+* Added the `Dwarf::format_error` method.
+ [#408](https://github.com/gimli-rs/gimli/pull/408)
+
+* Added the `Dwarf::die_ranges` method.
+ [#417](https://github.com/gimli-rs/gimli/pull/417)
+
+* Added the `Dwarf::unit_ranges` method.
+ [#417](https://github.com/gimli-rs/gimli/pull/417)
+
+* Added support for writing `.debug_frame` and `.eh_frame` sections.
+ [#412](https://github.com/gimli-rs/gimli/pull/412)
+ [#419](https://github.com/gimli-rs/gimli/pull/419)
+
+### Fixed
+
+* The `code_alignment_factor` is now used when evaluting CFI instructions
+ that advance the location.
+ [#401](https://github.com/gimli-rs/gimli/pull/401)
+
+* Fixed parsing of pointers encoded with `DW_EH_PE_funcrel`.
+ [#402](https://github.com/gimli-rs/gimli/pull/402)
+
+* Use the FDE address encoding from the augmentation when parsing `DW_CFA_set_loc`.
+ [#403](https://github.com/gimli-rs/gimli/pull/403)
+
+* Fixed setting of `.eh_frame` base addresses in dwarfdump.
+ [#410](https://github.com/gimli-rs/gimli/pull/410)
+
+## 0.17.0
+
+Released 2019/02/21.
+
+The focus of this release has been on improving DWARF 5 support, and
+adding support for writing DWARF.
+
+### Breaking changes
+
+* Changed register values to a `Register` type instead of `u8`/`u64`.
+ [#328](https://github.com/gimli-rs/gimli/pull/328)
+
+* Replaced `BaseAddresses::set_cfi` with `set_eh_frame_hdr` and `set_eh_frame`.
+ Replaced `BaseAddresses::set_data` with `set_got`.
+ You should now use the same `BaseAddresses` value for parsing both
+ `.eh_frame` and `.eh_frame_hdr`.
+ [#351](https://github.com/gimli-rs/gimli/pull/351)
+
+* Renamed many types and functions related to `.debug_line`.
+ Renamed `LineNumberProgram` to `LineProgram`.
+ Renamed `IncompleteLineNumberProgram` to `IncompleteLineProgram`.
+ Renamed `CompleteLineNumberProgram` to `CompleteLineProgram`.
+ Renamed `LineNumberProgramHeader` to `LineProgramHeader`.
+ Renamed `LineNumberRow` to `LineRow`.
+ Renamed `StateMachine` to `LineRows`.
+ Renamed `Opcode` to `LineInstruction`.
+ Renamed `OpcodesIter` to `LineInstructions`.
+ Renamed `LineNumberSequence` to `LineSequence`.
+ [#359](https://github.com/gimli-rs/gimli/pull/359)
+
+* Added `Offset` type parameter to `AttributeValue`, `LineProgram`,
+ `IncompleteLineProgram`, `CompleteLineProgram`, `LineRows`, `LineInstruction`,
+ and `FileEntry`.
+ [#324](https://github.com/gimli-rs/gimli/pull/324)
+
+* Changed `FileEntry::path_name`, `FileEntry::directory`, and
+ `LineProgramHeader::directory` to return an `AttributeValue` instead
+ of a `Reader`.
+ [#366](https://github.com/gimli-rs/gimli/pull/366)
+
+* Renamed `FileEntry::last_modification` to `FileEntry::timestamp`
+ and renamed `FileEntry::length` to `FileEntry::size`.
+ [#366](https://github.com/gimli-rs/gimli/pull/366)
+
+* Added an `Encoding` type. Changed many functions that previously accepted
+ `Format`, version or address size parameters to accept an `Encoding`
+ parameter instead.
+ Notable changes are `LocationLists::locations`, `RangeLists::ranges`,
+ and `Expression::evaluation`.
+ [#364](https://github.com/gimli-rs/gimli/pull/364)
+
+* Changed return type of `LocationLists::new` and `RangeLists::new`.
+ [#370](https://github.com/gimli-rs/gimli/pull/370)
+
+* Added parameters to `LocationsLists::locations` and `RangeLists::ranges`
+ to support `.debug_addr`.
+ [#358](https://github.com/gimli-rs/gimli/pull/358)
+
+* Added more `AttributeValue` variants: `DebugAddrBase`, `DebugAddrIndex`,
+ `DebugLocListsBase`, `DebugLocListsIndex`, `DebugRngListsBase`, `DebugRngListsIndex`,
+ `DebugStrOffsetsBase`, `DebugStrOffsetsIndex`, `DebugLineStrRef`.
+ [#358](https://github.com/gimli-rs/gimli/pull/358)
+
+* Changed `AttributeValue::Data*` attributes to native endian integers instead
+ of byte arrays.
+ [#365](https://github.com/gimli-rs/gimli/pull/365)
+
+* Replaced `EvaluationResult::TextBase` with
+ `EvaluationResult::RequiresRelocatedAddress`. The handling of `TextBase`
+ was incorrect.
+ [#335](https://github.com/gimli-rs/gimli/pull/335)
+
+* Added `EvaluationResult::IndexedAddress` for operations that require an
+ address from `.debug_addr`.
+ [#358](https://github.com/gimli-rs/gimli/pull/358)
+
+* Added `Reader::read_slice`. Added a default implementation of
+ `Reader::read_u8_array` which uses this.
+ [#358](https://github.com/gimli-rs/gimli/pull/358)
+
+### Added
+
+* Added initial support for writing DWARF. This is targeted at supporting
+ line number information only.
+ [#340](https://github.com/gimli-rs/gimli/pull/340)
+ [#344](https://github.com/gimli-rs/gimli/pull/344)
+ [#346](https://github.com/gimli-rs/gimli/pull/346)
+ [#361](https://github.com/gimli-rs/gimli/pull/361)
+ [#362](https://github.com/gimli-rs/gimli/pull/362)
+ [#365](https://github.com/gimli-rs/gimli/pull/365)
+ [#368](https://github.com/gimli-rs/gimli/pull/368)
+ [#382](https://github.com/gimli-rs/gimli/pull/382)
+
+* Added `read` and `write` Cargo features. Both are enabled by default.
+ [#343](https://github.com/gimli-rs/gimli/pull/343)
+
+* Added support for reading DWARF 5 `.debug_line` and `.debug_line_str` sections.
+ [#366](https://github.com/gimli-rs/gimli/pull/366)
+
+* Added support for reading DWARF 5 `.debug_str_offsets` sections, including
+ parsing `DW_FORM_strx*` attributes.
+ [#358](https://github.com/gimli-rs/gimli/pull/358)
+
+* Added support for reading DWARF 5 `.debug_addr` sections, including parsing
+ `DW_FORM_addrx*` attributes and evaluating `DW_OP_addrx` and `DW_OP_constx`
+ operations.
+ [#358](https://github.com/gimli-rs/gimli/pull/358)
+
+* Added support for reading DWARF 5 indexed addresses and offsets in
+ `.debug_loclists` and `.debug_rnglists`, including parsing `DW_FORM_rnglistx`
+ and `DW_FORM_loclistx` attributes.
+ [#358](https://github.com/gimli-rs/gimli/pull/358)
+
+* Added high level `Dwarf` and `Unit` types. Existing code does not need to
+ switch to using these types, but doing so will make DWARF 5 support simpler.
+ [#352](https://github.com/gimli-rs/gimli/pull/352)
+ [#380](https://github.com/gimli-rs/gimli/pull/380)
+ [#381](https://github.com/gimli-rs/gimli/pull/381)
+
+* Added `EhFrame::set_address_size` and `DebugFrame::set_address_size` methods
+ to allow parsing non-native CFI sections. The default address size is still
+ the native size.
+ [#325](https://github.com/gimli-rs/gimli/pull/325)
+
+* Added architecture specific definitions for `Register` values and names.
+ Changed dwarfdump to print them.
+ [#328](https://github.com/gimli-rs/gimli/pull/328)
+
+* Added support for reading relocatable DWARF sections.
+ [#337](https://github.com/gimli-rs/gimli/pull/337)
+
+* Added parsing of `DW_FORM_data16`.
+ [#366](https://github.com/gimli-rs/gimli/pull/366)
+
+### Fixed
+
+* Fixed parsing DWARF 5 ranges with `start == end == 0`.
+ [#323](https://github.com/gimli-rs/gimli/pull/323)
+
+* Changed `LineRows` to be covariant in its `Reader` type parameter.
+ [#324](https://github.com/gimli-rs/gimli/pull/324)
+
+* Fixed handling of empty units in dwarfdump.
+ [#330](https://github.com/gimli-rs/gimli/pull/330)
+
+* Fixed `UnitHeader::length_including_self` for `Dwarf64`.
+ [#342](https://github.com/gimli-rs/gimli/pull/342)
+
+* Fixed parsing of `DW_CFA_set_loc`.
+ [#355](https://github.com/gimli-rs/gimli/pull/355)
+
+* Fixed handling of multiple headers in `.debug_loclists` and `.debug_rnglists`.
+ [#370](https://github.com/gimli-rs/gimli/pull/370)
+
+--------------------------------------------------------------------------------
+
+## 0.16.1
+
+Released 2018/08/28.
+
+### Added
+
+* Added `EhFrameHdr::lookup_and_parse`. [#316][]
+* Added support for `DW_CFA_GNU_args_size`. [#319][]
+
+### Fixed
+
+* Implement `Send`/`Sync` for `SubRange`. [#305][]
+* Fixed `alloc` support on nightly. [#306][] [#310][]
+
+[#305]: https://github.com/gimli-rs/gimli/pull/305
+[#306]: https://github.com/gimli-rs/gimli/pull/306
+[#310]: https://github.com/gimli-rs/gimli/pull/310
+[#316]: https://github.com/gimli-rs/gimli/pull/316
+[#319]: https://github.com/gimli-rs/gimli/pull/319
+
+--------------------------------------------------------------------------------
+
+## 0.16.0
+
+Released 2018/06/01.
+
+### Added
+
+* Added support for building in `#![no_std]` environments, when the `alloc`
+ crate is available. Disable the "std" feature and enable the "alloc"
+ feature. [#138][] [#271][]
+
+* Added support for DWARF 5 `.debug_rnglists` and `.debug_loclists`
+ sections. [#272][]
+
+* Added support for DWARF 5 `DW_FORM_ref_sup` and `DW_FORM_strp_sup` attribute
+ forms. [#288][]
+
+* Added support for DWARF 5 operations on typed values. [#293][]
+
+* A `dwarf-validate` example program that checks the integrity of the given
+ DWARF and its references between sections. [#290][]
+
+* Added the `EndianReader<T>` type, an easy way to define a custom `Reader`
+ implementation with a reference to a generic buffer of bytes and an associated
+ endianity. [#298][] [#302][]
+
+### Changed
+
+* Various speed improvements for evaluating `.debug_line` line number
+ programs. [#276][]
+
+* The example `dwarfdump` clone is a [whole lot faster
+ now][dwarfdump-faster]. [#282][] [#284][] [#285][]
+
+### Deprecated
+
+* `EndianBuf` has been renamed to `EndianSlice`, use that name instead. [#295][]
+
+### Fixed
+
+* Evaluating the `DW_CFA_restore_state` opcode properly maintains the current
+ location. Previously it would incorrectly restore the old location when
+ popping from evaluation stack. [#274][]
+
+[#271]: https://github.com/gimli-rs/gimli/issues/271
+[#138]: https://github.com/gimli-rs/gimli/issues/138
+[#274]: https://github.com/gimli-rs/gimli/issues/274
+[#272]: https://github.com/gimli-rs/gimli/issues/272
+[#276]: https://github.com/gimli-rs/gimli/issues/276
+[#282]: https://github.com/gimli-rs/gimli/issues/282
+[#285]: https://github.com/gimli-rs/gimli/issues/285
+[#284]: https://github.com/gimli-rs/gimli/issues/284
+[#288]: https://github.com/gimli-rs/gimli/issues/288
+[#290]: https://github.com/gimli-rs/gimli/issues/290
+[#293]: https://github.com/gimli-rs/gimli/issues/293
+[#295]: https://github.com/gimli-rs/gimli/issues/295
+[#298]: https://github.com/gimli-rs/gimli/issues/298
+[#302]: https://github.com/gimli-rs/gimli/issues/302
+[dwarfdump-faster]: https://robert.ocallahan.org/2018/03/speeding-up-dwarfdump-with-rust.html
+
+--------------------------------------------------------------------------------
+
+## 0.15.0
+
+Released 2017/12/01.
+
+### Added
+
+* Added the `EndianBuf::to_string()` method. [#233][]
+
+* Added more robust error handling in our example `dwarfdump` clone. [#234][]
+
+* Added `FrameDescriptionEntry::initial_address` method. [#237][]
+
+* Added `FrameDescriptionEntry::len` method. [#237][]
+
+* Added the `FrameDescriptionEntry::entry_len` method. [#241][]
+
+* Added the `CommonInformationEntry::offset` method. [#241][]
+
+* Added the `CommonInformationEntry::entry_len` method. [#241][]
+
+* Added the `CommonInformationEntry::version` method. [#241][]
+
+* Added the `CommonInformationEntry::augmentation` method. [#241][]
+
+* Added the `CommonInformationEntry::code_alignment_factor` method. [#241][]
+
+* Added the `CommonInformationEntry::data_alignment_factor` method. [#241][]
+
+* Added the `CommonInformationEntry::return_address_register` method. [#241][]
+
+* Added support for printing `.eh_frame` sections to our example `dwarfdump`
+ clone. [#241][]
+
+* Added support for parsing the `.eh_frame_hdr` section. On Linux, the
+ `.eh_frame_hdr` section provides a pointer to the already-mapped-in-memory
+ `.eh_frame` data, so that it doesn't need to be duplicated, and a binary
+ search table of its entries for faster unwinding information lookups. [#250][]
+
+* Added support for parsing DWARF 5 compilation unit headers. [#257][]
+
+* Added support for DWARF 5's `DW_FORM_implicit_const`. [#257][]
+
+### Changed
+
+* Unwinding methods now give ownership of the unwinding context back to the
+ caller if errors are encountered, not just on the success path. This allows
+ recovering from errors in signal-safe code, where constructing a new unwinding
+ context is not an option because it requires allocation. This is a **breaking
+ change** affecting `UnwindSection::unwind_info_for_address` and
+ `UninitializedUnwindContext::initialize`. [#241][]
+
+* `CfaRule` and `RegisterRule` now expose their `DW_OP` expressions as
+ `Expression`. This is a minor **breaking change**. [#241][]
+
+* The `Error::UnknownVersion` variant now contains the unknown version
+ number. This is a minor **breaking change**. [#245][]
+
+* `EvaluationResult::RequiresEntryValue` requires an `Expression` instead of a
+ `Reader` now. This is a minor **breaking change**. [#256][]
+
+
+[#233]: https://github.com/gimli-rs/gimli/pull/233
+[#234]: https://github.com/gimli-rs/gimli/pull/234
+[#237]: https://github.com/gimli-rs/gimli/pull/237
+[#241]: https://github.com/gimli-rs/gimli/pull/241
+[#245]: https://github.com/gimli-rs/gimli/pull/245
+[#250]: https://github.com/gimli-rs/gimli/pull/250
+[#256]: https://github.com/gimli-rs/gimli/pull/256
+[#257]: https://github.com/gimli-rs/gimli/pull/257
+
+--------------------------------------------------------------------------------
+
+## 0.14.0
+
+Released 2017/08/08.
+
+### Added
+
+* All `pub` types now `derive(Hash)`. [#192][]
+
+* All the constants from DWARF 5 are now defined. [#193][]
+
+* Added support for the `DW_OP_GNU_parameter_ref` GNU extension to parsing and
+ evaluation DWARF opcodes. [#208][]
+
+* Improved LEB128 parsing performance. [#216][]
+
+* Improved `.debug_{aranges,pubnames,pubtypes}` parsing performance. [#218][]
+
+* Added the ability to choose endianity dynamically at run time, rather than
+ only statically at compile time. [#219][]
+
+### Changed
+
+* The biggest change of this release is that `gimli` no longer requires the
+ object file's section be fully loaded into memory. This enables using `gimli`
+ on 32 bit platforms where there often isn't enough contiguous virtual memory
+ address space to load debugging information into. The default behavior is
+ still geared for 64 bit platforms, where address space overfloweth, and you
+ can still load the whole sections of the object file (or the entire object
+ file) into memory. This is abstracted over with the `gimli::Reader`
+ trait. This manifests as small (but many) breaking changes to much of the
+ public API. [#182][]
+
+### Fixed
+
+* The `DW_END_*` constants for defining endianity of a compilation unit were
+ previously incorrect. [#193][]
+
+* The `DW_OP_addr` opcode is relative to the base address of the `.text` section
+ of the binary, but we were incorrectly treating it as an absolute value. [#210][]
+
+[GitHub]: https://github.com/gimli-rs/gimli
+[crates.io]: https://crates.io/crates/gimli
+[contributing]: https://github.com/gimli-rs/gimli/blob/master/CONTRIBUTING.md
+[easy]: https://github.com/gimli-rs/gimli/issues?q=is%3Aopen+is%3Aissue+label%3Aeasy
+[#192]: https://github.com/gimli-rs/gimli/pull/192
+[#193]: https://github.com/gimli-rs/gimli/pull/193
+[#182]: https://github.com/gimli-rs/gimli/issues/182
+[#208]: https://github.com/gimli-rs/gimli/pull/208
+[#210]: https://github.com/gimli-rs/gimli/pull/210
+[#216]: https://github.com/gimli-rs/gimli/pull/216
+[#218]: https://github.com/gimli-rs/gimli/pull/218
+[#219]: https://github.com/gimli-rs/gimli/pull/219
diff --git a/vendor/gimli-0.26.2/CONTRIBUTING.md b/vendor/gimli-0.26.2/CONTRIBUTING.md
new file mode 100644
index 000000000..4f9e574ce
--- /dev/null
+++ b/vendor/gimli-0.26.2/CONTRIBUTING.md
@@ -0,0 +1,137 @@
+# Contributing to `gimli`
+
+Hi! We'd love to have your contributions! If you want help or mentorship, reach
+out to us in a GitHub issue, or ping `fitzgen` in `#rust` on `irc.mozilla.org`.
+
+* [Code of Conduct](#coc)
+* [Filing an Issue](#issues)
+* [Building `gimli`](#building)
+* [Testing `gimli`](#testing)
+ * [Test Coverage](#coverage)
+ * [Using `test-assembler`](#test-assembler)
+ * [Fuzzing](#fuzzing)
+* [Benchmarking](#benchmarking)
+* [Style](#style)
+
+## <a id="coc"></a> Code of Conduct
+
+We abide by the
+[Rust Code of Conduct](https://www.rust-lang.org/en-US/conduct.html) and ask
+that you do as well.
+
+## <a id="issues"></a> Filing an Issue
+
+Think you've found a bug? File an issue! To help us understand and reproduce the
+issue, provide us with:
+
+* The (preferably minimal) test case
+* Steps to reproduce the issue using the test case
+* The expected result of following those steps
+* The actual result of following those steps
+
+Definitely file an issue if you see an unexpected panic originating from within
+`gimli`! `gimli` should never panic unless it is explicitly documented to panic
+in the specific circumstances provided.
+
+## <a id="building"></a> Building `gimli`
+
+`gimli` should always build on stable `rustc`, but we recommend using
+[`rustup`](https://www.rustup.rs/) so you can switch to nightly `rustc` and run
+benchmarks.
+
+To build `gimli`:
+
+```
+$ cargo build
+```
+
+## <a id="testing"></a> Testing `gimli`
+
+Run the tests with `cargo`:
+
+```
+$ cargo test
+```
+
+### <a id="coverage"></a> Test Coverage
+
+If you have `kcov` installed under linux, then you can generate code coverage
+results using the `coverage` script in the root of the repository, and view them
+at `target/kcov/index.html`. Otherwise you can create a pull request and view
+the coverage results on coveralls.io.
+
+```
+$ ./coverage
+```
+
+The ideal we aim to reach is having our unit tests exercise every branch in
+`gimli`. We allow an exception for branches which propagate errors inside a
+`try!(..)` invocation, but we *do* want to exercise the original error paths.
+
+Pull requests adding new code should ensure that this ideal is met.
+
+At the time of writing we have 94% test coverage according to our coveralls.io
+continuous integration. That number should generally stay the same or go up ;)
+This is a bit subjective, because -.001% is just noise and doesn't matter.
+
+### <a id="test-assembler"></a> Using `test-assembler`
+
+We use the awesome
+[`test-assembler`](https://github.com/luser/rust-test-assembler) crate to
+construct binary test data. It makes building complex test cases readable.
+
+[Here is an example usage in `gimli`](https://github.com/gimli-rs/gimli/blob/156451f3fe6eeb2fa62b84b362c33fcb176e1171/src/loc.rs#L263)
+
+### <a id="fuzzing"></a> Fuzzing
+
+First, install `cargo fuzz`:
+
+```
+$ cargo install cargo-fuzz
+```
+
+Optionally, [set up the corpora for our fuzz targets by following these
+instructions](https://github.com/gimli-rs/gimli-libfuzzer-corpora/blob/master/README.md#using-these-corpora).
+
+Finally, run a fuzz target! In this case, we are running the `eh_frame` fuzz
+target:
+
+```
+$ cargo fuzz run eh_frame
+```
+
+The fuzz target definitions live in `fuzz/fuzz_targets/*`. You can add new ones
+via `cargo fuzz add <my_new_target>`.
+
+## <a id="benchmarking"></a> Benchmarking
+
+The benchmarks require nightly `rustc`, so use `rustup`:
+
+```
+$ rustup run nightly cargo bench
+```
+
+We aim to be the fastest DWARF library. Period.
+
+Please provide before and after benchmark results with your pull requests. You
+may also find [`cargo benchcmp`](https://github.com/BurntSushi/cargo-benchcmp)
+handy for comparing results.
+
+Pull requests adding `#[bench]` micro-benchmarks that exercise a new edge case
+are very welcome!
+
+## <a id="style"></a> Style
+
+We use `rustfmt` to automatically format and style all of our code.
+
+To install `rustfmt`:
+
+```
+$ rustup component add rustfmt-preview
+```
+
+To run `rustfmt` on `gimli`:
+
+```
+$ cargo fmt
+```
diff --git a/vendor/gimli-0.26.2/Cargo.lock b/vendor/gimli-0.26.2/Cargo.lock
new file mode 100644
index 000000000..b4a719a0c
--- /dev/null
+++ b/vendor/gimli-0.26.2/Cargo.lock
@@ -0,0 +1,358 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+version = 3
+
+[[package]]
+name = "adler"
+version = "1.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
+
+[[package]]
+name = "aho-corasick"
+version = "0.7.18"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1e37cfd5e7657ada45f742d6e99ca5788580b5c529dc78faf11ece6dc702656f"
+dependencies = [
+ "memchr",
+]
+
+[[package]]
+name = "autocfg"
+version = "1.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a"
+
+[[package]]
+name = "byteorder"
+version = "1.4.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"
+
+[[package]]
+name = "cfg-if"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
+
+[[package]]
+name = "compiler_builtins"
+version = "0.1.51"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3587b3669d6f2c1cfd34c475272dabcfef29d52703933f6f72ebb36d6bd81a97"
+
+[[package]]
+name = "crc32fast"
+version = "1.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "81156fece84ab6a9f2afdb109ce3ae577e42b1228441eded99bd77f627953b1a"
+dependencies = [
+ "cfg-if",
+]
+
+[[package]]
+name = "crossbeam"
+version = "0.8.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4ae5588f6b3c3cb05239e90bd110f257254aecd01e4635400391aeae07497845"
+dependencies = [
+ "cfg-if",
+ "crossbeam-channel",
+ "crossbeam-deque",
+ "crossbeam-epoch",
+ "crossbeam-queue",
+ "crossbeam-utils",
+]
+
+[[package]]
+name = "crossbeam-channel"
+version = "0.5.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "06ed27e177f16d65f0f0c22a213e17c696ace5dd64b14258b52f9417ccb52db4"
+dependencies = [
+ "cfg-if",
+ "crossbeam-utils",
+]
+
+[[package]]
+name = "crossbeam-deque"
+version = "0.8.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6455c0ca19f0d2fbf751b908d5c55c1f5cbc65e03c4225427254b46890bdde1e"
+dependencies = [
+ "cfg-if",
+ "crossbeam-epoch",
+ "crossbeam-utils",
+]
+
+[[package]]
+name = "crossbeam-epoch"
+version = "0.9.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4ec02e091aa634e2c3ada4a392989e7c3116673ef0ac5b72232439094d73b7fd"
+dependencies = [
+ "cfg-if",
+ "crossbeam-utils",
+ "lazy_static",
+ "memoffset",
+ "scopeguard",
+]
+
+[[package]]
+name = "crossbeam-queue"
+version = "0.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9b10ddc024425c88c2ad148c1b0fd53f4c6d38db9697c9f1588381212fa657c9"
+dependencies = [
+ "cfg-if",
+ "crossbeam-utils",
+]
+
+[[package]]
+name = "crossbeam-utils"
+version = "0.8.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d82cfc11ce7f2c3faef78d8a684447b40d503d9681acebed6cb728d45940c4db"
+dependencies = [
+ "cfg-if",
+ "lazy_static",
+]
+
+[[package]]
+name = "either"
+version = "1.6.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457"
+
+[[package]]
+name = "fallible-iterator"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4443176a9f2c162692bd3d352d745ef9413eec5782a80d8fd6f8a1ac692a07f7"
+
+[[package]]
+name = "flate2"
+version = "1.0.22"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1e6988e897c1c9c485f43b47a529cef42fde0547f9d8d41a7062518f1d8fc53f"
+dependencies = [
+ "cfg-if",
+ "crc32fast",
+ "libc",
+ "miniz_oxide",
+]
+
+[[package]]
+name = "getopts"
+version = "0.2.21"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "14dbbfd5c71d70241ecf9e6f13737f7b5ce823821063188d7e46c41d371eebd5"
+dependencies = [
+ "unicode-width",
+]
+
+[[package]]
+name = "gimli"
+version = "0.26.2"
+dependencies = [
+ "compiler_builtins",
+ "crossbeam",
+ "fallible-iterator",
+ "getopts",
+ "indexmap",
+ "memmap2",
+ "num_cpus",
+ "object",
+ "rayon",
+ "regex",
+ "rustc-std-workspace-alloc",
+ "rustc-std-workspace-core",
+ "stable_deref_trait",
+ "test-assembler",
+ "typed-arena",
+]
+
+[[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",
+]
+
+[[package]]
+name = "indexmap"
+version = "1.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bc633605454125dec4b66843673f01c7df2b89479b32e0ed634e43a91cff62a5"
+dependencies = [
+ "autocfg",
+ "hashbrown",
+]
+
+[[package]]
+name = "lazy_static"
+version = "1.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
+
+[[package]]
+name = "libc"
+version = "0.2.105"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "869d572136620d55835903746bcb5cdc54cb2851fd0aeec53220b4bb65ef3013"
+
+[[package]]
+name = "memchr"
+version = "2.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a"
+
+[[package]]
+name = "memmap2"
+version = "0.5.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3a79b39c93a7a5a27eeaf9a23b5ff43f1b9e0ad6b1cdd441140ae53c35613fc7"
+dependencies = [
+ "libc",
+]
+
+[[package]]
+name = "memoffset"
+version = "0.6.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "59accc507f1338036a0477ef61afdae33cde60840f4dfe481319ce3ad116ddf9"
+dependencies = [
+ "autocfg",
+]
+
+[[package]]
+name = "miniz_oxide"
+version = "0.4.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a92518e98c078586bc6c934028adcca4c92a53d6a958196de835170a01d84e4b"
+dependencies = [
+ "adler",
+ "autocfg",
+]
+
+[[package]]
+name = "num_cpus"
+version = "1.13.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "05499f3756671c15885fee9034446956fff3f243d6077b91e5767df161f766b3"
+dependencies = [
+ "hermit-abi",
+ "libc",
+]
+
+[[package]]
+name = "object"
+version = "0.29.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "21158b2c33aa6d4561f1c0a6ea283ca92bc54802a93b263e910746d679a7eb53"
+dependencies = [
+ "flate2",
+ "memchr",
+ "wasmparser",
+]
+
+[[package]]
+name = "rayon"
+version = "1.5.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c06aca804d41dbc8ba42dfd964f0d01334eceb64314b9ecf7c5fad5188a06d90"
+dependencies = [
+ "autocfg",
+ "crossbeam-deque",
+ "either",
+ "rayon-core",
+]
+
+[[package]]
+name = "rayon-core"
+version = "1.9.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d78120e2c850279833f1dd3582f730c4ab53ed95aeaaaa862a2a5c71b1656d8e"
+dependencies = [
+ "crossbeam-channel",
+ "crossbeam-deque",
+ "crossbeam-utils",
+ "lazy_static",
+ "num_cpus",
+]
+
+[[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 = "rustc-std-workspace-alloc"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ff66d57013a5686e1917ed6a025d54dd591fcda71a41fe07edf4d16726aefa86"
+
+[[package]]
+name = "rustc-std-workspace-core"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1956f5517128a2b6f23ab2dadf1a976f4f5b27962e7724c2bf3d45e539ec098c"
+
+[[package]]
+name = "scopeguard"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
+
+[[package]]
+name = "stable_deref_trait"
+version = "1.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3"
+
+[[package]]
+name = "test-assembler"
+version = "0.1.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9a6da51de149453f5c43fa67d5e73cccd75b3c5727a38a2f18c5f3c47f2db582"
+dependencies = [
+ "byteorder",
+]
+
+[[package]]
+name = "typed-arena"
+version = "2.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0685c84d5d54d1c26f7d3eb96cd41550adb97baed141a761cf335d3d33bcd0ae"
+
+[[package]]
+name = "unicode-width"
+version = "0.1.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3ed742d4ea2bd1176e236172c8429aaf54486e7ac098db29ffe6529e0ce50973"
+
+[[package]]
+name = "wasmparser"
+version = "0.57.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "32fddd575d477c6e9702484139cf9f23dcd554b06d185ed0f56c857dd3a47aa6"
diff --git a/vendor/gimli-0.26.2/Cargo.toml b/vendor/gimli-0.26.2/Cargo.toml
new file mode 100644
index 000000000..f36ccd936
--- /dev/null
+++ b/vendor/gimli-0.26.2/Cargo.toml
@@ -0,0 +1,146 @@
+# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
+#
+# When uploading crates to the registry Cargo will automatically
+# "normalize" Cargo.toml files for maximal compatibility
+# with all versions of Cargo and also rewrite `path` dependencies
+# to registry (e.g., crates.io) dependencies.
+#
+# If you are reading this file be aware that the original Cargo.toml
+# will likely look very different (and much more reasonable).
+# See Cargo.toml.orig for the original contents.
+
+[package]
+edition = "2018"
+name = "gimli"
+version = "0.26.2"
+exclude = [
+ "/releases/*",
+ "/.github",
+]
+description = "A library for reading and writing the DWARF debugging format."
+documentation = "https://docs.rs/gimli"
+readme = "./README.md"
+keywords = [
+ "DWARF",
+ "debug",
+ "ELF",
+ "eh_frame",
+]
+categories = [
+ "development-tools::debugging",
+ "development-tools::profiling",
+ "parser-implementations",
+]
+license = "MIT OR Apache-2.0"
+repository = "https://github.com/gimli-rs/gimli"
+
+[profile.bench]
+codegen-units = 1
+debug = true
+split-debuginfo = "packed"
+
+[profile.test]
+split-debuginfo = "packed"
+
+[[example]]
+name = "simple"
+required-features = ["read"]
+
+[[example]]
+name = "simple_line"
+required-features = ["read"]
+
+[[example]]
+name = "dwarfdump"
+required-features = [
+ "read",
+ "std",
+]
+
+[[example]]
+name = "dwarf-validate"
+required-features = [
+ "read",
+ "std",
+]
+
+[dependencies.alloc]
+version = "1.0.0"
+optional = true
+package = "rustc-std-workspace-alloc"
+
+[dependencies.compiler_builtins]
+version = "0.1.2"
+optional = true
+
+[dependencies.core]
+version = "1.0.0"
+optional = true
+package = "rustc-std-workspace-core"
+
+[dependencies.fallible-iterator]
+version = "0.2.0"
+optional = true
+default-features = false
+
+[dependencies.indexmap]
+version = "1.0.2"
+optional = true
+
+[dependencies.stable_deref_trait]
+version = "1.1.0"
+optional = true
+default-features = false
+
+[dev-dependencies.crossbeam]
+version = "0.8"
+
+[dev-dependencies.getopts]
+version = "0.2"
+
+[dev-dependencies.memmap2]
+version = "0.5.5"
+
+[dev-dependencies.num_cpus]
+version = "1"
+
+[dev-dependencies.object]
+version = "0.29.0"
+features = ["wasm"]
+
+[dev-dependencies.rayon]
+version = "1.0"
+
+[dev-dependencies.regex]
+version = "1"
+
+[dev-dependencies.test-assembler]
+version = "0.1.3"
+
+[dev-dependencies.typed-arena]
+version = "2"
+
+[features]
+default = [
+ "read",
+ "write",
+ "std",
+ "fallible-iterator",
+ "endian-reader",
+]
+endian-reader = [
+ "read",
+ "stable_deref_trait",
+]
+read = ["read-core"]
+read-core = []
+rustc-dep-of-std = [
+ "core",
+ "alloc",
+ "compiler_builtins",
+]
+std = [
+ "fallible-iterator/std",
+ "stable_deref_trait/std",
+]
+write = ["indexmap"]
diff --git a/vendor/gimli-0.26.2/LICENSE-APACHE b/vendor/gimli-0.26.2/LICENSE-APACHE
new file mode 100644
index 000000000..16fe87b06
--- /dev/null
+++ b/vendor/gimli-0.26.2/LICENSE-APACHE
@@ -0,0 +1,201 @@
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+END OF TERMS AND CONDITIONS
+
+APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+Copyright [yyyy] [name of copyright owner]
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
diff --git a/vendor/gimli-0.26.2/LICENSE-MIT b/vendor/gimli-0.26.2/LICENSE-MIT
new file mode 100644
index 000000000..e69282e38
--- /dev/null
+++ b/vendor/gimli-0.26.2/LICENSE-MIT
@@ -0,0 +1,25 @@
+Copyright (c) 2015 The Rust Project Developers
+
+Permission is hereby granted, free of charge, to any
+person obtaining a copy of this software and associated
+documentation files (the "Software"), to deal in the
+Software without restriction, including without
+limitation the rights to use, copy, modify, merge,
+publish, distribute, sublicense, and/or sell copies of
+the Software, and to permit persons to whom the Software
+is furnished to do so, subject to the following
+conditions:
+
+The above copyright notice and this permission notice
+shall be included in all copies or substantial portions
+of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
+ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
+TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
+SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
+IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
diff --git a/vendor/gimli-0.26.2/README.md b/vendor/gimli-0.26.2/README.md
new file mode 100644
index 000000000..19e7bbd0e
--- /dev/null
+++ b/vendor/gimli-0.26.2/README.md
@@ -0,0 +1,78 @@
+# `gimli`
+
+[![](https://img.shields.io/crates/v/gimli.svg) ![](https://img.shields.io/crates/d/gimli.svg)](https://crates.io/crates/gimli)
+[![](https://docs.rs/gimli/badge.svg)](https://docs.rs/gimli/)
+[![Build Status](https://github.com/gimli-rs/gimli/workflows/Rust/badge.svg)](https://github.com/gimli-rs/gimli/actions)
+[![Coverage Status](https://coveralls.io/repos/github/gimli-rs/gimli/badge.svg?branch=master)](https://coveralls.io/github/gimli-rs/gimli?branch=master)
+
+`gimli` is a blazing fast library for consuming the
+[DWARF debugging format](https://dwarfstd.org/).
+
+* **Zero copy:** everything is just a reference to the original input buffer. No
+ copies of the input data get made.
+
+* **Lazy:** you can iterate compilation units without parsing their
+ contents. Parse only as many debugging information entry (DIE) trees as you
+ iterate over. `gimli` also uses `DW_AT_sibling` references to avoid parsing a
+ DIE's children to find its next sibling, when possible.
+
+* **Cross-platform:** `gimli` makes no assumptions about what kind of object
+ file you're working with. The flipside to that is that it's up to you to
+ provide an ELF loader on Linux or Mach-O loader on macOS.
+
+ * Unsure which object file parser to use? Try the cross-platform
+ [`object`](https://github.com/gimli-rs/object) crate. See the
+ [`examples/`](./examples) directory for usage with `gimli`.
+
+## Install
+
+Add this to your `Cargo.toml`:
+
+```toml
+[dependencies]
+gimli = "0.26.2"
+```
+
+The minimum supported Rust version is 1.42.0.
+
+## Documentation
+
+* [Documentation on docs.rs](https://docs.rs/gimli/)
+
+* Example programs:
+
+ * [A simple `.debug_info` parser](./examples/simple.rs)
+
+ * [A simple `.debug_line` parser](./examples/simple_line.rs)
+
+ * [A `dwarfdump` clone](./examples/dwarfdump.rs)
+
+ * [An `addr2line` clone](https://github.com/gimli-rs/addr2line)
+
+ * [`ddbug`](https://github.com/gimli-rs/ddbug), a utility giving insight into
+ code generation by making debugging information readable.
+
+ * [`dwprod`](https://github.com/fitzgen/dwprod), a tiny utility to list the
+ compilers used to create each compilation unit within a shared library or
+ executable (via `DW_AT_producer`).
+
+ * [`dwarf-validate`](./examples/dwarf-validate.rs), a program to validate the
+ integrity of some DWARF and its references between sections and compilation
+ units.
+
+## License
+
+Licensed under either of
+
+ * Apache License, Version 2.0 ([`LICENSE-APACHE`](./LICENSE-APACHE) or https://www.apache.org/licenses/LICENSE-2.0)
+ * MIT license ([`LICENSE-MIT`](./LICENSE-MIT) or https://opensource.org/licenses/MIT)
+
+at your option.
+
+## Contribution
+
+See [CONTRIBUTING.md](./CONTRIBUTING.md) for hacking.
+
+Unless you explicitly state otherwise, any contribution intentionally submitted
+for inclusion in the work by you, as defined in the Apache-2.0 license, shall be
+dual licensed as above, without any additional terms or conditions.
diff --git a/vendor/gimli-0.26.2/benches/bench.rs b/vendor/gimli-0.26.2/benches/bench.rs
new file mode 100644
index 000000000..fb29df77c
--- /dev/null
+++ b/vendor/gimli-0.26.2/benches/bench.rs
@@ -0,0 +1,807 @@
+#![feature(test)]
+
+extern crate test;
+
+use gimli::{
+ AttributeValue, DebugAbbrev, DebugAddr, DebugAddrBase, DebugAranges, DebugInfo, DebugLine,
+ DebugLineOffset, DebugLoc, DebugLocLists, DebugPubNames, DebugPubTypes, DebugRanges,
+ DebugRngLists, Encoding, EndianSlice, EntriesTreeNode, Expression, LittleEndian, LocationLists,
+ Operation, RangeLists, RangeListsOffset, Reader, ReaderOffset,
+};
+use std::env;
+use std::fs::File;
+use std::io::Read;
+use std::path::PathBuf;
+use std::rc::Rc;
+
+pub fn read_section(section: &str) -> Vec<u8> {
+ let mut path = PathBuf::from(env::var("CARGO_MANIFEST_DIR").unwrap_or_else(|_| ".".into()));
+ path.push("./fixtures/self/");
+ path.push(section);
+
+ assert!(path.is_file());
+ let mut file = File::open(path).unwrap();
+
+ let mut buf = Vec::new();
+ file.read_to_end(&mut buf).unwrap();
+ buf
+}
+
+#[bench]
+fn bench_parsing_debug_abbrev(b: &mut test::Bencher) {
+ let debug_info = read_section("debug_info");
+ let debug_info = DebugInfo::new(&debug_info, LittleEndian);
+ let unit = debug_info
+ .units()
+ .next()
+ .expect("Should have at least one compilation unit")
+ .expect("And it should parse OK");
+
+ let debug_abbrev = read_section("debug_abbrev");
+
+ b.iter(|| {
+ let debug_abbrev = DebugAbbrev::new(&debug_abbrev, LittleEndian);
+ test::black_box(
+ unit.abbreviations(&debug_abbrev)
+ .expect("Should parse abbreviations"),
+ );
+ });
+}
+
+#[inline]
+fn impl_bench_parsing_debug_info<R: Reader>(
+ debug_info: DebugInfo<R>,
+ debug_abbrev: DebugAbbrev<R>,
+) {
+ let mut iter = debug_info.units();
+ while let Some(unit) = iter.next().expect("Should parse compilation unit") {
+ let abbrevs = unit
+ .abbreviations(&debug_abbrev)
+ .expect("Should parse abbreviations");
+
+ let mut cursor = unit.entries(&abbrevs);
+ while let Some((_, entry)) = cursor.next_dfs().expect("Should parse next dfs") {
+ let mut attrs = entry.attrs();
+ loop {
+ match attrs.next() {
+ Ok(Some(ref attr)) => {
+ test::black_box(attr);
+ }
+ Ok(None) => break,
+ e @ Err(_) => {
+ e.expect("Should parse entry's attribute");
+ }
+ }
+ }
+ }
+ }
+}
+
+#[bench]
+fn bench_parsing_debug_info(b: &mut test::Bencher) {
+ let debug_info = read_section("debug_info");
+ let debug_info = DebugInfo::new(&debug_info, LittleEndian);
+
+ let debug_abbrev = read_section("debug_abbrev");
+ let debug_abbrev = DebugAbbrev::new(&debug_abbrev, LittleEndian);
+
+ b.iter(|| impl_bench_parsing_debug_info(debug_info, debug_abbrev));
+}
+
+#[bench]
+fn bench_parsing_debug_info_with_endian_rc_slice(b: &mut test::Bencher) {
+ let debug_info = read_section("debug_info");
+ let debug_info = Rc::from(&debug_info[..]);
+ let debug_info = gimli::EndianRcSlice::new(debug_info, LittleEndian);
+ let debug_info = DebugInfo::from(debug_info);
+
+ let debug_abbrev = read_section("debug_abbrev");
+ let debug_abbrev = Rc::from(&debug_abbrev[..]);
+ let debug_abbrev = gimli::EndianRcSlice::new(debug_abbrev, LittleEndian);
+ let debug_abbrev = DebugAbbrev::from(debug_abbrev);
+
+ b.iter(|| impl_bench_parsing_debug_info(debug_info.clone(), debug_abbrev.clone()));
+}
+
+#[bench]
+fn bench_parsing_debug_info_tree(b: &mut test::Bencher) {
+ let debug_abbrev = read_section("debug_abbrev");
+ let debug_abbrev = DebugAbbrev::new(&debug_abbrev, LittleEndian);
+
+ let debug_info = read_section("debug_info");
+
+ b.iter(|| {
+ let debug_info = DebugInfo::new(&debug_info, LittleEndian);
+
+ let mut iter = debug_info.units();
+ while let Some(unit) = iter.next().expect("Should parse compilation unit") {
+ let abbrevs = unit
+ .abbreviations(&debug_abbrev)
+ .expect("Should parse abbreviations");
+
+ let mut tree = unit
+ .entries_tree(&abbrevs, None)
+ .expect("Should have entries tree");
+ let root = tree.root().expect("Should parse root entry");
+ parse_debug_info_tree(root);
+ }
+ });
+}
+
+fn parse_debug_info_tree<R: Reader>(node: EntriesTreeNode<R>) {
+ {
+ let mut attrs = node.entry().attrs();
+ loop {
+ match attrs.next() {
+ Ok(Some(ref attr)) => {
+ test::black_box(attr);
+ }
+ Ok(None) => break,
+ e @ Err(_) => {
+ e.expect("Should parse entry's attribute");
+ }
+ }
+ }
+ }
+ let mut children = node.children();
+ while let Some(child) = children.next().expect("Should parse child entry") {
+ parse_debug_info_tree(child);
+ }
+}
+
+#[bench]
+fn bench_parsing_debug_info_raw(b: &mut test::Bencher) {
+ let debug_abbrev = read_section("debug_abbrev");
+ let debug_abbrev = DebugAbbrev::new(&debug_abbrev, LittleEndian);
+
+ let debug_info = read_section("debug_info");
+
+ b.iter(|| {
+ let debug_info = DebugInfo::new(&debug_info, LittleEndian);
+
+ let mut iter = debug_info.units();
+ while let Some(unit) = iter.next().expect("Should parse compilation unit") {
+ let abbrevs = unit
+ .abbreviations(&debug_abbrev)
+ .expect("Should parse abbreviations");
+
+ let mut raw = unit
+ .entries_raw(&abbrevs, None)
+ .expect("Should have entries");
+ while !raw.is_empty() {
+ if let Some(abbrev) = raw
+ .read_abbreviation()
+ .expect("Should parse abbreviation code")
+ {
+ for spec in abbrev.attributes().iter().cloned() {
+ match raw.read_attribute(spec) {
+ Ok(ref attr) => {
+ test::black_box(attr);
+ }
+ e @ Err(_) => {
+ e.expect("Should parse attribute");
+ }
+ }
+ }
+ }
+ }
+ }
+ });
+}
+
+#[bench]
+fn bench_parsing_debug_aranges(b: &mut test::Bencher) {
+ let debug_aranges = read_section("debug_aranges");
+ let debug_aranges = DebugAranges::new(&debug_aranges, LittleEndian);
+
+ b.iter(|| {
+ let mut headers = debug_aranges.headers();
+ while let Some(header) = headers.next().expect("Should parse arange header OK") {
+ let mut entries = header.entries();
+ while let Some(arange) = entries.next().expect("Should parse arange entry OK") {
+ test::black_box(arange);
+ }
+ }
+ });
+}
+
+#[bench]
+fn bench_parsing_debug_pubnames(b: &mut test::Bencher) {
+ let debug_pubnames = read_section("debug_pubnames");
+ let debug_pubnames = DebugPubNames::new(&debug_pubnames, LittleEndian);
+
+ b.iter(|| {
+ let mut pubnames = debug_pubnames.items();
+ while let Some(pubname) = pubnames.next().expect("Should parse pubname OK") {
+ test::black_box(pubname);
+ }
+ });
+}
+
+#[bench]
+fn bench_parsing_debug_pubtypes(b: &mut test::Bencher) {
+ let debug_pubtypes = read_section("debug_pubtypes");
+ let debug_pubtypes = DebugPubTypes::new(&debug_pubtypes, LittleEndian);
+
+ b.iter(|| {
+ let mut pubtypes = debug_pubtypes.items();
+ while let Some(pubtype) = pubtypes.next().expect("Should parse pubtype OK") {
+ test::black_box(pubtype);
+ }
+ });
+}
+
+// We happen to know that there is a line number program and header at
+// offset 0 and that address size is 8 bytes. No need to parse DIEs to grab
+// this info off of the compilation units.
+const OFFSET: DebugLineOffset = DebugLineOffset(0);
+const ADDRESS_SIZE: u8 = 8;
+
+#[bench]
+fn bench_parsing_line_number_program_opcodes(b: &mut test::Bencher) {
+ let debug_line = read_section("debug_line");
+ let debug_line = DebugLine::new(&debug_line, LittleEndian);
+
+ b.iter(|| {
+ let program = debug_line
+ .program(OFFSET, ADDRESS_SIZE, None, None)
+ .expect("Should parse line number program header");
+ let header = program.header();
+
+ let mut instructions = header.instructions();
+ while let Some(instruction) = instructions
+ .next_instruction(header)
+ .expect("Should parse instruction")
+ {
+ test::black_box(instruction);
+ }
+ });
+}
+
+#[bench]
+fn bench_executing_line_number_programs(b: &mut test::Bencher) {
+ let debug_line = read_section("debug_line");
+ let debug_line = DebugLine::new(&debug_line, LittleEndian);
+
+ b.iter(|| {
+ let program = debug_line
+ .program(OFFSET, ADDRESS_SIZE, None, None)
+ .expect("Should parse line number program header");
+
+ let mut rows = program.rows();
+ while let Some(row) = rows
+ .next_row()
+ .expect("Should parse and execute all rows in the line number program")
+ {
+ test::black_box(row);
+ }
+ });
+}
+
+#[bench]
+fn bench_parsing_debug_loc(b: &mut test::Bencher) {
+ let debug_info = read_section("debug_info");
+ let debug_info = DebugInfo::new(&debug_info, LittleEndian);
+
+ let debug_abbrev = read_section("debug_abbrev");
+ let debug_abbrev = DebugAbbrev::new(&debug_abbrev, LittleEndian);
+
+ let debug_addr = DebugAddr::from(EndianSlice::new(&[], LittleEndian));
+ let debug_addr_base = DebugAddrBase(0);
+
+ let debug_loc = read_section("debug_loc");
+ let debug_loc = DebugLoc::new(&debug_loc, LittleEndian);
+ let debug_loclists = DebugLocLists::new(&[], LittleEndian);
+ let loclists = LocationLists::new(debug_loc, debug_loclists);
+
+ let mut offsets = Vec::new();
+
+ let mut iter = debug_info.units();
+ while let Some(unit) = iter.next().expect("Should parse compilation unit") {
+ let abbrevs = unit
+ .abbreviations(&debug_abbrev)
+ .expect("Should parse abbreviations");
+
+ let mut cursor = unit.entries(&abbrevs);
+ cursor.next_dfs().expect("Should parse next dfs");
+
+ let mut low_pc = 0;
+
+ {
+ let unit_entry = cursor.current().expect("Should have a root entry");
+ let low_pc_attr = unit_entry
+ .attr_value(gimli::DW_AT_low_pc)
+ .expect("Should parse low_pc");
+ if let Some(gimli::AttributeValue::Addr(address)) = low_pc_attr {
+ low_pc = address;
+ }
+ }
+
+ while cursor.next_dfs().expect("Should parse next dfs").is_some() {
+ let entry = cursor.current().expect("Should have a current entry");
+ let mut attrs = entry.attrs();
+ while let Some(attr) = attrs.next().expect("Should parse entry's attribute") {
+ if let gimli::AttributeValue::LocationListsRef(offset) = attr.value() {
+ offsets.push((offset, unit.encoding(), low_pc));
+ }
+ }
+ }
+ }
+
+ b.iter(|| {
+ for &(offset, encoding, base_address) in &*offsets {
+ let mut locs = loclists
+ .locations(offset, encoding, base_address, &debug_addr, debug_addr_base)
+ .expect("Should parse locations OK");
+ while let Some(loc) = locs.next().expect("Should parse next location") {
+ test::black_box(loc);
+ }
+ }
+ });
+}
+
+#[bench]
+fn bench_parsing_debug_ranges(b: &mut test::Bencher) {
+ let debug_info = read_section("debug_info");
+ let debug_info = DebugInfo::new(&debug_info, LittleEndian);
+
+ let debug_abbrev = read_section("debug_abbrev");
+ let debug_abbrev = DebugAbbrev::new(&debug_abbrev, LittleEndian);
+
+ let debug_addr = DebugAddr::from(EndianSlice::new(&[], LittleEndian));
+ let debug_addr_base = DebugAddrBase(0);
+
+ let debug_ranges = read_section("debug_ranges");
+ let debug_ranges = DebugRanges::new(&debug_ranges, LittleEndian);
+ let debug_rnglists = DebugRngLists::new(&[], LittleEndian);
+ let rnglists = RangeLists::new(debug_ranges, debug_rnglists);
+
+ let mut offsets = Vec::new();
+
+ let mut iter = debug_info.units();
+ while let Some(unit) = iter.next().expect("Should parse compilation unit") {
+ let abbrevs = unit
+ .abbreviations(&debug_abbrev)
+ .expect("Should parse abbreviations");
+
+ let mut cursor = unit.entries(&abbrevs);
+ cursor.next_dfs().expect("Should parse next dfs");
+
+ let mut low_pc = 0;
+
+ {
+ let unit_entry = cursor.current().expect("Should have a root entry");
+ let low_pc_attr = unit_entry
+ .attr_value(gimli::DW_AT_low_pc)
+ .expect("Should parse low_pc");
+ if let Some(gimli::AttributeValue::Addr(address)) = low_pc_attr {
+ low_pc = address;
+ }
+ }
+
+ while cursor.next_dfs().expect("Should parse next dfs").is_some() {
+ let entry = cursor.current().expect("Should have a current entry");
+ let mut attrs = entry.attrs();
+ while let Some(attr) = attrs.next().expect("Should parse entry's attribute") {
+ if let gimli::AttributeValue::RangeListsRef(offset) = attr.value() {
+ offsets.push((RangeListsOffset(offset.0), unit.encoding(), low_pc));
+ }
+ }
+ }
+ }
+
+ b.iter(|| {
+ for &(offset, encoding, base_address) in &*offsets {
+ let mut ranges = rnglists
+ .ranges(offset, encoding, base_address, &debug_addr, debug_addr_base)
+ .expect("Should parse ranges OK");
+ while let Some(range) = ranges.next().expect("Should parse next range") {
+ test::black_box(range);
+ }
+ }
+ });
+}
+
+fn debug_info_expressions<R: Reader>(
+ debug_info: &DebugInfo<R>,
+ debug_abbrev: &DebugAbbrev<R>,
+) -> Vec<(Expression<R>, Encoding)> {
+ let mut expressions = Vec::new();
+
+ let mut iter = debug_info.units();
+ while let Some(unit) = iter.next().expect("Should parse compilation unit") {
+ let abbrevs = unit
+ .abbreviations(debug_abbrev)
+ .expect("Should parse abbreviations");
+
+ let mut cursor = unit.entries(&abbrevs);
+ while let Some((_, entry)) = cursor.next_dfs().expect("Should parse next dfs") {
+ let mut attrs = entry.attrs();
+ while let Some(attr) = attrs.next().expect("Should parse entry's attribute") {
+ if let AttributeValue::Exprloc(expression) = attr.value() {
+ expressions.push((expression, unit.encoding()));
+ }
+ }
+ }
+ }
+
+ expressions
+}
+
+#[bench]
+fn bench_parsing_debug_info_expressions(b: &mut test::Bencher) {
+ let debug_abbrev = read_section("debug_abbrev");
+ let debug_abbrev = DebugAbbrev::new(&debug_abbrev, LittleEndian);
+
+ let debug_info = read_section("debug_info");
+ let debug_info = DebugInfo::new(&debug_info, LittleEndian);
+
+ let expressions = debug_info_expressions(&debug_info, &debug_abbrev);
+
+ b.iter(|| {
+ for &(expression, encoding) in &*expressions {
+ let mut pc = expression.0;
+ while !pc.is_empty() {
+ Operation::parse(&mut pc, encoding).expect("Should parse operation");
+ }
+ }
+ });
+}
+
+#[bench]
+fn bench_evaluating_debug_info_expressions(b: &mut test::Bencher) {
+ let debug_abbrev = read_section("debug_abbrev");
+ let debug_abbrev = DebugAbbrev::new(&debug_abbrev, LittleEndian);
+
+ let debug_info = read_section("debug_info");
+ let debug_info = DebugInfo::new(&debug_info, LittleEndian);
+
+ let expressions = debug_info_expressions(&debug_info, &debug_abbrev);
+
+ b.iter(|| {
+ for &(expression, encoding) in &*expressions {
+ let mut eval = expression.evaluation(encoding);
+ eval.set_initial_value(0);
+ let result = eval.evaluate().expect("Should evaluate expression");
+ test::black_box(result);
+ }
+ });
+}
+
+fn debug_loc_expressions<R: Reader>(
+ debug_info: &DebugInfo<R>,
+ debug_abbrev: &DebugAbbrev<R>,
+ debug_addr: &DebugAddr<R>,
+ loclists: &LocationLists<R>,
+) -> Vec<(Expression<R>, Encoding)> {
+ let debug_addr_base = DebugAddrBase(R::Offset::from_u8(0));
+
+ let mut expressions = Vec::new();
+
+ let mut iter = debug_info.units();
+ while let Some(unit) = iter.next().expect("Should parse compilation unit") {
+ let abbrevs = unit
+ .abbreviations(debug_abbrev)
+ .expect("Should parse abbreviations");
+
+ let mut cursor = unit.entries(&abbrevs);
+ cursor.next_dfs().expect("Should parse next dfs");
+
+ let mut low_pc = 0;
+
+ {
+ let unit_entry = cursor.current().expect("Should have a root entry");
+ let low_pc_attr = unit_entry
+ .attr_value(gimli::DW_AT_low_pc)
+ .expect("Should parse low_pc");
+ if let Some(gimli::AttributeValue::Addr(address)) = low_pc_attr {
+ low_pc = address;
+ }
+ }
+
+ while cursor.next_dfs().expect("Should parse next dfs").is_some() {
+ let entry = cursor.current().expect("Should have a current entry");
+ let mut attrs = entry.attrs();
+ while let Some(attr) = attrs.next().expect("Should parse entry's attribute") {
+ if let gimli::AttributeValue::LocationListsRef(offset) = attr.value() {
+ let mut locs = loclists
+ .locations(offset, unit.encoding(), low_pc, debug_addr, debug_addr_base)
+ .expect("Should parse locations OK");
+ while let Some(loc) = locs.next().expect("Should parse next location") {
+ expressions.push((loc.data, unit.encoding()));
+ }
+ }
+ }
+ }
+ }
+
+ expressions
+}
+
+#[bench]
+fn bench_parsing_debug_loc_expressions(b: &mut test::Bencher) {
+ let debug_info = read_section("debug_info");
+ let debug_info = DebugInfo::new(&debug_info, LittleEndian);
+
+ let debug_abbrev = read_section("debug_abbrev");
+ let debug_abbrev = DebugAbbrev::new(&debug_abbrev, LittleEndian);
+
+ let debug_addr = DebugAddr::from(EndianSlice::new(&[], LittleEndian));
+
+ let debug_loc = read_section("debug_loc");
+ let debug_loc = DebugLoc::new(&debug_loc, LittleEndian);
+ let debug_loclists = DebugLocLists::new(&[], LittleEndian);
+ let loclists = LocationLists::new(debug_loc, debug_loclists);
+
+ let expressions = debug_loc_expressions(&debug_info, &debug_abbrev, &debug_addr, &loclists);
+
+ b.iter(|| {
+ for &(expression, encoding) in &*expressions {
+ let mut pc = expression.0;
+ while !pc.is_empty() {
+ Operation::parse(&mut pc, encoding).expect("Should parse operation");
+ }
+ }
+ });
+}
+
+#[bench]
+fn bench_evaluating_debug_loc_expressions(b: &mut test::Bencher) {
+ let debug_info = read_section("debug_info");
+ let debug_info = DebugInfo::new(&debug_info, LittleEndian);
+
+ let debug_abbrev = read_section("debug_abbrev");
+ let debug_abbrev = DebugAbbrev::new(&debug_abbrev, LittleEndian);
+
+ let debug_addr = DebugAddr::from(EndianSlice::new(&[], LittleEndian));
+
+ let debug_loc = read_section("debug_loc");
+ let debug_loc = DebugLoc::new(&debug_loc, LittleEndian);
+ let debug_loclists = DebugLocLists::new(&[], LittleEndian);
+ let loclists = LocationLists::new(debug_loc, debug_loclists);
+
+ let expressions = debug_loc_expressions(&debug_info, &debug_abbrev, &debug_addr, &loclists);
+
+ b.iter(|| {
+ for &(expression, encoding) in &*expressions {
+ let mut eval = expression.evaluation(encoding);
+ eval.set_initial_value(0);
+ let result = eval.evaluate().expect("Should evaluate expression");
+ test::black_box(result);
+ }
+ });
+}
+
+// See comment above `test_parse_self_eh_frame`.
+#[cfg(target_pointer_width = "64")]
+mod cfi {
+ use super::*;
+ use fallible_iterator::FallibleIterator;
+
+ use gimli::{
+ BaseAddresses, CieOrFde, EhFrame, FrameDescriptionEntry, LittleEndian, UnwindContext,
+ UnwindSection,
+ };
+
+ #[bench]
+ fn iterate_entries_and_do_not_parse_any_fde(b: &mut test::Bencher) {
+ let eh_frame = read_section("eh_frame");
+ let eh_frame = EhFrame::new(&eh_frame, LittleEndian);
+
+ let bases = BaseAddresses::default()
+ .set_eh_frame(0)
+ .set_got(0)
+ .set_text(0);
+
+ b.iter(|| {
+ let mut entries = eh_frame.entries(&bases);
+ while let Some(entry) = entries.next().expect("Should parse CFI entry OK") {
+ test::black_box(entry);
+ }
+ });
+ }
+
+ #[bench]
+ fn iterate_entries_and_parse_every_fde(b: &mut test::Bencher) {
+ let eh_frame = read_section("eh_frame");
+ let eh_frame = EhFrame::new(&eh_frame, LittleEndian);
+
+ let bases = BaseAddresses::default()
+ .set_eh_frame(0)
+ .set_got(0)
+ .set_text(0);
+
+ b.iter(|| {
+ let mut entries = eh_frame.entries(&bases);
+ while let Some(entry) = entries.next().expect("Should parse CFI entry OK") {
+ match entry {
+ CieOrFde::Cie(cie) => {
+ test::black_box(cie);
+ }
+ CieOrFde::Fde(partial) => {
+ let fde = partial
+ .parse(EhFrame::cie_from_offset)
+ .expect("Should be able to get CIE for FED");
+ test::black_box(fde);
+ }
+ };
+ }
+ });
+ }
+
+ #[bench]
+ fn iterate_entries_and_parse_every_fde_and_instructions(b: &mut test::Bencher) {
+ let eh_frame = read_section("eh_frame");
+ let eh_frame = EhFrame::new(&eh_frame, LittleEndian);
+
+ let bases = BaseAddresses::default()
+ .set_eh_frame(0)
+ .set_got(0)
+ .set_text(0);
+
+ b.iter(|| {
+ let mut entries = eh_frame.entries(&bases);
+ while let Some(entry) = entries.next().expect("Should parse CFI entry OK") {
+ match entry {
+ CieOrFde::Cie(cie) => {
+ let mut instrs = cie.instructions(&eh_frame, &bases);
+ while let Some(i) =
+ instrs.next().expect("Can parse next CFI instruction OK")
+ {
+ test::black_box(i);
+ }
+ }
+ CieOrFde::Fde(partial) => {
+ let fde = partial
+ .parse(EhFrame::cie_from_offset)
+ .expect("Should be able to get CIE for FED");
+ let mut instrs = fde.instructions(&eh_frame, &bases);
+ while let Some(i) =
+ instrs.next().expect("Can parse next CFI instruction OK")
+ {
+ test::black_box(i);
+ }
+ }
+ };
+ }
+ });
+ }
+
+ #[bench]
+ fn iterate_entries_evaluate_every_fde(b: &mut test::Bencher) {
+ let eh_frame = read_section("eh_frame");
+ let eh_frame = EhFrame::new(&eh_frame, LittleEndian);
+
+ let bases = BaseAddresses::default()
+ .set_eh_frame(0)
+ .set_got(0)
+ .set_text(0);
+
+ let mut ctx = Box::new(UnwindContext::new());
+
+ b.iter(|| {
+ let mut entries = eh_frame.entries(&bases);
+ while let Some(entry) = entries.next().expect("Should parse CFI entry OK") {
+ match entry {
+ CieOrFde::Cie(_) => {}
+ CieOrFde::Fde(partial) => {
+ let fde = partial
+ .parse(EhFrame::cie_from_offset)
+ .expect("Should be able to get CIE for FED");
+ let mut table = fde
+ .rows(&eh_frame, &bases, &mut ctx)
+ .expect("Should be able to initialize ctx");
+ while let Some(row) =
+ table.next_row().expect("Should get next unwind table row")
+ {
+ test::black_box(row);
+ }
+ }
+ };
+ }
+ });
+ }
+
+ fn instrs_len<R: Reader>(
+ eh_frame: &EhFrame<R>,
+ bases: &BaseAddresses,
+ fde: &FrameDescriptionEntry<R>,
+ ) -> usize {
+ fde.instructions(eh_frame, bases)
+ .fold(0, |count, _| Ok(count + 1))
+ .expect("fold over instructions OK")
+ }
+
+ fn get_fde_with_longest_cfi_instructions<R: Reader>(
+ eh_frame: &EhFrame<R>,
+ bases: &BaseAddresses,
+ ) -> FrameDescriptionEntry<R> {
+ let mut longest: Option<(usize, FrameDescriptionEntry<_>)> = None;
+
+ let mut entries = eh_frame.entries(bases);
+ while let Some(entry) = entries.next().expect("Should parse CFI entry OK") {
+ match entry {
+ CieOrFde::Cie(_) => {}
+ CieOrFde::Fde(partial) => {
+ let fde = partial
+ .parse(EhFrame::cie_from_offset)
+ .expect("Should be able to get CIE for FED");
+
+ let this_len = instrs_len(eh_frame, bases, &fde);
+
+ let found_new_longest = match longest {
+ None => true,
+ Some((longest_len, ref _fde)) => this_len > longest_len,
+ };
+
+ if found_new_longest {
+ longest = Some((this_len, fde));
+ }
+ }
+ };
+ }
+
+ longest.expect("At least one FDE in .eh_frame").1
+ }
+
+ #[bench]
+ fn parse_longest_fde_instructions(b: &mut test::Bencher) {
+ let eh_frame = read_section("eh_frame");
+ let eh_frame = EhFrame::new(&eh_frame, LittleEndian);
+ let bases = BaseAddresses::default()
+ .set_eh_frame(0)
+ .set_got(0)
+ .set_text(0);
+ let fde = get_fde_with_longest_cfi_instructions(&eh_frame, &bases);
+
+ b.iter(|| {
+ let mut instrs = fde.instructions(&eh_frame, &bases);
+ while let Some(i) = instrs.next().expect("Should parse instruction OK") {
+ test::black_box(i);
+ }
+ });
+ }
+
+ #[bench]
+ fn eval_longest_fde_instructions_new_ctx_everytime(b: &mut test::Bencher) {
+ let eh_frame = read_section("eh_frame");
+ let eh_frame = EhFrame::new(&eh_frame, LittleEndian);
+ let bases = BaseAddresses::default()
+ .set_eh_frame(0)
+ .set_got(0)
+ .set_text(0);
+ let fde = get_fde_with_longest_cfi_instructions(&eh_frame, &bases);
+
+ b.iter(|| {
+ let mut ctx = Box::new(UnwindContext::new());
+ let mut table = fde
+ .rows(&eh_frame, &bases, &mut ctx)
+ .expect("Should initialize the ctx OK");
+ while let Some(row) = table.next_row().expect("Should get next unwind table row") {
+ test::black_box(row);
+ }
+ });
+ }
+
+ #[bench]
+ fn eval_longest_fde_instructions_same_ctx(b: &mut test::Bencher) {
+ let eh_frame = read_section("eh_frame");
+ let eh_frame = EhFrame::new(&eh_frame, LittleEndian);
+ let bases = BaseAddresses::default()
+ .set_eh_frame(0)
+ .set_got(0)
+ .set_text(0);
+ let fde = get_fde_with_longest_cfi_instructions(&eh_frame, &bases);
+
+ let mut ctx = Box::new(UnwindContext::new());
+
+ b.iter(|| {
+ let mut table = fde
+ .rows(&eh_frame, &bases, &mut ctx)
+ .expect("Should initialize the ctx OK");
+ while let Some(row) = table.next_row().expect("Should get next unwind table row") {
+ test::black_box(row);
+ }
+ });
+ }
+}
diff --git a/vendor/gimli-0.26.2/examples/dwarf-validate.rs b/vendor/gimli-0.26.2/examples/dwarf-validate.rs
new file mode 100644
index 000000000..54d8f3a1d
--- /dev/null
+++ b/vendor/gimli-0.26.2/examples/dwarf-validate.rs
@@ -0,0 +1,267 @@
+// Allow clippy lints when building without clippy.
+#![allow(unknown_lints)]
+
+use gimli::{AttributeValue, UnitHeader};
+use object::{Object, ObjectSection};
+use rayon::prelude::*;
+use std::borrow::{Borrow, Cow};
+use std::env;
+use std::fs;
+use std::io::{self, BufWriter, Write};
+use std::iter::Iterator;
+use std::path::{Path, PathBuf};
+use std::process;
+use std::sync::Mutex;
+use typed_arena::Arena;
+
+trait Reader: gimli::Reader<Offset = usize> + Send + Sync {
+ type SyncSendEndian: gimli::Endianity + Send + Sync;
+}
+
+impl<'input, Endian> Reader for gimli::EndianSlice<'input, Endian>
+where
+ Endian: gimli::Endianity + Send + Sync,
+{
+ type SyncSendEndian = Endian;
+}
+
+struct ErrorWriter<W: Write + Send> {
+ inner: Mutex<(W, usize)>,
+ path: PathBuf,
+}
+
+impl<W: Write + Send> ErrorWriter<W> {
+ #[allow(clippy::needless_pass_by_value)]
+ fn error(&self, s: String) {
+ let mut lock = self.inner.lock().unwrap();
+ writeln!(&mut lock.0, "DWARF error in {}: {}", self.path.display(), s).unwrap();
+ lock.1 += 1;
+ }
+}
+
+fn main() {
+ let mut w = BufWriter::new(io::stdout());
+ let mut errors = 0;
+ for arg in env::args_os().skip(1) {
+ let path = Path::new(&arg);
+ let file = match fs::File::open(&path) {
+ Ok(file) => file,
+ Err(err) => {
+ eprintln!("Failed to open file '{}': {}", path.display(), err);
+ errors += 1;
+ continue;
+ }
+ };
+ let file = match unsafe { memmap2::Mmap::map(&file) } {
+ Ok(mmap) => mmap,
+ Err(err) => {
+ eprintln!("Failed to map file '{}': {}", path.display(), &err);
+ errors += 1;
+ continue;
+ }
+ };
+ let file = match object::File::parse(&*file) {
+ Ok(file) => file,
+ Err(err) => {
+ eprintln!("Failed to parse file '{}': {}", path.display(), err);
+ errors += 1;
+ continue;
+ }
+ };
+
+ let endian = if file.is_little_endian() {
+ gimli::RunTimeEndian::Little
+ } else {
+ gimli::RunTimeEndian::Big
+ };
+ let mut error_writer = ErrorWriter {
+ inner: Mutex::new((&mut w, 0)),
+ path: path.to_owned(),
+ };
+ validate_file(&mut error_writer, &file, endian);
+ errors += error_writer.inner.into_inner().unwrap().1;
+ }
+ // Flush any errors.
+ drop(w);
+ if errors > 0 {
+ process::exit(1);
+ }
+}
+
+fn validate_file<W, Endian>(w: &mut ErrorWriter<W>, file: &object::File, endian: Endian)
+where
+ W: Write + Send,
+ Endian: gimli::Endianity + Send + Sync,
+{
+ let arena = Arena::new();
+
+ fn load_section<'a, 'file, 'input, S, Endian>(
+ arena: &'a Arena<Cow<'file, [u8]>>,
+ file: &'file object::File<'input>,
+ endian: Endian,
+ ) -> S
+ where
+ S: gimli::Section<gimli::EndianSlice<'a, Endian>>,
+ Endian: gimli::Endianity + Send + Sync,
+ 'file: 'input,
+ 'a: 'file,
+ {
+ let data = match file.section_by_name(S::section_name()) {
+ Some(ref section) => section
+ .uncompressed_data()
+ .unwrap_or(Cow::Borrowed(&[][..])),
+ None => Cow::Borrowed(&[][..]),
+ };
+ let data_ref = (*arena.alloc(data)).borrow();
+ S::from(gimli::EndianSlice::new(data_ref, endian))
+ }
+
+ // Variables representing sections of the file. The type of each is inferred from its use in the
+ // validate_info function below.
+ let debug_abbrev = &load_section(&arena, file, endian);
+ let debug_info = &load_section(&arena, file, endian);
+
+ validate_info(w, debug_info, debug_abbrev);
+}
+
+struct UnitSummary {
+ // True if we successfully parsed all the DIEs and attributes in the compilation unit
+ internally_valid: bool,
+ offset: gimli::DebugInfoOffset,
+ die_offsets: Vec<gimli::UnitOffset>,
+ global_die_references: Vec<(gimli::UnitOffset, gimli::DebugInfoOffset)>,
+}
+
+fn validate_info<W, R>(
+ w: &mut ErrorWriter<W>,
+ debug_info: &gimli::DebugInfo<R>,
+ debug_abbrev: &gimli::DebugAbbrev<R>,
+) where
+ W: Write + Send,
+ R: Reader,
+{
+ let mut units = Vec::new();
+ let mut units_iter = debug_info.units();
+ let mut last_offset = 0;
+ loop {
+ let u = match units_iter.next() {
+ Err(err) => {
+ w.error(format!(
+ "Can't read unit header at offset {:#x}, stopping reading units: {}",
+ last_offset, err
+ ));
+ break;
+ }
+ Ok(None) => break,
+ Ok(Some(u)) => u,
+ };
+ last_offset = u.offset().as_debug_info_offset().unwrap().0 + u.length_including_self();
+ units.push(u);
+ }
+ let process_unit = |unit: UnitHeader<R>| -> UnitSummary {
+ let unit_offset = unit.offset().as_debug_info_offset().unwrap();
+ let mut ret = UnitSummary {
+ internally_valid: false,
+ offset: unit_offset,
+ die_offsets: Vec::new(),
+ global_die_references: Vec::new(),
+ };
+ let abbrevs = match unit.abbreviations(debug_abbrev) {
+ Ok(abbrevs) => abbrevs,
+ Err(err) => {
+ w.error(format!(
+ "Invalid abbrevs for unit {:#x}: {}",
+ unit_offset.0, &err
+ ));
+ return ret;
+ }
+ };
+ let mut entries = unit.entries(&abbrevs);
+ let mut unit_refs = Vec::new();
+ loop {
+ let (_, entry) = match entries.next_dfs() {
+ Err(err) => {
+ w.error(format!(
+ "Invalid DIE for unit {:#x}: {}",
+ unit_offset.0, &err
+ ));
+ return ret;
+ }
+ Ok(None) => break,
+ Ok(Some(entry)) => entry,
+ };
+ ret.die_offsets.push(entry.offset());
+
+ let mut attrs = entry.attrs();
+ loop {
+ let attr = match attrs.next() {
+ Err(err) => {
+ w.error(format!(
+ "Invalid attribute for unit {:#x} at DIE {:#x}: {}",
+ unit_offset.0,
+ entry.offset().0,
+ &err
+ ));
+ return ret;
+ }
+ Ok(None) => break,
+ Ok(Some(attr)) => attr,
+ };
+ match attr.value() {
+ AttributeValue::UnitRef(offset) => {
+ unit_refs.push((entry.offset(), offset));
+ }
+ AttributeValue::DebugInfoRef(offset) => {
+ ret.global_die_references.push((entry.offset(), offset));
+ }
+ _ => (),
+ }
+ }
+ }
+ ret.internally_valid = true;
+ ret.die_offsets.shrink_to_fit();
+ ret.global_die_references.shrink_to_fit();
+
+ // Check intra-unit references
+ for (from, to) in unit_refs {
+ if ret.die_offsets.binary_search(&to).is_err() {
+ w.error(format!(
+ "Invalid intra-unit reference in unit {:#x} from DIE {:#x} to {:#x}",
+ unit_offset.0, from.0, to.0
+ ));
+ }
+ }
+
+ ret
+ };
+ let processed_units = units.into_par_iter().map(process_unit).collect::<Vec<_>>();
+
+ let check_unit = |summary: &UnitSummary| {
+ if !summary.internally_valid {
+ return;
+ }
+ for &(from, to) in summary.global_die_references.iter() {
+ let u = match processed_units.binary_search_by_key(&to, |v| v.offset) {
+ Ok(i) => &processed_units[i],
+ Err(i) => {
+ if i > 0 {
+ &processed_units[i - 1]
+ } else {
+ w.error(format!("Invalid cross-unit reference in unit {:#x} from DIE {:#x} to global DIE {:#x}: no unit found",
+ summary.offset.0, from.0, to.0));
+ continue;
+ }
+ }
+ };
+ if !u.internally_valid {
+ continue;
+ }
+ let to_offset = gimli::UnitOffset(to.0 - u.offset.0);
+ if u.die_offsets.binary_search(&to_offset).is_err() {
+ w.error(format!("Invalid cross-unit reference in unit {:#x} from DIE {:#x} to global DIE {:#x}: unit at {:#x} contains no DIE {:#x}",
+ summary.offset.0, from.0, to.0, u.offset.0, to_offset.0));
+ }
+ }
+ };
+ processed_units.par_iter().for_each(check_unit);
+}
diff --git a/vendor/gimli-0.26.2/examples/dwarfdump.rs b/vendor/gimli-0.26.2/examples/dwarfdump.rs
new file mode 100644
index 000000000..4b61fd572
--- /dev/null
+++ b/vendor/gimli-0.26.2/examples/dwarfdump.rs
@@ -0,0 +1,2417 @@
+// Allow clippy lints when building without clippy.
+#![allow(unknown_lints)]
+
+use fallible_iterator::FallibleIterator;
+use gimli::{Section, UnitHeader, UnitOffset, UnitSectionOffset, UnitType, UnwindSection};
+use object::{Object, ObjectSection, ObjectSymbol};
+use regex::bytes::Regex;
+use std::borrow::{Borrow, Cow};
+use std::cmp::min;
+use std::collections::HashMap;
+use std::env;
+use std::fmt::{self, Debug};
+use std::fs;
+use std::io;
+use std::io::{BufWriter, Write};
+use std::iter::Iterator;
+use std::mem;
+use std::process;
+use std::result;
+use std::sync::{Condvar, Mutex};
+use typed_arena::Arena;
+
+#[derive(Debug, Clone, Copy, PartialEq, Eq)]
+pub enum Error {
+ GimliError(gimli::Error),
+ ObjectError(object::read::Error),
+ IoError,
+}
+
+impl fmt::Display for Error {
+ #[inline]
+ fn fmt(&self, f: &mut fmt::Formatter) -> ::std::result::Result<(), fmt::Error> {
+ Debug::fmt(self, f)
+ }
+}
+
+fn writeln_error<W: Write, R: Reader>(
+ w: &mut W,
+ dwarf: &gimli::Dwarf<R>,
+ err: Error,
+ msg: &str,
+) -> io::Result<()> {
+ writeln!(
+ w,
+ "{}: {}",
+ msg,
+ match err {
+ Error::GimliError(err) => dwarf.format_error(err),
+ Error::ObjectError(err) =>
+ format!("{}:{:?}", "An object error occurred while reading", err),
+ Error::IoError => "An I/O error occurred while writing.".to_string(),
+ }
+ )
+}
+
+impl From<gimli::Error> for Error {
+ fn from(err: gimli::Error) -> Self {
+ Error::GimliError(err)
+ }
+}
+
+impl From<io::Error> for Error {
+ fn from(_: io::Error) -> Self {
+ Error::IoError
+ }
+}
+
+impl From<object::read::Error> for Error {
+ fn from(err: object::read::Error) -> Self {
+ Error::ObjectError(err)
+ }
+}
+
+pub type Result<T> = result::Result<T, Error>;
+
+fn parallel_output<W, II, F>(w: &mut W, max_workers: usize, iter: II, f: F) -> Result<()>
+where
+ W: Write + Send,
+ F: Sync + Fn(II::Item, &mut Vec<u8>) -> Result<()>,
+ II: IntoIterator,
+ II::IntoIter: Send,
+{
+ struct ParallelOutputState<I, W> {
+ iterator: I,
+ current_worker: usize,
+ result: Result<()>,
+ w: W,
+ }
+
+ let state = Mutex::new(ParallelOutputState {
+ iterator: iter.into_iter().fuse(),
+ current_worker: 0,
+ result: Ok(()),
+ w,
+ });
+ let workers = min(max_workers, num_cpus::get());
+ let mut condvars = Vec::new();
+ for _ in 0..workers {
+ condvars.push(Condvar::new());
+ }
+ {
+ let state_ref = &state;
+ let f_ref = &f;
+ let condvars_ref = &condvars;
+ crossbeam::scope(|scope| {
+ for i in 0..workers {
+ scope.spawn(move |_| {
+ let mut v = Vec::new();
+ let mut lock = state_ref.lock().unwrap();
+ while lock.current_worker != i {
+ lock = condvars_ref[i].wait(lock).unwrap();
+ }
+ loop {
+ let item = if lock.result.is_ok() {
+ lock.iterator.next()
+ } else {
+ None
+ };
+ lock.current_worker = (i + 1) % workers;
+ condvars_ref[lock.current_worker].notify_one();
+ mem::drop(lock);
+
+ let ret = if let Some(item) = item {
+ v.clear();
+ f_ref(item, &mut v)
+ } else {
+ return;
+ };
+
+ lock = state_ref.lock().unwrap();
+ while lock.current_worker != i {
+ lock = condvars_ref[i].wait(lock).unwrap();
+ }
+ if lock.result.is_ok() {
+ let ret2 = lock.w.write_all(&v);
+ if ret.is_err() {
+ lock.result = ret;
+ } else {
+ lock.result = ret2.map_err(Error::from);
+ }
+ }
+ }
+ });
+ }
+ })
+ .unwrap();
+ }
+ state.into_inner().unwrap().result
+}
+
+trait Reader: gimli::Reader<Offset = usize> + Send + Sync {}
+
+impl<'input, Endian> Reader for gimli::EndianSlice<'input, Endian> where
+ Endian: gimli::Endianity + Send + Sync
+{
+}
+
+type RelocationMap = HashMap<usize, object::Relocation>;
+
+fn add_relocations(
+ relocations: &mut RelocationMap,
+ file: &object::File,
+ section: &object::Section,
+) {
+ for (offset64, mut relocation) in section.relocations() {
+ let offset = offset64 as usize;
+ if offset as u64 != offset64 {
+ continue;
+ }
+ let offset = offset as usize;
+ match relocation.kind() {
+ object::RelocationKind::Absolute => {
+ match relocation.target() {
+ object::RelocationTarget::Symbol(symbol_idx) => {
+ match file.symbol_by_index(symbol_idx) {
+ Ok(symbol) => {
+ let addend =
+ symbol.address().wrapping_add(relocation.addend() as u64);
+ relocation.set_addend(addend as i64);
+ }
+ Err(_) => {
+ eprintln!(
+ "Relocation with invalid symbol for section {} at offset 0x{:08x}",
+ section.name().unwrap(),
+ offset
+ );
+ }
+ }
+ }
+ _ => {}
+ }
+ if relocations.insert(offset, relocation).is_some() {
+ eprintln!(
+ "Multiple relocations for section {} at offset 0x{:08x}",
+ section.name().unwrap(),
+ offset
+ );
+ }
+ }
+ _ => {
+ eprintln!(
+ "Unsupported relocation for section {} at offset 0x{:08x}",
+ section.name().unwrap(),
+ offset
+ );
+ }
+ }
+ }
+}
+
+/// Apply relocations to addresses and offsets during parsing,
+/// instead of requiring the data to be fully relocated prior
+/// to parsing.
+///
+/// Pros
+/// - allows readonly buffers, we don't need to implement writing of values back to buffers
+/// - potentially allows us to handle addresses and offsets differently
+/// - potentially allows us to add metadata from the relocation (eg symbol names)
+/// Cons
+/// - maybe incomplete
+#[derive(Debug, Clone)]
+struct Relocate<'a, R: gimli::Reader<Offset = usize>> {
+ relocations: &'a RelocationMap,
+ section: R,
+ reader: R,
+}
+
+impl<'a, R: gimli::Reader<Offset = usize>> Relocate<'a, R> {
+ fn relocate(&self, offset: usize, value: u64) -> u64 {
+ if let Some(relocation) = self.relocations.get(&offset) {
+ match relocation.kind() {
+ object::RelocationKind::Absolute => {
+ if relocation.has_implicit_addend() {
+ // Use the explicit addend too, because it may have the symbol value.
+ return value.wrapping_add(relocation.addend() as u64);
+ } else {
+ return relocation.addend() as u64;
+ }
+ }
+ _ => {}
+ }
+ };
+ value
+ }
+}
+
+impl<'a, R: gimli::Reader<Offset = usize>> gimli::Reader for Relocate<'a, R> {
+ type Endian = R::Endian;
+ type Offset = R::Offset;
+
+ fn read_address(&mut self, address_size: u8) -> gimli::Result<u64> {
+ let offset = self.reader.offset_from(&self.section);
+ let value = self.reader.read_address(address_size)?;
+ Ok(self.relocate(offset, value))
+ }
+
+ fn read_length(&mut self, format: gimli::Format) -> gimli::Result<usize> {
+ let offset = self.reader.offset_from(&self.section);
+ let value = self.reader.read_length(format)?;
+ <usize as gimli::ReaderOffset>::from_u64(self.relocate(offset, value as u64))
+ }
+
+ fn read_offset(&mut self, format: gimli::Format) -> gimli::Result<usize> {
+ let offset = self.reader.offset_from(&self.section);
+ let value = self.reader.read_offset(format)?;
+ <usize as gimli::ReaderOffset>::from_u64(self.relocate(offset, value as u64))
+ }
+
+ fn read_sized_offset(&mut self, size: u8) -> gimli::Result<usize> {
+ let offset = self.reader.offset_from(&self.section);
+ let value = self.reader.read_sized_offset(size)?;
+ <usize as gimli::ReaderOffset>::from_u64(self.relocate(offset, value as u64))
+ }
+
+ #[inline]
+ fn split(&mut self, len: Self::Offset) -> gimli::Result<Self> {
+ let mut other = self.clone();
+ other.reader.truncate(len)?;
+ self.reader.skip(len)?;
+ Ok(other)
+ }
+
+ // All remaining methods simply delegate to `self.reader`.
+
+ #[inline]
+ fn endian(&self) -> Self::Endian {
+ self.reader.endian()
+ }
+
+ #[inline]
+ fn len(&self) -> Self::Offset {
+ self.reader.len()
+ }
+
+ #[inline]
+ fn empty(&mut self) {
+ self.reader.empty()
+ }
+
+ #[inline]
+ fn truncate(&mut self, len: Self::Offset) -> gimli::Result<()> {
+ self.reader.truncate(len)
+ }
+
+ #[inline]
+ fn offset_from(&self, base: &Self) -> Self::Offset {
+ self.reader.offset_from(&base.reader)
+ }
+
+ #[inline]
+ fn offset_id(&self) -> gimli::ReaderOffsetId {
+ self.reader.offset_id()
+ }
+
+ #[inline]
+ fn lookup_offset_id(&self, id: gimli::ReaderOffsetId) -> Option<Self::Offset> {
+ self.reader.lookup_offset_id(id)
+ }
+
+ #[inline]
+ fn find(&self, byte: u8) -> gimli::Result<Self::Offset> {
+ self.reader.find(byte)
+ }
+
+ #[inline]
+ fn skip(&mut self, len: Self::Offset) -> gimli::Result<()> {
+ self.reader.skip(len)
+ }
+
+ #[inline]
+ fn to_slice(&self) -> gimli::Result<Cow<[u8]>> {
+ self.reader.to_slice()
+ }
+
+ #[inline]
+ fn to_string(&self) -> gimli::Result<Cow<str>> {
+ self.reader.to_string()
+ }
+
+ #[inline]
+ fn to_string_lossy(&self) -> gimli::Result<Cow<str>> {
+ self.reader.to_string_lossy()
+ }
+
+ #[inline]
+ fn read_slice(&mut self, buf: &mut [u8]) -> gimli::Result<()> {
+ self.reader.read_slice(buf)
+ }
+}
+
+impl<'a, R: Reader> Reader for Relocate<'a, R> {}
+
+#[derive(Default)]
+struct Flags<'a> {
+ eh_frame: bool,
+ goff: bool,
+ info: bool,
+ line: bool,
+ pubnames: bool,
+ pubtypes: bool,
+ aranges: bool,
+ dwo: bool,
+ dwp: bool,
+ dwo_parent: Option<object::File<'a>>,
+ sup: Option<object::File<'a>>,
+ raw: bool,
+ match_units: Option<Regex>,
+}
+
+fn print_usage(opts: &getopts::Options) -> ! {
+ let brief = format!("Usage: {} <options> <file>", env::args().next().unwrap());
+ write!(&mut io::stderr(), "{}", opts.usage(&brief)).ok();
+ process::exit(1);
+}
+
+fn main() {
+ let mut opts = getopts::Options::new();
+ opts.optflag(
+ "",
+ "eh-frame",
+ "print .eh-frame exception handling frame information",
+ );
+ opts.optflag("G", "", "show global die offsets");
+ opts.optflag("i", "", "print .debug_info and .debug_types sections");
+ opts.optflag("l", "", "print .debug_line section");
+ opts.optflag("p", "", "print .debug_pubnames section");
+ opts.optflag("r", "", "print .debug_aranges section");
+ opts.optflag("y", "", "print .debug_pubtypes section");
+ opts.optflag(
+ "",
+ "dwo",
+ "print the .dwo versions of the selected sections",
+ );
+ opts.optflag(
+ "",
+ "dwp",
+ "print the .dwp versions of the selected sections",
+ );
+ opts.optopt(
+ "",
+ "dwo-parent",
+ "use the specified file as the parent of the dwo or dwp (e.g. for .debug_addr)",
+ "library path",
+ );
+ opts.optflag("", "raw", "print raw data values");
+ opts.optopt(
+ "u",
+ "match-units",
+ "print compilation units whose output matches a regex",
+ "REGEX",
+ );
+ opts.optopt("", "sup", "path to supplementary object file", "PATH");
+
+ let matches = match opts.parse(env::args().skip(1)) {
+ Ok(m) => m,
+ Err(e) => {
+ writeln!(&mut io::stderr(), "{:?}\n", e).ok();
+ print_usage(&opts);
+ }
+ };
+ if matches.free.is_empty() {
+ print_usage(&opts);
+ }
+
+ let mut all = true;
+ let mut flags = Flags::default();
+ if matches.opt_present("eh-frame") {
+ flags.eh_frame = true;
+ all = false;
+ }
+ if matches.opt_present("G") {
+ flags.goff = true;
+ }
+ if matches.opt_present("i") {
+ flags.info = true;
+ all = false;
+ }
+ if matches.opt_present("l") {
+ flags.line = true;
+ all = false;
+ }
+ if matches.opt_present("p") {
+ flags.pubnames = true;
+ all = false;
+ }
+ if matches.opt_present("y") {
+ flags.pubtypes = true;
+ all = false;
+ }
+ if matches.opt_present("r") {
+ flags.aranges = true;
+ all = false;
+ }
+ if matches.opt_present("dwo") {
+ flags.dwo = true;
+ }
+ if matches.opt_present("dwp") {
+ flags.dwp = true;
+ }
+ if matches.opt_present("raw") {
+ flags.raw = true;
+ }
+ if all {
+ // .eh_frame is excluded even when printing all information.
+ // cosmetic flags like -G must be set explicitly too.
+ flags.info = true;
+ flags.line = true;
+ flags.pubnames = true;
+ flags.pubtypes = true;
+ flags.aranges = true;
+ }
+ flags.match_units = if let Some(r) = matches.opt_str("u") {
+ match Regex::new(&r) {
+ Ok(r) => Some(r),
+ Err(e) => {
+ eprintln!("Invalid regular expression {}: {}", r, e);
+ process::exit(1);
+ }
+ }
+ } else {
+ None
+ };
+
+ let arena_mmap = Arena::new();
+ let load_file = |path| {
+ let file = match fs::File::open(&path) {
+ Ok(file) => file,
+ Err(err) => {
+ eprintln!("Failed to open file '{}': {}", path, err);
+ process::exit(1);
+ }
+ };
+ let mmap = match unsafe { memmap2::Mmap::map(&file) } {
+ Ok(mmap) => mmap,
+ Err(err) => {
+ eprintln!("Failed to map file '{}': {}", path, err);
+ process::exit(1);
+ }
+ };
+ let mmap_ref = (*arena_mmap.alloc(mmap)).borrow();
+ match object::File::parse(&**mmap_ref) {
+ Ok(file) => Some(file),
+ Err(err) => {
+ eprintln!("Failed to parse file '{}': {}", path, err);
+ process::exit(1);
+ }
+ }
+ };
+
+ flags.sup = matches.opt_str("sup").and_then(load_file);
+ flags.dwo_parent = matches.opt_str("dwo-parent").and_then(load_file);
+ if flags.dwo_parent.is_some() && !flags.dwo && !flags.dwp {
+ eprintln!("--dwo-parent also requires --dwo or --dwp");
+ process::exit(1);
+ }
+ if flags.dwo_parent.is_none() && flags.dwp {
+ eprintln!("--dwp also requires --dwo-parent");
+ process::exit(1);
+ }
+
+ for file_path in &matches.free {
+ if matches.free.len() != 1 {
+ println!("{}", file_path);
+ println!();
+ }
+
+ let file = match fs::File::open(&file_path) {
+ Ok(file) => file,
+ Err(err) => {
+ eprintln!("Failed to open file '{}': {}", file_path, err);
+ continue;
+ }
+ };
+ let file = match unsafe { memmap2::Mmap::map(&file) } {
+ Ok(mmap) => mmap,
+ Err(err) => {
+ eprintln!("Failed to map file '{}': {}", file_path, err);
+ continue;
+ }
+ };
+ let file = match object::File::parse(&*file) {
+ Ok(file) => file,
+ Err(err) => {
+ eprintln!("Failed to parse file '{}': {}", file_path, err);
+ continue;
+ }
+ };
+
+ let endian = if file.is_little_endian() {
+ gimli::RunTimeEndian::Little
+ } else {
+ gimli::RunTimeEndian::Big
+ };
+ let ret = dump_file(&file, endian, &flags);
+ match ret {
+ Ok(_) => (),
+ Err(err) => eprintln!("Failed to dump '{}': {}", file_path, err,),
+ }
+ }
+}
+
+fn empty_file_section<'input, 'arena, Endian: gimli::Endianity>(
+ endian: Endian,
+ arena_relocations: &'arena Arena<RelocationMap>,
+) -> Relocate<'arena, gimli::EndianSlice<'arena, Endian>> {
+ let reader = gimli::EndianSlice::new(&[], endian);
+ let section = reader;
+ let relocations = RelocationMap::default();
+ let relocations = (*arena_relocations.alloc(relocations)).borrow();
+ Relocate {
+ relocations,
+ section,
+ reader,
+ }
+}
+
+fn load_file_section<'input, 'arena, Endian: gimli::Endianity>(
+ id: gimli::SectionId,
+ file: &object::File<'input>,
+ endian: Endian,
+ is_dwo: bool,
+ arena_data: &'arena Arena<Cow<'input, [u8]>>,
+ arena_relocations: &'arena Arena<RelocationMap>,
+) -> Result<Relocate<'arena, gimli::EndianSlice<'arena, Endian>>> {
+ let mut relocations = RelocationMap::default();
+ let name = if is_dwo {
+ id.dwo_name()
+ } else {
+ Some(id.name())
+ };
+
+ let data = match name.and_then(|name| file.section_by_name(&name)) {
+ Some(ref section) => {
+ // DWO sections never have relocations, so don't bother.
+ if !is_dwo {
+ add_relocations(&mut relocations, file, section);
+ }
+ section.uncompressed_data()?
+ }
+ // Use a non-zero capacity so that `ReaderOffsetId`s are unique.
+ None => Cow::Owned(Vec::with_capacity(1)),
+ };
+ let data_ref = (*arena_data.alloc(data)).borrow();
+ let reader = gimli::EndianSlice::new(data_ref, endian);
+ let section = reader;
+ let relocations = (*arena_relocations.alloc(relocations)).borrow();
+ Ok(Relocate {
+ relocations,
+ section,
+ reader,
+ })
+}
+
+fn dump_file<Endian>(file: &object::File, endian: Endian, flags: &Flags) -> Result<()>
+where
+ Endian: gimli::Endianity + Send + Sync,
+{
+ let arena_data = Arena::new();
+ let arena_relocations = Arena::new();
+
+ let dwo_parent = if let Some(dwo_parent_file) = flags.dwo_parent.as_ref() {
+ let mut load_dwo_parent_section = |id: gimli::SectionId| -> Result<_> {
+ load_file_section(
+ id,
+ dwo_parent_file,
+ endian,
+ false,
+ &arena_data,
+ &arena_relocations,
+ )
+ };
+ Some(gimli::Dwarf::load(&mut load_dwo_parent_section)?)
+ } else {
+ None
+ };
+ let dwo_parent = dwo_parent.as_ref();
+
+ let dwo_parent_units = if let Some(dwo_parent) = dwo_parent {
+ Some(
+ match dwo_parent
+ .units()
+ .map(|unit_header| dwo_parent.unit(unit_header))
+ .filter_map(|unit| Ok(unit.dwo_id.map(|dwo_id| (dwo_id, unit))))
+ .collect()
+ {
+ Ok(units) => units,
+ Err(err) => {
+ eprintln!("Failed to process --dwo-parent units: {}", err);
+ return Ok(());
+ }
+ },
+ )
+ } else {
+ None
+ };
+ let dwo_parent_units = dwo_parent_units.as_ref();
+
+ let mut load_section = |id: gimli::SectionId| -> Result<_> {
+ load_file_section(
+ id,
+ file,
+ endian,
+ flags.dwo || flags.dwp,
+ &arena_data,
+ &arena_relocations,
+ )
+ };
+
+ let w = &mut BufWriter::new(io::stdout());
+ if flags.dwp {
+ let empty = empty_file_section(endian, &arena_relocations);
+ let dwp = gimli::DwarfPackage::load(&mut load_section, empty)?;
+ dump_dwp(w, &dwp, dwo_parent.unwrap(), dwo_parent_units, flags)?;
+ w.flush()?;
+ return Ok(());
+ }
+
+ let mut dwarf = gimli::Dwarf::load(&mut load_section)?;
+ if flags.dwo {
+ dwarf.file_type = gimli::DwarfFileType::Dwo;
+ if let Some(dwo_parent) = dwo_parent {
+ dwarf.debug_addr = dwo_parent.debug_addr.clone();
+ dwarf
+ .ranges
+ .set_debug_ranges(dwo_parent.ranges.debug_ranges().clone());
+ }
+ }
+
+ if let Some(sup_file) = flags.sup.as_ref() {
+ let mut load_sup_section = |id: gimli::SectionId| -> Result<_> {
+ // Note: we really only need the `.debug_str` section,
+ // but for now we load them all.
+ load_file_section(id, sup_file, endian, false, &arena_data, &arena_relocations)
+ };
+ dwarf.load_sup(&mut load_sup_section)?;
+ }
+
+ if flags.eh_frame {
+ let eh_frame = gimli::EhFrame::load(&mut load_section).unwrap();
+ dump_eh_frame(w, file, eh_frame)?;
+ }
+ if flags.info {
+ dump_info(w, &dwarf, dwo_parent_units, flags)?;
+ dump_types(w, &dwarf, dwo_parent_units, flags)?;
+ }
+ if flags.line {
+ dump_line(w, &dwarf)?;
+ }
+ if flags.pubnames {
+ let debug_pubnames = &gimli::Section::load(&mut load_section).unwrap();
+ dump_pubnames(w, debug_pubnames, &dwarf.debug_info)?;
+ }
+ if flags.aranges {
+ let debug_aranges = &gimli::Section::load(&mut load_section).unwrap();
+ dump_aranges(w, debug_aranges)?;
+ }
+ if flags.pubtypes {
+ let debug_pubtypes = &gimli::Section::load(&mut load_section).unwrap();
+ dump_pubtypes(w, debug_pubtypes, &dwarf.debug_info)?;
+ }
+ w.flush()?;
+ Ok(())
+}
+
+fn dump_eh_frame<R: Reader, W: Write>(
+ w: &mut W,
+ file: &object::File,
+ mut eh_frame: gimli::EhFrame<R>,
+) -> Result<()> {
+ // TODO: this might be better based on the file format.
+ let address_size = file
+ .architecture()
+ .address_size()
+ .map(|w| w.bytes())
+ .unwrap_or(mem::size_of::<usize>() as u8);
+ eh_frame.set_address_size(address_size);
+
+ fn register_name_none(_: gimli::Register) -> Option<&'static str> {
+ None
+ }
+ let arch_register_name = match file.architecture() {
+ object::Architecture::Arm | object::Architecture::Aarch64 => gimli::Arm::register_name,
+ object::Architecture::I386 => gimli::X86::register_name,
+ object::Architecture::X86_64 => gimli::X86_64::register_name,
+ _ => register_name_none,
+ };
+ let register_name = &|register| match arch_register_name(register) {
+ Some(name) => Cow::Borrowed(name),
+ None => Cow::Owned(format!("{}", register.0)),
+ };
+
+ let mut bases = gimli::BaseAddresses::default();
+ if let Some(section) = file.section_by_name(".eh_frame_hdr") {
+ bases = bases.set_eh_frame_hdr(section.address());
+ }
+ if let Some(section) = file.section_by_name(".eh_frame") {
+ bases = bases.set_eh_frame(section.address());
+ }
+ if let Some(section) = file.section_by_name(".text") {
+ bases = bases.set_text(section.address());
+ }
+ if let Some(section) = file.section_by_name(".got") {
+ bases = bases.set_got(section.address());
+ }
+
+ // TODO: Print "__eh_frame" here on macOS, and more generally use the
+ // section that we're actually looking at, which is what the canonical
+ // dwarfdump does.
+ writeln!(
+ w,
+ "Exception handling frame information for section .eh_frame"
+ )?;
+
+ let mut cies = HashMap::new();
+
+ let mut entries = eh_frame.entries(&bases);
+ loop {
+ match entries.next()? {
+ None => return Ok(()),
+ Some(gimli::CieOrFde::Cie(cie)) => {
+ writeln!(w)?;
+ writeln!(w, "{:#010x}: CIE", cie.offset())?;
+ writeln!(w, " length: {:#010x}", cie.entry_len())?;
+ // TODO: CIE_id
+ writeln!(w, " version: {:#04x}", cie.version())?;
+ // TODO: augmentation
+ writeln!(w, " code_align: {}", cie.code_alignment_factor())?;
+ writeln!(w, " data_align: {}", cie.data_alignment_factor())?;
+ writeln!(
+ w,
+ " ra_register: {}",
+ register_name(cie.return_address_register())
+ )?;
+ if let Some(encoding) = cie.lsda_encoding() {
+ writeln!(
+ w,
+ " lsda_encoding: {}/{}",
+ encoding.application(),
+ encoding.format()
+ )?;
+ }
+ if let Some((encoding, personality)) = cie.personality_with_encoding() {
+ write!(
+ w,
+ " personality: {}/{} ",
+ encoding.application(),
+ encoding.format()
+ )?;
+ dump_pointer(w, personality)?;
+ writeln!(w)?;
+ }
+ if let Some(encoding) = cie.fde_address_encoding() {
+ writeln!(
+ w,
+ " fde_encoding: {}/{}",
+ encoding.application(),
+ encoding.format()
+ )?;
+ }
+ let instructions = cie.instructions(&eh_frame, &bases);
+ dump_cfi_instructions(w, instructions, true, register_name)?;
+ writeln!(w)?;
+ }
+ Some(gimli::CieOrFde::Fde(partial)) => {
+ let mut offset = None;
+ let fde = partial.parse(|_, bases, o| {
+ offset = Some(o);
+ cies.entry(o)
+ .or_insert_with(|| eh_frame.cie_from_offset(bases, o))
+ .clone()
+ })?;
+
+ writeln!(w)?;
+ writeln!(w, "{:#010x}: FDE", fde.offset())?;
+ writeln!(w, " length: {:#010x}", fde.entry_len())?;
+ writeln!(w, " CIE_pointer: {:#010x}", offset.unwrap().0)?;
+ // TODO: symbolicate the start address like the canonical dwarfdump does.
+ writeln!(w, " start_addr: {:#018x}", fde.initial_address())?;
+ writeln!(
+ w,
+ " range_size: {:#018x} (end_addr = {:#018x})",
+ fde.len(),
+ fde.initial_address() + fde.len()
+ )?;
+ if let Some(lsda) = fde.lsda() {
+ write!(w, " lsda: ")?;
+ dump_pointer(w, lsda)?;
+ writeln!(w)?;
+ }
+ let instructions = fde.instructions(&eh_frame, &bases);
+ dump_cfi_instructions(w, instructions, false, register_name)?;
+ writeln!(w)?;
+ }
+ }
+ }
+}
+
+fn dump_pointer<W: Write>(w: &mut W, p: gimli::Pointer) -> Result<()> {
+ match p {
+ gimli::Pointer::Direct(p) => {
+ write!(w, "{:#018x}", p)?;
+ }
+ gimli::Pointer::Indirect(p) => {
+ write!(w, "({:#018x})", p)?;
+ }
+ }
+ Ok(())
+}
+
+#[allow(clippy::unneeded_field_pattern)]
+fn dump_cfi_instructions<R: Reader, W: Write>(
+ w: &mut W,
+ mut insns: gimli::CallFrameInstructionIter<R>,
+ is_initial: bool,
+ register_name: &dyn Fn(gimli::Register) -> Cow<'static, str>,
+) -> Result<()> {
+ use gimli::CallFrameInstruction::*;
+
+ // TODO: we need to actually evaluate these instructions as we iterate them
+ // so we can print the initialized state for CIEs, and each unwind row's
+ // registers for FDEs.
+ //
+ // TODO: We should print DWARF expressions for the CFI instructions that
+ // embed DWARF expressions within themselves.
+
+ if !is_initial {
+ writeln!(w, " Instructions:")?;
+ }
+
+ loop {
+ match insns.next() {
+ Err(e) => {
+ writeln!(w, "Failed to decode CFI instruction: {}", e)?;
+ return Ok(());
+ }
+ Ok(None) => {
+ if is_initial {
+ writeln!(w, " Instructions: Init State:")?;
+ }
+ return Ok(());
+ }
+ Ok(Some(op)) => match op {
+ SetLoc { address } => {
+ writeln!(w, " DW_CFA_set_loc ({:#x})", address)?;
+ }
+ AdvanceLoc { delta } => {
+ writeln!(w, " DW_CFA_advance_loc ({})", delta)?;
+ }
+ DefCfa { register, offset } => {
+ writeln!(
+ w,
+ " DW_CFA_def_cfa ({}, {})",
+ register_name(register),
+ offset
+ )?;
+ }
+ DefCfaSf {
+ register,
+ factored_offset,
+ } => {
+ writeln!(
+ w,
+ " DW_CFA_def_cfa_sf ({}, {})",
+ register_name(register),
+ factored_offset
+ )?;
+ }
+ DefCfaRegister { register } => {
+ writeln!(
+ w,
+ " DW_CFA_def_cfa_register ({})",
+ register_name(register)
+ )?;
+ }
+ DefCfaOffset { offset } => {
+ writeln!(w, " DW_CFA_def_cfa_offset ({})", offset)?;
+ }
+ DefCfaOffsetSf { factored_offset } => {
+ writeln!(
+ w,
+ " DW_CFA_def_cfa_offset_sf ({})",
+ factored_offset
+ )?;
+ }
+ DefCfaExpression { expression: _ } => {
+ writeln!(w, " DW_CFA_def_cfa_expression (...)")?;
+ }
+ Undefined { register } => {
+ writeln!(
+ w,
+ " DW_CFA_undefined ({})",
+ register_name(register)
+ )?;
+ }
+ SameValue { register } => {
+ writeln!(
+ w,
+ " DW_CFA_same_value ({})",
+ register_name(register)
+ )?;
+ }
+ Offset {
+ register,
+ factored_offset,
+ } => {
+ writeln!(
+ w,
+ " DW_CFA_offset ({}, {})",
+ register_name(register),
+ factored_offset
+ )?;
+ }
+ OffsetExtendedSf {
+ register,
+ factored_offset,
+ } => {
+ writeln!(
+ w,
+ " DW_CFA_offset_extended_sf ({}, {})",
+ register_name(register),
+ factored_offset
+ )?;
+ }
+ ValOffset {
+ register,
+ factored_offset,
+ } => {
+ writeln!(
+ w,
+ " DW_CFA_val_offset ({}, {})",
+ register_name(register),
+ factored_offset
+ )?;
+ }
+ ValOffsetSf {
+ register,
+ factored_offset,
+ } => {
+ writeln!(
+ w,
+ " DW_CFA_val_offset_sf ({}, {})",
+ register_name(register),
+ factored_offset
+ )?;
+ }
+ Register {
+ dest_register,
+ src_register,
+ } => {
+ writeln!(
+ w,
+ " DW_CFA_register ({}, {})",
+ register_name(dest_register),
+ register_name(src_register)
+ )?;
+ }
+ Expression {
+ register,
+ expression: _,
+ } => {
+ writeln!(
+ w,
+ " DW_CFA_expression ({}, ...)",
+ register_name(register)
+ )?;
+ }
+ ValExpression {
+ register,
+ expression: _,
+ } => {
+ writeln!(
+ w,
+ " DW_CFA_val_expression ({}, ...)",
+ register_name(register)
+ )?;
+ }
+ Restore { register } => {
+ writeln!(
+ w,
+ " DW_CFA_restore ({})",
+ register_name(register)
+ )?;
+ }
+ RememberState => {
+ writeln!(w, " DW_CFA_remember_state")?;
+ }
+ RestoreState => {
+ writeln!(w, " DW_CFA_restore_state")?;
+ }
+ ArgsSize { size } => {
+ writeln!(w, " DW_CFA_GNU_args_size ({})", size)?;
+ }
+ Nop => {
+ writeln!(w, " DW_CFA_nop")?;
+ }
+ },
+ }
+ }
+}
+
+fn dump_dwp<R: Reader, W: Write + Send>(
+ w: &mut W,
+ dwp: &gimli::DwarfPackage<R>,
+ dwo_parent: &gimli::Dwarf<R>,
+ dwo_parent_units: Option<&HashMap<gimli::DwoId, gimli::Unit<R>>>,
+ flags: &Flags,
+) -> Result<()>
+where
+ R::Endian: Send + Sync,
+{
+ if dwp.cu_index.unit_count() != 0 {
+ writeln!(
+ w,
+ "\n.debug_cu_index: version = {}, sections = {}, units = {}, slots = {}",
+ dwp.cu_index.version(),
+ dwp.cu_index.section_count(),
+ dwp.cu_index.unit_count(),
+ dwp.cu_index.slot_count(),
+ )?;
+ for i in 1..=dwp.cu_index.unit_count() {
+ writeln!(w, "\nCU index {}", i)?;
+ dump_dwp_sections(
+ w,
+ &dwp,
+ dwo_parent,
+ dwo_parent_units,
+ flags,
+ dwp.cu_index.sections(i)?,
+ )?;
+ }
+ }
+
+ if dwp.tu_index.unit_count() != 0 {
+ writeln!(
+ w,
+ "\n.debug_tu_index: version = {}, sections = {}, units = {}, slots = {}",
+ dwp.tu_index.version(),
+ dwp.tu_index.section_count(),
+ dwp.tu_index.unit_count(),
+ dwp.tu_index.slot_count(),
+ )?;
+ for i in 1..=dwp.tu_index.unit_count() {
+ writeln!(w, "\nTU index {}", i)?;
+ dump_dwp_sections(
+ w,
+ &dwp,
+ dwo_parent,
+ dwo_parent_units,
+ flags,
+ dwp.tu_index.sections(i)?,
+ )?;
+ }
+ }
+
+ Ok(())
+}
+
+fn dump_dwp_sections<R: Reader, W: Write + Send>(
+ w: &mut W,
+ dwp: &gimli::DwarfPackage<R>,
+ dwo_parent: &gimli::Dwarf<R>,
+ dwo_parent_units: Option<&HashMap<gimli::DwoId, gimli::Unit<R>>>,
+ flags: &Flags,
+ sections: gimli::UnitIndexSectionIterator<R>,
+) -> Result<()>
+where
+ R::Endian: Send + Sync,
+{
+ for section in sections.clone() {
+ writeln!(
+ w,
+ " {}: offset = 0x{:x}, size = 0x{:x}",
+ section.section.dwo_name().unwrap(),
+ section.offset,
+ section.size
+ )?;
+ }
+ let dwarf = dwp.sections(sections, dwo_parent)?;
+ if flags.info {
+ dump_info(w, &dwarf, dwo_parent_units, flags)?;
+ dump_types(w, &dwarf, dwo_parent_units, flags)?;
+ }
+ if flags.line {
+ dump_line(w, &dwarf)?;
+ }
+ Ok(())
+}
+
+fn dump_info<R: Reader, W: Write + Send>(
+ w: &mut W,
+ dwarf: &gimli::Dwarf<R>,
+ dwo_parent_units: Option<&HashMap<gimli::DwoId, gimli::Unit<R>>>,
+ flags: &Flags,
+) -> Result<()>
+where
+ R::Endian: Send + Sync,
+{
+ writeln!(w, "\n.debug_info")?;
+
+ let units = match dwarf.units().collect::<Vec<_>>() {
+ Ok(units) => units,
+ Err(err) => {
+ writeln_error(
+ w,
+ dwarf,
+ Error::GimliError(err),
+ "Failed to read unit headers",
+ )?;
+ return Ok(());
+ }
+ };
+ let process_unit = |header: UnitHeader<R>, buf: &mut Vec<u8>| -> Result<()> {
+ dump_unit(buf, header, dwarf, dwo_parent_units, flags)?;
+ if !flags
+ .match_units
+ .as_ref()
+ .map(|r| r.is_match(&buf))
+ .unwrap_or(true)
+ {
+ buf.clear();
+ }
+ Ok(())
+ };
+ // Don't use more than 16 cores even if available. No point in soaking hundreds
+ // of cores if you happen to have them.
+ parallel_output(w, 16, units, process_unit)
+}
+
+fn dump_types<R: Reader, W: Write>(
+ w: &mut W,
+ dwarf: &gimli::Dwarf<R>,
+ dwo_parent_units: Option<&HashMap<gimli::DwoId, gimli::Unit<R>>>,
+ flags: &Flags,
+) -> Result<()> {
+ writeln!(w, "\n.debug_types")?;
+
+ let mut iter = dwarf.type_units();
+ while let Some(header) = iter.next()? {
+ dump_unit(w, header, dwarf, dwo_parent_units, flags)?;
+ }
+ Ok(())
+}
+
+fn dump_unit<R: Reader, W: Write>(
+ w: &mut W,
+ header: UnitHeader<R>,
+ dwarf: &gimli::Dwarf<R>,
+ dwo_parent_units: Option<&HashMap<gimli::DwoId, gimli::Unit<R>>>,
+ flags: &Flags,
+) -> Result<()> {
+ write!(w, "\nUNIT<")?;
+ match header.offset() {
+ UnitSectionOffset::DebugInfoOffset(o) => {
+ write!(w, ".debug_info+0x{:08x}", o.0)?;
+ }
+ UnitSectionOffset::DebugTypesOffset(o) => {
+ write!(w, ".debug_types+0x{:08x}", o.0)?;
+ }
+ }
+ writeln!(w, ">: length = 0x{:x}, format = {:?}, version = {}, address_size = {}, abbrev_offset = 0x{:x}",
+ header.unit_length(),
+ header.format(),
+ header.version(),
+ header.address_size(),
+ header.debug_abbrev_offset().0,
+ )?;
+
+ match header.type_() {
+ UnitType::Compilation | UnitType::Partial => (),
+ UnitType::Type {
+ type_signature,
+ type_offset,
+ }
+ | UnitType::SplitType {
+ type_signature,
+ type_offset,
+ } => {
+ write!(w, " signature = ")?;
+ dump_type_signature(w, type_signature)?;
+ writeln!(w)?;
+ writeln!(w, " type_offset = 0x{:x}", type_offset.0,)?;
+ }
+ UnitType::Skeleton(dwo_id) | UnitType::SplitCompilation(dwo_id) => {
+ write!(w, " dwo_id = ")?;
+ writeln!(w, "0x{:016x}", dwo_id.0)?;
+ }
+ }
+
+ let mut unit = match dwarf.unit(header) {
+ Ok(unit) => unit,
+ Err(err) => {
+ writeln_error(w, dwarf, err.into(), "Failed to parse unit root entry")?;
+ return Ok(());
+ }
+ };
+
+ if let Some(dwo_parent_units) = dwo_parent_units {
+ if let Some(dwo_id) = unit.dwo_id {
+ if let Some(parent_unit) = dwo_parent_units.get(&dwo_id) {
+ unit.copy_relocated_attributes(parent_unit);
+ }
+ }
+ }
+
+ let entries_result = dump_entries(w, unit, dwarf, flags);
+ if let Err(err) = entries_result {
+ writeln_error(w, dwarf, err, "Failed to dump entries")?;
+ }
+ Ok(())
+}
+
+fn spaces(buf: &mut String, len: usize) -> &str {
+ while buf.len() < len {
+ buf.push(' ');
+ }
+ &buf[..len]
+}
+
+// " GOFF=0x{:08x}" adds exactly 16 spaces.
+const GOFF_SPACES: usize = 16;
+
+fn write_offset<R: Reader, W: Write>(
+ w: &mut W,
+ unit: &gimli::Unit<R>,
+ offset: gimli::UnitOffset<R::Offset>,
+ flags: &Flags,
+) -> Result<()> {
+ write!(w, "<0x{:08x}", offset.0)?;
+ if flags.goff {
+ let goff = match offset.to_unit_section_offset(unit) {
+ UnitSectionOffset::DebugInfoOffset(o) => o.0,
+ UnitSectionOffset::DebugTypesOffset(o) => o.0,
+ };
+ write!(w, " GOFF=0x{:08x}", goff)?;
+ }
+ write!(w, ">")?;
+ Ok(())
+}
+
+fn dump_entries<R: Reader, W: Write>(
+ w: &mut W,
+ unit: gimli::Unit<R>,
+ dwarf: &gimli::Dwarf<R>,
+ flags: &Flags,
+) -> Result<()> {
+ let mut spaces_buf = String::new();
+
+ let mut entries = unit.entries_raw(None)?;
+ while !entries.is_empty() {
+ let offset = entries.next_offset();
+ let depth = entries.next_depth();
+ let abbrev = entries.read_abbreviation()?;
+
+ let mut indent = if depth >= 0 {
+ depth as usize * 2 + 2
+ } else {
+ 2
+ };
+ write!(w, "<{}{}>", if depth < 10 { " " } else { "" }, depth)?;
+ write_offset(w, &unit, offset, flags)?;
+ writeln!(
+ w,
+ "{}{}",
+ spaces(&mut spaces_buf, indent),
+ abbrev.map(|x| x.tag()).unwrap_or(gimli::DW_TAG_null)
+ )?;
+
+ indent += 18;
+ if flags.goff {
+ indent += GOFF_SPACES;
+ }
+
+ for spec in abbrev.map(|x| x.attributes()).unwrap_or(&[]) {
+ let attr = entries.read_attribute(*spec)?;
+ w.write_all(spaces(&mut spaces_buf, indent).as_bytes())?;
+ if let Some(n) = attr.name().static_string() {
+ let right_padding = 27 - std::cmp::min(27, n.len());
+ write!(w, "{}{} ", n, spaces(&mut spaces_buf, right_padding))?;
+ } else {
+ write!(w, "{:27} ", attr.name())?;
+ }
+ if flags.raw {
+ writeln!(w, "{:?}", attr.raw_value())?;
+ } else {
+ match dump_attr_value(w, &attr, &unit, dwarf) {
+ Ok(_) => (),
+ Err(err) => writeln_error(w, dwarf, err, "Failed to dump attribute value")?,
+ };
+ }
+ }
+ }
+ Ok(())
+}
+
+fn dump_attr_value<R: Reader, W: Write>(
+ w: &mut W,
+ attr: &gimli::Attribute<R>,
+ unit: &gimli::Unit<R>,
+ dwarf: &gimli::Dwarf<R>,
+) -> Result<()> {
+ let value = attr.value();
+ match value {
+ gimli::AttributeValue::Addr(address) => {
+ writeln!(w, "0x{:08x}", address)?;
+ }
+ gimli::AttributeValue::Block(data) => {
+ for byte in data.to_slice()?.iter() {
+ write!(w, "{:02x}", byte)?;
+ }
+ writeln!(w)?;
+ }
+ gimli::AttributeValue::Data1(_)
+ | gimli::AttributeValue::Data2(_)
+ | gimli::AttributeValue::Data4(_)
+ | gimli::AttributeValue::Data8(_) => {
+ if let (Some(udata), Some(sdata)) = (attr.udata_value(), attr.sdata_value()) {
+ if sdata >= 0 {
+ writeln!(w, "{}", udata)?;
+ } else {
+ writeln!(w, "{} ({})", udata, sdata)?;
+ }
+ } else {
+ writeln!(w, "{:?}", value)?;
+ }
+ }
+ gimli::AttributeValue::Sdata(data) => {
+ match attr.name() {
+ gimli::DW_AT_data_member_location => {
+ writeln!(w, "{}", data)?;
+ }
+ _ => {
+ if data >= 0 {
+ writeln!(w, "0x{:08x}", data)?;
+ } else {
+ writeln!(w, "0x{:08x} ({})", data, data)?;
+ }
+ }
+ };
+ }
+ gimli::AttributeValue::Udata(data) => {
+ match attr.name() {
+ gimli::DW_AT_high_pc => {
+ writeln!(w, "<offset-from-lowpc>{}", data)?;
+ }
+ gimli::DW_AT_data_member_location => {
+ if let Some(sdata) = attr.sdata_value() {
+ // This is a DW_FORM_data* value.
+ // libdwarf-dwarfdump displays this as signed too.
+ if sdata >= 0 {
+ writeln!(w, "{}", data)?;
+ } else {
+ writeln!(w, "{} ({})", data, sdata)?;
+ }
+ } else {
+ writeln!(w, "{}", data)?;
+ }
+ }
+ gimli::DW_AT_lower_bound | gimli::DW_AT_upper_bound => {
+ writeln!(w, "{}", data)?;
+ }
+ _ => {
+ writeln!(w, "0x{:08x}", data)?;
+ }
+ };
+ }
+ gimli::AttributeValue::Exprloc(ref data) => {
+ if let gimli::AttributeValue::Exprloc(_) = attr.raw_value() {
+ write!(w, "len 0x{:04x}: ", data.0.len())?;
+ for byte in data.0.to_slice()?.iter() {
+ write!(w, "{:02x}", byte)?;
+ }
+ write!(w, ": ")?;
+ }
+ dump_exprloc(w, unit.encoding(), data)?;
+ writeln!(w)?;
+ }
+ gimli::AttributeValue::Flag(true) => {
+ writeln!(w, "yes")?;
+ }
+ gimli::AttributeValue::Flag(false) => {
+ writeln!(w, "no")?;
+ }
+ gimli::AttributeValue::SecOffset(offset) => {
+ writeln!(w, "0x{:08x}", offset)?;
+ }
+ gimli::AttributeValue::DebugAddrBase(base) => {
+ writeln!(w, "<.debug_addr+0x{:08x}>", base.0)?;
+ }
+ gimli::AttributeValue::DebugAddrIndex(index) => {
+ write!(w, "(indirect address, index {:#x}): ", index.0)?;
+ let address = dwarf.address(unit, index)?;
+ writeln!(w, "0x{:08x}", address)?;
+ }
+ gimli::AttributeValue::UnitRef(offset) => {
+ write!(w, "0x{:08x}", offset.0)?;
+ match offset.to_unit_section_offset(unit) {
+ UnitSectionOffset::DebugInfoOffset(goff) => {
+ write!(w, "<.debug_info+0x{:08x}>", goff.0)?;
+ }
+ UnitSectionOffset::DebugTypesOffset(goff) => {
+ write!(w, "<.debug_types+0x{:08x}>", goff.0)?;
+ }
+ }
+ writeln!(w)?;
+ }
+ gimli::AttributeValue::DebugInfoRef(offset) => {
+ writeln!(w, "<.debug_info+0x{:08x}>", offset.0)?;
+ }
+ gimli::AttributeValue::DebugInfoRefSup(offset) => {
+ writeln!(w, "<.debug_info(sup)+0x{:08x}>", offset.0)?;
+ }
+ gimli::AttributeValue::DebugLineRef(offset) => {
+ writeln!(w, "<.debug_line+0x{:08x}>", offset.0)?;
+ }
+ gimli::AttributeValue::LocationListsRef(offset) => {
+ dump_loc_list(w, offset, unit, dwarf)?;
+ }
+ gimli::AttributeValue::DebugLocListsBase(base) => {
+ writeln!(w, "<.debug_loclists+0x{:08x}>", base.0)?;
+ }
+ gimli::AttributeValue::DebugLocListsIndex(index) => {
+ write!(w, "(indirect location list, index {:#x}): ", index.0)?;
+ let offset = dwarf.locations_offset(unit, index)?;
+ dump_loc_list(w, offset, unit, dwarf)?;
+ }
+ gimli::AttributeValue::DebugMacinfoRef(offset) => {
+ writeln!(w, "<.debug_macinfo+0x{:08x}>", offset.0)?;
+ }
+ gimli::AttributeValue::DebugMacroRef(offset) => {
+ writeln!(w, "<.debug_macro+0x{:08x}>", offset.0)?;
+ }
+ gimli::AttributeValue::RangeListsRef(offset) => {
+ let offset = dwarf.ranges_offset_from_raw(unit, offset);
+ dump_range_list(w, offset, unit, dwarf)?;
+ }
+ gimli::AttributeValue::DebugRngListsBase(base) => {
+ writeln!(w, "<.debug_rnglists+0x{:08x}>", base.0)?;
+ }
+ gimli::AttributeValue::DebugRngListsIndex(index) => {
+ write!(w, "(indirect range list, index {:#x}): ", index.0)?;
+ let offset = dwarf.ranges_offset(unit, index)?;
+ dump_range_list(w, offset, unit, dwarf)?;
+ }
+ gimli::AttributeValue::DebugTypesRef(signature) => {
+ dump_type_signature(w, signature)?;
+ writeln!(w, " <type signature>")?;
+ }
+ gimli::AttributeValue::DebugStrRef(offset) => {
+ if let Ok(s) = dwarf.debug_str.get_str(offset) {
+ writeln!(w, "{}", s.to_string_lossy()?)?;
+ } else {
+ writeln!(w, "<.debug_str+0x{:08x}>", offset.0)?;
+ }
+ }
+ gimli::AttributeValue::DebugStrRefSup(offset) => {
+ if let Some(s) = dwarf
+ .sup()
+ .and_then(|sup| sup.debug_str.get_str(offset).ok())
+ {
+ writeln!(w, "{}", s.to_string_lossy()?)?;
+ } else {
+ writeln!(w, "<.debug_str(sup)+0x{:08x}>", offset.0)?;
+ }
+ }
+ gimli::AttributeValue::DebugStrOffsetsBase(base) => {
+ writeln!(w, "<.debug_str_offsets+0x{:08x}>", base.0)?;
+ }
+ gimli::AttributeValue::DebugStrOffsetsIndex(index) => {
+ write!(w, "(indirect string, index {:#x}): ", index.0)?;
+ let offset = dwarf.debug_str_offsets.get_str_offset(
+ unit.encoding().format,
+ unit.str_offsets_base,
+ index,
+ )?;
+ if let Ok(s) = dwarf.debug_str.get_str(offset) {
+ writeln!(w, "{}", s.to_string_lossy()?)?;
+ } else {
+ writeln!(w, "<.debug_str+0x{:08x}>", offset.0)?;
+ }
+ }
+ gimli::AttributeValue::DebugLineStrRef(offset) => {
+ if let Ok(s) = dwarf.debug_line_str.get_str(offset) {
+ writeln!(w, "{}", s.to_string_lossy()?)?;
+ } else {
+ writeln!(w, "<.debug_line_str=0x{:08x}>", offset.0)?;
+ }
+ }
+ gimli::AttributeValue::String(s) => {
+ writeln!(w, "{}", s.to_string_lossy()?)?;
+ }
+ gimli::AttributeValue::Encoding(value) => {
+ writeln!(w, "{}", value)?;
+ }
+ gimli::AttributeValue::DecimalSign(value) => {
+ writeln!(w, "{}", value)?;
+ }
+ gimli::AttributeValue::Endianity(value) => {
+ writeln!(w, "{}", value)?;
+ }
+ gimli::AttributeValue::Accessibility(value) => {
+ writeln!(w, "{}", value)?;
+ }
+ gimli::AttributeValue::Visibility(value) => {
+ writeln!(w, "{}", value)?;
+ }
+ gimli::AttributeValue::Virtuality(value) => {
+ writeln!(w, "{}", value)?;
+ }
+ gimli::AttributeValue::Language(value) => {
+ writeln!(w, "{}", value)?;
+ }
+ gimli::AttributeValue::AddressClass(value) => {
+ writeln!(w, "{}", value)?;
+ }
+ gimli::AttributeValue::IdentifierCase(value) => {
+ writeln!(w, "{}", value)?;
+ }
+ gimli::AttributeValue::CallingConvention(value) => {
+ writeln!(w, "{}", value)?;
+ }
+ gimli::AttributeValue::Inline(value) => {
+ writeln!(w, "{}", value)?;
+ }
+ gimli::AttributeValue::Ordering(value) => {
+ writeln!(w, "{}", value)?;
+ }
+ gimli::AttributeValue::FileIndex(value) => {
+ write!(w, "0x{:08x}", value)?;
+ dump_file_index(w, value, unit, dwarf)?;
+ writeln!(w)?;
+ }
+ gimli::AttributeValue::DwoId(value) => {
+ writeln!(w, "0x{:016x}", value.0)?;
+ }
+ }
+
+ Ok(())
+}
+
+fn dump_type_signature<W: Write>(w: &mut W, signature: gimli::DebugTypeSignature) -> Result<()> {
+ write!(w, "0x{:016x}", signature.0)?;
+ Ok(())
+}
+
+fn dump_file_index<R: Reader, W: Write>(
+ w: &mut W,
+ file_index: u64,
+ unit: &gimli::Unit<R>,
+ dwarf: &gimli::Dwarf<R>,
+) -> Result<()> {
+ if file_index == 0 && unit.header.version() <= 4 {
+ return Ok(());
+ }
+ let header = match unit.line_program {
+ Some(ref program) => program.header(),
+ None => return Ok(()),
+ };
+ let file = match header.file(file_index) {
+ Some(file) => file,
+ None => {
+ writeln!(w, "Unable to get header for file {}", file_index)?;
+ return Ok(());
+ }
+ };
+ write!(w, " ")?;
+ if let Some(directory) = file.directory(header) {
+ let directory = dwarf.attr_string(unit, directory)?;
+ let directory = directory.to_string_lossy()?;
+ if file.directory_index() != 0 && !directory.starts_with('/') {
+ if let Some(ref comp_dir) = unit.comp_dir {
+ write!(w, "{}/", comp_dir.to_string_lossy()?,)?;
+ }
+ }
+ write!(w, "{}/", directory)?;
+ }
+ write!(
+ w,
+ "{}",
+ dwarf
+ .attr_string(unit, file.path_name())?
+ .to_string_lossy()?
+ )?;
+ Ok(())
+}
+
+fn dump_exprloc<R: Reader, W: Write>(
+ w: &mut W,
+ encoding: gimli::Encoding,
+ data: &gimli::Expression<R>,
+) -> Result<()> {
+ let mut pc = data.0.clone();
+ let mut space = false;
+ while pc.len() != 0 {
+ let pc_clone = pc.clone();
+ match gimli::Operation::parse(&mut pc, encoding) {
+ Ok(op) => {
+ if space {
+ write!(w, " ")?;
+ } else {
+ space = true;
+ }
+ dump_op(w, encoding, pc_clone, op)?;
+ }
+ Err(gimli::Error::InvalidExpression(op)) => {
+ writeln!(w, "WARNING: unsupported operation 0x{:02x}", op.0)?;
+ return Ok(());
+ }
+ Err(gimli::Error::UnsupportedRegister(register)) => {
+ writeln!(w, "WARNING: unsupported register {}", register)?;
+ return Ok(());
+ }
+ Err(gimli::Error::UnexpectedEof(_)) => {
+ writeln!(w, "WARNING: truncated or malformed expression")?;
+ return Ok(());
+ }
+ Err(e) => {
+ writeln!(w, "WARNING: unexpected operation parse error: {}", e)?;
+ return Ok(());
+ }
+ }
+ }
+ Ok(())
+}
+
+fn dump_op<R: Reader, W: Write>(
+ w: &mut W,
+ encoding: gimli::Encoding,
+ mut pc: R,
+ op: gimli::Operation<R>,
+) -> Result<()> {
+ let dwop = gimli::DwOp(pc.read_u8()?);
+ write!(w, "{}", dwop)?;
+ match op {
+ gimli::Operation::Deref {
+ base_type, size, ..
+ } => {
+ if dwop == gimli::DW_OP_deref_size || dwop == gimli::DW_OP_xderef_size {
+ write!(w, " {}", size)?;
+ }
+ if base_type != UnitOffset(0) {
+ write!(w, " type 0x{:08x}", base_type.0)?;
+ }
+ }
+ gimli::Operation::Pick { index } => {
+ if dwop == gimli::DW_OP_pick {
+ write!(w, " {}", index)?;
+ }
+ }
+ gimli::Operation::PlusConstant { value } => {
+ write!(w, " {}", value as i64)?;
+ }
+ gimli::Operation::Bra { target } => {
+ write!(w, " {}", target)?;
+ }
+ gimli::Operation::Skip { target } => {
+ write!(w, " {}", target)?;
+ }
+ gimli::Operation::SignedConstant { value } => match dwop {
+ gimli::DW_OP_const1s
+ | gimli::DW_OP_const2s
+ | gimli::DW_OP_const4s
+ | gimli::DW_OP_const8s
+ | gimli::DW_OP_consts => {
+ write!(w, " {}", value)?;
+ }
+ _ => {}
+ },
+ gimli::Operation::UnsignedConstant { value } => match dwop {
+ gimli::DW_OP_const1u
+ | gimli::DW_OP_const2u
+ | gimli::DW_OP_const4u
+ | gimli::DW_OP_const8u
+ | gimli::DW_OP_constu => {
+ write!(w, " {}", value)?;
+ }
+ _ => {
+ // These have the value encoded in the operation, eg DW_OP_lit0.
+ }
+ },
+ gimli::Operation::Register { register } => {
+ if dwop == gimli::DW_OP_regx {
+ write!(w, " {}", register.0)?;
+ }
+ }
+ gimli::Operation::RegisterOffset {
+ register,
+ offset,
+ base_type,
+ } => {
+ if dwop >= gimli::DW_OP_breg0 && dwop <= gimli::DW_OP_breg31 {
+ write!(w, "{:+}", offset)?;
+ } else {
+ write!(w, " {}", register.0)?;
+ if offset != 0 {
+ write!(w, "{:+}", offset)?;
+ }
+ if base_type != UnitOffset(0) {
+ write!(w, " type 0x{:08x}", base_type.0)?;
+ }
+ }
+ }
+ gimli::Operation::FrameOffset { offset } => {
+ write!(w, " {}", offset)?;
+ }
+ gimli::Operation::Call { offset } => match offset {
+ gimli::DieReference::UnitRef(gimli::UnitOffset(offset)) => {
+ write!(w, " 0x{:08x}", offset)?;
+ }
+ gimli::DieReference::DebugInfoRef(gimli::DebugInfoOffset(offset)) => {
+ write!(w, " 0x{:08x}", offset)?;
+ }
+ },
+ gimli::Operation::Piece {
+ size_in_bits,
+ bit_offset: None,
+ } => {
+ write!(w, " {}", size_in_bits / 8)?;
+ }
+ gimli::Operation::Piece {
+ size_in_bits,
+ bit_offset: Some(bit_offset),
+ } => {
+ write!(w, " 0x{:08x} offset 0x{:08x}", size_in_bits, bit_offset)?;
+ }
+ gimli::Operation::ImplicitValue { data } => {
+ let data = data.to_slice()?;
+ write!(w, " 0x{:08x} contents 0x", data.len())?;
+ for byte in data.iter() {
+ write!(w, "{:02x}", byte)?;
+ }
+ }
+ gimli::Operation::ImplicitPointer { value, byte_offset } => {
+ write!(w, " 0x{:08x} {}", value.0, byte_offset)?;
+ }
+ gimli::Operation::EntryValue { expression } => {
+ write!(w, "(")?;
+ dump_exprloc(w, encoding, &gimli::Expression(expression))?;
+ write!(w, ")")?;
+ }
+ gimli::Operation::ParameterRef { offset } => {
+ write!(w, " 0x{:08x}", offset.0)?;
+ }
+ gimli::Operation::Address { address } => {
+ write!(w, " 0x{:08x}", address)?;
+ }
+ gimli::Operation::AddressIndex { index } => {
+ write!(w, " 0x{:08x}", index.0)?;
+ }
+ gimli::Operation::ConstantIndex { index } => {
+ write!(w, " 0x{:08x}", index.0)?;
+ }
+ gimli::Operation::TypedLiteral { base_type, value } => {
+ write!(w, " type 0x{:08x} contents 0x", base_type.0)?;
+ for byte in value.to_slice()?.iter() {
+ write!(w, "{:02x}", byte)?;
+ }
+ }
+ gimli::Operation::Convert { base_type } => {
+ write!(w, " type 0x{:08x}", base_type.0)?;
+ }
+ gimli::Operation::Reinterpret { base_type } => {
+ write!(w, " type 0x{:08x}", base_type.0)?;
+ }
+ gimli::Operation::WasmLocal { index }
+ | gimli::Operation::WasmGlobal { index }
+ | gimli::Operation::WasmStack { index } => {
+ let wasmop = pc.read_u8()?;
+ write!(w, " 0x{:x} 0x{:x}", wasmop, index)?;
+ }
+ gimli::Operation::Drop
+ | gimli::Operation::Swap
+ | gimli::Operation::Rot
+ | gimli::Operation::Abs
+ | gimli::Operation::And
+ | gimli::Operation::Div
+ | gimli::Operation::Minus
+ | gimli::Operation::Mod
+ | gimli::Operation::Mul
+ | gimli::Operation::Neg
+ | gimli::Operation::Not
+ | gimli::Operation::Or
+ | gimli::Operation::Plus
+ | gimli::Operation::Shl
+ | gimli::Operation::Shr
+ | gimli::Operation::Shra
+ | gimli::Operation::Xor
+ | gimli::Operation::Eq
+ | gimli::Operation::Ge
+ | gimli::Operation::Gt
+ | gimli::Operation::Le
+ | gimli::Operation::Lt
+ | gimli::Operation::Ne
+ | gimli::Operation::Nop
+ | gimli::Operation::PushObjectAddress
+ | gimli::Operation::TLS
+ | gimli::Operation::CallFrameCFA
+ | gimli::Operation::StackValue => {}
+ };
+ Ok(())
+}
+
+fn dump_loc_list<R: Reader, W: Write>(
+ w: &mut W,
+ offset: gimli::LocationListsOffset<R::Offset>,
+ unit: &gimli::Unit<R>,
+ dwarf: &gimli::Dwarf<R>,
+) -> Result<()> {
+ let raw_locations = dwarf.raw_locations(unit, offset)?;
+ let raw_locations: Vec<_> = raw_locations.collect()?;
+ let mut locations = dwarf.locations(unit, offset)?;
+ writeln!(
+ w,
+ "<loclist at {}+0x{:08x} with {} entries>",
+ if unit.encoding().version < 5 {
+ ".debug_loc"
+ } else {
+ ".debug_loclists"
+ },
+ offset.0,
+ raw_locations.len()
+ )?;
+ for (i, raw) in raw_locations.iter().enumerate() {
+ write!(w, "\t\t\t[{:2}]", i)?;
+ match *raw {
+ gimli::RawLocListEntry::BaseAddress { addr } => {
+ writeln!(w, "<new base address 0x{:08x}>", addr)?;
+ }
+ gimli::RawLocListEntry::BaseAddressx { addr } => {
+ let addr_val = dwarf.address(unit, addr)?;
+ writeln!(w, "<new base addressx [{}]0x{:08x}>", addr.0, addr_val)?;
+ }
+ gimli::RawLocListEntry::StartxEndx {
+ begin,
+ end,
+ ref data,
+ } => {
+ let begin_val = dwarf.address(unit, begin)?;
+ let end_val = dwarf.address(unit, end)?;
+ let location = locations.next()?.unwrap();
+ write!(
+ w,
+ "<startx-endx \
+ low-off: [{}]0x{:08x} addr 0x{:08x} \
+ high-off: [{}]0x{:08x} addr 0x{:08x}>",
+ begin.0, begin_val, location.range.begin, end.0, end_val, location.range.end
+ )?;
+ dump_exprloc(w, unit.encoding(), data)?;
+ writeln!(w)?;
+ }
+ gimli::RawLocListEntry::StartxLength {
+ begin,
+ length,
+ ref data,
+ } => {
+ let begin_val = dwarf.address(unit, begin)?;
+ let location = locations.next()?.unwrap();
+ write!(
+ w,
+ "<start-length \
+ low-off: [{}]0x{:08x} addr 0x{:08x} \
+ high-off: 0x{:08x} addr 0x{:08x}>",
+ begin.0, begin_val, location.range.begin, length, location.range.end
+ )?;
+ dump_exprloc(w, unit.encoding(), data)?;
+ writeln!(w)?;
+ }
+ gimli::RawLocListEntry::AddressOrOffsetPair {
+ begin,
+ end,
+ ref data,
+ }
+ | gimli::RawLocListEntry::OffsetPair {
+ begin,
+ end,
+ ref data,
+ } => {
+ let location = locations.next()?.unwrap();
+ write!(
+ w,
+ "<offset pair \
+ low-off: 0x{:08x} addr 0x{:08x} \
+ high-off: 0x{:08x} addr 0x{:08x}>",
+ begin, location.range.begin, end, location.range.end
+ )?;
+ dump_exprloc(w, unit.encoding(), data)?;
+ writeln!(w)?;
+ }
+ gimli::RawLocListEntry::DefaultLocation { ref data } => {
+ write!(w, "<default location>")?;
+ dump_exprloc(w, unit.encoding(), data)?;
+ writeln!(w)?;
+ }
+ gimli::RawLocListEntry::StartEnd {
+ begin,
+ end,
+ ref data,
+ } => {
+ let location = locations.next()?.unwrap();
+ write!(
+ w,
+ "<start-end \
+ low-off: 0x{:08x} addr 0x{:08x} \
+ high-off: 0x{:08x} addr 0x{:08x}>",
+ begin, location.range.begin, end, location.range.end
+ )?;
+ dump_exprloc(w, unit.encoding(), data)?;
+ writeln!(w)?;
+ }
+ gimli::RawLocListEntry::StartLength {
+ begin,
+ length,
+ ref data,
+ } => {
+ let location = locations.next()?.unwrap();
+ write!(
+ w,
+ "<start-length \
+ low-off: 0x{:08x} addr 0x{:08x} \
+ high-off: 0x{:08x} addr 0x{:08x}>",
+ begin, location.range.begin, length, location.range.end
+ )?;
+ dump_exprloc(w, unit.encoding(), data)?;
+ writeln!(w)?;
+ }
+ };
+ }
+ Ok(())
+}
+
+fn dump_range_list<R: Reader, W: Write>(
+ w: &mut W,
+ offset: gimli::RangeListsOffset<R::Offset>,
+ unit: &gimli::Unit<R>,
+ dwarf: &gimli::Dwarf<R>,
+) -> Result<()> {
+ let raw_ranges = dwarf.raw_ranges(unit, offset)?;
+ let raw_ranges: Vec<_> = raw_ranges.collect()?;
+ let mut ranges = dwarf.ranges(unit, offset)?;
+ writeln!(
+ w,
+ "<rnglist at {}+0x{:08x} with {} entries>",
+ if unit.encoding().version < 5 {
+ ".debug_ranges"
+ } else {
+ ".debug_rnglists"
+ },
+ offset.0,
+ raw_ranges.len()
+ )?;
+ for (i, raw) in raw_ranges.iter().enumerate() {
+ write!(w, "\t\t\t[{:2}] ", i)?;
+ match *raw {
+ gimli::RawRngListEntry::AddressOrOffsetPair { begin, end } => {
+ let range = ranges.next()?.unwrap();
+ writeln!(
+ w,
+ "<address pair \
+ low-off: 0x{:08x} addr 0x{:08x} \
+ high-off: 0x{:08x} addr 0x{:08x}>",
+ begin, range.begin, end, range.end
+ )?;
+ }
+ gimli::RawRngListEntry::BaseAddress { addr } => {
+ writeln!(w, "<new base address 0x{:08x}>", addr)?;
+ }
+ gimli::RawRngListEntry::BaseAddressx { addr } => {
+ let addr_val = dwarf.address(unit, addr)?;
+ writeln!(w, "<new base addressx [{}]0x{:08x}>", addr.0, addr_val)?;
+ }
+ gimli::RawRngListEntry::StartxEndx { begin, end } => {
+ let begin_val = dwarf.address(unit, begin)?;
+ let end_val = dwarf.address(unit, end)?;
+ let range = if begin_val == end_val {
+ gimli::Range {
+ begin: begin_val,
+ end: end_val,
+ }
+ } else {
+ ranges.next()?.unwrap()
+ };
+ writeln!(
+ w,
+ "<startx-endx \
+ low-off: [{}]0x{:08x} addr 0x{:08x} \
+ high-off: [{}]0x{:08x} addr 0x{:08x}>",
+ begin.0, begin_val, range.begin, end.0, end_val, range.end
+ )?;
+ }
+ gimli::RawRngListEntry::StartxLength { begin, length } => {
+ let begin_val = dwarf.address(unit, begin)?;
+ let range = ranges.next()?.unwrap();
+ writeln!(
+ w,
+ "<startx-length \
+ low-off: [{}]0x{:08x} addr 0x{:08x} \
+ high-off: 0x{:08x} addr 0x{:08x}>",
+ begin.0, begin_val, range.begin, length, range.end
+ )?;
+ }
+ gimli::RawRngListEntry::OffsetPair { begin, end } => {
+ let range = ranges.next()?.unwrap();
+ writeln!(
+ w,
+ "<offset pair \
+ low-off: 0x{:08x} addr 0x{:08x} \
+ high-off: 0x{:08x} addr 0x{:08x}>",
+ begin, range.begin, end, range.end
+ )?;
+ }
+ gimli::RawRngListEntry::StartEnd { begin, end } => {
+ let range = if begin == end {
+ gimli::Range { begin, end }
+ } else {
+ ranges.next()?.unwrap()
+ };
+ writeln!(
+ w,
+ "<start-end \
+ low-off: 0x{:08x} addr 0x{:08x} \
+ high-off: 0x{:08x} addr 0x{:08x}>",
+ begin, range.begin, end, range.end
+ )?;
+ }
+ gimli::RawRngListEntry::StartLength { begin, length } => {
+ let range = ranges.next()?.unwrap();
+ writeln!(
+ w,
+ "<start-length \
+ low-off: 0x{:08x} addr 0x{:08x} \
+ high-off: 0x{:08x} addr 0x{:08x}>",
+ begin, range.begin, length, range.end
+ )?;
+ }
+ };
+ }
+ Ok(())
+}
+
+fn dump_line<R: Reader, W: Write>(w: &mut W, dwarf: &gimli::Dwarf<R>) -> Result<()> {
+ let mut iter = dwarf.units();
+ while let Some(header) = iter.next()? {
+ writeln!(
+ w,
+ "\n.debug_line: line number info for unit at .debug_info offset 0x{:08x}",
+ header.offset().as_debug_info_offset().unwrap().0
+ )?;
+ let unit = match dwarf.unit(header) {
+ Ok(unit) => unit,
+ Err(err) => {
+ writeln_error(
+ w,
+ dwarf,
+ err.into(),
+ "Failed to parse unit root entry for dump_line",
+ )?;
+ continue;
+ }
+ };
+ match dump_line_program(w, &unit, dwarf) {
+ Ok(_) => (),
+ Err(Error::IoError) => return Err(Error::IoError),
+ Err(err) => writeln_error(w, dwarf, err, "Failed to dump line program")?,
+ }
+ }
+ Ok(())
+}
+
+fn dump_line_program<R: Reader, W: Write>(
+ w: &mut W,
+ unit: &gimli::Unit<R>,
+ dwarf: &gimli::Dwarf<R>,
+) -> Result<()> {
+ if let Some(program) = unit.line_program.clone() {
+ {
+ let header = program.header();
+ writeln!(w)?;
+ writeln!(
+ w,
+ "Offset: 0x{:x}",
+ header.offset().0
+ )?;
+ writeln!(
+ w,
+ "Length: {}",
+ header.unit_length()
+ )?;
+ writeln!(
+ w,
+ "DWARF version: {}",
+ header.version()
+ )?;
+ writeln!(
+ w,
+ "Address size: {}",
+ header.address_size()
+ )?;
+ writeln!(
+ w,
+ "Prologue length: {}",
+ header.header_length()
+ )?;
+ writeln!(
+ w,
+ "Minimum instruction length: {}",
+ header.minimum_instruction_length()
+ )?;
+ writeln!(
+ w,
+ "Maximum operations per instruction: {}",
+ header.maximum_operations_per_instruction()
+ )?;
+ writeln!(
+ w,
+ "Default is_stmt: {}",
+ header.default_is_stmt()
+ )?;
+ writeln!(
+ w,
+ "Line base: {}",
+ header.line_base()
+ )?;
+ writeln!(
+ w,
+ "Line range: {}",
+ header.line_range()
+ )?;
+ writeln!(
+ w,
+ "Opcode base: {}",
+ header.opcode_base()
+ )?;
+
+ writeln!(w)?;
+ writeln!(w, "Opcodes:")?;
+ for (i, length) in header
+ .standard_opcode_lengths()
+ .to_slice()?
+ .iter()
+ .enumerate()
+ {
+ writeln!(w, " Opcode {} has {} args", i + 1, length)?;
+ }
+
+ let base = if header.version() >= 5 { 0 } else { 1 };
+ writeln!(w)?;
+ writeln!(w, "The Directory Table:")?;
+ for (i, dir) in header.include_directories().iter().enumerate() {
+ writeln!(
+ w,
+ " {} {}",
+ base + i,
+ dwarf.attr_string(unit, dir.clone())?.to_string_lossy()?
+ )?;
+ }
+
+ writeln!(w)?;
+ writeln!(w, "The File Name Table")?;
+ write!(w, " Entry\tDir\tTime\tSize")?;
+ if header.file_has_md5() {
+ write!(w, "\tMD5\t\t\t\t")?;
+ }
+ writeln!(w, "\tName")?;
+ for (i, file) in header.file_names().iter().enumerate() {
+ write!(
+ w,
+ " {}\t{}\t{}\t{}",
+ base + i,
+ file.directory_index(),
+ file.timestamp(),
+ file.size(),
+ )?;
+ if header.file_has_md5() {
+ let md5 = file.md5();
+ write!(w, "\t")?;
+ for i in 0..16 {
+ write!(w, "{:02X}", md5[i])?;
+ }
+ }
+ writeln!(
+ w,
+ "\t{}",
+ dwarf
+ .attr_string(unit, file.path_name())?
+ .to_string_lossy()?
+ )?;
+ }
+
+ writeln!(w)?;
+ writeln!(w, "Line Number Instructions:")?;
+ let mut instructions = header.instructions();
+ while let Some(instruction) = instructions.next_instruction(header)? {
+ writeln!(w, " {}", instruction)?;
+ }
+
+ writeln!(w)?;
+ writeln!(w, "Line Number Rows:")?;
+ writeln!(w, "<pc> [lno,col]")?;
+ }
+ let mut rows = program.rows();
+ let mut file_index = std::u64::MAX;
+ while let Some((header, row)) = rows.next_row()? {
+ let line = match row.line() {
+ Some(line) => line.get(),
+ None => 0,
+ };
+ let column = match row.column() {
+ gimli::ColumnType::Column(column) => column.get(),
+ gimli::ColumnType::LeftEdge => 0,
+ };
+ write!(w, "0x{:08x} [{:4},{:2}]", row.address(), line, column)?;
+ if row.is_stmt() {
+ write!(w, " NS")?;
+ }
+ if row.basic_block() {
+ write!(w, " BB")?;
+ }
+ if row.end_sequence() {
+ write!(w, " ET")?;
+ }
+ if row.prologue_end() {
+ write!(w, " PE")?;
+ }
+ if row.epilogue_begin() {
+ write!(w, " EB")?;
+ }
+ if row.isa() != 0 {
+ write!(w, " IS={}", row.isa())?;
+ }
+ if row.discriminator() != 0 {
+ write!(w, " DI={}", row.discriminator())?;
+ }
+ if file_index != row.file_index() {
+ file_index = row.file_index();
+ if let Some(file) = row.file(header) {
+ if let Some(directory) = file.directory(header) {
+ write!(
+ w,
+ " uri: \"{}/{}\"",
+ dwarf.attr_string(unit, directory)?.to_string_lossy()?,
+ dwarf
+ .attr_string(unit, file.path_name())?
+ .to_string_lossy()?
+ )?;
+ } else {
+ write!(
+ w,
+ " uri: \"{}\"",
+ dwarf
+ .attr_string(unit, file.path_name())?
+ .to_string_lossy()?
+ )?;
+ }
+ }
+ }
+ writeln!(w)?;
+ }
+ }
+ Ok(())
+}
+
+fn dump_pubnames<R: Reader, W: Write>(
+ w: &mut W,
+ debug_pubnames: &gimli::DebugPubNames<R>,
+ debug_info: &gimli::DebugInfo<R>,
+) -> Result<()> {
+ writeln!(w, "\n.debug_pubnames")?;
+
+ let mut cu_offset;
+ let mut cu_die_offset = gimli::DebugInfoOffset(0);
+ let mut prev_cu_offset = None;
+ let mut pubnames = debug_pubnames.items();
+ while let Some(pubname) = pubnames.next()? {
+ cu_offset = pubname.unit_header_offset();
+ if Some(cu_offset) != prev_cu_offset {
+ let cu = debug_info.header_from_offset(cu_offset)?;
+ cu_die_offset = gimli::DebugInfoOffset(cu_offset.0 + cu.header_size());
+ prev_cu_offset = Some(cu_offset);
+ }
+ let die_in_cu = pubname.die_offset();
+ let die_in_sect = cu_offset.0 + die_in_cu.0;
+ writeln!(w,
+ "global die-in-sect 0x{:08x}, cu-in-sect 0x{:08x}, die-in-cu 0x{:08x}, cu-header-in-sect 0x{:08x} '{}'",
+ die_in_sect,
+ cu_die_offset.0,
+ die_in_cu.0,
+ cu_offset.0,
+ pubname.name().to_string_lossy()?
+ )?;
+ }
+ Ok(())
+}
+
+fn dump_pubtypes<R: Reader, W: Write>(
+ w: &mut W,
+ debug_pubtypes: &gimli::DebugPubTypes<R>,
+ debug_info: &gimli::DebugInfo<R>,
+) -> Result<()> {
+ writeln!(w, "\n.debug_pubtypes")?;
+
+ let mut cu_offset;
+ let mut cu_die_offset = gimli::DebugInfoOffset(0);
+ let mut prev_cu_offset = None;
+ let mut pubtypes = debug_pubtypes.items();
+ while let Some(pubtype) = pubtypes.next()? {
+ cu_offset = pubtype.unit_header_offset();
+ if Some(cu_offset) != prev_cu_offset {
+ let cu = debug_info.header_from_offset(cu_offset)?;
+ cu_die_offset = gimli::DebugInfoOffset(cu_offset.0 + cu.header_size());
+ prev_cu_offset = Some(cu_offset);
+ }
+ let die_in_cu = pubtype.die_offset();
+ let die_in_sect = cu_offset.0 + die_in_cu.0;
+ writeln!(w,
+ "pubtype die-in-sect 0x{:08x}, cu-in-sect 0x{:08x}, die-in-cu 0x{:08x}, cu-header-in-sect 0x{:08x} '{}'",
+ die_in_sect,
+ cu_die_offset.0,
+ die_in_cu.0,
+ cu_offset.0,
+ pubtype.name().to_string_lossy()?
+ )?;
+ }
+ Ok(())
+}
+
+fn dump_aranges<R: Reader, W: Write>(
+ w: &mut W,
+ debug_aranges: &gimli::DebugAranges<R>,
+) -> Result<()> {
+ writeln!(w, "\n.debug_aranges")?;
+
+ let mut headers = debug_aranges.headers();
+ while let Some(header) = headers.next()? {
+ writeln!(
+ w,
+ "Address Range Header: length = 0x{:08x}, version = 0x{:04x}, cu_offset = 0x{:08x}, addr_size = 0x{:02x}, seg_size = 0x{:02x}",
+ header.length(),
+ header.encoding().version,
+ header.debug_info_offset().0,
+ header.encoding().address_size,
+ header.segment_size(),
+ )?;
+ let mut aranges = header.entries();
+ while let Some(arange) = aranges.next()? {
+ let range = arange.range();
+ if let Some(segment) = arange.segment() {
+ writeln!(
+ w,
+ "[0x{:016x}, 0x{:016x}) segment 0x{:x}",
+ range.begin, range.end, segment
+ )?;
+ } else {
+ writeln!(w, "[0x{:016x}, 0x{:016x})", range.begin, range.end)?;
+ }
+ }
+ }
+ Ok(())
+}
diff --git a/vendor/gimli-0.26.2/examples/simple.rs b/vendor/gimli-0.26.2/examples/simple.rs
new file mode 100644
index 000000000..7c958d45c
--- /dev/null
+++ b/vendor/gimli-0.26.2/examples/simple.rs
@@ -0,0 +1,67 @@
+//! A simple example of parsing `.debug_info`.
+
+use object::{Object, ObjectSection};
+use std::{borrow, env, fs};
+
+fn main() {
+ for path in env::args().skip(1) {
+ let file = fs::File::open(&path).unwrap();
+ let mmap = unsafe { memmap2::Mmap::map(&file).unwrap() };
+ let object = object::File::parse(&*mmap).unwrap();
+ let endian = if object.is_little_endian() {
+ gimli::RunTimeEndian::Little
+ } else {
+ gimli::RunTimeEndian::Big
+ };
+ dump_file(&object, endian).unwrap();
+ }
+}
+
+fn dump_file(object: &object::File, endian: gimli::RunTimeEndian) -> Result<(), gimli::Error> {
+ // Load a section and return as `Cow<[u8]>`.
+ let load_section = |id: gimli::SectionId| -> Result<borrow::Cow<[u8]>, gimli::Error> {
+ match object.section_by_name(id.name()) {
+ Some(ref section) => Ok(section
+ .uncompressed_data()
+ .unwrap_or(borrow::Cow::Borrowed(&[][..]))),
+ None => Ok(borrow::Cow::Borrowed(&[][..])),
+ }
+ };
+
+ // Load all of the sections.
+ let dwarf_cow = gimli::Dwarf::load(&load_section)?;
+
+ // Borrow a `Cow<[u8]>` to create an `EndianSlice`.
+ let borrow_section: &dyn for<'a> Fn(
+ &'a borrow::Cow<[u8]>,
+ ) -> gimli::EndianSlice<'a, gimli::RunTimeEndian> =
+ &|section| gimli::EndianSlice::new(&*section, endian);
+
+ // Create `EndianSlice`s for all of the sections.
+ let dwarf = dwarf_cow.borrow(&borrow_section);
+
+ // Iterate over the compilation units.
+ let mut iter = dwarf.units();
+ while let Some(header) = iter.next()? {
+ println!(
+ "Unit at <.debug_info+0x{:x}>",
+ header.offset().as_debug_info_offset().unwrap().0
+ );
+ let unit = dwarf.unit(header)?;
+
+ // Iterate over the Debugging Information Entries (DIEs) in the unit.
+ let mut depth = 0;
+ let mut entries = unit.entries();
+ while let Some((delta_depth, entry)) = entries.next_dfs()? {
+ depth += delta_depth;
+ println!("<{}><{:x}> {}", depth, entry.offset().0, entry.tag());
+
+ // Iterate over the attributes in the DIE.
+ let mut attrs = entry.attrs();
+ while let Some(attr) = attrs.next()? {
+ println!(" {}: {:?}", attr.name(), attr.value());
+ }
+ }
+ }
+ Ok(())
+}
diff --git a/vendor/gimli-0.26.2/examples/simple_line.rs b/vendor/gimli-0.26.2/examples/simple_line.rs
new file mode 100644
index 000000000..87b224cda
--- /dev/null
+++ b/vendor/gimli-0.26.2/examples/simple_line.rs
@@ -0,0 +1,106 @@
+//! A simple example of parsing `.debug_line`.
+
+use object::{Object, ObjectSection};
+use std::{borrow, env, fs, path};
+
+fn main() {
+ for path in env::args().skip(1) {
+ let file = fs::File::open(&path).unwrap();
+ let mmap = unsafe { memmap2::Mmap::map(&file).unwrap() };
+ let object = object::File::parse(&*mmap).unwrap();
+ let endian = if object.is_little_endian() {
+ gimli::RunTimeEndian::Little
+ } else {
+ gimli::RunTimeEndian::Big
+ };
+ dump_file(&object, endian).unwrap();
+ }
+}
+
+fn dump_file(object: &object::File, endian: gimli::RunTimeEndian) -> Result<(), gimli::Error> {
+ // Load a section and return as `Cow<[u8]>`.
+ let load_section = |id: gimli::SectionId| -> Result<borrow::Cow<[u8]>, gimli::Error> {
+ match object.section_by_name(id.name()) {
+ Some(ref section) => Ok(section
+ .uncompressed_data()
+ .unwrap_or(borrow::Cow::Borrowed(&[][..]))),
+ None => Ok(borrow::Cow::Borrowed(&[][..])),
+ }
+ };
+
+ // Load all of the sections.
+ let dwarf_cow = gimli::Dwarf::load(&load_section)?;
+
+ // Borrow a `Cow<[u8]>` to create an `EndianSlice`.
+ let borrow_section: &dyn for<'a> Fn(
+ &'a borrow::Cow<[u8]>,
+ ) -> gimli::EndianSlice<'a, gimli::RunTimeEndian> =
+ &|section| gimli::EndianSlice::new(&*section, endian);
+
+ // Create `EndianSlice`s for all of the sections.
+ let dwarf = dwarf_cow.borrow(&borrow_section);
+
+ // Iterate over the compilation units.
+ let mut iter = dwarf.units();
+ while let Some(header) = iter.next()? {
+ println!(
+ "Line number info for unit at <.debug_info+0x{:x}>",
+ header.offset().as_debug_info_offset().unwrap().0
+ );
+ let unit = dwarf.unit(header)?;
+
+ // Get the line program for the compilation unit.
+ if let Some(program) = unit.line_program.clone() {
+ let comp_dir = if let Some(ref dir) = unit.comp_dir {
+ path::PathBuf::from(dir.to_string_lossy().into_owned())
+ } else {
+ path::PathBuf::new()
+ };
+
+ // Iterate over the line program rows.
+ let mut rows = program.rows();
+ while let Some((header, row)) = rows.next_row()? {
+ if row.end_sequence() {
+ // End of sequence indicates a possible gap in addresses.
+ println!("{:x} end-sequence", row.address());
+ } else {
+ // Determine the path. Real applications should cache this for performance.
+ let mut path = path::PathBuf::new();
+ if let Some(file) = row.file(header) {
+ path = comp_dir.clone();
+
+ // The directory index 0 is defined to correspond to the compilation unit directory.
+ if file.directory_index() != 0 {
+ if let Some(dir) = file.directory(header) {
+ path.push(
+ dwarf.attr_string(&unit, dir)?.to_string_lossy().as_ref(),
+ );
+ }
+ }
+
+ path.push(
+ dwarf
+ .attr_string(&unit, file.path_name())?
+ .to_string_lossy()
+ .as_ref(),
+ );
+ }
+
+ // Determine line/column. DWARF line/column is never 0, so we use that
+ // but other applications may want to display this differently.
+ let line = match row.line() {
+ Some(line) => line.get(),
+ None => 0,
+ };
+ let column = match row.column() {
+ gimli::ColumnType::LeftEdge => 0,
+ gimli::ColumnType::Column(column) => column.get(),
+ };
+
+ println!("{:x} {}:{}:{}", row.address(), path.display(), line, column);
+ }
+ }
+ }
+ }
+ Ok(())
+}
diff --git a/vendor/gimli-0.26.2/fixtures/self/README.md b/vendor/gimli-0.26.2/fixtures/self/README.md
new file mode 100644
index 000000000..91053d9b4
--- /dev/null
+++ b/vendor/gimli-0.26.2/fixtures/self/README.md
@@ -0,0 +1,147 @@
+# What are these files?
+
+These files are the DWARF data generated for (an early version of) this
+library. Each file corresponds is a section from the built library's object
+file. By splitting the sections out to their own files, we don't need to worry
+about cross platform and cross object file format issues when running examples.
+
+# Updating and adding new sections
+
+## macOS
+
+Use `otool` to list the sections of a binary:
+
+```
+$ otool -l path/to/binary
+```
+
+You should see output similar to this:
+
+```
+Load command 0
+ cmd LC_SEGMENT_64
+ cmdsize 72
+ segname __PAGEZERO
+ vmaddr 0x0000000000000000
+ vmsize 0x0000000100000000
+ fileoff 0
+ filesize 0
+ maxprot 0x00000000
+ initprot 0x00000000
+ nsects 0
+ flags 0x0
+Load command 1
+ cmd LC_SEGMENT_64
+ cmdsize 712
+ segname __TEXT
+ vmaddr 0x0000000100000000
+ vmsize 0x00000000001b7000
+ fileoff 0
+ filesize 1798144
+ maxprot 0x00000007
+ initprot 0x00000005
+ nsects 8
+ flags 0x0
+Section
+ sectname __text
+ segname __TEXT
+ addr 0x0000000100000a50
+ size 0x0000000000170716
+ offset 2640
+ align 2^4 (16)
+ reloff 0
+ nreloc 0
+ flags 0x80000400
+ reserved1 0
+ reserved2 0
+```
+
+Etc.
+
+Find the `Section` entry of the section you'd like to isolate. For example, if
+you're looking for `eh_frame`, find an entry like this:
+
+```
+Section
+ sectname __eh_frame
+ segname __TEXT
+ addr 0x0000000100192f38
+ size 0x00000000000240c8
+ offset 1650488
+ align 2^3 (8)
+ reloff 0
+ nreloc 0
+ flags 0x00000000
+ reserved1 0
+ reserved2 0
+```
+
+Then use `dd` to copy `size` bytes starting from `offset`:
+
+```
+$ dd bs=1 skip=1650488 count=$(printf "%d" 0x00000000000240c8) if=path/to/binary of=fixtures/self/eh_frame
+```
+
+Finally, use `otool` and `hexdump` to verify that the isolated section has the
+same data as the section within the binary:
+
+```
+$ otool -s __TEXT __eh_frame path/to/binary | head
+path/to/binary:
+Contents of (__TEXT,__eh_frame) section
+0000000100192f38 14 00 00 00 00 00 00 00 01 7a 52 00 01 78 10 01
+0000000100192f48 10 0c 07 08 90 01 00 00 24 00 00 00 1c 00 00 00
+0000000100192f58 f8 da e6 ff ff ff ff ff 66 00 00 00 00 00 00 00
+0000000100192f68 00 41 0e 10 86 02 43 0d 06 00 00 00 00 00 00 00
+0000000100192f78 1c 00 00 00 00 00 00 00 01 7a 50 4c 52 00 01 78
+0000000100192f88 10 07 9b 9d 40 02 00 10 10 0c 07 08 90 01 00 00
+0000000100192f98 2c 00 00 00 24 00 00 00 20 db e6 ff ff ff ff ff
+0000000100192fa8 8d 00 00 00 00 00 00 00 08 37 e7 fd ff ff ff ff
+
+$ otool -s __TEXT __eh_frame path/to/binary | tail
+00000001001b6f68 9a 0a 00 00 00 00 00 00 00 41 0e 10 86 02 43 0d
+00000001001b6f78 06 50 83 07 8c 06 8d 05 8e 04 8f 03 00 00 00 00
+00000001001b6f88 24 00 00 00 7c 0e 00 00 30 a0 fb ff ff ff ff ff
+00000001001b6f98 15 00 00 00 00 00 00 00 00 41 0e 10 86 02 43 0d
+00000001001b6fa8 06 00 00 00 00 00 00 00 24 00 00 00 a4 0e 00 00
+00000001001b6fb8 28 a0 fb ff ff ff ff ff 1c 00 00 00 00 00 00 00
+00000001001b6fc8 00 41 0e 10 86 02 43 0d 06 00 00 00 00 00 00 00
+00000001001b6fd8 24 00 00 00 cc 0e 00 00 20 a0 fb ff ff ff ff ff
+00000001001b6fe8 66 01 00 00 00 00 00 00 00 41 0e 10 86 02 43 0d
+00000001001b6ff8 06 00 00 00 00 00 00 00
+```
+
+This should be the same, ignoring the leading offsets:
+
+```
+$ hexdump fixtures/self/eh_frame | head
+0000000 14 00 00 00 00 00 00 00 01 7a 52 00 01 78 10 01
+0000010 10 0c 07 08 90 01 00 00 24 00 00 00 1c 00 00 00
+0000020 f8 da e6 ff ff ff ff ff 66 00 00 00 00 00 00 00
+0000030 00 41 0e 10 86 02 43 0d 06 00 00 00 00 00 00 00
+0000040 1c 00 00 00 00 00 00 00 01 7a 50 4c 52 00 01 78
+0000050 10 07 9b 9d 40 02 00 10 10 0c 07 08 90 01 00 00
+0000060 2c 00 00 00 24 00 00 00 20 db e6 ff ff ff ff ff
+0000070 8d 00 00 00 00 00 00 00 08 37 e7 fd ff ff ff ff
+0000080 ff 41 0e 10 86 02 43 0d 06 00 00 00 00 00 00 00
+0000090 24 00 00 00 94 00 00 00 80 db e6 ff ff ff ff ff
+
+$ hexdump fixtures/self/eh_frame | tail
+0024040 06 50 83 07 8c 06 8d 05 8e 04 8f 03 00 00 00 00
+0024050 24 00 00 00 7c 0e 00 00 30 a0 fb ff ff ff ff ff
+0024060 15 00 00 00 00 00 00 00 00 41 0e 10 86 02 43 0d
+0024070 06 00 00 00 00 00 00 00 24 00 00 00 a4 0e 00 00
+0024080 28 a0 fb ff ff ff ff ff 1c 00 00 00 00 00 00 00
+0024090 00 41 0e 10 86 02 43 0d 06 00 00 00 00 00 00 00
+00240a0 24 00 00 00 cc 0e 00 00 20 a0 fb ff ff ff ff ff
+00240b0 66 01 00 00 00 00 00 00 00 41 0e 10 86 02 43 0d
+00240c0 06 00 00 00 00 00 00 00
+```
+
+## Linux
+
+Something like this:
+
+```
+objcopy --dump-section .eh_frame=fixtures/self/eh_frame path/to/binary
+```
diff --git a/vendor/gimli-0.26.2/fixtures/self/debug_abbrev b/vendor/gimli-0.26.2/fixtures/self/debug_abbrev
new file mode 100644
index 000000000..809e61152
--- /dev/null
+++ b/vendor/gimli-0.26.2/fixtures/self/debug_abbrev
Binary files differ
diff --git a/vendor/gimli-0.26.2/fixtures/self/debug_aranges b/vendor/gimli-0.26.2/fixtures/self/debug_aranges
new file mode 100644
index 000000000..b2d983d78
--- /dev/null
+++ b/vendor/gimli-0.26.2/fixtures/self/debug_aranges
Binary files differ
diff --git a/vendor/gimli-0.26.2/fixtures/self/debug_info b/vendor/gimli-0.26.2/fixtures/self/debug_info
new file mode 100644
index 000000000..aa430a5ce
--- /dev/null
+++ b/vendor/gimli-0.26.2/fixtures/self/debug_info
Binary files differ
diff --git a/vendor/gimli-0.26.2/fixtures/self/debug_inlined b/vendor/gimli-0.26.2/fixtures/self/debug_inlined
new file mode 100644
index 000000000..949d18c93
--- /dev/null
+++ b/vendor/gimli-0.26.2/fixtures/self/debug_inlined
Binary files differ
diff --git a/vendor/gimli-0.26.2/fixtures/self/debug_line b/vendor/gimli-0.26.2/fixtures/self/debug_line
new file mode 100644
index 000000000..896a07364
--- /dev/null
+++ b/vendor/gimli-0.26.2/fixtures/self/debug_line
Binary files differ
diff --git a/vendor/gimli-0.26.2/fixtures/self/debug_loc b/vendor/gimli-0.26.2/fixtures/self/debug_loc
new file mode 100644
index 000000000..3fcdb32ba
--- /dev/null
+++ b/vendor/gimli-0.26.2/fixtures/self/debug_loc
Binary files differ
diff --git a/vendor/gimli-0.26.2/fixtures/self/debug_pubnames b/vendor/gimli-0.26.2/fixtures/self/debug_pubnames
new file mode 100644
index 000000000..bbcd62e24
--- /dev/null
+++ b/vendor/gimli-0.26.2/fixtures/self/debug_pubnames
Binary files differ
diff --git a/vendor/gimli-0.26.2/fixtures/self/debug_pubtypes b/vendor/gimli-0.26.2/fixtures/self/debug_pubtypes
new file mode 100644
index 000000000..68b4e0405
--- /dev/null
+++ b/vendor/gimli-0.26.2/fixtures/self/debug_pubtypes
Binary files differ
diff --git a/vendor/gimli-0.26.2/fixtures/self/debug_ranges b/vendor/gimli-0.26.2/fixtures/self/debug_ranges
new file mode 100644
index 000000000..a5f52ed4a
--- /dev/null
+++ b/vendor/gimli-0.26.2/fixtures/self/debug_ranges
Binary files differ
diff --git a/vendor/gimli-0.26.2/fixtures/self/debug_str b/vendor/gimli-0.26.2/fixtures/self/debug_str
new file mode 100644
index 000000000..da35ee574
--- /dev/null
+++ b/vendor/gimli-0.26.2/fixtures/self/debug_str
Binary files differ
diff --git a/vendor/gimli-0.26.2/fixtures/self/eh_frame b/vendor/gimli-0.26.2/fixtures/self/eh_frame
new file mode 100644
index 000000000..1d4df1a61
--- /dev/null
+++ b/vendor/gimli-0.26.2/fixtures/self/eh_frame
Binary files differ
diff --git a/vendor/gimli-0.26.2/fixtures/self/eh_frame_hdr b/vendor/gimli-0.26.2/fixtures/self/eh_frame_hdr
new file mode 100644
index 000000000..a590ba213
--- /dev/null
+++ b/vendor/gimli-0.26.2/fixtures/self/eh_frame_hdr
Binary files differ
diff --git a/vendor/gimli-0.26.2/rustfmt.toml b/vendor/gimli-0.26.2/rustfmt.toml
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/vendor/gimli-0.26.2/rustfmt.toml
diff --git a/vendor/gimli-0.26.2/src/arch.rs b/vendor/gimli-0.26.2/src/arch.rs
new file mode 100644
index 000000000..f5b2e5ed8
--- /dev/null
+++ b/vendor/gimli-0.26.2/src/arch.rs
@@ -0,0 +1,603 @@
+use crate::common::Register;
+
+macro_rules! registers {
+ ($struct_name:ident, { $($name:ident = ($val:expr, $disp:expr)),+ $(,)? }
+ $(, aliases { $($alias_name:ident = ($alias_val:expr, $alias_disp:expr)),+ $(,)? })?) => {
+ #[allow(missing_docs)]
+ impl $struct_name {
+ $(
+ pub const $name: Register = Register($val);
+ )+
+ $(
+ $(pub const $alias_name: Register = Register($alias_val);)+
+ )*
+ }
+
+ impl $struct_name {
+ /// The name of a register, or `None` if the register number is unknown.
+ ///
+ /// Only returns the primary name for registers that alias with others.
+ pub fn register_name(register: Register) -> Option<&'static str> {
+ match register {
+ $(
+ Self::$name => Some($disp),
+ )+
+ _ => return None,
+ }
+ }
+
+ /// Converts a register name into a register number.
+ pub fn name_to_register(value: &str) -> Option<Register> {
+ match value {
+ $(
+ $disp => Some(Self::$name),
+ )+
+ $(
+ $($alias_disp => Some(Self::$alias_name),)+
+ )*
+ _ => return None,
+ }
+ }
+ }
+ };
+}
+
+/// ARM architecture specific definitions.
+///
+/// See [DWARF for the ARM Architecture](https://developer.arm.com/documentation/ihi0040/c/).
+#[derive(Debug, Clone, Copy)]
+pub struct Arm;
+
+registers!(Arm, {
+ R0 = (0, "R0"),
+ R1 = (1, "R1"),
+ R2 = (2, "R2"),
+ R3 = (3, "R3"),
+ R4 = (4, "R4"),
+ R5 = (5, "R5"),
+ R6 = (6, "R6"),
+ R7 = (7, "R7"),
+ R8 = (8, "R8"),
+ R9 = (9, "R9"),
+ R10 = (10, "R10"),
+ R11 = (11, "R11"),
+ R12 = (12, "R12"),
+ R13 = (13, "R13"),
+ R14 = (14, "R14"),
+ R15 = (15, "R15"),
+
+ WCGR0 = (104, "wCGR0"),
+ WCGR1 = (105, "wCGR1"),
+ WCGR2 = (106, "wCGR2"),
+ WCGR3 = (107, "wCGR3"),
+ WCGR4 = (108, "wCGR4"),
+ WCGR5 = (109, "wCGR5"),
+ WCGR6 = (110, "wCGR6"),
+ WCGR7 = (111, "wCGR7"),
+
+ WR0 = (112, "wR0"),
+ WR1 = (113, "wR1"),
+ WR2 = (114, "wR2"),
+ WR3 = (115, "wR3"),
+ WR4 = (116, "wR4"),
+ WR5 = (117, "wR5"),
+ WR6 = (118, "wR6"),
+ WR7 = (119, "wR7"),
+ WR8 = (120, "wR8"),
+ WR9 = (121, "wR9"),
+ WR10 = (122, "wR10"),
+ WR11 = (123, "wR11"),
+ WR12 = (124, "wR12"),
+ WR13 = (125, "wR13"),
+ WR14 = (126, "wR14"),
+ WR15 = (127, "wR15"),
+
+ SPSR = (128, "SPSR"),
+ SPSR_FIQ = (129, "SPSR_FIQ"),
+ SPSR_IRQ = (130, "SPSR_IRQ"),
+ SPSR_ABT = (131, "SPSR_ABT"),
+ SPSR_UND = (132, "SPSR_UND"),
+ SPSR_SVC = (133, "SPSR_SVC"),
+
+ R8_USR = (144, "R8_USR"),
+ R9_USR = (145, "R9_USR"),
+ R10_USR = (146, "R10_USR"),
+ R11_USR = (147, "R11_USR"),
+ R12_USR = (148, "R12_USR"),
+ R13_USR = (149, "R13_USR"),
+ R14_USR = (150, "R14_USR"),
+
+ R8_FIQ = (151, "R8_FIQ"),
+ R9_FIQ = (152, "R9_FIQ"),
+ R10_FIQ = (153, "R10_FIQ"),
+ R11_FIQ = (154, "R11_FIQ"),
+ R12_FIQ = (155, "R12_FIQ"),
+ R13_FIQ = (156, "R13_FIQ"),
+ R14_FIQ = (157, "R14_FIQ"),
+
+ R13_IRQ = (158, "R13_IRQ"),
+ R14_IRQ = (159, "R14_IRQ"),
+
+ R13_ABT = (160, "R13_ABT"),
+ R14_ABT = (161, "R14_ABT"),
+
+ R13_UND = (162, "R13_UND"),
+ R14_UND = (163, "R14_UND"),
+
+ R13_SVC = (164, "R13_SVC"),
+ R14_SVC = (165, "R14_SVC"),
+
+ WC0 = (192, "wC0"),
+ WC1 = (193, "wC1"),
+ WC2 = (194, "wC2"),
+ WC3 = (195, "wC3"),
+ WC4 = (196, "wC4"),
+ WC5 = (197, "wC5"),
+ WC6 = (198, "wC6"),
+ WC7 = (199, "wC7"),
+
+ D0 = (256, "D0"),
+ D1 = (257, "D1"),
+ D2 = (258, "D2"),
+ D3 = (259, "D3"),
+ D4 = (260, "D4"),
+ D5 = (261, "D5"),
+ D6 = (262, "D6"),
+ D7 = (263, "D7"),
+ D8 = (264, "D8"),
+ D9 = (265, "D9"),
+ D10 = (266, "D10"),
+ D11 = (267, "D11"),
+ D12 = (268, "D12"),
+ D13 = (269, "D13"),
+ D14 = (270, "D14"),
+ D15 = (271, "D15"),
+ D16 = (272, "D16"),
+ D17 = (273, "D17"),
+ D18 = (274, "D18"),
+ D19 = (275, "D19"),
+ D20 = (276, "D20"),
+ D21 = (277, "D21"),
+ D22 = (278, "D22"),
+ D23 = (279, "D23"),
+ D24 = (280, "D24"),
+ D25 = (281, "D25"),
+ D26 = (282, "D26"),
+ D27 = (283, "D27"),
+ D28 = (284, "D28"),
+ D29 = (285, "D29"),
+ D30 = (286, "D30"),
+ D31 = (287, "D31"),
+},
+aliases {
+ SP = (13, "SP"),
+ LR = (14, "LR"),
+ PC = (15, "PC"),
+
+ ACC0 = (104, "ACC0"),
+ ACC1 = (105, "ACC1"),
+ ACC2 = (106, "ACC2"),
+ ACC3 = (107, "ACC3"),
+ ACC4 = (108, "ACC4"),
+ ACC5 = (109, "ACC5"),
+ ACC6 = (110, "ACC6"),
+ ACC7 = (111, "ACC7"),
+
+ S0 = (256, "S0"),
+ S1 = (256, "S1"),
+ S2 = (257, "S2"),
+ S3 = (257, "S3"),
+ S4 = (258, "S4"),
+ S5 = (258, "S5"),
+ S6 = (259, "S6"),
+ S7 = (259, "S7"),
+ S8 = (260, "S8"),
+ S9 = (260, "S9"),
+ S10 = (261, "S10"),
+ S11 = (261, "S11"),
+ S12 = (262, "S12"),
+ S13 = (262, "S13"),
+ S14 = (263, "S14"),
+ S15 = (263, "S15"),
+ S16 = (264, "S16"),
+ S17 = (264, "S17"),
+ S18 = (265, "S18"),
+ S19 = (265, "S19"),
+ S20 = (266, "S20"),
+ S21 = (266, "S21"),
+ S22 = (267, "S22"),
+ S23 = (267, "S23"),
+ S24 = (268, "S24"),
+ S25 = (268, "S25"),
+ S26 = (269, "S26"),
+ S27 = (269, "S27"),
+ S28 = (270, "S28"),
+ S29 = (270, "S29"),
+ S30 = (271, "S30"),
+ S31 = (271, "S31"),
+});
+
+/// ARM 64-bit (AArch64) architecture specific definitions.
+///
+/// See [DWARF for the ARM 64-bit Architecture](https://developer.arm.com/documentation/ihi0057/b/).
+#[derive(Debug, Clone, Copy)]
+pub struct AArch64;
+
+registers!(AArch64, {
+ X0 = (0, "X0"),
+ X1 = (1, "X1"),
+ X2 = (2, "X2"),
+ X3 = (3, "X3"),
+ X4 = (4, "X4"),
+ X5 = (5, "X5"),
+ X6 = (6, "X6"),
+ X7 = (7, "X7"),
+ X8 = (8, "X8"),
+ X9 = (9, "X9"),
+ X10 = (10, "X10"),
+ X11 = (11, "X11"),
+ X12 = (12, "X12"),
+ X13 = (13, "X13"),
+ X14 = (14, "X14"),
+ X15 = (15, "X15"),
+ X16 = (16, "X16"),
+ X17 = (17, "X17"),
+ X18 = (18, "X18"),
+ X19 = (19, "X19"),
+ X20 = (20, "X20"),
+ X21 = (21, "X21"),
+ X22 = (22, "X22"),
+ X23 = (23, "X23"),
+ X24 = (24, "X24"),
+ X25 = (25, "X25"),
+ X26 = (26, "X26"),
+ X27 = (27, "X27"),
+ X28 = (28, "X28"),
+ X29 = (29, "X29"),
+ X30 = (30, "X30"),
+ SP = (31, "SP"),
+
+ V0 = (64, "V0"),
+ V1 = (65, "V1"),
+ V2 = (66, "V2"),
+ V3 = (67, "V3"),
+ V4 = (68, "V4"),
+ V5 = (69, "V5"),
+ V6 = (70, "V6"),
+ V7 = (71, "V7"),
+ V8 = (72, "V8"),
+ V9 = (73, "V9"),
+ V10 = (74, "V10"),
+ V11 = (75, "V11"),
+ V12 = (76, "V12"),
+ V13 = (77, "V13"),
+ V14 = (78, "V14"),
+ V15 = (79, "V15"),
+ V16 = (80, "V16"),
+ V17 = (81, "V17"),
+ V18 = (82, "V18"),
+ V19 = (83, "V19"),
+ V20 = (84, "V20"),
+ V21 = (85, "V21"),
+ V22 = (86, "V22"),
+ V23 = (87, "V23"),
+ V24 = (88, "V24"),
+ V25 = (89, "V25"),
+ V26 = (90, "V26"),
+ V27 = (91, "V27"),
+ V28 = (92, "V28"),
+ V29 = (93, "V29"),
+ V30 = (94, "V30"),
+ V31 = (95, "V31"),
+});
+
+/// RISC-V architecture specific definitions.
+///
+/// See [RISC-V ELF psABI specification](https://github.com/riscv/riscv-elf-psabi-doc).
+#[derive(Debug, Clone, Copy)]
+pub struct RiscV;
+
+registers!(RiscV, {
+ X0 = (0, "x0"),
+ X1 = (1, "x1"),
+ X2 = (2, "x2"),
+ X3 = (3, "x3"),
+ X4 = (4, "x4"),
+ X5 = (5, "x5"),
+ X6 = (6, "x6"),
+ X7 = (7, "x7"),
+ X8 = (8, "x8"),
+ X9 = (9, "x9"),
+ X10 = (10, "x10"),
+ X11 = (11, "x11"),
+ X12 = (12, "x12"),
+ X13 = (13, "x13"),
+ X14 = (14, "x14"),
+ X15 = (15, "x15"),
+ X16 = (16, "x16"),
+ X17 = (17, "x17"),
+ X18 = (18, "x18"),
+ X19 = (19, "x19"),
+ X20 = (20, "x20"),
+ X21 = (21, "x21"),
+ X22 = (22, "x22"),
+ X23 = (23, "x23"),
+ X24 = (24, "x24"),
+ X25 = (25, "x25"),
+ X26 = (26, "x26"),
+ X27 = (27, "x27"),
+ X28 = (28, "x28"),
+ X29 = (29, "x29"),
+ X30 = (30, "x30"),
+ X31 = (31, "x31"),
+
+ F0 = (32, "f0"),
+ F1 = (33, "f1"),
+ F2 = (34, "f2"),
+ F3 = (35, "f3"),
+ F4 = (36, "f4"),
+ F5 = (37, "f5"),
+ F6 = (38, "f6"),
+ F7 = (39, "f7"),
+ F8 = (40, "f8"),
+ F9 = (41, "f9"),
+ F10 = (42, "f10"),
+ F11 = (43, "f11"),
+ F12 = (44, "f12"),
+ F13 = (45, "f13"),
+ F14 = (46, "f14"),
+ F15 = (47, "f15"),
+ F16 = (48, "f16"),
+ F17 = (49, "f17"),
+ F18 = (50, "f18"),
+ F19 = (51, "f19"),
+ F20 = (52, "f20"),
+ F21 = (53, "f21"),
+ F22 = (54, "f22"),
+ F23 = (55, "f23"),
+ F24 = (56, "f24"),
+ F25 = (57, "f25"),
+ F26 = (58, "f26"),
+ F27 = (59, "f27"),
+ F28 = (60, "f28"),
+ F29 = (61, "f29"),
+ F30 = (62, "f30"),
+ F31 = (63, "f31"),
+},
+aliases {
+ ZERO = (0, "zero"),
+ RA = (1, "ra"),
+ SP = (2, "sp"),
+ GP = (3, "gp"),
+ TP = (4, "tp"),
+ T0 = (5, "t0"),
+ T1 = (6, "t1"),
+ T2 = (7, "t2"),
+ S0 = (8, "s0"),
+ S1 = (9, "s1"),
+ A0 = (10, "a0"),
+ A1 = (11, "a1"),
+ A2 = (12, "a2"),
+ A3 = (13, "a3"),
+ A4 = (14, "a4"),
+ A5 = (15, "a5"),
+ A6 = (16, "a6"),
+ A7 = (17, "a7"),
+ S2 = (18, "s2"),
+ S3 = (19, "s3"),
+ S4 = (20, "s4"),
+ S5 = (21, "s5"),
+ S6 = (22, "s6"),
+ S7 = (23, "s7"),
+ S8 = (24, "s8"),
+ S9 = (25, "s9"),
+ S10 = (26, "s10"),
+ S11 = (27, "s11"),
+ T3 = (28, "t3"),
+ T4 = (29, "t4"),
+ T5 = (30, "t5"),
+ T6 = (31, "t6"),
+
+ FT0 = (32, "ft0"),
+ FT1 = (33, "ft1"),
+ FT2 = (34, "ft2"),
+ FT3 = (35, "ft3"),
+ FT4 = (36, "ft4"),
+ FT5 = (37, "ft5"),
+ FT6 = (38, "ft6"),
+ FT7 = (39, "ft7"),
+ FS0 = (40, "fs0"),
+ FS1 = (41, "fs1"),
+ FA0 = (42, "fa0"),
+ FA1 = (43, "fa1"),
+ FA2 = (44, "fa2"),
+ FA3 = (45, "fa3"),
+ FA4 = (46, "fa4"),
+ FA5 = (47, "fa5"),
+ FA6 = (48, "fa6"),
+ FA7 = (49, "fa7"),
+ FS2 = (50, "fs2"),
+ FS3 = (51, "fs3"),
+ FS4 = (52, "fs4"),
+ FS5 = (53, "fs5"),
+ FS6 = (54, "fs6"),
+ FS7 = (55, "fs7"),
+ FS8 = (56, "fs8"),
+ FS9 = (57, "fs9"),
+ FS10 = (58, "fs10"),
+ FS11 = (59, "fs11"),
+ FT8 = (60, "ft8"),
+ FT9 = (61, "ft9"),
+ FT10 = (62, "ft10"),
+ FT11 = (63, "ft11"),
+});
+
+/// Intel i386 architecture specific definitions.
+///
+/// See Intel386 psABi version 1.1 at the [X86 psABI wiki](https://github.com/hjl-tools/x86-psABI/wiki/X86-psABI).
+#[derive(Debug, Clone, Copy)]
+pub struct X86;
+
+registers!(X86, {
+ EAX = (0, "eax"),
+ ECX = (1, "ecx"),
+ EDX = (2, "edx"),
+ EBX = (3, "ebx"),
+ ESP = (4, "esp"),
+ EBP = (5, "ebp"),
+ ESI = (6, "esi"),
+ EDI = (7, "edi"),
+
+ // Return Address register. This is stored in `0(%esp, "")` and is not a physical register.
+ RA = (8, "RA"),
+
+ ST0 = (11, "st0"),
+ ST1 = (12, "st1"),
+ ST2 = (13, "st2"),
+ ST3 = (14, "st3"),
+ ST4 = (15, "st4"),
+ ST5 = (16, "st5"),
+ ST6 = (17, "st6"),
+ ST7 = (18, "st7"),
+
+ XMM0 = (21, "xmm0"),
+ XMM1 = (22, "xmm1"),
+ XMM2 = (23, "xmm2"),
+ XMM3 = (24, "xmm3"),
+ XMM4 = (25, "xmm4"),
+ XMM5 = (26, "xmm5"),
+ XMM6 = (27, "xmm6"),
+ XMM7 = (28, "xmm7"),
+
+ MM0 = (29, "mm0"),
+ MM1 = (30, "mm1"),
+ MM2 = (31, "mm2"),
+ MM3 = (32, "mm3"),
+ MM4 = (33, "mm4"),
+ MM5 = (34, "mm5"),
+ MM6 = (35, "mm6"),
+ MM7 = (36, "mm7"),
+
+ MXCSR = (39, "mxcsr"),
+
+ ES = (40, "es"),
+ CS = (41, "cs"),
+ SS = (42, "ss"),
+ DS = (43, "ds"),
+ FS = (44, "fs"),
+ GS = (45, "gs"),
+
+ TR = (48, "tr"),
+ LDTR = (49, "ldtr"),
+
+ FS_BASE = (93, "fs.base"),
+ GS_BASE = (94, "gs.base"),
+});
+
+/// AMD64 architecture specific definitions.
+///
+/// See x86-64 psABI version 1.0 at the [X86 psABI wiki](https://github.com/hjl-tools/x86-psABI/wiki/X86-psABI).
+#[derive(Debug, Clone, Copy)]
+pub struct X86_64;
+
+registers!(X86_64, {
+ RAX = (0, "rax"),
+ RDX = (1, "rdx"),
+ RCX = (2, "rcx"),
+ RBX = (3, "rbx"),
+ RSI = (4, "rsi"),
+ RDI = (5, "rdi"),
+ RBP = (6, "rbp"),
+ RSP = (7, "rsp"),
+
+ R8 = (8, "r8"),
+ R9 = (9, "r9"),
+ R10 = (10, "r10"),
+ R11 = (11, "r11"),
+ R12 = (12, "r12"),
+ R13 = (13, "r13"),
+ R14 = (14, "r14"),
+ R15 = (15, "r15"),
+
+ // Return Address register. This is stored in `0(%rsp, "")` and is not a physical register.
+ RA = (16, "RA"),
+
+ XMM0 = (17, "xmm0"),
+ XMM1 = (18, "xmm1"),
+ XMM2 = (19, "xmm2"),
+ XMM3 = (20, "xmm3"),
+ XMM4 = (21, "xmm4"),
+ XMM5 = (22, "xmm5"),
+ XMM6 = (23, "xmm6"),
+ XMM7 = (24, "xmm7"),
+
+ XMM8 = (25, "xmm8"),
+ XMM9 = (26, "xmm9"),
+ XMM10 = (27, "xmm10"),
+ XMM11 = (28, "xmm11"),
+ XMM12 = (29, "xmm12"),
+ XMM13 = (30, "xmm13"),
+ XMM14 = (31, "xmm14"),
+ XMM15 = (32, "xmm15"),
+
+ ST0 = (33, "st0"),
+ ST1 = (34, "st1"),
+ ST2 = (35, "st2"),
+ ST3 = (36, "st3"),
+ ST4 = (37, "st4"),
+ ST5 = (38, "st5"),
+ ST6 = (39, "st6"),
+ ST7 = (40, "st7"),
+
+ MM0 = (41, "mm0"),
+ MM1 = (42, "mm1"),
+ MM2 = (43, "mm2"),
+ MM3 = (44, "mm3"),
+ MM4 = (45, "mm4"),
+ MM5 = (46, "mm5"),
+ MM6 = (47, "mm6"),
+ MM7 = (48, "mm7"),
+
+ RFLAGS = (49, "rFLAGS"),
+ ES = (50, "es"),
+ CS = (51, "cs"),
+ SS = (52, "ss"),
+ DS = (53, "ds"),
+ FS = (54, "fs"),
+ GS = (55, "gs"),
+
+ FS_BASE = (58, "fs.base"),
+ GS_BASE = (59, "gs.base"),
+
+ TR = (62, "tr"),
+ LDTR = (63, "ldtr"),
+ MXCSR = (64, "mxcsr"),
+ FCW = (65, "fcw"),
+ FSW = (66, "fsw"),
+
+ XMM16 = (67, "xmm16"),
+ XMM17 = (68, "xmm17"),
+ XMM18 = (69, "xmm18"),
+ XMM19 = (70, "xmm19"),
+ XMM20 = (71, "xmm20"),
+ XMM21 = (72, "xmm21"),
+ XMM22 = (73, "xmm22"),
+ XMM23 = (74, "xmm23"),
+ XMM24 = (75, "xmm24"),
+ XMM25 = (76, "xmm25"),
+ XMM26 = (77, "xmm26"),
+ XMM27 = (78, "xmm27"),
+ XMM28 = (79, "xmm28"),
+ XMM29 = (80, "xmm29"),
+ XMM30 = (81, "xmm30"),
+ XMM31 = (82, "xmm31"),
+
+ K0 = (118, "k0"),
+ K1 = (119, "k1"),
+ K2 = (120, "k2"),
+ K3 = (121, "k3"),
+ K4 = (122, "k4"),
+ K5 = (123, "k5"),
+ K6 = (124, "k6"),
+ K7 = (125, "k7"),
+});
diff --git a/vendor/gimli-0.26.2/src/common.rs b/vendor/gimli-0.26.2/src/common.rs
new file mode 100644
index 000000000..79cf76616
--- /dev/null
+++ b/vendor/gimli-0.26.2/src/common.rs
@@ -0,0 +1,363 @@
+/// Whether the format of a compilation unit is 32- or 64-bit.
+#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
+pub enum Format {
+ /// 64-bit DWARF
+ Dwarf64 = 8,
+ /// 32-bit DWARF
+ Dwarf32 = 4,
+}
+
+impl Format {
+ /// Return the serialized size of an initial length field for the format.
+ #[inline]
+ pub fn initial_length_size(self) -> u8 {
+ match self {
+ Format::Dwarf32 => 4,
+ Format::Dwarf64 => 12,
+ }
+ }
+
+ /// Return the natural word size for the format
+ #[inline]
+ pub fn word_size(self) -> u8 {
+ match self {
+ Format::Dwarf32 => 4,
+ Format::Dwarf64 => 8,
+ }
+ }
+}
+
+/// Encoding parameters that are commonly used for multiple DWARF sections.
+///
+/// This is intended to be small enough to pass by value.
+#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
+// `address_size` and `format` are used more often than `version`, so keep
+// them first.
+#[repr(C)]
+pub struct Encoding {
+ /// The size of an address.
+ pub address_size: u8,
+
+ // The size of a segment selector.
+ // TODO: pub segment_size: u8,
+ /// Whether the DWARF format is 32- or 64-bit.
+ pub format: Format,
+
+ /// The DWARF version of the header.
+ pub version: u16,
+}
+
+/// Encoding parameters for a line number program.
+#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
+pub struct LineEncoding {
+ /// The size in bytes of the smallest target machine instruction.
+ pub minimum_instruction_length: u8,
+
+ /// The maximum number of individual operations that may be encoded in an
+ /// instruction.
+ pub maximum_operations_per_instruction: u8,
+
+ /// The initial value of the `is_stmt` register.
+ pub default_is_stmt: bool,
+
+ /// The minimum value which a special opcode can add to the line register.
+ pub line_base: i8,
+
+ /// The range of values which a special opcode can add to the line register.
+ pub line_range: u8,
+}
+
+impl Default for LineEncoding {
+ fn default() -> Self {
+ // Values from LLVM.
+ LineEncoding {
+ minimum_instruction_length: 1,
+ maximum_operations_per_instruction: 1,
+ default_is_stmt: true,
+ line_base: -5,
+ line_range: 14,
+ }
+ }
+}
+
+/// A DWARF register number.
+///
+/// The meaning of this value is ABI dependent. This is generally encoded as
+/// a ULEB128, but supported architectures need 16 bits at most.
+#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
+pub struct Register(pub u16);
+
+/// An offset into the `.debug_abbrev` section.
+#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
+pub struct DebugAbbrevOffset<T = usize>(pub T);
+
+/// An offset to a set of entries in the `.debug_addr` section.
+#[derive(Debug, Clone, Copy, PartialEq, Eq)]
+pub struct DebugAddrBase<T = usize>(pub T);
+
+/// An index into a set of addresses in the `.debug_addr` section.
+#[derive(Debug, Clone, Copy, PartialEq, Eq)]
+pub struct DebugAddrIndex<T = usize>(pub T);
+
+/// An offset into the `.debug_aranges` section.
+#[derive(Debug, Clone, Copy, PartialEq, Eq)]
+pub struct DebugArangesOffset<T = usize>(pub T);
+
+/// An offset into the `.debug_info` section.
+#[derive(Debug, Clone, Copy, PartialEq, Eq, Ord, PartialOrd, Hash)]
+pub struct DebugInfoOffset<T = usize>(pub T);
+
+/// An offset into the `.debug_line` section.
+#[derive(Debug, Clone, Copy, PartialEq, Eq)]
+pub struct DebugLineOffset<T = usize>(pub T);
+
+/// An offset into the `.debug_line_str` section.
+#[derive(Debug, Clone, Copy, PartialEq, Eq)]
+pub struct DebugLineStrOffset<T = usize>(pub T);
+
+/// An offset into either the `.debug_loc` section or the `.debug_loclists` section,
+/// depending on the version of the unit the offset was contained in.
+#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
+pub struct LocationListsOffset<T = usize>(pub T);
+
+/// An offset to a set of location list offsets in the `.debug_loclists` section.
+#[derive(Debug, Clone, Copy, PartialEq, Eq)]
+pub struct DebugLocListsBase<T = usize>(pub T);
+
+/// An index into a set of location list offsets in the `.debug_loclists` section.
+#[derive(Debug, Clone, Copy, PartialEq, Eq)]
+pub struct DebugLocListsIndex<T = usize>(pub T);
+
+/// An offset into the `.debug_macinfo` section.
+#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
+pub struct DebugMacinfoOffset<T = usize>(pub T);
+
+/// An offset into the `.debug_macro` section.
+#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
+pub struct DebugMacroOffset<T = usize>(pub T);
+
+/// An offset into either the `.debug_ranges` section or the `.debug_rnglists` section,
+/// depending on the version of the unit the offset was contained in.
+///
+/// If this is from a DWARF 4 DWO file, then it must additionally be offset by the
+/// value of `DW_AT_GNU_ranges_base`. You can use `Dwarf::ranges_offset_from_raw` to do this.
+#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
+pub struct RawRangeListsOffset<T = usize>(pub T);
+
+/// An offset into either the `.debug_ranges` section or the `.debug_rnglists` section,
+/// depending on the version of the unit the offset was contained in.
+#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
+pub struct RangeListsOffset<T = usize>(pub T);
+
+/// An offset to a set of range list offsets in the `.debug_rnglists` section.
+#[derive(Debug, Clone, Copy, PartialEq, Eq)]
+pub struct DebugRngListsBase<T = usize>(pub T);
+
+/// An index into a set of range list offsets in the `.debug_rnglists` section.
+#[derive(Debug, Clone, Copy, PartialEq, Eq)]
+pub struct DebugRngListsIndex<T = usize>(pub T);
+
+/// An offset into the `.debug_str` section.
+#[derive(Debug, Clone, Copy, PartialEq, Eq)]
+pub struct DebugStrOffset<T = usize>(pub T);
+
+/// An offset to a set of entries in the `.debug_str_offsets` section.
+#[derive(Debug, Clone, Copy, PartialEq, Eq)]
+pub struct DebugStrOffsetsBase<T = usize>(pub T);
+
+/// An index into a set of entries in the `.debug_str_offsets` section.
+#[derive(Debug, Clone, Copy, PartialEq, Eq)]
+pub struct DebugStrOffsetsIndex<T = usize>(pub T);
+
+/// An offset into the `.debug_types` section.
+#[derive(Debug, Clone, Copy, PartialEq, Eq, Ord, PartialOrd, Hash)]
+pub struct DebugTypesOffset<T = usize>(pub T);
+
+/// A type signature as used in the `.debug_types` section.
+#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
+pub struct DebugTypeSignature(pub u64);
+
+/// An offset into the `.debug_frame` section.
+#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
+pub struct DebugFrameOffset<T = usize>(pub T);
+
+impl<T> From<T> for DebugFrameOffset<T> {
+ #[inline]
+ fn from(o: T) -> Self {
+ DebugFrameOffset(o)
+ }
+}
+
+/// An offset into the `.eh_frame` section.
+#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
+pub struct EhFrameOffset<T = usize>(pub T);
+
+impl<T> From<T> for EhFrameOffset<T> {
+ #[inline]
+ fn from(o: T) -> Self {
+ EhFrameOffset(o)
+ }
+}
+
+/// An offset into the `.debug_info` or `.debug_types` sections.
+#[derive(Debug, Clone, Copy, PartialEq, Eq, Ord, PartialOrd, Hash)]
+pub enum UnitSectionOffset<T = usize> {
+ /// An offset into the `.debug_info` section.
+ DebugInfoOffset(DebugInfoOffset<T>),
+ /// An offset into the `.debug_types` section.
+ DebugTypesOffset(DebugTypesOffset<T>),
+}
+
+impl<T> From<DebugInfoOffset<T>> for UnitSectionOffset<T> {
+ fn from(offset: DebugInfoOffset<T>) -> Self {
+ UnitSectionOffset::DebugInfoOffset(offset)
+ }
+}
+
+impl<T> From<DebugTypesOffset<T>> for UnitSectionOffset<T> {
+ fn from(offset: DebugTypesOffset<T>) -> Self {
+ UnitSectionOffset::DebugTypesOffset(offset)
+ }
+}
+
+impl<T> UnitSectionOffset<T>
+where
+ T: Clone,
+{
+ /// Returns the `DebugInfoOffset` inside, or `None` otherwise.
+ pub fn as_debug_info_offset(&self) -> Option<DebugInfoOffset<T>> {
+ match self {
+ UnitSectionOffset::DebugInfoOffset(offset) => Some(offset.clone()),
+ UnitSectionOffset::DebugTypesOffset(_) => None,
+ }
+ }
+ /// Returns the `DebugTypesOffset` inside, or `None` otherwise.
+ pub fn as_debug_types_offset(&self) -> Option<DebugTypesOffset<T>> {
+ match self {
+ UnitSectionOffset::DebugInfoOffset(_) => None,
+ UnitSectionOffset::DebugTypesOffset(offset) => Some(offset.clone()),
+ }
+ }
+}
+
+/// An identifier for a DWARF section.
+#[derive(Debug, Clone, Copy, PartialEq, Eq, Ord, PartialOrd, Hash)]
+pub enum SectionId {
+ /// The `.debug_abbrev` section.
+ DebugAbbrev,
+ /// The `.debug_addr` section.
+ DebugAddr,
+ /// The `.debug_aranges` section.
+ DebugAranges,
+ /// The `.debug_cu_index` section.
+ DebugCuIndex,
+ /// The `.debug_frame` section.
+ DebugFrame,
+ /// The `.eh_frame` section.
+ EhFrame,
+ /// The `.eh_frame_hdr` section.
+ EhFrameHdr,
+ /// The `.debug_info` section.
+ DebugInfo,
+ /// The `.debug_line` section.
+ DebugLine,
+ /// The `.debug_line_str` section.
+ DebugLineStr,
+ /// The `.debug_loc` section.
+ DebugLoc,
+ /// The `.debug_loclists` section.
+ DebugLocLists,
+ /// The `.debug_macinfo` section.
+ DebugMacinfo,
+ /// The `.debug_macro` section.
+ DebugMacro,
+ /// The `.debug_pubnames` section.
+ DebugPubNames,
+ /// The `.debug_pubtypes` section.
+ DebugPubTypes,
+ /// The `.debug_ranges` section.
+ DebugRanges,
+ /// The `.debug_rnglists` section.
+ DebugRngLists,
+ /// The `.debug_str` section.
+ DebugStr,
+ /// The `.debug_str_offsets` section.
+ DebugStrOffsets,
+ /// The `.debug_tu_index` section.
+ DebugTuIndex,
+ /// The `.debug_types` section.
+ DebugTypes,
+}
+
+impl SectionId {
+ /// Returns the ELF section name for this kind.
+ pub fn name(self) -> &'static str {
+ match self {
+ SectionId::DebugAbbrev => ".debug_abbrev",
+ SectionId::DebugAddr => ".debug_addr",
+ SectionId::DebugAranges => ".debug_aranges",
+ SectionId::DebugCuIndex => ".debug_cu_index",
+ SectionId::DebugFrame => ".debug_frame",
+ SectionId::EhFrame => ".eh_frame",
+ SectionId::EhFrameHdr => ".eh_frame_hdr",
+ SectionId::DebugInfo => ".debug_info",
+ SectionId::DebugLine => ".debug_line",
+ SectionId::DebugLineStr => ".debug_line_str",
+ SectionId::DebugLoc => ".debug_loc",
+ SectionId::DebugLocLists => ".debug_loclists",
+ SectionId::DebugMacinfo => ".debug_macinfo",
+ SectionId::DebugMacro => ".debug_macro",
+ SectionId::DebugPubNames => ".debug_pubnames",
+ SectionId::DebugPubTypes => ".debug_pubtypes",
+ SectionId::DebugRanges => ".debug_ranges",
+ SectionId::DebugRngLists => ".debug_rnglists",
+ SectionId::DebugStr => ".debug_str",
+ SectionId::DebugStrOffsets => ".debug_str_offsets",
+ SectionId::DebugTuIndex => ".debug_tu_index",
+ SectionId::DebugTypes => ".debug_types",
+ }
+ }
+
+ /// Returns the ELF section name for this kind, when found in a .dwo or .dwp file.
+ pub fn dwo_name(self) -> Option<&'static str> {
+ Some(match self {
+ SectionId::DebugAbbrev => ".debug_abbrev.dwo",
+ SectionId::DebugCuIndex => ".debug_cu_index",
+ SectionId::DebugInfo => ".debug_info.dwo",
+ SectionId::DebugLine => ".debug_line.dwo",
+ // The debug_loc section can be present in the dwo when using the
+ // GNU split-dwarf extension to DWARF4.
+ SectionId::DebugLoc => ".debug_loc.dwo",
+ SectionId::DebugLocLists => ".debug_loclists.dwo",
+ SectionId::DebugMacro => ".debug_macro.dwo",
+ SectionId::DebugRngLists => ".debug_rnglists.dwo",
+ SectionId::DebugStr => ".debug_str.dwo",
+ SectionId::DebugStrOffsets => ".debug_str_offsets.dwo",
+ SectionId::DebugTuIndex => ".debug_tu_index",
+ SectionId::DebugTypes => ".debug_types.dwo",
+ _ => return None,
+ })
+ }
+}
+
+/// An optionally-provided implementation-defined compilation unit ID to enable
+/// split DWARF and linking a split compilation unit back together.
+#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
+pub struct DwoId(pub u64);
+
+/// The "type" of file with DWARF debugging information. This determines, among other things,
+/// which files DWARF sections should be loaded from.
+#[derive(Debug, Clone, Copy, PartialEq, Eq)]
+pub enum DwarfFileType {
+ /// A normal executable or object file.
+ Main,
+ /// A .dwo split DWARF file.
+ Dwo,
+ // TODO: Supplementary files, .dwps?
+}
+
+impl Default for DwarfFileType {
+ fn default() -> Self {
+ DwarfFileType::Main
+ }
+}
diff --git a/vendor/gimli-0.26.2/src/constants.rs b/vendor/gimli-0.26.2/src/constants.rs
new file mode 100644
index 000000000..c617f4e2e
--- /dev/null
+++ b/vendor/gimli-0.26.2/src/constants.rs
@@ -0,0 +1,1425 @@
+// This file originally from https://github.com/philipc/rust-dwarf/ and
+// distributed under either MIT or Apache 2.0 licenses.
+//
+// Copyright 2016 The rust-dwarf Developers
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+//! Constant definitions.
+//!
+//! The DWARF spec's `DW_AT_*` type is represented as `struct DwAt(u16)`,
+//! `DW_FORM_*` as `DwForm(u16)`, etc.
+//!
+//! There are also exported const definitions for each constant.
+
+#![allow(non_upper_case_globals)]
+#![allow(missing_docs)]
+
+use core::fmt;
+
+// The `dw!` macro turns this:
+//
+// dw!(DwFoo(u32) {
+// DW_FOO_bar = 0,
+// DW_FOO_baz = 1,
+// DW_FOO_bang = 2,
+// });
+//
+// into this:
+//
+// #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
+// pub struct DwFoo(pub u32);
+//
+// pub const DW_FOO_bar: DwFoo = DwFoo(0);
+// pub const DW_FOO_baz: DwFoo = DwFoo(1);
+// pub const DW_FOO_bang: DwFoo = DwFoo(2);
+//
+// impl DwFoo {
+// pub fn static_string(&self) -> Option<&'static str> {
+// ...
+// }
+// }
+//
+// impl fmt::Display for DwFoo {
+// fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
+// ...
+// }
+// }
+macro_rules! dw {
+ ($(#[$meta:meta])* $struct_name:ident($struct_type:ty) { $($name:ident = $val:expr),+ $(,)? }) => {
+ $(#[$meta])*
+ #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
+ pub struct $struct_name(pub $struct_type);
+
+ $(
+ pub const $name: $struct_name = $struct_name($val);
+ )+
+
+ impl $struct_name {
+ pub fn static_string(&self) -> Option<&'static str> {
+ Some(match *self {
+ $(
+ $name => stringify!($name),
+ )+
+ _ => return None,
+ })
+ }
+ }
+
+ impl fmt::Display for $struct_name {
+ fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
+ if let Some(s) = self.static_string() {
+ f.pad(s)
+ } else {
+ #[cfg(feature = "read")]
+ {
+ f.pad(&format!("Unknown {}: {}", stringify!($struct_name), self.0))
+ }
+ #[cfg(not(feature = "read"))]
+ {
+ write!(f, "Unknown {}: {}", stringify!($struct_name), self.0)
+ }
+ }
+ }
+ }
+ };
+}
+
+dw!(
+/// The section type field in a `.dwp` unit index.
+///
+/// This is used for version 5 and later.
+///
+/// See Section 7.3.5.
+DwSect(u32) {
+ DW_SECT_INFO = 1,
+ DW_SECT_ABBREV = 3,
+ DW_SECT_LINE = 4,
+ DW_SECT_LOCLISTS = 5,
+ DW_SECT_STR_OFFSETS = 6,
+ DW_SECT_MACRO = 7,
+ DW_SECT_RNGLISTS = 8,
+});
+
+dw!(
+/// The section type field in a `.dwp` unit index with version 2.
+DwSectV2(u32) {
+ DW_SECT_V2_INFO = 1,
+ DW_SECT_V2_TYPES = 2,
+ DW_SECT_V2_ABBREV = 3,
+ DW_SECT_V2_LINE = 4,
+ DW_SECT_V2_LOC = 5,
+ DW_SECT_V2_STR_OFFSETS = 6,
+ DW_SECT_V2_MACINFO = 7,
+ DW_SECT_V2_MACRO = 8,
+});
+
+dw!(
+/// The unit type field in a unit header.
+///
+/// See Section 7.5.1, Table 7.2.
+DwUt(u8) {
+ DW_UT_compile = 0x01,
+ DW_UT_type = 0x02,
+ DW_UT_partial = 0x03,
+ DW_UT_skeleton = 0x04,
+ DW_UT_split_compile = 0x05,
+ DW_UT_split_type = 0x06,
+ DW_UT_lo_user = 0x80,
+ DW_UT_hi_user = 0xff,
+});
+
+dw!(
+/// The opcode for a call frame instruction.
+///
+/// Section 7.24:
+/// > Call frame instructions are encoded in one or more bytes. The primary
+/// > opcode is encoded in the high order two bits of the first byte (that is,
+/// > opcode = byte >> 6). An operand or extended opcode may be encoded in the
+/// > low order 6 bits. Additional operands are encoded in subsequent bytes.
+DwCfa(u8) {
+ DW_CFA_advance_loc = 0x01 << 6,
+ DW_CFA_offset = 0x02 << 6,
+ DW_CFA_restore = 0x03 << 6,
+ DW_CFA_nop = 0,
+ DW_CFA_set_loc = 0x01,
+ DW_CFA_advance_loc1 = 0x02,
+ DW_CFA_advance_loc2 = 0x03,
+ DW_CFA_advance_loc4 = 0x04,
+ DW_CFA_offset_extended = 0x05,
+ DW_CFA_restore_extended = 0x06,
+ DW_CFA_undefined = 0x07,
+ DW_CFA_same_value = 0x08,
+ DW_CFA_register = 0x09,
+ DW_CFA_remember_state = 0x0a,
+ DW_CFA_restore_state = 0x0b,
+ DW_CFA_def_cfa = 0x0c,
+ DW_CFA_def_cfa_register = 0x0d,
+ DW_CFA_def_cfa_offset = 0x0e,
+ DW_CFA_def_cfa_expression = 0x0f,
+ DW_CFA_expression = 0x10,
+ DW_CFA_offset_extended_sf = 0x11,
+ DW_CFA_def_cfa_sf = 0x12,
+ DW_CFA_def_cfa_offset_sf = 0x13,
+ DW_CFA_val_offset = 0x14,
+ DW_CFA_val_offset_sf = 0x15,
+ DW_CFA_val_expression = 0x16,
+
+ DW_CFA_lo_user = 0x1c,
+ DW_CFA_hi_user = 0x3f,
+
+ DW_CFA_MIPS_advance_loc8 = 0x1d,
+ DW_CFA_GNU_window_save = 0x2d,
+ DW_CFA_GNU_args_size = 0x2e,
+ DW_CFA_GNU_negative_offset_extended = 0x2f,
+});
+
+dw!(
+/// The child determination encodings for DIE attributes.
+///
+/// See Section 7.5.3, Table 7.4.
+DwChildren(u8) {
+ DW_CHILDREN_no = 0,
+ DW_CHILDREN_yes = 1,
+});
+
+dw!(
+/// The tag encodings for DIE attributes.
+///
+/// See Section 7.5.3, Table 7.3.
+DwTag(u16) {
+ DW_TAG_null = 0x00,
+
+ DW_TAG_array_type = 0x01,
+ DW_TAG_class_type = 0x02,
+ DW_TAG_entry_point = 0x03,
+ DW_TAG_enumeration_type = 0x04,
+ DW_TAG_formal_parameter = 0x05,
+ DW_TAG_imported_declaration = 0x08,
+ DW_TAG_label = 0x0a,
+ DW_TAG_lexical_block = 0x0b,
+ DW_TAG_member = 0x0d,
+ DW_TAG_pointer_type = 0x0f,
+ DW_TAG_reference_type = 0x10,
+ DW_TAG_compile_unit = 0x11,
+ DW_TAG_string_type = 0x12,
+ DW_TAG_structure_type = 0x13,
+ DW_TAG_subroutine_type = 0x15,
+ DW_TAG_typedef = 0x16,
+ DW_TAG_union_type = 0x17,
+ DW_TAG_unspecified_parameters = 0x18,
+ DW_TAG_variant = 0x19,
+ DW_TAG_common_block = 0x1a,
+ DW_TAG_common_inclusion = 0x1b,
+ DW_TAG_inheritance = 0x1c,
+ DW_TAG_inlined_subroutine = 0x1d,
+ DW_TAG_module = 0x1e,
+ DW_TAG_ptr_to_member_type = 0x1f,
+ DW_TAG_set_type = 0x20,
+ DW_TAG_subrange_type = 0x21,
+ DW_TAG_with_stmt = 0x22,
+ DW_TAG_access_declaration = 0x23,
+ DW_TAG_base_type = 0x24,
+ DW_TAG_catch_block = 0x25,
+ DW_TAG_const_type = 0x26,
+ DW_TAG_constant = 0x27,
+ DW_TAG_enumerator = 0x28,
+ DW_TAG_file_type = 0x29,
+ DW_TAG_friend = 0x2a,
+ DW_TAG_namelist = 0x2b,
+ DW_TAG_namelist_item = 0x2c,
+ DW_TAG_packed_type = 0x2d,
+ DW_TAG_subprogram = 0x2e,
+ DW_TAG_template_type_parameter = 0x2f,
+ DW_TAG_template_value_parameter = 0x30,
+ DW_TAG_thrown_type = 0x31,
+ DW_TAG_try_block = 0x32,
+ DW_TAG_variant_part = 0x33,
+ DW_TAG_variable = 0x34,
+ DW_TAG_volatile_type = 0x35,
+
+// DWARF 3.
+ DW_TAG_dwarf_procedure = 0x36,
+ DW_TAG_restrict_type = 0x37,
+ DW_TAG_interface_type = 0x38,
+ DW_TAG_namespace = 0x39,
+ DW_TAG_imported_module = 0x3a,
+ DW_TAG_unspecified_type = 0x3b,
+ DW_TAG_partial_unit = 0x3c,
+ DW_TAG_imported_unit = 0x3d,
+ DW_TAG_condition = 0x3f,
+ DW_TAG_shared_type = 0x40,
+
+// DWARF 4.
+ DW_TAG_type_unit = 0x41,
+ DW_TAG_rvalue_reference_type = 0x42,
+ DW_TAG_template_alias = 0x43,
+
+// DWARF 5.
+ DW_TAG_coarray_type = 0x44,
+ DW_TAG_generic_subrange = 0x45,
+ DW_TAG_dynamic_type = 0x46,
+ DW_TAG_atomic_type = 0x47,
+ DW_TAG_call_site = 0x48,
+ DW_TAG_call_site_parameter = 0x49,
+ DW_TAG_skeleton_unit = 0x4a,
+ DW_TAG_immutable_type = 0x4b,
+
+ DW_TAG_lo_user = 0x4080,
+ DW_TAG_hi_user = 0xffff,
+
+// SGI/MIPS extensions.
+ DW_TAG_MIPS_loop = 0x4081,
+
+// HP extensions.
+ DW_TAG_HP_array_descriptor = 0x4090,
+ DW_TAG_HP_Bliss_field = 0x4091,
+ DW_TAG_HP_Bliss_field_set = 0x4092,
+
+// GNU extensions.
+ DW_TAG_format_label = 0x4101,
+ DW_TAG_function_template = 0x4102,
+ DW_TAG_class_template = 0x4103,
+ DW_TAG_GNU_BINCL = 0x4104,
+ DW_TAG_GNU_EINCL = 0x4105,
+ DW_TAG_GNU_template_template_param = 0x4106,
+ DW_TAG_GNU_template_parameter_pack = 0x4107,
+ DW_TAG_GNU_formal_parameter_pack = 0x4108,
+ DW_TAG_GNU_call_site = 0x4109,
+ DW_TAG_GNU_call_site_parameter = 0x410a,
+
+ DW_TAG_APPLE_property = 0x4200,
+
+// SUN extensions.
+ DW_TAG_SUN_function_template = 0x4201,
+ DW_TAG_SUN_class_template = 0x4202,
+ DW_TAG_SUN_struct_template = 0x4203,
+ DW_TAG_SUN_union_template = 0x4204,
+ DW_TAG_SUN_indirect_inheritance = 0x4205,
+ DW_TAG_SUN_codeflags = 0x4206,
+ DW_TAG_SUN_memop_info = 0x4207,
+ DW_TAG_SUN_omp_child_func = 0x4208,
+ DW_TAG_SUN_rtti_descriptor = 0x4209,
+ DW_TAG_SUN_dtor_info = 0x420a,
+ DW_TAG_SUN_dtor = 0x420b,
+ DW_TAG_SUN_f90_interface = 0x420c,
+ DW_TAG_SUN_fortran_vax_structure = 0x420d,
+
+// ALTIUM extensions.
+ DW_TAG_ALTIUM_circ_type = 0x5101,
+ DW_TAG_ALTIUM_mwa_circ_type = 0x5102,
+ DW_TAG_ALTIUM_rev_carry_type = 0x5103,
+ DW_TAG_ALTIUM_rom = 0x5111,
+
+// Extensions for UPC.
+ DW_TAG_upc_shared_type = 0x8765,
+ DW_TAG_upc_strict_type = 0x8766,
+ DW_TAG_upc_relaxed_type = 0x8767,
+
+// PGI (STMicroelectronics) extensions.
+ DW_TAG_PGI_kanji_type = 0xa000,
+ DW_TAG_PGI_interface_block = 0xa020,
+
+// Borland extensions.
+ DW_TAG_BORLAND_property = 0xb000,
+ DW_TAG_BORLAND_Delphi_string = 0xb001,
+ DW_TAG_BORLAND_Delphi_dynamic_array = 0xb002,
+ DW_TAG_BORLAND_Delphi_set = 0xb003,
+ DW_TAG_BORLAND_Delphi_variant = 0xb004,
+});
+
+dw!(
+/// The attribute encodings for DIE attributes.
+///
+/// See Section 7.5.4, Table 7.5.
+DwAt(u16) {
+ DW_AT_null = 0x00,
+
+ DW_AT_sibling = 0x01,
+ DW_AT_location = 0x02,
+ DW_AT_name = 0x03,
+ DW_AT_ordering = 0x09,
+ DW_AT_byte_size = 0x0b,
+ DW_AT_bit_offset = 0x0c,
+ DW_AT_bit_size = 0x0d,
+ DW_AT_stmt_list = 0x10,
+ DW_AT_low_pc = 0x11,
+ DW_AT_high_pc = 0x12,
+ DW_AT_language = 0x13,
+ DW_AT_discr = 0x15,
+ DW_AT_discr_value = 0x16,
+ DW_AT_visibility = 0x17,
+ DW_AT_import = 0x18,
+ DW_AT_string_length = 0x19,
+ DW_AT_common_reference = 0x1a,
+ DW_AT_comp_dir = 0x1b,
+ DW_AT_const_value = 0x1c,
+ DW_AT_containing_type = 0x1d,
+ DW_AT_default_value = 0x1e,
+ DW_AT_inline = 0x20,
+ DW_AT_is_optional = 0x21,
+ DW_AT_lower_bound = 0x22,
+ DW_AT_producer = 0x25,
+ DW_AT_prototyped = 0x27,
+ DW_AT_return_addr = 0x2a,
+ DW_AT_start_scope = 0x2c,
+ DW_AT_bit_stride = 0x2e,
+ DW_AT_upper_bound = 0x2f,
+ DW_AT_abstract_origin = 0x31,
+ DW_AT_accessibility = 0x32,
+ DW_AT_address_class = 0x33,
+ DW_AT_artificial = 0x34,
+ DW_AT_base_types = 0x35,
+ DW_AT_calling_convention = 0x36,
+ DW_AT_count = 0x37,
+ DW_AT_data_member_location = 0x38,
+ DW_AT_decl_column = 0x39,
+ DW_AT_decl_file = 0x3a,
+ DW_AT_decl_line = 0x3b,
+ DW_AT_declaration = 0x3c,
+ DW_AT_discr_list = 0x3d,
+ DW_AT_encoding = 0x3e,
+ DW_AT_external = 0x3f,
+ DW_AT_frame_base = 0x40,
+ DW_AT_friend = 0x41,
+ DW_AT_identifier_case = 0x42,
+ DW_AT_macro_info = 0x43,
+ DW_AT_namelist_item = 0x44,
+ DW_AT_priority = 0x45,
+ DW_AT_segment = 0x46,
+ DW_AT_specification = 0x47,
+ DW_AT_static_link = 0x48,
+ DW_AT_type = 0x49,
+ DW_AT_use_location = 0x4a,
+ DW_AT_variable_parameter = 0x4b,
+ DW_AT_virtuality = 0x4c,
+ DW_AT_vtable_elem_location = 0x4d,
+
+// DWARF 3.
+ DW_AT_allocated = 0x4e,
+ DW_AT_associated = 0x4f,
+ DW_AT_data_location = 0x50,
+ DW_AT_byte_stride = 0x51,
+ DW_AT_entry_pc = 0x52,
+ DW_AT_use_UTF8 = 0x53,
+ DW_AT_extension = 0x54,
+ DW_AT_ranges = 0x55,
+ DW_AT_trampoline = 0x56,
+ DW_AT_call_column = 0x57,
+ DW_AT_call_file = 0x58,
+ DW_AT_call_line = 0x59,
+ DW_AT_description = 0x5a,
+ DW_AT_binary_scale = 0x5b,
+ DW_AT_decimal_scale = 0x5c,
+ DW_AT_small = 0x5d,
+ DW_AT_decimal_sign = 0x5e,
+ DW_AT_digit_count = 0x5f,
+ DW_AT_picture_string = 0x60,
+ DW_AT_mutable = 0x61,
+ DW_AT_threads_scaled = 0x62,
+ DW_AT_explicit = 0x63,
+ DW_AT_object_pointer = 0x64,
+ DW_AT_endianity = 0x65,
+ DW_AT_elemental = 0x66,
+ DW_AT_pure = 0x67,
+ DW_AT_recursive = 0x68,
+
+// DWARF 4.
+ DW_AT_signature = 0x69,
+ DW_AT_main_subprogram = 0x6a,
+ DW_AT_data_bit_offset = 0x6b,
+ DW_AT_const_expr = 0x6c,
+ DW_AT_enum_class = 0x6d,
+ DW_AT_linkage_name = 0x6e,
+
+// DWARF 5.
+ DW_AT_string_length_bit_size = 0x6f,
+ DW_AT_string_length_byte_size = 0x70,
+ DW_AT_rank = 0x71,
+ DW_AT_str_offsets_base = 0x72,
+ DW_AT_addr_base = 0x73,
+ DW_AT_rnglists_base = 0x74,
+ DW_AT_dwo_name = 0x76,
+ DW_AT_reference = 0x77,
+ DW_AT_rvalue_reference = 0x78,
+ DW_AT_macros = 0x79,
+ DW_AT_call_all_calls = 0x7a,
+ DW_AT_call_all_source_calls = 0x7b,
+ DW_AT_call_all_tail_calls = 0x7c,
+ DW_AT_call_return_pc = 0x7d,
+ DW_AT_call_value = 0x7e,
+ DW_AT_call_origin = 0x7f,
+ DW_AT_call_parameter = 0x80,
+ DW_AT_call_pc = 0x81,
+ DW_AT_call_tail_call = 0x82,
+ DW_AT_call_target = 0x83,
+ DW_AT_call_target_clobbered = 0x84,
+ DW_AT_call_data_location = 0x85,
+ DW_AT_call_data_value = 0x86,
+ DW_AT_noreturn = 0x87,
+ DW_AT_alignment = 0x88,
+ DW_AT_export_symbols = 0x89,
+ DW_AT_deleted = 0x8a,
+ DW_AT_defaulted = 0x8b,
+ DW_AT_loclists_base = 0x8c,
+
+ DW_AT_lo_user = 0x2000,
+ DW_AT_hi_user = 0x3fff,
+
+// SGI/MIPS extensions.
+ DW_AT_MIPS_fde = 0x2001,
+ DW_AT_MIPS_loop_begin = 0x2002,
+ DW_AT_MIPS_tail_loop_begin = 0x2003,
+ DW_AT_MIPS_epilog_begin = 0x2004,
+ DW_AT_MIPS_loop_unroll_factor = 0x2005,
+ DW_AT_MIPS_software_pipeline_depth = 0x2006,
+ DW_AT_MIPS_linkage_name = 0x2007,
+ DW_AT_MIPS_stride = 0x2008,
+ DW_AT_MIPS_abstract_name = 0x2009,
+ DW_AT_MIPS_clone_origin = 0x200a,
+ DW_AT_MIPS_has_inlines = 0x200b,
+ DW_AT_MIPS_stride_byte = 0x200c,
+ DW_AT_MIPS_stride_elem = 0x200d,
+ DW_AT_MIPS_ptr_dopetype = 0x200e,
+ DW_AT_MIPS_allocatable_dopetype = 0x200f,
+ DW_AT_MIPS_assumed_shape_dopetype = 0x2010,
+
+// This one appears to have only been implemented by Open64 for
+// fortran and may conflict with other extensions.
+ DW_AT_MIPS_assumed_size = 0x2011,
+
+// TODO: HP/CPQ extensions.
+// These conflict with the MIPS extensions.
+
+ DW_AT_INTEL_other_endian = 0x2026,
+
+// GNU extensions
+ DW_AT_sf_names = 0x2101,
+ DW_AT_src_info = 0x2102,
+ DW_AT_mac_info = 0x2103,
+ DW_AT_src_coords = 0x2104,
+ DW_AT_body_begin = 0x2105,
+ DW_AT_body_end = 0x2106,
+ DW_AT_GNU_vector = 0x2107,
+ DW_AT_GNU_guarded_by = 0x2108,
+ DW_AT_GNU_pt_guarded_by = 0x2109,
+ DW_AT_GNU_guarded = 0x210a,
+ DW_AT_GNU_pt_guarded = 0x210b,
+ DW_AT_GNU_locks_excluded = 0x210c,
+ DW_AT_GNU_exclusive_locks_required = 0x210d,
+ DW_AT_GNU_shared_locks_required = 0x210e,
+ DW_AT_GNU_odr_signature = 0x210f,
+ DW_AT_GNU_template_name = 0x2110,
+ DW_AT_GNU_call_site_value = 0x2111,
+ DW_AT_GNU_call_site_data_value = 0x2112,
+ DW_AT_GNU_call_site_target = 0x2113,
+ DW_AT_GNU_call_site_target_clobbered = 0x2114,
+ DW_AT_GNU_tail_call = 0x2115,
+ DW_AT_GNU_all_tail_call_sites = 0x2116,
+ DW_AT_GNU_all_call_sites = 0x2117,
+ DW_AT_GNU_all_source_call_sites = 0x2118,
+ DW_AT_GNU_macros = 0x2119,
+
+// Extensions for Fission proposal.
+ DW_AT_GNU_dwo_name = 0x2130,
+ DW_AT_GNU_dwo_id = 0x2131,
+ DW_AT_GNU_ranges_base = 0x2132,
+ DW_AT_GNU_addr_base = 0x2133,
+ DW_AT_GNU_pubnames = 0x2134,
+ DW_AT_GNU_pubtypes = 0x2135,
+ DW_AT_GNU_discriminator = 0x2136,
+ DW_AT_GNU_locviews = 0x2137,
+ DW_AT_GNU_entry_view = 0x2138,
+
+// Conflict with Sun.
+// DW_AT_VMS_rtnbeg_pd_address = 0x2201,
+
+// Sun extensions.
+ DW_AT_SUN_template = 0x2201,
+ DW_AT_SUN_alignment = 0x2202,
+ DW_AT_SUN_vtable = 0x2203,
+ DW_AT_SUN_count_guarantee = 0x2204,
+ DW_AT_SUN_command_line = 0x2205,
+ DW_AT_SUN_vbase = 0x2206,
+ DW_AT_SUN_compile_options = 0x2207,
+ DW_AT_SUN_language = 0x2208,
+ DW_AT_SUN_browser_file = 0x2209,
+ DW_AT_SUN_vtable_abi = 0x2210,
+ DW_AT_SUN_func_offsets = 0x2211,
+ DW_AT_SUN_cf_kind = 0x2212,
+ DW_AT_SUN_vtable_index = 0x2213,
+ DW_AT_SUN_omp_tpriv_addr = 0x2214,
+ DW_AT_SUN_omp_child_func = 0x2215,
+ DW_AT_SUN_func_offset = 0x2216,
+ DW_AT_SUN_memop_type_ref = 0x2217,
+ DW_AT_SUN_profile_id = 0x2218,
+ DW_AT_SUN_memop_signature = 0x2219,
+ DW_AT_SUN_obj_dir = 0x2220,
+ DW_AT_SUN_obj_file = 0x2221,
+ DW_AT_SUN_original_name = 0x2222,
+ DW_AT_SUN_hwcprof_signature = 0x2223,
+ DW_AT_SUN_amd64_parmdump = 0x2224,
+ DW_AT_SUN_part_link_name = 0x2225,
+ DW_AT_SUN_link_name = 0x2226,
+ DW_AT_SUN_pass_with_const = 0x2227,
+ DW_AT_SUN_return_with_const = 0x2228,
+ DW_AT_SUN_import_by_name = 0x2229,
+ DW_AT_SUN_f90_pointer = 0x222a,
+ DW_AT_SUN_pass_by_ref = 0x222b,
+ DW_AT_SUN_f90_allocatable = 0x222c,
+ DW_AT_SUN_f90_assumed_shape_array = 0x222d,
+ DW_AT_SUN_c_vla = 0x222e,
+ DW_AT_SUN_return_value_ptr = 0x2230,
+ DW_AT_SUN_dtor_start = 0x2231,
+ DW_AT_SUN_dtor_length = 0x2232,
+ DW_AT_SUN_dtor_state_initial = 0x2233,
+ DW_AT_SUN_dtor_state_final = 0x2234,
+ DW_AT_SUN_dtor_state_deltas = 0x2235,
+ DW_AT_SUN_import_by_lname = 0x2236,
+ DW_AT_SUN_f90_use_only = 0x2237,
+ DW_AT_SUN_namelist_spec = 0x2238,
+ DW_AT_SUN_is_omp_child_func = 0x2239,
+ DW_AT_SUN_fortran_main_alias = 0x223a,
+ DW_AT_SUN_fortran_based = 0x223b,
+
+ DW_AT_ALTIUM_loclist = 0x2300,
+
+ DW_AT_use_GNAT_descriptive_type = 0x2301,
+ DW_AT_GNAT_descriptive_type = 0x2302,
+ DW_AT_GNU_numerator = 0x2303,
+ DW_AT_GNU_denominator = 0x2304,
+ DW_AT_GNU_bias = 0x2305,
+
+ DW_AT_upc_threads_scaled = 0x3210,
+
+// PGI (STMicroelectronics) extensions.
+ DW_AT_PGI_lbase = 0x3a00,
+ DW_AT_PGI_soffset = 0x3a01,
+ DW_AT_PGI_lstride = 0x3a02,
+
+// Borland extensions.
+ DW_AT_BORLAND_property_read = 0x3b11,
+ DW_AT_BORLAND_property_write = 0x3b12,
+ DW_AT_BORLAND_property_implements = 0x3b13,
+ DW_AT_BORLAND_property_index = 0x3b14,
+ DW_AT_BORLAND_property_default = 0x3b15,
+ DW_AT_BORLAND_Delphi_unit = 0x3b20,
+ DW_AT_BORLAND_Delphi_class = 0x3b21,
+ DW_AT_BORLAND_Delphi_record = 0x3b22,
+ DW_AT_BORLAND_Delphi_metaclass = 0x3b23,
+ DW_AT_BORLAND_Delphi_constructor = 0x3b24,
+ DW_AT_BORLAND_Delphi_destructor = 0x3b25,
+ DW_AT_BORLAND_Delphi_anonymous_method = 0x3b26,
+ DW_AT_BORLAND_Delphi_interface = 0x3b27,
+ DW_AT_BORLAND_Delphi_ABI = 0x3b28,
+ DW_AT_BORLAND_Delphi_return = 0x3b29,
+ DW_AT_BORLAND_Delphi_frameptr = 0x3b30,
+ DW_AT_BORLAND_closure = 0x3b31,
+
+// LLVM project extensions.
+ DW_AT_LLVM_include_path = 0x3e00,
+ DW_AT_LLVM_config_macros = 0x3e01,
+ DW_AT_LLVM_isysroot = 0x3e02,
+
+// Apple extensions.
+ DW_AT_APPLE_optimized = 0x3fe1,
+ DW_AT_APPLE_flags = 0x3fe2,
+ DW_AT_APPLE_isa = 0x3fe3,
+ DW_AT_APPLE_block = 0x3fe4,
+ DW_AT_APPLE_major_runtime_vers = 0x3fe5,
+ DW_AT_APPLE_runtime_class = 0x3fe6,
+ DW_AT_APPLE_omit_frame_ptr = 0x3fe7,
+ DW_AT_APPLE_property_name = 0x3fe8,
+ DW_AT_APPLE_property_getter = 0x3fe9,
+ DW_AT_APPLE_property_setter = 0x3fea,
+ DW_AT_APPLE_property_attribute = 0x3feb,
+ DW_AT_APPLE_objc_complete_type = 0x3fec,
+ DW_AT_APPLE_property = 0x3fed
+});
+
+dw!(
+/// The attribute form encodings for DIE attributes.
+///
+/// See Section 7.5.6, Table 7.6.
+DwForm(u16) {
+ DW_FORM_null = 0x00,
+
+ DW_FORM_addr = 0x01,
+ DW_FORM_block2 = 0x03,
+ DW_FORM_block4 = 0x04,
+ DW_FORM_data2 = 0x05,
+ DW_FORM_data4 = 0x06,
+ DW_FORM_data8 = 0x07,
+ DW_FORM_string = 0x08,
+ DW_FORM_block = 0x09,
+ DW_FORM_block1 = 0x0a,
+ DW_FORM_data1 = 0x0b,
+ DW_FORM_flag = 0x0c,
+ DW_FORM_sdata = 0x0d,
+ DW_FORM_strp = 0x0e,
+ DW_FORM_udata = 0x0f,
+ DW_FORM_ref_addr = 0x10,
+ DW_FORM_ref1 = 0x11,
+ DW_FORM_ref2 = 0x12,
+ DW_FORM_ref4 = 0x13,
+ DW_FORM_ref8 = 0x14,
+ DW_FORM_ref_udata = 0x15,
+ DW_FORM_indirect = 0x16,
+
+// DWARF 4.
+ DW_FORM_sec_offset = 0x17,
+ DW_FORM_exprloc = 0x18,
+ DW_FORM_flag_present = 0x19,
+ DW_FORM_ref_sig8 = 0x20,
+
+// DWARF 5.
+ DW_FORM_strx = 0x1a,
+ DW_FORM_addrx = 0x1b,
+ DW_FORM_ref_sup4 = 0x1c,
+ DW_FORM_strp_sup = 0x1d,
+ DW_FORM_data16 = 0x1e,
+ DW_FORM_line_strp = 0x1f,
+ DW_FORM_implicit_const = 0x21,
+ DW_FORM_loclistx = 0x22,
+ DW_FORM_rnglistx = 0x23,
+ DW_FORM_ref_sup8 = 0x24,
+ DW_FORM_strx1 = 0x25,
+ DW_FORM_strx2 = 0x26,
+ DW_FORM_strx3 = 0x27,
+ DW_FORM_strx4 = 0x28,
+ DW_FORM_addrx1 = 0x29,
+ DW_FORM_addrx2 = 0x2a,
+ DW_FORM_addrx3 = 0x2b,
+ DW_FORM_addrx4 = 0x2c,
+
+// Extensions for Fission proposal
+ DW_FORM_GNU_addr_index = 0x1f01,
+ DW_FORM_GNU_str_index = 0x1f02,
+
+// Alternate debug sections proposal (output of "dwz" tool).
+ DW_FORM_GNU_ref_alt = 0x1f20,
+ DW_FORM_GNU_strp_alt = 0x1f21
+});
+
+dw!(
+/// The encodings of the constants used in the `DW_AT_encoding` attribute.
+///
+/// See Section 7.8, Table 7.11.
+DwAte(u8) {
+ DW_ATE_address = 0x01,
+ DW_ATE_boolean = 0x02,
+ DW_ATE_complex_float = 0x03,
+ DW_ATE_float = 0x04,
+ DW_ATE_signed = 0x05,
+ DW_ATE_signed_char = 0x06,
+ DW_ATE_unsigned = 0x07,
+ DW_ATE_unsigned_char = 0x08,
+
+// DWARF 3.
+ DW_ATE_imaginary_float = 0x09,
+ DW_ATE_packed_decimal = 0x0a,
+ DW_ATE_numeric_string = 0x0b,
+ DW_ATE_edited = 0x0c,
+ DW_ATE_signed_fixed = 0x0d,
+ DW_ATE_unsigned_fixed = 0x0e,
+ DW_ATE_decimal_float = 0x0f ,
+
+// DWARF 4.
+ DW_ATE_UTF = 0x10,
+ DW_ATE_UCS = 0x11,
+ DW_ATE_ASCII = 0x12,
+
+ DW_ATE_lo_user = 0x80,
+ DW_ATE_hi_user = 0xff,
+});
+
+dw!(
+/// The encodings of the constants used in location list entries.
+///
+/// See Section 7.7.3, Table 7.10.
+DwLle(u8) {
+ DW_LLE_end_of_list = 0x00,
+ DW_LLE_base_addressx = 0x01,
+ DW_LLE_startx_endx = 0x02,
+ DW_LLE_startx_length = 0x03,
+ DW_LLE_offset_pair = 0x04,
+ DW_LLE_default_location = 0x05,
+ DW_LLE_base_address = 0x06,
+ DW_LLE_start_end = 0x07,
+ DW_LLE_start_length = 0x08,
+ DW_LLE_GNU_view_pair = 0x09,
+});
+
+dw!(
+/// The encodings of the constants used in the `DW_AT_decimal_sign` attribute.
+///
+/// See Section 7.8, Table 7.12.
+DwDs(u8) {
+ DW_DS_unsigned = 0x01,
+ DW_DS_leading_overpunch = 0x02,
+ DW_DS_trailing_overpunch = 0x03,
+ DW_DS_leading_separate = 0x04,
+ DW_DS_trailing_separate = 0x05,
+});
+
+dw!(
+/// The encodings of the constants used in the `DW_AT_endianity` attribute.
+///
+/// See Section 7.8, Table 7.13.
+DwEnd(u8) {
+ DW_END_default = 0x00,
+ DW_END_big = 0x01,
+ DW_END_little = 0x02,
+ DW_END_lo_user = 0x40,
+ DW_END_hi_user = 0xff,
+});
+
+dw!(
+/// The encodings of the constants used in the `DW_AT_accessibility` attribute.
+///
+/// See Section 7.9, Table 7.14.
+DwAccess(u8) {
+ DW_ACCESS_public = 0x01,
+ DW_ACCESS_protected = 0x02,
+ DW_ACCESS_private = 0x03,
+});
+
+dw!(
+/// The encodings of the constants used in the `DW_AT_visibility` attribute.
+///
+/// See Section 7.10, Table 7.15.
+DwVis(u8) {
+ DW_VIS_local = 0x01,
+ DW_VIS_exported = 0x02,
+ DW_VIS_qualified = 0x03,
+});
+
+dw!(
+/// The encodings of the constants used in the `DW_AT_virtuality` attribute.
+///
+/// See Section 7.11, Table 7.16.
+DwVirtuality(u8) {
+ DW_VIRTUALITY_none = 0x00,
+ DW_VIRTUALITY_virtual = 0x01,
+ DW_VIRTUALITY_pure_virtual = 0x02,
+});
+
+dw!(
+/// The encodings of the constants used in the `DW_AT_language` attribute.
+///
+/// See Section 7.12, Table 7.17.
+DwLang(u16) {
+ DW_LANG_C89 = 0x0001,
+ DW_LANG_C = 0x0002,
+ DW_LANG_Ada83 = 0x0003,
+ DW_LANG_C_plus_plus = 0x0004,
+ DW_LANG_Cobol74 = 0x0005,
+ DW_LANG_Cobol85 = 0x0006,
+ DW_LANG_Fortran77 = 0x0007,
+ DW_LANG_Fortran90 = 0x0008,
+ DW_LANG_Pascal83 = 0x0009,
+ DW_LANG_Modula2 = 0x000a,
+ DW_LANG_Java = 0x000b,
+ DW_LANG_C99 = 0x000c,
+ DW_LANG_Ada95 = 0x000d,
+ DW_LANG_Fortran95 = 0x000e,
+ DW_LANG_PLI = 0x000f,
+ DW_LANG_ObjC = 0x0010,
+ DW_LANG_ObjC_plus_plus = 0x0011,
+ DW_LANG_UPC = 0x0012,
+ DW_LANG_D = 0x0013,
+ DW_LANG_Python = 0x0014,
+ DW_LANG_OpenCL = 0x0015,
+ DW_LANG_Go = 0x0016,
+ DW_LANG_Modula3 = 0x0017,
+ DW_LANG_Haskell = 0x0018,
+ DW_LANG_C_plus_plus_03 = 0x0019,
+ DW_LANG_C_plus_plus_11 = 0x001a,
+ DW_LANG_OCaml = 0x001b,
+ DW_LANG_Rust = 0x001c,
+ DW_LANG_C11 = 0x001d,
+ DW_LANG_Swift = 0x001e,
+ DW_LANG_Julia = 0x001f,
+ DW_LANG_Dylan = 0x0020,
+ DW_LANG_C_plus_plus_14 = 0x0021,
+ DW_LANG_Fortran03 = 0x0022,
+ DW_LANG_Fortran08 = 0x0023,
+ DW_LANG_RenderScript = 0x0024,
+ DW_LANG_BLISS = 0x0025,
+ DW_LANG_Kotlin = 0x0026,
+ DW_LANG_Zig = 0x0027,
+ DW_LANG_Crystal = 0x0028,
+ DW_LANG_C_plus_plus_17 = 0x002a,
+ DW_LANG_C_plus_plus_20 = 0x002b,
+ DW_LANG_C17 = 0x002c,
+ DW_LANG_Fortran18 = 0x002d,
+ DW_LANG_Ada2005 = 0x002e,
+ DW_LANG_Ada2012 = 0x002f,
+
+ DW_LANG_lo_user = 0x8000,
+ DW_LANG_hi_user = 0xffff,
+
+ DW_LANG_Mips_Assembler = 0x8001,
+ DW_LANG_GOOGLE_RenderScript = 0x8e57,
+ DW_LANG_SUN_Assembler = 0x9001,
+ DW_LANG_ALTIUM_Assembler = 0x9101,
+ DW_LANG_BORLAND_Delphi = 0xb000,
+});
+
+impl DwLang {
+ /// Get the default DW_AT_lower_bound for this language.
+ pub fn default_lower_bound(self) -> Option<usize> {
+ match self {
+ DW_LANG_C89
+ | DW_LANG_C
+ | DW_LANG_C_plus_plus
+ | DW_LANG_Java
+ | DW_LANG_C99
+ | DW_LANG_ObjC
+ | DW_LANG_ObjC_plus_plus
+ | DW_LANG_UPC
+ | DW_LANG_D
+ | DW_LANG_Python
+ | DW_LANG_OpenCL
+ | DW_LANG_Go
+ | DW_LANG_Haskell
+ | DW_LANG_C_plus_plus_03
+ | DW_LANG_C_plus_plus_11
+ | DW_LANG_OCaml
+ | DW_LANG_Rust
+ | DW_LANG_C11
+ | DW_LANG_Swift
+ | DW_LANG_Dylan
+ | DW_LANG_C_plus_plus_14
+ | DW_LANG_RenderScript
+ | DW_LANG_BLISS => Some(0),
+ DW_LANG_Ada83 | DW_LANG_Cobol74 | DW_LANG_Cobol85 | DW_LANG_Fortran77
+ | DW_LANG_Fortran90 | DW_LANG_Pascal83 | DW_LANG_Modula2 | DW_LANG_Ada95
+ | DW_LANG_Fortran95 | DW_LANG_PLI | DW_LANG_Modula3 | DW_LANG_Julia
+ | DW_LANG_Fortran03 | DW_LANG_Fortran08 => Some(1),
+ _ => None,
+ }
+ }
+}
+
+dw!(
+/// The encodings of the constants used in the `DW_AT_address_class` attribute.
+///
+/// There is only one value that is common to all target architectures.
+/// See Section 7.13.
+DwAddr(u64) {
+ DW_ADDR_none = 0x00,
+});
+
+dw!(
+/// The encodings of the constants used in the `DW_AT_identifier_case` attribute.
+///
+/// See Section 7.14, Table 7.18.
+DwId(u8) {
+ DW_ID_case_sensitive = 0x00,
+ DW_ID_up_case = 0x01,
+ DW_ID_down_case = 0x02,
+ DW_ID_case_insensitive = 0x03,
+});
+
+dw!(
+/// The encodings of the constants used in the `DW_AT_calling_convention` attribute.
+///
+/// See Section 7.15, Table 7.19.
+DwCc(u8) {
+ DW_CC_normal = 0x01,
+ DW_CC_program = 0x02,
+ DW_CC_nocall = 0x03,
+ DW_CC_pass_by_reference = 0x04,
+ DW_CC_pass_by_value = 0x05,
+ DW_CC_lo_user = 0x40,
+ DW_CC_hi_user = 0xff,
+});
+
+dw!(
+/// The encodings of the constants used in the `DW_AT_inline` attribute.
+///
+/// See Section 7.16, Table 7.20.
+DwInl(u8) {
+ DW_INL_not_inlined = 0x00,
+ DW_INL_inlined = 0x01,
+ DW_INL_declared_not_inlined = 0x02,
+ DW_INL_declared_inlined = 0x03,
+});
+
+dw!(
+/// The encodings of the constants used in the `DW_AT_ordering` attribute.
+///
+/// See Section 7.17, Table 7.17.
+DwOrd(u8) {
+ DW_ORD_row_major = 0x00,
+ DW_ORD_col_major = 0x01,
+});
+
+dw!(
+/// The encodings of the constants used in the `DW_AT_discr_list` attribute.
+///
+/// See Section 7.18, Table 7.22.
+DwDsc(u8) {
+ DW_DSC_label = 0x00,
+ DW_DSC_range = 0x01,
+});
+
+dw!(
+/// Name index attribute encodings.
+///
+/// See Section 7.19, Table 7.23.
+DwIdx(u16) {
+ DW_IDX_compile_unit = 1,
+ DW_IDX_type_unit = 2,
+ DW_IDX_die_offset = 3,
+ DW_IDX_parent = 4,
+ DW_IDX_type_hash = 5,
+ DW_IDX_lo_user = 0x2000,
+ DW_IDX_hi_user = 0x3fff,
+});
+
+dw!(
+/// The encodings of the constants used in the `DW_AT_defaulted` attribute.
+///
+/// See Section 7.20, Table 7.24.
+DwDefaulted(u8) {
+ DW_DEFAULTED_no = 0x00,
+ DW_DEFAULTED_in_class = 0x01,
+ DW_DEFAULTED_out_of_class = 0x02,
+});
+
+dw!(
+/// The encodings for the standard opcodes for line number information.
+///
+/// See Section 7.22, Table 7.25.
+DwLns(u8) {
+ DW_LNS_copy = 0x01,
+ DW_LNS_advance_pc = 0x02,
+ DW_LNS_advance_line = 0x03,
+ DW_LNS_set_file = 0x04,
+ DW_LNS_set_column = 0x05,
+ DW_LNS_negate_stmt = 0x06,
+ DW_LNS_set_basic_block = 0x07,
+ DW_LNS_const_add_pc = 0x08,
+ DW_LNS_fixed_advance_pc = 0x09,
+ DW_LNS_set_prologue_end = 0x0a,
+ DW_LNS_set_epilogue_begin = 0x0b,
+ DW_LNS_set_isa = 0x0c,
+});
+
+dw!(
+/// The encodings for the extended opcodes for line number information.
+///
+/// See Section 7.22, Table 7.26.
+DwLne(u8) {
+ DW_LNE_end_sequence = 0x01,
+ DW_LNE_set_address = 0x02,
+ DW_LNE_define_file = 0x03,
+ DW_LNE_set_discriminator = 0x04,
+
+ DW_LNE_lo_user = 0x80,
+ DW_LNE_hi_user = 0xff,
+});
+
+dw!(
+/// The encodings for the line number header entry formats.
+///
+/// See Section 7.22, Table 7.27.
+DwLnct(u16) {
+ DW_LNCT_path = 0x1,
+ DW_LNCT_directory_index = 0x2,
+ DW_LNCT_timestamp = 0x3,
+ DW_LNCT_size = 0x4,
+ DW_LNCT_MD5 = 0x5,
+ DW_LNCT_lo_user = 0x2000,
+ DW_LNCT_hi_user = 0x3fff,
+});
+
+dw!(
+/// The encodings for macro information entry types.
+///
+/// See Section 7.23, Table 7.28.
+DwMacro(u8) {
+ DW_MACRO_define = 0x01,
+ DW_MACRO_undef = 0x02,
+ DW_MACRO_start_file = 0x03,
+ DW_MACRO_end_file = 0x04,
+ DW_MACRO_define_strp = 0x05,
+ DW_MACRO_undef_strp = 0x06,
+ DW_MACRO_import = 0x07,
+ DW_MACRO_define_sup = 0x08,
+ DW_MACRO_undef_sup = 0x09,
+ DW_MACRO_import_sup = 0x0a,
+ DW_MACRO_define_strx = 0x0b,
+ DW_MACRO_undef_strx = 0x0c,
+ DW_MACRO_lo_user = 0xe0,
+ DW_MACRO_hi_user = 0xff,
+});
+
+dw!(
+/// Range list entry encoding values.
+///
+/// See Section 7.25, Table 7.30.
+DwRle(u8) {
+ DW_RLE_end_of_list = 0x00,
+ DW_RLE_base_addressx = 0x01,
+ DW_RLE_startx_endx = 0x02,
+ DW_RLE_startx_length = 0x03,
+ DW_RLE_offset_pair = 0x04,
+ DW_RLE_base_address = 0x05,
+ DW_RLE_start_end = 0x06,
+ DW_RLE_start_length = 0x07,
+});
+
+dw!(
+/// The encodings for DWARF expression operations.
+///
+/// See Section 7.7.1, Table 7.9.
+DwOp(u8) {
+ DW_OP_addr = 0x03,
+ DW_OP_deref = 0x06,
+ DW_OP_const1u = 0x08,
+ DW_OP_const1s = 0x09,
+ DW_OP_const2u = 0x0a,
+ DW_OP_const2s = 0x0b,
+ DW_OP_const4u = 0x0c,
+ DW_OP_const4s = 0x0d,
+ DW_OP_const8u = 0x0e,
+ DW_OP_const8s = 0x0f,
+ DW_OP_constu = 0x10,
+ DW_OP_consts = 0x11,
+ DW_OP_dup = 0x12,
+ DW_OP_drop = 0x13,
+ DW_OP_over = 0x14,
+ DW_OP_pick = 0x15,
+ DW_OP_swap = 0x16,
+ DW_OP_rot = 0x17,
+ DW_OP_xderef = 0x18,
+ DW_OP_abs = 0x19,
+ DW_OP_and = 0x1a,
+ DW_OP_div = 0x1b,
+ DW_OP_minus = 0x1c,
+ DW_OP_mod = 0x1d,
+ DW_OP_mul = 0x1e,
+ DW_OP_neg = 0x1f,
+ DW_OP_not = 0x20,
+ DW_OP_or = 0x21,
+ DW_OP_plus = 0x22,
+ DW_OP_plus_uconst = 0x23,
+ DW_OP_shl = 0x24,
+ DW_OP_shr = 0x25,
+ DW_OP_shra = 0x26,
+ DW_OP_xor = 0x27,
+ DW_OP_bra = 0x28,
+ DW_OP_eq = 0x29,
+ DW_OP_ge = 0x2a,
+ DW_OP_gt = 0x2b,
+ DW_OP_le = 0x2c,
+ DW_OP_lt = 0x2d,
+ DW_OP_ne = 0x2e,
+ DW_OP_skip = 0x2f,
+ DW_OP_lit0 = 0x30,
+ DW_OP_lit1 = 0x31,
+ DW_OP_lit2 = 0x32,
+ DW_OP_lit3 = 0x33,
+ DW_OP_lit4 = 0x34,
+ DW_OP_lit5 = 0x35,
+ DW_OP_lit6 = 0x36,
+ DW_OP_lit7 = 0x37,
+ DW_OP_lit8 = 0x38,
+ DW_OP_lit9 = 0x39,
+ DW_OP_lit10 = 0x3a,
+ DW_OP_lit11 = 0x3b,
+ DW_OP_lit12 = 0x3c,
+ DW_OP_lit13 = 0x3d,
+ DW_OP_lit14 = 0x3e,
+ DW_OP_lit15 = 0x3f,
+ DW_OP_lit16 = 0x40,
+ DW_OP_lit17 = 0x41,
+ DW_OP_lit18 = 0x42,
+ DW_OP_lit19 = 0x43,
+ DW_OP_lit20 = 0x44,
+ DW_OP_lit21 = 0x45,
+ DW_OP_lit22 = 0x46,
+ DW_OP_lit23 = 0x47,
+ DW_OP_lit24 = 0x48,
+ DW_OP_lit25 = 0x49,
+ DW_OP_lit26 = 0x4a,
+ DW_OP_lit27 = 0x4b,
+ DW_OP_lit28 = 0x4c,
+ DW_OP_lit29 = 0x4d,
+ DW_OP_lit30 = 0x4e,
+ DW_OP_lit31 = 0x4f,
+ DW_OP_reg0 = 0x50,
+ DW_OP_reg1 = 0x51,
+ DW_OP_reg2 = 0x52,
+ DW_OP_reg3 = 0x53,
+ DW_OP_reg4 = 0x54,
+ DW_OP_reg5 = 0x55,
+ DW_OP_reg6 = 0x56,
+ DW_OP_reg7 = 0x57,
+ DW_OP_reg8 = 0x58,
+ DW_OP_reg9 = 0x59,
+ DW_OP_reg10 = 0x5a,
+ DW_OP_reg11 = 0x5b,
+ DW_OP_reg12 = 0x5c,
+ DW_OP_reg13 = 0x5d,
+ DW_OP_reg14 = 0x5e,
+ DW_OP_reg15 = 0x5f,
+ DW_OP_reg16 = 0x60,
+ DW_OP_reg17 = 0x61,
+ DW_OP_reg18 = 0x62,
+ DW_OP_reg19 = 0x63,
+ DW_OP_reg20 = 0x64,
+ DW_OP_reg21 = 0x65,
+ DW_OP_reg22 = 0x66,
+ DW_OP_reg23 = 0x67,
+ DW_OP_reg24 = 0x68,
+ DW_OP_reg25 = 0x69,
+ DW_OP_reg26 = 0x6a,
+ DW_OP_reg27 = 0x6b,
+ DW_OP_reg28 = 0x6c,
+ DW_OP_reg29 = 0x6d,
+ DW_OP_reg30 = 0x6e,
+ DW_OP_reg31 = 0x6f,
+ DW_OP_breg0 = 0x70,
+ DW_OP_breg1 = 0x71,
+ DW_OP_breg2 = 0x72,
+ DW_OP_breg3 = 0x73,
+ DW_OP_breg4 = 0x74,
+ DW_OP_breg5 = 0x75,
+ DW_OP_breg6 = 0x76,
+ DW_OP_breg7 = 0x77,
+ DW_OP_breg8 = 0x78,
+ DW_OP_breg9 = 0x79,
+ DW_OP_breg10 = 0x7a,
+ DW_OP_breg11 = 0x7b,
+ DW_OP_breg12 = 0x7c,
+ DW_OP_breg13 = 0x7d,
+ DW_OP_breg14 = 0x7e,
+ DW_OP_breg15 = 0x7f,
+ DW_OP_breg16 = 0x80,
+ DW_OP_breg17 = 0x81,
+ DW_OP_breg18 = 0x82,
+ DW_OP_breg19 = 0x83,
+ DW_OP_breg20 = 0x84,
+ DW_OP_breg21 = 0x85,
+ DW_OP_breg22 = 0x86,
+ DW_OP_breg23 = 0x87,
+ DW_OP_breg24 = 0x88,
+ DW_OP_breg25 = 0x89,
+ DW_OP_breg26 = 0x8a,
+ DW_OP_breg27 = 0x8b,
+ DW_OP_breg28 = 0x8c,
+ DW_OP_breg29 = 0x8d,
+ DW_OP_breg30 = 0x8e,
+ DW_OP_breg31 = 0x8f,
+ DW_OP_regx = 0x90,
+ DW_OP_fbreg = 0x91,
+ DW_OP_bregx = 0x92,
+ DW_OP_piece = 0x93,
+ DW_OP_deref_size = 0x94,
+ DW_OP_xderef_size = 0x95,
+ DW_OP_nop = 0x96,
+ DW_OP_push_object_address = 0x97,
+ DW_OP_call2 = 0x98,
+ DW_OP_call4 = 0x99,
+ DW_OP_call_ref = 0x9a,
+ DW_OP_form_tls_address = 0x9b,
+ DW_OP_call_frame_cfa = 0x9c,
+ DW_OP_bit_piece = 0x9d,
+ DW_OP_implicit_value = 0x9e,
+ DW_OP_stack_value = 0x9f,
+ DW_OP_implicit_pointer = 0xa0,
+ DW_OP_addrx = 0xa1,
+ DW_OP_constx = 0xa2,
+ DW_OP_entry_value = 0xa3,
+ DW_OP_const_type = 0xa4,
+ DW_OP_regval_type = 0xa5,
+ DW_OP_deref_type = 0xa6,
+ DW_OP_xderef_type = 0xa7,
+ DW_OP_convert = 0xa8,
+ DW_OP_reinterpret = 0xa9,
+
+ // GNU extensions
+ DW_OP_GNU_push_tls_address = 0xe0,
+ DW_OP_GNU_implicit_pointer = 0xf2,
+ DW_OP_GNU_entry_value = 0xf3,
+ DW_OP_GNU_const_type = 0xf4,
+ DW_OP_GNU_regval_type = 0xf5,
+ DW_OP_GNU_deref_type = 0xf6,
+ DW_OP_GNU_convert = 0xf7,
+ DW_OP_GNU_reinterpret = 0xf9,
+ DW_OP_GNU_parameter_ref = 0xfa,
+ DW_OP_GNU_addr_index = 0xfb,
+ DW_OP_GNU_const_index = 0xfc,
+
+ // Wasm extensions
+ DW_OP_WASM_location = 0xed,
+});
+
+dw!(
+/// Pointer encoding used by `.eh_frame`.
+///
+/// The four lower bits describe the
+/// format of the pointer, the upper four bits describe how the encoding should
+/// be applied.
+///
+/// Defined in https://refspecs.linuxfoundation.org/LSB_4.0.0/LSB-Core-generic/LSB-Core-generic/dwarfext.html
+DwEhPe(u8) {
+// Format of pointer encoding.
+
+// "Unsigned value is encoded using the Little Endian Base 128"
+ DW_EH_PE_uleb128 = 0x1,
+// "A 2 bytes unsigned value."
+ DW_EH_PE_udata2 = 0x2,
+// "A 4 bytes unsigned value."
+ DW_EH_PE_udata4 = 0x3,
+// "An 8 bytes unsigned value."
+ DW_EH_PE_udata8 = 0x4,
+// "Signed value is encoded using the Little Endian Base 128"
+ DW_EH_PE_sleb128 = 0x9,
+// "A 2 bytes signed value."
+ DW_EH_PE_sdata2 = 0x0a,
+// "A 4 bytes signed value."
+ DW_EH_PE_sdata4 = 0x0b,
+// "An 8 bytes signed value."
+ DW_EH_PE_sdata8 = 0x0c,
+
+// How the pointer encoding should be applied.
+
+// `DW_EH_PE_pcrel` pointers are relative to their own location.
+ DW_EH_PE_pcrel = 0x10,
+// "Value is relative to the beginning of the .text section."
+ DW_EH_PE_textrel = 0x20,
+// "Value is relative to the beginning of the .got or .eh_frame_hdr section."
+ DW_EH_PE_datarel = 0x30,
+// "Value is relative to the beginning of the function."
+ DW_EH_PE_funcrel = 0x40,
+// "Value is aligned to an address unit sized boundary."
+ DW_EH_PE_aligned = 0x50,
+
+// This bit can be set for any of the above encoding applications. When set,
+// the encoded value is the address of the real pointer result, not the
+// pointer result itself.
+//
+// This isn't defined in the DWARF or the `.eh_frame` standards, but is
+// generated by both GNU/Linux and macOS tooling.
+ DW_EH_PE_indirect = 0x80,
+
+// These constants apply to both the lower and upper bits.
+
+// "The Value is a literal pointer whose size is determined by the
+// architecture."
+ DW_EH_PE_absptr = 0x0,
+// The absence of a pointer and encoding.
+ DW_EH_PE_omit = 0xff,
+});
+
+const DW_EH_PE_FORMAT_MASK: u8 = 0b0000_1111;
+
+// Ignores indirection bit.
+const DW_EH_PE_APPLICATION_MASK: u8 = 0b0111_0000;
+
+impl DwEhPe {
+ /// Get the pointer encoding's format.
+ #[inline]
+ pub fn format(self) -> DwEhPe {
+ DwEhPe(self.0 & DW_EH_PE_FORMAT_MASK)
+ }
+
+ /// Get the pointer encoding's application.
+ #[inline]
+ pub fn application(self) -> DwEhPe {
+ DwEhPe(self.0 & DW_EH_PE_APPLICATION_MASK)
+ }
+
+ /// Is this encoding the absent pointer encoding?
+ #[inline]
+ pub fn is_absent(self) -> bool {
+ self == DW_EH_PE_omit
+ }
+
+ /// Is this coding indirect? If so, its encoded value is the address of the
+ /// real pointer result, not the pointer result itself.
+ #[inline]
+ pub fn is_indirect(self) -> bool {
+ self.0 & DW_EH_PE_indirect.0 != 0
+ }
+
+ /// Is this a known, valid pointer encoding?
+ pub fn is_valid_encoding(self) -> bool {
+ if self.is_absent() {
+ return true;
+ }
+
+ match self.format() {
+ DW_EH_PE_absptr | DW_EH_PE_uleb128 | DW_EH_PE_udata2 | DW_EH_PE_udata4
+ | DW_EH_PE_udata8 | DW_EH_PE_sleb128 | DW_EH_PE_sdata2 | DW_EH_PE_sdata4
+ | DW_EH_PE_sdata8 => {}
+ _ => return false,
+ }
+
+ match self.application() {
+ DW_EH_PE_absptr | DW_EH_PE_pcrel | DW_EH_PE_textrel | DW_EH_PE_datarel
+ | DW_EH_PE_funcrel | DW_EH_PE_aligned => {}
+ _ => return false,
+ }
+
+ true
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+
+ #[test]
+ fn test_dw_eh_pe_format() {
+ let encoding = DwEhPe(DW_EH_PE_pcrel.0 | DW_EH_PE_uleb128.0);
+ assert_eq!(encoding.format(), DW_EH_PE_uleb128);
+ }
+
+ #[test]
+ fn test_dw_eh_pe_application() {
+ let encoding = DwEhPe(DW_EH_PE_pcrel.0 | DW_EH_PE_uleb128.0);
+ assert_eq!(encoding.application(), DW_EH_PE_pcrel);
+ }
+
+ #[test]
+ fn test_dw_eh_pe_is_absent() {
+ assert_eq!(DW_EH_PE_absptr.is_absent(), false);
+ assert_eq!(DW_EH_PE_omit.is_absent(), true);
+ }
+
+ #[test]
+ fn test_dw_eh_pe_is_valid_encoding_ok() {
+ let encoding = DwEhPe(DW_EH_PE_uleb128.0 | DW_EH_PE_pcrel.0);
+ assert!(encoding.is_valid_encoding());
+ assert!(DW_EH_PE_absptr.is_valid_encoding());
+ assert!(DW_EH_PE_omit.is_valid_encoding());
+ }
+
+ #[test]
+ fn test_dw_eh_pe_is_valid_encoding_bad_format() {
+ let encoding = DwEhPe((DW_EH_PE_sdata8.0 + 1) | DW_EH_PE_pcrel.0);
+ assert_eq!(encoding.is_valid_encoding(), false);
+ }
+
+ #[test]
+ fn test_dw_eh_pe_is_valid_encoding_bad_application() {
+ let encoding = DwEhPe(DW_EH_PE_sdata8.0 | (DW_EH_PE_aligned.0 + 1));
+ assert_eq!(encoding.is_valid_encoding(), false);
+ }
+}
diff --git a/vendor/gimli-0.26.2/src/endianity.rs b/vendor/gimli-0.26.2/src/endianity.rs
new file mode 100644
index 000000000..3201551f1
--- /dev/null
+++ b/vendor/gimli-0.26.2/src/endianity.rs
@@ -0,0 +1,256 @@
+//! Types for compile-time and run-time endianity.
+
+use core::convert::TryInto;
+use core::fmt::Debug;
+
+/// A trait describing the endianity of some buffer.
+pub trait Endianity: Debug + Default + Clone + Copy + PartialEq + Eq {
+ /// Return true for big endian byte order.
+ fn is_big_endian(self) -> bool;
+
+ /// Return true for little endian byte order.
+ #[inline]
+ fn is_little_endian(self) -> bool {
+ !self.is_big_endian()
+ }
+
+ /// Reads an unsigned 16 bit integer from `buf`.
+ ///
+ /// # Panics
+ ///
+ /// Panics when `buf.len() < 2`.
+ #[inline]
+ fn read_u16(self, buf: &[u8]) -> u16 {
+ let bytes: &[u8; 2] = buf[..2].try_into().unwrap();
+ if self.is_big_endian() {
+ u16::from_be_bytes(*bytes)
+ } else {
+ u16::from_le_bytes(*bytes)
+ }
+ }
+
+ /// Reads an unsigned 32 bit integer from `buf`.
+ ///
+ /// # Panics
+ ///
+ /// Panics when `buf.len() < 4`.
+ #[inline]
+ fn read_u32(self, buf: &[u8]) -> u32 {
+ let bytes: &[u8; 4] = buf[..4].try_into().unwrap();
+ if self.is_big_endian() {
+ u32::from_be_bytes(*bytes)
+ } else {
+ u32::from_le_bytes(*bytes)
+ }
+ }
+
+ /// Reads an unsigned 64 bit integer from `buf`.
+ ///
+ /// # Panics
+ ///
+ /// Panics when `buf.len() < 8`.
+ #[inline]
+ fn read_u64(self, buf: &[u8]) -> u64 {
+ let bytes: &[u8; 8] = buf[..8].try_into().unwrap();
+ if self.is_big_endian() {
+ u64::from_be_bytes(*bytes)
+ } else {
+ u64::from_le_bytes(*bytes)
+ }
+ }
+
+ /// Read an unsigned n-bytes integer u64.
+ ///
+ /// # Panics
+ ///
+ /// Panics when `buf.len() < 1` or `buf.len() > 8`.
+ #[inline]
+ fn read_uint(&mut self, buf: &[u8]) -> u64 {
+ let mut tmp = [0; 8];
+ if self.is_big_endian() {
+ tmp[8 - buf.len()..].copy_from_slice(buf);
+ } else {
+ tmp[..buf.len()].copy_from_slice(buf);
+ }
+ self.read_u64(&tmp)
+ }
+
+ /// Reads a signed 16 bit integer from `buf`.
+ ///
+ /// # Panics
+ ///
+ /// Panics when `buf.len() < 2`.
+ #[inline]
+ fn read_i16(self, buf: &[u8]) -> i16 {
+ self.read_u16(buf) as i16
+ }
+
+ /// Reads a signed 32 bit integer from `buf`.
+ ///
+ /// # Panics
+ ///
+ /// Panics when `buf.len() < 4`.
+ #[inline]
+ fn read_i32(self, buf: &[u8]) -> i32 {
+ self.read_u32(buf) as i32
+ }
+
+ /// Reads a signed 64 bit integer from `buf`.
+ ///
+ /// # Panics
+ ///
+ /// Panics when `buf.len() < 8`.
+ #[inline]
+ fn read_i64(self, buf: &[u8]) -> i64 {
+ self.read_u64(buf) as i64
+ }
+
+ /// Reads a 32 bit floating point number from `buf`.
+ ///
+ /// # Panics
+ ///
+ /// Panics when `buf.len() < 8`.
+ #[inline]
+ fn read_f32(self, buf: &[u8]) -> f32 {
+ f32::from_bits(self.read_u32(buf))
+ }
+
+ /// Reads a 32 bit floating point number from `buf`.
+ ///
+ /// # Panics
+ ///
+ /// Panics when `buf.len() < 8`.
+ #[inline]
+ fn read_f64(self, buf: &[u8]) -> f64 {
+ f64::from_bits(self.read_u64(buf))
+ }
+
+ /// Writes an unsigned 16 bit integer `n` to `buf`.
+ ///
+ /// # Panics
+ ///
+ /// Panics when `buf.len() < 2`.
+ #[inline]
+ fn write_u16(self, buf: &mut [u8], n: u16) {
+ let bytes = if self.is_big_endian() {
+ n.to_be_bytes()
+ } else {
+ n.to_le_bytes()
+ };
+ buf[..2].copy_from_slice(&bytes);
+ }
+
+ /// Writes an unsigned 32 bit integer `n` to `buf`.
+ ///
+ /// # Panics
+ ///
+ /// Panics when `buf.len() < 4`.
+ #[inline]
+ fn write_u32(self, buf: &mut [u8], n: u32) {
+ let bytes = if self.is_big_endian() {
+ n.to_be_bytes()
+ } else {
+ n.to_le_bytes()
+ };
+ buf[..4].copy_from_slice(&bytes);
+ }
+
+ /// Writes an unsigned 64 bit integer `n` to `buf`.
+ ///
+ /// # Panics
+ ///
+ /// Panics when `buf.len() < 8`.
+ #[inline]
+ fn write_u64(self, buf: &mut [u8], n: u64) {
+ let bytes = if self.is_big_endian() {
+ n.to_be_bytes()
+ } else {
+ n.to_le_bytes()
+ };
+ buf[..8].copy_from_slice(&bytes);
+ }
+}
+
+/// Byte order that is selectable at runtime.
+#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
+pub enum RunTimeEndian {
+ /// Little endian byte order.
+ Little,
+ /// Big endian byte order.
+ Big,
+}
+
+impl Default for RunTimeEndian {
+ #[cfg(target_endian = "little")]
+ #[inline]
+ fn default() -> RunTimeEndian {
+ RunTimeEndian::Little
+ }
+
+ #[cfg(target_endian = "big")]
+ #[inline]
+ fn default() -> RunTimeEndian {
+ RunTimeEndian::Big
+ }
+}
+
+impl Endianity for RunTimeEndian {
+ #[inline]
+ fn is_big_endian(self) -> bool {
+ self != RunTimeEndian::Little
+ }
+}
+
+/// Little endian byte order.
+#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
+pub struct LittleEndian;
+
+impl Default for LittleEndian {
+ #[inline]
+ fn default() -> LittleEndian {
+ LittleEndian
+ }
+}
+
+impl Endianity for LittleEndian {
+ #[inline]
+ fn is_big_endian(self) -> bool {
+ false
+ }
+}
+
+/// Big endian byte order.
+#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
+pub struct BigEndian;
+
+impl Default for BigEndian {
+ #[inline]
+ fn default() -> BigEndian {
+ BigEndian
+ }
+}
+
+impl Endianity for BigEndian {
+ #[inline]
+ fn is_big_endian(self) -> bool {
+ true
+ }
+}
+
+/// The native endianity for the target platform.
+#[cfg(target_endian = "little")]
+pub type NativeEndian = LittleEndian;
+
+#[cfg(target_endian = "little")]
+#[allow(non_upper_case_globals)]
+#[doc(hidden)]
+pub const NativeEndian: LittleEndian = LittleEndian;
+
+/// The native endianity for the target platform.
+#[cfg(target_endian = "big")]
+pub type NativeEndian = BigEndian;
+
+#[cfg(target_endian = "big")]
+#[allow(non_upper_case_globals)]
+#[doc(hidden)]
+pub const NativeEndian: BigEndian = BigEndian;
diff --git a/vendor/gimli-0.26.2/src/leb128.rs b/vendor/gimli-0.26.2/src/leb128.rs
new file mode 100644
index 000000000..de81cfdcf
--- /dev/null
+++ b/vendor/gimli-0.26.2/src/leb128.rs
@@ -0,0 +1,612 @@
+//! Read and write DWARF's "Little Endian Base 128" (LEB128) variable length
+//! integer encoding.
+//!
+//! The implementation is a direct translation of the psuedocode in the DWARF 4
+//! standard's appendix C.
+//!
+//! Read and write signed integers:
+//!
+//! ```
+//! # #[cfg(all(feature = "read", feature = "write"))] {
+//! use gimli::{EndianSlice, NativeEndian, leb128};
+//!
+//! let mut buf = [0; 1024];
+//!
+//! // Write to anything that implements `std::io::Write`.
+//! {
+//! let mut writable = &mut buf[..];
+//! leb128::write::signed(&mut writable, -12345).expect("Should write number");
+//! }
+//!
+//! // Read from anything that implements `gimli::Reader`.
+//! let mut readable = EndianSlice::new(&buf[..], NativeEndian);
+//! let val = leb128::read::signed(&mut readable).expect("Should read number");
+//! assert_eq!(val, -12345);
+//! # }
+//! ```
+//!
+//! Or read and write unsigned integers:
+//!
+//! ```
+//! # #[cfg(all(feature = "read", feature = "write"))] {
+//! use gimli::{EndianSlice, NativeEndian, leb128};
+//!
+//! let mut buf = [0; 1024];
+//!
+//! {
+//! let mut writable = &mut buf[..];
+//! leb128::write::unsigned(&mut writable, 98765).expect("Should write number");
+//! }
+//!
+//! let mut readable = EndianSlice::new(&buf[..], NativeEndian);
+//! let val = leb128::read::unsigned(&mut readable).expect("Should read number");
+//! assert_eq!(val, 98765);
+//! # }
+//! ```
+
+const CONTINUATION_BIT: u8 = 1 << 7;
+#[cfg(feature = "read-core")]
+const SIGN_BIT: u8 = 1 << 6;
+
+#[inline]
+fn low_bits_of_byte(byte: u8) -> u8 {
+ byte & !CONTINUATION_BIT
+}
+
+#[inline]
+#[allow(dead_code)]
+fn low_bits_of_u64(val: u64) -> u8 {
+ let byte = val & u64::from(core::u8::MAX);
+ low_bits_of_byte(byte as u8)
+}
+
+/// A module for reading signed and unsigned integers that have been LEB128
+/// encoded.
+#[cfg(feature = "read-core")]
+pub mod read {
+ use super::{low_bits_of_byte, CONTINUATION_BIT, SIGN_BIT};
+ use crate::read::{Error, Reader, Result};
+
+ /// Read bytes until the LEB128 continuation bit is not set.
+ pub fn skip<R: Reader>(r: &mut R) -> Result<()> {
+ loop {
+ let byte = r.read_u8()?;
+ if byte & CONTINUATION_BIT == 0 {
+ return Ok(());
+ }
+ }
+ }
+
+ /// Read an unsigned LEB128 number from the given `Reader` and
+ /// return it or an error if reading failed.
+ pub fn unsigned<R: Reader>(r: &mut R) -> Result<u64> {
+ let mut result = 0;
+ let mut shift = 0;
+
+ loop {
+ let byte = r.read_u8()?;
+ if shift == 63 && byte != 0x00 && byte != 0x01 {
+ return Err(Error::BadUnsignedLeb128);
+ }
+
+ let low_bits = u64::from(low_bits_of_byte(byte));
+ result |= low_bits << shift;
+
+ if byte & CONTINUATION_BIT == 0 {
+ return Ok(result);
+ }
+
+ shift += 7;
+ }
+ }
+
+ /// Read an LEB128 u16 from the given `Reader` and
+ /// return it or an error if reading failed.
+ pub fn u16<R: Reader>(r: &mut R) -> Result<u16> {
+ let byte = r.read_u8()?;
+ let mut result = u16::from(low_bits_of_byte(byte));
+ if byte & CONTINUATION_BIT == 0 {
+ return Ok(result);
+ }
+
+ let byte = r.read_u8()?;
+ result |= u16::from(low_bits_of_byte(byte)) << 7;
+ if byte & CONTINUATION_BIT == 0 {
+ return Ok(result);
+ }
+
+ let byte = r.read_u8()?;
+ if byte > 0x03 {
+ return Err(Error::BadUnsignedLeb128);
+ }
+ result += u16::from(byte) << 14;
+ Ok(result)
+ }
+
+ /// Read a signed LEB128 number from the given `Reader` and
+ /// return it or an error if reading failed.
+ pub fn signed<R: Reader>(r: &mut R) -> Result<i64> {
+ let mut result = 0;
+ let mut shift = 0;
+ let size = 64;
+ let mut byte;
+
+ loop {
+ byte = r.read_u8()?;
+ if shift == 63 && byte != 0x00 && byte != 0x7f {
+ return Err(Error::BadSignedLeb128);
+ }
+
+ let low_bits = i64::from(low_bits_of_byte(byte));
+ result |= low_bits << shift;
+ shift += 7;
+
+ if byte & CONTINUATION_BIT == 0 {
+ break;
+ }
+ }
+
+ if shift < size && (SIGN_BIT & byte) == SIGN_BIT {
+ // Sign extend the result.
+ result |= !0 << shift;
+ }
+
+ Ok(result)
+ }
+}
+
+/// A module for writing integers encoded as LEB128.
+#[cfg(feature = "write")]
+pub mod write {
+ use super::{low_bits_of_u64, CONTINUATION_BIT};
+ use std::io;
+
+ /// Write the given unsigned number using the LEB128 encoding to the given
+ /// `std::io::Write`able. Returns the number of bytes written to `w`, or an
+ /// error if writing failed.
+ pub fn unsigned<W>(w: &mut W, mut val: u64) -> Result<usize, io::Error>
+ where
+ W: io::Write,
+ {
+ let mut bytes_written = 0;
+ loop {
+ let mut byte = low_bits_of_u64(val);
+ val >>= 7;
+ if val != 0 {
+ // More bytes to come, so set the continuation bit.
+ byte |= CONTINUATION_BIT;
+ }
+
+ let buf = [byte];
+ w.write_all(&buf)?;
+ bytes_written += 1;
+
+ if val == 0 {
+ return Ok(bytes_written);
+ }
+ }
+ }
+
+ /// Return the size of the LEB128 encoding of the given unsigned number.
+ pub fn uleb128_size(mut val: u64) -> usize {
+ let mut size = 0;
+ loop {
+ val >>= 7;
+ size += 1;
+ if val == 0 {
+ return size;
+ }
+ }
+ }
+
+ /// Write the given signed number using the LEB128 encoding to the given
+ /// `std::io::Write`able. Returns the number of bytes written to `w`, or an
+ /// error if writing failed.
+ pub fn signed<W>(w: &mut W, mut val: i64) -> Result<usize, io::Error>
+ where
+ W: io::Write,
+ {
+ let mut bytes_written = 0;
+ loop {
+ let mut byte = val as u8;
+ // Keep the sign bit for testing
+ val >>= 6;
+ let done = val == 0 || val == -1;
+ if done {
+ byte &= !CONTINUATION_BIT;
+ } else {
+ // Remove the sign bit
+ val >>= 1;
+ // More bytes to come, so set the continuation bit.
+ byte |= CONTINUATION_BIT;
+ }
+
+ let buf = [byte];
+ w.write_all(&buf)?;
+ bytes_written += 1;
+
+ if done {
+ return Ok(bytes_written);
+ }
+ }
+ }
+
+ /// Return the size of the LEB128 encoding of the given signed number.
+ pub fn sleb128_size(mut val: i64) -> usize {
+ let mut size = 0;
+ loop {
+ val >>= 6;
+ let done = val == 0 || val == -1;
+ val >>= 1;
+ size += 1;
+ if done {
+ return size;
+ }
+ }
+ }
+}
+
+#[cfg(test)]
+#[cfg(all(feature = "read", feature = "write"))]
+mod tests {
+ use super::{low_bits_of_byte, low_bits_of_u64, read, write, CONTINUATION_BIT};
+ use crate::endianity::NativeEndian;
+ use crate::read::{EndianSlice, Error, ReaderOffsetId};
+
+ trait ResultExt {
+ fn map_eof(self, input: &[u8]) -> Self;
+ }
+
+ impl<T> ResultExt for Result<T, Error> {
+ fn map_eof(self, input: &[u8]) -> Self {
+ match self {
+ Err(Error::UnexpectedEof(id)) => {
+ let id = ReaderOffsetId(id.0 - input.as_ptr() as u64);
+ Err(Error::UnexpectedEof(id))
+ }
+ r => r,
+ }
+ }
+ }
+
+ #[test]
+ fn test_low_bits_of_byte() {
+ for i in 0..127 {
+ assert_eq!(i, low_bits_of_byte(i));
+ assert_eq!(i, low_bits_of_byte(i | CONTINUATION_BIT));
+ }
+ }
+
+ #[test]
+ fn test_low_bits_of_u64() {
+ for i in 0u64..127 {
+ assert_eq!(i as u8, low_bits_of_u64(1 << 16 | i));
+ assert_eq!(
+ i as u8,
+ low_bits_of_u64(i << 16 | i | (u64::from(CONTINUATION_BIT)))
+ );
+ }
+ }
+
+ // Examples from the DWARF 4 standard, section 7.6, figure 22.
+ #[test]
+ fn test_read_unsigned() {
+ let buf = [2u8];
+ let mut readable = EndianSlice::new(&buf[..], NativeEndian);
+ assert_eq!(
+ 2,
+ read::unsigned(&mut readable).expect("Should read number")
+ );
+
+ let buf = [127u8];
+ let mut readable = EndianSlice::new(&buf[..], NativeEndian);
+ assert_eq!(
+ 127,
+ read::unsigned(&mut readable).expect("Should read number")
+ );
+
+ let buf = [CONTINUATION_BIT, 1];
+ let mut readable = EndianSlice::new(&buf[..], NativeEndian);
+ assert_eq!(
+ 128,
+ read::unsigned(&mut readable).expect("Should read number")
+ );
+
+ let buf = [1u8 | CONTINUATION_BIT, 1];
+ let mut readable = EndianSlice::new(&buf[..], NativeEndian);
+ assert_eq!(
+ 129,
+ read::unsigned(&mut readable).expect("Should read number")
+ );
+
+ let buf = [2u8 | CONTINUATION_BIT, 1];
+ let mut readable = EndianSlice::new(&buf[..], NativeEndian);
+ assert_eq!(
+ 130,
+ read::unsigned(&mut readable).expect("Should read number")
+ );
+
+ let buf = [57u8 | CONTINUATION_BIT, 100];
+ let mut readable = EndianSlice::new(&buf[..], NativeEndian);
+ assert_eq!(
+ 12857,
+ read::unsigned(&mut readable).expect("Should read number")
+ );
+ }
+
+ // Examples from the DWARF 4 standard, section 7.6, figure 23.
+ #[test]
+ fn test_read_signed() {
+ let buf = [2u8];
+ let mut readable = EndianSlice::new(&buf[..], NativeEndian);
+ assert_eq!(2, read::signed(&mut readable).expect("Should read number"));
+
+ let buf = [0x7eu8];
+ let mut readable = EndianSlice::new(&buf[..], NativeEndian);
+ assert_eq!(-2, read::signed(&mut readable).expect("Should read number"));
+
+ let buf = [127u8 | CONTINUATION_BIT, 0];
+ let mut readable = EndianSlice::new(&buf[..], NativeEndian);
+ assert_eq!(
+ 127,
+ read::signed(&mut readable).expect("Should read number")
+ );
+
+ let buf = [1u8 | CONTINUATION_BIT, 0x7f];
+ let mut readable = EndianSlice::new(&buf[..], NativeEndian);
+ assert_eq!(
+ -127,
+ read::signed(&mut readable).expect("Should read number")
+ );
+
+ let buf = [CONTINUATION_BIT, 1];
+ let mut readable = EndianSlice::new(&buf[..], NativeEndian);
+ assert_eq!(
+ 128,
+ read::signed(&mut readable).expect("Should read number")
+ );
+
+ let buf = [CONTINUATION_BIT, 0x7f];
+ let mut readable = EndianSlice::new(&buf[..], NativeEndian);
+ assert_eq!(
+ -128,
+ read::signed(&mut readable).expect("Should read number")
+ );
+
+ let buf = [1u8 | CONTINUATION_BIT, 1];
+ let mut readable = EndianSlice::new(&buf[..], NativeEndian);
+ assert_eq!(
+ 129,
+ read::signed(&mut readable).expect("Should read number")
+ );
+
+ let buf = [0x7fu8 | CONTINUATION_BIT, 0x7e];
+ let mut readable = EndianSlice::new(&buf[..], NativeEndian);
+ assert_eq!(
+ -129,
+ read::signed(&mut readable).expect("Should read number")
+ );
+ }
+
+ #[test]
+ fn test_read_signed_63_bits() {
+ let buf = [
+ CONTINUATION_BIT,
+ CONTINUATION_BIT,
+ CONTINUATION_BIT,
+ CONTINUATION_BIT,
+ CONTINUATION_BIT,
+ CONTINUATION_BIT,
+ CONTINUATION_BIT,
+ CONTINUATION_BIT,
+ 0x40,
+ ];
+ let mut readable = EndianSlice::new(&buf[..], NativeEndian);
+ assert_eq!(
+ -0x4000_0000_0000_0000,
+ read::signed(&mut readable).expect("Should read number")
+ );
+ }
+
+ #[test]
+ fn test_read_unsigned_not_enough_data() {
+ let buf = [CONTINUATION_BIT];
+ let mut readable = EndianSlice::new(&buf[..], NativeEndian);
+ assert_eq!(
+ read::unsigned(&mut readable).map_eof(&buf),
+ Err(Error::UnexpectedEof(ReaderOffsetId(1)))
+ );
+ }
+
+ #[test]
+ fn test_read_signed_not_enough_data() {
+ let buf = [CONTINUATION_BIT];
+ let mut readable = EndianSlice::new(&buf[..], NativeEndian);
+ assert_eq!(
+ read::signed(&mut readable).map_eof(&buf),
+ Err(Error::UnexpectedEof(ReaderOffsetId(1)))
+ );
+ }
+
+ #[test]
+ fn test_write_unsigned_not_enough_space() {
+ let mut buf = [0; 1];
+ let mut writable = &mut buf[..];
+ match write::unsigned(&mut writable, 128) {
+ Err(e) => assert_eq!(e.kind(), std::io::ErrorKind::WriteZero),
+ otherwise => panic!("Unexpected: {:?}", otherwise),
+ }
+ }
+
+ #[test]
+ fn test_write_signed_not_enough_space() {
+ let mut buf = [0; 1];
+ let mut writable = &mut buf[..];
+ match write::signed(&mut writable, 128) {
+ Err(e) => assert_eq!(e.kind(), std::io::ErrorKind::WriteZero),
+ otherwise => panic!("Unexpected: {:?}", otherwise),
+ }
+ }
+
+ #[test]
+ fn dogfood_signed() {
+ fn inner(i: i64) {
+ let mut buf = [0u8; 1024];
+
+ {
+ let mut writable = &mut buf[..];
+ write::signed(&mut writable, i).expect("Should write signed number");
+ }
+
+ let mut readable = EndianSlice::new(&buf[..], NativeEndian);
+ let result = read::signed(&mut readable).expect("Should be able to read it back again");
+ assert_eq!(i, result);
+ }
+ for i in -513..513 {
+ inner(i);
+ }
+ inner(core::i64::MIN);
+ }
+
+ #[test]
+ fn dogfood_unsigned() {
+ for i in 0..1025 {
+ let mut buf = [0u8; 1024];
+
+ {
+ let mut writable = &mut buf[..];
+ write::unsigned(&mut writable, i).expect("Should write signed number");
+ }
+
+ let mut readable = EndianSlice::new(&buf[..], NativeEndian);
+ let result =
+ read::unsigned(&mut readable).expect("Should be able to read it back again");
+ assert_eq!(i, result);
+ }
+ }
+
+ #[test]
+ fn test_read_unsigned_overflow() {
+ let buf = [
+ 2u8 | CONTINUATION_BIT,
+ 2 | CONTINUATION_BIT,
+ 2 | CONTINUATION_BIT,
+ 2 | CONTINUATION_BIT,
+ 2 | CONTINUATION_BIT,
+ 2 | CONTINUATION_BIT,
+ 2 | CONTINUATION_BIT,
+ 2 | CONTINUATION_BIT,
+ 2 | CONTINUATION_BIT,
+ 2 | CONTINUATION_BIT,
+ 2 | CONTINUATION_BIT,
+ 2 | CONTINUATION_BIT,
+ 2 | CONTINUATION_BIT,
+ 2 | CONTINUATION_BIT,
+ 2 | CONTINUATION_BIT,
+ 2 | CONTINUATION_BIT,
+ 2 | CONTINUATION_BIT,
+ 2 | CONTINUATION_BIT,
+ 2 | CONTINUATION_BIT,
+ 2 | CONTINUATION_BIT,
+ 2 | CONTINUATION_BIT,
+ 2 | CONTINUATION_BIT,
+ 2 | CONTINUATION_BIT,
+ 2 | CONTINUATION_BIT,
+ 2 | CONTINUATION_BIT,
+ 2 | CONTINUATION_BIT,
+ 2 | CONTINUATION_BIT,
+ 2 | CONTINUATION_BIT,
+ 2 | CONTINUATION_BIT,
+ 2 | CONTINUATION_BIT,
+ 1,
+ ];
+ let mut readable = EndianSlice::new(&buf[..], NativeEndian);
+ assert!(read::unsigned(&mut readable).is_err());
+ }
+
+ #[test]
+ fn test_read_signed_overflow() {
+ let buf = [
+ 2u8 | CONTINUATION_BIT,
+ 2 | CONTINUATION_BIT,
+ 2 | CONTINUATION_BIT,
+ 2 | CONTINUATION_BIT,
+ 2 | CONTINUATION_BIT,
+ 2 | CONTINUATION_BIT,
+ 2 | CONTINUATION_BIT,
+ 2 | CONTINUATION_BIT,
+ 2 | CONTINUATION_BIT,
+ 2 | CONTINUATION_BIT,
+ 2 | CONTINUATION_BIT,
+ 2 | CONTINUATION_BIT,
+ 2 | CONTINUATION_BIT,
+ 2 | CONTINUATION_BIT,
+ 2 | CONTINUATION_BIT,
+ 2 | CONTINUATION_BIT,
+ 2 | CONTINUATION_BIT,
+ 2 | CONTINUATION_BIT,
+ 2 | CONTINUATION_BIT,
+ 2 | CONTINUATION_BIT,
+ 2 | CONTINUATION_BIT,
+ 2 | CONTINUATION_BIT,
+ 2 | CONTINUATION_BIT,
+ 2 | CONTINUATION_BIT,
+ 2 | CONTINUATION_BIT,
+ 2 | CONTINUATION_BIT,
+ 2 | CONTINUATION_BIT,
+ 2 | CONTINUATION_BIT,
+ 2 | CONTINUATION_BIT,
+ 2 | CONTINUATION_BIT,
+ 1,
+ ];
+ let mut readable = EndianSlice::new(&buf[..], NativeEndian);
+ assert!(read::signed(&mut readable).is_err());
+ }
+
+ #[test]
+ fn test_read_multiple() {
+ let buf = [2u8 | CONTINUATION_BIT, 1u8, 1u8];
+
+ let mut readable = EndianSlice::new(&buf[..], NativeEndian);
+ assert_eq!(
+ read::unsigned(&mut readable).expect("Should read first number"),
+ 130u64
+ );
+ assert_eq!(
+ read::unsigned(&mut readable).expect("Should read first number"),
+ 1u64
+ );
+ }
+
+ #[test]
+ fn test_read_u16() {
+ for (buf, val) in [
+ (&[2][..], 2),
+ (&[0x7f][..], 0x7f),
+ (&[0x80, 1][..], 0x80),
+ (&[0x81, 1][..], 0x81),
+ (&[0x82, 1][..], 0x82),
+ (&[0xff, 0x7f][..], 0x3fff),
+ (&[0x80, 0x80, 1][..], 0x4000),
+ (&[0xff, 0xff, 1][..], 0x7fff),
+ (&[0xff, 0xff, 3][..], 0xffff),
+ ]
+ .iter()
+ {
+ let mut readable = EndianSlice::new(buf, NativeEndian);
+ assert_eq!(*val, read::u16(&mut readable).expect("Should read number"));
+ }
+
+ for buf in [
+ &[0x80][..],
+ &[0x80, 0x80][..],
+ &[0x80, 0x80, 4][..],
+ &[0x80, 0x80, 0x80, 3][..],
+ ]
+ .iter()
+ {
+ let mut readable = EndianSlice::new(buf, NativeEndian);
+ assert!(read::u16(&mut readable).is_err(), "{:?}", buf);
+ }
+ }
+}
diff --git a/vendor/gimli-0.26.2/src/lib.rs b/vendor/gimli-0.26.2/src/lib.rs
new file mode 100644
index 000000000..ed1af9cbd
--- /dev/null
+++ b/vendor/gimli-0.26.2/src/lib.rs
@@ -0,0 +1,76 @@
+//! `gimli` is a library for reading and writing the
+//! [DWARF debugging format](https://dwarfstd.org/).
+//!
+//! See the [read](./read/index.html) and [write](./write/index.html) modules
+//! for examples and API documentation.
+//!
+//! ## Cargo Features
+//!
+//! Cargo features that can be enabled with `gimli`:
+//!
+//! * `std`: Enabled by default. Use the `std` library. Disabling this feature
+//! allows using `gimli` in embedded environments that do not have access to
+//! `std`. Note that even when `std` is disabled, `gimli` still requires an
+//! implementation of the `alloc` crate.
+//!
+//! * `read`: Enabled by default. Enables the `read` module. Use of `std` is
+//! optional.
+//!
+//! * `write`: Enabled by default. Enables the `write` module. Always uses
+//! the `std` library.
+#![deny(missing_docs)]
+#![deny(missing_debug_implementations)]
+// Selectively enable rust 2018 warnings
+#![warn(bare_trait_objects)]
+#![warn(unused_extern_crates)]
+#![warn(ellipsis_inclusive_range_patterns)]
+//#![warn(elided_lifetimes_in_paths)]
+#![warn(explicit_outlives_requirements)]
+// Allow clippy warnings when we aren't building with clippy.
+#![allow(unknown_lints)]
+// False positives with `fallible_iterator`.
+#![allow(clippy::should_implement_trait)]
+// Many false positives involving `continue`.
+#![allow(clippy::never_loop)]
+// False positives when block expressions are used inside an assertion.
+#![allow(clippy::panic_params)]
+#![no_std]
+
+#[allow(unused_imports)]
+#[cfg(any(feature = "read", feature = "write"))]
+#[macro_use]
+extern crate alloc;
+
+#[cfg(any(feature = "std", feature = "write"))]
+#[macro_use]
+extern crate std;
+
+#[cfg(feature = "stable_deref_trait")]
+pub use stable_deref_trait::{CloneStableDeref, StableDeref};
+
+mod common;
+pub use crate::common::*;
+
+mod arch;
+pub use crate::arch::*;
+
+pub mod constants;
+// For backwards compat.
+pub use crate::constants::*;
+
+mod endianity;
+pub use crate::endianity::{BigEndian, Endianity, LittleEndian, NativeEndian, RunTimeEndian};
+
+pub mod leb128;
+
+#[cfg(feature = "read-core")]
+pub mod read;
+// For backwards compat.
+#[cfg(feature = "read-core")]
+pub use crate::read::*;
+
+#[cfg(feature = "write")]
+pub mod write;
+
+#[cfg(test)]
+mod test_util;
diff --git a/vendor/gimli-0.26.2/src/read/abbrev.rs b/vendor/gimli-0.26.2/src/read/abbrev.rs
new file mode 100644
index 000000000..1a24835a7
--- /dev/null
+++ b/vendor/gimli-0.26.2/src/read/abbrev.rs
@@ -0,0 +1,996 @@
+//! Functions for parsing DWARF debugging abbreviations.
+
+use alloc::collections::btree_map;
+use alloc::vec::Vec;
+use core::convert::TryFrom;
+use core::fmt::{self, Debug};
+use core::iter::FromIterator;
+use core::ops::Deref;
+
+use crate::common::{DebugAbbrevOffset, Encoding, SectionId};
+use crate::constants;
+use crate::endianity::Endianity;
+use crate::read::{EndianSlice, Error, Reader, Result, Section, UnitHeader};
+
+/// The `DebugAbbrev` struct represents the abbreviations describing
+/// `DebuggingInformationEntry`s' attribute names and forms found in the
+/// `.debug_abbrev` section.
+#[derive(Debug, Default, Clone, Copy)]
+pub struct DebugAbbrev<R> {
+ debug_abbrev_section: R,
+}
+
+impl<'input, Endian> DebugAbbrev<EndianSlice<'input, Endian>>
+where
+ Endian: Endianity,
+{
+ /// Construct a new `DebugAbbrev` instance from the data in the `.debug_abbrev`
+ /// section.
+ ///
+ /// It is the caller's responsibility to read the `.debug_abbrev` section and
+ /// present it as a `&[u8]` slice. That means using some ELF loader on
+ /// Linux, a Mach-O loader on macOS, etc.
+ ///
+ /// ```
+ /// use gimli::{DebugAbbrev, LittleEndian};
+ ///
+ /// # let buf = [0x00, 0x01, 0x02, 0x03];
+ /// # let read_debug_abbrev_section_somehow = || &buf;
+ /// let debug_abbrev = DebugAbbrev::new(read_debug_abbrev_section_somehow(), LittleEndian);
+ /// ```
+ pub fn new(debug_abbrev_section: &'input [u8], endian: Endian) -> Self {
+ Self::from(EndianSlice::new(debug_abbrev_section, endian))
+ }
+}
+
+impl<R: Reader> DebugAbbrev<R> {
+ /// Parse the abbreviations at the given `offset` within this
+ /// `.debug_abbrev` section.
+ ///
+ /// The `offset` should generally be retrieved from a unit header.
+ pub fn abbreviations(
+ &self,
+ debug_abbrev_offset: DebugAbbrevOffset<R::Offset>,
+ ) -> Result<Abbreviations> {
+ let input = &mut self.debug_abbrev_section.clone();
+ input.skip(debug_abbrev_offset.0)?;
+ Abbreviations::parse(input)
+ }
+}
+
+impl<T> DebugAbbrev<T> {
+ /// Create a `DebugAbbrev` section that references the data in `self`.
+ ///
+ /// This is useful when `R` implements `Reader` but `T` does not.
+ ///
+ /// ## Example Usage
+ ///
+ /// ```rust,no_run
+ /// # let load_section = || unimplemented!();
+ /// // Read the DWARF section into a `Vec` with whatever object loader you're using.
+ /// let owned_section: gimli::DebugAbbrev<Vec<u8>> = load_section();
+ /// // Create a reference to the DWARF section.
+ /// let section = owned_section.borrow(|section| {
+ /// gimli::EndianSlice::new(&section, gimli::LittleEndian)
+ /// });
+ /// ```
+ pub fn borrow<'a, F, R>(&'a self, mut borrow: F) -> DebugAbbrev<R>
+ where
+ F: FnMut(&'a T) -> R,
+ {
+ borrow(&self.debug_abbrev_section).into()
+ }
+}
+
+impl<R> Section<R> for DebugAbbrev<R> {
+ fn id() -> SectionId {
+ SectionId::DebugAbbrev
+ }
+
+ fn reader(&self) -> &R {
+ &self.debug_abbrev_section
+ }
+}
+
+impl<R> From<R> for DebugAbbrev<R> {
+ fn from(debug_abbrev_section: R) -> Self {
+ DebugAbbrev {
+ debug_abbrev_section,
+ }
+ }
+}
+
+/// A set of type abbreviations.
+///
+/// Construct an `Abbreviations` instance with the
+/// [`abbreviations()`](struct.UnitHeader.html#method.abbreviations)
+/// method.
+#[derive(Debug, Default, Clone)]
+pub struct Abbreviations {
+ vec: Vec<Abbreviation>,
+ map: btree_map::BTreeMap<u64, Abbreviation>,
+}
+
+impl Abbreviations {
+ /// Construct a new, empty set of abbreviations.
+ fn empty() -> Abbreviations {
+ Abbreviations {
+ vec: Vec::new(),
+ map: btree_map::BTreeMap::new(),
+ }
+ }
+
+ /// Insert an abbreviation into the set.
+ ///
+ /// Returns `Ok` if it is the first abbreviation in the set with its code,
+ /// `Err` if the code is a duplicate and there already exists an
+ /// abbreviation in the set with the given abbreviation's code.
+ fn insert(&mut self, abbrev: Abbreviation) -> ::core::result::Result<(), ()> {
+ let code_usize = abbrev.code as usize;
+ if code_usize as u64 == abbrev.code {
+ // Optimize for sequential abbreviation codes by storing them
+ // in a Vec, as long as the map doesn't already contain them.
+ // A potential further optimization would be to allow some
+ // holes in the Vec, but there's no need for that yet.
+ if code_usize - 1 < self.vec.len() {
+ return Err(());
+ } else if code_usize - 1 == self.vec.len() {
+ if !self.map.is_empty() && self.map.contains_key(&abbrev.code) {
+ return Err(());
+ } else {
+ self.vec.push(abbrev);
+ return Ok(());
+ }
+ }
+ }
+ match self.map.entry(abbrev.code) {
+ btree_map::Entry::Occupied(_) => Err(()),
+ btree_map::Entry::Vacant(entry) => {
+ entry.insert(abbrev);
+ Ok(())
+ }
+ }
+ }
+
+ /// Get the abbreviation associated with the given code.
+ #[inline]
+ pub fn get(&self, code: u64) -> Option<&Abbreviation> {
+ if let Ok(code) = usize::try_from(code) {
+ let index = code.checked_sub(1)?;
+ if index < self.vec.len() {
+ return Some(&self.vec[index]);
+ }
+ }
+
+ self.map.get(&code)
+ }
+
+ /// Parse a series of abbreviations, terminated by a null abbreviation.
+ fn parse<R: Reader>(input: &mut R) -> Result<Abbreviations> {
+ let mut abbrevs = Abbreviations::empty();
+
+ while let Some(abbrev) = Abbreviation::parse(input)? {
+ if abbrevs.insert(abbrev).is_err() {
+ return Err(Error::DuplicateAbbreviationCode);
+ }
+ }
+
+ Ok(abbrevs)
+ }
+}
+
+/// An abbreviation describes the shape of a `DebuggingInformationEntry`'s type:
+/// its code, tag type, whether it has children, and its set of attributes.
+#[derive(Debug, Clone, PartialEq, Eq)]
+pub struct Abbreviation {
+ code: u64,
+ tag: constants::DwTag,
+ has_children: constants::DwChildren,
+ attributes: Attributes,
+}
+
+impl Abbreviation {
+ /// Construct a new `Abbreviation`.
+ ///
+ /// ### Panics
+ ///
+ /// Panics if `code` is `0`.
+ pub(crate) fn new(
+ code: u64,
+ tag: constants::DwTag,
+ has_children: constants::DwChildren,
+ attributes: Attributes,
+ ) -> Abbreviation {
+ assert_ne!(code, 0);
+ Abbreviation {
+ code,
+ tag,
+ has_children,
+ attributes,
+ }
+ }
+
+ /// Get this abbreviation's code.
+ #[inline]
+ pub fn code(&self) -> u64 {
+ self.code
+ }
+
+ /// Get this abbreviation's tag.
+ #[inline]
+ pub fn tag(&self) -> constants::DwTag {
+ self.tag
+ }
+
+ /// Return true if this abbreviation's type has children, false otherwise.
+ #[inline]
+ pub fn has_children(&self) -> bool {
+ self.has_children == constants::DW_CHILDREN_yes
+ }
+
+ /// Get this abbreviation's attributes.
+ #[inline]
+ pub fn attributes(&self) -> &[AttributeSpecification] {
+ &self.attributes[..]
+ }
+
+ /// Parse an abbreviation's tag.
+ fn parse_tag<R: Reader>(input: &mut R) -> Result<constants::DwTag> {
+ let val = input.read_uleb128_u16()?;
+ if val == 0 {
+ Err(Error::AbbreviationTagZero)
+ } else {
+ Ok(constants::DwTag(val))
+ }
+ }
+
+ /// Parse an abbreviation's "does the type have children?" byte.
+ fn parse_has_children<R: Reader>(input: &mut R) -> Result<constants::DwChildren> {
+ let val = input.read_u8()?;
+ let val = constants::DwChildren(val);
+ if val == constants::DW_CHILDREN_no || val == constants::DW_CHILDREN_yes {
+ Ok(val)
+ } else {
+ Err(Error::BadHasChildren)
+ }
+ }
+
+ /// Parse a series of attribute specifications, terminated by a null attribute
+ /// specification.
+ fn parse_attributes<R: Reader>(input: &mut R) -> Result<Attributes> {
+ let mut attrs = Attributes::new();
+
+ while let Some(attr) = AttributeSpecification::parse(input)? {
+ attrs.push(attr);
+ }
+
+ Ok(attrs)
+ }
+
+ /// Parse an abbreviation. Return `None` for the null abbreviation, `Some`
+ /// for an actual abbreviation.
+ fn parse<R: Reader>(input: &mut R) -> Result<Option<Abbreviation>> {
+ let code = input.read_uleb128()?;
+ if code == 0 {
+ return Ok(None);
+ }
+
+ let tag = Self::parse_tag(input)?;
+ let has_children = Self::parse_has_children(input)?;
+ let attributes = Self::parse_attributes(input)?;
+ let abbrev = Abbreviation::new(code, tag, has_children, attributes);
+ Ok(Some(abbrev))
+ }
+}
+
+/// A list of attributes found in an `Abbreviation`
+#[derive(Clone)]
+pub(crate) enum Attributes {
+ Inline {
+ buf: [AttributeSpecification; MAX_ATTRIBUTES_INLINE],
+ len: usize,
+ },
+ Heap(Vec<AttributeSpecification>),
+}
+
+// Length of 5 based on benchmark results for both x86-64 and i686.
+const MAX_ATTRIBUTES_INLINE: usize = 5;
+
+impl Attributes {
+ /// Returns a new empty list of attributes
+ fn new() -> Attributes {
+ let default =
+ AttributeSpecification::new(constants::DW_AT_null, constants::DW_FORM_null, None);
+ Attributes::Inline {
+ buf: [default; 5],
+ len: 0,
+ }
+ }
+
+ /// Pushes a new value onto this list of attributes.
+ fn push(&mut self, attr: AttributeSpecification) {
+ match self {
+ Attributes::Heap(list) => return list.push(attr),
+ Attributes::Inline {
+ buf,
+ len: MAX_ATTRIBUTES_INLINE,
+ } => {
+ let mut list = buf.to_vec();
+ list.push(attr);
+ *self = Attributes::Heap(list);
+ }
+ Attributes::Inline { buf, len } => {
+ buf[*len] = attr;
+ *len += 1;
+ }
+ }
+ }
+}
+
+impl Debug for Attributes {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ (&**self).fmt(f)
+ }
+}
+
+impl PartialEq for Attributes {
+ fn eq(&self, other: &Attributes) -> bool {
+ &**self == &**other
+ }
+}
+
+impl Eq for Attributes {}
+
+impl Deref for Attributes {
+ type Target = [AttributeSpecification];
+ fn deref(&self) -> &[AttributeSpecification] {
+ match self {
+ Attributes::Inline { buf, len } => &buf[..*len],
+ Attributes::Heap(list) => list,
+ }
+ }
+}
+
+impl FromIterator<AttributeSpecification> for Attributes {
+ fn from_iter<I>(iter: I) -> Attributes
+ where
+ I: IntoIterator<Item = AttributeSpecification>,
+ {
+ let mut list = Attributes::new();
+ for item in iter {
+ list.push(item);
+ }
+ return list;
+ }
+}
+
+impl From<Vec<AttributeSpecification>> for Attributes {
+ fn from(list: Vec<AttributeSpecification>) -> Attributes {
+ Attributes::Heap(list)
+ }
+}
+
+/// The description of an attribute in an abbreviated type. It is a pair of name
+/// and form.
+#[derive(Debug, Clone, Copy, PartialEq, Eq)]
+pub struct AttributeSpecification {
+ name: constants::DwAt,
+ form: constants::DwForm,
+ implicit_const_value: i64,
+}
+
+impl AttributeSpecification {
+ /// Construct a new `AttributeSpecification` from the given name and form
+ /// and implicit const value.
+ #[inline]
+ pub fn new(
+ name: constants::DwAt,
+ form: constants::DwForm,
+ implicit_const_value: Option<i64>,
+ ) -> AttributeSpecification {
+ debug_assert!(
+ (form == constants::DW_FORM_implicit_const && implicit_const_value.is_some())
+ || (form != constants::DW_FORM_implicit_const && implicit_const_value.is_none())
+ );
+ AttributeSpecification {
+ name,
+ form,
+ implicit_const_value: implicit_const_value.unwrap_or(0),
+ }
+ }
+
+ /// Get the attribute's name.
+ #[inline]
+ pub fn name(&self) -> constants::DwAt {
+ self.name
+ }
+
+ /// Get the attribute's form.
+ #[inline]
+ pub fn form(&self) -> constants::DwForm {
+ self.form
+ }
+
+ /// Get the attribute's implicit const value.
+ #[inline]
+ pub fn implicit_const_value(&self) -> Option<i64> {
+ if self.form == constants::DW_FORM_implicit_const {
+ Some(self.implicit_const_value)
+ } else {
+ None
+ }
+ }
+
+ /// Return the size of the attribute, in bytes.
+ ///
+ /// Note that because some attributes are variably sized, the size cannot
+ /// always be known without parsing, in which case we return `None`.
+ pub fn size<R: Reader>(&self, header: &UnitHeader<R>) -> Option<usize> {
+ get_attribute_size(self.form, header.encoding()).map(usize::from)
+ }
+
+ /// Parse an attribute's form.
+ fn parse_form<R: Reader>(input: &mut R) -> Result<constants::DwForm> {
+ let val = input.read_uleb128_u16()?;
+ if val == 0 {
+ Err(Error::AttributeFormZero)
+ } else {
+ Ok(constants::DwForm(val))
+ }
+ }
+
+ /// Parse an attribute specification. Returns `None` for the null attribute
+ /// specification, `Some` for an actual attribute specification.
+ fn parse<R: Reader>(input: &mut R) -> Result<Option<AttributeSpecification>> {
+ let name = input.read_uleb128_u16()?;
+ if name == 0 {
+ // Parse the null attribute specification.
+ let form = input.read_uleb128_u16()?;
+ return if form == 0 {
+ Ok(None)
+ } else {
+ Err(Error::ExpectedZero)
+ };
+ }
+
+ let name = constants::DwAt(name);
+ let form = Self::parse_form(input)?;
+ let implicit_const_value = if form == constants::DW_FORM_implicit_const {
+ Some(input.read_sleb128()?)
+ } else {
+ None
+ };
+ let spec = AttributeSpecification::new(name, form, implicit_const_value);
+ Ok(Some(spec))
+ }
+}
+
+#[inline]
+pub(crate) fn get_attribute_size(form: constants::DwForm, encoding: Encoding) -> Option<u8> {
+ match form {
+ constants::DW_FORM_addr => Some(encoding.address_size),
+
+ constants::DW_FORM_implicit_const |
+ constants::DW_FORM_flag_present => Some(0),
+
+ constants::DW_FORM_data1
+ | constants::DW_FORM_flag
+ | constants::DW_FORM_strx1
+ | constants::DW_FORM_ref1
+ | constants::DW_FORM_addrx1 => Some(1),
+
+ constants::DW_FORM_data2
+ | constants::DW_FORM_ref2
+ | constants::DW_FORM_addrx2
+ | constants::DW_FORM_strx2 => Some(2),
+
+ constants::DW_FORM_addrx3 | constants::DW_FORM_strx3 => Some(3),
+
+ constants::DW_FORM_data4
+ | constants::DW_FORM_ref_sup4
+ | constants::DW_FORM_ref4
+ | constants::DW_FORM_strx4
+ | constants::DW_FORM_addrx4 => Some(4),
+
+ constants::DW_FORM_data8
+ | constants::DW_FORM_ref8
+ | constants::DW_FORM_ref_sig8
+ | constants::DW_FORM_ref_sup8 => Some(8),
+
+ constants::DW_FORM_data16 => Some(16),
+
+ constants::DW_FORM_sec_offset
+ | constants::DW_FORM_GNU_ref_alt
+ | constants::DW_FORM_strp
+ | constants::DW_FORM_strp_sup
+ | constants::DW_FORM_GNU_strp_alt
+ | constants::DW_FORM_line_strp => Some(encoding.format.word_size()),
+
+ constants::DW_FORM_ref_addr => {
+ // This is an offset, but DWARF version 2 specifies that DW_FORM_ref_addr
+ // has the same size as an address on the target system. This was changed
+ // in DWARF version 3.
+ Some(if encoding.version == 2 {
+ encoding.address_size
+ } else {
+ encoding.format.word_size()
+ })
+ }
+
+ // Variably sized forms.
+ constants::DW_FORM_block |
+ constants::DW_FORM_block1 |
+ constants::DW_FORM_block2 |
+ constants::DW_FORM_block4 |
+ constants::DW_FORM_exprloc |
+ constants::DW_FORM_ref_udata |
+ constants::DW_FORM_string |
+ constants::DW_FORM_sdata |
+ constants::DW_FORM_udata |
+ constants::DW_FORM_indirect |
+
+ // We don't know the size of unknown forms.
+ _ => None,
+ }
+}
+
+#[cfg(test)]
+pub mod tests {
+ use super::*;
+ use crate::constants;
+ use crate::endianity::LittleEndian;
+ use crate::read::{EndianSlice, Error};
+ use crate::test_util::GimliSectionMethods;
+ #[cfg(target_pointer_width = "32")]
+ use core::u32;
+ use test_assembler::Section;
+
+ pub trait AbbrevSectionMethods {
+ fn abbrev(self, code: u64, tag: constants::DwTag, children: constants::DwChildren) -> Self;
+ fn abbrev_null(self) -> Self;
+ fn abbrev_attr(self, name: constants::DwAt, form: constants::DwForm) -> Self;
+ fn abbrev_attr_implicit_const(self, name: constants::DwAt, value: i64) -> Self;
+ fn abbrev_attr_null(self) -> Self;
+ }
+
+ impl AbbrevSectionMethods for Section {
+ fn abbrev(self, code: u64, tag: constants::DwTag, children: constants::DwChildren) -> Self {
+ self.uleb(code).uleb(tag.0.into()).D8(children.0)
+ }
+
+ fn abbrev_null(self) -> Self {
+ self.D8(0)
+ }
+
+ fn abbrev_attr(self, name: constants::DwAt, form: constants::DwForm) -> Self {
+ self.uleb(name.0.into()).uleb(form.0.into())
+ }
+
+ fn abbrev_attr_implicit_const(self, name: constants::DwAt, value: i64) -> Self {
+ self.uleb(name.0.into())
+ .uleb(constants::DW_FORM_implicit_const.0.into())
+ .sleb(value)
+ }
+
+ fn abbrev_attr_null(self) -> Self {
+ self.D8(0).D8(0)
+ }
+ }
+
+ #[test]
+ fn test_debug_abbrev_ok() {
+ let extra_start = [1, 2, 3, 4];
+ let expected_rest = [5, 6, 7, 8];
+ #[rustfmt::skip]
+ let buf = Section::new()
+ .append_bytes(&extra_start)
+ .abbrev(2, constants::DW_TAG_subprogram, constants::DW_CHILDREN_no)
+ .abbrev_attr(constants::DW_AT_name, constants::DW_FORM_string)
+ .abbrev_attr_null()
+ .abbrev(1, constants::DW_TAG_compile_unit, constants::DW_CHILDREN_yes)
+ .abbrev_attr(constants::DW_AT_producer, constants::DW_FORM_strp)
+ .abbrev_attr(constants::DW_AT_language, constants::DW_FORM_data2)
+ .abbrev_attr_null()
+ .abbrev_null()
+ .append_bytes(&expected_rest)
+ .get_contents()
+ .unwrap();
+
+ let abbrev1 = Abbreviation::new(
+ 1,
+ constants::DW_TAG_compile_unit,
+ constants::DW_CHILDREN_yes,
+ vec![
+ AttributeSpecification::new(
+ constants::DW_AT_producer,
+ constants::DW_FORM_strp,
+ None,
+ ),
+ AttributeSpecification::new(
+ constants::DW_AT_language,
+ constants::DW_FORM_data2,
+ None,
+ ),
+ ]
+ .into(),
+ );
+
+ let abbrev2 = Abbreviation::new(
+ 2,
+ constants::DW_TAG_subprogram,
+ constants::DW_CHILDREN_no,
+ vec![AttributeSpecification::new(
+ constants::DW_AT_name,
+ constants::DW_FORM_string,
+ None,
+ )]
+ .into(),
+ );
+
+ let debug_abbrev = DebugAbbrev::new(&buf, LittleEndian);
+ let debug_abbrev_offset = DebugAbbrevOffset(extra_start.len());
+ let abbrevs = debug_abbrev
+ .abbreviations(debug_abbrev_offset)
+ .expect("Should parse abbreviations");
+ assert_eq!(abbrevs.get(1), Some(&abbrev1));
+ assert_eq!(abbrevs.get(2), Some(&abbrev2));
+ }
+
+ #[test]
+ fn test_abbreviations_insert() {
+ fn abbrev(code: u16) -> Abbreviation {
+ Abbreviation::new(
+ code.into(),
+ constants::DwTag(code),
+ constants::DW_CHILDREN_no,
+ vec![].into(),
+ )
+ }
+
+ fn assert_abbrev(abbrevs: &Abbreviations, code: u16) {
+ let abbrev = abbrevs.get(code.into()).unwrap();
+ assert_eq!(abbrev.tag(), constants::DwTag(code));
+ }
+
+ // Sequential insert.
+ let mut abbrevs = Abbreviations::empty();
+ abbrevs.insert(abbrev(1)).unwrap();
+ abbrevs.insert(abbrev(2)).unwrap();
+ assert_eq!(abbrevs.vec.len(), 2);
+ assert!(abbrevs.map.is_empty());
+ assert_abbrev(&abbrevs, 1);
+ assert_abbrev(&abbrevs, 2);
+
+ // Out of order insert.
+ let mut abbrevs = Abbreviations::empty();
+ abbrevs.insert(abbrev(2)).unwrap();
+ abbrevs.insert(abbrev(3)).unwrap();
+ assert!(abbrevs.vec.is_empty());
+ assert_abbrev(&abbrevs, 2);
+ assert_abbrev(&abbrevs, 3);
+
+ // Mixed order insert.
+ let mut abbrevs = Abbreviations::empty();
+ abbrevs.insert(abbrev(1)).unwrap();
+ abbrevs.insert(abbrev(3)).unwrap();
+ abbrevs.insert(abbrev(2)).unwrap();
+ assert_eq!(abbrevs.vec.len(), 2);
+ assert_abbrev(&abbrevs, 1);
+ assert_abbrev(&abbrevs, 2);
+ assert_abbrev(&abbrevs, 3);
+
+ // Duplicate code in vec.
+ let mut abbrevs = Abbreviations::empty();
+ abbrevs.insert(abbrev(1)).unwrap();
+ abbrevs.insert(abbrev(2)).unwrap();
+ assert_eq!(abbrevs.insert(abbrev(1)), Err(()));
+ assert_eq!(abbrevs.insert(abbrev(2)), Err(()));
+
+ // Duplicate code in map when adding to map.
+ let mut abbrevs = Abbreviations::empty();
+ abbrevs.insert(abbrev(2)).unwrap();
+ assert_eq!(abbrevs.insert(abbrev(2)), Err(()));
+
+ // Duplicate code in map when adding to vec.
+ let mut abbrevs = Abbreviations::empty();
+ abbrevs.insert(abbrev(2)).unwrap();
+ abbrevs.insert(abbrev(1)).unwrap();
+ assert_eq!(abbrevs.insert(abbrev(2)), Err(()));
+
+ // 32-bit usize conversions.
+ let mut abbrevs = Abbreviations::empty();
+ abbrevs.insert(abbrev(2)).unwrap();
+ }
+
+ #[test]
+ #[cfg(target_pointer_width = "32")]
+ fn test_abbreviations_insert_32() {
+ fn abbrev(code: u64) -> Abbreviation {
+ Abbreviation::new(
+ code,
+ constants::DwTag(code as u16),
+ constants::DW_CHILDREN_no,
+ vec![].into(),
+ )
+ }
+
+ fn assert_abbrev(abbrevs: &Abbreviations, code: u64) {
+ let abbrev = abbrevs.get(code).unwrap();
+ assert_eq!(abbrev.tag(), constants::DwTag(code as u16));
+ }
+
+ let mut abbrevs = Abbreviations::empty();
+ abbrevs.insert(abbrev(1)).unwrap();
+
+ let wrap_code = (u32::MAX as u64 + 1) + 1;
+ // `get` should not treat the wrapped code as `1`.
+ assert_eq!(abbrevs.get(wrap_code), None);
+ // `insert` should not treat the wrapped code as `1`.
+ abbrevs.insert(abbrev(wrap_code)).unwrap();
+ assert_abbrev(&abbrevs, 1);
+ assert_abbrev(&abbrevs, wrap_code);
+ }
+
+ #[test]
+ fn test_parse_abbreviations_ok() {
+ let expected_rest = [1, 2, 3, 4];
+ #[rustfmt::skip]
+ let buf = Section::new()
+ .abbrev(2, constants::DW_TAG_subprogram, constants::DW_CHILDREN_no)
+ .abbrev_attr(constants::DW_AT_name, constants::DW_FORM_string)
+ .abbrev_attr_null()
+ .abbrev(1, constants::DW_TAG_compile_unit, constants::DW_CHILDREN_yes)
+ .abbrev_attr(constants::DW_AT_producer, constants::DW_FORM_strp)
+ .abbrev_attr(constants::DW_AT_language, constants::DW_FORM_data2)
+ .abbrev_attr_null()
+ .abbrev_null()
+ .append_bytes(&expected_rest)
+ .get_contents()
+ .unwrap();
+ let rest = &mut EndianSlice::new(&*buf, LittleEndian);
+
+ let abbrev1 = Abbreviation::new(
+ 1,
+ constants::DW_TAG_compile_unit,
+ constants::DW_CHILDREN_yes,
+ vec![
+ AttributeSpecification::new(
+ constants::DW_AT_producer,
+ constants::DW_FORM_strp,
+ None,
+ ),
+ AttributeSpecification::new(
+ constants::DW_AT_language,
+ constants::DW_FORM_data2,
+ None,
+ ),
+ ]
+ .into(),
+ );
+
+ let abbrev2 = Abbreviation::new(
+ 2,
+ constants::DW_TAG_subprogram,
+ constants::DW_CHILDREN_no,
+ vec![AttributeSpecification::new(
+ constants::DW_AT_name,
+ constants::DW_FORM_string,
+ None,
+ )]
+ .into(),
+ );
+
+ let abbrevs = Abbreviations::parse(rest).expect("Should parse abbreviations");
+ assert_eq!(abbrevs.get(1), Some(&abbrev1));
+ assert_eq!(abbrevs.get(2), Some(&abbrev2));
+ assert_eq!(*rest, EndianSlice::new(&expected_rest, LittleEndian));
+ }
+
+ #[test]
+ fn test_parse_abbreviations_duplicate() {
+ let expected_rest = [1, 2, 3, 4];
+ #[rustfmt::skip]
+ let buf = Section::new()
+ .abbrev(1, constants::DW_TAG_subprogram, constants::DW_CHILDREN_no)
+ .abbrev_attr(constants::DW_AT_name, constants::DW_FORM_string)
+ .abbrev_attr_null()
+ .abbrev(1, constants::DW_TAG_compile_unit, constants::DW_CHILDREN_yes)
+ .abbrev_attr(constants::DW_AT_producer, constants::DW_FORM_strp)
+ .abbrev_attr(constants::DW_AT_language, constants::DW_FORM_data2)
+ .abbrev_attr_null()
+ .abbrev_null()
+ .append_bytes(&expected_rest)
+ .get_contents()
+ .unwrap();
+ let buf = &mut EndianSlice::new(&*buf, LittleEndian);
+
+ match Abbreviations::parse(buf) {
+ Err(Error::DuplicateAbbreviationCode) => {}
+ otherwise => panic!("Unexpected result: {:?}", otherwise),
+ };
+ }
+
+ #[test]
+ fn test_parse_abbreviation_tag_ok() {
+ let buf = [0x01, 0x02];
+ let rest = &mut EndianSlice::new(&buf, LittleEndian);
+ let tag = Abbreviation::parse_tag(rest).expect("Should parse tag");
+ assert_eq!(tag, constants::DW_TAG_array_type);
+ assert_eq!(*rest, EndianSlice::new(&buf[1..], LittleEndian));
+ }
+
+ #[test]
+ fn test_parse_abbreviation_tag_zero() {
+ let buf = [0x00];
+ let buf = &mut EndianSlice::new(&buf, LittleEndian);
+ match Abbreviation::parse_tag(buf) {
+ Err(Error::AbbreviationTagZero) => {}
+ otherwise => panic!("Unexpected result: {:?}", otherwise),
+ };
+ }
+
+ #[test]
+ fn test_parse_abbreviation_has_children() {
+ let buf = [0x00, 0x01, 0x02];
+ let rest = &mut EndianSlice::new(&buf, LittleEndian);
+ let val = Abbreviation::parse_has_children(rest).expect("Should parse children");
+ assert_eq!(val, constants::DW_CHILDREN_no);
+ let val = Abbreviation::parse_has_children(rest).expect("Should parse children");
+ assert_eq!(val, constants::DW_CHILDREN_yes);
+ match Abbreviation::parse_has_children(rest) {
+ Err(Error::BadHasChildren) => {}
+ otherwise => panic!("Unexpected result: {:?}", otherwise),
+ };
+ }
+
+ #[test]
+ fn test_parse_abbreviation_ok() {
+ let expected_rest = [0x01, 0x02, 0x03, 0x04];
+ let buf = Section::new()
+ .abbrev(1, constants::DW_TAG_subprogram, constants::DW_CHILDREN_no)
+ .abbrev_attr(constants::DW_AT_name, constants::DW_FORM_string)
+ .abbrev_attr_null()
+ .append_bytes(&expected_rest)
+ .get_contents()
+ .unwrap();
+ let rest = &mut EndianSlice::new(&*buf, LittleEndian);
+
+ let expect = Some(Abbreviation::new(
+ 1,
+ constants::DW_TAG_subprogram,
+ constants::DW_CHILDREN_no,
+ vec![AttributeSpecification::new(
+ constants::DW_AT_name,
+ constants::DW_FORM_string,
+ None,
+ )]
+ .into(),
+ ));
+
+ let abbrev = Abbreviation::parse(rest).expect("Should parse abbreviation");
+ assert_eq!(abbrev, expect);
+ assert_eq!(*rest, EndianSlice::new(&expected_rest, LittleEndian));
+ }
+
+ #[test]
+ fn test_parse_abbreviation_implicit_const_ok() {
+ let expected_rest = [0x01, 0x02, 0x03, 0x04];
+ let buf = Section::new()
+ .abbrev(1, constants::DW_TAG_subprogram, constants::DW_CHILDREN_no)
+ .abbrev_attr_implicit_const(constants::DW_AT_name, -42)
+ .abbrev_attr_null()
+ .append_bytes(&expected_rest)
+ .get_contents()
+ .unwrap();
+ let rest = &mut EndianSlice::new(&*buf, LittleEndian);
+
+ let expect = Some(Abbreviation::new(
+ 1,
+ constants::DW_TAG_subprogram,
+ constants::DW_CHILDREN_no,
+ vec![AttributeSpecification::new(
+ constants::DW_AT_name,
+ constants::DW_FORM_implicit_const,
+ Some(-42),
+ )]
+ .into(),
+ ));
+
+ let abbrev = Abbreviation::parse(rest).expect("Should parse abbreviation");
+ assert_eq!(abbrev, expect);
+ assert_eq!(*rest, EndianSlice::new(&expected_rest, LittleEndian));
+ }
+
+ #[test]
+ fn test_parse_abbreviation_implicit_const_no_const() {
+ let buf = Section::new()
+ .abbrev(1, constants::DW_TAG_subprogram, constants::DW_CHILDREN_no)
+ .abbrev_attr(constants::DW_AT_name, constants::DW_FORM_implicit_const)
+ .get_contents()
+ .unwrap();
+ let buf = &mut EndianSlice::new(&*buf, LittleEndian);
+
+ match Abbreviation::parse(buf) {
+ Err(Error::UnexpectedEof(_)) => {}
+ otherwise => panic!("Unexpected result: {:?}", otherwise),
+ }
+ }
+
+ #[test]
+ fn test_parse_null_abbreviation_ok() {
+ let expected_rest = [0x01, 0x02, 0x03, 0x04];
+ let buf = Section::new()
+ .abbrev_null()
+ .append_bytes(&expected_rest)
+ .get_contents()
+ .unwrap();
+ let rest = &mut EndianSlice::new(&*buf, LittleEndian);
+
+ let abbrev = Abbreviation::parse(rest).expect("Should parse null abbreviation");
+ assert!(abbrev.is_none());
+ assert_eq!(*rest, EndianSlice::new(&expected_rest, LittleEndian));
+ }
+
+ #[test]
+ fn test_parse_attribute_form_ok() {
+ let buf = [0x01, 0x02];
+ let rest = &mut EndianSlice::new(&buf, LittleEndian);
+ let tag = AttributeSpecification::parse_form(rest).expect("Should parse form");
+ assert_eq!(tag, constants::DW_FORM_addr);
+ assert_eq!(*rest, EndianSlice::new(&buf[1..], LittleEndian));
+ }
+
+ #[test]
+ fn test_parse_attribute_form_zero() {
+ let buf = [0x00];
+ let buf = &mut EndianSlice::new(&buf, LittleEndian);
+ match AttributeSpecification::parse_form(buf) {
+ Err(Error::AttributeFormZero) => {}
+ otherwise => panic!("Unexpected result: {:?}", otherwise),
+ };
+ }
+
+ #[test]
+ fn test_parse_null_attribute_specification_ok() {
+ let buf = [0x00, 0x00, 0x01];
+ let rest = &mut EndianSlice::new(&buf, LittleEndian);
+ let attr =
+ AttributeSpecification::parse(rest).expect("Should parse null attribute specification");
+ assert!(attr.is_none());
+ assert_eq!(*rest, EndianSlice::new(&buf[2..], LittleEndian));
+ }
+
+ #[test]
+ fn test_parse_attribute_specifications_name_zero() {
+ let buf = [0x00, 0x01, 0x00, 0x00];
+ let buf = &mut EndianSlice::new(&buf, LittleEndian);
+ match AttributeSpecification::parse(buf) {
+ Err(Error::ExpectedZero) => {}
+ otherwise => panic!("Unexpected result: {:?}", otherwise),
+ };
+ }
+
+ #[test]
+ fn test_parse_attribute_specifications_form_zero() {
+ let buf = [0x01, 0x00, 0x00, 0x00];
+ let buf = &mut EndianSlice::new(&buf, LittleEndian);
+ match AttributeSpecification::parse(buf) {
+ Err(Error::AttributeFormZero) => {}
+ otherwise => panic!("Unexpected result: {:?}", otherwise),
+ };
+ }
+
+ #[test]
+ fn test_get_abbrev_zero() {
+ let mut abbrevs = Abbreviations::empty();
+ abbrevs
+ .insert(Abbreviation::new(
+ 1,
+ constants::DwTag(1),
+ constants::DW_CHILDREN_no,
+ vec![].into(),
+ ))
+ .unwrap();
+ assert!(abbrevs.get(0).is_none());
+ }
+}
diff --git a/vendor/gimli-0.26.2/src/read/addr.rs b/vendor/gimli-0.26.2/src/read/addr.rs
new file mode 100644
index 000000000..593f9fe3c
--- /dev/null
+++ b/vendor/gimli-0.26.2/src/read/addr.rs
@@ -0,0 +1,128 @@
+use crate::common::{DebugAddrBase, DebugAddrIndex, SectionId};
+use crate::read::{Reader, ReaderOffset, Result, Section};
+
+/// The raw contents of the `.debug_addr` section.
+#[derive(Debug, Default, Clone, Copy)]
+pub struct DebugAddr<R> {
+ section: R,
+}
+
+impl<R: Reader> DebugAddr<R> {
+ // TODO: add an iterator over the sets of addresses in the section.
+ // This is not needed for common usage of the section though.
+
+ /// Returns the address at the given `base` and `index`.
+ ///
+ /// A set of addresses in the `.debug_addr` section consists of a header
+ /// followed by a series of addresses.
+ ///
+ /// The `base` must be the `DW_AT_addr_base` value from the compilation unit DIE.
+ /// This is an offset that points to the first address following the header.
+ ///
+ /// The `index` is the value of a `DW_FORM_addrx` attribute.
+ ///
+ /// The `address_size` must be the size of the address for the compilation unit.
+ /// This value must also match the header. However, note that we do not parse the
+ /// header to validate this, since locating the header is unreliable, and the GNU
+ /// extensions do not emit it.
+ pub fn get_address(
+ &self,
+ address_size: u8,
+ base: DebugAddrBase<R::Offset>,
+ index: DebugAddrIndex<R::Offset>,
+ ) -> Result<u64> {
+ let input = &mut self.section.clone();
+ input.skip(base.0)?;
+ input.skip(R::Offset::from_u64(
+ index.0.into_u64() * u64::from(address_size),
+ )?)?;
+ input.read_address(address_size)
+ }
+}
+
+impl<T> DebugAddr<T> {
+ /// Create a `DebugAddr` section that references the data in `self`.
+ ///
+ /// This is useful when `R` implements `Reader` but `T` does not.
+ ///
+ /// ## Example Usage
+ ///
+ /// ```rust,no_run
+ /// # let load_section = || unimplemented!();
+ /// // Read the DWARF section into a `Vec` with whatever object loader you're using.
+ /// let owned_section: gimli::DebugAddr<Vec<u8>> = load_section();
+ /// // Create a reference to the DWARF section.
+ /// let section = owned_section.borrow(|section| {
+ /// gimli::EndianSlice::new(&section, gimli::LittleEndian)
+ /// });
+ /// ```
+ pub fn borrow<'a, F, R>(&'a self, mut borrow: F) -> DebugAddr<R>
+ where
+ F: FnMut(&'a T) -> R,
+ {
+ borrow(&self.section).into()
+ }
+}
+
+impl<R> Section<R> for DebugAddr<R> {
+ fn id() -> SectionId {
+ SectionId::DebugAddr
+ }
+
+ fn reader(&self) -> &R {
+ &self.section
+ }
+}
+
+impl<R> From<R> for DebugAddr<R> {
+ fn from(section: R) -> Self {
+ DebugAddr { section }
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+ use crate::read::EndianSlice;
+ use crate::test_util::GimliSectionMethods;
+ use crate::{Format, LittleEndian};
+ use test_assembler::{Endian, Label, LabelMaker, Section};
+
+ #[test]
+ fn test_get_address() {
+ for format in vec![Format::Dwarf32, Format::Dwarf64] {
+ for address_size in vec![4, 8] {
+ let zero = Label::new();
+ let length = Label::new();
+ let start = Label::new();
+ let first = Label::new();
+ let end = Label::new();
+ let mut section = Section::with_endian(Endian::Little)
+ .mark(&zero)
+ .initial_length(format, &length, &start)
+ .D16(5)
+ .D8(address_size)
+ .D8(0)
+ .mark(&first);
+ for i in 0..20 {
+ section = section.word(address_size, 1000 + i);
+ }
+ section = section.mark(&end);
+ length.set_const((&end - &start) as u64);
+
+ let section = section.get_contents().unwrap();
+ let debug_addr = DebugAddr::from(EndianSlice::new(&section, LittleEndian));
+ let base = DebugAddrBase((&first - &zero) as usize);
+
+ assert_eq!(
+ debug_addr.get_address(address_size, base, DebugAddrIndex(0)),
+ Ok(1000)
+ );
+ assert_eq!(
+ debug_addr.get_address(address_size, base, DebugAddrIndex(19)),
+ Ok(1019)
+ );
+ }
+ }
+ }
+}
diff --git a/vendor/gimli-0.26.2/src/read/aranges.rs b/vendor/gimli-0.26.2/src/read/aranges.rs
new file mode 100644
index 000000000..83159b69b
--- /dev/null
+++ b/vendor/gimli-0.26.2/src/read/aranges.rs
@@ -0,0 +1,660 @@
+use crate::common::{DebugArangesOffset, DebugInfoOffset, Encoding, SectionId};
+use crate::endianity::Endianity;
+use crate::read::{EndianSlice, Error, Range, Reader, ReaderOffset, Result, Section};
+
+/// The `DebugAranges` struct represents the DWARF address range information
+/// found in the `.debug_aranges` section.
+#[derive(Debug, Default, Clone, Copy)]
+pub struct DebugAranges<R> {
+ section: R,
+}
+
+impl<'input, Endian> DebugAranges<EndianSlice<'input, Endian>>
+where
+ Endian: Endianity,
+{
+ /// Construct a new `DebugAranges` instance from the data in the `.debug_aranges`
+ /// section.
+ ///
+ /// It is the caller's responsibility to read the `.debug_aranges` section and
+ /// present it as a `&[u8]` slice. That means using some ELF loader on
+ /// Linux, a Mach-O loader on macOS, etc.
+ ///
+ /// ```
+ /// use gimli::{DebugAranges, LittleEndian};
+ ///
+ /// # let buf = [];
+ /// # let read_debug_aranges_section = || &buf;
+ /// let debug_aranges =
+ /// DebugAranges::new(read_debug_aranges_section(), LittleEndian);
+ /// ```
+ pub fn new(section: &'input [u8], endian: Endian) -> Self {
+ DebugAranges {
+ section: EndianSlice::new(section, endian),
+ }
+ }
+}
+
+impl<R: Reader> DebugAranges<R> {
+ /// Iterate the sets of entries in the `.debug_aranges` section.
+ ///
+ /// Each set of entries belongs to a single unit.
+ pub fn headers(&self) -> ArangeHeaderIter<R> {
+ ArangeHeaderIter {
+ input: self.section.clone(),
+ offset: DebugArangesOffset(R::Offset::from_u8(0)),
+ }
+ }
+
+ /// Get the header at the given offset.
+ pub fn header(&self, offset: DebugArangesOffset<R::Offset>) -> Result<ArangeHeader<R>> {
+ let mut input = self.section.clone();
+ input.skip(offset.0)?;
+ ArangeHeader::parse(&mut input, offset)
+ }
+}
+
+impl<T> DebugAranges<T> {
+ /// Create a `DebugAranges` section that references the data in `self`.
+ ///
+ /// This is useful when `R` implements `Reader` but `T` does not.
+ ///
+ /// ## Example Usage
+ ///
+ /// ```rust,no_run
+ /// # let load_section = || unimplemented!();
+ /// // Read the DWARF section into a `Vec` with whatever object loader you're using.
+ /// let owned_section: gimli::DebugAranges<Vec<u8>> = load_section();
+ /// // Create a reference to the DWARF section.
+ /// let section = owned_section.borrow(|section| {
+ /// gimli::EndianSlice::new(&section, gimli::LittleEndian)
+ /// });
+ /// ```
+ pub fn borrow<'a, F, R>(&'a self, mut borrow: F) -> DebugAranges<R>
+ where
+ F: FnMut(&'a T) -> R,
+ {
+ borrow(&self.section).into()
+ }
+}
+
+impl<R> Section<R> for DebugAranges<R> {
+ fn id() -> SectionId {
+ SectionId::DebugAranges
+ }
+
+ fn reader(&self) -> &R {
+ &self.section
+ }
+}
+
+impl<R> From<R> for DebugAranges<R> {
+ fn from(section: R) -> Self {
+ DebugAranges { section }
+ }
+}
+
+/// An iterator over the headers of a `.debug_aranges` section.
+#[derive(Clone, Debug)]
+pub struct ArangeHeaderIter<R: Reader> {
+ input: R,
+ offset: DebugArangesOffset<R::Offset>,
+}
+
+impl<R: Reader> ArangeHeaderIter<R> {
+ /// Advance the iterator to the next header.
+ pub fn next(&mut self) -> Result<Option<ArangeHeader<R>>> {
+ if self.input.is_empty() {
+ return Ok(None);
+ }
+
+ let len = self.input.len();
+ match ArangeHeader::parse(&mut self.input, self.offset) {
+ Ok(header) => {
+ self.offset.0 += len - self.input.len();
+ Ok(Some(header))
+ }
+ Err(e) => {
+ self.input.empty();
+ Err(e)
+ }
+ }
+ }
+}
+
+#[cfg(feature = "fallible-iterator")]
+impl<R: Reader> fallible_iterator::FallibleIterator for ArangeHeaderIter<R> {
+ type Item = ArangeHeader<R>;
+ type Error = Error;
+
+ fn next(&mut self) -> ::core::result::Result<Option<Self::Item>, Self::Error> {
+ ArangeHeaderIter::next(self)
+ }
+}
+
+/// A header for a set of entries in the `.debug_arange` section.
+///
+/// These entries all belong to a single unit.
+#[derive(Debug, Clone, PartialEq, Eq)]
+pub struct ArangeHeader<R, Offset = <R as Reader>::Offset>
+where
+ R: Reader<Offset = Offset>,
+ Offset: ReaderOffset,
+{
+ offset: DebugArangesOffset<Offset>,
+ encoding: Encoding,
+ length: Offset,
+ debug_info_offset: DebugInfoOffset<Offset>,
+ segment_size: u8,
+ entries: R,
+}
+
+impl<R, Offset> ArangeHeader<R, Offset>
+where
+ R: Reader<Offset = Offset>,
+ Offset: ReaderOffset,
+{
+ fn parse(input: &mut R, offset: DebugArangesOffset<Offset>) -> Result<Self> {
+ let (length, format) = input.read_initial_length()?;
+ let mut rest = input.split(length)?;
+
+ // Check the version. The DWARF 5 spec says that this is always 2, but version 3
+ // has been observed in the wild, potentially due to a bug; see
+ // https://github.com/gimli-rs/gimli/issues/559 for more information.
+ // lldb allows versions 2 through 5, possibly by mistake.
+ let version = rest.read_u16()?;
+ if version != 2 && version != 3 {
+ return Err(Error::UnknownVersion(u64::from(version)));
+ }
+
+ let debug_info_offset = rest.read_offset(format).map(DebugInfoOffset)?;
+ let address_size = rest.read_u8()?;
+ let segment_size = rest.read_u8()?;
+
+ // unit_length + version + offset + address_size + segment_size
+ let header_length = format.initial_length_size() + 2 + format.word_size() + 1 + 1;
+
+ // The first tuple following the header in each set begins at an offset that is
+ // a multiple of the size of a single tuple (that is, the size of a segment selector
+ // plus twice the size of an address).
+ let tuple_length = address_size
+ .checked_mul(2)
+ .and_then(|x| x.checked_add(segment_size))
+ .ok_or(Error::InvalidAddressRange)?;
+ if tuple_length == 0 {
+ return Err(Error::InvalidAddressRange)?;
+ }
+ let padding = if header_length % tuple_length == 0 {
+ 0
+ } else {
+ tuple_length - header_length % tuple_length
+ };
+ rest.skip(R::Offset::from_u8(padding))?;
+
+ let encoding = Encoding {
+ format,
+ version,
+ address_size,
+ // TODO: segment_size
+ };
+ Ok(ArangeHeader {
+ offset,
+ encoding,
+ length,
+ debug_info_offset,
+ segment_size,
+ entries: rest,
+ })
+ }
+
+ /// Return the offset of this header within the `.debug_aranges` section.
+ #[inline]
+ pub fn offset(&self) -> DebugArangesOffset<Offset> {
+ self.offset
+ }
+
+ /// Return the length of this set of entries, including the header.
+ #[inline]
+ pub fn length(&self) -> Offset {
+ self.length
+ }
+
+ /// Return the encoding parameters for this set of entries.
+ #[inline]
+ pub fn encoding(&self) -> Encoding {
+ self.encoding
+ }
+
+ /// Return the segment size for this set of entries.
+ #[inline]
+ pub fn segment_size(&self) -> u8 {
+ self.segment_size
+ }
+
+ /// Return the offset into the .debug_info section for this set of arange entries.
+ #[inline]
+ pub fn debug_info_offset(&self) -> DebugInfoOffset<Offset> {
+ self.debug_info_offset
+ }
+
+ /// Return the arange entries in this set.
+ #[inline]
+ pub fn entries(&self) -> ArangeEntryIter<R> {
+ ArangeEntryIter {
+ input: self.entries.clone(),
+ encoding: self.encoding,
+ segment_size: self.segment_size,
+ }
+ }
+}
+
+/// An iterator over the aranges from a `.debug_aranges` section.
+///
+/// Can be [used with
+/// `FallibleIterator`](./index.html#using-with-fallibleiterator).
+#[derive(Debug, Clone)]
+pub struct ArangeEntryIter<R: Reader> {
+ input: R,
+ encoding: Encoding,
+ segment_size: u8,
+}
+
+impl<R: Reader> ArangeEntryIter<R> {
+ /// Advance the iterator and return the next arange.
+ ///
+ /// Returns the newly parsed arange as `Ok(Some(arange))`. Returns `Ok(None)`
+ /// when iteration is complete and all aranges have already been parsed and
+ /// yielded. If an error occurs while parsing the next arange, then this error
+ /// is returned as `Err(e)`, and all subsequent calls return `Ok(None)`.
+ pub fn next(&mut self) -> Result<Option<ArangeEntry>> {
+ if self.input.is_empty() {
+ return Ok(None);
+ }
+
+ match ArangeEntry::parse(&mut self.input, self.encoding, self.segment_size) {
+ Ok(Some(entry)) => Ok(Some(entry)),
+ Ok(None) => {
+ self.input.empty();
+ Ok(None)
+ }
+ Err(e) => {
+ self.input.empty();
+ Err(e)
+ }
+ }
+ }
+}
+
+#[cfg(feature = "fallible-iterator")]
+impl<R: Reader> fallible_iterator::FallibleIterator for ArangeEntryIter<R> {
+ type Item = ArangeEntry;
+ type Error = Error;
+
+ fn next(&mut self) -> ::core::result::Result<Option<Self::Item>, Self::Error> {
+ ArangeEntryIter::next(self)
+ }
+}
+
+/// A single parsed arange.
+#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
+pub struct ArangeEntry {
+ segment: Option<u64>,
+ address: u64,
+ length: u64,
+}
+
+impl ArangeEntry {
+ /// Parse a single arange. Return `None` for the null arange, `Some` for an actual arange.
+ fn parse<R: Reader>(
+ input: &mut R,
+ encoding: Encoding,
+ segment_size: u8,
+ ) -> Result<Option<Self>> {
+ let address_size = encoding.address_size;
+
+ let tuple_length = R::Offset::from_u8(2 * address_size + segment_size);
+ if tuple_length > input.len() {
+ input.empty();
+ return Ok(None);
+ }
+
+ let segment = if segment_size != 0 {
+ input.read_address(segment_size)?
+ } else {
+ 0
+ };
+ let address = input.read_address(address_size)?;
+ let length = input.read_address(address_size)?;
+
+ match (segment, address, length) {
+ // This is meant to be a null terminator, but in practice it can occur
+ // before the end, possibly due to a linker omitting a function and
+ // leaving an unrelocated entry.
+ (0, 0, 0) => Self::parse(input, encoding, segment_size),
+ _ => Ok(Some(ArangeEntry {
+ segment: if segment_size != 0 {
+ Some(segment)
+ } else {
+ None
+ },
+ address,
+ length,
+ })),
+ }
+ }
+
+ /// Return the segment selector of this arange.
+ #[inline]
+ pub fn segment(&self) -> Option<u64> {
+ self.segment
+ }
+
+ /// Return the beginning address of this arange.
+ #[inline]
+ pub fn address(&self) -> u64 {
+ self.address
+ }
+
+ /// Return the length of this arange.
+ #[inline]
+ pub fn length(&self) -> u64 {
+ self.length
+ }
+
+ /// Return the range.
+ #[inline]
+ pub fn range(&self) -> Range {
+ Range {
+ begin: self.address,
+ end: self.address.wrapping_add(self.length),
+ }
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+ use crate::common::{DebugInfoOffset, Format};
+ use crate::endianity::LittleEndian;
+ use crate::read::EndianSlice;
+
+ #[test]
+ fn test_iterate_headers() {
+ #[rustfmt::skip]
+ let buf = [
+ // 32-bit length = 28.
+ 0x1c, 0x00, 0x00, 0x00,
+ // Version.
+ 0x02, 0x00,
+ // Offset.
+ 0x01, 0x02, 0x03, 0x04,
+ // Address size.
+ 0x04,
+ // Segment size.
+ 0x00,
+ // Dummy padding and arange tuples.
+ 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+
+ // 32-bit length = 36.
+ 0x24, 0x00, 0x00, 0x00,
+ // Version.
+ 0x02, 0x00,
+ // Offset.
+ 0x11, 0x12, 0x13, 0x14,
+ // Address size.
+ 0x04,
+ // Segment size.
+ 0x00,
+ // Dummy padding and arange tuples.
+ 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ ];
+
+ let debug_aranges = DebugAranges::new(&buf, LittleEndian);
+ let mut headers = debug_aranges.headers();
+
+ let header = headers
+ .next()
+ .expect("should parse header ok")
+ .expect("should have a header");
+ assert_eq!(header.offset(), DebugArangesOffset(0));
+ assert_eq!(header.debug_info_offset(), DebugInfoOffset(0x0403_0201));
+
+ let header = headers
+ .next()
+ .expect("should parse header ok")
+ .expect("should have a header");
+ assert_eq!(header.offset(), DebugArangesOffset(0x20));
+ assert_eq!(header.debug_info_offset(), DebugInfoOffset(0x1413_1211));
+ }
+
+ #[test]
+ fn test_parse_header_ok() {
+ #[rustfmt::skip]
+ let buf = [
+ // 32-bit length = 32.
+ 0x20, 0x00, 0x00, 0x00,
+ // Version.
+ 0x02, 0x00,
+ // Offset.
+ 0x01, 0x02, 0x03, 0x04,
+ // Address size.
+ 0x08,
+ // Segment size.
+ 0x04,
+ // Length to here = 12, tuple length = 20.
+ // Padding to tuple length multiple = 4.
+ 0x10, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+
+ // Dummy arange tuple data.
+ 0x20, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+
+ // Dummy next arange.
+ 0x30, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+ ];
+
+ let rest = &mut EndianSlice::new(&buf, LittleEndian);
+
+ let header =
+ ArangeHeader::parse(rest, DebugArangesOffset(0x10)).expect("should parse header ok");
+
+ assert_eq!(
+ *rest,
+ EndianSlice::new(&buf[buf.len() - 16..], LittleEndian)
+ );
+ assert_eq!(
+ header,
+ ArangeHeader {
+ offset: DebugArangesOffset(0x10),
+ encoding: Encoding {
+ format: Format::Dwarf32,
+ version: 2,
+ address_size: 8,
+ },
+ length: 0x20,
+ debug_info_offset: DebugInfoOffset(0x0403_0201),
+ segment_size: 4,
+ entries: EndianSlice::new(&buf[buf.len() - 32..buf.len() - 16], LittleEndian),
+ }
+ );
+ }
+
+ #[test]
+ fn test_parse_header_overflow_error() {
+ #[rustfmt::skip]
+ let buf = [
+ // 32-bit length = 32.
+ 0x20, 0x00, 0x00, 0x00,
+ // Version.
+ 0x02, 0x00,
+ // Offset.
+ 0x01, 0x02, 0x03, 0x04,
+ // Address size.
+ 0xff,
+ // Segment size.
+ 0xff,
+ // Length to here = 12, tuple length = 20.
+ // Padding to tuple length multiple = 4.
+ 0x10, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+
+ // Dummy arange tuple data.
+ 0x20, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+
+ // Dummy next arange.
+ 0x30, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+ ];
+
+ let rest = &mut EndianSlice::new(&buf, LittleEndian);
+
+ let error = ArangeHeader::parse(rest, DebugArangesOffset(0x10))
+ .expect_err("should fail to parse header");
+ assert_eq!(error, Error::InvalidAddressRange);
+ }
+
+ #[test]
+ fn test_parse_header_div_by_zero_error() {
+ #[rustfmt::skip]
+ let buf = [
+ // 32-bit length = 32.
+ 0x20, 0x00, 0x00, 0x00,
+ // Version.
+ 0x02, 0x00,
+ // Offset.
+ 0x01, 0x02, 0x03, 0x04,
+ // Address size = 0. Could cause a division by zero if we aren't
+ // careful.
+ 0x00,
+ // Segment size.
+ 0x00,
+ // Length to here = 12, tuple length = 20.
+ // Padding to tuple length multiple = 4.
+ 0x10, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+
+ // Dummy arange tuple data.
+ 0x20, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+
+ // Dummy next arange.
+ 0x30, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+ ];
+
+ let rest = &mut EndianSlice::new(&buf, LittleEndian);
+
+ let error = ArangeHeader::parse(rest, DebugArangesOffset(0x10))
+ .expect_err("should fail to parse header");
+ assert_eq!(error, Error::InvalidAddressRange);
+ }
+
+ #[test]
+ fn test_parse_entry_ok() {
+ let encoding = Encoding {
+ format: Format::Dwarf32,
+ version: 2,
+ address_size: 4,
+ };
+ let segment_size = 0;
+ let buf = [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09];
+ let rest = &mut EndianSlice::new(&buf, LittleEndian);
+ let entry =
+ ArangeEntry::parse(rest, encoding, segment_size).expect("should parse entry ok");
+ assert_eq!(*rest, EndianSlice::new(&buf[buf.len() - 1..], LittleEndian));
+ assert_eq!(
+ entry,
+ Some(ArangeEntry {
+ segment: None,
+ address: 0x0403_0201,
+ length: 0x0807_0605,
+ })
+ );
+ }
+
+ #[test]
+ fn test_parse_entry_segment() {
+ let encoding = Encoding {
+ format: Format::Dwarf32,
+ version: 2,
+ address_size: 4,
+ };
+ let segment_size = 8;
+ #[rustfmt::skip]
+ let buf = [
+ // Segment.
+ 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
+ // Address.
+ 0x01, 0x02, 0x03, 0x04,
+ // Length.
+ 0x05, 0x06, 0x07, 0x08,
+ // Next tuple.
+ 0x09
+ ];
+ let rest = &mut EndianSlice::new(&buf, LittleEndian);
+ let entry =
+ ArangeEntry::parse(rest, encoding, segment_size).expect("should parse entry ok");
+ assert_eq!(*rest, EndianSlice::new(&buf[buf.len() - 1..], LittleEndian));
+ assert_eq!(
+ entry,
+ Some(ArangeEntry {
+ segment: Some(0x1817_1615_1413_1211),
+ address: 0x0403_0201,
+ length: 0x0807_0605,
+ })
+ );
+ }
+
+ #[test]
+ fn test_parse_entry_zero() {
+ let encoding = Encoding {
+ format: Format::Dwarf32,
+ version: 2,
+ address_size: 4,
+ };
+ let segment_size = 0;
+ #[rustfmt::skip]
+ let buf = [
+ // Zero tuple.
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ // Address.
+ 0x01, 0x02, 0x03, 0x04,
+ // Length.
+ 0x05, 0x06, 0x07, 0x08,
+ // Next tuple.
+ 0x09
+ ];
+ let rest = &mut EndianSlice::new(&buf, LittleEndian);
+ let entry =
+ ArangeEntry::parse(rest, encoding, segment_size).expect("should parse entry ok");
+ assert_eq!(*rest, EndianSlice::new(&buf[buf.len() - 1..], LittleEndian));
+ assert_eq!(
+ entry,
+ Some(ArangeEntry {
+ segment: None,
+ address: 0x0403_0201,
+ length: 0x0807_0605,
+ })
+ );
+ }
+}
diff --git a/vendor/gimli-0.26.2/src/read/cfi.rs b/vendor/gimli-0.26.2/src/read/cfi.rs
new file mode 100644
index 000000000..2e5167349
--- /dev/null
+++ b/vendor/gimli-0.26.2/src/read/cfi.rs
@@ -0,0 +1,7585 @@
+#[cfg(feature = "read")]
+use alloc::vec::Vec;
+
+use core::cmp::{Ord, Ordering};
+use core::fmt::{self, Debug};
+use core::iter::FromIterator;
+use core::mem;
+use core::num::Wrapping;
+
+use super::util::{ArrayLike, ArrayVec};
+use crate::common::{DebugFrameOffset, EhFrameOffset, Encoding, Format, Register, SectionId};
+use crate::constants::{self, DwEhPe};
+use crate::endianity::Endianity;
+use crate::read::{
+ EndianSlice, Error, Expression, Reader, ReaderOffset, Result, Section, StoreOnHeap,
+};
+
+/// `DebugFrame` contains the `.debug_frame` section's frame unwinding
+/// information required to unwind to and recover registers from older frames on
+/// the stack. For example, this is useful for a debugger that wants to print
+/// locals in a backtrace.
+///
+/// Most interesting methods are defined in the
+/// [`UnwindSection`](trait.UnwindSection.html) trait.
+///
+/// ### Differences between `.debug_frame` and `.eh_frame`
+///
+/// While the `.debug_frame` section's information has a lot of overlap with the
+/// `.eh_frame` section's information, the `.eh_frame` information tends to only
+/// encode the subset of information needed for exception handling. Often, only
+/// one of `.eh_frame` or `.debug_frame` will be present in an object file.
+#[derive(Clone, Copy, Debug, PartialEq, Eq)]
+pub struct DebugFrame<R: Reader> {
+ section: R,
+ address_size: u8,
+ segment_size: u8,
+}
+
+impl<R: Reader> DebugFrame<R> {
+ /// Set the size of a target address in bytes.
+ ///
+ /// This defaults to the native word size.
+ /// This is only used if the CIE version is less than 4.
+ pub fn set_address_size(&mut self, address_size: u8) {
+ self.address_size = address_size
+ }
+
+ /// Set the size of a segment selector in bytes.
+ ///
+ /// This defaults to 0.
+ /// This is only used if the CIE version is less than 4.
+ pub fn set_segment_size(&mut self, segment_size: u8) {
+ self.segment_size = segment_size
+ }
+}
+
+impl<'input, Endian> DebugFrame<EndianSlice<'input, Endian>>
+where
+ Endian: Endianity,
+{
+ /// Construct a new `DebugFrame` instance from the data in the
+ /// `.debug_frame` section.
+ ///
+ /// It is the caller's responsibility to read the section and present it as
+ /// a `&[u8]` slice. That means using some ELF loader on Linux, a Mach-O
+ /// loader on macOS, etc.
+ ///
+ /// ```
+ /// use gimli::{DebugFrame, NativeEndian};
+ ///
+ /// // Use with `.debug_frame`
+ /// # let buf = [0x00, 0x01, 0x02, 0x03];
+ /// # let read_debug_frame_section_somehow = || &buf;
+ /// let debug_frame = DebugFrame::new(read_debug_frame_section_somehow(), NativeEndian);
+ /// ```
+ pub fn new(section: &'input [u8], endian: Endian) -> Self {
+ Self::from(EndianSlice::new(section, endian))
+ }
+}
+
+impl<R: Reader> Section<R> for DebugFrame<R> {
+ fn id() -> SectionId {
+ SectionId::DebugFrame
+ }
+
+ fn reader(&self) -> &R {
+ &self.section
+ }
+}
+
+impl<R: Reader> From<R> for DebugFrame<R> {
+ fn from(section: R) -> Self {
+ // Default to no segments and native word size.
+ DebugFrame {
+ section,
+ address_size: mem::size_of::<usize>() as u8,
+ segment_size: 0,
+ }
+ }
+}
+
+/// `EhFrameHdr` contains the information about the `.eh_frame_hdr` section.
+///
+/// A pointer to the start of the `.eh_frame` data, and optionally, a binary
+/// search table of pointers to the `.eh_frame` records that are found in this section.
+#[derive(Clone, Copy, Debug, PartialEq, Eq)]
+pub struct EhFrameHdr<R: Reader>(R);
+
+/// `ParsedEhFrameHdr` contains the parsed information from the `.eh_frame_hdr` section.
+#[derive(Clone, Debug)]
+pub struct ParsedEhFrameHdr<R: Reader> {
+ address_size: u8,
+ section: R,
+
+ eh_frame_ptr: Pointer,
+ fde_count: u64,
+ table_enc: DwEhPe,
+ table: R,
+}
+
+impl<'input, Endian> EhFrameHdr<EndianSlice<'input, Endian>>
+where
+ Endian: Endianity,
+{
+ /// Constructs a new `EhFrameHdr` instance from the data in the `.eh_frame_hdr` section.
+ pub fn new(section: &'input [u8], endian: Endian) -> Self {
+ Self::from(EndianSlice::new(section, endian))
+ }
+}
+
+impl<R: Reader> EhFrameHdr<R> {
+ /// Parses this `EhFrameHdr` to a `ParsedEhFrameHdr`.
+ pub fn parse(&self, bases: &BaseAddresses, address_size: u8) -> Result<ParsedEhFrameHdr<R>> {
+ let mut reader = self.0.clone();
+ let version = reader.read_u8()?;
+ if version != 1 {
+ return Err(Error::UnknownVersion(u64::from(version)));
+ }
+
+ let eh_frame_ptr_enc = parse_pointer_encoding(&mut reader)?;
+ let fde_count_enc = parse_pointer_encoding(&mut reader)?;
+ let table_enc = parse_pointer_encoding(&mut reader)?;
+
+ let parameters = PointerEncodingParameters {
+ bases: &bases.eh_frame_hdr,
+ func_base: None,
+ address_size,
+ section: &self.0,
+ };
+
+ // Omitting this pointer is not valid (defeats the purpose of .eh_frame_hdr entirely)
+ if eh_frame_ptr_enc == constants::DW_EH_PE_omit {
+ return Err(Error::CannotParseOmitPointerEncoding);
+ }
+ let eh_frame_ptr = parse_encoded_pointer(eh_frame_ptr_enc, &parameters, &mut reader)?;
+
+ let fde_count;
+ if fde_count_enc == constants::DW_EH_PE_omit || table_enc == constants::DW_EH_PE_omit {
+ fde_count = 0
+ } else {
+ let ptr = parse_encoded_pointer(fde_count_enc, &parameters, &mut reader)?;
+ fde_count = match ptr {
+ Pointer::Direct(c) => c,
+ Pointer::Indirect(_) => return Err(Error::UnsupportedPointerEncoding),
+ }
+ }
+
+ Ok(ParsedEhFrameHdr {
+ address_size,
+ section: self.0.clone(),
+
+ eh_frame_ptr,
+ fde_count,
+ table_enc,
+ table: reader,
+ })
+ }
+}
+
+impl<R: Reader> Section<R> for EhFrameHdr<R> {
+ fn id() -> SectionId {
+ SectionId::EhFrameHdr
+ }
+
+ fn reader(&self) -> &R {
+ &self.0
+ }
+}
+
+impl<R: Reader> From<R> for EhFrameHdr<R> {
+ fn from(section: R) -> Self {
+ EhFrameHdr(section)
+ }
+}
+
+impl<R: Reader> ParsedEhFrameHdr<R> {
+ /// Returns the address of the binary's `.eh_frame` section.
+ pub fn eh_frame_ptr(&self) -> Pointer {
+ self.eh_frame_ptr
+ }
+
+ /// Retrieves the CFI binary search table, if there is one.
+ pub fn table(&self) -> Option<EhHdrTable<R>> {
+ // There are two big edge cases here:
+ // * You search the table for an invalid address. As this is just a binary
+ // search table, we always have to return a valid result for that (unless
+ // you specify an address that is lower than the first address in the
+ // table). Since this means that you have to recheck that the FDE contains
+ // your address anyways, we just return the first FDE even when the address
+ // is too low. After all, we're just doing a normal binary search.
+ // * This falls apart when the table is empty - there is no entry we could
+ // return. We conclude that an empty table is not really a table at all.
+ if self.fde_count == 0 {
+ None
+ } else {
+ Some(EhHdrTable { hdr: self })
+ }
+ }
+}
+
+/// An iterator for `.eh_frame_hdr` section's binary search table.
+///
+/// Each table entry consists of a tuple containing an `initial_location` and `address`.
+/// The `initial location` represents the first address that the targeted FDE
+/// is able to decode. The `address` is the address of the FDE in the `.eh_frame` section.
+/// The `address` can be converted with `EhHdrTable::pointer_to_offset` and `EhFrame::fde_from_offset` to an FDE.
+#[derive(Debug)]
+pub struct EhHdrTableIter<'a, 'bases, R: Reader> {
+ hdr: &'a ParsedEhFrameHdr<R>,
+ table: R,
+ bases: &'bases BaseAddresses,
+ remain: u64,
+}
+
+impl<'a, 'bases, R: Reader> EhHdrTableIter<'a, 'bases, R> {
+ /// Yield the next entry in the `EhHdrTableIter`.
+ pub fn next(&mut self) -> Result<Option<(Pointer, Pointer)>> {
+ if self.remain == 0 {
+ return Ok(None);
+ }
+
+ let parameters = PointerEncodingParameters {
+ bases: &self.bases.eh_frame_hdr,
+ func_base: None,
+ address_size: self.hdr.address_size,
+ section: &self.hdr.section,
+ };
+
+ self.remain -= 1;
+ let from = parse_encoded_pointer(self.hdr.table_enc, &parameters, &mut self.table)?;
+ let to = parse_encoded_pointer(self.hdr.table_enc, &parameters, &mut self.table)?;
+ Ok(Some((from, to)))
+ }
+ /// Yield the nth entry in the `EhHdrTableIter`
+ pub fn nth(&mut self, n: usize) -> Result<Option<(Pointer, Pointer)>> {
+ use core::convert::TryFrom;
+ let size = match self.hdr.table_enc.format() {
+ constants::DW_EH_PE_uleb128 | constants::DW_EH_PE_sleb128 => {
+ return Err(Error::VariableLengthSearchTable);
+ }
+ constants::DW_EH_PE_sdata2 | constants::DW_EH_PE_udata2 => 2,
+ constants::DW_EH_PE_sdata4 | constants::DW_EH_PE_udata4 => 4,
+ constants::DW_EH_PE_sdata8 | constants::DW_EH_PE_udata8 => 8,
+ _ => return Err(Error::UnknownPointerEncoding),
+ };
+
+ let row_size = size * 2;
+ let n = u64::try_from(n).map_err(|_| Error::UnsupportedOffset)?;
+ self.remain = self.remain.saturating_sub(n);
+ self.table.skip(R::Offset::from_u64(n * row_size)?)?;
+ self.next()
+ }
+}
+
+#[cfg(feature = "fallible-iterator")]
+impl<'a, 'bases, R: Reader> fallible_iterator::FallibleIterator for EhHdrTableIter<'a, 'bases, R> {
+ type Item = (Pointer, Pointer);
+ type Error = Error;
+ fn next(&mut self) -> Result<Option<Self::Item>> {
+ EhHdrTableIter::next(self)
+ }
+
+ fn size_hint(&self) -> (usize, Option<usize>) {
+ use core::convert::TryInto;
+ (
+ self.remain.try_into().unwrap_or(0),
+ self.remain.try_into().ok(),
+ )
+ }
+
+ fn nth(&mut self, n: usize) -> Result<Option<Self::Item>> {
+ EhHdrTableIter::nth(self, n)
+ }
+}
+
+/// The CFI binary search table that is an optional part of the `.eh_frame_hdr` section.
+#[derive(Debug, Clone)]
+pub struct EhHdrTable<'a, R: Reader> {
+ hdr: &'a ParsedEhFrameHdr<R>,
+}
+
+impl<'a, R: Reader + 'a> EhHdrTable<'a, R> {
+ /// Return an iterator that can walk the `.eh_frame_hdr` table.
+ ///
+ /// Each table entry consists of a tuple containing an `initial_location` and `address`.
+ /// The `initial location` represents the first address that the targeted FDE
+ /// is able to decode. The `address` is the address of the FDE in the `.eh_frame` section.
+ /// The `address` can be converted with `EhHdrTable::pointer_to_offset` and `EhFrame::fde_from_offset` to an FDE.
+ pub fn iter<'bases>(&self, bases: &'bases BaseAddresses) -> EhHdrTableIter<'_, 'bases, R> {
+ EhHdrTableIter {
+ hdr: self.hdr,
+ bases,
+ remain: self.hdr.fde_count,
+ table: self.hdr.table.clone(),
+ }
+ }
+ /// *Probably* returns a pointer to the FDE for the given address.
+ ///
+ /// This performs a binary search, so if there is no FDE for the given address,
+ /// this function **will** return a pointer to any other FDE that's close by.
+ ///
+ /// To be sure, you **must** call `contains` on the FDE.
+ pub fn lookup(&self, address: u64, bases: &BaseAddresses) -> Result<Pointer> {
+ let size = match self.hdr.table_enc.format() {
+ constants::DW_EH_PE_uleb128 | constants::DW_EH_PE_sleb128 => {
+ return Err(Error::VariableLengthSearchTable);
+ }
+ constants::DW_EH_PE_sdata2 | constants::DW_EH_PE_udata2 => 2,
+ constants::DW_EH_PE_sdata4 | constants::DW_EH_PE_udata4 => 4,
+ constants::DW_EH_PE_sdata8 | constants::DW_EH_PE_udata8 => 8,
+ _ => return Err(Error::UnknownPointerEncoding),
+ };
+
+ let row_size = size * 2;
+
+ let mut len = self.hdr.fde_count;
+
+ let mut reader = self.hdr.table.clone();
+
+ let parameters = PointerEncodingParameters {
+ bases: &bases.eh_frame_hdr,
+ func_base: None,
+ address_size: self.hdr.address_size,
+ section: &self.hdr.section,
+ };
+
+ while len > 1 {
+ let head = reader.split(R::Offset::from_u64((len / 2) * row_size)?)?;
+ let tail = reader.clone();
+
+ let pivot = parse_encoded_pointer(self.hdr.table_enc, &parameters, &mut reader)?;
+ let pivot = match pivot {
+ Pointer::Direct(x) => x,
+ Pointer::Indirect(_) => return Err(Error::UnsupportedPointerEncoding),
+ };
+
+ match pivot.cmp(&address) {
+ Ordering::Equal => {
+ reader = tail;
+ break;
+ }
+ Ordering::Less => {
+ reader = tail;
+ len = len - (len / 2);
+ }
+ Ordering::Greater => {
+ reader = head;
+ len /= 2;
+ }
+ }
+ }
+
+ reader.skip(R::Offset::from_u64(size)?)?;
+
+ parse_encoded_pointer(self.hdr.table_enc, &parameters, &mut reader)
+ }
+
+ /// Convert a `Pointer` to a section offset.
+ ///
+ /// This does not support indirect pointers.
+ pub fn pointer_to_offset(&self, ptr: Pointer) -> Result<EhFrameOffset<R::Offset>> {
+ let ptr = match ptr {
+ Pointer::Direct(x) => x,
+ _ => return Err(Error::UnsupportedPointerEncoding),
+ };
+
+ let eh_frame_ptr = match self.hdr.eh_frame_ptr() {
+ Pointer::Direct(x) => x,
+ _ => return Err(Error::UnsupportedPointerEncoding),
+ };
+
+ // Calculate the offset in the EhFrame section
+ R::Offset::from_u64(ptr - eh_frame_ptr).map(EhFrameOffset)
+ }
+
+ /// Returns a parsed FDE for the given address, or `NoUnwindInfoForAddress`
+ /// if there are none.
+ ///
+ /// You must provide a function to get its associated CIE. See
+ /// `PartialFrameDescriptionEntry::parse` for more information.
+ ///
+ /// # Example
+ ///
+ /// ```
+ /// # use gimli::{BaseAddresses, EhFrame, ParsedEhFrameHdr, EndianSlice, NativeEndian, Error, UnwindSection};
+ /// # fn foo() -> Result<(), Error> {
+ /// # let eh_frame: EhFrame<EndianSlice<NativeEndian>> = unreachable!();
+ /// # let eh_frame_hdr: ParsedEhFrameHdr<EndianSlice<NativeEndian>> = unimplemented!();
+ /// # let addr = 0;
+ /// # let bases = unimplemented!();
+ /// let table = eh_frame_hdr.table().unwrap();
+ /// let fde = table.fde_for_address(&eh_frame, &bases, addr, EhFrame::cie_from_offset)?;
+ /// # Ok(())
+ /// # }
+ /// ```
+ pub fn fde_for_address<F>(
+ &self,
+ frame: &EhFrame<R>,
+ bases: &BaseAddresses,
+ address: u64,
+ get_cie: F,
+ ) -> Result<FrameDescriptionEntry<R>>
+ where
+ F: FnMut(
+ &EhFrame<R>,
+ &BaseAddresses,
+ EhFrameOffset<R::Offset>,
+ ) -> Result<CommonInformationEntry<R>>,
+ {
+ let fdeptr = self.lookup(address, bases)?;
+ let offset = self.pointer_to_offset(fdeptr)?;
+ let entry = frame.fde_from_offset(bases, offset, get_cie)?;
+ if entry.contains(address) {
+ Ok(entry)
+ } else {
+ Err(Error::NoUnwindInfoForAddress)
+ }
+ }
+
+ #[inline]
+ #[doc(hidden)]
+ #[deprecated(note = "Method renamed to fde_for_address; use that instead.")]
+ pub fn lookup_and_parse<F>(
+ &self,
+ address: u64,
+ bases: &BaseAddresses,
+ frame: EhFrame<R>,
+ get_cie: F,
+ ) -> Result<FrameDescriptionEntry<R>>
+ where
+ F: FnMut(
+ &EhFrame<R>,
+ &BaseAddresses,
+ EhFrameOffset<R::Offset>,
+ ) -> Result<CommonInformationEntry<R>>,
+ {
+ self.fde_for_address(&frame, bases, address, get_cie)
+ }
+
+ /// Returns the frame unwind information for the given address,
+ /// or `NoUnwindInfoForAddress` if there are none.
+ ///
+ /// You must provide a function to get the associated CIE. See
+ /// `PartialFrameDescriptionEntry::parse` for more information.
+ pub fn unwind_info_for_address<'ctx, F, A: UnwindContextStorage<R>>(
+ &self,
+ frame: &EhFrame<R>,
+ bases: &BaseAddresses,
+ ctx: &'ctx mut UnwindContext<R, A>,
+ address: u64,
+ get_cie: F,
+ ) -> Result<&'ctx UnwindTableRow<R, A>>
+ where
+ F: FnMut(
+ &EhFrame<R>,
+ &BaseAddresses,
+ EhFrameOffset<R::Offset>,
+ ) -> Result<CommonInformationEntry<R>>,
+ {
+ let fde = self.fde_for_address(frame, bases, address, get_cie)?;
+ fde.unwind_info_for_address(frame, bases, ctx, address)
+ }
+}
+
+/// `EhFrame` contains the frame unwinding information needed during exception
+/// handling found in the `.eh_frame` section.
+///
+/// Most interesting methods are defined in the
+/// [`UnwindSection`](trait.UnwindSection.html) trait.
+///
+/// See
+/// [`DebugFrame`](./struct.DebugFrame.html#differences-between-debug_frame-and-eh_frame)
+/// for some discussion on the differences between `.debug_frame` and
+/// `.eh_frame`.
+#[derive(Clone, Copy, Debug, PartialEq, Eq)]
+pub struct EhFrame<R: Reader> {
+ section: R,
+ address_size: u8,
+}
+
+impl<R: Reader> EhFrame<R> {
+ /// Set the size of a target address in bytes.
+ ///
+ /// This defaults to the native word size.
+ pub fn set_address_size(&mut self, address_size: u8) {
+ self.address_size = address_size
+ }
+}
+
+impl<'input, Endian> EhFrame<EndianSlice<'input, Endian>>
+where
+ Endian: Endianity,
+{
+ /// Construct a new `EhFrame` instance from the data in the
+ /// `.eh_frame` section.
+ ///
+ /// It is the caller's responsibility to read the section and present it as
+ /// a `&[u8]` slice. That means using some ELF loader on Linux, a Mach-O
+ /// loader on macOS, etc.
+ ///
+ /// ```
+ /// use gimli::{EhFrame, EndianSlice, NativeEndian};
+ ///
+ /// // Use with `.eh_frame`
+ /// # let buf = [0x00, 0x01, 0x02, 0x03];
+ /// # let read_eh_frame_section_somehow = || &buf;
+ /// let eh_frame = EhFrame::new(read_eh_frame_section_somehow(), NativeEndian);
+ /// ```
+ pub fn new(section: &'input [u8], endian: Endian) -> Self {
+ Self::from(EndianSlice::new(section, endian))
+ }
+}
+
+impl<R: Reader> Section<R> for EhFrame<R> {
+ fn id() -> SectionId {
+ SectionId::EhFrame
+ }
+
+ fn reader(&self) -> &R {
+ &self.section
+ }
+}
+
+impl<R: Reader> From<R> for EhFrame<R> {
+ fn from(section: R) -> Self {
+ // Default to native word size.
+ EhFrame {
+ section,
+ address_size: mem::size_of::<usize>() as u8,
+ }
+ }
+}
+
+// This has to be `pub` to silence a warning (that is deny(..)'d by default) in
+// rustc. Eventually, not having this `pub` will become a hard error.
+#[doc(hidden)]
+#[allow(missing_docs)]
+#[derive(Clone, Copy, Debug, PartialEq, Eq)]
+pub enum CieOffsetEncoding {
+ U32,
+ U64,
+}
+
+/// An offset into an `UnwindSection`.
+//
+// Needed to avoid conflicting implementations of `Into<T>`.
+pub trait UnwindOffset<T = usize>: Copy + Debug + Eq + From<T>
+where
+ T: ReaderOffset,
+{
+ /// Convert an `UnwindOffset<T>` into a `T`.
+ fn into(self) -> T;
+}
+
+impl<T> UnwindOffset<T> for DebugFrameOffset<T>
+where
+ T: ReaderOffset,
+{
+ #[inline]
+ fn into(self) -> T {
+ self.0
+ }
+}
+
+impl<T> UnwindOffset<T> for EhFrameOffset<T>
+where
+ T: ReaderOffset,
+{
+ #[inline]
+ fn into(self) -> T {
+ self.0
+ }
+}
+
+/// This trait completely encapsulates everything that is different between
+/// `.eh_frame` and `.debug_frame`, as well as all the bits that can change
+/// between DWARF versions.
+#[doc(hidden)]
+pub trait _UnwindSectionPrivate<R: Reader> {
+ /// Get the underlying section data.
+ fn section(&self) -> &R;
+
+ /// Returns true if the given length value should be considered an
+ /// end-of-entries sentinel.
+ fn length_value_is_end_of_entries(length: R::Offset) -> bool;
+
+ /// Return true if the given offset if the CIE sentinel, false otherwise.
+ fn is_cie(format: Format, id: u64) -> bool;
+
+ /// Return the CIE offset/ID encoding used by this unwind section with the
+ /// given DWARF format.
+ fn cie_offset_encoding(format: Format) -> CieOffsetEncoding;
+
+ /// For `.eh_frame`, CIE offsets are relative to the current position. For
+ /// `.debug_frame`, they are relative to the start of the section. We always
+ /// internally store them relative to the section, so we handle translating
+ /// `.eh_frame`'s relative offsets in this method. If the offset calculation
+ /// underflows, return `None`.
+ fn resolve_cie_offset(&self, base: R::Offset, offset: R::Offset) -> Option<R::Offset>;
+
+ /// Does this version of this unwind section encode address and segment
+ /// sizes in its CIEs?
+ fn has_address_and_segment_sizes(version: u8) -> bool;
+
+ /// The address size to use if `has_address_and_segment_sizes` returns false.
+ fn address_size(&self) -> u8;
+
+ /// The segment size to use if `has_address_and_segment_sizes` returns false.
+ fn segment_size(&self) -> u8;
+}
+
+/// A section holding unwind information: either `.debug_frame` or
+/// `.eh_frame`. See [`DebugFrame`](./struct.DebugFrame.html) and
+/// [`EhFrame`](./struct.EhFrame.html) respectively.
+pub trait UnwindSection<R: Reader>: Clone + Debug + _UnwindSectionPrivate<R> {
+ /// The offset type associated with this CFI section. Either
+ /// `DebugFrameOffset` or `EhFrameOffset`.
+ type Offset: UnwindOffset<R::Offset>;
+
+ /// Iterate over the `CommonInformationEntry`s and `FrameDescriptionEntry`s
+ /// in this `.debug_frame` section.
+ ///
+ /// Can be [used with
+ /// `FallibleIterator`](./index.html#using-with-fallibleiterator).
+ fn entries<'bases>(&self, bases: &'bases BaseAddresses) -> CfiEntriesIter<'bases, Self, R> {
+ CfiEntriesIter {
+ section: self.clone(),
+ bases,
+ input: self.section().clone(),
+ }
+ }
+
+ /// Parse the `CommonInformationEntry` at the given offset.
+ fn cie_from_offset(
+ &self,
+ bases: &BaseAddresses,
+ offset: Self::Offset,
+ ) -> Result<CommonInformationEntry<R>> {
+ let offset = UnwindOffset::into(offset);
+ let input = &mut self.section().clone();
+ input.skip(offset)?;
+ CommonInformationEntry::parse(bases, self, input)
+ }
+
+ /// Parse the `PartialFrameDescriptionEntry` at the given offset.
+ fn partial_fde_from_offset<'bases>(
+ &self,
+ bases: &'bases BaseAddresses,
+ offset: Self::Offset,
+ ) -> Result<PartialFrameDescriptionEntry<'bases, Self, R>> {
+ let offset = UnwindOffset::into(offset);
+ let input = &mut self.section().clone();
+ input.skip(offset)?;
+ PartialFrameDescriptionEntry::parse_partial(self, bases, input)
+ }
+
+ /// Parse the `FrameDescriptionEntry` at the given offset.
+ fn fde_from_offset<F>(
+ &self,
+ bases: &BaseAddresses,
+ offset: Self::Offset,
+ get_cie: F,
+ ) -> Result<FrameDescriptionEntry<R>>
+ where
+ F: FnMut(&Self, &BaseAddresses, Self::Offset) -> Result<CommonInformationEntry<R>>,
+ {
+ let partial = self.partial_fde_from_offset(bases, offset)?;
+ partial.parse(get_cie)
+ }
+
+ /// Find the `FrameDescriptionEntry` for the given address.
+ ///
+ /// If found, the FDE is returned. If not found,
+ /// `Err(gimli::Error::NoUnwindInfoForAddress)` is returned.
+ /// If parsing fails, the error is returned.
+ ///
+ /// You must provide a function to get its associated CIE. See
+ /// `PartialFrameDescriptionEntry::parse` for more information.
+ ///
+ /// Note: this iterates over all FDEs. If available, it is possible
+ /// to do a binary search with `EhFrameHdr::fde_for_address` instead.
+ fn fde_for_address<F>(
+ &self,
+ bases: &BaseAddresses,
+ address: u64,
+ mut get_cie: F,
+ ) -> Result<FrameDescriptionEntry<R>>
+ where
+ F: FnMut(&Self, &BaseAddresses, Self::Offset) -> Result<CommonInformationEntry<R>>,
+ {
+ let mut entries = self.entries(bases);
+ while let Some(entry) = entries.next()? {
+ match entry {
+ CieOrFde::Cie(_) => {}
+ CieOrFde::Fde(partial) => {
+ let fde = partial.parse(&mut get_cie)?;
+ if fde.contains(address) {
+ return Ok(fde);
+ }
+ }
+ }
+ }
+ Err(Error::NoUnwindInfoForAddress)
+ }
+
+ /// Find the frame unwind information for the given address.
+ ///
+ /// If found, the unwind information is returned. If not found,
+ /// `Err(gimli::Error::NoUnwindInfoForAddress)` is returned. If parsing or
+ /// CFI evaluation fails, the error is returned.
+ ///
+ /// ```
+ /// use gimli::{BaseAddresses, EhFrame, EndianSlice, NativeEndian, UnwindContext,
+ /// UnwindSection};
+ ///
+ /// # fn foo() -> gimli::Result<()> {
+ /// # let read_eh_frame_section = || unimplemented!();
+ /// // Get the `.eh_frame` section from the object file. Alternatively,
+ /// // use `EhFrame` with the `.eh_frame` section of the object file.
+ /// let eh_frame = EhFrame::new(read_eh_frame_section(), NativeEndian);
+ ///
+ /// # let get_frame_pc = || unimplemented!();
+ /// // Get the address of the PC for a frame you'd like to unwind.
+ /// let address = get_frame_pc();
+ ///
+ /// // This context is reusable, which cuts down on heap allocations.
+ /// let ctx = UnwindContext::new();
+ ///
+ /// // Optionally provide base addresses for any relative pointers. If a
+ /// // base address isn't provided and a pointer is found that is relative to
+ /// // it, we will return an `Err`.
+ /// # let address_of_text_section_in_memory = unimplemented!();
+ /// # let address_of_got_section_in_memory = unimplemented!();
+ /// let bases = BaseAddresses::default()
+ /// .set_text(address_of_text_section_in_memory)
+ /// .set_got(address_of_got_section_in_memory);
+ ///
+ /// let unwind_info = eh_frame.unwind_info_for_address(
+ /// &bases,
+ /// &mut ctx,
+ /// address,
+ /// EhFrame::cie_from_offset,
+ /// )?;
+ ///
+ /// # let do_stuff_with = |_| unimplemented!();
+ /// do_stuff_with(unwind_info);
+ /// # let _ = ctx;
+ /// # unreachable!()
+ /// # }
+ /// ```
+ #[inline]
+ fn unwind_info_for_address<'ctx, F, A: UnwindContextStorage<R>>(
+ &self,
+ bases: &BaseAddresses,
+ ctx: &'ctx mut UnwindContext<R, A>,
+ address: u64,
+ get_cie: F,
+ ) -> Result<&'ctx UnwindTableRow<R, A>>
+ where
+ F: FnMut(&Self, &BaseAddresses, Self::Offset) -> Result<CommonInformationEntry<R>>,
+ {
+ let fde = self.fde_for_address(bases, address, get_cie)?;
+ fde.unwind_info_for_address(self, bases, ctx, address)
+ }
+}
+
+impl<R: Reader> _UnwindSectionPrivate<R> for DebugFrame<R> {
+ fn section(&self) -> &R {
+ &self.section
+ }
+
+ fn length_value_is_end_of_entries(_: R::Offset) -> bool {
+ false
+ }
+
+ fn is_cie(format: Format, id: u64) -> bool {
+ match format {
+ Format::Dwarf32 => id == 0xffff_ffff,
+ Format::Dwarf64 => id == 0xffff_ffff_ffff_ffff,
+ }
+ }
+
+ fn cie_offset_encoding(format: Format) -> CieOffsetEncoding {
+ match format {
+ Format::Dwarf32 => CieOffsetEncoding::U32,
+ Format::Dwarf64 => CieOffsetEncoding::U64,
+ }
+ }
+
+ fn resolve_cie_offset(&self, _: R::Offset, offset: R::Offset) -> Option<R::Offset> {
+ Some(offset)
+ }
+
+ fn has_address_and_segment_sizes(version: u8) -> bool {
+ version == 4
+ }
+
+ fn address_size(&self) -> u8 {
+ self.address_size
+ }
+
+ fn segment_size(&self) -> u8 {
+ self.segment_size
+ }
+}
+
+impl<R: Reader> UnwindSection<R> for DebugFrame<R> {
+ type Offset = DebugFrameOffset<R::Offset>;
+}
+
+impl<R: Reader> _UnwindSectionPrivate<R> for EhFrame<R> {
+ fn section(&self) -> &R {
+ &self.section
+ }
+
+ fn length_value_is_end_of_entries(length: R::Offset) -> bool {
+ length.into_u64() == 0
+ }
+
+ fn is_cie(_: Format, id: u64) -> bool {
+ id == 0
+ }
+
+ fn cie_offset_encoding(_format: Format) -> CieOffsetEncoding {
+ // `.eh_frame` offsets are always 4 bytes, regardless of the DWARF
+ // format.
+ CieOffsetEncoding::U32
+ }
+
+ fn resolve_cie_offset(&self, base: R::Offset, offset: R::Offset) -> Option<R::Offset> {
+ base.checked_sub(offset)
+ }
+
+ fn has_address_and_segment_sizes(_version: u8) -> bool {
+ false
+ }
+
+ fn address_size(&self) -> u8 {
+ self.address_size
+ }
+
+ fn segment_size(&self) -> u8 {
+ 0
+ }
+}
+
+impl<R: Reader> UnwindSection<R> for EhFrame<R> {
+ type Offset = EhFrameOffset<R::Offset>;
+}
+
+/// Optional base addresses for the relative `DW_EH_PE_*` encoded pointers.
+///
+/// During CIE/FDE parsing, if a relative pointer is encountered for a base
+/// address that is unknown, an Err will be returned.
+///
+/// ```
+/// use gimli::BaseAddresses;
+///
+/// # fn foo() {
+/// # let address_of_eh_frame_hdr_section_in_memory = unimplemented!();
+/// # let address_of_eh_frame_section_in_memory = unimplemented!();
+/// # let address_of_text_section_in_memory = unimplemented!();
+/// # let address_of_got_section_in_memory = unimplemented!();
+/// # let address_of_the_start_of_current_func = unimplemented!();
+/// let bases = BaseAddresses::default()
+/// .set_eh_frame_hdr(address_of_eh_frame_hdr_section_in_memory)
+/// .set_eh_frame(address_of_eh_frame_section_in_memory)
+/// .set_text(address_of_text_section_in_memory)
+/// .set_got(address_of_got_section_in_memory);
+/// # let _ = bases;
+/// # }
+/// ```
+#[derive(Clone, Default, Debug, PartialEq, Eq)]
+pub struct BaseAddresses {
+ /// The base addresses to use for pointers in the `.eh_frame_hdr` section.
+ pub eh_frame_hdr: SectionBaseAddresses,
+
+ /// The base addresses to use for pointers in the `.eh_frame` section.
+ pub eh_frame: SectionBaseAddresses,
+}
+
+/// Optional base addresses for the relative `DW_EH_PE_*` encoded pointers
+/// in a particular section.
+///
+/// See `BaseAddresses` for methods that are helpful in setting these addresses.
+#[derive(Clone, Default, Debug, PartialEq, Eq)]
+pub struct SectionBaseAddresses {
+ /// The address of the section containing the pointer.
+ pub section: Option<u64>,
+
+ /// The base address for text relative pointers.
+ /// This is generally the address of the `.text` section.
+ pub text: Option<u64>,
+
+ /// The base address for data relative pointers.
+ ///
+ /// For pointers in the `.eh_frame_hdr` section, this is the address
+ /// of the `.eh_frame_hdr` section
+ ///
+ /// For pointers in the `.eh_frame` section, this is generally the
+ /// global pointer, such as the address of the `.got` section.
+ pub data: Option<u64>,
+}
+
+impl BaseAddresses {
+ /// Set the `.eh_frame_hdr` section base address.
+ #[inline]
+ pub fn set_eh_frame_hdr(mut self, addr: u64) -> Self {
+ self.eh_frame_hdr.section = Some(addr);
+ self.eh_frame_hdr.data = Some(addr);
+ self
+ }
+
+ /// Set the `.eh_frame` section base address.
+ #[inline]
+ pub fn set_eh_frame(mut self, addr: u64) -> Self {
+ self.eh_frame.section = Some(addr);
+ self
+ }
+
+ /// Set the `.text` section base address.
+ #[inline]
+ pub fn set_text(mut self, addr: u64) -> Self {
+ self.eh_frame_hdr.text = Some(addr);
+ self.eh_frame.text = Some(addr);
+ self
+ }
+
+ /// Set the `.got` section base address.
+ #[inline]
+ pub fn set_got(mut self, addr: u64) -> Self {
+ self.eh_frame.data = Some(addr);
+ self
+ }
+}
+
+/// An iterator over CIE and FDE entries in a `.debug_frame` or `.eh_frame`
+/// section.
+///
+/// Some pointers may be encoded relative to various base addresses. Use the
+/// [`BaseAddresses`](./struct.BaseAddresses.html) parameter to provide them. By
+/// default, none are provided. If a relative pointer is encountered for a base
+/// address that is unknown, an `Err` will be returned and iteration will abort.
+///
+/// Can be [used with
+/// `FallibleIterator`](./index.html#using-with-fallibleiterator).
+///
+/// ```
+/// use gimli::{BaseAddresses, EhFrame, EndianSlice, NativeEndian, UnwindSection};
+///
+/// # fn foo() -> gimli::Result<()> {
+/// # let read_eh_frame_somehow = || unimplemented!();
+/// let eh_frame = EhFrame::new(read_eh_frame_somehow(), NativeEndian);
+///
+/// # let address_of_eh_frame_hdr_section_in_memory = unimplemented!();
+/// # let address_of_eh_frame_section_in_memory = unimplemented!();
+/// # let address_of_text_section_in_memory = unimplemented!();
+/// # let address_of_got_section_in_memory = unimplemented!();
+/// # let address_of_the_start_of_current_func = unimplemented!();
+/// // Provide base addresses for relative pointers.
+/// let bases = BaseAddresses::default()
+/// .set_eh_frame_hdr(address_of_eh_frame_hdr_section_in_memory)
+/// .set_eh_frame(address_of_eh_frame_section_in_memory)
+/// .set_text(address_of_text_section_in_memory)
+/// .set_got(address_of_got_section_in_memory);
+///
+/// let mut entries = eh_frame.entries(&bases);
+///
+/// # let do_stuff_with = |_| unimplemented!();
+/// while let Some(entry) = entries.next()? {
+/// do_stuff_with(entry)
+/// }
+/// # unreachable!()
+/// # }
+/// ```
+#[derive(Clone, Debug)]
+pub struct CfiEntriesIter<'bases, Section, R>
+where
+ R: Reader,
+ Section: UnwindSection<R>,
+{
+ section: Section,
+ bases: &'bases BaseAddresses,
+ input: R,
+}
+
+impl<'bases, Section, R> CfiEntriesIter<'bases, Section, R>
+where
+ R: Reader,
+ Section: UnwindSection<R>,
+{
+ /// Advance the iterator to the next entry.
+ pub fn next(&mut self) -> Result<Option<CieOrFde<'bases, Section, R>>> {
+ if self.input.is_empty() {
+ return Ok(None);
+ }
+
+ match parse_cfi_entry(self.bases, &self.section, &mut self.input) {
+ Err(e) => {
+ self.input.empty();
+ Err(e)
+ }
+ Ok(None) => {
+ self.input.empty();
+ Ok(None)
+ }
+ Ok(Some(entry)) => Ok(Some(entry)),
+ }
+ }
+}
+
+#[cfg(feature = "fallible-iterator")]
+impl<'bases, Section, R> fallible_iterator::FallibleIterator for CfiEntriesIter<'bases, Section, R>
+where
+ R: Reader,
+ Section: UnwindSection<R>,
+{
+ type Item = CieOrFde<'bases, Section, R>;
+ type Error = Error;
+
+ fn next(&mut self) -> ::core::result::Result<Option<Self::Item>, Self::Error> {
+ CfiEntriesIter::next(self)
+ }
+}
+
+/// Either a `CommonInformationEntry` (CIE) or a `FrameDescriptionEntry` (FDE).
+#[derive(Clone, Debug, PartialEq, Eq)]
+pub enum CieOrFde<'bases, Section, R>
+where
+ R: Reader,
+ Section: UnwindSection<R>,
+{
+ /// This CFI entry is a `CommonInformationEntry`.
+ Cie(CommonInformationEntry<R>),
+ /// This CFI entry is a `FrameDescriptionEntry`, however fully parsing it
+ /// requires parsing its CIE first, so it is left in a partially parsed
+ /// state.
+ Fde(PartialFrameDescriptionEntry<'bases, Section, R>),
+}
+
+#[allow(clippy::type_complexity)]
+fn parse_cfi_entry<'bases, Section, R>(
+ bases: &'bases BaseAddresses,
+ section: &Section,
+ input: &mut R,
+) -> Result<Option<CieOrFde<'bases, Section, R>>>
+where
+ R: Reader,
+ Section: UnwindSection<R>,
+{
+ let (offset, length, format) = loop {
+ let offset = input.offset_from(section.section());
+ let (length, format) = input.read_initial_length()?;
+
+ if Section::length_value_is_end_of_entries(length) {
+ return Ok(None);
+ }
+
+ // Hack: skip zero padding inserted by buggy compilers/linkers.
+ // We require that the padding is a multiple of 32-bits, otherwise
+ // there is no reliable way to determine when the padding ends. This
+ // should be okay since CFI entries must be aligned to the address size.
+
+ if length.into_u64() != 0 || format != Format::Dwarf32 {
+ break (offset, length, format);
+ }
+ };
+
+ let mut rest = input.split(length)?;
+ let cie_offset_base = rest.offset_from(section.section());
+ let cie_id_or_offset = match Section::cie_offset_encoding(format) {
+ CieOffsetEncoding::U32 => rest.read_u32().map(u64::from)?,
+ CieOffsetEncoding::U64 => rest.read_u64()?,
+ };
+
+ if Section::is_cie(format, cie_id_or_offset) {
+ let cie = CommonInformationEntry::parse_rest(offset, length, format, bases, section, rest)?;
+ Ok(Some(CieOrFde::Cie(cie)))
+ } else {
+ let cie_offset = R::Offset::from_u64(cie_id_or_offset)?;
+ let cie_offset = match section.resolve_cie_offset(cie_offset_base, cie_offset) {
+ None => return Err(Error::OffsetOutOfBounds),
+ Some(cie_offset) => cie_offset,
+ };
+
+ let fde = PartialFrameDescriptionEntry {
+ offset,
+ length,
+ format,
+ cie_offset: cie_offset.into(),
+ rest,
+ section: section.clone(),
+ bases,
+ };
+
+ Ok(Some(CieOrFde::Fde(fde)))
+ }
+}
+
+/// We support the z-style augmentation [defined by `.eh_frame`][ehframe].
+///
+/// [ehframe]: https://refspecs.linuxfoundation.org/LSB_3.0.0/LSB-Core-generic/LSB-Core-generic/ehframechpt.html
+#[derive(Copy, Clone, Debug, Default, PartialEq, Eq)]
+pub struct Augmentation {
+ /// > A 'L' may be present at any position after the first character of the
+ /// > string. This character may only be present if 'z' is the first character
+ /// > of the string. If present, it indicates the presence of one argument in
+ /// > the Augmentation Data of the CIE, and a corresponding argument in the
+ /// > Augmentation Data of the FDE. The argument in the Augmentation Data of
+ /// > the CIE is 1-byte and represents the pointer encoding used for the
+ /// > argument in the Augmentation Data of the FDE, which is the address of a
+ /// > language-specific data area (LSDA). The size of the LSDA pointer is
+ /// > specified by the pointer encoding used.
+ lsda: Option<constants::DwEhPe>,
+
+ /// > A 'P' may be present at any position after the first character of the
+ /// > string. This character may only be present if 'z' is the first character
+ /// > of the string. If present, it indicates the presence of two arguments in
+ /// > the Augmentation Data of the CIE. The first argument is 1-byte and
+ /// > represents the pointer encoding used for the second argument, which is
+ /// > the address of a personality routine handler. The size of the
+ /// > personality routine pointer is specified by the pointer encoding used.
+ personality: Option<(constants::DwEhPe, Pointer)>,
+
+ /// > A 'R' may be present at any position after the first character of the
+ /// > string. This character may only be present if 'z' is the first character
+ /// > of the string. If present, The Augmentation Data shall include a 1 byte
+ /// > argument that represents the pointer encoding for the address pointers
+ /// > used in the FDE.
+ fde_address_encoding: Option<constants::DwEhPe>,
+
+ /// True if this CIE's FDEs are trampolines for signal handlers.
+ is_signal_trampoline: bool,
+}
+
+impl Augmentation {
+ fn parse<Section, R>(
+ augmentation_str: &mut R,
+ bases: &BaseAddresses,
+ address_size: u8,
+ section: &Section,
+ input: &mut R,
+ ) -> Result<Augmentation>
+ where
+ R: Reader,
+ Section: UnwindSection<R>,
+ {
+ debug_assert!(
+ !augmentation_str.is_empty(),
+ "Augmentation::parse should only be called if we have an augmentation"
+ );
+
+ let mut augmentation = Augmentation::default();
+
+ let mut parsed_first = false;
+ let mut data = None;
+
+ while !augmentation_str.is_empty() {
+ let ch = augmentation_str.read_u8()?;
+ match ch {
+ b'z' => {
+ if parsed_first {
+ return Err(Error::UnknownAugmentation);
+ }
+
+ let augmentation_length = input.read_uleb128().and_then(R::Offset::from_u64)?;
+ data = Some(input.split(augmentation_length)?);
+ }
+ b'L' => {
+ let rest = data.as_mut().ok_or(Error::UnknownAugmentation)?;
+ let encoding = parse_pointer_encoding(rest)?;
+ augmentation.lsda = Some(encoding);
+ }
+ b'P' => {
+ let rest = data.as_mut().ok_or(Error::UnknownAugmentation)?;
+ let encoding = parse_pointer_encoding(rest)?;
+ let parameters = PointerEncodingParameters {
+ bases: &bases.eh_frame,
+ func_base: None,
+ address_size,
+ section: section.section(),
+ };
+
+ let personality = parse_encoded_pointer(encoding, &parameters, rest)?;
+ augmentation.personality = Some((encoding, personality));
+ }
+ b'R' => {
+ let rest = data.as_mut().ok_or(Error::UnknownAugmentation)?;
+ let encoding = parse_pointer_encoding(rest)?;
+ augmentation.fde_address_encoding = Some(encoding);
+ }
+ b'S' => augmentation.is_signal_trampoline = true,
+ _ => return Err(Error::UnknownAugmentation),
+ }
+
+ parsed_first = true;
+ }
+
+ Ok(augmentation)
+ }
+}
+
+/// Parsed augmentation data for a `FrameDescriptEntry`.
+#[derive(Clone, Debug, Default, PartialEq, Eq)]
+struct AugmentationData {
+ lsda: Option<Pointer>,
+}
+
+impl AugmentationData {
+ fn parse<R: Reader>(
+ augmentation: &Augmentation,
+ encoding_parameters: &PointerEncodingParameters<R>,
+ input: &mut R,
+ ) -> Result<AugmentationData> {
+ // In theory, we should be iterating over the original augmentation
+ // string, interpreting each character, and reading the appropriate bits
+ // out of the augmentation data as we go. However, the only character
+ // that defines augmentation data in the FDE is the 'L' character, so we
+ // can just check for its presence directly.
+
+ let aug_data_len = input.read_uleb128().and_then(R::Offset::from_u64)?;
+ let rest = &mut input.split(aug_data_len)?;
+ let mut augmentation_data = AugmentationData::default();
+ if let Some(encoding) = augmentation.lsda {
+ let lsda = parse_encoded_pointer(encoding, encoding_parameters, rest)?;
+ augmentation_data.lsda = Some(lsda);
+ }
+ Ok(augmentation_data)
+ }
+}
+
+/// > A Common Information Entry holds information that is shared among many
+/// > Frame Description Entries. There is at least one CIE in every non-empty
+/// > `.debug_frame` section.
+#[derive(Clone, Debug, PartialEq, Eq)]
+pub struct CommonInformationEntry<R, Offset = <R as Reader>::Offset>
+where
+ R: Reader<Offset = Offset>,
+ Offset: ReaderOffset,
+{
+ /// The offset of this entry from the start of its containing section.
+ offset: Offset,
+
+ /// > A constant that gives the number of bytes of the CIE structure, not
+ /// > including the length field itself (see Section 7.2.2). The size of the
+ /// > length field plus the value of length must be an integral multiple of
+ /// > the address size.
+ length: Offset,
+
+ format: Format,
+
+ /// > A version number (see Section 7.23). This number is specific to the
+ /// > call frame information and is independent of the DWARF version number.
+ version: u8,
+
+ /// The parsed augmentation, if any.
+ augmentation: Option<Augmentation>,
+
+ /// > The size of a target address in this CIE and any FDEs that use it, in
+ /// > bytes. If a compilation unit exists for this frame, its address size
+ /// > must match the address size here.
+ address_size: u8,
+
+ /// "The size of a segment selector in this CIE and any FDEs that use it, in
+ /// bytes."
+ segment_size: u8,
+
+ /// "A constant that is factored out of all advance location instructions
+ /// (see Section 6.4.2.1)."
+ code_alignment_factor: u64,
+
+ /// > A constant that is factored out of certain offset instructions (see
+ /// > below). The resulting value is (operand * data_alignment_factor).
+ data_alignment_factor: i64,
+
+ /// > An unsigned LEB128 constant that indicates which column in the rule
+ /// > table represents the return address of the function. Note that this
+ /// > column might not correspond to an actual machine register.
+ return_address_register: Register,
+
+ /// > A sequence of rules that are interpreted to create the initial setting
+ /// > of each column in the table.
+ ///
+ /// > The default rule for all columns before interpretation of the initial
+ /// > instructions is the undefined rule. However, an ABI authoring body or a
+ /// > compilation system authoring body may specify an alternate default
+ /// > value for any or all columns.
+ ///
+ /// This is followed by `DW_CFA_nop` padding until the end of `length` bytes
+ /// in the input.
+ initial_instructions: R,
+}
+
+impl<R: Reader> CommonInformationEntry<R> {
+ fn parse<Section: UnwindSection<R>>(
+ bases: &BaseAddresses,
+ section: &Section,
+ input: &mut R,
+ ) -> Result<CommonInformationEntry<R>> {
+ match parse_cfi_entry(bases, section, input)? {
+ Some(CieOrFde::Cie(cie)) => Ok(cie),
+ Some(CieOrFde::Fde(_)) => Err(Error::NotCieId),
+ None => Err(Error::NoEntryAtGivenOffset),
+ }
+ }
+
+ fn parse_rest<Section: UnwindSection<R>>(
+ offset: R::Offset,
+ length: R::Offset,
+ format: Format,
+ bases: &BaseAddresses,
+ section: &Section,
+ mut rest: R,
+ ) -> Result<CommonInformationEntry<R>> {
+ let version = rest.read_u8()?;
+
+ // Version 1 of `.debug_frame` corresponds to DWARF 2, and then for
+ // DWARF 3 and 4, I think they decided to just match the standard's
+ // version.
+ match version {
+ 1 | 3 | 4 => (),
+ _ => return Err(Error::UnknownVersion(u64::from(version))),
+ }
+
+ let mut augmentation_string = rest.read_null_terminated_slice()?;
+
+ let (address_size, segment_size) = if Section::has_address_and_segment_sizes(version) {
+ let address_size = rest.read_u8()?;
+ let segment_size = rest.read_u8()?;
+ (address_size, segment_size)
+ } else {
+ (section.address_size(), section.segment_size())
+ };
+
+ let code_alignment_factor = rest.read_uleb128()?;
+ let data_alignment_factor = rest.read_sleb128()?;
+
+ let return_address_register = if version == 1 {
+ Register(rest.read_u8()?.into())
+ } else {
+ rest.read_uleb128().and_then(Register::from_u64)?
+ };
+
+ let augmentation = if augmentation_string.is_empty() {
+ None
+ } else {
+ Some(Augmentation::parse(
+ &mut augmentation_string,
+ bases,
+ address_size,
+ section,
+ &mut rest,
+ )?)
+ };
+
+ let entry = CommonInformationEntry {
+ offset,
+ length,
+ format,
+ version,
+ augmentation,
+ address_size,
+ segment_size,
+ code_alignment_factor,
+ data_alignment_factor,
+ return_address_register,
+ initial_instructions: rest,
+ };
+
+ Ok(entry)
+ }
+}
+
+/// # Signal Safe Methods
+///
+/// These methods are guaranteed not to allocate, acquire locks, or perform any
+/// other signal-unsafe operations.
+impl<R: Reader> CommonInformationEntry<R> {
+ /// Get the offset of this entry from the start of its containing section.
+ pub fn offset(&self) -> R::Offset {
+ self.offset
+ }
+
+ /// Return the encoding parameters for this CIE.
+ pub fn encoding(&self) -> Encoding {
+ Encoding {
+ format: self.format,
+ version: u16::from(self.version),
+ address_size: self.address_size,
+ }
+ }
+
+ /// The size of addresses (in bytes) in this CIE.
+ pub fn address_size(&self) -> u8 {
+ self.address_size
+ }
+
+ /// Iterate over this CIE's initial instructions.
+ ///
+ /// Can be [used with
+ /// `FallibleIterator`](./index.html#using-with-fallibleiterator).
+ pub fn instructions<'a, Section>(
+ &self,
+ section: &'a Section,
+ bases: &'a BaseAddresses,
+ ) -> CallFrameInstructionIter<'a, R>
+ where
+ Section: UnwindSection<R>,
+ {
+ CallFrameInstructionIter {
+ input: self.initial_instructions.clone(),
+ address_encoding: None,
+ parameters: PointerEncodingParameters {
+ bases: &bases.eh_frame,
+ func_base: None,
+ address_size: self.address_size,
+ section: section.section(),
+ },
+ }
+ }
+
+ /// > A constant that gives the number of bytes of the CIE structure, not
+ /// > including the length field itself (see Section 7.2.2). The size of the
+ /// > length field plus the value of length must be an integral multiple of
+ /// > the address size.
+ pub fn entry_len(&self) -> R::Offset {
+ self.length
+ }
+
+ /// > A version number (see Section 7.23). This number is specific to the
+ /// > call frame information and is independent of the DWARF version number.
+ pub fn version(&self) -> u8 {
+ self.version
+ }
+
+ /// Get the augmentation data, if any exists.
+ ///
+ /// The only augmentation understood by `gimli` is that which is defined by
+ /// `.eh_frame`.
+ pub fn augmentation(&self) -> Option<&Augmentation> {
+ self.augmentation.as_ref()
+ }
+
+ /// True if this CIE's FDEs have a LSDA.
+ pub fn has_lsda(&self) -> bool {
+ self.augmentation.map_or(false, |a| a.lsda.is_some())
+ }
+
+ /// Return the encoding of the LSDA address for this CIE's FDEs.
+ pub fn lsda_encoding(&self) -> Option<constants::DwEhPe> {
+ self.augmentation.and_then(|a| a.lsda)
+ }
+
+ /// Return the encoding and address of the personality routine handler
+ /// for this CIE's FDEs.
+ pub fn personality_with_encoding(&self) -> Option<(constants::DwEhPe, Pointer)> {
+ self.augmentation.as_ref().and_then(|a| a.personality)
+ }
+
+ /// Return the address of the personality routine handler
+ /// for this CIE's FDEs.
+ pub fn personality(&self) -> Option<Pointer> {
+ self.augmentation
+ .as_ref()
+ .and_then(|a| a.personality)
+ .map(|(_, p)| p)
+ }
+
+ /// Return the encoding of the addresses for this CIE's FDEs.
+ pub fn fde_address_encoding(&self) -> Option<constants::DwEhPe> {
+ self.augmentation.and_then(|a| a.fde_address_encoding)
+ }
+
+ /// True if this CIE's FDEs are trampolines for signal handlers.
+ pub fn is_signal_trampoline(&self) -> bool {
+ self.augmentation.map_or(false, |a| a.is_signal_trampoline)
+ }
+
+ /// > A constant that is factored out of all advance location instructions
+ /// > (see Section 6.4.2.1).
+ pub fn code_alignment_factor(&self) -> u64 {
+ self.code_alignment_factor
+ }
+
+ /// > A constant that is factored out of certain offset instructions (see
+ /// > below). The resulting value is (operand * data_alignment_factor).
+ pub fn data_alignment_factor(&self) -> i64 {
+ self.data_alignment_factor
+ }
+
+ /// > An unsigned ... constant that indicates which column in the rule
+ /// > table represents the return address of the function. Note that this
+ /// > column might not correspond to an actual machine register.
+ pub fn return_address_register(&self) -> Register {
+ self.return_address_register
+ }
+}
+
+/// A partially parsed `FrameDescriptionEntry`.
+///
+/// Fully parsing this FDE requires first parsing its CIE.
+#[derive(Clone, Debug, PartialEq, Eq)]
+pub struct PartialFrameDescriptionEntry<'bases, Section, R>
+where
+ R: Reader,
+ Section: UnwindSection<R>,
+{
+ offset: R::Offset,
+ length: R::Offset,
+ format: Format,
+ cie_offset: Section::Offset,
+ rest: R,
+ section: Section,
+ bases: &'bases BaseAddresses,
+}
+
+impl<'bases, Section, R> PartialFrameDescriptionEntry<'bases, Section, R>
+where
+ R: Reader,
+ Section: UnwindSection<R>,
+{
+ fn parse_partial(
+ section: &Section,
+ bases: &'bases BaseAddresses,
+ input: &mut R,
+ ) -> Result<PartialFrameDescriptionEntry<'bases, Section, R>> {
+ match parse_cfi_entry(bases, section, input)? {
+ Some(CieOrFde::Cie(_)) => Err(Error::NotFdePointer),
+ Some(CieOrFde::Fde(partial)) => Ok(partial),
+ None => Err(Error::NoEntryAtGivenOffset),
+ }
+ }
+
+ /// Fully parse this FDE.
+ ///
+ /// You must provide a function get its associated CIE (either by parsing it
+ /// on demand, or looking it up in some table mapping offsets to CIEs that
+ /// you've already parsed, etc.)
+ pub fn parse<F>(&self, get_cie: F) -> Result<FrameDescriptionEntry<R>>
+ where
+ F: FnMut(&Section, &BaseAddresses, Section::Offset) -> Result<CommonInformationEntry<R>>,
+ {
+ FrameDescriptionEntry::parse_rest(
+ self.offset,
+ self.length,
+ self.format,
+ self.cie_offset,
+ self.rest.clone(),
+ &self.section,
+ self.bases,
+ get_cie,
+ )
+ }
+}
+
+/// A `FrameDescriptionEntry` is a set of CFA instructions for an address range.
+#[derive(Clone, Debug, PartialEq, Eq)]
+pub struct FrameDescriptionEntry<R, Offset = <R as Reader>::Offset>
+where
+ R: Reader<Offset = Offset>,
+ Offset: ReaderOffset,
+{
+ /// The start of this entry within its containing section.
+ offset: Offset,
+
+ /// > A constant that gives the number of bytes of the header and
+ /// > instruction stream for this function, not including the length field
+ /// > itself (see Section 7.2.2). The size of the length field plus the value
+ /// > of length must be an integral multiple of the address size.
+ length: Offset,
+
+ format: Format,
+
+ /// "A constant offset into the .debug_frame section that denotes the CIE
+ /// that is associated with this FDE."
+ ///
+ /// This is the CIE at that offset.
+ cie: CommonInformationEntry<R, Offset>,
+
+ /// > The address of the first location associated with this table entry. If
+ /// > the segment_size field of this FDE's CIE is non-zero, the initial
+ /// > location is preceded by a segment selector of the given length.
+ initial_segment: u64,
+ initial_address: u64,
+
+ /// "The number of bytes of program instructions described by this entry."
+ address_range: u64,
+
+ /// The parsed augmentation data, if we have any.
+ augmentation: Option<AugmentationData>,
+
+ /// "A sequence of table defining instructions that are described below."
+ ///
+ /// This is followed by `DW_CFA_nop` padding until `length` bytes of the
+ /// input are consumed.
+ instructions: R,
+}
+
+impl<R: Reader> FrameDescriptionEntry<R> {
+ #[allow(clippy::too_many_arguments)]
+ fn parse_rest<Section, F>(
+ offset: R::Offset,
+ length: R::Offset,
+ format: Format,
+ cie_pointer: Section::Offset,
+ mut rest: R,
+ section: &Section,
+ bases: &BaseAddresses,
+ mut get_cie: F,
+ ) -> Result<FrameDescriptionEntry<R>>
+ where
+ Section: UnwindSection<R>,
+ F: FnMut(&Section, &BaseAddresses, Section::Offset) -> Result<CommonInformationEntry<R>>,
+ {
+ let cie = get_cie(section, bases, cie_pointer)?;
+
+ let initial_segment = if cie.segment_size > 0 {
+ rest.read_address(cie.segment_size)?
+ } else {
+ 0
+ };
+
+ let mut parameters = PointerEncodingParameters {
+ bases: &bases.eh_frame,
+ func_base: None,
+ address_size: cie.address_size,
+ section: section.section(),
+ };
+
+ let (initial_address, address_range) = Self::parse_addresses(&mut rest, &cie, &parameters)?;
+ parameters.func_base = Some(initial_address);
+
+ let aug_data = if let Some(ref augmentation) = cie.augmentation {
+ Some(AugmentationData::parse(
+ augmentation,
+ &parameters,
+ &mut rest,
+ )?)
+ } else {
+ None
+ };
+
+ let entry = FrameDescriptionEntry {
+ offset,
+ length,
+ format,
+ cie,
+ initial_segment,
+ initial_address,
+ address_range,
+ augmentation: aug_data,
+ instructions: rest,
+ };
+
+ Ok(entry)
+ }
+
+ fn parse_addresses(
+ input: &mut R,
+ cie: &CommonInformationEntry<R>,
+ parameters: &PointerEncodingParameters<R>,
+ ) -> Result<(u64, u64)> {
+ let encoding = cie.augmentation().and_then(|a| a.fde_address_encoding);
+ if let Some(encoding) = encoding {
+ let initial_address = parse_encoded_pointer(encoding, parameters, input)?;
+
+ // Ignore indirection.
+ let initial_address = initial_address.into();
+
+ // Address ranges cannot be relative to anything, so just grab the
+ // data format bits from the encoding.
+ let address_range = parse_encoded_pointer(encoding.format(), parameters, input)?;
+ Ok((initial_address, address_range.into()))
+ } else {
+ let initial_address = input.read_address(cie.address_size)?;
+ let address_range = input.read_address(cie.address_size)?;
+ Ok((initial_address, address_range))
+ }
+ }
+
+ /// Return the table of unwind information for this FDE.
+ #[inline]
+ pub fn rows<'a, 'ctx, Section: UnwindSection<R>, A: UnwindContextStorage<R>>(
+ &self,
+ section: &'a Section,
+ bases: &'a BaseAddresses,
+ ctx: &'ctx mut UnwindContext<R, A>,
+ ) -> Result<UnwindTable<'a, 'ctx, R, A>> {
+ UnwindTable::new(section, bases, ctx, self)
+ }
+
+ /// Find the frame unwind information for the given address.
+ ///
+ /// If found, the unwind information is returned along with the reset
+ /// context in the form `Ok((unwind_info, context))`. If not found,
+ /// `Err(gimli::Error::NoUnwindInfoForAddress)` is returned. If parsing or
+ /// CFI evaluation fails, the error is returned.
+ pub fn unwind_info_for_address<'ctx, Section: UnwindSection<R>, A: UnwindContextStorage<R>>(
+ &self,
+ section: &Section,
+ bases: &BaseAddresses,
+ ctx: &'ctx mut UnwindContext<R, A>,
+ address: u64,
+ ) -> Result<&'ctx UnwindTableRow<R, A>> {
+ let mut table = self.rows(section, bases, ctx)?;
+ while let Some(row) = table.next_row()? {
+ if row.contains(address) {
+ return Ok(table.ctx.row());
+ }
+ }
+ Err(Error::NoUnwindInfoForAddress)
+ }
+}
+
+/// # Signal Safe Methods
+///
+/// These methods are guaranteed not to allocate, acquire locks, or perform any
+/// other signal-unsafe operations.
+#[allow(clippy::len_without_is_empty)]
+impl<R: Reader> FrameDescriptionEntry<R> {
+ /// Get the offset of this entry from the start of its containing section.
+ pub fn offset(&self) -> R::Offset {
+ self.offset
+ }
+
+ /// Get a reference to this FDE's CIE.
+ pub fn cie(&self) -> &CommonInformationEntry<R> {
+ &self.cie
+ }
+
+ /// > A constant that gives the number of bytes of the header and
+ /// > instruction stream for this function, not including the length field
+ /// > itself (see Section 7.2.2). The size of the length field plus the value
+ /// > of length must be an integral multiple of the address size.
+ pub fn entry_len(&self) -> R::Offset {
+ self.length
+ }
+
+ /// Iterate over this FDE's instructions.
+ ///
+ /// Will not include the CIE's initial instructions, if you want those do
+ /// `fde.cie().instructions()` first.
+ ///
+ /// Can be [used with
+ /// `FallibleIterator`](./index.html#using-with-fallibleiterator).
+ pub fn instructions<'a, Section>(
+ &self,
+ section: &'a Section,
+ bases: &'a BaseAddresses,
+ ) -> CallFrameInstructionIter<'a, R>
+ where
+ Section: UnwindSection<R>,
+ {
+ CallFrameInstructionIter {
+ input: self.instructions.clone(),
+ address_encoding: self.cie.augmentation().and_then(|a| a.fde_address_encoding),
+ parameters: PointerEncodingParameters {
+ bases: &bases.eh_frame,
+ func_base: None,
+ address_size: self.cie.address_size,
+ section: section.section(),
+ },
+ }
+ }
+
+ /// The first address for which this entry has unwind information for.
+ pub fn initial_address(&self) -> u64 {
+ self.initial_address
+ }
+
+ /// The number of bytes of instructions that this entry has unwind
+ /// information for.
+ pub fn len(&self) -> u64 {
+ self.address_range
+ }
+
+ /// Return `true` if the given address is within this FDE, `false`
+ /// otherwise.
+ ///
+ /// This is equivalent to `entry.initial_address() <= address <
+ /// entry.initial_address() + entry.len()`.
+ pub fn contains(&self, address: u64) -> bool {
+ let start = self.initial_address();
+ let end = start + self.len();
+ start <= address && address < end
+ }
+
+ /// The address of this FDE's language-specific data area (LSDA), if it has
+ /// any.
+ pub fn lsda(&self) -> Option<Pointer> {
+ self.augmentation.as_ref().and_then(|a| a.lsda)
+ }
+
+ /// Return true if this FDE's function is a trampoline for a signal handler.
+ #[inline]
+ pub fn is_signal_trampoline(&self) -> bool {
+ self.cie().is_signal_trampoline()
+ }
+
+ /// Return the address of the FDE's function's personality routine
+ /// handler. The personality routine does language-specific clean up when
+ /// unwinding the stack frames with the intent to not run them again.
+ #[inline]
+ pub fn personality(&self) -> Option<Pointer> {
+ self.cie().personality()
+ }
+}
+
+/// Specification of what storage should be used for [`UnwindContext`].
+///
+#[cfg_attr(
+ feature = "read",
+ doc = "
+Normally you would only need to use [`StoreOnHeap`], which places the stack
+on the heap using [`Vec`]. This is the default storage type parameter for [`UnwindContext`].
+"
+)]
+///
+/// If you need to avoid [`UnwindContext`] from allocating memory, e.g. for signal safety,
+/// you can provide you own storage specification:
+/// ```rust,no_run
+/// # use gimli::*;
+/// #
+/// # fn foo<'a>(some_fde: gimli::FrameDescriptionEntry<gimli::EndianSlice<'a, gimli::LittleEndian>>)
+/// # -> gimli::Result<()> {
+/// # let eh_frame: gimli::EhFrame<_> = unreachable!();
+/// # let bases = unimplemented!();
+/// #
+/// struct StoreOnStack;
+///
+/// impl<R: Reader> UnwindContextStorage<R> for StoreOnStack {
+/// type Rules = [(Register, RegisterRule<R>); 192];
+/// type Stack = [UnwindTableRow<R, Self>; 4];
+/// }
+///
+/// let mut ctx = UnwindContext::<_, StoreOnStack>::new_in();
+///
+/// // Initialize the context by evaluating the CIE's initial instruction program,
+/// // and generate the unwind table.
+/// let mut table = some_fde.rows(&eh_frame, &bases, &mut ctx)?;
+/// while let Some(row) = table.next_row()? {
+/// // Do stuff with each row...
+/// # let _ = row;
+/// }
+/// # unreachable!()
+/// # }
+/// ```
+pub trait UnwindContextStorage<R: Reader>: Sized {
+ /// The storage used for register rules in a unwind table row.
+ ///
+ /// Note that this is nested within the stack.
+ type Rules: ArrayLike<Item = (Register, RegisterRule<R>)>;
+
+ /// The storage used for unwind table row stack.
+ type Stack: ArrayLike<Item = UnwindTableRow<R, Self>>;
+}
+
+#[cfg(feature = "read")]
+const MAX_RULES: usize = 192;
+
+#[cfg(feature = "read")]
+impl<R: Reader> UnwindContextStorage<R> for StoreOnHeap {
+ type Rules = [(Register, RegisterRule<R>); MAX_RULES];
+ type Stack = Vec<UnwindTableRow<R, Self>>;
+}
+
+/// Common context needed when evaluating the call frame unwinding information.
+///
+/// This structure can be large so it is advisable to place it on the heap.
+/// To avoid re-allocating the context multiple times when evaluating multiple
+/// CFI programs, it can be reused.
+///
+/// ```
+/// use gimli::{UnwindContext, UnwindTable};
+///
+/// # fn foo<'a>(some_fde: gimli::FrameDescriptionEntry<gimli::EndianSlice<'a, gimli::LittleEndian>>)
+/// # -> gimli::Result<()> {
+/// # let eh_frame: gimli::EhFrame<_> = unreachable!();
+/// # let bases = unimplemented!();
+/// // An uninitialized context.
+/// let mut ctx = Box::new(UnwindContext::new());
+///
+/// // Initialize the context by evaluating the CIE's initial instruction program,
+/// // and generate the unwind table.
+/// let mut table = some_fde.rows(&eh_frame, &bases, &mut ctx)?;
+/// while let Some(row) = table.next_row()? {
+/// // Do stuff with each row...
+/// # let _ = row;
+/// }
+/// # unreachable!()
+/// # }
+/// ```
+#[derive(Clone, PartialEq, Eq)]
+pub struct UnwindContext<R: Reader, A: UnwindContextStorage<R> = StoreOnHeap> {
+ // Stack of rows. The last row is the row currently being built by the
+ // program. There is always at least one row. The vast majority of CFI
+ // programs will only ever have one row on the stack.
+ stack: ArrayVec<A::Stack>,
+
+ // If we are evaluating an FDE's instructions, then `is_initialized` will be
+ // `true`. If `initial_rule` is `Some`, then the initial register rules are either
+ // all default rules or have just 1 non-default rule, stored in `initial_rule`.
+ // If it's `None`, `stack[0]` will contain the initial register rules
+ // described by the CIE's initial instructions. These rules are used by
+ // `DW_CFA_restore`. Otherwise, when we are currently evaluating a CIE's
+ // initial instructions, `is_initialized` will be `false` and initial rules
+ // cannot be read.
+ initial_rule: Option<(Register, RegisterRule<R>)>,
+
+ is_initialized: bool,
+}
+
+impl<R: Reader, S: UnwindContextStorage<R>> Debug for UnwindContext<R, S> {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ f.debug_struct("UnwindContext")
+ .field("stack", &self.stack)
+ .field("initial_rule", &self.initial_rule)
+ .field("is_initialized", &self.is_initialized)
+ .finish()
+ }
+}
+
+impl<R: Reader, A: UnwindContextStorage<R>> Default for UnwindContext<R, A> {
+ fn default() -> Self {
+ Self::new_in()
+ }
+}
+
+#[cfg(feature = "read")]
+impl<R: Reader> UnwindContext<R> {
+ /// Construct a new call frame unwinding context.
+ pub fn new() -> Self {
+ Self::new_in()
+ }
+}
+
+/// # Signal Safe Methods
+///
+/// These methods are guaranteed not to allocate, acquire locks, or perform any
+/// other signal-unsafe operations, if an non-allocating storage is used.
+impl<R: Reader, A: UnwindContextStorage<R>> UnwindContext<R, A> {
+ /// Construct a new call frame unwinding context.
+ pub fn new_in() -> Self {
+ let mut ctx = UnwindContext {
+ stack: Default::default(),
+ initial_rule: None,
+ is_initialized: false,
+ };
+ ctx.reset();
+ ctx
+ }
+
+ /// Run the CIE's initial instructions and initialize this `UnwindContext`.
+ fn initialize<Section: UnwindSection<R>>(
+ &mut self,
+ section: &Section,
+ bases: &BaseAddresses,
+ cie: &CommonInformationEntry<R>,
+ ) -> Result<()> {
+ if self.is_initialized {
+ self.reset();
+ }
+
+ let mut table = UnwindTable::new_for_cie(section, bases, self, cie);
+ while let Some(_) = table.next_row()? {}
+
+ self.save_initial_rules()?;
+ Ok(())
+ }
+
+ fn reset(&mut self) {
+ self.stack.clear();
+ self.stack.try_push(UnwindTableRow::default()).unwrap();
+ debug_assert!(self.stack[0].is_default());
+ self.initial_rule = None;
+ self.is_initialized = false;
+ }
+
+ fn row(&self) -> &UnwindTableRow<R, A> {
+ self.stack.last().unwrap()
+ }
+
+ fn row_mut(&mut self) -> &mut UnwindTableRow<R, A> {
+ self.stack.last_mut().unwrap()
+ }
+
+ fn save_initial_rules(&mut self) -> Result<()> {
+ assert_eq!(self.is_initialized, false);
+ self.initial_rule = match *self.stack.last().unwrap().registers.rules {
+ // All rules are default (undefined). In this case just synthesize
+ // an undefined rule.
+ [] => Some((Register(0), RegisterRule::Undefined)),
+ [ref rule] => Some(rule.clone()),
+ _ => {
+ let rules = self.stack.last().unwrap().clone();
+ self.stack
+ .try_insert(0, rules)
+ .map_err(|_| Error::StackFull)?;
+ None
+ }
+ };
+ self.is_initialized = true;
+ Ok(())
+ }
+
+ fn start_address(&self) -> u64 {
+ self.row().start_address
+ }
+
+ fn set_start_address(&mut self, start_address: u64) {
+ let row = self.row_mut();
+ row.start_address = start_address;
+ }
+
+ fn set_register_rule(&mut self, register: Register, rule: RegisterRule<R>) -> Result<()> {
+ let row = self.row_mut();
+ row.registers.set(register, rule)
+ }
+
+ /// Returns `None` if we have not completed evaluation of a CIE's initial
+ /// instructions.
+ fn get_initial_rule(&self, register: Register) -> Option<RegisterRule<R>> {
+ if !self.is_initialized {
+ return None;
+ }
+ Some(match self.initial_rule {
+ None => self.stack[0].registers.get(register),
+ Some((r, ref rule)) if r == register => rule.clone(),
+ _ => RegisterRule::Undefined,
+ })
+ }
+
+ fn set_cfa(&mut self, cfa: CfaRule<R>) {
+ self.row_mut().cfa = cfa;
+ }
+
+ fn cfa_mut(&mut self) -> &mut CfaRule<R> {
+ &mut self.row_mut().cfa
+ }
+
+ fn push_row(&mut self) -> Result<()> {
+ let new_row = self.row().clone();
+ self.stack.try_push(new_row).map_err(|_| Error::StackFull)
+ }
+
+ fn pop_row(&mut self) -> Result<()> {
+ let min_size = if self.is_initialized && self.initial_rule.is_none() {
+ 2
+ } else {
+ 1
+ };
+ if self.stack.len() <= min_size {
+ return Err(Error::PopWithEmptyStack);
+ }
+ self.stack.pop().unwrap();
+ Ok(())
+ }
+}
+
+/// The `UnwindTable` iteratively evaluates a `FrameDescriptionEntry`'s
+/// `CallFrameInstruction` program, yielding the each row one at a time.
+///
+/// > 6.4.1 Structure of Call Frame Information
+/// >
+/// > DWARF supports virtual unwinding by defining an architecture independent
+/// > basis for recording how procedures save and restore registers during their
+/// > lifetimes. This basis must be augmented on some machines with specific
+/// > information that is defined by an architecture specific ABI authoring
+/// > committee, a hardware vendor, or a compiler producer. The body defining a
+/// > specific augmentation is referred to below as the “augmenter.”
+/// >
+/// > Abstractly, this mechanism describes a very large table that has the
+/// > following structure:
+/// >
+/// > <table>
+/// > <tr>
+/// > <th>LOC</th><th>CFA</th><th>R0</th><th>R1</th><td>...</td><th>RN</th>
+/// > </tr>
+/// > <tr>
+/// > <th>L0</th> <td></td> <td></td> <td></td> <td></td> <td></td>
+/// > </tr>
+/// > <tr>
+/// > <th>L1</th> <td></td> <td></td> <td></td> <td></td> <td></td>
+/// > </tr>
+/// > <tr>
+/// > <td>...</td><td></td> <td></td> <td></td> <td></td> <td></td>
+/// > </tr>
+/// > <tr>
+/// > <th>LN</th> <td></td> <td></td> <td></td> <td></td> <td></td>
+/// > </tr>
+/// > </table>
+/// >
+/// > The first column indicates an address for every location that contains code
+/// > in a program. (In shared objects, this is an object-relative offset.) The
+/// > remaining columns contain virtual unwinding rules that are associated with
+/// > the indicated location.
+/// >
+/// > The CFA column defines the rule which computes the Canonical Frame Address
+/// > value; it may be either a register and a signed offset that are added
+/// > together, or a DWARF expression that is evaluated.
+/// >
+/// > The remaining columns are labeled by register number. This includes some
+/// > registers that have special designation on some architectures such as the PC
+/// > and the stack pointer register. (The actual mapping of registers for a
+/// > particular architecture is defined by the augmenter.) The register columns
+/// > contain rules that describe whether a given register has been saved and the
+/// > rule to find the value for the register in the previous frame.
+/// >
+/// > ...
+/// >
+/// > This table would be extremely large if actually constructed as
+/// > described. Most of the entries at any point in the table are identical to
+/// > the ones above them. The whole table can be represented quite compactly by
+/// > recording just the differences starting at the beginning address of each
+/// > subroutine in the program.
+#[derive(Debug)]
+pub struct UnwindTable<'a, 'ctx, R: Reader, A: UnwindContextStorage<R> = StoreOnHeap> {
+ code_alignment_factor: Wrapping<u64>,
+ data_alignment_factor: Wrapping<i64>,
+ next_start_address: u64,
+ last_end_address: u64,
+ returned_last_row: bool,
+ current_row_valid: bool,
+ instructions: CallFrameInstructionIter<'a, R>,
+ ctx: &'ctx mut UnwindContext<R, A>,
+}
+
+/// # Signal Safe Methods
+///
+/// These methods are guaranteed not to allocate, acquire locks, or perform any
+/// other signal-unsafe operations.
+impl<'a, 'ctx, R: Reader, A: UnwindContextStorage<R>> UnwindTable<'a, 'ctx, R, A> {
+ /// Construct a new `UnwindTable` for the given
+ /// `FrameDescriptionEntry`'s CFI unwinding program.
+ pub fn new<Section: UnwindSection<R>>(
+ section: &'a Section,
+ bases: &'a BaseAddresses,
+ ctx: &'ctx mut UnwindContext<R, A>,
+ fde: &FrameDescriptionEntry<R>,
+ ) -> Result<Self> {
+ ctx.initialize(section, bases, fde.cie())?;
+ Ok(Self::new_for_fde(section, bases, ctx, fde))
+ }
+
+ fn new_for_fde<Section: UnwindSection<R>>(
+ section: &'a Section,
+ bases: &'a BaseAddresses,
+ ctx: &'ctx mut UnwindContext<R, A>,
+ fde: &FrameDescriptionEntry<R>,
+ ) -> Self {
+ assert!(ctx.stack.len() >= 1);
+ UnwindTable {
+ code_alignment_factor: Wrapping(fde.cie().code_alignment_factor()),
+ data_alignment_factor: Wrapping(fde.cie().data_alignment_factor()),
+ next_start_address: fde.initial_address(),
+ last_end_address: fde.initial_address().wrapping_add(fde.len()),
+ returned_last_row: false,
+ current_row_valid: false,
+ instructions: fde.instructions(section, bases),
+ ctx,
+ }
+ }
+
+ fn new_for_cie<Section: UnwindSection<R>>(
+ section: &'a Section,
+ bases: &'a BaseAddresses,
+ ctx: &'ctx mut UnwindContext<R, A>,
+ cie: &CommonInformationEntry<R>,
+ ) -> Self {
+ assert!(ctx.stack.len() >= 1);
+ UnwindTable {
+ code_alignment_factor: Wrapping(cie.code_alignment_factor()),
+ data_alignment_factor: Wrapping(cie.data_alignment_factor()),
+ next_start_address: 0,
+ last_end_address: 0,
+ returned_last_row: false,
+ current_row_valid: false,
+ instructions: cie.instructions(section, bases),
+ ctx,
+ }
+ }
+
+ /// Evaluate call frame instructions until the next row of the table is
+ /// completed, and return it.
+ ///
+ /// Unfortunately, this cannot be used with `FallibleIterator` because of
+ /// the restricted lifetime of the yielded item.
+ pub fn next_row(&mut self) -> Result<Option<&UnwindTableRow<R, A>>> {
+ assert!(self.ctx.stack.len() >= 1);
+ self.ctx.set_start_address(self.next_start_address);
+ self.current_row_valid = false;
+
+ loop {
+ match self.instructions.next() {
+ Err(e) => return Err(e),
+
+ Ok(None) => {
+ if self.returned_last_row {
+ return Ok(None);
+ }
+
+ let row = self.ctx.row_mut();
+ row.end_address = self.last_end_address;
+
+ self.returned_last_row = true;
+ self.current_row_valid = true;
+ return Ok(Some(row));
+ }
+
+ Ok(Some(instruction)) => {
+ if self.evaluate(instruction)? {
+ self.current_row_valid = true;
+ return Ok(Some(self.ctx.row()));
+ }
+ }
+ };
+ }
+ }
+
+ /// Returns the current row with the lifetime of the context.
+ pub fn into_current_row(self) -> Option<&'ctx UnwindTableRow<R, A>> {
+ if self.current_row_valid {
+ Some(self.ctx.row())
+ } else {
+ None
+ }
+ }
+
+ /// Evaluate one call frame instruction. Return `Ok(true)` if the row is
+ /// complete, `Ok(false)` otherwise.
+ fn evaluate(&mut self, instruction: CallFrameInstruction<R>) -> Result<bool> {
+ use crate::CallFrameInstruction::*;
+
+ match instruction {
+ // Instructions that complete the current row and advance the
+ // address for the next row.
+ SetLoc { address } => {
+ if address < self.ctx.start_address() {
+ return Err(Error::InvalidAddressRange);
+ }
+
+ self.next_start_address = address;
+ self.ctx.row_mut().end_address = self.next_start_address;
+ return Ok(true);
+ }
+ AdvanceLoc { delta } => {
+ let delta = Wrapping(u64::from(delta)) * self.code_alignment_factor;
+ self.next_start_address = (Wrapping(self.ctx.start_address()) + delta).0;
+ self.ctx.row_mut().end_address = self.next_start_address;
+ return Ok(true);
+ }
+
+ // Instructions that modify the CFA.
+ DefCfa { register, offset } => {
+ self.ctx.set_cfa(CfaRule::RegisterAndOffset {
+ register,
+ offset: offset as i64,
+ });
+ }
+ DefCfaSf {
+ register,
+ factored_offset,
+ } => {
+ let data_align = self.data_alignment_factor;
+ self.ctx.set_cfa(CfaRule::RegisterAndOffset {
+ register,
+ offset: (Wrapping(factored_offset) * data_align).0,
+ });
+ }
+ DefCfaRegister { register } => {
+ if let CfaRule::RegisterAndOffset {
+ register: ref mut reg,
+ ..
+ } = *self.ctx.cfa_mut()
+ {
+ *reg = register;
+ } else {
+ return Err(Error::CfiInstructionInInvalidContext);
+ }
+ }
+ DefCfaOffset { offset } => {
+ if let CfaRule::RegisterAndOffset {
+ offset: ref mut off,
+ ..
+ } = *self.ctx.cfa_mut()
+ {
+ *off = offset as i64;
+ } else {
+ return Err(Error::CfiInstructionInInvalidContext);
+ }
+ }
+ DefCfaOffsetSf { factored_offset } => {
+ if let CfaRule::RegisterAndOffset {
+ offset: ref mut off,
+ ..
+ } = *self.ctx.cfa_mut()
+ {
+ let data_align = self.data_alignment_factor;
+ *off = (Wrapping(factored_offset) * data_align).0;
+ } else {
+ return Err(Error::CfiInstructionInInvalidContext);
+ }
+ }
+ DefCfaExpression { expression } => {
+ self.ctx.set_cfa(CfaRule::Expression(expression));
+ }
+
+ // Instructions that define register rules.
+ Undefined { register } => {
+ self.ctx
+ .set_register_rule(register, RegisterRule::Undefined)?;
+ }
+ SameValue { register } => {
+ self.ctx
+ .set_register_rule(register, RegisterRule::SameValue)?;
+ }
+ Offset {
+ register,
+ factored_offset,
+ } => {
+ let offset = Wrapping(factored_offset as i64) * self.data_alignment_factor;
+ self.ctx
+ .set_register_rule(register, RegisterRule::Offset(offset.0))?;
+ }
+ OffsetExtendedSf {
+ register,
+ factored_offset,
+ } => {
+ let offset = Wrapping(factored_offset) * self.data_alignment_factor;
+ self.ctx
+ .set_register_rule(register, RegisterRule::Offset(offset.0))?;
+ }
+ ValOffset {
+ register,
+ factored_offset,
+ } => {
+ let offset = Wrapping(factored_offset as i64) * self.data_alignment_factor;
+ self.ctx
+ .set_register_rule(register, RegisterRule::ValOffset(offset.0))?;
+ }
+ ValOffsetSf {
+ register,
+ factored_offset,
+ } => {
+ let offset = Wrapping(factored_offset) * self.data_alignment_factor;
+ self.ctx
+ .set_register_rule(register, RegisterRule::ValOffset(offset.0))?;
+ }
+ Register {
+ dest_register,
+ src_register,
+ } => {
+ self.ctx
+ .set_register_rule(dest_register, RegisterRule::Register(src_register))?;
+ }
+ Expression {
+ register,
+ expression,
+ } => {
+ let expression = RegisterRule::Expression(expression);
+ self.ctx.set_register_rule(register, expression)?;
+ }
+ ValExpression {
+ register,
+ expression,
+ } => {
+ let expression = RegisterRule::ValExpression(expression);
+ self.ctx.set_register_rule(register, expression)?;
+ }
+ Restore { register } => {
+ let initial_rule = if let Some(rule) = self.ctx.get_initial_rule(register) {
+ rule
+ } else {
+ // Can't restore the initial rule when we are
+ // evaluating the initial rules!
+ return Err(Error::CfiInstructionInInvalidContext);
+ };
+
+ self.ctx.set_register_rule(register, initial_rule)?;
+ }
+
+ // Row push and pop instructions.
+ RememberState => {
+ self.ctx.push_row()?;
+ }
+ RestoreState => {
+ // Pop state while preserving current location.
+ let start_address = self.ctx.start_address();
+ self.ctx.pop_row()?;
+ self.ctx.set_start_address(start_address);
+ }
+
+ // GNU Extension. Save the size somewhere so the unwinder can use
+ // it when restoring IP
+ ArgsSize { size } => {
+ self.ctx.row_mut().saved_args_size = size;
+ }
+
+ // No operation.
+ Nop => {}
+ };
+
+ Ok(false)
+ }
+}
+
+// We tend to have very few register rules: usually only a couple. Even if we
+// have a rule for every register, on x86-64 with SSE and everything we're
+// talking about ~100 rules. So rather than keeping the rules in a hash map, or
+// a vector indexed by register number (which would lead to filling lots of
+// empty entries), we store them as a vec of (register number, register rule)
+// pairs.
+//
+// Additionally, because every register's default rule is implicitly
+// `RegisterRule::Undefined`, we never store a register's rule in this vec if it
+// is undefined and save a little bit more space and do a little fewer
+// comparisons that way.
+//
+// The maximum number of rules preallocated by libunwind is 97 for AArch64, 128
+// for ARM, and even 188 for MIPS. It is extremely unlikely to encounter this
+// many register rules in practice.
+//
+// See:
+// - https://github.com/libunwind/libunwind/blob/11fd461095ea98f4b3e3a361f5a8a558519363fa/include/tdep-x86_64/dwarf-config.h#L36
+// - https://github.com/libunwind/libunwind/blob/11fd461095ea98f4b3e3a361f5a8a558519363fa/include/tdep-aarch64/dwarf-config.h#L32
+// - https://github.com/libunwind/libunwind/blob/11fd461095ea98f4b3e3a361f5a8a558519363fa/include/tdep-arm/dwarf-config.h#L31
+// - https://github.com/libunwind/libunwind/blob/11fd461095ea98f4b3e3a361f5a8a558519363fa/include/tdep-mips/dwarf-config.h#L31
+struct RegisterRuleMap<R: Reader, S: UnwindContextStorage<R> = StoreOnHeap> {
+ rules: ArrayVec<S::Rules>,
+}
+
+impl<R: Reader, S: UnwindContextStorage<R>> Debug for RegisterRuleMap<R, S> {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ f.debug_struct("RegisterRuleMap")
+ .field("rules", &self.rules)
+ .finish()
+ }
+}
+
+impl<R: Reader, S: UnwindContextStorage<R>> Clone for RegisterRuleMap<R, S> {
+ fn clone(&self) -> Self {
+ Self {
+ rules: self.rules.clone(),
+ }
+ }
+}
+
+impl<R: Reader, S: UnwindContextStorage<R>> Default for RegisterRuleMap<R, S> {
+ fn default() -> Self {
+ RegisterRuleMap {
+ rules: Default::default(),
+ }
+ }
+}
+
+/// # Signal Safe Methods
+///
+/// These methods are guaranteed not to allocate, acquire locks, or perform any
+/// other signal-unsafe operations.
+impl<R: Reader, S: UnwindContextStorage<R>> RegisterRuleMap<R, S> {
+ fn is_default(&self) -> bool {
+ self.rules.is_empty()
+ }
+
+ fn get(&self, register: Register) -> RegisterRule<R> {
+ self.rules
+ .iter()
+ .find(|rule| rule.0 == register)
+ .map(|r| {
+ debug_assert!(r.1.is_defined());
+ r.1.clone()
+ })
+ .unwrap_or(RegisterRule::Undefined)
+ }
+
+ fn set(&mut self, register: Register, rule: RegisterRule<R>) -> Result<()> {
+ if !rule.is_defined() {
+ let idx = self
+ .rules
+ .iter()
+ .enumerate()
+ .find(|&(_, r)| r.0 == register)
+ .map(|(i, _)| i);
+ if let Some(idx) = idx {
+ self.rules.swap_remove(idx);
+ }
+ return Ok(());
+ }
+
+ for &mut (reg, ref mut old_rule) in &mut *self.rules {
+ debug_assert!(old_rule.is_defined());
+ if reg == register {
+ *old_rule = rule;
+ return Ok(());
+ }
+ }
+
+ self.rules
+ .try_push((register, rule))
+ .map_err(|_| Error::TooManyRegisterRules)
+ }
+
+ fn iter(&self) -> RegisterRuleIter<R> {
+ RegisterRuleIter(self.rules.iter())
+ }
+}
+
+impl<'a, R, S: UnwindContextStorage<R>> FromIterator<&'a (Register, RegisterRule<R>)>
+ for RegisterRuleMap<R, S>
+where
+ R: 'a + Reader,
+{
+ fn from_iter<T>(iter: T) -> Self
+ where
+ T: IntoIterator<Item = &'a (Register, RegisterRule<R>)>,
+ {
+ let iter = iter.into_iter();
+ let mut rules = RegisterRuleMap::default();
+ for &(reg, ref rule) in iter.filter(|r| r.1.is_defined()) {
+ rules.set(reg, rule.clone()).expect(
+ "This is only used in tests, impl isn't exposed publicly.
+ If you trip this, fix your test",
+ );
+ }
+ rules
+ }
+}
+
+impl<R, S: UnwindContextStorage<R>> PartialEq for RegisterRuleMap<R, S>
+where
+ R: Reader + PartialEq,
+{
+ fn eq(&self, rhs: &Self) -> bool {
+ for &(reg, ref rule) in &*self.rules {
+ debug_assert!(rule.is_defined());
+ if *rule != rhs.get(reg) {
+ return false;
+ }
+ }
+
+ for &(reg, ref rhs_rule) in &*rhs.rules {
+ debug_assert!(rhs_rule.is_defined());
+ if *rhs_rule != self.get(reg) {
+ return false;
+ }
+ }
+
+ true
+ }
+}
+
+impl<R, S: UnwindContextStorage<R>> Eq for RegisterRuleMap<R, S> where R: Reader + Eq {}
+
+/// An unordered iterator for register rules.
+#[derive(Debug, Clone)]
+pub struct RegisterRuleIter<'iter, R>(::core::slice::Iter<'iter, (Register, RegisterRule<R>)>)
+where
+ R: Reader;
+
+impl<'iter, R: Reader> Iterator for RegisterRuleIter<'iter, R> {
+ type Item = &'iter (Register, RegisterRule<R>);
+
+ fn next(&mut self) -> Option<Self::Item> {
+ self.0.next()
+ }
+}
+
+/// A row in the virtual unwind table that describes how to find the values of
+/// the registers in the *previous* frame for a range of PC addresses.
+#[derive(PartialEq, Eq)]
+pub struct UnwindTableRow<R: Reader, S: UnwindContextStorage<R> = StoreOnHeap> {
+ start_address: u64,
+ end_address: u64,
+ saved_args_size: u64,
+ cfa: CfaRule<R>,
+ registers: RegisterRuleMap<R, S>,
+}
+
+impl<R: Reader, S: UnwindContextStorage<R>> Debug for UnwindTableRow<R, S> {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ f.debug_struct("UnwindTableRow")
+ .field("start_address", &self.start_address)
+ .field("end_address", &self.end_address)
+ .field("saved_args_size", &self.saved_args_size)
+ .field("cfa", &self.cfa)
+ .field("registers", &self.registers)
+ .finish()
+ }
+}
+
+impl<R: Reader, S: UnwindContextStorage<R>> Clone for UnwindTableRow<R, S> {
+ fn clone(&self) -> Self {
+ Self {
+ start_address: self.start_address,
+ end_address: self.end_address,
+ saved_args_size: self.saved_args_size,
+ cfa: self.cfa.clone(),
+ registers: self.registers.clone(),
+ }
+ }
+}
+
+impl<R: Reader, S: UnwindContextStorage<R>> Default for UnwindTableRow<R, S> {
+ fn default() -> Self {
+ UnwindTableRow {
+ start_address: 0,
+ end_address: 0,
+ saved_args_size: 0,
+ cfa: Default::default(),
+ registers: Default::default(),
+ }
+ }
+}
+
+impl<R: Reader, S: UnwindContextStorage<R>> UnwindTableRow<R, S> {
+ fn is_default(&self) -> bool {
+ self.start_address == 0
+ && self.end_address == 0
+ && self.cfa.is_default()
+ && self.registers.is_default()
+ }
+
+ /// Get the starting PC address that this row applies to.
+ pub fn start_address(&self) -> u64 {
+ self.start_address
+ }
+
+ /// Get the end PC address where this row's register rules become
+ /// unapplicable.
+ ///
+ /// In other words, this row describes how to recover the last frame's
+ /// registers for all PCs where `row.start_address() <= PC <
+ /// row.end_address()`. This row does NOT describe how to recover registers
+ /// when `PC == row.end_address()`.
+ pub fn end_address(&self) -> u64 {
+ self.end_address
+ }
+
+ /// Return `true` if the given `address` is within this row's address range,
+ /// `false` otherwise.
+ pub fn contains(&self, address: u64) -> bool {
+ self.start_address <= address && address < self.end_address
+ }
+
+ /// Returns the amount of args currently on the stack.
+ ///
+ /// When unwinding, if the personality function requested a change in IP,
+ /// the SP needs to be adjusted by saved_args_size.
+ pub fn saved_args_size(&self) -> u64 {
+ self.saved_args_size
+ }
+
+ /// Get the canonical frame address (CFA) recovery rule for this row.
+ pub fn cfa(&self) -> &CfaRule<R> {
+ &self.cfa
+ }
+
+ /// Get the register recovery rule for the given register number.
+ ///
+ /// The register number mapping is architecture dependent. For example, in
+ /// the x86-64 ABI the register number mapping is defined in Figure 3.36:
+ ///
+ /// > Figure 3.36: DWARF Register Number Mapping
+ /// >
+ /// > <table>
+ /// > <tr><th>Register Name</th> <th>Number</th> <th>Abbreviation</th></tr>
+ /// > <tr><td>General Purpose Register RAX</td> <td>0</td> <td>%rax</td></tr>
+ /// > <tr><td>General Purpose Register RDX</td> <td>1</td> <td>%rdx</td></tr>
+ /// > <tr><td>General Purpose Register RCX</td> <td>2</td> <td>%rcx</td></tr>
+ /// > <tr><td>General Purpose Register RBX</td> <td>3</td> <td>%rbx</td></tr>
+ /// > <tr><td>General Purpose Register RSI</td> <td>4</td> <td>%rsi</td></tr>
+ /// > <tr><td>General Purpose Register RDI</td> <td>5</td> <td>%rdi</td></tr>
+ /// > <tr><td>General Purpose Register RBP</td> <td>6</td> <td>%rbp</td></tr>
+ /// > <tr><td>Stack Pointer Register RSP</td> <td>7</td> <td>%rsp</td></tr>
+ /// > <tr><td>Extended Integer Registers 8-15</td> <td>8-15</td> <td>%r8-%r15</td></tr>
+ /// > <tr><td>Return Address RA</td> <td>16</td> <td></td></tr>
+ /// > <tr><td>Vector Registers 0–7</td> <td>17-24</td> <td>%xmm0–%xmm7</td></tr>
+ /// > <tr><td>Extended Vector Registers 8–15</td> <td>25-32</td> <td>%xmm8–%xmm15</td></tr>
+ /// > <tr><td>Floating Point Registers 0–7</td> <td>33-40</td> <td>%st0–%st7</td></tr>
+ /// > <tr><td>MMX Registers 0–7</td> <td>41-48</td> <td>%mm0–%mm7</td></tr>
+ /// > <tr><td>Flag Register</td> <td>49</td> <td>%rFLAGS</td></tr>
+ /// > <tr><td>Segment Register ES</td> <td>50</td> <td>%es</td></tr>
+ /// > <tr><td>Segment Register CS</td> <td>51</td> <td>%cs</td></tr>
+ /// > <tr><td>Segment Register SS</td> <td>52</td> <td>%ss</td></tr>
+ /// > <tr><td>Segment Register DS</td> <td>53</td> <td>%ds</td></tr>
+ /// > <tr><td>Segment Register FS</td> <td>54</td> <td>%fs</td></tr>
+ /// > <tr><td>Segment Register GS</td> <td>55</td> <td>%gs</td></tr>
+ /// > <tr><td>Reserved</td> <td>56-57</td> <td></td></tr>
+ /// > <tr><td>FS Base address</td> <td>58</td> <td>%fs.base</td></tr>
+ /// > <tr><td>GS Base address</td> <td>59</td> <td>%gs.base</td></tr>
+ /// > <tr><td>Reserved</td> <td>60-61</td> <td></td></tr>
+ /// > <tr><td>Task Register</td> <td>62</td> <td>%tr</td></tr>
+ /// > <tr><td>LDT Register</td> <td>63</td> <td>%ldtr</td></tr>
+ /// > <tr><td>128-bit Media Control and Status</td> <td>64</td> <td>%mxcsr</td></tr>
+ /// > <tr><td>x87 Control Word</td> <td>65</td> <td>%fcw</td></tr>
+ /// > <tr><td>x87 Status Word</td> <td>66</td> <td>%fsw</td></tr>
+ /// > <tr><td>Upper Vector Registers 16–31</td> <td>67-82</td> <td>%xmm16–%xmm31</td></tr>
+ /// > <tr><td>Reserved</td> <td>83-117</td> <td></td></tr>
+ /// > <tr><td>Vector Mask Registers 0–7</td> <td>118-125</td> <td>%k0–%k7</td></tr>
+ /// > <tr><td>Reserved</td> <td>126-129</td> <td></td></tr>
+ /// > </table>
+ pub fn register(&self, register: Register) -> RegisterRule<R> {
+ self.registers.get(register)
+ }
+
+ /// Iterate over all defined register `(number, rule)` pairs.
+ ///
+ /// The rules are not iterated in any guaranteed order. Any register that
+ /// does not make an appearance in the iterator implicitly has the rule
+ /// `RegisterRule::Undefined`.
+ ///
+ /// ```
+ /// # use gimli::{EndianSlice, LittleEndian, UnwindTableRow};
+ /// # fn foo<'input>(unwind_table_row: UnwindTableRow<EndianSlice<'input, LittleEndian>>) {
+ /// for &(register, ref rule) in unwind_table_row.registers() {
+ /// // ...
+ /// # drop(register); drop(rule);
+ /// }
+ /// # }
+ /// ```
+ pub fn registers(&self) -> RegisterRuleIter<R> {
+ self.registers.iter()
+ }
+}
+
+/// The canonical frame address (CFA) recovery rules.
+#[derive(Clone, Debug, PartialEq, Eq)]
+pub enum CfaRule<R: Reader> {
+ /// The CFA is given offset from the given register's value.
+ RegisterAndOffset {
+ /// The register containing the base value.
+ register: Register,
+ /// The offset from the register's base value.
+ offset: i64,
+ },
+ /// The CFA is obtained by evaluating this `Reader` as a DWARF expression
+ /// program.
+ Expression(Expression<R>),
+}
+
+impl<R: Reader> Default for CfaRule<R> {
+ fn default() -> Self {
+ CfaRule::RegisterAndOffset {
+ register: Register(0),
+ offset: 0,
+ }
+ }
+}
+
+impl<R: Reader> CfaRule<R> {
+ fn is_default(&self) -> bool {
+ match *self {
+ CfaRule::RegisterAndOffset { register, offset } => {
+ register == Register(0) && offset == 0
+ }
+ _ => false,
+ }
+ }
+}
+
+/// An entry in the abstract CFI table that describes how to find the value of a
+/// register.
+///
+/// "The register columns contain rules that describe whether a given register
+/// has been saved and the rule to find the value for the register in the
+/// previous frame."
+#[derive(Clone, Debug, PartialEq, Eq)]
+pub enum RegisterRule<R: Reader> {
+ /// > A register that has this rule has no recoverable value in the previous
+ /// > frame. (By convention, it is not preserved by a callee.)
+ Undefined,
+
+ /// > This register has not been modified from the previous frame. (By
+ /// > convention, it is preserved by the callee, but the callee has not
+ /// > modified it.)
+ SameValue,
+
+ /// "The previous value of this register is saved at the address CFA+N where
+ /// CFA is the current CFA value and N is a signed offset."
+ Offset(i64),
+
+ /// "The previous value of this register is the value CFA+N where CFA is the
+ /// current CFA value and N is a signed offset."
+ ValOffset(i64),
+
+ /// "The previous value of this register is stored in another register
+ /// numbered R."
+ Register(Register),
+
+ /// "The previous value of this register is located at the address produced
+ /// by executing the DWARF expression."
+ Expression(Expression<R>),
+
+ /// "The previous value of this register is the value produced by executing
+ /// the DWARF expression."
+ ValExpression(Expression<R>),
+
+ /// "The rule is defined externally to this specification by the augmenter."
+ Architectural,
+}
+
+impl<R: Reader> RegisterRule<R> {
+ fn is_defined(&self) -> bool {
+ match *self {
+ RegisterRule::Undefined => false,
+ _ => true,
+ }
+ }
+}
+
+/// A parsed call frame instruction.
+#[derive(Clone, Debug, PartialEq, Eq)]
+pub enum CallFrameInstruction<R: Reader> {
+ // 6.4.2.1 Row Creation Methods
+ /// > 1. DW_CFA_set_loc
+ /// >
+ /// > The DW_CFA_set_loc instruction takes a single operand that represents
+ /// > a target address. The required action is to create a new table row
+ /// > using the specified address as the location. All other values in the
+ /// > new row are initially identical to the current row. The new location
+ /// > value is always greater than the current one. If the segment_size
+ /// > field of this FDE's CIE is non- zero, the initial location is preceded
+ /// > by a segment selector of the given length.
+ SetLoc {
+ /// The target address.
+ address: u64,
+ },
+
+ /// The `AdvanceLoc` instruction is used for all of `DW_CFA_advance_loc` and
+ /// `DW_CFA_advance_loc{1,2,4}`.
+ ///
+ /// > 2. DW_CFA_advance_loc
+ /// >
+ /// > The DW_CFA_advance instruction takes a single operand (encoded with
+ /// > the opcode) that represents a constant delta. The required action is
+ /// > to create a new table row with a location value that is computed by
+ /// > taking the current entry’s location value and adding the value of
+ /// > delta * code_alignment_factor. All other values in the new row are
+ /// > initially identical to the current row.
+ AdvanceLoc {
+ /// The delta to be added to the current address.
+ delta: u32,
+ },
+
+ // 6.4.2.2 CFA Definition Methods
+ /// > 1. DW_CFA_def_cfa
+ /// >
+ /// > The DW_CFA_def_cfa instruction takes two unsigned LEB128 operands
+ /// > representing a register number and a (non-factored) offset. The
+ /// > required action is to define the current CFA rule to use the provided
+ /// > register and offset.
+ DefCfa {
+ /// The target register's number.
+ register: Register,
+ /// The non-factored offset.
+ offset: u64,
+ },
+
+ /// > 2. DW_CFA_def_cfa_sf
+ /// >
+ /// > The DW_CFA_def_cfa_sf instruction takes two operands: an unsigned
+ /// > LEB128 value representing a register number and a signed LEB128
+ /// > factored offset. This instruction is identical to DW_CFA_def_cfa
+ /// > except that the second operand is signed and factored. The resulting
+ /// > offset is factored_offset * data_alignment_factor.
+ DefCfaSf {
+ /// The target register's number.
+ register: Register,
+ /// The factored offset.
+ factored_offset: i64,
+ },
+
+ /// > 3. DW_CFA_def_cfa_register
+ /// >
+ /// > The DW_CFA_def_cfa_register instruction takes a single unsigned LEB128
+ /// > operand representing a register number. The required action is to
+ /// > define the current CFA rule to use the provided register (but to keep
+ /// > the old offset). This operation is valid only if the current CFA rule
+ /// > is defined to use a register and offset.
+ DefCfaRegister {
+ /// The target register's number.
+ register: Register,
+ },
+
+ /// > 4. DW_CFA_def_cfa_offset
+ /// >
+ /// > The DW_CFA_def_cfa_offset instruction takes a single unsigned LEB128
+ /// > operand representing a (non-factored) offset. The required action is
+ /// > to define the current CFA rule to use the provided offset (but to keep
+ /// > the old register). This operation is valid only if the current CFA
+ /// > rule is defined to use a register and offset.
+ DefCfaOffset {
+ /// The non-factored offset.
+ offset: u64,
+ },
+
+ /// > 5. DW_CFA_def_cfa_offset_sf
+ /// >
+ /// > The DW_CFA_def_cfa_offset_sf instruction takes a signed LEB128 operand
+ /// > representing a factored offset. This instruction is identical to
+ /// > DW_CFA_def_cfa_offset except that the operand is signed and
+ /// > factored. The resulting offset is factored_offset *
+ /// > data_alignment_factor. This operation is valid only if the current CFA
+ /// > rule is defined to use a register and offset.
+ DefCfaOffsetSf {
+ /// The factored offset.
+ factored_offset: i64,
+ },
+
+ /// > 6. DW_CFA_def_cfa_expression
+ /// >
+ /// > The DW_CFA_def_cfa_expression instruction takes a single operand
+ /// > encoded as a DW_FORM_exprloc value representing a DWARF
+ /// > expression. The required action is to establish that expression as the
+ /// > means by which the current CFA is computed.
+ DefCfaExpression {
+ /// The DWARF expression.
+ expression: Expression<R>,
+ },
+
+ // 6.4.2.3 Register Rule Instructions
+ /// > 1. DW_CFA_undefined
+ /// >
+ /// > The DW_CFA_undefined instruction takes a single unsigned LEB128
+ /// > operand that represents a register number. The required action is to
+ /// > set the rule for the specified register to “undefined.”
+ Undefined {
+ /// The target register's number.
+ register: Register,
+ },
+
+ /// > 2. DW_CFA_same_value
+ /// >
+ /// > The DW_CFA_same_value instruction takes a single unsigned LEB128
+ /// > operand that represents a register number. The required action is to
+ /// > set the rule for the specified register to “same value.”
+ SameValue {
+ /// The target register's number.
+ register: Register,
+ },
+
+ /// The `Offset` instruction represents both `DW_CFA_offset` and
+ /// `DW_CFA_offset_extended`.
+ ///
+ /// > 3. DW_CFA_offset
+ /// >
+ /// > The DW_CFA_offset instruction takes two operands: a register number
+ /// > (encoded with the opcode) and an unsigned LEB128 constant representing
+ /// > a factored offset. The required action is to change the rule for the
+ /// > register indicated by the register number to be an offset(N) rule
+ /// > where the value of N is factored offset * data_alignment_factor.
+ Offset {
+ /// The target register's number.
+ register: Register,
+ /// The factored offset.
+ factored_offset: u64,
+ },
+
+ /// > 5. DW_CFA_offset_extended_sf
+ /// >
+ /// > The DW_CFA_offset_extended_sf instruction takes two operands: an
+ /// > unsigned LEB128 value representing a register number and a signed
+ /// > LEB128 factored offset. This instruction is identical to
+ /// > DW_CFA_offset_extended except that the second operand is signed and
+ /// > factored. The resulting offset is factored_offset *
+ /// > data_alignment_factor.
+ OffsetExtendedSf {
+ /// The target register's number.
+ register: Register,
+ /// The factored offset.
+ factored_offset: i64,
+ },
+
+ /// > 6. DW_CFA_val_offset
+ /// >
+ /// > The DW_CFA_val_offset instruction takes two unsigned LEB128 operands
+ /// > representing a register number and a factored offset. The required
+ /// > action is to change the rule for the register indicated by the
+ /// > register number to be a val_offset(N) rule where the value of N is
+ /// > factored_offset * data_alignment_factor.
+ ValOffset {
+ /// The target register's number.
+ register: Register,
+ /// The factored offset.
+ factored_offset: u64,
+ },
+
+ /// > 7. DW_CFA_val_offset_sf
+ /// >
+ /// > The DW_CFA_val_offset_sf instruction takes two operands: an unsigned
+ /// > LEB128 value representing a register number and a signed LEB128
+ /// > factored offset. This instruction is identical to DW_CFA_val_offset
+ /// > except that the second operand is signed and factored. The resulting
+ /// > offset is factored_offset * data_alignment_factor.
+ ValOffsetSf {
+ /// The target register's number.
+ register: Register,
+ /// The factored offset.
+ factored_offset: i64,
+ },
+
+ /// > 8. DW_CFA_register
+ /// >
+ /// > The DW_CFA_register instruction takes two unsigned LEB128 operands
+ /// > representing register numbers. The required action is to set the rule
+ /// > for the first register to be register(R) where R is the second
+ /// > register.
+ Register {
+ /// The number of the register whose rule is being changed.
+ dest_register: Register,
+ /// The number of the register where the other register's value can be
+ /// found.
+ src_register: Register,
+ },
+
+ /// > 9. DW_CFA_expression
+ /// >
+ /// > The DW_CFA_expression instruction takes two operands: an unsigned
+ /// > LEB128 value representing a register number, and a DW_FORM_block value
+ /// > representing a DWARF expression. The required action is to change the
+ /// > rule for the register indicated by the register number to be an
+ /// > expression(E) rule where E is the DWARF expression. That is, the DWARF
+ /// > expression computes the address. The value of the CFA is pushed on the
+ /// > DWARF evaluation stack prior to execution of the DWARF expression.
+ Expression {
+ /// The target register's number.
+ register: Register,
+ /// The DWARF expression.
+ expression: Expression<R>,
+ },
+
+ /// > 10. DW_CFA_val_expression
+ /// >
+ /// > The DW_CFA_val_expression instruction takes two operands: an unsigned
+ /// > LEB128 value representing a register number, and a DW_FORM_block value
+ /// > representing a DWARF expression. The required action is to change the
+ /// > rule for the register indicated by the register number to be a
+ /// > val_expression(E) rule where E is the DWARF expression. That is, the
+ /// > DWARF expression computes the value of the given register. The value
+ /// > of the CFA is pushed on the DWARF evaluation stack prior to execution
+ /// > of the DWARF expression.
+ ValExpression {
+ /// The target register's number.
+ register: Register,
+ /// The DWARF expression.
+ expression: Expression<R>,
+ },
+
+ /// The `Restore` instruction represents both `DW_CFA_restore` and
+ /// `DW_CFA_restore_extended`.
+ ///
+ /// > 11. DW_CFA_restore
+ /// >
+ /// > The DW_CFA_restore instruction takes a single operand (encoded with
+ /// > the opcode) that represents a register number. The required action is
+ /// > to change the rule for the indicated register to the rule assigned it
+ /// > by the initial_instructions in the CIE.
+ Restore {
+ /// The register to be reset.
+ register: Register,
+ },
+
+ // 6.4.2.4 Row State Instructions
+ /// > 1. DW_CFA_remember_state
+ /// >
+ /// > The DW_CFA_remember_state instruction takes no operands. The required
+ /// > action is to push the set of rules for every register onto an implicit
+ /// > stack.
+ RememberState,
+
+ /// > 2. DW_CFA_restore_state
+ /// >
+ /// > The DW_CFA_restore_state instruction takes no operands. The required
+ /// > action is to pop the set of rules off the implicit stack and place
+ /// > them in the current row.
+ RestoreState,
+
+ /// > DW_CFA_GNU_args_size
+ /// >
+ /// > GNU Extension
+ /// >
+ /// > The DW_CFA_GNU_args_size instruction takes an unsigned LEB128 operand
+ /// > representing an argument size. This instruction specifies the total of
+ /// > the size of the arguments which have been pushed onto the stack.
+ ArgsSize {
+ /// The size of the arguments which have been pushed onto the stack
+ size: u64,
+ },
+
+ // 6.4.2.5 Padding Instruction
+ /// > 1. DW_CFA_nop
+ /// >
+ /// > The DW_CFA_nop instruction has no operands and no required actions. It
+ /// > is used as padding to make a CIE or FDE an appropriate size.
+ Nop,
+}
+
+const CFI_INSTRUCTION_HIGH_BITS_MASK: u8 = 0b1100_0000;
+const CFI_INSTRUCTION_LOW_BITS_MASK: u8 = !CFI_INSTRUCTION_HIGH_BITS_MASK;
+
+impl<R: Reader> CallFrameInstruction<R> {
+ fn parse(
+ input: &mut R,
+ address_encoding: Option<DwEhPe>,
+ parameters: &PointerEncodingParameters<R>,
+ ) -> Result<CallFrameInstruction<R>> {
+ let instruction = input.read_u8()?;
+ let high_bits = instruction & CFI_INSTRUCTION_HIGH_BITS_MASK;
+
+ if high_bits == constants::DW_CFA_advance_loc.0 {
+ let delta = instruction & CFI_INSTRUCTION_LOW_BITS_MASK;
+ return Ok(CallFrameInstruction::AdvanceLoc {
+ delta: u32::from(delta),
+ });
+ }
+
+ if high_bits == constants::DW_CFA_offset.0 {
+ let register = Register((instruction & CFI_INSTRUCTION_LOW_BITS_MASK).into());
+ let offset = input.read_uleb128()?;
+ return Ok(CallFrameInstruction::Offset {
+ register,
+ factored_offset: offset,
+ });
+ }
+
+ if high_bits == constants::DW_CFA_restore.0 {
+ let register = Register((instruction & CFI_INSTRUCTION_LOW_BITS_MASK).into());
+ return Ok(CallFrameInstruction::Restore { register });
+ }
+
+ debug_assert_eq!(high_bits, 0);
+ let instruction = constants::DwCfa(instruction);
+
+ match instruction {
+ constants::DW_CFA_nop => Ok(CallFrameInstruction::Nop),
+
+ constants::DW_CFA_set_loc => {
+ let address = if let Some(encoding) = address_encoding {
+ match parse_encoded_pointer(encoding, parameters, input)? {
+ Pointer::Direct(x) => x,
+ _ => return Err(Error::UnsupportedPointerEncoding),
+ }
+ } else {
+ input.read_address(parameters.address_size)?
+ };
+ Ok(CallFrameInstruction::SetLoc { address })
+ }
+
+ constants::DW_CFA_advance_loc1 => {
+ let delta = input.read_u8()?;
+ Ok(CallFrameInstruction::AdvanceLoc {
+ delta: u32::from(delta),
+ })
+ }
+
+ constants::DW_CFA_advance_loc2 => {
+ let delta = input.read_u16()?;
+ Ok(CallFrameInstruction::AdvanceLoc {
+ delta: u32::from(delta),
+ })
+ }
+
+ constants::DW_CFA_advance_loc4 => {
+ let delta = input.read_u32()?;
+ Ok(CallFrameInstruction::AdvanceLoc { delta })
+ }
+
+ constants::DW_CFA_offset_extended => {
+ let register = input.read_uleb128().and_then(Register::from_u64)?;
+ let offset = input.read_uleb128()?;
+ Ok(CallFrameInstruction::Offset {
+ register,
+ factored_offset: offset,
+ })
+ }
+
+ constants::DW_CFA_restore_extended => {
+ let register = input.read_uleb128().and_then(Register::from_u64)?;
+ Ok(CallFrameInstruction::Restore { register })
+ }
+
+ constants::DW_CFA_undefined => {
+ let register = input.read_uleb128().and_then(Register::from_u64)?;
+ Ok(CallFrameInstruction::Undefined { register })
+ }
+
+ constants::DW_CFA_same_value => {
+ let register = input.read_uleb128().and_then(Register::from_u64)?;
+ Ok(CallFrameInstruction::SameValue { register })
+ }
+
+ constants::DW_CFA_register => {
+ let dest = input.read_uleb128().and_then(Register::from_u64)?;
+ let src = input.read_uleb128().and_then(Register::from_u64)?;
+ Ok(CallFrameInstruction::Register {
+ dest_register: dest,
+ src_register: src,
+ })
+ }
+
+ constants::DW_CFA_remember_state => Ok(CallFrameInstruction::RememberState),
+
+ constants::DW_CFA_restore_state => Ok(CallFrameInstruction::RestoreState),
+
+ constants::DW_CFA_def_cfa => {
+ let register = input.read_uleb128().and_then(Register::from_u64)?;
+ let offset = input.read_uleb128()?;
+ Ok(CallFrameInstruction::DefCfa { register, offset })
+ }
+
+ constants::DW_CFA_def_cfa_register => {
+ let register = input.read_uleb128().and_then(Register::from_u64)?;
+ Ok(CallFrameInstruction::DefCfaRegister { register })
+ }
+
+ constants::DW_CFA_def_cfa_offset => {
+ let offset = input.read_uleb128()?;
+ Ok(CallFrameInstruction::DefCfaOffset { offset })
+ }
+
+ constants::DW_CFA_def_cfa_expression => {
+ let len = input.read_uleb128().and_then(R::Offset::from_u64)?;
+ let expression = input.split(len)?;
+ Ok(CallFrameInstruction::DefCfaExpression {
+ expression: Expression(expression),
+ })
+ }
+
+ constants::DW_CFA_expression => {
+ let register = input.read_uleb128().and_then(Register::from_u64)?;
+ let len = input.read_uleb128().and_then(R::Offset::from_u64)?;
+ let expression = input.split(len)?;
+ Ok(CallFrameInstruction::Expression {
+ register,
+ expression: Expression(expression),
+ })
+ }
+
+ constants::DW_CFA_offset_extended_sf => {
+ let register = input.read_uleb128().and_then(Register::from_u64)?;
+ let offset = input.read_sleb128()?;
+ Ok(CallFrameInstruction::OffsetExtendedSf {
+ register,
+ factored_offset: offset,
+ })
+ }
+
+ constants::DW_CFA_def_cfa_sf => {
+ let register = input.read_uleb128().and_then(Register::from_u64)?;
+ let offset = input.read_sleb128()?;
+ Ok(CallFrameInstruction::DefCfaSf {
+ register,
+ factored_offset: offset,
+ })
+ }
+
+ constants::DW_CFA_def_cfa_offset_sf => {
+ let offset = input.read_sleb128()?;
+ Ok(CallFrameInstruction::DefCfaOffsetSf {
+ factored_offset: offset,
+ })
+ }
+
+ constants::DW_CFA_val_offset => {
+ let register = input.read_uleb128().and_then(Register::from_u64)?;
+ let offset = input.read_uleb128()?;
+ Ok(CallFrameInstruction::ValOffset {
+ register,
+ factored_offset: offset,
+ })
+ }
+
+ constants::DW_CFA_val_offset_sf => {
+ let register = input.read_uleb128().and_then(Register::from_u64)?;
+ let offset = input.read_sleb128()?;
+ Ok(CallFrameInstruction::ValOffsetSf {
+ register,
+ factored_offset: offset,
+ })
+ }
+
+ constants::DW_CFA_val_expression => {
+ let register = input.read_uleb128().and_then(Register::from_u64)?;
+ let len = input.read_uleb128().and_then(R::Offset::from_u64)?;
+ let expression = input.split(len)?;
+ Ok(CallFrameInstruction::ValExpression {
+ register,
+ expression: Expression(expression),
+ })
+ }
+
+ constants::DW_CFA_GNU_args_size => {
+ let size = input.read_uleb128()?;
+ Ok(CallFrameInstruction::ArgsSize { size })
+ }
+
+ otherwise => Err(Error::UnknownCallFrameInstruction(otherwise)),
+ }
+ }
+}
+
+/// A lazy iterator parsing call frame instructions.
+///
+/// Can be [used with
+/// `FallibleIterator`](./index.html#using-with-fallibleiterator).
+#[derive(Clone, Debug)]
+pub struct CallFrameInstructionIter<'a, R: Reader> {
+ input: R,
+ address_encoding: Option<constants::DwEhPe>,
+ parameters: PointerEncodingParameters<'a, R>,
+}
+
+impl<'a, R: Reader> CallFrameInstructionIter<'a, R> {
+ /// Parse the next call frame instruction.
+ pub fn next(&mut self) -> Result<Option<CallFrameInstruction<R>>> {
+ if self.input.is_empty() {
+ return Ok(None);
+ }
+
+ match CallFrameInstruction::parse(&mut self.input, self.address_encoding, &self.parameters)
+ {
+ Ok(instruction) => Ok(Some(instruction)),
+ Err(e) => {
+ self.input.empty();
+ Err(e)
+ }
+ }
+ }
+}
+
+#[cfg(feature = "fallible-iterator")]
+impl<'a, R: Reader> fallible_iterator::FallibleIterator for CallFrameInstructionIter<'a, R> {
+ type Item = CallFrameInstruction<R>;
+ type Error = Error;
+
+ fn next(&mut self) -> ::core::result::Result<Option<Self::Item>, Self::Error> {
+ CallFrameInstructionIter::next(self)
+ }
+}
+
+/// Parse a `DW_EH_PE_*` pointer encoding.
+#[doc(hidden)]
+#[inline]
+fn parse_pointer_encoding<R: Reader>(input: &mut R) -> Result<constants::DwEhPe> {
+ let eh_pe = input.read_u8()?;
+ let eh_pe = constants::DwEhPe(eh_pe);
+
+ if eh_pe.is_valid_encoding() {
+ Ok(eh_pe)
+ } else {
+ Err(Error::UnknownPointerEncoding)
+ }
+}
+
+/// A decoded pointer.
+#[derive(Copy, Clone, Debug, PartialEq, Eq)]
+pub enum Pointer {
+ /// This value is the decoded pointer value.
+ Direct(u64),
+
+ /// This value is *not* the pointer value, but points to the address of
+ /// where the real pointer value lives. In other words, deref this pointer
+ /// to get the real pointer value.
+ ///
+ /// Chase this pointer at your own risk: do you trust the DWARF data it came
+ /// from?
+ Indirect(u64),
+}
+
+impl Default for Pointer {
+ #[inline]
+ fn default() -> Self {
+ Pointer::Direct(0)
+ }
+}
+
+impl Into<u64> for Pointer {
+ #[inline]
+ fn into(self) -> u64 {
+ match self {
+ Pointer::Direct(p) | Pointer::Indirect(p) => p,
+ }
+ }
+}
+
+impl Pointer {
+ #[inline]
+ fn new(encoding: constants::DwEhPe, address: u64) -> Pointer {
+ if encoding.is_indirect() {
+ Pointer::Indirect(address)
+ } else {
+ Pointer::Direct(address)
+ }
+ }
+}
+
+#[derive(Clone, Debug)]
+struct PointerEncodingParameters<'a, R: Reader> {
+ bases: &'a SectionBaseAddresses,
+ func_base: Option<u64>,
+ address_size: u8,
+ section: &'a R,
+}
+
+fn parse_encoded_pointer<R: Reader>(
+ encoding: constants::DwEhPe,
+ parameters: &PointerEncodingParameters<R>,
+ input: &mut R,
+) -> Result<Pointer> {
+ // TODO: check this once only in parse_pointer_encoding
+ if !encoding.is_valid_encoding() {
+ return Err(Error::UnknownPointerEncoding);
+ }
+
+ if encoding == constants::DW_EH_PE_omit {
+ return Err(Error::CannotParseOmitPointerEncoding);
+ }
+
+ let base = match encoding.application() {
+ constants::DW_EH_PE_absptr => 0,
+ constants::DW_EH_PE_pcrel => {
+ if let Some(section_base) = parameters.bases.section {
+ let offset_from_section = input.offset_from(parameters.section);
+ section_base.wrapping_add(offset_from_section.into_u64())
+ } else {
+ return Err(Error::PcRelativePointerButSectionBaseIsUndefined);
+ }
+ }
+ constants::DW_EH_PE_textrel => {
+ if let Some(text) = parameters.bases.text {
+ text
+ } else {
+ return Err(Error::TextRelativePointerButTextBaseIsUndefined);
+ }
+ }
+ constants::DW_EH_PE_datarel => {
+ if let Some(data) = parameters.bases.data {
+ data
+ } else {
+ return Err(Error::DataRelativePointerButDataBaseIsUndefined);
+ }
+ }
+ constants::DW_EH_PE_funcrel => {
+ if let Some(func) = parameters.func_base {
+ func
+ } else {
+ return Err(Error::FuncRelativePointerInBadContext);
+ }
+ }
+ constants::DW_EH_PE_aligned => return Err(Error::UnsupportedPointerEncoding),
+ _ => unreachable!(),
+ };
+
+ let offset = match encoding.format() {
+ // Unsigned variants.
+ constants::DW_EH_PE_absptr => input.read_address(parameters.address_size),
+ constants::DW_EH_PE_uleb128 => input.read_uleb128(),
+ constants::DW_EH_PE_udata2 => input.read_u16().map(u64::from),
+ constants::DW_EH_PE_udata4 => input.read_u32().map(u64::from),
+ constants::DW_EH_PE_udata8 => input.read_u64(),
+
+ // Signed variants. Here we sign extend the values (happens by
+ // default when casting a signed integer to a larger range integer
+ // in Rust), return them as u64, and rely on wrapping addition to do
+ // the right thing when adding these offsets to their bases.
+ constants::DW_EH_PE_sleb128 => input.read_sleb128().map(|a| a as u64),
+ constants::DW_EH_PE_sdata2 => input.read_i16().map(|a| a as u64),
+ constants::DW_EH_PE_sdata4 => input.read_i32().map(|a| a as u64),
+ constants::DW_EH_PE_sdata8 => input.read_i64().map(|a| a as u64),
+
+ // That was all of the valid encoding formats.
+ _ => unreachable!(),
+ }?;
+
+ Ok(Pointer::new(encoding, base.wrapping_add(offset)))
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+ use super::{parse_cfi_entry, AugmentationData, RegisterRuleMap, UnwindContext};
+ use crate::common::Format;
+ use crate::constants;
+ use crate::endianity::{BigEndian, Endianity, LittleEndian, NativeEndian};
+ use crate::read::{
+ EndianSlice, Error, Expression, Pointer, ReaderOffsetId, Result, Section as ReadSection,
+ };
+ use crate::test_util::GimliSectionMethods;
+ use alloc::boxed::Box;
+ use alloc::vec::Vec;
+ use core::marker::PhantomData;
+ use core::mem;
+ use core::u64;
+ use test_assembler::{Endian, Label, LabelMaker, LabelOrNum, Section, ToLabelOrNum};
+
+ // Ensure each test tries to read the same section kind that it wrote.
+ #[derive(Clone, Copy)]
+ struct SectionKind<Section>(PhantomData<Section>);
+
+ impl<T> SectionKind<T> {
+ fn endian<'input, E>(self) -> Endian
+ where
+ E: Endianity,
+ T: UnwindSection<EndianSlice<'input, E>>,
+ T::Offset: UnwindOffset<usize>,
+ {
+ if E::default().is_big_endian() {
+ Endian::Big
+ } else {
+ Endian::Little
+ }
+ }
+
+ fn section<'input, E>(self, contents: &'input [u8]) -> T
+ where
+ E: Endianity,
+ T: UnwindSection<EndianSlice<'input, E>> + ReadSection<EndianSlice<'input, E>>,
+ T::Offset: UnwindOffset<usize>,
+ {
+ EndianSlice::new(contents, E::default()).into()
+ }
+ }
+
+ fn debug_frame_le<'a>() -> SectionKind<DebugFrame<EndianSlice<'a, LittleEndian>>> {
+ SectionKind(PhantomData)
+ }
+
+ fn debug_frame_be<'a>() -> SectionKind<DebugFrame<EndianSlice<'a, BigEndian>>> {
+ SectionKind(PhantomData)
+ }
+
+ fn eh_frame_le<'a>() -> SectionKind<EhFrame<EndianSlice<'a, LittleEndian>>> {
+ SectionKind(PhantomData)
+ }
+
+ fn parse_fde<Section, O, F, R>(
+ section: Section,
+ input: &mut R,
+ get_cie: F,
+ ) -> Result<FrameDescriptionEntry<R>>
+ where
+ R: Reader,
+ Section: UnwindSection<R, Offset = O>,
+ O: UnwindOffset<R::Offset>,
+ F: FnMut(&Section, &BaseAddresses, O) -> Result<CommonInformationEntry<R>>,
+ {
+ let bases = Default::default();
+ match parse_cfi_entry(&bases, &section, input) {
+ Ok(Some(CieOrFde::Fde(partial))) => partial.parse(get_cie),
+ Ok(_) => Err(Error::NoEntryAtGivenOffset),
+ Err(e) => Err(e),
+ }
+ }
+
+ // Mixin methods for `Section` to help define binary test data.
+
+ trait CfiSectionMethods: GimliSectionMethods {
+ fn cie<'aug, 'input, E, T>(
+ self,
+ _kind: SectionKind<T>,
+ augmentation: Option<&'aug str>,
+ cie: &mut CommonInformationEntry<EndianSlice<'input, E>>,
+ ) -> Self
+ where
+ E: Endianity,
+ T: UnwindSection<EndianSlice<'input, E>>,
+ T::Offset: UnwindOffset;
+ fn fde<'a, 'input, E, T, L>(
+ self,
+ _kind: SectionKind<T>,
+ cie_offset: L,
+ fde: &mut FrameDescriptionEntry<EndianSlice<'input, E>>,
+ ) -> Self
+ where
+ E: Endianity,
+ T: UnwindSection<EndianSlice<'input, E>>,
+ T::Offset: UnwindOffset,
+ L: ToLabelOrNum<'a, u64>;
+ }
+
+ impl CfiSectionMethods for Section {
+ fn cie<'aug, 'input, E, T>(
+ self,
+ _kind: SectionKind<T>,
+ augmentation: Option<&'aug str>,
+ cie: &mut CommonInformationEntry<EndianSlice<'input, E>>,
+ ) -> Self
+ where
+ E: Endianity,
+ T: UnwindSection<EndianSlice<'input, E>>,
+ T::Offset: UnwindOffset,
+ {
+ cie.offset = self.size() as _;
+ let length = Label::new();
+ let start = Label::new();
+ let end = Label::new();
+
+ let section = match cie.format {
+ Format::Dwarf32 => self.D32(&length).mark(&start).D32(0xffff_ffff),
+ Format::Dwarf64 => {
+ let section = self.D32(0xffff_ffff);
+ section.D64(&length).mark(&start).D64(0xffff_ffff_ffff_ffff)
+ }
+ };
+
+ let mut section = section.D8(cie.version);
+
+ if let Some(augmentation) = augmentation {
+ section = section.append_bytes(augmentation.as_bytes());
+ }
+
+ // Null terminator for augmentation string.
+ let section = section.D8(0);
+
+ let section = if T::has_address_and_segment_sizes(cie.version) {
+ section.D8(cie.address_size).D8(cie.segment_size)
+ } else {
+ section
+ };
+
+ let section = section
+ .uleb(cie.code_alignment_factor)
+ .sleb(cie.data_alignment_factor)
+ .uleb(cie.return_address_register.0.into())
+ .append_bytes(cie.initial_instructions.into())
+ .mark(&end);
+
+ cie.length = (&end - &start) as usize;
+ length.set_const(cie.length as u64);
+
+ section
+ }
+
+ fn fde<'a, 'input, E, T, L>(
+ self,
+ _kind: SectionKind<T>,
+ cie_offset: L,
+ fde: &mut FrameDescriptionEntry<EndianSlice<'input, E>>,
+ ) -> Self
+ where
+ E: Endianity,
+ T: UnwindSection<EndianSlice<'input, E>>,
+ T::Offset: UnwindOffset,
+ L: ToLabelOrNum<'a, u64>,
+ {
+ fde.offset = self.size() as _;
+ let length = Label::new();
+ let start = Label::new();
+ let end = Label::new();
+
+ assert_eq!(fde.format, fde.cie.format);
+
+ let section = match T::cie_offset_encoding(fde.format) {
+ CieOffsetEncoding::U32 => {
+ let section = self.D32(&length).mark(&start);
+ match cie_offset.to_labelornum() {
+ LabelOrNum::Label(ref l) => section.D32(l),
+ LabelOrNum::Num(o) => section.D32(o as u32),
+ }
+ }
+ CieOffsetEncoding::U64 => {
+ let section = self.D32(0xffff_ffff);
+ section.D64(&length).mark(&start).D64(cie_offset)
+ }
+ };
+
+ let section = match fde.cie.segment_size {
+ 0 => section,
+ 4 => section.D32(fde.initial_segment as u32),
+ 8 => section.D64(fde.initial_segment),
+ x => panic!("Unsupported test segment size: {}", x),
+ };
+
+ let section = match fde.cie.address_size {
+ 4 => section
+ .D32(fde.initial_address() as u32)
+ .D32(fde.len() as u32),
+ 8 => section.D64(fde.initial_address()).D64(fde.len()),
+ x => panic!("Unsupported address size: {}", x),
+ };
+
+ let section = if let Some(ref augmentation) = fde.augmentation {
+ let cie_aug = fde
+ .cie
+ .augmentation
+ .expect("FDE has augmentation, but CIE doesn't");
+
+ if let Some(lsda) = augmentation.lsda {
+ // We only support writing `DW_EH_PE_absptr` here.
+ assert_eq!(
+ cie_aug
+ .lsda
+ .expect("FDE has lsda, but CIE doesn't")
+ .format(),
+ constants::DW_EH_PE_absptr
+ );
+
+ // Augmentation data length
+ let section = section.uleb(u64::from(fde.cie.address_size));
+ match fde.cie.address_size {
+ 4 => section.D32({
+ let x: u64 = lsda.into();
+ x as u32
+ }),
+ 8 => section.D64({
+ let x: u64 = lsda.into();
+ x
+ }),
+ x => panic!("Unsupported address size: {}", x),
+ }
+ } else {
+ // Even if we don't have any augmentation data, if there is
+ // an augmentation defined, we need to put the length in.
+ section.uleb(0)
+ }
+ } else {
+ section
+ };
+
+ let section = section.append_bytes(fde.instructions.into()).mark(&end);
+
+ fde.length = (&end - &start) as usize;
+ length.set_const(fde.length as u64);
+
+ section
+ }
+ }
+
+ trait ResultExt {
+ fn map_eof(self, input: &[u8]) -> Self;
+ }
+
+ impl<T> ResultExt for Result<T> {
+ fn map_eof(self, input: &[u8]) -> Self {
+ match self {
+ Err(Error::UnexpectedEof(id)) => {
+ let id = ReaderOffsetId(id.0 - input.as_ptr() as u64);
+ Err(Error::UnexpectedEof(id))
+ }
+ r => r,
+ }
+ }
+ }
+
+ #[allow(clippy::type_complexity)]
+ #[allow(clippy::needless_pass_by_value)]
+ fn assert_parse_cie<'input, E>(
+ kind: SectionKind<DebugFrame<EndianSlice<'input, E>>>,
+ section: Section,
+ address_size: u8,
+ expected: Result<(
+ EndianSlice<'input, E>,
+ CommonInformationEntry<EndianSlice<'input, E>>,
+ )>,
+ ) where
+ E: Endianity,
+ {
+ let section = section.get_contents().unwrap();
+ let mut debug_frame = kind.section(&section);
+ debug_frame.set_address_size(address_size);
+ let input = &mut EndianSlice::new(&section, E::default());
+ let bases = Default::default();
+ let result = CommonInformationEntry::parse(&bases, &debug_frame, input);
+ let result = result.map(|cie| (*input, cie)).map_eof(&section);
+ assert_eq!(result, expected);
+ }
+
+ #[test]
+ fn test_parse_cie_incomplete_length_32() {
+ let kind = debug_frame_le();
+ let section = Section::with_endian(kind.endian()).L16(5);
+ assert_parse_cie(
+ kind,
+ section,
+ 8,
+ Err(Error::UnexpectedEof(ReaderOffsetId(0))),
+ );
+ }
+
+ #[test]
+ fn test_parse_cie_incomplete_length_64() {
+ let kind = debug_frame_le();
+ let section = Section::with_endian(kind.endian())
+ .L32(0xffff_ffff)
+ .L32(12345);
+ assert_parse_cie(
+ kind,
+ section,
+ 8,
+ Err(Error::UnexpectedEof(ReaderOffsetId(4))),
+ );
+ }
+
+ #[test]
+ fn test_parse_cie_incomplete_id_32() {
+ let kind = debug_frame_be();
+ let section = Section::with_endian(kind.endian())
+ // The length is not large enough to contain the ID.
+ .B32(3)
+ .B32(0xffff_ffff);
+ assert_parse_cie(
+ kind,
+ section,
+ 8,
+ Err(Error::UnexpectedEof(ReaderOffsetId(4))),
+ );
+ }
+
+ #[test]
+ fn test_parse_cie_bad_id_32() {
+ let kind = debug_frame_be();
+ let section = Section::with_endian(kind.endian())
+ // Initial length
+ .B32(4)
+ // Not the CIE Id.
+ .B32(0xbad1_bad2);
+ assert_parse_cie(kind, section, 8, Err(Error::NotCieId));
+ }
+
+ #[test]
+ fn test_parse_cie_32_bad_version() {
+ let mut cie = CommonInformationEntry {
+ offset: 0,
+ length: 0,
+ format: Format::Dwarf32,
+ version: 99,
+ augmentation: None,
+ address_size: 4,
+ segment_size: 0,
+ code_alignment_factor: 1,
+ data_alignment_factor: 2,
+ return_address_register: Register(3),
+ initial_instructions: EndianSlice::new(&[], LittleEndian),
+ };
+
+ let kind = debug_frame_le();
+ let section = Section::with_endian(kind.endian()).cie(kind, None, &mut cie);
+ assert_parse_cie(kind, section, 4, Err(Error::UnknownVersion(99)));
+ }
+
+ #[test]
+ fn test_parse_cie_unknown_augmentation() {
+ let length = Label::new();
+ let start = Label::new();
+ let end = Label::new();
+
+ let augmentation = Some("replicant");
+ let expected_rest = [1, 2, 3];
+
+ let kind = debug_frame_le();
+ let section = Section::with_endian(kind.endian())
+ // Initial length
+ .L32(&length)
+ .mark(&start)
+ // CIE Id
+ .L32(0xffff_ffff)
+ // Version
+ .D8(4)
+ // Augmentation
+ .append_bytes(augmentation.unwrap().as_bytes())
+ // Null terminator
+ .D8(0)
+ // Extra augmented data that we can't understand.
+ .L32(1)
+ .L32(2)
+ .L32(3)
+ .L32(4)
+ .L32(5)
+ .L32(6)
+ .mark(&end)
+ .append_bytes(&expected_rest);
+
+ let expected_length = (&end - &start) as u64;
+ length.set_const(expected_length);
+
+ assert_parse_cie(kind, section, 8, Err(Error::UnknownAugmentation));
+ }
+
+ fn test_parse_cie(format: Format, version: u8, address_size: u8) {
+ let expected_rest = [1, 2, 3, 4, 5, 6, 7, 8, 9];
+ let expected_instrs: Vec<_> = (0..4).map(|_| constants::DW_CFA_nop.0).collect();
+
+ let mut cie = CommonInformationEntry {
+ offset: 0,
+ length: 0,
+ format,
+ version,
+ augmentation: None,
+ address_size,
+ segment_size: 0,
+ code_alignment_factor: 16,
+ data_alignment_factor: 32,
+ return_address_register: Register(1),
+ initial_instructions: EndianSlice::new(&expected_instrs, LittleEndian),
+ };
+
+ let kind = debug_frame_le();
+ let section = Section::with_endian(kind.endian())
+ .cie(kind, None, &mut cie)
+ .append_bytes(&expected_rest);
+
+ assert_parse_cie(
+ kind,
+ section,
+ address_size,
+ Ok((EndianSlice::new(&expected_rest, LittleEndian), cie)),
+ );
+ }
+
+ #[test]
+ fn test_parse_cie_32_ok() {
+ test_parse_cie(Format::Dwarf32, 1, 4);
+ test_parse_cie(Format::Dwarf32, 1, 8);
+ test_parse_cie(Format::Dwarf32, 4, 4);
+ test_parse_cie(Format::Dwarf32, 4, 8);
+ }
+
+ #[test]
+ fn test_parse_cie_64_ok() {
+ test_parse_cie(Format::Dwarf64, 1, 4);
+ test_parse_cie(Format::Dwarf64, 1, 8);
+ test_parse_cie(Format::Dwarf64, 4, 4);
+ test_parse_cie(Format::Dwarf64, 4, 8);
+ }
+
+ #[test]
+ fn test_parse_cie_length_too_big() {
+ let expected_instrs: Vec<_> = (0..13).map(|_| constants::DW_CFA_nop.0).collect();
+
+ let mut cie = CommonInformationEntry {
+ offset: 0,
+ length: 0,
+ format: Format::Dwarf32,
+ version: 4,
+ augmentation: None,
+ address_size: 4,
+ segment_size: 0,
+ code_alignment_factor: 0,
+ data_alignment_factor: 0,
+ return_address_register: Register(3),
+ initial_instructions: EndianSlice::new(&expected_instrs, LittleEndian),
+ };
+
+ let kind = debug_frame_le();
+ let section = Section::with_endian(kind.endian()).cie(kind, None, &mut cie);
+
+ let mut contents = section.get_contents().unwrap();
+
+ // Overwrite the length to be too big.
+ contents[0] = 0;
+ contents[1] = 0;
+ contents[2] = 0;
+ contents[3] = 255;
+
+ let debug_frame = DebugFrame::new(&contents, LittleEndian);
+ let bases = Default::default();
+ assert_eq!(
+ CommonInformationEntry::parse(
+ &bases,
+ &debug_frame,
+ &mut EndianSlice::new(&contents, LittleEndian)
+ )
+ .map_eof(&contents),
+ Err(Error::UnexpectedEof(ReaderOffsetId(4)))
+ );
+ }
+
+ #[test]
+ fn test_parse_fde_incomplete_length_32() {
+ let kind = debug_frame_le();
+ let section = Section::with_endian(kind.endian()).L16(5);
+ let section = section.get_contents().unwrap();
+ let debug_frame = kind.section(&section);
+ let rest = &mut EndianSlice::new(&section, LittleEndian);
+ assert_eq!(
+ parse_fde(debug_frame, rest, UnwindSection::cie_from_offset).map_eof(&section),
+ Err(Error::UnexpectedEof(ReaderOffsetId(0)))
+ );
+ }
+
+ #[test]
+ fn test_parse_fde_incomplete_length_64() {
+ let kind = debug_frame_le();
+ let section = Section::with_endian(kind.endian())
+ .L32(0xffff_ffff)
+ .L32(12345);
+ let section = section.get_contents().unwrap();
+ let debug_frame = kind.section(&section);
+ let rest = &mut EndianSlice::new(&section, LittleEndian);
+ assert_eq!(
+ parse_fde(debug_frame, rest, UnwindSection::cie_from_offset).map_eof(&section),
+ Err(Error::UnexpectedEof(ReaderOffsetId(4)))
+ );
+ }
+
+ #[test]
+ fn test_parse_fde_incomplete_cie_pointer_32() {
+ let kind = debug_frame_be();
+ let section = Section::with_endian(kind.endian())
+ // The length is not large enough to contain the CIE pointer.
+ .B32(3)
+ .B32(1994);
+ let section = section.get_contents().unwrap();
+ let debug_frame = kind.section(&section);
+ let rest = &mut EndianSlice::new(&section, BigEndian);
+ assert_eq!(
+ parse_fde(debug_frame, rest, UnwindSection::cie_from_offset).map_eof(&section),
+ Err(Error::UnexpectedEof(ReaderOffsetId(4)))
+ );
+ }
+
+ #[test]
+ fn test_parse_fde_32_ok() {
+ let expected_rest = [1, 2, 3, 4, 5, 6, 7, 8, 9];
+ let cie_offset = 0xbad0_bad1;
+ let expected_instrs: Vec<_> = (0..7).map(|_| constants::DW_CFA_nop.0).collect();
+
+ let cie = CommonInformationEntry {
+ offset: 0,
+ length: 100,
+ format: Format::Dwarf32,
+ version: 4,
+ augmentation: None,
+ // DWARF32 with a 64 bit address size! Holy moly!
+ address_size: 8,
+ segment_size: 0,
+ code_alignment_factor: 3,
+ data_alignment_factor: 2,
+ return_address_register: Register(1),
+ initial_instructions: EndianSlice::new(&[], LittleEndian),
+ };
+
+ let mut fde = FrameDescriptionEntry {
+ offset: 0,
+ length: 0,
+ format: Format::Dwarf32,
+ cie: cie.clone(),
+ initial_segment: 0,
+ initial_address: 0xfeed_beef,
+ address_range: 39,
+ augmentation: None,
+ instructions: EndianSlice::new(&expected_instrs, LittleEndian),
+ };
+
+ let kind = debug_frame_le();
+ let section = Section::with_endian(kind.endian())
+ .fde(kind, cie_offset, &mut fde)
+ .append_bytes(&expected_rest);
+
+ let section = section.get_contents().unwrap();
+ let debug_frame = kind.section(&section);
+ let rest = &mut EndianSlice::new(&section, LittleEndian);
+
+ let get_cie = |_: &_, _: &_, offset| {
+ assert_eq!(offset, DebugFrameOffset(cie_offset as usize));
+ Ok(cie.clone())
+ };
+
+ assert_eq!(parse_fde(debug_frame, rest, get_cie), Ok(fde));
+ assert_eq!(*rest, EndianSlice::new(&expected_rest, LittleEndian));
+ }
+
+ #[test]
+ fn test_parse_fde_32_with_segment_ok() {
+ let expected_rest = [1, 2, 3, 4, 5, 6, 7, 8, 9];
+ let cie_offset = 0xbad0_bad1;
+ let expected_instrs: Vec<_> = (0..92).map(|_| constants::DW_CFA_nop.0).collect();
+
+ let cie = CommonInformationEntry {
+ offset: 0,
+ length: 100,
+ format: Format::Dwarf32,
+ version: 4,
+ augmentation: None,
+ address_size: 4,
+ segment_size: 4,
+ code_alignment_factor: 3,
+ data_alignment_factor: 2,
+ return_address_register: Register(1),
+ initial_instructions: EndianSlice::new(&[], LittleEndian),
+ };
+
+ let mut fde = FrameDescriptionEntry {
+ offset: 0,
+ length: 0,
+ format: Format::Dwarf32,
+ cie: cie.clone(),
+ initial_segment: 0xbadb_ad11,
+ initial_address: 0xfeed_beef,
+ address_range: 999,
+ augmentation: None,
+ instructions: EndianSlice::new(&expected_instrs, LittleEndian),
+ };
+
+ let kind = debug_frame_le();
+ let section = Section::with_endian(kind.endian())
+ .fde(kind, cie_offset, &mut fde)
+ .append_bytes(&expected_rest);
+
+ let section = section.get_contents().unwrap();
+ let debug_frame = kind.section(&section);
+ let rest = &mut EndianSlice::new(&section, LittleEndian);
+
+ let get_cie = |_: &_, _: &_, offset| {
+ assert_eq!(offset, DebugFrameOffset(cie_offset as usize));
+ Ok(cie.clone())
+ };
+
+ assert_eq!(parse_fde(debug_frame, rest, get_cie), Ok(fde));
+ assert_eq!(*rest, EndianSlice::new(&expected_rest, LittleEndian));
+ }
+
+ #[test]
+ fn test_parse_fde_64_ok() {
+ let expected_rest = [1, 2, 3, 4, 5, 6, 7, 8, 9];
+ let cie_offset = 0xbad0_bad1;
+ let expected_instrs: Vec<_> = (0..7).map(|_| constants::DW_CFA_nop.0).collect();
+
+ let cie = CommonInformationEntry {
+ offset: 0,
+ length: 100,
+ format: Format::Dwarf64,
+ version: 4,
+ augmentation: None,
+ address_size: 8,
+ segment_size: 0,
+ code_alignment_factor: 3,
+ data_alignment_factor: 2,
+ return_address_register: Register(1),
+ initial_instructions: EndianSlice::new(&[], LittleEndian),
+ };
+
+ let mut fde = FrameDescriptionEntry {
+ offset: 0,
+ length: 0,
+ format: Format::Dwarf64,
+ cie: cie.clone(),
+ initial_segment: 0,
+ initial_address: 0xfeed_beef,
+ address_range: 999,
+ augmentation: None,
+ instructions: EndianSlice::new(&expected_instrs, LittleEndian),
+ };
+
+ let kind = debug_frame_le();
+ let section = Section::with_endian(kind.endian())
+ .fde(kind, cie_offset, &mut fde)
+ .append_bytes(&expected_rest);
+
+ let section = section.get_contents().unwrap();
+ let debug_frame = kind.section(&section);
+ let rest = &mut EndianSlice::new(&section, LittleEndian);
+
+ let get_cie = |_: &_, _: &_, offset| {
+ assert_eq!(offset, DebugFrameOffset(cie_offset as usize));
+ Ok(cie.clone())
+ };
+
+ assert_eq!(parse_fde(debug_frame, rest, get_cie), Ok(fde));
+ assert_eq!(*rest, EndianSlice::new(&expected_rest, LittleEndian));
+ }
+
+ #[test]
+ fn test_parse_cfi_entry_on_cie_32_ok() {
+ let expected_rest = [1, 2, 3, 4, 5, 6, 7, 8, 9];
+ let expected_instrs: Vec<_> = (0..4).map(|_| constants::DW_CFA_nop.0).collect();
+
+ let mut cie = CommonInformationEntry {
+ offset: 0,
+ length: 0,
+ format: Format::Dwarf32,
+ version: 4,
+ augmentation: None,
+ address_size: 4,
+ segment_size: 0,
+ code_alignment_factor: 16,
+ data_alignment_factor: 32,
+ return_address_register: Register(1),
+ initial_instructions: EndianSlice::new(&expected_instrs, BigEndian),
+ };
+
+ let kind = debug_frame_be();
+ let section = Section::with_endian(kind.endian())
+ .cie(kind, None, &mut cie)
+ .append_bytes(&expected_rest);
+ let section = section.get_contents().unwrap();
+ let debug_frame = kind.section(&section);
+ let rest = &mut EndianSlice::new(&section, BigEndian);
+
+ let bases = Default::default();
+ assert_eq!(
+ parse_cfi_entry(&bases, &debug_frame, rest),
+ Ok(Some(CieOrFde::Cie(cie)))
+ );
+ assert_eq!(*rest, EndianSlice::new(&expected_rest, BigEndian));
+ }
+
+ #[test]
+ fn test_parse_cfi_entry_on_fde_32_ok() {
+ let cie_offset = 0x1234_5678;
+ let expected_rest = [1, 2, 3, 4, 5, 6, 7, 8, 9];
+ let expected_instrs: Vec<_> = (0..4).map(|_| constants::DW_CFA_nop.0).collect();
+
+ let cie = CommonInformationEntry {
+ offset: 0,
+ length: 0,
+ format: Format::Dwarf32,
+ version: 4,
+ augmentation: None,
+ address_size: 4,
+ segment_size: 0,
+ code_alignment_factor: 16,
+ data_alignment_factor: 32,
+ return_address_register: Register(1),
+ initial_instructions: EndianSlice::new(&[], BigEndian),
+ };
+
+ let mut fde = FrameDescriptionEntry {
+ offset: 0,
+ length: 0,
+ format: Format::Dwarf32,
+ cie: cie.clone(),
+ initial_segment: 0,
+ initial_address: 0xfeed_beef,
+ address_range: 39,
+ augmentation: None,
+ instructions: EndianSlice::new(&expected_instrs, BigEndian),
+ };
+
+ let kind = debug_frame_be();
+ let section = Section::with_endian(kind.endian())
+ .fde(kind, cie_offset, &mut fde)
+ .append_bytes(&expected_rest);
+
+ let section = section.get_contents().unwrap();
+ let debug_frame = kind.section(&section);
+ let rest = &mut EndianSlice::new(&section, BigEndian);
+
+ let bases = Default::default();
+ match parse_cfi_entry(&bases, &debug_frame, rest) {
+ Ok(Some(CieOrFde::Fde(partial))) => {
+ assert_eq!(*rest, EndianSlice::new(&expected_rest, BigEndian));
+
+ assert_eq!(partial.length, fde.length);
+ assert_eq!(partial.format, fde.format);
+ assert_eq!(partial.cie_offset, DebugFrameOffset(cie_offset as usize));
+
+ let get_cie = |_: &_, _: &_, offset| {
+ assert_eq!(offset, DebugFrameOffset(cie_offset as usize));
+ Ok(cie.clone())
+ };
+
+ assert_eq!(partial.parse(get_cie), Ok(fde));
+ }
+ otherwise => panic!("Unexpected result: {:#?}", otherwise),
+ }
+ }
+
+ #[test]
+ fn test_cfi_entries_iter() {
+ let expected_instrs1: Vec<_> = (0..4).map(|_| constants::DW_CFA_nop.0).collect();
+
+ let expected_instrs2: Vec<_> = (0..8).map(|_| constants::DW_CFA_nop.0).collect();
+
+ let expected_instrs3: Vec<_> = (0..12).map(|_| constants::DW_CFA_nop.0).collect();
+
+ let expected_instrs4: Vec<_> = (0..16).map(|_| constants::DW_CFA_nop.0).collect();
+
+ let mut cie1 = CommonInformationEntry {
+ offset: 0,
+ length: 0,
+ format: Format::Dwarf32,
+ version: 4,
+ augmentation: None,
+ address_size: 4,
+ segment_size: 0,
+ code_alignment_factor: 1,
+ data_alignment_factor: 2,
+ return_address_register: Register(3),
+ initial_instructions: EndianSlice::new(&expected_instrs1, BigEndian),
+ };
+
+ let mut cie2 = CommonInformationEntry {
+ offset: 0,
+ length: 0,
+ format: Format::Dwarf32,
+ version: 4,
+ augmentation: None,
+ address_size: 4,
+ segment_size: 0,
+ code_alignment_factor: 3,
+ data_alignment_factor: 2,
+ return_address_register: Register(1),
+ initial_instructions: EndianSlice::new(&expected_instrs2, BigEndian),
+ };
+
+ let cie1_location = Label::new();
+ let cie2_location = Label::new();
+
+ // Write the CIEs first so that their length gets set before we clone
+ // them into the FDEs and our equality assertions down the line end up
+ // with all the CIEs always having he correct length.
+ let kind = debug_frame_be();
+ let section = Section::with_endian(kind.endian())
+ .mark(&cie1_location)
+ .cie(kind, None, &mut cie1)
+ .mark(&cie2_location)
+ .cie(kind, None, &mut cie2);
+
+ let mut fde1 = FrameDescriptionEntry {
+ offset: 0,
+ length: 0,
+ format: Format::Dwarf32,
+ cie: cie1.clone(),
+ initial_segment: 0,
+ initial_address: 0xfeed_beef,
+ address_range: 39,
+ augmentation: None,
+ instructions: EndianSlice::new(&expected_instrs3, BigEndian),
+ };
+
+ let mut fde2 = FrameDescriptionEntry {
+ offset: 0,
+ length: 0,
+ format: Format::Dwarf32,
+ cie: cie2.clone(),
+ initial_segment: 0,
+ initial_address: 0xfeed_face,
+ address_range: 9000,
+ augmentation: None,
+ instructions: EndianSlice::new(&expected_instrs4, BigEndian),
+ };
+
+ let section =
+ section
+ .fde(kind, &cie1_location, &mut fde1)
+ .fde(kind, &cie2_location, &mut fde2);
+
+ section.start().set_const(0);
+
+ let cie1_offset = cie1_location.value().unwrap() as usize;
+ let cie2_offset = cie2_location.value().unwrap() as usize;
+
+ let contents = section.get_contents().unwrap();
+ let debug_frame = kind.section(&contents);
+
+ let bases = Default::default();
+ let mut entries = debug_frame.entries(&bases);
+
+ assert_eq!(entries.next(), Ok(Some(CieOrFde::Cie(cie1.clone()))));
+ assert_eq!(entries.next(), Ok(Some(CieOrFde::Cie(cie2.clone()))));
+
+ match entries.next() {
+ Ok(Some(CieOrFde::Fde(partial))) => {
+ assert_eq!(partial.length, fde1.length);
+ assert_eq!(partial.format, fde1.format);
+ assert_eq!(partial.cie_offset, DebugFrameOffset(cie1_offset));
+
+ let get_cie = |_: &_, _: &_, offset| {
+ assert_eq!(offset, DebugFrameOffset(cie1_offset));
+ Ok(cie1.clone())
+ };
+ assert_eq!(partial.parse(get_cie), Ok(fde1));
+ }
+ otherwise => panic!("Unexpected result: {:#?}", otherwise),
+ }
+
+ match entries.next() {
+ Ok(Some(CieOrFde::Fde(partial))) => {
+ assert_eq!(partial.length, fde2.length);
+ assert_eq!(partial.format, fde2.format);
+ assert_eq!(partial.cie_offset, DebugFrameOffset(cie2_offset));
+
+ let get_cie = |_: &_, _: &_, offset| {
+ assert_eq!(offset, DebugFrameOffset(cie2_offset));
+ Ok(cie2.clone())
+ };
+ assert_eq!(partial.parse(get_cie), Ok(fde2));
+ }
+ otherwise => panic!("Unexpected result: {:#?}", otherwise),
+ }
+
+ assert_eq!(entries.next(), Ok(None));
+ }
+
+ #[test]
+ fn test_parse_cie_from_offset() {
+ let filler = [1, 2, 3, 4, 5, 6, 7, 8, 9];
+ let instrs: Vec<_> = (0..5).map(|_| constants::DW_CFA_nop.0).collect();
+
+ let mut cie = CommonInformationEntry {
+ offset: 0,
+ length: 0,
+ format: Format::Dwarf64,
+ version: 4,
+ augmentation: None,
+ address_size: 4,
+ segment_size: 0,
+ code_alignment_factor: 4,
+ data_alignment_factor: 8,
+ return_address_register: Register(12),
+ initial_instructions: EndianSlice::new(&instrs, LittleEndian),
+ };
+
+ let cie_location = Label::new();
+
+ let kind = debug_frame_le();
+ let section = Section::with_endian(kind.endian())
+ .append_bytes(&filler)
+ .mark(&cie_location)
+ .cie(kind, None, &mut cie)
+ .append_bytes(&filler);
+
+ section.start().set_const(0);
+
+ let cie_offset = DebugFrameOffset(cie_location.value().unwrap() as usize);
+
+ let contents = section.get_contents().unwrap();
+ let debug_frame = kind.section(&contents);
+ let bases = Default::default();
+
+ assert_eq!(debug_frame.cie_from_offset(&bases, cie_offset), Ok(cie));
+ }
+
+ fn parse_cfi_instruction<R: Reader + Default>(
+ input: &mut R,
+ address_size: u8,
+ ) -> Result<CallFrameInstruction<R>> {
+ let parameters = &PointerEncodingParameters {
+ bases: &SectionBaseAddresses::default(),
+ func_base: None,
+ address_size,
+ section: &R::default(),
+ };
+ CallFrameInstruction::parse(input, None, parameters)
+ }
+
+ #[test]
+ fn test_parse_cfi_instruction_advance_loc() {
+ let expected_rest = [1, 2, 3, 4];
+ let expected_delta = 42;
+ let section = Section::with_endian(Endian::Little)
+ .D8(constants::DW_CFA_advance_loc.0 | expected_delta)
+ .append_bytes(&expected_rest);
+ let contents = section.get_contents().unwrap();
+ let input = &mut EndianSlice::new(&contents, LittleEndian);
+ assert_eq!(
+ parse_cfi_instruction(input, 8),
+ Ok(CallFrameInstruction::AdvanceLoc {
+ delta: u32::from(expected_delta),
+ })
+ );
+ assert_eq!(*input, EndianSlice::new(&expected_rest, LittleEndian));
+ }
+
+ #[test]
+ fn test_parse_cfi_instruction_offset() {
+ let expected_rest = [1, 2, 3, 4];
+ let expected_reg = 3;
+ let expected_offset = 1997;
+ let section = Section::with_endian(Endian::Little)
+ .D8(constants::DW_CFA_offset.0 | expected_reg)
+ .uleb(expected_offset)
+ .append_bytes(&expected_rest);
+ let contents = section.get_contents().unwrap();
+ let input = &mut EndianSlice::new(&contents, LittleEndian);
+ assert_eq!(
+ parse_cfi_instruction(input, 8),
+ Ok(CallFrameInstruction::Offset {
+ register: Register(expected_reg.into()),
+ factored_offset: expected_offset,
+ })
+ );
+ assert_eq!(*input, EndianSlice::new(&expected_rest, LittleEndian));
+ }
+
+ #[test]
+ fn test_parse_cfi_instruction_restore() {
+ let expected_rest = [1, 2, 3, 4];
+ let expected_reg = 3;
+ let section = Section::with_endian(Endian::Little)
+ .D8(constants::DW_CFA_restore.0 | expected_reg)
+ .append_bytes(&expected_rest);
+ let contents = section.get_contents().unwrap();
+ let input = &mut EndianSlice::new(&contents, LittleEndian);
+ assert_eq!(
+ parse_cfi_instruction(input, 8),
+ Ok(CallFrameInstruction::Restore {
+ register: Register(expected_reg.into()),
+ })
+ );
+ assert_eq!(*input, EndianSlice::new(&expected_rest, LittleEndian));
+ }
+
+ #[test]
+ fn test_parse_cfi_instruction_nop() {
+ let expected_rest = [1, 2, 3, 4];
+ let section = Section::with_endian(Endian::Little)
+ .D8(constants::DW_CFA_nop.0)
+ .append_bytes(&expected_rest);
+ let contents = section.get_contents().unwrap();
+ let input = &mut EndianSlice::new(&contents, LittleEndian);
+ assert_eq!(
+ parse_cfi_instruction(input, 8),
+ Ok(CallFrameInstruction::Nop)
+ );
+ assert_eq!(*input, EndianSlice::new(&expected_rest, LittleEndian));
+ }
+
+ #[test]
+ fn test_parse_cfi_instruction_set_loc() {
+ let expected_rest = [1, 2, 3, 4];
+ let expected_addr = 0xdead_beef;
+ let section = Section::with_endian(Endian::Little)
+ .D8(constants::DW_CFA_set_loc.0)
+ .L64(expected_addr)
+ .append_bytes(&expected_rest);
+ let contents = section.get_contents().unwrap();
+ let input = &mut EndianSlice::new(&contents, LittleEndian);
+ assert_eq!(
+ parse_cfi_instruction(input, 8),
+ Ok(CallFrameInstruction::SetLoc {
+ address: expected_addr,
+ })
+ );
+ assert_eq!(*input, EndianSlice::new(&expected_rest, LittleEndian));
+ }
+
+ #[test]
+ fn test_parse_cfi_instruction_set_loc_encoding() {
+ let text_base = 0xfeed_face;
+ let addr_offset = 0xbeef;
+ let expected_addr = text_base + addr_offset;
+ let expected_rest = [1, 2, 3, 4];
+ let section = Section::with_endian(Endian::Little)
+ .D8(constants::DW_CFA_set_loc.0)
+ .L64(addr_offset)
+ .append_bytes(&expected_rest);
+ let contents = section.get_contents().unwrap();
+ let input = &mut EndianSlice::new(&contents, LittleEndian);
+ let parameters = &PointerEncodingParameters {
+ bases: &BaseAddresses::default().set_text(text_base).eh_frame,
+ func_base: None,
+ address_size: 8,
+ section: &EndianSlice::new(&[], LittleEndian),
+ };
+ assert_eq!(
+ CallFrameInstruction::parse(input, Some(constants::DW_EH_PE_textrel), parameters),
+ Ok(CallFrameInstruction::SetLoc {
+ address: expected_addr,
+ })
+ );
+ assert_eq!(*input, EndianSlice::new(&expected_rest, LittleEndian));
+ }
+
+ #[test]
+ fn test_parse_cfi_instruction_advance_loc1() {
+ let expected_rest = [1, 2, 3, 4];
+ let expected_delta = 8;
+ let section = Section::with_endian(Endian::Little)
+ .D8(constants::DW_CFA_advance_loc1.0)
+ .D8(expected_delta)
+ .append_bytes(&expected_rest);
+ let contents = section.get_contents().unwrap();
+ let input = &mut EndianSlice::new(&contents, LittleEndian);
+ assert_eq!(
+ parse_cfi_instruction(input, 8),
+ Ok(CallFrameInstruction::AdvanceLoc {
+ delta: u32::from(expected_delta),
+ })
+ );
+ assert_eq!(*input, EndianSlice::new(&expected_rest, LittleEndian));
+ }
+
+ #[test]
+ fn test_parse_cfi_instruction_advance_loc2() {
+ let expected_rest = [1, 2, 3, 4];
+ let expected_delta = 500;
+ let section = Section::with_endian(Endian::Little)
+ .D8(constants::DW_CFA_advance_loc2.0)
+ .L16(expected_delta)
+ .append_bytes(&expected_rest);
+ let contents = section.get_contents().unwrap();
+ let input = &mut EndianSlice::new(&contents, LittleEndian);
+ assert_eq!(
+ parse_cfi_instruction(input, 8),
+ Ok(CallFrameInstruction::AdvanceLoc {
+ delta: u32::from(expected_delta),
+ })
+ );
+ assert_eq!(*input, EndianSlice::new(&expected_rest, LittleEndian));
+ }
+
+ #[test]
+ fn test_parse_cfi_instruction_advance_loc4() {
+ let expected_rest = [1, 2, 3, 4];
+ let expected_delta = 1 << 20;
+ let section = Section::with_endian(Endian::Little)
+ .D8(constants::DW_CFA_advance_loc4.0)
+ .L32(expected_delta)
+ .append_bytes(&expected_rest);
+ let contents = section.get_contents().unwrap();
+ let input = &mut EndianSlice::new(&contents, LittleEndian);
+ assert_eq!(
+ parse_cfi_instruction(input, 8),
+ Ok(CallFrameInstruction::AdvanceLoc {
+ delta: expected_delta,
+ })
+ );
+ assert_eq!(*input, EndianSlice::new(&expected_rest, LittleEndian));
+ }
+
+ #[test]
+ fn test_parse_cfi_instruction_offset_extended() {
+ let expected_rest = [1, 2, 3, 4];
+ let expected_reg = 7;
+ let expected_offset = 33;
+ let section = Section::with_endian(Endian::Little)
+ .D8(constants::DW_CFA_offset_extended.0)
+ .uleb(expected_reg.into())
+ .uleb(expected_offset)
+ .append_bytes(&expected_rest);
+ let contents = section.get_contents().unwrap();
+ let input = &mut EndianSlice::new(&contents, LittleEndian);
+ assert_eq!(
+ parse_cfi_instruction(input, 8),
+ Ok(CallFrameInstruction::Offset {
+ register: Register(expected_reg),
+ factored_offset: expected_offset,
+ })
+ );
+ assert_eq!(*input, EndianSlice::new(&expected_rest, LittleEndian));
+ }
+
+ #[test]
+ fn test_parse_cfi_instruction_restore_extended() {
+ let expected_rest = [1, 2, 3, 4];
+ let expected_reg = 7;
+ let section = Section::with_endian(Endian::Little)
+ .D8(constants::DW_CFA_restore_extended.0)
+ .uleb(expected_reg.into())
+ .append_bytes(&expected_rest);
+ let contents = section.get_contents().unwrap();
+ let input = &mut EndianSlice::new(&contents, LittleEndian);
+ assert_eq!(
+ parse_cfi_instruction(input, 8),
+ Ok(CallFrameInstruction::Restore {
+ register: Register(expected_reg),
+ })
+ );
+ assert_eq!(*input, EndianSlice::new(&expected_rest, LittleEndian));
+ }
+
+ #[test]
+ fn test_parse_cfi_instruction_undefined() {
+ let expected_rest = [1, 2, 3, 4];
+ let expected_reg = 7;
+ let section = Section::with_endian(Endian::Little)
+ .D8(constants::DW_CFA_undefined.0)
+ .uleb(expected_reg.into())
+ .append_bytes(&expected_rest);
+ let contents = section.get_contents().unwrap();
+ let input = &mut EndianSlice::new(&contents, LittleEndian);
+ assert_eq!(
+ parse_cfi_instruction(input, 8),
+ Ok(CallFrameInstruction::Undefined {
+ register: Register(expected_reg),
+ })
+ );
+ assert_eq!(*input, EndianSlice::new(&expected_rest, LittleEndian));
+ }
+
+ #[test]
+ fn test_parse_cfi_instruction_same_value() {
+ let expected_rest = [1, 2, 3, 4];
+ let expected_reg = 7;
+ let section = Section::with_endian(Endian::Little)
+ .D8(constants::DW_CFA_same_value.0)
+ .uleb(expected_reg.into())
+ .append_bytes(&expected_rest);
+ let contents = section.get_contents().unwrap();
+ let input = &mut EndianSlice::new(&contents, LittleEndian);
+ assert_eq!(
+ parse_cfi_instruction(input, 8),
+ Ok(CallFrameInstruction::SameValue {
+ register: Register(expected_reg),
+ })
+ );
+ assert_eq!(*input, EndianSlice::new(&expected_rest, LittleEndian));
+ }
+
+ #[test]
+ fn test_parse_cfi_instruction_register() {
+ let expected_rest = [1, 2, 3, 4];
+ let expected_dest_reg = 7;
+ let expected_src_reg = 8;
+ let section = Section::with_endian(Endian::Little)
+ .D8(constants::DW_CFA_register.0)
+ .uleb(expected_dest_reg.into())
+ .uleb(expected_src_reg.into())
+ .append_bytes(&expected_rest);
+ let contents = section.get_contents().unwrap();
+ let input = &mut EndianSlice::new(&contents, LittleEndian);
+ assert_eq!(
+ parse_cfi_instruction(input, 8),
+ Ok(CallFrameInstruction::Register {
+ dest_register: Register(expected_dest_reg),
+ src_register: Register(expected_src_reg),
+ })
+ );
+ assert_eq!(*input, EndianSlice::new(&expected_rest, LittleEndian));
+ }
+
+ #[test]
+ fn test_parse_cfi_instruction_remember_state() {
+ let expected_rest = [1, 2, 3, 4];
+ let section = Section::with_endian(Endian::Little)
+ .D8(constants::DW_CFA_remember_state.0)
+ .append_bytes(&expected_rest);
+ let contents = section.get_contents().unwrap();
+ let input = &mut EndianSlice::new(&contents, LittleEndian);
+ assert_eq!(
+ parse_cfi_instruction(input, 8),
+ Ok(CallFrameInstruction::RememberState)
+ );
+ assert_eq!(*input, EndianSlice::new(&expected_rest, LittleEndian));
+ }
+
+ #[test]
+ fn test_parse_cfi_instruction_restore_state() {
+ let expected_rest = [1, 2, 3, 4];
+ let section = Section::with_endian(Endian::Little)
+ .D8(constants::DW_CFA_restore_state.0)
+ .append_bytes(&expected_rest);
+ let contents = section.get_contents().unwrap();
+ let input = &mut EndianSlice::new(&contents, LittleEndian);
+ assert_eq!(
+ parse_cfi_instruction(input, 8),
+ Ok(CallFrameInstruction::RestoreState)
+ );
+ assert_eq!(*input, EndianSlice::new(&expected_rest, LittleEndian));
+ }
+
+ #[test]
+ fn test_parse_cfi_instruction_def_cfa() {
+ let expected_rest = [1, 2, 3, 4];
+ let expected_reg = 2;
+ let expected_offset = 0;
+ let section = Section::with_endian(Endian::Little)
+ .D8(constants::DW_CFA_def_cfa.0)
+ .uleb(expected_reg.into())
+ .uleb(expected_offset)
+ .append_bytes(&expected_rest);
+ let contents = section.get_contents().unwrap();
+ let input = &mut EndianSlice::new(&contents, LittleEndian);
+ assert_eq!(
+ parse_cfi_instruction(input, 8),
+ Ok(CallFrameInstruction::DefCfa {
+ register: Register(expected_reg),
+ offset: expected_offset,
+ })
+ );
+ assert_eq!(*input, EndianSlice::new(&expected_rest, LittleEndian));
+ }
+
+ #[test]
+ fn test_parse_cfi_instruction_def_cfa_register() {
+ let expected_rest = [1, 2, 3, 4];
+ let expected_reg = 2;
+ let section = Section::with_endian(Endian::Little)
+ .D8(constants::DW_CFA_def_cfa_register.0)
+ .uleb(expected_reg.into())
+ .append_bytes(&expected_rest);
+ let contents = section.get_contents().unwrap();
+ let input = &mut EndianSlice::new(&contents, LittleEndian);
+ assert_eq!(
+ parse_cfi_instruction(input, 8),
+ Ok(CallFrameInstruction::DefCfaRegister {
+ register: Register(expected_reg),
+ })
+ );
+ assert_eq!(*input, EndianSlice::new(&expected_rest, LittleEndian));
+ }
+
+ #[test]
+ fn test_parse_cfi_instruction_def_cfa_offset() {
+ let expected_rest = [1, 2, 3, 4];
+ let expected_offset = 23;
+ let section = Section::with_endian(Endian::Little)
+ .D8(constants::DW_CFA_def_cfa_offset.0)
+ .uleb(expected_offset)
+ .append_bytes(&expected_rest);
+ let contents = section.get_contents().unwrap();
+ let input = &mut EndianSlice::new(&contents, LittleEndian);
+ assert_eq!(
+ parse_cfi_instruction(input, 8),
+ Ok(CallFrameInstruction::DefCfaOffset {
+ offset: expected_offset,
+ })
+ );
+ assert_eq!(*input, EndianSlice::new(&expected_rest, LittleEndian));
+ }
+
+ #[test]
+ fn test_parse_cfi_instruction_def_cfa_expression() {
+ let expected_rest = [1, 2, 3, 4];
+ let expected_expr = [10, 9, 8, 7, 6, 5, 4, 3, 2, 1];
+
+ let length = Label::new();
+ let start = Label::new();
+ let end = Label::new();
+
+ let section = Section::with_endian(Endian::Little)
+ .D8(constants::DW_CFA_def_cfa_expression.0)
+ .D8(&length)
+ .mark(&start)
+ .append_bytes(&expected_expr)
+ .mark(&end)
+ .append_bytes(&expected_rest);
+
+ length.set_const((&end - &start) as u64);
+ let contents = section.get_contents().unwrap();
+ let input = &mut EndianSlice::new(&contents, LittleEndian);
+
+ assert_eq!(
+ parse_cfi_instruction(input, 8),
+ Ok(CallFrameInstruction::DefCfaExpression {
+ expression: Expression(EndianSlice::new(&expected_expr, LittleEndian)),
+ })
+ );
+ assert_eq!(*input, EndianSlice::new(&expected_rest, LittleEndian));
+ }
+
+ #[test]
+ fn test_parse_cfi_instruction_expression() {
+ let expected_rest = [1, 2, 3, 4];
+ let expected_reg = 99;
+ let expected_expr = [10, 9, 8, 7, 6, 5, 4, 3, 2, 1];
+
+ let length = Label::new();
+ let start = Label::new();
+ let end = Label::new();
+
+ let section = Section::with_endian(Endian::Little)
+ .D8(constants::DW_CFA_expression.0)
+ .uleb(expected_reg.into())
+ .D8(&length)
+ .mark(&start)
+ .append_bytes(&expected_expr)
+ .mark(&end)
+ .append_bytes(&expected_rest);
+
+ length.set_const((&end - &start) as u64);
+ let contents = section.get_contents().unwrap();
+ let input = &mut EndianSlice::new(&contents, LittleEndian);
+
+ assert_eq!(
+ parse_cfi_instruction(input, 8),
+ Ok(CallFrameInstruction::Expression {
+ register: Register(expected_reg),
+ expression: Expression(EndianSlice::new(&expected_expr, LittleEndian)),
+ })
+ );
+ assert_eq!(*input, EndianSlice::new(&expected_rest, LittleEndian));
+ }
+
+ #[test]
+ fn test_parse_cfi_instruction_offset_extended_sf() {
+ let expected_rest = [1, 2, 3, 4];
+ let expected_reg = 7;
+ let expected_offset = -33;
+ let section = Section::with_endian(Endian::Little)
+ .D8(constants::DW_CFA_offset_extended_sf.0)
+ .uleb(expected_reg.into())
+ .sleb(expected_offset)
+ .append_bytes(&expected_rest);
+ let contents = section.get_contents().unwrap();
+ let input = &mut EndianSlice::new(&contents, LittleEndian);
+ assert_eq!(
+ parse_cfi_instruction(input, 8),
+ Ok(CallFrameInstruction::OffsetExtendedSf {
+ register: Register(expected_reg),
+ factored_offset: expected_offset,
+ })
+ );
+ assert_eq!(*input, EndianSlice::new(&expected_rest, LittleEndian));
+ }
+
+ #[test]
+ fn test_parse_cfi_instruction_def_cfa_sf() {
+ let expected_rest = [1, 2, 3, 4];
+ let expected_reg = 2;
+ let expected_offset = -9999;
+ let section = Section::with_endian(Endian::Little)
+ .D8(constants::DW_CFA_def_cfa_sf.0)
+ .uleb(expected_reg.into())
+ .sleb(expected_offset)
+ .append_bytes(&expected_rest);
+ let contents = section.get_contents().unwrap();
+ let input = &mut EndianSlice::new(&contents, LittleEndian);
+ assert_eq!(
+ parse_cfi_instruction(input, 8),
+ Ok(CallFrameInstruction::DefCfaSf {
+ register: Register(expected_reg),
+ factored_offset: expected_offset,
+ })
+ );
+ assert_eq!(*input, EndianSlice::new(&expected_rest, LittleEndian));
+ }
+
+ #[test]
+ fn test_parse_cfi_instruction_def_cfa_offset_sf() {
+ let expected_rest = [1, 2, 3, 4];
+ let expected_offset = -123;
+ let section = Section::with_endian(Endian::Little)
+ .D8(constants::DW_CFA_def_cfa_offset_sf.0)
+ .sleb(expected_offset)
+ .append_bytes(&expected_rest);
+ let contents = section.get_contents().unwrap();
+ let input = &mut EndianSlice::new(&contents, LittleEndian);
+ assert_eq!(
+ parse_cfi_instruction(input, 8),
+ Ok(CallFrameInstruction::DefCfaOffsetSf {
+ factored_offset: expected_offset,
+ })
+ );
+ assert_eq!(*input, EndianSlice::new(&expected_rest, LittleEndian));
+ }
+
+ #[test]
+ fn test_parse_cfi_instruction_val_offset() {
+ let expected_rest = [1, 2, 3, 4];
+ let expected_reg = 50;
+ let expected_offset = 23;
+ let section = Section::with_endian(Endian::Little)
+ .D8(constants::DW_CFA_val_offset.0)
+ .uleb(expected_reg.into())
+ .uleb(expected_offset)
+ .append_bytes(&expected_rest);
+ let contents = section.get_contents().unwrap();
+ let input = &mut EndianSlice::new(&contents, LittleEndian);
+ assert_eq!(
+ parse_cfi_instruction(input, 8),
+ Ok(CallFrameInstruction::ValOffset {
+ register: Register(expected_reg),
+ factored_offset: expected_offset,
+ })
+ );
+ assert_eq!(*input, EndianSlice::new(&expected_rest, LittleEndian));
+ }
+
+ #[test]
+ fn test_parse_cfi_instruction_val_offset_sf() {
+ let expected_rest = [1, 2, 3, 4];
+ let expected_reg = 50;
+ let expected_offset = -23;
+ let section = Section::with_endian(Endian::Little)
+ .D8(constants::DW_CFA_val_offset_sf.0)
+ .uleb(expected_reg.into())
+ .sleb(expected_offset)
+ .append_bytes(&expected_rest);
+ let contents = section.get_contents().unwrap();
+ let input = &mut EndianSlice::new(&contents, LittleEndian);
+ assert_eq!(
+ parse_cfi_instruction(input, 8),
+ Ok(CallFrameInstruction::ValOffsetSf {
+ register: Register(expected_reg),
+ factored_offset: expected_offset,
+ })
+ );
+ assert_eq!(*input, EndianSlice::new(&expected_rest, LittleEndian));
+ }
+
+ #[test]
+ fn test_parse_cfi_instruction_val_expression() {
+ let expected_rest = [1, 2, 3, 4];
+ let expected_reg = 50;
+ let expected_expr = [2, 2, 1, 1, 5, 5];
+
+ let length = Label::new();
+ let start = Label::new();
+ let end = Label::new();
+
+ let section = Section::with_endian(Endian::Little)
+ .D8(constants::DW_CFA_val_expression.0)
+ .uleb(expected_reg.into())
+ .D8(&length)
+ .mark(&start)
+ .append_bytes(&expected_expr)
+ .mark(&end)
+ .append_bytes(&expected_rest);
+
+ length.set_const((&end - &start) as u64);
+ let contents = section.get_contents().unwrap();
+ let input = &mut EndianSlice::new(&contents, LittleEndian);
+
+ assert_eq!(
+ parse_cfi_instruction(input, 8),
+ Ok(CallFrameInstruction::ValExpression {
+ register: Register(expected_reg),
+ expression: Expression(EndianSlice::new(&expected_expr, LittleEndian)),
+ })
+ );
+ assert_eq!(*input, EndianSlice::new(&expected_rest, LittleEndian));
+ }
+
+ #[test]
+ fn test_parse_cfi_instruction_unknown_instruction() {
+ let expected_rest = [1, 2, 3, 4];
+ let unknown_instr = constants::DwCfa(0b0011_1111);
+ let section = Section::with_endian(Endian::Little)
+ .D8(unknown_instr.0)
+ .append_bytes(&expected_rest);
+ let contents = section.get_contents().unwrap();
+ let input = &mut EndianSlice::new(&contents, LittleEndian);
+ assert_eq!(
+ parse_cfi_instruction(input, 8),
+ Err(Error::UnknownCallFrameInstruction(unknown_instr))
+ );
+ }
+
+ #[test]
+ fn test_call_frame_instruction_iter_ok() {
+ let expected_reg = 50;
+ let expected_expr = [2, 2, 1, 1, 5, 5];
+ let expected_delta = 230;
+
+ let length = Label::new();
+ let start = Label::new();
+ let end = Label::new();
+
+ let section = Section::with_endian(Endian::Big)
+ .D8(constants::DW_CFA_val_expression.0)
+ .uleb(expected_reg.into())
+ .D8(&length)
+ .mark(&start)
+ .append_bytes(&expected_expr)
+ .mark(&end)
+ .D8(constants::DW_CFA_advance_loc1.0)
+ .D8(expected_delta);
+
+ length.set_const((&end - &start) as u64);
+ let contents = section.get_contents().unwrap();
+ let input = EndianSlice::new(&contents, BigEndian);
+ let parameters = PointerEncodingParameters {
+ bases: &SectionBaseAddresses::default(),
+ func_base: None,
+ address_size: 8,
+ section: &EndianSlice::default(),
+ };
+ let mut iter = CallFrameInstructionIter {
+ input,
+ address_encoding: None,
+ parameters,
+ };
+
+ assert_eq!(
+ iter.next(),
+ Ok(Some(CallFrameInstruction::ValExpression {
+ register: Register(expected_reg),
+ expression: Expression(EndianSlice::new(&expected_expr, BigEndian)),
+ }))
+ );
+
+ assert_eq!(
+ iter.next(),
+ Ok(Some(CallFrameInstruction::AdvanceLoc {
+ delta: u32::from(expected_delta),
+ }))
+ );
+
+ assert_eq!(iter.next(), Ok(None));
+ }
+
+ #[test]
+ fn test_call_frame_instruction_iter_err() {
+ // DW_CFA_advance_loc1 without an operand.
+ let section = Section::with_endian(Endian::Big).D8(constants::DW_CFA_advance_loc1.0);
+
+ let contents = section.get_contents().unwrap();
+ let input = EndianSlice::new(&contents, BigEndian);
+ let parameters = PointerEncodingParameters {
+ bases: &SectionBaseAddresses::default(),
+ func_base: None,
+ address_size: 8,
+ section: &EndianSlice::default(),
+ };
+ let mut iter = CallFrameInstructionIter {
+ input,
+ address_encoding: None,
+ parameters,
+ };
+
+ assert_eq!(
+ iter.next().map_eof(&contents),
+ Err(Error::UnexpectedEof(ReaderOffsetId(1)))
+ );
+ assert_eq!(iter.next(), Ok(None));
+ }
+
+ #[allow(clippy::needless_pass_by_value)]
+ fn assert_eval<'a, I>(
+ mut initial_ctx: UnwindContext<EndianSlice<'a, LittleEndian>>,
+ expected_ctx: UnwindContext<EndianSlice<'a, LittleEndian>>,
+ cie: CommonInformationEntry<EndianSlice<'a, LittleEndian>>,
+ fde: Option<FrameDescriptionEntry<EndianSlice<'a, LittleEndian>>>,
+ instructions: I,
+ ) where
+ I: AsRef<
+ [(
+ Result<bool>,
+ CallFrameInstruction<EndianSlice<'a, LittleEndian>>,
+ )],
+ >,
+ {
+ {
+ let section = &DebugFrame::from(EndianSlice::default());
+ let bases = &BaseAddresses::default();
+ let mut table = match fde {
+ Some(fde) => UnwindTable::new_for_fde(section, bases, &mut initial_ctx, &fde),
+ None => UnwindTable::new_for_cie(section, bases, &mut initial_ctx, &cie),
+ };
+ for &(ref expected_result, ref instruction) in instructions.as_ref() {
+ assert_eq!(*expected_result, table.evaluate(instruction.clone()));
+ }
+ }
+
+ assert_eq!(expected_ctx, initial_ctx);
+ }
+
+ fn make_test_cie<'a>() -> CommonInformationEntry<EndianSlice<'a, LittleEndian>> {
+ CommonInformationEntry {
+ offset: 0,
+ format: Format::Dwarf64,
+ length: 0,
+ return_address_register: Register(0),
+ version: 4,
+ address_size: mem::size_of::<usize>() as u8,
+ initial_instructions: EndianSlice::new(&[], LittleEndian),
+ augmentation: None,
+ segment_size: 0,
+ data_alignment_factor: 2,
+ code_alignment_factor: 3,
+ }
+ }
+
+ #[test]
+ fn test_eval_set_loc() {
+ let cie = make_test_cie();
+ let ctx = UnwindContext::new();
+ let mut expected = ctx.clone();
+ expected.row_mut().end_address = 42;
+ let instructions = [(Ok(true), CallFrameInstruction::SetLoc { address: 42 })];
+ assert_eval(ctx, expected, cie, None, instructions);
+ }
+
+ #[test]
+ fn test_eval_set_loc_backwards() {
+ let cie = make_test_cie();
+ let mut ctx = UnwindContext::new();
+ ctx.row_mut().start_address = 999;
+ let expected = ctx.clone();
+ let instructions = [(
+ Err(Error::InvalidAddressRange),
+ CallFrameInstruction::SetLoc { address: 42 },
+ )];
+ assert_eval(ctx, expected, cie, None, instructions);
+ }
+
+ #[test]
+ fn test_eval_advance_loc() {
+ let cie = make_test_cie();
+ let mut ctx = UnwindContext::new();
+ ctx.row_mut().start_address = 3;
+ let mut expected = ctx.clone();
+ expected.row_mut().end_address = 3 + 2 * cie.code_alignment_factor;
+ let instructions = [(Ok(true), CallFrameInstruction::AdvanceLoc { delta: 2 })];
+ assert_eval(ctx, expected, cie, None, instructions);
+ }
+
+ #[test]
+ fn test_eval_advance_loc_overflow() {
+ let cie = make_test_cie();
+ let mut ctx = UnwindContext::new();
+ ctx.row_mut().start_address = u64::MAX;
+ let mut expected = ctx.clone();
+ expected.row_mut().end_address = 42 * cie.code_alignment_factor - 1;
+ let instructions = [(Ok(true), CallFrameInstruction::AdvanceLoc { delta: 42 })];
+ assert_eval(ctx, expected, cie, None, instructions);
+ }
+
+ #[test]
+ fn test_eval_def_cfa() {
+ let cie = make_test_cie();
+ let ctx = UnwindContext::new();
+ let mut expected = ctx.clone();
+ expected.set_cfa(CfaRule::RegisterAndOffset {
+ register: Register(42),
+ offset: 36,
+ });
+ let instructions = [(
+ Ok(false),
+ CallFrameInstruction::DefCfa {
+ register: Register(42),
+ offset: 36,
+ },
+ )];
+ assert_eval(ctx, expected, cie, None, instructions);
+ }
+
+ #[test]
+ fn test_eval_def_cfa_sf() {
+ let cie = make_test_cie();
+ let ctx = UnwindContext::new();
+ let mut expected = ctx.clone();
+ expected.set_cfa(CfaRule::RegisterAndOffset {
+ register: Register(42),
+ offset: 36 * cie.data_alignment_factor as i64,
+ });
+ let instructions = [(
+ Ok(false),
+ CallFrameInstruction::DefCfaSf {
+ register: Register(42),
+ factored_offset: 36,
+ },
+ )];
+ assert_eval(ctx, expected, cie, None, instructions);
+ }
+
+ #[test]
+ fn test_eval_def_cfa_register() {
+ let cie = make_test_cie();
+ let mut ctx = UnwindContext::new();
+ ctx.set_cfa(CfaRule::RegisterAndOffset {
+ register: Register(3),
+ offset: 8,
+ });
+ let mut expected = ctx.clone();
+ expected.set_cfa(CfaRule::RegisterAndOffset {
+ register: Register(42),
+ offset: 8,
+ });
+ let instructions = [(
+ Ok(false),
+ CallFrameInstruction::DefCfaRegister {
+ register: Register(42),
+ },
+ )];
+ assert_eval(ctx, expected, cie, None, instructions);
+ }
+
+ #[test]
+ fn test_eval_def_cfa_register_invalid_context() {
+ let cie = make_test_cie();
+ let mut ctx = UnwindContext::new();
+ ctx.set_cfa(CfaRule::Expression(Expression(EndianSlice::new(
+ &[],
+ LittleEndian,
+ ))));
+ let expected = ctx.clone();
+ let instructions = [(
+ Err(Error::CfiInstructionInInvalidContext),
+ CallFrameInstruction::DefCfaRegister {
+ register: Register(42),
+ },
+ )];
+ assert_eval(ctx, expected, cie, None, instructions);
+ }
+
+ #[test]
+ fn test_eval_def_cfa_offset() {
+ let cie = make_test_cie();
+ let mut ctx = UnwindContext::new();
+ ctx.set_cfa(CfaRule::RegisterAndOffset {
+ register: Register(3),
+ offset: 8,
+ });
+ let mut expected = ctx.clone();
+ expected.set_cfa(CfaRule::RegisterAndOffset {
+ register: Register(3),
+ offset: 42,
+ });
+ let instructions = [(Ok(false), CallFrameInstruction::DefCfaOffset { offset: 42 })];
+ assert_eval(ctx, expected, cie, None, instructions);
+ }
+
+ #[test]
+ fn test_eval_def_cfa_offset_invalid_context() {
+ let cie = make_test_cie();
+ let mut ctx = UnwindContext::new();
+ ctx.set_cfa(CfaRule::Expression(Expression(EndianSlice::new(
+ &[],
+ LittleEndian,
+ ))));
+ let expected = ctx.clone();
+ let instructions = [(
+ Err(Error::CfiInstructionInInvalidContext),
+ CallFrameInstruction::DefCfaOffset { offset: 1993 },
+ )];
+ assert_eval(ctx, expected, cie, None, instructions);
+ }
+
+ #[test]
+ fn test_eval_def_cfa_expression() {
+ let expr = [1, 2, 3, 4];
+ let cie = make_test_cie();
+ let ctx = UnwindContext::new();
+ let mut expected = ctx.clone();
+ expected.set_cfa(CfaRule::Expression(Expression(EndianSlice::new(
+ &expr,
+ LittleEndian,
+ ))));
+ let instructions = [(
+ Ok(false),
+ CallFrameInstruction::DefCfaExpression {
+ expression: Expression(EndianSlice::new(&expr, LittleEndian)),
+ },
+ )];
+ assert_eval(ctx, expected, cie, None, instructions);
+ }
+
+ #[test]
+ fn test_eval_undefined() {
+ let cie = make_test_cie();
+ let ctx = UnwindContext::new();
+ let mut expected = ctx.clone();
+ expected
+ .set_register_rule(Register(5), RegisterRule::Undefined)
+ .unwrap();
+ let instructions = [(
+ Ok(false),
+ CallFrameInstruction::Undefined {
+ register: Register(5),
+ },
+ )];
+ assert_eval(ctx, expected, cie, None, instructions);
+ }
+
+ #[test]
+ fn test_eval_same_value() {
+ let cie = make_test_cie();
+ let ctx = UnwindContext::new();
+ let mut expected = ctx.clone();
+ expected
+ .set_register_rule(Register(0), RegisterRule::SameValue)
+ .unwrap();
+ let instructions = [(
+ Ok(false),
+ CallFrameInstruction::SameValue {
+ register: Register(0),
+ },
+ )];
+ assert_eval(ctx, expected, cie, None, instructions);
+ }
+
+ #[test]
+ fn test_eval_offset() {
+ let cie = make_test_cie();
+ let ctx = UnwindContext::new();
+ let mut expected = ctx.clone();
+ expected
+ .set_register_rule(
+ Register(2),
+ RegisterRule::Offset(3 * cie.data_alignment_factor),
+ )
+ .unwrap();
+ let instructions = [(
+ Ok(false),
+ CallFrameInstruction::Offset {
+ register: Register(2),
+ factored_offset: 3,
+ },
+ )];
+ assert_eval(ctx, expected, cie, None, instructions);
+ }
+
+ #[test]
+ fn test_eval_offset_extended_sf() {
+ let cie = make_test_cie();
+ let ctx = UnwindContext::new();
+ let mut expected = ctx.clone();
+ expected
+ .set_register_rule(
+ Register(4),
+ RegisterRule::Offset(-3 * cie.data_alignment_factor),
+ )
+ .unwrap();
+ let instructions = [(
+ Ok(false),
+ CallFrameInstruction::OffsetExtendedSf {
+ register: Register(4),
+ factored_offset: -3,
+ },
+ )];
+ assert_eval(ctx, expected, cie, None, instructions);
+ }
+
+ #[test]
+ fn test_eval_val_offset() {
+ let cie = make_test_cie();
+ let ctx = UnwindContext::new();
+ let mut expected = ctx.clone();
+ expected
+ .set_register_rule(
+ Register(5),
+ RegisterRule::ValOffset(7 * cie.data_alignment_factor),
+ )
+ .unwrap();
+ let instructions = [(
+ Ok(false),
+ CallFrameInstruction::ValOffset {
+ register: Register(5),
+ factored_offset: 7,
+ },
+ )];
+ assert_eval(ctx, expected, cie, None, instructions);
+ }
+
+ #[test]
+ fn test_eval_val_offset_sf() {
+ let cie = make_test_cie();
+ let ctx = UnwindContext::new();
+ let mut expected = ctx.clone();
+ expected
+ .set_register_rule(
+ Register(5),
+ RegisterRule::ValOffset(-7 * cie.data_alignment_factor),
+ )
+ .unwrap();
+ let instructions = [(
+ Ok(false),
+ CallFrameInstruction::ValOffsetSf {
+ register: Register(5),
+ factored_offset: -7,
+ },
+ )];
+ assert_eval(ctx, expected, cie, None, instructions);
+ }
+
+ #[test]
+ fn test_eval_expression() {
+ let expr = [1, 2, 3, 4];
+ let cie = make_test_cie();
+ let ctx = UnwindContext::new();
+ let mut expected = ctx.clone();
+ expected
+ .set_register_rule(
+ Register(9),
+ RegisterRule::Expression(Expression(EndianSlice::new(&expr, LittleEndian))),
+ )
+ .unwrap();
+ let instructions = [(
+ Ok(false),
+ CallFrameInstruction::Expression {
+ register: Register(9),
+ expression: Expression(EndianSlice::new(&expr, LittleEndian)),
+ },
+ )];
+ assert_eval(ctx, expected, cie, None, instructions);
+ }
+
+ #[test]
+ fn test_eval_val_expression() {
+ let expr = [1, 2, 3, 4];
+ let cie = make_test_cie();
+ let ctx = UnwindContext::new();
+ let mut expected = ctx.clone();
+ expected
+ .set_register_rule(
+ Register(9),
+ RegisterRule::ValExpression(Expression(EndianSlice::new(&expr, LittleEndian))),
+ )
+ .unwrap();
+ let instructions = [(
+ Ok(false),
+ CallFrameInstruction::ValExpression {
+ register: Register(9),
+ expression: Expression(EndianSlice::new(&expr, LittleEndian)),
+ },
+ )];
+ assert_eval(ctx, expected, cie, None, instructions);
+ }
+
+ #[test]
+ fn test_eval_restore() {
+ let cie = make_test_cie();
+ let fde = FrameDescriptionEntry {
+ offset: 0,
+ format: Format::Dwarf64,
+ length: 0,
+ address_range: 0,
+ augmentation: None,
+ initial_address: 0,
+ initial_segment: 0,
+ cie: cie.clone(),
+ instructions: EndianSlice::new(&[], LittleEndian),
+ };
+
+ let mut ctx = UnwindContext::new();
+ ctx.set_register_rule(Register(0), RegisterRule::Offset(1))
+ .unwrap();
+ ctx.save_initial_rules().unwrap();
+ let expected = ctx.clone();
+ ctx.set_register_rule(Register(0), RegisterRule::Offset(2))
+ .unwrap();
+
+ let instructions = [(
+ Ok(false),
+ CallFrameInstruction::Restore {
+ register: Register(0),
+ },
+ )];
+ assert_eval(ctx, expected, cie, Some(fde), instructions);
+ }
+
+ #[test]
+ fn test_eval_restore_havent_saved_initial_context() {
+ let cie = make_test_cie();
+ let ctx = UnwindContext::new();
+ let expected = ctx.clone();
+ let instructions = [(
+ Err(Error::CfiInstructionInInvalidContext),
+ CallFrameInstruction::Restore {
+ register: Register(0),
+ },
+ )];
+ assert_eval(ctx, expected, cie, None, instructions);
+ }
+
+ #[test]
+ fn test_eval_remember_state() {
+ let cie = make_test_cie();
+ let ctx = UnwindContext::new();
+ let mut expected = ctx.clone();
+ expected.push_row().unwrap();
+ let instructions = [(Ok(false), CallFrameInstruction::RememberState)];
+ assert_eval(ctx, expected, cie, None, instructions);
+ }
+
+ #[test]
+ fn test_eval_restore_state() {
+ let cie = make_test_cie();
+
+ let mut ctx = UnwindContext::new();
+ ctx.set_start_address(1);
+ ctx.set_register_rule(Register(0), RegisterRule::SameValue)
+ .unwrap();
+ let mut expected = ctx.clone();
+ ctx.push_row().unwrap();
+ ctx.set_start_address(2);
+ ctx.set_register_rule(Register(0), RegisterRule::Offset(16))
+ .unwrap();
+
+ // Restore state should preserve current location.
+ expected.set_start_address(2);
+
+ let instructions = [
+ // First one pops just fine.
+ (Ok(false), CallFrameInstruction::RestoreState),
+ // Second pop would try to pop out of bounds.
+ (
+ Err(Error::PopWithEmptyStack),
+ CallFrameInstruction::RestoreState,
+ ),
+ ];
+
+ assert_eval(ctx, expected, cie, None, instructions);
+ }
+
+ #[test]
+ fn test_eval_nop() {
+ let cie = make_test_cie();
+ let ctx = UnwindContext::new();
+ let expected = ctx.clone();
+ let instructions = [(Ok(false), CallFrameInstruction::Nop)];
+ assert_eval(ctx, expected, cie, None, instructions);
+ }
+
+ #[test]
+ fn test_unwind_table_cie_no_rule() {
+ #[allow(clippy::identity_op)]
+ let initial_instructions = Section::with_endian(Endian::Little)
+ // The CFA is -12 from register 4.
+ .D8(constants::DW_CFA_def_cfa_sf.0)
+ .uleb(4)
+ .sleb(-12)
+ .append_repeated(constants::DW_CFA_nop.0, 4);
+ let initial_instructions = initial_instructions.get_contents().unwrap();
+
+ let cie = CommonInformationEntry {
+ offset: 0,
+ length: 0,
+ format: Format::Dwarf32,
+ version: 4,
+ augmentation: None,
+ address_size: 8,
+ segment_size: 0,
+ code_alignment_factor: 1,
+ data_alignment_factor: 1,
+ return_address_register: Register(3),
+ initial_instructions: EndianSlice::new(&initial_instructions, LittleEndian),
+ };
+
+ let instructions = Section::with_endian(Endian::Little)
+ // A bunch of nop padding.
+ .append_repeated(constants::DW_CFA_nop.0, 8);
+ let instructions = instructions.get_contents().unwrap();
+
+ let fde = FrameDescriptionEntry {
+ offset: 0,
+ length: 0,
+ format: Format::Dwarf32,
+ cie: cie.clone(),
+ initial_segment: 0,
+ initial_address: 0,
+ address_range: 100,
+ augmentation: None,
+ instructions: EndianSlice::new(&instructions, LittleEndian),
+ };
+
+ let section = &DebugFrame::from(EndianSlice::default());
+ let bases = &BaseAddresses::default();
+ let mut ctx = Box::new(UnwindContext::new());
+
+ let mut table = fde
+ .rows(section, bases, &mut ctx)
+ .expect("Should run initial program OK");
+ assert!(table.ctx.is_initialized);
+ let expected_initial_rule = (Register(0), RegisterRule::Undefined);
+ assert_eq!(table.ctx.initial_rule, Some(expected_initial_rule));
+
+ {
+ let row = table.next_row().expect("Should evaluate first row OK");
+ let expected = UnwindTableRow {
+ start_address: 0,
+ end_address: 100,
+ saved_args_size: 0,
+ cfa: CfaRule::RegisterAndOffset {
+ register: Register(4),
+ offset: -12,
+ },
+ registers: [].iter().collect(),
+ };
+ assert_eq!(Some(&expected), row);
+ }
+
+ // All done!
+ assert_eq!(Ok(None), table.next_row());
+ assert_eq!(Ok(None), table.next_row());
+ }
+
+ #[test]
+ fn test_unwind_table_cie_single_rule() {
+ #[allow(clippy::identity_op)]
+ let initial_instructions = Section::with_endian(Endian::Little)
+ // The CFA is -12 from register 4.
+ .D8(constants::DW_CFA_def_cfa_sf.0)
+ .uleb(4)
+ .sleb(-12)
+ // Register 3 is 4 from the CFA.
+ .D8(constants::DW_CFA_offset.0 | 3)
+ .uleb(4)
+ .append_repeated(constants::DW_CFA_nop.0, 4);
+ let initial_instructions = initial_instructions.get_contents().unwrap();
+
+ let cie = CommonInformationEntry {
+ offset: 0,
+ length: 0,
+ format: Format::Dwarf32,
+ version: 4,
+ augmentation: None,
+ address_size: 8,
+ segment_size: 0,
+ code_alignment_factor: 1,
+ data_alignment_factor: 1,
+ return_address_register: Register(3),
+ initial_instructions: EndianSlice::new(&initial_instructions, LittleEndian),
+ };
+
+ let instructions = Section::with_endian(Endian::Little)
+ // A bunch of nop padding.
+ .append_repeated(constants::DW_CFA_nop.0, 8);
+ let instructions = instructions.get_contents().unwrap();
+
+ let fde = FrameDescriptionEntry {
+ offset: 0,
+ length: 0,
+ format: Format::Dwarf32,
+ cie: cie.clone(),
+ initial_segment: 0,
+ initial_address: 0,
+ address_range: 100,
+ augmentation: None,
+ instructions: EndianSlice::new(&instructions, LittleEndian),
+ };
+
+ let section = &DebugFrame::from(EndianSlice::default());
+ let bases = &BaseAddresses::default();
+ let mut ctx = Box::new(UnwindContext::new());
+
+ let mut table = fde
+ .rows(section, bases, &mut ctx)
+ .expect("Should run initial program OK");
+ assert!(table.ctx.is_initialized);
+ let expected_initial_rule = (Register(3), RegisterRule::Offset(4));
+ assert_eq!(table.ctx.initial_rule, Some(expected_initial_rule));
+
+ {
+ let row = table.next_row().expect("Should evaluate first row OK");
+ let expected = UnwindTableRow {
+ start_address: 0,
+ end_address: 100,
+ saved_args_size: 0,
+ cfa: CfaRule::RegisterAndOffset {
+ register: Register(4),
+ offset: -12,
+ },
+ registers: [(Register(3), RegisterRule::Offset(4))].iter().collect(),
+ };
+ assert_eq!(Some(&expected), row);
+ }
+
+ // All done!
+ assert_eq!(Ok(None), table.next_row());
+ assert_eq!(Ok(None), table.next_row());
+ }
+
+ #[test]
+ fn test_unwind_table_next_row() {
+ #[allow(clippy::identity_op)]
+ let initial_instructions = Section::with_endian(Endian::Little)
+ // The CFA is -12 from register 4.
+ .D8(constants::DW_CFA_def_cfa_sf.0)
+ .uleb(4)
+ .sleb(-12)
+ // Register 0 is 8 from the CFA.
+ .D8(constants::DW_CFA_offset.0 | 0)
+ .uleb(8)
+ // Register 3 is 4 from the CFA.
+ .D8(constants::DW_CFA_offset.0 | 3)
+ .uleb(4)
+ .append_repeated(constants::DW_CFA_nop.0, 4);
+ let initial_instructions = initial_instructions.get_contents().unwrap();
+
+ let cie = CommonInformationEntry {
+ offset: 0,
+ length: 0,
+ format: Format::Dwarf32,
+ version: 4,
+ augmentation: None,
+ address_size: 8,
+ segment_size: 0,
+ code_alignment_factor: 1,
+ data_alignment_factor: 1,
+ return_address_register: Register(3),
+ initial_instructions: EndianSlice::new(&initial_instructions, LittleEndian),
+ };
+
+ let instructions = Section::with_endian(Endian::Little)
+ // Initial instructions form a row, advance the address by 1.
+ .D8(constants::DW_CFA_advance_loc1.0)
+ .D8(1)
+ // Register 0 is -16 from the CFA.
+ .D8(constants::DW_CFA_offset_extended_sf.0)
+ .uleb(0)
+ .sleb(-16)
+ // Finish this row, advance the address by 32.
+ .D8(constants::DW_CFA_advance_loc1.0)
+ .D8(32)
+ // Register 3 is -4 from the CFA.
+ .D8(constants::DW_CFA_offset_extended_sf.0)
+ .uleb(3)
+ .sleb(-4)
+ // Finish this row, advance the address by 64.
+ .D8(constants::DW_CFA_advance_loc1.0)
+ .D8(64)
+ // Register 5 is 4 from the CFA.
+ .D8(constants::DW_CFA_offset.0 | 5)
+ .uleb(4)
+ // A bunch of nop padding.
+ .append_repeated(constants::DW_CFA_nop.0, 8);
+ let instructions = instructions.get_contents().unwrap();
+
+ let fde = FrameDescriptionEntry {
+ offset: 0,
+ length: 0,
+ format: Format::Dwarf32,
+ cie: cie.clone(),
+ initial_segment: 0,
+ initial_address: 0,
+ address_range: 100,
+ augmentation: None,
+ instructions: EndianSlice::new(&instructions, LittleEndian),
+ };
+
+ let section = &DebugFrame::from(EndianSlice::default());
+ let bases = &BaseAddresses::default();
+ let mut ctx = Box::new(UnwindContext::new());
+
+ let mut table = fde
+ .rows(section, bases, &mut ctx)
+ .expect("Should run initial program OK");
+ assert!(table.ctx.is_initialized);
+ assert!(table.ctx.initial_rule.is_none());
+ let expected_initial_rules: RegisterRuleMap<_> = [
+ (Register(0), RegisterRule::Offset(8)),
+ (Register(3), RegisterRule::Offset(4)),
+ ]
+ .iter()
+ .collect();
+ assert_eq!(table.ctx.stack[0].registers, expected_initial_rules);
+
+ {
+ let row = table.next_row().expect("Should evaluate first row OK");
+ let expected = UnwindTableRow {
+ start_address: 0,
+ end_address: 1,
+ saved_args_size: 0,
+ cfa: CfaRule::RegisterAndOffset {
+ register: Register(4),
+ offset: -12,
+ },
+ registers: [
+ (Register(0), RegisterRule::Offset(8)),
+ (Register(3), RegisterRule::Offset(4)),
+ ]
+ .iter()
+ .collect(),
+ };
+ assert_eq!(Some(&expected), row);
+ }
+
+ {
+ let row = table.next_row().expect("Should evaluate second row OK");
+ let expected = UnwindTableRow {
+ start_address: 1,
+ end_address: 33,
+ saved_args_size: 0,
+ cfa: CfaRule::RegisterAndOffset {
+ register: Register(4),
+ offset: -12,
+ },
+ registers: [
+ (Register(0), RegisterRule::Offset(-16)),
+ (Register(3), RegisterRule::Offset(4)),
+ ]
+ .iter()
+ .collect(),
+ };
+ assert_eq!(Some(&expected), row);
+ }
+
+ {
+ let row = table.next_row().expect("Should evaluate third row OK");
+ let expected = UnwindTableRow {
+ start_address: 33,
+ end_address: 97,
+ saved_args_size: 0,
+ cfa: CfaRule::RegisterAndOffset {
+ register: Register(4),
+ offset: -12,
+ },
+ registers: [
+ (Register(0), RegisterRule::Offset(-16)),
+ (Register(3), RegisterRule::Offset(-4)),
+ ]
+ .iter()
+ .collect(),
+ };
+ assert_eq!(Some(&expected), row);
+ }
+
+ {
+ let row = table.next_row().expect("Should evaluate fourth row OK");
+ let expected = UnwindTableRow {
+ start_address: 97,
+ end_address: 100,
+ saved_args_size: 0,
+ cfa: CfaRule::RegisterAndOffset {
+ register: Register(4),
+ offset: -12,
+ },
+ registers: [
+ (Register(0), RegisterRule::Offset(-16)),
+ (Register(3), RegisterRule::Offset(-4)),
+ (Register(5), RegisterRule::Offset(4)),
+ ]
+ .iter()
+ .collect(),
+ };
+ assert_eq!(Some(&expected), row);
+ }
+
+ // All done!
+ assert_eq!(Ok(None), table.next_row());
+ assert_eq!(Ok(None), table.next_row());
+ }
+
+ #[test]
+ fn test_unwind_info_for_address_ok() {
+ let instrs1 = Section::with_endian(Endian::Big)
+ // The CFA is -12 from register 4.
+ .D8(constants::DW_CFA_def_cfa_sf.0)
+ .uleb(4)
+ .sleb(-12);
+ let instrs1 = instrs1.get_contents().unwrap();
+
+ let instrs2: Vec<_> = (0..8).map(|_| constants::DW_CFA_nop.0).collect();
+
+ let instrs3 = Section::with_endian(Endian::Big)
+ // Initial instructions form a row, advance the address by 100.
+ .D8(constants::DW_CFA_advance_loc1.0)
+ .D8(100)
+ // Register 0 is -16 from the CFA.
+ .D8(constants::DW_CFA_offset_extended_sf.0)
+ .uleb(0)
+ .sleb(-16);
+ let instrs3 = instrs3.get_contents().unwrap();
+
+ let instrs4: Vec<_> = (0..16).map(|_| constants::DW_CFA_nop.0).collect();
+
+ let mut cie1 = CommonInformationEntry {
+ offset: 0,
+ length: 0,
+ format: Format::Dwarf32,
+ version: 4,
+ augmentation: None,
+ address_size: 8,
+ segment_size: 0,
+ code_alignment_factor: 1,
+ data_alignment_factor: 1,
+ return_address_register: Register(3),
+ initial_instructions: EndianSlice::new(&instrs1, BigEndian),
+ };
+
+ let mut cie2 = CommonInformationEntry {
+ offset: 0,
+ length: 0,
+ format: Format::Dwarf32,
+ version: 4,
+ augmentation: None,
+ address_size: 4,
+ segment_size: 0,
+ code_alignment_factor: 1,
+ data_alignment_factor: 1,
+ return_address_register: Register(1),
+ initial_instructions: EndianSlice::new(&instrs2, BigEndian),
+ };
+
+ let cie1_location = Label::new();
+ let cie2_location = Label::new();
+
+ // Write the CIEs first so that their length gets set before we clone
+ // them into the FDEs and our equality assertions down the line end up
+ // with all the CIEs always having he correct length.
+ let kind = debug_frame_be();
+ let section = Section::with_endian(kind.endian())
+ .mark(&cie1_location)
+ .cie(kind, None, &mut cie1)
+ .mark(&cie2_location)
+ .cie(kind, None, &mut cie2);
+
+ let mut fde1 = FrameDescriptionEntry {
+ offset: 0,
+ length: 0,
+ format: Format::Dwarf32,
+ cie: cie1.clone(),
+ initial_segment: 0,
+ initial_address: 0xfeed_beef,
+ address_range: 200,
+ augmentation: None,
+ instructions: EndianSlice::new(&instrs3, BigEndian),
+ };
+
+ let mut fde2 = FrameDescriptionEntry {
+ offset: 0,
+ length: 0,
+ format: Format::Dwarf32,
+ cie: cie2.clone(),
+ initial_segment: 0,
+ initial_address: 0xfeed_face,
+ address_range: 9000,
+ augmentation: None,
+ instructions: EndianSlice::new(&instrs4, BigEndian),
+ };
+
+ let section =
+ section
+ .fde(kind, &cie1_location, &mut fde1)
+ .fde(kind, &cie2_location, &mut fde2);
+ section.start().set_const(0);
+
+ let contents = section.get_contents().unwrap();
+ let debug_frame = kind.section(&contents);
+
+ // Get the second row of the unwind table in `instrs3`.
+ let bases = Default::default();
+ let mut ctx = Box::new(UnwindContext::new());
+ let result = debug_frame.unwind_info_for_address(
+ &bases,
+ &mut ctx,
+ 0xfeed_beef + 150,
+ DebugFrame::cie_from_offset,
+ );
+ assert!(result.is_ok());
+ let unwind_info = result.unwrap();
+
+ assert_eq!(
+ *unwind_info,
+ UnwindTableRow {
+ start_address: fde1.initial_address() + 100,
+ end_address: fde1.initial_address() + fde1.len(),
+ saved_args_size: 0,
+ cfa: CfaRule::RegisterAndOffset {
+ register: Register(4),
+ offset: -12,
+ },
+ registers: [(Register(0), RegisterRule::Offset(-16))].iter().collect(),
+ }
+ );
+ }
+
+ #[test]
+ fn test_unwind_info_for_address_not_found() {
+ let debug_frame = DebugFrame::new(&[], NativeEndian);
+ let bases = Default::default();
+ let mut ctx = Box::new(UnwindContext::new());
+ let result = debug_frame.unwind_info_for_address(
+ &bases,
+ &mut ctx,
+ 0xbadb_ad99,
+ DebugFrame::cie_from_offset,
+ );
+ assert!(result.is_err());
+ assert_eq!(result.unwrap_err(), Error::NoUnwindInfoForAddress);
+ }
+
+ #[test]
+ fn test_eh_frame_hdr_unknown_version() {
+ let bases = BaseAddresses::default();
+ let buf = &[42];
+ let result = EhFrameHdr::new(buf, NativeEndian).parse(&bases, 8);
+ assert!(result.is_err());
+ assert_eq!(result.unwrap_err(), Error::UnknownVersion(42));
+ }
+
+ #[test]
+ fn test_eh_frame_hdr_omit_ehptr() {
+ let section = Section::with_endian(Endian::Little)
+ .L8(1)
+ .L8(0xff)
+ .L8(0x03)
+ .L8(0x0b)
+ .L32(2)
+ .L32(10)
+ .L32(1)
+ .L32(20)
+ .L32(2)
+ .L32(0);
+ let section = section.get_contents().unwrap();
+ let bases = BaseAddresses::default();
+ let result = EhFrameHdr::new(&section, LittleEndian).parse(&bases, 8);
+ assert!(result.is_err());
+ assert_eq!(result.unwrap_err(), Error::CannotParseOmitPointerEncoding);
+ }
+
+ #[test]
+ fn test_eh_frame_hdr_omit_count() {
+ let section = Section::with_endian(Endian::Little)
+ .L8(1)
+ .L8(0x0b)
+ .L8(0xff)
+ .L8(0x0b)
+ .L32(0x12345);
+ let section = section.get_contents().unwrap();
+ let bases = BaseAddresses::default();
+ let result = EhFrameHdr::new(&section, LittleEndian).parse(&bases, 8);
+ assert!(result.is_ok());
+ let result = result.unwrap();
+ assert_eq!(result.eh_frame_ptr(), Pointer::Direct(0x12345));
+ assert!(result.table().is_none());
+ }
+
+ #[test]
+ fn test_eh_frame_hdr_omit_table() {
+ let section = Section::with_endian(Endian::Little)
+ .L8(1)
+ .L8(0x0b)
+ .L8(0x03)
+ .L8(0xff)
+ .L32(0x12345)
+ .L32(2);
+ let section = section.get_contents().unwrap();
+ let bases = BaseAddresses::default();
+ let result = EhFrameHdr::new(&section, LittleEndian).parse(&bases, 8);
+ assert!(result.is_ok());
+ let result = result.unwrap();
+ assert_eq!(result.eh_frame_ptr(), Pointer::Direct(0x12345));
+ assert!(result.table().is_none());
+ }
+
+ #[test]
+ fn test_eh_frame_hdr_varlen_table() {
+ let section = Section::with_endian(Endian::Little)
+ .L8(1)
+ .L8(0x0b)
+ .L8(0x03)
+ .L8(0x01)
+ .L32(0x12345)
+ .L32(2);
+ let section = section.get_contents().unwrap();
+ let bases = BaseAddresses::default();
+ let result = EhFrameHdr::new(&section, LittleEndian).parse(&bases, 8);
+ assert!(result.is_ok());
+ let result = result.unwrap();
+ assert_eq!(result.eh_frame_ptr(), Pointer::Direct(0x12345));
+ let table = result.table();
+ assert!(table.is_some());
+ let table = table.unwrap();
+ assert_eq!(
+ table.lookup(0, &bases),
+ Err(Error::VariableLengthSearchTable)
+ );
+ }
+
+ #[test]
+ fn test_eh_frame_hdr_indirect_length() {
+ let section = Section::with_endian(Endian::Little)
+ .L8(1)
+ .L8(0x0b)
+ .L8(0x83)
+ .L8(0x0b)
+ .L32(0x12345)
+ .L32(2);
+ let section = section.get_contents().unwrap();
+ let bases = BaseAddresses::default();
+ let result = EhFrameHdr::new(&section, LittleEndian).parse(&bases, 8);
+ assert!(result.is_err());
+ assert_eq!(result.unwrap_err(), Error::UnsupportedPointerEncoding);
+ }
+
+ #[test]
+ fn test_eh_frame_hdr_indirect_ptrs() {
+ let section = Section::with_endian(Endian::Little)
+ .L8(1)
+ .L8(0x8b)
+ .L8(0x03)
+ .L8(0x8b)
+ .L32(0x12345)
+ .L32(2)
+ .L32(10)
+ .L32(1)
+ .L32(20)
+ .L32(2);
+ let section = section.get_contents().unwrap();
+ let bases = BaseAddresses::default();
+ let result = EhFrameHdr::new(&section, LittleEndian).parse(&bases, 8);
+ assert!(result.is_ok());
+ let result = result.unwrap();
+ assert_eq!(result.eh_frame_ptr(), Pointer::Indirect(0x12345));
+ let table = result.table();
+ assert!(table.is_some());
+ let table = table.unwrap();
+ assert_eq!(
+ table.lookup(0, &bases),
+ Err(Error::UnsupportedPointerEncoding)
+ );
+ }
+
+ #[test]
+ fn test_eh_frame_hdr_good() {
+ let section = Section::with_endian(Endian::Little)
+ .L8(1)
+ .L8(0x0b)
+ .L8(0x03)
+ .L8(0x0b)
+ .L32(0x12345)
+ .L32(2)
+ .L32(10)
+ .L32(1)
+ .L32(20)
+ .L32(2);
+ let section = section.get_contents().unwrap();
+ let bases = BaseAddresses::default();
+ let result = EhFrameHdr::new(&section, LittleEndian).parse(&bases, 8);
+ assert!(result.is_ok());
+ let result = result.unwrap();
+ assert_eq!(result.eh_frame_ptr(), Pointer::Direct(0x12345));
+ let table = result.table();
+ assert!(table.is_some());
+ let table = table.unwrap();
+ assert_eq!(table.lookup(0, &bases), Ok(Pointer::Direct(1)));
+ assert_eq!(table.lookup(9, &bases), Ok(Pointer::Direct(1)));
+ assert_eq!(table.lookup(10, &bases), Ok(Pointer::Direct(1)));
+ assert_eq!(table.lookup(11, &bases), Ok(Pointer::Direct(1)));
+ assert_eq!(table.lookup(19, &bases), Ok(Pointer::Direct(1)));
+ assert_eq!(table.lookup(20, &bases), Ok(Pointer::Direct(2)));
+ assert_eq!(table.lookup(21, &bases), Ok(Pointer::Direct(2)));
+ assert_eq!(table.lookup(100_000, &bases), Ok(Pointer::Direct(2)));
+ }
+
+ #[test]
+ fn test_eh_frame_fde_for_address_good() {
+ // First, setup eh_frame
+ // Write the CIE first so that its length gets set before we clone it
+ // into the FDE.
+ let mut cie = make_test_cie();
+ cie.format = Format::Dwarf32;
+ cie.version = 1;
+
+ let start_of_cie = Label::new();
+ let end_of_cie = Label::new();
+
+ let kind = eh_frame_le();
+ let section = Section::with_endian(kind.endian())
+ .append_repeated(0, 16)
+ .mark(&start_of_cie)
+ .cie(kind, None, &mut cie)
+ .mark(&end_of_cie);
+
+ let mut fde1 = FrameDescriptionEntry {
+ offset: 0,
+ length: 0,
+ format: Format::Dwarf32,
+ cie: cie.clone(),
+ initial_segment: 0,
+ initial_address: 9,
+ address_range: 4,
+ augmentation: None,
+ instructions: EndianSlice::new(&[], LittleEndian),
+ };
+ let mut fde2 = FrameDescriptionEntry {
+ offset: 0,
+ length: 0,
+ format: Format::Dwarf32,
+ cie: cie.clone(),
+ initial_segment: 0,
+ initial_address: 20,
+ address_range: 8,
+ augmentation: None,
+ instructions: EndianSlice::new(&[], LittleEndian),
+ };
+
+ let start_of_fde1 = Label::new();
+ let start_of_fde2 = Label::new();
+
+ let section = section
+ // +4 for the FDE length before the CIE offset.
+ .mark(&start_of_fde1)
+ .fde(kind, (&start_of_fde1 - &start_of_cie + 4) as u64, &mut fde1)
+ .mark(&start_of_fde2)
+ .fde(kind, (&start_of_fde2 - &start_of_cie + 4) as u64, &mut fde2);
+
+ section.start().set_const(0);
+ let section = section.get_contents().unwrap();
+ let section = EndianSlice::new(&section, LittleEndian);
+ let eh_frame = kind.section(&section);
+
+ // Setup eh_frame_hdr
+ let section = Section::with_endian(kind.endian())
+ .L8(1)
+ .L8(0x0b)
+ .L8(0x03)
+ .L8(0x0b)
+ .L32(0x12345)
+ .L32(2)
+ .L32(10)
+ .L32(0x12345 + start_of_fde1.value().unwrap() as u32)
+ .L32(20)
+ .L32(0x12345 + start_of_fde2.value().unwrap() as u32);
+
+ let section = section.get_contents().unwrap();
+ let bases = BaseAddresses::default();
+ let eh_frame_hdr = EhFrameHdr::new(&section, LittleEndian).parse(&bases, 8);
+ assert!(eh_frame_hdr.is_ok());
+ let eh_frame_hdr = eh_frame_hdr.unwrap();
+
+ let table = eh_frame_hdr.table();
+ assert!(table.is_some());
+ let table = table.unwrap();
+
+ let bases = Default::default();
+ let mut iter = table.iter(&bases);
+ assert_eq!(
+ iter.next(),
+ Ok(Some((
+ Pointer::Direct(10),
+ Pointer::Direct(0x12345 + start_of_fde1.value().unwrap() as u64)
+ )))
+ );
+ assert_eq!(
+ iter.next(),
+ Ok(Some((
+ Pointer::Direct(20),
+ Pointer::Direct(0x12345 + start_of_fde2.value().unwrap() as u64)
+ )))
+ );
+ assert_eq!(iter.next(), Ok(None));
+
+ assert_eq!(
+ table.iter(&bases).nth(0),
+ Ok(Some((
+ Pointer::Direct(10),
+ Pointer::Direct(0x12345 + start_of_fde1.value().unwrap() as u64)
+ )))
+ );
+
+ assert_eq!(
+ table.iter(&bases).nth(1),
+ Ok(Some((
+ Pointer::Direct(20),
+ Pointer::Direct(0x12345 + start_of_fde2.value().unwrap() as u64)
+ )))
+ );
+ assert_eq!(table.iter(&bases).nth(2), Ok(None));
+
+ let f = |_: &_, _: &_, o: EhFrameOffset| {
+ assert_eq!(o, EhFrameOffset(start_of_cie.value().unwrap() as usize));
+ Ok(cie.clone())
+ };
+ assert_eq!(
+ table.fde_for_address(&eh_frame, &bases, 9, f),
+ Ok(fde1.clone())
+ );
+ assert_eq!(
+ table.fde_for_address(&eh_frame, &bases, 10, f),
+ Ok(fde1.clone())
+ );
+ assert_eq!(table.fde_for_address(&eh_frame, &bases, 11, f), Ok(fde1));
+ assert_eq!(
+ table.fde_for_address(&eh_frame, &bases, 19, f),
+ Err(Error::NoUnwindInfoForAddress)
+ );
+ assert_eq!(
+ table.fde_for_address(&eh_frame, &bases, 20, f),
+ Ok(fde2.clone())
+ );
+ assert_eq!(table.fde_for_address(&eh_frame, &bases, 21, f), Ok(fde2));
+ assert_eq!(
+ table.fde_for_address(&eh_frame, &bases, 100_000, f),
+ Err(Error::NoUnwindInfoForAddress)
+ );
+ }
+
+ #[test]
+ fn test_eh_frame_stops_at_zero_length() {
+ let section = Section::with_endian(Endian::Little).L32(0);
+ let section = section.get_contents().unwrap();
+ let rest = &mut EndianSlice::new(&section, LittleEndian);
+ let bases = Default::default();
+
+ assert_eq!(
+ parse_cfi_entry(&bases, &EhFrame::new(&*section, LittleEndian), rest),
+ Ok(None)
+ );
+
+ assert_eq!(
+ EhFrame::new(&section, LittleEndian).cie_from_offset(&bases, EhFrameOffset(0)),
+ Err(Error::NoEntryAtGivenOffset)
+ );
+ }
+
+ fn resolve_cie_offset(buf: &[u8], cie_offset: usize) -> Result<usize> {
+ let mut fde = FrameDescriptionEntry {
+ offset: 0,
+ length: 0,
+ format: Format::Dwarf64,
+ cie: make_test_cie(),
+ initial_segment: 0,
+ initial_address: 0xfeed_beef,
+ address_range: 39,
+ augmentation: None,
+ instructions: EndianSlice::new(&[], LittleEndian),
+ };
+
+ let kind = eh_frame_le();
+ let section = Section::with_endian(kind.endian())
+ .append_bytes(&buf)
+ .fde(kind, cie_offset as u64, &mut fde)
+ .append_bytes(&buf);
+
+ let section = section.get_contents().unwrap();
+ let eh_frame = kind.section(&section);
+ let input = &mut EndianSlice::new(&section[buf.len()..], LittleEndian);
+
+ let bases = Default::default();
+ match parse_cfi_entry(&bases, &eh_frame, input) {
+ Ok(Some(CieOrFde::Fde(partial))) => Ok(partial.cie_offset.0),
+ Err(e) => Err(e),
+ otherwise => panic!("Unexpected result: {:#?}", otherwise),
+ }
+ }
+
+ #[test]
+ fn test_eh_frame_resolve_cie_offset_ok() {
+ let buf = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
+ let cie_offset = 2;
+ // + 4 for size of length field
+ assert_eq!(
+ resolve_cie_offset(&buf, buf.len() + 4 - cie_offset),
+ Ok(cie_offset)
+ );
+ }
+
+ #[test]
+ fn test_eh_frame_resolve_cie_offset_out_of_bounds() {
+ let buf = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
+ assert_eq!(
+ resolve_cie_offset(&buf, buf.len() + 4 + 2),
+ Err(Error::OffsetOutOfBounds)
+ );
+ }
+
+ #[test]
+ fn test_eh_frame_resolve_cie_offset_underflow() {
+ let buf = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
+ assert_eq!(
+ resolve_cie_offset(&buf, ::core::usize::MAX),
+ Err(Error::OffsetOutOfBounds)
+ );
+ }
+
+ #[test]
+ fn test_eh_frame_fde_ok() {
+ let mut cie = make_test_cie();
+ cie.format = Format::Dwarf32;
+ cie.version = 1;
+
+ let start_of_cie = Label::new();
+ let end_of_cie = Label::new();
+
+ // Write the CIE first so that its length gets set before we clone it
+ // into the FDE.
+ let kind = eh_frame_le();
+ let section = Section::with_endian(kind.endian())
+ .append_repeated(0, 16)
+ .mark(&start_of_cie)
+ .cie(kind, None, &mut cie)
+ .mark(&end_of_cie);
+
+ let mut fde = FrameDescriptionEntry {
+ offset: 0,
+ length: 0,
+ format: Format::Dwarf32,
+ cie: cie.clone(),
+ initial_segment: 0,
+ initial_address: 0xfeed_beef,
+ address_range: 999,
+ augmentation: None,
+ instructions: EndianSlice::new(&[], LittleEndian),
+ };
+
+ let section = section
+ // +4 for the FDE length before the CIE offset.
+ .fde(kind, (&end_of_cie - &start_of_cie + 4) as u64, &mut fde);
+
+ section.start().set_const(0);
+ let section = section.get_contents().unwrap();
+ let eh_frame = kind.section(&section);
+ let section = EndianSlice::new(&section, LittleEndian);
+
+ let mut offset = None;
+ match parse_fde(
+ eh_frame,
+ &mut section.range_from(end_of_cie.value().unwrap() as usize..),
+ |_, _, o| {
+ offset = Some(o);
+ assert_eq!(o, EhFrameOffset(start_of_cie.value().unwrap() as usize));
+ Ok(cie.clone())
+ },
+ ) {
+ Ok(actual) => assert_eq!(actual, fde),
+ otherwise => panic!("Unexpected result {:?}", otherwise),
+ }
+ assert!(offset.is_some());
+ }
+
+ #[test]
+ fn test_eh_frame_fde_out_of_bounds() {
+ let mut cie = make_test_cie();
+ cie.version = 1;
+
+ let end_of_cie = Label::new();
+
+ let mut fde = FrameDescriptionEntry {
+ offset: 0,
+ length: 0,
+ format: Format::Dwarf64,
+ cie: cie.clone(),
+ initial_segment: 0,
+ initial_address: 0xfeed_beef,
+ address_range: 999,
+ augmentation: None,
+ instructions: EndianSlice::new(&[], LittleEndian),
+ };
+
+ let kind = eh_frame_le();
+ let section = Section::with_endian(kind.endian())
+ .cie(kind, None, &mut cie)
+ .mark(&end_of_cie)
+ .fde(kind, 99_999_999_999_999, &mut fde);
+
+ section.start().set_const(0);
+ let section = section.get_contents().unwrap();
+ let eh_frame = kind.section(&section);
+ let section = EndianSlice::new(&section, LittleEndian);
+
+ let result = parse_fde(
+ eh_frame,
+ &mut section.range_from(end_of_cie.value().unwrap() as usize..),
+ UnwindSection::cie_from_offset,
+ );
+ assert_eq!(result, Err(Error::OffsetOutOfBounds));
+ }
+
+ #[test]
+ fn test_augmentation_parse_not_z_augmentation() {
+ let augmentation = &mut EndianSlice::new(b"wtf", NativeEndian);
+ let bases = Default::default();
+ let address_size = 8;
+ let section = EhFrame::new(&[], NativeEndian);
+ let input = &mut EndianSlice::new(&[], NativeEndian);
+ assert_eq!(
+ Augmentation::parse(augmentation, &bases, address_size, &section, input),
+ Err(Error::UnknownAugmentation)
+ );
+ }
+
+ #[test]
+ fn test_augmentation_parse_just_signal_trampoline() {
+ let aug_str = &mut EndianSlice::new(b"S", LittleEndian);
+ let bases = Default::default();
+ let address_size = 8;
+ let section = EhFrame::new(&[], LittleEndian);
+ let input = &mut EndianSlice::new(&[], LittleEndian);
+
+ let mut augmentation = Augmentation::default();
+ augmentation.is_signal_trampoline = true;
+
+ assert_eq!(
+ Augmentation::parse(aug_str, &bases, address_size, &section, input),
+ Ok(augmentation)
+ );
+ }
+
+ #[test]
+ fn test_augmentation_parse_unknown_part_of_z_augmentation() {
+ // The 'Z' character is not defined by the z-style augmentation.
+ let bases = Default::default();
+ let address_size = 8;
+ let section = Section::with_endian(Endian::Little)
+ .uleb(4)
+ .append_repeated(4, 4)
+ .get_contents()
+ .unwrap();
+ let section = EhFrame::new(&section, LittleEndian);
+ let input = &mut section.section().clone();
+ let augmentation = &mut EndianSlice::new(b"zZ", LittleEndian);
+ assert_eq!(
+ Augmentation::parse(augmentation, &bases, address_size, &section, input),
+ Err(Error::UnknownAugmentation)
+ );
+ }
+
+ #[test]
+ #[allow(non_snake_case)]
+ fn test_augmentation_parse_L() {
+ let bases = Default::default();
+ let address_size = 8;
+ let rest = [9, 8, 7, 6, 5, 4, 3, 2, 1];
+
+ let section = Section::with_endian(Endian::Little)
+ .uleb(1)
+ .D8(constants::DW_EH_PE_uleb128.0)
+ .append_bytes(&rest)
+ .get_contents()
+ .unwrap();
+ let section = EhFrame::new(&section, LittleEndian);
+ let input = &mut section.section().clone();
+ let aug_str = &mut EndianSlice::new(b"zL", LittleEndian);
+
+ let mut augmentation = Augmentation::default();
+ augmentation.lsda = Some(constants::DW_EH_PE_uleb128);
+
+ assert_eq!(
+ Augmentation::parse(aug_str, &bases, address_size, &section, input),
+ Ok(augmentation)
+ );
+ assert_eq!(*input, EndianSlice::new(&rest, LittleEndian));
+ }
+
+ #[test]
+ #[allow(non_snake_case)]
+ fn test_augmentation_parse_P() {
+ let bases = Default::default();
+ let address_size = 8;
+ let rest = [9, 8, 7, 6, 5, 4, 3, 2, 1];
+
+ let section = Section::with_endian(Endian::Little)
+ .uleb(9)
+ .D8(constants::DW_EH_PE_udata8.0)
+ .L64(0xf00d_f00d)
+ .append_bytes(&rest)
+ .get_contents()
+ .unwrap();
+ let section = EhFrame::new(&section, LittleEndian);
+ let input = &mut section.section().clone();
+ let aug_str = &mut EndianSlice::new(b"zP", LittleEndian);
+
+ let mut augmentation = Augmentation::default();
+ augmentation.personality = Some((constants::DW_EH_PE_udata8, Pointer::Direct(0xf00d_f00d)));
+
+ assert_eq!(
+ Augmentation::parse(aug_str, &bases, address_size, &section, input),
+ Ok(augmentation)
+ );
+ assert_eq!(*input, EndianSlice::new(&rest, LittleEndian));
+ }
+
+ #[test]
+ #[allow(non_snake_case)]
+ fn test_augmentation_parse_R() {
+ let bases = Default::default();
+ let address_size = 8;
+ let rest = [9, 8, 7, 6, 5, 4, 3, 2, 1];
+
+ let section = Section::with_endian(Endian::Little)
+ .uleb(1)
+ .D8(constants::DW_EH_PE_udata4.0)
+ .append_bytes(&rest)
+ .get_contents()
+ .unwrap();
+ let section = EhFrame::new(&section, LittleEndian);
+ let input = &mut section.section().clone();
+ let aug_str = &mut EndianSlice::new(b"zR", LittleEndian);
+
+ let mut augmentation = Augmentation::default();
+ augmentation.fde_address_encoding = Some(constants::DW_EH_PE_udata4);
+
+ assert_eq!(
+ Augmentation::parse(aug_str, &bases, address_size, &section, input),
+ Ok(augmentation)
+ );
+ assert_eq!(*input, EndianSlice::new(&rest, LittleEndian));
+ }
+
+ #[test]
+ #[allow(non_snake_case)]
+ fn test_augmentation_parse_S() {
+ let bases = Default::default();
+ let address_size = 8;
+ let rest = [9, 8, 7, 6, 5, 4, 3, 2, 1];
+
+ let section = Section::with_endian(Endian::Little)
+ .uleb(0)
+ .append_bytes(&rest)
+ .get_contents()
+ .unwrap();
+ let section = EhFrame::new(&section, LittleEndian);
+ let input = &mut section.section().clone();
+ let aug_str = &mut EndianSlice::new(b"zS", LittleEndian);
+
+ let mut augmentation = Augmentation::default();
+ augmentation.is_signal_trampoline = true;
+
+ assert_eq!(
+ Augmentation::parse(aug_str, &bases, address_size, &section, input),
+ Ok(augmentation)
+ );
+ assert_eq!(*input, EndianSlice::new(&rest, LittleEndian));
+ }
+
+ #[test]
+ fn test_augmentation_parse_all() {
+ let bases = Default::default();
+ let address_size = 8;
+ let rest = [9, 8, 7, 6, 5, 4, 3, 2, 1];
+
+ let section = Section::with_endian(Endian::Little)
+ .uleb(1 + 9 + 1)
+ // L
+ .D8(constants::DW_EH_PE_uleb128.0)
+ // P
+ .D8(constants::DW_EH_PE_udata8.0)
+ .L64(0x1bad_f00d)
+ // R
+ .D8(constants::DW_EH_PE_uleb128.0)
+ .append_bytes(&rest)
+ .get_contents()
+ .unwrap();
+ let section = EhFrame::new(&section, LittleEndian);
+ let input = &mut section.section().clone();
+ let aug_str = &mut EndianSlice::new(b"zLPRS", LittleEndian);
+
+ let augmentation = Augmentation {
+ lsda: Some(constants::DW_EH_PE_uleb128),
+ personality: Some((constants::DW_EH_PE_udata8, Pointer::Direct(0x1bad_f00d))),
+ fde_address_encoding: Some(constants::DW_EH_PE_uleb128),
+ is_signal_trampoline: true,
+ };
+
+ assert_eq!(
+ Augmentation::parse(aug_str, &bases, address_size, &section, input),
+ Ok(augmentation)
+ );
+ assert_eq!(*input, EndianSlice::new(&rest, LittleEndian));
+ }
+
+ #[test]
+ fn test_eh_frame_fde_no_augmentation() {
+ let instrs = [1, 2, 3, 4];
+ let cie_offset = 1;
+
+ let mut cie = make_test_cie();
+ cie.format = Format::Dwarf32;
+ cie.version = 1;
+
+ let mut fde = FrameDescriptionEntry {
+ offset: 0,
+ length: 0,
+ format: Format::Dwarf32,
+ cie: cie.clone(),
+ initial_segment: 0,
+ initial_address: 0xfeed_face,
+ address_range: 9000,
+ augmentation: None,
+ instructions: EndianSlice::new(&instrs, LittleEndian),
+ };
+
+ let rest = [1, 2, 3, 4];
+
+ let kind = eh_frame_le();
+ let section = Section::with_endian(kind.endian())
+ .fde(kind, cie_offset, &mut fde)
+ .append_bytes(&rest)
+ .get_contents()
+ .unwrap();
+ let section = kind.section(&section);
+ let input = &mut section.section().clone();
+
+ let result = parse_fde(section, input, |_, _, _| Ok(cie.clone()));
+ assert_eq!(result, Ok(fde));
+ assert_eq!(*input, EndianSlice::new(&rest, LittleEndian));
+ }
+
+ #[test]
+ fn test_eh_frame_fde_empty_augmentation() {
+ let instrs = [1, 2, 3, 4];
+ let cie_offset = 1;
+
+ let mut cie = make_test_cie();
+ cie.format = Format::Dwarf32;
+ cie.version = 1;
+ cie.augmentation = Some(Augmentation::default());
+
+ let mut fde = FrameDescriptionEntry {
+ offset: 0,
+ length: 0,
+ format: Format::Dwarf32,
+ cie: cie.clone(),
+ initial_segment: 0,
+ initial_address: 0xfeed_face,
+ address_range: 9000,
+ augmentation: Some(AugmentationData::default()),
+ instructions: EndianSlice::new(&instrs, LittleEndian),
+ };
+
+ let rest = [1, 2, 3, 4];
+
+ let kind = eh_frame_le();
+ let section = Section::with_endian(kind.endian())
+ .fde(kind, cie_offset, &mut fde)
+ .append_bytes(&rest)
+ .get_contents()
+ .unwrap();
+ let section = kind.section(&section);
+ let input = &mut section.section().clone();
+
+ let result = parse_fde(section, input, |_, _, _| Ok(cie.clone()));
+ assert_eq!(result, Ok(fde));
+ assert_eq!(*input, EndianSlice::new(&rest, LittleEndian));
+ }
+
+ #[test]
+ fn test_eh_frame_fde_lsda_augmentation() {
+ let instrs = [1, 2, 3, 4];
+ let cie_offset = 1;
+
+ let mut cie = make_test_cie();
+ cie.format = Format::Dwarf32;
+ cie.version = 1;
+ cie.augmentation = Some(Augmentation::default());
+ cie.augmentation.as_mut().unwrap().lsda = Some(constants::DW_EH_PE_absptr);
+
+ let mut fde = FrameDescriptionEntry {
+ offset: 0,
+ length: 0,
+ format: Format::Dwarf32,
+ cie: cie.clone(),
+ initial_segment: 0,
+ initial_address: 0xfeed_face,
+ address_range: 9000,
+ augmentation: Some(AugmentationData {
+ lsda: Some(Pointer::Direct(0x1122_3344)),
+ }),
+ instructions: EndianSlice::new(&instrs, LittleEndian),
+ };
+
+ let rest = [1, 2, 3, 4];
+
+ let kind = eh_frame_le();
+ let section = Section::with_endian(kind.endian())
+ .fde(kind, cie_offset, &mut fde)
+ .append_bytes(&rest)
+ .get_contents()
+ .unwrap();
+ let section = kind.section(&section);
+ let input = &mut section.section().clone();
+
+ let result = parse_fde(section, input, |_, _, _| Ok(cie.clone()));
+ assert_eq!(result, Ok(fde));
+ assert_eq!(*input, EndianSlice::new(&rest, LittleEndian));
+ }
+
+ #[test]
+ fn test_eh_frame_fde_lsda_function_relative() {
+ let instrs = [1, 2, 3, 4];
+ let cie_offset = 1;
+
+ let mut cie = make_test_cie();
+ cie.format = Format::Dwarf32;
+ cie.version = 1;
+ cie.augmentation = Some(Augmentation::default());
+ cie.augmentation.as_mut().unwrap().lsda = Some(constants::DwEhPe(
+ constants::DW_EH_PE_funcrel.0 | constants::DW_EH_PE_absptr.0,
+ ));
+
+ let mut fde = FrameDescriptionEntry {
+ offset: 0,
+ length: 0,
+ format: Format::Dwarf32,
+ cie: cie.clone(),
+ initial_segment: 0,
+ initial_address: 0xfeed_face,
+ address_range: 9000,
+ augmentation: Some(AugmentationData {
+ lsda: Some(Pointer::Direct(0xbeef)),
+ }),
+ instructions: EndianSlice::new(&instrs, LittleEndian),
+ };
+
+ let rest = [1, 2, 3, 4];
+
+ let kind = eh_frame_le();
+ let section = Section::with_endian(kind.endian())
+ .append_repeated(10, 10)
+ .fde(kind, cie_offset, &mut fde)
+ .append_bytes(&rest)
+ .get_contents()
+ .unwrap();
+ let section = kind.section(&section);
+ let input = &mut section.section().range_from(10..);
+
+ // Adjust the FDE's augmentation to be relative to the function.
+ fde.augmentation.as_mut().unwrap().lsda = Some(Pointer::Direct(0xfeed_face + 0xbeef));
+
+ let result = parse_fde(section, input, |_, _, _| Ok(cie.clone()));
+ assert_eq!(result, Ok(fde));
+ assert_eq!(*input, EndianSlice::new(&rest, LittleEndian));
+ }
+
+ #[test]
+ fn test_eh_frame_cie_personality_function_relative_bad_context() {
+ let instrs = [1, 2, 3, 4];
+
+ let length = Label::new();
+ let start = Label::new();
+ let end = Label::new();
+
+ let aug_len = Label::new();
+ let aug_start = Label::new();
+ let aug_end = Label::new();
+
+ let section = Section::with_endian(Endian::Little)
+ // Length
+ .L32(&length)
+ .mark(&start)
+ // CIE ID
+ .L32(0)
+ // Version
+ .D8(1)
+ // Augmentation
+ .append_bytes(b"zP\0")
+ // Code alignment factor
+ .uleb(1)
+ // Data alignment factor
+ .sleb(1)
+ // Return address register
+ .uleb(1)
+ // Augmentation data length. This is a uleb, be we rely on the value
+ // being less than 2^7 and therefore a valid uleb (can't use Label
+ // with uleb).
+ .D8(&aug_len)
+ .mark(&aug_start)
+ // Augmentation data. Personality encoding and then encoded pointer.
+ .D8(constants::DW_EH_PE_funcrel.0 | constants::DW_EH_PE_uleb128.0)
+ .uleb(1)
+ .mark(&aug_end)
+ // Initial instructions
+ .append_bytes(&instrs)
+ .mark(&end);
+
+ length.set_const((&end - &start) as u64);
+ aug_len.set_const((&aug_end - &aug_start) as u64);
+
+ let section = section.get_contents().unwrap();
+ let section = EhFrame::new(&section, LittleEndian);
+
+ let bases = BaseAddresses::default();
+ let mut iter = section.entries(&bases);
+ assert_eq!(iter.next(), Err(Error::FuncRelativePointerInBadContext));
+ }
+
+ #[test]
+ fn register_rule_map_eq() {
+ // Different order, but still equal.
+ let map1: RegisterRuleMap<EndianSlice<LittleEndian>> = [
+ (Register(0), RegisterRule::SameValue),
+ (Register(3), RegisterRule::Offset(1)),
+ ]
+ .iter()
+ .collect();
+ let map2: RegisterRuleMap<EndianSlice<LittleEndian>> = [
+ (Register(3), RegisterRule::Offset(1)),
+ (Register(0), RegisterRule::SameValue),
+ ]
+ .iter()
+ .collect();
+ assert_eq!(map1, map2);
+ assert_eq!(map2, map1);
+
+ // Not equal.
+ let map3: RegisterRuleMap<EndianSlice<LittleEndian>> = [
+ (Register(0), RegisterRule::SameValue),
+ (Register(2), RegisterRule::Offset(1)),
+ ]
+ .iter()
+ .collect();
+ let map4: RegisterRuleMap<EndianSlice<LittleEndian>> = [
+ (Register(3), RegisterRule::Offset(1)),
+ (Register(0), RegisterRule::SameValue),
+ ]
+ .iter()
+ .collect();
+ assert!(map3 != map4);
+ assert!(map4 != map3);
+
+ // One has undefined explicitly set, other implicitly has undefined.
+ let mut map5 = RegisterRuleMap::<EndianSlice<LittleEndian>>::default();
+ map5.set(Register(0), RegisterRule::SameValue).unwrap();
+ map5.set(Register(0), RegisterRule::Undefined).unwrap();
+ let map6 = RegisterRuleMap::<EndianSlice<LittleEndian>>::default();
+ assert_eq!(map5, map6);
+ assert_eq!(map6, map5);
+ }
+
+ #[test]
+ fn iter_register_rules() {
+ let mut row = UnwindTableRow::<EndianSlice<LittleEndian>>::default();
+ row.registers = [
+ (Register(0), RegisterRule::SameValue),
+ (Register(1), RegisterRule::Offset(1)),
+ (Register(2), RegisterRule::ValOffset(2)),
+ ]
+ .iter()
+ .collect();
+
+ let mut found0 = false;
+ let mut found1 = false;
+ let mut found2 = false;
+
+ for &(register, ref rule) in row.registers() {
+ match register.0 {
+ 0 => {
+ assert_eq!(found0, false);
+ found0 = true;
+ assert_eq!(*rule, RegisterRule::SameValue);
+ }
+ 1 => {
+ assert_eq!(found1, false);
+ found1 = true;
+ assert_eq!(*rule, RegisterRule::Offset(1));
+ }
+ 2 => {
+ assert_eq!(found2, false);
+ found2 = true;
+ assert_eq!(*rule, RegisterRule::ValOffset(2));
+ }
+ x => panic!("Unexpected register rule: ({}, {:?})", x, rule),
+ }
+ }
+
+ assert_eq!(found0, true);
+ assert_eq!(found1, true);
+ assert_eq!(found2, true);
+ }
+
+ #[test]
+ #[cfg(target_pointer_width = "64")]
+ fn size_of_unwind_ctx() {
+ use core::mem;
+ let size = mem::size_of::<UnwindContext<EndianSlice<NativeEndian>>>();
+ let max_size = 30968;
+ if size > max_size {
+ assert_eq!(size, max_size);
+ }
+ }
+
+ #[test]
+ #[cfg(target_pointer_width = "64")]
+ fn size_of_register_rule_map() {
+ use core::mem;
+ let size = mem::size_of::<RegisterRuleMap<EndianSlice<NativeEndian>>>();
+ let max_size = 6152;
+ if size > max_size {
+ assert_eq!(size, max_size);
+ }
+ }
+
+ #[test]
+ fn test_parse_pointer_encoding_ok() {
+ use crate::endianity::NativeEndian;
+ let expected =
+ constants::DwEhPe(constants::DW_EH_PE_uleb128.0 | constants::DW_EH_PE_pcrel.0);
+ let input = [expected.0, 1, 2, 3, 4];
+ let input = &mut EndianSlice::new(&input, NativeEndian);
+ assert_eq!(parse_pointer_encoding(input), Ok(expected));
+ assert_eq!(*input, EndianSlice::new(&[1, 2, 3, 4], NativeEndian));
+ }
+
+ #[test]
+ fn test_parse_pointer_encoding_bad_encoding() {
+ use crate::endianity::NativeEndian;
+ let expected =
+ constants::DwEhPe((constants::DW_EH_PE_sdata8.0 + 1) | constants::DW_EH_PE_pcrel.0);
+ let input = [expected.0, 1, 2, 3, 4];
+ let input = &mut EndianSlice::new(&input, NativeEndian);
+ assert_eq!(
+ Err(Error::UnknownPointerEncoding),
+ parse_pointer_encoding(input)
+ );
+ }
+
+ #[test]
+ fn test_parse_encoded_pointer_absptr() {
+ let encoding = constants::DW_EH_PE_absptr;
+ let expected_rest = [1, 2, 3, 4];
+
+ let input = Section::with_endian(Endian::Little)
+ .L32(0xf00d_f00d)
+ .append_bytes(&expected_rest);
+ let input = input.get_contents().unwrap();
+ let input = EndianSlice::new(&input, LittleEndian);
+ let mut rest = input;
+
+ let parameters = PointerEncodingParameters {
+ bases: &SectionBaseAddresses::default(),
+ func_base: None,
+ address_size: 4,
+ section: &input,
+ };
+ assert_eq!(
+ parse_encoded_pointer(encoding, &parameters, &mut rest),
+ Ok(Pointer::Direct(0xf00d_f00d))
+ );
+ assert_eq!(rest, EndianSlice::new(&expected_rest, LittleEndian));
+ }
+
+ #[test]
+ fn test_parse_encoded_pointer_pcrel() {
+ let encoding = constants::DW_EH_PE_pcrel;
+ let expected_rest = [1, 2, 3, 4];
+
+ let input = Section::with_endian(Endian::Little)
+ .append_repeated(0, 0x10)
+ .L32(0x1)
+ .append_bytes(&expected_rest);
+ let input = input.get_contents().unwrap();
+ let input = EndianSlice::new(&input, LittleEndian);
+ let mut rest = input.range_from(0x10..);
+
+ let parameters = PointerEncodingParameters {
+ bases: &BaseAddresses::default().set_eh_frame(0x100).eh_frame,
+ func_base: None,
+ address_size: 4,
+ section: &input,
+ };
+ assert_eq!(
+ parse_encoded_pointer(encoding, &parameters, &mut rest),
+ Ok(Pointer::Direct(0x111))
+ );
+ assert_eq!(rest, EndianSlice::new(&expected_rest, LittleEndian));
+ }
+
+ #[test]
+ fn test_parse_encoded_pointer_pcrel_undefined() {
+ let encoding = constants::DW_EH_PE_pcrel;
+
+ let input = Section::with_endian(Endian::Little).L32(0x1);
+ let input = input.get_contents().unwrap();
+ let input = EndianSlice::new(&input, LittleEndian);
+ let mut rest = input;
+
+ let parameters = PointerEncodingParameters {
+ bases: &SectionBaseAddresses::default(),
+ func_base: None,
+ address_size: 4,
+ section: &input,
+ };
+ assert_eq!(
+ parse_encoded_pointer(encoding, &parameters, &mut rest),
+ Err(Error::PcRelativePointerButSectionBaseIsUndefined)
+ );
+ }
+
+ #[test]
+ fn test_parse_encoded_pointer_textrel() {
+ let encoding = constants::DW_EH_PE_textrel;
+ let expected_rest = [1, 2, 3, 4];
+
+ let input = Section::with_endian(Endian::Little)
+ .L32(0x1)
+ .append_bytes(&expected_rest);
+ let input = input.get_contents().unwrap();
+ let input = EndianSlice::new(&input, LittleEndian);
+ let mut rest = input;
+
+ let parameters = PointerEncodingParameters {
+ bases: &BaseAddresses::default().set_text(0x10).eh_frame,
+ func_base: None,
+ address_size: 4,
+ section: &input,
+ };
+ assert_eq!(
+ parse_encoded_pointer(encoding, &parameters, &mut rest),
+ Ok(Pointer::Direct(0x11))
+ );
+ assert_eq!(rest, EndianSlice::new(&expected_rest, LittleEndian));
+ }
+
+ #[test]
+ fn test_parse_encoded_pointer_textrel_undefined() {
+ let encoding = constants::DW_EH_PE_textrel;
+
+ let input = Section::with_endian(Endian::Little).L32(0x1);
+ let input = input.get_contents().unwrap();
+ let input = EndianSlice::new(&input, LittleEndian);
+ let mut rest = input;
+
+ let parameters = PointerEncodingParameters {
+ bases: &SectionBaseAddresses::default(),
+ func_base: None,
+ address_size: 4,
+ section: &input,
+ };
+ assert_eq!(
+ parse_encoded_pointer(encoding, &parameters, &mut rest),
+ Err(Error::TextRelativePointerButTextBaseIsUndefined)
+ );
+ }
+
+ #[test]
+ fn test_parse_encoded_pointer_datarel() {
+ let encoding = constants::DW_EH_PE_datarel;
+ let expected_rest = [1, 2, 3, 4];
+
+ let input = Section::with_endian(Endian::Little)
+ .L32(0x1)
+ .append_bytes(&expected_rest);
+ let input = input.get_contents().unwrap();
+ let input = EndianSlice::new(&input, LittleEndian);
+ let mut rest = input;
+
+ let parameters = PointerEncodingParameters {
+ bases: &BaseAddresses::default().set_got(0x10).eh_frame,
+ func_base: None,
+ address_size: 4,
+ section: &input,
+ };
+ assert_eq!(
+ parse_encoded_pointer(encoding, &parameters, &mut rest),
+ Ok(Pointer::Direct(0x11))
+ );
+ assert_eq!(rest, EndianSlice::new(&expected_rest, LittleEndian));
+ }
+
+ #[test]
+ fn test_parse_encoded_pointer_datarel_undefined() {
+ let encoding = constants::DW_EH_PE_datarel;
+
+ let input = Section::with_endian(Endian::Little).L32(0x1);
+ let input = input.get_contents().unwrap();
+ let input = EndianSlice::new(&input, LittleEndian);
+ let mut rest = input;
+
+ let parameters = PointerEncodingParameters {
+ bases: &SectionBaseAddresses::default(),
+ func_base: None,
+ address_size: 4,
+ section: &input,
+ };
+ assert_eq!(
+ parse_encoded_pointer(encoding, &parameters, &mut rest),
+ Err(Error::DataRelativePointerButDataBaseIsUndefined)
+ );
+ }
+
+ #[test]
+ fn test_parse_encoded_pointer_funcrel() {
+ let encoding = constants::DW_EH_PE_funcrel;
+ let expected_rest = [1, 2, 3, 4];
+
+ let input = Section::with_endian(Endian::Little)
+ .L32(0x1)
+ .append_bytes(&expected_rest);
+ let input = input.get_contents().unwrap();
+ let input = EndianSlice::new(&input, LittleEndian);
+ let mut rest = input;
+
+ let parameters = PointerEncodingParameters {
+ bases: &SectionBaseAddresses::default(),
+ func_base: Some(0x10),
+ address_size: 4,
+ section: &input,
+ };
+ assert_eq!(
+ parse_encoded_pointer(encoding, &parameters, &mut rest),
+ Ok(Pointer::Direct(0x11))
+ );
+ assert_eq!(rest, EndianSlice::new(&expected_rest, LittleEndian));
+ }
+
+ #[test]
+ fn test_parse_encoded_pointer_funcrel_undefined() {
+ let encoding = constants::DW_EH_PE_funcrel;
+
+ let input = Section::with_endian(Endian::Little).L32(0x1);
+ let input = input.get_contents().unwrap();
+ let input = EndianSlice::new(&input, LittleEndian);
+ let mut rest = input;
+
+ let parameters = PointerEncodingParameters {
+ bases: &SectionBaseAddresses::default(),
+ func_base: None,
+ address_size: 4,
+ section: &input,
+ };
+ assert_eq!(
+ parse_encoded_pointer(encoding, &parameters, &mut rest),
+ Err(Error::FuncRelativePointerInBadContext)
+ );
+ }
+
+ #[test]
+ fn test_parse_encoded_pointer_uleb128() {
+ let encoding =
+ constants::DwEhPe(constants::DW_EH_PE_absptr.0 | constants::DW_EH_PE_uleb128.0);
+ let expected_rest = [1, 2, 3, 4];
+
+ let input = Section::with_endian(Endian::Little)
+ .uleb(0x12_3456)
+ .append_bytes(&expected_rest);
+ let input = input.get_contents().unwrap();
+ let input = EndianSlice::new(&input, LittleEndian);
+ let mut rest = input;
+
+ let parameters = PointerEncodingParameters {
+ bases: &SectionBaseAddresses::default(),
+ func_base: None,
+ address_size: 4,
+ section: &input,
+ };
+ assert_eq!(
+ parse_encoded_pointer(encoding, &parameters, &mut rest),
+ Ok(Pointer::Direct(0x12_3456))
+ );
+ assert_eq!(rest, EndianSlice::new(&expected_rest, LittleEndian));
+ }
+
+ #[test]
+ fn test_parse_encoded_pointer_udata2() {
+ let encoding =
+ constants::DwEhPe(constants::DW_EH_PE_absptr.0 | constants::DW_EH_PE_udata2.0);
+ let expected_rest = [1, 2, 3, 4];
+
+ let input = Section::with_endian(Endian::Little)
+ .L16(0x1234)
+ .append_bytes(&expected_rest);
+ let input = input.get_contents().unwrap();
+ let input = EndianSlice::new(&input, LittleEndian);
+ let mut rest = input;
+
+ let parameters = PointerEncodingParameters {
+ bases: &SectionBaseAddresses::default(),
+ func_base: None,
+ address_size: 4,
+ section: &input,
+ };
+ assert_eq!(
+ parse_encoded_pointer(encoding, &parameters, &mut rest),
+ Ok(Pointer::Direct(0x1234))
+ );
+ assert_eq!(rest, EndianSlice::new(&expected_rest, LittleEndian));
+ }
+
+ #[test]
+ fn test_parse_encoded_pointer_udata4() {
+ let encoding =
+ constants::DwEhPe(constants::DW_EH_PE_absptr.0 | constants::DW_EH_PE_udata4.0);
+ let expected_rest = [1, 2, 3, 4];
+
+ let input = Section::with_endian(Endian::Little)
+ .L32(0x1234_5678)
+ .append_bytes(&expected_rest);
+ let input = input.get_contents().unwrap();
+ let input = EndianSlice::new(&input, LittleEndian);
+ let mut rest = input;
+
+ let parameters = PointerEncodingParameters {
+ bases: &SectionBaseAddresses::default(),
+ func_base: None,
+ address_size: 4,
+ section: &input,
+ };
+ assert_eq!(
+ parse_encoded_pointer(encoding, &parameters, &mut rest),
+ Ok(Pointer::Direct(0x1234_5678))
+ );
+ assert_eq!(rest, EndianSlice::new(&expected_rest, LittleEndian));
+ }
+
+ #[test]
+ fn test_parse_encoded_pointer_udata8() {
+ let encoding =
+ constants::DwEhPe(constants::DW_EH_PE_absptr.0 | constants::DW_EH_PE_udata8.0);
+ let expected_rest = [1, 2, 3, 4];
+
+ let input = Section::with_endian(Endian::Little)
+ .L64(0x1234_5678_1234_5678)
+ .append_bytes(&expected_rest);
+ let input = input.get_contents().unwrap();
+ let input = EndianSlice::new(&input, LittleEndian);
+ let mut rest = input;
+
+ let parameters = PointerEncodingParameters {
+ bases: &SectionBaseAddresses::default(),
+ func_base: None,
+ address_size: 4,
+ section: &input,
+ };
+ assert_eq!(
+ parse_encoded_pointer(encoding, &parameters, &mut rest),
+ Ok(Pointer::Direct(0x1234_5678_1234_5678))
+ );
+ assert_eq!(rest, EndianSlice::new(&expected_rest, LittleEndian));
+ }
+
+ #[test]
+ fn test_parse_encoded_pointer_sleb128() {
+ let encoding =
+ constants::DwEhPe(constants::DW_EH_PE_textrel.0 | constants::DW_EH_PE_sleb128.0);
+ let expected_rest = [1, 2, 3, 4];
+
+ let input = Section::with_endian(Endian::Little)
+ .sleb(-0x1111)
+ .append_bytes(&expected_rest);
+ let input = input.get_contents().unwrap();
+ let input = EndianSlice::new(&input, LittleEndian);
+ let mut rest = input;
+
+ let parameters = PointerEncodingParameters {
+ bases: &BaseAddresses::default().set_text(0x1111_1111).eh_frame,
+ func_base: None,
+ address_size: 4,
+ section: &input,
+ };
+ assert_eq!(
+ parse_encoded_pointer(encoding, &parameters, &mut rest),
+ Ok(Pointer::Direct(0x1111_0000))
+ );
+ assert_eq!(rest, EndianSlice::new(&expected_rest, LittleEndian));
+ }
+
+ #[test]
+ fn test_parse_encoded_pointer_sdata2() {
+ let encoding =
+ constants::DwEhPe(constants::DW_EH_PE_absptr.0 | constants::DW_EH_PE_sdata2.0);
+ let expected_rest = [1, 2, 3, 4];
+ let expected = 0x111 as i16;
+
+ let input = Section::with_endian(Endian::Little)
+ .L16(expected as u16)
+ .append_bytes(&expected_rest);
+ let input = input.get_contents().unwrap();
+ let input = EndianSlice::new(&input, LittleEndian);
+ let mut rest = input;
+
+ let parameters = PointerEncodingParameters {
+ bases: &SectionBaseAddresses::default(),
+ func_base: None,
+ address_size: 4,
+ section: &input,
+ };
+ assert_eq!(
+ parse_encoded_pointer(encoding, &parameters, &mut rest),
+ Ok(Pointer::Direct(expected as u64))
+ );
+ assert_eq!(rest, EndianSlice::new(&expected_rest, LittleEndian));
+ }
+
+ #[test]
+ fn test_parse_encoded_pointer_sdata4() {
+ let encoding =
+ constants::DwEhPe(constants::DW_EH_PE_absptr.0 | constants::DW_EH_PE_sdata4.0);
+ let expected_rest = [1, 2, 3, 4];
+ let expected = 0x111_1111 as i32;
+
+ let input = Section::with_endian(Endian::Little)
+ .L32(expected as u32)
+ .append_bytes(&expected_rest);
+ let input = input.get_contents().unwrap();
+ let input = EndianSlice::new(&input, LittleEndian);
+ let mut rest = input;
+
+ let parameters = PointerEncodingParameters {
+ bases: &SectionBaseAddresses::default(),
+ func_base: None,
+ address_size: 4,
+ section: &input,
+ };
+ assert_eq!(
+ parse_encoded_pointer(encoding, &parameters, &mut rest),
+ Ok(Pointer::Direct(expected as u64))
+ );
+ assert_eq!(rest, EndianSlice::new(&expected_rest, LittleEndian));
+ }
+
+ #[test]
+ fn test_parse_encoded_pointer_sdata8() {
+ let encoding =
+ constants::DwEhPe(constants::DW_EH_PE_absptr.0 | constants::DW_EH_PE_sdata8.0);
+ let expected_rest = [1, 2, 3, 4];
+ let expected = -0x11_1111_1222_2222 as i64;
+
+ let input = Section::with_endian(Endian::Little)
+ .L64(expected as u64)
+ .append_bytes(&expected_rest);
+ let input = input.get_contents().unwrap();
+ let input = EndianSlice::new(&input, LittleEndian);
+ let mut rest = input;
+
+ let parameters = PointerEncodingParameters {
+ bases: &SectionBaseAddresses::default(),
+ func_base: None,
+ address_size: 4,
+ section: &input,
+ };
+ assert_eq!(
+ parse_encoded_pointer(encoding, &parameters, &mut rest),
+ Ok(Pointer::Direct(expected as u64))
+ );
+ assert_eq!(rest, EndianSlice::new(&expected_rest, LittleEndian));
+ }
+
+ #[test]
+ fn test_parse_encoded_pointer_omit() {
+ let encoding = constants::DW_EH_PE_omit;
+
+ let input = Section::with_endian(Endian::Little).L32(0x1);
+ let input = input.get_contents().unwrap();
+ let input = EndianSlice::new(&input, LittleEndian);
+ let mut rest = input;
+
+ let parameters = PointerEncodingParameters {
+ bases: &SectionBaseAddresses::default(),
+ func_base: None,
+ address_size: 4,
+ section: &input,
+ };
+ assert_eq!(
+ parse_encoded_pointer(encoding, &parameters, &mut rest),
+ Err(Error::CannotParseOmitPointerEncoding)
+ );
+ assert_eq!(rest, input);
+ }
+
+ #[test]
+ fn test_parse_encoded_pointer_bad_encoding() {
+ let encoding = constants::DwEhPe(constants::DW_EH_PE_sdata8.0 + 1);
+
+ let input = Section::with_endian(Endian::Little).L32(0x1);
+ let input = input.get_contents().unwrap();
+ let input = EndianSlice::new(&input, LittleEndian);
+ let mut rest = input;
+
+ let parameters = PointerEncodingParameters {
+ bases: &SectionBaseAddresses::default(),
+ func_base: None,
+ address_size: 4,
+ section: &input,
+ };
+ assert_eq!(
+ parse_encoded_pointer(encoding, &parameters, &mut rest),
+ Err(Error::UnknownPointerEncoding)
+ );
+ }
+
+ #[test]
+ fn test_parse_encoded_pointer_aligned() {
+ // FIXME: support this encoding!
+
+ let encoding = constants::DW_EH_PE_aligned;
+
+ let input = Section::with_endian(Endian::Little).L32(0x1);
+ let input = input.get_contents().unwrap();
+ let input = EndianSlice::new(&input, LittleEndian);
+ let mut rest = input;
+
+ let parameters = PointerEncodingParameters {
+ bases: &SectionBaseAddresses::default(),
+ func_base: None,
+ address_size: 4,
+ section: &input,
+ };
+ assert_eq!(
+ parse_encoded_pointer(encoding, &parameters, &mut rest),
+ Err(Error::UnsupportedPointerEncoding)
+ );
+ }
+
+ #[test]
+ fn test_parse_encoded_pointer_indirect() {
+ let expected_rest = [1, 2, 3, 4];
+ let encoding = constants::DW_EH_PE_indirect;
+
+ let input = Section::with_endian(Endian::Little)
+ .L32(0x1234_5678)
+ .append_bytes(&expected_rest);
+ let input = input.get_contents().unwrap();
+ let input = EndianSlice::new(&input, LittleEndian);
+ let mut rest = input;
+
+ let parameters = PointerEncodingParameters {
+ bases: &SectionBaseAddresses::default(),
+ func_base: None,
+ address_size: 4,
+ section: &input,
+ };
+ assert_eq!(
+ parse_encoded_pointer(encoding, &parameters, &mut rest),
+ Ok(Pointer::Indirect(0x1234_5678))
+ );
+ assert_eq!(rest, EndianSlice::new(&expected_rest, LittleEndian));
+ }
+}
diff --git a/vendor/gimli-0.26.2/src/read/dwarf.rs b/vendor/gimli-0.26.2/src/read/dwarf.rs
new file mode 100644
index 000000000..b63526941
--- /dev/null
+++ b/vendor/gimli-0.26.2/src/read/dwarf.rs
@@ -0,0 +1,1143 @@
+use alloc::string::String;
+use alloc::sync::Arc;
+
+use crate::common::{
+ DebugAddrBase, DebugAddrIndex, DebugInfoOffset, DebugLineStrOffset, DebugLocListsBase,
+ DebugLocListsIndex, DebugRngListsBase, DebugRngListsIndex, DebugStrOffset, DebugStrOffsetsBase,
+ DebugStrOffsetsIndex, DebugTypeSignature, DebugTypesOffset, DwarfFileType, DwoId, Encoding,
+ LocationListsOffset, RangeListsOffset, RawRangeListsOffset, SectionId, UnitSectionOffset,
+};
+use crate::constants;
+use crate::read::{
+ Abbreviations, AttributeValue, DebugAbbrev, DebugAddr, DebugAranges, DebugCuIndex, DebugInfo,
+ DebugInfoUnitHeadersIter, DebugLine, DebugLineStr, DebugLoc, DebugLocLists, DebugRngLists,
+ DebugStr, DebugStrOffsets, DebugTuIndex, DebugTypes, DebugTypesUnitHeadersIter,
+ DebuggingInformationEntry, EntriesCursor, EntriesRaw, EntriesTree, Error,
+ IncompleteLineProgram, LocListIter, LocationLists, Range, RangeLists, RawLocListIter,
+ RawRngListIter, Reader, ReaderOffset, ReaderOffsetId, Result, RngListIter, Section, UnitHeader,
+ UnitIndex, UnitIndexSectionIterator, UnitOffset, UnitType,
+};
+
+/// All of the commonly used DWARF sections, and other common information.
+#[derive(Debug, Default)]
+pub struct Dwarf<R> {
+ /// The `.debug_abbrev` section.
+ pub debug_abbrev: DebugAbbrev<R>,
+
+ /// The `.debug_addr` section.
+ pub debug_addr: DebugAddr<R>,
+
+ /// The `.debug_aranges` section.
+ pub debug_aranges: DebugAranges<R>,
+
+ /// The `.debug_info` section.
+ pub debug_info: DebugInfo<R>,
+
+ /// The `.debug_line` section.
+ pub debug_line: DebugLine<R>,
+
+ /// The `.debug_line_str` section.
+ pub debug_line_str: DebugLineStr<R>,
+
+ /// The `.debug_str` section.
+ pub debug_str: DebugStr<R>,
+
+ /// The `.debug_str_offsets` section.
+ pub debug_str_offsets: DebugStrOffsets<R>,
+
+ /// The `.debug_types` section.
+ pub debug_types: DebugTypes<R>,
+
+ /// The location lists in the `.debug_loc` and `.debug_loclists` sections.
+ pub locations: LocationLists<R>,
+
+ /// The range lists in the `.debug_ranges` and `.debug_rnglists` sections.
+ pub ranges: RangeLists<R>,
+
+ /// The type of this file.
+ pub file_type: DwarfFileType,
+
+ /// The DWARF sections for a supplementary object file.
+ pub sup: Option<Arc<Dwarf<R>>>,
+}
+
+impl<T> Dwarf<T> {
+ /// Try to load the DWARF sections using the given loader function.
+ ///
+ /// `section` loads a DWARF section from the object file.
+ /// It should return an empty section if the section does not exist.
+ ///
+ /// `section` may either directly return a `Reader` instance (such as
+ /// `EndianSlice`), or it may return some other type and then convert
+ /// that type into a `Reader` using `Dwarf::borrow`.
+ ///
+ /// After loading, the user should set the `file_type` field and
+ /// call `load_sup` if required.
+ pub fn load<F, E>(mut section: F) -> core::result::Result<Self, E>
+ where
+ F: FnMut(SectionId) -> core::result::Result<T, E>,
+ {
+ // Section types are inferred.
+ let debug_loc = Section::load(&mut section)?;
+ let debug_loclists = Section::load(&mut section)?;
+ let debug_ranges = Section::load(&mut section)?;
+ let debug_rnglists = Section::load(&mut section)?;
+ Ok(Dwarf {
+ debug_abbrev: Section::load(&mut section)?,
+ debug_addr: Section::load(&mut section)?,
+ debug_aranges: Section::load(&mut section)?,
+ debug_info: Section::load(&mut section)?,
+ debug_line: Section::load(&mut section)?,
+ debug_line_str: Section::load(&mut section)?,
+ debug_str: Section::load(&mut section)?,
+ debug_str_offsets: Section::load(&mut section)?,
+ debug_types: Section::load(&mut section)?,
+ locations: LocationLists::new(debug_loc, debug_loclists),
+ ranges: RangeLists::new(debug_ranges, debug_rnglists),
+ file_type: DwarfFileType::Main,
+ sup: None,
+ })
+ }
+
+ /// Load the DWARF sections from the supplementary object file.
+ ///
+ /// `section` operates the same as for `load`.
+ ///
+ /// Sets `self.sup`, replacing any previous value.
+ pub fn load_sup<F, E>(&mut self, section: F) -> core::result::Result<(), E>
+ where
+ F: FnMut(SectionId) -> core::result::Result<T, E>,
+ {
+ self.sup = Some(Arc::new(Self::load(section)?));
+ Ok(())
+ }
+
+ /// Create a `Dwarf` structure that references the data in `self`.
+ ///
+ /// This is useful when `R` implements `Reader` but `T` does not.
+ ///
+ /// ## Example Usage
+ ///
+ /// It can be useful to load DWARF sections into owned data structures,
+ /// such as `Vec`. However, we do not implement the `Reader` trait
+ /// for `Vec`, because it would be very inefficient, but this trait
+ /// is required for all of the methods that parse the DWARF data.
+ /// So we first load the DWARF sections into `Vec`s, and then use
+ /// `borrow` to create `Reader`s that reference the data.
+ ///
+ /// ```rust,no_run
+ /// # fn example() -> Result<(), gimli::Error> {
+ /// # let loader = |name| -> Result<_, gimli::Error> { unimplemented!() };
+ /// # let sup_loader = |name| -> Result<_, gimli::Error> { unimplemented!() };
+ /// // Read the DWARF sections into `Vec`s with whatever object loader you're using.
+ /// let mut owned_dwarf: gimli::Dwarf<Vec<u8>> = gimli::Dwarf::load(loader)?;
+ /// owned_dwarf.load_sup(sup_loader)?;
+ /// // Create references to the DWARF sections.
+ /// let dwarf = owned_dwarf.borrow(|section| {
+ /// gimli::EndianSlice::new(&section, gimli::LittleEndian)
+ /// });
+ /// # unreachable!()
+ /// # }
+ /// ```
+ pub fn borrow<'a, F, R>(&'a self, mut borrow: F) -> Dwarf<R>
+ where
+ F: FnMut(&'a T) -> R,
+ {
+ Dwarf {
+ debug_abbrev: self.debug_abbrev.borrow(&mut borrow),
+ debug_addr: self.debug_addr.borrow(&mut borrow),
+ debug_aranges: self.debug_aranges.borrow(&mut borrow),
+ debug_info: self.debug_info.borrow(&mut borrow),
+ debug_line: self.debug_line.borrow(&mut borrow),
+ debug_line_str: self.debug_line_str.borrow(&mut borrow),
+ debug_str: self.debug_str.borrow(&mut borrow),
+ debug_str_offsets: self.debug_str_offsets.borrow(&mut borrow),
+ debug_types: self.debug_types.borrow(&mut borrow),
+ locations: self.locations.borrow(&mut borrow),
+ ranges: self.ranges.borrow(&mut borrow),
+ file_type: self.file_type,
+ sup: self.sup().map(|sup| Arc::new(sup.borrow(borrow))),
+ }
+ }
+
+ /// Return a reference to the DWARF sections for supplementary object file.
+ pub fn sup(&self) -> Option<&Dwarf<T>> {
+ self.sup.as_ref().map(Arc::as_ref)
+ }
+}
+
+impl<R: Reader> Dwarf<R> {
+ /// Iterate the unit headers in the `.debug_info` section.
+ ///
+ /// Can be [used with
+ /// `FallibleIterator`](./index.html#using-with-fallibleiterator).
+ #[inline]
+ pub fn units(&self) -> DebugInfoUnitHeadersIter<R> {
+ self.debug_info.units()
+ }
+
+ /// Construct a new `Unit` from the given unit header.
+ #[inline]
+ pub fn unit(&self, header: UnitHeader<R>) -> Result<Unit<R>> {
+ Unit::new(self, header)
+ }
+
+ /// Iterate the type-unit headers in the `.debug_types` section.
+ ///
+ /// Can be [used with
+ /// `FallibleIterator`](./index.html#using-with-fallibleiterator).
+ #[inline]
+ pub fn type_units(&self) -> DebugTypesUnitHeadersIter<R> {
+ self.debug_types.units()
+ }
+
+ /// Parse the abbreviations for a compilation unit.
+ // TODO: provide caching of abbreviations
+ #[inline]
+ pub fn abbreviations(&self, unit: &UnitHeader<R>) -> Result<Abbreviations> {
+ unit.abbreviations(&self.debug_abbrev)
+ }
+
+ /// Return the string offset at the given index.
+ #[inline]
+ pub fn string_offset(
+ &self,
+ unit: &Unit<R>,
+ index: DebugStrOffsetsIndex<R::Offset>,
+ ) -> Result<DebugStrOffset<R::Offset>> {
+ self.debug_str_offsets
+ .get_str_offset(unit.header.format(), unit.str_offsets_base, index)
+ }
+
+ /// Return the string at the given offset in `.debug_str`.
+ #[inline]
+ pub fn string(&self, offset: DebugStrOffset<R::Offset>) -> Result<R> {
+ self.debug_str.get_str(offset)
+ }
+
+ /// Return the string at the given offset in `.debug_line_str`.
+ #[inline]
+ pub fn line_string(&self, offset: DebugLineStrOffset<R::Offset>) -> Result<R> {
+ self.debug_line_str.get_str(offset)
+ }
+
+ /// Return an attribute value as a string slice.
+ ///
+ /// If the attribute value is one of:
+ ///
+ /// - an inline `DW_FORM_string` string
+ /// - a `DW_FORM_strp` reference to an offset into the `.debug_str` section
+ /// - a `DW_FORM_strp_sup` reference to an offset into a supplementary
+ /// object file
+ /// - a `DW_FORM_line_strp` reference to an offset into the `.debug_line_str`
+ /// section
+ /// - a `DW_FORM_strx` index into the `.debug_str_offsets` entries for the unit
+ ///
+ /// then return the attribute's string value. Returns an error if the attribute
+ /// value does not have a string form, or if a string form has an invalid value.
+ pub fn attr_string(&self, unit: &Unit<R>, attr: AttributeValue<R>) -> Result<R> {
+ match attr {
+ AttributeValue::String(string) => Ok(string),
+ AttributeValue::DebugStrRef(offset) => self.debug_str.get_str(offset),
+ AttributeValue::DebugStrRefSup(offset) => {
+ if let Some(sup) = self.sup() {
+ sup.debug_str.get_str(offset)
+ } else {
+ Err(Error::ExpectedStringAttributeValue)
+ }
+ }
+ AttributeValue::DebugLineStrRef(offset) => self.debug_line_str.get_str(offset),
+ AttributeValue::DebugStrOffsetsIndex(index) => {
+ let offset = self.debug_str_offsets.get_str_offset(
+ unit.header.format(),
+ unit.str_offsets_base,
+ index,
+ )?;
+ self.debug_str.get_str(offset)
+ }
+ _ => Err(Error::ExpectedStringAttributeValue),
+ }
+ }
+
+ /// Return the address at the given index.
+ pub fn address(&self, unit: &Unit<R>, index: DebugAddrIndex<R::Offset>) -> Result<u64> {
+ self.debug_addr
+ .get_address(unit.encoding().address_size, unit.addr_base, index)
+ }
+
+ /// Try to return an attribute value as an address.
+ ///
+ /// If the attribute value is one of:
+ ///
+ /// - a `DW_FORM_addr`
+ /// - a `DW_FORM_addrx` index into the `.debug_addr` entries for the unit
+ ///
+ /// then return the address.
+ /// Returns `None` for other forms.
+ pub fn attr_address(&self, unit: &Unit<R>, attr: AttributeValue<R>) -> Result<Option<u64>> {
+ match attr {
+ AttributeValue::Addr(addr) => Ok(Some(addr)),
+ AttributeValue::DebugAddrIndex(index) => self.address(unit, index).map(Some),
+ _ => Ok(None),
+ }
+ }
+
+ /// Return the range list offset for the given raw offset.
+ ///
+ /// This handles adding `DW_AT_GNU_ranges_base` if required.
+ pub fn ranges_offset_from_raw(
+ &self,
+ unit: &Unit<R>,
+ offset: RawRangeListsOffset<R::Offset>,
+ ) -> RangeListsOffset<R::Offset> {
+ if self.file_type == DwarfFileType::Dwo && unit.header.version() < 5 {
+ RangeListsOffset(offset.0.wrapping_add(unit.rnglists_base.0))
+ } else {
+ RangeListsOffset(offset.0)
+ }
+ }
+
+ /// Return the range list offset at the given index.
+ pub fn ranges_offset(
+ &self,
+ unit: &Unit<R>,
+ index: DebugRngListsIndex<R::Offset>,
+ ) -> Result<RangeListsOffset<R::Offset>> {
+ self.ranges
+ .get_offset(unit.encoding(), unit.rnglists_base, index)
+ }
+
+ /// Iterate over the `RangeListEntry`s starting at the given offset.
+ pub fn ranges(
+ &self,
+ unit: &Unit<R>,
+ offset: RangeListsOffset<R::Offset>,
+ ) -> Result<RngListIter<R>> {
+ self.ranges.ranges(
+ offset,
+ unit.encoding(),
+ unit.low_pc,
+ &self.debug_addr,
+ unit.addr_base,
+ )
+ }
+
+ /// Iterate over the `RawRngListEntry`ies starting at the given offset.
+ pub fn raw_ranges(
+ &self,
+ unit: &Unit<R>,
+ offset: RangeListsOffset<R::Offset>,
+ ) -> Result<RawRngListIter<R>> {
+ self.ranges.raw_ranges(offset, unit.encoding())
+ }
+
+ /// Try to return an attribute value as a range list offset.
+ ///
+ /// If the attribute value is one of:
+ ///
+ /// - a `DW_FORM_sec_offset` reference to the `.debug_ranges` or `.debug_rnglists` sections
+ /// - a `DW_FORM_rnglistx` index into the `.debug_rnglists` entries for the unit
+ ///
+ /// then return the range list offset of the range list.
+ /// Returns `None` for other forms.
+ pub fn attr_ranges_offset(
+ &self,
+ unit: &Unit<R>,
+ attr: AttributeValue<R>,
+ ) -> Result<Option<RangeListsOffset<R::Offset>>> {
+ match attr {
+ AttributeValue::RangeListsRef(offset) => {
+ Ok(Some(self.ranges_offset_from_raw(unit, offset)))
+ }
+ AttributeValue::DebugRngListsIndex(index) => self.ranges_offset(unit, index).map(Some),
+ _ => Ok(None),
+ }
+ }
+
+ /// Try to return an attribute value as a range list entry iterator.
+ ///
+ /// If the attribute value is one of:
+ ///
+ /// - a `DW_FORM_sec_offset` reference to the `.debug_ranges` or `.debug_rnglists` sections
+ /// - a `DW_FORM_rnglistx` index into the `.debug_rnglists` entries for the unit
+ ///
+ /// then return an iterator over the entries in the range list.
+ /// Returns `None` for other forms.
+ pub fn attr_ranges(
+ &self,
+ unit: &Unit<R>,
+ attr: AttributeValue<R>,
+ ) -> Result<Option<RngListIter<R>>> {
+ match self.attr_ranges_offset(unit, attr)? {
+ Some(offset) => Ok(Some(self.ranges(unit, offset)?)),
+ None => Ok(None),
+ }
+ }
+
+ /// Return an iterator for the address ranges of a `DebuggingInformationEntry`.
+ ///
+ /// This uses `DW_AT_low_pc`, `DW_AT_high_pc` and `DW_AT_ranges`.
+ pub fn die_ranges(
+ &self,
+ unit: &Unit<R>,
+ entry: &DebuggingInformationEntry<R>,
+ ) -> Result<RangeIter<R>> {
+ let mut low_pc = None;
+ let mut high_pc = None;
+ let mut size = None;
+ let mut attrs = entry.attrs();
+ while let Some(attr) = attrs.next()? {
+ match attr.name() {
+ constants::DW_AT_low_pc => {
+ low_pc = Some(
+ self.attr_address(unit, attr.value())?
+ .ok_or(Error::UnsupportedAttributeForm)?,
+ );
+ }
+ constants::DW_AT_high_pc => match attr.value() {
+ AttributeValue::Udata(val) => size = Some(val),
+ attr => {
+ high_pc = Some(
+ self.attr_address(unit, attr)?
+ .ok_or(Error::UnsupportedAttributeForm)?,
+ );
+ }
+ },
+ constants::DW_AT_ranges => {
+ if let Some(list) = self.attr_ranges(unit, attr.value())? {
+ return Ok(RangeIter(RangeIterInner::List(list)));
+ }
+ }
+ _ => {}
+ }
+ }
+ let range = low_pc.and_then(|begin| {
+ let end = size.map(|size| begin + size).or(high_pc);
+ // TODO: perhaps return an error if `end` is `None`
+ end.map(|end| Range { begin, end })
+ });
+ Ok(RangeIter(RangeIterInner::Single(range)))
+ }
+
+ /// Return an iterator for the address ranges of a `Unit`.
+ ///
+ /// This uses `DW_AT_low_pc`, `DW_AT_high_pc` and `DW_AT_ranges` of the
+ /// root `DebuggingInformationEntry`.
+ pub fn unit_ranges(&self, unit: &Unit<R>) -> Result<RangeIter<R>> {
+ let mut cursor = unit.header.entries(&unit.abbreviations);
+ cursor.next_dfs()?;
+ let root = cursor.current().ok_or(Error::MissingUnitDie)?;
+ self.die_ranges(unit, root)
+ }
+
+ /// Return the location list offset at the given index.
+ pub fn locations_offset(
+ &self,
+ unit: &Unit<R>,
+ index: DebugLocListsIndex<R::Offset>,
+ ) -> Result<LocationListsOffset<R::Offset>> {
+ self.locations
+ .get_offset(unit.encoding(), unit.loclists_base, index)
+ }
+
+ /// Iterate over the `LocationListEntry`s starting at the given offset.
+ pub fn locations(
+ &self,
+ unit: &Unit<R>,
+ offset: LocationListsOffset<R::Offset>,
+ ) -> Result<LocListIter<R>> {
+ match self.file_type {
+ DwarfFileType::Main => self.locations.locations(
+ offset,
+ unit.encoding(),
+ unit.low_pc,
+ &self.debug_addr,
+ unit.addr_base,
+ ),
+ DwarfFileType::Dwo => self.locations.locations_dwo(
+ offset,
+ unit.encoding(),
+ unit.low_pc,
+ &self.debug_addr,
+ unit.addr_base,
+ ),
+ }
+ }
+
+ /// Iterate over the raw `LocationListEntry`s starting at the given offset.
+ pub fn raw_locations(
+ &self,
+ unit: &Unit<R>,
+ offset: LocationListsOffset<R::Offset>,
+ ) -> Result<RawLocListIter<R>> {
+ match self.file_type {
+ DwarfFileType::Main => self.locations.raw_locations(offset, unit.encoding()),
+ DwarfFileType::Dwo => self.locations.raw_locations_dwo(offset, unit.encoding()),
+ }
+ }
+
+ /// Try to return an attribute value as a location list offset.
+ ///
+ /// If the attribute value is one of:
+ ///
+ /// - a `DW_FORM_sec_offset` reference to the `.debug_loc` or `.debug_loclists` sections
+ /// - a `DW_FORM_loclistx` index into the `.debug_loclists` entries for the unit
+ ///
+ /// then return the location list offset of the location list.
+ /// Returns `None` for other forms.
+ pub fn attr_locations_offset(
+ &self,
+ unit: &Unit<R>,
+ attr: AttributeValue<R>,
+ ) -> Result<Option<LocationListsOffset<R::Offset>>> {
+ match attr {
+ AttributeValue::LocationListsRef(offset) => Ok(Some(offset)),
+ AttributeValue::DebugLocListsIndex(index) => {
+ self.locations_offset(unit, index).map(Some)
+ }
+ _ => Ok(None),
+ }
+ }
+
+ /// Try to return an attribute value as a location list entry iterator.
+ ///
+ /// If the attribute value is one of:
+ ///
+ /// - a `DW_FORM_sec_offset` reference to the `.debug_loc` or `.debug_loclists` sections
+ /// - a `DW_FORM_loclistx` index into the `.debug_loclists` entries for the unit
+ ///
+ /// then return an iterator over the entries in the location list.
+ /// Returns `None` for other forms.
+ pub fn attr_locations(
+ &self,
+ unit: &Unit<R>,
+ attr: AttributeValue<R>,
+ ) -> Result<Option<LocListIter<R>>> {
+ match self.attr_locations_offset(unit, attr)? {
+ Some(offset) => Ok(Some(self.locations(unit, offset)?)),
+ None => Ok(None),
+ }
+ }
+
+ /// Call `Reader::lookup_offset_id` for each section, and return the first match.
+ ///
+ /// The first element of the tuple is `true` for supplementary sections.
+ pub fn lookup_offset_id(&self, id: ReaderOffsetId) -> Option<(bool, SectionId, R::Offset)> {
+ None.or_else(|| self.debug_abbrev.lookup_offset_id(id))
+ .or_else(|| self.debug_addr.lookup_offset_id(id))
+ .or_else(|| self.debug_aranges.lookup_offset_id(id))
+ .or_else(|| self.debug_info.lookup_offset_id(id))
+ .or_else(|| self.debug_line.lookup_offset_id(id))
+ .or_else(|| self.debug_line_str.lookup_offset_id(id))
+ .or_else(|| self.debug_str.lookup_offset_id(id))
+ .or_else(|| self.debug_str_offsets.lookup_offset_id(id))
+ .or_else(|| self.debug_types.lookup_offset_id(id))
+ .or_else(|| self.locations.lookup_offset_id(id))
+ .or_else(|| self.ranges.lookup_offset_id(id))
+ .map(|(id, offset)| (false, id, offset))
+ .or_else(|| {
+ self.sup()
+ .and_then(|sup| sup.lookup_offset_id(id))
+ .map(|(_, id, offset)| (true, id, offset))
+ })
+ }
+
+ /// Returns a string representation of the given error.
+ ///
+ /// This uses information from the DWARF sections to provide more information in some cases.
+ pub fn format_error(&self, err: Error) -> String {
+ #[allow(clippy::single_match)]
+ match err {
+ Error::UnexpectedEof(id) => match self.lookup_offset_id(id) {
+ Some((sup, section, offset)) => {
+ return format!(
+ "{} at {}{}+0x{:x}",
+ err,
+ section.name(),
+ if sup { "(sup)" } else { "" },
+ offset.into_u64(),
+ );
+ }
+ None => {}
+ },
+ _ => {}
+ }
+ err.description().into()
+ }
+}
+
+/// The sections from a `.dwp` file.
+#[derive(Debug)]
+pub struct DwarfPackage<R: Reader> {
+ /// The compilation unit index in the `.debug_cu_index` section.
+ pub cu_index: UnitIndex<R>,
+
+ /// The type unit index in the `.debug_tu_index` section.
+ pub tu_index: UnitIndex<R>,
+
+ /// The `.debug_abbrev.dwo` section.
+ pub debug_abbrev: DebugAbbrev<R>,
+
+ /// The `.debug_info.dwo` section.
+ pub debug_info: DebugInfo<R>,
+
+ /// The `.debug_line.dwo` section.
+ pub debug_line: DebugLine<R>,
+
+ /// The `.debug_str.dwo` section.
+ pub debug_str: DebugStr<R>,
+
+ /// The `.debug_str_offsets.dwo` section.
+ pub debug_str_offsets: DebugStrOffsets<R>,
+
+ /// The `.debug_loc.dwo` section.
+ ///
+ /// Only present when using GNU split-dwarf extension to DWARF 4.
+ pub debug_loc: DebugLoc<R>,
+
+ /// The `.debug_loclists.dwo` section.
+ pub debug_loclists: DebugLocLists<R>,
+
+ /// The `.debug_rnglists.dwo` section.
+ pub debug_rnglists: DebugRngLists<R>,
+
+ /// The `.debug_types.dwo` section.
+ ///
+ /// Only present when using GNU split-dwarf extension to DWARF 4.
+ pub debug_types: DebugTypes<R>,
+
+ /// An empty section.
+ ///
+ /// Used when creating `Dwarf<R>`.
+ pub empty: R,
+}
+
+impl<R: Reader> DwarfPackage<R> {
+ /// Try to load the `.dwp` sections using the given loader function.
+ ///
+ /// `section` loads a DWARF section from the object file.
+ /// It should return an empty section if the section does not exist.
+ pub fn load<F, E>(mut section: F, empty: R) -> core::result::Result<Self, E>
+ where
+ F: FnMut(SectionId) -> core::result::Result<R, E>,
+ E: From<Error>,
+ {
+ Ok(DwarfPackage {
+ cu_index: DebugCuIndex::load(&mut section)?.index()?,
+ tu_index: DebugTuIndex::load(&mut section)?.index()?,
+ // Section types are inferred.
+ debug_abbrev: Section::load(&mut section)?,
+ debug_info: Section::load(&mut section)?,
+ debug_line: Section::load(&mut section)?,
+ debug_str: Section::load(&mut section)?,
+ debug_str_offsets: Section::load(&mut section)?,
+ debug_loc: Section::load(&mut section)?,
+ debug_loclists: Section::load(&mut section)?,
+ debug_rnglists: Section::load(&mut section)?,
+ debug_types: Section::load(&mut section)?,
+ empty,
+ })
+ }
+
+ /// Find the compilation unit with the given DWO identifier and return its section
+ /// contributions.
+ pub fn find_cu(&self, id: DwoId, parent: &Dwarf<R>) -> Result<Option<Dwarf<R>>> {
+ let row = match self.cu_index.find(id.0) {
+ Some(row) => row,
+ None => return Ok(None),
+ };
+ self.cu_sections(row, parent).map(Some)
+ }
+
+ /// Find the type unit with the given type signature and return its section
+ /// contributions.
+ pub fn find_tu(
+ &self,
+ signature: DebugTypeSignature,
+ parent: &Dwarf<R>,
+ ) -> Result<Option<Dwarf<R>>> {
+ let row = match self.tu_index.find(signature.0) {
+ Some(row) => row,
+ None => return Ok(None),
+ };
+ self.tu_sections(row, parent).map(Some)
+ }
+
+ /// Return the section contributions of the compilation unit at the given index.
+ ///
+ /// The index must be in the range `1..cu_index.unit_count`.
+ ///
+ /// This function should only be needed by low level parsers.
+ pub fn cu_sections(&self, index: u32, parent: &Dwarf<R>) -> Result<Dwarf<R>> {
+ self.sections(self.cu_index.sections(index)?, parent)
+ }
+
+ /// Return the section contributions of the compilation unit at the given index.
+ ///
+ /// The index must be in the range `1..tu_index.unit_count`.
+ ///
+ /// This function should only be needed by low level parsers.
+ pub fn tu_sections(&self, index: u32, parent: &Dwarf<R>) -> Result<Dwarf<R>> {
+ self.sections(self.tu_index.sections(index)?, parent)
+ }
+
+ /// Return the section contributions of a unit.
+ ///
+ /// This function should only be needed by low level parsers.
+ pub fn sections(
+ &self,
+ sections: UnitIndexSectionIterator<R>,
+ parent: &Dwarf<R>,
+ ) -> Result<Dwarf<R>> {
+ let mut abbrev_offset = 0;
+ let mut abbrev_size = 0;
+ let mut info_offset = 0;
+ let mut info_size = 0;
+ let mut line_offset = 0;
+ let mut line_size = 0;
+ let mut loc_offset = 0;
+ let mut loc_size = 0;
+ let mut loclists_offset = 0;
+ let mut loclists_size = 0;
+ let mut str_offsets_offset = 0;
+ let mut str_offsets_size = 0;
+ let mut rnglists_offset = 0;
+ let mut rnglists_size = 0;
+ let mut types_offset = 0;
+ let mut types_size = 0;
+ for section in sections {
+ match section.section {
+ SectionId::DebugAbbrev => {
+ abbrev_offset = section.offset;
+ abbrev_size = section.size;
+ }
+ SectionId::DebugInfo => {
+ info_offset = section.offset;
+ info_size = section.size;
+ }
+ SectionId::DebugLine => {
+ line_offset = section.offset;
+ line_size = section.size;
+ }
+ SectionId::DebugLoc => {
+ loc_offset = section.offset;
+ loc_size = section.size;
+ }
+ SectionId::DebugLocLists => {
+ loclists_offset = section.offset;
+ loclists_size = section.size;
+ }
+ SectionId::DebugStrOffsets => {
+ str_offsets_offset = section.offset;
+ str_offsets_size = section.size;
+ }
+ SectionId::DebugRngLists => {
+ rnglists_offset = section.offset;
+ rnglists_size = section.size;
+ }
+ SectionId::DebugTypes => {
+ types_offset = section.offset;
+ types_size = section.size;
+ }
+ SectionId::DebugMacro | SectionId::DebugMacinfo => {
+ // These are valid but we can't parse these yet.
+ }
+ _ => return Err(Error::UnknownIndexSection),
+ }
+ }
+
+ let debug_abbrev = self.debug_abbrev.dwp_range(abbrev_offset, abbrev_size)?;
+ let debug_info = self.debug_info.dwp_range(info_offset, info_size)?;
+ let debug_line = self.debug_line.dwp_range(line_offset, line_size)?;
+ let debug_loc = self.debug_loc.dwp_range(loc_offset, loc_size)?;
+ let debug_loclists = self
+ .debug_loclists
+ .dwp_range(loclists_offset, loclists_size)?;
+ let debug_str_offsets = self
+ .debug_str_offsets
+ .dwp_range(str_offsets_offset, str_offsets_size)?;
+ let debug_rnglists = self
+ .debug_rnglists
+ .dwp_range(rnglists_offset, rnglists_size)?;
+ let debug_types = self.debug_types.dwp_range(types_offset, types_size)?;
+
+ let debug_str = self.debug_str.clone();
+
+ let debug_addr = parent.debug_addr.clone();
+ let debug_ranges = parent.ranges.debug_ranges().clone();
+
+ let debug_aranges = self.empty.clone().into();
+ let debug_line_str = self.empty.clone().into();
+
+ Ok(Dwarf {
+ debug_abbrev,
+ debug_addr,
+ debug_aranges,
+ debug_info,
+ debug_line,
+ debug_line_str,
+ debug_str,
+ debug_str_offsets,
+ debug_types,
+ locations: LocationLists::new(debug_loc, debug_loclists),
+ ranges: RangeLists::new(debug_ranges, debug_rnglists),
+ file_type: DwarfFileType::Dwo,
+ sup: None,
+ })
+ }
+}
+
+/// All of the commonly used information for a unit in the `.debug_info` or `.debug_types`
+/// sections.
+#[derive(Debug)]
+pub struct Unit<R, Offset = <R as Reader>::Offset>
+where
+ R: Reader<Offset = Offset>,
+ Offset: ReaderOffset,
+{
+ /// The header of the unit.
+ pub header: UnitHeader<R, Offset>,
+
+ /// The parsed abbreviations for the unit.
+ pub abbreviations: Abbreviations,
+
+ /// The `DW_AT_name` attribute of the unit.
+ pub name: Option<R>,
+
+ /// The `DW_AT_comp_dir` attribute of the unit.
+ pub comp_dir: Option<R>,
+
+ /// The `DW_AT_low_pc` attribute of the unit. Defaults to 0.
+ pub low_pc: u64,
+
+ /// The `DW_AT_str_offsets_base` attribute of the unit. Defaults to 0.
+ pub str_offsets_base: DebugStrOffsetsBase<Offset>,
+
+ /// The `DW_AT_addr_base` attribute of the unit. Defaults to 0.
+ pub addr_base: DebugAddrBase<Offset>,
+
+ /// The `DW_AT_loclists_base` attribute of the unit. Defaults to 0.
+ pub loclists_base: DebugLocListsBase<Offset>,
+
+ /// The `DW_AT_rnglists_base` attribute of the unit. Defaults to 0.
+ pub rnglists_base: DebugRngListsBase<Offset>,
+
+ /// The line number program of the unit.
+ pub line_program: Option<IncompleteLineProgram<R, Offset>>,
+
+ /// The DWO ID of a skeleton unit or split compilation unit.
+ pub dwo_id: Option<DwoId>,
+}
+
+impl<R: Reader> Unit<R> {
+ /// Construct a new `Unit` from the given unit header.
+ #[inline]
+ pub fn new(dwarf: &Dwarf<R>, header: UnitHeader<R>) -> Result<Self> {
+ let abbreviations = header.abbreviations(&dwarf.debug_abbrev)?;
+ let mut unit = Unit {
+ abbreviations,
+ name: None,
+ comp_dir: None,
+ low_pc: 0,
+ str_offsets_base: DebugStrOffsetsBase::default_for_encoding_and_file(
+ header.encoding(),
+ dwarf.file_type,
+ ),
+ // NB: Because the .debug_addr section never lives in a .dwo, we can assume its base is always 0 or provided.
+ addr_base: DebugAddrBase(R::Offset::from_u8(0)),
+ loclists_base: DebugLocListsBase::default_for_encoding_and_file(
+ header.encoding(),
+ dwarf.file_type,
+ ),
+ rnglists_base: DebugRngListsBase::default_for_encoding_and_file(
+ header.encoding(),
+ dwarf.file_type,
+ ),
+ line_program: None,
+ dwo_id: match header.type_() {
+ UnitType::Skeleton(dwo_id) | UnitType::SplitCompilation(dwo_id) => Some(dwo_id),
+ _ => None,
+ },
+ header,
+ };
+ let mut name = None;
+ let mut comp_dir = None;
+ let mut line_program_offset = None;
+ let mut low_pc_attr = None;
+
+ {
+ let mut cursor = unit.header.entries(&unit.abbreviations);
+ cursor.next_dfs()?;
+ let root = cursor.current().ok_or(Error::MissingUnitDie)?;
+ let mut attrs = root.attrs();
+ while let Some(attr) = attrs.next()? {
+ match attr.name() {
+ constants::DW_AT_name => {
+ name = Some(attr.value());
+ }
+ constants::DW_AT_comp_dir => {
+ comp_dir = Some(attr.value());
+ }
+ constants::DW_AT_low_pc => {
+ low_pc_attr = Some(attr.value());
+ }
+ constants::DW_AT_stmt_list => {
+ if let AttributeValue::DebugLineRef(offset) = attr.value() {
+ line_program_offset = Some(offset);
+ }
+ }
+ constants::DW_AT_str_offsets_base => {
+ if let AttributeValue::DebugStrOffsetsBase(base) = attr.value() {
+ unit.str_offsets_base = base;
+ }
+ }
+ constants::DW_AT_addr_base | constants::DW_AT_GNU_addr_base => {
+ if let AttributeValue::DebugAddrBase(base) = attr.value() {
+ unit.addr_base = base;
+ }
+ }
+ constants::DW_AT_loclists_base => {
+ if let AttributeValue::DebugLocListsBase(base) = attr.value() {
+ unit.loclists_base = base;
+ }
+ }
+ constants::DW_AT_rnglists_base | constants::DW_AT_GNU_ranges_base => {
+ if let AttributeValue::DebugRngListsBase(base) = attr.value() {
+ unit.rnglists_base = base;
+ }
+ }
+ constants::DW_AT_GNU_dwo_id => {
+ if unit.dwo_id.is_none() {
+ if let AttributeValue::DwoId(dwo_id) = attr.value() {
+ unit.dwo_id = Some(dwo_id);
+ }
+ }
+ }
+ _ => {}
+ }
+ }
+ }
+
+ unit.name = match name {
+ Some(val) => dwarf.attr_string(&unit, val).ok(),
+ None => None,
+ };
+ unit.comp_dir = match comp_dir {
+ Some(val) => dwarf.attr_string(&unit, val).ok(),
+ None => None,
+ };
+ unit.line_program = match line_program_offset {
+ Some(offset) => Some(dwarf.debug_line.program(
+ offset,
+ unit.header.address_size(),
+ unit.comp_dir.clone(),
+ unit.name.clone(),
+ )?),
+ None => None,
+ };
+ if let Some(low_pc_attr) = low_pc_attr {
+ if let Some(addr) = dwarf.attr_address(&unit, low_pc_attr)? {
+ unit.low_pc = addr;
+ }
+ }
+ Ok(unit)
+ }
+
+ /// Return the encoding parameters for this unit.
+ #[inline]
+ pub fn encoding(&self) -> Encoding {
+ self.header.encoding()
+ }
+
+ /// Read the `DebuggingInformationEntry` at the given offset.
+ pub fn entry(&self, offset: UnitOffset<R::Offset>) -> Result<DebuggingInformationEntry<R>> {
+ self.header.entry(&self.abbreviations, offset)
+ }
+
+ /// Navigate this unit's `DebuggingInformationEntry`s.
+ #[inline]
+ pub fn entries(&self) -> EntriesCursor<R> {
+ self.header.entries(&self.abbreviations)
+ }
+
+ /// Navigate this unit's `DebuggingInformationEntry`s
+ /// starting at the given offset.
+ #[inline]
+ pub fn entries_at_offset(&self, offset: UnitOffset<R::Offset>) -> Result<EntriesCursor<R>> {
+ self.header.entries_at_offset(&self.abbreviations, offset)
+ }
+
+ /// Navigate this unit's `DebuggingInformationEntry`s as a tree
+ /// starting at the given offset.
+ #[inline]
+ pub fn entries_tree(&self, offset: Option<UnitOffset<R::Offset>>) -> Result<EntriesTree<R>> {
+ self.header.entries_tree(&self.abbreviations, offset)
+ }
+
+ /// Read the raw data that defines the Debugging Information Entries.
+ #[inline]
+ pub fn entries_raw(&self, offset: Option<UnitOffset<R::Offset>>) -> Result<EntriesRaw<R>> {
+ self.header.entries_raw(&self.abbreviations, offset)
+ }
+
+ /// Copy attributes that are subject to relocation from another unit. This is intended
+ /// to be used to copy attributes from a skeleton compilation unit to the corresponding
+ /// split compilation unit.
+ pub fn copy_relocated_attributes(&mut self, other: &Unit<R>) {
+ self.low_pc = other.low_pc;
+ self.addr_base = other.addr_base;
+ if self.header.version() < 5 {
+ self.rnglists_base = other.rnglists_base;
+ }
+ }
+}
+
+impl<T: ReaderOffset> UnitSectionOffset<T> {
+ /// Convert an offset to be relative to the start of the given unit,
+ /// instead of relative to the start of the section.
+ /// Returns `None` if the offset is not within the unit entries.
+ pub fn to_unit_offset<R>(&self, unit: &Unit<R>) -> Option<UnitOffset<T>>
+ where
+ R: Reader<Offset = T>,
+ {
+ let (offset, unit_offset) = match (self, unit.header.offset()) {
+ (
+ UnitSectionOffset::DebugInfoOffset(offset),
+ UnitSectionOffset::DebugInfoOffset(unit_offset),
+ ) => (offset.0, unit_offset.0),
+ (
+ UnitSectionOffset::DebugTypesOffset(offset),
+ UnitSectionOffset::DebugTypesOffset(unit_offset),
+ ) => (offset.0, unit_offset.0),
+ _ => return None,
+ };
+ let offset = match offset.checked_sub(unit_offset) {
+ Some(offset) => UnitOffset(offset),
+ None => return None,
+ };
+ if !unit.header.is_valid_offset(offset) {
+ return None;
+ }
+ Some(offset)
+ }
+}
+
+impl<T: ReaderOffset> UnitOffset<T> {
+ /// Convert an offset to be relative to the start of the .debug_info section,
+ /// instead of relative to the start of the given compilation unit.
+ ///
+ /// Does not check that the offset is valid.
+ pub fn to_unit_section_offset<R>(&self, unit: &Unit<R>) -> UnitSectionOffset<T>
+ where
+ R: Reader<Offset = T>,
+ {
+ match unit.header.offset() {
+ UnitSectionOffset::DebugInfoOffset(unit_offset) => {
+ DebugInfoOffset(unit_offset.0 + self.0).into()
+ }
+ UnitSectionOffset::DebugTypesOffset(unit_offset) => {
+ DebugTypesOffset(unit_offset.0 + self.0).into()
+ }
+ }
+ }
+}
+
+/// An iterator for the address ranges of a `DebuggingInformationEntry`.
+///
+/// Returned by `Dwarf::die_ranges` and `Dwarf::unit_ranges`.
+#[derive(Debug)]
+pub struct RangeIter<R: Reader>(RangeIterInner<R>);
+
+#[derive(Debug)]
+enum RangeIterInner<R: Reader> {
+ Single(Option<Range>),
+ List(RngListIter<R>),
+}
+
+impl<R: Reader> Default for RangeIter<R> {
+ fn default() -> Self {
+ RangeIter(RangeIterInner::Single(None))
+ }
+}
+
+impl<R: Reader> RangeIter<R> {
+ /// Advance the iterator to the next range.
+ pub fn next(&mut self) -> Result<Option<Range>> {
+ match self.0 {
+ RangeIterInner::Single(ref mut range) => Ok(range.take()),
+ RangeIterInner::List(ref mut list) => list.next(),
+ }
+ }
+}
+
+#[cfg(feature = "fallible-iterator")]
+impl<R: Reader> fallible_iterator::FallibleIterator for RangeIter<R> {
+ type Item = Range;
+ type Error = Error;
+
+ #[inline]
+ fn next(&mut self) -> ::core::result::Result<Option<Self::Item>, Self::Error> {
+ RangeIter::next(self)
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+ use crate::read::EndianSlice;
+ use crate::{Endianity, LittleEndian};
+
+ /// Ensure that `Dwarf<R>` is covariant wrt R.
+ #[test]
+ fn test_dwarf_variance() {
+ /// This only needs to compile.
+ fn _f<'a: 'b, 'b, E: Endianity>(x: Dwarf<EndianSlice<'a, E>>) -> Dwarf<EndianSlice<'b, E>> {
+ x
+ }
+ }
+
+ /// Ensure that `Unit<R>` is covariant wrt R.
+ #[test]
+ fn test_dwarf_unit_variance() {
+ /// This only needs to compile.
+ fn _f<'a: 'b, 'b, E: Endianity>(x: Unit<EndianSlice<'a, E>>) -> Unit<EndianSlice<'b, E>> {
+ x
+ }
+ }
+
+ #[test]
+ fn test_send() {
+ fn assert_is_send<T: Send>() {}
+ assert_is_send::<Dwarf<EndianSlice<LittleEndian>>>();
+ assert_is_send::<Unit<EndianSlice<LittleEndian>>>();
+ }
+
+ #[test]
+ fn test_format_error() {
+ let mut owned_dwarf = Dwarf::load(|_| -> Result<_> { Ok(vec![1, 2]) }).unwrap();
+ owned_dwarf
+ .load_sup(|_| -> Result<_> { Ok(vec![1, 2]) })
+ .unwrap();
+ let dwarf = owned_dwarf.borrow(|section| EndianSlice::new(&section, LittleEndian));
+
+ match dwarf.debug_str.get_str(DebugStrOffset(1)) {
+ Ok(r) => panic!("Unexpected str {:?}", r),
+ Err(e) => {
+ assert_eq!(
+ dwarf.format_error(e),
+ "Hit the end of input before it was expected at .debug_str+0x1"
+ );
+ }
+ }
+ match dwarf.sup().unwrap().debug_str.get_str(DebugStrOffset(1)) {
+ Ok(r) => panic!("Unexpected str {:?}", r),
+ Err(e) => {
+ assert_eq!(
+ dwarf.format_error(e),
+ "Hit the end of input before it was expected at .debug_str(sup)+0x1"
+ );
+ }
+ }
+ assert_eq!(dwarf.format_error(Error::Io), Error::Io.description());
+ }
+}
diff --git a/vendor/gimli-0.26.2/src/read/endian_reader.rs b/vendor/gimli-0.26.2/src/read/endian_reader.rs
new file mode 100644
index 000000000..8852b3804
--- /dev/null
+++ b/vendor/gimli-0.26.2/src/read/endian_reader.rs
@@ -0,0 +1,639 @@
+//! Defining custom `Reader`s quickly.
+
+use alloc::borrow::Cow;
+use alloc::rc::Rc;
+use alloc::string::String;
+use alloc::sync::Arc;
+use core::fmt::Debug;
+use core::ops::{Deref, Index, Range, RangeFrom, RangeTo};
+use core::slice;
+use core::str;
+use stable_deref_trait::CloneStableDeref;
+
+use crate::endianity::Endianity;
+use crate::read::{Error, Reader, ReaderOffsetId, Result};
+
+/// A reference counted, non-thread-safe slice of bytes and associated
+/// endianity.
+///
+/// ```
+/// # #[cfg(feature = "std")] {
+/// use std::rc::Rc;
+///
+/// let buf = Rc::from(&[1, 2, 3, 4][..]);
+/// let reader = gimli::EndianRcSlice::new(buf, gimli::NativeEndian);
+/// # let _ = reader;
+/// # }
+/// ```
+pub type EndianRcSlice<Endian> = EndianReader<Endian, Rc<[u8]>>;
+
+/// An atomically reference counted, thread-safe slice of bytes and associated
+/// endianity.
+///
+/// ```
+/// # #[cfg(feature = "std")] {
+/// use std::sync::Arc;
+///
+/// let buf = Arc::from(&[1, 2, 3, 4][..]);
+/// let reader = gimli::EndianArcSlice::new(buf, gimli::NativeEndian);
+/// # let _ = reader;
+/// # }
+/// ```
+pub type EndianArcSlice<Endian> = EndianReader<Endian, Arc<[u8]>>;
+
+/// An easy way to define a custom `Reader` implementation with a reference to a
+/// generic buffer of bytes and an associated endianity.
+///
+/// Note that the whole original buffer is kept alive in memory even if there is
+/// only one reader that references only a handful of bytes from that original
+/// buffer. That is, `EndianReader` will not do any copying, moving, or
+/// compacting in order to free up unused regions of the original buffer. If you
+/// require this kind of behavior, it is up to you to implement `Reader`
+/// directly by-hand.
+///
+/// # Example
+///
+/// Say you have an `mmap`ed file that you want to serve as a `gimli::Reader`.
+/// You can wrap that `mmap`ed file up in a `MmapFile` type and use
+/// `EndianReader<Rc<MmapFile>>` or `EndianReader<Arc<MmapFile>>` as readers as
+/// long as `MmapFile` dereferences to the underlying `[u8]` data.
+///
+/// ```
+/// use std::io;
+/// use std::ops::Deref;
+/// use std::path::Path;
+/// use std::slice;
+/// use std::sync::Arc;
+///
+/// /// A type that represents an `mmap`ed file.
+/// #[derive(Debug)]
+/// pub struct MmapFile {
+/// ptr: *const u8,
+/// len: usize,
+/// }
+///
+/// impl MmapFile {
+/// pub fn new(path: &Path) -> io::Result<MmapFile> {
+/// // Call `mmap` and check for errors and all that...
+/// # unimplemented!()
+/// }
+/// }
+///
+/// impl Drop for MmapFile {
+/// fn drop(&mut self) {
+/// // Call `munmap` to clean up after ourselves...
+/// # unimplemented!()
+/// }
+/// }
+///
+/// // And `MmapFile` can deref to a slice of the `mmap`ed region of memory.
+/// impl Deref for MmapFile {
+/// type Target = [u8];
+/// fn deref(&self) -> &[u8] {
+/// unsafe {
+/// slice::from_raw_parts(self.ptr, self.len)
+/// }
+/// }
+/// }
+///
+/// /// A type that represents a shared `mmap`ed file.
+/// #[derive(Debug, Clone)]
+/// pub struct ArcMmapFile(Arc<MmapFile>);
+///
+/// // And `ArcMmapFile` can deref to a slice of the `mmap`ed region of memory.
+/// impl Deref for ArcMmapFile {
+/// type Target = [u8];
+/// fn deref(&self) -> &[u8] {
+/// &self.0
+/// }
+/// }
+///
+/// // These are both valid for any `Rc` or `Arc`.
+/// unsafe impl gimli::StableDeref for ArcMmapFile {}
+/// unsafe impl gimli::CloneStableDeref for ArcMmapFile {}
+///
+/// /// A `gimli::Reader` that is backed by an `mmap`ed file!
+/// pub type MmapFileReader<Endian> = gimli::EndianReader<Endian, ArcMmapFile>;
+/// # fn test(_: &MmapFileReader<gimli::NativeEndian>) { }
+/// ```
+#[derive(Debug, Clone, Copy, Hash)]
+pub struct EndianReader<Endian, T>
+where
+ Endian: Endianity,
+ T: CloneStableDeref<Target = [u8]> + Debug,
+{
+ range: SubRange<T>,
+ endian: Endian,
+}
+
+impl<Endian, T1, T2> PartialEq<EndianReader<Endian, T2>> for EndianReader<Endian, T1>
+where
+ Endian: Endianity,
+ T1: CloneStableDeref<Target = [u8]> + Debug,
+ T2: CloneStableDeref<Target = [u8]> + Debug,
+{
+ fn eq(&self, rhs: &EndianReader<Endian, T2>) -> bool {
+ self.bytes() == rhs.bytes()
+ }
+}
+
+impl<Endian, T> Eq for EndianReader<Endian, T>
+where
+ Endian: Endianity,
+ T: CloneStableDeref<Target = [u8]> + Debug,
+{
+}
+
+// This is separated out from `EndianReader` so that we can avoid running afoul
+// of borrowck. We need to `read_slice(&mut self, ...) -> &[u8]` and then call
+// `self.endian.read_whatever` on the result. The problem is that the returned
+// slice keeps the `&mut self` borrow active, so we wouldn't be able to access
+// `self.endian`. Splitting the sub-range out from the endian lets us work
+// around this, making it so that only the `self.range` borrow is held active,
+// not all of `self`.
+//
+// This also serves to encapsulate the unsafe code concerning `CloneStableDeref`.
+// The `bytes` member is held so that the bytes live long enough, and the
+// `CloneStableDeref` ensures these bytes never move. The `ptr` and `len`
+// members point inside `bytes`, and are updated during read operations.
+#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
+struct SubRange<T>
+where
+ T: CloneStableDeref<Target = [u8]> + Debug,
+{
+ bytes: T,
+ ptr: *const u8,
+ len: usize,
+}
+
+unsafe impl<T> Send for SubRange<T> where T: CloneStableDeref<Target = [u8]> + Debug + Send {}
+
+unsafe impl<T> Sync for SubRange<T> where T: CloneStableDeref<Target = [u8]> + Debug + Sync {}
+
+impl<T> SubRange<T>
+where
+ T: CloneStableDeref<Target = [u8]> + Debug,
+{
+ #[inline]
+ fn new(bytes: T) -> Self {
+ let ptr = bytes.as_ptr();
+ let len = bytes.len();
+ SubRange { bytes, ptr, len }
+ }
+
+ #[inline]
+ fn bytes(&self) -> &[u8] {
+ // Safe because `T` implements `CloneStableDeref`, `bytes` can't be modified,
+ // and all operations that modify `ptr` and `len` ensure they stay in range.
+ unsafe { slice::from_raw_parts(self.ptr, self.len) }
+ }
+
+ #[inline]
+ fn len(&self) -> usize {
+ self.len
+ }
+
+ #[inline]
+ fn truncate(&mut self, len: usize) {
+ assert!(len <= self.len);
+ self.len = len;
+ }
+
+ #[inline]
+ fn skip(&mut self, len: usize) {
+ assert!(len <= self.len);
+ self.ptr = unsafe { self.ptr.add(len) };
+ self.len -= len;
+ }
+
+ #[inline]
+ fn read_slice(&mut self, len: usize) -> Option<&[u8]> {
+ if self.len() < len {
+ None
+ } else {
+ // Same as for `bytes()`.
+ let bytes = unsafe { slice::from_raw_parts(self.ptr, len) };
+ self.skip(len);
+ Some(bytes)
+ }
+ }
+}
+
+impl<Endian, T> EndianReader<Endian, T>
+where
+ Endian: Endianity,
+ T: CloneStableDeref<Target = [u8]> + Debug,
+{
+ /// Construct a new `EndianReader` with the given bytes.
+ #[inline]
+ pub fn new(bytes: T, endian: Endian) -> EndianReader<Endian, T> {
+ EndianReader {
+ range: SubRange::new(bytes),
+ endian,
+ }
+ }
+
+ /// Return a reference to the raw bytes underlying this reader.
+ #[inline]
+ pub fn bytes(&self) -> &[u8] {
+ self.range.bytes()
+ }
+}
+
+/// # Range Methods
+///
+/// Unfortunately, `std::ops::Index` *must* return a reference, so we can't
+/// implement `Index<Range<usize>>` to return a new `EndianReader` the way we
+/// would like to. Instead, we abandon fancy indexing operators and have these
+/// plain old methods.
+impl<Endian, T> EndianReader<Endian, T>
+where
+ Endian: Endianity,
+ T: CloneStableDeref<Target = [u8]> + Debug,
+{
+ /// Take the given `start..end` range of the underlying buffer and return a
+ /// new `EndianReader`.
+ ///
+ /// ```
+ /// # #[cfg(feature = "std")] {
+ /// use gimli::{EndianReader, LittleEndian};
+ /// use std::sync::Arc;
+ ///
+ /// let buf = Arc::<[u8]>::from(&[0x01, 0x02, 0x03, 0x04][..]);
+ /// let reader = EndianReader::new(buf.clone(), LittleEndian);
+ /// assert_eq!(reader.range(1..3),
+ /// EndianReader::new(&buf[1..3], LittleEndian));
+ /// # }
+ /// ```
+ ///
+ /// # Panics
+ ///
+ /// Panics if the range is out of bounds.
+ pub fn range(&self, idx: Range<usize>) -> EndianReader<Endian, T> {
+ let mut r = self.clone();
+ r.range.skip(idx.start);
+ r.range.truncate(idx.len());
+ r
+ }
+
+ /// Take the given `start..` range of the underlying buffer and return a new
+ /// `EndianReader`.
+ ///
+ /// ```
+ /// # #[cfg(feature = "std")] {
+ /// use gimli::{EndianReader, LittleEndian};
+ /// use std::sync::Arc;
+ ///
+ /// let buf = Arc::<[u8]>::from(&[0x01, 0x02, 0x03, 0x04][..]);
+ /// let reader = EndianReader::new(buf.clone(), LittleEndian);
+ /// assert_eq!(reader.range_from(2..),
+ /// EndianReader::new(&buf[2..], LittleEndian));
+ /// # }
+ /// ```
+ ///
+ /// # Panics
+ ///
+ /// Panics if the range is out of bounds.
+ pub fn range_from(&self, idx: RangeFrom<usize>) -> EndianReader<Endian, T> {
+ let mut r = self.clone();
+ r.range.skip(idx.start);
+ r
+ }
+
+ /// Take the given `..end` range of the underlying buffer and return a new
+ /// `EndianReader`.
+ ///
+ /// ```
+ /// # #[cfg(feature = "std")] {
+ /// use gimli::{EndianReader, LittleEndian};
+ /// use std::sync::Arc;
+ ///
+ /// let buf = Arc::<[u8]>::from(&[0x01, 0x02, 0x03, 0x04][..]);
+ /// let reader = EndianReader::new(buf.clone(), LittleEndian);
+ /// assert_eq!(reader.range_to(..3),
+ /// EndianReader::new(&buf[..3], LittleEndian));
+ /// # }
+ /// ```
+ ///
+ /// # Panics
+ ///
+ /// Panics if the range is out of bounds.
+ pub fn range_to(&self, idx: RangeTo<usize>) -> EndianReader<Endian, T> {
+ let mut r = self.clone();
+ r.range.truncate(idx.end);
+ r
+ }
+}
+
+impl<Endian, T> Index<usize> for EndianReader<Endian, T>
+where
+ Endian: Endianity,
+ T: CloneStableDeref<Target = [u8]> + Debug,
+{
+ type Output = u8;
+ fn index(&self, idx: usize) -> &Self::Output {
+ &self.bytes()[idx]
+ }
+}
+
+impl<Endian, T> Index<RangeFrom<usize>> for EndianReader<Endian, T>
+where
+ Endian: Endianity,
+ T: CloneStableDeref<Target = [u8]> + Debug,
+{
+ type Output = [u8];
+ fn index(&self, idx: RangeFrom<usize>) -> &Self::Output {
+ &self.bytes()[idx]
+ }
+}
+
+impl<Endian, T> Deref for EndianReader<Endian, T>
+where
+ Endian: Endianity,
+ T: CloneStableDeref<Target = [u8]> + Debug,
+{
+ type Target = [u8];
+ fn deref(&self) -> &Self::Target {
+ self.bytes()
+ }
+}
+
+impl<Endian, T> Reader for EndianReader<Endian, T>
+where
+ Endian: Endianity,
+ T: CloneStableDeref<Target = [u8]> + Debug,
+{
+ type Endian = Endian;
+ type Offset = usize;
+
+ #[inline]
+ fn endian(&self) -> Endian {
+ self.endian
+ }
+
+ #[inline]
+ fn len(&self) -> usize {
+ self.range.len()
+ }
+
+ #[inline]
+ fn empty(&mut self) {
+ self.range.truncate(0);
+ }
+
+ #[inline]
+ fn truncate(&mut self, len: usize) -> Result<()> {
+ if self.len() < len {
+ Err(Error::UnexpectedEof(self.offset_id()))
+ } else {
+ self.range.truncate(len);
+ Ok(())
+ }
+ }
+
+ #[inline]
+ fn offset_from(&self, base: &EndianReader<Endian, T>) -> usize {
+ let base_ptr = base.bytes().as_ptr() as *const u8 as usize;
+ let ptr = self.bytes().as_ptr() as *const u8 as usize;
+ debug_assert!(base_ptr <= ptr);
+ debug_assert!(ptr + self.bytes().len() <= base_ptr + base.bytes().len());
+ ptr - base_ptr
+ }
+
+ #[inline]
+ fn offset_id(&self) -> ReaderOffsetId {
+ ReaderOffsetId(self.bytes().as_ptr() as u64)
+ }
+
+ #[inline]
+ fn lookup_offset_id(&self, id: ReaderOffsetId) -> Option<Self::Offset> {
+ let id = id.0;
+ let self_id = self.bytes().as_ptr() as u64;
+ let self_len = self.bytes().len() as u64;
+ if id >= self_id && id <= self_id + self_len {
+ Some((id - self_id) as usize)
+ } else {
+ None
+ }
+ }
+
+ #[inline]
+ fn find(&self, byte: u8) -> Result<usize> {
+ self.bytes()
+ .iter()
+ .position(|x| *x == byte)
+ .ok_or_else(|| Error::UnexpectedEof(self.offset_id()))
+ }
+
+ #[inline]
+ fn skip(&mut self, len: usize) -> Result<()> {
+ if self.len() < len {
+ Err(Error::UnexpectedEof(self.offset_id()))
+ } else {
+ self.range.skip(len);
+ Ok(())
+ }
+ }
+
+ #[inline]
+ fn split(&mut self, len: usize) -> Result<Self> {
+ if self.len() < len {
+ Err(Error::UnexpectedEof(self.offset_id()))
+ } else {
+ let mut r = self.clone();
+ r.range.truncate(len);
+ self.range.skip(len);
+ Ok(r)
+ }
+ }
+
+ #[inline]
+ fn to_slice(&self) -> Result<Cow<[u8]>> {
+ Ok(self.bytes().into())
+ }
+
+ #[inline]
+ fn to_string(&self) -> Result<Cow<str>> {
+ match str::from_utf8(self.bytes()) {
+ Ok(s) => Ok(s.into()),
+ _ => Err(Error::BadUtf8),
+ }
+ }
+
+ #[inline]
+ fn to_string_lossy(&self) -> Result<Cow<str>> {
+ Ok(String::from_utf8_lossy(self.bytes()))
+ }
+
+ #[inline]
+ fn read_slice(&mut self, buf: &mut [u8]) -> Result<()> {
+ match self.range.read_slice(buf.len()) {
+ Some(slice) => {
+ buf.copy_from_slice(slice);
+ Ok(())
+ }
+ None => Err(Error::UnexpectedEof(self.offset_id())),
+ }
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+ use crate::endianity::NativeEndian;
+ use crate::read::Reader;
+
+ fn native_reader<T: CloneStableDeref<Target = [u8]> + Debug>(
+ bytes: T,
+ ) -> EndianReader<NativeEndian, T> {
+ EndianReader::new(bytes, NativeEndian)
+ }
+
+ const BUF: &[u8] = &[1, 2, 3, 4, 5, 6, 7, 8, 9, 0];
+
+ #[test]
+ fn test_reader_split() {
+ let mut reader = native_reader(BUF);
+ let left = reader.split(3).unwrap();
+ assert_eq!(left, native_reader(&BUF[..3]));
+ assert_eq!(reader, native_reader(&BUF[3..]));
+ }
+
+ #[test]
+ fn test_reader_split_out_of_bounds() {
+ let mut reader = native_reader(BUF);
+ assert!(reader.split(30).is_err());
+ }
+
+ #[test]
+ fn bytes_and_len_and_range_and_eq() {
+ let reader = native_reader(BUF);
+ assert_eq!(reader.len(), BUF.len());
+ assert_eq!(reader.bytes(), BUF);
+ assert_eq!(reader, native_reader(BUF));
+
+ let range = reader.range(2..8);
+ let buf_range = &BUF[2..8];
+ assert_eq!(range.len(), buf_range.len());
+ assert_eq!(range.bytes(), buf_range);
+ assert_ne!(range, native_reader(BUF));
+ assert_eq!(range, native_reader(buf_range));
+
+ let range_from = range.range_from(1..);
+ let buf_range_from = &buf_range[1..];
+ assert_eq!(range_from.len(), buf_range_from.len());
+ assert_eq!(range_from.bytes(), buf_range_from);
+ assert_ne!(range_from, native_reader(BUF));
+ assert_eq!(range_from, native_reader(buf_range_from));
+
+ let range_to = range_from.range_to(..4);
+ let buf_range_to = &buf_range_from[..4];
+ assert_eq!(range_to.len(), buf_range_to.len());
+ assert_eq!(range_to.bytes(), buf_range_to);
+ assert_ne!(range_to, native_reader(BUF));
+ assert_eq!(range_to, native_reader(buf_range_to));
+ }
+
+ #[test]
+ fn find() {
+ let mut reader = native_reader(BUF);
+ reader.skip(2).unwrap();
+ assert_eq!(
+ reader.find(5),
+ Ok(BUF[2..].iter().position(|x| *x == 5).unwrap())
+ );
+ }
+
+ #[test]
+ fn indexing() {
+ let mut reader = native_reader(BUF);
+ reader.skip(2).unwrap();
+ assert_eq!(reader[0], BUF[2]);
+ }
+
+ #[test]
+ #[should_panic]
+ fn indexing_out_of_bounds() {
+ let mut reader = native_reader(BUF);
+ reader.skip(2).unwrap();
+ let _ = reader[900];
+ }
+
+ #[test]
+ fn endian() {
+ let reader = native_reader(BUF);
+ assert_eq!(reader.endian(), NativeEndian);
+ }
+
+ #[test]
+ fn empty() {
+ let mut reader = native_reader(BUF);
+ assert!(!reader.is_empty());
+ reader.empty();
+ assert!(reader.is_empty());
+ assert!(reader.bytes().is_empty());
+ }
+
+ #[test]
+ fn truncate() {
+ let reader = native_reader(BUF);
+ let mut reader = reader.range(2..8);
+ reader.truncate(2).unwrap();
+ assert_eq!(reader.bytes(), &BUF[2..4]);
+ }
+
+ #[test]
+ fn offset_from() {
+ let reader = native_reader(BUF);
+ let sub = reader.range(2..8);
+ assert_eq!(sub.offset_from(&reader), 2);
+ }
+
+ #[test]
+ fn skip() {
+ let mut reader = native_reader(BUF);
+ reader.skip(2).unwrap();
+ assert_eq!(reader.bytes(), &BUF[2..]);
+ }
+
+ #[test]
+ fn to_slice() {
+ assert_eq!(
+ native_reader(BUF).range(2..5).to_slice(),
+ Ok(Cow::from(&BUF[2..5]))
+ );
+ }
+
+ #[test]
+ fn to_string_ok() {
+ let buf = b"hello, world!";
+ let reader = native_reader(&buf[..]);
+ let reader = reader.range_from(7..);
+ assert_eq!(reader.to_string(), Ok(Cow::from("world!")));
+ }
+
+ // The rocket emoji (🚀 = [0xf0, 0x9f, 0x9a, 0x80]) but rotated left by one
+ // to make it invalid UTF-8.
+ const BAD_UTF8: &[u8] = &[0x9f, 0x9a, 0x80, 0xf0];
+
+ #[test]
+ fn to_string_err() {
+ let reader = native_reader(BAD_UTF8);
+ assert!(reader.to_string().is_err());
+ }
+
+ #[test]
+ fn to_string_lossy() {
+ let reader = native_reader(BAD_UTF8);
+ assert_eq!(reader.to_string_lossy(), Ok(Cow::from("����")));
+ }
+
+ #[test]
+ fn read_u8_array() {
+ let mut reader = native_reader(BAD_UTF8);
+ reader.skip(1).unwrap();
+ let arr: [u8; 2] = reader.read_u8_array().unwrap();
+ assert_eq!(arr, &BAD_UTF8[1..3]);
+ assert_eq!(reader.bytes(), &BAD_UTF8[3..]);
+ }
+}
diff --git a/vendor/gimli-0.26.2/src/read/endian_slice.rs b/vendor/gimli-0.26.2/src/read/endian_slice.rs
new file mode 100644
index 000000000..05262cdec
--- /dev/null
+++ b/vendor/gimli-0.26.2/src/read/endian_slice.rs
@@ -0,0 +1,350 @@
+//! Working with byte slices that have an associated endianity.
+
+#[cfg(feature = "read")]
+use alloc::borrow::Cow;
+#[cfg(feature = "read")]
+use alloc::string::String;
+use core::ops::{Deref, Index, Range, RangeFrom, RangeTo};
+use core::str;
+
+use crate::endianity::Endianity;
+use crate::read::{Error, Reader, ReaderOffsetId, Result};
+
+/// A `&[u8]` slice with endianity metadata.
+///
+/// This implements the `Reader` trait, which is used for all reading of DWARF sections.
+#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Hash)]
+pub struct EndianSlice<'input, Endian>
+where
+ Endian: Endianity,
+{
+ slice: &'input [u8],
+ endian: Endian,
+}
+
+impl<'input, Endian> EndianSlice<'input, Endian>
+where
+ Endian: Endianity,
+{
+ /// Construct a new `EndianSlice` with the given slice and endianity.
+ #[inline]
+ pub fn new(slice: &'input [u8], endian: Endian) -> EndianSlice<'input, Endian> {
+ EndianSlice { slice, endian }
+ }
+
+ /// Return a reference to the raw slice.
+ #[inline]
+ #[doc(hidden)]
+ #[deprecated(note = "Method renamed to EndianSlice::slice; use that instead.")]
+ pub fn buf(&self) -> &'input [u8] {
+ self.slice
+ }
+
+ /// Return a reference to the raw slice.
+ #[inline]
+ pub fn slice(&self) -> &'input [u8] {
+ self.slice
+ }
+
+ /// Split the slice in two at the given index, resulting in the tuple where
+ /// the first item has range [0, idx), and the second has range [idx,
+ /// len). Panics if the index is out of bounds.
+ #[inline]
+ pub fn split_at(
+ &self,
+ idx: usize,
+ ) -> (EndianSlice<'input, Endian>, EndianSlice<'input, Endian>) {
+ (self.range_to(..idx), self.range_from(idx..))
+ }
+
+ /// Find the first occurence of a byte in the slice, and return its index.
+ #[inline]
+ pub fn find(&self, byte: u8) -> Option<usize> {
+ self.slice.iter().position(|ch| *ch == byte)
+ }
+
+ /// Return the offset of the start of the slice relative to the start
+ /// of the given slice.
+ #[inline]
+ pub fn offset_from(&self, base: EndianSlice<'input, Endian>) -> usize {
+ let base_ptr = base.slice.as_ptr() as *const u8 as usize;
+ let ptr = self.slice.as_ptr() as *const u8 as usize;
+ debug_assert!(base_ptr <= ptr);
+ debug_assert!(ptr + self.slice.len() <= base_ptr + base.slice.len());
+ ptr - base_ptr
+ }
+
+ /// Converts the slice to a string using `str::from_utf8`.
+ ///
+ /// Returns an error if the slice contains invalid characters.
+ #[inline]
+ pub fn to_string(&self) -> Result<&'input str> {
+ str::from_utf8(self.slice).map_err(|_| Error::BadUtf8)
+ }
+
+ /// Converts the slice to a string, including invalid characters,
+ /// using `String::from_utf8_lossy`.
+ #[cfg(feature = "read")]
+ #[inline]
+ pub fn to_string_lossy(&self) -> Cow<'input, str> {
+ String::from_utf8_lossy(self.slice)
+ }
+
+ #[inline]
+ fn read_slice(&mut self, len: usize) -> Result<&'input [u8]> {
+ if self.slice.len() < len {
+ Err(Error::UnexpectedEof(self.offset_id()))
+ } else {
+ let val = &self.slice[..len];
+ self.slice = &self.slice[len..];
+ Ok(val)
+ }
+ }
+}
+
+/// # Range Methods
+///
+/// Unfortunately, `std::ops::Index` *must* return a reference, so we can't
+/// implement `Index<Range<usize>>` to return a new `EndianSlice` the way we would
+/// like to. Instead, we abandon fancy indexing operators and have these plain
+/// old methods.
+impl<'input, Endian> EndianSlice<'input, Endian>
+where
+ Endian: Endianity,
+{
+ /// Take the given `start..end` range of the underlying slice and return a
+ /// new `EndianSlice`.
+ ///
+ /// ```
+ /// use gimli::{EndianSlice, LittleEndian};
+ ///
+ /// let slice = &[0x01, 0x02, 0x03, 0x04];
+ /// let endian_slice = EndianSlice::new(slice, LittleEndian);
+ /// assert_eq!(endian_slice.range(1..3),
+ /// EndianSlice::new(&slice[1..3], LittleEndian));
+ /// ```
+ pub fn range(&self, idx: Range<usize>) -> EndianSlice<'input, Endian> {
+ EndianSlice {
+ slice: &self.slice[idx],
+ endian: self.endian,
+ }
+ }
+
+ /// Take the given `start..` range of the underlying slice and return a new
+ /// `EndianSlice`.
+ ///
+ /// ```
+ /// use gimli::{EndianSlice, LittleEndian};
+ ///
+ /// let slice = &[0x01, 0x02, 0x03, 0x04];
+ /// let endian_slice = EndianSlice::new(slice, LittleEndian);
+ /// assert_eq!(endian_slice.range_from(2..),
+ /// EndianSlice::new(&slice[2..], LittleEndian));
+ /// ```
+ pub fn range_from(&self, idx: RangeFrom<usize>) -> EndianSlice<'input, Endian> {
+ EndianSlice {
+ slice: &self.slice[idx],
+ endian: self.endian,
+ }
+ }
+
+ /// Take the given `..end` range of the underlying slice and return a new
+ /// `EndianSlice`.
+ ///
+ /// ```
+ /// use gimli::{EndianSlice, LittleEndian};
+ ///
+ /// let slice = &[0x01, 0x02, 0x03, 0x04];
+ /// let endian_slice = EndianSlice::new(slice, LittleEndian);
+ /// assert_eq!(endian_slice.range_to(..3),
+ /// EndianSlice::new(&slice[..3], LittleEndian));
+ /// ```
+ pub fn range_to(&self, idx: RangeTo<usize>) -> EndianSlice<'input, Endian> {
+ EndianSlice {
+ slice: &self.slice[idx],
+ endian: self.endian,
+ }
+ }
+}
+
+impl<'input, Endian> Index<usize> for EndianSlice<'input, Endian>
+where
+ Endian: Endianity,
+{
+ type Output = u8;
+ fn index(&self, idx: usize) -> &Self::Output {
+ &self.slice[idx]
+ }
+}
+
+impl<'input, Endian> Index<RangeFrom<usize>> for EndianSlice<'input, Endian>
+where
+ Endian: Endianity,
+{
+ type Output = [u8];
+ fn index(&self, idx: RangeFrom<usize>) -> &Self::Output {
+ &self.slice[idx]
+ }
+}
+
+impl<'input, Endian> Deref for EndianSlice<'input, Endian>
+where
+ Endian: Endianity,
+{
+ type Target = [u8];
+ fn deref(&self) -> &Self::Target {
+ self.slice
+ }
+}
+
+impl<'input, Endian> Into<&'input [u8]> for EndianSlice<'input, Endian>
+where
+ Endian: Endianity,
+{
+ fn into(self) -> &'input [u8] {
+ self.slice
+ }
+}
+
+impl<'input, Endian> Reader for EndianSlice<'input, Endian>
+where
+ Endian: Endianity,
+{
+ type Endian = Endian;
+ type Offset = usize;
+
+ #[inline]
+ fn endian(&self) -> Endian {
+ self.endian
+ }
+
+ #[inline]
+ fn len(&self) -> usize {
+ self.slice.len()
+ }
+
+ #[inline]
+ fn is_empty(&self) -> bool {
+ self.slice.is_empty()
+ }
+
+ #[inline]
+ fn empty(&mut self) {
+ self.slice = &[];
+ }
+
+ #[inline]
+ fn truncate(&mut self, len: usize) -> Result<()> {
+ if self.slice.len() < len {
+ Err(Error::UnexpectedEof(self.offset_id()))
+ } else {
+ self.slice = &self.slice[..len];
+ Ok(())
+ }
+ }
+
+ #[inline]
+ fn offset_from(&self, base: &Self) -> usize {
+ self.offset_from(*base)
+ }
+
+ #[inline]
+ fn offset_id(&self) -> ReaderOffsetId {
+ ReaderOffsetId(self.slice.as_ptr() as u64)
+ }
+
+ #[inline]
+ fn lookup_offset_id(&self, id: ReaderOffsetId) -> Option<Self::Offset> {
+ let id = id.0;
+ let self_id = self.slice.as_ptr() as u64;
+ let self_len = self.slice.len() as u64;
+ if id >= self_id && id <= self_id + self_len {
+ Some((id - self_id) as usize)
+ } else {
+ None
+ }
+ }
+
+ #[inline]
+ fn find(&self, byte: u8) -> Result<usize> {
+ self.find(byte)
+ .ok_or_else(|| Error::UnexpectedEof(self.offset_id()))
+ }
+
+ #[inline]
+ fn skip(&mut self, len: usize) -> Result<()> {
+ if self.slice.len() < len {
+ Err(Error::UnexpectedEof(self.offset_id()))
+ } else {
+ self.slice = &self.slice[len..];
+ Ok(())
+ }
+ }
+
+ #[inline]
+ fn split(&mut self, len: usize) -> Result<Self> {
+ let slice = self.read_slice(len)?;
+ Ok(EndianSlice::new(slice, self.endian))
+ }
+
+ #[cfg(not(feature = "read"))]
+ fn cannot_implement() -> super::reader::seal_if_no_alloc::Sealed {
+ super::reader::seal_if_no_alloc::Sealed
+ }
+
+ #[cfg(feature = "read")]
+ #[inline]
+ fn to_slice(&self) -> Result<Cow<[u8]>> {
+ Ok(self.slice.into())
+ }
+
+ #[cfg(feature = "read")]
+ #[inline]
+ fn to_string(&self) -> Result<Cow<str>> {
+ match str::from_utf8(self.slice) {
+ Ok(s) => Ok(s.into()),
+ _ => Err(Error::BadUtf8),
+ }
+ }
+
+ #[cfg(feature = "read")]
+ #[inline]
+ fn to_string_lossy(&self) -> Result<Cow<str>> {
+ Ok(String::from_utf8_lossy(self.slice))
+ }
+
+ #[inline]
+ fn read_slice(&mut self, buf: &mut [u8]) -> Result<()> {
+ let slice = self.read_slice(buf.len())?;
+ buf.copy_from_slice(slice);
+ Ok(())
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+ use crate::endianity::NativeEndian;
+
+ #[test]
+ fn test_endian_slice_split_at() {
+ let endian = NativeEndian;
+ let slice = &[1, 2, 3, 4, 5, 6, 7, 8, 9, 0];
+ let eb = EndianSlice::new(slice, endian);
+ assert_eq!(
+ eb.split_at(3),
+ (
+ EndianSlice::new(&slice[..3], endian),
+ EndianSlice::new(&slice[3..], endian)
+ )
+ );
+ }
+
+ #[test]
+ #[should_panic]
+ fn test_endian_slice_split_at_out_of_bounds() {
+ let slice = &[1, 2, 3, 4, 5, 6, 7, 8, 9, 0];
+ let eb = EndianSlice::new(slice, NativeEndian);
+ eb.split_at(30);
+ }
+}
diff --git a/vendor/gimli-0.26.2/src/read/index.rs b/vendor/gimli-0.26.2/src/read/index.rs
new file mode 100644
index 000000000..129eb2fb1
--- /dev/null
+++ b/vendor/gimli-0.26.2/src/read/index.rs
@@ -0,0 +1,535 @@
+use core::slice;
+
+use crate::common::SectionId;
+use crate::constants;
+use crate::endianity::Endianity;
+use crate::read::{EndianSlice, Error, Reader, ReaderOffset, Result, Section};
+
+/// The data in the `.debug_cu_index` section of a `.dwp` file.
+///
+/// This section contains the compilation unit index.
+#[derive(Debug, Default, Clone, Copy)]
+pub struct DebugCuIndex<R> {
+ section: R,
+}
+
+impl<'input, Endian> DebugCuIndex<EndianSlice<'input, Endian>>
+where
+ Endian: Endianity,
+{
+ /// Construct a new `DebugCuIndex` instance from the data in the `.debug_cu_index`
+ /// section.
+ pub fn new(section: &'input [u8], endian: Endian) -> Self {
+ Self::from(EndianSlice::new(section, endian))
+ }
+}
+
+impl<R> Section<R> for DebugCuIndex<R> {
+ fn id() -> SectionId {
+ SectionId::DebugCuIndex
+ }
+
+ fn reader(&self) -> &R {
+ &self.section
+ }
+}
+
+impl<R> From<R> for DebugCuIndex<R> {
+ fn from(section: R) -> Self {
+ DebugCuIndex { section }
+ }
+}
+
+impl<R: Reader> DebugCuIndex<R> {
+ /// Parse the index header.
+ pub fn index(self) -> Result<UnitIndex<R>> {
+ UnitIndex::parse(self.section)
+ }
+}
+
+/// The data in the `.debug_tu_index` section of a `.dwp` file.
+///
+/// This section contains the type unit index.
+#[derive(Debug, Default, Clone, Copy)]
+pub struct DebugTuIndex<R> {
+ section: R,
+}
+
+impl<'input, Endian> DebugTuIndex<EndianSlice<'input, Endian>>
+where
+ Endian: Endianity,
+{
+ /// Construct a new `DebugTuIndex` instance from the data in the `.debug_tu_index`
+ /// section.
+ pub fn new(section: &'input [u8], endian: Endian) -> Self {
+ Self::from(EndianSlice::new(section, endian))
+ }
+}
+
+impl<R> Section<R> for DebugTuIndex<R> {
+ fn id() -> SectionId {
+ SectionId::DebugTuIndex
+ }
+
+ fn reader(&self) -> &R {
+ &self.section
+ }
+}
+
+impl<R> From<R> for DebugTuIndex<R> {
+ fn from(section: R) -> Self {
+ DebugTuIndex { section }
+ }
+}
+
+impl<R: Reader> DebugTuIndex<R> {
+ /// Parse the index header.
+ pub fn index(self) -> Result<UnitIndex<R>> {
+ UnitIndex::parse(self.section)
+ }
+}
+
+const SECTION_COUNT_MAX: u8 = 8;
+
+/// The partially parsed index from a `DebugCuIndex` or `DebugTuIndex`.
+#[derive(Debug, Clone)]
+pub struct UnitIndex<R: Reader> {
+ version: u16,
+ section_count: u32,
+ unit_count: u32,
+ slot_count: u32,
+ hash_ids: R,
+ hash_rows: R,
+ // Only `section_count` values are valid.
+ sections: [SectionId; SECTION_COUNT_MAX as usize],
+ offsets: R,
+ sizes: R,
+}
+
+impl<R: Reader> UnitIndex<R> {
+ fn parse(mut input: R) -> Result<UnitIndex<R>> {
+ if input.is_empty() {
+ return Ok(UnitIndex {
+ version: 5,
+ section_count: 0,
+ unit_count: 0,
+ slot_count: 0,
+ hash_ids: input.clone(),
+ hash_rows: input.clone(),
+ sections: [SectionId::DebugAbbrev; SECTION_COUNT_MAX as usize],
+ offsets: input.clone(),
+ sizes: input.clone(),
+ });
+ }
+
+ // GNU split-dwarf extension to DWARF 4 uses a 32-bit version,
+ // but DWARF 5 uses a 16-bit version followed by 16-bit padding.
+ let mut original_input = input.clone();
+ let version;
+ if input.read_u32()? == 2 {
+ version = 2
+ } else {
+ version = original_input.read_u16()?;
+ if version != 5 {
+ return Err(Error::UnknownVersion(version.into()));
+ }
+ }
+
+ let section_count = input.read_u32()?;
+ let unit_count = input.read_u32()?;
+ let slot_count = input.read_u32()?;
+ if slot_count == 0 || slot_count & (slot_count - 1) != 0 || slot_count <= unit_count {
+ return Err(Error::InvalidIndexSlotCount);
+ }
+
+ let hash_ids = input.split(R::Offset::from_u64(u64::from(slot_count) * 8)?)?;
+ let hash_rows = input.split(R::Offset::from_u64(u64::from(slot_count) * 4)?)?;
+
+ let mut sections = [SectionId::DebugAbbrev; SECTION_COUNT_MAX as usize];
+ if section_count > SECTION_COUNT_MAX.into() {
+ return Err(Error::InvalidIndexSectionCount);
+ }
+ for i in 0..section_count {
+ let section = input.read_u32()?;
+ sections[i as usize] = if version == 2 {
+ match constants::DwSectV2(section) {
+ constants::DW_SECT_V2_INFO => SectionId::DebugInfo,
+ constants::DW_SECT_V2_TYPES => SectionId::DebugTypes,
+ constants::DW_SECT_V2_ABBREV => SectionId::DebugAbbrev,
+ constants::DW_SECT_V2_LINE => SectionId::DebugLine,
+ constants::DW_SECT_V2_LOC => SectionId::DebugLoc,
+ constants::DW_SECT_V2_STR_OFFSETS => SectionId::DebugStrOffsets,
+ constants::DW_SECT_V2_MACINFO => SectionId::DebugMacinfo,
+ constants::DW_SECT_V2_MACRO => SectionId::DebugMacro,
+ _ => return Err(Error::UnknownIndexSection),
+ }
+ } else {
+ match constants::DwSect(section) {
+ constants::DW_SECT_INFO => SectionId::DebugInfo,
+ constants::DW_SECT_ABBREV => SectionId::DebugAbbrev,
+ constants::DW_SECT_LINE => SectionId::DebugLine,
+ constants::DW_SECT_LOCLISTS => SectionId::DebugLocLists,
+ constants::DW_SECT_STR_OFFSETS => SectionId::DebugStrOffsets,
+ constants::DW_SECT_MACRO => SectionId::DebugMacro,
+ constants::DW_SECT_RNGLISTS => SectionId::DebugRngLists,
+ _ => return Err(Error::UnknownIndexSection),
+ }
+ };
+ }
+
+ let offsets = input.split(R::Offset::from_u64(
+ u64::from(unit_count) * u64::from(section_count) * 4,
+ )?)?;
+ let sizes = input.split(R::Offset::from_u64(
+ u64::from(unit_count) * u64::from(section_count) * 4,
+ )?)?;
+
+ Ok(UnitIndex {
+ version,
+ section_count,
+ unit_count,
+ slot_count,
+ hash_ids,
+ hash_rows,
+ sections,
+ offsets,
+ sizes,
+ })
+ }
+
+ /// Find `id` in the index hash table, and return the row index.
+ ///
+ /// `id` may be a compilation unit ID if this index is from `.debug_cu_index`,
+ /// or a type signature if this index is from `.debug_tu_index`.
+ pub fn find(&self, id: u64) -> Option<u32> {
+ if self.slot_count == 0 {
+ return None;
+ }
+ let mask = u64::from(self.slot_count - 1);
+ let mut hash1 = id & mask;
+ let hash2 = ((id >> 32) & mask) | 1;
+ for _ in 0..self.slot_count {
+ // The length of these arrays was validated in `UnitIndex::parse`.
+ let mut hash_ids = self.hash_ids.clone();
+ hash_ids.skip(R::Offset::from_u64(hash1 * 8).ok()?).ok()?;
+ let hash_id = hash_ids.read_u64().ok()?;
+ if hash_id == id {
+ let mut hash_rows = self.hash_rows.clone();
+ hash_rows.skip(R::Offset::from_u64(hash1 * 4).ok()?).ok()?;
+ let hash_row = hash_rows.read_u32().ok()?;
+ return Some(hash_row);
+ }
+ if hash_id == 0 {
+ return None;
+ }
+ hash1 = (hash1 + hash2) & mask;
+ }
+ None
+ }
+
+ /// Return the section offsets and sizes for the given row index.
+ pub fn sections(&self, mut row: u32) -> Result<UnitIndexSectionIterator<R>> {
+ if row == 0 {
+ return Err(Error::InvalidIndexRow);
+ }
+ row -= 1;
+ if row >= self.unit_count {
+ return Err(Error::InvalidIndexRow);
+ }
+ let mut offsets = self.offsets.clone();
+ offsets.skip(R::Offset::from_u64(
+ u64::from(row) * u64::from(self.section_count) * 4,
+ )?)?;
+ let mut sizes = self.sizes.clone();
+ sizes.skip(R::Offset::from_u64(
+ u64::from(row) * u64::from(self.section_count) * 4,
+ )?)?;
+ Ok(UnitIndexSectionIterator {
+ sections: self.sections[..self.section_count as usize].iter(),
+ offsets,
+ sizes,
+ })
+ }
+
+ /// Return the version.
+ pub fn version(&self) -> u16 {
+ self.version
+ }
+
+ /// Return the number of sections.
+ pub fn section_count(&self) -> u32 {
+ self.section_count
+ }
+
+ /// Return the number of units.
+ pub fn unit_count(&self) -> u32 {
+ self.unit_count
+ }
+
+ /// Return the number of slots.
+ pub fn slot_count(&self) -> u32 {
+ self.slot_count
+ }
+}
+
+/// An iterator over the section offsets and sizes for a row in a `UnitIndex`.
+#[derive(Debug, Clone)]
+pub struct UnitIndexSectionIterator<'index, R: Reader> {
+ sections: slice::Iter<'index, SectionId>,
+ offsets: R,
+ sizes: R,
+}
+
+impl<'index, R: Reader> Iterator for UnitIndexSectionIterator<'index, R> {
+ type Item = UnitIndexSection;
+
+ fn next(&mut self) -> Option<UnitIndexSection> {
+ let section = *self.sections.next()?;
+ // The length of these arrays was validated in `UnitIndex::parse`.
+ let offset = self.offsets.read_u32().ok()?;
+ let size = self.sizes.read_u32().ok()?;
+ Some(UnitIndexSection {
+ section,
+ offset,
+ size,
+ })
+ }
+}
+
+/// Information about a unit's contribution to a section in a `.dwp` file.
+#[derive(Debug, Clone, Copy, PartialEq, Eq)]
+pub struct UnitIndexSection {
+ /// The section kind.
+ pub section: SectionId,
+ /// The base offset of the unit's contribution to the section.
+ pub offset: u32,
+ /// The size of the unit's contribution to the section.
+ pub size: u32,
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+ use crate::endianity::BigEndian;
+ use test_assembler::{Endian, Section};
+
+ #[test]
+ fn test_empty() {
+ let buf = EndianSlice::new(&[], BigEndian);
+ let index = UnitIndex::parse(buf).unwrap();
+ assert!(index.find(0).is_none());
+ }
+
+ #[test]
+ fn test_version_2() {
+ #[rustfmt::skip]
+ let section = Section::with_endian(Endian::Big)
+ // Header.
+ .D32(2).D32(0).D32(0).D32(1)
+ // Slots.
+ .D64(0).D32(0);
+ let buf = section.get_contents().unwrap();
+ let buf = EndianSlice::new(&buf, BigEndian);
+ let index = UnitIndex::parse(buf).unwrap();
+ assert_eq!(index.version, 2);
+ }
+
+ #[test]
+ fn test_version_5() {
+ #[rustfmt::skip]
+ let section = Section::with_endian(Endian::Big)
+ // Header.
+ .D16(5).D16(0).D32(0).D32(0).D32(1)
+ // Slots.
+ .D64(0).D32(0);
+ let buf = section.get_contents().unwrap();
+ let buf = EndianSlice::new(&buf, BigEndian);
+ let index = UnitIndex::parse(buf).unwrap();
+ assert_eq!(index.version, 5);
+ }
+
+ #[test]
+ fn test_version_5_invalid() {
+ #[rustfmt::skip]
+ let section = Section::with_endian(Endian::Big)
+ // Header.
+ .D32(5).D32(0).D32(0).D32(1)
+ // Slots.
+ .D64(0).D32(0);
+ let buf = section.get_contents().unwrap();
+ let buf = EndianSlice::new(&buf, BigEndian);
+ assert!(UnitIndex::parse(buf).is_err());
+ }
+
+ #[test]
+ fn test_version_2_sections() {
+ #[rustfmt::skip]
+ let section = Section::with_endian(Endian::Big)
+ // Header.
+ .D32(2).D32(8).D32(1).D32(2)
+ // Slots.
+ .D64(0).D64(0).D32(0).D32(0)
+ // Sections.
+ .D32(constants::DW_SECT_V2_INFO.0)
+ .D32(constants::DW_SECT_V2_TYPES.0)
+ .D32(constants::DW_SECT_V2_ABBREV.0)
+ .D32(constants::DW_SECT_V2_LINE.0)
+ .D32(constants::DW_SECT_V2_LOC.0)
+ .D32(constants::DW_SECT_V2_STR_OFFSETS.0)
+ .D32(constants::DW_SECT_V2_MACINFO.0)
+ .D32(constants::DW_SECT_V2_MACRO.0)
+ // Offsets.
+ .D32(11).D32(12).D32(13).D32(14).D32(15).D32(16).D32(17).D32(18)
+ // Sizes.
+ .D32(21).D32(22).D32(23).D32(24).D32(25).D32(26).D32(27).D32(28);
+ let buf = section.get_contents().unwrap();
+ let buf = EndianSlice::new(&buf, BigEndian);
+ let index = UnitIndex::parse(buf).unwrap();
+ assert_eq!(index.section_count, 8);
+ assert_eq!(
+ index.sections,
+ [
+ SectionId::DebugInfo,
+ SectionId::DebugTypes,
+ SectionId::DebugAbbrev,
+ SectionId::DebugLine,
+ SectionId::DebugLoc,
+ SectionId::DebugStrOffsets,
+ SectionId::DebugMacinfo,
+ SectionId::DebugMacro,
+ ]
+ );
+ #[rustfmt::skip]
+ let expect = [
+ UnitIndexSection { section: SectionId::DebugInfo, offset: 11, size: 21 },
+ UnitIndexSection { section: SectionId::DebugTypes, offset: 12, size: 22 },
+ UnitIndexSection { section: SectionId::DebugAbbrev, offset: 13, size: 23 },
+ UnitIndexSection { section: SectionId::DebugLine, offset: 14, size: 24 },
+ UnitIndexSection { section: SectionId::DebugLoc, offset: 15, size: 25 },
+ UnitIndexSection { section: SectionId::DebugStrOffsets, offset: 16, size: 26 },
+ UnitIndexSection { section: SectionId::DebugMacinfo, offset: 17, size: 27 },
+ UnitIndexSection { section: SectionId::DebugMacro, offset: 18, size: 28 },
+ ];
+ let mut sections = index.sections(1).unwrap();
+ for section in &expect {
+ assert_eq!(*section, sections.next().unwrap());
+ }
+ assert!(sections.next().is_none());
+ }
+
+ #[test]
+ fn test_version_5_sections() {
+ #[rustfmt::skip]
+ let section = Section::with_endian(Endian::Big)
+ // Header.
+ .D16(5).D16(0).D32(7).D32(1).D32(2)
+ // Slots.
+ .D64(0).D64(0).D32(0).D32(0)
+ // Sections.
+ .D32(constants::DW_SECT_INFO.0)
+ .D32(constants::DW_SECT_ABBREV.0)
+ .D32(constants::DW_SECT_LINE.0)
+ .D32(constants::DW_SECT_LOCLISTS.0)
+ .D32(constants::DW_SECT_STR_OFFSETS.0)
+ .D32(constants::DW_SECT_MACRO.0)
+ .D32(constants::DW_SECT_RNGLISTS.0)
+ // Offsets.
+ .D32(11).D32(12).D32(13).D32(14).D32(15).D32(16).D32(17)
+ // Sizes.
+ .D32(21).D32(22).D32(23).D32(24).D32(25).D32(26).D32(27);
+ let buf = section.get_contents().unwrap();
+ let buf = EndianSlice::new(&buf, BigEndian);
+ let index = UnitIndex::parse(buf).unwrap();
+ assert_eq!(index.section_count, 7);
+ assert_eq!(
+ index.sections[..7],
+ [
+ SectionId::DebugInfo,
+ SectionId::DebugAbbrev,
+ SectionId::DebugLine,
+ SectionId::DebugLocLists,
+ SectionId::DebugStrOffsets,
+ SectionId::DebugMacro,
+ SectionId::DebugRngLists,
+ ]
+ );
+ #[rustfmt::skip]
+ let expect = [
+ UnitIndexSection { section: SectionId::DebugInfo, offset: 11, size: 21 },
+ UnitIndexSection { section: SectionId::DebugAbbrev, offset: 12, size: 22 },
+ UnitIndexSection { section: SectionId::DebugLine, offset: 13, size: 23 },
+ UnitIndexSection { section: SectionId::DebugLocLists, offset: 14, size: 24 },
+ UnitIndexSection { section: SectionId::DebugStrOffsets, offset: 15, size: 25 },
+ UnitIndexSection { section: SectionId::DebugMacro, offset: 16, size: 26 },
+ UnitIndexSection { section: SectionId::DebugRngLists, offset: 17, size: 27 },
+ ];
+ let mut sections = index.sections(1).unwrap();
+ for section in &expect {
+ assert_eq!(*section, sections.next().unwrap());
+ }
+ assert!(sections.next().is_none());
+
+ assert!(index.sections(0).is_err());
+ assert!(index.sections(2).is_err());
+ }
+
+ #[test]
+ fn test_hash() {
+ #[rustfmt::skip]
+ let section = Section::with_endian(Endian::Big)
+ // Header.
+ .D16(5).D16(0).D32(2).D32(3).D32(4)
+ // Slots.
+ .D64(0xffff_fff2_ffff_fff1)
+ .D64(0xffff_fff0_ffff_fff1)
+ .D64(0xffff_fff1_ffff_fff1)
+ .D64(0)
+ .D32(3).D32(1).D32(2).D32(0)
+ // Sections.
+ .D32(constants::DW_SECT_INFO.0)
+ .D32(constants::DW_SECT_ABBREV.0)
+ // Offsets.
+ .D32(0).D32(0).D32(0).D32(0).D32(0).D32(0)
+ // Sizes.
+ .D32(0).D32(0).D32(0).D32(0).D32(0).D32(0);
+ let buf = section.get_contents().unwrap();
+ let buf = EndianSlice::new(&buf, BigEndian);
+ let index = UnitIndex::parse(buf).unwrap();
+ assert_eq!(index.version(), 5);
+ assert_eq!(index.slot_count(), 4);
+ assert_eq!(index.unit_count(), 3);
+ assert_eq!(index.section_count(), 2);
+ assert_eq!(index.find(0xffff_fff0_ffff_fff1), Some(1));
+ assert_eq!(index.find(0xffff_fff1_ffff_fff1), Some(2));
+ assert_eq!(index.find(0xffff_fff2_ffff_fff1), Some(3));
+ assert_eq!(index.find(0xffff_fff3_ffff_fff1), None);
+ }
+
+ #[test]
+ fn test_cu_index() {
+ #[rustfmt::skip]
+ let section = Section::with_endian(Endian::Big)
+ // Header.
+ .D16(5).D16(0).D32(0).D32(0).D32(1)
+ // Slots.
+ .D64(0).D32(0);
+ let buf = section.get_contents().unwrap();
+ let cu_index = DebugCuIndex::new(&buf, BigEndian);
+ let index = cu_index.index().unwrap();
+ assert_eq!(index.version, 5);
+ }
+
+ #[test]
+ fn test_tu_index() {
+ #[rustfmt::skip]
+ let section = Section::with_endian(Endian::Big)
+ // Header.
+ .D16(5).D16(0).D32(0).D32(0).D32(1)
+ // Slots.
+ .D64(0).D32(0);
+ let buf = section.get_contents().unwrap();
+ let tu_index = DebugTuIndex::new(&buf, BigEndian);
+ let index = tu_index.index().unwrap();
+ assert_eq!(index.version, 5);
+ }
+}
diff --git a/vendor/gimli-0.26.2/src/read/line.rs b/vendor/gimli-0.26.2/src/read/line.rs
new file mode 100644
index 000000000..0e7380bb9
--- /dev/null
+++ b/vendor/gimli-0.26.2/src/read/line.rs
@@ -0,0 +1,3030 @@
+use alloc::vec::Vec;
+use core::fmt;
+use core::num::{NonZeroU64, Wrapping};
+use core::result;
+
+use crate::common::{
+ DebugLineOffset, DebugLineStrOffset, DebugStrOffset, DebugStrOffsetsIndex, Encoding, Format,
+ LineEncoding, SectionId,
+};
+use crate::constants;
+use crate::endianity::Endianity;
+use crate::read::{AttributeValue, EndianSlice, Error, Reader, ReaderOffset, Result, Section};
+
+/// The `DebugLine` struct contains the source location to instruction mapping
+/// found in the `.debug_line` section.
+#[derive(Debug, Default, Clone, Copy)]
+pub struct DebugLine<R> {
+ debug_line_section: R,
+}
+
+impl<'input, Endian> DebugLine<EndianSlice<'input, Endian>>
+where
+ Endian: Endianity,
+{
+ /// Construct a new `DebugLine` instance from the data in the `.debug_line`
+ /// section.
+ ///
+ /// It is the caller's responsibility to read the `.debug_line` section and
+ /// present it as a `&[u8]` slice. That means using some ELF loader on
+ /// Linux, a Mach-O loader on macOS, etc.
+ ///
+ /// ```
+ /// use gimli::{DebugLine, LittleEndian};
+ ///
+ /// # let buf = [0x00, 0x01, 0x02, 0x03];
+ /// # let read_debug_line_section_somehow = || &buf;
+ /// let debug_line = DebugLine::new(read_debug_line_section_somehow(), LittleEndian);
+ /// ```
+ pub fn new(debug_line_section: &'input [u8], endian: Endian) -> Self {
+ Self::from(EndianSlice::new(debug_line_section, endian))
+ }
+}
+
+impl<R: Reader> DebugLine<R> {
+ /// Parse the line number program whose header is at the given `offset` in the
+ /// `.debug_line` section.
+ ///
+ /// The `address_size` must match the compilation unit that the lines apply to.
+ /// The `comp_dir` should be from the `DW_AT_comp_dir` attribute of the compilation
+ /// unit. The `comp_name` should be from the `DW_AT_name` attribute of the
+ /// compilation unit.
+ ///
+ /// ```rust,no_run
+ /// use gimli::{DebugLine, DebugLineOffset, IncompleteLineProgram, EndianSlice, LittleEndian};
+ ///
+ /// # let buf = [];
+ /// # let read_debug_line_section_somehow = || &buf;
+ /// let debug_line = DebugLine::new(read_debug_line_section_somehow(), LittleEndian);
+ ///
+ /// // In a real example, we'd grab the offset via a compilation unit
+ /// // entry's `DW_AT_stmt_list` attribute, and the address size from that
+ /// // unit directly.
+ /// let offset = DebugLineOffset(0);
+ /// let address_size = 8;
+ ///
+ /// let program = debug_line.program(offset, address_size, None, None)
+ /// .expect("should have found a header at that offset, and parsed it OK");
+ /// ```
+ pub fn program(
+ &self,
+ offset: DebugLineOffset<R::Offset>,
+ address_size: u8,
+ comp_dir: Option<R>,
+ comp_name: Option<R>,
+ ) -> Result<IncompleteLineProgram<R>> {
+ let input = &mut self.debug_line_section.clone();
+ input.skip(offset.0)?;
+ let header = LineProgramHeader::parse(input, offset, address_size, comp_dir, comp_name)?;
+ let program = IncompleteLineProgram { header };
+ Ok(program)
+ }
+}
+
+impl<T> DebugLine<T> {
+ /// Create a `DebugLine` section that references the data in `self`.
+ ///
+ /// This is useful when `R` implements `Reader` but `T` does not.
+ ///
+ /// ## Example Usage
+ ///
+ /// ```rust,no_run
+ /// # let load_section = || unimplemented!();
+ /// // Read the DWARF section into a `Vec` with whatever object loader you're using.
+ /// let owned_section: gimli::DebugLine<Vec<u8>> = load_section();
+ /// // Create a reference to the DWARF section.
+ /// let section = owned_section.borrow(|section| {
+ /// gimli::EndianSlice::new(&section, gimli::LittleEndian)
+ /// });
+ /// ```
+ pub fn borrow<'a, F, R>(&'a self, mut borrow: F) -> DebugLine<R>
+ where
+ F: FnMut(&'a T) -> R,
+ {
+ borrow(&self.debug_line_section).into()
+ }
+}
+
+impl<R> Section<R> for DebugLine<R> {
+ fn id() -> SectionId {
+ SectionId::DebugLine
+ }
+
+ fn reader(&self) -> &R {
+ &self.debug_line_section
+ }
+}
+
+impl<R> From<R> for DebugLine<R> {
+ fn from(debug_line_section: R) -> Self {
+ DebugLine { debug_line_section }
+ }
+}
+
+/// Deprecated. `LineNumberProgram` has been renamed to `LineProgram`.
+#[deprecated(note = "LineNumberProgram has been renamed to LineProgram, use that instead.")]
+pub type LineNumberProgram<R, Offset> = dyn LineProgram<R, Offset>;
+
+/// A `LineProgram` provides access to a `LineProgramHeader` and
+/// a way to add files to the files table if necessary. Gimli consumers should
+/// never need to use or see this trait.
+pub trait LineProgram<R, Offset = <R as Reader>::Offset>
+where
+ R: Reader<Offset = Offset>,
+ Offset: ReaderOffset,
+{
+ /// Get a reference to the held `LineProgramHeader`.
+ fn header(&self) -> &LineProgramHeader<R, Offset>;
+ /// Add a file to the file table if necessary.
+ fn add_file(&mut self, file: FileEntry<R, Offset>);
+}
+
+impl<R, Offset> LineProgram<R, Offset> for IncompleteLineProgram<R, Offset>
+where
+ R: Reader<Offset = Offset>,
+ Offset: ReaderOffset,
+{
+ fn header(&self) -> &LineProgramHeader<R, Offset> {
+ &self.header
+ }
+ fn add_file(&mut self, file: FileEntry<R, Offset>) {
+ self.header.file_names.push(file);
+ }
+}
+
+impl<'program, R, Offset> LineProgram<R, Offset> for &'program CompleteLineProgram<R, Offset>
+where
+ R: Reader<Offset = Offset>,
+ Offset: ReaderOffset,
+{
+ fn header(&self) -> &LineProgramHeader<R, Offset> {
+ &self.header
+ }
+ fn add_file(&mut self, _: FileEntry<R, Offset>) {
+ // Nop. Our file table is already complete.
+ }
+}
+
+/// Deprecated. `StateMachine` has been renamed to `LineRows`.
+#[deprecated(note = "StateMachine has been renamed to LineRows, use that instead.")]
+pub type StateMachine<R, Program, Offset> = LineRows<R, Program, Offset>;
+
+/// Executes a `LineProgram` to iterate over the rows in the matrix of line number information.
+///
+/// "The hypothetical machine used by a consumer of the line number information
+/// to expand the byte-coded instruction stream into a matrix of line number
+/// information." -- Section 6.2.1
+#[derive(Debug, Clone)]
+pub struct LineRows<R, Program, Offset = <R as Reader>::Offset>
+where
+ Program: LineProgram<R, Offset>,
+ R: Reader<Offset = Offset>,
+ Offset: ReaderOffset,
+{
+ program: Program,
+ row: LineRow,
+ instructions: LineInstructions<R>,
+}
+
+type OneShotLineRows<R, Offset = <R as Reader>::Offset> =
+ LineRows<R, IncompleteLineProgram<R, Offset>, Offset>;
+
+type ResumedLineRows<'program, R, Offset = <R as Reader>::Offset> =
+ LineRows<R, &'program CompleteLineProgram<R, Offset>, Offset>;
+
+impl<R, Program, Offset> LineRows<R, Program, Offset>
+where
+ Program: LineProgram<R, Offset>,
+ R: Reader<Offset = Offset>,
+ Offset: ReaderOffset,
+{
+ #[allow(clippy::new_ret_no_self)]
+ fn new(program: IncompleteLineProgram<R, Offset>) -> OneShotLineRows<R, Offset> {
+ let row = LineRow::new(program.header());
+ let instructions = LineInstructions {
+ input: program.header().program_buf.clone(),
+ };
+ LineRows {
+ program,
+ row,
+ instructions,
+ }
+ }
+
+ fn resume<'program>(
+ program: &'program CompleteLineProgram<R, Offset>,
+ sequence: &LineSequence<R>,
+ ) -> ResumedLineRows<'program, R, Offset> {
+ let row = LineRow::new(program.header());
+ let instructions = sequence.instructions.clone();
+ LineRows {
+ program,
+ row,
+ instructions,
+ }
+ }
+
+ /// Get a reference to the header for this state machine's line number
+ /// program.
+ #[inline]
+ pub fn header(&self) -> &LineProgramHeader<R, Offset> {
+ self.program.header()
+ }
+
+ /// Parse and execute the next instructions in the line number program until
+ /// another row in the line number matrix is computed.
+ ///
+ /// The freshly computed row is returned as `Ok(Some((header, row)))`.
+ /// If the matrix is complete, and there are no more new rows in the line
+ /// number matrix, then `Ok(None)` is returned. If there was an error parsing
+ /// an instruction, then `Err(e)` is returned.
+ ///
+ /// Unfortunately, the references mean that this cannot be a
+ /// `FallibleIterator`.
+ pub fn next_row(&mut self) -> Result<Option<(&LineProgramHeader<R, Offset>, &LineRow)>> {
+ // Perform any reset that was required after copying the previous row.
+ self.row.reset(self.program.header());
+
+ loop {
+ // Split the borrow here, rather than calling `self.header()`.
+ match self.instructions.next_instruction(self.program.header()) {
+ Err(err) => return Err(err),
+ Ok(None) => return Ok(None),
+ Ok(Some(instruction)) => {
+ if self.row.execute(instruction, &mut self.program) {
+ return Ok(Some((self.header(), &self.row)));
+ }
+ // Fall through, parse the next instruction, and see if that
+ // yields a row.
+ }
+ }
+ }
+ }
+}
+
+/// Deprecated. `Opcode` has been renamed to `LineInstruction`.
+#[deprecated(note = "Opcode has been renamed to LineInstruction, use that instead.")]
+pub type Opcode<R> = LineInstruction<R, <R as Reader>::Offset>;
+
+/// A parsed line number program instruction.
+#[derive(Clone, Copy, Debug, PartialEq, Eq)]
+pub enum LineInstruction<R, Offset = <R as Reader>::Offset>
+where
+ R: Reader<Offset = Offset>,
+ Offset: ReaderOffset,
+{
+ /// > ### 6.2.5.1 Special Opcodes
+ /// >
+ /// > Each ubyte special opcode has the following effect on the state machine:
+ /// >
+ /// > 1. Add a signed integer to the line register.
+ /// >
+ /// > 2. Modify the operation pointer by incrementing the address and
+ /// > op_index registers as described below.
+ /// >
+ /// > 3. Append a row to the matrix using the current values of the state
+ /// > machine registers.
+ /// >
+ /// > 4. Set the basic_block register to “false.”
+ /// >
+ /// > 5. Set the prologue_end register to “false.”
+ /// >
+ /// > 6. Set the epilogue_begin register to “false.”
+ /// >
+ /// > 7. Set the discriminator register to 0.
+ /// >
+ /// > All of the special opcodes do those same seven things; they differ from
+ /// > one another only in what values they add to the line, address and
+ /// > op_index registers.
+ Special(u8),
+
+ /// "[`LineInstruction::Copy`] appends a row to the matrix using the current
+ /// values of the state machine registers. Then it sets the discriminator
+ /// register to 0, and sets the basic_block, prologue_end and epilogue_begin
+ /// registers to “false.”"
+ Copy,
+
+ /// "The DW_LNS_advance_pc opcode takes a single unsigned LEB128 operand as
+ /// the operation advance and modifies the address and op_index registers
+ /// [the same as `LineInstruction::Special`]"
+ AdvancePc(u64),
+
+ /// "The DW_LNS_advance_line opcode takes a single signed LEB128 operand and
+ /// adds that value to the line register of the state machine."
+ AdvanceLine(i64),
+
+ /// "The DW_LNS_set_file opcode takes a single unsigned LEB128 operand and
+ /// stores it in the file register of the state machine."
+ SetFile(u64),
+
+ /// "The DW_LNS_set_column opcode takes a single unsigned LEB128 operand and
+ /// stores it in the column register of the state machine."
+ SetColumn(u64),
+
+ /// "The DW_LNS_negate_stmt opcode takes no operands. It sets the is_stmt
+ /// register of the state machine to the logical negation of its current
+ /// value."
+ NegateStatement,
+
+ /// "The DW_LNS_set_basic_block opcode takes no operands. It sets the
+ /// basic_block register of the state machine to “true.”"
+ SetBasicBlock,
+
+ /// > The DW_LNS_const_add_pc opcode takes no operands. It advances the
+ /// > address and op_index registers by the increments corresponding to
+ /// > special opcode 255.
+ /// >
+ /// > When the line number program needs to advance the address by a small
+ /// > amount, it can use a single special opcode, which occupies a single
+ /// > byte. When it needs to advance the address by up to twice the range of
+ /// > the last special opcode, it can use DW_LNS_const_add_pc followed by a
+ /// > special opcode, for a total of two bytes. Only if it needs to advance
+ /// > the address by more than twice that range will it need to use both
+ /// > DW_LNS_advance_pc and a special opcode, requiring three or more bytes.
+ ConstAddPc,
+
+ /// > The DW_LNS_fixed_advance_pc opcode takes a single uhalf (unencoded)
+ /// > operand and adds it to the address register of the state machine and
+ /// > sets the op_index register to 0. This is the only standard opcode whose
+ /// > operand is not a variable length number. It also does not multiply the
+ /// > operand by the minimum_instruction_length field of the header.
+ FixedAddPc(u16),
+
+ /// "[`LineInstruction::SetPrologueEnd`] sets the prologue_end register to “true”."
+ SetPrologueEnd,
+
+ /// "[`LineInstruction::SetEpilogueBegin`] sets the epilogue_begin register to
+ /// “true”."
+ SetEpilogueBegin,
+
+ /// "The DW_LNS_set_isa opcode takes a single unsigned LEB128 operand and
+ /// stores that value in the isa register of the state machine."
+ SetIsa(u64),
+
+ /// An unknown standard opcode with zero operands.
+ UnknownStandard0(constants::DwLns),
+
+ /// An unknown standard opcode with one operand.
+ UnknownStandard1(constants::DwLns, u64),
+
+ /// An unknown standard opcode with multiple operands.
+ UnknownStandardN(constants::DwLns, R),
+
+ /// > [`LineInstruction::EndSequence`] sets the end_sequence register of the state
+ /// > machine to “true” and appends a row to the matrix using the current
+ /// > values of the state-machine registers. Then it resets the registers to
+ /// > the initial values specified above (see Section 6.2.2). Every line
+ /// > number program sequence must end with a DW_LNE_end_sequence instruction
+ /// > which creates a row whose address is that of the byte after the last
+ /// > target machine instruction of the sequence.
+ EndSequence,
+
+ /// > The DW_LNE_set_address opcode takes a single relocatable address as an
+ /// > operand. The size of the operand is the size of an address on the target
+ /// > machine. It sets the address register to the value given by the
+ /// > relocatable address and sets the op_index register to 0.
+ /// >
+ /// > All of the other line number program opcodes that affect the address
+ /// > register add a delta to it. This instruction stores a relocatable value
+ /// > into it instead.
+ SetAddress(u64),
+
+ /// Defines a new source file in the line number program and appends it to
+ /// the line number program header's list of source files.
+ DefineFile(FileEntry<R, Offset>),
+
+ /// "The DW_LNE_set_discriminator opcode takes a single parameter, an
+ /// unsigned LEB128 integer. It sets the discriminator register to the new
+ /// value."
+ SetDiscriminator(u64),
+
+ /// An unknown extended opcode and the slice of its unparsed operands.
+ UnknownExtended(constants::DwLne, R),
+}
+
+impl<R, Offset> LineInstruction<R, Offset>
+where
+ R: Reader<Offset = Offset>,
+ Offset: ReaderOffset,
+{
+ fn parse<'header>(
+ header: &'header LineProgramHeader<R>,
+ input: &mut R,
+ ) -> Result<LineInstruction<R>>
+ where
+ R: 'header,
+ {
+ let opcode = input.read_u8()?;
+ if opcode == 0 {
+ let length = input.read_uleb128().and_then(R::Offset::from_u64)?;
+ let mut instr_rest = input.split(length)?;
+ let opcode = instr_rest.read_u8()?;
+
+ match constants::DwLne(opcode) {
+ constants::DW_LNE_end_sequence => Ok(LineInstruction::EndSequence),
+
+ constants::DW_LNE_set_address => {
+ let address = instr_rest.read_address(header.address_size())?;
+ Ok(LineInstruction::SetAddress(address))
+ }
+
+ constants::DW_LNE_define_file => {
+ if header.version() <= 4 {
+ let path_name = instr_rest.read_null_terminated_slice()?;
+ let entry = FileEntry::parse(&mut instr_rest, path_name)?;
+ Ok(LineInstruction::DefineFile(entry))
+ } else {
+ Ok(LineInstruction::UnknownExtended(
+ constants::DW_LNE_define_file,
+ instr_rest,
+ ))
+ }
+ }
+
+ constants::DW_LNE_set_discriminator => {
+ let discriminator = instr_rest.read_uleb128()?;
+ Ok(LineInstruction::SetDiscriminator(discriminator))
+ }
+
+ otherwise => Ok(LineInstruction::UnknownExtended(otherwise, instr_rest)),
+ }
+ } else if opcode >= header.opcode_base {
+ Ok(LineInstruction::Special(opcode))
+ } else {
+ match constants::DwLns(opcode) {
+ constants::DW_LNS_copy => Ok(LineInstruction::Copy),
+
+ constants::DW_LNS_advance_pc => {
+ let advance = input.read_uleb128()?;
+ Ok(LineInstruction::AdvancePc(advance))
+ }
+
+ constants::DW_LNS_advance_line => {
+ let increment = input.read_sleb128()?;
+ Ok(LineInstruction::AdvanceLine(increment))
+ }
+
+ constants::DW_LNS_set_file => {
+ let file = input.read_uleb128()?;
+ Ok(LineInstruction::SetFile(file))
+ }
+
+ constants::DW_LNS_set_column => {
+ let column = input.read_uleb128()?;
+ Ok(LineInstruction::SetColumn(column))
+ }
+
+ constants::DW_LNS_negate_stmt => Ok(LineInstruction::NegateStatement),
+
+ constants::DW_LNS_set_basic_block => Ok(LineInstruction::SetBasicBlock),
+
+ constants::DW_LNS_const_add_pc => Ok(LineInstruction::ConstAddPc),
+
+ constants::DW_LNS_fixed_advance_pc => {
+ let advance = input.read_u16()?;
+ Ok(LineInstruction::FixedAddPc(advance))
+ }
+
+ constants::DW_LNS_set_prologue_end => Ok(LineInstruction::SetPrologueEnd),
+
+ constants::DW_LNS_set_epilogue_begin => Ok(LineInstruction::SetEpilogueBegin),
+
+ constants::DW_LNS_set_isa => {
+ let isa = input.read_uleb128()?;
+ Ok(LineInstruction::SetIsa(isa))
+ }
+
+ otherwise => {
+ let mut opcode_lengths = header.standard_opcode_lengths().clone();
+ opcode_lengths.skip(R::Offset::from_u8(opcode - 1))?;
+ let num_args = opcode_lengths.read_u8()? as usize;
+ match num_args {
+ 0 => Ok(LineInstruction::UnknownStandard0(otherwise)),
+ 1 => {
+ let arg = input.read_uleb128()?;
+ Ok(LineInstruction::UnknownStandard1(otherwise, arg))
+ }
+ _ => {
+ let mut args = input.clone();
+ for _ in 0..num_args {
+ input.read_uleb128()?;
+ }
+ let len = input.offset_from(&args);
+ args.truncate(len)?;
+ Ok(LineInstruction::UnknownStandardN(otherwise, args))
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+impl<R, Offset> fmt::Display for LineInstruction<R, Offset>
+where
+ R: Reader<Offset = Offset>,
+ Offset: ReaderOffset,
+{
+ fn fmt(&self, f: &mut fmt::Formatter) -> result::Result<(), fmt::Error> {
+ match *self {
+ LineInstruction::Special(opcode) => write!(f, "Special opcode {}", opcode),
+ LineInstruction::Copy => write!(f, "{}", constants::DW_LNS_copy),
+ LineInstruction::AdvancePc(advance) => {
+ write!(f, "{} by {}", constants::DW_LNS_advance_pc, advance)
+ }
+ LineInstruction::AdvanceLine(increment) => {
+ write!(f, "{} by {}", constants::DW_LNS_advance_line, increment)
+ }
+ LineInstruction::SetFile(file) => {
+ write!(f, "{} to {}", constants::DW_LNS_set_file, file)
+ }
+ LineInstruction::SetColumn(column) => {
+ write!(f, "{} to {}", constants::DW_LNS_set_column, column)
+ }
+ LineInstruction::NegateStatement => write!(f, "{}", constants::DW_LNS_negate_stmt),
+ LineInstruction::SetBasicBlock => write!(f, "{}", constants::DW_LNS_set_basic_block),
+ LineInstruction::ConstAddPc => write!(f, "{}", constants::DW_LNS_const_add_pc),
+ LineInstruction::FixedAddPc(advance) => {
+ write!(f, "{} by {}", constants::DW_LNS_fixed_advance_pc, advance)
+ }
+ LineInstruction::SetPrologueEnd => write!(f, "{}", constants::DW_LNS_set_prologue_end),
+ LineInstruction::SetEpilogueBegin => {
+ write!(f, "{}", constants::DW_LNS_set_epilogue_begin)
+ }
+ LineInstruction::SetIsa(isa) => write!(f, "{} to {}", constants::DW_LNS_set_isa, isa),
+ LineInstruction::UnknownStandard0(opcode) => write!(f, "Unknown {}", opcode),
+ LineInstruction::UnknownStandard1(opcode, arg) => {
+ write!(f, "Unknown {} with operand {}", opcode, arg)
+ }
+ LineInstruction::UnknownStandardN(opcode, ref args) => {
+ write!(f, "Unknown {} with operands {:?}", opcode, args)
+ }
+ LineInstruction::EndSequence => write!(f, "{}", constants::DW_LNE_end_sequence),
+ LineInstruction::SetAddress(address) => {
+ write!(f, "{} to {}", constants::DW_LNE_set_address, address)
+ }
+ LineInstruction::DefineFile(_) => write!(f, "{}", constants::DW_LNE_define_file),
+ LineInstruction::SetDiscriminator(discr) => {
+ write!(f, "{} to {}", constants::DW_LNE_set_discriminator, discr)
+ }
+ LineInstruction::UnknownExtended(opcode, _) => write!(f, "Unknown {}", opcode),
+ }
+ }
+}
+
+/// Deprecated. `OpcodesIter` has been renamed to `LineInstructions`.
+#[deprecated(note = "OpcodesIter has been renamed to LineInstructions, use that instead.")]
+pub type OpcodesIter<R> = LineInstructions<R>;
+
+/// An iterator yielding parsed instructions.
+///
+/// See
+/// [`LineProgramHeader::instructions`](./struct.LineProgramHeader.html#method.instructions)
+/// for more details.
+#[derive(Clone, Debug)]
+pub struct LineInstructions<R: Reader> {
+ input: R,
+}
+
+impl<R: Reader> LineInstructions<R> {
+ fn remove_trailing(&self, other: &LineInstructions<R>) -> Result<LineInstructions<R>> {
+ let offset = other.input.offset_from(&self.input);
+ let mut input = self.input.clone();
+ input.truncate(offset)?;
+ Ok(LineInstructions { input })
+ }
+}
+
+impl<R: Reader> LineInstructions<R> {
+ /// Advance the iterator and return the next instruction.
+ ///
+ /// Returns the newly parsed instruction as `Ok(Some(instruction))`. Returns
+ /// `Ok(None)` when iteration is complete and all instructions have already been
+ /// parsed and yielded. If an error occurs while parsing the next attribute,
+ /// then this error is returned as `Err(e)`, and all subsequent calls return
+ /// `Ok(None)`.
+ ///
+ /// Unfortunately, the `header` parameter means that this cannot be a
+ /// `FallibleIterator`.
+ #[allow(clippy::inline_always)]
+ #[inline(always)]
+ pub fn next_instruction(
+ &mut self,
+ header: &LineProgramHeader<R>,
+ ) -> Result<Option<LineInstruction<R>>> {
+ if self.input.is_empty() {
+ return Ok(None);
+ }
+
+ match LineInstruction::parse(header, &mut self.input) {
+ Ok(instruction) => Ok(Some(instruction)),
+ Err(e) => {
+ self.input.empty();
+ Err(e)
+ }
+ }
+ }
+}
+
+/// Deprecated. `LineNumberRow` has been renamed to `LineRow`.
+#[deprecated(note = "LineNumberRow has been renamed to LineRow, use that instead.")]
+pub type LineNumberRow = LineRow;
+
+/// A row in the line number program's resulting matrix.
+///
+/// Each row is a copy of the registers of the state machine, as defined in section 6.2.2.
+#[derive(Clone, Copy, Debug, PartialEq, Eq)]
+pub struct LineRow {
+ address: Wrapping<u64>,
+ op_index: Wrapping<u64>,
+ file: u64,
+ line: Wrapping<u64>,
+ column: u64,
+ is_stmt: bool,
+ basic_block: bool,
+ end_sequence: bool,
+ prologue_end: bool,
+ epilogue_begin: bool,
+ isa: u64,
+ discriminator: u64,
+}
+
+impl LineRow {
+ /// Create a line number row in the initial state for the given program.
+ pub fn new<R: Reader>(header: &LineProgramHeader<R>) -> Self {
+ LineRow {
+ // "At the beginning of each sequence within a line number program, the
+ // state of the registers is:" -- Section 6.2.2
+ address: Wrapping(0),
+ op_index: Wrapping(0),
+ file: 1,
+ line: Wrapping(1),
+ column: 0,
+ // "determined by default_is_stmt in the line number program header"
+ is_stmt: header.line_encoding.default_is_stmt,
+ basic_block: false,
+ end_sequence: false,
+ prologue_end: false,
+ epilogue_begin: false,
+ // "The isa value 0 specifies that the instruction set is the
+ // architecturally determined default instruction set. This may be fixed
+ // by the ABI, or it may be specified by other means, for example, by
+ // the object file description."
+ isa: 0,
+ discriminator: 0,
+ }
+ }
+
+ /// "The program-counter value corresponding to a machine instruction
+ /// generated by the compiler."
+ #[inline]
+ pub fn address(&self) -> u64 {
+ self.address.0
+ }
+
+ /// > An unsigned integer representing the index of an operation within a VLIW
+ /// > instruction. The index of the first operation is 0. For non-VLIW
+ /// > architectures, this register will always be 0.
+ /// >
+ /// > The address and op_index registers, taken together, form an operation
+ /// > pointer that can reference any individual operation with the
+ /// > instruction stream.
+ #[inline]
+ pub fn op_index(&self) -> u64 {
+ self.op_index.0
+ }
+
+ /// "An unsigned integer indicating the identity of the source file
+ /// corresponding to a machine instruction."
+ #[inline]
+ pub fn file_index(&self) -> u64 {
+ self.file
+ }
+
+ /// The source file corresponding to the current machine instruction.
+ #[inline]
+ pub fn file<'header, R: Reader>(
+ &self,
+ header: &'header LineProgramHeader<R>,
+ ) -> Option<&'header FileEntry<R>> {
+ header.file(self.file)
+ }
+
+ /// "An unsigned integer indicating a source line number. Lines are numbered
+ /// beginning at 1. The compiler may emit the value 0 in cases where an
+ /// instruction cannot be attributed to any source line."
+ /// Line number values of 0 are represented as `None`.
+ #[inline]
+ pub fn line(&self) -> Option<NonZeroU64> {
+ NonZeroU64::new(self.line.0)
+ }
+
+ /// "An unsigned integer indicating a column number within a source
+ /// line. Columns are numbered beginning at 1. The value 0 is reserved to
+ /// indicate that a statement begins at the “left edge” of the line."
+ #[inline]
+ pub fn column(&self) -> ColumnType {
+ NonZeroU64::new(self.column)
+ .map(ColumnType::Column)
+ .unwrap_or(ColumnType::LeftEdge)
+ }
+
+ /// "A boolean indicating that the current instruction is a recommended
+ /// breakpoint location. A recommended breakpoint location is intended to
+ /// “represent” a line, a statement and/or a semantically distinct subpart
+ /// of a statement."
+ #[inline]
+ pub fn is_stmt(&self) -> bool {
+ self.is_stmt
+ }
+
+ /// "A boolean indicating that the current instruction is the beginning of a
+ /// basic block."
+ #[inline]
+ pub fn basic_block(&self) -> bool {
+ self.basic_block
+ }
+
+ /// "A boolean indicating that the current address is that of the first byte
+ /// after the end of a sequence of target machine instructions. end_sequence
+ /// terminates a sequence of lines; therefore other information in the same
+ /// row is not meaningful."
+ #[inline]
+ pub fn end_sequence(&self) -> bool {
+ self.end_sequence
+ }
+
+ /// "A boolean indicating that the current address is one (of possibly many)
+ /// where execution should be suspended for an entry breakpoint of a
+ /// function."
+ #[inline]
+ pub fn prologue_end(&self) -> bool {
+ self.prologue_end
+ }
+
+ /// "A boolean indicating that the current address is one (of possibly many)
+ /// where execution should be suspended for an exit breakpoint of a
+ /// function."
+ #[inline]
+ pub fn epilogue_begin(&self) -> bool {
+ self.epilogue_begin
+ }
+
+ /// Tag for the current instruction set architecture.
+ ///
+ /// > An unsigned integer whose value encodes the applicable instruction set
+ /// > architecture for the current instruction.
+ /// >
+ /// > The encoding of instruction sets should be shared by all users of a
+ /// > given architecture. It is recommended that this encoding be defined by
+ /// > the ABI authoring committee for each architecture.
+ #[inline]
+ pub fn isa(&self) -> u64 {
+ self.isa
+ }
+
+ /// "An unsigned integer identifying the block to which the current
+ /// instruction belongs. Discriminator values are assigned arbitrarily by
+ /// the DWARF producer and serve to distinguish among multiple blocks that
+ /// may all be associated with the same source file, line, and column. Where
+ /// only one block exists for a given source position, the discriminator
+ /// value should be zero."
+ #[inline]
+ pub fn discriminator(&self) -> u64 {
+ self.discriminator
+ }
+
+ /// Execute the given instruction, and return true if a new row in the
+ /// line number matrix needs to be generated.
+ ///
+ /// Unknown opcodes are treated as no-ops.
+ #[inline]
+ pub fn execute<R, Program>(
+ &mut self,
+ instruction: LineInstruction<R>,
+ program: &mut Program,
+ ) -> bool
+ where
+ Program: LineProgram<R>,
+ R: Reader,
+ {
+ match instruction {
+ LineInstruction::Special(opcode) => {
+ self.exec_special_opcode(opcode, program.header());
+ true
+ }
+
+ LineInstruction::Copy => true,
+
+ LineInstruction::AdvancePc(operation_advance) => {
+ self.apply_operation_advance(operation_advance, program.header());
+ false
+ }
+
+ LineInstruction::AdvanceLine(line_increment) => {
+ self.apply_line_advance(line_increment);
+ false
+ }
+
+ LineInstruction::SetFile(file) => {
+ self.file = file;
+ false
+ }
+
+ LineInstruction::SetColumn(column) => {
+ self.column = column;
+ false
+ }
+
+ LineInstruction::NegateStatement => {
+ self.is_stmt = !self.is_stmt;
+ false
+ }
+
+ LineInstruction::SetBasicBlock => {
+ self.basic_block = true;
+ false
+ }
+
+ LineInstruction::ConstAddPc => {
+ let adjusted = self.adjust_opcode(255, program.header());
+ let operation_advance = adjusted / program.header().line_encoding.line_range;
+ self.apply_operation_advance(u64::from(operation_advance), program.header());
+ false
+ }
+
+ LineInstruction::FixedAddPc(operand) => {
+ self.address += Wrapping(u64::from(operand));
+ self.op_index.0 = 0;
+ false
+ }
+
+ LineInstruction::SetPrologueEnd => {
+ self.prologue_end = true;
+ false
+ }
+
+ LineInstruction::SetEpilogueBegin => {
+ self.epilogue_begin = true;
+ false
+ }
+
+ LineInstruction::SetIsa(isa) => {
+ self.isa = isa;
+ false
+ }
+
+ LineInstruction::EndSequence => {
+ self.end_sequence = true;
+ true
+ }
+
+ LineInstruction::SetAddress(address) => {
+ self.address.0 = address;
+ self.op_index.0 = 0;
+ false
+ }
+
+ LineInstruction::DefineFile(entry) => {
+ program.add_file(entry);
+ false
+ }
+
+ LineInstruction::SetDiscriminator(discriminator) => {
+ self.discriminator = discriminator;
+ false
+ }
+
+ // Compatibility with future opcodes.
+ LineInstruction::UnknownStandard0(_)
+ | LineInstruction::UnknownStandard1(_, _)
+ | LineInstruction::UnknownStandardN(_, _)
+ | LineInstruction::UnknownExtended(_, _) => false,
+ }
+ }
+
+ /// Perform any reset that was required after copying the previous row.
+ #[inline]
+ pub fn reset<R: Reader>(&mut self, header: &LineProgramHeader<R>) {
+ if self.end_sequence {
+ // Previous instruction was EndSequence, so reset everything
+ // as specified in Section 6.2.5.3.
+ *self = Self::new(header);
+ } else {
+ // Previous instruction was one of:
+ // - Special - specified in Section 6.2.5.1, steps 4-7
+ // - Copy - specified in Section 6.2.5.2
+ // The reset behaviour is the same in both cases.
+ self.discriminator = 0;
+ self.basic_block = false;
+ self.prologue_end = false;
+ self.epilogue_begin = false;
+ }
+ }
+
+ /// Step 1 of section 6.2.5.1
+ fn apply_line_advance(&mut self, line_increment: i64) {
+ if line_increment < 0 {
+ let decrement = -line_increment as u64;
+ if decrement <= self.line.0 {
+ self.line.0 -= decrement;
+ } else {
+ self.line.0 = 0;
+ }
+ } else {
+ self.line += Wrapping(line_increment as u64);
+ }
+ }
+
+ /// Step 2 of section 6.2.5.1
+ fn apply_operation_advance<R: Reader>(
+ &mut self,
+ operation_advance: u64,
+ header: &LineProgramHeader<R>,
+ ) {
+ let operation_advance = Wrapping(operation_advance);
+
+ let minimum_instruction_length = u64::from(header.line_encoding.minimum_instruction_length);
+ let minimum_instruction_length = Wrapping(minimum_instruction_length);
+
+ let maximum_operations_per_instruction =
+ u64::from(header.line_encoding.maximum_operations_per_instruction);
+ let maximum_operations_per_instruction = Wrapping(maximum_operations_per_instruction);
+
+ if maximum_operations_per_instruction.0 == 1 {
+ self.address += minimum_instruction_length * operation_advance;
+ self.op_index.0 = 0;
+ } else {
+ let op_index_with_advance = self.op_index + operation_advance;
+ self.address += minimum_instruction_length
+ * (op_index_with_advance / maximum_operations_per_instruction);
+ self.op_index = op_index_with_advance % maximum_operations_per_instruction;
+ }
+ }
+
+ #[inline]
+ fn adjust_opcode<R: Reader>(&self, opcode: u8, header: &LineProgramHeader<R>) -> u8 {
+ opcode - header.opcode_base
+ }
+
+ /// Section 6.2.5.1
+ fn exec_special_opcode<R: Reader>(&mut self, opcode: u8, header: &LineProgramHeader<R>) {
+ let adjusted_opcode = self.adjust_opcode(opcode, header);
+
+ let line_range = header.line_encoding.line_range;
+ let line_advance = adjusted_opcode % line_range;
+ let operation_advance = adjusted_opcode / line_range;
+
+ // Step 1
+ let line_base = i64::from(header.line_encoding.line_base);
+ self.apply_line_advance(line_base + i64::from(line_advance));
+
+ // Step 2
+ self.apply_operation_advance(u64::from(operation_advance), header);
+ }
+}
+
+/// The type of column that a row is referring to.
+#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
+pub enum ColumnType {
+ /// The `LeftEdge` means that the statement begins at the start of the new
+ /// line.
+ LeftEdge,
+ /// A column number, whose range begins at 1.
+ Column(NonZeroU64),
+}
+
+/// Deprecated. `LineNumberSequence` has been renamed to `LineSequence`.
+#[deprecated(note = "LineNumberSequence has been renamed to LineSequence, use that instead.")]
+pub type LineNumberSequence<R> = LineSequence<R>;
+
+/// A sequence within a line number program. A sequence, as defined in section
+/// 6.2.5 of the standard, is a linear subset of a line number program within
+/// which addresses are monotonically increasing.
+#[derive(Clone, Debug)]
+pub struct LineSequence<R: Reader> {
+ /// The first address that is covered by this sequence within the line number
+ /// program.
+ pub start: u64,
+ /// The first address that is *not* covered by this sequence within the line
+ /// number program.
+ pub end: u64,
+ instructions: LineInstructions<R>,
+}
+
+/// Deprecated. `LineNumberProgramHeader` has been renamed to `LineProgramHeader`.
+#[deprecated(
+ note = "LineNumberProgramHeader has been renamed to LineProgramHeader, use that instead."
+)]
+pub type LineNumberProgramHeader<R, Offset> = LineProgramHeader<R, Offset>;
+
+/// A header for a line number program in the `.debug_line` section, as defined
+/// in section 6.2.4 of the standard.
+#[derive(Clone, Debug, Eq, PartialEq)]
+pub struct LineProgramHeader<R, Offset = <R as Reader>::Offset>
+where
+ R: Reader<Offset = Offset>,
+ Offset: ReaderOffset,
+{
+ encoding: Encoding,
+ offset: DebugLineOffset<Offset>,
+ unit_length: Offset,
+
+ header_length: Offset,
+
+ line_encoding: LineEncoding,
+
+ /// "The number assigned to the first special opcode."
+ opcode_base: u8,
+
+ /// "This array specifies the number of LEB128 operands for each of the
+ /// standard opcodes. The first element of the array corresponds to the
+ /// opcode whose value is 1, and the last element corresponds to the opcode
+ /// whose value is `opcode_base - 1`."
+ standard_opcode_lengths: R,
+
+ /// "A sequence of directory entry format descriptions."
+ directory_entry_format: Vec<FileEntryFormat>,
+
+ /// > Entries in this sequence describe each path that was searched for
+ /// > included source files in this compilation. (The paths include those
+ /// > directories specified explicitly by the user for the compiler to search
+ /// > and those the compiler searches without explicit direction.) Each path
+ /// > entry is either a full path name or is relative to the current directory
+ /// > of the compilation.
+ /// >
+ /// > The last entry is followed by a single null byte.
+ include_directories: Vec<AttributeValue<R, Offset>>,
+
+ /// "A sequence of file entry format descriptions."
+ file_name_entry_format: Vec<FileEntryFormat>,
+
+ /// "Entries in this sequence describe source files that contribute to the
+ /// line number information for this compilation unit or is used in other
+ /// contexts."
+ file_names: Vec<FileEntry<R, Offset>>,
+
+ /// The encoded line program instructions.
+ program_buf: R,
+
+ /// The current directory of the compilation.
+ comp_dir: Option<R>,
+
+ /// The primary source file.
+ comp_file: Option<FileEntry<R, Offset>>,
+}
+
+impl<R, Offset> LineProgramHeader<R, Offset>
+where
+ R: Reader<Offset = Offset>,
+ Offset: ReaderOffset,
+{
+ /// Return the offset of the line number program header in the `.debug_line` section.
+ pub fn offset(&self) -> DebugLineOffset<R::Offset> {
+ self.offset
+ }
+
+ /// Return the length of the line number program and header, not including
+ /// the length of the encoded length itself.
+ pub fn unit_length(&self) -> R::Offset {
+ self.unit_length
+ }
+
+ /// Return the encoding parameters for this header's line program.
+ pub fn encoding(&self) -> Encoding {
+ self.encoding
+ }
+
+ /// Get the version of this header's line program.
+ pub fn version(&self) -> u16 {
+ self.encoding.version
+ }
+
+ /// Get the length of the encoded line number program header, not including
+ /// the length of the encoded length itself.
+ pub fn header_length(&self) -> R::Offset {
+ self.header_length
+ }
+
+ /// Get the size in bytes of a target machine address.
+ pub fn address_size(&self) -> u8 {
+ self.encoding.address_size
+ }
+
+ /// Whether this line program is encoded in 64- or 32-bit DWARF.
+ pub fn format(&self) -> Format {
+ self.encoding.format
+ }
+
+ /// Get the line encoding parameters for this header's line program.
+ pub fn line_encoding(&self) -> LineEncoding {
+ self.line_encoding
+ }
+
+ /// Get the minimum instruction length any instruction in this header's line
+ /// program may have.
+ pub fn minimum_instruction_length(&self) -> u8 {
+ self.line_encoding.minimum_instruction_length
+ }
+
+ /// Get the maximum number of operations each instruction in this header's
+ /// line program may have.
+ pub fn maximum_operations_per_instruction(&self) -> u8 {
+ self.line_encoding.maximum_operations_per_instruction
+ }
+
+ /// Get the default value of the `is_stmt` register for this header's line
+ /// program.
+ pub fn default_is_stmt(&self) -> bool {
+ self.line_encoding.default_is_stmt
+ }
+
+ /// Get the line base for this header's line program.
+ pub fn line_base(&self) -> i8 {
+ self.line_encoding.line_base
+ }
+
+ /// Get the line range for this header's line program.
+ pub fn line_range(&self) -> u8 {
+ self.line_encoding.line_range
+ }
+
+ /// Get opcode base for this header's line program.
+ pub fn opcode_base(&self) -> u8 {
+ self.opcode_base
+ }
+
+ /// An array of `u8` that specifies the number of LEB128 operands for
+ /// each of the standard opcodes.
+ pub fn standard_opcode_lengths(&self) -> &R {
+ &self.standard_opcode_lengths
+ }
+
+ /// Get the format of a directory entry.
+ pub fn directory_entry_format(&self) -> &[FileEntryFormat] {
+ &self.directory_entry_format[..]
+ }
+
+ /// Get the set of include directories for this header's line program.
+ ///
+ /// For DWARF version <= 4, the compilation's current directory is not included
+ /// in the return value, but is implicitly considered to be in the set per spec.
+ pub fn include_directories(&self) -> &[AttributeValue<R, Offset>] {
+ &self.include_directories[..]
+ }
+
+ /// The include directory with the given directory index.
+ ///
+ /// A directory index of 0 corresponds to the compilation unit directory.
+ pub fn directory(&self, directory: u64) -> Option<AttributeValue<R, Offset>> {
+ if self.encoding.version <= 4 {
+ if directory == 0 {
+ self.comp_dir.clone().map(AttributeValue::String)
+ } else {
+ let directory = directory as usize - 1;
+ self.include_directories.get(directory).cloned()
+ }
+ } else {
+ self.include_directories.get(directory as usize).cloned()
+ }
+ }
+
+ /// Get the format of a file name entry.
+ pub fn file_name_entry_format(&self) -> &[FileEntryFormat] {
+ &self.file_name_entry_format[..]
+ }
+
+ /// Return true if the file entries may have valid timestamps.
+ ///
+ /// Only returns false if we definitely know that all timestamp fields
+ /// are invalid.
+ pub fn file_has_timestamp(&self) -> bool {
+ self.encoding.version <= 4
+ || self
+ .file_name_entry_format
+ .iter()
+ .any(|x| x.content_type == constants::DW_LNCT_timestamp)
+ }
+
+ /// Return true if the file entries may have valid sizes.
+ ///
+ /// Only returns false if we definitely know that all size fields
+ /// are invalid.
+ pub fn file_has_size(&self) -> bool {
+ self.encoding.version <= 4
+ || self
+ .file_name_entry_format
+ .iter()
+ .any(|x| x.content_type == constants::DW_LNCT_size)
+ }
+
+ /// Return true if the file name entry format contains an MD5 field.
+ pub fn file_has_md5(&self) -> bool {
+ self.file_name_entry_format
+ .iter()
+ .any(|x| x.content_type == constants::DW_LNCT_MD5)
+ }
+
+ /// Get the list of source files that appear in this header's line program.
+ pub fn file_names(&self) -> &[FileEntry<R, Offset>] {
+ &self.file_names[..]
+ }
+
+ /// The source file with the given file index.
+ ///
+ /// A file index of 0 corresponds to the compilation unit file.
+ /// Note that a file index of 0 is invalid for DWARF version <= 4,
+ /// but we support it anyway.
+ pub fn file(&self, file: u64) -> Option<&FileEntry<R, Offset>> {
+ if self.encoding.version <= 4 {
+ if file == 0 {
+ self.comp_file.as_ref()
+ } else {
+ let file = file as usize - 1;
+ self.file_names.get(file)
+ }
+ } else {
+ self.file_names.get(file as usize)
+ }
+ }
+
+ /// Get the raw, un-parsed `EndianSlice` containing this header's line number
+ /// program.
+ ///
+ /// ```
+ /// # fn foo() {
+ /// use gimli::{LineProgramHeader, EndianSlice, NativeEndian};
+ ///
+ /// fn get_line_number_program_header<'a>() -> LineProgramHeader<EndianSlice<'a, NativeEndian>> {
+ /// // Get a line number program header from some offset in a
+ /// // `.debug_line` section...
+ /// # unimplemented!()
+ /// }
+ ///
+ /// let header = get_line_number_program_header();
+ /// let raw_program = header.raw_program_buf();
+ /// println!("The length of the raw program in bytes is {}", raw_program.len());
+ /// # }
+ /// ```
+ pub fn raw_program_buf(&self) -> R {
+ self.program_buf.clone()
+ }
+
+ /// Iterate over the instructions in this header's line number program, parsing
+ /// them as we go.
+ pub fn instructions(&self) -> LineInstructions<R> {
+ LineInstructions {
+ input: self.program_buf.clone(),
+ }
+ }
+
+ fn parse(
+ input: &mut R,
+ offset: DebugLineOffset<Offset>,
+ mut address_size: u8,
+ mut comp_dir: Option<R>,
+ comp_name: Option<R>,
+ ) -> Result<LineProgramHeader<R, Offset>> {
+ let (unit_length, format) = input.read_initial_length()?;
+ let rest = &mut input.split(unit_length)?;
+
+ let version = rest.read_u16()?;
+ if version < 2 || version > 5 {
+ return Err(Error::UnknownVersion(u64::from(version)));
+ }
+
+ if version >= 5 {
+ address_size = rest.read_u8()?;
+ let segment_selector_size = rest.read_u8()?;
+ if segment_selector_size != 0 {
+ return Err(Error::UnsupportedSegmentSize);
+ }
+ }
+
+ let encoding = Encoding {
+ format,
+ version,
+ address_size,
+ };
+
+ let header_length = rest.read_length(format)?;
+
+ let mut program_buf = rest.clone();
+ program_buf.skip(header_length)?;
+ rest.truncate(header_length)?;
+
+ let minimum_instruction_length = rest.read_u8()?;
+ if minimum_instruction_length == 0 {
+ return Err(Error::MinimumInstructionLengthZero);
+ }
+
+ // This field did not exist before DWARF 4, but is specified to be 1 for
+ // non-VLIW architectures, which makes it a no-op.
+ let maximum_operations_per_instruction = if version >= 4 { rest.read_u8()? } else { 1 };
+ if maximum_operations_per_instruction == 0 {
+ return Err(Error::MaximumOperationsPerInstructionZero);
+ }
+
+ let default_is_stmt = rest.read_u8()? != 0;
+ let line_base = rest.read_i8()?;
+ let line_range = rest.read_u8()?;
+ if line_range == 0 {
+ return Err(Error::LineRangeZero);
+ }
+ let line_encoding = LineEncoding {
+ minimum_instruction_length,
+ maximum_operations_per_instruction,
+ default_is_stmt,
+ line_base,
+ line_range,
+ };
+
+ let opcode_base = rest.read_u8()?;
+ if opcode_base == 0 {
+ return Err(Error::OpcodeBaseZero);
+ }
+
+ let standard_opcode_count = R::Offset::from_u8(opcode_base - 1);
+ let standard_opcode_lengths = rest.split(standard_opcode_count)?;
+
+ let directory_entry_format;
+ let mut include_directories = Vec::new();
+ if version <= 4 {
+ directory_entry_format = Vec::new();
+ loop {
+ let directory = rest.read_null_terminated_slice()?;
+ if directory.is_empty() {
+ break;
+ }
+ include_directories.push(AttributeValue::String(directory));
+ }
+ } else {
+ comp_dir = None;
+ directory_entry_format = FileEntryFormat::parse(rest)?;
+ let count = rest.read_uleb128()?;
+ for _ in 0..count {
+ include_directories.push(parse_directory_v5(
+ rest,
+ encoding,
+ &directory_entry_format,
+ )?);
+ }
+ }
+
+ let comp_file;
+ let file_name_entry_format;
+ let mut file_names = Vec::new();
+ if version <= 4 {
+ comp_file = comp_name.map(|name| FileEntry {
+ path_name: AttributeValue::String(name),
+ directory_index: 0,
+ timestamp: 0,
+ size: 0,
+ md5: [0; 16],
+ });
+
+ file_name_entry_format = Vec::new();
+ loop {
+ let path_name = rest.read_null_terminated_slice()?;
+ if path_name.is_empty() {
+ break;
+ }
+ file_names.push(FileEntry::parse(rest, path_name)?);
+ }
+ } else {
+ comp_file = None;
+ file_name_entry_format = FileEntryFormat::parse(rest)?;
+ let count = rest.read_uleb128()?;
+ for _ in 0..count {
+ file_names.push(parse_file_v5(rest, encoding, &file_name_entry_format)?);
+ }
+ }
+
+ let header = LineProgramHeader {
+ encoding,
+ offset,
+ unit_length,
+ header_length,
+ line_encoding,
+ opcode_base,
+ standard_opcode_lengths,
+ directory_entry_format,
+ include_directories,
+ file_name_entry_format,
+ file_names,
+ program_buf,
+ comp_dir,
+ comp_file,
+ };
+ Ok(header)
+ }
+}
+
+/// Deprecated. `IncompleteLineNumberProgram` has been renamed to `IncompleteLineProgram`.
+#[deprecated(
+ note = "IncompleteLineNumberProgram has been renamed to IncompleteLineProgram, use that instead."
+)]
+pub type IncompleteLineNumberProgram<R, Offset> = IncompleteLineProgram<R, Offset>;
+
+/// A line number program that has not been run to completion.
+#[derive(Clone, Debug, Eq, PartialEq)]
+pub struct IncompleteLineProgram<R, Offset = <R as Reader>::Offset>
+where
+ R: Reader<Offset = Offset>,
+ Offset: ReaderOffset,
+{
+ header: LineProgramHeader<R, Offset>,
+}
+
+impl<R, Offset> IncompleteLineProgram<R, Offset>
+where
+ R: Reader<Offset = Offset>,
+ Offset: ReaderOffset,
+{
+ /// Retrieve the `LineProgramHeader` for this program.
+ pub fn header(&self) -> &LineProgramHeader<R, Offset> {
+ &self.header
+ }
+
+ /// Construct a new `LineRows` for executing this program to iterate
+ /// over rows in the line information matrix.
+ pub fn rows(self) -> OneShotLineRows<R, Offset> {
+ OneShotLineRows::new(self)
+ }
+
+ /// Execute the line number program, completing the `IncompleteLineProgram`
+ /// into a `CompleteLineProgram` and producing an array of sequences within
+ /// the line number program that can later be used with
+ /// `CompleteLineProgram::resume_from`.
+ ///
+ /// ```
+ /// # fn foo() {
+ /// use gimli::{IncompleteLineProgram, EndianSlice, NativeEndian};
+ ///
+ /// fn get_line_number_program<'a>() -> IncompleteLineProgram<EndianSlice<'a, NativeEndian>> {
+ /// // Get a line number program from some offset in a
+ /// // `.debug_line` section...
+ /// # unimplemented!()
+ /// }
+ ///
+ /// let program = get_line_number_program();
+ /// let (program, sequences) = program.sequences().unwrap();
+ /// println!("There are {} sequences in this line number program", sequences.len());
+ /// # }
+ /// ```
+ #[allow(clippy::type_complexity)]
+ pub fn sequences(self) -> Result<(CompleteLineProgram<R, Offset>, Vec<LineSequence<R>>)> {
+ let mut sequences = Vec::new();
+ let mut rows = self.rows();
+ let mut instructions = rows.instructions.clone();
+ let mut sequence_start_addr = None;
+ loop {
+ let sequence_end_addr;
+ if rows.next_row()?.is_none() {
+ break;
+ }
+
+ let row = &rows.row;
+ if row.end_sequence() {
+ sequence_end_addr = row.address();
+ } else if sequence_start_addr.is_none() {
+ sequence_start_addr = Some(row.address());
+ continue;
+ } else {
+ continue;
+ }
+
+ // We just finished a sequence.
+ sequences.push(LineSequence {
+ // In theory one could have multiple DW_LNE_end_sequence instructions
+ // in a row.
+ start: sequence_start_addr.unwrap_or(0),
+ end: sequence_end_addr,
+ instructions: instructions.remove_trailing(&rows.instructions)?,
+ });
+ sequence_start_addr = None;
+ instructions = rows.instructions.clone();
+ }
+
+ let program = CompleteLineProgram {
+ header: rows.program.header,
+ };
+ Ok((program, sequences))
+ }
+}
+
+/// Deprecated. `CompleteLineNumberProgram` has been renamed to `CompleteLineProgram`.
+#[deprecated(
+ note = "CompleteLineNumberProgram has been renamed to CompleteLineProgram, use that instead."
+)]
+pub type CompleteLineNumberProgram<R, Offset> = CompleteLineProgram<R, Offset>;
+
+/// A line number program that has previously been run to completion.
+#[derive(Clone, Debug, Eq, PartialEq)]
+pub struct CompleteLineProgram<R, Offset = <R as Reader>::Offset>
+where
+ R: Reader<Offset = Offset>,
+ Offset: ReaderOffset,
+{
+ header: LineProgramHeader<R, Offset>,
+}
+
+impl<R, Offset> CompleteLineProgram<R, Offset>
+where
+ R: Reader<Offset = Offset>,
+ Offset: ReaderOffset,
+{
+ /// Retrieve the `LineProgramHeader` for this program.
+ pub fn header(&self) -> &LineProgramHeader<R, Offset> {
+ &self.header
+ }
+
+ /// Construct a new `LineRows` for executing the subset of the line
+ /// number program identified by 'sequence' and generating the line information
+ /// matrix.
+ ///
+ /// ```
+ /// # fn foo() {
+ /// use gimli::{IncompleteLineProgram, EndianSlice, NativeEndian};
+ ///
+ /// fn get_line_number_program<'a>() -> IncompleteLineProgram<EndianSlice<'a, NativeEndian>> {
+ /// // Get a line number program from some offset in a
+ /// // `.debug_line` section...
+ /// # unimplemented!()
+ /// }
+ ///
+ /// let program = get_line_number_program();
+ /// let (program, sequences) = program.sequences().unwrap();
+ /// for sequence in &sequences {
+ /// let mut sm = program.resume_from(sequence);
+ /// }
+ /// # }
+ /// ```
+ pub fn resume_from<'program>(
+ &'program self,
+ sequence: &LineSequence<R>,
+ ) -> ResumedLineRows<'program, R, Offset> {
+ ResumedLineRows::resume(self, sequence)
+ }
+}
+
+/// An entry in the `LineProgramHeader`'s `file_names` set.
+#[derive(Copy, Clone, Debug, PartialEq, Eq)]
+pub struct FileEntry<R, Offset = <R as Reader>::Offset>
+where
+ R: Reader<Offset = Offset>,
+ Offset: ReaderOffset,
+{
+ path_name: AttributeValue<R, Offset>,
+ directory_index: u64,
+ timestamp: u64,
+ size: u64,
+ md5: [u8; 16],
+}
+
+impl<R, Offset> FileEntry<R, Offset>
+where
+ R: Reader<Offset = Offset>,
+ Offset: ReaderOffset,
+{
+ // version 2-4
+ fn parse(input: &mut R, path_name: R) -> Result<FileEntry<R, Offset>> {
+ let directory_index = input.read_uleb128()?;
+ let timestamp = input.read_uleb128()?;
+ let size = input.read_uleb128()?;
+
+ let entry = FileEntry {
+ path_name: AttributeValue::String(path_name),
+ directory_index,
+ timestamp,
+ size,
+ md5: [0; 16],
+ };
+
+ Ok(entry)
+ }
+
+ /// > A slice containing the full or relative path name of
+ /// > a source file. If the entry contains a file name or a relative path
+ /// > name, the file is located relative to either the compilation directory
+ /// > (as specified by the DW_AT_comp_dir attribute given in the compilation
+ /// > unit) or one of the directories in the include_directories section.
+ pub fn path_name(&self) -> AttributeValue<R, Offset> {
+ self.path_name.clone()
+ }
+
+ /// > An unsigned LEB128 number representing the directory index of the
+ /// > directory in which the file was found.
+ /// >
+ /// > ...
+ /// >
+ /// > The directory index represents an entry in the include_directories
+ /// > section of the line number program header. The index is 0 if the file
+ /// > was found in the current directory of the compilation, 1 if it was found
+ /// > in the first directory in the include_directories section, and so
+ /// > on. The directory index is ignored for file names that represent full
+ /// > path names.
+ pub fn directory_index(&self) -> u64 {
+ self.directory_index
+ }
+
+ /// Get this file's directory.
+ ///
+ /// A directory index of 0 corresponds to the compilation unit directory.
+ pub fn directory(&self, header: &LineProgramHeader<R>) -> Option<AttributeValue<R, Offset>> {
+ header.directory(self.directory_index)
+ }
+
+ /// The implementation-defined time of last modification of the file,
+ /// or 0 if not available.
+ pub fn timestamp(&self) -> u64 {
+ self.timestamp
+ }
+
+ /// "An unsigned LEB128 number representing the time of last modification of
+ /// the file, or 0 if not available."
+ // Terminology changed in DWARF version 5.
+ #[doc(hidden)]
+ pub fn last_modification(&self) -> u64 {
+ self.timestamp
+ }
+
+ /// The size of the file in bytes, or 0 if not available.
+ pub fn size(&self) -> u64 {
+ self.size
+ }
+
+ /// "An unsigned LEB128 number representing the length in bytes of the file,
+ /// or 0 if not available."
+ // Terminology changed in DWARF version 5.
+ #[doc(hidden)]
+ pub fn length(&self) -> u64 {
+ self.size
+ }
+
+ /// A 16-byte MD5 digest of the file contents.
+ ///
+ /// Only valid if `LineProgramHeader::file_has_md5` returns `true`.
+ pub fn md5(&self) -> &[u8; 16] {
+ &self.md5
+ }
+}
+
+/// The format of a component of an include directory or file name entry.
+#[derive(Copy, Clone, Debug, PartialEq, Eq)]
+pub struct FileEntryFormat {
+ /// The type of information that is represented by the component.
+ pub content_type: constants::DwLnct,
+
+ /// The encoding form of the component value.
+ pub form: constants::DwForm,
+}
+
+impl FileEntryFormat {
+ fn parse<R: Reader>(input: &mut R) -> Result<Vec<FileEntryFormat>> {
+ let format_count = input.read_u8()? as usize;
+ let mut format = Vec::with_capacity(format_count);
+ let mut path_count = 0;
+ for _ in 0..format_count {
+ let content_type = input.read_uleb128()?;
+ let content_type = if content_type > u64::from(u16::max_value()) {
+ constants::DwLnct(u16::max_value())
+ } else {
+ constants::DwLnct(content_type as u16)
+ };
+ if content_type == constants::DW_LNCT_path {
+ path_count += 1;
+ }
+
+ let form = constants::DwForm(input.read_uleb128_u16()?);
+
+ format.push(FileEntryFormat { content_type, form });
+ }
+ if path_count != 1 {
+ return Err(Error::MissingFileEntryFormatPath);
+ }
+ Ok(format)
+ }
+}
+
+fn parse_directory_v5<R: Reader>(
+ input: &mut R,
+ encoding: Encoding,
+ formats: &[FileEntryFormat],
+) -> Result<AttributeValue<R>> {
+ let mut path_name = None;
+
+ for format in formats {
+ let value = parse_attribute(input, encoding, format.form)?;
+ if format.content_type == constants::DW_LNCT_path {
+ path_name = Some(value);
+ }
+ }
+
+ Ok(path_name.unwrap())
+}
+
+fn parse_file_v5<R: Reader>(
+ input: &mut R,
+ encoding: Encoding,
+ formats: &[FileEntryFormat],
+) -> Result<FileEntry<R>> {
+ let mut path_name = None;
+ let mut directory_index = 0;
+ let mut timestamp = 0;
+ let mut size = 0;
+ let mut md5 = [0; 16];
+
+ for format in formats {
+ let value = parse_attribute(input, encoding, format.form)?;
+ match format.content_type {
+ constants::DW_LNCT_path => path_name = Some(value),
+ constants::DW_LNCT_directory_index => {
+ if let Some(value) = value.udata_value() {
+ directory_index = value;
+ }
+ }
+ constants::DW_LNCT_timestamp => {
+ if let Some(value) = value.udata_value() {
+ timestamp = value;
+ }
+ }
+ constants::DW_LNCT_size => {
+ if let Some(value) = value.udata_value() {
+ size = value;
+ }
+ }
+ constants::DW_LNCT_MD5 => {
+ if let AttributeValue::Block(mut value) = value {
+ if value.len().into_u64() == 16 {
+ md5 = value.read_u8_array()?;
+ }
+ }
+ }
+ // Ignore unknown content types.
+ _ => {}
+ }
+ }
+
+ Ok(FileEntry {
+ path_name: path_name.unwrap(),
+ directory_index,
+ timestamp,
+ size,
+ md5,
+ })
+}
+
+// TODO: this should be shared with unit::parse_attribute(), but that is hard to do.
+fn parse_attribute<R: Reader>(
+ input: &mut R,
+ encoding: Encoding,
+ form: constants::DwForm,
+) -> Result<AttributeValue<R>> {
+ Ok(match form {
+ constants::DW_FORM_block1 => {
+ let len = input.read_u8().map(R::Offset::from_u8)?;
+ let block = input.split(len)?;
+ AttributeValue::Block(block)
+ }
+ constants::DW_FORM_block2 => {
+ let len = input.read_u16().map(R::Offset::from_u16)?;
+ let block = input.split(len)?;
+ AttributeValue::Block(block)
+ }
+ constants::DW_FORM_block4 => {
+ let len = input.read_u32().map(R::Offset::from_u32)?;
+ let block = input.split(len)?;
+ AttributeValue::Block(block)
+ }
+ constants::DW_FORM_block => {
+ let len = input.read_uleb128().and_then(R::Offset::from_u64)?;
+ let block = input.split(len)?;
+ AttributeValue::Block(block)
+ }
+ constants::DW_FORM_data1 => {
+ let data = input.read_u8()?;
+ AttributeValue::Data1(data)
+ }
+ constants::DW_FORM_data2 => {
+ let data = input.read_u16()?;
+ AttributeValue::Data2(data)
+ }
+ constants::DW_FORM_data4 => {
+ let data = input.read_u32()?;
+ AttributeValue::Data4(data)
+ }
+ constants::DW_FORM_data8 => {
+ let data = input.read_u64()?;
+ AttributeValue::Data8(data)
+ }
+ constants::DW_FORM_data16 => {
+ let block = input.split(R::Offset::from_u8(16))?;
+ AttributeValue::Block(block)
+ }
+ constants::DW_FORM_udata => {
+ let data = input.read_uleb128()?;
+ AttributeValue::Udata(data)
+ }
+ constants::DW_FORM_sdata => {
+ let data = input.read_sleb128()?;
+ AttributeValue::Sdata(data)
+ }
+ constants::DW_FORM_flag => {
+ let present = input.read_u8()?;
+ AttributeValue::Flag(present != 0)
+ }
+ constants::DW_FORM_sec_offset => {
+ let offset = input.read_offset(encoding.format)?;
+ AttributeValue::SecOffset(offset)
+ }
+ constants::DW_FORM_string => {
+ let string = input.read_null_terminated_slice()?;
+ AttributeValue::String(string)
+ }
+ constants::DW_FORM_strp => {
+ let offset = input.read_offset(encoding.format)?;
+ AttributeValue::DebugStrRef(DebugStrOffset(offset))
+ }
+ constants::DW_FORM_strp_sup | constants::DW_FORM_GNU_strp_alt => {
+ let offset = input.read_offset(encoding.format)?;
+ AttributeValue::DebugStrRefSup(DebugStrOffset(offset))
+ }
+ constants::DW_FORM_line_strp => {
+ let offset = input.read_offset(encoding.format)?;
+ AttributeValue::DebugLineStrRef(DebugLineStrOffset(offset))
+ }
+ constants::DW_FORM_strx | constants::DW_FORM_GNU_str_index => {
+ let index = input.read_uleb128().and_then(R::Offset::from_u64)?;
+ AttributeValue::DebugStrOffsetsIndex(DebugStrOffsetsIndex(index))
+ }
+ constants::DW_FORM_strx1 => {
+ let index = input.read_u8().map(R::Offset::from_u8)?;
+ AttributeValue::DebugStrOffsetsIndex(DebugStrOffsetsIndex(index))
+ }
+ constants::DW_FORM_strx2 => {
+ let index = input.read_u16().map(R::Offset::from_u16)?;
+ AttributeValue::DebugStrOffsetsIndex(DebugStrOffsetsIndex(index))
+ }
+ constants::DW_FORM_strx3 => {
+ let index = input.read_uint(3).and_then(R::Offset::from_u64)?;
+ AttributeValue::DebugStrOffsetsIndex(DebugStrOffsetsIndex(index))
+ }
+ constants::DW_FORM_strx4 => {
+ let index = input.read_u32().map(R::Offset::from_u32)?;
+ AttributeValue::DebugStrOffsetsIndex(DebugStrOffsetsIndex(index))
+ }
+ _ => {
+ return Err(Error::UnknownForm);
+ }
+ })
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+ use crate::constants;
+ use crate::endianity::LittleEndian;
+ use crate::read::{EndianSlice, Error};
+ use crate::test_util::GimliSectionMethods;
+ use core::u64;
+ use core::u8;
+ use test_assembler::{Endian, Label, LabelMaker, Section};
+
+ #[test]
+ fn test_parse_debug_line_32_ok() {
+ #[rustfmt::skip]
+ let buf = [
+ // 32-bit length = 62.
+ 0x3e, 0x00, 0x00, 0x00,
+ // Version.
+ 0x04, 0x00,
+ // Header length = 40.
+ 0x28, 0x00, 0x00, 0x00,
+ // Minimum instruction length.
+ 0x01,
+ // Maximum operations per byte.
+ 0x01,
+ // Default is_stmt.
+ 0x01,
+ // Line base.
+ 0x00,
+ // Line range.
+ 0x01,
+ // Opcode base.
+ 0x03,
+ // Standard opcode lengths for opcodes 1 .. opcode base - 1.
+ 0x01, 0x02,
+ // Include directories = '/', 'i', 'n', 'c', '\0', '/', 'i', 'n', 'c', '2', '\0', '\0'
+ 0x2f, 0x69, 0x6e, 0x63, 0x00, 0x2f, 0x69, 0x6e, 0x63, 0x32, 0x00, 0x00,
+ // File names
+ // foo.rs
+ 0x66, 0x6f, 0x6f, 0x2e, 0x72, 0x73, 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ // bar.h
+ 0x62, 0x61, 0x72, 0x2e, 0x68, 0x00,
+ 0x01,
+ 0x00,
+ 0x00,
+ // End file names.
+ 0x00,
+
+ // Dummy line program data.
+ 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+
+ // Dummy next line program.
+ 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+ ];
+
+ let rest = &mut EndianSlice::new(&buf, LittleEndian);
+ let comp_dir = EndianSlice::new(b"/comp_dir", LittleEndian);
+ let comp_name = EndianSlice::new(b"/comp_name", LittleEndian);
+
+ let header =
+ LineProgramHeader::parse(rest, DebugLineOffset(0), 4, Some(comp_dir), Some(comp_name))
+ .expect("should parse header ok");
+
+ assert_eq!(
+ *rest,
+ EndianSlice::new(&buf[buf.len() - 16..], LittleEndian)
+ );
+
+ assert_eq!(header.offset, DebugLineOffset(0));
+ assert_eq!(header.version(), 4);
+ assert_eq!(header.minimum_instruction_length(), 1);
+ assert_eq!(header.maximum_operations_per_instruction(), 1);
+ assert_eq!(header.default_is_stmt(), true);
+ assert_eq!(header.line_base(), 0);
+ assert_eq!(header.line_range(), 1);
+ assert_eq!(header.opcode_base(), 3);
+ assert_eq!(header.directory(0), Some(AttributeValue::String(comp_dir)));
+ assert_eq!(
+ header.file(0).unwrap().path_name,
+ AttributeValue::String(comp_name)
+ );
+
+ let expected_lengths = [1, 2];
+ assert_eq!(header.standard_opcode_lengths().slice(), &expected_lengths);
+
+ let expected_include_directories = [
+ AttributeValue::String(EndianSlice::new(b"/inc", LittleEndian)),
+ AttributeValue::String(EndianSlice::new(b"/inc2", LittleEndian)),
+ ];
+ assert_eq!(header.include_directories(), &expected_include_directories);
+
+ let expected_file_names = [
+ FileEntry {
+ path_name: AttributeValue::String(EndianSlice::new(b"foo.rs", LittleEndian)),
+ directory_index: 0,
+ timestamp: 0,
+ size: 0,
+ md5: [0; 16],
+ },
+ FileEntry {
+ path_name: AttributeValue::String(EndianSlice::new(b"bar.h", LittleEndian)),
+ directory_index: 1,
+ timestamp: 0,
+ size: 0,
+ md5: [0; 16],
+ },
+ ];
+ assert_eq!(&*header.file_names(), &expected_file_names);
+ }
+
+ #[test]
+ fn test_parse_debug_line_header_length_too_short() {
+ #[rustfmt::skip]
+ let buf = [
+ // 32-bit length = 62.
+ 0x3e, 0x00, 0x00, 0x00,
+ // Version.
+ 0x04, 0x00,
+ // Header length = 20. TOO SHORT!!!
+ 0x15, 0x00, 0x00, 0x00,
+ // Minimum instruction length.
+ 0x01,
+ // Maximum operations per byte.
+ 0x01,
+ // Default is_stmt.
+ 0x01,
+ // Line base.
+ 0x00,
+ // Line range.
+ 0x01,
+ // Opcode base.
+ 0x03,
+ // Standard opcode lengths for opcodes 1 .. opcode base - 1.
+ 0x01, 0x02,
+ // Include directories = '/', 'i', 'n', 'c', '\0', '/', 'i', 'n', 'c', '2', '\0', '\0'
+ 0x2f, 0x69, 0x6e, 0x63, 0x00, 0x2f, 0x69, 0x6e, 0x63, 0x32, 0x00, 0x00,
+ // File names
+ // foo.rs
+ 0x66, 0x6f, 0x6f, 0x2e, 0x72, 0x73, 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ // bar.h
+ 0x62, 0x61, 0x72, 0x2e, 0x68, 0x00,
+ 0x01,
+ 0x00,
+ 0x00,
+ // End file names.
+ 0x00,
+
+ // Dummy line program data.
+ 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+
+ // Dummy next line program.
+ 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+ ];
+
+ let input = &mut EndianSlice::new(&buf, LittleEndian);
+
+ match LineProgramHeader::parse(input, DebugLineOffset(0), 4, None, None) {
+ Err(Error::UnexpectedEof(_)) => return,
+ otherwise => panic!("Unexpected result: {:?}", otherwise),
+ }
+ }
+
+ #[test]
+ fn test_parse_debug_line_unit_length_too_short() {
+ #[rustfmt::skip]
+ let buf = [
+ // 32-bit length = 40. TOO SHORT!!!
+ 0x28, 0x00, 0x00, 0x00,
+ // Version.
+ 0x04, 0x00,
+ // Header length = 40.
+ 0x28, 0x00, 0x00, 0x00,
+ // Minimum instruction length.
+ 0x01,
+ // Maximum operations per byte.
+ 0x01,
+ // Default is_stmt.
+ 0x01,
+ // Line base.
+ 0x00,
+ // Line range.
+ 0x01,
+ // Opcode base.
+ 0x03,
+ // Standard opcode lengths for opcodes 1 .. opcode base - 1.
+ 0x01, 0x02,
+ // Include directories = '/', 'i', 'n', 'c', '\0', '/', 'i', 'n', 'c', '2', '\0', '\0'
+ 0x2f, 0x69, 0x6e, 0x63, 0x00, 0x2f, 0x69, 0x6e, 0x63, 0x32, 0x00, 0x00,
+ // File names
+ // foo.rs
+ 0x66, 0x6f, 0x6f, 0x2e, 0x72, 0x73, 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ // bar.h
+ 0x62, 0x61, 0x72, 0x2e, 0x68, 0x00,
+ 0x01,
+ 0x00,
+ 0x00,
+ // End file names.
+ 0x00,
+
+ // Dummy line program data.
+ 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+
+ // Dummy next line program.
+ 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+ ];
+
+ let input = &mut EndianSlice::new(&buf, LittleEndian);
+
+ match LineProgramHeader::parse(input, DebugLineOffset(0), 4, None, None) {
+ Err(Error::UnexpectedEof(_)) => return,
+ otherwise => panic!("Unexpected result: {:?}", otherwise),
+ }
+ }
+
+ const OPCODE_BASE: u8 = 13;
+ const STANDARD_OPCODE_LENGTHS: &[u8] = &[0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1];
+
+ fn make_test_header(
+ buf: EndianSlice<LittleEndian>,
+ ) -> LineProgramHeader<EndianSlice<LittleEndian>> {
+ let encoding = Encoding {
+ format: Format::Dwarf32,
+ version: 4,
+ address_size: 8,
+ };
+ let line_encoding = LineEncoding {
+ line_base: -3,
+ line_range: 12,
+ ..Default::default()
+ };
+ LineProgramHeader {
+ encoding,
+ offset: DebugLineOffset(0),
+ unit_length: 1,
+ header_length: 1,
+ line_encoding,
+ opcode_base: OPCODE_BASE,
+ standard_opcode_lengths: EndianSlice::new(STANDARD_OPCODE_LENGTHS, LittleEndian),
+ file_names: vec![
+ FileEntry {
+ path_name: AttributeValue::String(EndianSlice::new(b"foo.c", LittleEndian)),
+ directory_index: 0,
+ timestamp: 0,
+ size: 0,
+ md5: [0; 16],
+ },
+ FileEntry {
+ path_name: AttributeValue::String(EndianSlice::new(b"bar.rs", LittleEndian)),
+ directory_index: 0,
+ timestamp: 0,
+ size: 0,
+ md5: [0; 16],
+ },
+ ],
+ include_directories: vec![],
+ directory_entry_format: vec![],
+ file_name_entry_format: vec![],
+ program_buf: buf,
+ comp_dir: None,
+ comp_file: None,
+ }
+ }
+
+ fn make_test_program(
+ buf: EndianSlice<LittleEndian>,
+ ) -> IncompleteLineProgram<EndianSlice<LittleEndian>> {
+ IncompleteLineProgram {
+ header: make_test_header(buf),
+ }
+ }
+
+ #[test]
+ fn test_parse_special_opcodes() {
+ for i in OPCODE_BASE..u8::MAX {
+ let input = [i, 0, 0, 0];
+ let input = EndianSlice::new(&input, LittleEndian);
+ let header = make_test_header(input);
+
+ let mut rest = input;
+ let opcode =
+ LineInstruction::parse(&header, &mut rest).expect("Should parse the opcode OK");
+
+ assert_eq!(*rest, *input.range_from(1..));
+ assert_eq!(opcode, LineInstruction::Special(i));
+ }
+ }
+
+ #[test]
+ fn test_parse_standard_opcodes() {
+ fn test<Operands>(
+ raw: constants::DwLns,
+ operands: Operands,
+ expected: LineInstruction<EndianSlice<LittleEndian>>,
+ ) where
+ Operands: AsRef<[u8]>,
+ {
+ let mut input = Vec::new();
+ input.push(raw.0);
+ input.extend_from_slice(operands.as_ref());
+
+ let expected_rest = [0, 1, 2, 3, 4];
+ input.extend_from_slice(&expected_rest);
+
+ let input = EndianSlice::new(&*input, LittleEndian);
+ let header = make_test_header(input);
+
+ let mut rest = input;
+ let opcode =
+ LineInstruction::parse(&header, &mut rest).expect("Should parse the opcode OK");
+
+ assert_eq!(opcode, expected);
+ assert_eq!(*rest, expected_rest);
+ }
+
+ test(constants::DW_LNS_copy, [], LineInstruction::Copy);
+ test(
+ constants::DW_LNS_advance_pc,
+ [42],
+ LineInstruction::AdvancePc(42),
+ );
+ test(
+ constants::DW_LNS_advance_line,
+ [9],
+ LineInstruction::AdvanceLine(9),
+ );
+ test(constants::DW_LNS_set_file, [7], LineInstruction::SetFile(7));
+ test(
+ constants::DW_LNS_set_column,
+ [1],
+ LineInstruction::SetColumn(1),
+ );
+ test(
+ constants::DW_LNS_negate_stmt,
+ [],
+ LineInstruction::NegateStatement,
+ );
+ test(
+ constants::DW_LNS_set_basic_block,
+ [],
+ LineInstruction::SetBasicBlock,
+ );
+ test(
+ constants::DW_LNS_const_add_pc,
+ [],
+ LineInstruction::ConstAddPc,
+ );
+ test(
+ constants::DW_LNS_fixed_advance_pc,
+ [42, 0],
+ LineInstruction::FixedAddPc(42),
+ );
+ test(
+ constants::DW_LNS_set_prologue_end,
+ [],
+ LineInstruction::SetPrologueEnd,
+ );
+ test(
+ constants::DW_LNS_set_isa,
+ [57 + 0x80, 100],
+ LineInstruction::SetIsa(12857),
+ );
+ }
+
+ #[test]
+ fn test_parse_unknown_standard_opcode_no_args() {
+ let input = [OPCODE_BASE, 1, 2, 3];
+ let input = EndianSlice::new(&input, LittleEndian);
+ let mut standard_opcode_lengths = Vec::new();
+ let mut header = make_test_header(input);
+ standard_opcode_lengths.extend(header.standard_opcode_lengths.slice());
+ standard_opcode_lengths.push(0);
+ header.opcode_base += 1;
+ header.standard_opcode_lengths = EndianSlice::new(&standard_opcode_lengths, LittleEndian);
+
+ let mut rest = input;
+ let opcode =
+ LineInstruction::parse(&header, &mut rest).expect("Should parse the opcode OK");
+
+ assert_eq!(
+ opcode,
+ LineInstruction::UnknownStandard0(constants::DwLns(OPCODE_BASE))
+ );
+ assert_eq!(*rest, *input.range_from(1..));
+ }
+
+ #[test]
+ fn test_parse_unknown_standard_opcode_one_arg() {
+ let input = [OPCODE_BASE, 1, 2, 3];
+ let input = EndianSlice::new(&input, LittleEndian);
+ let mut standard_opcode_lengths = Vec::new();
+ let mut header = make_test_header(input);
+ standard_opcode_lengths.extend(header.standard_opcode_lengths.slice());
+ standard_opcode_lengths.push(1);
+ header.opcode_base += 1;
+ header.standard_opcode_lengths = EndianSlice::new(&standard_opcode_lengths, LittleEndian);
+
+ let mut rest = input;
+ let opcode =
+ LineInstruction::parse(&header, &mut rest).expect("Should parse the opcode OK");
+
+ assert_eq!(
+ opcode,
+ LineInstruction::UnknownStandard1(constants::DwLns(OPCODE_BASE), 1)
+ );
+ assert_eq!(*rest, *input.range_from(2..));
+ }
+
+ #[test]
+ fn test_parse_unknown_standard_opcode_many_args() {
+ let input = [OPCODE_BASE, 1, 2, 3];
+ let input = EndianSlice::new(&input, LittleEndian);
+ let args = EndianSlice::new(&input[1..], LittleEndian);
+ let mut standard_opcode_lengths = Vec::new();
+ let mut header = make_test_header(input);
+ standard_opcode_lengths.extend(header.standard_opcode_lengths.slice());
+ standard_opcode_lengths.push(3);
+ header.opcode_base += 1;
+ header.standard_opcode_lengths = EndianSlice::new(&standard_opcode_lengths, LittleEndian);
+
+ let mut rest = input;
+ let opcode =
+ LineInstruction::parse(&header, &mut rest).expect("Should parse the opcode OK");
+
+ assert_eq!(
+ opcode,
+ LineInstruction::UnknownStandardN(constants::DwLns(OPCODE_BASE), args)
+ );
+ assert_eq!(*rest, []);
+ }
+
+ #[test]
+ fn test_parse_extended_opcodes() {
+ fn test<Operands>(
+ raw: constants::DwLne,
+ operands: Operands,
+ expected: LineInstruction<EndianSlice<LittleEndian>>,
+ ) where
+ Operands: AsRef<[u8]>,
+ {
+ let mut input = Vec::new();
+ input.push(0);
+
+ let operands = operands.as_ref();
+ input.push(1 + operands.len() as u8);
+
+ input.push(raw.0);
+ input.extend_from_slice(operands);
+
+ let expected_rest = [0, 1, 2, 3, 4];
+ input.extend_from_slice(&expected_rest);
+
+ let input = EndianSlice::new(&input, LittleEndian);
+ let header = make_test_header(input);
+
+ let mut rest = input;
+ let opcode =
+ LineInstruction::parse(&header, &mut rest).expect("Should parse the opcode OK");
+
+ assert_eq!(opcode, expected);
+ assert_eq!(*rest, expected_rest);
+ }
+
+ test(
+ constants::DW_LNE_end_sequence,
+ [],
+ LineInstruction::EndSequence,
+ );
+ test(
+ constants::DW_LNE_set_address,
+ [1, 2, 3, 4, 5, 6, 7, 8],
+ LineInstruction::SetAddress(578_437_695_752_307_201),
+ );
+ test(
+ constants::DW_LNE_set_discriminator,
+ [42],
+ LineInstruction::SetDiscriminator(42),
+ );
+
+ let mut file = Vec::new();
+ // "foo.c"
+ let path_name = [b'f', b'o', b'o', b'.', b'c', 0];
+ file.extend_from_slice(&path_name);
+ // Directory index.
+ file.push(0);
+ // Last modification of file.
+ file.push(1);
+ // Size of file.
+ file.push(2);
+
+ test(
+ constants::DW_LNE_define_file,
+ file,
+ LineInstruction::DefineFile(FileEntry {
+ path_name: AttributeValue::String(EndianSlice::new(b"foo.c", LittleEndian)),
+ directory_index: 0,
+ timestamp: 1,
+ size: 2,
+ md5: [0; 16],
+ }),
+ );
+
+ // Unknown extended opcode.
+ let operands = [1, 2, 3, 4, 5, 6];
+ let opcode = constants::DwLne(99);
+ test(
+ opcode,
+ operands,
+ LineInstruction::UnknownExtended(opcode, EndianSlice::new(&operands, LittleEndian)),
+ );
+ }
+
+ #[test]
+ fn test_file_entry_directory() {
+ let path_name = [b'f', b'o', b'o', b'.', b'r', b's', 0];
+
+ let mut file = FileEntry {
+ path_name: AttributeValue::String(EndianSlice::new(&path_name, LittleEndian)),
+ directory_index: 1,
+ timestamp: 0,
+ size: 0,
+ md5: [0; 16],
+ };
+
+ let mut header = make_test_header(EndianSlice::new(&[], LittleEndian));
+
+ let dir = AttributeValue::String(EndianSlice::new(b"dir", LittleEndian));
+ header.include_directories.push(dir);
+
+ assert_eq!(file.directory(&header), Some(dir));
+
+ // Now test the compilation's current directory.
+ file.directory_index = 0;
+ assert_eq!(file.directory(&header), None);
+ }
+
+ fn assert_exec_opcode<'input>(
+ header: LineProgramHeader<EndianSlice<'input, LittleEndian>>,
+ mut registers: LineRow,
+ opcode: LineInstruction<EndianSlice<'input, LittleEndian>>,
+ expected_registers: LineRow,
+ expect_new_row: bool,
+ ) {
+ let mut program = IncompleteLineProgram { header };
+ let is_new_row = registers.execute(opcode, &mut program);
+
+ assert_eq!(is_new_row, expect_new_row);
+ assert_eq!(registers, expected_registers);
+ }
+
+ #[test]
+ fn test_exec_special_noop() {
+ let header = make_test_header(EndianSlice::new(&[], LittleEndian));
+
+ let initial_registers = LineRow::new(&header);
+ let opcode = LineInstruction::Special(16);
+ let expected_registers = initial_registers;
+
+ assert_exec_opcode(header, initial_registers, opcode, expected_registers, true);
+ }
+
+ #[test]
+ fn test_exec_special_negative_line_advance() {
+ let header = make_test_header(EndianSlice::new(&[], LittleEndian));
+
+ let mut initial_registers = LineRow::new(&header);
+ initial_registers.line.0 = 10;
+
+ let opcode = LineInstruction::Special(13);
+
+ let mut expected_registers = initial_registers;
+ expected_registers.line.0 -= 3;
+
+ assert_exec_opcode(header, initial_registers, opcode, expected_registers, true);
+ }
+
+ #[test]
+ fn test_exec_special_positive_line_advance() {
+ let header = make_test_header(EndianSlice::new(&[], LittleEndian));
+
+ let initial_registers = LineRow::new(&header);
+
+ let opcode = LineInstruction::Special(19);
+
+ let mut expected_registers = initial_registers;
+ expected_registers.line.0 += 3;
+
+ assert_exec_opcode(header, initial_registers, opcode, expected_registers, true);
+ }
+
+ #[test]
+ fn test_exec_special_positive_address_advance() {
+ let header = make_test_header(EndianSlice::new(&[], LittleEndian));
+
+ let initial_registers = LineRow::new(&header);
+
+ let opcode = LineInstruction::Special(52);
+
+ let mut expected_registers = initial_registers;
+ expected_registers.address.0 += 3;
+
+ assert_exec_opcode(header, initial_registers, opcode, expected_registers, true);
+ }
+
+ #[test]
+ fn test_exec_special_positive_address_and_line_advance() {
+ let header = make_test_header(EndianSlice::new(&[], LittleEndian));
+
+ let initial_registers = LineRow::new(&header);
+
+ let opcode = LineInstruction::Special(55);
+
+ let mut expected_registers = initial_registers;
+ expected_registers.address.0 += 3;
+ expected_registers.line.0 += 3;
+
+ assert_exec_opcode(header, initial_registers, opcode, expected_registers, true);
+ }
+
+ #[test]
+ fn test_exec_special_positive_address_and_negative_line_advance() {
+ let header = make_test_header(EndianSlice::new(&[], LittleEndian));
+
+ let mut initial_registers = LineRow::new(&header);
+ initial_registers.line.0 = 10;
+
+ let opcode = LineInstruction::Special(49);
+
+ let mut expected_registers = initial_registers;
+ expected_registers.address.0 += 3;
+ expected_registers.line.0 -= 3;
+
+ assert_exec_opcode(header, initial_registers, opcode, expected_registers, true);
+ }
+
+ #[test]
+ fn test_exec_special_line_underflow() {
+ let header = make_test_header(EndianSlice::new(&[], LittleEndian));
+
+ let mut initial_registers = LineRow::new(&header);
+ initial_registers.line.0 = 2;
+
+ // -3 line advance.
+ let opcode = LineInstruction::Special(13);
+
+ let mut expected_registers = initial_registers;
+ // Clamp at 0. No idea if this is the best way to handle this situation
+ // or not...
+ expected_registers.line.0 = 0;
+
+ assert_exec_opcode(header, initial_registers, opcode, expected_registers, true);
+ }
+
+ #[test]
+ fn test_exec_copy() {
+ let header = make_test_header(EndianSlice::new(&[], LittleEndian));
+
+ let mut initial_registers = LineRow::new(&header);
+ initial_registers.address.0 = 1337;
+ initial_registers.line.0 = 42;
+
+ let opcode = LineInstruction::Copy;
+
+ let expected_registers = initial_registers;
+
+ assert_exec_opcode(header, initial_registers, opcode, expected_registers, true);
+ }
+
+ #[test]
+ fn test_exec_advance_pc() {
+ let header = make_test_header(EndianSlice::new(&[], LittleEndian));
+ let initial_registers = LineRow::new(&header);
+ let opcode = LineInstruction::AdvancePc(42);
+
+ let mut expected_registers = initial_registers;
+ expected_registers.address.0 += 42;
+
+ assert_exec_opcode(header, initial_registers, opcode, expected_registers, false);
+ }
+
+ #[test]
+ fn test_exec_advance_pc_overflow() {
+ let header = make_test_header(EndianSlice::new(&[], LittleEndian));
+ let opcode = LineInstruction::AdvancePc(42);
+
+ let mut initial_registers = LineRow::new(&header);
+ initial_registers.address.0 = u64::MAX;
+
+ let mut expected_registers = initial_registers;
+ expected_registers.address.0 = 41;
+
+ assert_exec_opcode(header, initial_registers, opcode, expected_registers, false);
+ }
+
+ #[test]
+ fn test_exec_advance_line() {
+ let header = make_test_header(EndianSlice::new(&[], LittleEndian));
+ let initial_registers = LineRow::new(&header);
+ let opcode = LineInstruction::AdvanceLine(42);
+
+ let mut expected_registers = initial_registers;
+ expected_registers.line.0 += 42;
+
+ assert_exec_opcode(header, initial_registers, opcode, expected_registers, false);
+ }
+
+ #[test]
+ fn test_exec_advance_line_overflow() {
+ let header = make_test_header(EndianSlice::new(&[], LittleEndian));
+ let opcode = LineInstruction::AdvanceLine(42);
+
+ let mut initial_registers = LineRow::new(&header);
+ initial_registers.line.0 = u64::MAX;
+
+ let mut expected_registers = initial_registers;
+ expected_registers.line.0 = 41;
+
+ assert_exec_opcode(header, initial_registers, opcode, expected_registers, false);
+ }
+
+ #[test]
+ fn test_exec_set_file_in_bounds() {
+ for file_idx in 1..3 {
+ let header = make_test_header(EndianSlice::new(&[], LittleEndian));
+ let initial_registers = LineRow::new(&header);
+ let opcode = LineInstruction::SetFile(file_idx);
+
+ let mut expected_registers = initial_registers;
+ expected_registers.file = file_idx;
+
+ assert_exec_opcode(header, initial_registers, opcode, expected_registers, false);
+ }
+ }
+
+ #[test]
+ fn test_exec_set_file_out_of_bounds() {
+ let header = make_test_header(EndianSlice::new(&[], LittleEndian));
+ let initial_registers = LineRow::new(&header);
+ let opcode = LineInstruction::SetFile(100);
+
+ // The spec doesn't say anything about rejecting input programs
+ // that set the file register out of bounds of the actual number
+ // of files that have been defined. Instead, we cross our
+ // fingers and hope that one gets defined before
+ // `LineRow::file` gets called and handle the error at
+ // that time if need be.
+ let mut expected_registers = initial_registers;
+ expected_registers.file = 100;
+
+ assert_exec_opcode(header, initial_registers, opcode, expected_registers, false);
+ }
+
+ #[test]
+ fn test_file_entry_file_index_out_of_bounds() {
+ // These indices are 1-based, so 0 is invalid. 100 is way more than the
+ // number of files defined in the header.
+ let out_of_bounds_indices = [0, 100];
+
+ for file_idx in &out_of_bounds_indices[..] {
+ let header = make_test_header(EndianSlice::new(&[], LittleEndian));
+ let mut row = LineRow::new(&header);
+
+ row.file = *file_idx;
+
+ assert_eq!(row.file(&header), None);
+ }
+ }
+
+ #[test]
+ fn test_file_entry_file_index_in_bounds() {
+ let header = make_test_header(EndianSlice::new(&[], LittleEndian));
+ let mut row = LineRow::new(&header);
+
+ row.file = 2;
+
+ assert_eq!(row.file(&header), Some(&header.file_names()[1]));
+ }
+
+ #[test]
+ fn test_exec_set_column() {
+ let header = make_test_header(EndianSlice::new(&[], LittleEndian));
+ let initial_registers = LineRow::new(&header);
+ let opcode = LineInstruction::SetColumn(42);
+
+ let mut expected_registers = initial_registers;
+ expected_registers.column = 42;
+
+ assert_exec_opcode(header, initial_registers, opcode, expected_registers, false);
+ }
+
+ #[test]
+ fn test_exec_negate_statement() {
+ let header = make_test_header(EndianSlice::new(&[], LittleEndian));
+ let initial_registers = LineRow::new(&header);
+ let opcode = LineInstruction::NegateStatement;
+
+ let mut expected_registers = initial_registers;
+ expected_registers.is_stmt = !initial_registers.is_stmt;
+
+ assert_exec_opcode(header, initial_registers, opcode, expected_registers, false);
+ }
+
+ #[test]
+ fn test_exec_set_basic_block() {
+ let header = make_test_header(EndianSlice::new(&[], LittleEndian));
+
+ let mut initial_registers = LineRow::new(&header);
+ initial_registers.basic_block = false;
+
+ let opcode = LineInstruction::SetBasicBlock;
+
+ let mut expected_registers = initial_registers;
+ expected_registers.basic_block = true;
+
+ assert_exec_opcode(header, initial_registers, opcode, expected_registers, false);
+ }
+
+ #[test]
+ fn test_exec_const_add_pc() {
+ let header = make_test_header(EndianSlice::new(&[], LittleEndian));
+ let initial_registers = LineRow::new(&header);
+ let opcode = LineInstruction::ConstAddPc;
+
+ let mut expected_registers = initial_registers;
+ expected_registers.address.0 += 20;
+
+ assert_exec_opcode(header, initial_registers, opcode, expected_registers, false);
+ }
+
+ #[test]
+ fn test_exec_fixed_add_pc() {
+ let header = make_test_header(EndianSlice::new(&[], LittleEndian));
+
+ let mut initial_registers = LineRow::new(&header);
+ initial_registers.op_index.0 = 1;
+
+ let opcode = LineInstruction::FixedAddPc(10);
+
+ let mut expected_registers = initial_registers;
+ expected_registers.address.0 += 10;
+ expected_registers.op_index.0 = 0;
+
+ assert_exec_opcode(header, initial_registers, opcode, expected_registers, false);
+ }
+
+ #[test]
+ fn test_exec_set_prologue_end() {
+ let header = make_test_header(EndianSlice::new(&[], LittleEndian));
+
+ let mut initial_registers = LineRow::new(&header);
+ initial_registers.prologue_end = false;
+
+ let opcode = LineInstruction::SetPrologueEnd;
+
+ let mut expected_registers = initial_registers;
+ expected_registers.prologue_end = true;
+
+ assert_exec_opcode(header, initial_registers, opcode, expected_registers, false);
+ }
+
+ #[test]
+ fn test_exec_set_isa() {
+ let header = make_test_header(EndianSlice::new(&[], LittleEndian));
+ let initial_registers = LineRow::new(&header);
+ let opcode = LineInstruction::SetIsa(1993);
+
+ let mut expected_registers = initial_registers;
+ expected_registers.isa = 1993;
+
+ assert_exec_opcode(header, initial_registers, opcode, expected_registers, false);
+ }
+
+ #[test]
+ fn test_exec_unknown_standard_0() {
+ let header = make_test_header(EndianSlice::new(&[], LittleEndian));
+ let initial_registers = LineRow::new(&header);
+ let opcode = LineInstruction::UnknownStandard0(constants::DwLns(111));
+ let expected_registers = initial_registers;
+ assert_exec_opcode(header, initial_registers, opcode, expected_registers, false);
+ }
+
+ #[test]
+ fn test_exec_unknown_standard_1() {
+ let header = make_test_header(EndianSlice::new(&[], LittleEndian));
+ let initial_registers = LineRow::new(&header);
+ let opcode = LineInstruction::UnknownStandard1(constants::DwLns(111), 2);
+ let expected_registers = initial_registers;
+ assert_exec_opcode(header, initial_registers, opcode, expected_registers, false);
+ }
+
+ #[test]
+ fn test_exec_unknown_standard_n() {
+ let header = make_test_header(EndianSlice::new(&[], LittleEndian));
+ let initial_registers = LineRow::new(&header);
+ let opcode = LineInstruction::UnknownStandardN(
+ constants::DwLns(111),
+ EndianSlice::new(&[2, 2, 2], LittleEndian),
+ );
+ let expected_registers = initial_registers;
+ assert_exec_opcode(header, initial_registers, opcode, expected_registers, false);
+ }
+
+ #[test]
+ fn test_exec_end_sequence() {
+ let header = make_test_header(EndianSlice::new(&[], LittleEndian));
+ let initial_registers = LineRow::new(&header);
+ let opcode = LineInstruction::EndSequence;
+
+ let mut expected_registers = initial_registers;
+ expected_registers.end_sequence = true;
+
+ assert_exec_opcode(header, initial_registers, opcode, expected_registers, true);
+ }
+
+ #[test]
+ fn test_exec_set_address() {
+ let header = make_test_header(EndianSlice::new(&[], LittleEndian));
+ let initial_registers = LineRow::new(&header);
+ let opcode = LineInstruction::SetAddress(3030);
+
+ let mut expected_registers = initial_registers;
+ expected_registers.address.0 = 3030;
+
+ assert_exec_opcode(header, initial_registers, opcode, expected_registers, false);
+ }
+
+ #[test]
+ fn test_exec_define_file() {
+ let mut program = make_test_program(EndianSlice::new(&[], LittleEndian));
+ let mut row = LineRow::new(program.header());
+
+ let file = FileEntry {
+ path_name: AttributeValue::String(EndianSlice::new(b"test.cpp", LittleEndian)),
+ directory_index: 0,
+ timestamp: 0,
+ size: 0,
+ md5: [0; 16],
+ };
+
+ let opcode = LineInstruction::DefineFile(file);
+ let is_new_row = row.execute(opcode, &mut program);
+
+ assert_eq!(is_new_row, false);
+ assert_eq!(Some(&file), program.header().file_names.last());
+ }
+
+ #[test]
+ fn test_exec_set_discriminator() {
+ let header = make_test_header(EndianSlice::new(&[], LittleEndian));
+ let initial_registers = LineRow::new(&header);
+ let opcode = LineInstruction::SetDiscriminator(9);
+
+ let mut expected_registers = initial_registers;
+ expected_registers.discriminator = 9;
+
+ assert_exec_opcode(header, initial_registers, opcode, expected_registers, false);
+ }
+
+ #[test]
+ fn test_exec_unknown_extended() {
+ let header = make_test_header(EndianSlice::new(&[], LittleEndian));
+ let initial_registers = LineRow::new(&header);
+ let opcode = LineInstruction::UnknownExtended(
+ constants::DwLne(74),
+ EndianSlice::new(&[], LittleEndian),
+ );
+ let expected_registers = initial_registers;
+ assert_exec_opcode(header, initial_registers, opcode, expected_registers, false);
+ }
+
+ /// Ensure that `LineRows<R,P>` is covariant wrt R.
+ /// This only needs to compile.
+ #[allow(dead_code, unreachable_code, unused_variables)]
+ fn test_line_rows_variance<'a, 'b>(_: &'a [u8], _: &'b [u8])
+ where
+ 'a: 'b,
+ {
+ let a: &OneShotLineRows<EndianSlice<'a, LittleEndian>> = unimplemented!();
+ let _: &OneShotLineRows<EndianSlice<'b, LittleEndian>> = a;
+ }
+
+ #[test]
+ fn test_parse_debug_line_v5_ok() {
+ let expected_lengths = &[1, 2];
+ let expected_program = &[0, 1, 2, 3, 4];
+ let expected_rest = &[5, 6, 7, 8, 9];
+ let expected_include_directories = [
+ AttributeValue::String(EndianSlice::new(b"dir1", LittleEndian)),
+ AttributeValue::String(EndianSlice::new(b"dir2", LittleEndian)),
+ ];
+ let expected_file_names = [
+ FileEntry {
+ path_name: AttributeValue::String(EndianSlice::new(b"file1", LittleEndian)),
+ directory_index: 0,
+ timestamp: 0,
+ size: 0,
+ md5: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16],
+ },
+ FileEntry {
+ path_name: AttributeValue::String(EndianSlice::new(b"file2", LittleEndian)),
+ directory_index: 1,
+ timestamp: 0,
+ size: 0,
+ md5: [
+ 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26,
+ ],
+ },
+ ];
+
+ for format in vec![Format::Dwarf32, Format::Dwarf64] {
+ let length = Label::new();
+ let header_length = Label::new();
+ let start = Label::new();
+ let header_start = Label::new();
+ let end = Label::new();
+ let header_end = Label::new();
+ let section = Section::with_endian(Endian::Little)
+ .initial_length(format, &length, &start)
+ .D16(5)
+ // Address size.
+ .D8(4)
+ // Segment selector size.
+ .D8(0)
+ .word_label(format.word_size(), &header_length)
+ .mark(&header_start)
+ // Minimum instruction length.
+ .D8(1)
+ // Maximum operations per byte.
+ .D8(1)
+ // Default is_stmt.
+ .D8(1)
+ // Line base.
+ .D8(0)
+ // Line range.
+ .D8(1)
+ // Opcode base.
+ .D8(expected_lengths.len() as u8 + 1)
+ // Standard opcode lengths for opcodes 1 .. opcode base - 1.
+ .append_bytes(expected_lengths)
+ // Directory entry format count.
+ .D8(1)
+ .uleb(constants::DW_LNCT_path.0 as u64)
+ .uleb(constants::DW_FORM_string.0 as u64)
+ // Directory count.
+ .D8(2)
+ .append_bytes(b"dir1\0")
+ .append_bytes(b"dir2\0")
+ // File entry format count.
+ .D8(3)
+ .uleb(constants::DW_LNCT_path.0 as u64)
+ .uleb(constants::DW_FORM_string.0 as u64)
+ .uleb(constants::DW_LNCT_directory_index.0 as u64)
+ .uleb(constants::DW_FORM_data1.0 as u64)
+ .uleb(constants::DW_LNCT_MD5.0 as u64)
+ .uleb(constants::DW_FORM_data16.0 as u64)
+ // File count.
+ .D8(2)
+ .append_bytes(b"file1\0")
+ .D8(0)
+ .append_bytes(&expected_file_names[0].md5)
+ .append_bytes(b"file2\0")
+ .D8(1)
+ .append_bytes(&expected_file_names[1].md5)
+ .mark(&header_end)
+ // Dummy line program data.
+ .append_bytes(expected_program)
+ .mark(&end)
+ // Dummy trailing data.
+ .append_bytes(expected_rest);
+ length.set_const((&end - &start) as u64);
+ header_length.set_const((&header_end - &header_start) as u64);
+ let section = section.get_contents().unwrap();
+
+ let input = &mut EndianSlice::new(&section, LittleEndian);
+
+ let header = LineProgramHeader::parse(input, DebugLineOffset(0), 0, None, None)
+ .expect("should parse header ok");
+
+ assert_eq!(header.raw_program_buf().slice(), expected_program);
+ assert_eq!(input.slice(), expected_rest);
+
+ assert_eq!(header.offset, DebugLineOffset(0));
+ assert_eq!(header.version(), 5);
+ assert_eq!(header.address_size(), 4);
+ assert_eq!(header.minimum_instruction_length(), 1);
+ assert_eq!(header.maximum_operations_per_instruction(), 1);
+ assert_eq!(header.default_is_stmt(), true);
+ assert_eq!(header.line_base(), 0);
+ assert_eq!(header.line_range(), 1);
+ assert_eq!(header.opcode_base(), expected_lengths.len() as u8 + 1);
+ assert_eq!(header.standard_opcode_lengths().slice(), expected_lengths);
+ assert_eq!(
+ header.directory_entry_format(),
+ &[FileEntryFormat {
+ content_type: constants::DW_LNCT_path,
+ form: constants::DW_FORM_string,
+ }]
+ );
+ assert_eq!(header.include_directories(), expected_include_directories);
+ assert_eq!(header.directory(0), Some(expected_include_directories[0]));
+ assert_eq!(
+ header.file_name_entry_format(),
+ &[
+ FileEntryFormat {
+ content_type: constants::DW_LNCT_path,
+ form: constants::DW_FORM_string,
+ },
+ FileEntryFormat {
+ content_type: constants::DW_LNCT_directory_index,
+ form: constants::DW_FORM_data1,
+ },
+ FileEntryFormat {
+ content_type: constants::DW_LNCT_MD5,
+ form: constants::DW_FORM_data16,
+ }
+ ]
+ );
+ assert_eq!(header.file_names(), expected_file_names);
+ assert_eq!(header.file(0), Some(&expected_file_names[0]));
+ }
+ }
+}
diff --git a/vendor/gimli-0.26.2/src/read/lists.rs b/vendor/gimli-0.26.2/src/read/lists.rs
new file mode 100644
index 000000000..898a757d3
--- /dev/null
+++ b/vendor/gimli-0.26.2/src/read/lists.rs
@@ -0,0 +1,68 @@
+use crate::common::{Encoding, Format};
+use crate::read::{Error, Reader, Result};
+
+#[derive(Debug, Clone, Copy)]
+pub(crate) struct ListsHeader {
+ encoding: Encoding,
+ #[allow(dead_code)]
+ offset_entry_count: u32,
+}
+
+impl Default for ListsHeader {
+ fn default() -> Self {
+ ListsHeader {
+ encoding: Encoding {
+ format: Format::Dwarf32,
+ version: 5,
+ address_size: 0,
+ },
+ offset_entry_count: 0,
+ }
+ }
+}
+
+impl ListsHeader {
+ /// Return the serialized size of the table header.
+ #[allow(dead_code)]
+ #[inline]
+ fn size(self) -> u8 {
+ // initial_length + version + address_size + segment_selector_size + offset_entry_count
+ ListsHeader::size_for_encoding(self.encoding)
+ }
+
+ /// Return the serialized size of the table header.
+ #[inline]
+ pub(crate) fn size_for_encoding(encoding: Encoding) -> u8 {
+ // initial_length + version + address_size + segment_selector_size + offset_entry_count
+ encoding.format.initial_length_size() + 2 + 1 + 1 + 4
+ }
+}
+
+// TODO: add an iterator over headers in the appropriate sections section
+#[allow(dead_code)]
+fn parse_header<R: Reader>(input: &mut R) -> Result<ListsHeader> {
+ let (length, format) = input.read_initial_length()?;
+ input.truncate(length)?;
+
+ let version = input.read_u16()?;
+ if version != 5 {
+ return Err(Error::UnknownVersion(u64::from(version)));
+ }
+
+ let address_size = input.read_u8()?;
+ let segment_selector_size = input.read_u8()?;
+ if segment_selector_size != 0 {
+ return Err(Error::UnsupportedSegmentSize);
+ }
+ let offset_entry_count = input.read_u32()?;
+
+ let encoding = Encoding {
+ format,
+ version,
+ address_size,
+ };
+ Ok(ListsHeader {
+ encoding,
+ offset_entry_count,
+ })
+}
diff --git a/vendor/gimli-0.26.2/src/read/loclists.rs b/vendor/gimli-0.26.2/src/read/loclists.rs
new file mode 100644
index 000000000..3902c181b
--- /dev/null
+++ b/vendor/gimli-0.26.2/src/read/loclists.rs
@@ -0,0 +1,1514 @@
+use crate::common::{
+ DebugAddrBase, DebugAddrIndex, DebugLocListsBase, DebugLocListsIndex, DwarfFileType, Encoding,
+ LocationListsOffset, SectionId,
+};
+use crate::constants;
+use crate::endianity::Endianity;
+use crate::read::{
+ lists::ListsHeader, DebugAddr, EndianSlice, Error, Expression, Range, RawRange, Reader,
+ ReaderOffset, ReaderOffsetId, Result, Section,
+};
+
+/// The raw contents of the `.debug_loc` section.
+#[derive(Debug, Default, Clone, Copy)]
+pub struct DebugLoc<R> {
+ pub(crate) section: R,
+}
+
+impl<'input, Endian> DebugLoc<EndianSlice<'input, Endian>>
+where
+ Endian: Endianity,
+{
+ /// Construct a new `DebugLoc` instance from the data in the `.debug_loc`
+ /// section.
+ ///
+ /// It is the caller's responsibility to read the `.debug_loc` section and
+ /// present it as a `&[u8]` slice. That means using some ELF loader on
+ /// Linux, a Mach-O loader on macOS, etc.
+ ///
+ /// ```
+ /// use gimli::{DebugLoc, LittleEndian};
+ ///
+ /// # let buf = [0x00, 0x01, 0x02, 0x03];
+ /// # let read_debug_loc_section_somehow = || &buf;
+ /// let debug_loc = DebugLoc::new(read_debug_loc_section_somehow(), LittleEndian);
+ /// ```
+ pub fn new(section: &'input [u8], endian: Endian) -> Self {
+ Self::from(EndianSlice::new(section, endian))
+ }
+}
+
+impl<R> Section<R> for DebugLoc<R> {
+ fn id() -> SectionId {
+ SectionId::DebugLoc
+ }
+
+ fn reader(&self) -> &R {
+ &self.section
+ }
+}
+
+impl<R> From<R> for DebugLoc<R> {
+ fn from(section: R) -> Self {
+ DebugLoc { section }
+ }
+}
+
+/// The `DebugLocLists` struct represents the DWARF data
+/// found in the `.debug_loclists` section.
+#[derive(Debug, Default, Clone, Copy)]
+pub struct DebugLocLists<R> {
+ section: R,
+}
+
+impl<'input, Endian> DebugLocLists<EndianSlice<'input, Endian>>
+where
+ Endian: Endianity,
+{
+ /// Construct a new `DebugLocLists` instance from the data in the `.debug_loclists`
+ /// section.
+ ///
+ /// It is the caller's responsibility to read the `.debug_loclists` section and
+ /// present it as a `&[u8]` slice. That means using some ELF loader on
+ /// Linux, a Mach-O loader on macOS, etc.
+ ///
+ /// ```
+ /// use gimli::{DebugLocLists, LittleEndian};
+ ///
+ /// # let buf = [0x00, 0x01, 0x02, 0x03];
+ /// # let read_debug_loclists_section_somehow = || &buf;
+ /// let debug_loclists = DebugLocLists::new(read_debug_loclists_section_somehow(), LittleEndian);
+ /// ```
+ pub fn new(section: &'input [u8], endian: Endian) -> Self {
+ Self::from(EndianSlice::new(section, endian))
+ }
+}
+
+impl<R> Section<R> for DebugLocLists<R> {
+ fn id() -> SectionId {
+ SectionId::DebugLocLists
+ }
+
+ fn reader(&self) -> &R {
+ &self.section
+ }
+}
+
+impl<R> From<R> for DebugLocLists<R> {
+ fn from(section: R) -> Self {
+ DebugLocLists { section }
+ }
+}
+
+pub(crate) type LocListsHeader = ListsHeader;
+
+impl<Offset> DebugLocListsBase<Offset>
+where
+ Offset: ReaderOffset,
+{
+ /// Returns a `DebugLocListsBase` with the default value of DW_AT_loclists_base
+ /// for the given `Encoding` and `DwarfFileType`.
+ pub fn default_for_encoding_and_file(
+ encoding: Encoding,
+ file_type: DwarfFileType,
+ ) -> DebugLocListsBase<Offset> {
+ if encoding.version >= 5 && file_type == DwarfFileType::Dwo {
+ // In .dwo files, the compiler omits the DW_AT_loclists_base attribute (because there is
+ // only a single unit in the file) but we must skip past the header, which the attribute
+ // would normally do for us.
+ DebugLocListsBase(Offset::from_u8(LocListsHeader::size_for_encoding(encoding)))
+ } else {
+ DebugLocListsBase(Offset::from_u8(0))
+ }
+ }
+}
+
+/// The DWARF data found in `.debug_loc` and `.debug_loclists` sections.
+#[derive(Debug, Default, Clone, Copy)]
+pub struct LocationLists<R> {
+ debug_loc: DebugLoc<R>,
+ debug_loclists: DebugLocLists<R>,
+}
+
+impl<R> LocationLists<R> {
+ /// Construct a new `LocationLists` instance from the data in the `.debug_loc` and
+ /// `.debug_loclists` sections.
+ pub fn new(debug_loc: DebugLoc<R>, debug_loclists: DebugLocLists<R>) -> LocationLists<R> {
+ LocationLists {
+ debug_loc,
+ debug_loclists,
+ }
+ }
+}
+
+impl<T> LocationLists<T> {
+ /// Create a `LocationLists` that references the data in `self`.
+ ///
+ /// This is useful when `R` implements `Reader` but `T` does not.
+ ///
+ /// ## Example Usage
+ ///
+ /// ```rust,no_run
+ /// # let load_section = || unimplemented!();
+ /// // Read the DWARF section into a `Vec` with whatever object loader you're using.
+ /// let owned_section: gimli::LocationLists<Vec<u8>> = load_section();
+ /// // Create a reference to the DWARF section.
+ /// let section = owned_section.borrow(|section| {
+ /// gimli::EndianSlice::new(&section, gimli::LittleEndian)
+ /// });
+ /// ```
+ pub fn borrow<'a, F, R>(&'a self, mut borrow: F) -> LocationLists<R>
+ where
+ F: FnMut(&'a T) -> R,
+ {
+ LocationLists {
+ debug_loc: borrow(&self.debug_loc.section).into(),
+ debug_loclists: borrow(&self.debug_loclists.section).into(),
+ }
+ }
+}
+
+impl<R: Reader> LocationLists<R> {
+ /// Iterate over the `LocationListEntry`s starting at the given offset.
+ ///
+ /// The `unit_encoding` must match the compilation unit that the
+ /// offset was contained in.
+ ///
+ /// The `base_address` should be obtained from the `DW_AT_low_pc` attribute in the
+ /// `DW_TAG_compile_unit` entry for the compilation unit that contains this location
+ /// list.
+ ///
+ /// Can be [used with
+ /// `FallibleIterator`](./index.html#using-with-fallibleiterator).
+ pub fn locations(
+ &self,
+ offset: LocationListsOffset<R::Offset>,
+ unit_encoding: Encoding,
+ base_address: u64,
+ debug_addr: &DebugAddr<R>,
+ debug_addr_base: DebugAddrBase<R::Offset>,
+ ) -> Result<LocListIter<R>> {
+ Ok(LocListIter::new(
+ self.raw_locations(offset, unit_encoding)?,
+ base_address,
+ debug_addr.clone(),
+ debug_addr_base,
+ ))
+ }
+
+ /// Similar to `locations`, but with special handling for .dwo files.
+ /// This should only been used when this `LocationLists` was loaded from a
+ /// .dwo file.
+ pub fn locations_dwo(
+ &self,
+ offset: LocationListsOffset<R::Offset>,
+ unit_encoding: Encoding,
+ base_address: u64,
+ debug_addr: &DebugAddr<R>,
+ debug_addr_base: DebugAddrBase<R::Offset>,
+ ) -> Result<LocListIter<R>> {
+ Ok(LocListIter::new(
+ self.raw_locations_dwo(offset, unit_encoding)?,
+ base_address,
+ debug_addr.clone(),
+ debug_addr_base,
+ ))
+ }
+
+ /// Iterate over the raw `LocationListEntry`s starting at the given offset.
+ ///
+ /// The `unit_encoding` must match the compilation unit that the
+ /// offset was contained in.
+ ///
+ /// This iterator does not perform any processing of the location entries,
+ /// such as handling base addresses.
+ ///
+ /// Can be [used with
+ /// `FallibleIterator`](./index.html#using-with-fallibleiterator).
+ pub fn raw_locations(
+ &self,
+ offset: LocationListsOffset<R::Offset>,
+ unit_encoding: Encoding,
+ ) -> Result<RawLocListIter<R>> {
+ let (mut input, format) = if unit_encoding.version <= 4 {
+ (self.debug_loc.section.clone(), LocListsFormat::Bare)
+ } else {
+ (self.debug_loclists.section.clone(), LocListsFormat::LLE)
+ };
+ input.skip(offset.0)?;
+ Ok(RawLocListIter::new(input, unit_encoding, format))
+ }
+
+ /// Similar to `raw_locations`, but with special handling for .dwo files.
+ /// This should only been used when this `LocationLists` was loaded from a
+ /// .dwo file.
+ pub fn raw_locations_dwo(
+ &self,
+ offset: LocationListsOffset<R::Offset>,
+ unit_encoding: Encoding,
+ ) -> Result<RawLocListIter<R>> {
+ let mut input = if unit_encoding.version <= 4 {
+ // In the GNU split dwarf extension the locations are present in the
+ // .debug_loc section but are encoded with the DW_LLE values used
+ // for the DWARF 5 .debug_loclists section.
+ self.debug_loc.section.clone()
+ } else {
+ self.debug_loclists.section.clone()
+ };
+ input.skip(offset.0)?;
+ Ok(RawLocListIter::new(
+ input,
+ unit_encoding,
+ LocListsFormat::LLE,
+ ))
+ }
+
+ /// Returns the `.debug_loclists` offset at the given `base` and `index`.
+ ///
+ /// The `base` must be the `DW_AT_loclists_base` value from the compilation unit DIE.
+ /// This is an offset that points to the first entry following the header.
+ ///
+ /// The `index` is the value of a `DW_FORM_loclistx` attribute.
+ pub fn get_offset(
+ &self,
+ unit_encoding: Encoding,
+ base: DebugLocListsBase<R::Offset>,
+ index: DebugLocListsIndex<R::Offset>,
+ ) -> Result<LocationListsOffset<R::Offset>> {
+ let format = unit_encoding.format;
+ let input = &mut self.debug_loclists.section.clone();
+ input.skip(base.0)?;
+ input.skip(R::Offset::from_u64(
+ index.0.into_u64() * u64::from(format.word_size()),
+ )?)?;
+ input
+ .read_offset(format)
+ .map(|x| LocationListsOffset(base.0 + x))
+ }
+
+ /// Call `Reader::lookup_offset_id` for each section, and return the first match.
+ pub fn lookup_offset_id(&self, id: ReaderOffsetId) -> Option<(SectionId, R::Offset)> {
+ self.debug_loc
+ .lookup_offset_id(id)
+ .or_else(|| self.debug_loclists.lookup_offset_id(id))
+ }
+}
+
+#[derive(Debug, Clone, Copy, PartialEq, Eq)]
+enum LocListsFormat {
+ /// The bare location list format used before DWARF 5.
+ Bare,
+ /// The DW_LLE encoded range list format used in DWARF 5 and the non-standard GNU
+ /// split dwarf extension.
+ LLE,
+}
+
+/// A raw iterator over a location list.
+///
+/// This iterator does not perform any processing of the location entries,
+/// such as handling base addresses.
+#[derive(Debug)]
+pub struct RawLocListIter<R: Reader> {
+ input: R,
+ encoding: Encoding,
+ format: LocListsFormat,
+}
+
+/// A raw entry in .debug_loclists.
+#[derive(Clone, Debug)]
+pub enum RawLocListEntry<R: Reader> {
+ /// A location from DWARF version <= 4.
+ AddressOrOffsetPair {
+ /// Start of range. May be an address or an offset.
+ begin: u64,
+ /// End of range. May be an address or an offset.
+ end: u64,
+ /// expression
+ data: Expression<R>,
+ },
+ /// DW_LLE_base_address
+ BaseAddress {
+ /// base address
+ addr: u64,
+ },
+ /// DW_LLE_base_addressx
+ BaseAddressx {
+ /// base address
+ addr: DebugAddrIndex<R::Offset>,
+ },
+ /// DW_LLE_startx_endx
+ StartxEndx {
+ /// start of range
+ begin: DebugAddrIndex<R::Offset>,
+ /// end of range
+ end: DebugAddrIndex<R::Offset>,
+ /// expression
+ data: Expression<R>,
+ },
+ /// DW_LLE_startx_length
+ StartxLength {
+ /// start of range
+ begin: DebugAddrIndex<R::Offset>,
+ /// length of range
+ length: u64,
+ /// expression
+ data: Expression<R>,
+ },
+ /// DW_LLE_offset_pair
+ OffsetPair {
+ /// start of range
+ begin: u64,
+ /// end of range
+ end: u64,
+ /// expression
+ data: Expression<R>,
+ },
+ /// DW_LLE_default_location
+ DefaultLocation {
+ /// expression
+ data: Expression<R>,
+ },
+ /// DW_LLE_start_end
+ StartEnd {
+ /// start of range
+ begin: u64,
+ /// end of range
+ end: u64,
+ /// expression
+ data: Expression<R>,
+ },
+ /// DW_LLE_start_length
+ StartLength {
+ /// start of range
+ begin: u64,
+ /// length of range
+ length: u64,
+ /// expression
+ data: Expression<R>,
+ },
+}
+
+fn parse_data<R: Reader>(input: &mut R, encoding: Encoding) -> Result<Expression<R>> {
+ if encoding.version >= 5 {
+ let len = R::Offset::from_u64(input.read_uleb128()?)?;
+ Ok(Expression(input.split(len)?))
+ } else {
+ // In the GNU split-dwarf extension this is a fixed 2 byte value.
+ let len = R::Offset::from_u16(input.read_u16()?);
+ Ok(Expression(input.split(len)?))
+ }
+}
+
+impl<R: Reader> RawLocListEntry<R> {
+ /// Parse a location list entry from `.debug_loclists`
+ fn parse(input: &mut R, encoding: Encoding, format: LocListsFormat) -> Result<Option<Self>> {
+ match format {
+ LocListsFormat::Bare => {
+ let range = RawRange::parse(input, encoding.address_size)?;
+ return Ok(if range.is_end() {
+ None
+ } else if range.is_base_address(encoding.address_size) {
+ Some(RawLocListEntry::BaseAddress { addr: range.end })
+ } else {
+ let len = R::Offset::from_u16(input.read_u16()?);
+ let data = Expression(input.split(len)?);
+ Some(RawLocListEntry::AddressOrOffsetPair {
+ begin: range.begin,
+ end: range.end,
+ data,
+ })
+ });
+ }
+ LocListsFormat::LLE => Ok(match constants::DwLle(input.read_u8()?) {
+ constants::DW_LLE_end_of_list => None,
+ constants::DW_LLE_base_addressx => Some(RawLocListEntry::BaseAddressx {
+ addr: DebugAddrIndex(input.read_uleb128().and_then(R::Offset::from_u64)?),
+ }),
+ constants::DW_LLE_startx_endx => Some(RawLocListEntry::StartxEndx {
+ begin: DebugAddrIndex(input.read_uleb128().and_then(R::Offset::from_u64)?),
+ end: DebugAddrIndex(input.read_uleb128().and_then(R::Offset::from_u64)?),
+ data: parse_data(input, encoding)?,
+ }),
+ constants::DW_LLE_startx_length => Some(RawLocListEntry::StartxLength {
+ begin: DebugAddrIndex(input.read_uleb128().and_then(R::Offset::from_u64)?),
+ length: if encoding.version >= 5 {
+ input.read_uleb128()?
+ } else {
+ // In the GNU split-dwarf extension this is a fixed 4 byte value.
+ input.read_u32()? as u64
+ },
+ data: parse_data(input, encoding)?,
+ }),
+ constants::DW_LLE_offset_pair => Some(RawLocListEntry::OffsetPair {
+ begin: input.read_uleb128()?,
+ end: input.read_uleb128()?,
+ data: parse_data(input, encoding)?,
+ }),
+ constants::DW_LLE_default_location => Some(RawLocListEntry::DefaultLocation {
+ data: parse_data(input, encoding)?,
+ }),
+ constants::DW_LLE_base_address => Some(RawLocListEntry::BaseAddress {
+ addr: input.read_address(encoding.address_size)?,
+ }),
+ constants::DW_LLE_start_end => Some(RawLocListEntry::StartEnd {
+ begin: input.read_address(encoding.address_size)?,
+ end: input.read_address(encoding.address_size)?,
+ data: parse_data(input, encoding)?,
+ }),
+ constants::DW_LLE_start_length => Some(RawLocListEntry::StartLength {
+ begin: input.read_address(encoding.address_size)?,
+ length: input.read_uleb128()?,
+ data: parse_data(input, encoding)?,
+ }),
+ _ => {
+ return Err(Error::InvalidAddressRange);
+ }
+ }),
+ }
+ }
+}
+
+impl<R: Reader> RawLocListIter<R> {
+ /// Construct a `RawLocListIter`.
+ fn new(input: R, encoding: Encoding, format: LocListsFormat) -> RawLocListIter<R> {
+ RawLocListIter {
+ input,
+ encoding,
+ format,
+ }
+ }
+
+ /// Advance the iterator to the next location.
+ pub fn next(&mut self) -> Result<Option<RawLocListEntry<R>>> {
+ if self.input.is_empty() {
+ return Ok(None);
+ }
+
+ match RawLocListEntry::parse(&mut self.input, self.encoding, self.format) {
+ Ok(entry) => {
+ if entry.is_none() {
+ self.input.empty();
+ }
+ Ok(entry)
+ }
+ Err(e) => {
+ self.input.empty();
+ Err(e)
+ }
+ }
+ }
+}
+
+#[cfg(feature = "fallible-iterator")]
+impl<R: Reader> fallible_iterator::FallibleIterator for RawLocListIter<R> {
+ type Item = RawLocListEntry<R>;
+ type Error = Error;
+
+ fn next(&mut self) -> ::core::result::Result<Option<Self::Item>, Self::Error> {
+ RawLocListIter::next(self)
+ }
+}
+
+/// An iterator over a location list.
+///
+/// This iterator internally handles processing of base address selection entries
+/// and list end entries. Thus, it only returns location entries that are valid
+/// and already adjusted for the base address.
+#[derive(Debug)]
+pub struct LocListIter<R: Reader> {
+ raw: RawLocListIter<R>,
+ base_address: u64,
+ debug_addr: DebugAddr<R>,
+ debug_addr_base: DebugAddrBase<R::Offset>,
+}
+
+impl<R: Reader> LocListIter<R> {
+ /// Construct a `LocListIter`.
+ fn new(
+ raw: RawLocListIter<R>,
+ base_address: u64,
+ debug_addr: DebugAddr<R>,
+ debug_addr_base: DebugAddrBase<R::Offset>,
+ ) -> LocListIter<R> {
+ LocListIter {
+ raw,
+ base_address,
+ debug_addr,
+ debug_addr_base,
+ }
+ }
+
+ #[inline]
+ fn get_address(&self, index: DebugAddrIndex<R::Offset>) -> Result<u64> {
+ self.debug_addr
+ .get_address(self.raw.encoding.address_size, self.debug_addr_base, index)
+ }
+
+ /// Advance the iterator to the next location.
+ pub fn next(&mut self) -> Result<Option<LocationListEntry<R>>> {
+ loop {
+ let raw_loc = match self.raw.next()? {
+ Some(loc) => loc,
+ None => return Ok(None),
+ };
+
+ let (range, data) = match raw_loc {
+ RawLocListEntry::BaseAddress { addr } => {
+ self.base_address = addr;
+ continue;
+ }
+ RawLocListEntry::BaseAddressx { addr } => {
+ self.base_address = self.get_address(addr)?;
+ continue;
+ }
+ RawLocListEntry::StartxEndx { begin, end, data } => {
+ let begin = self.get_address(begin)?;
+ let end = self.get_address(end)?;
+ (Range { begin, end }, data)
+ }
+ RawLocListEntry::StartxLength {
+ begin,
+ length,
+ data,
+ } => {
+ let begin = self.get_address(begin)?;
+ let end = begin + length;
+ (Range { begin, end }, data)
+ }
+ RawLocListEntry::DefaultLocation { data } => (
+ Range {
+ begin: 0,
+ end: u64::max_value(),
+ },
+ data,
+ ),
+ RawLocListEntry::AddressOrOffsetPair { begin, end, data }
+ | RawLocListEntry::OffsetPair { begin, end, data } => {
+ let mut range = Range { begin, end };
+ range.add_base_address(self.base_address, self.raw.encoding.address_size);
+ (range, data)
+ }
+ RawLocListEntry::StartEnd { begin, end, data } => (Range { begin, end }, data),
+ RawLocListEntry::StartLength {
+ begin,
+ length,
+ data,
+ } => (
+ Range {
+ begin,
+ end: begin + length,
+ },
+ data,
+ ),
+ };
+
+ if range.begin > range.end {
+ self.raw.input.empty();
+ return Err(Error::InvalidLocationAddressRange);
+ }
+
+ return Ok(Some(LocationListEntry { range, data }));
+ }
+ }
+}
+
+#[cfg(feature = "fallible-iterator")]
+impl<R: Reader> fallible_iterator::FallibleIterator for LocListIter<R> {
+ type Item = LocationListEntry<R>;
+ type Error = Error;
+
+ fn next(&mut self) -> ::core::result::Result<Option<Self::Item>, Self::Error> {
+ LocListIter::next(self)
+ }
+}
+
+/// A location list entry from the `.debug_loc` or `.debug_loclists` sections.
+#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
+pub struct LocationListEntry<R: Reader> {
+ /// The address range that this location is valid for.
+ pub range: Range,
+
+ /// The data containing a single location description.
+ pub data: Expression<R>,
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+ use crate::common::Format;
+ use crate::endianity::LittleEndian;
+ use crate::read::{EndianSlice, Range};
+ use crate::test_util::GimliSectionMethods;
+ use test_assembler::{Endian, Label, LabelMaker, Section};
+
+ #[test]
+ fn test_loclists_32() {
+ let encoding = Encoding {
+ format: Format::Dwarf32,
+ version: 5,
+ address_size: 4,
+ };
+
+ let section = Section::with_endian(Endian::Little)
+ .L32(0x0300_0000)
+ .L32(0x0301_0300)
+ .L32(0x0301_0400)
+ .L32(0x0301_0500);
+ let buf = section.get_contents().unwrap();
+ let debug_addr = &DebugAddr::from(EndianSlice::new(&buf, LittleEndian));
+ let debug_addr_base = DebugAddrBase(0);
+
+ let start = Label::new();
+ let first = Label::new();
+ let size = Label::new();
+ #[rustfmt::skip]
+ let section = Section::with_endian(Endian::Little)
+ // Header
+ .mark(&start)
+ .L32(&size)
+ .L16(encoding.version)
+ .L8(encoding.address_size)
+ .L8(0)
+ .L32(0)
+ .mark(&first)
+ // OffsetPair
+ .L8(4).uleb(0x10200).uleb(0x10300).uleb(4).L32(2)
+ // A base address selection followed by an OffsetPair.
+ .L8(6).L32(0x0200_0000)
+ .L8(4).uleb(0x10400).uleb(0x10500).uleb(4).L32(3)
+ // An empty OffsetPair followed by a normal OffsetPair.
+ .L8(4).uleb(0x10600).uleb(0x10600).uleb(4).L32(4)
+ .L8(4).uleb(0x10800).uleb(0x10900).uleb(4).L32(5)
+ // A StartEnd
+ .L8(7).L32(0x201_0a00).L32(0x201_0b00).uleb(4).L32(6)
+ // A StartLength
+ .L8(8).L32(0x201_0c00).uleb(0x100).uleb(4).L32(7)
+ // An OffsetPair that starts at 0.
+ .L8(4).uleb(0).uleb(1).uleb(4).L32(8)
+ // An OffsetPair that ends at -1.
+ .L8(6).L32(0)
+ .L8(4).uleb(0).uleb(0xffff_ffff).uleb(4).L32(9)
+ // A DefaultLocation
+ .L8(5).uleb(4).L32(10)
+ // A BaseAddressx + OffsetPair
+ .L8(1).uleb(0)
+ .L8(4).uleb(0x10100).uleb(0x10200).uleb(4).L32(11)
+ // A StartxEndx
+ .L8(2).uleb(1).uleb(2).uleb(4).L32(12)
+ // A StartxLength
+ .L8(3).uleb(3).uleb(0x100).uleb(4).L32(13)
+ // A range end.
+ .L8(0)
+ // Some extra data.
+ .L32(0xffff_ffff);
+ size.set_const((&section.here() - &start - 4) as u64);
+
+ let buf = section.get_contents().unwrap();
+ let debug_loc = DebugLoc::new(&[], LittleEndian);
+ let debug_loclists = DebugLocLists::new(&buf, LittleEndian);
+ let loclists = LocationLists::new(debug_loc, debug_loclists);
+ let offset = LocationListsOffset((&first - &start) as usize);
+ let mut locations = loclists
+ .locations(offset, encoding, 0x0100_0000, debug_addr, debug_addr_base)
+ .unwrap();
+
+ // A normal location.
+ assert_eq!(
+ locations.next(),
+ Ok(Some(LocationListEntry {
+ range: Range {
+ begin: 0x0101_0200,
+ end: 0x0101_0300,
+ },
+ data: Expression(EndianSlice::new(&[2, 0, 0, 0], LittleEndian)),
+ }))
+ );
+
+ // A base address selection followed by a normal location.
+ assert_eq!(
+ locations.next(),
+ Ok(Some(LocationListEntry {
+ range: Range {
+ begin: 0x0201_0400,
+ end: 0x0201_0500,
+ },
+ data: Expression(EndianSlice::new(&[3, 0, 0, 0], LittleEndian)),
+ }))
+ );
+
+ // An empty location range followed by a normal location.
+ assert_eq!(
+ locations.next(),
+ Ok(Some(LocationListEntry {
+ range: Range {
+ begin: 0x0201_0600,
+ end: 0x0201_0600,
+ },
+ data: Expression(EndianSlice::new(&[4, 0, 0, 0], LittleEndian)),
+ }))
+ );
+ assert_eq!(
+ locations.next(),
+ Ok(Some(LocationListEntry {
+ range: Range {
+ begin: 0x0201_0800,
+ end: 0x0201_0900,
+ },
+ data: Expression(EndianSlice::new(&[5, 0, 0, 0], LittleEndian)),
+ }))
+ );
+
+ // A normal location.
+ assert_eq!(
+ locations.next(),
+ Ok(Some(LocationListEntry {
+ range: Range {
+ begin: 0x0201_0a00,
+ end: 0x0201_0b00,
+ },
+ data: Expression(EndianSlice::new(&[6, 0, 0, 0], LittleEndian)),
+ }))
+ );
+
+ // A normal location.
+ assert_eq!(
+ locations.next(),
+ Ok(Some(LocationListEntry {
+ range: Range {
+ begin: 0x0201_0c00,
+ end: 0x0201_0d00,
+ },
+ data: Expression(EndianSlice::new(&[7, 0, 0, 0], LittleEndian)),
+ }))
+ );
+
+ // A location range that starts at 0.
+ assert_eq!(
+ locations.next(),
+ Ok(Some(LocationListEntry {
+ range: Range {
+ begin: 0x0200_0000,
+ end: 0x0200_0001,
+ },
+ data: Expression(EndianSlice::new(&[8, 0, 0, 0], LittleEndian)),
+ }))
+ );
+
+ // A location range that ends at -1.
+ assert_eq!(
+ locations.next(),
+ Ok(Some(LocationListEntry {
+ range: Range {
+ begin: 0x0000_0000,
+ end: 0xffff_ffff,
+ },
+ data: Expression(EndianSlice::new(&[9, 0, 0, 0], LittleEndian)),
+ }))
+ );
+
+ // A DefaultLocation.
+ assert_eq!(
+ locations.next(),
+ Ok(Some(LocationListEntry {
+ range: Range {
+ begin: 0,
+ end: u64::max_value(),
+ },
+ data: Expression(EndianSlice::new(&[10, 0, 0, 0], LittleEndian)),
+ }))
+ );
+
+ // A BaseAddressx + OffsetPair
+ assert_eq!(
+ locations.next(),
+ Ok(Some(LocationListEntry {
+ range: Range {
+ begin: 0x0301_0100,
+ end: 0x0301_0200,
+ },
+ data: Expression(EndianSlice::new(&[11, 0, 0, 0], LittleEndian)),
+ }))
+ );
+
+ // A StartxEndx
+ assert_eq!(
+ locations.next(),
+ Ok(Some(LocationListEntry {
+ range: Range {
+ begin: 0x0301_0300,
+ end: 0x0301_0400,
+ },
+ data: Expression(EndianSlice::new(&[12, 0, 0, 0], LittleEndian)),
+ }))
+ );
+
+ // A StartxLength
+ assert_eq!(
+ locations.next(),
+ Ok(Some(LocationListEntry {
+ range: Range {
+ begin: 0x0301_0500,
+ end: 0x0301_0600,
+ },
+ data: Expression(EndianSlice::new(&[13, 0, 0, 0], LittleEndian)),
+ }))
+ );
+
+ // A location list end.
+ assert_eq!(locations.next(), Ok(None));
+
+ // An offset at the end of buf.
+ let mut locations = loclists
+ .locations(
+ LocationListsOffset(buf.len()),
+ encoding,
+ 0x0100_0000,
+ debug_addr,
+ debug_addr_base,
+ )
+ .unwrap();
+ assert_eq!(locations.next(), Ok(None));
+ }
+
+ #[test]
+ fn test_loclists_64() {
+ let encoding = Encoding {
+ format: Format::Dwarf64,
+ version: 5,
+ address_size: 8,
+ };
+
+ let section = Section::with_endian(Endian::Little)
+ .L64(0x0300_0000)
+ .L64(0x0301_0300)
+ .L64(0x0301_0400)
+ .L64(0x0301_0500);
+ let buf = section.get_contents().unwrap();
+ let debug_addr = &DebugAddr::from(EndianSlice::new(&buf, LittleEndian));
+ let debug_addr_base = DebugAddrBase(0);
+
+ let start = Label::new();
+ let first = Label::new();
+ let size = Label::new();
+ #[rustfmt::skip]
+ let section = Section::with_endian(Endian::Little)
+ // Header
+ .mark(&start)
+ .L32(0xffff_ffff)
+ .L64(&size)
+ .L16(encoding.version)
+ .L8(encoding.address_size)
+ .L8(0)
+ .L32(0)
+ .mark(&first)
+ // OffsetPair
+ .L8(4).uleb(0x10200).uleb(0x10300).uleb(4).L32(2)
+ // A base address selection followed by an OffsetPair.
+ .L8(6).L64(0x0200_0000)
+ .L8(4).uleb(0x10400).uleb(0x10500).uleb(4).L32(3)
+ // An empty OffsetPair followed by a normal OffsetPair.
+ .L8(4).uleb(0x10600).uleb(0x10600).uleb(4).L32(4)
+ .L8(4).uleb(0x10800).uleb(0x10900).uleb(4).L32(5)
+ // A StartEnd
+ .L8(7).L64(0x201_0a00).L64(0x201_0b00).uleb(4).L32(6)
+ // A StartLength
+ .L8(8).L64(0x201_0c00).uleb(0x100).uleb(4).L32(7)
+ // An OffsetPair that starts at 0.
+ .L8(4).uleb(0).uleb(1).uleb(4).L32(8)
+ // An OffsetPair that ends at -1.
+ .L8(6).L64(0)
+ .L8(4).uleb(0).uleb(0xffff_ffff).uleb(4).L32(9)
+ // A DefaultLocation
+ .L8(5).uleb(4).L32(10)
+ // A BaseAddressx + OffsetPair
+ .L8(1).uleb(0)
+ .L8(4).uleb(0x10100).uleb(0x10200).uleb(4).L32(11)
+ // A StartxEndx
+ .L8(2).uleb(1).uleb(2).uleb(4).L32(12)
+ // A StartxLength
+ .L8(3).uleb(3).uleb(0x100).uleb(4).L32(13)
+ // A range end.
+ .L8(0)
+ // Some extra data.
+ .L32(0xffff_ffff);
+ size.set_const((&section.here() - &start - 12) as u64);
+
+ let buf = section.get_contents().unwrap();
+ let debug_loc = DebugLoc::new(&[], LittleEndian);
+ let debug_loclists = DebugLocLists::new(&buf, LittleEndian);
+ let loclists = LocationLists::new(debug_loc, debug_loclists);
+ let offset = LocationListsOffset((&first - &start) as usize);
+ let mut locations = loclists
+ .locations(offset, encoding, 0x0100_0000, debug_addr, debug_addr_base)
+ .unwrap();
+
+ // A normal location.
+ assert_eq!(
+ locations.next(),
+ Ok(Some(LocationListEntry {
+ range: Range {
+ begin: 0x0101_0200,
+ end: 0x0101_0300,
+ },
+ data: Expression(EndianSlice::new(&[2, 0, 0, 0], LittleEndian)),
+ }))
+ );
+
+ // A base address selection followed by a normal location.
+ assert_eq!(
+ locations.next(),
+ Ok(Some(LocationListEntry {
+ range: Range {
+ begin: 0x0201_0400,
+ end: 0x0201_0500,
+ },
+ data: Expression(EndianSlice::new(&[3, 0, 0, 0], LittleEndian)),
+ }))
+ );
+
+ // An empty location range followed by a normal location.
+ assert_eq!(
+ locations.next(),
+ Ok(Some(LocationListEntry {
+ range: Range {
+ begin: 0x0201_0600,
+ end: 0x0201_0600,
+ },
+ data: Expression(EndianSlice::new(&[4, 0, 0, 0], LittleEndian)),
+ }))
+ );
+ assert_eq!(
+ locations.next(),
+ Ok(Some(LocationListEntry {
+ range: Range {
+ begin: 0x0201_0800,
+ end: 0x0201_0900,
+ },
+ data: Expression(EndianSlice::new(&[5, 0, 0, 0], LittleEndian)),
+ }))
+ );
+
+ // A normal location.
+ assert_eq!(
+ locations.next(),
+ Ok(Some(LocationListEntry {
+ range: Range {
+ begin: 0x0201_0a00,
+ end: 0x0201_0b00,
+ },
+ data: Expression(EndianSlice::new(&[6, 0, 0, 0], LittleEndian)),
+ }))
+ );
+
+ // A normal location.
+ assert_eq!(
+ locations.next(),
+ Ok(Some(LocationListEntry {
+ range: Range {
+ begin: 0x0201_0c00,
+ end: 0x0201_0d00,
+ },
+ data: Expression(EndianSlice::new(&[7, 0, 0, 0], LittleEndian)),
+ }))
+ );
+
+ // A location range that starts at 0.
+ assert_eq!(
+ locations.next(),
+ Ok(Some(LocationListEntry {
+ range: Range {
+ begin: 0x0200_0000,
+ end: 0x0200_0001,
+ },
+ data: Expression(EndianSlice::new(&[8, 0, 0, 0], LittleEndian)),
+ }))
+ );
+
+ // A location range that ends at -1.
+ assert_eq!(
+ locations.next(),
+ Ok(Some(LocationListEntry {
+ range: Range {
+ begin: 0x0000_0000,
+ end: 0xffff_ffff,
+ },
+ data: Expression(EndianSlice::new(&[9, 0, 0, 0], LittleEndian)),
+ }))
+ );
+
+ // A DefaultLocation.
+ assert_eq!(
+ locations.next(),
+ Ok(Some(LocationListEntry {
+ range: Range {
+ begin: 0,
+ end: u64::max_value(),
+ },
+ data: Expression(EndianSlice::new(&[10, 0, 0, 0], LittleEndian)),
+ }))
+ );
+
+ // A BaseAddressx + OffsetPair
+ assert_eq!(
+ locations.next(),
+ Ok(Some(LocationListEntry {
+ range: Range {
+ begin: 0x0301_0100,
+ end: 0x0301_0200,
+ },
+ data: Expression(EndianSlice::new(&[11, 0, 0, 0], LittleEndian)),
+ }))
+ );
+
+ // A StartxEndx
+ assert_eq!(
+ locations.next(),
+ Ok(Some(LocationListEntry {
+ range: Range {
+ begin: 0x0301_0300,
+ end: 0x0301_0400,
+ },
+ data: Expression(EndianSlice::new(&[12, 0, 0, 0], LittleEndian)),
+ }))
+ );
+
+ // A StartxLength
+ assert_eq!(
+ locations.next(),
+ Ok(Some(LocationListEntry {
+ range: Range {
+ begin: 0x0301_0500,
+ end: 0x0301_0600,
+ },
+ data: Expression(EndianSlice::new(&[13, 0, 0, 0], LittleEndian)),
+ }))
+ );
+
+ // A location list end.
+ assert_eq!(locations.next(), Ok(None));
+
+ // An offset at the end of buf.
+ let mut locations = loclists
+ .locations(
+ LocationListsOffset(buf.len()),
+ encoding,
+ 0x0100_0000,
+ debug_addr,
+ debug_addr_base,
+ )
+ .unwrap();
+ assert_eq!(locations.next(), Ok(None));
+ }
+
+ #[test]
+ fn test_location_list_32() {
+ let start = Label::new();
+ let first = Label::new();
+ #[rustfmt::skip]
+ let section = Section::with_endian(Endian::Little)
+ // A location before the offset.
+ .mark(&start)
+ .L32(0x10000).L32(0x10100).L16(4).L32(1)
+ .mark(&first)
+ // A normal location.
+ .L32(0x10200).L32(0x10300).L16(4).L32(2)
+ // A base address selection followed by a normal location.
+ .L32(0xffff_ffff).L32(0x0200_0000)
+ .L32(0x10400).L32(0x10500).L16(4).L32(3)
+ // An empty location range followed by a normal location.
+ .L32(0x10600).L32(0x10600).L16(4).L32(4)
+ .L32(0x10800).L32(0x10900).L16(4).L32(5)
+ // A location range that starts at 0.
+ .L32(0).L32(1).L16(4).L32(6)
+ // A location range that ends at -1.
+ .L32(0xffff_ffff).L32(0x0000_0000)
+ .L32(0).L32(0xffff_ffff).L16(4).L32(7)
+ // A location list end.
+ .L32(0).L32(0)
+ // Some extra data.
+ .L32(0);
+
+ let buf = section.get_contents().unwrap();
+ let debug_loc = DebugLoc::new(&buf, LittleEndian);
+ let debug_loclists = DebugLocLists::new(&[], LittleEndian);
+ let loclists = LocationLists::new(debug_loc, debug_loclists);
+ let offset = LocationListsOffset((&first - &start) as usize);
+ let debug_addr = &DebugAddr::from(EndianSlice::new(&[], LittleEndian));
+ let debug_addr_base = DebugAddrBase(0);
+ let encoding = Encoding {
+ format: Format::Dwarf32,
+ version: 4,
+ address_size: 4,
+ };
+ let mut locations = loclists
+ .locations(offset, encoding, 0x0100_0000, debug_addr, debug_addr_base)
+ .unwrap();
+
+ // A normal location.
+ assert_eq!(
+ locations.next(),
+ Ok(Some(LocationListEntry {
+ range: Range {
+ begin: 0x0101_0200,
+ end: 0x0101_0300,
+ },
+ data: Expression(EndianSlice::new(&[2, 0, 0, 0], LittleEndian)),
+ }))
+ );
+
+ // A base address selection followed by a normal location.
+ assert_eq!(
+ locations.next(),
+ Ok(Some(LocationListEntry {
+ range: Range {
+ begin: 0x0201_0400,
+ end: 0x0201_0500,
+ },
+ data: Expression(EndianSlice::new(&[3, 0, 0, 0], LittleEndian)),
+ }))
+ );
+
+ // An empty location range followed by a normal location.
+ assert_eq!(
+ locations.next(),
+ Ok(Some(LocationListEntry {
+ range: Range {
+ begin: 0x0201_0600,
+ end: 0x0201_0600,
+ },
+ data: Expression(EndianSlice::new(&[4, 0, 0, 0], LittleEndian)),
+ }))
+ );
+ assert_eq!(
+ locations.next(),
+ Ok(Some(LocationListEntry {
+ range: Range {
+ begin: 0x0201_0800,
+ end: 0x0201_0900,
+ },
+ data: Expression(EndianSlice::new(&[5, 0, 0, 0], LittleEndian)),
+ }))
+ );
+
+ // A location range that starts at 0.
+ assert_eq!(
+ locations.next(),
+ Ok(Some(LocationListEntry {
+ range: Range {
+ begin: 0x0200_0000,
+ end: 0x0200_0001,
+ },
+ data: Expression(EndianSlice::new(&[6, 0, 0, 0], LittleEndian)),
+ }))
+ );
+
+ // A location range that ends at -1.
+ assert_eq!(
+ locations.next(),
+ Ok(Some(LocationListEntry {
+ range: Range {
+ begin: 0x0000_0000,
+ end: 0xffff_ffff,
+ },
+ data: Expression(EndianSlice::new(&[7, 0, 0, 0], LittleEndian)),
+ }))
+ );
+
+ // A location list end.
+ assert_eq!(locations.next(), Ok(None));
+
+ // An offset at the end of buf.
+ let mut locations = loclists
+ .locations(
+ LocationListsOffset(buf.len()),
+ encoding,
+ 0x0100_0000,
+ debug_addr,
+ debug_addr_base,
+ )
+ .unwrap();
+ assert_eq!(locations.next(), Ok(None));
+ }
+
+ #[test]
+ fn test_location_list_64() {
+ let start = Label::new();
+ let first = Label::new();
+ #[rustfmt::skip]
+ let section = Section::with_endian(Endian::Little)
+ // A location before the offset.
+ .mark(&start)
+ .L64(0x10000).L64(0x10100).L16(4).L32(1)
+ .mark(&first)
+ // A normal location.
+ .L64(0x10200).L64(0x10300).L16(4).L32(2)
+ // A base address selection followed by a normal location.
+ .L64(0xffff_ffff_ffff_ffff).L64(0x0200_0000)
+ .L64(0x10400).L64(0x10500).L16(4).L32(3)
+ // An empty location range followed by a normal location.
+ .L64(0x10600).L64(0x10600).L16(4).L32(4)
+ .L64(0x10800).L64(0x10900).L16(4).L32(5)
+ // A location range that starts at 0.
+ .L64(0).L64(1).L16(4).L32(6)
+ // A location range that ends at -1.
+ .L64(0xffff_ffff_ffff_ffff).L64(0x0000_0000)
+ .L64(0).L64(0xffff_ffff_ffff_ffff).L16(4).L32(7)
+ // A location list end.
+ .L64(0).L64(0)
+ // Some extra data.
+ .L64(0);
+
+ let buf = section.get_contents().unwrap();
+ let debug_loc = DebugLoc::new(&buf, LittleEndian);
+ let debug_loclists = DebugLocLists::new(&[], LittleEndian);
+ let loclists = LocationLists::new(debug_loc, debug_loclists);
+ let offset = LocationListsOffset((&first - &start) as usize);
+ let debug_addr = &DebugAddr::from(EndianSlice::new(&[], LittleEndian));
+ let debug_addr_base = DebugAddrBase(0);
+ let encoding = Encoding {
+ format: Format::Dwarf64,
+ version: 4,
+ address_size: 8,
+ };
+ let mut locations = loclists
+ .locations(offset, encoding, 0x0100_0000, debug_addr, debug_addr_base)
+ .unwrap();
+
+ // A normal location.
+ assert_eq!(
+ locations.next(),
+ Ok(Some(LocationListEntry {
+ range: Range {
+ begin: 0x0101_0200,
+ end: 0x0101_0300,
+ },
+ data: Expression(EndianSlice::new(&[2, 0, 0, 0], LittleEndian)),
+ }))
+ );
+
+ // A base address selection followed by a normal location.
+ assert_eq!(
+ locations.next(),
+ Ok(Some(LocationListEntry {
+ range: Range {
+ begin: 0x0201_0400,
+ end: 0x0201_0500,
+ },
+ data: Expression(EndianSlice::new(&[3, 0, 0, 0], LittleEndian)),
+ }))
+ );
+
+ // An empty location range followed by a normal location.
+ assert_eq!(
+ locations.next(),
+ Ok(Some(LocationListEntry {
+ range: Range {
+ begin: 0x0201_0600,
+ end: 0x0201_0600,
+ },
+ data: Expression(EndianSlice::new(&[4, 0, 0, 0], LittleEndian)),
+ }))
+ );
+ assert_eq!(
+ locations.next(),
+ Ok(Some(LocationListEntry {
+ range: Range {
+ begin: 0x0201_0800,
+ end: 0x0201_0900,
+ },
+ data: Expression(EndianSlice::new(&[5, 0, 0, 0], LittleEndian)),
+ }))
+ );
+
+ // A location range that starts at 0.
+ assert_eq!(
+ locations.next(),
+ Ok(Some(LocationListEntry {
+ range: Range {
+ begin: 0x0200_0000,
+ end: 0x0200_0001,
+ },
+ data: Expression(EndianSlice::new(&[6, 0, 0, 0], LittleEndian)),
+ }))
+ );
+
+ // A location range that ends at -1.
+ assert_eq!(
+ locations.next(),
+ Ok(Some(LocationListEntry {
+ range: Range {
+ begin: 0x0,
+ end: 0xffff_ffff_ffff_ffff,
+ },
+ data: Expression(EndianSlice::new(&[7, 0, 0, 0], LittleEndian)),
+ }))
+ );
+
+ // A location list end.
+ assert_eq!(locations.next(), Ok(None));
+
+ // An offset at the end of buf.
+ let mut locations = loclists
+ .locations(
+ LocationListsOffset(buf.len()),
+ encoding,
+ 0x0100_0000,
+ debug_addr,
+ debug_addr_base,
+ )
+ .unwrap();
+ assert_eq!(locations.next(), Ok(None));
+ }
+
+ #[test]
+ fn test_locations_invalid() {
+ #[rustfmt::skip]
+ let section = Section::with_endian(Endian::Little)
+ // An invalid location range.
+ .L32(0x20000).L32(0x10000).L16(4).L32(1)
+ // An invalid range after wrapping.
+ .L32(0x20000).L32(0xff01_0000).L16(4).L32(2);
+
+ let buf = section.get_contents().unwrap();
+ let debug_loc = DebugLoc::new(&buf, LittleEndian);
+ let debug_loclists = DebugLocLists::new(&[], LittleEndian);
+ let loclists = LocationLists::new(debug_loc, debug_loclists);
+ let debug_addr = &DebugAddr::from(EndianSlice::new(&[], LittleEndian));
+ let debug_addr_base = DebugAddrBase(0);
+ let encoding = Encoding {
+ format: Format::Dwarf32,
+ version: 4,
+ address_size: 4,
+ };
+
+ // An invalid location range.
+ let mut locations = loclists
+ .locations(
+ LocationListsOffset(0x0),
+ encoding,
+ 0x0100_0000,
+ debug_addr,
+ debug_addr_base,
+ )
+ .unwrap();
+ assert_eq!(locations.next(), Err(Error::InvalidLocationAddressRange));
+
+ // An invalid location range after wrapping.
+ let mut locations = loclists
+ .locations(
+ LocationListsOffset(14),
+ encoding,
+ 0x0100_0000,
+ debug_addr,
+ debug_addr_base,
+ )
+ .unwrap();
+ assert_eq!(locations.next(), Err(Error::InvalidLocationAddressRange));
+
+ // An invalid offset.
+ match loclists.locations(
+ LocationListsOffset(buf.len() + 1),
+ encoding,
+ 0x0100_0000,
+ debug_addr,
+ debug_addr_base,
+ ) {
+ Err(Error::UnexpectedEof(_)) => {}
+ otherwise => panic!("Unexpected result: {:?}", otherwise),
+ }
+ }
+
+ #[test]
+ fn test_get_offset() {
+ for format in vec![Format::Dwarf32, Format::Dwarf64] {
+ let encoding = Encoding {
+ format,
+ version: 5,
+ address_size: 4,
+ };
+
+ let zero = Label::new();
+ let length = Label::new();
+ let start = Label::new();
+ let first = Label::new();
+ let end = Label::new();
+ let mut section = Section::with_endian(Endian::Little)
+ .mark(&zero)
+ .initial_length(format, &length, &start)
+ .D16(encoding.version)
+ .D8(encoding.address_size)
+ .D8(0)
+ .D32(20)
+ .mark(&first);
+ for i in 0..20 {
+ section = section.word(format.word_size(), 1000 + i);
+ }
+ section = section.mark(&end);
+ length.set_const((&end - &start) as u64);
+ let section = section.get_contents().unwrap();
+
+ let debug_loc = DebugLoc::from(EndianSlice::new(&[], LittleEndian));
+ let debug_loclists = DebugLocLists::from(EndianSlice::new(&section, LittleEndian));
+ let locations = LocationLists::new(debug_loc, debug_loclists);
+
+ let base = DebugLocListsBase((&first - &zero) as usize);
+ assert_eq!(
+ locations.get_offset(encoding, base, DebugLocListsIndex(0)),
+ Ok(LocationListsOffset(base.0 + 1000))
+ );
+ assert_eq!(
+ locations.get_offset(encoding, base, DebugLocListsIndex(19)),
+ Ok(LocationListsOffset(base.0 + 1019))
+ );
+ }
+ }
+
+ #[test]
+ fn test_loclists_gnu_v4_split_dwarf() {
+ #[rustfmt::skip]
+ let buf = [
+ 0x03, // DW_LLE_startx_length
+ 0x00, // ULEB encoded b7
+ 0x08, 0x00, 0x00, 0x00, // Fixed 4 byte length of 8
+ 0x03, 0x00, // Fixed two byte length of the location
+ 0x11, 0x00, // DW_OP_constu 0
+ 0x9f, // DW_OP_stack_value
+ // Padding data
+ //0x99, 0x99, 0x99, 0x99
+ ];
+ let data_buf = [0x11, 0x00, 0x9f];
+ let expected_data = EndianSlice::new(&data_buf, LittleEndian);
+ let debug_loc = DebugLoc::new(&buf, LittleEndian);
+ let debug_loclists = DebugLocLists::new(&[], LittleEndian);
+ let loclists = LocationLists::new(debug_loc, debug_loclists);
+ let debug_addr =
+ &DebugAddr::from(EndianSlice::new(&[0x01, 0x02, 0x03, 0x04], LittleEndian));
+ let debug_addr_base = DebugAddrBase(0);
+ let encoding = Encoding {
+ format: Format::Dwarf32,
+ version: 4,
+ address_size: 4,
+ };
+
+ // An invalid location range.
+ let mut locations = loclists
+ .locations_dwo(
+ LocationListsOffset(0x0),
+ encoding,
+ 0,
+ debug_addr,
+ debug_addr_base,
+ )
+ .unwrap();
+ assert_eq!(
+ locations.next(),
+ Ok(Some(LocationListEntry {
+ range: Range {
+ begin: 0x0403_0201,
+ end: 0x0403_0209
+ },
+ data: Expression(expected_data),
+ }))
+ );
+ }
+}
diff --git a/vendor/gimli-0.26.2/src/read/lookup.rs b/vendor/gimli-0.26.2/src/read/lookup.rs
new file mode 100644
index 000000000..1d082f24f
--- /dev/null
+++ b/vendor/gimli-0.26.2/src/read/lookup.rs
@@ -0,0 +1,202 @@
+use core::marker::PhantomData;
+
+use crate::common::{DebugInfoOffset, Format};
+use crate::read::{parse_debug_info_offset, Error, Reader, ReaderOffset, Result, UnitOffset};
+
+// The various "Accelerated Access" sections (DWARF standard v4 Section 6.1) all have
+// similar structures. They consist of a header with metadata and an offset into the
+// .debug_info section for the entire compilation unit, and a series
+// of following entries that list addresses (for .debug_aranges) or names
+// (for .debug_pubnames and .debug_pubtypes) that are covered.
+//
+// Because these three tables all have similar structures, we abstract out some of
+// the parsing mechanics.
+
+pub trait LookupParser<R: Reader> {
+ /// The type of the produced header.
+ type Header;
+ /// The type of the produced entry.
+ type Entry;
+
+ /// Parse a header from `input`. Returns a tuple of `input` sliced to contain just the entries
+ /// corresponding to this header (without the header itself), and the parsed representation of
+ /// the header itself.
+ fn parse_header(input: &mut R) -> Result<(R, Self::Header)>;
+
+ /// Parse a single entry from `input`. Returns either a parsed representation of the entry
+ /// or None if `input` is exhausted.
+ fn parse_entry(input: &mut R, header: &Self::Header) -> Result<Option<Self::Entry>>;
+}
+
+#[derive(Clone, Debug)]
+pub struct DebugLookup<R, Parser>
+where
+ R: Reader,
+ Parser: LookupParser<R>,
+{
+ input_buffer: R,
+ phantom: PhantomData<Parser>,
+}
+
+impl<R, Parser> From<R> for DebugLookup<R, Parser>
+where
+ R: Reader,
+ Parser: LookupParser<R>,
+{
+ fn from(input_buffer: R) -> Self {
+ DebugLookup {
+ input_buffer,
+ phantom: PhantomData,
+ }
+ }
+}
+
+impl<R, Parser> DebugLookup<R, Parser>
+where
+ R: Reader,
+ Parser: LookupParser<R>,
+{
+ pub fn items(&self) -> LookupEntryIter<R, Parser> {
+ LookupEntryIter {
+ current_set: None,
+ remaining_input: self.input_buffer.clone(),
+ }
+ }
+
+ pub fn reader(&self) -> &R {
+ &self.input_buffer
+ }
+}
+
+#[derive(Clone, Debug)]
+pub struct LookupEntryIter<R, Parser>
+where
+ R: Reader,
+ Parser: LookupParser<R>,
+{
+ current_set: Option<(R, Parser::Header)>, // Only none at the very beginning and end.
+ remaining_input: R,
+}
+
+impl<R, Parser> LookupEntryIter<R, Parser>
+where
+ R: Reader,
+ Parser: LookupParser<R>,
+{
+ /// Advance the iterator and return the next entry.
+ ///
+ /// Returns the newly parsed entry as `Ok(Some(Parser::Entry))`. Returns
+ /// `Ok(None)` when iteration is complete and all entries have already been
+ /// parsed and yielded. If an error occurs while parsing the next entry,
+ /// then this error is returned as `Err(e)`, and all subsequent calls return
+ /// `Ok(None)`.
+ ///
+ /// Can be [used with `FallibleIterator`](./index.html#using-with-fallibleiterator).
+ pub fn next(&mut self) -> Result<Option<Parser::Entry>> {
+ loop {
+ if let Some((ref mut input, ref header)) = self.current_set {
+ if !input.is_empty() {
+ match Parser::parse_entry(input, header) {
+ Ok(Some(entry)) => return Ok(Some(entry)),
+ Ok(None) => {}
+ Err(e) => {
+ input.empty();
+ self.remaining_input.empty();
+ return Err(e);
+ }
+ }
+ }
+ }
+ if self.remaining_input.is_empty() {
+ self.current_set = None;
+ return Ok(None);
+ }
+ match Parser::parse_header(&mut self.remaining_input) {
+ Ok(set) => {
+ self.current_set = Some(set);
+ }
+ Err(e) => {
+ self.current_set = None;
+ self.remaining_input.empty();
+ return Err(e);
+ }
+ }
+ }
+ }
+}
+
+#[derive(Debug, Clone, PartialEq, Eq)]
+pub struct PubStuffHeader<T = usize> {
+ format: Format,
+ length: T,
+ version: u16,
+ unit_offset: DebugInfoOffset<T>,
+ unit_length: T,
+}
+
+pub trait PubStuffEntry<R: Reader> {
+ fn new(
+ die_offset: UnitOffset<R::Offset>,
+ name: R,
+ unit_header_offset: DebugInfoOffset<R::Offset>,
+ ) -> Self;
+}
+
+#[derive(Clone, Debug)]
+pub struct PubStuffParser<R, Entry>
+where
+ R: Reader,
+ Entry: PubStuffEntry<R>,
+{
+ // This struct is never instantiated.
+ phantom: PhantomData<(R, Entry)>,
+}
+
+impl<R, Entry> LookupParser<R> for PubStuffParser<R, Entry>
+where
+ R: Reader,
+ Entry: PubStuffEntry<R>,
+{
+ type Header = PubStuffHeader<R::Offset>;
+ type Entry = Entry;
+
+ /// Parse an pubthings set header. Returns a tuple of the
+ /// pubthings to be parsed for this set, and the newly created PubThingHeader struct.
+ fn parse_header(input: &mut R) -> Result<(R, Self::Header)> {
+ let (length, format) = input.read_initial_length()?;
+ let mut rest = input.split(length)?;
+
+ let version = rest.read_u16()?;
+ if version != 2 {
+ return Err(Error::UnknownVersion(u64::from(version)));
+ }
+
+ let unit_offset = parse_debug_info_offset(&mut rest, format)?;
+ let unit_length = rest.read_length(format)?;
+
+ let header = PubStuffHeader {
+ format,
+ length,
+ version,
+ unit_offset,
+ unit_length,
+ };
+ Ok((rest, header))
+ }
+
+ /// Parse a single pubthing. Return `None` for the null pubthing, `Some` for an actual pubthing.
+ fn parse_entry(input: &mut R, header: &Self::Header) -> Result<Option<Self::Entry>> {
+ let offset = input.read_offset(header.format)?;
+ if offset.into_u64() == 0 {
+ input.empty();
+ Ok(None)
+ } else {
+ let name = input.read_null_terminated_slice()?;
+ Ok(Some(Self::Entry::new(
+ UnitOffset(offset),
+ name,
+ header.unit_offset,
+ )))
+ }
+ }
+}
diff --git a/vendor/gimli-0.26.2/src/read/mod.rs b/vendor/gimli-0.26.2/src/read/mod.rs
new file mode 100644
index 000000000..3110957c2
--- /dev/null
+++ b/vendor/gimli-0.26.2/src/read/mod.rs
@@ -0,0 +1,821 @@
+//! Read DWARF debugging information.
+//!
+//! * [Example Usage](#example-usage)
+//! * [API Structure](#api-structure)
+//! * [Using with `FallibleIterator`](#using-with-fallibleiterator)
+//!
+//! ## Example Usage
+//!
+//! Print out all of the functions in the debuggee program:
+//!
+//! ```rust,no_run
+//! # fn example() -> Result<(), gimli::Error> {
+//! # type R = gimli::EndianSlice<'static, gimli::LittleEndian>;
+//! # let get_file_section_reader = |name| -> Result<R, gimli::Error> { unimplemented!() };
+//! # let get_sup_file_section_reader = |name| -> Result<R, gimli::Error> { unimplemented!() };
+//! // Read the DWARF sections with whatever object loader you're using.
+//! // These closures should return a `Reader` instance (e.g. `EndianSlice`).
+//! let loader = |section: gimli::SectionId| { get_file_section_reader(section.name()) };
+//! let sup_loader = |section: gimli::SectionId| { get_sup_file_section_reader(section.name()) };
+//! let mut dwarf = gimli::Dwarf::load(loader)?;
+//! dwarf.load_sup(sup_loader)?;
+//!
+//! // Iterate over all compilation units.
+//! let mut iter = dwarf.units();
+//! while let Some(header) = iter.next()? {
+//! // Parse the abbreviations and other information for this compilation unit.
+//! let unit = dwarf.unit(header)?;
+//!
+//! // Iterate over all of this compilation unit's entries.
+//! let mut entries = unit.entries();
+//! while let Some((_, entry)) = entries.next_dfs()? {
+//! // If we find an entry for a function, print it.
+//! if entry.tag() == gimli::DW_TAG_subprogram {
+//! println!("Found a function: {:?}", entry);
+//! }
+//! }
+//! }
+//! # unreachable!()
+//! # }
+//! ```
+//!
+//! Full example programs:
+//!
+//! * [A simple parser](https://github.com/gimli-rs/gimli/blob/master/examples/simple.rs)
+//!
+//! * [A `dwarfdump`
+//! clone](https://github.com/gimli-rs/gimli/blob/master/examples/dwarfdump.rs)
+//!
+//! * [An `addr2line` clone](https://github.com/gimli-rs/addr2line)
+//!
+//! * [`ddbug`](https://github.com/gimli-rs/ddbug), a utility giving insight into
+//! code generation by making debugging information readable
+//!
+//! * [`dwprod`](https://github.com/fitzgen/dwprod), a tiny utility to list the
+//! compilers used to create each compilation unit within a shared library or
+//! executable (via `DW_AT_producer`)
+//!
+//! * [`dwarf-validate`](https://github.com/gimli-rs/gimli/blob/master/examples/dwarf-validate.rs),
+//! a program to validate the integrity of some DWARF and its references
+//! between sections and compilation units.
+//!
+//! ## API Structure
+//!
+//! * Basic familiarity with DWARF is assumed.
+//!
+//! * The [`Dwarf`](./struct.Dwarf.html) type contains the commonly used DWARF
+//! sections. It has methods that simplify access to debugging data that spans
+//! multiple sections. Use of this type is optional, but recommended.
+//!
+//! * Each section gets its own type. Consider these types the entry points to
+//! the library:
+//!
+//! * [`DebugAbbrev`](./struct.DebugAbbrev.html): The `.debug_abbrev` section.
+//!
+//! * [`DebugAddr`](./struct.DebugAddr.html): The `.debug_addr` section.
+//!
+//! * [`DebugAranges`](./struct.DebugAranges.html): The `.debug_aranges`
+//! section.
+//!
+//! * [`DebugFrame`](./struct.DebugFrame.html): The `.debug_frame` section.
+//!
+//! * [`DebugInfo`](./struct.DebugInfo.html): The `.debug_info` section.
+//!
+//! * [`DebugLine`](./struct.DebugLine.html): The `.debug_line` section.
+//!
+//! * [`DebugLineStr`](./struct.DebugLineStr.html): The `.debug_line_str` section.
+//!
+//! * [`DebugLoc`](./struct.DebugLoc.html): The `.debug_loc` section.
+//!
+//! * [`DebugLocLists`](./struct.DebugLocLists.html): The `.debug_loclists` section.
+//!
+//! * [`DebugPubNames`](./struct.DebugPubNames.html): The `.debug_pubnames`
+//! section.
+//!
+//! * [`DebugPubTypes`](./struct.DebugPubTypes.html): The `.debug_pubtypes`
+//! section.
+//!
+//! * [`DebugRanges`](./struct.DebugRanges.html): The `.debug_ranges` section.
+//!
+//! * [`DebugRngLists`](./struct.DebugRngLists.html): The `.debug_rnglists` section.
+//!
+//! * [`DebugStr`](./struct.DebugStr.html): The `.debug_str` section.
+//!
+//! * [`DebugStrOffsets`](./struct.DebugStrOffsets.html): The `.debug_str_offsets` section.
+//!
+//! * [`DebugTypes`](./struct.DebugTypes.html): The `.debug_types` section.
+//!
+//! * [`DebugCuIndex`](./struct.DebugCuIndex.html): The `.debug_cu_index` section.
+//!
+//! * [`DebugTuIndex`](./struct.DebugTuIndex.html): The `.debug_tu_index` section.
+//!
+//! * [`EhFrame`](./struct.EhFrame.html): The `.eh_frame` section.
+//!
+//! * [`EhFrameHdr`](./struct.EhFrameHdr.html): The `.eh_frame_hdr` section.
+//!
+//! * Each section type exposes methods for accessing the debugging data encoded
+//! in that section. For example, the [`DebugInfo`](./struct.DebugInfo.html)
+//! struct has the [`units`](./struct.DebugInfo.html#method.units) method for
+//! iterating over the compilation units defined within it.
+//!
+//! * Offsets into a section are strongly typed: an offset into `.debug_info` is
+//! the [`DebugInfoOffset`](./struct.DebugInfoOffset.html) type. It cannot be
+//! used to index into the [`DebugLine`](./struct.DebugLine.html) type because
+//! `DebugLine` represents the `.debug_line` section. There are similar types
+//! for offsets relative to a compilation unit rather than a section.
+//!
+//! ## Using with `FallibleIterator`
+//!
+//! The standard library's `Iterator` trait and related APIs do not play well
+//! with iterators where the `next` operation is fallible. One can make the
+//! `Iterator`'s associated `Item` type be a `Result<T, E>`, however the
+//! provided methods cannot gracefully handle the case when an `Err` is
+//! returned.
+//!
+//! This situation led to the
+//! [`fallible-iterator`](https://crates.io/crates/fallible-iterator) crate's
+//! existence. You can read more of the rationale for its existence in its
+//! docs. The crate provides the helpers you have come to expect (eg `map`,
+//! `filter`, etc) for iterators that can fail.
+//!
+//! `gimli`'s many lazy parsing iterators are a perfect match for the
+//! `fallible-iterator` crate's `FallibleIterator` trait because parsing is not
+//! done eagerly. Parse errors later in the input might only be discovered after
+//! having iterated through many items.
+//!
+//! To use `gimli` iterators with `FallibleIterator`, import the crate and trait
+//! into your code:
+//!
+//! ```
+//! # #[cfg(feature = "fallible-iterator")]
+//! # fn foo() {
+//! // Use the `FallibleIterator` trait so its methods are in scope!
+//! use fallible_iterator::FallibleIterator;
+//! use gimli::{DebugAranges, EndianSlice, LittleEndian};
+//!
+//! fn find_sum_of_address_range_lengths(aranges: DebugAranges<EndianSlice<LittleEndian>>)
+//! -> gimli::Result<u64>
+//! {
+//! // `DebugAranges::headers` returns a `FallibleIterator`!
+//! aranges.headers()
+//! // `flat_map` is provided by `FallibleIterator`!
+//! .flat_map(|header| Ok(header.entries()))
+//! // `map` is provided by `FallibleIterator`!
+//! .map(|arange| Ok(arange.length()))
+//! // `fold` is provided by `FallibleIterator`!
+//! .fold(0, |sum, len| Ok(sum + len))
+//! }
+//! # }
+//! # fn main() {}
+//! ```
+
+use core::fmt::{self, Debug};
+use core::result;
+#[cfg(feature = "std")]
+use std::{error, io};
+
+use crate::common::{Register, SectionId};
+use crate::constants;
+
+mod util;
+pub use util::*;
+
+mod addr;
+pub use self::addr::*;
+
+mod cfi;
+pub use self::cfi::*;
+
+#[cfg(feature = "read")]
+mod dwarf;
+#[cfg(feature = "read")]
+pub use self::dwarf::*;
+
+mod endian_slice;
+pub use self::endian_slice::*;
+
+#[cfg(feature = "endian-reader")]
+mod endian_reader;
+#[cfg(feature = "endian-reader")]
+pub use self::endian_reader::*;
+
+mod reader;
+pub use self::reader::*;
+
+#[cfg(feature = "read")]
+mod abbrev;
+#[cfg(feature = "read")]
+pub use self::abbrev::*;
+
+mod aranges;
+pub use self::aranges::*;
+
+mod index;
+pub use self::index::*;
+
+#[cfg(feature = "read")]
+mod line;
+#[cfg(feature = "read")]
+pub use self::line::*;
+
+mod lists;
+
+mod loclists;
+pub use self::loclists::*;
+
+#[cfg(feature = "read")]
+mod lookup;
+
+mod op;
+pub use self::op::*;
+
+#[cfg(feature = "read")]
+mod pubnames;
+#[cfg(feature = "read")]
+pub use self::pubnames::*;
+
+#[cfg(feature = "read")]
+mod pubtypes;
+#[cfg(feature = "read")]
+pub use self::pubtypes::*;
+
+mod rnglists;
+pub use self::rnglists::*;
+
+mod str;
+pub use self::str::*;
+
+/// An offset into the current compilation or type unit.
+#[derive(Debug, Clone, Copy, PartialEq, Eq, Ord, PartialOrd, Hash)]
+pub struct UnitOffset<T = usize>(pub T);
+
+#[cfg(feature = "read")]
+mod unit;
+#[cfg(feature = "read")]
+pub use self::unit::*;
+
+mod value;
+pub use self::value::*;
+
+/// Indicates that storage should be allocated on heap.
+#[derive(Debug, Clone, Copy, PartialEq, Eq)]
+pub struct StoreOnHeap;
+
+/// `EndianBuf` has been renamed to `EndianSlice`. For ease of upgrading across
+/// `gimli` versions, we export this type alias.
+#[deprecated(note = "EndianBuf has been renamed to EndianSlice, use that instead.")]
+pub type EndianBuf<'input, Endian> = EndianSlice<'input, Endian>;
+
+/// An error that occurred when parsing.
+#[derive(Debug, Clone, Copy, PartialEq, Eq)]
+pub enum Error {
+ /// An I/O error occurred while reading.
+ Io,
+ /// Found a PC relative pointer, but the section base is undefined.
+ PcRelativePointerButSectionBaseIsUndefined,
+ /// Found a `.text` relative pointer, but the `.text` base is undefined.
+ TextRelativePointerButTextBaseIsUndefined,
+ /// Found a data relative pointer, but the data base is undefined.
+ DataRelativePointerButDataBaseIsUndefined,
+ /// Found a function relative pointer in a context that does not have a
+ /// function base.
+ FuncRelativePointerInBadContext,
+ /// Cannot parse a pointer with a `DW_EH_PE_omit` encoding.
+ CannotParseOmitPointerEncoding,
+ /// An error parsing an unsigned LEB128 value.
+ BadUnsignedLeb128,
+ /// An error parsing a signed LEB128 value.
+ BadSignedLeb128,
+ /// An abbreviation declared that its tag is zero, but zero is reserved for
+ /// null records.
+ AbbreviationTagZero,
+ /// An attribute specification declared that its form is zero, but zero is
+ /// reserved for null records.
+ AttributeFormZero,
+ /// The abbreviation's has-children byte was not one of
+ /// `DW_CHILDREN_{yes,no}`.
+ BadHasChildren,
+ /// The specified length is impossible.
+ BadLength,
+ /// Found an unknown `DW_FORM_*` type.
+ UnknownForm,
+ /// Expected a zero, found something else.
+ ExpectedZero,
+ /// Found an abbreviation code that has already been used.
+ DuplicateAbbreviationCode,
+ /// Found a duplicate arange.
+ DuplicateArange,
+ /// Found an unknown reserved length value.
+ UnknownReservedLength,
+ /// Found an unknown DWARF version.
+ UnknownVersion(u64),
+ /// Found a record with an unknown abbreviation code.
+ UnknownAbbreviation,
+ /// Hit the end of input before it was expected.
+ UnexpectedEof(ReaderOffsetId),
+ /// Read a null entry before it was expected.
+ UnexpectedNull,
+ /// Found an unknown standard opcode.
+ UnknownStandardOpcode(constants::DwLns),
+ /// Found an unknown extended opcode.
+ UnknownExtendedOpcode(constants::DwLne),
+ /// The specified address size is not supported.
+ UnsupportedAddressSize(u8),
+ /// The specified offset size is not supported.
+ UnsupportedOffsetSize(u8),
+ /// The specified field size is not supported.
+ UnsupportedFieldSize(u8),
+ /// The minimum instruction length must not be zero.
+ MinimumInstructionLengthZero,
+ /// The maximum operations per instruction must not be zero.
+ MaximumOperationsPerInstructionZero,
+ /// The line range must not be zero.
+ LineRangeZero,
+ /// The opcode base must not be zero.
+ OpcodeBaseZero,
+ /// Found an invalid UTF-8 string.
+ BadUtf8,
+ /// Expected to find the CIE ID, but found something else.
+ NotCieId,
+ /// Expected to find a pointer to a CIE, but found the CIE ID instead.
+ NotCiePointer,
+ /// Expected to find a pointer to an FDE, but found a CIE instead.
+ NotFdePointer,
+ /// Invalid branch target for a DW_OP_bra or DW_OP_skip.
+ BadBranchTarget(u64),
+ /// DW_OP_push_object_address used but no address passed in.
+ InvalidPushObjectAddress,
+ /// Not enough items on the stack when evaluating an expression.
+ NotEnoughStackItems,
+ /// Too many iterations to compute the expression.
+ TooManyIterations,
+ /// An unrecognized operation was found while parsing a DWARF
+ /// expression.
+ InvalidExpression(constants::DwOp),
+ /// An unsupported operation was found while evaluating a DWARF expression.
+ UnsupportedEvaluation,
+ /// The expression had a piece followed by an expression
+ /// terminator without a piece.
+ InvalidPiece,
+ /// An expression-terminating operation was followed by something
+ /// other than the end of the expression or a piece operation.
+ InvalidExpressionTerminator(u64),
+ /// Division or modulus by zero when evaluating an expression.
+ DivisionByZero,
+ /// An expression operation used mismatching types.
+ TypeMismatch,
+ /// An expression operation required an integral type but saw a
+ /// floating point type.
+ IntegralTypeRequired,
+ /// An expression operation used types that are not supported.
+ UnsupportedTypeOperation,
+ /// The shift value in an expression must be a non-negative integer.
+ InvalidShiftExpression,
+ /// An unknown DW_CFA_* instruction.
+ UnknownCallFrameInstruction(constants::DwCfa),
+ /// The end of an address range was before the beginning.
+ InvalidAddressRange,
+ /// The end offset of a loc list entry was before the beginning.
+ InvalidLocationAddressRange,
+ /// Encountered a call frame instruction in a context in which it is not
+ /// valid.
+ CfiInstructionInInvalidContext,
+ /// When evaluating call frame instructions, found a `DW_CFA_restore_state`
+ /// stack pop instruction, but the stack was empty, and had nothing to pop.
+ PopWithEmptyStack,
+ /// Do not have unwind info for the given address.
+ NoUnwindInfoForAddress,
+ /// An offset value was larger than the maximum supported value.
+ UnsupportedOffset,
+ /// The given pointer encoding is either unknown or invalid.
+ UnknownPointerEncoding,
+ /// Did not find an entry at the given offset.
+ NoEntryAtGivenOffset,
+ /// The given offset is out of bounds.
+ OffsetOutOfBounds,
+ /// Found an unknown CFI augmentation.
+ UnknownAugmentation,
+ /// We do not support the given pointer encoding yet.
+ UnsupportedPointerEncoding,
+ /// Registers larger than `u16` are not supported.
+ UnsupportedRegister(u64),
+ /// The CFI program defined more register rules than we have storage for.
+ TooManyRegisterRules,
+ /// Attempted to push onto the CFI or evaluation stack, but it was already
+ /// at full capacity.
+ StackFull,
+ /// The `.eh_frame_hdr` binary search table claims to be variable-length encoded,
+ /// which makes binary search impossible.
+ VariableLengthSearchTable,
+ /// The `DW_UT_*` value for this unit is not supported yet.
+ UnsupportedUnitType,
+ /// Ranges using AddressIndex are not supported yet.
+ UnsupportedAddressIndex,
+ /// Nonzero segment selector sizes aren't supported yet.
+ UnsupportedSegmentSize,
+ /// A compilation unit or type unit is missing its top level DIE.
+ MissingUnitDie,
+ /// A DIE attribute used an unsupported form.
+ UnsupportedAttributeForm,
+ /// Missing DW_LNCT_path in file entry format.
+ MissingFileEntryFormatPath,
+ /// Expected an attribute value to be a string form.
+ ExpectedStringAttributeValue,
+ /// `DW_FORM_implicit_const` used in an invalid context.
+ InvalidImplicitConst,
+ /// Invalid section count in `.dwp` index.
+ InvalidIndexSectionCount,
+ /// Invalid slot count in `.dwp` index.
+ InvalidIndexSlotCount,
+ /// Invalid hash row in `.dwp` index.
+ InvalidIndexRow,
+ /// Unknown section type in `.dwp` index.
+ UnknownIndexSection,
+}
+
+impl fmt::Display for Error {
+ #[inline]
+ fn fmt(&self, f: &mut fmt::Formatter) -> ::core::result::Result<(), fmt::Error> {
+ write!(f, "{}", self.description())
+ }
+}
+
+impl Error {
+ /// A short description of the error.
+ pub fn description(&self) -> &str {
+ match *self {
+ Error::Io => "An I/O error occurred while reading.",
+ Error::PcRelativePointerButSectionBaseIsUndefined => {
+ "Found a PC relative pointer, but the section base is undefined."
+ }
+ Error::TextRelativePointerButTextBaseIsUndefined => {
+ "Found a `.text` relative pointer, but the `.text` base is undefined."
+ }
+ Error::DataRelativePointerButDataBaseIsUndefined => {
+ "Found a data relative pointer, but the data base is undefined."
+ }
+ Error::FuncRelativePointerInBadContext => {
+ "Found a function relative pointer in a context that does not have a function base."
+ }
+ Error::CannotParseOmitPointerEncoding => {
+ "Cannot parse a pointer with a `DW_EH_PE_omit` encoding."
+ }
+ Error::BadUnsignedLeb128 => "An error parsing an unsigned LEB128 value",
+ Error::BadSignedLeb128 => "An error parsing a signed LEB128 value",
+ Error::AbbreviationTagZero => {
+ "An abbreviation declared that its tag is zero,
+ but zero is reserved for null records"
+ }
+ Error::AttributeFormZero => {
+ "An attribute specification declared that its form is zero,
+ but zero is reserved for null records"
+ }
+ Error::BadHasChildren => {
+ "The abbreviation's has-children byte was not one of
+ `DW_CHILDREN_{yes,no}`"
+ }
+ Error::BadLength => "The specified length is impossible",
+ Error::UnknownForm => "Found an unknown `DW_FORM_*` type",
+ Error::ExpectedZero => "Expected a zero, found something else",
+ Error::DuplicateAbbreviationCode => {
+ "Found an abbreviation code that has already been used"
+ }
+ Error::DuplicateArange => "Found a duplicate arange",
+ Error::UnknownReservedLength => "Found an unknown reserved length value",
+ Error::UnknownVersion(_) => "Found an unknown DWARF version",
+ Error::UnknownAbbreviation => "Found a record with an unknown abbreviation code",
+ Error::UnexpectedEof(_) => "Hit the end of input before it was expected",
+ Error::UnexpectedNull => "Read a null entry before it was expected.",
+ Error::UnknownStandardOpcode(_) => "Found an unknown standard opcode",
+ Error::UnknownExtendedOpcode(_) => "Found an unknown extended opcode",
+ Error::UnsupportedAddressSize(_) => "The specified address size is not supported",
+ Error::UnsupportedOffsetSize(_) => "The specified offset size is not supported",
+ Error::UnsupportedFieldSize(_) => "The specified field size is not supported",
+ Error::MinimumInstructionLengthZero => {
+ "The minimum instruction length must not be zero."
+ }
+ Error::MaximumOperationsPerInstructionZero => {
+ "The maximum operations per instruction must not be zero."
+ }
+ Error::LineRangeZero => "The line range must not be zero.",
+ Error::OpcodeBaseZero => "The opcode base must not be zero.",
+ Error::BadUtf8 => "Found an invalid UTF-8 string.",
+ Error::NotCieId => "Expected to find the CIE ID, but found something else.",
+ Error::NotCiePointer => "Expected to find a CIE pointer, but found the CIE ID instead.",
+ Error::NotFdePointer => {
+ "Expected to find an FDE pointer, but found a CIE pointer instead."
+ }
+ Error::BadBranchTarget(_) => "Invalid branch target in DWARF expression",
+ Error::InvalidPushObjectAddress => {
+ "DW_OP_push_object_address used but no object address given"
+ }
+ Error::NotEnoughStackItems => "Not enough items on stack when evaluating expression",
+ Error::TooManyIterations => "Too many iterations to evaluate DWARF expression",
+ Error::InvalidExpression(_) => "Invalid opcode in DWARF expression",
+ Error::UnsupportedEvaluation => "Unsupported operation when evaluating expression",
+ Error::InvalidPiece => {
+ "DWARF expression has piece followed by non-piece expression at end"
+ }
+ Error::InvalidExpressionTerminator(_) => "Expected DW_OP_piece or DW_OP_bit_piece",
+ Error::DivisionByZero => "Division or modulus by zero when evaluating expression",
+ Error::TypeMismatch => "Type mismatch when evaluating expression",
+ Error::IntegralTypeRequired => "Integral type expected when evaluating expression",
+ Error::UnsupportedTypeOperation => {
+ "An expression operation used types that are not supported"
+ }
+ Error::InvalidShiftExpression => {
+ "The shift value in an expression must be a non-negative integer."
+ }
+ Error::UnknownCallFrameInstruction(_) => "An unknown DW_CFA_* instructiion",
+ Error::InvalidAddressRange => {
+ "The end of an address range must not be before the beginning."
+ }
+ Error::InvalidLocationAddressRange => {
+ "The end offset of a location list entry must not be before the beginning."
+ }
+ Error::CfiInstructionInInvalidContext => {
+ "Encountered a call frame instruction in a context in which it is not valid."
+ }
+ Error::PopWithEmptyStack => {
+ "When evaluating call frame instructions, found a `DW_CFA_restore_state` stack pop \
+ instruction, but the stack was empty, and had nothing to pop."
+ }
+ Error::NoUnwindInfoForAddress => "Do not have unwind info for the given address.",
+ Error::UnsupportedOffset => {
+ "An offset value was larger than the maximum supported value."
+ }
+ Error::UnknownPointerEncoding => {
+ "The given pointer encoding is either unknown or invalid."
+ }
+ Error::NoEntryAtGivenOffset => "Did not find an entry at the given offset.",
+ Error::OffsetOutOfBounds => "The given offset is out of bounds.",
+ Error::UnknownAugmentation => "Found an unknown CFI augmentation.",
+ Error::UnsupportedPointerEncoding => {
+ "We do not support the given pointer encoding yet."
+ }
+ Error::UnsupportedRegister(_) => "Registers larger than `u16` are not supported.",
+ Error::TooManyRegisterRules => {
+ "The CFI program defined more register rules than we have storage for."
+ }
+ Error::StackFull => {
+ "Attempted to push onto the CFI stack, but it was already at full capacity."
+ }
+ Error::VariableLengthSearchTable => {
+ "The `.eh_frame_hdr` binary search table claims to be variable-length encoded, \
+ which makes binary search impossible."
+ }
+ Error::UnsupportedUnitType => "The `DW_UT_*` value for this unit is not supported yet",
+ Error::UnsupportedAddressIndex => "Ranges involving AddressIndex are not supported yet",
+ Error::UnsupportedSegmentSize => "Nonzero segment size not supported yet",
+ Error::MissingUnitDie => {
+ "A compilation unit or type unit is missing its top level DIE."
+ }
+ Error::UnsupportedAttributeForm => "A DIE attribute used an unsupported form.",
+ Error::MissingFileEntryFormatPath => "Missing DW_LNCT_path in file entry format.",
+ Error::ExpectedStringAttributeValue => {
+ "Expected an attribute value to be a string form."
+ }
+ Error::InvalidImplicitConst => "DW_FORM_implicit_const used in an invalid context.",
+ Error::InvalidIndexSectionCount => "Invalid section count in `.dwp` index.",
+ Error::InvalidIndexSlotCount => "Invalid slot count in `.dwp` index.",
+ Error::InvalidIndexRow => "Invalid hash row in `.dwp` index.",
+ Error::UnknownIndexSection => "Unknown section type in `.dwp` index.",
+ }
+ }
+}
+
+#[cfg(feature = "std")]
+impl error::Error for Error {}
+
+#[cfg(feature = "std")]
+impl From<io::Error> for Error {
+ fn from(_: io::Error) -> Self {
+ Error::Io
+ }
+}
+
+/// The result of a parse.
+pub type Result<T> = result::Result<T, Error>;
+
+/// A convenience trait for loading DWARF sections from object files. To be
+/// used like:
+///
+/// ```
+/// use gimli::{DebugInfo, EndianSlice, LittleEndian, Reader, Section};
+///
+/// let buf = [0x00, 0x01, 0x02, 0x03];
+/// let reader = EndianSlice::new(&buf, LittleEndian);
+/// let loader = |name| -> Result<_, ()> { Ok(reader) };
+///
+/// let debug_info: DebugInfo<_> = Section::load(loader).unwrap();
+/// ```
+pub trait Section<R>: From<R> {
+ /// Returns the section id for this type.
+ fn id() -> SectionId;
+
+ /// Returns the ELF section name for this type.
+ fn section_name() -> &'static str {
+ Self::id().name()
+ }
+
+ /// Returns the ELF section name (if any) for this type when used in a dwo
+ /// file.
+ fn dwo_section_name() -> Option<&'static str> {
+ Self::id().dwo_name()
+ }
+
+ /// Try to load the section using the given loader function.
+ fn load<F, E>(f: F) -> core::result::Result<Self, E>
+ where
+ F: FnOnce(SectionId) -> core::result::Result<R, E>,
+ {
+ f(Self::id()).map(From::from)
+ }
+
+ /// Returns the `Reader` for this section.
+ fn reader(&self) -> &R
+ where
+ R: Reader;
+
+ /// Returns the subrange of the section that is the contribution of
+ /// a unit in a `.dwp` file.
+ fn dwp_range(&self, offset: u32, size: u32) -> Result<Self>
+ where
+ R: Reader,
+ {
+ let mut data = self.reader().clone();
+ data.skip(R::Offset::from_u32(offset))?;
+ data.truncate(R::Offset::from_u32(size))?;
+ Ok(data.into())
+ }
+
+ /// Returns the `Reader` for this section.
+ fn lookup_offset_id(&self, id: ReaderOffsetId) -> Option<(SectionId, R::Offset)>
+ where
+ R: Reader,
+ {
+ self.reader()
+ .lookup_offset_id(id)
+ .map(|offset| (Self::id(), offset))
+ }
+}
+
+impl Register {
+ pub(crate) fn from_u64(x: u64) -> Result<Register> {
+ let y = x as u16;
+ if u64::from(y) == x {
+ Ok(Register(y))
+ } else {
+ Err(Error::UnsupportedRegister(x))
+ }
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+ use crate::common::Format;
+ use crate::endianity::LittleEndian;
+ use test_assembler::{Endian, Section};
+
+ #[test]
+ fn test_parse_initial_length_32_ok() {
+ let section = Section::with_endian(Endian::Little).L32(0x7856_3412);
+ let buf = section.get_contents().unwrap();
+
+ let input = &mut EndianSlice::new(&buf, LittleEndian);
+ match input.read_initial_length() {
+ Ok((length, format)) => {
+ assert_eq!(input.len(), 0);
+ assert_eq!(format, Format::Dwarf32);
+ assert_eq!(0x7856_3412, length);
+ }
+ otherwise => panic!("Unexpected result: {:?}", otherwise),
+ }
+ }
+
+ #[test]
+ fn test_parse_initial_length_64_ok() {
+ let section = Section::with_endian(Endian::Little)
+ // Dwarf_64_INITIAL_UNIT_LENGTH
+ .L32(0xffff_ffff)
+ // Actual length
+ .L64(0xffde_bc9a_7856_3412);
+ let buf = section.get_contents().unwrap();
+ let input = &mut EndianSlice::new(&buf, LittleEndian);
+
+ #[cfg(target_pointer_width = "64")]
+ match input.read_initial_length() {
+ Ok((length, format)) => {
+ assert_eq!(input.len(), 0);
+ assert_eq!(format, Format::Dwarf64);
+ assert_eq!(0xffde_bc9a_7856_3412, length);
+ }
+ otherwise => panic!("Unexpected result: {:?}", otherwise),
+ }
+
+ #[cfg(target_pointer_width = "32")]
+ match input.read_initial_length() {
+ Err(Error::UnsupportedOffset) => {}
+ otherwise => panic!("Unexpected result: {:?}", otherwise),
+ };
+ }
+
+ #[test]
+ fn test_parse_initial_length_unknown_reserved_value() {
+ let section = Section::with_endian(Endian::Little).L32(0xffff_fffe);
+ let buf = section.get_contents().unwrap();
+
+ let input = &mut EndianSlice::new(&buf, LittleEndian);
+ match input.read_initial_length() {
+ Err(Error::UnknownReservedLength) => assert!(true),
+ otherwise => panic!("Unexpected result: {:?}", otherwise),
+ };
+ }
+
+ #[test]
+ fn test_parse_initial_length_incomplete() {
+ let buf = [0xff, 0xff, 0xff]; // Need at least 4 bytes.
+
+ let input = &mut EndianSlice::new(&buf, LittleEndian);
+ match input.read_initial_length() {
+ Err(Error::UnexpectedEof(_)) => assert!(true),
+ otherwise => panic!("Unexpected result: {:?}", otherwise),
+ };
+ }
+
+ #[test]
+ fn test_parse_initial_length_64_incomplete() {
+ let section = Section::with_endian(Endian::Little)
+ // Dwarf_64_INITIAL_UNIT_LENGTH
+ .L32(0xffff_ffff)
+ // Actual length is not long enough.
+ .L32(0x7856_3412);
+ let buf = section.get_contents().unwrap();
+
+ let input = &mut EndianSlice::new(&buf, LittleEndian);
+ match input.read_initial_length() {
+ Err(Error::UnexpectedEof(_)) => assert!(true),
+ otherwise => panic!("Unexpected result: {:?}", otherwise),
+ };
+ }
+
+ #[test]
+ fn test_parse_offset_32() {
+ let section = Section::with_endian(Endian::Little).L32(0x0123_4567);
+ let buf = section.get_contents().unwrap();
+
+ let input = &mut EndianSlice::new(&buf, LittleEndian);
+ match input.read_offset(Format::Dwarf32) {
+ Ok(val) => {
+ assert_eq!(input.len(), 0);
+ assert_eq!(val, 0x0123_4567);
+ }
+ otherwise => panic!("Unexpected result: {:?}", otherwise),
+ };
+ }
+
+ #[test]
+ fn test_parse_offset_64_small() {
+ let section = Section::with_endian(Endian::Little).L64(0x0123_4567);
+ let buf = section.get_contents().unwrap();
+
+ let input = &mut EndianSlice::new(&buf, LittleEndian);
+ match input.read_offset(Format::Dwarf64) {
+ Ok(val) => {
+ assert_eq!(input.len(), 0);
+ assert_eq!(val, 0x0123_4567);
+ }
+ otherwise => panic!("Unexpected result: {:?}", otherwise),
+ };
+ }
+
+ #[test]
+ #[cfg(target_pointer_width = "64")]
+ fn test_parse_offset_64_large() {
+ let section = Section::with_endian(Endian::Little).L64(0x0123_4567_89ab_cdef);
+ let buf = section.get_contents().unwrap();
+
+ let input = &mut EndianSlice::new(&buf, LittleEndian);
+ match input.read_offset(Format::Dwarf64) {
+ Ok(val) => {
+ assert_eq!(input.len(), 0);
+ assert_eq!(val, 0x0123_4567_89ab_cdef);
+ }
+ otherwise => panic!("Unexpected result: {:?}", otherwise),
+ };
+ }
+
+ #[test]
+ #[cfg(target_pointer_width = "32")]
+ fn test_parse_offset_64_large() {
+ let section = Section::with_endian(Endian::Little).L64(0x0123_4567_89ab_cdef);
+ let buf = section.get_contents().unwrap();
+
+ let input = &mut EndianSlice::new(&buf, LittleEndian);
+ match input.read_offset(Format::Dwarf64) {
+ Err(Error::UnsupportedOffset) => assert!(true),
+ otherwise => panic!("Unexpected result: {:?}", otherwise),
+ };
+ }
+}
diff --git a/vendor/gimli-0.26.2/src/read/op.rs b/vendor/gimli-0.26.2/src/read/op.rs
new file mode 100644
index 000000000..88ea20297
--- /dev/null
+++ b/vendor/gimli-0.26.2/src/read/op.rs
@@ -0,0 +1,4114 @@
+//! Functions for parsing and evaluating DWARF expressions.
+
+#[cfg(feature = "read")]
+use alloc::vec::Vec;
+use core::mem;
+
+use super::util::{ArrayLike, ArrayVec};
+use crate::common::{DebugAddrIndex, DebugInfoOffset, Encoding, Register};
+use crate::constants;
+use crate::read::{Error, Reader, ReaderOffset, Result, StoreOnHeap, UnitOffset, Value, ValueType};
+
+/// A reference to a DIE, either relative to the current CU or
+/// relative to the section.
+#[derive(Debug, Clone, Copy, PartialEq, Eq)]
+pub enum DieReference<T = usize> {
+ /// A CU-relative reference.
+ UnitRef(UnitOffset<T>),
+ /// A section-relative reference.
+ DebugInfoRef(DebugInfoOffset<T>),
+}
+
+/// A single decoded DWARF expression operation.
+///
+/// DWARF expression evaluation is done in two parts: first the raw
+/// bytes of the next part of the expression are decoded; and then the
+/// decoded operation is evaluated. This approach lets other
+/// consumers inspect the DWARF expression without reimplementing the
+/// decoding operation.
+///
+/// Multiple DWARF opcodes may decode into a single `Operation`. For
+/// example, both `DW_OP_deref` and `DW_OP_xderef` are represented
+/// using `Operation::Deref`.
+#[derive(Debug, Clone, Copy, PartialEq, Eq)]
+pub enum Operation<R, Offset = <R as Reader>::Offset>
+where
+ R: Reader<Offset = Offset>,
+ Offset: ReaderOffset,
+{
+ /// Dereference the topmost value of the stack.
+ Deref {
+ /// The DIE of the base type or 0 to indicate the generic type
+ base_type: UnitOffset<Offset>,
+ /// The size of the data to dereference.
+ size: u8,
+ /// True if the dereference operation takes an address space
+ /// argument from the stack; false otherwise.
+ space: bool,
+ },
+ /// Drop an item from the stack.
+ Drop,
+ /// Pick an item from the stack and push it on top of the stack.
+ /// This operation handles `DW_OP_pick`, `DW_OP_dup`, and
+ /// `DW_OP_over`.
+ Pick {
+ /// The index, from the top of the stack, of the item to copy.
+ index: u8,
+ },
+ /// Swap the top two stack items.
+ Swap,
+ /// Rotate the top three stack items.
+ Rot,
+ /// Take the absolute value of the top of the stack.
+ Abs,
+ /// Bitwise `and` of the top two values on the stack.
+ And,
+ /// Divide the top two values on the stack.
+ Div,
+ /// Subtract the top two values on the stack.
+ Minus,
+ /// Modulus of the top two values on the stack.
+ Mod,
+ /// Multiply the top two values on the stack.
+ Mul,
+ /// Negate the top of the stack.
+ Neg,
+ /// Bitwise `not` of the top of the stack.
+ Not,
+ /// Bitwise `or` of the top two values on the stack.
+ Or,
+ /// Add the top two values on the stack.
+ Plus,
+ /// Add a constant to the topmost value on the stack.
+ PlusConstant {
+ /// The value to add.
+ value: u64,
+ },
+ /// Logical left shift of the 2nd value on the stack by the number
+ /// of bits given by the topmost value on the stack.
+ Shl,
+ /// Right shift of the 2nd value on the stack by the number of
+ /// bits given by the topmost value on the stack.
+ Shr,
+ /// Arithmetic left shift of the 2nd value on the stack by the
+ /// number of bits given by the topmost value on the stack.
+ Shra,
+ /// Bitwise `xor` of the top two values on the stack.
+ Xor,
+ /// Branch to the target location if the top of stack is nonzero.
+ Bra {
+ /// The relative offset to the target bytecode.
+ target: i16,
+ },
+ /// Compare the top two stack values for equality.
+ Eq,
+ /// Compare the top two stack values using `>=`.
+ Ge,
+ /// Compare the top two stack values using `>`.
+ Gt,
+ /// Compare the top two stack values using `<=`.
+ Le,
+ /// Compare the top two stack values using `<`.
+ Lt,
+ /// Compare the top two stack values using `!=`.
+ Ne,
+ /// Unconditional branch to the target location.
+ Skip {
+ /// The relative offset to the target bytecode.
+ target: i16,
+ },
+ /// Push an unsigned constant value on the stack. This handles multiple
+ /// DWARF opcodes.
+ UnsignedConstant {
+ /// The value to push.
+ value: u64,
+ },
+ /// Push a signed constant value on the stack. This handles multiple
+ /// DWARF opcodes.
+ SignedConstant {
+ /// The value to push.
+ value: i64,
+ },
+ /// Indicate that this piece's location is in the given register.
+ ///
+ /// Completes the piece or expression.
+ Register {
+ /// The register number.
+ register: Register,
+ },
+ /// Find the value of the given register, add the offset, and then
+ /// push the resulting sum on the stack.
+ RegisterOffset {
+ /// The register number.
+ register: Register,
+ /// The offset to add.
+ offset: i64,
+ /// The DIE of the base type or 0 to indicate the generic type
+ base_type: UnitOffset<Offset>,
+ },
+ /// Compute the frame base (using `DW_AT_frame_base`), add the
+ /// given offset, and then push the resulting sum on the stack.
+ FrameOffset {
+ /// The offset to add.
+ offset: i64,
+ },
+ /// No operation.
+ Nop,
+ /// Push the object address on the stack.
+ PushObjectAddress,
+ /// Evaluate a DWARF expression as a subroutine. The expression
+ /// comes from the `DW_AT_location` attribute of the indicated
+ /// DIE.
+ Call {
+ /// The DIE to use.
+ offset: DieReference<Offset>,
+ },
+ /// Compute the address of a thread-local variable and push it on
+ /// the stack.
+ TLS,
+ /// Compute the call frame CFA and push it on the stack.
+ CallFrameCFA,
+ /// Terminate a piece.
+ Piece {
+ /// The size of this piece in bits.
+ size_in_bits: u64,
+ /// The bit offset of this piece. If `None`, then this piece
+ /// was specified using `DW_OP_piece` and should start at the
+ /// next byte boundary.
+ bit_offset: Option<u64>,
+ },
+ /// The object has no location, but has a known constant value.
+ ///
+ /// Represents `DW_OP_implicit_value`.
+ /// Completes the piece or expression.
+ ImplicitValue {
+ /// The implicit value to use.
+ data: R,
+ },
+ /// The object has no location, but its value is at the top of the stack.
+ ///
+ /// Represents `DW_OP_stack_value`.
+ /// Completes the piece or expression.
+ StackValue,
+ /// The object is a pointer to a value which has no actual location,
+ /// such as an implicit value or a stack value.
+ ///
+ /// Represents `DW_OP_implicit_pointer`.
+ /// Completes the piece or expression.
+ ImplicitPointer {
+ /// The `.debug_info` offset of the value that this is an implicit pointer into.
+ value: DebugInfoOffset<Offset>,
+ /// The byte offset into the value that the implicit pointer points to.
+ byte_offset: i64,
+ },
+ /// Evaluate an expression at the entry to the current subprogram, and push it on the stack.
+ ///
+ /// Represents `DW_OP_entry_value`.
+ EntryValue {
+ /// The expression to be evaluated.
+ expression: R,
+ },
+ /// This represents a parameter that was optimized out.
+ ///
+ /// The offset points to the definition of the parameter, and is
+ /// matched to the `DW_TAG_GNU_call_site_parameter` in the caller that also
+ /// points to the same definition of the parameter.
+ ///
+ /// Represents `DW_OP_GNU_parameter_ref`.
+ ParameterRef {
+ /// The DIE to use.
+ offset: UnitOffset<Offset>,
+ },
+ /// Relocate the address if needed, and push it on the stack.
+ ///
+ /// Represents `DW_OP_addr`.
+ Address {
+ /// The offset to add.
+ address: u64,
+ },
+ /// Read the address at the given index in `.debug_addr, relocate the address if needed,
+ /// and push it on the stack.
+ ///
+ /// Represents `DW_OP_addrx`.
+ AddressIndex {
+ /// The index of the address in `.debug_addr`.
+ index: DebugAddrIndex<Offset>,
+ },
+ /// Read the address at the given index in `.debug_addr, and push it on the stack.
+ /// Do not relocate the address.
+ ///
+ /// Represents `DW_OP_constx`.
+ ConstantIndex {
+ /// The index of the address in `.debug_addr`.
+ index: DebugAddrIndex<Offset>,
+ },
+ /// Interpret the value bytes as a constant of a given type, and push it on the stack.
+ ///
+ /// Represents `DW_OP_const_type`.
+ TypedLiteral {
+ /// The DIE of the base type.
+ base_type: UnitOffset<Offset>,
+ /// The value bytes.
+ value: R,
+ },
+ /// Pop the top stack entry, convert it to a different type, and push it on the stack.
+ ///
+ /// Represents `DW_OP_convert`.
+ Convert {
+ /// The DIE of the base type.
+ base_type: UnitOffset<Offset>,
+ },
+ /// Pop the top stack entry, reinterpret the bits in its value as a different type,
+ /// and push it on the stack.
+ ///
+ /// Represents `DW_OP_reinterpret`.
+ Reinterpret {
+ /// The DIE of the base type.
+ base_type: UnitOffset<Offset>,
+ },
+ /// The index of a local in the currently executing function.
+ ///
+ /// Represents `DW_OP_WASM_location 0x00`.
+ /// Completes the piece or expression.
+ WasmLocal {
+ /// The index of the local.
+ index: u32,
+ },
+ /// The index of a global.
+ ///
+ /// Represents `DW_OP_WASM_location 0x01` or `DW_OP_WASM_location 0x03`.
+ /// Completes the piece or expression.
+ WasmGlobal {
+ /// The index of the global.
+ index: u32,
+ },
+ /// The index of an item on the operand stack.
+ ///
+ /// Represents `DW_OP_WASM_location 0x02`.
+ /// Completes the piece or expression.
+ WasmStack {
+ /// The index of the stack item. 0 is the bottom of the operand stack.
+ index: u32,
+ },
+}
+
+#[derive(Debug)]
+enum OperationEvaluationResult<R: Reader> {
+ Piece,
+ Incomplete,
+ Complete { location: Location<R> },
+ Waiting(EvaluationWaiting<R>, EvaluationResult<R>),
+}
+
+/// A single location of a piece of the result of a DWARF expression.
+#[derive(Debug, Clone, Copy, PartialEq)]
+pub enum Location<R, Offset = <R as Reader>::Offset>
+where
+ R: Reader<Offset = Offset>,
+ Offset: ReaderOffset,
+{
+ /// The piece is empty. Ordinarily this means the piece has been
+ /// optimized away.
+ Empty,
+ /// The piece is found in a register.
+ Register {
+ /// The register number.
+ register: Register,
+ },
+ /// The piece is found in memory.
+ Address {
+ /// The address.
+ address: u64,
+ },
+ /// The piece has no location but its value is known.
+ Value {
+ /// The value.
+ value: Value,
+ },
+ /// The piece is represented by some constant bytes.
+ Bytes {
+ /// The value.
+ value: R,
+ },
+ /// The piece is a pointer to a value which has no actual location.
+ ImplicitPointer {
+ /// The `.debug_info` offset of the value that this is an implicit pointer into.
+ value: DebugInfoOffset<Offset>,
+ /// The byte offset into the value that the implicit pointer points to.
+ byte_offset: i64,
+ },
+}
+
+impl<R, Offset> Location<R, Offset>
+where
+ R: Reader<Offset = Offset>,
+ Offset: ReaderOffset,
+{
+ /// Return true if the piece is empty.
+ pub fn is_empty(&self) -> bool {
+ match *self {
+ Location::Empty => true,
+ _ => false,
+ }
+ }
+}
+
+/// The description of a single piece of the result of a DWARF
+/// expression.
+#[derive(Debug, Clone, Copy, PartialEq)]
+pub struct Piece<R, Offset = <R as Reader>::Offset>
+where
+ R: Reader<Offset = Offset>,
+ Offset: ReaderOffset,
+{
+ /// If given, the size of the piece in bits. If `None`, there
+ /// must be only one piece whose size is all of the object.
+ pub size_in_bits: Option<u64>,
+ /// If given, the bit offset of the piece within the location.
+ /// If the location is a `Location::Register` or `Location::Value`,
+ /// then this offset is from the least significant bit end of
+ /// the register or value.
+ /// If the location is a `Location::Address` then the offset uses
+ /// the bit numbering and direction conventions of the language
+ /// and target system.
+ ///
+ /// If `None`, the piece starts at the location. If the
+ /// location is a register whose size is larger than the piece,
+ /// then placement within the register is defined by the ABI.
+ pub bit_offset: Option<u64>,
+ /// Where this piece is to be found.
+ pub location: Location<R, Offset>,
+}
+
+// A helper function to handle branch offsets.
+fn compute_pc<R: Reader>(pc: &R, bytecode: &R, offset: i16) -> Result<R> {
+ let pc_offset = pc.offset_from(bytecode);
+ let new_pc_offset = pc_offset.wrapping_add(R::Offset::from_i16(offset));
+ if new_pc_offset > bytecode.len() {
+ Err(Error::BadBranchTarget(new_pc_offset.into_u64()))
+ } else {
+ let mut new_pc = bytecode.clone();
+ new_pc.skip(new_pc_offset)?;
+ Ok(new_pc)
+ }
+}
+
+fn generic_type<O: ReaderOffset>() -> UnitOffset<O> {
+ UnitOffset(O::from_u64(0).unwrap())
+}
+
+impl<R, Offset> Operation<R, Offset>
+where
+ R: Reader<Offset = Offset>,
+ Offset: ReaderOffset,
+{
+ /// Parse a single DWARF expression operation.
+ ///
+ /// This is useful when examining a DWARF expression for reasons other
+ /// than direct evaluation.
+ ///
+ /// `bytes` points to a the operation to decode. It should point into
+ /// the same array as `bytecode`, which should be the entire
+ /// expression.
+ pub fn parse(bytes: &mut R, encoding: Encoding) -> Result<Operation<R, Offset>> {
+ let opcode = bytes.read_u8()?;
+ let name = constants::DwOp(opcode);
+ match name {
+ constants::DW_OP_addr => {
+ let address = bytes.read_address(encoding.address_size)?;
+ Ok(Operation::Address { address })
+ }
+ constants::DW_OP_deref => Ok(Operation::Deref {
+ base_type: generic_type(),
+ size: encoding.address_size,
+ space: false,
+ }),
+ constants::DW_OP_const1u => {
+ let value = bytes.read_u8()?;
+ Ok(Operation::UnsignedConstant {
+ value: u64::from(value),
+ })
+ }
+ constants::DW_OP_const1s => {
+ let value = bytes.read_i8()?;
+ Ok(Operation::SignedConstant {
+ value: i64::from(value),
+ })
+ }
+ constants::DW_OP_const2u => {
+ let value = bytes.read_u16()?;
+ Ok(Operation::UnsignedConstant {
+ value: u64::from(value),
+ })
+ }
+ constants::DW_OP_const2s => {
+ let value = bytes.read_i16()?;
+ Ok(Operation::SignedConstant {
+ value: i64::from(value),
+ })
+ }
+ constants::DW_OP_const4u => {
+ let value = bytes.read_u32()?;
+ Ok(Operation::UnsignedConstant {
+ value: u64::from(value),
+ })
+ }
+ constants::DW_OP_const4s => {
+ let value = bytes.read_i32()?;
+ Ok(Operation::SignedConstant {
+ value: i64::from(value),
+ })
+ }
+ constants::DW_OP_const8u => {
+ let value = bytes.read_u64()?;
+ Ok(Operation::UnsignedConstant { value })
+ }
+ constants::DW_OP_const8s => {
+ let value = bytes.read_i64()?;
+ Ok(Operation::SignedConstant { value })
+ }
+ constants::DW_OP_constu => {
+ let value = bytes.read_uleb128()?;
+ Ok(Operation::UnsignedConstant { value })
+ }
+ constants::DW_OP_consts => {
+ let value = bytes.read_sleb128()?;
+ Ok(Operation::SignedConstant { value })
+ }
+ constants::DW_OP_dup => Ok(Operation::Pick { index: 0 }),
+ constants::DW_OP_drop => Ok(Operation::Drop),
+ constants::DW_OP_over => Ok(Operation::Pick { index: 1 }),
+ constants::DW_OP_pick => {
+ let value = bytes.read_u8()?;
+ Ok(Operation::Pick { index: value })
+ }
+ constants::DW_OP_swap => Ok(Operation::Swap),
+ constants::DW_OP_rot => Ok(Operation::Rot),
+ constants::DW_OP_xderef => Ok(Operation::Deref {
+ base_type: generic_type(),
+ size: encoding.address_size,
+ space: true,
+ }),
+ constants::DW_OP_abs => Ok(Operation::Abs),
+ constants::DW_OP_and => Ok(Operation::And),
+ constants::DW_OP_div => Ok(Operation::Div),
+ constants::DW_OP_minus => Ok(Operation::Minus),
+ constants::DW_OP_mod => Ok(Operation::Mod),
+ constants::DW_OP_mul => Ok(Operation::Mul),
+ constants::DW_OP_neg => Ok(Operation::Neg),
+ constants::DW_OP_not => Ok(Operation::Not),
+ constants::DW_OP_or => Ok(Operation::Or),
+ constants::DW_OP_plus => Ok(Operation::Plus),
+ constants::DW_OP_plus_uconst => {
+ let value = bytes.read_uleb128()?;
+ Ok(Operation::PlusConstant { value })
+ }
+ constants::DW_OP_shl => Ok(Operation::Shl),
+ constants::DW_OP_shr => Ok(Operation::Shr),
+ constants::DW_OP_shra => Ok(Operation::Shra),
+ constants::DW_OP_xor => Ok(Operation::Xor),
+ constants::DW_OP_bra => {
+ let target = bytes.read_i16()?;
+ Ok(Operation::Bra { target })
+ }
+ constants::DW_OP_eq => Ok(Operation::Eq),
+ constants::DW_OP_ge => Ok(Operation::Ge),
+ constants::DW_OP_gt => Ok(Operation::Gt),
+ constants::DW_OP_le => Ok(Operation::Le),
+ constants::DW_OP_lt => Ok(Operation::Lt),
+ constants::DW_OP_ne => Ok(Operation::Ne),
+ constants::DW_OP_skip => {
+ let target = bytes.read_i16()?;
+ Ok(Operation::Skip { target })
+ }
+ constants::DW_OP_lit0
+ | constants::DW_OP_lit1
+ | constants::DW_OP_lit2
+ | constants::DW_OP_lit3
+ | constants::DW_OP_lit4
+ | constants::DW_OP_lit5
+ | constants::DW_OP_lit6
+ | constants::DW_OP_lit7
+ | constants::DW_OP_lit8
+ | constants::DW_OP_lit9
+ | constants::DW_OP_lit10
+ | constants::DW_OP_lit11
+ | constants::DW_OP_lit12
+ | constants::DW_OP_lit13
+ | constants::DW_OP_lit14
+ | constants::DW_OP_lit15
+ | constants::DW_OP_lit16
+ | constants::DW_OP_lit17
+ | constants::DW_OP_lit18
+ | constants::DW_OP_lit19
+ | constants::DW_OP_lit20
+ | constants::DW_OP_lit21
+ | constants::DW_OP_lit22
+ | constants::DW_OP_lit23
+ | constants::DW_OP_lit24
+ | constants::DW_OP_lit25
+ | constants::DW_OP_lit26
+ | constants::DW_OP_lit27
+ | constants::DW_OP_lit28
+ | constants::DW_OP_lit29
+ | constants::DW_OP_lit30
+ | constants::DW_OP_lit31 => Ok(Operation::UnsignedConstant {
+ value: (opcode - constants::DW_OP_lit0.0).into(),
+ }),
+ constants::DW_OP_reg0
+ | constants::DW_OP_reg1
+ | constants::DW_OP_reg2
+ | constants::DW_OP_reg3
+ | constants::DW_OP_reg4
+ | constants::DW_OP_reg5
+ | constants::DW_OP_reg6
+ | constants::DW_OP_reg7
+ | constants::DW_OP_reg8
+ | constants::DW_OP_reg9
+ | constants::DW_OP_reg10
+ | constants::DW_OP_reg11
+ | constants::DW_OP_reg12
+ | constants::DW_OP_reg13
+ | constants::DW_OP_reg14
+ | constants::DW_OP_reg15
+ | constants::DW_OP_reg16
+ | constants::DW_OP_reg17
+ | constants::DW_OP_reg18
+ | constants::DW_OP_reg19
+ | constants::DW_OP_reg20
+ | constants::DW_OP_reg21
+ | constants::DW_OP_reg22
+ | constants::DW_OP_reg23
+ | constants::DW_OP_reg24
+ | constants::DW_OP_reg25
+ | constants::DW_OP_reg26
+ | constants::DW_OP_reg27
+ | constants::DW_OP_reg28
+ | constants::DW_OP_reg29
+ | constants::DW_OP_reg30
+ | constants::DW_OP_reg31 => Ok(Operation::Register {
+ register: Register((opcode - constants::DW_OP_reg0.0).into()),
+ }),
+ constants::DW_OP_breg0
+ | constants::DW_OP_breg1
+ | constants::DW_OP_breg2
+ | constants::DW_OP_breg3
+ | constants::DW_OP_breg4
+ | constants::DW_OP_breg5
+ | constants::DW_OP_breg6
+ | constants::DW_OP_breg7
+ | constants::DW_OP_breg8
+ | constants::DW_OP_breg9
+ | constants::DW_OP_breg10
+ | constants::DW_OP_breg11
+ | constants::DW_OP_breg12
+ | constants::DW_OP_breg13
+ | constants::DW_OP_breg14
+ | constants::DW_OP_breg15
+ | constants::DW_OP_breg16
+ | constants::DW_OP_breg17
+ | constants::DW_OP_breg18
+ | constants::DW_OP_breg19
+ | constants::DW_OP_breg20
+ | constants::DW_OP_breg21
+ | constants::DW_OP_breg22
+ | constants::DW_OP_breg23
+ | constants::DW_OP_breg24
+ | constants::DW_OP_breg25
+ | constants::DW_OP_breg26
+ | constants::DW_OP_breg27
+ | constants::DW_OP_breg28
+ | constants::DW_OP_breg29
+ | constants::DW_OP_breg30
+ | constants::DW_OP_breg31 => {
+ let value = bytes.read_sleb128()?;
+ Ok(Operation::RegisterOffset {
+ register: Register((opcode - constants::DW_OP_breg0.0).into()),
+ offset: value,
+ base_type: generic_type(),
+ })
+ }
+ constants::DW_OP_regx => {
+ let register = bytes.read_uleb128().and_then(Register::from_u64)?;
+ Ok(Operation::Register { register })
+ }
+ constants::DW_OP_fbreg => {
+ let value = bytes.read_sleb128()?;
+ Ok(Operation::FrameOffset { offset: value })
+ }
+ constants::DW_OP_bregx => {
+ let register = bytes.read_uleb128().and_then(Register::from_u64)?;
+ let offset = bytes.read_sleb128()?;
+ Ok(Operation::RegisterOffset {
+ register,
+ offset,
+ base_type: generic_type(),
+ })
+ }
+ constants::DW_OP_piece => {
+ let size = bytes.read_uleb128()?;
+ Ok(Operation::Piece {
+ size_in_bits: 8 * size,
+ bit_offset: None,
+ })
+ }
+ constants::DW_OP_deref_size => {
+ let size = bytes.read_u8()?;
+ Ok(Operation::Deref {
+ base_type: generic_type(),
+ size,
+ space: false,
+ })
+ }
+ constants::DW_OP_xderef_size => {
+ let size = bytes.read_u8()?;
+ Ok(Operation::Deref {
+ base_type: generic_type(),
+ size,
+ space: true,
+ })
+ }
+ constants::DW_OP_nop => Ok(Operation::Nop),
+ constants::DW_OP_push_object_address => Ok(Operation::PushObjectAddress),
+ constants::DW_OP_call2 => {
+ let value = bytes.read_u16().map(R::Offset::from_u16)?;
+ Ok(Operation::Call {
+ offset: DieReference::UnitRef(UnitOffset(value)),
+ })
+ }
+ constants::DW_OP_call4 => {
+ let value = bytes.read_u32().map(R::Offset::from_u32)?;
+ Ok(Operation::Call {
+ offset: DieReference::UnitRef(UnitOffset(value)),
+ })
+ }
+ constants::DW_OP_call_ref => {
+ let value = bytes.read_offset(encoding.format)?;
+ Ok(Operation::Call {
+ offset: DieReference::DebugInfoRef(DebugInfoOffset(value)),
+ })
+ }
+ constants::DW_OP_form_tls_address | constants::DW_OP_GNU_push_tls_address => {
+ Ok(Operation::TLS)
+ }
+ constants::DW_OP_call_frame_cfa => Ok(Operation::CallFrameCFA),
+ constants::DW_OP_bit_piece => {
+ let size = bytes.read_uleb128()?;
+ let offset = bytes.read_uleb128()?;
+ Ok(Operation::Piece {
+ size_in_bits: size,
+ bit_offset: Some(offset),
+ })
+ }
+ constants::DW_OP_implicit_value => {
+ let len = bytes.read_uleb128().and_then(R::Offset::from_u64)?;
+ let data = bytes.split(len)?;
+ Ok(Operation::ImplicitValue { data })
+ }
+ constants::DW_OP_stack_value => Ok(Operation::StackValue),
+ constants::DW_OP_implicit_pointer | constants::DW_OP_GNU_implicit_pointer => {
+ let value = if encoding.version == 2 {
+ bytes
+ .read_address(encoding.address_size)
+ .and_then(Offset::from_u64)?
+ } else {
+ bytes.read_offset(encoding.format)?
+ };
+ let byte_offset = bytes.read_sleb128()?;
+ Ok(Operation::ImplicitPointer {
+ value: DebugInfoOffset(value),
+ byte_offset,
+ })
+ }
+ constants::DW_OP_addrx | constants::DW_OP_GNU_addr_index => {
+ let index = bytes.read_uleb128().and_then(R::Offset::from_u64)?;
+ Ok(Operation::AddressIndex {
+ index: DebugAddrIndex(index),
+ })
+ }
+ constants::DW_OP_constx | constants::DW_OP_GNU_const_index => {
+ let index = bytes.read_uleb128().and_then(R::Offset::from_u64)?;
+ Ok(Operation::ConstantIndex {
+ index: DebugAddrIndex(index),
+ })
+ }
+ constants::DW_OP_entry_value | constants::DW_OP_GNU_entry_value => {
+ let len = bytes.read_uleb128().and_then(R::Offset::from_u64)?;
+ let expression = bytes.split(len)?;
+ Ok(Operation::EntryValue { expression })
+ }
+ constants::DW_OP_GNU_parameter_ref => {
+ let value = bytes.read_u32().map(R::Offset::from_u32)?;
+ Ok(Operation::ParameterRef {
+ offset: UnitOffset(value),
+ })
+ }
+ constants::DW_OP_const_type | constants::DW_OP_GNU_const_type => {
+ let base_type = bytes.read_uleb128().and_then(R::Offset::from_u64)?;
+ let len = bytes.read_u8()?;
+ let value = bytes.split(R::Offset::from_u8(len))?;
+ Ok(Operation::TypedLiteral {
+ base_type: UnitOffset(base_type),
+ value,
+ })
+ }
+ constants::DW_OP_regval_type | constants::DW_OP_GNU_regval_type => {
+ let register = bytes.read_uleb128().and_then(Register::from_u64)?;
+ let base_type = bytes.read_uleb128().and_then(R::Offset::from_u64)?;
+ Ok(Operation::RegisterOffset {
+ register,
+ offset: 0,
+ base_type: UnitOffset(base_type),
+ })
+ }
+ constants::DW_OP_deref_type | constants::DW_OP_GNU_deref_type => {
+ let size = bytes.read_u8()?;
+ let base_type = bytes.read_uleb128().and_then(R::Offset::from_u64)?;
+ Ok(Operation::Deref {
+ base_type: UnitOffset(base_type),
+ size,
+ space: false,
+ })
+ }
+ constants::DW_OP_xderef_type => {
+ let size = bytes.read_u8()?;
+ let base_type = bytes.read_uleb128().and_then(R::Offset::from_u64)?;
+ Ok(Operation::Deref {
+ base_type: UnitOffset(base_type),
+ size,
+ space: true,
+ })
+ }
+ constants::DW_OP_convert | constants::DW_OP_GNU_convert => {
+ let base_type = bytes.read_uleb128().and_then(R::Offset::from_u64)?;
+ Ok(Operation::Convert {
+ base_type: UnitOffset(base_type),
+ })
+ }
+ constants::DW_OP_reinterpret | constants::DW_OP_GNU_reinterpret => {
+ let base_type = bytes.read_uleb128().and_then(R::Offset::from_u64)?;
+ Ok(Operation::Reinterpret {
+ base_type: UnitOffset(base_type),
+ })
+ }
+ constants::DW_OP_WASM_location => match bytes.read_u8()? {
+ 0x0 => {
+ let index = bytes.read_uleb128_u32()?;
+ Ok(Operation::WasmLocal { index })
+ }
+ 0x1 => {
+ let index = bytes.read_uleb128_u32()?;
+ Ok(Operation::WasmGlobal { index })
+ }
+ 0x2 => {
+ let index = bytes.read_uleb128_u32()?;
+ Ok(Operation::WasmStack { index })
+ }
+ 0x3 => {
+ let index = bytes.read_u32()?;
+ Ok(Operation::WasmGlobal { index })
+ }
+ _ => Err(Error::InvalidExpression(name)),
+ },
+ _ => Err(Error::InvalidExpression(name)),
+ }
+ }
+}
+
+#[derive(Debug)]
+enum EvaluationState<R: Reader> {
+ Start(Option<u64>),
+ Ready,
+ Error(Error),
+ Complete,
+ Waiting(EvaluationWaiting<R>),
+}
+
+#[derive(Debug)]
+enum EvaluationWaiting<R: Reader> {
+ Memory,
+ Register { offset: i64 },
+ FrameBase { offset: i64 },
+ Tls,
+ Cfa,
+ AtLocation,
+ EntryValue,
+ ParameterRef,
+ RelocatedAddress,
+ IndexedAddress,
+ TypedLiteral { value: R },
+ Convert,
+ Reinterpret,
+}
+
+/// The state of an `Evaluation` after evaluating a DWARF expression.
+/// The evaluation is either `Complete`, or it requires more data
+/// to continue, as described by the variant.
+#[derive(Debug, PartialEq)]
+pub enum EvaluationResult<R: Reader> {
+ /// The `Evaluation` is complete, and `Evaluation::result()` can be called.
+ Complete,
+ /// The `Evaluation` needs a value from memory to proceed further. Once the
+ /// caller determines what value to provide it should resume the `Evaluation`
+ /// by calling `Evaluation::resume_with_memory`.
+ RequiresMemory {
+ /// The address of the value required.
+ address: u64,
+ /// The size of the value required. This is guaranteed to be at most the
+ /// word size of the target architecture.
+ size: u8,
+ /// If not `None`, a target-specific address space value.
+ space: Option<u64>,
+ /// The DIE of the base type or 0 to indicate the generic type
+ base_type: UnitOffset<R::Offset>,
+ },
+ /// The `Evaluation` needs a value from a register to proceed further. Once
+ /// the caller determines what value to provide it should resume the
+ /// `Evaluation` by calling `Evaluation::resume_with_register`.
+ RequiresRegister {
+ /// The register number.
+ register: Register,
+ /// The DIE of the base type or 0 to indicate the generic type
+ base_type: UnitOffset<R::Offset>,
+ },
+ /// The `Evaluation` needs the frame base address to proceed further. Once
+ /// the caller determines what value to provide it should resume the
+ /// `Evaluation` by calling `Evaluation::resume_with_frame_base`. The frame
+ /// base address is the address produced by the location description in the
+ /// `DW_AT_frame_base` attribute of the current function.
+ RequiresFrameBase,
+ /// The `Evaluation` needs a value from TLS to proceed further. Once the
+ /// caller determines what value to provide it should resume the
+ /// `Evaluation` by calling `Evaluation::resume_with_tls`.
+ RequiresTls(u64),
+ /// The `Evaluation` needs the CFA to proceed further. Once the caller
+ /// determines what value to provide it should resume the `Evaluation` by
+ /// calling `Evaluation::resume_with_call_frame_cfa`.
+ RequiresCallFrameCfa,
+ /// The `Evaluation` needs the DWARF expression at the given location to
+ /// proceed further. Once the caller determines what value to provide it
+ /// should resume the `Evaluation` by calling
+ /// `Evaluation::resume_with_at_location`.
+ RequiresAtLocation(DieReference<R::Offset>),
+ /// The `Evaluation` needs the value produced by evaluating a DWARF
+ /// expression at the entry point of the current subprogram. Once the
+ /// caller determines what value to provide it should resume the
+ /// `Evaluation` by calling `Evaluation::resume_with_entry_value`.
+ RequiresEntryValue(Expression<R>),
+ /// The `Evaluation` needs the value of the parameter at the given location
+ /// in the current function's caller. Once the caller determines what value
+ /// to provide it should resume the `Evaluation` by calling
+ /// `Evaluation::resume_with_parameter_ref`.
+ RequiresParameterRef(UnitOffset<R::Offset>),
+ /// The `Evaluation` needs an address to be relocated to proceed further.
+ /// Once the caller determines what value to provide it should resume the
+ /// `Evaluation` by calling `Evaluation::resume_with_relocated_address`.
+ RequiresRelocatedAddress(u64),
+ /// The `Evaluation` needs an address from the `.debug_addr` section.
+ /// This address may also need to be relocated.
+ /// Once the caller determines what value to provide it should resume the
+ /// `Evaluation` by calling `Evaluation::resume_with_indexed_address`.
+ RequiresIndexedAddress {
+ /// The index of the address in the `.debug_addr` section,
+ /// relative to the `DW_AT_addr_base` of the compilation unit.
+ index: DebugAddrIndex<R::Offset>,
+ /// Whether the address also needs to be relocated.
+ relocate: bool,
+ },
+ /// The `Evaluation` needs the `ValueType` for the base type DIE at
+ /// the give unit offset. Once the caller determines what value to provide it
+ /// should resume the `Evaluation` by calling
+ /// `Evaluation::resume_with_base_type`.
+ RequiresBaseType(UnitOffset<R::Offset>),
+}
+
+/// The bytecode for a DWARF expression or location description.
+#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
+pub struct Expression<R: Reader>(pub R);
+
+impl<R: Reader> Expression<R> {
+ /// Create an evaluation for this expression.
+ ///
+ /// The `encoding` is determined by the
+ /// [`CompilationUnitHeader`](struct.CompilationUnitHeader.html) or
+ /// [`TypeUnitHeader`](struct.TypeUnitHeader.html) that this expression
+ /// relates to.
+ ///
+ /// # Examples
+ /// ```rust,no_run
+ /// use gimli::Expression;
+ /// # let endian = gimli::LittleEndian;
+ /// # let debug_info = gimli::DebugInfo::from(gimli::EndianSlice::new(&[], endian));
+ /// # let unit = debug_info.units().next().unwrap().unwrap();
+ /// # let bytecode = gimli::EndianSlice::new(&[], endian);
+ /// let expression = gimli::Expression(bytecode);
+ /// let mut eval = expression.evaluation(unit.encoding());
+ /// let mut result = eval.evaluate().unwrap();
+ /// ```
+ #[cfg(feature = "read")]
+ #[inline]
+ pub fn evaluation(self, encoding: Encoding) -> Evaluation<R> {
+ Evaluation::new(self.0, encoding)
+ }
+
+ /// Return an iterator for the operations in the expression.
+ pub fn operations(self, encoding: Encoding) -> OperationIter<R> {
+ OperationIter {
+ input: self.0,
+ encoding,
+ }
+ }
+}
+
+/// An iterator for the operations in an expression.
+#[derive(Debug, Clone, Copy)]
+pub struct OperationIter<R: Reader> {
+ input: R,
+ encoding: Encoding,
+}
+
+impl<R: Reader> OperationIter<R> {
+ /// Read the next operation in an expression.
+ pub fn next(&mut self) -> Result<Option<Operation<R>>> {
+ if self.input.is_empty() {
+ return Ok(None);
+ }
+ match Operation::parse(&mut self.input, self.encoding) {
+ Ok(op) => Ok(Some(op)),
+ Err(e) => {
+ self.input.empty();
+ Err(e)
+ }
+ }
+ }
+
+ /// Return the current byte offset of the iterator.
+ pub fn offset_from(&self, expression: &Expression<R>) -> R::Offset {
+ self.input.offset_from(&expression.0)
+ }
+}
+
+/// Specification of what storage should be used for [`Evaluation`].
+///
+#[cfg_attr(
+ feature = "read",
+ doc = "
+Normally you would only need to use [`StoreOnHeap`], which places the stacks and the results
+on the heap using [`Vec`]. This is the default storage type parameter for [`Evaluation`].
+"
+)]
+///
+/// If you need to avoid [`Evaluation`] from allocating memory, e.g. for signal safety,
+/// you can provide you own storage specification:
+/// ```rust,no_run
+/// # use gimli::*;
+/// # let bytecode = EndianSlice::new(&[], LittleEndian);
+/// # let encoding = unimplemented!();
+/// # let get_register_value = |_, _| Value::Generic(42);
+/// # let get_frame_base = || 0xdeadbeef;
+/// #
+/// struct StoreOnStack;
+///
+/// impl<R: Reader> EvaluationStorage<R> for StoreOnStack {
+/// type Stack = [Value; 64];
+/// type ExpressionStack = [(R, R); 4];
+/// type Result = [Piece<R>; 1];
+/// }
+///
+/// let mut eval = Evaluation::<_, StoreOnStack>::new_in(bytecode, encoding);
+/// let mut result = eval.evaluate().unwrap();
+/// while result != EvaluationResult::Complete {
+/// match result {
+/// EvaluationResult::RequiresRegister { register, base_type } => {
+/// let value = get_register_value(register, base_type);
+/// result = eval.resume_with_register(value).unwrap();
+/// },
+/// EvaluationResult::RequiresFrameBase => {
+/// let frame_base = get_frame_base();
+/// result = eval.resume_with_frame_base(frame_base).unwrap();
+/// },
+/// _ => unimplemented!(),
+/// };
+/// }
+///
+/// let result = eval.as_result();
+/// println!("{:?}", result);
+/// ```
+pub trait EvaluationStorage<R: Reader> {
+ /// The storage used for the evaluation stack.
+ type Stack: ArrayLike<Item = Value>;
+ /// The storage used for the expression stack.
+ type ExpressionStack: ArrayLike<Item = (R, R)>;
+ /// The storage used for the results.
+ type Result: ArrayLike<Item = Piece<R>>;
+}
+
+#[cfg(feature = "read")]
+impl<R: Reader> EvaluationStorage<R> for StoreOnHeap {
+ type Stack = Vec<Value>;
+ type ExpressionStack = Vec<(R, R)>;
+ type Result = Vec<Piece<R>>;
+}
+
+/// A DWARF expression evaluator.
+///
+/// # Usage
+/// A DWARF expression may require additional data to produce a final result,
+/// such as the value of a register or a memory location. Once initial setup
+/// is complete (i.e. `set_initial_value()`, `set_object_address()`) the
+/// consumer calls the `evaluate()` method. That returns an `EvaluationResult`,
+/// which is either `EvaluationResult::Complete` or a value indicating what
+/// data is needed to resume the `Evaluation`. The consumer is responsible for
+/// producing that data and resuming the computation with the correct method,
+/// as documented for `EvaluationResult`. Only once an `EvaluationResult::Complete`
+/// is returned can the consumer call `result()`.
+///
+/// This design allows the consumer of `Evaluation` to decide how and when to
+/// produce the required data and resume the computation. The `Evaluation` can
+/// be driven synchronously (as shown below) or by some asynchronous mechanism
+/// such as futures.
+///
+/// # Examples
+/// ```rust,no_run
+/// use gimli::{EndianSlice, Evaluation, EvaluationResult, Format, LittleEndian, Value};
+/// # let bytecode = EndianSlice::new(&[], LittleEndian);
+/// # let encoding = unimplemented!();
+/// # let get_register_value = |_, _| Value::Generic(42);
+/// # let get_frame_base = || 0xdeadbeef;
+///
+/// let mut eval = Evaluation::new(bytecode, encoding);
+/// let mut result = eval.evaluate().unwrap();
+/// while result != EvaluationResult::Complete {
+/// match result {
+/// EvaluationResult::RequiresRegister { register, base_type } => {
+/// let value = get_register_value(register, base_type);
+/// result = eval.resume_with_register(value).unwrap();
+/// },
+/// EvaluationResult::RequiresFrameBase => {
+/// let frame_base = get_frame_base();
+/// result = eval.resume_with_frame_base(frame_base).unwrap();
+/// },
+/// _ => unimplemented!(),
+/// };
+/// }
+///
+/// let result = eval.result();
+/// println!("{:?}", result);
+/// ```
+#[derive(Debug)]
+pub struct Evaluation<R: Reader, S: EvaluationStorage<R> = StoreOnHeap> {
+ bytecode: R,
+ encoding: Encoding,
+ object_address: Option<u64>,
+ max_iterations: Option<u32>,
+ iteration: u32,
+ state: EvaluationState<R>,
+
+ // Stack operations are done on word-sized values. We do all
+ // operations on 64-bit values, and then mask the results
+ // appropriately when popping.
+ addr_mask: u64,
+
+ // The stack.
+ stack: ArrayVec<S::Stack>,
+
+ // The next operation to decode and evaluate.
+ pc: R,
+
+ // If we see a DW_OP_call* operation, the previous PC and bytecode
+ // is stored here while evaluating the subroutine.
+ expression_stack: ArrayVec<S::ExpressionStack>,
+
+ result: ArrayVec<S::Result>,
+}
+
+#[cfg(feature = "read")]
+impl<R: Reader> Evaluation<R> {
+ /// Create a new DWARF expression evaluator.
+ ///
+ /// The new evaluator is created without an initial value, without
+ /// an object address, and without a maximum number of iterations.
+ pub fn new(bytecode: R, encoding: Encoding) -> Self {
+ Self::new_in(bytecode, encoding)
+ }
+
+ /// Get the result of this `Evaluation`.
+ ///
+ /// # Panics
+ /// Panics if this `Evaluation` has not been driven to completion.
+ pub fn result(self) -> Vec<Piece<R>> {
+ match self.state {
+ EvaluationState::Complete => self.result.into_vec(),
+ _ => {
+ panic!("Called `Evaluation::result` on an `Evaluation` that has not been completed")
+ }
+ }
+ }
+}
+
+impl<R: Reader, S: EvaluationStorage<R>> Evaluation<R, S> {
+ /// Create a new DWARF expression evaluator.
+ ///
+ /// The new evaluator is created without an initial value, without
+ /// an object address, and without a maximum number of iterations.
+ pub fn new_in(bytecode: R, encoding: Encoding) -> Self {
+ let pc = bytecode.clone();
+ Evaluation {
+ bytecode,
+ encoding,
+ object_address: None,
+ max_iterations: None,
+ iteration: 0,
+ state: EvaluationState::Start(None),
+ addr_mask: if encoding.address_size == 8 {
+ !0u64
+ } else {
+ (1 << (8 * u64::from(encoding.address_size))) - 1
+ },
+ stack: Default::default(),
+ expression_stack: Default::default(),
+ pc,
+ result: Default::default(),
+ }
+ }
+
+ /// Set an initial value to be pushed on the DWARF expression
+ /// evaluator's stack. This can be used in cases like
+ /// `DW_AT_vtable_elem_location`, which require a value on the
+ /// stack before evaluation commences. If no initial value is
+ /// set, and the expression uses an opcode requiring the initial
+ /// value, then evaluation will fail with an error.
+ ///
+ /// # Panics
+ /// Panics if `set_initial_value()` has already been called, or if
+ /// `evaluate()` has already been called.
+ pub fn set_initial_value(&mut self, value: u64) {
+ match self.state {
+ EvaluationState::Start(None) => {
+ self.state = EvaluationState::Start(Some(value));
+ }
+ _ => panic!(
+ "`Evaluation::set_initial_value` was called twice, or after evaluation began."
+ ),
+ };
+ }
+
+ /// Set the enclosing object's address, as used by
+ /// `DW_OP_push_object_address`. If no object address is set, and
+ /// the expression uses an opcode requiring the object address,
+ /// then evaluation will fail with an error.
+ pub fn set_object_address(&mut self, value: u64) {
+ self.object_address = Some(value);
+ }
+
+ /// Set the maximum number of iterations to be allowed by the
+ /// expression evaluator.
+ ///
+ /// An iteration corresponds approximately to the evaluation of a
+ /// single operation in an expression ("approximately" because the
+ /// implementation may allow two such operations in some cases).
+ /// The default is not to have a maximum; once set, it's not
+ /// possible to go back to this default state. This value can be
+ /// set to avoid denial of service attacks by bad DWARF bytecode.
+ pub fn set_max_iterations(&mut self, value: u32) {
+ self.max_iterations = Some(value);
+ }
+
+ fn pop(&mut self) -> Result<Value> {
+ match self.stack.pop() {
+ Some(value) => Ok(value),
+ None => Err(Error::NotEnoughStackItems),
+ }
+ }
+
+ fn push(&mut self, value: Value) -> Result<()> {
+ self.stack.try_push(value).map_err(|_| Error::StackFull)
+ }
+
+ #[allow(clippy::cyclomatic_complexity)]
+ fn evaluate_one_operation(&mut self) -> Result<OperationEvaluationResult<R>> {
+ let operation = Operation::parse(&mut self.pc, self.encoding)?;
+
+ match operation {
+ Operation::Deref {
+ base_type,
+ size,
+ space,
+ } => {
+ let entry = self.pop()?;
+ let addr = entry.to_u64(self.addr_mask)?;
+ let addr_space = if space {
+ let entry = self.pop()?;
+ let value = entry.to_u64(self.addr_mask)?;
+ Some(value)
+ } else {
+ None
+ };
+ return Ok(OperationEvaluationResult::Waiting(
+ EvaluationWaiting::Memory,
+ EvaluationResult::RequiresMemory {
+ address: addr,
+ size,
+ space: addr_space,
+ base_type,
+ },
+ ));
+ }
+
+ Operation::Drop => {
+ self.pop()?;
+ }
+ Operation::Pick { index } => {
+ let len = self.stack.len();
+ let index = index as usize;
+ if index >= len {
+ return Err(Error::NotEnoughStackItems);
+ }
+ let value = self.stack[len - index - 1];
+ self.push(value)?;
+ }
+ Operation::Swap => {
+ let top = self.pop()?;
+ let next = self.pop()?;
+ self.push(top)?;
+ self.push(next)?;
+ }
+ Operation::Rot => {
+ let one = self.pop()?;
+ let two = self.pop()?;
+ let three = self.pop()?;
+ self.push(one)?;
+ self.push(three)?;
+ self.push(two)?;
+ }
+
+ Operation::Abs => {
+ let value = self.pop()?;
+ let result = value.abs(self.addr_mask)?;
+ self.push(result)?;
+ }
+ Operation::And => {
+ let rhs = self.pop()?;
+ let lhs = self.pop()?;
+ let result = lhs.and(rhs, self.addr_mask)?;
+ self.push(result)?;
+ }
+ Operation::Div => {
+ let rhs = self.pop()?;
+ let lhs = self.pop()?;
+ let result = lhs.div(rhs, self.addr_mask)?;
+ self.push(result)?;
+ }
+ Operation::Minus => {
+ let rhs = self.pop()?;
+ let lhs = self.pop()?;
+ let result = lhs.sub(rhs, self.addr_mask)?;
+ self.push(result)?;
+ }
+ Operation::Mod => {
+ let rhs = self.pop()?;
+ let lhs = self.pop()?;
+ let result = lhs.rem(rhs, self.addr_mask)?;
+ self.push(result)?;
+ }
+ Operation::Mul => {
+ let rhs = self.pop()?;
+ let lhs = self.pop()?;
+ let result = lhs.mul(rhs, self.addr_mask)?;
+ self.push(result)?;
+ }
+ Operation::Neg => {
+ let v = self.pop()?;
+ let result = v.neg(self.addr_mask)?;
+ self.push(result)?;
+ }
+ Operation::Not => {
+ let value = self.pop()?;
+ let result = value.not(self.addr_mask)?;
+ self.push(result)?;
+ }
+ Operation::Or => {
+ let rhs = self.pop()?;
+ let lhs = self.pop()?;
+ let result = lhs.or(rhs, self.addr_mask)?;
+ self.push(result)?;
+ }
+ Operation::Plus => {
+ let rhs = self.pop()?;
+ let lhs = self.pop()?;
+ let result = lhs.add(rhs, self.addr_mask)?;
+ self.push(result)?;
+ }
+ Operation::PlusConstant { value } => {
+ let lhs = self.pop()?;
+ let rhs = Value::from_u64(lhs.value_type(), value)?;
+ let result = lhs.add(rhs, self.addr_mask)?;
+ self.push(result)?;
+ }
+ Operation::Shl => {
+ let rhs = self.pop()?;
+ let lhs = self.pop()?;
+ let result = lhs.shl(rhs, self.addr_mask)?;
+ self.push(result)?;
+ }
+ Operation::Shr => {
+ let rhs = self.pop()?;
+ let lhs = self.pop()?;
+ let result = lhs.shr(rhs, self.addr_mask)?;
+ self.push(result)?;
+ }
+ Operation::Shra => {
+ let rhs = self.pop()?;
+ let lhs = self.pop()?;
+ let result = lhs.shra(rhs, self.addr_mask)?;
+ self.push(result)?;
+ }
+ Operation::Xor => {
+ let rhs = self.pop()?;
+ let lhs = self.pop()?;
+ let result = lhs.xor(rhs, self.addr_mask)?;
+ self.push(result)?;
+ }
+
+ Operation::Bra { target } => {
+ let entry = self.pop()?;
+ let v = entry.to_u64(self.addr_mask)?;
+ if v != 0 {
+ self.pc = compute_pc(&self.pc, &self.bytecode, target)?;
+ }
+ }
+
+ Operation::Eq => {
+ let rhs = self.pop()?;
+ let lhs = self.pop()?;
+ let result = lhs.eq(rhs, self.addr_mask)?;
+ self.push(result)?;
+ }
+ Operation::Ge => {
+ let rhs = self.pop()?;
+ let lhs = self.pop()?;
+ let result = lhs.ge(rhs, self.addr_mask)?;
+ self.push(result)?;
+ }
+ Operation::Gt => {
+ let rhs = self.pop()?;
+ let lhs = self.pop()?;
+ let result = lhs.gt(rhs, self.addr_mask)?;
+ self.push(result)?;
+ }
+ Operation::Le => {
+ let rhs = self.pop()?;
+ let lhs = self.pop()?;
+ let result = lhs.le(rhs, self.addr_mask)?;
+ self.push(result)?;
+ }
+ Operation::Lt => {
+ let rhs = self.pop()?;
+ let lhs = self.pop()?;
+ let result = lhs.lt(rhs, self.addr_mask)?;
+ self.push(result)?;
+ }
+ Operation::Ne => {
+ let rhs = self.pop()?;
+ let lhs = self.pop()?;
+ let result = lhs.ne(rhs, self.addr_mask)?;
+ self.push(result)?;
+ }
+
+ Operation::Skip { target } => {
+ self.pc = compute_pc(&self.pc, &self.bytecode, target)?;
+ }
+
+ Operation::UnsignedConstant { value } => {
+ self.push(Value::Generic(value))?;
+ }
+
+ Operation::SignedConstant { value } => {
+ self.push(Value::Generic(value as u64))?;
+ }
+
+ Operation::RegisterOffset {
+ register,
+ offset,
+ base_type,
+ } => {
+ return Ok(OperationEvaluationResult::Waiting(
+ EvaluationWaiting::Register { offset },
+ EvaluationResult::RequiresRegister {
+ register,
+ base_type,
+ },
+ ));
+ }
+
+ Operation::FrameOffset { offset } => {
+ return Ok(OperationEvaluationResult::Waiting(
+ EvaluationWaiting::FrameBase { offset },
+ EvaluationResult::RequiresFrameBase,
+ ));
+ }
+
+ Operation::Nop => {}
+
+ Operation::PushObjectAddress => {
+ if let Some(value) = self.object_address {
+ self.push(Value::Generic(value))?;
+ } else {
+ return Err(Error::InvalidPushObjectAddress);
+ }
+ }
+
+ Operation::Call { offset } => {
+ return Ok(OperationEvaluationResult::Waiting(
+ EvaluationWaiting::AtLocation,
+ EvaluationResult::RequiresAtLocation(offset),
+ ));
+ }
+
+ Operation::TLS => {
+ let entry = self.pop()?;
+ let index = entry.to_u64(self.addr_mask)?;
+ return Ok(OperationEvaluationResult::Waiting(
+ EvaluationWaiting::Tls,
+ EvaluationResult::RequiresTls(index),
+ ));
+ }
+
+ Operation::CallFrameCFA => {
+ return Ok(OperationEvaluationResult::Waiting(
+ EvaluationWaiting::Cfa,
+ EvaluationResult::RequiresCallFrameCfa,
+ ));
+ }
+
+ Operation::Register { register } => {
+ let location = Location::Register { register };
+ return Ok(OperationEvaluationResult::Complete { location });
+ }
+
+ Operation::ImplicitValue { ref data } => {
+ let location = Location::Bytes {
+ value: data.clone(),
+ };
+ return Ok(OperationEvaluationResult::Complete { location });
+ }
+
+ Operation::StackValue => {
+ let value = self.pop()?;
+ let location = Location::Value { value };
+ return Ok(OperationEvaluationResult::Complete { location });
+ }
+
+ Operation::ImplicitPointer { value, byte_offset } => {
+ let location = Location::ImplicitPointer { value, byte_offset };
+ return Ok(OperationEvaluationResult::Complete { location });
+ }
+
+ Operation::EntryValue { ref expression } => {
+ return Ok(OperationEvaluationResult::Waiting(
+ EvaluationWaiting::EntryValue,
+ EvaluationResult::RequiresEntryValue(Expression(expression.clone())),
+ ));
+ }
+
+ Operation::ParameterRef { offset } => {
+ return Ok(OperationEvaluationResult::Waiting(
+ EvaluationWaiting::ParameterRef,
+ EvaluationResult::RequiresParameterRef(offset),
+ ));
+ }
+
+ Operation::Address { address } => {
+ return Ok(OperationEvaluationResult::Waiting(
+ EvaluationWaiting::RelocatedAddress,
+ EvaluationResult::RequiresRelocatedAddress(address),
+ ));
+ }
+
+ Operation::AddressIndex { index } => {
+ return Ok(OperationEvaluationResult::Waiting(
+ EvaluationWaiting::IndexedAddress,
+ EvaluationResult::RequiresIndexedAddress {
+ index,
+ relocate: true,
+ },
+ ));
+ }
+
+ Operation::ConstantIndex { index } => {
+ return Ok(OperationEvaluationResult::Waiting(
+ EvaluationWaiting::IndexedAddress,
+ EvaluationResult::RequiresIndexedAddress {
+ index,
+ relocate: false,
+ },
+ ));
+ }
+
+ Operation::Piece {
+ size_in_bits,
+ bit_offset,
+ } => {
+ let location = if self.stack.is_empty() {
+ Location::Empty
+ } else {
+ let entry = self.pop()?;
+ let address = entry.to_u64(self.addr_mask)?;
+ Location::Address { address }
+ };
+ self.result
+ .try_push(Piece {
+ size_in_bits: Some(size_in_bits),
+ bit_offset,
+ location,
+ })
+ .map_err(|_| Error::StackFull)?;
+ return Ok(OperationEvaluationResult::Piece);
+ }
+
+ Operation::TypedLiteral { base_type, value } => {
+ return Ok(OperationEvaluationResult::Waiting(
+ EvaluationWaiting::TypedLiteral { value },
+ EvaluationResult::RequiresBaseType(base_type),
+ ));
+ }
+ Operation::Convert { base_type } => {
+ return Ok(OperationEvaluationResult::Waiting(
+ EvaluationWaiting::Convert,
+ EvaluationResult::RequiresBaseType(base_type),
+ ));
+ }
+ Operation::Reinterpret { base_type } => {
+ return Ok(OperationEvaluationResult::Waiting(
+ EvaluationWaiting::Reinterpret,
+ EvaluationResult::RequiresBaseType(base_type),
+ ));
+ }
+ Operation::WasmLocal { .. }
+ | Operation::WasmGlobal { .. }
+ | Operation::WasmStack { .. } => {
+ return Err(Error::UnsupportedEvaluation);
+ }
+ }
+
+ Ok(OperationEvaluationResult::Incomplete)
+ }
+
+ /// Get the result of this `Evaluation`.
+ ///
+ /// # Panics
+ /// Panics if this `Evaluation` has not been driven to completion.
+ pub fn as_result(&self) -> &[Piece<R>] {
+ match self.state {
+ EvaluationState::Complete => &self.result,
+ _ => {
+ panic!("Called `Evaluation::result` on an `Evaluation` that has not been completed")
+ }
+ }
+ }
+
+ /// Evaluate a DWARF expression. This method should only ever be called
+ /// once. If the returned `EvaluationResult` is not
+ /// `EvaluationResult::Complete`, the caller should provide the required
+ /// value and resume the evaluation by calling the appropriate resume_with
+ /// method on `Evaluation`.
+ pub fn evaluate(&mut self) -> Result<EvaluationResult<R>> {
+ match self.state {
+ EvaluationState::Start(initial_value) => {
+ if let Some(value) = initial_value {
+ self.push(Value::Generic(value))?;
+ }
+ self.state = EvaluationState::Ready;
+ }
+ EvaluationState::Ready => {}
+ EvaluationState::Error(err) => return Err(err),
+ EvaluationState::Complete => return Ok(EvaluationResult::Complete),
+ EvaluationState::Waiting(_) => panic!(),
+ };
+
+ match self.evaluate_internal() {
+ Ok(r) => Ok(r),
+ Err(e) => {
+ self.state = EvaluationState::Error(e);
+ Err(e)
+ }
+ }
+ }
+
+ /// Resume the `Evaluation` with the provided memory `value`. This will apply
+ /// the provided memory value to the evaluation and continue evaluating
+ /// opcodes until the evaluation is completed, reaches an error, or needs
+ /// more information again.
+ ///
+ /// # Panics
+ /// Panics if this `Evaluation` did not previously stop with `EvaluationResult::RequiresMemory`.
+ pub fn resume_with_memory(&mut self, value: Value) -> Result<EvaluationResult<R>> {
+ match self.state {
+ EvaluationState::Error(err) => return Err(err),
+ EvaluationState::Waiting(EvaluationWaiting::Memory) => {
+ self.push(value)?;
+ }
+ _ => panic!(
+ "Called `Evaluation::resume_with_memory` without a preceding `EvaluationResult::RequiresMemory`"
+ ),
+ };
+
+ self.evaluate_internal()
+ }
+
+ /// Resume the `Evaluation` with the provided `register` value. This will apply
+ /// the provided register value to the evaluation and continue evaluating
+ /// opcodes until the evaluation is completed, reaches an error, or needs
+ /// more information again.
+ ///
+ /// # Panics
+ /// Panics if this `Evaluation` did not previously stop with `EvaluationResult::RequiresRegister`.
+ pub fn resume_with_register(&mut self, value: Value) -> Result<EvaluationResult<R>> {
+ match self.state {
+ EvaluationState::Error(err) => return Err(err),
+ EvaluationState::Waiting(EvaluationWaiting::Register { offset }) => {
+ let offset = Value::from_u64(value.value_type(), offset as u64)?;
+ let value = value.add(offset, self.addr_mask)?;
+ self.push(value)?;
+ }
+ _ => panic!(
+ "Called `Evaluation::resume_with_register` without a preceding `EvaluationResult::RequiresRegister`"
+ ),
+ };
+
+ self.evaluate_internal()
+ }
+
+ /// Resume the `Evaluation` with the provided `frame_base`. This will
+ /// apply the provided frame base value to the evaluation and continue
+ /// evaluating opcodes until the evaluation is completed, reaches an error,
+ /// or needs more information again.
+ ///
+ /// # Panics
+ /// Panics if this `Evaluation` did not previously stop with `EvaluationResult::RequiresFrameBase`.
+ pub fn resume_with_frame_base(&mut self, frame_base: u64) -> Result<EvaluationResult<R>> {
+ match self.state {
+ EvaluationState::Error(err) => return Err(err),
+ EvaluationState::Waiting(EvaluationWaiting::FrameBase { offset }) => {
+ self.push(Value::Generic(frame_base.wrapping_add(offset as u64)))?;
+ }
+ _ => panic!(
+ "Called `Evaluation::resume_with_frame_base` without a preceding `EvaluationResult::RequiresFrameBase`"
+ ),
+ };
+
+ self.evaluate_internal()
+ }
+
+ /// Resume the `Evaluation` with the provided `value`. This will apply
+ /// the provided TLS value to the evaluation and continue evaluating
+ /// opcodes until the evaluation is completed, reaches an error, or needs
+ /// more information again.
+ ///
+ /// # Panics
+ /// Panics if this `Evaluation` did not previously stop with `EvaluationResult::RequiresTls`.
+ pub fn resume_with_tls(&mut self, value: u64) -> Result<EvaluationResult<R>> {
+ match self.state {
+ EvaluationState::Error(err) => return Err(err),
+ EvaluationState::Waiting(EvaluationWaiting::Tls) => {
+ self.push(Value::Generic(value))?;
+ }
+ _ => panic!(
+ "Called `Evaluation::resume_with_tls` without a preceding `EvaluationResult::RequiresTls`"
+ ),
+ };
+
+ self.evaluate_internal()
+ }
+
+ /// Resume the `Evaluation` with the provided `cfa`. This will
+ /// apply the provided CFA value to the evaluation and continue evaluating
+ /// opcodes until the evaluation is completed, reaches an error, or needs
+ /// more information again.
+ ///
+ /// # Panics
+ /// Panics if this `Evaluation` did not previously stop with `EvaluationResult::RequiresCallFrameCfa`.
+ pub fn resume_with_call_frame_cfa(&mut self, cfa: u64) -> Result<EvaluationResult<R>> {
+ match self.state {
+ EvaluationState::Error(err) => return Err(err),
+ EvaluationState::Waiting(EvaluationWaiting::Cfa) => {
+ self.push(Value::Generic(cfa))?;
+ }
+ _ => panic!(
+ "Called `Evaluation::resume_with_call_frame_cfa` without a preceding `EvaluationResult::RequiresCallFrameCfa`"
+ ),
+ };
+
+ self.evaluate_internal()
+ }
+
+ /// Resume the `Evaluation` with the provided `bytes`. This will
+ /// continue processing the evaluation with the new expression provided
+ /// until the evaluation is completed, reaches an error, or needs more
+ /// information again.
+ ///
+ /// # Panics
+ /// Panics if this `Evaluation` did not previously stop with `EvaluationResult::RequiresAtLocation`.
+ pub fn resume_with_at_location(&mut self, mut bytes: R) -> Result<EvaluationResult<R>> {
+ match self.state {
+ EvaluationState::Error(err) => return Err(err),
+ EvaluationState::Waiting(EvaluationWaiting::AtLocation) => {
+ if !bytes.is_empty() {
+ let mut pc = bytes.clone();
+ mem::swap(&mut pc, &mut self.pc);
+ mem::swap(&mut bytes, &mut self.bytecode);
+ self.expression_stack.try_push((pc, bytes)).map_err(|_| Error::StackFull)?;
+ }
+ }
+ _ => panic!(
+ "Called `Evaluation::resume_with_at_location` without a precedeing `EvaluationResult::RequiresAtLocation`"
+ ),
+ };
+
+ self.evaluate_internal()
+ }
+
+ /// Resume the `Evaluation` with the provided `entry_value`. This will
+ /// apply the provided entry value to the evaluation and continue evaluating
+ /// opcodes until the evaluation is completed, reaches an error, or needs
+ /// more information again.
+ ///
+ /// # Panics
+ /// Panics if this `Evaluation` did not previously stop with `EvaluationResult::RequiresEntryValue`.
+ pub fn resume_with_entry_value(&mut self, entry_value: Value) -> Result<EvaluationResult<R>> {
+ match self.state {
+ EvaluationState::Error(err) => return Err(err),
+ EvaluationState::Waiting(EvaluationWaiting::EntryValue) => {
+ self.push(entry_value)?;
+ }
+ _ => panic!(
+ "Called `Evaluation::resume_with_entry_value` without a preceding `EvaluationResult::RequiresEntryValue`"
+ ),
+ };
+
+ self.evaluate_internal()
+ }
+
+ /// Resume the `Evaluation` with the provided `parameter_value`. This will
+ /// apply the provided parameter value to the evaluation and continue evaluating
+ /// opcodes until the evaluation is completed, reaches an error, or needs
+ /// more information again.
+ ///
+ /// # Panics
+ /// Panics if this `Evaluation` did not previously stop with `EvaluationResult::RequiresParameterRef`.
+ pub fn resume_with_parameter_ref(
+ &mut self,
+ parameter_value: u64,
+ ) -> Result<EvaluationResult<R>> {
+ match self.state {
+ EvaluationState::Error(err) => return Err(err),
+ EvaluationState::Waiting(EvaluationWaiting::ParameterRef) => {
+ self.push(Value::Generic(parameter_value))?;
+ }
+ _ => panic!(
+ "Called `Evaluation::resume_with_parameter_ref` without a preceding `EvaluationResult::RequiresParameterRef`"
+ ),
+ };
+
+ self.evaluate_internal()
+ }
+
+ /// Resume the `Evaluation` with the provided relocated `address`. This will use the
+ /// provided relocated address for the operation that required it, and continue evaluating
+ /// opcodes until the evaluation is completed, reaches an error, or needs
+ /// more information again.
+ ///
+ /// # Panics
+ /// Panics if this `Evaluation` did not previously stop with
+ /// `EvaluationResult::RequiresRelocatedAddress`.
+ pub fn resume_with_relocated_address(&mut self, address: u64) -> Result<EvaluationResult<R>> {
+ match self.state {
+ EvaluationState::Error(err) => return Err(err),
+ EvaluationState::Waiting(EvaluationWaiting::RelocatedAddress) => {
+ self.push(Value::Generic(address))?;
+ }
+ _ => panic!(
+ "Called `Evaluation::resume_with_relocated_address` without a preceding `EvaluationResult::RequiresRelocatedAddress`"
+ ),
+ };
+
+ self.evaluate_internal()
+ }
+
+ /// Resume the `Evaluation` with the provided indexed `address`. This will use the
+ /// provided indexed address for the operation that required it, and continue evaluating
+ /// opcodes until the evaluation is completed, reaches an error, or needs
+ /// more information again.
+ ///
+ /// # Panics
+ /// Panics if this `Evaluation` did not previously stop with
+ /// `EvaluationResult::RequiresIndexedAddress`.
+ pub fn resume_with_indexed_address(&mut self, address: u64) -> Result<EvaluationResult<R>> {
+ match self.state {
+ EvaluationState::Error(err) => return Err(err),
+ EvaluationState::Waiting(EvaluationWaiting::IndexedAddress) => {
+ self.push(Value::Generic(address))?;
+ }
+ _ => panic!(
+ "Called `Evaluation::resume_with_indexed_address` without a preceding `EvaluationResult::RequiresIndexedAddress`"
+ ),
+ };
+
+ self.evaluate_internal()
+ }
+
+ /// Resume the `Evaluation` with the provided `base_type`. This will use the
+ /// provided base type for the operation that required it, and continue evaluating
+ /// opcodes until the evaluation is completed, reaches an error, or needs
+ /// more information again.
+ ///
+ /// # Panics
+ /// Panics if this `Evaluation` did not previously stop with `EvaluationResult::RequiresBaseType`.
+ pub fn resume_with_base_type(&mut self, base_type: ValueType) -> Result<EvaluationResult<R>> {
+ let value = match self.state {
+ EvaluationState::Error(err) => return Err(err),
+ EvaluationState::Waiting(EvaluationWaiting::TypedLiteral { ref value }) => {
+ Value::parse(base_type, value.clone())?
+ }
+ EvaluationState::Waiting(EvaluationWaiting::Convert) => {
+ let entry = self.pop()?;
+ entry.convert(base_type, self.addr_mask)?
+ }
+ EvaluationState::Waiting(EvaluationWaiting::Reinterpret) => {
+ let entry = self.pop()?;
+ entry.reinterpret(base_type, self.addr_mask)?
+ }
+ _ => panic!(
+ "Called `Evaluation::resume_with_base_type` without a preceding `EvaluationResult::RequiresBaseType`"
+ ),
+ };
+ self.push(value)?;
+ self.evaluate_internal()
+ }
+
+ fn end_of_expression(&mut self) -> bool {
+ while self.pc.is_empty() {
+ match self.expression_stack.pop() {
+ Some((newpc, newbytes)) => {
+ self.pc = newpc;
+ self.bytecode = newbytes;
+ }
+ None => return true,
+ }
+ }
+ false
+ }
+
+ fn evaluate_internal(&mut self) -> Result<EvaluationResult<R>> {
+ while !self.end_of_expression() {
+ self.iteration += 1;
+ if let Some(max_iterations) = self.max_iterations {
+ if self.iteration > max_iterations {
+ return Err(Error::TooManyIterations);
+ }
+ }
+
+ let op_result = self.evaluate_one_operation()?;
+ match op_result {
+ OperationEvaluationResult::Piece => {}
+ OperationEvaluationResult::Incomplete => {
+ if self.end_of_expression() && !self.result.is_empty() {
+ // We saw a piece earlier and then some
+ // unterminated piece. It's not clear this is
+ // well-defined.
+ return Err(Error::InvalidPiece);
+ }
+ }
+ OperationEvaluationResult::Complete { location } => {
+ if self.end_of_expression() {
+ if !self.result.is_empty() {
+ // We saw a piece earlier and then some
+ // unterminated piece. It's not clear this is
+ // well-defined.
+ return Err(Error::InvalidPiece);
+ }
+ self.result
+ .try_push(Piece {
+ size_in_bits: None,
+ bit_offset: None,
+ location,
+ })
+ .map_err(|_| Error::StackFull)?;
+ } else {
+ // If there are more operations, then the next operation must
+ // be a Piece.
+ match Operation::parse(&mut self.pc, self.encoding)? {
+ Operation::Piece {
+ size_in_bits,
+ bit_offset,
+ } => {
+ self.result
+ .try_push(Piece {
+ size_in_bits: Some(size_in_bits),
+ bit_offset,
+ location,
+ })
+ .map_err(|_| Error::StackFull)?;
+ }
+ _ => {
+ let value =
+ self.bytecode.len().into_u64() - self.pc.len().into_u64() - 1;
+ return Err(Error::InvalidExpressionTerminator(value));
+ }
+ }
+ }
+ }
+ OperationEvaluationResult::Waiting(waiting, result) => {
+ self.state = EvaluationState::Waiting(waiting);
+ return Ok(result);
+ }
+ };
+ }
+
+ // If no pieces have been seen, use the stack top as the
+ // result.
+ if self.result.is_empty() {
+ let entry = self.pop()?;
+ let addr = entry.to_u64(self.addr_mask)?;
+ self.result
+ .try_push(Piece {
+ size_in_bits: None,
+ bit_offset: None,
+ location: Location::Address { address: addr },
+ })
+ .map_err(|_| Error::StackFull)?;
+ }
+
+ self.state = EvaluationState::Complete;
+ Ok(EvaluationResult::Complete)
+ }
+}
+
+#[cfg(test)]
+// Tests require leb128::write.
+#[cfg(feature = "write")]
+mod tests {
+ use super::*;
+ use crate::common::Format;
+ use crate::constants;
+ use crate::endianity::LittleEndian;
+ use crate::leb128;
+ use crate::read::{EndianSlice, Error, Result, UnitOffset};
+ use crate::test_util::GimliSectionMethods;
+ use core::usize;
+ use test_assembler::{Endian, Section};
+
+ fn encoding4() -> Encoding {
+ Encoding {
+ format: Format::Dwarf32,
+ version: 4,
+ address_size: 4,
+ }
+ }
+
+ fn encoding8() -> Encoding {
+ Encoding {
+ format: Format::Dwarf64,
+ version: 4,
+ address_size: 8,
+ }
+ }
+
+ #[test]
+ fn test_compute_pc() {
+ // Contents don't matter for this test, just length.
+ let bytes = [0, 1, 2, 3, 4];
+ let bytecode = &bytes[..];
+ let ebuf = &EndianSlice::new(bytecode, LittleEndian);
+
+ assert_eq!(compute_pc(ebuf, ebuf, 0), Ok(*ebuf));
+ assert_eq!(
+ compute_pc(ebuf, ebuf, -1),
+ Err(Error::BadBranchTarget(usize::MAX as u64))
+ );
+ assert_eq!(compute_pc(ebuf, ebuf, 5), Ok(ebuf.range_from(5..)));
+ assert_eq!(
+ compute_pc(&ebuf.range_from(3..), ebuf, -2),
+ Ok(ebuf.range_from(1..))
+ );
+ assert_eq!(
+ compute_pc(&ebuf.range_from(2..), ebuf, 2),
+ Ok(ebuf.range_from(4..))
+ );
+ }
+
+ fn check_op_parse_simple<'input>(
+ input: &'input [u8],
+ expect: &Operation<EndianSlice<'input, LittleEndian>>,
+ encoding: Encoding,
+ ) {
+ let buf = EndianSlice::new(input, LittleEndian);
+ let mut pc = buf;
+ let value = Operation::parse(&mut pc, encoding);
+ match value {
+ Ok(val) => {
+ assert_eq!(val, *expect);
+ assert_eq!(pc.len(), 0);
+ }
+ _ => panic!("Unexpected result"),
+ }
+ }
+
+ fn check_op_parse_eof(input: &[u8], encoding: Encoding) {
+ let buf = EndianSlice::new(input, LittleEndian);
+ let mut pc = buf;
+ match Operation::parse(&mut pc, encoding) {
+ Err(Error::UnexpectedEof(id)) => {
+ assert!(buf.lookup_offset_id(id).is_some());
+ }
+
+ _ => panic!("Unexpected result"),
+ }
+ }
+
+ fn check_op_parse<F>(
+ input: F,
+ expect: &Operation<EndianSlice<LittleEndian>>,
+ encoding: Encoding,
+ ) where
+ F: Fn(Section) -> Section,
+ {
+ let input = input(Section::with_endian(Endian::Little))
+ .get_contents()
+ .unwrap();
+ for i in 1..input.len() {
+ check_op_parse_eof(&input[..i], encoding);
+ }
+ check_op_parse_simple(&input, expect, encoding);
+ }
+
+ #[test]
+ fn test_op_parse_onebyte() {
+ // Doesn't matter for this test.
+ let encoding = encoding4();
+
+ // Test all single-byte opcodes.
+ #[rustfmt::skip]
+ let inputs = [
+ (
+ constants::DW_OP_deref,
+ Operation::Deref {
+ base_type: generic_type(),
+ size: encoding.address_size,
+ space: false,
+ },
+ ),
+ (constants::DW_OP_dup, Operation::Pick { index: 0 }),
+ (constants::DW_OP_drop, Operation::Drop),
+ (constants::DW_OP_over, Operation::Pick { index: 1 }),
+ (constants::DW_OP_swap, Operation::Swap),
+ (constants::DW_OP_rot, Operation::Rot),
+ (
+ constants::DW_OP_xderef,
+ Operation::Deref {
+ base_type: generic_type(),
+ size: encoding.address_size,
+ space: true,
+ },
+ ),
+ (constants::DW_OP_abs, Operation::Abs),
+ (constants::DW_OP_and, Operation::And),
+ (constants::DW_OP_div, Operation::Div),
+ (constants::DW_OP_minus, Operation::Minus),
+ (constants::DW_OP_mod, Operation::Mod),
+ (constants::DW_OP_mul, Operation::Mul),
+ (constants::DW_OP_neg, Operation::Neg),
+ (constants::DW_OP_not, Operation::Not),
+ (constants::DW_OP_or, Operation::Or),
+ (constants::DW_OP_plus, Operation::Plus),
+ (constants::DW_OP_shl, Operation::Shl),
+ (constants::DW_OP_shr, Operation::Shr),
+ (constants::DW_OP_shra, Operation::Shra),
+ (constants::DW_OP_xor, Operation::Xor),
+ (constants::DW_OP_eq, Operation::Eq),
+ (constants::DW_OP_ge, Operation::Ge),
+ (constants::DW_OP_gt, Operation::Gt),
+ (constants::DW_OP_le, Operation::Le),
+ (constants::DW_OP_lt, Operation::Lt),
+ (constants::DW_OP_ne, Operation::Ne),
+ (constants::DW_OP_lit0, Operation::UnsignedConstant { value: 0 }),
+ (constants::DW_OP_lit1, Operation::UnsignedConstant { value: 1 }),
+ (constants::DW_OP_lit2, Operation::UnsignedConstant { value: 2 }),
+ (constants::DW_OP_lit3, Operation::UnsignedConstant { value: 3 }),
+ (constants::DW_OP_lit4, Operation::UnsignedConstant { value: 4 }),
+ (constants::DW_OP_lit5, Operation::UnsignedConstant { value: 5 }),
+ (constants::DW_OP_lit6, Operation::UnsignedConstant { value: 6 }),
+ (constants::DW_OP_lit7, Operation::UnsignedConstant { value: 7 }),
+ (constants::DW_OP_lit8, Operation::UnsignedConstant { value: 8 }),
+ (constants::DW_OP_lit9, Operation::UnsignedConstant { value: 9 }),
+ (constants::DW_OP_lit10, Operation::UnsignedConstant { value: 10 }),
+ (constants::DW_OP_lit11, Operation::UnsignedConstant { value: 11 }),
+ (constants::DW_OP_lit12, Operation::UnsignedConstant { value: 12 }),
+ (constants::DW_OP_lit13, Operation::UnsignedConstant { value: 13 }),
+ (constants::DW_OP_lit14, Operation::UnsignedConstant { value: 14 }),
+ (constants::DW_OP_lit15, Operation::UnsignedConstant { value: 15 }),
+ (constants::DW_OP_lit16, Operation::UnsignedConstant { value: 16 }),
+ (constants::DW_OP_lit17, Operation::UnsignedConstant { value: 17 }),
+ (constants::DW_OP_lit18, Operation::UnsignedConstant { value: 18 }),
+ (constants::DW_OP_lit19, Operation::UnsignedConstant { value: 19 }),
+ (constants::DW_OP_lit20, Operation::UnsignedConstant { value: 20 }),
+ (constants::DW_OP_lit21, Operation::UnsignedConstant { value: 21 }),
+ (constants::DW_OP_lit22, Operation::UnsignedConstant { value: 22 }),
+ (constants::DW_OP_lit23, Operation::UnsignedConstant { value: 23 }),
+ (constants::DW_OP_lit24, Operation::UnsignedConstant { value: 24 }),
+ (constants::DW_OP_lit25, Operation::UnsignedConstant { value: 25 }),
+ (constants::DW_OP_lit26, Operation::UnsignedConstant { value: 26 }),
+ (constants::DW_OP_lit27, Operation::UnsignedConstant { value: 27 }),
+ (constants::DW_OP_lit28, Operation::UnsignedConstant { value: 28 }),
+ (constants::DW_OP_lit29, Operation::UnsignedConstant { value: 29 }),
+ (constants::DW_OP_lit30, Operation::UnsignedConstant { value: 30 }),
+ (constants::DW_OP_lit31, Operation::UnsignedConstant { value: 31 }),
+ (constants::DW_OP_reg0, Operation::Register { register: Register(0) }),
+ (constants::DW_OP_reg1, Operation::Register { register: Register(1) }),
+ (constants::DW_OP_reg2, Operation::Register { register: Register(2) }),
+ (constants::DW_OP_reg3, Operation::Register { register: Register(3) }),
+ (constants::DW_OP_reg4, Operation::Register { register: Register(4) }),
+ (constants::DW_OP_reg5, Operation::Register { register: Register(5) }),
+ (constants::DW_OP_reg6, Operation::Register { register: Register(6) }),
+ (constants::DW_OP_reg7, Operation::Register { register: Register(7) }),
+ (constants::DW_OP_reg8, Operation::Register { register: Register(8) }),
+ (constants::DW_OP_reg9, Operation::Register { register: Register(9) }),
+ (constants::DW_OP_reg10, Operation::Register { register: Register(10) }),
+ (constants::DW_OP_reg11, Operation::Register { register: Register(11) }),
+ (constants::DW_OP_reg12, Operation::Register { register: Register(12) }),
+ (constants::DW_OP_reg13, Operation::Register { register: Register(13) }),
+ (constants::DW_OP_reg14, Operation::Register { register: Register(14) }),
+ (constants::DW_OP_reg15, Operation::Register { register: Register(15) }),
+ (constants::DW_OP_reg16, Operation::Register { register: Register(16) }),
+ (constants::DW_OP_reg17, Operation::Register { register: Register(17) }),
+ (constants::DW_OP_reg18, Operation::Register { register: Register(18) }),
+ (constants::DW_OP_reg19, Operation::Register { register: Register(19) }),
+ (constants::DW_OP_reg20, Operation::Register { register: Register(20) }),
+ (constants::DW_OP_reg21, Operation::Register { register: Register(21) }),
+ (constants::DW_OP_reg22, Operation::Register { register: Register(22) }),
+ (constants::DW_OP_reg23, Operation::Register { register: Register(23) }),
+ (constants::DW_OP_reg24, Operation::Register { register: Register(24) }),
+ (constants::DW_OP_reg25, Operation::Register { register: Register(25) }),
+ (constants::DW_OP_reg26, Operation::Register { register: Register(26) }),
+ (constants::DW_OP_reg27, Operation::Register { register: Register(27) }),
+ (constants::DW_OP_reg28, Operation::Register { register: Register(28) }),
+ (constants::DW_OP_reg29, Operation::Register { register: Register(29) }),
+ (constants::DW_OP_reg30, Operation::Register { register: Register(30) }),
+ (constants::DW_OP_reg31, Operation::Register { register: Register(31) }),
+ (constants::DW_OP_nop, Operation::Nop),
+ (constants::DW_OP_push_object_address, Operation::PushObjectAddress),
+ (constants::DW_OP_form_tls_address, Operation::TLS),
+ (constants::DW_OP_GNU_push_tls_address, Operation::TLS),
+ (constants::DW_OP_call_frame_cfa, Operation::CallFrameCFA),
+ (constants::DW_OP_stack_value, Operation::StackValue),
+ ];
+
+ let input = [];
+ check_op_parse_eof(&input[..], encoding);
+
+ for item in inputs.iter() {
+ let (opcode, ref result) = *item;
+ check_op_parse(|s| s.D8(opcode.0), result, encoding);
+ }
+ }
+
+ #[test]
+ fn test_op_parse_twobyte() {
+ // Doesn't matter for this test.
+ let encoding = encoding4();
+
+ let inputs = [
+ (
+ constants::DW_OP_const1u,
+ 23,
+ Operation::UnsignedConstant { value: 23 },
+ ),
+ (
+ constants::DW_OP_const1s,
+ (-23i8) as u8,
+ Operation::SignedConstant { value: -23 },
+ ),
+ (constants::DW_OP_pick, 7, Operation::Pick { index: 7 }),
+ (
+ constants::DW_OP_deref_size,
+ 19,
+ Operation::Deref {
+ base_type: generic_type(),
+ size: 19,
+ space: false,
+ },
+ ),
+ (
+ constants::DW_OP_xderef_size,
+ 19,
+ Operation::Deref {
+ base_type: generic_type(),
+ size: 19,
+ space: true,
+ },
+ ),
+ ];
+
+ for item in inputs.iter() {
+ let (opcode, arg, ref result) = *item;
+ check_op_parse(|s| s.D8(opcode.0).D8(arg), result, encoding);
+ }
+ }
+
+ #[test]
+ fn test_op_parse_threebyte() {
+ // Doesn't matter for this test.
+ let encoding = encoding4();
+
+ // While bra and skip are 3-byte opcodes, they aren't tested here,
+ // but rather specially in their own function.
+ let inputs = [
+ (
+ constants::DW_OP_const2u,
+ 23,
+ Operation::UnsignedConstant { value: 23 },
+ ),
+ (
+ constants::DW_OP_const2s,
+ (-23i16) as u16,
+ Operation::SignedConstant { value: -23 },
+ ),
+ (
+ constants::DW_OP_call2,
+ 1138,
+ Operation::Call {
+ offset: DieReference::UnitRef(UnitOffset(1138)),
+ },
+ ),
+ (
+ constants::DW_OP_bra,
+ (-23i16) as u16,
+ Operation::Bra { target: -23 },
+ ),
+ (
+ constants::DW_OP_skip,
+ (-23i16) as u16,
+ Operation::Skip { target: -23 },
+ ),
+ ];
+
+ for item in inputs.iter() {
+ let (opcode, arg, ref result) = *item;
+ check_op_parse(|s| s.D8(opcode.0).L16(arg), result, encoding);
+ }
+ }
+
+ #[test]
+ fn test_op_parse_fivebyte() {
+ // There are some tests here that depend on address size.
+ let encoding = encoding4();
+
+ let inputs = [
+ (
+ constants::DW_OP_addr,
+ 0x1234_5678,
+ Operation::Address {
+ address: 0x1234_5678,
+ },
+ ),
+ (
+ constants::DW_OP_const4u,
+ 0x1234_5678,
+ Operation::UnsignedConstant { value: 0x1234_5678 },
+ ),
+ (
+ constants::DW_OP_const4s,
+ (-23i32) as u32,
+ Operation::SignedConstant { value: -23 },
+ ),
+ (
+ constants::DW_OP_call4,
+ 0x1234_5678,
+ Operation::Call {
+ offset: DieReference::UnitRef(UnitOffset(0x1234_5678)),
+ },
+ ),
+ (
+ constants::DW_OP_call_ref,
+ 0x1234_5678,
+ Operation::Call {
+ offset: DieReference::DebugInfoRef(DebugInfoOffset(0x1234_5678)),
+ },
+ ),
+ ];
+
+ for item in inputs.iter() {
+ let (op, arg, ref expect) = *item;
+ check_op_parse(|s| s.D8(op.0).L32(arg), expect, encoding);
+ }
+ }
+
+ #[test]
+ #[cfg(target_pointer_width = "64")]
+ fn test_op_parse_ninebyte() {
+ // There are some tests here that depend on address size.
+ let encoding = encoding8();
+
+ let inputs = [
+ (
+ constants::DW_OP_addr,
+ 0x1234_5678_1234_5678,
+ Operation::Address {
+ address: 0x1234_5678_1234_5678,
+ },
+ ),
+ (
+ constants::DW_OP_const8u,
+ 0x1234_5678_1234_5678,
+ Operation::UnsignedConstant {
+ value: 0x1234_5678_1234_5678,
+ },
+ ),
+ (
+ constants::DW_OP_const8s,
+ (-23i64) as u64,
+ Operation::SignedConstant { value: -23 },
+ ),
+ (
+ constants::DW_OP_call_ref,
+ 0x1234_5678_1234_5678,
+ Operation::Call {
+ offset: DieReference::DebugInfoRef(DebugInfoOffset(0x1234_5678_1234_5678)),
+ },
+ ),
+ ];
+
+ for item in inputs.iter() {
+ let (op, arg, ref expect) = *item;
+ check_op_parse(|s| s.D8(op.0).L64(arg), expect, encoding);
+ }
+ }
+
+ #[test]
+ fn test_op_parse_sleb() {
+ // Doesn't matter for this test.
+ let encoding = encoding4();
+
+ let values = [
+ -1i64,
+ 0,
+ 1,
+ 0x100,
+ 0x1eee_eeee,
+ 0x7fff_ffff_ffff_ffff,
+ -0x100,
+ -0x1eee_eeee,
+ -0x7fff_ffff_ffff_ffff,
+ ];
+ for value in values.iter() {
+ let mut inputs = vec![
+ (
+ constants::DW_OP_consts.0,
+ Operation::SignedConstant { value: *value },
+ ),
+ (
+ constants::DW_OP_fbreg.0,
+ Operation::FrameOffset { offset: *value },
+ ),
+ ];
+
+ for i in 0..32 {
+ inputs.push((
+ constants::DW_OP_breg0.0 + i,
+ Operation::RegisterOffset {
+ register: Register(i.into()),
+ offset: *value,
+ base_type: UnitOffset(0),
+ },
+ ));
+ }
+
+ for item in inputs.iter() {
+ let (op, ref expect) = *item;
+ check_op_parse(|s| s.D8(op).sleb(*value), expect, encoding);
+ }
+ }
+ }
+
+ #[test]
+ fn test_op_parse_uleb() {
+ // Doesn't matter for this test.
+ let encoding = encoding4();
+
+ let values = [
+ 0,
+ 1,
+ 0x100,
+ (!0u16).into(),
+ 0x1eee_eeee,
+ 0x7fff_ffff_ffff_ffff,
+ !0u64,
+ ];
+ for value in values.iter() {
+ let mut inputs = vec![
+ (
+ constants::DW_OP_constu,
+ Operation::UnsignedConstant { value: *value },
+ ),
+ (
+ constants::DW_OP_plus_uconst,
+ Operation::PlusConstant { value: *value },
+ ),
+ ];
+
+ if *value <= (!0u16).into() {
+ inputs.push((
+ constants::DW_OP_regx,
+ Operation::Register {
+ register: Register::from_u64(*value).unwrap(),
+ },
+ ));
+ }
+
+ if *value <= (!0u32).into() {
+ inputs.extend(&[
+ (
+ constants::DW_OP_addrx,
+ Operation::AddressIndex {
+ index: DebugAddrIndex(*value as usize),
+ },
+ ),
+ (
+ constants::DW_OP_constx,
+ Operation::ConstantIndex {
+ index: DebugAddrIndex(*value as usize),
+ },
+ ),
+ ]);
+ }
+
+ // FIXME
+ if *value < !0u64 / 8 {
+ inputs.push((
+ constants::DW_OP_piece,
+ Operation::Piece {
+ size_in_bits: 8 * value,
+ bit_offset: None,
+ },
+ ));
+ }
+
+ for item in inputs.iter() {
+ let (op, ref expect) = *item;
+ let input = Section::with_endian(Endian::Little)
+ .D8(op.0)
+ .uleb(*value)
+ .get_contents()
+ .unwrap();
+ check_op_parse_simple(&input, expect, encoding);
+ }
+ }
+ }
+
+ #[test]
+ fn test_op_parse_bregx() {
+ // Doesn't matter for this test.
+ let encoding = encoding4();
+
+ let uvalues = [0, 1, 0x100, !0u16];
+ let svalues = [
+ -1i64,
+ 0,
+ 1,
+ 0x100,
+ 0x1eee_eeee,
+ 0x7fff_ffff_ffff_ffff,
+ -0x100,
+ -0x1eee_eeee,
+ -0x7fff_ffff_ffff_ffff,
+ ];
+
+ for v1 in uvalues.iter() {
+ for v2 in svalues.iter() {
+ check_op_parse(
+ |s| s.D8(constants::DW_OP_bregx.0).uleb((*v1).into()).sleb(*v2),
+ &Operation::RegisterOffset {
+ register: Register(*v1),
+ offset: *v2,
+ base_type: UnitOffset(0),
+ },
+ encoding,
+ );
+ }
+ }
+ }
+
+ #[test]
+ fn test_op_parse_bit_piece() {
+ // Doesn't matter for this test.
+ let encoding = encoding4();
+
+ let values = [0, 1, 0x100, 0x1eee_eeee, 0x7fff_ffff_ffff_ffff, !0u64];
+
+ for v1 in values.iter() {
+ for v2 in values.iter() {
+ let input = Section::with_endian(Endian::Little)
+ .D8(constants::DW_OP_bit_piece.0)
+ .uleb(*v1)
+ .uleb(*v2)
+ .get_contents()
+ .unwrap();
+ check_op_parse_simple(
+ &input,
+ &Operation::Piece {
+ size_in_bits: *v1,
+ bit_offset: Some(*v2),
+ },
+ encoding,
+ );
+ }
+ }
+ }
+
+ #[test]
+ fn test_op_parse_implicit_value() {
+ // Doesn't matter for this test.
+ let encoding = encoding4();
+
+ let data = b"hello";
+
+ check_op_parse(
+ |s| {
+ s.D8(constants::DW_OP_implicit_value.0)
+ .uleb(data.len() as u64)
+ .append_bytes(&data[..])
+ },
+ &Operation::ImplicitValue {
+ data: EndianSlice::new(&data[..], LittleEndian),
+ },
+ encoding,
+ );
+ }
+
+ #[test]
+ fn test_op_parse_const_type() {
+ // Doesn't matter for this test.
+ let encoding = encoding4();
+
+ let data = b"hello";
+
+ check_op_parse(
+ |s| {
+ s.D8(constants::DW_OP_const_type.0)
+ .uleb(100)
+ .D8(data.len() as u8)
+ .append_bytes(&data[..])
+ },
+ &Operation::TypedLiteral {
+ base_type: UnitOffset(100),
+ value: EndianSlice::new(&data[..], LittleEndian),
+ },
+ encoding,
+ );
+ check_op_parse(
+ |s| {
+ s.D8(constants::DW_OP_GNU_const_type.0)
+ .uleb(100)
+ .D8(data.len() as u8)
+ .append_bytes(&data[..])
+ },
+ &Operation::TypedLiteral {
+ base_type: UnitOffset(100),
+ value: EndianSlice::new(&data[..], LittleEndian),
+ },
+ encoding,
+ );
+ }
+
+ #[test]
+ fn test_op_parse_regval_type() {
+ // Doesn't matter for this test.
+ let encoding = encoding4();
+
+ check_op_parse(
+ |s| s.D8(constants::DW_OP_regval_type.0).uleb(1).uleb(100),
+ &Operation::RegisterOffset {
+ register: Register(1),
+ offset: 0,
+ base_type: UnitOffset(100),
+ },
+ encoding,
+ );
+ check_op_parse(
+ |s| s.D8(constants::DW_OP_GNU_regval_type.0).uleb(1).uleb(100),
+ &Operation::RegisterOffset {
+ register: Register(1),
+ offset: 0,
+ base_type: UnitOffset(100),
+ },
+ encoding,
+ );
+ }
+
+ #[test]
+ fn test_op_parse_deref_type() {
+ // Doesn't matter for this test.
+ let encoding = encoding4();
+
+ check_op_parse(
+ |s| s.D8(constants::DW_OP_deref_type.0).D8(8).uleb(100),
+ &Operation::Deref {
+ base_type: UnitOffset(100),
+ size: 8,
+ space: false,
+ },
+ encoding,
+ );
+ check_op_parse(
+ |s| s.D8(constants::DW_OP_GNU_deref_type.0).D8(8).uleb(100),
+ &Operation::Deref {
+ base_type: UnitOffset(100),
+ size: 8,
+ space: false,
+ },
+ encoding,
+ );
+ check_op_parse(
+ |s| s.D8(constants::DW_OP_xderef_type.0).D8(8).uleb(100),
+ &Operation::Deref {
+ base_type: UnitOffset(100),
+ size: 8,
+ space: true,
+ },
+ encoding,
+ );
+ }
+
+ #[test]
+ fn test_op_convert() {
+ // Doesn't matter for this test.
+ let encoding = encoding4();
+
+ check_op_parse(
+ |s| s.D8(constants::DW_OP_convert.0).uleb(100),
+ &Operation::Convert {
+ base_type: UnitOffset(100),
+ },
+ encoding,
+ );
+ check_op_parse(
+ |s| s.D8(constants::DW_OP_GNU_convert.0).uleb(100),
+ &Operation::Convert {
+ base_type: UnitOffset(100),
+ },
+ encoding,
+ );
+ }
+
+ #[test]
+ fn test_op_reinterpret() {
+ // Doesn't matter for this test.
+ let encoding = encoding4();
+
+ check_op_parse(
+ |s| s.D8(constants::DW_OP_reinterpret.0).uleb(100),
+ &Operation::Reinterpret {
+ base_type: UnitOffset(100),
+ },
+ encoding,
+ );
+ check_op_parse(
+ |s| s.D8(constants::DW_OP_GNU_reinterpret.0).uleb(100),
+ &Operation::Reinterpret {
+ base_type: UnitOffset(100),
+ },
+ encoding,
+ );
+ }
+
+ #[test]
+ fn test_op_parse_implicit_pointer() {
+ for op in &[
+ constants::DW_OP_implicit_pointer,
+ constants::DW_OP_GNU_implicit_pointer,
+ ] {
+ check_op_parse(
+ |s| s.D8(op.0).D32(0x1234_5678).sleb(0x123),
+ &Operation::ImplicitPointer {
+ value: DebugInfoOffset(0x1234_5678),
+ byte_offset: 0x123,
+ },
+ encoding4(),
+ );
+
+ check_op_parse(
+ |s| s.D8(op.0).D64(0x1234_5678).sleb(0x123),
+ &Operation::ImplicitPointer {
+ value: DebugInfoOffset(0x1234_5678),
+ byte_offset: 0x123,
+ },
+ encoding8(),
+ );
+
+ check_op_parse(
+ |s| s.D8(op.0).D64(0x1234_5678).sleb(0x123),
+ &Operation::ImplicitPointer {
+ value: DebugInfoOffset(0x1234_5678),
+ byte_offset: 0x123,
+ },
+ Encoding {
+ format: Format::Dwarf32,
+ version: 2,
+ address_size: 8,
+ },
+ )
+ }
+ }
+
+ #[test]
+ fn test_op_parse_entry_value() {
+ for op in &[
+ constants::DW_OP_entry_value,
+ constants::DW_OP_GNU_entry_value,
+ ] {
+ let data = b"hello";
+ check_op_parse(
+ |s| s.D8(op.0).uleb(data.len() as u64).append_bytes(&data[..]),
+ &Operation::EntryValue {
+ expression: EndianSlice::new(&data[..], LittleEndian),
+ },
+ encoding4(),
+ );
+ }
+ }
+
+ #[test]
+ fn test_op_parse_gnu_parameter_ref() {
+ check_op_parse(
+ |s| s.D8(constants::DW_OP_GNU_parameter_ref.0).D32(0x1234_5678),
+ &Operation::ParameterRef {
+ offset: UnitOffset(0x1234_5678),
+ },
+ encoding4(),
+ )
+ }
+
+ #[test]
+ fn test_op_wasm() {
+ // Doesn't matter for this test.
+ let encoding = encoding4();
+
+ check_op_parse(
+ |s| s.D8(constants::DW_OP_WASM_location.0).D8(0).uleb(1000),
+ &Operation::WasmLocal { index: 1000 },
+ encoding,
+ );
+ check_op_parse(
+ |s| s.D8(constants::DW_OP_WASM_location.0).D8(1).uleb(1000),
+ &Operation::WasmGlobal { index: 1000 },
+ encoding,
+ );
+ check_op_parse(
+ |s| s.D8(constants::DW_OP_WASM_location.0).D8(2).uleb(1000),
+ &Operation::WasmStack { index: 1000 },
+ encoding,
+ );
+ check_op_parse(
+ |s| s.D8(constants::DW_OP_WASM_location.0).D8(3).D32(1000),
+ &Operation::WasmGlobal { index: 1000 },
+ encoding,
+ );
+ }
+
+ enum AssemblerEntry {
+ Op(constants::DwOp),
+ Mark(u8),
+ Branch(u8),
+ U8(u8),
+ U16(u16),
+ U32(u32),
+ U64(u64),
+ Uleb(u64),
+ Sleb(u64),
+ }
+
+ fn assemble(entries: &[AssemblerEntry]) -> Vec<u8> {
+ let mut result = Vec::new();
+
+ struct Marker(Option<usize>, Vec<usize>);
+
+ let mut markers = Vec::new();
+ for _ in 0..256 {
+ markers.push(Marker(None, Vec::new()));
+ }
+
+ fn write(stack: &mut Vec<u8>, index: usize, mut num: u64, nbytes: u8) {
+ for i in 0..nbytes as usize {
+ stack[index + i] = (num & 0xff) as u8;
+ num >>= 8;
+ }
+ }
+
+ fn push(stack: &mut Vec<u8>, num: u64, nbytes: u8) {
+ let index = stack.len();
+ for _ in 0..nbytes {
+ stack.push(0);
+ }
+ write(stack, index, num, nbytes);
+ }
+
+ for item in entries {
+ match *item {
+ AssemblerEntry::Op(op) => result.push(op.0),
+ AssemblerEntry::Mark(num) => {
+ assert!(markers[num as usize].0.is_none());
+ markers[num as usize].0 = Some(result.len());
+ }
+ AssemblerEntry::Branch(num) => {
+ markers[num as usize].1.push(result.len());
+ push(&mut result, 0, 2);
+ }
+ AssemblerEntry::U8(num) => result.push(num),
+ AssemblerEntry::U16(num) => push(&mut result, u64::from(num), 2),
+ AssemblerEntry::U32(num) => push(&mut result, u64::from(num), 4),
+ AssemblerEntry::U64(num) => push(&mut result, num, 8),
+ AssemblerEntry::Uleb(num) => {
+ leb128::write::unsigned(&mut result, num).unwrap();
+ }
+ AssemblerEntry::Sleb(num) => {
+ leb128::write::signed(&mut result, num as i64).unwrap();
+ }
+ }
+ }
+
+ // Update all the branches.
+ for marker in markers {
+ if let Some(offset) = marker.0 {
+ for branch_offset in marker.1 {
+ let delta = offset.wrapping_sub(branch_offset + 2) as u64;
+ write(&mut result, branch_offset, delta, 2);
+ }
+ }
+ }
+
+ result
+ }
+
+ #[allow(clippy::too_many_arguments)]
+ fn check_eval_with_args<F>(
+ program: &[AssemblerEntry],
+ expect: Result<&[Piece<EndianSlice<LittleEndian>>]>,
+ encoding: Encoding,
+ object_address: Option<u64>,
+ initial_value: Option<u64>,
+ max_iterations: Option<u32>,
+ f: F,
+ ) where
+ for<'a> F: Fn(
+ &mut Evaluation<EndianSlice<'a, LittleEndian>>,
+ EvaluationResult<EndianSlice<'a, LittleEndian>>,
+ ) -> Result<EvaluationResult<EndianSlice<'a, LittleEndian>>>,
+ {
+ let bytes = assemble(program);
+ let bytes = EndianSlice::new(&bytes, LittleEndian);
+
+ let mut eval = Evaluation::new(bytes, encoding);
+
+ if let Some(val) = object_address {
+ eval.set_object_address(val);
+ }
+ if let Some(val) = initial_value {
+ eval.set_initial_value(val);
+ }
+ if let Some(val) = max_iterations {
+ eval.set_max_iterations(val);
+ }
+
+ let result = match eval.evaluate() {
+ Err(e) => Err(e),
+ Ok(r) => f(&mut eval, r),
+ };
+
+ match (result, expect) {
+ (Ok(EvaluationResult::Complete), Ok(pieces)) => {
+ let vec = eval.result();
+ assert_eq!(vec.len(), pieces.len());
+ for i in 0..pieces.len() {
+ assert_eq!(vec[i], pieces[i]);
+ }
+ }
+ (Err(f1), Err(f2)) => {
+ assert_eq!(f1, f2);
+ }
+ otherwise => panic!("Unexpected result: {:?}", otherwise),
+ }
+ }
+
+ fn check_eval(
+ program: &[AssemblerEntry],
+ expect: Result<&[Piece<EndianSlice<LittleEndian>>]>,
+ encoding: Encoding,
+ ) {
+ check_eval_with_args(program, expect, encoding, None, None, None, |_, result| {
+ Ok(result)
+ });
+ }
+
+ #[test]
+ fn test_eval_arith() {
+ // It's nice if an operation and its arguments can fit on a single
+ // line in the test program.
+ use self::AssemblerEntry::*;
+ use crate::constants::*;
+
+ // Indices of marks in the assembly.
+ let done = 0;
+ let fail = 1;
+
+ #[rustfmt::skip]
+ let program = [
+ Op(DW_OP_const1u), U8(23),
+ Op(DW_OP_const1s), U8((-23i8) as u8),
+ Op(DW_OP_plus),
+ Op(DW_OP_bra), Branch(fail),
+
+ Op(DW_OP_const2u), U16(23),
+ Op(DW_OP_const2s), U16((-23i16) as u16),
+ Op(DW_OP_plus),
+ Op(DW_OP_bra), Branch(fail),
+
+ Op(DW_OP_const4u), U32(0x1111_2222),
+ Op(DW_OP_const4s), U32((-0x1111_2222i32) as u32),
+ Op(DW_OP_plus),
+ Op(DW_OP_bra), Branch(fail),
+
+ // Plus should overflow.
+ Op(DW_OP_const1s), U8(0xff),
+ Op(DW_OP_const1u), U8(1),
+ Op(DW_OP_plus),
+ Op(DW_OP_bra), Branch(fail),
+
+ Op(DW_OP_const1s), U8(0xff),
+ Op(DW_OP_plus_uconst), Uleb(1),
+ Op(DW_OP_bra), Branch(fail),
+
+ // Minus should underflow.
+ Op(DW_OP_const1s), U8(0),
+ Op(DW_OP_const1u), U8(1),
+ Op(DW_OP_minus),
+ Op(DW_OP_const1s), U8(0xff),
+ Op(DW_OP_ne),
+ Op(DW_OP_bra), Branch(fail),
+
+ Op(DW_OP_const1s), U8(0xff),
+ Op(DW_OP_abs),
+ Op(DW_OP_const1u), U8(1),
+ Op(DW_OP_minus),
+ Op(DW_OP_bra), Branch(fail),
+
+ Op(DW_OP_const4u), U32(0xf078_fffe),
+ Op(DW_OP_const4u), U32(0x0f87_0001),
+ Op(DW_OP_and),
+ Op(DW_OP_bra), Branch(fail),
+
+ Op(DW_OP_const4u), U32(0xf078_fffe),
+ Op(DW_OP_const4u), U32(0xf000_00fe),
+ Op(DW_OP_and),
+ Op(DW_OP_const4u), U32(0xf000_00fe),
+ Op(DW_OP_ne),
+ Op(DW_OP_bra), Branch(fail),
+
+ // Division is signed.
+ Op(DW_OP_const1s), U8(0xfe),
+ Op(DW_OP_const1s), U8(2),
+ Op(DW_OP_div),
+ Op(DW_OP_plus_uconst), Uleb(1),
+ Op(DW_OP_bra), Branch(fail),
+
+ // Mod is unsigned.
+ Op(DW_OP_const1s), U8(0xfd),
+ Op(DW_OP_const1s), U8(2),
+ Op(DW_OP_mod),
+ Op(DW_OP_neg),
+ Op(DW_OP_plus_uconst), Uleb(1),
+ Op(DW_OP_bra), Branch(fail),
+
+ // Overflow is defined for multiplication.
+ Op(DW_OP_const4u), U32(0x8000_0001),
+ Op(DW_OP_lit2),
+ Op(DW_OP_mul),
+ Op(DW_OP_lit2),
+ Op(DW_OP_ne),
+ Op(DW_OP_bra), Branch(fail),
+
+ Op(DW_OP_const4u), U32(0xf0f0_f0f0),
+ Op(DW_OP_const4u), U32(0xf0f0_f0f0),
+ Op(DW_OP_xor),
+ Op(DW_OP_bra), Branch(fail),
+
+ Op(DW_OP_const4u), U32(0xf0f0_f0f0),
+ Op(DW_OP_const4u), U32(0x0f0f_0f0f),
+ Op(DW_OP_or),
+ Op(DW_OP_not),
+ Op(DW_OP_bra), Branch(fail),
+
+ // In 32 bit mode, values are truncated.
+ Op(DW_OP_const8u), U64(0xffff_ffff_0000_0000),
+ Op(DW_OP_lit2),
+ Op(DW_OP_div),
+ Op(DW_OP_bra), Branch(fail),
+
+ Op(DW_OP_const1u), U8(0xff),
+ Op(DW_OP_lit1),
+ Op(DW_OP_shl),
+ Op(DW_OP_const2u), U16(0x1fe),
+ Op(DW_OP_ne),
+ Op(DW_OP_bra), Branch(fail),
+
+ Op(DW_OP_const1u), U8(0xff),
+ Op(DW_OP_const1u), U8(50),
+ Op(DW_OP_shl),
+ Op(DW_OP_bra), Branch(fail),
+
+ // Absurd shift.
+ Op(DW_OP_const1u), U8(0xff),
+ Op(DW_OP_const1s), U8(0xff),
+ Op(DW_OP_shl),
+ Op(DW_OP_bra), Branch(fail),
+
+ Op(DW_OP_const1s), U8(0xff),
+ Op(DW_OP_lit1),
+ Op(DW_OP_shr),
+ Op(DW_OP_const4u), U32(0x7fff_ffff),
+ Op(DW_OP_ne),
+ Op(DW_OP_bra), Branch(fail),
+
+ Op(DW_OP_const1s), U8(0xff),
+ Op(DW_OP_const1u), U8(0xff),
+ Op(DW_OP_shr),
+ Op(DW_OP_bra), Branch(fail),
+
+ Op(DW_OP_const1s), U8(0xff),
+ Op(DW_OP_lit1),
+ Op(DW_OP_shra),
+ Op(DW_OP_const1s), U8(0xff),
+ Op(DW_OP_ne),
+ Op(DW_OP_bra), Branch(fail),
+
+ Op(DW_OP_const1s), U8(0xff),
+ Op(DW_OP_const1u), U8(0xff),
+ Op(DW_OP_shra),
+ Op(DW_OP_const1s), U8(0xff),
+ Op(DW_OP_ne),
+ Op(DW_OP_bra), Branch(fail),
+
+ // Success.
+ Op(DW_OP_lit0),
+ Op(DW_OP_nop),
+ Op(DW_OP_skip), Branch(done),
+
+ Mark(fail),
+ Op(DW_OP_lit1),
+
+ Mark(done),
+ Op(DW_OP_stack_value),
+ ];
+
+ let result = [Piece {
+ size_in_bits: None,
+ bit_offset: None,
+ location: Location::Value {
+ value: Value::Generic(0),
+ },
+ }];
+
+ check_eval(&program, Ok(&result), encoding4());
+ }
+
+ #[test]
+ fn test_eval_arith64() {
+ // It's nice if an operation and its arguments can fit on a single
+ // line in the test program.
+ use self::AssemblerEntry::*;
+ use crate::constants::*;
+
+ // Indices of marks in the assembly.
+ let done = 0;
+ let fail = 1;
+
+ #[rustfmt::skip]
+ let program = [
+ Op(DW_OP_const8u), U64(0x1111_2222_3333_4444),
+ Op(DW_OP_const8s), U64((-0x1111_2222_3333_4444i64) as u64),
+ Op(DW_OP_plus),
+ Op(DW_OP_bra), Branch(fail),
+
+ Op(DW_OP_constu), Uleb(0x1111_2222_3333_4444),
+ Op(DW_OP_consts), Sleb((-0x1111_2222_3333_4444i64) as u64),
+ Op(DW_OP_plus),
+ Op(DW_OP_bra), Branch(fail),
+
+ Op(DW_OP_lit1),
+ Op(DW_OP_plus_uconst), Uleb(!0u64),
+ Op(DW_OP_bra), Branch(fail),
+
+ Op(DW_OP_lit1),
+ Op(DW_OP_neg),
+ Op(DW_OP_not),
+ Op(DW_OP_bra), Branch(fail),
+
+ Op(DW_OP_const8u), U64(0x8000_0000_0000_0000),
+ Op(DW_OP_const1u), U8(63),
+ Op(DW_OP_shr),
+ Op(DW_OP_lit1),
+ Op(DW_OP_ne),
+ Op(DW_OP_bra), Branch(fail),
+
+ Op(DW_OP_const8u), U64(0x8000_0000_0000_0000),
+ Op(DW_OP_const1u), U8(62),
+ Op(DW_OP_shra),
+ Op(DW_OP_plus_uconst), Uleb(2),
+ Op(DW_OP_bra), Branch(fail),
+
+ Op(DW_OP_lit1),
+ Op(DW_OP_const1u), U8(63),
+ Op(DW_OP_shl),
+ Op(DW_OP_const8u), U64(0x8000_0000_0000_0000),
+ Op(DW_OP_ne),
+ Op(DW_OP_bra), Branch(fail),
+
+ // Success.
+ Op(DW_OP_lit0),
+ Op(DW_OP_nop),
+ Op(DW_OP_skip), Branch(done),
+
+ Mark(fail),
+ Op(DW_OP_lit1),
+
+ Mark(done),
+ Op(DW_OP_stack_value),
+ ];
+
+ let result = [Piece {
+ size_in_bits: None,
+ bit_offset: None,
+ location: Location::Value {
+ value: Value::Generic(0),
+ },
+ }];
+
+ check_eval(&program, Ok(&result), encoding8());
+ }
+
+ #[test]
+ fn test_eval_compare() {
+ // It's nice if an operation and its arguments can fit on a single
+ // line in the test program.
+ use self::AssemblerEntry::*;
+ use crate::constants::*;
+
+ // Indices of marks in the assembly.
+ let done = 0;
+ let fail = 1;
+
+ #[rustfmt::skip]
+ let program = [
+ // Comparisons are signed.
+ Op(DW_OP_const1s), U8(1),
+ Op(DW_OP_const1s), U8(0xff),
+ Op(DW_OP_lt),
+ Op(DW_OP_bra), Branch(fail),
+
+ Op(DW_OP_const1s), U8(0xff),
+ Op(DW_OP_const1s), U8(1),
+ Op(DW_OP_gt),
+ Op(DW_OP_bra), Branch(fail),
+
+ Op(DW_OP_const1s), U8(1),
+ Op(DW_OP_const1s), U8(0xff),
+ Op(DW_OP_le),
+ Op(DW_OP_bra), Branch(fail),
+
+ Op(DW_OP_const1s), U8(0xff),
+ Op(DW_OP_const1s), U8(1),
+ Op(DW_OP_ge),
+ Op(DW_OP_bra), Branch(fail),
+
+ Op(DW_OP_const1s), U8(0xff),
+ Op(DW_OP_const1s), U8(1),
+ Op(DW_OP_eq),
+ Op(DW_OP_bra), Branch(fail),
+
+ Op(DW_OP_const4s), U32(1),
+ Op(DW_OP_const1s), U8(1),
+ Op(DW_OP_ne),
+ Op(DW_OP_bra), Branch(fail),
+
+ // Success.
+ Op(DW_OP_lit0),
+ Op(DW_OP_nop),
+ Op(DW_OP_skip), Branch(done),
+
+ Mark(fail),
+ Op(DW_OP_lit1),
+
+ Mark(done),
+ Op(DW_OP_stack_value),
+ ];
+
+ let result = [Piece {
+ size_in_bits: None,
+ bit_offset: None,
+ location: Location::Value {
+ value: Value::Generic(0),
+ },
+ }];
+
+ check_eval(&program, Ok(&result), encoding4());
+ }
+
+ #[test]
+ fn test_eval_stack() {
+ // It's nice if an operation and its arguments can fit on a single
+ // line in the test program.
+ use self::AssemblerEntry::*;
+ use crate::constants::*;
+
+ #[rustfmt::skip]
+ let program = [
+ Op(DW_OP_lit17), // -- 17
+ Op(DW_OP_dup), // -- 17 17
+ Op(DW_OP_over), // -- 17 17 17
+ Op(DW_OP_minus), // -- 17 0
+ Op(DW_OP_swap), // -- 0 17
+ Op(DW_OP_dup), // -- 0 17 17
+ Op(DW_OP_plus_uconst), Uleb(1), // -- 0 17 18
+ Op(DW_OP_rot), // -- 18 0 17
+ Op(DW_OP_pick), U8(2), // -- 18 0 17 18
+ Op(DW_OP_pick), U8(3), // -- 18 0 17 18 18
+ Op(DW_OP_minus), // -- 18 0 17 0
+ Op(DW_OP_drop), // -- 18 0 17
+ Op(DW_OP_swap), // -- 18 17 0
+ Op(DW_OP_drop), // -- 18 17
+ Op(DW_OP_minus), // -- 1
+ Op(DW_OP_stack_value),
+ ];
+
+ let result = [Piece {
+ size_in_bits: None,
+ bit_offset: None,
+ location: Location::Value {
+ value: Value::Generic(1),
+ },
+ }];
+
+ check_eval(&program, Ok(&result), encoding4());
+ }
+
+ #[test]
+ fn test_eval_lit_and_reg() {
+ // It's nice if an operation and its arguments can fit on a single
+ // line in the test program.
+ use self::AssemblerEntry::*;
+ use crate::constants::*;
+
+ let mut program = Vec::new();
+ program.push(Op(DW_OP_lit0));
+ for i in 0..32 {
+ program.push(Op(DwOp(DW_OP_lit0.0 + i)));
+ program.push(Op(DwOp(DW_OP_breg0.0 + i)));
+ program.push(Sleb(u64::from(i)));
+ program.push(Op(DW_OP_plus));
+ program.push(Op(DW_OP_plus));
+ }
+
+ program.push(Op(DW_OP_bregx));
+ program.push(Uleb(0x1234));
+ program.push(Sleb(0x1234));
+ program.push(Op(DW_OP_plus));
+
+ program.push(Op(DW_OP_stack_value));
+
+ let result = [Piece {
+ size_in_bits: None,
+ bit_offset: None,
+ location: Location::Value {
+ value: Value::Generic(496),
+ },
+ }];
+
+ check_eval_with_args(
+ &program,
+ Ok(&result),
+ encoding4(),
+ None,
+ None,
+ None,
+ |eval, mut result| {
+ while result != EvaluationResult::Complete {
+ result = eval.resume_with_register(match result {
+ EvaluationResult::RequiresRegister {
+ register,
+ base_type,
+ } => {
+ assert_eq!(base_type, UnitOffset(0));
+ Value::Generic(u64::from(register.0).wrapping_neg())
+ }
+ _ => panic!(),
+ })?;
+ }
+ Ok(result)
+ },
+ );
+ }
+
+ #[test]
+ fn test_eval_memory() {
+ // It's nice if an operation and its arguments can fit on a single
+ // line in the test program.
+ use self::AssemblerEntry::*;
+ use crate::constants::*;
+
+ // Indices of marks in the assembly.
+ let done = 0;
+ let fail = 1;
+
+ #[rustfmt::skip]
+ let program = [
+ Op(DW_OP_addr), U32(0x7fff_ffff),
+ Op(DW_OP_deref),
+ Op(DW_OP_const4u), U32(0xffff_fffc),
+ Op(DW_OP_ne),
+ Op(DW_OP_bra), Branch(fail),
+
+ Op(DW_OP_addr), U32(0x7fff_ffff),
+ Op(DW_OP_deref_size), U8(2),
+ Op(DW_OP_const4u), U32(0xfffc),
+ Op(DW_OP_ne),
+ Op(DW_OP_bra), Branch(fail),
+
+ Op(DW_OP_lit1),
+ Op(DW_OP_addr), U32(0x7fff_ffff),
+ Op(DW_OP_xderef),
+ Op(DW_OP_const4u), U32(0xffff_fffd),
+ Op(DW_OP_ne),
+ Op(DW_OP_bra), Branch(fail),
+
+ Op(DW_OP_lit1),
+ Op(DW_OP_addr), U32(0x7fff_ffff),
+ Op(DW_OP_xderef_size), U8(2),
+ Op(DW_OP_const4u), U32(0xfffd),
+ Op(DW_OP_ne),
+ Op(DW_OP_bra), Branch(fail),
+
+ Op(DW_OP_lit17),
+ Op(DW_OP_form_tls_address),
+ Op(DW_OP_constu), Uleb(!17),
+ Op(DW_OP_ne),
+ Op(DW_OP_bra), Branch(fail),
+
+ Op(DW_OP_lit17),
+ Op(DW_OP_GNU_push_tls_address),
+ Op(DW_OP_constu), Uleb(!17),
+ Op(DW_OP_ne),
+ Op(DW_OP_bra), Branch(fail),
+
+ Op(DW_OP_addrx), Uleb(0x10),
+ Op(DW_OP_deref),
+ Op(DW_OP_const4u), U32(0x4040),
+ Op(DW_OP_ne),
+ Op(DW_OP_bra), Branch(fail),
+
+ Op(DW_OP_constx), Uleb(17),
+ Op(DW_OP_form_tls_address),
+ Op(DW_OP_constu), Uleb(!27),
+ Op(DW_OP_ne),
+ Op(DW_OP_bra), Branch(fail),
+
+ // Success.
+ Op(DW_OP_lit0),
+ Op(DW_OP_nop),
+ Op(DW_OP_skip), Branch(done),
+
+ Mark(fail),
+ Op(DW_OP_lit1),
+
+ Mark(done),
+ Op(DW_OP_stack_value),
+ ];
+
+ let result = [Piece {
+ size_in_bits: None,
+ bit_offset: None,
+ location: Location::Value {
+ value: Value::Generic(0),
+ },
+ }];
+
+ check_eval_with_args(
+ &program,
+ Ok(&result),
+ encoding4(),
+ None,
+ None,
+ None,
+ |eval, mut result| {
+ while result != EvaluationResult::Complete {
+ result = match result {
+ EvaluationResult::RequiresMemory {
+ address,
+ size,
+ space,
+ base_type,
+ } => {
+ assert_eq!(base_type, UnitOffset(0));
+ let mut v = address << 2;
+ if let Some(value) = space {
+ v += value;
+ }
+ v &= (1u64 << (8 * size)) - 1;
+ eval.resume_with_memory(Value::Generic(v))?
+ }
+ EvaluationResult::RequiresTls(slot) => eval.resume_with_tls(!slot)?,
+ EvaluationResult::RequiresRelocatedAddress(address) => {
+ eval.resume_with_relocated_address(address)?
+ }
+ EvaluationResult::RequiresIndexedAddress { index, relocate } => {
+ if relocate {
+ eval.resume_with_indexed_address(0x1000 + index.0 as u64)?
+ } else {
+ eval.resume_with_indexed_address(10 + index.0 as u64)?
+ }
+ }
+ _ => panic!(),
+ };
+ }
+
+ Ok(result)
+ },
+ );
+ }
+
+ #[test]
+ fn test_eval_register() {
+ // It's nice if an operation and its arguments can fit on a single
+ // line in the test program.
+ use self::AssemblerEntry::*;
+ use crate::constants::*;
+
+ for i in 0..32 {
+ #[rustfmt::skip]
+ let program = [
+ Op(DwOp(DW_OP_reg0.0 + i)),
+ // Included only in the "bad" run.
+ Op(DW_OP_lit23),
+ ];
+ let ok_result = [Piece {
+ size_in_bits: None,
+ bit_offset: None,
+ location: Location::Register {
+ register: Register(i.into()),
+ },
+ }];
+
+ check_eval(&program[..1], Ok(&ok_result), encoding4());
+
+ check_eval(
+ &program,
+ Err(Error::InvalidExpressionTerminator(1)),
+ encoding4(),
+ );
+ }
+
+ #[rustfmt::skip]
+ let program = [
+ Op(DW_OP_regx), Uleb(0x1234)
+ ];
+
+ let result = [Piece {
+ size_in_bits: None,
+ bit_offset: None,
+ location: Location::Register {
+ register: Register(0x1234),
+ },
+ }];
+
+ check_eval(&program, Ok(&result), encoding4());
+ }
+
+ #[test]
+ fn test_eval_context() {
+ // It's nice if an operation and its arguments can fit on a single
+ // line in the test program.
+ use self::AssemblerEntry::*;
+ use crate::constants::*;
+
+ // Test `frame_base` and `call_frame_cfa` callbacks.
+ #[rustfmt::skip]
+ let program = [
+ Op(DW_OP_fbreg), Sleb((-8i8) as u64),
+ Op(DW_OP_call_frame_cfa),
+ Op(DW_OP_plus),
+ Op(DW_OP_neg),
+ Op(DW_OP_stack_value)
+ ];
+
+ let result = [Piece {
+ size_in_bits: None,
+ bit_offset: None,
+ location: Location::Value {
+ value: Value::Generic(9),
+ },
+ }];
+
+ check_eval_with_args(
+ &program,
+ Ok(&result),
+ encoding8(),
+ None,
+ None,
+ None,
+ |eval, result| {
+ match result {
+ EvaluationResult::RequiresFrameBase => {}
+ _ => panic!(),
+ };
+ match eval.resume_with_frame_base(0x0123_4567_89ab_cdef)? {
+ EvaluationResult::RequiresCallFrameCfa => {}
+ _ => panic!(),
+ };
+ eval.resume_with_call_frame_cfa(0xfedc_ba98_7654_3210)
+ },
+ );
+
+ // Test `evaluate_entry_value` callback.
+ #[rustfmt::skip]
+ let program = [
+ Op(DW_OP_entry_value), Uleb(8), U64(0x1234_5678),
+ Op(DW_OP_stack_value)
+ ];
+
+ let result = [Piece {
+ size_in_bits: None,
+ bit_offset: None,
+ location: Location::Value {
+ value: Value::Generic(0x1234_5678),
+ },
+ }];
+
+ check_eval_with_args(
+ &program,
+ Ok(&result),
+ encoding8(),
+ None,
+ None,
+ None,
+ |eval, result| {
+ let entry_value = match result {
+ EvaluationResult::RequiresEntryValue(mut expression) => {
+ expression.0.read_u64()?
+ }
+ _ => panic!(),
+ };
+ eval.resume_with_entry_value(Value::Generic(entry_value))
+ },
+ );
+
+ // Test missing `object_address` field.
+ #[rustfmt::skip]
+ let program = [
+ Op(DW_OP_push_object_address),
+ ];
+
+ check_eval_with_args(
+ &program,
+ Err(Error::InvalidPushObjectAddress),
+ encoding4(),
+ None,
+ None,
+ None,
+ |_, _| panic!(),
+ );
+
+ // Test `object_address` field.
+ #[rustfmt::skip]
+ let program = [
+ Op(DW_OP_push_object_address),
+ Op(DW_OP_stack_value),
+ ];
+
+ let result = [Piece {
+ size_in_bits: None,
+ bit_offset: None,
+ location: Location::Value {
+ value: Value::Generic(0xff),
+ },
+ }];
+
+ check_eval_with_args(
+ &program,
+ Ok(&result),
+ encoding8(),
+ Some(0xff),
+ None,
+ None,
+ |_, result| Ok(result),
+ );
+
+ // Test `initial_value` field.
+ #[rustfmt::skip]
+ let program = [
+ ];
+
+ let result = [Piece {
+ size_in_bits: None,
+ bit_offset: None,
+ location: Location::Address {
+ address: 0x1234_5678,
+ },
+ }];
+
+ check_eval_with_args(
+ &program,
+ Ok(&result),
+ encoding8(),
+ None,
+ Some(0x1234_5678),
+ None,
+ |_, result| Ok(result),
+ );
+ }
+
+ #[test]
+ fn test_eval_empty_stack() {
+ // It's nice if an operation and its arguments can fit on a single
+ // line in the test program.
+ use self::AssemblerEntry::*;
+ use crate::constants::*;
+
+ #[rustfmt::skip]
+ let program = [
+ Op(DW_OP_stack_value)
+ ];
+
+ check_eval(&program, Err(Error::NotEnoughStackItems), encoding4());
+ }
+
+ #[test]
+ fn test_eval_call() {
+ // It's nice if an operation and its arguments can fit on a single
+ // line in the test program.
+ use self::AssemblerEntry::*;
+ use crate::constants::*;
+
+ #[rustfmt::skip]
+ let program = [
+ Op(DW_OP_lit23),
+ Op(DW_OP_call2), U16(0x7755),
+ Op(DW_OP_call4), U32(0x7755_aaee),
+ Op(DW_OP_call_ref), U32(0x7755_aaee),
+ Op(DW_OP_stack_value)
+ ];
+
+ let result = [Piece {
+ size_in_bits: None,
+ bit_offset: None,
+ location: Location::Value {
+ value: Value::Generic(23),
+ },
+ }];
+
+ check_eval_with_args(
+ &program,
+ Ok(&result),
+ encoding4(),
+ None,
+ None,
+ None,
+ |eval, result| {
+ let buf = EndianSlice::new(&[], LittleEndian);
+ match result {
+ EvaluationResult::RequiresAtLocation(_) => {}
+ _ => panic!(),
+ };
+
+ eval.resume_with_at_location(buf)?;
+
+ match result {
+ EvaluationResult::RequiresAtLocation(_) => {}
+ _ => panic!(),
+ };
+
+ eval.resume_with_at_location(buf)?;
+
+ match result {
+ EvaluationResult::RequiresAtLocation(_) => {}
+ _ => panic!(),
+ };
+
+ eval.resume_with_at_location(buf)
+ },
+ );
+
+ // DW_OP_lit2 DW_OP_mul
+ const SUBR: &[u8] = &[0x32, 0x1e];
+
+ let result = [Piece {
+ size_in_bits: None,
+ bit_offset: None,
+ location: Location::Value {
+ value: Value::Generic(184),
+ },
+ }];
+
+ check_eval_with_args(
+ &program,
+ Ok(&result),
+ encoding4(),
+ None,
+ None,
+ None,
+ |eval, result| {
+ let buf = EndianSlice::new(SUBR, LittleEndian);
+ match result {
+ EvaluationResult::RequiresAtLocation(_) => {}
+ _ => panic!(),
+ };
+
+ eval.resume_with_at_location(buf)?;
+
+ match result {
+ EvaluationResult::RequiresAtLocation(_) => {}
+ _ => panic!(),
+ };
+
+ eval.resume_with_at_location(buf)?;
+
+ match result {
+ EvaluationResult::RequiresAtLocation(_) => {}
+ _ => panic!(),
+ };
+
+ eval.resume_with_at_location(buf)
+ },
+ );
+ }
+
+ #[test]
+ fn test_eval_pieces() {
+ // It's nice if an operation and its arguments can fit on a single
+ // line in the test program.
+ use self::AssemblerEntry::*;
+ use crate::constants::*;
+
+ // Example from DWARF 2.6.1.3.
+ #[rustfmt::skip]
+ let program = [
+ Op(DW_OP_reg3),
+ Op(DW_OP_piece), Uleb(4),
+ Op(DW_OP_reg4),
+ Op(DW_OP_piece), Uleb(2),
+ ];
+
+ let result = [
+ Piece {
+ size_in_bits: Some(32),
+ bit_offset: None,
+ location: Location::Register {
+ register: Register(3),
+ },
+ },
+ Piece {
+ size_in_bits: Some(16),
+ bit_offset: None,
+ location: Location::Register {
+ register: Register(4),
+ },
+ },
+ ];
+
+ check_eval(&program, Ok(&result), encoding4());
+
+ // Example from DWARF 2.6.1.3 (but hacked since dealing with fbreg
+ // in the tests is a pain).
+ #[rustfmt::skip]
+ let program = [
+ Op(DW_OP_reg0),
+ Op(DW_OP_piece), Uleb(4),
+ Op(DW_OP_piece), Uleb(4),
+ Op(DW_OP_addr), U32(0x7fff_ffff),
+ Op(DW_OP_piece), Uleb(4),
+ ];
+
+ let result = [
+ Piece {
+ size_in_bits: Some(32),
+ bit_offset: None,
+ location: Location::Register {
+ register: Register(0),
+ },
+ },
+ Piece {
+ size_in_bits: Some(32),
+ bit_offset: None,
+ location: Location::Empty,
+ },
+ Piece {
+ size_in_bits: Some(32),
+ bit_offset: None,
+ location: Location::Address {
+ address: 0x7fff_ffff,
+ },
+ },
+ ];
+
+ check_eval_with_args(
+ &program,
+ Ok(&result),
+ encoding4(),
+ None,
+ None,
+ None,
+ |eval, mut result| {
+ while result != EvaluationResult::Complete {
+ result = match result {
+ EvaluationResult::RequiresRelocatedAddress(address) => {
+ eval.resume_with_relocated_address(address)?
+ }
+ _ => panic!(),
+ };
+ }
+
+ Ok(result)
+ },
+ );
+
+ #[rustfmt::skip]
+ let program = [
+ Op(DW_OP_implicit_value), Uleb(5),
+ U8(23), U8(24), U8(25), U8(26), U8(0),
+ ];
+
+ const BYTES: &[u8] = &[23, 24, 25, 26, 0];
+
+ let result = [Piece {
+ size_in_bits: None,
+ bit_offset: None,
+ location: Location::Bytes {
+ value: EndianSlice::new(BYTES, LittleEndian),
+ },
+ }];
+
+ check_eval(&program, Ok(&result), encoding4());
+
+ #[rustfmt::skip]
+ let program = [
+ Op(DW_OP_lit7),
+ Op(DW_OP_stack_value),
+ Op(DW_OP_bit_piece), Uleb(5), Uleb(0),
+ Op(DW_OP_bit_piece), Uleb(3), Uleb(0),
+ ];
+
+ let result = [
+ Piece {
+ size_in_bits: Some(5),
+ bit_offset: Some(0),
+ location: Location::Value {
+ value: Value::Generic(7),
+ },
+ },
+ Piece {
+ size_in_bits: Some(3),
+ bit_offset: Some(0),
+ location: Location::Empty,
+ },
+ ];
+
+ check_eval(&program, Ok(&result), encoding4());
+
+ #[rustfmt::skip]
+ let program = [
+ Op(DW_OP_lit7),
+ ];
+
+ let result = [Piece {
+ size_in_bits: None,
+ bit_offset: None,
+ location: Location::Address { address: 7 },
+ }];
+
+ check_eval(&program, Ok(&result), encoding4());
+
+ #[rustfmt::skip]
+ let program = [
+ Op(DW_OP_implicit_pointer), U32(0x1234_5678), Sleb(0x123),
+ ];
+
+ let result = [Piece {
+ size_in_bits: None,
+ bit_offset: None,
+ location: Location::ImplicitPointer {
+ value: DebugInfoOffset(0x1234_5678),
+ byte_offset: 0x123,
+ },
+ }];
+
+ check_eval(&program, Ok(&result), encoding4());
+
+ #[rustfmt::skip]
+ let program = [
+ Op(DW_OP_reg3),
+ Op(DW_OP_piece), Uleb(4),
+ Op(DW_OP_reg4),
+ ];
+
+ check_eval(&program, Err(Error::InvalidPiece), encoding4());
+
+ #[rustfmt::skip]
+ let program = [
+ Op(DW_OP_reg3),
+ Op(DW_OP_piece), Uleb(4),
+ Op(DW_OP_lit0),
+ ];
+
+ check_eval(&program, Err(Error::InvalidPiece), encoding4());
+ }
+
+ #[test]
+ fn test_eval_max_iterations() {
+ // It's nice if an operation and its arguments can fit on a single
+ // line in the test program.
+ use self::AssemblerEntry::*;
+ use crate::constants::*;
+
+ #[rustfmt::skip]
+ let program = [
+ Mark(1),
+ Op(DW_OP_skip), Branch(1),
+ ];
+
+ check_eval_with_args(
+ &program,
+ Err(Error::TooManyIterations),
+ encoding4(),
+ None,
+ None,
+ Some(150),
+ |_, _| panic!(),
+ );
+ }
+
+ #[test]
+ fn test_eval_typed_stack() {
+ use self::AssemblerEntry::*;
+ use crate::constants::*;
+
+ let base_types = [
+ ValueType::Generic,
+ ValueType::U16,
+ ValueType::U32,
+ ValueType::F32,
+ ];
+
+ // TODO: convert, reinterpret
+ #[rustfmt::skip]
+ let tests = [
+ (
+ &[
+ Op(DW_OP_const_type), Uleb(1), U8(2), U16(0x1234),
+ Op(DW_OP_stack_value),
+ ][..],
+ Value::U16(0x1234),
+ ),
+ (
+ &[
+ Op(DW_OP_regval_type), Uleb(0x1234), Uleb(1),
+ Op(DW_OP_stack_value),
+ ][..],
+ Value::U16(0x2340),
+ ),
+ (
+ &[
+ Op(DW_OP_addr), U32(0x7fff_ffff),
+ Op(DW_OP_deref_type), U8(2), Uleb(1),
+ Op(DW_OP_stack_value),
+ ][..],
+ Value::U16(0xfff0),
+ ),
+ (
+ &[
+ Op(DW_OP_lit1),
+ Op(DW_OP_addr), U32(0x7fff_ffff),
+ Op(DW_OP_xderef_type), U8(2), Uleb(1),
+ Op(DW_OP_stack_value),
+ ][..],
+ Value::U16(0xfff1),
+ ),
+ (
+ &[
+ Op(DW_OP_const_type), Uleb(1), U8(2), U16(0x1234),
+ Op(DW_OP_convert), Uleb(2),
+ Op(DW_OP_stack_value),
+ ][..],
+ Value::U32(0x1234),
+ ),
+ (
+ &[
+ Op(DW_OP_const_type), Uleb(2), U8(4), U32(0x3f80_0000),
+ Op(DW_OP_reinterpret), Uleb(3),
+ Op(DW_OP_stack_value),
+ ][..],
+ Value::F32(1.0),
+ ),
+ ];
+ for &(program, value) in &tests {
+ let result = [Piece {
+ size_in_bits: None,
+ bit_offset: None,
+ location: Location::Value { value },
+ }];
+
+ check_eval_with_args(
+ program,
+ Ok(&result),
+ encoding4(),
+ None,
+ None,
+ None,
+ |eval, mut result| {
+ while result != EvaluationResult::Complete {
+ result = match result {
+ EvaluationResult::RequiresMemory {
+ address,
+ size,
+ space,
+ base_type,
+ } => {
+ let mut v = address << 4;
+ if let Some(value) = space {
+ v += value;
+ }
+ v &= (1u64 << (8 * size)) - 1;
+ let v = Value::from_u64(base_types[base_type.0], v)?;
+ eval.resume_with_memory(v)?
+ }
+ EvaluationResult::RequiresRegister {
+ register,
+ base_type,
+ } => {
+ let v = Value::from_u64(
+ base_types[base_type.0],
+ u64::from(register.0) << 4,
+ )?;
+ eval.resume_with_register(v)?
+ }
+ EvaluationResult::RequiresBaseType(offset) => {
+ eval.resume_with_base_type(base_types[offset.0])?
+ }
+ EvaluationResult::RequiresRelocatedAddress(address) => {
+ eval.resume_with_relocated_address(address)?
+ }
+ _ => panic!("Unexpected result {:?}", result),
+ }
+ }
+ Ok(result)
+ },
+ );
+ }
+ }
+}
diff --git a/vendor/gimli-0.26.2/src/read/pubnames.rs b/vendor/gimli-0.26.2/src/read/pubnames.rs
new file mode 100644
index 000000000..e8b7e5528
--- /dev/null
+++ b/vendor/gimli-0.26.2/src/read/pubnames.rs
@@ -0,0 +1,141 @@
+use crate::common::{DebugInfoOffset, SectionId};
+use crate::endianity::Endianity;
+use crate::read::lookup::{DebugLookup, LookupEntryIter, PubStuffEntry, PubStuffParser};
+use crate::read::{EndianSlice, Reader, Result, Section, UnitOffset};
+
+/// A single parsed pubname.
+#[derive(Debug, Clone)]
+pub struct PubNamesEntry<R: Reader> {
+ unit_header_offset: DebugInfoOffset<R::Offset>,
+ die_offset: UnitOffset<R::Offset>,
+ name: R,
+}
+
+impl<R: Reader> PubNamesEntry<R> {
+ /// Returns the name this entry refers to.
+ pub fn name(&self) -> &R {
+ &self.name
+ }
+
+ /// Returns the offset into the .debug_info section for the header of the compilation unit
+ /// which contains this name.
+ pub fn unit_header_offset(&self) -> DebugInfoOffset<R::Offset> {
+ self.unit_header_offset
+ }
+
+ /// Returns the offset into the compilation unit for the debugging information entry which
+ /// has this name.
+ pub fn die_offset(&self) -> UnitOffset<R::Offset> {
+ self.die_offset
+ }
+}
+
+impl<R: Reader> PubStuffEntry<R> for PubNamesEntry<R> {
+ fn new(
+ die_offset: UnitOffset<R::Offset>,
+ name: R,
+ unit_header_offset: DebugInfoOffset<R::Offset>,
+ ) -> Self {
+ PubNamesEntry {
+ unit_header_offset,
+ die_offset,
+ name,
+ }
+ }
+}
+
+/// The `DebugPubNames` struct represents the DWARF public names information
+/// found in the `.debug_pubnames` section.
+#[derive(Debug, Clone)]
+pub struct DebugPubNames<R: Reader>(DebugLookup<R, PubStuffParser<R, PubNamesEntry<R>>>);
+
+impl<'input, Endian> DebugPubNames<EndianSlice<'input, Endian>>
+where
+ Endian: Endianity,
+{
+ /// Construct a new `DebugPubNames` instance from the data in the `.debug_pubnames`
+ /// section.
+ ///
+ /// It is the caller's responsibility to read the `.debug_pubnames` section and
+ /// present it as a `&[u8]` slice. That means using some ELF loader on
+ /// Linux, a Mach-O loader on macOS, etc.
+ ///
+ /// ```
+ /// use gimli::{DebugPubNames, LittleEndian};
+ ///
+ /// # let buf = [];
+ /// # let read_debug_pubnames_section_somehow = || &buf;
+ /// let debug_pubnames =
+ /// DebugPubNames::new(read_debug_pubnames_section_somehow(), LittleEndian);
+ /// ```
+ pub fn new(debug_pubnames_section: &'input [u8], endian: Endian) -> Self {
+ Self::from(EndianSlice::new(debug_pubnames_section, endian))
+ }
+}
+
+impl<R: Reader> DebugPubNames<R> {
+ /// Iterate the pubnames in the `.debug_pubnames` section.
+ ///
+ /// ```
+ /// use gimli::{DebugPubNames, EndianSlice, LittleEndian};
+ ///
+ /// # let buf = [];
+ /// # let read_debug_pubnames_section_somehow = || &buf;
+ /// let debug_pubnames =
+ /// DebugPubNames::new(read_debug_pubnames_section_somehow(), LittleEndian);
+ ///
+ /// let mut iter = debug_pubnames.items();
+ /// while let Some(pubname) = iter.next().unwrap() {
+ /// println!("pubname {} found!", pubname.name().to_string_lossy());
+ /// }
+ /// ```
+ pub fn items(&self) -> PubNamesEntryIter<R> {
+ PubNamesEntryIter(self.0.items())
+ }
+}
+
+impl<R: Reader> Section<R> for DebugPubNames<R> {
+ fn id() -> SectionId {
+ SectionId::DebugPubNames
+ }
+
+ fn reader(&self) -> &R {
+ self.0.reader()
+ }
+}
+
+impl<R: Reader> From<R> for DebugPubNames<R> {
+ fn from(debug_pubnames_section: R) -> Self {
+ DebugPubNames(DebugLookup::from(debug_pubnames_section))
+ }
+}
+
+/// An iterator over the pubnames from a `.debug_pubnames` section.
+///
+/// Can be [used with
+/// `FallibleIterator`](./index.html#using-with-fallibleiterator).
+#[derive(Debug, Clone)]
+pub struct PubNamesEntryIter<R: Reader>(LookupEntryIter<R, PubStuffParser<R, PubNamesEntry<R>>>);
+
+impl<R: Reader> PubNamesEntryIter<R> {
+ /// Advance the iterator and return the next pubname.
+ ///
+ /// Returns the newly parsed pubname as `Ok(Some(pubname))`. Returns
+ /// `Ok(None)` when iteration is complete and all pubnames have already been
+ /// parsed and yielded. If an error occurs while parsing the next pubname,
+ /// then this error is returned as `Err(e)`, and all subsequent calls return
+ /// `Ok(None)`.
+ pub fn next(&mut self) -> Result<Option<PubNamesEntry<R>>> {
+ self.0.next()
+ }
+}
+
+#[cfg(feature = "fallible-iterator")]
+impl<R: Reader> fallible_iterator::FallibleIterator for PubNamesEntryIter<R> {
+ type Item = PubNamesEntry<R>;
+ type Error = crate::read::Error;
+
+ fn next(&mut self) -> ::core::result::Result<Option<Self::Item>, Self::Error> {
+ self.0.next()
+ }
+}
diff --git a/vendor/gimli-0.26.2/src/read/pubtypes.rs b/vendor/gimli-0.26.2/src/read/pubtypes.rs
new file mode 100644
index 000000000..6723b4222
--- /dev/null
+++ b/vendor/gimli-0.26.2/src/read/pubtypes.rs
@@ -0,0 +1,141 @@
+use crate::common::{DebugInfoOffset, SectionId};
+use crate::endianity::Endianity;
+use crate::read::lookup::{DebugLookup, LookupEntryIter, PubStuffEntry, PubStuffParser};
+use crate::read::{EndianSlice, Reader, Result, Section, UnitOffset};
+
+/// A single parsed pubtype.
+#[derive(Debug, Clone)]
+pub struct PubTypesEntry<R: Reader> {
+ unit_header_offset: DebugInfoOffset<R::Offset>,
+ die_offset: UnitOffset<R::Offset>,
+ name: R,
+}
+
+impl<R: Reader> PubTypesEntry<R> {
+ /// Returns the name of the type this entry refers to.
+ pub fn name(&self) -> &R {
+ &self.name
+ }
+
+ /// Returns the offset into the .debug_info section for the header of the compilation unit
+ /// which contains the type with this name.
+ pub fn unit_header_offset(&self) -> DebugInfoOffset<R::Offset> {
+ self.unit_header_offset
+ }
+
+ /// Returns the offset into the compilation unit for the debugging information entry which
+ /// the type with this name.
+ pub fn die_offset(&self) -> UnitOffset<R::Offset> {
+ self.die_offset
+ }
+}
+
+impl<R: Reader> PubStuffEntry<R> for PubTypesEntry<R> {
+ fn new(
+ die_offset: UnitOffset<R::Offset>,
+ name: R,
+ unit_header_offset: DebugInfoOffset<R::Offset>,
+ ) -> Self {
+ PubTypesEntry {
+ unit_header_offset,
+ die_offset,
+ name,
+ }
+ }
+}
+
+/// The `DebugPubTypes` struct represents the DWARF public types information
+/// found in the `.debug_info` section.
+#[derive(Debug, Clone)]
+pub struct DebugPubTypes<R: Reader>(DebugLookup<R, PubStuffParser<R, PubTypesEntry<R>>>);
+
+impl<'input, Endian> DebugPubTypes<EndianSlice<'input, Endian>>
+where
+ Endian: Endianity,
+{
+ /// Construct a new `DebugPubTypes` instance from the data in the `.debug_pubtypes`
+ /// section.
+ ///
+ /// It is the caller's responsibility to read the `.debug_pubtypes` section and
+ /// present it as a `&[u8]` slice. That means using some ELF loader on
+ /// Linux, a Mach-O loader on macOS, etc.
+ ///
+ /// ```
+ /// use gimli::{DebugPubTypes, LittleEndian};
+ ///
+ /// # let buf = [];
+ /// # let read_debug_pubtypes_somehow = || &buf;
+ /// let debug_pubtypes =
+ /// DebugPubTypes::new(read_debug_pubtypes_somehow(), LittleEndian);
+ /// ```
+ pub fn new(debug_pubtypes_section: &'input [u8], endian: Endian) -> Self {
+ Self::from(EndianSlice::new(debug_pubtypes_section, endian))
+ }
+}
+
+impl<R: Reader> DebugPubTypes<R> {
+ /// Iterate the pubtypes in the `.debug_pubtypes` section.
+ ///
+ /// ```
+ /// use gimli::{DebugPubTypes, EndianSlice, LittleEndian};
+ ///
+ /// # let buf = [];
+ /// # let read_debug_pubtypes_section_somehow = || &buf;
+ /// let debug_pubtypes =
+ /// DebugPubTypes::new(read_debug_pubtypes_section_somehow(), LittleEndian);
+ ///
+ /// let mut iter = debug_pubtypes.items();
+ /// while let Some(pubtype) = iter.next().unwrap() {
+ /// println!("pubtype {} found!", pubtype.name().to_string_lossy());
+ /// }
+ /// ```
+ pub fn items(&self) -> PubTypesEntryIter<R> {
+ PubTypesEntryIter(self.0.items())
+ }
+}
+
+impl<R: Reader> Section<R> for DebugPubTypes<R> {
+ fn id() -> SectionId {
+ SectionId::DebugPubTypes
+ }
+
+ fn reader(&self) -> &R {
+ self.0.reader()
+ }
+}
+
+impl<R: Reader> From<R> for DebugPubTypes<R> {
+ fn from(debug_pubtypes_section: R) -> Self {
+ DebugPubTypes(DebugLookup::from(debug_pubtypes_section))
+ }
+}
+
+/// An iterator over the pubtypes from a `.debug_pubtypes` section.
+///
+/// Can be [used with
+/// `FallibleIterator`](./index.html#using-with-fallibleiterator).
+#[derive(Debug, Clone)]
+pub struct PubTypesEntryIter<R: Reader>(LookupEntryIter<R, PubStuffParser<R, PubTypesEntry<R>>>);
+
+impl<R: Reader> PubTypesEntryIter<R> {
+ /// Advance the iterator and return the next pubtype.
+ ///
+ /// Returns the newly parsed pubtype as `Ok(Some(pubtype))`. Returns
+ /// `Ok(None)` when iteration is complete and all pubtypes have already been
+ /// parsed and yielded. If an error occurs while parsing the next pubtype,
+ /// then this error is returned as `Err(e)`, and all subsequent calls return
+ /// `Ok(None)`.
+ pub fn next(&mut self) -> Result<Option<PubTypesEntry<R>>> {
+ self.0.next()
+ }
+}
+
+#[cfg(feature = "fallible-iterator")]
+impl<R: Reader> fallible_iterator::FallibleIterator for PubTypesEntryIter<R> {
+ type Item = PubTypesEntry<R>;
+ type Error = crate::read::Error;
+
+ fn next(&mut self) -> ::core::result::Result<Option<Self::Item>, Self::Error> {
+ self.0.next()
+ }
+}
diff --git a/vendor/gimli-0.26.2/src/read/reader.rs b/vendor/gimli-0.26.2/src/read/reader.rs
new file mode 100644
index 000000000..1bb748bb8
--- /dev/null
+++ b/vendor/gimli-0.26.2/src/read/reader.rs
@@ -0,0 +1,502 @@
+#[cfg(feature = "read")]
+use alloc::borrow::Cow;
+use core::convert::TryInto;
+use core::fmt::Debug;
+use core::hash::Hash;
+use core::ops::{Add, AddAssign, Sub};
+
+use crate::common::Format;
+use crate::endianity::Endianity;
+use crate::leb128;
+use crate::read::{Error, Result};
+
+/// An identifier for an offset within a section reader.
+///
+/// This is used for error reporting. The meaning of this value is specific to
+/// each reader implementation. The values should be chosen to be unique amongst
+/// all readers. If values are not unique then errors may point to the wrong reader.
+#[derive(Debug, Clone, Copy, PartialEq, Eq)]
+pub struct ReaderOffsetId(pub u64);
+
+/// A trait for offsets with a DWARF section.
+///
+/// This allows consumers to choose a size that is appropriate for their address space.
+pub trait ReaderOffset:
+ Debug + Copy + Eq + Ord + Hash + Add<Output = Self> + AddAssign + Sub<Output = Self>
+{
+ /// Convert a u8 to an offset.
+ fn from_u8(offset: u8) -> Self;
+
+ /// Convert a u16 to an offset.
+ fn from_u16(offset: u16) -> Self;
+
+ /// Convert an i16 to an offset.
+ fn from_i16(offset: i16) -> Self;
+
+ /// Convert a u32 to an offset.
+ fn from_u32(offset: u32) -> Self;
+
+ /// Convert a u64 to an offset.
+ ///
+ /// Returns `Error::UnsupportedOffset` if the value is too large.
+ fn from_u64(offset: u64) -> Result<Self>;
+
+ /// Convert an offset to a u64.
+ fn into_u64(self) -> u64;
+
+ /// Wrapping (modular) addition. Computes `self + other`.
+ fn wrapping_add(self, other: Self) -> Self;
+
+ /// Checked subtraction. Computes `self - other`.
+ fn checked_sub(self, other: Self) -> Option<Self>;
+}
+
+impl ReaderOffset for u64 {
+ #[inline]
+ fn from_u8(offset: u8) -> Self {
+ u64::from(offset)
+ }
+
+ #[inline]
+ fn from_u16(offset: u16) -> Self {
+ u64::from(offset)
+ }
+
+ #[inline]
+ fn from_i16(offset: i16) -> Self {
+ offset as u64
+ }
+
+ #[inline]
+ fn from_u32(offset: u32) -> Self {
+ u64::from(offset)
+ }
+
+ #[inline]
+ fn from_u64(offset: u64) -> Result<Self> {
+ Ok(offset)
+ }
+
+ #[inline]
+ fn into_u64(self) -> u64 {
+ self
+ }
+
+ #[inline]
+ fn wrapping_add(self, other: Self) -> Self {
+ self.wrapping_add(other)
+ }
+
+ #[inline]
+ fn checked_sub(self, other: Self) -> Option<Self> {
+ self.checked_sub(other)
+ }
+}
+
+impl ReaderOffset for u32 {
+ #[inline]
+ fn from_u8(offset: u8) -> Self {
+ u32::from(offset)
+ }
+
+ #[inline]
+ fn from_u16(offset: u16) -> Self {
+ u32::from(offset)
+ }
+
+ #[inline]
+ fn from_i16(offset: i16) -> Self {
+ offset as u32
+ }
+
+ #[inline]
+ fn from_u32(offset: u32) -> Self {
+ offset
+ }
+
+ #[inline]
+ fn from_u64(offset64: u64) -> Result<Self> {
+ let offset = offset64 as u32;
+ if u64::from(offset) == offset64 {
+ Ok(offset)
+ } else {
+ Err(Error::UnsupportedOffset)
+ }
+ }
+
+ #[inline]
+ fn into_u64(self) -> u64 {
+ u64::from(self)
+ }
+
+ #[inline]
+ fn wrapping_add(self, other: Self) -> Self {
+ self.wrapping_add(other)
+ }
+
+ #[inline]
+ fn checked_sub(self, other: Self) -> Option<Self> {
+ self.checked_sub(other)
+ }
+}
+
+impl ReaderOffset for usize {
+ #[inline]
+ fn from_u8(offset: u8) -> Self {
+ offset as usize
+ }
+
+ #[inline]
+ fn from_u16(offset: u16) -> Self {
+ offset as usize
+ }
+
+ #[inline]
+ fn from_i16(offset: i16) -> Self {
+ offset as usize
+ }
+
+ #[inline]
+ fn from_u32(offset: u32) -> Self {
+ offset as usize
+ }
+
+ #[inline]
+ fn from_u64(offset64: u64) -> Result<Self> {
+ let offset = offset64 as usize;
+ if offset as u64 == offset64 {
+ Ok(offset)
+ } else {
+ Err(Error::UnsupportedOffset)
+ }
+ }
+
+ #[inline]
+ fn into_u64(self) -> u64 {
+ self as u64
+ }
+
+ #[inline]
+ fn wrapping_add(self, other: Self) -> Self {
+ self.wrapping_add(other)
+ }
+
+ #[inline]
+ fn checked_sub(self, other: Self) -> Option<Self> {
+ self.checked_sub(other)
+ }
+}
+
+#[cfg(not(feature = "read"))]
+pub(crate) mod seal_if_no_alloc {
+ #[derive(Debug)]
+ pub struct Sealed;
+}
+
+/// A trait for reading the data from a DWARF section.
+///
+/// All read operations advance the section offset of the reader
+/// unless specified otherwise.
+///
+/// ## Choosing a `Reader` Implementation
+///
+/// `gimli` comes with a few different `Reader` implementations and lets you
+/// choose the one that is right for your use case. A `Reader` is essentially a
+/// view into the raw bytes that make up some DWARF, but this view might borrow
+/// the underlying data or use reference counting ownership, and it might be
+/// thread safe or not.
+///
+/// | Implementation | Ownership | Thread Safe | Notes |
+/// |:------------------|:------------------|:------------|:------|
+/// | [`EndianSlice`](./struct.EndianSlice.html) | Borrowed | Yes | Fastest, but requires that all of your code work with borrows. |
+/// | [`EndianRcSlice`](./struct.EndianRcSlice.html) | Reference counted | No | Shared ownership via reference counting, which alleviates the borrow restrictions of `EndianSlice` but imposes reference counting increments and decrements. Cannot be sent across threads, because the reference count is not atomic. |
+/// | [`EndianArcSlice`](./struct.EndianArcSlice.html) | Reference counted | Yes | The same as `EndianRcSlice`, but uses atomic reference counting, and therefore reference counting operations are slower but `EndianArcSlice`s may be sent across threads. |
+/// | [`EndianReader<T>`](./struct.EndianReader.html) | Same as `T` | Same as `T` | Escape hatch for easily defining your own type of `Reader`. |
+pub trait Reader: Debug + Clone {
+ /// The endianity of bytes that are read.
+ type Endian: Endianity;
+
+ /// The type used for offsets and lengths.
+ type Offset: ReaderOffset;
+
+ /// Return the endianity of bytes that are read.
+ fn endian(&self) -> Self::Endian;
+
+ /// Return the number of bytes remaining.
+ fn len(&self) -> Self::Offset;
+
+ /// Set the number of bytes remaining to zero.
+ fn empty(&mut self);
+
+ /// Set the number of bytes remaining to the specified length.
+ fn truncate(&mut self, len: Self::Offset) -> Result<()>;
+
+ /// Return the offset of this reader's data relative to the start of
+ /// the given base reader's data.
+ ///
+ /// May panic if this reader's data is not contained within the given
+ /// base reader's data.
+ fn offset_from(&self, base: &Self) -> Self::Offset;
+
+ /// Return an identifier for the current reader offset.
+ fn offset_id(&self) -> ReaderOffsetId;
+
+ /// Return the offset corresponding to the given `id` if
+ /// it is associated with this reader.
+ fn lookup_offset_id(&self, id: ReaderOffsetId) -> Option<Self::Offset>;
+
+ /// Find the index of the first occurence of the given byte.
+ /// The offset of the reader is not changed.
+ fn find(&self, byte: u8) -> Result<Self::Offset>;
+
+ /// Discard the specified number of bytes.
+ fn skip(&mut self, len: Self::Offset) -> Result<()>;
+
+ /// Split a reader in two.
+ ///
+ /// A new reader is returned that can be used to read the next
+ /// `len` bytes, and `self` is advanced so that it reads the remainder.
+ fn split(&mut self, len: Self::Offset) -> Result<Self>;
+
+ /// This trait cannot be implemented if "read" feature is not enabled.
+ ///
+ /// `Reader` trait has a few methods that depend on `alloc` crate.
+ /// Disallowing `Reader` trait implementation prevents a crate that only depends on
+ /// "read-core" from being broken if another crate depending on `gimli` enables
+ /// "read" feature.
+ #[cfg(not(feature = "read"))]
+ fn cannot_implement() -> seal_if_no_alloc::Sealed;
+
+ /// Return all remaining data as a clone-on-write slice.
+ ///
+ /// The slice will be borrowed where possible, but some readers may
+ /// always return an owned vector.
+ ///
+ /// Does not advance the reader.
+ #[cfg(feature = "read")]
+ fn to_slice(&self) -> Result<Cow<[u8]>>;
+
+ /// Convert all remaining data to a clone-on-write string.
+ ///
+ /// The string will be borrowed where possible, but some readers may
+ /// always return an owned string.
+ ///
+ /// Does not advance the reader.
+ ///
+ /// Returns an error if the data contains invalid characters.
+ #[cfg(feature = "read")]
+ fn to_string(&self) -> Result<Cow<str>>;
+
+ /// Convert all remaining data to a clone-on-write string, including invalid characters.
+ ///
+ /// The string will be borrowed where possible, but some readers may
+ /// always return an owned string.
+ ///
+ /// Does not advance the reader.
+ #[cfg(feature = "read")]
+ fn to_string_lossy(&self) -> Result<Cow<str>>;
+
+ /// Read exactly `buf.len()` bytes into `buf`.
+ fn read_slice(&mut self, buf: &mut [u8]) -> Result<()>;
+
+ /// Read a u8 array.
+ #[inline]
+ fn read_u8_array<A>(&mut self) -> Result<A>
+ where
+ A: Sized + Default + AsMut<[u8]>,
+ {
+ let mut val = Default::default();
+ self.read_slice(<A as AsMut<[u8]>>::as_mut(&mut val))?;
+ Ok(val)
+ }
+
+ /// Return true if the number of bytes remaining is zero.
+ #[inline]
+ fn is_empty(&self) -> bool {
+ self.len() == Self::Offset::from_u8(0)
+ }
+
+ /// Read a u8.
+ #[inline]
+ fn read_u8(&mut self) -> Result<u8> {
+ let a: [u8; 1] = self.read_u8_array()?;
+ Ok(a[0])
+ }
+
+ /// Read an i8.
+ #[inline]
+ fn read_i8(&mut self) -> Result<i8> {
+ let a: [u8; 1] = self.read_u8_array()?;
+ Ok(a[0] as i8)
+ }
+
+ /// Read a u16.
+ #[inline]
+ fn read_u16(&mut self) -> Result<u16> {
+ let a: [u8; 2] = self.read_u8_array()?;
+ Ok(self.endian().read_u16(&a))
+ }
+
+ /// Read an i16.
+ #[inline]
+ fn read_i16(&mut self) -> Result<i16> {
+ let a: [u8; 2] = self.read_u8_array()?;
+ Ok(self.endian().read_i16(&a))
+ }
+
+ /// Read a u32.
+ #[inline]
+ fn read_u32(&mut self) -> Result<u32> {
+ let a: [u8; 4] = self.read_u8_array()?;
+ Ok(self.endian().read_u32(&a))
+ }
+
+ /// Read an i32.
+ #[inline]
+ fn read_i32(&mut self) -> Result<i32> {
+ let a: [u8; 4] = self.read_u8_array()?;
+ Ok(self.endian().read_i32(&a))
+ }
+
+ /// Read a u64.
+ #[inline]
+ fn read_u64(&mut self) -> Result<u64> {
+ let a: [u8; 8] = self.read_u8_array()?;
+ Ok(self.endian().read_u64(&a))
+ }
+
+ /// Read an i64.
+ #[inline]
+ fn read_i64(&mut self) -> Result<i64> {
+ let a: [u8; 8] = self.read_u8_array()?;
+ Ok(self.endian().read_i64(&a))
+ }
+
+ /// Read a f32.
+ #[inline]
+ fn read_f32(&mut self) -> Result<f32> {
+ let a: [u8; 4] = self.read_u8_array()?;
+ Ok(self.endian().read_f32(&a))
+ }
+
+ /// Read a f64.
+ #[inline]
+ fn read_f64(&mut self) -> Result<f64> {
+ let a: [u8; 8] = self.read_u8_array()?;
+ Ok(self.endian().read_f64(&a))
+ }
+
+ /// Read an unsigned n-bytes integer u64.
+ ///
+ /// # Panics
+ ///
+ /// Panics when nbytes < 1 or nbytes > 8
+ #[inline]
+ fn read_uint(&mut self, n: usize) -> Result<u64> {
+ let mut buf = [0; 8];
+ self.read_slice(&mut buf[..n])?;
+ Ok(self.endian().read_uint(&buf[..n]))
+ }
+
+ /// Read a null-terminated slice, and return it (excluding the null).
+ fn read_null_terminated_slice(&mut self) -> Result<Self> {
+ let idx = self.find(0)?;
+ let val = self.split(idx)?;
+ self.skip(Self::Offset::from_u8(1))?;
+ Ok(val)
+ }
+
+ /// Skip a LEB128 encoded integer.
+ fn skip_leb128(&mut self) -> Result<()> {
+ leb128::read::skip(self)
+ }
+
+ /// Read an unsigned LEB128 encoded integer.
+ fn read_uleb128(&mut self) -> Result<u64> {
+ leb128::read::unsigned(self)
+ }
+
+ /// Read an unsigned LEB128 encoded u32.
+ fn read_uleb128_u32(&mut self) -> Result<u32> {
+ leb128::read::unsigned(self)?
+ .try_into()
+ .map_err(|_| Error::BadUnsignedLeb128)
+ }
+
+ /// Read an unsigned LEB128 encoded u16.
+ fn read_uleb128_u16(&mut self) -> Result<u16> {
+ leb128::read::u16(self)
+ }
+
+ /// Read a signed LEB128 encoded integer.
+ fn read_sleb128(&mut self) -> Result<i64> {
+ leb128::read::signed(self)
+ }
+
+ /// Read an initial length field.
+ ///
+ /// This field is encoded as either a 32-bit length or
+ /// a 64-bit length, and the returned `Format` indicates which.
+ fn read_initial_length(&mut self) -> Result<(Self::Offset, Format)> {
+ const MAX_DWARF_32_UNIT_LENGTH: u32 = 0xffff_fff0;
+ const DWARF_64_INITIAL_UNIT_LENGTH: u32 = 0xffff_ffff;
+
+ let val = self.read_u32()?;
+ if val < MAX_DWARF_32_UNIT_LENGTH {
+ Ok((Self::Offset::from_u32(val), Format::Dwarf32))
+ } else if val == DWARF_64_INITIAL_UNIT_LENGTH {
+ let val = self.read_u64().and_then(Self::Offset::from_u64)?;
+ Ok((val, Format::Dwarf64))
+ } else {
+ Err(Error::UnknownReservedLength)
+ }
+ }
+
+ /// Read an address-sized integer, and return it as a `u64`.
+ fn read_address(&mut self, address_size: u8) -> Result<u64> {
+ match address_size {
+ 1 => self.read_u8().map(u64::from),
+ 2 => self.read_u16().map(u64::from),
+ 4 => self.read_u32().map(u64::from),
+ 8 => self.read_u64(),
+ otherwise => Err(Error::UnsupportedAddressSize(otherwise)),
+ }
+ }
+
+ /// Parse a word-sized integer according to the DWARF format.
+ ///
+ /// These are always used to encode section offsets or lengths,
+ /// and so have a type of `Self::Offset`.
+ fn read_word(&mut self, format: Format) -> Result<Self::Offset> {
+ match format {
+ Format::Dwarf32 => self.read_u32().map(Self::Offset::from_u32),
+ Format::Dwarf64 => self.read_u64().and_then(Self::Offset::from_u64),
+ }
+ }
+
+ /// Parse a word-sized section length according to the DWARF format.
+ #[inline]
+ fn read_length(&mut self, format: Format) -> Result<Self::Offset> {
+ self.read_word(format)
+ }
+
+ /// Parse a word-sized section offset according to the DWARF format.
+ #[inline]
+ fn read_offset(&mut self, format: Format) -> Result<Self::Offset> {
+ self.read_word(format)
+ }
+
+ /// Parse a section offset of the given size.
+ ///
+ /// This is used for `DW_FORM_ref_addr` values in DWARF version 2.
+ fn read_sized_offset(&mut self, size: u8) -> Result<Self::Offset> {
+ match size {
+ 1 => self.read_u8().map(u64::from),
+ 2 => self.read_u16().map(u64::from),
+ 4 => self.read_u32().map(u64::from),
+ 8 => self.read_u64(),
+ otherwise => Err(Error::UnsupportedOffsetSize(otherwise)),
+ }
+ .and_then(Self::Offset::from_u64)
+ }
+}
diff --git a/vendor/gimli-0.26.2/src/read/rnglists.rs b/vendor/gimli-0.26.2/src/read/rnglists.rs
new file mode 100644
index 000000000..d8d49042f
--- /dev/null
+++ b/vendor/gimli-0.26.2/src/read/rnglists.rs
@@ -0,0 +1,1354 @@
+use crate::common::{
+ DebugAddrBase, DebugAddrIndex, DebugRngListsBase, DebugRngListsIndex, DwarfFileType, Encoding,
+ RangeListsOffset, SectionId,
+};
+use crate::constants;
+use crate::endianity::Endianity;
+use crate::read::{
+ lists::ListsHeader, DebugAddr, EndianSlice, Error, Reader, ReaderOffset, ReaderOffsetId,
+ Result, Section,
+};
+
+/// The raw contents of the `.debug_ranges` section.
+#[derive(Debug, Default, Clone, Copy)]
+pub struct DebugRanges<R> {
+ pub(crate) section: R,
+}
+
+impl<'input, Endian> DebugRanges<EndianSlice<'input, Endian>>
+where
+ Endian: Endianity,
+{
+ /// Construct a new `DebugRanges` instance from the data in the `.debug_ranges`
+ /// section.
+ ///
+ /// It is the caller's responsibility to read the `.debug_ranges` section and
+ /// present it as a `&[u8]` slice. That means using some ELF loader on
+ /// Linux, a Mach-O loader on macOS, etc.
+ ///
+ /// ```
+ /// use gimli::{DebugRanges, LittleEndian};
+ ///
+ /// # let buf = [0x00, 0x01, 0x02, 0x03];
+ /// # let read_debug_ranges_section_somehow = || &buf;
+ /// let debug_ranges = DebugRanges::new(read_debug_ranges_section_somehow(), LittleEndian);
+ /// ```
+ pub fn new(section: &'input [u8], endian: Endian) -> Self {
+ Self::from(EndianSlice::new(section, endian))
+ }
+}
+
+impl<R> Section<R> for DebugRanges<R> {
+ fn id() -> SectionId {
+ SectionId::DebugRanges
+ }
+
+ fn reader(&self) -> &R {
+ &self.section
+ }
+}
+
+impl<R> From<R> for DebugRanges<R> {
+ fn from(section: R) -> Self {
+ DebugRanges { section }
+ }
+}
+
+/// The `DebugRngLists` struct represents the contents of the
+/// `.debug_rnglists` section.
+#[derive(Debug, Default, Clone, Copy)]
+pub struct DebugRngLists<R> {
+ section: R,
+}
+
+impl<'input, Endian> DebugRngLists<EndianSlice<'input, Endian>>
+where
+ Endian: Endianity,
+{
+ /// Construct a new `DebugRngLists` instance from the data in the
+ /// `.debug_rnglists` section.
+ ///
+ /// It is the caller's responsibility to read the `.debug_rnglists`
+ /// section and present it as a `&[u8]` slice. That means using some ELF
+ /// loader on Linux, a Mach-O loader on macOS, etc.
+ ///
+ /// ```
+ /// use gimli::{DebugRngLists, LittleEndian};
+ ///
+ /// # let buf = [0x00, 0x01, 0x02, 0x03];
+ /// # let read_debug_rnglists_section_somehow = || &buf;
+ /// let debug_rnglists =
+ /// DebugRngLists::new(read_debug_rnglists_section_somehow(), LittleEndian);
+ /// ```
+ pub fn new(section: &'input [u8], endian: Endian) -> Self {
+ Self::from(EndianSlice::new(section, endian))
+ }
+}
+
+impl<R> Section<R> for DebugRngLists<R> {
+ fn id() -> SectionId {
+ SectionId::DebugRngLists
+ }
+
+ fn reader(&self) -> &R {
+ &self.section
+ }
+}
+
+impl<R> From<R> for DebugRngLists<R> {
+ fn from(section: R) -> Self {
+ DebugRngLists { section }
+ }
+}
+
+#[allow(unused)]
+pub(crate) type RngListsHeader = ListsHeader;
+
+impl<Offset> DebugRngListsBase<Offset>
+where
+ Offset: ReaderOffset,
+{
+ /// Returns a `DebugRngListsBase` with the default value of DW_AT_rnglists_base
+ /// for the given `Encoding` and `DwarfFileType`.
+ pub fn default_for_encoding_and_file(
+ encoding: Encoding,
+ file_type: DwarfFileType,
+ ) -> DebugRngListsBase<Offset> {
+ if encoding.version >= 5 && file_type == DwarfFileType::Dwo {
+ // In .dwo files, the compiler omits the DW_AT_rnglists_base attribute (because there is
+ // only a single unit in the file) but we must skip past the header, which the attribute
+ // would normally do for us.
+ DebugRngListsBase(Offset::from_u8(RngListsHeader::size_for_encoding(encoding)))
+ } else {
+ DebugRngListsBase(Offset::from_u8(0))
+ }
+ }
+}
+
+/// The DWARF data found in `.debug_ranges` and `.debug_rnglists` sections.
+#[derive(Debug, Default, Clone, Copy)]
+pub struct RangeLists<R> {
+ debug_ranges: DebugRanges<R>,
+ debug_rnglists: DebugRngLists<R>,
+}
+
+impl<R> RangeLists<R> {
+ /// Construct a new `RangeLists` instance from the data in the `.debug_ranges` and
+ /// `.debug_rnglists` sections.
+ pub fn new(debug_ranges: DebugRanges<R>, debug_rnglists: DebugRngLists<R>) -> RangeLists<R> {
+ RangeLists {
+ debug_ranges,
+ debug_rnglists,
+ }
+ }
+
+ /// Return the `.debug_ranges` section.
+ pub fn debug_ranges(&self) -> &DebugRanges<R> {
+ &self.debug_ranges
+ }
+
+ /// Replace the `.debug_ranges` section.
+ ///
+ /// This is useful for `.dwo` files when using the GNU split-dwarf extension to DWARF 4.
+ pub fn set_debug_ranges(&mut self, debug_ranges: DebugRanges<R>) {
+ self.debug_ranges = debug_ranges;
+ }
+
+ /// Return the `.debug_rnglists` section.
+ pub fn debug_rnglists(&self) -> &DebugRngLists<R> {
+ &self.debug_rnglists
+ }
+}
+
+impl<T> RangeLists<T> {
+ /// Create a `RangeLists` that references the data in `self`.
+ ///
+ /// This is useful when `R` implements `Reader` but `T` does not.
+ ///
+ /// ## Example Usage
+ ///
+ /// ```rust,no_run
+ /// # let load_section = || unimplemented!();
+ /// // Read the DWARF section into a `Vec` with whatever object loader you're using.
+ /// let owned_section: gimli::RangeLists<Vec<u8>> = load_section();
+ /// // Create a reference to the DWARF section.
+ /// let section = owned_section.borrow(|section| {
+ /// gimli::EndianSlice::new(&section, gimli::LittleEndian)
+ /// });
+ /// ```
+ pub fn borrow<'a, F, R>(&'a self, mut borrow: F) -> RangeLists<R>
+ where
+ F: FnMut(&'a T) -> R,
+ {
+ RangeLists {
+ debug_ranges: borrow(&self.debug_ranges.section).into(),
+ debug_rnglists: borrow(&self.debug_rnglists.section).into(),
+ }
+ }
+}
+
+impl<R: Reader> RangeLists<R> {
+ /// Iterate over the `Range` list entries starting at the given offset.
+ ///
+ /// The `unit_version` and `address_size` must match the compilation unit that the
+ /// offset was contained in.
+ ///
+ /// The `base_address` should be obtained from the `DW_AT_low_pc` attribute in the
+ /// `DW_TAG_compile_unit` entry for the compilation unit that contains this range list.
+ ///
+ /// Can be [used with
+ /// `FallibleIterator`](./index.html#using-with-fallibleiterator).
+ pub fn ranges(
+ &self,
+ offset: RangeListsOffset<R::Offset>,
+ unit_encoding: Encoding,
+ base_address: u64,
+ debug_addr: &DebugAddr<R>,
+ debug_addr_base: DebugAddrBase<R::Offset>,
+ ) -> Result<RngListIter<R>> {
+ Ok(RngListIter::new(
+ self.raw_ranges(offset, unit_encoding)?,
+ base_address,
+ debug_addr.clone(),
+ debug_addr_base,
+ ))
+ }
+
+ /// Iterate over the `RawRngListEntry`ies starting at the given offset.
+ ///
+ /// The `unit_encoding` must match the compilation unit that the
+ /// offset was contained in.
+ ///
+ /// This iterator does not perform any processing of the range entries,
+ /// such as handling base addresses.
+ ///
+ /// Can be [used with
+ /// `FallibleIterator`](./index.html#using-with-fallibleiterator).
+ pub fn raw_ranges(
+ &self,
+ offset: RangeListsOffset<R::Offset>,
+ unit_encoding: Encoding,
+ ) -> Result<RawRngListIter<R>> {
+ let (mut input, format) = if unit_encoding.version <= 4 {
+ (self.debug_ranges.section.clone(), RangeListsFormat::Bare)
+ } else {
+ (self.debug_rnglists.section.clone(), RangeListsFormat::RLE)
+ };
+ input.skip(offset.0)?;
+ Ok(RawRngListIter::new(input, unit_encoding, format))
+ }
+
+ /// Returns the `.debug_rnglists` offset at the given `base` and `index`.
+ ///
+ /// The `base` must be the `DW_AT_rnglists_base` value from the compilation unit DIE.
+ /// This is an offset that points to the first entry following the header.
+ ///
+ /// The `index` is the value of a `DW_FORM_rnglistx` attribute.
+ ///
+ /// The `unit_encoding` must match the compilation unit that the
+ /// index was contained in.
+ pub fn get_offset(
+ &self,
+ unit_encoding: Encoding,
+ base: DebugRngListsBase<R::Offset>,
+ index: DebugRngListsIndex<R::Offset>,
+ ) -> Result<RangeListsOffset<R::Offset>> {
+ let format = unit_encoding.format;
+ let input = &mut self.debug_rnglists.section.clone();
+ input.skip(base.0)?;
+ input.skip(R::Offset::from_u64(
+ index.0.into_u64() * u64::from(format.word_size()),
+ )?)?;
+ input
+ .read_offset(format)
+ .map(|x| RangeListsOffset(base.0 + x))
+ }
+
+ /// Call `Reader::lookup_offset_id` for each section, and return the first match.
+ pub fn lookup_offset_id(&self, id: ReaderOffsetId) -> Option<(SectionId, R::Offset)> {
+ self.debug_ranges
+ .lookup_offset_id(id)
+ .or_else(|| self.debug_rnglists.lookup_offset_id(id))
+ }
+}
+
+#[derive(Debug, Clone, Copy, PartialEq, Eq)]
+enum RangeListsFormat {
+ /// The bare range list format used before DWARF 5.
+ Bare,
+ /// The DW_RLE encoded range list format used in DWARF 5.
+ RLE,
+}
+
+/// A raw iterator over an address range list.
+///
+/// This iterator does not perform any processing of the range entries,
+/// such as handling base addresses.
+#[derive(Debug)]
+pub struct RawRngListIter<R: Reader> {
+ input: R,
+ encoding: Encoding,
+ format: RangeListsFormat,
+}
+
+/// A raw entry in .debug_rnglists
+#[derive(Clone, Debug)]
+pub enum RawRngListEntry<T> {
+ /// A range from DWARF version <= 4.
+ AddressOrOffsetPair {
+ /// Start of range. May be an address or an offset.
+ begin: u64,
+ /// End of range. May be an address or an offset.
+ end: u64,
+ },
+ /// DW_RLE_base_address
+ BaseAddress {
+ /// base address
+ addr: u64,
+ },
+ /// DW_RLE_base_addressx
+ BaseAddressx {
+ /// base address
+ addr: DebugAddrIndex<T>,
+ },
+ /// DW_RLE_startx_endx
+ StartxEndx {
+ /// start of range
+ begin: DebugAddrIndex<T>,
+ /// end of range
+ end: DebugAddrIndex<T>,
+ },
+ /// DW_RLE_startx_length
+ StartxLength {
+ /// start of range
+ begin: DebugAddrIndex<T>,
+ /// length of range
+ length: u64,
+ },
+ /// DW_RLE_offset_pair
+ OffsetPair {
+ /// start of range
+ begin: u64,
+ /// end of range
+ end: u64,
+ },
+ /// DW_RLE_start_end
+ StartEnd {
+ /// start of range
+ begin: u64,
+ /// end of range
+ end: u64,
+ },
+ /// DW_RLE_start_length
+ StartLength {
+ /// start of range
+ begin: u64,
+ /// length of range
+ length: u64,
+ },
+}
+
+impl<T: ReaderOffset> RawRngListEntry<T> {
+ /// Parse a range entry from `.debug_rnglists`
+ fn parse<R: Reader<Offset = T>>(
+ input: &mut R,
+ encoding: Encoding,
+ format: RangeListsFormat,
+ ) -> Result<Option<Self>> {
+ match format {
+ RangeListsFormat::Bare => {
+ let range = RawRange::parse(input, encoding.address_size)?;
+ return Ok(if range.is_end() {
+ None
+ } else if range.is_base_address(encoding.address_size) {
+ Some(RawRngListEntry::BaseAddress { addr: range.end })
+ } else {
+ Some(RawRngListEntry::AddressOrOffsetPair {
+ begin: range.begin,
+ end: range.end,
+ })
+ });
+ }
+ RangeListsFormat::RLE => Ok(match constants::DwRle(input.read_u8()?) {
+ constants::DW_RLE_end_of_list => None,
+ constants::DW_RLE_base_addressx => Some(RawRngListEntry::BaseAddressx {
+ addr: DebugAddrIndex(input.read_uleb128().and_then(R::Offset::from_u64)?),
+ }),
+ constants::DW_RLE_startx_endx => Some(RawRngListEntry::StartxEndx {
+ begin: DebugAddrIndex(input.read_uleb128().and_then(R::Offset::from_u64)?),
+ end: DebugAddrIndex(input.read_uleb128().and_then(R::Offset::from_u64)?),
+ }),
+ constants::DW_RLE_startx_length => Some(RawRngListEntry::StartxLength {
+ begin: DebugAddrIndex(input.read_uleb128().and_then(R::Offset::from_u64)?),
+ length: input.read_uleb128()?,
+ }),
+ constants::DW_RLE_offset_pair => Some(RawRngListEntry::OffsetPair {
+ begin: input.read_uleb128()?,
+ end: input.read_uleb128()?,
+ }),
+ constants::DW_RLE_base_address => Some(RawRngListEntry::BaseAddress {
+ addr: input.read_address(encoding.address_size)?,
+ }),
+ constants::DW_RLE_start_end => Some(RawRngListEntry::StartEnd {
+ begin: input.read_address(encoding.address_size)?,
+ end: input.read_address(encoding.address_size)?,
+ }),
+ constants::DW_RLE_start_length => Some(RawRngListEntry::StartLength {
+ begin: input.read_address(encoding.address_size)?,
+ length: input.read_uleb128()?,
+ }),
+ _ => {
+ return Err(Error::InvalidAddressRange);
+ }
+ }),
+ }
+ }
+}
+
+impl<R: Reader> RawRngListIter<R> {
+ /// Construct a `RawRngListIter`.
+ fn new(input: R, encoding: Encoding, format: RangeListsFormat) -> RawRngListIter<R> {
+ RawRngListIter {
+ input,
+ encoding,
+ format,
+ }
+ }
+
+ /// Advance the iterator to the next range.
+ pub fn next(&mut self) -> Result<Option<RawRngListEntry<R::Offset>>> {
+ if self.input.is_empty() {
+ return Ok(None);
+ }
+
+ match RawRngListEntry::parse(&mut self.input, self.encoding, self.format) {
+ Ok(range) => {
+ if range.is_none() {
+ self.input.empty();
+ }
+ Ok(range)
+ }
+ Err(e) => {
+ self.input.empty();
+ Err(e)
+ }
+ }
+ }
+}
+
+#[cfg(feature = "fallible-iterator")]
+impl<R: Reader> fallible_iterator::FallibleIterator for RawRngListIter<R> {
+ type Item = RawRngListEntry<R::Offset>;
+ type Error = Error;
+
+ fn next(&mut self) -> ::core::result::Result<Option<Self::Item>, Self::Error> {
+ RawRngListIter::next(self)
+ }
+}
+
+/// An iterator over an address range list.
+///
+/// This iterator internally handles processing of base addresses and different
+/// entry types. Thus, it only returns range entries that are valid
+/// and already adjusted for the base address.
+#[derive(Debug)]
+pub struct RngListIter<R: Reader> {
+ raw: RawRngListIter<R>,
+ base_address: u64,
+ debug_addr: DebugAddr<R>,
+ debug_addr_base: DebugAddrBase<R::Offset>,
+}
+
+impl<R: Reader> RngListIter<R> {
+ /// Construct a `RngListIter`.
+ fn new(
+ raw: RawRngListIter<R>,
+ base_address: u64,
+ debug_addr: DebugAddr<R>,
+ debug_addr_base: DebugAddrBase<R::Offset>,
+ ) -> RngListIter<R> {
+ RngListIter {
+ raw,
+ base_address,
+ debug_addr,
+ debug_addr_base,
+ }
+ }
+
+ #[inline]
+ fn get_address(&self, index: DebugAddrIndex<R::Offset>) -> Result<u64> {
+ self.debug_addr
+ .get_address(self.raw.encoding.address_size, self.debug_addr_base, index)
+ }
+
+ /// Advance the iterator to the next range.
+ pub fn next(&mut self) -> Result<Option<Range>> {
+ loop {
+ let raw_range = match self.raw.next()? {
+ Some(range) => range,
+ None => return Ok(None),
+ };
+
+ let range = match raw_range {
+ RawRngListEntry::BaseAddress { addr } => {
+ self.base_address = addr;
+ continue;
+ }
+ RawRngListEntry::BaseAddressx { addr } => {
+ self.base_address = self.get_address(addr)?;
+ continue;
+ }
+ RawRngListEntry::StartxEndx { begin, end } => {
+ let begin = self.get_address(begin)?;
+ let end = self.get_address(end)?;
+ Range { begin, end }
+ }
+ RawRngListEntry::StartxLength { begin, length } => {
+ let begin = self.get_address(begin)?;
+ let end = begin + length;
+ Range { begin, end }
+ }
+ RawRngListEntry::AddressOrOffsetPair { begin, end }
+ | RawRngListEntry::OffsetPair { begin, end } => {
+ let mut range = Range { begin, end };
+ range.add_base_address(self.base_address, self.raw.encoding.address_size);
+ range
+ }
+ RawRngListEntry::StartEnd { begin, end } => Range { begin, end },
+ RawRngListEntry::StartLength { begin, length } => Range {
+ begin,
+ end: begin + length,
+ },
+ };
+
+ if range.begin > range.end {
+ self.raw.input.empty();
+ return Err(Error::InvalidAddressRange);
+ }
+
+ return Ok(Some(range));
+ }
+ }
+}
+
+#[cfg(feature = "fallible-iterator")]
+impl<R: Reader> fallible_iterator::FallibleIterator for RngListIter<R> {
+ type Item = Range;
+ type Error = Error;
+
+ fn next(&mut self) -> ::core::result::Result<Option<Self::Item>, Self::Error> {
+ RngListIter::next(self)
+ }
+}
+
+/// A raw address range from the `.debug_ranges` section.
+#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
+pub(crate) struct RawRange {
+ /// The beginning address of the range.
+ pub begin: u64,
+
+ /// The first address past the end of the range.
+ pub end: u64,
+}
+
+impl RawRange {
+ /// Check if this is a range end entry.
+ ///
+ /// This will only occur for raw ranges.
+ #[inline]
+ pub fn is_end(&self) -> bool {
+ self.begin == 0 && self.end == 0
+ }
+
+ /// Check if this is a base address selection entry.
+ ///
+ /// A base address selection entry changes the base address that subsequent
+ /// range entries are relative to. This will only occur for raw ranges.
+ #[inline]
+ pub fn is_base_address(&self, address_size: u8) -> bool {
+ self.begin == !0 >> (64 - address_size * 8)
+ }
+
+ /// Parse an address range entry from `.debug_ranges` or `.debug_loc`.
+ #[doc(hidden)]
+ #[inline]
+ pub fn parse<R: Reader>(input: &mut R, address_size: u8) -> Result<RawRange> {
+ let begin = input.read_address(address_size)?;
+ let end = input.read_address(address_size)?;
+ let range = RawRange { begin, end };
+ Ok(range)
+ }
+}
+
+/// An address range from the `.debug_ranges`, `.debug_rnglists`, or `.debug_aranges` sections.
+#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
+pub struct Range {
+ /// The beginning address of the range.
+ pub begin: u64,
+
+ /// The first address past the end of the range.
+ pub end: u64,
+}
+
+impl Range {
+ /// Add a base address to this range.
+ #[inline]
+ pub(crate) fn add_base_address(&mut self, base_address: u64, address_size: u8) {
+ let mask = !0 >> (64 - address_size * 8);
+ self.begin = base_address.wrapping_add(self.begin) & mask;
+ self.end = base_address.wrapping_add(self.end) & mask;
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+ use crate::common::Format;
+ use crate::endianity::LittleEndian;
+ use crate::test_util::GimliSectionMethods;
+ use test_assembler::{Endian, Label, LabelMaker, Section};
+
+ #[test]
+ fn test_rnglists_32() {
+ let encoding = Encoding {
+ format: Format::Dwarf32,
+ version: 5,
+ address_size: 4,
+ };
+ let section = Section::with_endian(Endian::Little)
+ .L32(0x0300_0000)
+ .L32(0x0301_0300)
+ .L32(0x0301_0400)
+ .L32(0x0301_0500);
+ let buf = section.get_contents().unwrap();
+ let debug_addr = &DebugAddr::from(EndianSlice::new(&buf, LittleEndian));
+ let debug_addr_base = DebugAddrBase(0);
+
+ let start = Label::new();
+ let first = Label::new();
+ let size = Label::new();
+ #[rustfmt::skip]
+ let section = Section::with_endian(Endian::Little)
+ // Header
+ .mark(&start)
+ .L32(&size)
+ .L16(encoding.version)
+ .L8(encoding.address_size)
+ .L8(0)
+ .L32(0)
+ .mark(&first)
+ // OffsetPair
+ .L8(4).uleb(0x10200).uleb(0x10300)
+ // A base address selection followed by an OffsetPair.
+ .L8(5).L32(0x0200_0000)
+ .L8(4).uleb(0x10400).uleb(0x10500)
+ // An empty OffsetPair followed by a normal OffsetPair.
+ .L8(4).uleb(0x10600).uleb(0x10600)
+ .L8(4).uleb(0x10800).uleb(0x10900)
+ // A StartEnd
+ .L8(6).L32(0x201_0a00).L32(0x201_0b00)
+ // A StartLength
+ .L8(7).L32(0x201_0c00).uleb(0x100)
+ // An OffsetPair that starts at 0.
+ .L8(4).uleb(0).uleb(1)
+ // An OffsetPair that starts and ends at 0.
+ .L8(4).uleb(0).uleb(0)
+ // An OffsetPair that ends at -1.
+ .L8(5).L32(0)
+ .L8(4).uleb(0).uleb(0xffff_ffff)
+ // A BaseAddressx + OffsetPair
+ .L8(1).uleb(0)
+ .L8(4).uleb(0x10100).uleb(0x10200)
+ // A StartxEndx
+ .L8(2).uleb(1).uleb(2)
+ // A StartxLength
+ .L8(3).uleb(3).uleb(0x100)
+ // A range end.
+ .L8(0)
+ // Some extra data.
+ .L32(0xffff_ffff);
+ size.set_const((&section.here() - &start - 4) as u64);
+
+ let buf = section.get_contents().unwrap();
+ let debug_ranges = DebugRanges::new(&[], LittleEndian);
+ let debug_rnglists = DebugRngLists::new(&buf, LittleEndian);
+ let rnglists = RangeLists::new(debug_ranges, debug_rnglists);
+ let offset = RangeListsOffset((&first - &start) as usize);
+ let mut ranges = rnglists
+ .ranges(offset, encoding, 0x0100_0000, debug_addr, debug_addr_base)
+ .unwrap();
+
+ // A normal range.
+ assert_eq!(
+ ranges.next(),
+ Ok(Some(Range {
+ begin: 0x0101_0200,
+ end: 0x0101_0300,
+ }))
+ );
+
+ // A base address selection followed by a normal range.
+ assert_eq!(
+ ranges.next(),
+ Ok(Some(Range {
+ begin: 0x0201_0400,
+ end: 0x0201_0500,
+ }))
+ );
+
+ // An empty range followed by a normal range.
+ assert_eq!(
+ ranges.next(),
+ Ok(Some(Range {
+ begin: 0x0201_0600,
+ end: 0x0201_0600,
+ }))
+ );
+ assert_eq!(
+ ranges.next(),
+ Ok(Some(Range {
+ begin: 0x0201_0800,
+ end: 0x0201_0900,
+ }))
+ );
+
+ // A normal range.
+ assert_eq!(
+ ranges.next(),
+ Ok(Some(Range {
+ begin: 0x0201_0a00,
+ end: 0x0201_0b00,
+ }))
+ );
+
+ // A normal range.
+ assert_eq!(
+ ranges.next(),
+ Ok(Some(Range {
+ begin: 0x0201_0c00,
+ end: 0x0201_0d00,
+ }))
+ );
+
+ // A range that starts at 0.
+ assert_eq!(
+ ranges.next(),
+ Ok(Some(Range {
+ begin: 0x0200_0000,
+ end: 0x0200_0001,
+ }))
+ );
+
+ // A range that starts and ends at 0.
+ assert_eq!(
+ ranges.next(),
+ Ok(Some(Range {
+ begin: 0x0200_0000,
+ end: 0x0200_0000,
+ }))
+ );
+
+ // A range that ends at -1.
+ assert_eq!(
+ ranges.next(),
+ Ok(Some(Range {
+ begin: 0x0000_0000,
+ end: 0xffff_ffff,
+ }))
+ );
+
+ // A BaseAddressx + OffsetPair
+ assert_eq!(
+ ranges.next(),
+ Ok(Some(Range {
+ begin: 0x0301_0100,
+ end: 0x0301_0200,
+ }))
+ );
+
+ // A StartxEndx
+ assert_eq!(
+ ranges.next(),
+ Ok(Some(Range {
+ begin: 0x0301_0300,
+ end: 0x0301_0400,
+ }))
+ );
+
+ // A StartxLength
+ assert_eq!(
+ ranges.next(),
+ Ok(Some(Range {
+ begin: 0x0301_0500,
+ end: 0x0301_0600,
+ }))
+ );
+
+ // A range end.
+ assert_eq!(ranges.next(), Ok(None));
+
+ // An offset at the end of buf.
+ let mut ranges = rnglists
+ .ranges(
+ RangeListsOffset(buf.len()),
+ encoding,
+ 0x0100_0000,
+ debug_addr,
+ debug_addr_base,
+ )
+ .unwrap();
+ assert_eq!(ranges.next(), Ok(None));
+ }
+
+ #[test]
+ fn test_rnglists_64() {
+ let encoding = Encoding {
+ format: Format::Dwarf64,
+ version: 5,
+ address_size: 8,
+ };
+ let section = Section::with_endian(Endian::Little)
+ .L64(0x0300_0000)
+ .L64(0x0301_0300)
+ .L64(0x0301_0400)
+ .L64(0x0301_0500);
+ let buf = section.get_contents().unwrap();
+ let debug_addr = &DebugAddr::from(EndianSlice::new(&buf, LittleEndian));
+ let debug_addr_base = DebugAddrBase(0);
+
+ let start = Label::new();
+ let first = Label::new();
+ let size = Label::new();
+ #[rustfmt::skip]
+ let section = Section::with_endian(Endian::Little)
+ // Header
+ .mark(&start)
+ .L32(0xffff_ffff)
+ .L64(&size)
+ .L16(encoding.version)
+ .L8(encoding.address_size)
+ .L8(0)
+ .L32(0)
+ .mark(&first)
+ // OffsetPair
+ .L8(4).uleb(0x10200).uleb(0x10300)
+ // A base address selection followed by an OffsetPair.
+ .L8(5).L64(0x0200_0000)
+ .L8(4).uleb(0x10400).uleb(0x10500)
+ // An empty OffsetPair followed by a normal OffsetPair.
+ .L8(4).uleb(0x10600).uleb(0x10600)
+ .L8(4).uleb(0x10800).uleb(0x10900)
+ // A StartEnd
+ .L8(6).L64(0x201_0a00).L64(0x201_0b00)
+ // A StartLength
+ .L8(7).L64(0x201_0c00).uleb(0x100)
+ // An OffsetPair that starts at 0.
+ .L8(4).uleb(0).uleb(1)
+ // An OffsetPair that starts and ends at 0.
+ .L8(4).uleb(0).uleb(0)
+ // An OffsetPair that ends at -1.
+ .L8(5).L64(0)
+ .L8(4).uleb(0).uleb(0xffff_ffff)
+ // A BaseAddressx + OffsetPair
+ .L8(1).uleb(0)
+ .L8(4).uleb(0x10100).uleb(0x10200)
+ // A StartxEndx
+ .L8(2).uleb(1).uleb(2)
+ // A StartxLength
+ .L8(3).uleb(3).uleb(0x100)
+ // A range end.
+ .L8(0)
+ // Some extra data.
+ .L32(0xffff_ffff);
+ size.set_const((&section.here() - &start - 12) as u64);
+
+ let buf = section.get_contents().unwrap();
+ let debug_ranges = DebugRanges::new(&[], LittleEndian);
+ let debug_rnglists = DebugRngLists::new(&buf, LittleEndian);
+ let rnglists = RangeLists::new(debug_ranges, debug_rnglists);
+ let offset = RangeListsOffset((&first - &start) as usize);
+ let mut ranges = rnglists
+ .ranges(offset, encoding, 0x0100_0000, debug_addr, debug_addr_base)
+ .unwrap();
+
+ // A normal range.
+ assert_eq!(
+ ranges.next(),
+ Ok(Some(Range {
+ begin: 0x0101_0200,
+ end: 0x0101_0300,
+ }))
+ );
+
+ // A base address selection followed by a normal range.
+ assert_eq!(
+ ranges.next(),
+ Ok(Some(Range {
+ begin: 0x0201_0400,
+ end: 0x0201_0500,
+ }))
+ );
+
+ // An empty range followed by a normal range.
+ assert_eq!(
+ ranges.next(),
+ Ok(Some(Range {
+ begin: 0x0201_0600,
+ end: 0x0201_0600,
+ }))
+ );
+ assert_eq!(
+ ranges.next(),
+ Ok(Some(Range {
+ begin: 0x0201_0800,
+ end: 0x0201_0900,
+ }))
+ );
+
+ // A normal range.
+ assert_eq!(
+ ranges.next(),
+ Ok(Some(Range {
+ begin: 0x0201_0a00,
+ end: 0x0201_0b00,
+ }))
+ );
+
+ // A normal range.
+ assert_eq!(
+ ranges.next(),
+ Ok(Some(Range {
+ begin: 0x0201_0c00,
+ end: 0x0201_0d00,
+ }))
+ );
+
+ // A range that starts at 0.
+ assert_eq!(
+ ranges.next(),
+ Ok(Some(Range {
+ begin: 0x0200_0000,
+ end: 0x0200_0001,
+ }))
+ );
+
+ // A range that starts and ends at 0.
+ assert_eq!(
+ ranges.next(),
+ Ok(Some(Range {
+ begin: 0x0200_0000,
+ end: 0x0200_0000,
+ }))
+ );
+
+ // A range that ends at -1.
+ assert_eq!(
+ ranges.next(),
+ Ok(Some(Range {
+ begin: 0x0000_0000,
+ end: 0xffff_ffff,
+ }))
+ );
+
+ // A BaseAddressx + OffsetPair
+ assert_eq!(
+ ranges.next(),
+ Ok(Some(Range {
+ begin: 0x0301_0100,
+ end: 0x0301_0200,
+ }))
+ );
+
+ // A StartxEndx
+ assert_eq!(
+ ranges.next(),
+ Ok(Some(Range {
+ begin: 0x0301_0300,
+ end: 0x0301_0400,
+ }))
+ );
+
+ // A StartxLength
+ assert_eq!(
+ ranges.next(),
+ Ok(Some(Range {
+ begin: 0x0301_0500,
+ end: 0x0301_0600,
+ }))
+ );
+
+ // A range end.
+ assert_eq!(ranges.next(), Ok(None));
+
+ // An offset at the end of buf.
+ let mut ranges = rnglists
+ .ranges(
+ RangeListsOffset(buf.len()),
+ encoding,
+ 0x0100_0000,
+ debug_addr,
+ debug_addr_base,
+ )
+ .unwrap();
+ assert_eq!(ranges.next(), Ok(None));
+ }
+
+ #[test]
+ fn test_raw_range() {
+ let range = RawRange {
+ begin: 0,
+ end: 0xffff_ffff,
+ };
+ assert!(!range.is_end());
+ assert!(!range.is_base_address(4));
+ assert!(!range.is_base_address(8));
+
+ let range = RawRange { begin: 0, end: 0 };
+ assert!(range.is_end());
+ assert!(!range.is_base_address(4));
+ assert!(!range.is_base_address(8));
+
+ let range = RawRange {
+ begin: 0xffff_ffff,
+ end: 0,
+ };
+ assert!(!range.is_end());
+ assert!(range.is_base_address(4));
+ assert!(!range.is_base_address(8));
+
+ let range = RawRange {
+ begin: 0xffff_ffff_ffff_ffff,
+ end: 0,
+ };
+ assert!(!range.is_end());
+ assert!(!range.is_base_address(4));
+ assert!(range.is_base_address(8));
+ }
+
+ #[test]
+ fn test_ranges_32() {
+ let start = Label::new();
+ let first = Label::new();
+ #[rustfmt::skip]
+ let section = Section::with_endian(Endian::Little)
+ // A range before the offset.
+ .mark(&start)
+ .L32(0x10000).L32(0x10100)
+ .mark(&first)
+ // A normal range.
+ .L32(0x10200).L32(0x10300)
+ // A base address selection followed by a normal range.
+ .L32(0xffff_ffff).L32(0x0200_0000)
+ .L32(0x10400).L32(0x10500)
+ // An empty range followed by a normal range.
+ .L32(0x10600).L32(0x10600)
+ .L32(0x10800).L32(0x10900)
+ // A range that starts at 0.
+ .L32(0).L32(1)
+ // A range that ends at -1.
+ .L32(0xffff_ffff).L32(0x0000_0000)
+ .L32(0).L32(0xffff_ffff)
+ // A range end.
+ .L32(0).L32(0)
+ // Some extra data.
+ .L32(0);
+
+ let buf = section.get_contents().unwrap();
+ let debug_ranges = DebugRanges::new(&buf, LittleEndian);
+ let debug_rnglists = DebugRngLists::new(&[], LittleEndian);
+ let rnglists = RangeLists::new(debug_ranges, debug_rnglists);
+ let offset = RangeListsOffset((&first - &start) as usize);
+ let debug_addr = &DebugAddr::from(EndianSlice::new(&[], LittleEndian));
+ let debug_addr_base = DebugAddrBase(0);
+ let encoding = Encoding {
+ format: Format::Dwarf32,
+ version: 4,
+ address_size: 4,
+ };
+ let mut ranges = rnglists
+ .ranges(offset, encoding, 0x0100_0000, debug_addr, debug_addr_base)
+ .unwrap();
+
+ // A normal range.
+ assert_eq!(
+ ranges.next(),
+ Ok(Some(Range {
+ begin: 0x0101_0200,
+ end: 0x0101_0300,
+ }))
+ );
+
+ // A base address selection followed by a normal range.
+ assert_eq!(
+ ranges.next(),
+ Ok(Some(Range {
+ begin: 0x0201_0400,
+ end: 0x0201_0500,
+ }))
+ );
+
+ // An empty range followed by a normal range.
+ assert_eq!(
+ ranges.next(),
+ Ok(Some(Range {
+ begin: 0x0201_0600,
+ end: 0x0201_0600,
+ }))
+ );
+ assert_eq!(
+ ranges.next(),
+ Ok(Some(Range {
+ begin: 0x0201_0800,
+ end: 0x0201_0900,
+ }))
+ );
+
+ // A range that starts at 0.
+ assert_eq!(
+ ranges.next(),
+ Ok(Some(Range {
+ begin: 0x0200_0000,
+ end: 0x0200_0001,
+ }))
+ );
+
+ // A range that ends at -1.
+ assert_eq!(
+ ranges.next(),
+ Ok(Some(Range {
+ begin: 0x0000_0000,
+ end: 0xffff_ffff,
+ }))
+ );
+
+ // A range end.
+ assert_eq!(ranges.next(), Ok(None));
+
+ // An offset at the end of buf.
+ let mut ranges = rnglists
+ .ranges(
+ RangeListsOffset(buf.len()),
+ encoding,
+ 0x0100_0000,
+ debug_addr,
+ debug_addr_base,
+ )
+ .unwrap();
+ assert_eq!(ranges.next(), Ok(None));
+ }
+
+ #[test]
+ fn test_ranges_64() {
+ let start = Label::new();
+ let first = Label::new();
+ #[rustfmt::skip]
+ let section = Section::with_endian(Endian::Little)
+ // A range before the offset.
+ .mark(&start)
+ .L64(0x10000).L64(0x10100)
+ .mark(&first)
+ // A normal range.
+ .L64(0x10200).L64(0x10300)
+ // A base address selection followed by a normal range.
+ .L64(0xffff_ffff_ffff_ffff).L64(0x0200_0000)
+ .L64(0x10400).L64(0x10500)
+ // An empty range followed by a normal range.
+ .L64(0x10600).L64(0x10600)
+ .L64(0x10800).L64(0x10900)
+ // A range that starts at 0.
+ .L64(0).L64(1)
+ // A range that ends at -1.
+ .L64(0xffff_ffff_ffff_ffff).L64(0x0000_0000)
+ .L64(0).L64(0xffff_ffff_ffff_ffff)
+ // A range end.
+ .L64(0).L64(0)
+ // Some extra data.
+ .L64(0);
+
+ let buf = section.get_contents().unwrap();
+ let debug_ranges = DebugRanges::new(&buf, LittleEndian);
+ let debug_rnglists = DebugRngLists::new(&[], LittleEndian);
+ let rnglists = RangeLists::new(debug_ranges, debug_rnglists);
+ let offset = RangeListsOffset((&first - &start) as usize);
+ let debug_addr = &DebugAddr::from(EndianSlice::new(&[], LittleEndian));
+ let debug_addr_base = DebugAddrBase(0);
+ let encoding = Encoding {
+ format: Format::Dwarf64,
+ version: 4,
+ address_size: 8,
+ };
+ let mut ranges = rnglists
+ .ranges(offset, encoding, 0x0100_0000, debug_addr, debug_addr_base)
+ .unwrap();
+
+ // A normal range.
+ assert_eq!(
+ ranges.next(),
+ Ok(Some(Range {
+ begin: 0x0101_0200,
+ end: 0x0101_0300,
+ }))
+ );
+
+ // A base address selection followed by a normal range.
+ assert_eq!(
+ ranges.next(),
+ Ok(Some(Range {
+ begin: 0x0201_0400,
+ end: 0x0201_0500,
+ }))
+ );
+
+ // An empty range followed by a normal range.
+ assert_eq!(
+ ranges.next(),
+ Ok(Some(Range {
+ begin: 0x0201_0600,
+ end: 0x0201_0600,
+ }))
+ );
+ assert_eq!(
+ ranges.next(),
+ Ok(Some(Range {
+ begin: 0x0201_0800,
+ end: 0x0201_0900,
+ }))
+ );
+
+ // A range that starts at 0.
+ assert_eq!(
+ ranges.next(),
+ Ok(Some(Range {
+ begin: 0x0200_0000,
+ end: 0x0200_0001,
+ }))
+ );
+
+ // A range that ends at -1.
+ assert_eq!(
+ ranges.next(),
+ Ok(Some(Range {
+ begin: 0x0,
+ end: 0xffff_ffff_ffff_ffff,
+ }))
+ );
+
+ // A range end.
+ assert_eq!(ranges.next(), Ok(None));
+
+ // An offset at the end of buf.
+ let mut ranges = rnglists
+ .ranges(
+ RangeListsOffset(buf.len()),
+ encoding,
+ 0x0100_0000,
+ debug_addr,
+ debug_addr_base,
+ )
+ .unwrap();
+ assert_eq!(ranges.next(), Ok(None));
+ }
+
+ #[test]
+ fn test_ranges_invalid() {
+ #[rustfmt::skip]
+ let section = Section::with_endian(Endian::Little)
+ // An invalid range.
+ .L32(0x20000).L32(0x10000)
+ // An invalid range after wrapping.
+ .L32(0x20000).L32(0xff01_0000);
+
+ let buf = section.get_contents().unwrap();
+ let debug_ranges = DebugRanges::new(&buf, LittleEndian);
+ let debug_rnglists = DebugRngLists::new(&[], LittleEndian);
+ let rnglists = RangeLists::new(debug_ranges, debug_rnglists);
+ let debug_addr = &DebugAddr::from(EndianSlice::new(&[], LittleEndian));
+ let debug_addr_base = DebugAddrBase(0);
+ let encoding = Encoding {
+ format: Format::Dwarf32,
+ version: 4,
+ address_size: 4,
+ };
+
+ // An invalid range.
+ let mut ranges = rnglists
+ .ranges(
+ RangeListsOffset(0x0),
+ encoding,
+ 0x0100_0000,
+ debug_addr,
+ debug_addr_base,
+ )
+ .unwrap();
+ assert_eq!(ranges.next(), Err(Error::InvalidAddressRange));
+
+ // An invalid range after wrapping.
+ let mut ranges = rnglists
+ .ranges(
+ RangeListsOffset(0x8),
+ encoding,
+ 0x0100_0000,
+ debug_addr,
+ debug_addr_base,
+ )
+ .unwrap();
+ assert_eq!(ranges.next(), Err(Error::InvalidAddressRange));
+
+ // An invalid offset.
+ match rnglists.ranges(
+ RangeListsOffset(buf.len() + 1),
+ encoding,
+ 0x0100_0000,
+ debug_addr,
+ debug_addr_base,
+ ) {
+ Err(Error::UnexpectedEof(_)) => {}
+ otherwise => panic!("Unexpected result: {:?}", otherwise),
+ }
+ }
+
+ #[test]
+ fn test_get_offset() {
+ for format in vec![Format::Dwarf32, Format::Dwarf64] {
+ let encoding = Encoding {
+ format,
+ version: 5,
+ address_size: 4,
+ };
+
+ let zero = Label::new();
+ let length = Label::new();
+ let start = Label::new();
+ let first = Label::new();
+ let end = Label::new();
+ let mut section = Section::with_endian(Endian::Little)
+ .mark(&zero)
+ .initial_length(format, &length, &start)
+ .D16(encoding.version)
+ .D8(encoding.address_size)
+ .D8(0)
+ .D32(20)
+ .mark(&first);
+ for i in 0..20 {
+ section = section.word(format.word_size(), 1000 + i);
+ }
+ section = section.mark(&end);
+ length.set_const((&end - &start) as u64);
+ let section = section.get_contents().unwrap();
+
+ let debug_ranges = DebugRanges::from(EndianSlice::new(&[], LittleEndian));
+ let debug_rnglists = DebugRngLists::from(EndianSlice::new(&section, LittleEndian));
+ let ranges = RangeLists::new(debug_ranges, debug_rnglists);
+
+ let base = DebugRngListsBase((&first - &zero) as usize);
+ assert_eq!(
+ ranges.get_offset(encoding, base, DebugRngListsIndex(0)),
+ Ok(RangeListsOffset(base.0 + 1000))
+ );
+ assert_eq!(
+ ranges.get_offset(encoding, base, DebugRngListsIndex(19)),
+ Ok(RangeListsOffset(base.0 + 1019))
+ );
+ }
+ }
+}
diff --git a/vendor/gimli-0.26.2/src/read/str.rs b/vendor/gimli-0.26.2/src/read/str.rs
new file mode 100644
index 000000000..c6b87d8f9
--- /dev/null
+++ b/vendor/gimli-0.26.2/src/read/str.rs
@@ -0,0 +1,321 @@
+use crate::common::{
+ DebugLineStrOffset, DebugStrOffset, DebugStrOffsetsBase, DebugStrOffsetsIndex, DwarfFileType,
+ Encoding, SectionId,
+};
+use crate::endianity::Endianity;
+use crate::read::{EndianSlice, Reader, ReaderOffset, Result, Section};
+use crate::Format;
+
+/// The `DebugStr` struct represents the DWARF strings
+/// found in the `.debug_str` section.
+#[derive(Debug, Default, Clone, Copy)]
+pub struct DebugStr<R> {
+ debug_str_section: R,
+}
+
+impl<'input, Endian> DebugStr<EndianSlice<'input, Endian>>
+where
+ Endian: Endianity,
+{
+ /// Construct a new `DebugStr` instance from the data in the `.debug_str`
+ /// section.
+ ///
+ /// It is the caller's responsibility to read the `.debug_str` section and
+ /// present it as a `&[u8]` slice. That means using some ELF loader on
+ /// Linux, a Mach-O loader on macOS, etc.
+ ///
+ /// ```
+ /// use gimli::{DebugStr, LittleEndian};
+ ///
+ /// # let buf = [0x00, 0x01, 0x02, 0x03];
+ /// # let read_debug_str_section_somehow = || &buf;
+ /// let debug_str = DebugStr::new(read_debug_str_section_somehow(), LittleEndian);
+ /// ```
+ pub fn new(debug_str_section: &'input [u8], endian: Endian) -> Self {
+ Self::from(EndianSlice::new(debug_str_section, endian))
+ }
+}
+
+impl<R: Reader> DebugStr<R> {
+ /// Lookup a string from the `.debug_str` section by DebugStrOffset.
+ ///
+ /// ```
+ /// use gimli::{DebugStr, DebugStrOffset, LittleEndian};
+ ///
+ /// # let buf = [0x01, 0x02, 0x00];
+ /// # let offset = DebugStrOffset(0);
+ /// # let read_debug_str_section_somehow = || &buf;
+ /// # let debug_str_offset_somehow = || offset;
+ /// let debug_str = DebugStr::new(read_debug_str_section_somehow(), LittleEndian);
+ /// println!("Found string {:?}", debug_str.get_str(debug_str_offset_somehow()));
+ /// ```
+ pub fn get_str(&self, offset: DebugStrOffset<R::Offset>) -> Result<R> {
+ let input = &mut self.debug_str_section.clone();
+ input.skip(offset.0)?;
+ input.read_null_terminated_slice()
+ }
+}
+
+impl<T> DebugStr<T> {
+ /// Create a `DebugStr` section that references the data in `self`.
+ ///
+ /// This is useful when `R` implements `Reader` but `T` does not.
+ ///
+ /// ## Example Usage
+ ///
+ /// ```rust,no_run
+ /// # let load_section = || unimplemented!();
+ /// // Read the DWARF section into a `Vec` with whatever object loader you're using.
+ /// let owned_section: gimli::DebugStr<Vec<u8>> = load_section();
+ /// // Create a reference to the DWARF section.
+ /// let section = owned_section.borrow(|section| {
+ /// gimli::EndianSlice::new(&section, gimli::LittleEndian)
+ /// });
+ /// ```
+ pub fn borrow<'a, F, R>(&'a self, mut borrow: F) -> DebugStr<R>
+ where
+ F: FnMut(&'a T) -> R,
+ {
+ borrow(&self.debug_str_section).into()
+ }
+}
+
+impl<R> Section<R> for DebugStr<R> {
+ fn id() -> SectionId {
+ SectionId::DebugStr
+ }
+
+ fn reader(&self) -> &R {
+ &self.debug_str_section
+ }
+}
+
+impl<R> From<R> for DebugStr<R> {
+ fn from(debug_str_section: R) -> Self {
+ DebugStr { debug_str_section }
+ }
+}
+
+/// The raw contents of the `.debug_str_offsets` section.
+#[derive(Debug, Default, Clone, Copy)]
+pub struct DebugStrOffsets<R> {
+ section: R,
+}
+
+impl<R: Reader> DebugStrOffsets<R> {
+ // TODO: add an iterator over the sets of entries in the section.
+ // This is not needed for common usage of the section though.
+
+ /// Returns the `.debug_str` offset at the given `base` and `index`.
+ ///
+ /// A set of entries in the `.debug_str_offsets` section consists of a header
+ /// followed by a series of string table offsets.
+ ///
+ /// The `base` must be the `DW_AT_str_offsets_base` value from the compilation unit DIE.
+ /// This is an offset that points to the first entry following the header.
+ ///
+ /// The `index` is the value of a `DW_FORM_strx` attribute.
+ ///
+ /// The `format` must be the DWARF format of the compilation unit. This format must
+ /// match the header. However, note that we do not parse the header to validate this,
+ /// since locating the header is unreliable, and the GNU extensions do not emit it.
+ pub fn get_str_offset(
+ &self,
+ format: Format,
+ base: DebugStrOffsetsBase<R::Offset>,
+ index: DebugStrOffsetsIndex<R::Offset>,
+ ) -> Result<DebugStrOffset<R::Offset>> {
+ let input = &mut self.section.clone();
+ input.skip(base.0)?;
+ input.skip(R::Offset::from_u64(
+ index.0.into_u64() * u64::from(format.word_size()),
+ )?)?;
+ input.read_offset(format).map(DebugStrOffset)
+ }
+}
+
+impl<T> DebugStrOffsets<T> {
+ /// Create a `DebugStrOffsets` section that references the data in `self`.
+ ///
+ /// This is useful when `R` implements `Reader` but `T` does not.
+ ///
+ /// ## Example Usage
+ ///
+ /// ```rust,no_run
+ /// # let load_section = || unimplemented!();
+ /// // Read the DWARF section into a `Vec` with whatever object loader you're using.
+ /// let owned_section: gimli::DebugStrOffsets<Vec<u8>> = load_section();
+ /// // Create a reference to the DWARF section.
+ /// let section = owned_section.borrow(|section| {
+ /// gimli::EndianSlice::new(&section, gimli::LittleEndian)
+ /// });
+ /// ```
+ pub fn borrow<'a, F, R>(&'a self, mut borrow: F) -> DebugStrOffsets<R>
+ where
+ F: FnMut(&'a T) -> R,
+ {
+ borrow(&self.section).into()
+ }
+}
+
+impl<R> Section<R> for DebugStrOffsets<R> {
+ fn id() -> SectionId {
+ SectionId::DebugStrOffsets
+ }
+
+ fn reader(&self) -> &R {
+ &self.section
+ }
+}
+
+impl<R> From<R> for DebugStrOffsets<R> {
+ fn from(section: R) -> Self {
+ DebugStrOffsets { section }
+ }
+}
+
+impl<Offset> DebugStrOffsetsBase<Offset>
+where
+ Offset: ReaderOffset,
+{
+ /// Returns a `DebugStrOffsetsBase` with the default value of DW_AT_str_offsets_base
+ /// for the given `Encoding` and `DwarfFileType`.
+ pub fn default_for_encoding_and_file(
+ encoding: Encoding,
+ file_type: DwarfFileType,
+ ) -> DebugStrOffsetsBase<Offset> {
+ if encoding.version >= 5 && file_type == DwarfFileType::Dwo {
+ // In .dwo files, the compiler omits the DW_AT_str_offsets_base attribute (because there is
+ // only a single unit in the file) but we must skip past the header, which the attribute
+ // would normally do for us.
+ // initial_length_size + version + 2 bytes of padding.
+ DebugStrOffsetsBase(Offset::from_u8(
+ encoding.format.initial_length_size() + 2 + 2,
+ ))
+ } else {
+ DebugStrOffsetsBase(Offset::from_u8(0))
+ }
+ }
+}
+
+/// The `DebugLineStr` struct represents the DWARF strings
+/// found in the `.debug_line_str` section.
+#[derive(Debug, Default, Clone, Copy)]
+pub struct DebugLineStr<R> {
+ section: R,
+}
+
+impl<'input, Endian> DebugLineStr<EndianSlice<'input, Endian>>
+where
+ Endian: Endianity,
+{
+ /// Construct a new `DebugLineStr` instance from the data in the `.debug_line_str`
+ /// section.
+ ///
+ /// It is the caller's responsibility to read the `.debug_line_str` section and
+ /// present it as a `&[u8]` slice. That means using some ELF loader on
+ /// Linux, a Mach-O loader on macOS, etc.
+ ///
+ /// ```
+ /// use gimli::{DebugLineStr, LittleEndian};
+ ///
+ /// # let buf = [0x00, 0x01, 0x02, 0x03];
+ /// # let read_debug_line_str_section_somehow = || &buf;
+ /// let debug_str = DebugLineStr::new(read_debug_line_str_section_somehow(), LittleEndian);
+ /// ```
+ pub fn new(debug_line_str_section: &'input [u8], endian: Endian) -> Self {
+ Self::from(EndianSlice::new(debug_line_str_section, endian))
+ }
+}
+
+impl<R: Reader> DebugLineStr<R> {
+ /// Lookup a string from the `.debug_line_str` section by DebugLineStrOffset.
+ pub fn get_str(&self, offset: DebugLineStrOffset<R::Offset>) -> Result<R> {
+ let input = &mut self.section.clone();
+ input.skip(offset.0)?;
+ input.read_null_terminated_slice()
+ }
+}
+
+impl<T> DebugLineStr<T> {
+ /// Create a `DebugLineStr` section that references the data in `self`.
+ ///
+ /// This is useful when `R` implements `Reader` but `T` does not.
+ ///
+ /// ## Example Usage
+ ///
+ /// ```rust,no_run
+ /// # let load_section = || unimplemented!();
+ /// // Read the DWARF section into a `Vec` with whatever object loader you're using.
+ /// let owned_section: gimli::DebugLineStr<Vec<u8>> = load_section();
+ /// // Create a reference to the DWARF section.
+ /// let section = owned_section.borrow(|section| {
+ /// gimli::EndianSlice::new(&section, gimli::LittleEndian)
+ /// });
+ /// ```
+ pub fn borrow<'a, F, R>(&'a self, mut borrow: F) -> DebugLineStr<R>
+ where
+ F: FnMut(&'a T) -> R,
+ {
+ borrow(&self.section).into()
+ }
+}
+
+impl<R> Section<R> for DebugLineStr<R> {
+ fn id() -> SectionId {
+ SectionId::DebugLineStr
+ }
+
+ fn reader(&self) -> &R {
+ &self.section
+ }
+}
+
+impl<R> From<R> for DebugLineStr<R> {
+ fn from(section: R) -> Self {
+ DebugLineStr { section }
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+ use crate::test_util::GimliSectionMethods;
+ use crate::LittleEndian;
+ use test_assembler::{Endian, Label, LabelMaker, Section};
+
+ #[test]
+ fn test_get_str_offset() {
+ for format in vec![Format::Dwarf32, Format::Dwarf64] {
+ let zero = Label::new();
+ let length = Label::new();
+ let start = Label::new();
+ let first = Label::new();
+ let end = Label::new();
+ let mut section = Section::with_endian(Endian::Little)
+ .mark(&zero)
+ .initial_length(format, &length, &start)
+ .D16(5)
+ .D16(0)
+ .mark(&first);
+ for i in 0..20 {
+ section = section.word(format.word_size(), 1000 + i);
+ }
+ section = section.mark(&end);
+ length.set_const((&end - &start) as u64);
+
+ let section = section.get_contents().unwrap();
+ let debug_str_offsets = DebugStrOffsets::from(EndianSlice::new(&section, LittleEndian));
+ let base = DebugStrOffsetsBase((&first - &zero) as usize);
+
+ assert_eq!(
+ debug_str_offsets.get_str_offset(format, base, DebugStrOffsetsIndex(0)),
+ Ok(DebugStrOffset(1000))
+ );
+ assert_eq!(
+ debug_str_offsets.get_str_offset(format, base, DebugStrOffsetsIndex(19)),
+ Ok(DebugStrOffset(1019))
+ );
+ }
+ }
+}
diff --git a/vendor/gimli-0.26.2/src/read/unit.rs b/vendor/gimli-0.26.2/src/read/unit.rs
new file mode 100644
index 000000000..670e55efd
--- /dev/null
+++ b/vendor/gimli-0.26.2/src/read/unit.rs
@@ -0,0 +1,6146 @@
+//! Functions for parsing DWARF `.debug_info` and `.debug_types` sections.
+
+use core::cell::Cell;
+use core::ops::{Range, RangeFrom, RangeTo};
+use core::{u16, u8};
+
+use crate::common::{
+ DebugAbbrevOffset, DebugAddrBase, DebugAddrIndex, DebugInfoOffset, DebugLineOffset,
+ DebugLineStrOffset, DebugLocListsBase, DebugLocListsIndex, DebugMacinfoOffset,
+ DebugMacroOffset, DebugRngListsBase, DebugRngListsIndex, DebugStrOffset, DebugStrOffsetsBase,
+ DebugStrOffsetsIndex, DebugTypeSignature, DebugTypesOffset, DwoId, Encoding, Format,
+ LocationListsOffset, RawRangeListsOffset, SectionId, UnitSectionOffset,
+};
+use crate::constants;
+use crate::endianity::Endianity;
+use crate::read::abbrev::get_attribute_size;
+use crate::read::{
+ Abbreviation, Abbreviations, AttributeSpecification, DebugAbbrev, DebugStr, EndianSlice, Error,
+ Expression, Reader, ReaderOffset, Result, Section, UnitOffset,
+};
+
+impl<T: ReaderOffset> DebugTypesOffset<T> {
+ /// Convert an offset to be relative to the start of the given unit,
+ /// instead of relative to the start of the .debug_types section.
+ /// Returns `None` if the offset is not within the unit entries.
+ pub fn to_unit_offset<R>(&self, unit: &UnitHeader<R>) -> Option<UnitOffset<T>>
+ where
+ R: Reader<Offset = T>,
+ {
+ let unit_offset = unit.offset().as_debug_types_offset()?;
+ let offset = UnitOffset(self.0.checked_sub(unit_offset.0)?);
+ if !unit.is_valid_offset(offset) {
+ return None;
+ }
+ Some(offset)
+ }
+}
+
+impl<T: ReaderOffset> DebugInfoOffset<T> {
+ /// Convert an offset to be relative to the start of the given unit,
+ /// instead of relative to the start of the .debug_info section.
+ /// Returns `None` if the offset is not within this unit entries.
+ pub fn to_unit_offset<R>(&self, unit: &UnitHeader<R>) -> Option<UnitOffset<T>>
+ where
+ R: Reader<Offset = T>,
+ {
+ let unit_offset = unit.offset().as_debug_info_offset()?;
+ let offset = UnitOffset(self.0.checked_sub(unit_offset.0)?);
+ if !unit.is_valid_offset(offset) {
+ return None;
+ }
+ Some(offset)
+ }
+}
+
+impl<T: ReaderOffset> UnitOffset<T> {
+ /// Convert an offset to be relative to the start of the .debug_info section,
+ /// instead of relative to the start of the given unit. Returns None if the
+ /// provided unit lives in the .debug_types section.
+ pub fn to_debug_info_offset<R>(&self, unit: &UnitHeader<R>) -> Option<DebugInfoOffset<T>>
+ where
+ R: Reader<Offset = T>,
+ {
+ let unit_offset = unit.offset().as_debug_info_offset()?;
+ Some(DebugInfoOffset(unit_offset.0 + self.0))
+ }
+
+ /// Convert an offset to be relative to the start of the .debug_types section,
+ /// instead of relative to the start of the given unit. Returns None if the
+ /// provided unit lives in the .debug_info section.
+ pub fn to_debug_types_offset<R>(&self, unit: &UnitHeader<R>) -> Option<DebugTypesOffset<T>>
+ where
+ R: Reader<Offset = T>,
+ {
+ let unit_offset = unit.offset().as_debug_types_offset()?;
+ Some(DebugTypesOffset(unit_offset.0 + self.0))
+ }
+}
+
+/// The `DebugInfo` struct represents the DWARF debugging information found in
+/// the `.debug_info` section.
+#[derive(Debug, Default, Clone, Copy)]
+pub struct DebugInfo<R> {
+ debug_info_section: R,
+}
+
+impl<'input, Endian> DebugInfo<EndianSlice<'input, Endian>>
+where
+ Endian: Endianity,
+{
+ /// Construct a new `DebugInfo` instance from the data in the `.debug_info`
+ /// section.
+ ///
+ /// It is the caller's responsibility to read the `.debug_info` section and
+ /// present it as a `&[u8]` slice. That means using some ELF loader on
+ /// Linux, a Mach-O loader on macOS, etc.
+ ///
+ /// ```
+ /// use gimli::{DebugInfo, LittleEndian};
+ ///
+ /// # let buf = [0x00, 0x01, 0x02, 0x03];
+ /// # let read_debug_info_section_somehow = || &buf;
+ /// let debug_info = DebugInfo::new(read_debug_info_section_somehow(), LittleEndian);
+ /// ```
+ pub fn new(debug_info_section: &'input [u8], endian: Endian) -> Self {
+ Self::from(EndianSlice::new(debug_info_section, endian))
+ }
+}
+
+impl<R: Reader> DebugInfo<R> {
+ /// Iterate the units in this `.debug_info` section.
+ ///
+ /// ```
+ /// use gimli::{DebugInfo, LittleEndian};
+ ///
+ /// # let buf = [];
+ /// # let read_debug_info_section_somehow = || &buf;
+ /// let debug_info = DebugInfo::new(read_debug_info_section_somehow(), LittleEndian);
+ ///
+ /// let mut iter = debug_info.units();
+ /// while let Some(unit) = iter.next().unwrap() {
+ /// println!("unit's length is {}", unit.unit_length());
+ /// }
+ /// ```
+ ///
+ /// Can be [used with
+ /// `FallibleIterator`](./index.html#using-with-fallibleiterator).
+ pub fn units(&self) -> DebugInfoUnitHeadersIter<R> {
+ DebugInfoUnitHeadersIter {
+ input: self.debug_info_section.clone(),
+ offset: DebugInfoOffset(R::Offset::from_u8(0)),
+ }
+ }
+
+ /// Get the UnitHeader located at offset from this .debug_info section.
+ ///
+ ///
+ pub fn header_from_offset(&self, offset: DebugInfoOffset<R::Offset>) -> Result<UnitHeader<R>> {
+ let input = &mut self.debug_info_section.clone();
+ input.skip(offset.0)?;
+ parse_unit_header(input, offset.into())
+ }
+}
+
+impl<T> DebugInfo<T> {
+ /// Create a `DebugInfo` section that references the data in `self`.
+ ///
+ /// This is useful when `R` implements `Reader` but `T` does not.
+ ///
+ /// ## Example Usage
+ ///
+ /// ```rust,no_run
+ /// # let load_section = || unimplemented!();
+ /// // Read the DWARF section into a `Vec` with whatever object loader you're using.
+ /// let owned_section: gimli::DebugInfo<Vec<u8>> = load_section();
+ /// // Create a reference to the DWARF section.
+ /// let section = owned_section.borrow(|section| {
+ /// gimli::EndianSlice::new(&section, gimli::LittleEndian)
+ /// });
+ /// ```
+ pub fn borrow<'a, F, R>(&'a self, mut borrow: F) -> DebugInfo<R>
+ where
+ F: FnMut(&'a T) -> R,
+ {
+ borrow(&self.debug_info_section).into()
+ }
+}
+
+impl<R> Section<R> for DebugInfo<R> {
+ fn id() -> SectionId {
+ SectionId::DebugInfo
+ }
+
+ fn reader(&self) -> &R {
+ &self.debug_info_section
+ }
+}
+
+impl<R> From<R> for DebugInfo<R> {
+ fn from(debug_info_section: R) -> Self {
+ DebugInfo { debug_info_section }
+ }
+}
+
+/// An iterator over the units of a .debug_info section.
+///
+/// See the [documentation on
+/// `DebugInfo::units`](./struct.DebugInfo.html#method.units) for more detail.
+#[derive(Clone, Debug)]
+pub struct DebugInfoUnitHeadersIter<R: Reader> {
+ input: R,
+ offset: DebugInfoOffset<R::Offset>,
+}
+
+impl<R: Reader> DebugInfoUnitHeadersIter<R> {
+ /// Advance the iterator to the next unit header.
+ pub fn next(&mut self) -> Result<Option<UnitHeader<R>>> {
+ if self.input.is_empty() {
+ Ok(None)
+ } else {
+ let len = self.input.len();
+ match parse_unit_header(&mut self.input, self.offset.into()) {
+ Ok(header) => {
+ self.offset.0 += len - self.input.len();
+ Ok(Some(header))
+ }
+ Err(e) => {
+ self.input.empty();
+ Err(e)
+ }
+ }
+ }
+ }
+}
+
+#[cfg(feature = "fallible-iterator")]
+impl<R: Reader> fallible_iterator::FallibleIterator for DebugInfoUnitHeadersIter<R> {
+ type Item = UnitHeader<R>;
+ type Error = Error;
+
+ fn next(&mut self) -> ::core::result::Result<Option<Self::Item>, Self::Error> {
+ DebugInfoUnitHeadersIter::next(self)
+ }
+}
+
+/// Parse the unit type from the unit header.
+fn parse_unit_type<R: Reader>(input: &mut R) -> Result<constants::DwUt> {
+ let val = input.read_u8()?;
+ Ok(constants::DwUt(val))
+}
+
+/// Parse the `debug_abbrev_offset` in the compilation unit header.
+fn parse_debug_abbrev_offset<R: Reader>(
+ input: &mut R,
+ format: Format,
+) -> Result<DebugAbbrevOffset<R::Offset>> {
+ input.read_offset(format).map(DebugAbbrevOffset)
+}
+
+/// Parse the `debug_info_offset` in the arange header.
+pub(crate) fn parse_debug_info_offset<R: Reader>(
+ input: &mut R,
+ format: Format,
+) -> Result<DebugInfoOffset<R::Offset>> {
+ input.read_offset(format).map(DebugInfoOffset)
+}
+
+/// This enum specifies the type of the unit and any type
+/// specific data carried in the header (e.g. the type
+/// signature/type offset of a type unit).
+#[derive(Debug, Clone, Copy, PartialEq, Eq)]
+pub enum UnitType<Offset>
+where
+ Offset: ReaderOffset,
+{
+ /// In DWARF5, a unit with type `DW_UT_compile`. In previous DWARF versions,
+ /// any unit appearing in the .debug_info section.
+ Compilation,
+ /// In DWARF5, a unit with type `DW_UT_type`. In DWARF4, any unit appearing
+ /// in the .debug_types section.
+ Type {
+ /// The unique type signature for this type unit.
+ type_signature: DebugTypeSignature,
+ /// The offset within this type unit where the type is defined.
+ type_offset: UnitOffset<Offset>,
+ },
+ /// A unit with type `DW_UT_partial`. The root DIE of this unit should be a
+ /// `DW_TAG_partial_unit`.
+ Partial,
+ /// A unit with type `DW_UT_skeleton`. The enclosed dwo_id can be used to
+ /// link this with the corresponding `SplitCompilation` unit in a dwo file.
+ /// NB: The non-standard GNU split DWARF extension to DWARF 4 will instead
+ /// be a `Compilation` unit with the dwo_id present as an attribute on the
+ /// root DIE.
+ Skeleton(DwoId),
+ /// A unit with type `DW_UT_split_compile`. The enclosed dwo_id can be used to
+ /// link this with the corresponding `Skeleton` unit in the original binary.
+ /// NB: The non-standard GNU split DWARF extension to DWARF 4 will instead
+ /// be a `Compilation` unit with the dwo_id present as an attribute on the
+ /// root DIE.
+ SplitCompilation(DwoId),
+ /// A unit with type `DW_UT_split_type`. A split type unit is identical to a
+ /// conventional type unit except for the section in which it appears.
+ SplitType {
+ /// The unique type signature for this type unit.
+ type_signature: DebugTypeSignature,
+ /// The offset within this type unit where the type is defined.
+ type_offset: UnitOffset<Offset>,
+ },
+}
+
+impl<Offset> UnitType<Offset>
+where
+ Offset: ReaderOffset,
+{
+ // TODO: This will be used by the DWARF writing code once it
+ // supports unit types other than simple compilation units.
+ #[allow(unused)]
+ pub(crate) fn dw_ut(&self) -> constants::DwUt {
+ match self {
+ UnitType::Compilation => constants::DW_UT_compile,
+ UnitType::Type { .. } => constants::DW_UT_type,
+ UnitType::Partial => constants::DW_UT_partial,
+ UnitType::Skeleton(_) => constants::DW_UT_skeleton,
+ UnitType::SplitCompilation(_) => constants::DW_UT_split_compile,
+ UnitType::SplitType { .. } => constants::DW_UT_split_type,
+ }
+ }
+}
+
+/// The common fields for the headers of compilation units and
+/// type units.
+#[derive(Debug, Clone, Copy, PartialEq, Eq)]
+pub struct UnitHeader<R, Offset = <R as Reader>::Offset>
+where
+ R: Reader<Offset = Offset>,
+ Offset: ReaderOffset,
+{
+ encoding: Encoding,
+ unit_length: Offset,
+ unit_type: UnitType<Offset>,
+ debug_abbrev_offset: DebugAbbrevOffset<Offset>,
+ unit_offset: UnitSectionOffset<Offset>,
+ entries_buf: R,
+}
+
+/// Static methods.
+impl<R, Offset> UnitHeader<R, Offset>
+where
+ R: Reader<Offset = Offset>,
+ Offset: ReaderOffset,
+{
+ /// Construct a new `UnitHeader`.
+ pub fn new(
+ encoding: Encoding,
+ unit_length: Offset,
+ unit_type: UnitType<Offset>,
+ debug_abbrev_offset: DebugAbbrevOffset<Offset>,
+ unit_offset: UnitSectionOffset<Offset>,
+ entries_buf: R,
+ ) -> Self {
+ UnitHeader {
+ encoding,
+ unit_length,
+ unit_type,
+ debug_abbrev_offset,
+ unit_offset,
+ entries_buf,
+ }
+ }
+}
+
+/// Instance methods.
+impl<R, Offset> UnitHeader<R, Offset>
+where
+ R: Reader<Offset = Offset>,
+ Offset: ReaderOffset,
+{
+ /// Get the offset of this unit within its section.
+ pub fn offset(&self) -> UnitSectionOffset<Offset> {
+ self.unit_offset
+ }
+
+ /// Return the serialized size of the common unit header for the given
+ /// DWARF format.
+ pub fn size_of_header(&self) -> usize {
+ let unit_length_size = self.encoding.format.initial_length_size() as usize;
+ let version_size = 2;
+ let debug_abbrev_offset_size = self.encoding.format.word_size() as usize;
+ let address_size_size = 1;
+ let unit_type_size = if self.encoding.version == 5 { 1 } else { 0 };
+ let type_specific_size = match self.unit_type {
+ UnitType::Compilation | UnitType::Partial => 0,
+ UnitType::Type { .. } | UnitType::SplitType { .. } => {
+ let type_signature_size = 8;
+ let type_offset_size = self.encoding.format.word_size() as usize;
+ type_signature_size + type_offset_size
+ }
+ UnitType::Skeleton(_) | UnitType::SplitCompilation(_) => 8,
+ };
+
+ unit_length_size
+ + version_size
+ + debug_abbrev_offset_size
+ + address_size_size
+ + unit_type_size
+ + type_specific_size
+ }
+
+ /// Get the length of the debugging info for this compilation unit, not
+ /// including the byte length of the encoded length itself.
+ pub fn unit_length(&self) -> Offset {
+ self.unit_length
+ }
+
+ /// Get the length of the debugging info for this compilation unit,
+ /// including the byte length of the encoded length itself.
+ pub fn length_including_self(&self) -> Offset {
+ Offset::from_u8(self.format().initial_length_size()) + self.unit_length
+ }
+
+ /// Return the encoding parameters for this unit.
+ pub fn encoding(&self) -> Encoding {
+ self.encoding
+ }
+
+ /// Get the DWARF version of the debugging info for this compilation unit.
+ pub fn version(&self) -> u16 {
+ self.encoding.version
+ }
+
+ /// Get the UnitType of this unit.
+ pub fn type_(&self) -> UnitType<Offset> {
+ self.unit_type
+ }
+
+ /// The offset into the `.debug_abbrev` section for this compilation unit's
+ /// debugging information entries' abbreviations.
+ pub fn debug_abbrev_offset(&self) -> DebugAbbrevOffset<Offset> {
+ self.debug_abbrev_offset
+ }
+
+ /// The size of addresses (in bytes) in this compilation unit.
+ pub fn address_size(&self) -> u8 {
+ self.encoding.address_size
+ }
+
+ /// Whether this compilation unit is encoded in 64- or 32-bit DWARF.
+ pub fn format(&self) -> Format {
+ self.encoding.format
+ }
+
+ /// The serialized size of the header for this compilation unit.
+ pub fn header_size(&self) -> Offset {
+ self.length_including_self() - self.entries_buf.len()
+ }
+
+ pub(crate) fn is_valid_offset(&self, offset: UnitOffset<Offset>) -> bool {
+ let size_of_header = self.header_size();
+ if offset.0 < size_of_header {
+ return false;
+ }
+
+ let relative_to_entries_buf = offset.0 - size_of_header;
+ relative_to_entries_buf < self.entries_buf.len()
+ }
+
+ /// Get the underlying bytes for the supplied range.
+ pub fn range(&self, idx: Range<UnitOffset<Offset>>) -> Result<R> {
+ if !self.is_valid_offset(idx.start) {
+ return Err(Error::OffsetOutOfBounds);
+ }
+ if !self.is_valid_offset(idx.end) {
+ return Err(Error::OffsetOutOfBounds);
+ }
+ assert!(idx.start <= idx.end);
+ let size_of_header = self.header_size();
+ let start = idx.start.0 - size_of_header;
+ let end = idx.end.0 - size_of_header;
+ let mut input = self.entries_buf.clone();
+ input.skip(start)?;
+ input.truncate(end - start)?;
+ Ok(input)
+ }
+
+ /// Get the underlying bytes for the supplied range.
+ pub fn range_from(&self, idx: RangeFrom<UnitOffset<Offset>>) -> Result<R> {
+ if !self.is_valid_offset(idx.start) {
+ return Err(Error::OffsetOutOfBounds);
+ }
+ let start = idx.start.0 - self.header_size();
+ let mut input = self.entries_buf.clone();
+ input.skip(start)?;
+ Ok(input)
+ }
+
+ /// Get the underlying bytes for the supplied range.
+ pub fn range_to(&self, idx: RangeTo<UnitOffset<Offset>>) -> Result<R> {
+ if !self.is_valid_offset(idx.end) {
+ return Err(Error::OffsetOutOfBounds);
+ }
+ let end = idx.end.0 - self.header_size();
+ let mut input = self.entries_buf.clone();
+ input.truncate(end)?;
+ Ok(input)
+ }
+
+ /// Read the `DebuggingInformationEntry` at the given offset.
+ pub fn entry<'me, 'abbrev>(
+ &'me self,
+ abbreviations: &'abbrev Abbreviations,
+ offset: UnitOffset<Offset>,
+ ) -> Result<DebuggingInformationEntry<'abbrev, 'me, R>> {
+ let mut input = self.range_from(offset..)?;
+ let entry = DebuggingInformationEntry::parse(&mut input, self, abbreviations)?;
+ entry.ok_or(Error::NoEntryAtGivenOffset)
+ }
+
+ /// Navigate this unit's `DebuggingInformationEntry`s.
+ pub fn entries<'me, 'abbrev>(
+ &'me self,
+ abbreviations: &'abbrev Abbreviations,
+ ) -> EntriesCursor<'abbrev, 'me, R> {
+ EntriesCursor {
+ unit: self,
+ input: self.entries_buf.clone(),
+ abbreviations,
+ cached_current: None,
+ delta_depth: 0,
+ }
+ }
+
+ /// Navigate this compilation unit's `DebuggingInformationEntry`s
+ /// starting at the given offset.
+ pub fn entries_at_offset<'me, 'abbrev>(
+ &'me self,
+ abbreviations: &'abbrev Abbreviations,
+ offset: UnitOffset<Offset>,
+ ) -> Result<EntriesCursor<'abbrev, 'me, R>> {
+ let input = self.range_from(offset..)?;
+ Ok(EntriesCursor {
+ unit: self,
+ input,
+ abbreviations,
+ cached_current: None,
+ delta_depth: 0,
+ })
+ }
+
+ /// Navigate this unit's `DebuggingInformationEntry`s as a tree
+ /// starting at the given offset.
+ pub fn entries_tree<'me, 'abbrev>(
+ &'me self,
+ abbreviations: &'abbrev Abbreviations,
+ offset: Option<UnitOffset<Offset>>,
+ ) -> Result<EntriesTree<'abbrev, 'me, R>> {
+ let input = match offset {
+ Some(offset) => self.range_from(offset..)?,
+ None => self.entries_buf.clone(),
+ };
+ Ok(EntriesTree::new(input, self, abbreviations))
+ }
+
+ /// Read the raw data that defines the Debugging Information Entries.
+ pub fn entries_raw<'me, 'abbrev>(
+ &'me self,
+ abbreviations: &'abbrev Abbreviations,
+ offset: Option<UnitOffset<Offset>>,
+ ) -> Result<EntriesRaw<'abbrev, 'me, R>> {
+ let input = match offset {
+ Some(offset) => self.range_from(offset..)?,
+ None => self.entries_buf.clone(),
+ };
+ Ok(EntriesRaw {
+ input,
+ unit: self,
+ abbreviations,
+ depth: 0,
+ })
+ }
+
+ /// Parse this unit's abbreviations.
+ pub fn abbreviations(&self, debug_abbrev: &DebugAbbrev<R>) -> Result<Abbreviations> {
+ debug_abbrev.abbreviations(self.debug_abbrev_offset())
+ }
+}
+
+/// Parse a unit header.
+fn parse_unit_header<R, Offset>(
+ input: &mut R,
+ unit_offset: UnitSectionOffset<Offset>,
+) -> Result<UnitHeader<R>>
+where
+ R: Reader<Offset = Offset>,
+ Offset: ReaderOffset,
+{
+ let (unit_length, format) = input.read_initial_length()?;
+ let mut rest = input.split(unit_length)?;
+
+ let version = rest.read_u16()?;
+ let abbrev_offset;
+ let address_size;
+ let unit_type;
+ // DWARF 1 was very different, and is obsolete, so isn't supported by this
+ // reader.
+ if 2 <= version && version <= 4 {
+ abbrev_offset = parse_debug_abbrev_offset(&mut rest, format)?;
+ address_size = rest.read_u8()?;
+ // Before DWARF5, all units in the .debug_info section are compilation
+ // units, and all units in the .debug_types section are type units.
+ unit_type = match unit_offset {
+ UnitSectionOffset::DebugInfoOffset(_) => constants::DW_UT_compile,
+ UnitSectionOffset::DebugTypesOffset(_) => constants::DW_UT_type,
+ };
+ } else if version == 5 {
+ unit_type = parse_unit_type(&mut rest)?;
+ address_size = rest.read_u8()?;
+ abbrev_offset = parse_debug_abbrev_offset(&mut rest, format)?;
+ } else {
+ return Err(Error::UnknownVersion(u64::from(version)));
+ }
+ let encoding = Encoding {
+ format,
+ version,
+ address_size,
+ };
+
+ // Parse any data specific to this type of unit.
+ let unit_type = match unit_type {
+ constants::DW_UT_compile => UnitType::Compilation,
+ constants::DW_UT_type => {
+ let type_signature = parse_type_signature(&mut rest)?;
+ let type_offset = parse_type_offset(&mut rest, format)?;
+ UnitType::Type {
+ type_signature,
+ type_offset,
+ }
+ }
+ constants::DW_UT_partial => UnitType::Partial,
+ constants::DW_UT_skeleton => {
+ let dwo_id = parse_dwo_id(&mut rest)?;
+ UnitType::Skeleton(dwo_id)
+ }
+ constants::DW_UT_split_compile => {
+ let dwo_id = parse_dwo_id(&mut rest)?;
+ UnitType::SplitCompilation(dwo_id)
+ }
+ constants::DW_UT_split_type => {
+ let type_signature = parse_type_signature(&mut rest)?;
+ let type_offset = parse_type_offset(&mut rest, format)?;
+ UnitType::SplitType {
+ type_signature,
+ type_offset,
+ }
+ }
+ _ => return Err(Error::UnsupportedUnitType),
+ };
+
+ Ok(UnitHeader::new(
+ encoding,
+ unit_length,
+ unit_type,
+ abbrev_offset,
+ unit_offset,
+ rest,
+ ))
+}
+
+/// Parse a dwo_id from a header
+fn parse_dwo_id<R: Reader>(input: &mut R) -> Result<DwoId> {
+ Ok(DwoId(input.read_u64()?))
+}
+
+/// A Debugging Information Entry (DIE).
+///
+/// DIEs have a set of attributes and optionally have children DIEs as well.
+#[derive(Clone, Debug)]
+pub struct DebuggingInformationEntry<'abbrev, 'unit, R, Offset = <R as Reader>::Offset>
+where
+ R: Reader<Offset = Offset>,
+ Offset: ReaderOffset,
+{
+ offset: UnitOffset<Offset>,
+ attrs_slice: R,
+ attrs_len: Cell<Option<Offset>>,
+ abbrev: &'abbrev Abbreviation,
+ unit: &'unit UnitHeader<R, Offset>,
+}
+
+impl<'abbrev, 'unit, R, Offset> DebuggingInformationEntry<'abbrev, 'unit, R, Offset>
+where
+ R: Reader<Offset = Offset>,
+ Offset: ReaderOffset,
+{
+ /// Construct a new `DebuggingInformationEntry`.
+ pub fn new(
+ offset: UnitOffset<Offset>,
+ attrs_slice: R,
+ abbrev: &'abbrev Abbreviation,
+ unit: &'unit UnitHeader<R, Offset>,
+ ) -> Self {
+ DebuggingInformationEntry {
+ offset,
+ attrs_slice,
+ attrs_len: Cell::new(None),
+ abbrev,
+ unit,
+ }
+ }
+
+ /// Get this entry's code.
+ pub fn code(&self) -> u64 {
+ self.abbrev.code()
+ }
+
+ /// Get this entry's offset.
+ pub fn offset(&self) -> UnitOffset<Offset> {
+ self.offset
+ }
+
+ /// Get this entry's `DW_TAG_whatever` tag.
+ ///
+ /// ```
+ /// # use gimli::{DebugAbbrev, DebugInfo, LittleEndian};
+ /// # let info_buf = [
+ /// # // Comilation unit header
+ /// #
+ /// # // 32-bit unit length = 12
+ /// # 0x0c, 0x00, 0x00, 0x00,
+ /// # // Version 4
+ /// # 0x04, 0x00,
+ /// # // debug_abbrev_offset
+ /// # 0x00, 0x00, 0x00, 0x00,
+ /// # // Address size
+ /// # 0x04,
+ /// #
+ /// # // DIEs
+ /// #
+ /// # // Abbreviation code
+ /// # 0x01,
+ /// # // Attribute of form DW_FORM_string = "foo\0"
+ /// # 0x66, 0x6f, 0x6f, 0x00,
+ /// # ];
+ /// # let debug_info = DebugInfo::new(&info_buf, LittleEndian);
+ /// # let abbrev_buf = [
+ /// # // Code
+ /// # 0x01,
+ /// # // DW_TAG_subprogram
+ /// # 0x2e,
+ /// # // DW_CHILDREN_no
+ /// # 0x00,
+ /// # // Begin attributes
+ /// # // Attribute name = DW_AT_name
+ /// # 0x03,
+ /// # // Attribute form = DW_FORM_string
+ /// # 0x08,
+ /// # // End attributes
+ /// # 0x00,
+ /// # 0x00,
+ /// # // Null terminator
+ /// # 0x00
+ /// # ];
+ /// # let debug_abbrev = DebugAbbrev::new(&abbrev_buf, LittleEndian);
+ /// # let unit = debug_info.units().next().unwrap().unwrap();
+ /// # let abbrevs = unit.abbreviations(&debug_abbrev).unwrap();
+ /// # let mut cursor = unit.entries(&abbrevs);
+ /// # let (_, entry) = cursor.next_dfs().unwrap().unwrap();
+ /// # let mut get_some_entry = || entry;
+ /// let entry = get_some_entry();
+ ///
+ /// match entry.tag() {
+ /// gimli::DW_TAG_subprogram =>
+ /// println!("this entry contains debug info about a function"),
+ /// gimli::DW_TAG_inlined_subroutine =>
+ /// println!("this entry contains debug info about a particular instance of inlining"),
+ /// gimli::DW_TAG_variable =>
+ /// println!("this entry contains debug info about a local variable"),
+ /// gimli::DW_TAG_formal_parameter =>
+ /// println!("this entry contains debug info about a function parameter"),
+ /// otherwise =>
+ /// println!("this entry is some other kind of data: {:?}", otherwise),
+ /// };
+ /// ```
+ pub fn tag(&self) -> constants::DwTag {
+ self.abbrev.tag()
+ }
+
+ /// Return true if this entry's type can have children, false otherwise.
+ pub fn has_children(&self) -> bool {
+ self.abbrev.has_children()
+ }
+
+ /// Iterate over this entry's set of attributes.
+ ///
+ /// ```
+ /// use gimli::{DebugAbbrev, DebugInfo, LittleEndian};
+ ///
+ /// // Read the `.debug_info` section.
+ ///
+ /// # let info_buf = [
+ /// # // Comilation unit header
+ /// #
+ /// # // 32-bit unit length = 12
+ /// # 0x0c, 0x00, 0x00, 0x00,
+ /// # // Version 4
+ /// # 0x04, 0x00,
+ /// # // debug_abbrev_offset
+ /// # 0x00, 0x00, 0x00, 0x00,
+ /// # // Address size
+ /// # 0x04,
+ /// #
+ /// # // DIEs
+ /// #
+ /// # // Abbreviation code
+ /// # 0x01,
+ /// # // Attribute of form DW_FORM_string = "foo\0"
+ /// # 0x66, 0x6f, 0x6f, 0x00,
+ /// # ];
+ /// # let read_debug_info_section_somehow = || &info_buf;
+ /// let debug_info = DebugInfo::new(read_debug_info_section_somehow(), LittleEndian);
+ ///
+ /// // Get the data about the first compilation unit out of the `.debug_info`.
+ ///
+ /// let unit = debug_info.units().next()
+ /// .expect("Should have at least one compilation unit")
+ /// .expect("and it should parse ok");
+ ///
+ /// // Read the `.debug_abbrev` section and parse the
+ /// // abbreviations for our compilation unit.
+ ///
+ /// # let abbrev_buf = [
+ /// # // Code
+ /// # 0x01,
+ /// # // DW_TAG_subprogram
+ /// # 0x2e,
+ /// # // DW_CHILDREN_no
+ /// # 0x00,
+ /// # // Begin attributes
+ /// # // Attribute name = DW_AT_name
+ /// # 0x03,
+ /// # // Attribute form = DW_FORM_string
+ /// # 0x08,
+ /// # // End attributes
+ /// # 0x00,
+ /// # 0x00,
+ /// # // Null terminator
+ /// # 0x00
+ /// # ];
+ /// # let read_debug_abbrev_section_somehow = || &abbrev_buf;
+ /// let debug_abbrev = DebugAbbrev::new(read_debug_abbrev_section_somehow(), LittleEndian);
+ /// let abbrevs = unit.abbreviations(&debug_abbrev).unwrap();
+ ///
+ /// // Get the first entry from that compilation unit.
+ ///
+ /// let mut cursor = unit.entries(&abbrevs);
+ /// let (_, entry) = cursor.next_dfs()
+ /// .expect("Should parse next entry")
+ /// .expect("Should have at least one entry");
+ ///
+ /// // Finally, print the first entry's attributes.
+ ///
+ /// let mut attrs = entry.attrs();
+ /// while let Some(attr) = attrs.next().unwrap() {
+ /// println!("Attribute name = {:?}", attr.name());
+ /// println!("Attribute value = {:?}", attr.value());
+ /// }
+ /// ```
+ ///
+ /// Can be [used with
+ /// `FallibleIterator`](./index.html#using-with-fallibleiterator).
+ pub fn attrs<'me>(&'me self) -> AttrsIter<'abbrev, 'me, 'unit, R> {
+ AttrsIter {
+ input: self.attrs_slice.clone(),
+ attributes: self.abbrev.attributes(),
+ entry: self,
+ }
+ }
+
+ /// Find the first attribute in this entry which has the given name,
+ /// and return it. Returns `Ok(None)` if no attribute is found.
+ pub fn attr(&self, name: constants::DwAt) -> Result<Option<Attribute<R>>> {
+ let mut attrs = self.attrs();
+ while let Some(attr) = attrs.next()? {
+ if attr.name() == name {
+ return Ok(Some(attr));
+ }
+ }
+ Ok(None)
+ }
+
+ /// Find the first attribute in this entry which has the given name,
+ /// and return its raw value. Returns `Ok(None)` if no attribute is found.
+ pub fn attr_value_raw(&self, name: constants::DwAt) -> Result<Option<AttributeValue<R>>> {
+ self.attr(name)
+ .map(|attr| attr.map(|attr| attr.raw_value()))
+ }
+
+ /// Find the first attribute in this entry which has the given name,
+ /// and return its normalized value. Returns `Ok(None)` if no
+ /// attribute is found.
+ pub fn attr_value(&self, name: constants::DwAt) -> Result<Option<AttributeValue<R>>> {
+ self.attr(name).map(|attr| attr.map(|attr| attr.value()))
+ }
+
+ /// Return the input buffer after the last attribute.
+ #[allow(clippy::inline_always)]
+ #[inline(always)]
+ fn after_attrs(&self) -> Result<R> {
+ if let Some(attrs_len) = self.attrs_len.get() {
+ let mut input = self.attrs_slice.clone();
+ input.skip(attrs_len)?;
+ Ok(input)
+ } else {
+ let mut attrs = self.attrs();
+ while let Some(_) = attrs.next()? {}
+ Ok(attrs.input)
+ }
+ }
+
+ /// Use the `DW_AT_sibling` attribute to find the input buffer for the
+ /// next sibling. Returns `None` if the attribute is missing or invalid.
+ fn sibling(&self) -> Option<R> {
+ let attr = self.attr_value(constants::DW_AT_sibling);
+ if let Ok(Some(AttributeValue::UnitRef(offset))) = attr {
+ if offset.0 > self.offset.0 {
+ if let Ok(input) = self.unit.range_from(offset..) {
+ return Some(input);
+ }
+ }
+ }
+ None
+ }
+
+ /// Parse an entry. Returns `Ok(None)` for null entries.
+ #[allow(clippy::inline_always)]
+ #[inline(always)]
+ fn parse(
+ input: &mut R,
+ unit: &'unit UnitHeader<R>,
+ abbreviations: &'abbrev Abbreviations,
+ ) -> Result<Option<Self>> {
+ let offset = unit.header_size() + input.offset_from(&unit.entries_buf);
+ let code = input.read_uleb128()?;
+ if code == 0 {
+ return Ok(None);
+ };
+ let abbrev = abbreviations.get(code).ok_or(Error::UnknownAbbreviation)?;
+ Ok(Some(DebuggingInformationEntry {
+ offset: UnitOffset(offset),
+ attrs_slice: input.clone(),
+ attrs_len: Cell::new(None),
+ abbrev,
+ unit,
+ }))
+ }
+}
+
+/// The value of an attribute in a `DebuggingInformationEntry`.
+//
+// Set the discriminant size so that all variants use the same alignment
+// for their data. This gives better code generation in `parse_attribute`.
+#[repr(u64)]
+#[derive(Clone, Copy, Debug, Eq, PartialEq)]
+pub enum AttributeValue<R, Offset = <R as Reader>::Offset>
+where
+ R: Reader<Offset = Offset>,
+ Offset: ReaderOffset,
+{
+ /// "Refers to some location in the address space of the described program."
+ Addr(u64),
+
+ /// A slice of an arbitrary number of bytes.
+ Block(R),
+
+ /// A one byte constant data value. How to interpret the byte depends on context.
+ ///
+ /// From section 7 of the standard: "Depending on context, it may be a
+ /// signed integer, an unsigned integer, a floating-point constant, or
+ /// anything else."
+ Data1(u8),
+
+ /// A two byte constant data value. How to interpret the bytes depends on context.
+ ///
+ /// These bytes have been converted from `R::Endian`. This may need to be reversed
+ /// if this was not required.
+ ///
+ /// From section 7 of the standard: "Depending on context, it may be a
+ /// signed integer, an unsigned integer, a floating-point constant, or
+ /// anything else."
+ Data2(u16),
+
+ /// A four byte constant data value. How to interpret the bytes depends on context.
+ ///
+ /// These bytes have been converted from `R::Endian`. This may need to be reversed
+ /// if this was not required.
+ ///
+ /// From section 7 of the standard: "Depending on context, it may be a
+ /// signed integer, an unsigned integer, a floating-point constant, or
+ /// anything else."
+ Data4(u32),
+
+ /// An eight byte constant data value. How to interpret the bytes depends on context.
+ ///
+ /// These bytes have been converted from `R::Endian`. This may need to be reversed
+ /// if this was not required.
+ ///
+ /// From section 7 of the standard: "Depending on context, it may be a
+ /// signed integer, an unsigned integer, a floating-point constant, or
+ /// anything else."
+ Data8(u64),
+
+ /// A signed integer constant.
+ Sdata(i64),
+
+ /// An unsigned integer constant.
+ Udata(u64),
+
+ /// "The information bytes contain a DWARF expression (see Section 2.5) or
+ /// location description (see Section 2.6)."
+ Exprloc(Expression<R>),
+
+ /// A boolean that indicates presence or absence of the attribute.
+ Flag(bool),
+
+ /// An offset into another section. Which section this is an offset into
+ /// depends on context.
+ SecOffset(Offset),
+
+ /// An offset to a set of addresses in the `.debug_addr` section.
+ DebugAddrBase(DebugAddrBase<Offset>),
+
+ /// An index into a set of addresses in the `.debug_addr` section.
+ DebugAddrIndex(DebugAddrIndex<Offset>),
+
+ /// An offset into the current compilation unit.
+ UnitRef(UnitOffset<Offset>),
+
+ /// An offset into the current `.debug_info` section, but possibly a
+ /// different compilation unit from the current one.
+ DebugInfoRef(DebugInfoOffset<Offset>),
+
+ /// An offset into the `.debug_info` section of the supplementary object file.
+ DebugInfoRefSup(DebugInfoOffset<Offset>),
+
+ /// An offset into the `.debug_line` section.
+ DebugLineRef(DebugLineOffset<Offset>),
+
+ /// An offset into either the `.debug_loc` section or the `.debug_loclists` section.
+ LocationListsRef(LocationListsOffset<Offset>),
+
+ /// An offset to a set of offsets in the `.debug_loclists` section.
+ DebugLocListsBase(DebugLocListsBase<Offset>),
+
+ /// An index into a set of offsets in the `.debug_loclists` section.
+ DebugLocListsIndex(DebugLocListsIndex<Offset>),
+
+ /// An offset into the `.debug_macinfo` section.
+ DebugMacinfoRef(DebugMacinfoOffset<Offset>),
+
+ /// An offset into the `.debug_macro` section.
+ DebugMacroRef(DebugMacroOffset<Offset>),
+
+ /// An offset into the `.debug_ranges` section.
+ RangeListsRef(RawRangeListsOffset<Offset>),
+
+ /// An offset to a set of offsets in the `.debug_rnglists` section.
+ DebugRngListsBase(DebugRngListsBase<Offset>),
+
+ /// An index into a set of offsets in the `.debug_rnglists` section.
+ DebugRngListsIndex(DebugRngListsIndex<Offset>),
+
+ /// A type signature.
+ DebugTypesRef(DebugTypeSignature),
+
+ /// An offset into the `.debug_str` section.
+ DebugStrRef(DebugStrOffset<Offset>),
+
+ /// An offset into the `.debug_str` section of the supplementary object file.
+ DebugStrRefSup(DebugStrOffset<Offset>),
+
+ /// An offset to a set of entries in the `.debug_str_offsets` section.
+ DebugStrOffsetsBase(DebugStrOffsetsBase<Offset>),
+
+ /// An index into a set of entries in the `.debug_str_offsets` section.
+ DebugStrOffsetsIndex(DebugStrOffsetsIndex<Offset>),
+
+ /// An offset into the `.debug_line_str` section.
+ DebugLineStrRef(DebugLineStrOffset<Offset>),
+
+ /// A slice of bytes representing a string. Does not include a final null byte.
+ /// Not guaranteed to be UTF-8 or anything like that.
+ String(R),
+
+ /// The value of a `DW_AT_encoding` attribute.
+ Encoding(constants::DwAte),
+
+ /// The value of a `DW_AT_decimal_sign` attribute.
+ DecimalSign(constants::DwDs),
+
+ /// The value of a `DW_AT_endianity` attribute.
+ Endianity(constants::DwEnd),
+
+ /// The value of a `DW_AT_accessibility` attribute.
+ Accessibility(constants::DwAccess),
+
+ /// The value of a `DW_AT_visibility` attribute.
+ Visibility(constants::DwVis),
+
+ /// The value of a `DW_AT_virtuality` attribute.
+ Virtuality(constants::DwVirtuality),
+
+ /// The value of a `DW_AT_language` attribute.
+ Language(constants::DwLang),
+
+ /// The value of a `DW_AT_address_class` attribute.
+ AddressClass(constants::DwAddr),
+
+ /// The value of a `DW_AT_identifier_case` attribute.
+ IdentifierCase(constants::DwId),
+
+ /// The value of a `DW_AT_calling_convention` attribute.
+ CallingConvention(constants::DwCc),
+
+ /// The value of a `DW_AT_inline` attribute.
+ Inline(constants::DwInl),
+
+ /// The value of a `DW_AT_ordering` attribute.
+ Ordering(constants::DwOrd),
+
+ /// An index into the filename entries from the line number information
+ /// table for the compilation unit containing this value.
+ FileIndex(u64),
+
+ /// An implementation-defined identifier uniquely identifying a compilation
+ /// unit.
+ DwoId(DwoId),
+}
+
+/// An attribute in a `DebuggingInformationEntry`, consisting of a name and
+/// associated value.
+#[derive(Copy, Clone, Debug, Eq, PartialEq)]
+pub struct Attribute<R: Reader> {
+ name: constants::DwAt,
+ value: AttributeValue<R>,
+}
+
+impl<R: Reader> Attribute<R> {
+ /// Get this attribute's name.
+ pub fn name(&self) -> constants::DwAt {
+ self.name
+ }
+
+ /// Get this attribute's raw value.
+ pub fn raw_value(&self) -> AttributeValue<R> {
+ self.value.clone()
+ }
+
+ /// Get this attribute's normalized value.
+ ///
+ /// Attribute values can potentially be encoded in multiple equivalent forms,
+ /// and may have special meaning depending on the attribute name. This method
+ /// converts the attribute value to a normalized form based on the attribute
+ /// name.
+ ///
+ /// See "Table 7.5: Attribute encodings" and "Table 7.6: Attribute form encodings".
+ #[allow(clippy::cyclomatic_complexity)]
+ #[allow(clippy::match_same_arms)]
+ pub fn value(&self) -> AttributeValue<R> {
+ // Table 7.5 shows the possible attribute classes for each name.
+ // Table 7.6 shows the possible attribute classes for each form.
+ // For each attribute name, we need to match on the form, and
+ // convert it to one of the classes that is allowed for both
+ // the name and the form.
+ //
+ // The individual class conversions rarely vary for each name,
+ // so for each class conversion we define a macro that matches
+ // on the allowed forms for that class.
+ //
+ // For some classes, we don't need to do any conversion, so their
+ // macro is empty. In the future we may want to fill them in to
+ // provide strict checking of the forms for each class. For now,
+ // they simply provide a way to document the allowed classes for
+ // each name.
+
+ // DW_FORM_addr
+ // DW_FORM_addrx
+ // DW_FORM_addrx1
+ // DW_FORM_addrx2
+ // DW_FORM_addrx3
+ // DW_FORM_addrx4
+ macro_rules! address {
+ () => {};
+ }
+ // DW_FORM_sec_offset
+ macro_rules! addrptr {
+ () => {
+ if let Some(offset) = self.offset_value() {
+ return AttributeValue::DebugAddrBase(DebugAddrBase(offset));
+ }
+ };
+ }
+ // DW_FORM_block
+ // DW_FORM_block1
+ // DW_FORM_block2
+ // DW_FORM_block4
+ macro_rules! block {
+ () => {};
+ }
+ // DW_FORM_sdata
+ // DW_FORM_udata
+ // DW_FORM_data1
+ // DW_FORM_data2
+ // DW_FORM_data4
+ // DW_FORM_data8
+ // DW_FORM_data16
+ // DW_FORM_implicit_const
+ macro_rules! constant {
+ ($value:ident, $variant:ident) => {
+ if let Some(value) = self.$value() {
+ return AttributeValue::$variant(value);
+ }
+ };
+ ($value:ident, $variant:ident, $constant:ident) => {
+ if let Some(value) = self.$value() {
+ return AttributeValue::$variant(constants::$constant(value));
+ }
+ };
+ }
+ // DW_FORM_exprloc
+ macro_rules! exprloc {
+ () => {
+ if let Some(value) = self.exprloc_value() {
+ return AttributeValue::Exprloc(value);
+ }
+ };
+ }
+ // DW_FORM_flag
+ // DW_FORM_flag_present
+ macro_rules! flag {
+ () => {};
+ }
+ // DW_FORM_sec_offset
+ macro_rules! lineptr {
+ () => {
+ if let Some(offset) = self.offset_value() {
+ return AttributeValue::DebugLineRef(DebugLineOffset(offset));
+ }
+ };
+ }
+ // This also covers `loclist` in DWARF version 5.
+ // DW_FORM_sec_offset
+ // DW_FORM_loclistx
+ macro_rules! loclistptr {
+ () => {
+ // DebugLocListsIndex is also an allowed form in DWARF version 5.
+ if let Some(offset) = self.offset_value() {
+ return AttributeValue::LocationListsRef(LocationListsOffset(offset));
+ }
+ };
+ }
+ // DW_FORM_sec_offset
+ macro_rules! loclistsptr {
+ () => {
+ if let Some(offset) = self.offset_value() {
+ return AttributeValue::DebugLocListsBase(DebugLocListsBase(offset));
+ }
+ };
+ }
+ // DWARF version <= 4.
+ // DW_FORM_sec_offset
+ macro_rules! macinfoptr {
+ () => {
+ if let Some(offset) = self.offset_value() {
+ return AttributeValue::DebugMacinfoRef(DebugMacinfoOffset(offset));
+ }
+ };
+ }
+ // DWARF version >= 5.
+ // DW_FORM_sec_offset
+ macro_rules! macroptr {
+ () => {
+ if let Some(offset) = self.offset_value() {
+ return AttributeValue::DebugMacroRef(DebugMacroOffset(offset));
+ }
+ };
+ }
+ // DW_FORM_ref_addr
+ // DW_FORM_ref1
+ // DW_FORM_ref2
+ // DW_FORM_ref4
+ // DW_FORM_ref8
+ // DW_FORM_ref_udata
+ // DW_FORM_ref_sig8
+ // DW_FORM_ref_sup4
+ // DW_FORM_ref_sup8
+ macro_rules! reference {
+ () => {};
+ }
+ // This also covers `rnglist` in DWARF version 5.
+ // DW_FORM_sec_offset
+ // DW_FORM_rnglistx
+ macro_rules! rangelistptr {
+ () => {
+ // DebugRngListsIndex is also an allowed form in DWARF version 5.
+ if let Some(offset) = self.offset_value() {
+ return AttributeValue::RangeListsRef(RawRangeListsOffset(offset));
+ }
+ };
+ }
+ // DW_FORM_sec_offset
+ macro_rules! rnglistsptr {
+ () => {
+ if let Some(offset) = self.offset_value() {
+ return AttributeValue::DebugRngListsBase(DebugRngListsBase(offset));
+ }
+ };
+ }
+ // DW_FORM_string
+ // DW_FORM_strp
+ // DW_FORM_strx
+ // DW_FORM_strx1
+ // DW_FORM_strx2
+ // DW_FORM_strx3
+ // DW_FORM_strx4
+ // DW_FORM_strp_sup
+ // DW_FORM_line_strp
+ macro_rules! string {
+ () => {};
+ }
+ // DW_FORM_sec_offset
+ macro_rules! stroffsetsptr {
+ () => {
+ if let Some(offset) = self.offset_value() {
+ return AttributeValue::DebugStrOffsetsBase(DebugStrOffsetsBase(offset));
+ }
+ };
+ }
+ // This isn't a separate form but it's useful to distinguish it from a generic udata.
+ macro_rules! dwoid {
+ () => {
+ if let Some(value) = self.udata_value() {
+ return AttributeValue::DwoId(DwoId(value));
+ }
+ };
+ }
+
+ // Perform the allowed class conversions for each attribute name.
+ match self.name {
+ constants::DW_AT_sibling => {
+ reference!();
+ }
+ constants::DW_AT_location => {
+ exprloc!();
+ loclistptr!();
+ }
+ constants::DW_AT_name => {
+ string!();
+ }
+ constants::DW_AT_ordering => {
+ constant!(u8_value, Ordering, DwOrd);
+ }
+ constants::DW_AT_byte_size
+ | constants::DW_AT_bit_offset
+ | constants::DW_AT_bit_size => {
+ constant!(udata_value, Udata);
+ exprloc!();
+ reference!();
+ }
+ constants::DW_AT_stmt_list => {
+ lineptr!();
+ }
+ constants::DW_AT_low_pc => {
+ address!();
+ }
+ constants::DW_AT_high_pc => {
+ address!();
+ constant!(udata_value, Udata);
+ }
+ constants::DW_AT_language => {
+ constant!(u16_value, Language, DwLang);
+ }
+ constants::DW_AT_discr => {
+ reference!();
+ }
+ constants::DW_AT_discr_value => {
+ // constant: depends on type of DW_TAG_variant_part,
+ // so caller must normalize.
+ }
+ constants::DW_AT_visibility => {
+ constant!(u8_value, Visibility, DwVis);
+ }
+ constants::DW_AT_import => {
+ reference!();
+ }
+ constants::DW_AT_string_length => {
+ exprloc!();
+ loclistptr!();
+ reference!();
+ }
+ constants::DW_AT_common_reference => {
+ reference!();
+ }
+ constants::DW_AT_comp_dir => {
+ string!();
+ }
+ constants::DW_AT_const_value => {
+ // TODO: constant: sign depends on DW_AT_type.
+ block!();
+ string!();
+ }
+ constants::DW_AT_containing_type => {
+ reference!();
+ }
+ constants::DW_AT_default_value => {
+ // TODO: constant: sign depends on DW_AT_type.
+ reference!();
+ flag!();
+ }
+ constants::DW_AT_inline => {
+ constant!(u8_value, Inline, DwInl);
+ }
+ constants::DW_AT_is_optional => {
+ flag!();
+ }
+ constants::DW_AT_lower_bound => {
+ // TODO: constant: sign depends on DW_AT_type.
+ exprloc!();
+ reference!();
+ }
+ constants::DW_AT_producer => {
+ string!();
+ }
+ constants::DW_AT_prototyped => {
+ flag!();
+ }
+ constants::DW_AT_return_addr => {
+ exprloc!();
+ loclistptr!();
+ }
+ constants::DW_AT_start_scope => {
+ // TODO: constant
+ rangelistptr!();
+ }
+ constants::DW_AT_bit_stride => {
+ constant!(udata_value, Udata);
+ exprloc!();
+ reference!();
+ }
+ constants::DW_AT_upper_bound => {
+ // TODO: constant: sign depends on DW_AT_type.
+ exprloc!();
+ reference!();
+ }
+ constants::DW_AT_abstract_origin => {
+ reference!();
+ }
+ constants::DW_AT_accessibility => {
+ constant!(u8_value, Accessibility, DwAccess);
+ }
+ constants::DW_AT_address_class => {
+ constant!(udata_value, AddressClass, DwAddr);
+ }
+ constants::DW_AT_artificial => {
+ flag!();
+ }
+ constants::DW_AT_base_types => {
+ reference!();
+ }
+ constants::DW_AT_calling_convention => {
+ constant!(u8_value, CallingConvention, DwCc);
+ }
+ constants::DW_AT_count => {
+ // TODO: constant
+ exprloc!();
+ reference!();
+ }
+ constants::DW_AT_data_member_location => {
+ // Constants must be handled before loclistptr so that DW_FORM_data4/8
+ // are correctly interpreted for DWARF version 4+.
+ constant!(udata_value, Udata);
+ exprloc!();
+ loclistptr!();
+ }
+ constants::DW_AT_decl_column => {
+ constant!(udata_value, Udata);
+ }
+ constants::DW_AT_decl_file => {
+ constant!(udata_value, FileIndex);
+ }
+ constants::DW_AT_decl_line => {
+ constant!(udata_value, Udata);
+ }
+ constants::DW_AT_declaration => {
+ flag!();
+ }
+ constants::DW_AT_discr_list => {
+ block!();
+ }
+ constants::DW_AT_encoding => {
+ constant!(u8_value, Encoding, DwAte);
+ }
+ constants::DW_AT_external => {
+ flag!();
+ }
+ constants::DW_AT_frame_base => {
+ exprloc!();
+ loclistptr!();
+ }
+ constants::DW_AT_friend => {
+ reference!();
+ }
+ constants::DW_AT_identifier_case => {
+ constant!(u8_value, IdentifierCase, DwId);
+ }
+ constants::DW_AT_macro_info => {
+ macinfoptr!();
+ }
+ constants::DW_AT_namelist_item => {
+ reference!();
+ }
+ constants::DW_AT_priority => {
+ reference!();
+ }
+ constants::DW_AT_segment => {
+ exprloc!();
+ loclistptr!();
+ }
+ constants::DW_AT_specification => {
+ reference!();
+ }
+ constants::DW_AT_static_link => {
+ exprloc!();
+ loclistptr!();
+ }
+ constants::DW_AT_type => {
+ reference!();
+ }
+ constants::DW_AT_use_location => {
+ exprloc!();
+ loclistptr!();
+ }
+ constants::DW_AT_variable_parameter => {
+ flag!();
+ }
+ constants::DW_AT_virtuality => {
+ constant!(u8_value, Virtuality, DwVirtuality);
+ }
+ constants::DW_AT_vtable_elem_location => {
+ exprloc!();
+ loclistptr!();
+ }
+ constants::DW_AT_allocated => {
+ // TODO: constant
+ exprloc!();
+ reference!();
+ }
+ constants::DW_AT_associated => {
+ // TODO: constant
+ exprloc!();
+ reference!();
+ }
+ constants::DW_AT_data_location => {
+ exprloc!();
+ }
+ constants::DW_AT_byte_stride => {
+ constant!(udata_value, Udata);
+ exprloc!();
+ reference!();
+ }
+ constants::DW_AT_entry_pc => {
+ // TODO: constant
+ address!();
+ }
+ constants::DW_AT_use_UTF8 => {
+ flag!();
+ }
+ constants::DW_AT_extension => {
+ reference!();
+ }
+ constants::DW_AT_ranges => {
+ rangelistptr!();
+ }
+ constants::DW_AT_trampoline => {
+ address!();
+ flag!();
+ reference!();
+ string!();
+ }
+ constants::DW_AT_call_column => {
+ constant!(udata_value, Udata);
+ }
+ constants::DW_AT_call_file => {
+ constant!(udata_value, FileIndex);
+ }
+ constants::DW_AT_call_line => {
+ constant!(udata_value, Udata);
+ }
+ constants::DW_AT_description => {
+ string!();
+ }
+ constants::DW_AT_binary_scale => {
+ // TODO: constant
+ }
+ constants::DW_AT_decimal_scale => {
+ // TODO: constant
+ }
+ constants::DW_AT_small => {
+ reference!();
+ }
+ constants::DW_AT_decimal_sign => {
+ constant!(u8_value, DecimalSign, DwDs);
+ }
+ constants::DW_AT_digit_count => {
+ // TODO: constant
+ }
+ constants::DW_AT_picture_string => {
+ string!();
+ }
+ constants::DW_AT_mutable => {
+ flag!();
+ }
+ constants::DW_AT_threads_scaled => {
+ flag!();
+ }
+ constants::DW_AT_explicit => {
+ flag!();
+ }
+ constants::DW_AT_object_pointer => {
+ reference!();
+ }
+ constants::DW_AT_endianity => {
+ constant!(u8_value, Endianity, DwEnd);
+ }
+ constants::DW_AT_elemental => {
+ flag!();
+ }
+ constants::DW_AT_pure => {
+ flag!();
+ }
+ constants::DW_AT_recursive => {
+ flag!();
+ }
+ constants::DW_AT_signature => {
+ reference!();
+ }
+ constants::DW_AT_main_subprogram => {
+ flag!();
+ }
+ constants::DW_AT_data_bit_offset => {
+ // TODO: constant
+ }
+ constants::DW_AT_const_expr => {
+ flag!();
+ }
+ constants::DW_AT_enum_class => {
+ flag!();
+ }
+ constants::DW_AT_linkage_name => {
+ string!();
+ }
+ constants::DW_AT_string_length_bit_size => {
+ // TODO: constant
+ }
+ constants::DW_AT_string_length_byte_size => {
+ // TODO: constant
+ }
+ constants::DW_AT_rank => {
+ // TODO: constant
+ exprloc!();
+ }
+ constants::DW_AT_str_offsets_base => {
+ stroffsetsptr!();
+ }
+ constants::DW_AT_addr_base | constants::DW_AT_GNU_addr_base => {
+ addrptr!();
+ }
+ constants::DW_AT_rnglists_base | constants::DW_AT_GNU_ranges_base => {
+ rnglistsptr!();
+ }
+ constants::DW_AT_dwo_name => {
+ string!();
+ }
+ constants::DW_AT_reference => {
+ flag!();
+ }
+ constants::DW_AT_rvalue_reference => {
+ flag!();
+ }
+ constants::DW_AT_macros => {
+ macroptr!();
+ }
+ constants::DW_AT_call_all_calls => {
+ flag!();
+ }
+ constants::DW_AT_call_all_source_calls => {
+ flag!();
+ }
+ constants::DW_AT_call_all_tail_calls => {
+ flag!();
+ }
+ constants::DW_AT_call_return_pc => {
+ address!();
+ }
+ constants::DW_AT_call_value => {
+ exprloc!();
+ }
+ constants::DW_AT_call_origin => {
+ exprloc!();
+ }
+ constants::DW_AT_call_parameter => {
+ reference!();
+ }
+ constants::DW_AT_call_pc => {
+ address!();
+ }
+ constants::DW_AT_call_tail_call => {
+ flag!();
+ }
+ constants::DW_AT_call_target => {
+ exprloc!();
+ }
+ constants::DW_AT_call_target_clobbered => {
+ exprloc!();
+ }
+ constants::DW_AT_call_data_location => {
+ exprloc!();
+ }
+ constants::DW_AT_call_data_value => {
+ exprloc!();
+ }
+ constants::DW_AT_noreturn => {
+ flag!();
+ }
+ constants::DW_AT_alignment => {
+ // TODO: constant
+ }
+ constants::DW_AT_export_symbols => {
+ flag!();
+ }
+ constants::DW_AT_deleted => {
+ flag!();
+ }
+ constants::DW_AT_defaulted => {
+ // TODO: constant
+ }
+ constants::DW_AT_loclists_base => {
+ loclistsptr!();
+ }
+ constants::DW_AT_GNU_dwo_id => {
+ dwoid!();
+ }
+ _ => {}
+ }
+ self.value.clone()
+ }
+
+ /// Try to convert this attribute's value to a u8.
+ #[inline]
+ pub fn u8_value(&self) -> Option<u8> {
+ self.value.u8_value()
+ }
+
+ /// Try to convert this attribute's value to a u16.
+ #[inline]
+ pub fn u16_value(&self) -> Option<u16> {
+ self.value.u16_value()
+ }
+
+ /// Try to convert this attribute's value to an unsigned integer.
+ #[inline]
+ pub fn udata_value(&self) -> Option<u64> {
+ self.value.udata_value()
+ }
+
+ /// Try to convert this attribute's value to a signed integer.
+ #[inline]
+ pub fn sdata_value(&self) -> Option<i64> {
+ self.value.sdata_value()
+ }
+
+ /// Try to convert this attribute's value to an offset.
+ #[inline]
+ pub fn offset_value(&self) -> Option<R::Offset> {
+ self.value.offset_value()
+ }
+
+ /// Try to convert this attribute's value to an expression or location buffer.
+ ///
+ /// Expressions and locations may be `DW_FORM_block*` or `DW_FORM_exprloc`.
+ /// The standard doesn't mention `DW_FORM_block*` as a possible form, but
+ /// it is encountered in practice.
+ #[inline]
+ pub fn exprloc_value(&self) -> Option<Expression<R>> {
+ self.value.exprloc_value()
+ }
+
+ /// Try to return this attribute's value as a string slice.
+ ///
+ /// If this attribute's value is either an inline `DW_FORM_string` string,
+ /// or a `DW_FORM_strp` reference to an offset into the `.debug_str`
+ /// section, return the attribute's string value as `Some`. Other attribute
+ /// value forms are returned as `None`.
+ ///
+ /// Warning: this function does not handle all possible string forms.
+ /// Use `Dwarf::attr_string` instead.
+ #[inline]
+ pub fn string_value(&self, debug_str: &DebugStr<R>) -> Option<R> {
+ self.value.string_value(debug_str)
+ }
+
+ /// Try to return this attribute's value as a string slice.
+ ///
+ /// If this attribute's value is either an inline `DW_FORM_string` string,
+ /// or a `DW_FORM_strp` reference to an offset into the `.debug_str`
+ /// section, or a `DW_FORM_strp_sup` reference to an offset into a supplementary
+ /// object file, return the attribute's string value as `Some`. Other attribute
+ /// value forms are returned as `None`.
+ ///
+ /// Warning: this function does not handle all possible string forms.
+ /// Use `Dwarf::attr_string` instead.
+ #[inline]
+ pub fn string_value_sup(
+ &self,
+ debug_str: &DebugStr<R>,
+ debug_str_sup: Option<&DebugStr<R>>,
+ ) -> Option<R> {
+ self.value.string_value_sup(debug_str, debug_str_sup)
+ }
+}
+
+impl<R, Offset> AttributeValue<R, Offset>
+where
+ R: Reader<Offset = Offset>,
+ Offset: ReaderOffset,
+{
+ /// Try to convert this attribute's value to a u8.
+ pub fn u8_value(&self) -> Option<u8> {
+ if let Some(value) = self.udata_value() {
+ if value <= u64::from(u8::MAX) {
+ return Some(value as u8);
+ }
+ }
+ None
+ }
+
+ /// Try to convert this attribute's value to a u16.
+ pub fn u16_value(&self) -> Option<u16> {
+ if let Some(value) = self.udata_value() {
+ if value <= u64::from(u16::MAX) {
+ return Some(value as u16);
+ }
+ }
+ None
+ }
+
+ /// Try to convert this attribute's value to an unsigned integer.
+ pub fn udata_value(&self) -> Option<u64> {
+ Some(match *self {
+ AttributeValue::Data1(data) => u64::from(data),
+ AttributeValue::Data2(data) => u64::from(data),
+ AttributeValue::Data4(data) => u64::from(data),
+ AttributeValue::Data8(data) => data,
+ AttributeValue::Udata(data) => data,
+ AttributeValue::Sdata(data) => {
+ if data < 0 {
+ // Maybe we should emit a warning here
+ return None;
+ }
+ data as u64
+ }
+ _ => return None,
+ })
+ }
+
+ /// Try to convert this attribute's value to a signed integer.
+ pub fn sdata_value(&self) -> Option<i64> {
+ Some(match *self {
+ AttributeValue::Data1(data) => i64::from(data as i8),
+ AttributeValue::Data2(data) => i64::from(data as i16),
+ AttributeValue::Data4(data) => i64::from(data as i32),
+ AttributeValue::Data8(data) => data as i64,
+ AttributeValue::Sdata(data) => data,
+ AttributeValue::Udata(data) => {
+ if data > i64::max_value() as u64 {
+ // Maybe we should emit a warning here
+ return None;
+ }
+ data as i64
+ }
+ _ => return None,
+ })
+ }
+
+ /// Try to convert this attribute's value to an offset.
+ pub fn offset_value(&self) -> Option<R::Offset> {
+ // While offsets will be DW_FORM_data4/8 in DWARF version 2/3,
+ // these have already been converted to `SecOffset.
+ if let AttributeValue::SecOffset(offset) = *self {
+ Some(offset)
+ } else {
+ None
+ }
+ }
+
+ /// Try to convert this attribute's value to an expression or location buffer.
+ ///
+ /// Expressions and locations may be `DW_FORM_block*` or `DW_FORM_exprloc`.
+ /// The standard doesn't mention `DW_FORM_block*` as a possible form, but
+ /// it is encountered in practice.
+ pub fn exprloc_value(&self) -> Option<Expression<R>> {
+ Some(match *self {
+ AttributeValue::Block(ref data) => Expression(data.clone()),
+ AttributeValue::Exprloc(ref data) => data.clone(),
+ _ => return None,
+ })
+ }
+
+ /// Try to return this attribute's value as a string slice.
+ ///
+ /// If this attribute's value is either an inline `DW_FORM_string` string,
+ /// or a `DW_FORM_strp` reference to an offset into the `.debug_str`
+ /// section, return the attribute's string value as `Some`. Other attribute
+ /// value forms are returned as `None`.
+ ///
+ /// Warning: this function does not handle all possible string forms.
+ /// Use `Dwarf::attr_string` instead.
+ pub fn string_value(&self, debug_str: &DebugStr<R>) -> Option<R> {
+ match *self {
+ AttributeValue::String(ref string) => Some(string.clone()),
+ AttributeValue::DebugStrRef(offset) => debug_str.get_str(offset).ok(),
+ _ => None,
+ }
+ }
+
+ /// Try to return this attribute's value as a string slice.
+ ///
+ /// If this attribute's value is either an inline `DW_FORM_string` string,
+ /// or a `DW_FORM_strp` reference to an offset into the `.debug_str`
+ /// section, or a `DW_FORM_strp_sup` reference to an offset into a supplementary
+ /// object file, return the attribute's string value as `Some`. Other attribute
+ /// value forms are returned as `None`.
+ ///
+ /// Warning: this function does not handle all possible string forms.
+ /// Use `Dwarf::attr_string` instead.
+ pub fn string_value_sup(
+ &self,
+ debug_str: &DebugStr<R>,
+ debug_str_sup: Option<&DebugStr<R>>,
+ ) -> Option<R> {
+ match *self {
+ AttributeValue::String(ref string) => Some(string.clone()),
+ AttributeValue::DebugStrRef(offset) => debug_str.get_str(offset).ok(),
+ AttributeValue::DebugStrRefSup(offset) => {
+ debug_str_sup.and_then(|s| s.get_str(offset).ok())
+ }
+ _ => None,
+ }
+ }
+}
+
+fn length_u8_value<R: Reader>(input: &mut R) -> Result<R> {
+ let len = input.read_u8().map(R::Offset::from_u8)?;
+ input.split(len)
+}
+
+fn length_u16_value<R: Reader>(input: &mut R) -> Result<R> {
+ let len = input.read_u16().map(R::Offset::from_u16)?;
+ input.split(len)
+}
+
+fn length_u32_value<R: Reader>(input: &mut R) -> Result<R> {
+ let len = input.read_u32().map(R::Offset::from_u32)?;
+ input.split(len)
+}
+
+fn length_uleb128_value<R: Reader>(input: &mut R) -> Result<R> {
+ let len = input.read_uleb128().and_then(R::Offset::from_u64)?;
+ input.split(len)
+}
+
+// Return true if the given `name` can be a section offset in DWARF version 2/3.
+// This is required to correctly handle relocations.
+fn allow_section_offset(name: constants::DwAt, version: u16) -> bool {
+ match name {
+ constants::DW_AT_location
+ | constants::DW_AT_stmt_list
+ | constants::DW_AT_string_length
+ | constants::DW_AT_return_addr
+ | constants::DW_AT_start_scope
+ | constants::DW_AT_frame_base
+ | constants::DW_AT_macro_info
+ | constants::DW_AT_macros
+ | constants::DW_AT_segment
+ | constants::DW_AT_static_link
+ | constants::DW_AT_use_location
+ | constants::DW_AT_vtable_elem_location
+ | constants::DW_AT_ranges => true,
+ constants::DW_AT_data_member_location => version == 2 || version == 3,
+ _ => false,
+ }
+}
+
+pub(crate) fn parse_attribute<'unit, R: Reader>(
+ input: &mut R,
+ encoding: Encoding,
+ spec: AttributeSpecification,
+) -> Result<Attribute<R>> {
+ let mut form = spec.form();
+ loop {
+ let value = match form {
+ constants::DW_FORM_indirect => {
+ let dynamic_form = input.read_uleb128_u16()?;
+ form = constants::DwForm(dynamic_form);
+ continue;
+ }
+ constants::DW_FORM_addr => {
+ let addr = input.read_address(encoding.address_size)?;
+ AttributeValue::Addr(addr)
+ }
+ constants::DW_FORM_block1 => {
+ let block = length_u8_value(input)?;
+ AttributeValue::Block(block)
+ }
+ constants::DW_FORM_block2 => {
+ let block = length_u16_value(input)?;
+ AttributeValue::Block(block)
+ }
+ constants::DW_FORM_block4 => {
+ let block = length_u32_value(input)?;
+ AttributeValue::Block(block)
+ }
+ constants::DW_FORM_block => {
+ let block = length_uleb128_value(input)?;
+ AttributeValue::Block(block)
+ }
+ constants::DW_FORM_data1 => {
+ let data = input.read_u8()?;
+ AttributeValue::Data1(data)
+ }
+ constants::DW_FORM_data2 => {
+ let data = input.read_u16()?;
+ AttributeValue::Data2(data)
+ }
+ constants::DW_FORM_data4 => {
+ // DWARF version 2/3 may use DW_FORM_data4/8 for section offsets.
+ // Ensure we handle relocations here.
+ if encoding.format == Format::Dwarf32
+ && allow_section_offset(spec.name(), encoding.version)
+ {
+ let offset = input.read_offset(Format::Dwarf32)?;
+ AttributeValue::SecOffset(offset)
+ } else {
+ let data = input.read_u32()?;
+ AttributeValue::Data4(data)
+ }
+ }
+ constants::DW_FORM_data8 => {
+ // DWARF version 2/3 may use DW_FORM_data4/8 for section offsets.
+ // Ensure we handle relocations here.
+ if encoding.format == Format::Dwarf64
+ && allow_section_offset(spec.name(), encoding.version)
+ {
+ let offset = input.read_offset(Format::Dwarf64)?;
+ AttributeValue::SecOffset(offset)
+ } else {
+ let data = input.read_u64()?;
+ AttributeValue::Data8(data)
+ }
+ }
+ constants::DW_FORM_data16 => {
+ let block = input.split(R::Offset::from_u8(16))?;
+ AttributeValue::Block(block)
+ }
+ constants::DW_FORM_udata => {
+ let data = input.read_uleb128()?;
+ AttributeValue::Udata(data)
+ }
+ constants::DW_FORM_sdata => {
+ let data = input.read_sleb128()?;
+ AttributeValue::Sdata(data)
+ }
+ constants::DW_FORM_exprloc => {
+ let block = length_uleb128_value(input)?;
+ AttributeValue::Exprloc(Expression(block))
+ }
+ constants::DW_FORM_flag => {
+ let present = input.read_u8()?;
+ AttributeValue::Flag(present != 0)
+ }
+ constants::DW_FORM_flag_present => {
+ // FlagPresent is this weird compile time always true thing that
+ // isn't actually present in the serialized DIEs, only in the abbreviation.
+ AttributeValue::Flag(true)
+ }
+ constants::DW_FORM_sec_offset => {
+ let offset = input.read_offset(encoding.format)?;
+ AttributeValue::SecOffset(offset)
+ }
+ constants::DW_FORM_ref1 => {
+ let reference = input.read_u8().map(R::Offset::from_u8)?;
+ AttributeValue::UnitRef(UnitOffset(reference))
+ }
+ constants::DW_FORM_ref2 => {
+ let reference = input.read_u16().map(R::Offset::from_u16)?;
+ AttributeValue::UnitRef(UnitOffset(reference))
+ }
+ constants::DW_FORM_ref4 => {
+ let reference = input.read_u32().map(R::Offset::from_u32)?;
+ AttributeValue::UnitRef(UnitOffset(reference))
+ }
+ constants::DW_FORM_ref8 => {
+ let reference = input.read_u64().and_then(R::Offset::from_u64)?;
+ AttributeValue::UnitRef(UnitOffset(reference))
+ }
+ constants::DW_FORM_ref_udata => {
+ let reference = input.read_uleb128().and_then(R::Offset::from_u64)?;
+ AttributeValue::UnitRef(UnitOffset(reference))
+ }
+ constants::DW_FORM_ref_addr => {
+ // This is an offset, but DWARF version 2 specifies that DW_FORM_ref_addr
+ // has the same size as an address on the target system. This was changed
+ // in DWARF version 3.
+ let offset = if encoding.version == 2 {
+ input.read_sized_offset(encoding.address_size)?
+ } else {
+ input.read_offset(encoding.format)?
+ };
+ AttributeValue::DebugInfoRef(DebugInfoOffset(offset))
+ }
+ constants::DW_FORM_ref_sig8 => {
+ let signature = input.read_u64()?;
+ AttributeValue::DebugTypesRef(DebugTypeSignature(signature))
+ }
+ constants::DW_FORM_ref_sup4 => {
+ let offset = input.read_u32().map(R::Offset::from_u32)?;
+ AttributeValue::DebugInfoRefSup(DebugInfoOffset(offset))
+ }
+ constants::DW_FORM_ref_sup8 => {
+ let offset = input.read_u64().and_then(R::Offset::from_u64)?;
+ AttributeValue::DebugInfoRefSup(DebugInfoOffset(offset))
+ }
+ constants::DW_FORM_GNU_ref_alt => {
+ let offset = input.read_offset(encoding.format)?;
+ AttributeValue::DebugInfoRefSup(DebugInfoOffset(offset))
+ }
+ constants::DW_FORM_string => {
+ let string = input.read_null_terminated_slice()?;
+ AttributeValue::String(string)
+ }
+ constants::DW_FORM_strp => {
+ let offset = input.read_offset(encoding.format)?;
+ AttributeValue::DebugStrRef(DebugStrOffset(offset))
+ }
+ constants::DW_FORM_strp_sup | constants::DW_FORM_GNU_strp_alt => {
+ let offset = input.read_offset(encoding.format)?;
+ AttributeValue::DebugStrRefSup(DebugStrOffset(offset))
+ }
+ constants::DW_FORM_line_strp => {
+ let offset = input.read_offset(encoding.format)?;
+ AttributeValue::DebugLineStrRef(DebugLineStrOffset(offset))
+ }
+ constants::DW_FORM_implicit_const => {
+ let data = spec
+ .implicit_const_value()
+ .ok_or(Error::InvalidImplicitConst)?;
+ AttributeValue::Sdata(data)
+ }
+ constants::DW_FORM_strx | constants::DW_FORM_GNU_str_index => {
+ let index = input.read_uleb128().and_then(R::Offset::from_u64)?;
+ AttributeValue::DebugStrOffsetsIndex(DebugStrOffsetsIndex(index))
+ }
+ constants::DW_FORM_strx1 => {
+ let index = input.read_u8().map(R::Offset::from_u8)?;
+ AttributeValue::DebugStrOffsetsIndex(DebugStrOffsetsIndex(index))
+ }
+ constants::DW_FORM_strx2 => {
+ let index = input.read_u16().map(R::Offset::from_u16)?;
+ AttributeValue::DebugStrOffsetsIndex(DebugStrOffsetsIndex(index))
+ }
+ constants::DW_FORM_strx3 => {
+ let index = input.read_uint(3).and_then(R::Offset::from_u64)?;
+ AttributeValue::DebugStrOffsetsIndex(DebugStrOffsetsIndex(index))
+ }
+ constants::DW_FORM_strx4 => {
+ let index = input.read_u32().map(R::Offset::from_u32)?;
+ AttributeValue::DebugStrOffsetsIndex(DebugStrOffsetsIndex(index))
+ }
+ constants::DW_FORM_addrx | constants::DW_FORM_GNU_addr_index => {
+ let index = input.read_uleb128().and_then(R::Offset::from_u64)?;
+ AttributeValue::DebugAddrIndex(DebugAddrIndex(index))
+ }
+ constants::DW_FORM_addrx1 => {
+ let index = input.read_u8().map(R::Offset::from_u8)?;
+ AttributeValue::DebugAddrIndex(DebugAddrIndex(index))
+ }
+ constants::DW_FORM_addrx2 => {
+ let index = input.read_u16().map(R::Offset::from_u16)?;
+ AttributeValue::DebugAddrIndex(DebugAddrIndex(index))
+ }
+ constants::DW_FORM_addrx3 => {
+ let index = input.read_uint(3).and_then(R::Offset::from_u64)?;
+ AttributeValue::DebugAddrIndex(DebugAddrIndex(index))
+ }
+ constants::DW_FORM_addrx4 => {
+ let index = input.read_u32().map(R::Offset::from_u32)?;
+ AttributeValue::DebugAddrIndex(DebugAddrIndex(index))
+ }
+ constants::DW_FORM_loclistx => {
+ let index = input.read_uleb128().and_then(R::Offset::from_u64)?;
+ AttributeValue::DebugLocListsIndex(DebugLocListsIndex(index))
+ }
+ constants::DW_FORM_rnglistx => {
+ let index = input.read_uleb128().and_then(R::Offset::from_u64)?;
+ AttributeValue::DebugRngListsIndex(DebugRngListsIndex(index))
+ }
+ _ => {
+ return Err(Error::UnknownForm);
+ }
+ };
+ let attr = Attribute {
+ name: spec.name(),
+ value,
+ };
+ return Ok(attr);
+ }
+}
+
+pub(crate) fn skip_attributes<'unit, R: Reader>(
+ input: &mut R,
+ encoding: Encoding,
+ specs: &[AttributeSpecification],
+) -> Result<()> {
+ let mut skip_bytes = R::Offset::from_u8(0);
+ for spec in specs {
+ let mut form = spec.form();
+ loop {
+ if let Some(len) = get_attribute_size(form, encoding) {
+ // We know the length of this attribute. Accumulate that length.
+ skip_bytes += R::Offset::from_u8(len);
+ break;
+ }
+
+ // We have encountered a variable-length attribute.
+ if skip_bytes != R::Offset::from_u8(0) {
+ // Skip the accumulated skip bytes and then read the attribute normally.
+ input.skip(skip_bytes)?;
+ skip_bytes = R::Offset::from_u8(0);
+ }
+
+ match form {
+ constants::DW_FORM_indirect => {
+ let dynamic_form = input.read_uleb128_u16()?;
+ form = constants::DwForm(dynamic_form);
+ continue;
+ }
+ constants::DW_FORM_block1 => {
+ skip_bytes = input.read_u8().map(R::Offset::from_u8)?;
+ }
+ constants::DW_FORM_block2 => {
+ skip_bytes = input.read_u16().map(R::Offset::from_u16)?;
+ }
+ constants::DW_FORM_block4 => {
+ skip_bytes = input.read_u32().map(R::Offset::from_u32)?;
+ }
+ constants::DW_FORM_block | constants::DW_FORM_exprloc => {
+ skip_bytes = input.read_uleb128().and_then(R::Offset::from_u64)?;
+ }
+ constants::DW_FORM_string => {
+ let _ = input.read_null_terminated_slice()?;
+ }
+ constants::DW_FORM_udata
+ | constants::DW_FORM_sdata
+ | constants::DW_FORM_ref_udata
+ | constants::DW_FORM_strx
+ | constants::DW_FORM_GNU_str_index
+ | constants::DW_FORM_addrx
+ | constants::DW_FORM_GNU_addr_index
+ | constants::DW_FORM_loclistx
+ | constants::DW_FORM_rnglistx => {
+ input.skip_leb128()?;
+ }
+ _ => {
+ return Err(Error::UnknownForm);
+ }
+ };
+ break;
+ }
+ }
+ if skip_bytes != R::Offset::from_u8(0) {
+ // Skip the remaining accumulated skip bytes.
+ input.skip(skip_bytes)?;
+ }
+ Ok(())
+}
+
+/// An iterator over a particular entry's attributes.
+///
+/// See [the documentation for
+/// `DebuggingInformationEntry::attrs()`](./struct.DebuggingInformationEntry.html#method.attrs)
+/// for details.
+///
+/// Can be [used with
+/// `FallibleIterator`](./index.html#using-with-fallibleiterator).
+#[derive(Clone, Copy, Debug)]
+pub struct AttrsIter<'abbrev, 'entry, 'unit, R: Reader> {
+ input: R,
+ attributes: &'abbrev [AttributeSpecification],
+ entry: &'entry DebuggingInformationEntry<'abbrev, 'unit, R>,
+}
+
+impl<'abbrev, 'entry, 'unit, R: Reader> AttrsIter<'abbrev, 'entry, 'unit, R> {
+ /// Advance the iterator and return the next attribute.
+ ///
+ /// Returns `None` when iteration is finished. If an error
+ /// occurs while parsing the next attribute, then this error
+ /// is returned, and all subsequent calls return `None`.
+ #[allow(clippy::inline_always)]
+ #[inline(always)]
+ pub fn next(&mut self) -> Result<Option<Attribute<R>>> {
+ if self.attributes.is_empty() {
+ // Now that we have parsed all of the attributes, we know where
+ // either (1) this entry's children start, if the abbreviation says
+ // this entry has children; or (2) where this entry's siblings
+ // begin.
+ if let Some(end) = self.entry.attrs_len.get() {
+ debug_assert_eq!(end, self.input.offset_from(&self.entry.attrs_slice));
+ } else {
+ self.entry
+ .attrs_len
+ .set(Some(self.input.offset_from(&self.entry.attrs_slice)));
+ }
+
+ return Ok(None);
+ }
+
+ let spec = self.attributes[0];
+ let rest_spec = &self.attributes[1..];
+ match parse_attribute(&mut self.input, self.entry.unit.encoding(), spec) {
+ Ok(attr) => {
+ self.attributes = rest_spec;
+ Ok(Some(attr))
+ }
+ Err(e) => {
+ self.input.empty();
+ Err(e)
+ }
+ }
+ }
+}
+
+#[cfg(feature = "fallible-iterator")]
+impl<'abbrev, 'entry, 'unit, R: Reader> fallible_iterator::FallibleIterator
+ for AttrsIter<'abbrev, 'entry, 'unit, R>
+{
+ type Item = Attribute<R>;
+ type Error = Error;
+
+ fn next(&mut self) -> ::core::result::Result<Option<Self::Item>, Self::Error> {
+ AttrsIter::next(self)
+ }
+}
+
+/// A raw reader of the data that defines the Debugging Information Entries.
+///
+/// `EntriesRaw` provides primitives to read the components of Debugging Information
+/// Entries (DIEs). A DIE consists of an abbreviation code (read with `read_abbreviation`)
+/// followed by a number of attributes (read with `read_attribute`).
+/// The user must provide the control flow to read these correctly.
+/// In particular, all attributes must always be read before reading another
+/// abbreviation code.
+///
+/// `EntriesRaw` lacks some features of `EntriesCursor`, such as the ability to skip
+/// to the next sibling DIE. However, this also allows it to optimize better, since it
+/// does not need to perform the extra bookkeeping required to support these features,
+/// and thus it is suitable for cases where performance is important.
+///
+/// ## Example Usage
+/// ```rust,no_run
+/// # fn example() -> Result<(), gimli::Error> {
+/// # let debug_info = gimli::DebugInfo::new(&[], gimli::LittleEndian);
+/// # let get_some_unit = || debug_info.units().next().unwrap().unwrap();
+/// let unit = get_some_unit();
+/// # let debug_abbrev = gimli::DebugAbbrev::new(&[], gimli::LittleEndian);
+/// # let get_abbrevs_for_unit = |_| unit.abbreviations(&debug_abbrev).unwrap();
+/// let abbrevs = get_abbrevs_for_unit(&unit);
+///
+/// let mut entries = unit.entries_raw(&abbrevs, None)?;
+/// while !entries.is_empty() {
+/// let abbrev = if let Some(abbrev) = entries.read_abbreviation()? {
+/// abbrev
+/// } else {
+/// // Null entry with no attributes.
+/// continue
+/// };
+/// match abbrev.tag() {
+/// gimli::DW_TAG_subprogram => {
+/// // Loop over attributes for DIEs we care about.
+/// for spec in abbrev.attributes() {
+/// let attr = entries.read_attribute(*spec)?;
+/// match attr.name() {
+/// // Handle attributes.
+/// _ => {}
+/// }
+/// }
+/// }
+/// _ => {
+/// // Skip attributes for DIEs we don't care about.
+/// entries.skip_attributes(abbrev.attributes());
+/// }
+/// }
+/// }
+/// # unreachable!()
+/// # }
+/// ```
+#[derive(Clone, Debug)]
+pub struct EntriesRaw<'abbrev, 'unit, R>
+where
+ R: Reader,
+{
+ input: R,
+ unit: &'unit UnitHeader<R>,
+ abbreviations: &'abbrev Abbreviations,
+ depth: isize,
+}
+
+impl<'abbrev, 'unit, R: Reader> EntriesRaw<'abbrev, 'unit, R> {
+ /// Return true if there is no more input.
+ #[inline]
+ pub fn is_empty(&self) -> bool {
+ self.input.is_empty()
+ }
+
+ /// Return the unit offset at which the reader will read next.
+ ///
+ /// If you want the offset of the next entry, then this must be called prior to reading
+ /// the next entry.
+ pub fn next_offset(&self) -> UnitOffset<R::Offset> {
+ UnitOffset(self.unit.header_size() + self.input.offset_from(&self.unit.entries_buf))
+ }
+
+ /// Return the depth of the next entry.
+ ///
+ /// This depth is updated when `read_abbreviation` is called, and is updated
+ /// based on null entries and the `has_children` field in the abbreviation.
+ #[inline]
+ pub fn next_depth(&self) -> isize {
+ self.depth
+ }
+
+ /// Read an abbreviation code and lookup the corresponding `Abbreviation`.
+ ///
+ /// Returns `Ok(None)` for null entries.
+ #[inline]
+ pub fn read_abbreviation(&mut self) -> Result<Option<&'abbrev Abbreviation>> {
+ let code = self.input.read_uleb128()?;
+ if code == 0 {
+ self.depth -= 1;
+ return Ok(None);
+ };
+ let abbrev = self
+ .abbreviations
+ .get(code)
+ .ok_or(Error::UnknownAbbreviation)?;
+ if abbrev.has_children() {
+ self.depth += 1;
+ }
+ Ok(Some(abbrev))
+ }
+
+ /// Read an attribute.
+ #[inline]
+ pub fn read_attribute(&mut self, spec: AttributeSpecification) -> Result<Attribute<R>> {
+ parse_attribute(&mut self.input, self.unit.encoding(), spec)
+ }
+
+ /// Skip all the attributes of an abbreviation.
+ #[inline]
+ pub fn skip_attributes(&mut self, specs: &[AttributeSpecification]) -> Result<()> {
+ skip_attributes(&mut self.input, self.unit.encoding(), specs)
+ }
+}
+
+/// A cursor into the Debugging Information Entries tree for a compilation unit.
+///
+/// The `EntriesCursor` can traverse the DIE tree in DFS order using `next_dfs()`,
+/// or skip to the next sibling of the entry the cursor is currently pointing to
+/// using `next_sibling()`.
+///
+/// It is also possible to traverse the DIE tree at a lower abstraction level
+/// using `next_entry()`. This method does not skip over null entries, or provide
+/// any indication of the current tree depth. In this case, you must use `current()`
+/// to obtain the current entry, and `current().has_children()` to determine if
+/// the entry following the current entry will be a sibling or child. `current()`
+/// will return `None` if the current entry is a null entry, which signifies the
+/// end of the current tree depth.
+#[derive(Clone, Debug)]
+pub struct EntriesCursor<'abbrev, 'unit, R>
+where
+ R: Reader,
+{
+ input: R,
+ unit: &'unit UnitHeader<R>,
+ abbreviations: &'abbrev Abbreviations,
+ cached_current: Option<DebuggingInformationEntry<'abbrev, 'unit, R>>,
+ delta_depth: isize,
+}
+
+impl<'abbrev, 'unit, R: Reader> EntriesCursor<'abbrev, 'unit, R> {
+ /// Get a reference to the entry that the cursor is currently pointing to.
+ ///
+ /// If the cursor is not pointing at an entry, or if the current entry is a
+ /// null entry, then `None` is returned.
+ #[inline]
+ pub fn current(&self) -> Option<&DebuggingInformationEntry<'abbrev, 'unit, R>> {
+ self.cached_current.as_ref()
+ }
+
+ /// Move the cursor to the next DIE in the tree.
+ ///
+ /// Returns `Some` if there is a next entry, even if this entry is null.
+ /// If there is no next entry, then `None` is returned.
+ pub fn next_entry(&mut self) -> Result<Option<()>> {
+ if let Some(ref current) = self.cached_current {
+ self.input = current.after_attrs()?;
+ }
+
+ if self.input.is_empty() {
+ self.cached_current = None;
+ self.delta_depth = 0;
+ return Ok(None);
+ }
+
+ match DebuggingInformationEntry::parse(&mut self.input, self.unit, self.abbreviations) {
+ Ok(Some(entry)) => {
+ self.delta_depth = entry.has_children() as isize;
+ self.cached_current = Some(entry);
+ Ok(Some(()))
+ }
+ Ok(None) => {
+ self.delta_depth = -1;
+ self.cached_current = None;
+ Ok(Some(()))
+ }
+ Err(e) => {
+ self.input.empty();
+ self.delta_depth = 0;
+ self.cached_current = None;
+ Err(e)
+ }
+ }
+ }
+
+ /// Move the cursor to the next DIE in the tree in DFS order.
+ ///
+ /// Upon successful movement of the cursor, return the delta traversal
+ /// depth and the entry:
+ ///
+ /// * If we moved down into the previous current entry's children, we get
+ /// `Some((1, entry))`.
+ ///
+ /// * If we moved to the previous current entry's sibling, we get
+ /// `Some((0, entry))`.
+ ///
+ /// * If the previous entry does not have any siblings and we move up to
+ /// its parent's next sibling, then we get `Some((-1, entry))`. Note that
+ /// if the parent doesn't have a next sibling, then it could go up to the
+ /// parent's parent's next sibling and return `Some((-2, entry))`, etc.
+ ///
+ /// If there is no next entry, then `None` is returned.
+ ///
+ /// Here is an example that finds the first entry in a compilation unit that
+ /// does not have any children.
+ ///
+ /// ```
+ /// # use gimli::{DebugAbbrev, DebugInfo, LittleEndian};
+ /// # let info_buf = [
+ /// # // Comilation unit header
+ /// #
+ /// # // 32-bit unit length = 25
+ /// # 0x19, 0x00, 0x00, 0x00,
+ /// # // Version 4
+ /// # 0x04, 0x00,
+ /// # // debug_abbrev_offset
+ /// # 0x00, 0x00, 0x00, 0x00,
+ /// # // Address size
+ /// # 0x04,
+ /// #
+ /// # // DIEs
+ /// #
+ /// # // Abbreviation code
+ /// # 0x01,
+ /// # // Attribute of form DW_FORM_string = "foo\0"
+ /// # 0x66, 0x6f, 0x6f, 0x00,
+ /// #
+ /// # // Children
+ /// #
+ /// # // Abbreviation code
+ /// # 0x01,
+ /// # // Attribute of form DW_FORM_string = "foo\0"
+ /// # 0x66, 0x6f, 0x6f, 0x00,
+ /// #
+ /// # // Children
+ /// #
+ /// # // Abbreviation code
+ /// # 0x01,
+ /// # // Attribute of form DW_FORM_string = "foo\0"
+ /// # 0x66, 0x6f, 0x6f, 0x00,
+ /// #
+ /// # // Children
+ /// #
+ /// # // End of children
+ /// # 0x00,
+ /// #
+ /// # // End of children
+ /// # 0x00,
+ /// #
+ /// # // End of children
+ /// # 0x00,
+ /// # ];
+ /// # let debug_info = DebugInfo::new(&info_buf, LittleEndian);
+ /// #
+ /// # let abbrev_buf = [
+ /// # // Code
+ /// # 0x01,
+ /// # // DW_TAG_subprogram
+ /// # 0x2e,
+ /// # // DW_CHILDREN_yes
+ /// # 0x01,
+ /// # // Begin attributes
+ /// # // Attribute name = DW_AT_name
+ /// # 0x03,
+ /// # // Attribute form = DW_FORM_string
+ /// # 0x08,
+ /// # // End attributes
+ /// # 0x00,
+ /// # 0x00,
+ /// # // Null terminator
+ /// # 0x00
+ /// # ];
+ /// # let debug_abbrev = DebugAbbrev::new(&abbrev_buf, LittleEndian);
+ /// #
+ /// # let get_some_unit = || debug_info.units().next().unwrap().unwrap();
+ ///
+ /// let unit = get_some_unit();
+ /// # let get_abbrevs_for_unit = |_| unit.abbreviations(&debug_abbrev).unwrap();
+ /// let abbrevs = get_abbrevs_for_unit(&unit);
+ ///
+ /// let mut first_entry_with_no_children = None;
+ /// let mut cursor = unit.entries(&abbrevs);
+ ///
+ /// // Move the cursor to the root.
+ /// assert!(cursor.next_dfs().unwrap().is_some());
+ ///
+ /// // Traverse the DIE tree in depth-first search order.
+ /// let mut depth = 0;
+ /// while let Some((delta_depth, current)) = cursor.next_dfs().expect("Should parse next dfs") {
+ /// // Update depth value, and break out of the loop when we
+ /// // return to the original starting position.
+ /// depth += delta_depth;
+ /// if depth <= 0 {
+ /// break;
+ /// }
+ ///
+ /// first_entry_with_no_children = Some(current.clone());
+ /// }
+ ///
+ /// println!("The first entry with no children is {:?}",
+ /// first_entry_with_no_children.unwrap());
+ /// ```
+ #[allow(clippy::type_complexity)]
+ pub fn next_dfs(
+ &mut self,
+ ) -> Result<Option<(isize, &DebuggingInformationEntry<'abbrev, 'unit, R>)>> {
+ let mut delta_depth = self.delta_depth;
+ loop {
+ // The next entry should be the one we want.
+ if self.next_entry()?.is_some() {
+ if let Some(ref entry) = self.cached_current {
+ return Ok(Some((delta_depth, entry)));
+ }
+
+ // next_entry() read a null entry.
+ delta_depth += self.delta_depth;
+ } else {
+ return Ok(None);
+ }
+ }
+ }
+
+ /// Move the cursor to the next sibling DIE of the current one.
+ ///
+ /// Returns `Ok(Some(entry))` when the cursor has been moved to
+ /// the next sibling, `Ok(None)` when there is no next sibling.
+ ///
+ /// The depth of the cursor is never changed if this method returns `Ok`.
+ /// Once `Ok(None)` is returned, this method will continue to return
+ /// `Ok(None)` until either `next_entry` or `next_dfs` is called.
+ ///
+ /// Here is an example that iterates over all of the direct children of the
+ /// root entry:
+ ///
+ /// ```
+ /// # use gimli::{DebugAbbrev, DebugInfo, LittleEndian};
+ /// # let info_buf = [
+ /// # // Comilation unit header
+ /// #
+ /// # // 32-bit unit length = 25
+ /// # 0x19, 0x00, 0x00, 0x00,
+ /// # // Version 4
+ /// # 0x04, 0x00,
+ /// # // debug_abbrev_offset
+ /// # 0x00, 0x00, 0x00, 0x00,
+ /// # // Address size
+ /// # 0x04,
+ /// #
+ /// # // DIEs
+ /// #
+ /// # // Abbreviation code
+ /// # 0x01,
+ /// # // Attribute of form DW_FORM_string = "foo\0"
+ /// # 0x66, 0x6f, 0x6f, 0x00,
+ /// #
+ /// # // Children
+ /// #
+ /// # // Abbreviation code
+ /// # 0x01,
+ /// # // Attribute of form DW_FORM_string = "foo\0"
+ /// # 0x66, 0x6f, 0x6f, 0x00,
+ /// #
+ /// # // Children
+ /// #
+ /// # // Abbreviation code
+ /// # 0x01,
+ /// # // Attribute of form DW_FORM_string = "foo\0"
+ /// # 0x66, 0x6f, 0x6f, 0x00,
+ /// #
+ /// # // Children
+ /// #
+ /// # // End of children
+ /// # 0x00,
+ /// #
+ /// # // End of children
+ /// # 0x00,
+ /// #
+ /// # // End of children
+ /// # 0x00,
+ /// # ];
+ /// # let debug_info = DebugInfo::new(&info_buf, LittleEndian);
+ /// #
+ /// # let get_some_unit = || debug_info.units().next().unwrap().unwrap();
+ ///
+ /// # let abbrev_buf = [
+ /// # // Code
+ /// # 0x01,
+ /// # // DW_TAG_subprogram
+ /// # 0x2e,
+ /// # // DW_CHILDREN_yes
+ /// # 0x01,
+ /// # // Begin attributes
+ /// # // Attribute name = DW_AT_name
+ /// # 0x03,
+ /// # // Attribute form = DW_FORM_string
+ /// # 0x08,
+ /// # // End attributes
+ /// # 0x00,
+ /// # 0x00,
+ /// # // Null terminator
+ /// # 0x00
+ /// # ];
+ /// # let debug_abbrev = DebugAbbrev::new(&abbrev_buf, LittleEndian);
+ /// #
+ /// let unit = get_some_unit();
+ /// # let get_abbrevs_for_unit = |_| unit.abbreviations(&debug_abbrev).unwrap();
+ /// let abbrevs = get_abbrevs_for_unit(&unit);
+ ///
+ /// let mut cursor = unit.entries(&abbrevs);
+ ///
+ /// // Move the cursor to the root.
+ /// assert!(cursor.next_dfs().unwrap().is_some());
+ ///
+ /// // Move the cursor to the root's first child.
+ /// assert!(cursor.next_dfs().unwrap().is_some());
+ ///
+ /// // Iterate the root's children.
+ /// loop {
+ /// {
+ /// let current = cursor.current().expect("Should be at an entry");
+ /// println!("{:?} is a child of the root", current);
+ /// }
+ ///
+ /// if cursor.next_sibling().expect("Should parse next sibling").is_none() {
+ /// break;
+ /// }
+ /// }
+ /// ```
+ pub fn next_sibling(
+ &mut self,
+ ) -> Result<Option<&DebuggingInformationEntry<'abbrev, 'unit, R>>> {
+ if self.current().is_none() {
+ // We're already at the null for the end of the sibling list.
+ return Ok(None);
+ }
+
+ // Loop until we find an entry at the current level.
+ let mut depth = 0;
+ loop {
+ // Use is_some() and unwrap() to keep borrow checker happy.
+ if self.current().is_some() && self.current().unwrap().has_children() {
+ if let Some(sibling_input) = self.current().unwrap().sibling() {
+ // Fast path: this entry has a DW_AT_sibling
+ // attribute pointing to its sibling, so jump
+ // to it (which keeps us at the same depth).
+ self.input = sibling_input;
+ self.cached_current = None;
+ } else {
+ // This entry has children, so the next entry is
+ // down one level.
+ depth += 1;
+ }
+ }
+
+ if self.next_entry()?.is_none() {
+ // End of input.
+ return Ok(None);
+ }
+
+ if depth == 0 {
+ // Found an entry at the current level.
+ return Ok(self.current());
+ }
+
+ if self.current().is_none() {
+ // A null entry means the end of a child list, so we're
+ // back up a level.
+ depth -= 1;
+ }
+ }
+ }
+}
+
+/// The state information for a tree view of the Debugging Information Entries.
+///
+/// The `EntriesTree` can be used to recursively iterate through the DIE
+/// tree, following the parent/child relationships. The `EntriesTree` contains
+/// shared state for all nodes in the tree, avoiding any duplicate parsing of
+/// entries during the traversal.
+///
+/// ## Example Usage
+/// ```rust,no_run
+/// # fn example() -> Result<(), gimli::Error> {
+/// # let debug_info = gimli::DebugInfo::new(&[], gimli::LittleEndian);
+/// # let get_some_unit = || debug_info.units().next().unwrap().unwrap();
+/// let unit = get_some_unit();
+/// # let debug_abbrev = gimli::DebugAbbrev::new(&[], gimli::LittleEndian);
+/// # let get_abbrevs_for_unit = |_| unit.abbreviations(&debug_abbrev).unwrap();
+/// let abbrevs = get_abbrevs_for_unit(&unit);
+///
+/// let mut tree = unit.entries_tree(&abbrevs, None)?;
+/// let root = tree.root()?;
+/// process_tree(root)?;
+/// # unreachable!()
+/// # }
+///
+/// fn process_tree<R>(mut node: gimli::EntriesTreeNode<R>) -> gimli::Result<()>
+/// where R: gimli::Reader
+/// {
+/// {
+/// // Examine the entry attributes.
+/// let mut attrs = node.entry().attrs();
+/// while let Some(attr) = attrs.next()? {
+/// }
+/// }
+/// let mut children = node.children();
+/// while let Some(child) = children.next()? {
+/// // Recursively process a child.
+/// process_tree(child);
+/// }
+/// Ok(())
+/// }
+/// ```
+#[derive(Clone, Debug)]
+pub struct EntriesTree<'abbrev, 'unit, R>
+where
+ R: Reader,
+{
+ root: R,
+ unit: &'unit UnitHeader<R>,
+ abbreviations: &'abbrev Abbreviations,
+ input: R,
+ entry: Option<DebuggingInformationEntry<'abbrev, 'unit, R>>,
+ depth: isize,
+}
+
+impl<'abbrev, 'unit, R: Reader> EntriesTree<'abbrev, 'unit, R> {
+ fn new(root: R, unit: &'unit UnitHeader<R>, abbreviations: &'abbrev Abbreviations) -> Self {
+ let input = root.clone();
+ EntriesTree {
+ root,
+ unit,
+ abbreviations,
+ input,
+ entry: None,
+ depth: 0,
+ }
+ }
+
+ /// Returns the root node of the tree.
+ pub fn root<'me>(&'me mut self) -> Result<EntriesTreeNode<'abbrev, 'unit, 'me, R>> {
+ self.input = self.root.clone();
+ self.entry =
+ DebuggingInformationEntry::parse(&mut self.input, self.unit, self.abbreviations)?;
+ if self.entry.is_none() {
+ return Err(Error::UnexpectedNull);
+ }
+ self.depth = 0;
+ Ok(EntriesTreeNode::new(self, 1))
+ }
+
+ /// Move the cursor to the next entry at the specified depth.
+ ///
+ /// Requires `depth <= self.depth + 1`.
+ ///
+ /// Returns `true` if successful.
+ fn next(&mut self, depth: isize) -> Result<bool> {
+ if self.depth < depth {
+ debug_assert_eq!(self.depth + 1, depth);
+
+ match self.entry {
+ Some(ref entry) => {
+ if !entry.has_children() {
+ return Ok(false);
+ }
+ self.depth += 1;
+ self.input = entry.after_attrs()?;
+ }
+ None => return Ok(false),
+ }
+
+ if self.input.is_empty() {
+ self.entry = None;
+ return Ok(false);
+ }
+
+ return match DebuggingInformationEntry::parse(
+ &mut self.input,
+ self.unit,
+ self.abbreviations,
+ ) {
+ Ok(entry) => {
+ self.entry = entry;
+ Ok(self.entry.is_some())
+ }
+ Err(e) => {
+ self.input.empty();
+ self.entry = None;
+ Err(e)
+ }
+ };
+ }
+
+ loop {
+ match self.entry {
+ Some(ref entry) => {
+ if entry.has_children() {
+ if let Some(sibling_input) = entry.sibling() {
+ // Fast path: this entry has a DW_AT_sibling
+ // attribute pointing to its sibling, so jump
+ // to it (which keeps us at the same depth).
+ self.input = sibling_input;
+ } else {
+ // This entry has children, so the next entry is
+ // down one level.
+ self.depth += 1;
+ self.input = entry.after_attrs()?;
+ }
+ } else {
+ // This entry has no children, so next entry is at same depth.
+ self.input = entry.after_attrs()?;
+ }
+ }
+ None => {
+ // This entry is a null, so next entry is up one level.
+ self.depth -= 1;
+ }
+ }
+
+ if self.input.is_empty() {
+ self.entry = None;
+ return Ok(false);
+ }
+
+ match DebuggingInformationEntry::parse(&mut self.input, self.unit, self.abbreviations) {
+ Ok(entry) => {
+ self.entry = entry;
+ if self.depth == depth {
+ return Ok(self.entry.is_some());
+ }
+ }
+ Err(e) => {
+ self.input.empty();
+ self.entry = None;
+ return Err(e);
+ }
+ }
+ }
+ }
+}
+
+/// A node in the Debugging Information Entry tree.
+///
+/// The root node of a tree can be obtained
+/// via [`EntriesTree::root`](./struct.EntriesTree.html#method.root).
+#[derive(Debug)]
+pub struct EntriesTreeNode<'abbrev, 'unit, 'tree, R: Reader> {
+ tree: &'tree mut EntriesTree<'abbrev, 'unit, R>,
+ depth: isize,
+}
+
+impl<'abbrev, 'unit, 'tree, R: Reader> EntriesTreeNode<'abbrev, 'unit, 'tree, R> {
+ fn new(
+ tree: &'tree mut EntriesTree<'abbrev, 'unit, R>,
+ depth: isize,
+ ) -> EntriesTreeNode<'abbrev, 'unit, 'tree, R> {
+ debug_assert!(tree.entry.is_some());
+ EntriesTreeNode { tree, depth }
+ }
+
+ /// Returns the current entry in the tree.
+ pub fn entry(&self) -> &DebuggingInformationEntry<'abbrev, 'unit, R> {
+ // We never create a node without an entry.
+ self.tree.entry.as_ref().unwrap()
+ }
+
+ /// Create an iterator for the children of the current entry.
+ ///
+ /// The current entry can no longer be accessed after creating the
+ /// iterator.
+ pub fn children(self) -> EntriesTreeIter<'abbrev, 'unit, 'tree, R> {
+ EntriesTreeIter::new(self.tree, self.depth)
+ }
+}
+
+/// An iterator that allows traversal of the children of an
+/// `EntriesTreeNode`.
+///
+/// The items returned by this iterator are also `EntriesTreeNode`s,
+/// which allow recursive traversal of grandchildren, etc.
+#[derive(Debug)]
+pub struct EntriesTreeIter<'abbrev, 'unit, 'tree, R: Reader> {
+ tree: &'tree mut EntriesTree<'abbrev, 'unit, R>,
+ depth: isize,
+ empty: bool,
+}
+
+impl<'abbrev, 'unit, 'tree, R: Reader> EntriesTreeIter<'abbrev, 'unit, 'tree, R> {
+ fn new(
+ tree: &'tree mut EntriesTree<'abbrev, 'unit, R>,
+ depth: isize,
+ ) -> EntriesTreeIter<'abbrev, 'unit, 'tree, R> {
+ EntriesTreeIter {
+ tree,
+ depth,
+ empty: false,
+ }
+ }
+
+ /// Returns an `EntriesTreeNode` for the next child entry.
+ ///
+ /// Returns `None` if there are no more children.
+ pub fn next<'me>(&'me mut self) -> Result<Option<EntriesTreeNode<'abbrev, 'unit, 'me, R>>> {
+ if self.empty {
+ Ok(None)
+ } else if self.tree.next(self.depth)? {
+ Ok(Some(EntriesTreeNode::new(self.tree, self.depth + 1)))
+ } else {
+ self.empty = true;
+ Ok(None)
+ }
+ }
+}
+
+/// Parse a type unit header's unique type signature. Callers should handle
+/// unique-ness checking.
+fn parse_type_signature<R: Reader>(input: &mut R) -> Result<DebugTypeSignature> {
+ input.read_u64().map(DebugTypeSignature)
+}
+
+/// Parse a type unit header's type offset.
+fn parse_type_offset<R: Reader>(input: &mut R, format: Format) -> Result<UnitOffset<R::Offset>> {
+ input.read_offset(format).map(UnitOffset)
+}
+
+/// The `DebugTypes` struct represents the DWARF type information
+/// found in the `.debug_types` section.
+#[derive(Debug, Default, Clone, Copy)]
+pub struct DebugTypes<R> {
+ debug_types_section: R,
+}
+
+impl<'input, Endian> DebugTypes<EndianSlice<'input, Endian>>
+where
+ Endian: Endianity,
+{
+ /// Construct a new `DebugTypes` instance from the data in the `.debug_types`
+ /// section.
+ ///
+ /// It is the caller's responsibility to read the `.debug_types` section and
+ /// present it as a `&[u8]` slice. That means using some ELF loader on
+ /// Linux, a Mach-O loader on macOS, etc.
+ ///
+ /// ```
+ /// use gimli::{DebugTypes, LittleEndian};
+ ///
+ /// # let buf = [0x00, 0x01, 0x02, 0x03];
+ /// # let read_debug_types_section_somehow = || &buf;
+ /// let debug_types = DebugTypes::new(read_debug_types_section_somehow(), LittleEndian);
+ /// ```
+ pub fn new(debug_types_section: &'input [u8], endian: Endian) -> Self {
+ Self::from(EndianSlice::new(debug_types_section, endian))
+ }
+}
+
+impl<T> DebugTypes<T> {
+ /// Create a `DebugTypes` section that references the data in `self`.
+ ///
+ /// This is useful when `R` implements `Reader` but `T` does not.
+ ///
+ /// ## Example Usage
+ ///
+ /// ```rust,no_run
+ /// # let load_section = || unimplemented!();
+ /// // Read the DWARF section into a `Vec` with whatever object loader you're using.
+ /// let owned_section: gimli::DebugTypes<Vec<u8>> = load_section();
+ /// // Create a reference to the DWARF section.
+ /// let section = owned_section.borrow(|section| {
+ /// gimli::EndianSlice::new(&section, gimli::LittleEndian)
+ /// });
+ /// ```
+ pub fn borrow<'a, F, R>(&'a self, mut borrow: F) -> DebugTypes<R>
+ where
+ F: FnMut(&'a T) -> R,
+ {
+ borrow(&self.debug_types_section).into()
+ }
+}
+
+impl<R> Section<R> for DebugTypes<R> {
+ fn id() -> SectionId {
+ SectionId::DebugTypes
+ }
+
+ fn reader(&self) -> &R {
+ &self.debug_types_section
+ }
+}
+
+impl<R> From<R> for DebugTypes<R> {
+ fn from(debug_types_section: R) -> Self {
+ DebugTypes {
+ debug_types_section,
+ }
+ }
+}
+
+impl<R: Reader> DebugTypes<R> {
+ /// Iterate the type-units in this `.debug_types` section.
+ ///
+ /// ```
+ /// use gimli::{DebugTypes, LittleEndian};
+ ///
+ /// # let buf = [];
+ /// # let read_debug_types_section_somehow = || &buf;
+ /// let debug_types = DebugTypes::new(read_debug_types_section_somehow(), LittleEndian);
+ ///
+ /// let mut iter = debug_types.units();
+ /// while let Some(unit) = iter.next().unwrap() {
+ /// println!("unit's length is {}", unit.unit_length());
+ /// }
+ /// ```
+ ///
+ /// Can be [used with
+ /// `FallibleIterator`](./index.html#using-with-fallibleiterator).
+ pub fn units(&self) -> DebugTypesUnitHeadersIter<R> {
+ DebugTypesUnitHeadersIter {
+ input: self.debug_types_section.clone(),
+ offset: DebugTypesOffset(R::Offset::from_u8(0)),
+ }
+ }
+}
+
+/// An iterator over the type-units of this `.debug_types` section.
+///
+/// See the [documentation on
+/// `DebugTypes::units`](./struct.DebugTypes.html#method.units) for
+/// more detail.
+#[derive(Clone, Debug)]
+pub struct DebugTypesUnitHeadersIter<R: Reader> {
+ input: R,
+ offset: DebugTypesOffset<R::Offset>,
+}
+
+impl<R: Reader> DebugTypesUnitHeadersIter<R> {
+ /// Advance the iterator to the next type unit header.
+ pub fn next(&mut self) -> Result<Option<UnitHeader<R>>> {
+ if self.input.is_empty() {
+ Ok(None)
+ } else {
+ let len = self.input.len();
+ match parse_unit_header(&mut self.input, self.offset.into()) {
+ Ok(header) => {
+ self.offset.0 += len - self.input.len();
+ Ok(Some(header))
+ }
+ Err(e) => {
+ self.input.empty();
+ Err(e)
+ }
+ }
+ }
+ }
+}
+
+#[cfg(feature = "fallible-iterator")]
+impl<R: Reader> fallible_iterator::FallibleIterator for DebugTypesUnitHeadersIter<R> {
+ type Item = UnitHeader<R>;
+ type Error = Error;
+
+ fn next(&mut self) -> ::core::result::Result<Option<Self::Item>, Self::Error> {
+ DebugTypesUnitHeadersIter::next(self)
+ }
+}
+
+#[cfg(test)]
+// Tests require leb128::write.
+#[cfg(feature = "write")]
+mod tests {
+ use super::*;
+ use crate::constants;
+ use crate::constants::*;
+ use crate::endianity::{Endianity, LittleEndian};
+ use crate::leb128;
+ use crate::read::abbrev::tests::AbbrevSectionMethods;
+ use crate::read::{
+ Abbreviation, AttributeSpecification, DebugAbbrev, EndianSlice, Error, Result,
+ };
+ use crate::test_util::GimliSectionMethods;
+ use alloc::vec::Vec;
+ use core::cell::Cell;
+ use test_assembler::{Endian, Label, LabelMaker, Section};
+
+ // Mixin methods for `Section` to help define binary test data.
+
+ trait UnitSectionMethods {
+ fn unit<'input, E>(self, unit: &mut UnitHeader<EndianSlice<'input, E>>) -> Self
+ where
+ E: Endianity;
+ fn die<F>(self, code: u64, attr: F) -> Self
+ where
+ F: Fn(Section) -> Section;
+ fn die_null(self) -> Self;
+ fn attr_string(self, s: &str) -> Self;
+ fn attr_ref1(self, o: u8) -> Self;
+ fn offset(self, offset: usize, format: Format) -> Self;
+ }
+
+ impl UnitSectionMethods for Section {
+ fn unit<'input, E>(self, unit: &mut UnitHeader<EndianSlice<'input, E>>) -> Self
+ where
+ E: Endianity,
+ {
+ let size = self.size();
+ let length = Label::new();
+ let start = Label::new();
+ let end = Label::new();
+
+ let section = match unit.format() {
+ Format::Dwarf32 => self.L32(&length),
+ Format::Dwarf64 => self.L32(0xffff_ffff).L64(&length),
+ };
+
+ let section = match unit.version() {
+ 2 | 3 | 4 => section
+ .mark(&start)
+ .L16(unit.version())
+ .offset(unit.debug_abbrev_offset.0, unit.format())
+ .D8(unit.address_size()),
+ 5 => section
+ .mark(&start)
+ .L16(unit.version())
+ .D8(unit.type_().dw_ut().0)
+ .D8(unit.address_size())
+ .offset(unit.debug_abbrev_offset.0, unit.format()),
+ _ => unreachable!(),
+ };
+
+ let section = match unit.type_() {
+ UnitType::Compilation | UnitType::Partial => {
+ unit.unit_offset = DebugInfoOffset(size as usize).into();
+ section
+ }
+ UnitType::Type {
+ type_signature,
+ type_offset,
+ }
+ | UnitType::SplitType {
+ type_signature,
+ type_offset,
+ } => {
+ if unit.version() == 5 {
+ unit.unit_offset = DebugInfoOffset(size as usize).into();
+ } else {
+ unit.unit_offset = DebugTypesOffset(size as usize).into();
+ }
+ section
+ .L64(type_signature.0)
+ .offset(type_offset.0, unit.format())
+ }
+ UnitType::Skeleton(dwo_id) | UnitType::SplitCompilation(dwo_id) => {
+ unit.unit_offset = DebugInfoOffset(size as usize).into();
+ section.L64(dwo_id.0)
+ }
+ };
+
+ let section = section.append_bytes(unit.entries_buf.into()).mark(&end);
+
+ unit.unit_length = (&end - &start) as usize;
+ length.set_const(unit.unit_length as u64);
+
+ section
+ }
+
+ fn die<F>(self, code: u64, attr: F) -> Self
+ where
+ F: Fn(Section) -> Section,
+ {
+ let section = self.uleb(code);
+ attr(section)
+ }
+
+ fn die_null(self) -> Self {
+ self.D8(0)
+ }
+
+ fn attr_string(self, attr: &str) -> Self {
+ self.append_bytes(attr.as_bytes()).D8(0)
+ }
+
+ fn attr_ref1(self, attr: u8) -> Self {
+ self.D8(attr)
+ }
+
+ fn offset(self, offset: usize, format: Format) -> Self {
+ match format {
+ Format::Dwarf32 => self.L32(offset as u32),
+ Format::Dwarf64 => self.L64(offset as u64),
+ }
+ }
+ }
+
+ /// Ensure that `UnitHeader<R>` is covariant wrt R.
+ #[test]
+ fn test_unit_header_variance() {
+ /// This only needs to compile.
+ fn _f<'a: 'b, 'b, E: Endianity>(
+ x: UnitHeader<EndianSlice<'a, E>>,
+ ) -> UnitHeader<EndianSlice<'b, E>> {
+ x
+ }
+ }
+
+ #[test]
+ fn test_parse_debug_abbrev_offset_32() {
+ let section = Section::with_endian(Endian::Little).L32(0x0403_0201);
+ let buf = section.get_contents().unwrap();
+ let buf = &mut EndianSlice::new(&buf, LittleEndian);
+
+ match parse_debug_abbrev_offset(buf, Format::Dwarf32) {
+ Ok(val) => assert_eq!(val, DebugAbbrevOffset(0x0403_0201)),
+ otherwise => panic!("Unexpected result: {:?}", otherwise),
+ };
+ }
+
+ #[test]
+ fn test_parse_debug_abbrev_offset_32_incomplete() {
+ let buf = [0x01, 0x02];
+ let buf = &mut EndianSlice::new(&buf, LittleEndian);
+
+ match parse_debug_abbrev_offset(buf, Format::Dwarf32) {
+ Err(Error::UnexpectedEof(_)) => assert!(true),
+ otherwise => panic!("Unexpected result: {:?}", otherwise),
+ };
+ }
+
+ #[test]
+ #[cfg(target_pointer_width = "64")]
+ fn test_parse_debug_abbrev_offset_64() {
+ let section = Section::with_endian(Endian::Little).L64(0x0807_0605_0403_0201);
+ let buf = section.get_contents().unwrap();
+ let buf = &mut EndianSlice::new(&buf, LittleEndian);
+
+ match parse_debug_abbrev_offset(buf, Format::Dwarf64) {
+ Ok(val) => assert_eq!(val, DebugAbbrevOffset(0x0807_0605_0403_0201)),
+ otherwise => panic!("Unexpected result: {:?}", otherwise),
+ };
+ }
+
+ #[test]
+ fn test_parse_debug_abbrev_offset_64_incomplete() {
+ let buf = [0x01, 0x02];
+ let buf = &mut EndianSlice::new(&buf, LittleEndian);
+
+ match parse_debug_abbrev_offset(buf, Format::Dwarf64) {
+ Err(Error::UnexpectedEof(_)) => assert!(true),
+ otherwise => panic!("Unexpected result: {:?}", otherwise),
+ };
+ }
+
+ #[test]
+ fn test_parse_debug_info_offset_32() {
+ let section = Section::with_endian(Endian::Little).L32(0x0403_0201);
+ let buf = section.get_contents().unwrap();
+ let buf = &mut EndianSlice::new(&buf, LittleEndian);
+
+ match parse_debug_info_offset(buf, Format::Dwarf32) {
+ Ok(val) => assert_eq!(val, DebugInfoOffset(0x0403_0201)),
+ otherwise => panic!("Unexpected result: {:?}", otherwise),
+ };
+ }
+
+ #[test]
+ fn test_parse_debug_info_offset_32_incomplete() {
+ let buf = [0x01, 0x02];
+ let buf = &mut EndianSlice::new(&buf, LittleEndian);
+
+ match parse_debug_info_offset(buf, Format::Dwarf32) {
+ Err(Error::UnexpectedEof(_)) => assert!(true),
+ otherwise => panic!("Unexpected result: {:?}", otherwise),
+ };
+ }
+
+ #[test]
+ #[cfg(target_pointer_width = "64")]
+ fn test_parse_debug_info_offset_64() {
+ let section = Section::with_endian(Endian::Little).L64(0x0807_0605_0403_0201);
+ let buf = section.get_contents().unwrap();
+ let buf = &mut EndianSlice::new(&buf, LittleEndian);
+
+ match parse_debug_info_offset(buf, Format::Dwarf64) {
+ Ok(val) => assert_eq!(val, DebugInfoOffset(0x0807_0605_0403_0201)),
+ otherwise => panic!("Unexpected result: {:?}", otherwise),
+ };
+ }
+
+ #[test]
+ fn test_parse_debug_info_offset_64_incomplete() {
+ let buf = [0x01, 0x02];
+ let buf = &mut EndianSlice::new(&buf, LittleEndian);
+
+ match parse_debug_info_offset(buf, Format::Dwarf64) {
+ Err(Error::UnexpectedEof(_)) => assert!(true),
+ otherwise => panic!("Unexpected result: {:?}", otherwise),
+ };
+ }
+
+ #[test]
+ #[cfg(target_pointer_width = "64")]
+ fn test_units() {
+ let expected_rest = &[1, 2, 3, 4, 5, 6, 7, 8, 9];
+ let mut unit64 = UnitHeader {
+ encoding: Encoding {
+ format: Format::Dwarf64,
+ version: 4,
+ address_size: 8,
+ },
+ unit_length: 0,
+ unit_type: UnitType::Compilation,
+ debug_abbrev_offset: DebugAbbrevOffset(0x0102_0304_0506_0708),
+ unit_offset: DebugInfoOffset(0).into(),
+ entries_buf: EndianSlice::new(expected_rest, LittleEndian),
+ };
+ let mut unit32 = UnitHeader {
+ encoding: Encoding {
+ format: Format::Dwarf32,
+ version: 4,
+ address_size: 4,
+ },
+ unit_length: 0,
+ unit_type: UnitType::Compilation,
+ debug_abbrev_offset: DebugAbbrevOffset(0x0807_0605),
+ unit_offset: DebugInfoOffset(0).into(),
+ entries_buf: EndianSlice::new(expected_rest, LittleEndian),
+ };
+ let section = Section::with_endian(Endian::Little)
+ .unit(&mut unit64)
+ .unit(&mut unit32);
+ let buf = section.get_contents().unwrap();
+
+ let debug_info = DebugInfo::new(&buf, LittleEndian);
+ let mut units = debug_info.units();
+
+ assert_eq!(units.next(), Ok(Some(unit64)));
+ assert_eq!(units.next(), Ok(Some(unit32)));
+ assert_eq!(units.next(), Ok(None));
+ }
+
+ #[test]
+ fn test_unit_version_unknown_version() {
+ let buf = [0x02, 0x00, 0x00, 0x00, 0xab, 0xcd];
+ let rest = &mut EndianSlice::new(&buf, LittleEndian);
+
+ match parse_unit_header(rest, DebugInfoOffset(0).into()) {
+ Err(Error::UnknownVersion(0xcdab)) => assert!(true),
+ otherwise => panic!("Unexpected result: {:?}", otherwise),
+ };
+
+ let buf = [0x02, 0x00, 0x00, 0x00, 0x1, 0x0];
+ let rest = &mut EndianSlice::new(&buf, LittleEndian);
+
+ match parse_unit_header(rest, DebugInfoOffset(0).into()) {
+ Err(Error::UnknownVersion(1)) => assert!(true),
+ otherwise => panic!("Unexpected result: {:?}", otherwise),
+ };
+ }
+
+ #[test]
+ fn test_unit_version_incomplete() {
+ let buf = [0x01, 0x00, 0x00, 0x00, 0x04];
+ let rest = &mut EndianSlice::new(&buf, LittleEndian);
+
+ match parse_unit_header(rest, DebugInfoOffset(0).into()) {
+ Err(Error::UnexpectedEof(_)) => assert!(true),
+ otherwise => panic!("Unexpected result: {:?}", otherwise),
+ };
+ }
+
+ #[test]
+ fn test_parse_unit_header_32_ok() {
+ let expected_rest = &[1, 2, 3, 4, 5, 6, 7, 8, 9];
+ let encoding = Encoding {
+ format: Format::Dwarf32,
+ version: 4,
+ address_size: 4,
+ };
+ let mut expected_unit = UnitHeader {
+ encoding,
+ unit_length: 0,
+ unit_type: UnitType::Compilation,
+ debug_abbrev_offset: DebugAbbrevOffset(0x0807_0605),
+ unit_offset: DebugInfoOffset(0).into(),
+ entries_buf: EndianSlice::new(expected_rest, LittleEndian),
+ };
+ let section = Section::with_endian(Endian::Little)
+ .unit(&mut expected_unit)
+ .append_bytes(expected_rest);
+ let buf = section.get_contents().unwrap();
+ let rest = &mut EndianSlice::new(&buf, LittleEndian);
+
+ assert_eq!(
+ parse_unit_header(rest, DebugInfoOffset(0).into()),
+ Ok(expected_unit)
+ );
+ assert_eq!(*rest, EndianSlice::new(expected_rest, LittleEndian));
+ }
+
+ #[test]
+ #[cfg(target_pointer_width = "64")]
+ fn test_parse_unit_header_64_ok() {
+ let expected_rest = &[1, 2, 3, 4, 5, 6, 7, 8, 9];
+ let encoding = Encoding {
+ format: Format::Dwarf64,
+ version: 4,
+ address_size: 8,
+ };
+ let mut expected_unit = UnitHeader {
+ encoding,
+ unit_length: 0,
+ unit_type: UnitType::Compilation,
+ debug_abbrev_offset: DebugAbbrevOffset(0x0102_0304_0506_0708),
+ unit_offset: DebugInfoOffset(0).into(),
+ entries_buf: EndianSlice::new(expected_rest, LittleEndian),
+ };
+ let section = Section::with_endian(Endian::Little)
+ .unit(&mut expected_unit)
+ .append_bytes(expected_rest);
+ let buf = section.get_contents().unwrap();
+ let rest = &mut EndianSlice::new(&buf, LittleEndian);
+
+ assert_eq!(
+ parse_unit_header(rest, DebugInfoOffset(0).into()),
+ Ok(expected_unit)
+ );
+ assert_eq!(*rest, EndianSlice::new(expected_rest, LittleEndian));
+ }
+
+ #[test]
+ fn test_parse_v5_unit_header_32_ok() {
+ let expected_rest = &[1, 2, 3, 4, 5, 6, 7, 8, 9];
+ let encoding = Encoding {
+ format: Format::Dwarf32,
+ version: 5,
+ address_size: 4,
+ };
+ let mut expected_unit = UnitHeader {
+ encoding,
+ unit_length: 0,
+ unit_type: UnitType::Compilation,
+ debug_abbrev_offset: DebugAbbrevOffset(0x0807_0605),
+ unit_offset: DebugInfoOffset(0).into(),
+ entries_buf: EndianSlice::new(expected_rest, LittleEndian),
+ };
+ let section = Section::with_endian(Endian::Little)
+ .unit(&mut expected_unit)
+ .append_bytes(expected_rest);
+ let buf = section.get_contents().unwrap();
+ let rest = &mut EndianSlice::new(&buf, LittleEndian);
+
+ assert_eq!(
+ parse_unit_header(rest, DebugInfoOffset(0).into()),
+ Ok(expected_unit)
+ );
+ assert_eq!(*rest, EndianSlice::new(expected_rest, LittleEndian));
+ }
+
+ #[test]
+ #[cfg(target_pointer_width = "64")]
+ fn test_parse_v5_unit_header_64_ok() {
+ let expected_rest = &[1, 2, 3, 4, 5, 6, 7, 8, 9];
+ let encoding = Encoding {
+ format: Format::Dwarf64,
+ version: 5,
+ address_size: 8,
+ };
+ let mut expected_unit = UnitHeader {
+ encoding,
+ unit_length: 0,
+ unit_type: UnitType::Compilation,
+ debug_abbrev_offset: DebugAbbrevOffset(0x0102_0304_0506_0708),
+ unit_offset: DebugInfoOffset(0).into(),
+ entries_buf: EndianSlice::new(expected_rest, LittleEndian),
+ };
+ let section = Section::with_endian(Endian::Little)
+ .unit(&mut expected_unit)
+ .append_bytes(expected_rest);
+ let buf = section.get_contents().unwrap();
+ let rest = &mut EndianSlice::new(&buf, LittleEndian);
+
+ assert_eq!(
+ parse_unit_header(rest, DebugInfoOffset(0).into()),
+ Ok(expected_unit)
+ );
+ assert_eq!(*rest, EndianSlice::new(expected_rest, LittleEndian));
+ }
+
+ #[test]
+ fn test_parse_v5_partial_unit_header_32_ok() {
+ let expected_rest = &[1, 2, 3, 4, 5, 6, 7, 8, 9];
+ let encoding = Encoding {
+ format: Format::Dwarf32,
+ version: 5,
+ address_size: 4,
+ };
+ let mut expected_unit = UnitHeader {
+ encoding,
+ unit_length: 0,
+ unit_type: UnitType::Partial,
+ debug_abbrev_offset: DebugAbbrevOffset(0x0807_0605),
+ unit_offset: DebugInfoOffset(0).into(),
+ entries_buf: EndianSlice::new(expected_rest, LittleEndian),
+ };
+ let section = Section::with_endian(Endian::Little)
+ .unit(&mut expected_unit)
+ .append_bytes(expected_rest);
+ let buf = section.get_contents().unwrap();
+ let rest = &mut EndianSlice::new(&buf, LittleEndian);
+
+ assert_eq!(
+ parse_unit_header(rest, DebugInfoOffset(0).into()),
+ Ok(expected_unit)
+ );
+ assert_eq!(*rest, EndianSlice::new(expected_rest, LittleEndian));
+ }
+
+ #[test]
+ #[cfg(target_pointer_width = "64")]
+ fn test_parse_v5_partial_unit_header_64_ok() {
+ let expected_rest = &[1, 2, 3, 4, 5, 6, 7, 8, 9];
+ let encoding = Encoding {
+ format: Format::Dwarf64,
+ version: 5,
+ address_size: 8,
+ };
+ let mut expected_unit = UnitHeader {
+ encoding,
+ unit_length: 0,
+ unit_type: UnitType::Partial,
+ debug_abbrev_offset: DebugAbbrevOffset(0x0102_0304_0506_0708),
+ unit_offset: DebugInfoOffset(0).into(),
+ entries_buf: EndianSlice::new(expected_rest, LittleEndian),
+ };
+ let section = Section::with_endian(Endian::Little)
+ .unit(&mut expected_unit)
+ .append_bytes(expected_rest);
+ let buf = section.get_contents().unwrap();
+ let rest = &mut EndianSlice::new(&buf, LittleEndian);
+
+ assert_eq!(
+ parse_unit_header(rest, DebugInfoOffset(0).into()),
+ Ok(expected_unit)
+ );
+ assert_eq!(*rest, EndianSlice::new(expected_rest, LittleEndian));
+ }
+
+ #[test]
+ fn test_parse_v5_skeleton_unit_header_32_ok() {
+ let expected_rest = &[1, 2, 3, 4, 5, 6, 7, 8, 9];
+ let encoding = Encoding {
+ format: Format::Dwarf32,
+ version: 5,
+ address_size: 4,
+ };
+ let mut expected_unit = UnitHeader {
+ encoding,
+ unit_length: 0,
+ unit_type: UnitType::Skeleton(DwoId(0x0706_5040_0302_1000)),
+ debug_abbrev_offset: DebugAbbrevOffset(0x0807_0605),
+ unit_offset: DebugInfoOffset(0).into(),
+ entries_buf: EndianSlice::new(expected_rest, LittleEndian),
+ };
+ let section = Section::with_endian(Endian::Little)
+ .unit(&mut expected_unit)
+ .append_bytes(expected_rest);
+ let buf = section.get_contents().unwrap();
+ let rest = &mut EndianSlice::new(&buf, LittleEndian);
+
+ assert_eq!(
+ parse_unit_header(rest, DebugInfoOffset(0).into()),
+ Ok(expected_unit)
+ );
+ assert_eq!(*rest, EndianSlice::new(expected_rest, LittleEndian));
+ }
+
+ #[test]
+ #[cfg(target_pointer_width = "64")]
+ fn test_parse_v5_skeleton_unit_header_64_ok() {
+ let expected_rest = &[1, 2, 3, 4, 5, 6, 7, 8, 9];
+ let encoding = Encoding {
+ format: Format::Dwarf64,
+ version: 5,
+ address_size: 8,
+ };
+ let mut expected_unit = UnitHeader {
+ encoding,
+ unit_length: 0,
+ unit_type: UnitType::Skeleton(DwoId(0x0706_5040_0302_1000)),
+ debug_abbrev_offset: DebugAbbrevOffset(0x0102_0304_0506_0708),
+ unit_offset: DebugInfoOffset(0).into(),
+ entries_buf: EndianSlice::new(expected_rest, LittleEndian),
+ };
+ let section = Section::with_endian(Endian::Little)
+ .unit(&mut expected_unit)
+ .append_bytes(expected_rest);
+ let buf = section.get_contents().unwrap();
+ let rest = &mut EndianSlice::new(&buf, LittleEndian);
+
+ assert_eq!(
+ parse_unit_header(rest, DebugInfoOffset(0).into()),
+ Ok(expected_unit)
+ );
+ assert_eq!(*rest, EndianSlice::new(expected_rest, LittleEndian));
+ }
+
+ #[test]
+ fn test_parse_v5_split_compilation_unit_header_32_ok() {
+ let expected_rest = &[1, 2, 3, 4, 5, 6, 7, 8, 9];
+ let encoding = Encoding {
+ format: Format::Dwarf32,
+ version: 5,
+ address_size: 4,
+ };
+ let mut expected_unit = UnitHeader {
+ encoding,
+ unit_length: 0,
+ unit_type: UnitType::SplitCompilation(DwoId(0x0706_5040_0302_1000)),
+ debug_abbrev_offset: DebugAbbrevOffset(0x0807_0605),
+ unit_offset: DebugInfoOffset(0).into(),
+ entries_buf: EndianSlice::new(expected_rest, LittleEndian),
+ };
+ let section = Section::with_endian(Endian::Little)
+ .unit(&mut expected_unit)
+ .append_bytes(expected_rest);
+ let buf = section.get_contents().unwrap();
+ let rest = &mut EndianSlice::new(&buf, LittleEndian);
+
+ assert_eq!(
+ parse_unit_header(rest, DebugInfoOffset(0).into()),
+ Ok(expected_unit)
+ );
+ assert_eq!(*rest, EndianSlice::new(expected_rest, LittleEndian));
+ }
+
+ #[test]
+ #[cfg(target_pointer_width = "64")]
+ fn test_parse_v5_split_compilation_unit_header_64_ok() {
+ let expected_rest = &[1, 2, 3, 4, 5, 6, 7, 8, 9];
+ let encoding = Encoding {
+ format: Format::Dwarf64,
+ version: 5,
+ address_size: 8,
+ };
+ let mut expected_unit = UnitHeader {
+ encoding,
+ unit_length: 0,
+ unit_type: UnitType::SplitCompilation(DwoId(0x0706_5040_0302_1000)),
+ debug_abbrev_offset: DebugAbbrevOffset(0x0102_0304_0506_0708),
+ unit_offset: DebugInfoOffset(0).into(),
+ entries_buf: EndianSlice::new(expected_rest, LittleEndian),
+ };
+ let section = Section::with_endian(Endian::Little)
+ .unit(&mut expected_unit)
+ .append_bytes(expected_rest);
+ let buf = section.get_contents().unwrap();
+ let rest = &mut EndianSlice::new(&buf, LittleEndian);
+
+ assert_eq!(
+ parse_unit_header(rest, DebugInfoOffset(0).into()),
+ Ok(expected_unit)
+ );
+ assert_eq!(*rest, EndianSlice::new(expected_rest, LittleEndian));
+ }
+
+ #[test]
+ fn test_parse_type_offset_32_ok() {
+ let buf = [0x12, 0x34, 0x56, 0x78, 0x00];
+ let rest = &mut EndianSlice::new(&buf, LittleEndian);
+
+ match parse_type_offset(rest, Format::Dwarf32) {
+ Ok(offset) => {
+ assert_eq!(rest.len(), 1);
+ assert_eq!(UnitOffset(0x7856_3412), offset);
+ }
+ otherwise => panic!("Unexpected result: {:?}", otherwise),
+ }
+ }
+
+ #[test]
+ #[cfg(target_pointer_width = "64")]
+ fn test_parse_type_offset_64_ok() {
+ let buf = [0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xff, 0x00];
+ let rest = &mut EndianSlice::new(&buf, LittleEndian);
+
+ match parse_type_offset(rest, Format::Dwarf64) {
+ Ok(offset) => {
+ assert_eq!(rest.len(), 1);
+ assert_eq!(UnitOffset(0xffde_bc9a_7856_3412), offset);
+ }
+ otherwise => panic!("Unexpected result: {:?}", otherwise),
+ }
+ }
+
+ #[test]
+ fn test_parse_type_offset_incomplete() {
+ // Need at least 4 bytes.
+ let buf = [0xff, 0xff, 0xff];
+ let rest = &mut EndianSlice::new(&buf, LittleEndian);
+
+ match parse_type_offset(rest, Format::Dwarf32) {
+ Err(Error::UnexpectedEof(_)) => assert!(true),
+ otherwise => panic!("Unexpected result: {:?}", otherwise),
+ };
+ }
+
+ #[test]
+ fn test_parse_type_unit_header_32_ok() {
+ let expected_rest = &[1, 2, 3, 4, 5, 6, 7, 8, 9];
+ let encoding = Encoding {
+ format: Format::Dwarf32,
+ version: 4,
+ address_size: 8,
+ };
+ let mut expected_unit = UnitHeader {
+ encoding,
+ unit_length: 0,
+ unit_type: UnitType::Type {
+ type_signature: DebugTypeSignature(0xdead_beef_dead_beef),
+ type_offset: UnitOffset(0x7856_3412),
+ },
+ debug_abbrev_offset: DebugAbbrevOffset(0x0807_0605),
+ unit_offset: DebugTypesOffset(0).into(),
+ entries_buf: EndianSlice::new(expected_rest, LittleEndian),
+ };
+ let section = Section::with_endian(Endian::Little)
+ .unit(&mut expected_unit)
+ .append_bytes(expected_rest);
+ let buf = section.get_contents().unwrap();
+ let rest = &mut EndianSlice::new(&buf, LittleEndian);
+
+ assert_eq!(
+ parse_unit_header(rest, DebugTypesOffset(0).into()),
+ Ok(expected_unit)
+ );
+ assert_eq!(*rest, EndianSlice::new(expected_rest, LittleEndian));
+ }
+
+ #[test]
+ #[cfg(target_pointer_width = "64")]
+ fn test_parse_type_unit_header_64_ok() {
+ let expected_rest = &[1, 2, 3, 4, 5, 6, 7, 8, 9];
+ let encoding = Encoding {
+ format: Format::Dwarf64,
+ version: 4,
+ address_size: 8,
+ };
+ let mut expected_unit = UnitHeader {
+ encoding,
+ unit_length: 0,
+ unit_type: UnitType::Type {
+ type_signature: DebugTypeSignature(0xdead_beef_dead_beef),
+ type_offset: UnitOffset(0x7856_3412_7856_3412),
+ },
+ debug_abbrev_offset: DebugAbbrevOffset(0x0807_0605),
+ unit_offset: DebugTypesOffset(0).into(),
+ entries_buf: EndianSlice::new(expected_rest, LittleEndian),
+ };
+ let section = Section::with_endian(Endian::Little)
+ .unit(&mut expected_unit)
+ .append_bytes(expected_rest);
+ let buf = section.get_contents().unwrap();
+ let rest = &mut EndianSlice::new(&buf, LittleEndian);
+
+ assert_eq!(
+ parse_unit_header(rest, DebugTypesOffset(0).into()),
+ Ok(expected_unit)
+ );
+ assert_eq!(*rest, EndianSlice::new(expected_rest, LittleEndian));
+ }
+
+ #[test]
+ fn test_parse_v5_type_unit_header_32_ok() {
+ let expected_rest = &[1, 2, 3, 4, 5, 6, 7, 8, 9];
+ let encoding = Encoding {
+ format: Format::Dwarf32,
+ version: 5,
+ address_size: 8,
+ };
+ let mut expected_unit = UnitHeader {
+ encoding,
+ unit_length: 0,
+ unit_type: UnitType::Type {
+ type_signature: DebugTypeSignature(0xdead_beef_dead_beef),
+ type_offset: UnitOffset(0x7856_3412),
+ },
+ debug_abbrev_offset: DebugAbbrevOffset(0x0807_0605),
+ unit_offset: DebugInfoOffset(0).into(),
+ entries_buf: EndianSlice::new(expected_rest, LittleEndian),
+ };
+ let section = Section::with_endian(Endian::Little)
+ .unit(&mut expected_unit)
+ .append_bytes(expected_rest);
+ let buf = section.get_contents().unwrap();
+ let rest = &mut EndianSlice::new(&buf, LittleEndian);
+
+ assert_eq!(
+ parse_unit_header(rest, DebugInfoOffset(0).into()),
+ Ok(expected_unit)
+ );
+ assert_eq!(*rest, EndianSlice::new(expected_rest, LittleEndian));
+ }
+
+ #[test]
+ #[cfg(target_pointer_width = "64")]
+ fn test_parse_v5_type_unit_header_64_ok() {
+ let expected_rest = &[1, 2, 3, 4, 5, 6, 7, 8, 9];
+ let encoding = Encoding {
+ format: Format::Dwarf64,
+ version: 5,
+ address_size: 8,
+ };
+ let mut expected_unit = UnitHeader {
+ encoding,
+ unit_length: 0,
+ unit_type: UnitType::Type {
+ type_signature: DebugTypeSignature(0xdead_beef_dead_beef),
+ type_offset: UnitOffset(0x7856_3412_7856_3412),
+ },
+ debug_abbrev_offset: DebugAbbrevOffset(0x0807_0605),
+ unit_offset: DebugInfoOffset(0).into(),
+ entries_buf: EndianSlice::new(expected_rest, LittleEndian),
+ };
+ let section = Section::with_endian(Endian::Little)
+ .unit(&mut expected_unit)
+ .append_bytes(expected_rest);
+ let buf = section.get_contents().unwrap();
+ let rest = &mut EndianSlice::new(&buf, LittleEndian);
+
+ assert_eq!(
+ parse_unit_header(rest, DebugInfoOffset(0).into()),
+ Ok(expected_unit)
+ );
+ assert_eq!(*rest, EndianSlice::new(expected_rest, LittleEndian));
+ }
+
+ #[test]
+ fn test_parse_v5_split_type_unit_header_32_ok() {
+ let expected_rest = &[1, 2, 3, 4, 5, 6, 7, 8, 9];
+ let encoding = Encoding {
+ format: Format::Dwarf32,
+ version: 5,
+ address_size: 8,
+ };
+ let mut expected_unit = UnitHeader {
+ encoding,
+ unit_length: 0,
+ unit_type: UnitType::SplitType {
+ type_signature: DebugTypeSignature(0xdead_beef_dead_beef),
+ type_offset: UnitOffset(0x7856_3412),
+ },
+ debug_abbrev_offset: DebugAbbrevOffset(0x0807_0605),
+ unit_offset: DebugInfoOffset(0).into(),
+ entries_buf: EndianSlice::new(expected_rest, LittleEndian),
+ };
+ let section = Section::with_endian(Endian::Little)
+ .unit(&mut expected_unit)
+ .append_bytes(expected_rest);
+ let buf = section.get_contents().unwrap();
+ let rest = &mut EndianSlice::new(&buf, LittleEndian);
+
+ assert_eq!(
+ parse_unit_header(rest, DebugInfoOffset(0).into()),
+ Ok(expected_unit)
+ );
+ assert_eq!(*rest, EndianSlice::new(expected_rest, LittleEndian));
+ }
+
+ #[test]
+ #[cfg(target_pointer_width = "64")]
+ fn test_parse_v5_split_type_unit_header_64_ok() {
+ let expected_rest = &[1, 2, 3, 4, 5, 6, 7, 8, 9];
+ let encoding = Encoding {
+ format: Format::Dwarf64,
+ version: 5,
+ address_size: 8,
+ };
+ let mut expected_unit = UnitHeader {
+ encoding,
+ unit_length: 0,
+ unit_type: UnitType::SplitType {
+ type_signature: DebugTypeSignature(0xdead_beef_dead_beef),
+ type_offset: UnitOffset(0x7856_3412_7856_3412),
+ },
+ debug_abbrev_offset: DebugAbbrevOffset(0x0807_0605),
+ unit_offset: DebugInfoOffset(0).into(),
+ entries_buf: EndianSlice::new(expected_rest, LittleEndian),
+ };
+ let section = Section::with_endian(Endian::Little)
+ .unit(&mut expected_unit)
+ .append_bytes(expected_rest);
+ let buf = section.get_contents().unwrap();
+ let rest = &mut EndianSlice::new(&buf, LittleEndian);
+
+ assert_eq!(
+ parse_unit_header(rest, DebugInfoOffset(0).into()),
+ Ok(expected_unit)
+ );
+ assert_eq!(*rest, EndianSlice::new(expected_rest, LittleEndian));
+ }
+
+ fn section_contents<F>(f: F) -> Vec<u8>
+ where
+ F: Fn(Section) -> Section,
+ {
+ f(Section::with_endian(Endian::Little))
+ .get_contents()
+ .unwrap()
+ }
+
+ #[test]
+ fn test_attribute_value() {
+ let mut unit = test_parse_attribute_unit_default();
+ let endian = unit.entries_buf.endian();
+
+ let block_data = &[1, 2, 3, 4];
+ let buf = section_contents(|s| s.uleb(block_data.len() as u64).append_bytes(block_data));
+ let block = EndianSlice::new(&buf, endian);
+
+ let buf = section_contents(|s| s.L32(0x0102_0304));
+ let data4 = EndianSlice::new(&buf, endian);
+
+ let buf = section_contents(|s| s.L64(0x0102_0304_0506_0708));
+ let data8 = EndianSlice::new(&buf, endian);
+
+ let tests = [
+ (
+ Format::Dwarf32,
+ 2,
+ constants::DW_AT_data_member_location,
+ constants::DW_FORM_block,
+ block,
+ AttributeValue::Block(EndianSlice::new(block_data, endian)),
+ AttributeValue::Exprloc(Expression(EndianSlice::new(block_data, endian))),
+ ),
+ (
+ Format::Dwarf32,
+ 2,
+ constants::DW_AT_data_member_location,
+ constants::DW_FORM_data4,
+ data4,
+ AttributeValue::SecOffset(0x0102_0304),
+ AttributeValue::LocationListsRef(LocationListsOffset(0x0102_0304)),
+ ),
+ (
+ Format::Dwarf64,
+ 2,
+ constants::DW_AT_data_member_location,
+ constants::DW_FORM_data4,
+ data4,
+ AttributeValue::Data4(0x0102_0304),
+ AttributeValue::Udata(0x0102_0304),
+ ),
+ (
+ Format::Dwarf32,
+ 4,
+ constants::DW_AT_data_member_location,
+ constants::DW_FORM_data4,
+ data4,
+ AttributeValue::Data4(0x0102_0304),
+ AttributeValue::Udata(0x0102_0304),
+ ),
+ (
+ Format::Dwarf32,
+ 2,
+ constants::DW_AT_data_member_location,
+ constants::DW_FORM_data8,
+ data8,
+ AttributeValue::Data8(0x0102_0304_0506_0708),
+ AttributeValue::Udata(0x0102_0304_0506_0708),
+ ),
+ #[cfg(target_pointer_width = "64")]
+ (
+ Format::Dwarf64,
+ 2,
+ constants::DW_AT_data_member_location,
+ constants::DW_FORM_data8,
+ data8,
+ AttributeValue::SecOffset(0x0102_0304_0506_0708),
+ AttributeValue::LocationListsRef(LocationListsOffset(0x0102_0304_0506_0708)),
+ ),
+ (
+ Format::Dwarf64,
+ 4,
+ constants::DW_AT_data_member_location,
+ constants::DW_FORM_data8,
+ data8,
+ AttributeValue::Data8(0x0102_0304_0506_0708),
+ AttributeValue::Udata(0x0102_0304_0506_0708),
+ ),
+ (
+ Format::Dwarf32,
+ 4,
+ constants::DW_AT_location,
+ constants::DW_FORM_data4,
+ data4,
+ AttributeValue::SecOffset(0x0102_0304),
+ AttributeValue::LocationListsRef(LocationListsOffset(0x0102_0304)),
+ ),
+ #[cfg(target_pointer_width = "64")]
+ (
+ Format::Dwarf64,
+ 4,
+ constants::DW_AT_location,
+ constants::DW_FORM_data8,
+ data8,
+ AttributeValue::SecOffset(0x0102_0304_0506_0708),
+ AttributeValue::LocationListsRef(LocationListsOffset(0x0102_0304_0506_0708)),
+ ),
+ (
+ Format::Dwarf32,
+ 4,
+ constants::DW_AT_str_offsets_base,
+ constants::DW_FORM_sec_offset,
+ data4,
+ AttributeValue::SecOffset(0x0102_0304),
+ AttributeValue::DebugStrOffsetsBase(DebugStrOffsetsBase(0x0102_0304)),
+ ),
+ (
+ Format::Dwarf32,
+ 4,
+ constants::DW_AT_stmt_list,
+ constants::DW_FORM_sec_offset,
+ data4,
+ AttributeValue::SecOffset(0x0102_0304),
+ AttributeValue::DebugLineRef(DebugLineOffset(0x0102_0304)),
+ ),
+ (
+ Format::Dwarf32,
+ 4,
+ constants::DW_AT_addr_base,
+ constants::DW_FORM_sec_offset,
+ data4,
+ AttributeValue::SecOffset(0x0102_0304),
+ AttributeValue::DebugAddrBase(DebugAddrBase(0x0102_0304)),
+ ),
+ (
+ Format::Dwarf32,
+ 4,
+ constants::DW_AT_rnglists_base,
+ constants::DW_FORM_sec_offset,
+ data4,
+ AttributeValue::SecOffset(0x0102_0304),
+ AttributeValue::DebugRngListsBase(DebugRngListsBase(0x0102_0304)),
+ ),
+ (
+ Format::Dwarf32,
+ 4,
+ constants::DW_AT_loclists_base,
+ constants::DW_FORM_sec_offset,
+ data4,
+ AttributeValue::SecOffset(0x0102_0304),
+ AttributeValue::DebugLocListsBase(DebugLocListsBase(0x0102_0304)),
+ ),
+ ];
+
+ for test in tests.iter() {
+ let (format, version, name, form, mut input, expect_raw, expect_value) = *test;
+ unit.encoding.format = format;
+ unit.encoding.version = version;
+ let spec = AttributeSpecification::new(name, form, None);
+ let attribute =
+ parse_attribute(&mut input, unit.encoding(), spec).expect("Should parse attribute");
+ assert_eq!(attribute.raw_value(), expect_raw);
+ assert_eq!(attribute.value(), expect_value);
+ }
+ }
+
+ #[test]
+ fn test_attribute_udata_sdata_value() {
+ #[allow(clippy::type_complexity)]
+ let tests: &[(
+ AttributeValue<EndianSlice<LittleEndian>>,
+ Option<u64>,
+ Option<i64>,
+ )] = &[
+ (AttributeValue::Data1(1), Some(1), Some(1)),
+ (
+ AttributeValue::Data1(core::u8::MAX),
+ Some(u64::from(std::u8::MAX)),
+ Some(-1),
+ ),
+ (AttributeValue::Data2(1), Some(1), Some(1)),
+ (
+ AttributeValue::Data2(core::u16::MAX),
+ Some(u64::from(std::u16::MAX)),
+ Some(-1),
+ ),
+ (AttributeValue::Data4(1), Some(1), Some(1)),
+ (
+ AttributeValue::Data4(core::u32::MAX),
+ Some(u64::from(std::u32::MAX)),
+ Some(-1),
+ ),
+ (AttributeValue::Data8(1), Some(1), Some(1)),
+ (
+ AttributeValue::Data8(core::u64::MAX),
+ Some(core::u64::MAX),
+ Some(-1),
+ ),
+ (AttributeValue::Sdata(1), Some(1), Some(1)),
+ (AttributeValue::Sdata(-1), None, Some(-1)),
+ (AttributeValue::Udata(1), Some(1), Some(1)),
+ (AttributeValue::Udata(1u64 << 63), Some(1u64 << 63), None),
+ ];
+ for test in tests.iter() {
+ let (value, expect_udata, expect_sdata) = *test;
+ let attribute = Attribute {
+ name: DW_AT_data_member_location,
+ value,
+ };
+ assert_eq!(attribute.udata_value(), expect_udata);
+ assert_eq!(attribute.sdata_value(), expect_sdata);
+ }
+ }
+
+ fn test_parse_attribute_unit<Endian>(
+ address_size: u8,
+ format: Format,
+ endian: Endian,
+ ) -> UnitHeader<EndianSlice<'static, Endian>>
+ where
+ Endian: Endianity,
+ {
+ let encoding = Encoding {
+ format,
+ version: 4,
+ address_size,
+ };
+ UnitHeader::new(
+ encoding,
+ 7,
+ UnitType::Compilation,
+ DebugAbbrevOffset(0x0807_0605),
+ DebugInfoOffset(0).into(),
+ EndianSlice::new(&[], endian),
+ )
+ }
+
+ fn test_parse_attribute_unit_default() -> UnitHeader<EndianSlice<'static, LittleEndian>> {
+ test_parse_attribute_unit(4, Format::Dwarf32, LittleEndian)
+ }
+
+ fn test_parse_attribute<'input, Endian>(
+ buf: &'input [u8],
+ len: usize,
+ unit: &UnitHeader<EndianSlice<'input, Endian>>,
+ form: constants::DwForm,
+ value: AttributeValue<EndianSlice<'input, Endian>>,
+ ) where
+ Endian: Endianity,
+ {
+ let spec = AttributeSpecification::new(constants::DW_AT_low_pc, form, None);
+
+ let expect = Attribute {
+ name: constants::DW_AT_low_pc,
+ value,
+ };
+
+ let rest = &mut EndianSlice::new(buf, Endian::default());
+ match parse_attribute(rest, unit.encoding(), spec) {
+ Ok(attr) => {
+ assert_eq!(attr, expect);
+ assert_eq!(*rest, EndianSlice::new(&buf[len..], Endian::default()));
+ if let Some(size) = spec.size(unit) {
+ assert_eq!(rest.len() + size, buf.len());
+ }
+ }
+ otherwise => {
+ assert!(false, "Unexpected parse result = {:#?}", otherwise);
+ }
+ };
+ }
+
+ #[test]
+ fn test_parse_attribute_addr() {
+ let buf = [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08];
+ let unit = test_parse_attribute_unit(4, Format::Dwarf32, LittleEndian);
+ let form = constants::DW_FORM_addr;
+ let value = AttributeValue::Addr(0x0403_0201);
+ test_parse_attribute(&buf, 4, &unit, form, value);
+ }
+
+ #[test]
+ fn test_parse_attribute_addr8() {
+ let buf = [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08];
+ let unit = test_parse_attribute_unit(8, Format::Dwarf32, LittleEndian);
+ let form = constants::DW_FORM_addr;
+ let value = AttributeValue::Addr(0x0807_0605_0403_0201);
+ test_parse_attribute(&buf, 8, &unit, form, value);
+ }
+
+ #[test]
+ fn test_parse_attribute_block1() {
+ // Length of data (3), three bytes of data, two bytes of left over input.
+ let buf = [0x03, 0x09, 0x09, 0x09, 0x00, 0x00];
+ let unit = test_parse_attribute_unit_default();
+ let form = constants::DW_FORM_block1;
+ let value = AttributeValue::Block(EndianSlice::new(&buf[1..4], LittleEndian));
+ test_parse_attribute(&buf, 4, &unit, form, value);
+ }
+
+ #[test]
+ fn test_parse_attribute_block2() {
+ // Two byte length of data (2), two bytes of data, two bytes of left over input.
+ let buf = [0x02, 0x00, 0x09, 0x09, 0x00, 0x00];
+ let unit = test_parse_attribute_unit_default();
+ let form = constants::DW_FORM_block2;
+ let value = AttributeValue::Block(EndianSlice::new(&buf[2..4], LittleEndian));
+ test_parse_attribute(&buf, 4, &unit, form, value);
+ }
+
+ #[test]
+ fn test_parse_attribute_block4() {
+ // Four byte length of data (2), two bytes of data, no left over input.
+ let buf = [0x02, 0x00, 0x00, 0x00, 0x99, 0x99];
+ let unit = test_parse_attribute_unit_default();
+ let form = constants::DW_FORM_block4;
+ let value = AttributeValue::Block(EndianSlice::new(&buf[4..], LittleEndian));
+ test_parse_attribute(&buf, 6, &unit, form, value);
+ }
+
+ #[test]
+ fn test_parse_attribute_block() {
+ // LEB length of data (2, one byte), two bytes of data, no left over input.
+ let buf = [0x02, 0x99, 0x99];
+ let unit = test_parse_attribute_unit_default();
+ let form = constants::DW_FORM_block;
+ let value = AttributeValue::Block(EndianSlice::new(&buf[1..], LittleEndian));
+ test_parse_attribute(&buf, 3, &unit, form, value);
+ }
+
+ #[test]
+ fn test_parse_attribute_data1() {
+ let buf = [0x03];
+ let unit = test_parse_attribute_unit_default();
+ let form = constants::DW_FORM_data1;
+ let value = AttributeValue::Data1(0x03);
+ test_parse_attribute(&buf, 1, &unit, form, value);
+ }
+
+ #[test]
+ fn test_parse_attribute_data2() {
+ let buf = [0x02, 0x01, 0x0];
+ let unit = test_parse_attribute_unit_default();
+ let form = constants::DW_FORM_data2;
+ let value = AttributeValue::Data2(0x0102);
+ test_parse_attribute(&buf, 2, &unit, form, value);
+ }
+
+ #[test]
+ fn test_parse_attribute_data4() {
+ let buf = [0x01, 0x02, 0x03, 0x04, 0x99, 0x99];
+ let unit = test_parse_attribute_unit_default();
+ let form = constants::DW_FORM_data4;
+ let value = AttributeValue::Data4(0x0403_0201);
+ test_parse_attribute(&buf, 4, &unit, form, value);
+ }
+
+ #[test]
+ fn test_parse_attribute_data8() {
+ let buf = [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x99, 0x99];
+ let unit = test_parse_attribute_unit_default();
+ let form = constants::DW_FORM_data8;
+ let value = AttributeValue::Data8(0x0807_0605_0403_0201);
+ test_parse_attribute(&buf, 8, &unit, form, value);
+ }
+
+ #[test]
+ fn test_parse_attribute_udata() {
+ let mut buf = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
+
+ let bytes_written = {
+ let mut writable = &mut buf[..];
+ leb128::write::unsigned(&mut writable, 4097).expect("should write ok")
+ };
+
+ let unit = test_parse_attribute_unit_default();
+ let form = constants::DW_FORM_udata;
+ let value = AttributeValue::Udata(4097);
+ test_parse_attribute(&buf, bytes_written, &unit, form, value);
+ }
+
+ #[test]
+ fn test_parse_attribute_sdata() {
+ let mut buf = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
+
+ let bytes_written = {
+ let mut writable = &mut buf[..];
+ leb128::write::signed(&mut writable, -4097).expect("should write ok")
+ };
+
+ let unit = test_parse_attribute_unit_default();
+ let form = constants::DW_FORM_sdata;
+ let value = AttributeValue::Sdata(-4097);
+ test_parse_attribute(&buf, bytes_written, &unit, form, value);
+ }
+
+ #[test]
+ fn test_parse_attribute_exprloc() {
+ // LEB length of data (2, one byte), two bytes of data, one byte left over input.
+ let buf = [0x02, 0x99, 0x99, 0x11];
+ let unit = test_parse_attribute_unit_default();
+ let form = constants::DW_FORM_exprloc;
+ let value = AttributeValue::Exprloc(Expression(EndianSlice::new(&buf[1..3], LittleEndian)));
+ test_parse_attribute(&buf, 3, &unit, form, value);
+ }
+
+ #[test]
+ fn test_parse_attribute_flag_true() {
+ let buf = [0x42];
+ let unit = test_parse_attribute_unit_default();
+ let form = constants::DW_FORM_flag;
+ let value = AttributeValue::Flag(true);
+ test_parse_attribute(&buf, 1, &unit, form, value);
+ }
+
+ #[test]
+ fn test_parse_attribute_flag_false() {
+ let buf = [0x00];
+ let unit = test_parse_attribute_unit_default();
+ let form = constants::DW_FORM_flag;
+ let value = AttributeValue::Flag(false);
+ test_parse_attribute(&buf, 1, &unit, form, value);
+ }
+
+ #[test]
+ fn test_parse_attribute_flag_present() {
+ let buf = [0x01, 0x02, 0x03, 0x04];
+ let unit = test_parse_attribute_unit_default();
+ let form = constants::DW_FORM_flag_present;
+ let value = AttributeValue::Flag(true);
+ // DW_FORM_flag_present does not consume any bytes of the input stream.
+ test_parse_attribute(&buf, 0, &unit, form, value);
+ }
+
+ #[test]
+ fn test_parse_attribute_sec_offset_32() {
+ let buf = [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x10];
+ let unit = test_parse_attribute_unit(4, Format::Dwarf32, LittleEndian);
+ let form = constants::DW_FORM_sec_offset;
+ let value = AttributeValue::SecOffset(0x0403_0201);
+ test_parse_attribute(&buf, 4, &unit, form, value);
+ }
+
+ #[test]
+ #[cfg(target_pointer_width = "64")]
+ fn test_parse_attribute_sec_offset_64() {
+ let buf = [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x10];
+ let unit = test_parse_attribute_unit(4, Format::Dwarf64, LittleEndian);
+ let form = constants::DW_FORM_sec_offset;
+ let value = AttributeValue::SecOffset(0x0807_0605_0403_0201);
+ test_parse_attribute(&buf, 8, &unit, form, value);
+ }
+
+ #[test]
+ fn test_parse_attribute_ref1() {
+ let buf = [0x03];
+ let unit = test_parse_attribute_unit_default();
+ let form = constants::DW_FORM_ref1;
+ let value = AttributeValue::UnitRef(UnitOffset(3));
+ test_parse_attribute(&buf, 1, &unit, form, value);
+ }
+
+ #[test]
+ fn test_parse_attribute_ref2() {
+ let buf = [0x02, 0x01, 0x0];
+ let unit = test_parse_attribute_unit_default();
+ let form = constants::DW_FORM_ref2;
+ let value = AttributeValue::UnitRef(UnitOffset(258));
+ test_parse_attribute(&buf, 2, &unit, form, value);
+ }
+
+ #[test]
+ fn test_parse_attribute_ref4() {
+ let buf = [0x01, 0x02, 0x03, 0x04, 0x99, 0x99];
+ let unit = test_parse_attribute_unit_default();
+ let form = constants::DW_FORM_ref4;
+ let value = AttributeValue::UnitRef(UnitOffset(0x0403_0201));
+ test_parse_attribute(&buf, 4, &unit, form, value);
+ }
+
+ #[test]
+ #[cfg(target_pointer_width = "64")]
+ fn test_parse_attribute_ref8() {
+ let buf = [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x99, 0x99];
+ let unit = test_parse_attribute_unit_default();
+ let form = constants::DW_FORM_ref8;
+ let value = AttributeValue::UnitRef(UnitOffset(0x0807_0605_0403_0201));
+ test_parse_attribute(&buf, 8, &unit, form, value);
+ }
+
+ #[test]
+ fn test_parse_attribute_ref_sup4() {
+ let buf = [0x01, 0x02, 0x03, 0x04, 0x99, 0x99];
+ let unit = test_parse_attribute_unit_default();
+ let form = constants::DW_FORM_ref_sup4;
+ let value = AttributeValue::DebugInfoRefSup(DebugInfoOffset(0x0403_0201));
+ test_parse_attribute(&buf, 4, &unit, form, value);
+ }
+
+ #[test]
+ #[cfg(target_pointer_width = "64")]
+ fn test_parse_attribute_ref_sup8() {
+ let buf = [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x99, 0x99];
+ let unit = test_parse_attribute_unit_default();
+ let form = constants::DW_FORM_ref_sup8;
+ let value = AttributeValue::DebugInfoRefSup(DebugInfoOffset(0x0807_0605_0403_0201));
+ test_parse_attribute(&buf, 8, &unit, form, value);
+ }
+
+ #[test]
+ fn test_parse_attribute_refudata() {
+ let mut buf = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
+
+ let bytes_written = {
+ let mut writable = &mut buf[..];
+ leb128::write::unsigned(&mut writable, 4097).expect("should write ok")
+ };
+
+ let unit = test_parse_attribute_unit_default();
+ let form = constants::DW_FORM_ref_udata;
+ let value = AttributeValue::UnitRef(UnitOffset(4097));
+ test_parse_attribute(&buf, bytes_written, &unit, form, value);
+ }
+
+ #[test]
+ fn test_parse_attribute_refaddr_32() {
+ let buf = [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x99, 0x99];
+ let unit = test_parse_attribute_unit(4, Format::Dwarf32, LittleEndian);
+ let form = constants::DW_FORM_ref_addr;
+ let value = AttributeValue::DebugInfoRef(DebugInfoOffset(0x0403_0201));
+ test_parse_attribute(&buf, 4, &unit, form, value);
+ }
+
+ #[test]
+ #[cfg(target_pointer_width = "64")]
+ fn test_parse_attribute_refaddr_64() {
+ let buf = [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x99, 0x99];
+ let unit = test_parse_attribute_unit(4, Format::Dwarf64, LittleEndian);
+ let form = constants::DW_FORM_ref_addr;
+ let value = AttributeValue::DebugInfoRef(DebugInfoOffset(0x0807_0605_0403_0201));
+ test_parse_attribute(&buf, 8, &unit, form, value);
+ }
+
+ #[test]
+ fn test_parse_attribute_refaddr_version2() {
+ let buf = [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x99, 0x99];
+ let mut unit = test_parse_attribute_unit(4, Format::Dwarf32, LittleEndian);
+ unit.encoding.version = 2;
+ let form = constants::DW_FORM_ref_addr;
+ let value = AttributeValue::DebugInfoRef(DebugInfoOffset(0x0403_0201));
+ test_parse_attribute(&buf, 4, &unit, form, value);
+ }
+
+ #[test]
+ #[cfg(target_pointer_width = "64")]
+ fn test_parse_attribute_refaddr8_version2() {
+ let buf = [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x99, 0x99];
+ let mut unit = test_parse_attribute_unit(8, Format::Dwarf32, LittleEndian);
+ unit.encoding.version = 2;
+ let form = constants::DW_FORM_ref_addr;
+ let value = AttributeValue::DebugInfoRef(DebugInfoOffset(0x0807_0605_0403_0201));
+ test_parse_attribute(&buf, 8, &unit, form, value);
+ }
+
+ #[test]
+ fn test_parse_attribute_gnu_ref_alt_32() {
+ let buf = [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x99, 0x99];
+ let unit = test_parse_attribute_unit(4, Format::Dwarf32, LittleEndian);
+ let form = constants::DW_FORM_GNU_ref_alt;
+ let value = AttributeValue::DebugInfoRefSup(DebugInfoOffset(0x0403_0201));
+ test_parse_attribute(&buf, 4, &unit, form, value);
+ }
+
+ #[test]
+ #[cfg(target_pointer_width = "64")]
+ fn test_parse_attribute_gnu_ref_alt_64() {
+ let buf = [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x99, 0x99];
+ let unit = test_parse_attribute_unit(4, Format::Dwarf64, LittleEndian);
+ let form = constants::DW_FORM_GNU_ref_alt;
+ let value = AttributeValue::DebugInfoRefSup(DebugInfoOffset(0x0807_0605_0403_0201));
+ test_parse_attribute(&buf, 8, &unit, form, value);
+ }
+
+ #[test]
+ fn test_parse_attribute_refsig8() {
+ let buf = [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x99, 0x99];
+ let unit = test_parse_attribute_unit_default();
+ let form = constants::DW_FORM_ref_sig8;
+ let value = AttributeValue::DebugTypesRef(DebugTypeSignature(0x0807_0605_0403_0201));
+ test_parse_attribute(&buf, 8, &unit, form, value);
+ }
+
+ #[test]
+ fn test_parse_attribute_string() {
+ let buf = [0x01, 0x02, 0x03, 0x04, 0x05, 0x0, 0x99, 0x99];
+ let unit = test_parse_attribute_unit_default();
+ let form = constants::DW_FORM_string;
+ let value = AttributeValue::String(EndianSlice::new(&buf[..5], LittleEndian));
+ test_parse_attribute(&buf, 6, &unit, form, value);
+ }
+
+ #[test]
+ fn test_parse_attribute_strp_32() {
+ let buf = [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x99, 0x99];
+ let unit = test_parse_attribute_unit(4, Format::Dwarf32, LittleEndian);
+ let form = constants::DW_FORM_strp;
+ let value = AttributeValue::DebugStrRef(DebugStrOffset(0x0403_0201));
+ test_parse_attribute(&buf, 4, &unit, form, value);
+ }
+
+ #[test]
+ #[cfg(target_pointer_width = "64")]
+ fn test_parse_attribute_strp_64() {
+ let buf = [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x99, 0x99];
+ let unit = test_parse_attribute_unit(4, Format::Dwarf64, LittleEndian);
+ let form = constants::DW_FORM_strp;
+ let value = AttributeValue::DebugStrRef(DebugStrOffset(0x0807_0605_0403_0201));
+ test_parse_attribute(&buf, 8, &unit, form, value);
+ }
+
+ #[test]
+ fn test_parse_attribute_strp_sup_32() {
+ let buf = [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x99, 0x99];
+ let unit = test_parse_attribute_unit(4, Format::Dwarf32, LittleEndian);
+ let form = constants::DW_FORM_strp_sup;
+ let value = AttributeValue::DebugStrRefSup(DebugStrOffset(0x0403_0201));
+ test_parse_attribute(&buf, 4, &unit, form, value);
+ }
+
+ #[test]
+ #[cfg(target_pointer_width = "64")]
+ fn test_parse_attribute_strp_sup_64() {
+ let buf = [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x99, 0x99];
+ let unit = test_parse_attribute_unit(4, Format::Dwarf64, LittleEndian);
+ let form = constants::DW_FORM_strp_sup;
+ let value = AttributeValue::DebugStrRefSup(DebugStrOffset(0x0807_0605_0403_0201));
+ test_parse_attribute(&buf, 8, &unit, form, value);
+ }
+
+ #[test]
+ fn test_parse_attribute_gnu_strp_alt_32() {
+ let buf = [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x99, 0x99];
+ let unit = test_parse_attribute_unit(4, Format::Dwarf32, LittleEndian);
+ let form = constants::DW_FORM_GNU_strp_alt;
+ let value = AttributeValue::DebugStrRefSup(DebugStrOffset(0x0403_0201));
+ test_parse_attribute(&buf, 4, &unit, form, value);
+ }
+
+ #[test]
+ #[cfg(target_pointer_width = "64")]
+ fn test_parse_attribute_gnu_strp_alt_64() {
+ let buf = [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x99, 0x99];
+ let unit = test_parse_attribute_unit(4, Format::Dwarf64, LittleEndian);
+ let form = constants::DW_FORM_GNU_strp_alt;
+ let value = AttributeValue::DebugStrRefSup(DebugStrOffset(0x0807_0605_0403_0201));
+ test_parse_attribute(&buf, 8, &unit, form, value);
+ }
+
+ #[test]
+ fn test_parse_attribute_strx() {
+ let mut buf = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
+
+ let bytes_written = {
+ let mut writable = &mut buf[..];
+ leb128::write::unsigned(&mut writable, 4097).expect("should write ok")
+ };
+
+ let unit = test_parse_attribute_unit_default();
+ let form = constants::DW_FORM_strx;
+ let value = AttributeValue::DebugStrOffsetsIndex(DebugStrOffsetsIndex(4097));
+ test_parse_attribute(&buf, bytes_written, &unit, form, value);
+ }
+
+ #[test]
+ fn test_parse_attribute_strx1() {
+ let buf = [0x01, 0x99, 0x99];
+ let unit = test_parse_attribute_unit(4, Format::Dwarf64, LittleEndian);
+ let form = constants::DW_FORM_strx1;
+ let value = AttributeValue::DebugStrOffsetsIndex(DebugStrOffsetsIndex(0x01));
+ test_parse_attribute(&buf, 1, &unit, form, value);
+ }
+
+ #[test]
+ fn test_parse_attribute_strx2() {
+ let buf = [0x01, 0x02, 0x99, 0x99];
+ let unit = test_parse_attribute_unit(4, Format::Dwarf64, LittleEndian);
+ let form = constants::DW_FORM_strx2;
+ let value = AttributeValue::DebugStrOffsetsIndex(DebugStrOffsetsIndex(0x0201));
+ test_parse_attribute(&buf, 2, &unit, form, value);
+ }
+
+ #[test]
+ fn test_parse_attribute_strx3() {
+ let buf = [0x01, 0x02, 0x03, 0x99, 0x99];
+ let unit = test_parse_attribute_unit(4, Format::Dwarf64, LittleEndian);
+ let form = constants::DW_FORM_strx3;
+ let value = AttributeValue::DebugStrOffsetsIndex(DebugStrOffsetsIndex(0x03_0201));
+ test_parse_attribute(&buf, 3, &unit, form, value);
+ }
+
+ #[test]
+ fn test_parse_attribute_strx4() {
+ let buf = [0x01, 0x02, 0x03, 0x04, 0x99, 0x99];
+ let unit = test_parse_attribute_unit(4, Format::Dwarf64, LittleEndian);
+ let form = constants::DW_FORM_strx4;
+ let value = AttributeValue::DebugStrOffsetsIndex(DebugStrOffsetsIndex(0x0403_0201));
+ test_parse_attribute(&buf, 4, &unit, form, value);
+ }
+
+ #[test]
+ fn test_parse_attribute_addrx() {
+ let mut buf = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
+
+ let bytes_written = {
+ let mut writable = &mut buf[..];
+ leb128::write::unsigned(&mut writable, 4097).expect("should write ok")
+ };
+
+ let unit = test_parse_attribute_unit_default();
+ let form = constants::DW_FORM_addrx;
+ let value = AttributeValue::DebugAddrIndex(DebugAddrIndex(4097));
+ test_parse_attribute(&buf, bytes_written, &unit, form, value);
+ }
+
+ #[test]
+ fn test_parse_attribute_addrx1() {
+ let buf = [0x01, 0x99, 0x99];
+ let unit = test_parse_attribute_unit(4, Format::Dwarf64, LittleEndian);
+ let form = constants::DW_FORM_addrx1;
+ let value = AttributeValue::DebugAddrIndex(DebugAddrIndex(0x01));
+ test_parse_attribute(&buf, 1, &unit, form, value);
+ }
+
+ #[test]
+ fn test_parse_attribute_addrx2() {
+ let buf = [0x01, 0x02, 0x99, 0x99];
+ let unit = test_parse_attribute_unit(4, Format::Dwarf64, LittleEndian);
+ let form = constants::DW_FORM_addrx2;
+ let value = AttributeValue::DebugAddrIndex(DebugAddrIndex(0x0201));
+ test_parse_attribute(&buf, 2, &unit, form, value);
+ }
+
+ #[test]
+ fn test_parse_attribute_addrx3() {
+ let buf = [0x01, 0x02, 0x03, 0x99, 0x99];
+ let unit = test_parse_attribute_unit(4, Format::Dwarf64, LittleEndian);
+ let form = constants::DW_FORM_addrx3;
+ let value = AttributeValue::DebugAddrIndex(DebugAddrIndex(0x03_0201));
+ test_parse_attribute(&buf, 3, &unit, form, value);
+ }
+
+ #[test]
+ fn test_parse_attribute_addrx4() {
+ let buf = [0x01, 0x02, 0x03, 0x04, 0x99, 0x99];
+ let unit = test_parse_attribute_unit(4, Format::Dwarf64, LittleEndian);
+ let form = constants::DW_FORM_addrx4;
+ let value = AttributeValue::DebugAddrIndex(DebugAddrIndex(0x0403_0201));
+ test_parse_attribute(&buf, 4, &unit, form, value);
+ }
+
+ #[test]
+ fn test_parse_attribute_loclistx() {
+ let mut buf = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
+
+ let bytes_written = {
+ let mut writable = &mut buf[..];
+ leb128::write::unsigned(&mut writable, 4097).expect("should write ok")
+ };
+
+ let unit = test_parse_attribute_unit_default();
+ let form = constants::DW_FORM_loclistx;
+ let value = AttributeValue::DebugLocListsIndex(DebugLocListsIndex(4097));
+ test_parse_attribute(&buf, bytes_written, &unit, form, value);
+ }
+
+ #[test]
+ fn test_parse_attribute_rnglistx() {
+ let mut buf = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
+
+ let bytes_written = {
+ let mut writable = &mut buf[..];
+ leb128::write::unsigned(&mut writable, 4097).expect("should write ok")
+ };
+
+ let unit = test_parse_attribute_unit_default();
+ let form = constants::DW_FORM_rnglistx;
+ let value = AttributeValue::DebugRngListsIndex(DebugRngListsIndex(4097));
+ test_parse_attribute(&buf, bytes_written, &unit, form, value);
+ }
+
+ #[test]
+ fn test_parse_attribute_indirect() {
+ let mut buf = [0; 100];
+
+ let bytes_written = {
+ let mut writable = &mut buf[..];
+ leb128::write::unsigned(&mut writable, constants::DW_FORM_udata.0.into())
+ .expect("should write udata")
+ + leb128::write::unsigned(&mut writable, 9_999_999).expect("should write value")
+ };
+
+ let unit = test_parse_attribute_unit_default();
+ let form = constants::DW_FORM_indirect;
+ let value = AttributeValue::Udata(9_999_999);
+ test_parse_attribute(&buf, bytes_written, &unit, form, value);
+ }
+
+ #[test]
+ fn test_parse_attribute_indirect_implicit_const() {
+ let encoding = Encoding {
+ format: Format::Dwarf32,
+ version: 4,
+ address_size: 4,
+ };
+ let mut buf = [0; 100];
+ let mut writable = &mut buf[..];
+ leb128::write::unsigned(&mut writable, constants::DW_FORM_implicit_const.0.into())
+ .expect("should write implicit_const");
+
+ let input = &mut EndianSlice::new(&buf, LittleEndian);
+ let spec =
+ AttributeSpecification::new(constants::DW_AT_low_pc, constants::DW_FORM_indirect, None);
+ assert_eq!(
+ parse_attribute(input, encoding, spec),
+ Err(Error::InvalidImplicitConst)
+ );
+ }
+
+ #[test]
+ fn test_attrs_iter() {
+ let encoding = Encoding {
+ format: Format::Dwarf32,
+ version: 4,
+ address_size: 4,
+ };
+ let unit = UnitHeader::new(
+ encoding,
+ 7,
+ UnitType::Compilation,
+ DebugAbbrevOffset(0x0807_0605),
+ DebugInfoOffset(0).into(),
+ EndianSlice::new(&[], LittleEndian),
+ );
+
+ let abbrev = Abbreviation::new(
+ 42,
+ constants::DW_TAG_subprogram,
+ constants::DW_CHILDREN_yes,
+ vec![
+ AttributeSpecification::new(constants::DW_AT_name, constants::DW_FORM_string, None),
+ AttributeSpecification::new(constants::DW_AT_low_pc, constants::DW_FORM_addr, None),
+ AttributeSpecification::new(
+ constants::DW_AT_high_pc,
+ constants::DW_FORM_addr,
+ None,
+ ),
+ ]
+ .into(),
+ );
+
+ // "foo", 42, 1337, 4 dangling bytes of 0xaa where children would be
+ let buf = [
+ 0x66, 0x6f, 0x6f, 0x00, 0x2a, 0x00, 0x00, 0x00, 0x39, 0x05, 0x00, 0x00, 0xaa, 0xaa,
+ 0xaa, 0xaa,
+ ];
+
+ let entry = DebuggingInformationEntry {
+ offset: UnitOffset(0),
+ attrs_slice: EndianSlice::new(&buf, LittleEndian),
+ attrs_len: Cell::new(None),
+ abbrev: &abbrev,
+ unit: &unit,
+ };
+
+ let mut attrs = AttrsIter {
+ input: EndianSlice::new(&buf, LittleEndian),
+ attributes: abbrev.attributes(),
+ entry: &entry,
+ };
+
+ match attrs.next() {
+ Ok(Some(attr)) => {
+ assert_eq!(
+ attr,
+ Attribute {
+ name: constants::DW_AT_name,
+ value: AttributeValue::String(EndianSlice::new(b"foo", LittleEndian)),
+ }
+ );
+ }
+ otherwise => {
+ assert!(false, "Unexpected parse result = {:#?}", otherwise);
+ }
+ }
+
+ assert!(entry.attrs_len.get().is_none());
+
+ match attrs.next() {
+ Ok(Some(attr)) => {
+ assert_eq!(
+ attr,
+ Attribute {
+ name: constants::DW_AT_low_pc,
+ value: AttributeValue::Addr(0x2a),
+ }
+ );
+ }
+ otherwise => {
+ assert!(false, "Unexpected parse result = {:#?}", otherwise);
+ }
+ }
+
+ assert!(entry.attrs_len.get().is_none());
+
+ match attrs.next() {
+ Ok(Some(attr)) => {
+ assert_eq!(
+ attr,
+ Attribute {
+ name: constants::DW_AT_high_pc,
+ value: AttributeValue::Addr(0x539),
+ }
+ );
+ }
+ otherwise => {
+ assert!(false, "Unexpected parse result = {:#?}", otherwise);
+ }
+ }
+
+ assert!(entry.attrs_len.get().is_none());
+
+ assert!(attrs.next().expect("should parse next").is_none());
+ assert!(entry.attrs_len.get().is_some());
+ assert_eq!(
+ entry.attrs_len.get().expect("should have entry.attrs_len"),
+ buf.len() - 4
+ )
+ }
+
+ #[test]
+ fn test_attrs_iter_incomplete() {
+ let encoding = Encoding {
+ format: Format::Dwarf32,
+ version: 4,
+ address_size: 4,
+ };
+ let unit = UnitHeader::new(
+ encoding,
+ 7,
+ UnitType::Compilation,
+ DebugAbbrevOffset(0x0807_0605),
+ DebugInfoOffset(0).into(),
+ EndianSlice::new(&[], LittleEndian),
+ );
+
+ let abbrev = Abbreviation::new(
+ 42,
+ constants::DW_TAG_subprogram,
+ constants::DW_CHILDREN_yes,
+ vec![
+ AttributeSpecification::new(constants::DW_AT_name, constants::DW_FORM_string, None),
+ AttributeSpecification::new(constants::DW_AT_low_pc, constants::DW_FORM_addr, None),
+ AttributeSpecification::new(
+ constants::DW_AT_high_pc,
+ constants::DW_FORM_addr,
+ None,
+ ),
+ ]
+ .into(),
+ );
+
+ // "foo"
+ let buf = [0x66, 0x6f, 0x6f, 0x00];
+
+ let entry = DebuggingInformationEntry {
+ offset: UnitOffset(0),
+ attrs_slice: EndianSlice::new(&buf, LittleEndian),
+ attrs_len: Cell::new(None),
+ abbrev: &abbrev,
+ unit: &unit,
+ };
+
+ let mut attrs = AttrsIter {
+ input: EndianSlice::new(&buf, LittleEndian),
+ attributes: abbrev.attributes(),
+ entry: &entry,
+ };
+
+ match attrs.next() {
+ Ok(Some(attr)) => {
+ assert_eq!(
+ attr,
+ Attribute {
+ name: constants::DW_AT_name,
+ value: AttributeValue::String(EndianSlice::new(b"foo", LittleEndian)),
+ }
+ );
+ }
+ otherwise => {
+ assert!(false, "Unexpected parse result = {:#?}", otherwise);
+ }
+ }
+
+ assert!(entry.attrs_len.get().is_none());
+
+ // Return error for incomplete attribute.
+ assert!(attrs.next().is_err());
+ assert!(entry.attrs_len.get().is_none());
+
+ // Return error for all subsequent calls.
+ assert!(attrs.next().is_err());
+ assert!(attrs.next().is_err());
+ assert!(attrs.next().is_err());
+ assert!(attrs.next().is_err());
+ assert!(entry.attrs_len.get().is_none());
+ }
+
+ fn assert_entry_name<Endian>(entry: &DebuggingInformationEntry<EndianSlice<Endian>>, name: &str)
+ where
+ Endian: Endianity,
+ {
+ let value = entry
+ .attr_value(constants::DW_AT_name)
+ .expect("Should have parsed the name attribute")
+ .expect("Should have found the name attribute");
+
+ assert_eq!(
+ value,
+ AttributeValue::String(EndianSlice::new(name.as_bytes(), Endian::default()))
+ );
+ }
+
+ fn assert_current_name<Endian>(cursor: &EntriesCursor<EndianSlice<Endian>>, name: &str)
+ where
+ Endian: Endianity,
+ {
+ let entry = cursor.current().expect("Should have an entry result");
+ assert_entry_name(entry, name);
+ }
+
+ fn assert_next_entry<Endian>(cursor: &mut EntriesCursor<EndianSlice<Endian>>, name: &str)
+ where
+ Endian: Endianity,
+ {
+ cursor
+ .next_entry()
+ .expect("Should parse next entry")
+ .expect("Should have an entry");
+ assert_current_name(cursor, name);
+ }
+
+ fn assert_next_entry_null<Endian>(cursor: &mut EntriesCursor<EndianSlice<Endian>>)
+ where
+ Endian: Endianity,
+ {
+ cursor
+ .next_entry()
+ .expect("Should parse next entry")
+ .expect("Should have an entry");
+ assert!(cursor.current().is_none());
+ }
+
+ fn assert_next_dfs<Endian>(
+ cursor: &mut EntriesCursor<EndianSlice<Endian>>,
+ name: &str,
+ depth: isize,
+ ) where
+ Endian: Endianity,
+ {
+ {
+ let (val, entry) = cursor
+ .next_dfs()
+ .expect("Should parse next dfs")
+ .expect("Should not be done with traversal");
+ assert_eq!(val, depth);
+ assert_entry_name(entry, name);
+ }
+ assert_current_name(cursor, name);
+ }
+
+ fn assert_next_sibling<Endian>(cursor: &mut EntriesCursor<EndianSlice<Endian>>, name: &str)
+ where
+ Endian: Endianity,
+ {
+ {
+ let entry = cursor
+ .next_sibling()
+ .expect("Should parse next sibling")
+ .expect("Should not be done with traversal");
+ assert_entry_name(entry, name);
+ }
+ assert_current_name(cursor, name);
+ }
+
+ fn assert_valid_sibling_ptr<Endian>(cursor: &EntriesCursor<EndianSlice<Endian>>)
+ where
+ Endian: Endianity,
+ {
+ let sibling_ptr = cursor
+ .current()
+ .expect("Should have current entry")
+ .attr_value(constants::DW_AT_sibling);
+ match sibling_ptr {
+ Ok(Some(AttributeValue::UnitRef(offset))) => {
+ cursor
+ .unit
+ .range_from(offset..)
+ .expect("Sibling offset should be valid");
+ }
+ _ => panic!("Invalid sibling pointer {:?}", sibling_ptr),
+ }
+ }
+
+ fn entries_cursor_tests_abbrev_buf() -> Vec<u8> {
+ #[rustfmt::skip]
+ let section = Section::with_endian(Endian::Little)
+ .abbrev(1, DW_TAG_subprogram, DW_CHILDREN_yes)
+ .abbrev_attr(DW_AT_name, DW_FORM_string)
+ .abbrev_attr_null()
+ .abbrev_null();
+ section.get_contents().unwrap()
+ }
+
+ fn entries_cursor_tests_debug_info_buf() -> Vec<u8> {
+ #[rustfmt::skip]
+ let section = Section::with_endian(Endian::Little)
+ .die(1, |s| s.attr_string("001"))
+ .die(1, |s| s.attr_string("002"))
+ .die(1, |s| s.attr_string("003"))
+ .die_null()
+ .die_null()
+ .die(1, |s| s.attr_string("004"))
+ .die(1, |s| s.attr_string("005"))
+ .die_null()
+ .die(1, |s| s.attr_string("006"))
+ .die_null()
+ .die_null()
+ .die(1, |s| s.attr_string("007"))
+ .die(1, |s| s.attr_string("008"))
+ .die(1, |s| s.attr_string("009"))
+ .die_null()
+ .die_null()
+ .die_null()
+ .die(1, |s| s.attr_string("010"))
+ .die_null()
+ .die_null();
+ let entries_buf = section.get_contents().unwrap();
+
+ let encoding = Encoding {
+ format: Format::Dwarf32,
+ version: 4,
+ address_size: 4,
+ };
+ let mut unit = UnitHeader {
+ encoding,
+ unit_length: 0,
+ unit_type: UnitType::Compilation,
+ debug_abbrev_offset: DebugAbbrevOffset(0),
+ unit_offset: DebugInfoOffset(0).into(),
+ entries_buf: EndianSlice::new(&entries_buf, LittleEndian),
+ };
+ let section = Section::with_endian(Endian::Little).unit(&mut unit);
+ section.get_contents().unwrap()
+ }
+
+ #[test]
+ fn test_cursor_next_entry_incomplete() {
+ #[rustfmt::skip]
+ let section = Section::with_endian(Endian::Little)
+ .die(1, |s| s.attr_string("001"))
+ .die(1, |s| s.attr_string("002"))
+ .die(1, |s| s);
+ let entries_buf = section.get_contents().unwrap();
+
+ let encoding = Encoding {
+ format: Format::Dwarf32,
+ version: 4,
+ address_size: 4,
+ };
+ let mut unit = UnitHeader {
+ encoding,
+ unit_length: 0,
+ unit_type: UnitType::Compilation,
+ debug_abbrev_offset: DebugAbbrevOffset(0),
+ unit_offset: DebugInfoOffset(0).into(),
+ entries_buf: EndianSlice::new(&entries_buf, LittleEndian),
+ };
+ let section = Section::with_endian(Endian::Little).unit(&mut unit);
+ let info_buf = &section.get_contents().unwrap();
+ let debug_info = DebugInfo::new(info_buf, LittleEndian);
+
+ let unit = debug_info
+ .units()
+ .next()
+ .expect("should have a unit result")
+ .expect("and it should be ok");
+
+ let abbrevs_buf = &entries_cursor_tests_abbrev_buf();
+ let debug_abbrev = DebugAbbrev::new(abbrevs_buf, LittleEndian);
+
+ let abbrevs = unit
+ .abbreviations(&debug_abbrev)
+ .expect("Should parse abbreviations");
+
+ let mut cursor = unit.entries(&abbrevs);
+
+ assert_next_entry(&mut cursor, "001");
+ assert_next_entry(&mut cursor, "002");
+
+ {
+ // Entry code is present, but none of the attributes.
+ cursor
+ .next_entry()
+ .expect("Should parse next entry")
+ .expect("Should have an entry");
+ let entry = cursor.current().expect("Should have an entry result");
+ assert!(entry.attrs().next().is_err());
+ }
+
+ assert!(cursor.next_entry().is_err());
+ assert!(cursor.next_entry().is_err());
+ }
+
+ #[test]
+ fn test_cursor_next_entry() {
+ let info_buf = &entries_cursor_tests_debug_info_buf();
+ let debug_info = DebugInfo::new(info_buf, LittleEndian);
+
+ let unit = debug_info
+ .units()
+ .next()
+ .expect("should have a unit result")
+ .expect("and it should be ok");
+
+ let abbrevs_buf = &entries_cursor_tests_abbrev_buf();
+ let debug_abbrev = DebugAbbrev::new(abbrevs_buf, LittleEndian);
+
+ let abbrevs = unit
+ .abbreviations(&debug_abbrev)
+ .expect("Should parse abbreviations");
+
+ let mut cursor = unit.entries(&abbrevs);
+
+ assert_next_entry(&mut cursor, "001");
+ assert_next_entry(&mut cursor, "002");
+ assert_next_entry(&mut cursor, "003");
+ assert_next_entry_null(&mut cursor);
+ assert_next_entry_null(&mut cursor);
+ assert_next_entry(&mut cursor, "004");
+ assert_next_entry(&mut cursor, "005");
+ assert_next_entry_null(&mut cursor);
+ assert_next_entry(&mut cursor, "006");
+ assert_next_entry_null(&mut cursor);
+ assert_next_entry_null(&mut cursor);
+ assert_next_entry(&mut cursor, "007");
+ assert_next_entry(&mut cursor, "008");
+ assert_next_entry(&mut cursor, "009");
+ assert_next_entry_null(&mut cursor);
+ assert_next_entry_null(&mut cursor);
+ assert_next_entry_null(&mut cursor);
+ assert_next_entry(&mut cursor, "010");
+ assert_next_entry_null(&mut cursor);
+ assert_next_entry_null(&mut cursor);
+
+ assert!(cursor
+ .next_entry()
+ .expect("Should parse next entry")
+ .is_none());
+ assert!(cursor.current().is_none());
+ }
+
+ #[test]
+ fn test_cursor_next_dfs() {
+ let info_buf = &entries_cursor_tests_debug_info_buf();
+ let debug_info = DebugInfo::new(info_buf, LittleEndian);
+
+ let unit = debug_info
+ .units()
+ .next()
+ .expect("should have a unit result")
+ .expect("and it should be ok");
+
+ let abbrevs_buf = &entries_cursor_tests_abbrev_buf();
+ let debug_abbrev = DebugAbbrev::new(abbrevs_buf, LittleEndian);
+
+ let abbrevs = unit
+ .abbreviations(&debug_abbrev)
+ .expect("Should parse abbreviations");
+
+ let mut cursor = unit.entries(&abbrevs);
+
+ assert_next_dfs(&mut cursor, "001", 0);
+ assert_next_dfs(&mut cursor, "002", 1);
+ assert_next_dfs(&mut cursor, "003", 1);
+ assert_next_dfs(&mut cursor, "004", -1);
+ assert_next_dfs(&mut cursor, "005", 1);
+ assert_next_dfs(&mut cursor, "006", 0);
+ assert_next_dfs(&mut cursor, "007", -1);
+ assert_next_dfs(&mut cursor, "008", 1);
+ assert_next_dfs(&mut cursor, "009", 1);
+ assert_next_dfs(&mut cursor, "010", -2);
+
+ assert!(cursor.next_dfs().expect("Should parse next dfs").is_none());
+ assert!(cursor.current().is_none());
+ }
+
+ #[test]
+ fn test_cursor_next_sibling_no_sibling_ptr() {
+ let info_buf = &entries_cursor_tests_debug_info_buf();
+ let debug_info = DebugInfo::new(info_buf, LittleEndian);
+
+ let unit = debug_info
+ .units()
+ .next()
+ .expect("should have a unit result")
+ .expect("and it should be ok");
+
+ let abbrevs_buf = &entries_cursor_tests_abbrev_buf();
+ let debug_abbrev = DebugAbbrev::new(abbrevs_buf, LittleEndian);
+
+ let abbrevs = unit
+ .abbreviations(&debug_abbrev)
+ .expect("Should parse abbreviations");
+
+ let mut cursor = unit.entries(&abbrevs);
+
+ assert_next_dfs(&mut cursor, "001", 0);
+
+ // Down to the first child of the root entry.
+
+ assert_next_dfs(&mut cursor, "002", 1);
+
+ // Now iterate all children of the root via `next_sibling`.
+
+ assert_next_sibling(&mut cursor, "004");
+ assert_next_sibling(&mut cursor, "007");
+ assert_next_sibling(&mut cursor, "010");
+
+ // There should be no more siblings.
+
+ assert!(cursor
+ .next_sibling()
+ .expect("Should parse next sibling")
+ .is_none());
+ assert!(cursor.current().is_none());
+ }
+
+ #[test]
+ fn test_cursor_next_sibling_continuation() {
+ let info_buf = &entries_cursor_tests_debug_info_buf();
+ let debug_info = DebugInfo::new(info_buf, LittleEndian);
+
+ let unit = debug_info
+ .units()
+ .next()
+ .expect("should have a unit result")
+ .expect("and it should be ok");
+
+ let abbrevs_buf = &entries_cursor_tests_abbrev_buf();
+ let debug_abbrev = DebugAbbrev::new(abbrevs_buf, LittleEndian);
+
+ let abbrevs = unit
+ .abbreviations(&debug_abbrev)
+ .expect("Should parse abbreviations");
+
+ let mut cursor = unit.entries(&abbrevs);
+
+ assert_next_dfs(&mut cursor, "001", 0);
+
+ // Down to the first child of the root entry.
+
+ assert_next_dfs(&mut cursor, "002", 1);
+
+ // Get the next sibling, then iterate its children
+
+ assert_next_sibling(&mut cursor, "004");
+ assert_next_dfs(&mut cursor, "005", 1);
+ assert_next_sibling(&mut cursor, "006");
+ assert!(cursor
+ .next_sibling()
+ .expect("Should parse next sibling")
+ .is_none());
+ assert!(cursor
+ .next_sibling()
+ .expect("Should parse next sibling")
+ .is_none());
+ assert!(cursor
+ .next_sibling()
+ .expect("Should parse next sibling")
+ .is_none());
+ assert!(cursor
+ .next_sibling()
+ .expect("Should parse next sibling")
+ .is_none());
+
+ // And we should be able to continue with the children of the root entry.
+
+ assert_next_dfs(&mut cursor, "007", -1);
+ assert_next_sibling(&mut cursor, "010");
+
+ // There should be no more siblings.
+
+ assert!(cursor
+ .next_sibling()
+ .expect("Should parse next sibling")
+ .is_none());
+ assert!(cursor.current().is_none());
+ }
+
+ fn entries_cursor_sibling_abbrev_buf() -> Vec<u8> {
+ #[rustfmt::skip]
+ let section = Section::with_endian(Endian::Little)
+ .abbrev(1, DW_TAG_subprogram, DW_CHILDREN_yes)
+ .abbrev_attr(DW_AT_name, DW_FORM_string)
+ .abbrev_attr(DW_AT_sibling, DW_FORM_ref1)
+ .abbrev_attr_null()
+ .abbrev(2, DW_TAG_subprogram, DW_CHILDREN_yes)
+ .abbrev_attr(DW_AT_name, DW_FORM_string)
+ .abbrev_attr_null()
+ .abbrev_null();
+ section.get_contents().unwrap()
+ }
+
+ fn entries_cursor_sibling_entries_buf(header_size: usize) -> Vec<u8> {
+ let start = Label::new();
+ let sibling004_ref = Label::new();
+ let sibling004 = Label::new();
+ let sibling009_ref = Label::new();
+ let sibling009 = Label::new();
+
+ #[rustfmt::skip]
+ let section = Section::with_endian(Endian::Little)
+ .mark(&start)
+ .die(2, |s| s.attr_string("001"))
+ // Valid sibling attribute.
+ .die(1, |s| s.attr_string("002").D8(&sibling004_ref))
+ // Invalid code to ensure the sibling attribute was used.
+ .die(10, |s| s.attr_string("003"))
+ .die_null()
+ .die_null()
+ .mark(&sibling004)
+ // Invalid sibling attribute.
+ .die(1, |s| s.attr_string("004").attr_ref1(255))
+ .die(2, |s| s.attr_string("005"))
+ .die_null()
+ .die_null()
+ // Sibling attribute in child only.
+ .die(2, |s| s.attr_string("006"))
+ // Valid sibling attribute.
+ .die(1, |s| s.attr_string("007").D8(&sibling009_ref))
+ // Invalid code to ensure the sibling attribute was used.
+ .die(10, |s| s.attr_string("008"))
+ .die_null()
+ .die_null()
+ .mark(&sibling009)
+ .die(2, |s| s.attr_string("009"))
+ .die_null()
+ .die_null()
+ // No sibling attribute.
+ .die(2, |s| s.attr_string("010"))
+ .die(2, |s| s.attr_string("011"))
+ .die_null()
+ .die_null()
+ .die_null();
+
+ let offset = header_size as u64 + (&sibling004 - &start) as u64;
+ sibling004_ref.set_const(offset);
+
+ let offset = header_size as u64 + (&sibling009 - &start) as u64;
+ sibling009_ref.set_const(offset);
+
+ section.get_contents().unwrap()
+ }
+
+ fn test_cursor_next_sibling_with_ptr(cursor: &mut EntriesCursor<EndianSlice<LittleEndian>>) {
+ assert_next_dfs(cursor, "001", 0);
+
+ // Down to the first child of the root.
+
+ assert_next_dfs(cursor, "002", 1);
+
+ // Now iterate all children of the root via `next_sibling`.
+
+ assert_valid_sibling_ptr(&cursor);
+ assert_next_sibling(cursor, "004");
+ assert_next_sibling(cursor, "006");
+ assert_next_sibling(cursor, "010");
+
+ // There should be no more siblings.
+
+ assert!(cursor
+ .next_sibling()
+ .expect("Should parse next sibling")
+ .is_none());
+ assert!(cursor.current().is_none());
+ }
+
+ #[test]
+ fn test_debug_info_next_sibling_with_ptr() {
+ let encoding = Encoding {
+ format: Format::Dwarf32,
+ version: 4,
+ address_size: 4,
+ };
+
+ let mut unit = UnitHeader {
+ encoding,
+ unit_length: 0,
+ unit_type: UnitType::Compilation,
+ debug_abbrev_offset: DebugAbbrevOffset(0),
+ unit_offset: DebugInfoOffset(0).into(),
+ entries_buf: EndianSlice::new(&[], LittleEndian),
+ };
+ let header_size = unit.size_of_header();
+ let entries_buf = entries_cursor_sibling_entries_buf(header_size);
+ unit.entries_buf = EndianSlice::new(&entries_buf, LittleEndian);
+ let section = Section::with_endian(Endian::Little).unit(&mut unit);
+ let info_buf = section.get_contents().unwrap();
+ let debug_info = DebugInfo::new(&info_buf, LittleEndian);
+
+ let unit = debug_info
+ .units()
+ .next()
+ .expect("should have a unit result")
+ .expect("and it should be ok");
+
+ let abbrev_buf = entries_cursor_sibling_abbrev_buf();
+ let debug_abbrev = DebugAbbrev::new(&abbrev_buf, LittleEndian);
+
+ let abbrevs = unit
+ .abbreviations(&debug_abbrev)
+ .expect("Should parse abbreviations");
+
+ let mut cursor = unit.entries(&abbrevs);
+ test_cursor_next_sibling_with_ptr(&mut cursor);
+ }
+
+ #[test]
+ fn test_debug_types_next_sibling_with_ptr() {
+ let encoding = Encoding {
+ format: Format::Dwarf32,
+ version: 4,
+ address_size: 4,
+ };
+ let mut unit = UnitHeader {
+ encoding,
+ unit_length: 0,
+ unit_type: UnitType::Type {
+ type_signature: DebugTypeSignature(0),
+ type_offset: UnitOffset(0),
+ },
+ debug_abbrev_offset: DebugAbbrevOffset(0),
+ unit_offset: DebugTypesOffset(0).into(),
+ entries_buf: EndianSlice::new(&[], LittleEndian),
+ };
+ let header_size = unit.size_of_header();
+ let entries_buf = entries_cursor_sibling_entries_buf(header_size);
+ unit.entries_buf = EndianSlice::new(&entries_buf, LittleEndian);
+ let section = Section::with_endian(Endian::Little).unit(&mut unit);
+ let info_buf = section.get_contents().unwrap();
+ let debug_types = DebugTypes::new(&info_buf, LittleEndian);
+
+ let unit = debug_types
+ .units()
+ .next()
+ .expect("should have a unit result")
+ .expect("and it should be ok");
+
+ let abbrev_buf = entries_cursor_sibling_abbrev_buf();
+ let debug_abbrev = DebugAbbrev::new(&abbrev_buf, LittleEndian);
+
+ let abbrevs = unit
+ .abbreviations(&debug_abbrev)
+ .expect("Should parse abbreviations");
+
+ let mut cursor = unit.entries(&abbrevs);
+ test_cursor_next_sibling_with_ptr(&mut cursor);
+ }
+
+ #[test]
+ fn test_entries_at_offset() {
+ let info_buf = &entries_cursor_tests_debug_info_buf();
+ let debug_info = DebugInfo::new(info_buf, LittleEndian);
+
+ let unit = debug_info
+ .units()
+ .next()
+ .expect("should have a unit result")
+ .expect("and it should be ok");
+
+ let abbrevs_buf = &entries_cursor_tests_abbrev_buf();
+ let debug_abbrev = DebugAbbrev::new(abbrevs_buf, LittleEndian);
+
+ let abbrevs = unit
+ .abbreviations(&debug_abbrev)
+ .expect("Should parse abbreviations");
+
+ let mut cursor = unit
+ .entries_at_offset(&abbrevs, UnitOffset(unit.header_size()))
+ .unwrap();
+ assert_next_entry(&mut cursor, "001");
+
+ let cursor = unit.entries_at_offset(&abbrevs, UnitOffset(0));
+ match cursor {
+ Err(Error::OffsetOutOfBounds) => {}
+ otherwise => {
+ assert!(false, "Unexpected parse result = {:#?}", otherwise);
+ }
+ }
+ }
+
+ fn entries_tree_tests_debug_abbrevs_buf() -> Vec<u8> {
+ #[rustfmt::skip]
+ let section = Section::with_endian(Endian::Little)
+ .abbrev(1, DW_TAG_subprogram, DW_CHILDREN_yes)
+ .abbrev_attr(DW_AT_name, DW_FORM_string)
+ .abbrev_attr_null()
+ .abbrev(2, DW_TAG_subprogram, DW_CHILDREN_no)
+ .abbrev_attr(DW_AT_name, DW_FORM_string)
+ .abbrev_attr_null()
+ .abbrev_null()
+ .get_contents()
+ .unwrap();
+ section
+ }
+
+ fn entries_tree_tests_debug_info_buf(header_size: usize) -> (Vec<u8>, UnitOffset) {
+ let start = Label::new();
+ let entry2 = Label::new();
+ #[rustfmt::skip]
+ let section = Section::with_endian(Endian::Little)
+ .mark(&start)
+ .die(1, |s| s.attr_string("root"))
+ .die(1, |s| s.attr_string("1"))
+ .die(1, |s| s.attr_string("1a"))
+ .die_null()
+ .die(2, |s| s.attr_string("1b"))
+ .die_null()
+ .mark(&entry2)
+ .die(1, |s| s.attr_string("2"))
+ .die(1, |s| s.attr_string("2a"))
+ .die(1, |s| s.attr_string("2a1"))
+ .die_null()
+ .die_null()
+ .die(1, |s| s.attr_string("2b"))
+ .die(2, |s| s.attr_string("2b1"))
+ .die_null()
+ .die_null()
+ .die(1, |s| s.attr_string("3"))
+ .die(1, |s| s.attr_string("3a"))
+ .die(2, |s| s.attr_string("3a1"))
+ .die(2, |s| s.attr_string("3a2"))
+ .die_null()
+ .die(2, |s| s.attr_string("3b"))
+ .die_null()
+ .die(2, |s| s.attr_string("final"))
+ .die_null()
+ .get_contents()
+ .unwrap();
+ let entry2 = UnitOffset(header_size + (&entry2 - &start) as usize);
+ (section, entry2)
+ }
+
+ #[test]
+ fn test_entries_tree() {
+ fn assert_entry<'input, 'abbrev, 'unit, 'tree, Endian>(
+ node: Result<
+ Option<EntriesTreeNode<'abbrev, 'unit, 'tree, EndianSlice<'input, Endian>>>,
+ >,
+ name: &str,
+ ) -> EntriesTreeIter<'abbrev, 'unit, 'tree, EndianSlice<'input, Endian>>
+ where
+ Endian: Endianity,
+ {
+ let node = node
+ .expect("Should parse entry")
+ .expect("Should have entry");
+ assert_entry_name(node.entry(), name);
+ node.children()
+ }
+
+ fn assert_null<E: Endianity>(node: Result<Option<EntriesTreeNode<EndianSlice<E>>>>) {
+ match node {
+ Ok(None) => {}
+ otherwise => {
+ assert!(false, "Unexpected parse result = {:#?}", otherwise);
+ }
+ }
+ }
+
+ let abbrevs_buf = entries_tree_tests_debug_abbrevs_buf();
+ let debug_abbrev = DebugAbbrev::new(&abbrevs_buf, LittleEndian);
+
+ let encoding = Encoding {
+ format: Format::Dwarf32,
+ version: 4,
+ address_size: 4,
+ };
+ let mut unit = UnitHeader {
+ encoding,
+ unit_length: 0,
+ unit_type: UnitType::Compilation,
+ debug_abbrev_offset: DebugAbbrevOffset(0),
+ unit_offset: DebugInfoOffset(0).into(),
+ entries_buf: EndianSlice::new(&[], LittleEndian),
+ };
+ let header_size = unit.size_of_header();
+ let (entries_buf, entry2) = entries_tree_tests_debug_info_buf(header_size);
+ unit.entries_buf = EndianSlice::new(&entries_buf, LittleEndian);
+ let info_buf = Section::with_endian(Endian::Little)
+ .unit(&mut unit)
+ .get_contents()
+ .unwrap();
+ let debug_info = DebugInfo::new(&info_buf, LittleEndian);
+
+ let unit = debug_info
+ .units()
+ .next()
+ .expect("Should parse unit")
+ .expect("and it should be some");
+ let abbrevs = unit
+ .abbreviations(&debug_abbrev)
+ .expect("Should parse abbreviations");
+ let mut tree = unit
+ .entries_tree(&abbrevs, None)
+ .expect("Should have entries tree");
+
+ // Test we can restart iteration of the tree.
+ {
+ let mut iter = assert_entry(tree.root().map(Some), "root");
+ assert_entry(iter.next(), "1");
+ }
+ {
+ let mut iter = assert_entry(tree.root().map(Some), "root");
+ assert_entry(iter.next(), "1");
+ }
+
+ let mut iter = assert_entry(tree.root().map(Some), "root");
+ {
+ // Test iteration with children.
+ let mut iter = assert_entry(iter.next(), "1");
+ {
+ // Test iteration with children flag, but no children.
+ let mut iter = assert_entry(iter.next(), "1a");
+ assert_null(iter.next());
+ assert_null(iter.next());
+ }
+ {
+ // Test iteration without children flag.
+ let mut iter = assert_entry(iter.next(), "1b");
+ assert_null(iter.next());
+ assert_null(iter.next());
+ }
+ assert_null(iter.next());
+ assert_null(iter.next());
+ }
+ {
+ // Test skipping over children.
+ let mut iter = assert_entry(iter.next(), "2");
+ assert_entry(iter.next(), "2a");
+ assert_entry(iter.next(), "2b");
+ assert_null(iter.next());
+ }
+ {
+ // Test skipping after partial iteration.
+ let mut iter = assert_entry(iter.next(), "3");
+ {
+ let mut iter = assert_entry(iter.next(), "3a");
+ assert_entry(iter.next(), "3a1");
+ // Parent iter should be able to skip over "3a2".
+ }
+ assert_entry(iter.next(), "3b");
+ assert_null(iter.next());
+ }
+ assert_entry(iter.next(), "final");
+ assert_null(iter.next());
+
+ // Test starting at an offset.
+ let mut tree = unit
+ .entries_tree(&abbrevs, Some(entry2))
+ .expect("Should have entries tree");
+ let mut iter = assert_entry(tree.root().map(Some), "2");
+ assert_entry(iter.next(), "2a");
+ assert_entry(iter.next(), "2b");
+ assert_null(iter.next());
+ }
+
+ #[test]
+ fn test_entries_raw() {
+ fn assert_abbrev<'input, 'abbrev, 'unit, Endian>(
+ entries: &mut EntriesRaw<'abbrev, 'unit, EndianSlice<'input, Endian>>,
+ tag: DwTag,
+ ) -> &'abbrev Abbreviation
+ where
+ Endian: Endianity,
+ {
+ let abbrev = entries
+ .read_abbreviation()
+ .expect("Should parse abbrev")
+ .expect("Should have abbrev");
+ assert_eq!(abbrev.tag(), tag);
+ abbrev
+ }
+
+ fn assert_null<'input, 'abbrev, 'unit, Endian>(
+ entries: &mut EntriesRaw<'abbrev, 'unit, EndianSlice<'input, Endian>>,
+ ) where
+ Endian: Endianity,
+ {
+ match entries.read_abbreviation() {
+ Ok(None) => {}
+ otherwise => {
+ assert!(false, "Unexpected parse result = {:#?}", otherwise);
+ }
+ }
+ }
+
+ fn assert_attr<'input, 'abbrev, 'unit, Endian>(
+ entries: &mut EntriesRaw<'abbrev, 'unit, EndianSlice<'input, Endian>>,
+ spec: Option<AttributeSpecification>,
+ name: DwAt,
+ value: &str,
+ ) where
+ Endian: Endianity,
+ {
+ let spec = spec.expect("Should have attribute specification");
+ let attr = entries
+ .read_attribute(spec)
+ .expect("Should parse attribute");
+ assert_eq!(attr.name(), name);
+ assert_eq!(
+ attr.value(),
+ AttributeValue::String(EndianSlice::new(value.as_bytes(), Endian::default()))
+ );
+ }
+
+ #[rustfmt::skip]
+ let section = Section::with_endian(Endian::Little)
+ .abbrev(1, DW_TAG_subprogram, DW_CHILDREN_yes)
+ .abbrev_attr(DW_AT_name, DW_FORM_string)
+ .abbrev_attr(DW_AT_linkage_name, DW_FORM_string)
+ .abbrev_attr_null()
+ .abbrev(2, DW_TAG_variable, DW_CHILDREN_no)
+ .abbrev_attr(DW_AT_name, DW_FORM_string)
+ .abbrev_attr_null()
+ .abbrev_null();
+ let abbrevs_buf = section.get_contents().unwrap();
+ let debug_abbrev = DebugAbbrev::new(&abbrevs_buf, LittleEndian);
+
+ #[rustfmt::skip]
+ let section = Section::with_endian(Endian::Little)
+ .die(1, |s| s.attr_string("f1").attr_string("l1"))
+ .die(2, |s| s.attr_string("v1"))
+ .die(2, |s| s.attr_string("v2"))
+ .die(1, |s| s.attr_string("f2").attr_string("l2"))
+ .die_null()
+ .die_null();
+ let entries_buf = section.get_contents().unwrap();
+
+ let encoding = Encoding {
+ format: Format::Dwarf32,
+ version: 4,
+ address_size: 4,
+ };
+ let mut unit = UnitHeader {
+ encoding,
+ unit_length: 0,
+ unit_type: UnitType::Compilation,
+ debug_abbrev_offset: DebugAbbrevOffset(0),
+ unit_offset: DebugInfoOffset(0).into(),
+ entries_buf: EndianSlice::new(&entries_buf, LittleEndian),
+ };
+ let section = Section::with_endian(Endian::Little).unit(&mut unit);
+ let info_buf = section.get_contents().unwrap();
+ let debug_info = DebugInfo::new(&info_buf, LittleEndian);
+
+ let unit = debug_info
+ .units()
+ .next()
+ .expect("should have a unit result")
+ .expect("and it should be ok");
+
+ let abbrevs = unit
+ .abbreviations(&debug_abbrev)
+ .expect("Should parse abbreviations");
+
+ let mut entries = unit
+ .entries_raw(&abbrevs, None)
+ .expect("Should have entries");
+
+ assert_eq!(entries.next_depth(), 0);
+ let abbrev = assert_abbrev(&mut entries, DW_TAG_subprogram);
+ let mut attrs = abbrev.attributes().iter().copied();
+ assert_attr(&mut entries, attrs.next(), DW_AT_name, "f1");
+ assert_attr(&mut entries, attrs.next(), DW_AT_linkage_name, "l1");
+ assert!(attrs.next().is_none());
+
+ assert_eq!(entries.next_depth(), 1);
+ let abbrev = assert_abbrev(&mut entries, DW_TAG_variable);
+ let mut attrs = abbrev.attributes().iter().copied();
+ assert_attr(&mut entries, attrs.next(), DW_AT_name, "v1");
+ assert!(attrs.next().is_none());
+
+ assert_eq!(entries.next_depth(), 1);
+ let abbrev = assert_abbrev(&mut entries, DW_TAG_variable);
+ let mut attrs = abbrev.attributes().iter().copied();
+ assert_attr(&mut entries, attrs.next(), DW_AT_name, "v2");
+ assert!(attrs.next().is_none());
+
+ assert_eq!(entries.next_depth(), 1);
+ let abbrev = assert_abbrev(&mut entries, DW_TAG_subprogram);
+ let mut attrs = abbrev.attributes().iter().copied();
+ assert_attr(&mut entries, attrs.next(), DW_AT_name, "f2");
+ assert_attr(&mut entries, attrs.next(), DW_AT_linkage_name, "l2");
+ assert!(attrs.next().is_none());
+
+ assert_eq!(entries.next_depth(), 2);
+ assert_null(&mut entries);
+
+ assert_eq!(entries.next_depth(), 1);
+ assert_null(&mut entries);
+
+ assert_eq!(entries.next_depth(), 0);
+ assert!(entries.is_empty());
+ }
+
+ #[test]
+ fn test_debug_info_offset() {
+ let padding = &[0; 10];
+ let entries = &[0; 20];
+ let encoding = Encoding {
+ format: Format::Dwarf32,
+ version: 4,
+ address_size: 4,
+ };
+ let mut unit = UnitHeader {
+ encoding,
+ unit_length: 0,
+ unit_type: UnitType::Compilation,
+ debug_abbrev_offset: DebugAbbrevOffset(0),
+ unit_offset: DebugInfoOffset(0).into(),
+ entries_buf: EndianSlice::new(entries, LittleEndian),
+ };
+ Section::with_endian(Endian::Little)
+ .append_bytes(padding)
+ .unit(&mut unit);
+ let offset = padding.len();
+ let header_length = unit.size_of_header();
+ let length = unit.length_including_self();
+ assert_eq!(DebugInfoOffset(0).to_unit_offset(&unit), None);
+ assert_eq!(DebugInfoOffset(offset - 1).to_unit_offset(&unit), None);
+ assert_eq!(DebugInfoOffset(offset).to_unit_offset(&unit), None);
+ assert_eq!(
+ DebugInfoOffset(offset + header_length - 1).to_unit_offset(&unit),
+ None
+ );
+ assert_eq!(
+ DebugInfoOffset(offset + header_length).to_unit_offset(&unit),
+ Some(UnitOffset(header_length))
+ );
+ assert_eq!(
+ DebugInfoOffset(offset + length - 1).to_unit_offset(&unit),
+ Some(UnitOffset(length - 1))
+ );
+ assert_eq!(DebugInfoOffset(offset + length).to_unit_offset(&unit), None);
+ assert_eq!(
+ UnitOffset(header_length).to_debug_info_offset(&unit),
+ Some(DebugInfoOffset(offset + header_length))
+ );
+ assert_eq!(
+ UnitOffset(length - 1).to_debug_info_offset(&unit),
+ Some(DebugInfoOffset(offset + length - 1))
+ );
+ }
+
+ #[test]
+ fn test_debug_types_offset() {
+ let padding = &[0; 10];
+ let entries = &[0; 20];
+ let encoding = Encoding {
+ format: Format::Dwarf32,
+ version: 4,
+ address_size: 4,
+ };
+ let mut unit = UnitHeader {
+ encoding,
+ unit_length: 0,
+ unit_type: UnitType::Type {
+ type_signature: DebugTypeSignature(0),
+ type_offset: UnitOffset(0),
+ },
+ debug_abbrev_offset: DebugAbbrevOffset(0),
+ unit_offset: DebugTypesOffset(0).into(),
+ entries_buf: EndianSlice::new(entries, LittleEndian),
+ };
+ Section::with_endian(Endian::Little)
+ .append_bytes(padding)
+ .unit(&mut unit);
+ let offset = padding.len();
+ let header_length = unit.size_of_header();
+ let length = unit.length_including_self();
+ assert_eq!(DebugTypesOffset(0).to_unit_offset(&unit), None);
+ assert_eq!(DebugTypesOffset(offset - 1).to_unit_offset(&unit), None);
+ assert_eq!(DebugTypesOffset(offset).to_unit_offset(&unit), None);
+ assert_eq!(
+ DebugTypesOffset(offset + header_length - 1).to_unit_offset(&unit),
+ None
+ );
+ assert_eq!(
+ DebugTypesOffset(offset + header_length).to_unit_offset(&unit),
+ Some(UnitOffset(header_length))
+ );
+ assert_eq!(
+ DebugTypesOffset(offset + length - 1).to_unit_offset(&unit),
+ Some(UnitOffset(length - 1))
+ );
+ assert_eq!(
+ DebugTypesOffset(offset + length).to_unit_offset(&unit),
+ None
+ );
+ assert_eq!(
+ UnitOffset(header_length).to_debug_types_offset(&unit),
+ Some(DebugTypesOffset(offset + header_length))
+ );
+ assert_eq!(
+ UnitOffset(length - 1).to_debug_types_offset(&unit),
+ Some(DebugTypesOffset(offset + length - 1))
+ );
+ }
+
+ #[test]
+ fn test_length_including_self() {
+ let encoding = Encoding {
+ format: Format::Dwarf32,
+ version: 4,
+ address_size: 4,
+ };
+ let mut unit = UnitHeader {
+ encoding,
+ unit_length: 0,
+ unit_type: UnitType::Compilation,
+ debug_abbrev_offset: DebugAbbrevOffset(0),
+ unit_offset: DebugInfoOffset(0).into(),
+ entries_buf: EndianSlice::new(&[], LittleEndian),
+ };
+ unit.encoding.format = Format::Dwarf32;
+ assert_eq!(unit.length_including_self(), 4);
+ unit.encoding.format = Format::Dwarf64;
+ assert_eq!(unit.length_including_self(), 12);
+ unit.unit_length = 10;
+ assert_eq!(unit.length_including_self(), 22);
+ }
+
+ #[test]
+ fn test_parse_type_unit_abbrevs() {
+ let types_buf = [
+ // Type unit header
+ 0x25, 0x00, 0x00, 0x00, // 32-bit unit length = 37
+ 0x04, 0x00, // Version 4
+ 0x00, 0x00, 0x00, 0x00, // debug_abbrev_offset
+ 0x04, // Address size
+ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, // Type signature
+ 0x01, 0x02, 0x03, 0x04, // Type offset
+ // DIEs
+ // Abbreviation code
+ 0x01, // Attribute of form DW_FORM_string = "foo\0"
+ 0x66, 0x6f, 0x6f, 0x00, // Children
+ // Abbreviation code
+ 0x01, // Attribute of form DW_FORM_string = "foo\0"
+ 0x66, 0x6f, 0x6f, 0x00, // Children
+ // Abbreviation code
+ 0x01, // Attribute of form DW_FORM_string = "foo\0"
+ 0x66, 0x6f, 0x6f, 0x00, // Children
+ 0x00, // End of children
+ 0x00, // End of children
+ 0x00, // End of children
+ ];
+ let debug_types = DebugTypes::new(&types_buf, LittleEndian);
+
+ let abbrev_buf = [
+ // Code
+ 0x01, // DW_TAG_subprogram
+ 0x2e, // DW_CHILDREN_yes
+ 0x01, // Begin attributes
+ 0x03, // Attribute name = DW_AT_name
+ 0x08, // Attribute form = DW_FORM_string
+ 0x00, 0x00, // End attributes
+ 0x00, // Null terminator
+ ];
+
+ let get_some_type_unit = || debug_types.units().next().unwrap().unwrap();
+
+ let unit = get_some_type_unit();
+
+ let read_debug_abbrev_section_somehow = || &abbrev_buf;
+ let debug_abbrev = DebugAbbrev::new(read_debug_abbrev_section_somehow(), LittleEndian);
+ let _abbrevs_for_unit = unit.abbreviations(&debug_abbrev).unwrap();
+ }
+}
diff --git a/vendor/gimli-0.26.2/src/read/util.rs b/vendor/gimli-0.26.2/src/read/util.rs
new file mode 100644
index 000000000..16eafdde4
--- /dev/null
+++ b/vendor/gimli-0.26.2/src/read/util.rs
@@ -0,0 +1,250 @@
+#[cfg(feature = "read")]
+use alloc::boxed::Box;
+#[cfg(feature = "read")]
+use alloc::vec::Vec;
+use core::fmt;
+use core::mem::MaybeUninit;
+use core::ops;
+use core::ptr;
+use core::slice;
+
+mod sealed {
+ // SAFETY: Implementer must not modify the content in storage.
+ pub unsafe trait Sealed {
+ type Storage;
+
+ fn new_storage() -> Self::Storage;
+
+ fn grow(_storage: &mut Self::Storage, _additional: usize) -> Result<(), CapacityFull> {
+ Err(CapacityFull)
+ }
+ }
+
+ #[derive(Clone, Copy, Debug)]
+ pub struct CapacityFull;
+}
+
+use sealed::*;
+
+/// Marker trait for types that can be used as backing storage when a growable array type is needed.
+///
+/// This trait is sealed and cannot be implemented for types outside this crate.
+pub trait ArrayLike: Sealed {
+ /// Type of the elements being stored.
+ type Item;
+
+ #[doc(hidden)]
+ fn as_slice(storage: &Self::Storage) -> &[MaybeUninit<Self::Item>];
+
+ #[doc(hidden)]
+ fn as_mut_slice(storage: &mut Self::Storage) -> &mut [MaybeUninit<Self::Item>];
+}
+
+// Use macro since const generics can't be used due to MSRV.
+macro_rules! impl_array {
+ () => {};
+ ($n:literal $($rest:tt)*) => {
+ // SAFETY: does not modify the content in storage.
+ unsafe impl<T> Sealed for [T; $n] {
+ type Storage = [MaybeUninit<T>; $n];
+
+ fn new_storage() -> Self::Storage {
+ // SAFETY: An uninitialized `[MaybeUninit<_>; _]` is valid.
+ unsafe { MaybeUninit::uninit().assume_init() }
+ }
+ }
+
+ impl<T> ArrayLike for [T; $n] {
+ type Item = T;
+
+ fn as_slice(storage: &Self::Storage) -> &[MaybeUninit<T>] {
+ storage
+ }
+
+ fn as_mut_slice(storage: &mut Self::Storage) -> &mut [MaybeUninit<T>] {
+ storage
+ }
+ }
+
+ impl_array!($($rest)*);
+ }
+}
+
+impl_array!(0 1 2 3 4 8 16 32 64 128 192);
+
+#[cfg(feature = "read")]
+unsafe impl<T> Sealed for Vec<T> {
+ type Storage = Box<[MaybeUninit<T>]>;
+
+ fn new_storage() -> Self::Storage {
+ Box::new([])
+ }
+
+ fn grow(storage: &mut Self::Storage, additional: usize) -> Result<(), CapacityFull> {
+ let mut vec: Vec<_> = core::mem::replace(storage, Box::new([])).into();
+ vec.reserve(additional);
+ // SAFETY: This is a `Vec` of `MaybeUninit`.
+ unsafe { vec.set_len(vec.capacity()) };
+ *storage = vec.into_boxed_slice();
+ Ok(())
+ }
+}
+
+#[cfg(feature = "read")]
+impl<T> ArrayLike for Vec<T> {
+ type Item = T;
+
+ fn as_slice(storage: &Self::Storage) -> &[MaybeUninit<T>] {
+ storage
+ }
+
+ fn as_mut_slice(storage: &mut Self::Storage) -> &mut [MaybeUninit<T>] {
+ storage
+ }
+}
+
+pub(crate) struct ArrayVec<A: ArrayLike> {
+ storage: A::Storage,
+ len: usize,
+}
+
+impl<A: ArrayLike> ArrayVec<A> {
+ pub fn new() -> Self {
+ Self {
+ storage: A::new_storage(),
+ len: 0,
+ }
+ }
+
+ pub fn clear(&mut self) {
+ let ptr: *mut [A::Item] = &mut **self;
+ // Set length first so the type invariant is upheld even if `drop_in_place` panicks.
+ self.len = 0;
+ // SAFETY: `ptr` contains valid elements only and we "forget" them by setting the length.
+ unsafe { ptr::drop_in_place(ptr) };
+ }
+
+ pub fn try_push(&mut self, value: A::Item) -> Result<(), CapacityFull> {
+ let mut storage = A::as_mut_slice(&mut self.storage);
+ if self.len >= storage.len() {
+ A::grow(&mut self.storage, 1)?;
+ storage = A::as_mut_slice(&mut self.storage);
+ }
+
+ storage[self.len] = MaybeUninit::new(value);
+ self.len += 1;
+ Ok(())
+ }
+
+ pub fn try_insert(&mut self, index: usize, element: A::Item) -> Result<(), CapacityFull> {
+ assert!(index <= self.len);
+
+ let mut storage = A::as_mut_slice(&mut self.storage);
+ if self.len >= storage.len() {
+ A::grow(&mut self.storage, 1)?;
+ storage = A::as_mut_slice(&mut self.storage);
+ }
+
+ // SAFETY: storage[index] is filled later.
+ unsafe {
+ let p = storage.as_mut_ptr().add(index);
+ core::ptr::copy(p as *const _, p.add(1), self.len - index);
+ }
+ storage[index] = MaybeUninit::new(element);
+ self.len += 1;
+ Ok(())
+ }
+
+ pub fn pop(&mut self) -> Option<A::Item> {
+ if self.len == 0 {
+ None
+ } else {
+ self.len -= 1;
+ // SAFETY: this element is valid and we "forget" it by setting the length.
+ Some(unsafe { A::as_slice(&mut self.storage)[self.len].as_ptr().read() })
+ }
+ }
+
+ pub fn swap_remove(&mut self, index: usize) -> A::Item {
+ assert!(self.len > 0);
+ A::as_mut_slice(&mut self.storage).swap(index, self.len - 1);
+ self.pop().unwrap()
+ }
+}
+
+#[cfg(feature = "read")]
+impl<T> ArrayVec<Vec<T>> {
+ pub fn into_vec(mut self) -> Vec<T> {
+ let len = core::mem::replace(&mut self.len, 0);
+ let storage = core::mem::replace(&mut self.storage, Box::new([]));
+ let slice = Box::leak(storage);
+ debug_assert!(len <= slice.len());
+ // SAFETY: valid elements.
+ unsafe { Vec::from_raw_parts(slice.as_mut_ptr() as *mut T, len, slice.len()) }
+ }
+}
+
+impl<A: ArrayLike> Drop for ArrayVec<A> {
+ fn drop(&mut self) {
+ self.clear();
+ }
+}
+
+impl<A: ArrayLike> Default for ArrayVec<A> {
+ fn default() -> Self {
+ Self::new()
+ }
+}
+
+impl<A: ArrayLike> ops::Deref for ArrayVec<A> {
+ type Target = [A::Item];
+
+ fn deref(&self) -> &[A::Item] {
+ let slice = &A::as_slice(&self.storage);
+ debug_assert!(self.len <= slice.len());
+ // SAFETY: valid elements.
+ unsafe { slice::from_raw_parts(slice.as_ptr() as _, self.len) }
+ }
+}
+
+impl<A: ArrayLike> ops::DerefMut for ArrayVec<A> {
+ fn deref_mut(&mut self) -> &mut [A::Item] {
+ let slice = &mut A::as_mut_slice(&mut self.storage);
+ debug_assert!(self.len <= slice.len());
+ // SAFETY: valid elements.
+ unsafe { slice::from_raw_parts_mut(slice.as_mut_ptr() as _, self.len) }
+ }
+}
+
+impl<A: ArrayLike> Clone for ArrayVec<A>
+where
+ A::Item: Clone,
+{
+ fn clone(&self) -> Self {
+ let mut new = Self::default();
+ for value in &**self {
+ new.try_push(value.clone()).unwrap();
+ }
+ new
+ }
+}
+
+impl<A: ArrayLike> PartialEq for ArrayVec<A>
+where
+ A::Item: PartialEq,
+{
+ fn eq(&self, other: &Self) -> bool {
+ **self == **other
+ }
+}
+
+impl<A: ArrayLike> Eq for ArrayVec<A> where A::Item: Eq {}
+
+impl<A: ArrayLike> fmt::Debug for ArrayVec<A>
+where
+ A::Item: fmt::Debug,
+{
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ fmt::Debug::fmt(&**self, f)
+ }
+}
diff --git a/vendor/gimli-0.26.2/src/read/value.rs b/vendor/gimli-0.26.2/src/read/value.rs
new file mode 100644
index 000000000..6f43ebb26
--- /dev/null
+++ b/vendor/gimli-0.26.2/src/read/value.rs
@@ -0,0 +1,1621 @@
+//! Definitions for values used in DWARF expressions.
+
+use crate::constants;
+#[cfg(feature = "read")]
+use crate::read::{AttributeValue, DebuggingInformationEntry};
+use crate::read::{Error, Reader, Result};
+
+/// Convert a u64 to an i64, with sign extension if required.
+///
+/// This is primarily used when needing to treat `Value::Generic`
+/// as a signed value.
+#[inline]
+fn sign_extend(value: u64, mask: u64) -> i64 {
+ let value = (value & mask) as i64;
+ let sign = ((mask >> 1) + 1) as i64;
+ (value ^ sign).wrapping_sub(sign)
+}
+
+#[inline]
+fn mask_bit_size(addr_mask: u64) -> u32 {
+ 64 - addr_mask.leading_zeros()
+}
+
+/// The type of an entry on the DWARF stack.
+#[derive(Debug, Clone, Copy, PartialEq, Eq)]
+pub enum ValueType {
+ /// The generic type, which is address-sized and of unspecified sign,
+ /// as specified in the DWARF 5 standard, section 2.5.1.
+ /// This type is also used to represent address base types.
+ Generic,
+ /// Signed 8-bit integer type.
+ I8,
+ /// Unsigned 8-bit integer type.
+ U8,
+ /// Signed 16-bit integer type.
+ I16,
+ /// Unsigned 16-bit integer type.
+ U16,
+ /// Signed 32-bit integer type.
+ I32,
+ /// Unsigned 32-bit integer type.
+ U32,
+ /// Signed 64-bit integer type.
+ I64,
+ /// Unsigned 64-bit integer type.
+ U64,
+ /// 32-bit floating point type.
+ F32,
+ /// 64-bit floating point type.
+ F64,
+}
+
+/// The value of an entry on the DWARF stack.
+#[derive(Debug, Clone, Copy, PartialEq)]
+pub enum Value {
+ /// A generic value, which is address-sized and of unspecified sign.
+ Generic(u64),
+ /// A signed 8-bit integer value.
+ I8(i8),
+ /// An unsigned 8-bit integer value.
+ U8(u8),
+ /// A signed 16-bit integer value.
+ I16(i16),
+ /// An unsigned 16-bit integer value.
+ U16(u16),
+ /// A signed 32-bit integer value.
+ I32(i32),
+ /// An unsigned 32-bit integer value.
+ U32(u32),
+ /// A signed 64-bit integer value.
+ I64(i64),
+ /// An unsigned 64-bit integer value.
+ U64(u64),
+ /// A 32-bit floating point value.
+ F32(f32),
+ /// A 64-bit floating point value.
+ F64(f64),
+}
+
+impl ValueType {
+ /// The size in bits of a value for this type.
+ pub fn bit_size(self, addr_mask: u64) -> u32 {
+ match self {
+ ValueType::Generic => mask_bit_size(addr_mask),
+ ValueType::I8 | ValueType::U8 => 8,
+ ValueType::I16 | ValueType::U16 => 16,
+ ValueType::I32 | ValueType::U32 | ValueType::F32 => 32,
+ ValueType::I64 | ValueType::U64 | ValueType::F64 => 64,
+ }
+ }
+
+ /// Construct a `ValueType` from the attributes of a base type DIE.
+ pub fn from_encoding(encoding: constants::DwAte, byte_size: u64) -> Option<ValueType> {
+ Some(match (encoding, byte_size) {
+ (constants::DW_ATE_signed, 1) => ValueType::I8,
+ (constants::DW_ATE_signed, 2) => ValueType::I16,
+ (constants::DW_ATE_signed, 4) => ValueType::I32,
+ (constants::DW_ATE_signed, 8) => ValueType::I64,
+ (constants::DW_ATE_unsigned, 1) => ValueType::U8,
+ (constants::DW_ATE_unsigned, 2) => ValueType::U16,
+ (constants::DW_ATE_unsigned, 4) => ValueType::U32,
+ (constants::DW_ATE_unsigned, 8) => ValueType::U64,
+ (constants::DW_ATE_float, 4) => ValueType::F32,
+ (constants::DW_ATE_float, 8) => ValueType::F64,
+ _ => return None,
+ })
+ }
+
+ /// Construct a `ValueType` from a base type DIE.
+ #[cfg(feature = "read")]
+ pub fn from_entry<R: Reader>(
+ entry: &DebuggingInformationEntry<R>,
+ ) -> Result<Option<ValueType>> {
+ if entry.tag() != constants::DW_TAG_base_type {
+ return Ok(None);
+ }
+ let mut encoding = None;
+ let mut byte_size = None;
+ let mut endianity = constants::DW_END_default;
+ let mut attrs = entry.attrs();
+ while let Some(attr) = attrs.next()? {
+ match attr.name() {
+ constants::DW_AT_byte_size => byte_size = attr.udata_value(),
+ constants::DW_AT_encoding => {
+ if let AttributeValue::Encoding(x) = attr.value() {
+ encoding = Some(x);
+ }
+ }
+ constants::DW_AT_endianity => {
+ if let AttributeValue::Endianity(x) = attr.value() {
+ endianity = x;
+ }
+ }
+ _ => {}
+ }
+ }
+
+ if endianity != constants::DW_END_default {
+ // TODO: we could check if it matches the reader endianity,
+ // but normally it would use DW_END_default in that case.
+ return Ok(None);
+ }
+
+ if let (Some(encoding), Some(byte_size)) = (encoding, byte_size) {
+ Ok(ValueType::from_encoding(encoding, byte_size))
+ } else {
+ Ok(None)
+ }
+ }
+}
+
+impl Value {
+ /// Return the `ValueType` corresponding to this `Value`.
+ pub fn value_type(&self) -> ValueType {
+ match *self {
+ Value::Generic(_) => ValueType::Generic,
+ Value::I8(_) => ValueType::I8,
+ Value::U8(_) => ValueType::U8,
+ Value::I16(_) => ValueType::I16,
+ Value::U16(_) => ValueType::U16,
+ Value::I32(_) => ValueType::I32,
+ Value::U32(_) => ValueType::U32,
+ Value::I64(_) => ValueType::I64,
+ Value::U64(_) => ValueType::U64,
+ Value::F32(_) => ValueType::F32,
+ Value::F64(_) => ValueType::F64,
+ }
+ }
+
+ /// Read a `Value` with the given `value_type` from a `Reader`.
+ pub fn parse<R: Reader>(value_type: ValueType, mut bytes: R) -> Result<Value> {
+ let value = match value_type {
+ ValueType::I8 => Value::I8(bytes.read_i8()?),
+ ValueType::U8 => Value::U8(bytes.read_u8()?),
+ ValueType::I16 => Value::I16(bytes.read_i16()?),
+ ValueType::U16 => Value::U16(bytes.read_u16()?),
+ ValueType::I32 => Value::I32(bytes.read_i32()?),
+ ValueType::U32 => Value::U32(bytes.read_u32()?),
+ ValueType::I64 => Value::I64(bytes.read_i64()?),
+ ValueType::U64 => Value::U64(bytes.read_u64()?),
+ ValueType::F32 => Value::F32(bytes.read_f32()?),
+ ValueType::F64 => Value::F64(bytes.read_f64()?),
+ _ => return Err(Error::UnsupportedTypeOperation),
+ };
+ Ok(value)
+ }
+
+ /// Convert a `Value` to a `u64`.
+ ///
+ /// The `ValueType` of `self` must be integral.
+ /// Values are sign extended if the source value is signed.
+ pub fn to_u64(self, addr_mask: u64) -> Result<u64> {
+ let value = match self {
+ Value::Generic(value) => value & addr_mask,
+ Value::I8(value) => value as u64,
+ Value::U8(value) => u64::from(value),
+ Value::I16(value) => value as u64,
+ Value::U16(value) => u64::from(value),
+ Value::I32(value) => value as u64,
+ Value::U32(value) => u64::from(value),
+ Value::I64(value) => value as u64,
+ Value::U64(value) => value as u64,
+ _ => return Err(Error::IntegralTypeRequired),
+ };
+ Ok(value)
+ }
+
+ /// Create a `Value` with the given `value_type` from a `u64` value.
+ ///
+ /// The `value_type` may be integral or floating point.
+ /// The result is truncated if the `u64` value does
+ /// not fit the bounds of the `value_type`.
+ pub fn from_u64(value_type: ValueType, value: u64) -> Result<Value> {
+ let value = match value_type {
+ ValueType::Generic => Value::Generic(value),
+ ValueType::I8 => Value::I8(value as i8),
+ ValueType::U8 => Value::U8(value as u8),
+ ValueType::I16 => Value::I16(value as i16),
+ ValueType::U16 => Value::U16(value as u16),
+ ValueType::I32 => Value::I32(value as i32),
+ ValueType::U32 => Value::U32(value as u32),
+ ValueType::I64 => Value::I64(value as i64),
+ ValueType::U64 => Value::U64(value),
+ ValueType::F32 => Value::F32(value as f32),
+ ValueType::F64 => Value::F64(value as f64),
+ };
+ Ok(value)
+ }
+
+ /// Create a `Value` with the given `value_type` from a `f32` value.
+ ///
+ /// The `value_type` may be integral or floating point.
+ /// The result is not defined if the `f32` value does
+ /// not fit the bounds of the `value_type`.
+ fn from_f32(value_type: ValueType, value: f32) -> Result<Value> {
+ let value = match value_type {
+ ValueType::Generic => Value::Generic(value as u64),
+ ValueType::I8 => Value::I8(value as i8),
+ ValueType::U8 => Value::U8(value as u8),
+ ValueType::I16 => Value::I16(value as i16),
+ ValueType::U16 => Value::U16(value as u16),
+ ValueType::I32 => Value::I32(value as i32),
+ ValueType::U32 => Value::U32(value as u32),
+ ValueType::I64 => Value::I64(value as i64),
+ ValueType::U64 => Value::U64(value as u64),
+ ValueType::F32 => Value::F32(value),
+ ValueType::F64 => Value::F64(f64::from(value)),
+ };
+ Ok(value)
+ }
+
+ /// Create a `Value` with the given `value_type` from a `f64` value.
+ ///
+ /// The `value_type` may be integral or floating point.
+ /// The result is not defined if the `f64` value does
+ /// not fit the bounds of the `value_type`.
+ fn from_f64(value_type: ValueType, value: f64) -> Result<Value> {
+ let value = match value_type {
+ ValueType::Generic => Value::Generic(value as u64),
+ ValueType::I8 => Value::I8(value as i8),
+ ValueType::U8 => Value::U8(value as u8),
+ ValueType::I16 => Value::I16(value as i16),
+ ValueType::U16 => Value::U16(value as u16),
+ ValueType::I32 => Value::I32(value as i32),
+ ValueType::U32 => Value::U32(value as u32),
+ ValueType::I64 => Value::I64(value as i64),
+ ValueType::U64 => Value::U64(value as u64),
+ ValueType::F32 => Value::F32(value as f32),
+ ValueType::F64 => Value::F64(value),
+ };
+ Ok(value)
+ }
+
+ /// Convert a `Value` to the given `value_type`.
+ ///
+ /// When converting between integral types, the result is truncated
+ /// if the source value does not fit the bounds of the `value_type`.
+ /// When converting from floating point types, the result is not defined
+ /// if the source value does not fit the bounds of the `value_type`.
+ ///
+ /// This corresponds to the DWARF `DW_OP_convert` operation.
+ pub fn convert(self, value_type: ValueType, addr_mask: u64) -> Result<Value> {
+ match self {
+ Value::F32(value) => Value::from_f32(value_type, value),
+ Value::F64(value) => Value::from_f64(value_type, value),
+ _ => Value::from_u64(value_type, self.to_u64(addr_mask)?),
+ }
+ }
+
+ /// Reinterpret the bits in a `Value` as the given `value_type`.
+ ///
+ /// The source and result value types must have equal sizes.
+ ///
+ /// This corresponds to the DWARF `DW_OP_reinterpret` operation.
+ pub fn reinterpret(self, value_type: ValueType, addr_mask: u64) -> Result<Value> {
+ if self.value_type().bit_size(addr_mask) != value_type.bit_size(addr_mask) {
+ return Err(Error::TypeMismatch);
+ }
+ let bits = match self {
+ Value::Generic(value) => value,
+ Value::I8(value) => value as u64,
+ Value::U8(value) => u64::from(value),
+ Value::I16(value) => value as u64,
+ Value::U16(value) => u64::from(value),
+ Value::I32(value) => value as u64,
+ Value::U32(value) => u64::from(value),
+ Value::I64(value) => value as u64,
+ Value::U64(value) => value,
+ Value::F32(value) => u64::from(f32::to_bits(value)),
+ Value::F64(value) => f64::to_bits(value),
+ };
+ let value = match value_type {
+ ValueType::Generic => Value::Generic(bits),
+ ValueType::I8 => Value::I8(bits as i8),
+ ValueType::U8 => Value::U8(bits as u8),
+ ValueType::I16 => Value::I16(bits as i16),
+ ValueType::U16 => Value::U16(bits as u16),
+ ValueType::I32 => Value::I32(bits as i32),
+ ValueType::U32 => Value::U32(bits as u32),
+ ValueType::I64 => Value::I64(bits as i64),
+ ValueType::U64 => Value::U64(bits),
+ ValueType::F32 => Value::F32(f32::from_bits(bits as u32)),
+ ValueType::F64 => Value::F64(f64::from_bits(bits)),
+ };
+ Ok(value)
+ }
+
+ /// Perform an absolute value operation.
+ ///
+ /// If the value type is `Generic`, then it is interpreted as a signed value.
+ ///
+ /// This corresponds to the DWARF `DW_OP_abs` operation.
+ pub fn abs(self, addr_mask: u64) -> Result<Value> {
+ // wrapping_abs() can be used because DWARF specifies that the result is undefined
+ // for negative minimal values.
+ let value = match self {
+ Value::Generic(value) => {
+ Value::Generic(sign_extend(value, addr_mask).wrapping_abs() as u64)
+ }
+ Value::I8(value) => Value::I8(value.wrapping_abs()),
+ Value::I16(value) => Value::I16(value.wrapping_abs()),
+ Value::I32(value) => Value::I32(value.wrapping_abs()),
+ Value::I64(value) => Value::I64(value.wrapping_abs()),
+ // f32/f64::abs() is not available in libcore
+ Value::F32(value) => Value::F32(if value < 0. { -value } else { value }),
+ Value::F64(value) => Value::F64(if value < 0. { -value } else { value }),
+ Value::U8(_) | Value::U16(_) | Value::U32(_) | Value::U64(_) => self,
+ };
+ Ok(value)
+ }
+
+ /// Perform a negation operation.
+ ///
+ /// If the value type is `Generic`, then it is interpreted as a signed value.
+ ///
+ /// This corresponds to the DWARF `DW_OP_neg` operation.
+ pub fn neg(self, addr_mask: u64) -> Result<Value> {
+ // wrapping_neg() can be used because DWARF specifies that the result is undefined
+ // for negative minimal values.
+ let value = match self {
+ Value::Generic(value) => {
+ Value::Generic(sign_extend(value, addr_mask).wrapping_neg() as u64)
+ }
+ Value::I8(value) => Value::I8(value.wrapping_neg()),
+ Value::I16(value) => Value::I16(value.wrapping_neg()),
+ Value::I32(value) => Value::I32(value.wrapping_neg()),
+ Value::I64(value) => Value::I64(value.wrapping_neg()),
+ Value::F32(value) => Value::F32(-value),
+ Value::F64(value) => Value::F64(-value),
+ // It's unclear if these should implicity convert to a signed value.
+ // For now, we don't support them.
+ Value::U8(_) | Value::U16(_) | Value::U32(_) | Value::U64(_) => {
+ return Err(Error::UnsupportedTypeOperation);
+ }
+ };
+ Ok(value)
+ }
+
+ /// Perform an addition operation.
+ ///
+ /// This operation requires matching types.
+ ///
+ /// This corresponds to the DWARF `DW_OP_plus` operation.
+ pub fn add(self, rhs: Value, addr_mask: u64) -> Result<Value> {
+ let value = match (self, rhs) {
+ (Value::Generic(v1), Value::Generic(v2)) => {
+ Value::Generic(v1.wrapping_add(v2) & addr_mask)
+ }
+ (Value::I8(v1), Value::I8(v2)) => Value::I8(v1.wrapping_add(v2)),
+ (Value::U8(v1), Value::U8(v2)) => Value::U8(v1.wrapping_add(v2)),
+ (Value::I16(v1), Value::I16(v2)) => Value::I16(v1.wrapping_add(v2)),
+ (Value::U16(v1), Value::U16(v2)) => Value::U16(v1.wrapping_add(v2)),
+ (Value::I32(v1), Value::I32(v2)) => Value::I32(v1.wrapping_add(v2)),
+ (Value::U32(v1), Value::U32(v2)) => Value::U32(v1.wrapping_add(v2)),
+ (Value::I64(v1), Value::I64(v2)) => Value::I64(v1.wrapping_add(v2)),
+ (Value::U64(v1), Value::U64(v2)) => Value::U64(v1.wrapping_add(v2)),
+ (Value::F32(v1), Value::F32(v2)) => Value::F32(v1 + v2),
+ (Value::F64(v1), Value::F64(v2)) => Value::F64(v1 + v2),
+ _ => return Err(Error::TypeMismatch),
+ };
+ Ok(value)
+ }
+
+ /// Perform a subtraction operation.
+ ///
+ /// This operation requires matching types.
+ ///
+ /// This corresponds to the DWARF `DW_OP_minus` operation.
+ pub fn sub(self, rhs: Value, addr_mask: u64) -> Result<Value> {
+ let value = match (self, rhs) {
+ (Value::Generic(v1), Value::Generic(v2)) => {
+ Value::Generic(v1.wrapping_sub(v2) & addr_mask)
+ }
+ (Value::I8(v1), Value::I8(v2)) => Value::I8(v1.wrapping_sub(v2)),
+ (Value::U8(v1), Value::U8(v2)) => Value::U8(v1.wrapping_sub(v2)),
+ (Value::I16(v1), Value::I16(v2)) => Value::I16(v1.wrapping_sub(v2)),
+ (Value::U16(v1), Value::U16(v2)) => Value::U16(v1.wrapping_sub(v2)),
+ (Value::I32(v1), Value::I32(v2)) => Value::I32(v1.wrapping_sub(v2)),
+ (Value::U32(v1), Value::U32(v2)) => Value::U32(v1.wrapping_sub(v2)),
+ (Value::I64(v1), Value::I64(v2)) => Value::I64(v1.wrapping_sub(v2)),
+ (Value::U64(v1), Value::U64(v2)) => Value::U64(v1.wrapping_sub(v2)),
+ (Value::F32(v1), Value::F32(v2)) => Value::F32(v1 - v2),
+ (Value::F64(v1), Value::F64(v2)) => Value::F64(v1 - v2),
+ _ => return Err(Error::TypeMismatch),
+ };
+ Ok(value)
+ }
+
+ /// Perform a multiplication operation.
+ ///
+ /// This operation requires matching types.
+ ///
+ /// This corresponds to the DWARF `DW_OP_mul` operation.
+ pub fn mul(self, rhs: Value, addr_mask: u64) -> Result<Value> {
+ let value = match (self, rhs) {
+ (Value::Generic(v1), Value::Generic(v2)) => {
+ Value::Generic(v1.wrapping_mul(v2) & addr_mask)
+ }
+ (Value::I8(v1), Value::I8(v2)) => Value::I8(v1.wrapping_mul(v2)),
+ (Value::U8(v1), Value::U8(v2)) => Value::U8(v1.wrapping_mul(v2)),
+ (Value::I16(v1), Value::I16(v2)) => Value::I16(v1.wrapping_mul(v2)),
+ (Value::U16(v1), Value::U16(v2)) => Value::U16(v1.wrapping_mul(v2)),
+ (Value::I32(v1), Value::I32(v2)) => Value::I32(v1.wrapping_mul(v2)),
+ (Value::U32(v1), Value::U32(v2)) => Value::U32(v1.wrapping_mul(v2)),
+ (Value::I64(v1), Value::I64(v2)) => Value::I64(v1.wrapping_mul(v2)),
+ (Value::U64(v1), Value::U64(v2)) => Value::U64(v1.wrapping_mul(v2)),
+ (Value::F32(v1), Value::F32(v2)) => Value::F32(v1 * v2),
+ (Value::F64(v1), Value::F64(v2)) => Value::F64(v1 * v2),
+ _ => return Err(Error::TypeMismatch),
+ };
+ Ok(value)
+ }
+
+ /// Perform a division operation.
+ ///
+ /// This operation requires matching types.
+ /// If the value type is `Generic`, then it is interpreted as a signed value.
+ ///
+ /// This corresponds to the DWARF `DW_OP_div` operation.
+ pub fn div(self, rhs: Value, addr_mask: u64) -> Result<Value> {
+ match rhs {
+ Value::Generic(v2) if sign_extend(v2, addr_mask) == 0 => {
+ return Err(Error::DivisionByZero);
+ }
+ Value::I8(0)
+ | Value::U8(0)
+ | Value::I16(0)
+ | Value::U16(0)
+ | Value::I32(0)
+ | Value::U32(0)
+ | Value::I64(0)
+ | Value::U64(0) => {
+ return Err(Error::DivisionByZero);
+ }
+ _ => {}
+ }
+ let value = match (self, rhs) {
+ (Value::Generic(v1), Value::Generic(v2)) => {
+ // Signed division
+ Value::Generic(
+ sign_extend(v1, addr_mask).wrapping_div(sign_extend(v2, addr_mask)) as u64,
+ )
+ }
+ (Value::I8(v1), Value::I8(v2)) => Value::I8(v1.wrapping_div(v2)),
+ (Value::U8(v1), Value::U8(v2)) => Value::U8(v1.wrapping_div(v2)),
+ (Value::I16(v1), Value::I16(v2)) => Value::I16(v1.wrapping_div(v2)),
+ (Value::U16(v1), Value::U16(v2)) => Value::U16(v1.wrapping_div(v2)),
+ (Value::I32(v1), Value::I32(v2)) => Value::I32(v1.wrapping_div(v2)),
+ (Value::U32(v1), Value::U32(v2)) => Value::U32(v1.wrapping_div(v2)),
+ (Value::I64(v1), Value::I64(v2)) => Value::I64(v1.wrapping_div(v2)),
+ (Value::U64(v1), Value::U64(v2)) => Value::U64(v1.wrapping_div(v2)),
+ (Value::F32(v1), Value::F32(v2)) => Value::F32(v1 / v2),
+ (Value::F64(v1), Value::F64(v2)) => Value::F64(v1 / v2),
+ _ => return Err(Error::TypeMismatch),
+ };
+ Ok(value)
+ }
+
+ /// Perform a remainder operation.
+ ///
+ /// This operation requires matching integral types.
+ /// If the value type is `Generic`, then it is interpreted as an unsigned value.
+ ///
+ /// This corresponds to the DWARF `DW_OP_mod` operation.
+ pub fn rem(self, rhs: Value, addr_mask: u64) -> Result<Value> {
+ match rhs {
+ Value::Generic(rhs) if (rhs & addr_mask) == 0 => {
+ return Err(Error::DivisionByZero);
+ }
+ Value::I8(0)
+ | Value::U8(0)
+ | Value::I16(0)
+ | Value::U16(0)
+ | Value::I32(0)
+ | Value::U32(0)
+ | Value::I64(0)
+ | Value::U64(0) => {
+ return Err(Error::DivisionByZero);
+ }
+ _ => {}
+ }
+ let value = match (self, rhs) {
+ (Value::Generic(v1), Value::Generic(v2)) => {
+ // Unsigned modulus
+ Value::Generic((v1 & addr_mask).wrapping_rem(v2 & addr_mask))
+ }
+ (Value::I8(v1), Value::I8(v2)) => Value::I8(v1.wrapping_rem(v2)),
+ (Value::U8(v1), Value::U8(v2)) => Value::U8(v1.wrapping_rem(v2)),
+ (Value::I16(v1), Value::I16(v2)) => Value::I16(v1.wrapping_rem(v2)),
+ (Value::U16(v1), Value::U16(v2)) => Value::U16(v1.wrapping_rem(v2)),
+ (Value::I32(v1), Value::I32(v2)) => Value::I32(v1.wrapping_rem(v2)),
+ (Value::U32(v1), Value::U32(v2)) => Value::U32(v1.wrapping_rem(v2)),
+ (Value::I64(v1), Value::I64(v2)) => Value::I64(v1.wrapping_rem(v2)),
+ (Value::U64(v1), Value::U64(v2)) => Value::U64(v1.wrapping_rem(v2)),
+ (Value::F32(_), Value::F32(_)) => return Err(Error::IntegralTypeRequired),
+ (Value::F64(_), Value::F64(_)) => return Err(Error::IntegralTypeRequired),
+ _ => return Err(Error::TypeMismatch),
+ };
+ Ok(value)
+ }
+
+ /// Perform a bitwise not operation.
+ ///
+ /// This operation requires matching integral types.
+ ///
+ /// This corresponds to the DWARF `DW_OP_not` operation.
+ pub fn not(self, addr_mask: u64) -> Result<Value> {
+ let value_type = self.value_type();
+ let v = self.to_u64(addr_mask)?;
+ Value::from_u64(value_type, !v)
+ }
+
+ /// Perform a bitwise and operation.
+ ///
+ /// This operation requires matching integral types.
+ ///
+ /// This corresponds to the DWARF `DW_OP_and` operation.
+ pub fn and(self, rhs: Value, addr_mask: u64) -> Result<Value> {
+ let value_type = self.value_type();
+ if value_type != rhs.value_type() {
+ return Err(Error::TypeMismatch);
+ }
+ let v1 = self.to_u64(addr_mask)?;
+ let v2 = rhs.to_u64(addr_mask)?;
+ Value::from_u64(value_type, v1 & v2)
+ }
+
+ /// Perform a bitwise or operation.
+ ///
+ /// This operation requires matching integral types.
+ ///
+ /// This corresponds to the DWARF `DW_OP_or` operation.
+ pub fn or(self, rhs: Value, addr_mask: u64) -> Result<Value> {
+ let value_type = self.value_type();
+ if value_type != rhs.value_type() {
+ return Err(Error::TypeMismatch);
+ }
+ let v1 = self.to_u64(addr_mask)?;
+ let v2 = rhs.to_u64(addr_mask)?;
+ Value::from_u64(value_type, v1 | v2)
+ }
+
+ /// Perform a bitwise exclusive-or operation.
+ ///
+ /// This operation requires matching integral types.
+ ///
+ /// This corresponds to the DWARF `DW_OP_xor` operation.
+ pub fn xor(self, rhs: Value, addr_mask: u64) -> Result<Value> {
+ let value_type = self.value_type();
+ if value_type != rhs.value_type() {
+ return Err(Error::TypeMismatch);
+ }
+ let v1 = self.to_u64(addr_mask)?;
+ let v2 = rhs.to_u64(addr_mask)?;
+ Value::from_u64(value_type, v1 ^ v2)
+ }
+
+ /// Convert value to bit length suitable for a shift operation.
+ ///
+ /// If the value is negative then an error is returned.
+ fn shift_length(self) -> Result<u64> {
+ let value = match self {
+ Value::Generic(value) => value,
+ Value::I8(value) if value >= 0 => value as u64,
+ Value::U8(value) => u64::from(value),
+ Value::I16(value) if value >= 0 => value as u64,
+ Value::U16(value) => u64::from(value),
+ Value::I32(value) if value >= 0 => value as u64,
+ Value::U32(value) => u64::from(value),
+ Value::I64(value) if value >= 0 => value as u64,
+ Value::U64(value) => value,
+ _ => return Err(Error::InvalidShiftExpression),
+ };
+ Ok(value)
+ }
+
+ /// Perform a shift left operation.
+ ///
+ /// This operation requires integral types.
+ /// If the shift length exceeds the type size, then 0 is returned.
+ /// If the shift length is negative then an error is returned.
+ ///
+ /// This corresponds to the DWARF `DW_OP_shl` operation.
+ pub fn shl(self, rhs: Value, addr_mask: u64) -> Result<Value> {
+ let v2 = rhs.shift_length()?;
+ let value = match self {
+ Value::Generic(v1) => Value::Generic(if v2 >= u64::from(mask_bit_size(addr_mask)) {
+ 0
+ } else {
+ (v1 & addr_mask) << v2
+ }),
+ Value::I8(v1) => Value::I8(if v2 >= 8 { 0 } else { v1 << v2 }),
+ Value::U8(v1) => Value::U8(if v2 >= 8 { 0 } else { v1 << v2 }),
+ Value::I16(v1) => Value::I16(if v2 >= 16 { 0 } else { v1 << v2 }),
+ Value::U16(v1) => Value::U16(if v2 >= 16 { 0 } else { v1 << v2 }),
+ Value::I32(v1) => Value::I32(if v2 >= 32 { 0 } else { v1 << v2 }),
+ Value::U32(v1) => Value::U32(if v2 >= 32 { 0 } else { v1 << v2 }),
+ Value::I64(v1) => Value::I64(if v2 >= 64 { 0 } else { v1 << v2 }),
+ Value::U64(v1) => Value::U64(if v2 >= 64 { 0 } else { v1 << v2 }),
+ _ => return Err(Error::IntegralTypeRequired),
+ };
+ Ok(value)
+ }
+
+ /// Perform a logical shift right operation.
+ ///
+ /// This operation requires an unsigned integral type for the value.
+ /// If the value type is `Generic`, then it is interpreted as an unsigned value.
+ ///
+ /// This operation requires an integral type for the shift length.
+ /// If the shift length exceeds the type size, then 0 is returned.
+ /// If the shift length is negative then an error is returned.
+ ///
+ /// This corresponds to the DWARF `DW_OP_shr` operation.
+ pub fn shr(self, rhs: Value, addr_mask: u64) -> Result<Value> {
+ let v2 = rhs.shift_length()?;
+ let value = match self {
+ Value::Generic(v1) => Value::Generic(if v2 >= u64::from(mask_bit_size(addr_mask)) {
+ 0
+ } else {
+ (v1 & addr_mask) >> v2
+ }),
+ Value::U8(v1) => Value::U8(if v2 >= 8 { 0 } else { v1 >> v2 }),
+ Value::U16(v1) => Value::U16(if v2 >= 16 { 0 } else { v1 >> v2 }),
+ Value::U32(v1) => Value::U32(if v2 >= 32 { 0 } else { v1 >> v2 }),
+ Value::U64(v1) => Value::U64(if v2 >= 64 { 0 } else { v1 >> v2 }),
+ // It's unclear if signed values should implicity convert to an unsigned value.
+ // For now, we don't support them.
+ Value::I8(_) | Value::I16(_) | Value::I32(_) | Value::I64(_) => {
+ return Err(Error::UnsupportedTypeOperation);
+ }
+ _ => return Err(Error::IntegralTypeRequired),
+ };
+ Ok(value)
+ }
+
+ /// Perform an arithmetic shift right operation.
+ ///
+ /// This operation requires a signed integral type for the value.
+ /// If the value type is `Generic`, then it is interpreted as a signed value.
+ ///
+ /// This operation requires an integral type for the shift length.
+ /// If the shift length exceeds the type size, then 0 is returned for positive values,
+ /// and -1 is returned for negative values.
+ /// If the shift length is negative then an error is returned.
+ ///
+ /// This corresponds to the DWARF `DW_OP_shra` operation.
+ pub fn shra(self, rhs: Value, addr_mask: u64) -> Result<Value> {
+ let v2 = rhs.shift_length()?;
+ let value = match self {
+ Value::Generic(v1) => {
+ let v1 = sign_extend(v1, addr_mask);
+ let value = if v2 >= u64::from(mask_bit_size(addr_mask)) {
+ if v1 < 0 {
+ !0
+ } else {
+ 0
+ }
+ } else {
+ (v1 >> v2) as u64
+ };
+ Value::Generic(value)
+ }
+ Value::I8(v1) => Value::I8(if v2 >= 8 {
+ if v1 < 0 {
+ !0
+ } else {
+ 0
+ }
+ } else {
+ v1 >> v2
+ }),
+ Value::I16(v1) => Value::I16(if v2 >= 16 {
+ if v1 < 0 {
+ !0
+ } else {
+ 0
+ }
+ } else {
+ v1 >> v2
+ }),
+ Value::I32(v1) => Value::I32(if v2 >= 32 {
+ if v1 < 0 {
+ !0
+ } else {
+ 0
+ }
+ } else {
+ v1 >> v2
+ }),
+ Value::I64(v1) => Value::I64(if v2 >= 64 {
+ if v1 < 0 {
+ !0
+ } else {
+ 0
+ }
+ } else {
+ v1 >> v2
+ }),
+ // It's unclear if unsigned values should implicity convert to a signed value.
+ // For now, we don't support them.
+ Value::U8(_) | Value::U16(_) | Value::U32(_) | Value::U64(_) => {
+ return Err(Error::UnsupportedTypeOperation);
+ }
+ _ => return Err(Error::IntegralTypeRequired),
+ };
+ Ok(value)
+ }
+
+ /// Perform the `==` relational operation.
+ ///
+ /// This operation requires matching integral types.
+ /// If the value type is `Generic`, then it is interpreted as a signed value.
+ ///
+ /// This corresponds to the DWARF `DW_OP_eq` operation.
+ pub fn eq(self, rhs: Value, addr_mask: u64) -> Result<Value> {
+ let value = match (self, rhs) {
+ (Value::Generic(v1), Value::Generic(v2)) => {
+ sign_extend(v1, addr_mask) == sign_extend(v2, addr_mask)
+ }
+ (Value::I8(v1), Value::I8(v2)) => v1 == v2,
+ (Value::U8(v1), Value::U8(v2)) => v1 == v2,
+ (Value::I16(v1), Value::I16(v2)) => v1 == v2,
+ (Value::U16(v1), Value::U16(v2)) => v1 == v2,
+ (Value::I32(v1), Value::I32(v2)) => v1 == v2,
+ (Value::U32(v1), Value::U32(v2)) => v1 == v2,
+ (Value::I64(v1), Value::I64(v2)) => v1 == v2,
+ (Value::U64(v1), Value::U64(v2)) => v1 == v2,
+ (Value::F32(v1), Value::F32(v2)) => v1 == v2,
+ (Value::F64(v1), Value::F64(v2)) => v1 == v2,
+ _ => return Err(Error::TypeMismatch),
+ };
+ Ok(Value::Generic(value as u64))
+ }
+
+ /// Perform the `>=` relational operation.
+ ///
+ /// This operation requires matching integral types.
+ /// If the value type is `Generic`, then it is interpreted as a signed value.
+ ///
+ /// This corresponds to the DWARF `DW_OP_ge` operation.
+ pub fn ge(self, rhs: Value, addr_mask: u64) -> Result<Value> {
+ let value = match (self, rhs) {
+ (Value::Generic(v1), Value::Generic(v2)) => {
+ sign_extend(v1, addr_mask) >= sign_extend(v2, addr_mask)
+ }
+ (Value::I8(v1), Value::I8(v2)) => v1 >= v2,
+ (Value::U8(v1), Value::U8(v2)) => v1 >= v2,
+ (Value::I16(v1), Value::I16(v2)) => v1 >= v2,
+ (Value::U16(v1), Value::U16(v2)) => v1 >= v2,
+ (Value::I32(v1), Value::I32(v2)) => v1 >= v2,
+ (Value::U32(v1), Value::U32(v2)) => v1 >= v2,
+ (Value::I64(v1), Value::I64(v2)) => v1 >= v2,
+ (Value::U64(v1), Value::U64(v2)) => v1 >= v2,
+ (Value::F32(v1), Value::F32(v2)) => v1 >= v2,
+ (Value::F64(v1), Value::F64(v2)) => v1 >= v2,
+ _ => return Err(Error::TypeMismatch),
+ };
+ Ok(Value::Generic(value as u64))
+ }
+
+ /// Perform the `>` relational operation.
+ ///
+ /// This operation requires matching integral types.
+ /// If the value type is `Generic`, then it is interpreted as a signed value.
+ ///
+ /// This corresponds to the DWARF `DW_OP_gt` operation.
+ pub fn gt(self, rhs: Value, addr_mask: u64) -> Result<Value> {
+ let value = match (self, rhs) {
+ (Value::Generic(v1), Value::Generic(v2)) => {
+ sign_extend(v1, addr_mask) > sign_extend(v2, addr_mask)
+ }
+ (Value::I8(v1), Value::I8(v2)) => v1 > v2,
+ (Value::U8(v1), Value::U8(v2)) => v1 > v2,
+ (Value::I16(v1), Value::I16(v2)) => v1 > v2,
+ (Value::U16(v1), Value::U16(v2)) => v1 > v2,
+ (Value::I32(v1), Value::I32(v2)) => v1 > v2,
+ (Value::U32(v1), Value::U32(v2)) => v1 > v2,
+ (Value::I64(v1), Value::I64(v2)) => v1 > v2,
+ (Value::U64(v1), Value::U64(v2)) => v1 > v2,
+ (Value::F32(v1), Value::F32(v2)) => v1 > v2,
+ (Value::F64(v1), Value::F64(v2)) => v1 > v2,
+ _ => return Err(Error::TypeMismatch),
+ };
+ Ok(Value::Generic(value as u64))
+ }
+
+ /// Perform the `<= relational operation.
+ ///
+ /// This operation requires matching integral types.
+ /// If the value type is `Generic`, then it is interpreted as a signed value.
+ ///
+ /// This corresponds to the DWARF `DW_OP_le` operation.
+ pub fn le(self, rhs: Value, addr_mask: u64) -> Result<Value> {
+ let value = match (self, rhs) {
+ (Value::Generic(v1), Value::Generic(v2)) => {
+ sign_extend(v1, addr_mask) <= sign_extend(v2, addr_mask)
+ }
+ (Value::I8(v1), Value::I8(v2)) => v1 <= v2,
+ (Value::U8(v1), Value::U8(v2)) => v1 <= v2,
+ (Value::I16(v1), Value::I16(v2)) => v1 <= v2,
+ (Value::U16(v1), Value::U16(v2)) => v1 <= v2,
+ (Value::I32(v1), Value::I32(v2)) => v1 <= v2,
+ (Value::U32(v1), Value::U32(v2)) => v1 <= v2,
+ (Value::I64(v1), Value::I64(v2)) => v1 <= v2,
+ (Value::U64(v1), Value::U64(v2)) => v1 <= v2,
+ (Value::F32(v1), Value::F32(v2)) => v1 <= v2,
+ (Value::F64(v1), Value::F64(v2)) => v1 <= v2,
+ _ => return Err(Error::TypeMismatch),
+ };
+ Ok(Value::Generic(value as u64))
+ }
+
+ /// Perform the `< relational operation.
+ ///
+ /// This operation requires matching integral types.
+ /// If the value type is `Generic`, then it is interpreted as a signed value.
+ ///
+ /// This corresponds to the DWARF `DW_OP_lt` operation.
+ pub fn lt(self, rhs: Value, addr_mask: u64) -> Result<Value> {
+ let value = match (self, rhs) {
+ (Value::Generic(v1), Value::Generic(v2)) => {
+ sign_extend(v1, addr_mask) < sign_extend(v2, addr_mask)
+ }
+ (Value::I8(v1), Value::I8(v2)) => v1 < v2,
+ (Value::U8(v1), Value::U8(v2)) => v1 < v2,
+ (Value::I16(v1), Value::I16(v2)) => v1 < v2,
+ (Value::U16(v1), Value::U16(v2)) => v1 < v2,
+ (Value::I32(v1), Value::I32(v2)) => v1 < v2,
+ (Value::U32(v1), Value::U32(v2)) => v1 < v2,
+ (Value::I64(v1), Value::I64(v2)) => v1 < v2,
+ (Value::U64(v1), Value::U64(v2)) => v1 < v2,
+ (Value::F32(v1), Value::F32(v2)) => v1 < v2,
+ (Value::F64(v1), Value::F64(v2)) => v1 < v2,
+ _ => return Err(Error::TypeMismatch),
+ };
+ Ok(Value::Generic(value as u64))
+ }
+
+ /// Perform the `!= relational operation.
+ ///
+ /// This operation requires matching integral types.
+ /// If the value type is `Generic`, then it is interpreted as a signed value.
+ ///
+ /// This corresponds to the DWARF `DW_OP_ne` operation.
+ pub fn ne(self, rhs: Value, addr_mask: u64) -> Result<Value> {
+ let value = match (self, rhs) {
+ (Value::Generic(v1), Value::Generic(v2)) => {
+ sign_extend(v1, addr_mask) != sign_extend(v2, addr_mask)
+ }
+ (Value::I8(v1), Value::I8(v2)) => v1 != v2,
+ (Value::U8(v1), Value::U8(v2)) => v1 != v2,
+ (Value::I16(v1), Value::I16(v2)) => v1 != v2,
+ (Value::U16(v1), Value::U16(v2)) => v1 != v2,
+ (Value::I32(v1), Value::I32(v2)) => v1 != v2,
+ (Value::U32(v1), Value::U32(v2)) => v1 != v2,
+ (Value::I64(v1), Value::I64(v2)) => v1 != v2,
+ (Value::U64(v1), Value::U64(v2)) => v1 != v2,
+ (Value::F32(v1), Value::F32(v2)) => v1 != v2,
+ (Value::F64(v1), Value::F64(v2)) => v1 != v2,
+ _ => return Err(Error::TypeMismatch),
+ };
+ Ok(Value::Generic(value as u64))
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+ use crate::common::{DebugAbbrevOffset, DebugInfoOffset, Encoding, Format};
+ use crate::endianity::LittleEndian;
+ use crate::read::{
+ Abbreviation, AttributeSpecification, DebuggingInformationEntry, EndianSlice, UnitHeader,
+ UnitOffset, UnitType,
+ };
+
+ #[test]
+ #[rustfmt::skip]
+ fn valuetype_from_encoding() {
+ let encoding = Encoding {
+ format: Format::Dwarf32,
+ version: 4,
+ address_size: 4,
+ };
+ let unit = UnitHeader::new(
+ encoding,
+ 7,
+ UnitType::Compilation,
+ DebugAbbrevOffset(0),
+ DebugInfoOffset(0).into(),
+ EndianSlice::new(&[], LittleEndian),
+ );
+
+ let abbrev = Abbreviation::new(
+ 42,
+ constants::DW_TAG_base_type,
+ constants::DW_CHILDREN_no,
+ vec![
+ AttributeSpecification::new(
+ constants::DW_AT_byte_size,
+ constants::DW_FORM_udata,
+ None,
+ ),
+ AttributeSpecification::new(
+ constants::DW_AT_encoding,
+ constants::DW_FORM_udata,
+ None,
+ ),
+ AttributeSpecification::new(
+ constants::DW_AT_endianity,
+ constants::DW_FORM_udata,
+ None,
+ ),
+ ].into(),
+ );
+
+ for &(attrs, result) in &[
+ ([0x01, constants::DW_ATE_signed.0, constants::DW_END_default.0], ValueType::I8),
+ ([0x02, constants::DW_ATE_signed.0, constants::DW_END_default.0], ValueType::I16),
+ ([0x04, constants::DW_ATE_signed.0, constants::DW_END_default.0], ValueType::I32),
+ ([0x08, constants::DW_ATE_signed.0, constants::DW_END_default.0], ValueType::I64),
+ ([0x01, constants::DW_ATE_unsigned.0, constants::DW_END_default.0], ValueType::U8),
+ ([0x02, constants::DW_ATE_unsigned.0, constants::DW_END_default.0], ValueType::U16),
+ ([0x04, constants::DW_ATE_unsigned.0, constants::DW_END_default.0], ValueType::U32),
+ ([0x08, constants::DW_ATE_unsigned.0, constants::DW_END_default.0], ValueType::U64),
+ ([0x04, constants::DW_ATE_float.0, constants::DW_END_default.0], ValueType::F32),
+ ([0x08, constants::DW_ATE_float.0, constants::DW_END_default.0], ValueType::F64),
+ ] {
+ let entry = DebuggingInformationEntry::new(
+ UnitOffset(0),
+ EndianSlice::new(&attrs, LittleEndian),
+ &abbrev,
+ &unit,
+ );
+ assert_eq!(ValueType::from_entry(&entry), Ok(Some(result)));
+ }
+
+ for attrs in &[
+ [0x03, constants::DW_ATE_signed.0, constants::DW_END_default.0],
+ [0x02, constants::DW_ATE_signed.0, constants::DW_END_big.0],
+ ] {
+ let entry = DebuggingInformationEntry::new(
+ UnitOffset(0),
+ EndianSlice::new(attrs, LittleEndian),
+ &abbrev,
+ &unit,
+ );
+ assert_eq!(ValueType::from_entry(&entry), Ok(None));
+ }
+ }
+
+ #[test]
+ fn value_convert() {
+ let addr_mask = !0 >> 32;
+ for &(v, t, result) in &[
+ (Value::Generic(1), ValueType::I8, Ok(Value::I8(1))),
+ (Value::I8(1), ValueType::U8, Ok(Value::U8(1))),
+ (Value::U8(1), ValueType::I16, Ok(Value::I16(1))),
+ (Value::I16(1), ValueType::U16, Ok(Value::U16(1))),
+ (Value::U16(1), ValueType::I32, Ok(Value::I32(1))),
+ (Value::I32(1), ValueType::U32, Ok(Value::U32(1))),
+ (Value::U32(1), ValueType::F32, Ok(Value::F32(1.))),
+ (Value::F32(1.), ValueType::I64, Ok(Value::I64(1))),
+ (Value::I64(1), ValueType::U64, Ok(Value::U64(1))),
+ (Value::U64(1), ValueType::F64, Ok(Value::F64(1.))),
+ (Value::F64(1.), ValueType::Generic, Ok(Value::Generic(1))),
+ ] {
+ assert_eq!(v.convert(t, addr_mask), result);
+ }
+ }
+
+ #[test]
+ #[rustfmt::skip]
+ fn value_reinterpret() {
+ let addr_mask = !0 >> 32;
+ for &(v, t, result) in &[
+ // 8-bit
+ (Value::I8(-1), ValueType::U8, Ok(Value::U8(0xff))),
+ (Value::U8(0xff), ValueType::I8, Ok(Value::I8(-1))),
+ // 16-bit
+ (Value::I16(1), ValueType::U16, Ok(Value::U16(1))),
+ (Value::U16(1), ValueType::I16, Ok(Value::I16(1))),
+ // 32-bit
+ (Value::Generic(1), ValueType::I32, Ok(Value::I32(1))),
+ (Value::I32(1), ValueType::U32, Ok(Value::U32(1))),
+ (Value::U32(0x3f80_0000), ValueType::F32, Ok(Value::F32(1.0))),
+ (Value::F32(1.0), ValueType::Generic, Ok(Value::Generic(0x3f80_0000))),
+ // Type mismatches
+ (Value::Generic(1), ValueType::U8, Err(Error::TypeMismatch)),
+ (Value::U8(1), ValueType::U16, Err(Error::TypeMismatch)),
+ (Value::U16(1), ValueType::U32, Err(Error::TypeMismatch)),
+ (Value::U32(1), ValueType::U64, Err(Error::TypeMismatch)),
+ (Value::U64(1), ValueType::Generic, Err(Error::TypeMismatch)),
+ ] {
+ assert_eq!(v.reinterpret(t, addr_mask), result);
+ }
+
+ let addr_mask = !0;
+ for &(v, t, result) in &[
+ // 64-bit
+ (Value::Generic(1), ValueType::I64, Ok(Value::I64(1))),
+ (Value::I64(1), ValueType::U64, Ok(Value::U64(1))),
+ (Value::U64(0x3ff0_0000_0000_0000), ValueType::F64, Ok(Value::F64(1.0))),
+ (Value::F64(1.0), ValueType::Generic, Ok(Value::Generic(0x3ff0_0000_0000_0000))),
+ ] {
+ assert_eq!(v.reinterpret(t, addr_mask), result);
+ }
+ }
+
+ #[test]
+ #[rustfmt::skip]
+ fn value_abs() {
+ let addr_mask = 0xffff_ffff;
+ for &(v, result) in &[
+ (Value::Generic(0xffff_ffff), Ok(Value::Generic(1))),
+ (Value::I8(-1), Ok(Value::I8(1))),
+ (Value::U8(1), Ok(Value::U8(1))),
+ (Value::I16(-1), Ok(Value::I16(1))),
+ (Value::U16(1), Ok(Value::U16(1))),
+ (Value::I32(-1), Ok(Value::I32(1))),
+ (Value::U32(1), Ok(Value::U32(1))),
+ (Value::I64(-1), Ok(Value::I64(1))),
+ (Value::U64(1), Ok(Value::U64(1))),
+ (Value::F32(-1.), Ok(Value::F32(1.))),
+ (Value::F64(-1.), Ok(Value::F64(1.))),
+ ] {
+ assert_eq!(v.abs(addr_mask), result);
+ }
+ }
+
+ #[test]
+ #[rustfmt::skip]
+ fn value_neg() {
+ let addr_mask = 0xffff_ffff;
+ for &(v, result) in &[
+ (Value::Generic(0xffff_ffff), Ok(Value::Generic(1))),
+ (Value::I8(1), Ok(Value::I8(-1))),
+ (Value::U8(1), Err(Error::UnsupportedTypeOperation)),
+ (Value::I16(1), Ok(Value::I16(-1))),
+ (Value::U16(1), Err(Error::UnsupportedTypeOperation)),
+ (Value::I32(1), Ok(Value::I32(-1))),
+ (Value::U32(1), Err(Error::UnsupportedTypeOperation)),
+ (Value::I64(1), Ok(Value::I64(-1))),
+ (Value::U64(1), Err(Error::UnsupportedTypeOperation)),
+ (Value::F32(1.), Ok(Value::F32(-1.))),
+ (Value::F64(1.), Ok(Value::F64(-1.))),
+ ] {
+ assert_eq!(v.neg(addr_mask), result);
+ }
+ }
+
+ #[test]
+ #[rustfmt::skip]
+ fn value_add() {
+ let addr_mask = 0xffff_ffff;
+ for &(v1, v2, result) in &[
+ (Value::Generic(1), Value::Generic(2), Ok(Value::Generic(3))),
+ (Value::I8(-1), Value::I8(2), Ok(Value::I8(1))),
+ (Value::U8(1), Value::U8(2), Ok(Value::U8(3))),
+ (Value::I16(-1), Value::I16(2), Ok(Value::I16(1))),
+ (Value::U16(1), Value::U16(2), Ok(Value::U16(3))),
+ (Value::I32(-1), Value::I32(2), Ok(Value::I32(1))),
+ (Value::U32(1), Value::U32(2), Ok(Value::U32(3))),
+ (Value::I64(-1), Value::I64(2), Ok(Value::I64(1))),
+ (Value::U64(1), Value::U64(2), Ok(Value::U64(3))),
+ (Value::F32(-1.), Value::F32(2.), Ok(Value::F32(1.))),
+ (Value::F64(-1.), Value::F64(2.), Ok(Value::F64(1.))),
+ (Value::Generic(1), Value::U32(2), Err(Error::TypeMismatch)),
+ ] {
+ assert_eq!(v1.add(v2, addr_mask), result);
+ }
+ }
+
+ #[test]
+ #[rustfmt::skip]
+ fn value_sub() {
+ let addr_mask = 0xffff_ffff;
+ for &(v1, v2, result) in &[
+ (Value::Generic(3), Value::Generic(2), Ok(Value::Generic(1))),
+ (Value::I8(-1), Value::I8(2), Ok(Value::I8(-3))),
+ (Value::U8(3), Value::U8(2), Ok(Value::U8(1))),
+ (Value::I16(-1), Value::I16(2), Ok(Value::I16(-3))),
+ (Value::U16(3), Value::U16(2), Ok(Value::U16(1))),
+ (Value::I32(-1), Value::I32(2), Ok(Value::I32(-3))),
+ (Value::U32(3), Value::U32(2), Ok(Value::U32(1))),
+ (Value::I64(-1), Value::I64(2), Ok(Value::I64(-3))),
+ (Value::U64(3), Value::U64(2), Ok(Value::U64(1))),
+ (Value::F32(-1.), Value::F32(2.), Ok(Value::F32(-3.))),
+ (Value::F64(-1.), Value::F64(2.), Ok(Value::F64(-3.))),
+ (Value::Generic(3), Value::U32(2), Err(Error::TypeMismatch)),
+ ] {
+ assert_eq!(v1.sub(v2, addr_mask), result);
+ }
+ }
+
+ #[test]
+ #[rustfmt::skip]
+ fn value_mul() {
+ let addr_mask = 0xffff_ffff;
+ for &(v1, v2, result) in &[
+ (Value::Generic(2), Value::Generic(3), Ok(Value::Generic(6))),
+ (Value::I8(-2), Value::I8(3), Ok(Value::I8(-6))),
+ (Value::U8(2), Value::U8(3), Ok(Value::U8(6))),
+ (Value::I16(-2), Value::I16(3), Ok(Value::I16(-6))),
+ (Value::U16(2), Value::U16(3), Ok(Value::U16(6))),
+ (Value::I32(-2), Value::I32(3), Ok(Value::I32(-6))),
+ (Value::U32(2), Value::U32(3), Ok(Value::U32(6))),
+ (Value::I64(-2), Value::I64(3), Ok(Value::I64(-6))),
+ (Value::U64(2), Value::U64(3), Ok(Value::U64(6))),
+ (Value::F32(-2.), Value::F32(3.), Ok(Value::F32(-6.))),
+ (Value::F64(-2.), Value::F64(3.), Ok(Value::F64(-6.))),
+ (Value::Generic(2), Value::U32(3), Err(Error::TypeMismatch)),
+ ] {
+ assert_eq!(v1.mul(v2, addr_mask), result);
+ }
+ }
+
+ #[test]
+ #[rustfmt::skip]
+ fn value_div() {
+ let addr_mask = 0xffff_ffff;
+ for &(v1, v2, result) in &[
+ (Value::Generic(6), Value::Generic(3), Ok(Value::Generic(2))),
+ (Value::I8(-6), Value::I8(3), Ok(Value::I8(-2))),
+ (Value::U8(6), Value::U8(3), Ok(Value::U8(2))),
+ (Value::I16(-6), Value::I16(3), Ok(Value::I16(-2))),
+ (Value::U16(6), Value::U16(3), Ok(Value::U16(2))),
+ (Value::I32(-6), Value::I32(3), Ok(Value::I32(-2))),
+ (Value::U32(6), Value::U32(3), Ok(Value::U32(2))),
+ (Value::I64(-6), Value::I64(3), Ok(Value::I64(-2))),
+ (Value::U64(6), Value::U64(3), Ok(Value::U64(2))),
+ (Value::F32(-6.), Value::F32(3.), Ok(Value::F32(-2.))),
+ (Value::F64(-6.), Value::F64(3.), Ok(Value::F64(-2.))),
+ (Value::Generic(6), Value::U32(3), Err(Error::TypeMismatch)),
+ ] {
+ assert_eq!(v1.div(v2, addr_mask), result);
+ }
+ for &(v1, v2, result) in &[
+ (Value::Generic(6), Value::Generic(0), Err(Error::DivisionByZero)),
+ (Value::I8(-6), Value::I8(0), Err(Error::DivisionByZero)),
+ (Value::U8(6), Value::U8(0), Err(Error::DivisionByZero)),
+ (Value::I16(-6), Value::I16(0), Err(Error::DivisionByZero)),
+ (Value::U16(6), Value::U16(0), Err(Error::DivisionByZero)),
+ (Value::I32(-6), Value::I32(0), Err(Error::DivisionByZero)),
+ (Value::U32(6), Value::U32(0), Err(Error::DivisionByZero)),
+ (Value::I64(-6), Value::I64(0), Err(Error::DivisionByZero)),
+ (Value::U64(6), Value::U64(0), Err(Error::DivisionByZero)),
+ (Value::F32(-6.), Value::F32(0.), Ok(Value::F32(-6. / 0.))),
+ (Value::F64(-6.), Value::F64(0.), Ok(Value::F64(-6. / 0.))),
+ ] {
+ assert_eq!(v1.div(v2, addr_mask), result);
+ }
+ }
+
+ #[test]
+ #[rustfmt::skip]
+ fn value_rem() {
+ let addr_mask = 0xffff_ffff;
+ for &(v1, v2, result) in &[
+ (Value::Generic(3), Value::Generic(2), Ok(Value::Generic(1))),
+ (Value::I8(-3), Value::I8(2), Ok(Value::I8(-1))),
+ (Value::U8(3), Value::U8(2), Ok(Value::U8(1))),
+ (Value::I16(-3), Value::I16(2), Ok(Value::I16(-1))),
+ (Value::U16(3), Value::U16(2), Ok(Value::U16(1))),
+ (Value::I32(-3), Value::I32(2), Ok(Value::I32(-1))),
+ (Value::U32(3), Value::U32(2), Ok(Value::U32(1))),
+ (Value::I64(-3), Value::I64(2), Ok(Value::I64(-1))),
+ (Value::U64(3), Value::U64(2), Ok(Value::U64(1))),
+ (Value::F32(-3.), Value::F32(2.), Err(Error::IntegralTypeRequired)),
+ (Value::F64(-3.), Value::F64(2.), Err(Error::IntegralTypeRequired)),
+ (Value::Generic(3), Value::U32(2), Err(Error::TypeMismatch)),
+ ] {
+ assert_eq!(v1.rem(v2, addr_mask), result);
+ }
+ for &(v1, v2, result) in &[
+ (Value::Generic(3), Value::Generic(0), Err(Error::DivisionByZero)),
+ (Value::I8(-3), Value::I8(0), Err(Error::DivisionByZero)),
+ (Value::U8(3), Value::U8(0), Err(Error::DivisionByZero)),
+ (Value::I16(-3), Value::I16(0), Err(Error::DivisionByZero)),
+ (Value::U16(3), Value::U16(0), Err(Error::DivisionByZero)),
+ (Value::I32(-3), Value::I32(0), Err(Error::DivisionByZero)),
+ (Value::U32(3), Value::U32(0), Err(Error::DivisionByZero)),
+ (Value::I64(-3), Value::I64(0), Err(Error::DivisionByZero)),
+ (Value::U64(3), Value::U64(0), Err(Error::DivisionByZero)),
+ ] {
+ assert_eq!(v1.rem(v2, addr_mask), result);
+ }
+ }
+
+ #[test]
+ #[rustfmt::skip]
+ fn value_not() {
+ let addr_mask = 0xffff_ffff;
+ for &(v, result) in &[
+ (Value::Generic(1), Ok(Value::Generic(!1))),
+ (Value::I8(1), Ok(Value::I8(!1))),
+ (Value::U8(1), Ok(Value::U8(!1))),
+ (Value::I16(1), Ok(Value::I16(!1))),
+ (Value::U16(1), Ok(Value::U16(!1))),
+ (Value::I32(1), Ok(Value::I32(!1))),
+ (Value::U32(1), Ok(Value::U32(!1))),
+ (Value::I64(1), Ok(Value::I64(!1))),
+ (Value::U64(1), Ok(Value::U64(!1))),
+ (Value::F32(1.), Err(Error::IntegralTypeRequired)),
+ (Value::F64(1.), Err(Error::IntegralTypeRequired)),
+ ] {
+ assert_eq!(v.not(addr_mask), result);
+ }
+ }
+
+ #[test]
+ #[rustfmt::skip]
+ fn value_and() {
+ let addr_mask = 0xffff_ffff;
+ for &(v1, v2, result) in &[
+ (Value::Generic(3), Value::Generic(5), Ok(Value::Generic(1))),
+ (Value::I8(3), Value::I8(5), Ok(Value::I8(1))),
+ (Value::U8(3), Value::U8(5), Ok(Value::U8(1))),
+ (Value::I16(3), Value::I16(5), Ok(Value::I16(1))),
+ (Value::U16(3), Value::U16(5), Ok(Value::U16(1))),
+ (Value::I32(3), Value::I32(5), Ok(Value::I32(1))),
+ (Value::U32(3), Value::U32(5), Ok(Value::U32(1))),
+ (Value::I64(3), Value::I64(5), Ok(Value::I64(1))),
+ (Value::U64(3), Value::U64(5), Ok(Value::U64(1))),
+ (Value::F32(3.), Value::F32(5.), Err(Error::IntegralTypeRequired)),
+ (Value::F64(3.), Value::F64(5.), Err(Error::IntegralTypeRequired)),
+ (Value::Generic(3), Value::U32(5), Err(Error::TypeMismatch)),
+ ] {
+ assert_eq!(v1.and(v2, addr_mask), result);
+ }
+ }
+
+ #[test]
+ #[rustfmt::skip]
+ fn value_or() {
+ let addr_mask = 0xffff_ffff;
+ for &(v1, v2, result) in &[
+ (Value::Generic(3), Value::Generic(5), Ok(Value::Generic(7))),
+ (Value::I8(3), Value::I8(5), Ok(Value::I8(7))),
+ (Value::U8(3), Value::U8(5), Ok(Value::U8(7))),
+ (Value::I16(3), Value::I16(5), Ok(Value::I16(7))),
+ (Value::U16(3), Value::U16(5), Ok(Value::U16(7))),
+ (Value::I32(3), Value::I32(5), Ok(Value::I32(7))),
+ (Value::U32(3), Value::U32(5), Ok(Value::U32(7))),
+ (Value::I64(3), Value::I64(5), Ok(Value::I64(7))),
+ (Value::U64(3), Value::U64(5), Ok(Value::U64(7))),
+ (Value::F32(3.), Value::F32(5.), Err(Error::IntegralTypeRequired)),
+ (Value::F64(3.), Value::F64(5.), Err(Error::IntegralTypeRequired)),
+ (Value::Generic(3), Value::U32(5), Err(Error::TypeMismatch)),
+ ] {
+ assert_eq!(v1.or(v2, addr_mask), result);
+ }
+ }
+
+ #[test]
+ #[rustfmt::skip]
+ fn value_xor() {
+ let addr_mask = 0xffff_ffff;
+ for &(v1, v2, result) in &[
+ (Value::Generic(3), Value::Generic(5), Ok(Value::Generic(6))),
+ (Value::I8(3), Value::I8(5), Ok(Value::I8(6))),
+ (Value::U8(3), Value::U8(5), Ok(Value::U8(6))),
+ (Value::I16(3), Value::I16(5), Ok(Value::I16(6))),
+ (Value::U16(3), Value::U16(5), Ok(Value::U16(6))),
+ (Value::I32(3), Value::I32(5), Ok(Value::I32(6))),
+ (Value::U32(3), Value::U32(5), Ok(Value::U32(6))),
+ (Value::I64(3), Value::I64(5), Ok(Value::I64(6))),
+ (Value::U64(3), Value::U64(5), Ok(Value::U64(6))),
+ (Value::F32(3.), Value::F32(5.), Err(Error::IntegralTypeRequired)),
+ (Value::F64(3.), Value::F64(5.), Err(Error::IntegralTypeRequired)),
+ (Value::Generic(3), Value::U32(5), Err(Error::TypeMismatch)),
+ ] {
+ assert_eq!(v1.xor(v2, addr_mask), result);
+ }
+ }
+
+ #[test]
+ #[rustfmt::skip]
+ fn value_shl() {
+ let addr_mask = 0xffff_ffff;
+ for &(v1, v2, result) in &[
+ // One of each type
+ (Value::Generic(3), Value::Generic(5), Ok(Value::Generic(96))),
+ (Value::I8(3), Value::U8(5), Ok(Value::I8(96))),
+ (Value::U8(3), Value::I8(5), Ok(Value::U8(96))),
+ (Value::I16(3), Value::U16(5), Ok(Value::I16(96))),
+ (Value::U16(3), Value::I16(5), Ok(Value::U16(96))),
+ (Value::I32(3), Value::U32(5), Ok(Value::I32(96))),
+ (Value::U32(3), Value::I32(5), Ok(Value::U32(96))),
+ (Value::I64(3), Value::U64(5), Ok(Value::I64(96))),
+ (Value::U64(3), Value::I64(5), Ok(Value::U64(96))),
+ (Value::F32(3.), Value::U8(5), Err(Error::IntegralTypeRequired)),
+ (Value::F64(3.), Value::U8(5), Err(Error::IntegralTypeRequired)),
+ // Invalid shifts
+ (Value::U8(3), Value::I8(-5), Err(Error::InvalidShiftExpression)),
+ (Value::U8(3), Value::I16(-5), Err(Error::InvalidShiftExpression)),
+ (Value::U8(3), Value::I32(-5), Err(Error::InvalidShiftExpression)),
+ (Value::U8(3), Value::I64(-5), Err(Error::InvalidShiftExpression)),
+ (Value::U8(3), Value::F32(5.), Err(Error::InvalidShiftExpression)),
+ (Value::U8(3), Value::F64(5.), Err(Error::InvalidShiftExpression)),
+ // Large shifts
+ (Value::Generic(3), Value::Generic(32), Ok(Value::Generic(0))),
+ (Value::I8(3), Value::U8(8), Ok(Value::I8(0))),
+ (Value::U8(3), Value::I8(9), Ok(Value::U8(0))),
+ (Value::I16(3), Value::U16(17), Ok(Value::I16(0))),
+ (Value::U16(3), Value::I16(16), Ok(Value::U16(0))),
+ (Value::I32(3), Value::U32(32), Ok(Value::I32(0))),
+ (Value::U32(3), Value::I32(33), Ok(Value::U32(0))),
+ (Value::I64(3), Value::U64(65), Ok(Value::I64(0))),
+ (Value::U64(3), Value::I64(64), Ok(Value::U64(0))),
+ ] {
+ assert_eq!(v1.shl(v2, addr_mask), result);
+ }
+ }
+
+ #[test]
+ #[rustfmt::skip]
+ fn value_shr() {
+ let addr_mask = 0xffff_ffff;
+ for &(v1, v2, result) in &[
+ // One of each type
+ (Value::Generic(96), Value::Generic(5), Ok(Value::Generic(3))),
+ (Value::I8(96), Value::U8(5), Err(Error::UnsupportedTypeOperation)),
+ (Value::U8(96), Value::I8(5), Ok(Value::U8(3))),
+ (Value::I16(96), Value::U16(5), Err(Error::UnsupportedTypeOperation)),
+ (Value::U16(96), Value::I16(5), Ok(Value::U16(3))),
+ (Value::I32(96), Value::U32(5), Err(Error::UnsupportedTypeOperation)),
+ (Value::U32(96), Value::I32(5), Ok(Value::U32(3))),
+ (Value::I64(96), Value::U64(5), Err(Error::UnsupportedTypeOperation)),
+ (Value::U64(96), Value::I64(5), Ok(Value::U64(3))),
+ (Value::F32(96.), Value::U8(5), Err(Error::IntegralTypeRequired)),
+ (Value::F64(96.), Value::U8(5), Err(Error::IntegralTypeRequired)),
+ // Invalid shifts
+ (Value::U8(96), Value::I8(-5), Err(Error::InvalidShiftExpression)),
+ (Value::U8(96), Value::I16(-5), Err(Error::InvalidShiftExpression)),
+ (Value::U8(96), Value::I32(-5), Err(Error::InvalidShiftExpression)),
+ (Value::U8(96), Value::I64(-5), Err(Error::InvalidShiftExpression)),
+ (Value::U8(96), Value::F32(5.), Err(Error::InvalidShiftExpression)),
+ (Value::U8(96), Value::F64(5.), Err(Error::InvalidShiftExpression)),
+ // Large shifts
+ (Value::Generic(96), Value::Generic(32), Ok(Value::Generic(0))),
+ (Value::U8(96), Value::I8(9), Ok(Value::U8(0))),
+ (Value::U16(96), Value::I16(16), Ok(Value::U16(0))),
+ (Value::U32(96), Value::I32(33), Ok(Value::U32(0))),
+ (Value::U64(96), Value::I64(64), Ok(Value::U64(0))),
+ ] {
+ assert_eq!(v1.shr(v2, addr_mask), result);
+ }
+ }
+
+ #[test]
+ #[rustfmt::skip]
+ fn value_shra() {
+ let addr_mask = 0xffff_ffff;
+ for &(v1, v2, result) in &[
+ // One of each type
+ (Value::Generic(u64::from(-96i32 as u32)), Value::Generic(5), Ok(Value::Generic(-3i64 as u64))),
+ (Value::I8(-96), Value::U8(5), Ok(Value::I8(-3))),
+ (Value::U8(96), Value::I8(5), Err(Error::UnsupportedTypeOperation)),
+ (Value::I16(-96), Value::U16(5), Ok(Value::I16(-3))),
+ (Value::U16(96), Value::I16(5), Err(Error::UnsupportedTypeOperation)),
+ (Value::I32(-96), Value::U32(5), Ok(Value::I32(-3))),
+ (Value::U32(96), Value::I32(5), Err(Error::UnsupportedTypeOperation)),
+ (Value::I64(-96), Value::U64(5), Ok(Value::I64(-3))),
+ (Value::U64(96), Value::I64(5), Err(Error::UnsupportedTypeOperation)),
+ (Value::F32(96.), Value::U8(5), Err(Error::IntegralTypeRequired)),
+ (Value::F64(96.), Value::U8(5), Err(Error::IntegralTypeRequired)),
+ // Invalid shifts
+ (Value::U8(96), Value::I8(-5), Err(Error::InvalidShiftExpression)),
+ (Value::U8(96), Value::I16(-5), Err(Error::InvalidShiftExpression)),
+ (Value::U8(96), Value::I32(-5), Err(Error::InvalidShiftExpression)),
+ (Value::U8(96), Value::I64(-5), Err(Error::InvalidShiftExpression)),
+ (Value::U8(96), Value::F32(5.), Err(Error::InvalidShiftExpression)),
+ (Value::U8(96), Value::F64(5.), Err(Error::InvalidShiftExpression)),
+ // Large shifts
+ (Value::Generic(96), Value::Generic(32), Ok(Value::Generic(0))),
+ (Value::I8(96), Value::U8(8), Ok(Value::I8(0))),
+ (Value::I8(-96), Value::U8(8), Ok(Value::I8(-1))),
+ (Value::I16(96), Value::U16(17), Ok(Value::I16(0))),
+ (Value::I16(-96), Value::U16(17), Ok(Value::I16(-1))),
+ (Value::I32(96), Value::U32(32), Ok(Value::I32(0))),
+ (Value::I32(-96), Value::U32(32), Ok(Value::I32(-1))),
+ (Value::I64(96), Value::U64(65), Ok(Value::I64(0))),
+ (Value::I64(-96), Value::U64(65), Ok(Value::I64(-1))),
+ ] {
+ assert_eq!(v1.shra(v2, addr_mask), result);
+ }
+ }
+
+ #[test]
+ fn value_eq() {
+ let addr_mask = 0xffff_ffff;
+ for &(v1, v2, result) in &[
+ (Value::Generic(3), Value::Generic(3), Ok(Value::Generic(1))),
+ (Value::Generic(!3), Value::Generic(3), Ok(Value::Generic(0))),
+ (Value::I8(3), Value::I8(3), Ok(Value::Generic(1))),
+ (Value::I8(!3), Value::I8(3), Ok(Value::Generic(0))),
+ (Value::U8(3), Value::U8(3), Ok(Value::Generic(1))),
+ (Value::U8(!3), Value::U8(3), Ok(Value::Generic(0))),
+ (Value::I16(3), Value::I16(3), Ok(Value::Generic(1))),
+ (Value::I16(!3), Value::I16(3), Ok(Value::Generic(0))),
+ (Value::U16(3), Value::U16(3), Ok(Value::Generic(1))),
+ (Value::U16(!3), Value::U16(3), Ok(Value::Generic(0))),
+ (Value::I32(3), Value::I32(3), Ok(Value::Generic(1))),
+ (Value::I32(!3), Value::I32(3), Ok(Value::Generic(0))),
+ (Value::U32(3), Value::U32(3), Ok(Value::Generic(1))),
+ (Value::U32(!3), Value::U32(3), Ok(Value::Generic(0))),
+ (Value::I64(3), Value::I64(3), Ok(Value::Generic(1))),
+ (Value::I64(!3), Value::I64(3), Ok(Value::Generic(0))),
+ (Value::U64(3), Value::U64(3), Ok(Value::Generic(1))),
+ (Value::U64(!3), Value::U64(3), Ok(Value::Generic(0))),
+ (Value::F32(3.), Value::F32(3.), Ok(Value::Generic(1))),
+ (Value::F32(-3.), Value::F32(3.), Ok(Value::Generic(0))),
+ (Value::F64(3.), Value::F64(3.), Ok(Value::Generic(1))),
+ (Value::F64(-3.), Value::F64(3.), Ok(Value::Generic(0))),
+ (Value::Generic(3), Value::U32(3), Err(Error::TypeMismatch)),
+ ] {
+ assert_eq!(v1.eq(v2, addr_mask), result);
+ }
+ }
+
+ #[test]
+ fn value_ne() {
+ let addr_mask = 0xffff_ffff;
+ for &(v1, v2, result) in &[
+ (Value::Generic(3), Value::Generic(3), Ok(Value::Generic(0))),
+ (Value::Generic(!3), Value::Generic(3), Ok(Value::Generic(1))),
+ (Value::I8(3), Value::I8(3), Ok(Value::Generic(0))),
+ (Value::I8(!3), Value::I8(3), Ok(Value::Generic(1))),
+ (Value::U8(3), Value::U8(3), Ok(Value::Generic(0))),
+ (Value::U8(!3), Value::U8(3), Ok(Value::Generic(1))),
+ (Value::I16(3), Value::I16(3), Ok(Value::Generic(0))),
+ (Value::I16(!3), Value::I16(3), Ok(Value::Generic(1))),
+ (Value::U16(3), Value::U16(3), Ok(Value::Generic(0))),
+ (Value::U16(!3), Value::U16(3), Ok(Value::Generic(1))),
+ (Value::I32(3), Value::I32(3), Ok(Value::Generic(0))),
+ (Value::I32(!3), Value::I32(3), Ok(Value::Generic(1))),
+ (Value::U32(3), Value::U32(3), Ok(Value::Generic(0))),
+ (Value::U32(!3), Value::U32(3), Ok(Value::Generic(1))),
+ (Value::I64(3), Value::I64(3), Ok(Value::Generic(0))),
+ (Value::I64(!3), Value::I64(3), Ok(Value::Generic(1))),
+ (Value::U64(3), Value::U64(3), Ok(Value::Generic(0))),
+ (Value::U64(!3), Value::U64(3), Ok(Value::Generic(1))),
+ (Value::F32(3.), Value::F32(3.), Ok(Value::Generic(0))),
+ (Value::F32(-3.), Value::F32(3.), Ok(Value::Generic(1))),
+ (Value::F64(3.), Value::F64(3.), Ok(Value::Generic(0))),
+ (Value::F64(-3.), Value::F64(3.), Ok(Value::Generic(1))),
+ (Value::Generic(3), Value::U32(3), Err(Error::TypeMismatch)),
+ ] {
+ assert_eq!(v1.ne(v2, addr_mask), result);
+ }
+ }
+
+ #[test]
+ fn value_ge() {
+ let addr_mask = 0xffff_ffff;
+ for &(v1, v2, result) in &[
+ (Value::Generic(3), Value::Generic(!3), Ok(Value::Generic(1))),
+ (Value::Generic(!3), Value::Generic(3), Ok(Value::Generic(0))),
+ (Value::I8(3), Value::I8(!3), Ok(Value::Generic(1))),
+ (Value::I8(!3), Value::I8(3), Ok(Value::Generic(0))),
+ (Value::U8(3), Value::U8(!3), Ok(Value::Generic(0))),
+ (Value::U8(!3), Value::U8(3), Ok(Value::Generic(1))),
+ (Value::I16(3), Value::I16(!3), Ok(Value::Generic(1))),
+ (Value::I16(!3), Value::I16(3), Ok(Value::Generic(0))),
+ (Value::U16(3), Value::U16(!3), Ok(Value::Generic(0))),
+ (Value::U16(!3), Value::U16(3), Ok(Value::Generic(1))),
+ (Value::I32(3), Value::I32(!3), Ok(Value::Generic(1))),
+ (Value::I32(!3), Value::I32(3), Ok(Value::Generic(0))),
+ (Value::U32(3), Value::U32(!3), Ok(Value::Generic(0))),
+ (Value::U32(!3), Value::U32(3), Ok(Value::Generic(1))),
+ (Value::I64(3), Value::I64(!3), Ok(Value::Generic(1))),
+ (Value::I64(!3), Value::I64(3), Ok(Value::Generic(0))),
+ (Value::U64(3), Value::U64(!3), Ok(Value::Generic(0))),
+ (Value::U64(!3), Value::U64(3), Ok(Value::Generic(1))),
+ (Value::F32(3.), Value::F32(-3.), Ok(Value::Generic(1))),
+ (Value::F32(-3.), Value::F32(3.), Ok(Value::Generic(0))),
+ (Value::F64(3.), Value::F64(-3.), Ok(Value::Generic(1))),
+ (Value::F64(-3.), Value::F64(3.), Ok(Value::Generic(0))),
+ (Value::Generic(3), Value::U32(3), Err(Error::TypeMismatch)),
+ ] {
+ assert_eq!(v1.ge(v2, addr_mask), result);
+ }
+ }
+
+ #[test]
+ fn value_gt() {
+ let addr_mask = 0xffff_ffff;
+ for &(v1, v2, result) in &[
+ (Value::Generic(3), Value::Generic(!3), Ok(Value::Generic(1))),
+ (Value::Generic(!3), Value::Generic(3), Ok(Value::Generic(0))),
+ (Value::I8(3), Value::I8(!3), Ok(Value::Generic(1))),
+ (Value::I8(!3), Value::I8(3), Ok(Value::Generic(0))),
+ (Value::U8(3), Value::U8(!3), Ok(Value::Generic(0))),
+ (Value::U8(!3), Value::U8(3), Ok(Value::Generic(1))),
+ (Value::I16(3), Value::I16(!3), Ok(Value::Generic(1))),
+ (Value::I16(!3), Value::I16(3), Ok(Value::Generic(0))),
+ (Value::U16(3), Value::U16(!3), Ok(Value::Generic(0))),
+ (Value::U16(!3), Value::U16(3), Ok(Value::Generic(1))),
+ (Value::I32(3), Value::I32(!3), Ok(Value::Generic(1))),
+ (Value::I32(!3), Value::I32(3), Ok(Value::Generic(0))),
+ (Value::U32(3), Value::U32(!3), Ok(Value::Generic(0))),
+ (Value::U32(!3), Value::U32(3), Ok(Value::Generic(1))),
+ (Value::I64(3), Value::I64(!3), Ok(Value::Generic(1))),
+ (Value::I64(!3), Value::I64(3), Ok(Value::Generic(0))),
+ (Value::U64(3), Value::U64(!3), Ok(Value::Generic(0))),
+ (Value::U64(!3), Value::U64(3), Ok(Value::Generic(1))),
+ (Value::F32(3.), Value::F32(-3.), Ok(Value::Generic(1))),
+ (Value::F32(-3.), Value::F32(3.), Ok(Value::Generic(0))),
+ (Value::F64(3.), Value::F64(-3.), Ok(Value::Generic(1))),
+ (Value::F64(-3.), Value::F64(3.), Ok(Value::Generic(0))),
+ (Value::Generic(3), Value::U32(3), Err(Error::TypeMismatch)),
+ ] {
+ assert_eq!(v1.gt(v2, addr_mask), result);
+ }
+ }
+
+ #[test]
+ fn value_le() {
+ let addr_mask = 0xffff_ffff;
+ for &(v1, v2, result) in &[
+ (Value::Generic(3), Value::Generic(!3), Ok(Value::Generic(0))),
+ (Value::Generic(!3), Value::Generic(3), Ok(Value::Generic(1))),
+ (Value::I8(3), Value::I8(!3), Ok(Value::Generic(0))),
+ (Value::I8(!3), Value::I8(3), Ok(Value::Generic(1))),
+ (Value::U8(3), Value::U8(!3), Ok(Value::Generic(1))),
+ (Value::U8(!3), Value::U8(3), Ok(Value::Generic(0))),
+ (Value::I16(3), Value::I16(!3), Ok(Value::Generic(0))),
+ (Value::I16(!3), Value::I16(3), Ok(Value::Generic(1))),
+ (Value::U16(3), Value::U16(!3), Ok(Value::Generic(1))),
+ (Value::U16(!3), Value::U16(3), Ok(Value::Generic(0))),
+ (Value::I32(3), Value::I32(!3), Ok(Value::Generic(0))),
+ (Value::I32(!3), Value::I32(3), Ok(Value::Generic(1))),
+ (Value::U32(3), Value::U32(!3), Ok(Value::Generic(1))),
+ (Value::U32(!3), Value::U32(3), Ok(Value::Generic(0))),
+ (Value::I64(3), Value::I64(!3), Ok(Value::Generic(0))),
+ (Value::I64(!3), Value::I64(3), Ok(Value::Generic(1))),
+ (Value::U64(3), Value::U64(!3), Ok(Value::Generic(1))),
+ (Value::U64(!3), Value::U64(3), Ok(Value::Generic(0))),
+ (Value::F32(3.), Value::F32(-3.), Ok(Value::Generic(0))),
+ (Value::F32(-3.), Value::F32(3.), Ok(Value::Generic(1))),
+ (Value::F64(3.), Value::F64(-3.), Ok(Value::Generic(0))),
+ (Value::F64(-3.), Value::F64(3.), Ok(Value::Generic(1))),
+ (Value::Generic(3), Value::U32(3), Err(Error::TypeMismatch)),
+ ] {
+ assert_eq!(v1.le(v2, addr_mask), result);
+ }
+ }
+
+ #[test]
+ fn value_lt() {
+ let addr_mask = 0xffff_ffff;
+ for &(v1, v2, result) in &[
+ (Value::Generic(3), Value::Generic(!3), Ok(Value::Generic(0))),
+ (Value::Generic(!3), Value::Generic(3), Ok(Value::Generic(1))),
+ (Value::I8(3), Value::I8(!3), Ok(Value::Generic(0))),
+ (Value::I8(!3), Value::I8(3), Ok(Value::Generic(1))),
+ (Value::U8(3), Value::U8(!3), Ok(Value::Generic(1))),
+ (Value::U8(!3), Value::U8(3), Ok(Value::Generic(0))),
+ (Value::I16(3), Value::I16(!3), Ok(Value::Generic(0))),
+ (Value::I16(!3), Value::I16(3), Ok(Value::Generic(1))),
+ (Value::U16(3), Value::U16(!3), Ok(Value::Generic(1))),
+ (Value::U16(!3), Value::U16(3), Ok(Value::Generic(0))),
+ (Value::I32(3), Value::I32(!3), Ok(Value::Generic(0))),
+ (Value::I32(!3), Value::I32(3), Ok(Value::Generic(1))),
+ (Value::U32(3), Value::U32(!3), Ok(Value::Generic(1))),
+ (Value::U32(!3), Value::U32(3), Ok(Value::Generic(0))),
+ (Value::I64(3), Value::I64(!3), Ok(Value::Generic(0))),
+ (Value::I64(!3), Value::I64(3), Ok(Value::Generic(1))),
+ (Value::U64(3), Value::U64(!3), Ok(Value::Generic(1))),
+ (Value::U64(!3), Value::U64(3), Ok(Value::Generic(0))),
+ (Value::F32(3.), Value::F32(-3.), Ok(Value::Generic(0))),
+ (Value::F32(-3.), Value::F32(3.), Ok(Value::Generic(1))),
+ (Value::F64(3.), Value::F64(-3.), Ok(Value::Generic(0))),
+ (Value::F64(-3.), Value::F64(3.), Ok(Value::Generic(1))),
+ (Value::Generic(3), Value::U32(3), Err(Error::TypeMismatch)),
+ ] {
+ assert_eq!(v1.lt(v2, addr_mask), result);
+ }
+ }
+}
diff --git a/vendor/gimli-0.26.2/src/test_util.rs b/vendor/gimli-0.26.2/src/test_util.rs
new file mode 100644
index 000000000..706aaf934
--- /dev/null
+++ b/vendor/gimli-0.26.2/src/test_util.rs
@@ -0,0 +1,53 @@
+#![allow(missing_docs)]
+
+use crate::Format;
+use test_assembler::{Label, Section};
+
+pub trait GimliSectionMethods {
+ fn sleb(self, val: i64) -> Self;
+ fn uleb(self, val: u64) -> Self;
+ fn initial_length(self, format: Format, length: &Label, start: &Label) -> Self;
+ fn word(self, size: u8, val: u64) -> Self;
+ fn word_label(self, size: u8, val: &Label) -> Self;
+}
+
+impl GimliSectionMethods for Section {
+ fn sleb(mut self, mut val: i64) -> Self {
+ while val & !0x3f != 0 && val | 0x3f != -1 {
+ self = self.D8(val as u8 | 0x80);
+ val >>= 7;
+ }
+ self.D8(val as u8 & 0x7f)
+ }
+
+ fn uleb(mut self, mut val: u64) -> Self {
+ while val & !0x7f != 0 {
+ self = self.D8(val as u8 | 0x80);
+ val >>= 7;
+ }
+ self.D8(val as u8)
+ }
+
+ fn initial_length(self, format: Format, length: &Label, start: &Label) -> Self {
+ match format {
+ Format::Dwarf32 => self.D32(length).mark(start),
+ Format::Dwarf64 => self.D32(0xffff_ffff).D64(length).mark(start),
+ }
+ }
+
+ fn word(self, size: u8, val: u64) -> Self {
+ match size {
+ 4 => self.D32(val as u32),
+ 8 => self.D64(val),
+ _ => panic!("unsupported word size"),
+ }
+ }
+
+ fn word_label(self, size: u8, val: &Label) -> Self {
+ match size {
+ 4 => self.D32(val),
+ 8 => self.D64(val),
+ _ => panic!("unsupported word size"),
+ }
+ }
+}
diff --git a/vendor/gimli-0.26.2/src/write/abbrev.rs b/vendor/gimli-0.26.2/src/write/abbrev.rs
new file mode 100644
index 000000000..7cdfa969c
--- /dev/null
+++ b/vendor/gimli-0.26.2/src/write/abbrev.rs
@@ -0,0 +1,188 @@
+use alloc::vec::Vec;
+use indexmap::IndexSet;
+use std::ops::{Deref, DerefMut};
+
+use crate::common::{DebugAbbrevOffset, SectionId};
+use crate::constants;
+use crate::write::{Result, Section, Writer};
+
+/// A table of abbreviations that will be stored in a `.debug_abbrev` section.
+// Requirements:
+// - values are `Abbreviation`
+// - insertion returns an abbreviation code for use in writing a DIE
+// - inserting a duplicate returns the code of the existing value
+#[derive(Debug, Default)]
+pub(crate) struct AbbreviationTable {
+ abbrevs: IndexSet<Abbreviation>,
+}
+
+impl AbbreviationTable {
+ /// Add an abbreviation to the table and return its code.
+ pub fn add(&mut self, abbrev: Abbreviation) -> u64 {
+ let (code, _) = self.abbrevs.insert_full(abbrev);
+ // Code must be non-zero
+ (code + 1) as u64
+ }
+
+ /// Write the abbreviation table to the `.debug_abbrev` section.
+ pub fn write<W: Writer>(&self, w: &mut DebugAbbrev<W>) -> Result<()> {
+ for (code, abbrev) in self.abbrevs.iter().enumerate() {
+ w.write_uleb128((code + 1) as u64)?;
+ abbrev.write(w)?;
+ }
+ // Null abbreviation code
+ w.write_u8(0)
+ }
+}
+
+/// An abbreviation describes the shape of a `DebuggingInformationEntry`'s type:
+/// its tag type, whether it has children, and its set of attributes.
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub(crate) struct Abbreviation {
+ tag: constants::DwTag,
+ has_children: bool,
+ attributes: Vec<AttributeSpecification>,
+}
+
+impl Abbreviation {
+ /// Construct a new `Abbreviation`.
+ #[inline]
+ pub fn new(
+ tag: constants::DwTag,
+ has_children: bool,
+ attributes: Vec<AttributeSpecification>,
+ ) -> Abbreviation {
+ Abbreviation {
+ tag,
+ has_children,
+ attributes,
+ }
+ }
+
+ /// Write the abbreviation to the `.debug_abbrev` section.
+ pub fn write<W: Writer>(&self, w: &mut DebugAbbrev<W>) -> Result<()> {
+ w.write_uleb128(self.tag.0.into())?;
+ w.write_u8(if self.has_children {
+ constants::DW_CHILDREN_yes.0
+ } else {
+ constants::DW_CHILDREN_no.0
+ })?;
+ for attr in &self.attributes {
+ attr.write(w)?;
+ }
+ // Null name and form
+ w.write_u8(0)?;
+ w.write_u8(0)
+ }
+}
+
+/// The description of an attribute in an abbreviated type.
+// TODO: support implicit const
+#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
+pub(crate) struct AttributeSpecification {
+ name: constants::DwAt,
+ form: constants::DwForm,
+}
+
+impl AttributeSpecification {
+ /// Construct a new `AttributeSpecification`.
+ #[inline]
+ pub fn new(name: constants::DwAt, form: constants::DwForm) -> AttributeSpecification {
+ AttributeSpecification { name, form }
+ }
+
+ /// Write the attribute specification to the `.debug_abbrev` section.
+ #[inline]
+ pub fn write<W: Writer>(&self, w: &mut DebugAbbrev<W>) -> Result<()> {
+ w.write_uleb128(self.name.0.into())?;
+ w.write_uleb128(self.form.0.into())
+ }
+}
+
+define_section!(
+ DebugAbbrev,
+ DebugAbbrevOffset,
+ "A writable `.debug_abbrev` section."
+);
+
+#[cfg(test)]
+#[cfg(feature = "read")]
+mod tests {
+ use super::*;
+ use crate::constants;
+ use crate::read;
+ use crate::write::EndianVec;
+ use crate::LittleEndian;
+
+ #[test]
+ fn test_abbreviation_table() {
+ let mut abbrevs = AbbreviationTable::default();
+ let abbrev1 = Abbreviation::new(
+ constants::DW_TAG_subprogram,
+ false,
+ vec![AttributeSpecification::new(
+ constants::DW_AT_name,
+ constants::DW_FORM_string,
+ )],
+ );
+ let abbrev2 = Abbreviation::new(
+ constants::DW_TAG_compile_unit,
+ true,
+ vec![
+ AttributeSpecification::new(constants::DW_AT_producer, constants::DW_FORM_strp),
+ AttributeSpecification::new(constants::DW_AT_language, constants::DW_FORM_data2),
+ ],
+ );
+ let code1 = abbrevs.add(abbrev1.clone());
+ assert_eq!(code1, 1);
+ let code2 = abbrevs.add(abbrev2.clone());
+ assert_eq!(code2, 2);
+ assert_eq!(abbrevs.add(abbrev1.clone()), code1);
+ assert_eq!(abbrevs.add(abbrev2.clone()), code2);
+
+ let mut debug_abbrev = DebugAbbrev::from(EndianVec::new(LittleEndian));
+ let debug_abbrev_offset = debug_abbrev.offset();
+ assert_eq!(debug_abbrev_offset, DebugAbbrevOffset(0));
+ abbrevs.write(&mut debug_abbrev).unwrap();
+ assert_eq!(debug_abbrev.offset(), DebugAbbrevOffset(17));
+
+ let read_debug_abbrev = read::DebugAbbrev::new(debug_abbrev.slice(), LittleEndian);
+ let read_abbrevs = read_debug_abbrev
+ .abbreviations(debug_abbrev_offset)
+ .unwrap();
+
+ let read_abbrev1 = read_abbrevs.get(code1).unwrap();
+ assert_eq!(abbrev1.tag, read_abbrev1.tag());
+ assert_eq!(abbrev1.has_children, read_abbrev1.has_children());
+ assert_eq!(abbrev1.attributes.len(), read_abbrev1.attributes().len());
+ assert_eq!(
+ abbrev1.attributes[0].name,
+ read_abbrev1.attributes()[0].name()
+ );
+ assert_eq!(
+ abbrev1.attributes[0].form,
+ read_abbrev1.attributes()[0].form()
+ );
+
+ let read_abbrev2 = read_abbrevs.get(code2).unwrap();
+ assert_eq!(abbrev2.tag, read_abbrev2.tag());
+ assert_eq!(abbrev2.has_children, read_abbrev2.has_children());
+ assert_eq!(abbrev2.attributes.len(), read_abbrev2.attributes().len());
+ assert_eq!(
+ abbrev2.attributes[0].name,
+ read_abbrev2.attributes()[0].name()
+ );
+ assert_eq!(
+ abbrev2.attributes[0].form,
+ read_abbrev2.attributes()[0].form()
+ );
+ assert_eq!(
+ abbrev2.attributes[1].name,
+ read_abbrev2.attributes()[1].name()
+ );
+ assert_eq!(
+ abbrev2.attributes[1].form,
+ read_abbrev2.attributes()[1].form()
+ );
+ }
+}
diff --git a/vendor/gimli-0.26.2/src/write/cfi.rs b/vendor/gimli-0.26.2/src/write/cfi.rs
new file mode 100644
index 000000000..718cb69ad
--- /dev/null
+++ b/vendor/gimli-0.26.2/src/write/cfi.rs
@@ -0,0 +1,1025 @@
+use alloc::vec::Vec;
+use indexmap::IndexSet;
+use std::ops::{Deref, DerefMut};
+
+use crate::common::{DebugFrameOffset, EhFrameOffset, Encoding, Format, Register, SectionId};
+use crate::constants;
+use crate::write::{Address, BaseId, Error, Expression, Result, Section, Writer};
+
+define_section!(
+ DebugFrame,
+ DebugFrameOffset,
+ "A writable `.debug_frame` section."
+);
+
+define_section!(EhFrame, EhFrameOffset, "A writable `.eh_frame` section.");
+
+define_id!(CieId, "An identifier for a CIE in a `FrameTable`.");
+
+/// A table of frame description entries.
+#[derive(Debug, Default)]
+pub struct FrameTable {
+ /// Base id for CIEs.
+ base_id: BaseId,
+ /// The common information entries.
+ cies: IndexSet<CommonInformationEntry>,
+ /// The frame description entries.
+ fdes: Vec<(CieId, FrameDescriptionEntry)>,
+}
+
+impl FrameTable {
+ /// Add a CIE and return its id.
+ ///
+ /// If the CIE already exists, then return the id of the existing CIE.
+ pub fn add_cie(&mut self, cie: CommonInformationEntry) -> CieId {
+ let (index, _) = self.cies.insert_full(cie);
+ CieId::new(self.base_id, index)
+ }
+
+ /// The number of CIEs.
+ pub fn cie_count(&self) -> usize {
+ self.cies.len()
+ }
+
+ /// Add a FDE.
+ ///
+ /// Does not check for duplicates.
+ ///
+ /// # Panics
+ ///
+ /// Panics if the CIE id is invalid.
+ pub fn add_fde(&mut self, cie: CieId, fde: FrameDescriptionEntry) {
+ debug_assert_eq!(self.base_id, cie.base_id);
+ self.fdes.push((cie, fde));
+ }
+
+ /// The number of FDEs.
+ pub fn fde_count(&self) -> usize {
+ self.fdes.len()
+ }
+
+ /// Write the frame table entries to the given `.debug_frame` section.
+ pub fn write_debug_frame<W: Writer>(&self, w: &mut DebugFrame<W>) -> Result<()> {
+ self.write(&mut w.0, false)
+ }
+
+ /// Write the frame table entries to the given `.eh_frame` section.
+ pub fn write_eh_frame<W: Writer>(&self, w: &mut EhFrame<W>) -> Result<()> {
+ self.write(&mut w.0, true)
+ }
+
+ fn write<W: Writer>(&self, w: &mut W, eh_frame: bool) -> Result<()> {
+ let mut cie_offsets = vec![None; self.cies.len()];
+ for (cie_id, fde) in &self.fdes {
+ let cie_index = cie_id.index;
+ let cie = self.cies.get_index(cie_index).unwrap();
+ let cie_offset = match cie_offsets[cie_index] {
+ Some(offset) => offset,
+ None => {
+ // Only write CIEs as they are referenced.
+ let offset = cie.write(w, eh_frame)?;
+ cie_offsets[cie_index] = Some(offset);
+ offset
+ }
+ };
+
+ fde.write(w, eh_frame, cie_offset, cie)?;
+ }
+ // TODO: write length 0 terminator for eh_frame?
+ Ok(())
+ }
+}
+
+/// A common information entry. This contains information that is shared between FDEs.
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub struct CommonInformationEntry {
+ encoding: Encoding,
+
+ /// A constant that is factored out of code offsets.
+ ///
+ /// This should be set to the minimum instruction length.
+ /// Writing a code offset that is not a multiple of this factor will generate an error.
+ code_alignment_factor: u8,
+
+ /// A constant that is factored out of data offsets.
+ ///
+ /// This should be set to the minimum data alignment for the frame.
+ /// Writing a data offset that is not a multiple of this factor will generate an error.
+ data_alignment_factor: i8,
+
+ /// The return address register. This might not correspond to an actual machine register.
+ return_address_register: Register,
+
+ /// The address of the personality function and its encoding.
+ pub personality: Option<(constants::DwEhPe, Address)>,
+
+ /// The encoding to use for the LSDA address in FDEs.
+ ///
+ /// If set then all FDEs which use this CIE must have a LSDA address.
+ pub lsda_encoding: Option<constants::DwEhPe>,
+
+ /// The encoding to use for addresses in FDEs.
+ pub fde_address_encoding: constants::DwEhPe,
+
+ /// True for signal trampolines.
+ pub signal_trampoline: bool,
+
+ /// The initial instructions upon entry to this function.
+ instructions: Vec<CallFrameInstruction>,
+}
+
+impl CommonInformationEntry {
+ /// Create a new common information entry.
+ ///
+ /// The encoding version must be a CFI version, not a DWARF version.
+ pub fn new(
+ encoding: Encoding,
+ code_alignment_factor: u8,
+ data_alignment_factor: i8,
+ return_address_register: Register,
+ ) -> Self {
+ CommonInformationEntry {
+ encoding,
+ code_alignment_factor,
+ data_alignment_factor,
+ return_address_register,
+ personality: None,
+ lsda_encoding: None,
+ fde_address_encoding: constants::DW_EH_PE_absptr,
+ signal_trampoline: false,
+ instructions: Vec::new(),
+ }
+ }
+
+ /// Add an initial instruction.
+ pub fn add_instruction(&mut self, instruction: CallFrameInstruction) {
+ self.instructions.push(instruction);
+ }
+
+ fn has_augmentation(&self) -> bool {
+ self.personality.is_some()
+ || self.lsda_encoding.is_some()
+ || self.signal_trampoline
+ || self.fde_address_encoding != constants::DW_EH_PE_absptr
+ }
+
+ /// Returns the section offset of the CIE.
+ fn write<W: Writer>(&self, w: &mut W, eh_frame: bool) -> Result<usize> {
+ let encoding = self.encoding;
+ let offset = w.len();
+
+ let length_offset = w.write_initial_length(encoding.format)?;
+ let length_base = w.len();
+
+ if eh_frame {
+ w.write_u32(0)?;
+ } else {
+ match encoding.format {
+ Format::Dwarf32 => w.write_u32(0xffff_ffff)?,
+ Format::Dwarf64 => w.write_u64(0xffff_ffff_ffff_ffff)?,
+ }
+ }
+
+ if eh_frame {
+ if encoding.version != 1 {
+ return Err(Error::UnsupportedVersion(encoding.version));
+ };
+ } else {
+ match encoding.version {
+ 1 | 3 | 4 => {}
+ _ => return Err(Error::UnsupportedVersion(encoding.version)),
+ };
+ }
+ w.write_u8(encoding.version as u8)?;
+
+ let augmentation = self.has_augmentation();
+ if augmentation {
+ w.write_u8(b'z')?;
+ if self.lsda_encoding.is_some() {
+ w.write_u8(b'L')?;
+ }
+ if self.personality.is_some() {
+ w.write_u8(b'P')?;
+ }
+ if self.fde_address_encoding != constants::DW_EH_PE_absptr {
+ w.write_u8(b'R')?;
+ }
+ if self.signal_trampoline {
+ w.write_u8(b'S')?;
+ }
+ }
+ w.write_u8(0)?;
+
+ if encoding.version >= 4 {
+ w.write_u8(encoding.address_size)?;
+ // TODO: segment_selector_size
+ w.write_u8(0)?;
+ }
+
+ w.write_uleb128(self.code_alignment_factor.into())?;
+ w.write_sleb128(self.data_alignment_factor.into())?;
+
+ if !eh_frame && encoding.version == 1 {
+ let register = self.return_address_register.0 as u8;
+ if u16::from(register) != self.return_address_register.0 {
+ return Err(Error::ValueTooLarge);
+ }
+ w.write_u8(register)?;
+ } else {
+ w.write_uleb128(self.return_address_register.0.into())?;
+ }
+
+ if augmentation {
+ let augmentation_length_offset = w.len();
+ w.write_u8(0)?;
+ let augmentation_length_base = w.len();
+
+ if let Some(eh_pe) = self.lsda_encoding {
+ w.write_u8(eh_pe.0)?;
+ }
+ if let Some((eh_pe, address)) = self.personality {
+ w.write_u8(eh_pe.0)?;
+ w.write_eh_pointer(address, eh_pe, encoding.address_size)?;
+ }
+ if self.fde_address_encoding != constants::DW_EH_PE_absptr {
+ w.write_u8(self.fde_address_encoding.0)?;
+ }
+
+ let augmentation_length = (w.len() - augmentation_length_base) as u64;
+ debug_assert!(augmentation_length < 0x80);
+ w.write_udata_at(augmentation_length_offset, augmentation_length, 1)?;
+ }
+
+ for instruction in &self.instructions {
+ instruction.write(w, encoding, self)?;
+ }
+
+ write_nop(
+ w,
+ encoding.format.word_size() as usize + w.len() - length_base,
+ encoding.address_size,
+ )?;
+
+ let length = (w.len() - length_base) as u64;
+ w.write_initial_length_at(length_offset, length, encoding.format)?;
+
+ Ok(offset)
+ }
+}
+
+/// A frame description entry. There should be one FDE per function.
+#[derive(Debug, Clone, PartialEq, Eq)]
+pub struct FrameDescriptionEntry {
+ /// The initial address of the function.
+ address: Address,
+
+ /// The length in bytes of the function.
+ length: u32,
+
+ /// The address of the LSDA.
+ pub lsda: Option<Address>,
+
+ /// The instructions for this function, ordered by offset.
+ instructions: Vec<(u32, CallFrameInstruction)>,
+}
+
+impl FrameDescriptionEntry {
+ /// Create a new frame description entry for a function.
+ pub fn new(address: Address, length: u32) -> Self {
+ FrameDescriptionEntry {
+ address,
+ length,
+ lsda: None,
+ instructions: Vec::new(),
+ }
+ }
+
+ /// Add an instruction.
+ ///
+ /// Instructions must be added in increasing order of offset, or writing will fail.
+ pub fn add_instruction(&mut self, offset: u32, instruction: CallFrameInstruction) {
+ debug_assert!(self.instructions.last().map(|x| x.0).unwrap_or(0) <= offset);
+ self.instructions.push((offset, instruction));
+ }
+
+ fn write<W: Writer>(
+ &self,
+ w: &mut W,
+ eh_frame: bool,
+ cie_offset: usize,
+ cie: &CommonInformationEntry,
+ ) -> Result<()> {
+ let encoding = cie.encoding;
+ let length_offset = w.write_initial_length(encoding.format)?;
+ let length_base = w.len();
+
+ if eh_frame {
+ // .eh_frame uses a relative offset which doesn't need relocation.
+ w.write_udata((w.len() - cie_offset) as u64, 4)?;
+ } else {
+ w.write_offset(
+ cie_offset,
+ SectionId::DebugFrame,
+ encoding.format.word_size(),
+ )?;
+ }
+
+ if cie.fde_address_encoding != constants::DW_EH_PE_absptr {
+ w.write_eh_pointer(
+ self.address,
+ cie.fde_address_encoding,
+ encoding.address_size,
+ )?;
+ w.write_eh_pointer_data(
+ self.length.into(),
+ cie.fde_address_encoding.format(),
+ encoding.address_size,
+ )?;
+ } else {
+ w.write_address(self.address, encoding.address_size)?;
+ w.write_udata(self.length.into(), encoding.address_size)?;
+ }
+
+ if cie.has_augmentation() {
+ let mut augmentation_length = 0u64;
+ if self.lsda.is_some() {
+ augmentation_length += u64::from(encoding.address_size);
+ }
+ w.write_uleb128(augmentation_length)?;
+
+ debug_assert_eq!(self.lsda.is_some(), cie.lsda_encoding.is_some());
+ if let (Some(lsda), Some(lsda_encoding)) = (self.lsda, cie.lsda_encoding) {
+ w.write_eh_pointer(lsda, lsda_encoding, encoding.address_size)?;
+ }
+ }
+
+ let mut prev_offset = 0;
+ for (offset, instruction) in &self.instructions {
+ write_advance_loc(w, cie.code_alignment_factor, prev_offset, *offset)?;
+ prev_offset = *offset;
+ instruction.write(w, encoding, cie)?;
+ }
+
+ write_nop(
+ w,
+ encoding.format.word_size() as usize + w.len() - length_base,
+ encoding.address_size,
+ )?;
+
+ let length = (w.len() - length_base) as u64;
+ w.write_initial_length_at(length_offset, length, encoding.format)?;
+
+ Ok(())
+ }
+}
+
+/// An instruction in a frame description entry.
+///
+/// This may be a CFA definition, a register rule, or some other directive.
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub enum CallFrameInstruction {
+ /// Define the CFA rule to use the provided register and offset.
+ Cfa(Register, i32),
+ /// Update the CFA rule to use the provided register. The offset is unchanged.
+ CfaRegister(Register),
+ /// Update the CFA rule to use the provided offset. The register is unchanged.
+ CfaOffset(i32),
+ /// Define the CFA rule to use the provided expression.
+ CfaExpression(Expression),
+
+ /// Restore the initial rule for the register.
+ Restore(Register),
+ /// The previous value of the register is not recoverable.
+ Undefined(Register),
+ /// The register has not been modified.
+ SameValue(Register),
+ /// The previous value of the register is saved at address CFA + offset.
+ Offset(Register, i32),
+ /// The previous value of the register is CFA + offset.
+ ValOffset(Register, i32),
+ /// The previous value of the register is stored in another register.
+ Register(Register, Register),
+ /// The previous value of the register is saved at address given by the expression.
+ Expression(Register, Expression),
+ /// The previous value of the register is given by the expression.
+ ValExpression(Register, Expression),
+
+ /// Push all register rules onto a stack.
+ RememberState,
+ /// Pop all register rules off the stack.
+ RestoreState,
+ /// The size of the arguments that have been pushed onto the stack.
+ ArgsSize(u32),
+}
+
+impl CallFrameInstruction {
+ fn write<W: Writer>(
+ &self,
+ w: &mut W,
+ encoding: Encoding,
+ cie: &CommonInformationEntry,
+ ) -> Result<()> {
+ match *self {
+ CallFrameInstruction::Cfa(register, offset) => {
+ if offset < 0 {
+ let offset = factored_data_offset(offset, cie.data_alignment_factor)?;
+ w.write_u8(constants::DW_CFA_def_cfa_sf.0)?;
+ w.write_uleb128(register.0.into())?;
+ w.write_sleb128(offset.into())?;
+ } else {
+ // Unfactored offset.
+ w.write_u8(constants::DW_CFA_def_cfa.0)?;
+ w.write_uleb128(register.0.into())?;
+ w.write_uleb128(offset as u64)?;
+ }
+ }
+ CallFrameInstruction::CfaRegister(register) => {
+ w.write_u8(constants::DW_CFA_def_cfa_register.0)?;
+ w.write_uleb128(register.0.into())?;
+ }
+ CallFrameInstruction::CfaOffset(offset) => {
+ if offset < 0 {
+ let offset = factored_data_offset(offset, cie.data_alignment_factor)?;
+ w.write_u8(constants::DW_CFA_def_cfa_offset_sf.0)?;
+ w.write_sleb128(offset.into())?;
+ } else {
+ // Unfactored offset.
+ w.write_u8(constants::DW_CFA_def_cfa_offset.0)?;
+ w.write_uleb128(offset as u64)?;
+ }
+ }
+ CallFrameInstruction::CfaExpression(ref expression) => {
+ w.write_u8(constants::DW_CFA_def_cfa_expression.0)?;
+ w.write_uleb128(expression.size(encoding, None) as u64)?;
+ expression.write(w, None, encoding, None)?;
+ }
+ CallFrameInstruction::Restore(register) => {
+ if register.0 < 0x40 {
+ w.write_u8(constants::DW_CFA_restore.0 | register.0 as u8)?;
+ } else {
+ w.write_u8(constants::DW_CFA_restore_extended.0)?;
+ w.write_uleb128(register.0.into())?;
+ }
+ }
+ CallFrameInstruction::Undefined(register) => {
+ w.write_u8(constants::DW_CFA_undefined.0)?;
+ w.write_uleb128(register.0.into())?;
+ }
+ CallFrameInstruction::SameValue(register) => {
+ w.write_u8(constants::DW_CFA_same_value.0)?;
+ w.write_uleb128(register.0.into())?;
+ }
+ CallFrameInstruction::Offset(register, offset) => {
+ let offset = factored_data_offset(offset, cie.data_alignment_factor)?;
+ if offset < 0 {
+ w.write_u8(constants::DW_CFA_offset_extended_sf.0)?;
+ w.write_uleb128(register.0.into())?;
+ w.write_sleb128(offset.into())?;
+ } else if register.0 < 0x40 {
+ w.write_u8(constants::DW_CFA_offset.0 | register.0 as u8)?;
+ w.write_uleb128(offset as u64)?;
+ } else {
+ w.write_u8(constants::DW_CFA_offset_extended.0)?;
+ w.write_uleb128(register.0.into())?;
+ w.write_uleb128(offset as u64)?;
+ }
+ }
+ CallFrameInstruction::ValOffset(register, offset) => {
+ let offset = factored_data_offset(offset, cie.data_alignment_factor)?;
+ if offset < 0 {
+ w.write_u8(constants::DW_CFA_val_offset_sf.0)?;
+ w.write_uleb128(register.0.into())?;
+ w.write_sleb128(offset.into())?;
+ } else {
+ w.write_u8(constants::DW_CFA_val_offset.0)?;
+ w.write_uleb128(register.0.into())?;
+ w.write_uleb128(offset as u64)?;
+ }
+ }
+ CallFrameInstruction::Register(register1, register2) => {
+ w.write_u8(constants::DW_CFA_register.0)?;
+ w.write_uleb128(register1.0.into())?;
+ w.write_uleb128(register2.0.into())?;
+ }
+ CallFrameInstruction::Expression(register, ref expression) => {
+ w.write_u8(constants::DW_CFA_expression.0)?;
+ w.write_uleb128(register.0.into())?;
+ w.write_uleb128(expression.size(encoding, None) as u64)?;
+ expression.write(w, None, encoding, None)?;
+ }
+ CallFrameInstruction::ValExpression(register, ref expression) => {
+ w.write_u8(constants::DW_CFA_val_expression.0)?;
+ w.write_uleb128(register.0.into())?;
+ w.write_uleb128(expression.size(encoding, None) as u64)?;
+ expression.write(w, None, encoding, None)?;
+ }
+ CallFrameInstruction::RememberState => {
+ w.write_u8(constants::DW_CFA_remember_state.0)?;
+ }
+ CallFrameInstruction::RestoreState => {
+ w.write_u8(constants::DW_CFA_restore_state.0)?;
+ }
+ CallFrameInstruction::ArgsSize(size) => {
+ w.write_u8(constants::DW_CFA_GNU_args_size.0)?;
+ w.write_uleb128(size.into())?;
+ }
+ }
+ Ok(())
+ }
+}
+
+fn write_advance_loc<W: Writer>(
+ w: &mut W,
+ code_alignment_factor: u8,
+ prev_offset: u32,
+ offset: u32,
+) -> Result<()> {
+ if offset == prev_offset {
+ return Ok(());
+ }
+ let delta = factored_code_delta(prev_offset, offset, code_alignment_factor)?;
+ if delta < 0x40 {
+ w.write_u8(constants::DW_CFA_advance_loc.0 | delta as u8)?;
+ } else if delta < 0x100 {
+ w.write_u8(constants::DW_CFA_advance_loc1.0)?;
+ w.write_u8(delta as u8)?;
+ } else if delta < 0x10000 {
+ w.write_u8(constants::DW_CFA_advance_loc2.0)?;
+ w.write_u16(delta as u16)?;
+ } else {
+ w.write_u8(constants::DW_CFA_advance_loc4.0)?;
+ w.write_u32(delta)?;
+ }
+ Ok(())
+}
+
+fn write_nop<W: Writer>(w: &mut W, len: usize, align: u8) -> Result<()> {
+ debug_assert_eq!(align & (align - 1), 0);
+ let tail_len = (!len + 1) & (align as usize - 1);
+ for _ in 0..tail_len {
+ w.write_u8(constants::DW_CFA_nop.0)?;
+ }
+ Ok(())
+}
+
+fn factored_code_delta(prev_offset: u32, offset: u32, factor: u8) -> Result<u32> {
+ if offset < prev_offset {
+ return Err(Error::InvalidFrameCodeOffset(offset));
+ }
+ let delta = offset - prev_offset;
+ let factor = u32::from(factor);
+ let factored_delta = delta / factor;
+ if delta != factored_delta * factor {
+ return Err(Error::InvalidFrameCodeOffset(offset));
+ }
+ Ok(factored_delta)
+}
+
+fn factored_data_offset(offset: i32, factor: i8) -> Result<i32> {
+ let factor = i32::from(factor);
+ let factored_offset = offset / factor;
+ if offset != factored_offset * factor {
+ return Err(Error::InvalidFrameDataOffset(offset));
+ }
+ Ok(factored_offset)
+}
+
+#[cfg(feature = "read")]
+pub(crate) mod convert {
+ use super::*;
+ use crate::read::{self, Reader};
+ use crate::write::{ConvertError, ConvertResult};
+ use std::collections::{hash_map, HashMap};
+
+ impl FrameTable {
+ /// Create a frame table by reading the data in the given section.
+ ///
+ /// `convert_address` is a function to convert read addresses into the `Address`
+ /// type. For non-relocatable addresses, this function may simply return
+ /// `Address::Constant(address)`. For relocatable addresses, it is the caller's
+ /// responsibility to determine the symbol and addend corresponding to the address
+ /// and return `Address::Symbol { symbol, addend }`.
+ pub fn from<R, Section>(
+ frame: &Section,
+ convert_address: &dyn Fn(u64) -> Option<Address>,
+ ) -> ConvertResult<FrameTable>
+ where
+ R: Reader<Offset = usize>,
+ Section: read::UnwindSection<R>,
+ Section::Offset: read::UnwindOffset<usize>,
+ {
+ let bases = read::BaseAddresses::default().set_eh_frame(0);
+
+ let mut frame_table = FrameTable::default();
+
+ let mut cie_ids = HashMap::new();
+ let mut entries = frame.entries(&bases);
+ while let Some(entry) = entries.next()? {
+ let partial = match entry {
+ read::CieOrFde::Cie(_) => continue,
+ read::CieOrFde::Fde(partial) => partial,
+ };
+
+ // TODO: is it worth caching the parsed CIEs? It would be better if FDEs only
+ // stored a reference.
+ let from_fde = partial.parse(Section::cie_from_offset)?;
+ let from_cie = from_fde.cie();
+ let cie_id = match cie_ids.entry(from_cie.offset()) {
+ hash_map::Entry::Occupied(o) => *o.get(),
+ hash_map::Entry::Vacant(e) => {
+ let cie =
+ CommonInformationEntry::from(from_cie, frame, &bases, convert_address)?;
+ let cie_id = frame_table.add_cie(cie);
+ e.insert(cie_id);
+ cie_id
+ }
+ };
+ let fde = FrameDescriptionEntry::from(&from_fde, frame, &bases, convert_address)?;
+ frame_table.add_fde(cie_id, fde);
+ }
+
+ Ok(frame_table)
+ }
+ }
+
+ impl CommonInformationEntry {
+ fn from<R, Section>(
+ from_cie: &read::CommonInformationEntry<R>,
+ frame: &Section,
+ bases: &read::BaseAddresses,
+ convert_address: &dyn Fn(u64) -> Option<Address>,
+ ) -> ConvertResult<CommonInformationEntry>
+ where
+ R: Reader<Offset = usize>,
+ Section: read::UnwindSection<R>,
+ Section::Offset: read::UnwindOffset<usize>,
+ {
+ let mut cie = CommonInformationEntry::new(
+ from_cie.encoding(),
+ from_cie.code_alignment_factor() as u8,
+ from_cie.data_alignment_factor() as i8,
+ from_cie.return_address_register(),
+ );
+
+ cie.personality = match from_cie.personality_with_encoding() {
+ // We treat these the same because the encoding already determines
+ // whether it is indirect.
+ Some((eh_pe, read::Pointer::Direct(p)))
+ | Some((eh_pe, read::Pointer::Indirect(p))) => {
+ let address = convert_address(p).ok_or(ConvertError::InvalidAddress)?;
+ Some((eh_pe, address))
+ }
+ _ => None,
+ };
+ cie.lsda_encoding = from_cie.lsda_encoding();
+ cie.fde_address_encoding = from_cie
+ .fde_address_encoding()
+ .unwrap_or(constants::DW_EH_PE_absptr);
+ cie.signal_trampoline = from_cie.is_signal_trampoline();
+
+ let mut offset = 0;
+ let mut from_instructions = from_cie.instructions(frame, bases);
+ while let Some(from_instruction) = from_instructions.next()? {
+ if let Some(instruction) = CallFrameInstruction::from(
+ from_instruction,
+ from_cie,
+ convert_address,
+ &mut offset,
+ )? {
+ cie.instructions.push(instruction);
+ }
+ }
+ Ok(cie)
+ }
+ }
+
+ impl FrameDescriptionEntry {
+ fn from<R, Section>(
+ from_fde: &read::FrameDescriptionEntry<R>,
+ frame: &Section,
+ bases: &read::BaseAddresses,
+ convert_address: &dyn Fn(u64) -> Option<Address>,
+ ) -> ConvertResult<FrameDescriptionEntry>
+ where
+ R: Reader<Offset = usize>,
+ Section: read::UnwindSection<R>,
+ Section::Offset: read::UnwindOffset<usize>,
+ {
+ let address =
+ convert_address(from_fde.initial_address()).ok_or(ConvertError::InvalidAddress)?;
+ let length = from_fde.len() as u32;
+ let mut fde = FrameDescriptionEntry::new(address, length);
+
+ match from_fde.lsda() {
+ // We treat these the same because the encoding already determines
+ // whether it is indirect.
+ Some(read::Pointer::Direct(p)) | Some(read::Pointer::Indirect(p)) => {
+ let address = convert_address(p).ok_or(ConvertError::InvalidAddress)?;
+ fde.lsda = Some(address);
+ }
+ None => {}
+ }
+
+ let from_cie = from_fde.cie();
+ let mut offset = 0;
+ let mut from_instructions = from_fde.instructions(frame, bases);
+ while let Some(from_instruction) = from_instructions.next()? {
+ if let Some(instruction) = CallFrameInstruction::from(
+ from_instruction,
+ from_cie,
+ convert_address,
+ &mut offset,
+ )? {
+ fde.instructions.push((offset, instruction));
+ }
+ }
+
+ Ok(fde)
+ }
+ }
+
+ impl CallFrameInstruction {
+ fn from<R: Reader<Offset = usize>>(
+ from_instruction: read::CallFrameInstruction<R>,
+ from_cie: &read::CommonInformationEntry<R>,
+ convert_address: &dyn Fn(u64) -> Option<Address>,
+ offset: &mut u32,
+ ) -> ConvertResult<Option<CallFrameInstruction>> {
+ let convert_expression =
+ |x| Expression::from(x, from_cie.encoding(), None, None, None, convert_address);
+ // TODO: validate integer type conversions
+ Ok(Some(match from_instruction {
+ read::CallFrameInstruction::SetLoc { .. } => {
+ return Err(ConvertError::UnsupportedCfiInstruction);
+ }
+ read::CallFrameInstruction::AdvanceLoc { delta } => {
+ *offset += delta * from_cie.code_alignment_factor() as u32;
+ return Ok(None);
+ }
+ read::CallFrameInstruction::DefCfa { register, offset } => {
+ CallFrameInstruction::Cfa(register, offset as i32)
+ }
+ read::CallFrameInstruction::DefCfaSf {
+ register,
+ factored_offset,
+ } => {
+ let offset = factored_offset * from_cie.data_alignment_factor();
+ CallFrameInstruction::Cfa(register, offset as i32)
+ }
+ read::CallFrameInstruction::DefCfaRegister { register } => {
+ CallFrameInstruction::CfaRegister(register)
+ }
+
+ read::CallFrameInstruction::DefCfaOffset { offset } => {
+ CallFrameInstruction::CfaOffset(offset as i32)
+ }
+ read::CallFrameInstruction::DefCfaOffsetSf { factored_offset } => {
+ let offset = factored_offset * from_cie.data_alignment_factor();
+ CallFrameInstruction::CfaOffset(offset as i32)
+ }
+ read::CallFrameInstruction::DefCfaExpression { expression } => {
+ CallFrameInstruction::CfaExpression(convert_expression(expression)?)
+ }
+ read::CallFrameInstruction::Undefined { register } => {
+ CallFrameInstruction::Undefined(register)
+ }
+ read::CallFrameInstruction::SameValue { register } => {
+ CallFrameInstruction::SameValue(register)
+ }
+ read::CallFrameInstruction::Offset {
+ register,
+ factored_offset,
+ } => {
+ let offset = factored_offset as i64 * from_cie.data_alignment_factor();
+ CallFrameInstruction::Offset(register, offset as i32)
+ }
+ read::CallFrameInstruction::OffsetExtendedSf {
+ register,
+ factored_offset,
+ } => {
+ let offset = factored_offset * from_cie.data_alignment_factor();
+ CallFrameInstruction::Offset(register, offset as i32)
+ }
+ read::CallFrameInstruction::ValOffset {
+ register,
+ factored_offset,
+ } => {
+ let offset = factored_offset as i64 * from_cie.data_alignment_factor();
+ CallFrameInstruction::ValOffset(register, offset as i32)
+ }
+ read::CallFrameInstruction::ValOffsetSf {
+ register,
+ factored_offset,
+ } => {
+ let offset = factored_offset * from_cie.data_alignment_factor();
+ CallFrameInstruction::ValOffset(register, offset as i32)
+ }
+ read::CallFrameInstruction::Register {
+ dest_register,
+ src_register,
+ } => CallFrameInstruction::Register(dest_register, src_register),
+ read::CallFrameInstruction::Expression {
+ register,
+ expression,
+ } => CallFrameInstruction::Expression(register, convert_expression(expression)?),
+ read::CallFrameInstruction::ValExpression {
+ register,
+ expression,
+ } => CallFrameInstruction::ValExpression(register, convert_expression(expression)?),
+ read::CallFrameInstruction::Restore { register } => {
+ CallFrameInstruction::Restore(register)
+ }
+ read::CallFrameInstruction::RememberState => CallFrameInstruction::RememberState,
+ read::CallFrameInstruction::RestoreState => CallFrameInstruction::RestoreState,
+ read::CallFrameInstruction::ArgsSize { size } => {
+ CallFrameInstruction::ArgsSize(size as u32)
+ }
+ read::CallFrameInstruction::Nop => return Ok(None),
+ }))
+ }
+ }
+}
+
+#[cfg(test)]
+#[cfg(feature = "read")]
+mod tests {
+ use super::*;
+ use crate::arch::X86_64;
+ use crate::read;
+ use crate::write::EndianVec;
+ use crate::LittleEndian;
+
+ #[test]
+ fn test_frame_table() {
+ for &version in &[1, 3, 4] {
+ for &address_size in &[4, 8] {
+ for &format in &[Format::Dwarf32, Format::Dwarf64] {
+ let encoding = Encoding {
+ format,
+ version,
+ address_size,
+ };
+ let mut frames = FrameTable::default();
+
+ let cie1 = CommonInformationEntry::new(encoding, 1, 8, X86_64::RA);
+ let cie1_id = frames.add_cie(cie1.clone());
+ assert_eq!(cie1_id, frames.add_cie(cie1.clone()));
+
+ let mut cie2 = CommonInformationEntry::new(encoding, 1, 8, X86_64::RA);
+ cie2.lsda_encoding = Some(constants::DW_EH_PE_absptr);
+ cie2.personality =
+ Some((constants::DW_EH_PE_absptr, Address::Constant(0x1234)));
+ cie2.signal_trampoline = true;
+ let cie2_id = frames.add_cie(cie2.clone());
+ assert_ne!(cie1_id, cie2_id);
+ assert_eq!(cie2_id, frames.add_cie(cie2.clone()));
+
+ let fde1 = FrameDescriptionEntry::new(Address::Constant(0x1000), 0x10);
+ frames.add_fde(cie1_id, fde1.clone());
+
+ let fde2 = FrameDescriptionEntry::new(Address::Constant(0x2000), 0x20);
+ frames.add_fde(cie1_id, fde2.clone());
+
+ let mut fde3 = FrameDescriptionEntry::new(Address::Constant(0x3000), 0x30);
+ fde3.lsda = Some(Address::Constant(0x3300));
+ frames.add_fde(cie2_id, fde3.clone());
+
+ let mut fde4 = FrameDescriptionEntry::new(Address::Constant(0x4000), 0x40);
+ fde4.lsda = Some(Address::Constant(0x4400));
+ frames.add_fde(cie2_id, fde4.clone());
+
+ let mut cie3 = CommonInformationEntry::new(encoding, 1, 8, X86_64::RA);
+ cie3.fde_address_encoding = constants::DW_EH_PE_pcrel;
+ cie3.lsda_encoding = Some(constants::DW_EH_PE_pcrel);
+ cie3.personality = Some((constants::DW_EH_PE_pcrel, Address::Constant(0x1235)));
+ cie3.signal_trampoline = true;
+ let cie3_id = frames.add_cie(cie3.clone());
+ assert_ne!(cie2_id, cie3_id);
+ assert_eq!(cie3_id, frames.add_cie(cie3.clone()));
+
+ let mut fde5 = FrameDescriptionEntry::new(Address::Constant(0x5000), 0x50);
+ fde5.lsda = Some(Address::Constant(0x5500));
+ frames.add_fde(cie3_id, fde5.clone());
+
+ // Test writing `.debug_frame`.
+ let mut debug_frame = DebugFrame::from(EndianVec::new(LittleEndian));
+ frames.write_debug_frame(&mut debug_frame).unwrap();
+
+ let mut read_debug_frame =
+ read::DebugFrame::new(debug_frame.slice(), LittleEndian);
+ read_debug_frame.set_address_size(address_size);
+ let convert_frames = FrameTable::from(&read_debug_frame, &|address| {
+ Some(Address::Constant(address))
+ })
+ .unwrap();
+ assert_eq!(frames.cies, convert_frames.cies);
+ assert_eq!(frames.fdes.len(), convert_frames.fdes.len());
+ for (a, b) in frames.fdes.iter().zip(convert_frames.fdes.iter()) {
+ assert_eq!(a.1, b.1);
+ }
+
+ if version == 1 {
+ // Test writing `.eh_frame`.
+ let mut eh_frame = EhFrame::from(EndianVec::new(LittleEndian));
+ frames.write_eh_frame(&mut eh_frame).unwrap();
+
+ let mut read_eh_frame = read::EhFrame::new(eh_frame.slice(), LittleEndian);
+ read_eh_frame.set_address_size(address_size);
+ let convert_frames = FrameTable::from(&read_eh_frame, &|address| {
+ Some(Address::Constant(address))
+ })
+ .unwrap();
+ assert_eq!(frames.cies, convert_frames.cies);
+ assert_eq!(frames.fdes.len(), convert_frames.fdes.len());
+ for (a, b) in frames.fdes.iter().zip(convert_frames.fdes.iter()) {
+ assert_eq!(a.1, b.1);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ #[test]
+ fn test_frame_instruction() {
+ let mut expression = Expression::new();
+ expression.op_constu(0);
+
+ let cie_instructions = [
+ CallFrameInstruction::Cfa(X86_64::RSP, 8),
+ CallFrameInstruction::Offset(X86_64::RA, -8),
+ ];
+
+ let fde_instructions = [
+ (0, CallFrameInstruction::Cfa(X86_64::RSP, 0)),
+ (0, CallFrameInstruction::Cfa(X86_64::RSP, -8)),
+ (2, CallFrameInstruction::CfaRegister(X86_64::RBP)),
+ (4, CallFrameInstruction::CfaOffset(8)),
+ (4, CallFrameInstruction::CfaOffset(0)),
+ (4, CallFrameInstruction::CfaOffset(-8)),
+ (6, CallFrameInstruction::CfaExpression(expression.clone())),
+ (8, CallFrameInstruction::Restore(Register(1))),
+ (8, CallFrameInstruction::Restore(Register(101))),
+ (10, CallFrameInstruction::Undefined(Register(2))),
+ (12, CallFrameInstruction::SameValue(Register(3))),
+ (14, CallFrameInstruction::Offset(Register(4), 16)),
+ (14, CallFrameInstruction::Offset(Register(104), 16)),
+ (16, CallFrameInstruction::ValOffset(Register(5), -24)),
+ (16, CallFrameInstruction::ValOffset(Register(5), 24)),
+ (18, CallFrameInstruction::Register(Register(6), Register(7))),
+ (
+ 20,
+ CallFrameInstruction::Expression(Register(8), expression.clone()),
+ ),
+ (
+ 22,
+ CallFrameInstruction::ValExpression(Register(9), expression.clone()),
+ ),
+ (24 + 0x80, CallFrameInstruction::RememberState),
+ (26 + 0x280, CallFrameInstruction::RestoreState),
+ (28 + 0x20280, CallFrameInstruction::ArgsSize(23)),
+ ];
+
+ for &version in &[1, 3, 4] {
+ for &address_size in &[4, 8] {
+ for &format in &[Format::Dwarf32, Format::Dwarf64] {
+ let encoding = Encoding {
+ format,
+ version,
+ address_size,
+ };
+ let mut frames = FrameTable::default();
+
+ let mut cie = CommonInformationEntry::new(encoding, 2, 8, X86_64::RA);
+ for i in &cie_instructions {
+ cie.add_instruction(i.clone());
+ }
+ let cie_id = frames.add_cie(cie);
+
+ let mut fde = FrameDescriptionEntry::new(Address::Constant(0x1000), 0x10);
+ for (o, i) in &fde_instructions {
+ fde.add_instruction(*o, i.clone());
+ }
+ frames.add_fde(cie_id, fde);
+
+ let mut debug_frame = DebugFrame::from(EndianVec::new(LittleEndian));
+ frames.write_debug_frame(&mut debug_frame).unwrap();
+
+ let mut read_debug_frame =
+ read::DebugFrame::new(debug_frame.slice(), LittleEndian);
+ read_debug_frame.set_address_size(address_size);
+ let frames = FrameTable::from(&read_debug_frame, &|address| {
+ Some(Address::Constant(address))
+ })
+ .unwrap();
+
+ assert_eq!(
+ &frames.cies.get_index(0).unwrap().instructions,
+ &cie_instructions
+ );
+ assert_eq!(&frames.fdes[0].1.instructions, &fde_instructions);
+ }
+ }
+ }
+ }
+}
diff --git a/vendor/gimli-0.26.2/src/write/dwarf.rs b/vendor/gimli-0.26.2/src/write/dwarf.rs
new file mode 100644
index 000000000..ea507126a
--- /dev/null
+++ b/vendor/gimli-0.26.2/src/write/dwarf.rs
@@ -0,0 +1,138 @@
+use alloc::vec::Vec;
+
+use crate::common::Encoding;
+use crate::write::{
+ AbbreviationTable, LineProgram, LineStringTable, Result, Sections, StringTable, Unit,
+ UnitTable, Writer,
+};
+
+/// Writable DWARF information for more than one unit.
+#[derive(Debug, Default)]
+pub struct Dwarf {
+ /// A table of units. These are primarily stored in the `.debug_info` section,
+ /// but they also contain information that is stored in other sections.
+ pub units: UnitTable,
+
+ /// Extra line number programs that are not associated with a unit.
+ ///
+ /// These should only be used when generating DWARF5 line-only debug
+ /// information.
+ pub line_programs: Vec<LineProgram>,
+
+ /// A table of strings that will be stored in the `.debug_line_str` section.
+ pub line_strings: LineStringTable,
+
+ /// A table of strings that will be stored in the `.debug_str` section.
+ pub strings: StringTable,
+}
+
+impl Dwarf {
+ /// Create a new `Dwarf` instance.
+ #[inline]
+ pub fn new() -> Self {
+ Self::default()
+ }
+
+ /// Write the DWARF information to the given sections.
+ pub fn write<W: Writer>(&mut self, sections: &mut Sections<W>) -> Result<()> {
+ let line_strings = self.line_strings.write(&mut sections.debug_line_str)?;
+ let strings = self.strings.write(&mut sections.debug_str)?;
+ self.units.write(sections, &line_strings, &strings)?;
+ for line_program in &self.line_programs {
+ line_program.write(
+ &mut sections.debug_line,
+ line_program.encoding(),
+ &line_strings,
+ &strings,
+ )?;
+ }
+ Ok(())
+ }
+}
+
+/// Writable DWARF information for a single unit.
+#[derive(Debug)]
+pub struct DwarfUnit {
+ /// A unit. This is primarily stored in the `.debug_info` section,
+ /// but also contains information that is stored in other sections.
+ pub unit: Unit,
+
+ /// A table of strings that will be stored in the `.debug_line_str` section.
+ pub line_strings: LineStringTable,
+
+ /// A table of strings that will be stored in the `.debug_str` section.
+ pub strings: StringTable,
+}
+
+impl DwarfUnit {
+ /// Create a new `DwarfUnit`.
+ ///
+ /// Note: you should set `self.unit.line_program` after creation.
+ /// This cannot be done earlier because it may need to reference
+ /// `self.line_strings`.
+ pub fn new(encoding: Encoding) -> Self {
+ let unit = Unit::new(encoding, LineProgram::none());
+ DwarfUnit {
+ unit,
+ line_strings: LineStringTable::default(),
+ strings: StringTable::default(),
+ }
+ }
+
+ /// Write the DWARf information to the given sections.
+ pub fn write<W: Writer>(&mut self, sections: &mut Sections<W>) -> Result<()> {
+ let line_strings = self.line_strings.write(&mut sections.debug_line_str)?;
+ let strings = self.strings.write(&mut sections.debug_str)?;
+
+ let abbrev_offset = sections.debug_abbrev.offset();
+ let mut abbrevs = AbbreviationTable::default();
+
+ self.unit.write(
+ sections,
+ abbrev_offset,
+ &mut abbrevs,
+ &line_strings,
+ &strings,
+ )?;
+ // None should exist because we didn't give out any UnitId.
+ assert!(sections.debug_info_refs.is_empty());
+ assert!(sections.debug_loc_refs.is_empty());
+ assert!(sections.debug_loclists_refs.is_empty());
+
+ abbrevs.write(&mut sections.debug_abbrev)?;
+ Ok(())
+ }
+}
+
+#[cfg(feature = "read")]
+pub(crate) mod convert {
+ use super::*;
+ use crate::read::{self, Reader};
+ use crate::write::{Address, ConvertResult};
+
+ impl Dwarf {
+ /// Create a `write::Dwarf` by converting a `read::Dwarf`.
+ ///
+ /// `convert_address` is a function to convert read addresses into the `Address`
+ /// type. For non-relocatable addresses, this function may simply return
+ /// `Address::Constant(address)`. For relocatable addresses, it is the caller's
+ /// responsibility to determine the symbol and addend corresponding to the address
+ /// and return `Address::Symbol { symbol, addend }`.
+ pub fn from<R: Reader<Offset = usize>>(
+ dwarf: &read::Dwarf<R>,
+ convert_address: &dyn Fn(u64) -> Option<Address>,
+ ) -> ConvertResult<Dwarf> {
+ let mut line_strings = LineStringTable::default();
+ let mut strings = StringTable::default();
+ let units = UnitTable::from(dwarf, &mut line_strings, &mut strings, convert_address)?;
+ // TODO: convert the line programs that were not referenced by a unit.
+ let line_programs = Vec::new();
+ Ok(Dwarf {
+ units,
+ line_programs,
+ line_strings,
+ strings,
+ })
+ }
+ }
+}
diff --git a/vendor/gimli-0.26.2/src/write/endian_vec.rs b/vendor/gimli-0.26.2/src/write/endian_vec.rs
new file mode 100644
index 000000000..7b040606a
--- /dev/null
+++ b/vendor/gimli-0.26.2/src/write/endian_vec.rs
@@ -0,0 +1,117 @@
+use alloc::vec::Vec;
+use std::mem;
+
+use crate::endianity::Endianity;
+use crate::write::{Error, Result, Writer};
+
+/// A `Vec<u8>` with endianity metadata.
+///
+/// This implements the `Writer` trait, which is used for all writing of DWARF sections.
+#[derive(Debug, Clone)]
+pub struct EndianVec<Endian>
+where
+ Endian: Endianity,
+{
+ vec: Vec<u8>,
+ endian: Endian,
+}
+
+impl<Endian> EndianVec<Endian>
+where
+ Endian: Endianity,
+{
+ /// Construct an empty `EndianVec` with the given endianity.
+ pub fn new(endian: Endian) -> EndianVec<Endian> {
+ EndianVec {
+ vec: Vec::new(),
+ endian,
+ }
+ }
+
+ /// Return a reference to the raw slice.
+ pub fn slice(&self) -> &[u8] {
+ &self.vec
+ }
+
+ /// Convert into a `Vec<u8>`.
+ pub fn into_vec(self) -> Vec<u8> {
+ self.vec
+ }
+
+ /// Take any written data out of the `EndianVec`, leaving an empty `Vec` in its place.
+ pub fn take(&mut self) -> Vec<u8> {
+ let mut vec = Vec::new();
+ mem::swap(&mut self.vec, &mut vec);
+ vec
+ }
+}
+
+impl<Endian> Writer for EndianVec<Endian>
+where
+ Endian: Endianity,
+{
+ type Endian = Endian;
+
+ #[inline]
+ fn endian(&self) -> Self::Endian {
+ self.endian
+ }
+
+ #[inline]
+ fn len(&self) -> usize {
+ self.vec.len()
+ }
+
+ fn write(&mut self, bytes: &[u8]) -> Result<()> {
+ self.vec.extend(bytes);
+ Ok(())
+ }
+
+ fn write_at(&mut self, offset: usize, bytes: &[u8]) -> Result<()> {
+ if offset > self.vec.len() {
+ return Err(Error::OffsetOutOfBounds);
+ }
+ let to = &mut self.vec[offset..];
+ if bytes.len() > to.len() {
+ return Err(Error::LengthOutOfBounds);
+ }
+ let to = &mut to[..bytes.len()];
+ to.copy_from_slice(bytes);
+ Ok(())
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+ use crate::LittleEndian;
+
+ #[test]
+ fn test_endian_vec() {
+ let mut w = EndianVec::new(LittleEndian);
+ assert_eq!(w.endian(), LittleEndian);
+ assert_eq!(w.len(), 0);
+
+ w.write(&[1, 2]).unwrap();
+ assert_eq!(w.slice(), &[1, 2]);
+ assert_eq!(w.len(), 2);
+
+ w.write(&[3, 4, 5]).unwrap();
+ assert_eq!(w.slice(), &[1, 2, 3, 4, 5]);
+ assert_eq!(w.len(), 5);
+
+ w.write_at(0, &[6, 7]).unwrap();
+ assert_eq!(w.slice(), &[6, 7, 3, 4, 5]);
+ assert_eq!(w.len(), 5);
+
+ w.write_at(3, &[8, 9]).unwrap();
+ assert_eq!(w.slice(), &[6, 7, 3, 8, 9]);
+ assert_eq!(w.len(), 5);
+
+ assert_eq!(w.write_at(4, &[6, 7]), Err(Error::LengthOutOfBounds));
+ assert_eq!(w.write_at(5, &[6, 7]), Err(Error::LengthOutOfBounds));
+ assert_eq!(w.write_at(6, &[6, 7]), Err(Error::OffsetOutOfBounds));
+
+ assert_eq!(w.into_vec(), vec![6, 7, 3, 8, 9]);
+ }
+}
diff --git a/vendor/gimli-0.26.2/src/write/line.rs b/vendor/gimli-0.26.2/src/write/line.rs
new file mode 100644
index 000000000..310170d9a
--- /dev/null
+++ b/vendor/gimli-0.26.2/src/write/line.rs
@@ -0,0 +1,1960 @@
+use alloc::vec::Vec;
+use indexmap::{IndexMap, IndexSet};
+use std::ops::{Deref, DerefMut};
+
+use crate::common::{DebugLineOffset, Encoding, Format, LineEncoding, SectionId};
+use crate::constants;
+use crate::leb128;
+use crate::write::{
+ Address, DebugLineStrOffsets, DebugStrOffsets, Error, LineStringId, LineStringTable, Result,
+ Section, StringId, Writer,
+};
+
+/// The number assigned to the first special opcode.
+//
+// We output all instructions for all DWARF versions, since readers
+// should be able to ignore instructions they don't support.
+const OPCODE_BASE: u8 = 13;
+
+/// A line number program.
+#[derive(Debug, Clone)]
+pub struct LineProgram {
+ /// True if this line program was created with `LineProgram::none()`.
+ none: bool,
+ encoding: Encoding,
+ line_encoding: LineEncoding,
+
+ /// A list of source directory path names.
+ ///
+ /// If a path is relative, then the directory is located relative to the working
+ /// directory of the compilation unit.
+ ///
+ /// The first entry is for the working directory of the compilation unit.
+ directories: IndexSet<LineString>,
+
+ /// A list of source file entries.
+ ///
+ /// Each entry has a path name and a directory.
+ ///
+ /// If a path is a relative, then the file is located relative to the
+ /// directory. Otherwise the directory is meaningless.
+ ///
+ /// Does not include comp_file, even for version >= 5.
+ files: IndexMap<(LineString, DirectoryId), FileInfo>,
+
+ /// The primary source file of the compilation unit.
+ /// This is required for version >= 5, but we never reference it elsewhere
+ /// because DWARF defines DW_AT_decl_file=0 to mean not specified.
+ comp_file: (LineString, FileInfo),
+
+ /// True if the file entries may have valid timestamps.
+ ///
+ /// Entries may still have a timestamp of 0 even if this is set.
+ /// For version <= 4, this is ignored.
+ /// For version 5, this controls whether to emit `DW_LNCT_timestamp`.
+ pub file_has_timestamp: bool,
+
+ /// True if the file entries may have valid sizes.
+ ///
+ /// Entries may still have a size of 0 even if this is set.
+ /// For version <= 4, this is ignored.
+ /// For version 5, this controls whether to emit `DW_LNCT_size`.
+ pub file_has_size: bool,
+
+ /// True if the file entries have valid MD5 checksums.
+ ///
+ /// For version <= 4, this is ignored.
+ /// For version 5, this controls whether to emit `DW_LNCT_MD5`.
+ pub file_has_md5: bool,
+
+ prev_row: LineRow,
+ row: LineRow,
+ // TODO: this probably should be either rows or sequences instead
+ instructions: Vec<LineInstruction>,
+ in_sequence: bool,
+}
+
+impl LineProgram {
+ /// Create a new `LineProgram`.
+ ///
+ /// `comp_dir` defines the working directory of the compilation unit,
+ /// and must be the same as the `DW_AT_comp_dir` attribute
+ /// of the compilation unit DIE.
+ ///
+ /// `comp_file` and `comp_file_info` define the primary source file
+ /// of the compilation unit and must be the same as the `DW_AT_name`
+ /// attribute of the compilation unit DIE.
+ ///
+ /// # Panics
+ ///
+ /// Panics if `line_encoding.line_base` > 0.
+ ///
+ /// Panics if `line_encoding.line_base` + `line_encoding.line_range` <= 0.
+ ///
+ /// Panics if `comp_dir` is empty or contains a null byte.
+ ///
+ /// Panics if `comp_file` is empty or contains a null byte.
+ #[allow(clippy::too_many_arguments)]
+ #[allow(clippy::new_ret_no_self)]
+ pub fn new(
+ encoding: Encoding,
+ line_encoding: LineEncoding,
+ comp_dir: LineString,
+ comp_file: LineString,
+ comp_file_info: Option<FileInfo>,
+ ) -> LineProgram {
+ // We require a special opcode for a line advance of 0.
+ // See the debug_asserts in generate_row().
+ assert!(line_encoding.line_base <= 0);
+ assert!(line_encoding.line_base + line_encoding.line_range as i8 > 0);
+ let mut program = LineProgram {
+ none: false,
+ encoding,
+ line_encoding,
+ directories: IndexSet::new(),
+ files: IndexMap::new(),
+ comp_file: (comp_file, comp_file_info.unwrap_or_default()),
+ prev_row: LineRow::initial_state(line_encoding),
+ row: LineRow::initial_state(line_encoding),
+ instructions: Vec::new(),
+ in_sequence: false,
+ file_has_timestamp: false,
+ file_has_size: false,
+ file_has_md5: false,
+ };
+ // For all DWARF versions, directory index 0 is comp_dir.
+ // For version <= 4, the entry is implicit. We still add
+ // it here so that we use it, but we don't emit it.
+ program.add_directory(comp_dir);
+ program
+ }
+
+ /// Create a new `LineProgram` with no fields set.
+ ///
+ /// This can be used when the `LineProgram` will not be used.
+ ///
+ /// You should not attempt to add files or line instructions to
+ /// this line program, or write it to the `.debug_line` section.
+ pub fn none() -> Self {
+ let line_encoding = LineEncoding::default();
+ LineProgram {
+ none: true,
+ encoding: Encoding {
+ format: Format::Dwarf32,
+ version: 2,
+ address_size: 0,
+ },
+ line_encoding,
+ directories: IndexSet::new(),
+ files: IndexMap::new(),
+ comp_file: (LineString::String(Vec::new()), FileInfo::default()),
+ prev_row: LineRow::initial_state(line_encoding),
+ row: LineRow::initial_state(line_encoding),
+ instructions: Vec::new(),
+ in_sequence: false,
+ file_has_timestamp: false,
+ file_has_size: false,
+ file_has_md5: false,
+ }
+ }
+
+ /// Return true if this line program was created with `LineProgram::none()`.
+ #[inline]
+ pub fn is_none(&self) -> bool {
+ self.none
+ }
+
+ /// Return the encoding parameters for this line program.
+ #[inline]
+ pub fn encoding(&self) -> Encoding {
+ self.encoding
+ }
+
+ /// Return the DWARF version for this line program.
+ #[inline]
+ pub fn version(&self) -> u16 {
+ self.encoding.version
+ }
+
+ /// Return the address size in bytes for this line program.
+ #[inline]
+ pub fn address_size(&self) -> u8 {
+ self.encoding.address_size
+ }
+
+ /// Return the DWARF format for this line program.
+ #[inline]
+ pub fn format(&self) -> Format {
+ self.encoding.format
+ }
+
+ /// Return the id for the working directory of the compilation unit.
+ #[inline]
+ pub fn default_directory(&self) -> DirectoryId {
+ DirectoryId(0)
+ }
+
+ /// Add a directory entry and return its id.
+ ///
+ /// If the directory already exists, then return the id of the existing entry.
+ ///
+ /// If the path is relative, then the directory is located relative to the working
+ /// directory of the compilation unit.
+ ///
+ /// # Panics
+ ///
+ /// Panics if `directory` is empty or contains a null byte.
+ pub fn add_directory(&mut self, directory: LineString) -> DirectoryId {
+ if let LineString::String(ref val) = directory {
+ // For DWARF version <= 4, directories must not be empty.
+ // The first directory isn't emitted so skip the check for it.
+ if self.encoding.version <= 4 && !self.directories.is_empty() {
+ assert!(!val.is_empty());
+ }
+ assert!(!val.contains(&0));
+ }
+ let (index, _) = self.directories.insert_full(directory);
+ DirectoryId(index)
+ }
+
+ /// Get a reference to a directory entry.
+ ///
+ /// # Panics
+ ///
+ /// Panics if `id` is invalid.
+ pub fn get_directory(&self, id: DirectoryId) -> &LineString {
+ self.directories.get_index(id.0).unwrap()
+ }
+
+ /// Add a file entry and return its id.
+ ///
+ /// If the file already exists, then return the id of the existing entry.
+ ///
+ /// If the file path is relative, then the file is located relative
+ /// to the directory. Otherwise the directory is meaningless, but it
+ /// is still used as a key for file entries.
+ ///
+ /// If `info` is `None`, then new entries are assigned
+ /// default information, and existing entries are unmodified.
+ ///
+ /// If `info` is not `None`, then it is always assigned to the
+ /// entry, even if the entry already exists.
+ ///
+ /// # Panics
+ ///
+ /// Panics if 'file' is empty or contains a null byte.
+ pub fn add_file(
+ &mut self,
+ file: LineString,
+ directory: DirectoryId,
+ info: Option<FileInfo>,
+ ) -> FileId {
+ if let LineString::String(ref val) = file {
+ assert!(!val.is_empty());
+ assert!(!val.contains(&0));
+ }
+
+ let key = (file, directory);
+ let index = if let Some(info) = info {
+ let (index, _) = self.files.insert_full(key, info);
+ index
+ } else {
+ let entry = self.files.entry(key);
+ let index = entry.index();
+ entry.or_insert(FileInfo::default());
+ index
+ };
+ FileId::new(index)
+ }
+
+ /// Get a reference to a file entry.
+ ///
+ /// # Panics
+ ///
+ /// Panics if `id` is invalid.
+ pub fn get_file(&self, id: FileId) -> (&LineString, DirectoryId) {
+ match id.index() {
+ None => (&self.comp_file.0, DirectoryId(0)),
+ Some(index) => self
+ .files
+ .get_index(index)
+ .map(|entry| (&(entry.0).0, (entry.0).1))
+ .unwrap(),
+ }
+ }
+
+ /// Get a reference to the info for a file entry.
+ ///
+ /// # Panics
+ ///
+ /// Panics if `id` is invalid.
+ pub fn get_file_info(&self, id: FileId) -> &FileInfo {
+ match id.index() {
+ None => &self.comp_file.1,
+ Some(index) => self.files.get_index(index).map(|entry| entry.1).unwrap(),
+ }
+ }
+
+ /// Get a mutable reference to the info for a file entry.
+ ///
+ /// # Panics
+ ///
+ /// Panics if `id` is invalid.
+ pub fn get_file_info_mut(&mut self, id: FileId) -> &mut FileInfo {
+ match id.index() {
+ None => &mut self.comp_file.1,
+ Some(index) => self
+ .files
+ .get_index_mut(index)
+ .map(|entry| entry.1)
+ .unwrap(),
+ }
+ }
+
+ /// Begin a new sequence and set its base address.
+ ///
+ /// # Panics
+ ///
+ /// Panics if a sequence has already begun.
+ pub fn begin_sequence(&mut self, address: Option<Address>) {
+ assert!(!self.in_sequence);
+ self.in_sequence = true;
+ if let Some(address) = address {
+ self.instructions.push(LineInstruction::SetAddress(address));
+ }
+ }
+
+ /// End the sequence, and reset the row to its default values.
+ ///
+ /// Only the `address_offset` and op_index` fields of the current row are used.
+ ///
+ /// # Panics
+ ///
+ /// Panics if a sequence has not begun.
+ pub fn end_sequence(&mut self, address_offset: u64) {
+ assert!(self.in_sequence);
+ self.in_sequence = false;
+ self.row.address_offset = address_offset;
+ let op_advance = self.op_advance();
+ if op_advance != 0 {
+ self.instructions
+ .push(LineInstruction::AdvancePc(op_advance));
+ }
+ self.instructions.push(LineInstruction::EndSequence);
+ self.prev_row = LineRow::initial_state(self.line_encoding);
+ self.row = LineRow::initial_state(self.line_encoding);
+ }
+
+ /// Return true if a sequence has begun.
+ #[inline]
+ pub fn in_sequence(&self) -> bool {
+ self.in_sequence
+ }
+
+ /// Returns a reference to the data for the current row.
+ #[inline]
+ pub fn row(&mut self) -> &mut LineRow {
+ &mut self.row
+ }
+
+ /// Generates the line number information instructions for the current row.
+ ///
+ /// After the instructions are generated, it sets `discriminator` to 0, and sets
+ /// `basic_block`, `prologue_end`, and `epilogue_begin` to false.
+ ///
+ /// # Panics
+ ///
+ /// Panics if a sequence has not begun.
+ /// Panics if the address_offset decreases.
+ pub fn generate_row(&mut self) {
+ assert!(self.in_sequence);
+
+ // Output fields that are reset on every row.
+ if self.row.discriminator != 0 {
+ self.instructions
+ .push(LineInstruction::SetDiscriminator(self.row.discriminator));
+ self.row.discriminator = 0;
+ }
+ if self.row.basic_block {
+ self.instructions.push(LineInstruction::SetBasicBlock);
+ self.row.basic_block = false;
+ }
+ if self.row.prologue_end {
+ self.instructions.push(LineInstruction::SetPrologueEnd);
+ self.row.prologue_end = false;
+ }
+ if self.row.epilogue_begin {
+ self.instructions.push(LineInstruction::SetEpilogueBegin);
+ self.row.epilogue_begin = false;
+ }
+
+ // Output fields that are not reset on every row.
+ if self.row.is_statement != self.prev_row.is_statement {
+ self.instructions.push(LineInstruction::NegateStatement);
+ }
+ if self.row.file != self.prev_row.file {
+ self.instructions
+ .push(LineInstruction::SetFile(self.row.file));
+ }
+ if self.row.column != self.prev_row.column {
+ self.instructions
+ .push(LineInstruction::SetColumn(self.row.column));
+ }
+ if self.row.isa != self.prev_row.isa {
+ self.instructions
+ .push(LineInstruction::SetIsa(self.row.isa));
+ }
+
+ // Advance the line, address, and operation index.
+ let line_base = i64::from(self.line_encoding.line_base) as u64;
+ let line_range = u64::from(self.line_encoding.line_range);
+ let line_advance = self.row.line as i64 - self.prev_row.line as i64;
+ let op_advance = self.op_advance();
+
+ // Default to special advances of 0.
+ let special_base = u64::from(OPCODE_BASE);
+ // TODO: handle lack of special opcodes for 0 line advance
+ debug_assert!(self.line_encoding.line_base <= 0);
+ debug_assert!(self.line_encoding.line_base + self.line_encoding.line_range as i8 >= 0);
+ let special_default = special_base.wrapping_sub(line_base);
+ let mut special = special_default;
+ let mut use_special = false;
+
+ if line_advance != 0 {
+ let special_line = (line_advance as u64).wrapping_sub(line_base);
+ if special_line < line_range {
+ special = special_base + special_line;
+ use_special = true;
+ } else {
+ self.instructions
+ .push(LineInstruction::AdvanceLine(line_advance));
+ }
+ }
+
+ if op_advance != 0 {
+ // Using ConstAddPc can save a byte.
+ let (special_op_advance, const_add_pc) = if special + op_advance * line_range <= 255 {
+ (op_advance, false)
+ } else {
+ let op_range = (255 - special_base) / line_range;
+ (op_advance - op_range, true)
+ };
+
+ let special_op = special_op_advance * line_range;
+ if special + special_op <= 255 {
+ special += special_op;
+ use_special = true;
+ if const_add_pc {
+ self.instructions.push(LineInstruction::ConstAddPc);
+ }
+ } else {
+ self.instructions
+ .push(LineInstruction::AdvancePc(op_advance));
+ }
+ }
+
+ if use_special && special != special_default {
+ debug_assert!(special >= special_base);
+ debug_assert!(special <= 255);
+ self.instructions
+ .push(LineInstruction::Special(special as u8));
+ } else {
+ self.instructions.push(LineInstruction::Copy);
+ }
+
+ self.prev_row = self.row;
+ }
+
+ fn op_advance(&self) -> u64 {
+ debug_assert!(self.row.address_offset >= self.prev_row.address_offset);
+ let mut address_advance = self.row.address_offset - self.prev_row.address_offset;
+ if self.line_encoding.minimum_instruction_length != 1 {
+ debug_assert_eq!(
+ self.row.address_offset % u64::from(self.line_encoding.minimum_instruction_length),
+ 0
+ );
+ address_advance /= u64::from(self.line_encoding.minimum_instruction_length);
+ }
+ address_advance * u64::from(self.line_encoding.maximum_operations_per_instruction)
+ + self.row.op_index
+ - self.prev_row.op_index
+ }
+
+ /// Returns true if the line number program has no instructions.
+ ///
+ /// Does not check the file or directory entries.
+ #[inline]
+ pub fn is_empty(&self) -> bool {
+ self.instructions.is_empty()
+ }
+
+ /// Write the line number program to the given section.
+ ///
+ /// # Panics
+ ///
+ /// Panics if `self.is_none()`.
+ pub fn write<W: Writer>(
+ &self,
+ w: &mut DebugLine<W>,
+ encoding: Encoding,
+ debug_line_str_offsets: &DebugLineStrOffsets,
+ debug_str_offsets: &DebugStrOffsets,
+ ) -> Result<DebugLineOffset> {
+ assert!(!self.is_none());
+
+ if encoding.version < self.version()
+ || encoding.format != self.format()
+ || encoding.address_size != self.address_size()
+ {
+ return Err(Error::IncompatibleLineProgramEncoding);
+ }
+
+ let offset = w.offset();
+
+ let length_offset = w.write_initial_length(self.format())?;
+ let length_base = w.len();
+
+ if self.version() < 2 || self.version() > 5 {
+ return Err(Error::UnsupportedVersion(self.version()));
+ }
+ w.write_u16(self.version())?;
+
+ if self.version() >= 5 {
+ w.write_u8(self.address_size())?;
+ // Segment selector size.
+ w.write_u8(0)?;
+ }
+
+ let header_length_offset = w.len();
+ w.write_udata(0, self.format().word_size())?;
+ let header_length_base = w.len();
+
+ w.write_u8(self.line_encoding.minimum_instruction_length)?;
+ if self.version() >= 4 {
+ w.write_u8(self.line_encoding.maximum_operations_per_instruction)?;
+ } else if self.line_encoding.maximum_operations_per_instruction != 1 {
+ return Err(Error::NeedVersion(4));
+ };
+ w.write_u8(if self.line_encoding.default_is_stmt {
+ 1
+ } else {
+ 0
+ })?;
+ w.write_u8(self.line_encoding.line_base as u8)?;
+ w.write_u8(self.line_encoding.line_range)?;
+ w.write_u8(OPCODE_BASE)?;
+ w.write(&[0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1])?;
+
+ if self.version() <= 4 {
+ // The first directory is stored as DW_AT_comp_dir.
+ for dir in self.directories.iter().skip(1) {
+ dir.write(
+ w,
+ constants::DW_FORM_string,
+ self.encoding,
+ debug_line_str_offsets,
+ debug_str_offsets,
+ )?;
+ }
+ w.write_u8(0)?;
+
+ for ((file, dir), info) in self.files.iter() {
+ file.write(
+ w,
+ constants::DW_FORM_string,
+ self.encoding,
+ debug_line_str_offsets,
+ debug_str_offsets,
+ )?;
+ w.write_uleb128(dir.0 as u64)?;
+ w.write_uleb128(info.timestamp)?;
+ w.write_uleb128(info.size)?;
+ }
+ w.write_u8(0)?;
+ } else {
+ // Directory entry formats (only ever 1).
+ w.write_u8(1)?;
+ w.write_uleb128(u64::from(constants::DW_LNCT_path.0))?;
+ let dir_form = self.directories.get_index(0).unwrap().form();
+ w.write_uleb128(dir_form.0.into())?;
+
+ // Directory entries.
+ w.write_uleb128(self.directories.len() as u64)?;
+ for dir in self.directories.iter() {
+ dir.write(
+ w,
+ dir_form,
+ self.encoding,
+ debug_line_str_offsets,
+ debug_str_offsets,
+ )?;
+ }
+
+ // File name entry formats.
+ let count = 2
+ + if self.file_has_timestamp { 1 } else { 0 }
+ + if self.file_has_size { 1 } else { 0 }
+ + if self.file_has_md5 { 1 } else { 0 };
+ w.write_u8(count)?;
+ w.write_uleb128(u64::from(constants::DW_LNCT_path.0))?;
+ let file_form = self.comp_file.0.form();
+ w.write_uleb128(file_form.0.into())?;
+ w.write_uleb128(u64::from(constants::DW_LNCT_directory_index.0))?;
+ w.write_uleb128(constants::DW_FORM_udata.0.into())?;
+ if self.file_has_timestamp {
+ w.write_uleb128(u64::from(constants::DW_LNCT_timestamp.0))?;
+ w.write_uleb128(constants::DW_FORM_udata.0.into())?;
+ }
+ if self.file_has_size {
+ w.write_uleb128(u64::from(constants::DW_LNCT_size.0))?;
+ w.write_uleb128(constants::DW_FORM_udata.0.into())?;
+ }
+ if self.file_has_md5 {
+ w.write_uleb128(u64::from(constants::DW_LNCT_MD5.0))?;
+ w.write_uleb128(constants::DW_FORM_data16.0.into())?;
+ }
+
+ // File name entries.
+ w.write_uleb128(self.files.len() as u64 + 1)?;
+ let mut write_file = |file: &LineString, dir: DirectoryId, info: &FileInfo| {
+ file.write(
+ w,
+ file_form,
+ self.encoding,
+ debug_line_str_offsets,
+ debug_str_offsets,
+ )?;
+ w.write_uleb128(dir.0 as u64)?;
+ if self.file_has_timestamp {
+ w.write_uleb128(info.timestamp)?;
+ }
+ if self.file_has_size {
+ w.write_uleb128(info.size)?;
+ }
+ if self.file_has_md5 {
+ w.write(&info.md5)?;
+ }
+ Ok(())
+ };
+ write_file(&self.comp_file.0, DirectoryId(0), &self.comp_file.1)?;
+ for ((file, dir), info) in self.files.iter() {
+ write_file(file, *dir, info)?;
+ }
+ }
+
+ let header_length = (w.len() - header_length_base) as u64;
+ w.write_udata_at(
+ header_length_offset,
+ header_length,
+ self.format().word_size(),
+ )?;
+
+ for instruction in &self.instructions {
+ instruction.write(w, self.address_size())?;
+ }
+
+ let length = (w.len() - length_base) as u64;
+ w.write_initial_length_at(length_offset, length, self.format())?;
+
+ Ok(offset)
+ }
+}
+
+/// A row in the line number table that corresponds to a machine instruction.
+#[derive(Debug, Clone, Copy)]
+pub struct LineRow {
+ /// The offset of the instruction from the start address of the sequence.
+ pub address_offset: u64,
+ /// The index of an operation within a VLIW instruction.
+ ///
+ /// The index of the first operation is 0.
+ /// Set to 0 for non-VLIW instructions.
+ pub op_index: u64,
+
+ /// The source file corresponding to the instruction.
+ pub file: FileId,
+ /// The line number within the source file.
+ ///
+ /// Lines are numbered beginning at 1. Set to 0 if there is no source line.
+ pub line: u64,
+ /// The column number within the source line.
+ ///
+ /// Columns are numbered beginning at 1. Set to 0 for the "left edge" of the line.
+ pub column: u64,
+ /// An additional discriminator used to distinguish between source locations.
+ /// This value is assigned arbitrarily by the DWARF producer.
+ pub discriminator: u64,
+
+ /// Set to true if the instruction is a recommended breakpoint for a statement.
+ pub is_statement: bool,
+ /// Set to true if the instruction is the beginning of a basic block.
+ pub basic_block: bool,
+ /// Set to true if the instruction is a recommended breakpoint at the entry of a
+ /// function.
+ pub prologue_end: bool,
+ /// Set to true if the instruction is a recommended breakpoint prior to the exit of
+ /// a function.
+ pub epilogue_begin: bool,
+
+ /// The instruction set architecture of the instruction.
+ ///
+ /// Set to 0 for the default ISA. Other values are defined by the architecture ABI.
+ pub isa: u64,
+}
+
+impl LineRow {
+ /// Return the initial state as specified in the DWARF standard.
+ fn initial_state(line_encoding: LineEncoding) -> Self {
+ LineRow {
+ address_offset: 0,
+ op_index: 0,
+
+ file: FileId::initial_state(),
+ line: 1,
+ column: 0,
+ discriminator: 0,
+
+ is_statement: line_encoding.default_is_stmt,
+ basic_block: false,
+ prologue_end: false,
+ epilogue_begin: false,
+
+ isa: 0,
+ }
+ }
+}
+
+/// An instruction in a line number program.
+#[derive(Debug, Clone, Copy, PartialEq, Eq)]
+enum LineInstruction {
+ // Special opcodes
+ Special(u8),
+
+ // Standard opcodes
+ Copy,
+ AdvancePc(u64),
+ AdvanceLine(i64),
+ SetFile(FileId),
+ SetColumn(u64),
+ NegateStatement,
+ SetBasicBlock,
+ ConstAddPc,
+ // DW_LNS_fixed_advance_pc is not supported.
+ SetPrologueEnd,
+ SetEpilogueBegin,
+ SetIsa(u64),
+
+ // Extended opcodes
+ EndSequence,
+ // TODO: this doubles the size of this enum.
+ SetAddress(Address),
+ // DW_LNE_define_file is not supported.
+ SetDiscriminator(u64),
+}
+
+impl LineInstruction {
+ /// Write the line number instruction to the given section.
+ fn write<W: Writer>(self, w: &mut DebugLine<W>, address_size: u8) -> Result<()> {
+ use self::LineInstruction::*;
+ match self {
+ Special(val) => w.write_u8(val)?,
+ Copy => w.write_u8(constants::DW_LNS_copy.0)?,
+ AdvancePc(val) => {
+ w.write_u8(constants::DW_LNS_advance_pc.0)?;
+ w.write_uleb128(val)?;
+ }
+ AdvanceLine(val) => {
+ w.write_u8(constants::DW_LNS_advance_line.0)?;
+ w.write_sleb128(val)?;
+ }
+ SetFile(val) => {
+ w.write_u8(constants::DW_LNS_set_file.0)?;
+ w.write_uleb128(val.raw())?;
+ }
+ SetColumn(val) => {
+ w.write_u8(constants::DW_LNS_set_column.0)?;
+ w.write_uleb128(val)?;
+ }
+ NegateStatement => w.write_u8(constants::DW_LNS_negate_stmt.0)?,
+ SetBasicBlock => w.write_u8(constants::DW_LNS_set_basic_block.0)?,
+ ConstAddPc => w.write_u8(constants::DW_LNS_const_add_pc.0)?,
+ SetPrologueEnd => w.write_u8(constants::DW_LNS_set_prologue_end.0)?,
+ SetEpilogueBegin => w.write_u8(constants::DW_LNS_set_epilogue_begin.0)?,
+ SetIsa(val) => {
+ w.write_u8(constants::DW_LNS_set_isa.0)?;
+ w.write_uleb128(val)?;
+ }
+ EndSequence => {
+ w.write_u8(0)?;
+ w.write_uleb128(1)?;
+ w.write_u8(constants::DW_LNE_end_sequence.0)?;
+ }
+ SetAddress(address) => {
+ w.write_u8(0)?;
+ w.write_uleb128(1 + u64::from(address_size))?;
+ w.write_u8(constants::DW_LNE_set_address.0)?;
+ w.write_address(address, address_size)?;
+ }
+ SetDiscriminator(val) => {
+ let mut bytes = [0u8; 10];
+ // bytes is long enough so this will never fail.
+ let len = leb128::write::unsigned(&mut { &mut bytes[..] }, val).unwrap();
+ w.write_u8(0)?;
+ w.write_uleb128(1 + len as u64)?;
+ w.write_u8(constants::DW_LNE_set_discriminator.0)?;
+ w.write(&bytes[..len])?;
+ }
+ }
+ Ok(())
+ }
+}
+
+/// A string value for use in defining paths in line number programs.
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub enum LineString {
+ /// A slice of bytes representing a string. Must not include null bytes.
+ /// Not guaranteed to be UTF-8 or anything like that.
+ String(Vec<u8>),
+
+ /// A reference to a string in the `.debug_str` section.
+ StringRef(StringId),
+
+ /// A reference to a string in the `.debug_line_str` section.
+ LineStringRef(LineStringId),
+}
+
+impl LineString {
+ /// Create a `LineString` using the normal form for the given encoding.
+ pub fn new<T>(val: T, encoding: Encoding, line_strings: &mut LineStringTable) -> Self
+ where
+ T: Into<Vec<u8>>,
+ {
+ let val = val.into();
+ if encoding.version <= 4 {
+ LineString::String(val)
+ } else {
+ LineString::LineStringRef(line_strings.add(val))
+ }
+ }
+
+ fn form(&self) -> constants::DwForm {
+ match *self {
+ LineString::String(..) => constants::DW_FORM_string,
+ LineString::StringRef(..) => constants::DW_FORM_strp,
+ LineString::LineStringRef(..) => constants::DW_FORM_line_strp,
+ }
+ }
+
+ fn write<W: Writer>(
+ &self,
+ w: &mut DebugLine<W>,
+ form: constants::DwForm,
+ encoding: Encoding,
+ debug_line_str_offsets: &DebugLineStrOffsets,
+ debug_str_offsets: &DebugStrOffsets,
+ ) -> Result<()> {
+ if form != self.form() {
+ return Err(Error::LineStringFormMismatch);
+ }
+
+ match *self {
+ LineString::String(ref val) => {
+ if encoding.version <= 4 {
+ debug_assert!(!val.is_empty());
+ }
+ w.write(val)?;
+ w.write_u8(0)?;
+ }
+ LineString::StringRef(val) => {
+ if encoding.version < 5 {
+ return Err(Error::NeedVersion(5));
+ }
+ w.write_offset(
+ debug_str_offsets.get(val).0,
+ SectionId::DebugStr,
+ encoding.format.word_size(),
+ )?;
+ }
+ LineString::LineStringRef(val) => {
+ if encoding.version < 5 {
+ return Err(Error::NeedVersion(5));
+ }
+ w.write_offset(
+ debug_line_str_offsets.get(val).0,
+ SectionId::DebugLineStr,
+ encoding.format.word_size(),
+ )?;
+ }
+ }
+ Ok(())
+ }
+}
+
+/// An identifier for a directory in a `LineProgram`.
+///
+/// Defaults to the working directory of the compilation unit.
+#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
+pub struct DirectoryId(usize);
+
+// Force FileId access via the methods.
+mod id {
+ /// An identifier for a file in a `LineProgram`.
+ #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
+ pub struct FileId(usize);
+
+ impl FileId {
+ /// Create a FileId given an index into `LineProgram::files`.
+ pub(crate) fn new(index: usize) -> Self {
+ FileId(index + 1)
+ }
+
+ /// The index of the file in `LineProgram::files`.
+ pub(super) fn index(self) -> Option<usize> {
+ if self.0 == 0 {
+ None
+ } else {
+ Some(self.0 - 1)
+ }
+ }
+
+ /// The initial state of the file register.
+ pub(super) fn initial_state() -> Self {
+ FileId(1)
+ }
+
+ /// The raw value used when writing.
+ pub(crate) fn raw(self) -> u64 {
+ self.0 as u64
+ }
+
+ /// The id for file index 0 in DWARF version 5.
+ /// Only used when converting.
+ // Used for tests only.
+ #[allow(unused)]
+ pub(super) fn zero() -> Self {
+ FileId(0)
+ }
+ }
+}
+pub use self::id::*;
+
+/// Extra information for file in a `LineProgram`.
+#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)]
+pub struct FileInfo {
+ /// The implementation defined timestamp of the last modification of the file,
+ /// or 0 if not available.
+ pub timestamp: u64,
+
+ /// The size of the file in bytes, or 0 if not available.
+ pub size: u64,
+
+ /// A 16-byte MD5 digest of the file contents.
+ ///
+ /// Only used if version >= 5 and `LineProgram::file_has_md5` is `true`.
+ pub md5: [u8; 16],
+}
+
+define_section!(
+ DebugLine,
+ DebugLineOffset,
+ "A writable `.debug_line` section."
+);
+
+#[cfg(feature = "read")]
+mod convert {
+ use super::*;
+ use crate::read::{self, Reader};
+ use crate::write::{self, ConvertError, ConvertResult};
+
+ impl LineProgram {
+ /// Create a line number program by reading the data from the given program.
+ ///
+ /// Return the program and a mapping from file index to `FileId`.
+ pub fn from<R: Reader<Offset = usize>>(
+ mut from_program: read::IncompleteLineProgram<R>,
+ dwarf: &read::Dwarf<R>,
+ line_strings: &mut write::LineStringTable,
+ strings: &mut write::StringTable,
+ convert_address: &dyn Fn(u64) -> Option<Address>,
+ ) -> ConvertResult<(LineProgram, Vec<FileId>)> {
+ // Create mappings in case the source has duplicate files or directories.
+ let mut dirs = Vec::new();
+ let mut files = Vec::new();
+
+ let mut program = {
+ let from_header = from_program.header();
+ let encoding = from_header.encoding();
+
+ let comp_dir = match from_header.directory(0) {
+ Some(comp_dir) => LineString::from(comp_dir, dwarf, line_strings, strings)?,
+ None => LineString::new(&[][..], encoding, line_strings),
+ };
+
+ let (comp_name, comp_file_info) = match from_header.file(0) {
+ Some(comp_file) => {
+ if comp_file.directory_index() != 0 {
+ return Err(ConvertError::InvalidDirectoryIndex);
+ }
+ (
+ LineString::from(comp_file.path_name(), dwarf, line_strings, strings)?,
+ Some(FileInfo {
+ timestamp: comp_file.timestamp(),
+ size: comp_file.size(),
+ md5: *comp_file.md5(),
+ }),
+ )
+ }
+ None => (LineString::new(&[][..], encoding, line_strings), None),
+ };
+
+ if from_header.line_base() > 0 {
+ return Err(ConvertError::InvalidLineBase);
+ }
+ let mut program = LineProgram::new(
+ encoding,
+ from_header.line_encoding(),
+ comp_dir,
+ comp_name,
+ comp_file_info,
+ );
+
+ let file_skip;
+ if from_header.version() <= 4 {
+ // The first directory is implicit.
+ dirs.push(DirectoryId(0));
+ // A file index of 0 is invalid for version <= 4, but putting
+ // something there makes the indexing easier.
+ file_skip = 0;
+ files.push(FileId::zero());
+ } else {
+ // We don't add the first file to `files`, but still allow
+ // it to be referenced from converted instructions.
+ file_skip = 1;
+ files.push(FileId::zero());
+ }
+
+ for from_dir in from_header.include_directories() {
+ let from_dir =
+ LineString::from(from_dir.clone(), dwarf, line_strings, strings)?;
+ dirs.push(program.add_directory(from_dir));
+ }
+
+ program.file_has_timestamp = from_header.file_has_timestamp();
+ program.file_has_size = from_header.file_has_size();
+ program.file_has_md5 = from_header.file_has_md5();
+ for from_file in from_header.file_names().iter().skip(file_skip) {
+ let from_name =
+ LineString::from(from_file.path_name(), dwarf, line_strings, strings)?;
+ let from_dir = from_file.directory_index();
+ if from_dir >= dirs.len() as u64 {
+ return Err(ConvertError::InvalidDirectoryIndex);
+ }
+ let from_dir = dirs[from_dir as usize];
+ let from_info = Some(FileInfo {
+ timestamp: from_file.timestamp(),
+ size: from_file.size(),
+ md5: *from_file.md5(),
+ });
+ files.push(program.add_file(from_name, from_dir, from_info));
+ }
+
+ program
+ };
+
+ // We can't use the `from_program.rows()` because that wouldn't let
+ // us preserve address relocations.
+ let mut from_row = read::LineRow::new(from_program.header());
+ let mut instructions = from_program.header().instructions();
+ let mut address = None;
+ while let Some(instruction) = instructions.next_instruction(from_program.header())? {
+ match instruction {
+ read::LineInstruction::SetAddress(val) => {
+ if program.in_sequence() {
+ return Err(ConvertError::UnsupportedLineInstruction);
+ }
+ match convert_address(val) {
+ Some(val) => address = Some(val),
+ None => return Err(ConvertError::InvalidAddress),
+ }
+ from_row.execute(read::LineInstruction::SetAddress(0), &mut from_program);
+ }
+ read::LineInstruction::DefineFile(_) => {
+ return Err(ConvertError::UnsupportedLineInstruction);
+ }
+ _ => {
+ if from_row.execute(instruction, &mut from_program) {
+ if !program.in_sequence() {
+ program.begin_sequence(address);
+ address = None;
+ }
+ if from_row.end_sequence() {
+ program.end_sequence(from_row.address());
+ } else {
+ program.row().address_offset = from_row.address();
+ program.row().op_index = from_row.op_index();
+ program.row().file = {
+ let file = from_row.file_index();
+ if file >= files.len() as u64 {
+ return Err(ConvertError::InvalidFileIndex);
+ }
+ if file == 0 && program.version() <= 4 {
+ return Err(ConvertError::InvalidFileIndex);
+ }
+ files[file as usize]
+ };
+ program.row().line = match from_row.line() {
+ Some(line) => line.get(),
+ None => 0,
+ };
+ program.row().column = match from_row.column() {
+ read::ColumnType::LeftEdge => 0,
+ read::ColumnType::Column(val) => val.get(),
+ };
+ program.row().discriminator = from_row.discriminator();
+ program.row().is_statement = from_row.is_stmt();
+ program.row().basic_block = from_row.basic_block();
+ program.row().prologue_end = from_row.prologue_end();
+ program.row().epilogue_begin = from_row.epilogue_begin();
+ program.row().isa = from_row.isa();
+ program.generate_row();
+ }
+ from_row.reset(from_program.header());
+ }
+ }
+ };
+ }
+ Ok((program, files))
+ }
+ }
+
+ impl LineString {
+ fn from<R: Reader<Offset = usize>>(
+ from_attr: read::AttributeValue<R>,
+ dwarf: &read::Dwarf<R>,
+ line_strings: &mut write::LineStringTable,
+ strings: &mut write::StringTable,
+ ) -> ConvertResult<LineString> {
+ Ok(match from_attr {
+ read::AttributeValue::String(r) => LineString::String(r.to_slice()?.to_vec()),
+ read::AttributeValue::DebugStrRef(offset) => {
+ let r = dwarf.debug_str.get_str(offset)?;
+ let id = strings.add(r.to_slice()?);
+ LineString::StringRef(id)
+ }
+ read::AttributeValue::DebugLineStrRef(offset) => {
+ let r = dwarf.debug_line_str.get_str(offset)?;
+ let id = line_strings.add(r.to_slice()?);
+ LineString::LineStringRef(id)
+ }
+ _ => return Err(ConvertError::UnsupportedLineStringForm),
+ })
+ }
+ }
+}
+
+#[cfg(test)]
+#[cfg(feature = "read")]
+mod tests {
+ use super::*;
+ use crate::read;
+ use crate::write::{DebugLineStr, DebugStr, EndianVec, StringTable};
+ use crate::LittleEndian;
+
+ #[test]
+ fn test_line_program_table() {
+ let dir1 = LineString::String(b"dir1".to_vec());
+ let file1 = LineString::String(b"file1".to_vec());
+ let dir2 = LineString::String(b"dir2".to_vec());
+ let file2 = LineString::String(b"file2".to_vec());
+
+ let mut programs = Vec::new();
+ for &version in &[2, 3, 4, 5] {
+ for &address_size in &[4, 8] {
+ for &format in &[Format::Dwarf32, Format::Dwarf64] {
+ let encoding = Encoding {
+ format,
+ version,
+ address_size,
+ };
+ let mut program = LineProgram::new(
+ encoding,
+ LineEncoding::default(),
+ dir1.clone(),
+ file1.clone(),
+ None,
+ );
+
+ {
+ assert_eq!(&dir1, program.get_directory(program.default_directory()));
+ program.file_has_timestamp = true;
+ program.file_has_size = true;
+ if encoding.version >= 5 {
+ program.file_has_md5 = true;
+ }
+
+ let dir_id = program.add_directory(dir2.clone());
+ assert_eq!(&dir2, program.get_directory(dir_id));
+ assert_eq!(dir_id, program.add_directory(dir2.clone()));
+
+ let file_info = FileInfo {
+ timestamp: 1,
+ size: 2,
+ md5: if encoding.version >= 5 {
+ [3; 16]
+ } else {
+ [0; 16]
+ },
+ };
+ let file_id = program.add_file(file2.clone(), dir_id, Some(file_info));
+ assert_eq!((&file2, dir_id), program.get_file(file_id));
+ assert_eq!(file_info, *program.get_file_info(file_id));
+
+ program.get_file_info_mut(file_id).size = 3;
+ assert_ne!(file_info, *program.get_file_info(file_id));
+ assert_eq!(file_id, program.add_file(file2.clone(), dir_id, None));
+ assert_ne!(file_info, *program.get_file_info(file_id));
+ assert_eq!(
+ file_id,
+ program.add_file(file2.clone(), dir_id, Some(file_info))
+ );
+ assert_eq!(file_info, *program.get_file_info(file_id));
+
+ programs.push((program, file_id, encoding));
+ }
+ }
+ }
+ }
+
+ let debug_line_str_offsets = DebugLineStrOffsets::none();
+ let debug_str_offsets = DebugStrOffsets::none();
+ let mut debug_line = DebugLine::from(EndianVec::new(LittleEndian));
+ let mut debug_line_offsets = Vec::new();
+ for (program, _, encoding) in &programs {
+ debug_line_offsets.push(
+ program
+ .write(
+ &mut debug_line,
+ *encoding,
+ &debug_line_str_offsets,
+ &debug_str_offsets,
+ )
+ .unwrap(),
+ );
+ }
+
+ let read_debug_line = read::DebugLine::new(debug_line.slice(), LittleEndian);
+
+ let convert_address = &|address| Some(Address::Constant(address));
+ for ((program, file_id, encoding), offset) in programs.iter().zip(debug_line_offsets.iter())
+ {
+ let read_program = read_debug_line
+ .program(
+ *offset,
+ encoding.address_size,
+ Some(read::EndianSlice::new(b"dir1", LittleEndian)),
+ Some(read::EndianSlice::new(b"file1", LittleEndian)),
+ )
+ .unwrap();
+
+ let dwarf = read::Dwarf::default();
+ let mut convert_line_strings = LineStringTable::default();
+ let mut convert_strings = StringTable::default();
+ let (convert_program, convert_files) = LineProgram::from(
+ read_program,
+ &dwarf,
+ &mut convert_line_strings,
+ &mut convert_strings,
+ convert_address,
+ )
+ .unwrap();
+ assert_eq!(convert_program.version(), program.version());
+ assert_eq!(convert_program.address_size(), program.address_size());
+ assert_eq!(convert_program.format(), program.format());
+
+ let convert_file_id = convert_files[file_id.raw() as usize];
+ let (file, dir) = program.get_file(*file_id);
+ let (convert_file, convert_dir) = convert_program.get_file(convert_file_id);
+ assert_eq!(file, convert_file);
+ assert_eq!(
+ program.get_directory(dir),
+ convert_program.get_directory(convert_dir)
+ );
+ assert_eq!(
+ program.get_file_info(*file_id),
+ convert_program.get_file_info(convert_file_id)
+ );
+ }
+ }
+
+ #[test]
+ fn test_line_row() {
+ let dir1 = &b"dir1"[..];
+ let file1 = &b"file1"[..];
+ let file2 = &b"file2"[..];
+ let convert_address = &|address| Some(Address::Constant(address));
+
+ let debug_line_str_offsets = DebugLineStrOffsets::none();
+ let debug_str_offsets = DebugStrOffsets::none();
+
+ for &version in &[2, 3, 4, 5] {
+ for &address_size in &[4, 8] {
+ for &format in &[Format::Dwarf32, Format::Dwarf64] {
+ let encoding = Encoding {
+ format,
+ version,
+ address_size,
+ };
+ let line_base = -5;
+ let line_range = 14;
+ let neg_line_base = (-line_base) as u8;
+ let mut program = LineProgram::new(
+ encoding,
+ LineEncoding {
+ line_base,
+ line_range,
+ ..Default::default()
+ },
+ LineString::String(dir1.to_vec()),
+ LineString::String(file1.to_vec()),
+ None,
+ );
+ let dir_id = program.default_directory();
+ program.add_file(LineString::String(file1.to_vec()), dir_id, None);
+ let file_id =
+ program.add_file(LineString::String(file2.to_vec()), dir_id, None);
+
+ // Test sequences.
+ {
+ let mut program = program.clone();
+ let address = Address::Constant(0x12);
+ program.begin_sequence(Some(address));
+ assert_eq!(
+ program.instructions,
+ vec![LineInstruction::SetAddress(address)]
+ );
+ }
+
+ {
+ let mut program = program.clone();
+ program.begin_sequence(None);
+ assert_eq!(program.instructions, Vec::new());
+ }
+
+ {
+ let mut program = program.clone();
+ program.begin_sequence(None);
+ program.end_sequence(0x1234);
+ assert_eq!(
+ program.instructions,
+ vec![
+ LineInstruction::AdvancePc(0x1234),
+ LineInstruction::EndSequence
+ ]
+ );
+ }
+
+ // Create a base program.
+ program.begin_sequence(None);
+ program.row.line = 0x1000;
+ program.generate_row();
+ let base_row = program.row;
+ let base_instructions = program.instructions.clone();
+
+ // Create test cases.
+ let mut tests = Vec::new();
+
+ let row = base_row;
+ tests.push((row, vec![LineInstruction::Copy]));
+
+ let mut row = base_row;
+ row.line -= u64::from(neg_line_base);
+ tests.push((row, vec![LineInstruction::Special(OPCODE_BASE)]));
+
+ let mut row = base_row;
+ row.line += u64::from(line_range) - 1;
+ row.line -= u64::from(neg_line_base);
+ tests.push((
+ row,
+ vec![LineInstruction::Special(OPCODE_BASE + line_range - 1)],
+ ));
+
+ let mut row = base_row;
+ row.line += u64::from(line_range);
+ row.line -= u64::from(neg_line_base);
+ tests.push((
+ row,
+ vec![
+ LineInstruction::AdvanceLine(i64::from(line_range - neg_line_base)),
+ LineInstruction::Copy,
+ ],
+ ));
+
+ let mut row = base_row;
+ row.address_offset = 1;
+ row.line -= u64::from(neg_line_base);
+ tests.push((
+ row,
+ vec![LineInstruction::Special(OPCODE_BASE + line_range)],
+ ));
+
+ let op_range = (255 - OPCODE_BASE) / line_range;
+ let mut row = base_row;
+ row.address_offset = u64::from(op_range);
+ row.line -= u64::from(neg_line_base);
+ tests.push((
+ row,
+ vec![LineInstruction::Special(
+ OPCODE_BASE + op_range * line_range,
+ )],
+ ));
+
+ let mut row = base_row;
+ row.address_offset = u64::from(op_range);
+ row.line += u64::from(255 - OPCODE_BASE - op_range * line_range);
+ row.line -= u64::from(neg_line_base);
+ tests.push((row, vec![LineInstruction::Special(255)]));
+
+ let mut row = base_row;
+ row.address_offset = u64::from(op_range);
+ row.line += u64::from(255 - OPCODE_BASE - op_range * line_range) + 1;
+ row.line -= u64::from(neg_line_base);
+ tests.push((
+ row,
+ vec![LineInstruction::ConstAddPc, LineInstruction::Copy],
+ ));
+
+ let mut row = base_row;
+ row.address_offset = u64::from(op_range);
+ row.line += u64::from(255 - OPCODE_BASE - op_range * line_range) + 2;
+ row.line -= u64::from(neg_line_base);
+ tests.push((
+ row,
+ vec![
+ LineInstruction::ConstAddPc,
+ LineInstruction::Special(OPCODE_BASE + 6),
+ ],
+ ));
+
+ let mut row = base_row;
+ row.address_offset = u64::from(op_range) * 2;
+ row.line += u64::from(255 - OPCODE_BASE - op_range * line_range);
+ row.line -= u64::from(neg_line_base);
+ tests.push((
+ row,
+ vec![LineInstruction::ConstAddPc, LineInstruction::Special(255)],
+ ));
+
+ let mut row = base_row;
+ row.address_offset = u64::from(op_range) * 2;
+ row.line += u64::from(255 - OPCODE_BASE - op_range * line_range) + 1;
+ row.line -= u64::from(neg_line_base);
+ tests.push((
+ row,
+ vec![
+ LineInstruction::AdvancePc(row.address_offset),
+ LineInstruction::Copy,
+ ],
+ ));
+
+ let mut row = base_row;
+ row.address_offset = u64::from(op_range) * 2;
+ row.line += u64::from(255 - OPCODE_BASE - op_range * line_range) + 2;
+ row.line -= u64::from(neg_line_base);
+ tests.push((
+ row,
+ vec![
+ LineInstruction::AdvancePc(row.address_offset),
+ LineInstruction::Special(OPCODE_BASE + 6),
+ ],
+ ));
+
+ let mut row = base_row;
+ row.address_offset = 0x1234;
+ tests.push((
+ row,
+ vec![LineInstruction::AdvancePc(0x1234), LineInstruction::Copy],
+ ));
+
+ let mut row = base_row;
+ row.line += 0x1234;
+ tests.push((
+ row,
+ vec![LineInstruction::AdvanceLine(0x1234), LineInstruction::Copy],
+ ));
+
+ let mut row = base_row;
+ row.file = file_id;
+ tests.push((
+ row,
+ vec![LineInstruction::SetFile(file_id), LineInstruction::Copy],
+ ));
+
+ let mut row = base_row;
+ row.column = 0x1234;
+ tests.push((
+ row,
+ vec![LineInstruction::SetColumn(0x1234), LineInstruction::Copy],
+ ));
+
+ let mut row = base_row;
+ row.discriminator = 0x1234;
+ tests.push((
+ row,
+ vec![
+ LineInstruction::SetDiscriminator(0x1234),
+ LineInstruction::Copy,
+ ],
+ ));
+
+ let mut row = base_row;
+ row.is_statement = !row.is_statement;
+ tests.push((
+ row,
+ vec![LineInstruction::NegateStatement, LineInstruction::Copy],
+ ));
+
+ let mut row = base_row;
+ row.basic_block = true;
+ tests.push((
+ row,
+ vec![LineInstruction::SetBasicBlock, LineInstruction::Copy],
+ ));
+
+ let mut row = base_row;
+ row.prologue_end = true;
+ tests.push((
+ row,
+ vec![LineInstruction::SetPrologueEnd, LineInstruction::Copy],
+ ));
+
+ let mut row = base_row;
+ row.epilogue_begin = true;
+ tests.push((
+ row,
+ vec![LineInstruction::SetEpilogueBegin, LineInstruction::Copy],
+ ));
+
+ let mut row = base_row;
+ row.isa = 0x1234;
+ tests.push((
+ row,
+ vec![LineInstruction::SetIsa(0x1234), LineInstruction::Copy],
+ ));
+
+ for test in tests {
+ // Test generate_row().
+ let mut program = program.clone();
+ program.row = test.0;
+ program.generate_row();
+ assert_eq!(
+ &program.instructions[base_instructions.len()..],
+ &test.1[..]
+ );
+
+ // Test LineProgram::from().
+ let mut debug_line = DebugLine::from(EndianVec::new(LittleEndian));
+ let debug_line_offset = program
+ .write(
+ &mut debug_line,
+ encoding,
+ &debug_line_str_offsets,
+ &debug_str_offsets,
+ )
+ .unwrap();
+
+ let read_debug_line =
+ read::DebugLine::new(debug_line.slice(), LittleEndian);
+ let read_program = read_debug_line
+ .program(
+ debug_line_offset,
+ address_size,
+ Some(read::EndianSlice::new(dir1, LittleEndian)),
+ Some(read::EndianSlice::new(file1, LittleEndian)),
+ )
+ .unwrap();
+
+ let dwarf = read::Dwarf::default();
+ let mut convert_line_strings = LineStringTable::default();
+ let mut convert_strings = StringTable::default();
+ let (convert_program, _convert_files) = LineProgram::from(
+ read_program,
+ &dwarf,
+ &mut convert_line_strings,
+ &mut convert_strings,
+ convert_address,
+ )
+ .unwrap();
+ assert_eq!(
+ &convert_program.instructions[base_instructions.len()..],
+ &test.1[..]
+ );
+ }
+ }
+ }
+ }
+ }
+
+ #[test]
+ fn test_line_instruction() {
+ let dir1 = &b"dir1"[..];
+ let file1 = &b"file1"[..];
+
+ let debug_line_str_offsets = DebugLineStrOffsets::none();
+ let debug_str_offsets = DebugStrOffsets::none();
+
+ for &version in &[2, 3, 4, 5] {
+ for &address_size in &[4, 8] {
+ for &format in &[Format::Dwarf32, Format::Dwarf64] {
+ let encoding = Encoding {
+ format,
+ version,
+ address_size,
+ };
+ let mut program = LineProgram::new(
+ encoding,
+ LineEncoding::default(),
+ LineString::String(dir1.to_vec()),
+ LineString::String(file1.to_vec()),
+ None,
+ );
+ let dir_id = program.default_directory();
+ let file_id =
+ program.add_file(LineString::String(file1.to_vec()), dir_id, None);
+
+ for &(ref inst, ref expect_inst) in &[
+ (
+ LineInstruction::Special(OPCODE_BASE),
+ read::LineInstruction::Special(OPCODE_BASE),
+ ),
+ (
+ LineInstruction::Special(255),
+ read::LineInstruction::Special(255),
+ ),
+ (LineInstruction::Copy, read::LineInstruction::Copy),
+ (
+ LineInstruction::AdvancePc(0x12),
+ read::LineInstruction::AdvancePc(0x12),
+ ),
+ (
+ LineInstruction::AdvanceLine(0x12),
+ read::LineInstruction::AdvanceLine(0x12),
+ ),
+ (
+ LineInstruction::SetFile(file_id),
+ read::LineInstruction::SetFile(file_id.raw()),
+ ),
+ (
+ LineInstruction::SetColumn(0x12),
+ read::LineInstruction::SetColumn(0x12),
+ ),
+ (
+ LineInstruction::NegateStatement,
+ read::LineInstruction::NegateStatement,
+ ),
+ (
+ LineInstruction::SetBasicBlock,
+ read::LineInstruction::SetBasicBlock,
+ ),
+ (
+ LineInstruction::ConstAddPc,
+ read::LineInstruction::ConstAddPc,
+ ),
+ (
+ LineInstruction::SetPrologueEnd,
+ read::LineInstruction::SetPrologueEnd,
+ ),
+ (
+ LineInstruction::SetEpilogueBegin,
+ read::LineInstruction::SetEpilogueBegin,
+ ),
+ (
+ LineInstruction::SetIsa(0x12),
+ read::LineInstruction::SetIsa(0x12),
+ ),
+ (
+ LineInstruction::EndSequence,
+ read::LineInstruction::EndSequence,
+ ),
+ (
+ LineInstruction::SetAddress(Address::Constant(0x12)),
+ read::LineInstruction::SetAddress(0x12),
+ ),
+ (
+ LineInstruction::SetDiscriminator(0x12),
+ read::LineInstruction::SetDiscriminator(0x12),
+ ),
+ ][..]
+ {
+ let mut program = program.clone();
+ program.instructions.push(*inst);
+
+ let mut debug_line = DebugLine::from(EndianVec::new(LittleEndian));
+ let debug_line_offset = program
+ .write(
+ &mut debug_line,
+ encoding,
+ &debug_line_str_offsets,
+ &debug_str_offsets,
+ )
+ .unwrap();
+
+ let read_debug_line =
+ read::DebugLine::new(debug_line.slice(), LittleEndian);
+ let read_program = read_debug_line
+ .program(
+ debug_line_offset,
+ address_size,
+ Some(read::EndianSlice::new(dir1, LittleEndian)),
+ Some(read::EndianSlice::new(file1, LittleEndian)),
+ )
+ .unwrap();
+ let read_header = read_program.header();
+ let mut read_insts = read_header.instructions();
+ assert_eq!(
+ *expect_inst,
+ read_insts.next_instruction(read_header).unwrap().unwrap()
+ );
+ assert_eq!(None, read_insts.next_instruction(read_header).unwrap());
+ }
+ }
+ }
+ }
+ }
+
+ // Test that the address/line advance is correct. We don't test for optimality.
+ #[test]
+ #[allow(clippy::useless_vec)]
+ fn test_advance() {
+ let encoding = Encoding {
+ format: Format::Dwarf32,
+ version: 4,
+ address_size: 8,
+ };
+
+ let dir1 = &b"dir1"[..];
+ let file1 = &b"file1"[..];
+
+ let addresses = 0..50;
+ let lines = -10..25i64;
+
+ let debug_line_str_offsets = DebugLineStrOffsets::none();
+ let debug_str_offsets = DebugStrOffsets::none();
+
+ for minimum_instruction_length in vec![1, 4] {
+ for maximum_operations_per_instruction in vec![1, 3] {
+ for line_base in vec![-5, 0] {
+ for line_range in vec![10, 20] {
+ let line_encoding = LineEncoding {
+ minimum_instruction_length,
+ maximum_operations_per_instruction,
+ line_base,
+ line_range,
+ default_is_stmt: true,
+ };
+ let mut program = LineProgram::new(
+ encoding,
+ line_encoding,
+ LineString::String(dir1.to_vec()),
+ LineString::String(file1.to_vec()),
+ None,
+ );
+ for address_advance in addresses.clone() {
+ program.begin_sequence(Some(Address::Constant(0x1000)));
+ program.row().line = 0x10000;
+ program.generate_row();
+ for line_advance in lines.clone() {
+ {
+ let row = program.row();
+ row.address_offset +=
+ address_advance * u64::from(minimum_instruction_length);
+ row.line = row.line.wrapping_add(line_advance as u64);
+ }
+ program.generate_row();
+ }
+ let address_offset = program.row().address_offset
+ + u64::from(minimum_instruction_length);
+ program.end_sequence(address_offset);
+ }
+
+ let mut debug_line = DebugLine::from(EndianVec::new(LittleEndian));
+ let debug_line_offset = program
+ .write(
+ &mut debug_line,
+ encoding,
+ &debug_line_str_offsets,
+ &debug_str_offsets,
+ )
+ .unwrap();
+
+ let read_debug_line =
+ read::DebugLine::new(debug_line.slice(), LittleEndian);
+ let read_program = read_debug_line
+ .program(
+ debug_line_offset,
+ 8,
+ Some(read::EndianSlice::new(dir1, LittleEndian)),
+ Some(read::EndianSlice::new(file1, LittleEndian)),
+ )
+ .unwrap();
+
+ let mut rows = read_program.rows();
+ for address_advance in addresses.clone() {
+ let mut address;
+ let mut line;
+ {
+ let row = rows.next_row().unwrap().unwrap().1;
+ address = row.address();
+ line = row.line().unwrap().get();
+ }
+ assert_eq!(address, 0x1000);
+ assert_eq!(line, 0x10000);
+ for line_advance in lines.clone() {
+ let row = rows.next_row().unwrap().unwrap().1;
+ assert_eq!(
+ row.address() - address,
+ address_advance * u64::from(minimum_instruction_length)
+ );
+ assert_eq!(
+ (row.line().unwrap().get() as i64) - (line as i64),
+ line_advance
+ );
+ address = row.address();
+ line = row.line().unwrap().get();
+ }
+ let row = rows.next_row().unwrap().unwrap().1;
+ assert!(row.end_sequence());
+ }
+ }
+ }
+ }
+ }
+ }
+
+ #[test]
+ fn test_line_string() {
+ let version = 5;
+
+ let file = b"file1";
+
+ let mut strings = StringTable::default();
+ let string_id = strings.add("file2");
+ let mut debug_str = DebugStr::from(EndianVec::new(LittleEndian));
+ let debug_str_offsets = strings.write(&mut debug_str).unwrap();
+
+ let mut line_strings = LineStringTable::default();
+ let line_string_id = line_strings.add("file3");
+ let mut debug_line_str = DebugLineStr::from(EndianVec::new(LittleEndian));
+ let debug_line_str_offsets = line_strings.write(&mut debug_line_str).unwrap();
+
+ for &address_size in &[4, 8] {
+ for &format in &[Format::Dwarf32, Format::Dwarf64] {
+ let encoding = Encoding {
+ format,
+ version,
+ address_size,
+ };
+
+ for (file, expect_file) in vec![
+ (
+ LineString::String(file.to_vec()),
+ read::AttributeValue::String(read::EndianSlice::new(file, LittleEndian)),
+ ),
+ (
+ LineString::StringRef(string_id),
+ read::AttributeValue::DebugStrRef(debug_str_offsets.get(string_id)),
+ ),
+ (
+ LineString::LineStringRef(line_string_id),
+ read::AttributeValue::DebugLineStrRef(
+ debug_line_str_offsets.get(line_string_id),
+ ),
+ ),
+ ] {
+ let program = LineProgram::new(
+ encoding,
+ LineEncoding::default(),
+ LineString::String(b"dir".to_vec()),
+ file,
+ None,
+ );
+
+ let mut debug_line = DebugLine::from(EndianVec::new(LittleEndian));
+ let debug_line_offset = program
+ .write(
+ &mut debug_line,
+ encoding,
+ &debug_line_str_offsets,
+ &debug_str_offsets,
+ )
+ .unwrap();
+
+ let read_debug_line = read::DebugLine::new(debug_line.slice(), LittleEndian);
+ let read_program = read_debug_line
+ .program(debug_line_offset, address_size, None, None)
+ .unwrap();
+ let read_header = read_program.header();
+ assert_eq!(read_header.file(0).unwrap().path_name(), expect_file);
+ }
+ }
+ }
+ }
+
+ #[test]
+ fn test_missing_comp_dir() {
+ let debug_line_str_offsets = DebugLineStrOffsets::none();
+ let debug_str_offsets = DebugStrOffsets::none();
+
+ for &version in &[2, 3, 4, 5] {
+ for &address_size in &[4, 8] {
+ for &format in &[Format::Dwarf32, Format::Dwarf64] {
+ let encoding = Encoding {
+ format,
+ version,
+ address_size,
+ };
+ let program = LineProgram::new(
+ encoding,
+ LineEncoding::default(),
+ LineString::String(Vec::new()),
+ LineString::String(Vec::new()),
+ None,
+ );
+
+ let mut debug_line = DebugLine::from(EndianVec::new(LittleEndian));
+ let debug_line_offset = program
+ .write(
+ &mut debug_line,
+ encoding,
+ &debug_line_str_offsets,
+ &debug_str_offsets,
+ )
+ .unwrap();
+
+ let read_debug_line = read::DebugLine::new(debug_line.slice(), LittleEndian);
+ let read_program = read_debug_line
+ .program(
+ debug_line_offset,
+ address_size,
+ // Testing missing comp_dir/comp_name.
+ None,
+ None,
+ )
+ .unwrap();
+
+ let dwarf = read::Dwarf::default();
+ let mut convert_line_strings = LineStringTable::default();
+ let mut convert_strings = StringTable::default();
+ let convert_address = &|address| Some(Address::Constant(address));
+ LineProgram::from(
+ read_program,
+ &dwarf,
+ &mut convert_line_strings,
+ &mut convert_strings,
+ convert_address,
+ )
+ .unwrap();
+ }
+ }
+ }
+ }
+}
diff --git a/vendor/gimli-0.26.2/src/write/loc.rs b/vendor/gimli-0.26.2/src/write/loc.rs
new file mode 100644
index 000000000..ea0ecb1cf
--- /dev/null
+++ b/vendor/gimli-0.26.2/src/write/loc.rs
@@ -0,0 +1,549 @@
+use alloc::vec::Vec;
+use indexmap::IndexSet;
+use std::ops::{Deref, DerefMut};
+
+use crate::common::{Encoding, LocationListsOffset, SectionId};
+use crate::write::{
+ Address, BaseId, DebugInfoReference, Error, Expression, Result, Section, Sections, UnitOffsets,
+ Writer,
+};
+
+define_section!(
+ DebugLoc,
+ LocationListsOffset,
+ "A writable `.debug_loc` section."
+);
+define_section!(
+ DebugLocLists,
+ LocationListsOffset,
+ "A writable `.debug_loclists` section."
+);
+
+define_offsets!(
+ LocationListOffsets: LocationListId => LocationListsOffset,
+ "The section offsets of a series of location lists within the `.debug_loc` or `.debug_loclists` sections."
+);
+
+define_id!(
+ LocationListId,
+ "An identifier for a location list in a `LocationListTable`."
+);
+
+/// A table of location lists that will be stored in a `.debug_loc` or `.debug_loclists` section.
+#[derive(Debug, Default)]
+pub struct LocationListTable {
+ base_id: BaseId,
+ locations: IndexSet<LocationList>,
+}
+
+impl LocationListTable {
+ /// Add a location list to the table.
+ pub fn add(&mut self, loc_list: LocationList) -> LocationListId {
+ let (index, _) = self.locations.insert_full(loc_list);
+ LocationListId::new(self.base_id, index)
+ }
+
+ /// Write the location list table to the appropriate section for the given DWARF version.
+ pub(crate) fn write<W: Writer>(
+ &self,
+ sections: &mut Sections<W>,
+ encoding: Encoding,
+ unit_offsets: Option<&UnitOffsets>,
+ ) -> Result<LocationListOffsets> {
+ if self.locations.is_empty() {
+ return Ok(LocationListOffsets::none());
+ }
+
+ match encoding.version {
+ 2..=4 => self.write_loc(
+ &mut sections.debug_loc,
+ &mut sections.debug_loc_refs,
+ encoding,
+ unit_offsets,
+ ),
+ 5 => self.write_loclists(
+ &mut sections.debug_loclists,
+ &mut sections.debug_loclists_refs,
+ encoding,
+ unit_offsets,
+ ),
+ _ => Err(Error::UnsupportedVersion(encoding.version)),
+ }
+ }
+
+ /// Write the location list table to the `.debug_loc` section.
+ fn write_loc<W: Writer>(
+ &self,
+ w: &mut DebugLoc<W>,
+ refs: &mut Vec<DebugInfoReference>,
+ encoding: Encoding,
+ unit_offsets: Option<&UnitOffsets>,
+ ) -> Result<LocationListOffsets> {
+ let address_size = encoding.address_size;
+ let mut offsets = Vec::new();
+ for loc_list in self.locations.iter() {
+ offsets.push(w.offset());
+ for loc in &loc_list.0 {
+ // Note that we must ensure none of the ranges have both begin == 0 and end == 0.
+ // We do this by ensuring that begin != end, which is a bit more restrictive
+ // than required, but still seems reasonable.
+ match *loc {
+ Location::BaseAddress { address } => {
+ let marker = !0 >> (64 - address_size * 8);
+ w.write_udata(marker, address_size)?;
+ w.write_address(address, address_size)?;
+ }
+ Location::OffsetPair {
+ begin,
+ end,
+ ref data,
+ } => {
+ if begin == end {
+ return Err(Error::InvalidRange);
+ }
+ w.write_udata(begin, address_size)?;
+ w.write_udata(end, address_size)?;
+ write_expression(&mut w.0, refs, encoding, unit_offsets, data)?;
+ }
+ Location::StartEnd {
+ begin,
+ end,
+ ref data,
+ } => {
+ if begin == end {
+ return Err(Error::InvalidRange);
+ }
+ w.write_address(begin, address_size)?;
+ w.write_address(end, address_size)?;
+ write_expression(&mut w.0, refs, encoding, unit_offsets, data)?;
+ }
+ Location::StartLength {
+ begin,
+ length,
+ ref data,
+ } => {
+ let end = match begin {
+ Address::Constant(begin) => Address::Constant(begin + length),
+ Address::Symbol { symbol, addend } => Address::Symbol {
+ symbol,
+ addend: addend + length as i64,
+ },
+ };
+ if begin == end {
+ return Err(Error::InvalidRange);
+ }
+ w.write_address(begin, address_size)?;
+ w.write_address(end, address_size)?;
+ write_expression(&mut w.0, refs, encoding, unit_offsets, data)?;
+ }
+ Location::DefaultLocation { .. } => {
+ return Err(Error::InvalidRange);
+ }
+ }
+ }
+ w.write_udata(0, address_size)?;
+ w.write_udata(0, address_size)?;
+ }
+ Ok(LocationListOffsets {
+ base_id: self.base_id,
+ offsets,
+ })
+ }
+
+ /// Write the location list table to the `.debug_loclists` section.
+ fn write_loclists<W: Writer>(
+ &self,
+ w: &mut DebugLocLists<W>,
+ refs: &mut Vec<DebugInfoReference>,
+ encoding: Encoding,
+ unit_offsets: Option<&UnitOffsets>,
+ ) -> Result<LocationListOffsets> {
+ let mut offsets = Vec::new();
+
+ if encoding.version != 5 {
+ return Err(Error::NeedVersion(5));
+ }
+
+ let length_offset = w.write_initial_length(encoding.format)?;
+ let length_base = w.len();
+
+ w.write_u16(encoding.version)?;
+ w.write_u8(encoding.address_size)?;
+ w.write_u8(0)?; // segment_selector_size
+ w.write_u32(0)?; // offset_entry_count (when set to zero DW_FORM_rnglistx can't be used, see section 7.28)
+ // FIXME implement DW_FORM_rnglistx writing and implement the offset entry list
+
+ for loc_list in self.locations.iter() {
+ offsets.push(w.offset());
+ for loc in &loc_list.0 {
+ match *loc {
+ Location::BaseAddress { address } => {
+ w.write_u8(crate::constants::DW_LLE_base_address.0)?;
+ w.write_address(address, encoding.address_size)?;
+ }
+ Location::OffsetPair {
+ begin,
+ end,
+ ref data,
+ } => {
+ w.write_u8(crate::constants::DW_LLE_offset_pair.0)?;
+ w.write_uleb128(begin)?;
+ w.write_uleb128(end)?;
+ write_expression(&mut w.0, refs, encoding, unit_offsets, data)?;
+ }
+ Location::StartEnd {
+ begin,
+ end,
+ ref data,
+ } => {
+ w.write_u8(crate::constants::DW_LLE_start_end.0)?;
+ w.write_address(begin, encoding.address_size)?;
+ w.write_address(end, encoding.address_size)?;
+ write_expression(&mut w.0, refs, encoding, unit_offsets, data)?;
+ }
+ Location::StartLength {
+ begin,
+ length,
+ ref data,
+ } => {
+ w.write_u8(crate::constants::DW_LLE_start_length.0)?;
+ w.write_address(begin, encoding.address_size)?;
+ w.write_uleb128(length)?;
+ write_expression(&mut w.0, refs, encoding, unit_offsets, data)?;
+ }
+ Location::DefaultLocation { ref data } => {
+ w.write_u8(crate::constants::DW_LLE_default_location.0)?;
+ write_expression(&mut w.0, refs, encoding, unit_offsets, data)?;
+ }
+ }
+ }
+
+ w.write_u8(crate::constants::DW_LLE_end_of_list.0)?;
+ }
+
+ let length = (w.len() - length_base) as u64;
+ w.write_initial_length_at(length_offset, length, encoding.format)?;
+
+ Ok(LocationListOffsets {
+ base_id: self.base_id,
+ offsets,
+ })
+ }
+}
+
+/// A locations list that will be stored in a `.debug_loc` or `.debug_loclists` section.
+#[derive(Clone, Debug, Eq, PartialEq, Hash)]
+pub struct LocationList(pub Vec<Location>);
+
+/// A single location.
+#[derive(Clone, Debug, Eq, PartialEq, Hash)]
+pub enum Location {
+ /// DW_LLE_base_address
+ BaseAddress {
+ /// Base address.
+ address: Address,
+ },
+ /// DW_LLE_offset_pair
+ OffsetPair {
+ /// Start of range relative to base address.
+ begin: u64,
+ /// End of range relative to base address.
+ end: u64,
+ /// Location description.
+ data: Expression,
+ },
+ /// DW_LLE_start_end
+ StartEnd {
+ /// Start of range.
+ begin: Address,
+ /// End of range.
+ end: Address,
+ /// Location description.
+ data: Expression,
+ },
+ /// DW_LLE_start_length
+ StartLength {
+ /// Start of range.
+ begin: Address,
+ /// Length of range.
+ length: u64,
+ /// Location description.
+ data: Expression,
+ },
+ /// DW_LLE_default_location
+ DefaultLocation {
+ /// Location description.
+ data: Expression,
+ },
+}
+
+fn write_expression<W: Writer>(
+ w: &mut W,
+ refs: &mut Vec<DebugInfoReference>,
+ encoding: Encoding,
+ unit_offsets: Option<&UnitOffsets>,
+ val: &Expression,
+) -> Result<()> {
+ let size = val.size(encoding, unit_offsets) as u64;
+ if encoding.version <= 4 {
+ w.write_udata(size, 2)?;
+ } else {
+ w.write_uleb128(size)?;
+ }
+ val.write(w, Some(refs), encoding, unit_offsets)?;
+ Ok(())
+}
+
+#[cfg(feature = "read")]
+mod convert {
+ use super::*;
+
+ use crate::read::{self, Reader};
+ use crate::write::{ConvertError, ConvertResult, ConvertUnitContext};
+
+ impl LocationList {
+ /// Create a location list by reading the data from the give location list iter.
+ pub(crate) fn from<R: Reader<Offset = usize>>(
+ mut from: read::RawLocListIter<R>,
+ context: &ConvertUnitContext<R>,
+ ) -> ConvertResult<Self> {
+ let mut have_base_address = context.base_address != Address::Constant(0);
+ let convert_address =
+ |x| (context.convert_address)(x).ok_or(ConvertError::InvalidAddress);
+ let convert_expression = |x| {
+ Expression::from(
+ x,
+ context.unit.encoding(),
+ Some(context.dwarf),
+ Some(context.unit),
+ Some(context.entry_ids),
+ context.convert_address,
+ )
+ };
+ let mut loc_list = Vec::new();
+ while let Some(from_loc) = from.next()? {
+ let loc = match from_loc {
+ read::RawLocListEntry::AddressOrOffsetPair { begin, end, data } => {
+ // These were parsed as addresses, even if they are offsets.
+ let begin = convert_address(begin)?;
+ let end = convert_address(end)?;
+ let data = convert_expression(data)?;
+ match (begin, end) {
+ (Address::Constant(begin_offset), Address::Constant(end_offset)) => {
+ if have_base_address {
+ Location::OffsetPair {
+ begin: begin_offset,
+ end: end_offset,
+ data,
+ }
+ } else {
+ Location::StartEnd { begin, end, data }
+ }
+ }
+ _ => {
+ if have_base_address {
+ // At least one of begin/end is an address, but we also have
+ // a base address. Adding addresses is undefined.
+ return Err(ConvertError::InvalidRangeRelativeAddress);
+ }
+ Location::StartEnd { begin, end, data }
+ }
+ }
+ }
+ read::RawLocListEntry::BaseAddress { addr } => {
+ have_base_address = true;
+ let address = convert_address(addr)?;
+ Location::BaseAddress { address }
+ }
+ read::RawLocListEntry::BaseAddressx { addr } => {
+ have_base_address = true;
+ let address = convert_address(context.dwarf.address(context.unit, addr)?)?;
+ Location::BaseAddress { address }
+ }
+ read::RawLocListEntry::StartxEndx { begin, end, data } => {
+ let begin = convert_address(context.dwarf.address(context.unit, begin)?)?;
+ let end = convert_address(context.dwarf.address(context.unit, end)?)?;
+ let data = convert_expression(data)?;
+ Location::StartEnd { begin, end, data }
+ }
+ read::RawLocListEntry::StartxLength {
+ begin,
+ length,
+ data,
+ } => {
+ let begin = convert_address(context.dwarf.address(context.unit, begin)?)?;
+ let data = convert_expression(data)?;
+ Location::StartLength {
+ begin,
+ length,
+ data,
+ }
+ }
+ read::RawLocListEntry::OffsetPair { begin, end, data } => {
+ let data = convert_expression(data)?;
+ Location::OffsetPair { begin, end, data }
+ }
+ read::RawLocListEntry::StartEnd { begin, end, data } => {
+ let begin = convert_address(begin)?;
+ let end = convert_address(end)?;
+ let data = convert_expression(data)?;
+ Location::StartEnd { begin, end, data }
+ }
+ read::RawLocListEntry::StartLength {
+ begin,
+ length,
+ data,
+ } => {
+ let begin = convert_address(begin)?;
+ let data = convert_expression(data)?;
+ Location::StartLength {
+ begin,
+ length,
+ data,
+ }
+ }
+ read::RawLocListEntry::DefaultLocation { data } => {
+ let data = convert_expression(data)?;
+ Location::DefaultLocation { data }
+ }
+ };
+ // In some cases, existing data may contain begin == end, filtering
+ // these out.
+ match loc {
+ Location::StartLength { length, .. } if length == 0 => continue,
+ Location::StartEnd { begin, end, .. } if begin == end => continue,
+ Location::OffsetPair { begin, end, .. } if begin == end => continue,
+ _ => (),
+ }
+ loc_list.push(loc);
+ }
+ Ok(LocationList(loc_list))
+ }
+ }
+}
+
+#[cfg(test)]
+#[cfg(feature = "read")]
+mod tests {
+ use super::*;
+ use crate::common::{
+ DebugAbbrevOffset, DebugAddrBase, DebugInfoOffset, DebugLocListsBase, DebugRngListsBase,
+ DebugStrOffsetsBase, Format,
+ };
+ use crate::read;
+ use crate::write::{
+ ConvertUnitContext, EndianVec, LineStringTable, RangeListTable, StringTable,
+ };
+ use crate::LittleEndian;
+ use std::collections::HashMap;
+
+ #[test]
+ fn test_loc_list() {
+ let mut line_strings = LineStringTable::default();
+ let mut strings = StringTable::default();
+ let mut expression = Expression::new();
+ expression.op_constu(0);
+
+ for &version in &[2, 3, 4, 5] {
+ for &address_size in &[4, 8] {
+ for &format in &[Format::Dwarf32, Format::Dwarf64] {
+ let encoding = Encoding {
+ format,
+ version,
+ address_size,
+ };
+
+ let mut loc_list = LocationList(vec![
+ Location::StartLength {
+ begin: Address::Constant(6666),
+ length: 7777,
+ data: expression.clone(),
+ },
+ Location::StartEnd {
+ begin: Address::Constant(4444),
+ end: Address::Constant(5555),
+ data: expression.clone(),
+ },
+ Location::BaseAddress {
+ address: Address::Constant(1111),
+ },
+ Location::OffsetPair {
+ begin: 2222,
+ end: 3333,
+ data: expression.clone(),
+ },
+ ]);
+ if version >= 5 {
+ loc_list.0.push(Location::DefaultLocation {
+ data: expression.clone(),
+ });
+ }
+
+ let mut locations = LocationListTable::default();
+ let loc_list_id = locations.add(loc_list.clone());
+
+ let mut sections = Sections::new(EndianVec::new(LittleEndian));
+ let loc_list_offsets = locations.write(&mut sections, encoding, None).unwrap();
+ assert!(sections.debug_loc_refs.is_empty());
+ assert!(sections.debug_loclists_refs.is_empty());
+
+ let read_debug_loc =
+ read::DebugLoc::new(sections.debug_loc.slice(), LittleEndian);
+ let read_debug_loclists =
+ read::DebugLocLists::new(sections.debug_loclists.slice(), LittleEndian);
+ let read_loc = read::LocationLists::new(read_debug_loc, read_debug_loclists);
+ let offset = loc_list_offsets.get(loc_list_id);
+ let read_loc_list = read_loc.raw_locations(offset, encoding).unwrap();
+
+ let dwarf = read::Dwarf {
+ locations: read_loc,
+ ..Default::default()
+ };
+ let unit = read::Unit {
+ header: read::UnitHeader::new(
+ encoding,
+ 0,
+ read::UnitType::Compilation,
+ DebugAbbrevOffset(0),
+ DebugInfoOffset(0).into(),
+ read::EndianSlice::default(),
+ ),
+ abbreviations: read::Abbreviations::default(),
+ name: None,
+ comp_dir: None,
+ low_pc: 0,
+ str_offsets_base: DebugStrOffsetsBase(0),
+ addr_base: DebugAddrBase(0),
+ loclists_base: DebugLocListsBase(0),
+ rnglists_base: DebugRngListsBase(0),
+ line_program: None,
+ dwo_id: None,
+ };
+ let context = ConvertUnitContext {
+ dwarf: &dwarf,
+ unit: &unit,
+ line_strings: &mut line_strings,
+ strings: &mut strings,
+ ranges: &mut RangeListTable::default(),
+ locations: &mut locations,
+ convert_address: &|address| Some(Address::Constant(address)),
+ base_address: Address::Constant(0),
+ line_program_offset: None,
+ line_program_files: Vec::new(),
+ entry_ids: &HashMap::new(),
+ };
+ let convert_loc_list = LocationList::from(read_loc_list, &context).unwrap();
+
+ if version <= 4 {
+ loc_list.0[0] = Location::StartEnd {
+ begin: Address::Constant(6666),
+ end: Address::Constant(6666 + 7777),
+ data: expression.clone(),
+ };
+ }
+ assert_eq!(loc_list, convert_loc_list);
+ }
+ }
+ }
+ }
+}
diff --git a/vendor/gimli-0.26.2/src/write/mod.rs b/vendor/gimli-0.26.2/src/write/mod.rs
new file mode 100644
index 000000000..47ba6319d
--- /dev/null
+++ b/vendor/gimli-0.26.2/src/write/mod.rs
@@ -0,0 +1,425 @@
+//! Write DWARF debugging information.
+//!
+//! ## API Structure
+//!
+//! This module works by building up a representation of the debugging information
+//! in memory, and then writing it all at once. It supports two major use cases:
+//!
+//! * Use the [`DwarfUnit`](./struct.DwarfUnit.html) type when writing DWARF
+//! for a single compilation unit.
+//!
+//! * Use the [`Dwarf`](./struct.Dwarf.html) type when writing DWARF for multiple
+//! compilation units.
+//!
+//! The module also supports reading in DWARF debugging information and writing it out
+//! again, possibly after modifying it. Create a [`read::Dwarf`](../read/struct.Dwarf.html)
+//! instance, and then use [`Dwarf::from`](./struct.Dwarf.html#method.from) to convert
+//! it to a writable instance.
+//!
+//! ## Example Usage
+//!
+//! Write a compilation unit containing only the top level DIE.
+//!
+//! ```rust
+//! use gimli::write::{
+//! Address, AttributeValue, DwarfUnit, EndianVec, Error, Range, RangeList, Sections,
+//! };
+//!
+//! fn example() -> Result<(), Error> {
+//! // Choose the encoding parameters.
+//! let encoding = gimli::Encoding {
+//! format: gimli::Format::Dwarf32,
+//! version: 5,
+//! address_size: 8,
+//! };
+//! // Create a container for a single compilation unit.
+//! let mut dwarf = DwarfUnit::new(encoding);
+//! // Set a range attribute on the root DIE.
+//! let range_list = RangeList(vec![Range::StartLength {
+//! begin: Address::Constant(0x100),
+//! length: 42,
+//! }]);
+//! let range_list_id = dwarf.unit.ranges.add(range_list);
+//! let root = dwarf.unit.root();
+//! dwarf.unit.get_mut(root).set(
+//! gimli::DW_AT_ranges,
+//! AttributeValue::RangeListRef(range_list_id),
+//! );
+//! // Create a `Vec` for each DWARF section.
+//! let mut sections = Sections::new(EndianVec::new(gimli::LittleEndian));
+//! // Finally, write the DWARF data to the sections.
+//! dwarf.write(&mut sections)?;
+//! sections.for_each(|id, data| {
+//! // Here you can add the data to the output object file.
+//! Ok(())
+//! })
+//! }
+//! # fn main() {
+//! # example().unwrap();
+//! # }
+
+use std::error;
+use std::fmt;
+use std::result;
+
+use crate::constants;
+
+mod endian_vec;
+pub use self::endian_vec::*;
+
+mod writer;
+pub use self::writer::*;
+
+#[macro_use]
+mod section;
+pub use self::section::*;
+
+macro_rules! define_id {
+ ($name:ident, $docs:expr) => {
+ #[doc=$docs]
+ #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
+ pub struct $name {
+ base_id: BaseId,
+ index: usize,
+ }
+
+ impl $name {
+ #[inline]
+ fn new(base_id: BaseId, index: usize) -> Self {
+ $name { base_id, index }
+ }
+ }
+ };
+}
+
+macro_rules! define_offsets {
+ ($offsets:ident: $id:ident => $offset:ident, $off_doc:expr) => {
+ #[doc=$off_doc]
+ #[derive(Debug)]
+ pub struct $offsets {
+ base_id: BaseId,
+ // We know ids start at 0.
+ offsets: Vec<$offset>,
+ }
+
+ impl $offsets {
+ /// Return an empty list of offsets.
+ #[inline]
+ pub fn none() -> Self {
+ $offsets {
+ base_id: BaseId::default(),
+ offsets: Vec::new(),
+ }
+ }
+
+ /// Get the offset
+ ///
+ /// # Panics
+ ///
+ /// Panics if `id` is invalid.
+ #[inline]
+ pub fn get(&self, id: $id) -> $offset {
+ debug_assert_eq!(self.base_id, id.base_id);
+ self.offsets[id.index]
+ }
+
+ /// Return the number of offsets.
+ #[inline]
+ pub fn count(&self) -> usize {
+ self.offsets.len()
+ }
+ }
+ };
+}
+
+mod abbrev;
+pub use self::abbrev::*;
+
+mod cfi;
+pub use self::cfi::*;
+
+mod dwarf;
+pub use self::dwarf::*;
+
+mod line;
+pub use self::line::*;
+
+mod loc;
+pub use self::loc::*;
+
+mod op;
+pub use self::op::*;
+
+mod range;
+pub use self::range::*;
+
+mod str;
+pub use self::str::*;
+
+mod unit;
+pub use self::unit::*;
+
+/// An error that occurred when writing.
+#[derive(Debug, Clone, Copy, PartialEq, Eq)]
+pub enum Error {
+ /// The given offset is out of bounds.
+ OffsetOutOfBounds,
+ /// The given length is out of bounds.
+ LengthOutOfBounds,
+ /// The attribute value is an invalid for writing.
+ InvalidAttributeValue,
+ /// The value is too large for the encoding form.
+ ValueTooLarge,
+ /// Unsupported word size.
+ UnsupportedWordSize(u8),
+ /// Unsupported DWARF version.
+ UnsupportedVersion(u16),
+ /// The unit length is too large for the requested DWARF format.
+ InitialLengthOverflow,
+ /// The address is invalid.
+ InvalidAddress,
+ /// The reference is invalid.
+ InvalidReference,
+ /// A requested feature requires a different DWARF version.
+ NeedVersion(u16),
+ /// Strings in line number program have mismatched forms.
+ LineStringFormMismatch,
+ /// The range is empty or otherwise invalid.
+ InvalidRange,
+ /// The line number program encoding is incompatible with the unit encoding.
+ IncompatibleLineProgramEncoding,
+ /// Could not encode code offset for a frame instruction.
+ InvalidFrameCodeOffset(u32),
+ /// Could not encode data offset for a frame instruction.
+ InvalidFrameDataOffset(i32),
+ /// Unsupported eh_frame pointer encoding.
+ UnsupportedPointerEncoding(constants::DwEhPe),
+ /// Unsupported reference in CFI expression.
+ UnsupportedCfiExpressionReference,
+ /// Unsupported forward reference in expression.
+ UnsupportedExpressionForwardReference,
+}
+
+impl fmt::Display for Error {
+ fn fmt(&self, f: &mut fmt::Formatter) -> result::Result<(), fmt::Error> {
+ match *self {
+ Error::OffsetOutOfBounds => write!(f, "The given offset is out of bounds."),
+ Error::LengthOutOfBounds => write!(f, "The given length is out of bounds."),
+ Error::InvalidAttributeValue => {
+ write!(f, "The attribute value is an invalid for writing.")
+ }
+ Error::ValueTooLarge => write!(f, "The value is too large for the encoding form."),
+ Error::UnsupportedWordSize(size) => write!(f, "Unsupported word size: {}", size),
+ Error::UnsupportedVersion(version) => {
+ write!(f, "Unsupported DWARF version: {}", version)
+ }
+ Error::InitialLengthOverflow => write!(
+ f,
+ "The unit length is too large for the requested DWARF format."
+ ),
+ Error::InvalidAddress => write!(f, "The address is invalid."),
+ Error::InvalidReference => write!(f, "The reference is invalid."),
+ Error::NeedVersion(version) => write!(
+ f,
+ "A requested feature requires a DWARF version {}.",
+ version
+ ),
+ Error::LineStringFormMismatch => {
+ write!(f, "Strings in line number program have mismatched forms.")
+ }
+ Error::InvalidRange => write!(f, "The range is empty or otherwise invalid."),
+ Error::IncompatibleLineProgramEncoding => write!(
+ f,
+ "The line number program encoding is incompatible with the unit encoding."
+ ),
+ Error::InvalidFrameCodeOffset(offset) => write!(
+ f,
+ "Could not encode code offset ({}) for a frame instruction.",
+ offset,
+ ),
+ Error::InvalidFrameDataOffset(offset) => write!(
+ f,
+ "Could not encode data offset ({}) for a frame instruction.",
+ offset,
+ ),
+ Error::UnsupportedPointerEncoding(eh_pe) => {
+ write!(f, "Unsupported eh_frame pointer encoding ({}).", eh_pe)
+ }
+ Error::UnsupportedCfiExpressionReference => {
+ write!(f, "Unsupported reference in CFI expression.")
+ }
+ Error::UnsupportedExpressionForwardReference => {
+ write!(f, "Unsupported forward reference in expression.")
+ }
+ }
+ }
+}
+
+impl error::Error for Error {}
+
+/// The result of a write.
+pub type Result<T> = result::Result<T, Error>;
+
+/// An address.
+#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
+pub enum Address {
+ /// A fixed address that does not require relocation.
+ Constant(u64),
+ /// An address that is relative to a symbol which may be relocated.
+ Symbol {
+ /// The symbol that the address is relative to.
+ ///
+ /// The meaning of this value is decided by the writer, but
+ /// will typically be an index into a symbol table.
+ symbol: usize,
+ /// The offset of the address relative to the symbol.
+ ///
+ /// This will typically be used as the addend in a relocation.
+ addend: i64,
+ },
+}
+
+/// A reference to a `.debug_info` entry.
+#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
+pub enum Reference {
+ /// An external symbol.
+ ///
+ /// The meaning of this value is decided by the writer, but
+ /// will typically be an index into a symbol table.
+ Symbol(usize),
+ /// An entry in the same section.
+ ///
+ /// This only supports references in units that are emitted together.
+ Entry(UnitId, UnitEntryId),
+}
+
+// This type is only used in debug assertions.
+#[cfg(not(debug_assertions))]
+type BaseId = ();
+
+#[cfg(debug_assertions)]
+#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
+struct BaseId(usize);
+
+#[cfg(debug_assertions)]
+impl Default for BaseId {
+ fn default() -> Self {
+ use std::sync::atomic;
+ static BASE_ID: atomic::AtomicUsize = atomic::AtomicUsize::new(0);
+ BaseId(BASE_ID.fetch_add(1, atomic::Ordering::Relaxed))
+ }
+}
+
+#[cfg(feature = "read")]
+mod convert {
+ use super::*;
+ use crate::read;
+
+ pub(crate) use super::unit::convert::*;
+
+ /// An error that occurred when converting a read value into a write value.
+ #[derive(Debug, Clone, Copy, PartialEq, Eq)]
+ pub enum ConvertError {
+ /// An error occurred when reading.
+ Read(read::Error),
+ /// Writing of this attribute value is not implemented yet.
+ UnsupportedAttributeValue,
+ /// This attribute value is an invalid name/form combination.
+ InvalidAttributeValue,
+ /// A `.debug_info` reference does not refer to a valid entry.
+ InvalidDebugInfoOffset,
+ /// An address could not be converted.
+ InvalidAddress,
+ /// Writing this line number instruction is not implemented yet.
+ UnsupportedLineInstruction,
+ /// Writing this form of line string is not implemented yet.
+ UnsupportedLineStringForm,
+ /// A `.debug_line` file index is invalid.
+ InvalidFileIndex,
+ /// A `.debug_line` directory index is invalid.
+ InvalidDirectoryIndex,
+ /// A `.debug_line` line base is invalid.
+ InvalidLineBase,
+ /// A `.debug_line` reference is invalid.
+ InvalidLineRef,
+ /// A `.debug_info` unit entry reference is invalid.
+ InvalidUnitRef,
+ /// A `.debug_info` reference is invalid.
+ InvalidDebugInfoRef,
+ /// Invalid relative address in a range list.
+ InvalidRangeRelativeAddress,
+ /// Writing this CFI instruction is not implemented yet.
+ UnsupportedCfiInstruction,
+ /// Writing indirect pointers is not implemented yet.
+ UnsupportedIndirectAddress,
+ /// Writing this expression operation is not implemented yet.
+ UnsupportedOperation,
+ /// Operation branch target is invalid.
+ InvalidBranchTarget,
+ /// Writing this unit type is not supported yet.
+ UnsupportedUnitType,
+ }
+
+ impl fmt::Display for ConvertError {
+ fn fmt(&self, f: &mut fmt::Formatter) -> result::Result<(), fmt::Error> {
+ use self::ConvertError::*;
+ match *self {
+ Read(ref e) => e.fmt(f),
+ UnsupportedAttributeValue => {
+ write!(f, "Writing of this attribute value is not implemented yet.")
+ }
+ InvalidAttributeValue => write!(
+ f,
+ "This attribute value is an invalid name/form combination."
+ ),
+ InvalidDebugInfoOffset => write!(
+ f,
+ "A `.debug_info` reference does not refer to a valid entry."
+ ),
+ InvalidAddress => write!(f, "An address could not be converted."),
+ UnsupportedLineInstruction => write!(
+ f,
+ "Writing this line number instruction is not implemented yet."
+ ),
+ UnsupportedLineStringForm => write!(
+ f,
+ "Writing this form of line string is not implemented yet."
+ ),
+ InvalidFileIndex => write!(f, "A `.debug_line` file index is invalid."),
+ InvalidDirectoryIndex => write!(f, "A `.debug_line` directory index is invalid."),
+ InvalidLineBase => write!(f, "A `.debug_line` line base is invalid."),
+ InvalidLineRef => write!(f, "A `.debug_line` reference is invalid."),
+ InvalidUnitRef => write!(f, "A `.debug_info` unit entry reference is invalid."),
+ InvalidDebugInfoRef => write!(f, "A `.debug_info` reference is invalid."),
+ InvalidRangeRelativeAddress => {
+ write!(f, "Invalid relative address in a range list.")
+ }
+ UnsupportedCfiInstruction => {
+ write!(f, "Writing this CFI instruction is not implemented yet.")
+ }
+ UnsupportedIndirectAddress => {
+ write!(f, "Writing indirect pointers is not implemented yet.")
+ }
+ UnsupportedOperation => write!(
+ f,
+ "Writing this expression operation is not implemented yet."
+ ),
+ InvalidBranchTarget => write!(f, "Operation branch target is invalid."),
+ UnsupportedUnitType => write!(f, "Writing this unit type is not supported yet."),
+ }
+ }
+ }
+
+ impl error::Error for ConvertError {}
+
+ impl From<read::Error> for ConvertError {
+ fn from(e: read::Error) -> Self {
+ ConvertError::Read(e)
+ }
+ }
+
+ /// The result of a conversion.
+ pub type ConvertResult<T> = result::Result<T, ConvertError>;
+}
+#[cfg(feature = "read")]
+pub use self::convert::*;
diff --git a/vendor/gimli-0.26.2/src/write/op.rs b/vendor/gimli-0.26.2/src/write/op.rs
new file mode 100644
index 000000000..c70eec2dd
--- /dev/null
+++ b/vendor/gimli-0.26.2/src/write/op.rs
@@ -0,0 +1,1621 @@
+use alloc::boxed::Box;
+use alloc::vec::Vec;
+
+use crate::common::{Encoding, Register};
+use crate::constants::{self, DwOp};
+use crate::leb128::write::{sleb128_size, uleb128_size};
+use crate::write::{
+ Address, DebugInfoReference, Error, Reference, Result, UnitEntryId, UnitOffsets, Writer,
+};
+
+/// The bytecode for a DWARF expression or location description.
+#[derive(Debug, Default, Clone, PartialEq, Eq, Hash)]
+pub struct Expression {
+ operations: Vec<Operation>,
+}
+
+impl Expression {
+ /// Create an empty expression.
+ #[inline]
+ pub fn new() -> Self {
+ Self::default()
+ }
+
+ /// Create an expression from raw bytecode.
+ ///
+ /// This does not support operations that require references, such as `DW_OP_addr`.
+ #[inline]
+ pub fn raw(bytecode: Vec<u8>) -> Self {
+ Expression {
+ operations: vec![Operation::Raw(bytecode)],
+ }
+ }
+
+ /// Add an operation to the expression.
+ ///
+ /// This should only be used for operations that have no explicit operands.
+ pub fn op(&mut self, opcode: DwOp) {
+ self.operations.push(Operation::Simple(opcode));
+ }
+
+ /// Add a `DW_OP_addr` operation to the expression.
+ pub fn op_addr(&mut self, address: Address) {
+ self.operations.push(Operation::Address(address));
+ }
+
+ /// Add a `DW_OP_constu` operation to the expression.
+ ///
+ /// This may be emitted as a smaller equivalent operation.
+ pub fn op_constu(&mut self, value: u64) {
+ self.operations.push(Operation::UnsignedConstant(value));
+ }
+
+ /// Add a `DW_OP_consts` operation to the expression.
+ ///
+ /// This may be emitted as a smaller equivalent operation.
+ pub fn op_consts(&mut self, value: i64) {
+ self.operations.push(Operation::SignedConstant(value));
+ }
+
+ /// Add a `DW_OP_const_type` or `DW_OP_GNU_const_type` operation to the expression.
+ pub fn op_const_type(&mut self, base: UnitEntryId, value: Box<[u8]>) {
+ self.operations.push(Operation::ConstantType(base, value));
+ }
+
+ /// Add a `DW_OP_fbreg` operation to the expression.
+ pub fn op_fbreg(&mut self, offset: i64) {
+ self.operations.push(Operation::FrameOffset(offset));
+ }
+
+ /// Add a `DW_OP_bregx` operation to the expression.
+ ///
+ /// This may be emitted as a smaller equivalent operation.
+ pub fn op_breg(&mut self, register: Register, offset: i64) {
+ self.operations
+ .push(Operation::RegisterOffset(register, offset));
+ }
+
+ /// Add a `DW_OP_regval_type` or `DW_OP_GNU_regval_type` operation to the expression.
+ ///
+ /// This may be emitted as a smaller equivalent operation.
+ pub fn op_regval_type(&mut self, register: Register, base: UnitEntryId) {
+ self.operations
+ .push(Operation::RegisterType(register, base));
+ }
+
+ /// Add a `DW_OP_pick` operation to the expression.
+ ///
+ /// This may be emitted as a `DW_OP_dup` or `DW_OP_over` operation.
+ pub fn op_pick(&mut self, index: u8) {
+ self.operations.push(Operation::Pick(index));
+ }
+
+ /// Add a `DW_OP_deref` operation to the expression.
+ pub fn op_deref(&mut self) {
+ self.operations.push(Operation::Deref { space: false });
+ }
+
+ /// Add a `DW_OP_xderef` operation to the expression.
+ pub fn op_xderef(&mut self) {
+ self.operations.push(Operation::Deref { space: true });
+ }
+
+ /// Add a `DW_OP_deref_size` operation to the expression.
+ pub fn op_deref_size(&mut self, size: u8) {
+ self.operations
+ .push(Operation::DerefSize { size, space: false });
+ }
+
+ /// Add a `DW_OP_xderef_size` operation to the expression.
+ pub fn op_xderef_size(&mut self, size: u8) {
+ self.operations
+ .push(Operation::DerefSize { size, space: true });
+ }
+
+ /// Add a `DW_OP_deref_type` or `DW_OP_GNU_deref_type` operation to the expression.
+ pub fn op_deref_type(&mut self, size: u8, base: UnitEntryId) {
+ self.operations.push(Operation::DerefType {
+ size,
+ base,
+ space: false,
+ });
+ }
+
+ /// Add a `DW_OP_xderef_type` operation to the expression.
+ pub fn op_xderef_type(&mut self, size: u8, base: UnitEntryId) {
+ self.operations.push(Operation::DerefType {
+ size,
+ base,
+ space: true,
+ });
+ }
+
+ /// Add a `DW_OP_plus_uconst` operation to the expression.
+ pub fn op_plus_uconst(&mut self, value: u64) {
+ self.operations.push(Operation::PlusConstant(value));
+ }
+
+ /// Add a `DW_OP_skip` operation to the expression.
+ ///
+ /// Returns the index of the operation. The caller must call `set_target` with
+ /// this index to set the target of the branch.
+ pub fn op_skip(&mut self) -> usize {
+ let index = self.next_index();
+ self.operations.push(Operation::Skip(!0));
+ index
+ }
+
+ /// Add a `DW_OP_bra` operation to the expression.
+ ///
+ /// Returns the index of the operation. The caller must call `set_target` with
+ /// this index to set the target of the branch.
+ pub fn op_bra(&mut self) -> usize {
+ let index = self.next_index();
+ self.operations.push(Operation::Branch(!0));
+ index
+ }
+
+ /// Return the index that will be assigned to the next operation.
+ ///
+ /// This can be passed to `set_target`.
+ #[inline]
+ pub fn next_index(&self) -> usize {
+ self.operations.len()
+ }
+
+ /// Set the target of a `DW_OP_skip` or `DW_OP_bra` operation .
+ pub fn set_target(&mut self, operation: usize, new_target: usize) {
+ debug_assert!(new_target <= self.next_index());
+ debug_assert_ne!(operation, new_target);
+ match self.operations[operation] {
+ Operation::Skip(ref mut target) | Operation::Branch(ref mut target) => {
+ *target = new_target;
+ }
+ _ => unimplemented!(),
+ }
+ }
+
+ /// Add a `DW_OP_call4` operation to the expression.
+ pub fn op_call(&mut self, entry: UnitEntryId) {
+ self.operations.push(Operation::Call(entry));
+ }
+
+ /// Add a `DW_OP_call_ref` operation to the expression.
+ pub fn op_call_ref(&mut self, entry: Reference) {
+ self.operations.push(Operation::CallRef(entry));
+ }
+
+ /// Add a `DW_OP_convert` or `DW_OP_GNU_convert` operation to the expression.
+ ///
+ /// `base` is the DIE of the base type, or `None` for the generic type.
+ pub fn op_convert(&mut self, base: Option<UnitEntryId>) {
+ self.operations.push(Operation::Convert(base));
+ }
+
+ /// Add a `DW_OP_reinterpret` or `DW_OP_GNU_reinterpret` operation to the expression.
+ ///
+ /// `base` is the DIE of the base type, or `None` for the generic type.
+ pub fn op_reinterpret(&mut self, base: Option<UnitEntryId>) {
+ self.operations.push(Operation::Reinterpret(base));
+ }
+
+ /// Add a `DW_OP_entry_value` or `DW_OP_GNU_entry_value` operation to the expression.
+ pub fn op_entry_value(&mut self, expression: Expression) {
+ self.operations.push(Operation::EntryValue(expression));
+ }
+
+ /// Add a `DW_OP_regx` operation to the expression.
+ ///
+ /// This may be emitted as a smaller equivalent operation.
+ pub fn op_reg(&mut self, register: Register) {
+ self.operations.push(Operation::Register(register));
+ }
+
+ /// Add a `DW_OP_implicit_value` operation to the expression.
+ pub fn op_implicit_value(&mut self, data: Box<[u8]>) {
+ self.operations.push(Operation::ImplicitValue(data));
+ }
+
+ /// Add a `DW_OP_implicit_pointer` or `DW_OP_GNU_implicit_pointer` operation to the expression.
+ pub fn op_implicit_pointer(&mut self, entry: Reference, byte_offset: i64) {
+ self.operations
+ .push(Operation::ImplicitPointer { entry, byte_offset });
+ }
+
+ /// Add a `DW_OP_piece` operation to the expression.
+ pub fn op_piece(&mut self, size_in_bytes: u64) {
+ self.operations.push(Operation::Piece { size_in_bytes });
+ }
+
+ /// Add a `DW_OP_bit_piece` operation to the expression.
+ pub fn op_bit_piece(&mut self, size_in_bits: u64, bit_offset: u64) {
+ self.operations.push(Operation::BitPiece {
+ size_in_bits,
+ bit_offset,
+ });
+ }
+
+ /// Add a `DW_OP_GNU_parameter_ref` operation to the expression.
+ pub fn op_gnu_parameter_ref(&mut self, entry: UnitEntryId) {
+ self.operations.push(Operation::ParameterRef(entry));
+ }
+
+ /// Add a `DW_OP_WASM_location 0x0` operation to the expression.
+ pub fn op_wasm_local(&mut self, index: u32) {
+ self.operations.push(Operation::WasmLocal(index));
+ }
+
+ /// Add a `DW_OP_WASM_location 0x1` operation to the expression.
+ pub fn op_wasm_global(&mut self, index: u32) {
+ self.operations.push(Operation::WasmGlobal(index));
+ }
+
+ /// Add a `DW_OP_WASM_location 0x2` operation to the expression.
+ pub fn op_wasm_stack(&mut self, index: u32) {
+ self.operations.push(Operation::WasmStack(index));
+ }
+
+ pub(crate) fn size(&self, encoding: Encoding, unit_offsets: Option<&UnitOffsets>) -> usize {
+ let mut size = 0;
+ for operation in &self.operations {
+ size += operation.size(encoding, unit_offsets);
+ }
+ size
+ }
+
+ pub(crate) fn write<W: Writer>(
+ &self,
+ w: &mut W,
+ mut refs: Option<&mut Vec<DebugInfoReference>>,
+ encoding: Encoding,
+ unit_offsets: Option<&UnitOffsets>,
+ ) -> Result<()> {
+ // TODO: only calculate offsets if needed?
+ let mut offsets = Vec::with_capacity(self.operations.len());
+ let mut offset = w.len();
+ for operation in &self.operations {
+ offsets.push(offset);
+ offset += operation.size(encoding, unit_offsets);
+ }
+ offsets.push(offset);
+ for (operation, offset) in self.operations.iter().zip(offsets.iter().copied()) {
+ let refs = match refs {
+ Some(ref mut refs) => Some(&mut **refs),
+ None => None,
+ };
+ debug_assert_eq!(w.len(), offset);
+ operation.write(w, refs, encoding, unit_offsets, &offsets)?;
+ }
+ Ok(())
+ }
+}
+
+/// A single DWARF operation.
+//
+// This type is intentionally not public so that we can change the
+// representation of expressions as needed.
+//
+// Variants are listed in the order they appear in Section 2.5.
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+enum Operation {
+ /// Raw bytecode.
+ ///
+ /// Does not support references.
+ Raw(Vec<u8>),
+ /// An operation that has no explicit operands.
+ ///
+ /// Represents:
+ /// - `DW_OP_drop`, `DW_OP_swap`, `DW_OP_rot`
+ /// - `DW_OP_push_object_address`, `DW_OP_form_tls_address`, `DW_OP_call_frame_cfa`
+ /// - `DW_OP_abs`, `DW_OP_and`, `DW_OP_div`, `DW_OP_minus`, `DW_OP_mod`, `DW_OP_mul`,
+ /// `DW_OP_neg`, `DW_OP_not`, `DW_OP_or`, `DW_OP_plus`, `DW_OP_shl`, `DW_OP_shr`,
+ /// `DW_OP_shra`, `DW_OP_xor`
+ /// - `DW_OP_le`, `DW_OP_ge`, `DW_OP_eq`, `DW_OP_lt`, `DW_OP_gt`, `DW_OP_ne`
+ /// - `DW_OP_nop`
+ /// - `DW_OP_stack_value`
+ Simple(DwOp),
+ /// Relocate the address if needed, and push it on the stack.
+ ///
+ /// Represents `DW_OP_addr`.
+ Address(Address),
+ /// Push an unsigned constant value on the stack.
+ ///
+ /// Represents `DW_OP_constu`.
+ UnsignedConstant(u64),
+ /// Push a signed constant value on the stack.
+ ///
+ /// Represents `DW_OP_consts`.
+ SignedConstant(i64),
+ /* TODO: requires .debug_addr write support
+ /// Read the address at the given index in `.debug_addr, relocate the address if needed,
+ /// and push it on the stack.
+ ///
+ /// Represents `DW_OP_addrx`.
+ AddressIndex(DebugAddrIndex<Offset>),
+ /// Read the address at the given index in `.debug_addr, and push it on the stack.
+ /// Do not relocate the address.
+ ///
+ /// Represents `DW_OP_constx`.
+ ConstantIndex(DebugAddrIndex<Offset>),
+ */
+ /// Interpret the value bytes as a constant of a given type, and push it on the stack.
+ ///
+ /// Represents `DW_OP_const_type`.
+ ConstantType(UnitEntryId, Box<[u8]>),
+ /// Compute the frame base (using `DW_AT_frame_base`), add the
+ /// given offset, and then push the resulting sum on the stack.
+ ///
+ /// Represents `DW_OP_fbreg`.
+ FrameOffset(i64),
+ /// Find the contents of the given register, add the offset, and then
+ /// push the resulting sum on the stack.
+ ///
+ /// Represents `DW_OP_bregx`.
+ RegisterOffset(Register, i64),
+ /// Interpret the contents of the given register as a value of the given type,
+ /// and push it on the stack.
+ ///
+ /// Represents `DW_OP_regval_type`.
+ RegisterType(Register, UnitEntryId),
+ /// Copy the item at a stack index and push it on top of the stack.
+ ///
+ /// Represents `DW_OP_pick`, `DW_OP_dup`, and `DW_OP_over`.
+ Pick(u8),
+ /// Pop the topmost value of the stack, dereference it, and push the
+ /// resulting value.
+ ///
+ /// Represents `DW_OP_deref` and `DW_OP_xderef`.
+ Deref {
+ /// True if the dereference operation takes an address space
+ /// argument from the stack; false otherwise.
+ space: bool,
+ },
+ /// Pop the topmost value of the stack, dereference it to obtain a value
+ /// of the given size, and push the resulting value.
+ ///
+ /// Represents `DW_OP_deref_size` and `DW_OP_xderef_size`.
+ DerefSize {
+ /// True if the dereference operation takes an address space
+ /// argument from the stack; false otherwise.
+ space: bool,
+ /// The size of the data to dereference.
+ size: u8,
+ },
+ /// Pop the topmost value of the stack, dereference it to obtain a value
+ /// of the given type, and push the resulting value.
+ ///
+ /// Represents `DW_OP_deref_type` and `DW_OP_xderef_type`.
+ DerefType {
+ /// True if the dereference operation takes an address space
+ /// argument from the stack; false otherwise.
+ space: bool,
+ /// The size of the data to dereference.
+ size: u8,
+ /// The DIE of the base type, or `None` for the generic type.
+ base: UnitEntryId,
+ },
+ /// Add an unsigned constant to the topmost value on the stack.
+ ///
+ /// Represents `DW_OP_plus_uconst`.
+ PlusConstant(u64),
+ /// Unconditional branch to the target location.
+ ///
+ /// The value is the index within the expression of the operation to branch to.
+ /// This will be converted to a relative offset when writing.
+ ///
+ /// Represents `DW_OP_skip`.
+ Skip(usize),
+ /// Branch to the target location if the top of stack is nonzero.
+ ///
+ /// The value is the index within the expression of the operation to branch to.
+ /// This will be converted to a relative offset when writing.
+ ///
+ /// Represents `DW_OP_bra`.
+ Branch(usize),
+ /// Evaluate a DWARF expression as a subroutine.
+ ///
+ /// The expression comes from the `DW_AT_location` attribute of the indicated DIE.
+ ///
+ /// Represents `DW_OP_call4`.
+ Call(UnitEntryId),
+ /// Evaluate an external DWARF expression as a subroutine.
+ ///
+ /// The expression comes from the `DW_AT_location` attribute of the indicated DIE,
+ /// which may be in another compilation unit or shared object.
+ ///
+ /// Represents `DW_OP_call_ref`.
+ CallRef(Reference),
+ /// Pop the top stack entry, convert it to a different type, and push it on the stack.
+ ///
+ /// Represents `DW_OP_convert`.
+ Convert(Option<UnitEntryId>),
+ /// Pop the top stack entry, reinterpret the bits in its value as a different type,
+ /// and push it on the stack.
+ ///
+ /// Represents `DW_OP_reinterpret`.
+ Reinterpret(Option<UnitEntryId>),
+ /// Evaluate an expression at the entry to the current subprogram, and push it on the stack.
+ ///
+ /// Represents `DW_OP_entry_value`.
+ EntryValue(Expression),
+ // FIXME: EntryRegister
+ /// Indicate that this piece's location is in the given register.
+ ///
+ /// Completes the piece or expression.
+ ///
+ /// Represents `DW_OP_regx`.
+ Register(Register),
+ /// The object has no location, but has a known constant value.
+ ///
+ /// Completes the piece or expression.
+ ///
+ /// Represents `DW_OP_implicit_value`.
+ ImplicitValue(Box<[u8]>),
+ /// The object is a pointer to a value which has no actual location, such as
+ /// an implicit value or a stack value.
+ ///
+ /// Completes the piece or expression.
+ ///
+ /// Represents `DW_OP_implicit_pointer`.
+ ImplicitPointer {
+ /// The DIE of the value that this is an implicit pointer into.
+ entry: Reference,
+ /// The byte offset into the value that the implicit pointer points to.
+ byte_offset: i64,
+ },
+ /// Terminate a piece.
+ ///
+ /// Represents `DW_OP_piece`.
+ Piece {
+ /// The size of this piece in bytes.
+ size_in_bytes: u64,
+ },
+ /// Terminate a piece with a size in bits.
+ ///
+ /// Represents `DW_OP_bit_piece`.
+ BitPiece {
+ /// The size of this piece in bits.
+ size_in_bits: u64,
+ /// The bit offset of this piece.
+ bit_offset: u64,
+ },
+ /// This represents a parameter that was optimized out.
+ ///
+ /// The entry is the definition of the parameter, and is matched to
+ /// the `DW_TAG_GNU_call_site_parameter` in the caller that also
+ /// points to the same definition of the parameter.
+ ///
+ /// Represents `DW_OP_GNU_parameter_ref`.
+ ParameterRef(UnitEntryId),
+ /// The index of a local in the currently executing function.
+ ///
+ /// Represents `DW_OP_WASM_location 0x00`.
+ WasmLocal(u32),
+ /// The index of a global.
+ ///
+ /// Represents `DW_OP_WASM_location 0x01`.
+ WasmGlobal(u32),
+ /// The index of an item on the operand stack.
+ ///
+ /// Represents `DW_OP_WASM_location 0x02`.
+ WasmStack(u32),
+}
+
+impl Operation {
+ fn size(&self, encoding: Encoding, unit_offsets: Option<&UnitOffsets>) -> usize {
+ let base_size = |base| {
+ // Errors are handled during writes.
+ match unit_offsets {
+ Some(offsets) => uleb128_size(offsets.unit_offset(base)),
+ None => 0,
+ }
+ };
+ 1 + match *self {
+ Operation::Raw(ref bytecode) => return bytecode.len(),
+ Operation::Simple(_) => 0,
+ Operation::Address(_) => encoding.address_size as usize,
+ Operation::UnsignedConstant(value) => {
+ if value < 32 {
+ 0
+ } else {
+ uleb128_size(value)
+ }
+ }
+ Operation::SignedConstant(value) => sleb128_size(value),
+ Operation::ConstantType(base, ref value) => base_size(base) + 1 + value.len(),
+ Operation::FrameOffset(offset) => sleb128_size(offset),
+ Operation::RegisterOffset(register, offset) => {
+ if register.0 < 32 {
+ sleb128_size(offset)
+ } else {
+ uleb128_size(register.0.into()) + sleb128_size(offset)
+ }
+ }
+ Operation::RegisterType(register, base) => {
+ uleb128_size(register.0.into()) + base_size(base)
+ }
+ Operation::Pick(index) => {
+ if index > 1 {
+ 1
+ } else {
+ 0
+ }
+ }
+ Operation::Deref { .. } => 0,
+ Operation::DerefSize { .. } => 1,
+ Operation::DerefType { base, .. } => 1 + base_size(base),
+ Operation::PlusConstant(value) => uleb128_size(value),
+ Operation::Skip(_) => 2,
+ Operation::Branch(_) => 2,
+ Operation::Call(_) => 4,
+ Operation::CallRef(_) => encoding.format.word_size() as usize,
+ Operation::Convert(base) => match base {
+ Some(base) => base_size(base),
+ None => 1,
+ },
+ Operation::Reinterpret(base) => match base {
+ Some(base) => base_size(base),
+ None => 1,
+ },
+ Operation::EntryValue(ref expression) => {
+ let length = expression.size(encoding, unit_offsets);
+ uleb128_size(length as u64) + length
+ }
+ Operation::Register(register) => {
+ if register.0 < 32 {
+ 0
+ } else {
+ uleb128_size(register.0.into())
+ }
+ }
+ Operation::ImplicitValue(ref data) => uleb128_size(data.len() as u64) + data.len(),
+ Operation::ImplicitPointer { byte_offset, .. } => {
+ encoding.format.word_size() as usize + sleb128_size(byte_offset)
+ }
+ Operation::Piece { size_in_bytes } => uleb128_size(size_in_bytes),
+ Operation::BitPiece {
+ size_in_bits,
+ bit_offset,
+ } => uleb128_size(size_in_bits) + uleb128_size(bit_offset),
+ Operation::ParameterRef(_) => 4,
+ Operation::WasmLocal(index)
+ | Operation::WasmGlobal(index)
+ | Operation::WasmStack(index) => 1 + uleb128_size(index.into()),
+ }
+ }
+
+ pub(crate) fn write<W: Writer>(
+ &self,
+ w: &mut W,
+ refs: Option<&mut Vec<DebugInfoReference>>,
+ encoding: Encoding,
+ unit_offsets: Option<&UnitOffsets>,
+ offsets: &[usize],
+ ) -> Result<()> {
+ let entry_offset = |entry| match unit_offsets {
+ Some(offsets) => {
+ let offset = offsets.unit_offset(entry);
+ if offset == 0 {
+ Err(Error::UnsupportedExpressionForwardReference)
+ } else {
+ Ok(offset)
+ }
+ }
+ None => Err(Error::UnsupportedCfiExpressionReference),
+ };
+ match *self {
+ Operation::Raw(ref bytecode) => w.write(bytecode)?,
+ Operation::Simple(opcode) => w.write_u8(opcode.0)?,
+ Operation::Address(address) => {
+ w.write_u8(constants::DW_OP_addr.0)?;
+ w.write_address(address, encoding.address_size)?;
+ }
+ Operation::UnsignedConstant(value) => {
+ if value < 32 {
+ w.write_u8(constants::DW_OP_lit0.0 + value as u8)?;
+ } else {
+ w.write_u8(constants::DW_OP_constu.0)?;
+ w.write_uleb128(value)?;
+ }
+ }
+ Operation::SignedConstant(value) => {
+ w.write_u8(constants::DW_OP_consts.0)?;
+ w.write_sleb128(value)?;
+ }
+ Operation::ConstantType(base, ref value) => {
+ if encoding.version >= 5 {
+ w.write_u8(constants::DW_OP_const_type.0)?;
+ } else {
+ w.write_u8(constants::DW_OP_GNU_const_type.0)?;
+ }
+ w.write_uleb128(entry_offset(base)?)?;
+ w.write_udata(value.len() as u64, 1)?;
+ w.write(&value)?;
+ }
+ Operation::FrameOffset(offset) => {
+ w.write_u8(constants::DW_OP_fbreg.0)?;
+ w.write_sleb128(offset)?;
+ }
+ Operation::RegisterOffset(register, offset) => {
+ if register.0 < 32 {
+ w.write_u8(constants::DW_OP_breg0.0 + register.0 as u8)?;
+ } else {
+ w.write_u8(constants::DW_OP_bregx.0)?;
+ w.write_uleb128(register.0.into())?;
+ }
+ w.write_sleb128(offset)?;
+ }
+ Operation::RegisterType(register, base) => {
+ if encoding.version >= 5 {
+ w.write_u8(constants::DW_OP_regval_type.0)?;
+ } else {
+ w.write_u8(constants::DW_OP_GNU_regval_type.0)?;
+ }
+ w.write_uleb128(register.0.into())?;
+ w.write_uleb128(entry_offset(base)?)?;
+ }
+ Operation::Pick(index) => match index {
+ 0 => w.write_u8(constants::DW_OP_dup.0)?,
+ 1 => w.write_u8(constants::DW_OP_over.0)?,
+ _ => {
+ w.write_u8(constants::DW_OP_pick.0)?;
+ w.write_u8(index)?;
+ }
+ },
+ Operation::Deref { space } => {
+ if space {
+ w.write_u8(constants::DW_OP_xderef.0)?;
+ } else {
+ w.write_u8(constants::DW_OP_deref.0)?;
+ }
+ }
+ Operation::DerefSize { space, size } => {
+ if space {
+ w.write_u8(constants::DW_OP_xderef_size.0)?;
+ } else {
+ w.write_u8(constants::DW_OP_deref_size.0)?;
+ }
+ w.write_u8(size)?;
+ }
+ Operation::DerefType { space, size, base } => {
+ if space {
+ w.write_u8(constants::DW_OP_xderef_type.0)?;
+ } else {
+ if encoding.version >= 5 {
+ w.write_u8(constants::DW_OP_deref_type.0)?;
+ } else {
+ w.write_u8(constants::DW_OP_GNU_deref_type.0)?;
+ }
+ }
+ w.write_u8(size)?;
+ w.write_uleb128(entry_offset(base)?)?;
+ }
+ Operation::PlusConstant(value) => {
+ w.write_u8(constants::DW_OP_plus_uconst.0)?;
+ w.write_uleb128(value)?;
+ }
+ Operation::Skip(target) => {
+ w.write_u8(constants::DW_OP_skip.0)?;
+ let offset = offsets[target] as i64 - (w.len() as i64 + 2);
+ w.write_sdata(offset, 2)?;
+ }
+ Operation::Branch(target) => {
+ w.write_u8(constants::DW_OP_bra.0)?;
+ let offset = offsets[target] as i64 - (w.len() as i64 + 2);
+ w.write_sdata(offset, 2)?;
+ }
+ Operation::Call(entry) => {
+ w.write_u8(constants::DW_OP_call4.0)?;
+ // TODO: this probably won't work in practice, because we may
+ // only know the offsets of base type DIEs at this point.
+ w.write_udata(entry_offset(entry)?, 4)?;
+ }
+ Operation::CallRef(entry) => {
+ w.write_u8(constants::DW_OP_call_ref.0)?;
+ let size = encoding.format.word_size();
+ match entry {
+ Reference::Symbol(symbol) => w.write_reference(symbol, size)?,
+ Reference::Entry(unit, entry) => {
+ let refs = refs.ok_or(Error::InvalidReference)?;
+ refs.push(DebugInfoReference {
+ offset: w.len(),
+ unit,
+ entry,
+ size,
+ });
+ w.write_udata(0, size)?;
+ }
+ }
+ }
+ Operation::Convert(base) => {
+ if encoding.version >= 5 {
+ w.write_u8(constants::DW_OP_convert.0)?;
+ } else {
+ w.write_u8(constants::DW_OP_GNU_convert.0)?;
+ }
+ match base {
+ Some(base) => w.write_uleb128(entry_offset(base)?)?,
+ None => w.write_u8(0)?,
+ }
+ }
+ Operation::Reinterpret(base) => {
+ if encoding.version >= 5 {
+ w.write_u8(constants::DW_OP_reinterpret.0)?;
+ } else {
+ w.write_u8(constants::DW_OP_GNU_reinterpret.0)?;
+ }
+ match base {
+ Some(base) => w.write_uleb128(entry_offset(base)?)?,
+ None => w.write_u8(0)?,
+ }
+ }
+ Operation::EntryValue(ref expression) => {
+ if encoding.version >= 5 {
+ w.write_u8(constants::DW_OP_entry_value.0)?;
+ } else {
+ w.write_u8(constants::DW_OP_GNU_entry_value.0)?;
+ }
+ let length = expression.size(encoding, unit_offsets);
+ w.write_uleb128(length as u64)?;
+ expression.write(w, refs, encoding, unit_offsets)?;
+ }
+ Operation::Register(register) => {
+ if register.0 < 32 {
+ w.write_u8(constants::DW_OP_reg0.0 + register.0 as u8)?;
+ } else {
+ w.write_u8(constants::DW_OP_regx.0)?;
+ w.write_uleb128(register.0.into())?;
+ }
+ }
+ Operation::ImplicitValue(ref data) => {
+ w.write_u8(constants::DW_OP_implicit_value.0)?;
+ w.write_uleb128(data.len() as u64)?;
+ w.write(&data)?;
+ }
+ Operation::ImplicitPointer { entry, byte_offset } => {
+ if encoding.version >= 5 {
+ w.write_u8(constants::DW_OP_implicit_pointer.0)?;
+ } else {
+ w.write_u8(constants::DW_OP_GNU_implicit_pointer.0)?;
+ }
+ let size = if encoding.version == 2 {
+ encoding.address_size
+ } else {
+ encoding.format.word_size()
+ };
+ match entry {
+ Reference::Symbol(symbol) => {
+ w.write_reference(symbol, size)?;
+ }
+ Reference::Entry(unit, entry) => {
+ let refs = refs.ok_or(Error::InvalidReference)?;
+ refs.push(DebugInfoReference {
+ offset: w.len(),
+ unit,
+ entry,
+ size,
+ });
+ w.write_udata(0, size)?;
+ }
+ }
+ w.write_sleb128(byte_offset)?;
+ }
+ Operation::Piece { size_in_bytes } => {
+ w.write_u8(constants::DW_OP_piece.0)?;
+ w.write_uleb128(size_in_bytes)?;
+ }
+ Operation::BitPiece {
+ size_in_bits,
+ bit_offset,
+ } => {
+ w.write_u8(constants::DW_OP_bit_piece.0)?;
+ w.write_uleb128(size_in_bits)?;
+ w.write_uleb128(bit_offset)?;
+ }
+ Operation::ParameterRef(entry) => {
+ w.write_u8(constants::DW_OP_GNU_parameter_ref.0)?;
+ w.write_udata(entry_offset(entry)?, 4)?;
+ }
+ Operation::WasmLocal(index) => {
+ w.write(&[constants::DW_OP_WASM_location.0, 0])?;
+ w.write_uleb128(index.into())?;
+ }
+ Operation::WasmGlobal(index) => {
+ w.write(&[constants::DW_OP_WASM_location.0, 1])?;
+ w.write_uleb128(index.into())?;
+ }
+ Operation::WasmStack(index) => {
+ w.write(&[constants::DW_OP_WASM_location.0, 2])?;
+ w.write_uleb128(index.into())?;
+ }
+ }
+ Ok(())
+ }
+}
+
+#[cfg(feature = "read")]
+pub(crate) mod convert {
+ use super::*;
+ use crate::common::UnitSectionOffset;
+ use crate::read::{self, Reader};
+ use crate::write::{ConvertError, ConvertResult, UnitEntryId, UnitId};
+ use std::collections::HashMap;
+
+ impl Expression {
+ /// Create an expression from the input expression.
+ pub fn from<R: Reader<Offset = usize>>(
+ from_expression: read::Expression<R>,
+ encoding: Encoding,
+ dwarf: Option<&read::Dwarf<R>>,
+ unit: Option<&read::Unit<R>>,
+ entry_ids: Option<&HashMap<UnitSectionOffset, (UnitId, UnitEntryId)>>,
+ convert_address: &dyn Fn(u64) -> Option<Address>,
+ ) -> ConvertResult<Expression> {
+ let convert_unit_offset = |offset: read::UnitOffset| -> ConvertResult<_> {
+ let entry_ids = entry_ids.ok_or(ConvertError::UnsupportedOperation)?;
+ let unit = unit.ok_or(ConvertError::UnsupportedOperation)?;
+ let id = entry_ids
+ .get(&offset.to_unit_section_offset(unit))
+ .ok_or(ConvertError::InvalidUnitRef)?;
+ Ok(id.1)
+ };
+ let convert_debug_info_offset = |offset| -> ConvertResult<_> {
+ // TODO: support relocations
+ let entry_ids = entry_ids.ok_or(ConvertError::UnsupportedOperation)?;
+ let id = entry_ids
+ .get(&UnitSectionOffset::DebugInfoOffset(offset))
+ .ok_or(ConvertError::InvalidDebugInfoRef)?;
+ Ok(Reference::Entry(id.0, id.1))
+ };
+
+ // Calculate offsets for use in branch/skip operations.
+ let mut offsets = Vec::new();
+ let mut offset = 0;
+ let mut from_operations = from_expression.clone().operations(encoding);
+ while let Some(_) = from_operations.next()? {
+ offsets.push(offset);
+ offset = from_operations.offset_from(&from_expression);
+ }
+ offsets.push(from_expression.0.len());
+
+ let mut from_operations = from_expression.clone().operations(encoding);
+ let mut operations = Vec::new();
+ while let Some(from_operation) = from_operations.next()? {
+ let operation = match from_operation {
+ read::Operation::Deref {
+ base_type,
+ size,
+ space,
+ } => {
+ if base_type.0 != 0 {
+ let base = convert_unit_offset(base_type)?;
+ Operation::DerefType { space, size, base }
+ } else if size != encoding.address_size {
+ Operation::DerefSize { space, size }
+ } else {
+ Operation::Deref { space }
+ }
+ }
+ read::Operation::Drop => Operation::Simple(constants::DW_OP_drop),
+ read::Operation::Pick { index } => Operation::Pick(index),
+ read::Operation::Swap => Operation::Simple(constants::DW_OP_swap),
+ read::Operation::Rot => Operation::Simple(constants::DW_OP_rot),
+ read::Operation::Abs => Operation::Simple(constants::DW_OP_abs),
+ read::Operation::And => Operation::Simple(constants::DW_OP_and),
+ read::Operation::Div => Operation::Simple(constants::DW_OP_div),
+ read::Operation::Minus => Operation::Simple(constants::DW_OP_minus),
+ read::Operation::Mod => Operation::Simple(constants::DW_OP_mod),
+ read::Operation::Mul => Operation::Simple(constants::DW_OP_mul),
+ read::Operation::Neg => Operation::Simple(constants::DW_OP_neg),
+ read::Operation::Not => Operation::Simple(constants::DW_OP_not),
+ read::Operation::Or => Operation::Simple(constants::DW_OP_or),
+ read::Operation::Plus => Operation::Simple(constants::DW_OP_plus),
+ read::Operation::PlusConstant { value } => Operation::PlusConstant(value),
+ read::Operation::Shl => Operation::Simple(constants::DW_OP_shl),
+ read::Operation::Shr => Operation::Simple(constants::DW_OP_shr),
+ read::Operation::Shra => Operation::Simple(constants::DW_OP_shra),
+ read::Operation::Xor => Operation::Simple(constants::DW_OP_xor),
+ read::Operation::Eq => Operation::Simple(constants::DW_OP_eq),
+ read::Operation::Ge => Operation::Simple(constants::DW_OP_ge),
+ read::Operation::Gt => Operation::Simple(constants::DW_OP_gt),
+ read::Operation::Le => Operation::Simple(constants::DW_OP_le),
+ read::Operation::Lt => Operation::Simple(constants::DW_OP_lt),
+ read::Operation::Ne => Operation::Simple(constants::DW_OP_ne),
+ read::Operation::Bra { target } => {
+ let offset = from_operations
+ .offset_from(&from_expression)
+ .wrapping_add(i64::from(target) as usize);
+ let index = offsets
+ .binary_search(&offset)
+ .map_err(|_| ConvertError::InvalidBranchTarget)?;
+ Operation::Branch(index)
+ }
+ read::Operation::Skip { target } => {
+ let offset = from_operations
+ .offset_from(&from_expression)
+ .wrapping_add(i64::from(target) as usize);
+ let index = offsets
+ .binary_search(&offset)
+ .map_err(|_| ConvertError::InvalidBranchTarget)?;
+ Operation::Skip(index)
+ }
+ read::Operation::UnsignedConstant { value } => {
+ Operation::UnsignedConstant(value)
+ }
+ read::Operation::SignedConstant { value } => Operation::SignedConstant(value),
+ read::Operation::Register { register } => Operation::Register(register),
+ read::Operation::RegisterOffset {
+ register,
+ offset,
+ base_type,
+ } => {
+ if base_type.0 != 0 {
+ Operation::RegisterType(register, convert_unit_offset(base_type)?)
+ } else {
+ Operation::RegisterOffset(register, offset)
+ }
+ }
+ read::Operation::FrameOffset { offset } => Operation::FrameOffset(offset),
+ read::Operation::Nop => Operation::Simple(constants::DW_OP_nop),
+ read::Operation::PushObjectAddress => {
+ Operation::Simple(constants::DW_OP_push_object_address)
+ }
+ read::Operation::Call { offset } => match offset {
+ read::DieReference::UnitRef(offset) => {
+ Operation::Call(convert_unit_offset(offset)?)
+ }
+ read::DieReference::DebugInfoRef(offset) => {
+ Operation::CallRef(convert_debug_info_offset(offset)?)
+ }
+ },
+ read::Operation::TLS => Operation::Simple(constants::DW_OP_form_tls_address),
+ read::Operation::CallFrameCFA => {
+ Operation::Simple(constants::DW_OP_call_frame_cfa)
+ }
+ read::Operation::Piece {
+ size_in_bits,
+ bit_offset: None,
+ } => Operation::Piece {
+ size_in_bytes: size_in_bits / 8,
+ },
+ read::Operation::Piece {
+ size_in_bits,
+ bit_offset: Some(bit_offset),
+ } => Operation::BitPiece {
+ size_in_bits,
+ bit_offset,
+ },
+ read::Operation::ImplicitValue { data } => {
+ Operation::ImplicitValue(data.to_slice()?.into_owned().into())
+ }
+ read::Operation::StackValue => Operation::Simple(constants::DW_OP_stack_value),
+ read::Operation::ImplicitPointer { value, byte_offset } => {
+ let entry = convert_debug_info_offset(value)?;
+ Operation::ImplicitPointer { entry, byte_offset }
+ }
+ read::Operation::EntryValue { expression } => {
+ let expression = Expression::from(
+ read::Expression(expression),
+ encoding,
+ dwarf,
+ unit,
+ entry_ids,
+ convert_address,
+ )?;
+ Operation::EntryValue(expression)
+ }
+ read::Operation::ParameterRef { offset } => {
+ let entry = convert_unit_offset(offset)?;
+ Operation::ParameterRef(entry)
+ }
+ read::Operation::Address { address } => {
+ let address =
+ convert_address(address).ok_or(ConvertError::InvalidAddress)?;
+ Operation::Address(address)
+ }
+ read::Operation::AddressIndex { index } => {
+ let dwarf = dwarf.ok_or(ConvertError::UnsupportedOperation)?;
+ let unit = unit.ok_or(ConvertError::UnsupportedOperation)?;
+ let val = dwarf.address(unit, index)?;
+ let address = convert_address(val).ok_or(ConvertError::InvalidAddress)?;
+ Operation::Address(address)
+ }
+ read::Operation::ConstantIndex { index } => {
+ let dwarf = dwarf.ok_or(ConvertError::UnsupportedOperation)?;
+ let unit = unit.ok_or(ConvertError::UnsupportedOperation)?;
+ let val = dwarf.address(unit, index)?;
+ Operation::UnsignedConstant(val)
+ }
+ read::Operation::TypedLiteral { base_type, value } => {
+ let entry = convert_unit_offset(base_type)?;
+ Operation::ConstantType(entry, value.to_slice()?.into_owned().into())
+ }
+ read::Operation::Convert { base_type } => {
+ if base_type.0 == 0 {
+ Operation::Convert(None)
+ } else {
+ let entry = convert_unit_offset(base_type)?;
+ Operation::Convert(Some(entry))
+ }
+ }
+ read::Operation::Reinterpret { base_type } => {
+ if base_type.0 == 0 {
+ Operation::Reinterpret(None)
+ } else {
+ let entry = convert_unit_offset(base_type)?;
+ Operation::Reinterpret(Some(entry))
+ }
+ }
+ read::Operation::WasmLocal { index } => Operation::WasmLocal(index),
+ read::Operation::WasmGlobal { index } => Operation::WasmGlobal(index),
+ read::Operation::WasmStack { index } => Operation::WasmStack(index),
+ };
+ operations.push(operation);
+ }
+ Ok(Expression { operations })
+ }
+ }
+}
+
+#[cfg(test)]
+#[cfg(feature = "read")]
+mod tests {
+ use super::*;
+ use crate::common::{
+ DebugAbbrevOffset, DebugAddrBase, DebugInfoOffset, DebugLocListsBase, DebugRngListsBase,
+ DebugStrOffsetsBase, Format, SectionId,
+ };
+ use crate::read;
+ use crate::write::{
+ DebugLineStrOffsets, DebugStrOffsets, EndianVec, LineProgram, Sections, Unit, UnitTable,
+ };
+ use crate::LittleEndian;
+ use std::collections::HashMap;
+
+ #[test]
+ fn test_operation() {
+ for &version in &[3, 4, 5] {
+ for &address_size in &[4, 8] {
+ for &format in &[Format::Dwarf32, Format::Dwarf64] {
+ let encoding = Encoding {
+ format,
+ version,
+ address_size,
+ };
+
+ let mut units = UnitTable::default();
+ let unit_id = units.add(Unit::new(encoding, LineProgram::none()));
+ let unit = units.get_mut(unit_id);
+ let entry_id = unit.add(unit.root(), constants::DW_TAG_base_type);
+ let reference = Reference::Entry(unit_id, entry_id);
+
+ let mut sections = Sections::new(EndianVec::new(LittleEndian));
+ let debug_line_str_offsets = DebugLineStrOffsets::none();
+ let debug_str_offsets = DebugStrOffsets::none();
+ let debug_info_offsets = units
+ .write(&mut sections, &debug_line_str_offsets, &debug_str_offsets)
+ .unwrap();
+ let unit_offsets = debug_info_offsets.unit_offsets(unit_id);
+ let debug_info_offset = unit_offsets.debug_info_offset(entry_id);
+ let entry_offset =
+ read::UnitOffset(unit_offsets.unit_offset(entry_id) as usize);
+
+ let mut reg_expression = Expression::new();
+ reg_expression.op_reg(Register(23));
+
+ let operations: &[(&dyn Fn(&mut Expression), Operation, read::Operation<_>)] =
+ &[
+ (
+ &|x| x.op_deref(),
+ Operation::Deref { space: false },
+ read::Operation::Deref {
+ base_type: read::UnitOffset(0),
+ size: address_size,
+ space: false,
+ },
+ ),
+ (
+ &|x| x.op_xderef(),
+ Operation::Deref { space: true },
+ read::Operation::Deref {
+ base_type: read::UnitOffset(0),
+ size: address_size,
+ space: true,
+ },
+ ),
+ (
+ &|x| x.op_deref_size(2),
+ Operation::DerefSize {
+ space: false,
+ size: 2,
+ },
+ read::Operation::Deref {
+ base_type: read::UnitOffset(0),
+ size: 2,
+ space: false,
+ },
+ ),
+ (
+ &|x| x.op_xderef_size(2),
+ Operation::DerefSize {
+ space: true,
+ size: 2,
+ },
+ read::Operation::Deref {
+ base_type: read::UnitOffset(0),
+ size: 2,
+ space: true,
+ },
+ ),
+ (
+ &|x| x.op_deref_type(2, entry_id),
+ Operation::DerefType {
+ space: false,
+ size: 2,
+ base: entry_id,
+ },
+ read::Operation::Deref {
+ base_type: entry_offset,
+ size: 2,
+ space: false,
+ },
+ ),
+ (
+ &|x| x.op_xderef_type(2, entry_id),
+ Operation::DerefType {
+ space: true,
+ size: 2,
+ base: entry_id,
+ },
+ read::Operation::Deref {
+ base_type: entry_offset,
+ size: 2,
+ space: true,
+ },
+ ),
+ (
+ &|x| x.op(constants::DW_OP_drop),
+ Operation::Simple(constants::DW_OP_drop),
+ read::Operation::Drop,
+ ),
+ (
+ &|x| x.op_pick(0),
+ Operation::Pick(0),
+ read::Operation::Pick { index: 0 },
+ ),
+ (
+ &|x| x.op_pick(1),
+ Operation::Pick(1),
+ read::Operation::Pick { index: 1 },
+ ),
+ (
+ &|x| x.op_pick(2),
+ Operation::Pick(2),
+ read::Operation::Pick { index: 2 },
+ ),
+ (
+ &|x| x.op(constants::DW_OP_swap),
+ Operation::Simple(constants::DW_OP_swap),
+ read::Operation::Swap,
+ ),
+ (
+ &|x| x.op(constants::DW_OP_rot),
+ Operation::Simple(constants::DW_OP_rot),
+ read::Operation::Rot,
+ ),
+ (
+ &|x| x.op(constants::DW_OP_abs),
+ Operation::Simple(constants::DW_OP_abs),
+ read::Operation::Abs,
+ ),
+ (
+ &|x| x.op(constants::DW_OP_and),
+ Operation::Simple(constants::DW_OP_and),
+ read::Operation::And,
+ ),
+ (
+ &|x| x.op(constants::DW_OP_div),
+ Operation::Simple(constants::DW_OP_div),
+ read::Operation::Div,
+ ),
+ (
+ &|x| x.op(constants::DW_OP_minus),
+ Operation::Simple(constants::DW_OP_minus),
+ read::Operation::Minus,
+ ),
+ (
+ &|x| x.op(constants::DW_OP_mod),
+ Operation::Simple(constants::DW_OP_mod),
+ read::Operation::Mod,
+ ),
+ (
+ &|x| x.op(constants::DW_OP_mul),
+ Operation::Simple(constants::DW_OP_mul),
+ read::Operation::Mul,
+ ),
+ (
+ &|x| x.op(constants::DW_OP_neg),
+ Operation::Simple(constants::DW_OP_neg),
+ read::Operation::Neg,
+ ),
+ (
+ &|x| x.op(constants::DW_OP_not),
+ Operation::Simple(constants::DW_OP_not),
+ read::Operation::Not,
+ ),
+ (
+ &|x| x.op(constants::DW_OP_or),
+ Operation::Simple(constants::DW_OP_or),
+ read::Operation::Or,
+ ),
+ (
+ &|x| x.op(constants::DW_OP_plus),
+ Operation::Simple(constants::DW_OP_plus),
+ read::Operation::Plus,
+ ),
+ (
+ &|x| x.op_plus_uconst(23),
+ Operation::PlusConstant(23),
+ read::Operation::PlusConstant { value: 23 },
+ ),
+ (
+ &|x| x.op(constants::DW_OP_shl),
+ Operation::Simple(constants::DW_OP_shl),
+ read::Operation::Shl,
+ ),
+ (
+ &|x| x.op(constants::DW_OP_shr),
+ Operation::Simple(constants::DW_OP_shr),
+ read::Operation::Shr,
+ ),
+ (
+ &|x| x.op(constants::DW_OP_shra),
+ Operation::Simple(constants::DW_OP_shra),
+ read::Operation::Shra,
+ ),
+ (
+ &|x| x.op(constants::DW_OP_xor),
+ Operation::Simple(constants::DW_OP_xor),
+ read::Operation::Xor,
+ ),
+ (
+ &|x| x.op(constants::DW_OP_eq),
+ Operation::Simple(constants::DW_OP_eq),
+ read::Operation::Eq,
+ ),
+ (
+ &|x| x.op(constants::DW_OP_ge),
+ Operation::Simple(constants::DW_OP_ge),
+ read::Operation::Ge,
+ ),
+ (
+ &|x| x.op(constants::DW_OP_gt),
+ Operation::Simple(constants::DW_OP_gt),
+ read::Operation::Gt,
+ ),
+ (
+ &|x| x.op(constants::DW_OP_le),
+ Operation::Simple(constants::DW_OP_le),
+ read::Operation::Le,
+ ),
+ (
+ &|x| x.op(constants::DW_OP_lt),
+ Operation::Simple(constants::DW_OP_lt),
+ read::Operation::Lt,
+ ),
+ (
+ &|x| x.op(constants::DW_OP_ne),
+ Operation::Simple(constants::DW_OP_ne),
+ read::Operation::Ne,
+ ),
+ (
+ &|x| x.op_constu(23),
+ Operation::UnsignedConstant(23),
+ read::Operation::UnsignedConstant { value: 23 },
+ ),
+ (
+ &|x| x.op_consts(-23),
+ Operation::SignedConstant(-23),
+ read::Operation::SignedConstant { value: -23 },
+ ),
+ (
+ &|x| x.op_reg(Register(23)),
+ Operation::Register(Register(23)),
+ read::Operation::Register {
+ register: Register(23),
+ },
+ ),
+ (
+ &|x| x.op_reg(Register(123)),
+ Operation::Register(Register(123)),
+ read::Operation::Register {
+ register: Register(123),
+ },
+ ),
+ (
+ &|x| x.op_breg(Register(23), 34),
+ Operation::RegisterOffset(Register(23), 34),
+ read::Operation::RegisterOffset {
+ register: Register(23),
+ offset: 34,
+ base_type: read::UnitOffset(0),
+ },
+ ),
+ (
+ &|x| x.op_breg(Register(123), 34),
+ Operation::RegisterOffset(Register(123), 34),
+ read::Operation::RegisterOffset {
+ register: Register(123),
+ offset: 34,
+ base_type: read::UnitOffset(0),
+ },
+ ),
+ (
+ &|x| x.op_regval_type(Register(23), entry_id),
+ Operation::RegisterType(Register(23), entry_id),
+ read::Operation::RegisterOffset {
+ register: Register(23),
+ offset: 0,
+ base_type: entry_offset,
+ },
+ ),
+ (
+ &|x| x.op_fbreg(34),
+ Operation::FrameOffset(34),
+ read::Operation::FrameOffset { offset: 34 },
+ ),
+ (
+ &|x| x.op(constants::DW_OP_nop),
+ Operation::Simple(constants::DW_OP_nop),
+ read::Operation::Nop,
+ ),
+ (
+ &|x| x.op(constants::DW_OP_push_object_address),
+ Operation::Simple(constants::DW_OP_push_object_address),
+ read::Operation::PushObjectAddress,
+ ),
+ (
+ &|x| x.op_call(entry_id),
+ Operation::Call(entry_id),
+ read::Operation::Call {
+ offset: read::DieReference::UnitRef(entry_offset),
+ },
+ ),
+ (
+ &|x| x.op_call_ref(reference),
+ Operation::CallRef(reference),
+ read::Operation::Call {
+ offset: read::DieReference::DebugInfoRef(debug_info_offset),
+ },
+ ),
+ (
+ &|x| x.op(constants::DW_OP_form_tls_address),
+ Operation::Simple(constants::DW_OP_form_tls_address),
+ read::Operation::TLS,
+ ),
+ (
+ &|x| x.op(constants::DW_OP_call_frame_cfa),
+ Operation::Simple(constants::DW_OP_call_frame_cfa),
+ read::Operation::CallFrameCFA,
+ ),
+ (
+ &|x| x.op_piece(23),
+ Operation::Piece { size_in_bytes: 23 },
+ read::Operation::Piece {
+ size_in_bits: 23 * 8,
+ bit_offset: None,
+ },
+ ),
+ (
+ &|x| x.op_bit_piece(23, 34),
+ Operation::BitPiece {
+ size_in_bits: 23,
+ bit_offset: 34,
+ },
+ read::Operation::Piece {
+ size_in_bits: 23,
+ bit_offset: Some(34),
+ },
+ ),
+ (
+ &|x| x.op_implicit_value(vec![23].into()),
+ Operation::ImplicitValue(vec![23].into()),
+ read::Operation::ImplicitValue {
+ data: read::EndianSlice::new(&[23], LittleEndian),
+ },
+ ),
+ (
+ &|x| x.op(constants::DW_OP_stack_value),
+ Operation::Simple(constants::DW_OP_stack_value),
+ read::Operation::StackValue,
+ ),
+ (
+ &|x| x.op_implicit_pointer(reference, 23),
+ Operation::ImplicitPointer {
+ entry: reference,
+ byte_offset: 23,
+ },
+ read::Operation::ImplicitPointer {
+ value: debug_info_offset,
+ byte_offset: 23,
+ },
+ ),
+ (
+ &|x| x.op_entry_value(reg_expression.clone()),
+ Operation::EntryValue(reg_expression.clone()),
+ read::Operation::EntryValue {
+ expression: read::EndianSlice::new(
+ &[constants::DW_OP_reg23.0],
+ LittleEndian,
+ ),
+ },
+ ),
+ (
+ &|x| x.op_gnu_parameter_ref(entry_id),
+ Operation::ParameterRef(entry_id),
+ read::Operation::ParameterRef {
+ offset: entry_offset,
+ },
+ ),
+ (
+ &|x| x.op_addr(Address::Constant(23)),
+ Operation::Address(Address::Constant(23)),
+ read::Operation::Address { address: 23 },
+ ),
+ (
+ &|x| x.op_const_type(entry_id, vec![23].into()),
+ Operation::ConstantType(entry_id, vec![23].into()),
+ read::Operation::TypedLiteral {
+ base_type: entry_offset,
+ value: read::EndianSlice::new(&[23], LittleEndian),
+ },
+ ),
+ (
+ &|x| x.op_convert(None),
+ Operation::Convert(None),
+ read::Operation::Convert {
+ base_type: read::UnitOffset(0),
+ },
+ ),
+ (
+ &|x| x.op_convert(Some(entry_id)),
+ Operation::Convert(Some(entry_id)),
+ read::Operation::Convert {
+ base_type: entry_offset,
+ },
+ ),
+ (
+ &|x| x.op_reinterpret(None),
+ Operation::Reinterpret(None),
+ read::Operation::Reinterpret {
+ base_type: read::UnitOffset(0),
+ },
+ ),
+ (
+ &|x| x.op_reinterpret(Some(entry_id)),
+ Operation::Reinterpret(Some(entry_id)),
+ read::Operation::Reinterpret {
+ base_type: entry_offset,
+ },
+ ),
+ (
+ &|x| x.op_wasm_local(1000),
+ Operation::WasmLocal(1000),
+ read::Operation::WasmLocal { index: 1000 },
+ ),
+ (
+ &|x| x.op_wasm_global(1000),
+ Operation::WasmGlobal(1000),
+ read::Operation::WasmGlobal { index: 1000 },
+ ),
+ (
+ &|x| x.op_wasm_stack(1000),
+ Operation::WasmStack(1000),
+ read::Operation::WasmStack { index: 1000 },
+ ),
+ ];
+
+ let mut expression = Expression::new();
+ let start_index = expression.next_index();
+ for (f, o, _) in operations {
+ f(&mut expression);
+ assert_eq!(expression.operations.last(), Some(o));
+ }
+
+ let bra_index = expression.op_bra();
+ let skip_index = expression.op_skip();
+ expression.op(constants::DW_OP_nop);
+ let end_index = expression.next_index();
+ expression.set_target(bra_index, start_index);
+ expression.set_target(skip_index, end_index);
+
+ let mut w = EndianVec::new(LittleEndian);
+ let mut refs = Vec::new();
+ expression
+ .write(&mut w, Some(&mut refs), encoding, Some(&unit_offsets))
+ .unwrap();
+ for r in &refs {
+ assert_eq!(r.unit, unit_id);
+ assert_eq!(r.entry, entry_id);
+ w.write_offset_at(
+ r.offset,
+ debug_info_offset.0,
+ SectionId::DebugInfo,
+ r.size,
+ )
+ .unwrap();
+ }
+
+ let read_expression =
+ read::Expression(read::EndianSlice::new(w.slice(), LittleEndian));
+ let mut read_operations = read_expression.operations(encoding);
+ for (_, _, operation) in operations {
+ assert_eq!(read_operations.next(), Ok(Some(*operation)));
+ }
+
+ // 4 = DW_OP_skip + i16 + DW_OP_nop
+ assert_eq!(
+ read_operations.next(),
+ Ok(Some(read::Operation::Bra {
+ target: -(w.len() as i16) + 4
+ }))
+ );
+ // 1 = DW_OP_nop
+ assert_eq!(
+ read_operations.next(),
+ Ok(Some(read::Operation::Skip { target: 1 }))
+ );
+ assert_eq!(read_operations.next(), Ok(Some(read::Operation::Nop)));
+ assert_eq!(read_operations.next(), Ok(None));
+
+ // Fake the unit.
+ let unit = read::Unit {
+ header: read::UnitHeader::new(
+ encoding,
+ 0,
+ read::UnitType::Compilation,
+ DebugAbbrevOffset(0),
+ DebugInfoOffset(0).into(),
+ read::EndianSlice::new(&[], LittleEndian),
+ ),
+ abbreviations: read::Abbreviations::default(),
+ name: None,
+ comp_dir: None,
+ low_pc: 0,
+ str_offsets_base: DebugStrOffsetsBase(0),
+ addr_base: DebugAddrBase(0),
+ loclists_base: DebugLocListsBase(0),
+ rnglists_base: DebugRngListsBase(0),
+ line_program: None,
+ dwo_id: None,
+ };
+
+ let mut entry_ids = HashMap::new();
+ entry_ids.insert(debug_info_offset.into(), (unit_id, entry_id));
+ let convert_expression = Expression::from(
+ read_expression,
+ encoding,
+ None, /* dwarf */
+ Some(&unit),
+ Some(&entry_ids),
+ &|address| Some(Address::Constant(address)),
+ )
+ .unwrap();
+ let mut convert_operations = convert_expression.operations.iter();
+ for (_, operation, _) in operations {
+ assert_eq!(convert_operations.next(), Some(operation));
+ }
+ assert_eq!(
+ convert_operations.next(),
+ Some(&Operation::Branch(start_index))
+ );
+ assert_eq!(convert_operations.next(), Some(&Operation::Skip(end_index)));
+ assert_eq!(
+ convert_operations.next(),
+ Some(&Operation::Simple(constants::DW_OP_nop))
+ );
+ }
+ }
+ }
+ }
+}
diff --git a/vendor/gimli-0.26.2/src/write/range.rs b/vendor/gimli-0.26.2/src/write/range.rs
new file mode 100644
index 000000000..b44ce1b7b
--- /dev/null
+++ b/vendor/gimli-0.26.2/src/write/range.rs
@@ -0,0 +1,415 @@
+use alloc::vec::Vec;
+use indexmap::IndexSet;
+use std::ops::{Deref, DerefMut};
+
+use crate::common::{Encoding, RangeListsOffset, SectionId};
+use crate::write::{Address, BaseId, Error, Result, Section, Sections, Writer};
+
+define_section!(
+ DebugRanges,
+ RangeListsOffset,
+ "A writable `.debug_ranges` section."
+);
+define_section!(
+ DebugRngLists,
+ RangeListsOffset,
+ "A writable `.debug_rnglists` section."
+);
+
+define_offsets!(
+ RangeListOffsets: RangeListId => RangeListsOffset,
+ "The section offsets of a series of range lists within the `.debug_ranges` or `.debug_rnglists` sections."
+);
+
+define_id!(
+ RangeListId,
+ "An identifier for a range list in a `RangeListTable`."
+);
+
+/// A table of range lists that will be stored in a `.debug_ranges` or `.debug_rnglists` section.
+#[derive(Debug, Default)]
+pub struct RangeListTable {
+ base_id: BaseId,
+ ranges: IndexSet<RangeList>,
+}
+
+impl RangeListTable {
+ /// Add a range list to the table.
+ pub fn add(&mut self, range_list: RangeList) -> RangeListId {
+ let (index, _) = self.ranges.insert_full(range_list);
+ RangeListId::new(self.base_id, index)
+ }
+
+ /// Write the range list table to the appropriate section for the given DWARF version.
+ pub(crate) fn write<W: Writer>(
+ &self,
+ sections: &mut Sections<W>,
+ encoding: Encoding,
+ ) -> Result<RangeListOffsets> {
+ if self.ranges.is_empty() {
+ return Ok(RangeListOffsets::none());
+ }
+
+ match encoding.version {
+ 2..=4 => self.write_ranges(&mut sections.debug_ranges, encoding.address_size),
+ 5 => self.write_rnglists(&mut sections.debug_rnglists, encoding),
+ _ => Err(Error::UnsupportedVersion(encoding.version)),
+ }
+ }
+
+ /// Write the range list table to the `.debug_ranges` section.
+ fn write_ranges<W: Writer>(
+ &self,
+ w: &mut DebugRanges<W>,
+ address_size: u8,
+ ) -> Result<RangeListOffsets> {
+ let mut offsets = Vec::new();
+ for range_list in self.ranges.iter() {
+ offsets.push(w.offset());
+ for range in &range_list.0 {
+ // Note that we must ensure none of the ranges have both begin == 0 and end == 0.
+ // We do this by ensuring that begin != end, which is a bit more restrictive
+ // than required, but still seems reasonable.
+ match *range {
+ Range::BaseAddress { address } => {
+ let marker = !0 >> (64 - address_size * 8);
+ w.write_udata(marker, address_size)?;
+ w.write_address(address, address_size)?;
+ }
+ Range::OffsetPair { begin, end } => {
+ if begin == end {
+ return Err(Error::InvalidRange);
+ }
+ w.write_udata(begin, address_size)?;
+ w.write_udata(end, address_size)?;
+ }
+ Range::StartEnd { begin, end } => {
+ if begin == end {
+ return Err(Error::InvalidRange);
+ }
+ w.write_address(begin, address_size)?;
+ w.write_address(end, address_size)?;
+ }
+ Range::StartLength { begin, length } => {
+ let end = match begin {
+ Address::Constant(begin) => Address::Constant(begin + length),
+ Address::Symbol { symbol, addend } => Address::Symbol {
+ symbol,
+ addend: addend + length as i64,
+ },
+ };
+ if begin == end {
+ return Err(Error::InvalidRange);
+ }
+ w.write_address(begin, address_size)?;
+ w.write_address(end, address_size)?;
+ }
+ }
+ }
+ w.write_udata(0, address_size)?;
+ w.write_udata(0, address_size)?;
+ }
+ Ok(RangeListOffsets {
+ base_id: self.base_id,
+ offsets,
+ })
+ }
+
+ /// Write the range list table to the `.debug_rnglists` section.
+ fn write_rnglists<W: Writer>(
+ &self,
+ w: &mut DebugRngLists<W>,
+ encoding: Encoding,
+ ) -> Result<RangeListOffsets> {
+ let mut offsets = Vec::new();
+
+ if encoding.version != 5 {
+ return Err(Error::NeedVersion(5));
+ }
+
+ let length_offset = w.write_initial_length(encoding.format)?;
+ let length_base = w.len();
+
+ w.write_u16(encoding.version)?;
+ w.write_u8(encoding.address_size)?;
+ w.write_u8(0)?; // segment_selector_size
+ w.write_u32(0)?; // offset_entry_count (when set to zero DW_FORM_rnglistx can't be used, see section 7.28)
+ // FIXME implement DW_FORM_rnglistx writing and implement the offset entry list
+
+ for range_list in self.ranges.iter() {
+ offsets.push(w.offset());
+ for range in &range_list.0 {
+ match *range {
+ Range::BaseAddress { address } => {
+ w.write_u8(crate::constants::DW_RLE_base_address.0)?;
+ w.write_address(address, encoding.address_size)?;
+ }
+ Range::OffsetPair { begin, end } => {
+ w.write_u8(crate::constants::DW_RLE_offset_pair.0)?;
+ w.write_uleb128(begin)?;
+ w.write_uleb128(end)?;
+ }
+ Range::StartEnd { begin, end } => {
+ w.write_u8(crate::constants::DW_RLE_start_end.0)?;
+ w.write_address(begin, encoding.address_size)?;
+ w.write_address(end, encoding.address_size)?;
+ }
+ Range::StartLength { begin, length } => {
+ w.write_u8(crate::constants::DW_RLE_start_length.0)?;
+ w.write_address(begin, encoding.address_size)?;
+ w.write_uleb128(length)?;
+ }
+ }
+ }
+
+ w.write_u8(crate::constants::DW_RLE_end_of_list.0)?;
+ }
+
+ let length = (w.len() - length_base) as u64;
+ w.write_initial_length_at(length_offset, length, encoding.format)?;
+
+ Ok(RangeListOffsets {
+ base_id: self.base_id,
+ offsets,
+ })
+ }
+}
+
+/// A range list that will be stored in a `.debug_ranges` or `.debug_rnglists` section.
+#[derive(Clone, Debug, Eq, PartialEq, Hash)]
+pub struct RangeList(pub Vec<Range>);
+
+/// A single range.
+#[derive(Clone, Debug, Eq, PartialEq, Hash)]
+pub enum Range {
+ /// DW_RLE_base_address
+ BaseAddress {
+ /// Base address.
+ address: Address,
+ },
+ /// DW_RLE_offset_pair
+ OffsetPair {
+ /// Start of range relative to base address.
+ begin: u64,
+ /// End of range relative to base address.
+ end: u64,
+ },
+ /// DW_RLE_start_end
+ StartEnd {
+ /// Start of range.
+ begin: Address,
+ /// End of range.
+ end: Address,
+ },
+ /// DW_RLE_start_length
+ StartLength {
+ /// Start of range.
+ begin: Address,
+ /// Length of range.
+ length: u64,
+ },
+}
+
+#[cfg(feature = "read")]
+mod convert {
+ use super::*;
+
+ use crate::read::{self, Reader};
+ use crate::write::{ConvertError, ConvertResult, ConvertUnitContext};
+
+ impl RangeList {
+ /// Create a range list by reading the data from the give range list iter.
+ pub(crate) fn from<R: Reader<Offset = usize>>(
+ mut from: read::RawRngListIter<R>,
+ context: &ConvertUnitContext<R>,
+ ) -> ConvertResult<Self> {
+ let mut have_base_address = context.base_address != Address::Constant(0);
+ let convert_address =
+ |x| (context.convert_address)(x).ok_or(ConvertError::InvalidAddress);
+ let mut ranges = Vec::new();
+ while let Some(from_range) = from.next()? {
+ let range = match from_range {
+ read::RawRngListEntry::AddressOrOffsetPair { begin, end } => {
+ // These were parsed as addresses, even if they are offsets.
+ let begin = convert_address(begin)?;
+ let end = convert_address(end)?;
+ match (begin, end) {
+ (Address::Constant(begin_offset), Address::Constant(end_offset)) => {
+ if have_base_address {
+ Range::OffsetPair {
+ begin: begin_offset,
+ end: end_offset,
+ }
+ } else {
+ Range::StartEnd { begin, end }
+ }
+ }
+ _ => {
+ if have_base_address {
+ // At least one of begin/end is an address, but we also have
+ // a base address. Adding addresses is undefined.
+ return Err(ConvertError::InvalidRangeRelativeAddress);
+ }
+ Range::StartEnd { begin, end }
+ }
+ }
+ }
+ read::RawRngListEntry::BaseAddress { addr } => {
+ have_base_address = true;
+ let address = convert_address(addr)?;
+ Range::BaseAddress { address }
+ }
+ read::RawRngListEntry::BaseAddressx { addr } => {
+ have_base_address = true;
+ let address = convert_address(context.dwarf.address(context.unit, addr)?)?;
+ Range::BaseAddress { address }
+ }
+ read::RawRngListEntry::StartxEndx { begin, end } => {
+ let begin = convert_address(context.dwarf.address(context.unit, begin)?)?;
+ let end = convert_address(context.dwarf.address(context.unit, end)?)?;
+ Range::StartEnd { begin, end }
+ }
+ read::RawRngListEntry::StartxLength { begin, length } => {
+ let begin = convert_address(context.dwarf.address(context.unit, begin)?)?;
+ Range::StartLength { begin, length }
+ }
+ read::RawRngListEntry::OffsetPair { begin, end } => {
+ Range::OffsetPair { begin, end }
+ }
+ read::RawRngListEntry::StartEnd { begin, end } => {
+ let begin = convert_address(begin)?;
+ let end = convert_address(end)?;
+ Range::StartEnd { begin, end }
+ }
+ read::RawRngListEntry::StartLength { begin, length } => {
+ let begin = convert_address(begin)?;
+ Range::StartLength { begin, length }
+ }
+ };
+ // Filtering empty ranges out.
+ match range {
+ Range::StartLength { length, .. } if length == 0 => continue,
+ Range::StartEnd { begin, end, .. } if begin == end => continue,
+ Range::OffsetPair { begin, end, .. } if begin == end => continue,
+ _ => (),
+ }
+ ranges.push(range);
+ }
+ Ok(RangeList(ranges))
+ }
+ }
+}
+
+#[cfg(test)]
+#[cfg(feature = "read")]
+mod tests {
+ use super::*;
+ use crate::common::{
+ DebugAbbrevOffset, DebugAddrBase, DebugInfoOffset, DebugLocListsBase, DebugRngListsBase,
+ DebugStrOffsetsBase, Format,
+ };
+ use crate::read;
+ use crate::write::{
+ ConvertUnitContext, EndianVec, LineStringTable, LocationListTable, Range, RangeListTable,
+ StringTable,
+ };
+ use crate::LittleEndian;
+ use std::collections::HashMap;
+
+ #[test]
+ fn test_range() {
+ let mut line_strings = LineStringTable::default();
+ let mut strings = StringTable::default();
+
+ for &version in &[2, 3, 4, 5] {
+ for &address_size in &[4, 8] {
+ for &format in &[Format::Dwarf32, Format::Dwarf64] {
+ let encoding = Encoding {
+ format,
+ version,
+ address_size,
+ };
+
+ let mut range_list = RangeList(vec![
+ Range::StartLength {
+ begin: Address::Constant(6666),
+ length: 7777,
+ },
+ Range::StartEnd {
+ begin: Address::Constant(4444),
+ end: Address::Constant(5555),
+ },
+ Range::BaseAddress {
+ address: Address::Constant(1111),
+ },
+ Range::OffsetPair {
+ begin: 2222,
+ end: 3333,
+ },
+ ]);
+
+ let mut ranges = RangeListTable::default();
+ let range_list_id = ranges.add(range_list.clone());
+
+ let mut sections = Sections::new(EndianVec::new(LittleEndian));
+ let range_list_offsets = ranges.write(&mut sections, encoding).unwrap();
+
+ let read_debug_ranges =
+ read::DebugRanges::new(sections.debug_ranges.slice(), LittleEndian);
+ let read_debug_rnglists =
+ read::DebugRngLists::new(sections.debug_rnglists.slice(), LittleEndian);
+ let read_ranges = read::RangeLists::new(read_debug_ranges, read_debug_rnglists);
+ let offset = range_list_offsets.get(range_list_id);
+ let read_range_list = read_ranges.raw_ranges(offset, encoding).unwrap();
+
+ let dwarf = read::Dwarf {
+ ranges: read_ranges,
+ ..Default::default()
+ };
+ let unit = read::Unit {
+ header: read::UnitHeader::new(
+ encoding,
+ 0,
+ read::UnitType::Compilation,
+ DebugAbbrevOffset(0),
+ DebugInfoOffset(0).into(),
+ read::EndianSlice::default(),
+ ),
+ abbreviations: read::Abbreviations::default(),
+ name: None,
+ comp_dir: None,
+ low_pc: 0,
+ str_offsets_base: DebugStrOffsetsBase(0),
+ addr_base: DebugAddrBase(0),
+ loclists_base: DebugLocListsBase(0),
+ rnglists_base: DebugRngListsBase(0),
+ line_program: None,
+ dwo_id: None,
+ };
+ let context = ConvertUnitContext {
+ dwarf: &dwarf,
+ unit: &unit,
+ line_strings: &mut line_strings,
+ strings: &mut strings,
+ ranges: &mut ranges,
+ locations: &mut LocationListTable::default(),
+ convert_address: &|address| Some(Address::Constant(address)),
+ base_address: Address::Constant(0),
+ line_program_offset: None,
+ line_program_files: Vec::new(),
+ entry_ids: &HashMap::new(),
+ };
+ let convert_range_list = RangeList::from(read_range_list, &context).unwrap();
+
+ if version <= 4 {
+ range_list.0[0] = Range::StartEnd {
+ begin: Address::Constant(6666),
+ end: Address::Constant(6666 + 7777),
+ };
+ }
+ assert_eq!(range_list, convert_range_list);
+ }
+ }
+ }
+ }
+}
diff --git a/vendor/gimli-0.26.2/src/write/section.rs b/vendor/gimli-0.26.2/src/write/section.rs
new file mode 100644
index 000000000..e8f3378cd
--- /dev/null
+++ b/vendor/gimli-0.26.2/src/write/section.rs
@@ -0,0 +1,172 @@
+use std::ops::DerefMut;
+use std::result;
+use std::vec::Vec;
+
+use crate::common::SectionId;
+use crate::write::{
+ DebugAbbrev, DebugFrame, DebugInfo, DebugInfoReference, DebugLine, DebugLineStr, DebugLoc,
+ DebugLocLists, DebugRanges, DebugRngLists, DebugStr, EhFrame, Writer,
+};
+
+macro_rules! define_section {
+ ($name:ident, $offset:ident, $docs:expr) => {
+ #[doc=$docs]
+ #[derive(Debug, Default)]
+ pub struct $name<W: Writer>(pub W);
+
+ impl<W: Writer> $name<W> {
+ /// Return the offset of the next write.
+ pub fn offset(&self) -> $offset {
+ $offset(self.len())
+ }
+ }
+
+ impl<W: Writer> From<W> for $name<W> {
+ #[inline]
+ fn from(w: W) -> Self {
+ $name(w)
+ }
+ }
+
+ impl<W: Writer> Deref for $name<W> {
+ type Target = W;
+
+ #[inline]
+ fn deref(&self) -> &W {
+ &self.0
+ }
+ }
+
+ impl<W: Writer> DerefMut for $name<W> {
+ #[inline]
+ fn deref_mut(&mut self) -> &mut W {
+ &mut self.0
+ }
+ }
+
+ impl<W: Writer> Section<W> for $name<W> {
+ #[inline]
+ fn id(&self) -> SectionId {
+ SectionId::$name
+ }
+ }
+ };
+}
+
+/// Functionality common to all writable DWARF sections.
+pub trait Section<W: Writer>: DerefMut<Target = W> {
+ /// Returns the DWARF section kind for this type.
+ fn id(&self) -> SectionId;
+
+ /// Returns the ELF section name for this type.
+ fn name(&self) -> &'static str {
+ self.id().name()
+ }
+}
+
+/// All of the writable DWARF sections.
+#[derive(Debug, Default)]
+pub struct Sections<W: Writer> {
+ /// The `.debug_abbrev` section.
+ pub debug_abbrev: DebugAbbrev<W>,
+ /// The `.debug_info` section.
+ pub debug_info: DebugInfo<W>,
+ /// The `.debug_line` section.
+ pub debug_line: DebugLine<W>,
+ /// The `.debug_line_str` section.
+ pub debug_line_str: DebugLineStr<W>,
+ /// The `.debug_ranges` section.
+ pub debug_ranges: DebugRanges<W>,
+ /// The `.debug_rnglists` section.
+ pub debug_rnglists: DebugRngLists<W>,
+ /// The `.debug_loc` section.
+ pub debug_loc: DebugLoc<W>,
+ /// The `.debug_loclists` section.
+ pub debug_loclists: DebugLocLists<W>,
+ /// The `.debug_str` section.
+ pub debug_str: DebugStr<W>,
+ /// The `.debug_frame` section.
+ pub debug_frame: DebugFrame<W>,
+ /// The `.eh_frame` section.
+ pub eh_frame: EhFrame<W>,
+ /// Unresolved references in the `.debug_info` section.
+ pub(crate) debug_info_refs: Vec<DebugInfoReference>,
+ /// Unresolved references in the `.debug_loc` section.
+ pub(crate) debug_loc_refs: Vec<DebugInfoReference>,
+ /// Unresolved references in the `.debug_loclists` section.
+ pub(crate) debug_loclists_refs: Vec<DebugInfoReference>,
+}
+
+impl<W: Writer + Clone> Sections<W> {
+ /// Create a new `Sections` using clones of the given `section`.
+ pub fn new(section: W) -> Self {
+ Sections {
+ debug_abbrev: DebugAbbrev(section.clone()),
+ debug_info: DebugInfo(section.clone()),
+ debug_line: DebugLine(section.clone()),
+ debug_line_str: DebugLineStr(section.clone()),
+ debug_ranges: DebugRanges(section.clone()),
+ debug_rnglists: DebugRngLists(section.clone()),
+ debug_loc: DebugLoc(section.clone()),
+ debug_loclists: DebugLocLists(section.clone()),
+ debug_str: DebugStr(section.clone()),
+ debug_frame: DebugFrame(section.clone()),
+ eh_frame: EhFrame(section.clone()),
+ debug_info_refs: Vec::new(),
+ debug_loc_refs: Vec::new(),
+ debug_loclists_refs: Vec::new(),
+ }
+ }
+}
+
+impl<W: Writer> Sections<W> {
+ /// For each section, call `f` once with a shared reference.
+ pub fn for_each<F, E>(&self, mut f: F) -> result::Result<(), E>
+ where
+ F: FnMut(SectionId, &W) -> result::Result<(), E>,
+ {
+ macro_rules! f {
+ ($s:expr) => {
+ f($s.id(), &$s)
+ };
+ }
+ // Ordered so that earlier sections do not reference later sections.
+ f!(self.debug_abbrev)?;
+ f!(self.debug_str)?;
+ f!(self.debug_line_str)?;
+ f!(self.debug_line)?;
+ f!(self.debug_ranges)?;
+ f!(self.debug_rnglists)?;
+ f!(self.debug_loc)?;
+ f!(self.debug_loclists)?;
+ f!(self.debug_info)?;
+ f!(self.debug_frame)?;
+ f!(self.eh_frame)?;
+ Ok(())
+ }
+
+ /// For each section, call `f` once with a mutable reference.
+ pub fn for_each_mut<F, E>(&mut self, mut f: F) -> result::Result<(), E>
+ where
+ F: FnMut(SectionId, &mut W) -> result::Result<(), E>,
+ {
+ macro_rules! f {
+ ($s:expr) => {
+ f($s.id(), &mut $s)
+ };
+ }
+ // Ordered so that earlier sections do not reference later sections.
+ f!(self.debug_abbrev)?;
+ f!(self.debug_str)?;
+ f!(self.debug_line_str)?;
+ f!(self.debug_line)?;
+ f!(self.debug_ranges)?;
+ f!(self.debug_rnglists)?;
+ f!(self.debug_loc)?;
+ f!(self.debug_loclists)?;
+ f!(self.debug_info)?;
+ f!(self.debug_frame)?;
+ f!(self.eh_frame)?;
+ Ok(())
+ }
+}
diff --git a/vendor/gimli-0.26.2/src/write/str.rs b/vendor/gimli-0.26.2/src/write/str.rs
new file mode 100644
index 000000000..83285c035
--- /dev/null
+++ b/vendor/gimli-0.26.2/src/write/str.rs
@@ -0,0 +1,172 @@
+use alloc::vec::Vec;
+use indexmap::IndexSet;
+use std::ops::{Deref, DerefMut};
+
+use crate::common::{DebugLineStrOffset, DebugStrOffset, SectionId};
+use crate::write::{BaseId, Result, Section, Writer};
+
+// Requirements:
+// - values are `[u8]`, null bytes are not allowed
+// - insertion returns a fixed id
+// - inserting a duplicate returns the id of the existing value
+// - able to convert an id to a section offset
+// Optional?
+// - able to get an existing value given an id
+//
+// Limitations of current implementation (using IndexSet):
+// - inserting requires either an allocation for duplicates,
+// or a double lookup for non-duplicates
+// - doesn't preserve offsets when updating an existing `.debug_str` section
+//
+// Possible changes:
+// - calculate offsets as we add values, and use that as the id.
+// This would avoid the need for DebugStrOffsets but would make it
+// hard to implement `get`.
+macro_rules! define_string_table {
+ ($name:ident, $id:ident, $section:ident, $offsets:ident, $docs:expr) => {
+ #[doc=$docs]
+ #[derive(Debug, Default)]
+ pub struct $name {
+ base_id: BaseId,
+ strings: IndexSet<Vec<u8>>,
+ }
+
+ impl $name {
+ /// Add a string to the string table and return its id.
+ ///
+ /// If the string already exists, then return the id of the existing string.
+ ///
+ /// # Panics
+ ///
+ /// Panics if `bytes` contains a null byte.
+ pub fn add<T>(&mut self, bytes: T) -> $id
+ where
+ T: Into<Vec<u8>>,
+ {
+ let bytes = bytes.into();
+ assert!(!bytes.contains(&0));
+ let (index, _) = self.strings.insert_full(bytes);
+ $id::new(self.base_id, index)
+ }
+
+ /// Return the number of strings in the table.
+ #[inline]
+ pub fn count(&self) -> usize {
+ self.strings.len()
+ }
+
+ /// Get a reference to a string in the table.
+ ///
+ /// # Panics
+ ///
+ /// Panics if `id` is invalid.
+ pub fn get(&self, id: $id) -> &[u8] {
+ debug_assert_eq!(self.base_id, id.base_id);
+ self.strings.get_index(id.index).map(Vec::as_slice).unwrap()
+ }
+
+ /// Write the string table to the `.debug_str` section.
+ ///
+ /// Returns the offsets at which the strings are written.
+ pub fn write<W: Writer>(&self, w: &mut $section<W>) -> Result<$offsets> {
+ let mut offsets = Vec::new();
+ for bytes in self.strings.iter() {
+ offsets.push(w.offset());
+ w.write(bytes)?;
+ w.write_u8(0)?;
+ }
+
+ Ok($offsets {
+ base_id: self.base_id,
+ offsets,
+ })
+ }
+ }
+ };
+}
+
+define_id!(StringId, "An identifier for a string in a `StringTable`.");
+
+define_string_table!(
+ StringTable,
+ StringId,
+ DebugStr,
+ DebugStrOffsets,
+ "A table of strings that will be stored in a `.debug_str` section."
+);
+
+define_section!(DebugStr, DebugStrOffset, "A writable `.debug_str` section.");
+
+define_offsets!(
+ DebugStrOffsets: StringId => DebugStrOffset,
+ "The section offsets of all strings within a `.debug_str` section."
+);
+
+define_id!(
+ LineStringId,
+ "An identifier for a string in a `LineStringTable`."
+);
+
+define_string_table!(
+ LineStringTable,
+ LineStringId,
+ DebugLineStr,
+ DebugLineStrOffsets,
+ "A table of strings that will be stored in a `.debug_line_str` section."
+);
+
+define_section!(
+ DebugLineStr,
+ DebugLineStrOffset,
+ "A writable `.debug_line_str` section."
+);
+
+define_offsets!(
+ DebugLineStrOffsets: LineStringId => DebugLineStrOffset,
+ "The section offsets of all strings within a `.debug_line_str` section."
+);
+
+#[cfg(test)]
+#[cfg(feature = "read")]
+mod tests {
+ use super::*;
+ use crate::read;
+ use crate::write::EndianVec;
+ use crate::LittleEndian;
+
+ #[test]
+ fn test_string_table() {
+ let mut strings = StringTable::default();
+ assert_eq!(strings.count(), 0);
+ let id1 = strings.add(&b"one"[..]);
+ let id2 = strings.add(&b"two"[..]);
+ assert_eq!(strings.add(&b"one"[..]), id1);
+ assert_eq!(strings.add(&b"two"[..]), id2);
+ assert_eq!(strings.get(id1), &b"one"[..]);
+ assert_eq!(strings.get(id2), &b"two"[..]);
+ assert_eq!(strings.count(), 2);
+
+ let mut debug_str = DebugStr::from(EndianVec::new(LittleEndian));
+ let offsets = strings.write(&mut debug_str).unwrap();
+ assert_eq!(debug_str.slice(), b"one\0two\0");
+ assert_eq!(offsets.get(id1), DebugStrOffset(0));
+ assert_eq!(offsets.get(id2), DebugStrOffset(4));
+ assert_eq!(offsets.count(), 2);
+ }
+
+ #[test]
+ fn test_string_table_read() {
+ let mut strings = StringTable::default();
+ let id1 = strings.add(&b"one"[..]);
+ let id2 = strings.add(&b"two"[..]);
+
+ let mut debug_str = DebugStr::from(EndianVec::new(LittleEndian));
+ let offsets = strings.write(&mut debug_str).unwrap();
+
+ let read_debug_str = read::DebugStr::new(debug_str.slice(), LittleEndian);
+ let str1 = read_debug_str.get_str(offsets.get(id1)).unwrap();
+ let str2 = read_debug_str.get_str(offsets.get(id2)).unwrap();
+ assert_eq!(str1.slice(), &b"one"[..]);
+ assert_eq!(str2.slice(), &b"two"[..]);
+ }
+}
diff --git a/vendor/gimli-0.26.2/src/write/unit.rs b/vendor/gimli-0.26.2/src/write/unit.rs
new file mode 100644
index 000000000..bf85ff421
--- /dev/null
+++ b/vendor/gimli-0.26.2/src/write/unit.rs
@@ -0,0 +1,3157 @@
+use alloc::vec::Vec;
+use std::ops::{Deref, DerefMut};
+use std::{slice, usize};
+
+use crate::common::{
+ DebugAbbrevOffset, DebugInfoOffset, DebugLineOffset, DebugMacinfoOffset, DebugMacroOffset,
+ DebugStrOffset, DebugTypeSignature, DwoId, Encoding, Format, SectionId,
+};
+use crate::constants;
+use crate::leb128::write::{sleb128_size, uleb128_size};
+use crate::write::{
+ Abbreviation, AbbreviationTable, Address, AttributeSpecification, BaseId, DebugLineStrOffsets,
+ DebugStrOffsets, Error, Expression, FileId, LineProgram, LineStringId, LocationListId,
+ LocationListOffsets, LocationListTable, RangeListId, RangeListOffsets, RangeListTable,
+ Reference, Result, Section, Sections, StringId, Writer,
+};
+
+define_id!(UnitId, "An identifier for a unit in a `UnitTable`.");
+
+define_id!(UnitEntryId, "An identifier for an entry in a `Unit`.");
+
+/// A table of units that will be stored in the `.debug_info` section.
+#[derive(Debug, Default)]
+pub struct UnitTable {
+ base_id: BaseId,
+ units: Vec<Unit>,
+}
+
+impl UnitTable {
+ /// Create a new unit and add it to the table.
+ ///
+ /// `address_size` must be in bytes.
+ ///
+ /// Returns the `UnitId` of the new unit.
+ #[inline]
+ pub fn add(&mut self, unit: Unit) -> UnitId {
+ let id = UnitId::new(self.base_id, self.units.len());
+ self.units.push(unit);
+ id
+ }
+
+ /// Return the number of units.
+ #[inline]
+ pub fn count(&self) -> usize {
+ self.units.len()
+ }
+
+ /// Return the id of a unit.
+ ///
+ /// # Panics
+ ///
+ /// Panics if `index >= self.count()`.
+ #[inline]
+ pub fn id(&self, index: usize) -> UnitId {
+ assert!(index < self.count());
+ UnitId::new(self.base_id, index)
+ }
+
+ /// Get a reference to a unit.
+ ///
+ /// # Panics
+ ///
+ /// Panics if `id` is invalid.
+ #[inline]
+ pub fn get(&self, id: UnitId) -> &Unit {
+ debug_assert_eq!(self.base_id, id.base_id);
+ &self.units[id.index]
+ }
+
+ /// Get a mutable reference to a unit.
+ ///
+ /// # Panics
+ ///
+ /// Panics if `id` is invalid.
+ #[inline]
+ pub fn get_mut(&mut self, id: UnitId) -> &mut Unit {
+ debug_assert_eq!(self.base_id, id.base_id);
+ &mut self.units[id.index]
+ }
+
+ /// Write the units to the given sections.
+ ///
+ /// `strings` must contain the `.debug_str` offsets of the corresponding
+ /// `StringTable`.
+ pub fn write<W: Writer>(
+ &mut self,
+ sections: &mut Sections<W>,
+ line_strings: &DebugLineStrOffsets,
+ strings: &DebugStrOffsets,
+ ) -> Result<DebugInfoOffsets> {
+ let mut offsets = DebugInfoOffsets {
+ base_id: self.base_id,
+ units: Vec::new(),
+ };
+ for unit in &mut self.units {
+ // TODO: maybe share abbreviation tables
+ let abbrev_offset = sections.debug_abbrev.offset();
+ let mut abbrevs = AbbreviationTable::default();
+
+ offsets.units.push(unit.write(
+ sections,
+ abbrev_offset,
+ &mut abbrevs,
+ line_strings,
+ strings,
+ )?);
+
+ abbrevs.write(&mut sections.debug_abbrev)?;
+ }
+
+ write_section_refs(
+ &mut sections.debug_info_refs,
+ &mut sections.debug_info.0,
+ &offsets,
+ )?;
+ write_section_refs(
+ &mut sections.debug_loc_refs,
+ &mut sections.debug_loc.0,
+ &offsets,
+ )?;
+ write_section_refs(
+ &mut sections.debug_loclists_refs,
+ &mut sections.debug_loclists.0,
+ &offsets,
+ )?;
+
+ Ok(offsets)
+ }
+}
+
+fn write_section_refs<W: Writer>(
+ references: &mut Vec<DebugInfoReference>,
+ w: &mut W,
+ offsets: &DebugInfoOffsets,
+) -> Result<()> {
+ for r in references.drain(..) {
+ let entry_offset = offsets.entry(r.unit, r.entry).0;
+ debug_assert_ne!(entry_offset, 0);
+ w.write_offset_at(r.offset, entry_offset, SectionId::DebugInfo, r.size)?;
+ }
+ Ok(())
+}
+
+/// A unit's debugging information.
+#[derive(Debug)]
+pub struct Unit {
+ base_id: BaseId,
+ /// The encoding parameters for this unit.
+ encoding: Encoding,
+ /// The line number program for this unit.
+ pub line_program: LineProgram,
+ /// A table of range lists used by this unit.
+ pub ranges: RangeListTable,
+ /// A table of location lists used by this unit.
+ pub locations: LocationListTable,
+ /// All entries in this unit. The order is unrelated to the tree order.
+ // Requirements:
+ // - entries form a tree
+ // - entries can be added in any order
+ // - entries have a fixed id
+ // - able to quickly lookup an entry from its id
+ // Limitations of current implemention:
+ // - mutable iteration of children is messy due to borrow checker
+ entries: Vec<DebuggingInformationEntry>,
+ /// The index of the root entry in entries.
+ root: UnitEntryId,
+}
+
+impl Unit {
+ /// Create a new `Unit`.
+ pub fn new(encoding: Encoding, line_program: LineProgram) -> Self {
+ let base_id = BaseId::default();
+ let ranges = RangeListTable::default();
+ let locations = LocationListTable::default();
+ let mut entries = Vec::new();
+ let root = DebuggingInformationEntry::new(
+ base_id,
+ &mut entries,
+ None,
+ constants::DW_TAG_compile_unit,
+ );
+ Unit {
+ base_id,
+ encoding,
+ line_program,
+ ranges,
+ locations,
+ entries,
+ root,
+ }
+ }
+
+ /// Return the encoding parameters for this unit.
+ #[inline]
+ pub fn encoding(&self) -> Encoding {
+ self.encoding
+ }
+
+ /// Return the DWARF version for this unit.
+ #[inline]
+ pub fn version(&self) -> u16 {
+ self.encoding.version
+ }
+
+ /// Return the address size in bytes for this unit.
+ #[inline]
+ pub fn address_size(&self) -> u8 {
+ self.encoding.address_size
+ }
+
+ /// Return the DWARF format for this unit.
+ #[inline]
+ pub fn format(&self) -> Format {
+ self.encoding.format
+ }
+
+ /// Return the number of `DebuggingInformationEntry`s created for this unit.
+ ///
+ /// This includes entries that no longer have a parent.
+ #[inline]
+ pub fn count(&self) -> usize {
+ self.entries.len()
+ }
+
+ /// Return the id of the root entry.
+ #[inline]
+ pub fn root(&self) -> UnitEntryId {
+ self.root
+ }
+
+ /// Add a new `DebuggingInformationEntry` to this unit and return its id.
+ ///
+ /// The `parent` must be within the same unit.
+ ///
+ /// # Panics
+ ///
+ /// Panics if `parent` is invalid.
+ #[inline]
+ pub fn add(&mut self, parent: UnitEntryId, tag: constants::DwTag) -> UnitEntryId {
+ debug_assert_eq!(self.base_id, parent.base_id);
+ DebuggingInformationEntry::new(self.base_id, &mut self.entries, Some(parent), tag)
+ }
+
+ /// Get a reference to an entry.
+ ///
+ /// # Panics
+ ///
+ /// Panics if `id` is invalid.
+ #[inline]
+ pub fn get(&self, id: UnitEntryId) -> &DebuggingInformationEntry {
+ debug_assert_eq!(self.base_id, id.base_id);
+ &self.entries[id.index]
+ }
+
+ /// Get a mutable reference to an entry.
+ ///
+ /// # Panics
+ ///
+ /// Panics if `id` is invalid.
+ #[inline]
+ pub fn get_mut(&mut self, id: UnitEntryId) -> &mut DebuggingInformationEntry {
+ debug_assert_eq!(self.base_id, id.base_id);
+ &mut self.entries[id.index]
+ }
+
+ /// Return true if `self.line_program` is used by a DIE.
+ fn line_program_in_use(&self) -> bool {
+ if self.line_program.is_none() {
+ return false;
+ }
+ if !self.line_program.is_empty() {
+ return true;
+ }
+
+ for entry in &self.entries {
+ for attr in &entry.attrs {
+ if let AttributeValue::FileIndex(Some(_)) = attr.value {
+ return true;
+ }
+ }
+ }
+
+ false
+ }
+
+ /// Write the unit to the given sections.
+ pub(crate) fn write<W: Writer>(
+ &mut self,
+ sections: &mut Sections<W>,
+ abbrev_offset: DebugAbbrevOffset,
+ abbrevs: &mut AbbreviationTable,
+ line_strings: &DebugLineStrOffsets,
+ strings: &DebugStrOffsets,
+ ) -> Result<UnitOffsets> {
+ let line_program = if self.line_program_in_use() {
+ self.entries[self.root.index]
+ .set(constants::DW_AT_stmt_list, AttributeValue::LineProgramRef);
+ Some(self.line_program.write(
+ &mut sections.debug_line,
+ self.encoding,
+ line_strings,
+ strings,
+ )?)
+ } else {
+ self.entries[self.root.index].delete(constants::DW_AT_stmt_list);
+ None
+ };
+
+ // TODO: use .debug_types for type units in DWARF v4.
+ let w = &mut sections.debug_info;
+
+ let mut offsets = UnitOffsets {
+ base_id: self.base_id,
+ unit: w.offset(),
+ // Entries can be written in any order, so create the complete vec now.
+ entries: vec![EntryOffset::none(); self.entries.len()],
+ };
+
+ let length_offset = w.write_initial_length(self.format())?;
+ let length_base = w.len();
+
+ w.write_u16(self.version())?;
+ if 2 <= self.version() && self.version() <= 4 {
+ w.write_offset(
+ abbrev_offset.0,
+ SectionId::DebugAbbrev,
+ self.format().word_size(),
+ )?;
+ w.write_u8(self.address_size())?;
+ } else if self.version() == 5 {
+ w.write_u8(constants::DW_UT_compile.0)?;
+ w.write_u8(self.address_size())?;
+ w.write_offset(
+ abbrev_offset.0,
+ SectionId::DebugAbbrev,
+ self.format().word_size(),
+ )?;
+ } else {
+ return Err(Error::UnsupportedVersion(self.version()));
+ }
+
+ // Calculate all DIE offsets, so that we are able to output references to them.
+ // However, references to base types in expressions use ULEB128, so base types
+ // must be moved to the front before we can calculate offsets.
+ self.reorder_base_types();
+ let mut offset = w.len();
+ self.entries[self.root.index].calculate_offsets(
+ self,
+ &mut offset,
+ &mut offsets,
+ abbrevs,
+ )?;
+
+ let range_lists = self.ranges.write(sections, self.encoding)?;
+ // Location lists can't be written until we have DIE offsets.
+ let loc_lists = self
+ .locations
+ .write(sections, self.encoding, Some(&offsets))?;
+
+ let w = &mut sections.debug_info;
+ let mut unit_refs = Vec::new();
+ self.entries[self.root.index].write(
+ w,
+ &mut sections.debug_info_refs,
+ &mut unit_refs,
+ self,
+ &mut offsets,
+ abbrevs,
+ line_program,
+ line_strings,
+ strings,
+ &range_lists,
+ &loc_lists,
+ )?;
+
+ let length = (w.len() - length_base) as u64;
+ w.write_initial_length_at(length_offset, length, self.format())?;
+
+ for (offset, entry) in unit_refs {
+ // This does not need relocation.
+ w.write_udata_at(
+ offset.0,
+ offsets.unit_offset(entry),
+ self.format().word_size(),
+ )?;
+ }
+
+ Ok(offsets)
+ }
+
+ /// Reorder base types to come first so that typed stack operations
+ /// can get their offset.
+ fn reorder_base_types(&mut self) {
+ let root = &self.entries[self.root.index];
+ let mut root_children = Vec::with_capacity(root.children.len());
+ for entry in &root.children {
+ if self.entries[entry.index].tag == constants::DW_TAG_base_type {
+ root_children.push(*entry);
+ }
+ }
+ for entry in &root.children {
+ if self.entries[entry.index].tag != constants::DW_TAG_base_type {
+ root_children.push(*entry);
+ }
+ }
+ self.entries[self.root.index].children = root_children;
+ }
+}
+
+/// A Debugging Information Entry (DIE).
+///
+/// DIEs have a set of attributes and optionally have children DIEs as well.
+///
+/// DIEs form a tree without any cycles. This is enforced by specifying the
+/// parent when creating a DIE, and disallowing changes of parent.
+#[derive(Debug)]
+pub struct DebuggingInformationEntry {
+ id: UnitEntryId,
+ parent: Option<UnitEntryId>,
+ tag: constants::DwTag,
+ /// Whether to emit `DW_AT_sibling`.
+ sibling: bool,
+ attrs: Vec<Attribute>,
+ children: Vec<UnitEntryId>,
+}
+
+impl DebuggingInformationEntry {
+ /// Create a new `DebuggingInformationEntry`.
+ ///
+ /// # Panics
+ ///
+ /// Panics if `parent` is invalid.
+ #[allow(clippy::new_ret_no_self)]
+ fn new(
+ base_id: BaseId,
+ entries: &mut Vec<DebuggingInformationEntry>,
+ parent: Option<UnitEntryId>,
+ tag: constants::DwTag,
+ ) -> UnitEntryId {
+ let id = UnitEntryId::new(base_id, entries.len());
+ entries.push(DebuggingInformationEntry {
+ id,
+ parent,
+ tag,
+ sibling: false,
+ attrs: Vec::new(),
+ children: Vec::new(),
+ });
+ if let Some(parent) = parent {
+ debug_assert_eq!(base_id, parent.base_id);
+ assert_ne!(parent, id);
+ entries[parent.index].children.push(id);
+ }
+ id
+ }
+
+ /// Return the id of this entry.
+ #[inline]
+ pub fn id(&self) -> UnitEntryId {
+ self.id
+ }
+
+ /// Return the parent of this entry.
+ #[inline]
+ pub fn parent(&self) -> Option<UnitEntryId> {
+ self.parent
+ }
+
+ /// Return the tag of this entry.
+ #[inline]
+ pub fn tag(&self) -> constants::DwTag {
+ self.tag
+ }
+
+ /// Return `true` if a `DW_AT_sibling` attribute will be emitted.
+ #[inline]
+ pub fn sibling(&self) -> bool {
+ self.sibling
+ }
+
+ /// Set whether a `DW_AT_sibling` attribute will be emitted.
+ ///
+ /// The attribute will only be emitted if the DIE has children.
+ #[inline]
+ pub fn set_sibling(&mut self, sibling: bool) {
+ self.sibling = sibling;
+ }
+
+ /// Iterate over the attributes of this entry.
+ #[inline]
+ pub fn attrs(&self) -> slice::Iter<Attribute> {
+ self.attrs.iter()
+ }
+
+ /// Iterate over the attributes of this entry for modification.
+ #[inline]
+ pub fn attrs_mut(&mut self) -> slice::IterMut<Attribute> {
+ self.attrs.iter_mut()
+ }
+
+ /// Get an attribute.
+ pub fn get(&self, name: constants::DwAt) -> Option<&AttributeValue> {
+ self.attrs
+ .iter()
+ .find(|attr| attr.name == name)
+ .map(|attr| &attr.value)
+ }
+
+ /// Get an attribute for modification.
+ pub fn get_mut(&mut self, name: constants::DwAt) -> Option<&mut AttributeValue> {
+ self.attrs
+ .iter_mut()
+ .find(|attr| attr.name == name)
+ .map(|attr| &mut attr.value)
+ }
+
+ /// Set an attribute.
+ ///
+ /// Replaces any existing attribute with the same name.
+ ///
+ /// # Panics
+ ///
+ /// Panics if `name` is `DW_AT_sibling`. Use `set_sibling` instead.
+ pub fn set(&mut self, name: constants::DwAt, value: AttributeValue) {
+ assert_ne!(name, constants::DW_AT_sibling);
+ if let Some(attr) = self.attrs.iter_mut().find(|attr| attr.name == name) {
+ attr.value = value;
+ return;
+ }
+ self.attrs.push(Attribute { name, value });
+ }
+
+ /// Delete an attribute.
+ ///
+ /// Replaces any existing attribute with the same name.
+ pub fn delete(&mut self, name: constants::DwAt) {
+ self.attrs.retain(|x| x.name != name);
+ }
+
+ /// Iterate over the children of this entry.
+ ///
+ /// Note: use `Unit::add` to add a new child to this entry.
+ #[inline]
+ pub fn children(&self) -> slice::Iter<UnitEntryId> {
+ self.children.iter()
+ }
+
+ /// Delete a child entry and all of its children.
+ pub fn delete_child(&mut self, id: UnitEntryId) {
+ self.children.retain(|&child| child != id);
+ }
+
+ /// Return the type abbreviation for this DIE.
+ fn abbreviation(&self, encoding: Encoding) -> Result<Abbreviation> {
+ let mut attrs = Vec::new();
+
+ if self.sibling && !self.children.is_empty() {
+ let form = match encoding.format {
+ Format::Dwarf32 => constants::DW_FORM_ref4,
+ Format::Dwarf64 => constants::DW_FORM_ref8,
+ };
+ attrs.push(AttributeSpecification::new(constants::DW_AT_sibling, form));
+ }
+
+ for attr in &self.attrs {
+ attrs.push(attr.specification(encoding)?);
+ }
+
+ Ok(Abbreviation::new(
+ self.tag,
+ !self.children.is_empty(),
+ attrs,
+ ))
+ }
+
+ fn calculate_offsets(
+ &self,
+ unit: &Unit,
+ offset: &mut usize,
+ offsets: &mut UnitOffsets,
+ abbrevs: &mut AbbreviationTable,
+ ) -> Result<()> {
+ offsets.entries[self.id.index].offset = DebugInfoOffset(*offset);
+ offsets.entries[self.id.index].abbrev = abbrevs.add(self.abbreviation(unit.encoding())?);
+ *offset += self.size(unit, offsets);
+ if !self.children.is_empty() {
+ for child in &self.children {
+ unit.entries[child.index].calculate_offsets(unit, offset, offsets, abbrevs)?;
+ }
+ // Null child
+ *offset += 1;
+ }
+ Ok(())
+ }
+
+ fn size(&self, unit: &Unit, offsets: &UnitOffsets) -> usize {
+ let mut size = uleb128_size(offsets.abbrev(self.id));
+ if self.sibling && !self.children.is_empty() {
+ size += unit.format().word_size() as usize;
+ }
+ for attr in &self.attrs {
+ size += attr.value.size(unit, offsets);
+ }
+ size
+ }
+
+ /// Write the entry to the given sections.
+ #[allow(clippy::too_many_arguments)]
+ fn write<W: Writer>(
+ &self,
+ w: &mut DebugInfo<W>,
+ debug_info_refs: &mut Vec<DebugInfoReference>,
+ unit_refs: &mut Vec<(DebugInfoOffset, UnitEntryId)>,
+ unit: &Unit,
+ offsets: &mut UnitOffsets,
+ abbrevs: &mut AbbreviationTable,
+ line_program: Option<DebugLineOffset>,
+ line_strings: &DebugLineStrOffsets,
+ strings: &DebugStrOffsets,
+ range_lists: &RangeListOffsets,
+ loc_lists: &LocationListOffsets,
+ ) -> Result<()> {
+ debug_assert_eq!(offsets.debug_info_offset(self.id), w.offset());
+ w.write_uleb128(offsets.abbrev(self.id))?;
+
+ let sibling_offset = if self.sibling && !self.children.is_empty() {
+ let offset = w.offset();
+ w.write_udata(0, unit.format().word_size())?;
+ Some(offset)
+ } else {
+ None
+ };
+
+ for attr in &self.attrs {
+ attr.value.write(
+ w,
+ debug_info_refs,
+ unit_refs,
+ unit,
+ offsets,
+ line_program,
+ line_strings,
+ strings,
+ range_lists,
+ loc_lists,
+ )?;
+ }
+
+ if !self.children.is_empty() {
+ for child in &self.children {
+ unit.entries[child.index].write(
+ w,
+ debug_info_refs,
+ unit_refs,
+ unit,
+ offsets,
+ abbrevs,
+ line_program,
+ line_strings,
+ strings,
+ range_lists,
+ loc_lists,
+ )?;
+ }
+ // Null child
+ w.write_u8(0)?;
+ }
+
+ if let Some(offset) = sibling_offset {
+ let next_offset = (w.offset().0 - offsets.unit.0) as u64;
+ // This does not need relocation.
+ w.write_udata_at(offset.0, next_offset, unit.format().word_size())?;
+ }
+ Ok(())
+ }
+}
+
+/// An attribute in a `DebuggingInformationEntry`, consisting of a name and
+/// associated value.
+#[derive(Debug, Clone, PartialEq, Eq)]
+pub struct Attribute {
+ name: constants::DwAt,
+ value: AttributeValue,
+}
+
+impl Attribute {
+ /// Get the name of this attribute.
+ #[inline]
+ pub fn name(&self) -> constants::DwAt {
+ self.name
+ }
+
+ /// Get the value of this attribute.
+ #[inline]
+ pub fn get(&self) -> &AttributeValue {
+ &self.value
+ }
+
+ /// Set the value of this attribute.
+ #[inline]
+ pub fn set(&mut self, value: AttributeValue) {
+ self.value = value;
+ }
+
+ /// Return the type specification for this attribute.
+ fn specification(&self, encoding: Encoding) -> Result<AttributeSpecification> {
+ Ok(AttributeSpecification::new(
+ self.name,
+ self.value.form(encoding)?,
+ ))
+ }
+}
+
+/// The value of an attribute in a `DebuggingInformationEntry`.
+#[derive(Debug, Clone, PartialEq, Eq)]
+pub enum AttributeValue {
+ /// "Refers to some location in the address space of the described program."
+ Address(Address),
+
+ /// A slice of an arbitrary number of bytes.
+ Block(Vec<u8>),
+
+ /// A one byte constant data value. How to interpret the byte depends on context.
+ ///
+ /// From section 7 of the standard: "Depending on context, it may be a
+ /// signed integer, an unsigned integer, a floating-point constant, or
+ /// anything else."
+ Data1(u8),
+
+ /// A two byte constant data value. How to interpret the bytes depends on context.
+ ///
+ /// This value will be converted to the target endian before writing.
+ ///
+ /// From section 7 of the standard: "Depending on context, it may be a
+ /// signed integer, an unsigned integer, a floating-point constant, or
+ /// anything else."
+ Data2(u16),
+
+ /// A four byte constant data value. How to interpret the bytes depends on context.
+ ///
+ /// This value will be converted to the target endian before writing.
+ ///
+ /// From section 7 of the standard: "Depending on context, it may be a
+ /// signed integer, an unsigned integer, a floating-point constant, or
+ /// anything else."
+ Data4(u32),
+
+ /// An eight byte constant data value. How to interpret the bytes depends on context.
+ ///
+ /// This value will be converted to the target endian before writing.
+ ///
+ /// From section 7 of the standard: "Depending on context, it may be a
+ /// signed integer, an unsigned integer, a floating-point constant, or
+ /// anything else."
+ Data8(u64),
+
+ /// A signed integer constant.
+ Sdata(i64),
+
+ /// An unsigned integer constant.
+ Udata(u64),
+
+ /// "The information bytes contain a DWARF expression (see Section 2.5) or
+ /// location description (see Section 2.6)."
+ Exprloc(Expression),
+
+ /// A boolean that indicates presence or absence of the attribute.
+ Flag(bool),
+
+ /// An attribute that is always present.
+ FlagPresent,
+
+ /// A reference to a `DebuggingInformationEntry` in this unit.
+ UnitRef(UnitEntryId),
+
+ /// A reference to a `DebuggingInformationEntry` in a potentially different unit.
+ DebugInfoRef(Reference),
+
+ /// An offset into the `.debug_info` section of the supplementary object file.
+ ///
+ /// The API does not currently assist with generating this offset.
+ /// This variant will be removed from the API once support for writing
+ /// supplementary object files is implemented.
+ DebugInfoRefSup(DebugInfoOffset),
+
+ /// A reference to a line number program.
+ LineProgramRef,
+
+ /// A reference to a location list.
+ LocationListRef(LocationListId),
+
+ /// An offset into the `.debug_macinfo` section.
+ ///
+ /// The API does not currently assist with generating this offset.
+ /// This variant will be removed from the API once support for writing
+ /// `.debug_macinfo` sections is implemented.
+ DebugMacinfoRef(DebugMacinfoOffset),
+
+ /// An offset into the `.debug_macro` section.
+ ///
+ /// The API does not currently assist with generating this offset.
+ /// This variant will be removed from the API once support for writing
+ /// `.debug_macro` sections is implemented.
+ DebugMacroRef(DebugMacroOffset),
+
+ /// A reference to a range list.
+ RangeListRef(RangeListId),
+
+ /// A type signature.
+ ///
+ /// The API does not currently assist with generating this signature.
+ /// This variant will be removed from the API once support for writing
+ /// `.debug_types` sections is implemented.
+ DebugTypesRef(DebugTypeSignature),
+
+ /// A reference to a string in the `.debug_str` section.
+ StringRef(StringId),
+
+ /// An offset into the `.debug_str` section of the supplementary object file.
+ ///
+ /// The API does not currently assist with generating this offset.
+ /// This variant will be removed from the API once support for writing
+ /// supplementary object files is implemented.
+ DebugStrRefSup(DebugStrOffset),
+
+ /// A reference to a string in the `.debug_line_str` section.
+ LineStringRef(LineStringId),
+
+ /// A slice of bytes representing a string. Must not include null bytes.
+ /// Not guaranteed to be UTF-8 or anything like that.
+ String(Vec<u8>),
+
+ /// The value of a `DW_AT_encoding` attribute.
+ Encoding(constants::DwAte),
+
+ /// The value of a `DW_AT_decimal_sign` attribute.
+ DecimalSign(constants::DwDs),
+
+ /// The value of a `DW_AT_endianity` attribute.
+ Endianity(constants::DwEnd),
+
+ /// The value of a `DW_AT_accessibility` attribute.
+ Accessibility(constants::DwAccess),
+
+ /// The value of a `DW_AT_visibility` attribute.
+ Visibility(constants::DwVis),
+
+ /// The value of a `DW_AT_virtuality` attribute.
+ Virtuality(constants::DwVirtuality),
+
+ /// The value of a `DW_AT_language` attribute.
+ Language(constants::DwLang),
+
+ /// The value of a `DW_AT_address_class` attribute.
+ AddressClass(constants::DwAddr),
+
+ /// The value of a `DW_AT_identifier_case` attribute.
+ IdentifierCase(constants::DwId),
+
+ /// The value of a `DW_AT_calling_convention` attribute.
+ CallingConvention(constants::DwCc),
+
+ /// The value of a `DW_AT_inline` attribute.
+ Inline(constants::DwInl),
+
+ /// The value of a `DW_AT_ordering` attribute.
+ Ordering(constants::DwOrd),
+
+ /// An index into the filename entries from the line number information
+ /// table for the unit containing this value.
+ FileIndex(Option<FileId>),
+}
+
+impl AttributeValue {
+ /// Return the form that will be used to encode this value.
+ pub fn form(&self, encoding: Encoding) -> Result<constants::DwForm> {
+ // TODO: missing forms:
+ // - DW_FORM_indirect
+ // - DW_FORM_implicit_const
+ // - FW_FORM_block1/block2/block4
+ // - DW_FORM_str/strx1/strx2/strx3/strx4
+ // - DW_FORM_addrx/addrx1/addrx2/addrx3/addrx4
+ // - DW_FORM_data16
+ // - DW_FORM_line_strp
+ // - DW_FORM_loclistx
+ // - DW_FORM_rnglistx
+ let form = match *self {
+ AttributeValue::Address(_) => constants::DW_FORM_addr,
+ AttributeValue::Block(_) => constants::DW_FORM_block,
+ AttributeValue::Data1(_) => constants::DW_FORM_data1,
+ AttributeValue::Data2(_) => constants::DW_FORM_data2,
+ AttributeValue::Data4(_) => constants::DW_FORM_data4,
+ AttributeValue::Data8(_) => constants::DW_FORM_data8,
+ AttributeValue::Exprloc(_) => constants::DW_FORM_exprloc,
+ AttributeValue::Flag(_) => constants::DW_FORM_flag,
+ AttributeValue::FlagPresent => constants::DW_FORM_flag_present,
+ AttributeValue::UnitRef(_) => {
+ // Using a fixed size format lets us write a placeholder before we know
+ // the value.
+ match encoding.format {
+ Format::Dwarf32 => constants::DW_FORM_ref4,
+ Format::Dwarf64 => constants::DW_FORM_ref8,
+ }
+ }
+ AttributeValue::DebugInfoRef(_) => constants::DW_FORM_ref_addr,
+ AttributeValue::DebugInfoRefSup(_) => {
+ // TODO: should this depend on the size of supplementary section?
+ match encoding.format {
+ Format::Dwarf32 => constants::DW_FORM_ref_sup4,
+ Format::Dwarf64 => constants::DW_FORM_ref_sup8,
+ }
+ }
+ AttributeValue::LineProgramRef
+ | AttributeValue::LocationListRef(_)
+ | AttributeValue::DebugMacinfoRef(_)
+ | AttributeValue::DebugMacroRef(_)
+ | AttributeValue::RangeListRef(_) => {
+ if encoding.version == 2 || encoding.version == 3 {
+ match encoding.format {
+ Format::Dwarf32 => constants::DW_FORM_data4,
+ Format::Dwarf64 => constants::DW_FORM_data8,
+ }
+ } else {
+ constants::DW_FORM_sec_offset
+ }
+ }
+ AttributeValue::DebugTypesRef(_) => constants::DW_FORM_ref_sig8,
+ AttributeValue::StringRef(_) => constants::DW_FORM_strp,
+ AttributeValue::DebugStrRefSup(_) => constants::DW_FORM_strp_sup,
+ AttributeValue::LineStringRef(_) => constants::DW_FORM_line_strp,
+ AttributeValue::String(_) => constants::DW_FORM_string,
+ AttributeValue::Encoding(_)
+ | AttributeValue::DecimalSign(_)
+ | AttributeValue::Endianity(_)
+ | AttributeValue::Accessibility(_)
+ | AttributeValue::Visibility(_)
+ | AttributeValue::Virtuality(_)
+ | AttributeValue::Language(_)
+ | AttributeValue::AddressClass(_)
+ | AttributeValue::IdentifierCase(_)
+ | AttributeValue::CallingConvention(_)
+ | AttributeValue::Inline(_)
+ | AttributeValue::Ordering(_)
+ | AttributeValue::FileIndex(_)
+ | AttributeValue::Udata(_) => constants::DW_FORM_udata,
+ AttributeValue::Sdata(_) => constants::DW_FORM_sdata,
+ };
+ Ok(form)
+ }
+
+ fn size(&self, unit: &Unit, offsets: &UnitOffsets) -> usize {
+ macro_rules! debug_assert_form {
+ ($form:expr) => {
+ debug_assert_eq!(self.form(unit.encoding()).unwrap(), $form)
+ };
+ }
+ match *self {
+ AttributeValue::Address(_) => {
+ debug_assert_form!(constants::DW_FORM_addr);
+ unit.address_size() as usize
+ }
+ AttributeValue::Block(ref val) => {
+ debug_assert_form!(constants::DW_FORM_block);
+ uleb128_size(val.len() as u64) + val.len()
+ }
+ AttributeValue::Data1(_) => {
+ debug_assert_form!(constants::DW_FORM_data1);
+ 1
+ }
+ AttributeValue::Data2(_) => {
+ debug_assert_form!(constants::DW_FORM_data2);
+ 2
+ }
+ AttributeValue::Data4(_) => {
+ debug_assert_form!(constants::DW_FORM_data4);
+ 4
+ }
+ AttributeValue::Data8(_) => {
+ debug_assert_form!(constants::DW_FORM_data8);
+ 8
+ }
+ AttributeValue::Sdata(val) => {
+ debug_assert_form!(constants::DW_FORM_sdata);
+ sleb128_size(val)
+ }
+ AttributeValue::Udata(val) => {
+ debug_assert_form!(constants::DW_FORM_udata);
+ uleb128_size(val)
+ }
+ AttributeValue::Exprloc(ref val) => {
+ debug_assert_form!(constants::DW_FORM_exprloc);
+ let size = val.size(unit.encoding(), Some(offsets));
+ uleb128_size(size as u64) + size
+ }
+ AttributeValue::Flag(_) => {
+ debug_assert_form!(constants::DW_FORM_flag);
+ 1
+ }
+ AttributeValue::FlagPresent => {
+ debug_assert_form!(constants::DW_FORM_flag_present);
+ 0
+ }
+ AttributeValue::UnitRef(_) => {
+ match unit.format() {
+ Format::Dwarf32 => debug_assert_form!(constants::DW_FORM_ref4),
+ Format::Dwarf64 => debug_assert_form!(constants::DW_FORM_ref8),
+ }
+ unit.format().word_size() as usize
+ }
+ AttributeValue::DebugInfoRef(_) => {
+ debug_assert_form!(constants::DW_FORM_ref_addr);
+ if unit.version() == 2 {
+ unit.address_size() as usize
+ } else {
+ unit.format().word_size() as usize
+ }
+ }
+ AttributeValue::DebugInfoRefSup(_) => {
+ match unit.format() {
+ Format::Dwarf32 => debug_assert_form!(constants::DW_FORM_ref_sup4),
+ Format::Dwarf64 => debug_assert_form!(constants::DW_FORM_ref_sup8),
+ }
+ unit.format().word_size() as usize
+ }
+ AttributeValue::LineProgramRef => {
+ if unit.version() >= 4 {
+ debug_assert_form!(constants::DW_FORM_sec_offset);
+ }
+ unit.format().word_size() as usize
+ }
+ AttributeValue::LocationListRef(_) => {
+ if unit.version() >= 4 {
+ debug_assert_form!(constants::DW_FORM_sec_offset);
+ }
+ unit.format().word_size() as usize
+ }
+ AttributeValue::DebugMacinfoRef(_) => {
+ if unit.version() >= 4 {
+ debug_assert_form!(constants::DW_FORM_sec_offset);
+ }
+ unit.format().word_size() as usize
+ }
+ AttributeValue::DebugMacroRef(_) => {
+ if unit.version() >= 4 {
+ debug_assert_form!(constants::DW_FORM_sec_offset);
+ }
+ unit.format().word_size() as usize
+ }
+ AttributeValue::RangeListRef(_) => {
+ if unit.version() >= 4 {
+ debug_assert_form!(constants::DW_FORM_sec_offset);
+ }
+ unit.format().word_size() as usize
+ }
+ AttributeValue::DebugTypesRef(_) => {
+ debug_assert_form!(constants::DW_FORM_ref_sig8);
+ 8
+ }
+ AttributeValue::StringRef(_) => {
+ debug_assert_form!(constants::DW_FORM_strp);
+ unit.format().word_size() as usize
+ }
+ AttributeValue::DebugStrRefSup(_) => {
+ debug_assert_form!(constants::DW_FORM_strp_sup);
+ unit.format().word_size() as usize
+ }
+ AttributeValue::LineStringRef(_) => {
+ debug_assert_form!(constants::DW_FORM_line_strp);
+ unit.format().word_size() as usize
+ }
+ AttributeValue::String(ref val) => {
+ debug_assert_form!(constants::DW_FORM_string);
+ val.len() + 1
+ }
+ AttributeValue::Encoding(val) => {
+ debug_assert_form!(constants::DW_FORM_udata);
+ uleb128_size(val.0 as u64)
+ }
+ AttributeValue::DecimalSign(val) => {
+ debug_assert_form!(constants::DW_FORM_udata);
+ uleb128_size(val.0 as u64)
+ }
+ AttributeValue::Endianity(val) => {
+ debug_assert_form!(constants::DW_FORM_udata);
+ uleb128_size(val.0 as u64)
+ }
+ AttributeValue::Accessibility(val) => {
+ debug_assert_form!(constants::DW_FORM_udata);
+ uleb128_size(val.0 as u64)
+ }
+ AttributeValue::Visibility(val) => {
+ debug_assert_form!(constants::DW_FORM_udata);
+ uleb128_size(val.0 as u64)
+ }
+ AttributeValue::Virtuality(val) => {
+ debug_assert_form!(constants::DW_FORM_udata);
+ uleb128_size(val.0 as u64)
+ }
+ AttributeValue::Language(val) => {
+ debug_assert_form!(constants::DW_FORM_udata);
+ uleb128_size(val.0 as u64)
+ }
+ AttributeValue::AddressClass(val) => {
+ debug_assert_form!(constants::DW_FORM_udata);
+ uleb128_size(val.0 as u64)
+ }
+ AttributeValue::IdentifierCase(val) => {
+ debug_assert_form!(constants::DW_FORM_udata);
+ uleb128_size(val.0 as u64)
+ }
+ AttributeValue::CallingConvention(val) => {
+ debug_assert_form!(constants::DW_FORM_udata);
+ uleb128_size(val.0 as u64)
+ }
+ AttributeValue::Inline(val) => {
+ debug_assert_form!(constants::DW_FORM_udata);
+ uleb128_size(val.0 as u64)
+ }
+ AttributeValue::Ordering(val) => {
+ debug_assert_form!(constants::DW_FORM_udata);
+ uleb128_size(val.0 as u64)
+ }
+ AttributeValue::FileIndex(val) => {
+ debug_assert_form!(constants::DW_FORM_udata);
+ uleb128_size(val.map(FileId::raw).unwrap_or(0))
+ }
+ }
+ }
+
+ /// Write the attribute value to the given sections.
+ #[allow(clippy::cyclomatic_complexity, clippy::too_many_arguments)]
+ fn write<W: Writer>(
+ &self,
+ w: &mut DebugInfo<W>,
+ debug_info_refs: &mut Vec<DebugInfoReference>,
+ unit_refs: &mut Vec<(DebugInfoOffset, UnitEntryId)>,
+ unit: &Unit,
+ offsets: &UnitOffsets,
+ line_program: Option<DebugLineOffset>,
+ line_strings: &DebugLineStrOffsets,
+ strings: &DebugStrOffsets,
+ range_lists: &RangeListOffsets,
+ loc_lists: &LocationListOffsets,
+ ) -> Result<()> {
+ macro_rules! debug_assert_form {
+ ($form:expr) => {
+ debug_assert_eq!(self.form(unit.encoding()).unwrap(), $form)
+ };
+ }
+ match *self {
+ AttributeValue::Address(val) => {
+ debug_assert_form!(constants::DW_FORM_addr);
+ w.write_address(val, unit.address_size())?;
+ }
+ AttributeValue::Block(ref val) => {
+ debug_assert_form!(constants::DW_FORM_block);
+ w.write_uleb128(val.len() as u64)?;
+ w.write(&val)?;
+ }
+ AttributeValue::Data1(val) => {
+ debug_assert_form!(constants::DW_FORM_data1);
+ w.write_u8(val)?;
+ }
+ AttributeValue::Data2(val) => {
+ debug_assert_form!(constants::DW_FORM_data2);
+ w.write_u16(val)?;
+ }
+ AttributeValue::Data4(val) => {
+ debug_assert_form!(constants::DW_FORM_data4);
+ w.write_u32(val)?;
+ }
+ AttributeValue::Data8(val) => {
+ debug_assert_form!(constants::DW_FORM_data8);
+ w.write_u64(val)?;
+ }
+ AttributeValue::Sdata(val) => {
+ debug_assert_form!(constants::DW_FORM_sdata);
+ w.write_sleb128(val)?;
+ }
+ AttributeValue::Udata(val) => {
+ debug_assert_form!(constants::DW_FORM_udata);
+ w.write_uleb128(val)?;
+ }
+ AttributeValue::Exprloc(ref val) => {
+ debug_assert_form!(constants::DW_FORM_exprloc);
+ w.write_uleb128(val.size(unit.encoding(), Some(offsets)) as u64)?;
+ val.write(
+ &mut w.0,
+ Some(debug_info_refs),
+ unit.encoding(),
+ Some(offsets),
+ )?;
+ }
+ AttributeValue::Flag(val) => {
+ debug_assert_form!(constants::DW_FORM_flag);
+ w.write_u8(val as u8)?;
+ }
+ AttributeValue::FlagPresent => {
+ debug_assert_form!(constants::DW_FORM_flag_present);
+ }
+ AttributeValue::UnitRef(id) => {
+ match unit.format() {
+ Format::Dwarf32 => debug_assert_form!(constants::DW_FORM_ref4),
+ Format::Dwarf64 => debug_assert_form!(constants::DW_FORM_ref8),
+ }
+ unit_refs.push((w.offset(), id));
+ w.write_udata(0, unit.format().word_size())?;
+ }
+ AttributeValue::DebugInfoRef(reference) => {
+ debug_assert_form!(constants::DW_FORM_ref_addr);
+ let size = if unit.version() == 2 {
+ unit.address_size()
+ } else {
+ unit.format().word_size()
+ };
+ match reference {
+ Reference::Symbol(symbol) => w.write_reference(symbol, size)?,
+ Reference::Entry(unit, entry) => {
+ debug_info_refs.push(DebugInfoReference {
+ offset: w.len(),
+ unit,
+ entry,
+ size,
+ });
+ w.write_udata(0, size)?;
+ }
+ }
+ }
+ AttributeValue::DebugInfoRefSup(val) => {
+ match unit.format() {
+ Format::Dwarf32 => debug_assert_form!(constants::DW_FORM_ref_sup4),
+ Format::Dwarf64 => debug_assert_form!(constants::DW_FORM_ref_sup8),
+ }
+ w.write_udata(val.0 as u64, unit.format().word_size())?;
+ }
+ AttributeValue::LineProgramRef => {
+ if unit.version() >= 4 {
+ debug_assert_form!(constants::DW_FORM_sec_offset);
+ }
+ match line_program {
+ Some(line_program) => {
+ w.write_offset(
+ line_program.0,
+ SectionId::DebugLine,
+ unit.format().word_size(),
+ )?;
+ }
+ None => return Err(Error::InvalidAttributeValue),
+ }
+ }
+ AttributeValue::LocationListRef(val) => {
+ if unit.version() >= 4 {
+ debug_assert_form!(constants::DW_FORM_sec_offset);
+ }
+ let section = if unit.version() <= 4 {
+ SectionId::DebugLoc
+ } else {
+ SectionId::DebugLocLists
+ };
+ w.write_offset(loc_lists.get(val).0, section, unit.format().word_size())?;
+ }
+ AttributeValue::DebugMacinfoRef(val) => {
+ if unit.version() >= 4 {
+ debug_assert_form!(constants::DW_FORM_sec_offset);
+ }
+ w.write_offset(val.0, SectionId::DebugMacinfo, unit.format().word_size())?;
+ }
+ AttributeValue::DebugMacroRef(val) => {
+ if unit.version() >= 4 {
+ debug_assert_form!(constants::DW_FORM_sec_offset);
+ }
+ w.write_offset(val.0, SectionId::DebugMacro, unit.format().word_size())?;
+ }
+ AttributeValue::RangeListRef(val) => {
+ if unit.version() >= 4 {
+ debug_assert_form!(constants::DW_FORM_sec_offset);
+ }
+ let section = if unit.version() <= 4 {
+ SectionId::DebugRanges
+ } else {
+ SectionId::DebugRngLists
+ };
+ w.write_offset(range_lists.get(val).0, section, unit.format().word_size())?;
+ }
+ AttributeValue::DebugTypesRef(val) => {
+ debug_assert_form!(constants::DW_FORM_ref_sig8);
+ w.write_u64(val.0)?;
+ }
+ AttributeValue::StringRef(val) => {
+ debug_assert_form!(constants::DW_FORM_strp);
+ w.write_offset(
+ strings.get(val).0,
+ SectionId::DebugStr,
+ unit.format().word_size(),
+ )?;
+ }
+ AttributeValue::DebugStrRefSup(val) => {
+ debug_assert_form!(constants::DW_FORM_strp_sup);
+ w.write_udata(val.0 as u64, unit.format().word_size())?;
+ }
+ AttributeValue::LineStringRef(val) => {
+ debug_assert_form!(constants::DW_FORM_line_strp);
+ w.write_offset(
+ line_strings.get(val).0,
+ SectionId::DebugLineStr,
+ unit.format().word_size(),
+ )?;
+ }
+ AttributeValue::String(ref val) => {
+ debug_assert_form!(constants::DW_FORM_string);
+ w.write(&val)?;
+ w.write_u8(0)?;
+ }
+ AttributeValue::Encoding(val) => {
+ debug_assert_form!(constants::DW_FORM_udata);
+ w.write_uleb128(u64::from(val.0))?;
+ }
+ AttributeValue::DecimalSign(val) => {
+ debug_assert_form!(constants::DW_FORM_udata);
+ w.write_uleb128(u64::from(val.0))?;
+ }
+ AttributeValue::Endianity(val) => {
+ debug_assert_form!(constants::DW_FORM_udata);
+ w.write_uleb128(u64::from(val.0))?;
+ }
+ AttributeValue::Accessibility(val) => {
+ debug_assert_form!(constants::DW_FORM_udata);
+ w.write_uleb128(u64::from(val.0))?;
+ }
+ AttributeValue::Visibility(val) => {
+ debug_assert_form!(constants::DW_FORM_udata);
+ w.write_uleb128(u64::from(val.0))?;
+ }
+ AttributeValue::Virtuality(val) => {
+ debug_assert_form!(constants::DW_FORM_udata);
+ w.write_uleb128(u64::from(val.0))?;
+ }
+ AttributeValue::Language(val) => {
+ debug_assert_form!(constants::DW_FORM_udata);
+ w.write_uleb128(u64::from(val.0))?;
+ }
+ AttributeValue::AddressClass(val) => {
+ debug_assert_form!(constants::DW_FORM_udata);
+ w.write_uleb128(val.0)?;
+ }
+ AttributeValue::IdentifierCase(val) => {
+ debug_assert_form!(constants::DW_FORM_udata);
+ w.write_uleb128(u64::from(val.0))?;
+ }
+ AttributeValue::CallingConvention(val) => {
+ debug_assert_form!(constants::DW_FORM_udata);
+ w.write_uleb128(u64::from(val.0))?;
+ }
+ AttributeValue::Inline(val) => {
+ debug_assert_form!(constants::DW_FORM_udata);
+ w.write_uleb128(u64::from(val.0))?;
+ }
+ AttributeValue::Ordering(val) => {
+ debug_assert_form!(constants::DW_FORM_udata);
+ w.write_uleb128(u64::from(val.0))?;
+ }
+ AttributeValue::FileIndex(val) => {
+ debug_assert_form!(constants::DW_FORM_udata);
+ w.write_uleb128(val.map(FileId::raw).unwrap_or(0))?;
+ }
+ }
+ Ok(())
+ }
+}
+
+define_section!(
+ DebugInfo,
+ DebugInfoOffset,
+ "A writable `.debug_info` section."
+);
+
+/// The section offsets of all elements within a `.debug_info` section.
+#[derive(Debug, Default)]
+pub struct DebugInfoOffsets {
+ base_id: BaseId,
+ units: Vec<UnitOffsets>,
+}
+
+impl DebugInfoOffsets {
+ #[cfg(test)]
+ pub(crate) fn unit_offsets(&self, unit: UnitId) -> &UnitOffsets {
+ debug_assert_eq!(self.base_id, unit.base_id);
+ &self.units[unit.index]
+ }
+
+ /// Get the `.debug_info` section offset for the given unit.
+ #[inline]
+ pub fn unit(&self, unit: UnitId) -> DebugInfoOffset {
+ debug_assert_eq!(self.base_id, unit.base_id);
+ self.units[unit.index].unit
+ }
+
+ /// Get the `.debug_info` section offset for the given entry.
+ #[inline]
+ pub fn entry(&self, unit: UnitId, entry: UnitEntryId) -> DebugInfoOffset {
+ debug_assert_eq!(self.base_id, unit.base_id);
+ self.units[unit.index].debug_info_offset(entry)
+ }
+}
+
+/// The section offsets of all elements of a unit within a `.debug_info` section.
+#[derive(Debug)]
+pub(crate) struct UnitOffsets {
+ base_id: BaseId,
+ unit: DebugInfoOffset,
+ entries: Vec<EntryOffset>,
+}
+
+impl UnitOffsets {
+ #[cfg(test)]
+ fn none() -> Self {
+ UnitOffsets {
+ base_id: BaseId::default(),
+ unit: DebugInfoOffset(0),
+ entries: Vec::new(),
+ }
+ }
+
+ /// Get the .debug_info offset for the given entry.
+ #[inline]
+ pub(crate) fn debug_info_offset(&self, entry: UnitEntryId) -> DebugInfoOffset {
+ debug_assert_eq!(self.base_id, entry.base_id);
+ let offset = self.entries[entry.index].offset;
+ debug_assert_ne!(offset.0, 0);
+ offset
+ }
+
+ /// Get the unit offset for the given entry.
+ #[inline]
+ pub(crate) fn unit_offset(&self, entry: UnitEntryId) -> u64 {
+ let offset = self.debug_info_offset(entry);
+ (offset.0 - self.unit.0) as u64
+ }
+
+ /// Get the abbreviation code for the given entry.
+ #[inline]
+ pub(crate) fn abbrev(&self, entry: UnitEntryId) -> u64 {
+ debug_assert_eq!(self.base_id, entry.base_id);
+ self.entries[entry.index].abbrev
+ }
+}
+
+#[derive(Debug, Clone, Copy)]
+pub(crate) struct EntryOffset {
+ offset: DebugInfoOffset,
+ abbrev: u64,
+}
+
+impl EntryOffset {
+ fn none() -> Self {
+ EntryOffset {
+ offset: DebugInfoOffset(0),
+ abbrev: 0,
+ }
+ }
+}
+
+/// A reference to a `.debug_info` entry that has yet to be resolved.
+#[derive(Debug, Clone, Copy)]
+pub(crate) struct DebugInfoReference {
+ /// The offset within the section of the reference.
+ pub offset: usize,
+ /// The size of the reference.
+ pub size: u8,
+ /// The unit containing the entry.
+ pub unit: UnitId,
+ /// The entry being referenced.
+ pub entry: UnitEntryId,
+}
+
+#[cfg(feature = "read")]
+pub(crate) mod convert {
+ use super::*;
+ use crate::common::UnitSectionOffset;
+ use crate::read::{self, Reader};
+ use crate::write::{self, ConvertError, ConvertResult, LocationList, RangeList};
+ use std::collections::HashMap;
+
+ pub(crate) struct ConvertUnit<R: Reader<Offset = usize>> {
+ from_unit: read::Unit<R>,
+ base_id: BaseId,
+ encoding: Encoding,
+ entries: Vec<DebuggingInformationEntry>,
+ entry_offsets: Vec<read::UnitOffset>,
+ root: UnitEntryId,
+ }
+
+ pub(crate) struct ConvertUnitContext<'a, R: Reader<Offset = usize>> {
+ pub dwarf: &'a read::Dwarf<R>,
+ pub unit: &'a read::Unit<R>,
+ pub line_strings: &'a mut write::LineStringTable,
+ pub strings: &'a mut write::StringTable,
+ pub ranges: &'a mut write::RangeListTable,
+ pub locations: &'a mut write::LocationListTable,
+ pub convert_address: &'a dyn Fn(u64) -> Option<Address>,
+ pub base_address: Address,
+ pub line_program_offset: Option<DebugLineOffset>,
+ pub line_program_files: Vec<FileId>,
+ pub entry_ids: &'a HashMap<UnitSectionOffset, (UnitId, UnitEntryId)>,
+ }
+
+ impl UnitTable {
+ /// Create a unit table by reading the data in the given sections.
+ ///
+ /// This also updates the given tables with the values that are referenced from
+ /// attributes in this section.
+ ///
+ /// `convert_address` is a function to convert read addresses into the `Address`
+ /// type. For non-relocatable addresses, this function may simply return
+ /// `Address::Constant(address)`. For relocatable addresses, it is the caller's
+ /// responsibility to determine the symbol and addend corresponding to the address
+ /// and return `Address::Symbol { symbol, addend }`.
+ pub fn from<R: Reader<Offset = usize>>(
+ dwarf: &read::Dwarf<R>,
+ line_strings: &mut write::LineStringTable,
+ strings: &mut write::StringTable,
+ convert_address: &dyn Fn(u64) -> Option<Address>,
+ ) -> ConvertResult<UnitTable> {
+ let base_id = BaseId::default();
+ let mut unit_entries = Vec::new();
+ let mut entry_ids = HashMap::new();
+
+ let mut from_units = dwarf.units();
+ while let Some(from_unit) = from_units.next()? {
+ let unit_id = UnitId::new(base_id, unit_entries.len());
+ unit_entries.push(Unit::convert_entries(
+ from_unit,
+ unit_id,
+ &mut entry_ids,
+ dwarf,
+ )?);
+ }
+
+ // Attributes must be converted in a separate pass so that we can handle
+ // references to other compilation units.
+ let mut units = Vec::new();
+ for unit_entries in unit_entries.drain(..) {
+ units.push(Unit::convert_attributes(
+ unit_entries,
+ &entry_ids,
+ dwarf,
+ line_strings,
+ strings,
+ convert_address,
+ )?);
+ }
+
+ Ok(UnitTable { base_id, units })
+ }
+ }
+
+ impl Unit {
+ /// Create a unit by reading the data in the input sections.
+ ///
+ /// Does not add entry attributes.
+ #[allow(clippy::too_many_arguments)]
+ pub(crate) fn convert_entries<R: Reader<Offset = usize>>(
+ from_header: read::UnitHeader<R>,
+ unit_id: UnitId,
+ entry_ids: &mut HashMap<UnitSectionOffset, (UnitId, UnitEntryId)>,
+ dwarf: &read::Dwarf<R>,
+ ) -> ConvertResult<ConvertUnit<R>> {
+ match from_header.type_() {
+ read::UnitType::Compilation => (),
+ _ => return Err(ConvertError::UnsupportedUnitType),
+ }
+ let base_id = BaseId::default();
+
+ let from_unit = dwarf.unit(from_header)?;
+ let encoding = from_unit.encoding();
+
+ let mut entries = Vec::new();
+ let mut entry_offsets = Vec::new();
+
+ let mut from_tree = from_unit.entries_tree(None)?;
+ let from_root = from_tree.root()?;
+ let root = DebuggingInformationEntry::convert_entry(
+ from_root,
+ &from_unit,
+ base_id,
+ &mut entries,
+ &mut entry_offsets,
+ entry_ids,
+ None,
+ unit_id,
+ )?;
+
+ Ok(ConvertUnit {
+ from_unit,
+ base_id,
+ encoding,
+ entries,
+ entry_offsets,
+ root,
+ })
+ }
+
+ /// Create entry attributes by reading the data in the input sections.
+ fn convert_attributes<R: Reader<Offset = usize>>(
+ unit: ConvertUnit<R>,
+ entry_ids: &HashMap<UnitSectionOffset, (UnitId, UnitEntryId)>,
+ dwarf: &read::Dwarf<R>,
+ line_strings: &mut write::LineStringTable,
+ strings: &mut write::StringTable,
+ convert_address: &dyn Fn(u64) -> Option<Address>,
+ ) -> ConvertResult<Unit> {
+ let from_unit = unit.from_unit;
+ let base_address =
+ convert_address(from_unit.low_pc).ok_or(ConvertError::InvalidAddress)?;
+
+ let (line_program_offset, line_program, line_program_files) =
+ match from_unit.line_program {
+ Some(ref from_program) => {
+ let from_program = from_program.clone();
+ let line_program_offset = from_program.header().offset();
+ let (line_program, line_program_files) = LineProgram::from(
+ from_program,
+ dwarf,
+ line_strings,
+ strings,
+ convert_address,
+ )?;
+ (Some(line_program_offset), line_program, line_program_files)
+ }
+ None => (None, LineProgram::none(), Vec::new()),
+ };
+
+ let mut ranges = RangeListTable::default();
+ let mut locations = LocationListTable::default();
+
+ let mut context = ConvertUnitContext {
+ entry_ids,
+ dwarf,
+ unit: &from_unit,
+ line_strings,
+ strings,
+ ranges: &mut ranges,
+ locations: &mut locations,
+ convert_address,
+ base_address,
+ line_program_offset,
+ line_program_files,
+ };
+
+ let mut entries = unit.entries;
+ for entry in &mut entries {
+ entry.convert_attributes(&mut context, &unit.entry_offsets)?;
+ }
+
+ Ok(Unit {
+ base_id: unit.base_id,
+ encoding: unit.encoding,
+ line_program,
+ ranges,
+ locations,
+ entries,
+ root: unit.root,
+ })
+ }
+ }
+
+ impl DebuggingInformationEntry {
+ /// Create an entry by reading the data in the input sections.
+ ///
+ /// Does not add the entry attributes.
+ fn convert_entry<R: Reader<Offset = usize>>(
+ from: read::EntriesTreeNode<R>,
+ from_unit: &read::Unit<R>,
+ base_id: BaseId,
+ entries: &mut Vec<DebuggingInformationEntry>,
+ entry_offsets: &mut Vec<read::UnitOffset>,
+ entry_ids: &mut HashMap<UnitSectionOffset, (UnitId, UnitEntryId)>,
+ parent: Option<UnitEntryId>,
+ unit_id: UnitId,
+ ) -> ConvertResult<UnitEntryId> {
+ let from_entry = from.entry();
+ let id = DebuggingInformationEntry::new(base_id, entries, parent, from_entry.tag());
+ let offset = from_entry.offset();
+ entry_offsets.push(offset);
+ entry_ids.insert(offset.to_unit_section_offset(from_unit), (unit_id, id));
+
+ let mut from_children = from.children();
+ while let Some(from_child) = from_children.next()? {
+ DebuggingInformationEntry::convert_entry(
+ from_child,
+ from_unit,
+ base_id,
+ entries,
+ entry_offsets,
+ entry_ids,
+ Some(id),
+ unit_id,
+ )?;
+ }
+ Ok(id)
+ }
+
+ /// Create an entry's attributes by reading the data in the input sections.
+ fn convert_attributes<R: Reader<Offset = usize>>(
+ &mut self,
+ context: &mut ConvertUnitContext<R>,
+ entry_offsets: &[read::UnitOffset],
+ ) -> ConvertResult<()> {
+ let offset = entry_offsets[self.id.index];
+ let from = context.unit.entry(offset)?;
+ let mut from_attrs = from.attrs();
+ while let Some(from_attr) = from_attrs.next()? {
+ if from_attr.name() == constants::DW_AT_sibling {
+ // This may point to a null entry, so we have to treat it differently.
+ self.set_sibling(true);
+ } else if let Some(attr) = Attribute::from(context, &from_attr)? {
+ self.set(attr.name, attr.value);
+ }
+ }
+ Ok(())
+ }
+ }
+
+ impl Attribute {
+ /// Create an attribute by reading the data in the given sections.
+ pub(crate) fn from<R: Reader<Offset = usize>>(
+ context: &mut ConvertUnitContext<R>,
+ from: &read::Attribute<R>,
+ ) -> ConvertResult<Option<Attribute>> {
+ let value = AttributeValue::from(context, from.value())?;
+ Ok(value.map(|value| Attribute {
+ name: from.name(),
+ value,
+ }))
+ }
+ }
+
+ impl AttributeValue {
+ /// Create an attribute value by reading the data in the given sections.
+ pub(crate) fn from<R: Reader<Offset = usize>>(
+ context: &mut ConvertUnitContext<R>,
+ from: read::AttributeValue<R>,
+ ) -> ConvertResult<Option<AttributeValue>> {
+ let to = match from {
+ read::AttributeValue::Addr(val) => match (context.convert_address)(val) {
+ Some(val) => AttributeValue::Address(val),
+ None => return Err(ConvertError::InvalidAddress),
+ },
+ read::AttributeValue::Block(r) => AttributeValue::Block(r.to_slice()?.into()),
+ read::AttributeValue::Data1(val) => AttributeValue::Data1(val),
+ read::AttributeValue::Data2(val) => AttributeValue::Data2(val),
+ read::AttributeValue::Data4(val) => AttributeValue::Data4(val),
+ read::AttributeValue::Data8(val) => AttributeValue::Data8(val),
+ read::AttributeValue::Sdata(val) => AttributeValue::Sdata(val),
+ read::AttributeValue::Udata(val) => AttributeValue::Udata(val),
+ read::AttributeValue::Exprloc(expression) => {
+ let expression = Expression::from(
+ expression,
+ context.unit.encoding(),
+ Some(context.dwarf),
+ Some(context.unit),
+ Some(context.entry_ids),
+ context.convert_address,
+ )?;
+ AttributeValue::Exprloc(expression)
+ }
+ // TODO: it would be nice to preserve the flag form.
+ read::AttributeValue::Flag(val) => AttributeValue::Flag(val),
+ read::AttributeValue::DebugAddrBase(_base) => {
+ // We convert all address indices to addresses,
+ // so this is unneeded.
+ return Ok(None);
+ }
+ read::AttributeValue::DebugAddrIndex(index) => {
+ let val = context.dwarf.address(context.unit, index)?;
+ match (context.convert_address)(val) {
+ Some(val) => AttributeValue::Address(val),
+ None => return Err(ConvertError::InvalidAddress),
+ }
+ }
+ read::AttributeValue::UnitRef(val) => {
+ if !context.unit.header.is_valid_offset(val) {
+ return Err(ConvertError::InvalidUnitRef);
+ }
+ let id = context
+ .entry_ids
+ .get(&val.to_unit_section_offset(context.unit))
+ .ok_or(ConvertError::InvalidUnitRef)?;
+ AttributeValue::UnitRef(id.1)
+ }
+ read::AttributeValue::DebugInfoRef(val) => {
+ // TODO: support relocation of this value
+ let id = context
+ .entry_ids
+ .get(&UnitSectionOffset::DebugInfoOffset(val))
+ .ok_or(ConvertError::InvalidDebugInfoRef)?;
+ AttributeValue::DebugInfoRef(Reference::Entry(id.0, id.1))
+ }
+ read::AttributeValue::DebugInfoRefSup(val) => AttributeValue::DebugInfoRefSup(val),
+ read::AttributeValue::DebugLineRef(val) => {
+ // There should only be the line program in the CU DIE which we've already
+ // converted, so check if it matches that.
+ if Some(val) == context.line_program_offset {
+ AttributeValue::LineProgramRef
+ } else {
+ return Err(ConvertError::InvalidLineRef);
+ }
+ }
+ read::AttributeValue::DebugMacinfoRef(val) => AttributeValue::DebugMacinfoRef(val),
+ read::AttributeValue::DebugMacroRef(val) => AttributeValue::DebugMacroRef(val),
+ read::AttributeValue::LocationListsRef(val) => {
+ let iter = context
+ .dwarf
+ .locations
+ .raw_locations(val, context.unit.encoding())?;
+ let loc_list = LocationList::from(iter, context)?;
+ let loc_id = context.locations.add(loc_list);
+ AttributeValue::LocationListRef(loc_id)
+ }
+ read::AttributeValue::DebugLocListsBase(_base) => {
+ // We convert all location list indices to offsets,
+ // so this is unneeded.
+ return Ok(None);
+ }
+ read::AttributeValue::DebugLocListsIndex(index) => {
+ let offset = context.dwarf.locations_offset(context.unit, index)?;
+ let iter = context
+ .dwarf
+ .locations
+ .raw_locations(offset, context.unit.encoding())?;
+ let loc_list = LocationList::from(iter, context)?;
+ let loc_id = context.locations.add(loc_list);
+ AttributeValue::LocationListRef(loc_id)
+ }
+ read::AttributeValue::RangeListsRef(offset) => {
+ let offset = context.dwarf.ranges_offset_from_raw(context.unit, offset);
+ let iter = context.dwarf.raw_ranges(context.unit, offset)?;
+ let range_list = RangeList::from(iter, context)?;
+ let range_id = context.ranges.add(range_list);
+ AttributeValue::RangeListRef(range_id)
+ }
+ read::AttributeValue::DebugRngListsBase(_base) => {
+ // We convert all range list indices to offsets,
+ // so this is unneeded.
+ return Ok(None);
+ }
+ read::AttributeValue::DebugRngListsIndex(index) => {
+ let offset = context.dwarf.ranges_offset(context.unit, index)?;
+ let iter = context
+ .dwarf
+ .ranges
+ .raw_ranges(offset, context.unit.encoding())?;
+ let range_list = RangeList::from(iter, context)?;
+ let range_id = context.ranges.add(range_list);
+ AttributeValue::RangeListRef(range_id)
+ }
+ read::AttributeValue::DebugTypesRef(val) => AttributeValue::DebugTypesRef(val),
+ read::AttributeValue::DebugStrRef(offset) => {
+ let r = context.dwarf.string(offset)?;
+ let id = context.strings.add(r.to_slice()?);
+ AttributeValue::StringRef(id)
+ }
+ read::AttributeValue::DebugStrRefSup(val) => AttributeValue::DebugStrRefSup(val),
+ read::AttributeValue::DebugStrOffsetsBase(_base) => {
+ // We convert all string offsets to `.debug_str` references,
+ // so this is unneeded.
+ return Ok(None);
+ }
+ read::AttributeValue::DebugStrOffsetsIndex(index) => {
+ let offset = context.dwarf.string_offset(context.unit, index)?;
+ let r = context.dwarf.string(offset)?;
+ let id = context.strings.add(r.to_slice()?);
+ AttributeValue::StringRef(id)
+ }
+ read::AttributeValue::DebugLineStrRef(offset) => {
+ let r = context.dwarf.line_string(offset)?;
+ let id = context.line_strings.add(r.to_slice()?);
+ AttributeValue::LineStringRef(id)
+ }
+ read::AttributeValue::String(r) => AttributeValue::String(r.to_slice()?.into()),
+ read::AttributeValue::Encoding(val) => AttributeValue::Encoding(val),
+ read::AttributeValue::DecimalSign(val) => AttributeValue::DecimalSign(val),
+ read::AttributeValue::Endianity(val) => AttributeValue::Endianity(val),
+ read::AttributeValue::Accessibility(val) => AttributeValue::Accessibility(val),
+ read::AttributeValue::Visibility(val) => AttributeValue::Visibility(val),
+ read::AttributeValue::Virtuality(val) => AttributeValue::Virtuality(val),
+ read::AttributeValue::Language(val) => AttributeValue::Language(val),
+ read::AttributeValue::AddressClass(val) => AttributeValue::AddressClass(val),
+ read::AttributeValue::IdentifierCase(val) => AttributeValue::IdentifierCase(val),
+ read::AttributeValue::CallingConvention(val) => {
+ AttributeValue::CallingConvention(val)
+ }
+ read::AttributeValue::Inline(val) => AttributeValue::Inline(val),
+ read::AttributeValue::Ordering(val) => AttributeValue::Ordering(val),
+ read::AttributeValue::FileIndex(val) => {
+ if val == 0 {
+ // 0 means not specified, even for version 5.
+ AttributeValue::FileIndex(None)
+ } else {
+ match context.line_program_files.get(val as usize) {
+ Some(id) => AttributeValue::FileIndex(Some(*id)),
+ None => return Err(ConvertError::InvalidFileIndex),
+ }
+ }
+ }
+ // Should always be a more specific section reference.
+ read::AttributeValue::SecOffset(_) => {
+ return Err(ConvertError::InvalidAttributeValue);
+ }
+ read::AttributeValue::DwoId(DwoId(val)) => AttributeValue::Udata(val),
+ };
+ Ok(Some(to))
+ }
+ }
+}
+
+#[cfg(test)]
+#[cfg(feature = "read")]
+mod tests {
+ use super::*;
+ use crate::common::{
+ DebugAddrBase, DebugLocListsBase, DebugRngListsBase, DebugStrOffsetsBase, LineEncoding,
+ };
+ use crate::constants;
+ use crate::read;
+ use crate::write::{
+ DebugLine, DebugLineStr, DebugStr, DwarfUnit, EndianVec, LineString, LineStringTable,
+ Location, LocationList, LocationListTable, Range, RangeList, RangeListOffsets,
+ RangeListTable, StringTable,
+ };
+ use crate::LittleEndian;
+ use std::collections::HashMap;
+ use std::mem;
+
+ #[test]
+ #[allow(clippy::cyclomatic_complexity)]
+ fn test_unit_table() {
+ let mut strings = StringTable::default();
+
+ let mut units = UnitTable::default();
+ let unit_id1 = units.add(Unit::new(
+ Encoding {
+ version: 4,
+ address_size: 8,
+ format: Format::Dwarf32,
+ },
+ LineProgram::none(),
+ ));
+ let unit2 = units.add(Unit::new(
+ Encoding {
+ version: 2,
+ address_size: 4,
+ format: Format::Dwarf64,
+ },
+ LineProgram::none(),
+ ));
+ let unit3 = units.add(Unit::new(
+ Encoding {
+ version: 5,
+ address_size: 4,
+ format: Format::Dwarf32,
+ },
+ LineProgram::none(),
+ ));
+ assert_eq!(units.count(), 3);
+ {
+ let unit1 = units.get_mut(unit_id1);
+ assert_eq!(unit1.version(), 4);
+ assert_eq!(unit1.address_size(), 8);
+ assert_eq!(unit1.format(), Format::Dwarf32);
+ assert_eq!(unit1.count(), 1);
+
+ let root_id = unit1.root();
+ assert_eq!(root_id, UnitEntryId::new(unit1.base_id, 0));
+ {
+ let root = unit1.get_mut(root_id);
+ assert_eq!(root.id(), root_id);
+ assert!(root.parent().is_none());
+ assert_eq!(root.tag(), constants::DW_TAG_compile_unit);
+
+ // Test get/get_mut
+ assert!(root.get(constants::DW_AT_producer).is_none());
+ assert!(root.get_mut(constants::DW_AT_producer).is_none());
+ let mut producer = AttributeValue::String(b"root"[..].into());
+ root.set(constants::DW_AT_producer, producer.clone());
+ assert_eq!(root.get(constants::DW_AT_producer), Some(&producer));
+ assert_eq!(root.get_mut(constants::DW_AT_producer), Some(&mut producer));
+
+ // Test attrs
+ let mut attrs = root.attrs();
+ let attr = attrs.next().unwrap();
+ assert_eq!(attr.name(), constants::DW_AT_producer);
+ assert_eq!(attr.get(), &producer);
+ assert!(attrs.next().is_none());
+ }
+
+ let child1 = unit1.add(root_id, constants::DW_TAG_subprogram);
+ assert_eq!(child1, UnitEntryId::new(unit1.base_id, 1));
+ {
+ let child1 = unit1.get_mut(child1);
+ assert_eq!(child1.parent(), Some(root_id));
+
+ let tmp = AttributeValue::String(b"tmp"[..].into());
+ child1.set(constants::DW_AT_name, tmp.clone());
+ assert_eq!(child1.get(constants::DW_AT_name), Some(&tmp));
+
+ // Test attrs_mut
+ let name = AttributeValue::StringRef(strings.add(&b"child1"[..]));
+ {
+ let attr = child1.attrs_mut().next().unwrap();
+ assert_eq!(attr.name(), constants::DW_AT_name);
+ attr.set(name.clone());
+ }
+ assert_eq!(child1.get(constants::DW_AT_name), Some(&name));
+ }
+
+ let child2 = unit1.add(root_id, constants::DW_TAG_subprogram);
+ assert_eq!(child2, UnitEntryId::new(unit1.base_id, 2));
+ {
+ let child2 = unit1.get_mut(child2);
+ assert_eq!(child2.parent(), Some(root_id));
+
+ let tmp = AttributeValue::String(b"tmp"[..].into());
+ child2.set(constants::DW_AT_name, tmp.clone());
+ assert_eq!(child2.get(constants::DW_AT_name), Some(&tmp));
+
+ // Test replace
+ let name = AttributeValue::StringRef(strings.add(&b"child2"[..]));
+ child2.set(constants::DW_AT_name, name.clone());
+ assert_eq!(child2.get(constants::DW_AT_name), Some(&name));
+ }
+
+ {
+ let root = unit1.get(root_id);
+ assert_eq!(
+ root.children().cloned().collect::<Vec<_>>(),
+ vec![child1, child2]
+ );
+ }
+ }
+ {
+ let unit2 = units.get(unit2);
+ assert_eq!(unit2.version(), 2);
+ assert_eq!(unit2.address_size(), 4);
+ assert_eq!(unit2.format(), Format::Dwarf64);
+ assert_eq!(unit2.count(), 1);
+
+ let root = unit2.root();
+ assert_eq!(root, UnitEntryId::new(unit2.base_id, 0));
+ let root = unit2.get(root);
+ assert_eq!(root.id(), UnitEntryId::new(unit2.base_id, 0));
+ assert!(root.parent().is_none());
+ assert_eq!(root.tag(), constants::DW_TAG_compile_unit);
+ }
+
+ let mut sections = Sections::new(EndianVec::new(LittleEndian));
+ let debug_line_str_offsets = DebugLineStrOffsets::none();
+ let debug_str_offsets = strings.write(&mut sections.debug_str).unwrap();
+ units
+ .write(&mut sections, &debug_line_str_offsets, &debug_str_offsets)
+ .unwrap();
+
+ println!("{:?}", sections.debug_str);
+ println!("{:?}", sections.debug_info);
+ println!("{:?}", sections.debug_abbrev);
+
+ let dwarf = read::Dwarf {
+ debug_abbrev: read::DebugAbbrev::new(sections.debug_abbrev.slice(), LittleEndian),
+ debug_info: read::DebugInfo::new(sections.debug_info.slice(), LittleEndian),
+ debug_str: read::DebugStr::new(sections.debug_str.slice(), LittleEndian),
+ ..Default::default()
+ };
+ let mut read_units = dwarf.units();
+
+ {
+ let read_unit1 = read_units.next().unwrap().unwrap();
+ let unit1 = units.get(unit_id1);
+ assert_eq!(unit1.version(), read_unit1.version());
+ assert_eq!(unit1.address_size(), read_unit1.address_size());
+ assert_eq!(unit1.format(), read_unit1.format());
+
+ let read_unit1 = dwarf.unit(read_unit1).unwrap();
+ let mut read_entries = read_unit1.entries();
+
+ let root = unit1.get(unit1.root());
+ {
+ let (depth, read_root) = read_entries.next_dfs().unwrap().unwrap();
+ assert_eq!(depth, 0);
+ assert_eq!(root.tag(), read_root.tag());
+ assert!(read_root.has_children());
+
+ let producer = match root.get(constants::DW_AT_producer).unwrap() {
+ AttributeValue::String(ref producer) => &**producer,
+ otherwise => panic!("unexpected {:?}", otherwise),
+ };
+ assert_eq!(producer, b"root");
+ let read_producer = read_root
+ .attr_value(constants::DW_AT_producer)
+ .unwrap()
+ .unwrap();
+ assert_eq!(
+ dwarf
+ .attr_string(&read_unit1, read_producer)
+ .unwrap()
+ .slice(),
+ producer
+ );
+ }
+
+ let mut children = root.children().cloned();
+
+ {
+ let child = children.next().unwrap();
+ assert_eq!(child, UnitEntryId::new(unit1.base_id, 1));
+ let child = unit1.get(child);
+ let (depth, read_child) = read_entries.next_dfs().unwrap().unwrap();
+ assert_eq!(depth, 1);
+ assert_eq!(child.tag(), read_child.tag());
+ assert!(!read_child.has_children());
+
+ let name = match child.get(constants::DW_AT_name).unwrap() {
+ AttributeValue::StringRef(name) => *name,
+ otherwise => panic!("unexpected {:?}", otherwise),
+ };
+ let name = strings.get(name);
+ assert_eq!(name, b"child1");
+ let read_name = read_child
+ .attr_value(constants::DW_AT_name)
+ .unwrap()
+ .unwrap();
+ assert_eq!(
+ dwarf.attr_string(&read_unit1, read_name).unwrap().slice(),
+ name
+ );
+ }
+
+ {
+ let child = children.next().unwrap();
+ assert_eq!(child, UnitEntryId::new(unit1.base_id, 2));
+ let child = unit1.get(child);
+ let (depth, read_child) = read_entries.next_dfs().unwrap().unwrap();
+ assert_eq!(depth, 0);
+ assert_eq!(child.tag(), read_child.tag());
+ assert!(!read_child.has_children());
+
+ let name = match child.get(constants::DW_AT_name).unwrap() {
+ AttributeValue::StringRef(name) => *name,
+ otherwise => panic!("unexpected {:?}", otherwise),
+ };
+ let name = strings.get(name);
+ assert_eq!(name, b"child2");
+ let read_name = read_child
+ .attr_value(constants::DW_AT_name)
+ .unwrap()
+ .unwrap();
+ assert_eq!(
+ dwarf.attr_string(&read_unit1, read_name).unwrap().slice(),
+ name
+ );
+ }
+
+ assert!(read_entries.next_dfs().unwrap().is_none());
+ }
+
+ {
+ let read_unit2 = read_units.next().unwrap().unwrap();
+ let unit2 = units.get(unit2);
+ assert_eq!(unit2.version(), read_unit2.version());
+ assert_eq!(unit2.address_size(), read_unit2.address_size());
+ assert_eq!(unit2.format(), read_unit2.format());
+
+ let abbrevs = dwarf.abbreviations(&read_unit2).unwrap();
+ let mut read_entries = read_unit2.entries(&abbrevs);
+
+ {
+ let root = unit2.get(unit2.root());
+ let (depth, read_root) = read_entries.next_dfs().unwrap().unwrap();
+ assert_eq!(depth, 0);
+ assert_eq!(root.tag(), read_root.tag());
+ assert!(!read_root.has_children());
+ }
+
+ assert!(read_entries.next_dfs().unwrap().is_none());
+ }
+
+ {
+ let read_unit3 = read_units.next().unwrap().unwrap();
+ let unit3 = units.get(unit3);
+ assert_eq!(unit3.version(), read_unit3.version());
+ assert_eq!(unit3.address_size(), read_unit3.address_size());
+ assert_eq!(unit3.format(), read_unit3.format());
+
+ let abbrevs = dwarf.abbreviations(&read_unit3).unwrap();
+ let mut read_entries = read_unit3.entries(&abbrevs);
+
+ {
+ let root = unit3.get(unit3.root());
+ let (depth, read_root) = read_entries.next_dfs().unwrap().unwrap();
+ assert_eq!(depth, 0);
+ assert_eq!(root.tag(), read_root.tag());
+ assert!(!read_root.has_children());
+ }
+
+ assert!(read_entries.next_dfs().unwrap().is_none());
+ }
+
+ assert!(read_units.next().unwrap().is_none());
+
+ let mut convert_line_strings = LineStringTable::default();
+ let mut convert_strings = StringTable::default();
+ let convert_units = UnitTable::from(
+ &dwarf,
+ &mut convert_line_strings,
+ &mut convert_strings,
+ &|address| Some(Address::Constant(address)),
+ )
+ .unwrap();
+ assert_eq!(convert_units.count(), units.count());
+
+ for i in 0..convert_units.count() {
+ let unit_id = units.id(i);
+ let unit = units.get(unit_id);
+ let convert_unit_id = convert_units.id(i);
+ let convert_unit = convert_units.get(convert_unit_id);
+ assert_eq!(convert_unit.version(), unit.version());
+ assert_eq!(convert_unit.address_size(), unit.address_size());
+ assert_eq!(convert_unit.format(), unit.format());
+ assert_eq!(convert_unit.count(), unit.count());
+
+ let root = unit.get(unit.root());
+ let convert_root = convert_unit.get(convert_unit.root());
+ assert_eq!(convert_root.tag(), root.tag());
+ for (convert_attr, attr) in convert_root.attrs().zip(root.attrs()) {
+ assert_eq!(convert_attr, attr);
+ }
+ }
+ }
+
+ #[test]
+ fn test_attribute_value() {
+ // Create a string table and a string with a non-zero id/offset.
+ let mut strings = StringTable::default();
+ strings.add("string one");
+ let string_id = strings.add("string two");
+ let mut debug_str = DebugStr::from(EndianVec::new(LittleEndian));
+ let debug_str_offsets = strings.write(&mut debug_str).unwrap();
+ let read_debug_str = read::DebugStr::new(debug_str.slice(), LittleEndian);
+
+ let mut line_strings = LineStringTable::default();
+ line_strings.add("line string one");
+ let line_string_id = line_strings.add("line string two");
+ let mut debug_line_str = DebugLineStr::from(EndianVec::new(LittleEndian));
+ let debug_line_str_offsets = line_strings.write(&mut debug_line_str).unwrap();
+ let read_debug_line_str =
+ read::DebugLineStr::from(read::EndianSlice::new(debug_line_str.slice(), LittleEndian));
+
+ let data = vec![1, 2, 3, 4];
+ let read_data = read::EndianSlice::new(&[1, 2, 3, 4], LittleEndian);
+
+ let mut expression = Expression::new();
+ expression.op_constu(57);
+ let read_expression = read::Expression(read::EndianSlice::new(
+ &[constants::DW_OP_constu.0, 57],
+ LittleEndian,
+ ));
+
+ let mut ranges = RangeListTable::default();
+ let range_id = ranges.add(RangeList(vec![Range::StartEnd {
+ begin: Address::Constant(0x1234),
+ end: Address::Constant(0x2345),
+ }]));
+
+ let mut locations = LocationListTable::default();
+ let loc_id = locations.add(LocationList(vec![Location::StartEnd {
+ begin: Address::Constant(0x1234),
+ end: Address::Constant(0x2345),
+ data: expression.clone(),
+ }]));
+
+ for &version in &[2, 3, 4, 5] {
+ for &address_size in &[4, 8] {
+ for &format in &[Format::Dwarf32, Format::Dwarf64] {
+ let encoding = Encoding {
+ format,
+ version,
+ address_size,
+ };
+
+ let mut sections = Sections::new(EndianVec::new(LittleEndian));
+ let range_list_offsets = ranges.write(&mut sections, encoding).unwrap();
+ let loc_list_offsets = locations.write(&mut sections, encoding, None).unwrap();
+
+ let read_debug_ranges =
+ read::DebugRanges::new(sections.debug_ranges.slice(), LittleEndian);
+ let read_debug_rnglists =
+ read::DebugRngLists::new(sections.debug_rnglists.slice(), LittleEndian);
+
+ let read_debug_loc =
+ read::DebugLoc::new(sections.debug_loc.slice(), LittleEndian);
+ let read_debug_loclists =
+ read::DebugLocLists::new(sections.debug_loclists.slice(), LittleEndian);
+
+ let mut units = UnitTable::default();
+ let unit = units.add(Unit::new(encoding, LineProgram::none()));
+ let unit = units.get(unit);
+ let encoding = Encoding {
+ format,
+ version,
+ address_size,
+ };
+ let from_unit = read::UnitHeader::new(
+ encoding,
+ 0,
+ read::UnitType::Compilation,
+ DebugAbbrevOffset(0),
+ DebugInfoOffset(0).into(),
+ read::EndianSlice::new(&[], LittleEndian),
+ );
+
+ for &(ref name, ref value, ref expect_value) in &[
+ (
+ constants::DW_AT_name,
+ AttributeValue::Address(Address::Constant(0x1234)),
+ read::AttributeValue::Addr(0x1234),
+ ),
+ (
+ constants::DW_AT_name,
+ AttributeValue::Block(data.clone()),
+ read::AttributeValue::Block(read_data),
+ ),
+ (
+ constants::DW_AT_name,
+ AttributeValue::Data1(0x12),
+ read::AttributeValue::Data1(0x12),
+ ),
+ (
+ constants::DW_AT_name,
+ AttributeValue::Data2(0x1234),
+ read::AttributeValue::Data2(0x1234),
+ ),
+ (
+ constants::DW_AT_name,
+ AttributeValue::Data4(0x1234),
+ read::AttributeValue::Data4(0x1234),
+ ),
+ (
+ constants::DW_AT_name,
+ AttributeValue::Data8(0x1234),
+ read::AttributeValue::Data8(0x1234),
+ ),
+ (
+ constants::DW_AT_name,
+ AttributeValue::Sdata(0x1234),
+ read::AttributeValue::Sdata(0x1234),
+ ),
+ (
+ constants::DW_AT_name,
+ AttributeValue::Udata(0x1234),
+ read::AttributeValue::Udata(0x1234),
+ ),
+ (
+ constants::DW_AT_name,
+ AttributeValue::Exprloc(expression.clone()),
+ read::AttributeValue::Exprloc(read_expression),
+ ),
+ (
+ constants::DW_AT_name,
+ AttributeValue::Flag(false),
+ read::AttributeValue::Flag(false),
+ ),
+ /*
+ (
+ constants::DW_AT_name,
+ AttributeValue::FlagPresent,
+ read::AttributeValue::Flag(true),
+ ),
+ */
+ (
+ constants::DW_AT_name,
+ AttributeValue::DebugInfoRefSup(DebugInfoOffset(0x1234)),
+ read::AttributeValue::DebugInfoRefSup(DebugInfoOffset(0x1234)),
+ ),
+ (
+ constants::DW_AT_location,
+ AttributeValue::LocationListRef(loc_id),
+ read::AttributeValue::SecOffset(loc_list_offsets.get(loc_id).0),
+ ),
+ (
+ constants::DW_AT_macro_info,
+ AttributeValue::DebugMacinfoRef(DebugMacinfoOffset(0x1234)),
+ read::AttributeValue::SecOffset(0x1234),
+ ),
+ (
+ constants::DW_AT_macros,
+ AttributeValue::DebugMacroRef(DebugMacroOffset(0x1234)),
+ read::AttributeValue::SecOffset(0x1234),
+ ),
+ (
+ constants::DW_AT_ranges,
+ AttributeValue::RangeListRef(range_id),
+ read::AttributeValue::SecOffset(range_list_offsets.get(range_id).0),
+ ),
+ (
+ constants::DW_AT_name,
+ AttributeValue::DebugTypesRef(DebugTypeSignature(0x1234)),
+ read::AttributeValue::DebugTypesRef(DebugTypeSignature(0x1234)),
+ ),
+ (
+ constants::DW_AT_name,
+ AttributeValue::StringRef(string_id),
+ read::AttributeValue::DebugStrRef(debug_str_offsets.get(string_id)),
+ ),
+ (
+ constants::DW_AT_name,
+ AttributeValue::DebugStrRefSup(DebugStrOffset(0x1234)),
+ read::AttributeValue::DebugStrRefSup(DebugStrOffset(0x1234)),
+ ),
+ (
+ constants::DW_AT_name,
+ AttributeValue::LineStringRef(line_string_id),
+ read::AttributeValue::DebugLineStrRef(
+ debug_line_str_offsets.get(line_string_id),
+ ),
+ ),
+ (
+ constants::DW_AT_name,
+ AttributeValue::String(data.clone()),
+ read::AttributeValue::String(read_data),
+ ),
+ (
+ constants::DW_AT_encoding,
+ AttributeValue::Encoding(constants::DwAte(0x12)),
+ read::AttributeValue::Udata(0x12),
+ ),
+ (
+ constants::DW_AT_decimal_sign,
+ AttributeValue::DecimalSign(constants::DwDs(0x12)),
+ read::AttributeValue::Udata(0x12),
+ ),
+ (
+ constants::DW_AT_endianity,
+ AttributeValue::Endianity(constants::DwEnd(0x12)),
+ read::AttributeValue::Udata(0x12),
+ ),
+ (
+ constants::DW_AT_accessibility,
+ AttributeValue::Accessibility(constants::DwAccess(0x12)),
+ read::AttributeValue::Udata(0x12),
+ ),
+ (
+ constants::DW_AT_visibility,
+ AttributeValue::Visibility(constants::DwVis(0x12)),
+ read::AttributeValue::Udata(0x12),
+ ),
+ (
+ constants::DW_AT_virtuality,
+ AttributeValue::Virtuality(constants::DwVirtuality(0x12)),
+ read::AttributeValue::Udata(0x12),
+ ),
+ (
+ constants::DW_AT_language,
+ AttributeValue::Language(constants::DwLang(0x12)),
+ read::AttributeValue::Udata(0x12),
+ ),
+ (
+ constants::DW_AT_address_class,
+ AttributeValue::AddressClass(constants::DwAddr(0x12)),
+ read::AttributeValue::Udata(0x12),
+ ),
+ (
+ constants::DW_AT_identifier_case,
+ AttributeValue::IdentifierCase(constants::DwId(0x12)),
+ read::AttributeValue::Udata(0x12),
+ ),
+ (
+ constants::DW_AT_calling_convention,
+ AttributeValue::CallingConvention(constants::DwCc(0x12)),
+ read::AttributeValue::Udata(0x12),
+ ),
+ (
+ constants::DW_AT_ordering,
+ AttributeValue::Ordering(constants::DwOrd(0x12)),
+ read::AttributeValue::Udata(0x12),
+ ),
+ (
+ constants::DW_AT_inline,
+ AttributeValue::Inline(constants::DwInl(0x12)),
+ read::AttributeValue::Udata(0x12),
+ ),
+ ][..]
+ {
+ let form = value.form(encoding).unwrap();
+ let attr = Attribute {
+ name: *name,
+ value: value.clone(),
+ };
+
+ let offsets = UnitOffsets::none();
+ let line_program_offset = None;
+ let mut debug_info_refs = Vec::new();
+ let mut unit_refs = Vec::new();
+ let mut debug_info = DebugInfo::from(EndianVec::new(LittleEndian));
+ attr.value
+ .write(
+ &mut debug_info,
+ &mut debug_info_refs,
+ &mut unit_refs,
+ &unit,
+ &offsets,
+ line_program_offset,
+ &debug_line_str_offsets,
+ &debug_str_offsets,
+ &range_list_offsets,
+ &loc_list_offsets,
+ )
+ .unwrap();
+
+ let spec = read::AttributeSpecification::new(*name, form, None);
+ let mut r = read::EndianSlice::new(debug_info.slice(), LittleEndian);
+ let read_attr = read::parse_attribute(&mut r, encoding, spec).unwrap();
+ let read_value = &read_attr.raw_value();
+ // read::AttributeValue is invariant in the lifetime of R.
+ // The lifetimes here are all okay, so transmute it.
+ let read_value = unsafe {
+ mem::transmute::<
+ &read::AttributeValue<read::EndianSlice<LittleEndian>>,
+ &read::AttributeValue<read::EndianSlice<LittleEndian>>,
+ >(read_value)
+ };
+ assert_eq!(read_value, expect_value);
+
+ let dwarf = read::Dwarf {
+ debug_str: read_debug_str.clone(),
+ debug_line_str: read_debug_line_str.clone(),
+ ranges: read::RangeLists::new(read_debug_ranges, read_debug_rnglists),
+ locations: read::LocationLists::new(
+ read_debug_loc,
+ read_debug_loclists,
+ ),
+ ..Default::default()
+ };
+
+ let unit = read::Unit {
+ header: from_unit,
+ abbreviations: read::Abbreviations::default(),
+ name: None,
+ comp_dir: None,
+ low_pc: 0,
+ str_offsets_base: DebugStrOffsetsBase(0),
+ addr_base: DebugAddrBase(0),
+ loclists_base: DebugLocListsBase(0),
+ rnglists_base: DebugRngListsBase(0),
+ line_program: None,
+ dwo_id: None,
+ };
+
+ let mut context = convert::ConvertUnitContext {
+ dwarf: &dwarf,
+ unit: &unit,
+ line_strings: &mut line_strings,
+ strings: &mut strings,
+ ranges: &mut ranges,
+ locations: &mut locations,
+ convert_address: &|address| Some(Address::Constant(address)),
+ base_address: Address::Constant(0),
+ line_program_offset: None,
+ line_program_files: Vec::new(),
+ entry_ids: &HashMap::new(),
+ };
+
+ let convert_attr =
+ Attribute::from(&mut context, &read_attr).unwrap().unwrap();
+ assert_eq!(convert_attr, attr);
+ }
+ }
+ }
+ }
+ }
+
+ #[test]
+ #[allow(clippy::cyclomatic_complexity)]
+ fn test_unit_ref() {
+ let mut units = UnitTable::default();
+ let unit_id1 = units.add(Unit::new(
+ Encoding {
+ version: 4,
+ address_size: 8,
+ format: Format::Dwarf32,
+ },
+ LineProgram::none(),
+ ));
+ assert_eq!(unit_id1, units.id(0));
+ let unit_id2 = units.add(Unit::new(
+ Encoding {
+ version: 2,
+ address_size: 4,
+ format: Format::Dwarf64,
+ },
+ LineProgram::none(),
+ ));
+ assert_eq!(unit_id2, units.id(1));
+ let unit1_child1 = UnitEntryId::new(units.get(unit_id1).base_id, 1);
+ let unit1_child2 = UnitEntryId::new(units.get(unit_id1).base_id, 2);
+ let unit2_child1 = UnitEntryId::new(units.get(unit_id2).base_id, 1);
+ let unit2_child2 = UnitEntryId::new(units.get(unit_id2).base_id, 2);
+ {
+ let unit1 = units.get_mut(unit_id1);
+ let root = unit1.root();
+ let child_id1 = unit1.add(root, constants::DW_TAG_subprogram);
+ assert_eq!(child_id1, unit1_child1);
+ let child_id2 = unit1.add(root, constants::DW_TAG_subprogram);
+ assert_eq!(child_id2, unit1_child2);
+ {
+ let child1 = unit1.get_mut(child_id1);
+ child1.set(constants::DW_AT_type, AttributeValue::UnitRef(child_id2));
+ }
+ {
+ let child2 = unit1.get_mut(child_id2);
+ child2.set(
+ constants::DW_AT_type,
+ AttributeValue::DebugInfoRef(Reference::Entry(unit_id2, unit2_child1)),
+ );
+ }
+ }
+ {
+ let unit2 = units.get_mut(unit_id2);
+ let root = unit2.root();
+ let child_id1 = unit2.add(root, constants::DW_TAG_subprogram);
+ assert_eq!(child_id1, unit2_child1);
+ let child_id2 = unit2.add(root, constants::DW_TAG_subprogram);
+ assert_eq!(child_id2, unit2_child2);
+ {
+ let child1 = unit2.get_mut(child_id1);
+ child1.set(constants::DW_AT_type, AttributeValue::UnitRef(child_id2));
+ }
+ {
+ let child2 = unit2.get_mut(child_id2);
+ child2.set(
+ constants::DW_AT_type,
+ AttributeValue::DebugInfoRef(Reference::Entry(unit_id1, unit1_child1)),
+ );
+ }
+ }
+
+ let debug_line_str_offsets = DebugLineStrOffsets::none();
+ let debug_str_offsets = DebugStrOffsets::none();
+ let mut sections = Sections::new(EndianVec::new(LittleEndian));
+ let debug_info_offsets = units
+ .write(&mut sections, &debug_line_str_offsets, &debug_str_offsets)
+ .unwrap();
+
+ println!("{:?}", sections.debug_info);
+ println!("{:?}", sections.debug_abbrev);
+
+ let dwarf = read::Dwarf {
+ debug_abbrev: read::DebugAbbrev::new(sections.debug_abbrev.slice(), LittleEndian),
+ debug_info: read::DebugInfo::new(sections.debug_info.slice(), LittleEndian),
+ ..Default::default()
+ };
+
+ let mut read_units = dwarf.units();
+ {
+ let read_unit1 = read_units.next().unwrap().unwrap();
+ assert_eq!(
+ read_unit1.offset(),
+ debug_info_offsets.unit(unit_id1).into()
+ );
+
+ let abbrevs = dwarf.abbreviations(&read_unit1).unwrap();
+ let mut read_entries = read_unit1.entries(&abbrevs);
+ {
+ let (_, _read_root) = read_entries.next_dfs().unwrap().unwrap();
+ }
+ {
+ let (_, read_child1) = read_entries.next_dfs().unwrap().unwrap();
+ let offset = debug_info_offsets
+ .entry(unit_id1, unit1_child2)
+ .to_unit_offset(&read_unit1)
+ .unwrap();
+ assert_eq!(
+ read_child1.attr_value(constants::DW_AT_type).unwrap(),
+ Some(read::AttributeValue::UnitRef(offset))
+ );
+ }
+ {
+ let (_, read_child2) = read_entries.next_dfs().unwrap().unwrap();
+ let offset = debug_info_offsets.entry(unit_id2, unit2_child1);
+ assert_eq!(
+ read_child2.attr_value(constants::DW_AT_type).unwrap(),
+ Some(read::AttributeValue::DebugInfoRef(offset))
+ );
+ }
+ }
+ {
+ let read_unit2 = read_units.next().unwrap().unwrap();
+ assert_eq!(
+ read_unit2.offset(),
+ debug_info_offsets.unit(unit_id2).into()
+ );
+
+ let abbrevs = dwarf.abbreviations(&read_unit2).unwrap();
+ let mut read_entries = read_unit2.entries(&abbrevs);
+ {
+ let (_, _read_root) = read_entries.next_dfs().unwrap().unwrap();
+ }
+ {
+ let (_, read_child1) = read_entries.next_dfs().unwrap().unwrap();
+ let offset = debug_info_offsets
+ .entry(unit_id2, unit2_child2)
+ .to_unit_offset(&read_unit2)
+ .unwrap();
+ assert_eq!(
+ read_child1.attr_value(constants::DW_AT_type).unwrap(),
+ Some(read::AttributeValue::UnitRef(offset))
+ );
+ }
+ {
+ let (_, read_child2) = read_entries.next_dfs().unwrap().unwrap();
+ let offset = debug_info_offsets.entry(unit_id1, unit1_child1);
+ assert_eq!(
+ read_child2.attr_value(constants::DW_AT_type).unwrap(),
+ Some(read::AttributeValue::DebugInfoRef(offset))
+ );
+ }
+ }
+
+ let mut convert_line_strings = LineStringTable::default();
+ let mut convert_strings = StringTable::default();
+ let convert_units = UnitTable::from(
+ &dwarf,
+ &mut convert_line_strings,
+ &mut convert_strings,
+ &|address| Some(Address::Constant(address)),
+ )
+ .unwrap();
+ assert_eq!(convert_units.count(), units.count());
+
+ for i in 0..convert_units.count() {
+ let unit = units.get(units.id(i));
+ let convert_unit = convert_units.get(convert_units.id(i));
+ assert_eq!(convert_unit.version(), unit.version());
+ assert_eq!(convert_unit.address_size(), unit.address_size());
+ assert_eq!(convert_unit.format(), unit.format());
+ assert_eq!(convert_unit.count(), unit.count());
+
+ let root = unit.get(unit.root());
+ let convert_root = convert_unit.get(convert_unit.root());
+ assert_eq!(convert_root.tag(), root.tag());
+ for (convert_attr, attr) in convert_root.attrs().zip(root.attrs()) {
+ assert_eq!(convert_attr, attr);
+ }
+
+ let child1 = unit.get(UnitEntryId::new(unit.base_id, 1));
+ let convert_child1 = convert_unit.get(UnitEntryId::new(convert_unit.base_id, 1));
+ assert_eq!(convert_child1.tag(), child1.tag());
+ for (convert_attr, attr) in convert_child1.attrs().zip(child1.attrs()) {
+ assert_eq!(convert_attr.name, attr.name);
+ match (convert_attr.value.clone(), attr.value.clone()) {
+ (
+ AttributeValue::DebugInfoRef(Reference::Entry(convert_unit, convert_entry)),
+ AttributeValue::DebugInfoRef(Reference::Entry(unit, entry)),
+ ) => {
+ assert_eq!(convert_unit.index, unit.index);
+ assert_eq!(convert_entry.index, entry.index);
+ }
+ (AttributeValue::UnitRef(convert_id), AttributeValue::UnitRef(id)) => {
+ assert_eq!(convert_id.index, id.index);
+ }
+ (convert_value, value) => assert_eq!(convert_value, value),
+ }
+ }
+
+ let child2 = unit.get(UnitEntryId::new(unit.base_id, 2));
+ let convert_child2 = convert_unit.get(UnitEntryId::new(convert_unit.base_id, 2));
+ assert_eq!(convert_child2.tag(), child2.tag());
+ for (convert_attr, attr) in convert_child2.attrs().zip(child2.attrs()) {
+ assert_eq!(convert_attr.name, attr.name);
+ match (convert_attr.value.clone(), attr.value.clone()) {
+ (
+ AttributeValue::DebugInfoRef(Reference::Entry(convert_unit, convert_entry)),
+ AttributeValue::DebugInfoRef(Reference::Entry(unit, entry)),
+ ) => {
+ assert_eq!(convert_unit.index, unit.index);
+ assert_eq!(convert_entry.index, entry.index);
+ }
+ (AttributeValue::UnitRef(convert_id), AttributeValue::UnitRef(id)) => {
+ assert_eq!(convert_id.index, id.index);
+ }
+ (convert_value, value) => assert_eq!(convert_value, value),
+ }
+ }
+ }
+ }
+
+ #[test]
+ fn test_sibling() {
+ fn add_child(
+ unit: &mut Unit,
+ parent: UnitEntryId,
+ tag: constants::DwTag,
+ name: &str,
+ ) -> UnitEntryId {
+ let id = unit.add(parent, tag);
+ let child = unit.get_mut(id);
+ child.set(constants::DW_AT_name, AttributeValue::String(name.into()));
+ child.set_sibling(true);
+ id
+ }
+
+ fn add_children(units: &mut UnitTable, unit_id: UnitId) {
+ let unit = units.get_mut(unit_id);
+ let root = unit.root();
+ let child1 = add_child(unit, root, constants::DW_TAG_subprogram, "child1");
+ add_child(unit, child1, constants::DW_TAG_variable, "grandchild1");
+ add_child(unit, root, constants::DW_TAG_subprogram, "child2");
+ add_child(unit, root, constants::DW_TAG_subprogram, "child3");
+ }
+
+ fn next_child<R: read::Reader<Offset = usize>>(
+ entries: &mut read::EntriesCursor<R>,
+ ) -> (read::UnitOffset, Option<read::UnitOffset>) {
+ let (_, entry) = entries.next_dfs().unwrap().unwrap();
+ let offset = entry.offset();
+ let sibling =
+ entry
+ .attr_value(constants::DW_AT_sibling)
+ .unwrap()
+ .map(|attr| match attr {
+ read::AttributeValue::UnitRef(offset) => offset,
+ _ => panic!("bad sibling value"),
+ });
+ (offset, sibling)
+ }
+
+ fn check_sibling<R: read::Reader<Offset = usize>>(
+ unit: &read::UnitHeader<R>,
+ debug_abbrev: &read::DebugAbbrev<R>,
+ ) {
+ let abbrevs = unit.abbreviations(debug_abbrev).unwrap();
+ let mut entries = unit.entries(&abbrevs);
+ // root
+ entries.next_dfs().unwrap().unwrap();
+ // child1
+ let (_, sibling1) = next_child(&mut entries);
+ // grandchild1
+ entries.next_dfs().unwrap().unwrap();
+ // child2
+ let (offset2, sibling2) = next_child(&mut entries);
+ // child3
+ let (_, _) = next_child(&mut entries);
+ assert_eq!(sibling1, Some(offset2));
+ assert_eq!(sibling2, None);
+ }
+
+ let encoding = Encoding {
+ format: Format::Dwarf32,
+ version: 4,
+ address_size: 8,
+ };
+ let mut units = UnitTable::default();
+ let unit_id1 = units.add(Unit::new(encoding, LineProgram::none()));
+ add_children(&mut units, unit_id1);
+ let unit_id2 = units.add(Unit::new(encoding, LineProgram::none()));
+ add_children(&mut units, unit_id2);
+
+ let debug_line_str_offsets = DebugLineStrOffsets::none();
+ let debug_str_offsets = DebugStrOffsets::none();
+ let mut sections = Sections::new(EndianVec::new(LittleEndian));
+ units
+ .write(&mut sections, &debug_line_str_offsets, &debug_str_offsets)
+ .unwrap();
+
+ println!("{:?}", sections.debug_info);
+ println!("{:?}", sections.debug_abbrev);
+
+ let read_debug_info = read::DebugInfo::new(sections.debug_info.slice(), LittleEndian);
+ let read_debug_abbrev = read::DebugAbbrev::new(sections.debug_abbrev.slice(), LittleEndian);
+ let mut read_units = read_debug_info.units();
+ check_sibling(&read_units.next().unwrap().unwrap(), &read_debug_abbrev);
+ check_sibling(&read_units.next().unwrap().unwrap(), &read_debug_abbrev);
+ }
+
+ #[test]
+ fn test_line_ref() {
+ for &version in &[2, 3, 4, 5] {
+ for &address_size in &[4, 8] {
+ for &format in &[Format::Dwarf32, Format::Dwarf64] {
+ let encoding = Encoding {
+ format,
+ version,
+ address_size,
+ };
+
+ // The line program we'll be referencing.
+ let mut line_program = LineProgram::new(
+ encoding,
+ LineEncoding::default(),
+ LineString::String(b"comp_dir".to_vec()),
+ LineString::String(b"comp_name".to_vec()),
+ None,
+ );
+ let dir = line_program.default_directory();
+ let file1 =
+ line_program.add_file(LineString::String(b"file1".to_vec()), dir, None);
+ let file2 =
+ line_program.add_file(LineString::String(b"file2".to_vec()), dir, None);
+
+ // Write, read, and convert the line program, so that we have the info
+ // required to convert the attributes.
+ let line_strings = DebugLineStrOffsets::none();
+ let strings = DebugStrOffsets::none();
+ let mut debug_line = DebugLine::from(EndianVec::new(LittleEndian));
+ let line_program_offset = line_program
+ .write(&mut debug_line, encoding, &line_strings, &strings)
+ .unwrap();
+ let read_debug_line = read::DebugLine::new(debug_line.slice(), LittleEndian);
+ let read_line_program = read_debug_line
+ .program(
+ line_program_offset,
+ address_size,
+ Some(read::EndianSlice::new(b"comp_dir", LittleEndian)),
+ Some(read::EndianSlice::new(b"comp_name", LittleEndian)),
+ )
+ .unwrap();
+ let dwarf = read::Dwarf::default();
+ let mut convert_line_strings = LineStringTable::default();
+ let mut convert_strings = StringTable::default();
+ let (_, line_program_files) = LineProgram::from(
+ read_line_program,
+ &dwarf,
+ &mut convert_line_strings,
+ &mut convert_strings,
+ &|address| Some(Address::Constant(address)),
+ )
+ .unwrap();
+
+ // Fake the unit.
+ let mut units = UnitTable::default();
+ let unit = units.add(Unit::new(encoding, LineProgram::none()));
+ let unit = units.get(unit);
+ let from_unit = read::UnitHeader::new(
+ encoding,
+ 0,
+ read::UnitType::Compilation,
+ DebugAbbrevOffset(0),
+ DebugInfoOffset(0).into(),
+ read::EndianSlice::new(&[], LittleEndian),
+ );
+
+ for &(ref name, ref value, ref expect_value) in &[
+ (
+ constants::DW_AT_stmt_list,
+ AttributeValue::LineProgramRef,
+ read::AttributeValue::SecOffset(line_program_offset.0),
+ ),
+ (
+ constants::DW_AT_decl_file,
+ AttributeValue::FileIndex(Some(file1)),
+ read::AttributeValue::Udata(file1.raw()),
+ ),
+ (
+ constants::DW_AT_decl_file,
+ AttributeValue::FileIndex(Some(file2)),
+ read::AttributeValue::Udata(file2.raw()),
+ ),
+ ][..]
+ {
+ let mut ranges = RangeListTable::default();
+ let mut locations = LocationListTable::default();
+ let mut strings = StringTable::default();
+ let mut line_strings = LineStringTable::default();
+
+ let form = value.form(encoding).unwrap();
+ let attr = Attribute {
+ name: *name,
+ value: value.clone(),
+ };
+
+ let mut debug_info_refs = Vec::new();
+ let mut unit_refs = Vec::new();
+ let mut debug_info = DebugInfo::from(EndianVec::new(LittleEndian));
+ let offsets = UnitOffsets::none();
+ let debug_line_str_offsets = DebugLineStrOffsets::none();
+ let debug_str_offsets = DebugStrOffsets::none();
+ let range_list_offsets = RangeListOffsets::none();
+ let loc_list_offsets = LocationListOffsets::none();
+ attr.value
+ .write(
+ &mut debug_info,
+ &mut debug_info_refs,
+ &mut unit_refs,
+ &unit,
+ &offsets,
+ Some(line_program_offset),
+ &debug_line_str_offsets,
+ &debug_str_offsets,
+ &range_list_offsets,
+ &loc_list_offsets,
+ )
+ .unwrap();
+
+ let spec = read::AttributeSpecification::new(*name, form, None);
+ let mut r = read::EndianSlice::new(debug_info.slice(), LittleEndian);
+ let read_attr = read::parse_attribute(&mut r, encoding, spec).unwrap();
+ let read_value = &read_attr.raw_value();
+ // read::AttributeValue is invariant in the lifetime of R.
+ // The lifetimes here are all okay, so transmute it.
+ let read_value = unsafe {
+ mem::transmute::<
+ &read::AttributeValue<read::EndianSlice<LittleEndian>>,
+ &read::AttributeValue<read::EndianSlice<LittleEndian>>,
+ >(read_value)
+ };
+ assert_eq!(read_value, expect_value);
+
+ let unit = read::Unit {
+ header: from_unit,
+ abbreviations: read::Abbreviations::default(),
+ name: None,
+ comp_dir: None,
+ low_pc: 0,
+ str_offsets_base: DebugStrOffsetsBase(0),
+ addr_base: DebugAddrBase(0),
+ loclists_base: DebugLocListsBase(0),
+ rnglists_base: DebugRngListsBase(0),
+ line_program: None,
+ dwo_id: None,
+ };
+
+ let mut context = convert::ConvertUnitContext {
+ dwarf: &dwarf,
+ unit: &unit,
+ line_strings: &mut line_strings,
+ strings: &mut strings,
+ ranges: &mut ranges,
+ locations: &mut locations,
+ convert_address: &|address| Some(Address::Constant(address)),
+ base_address: Address::Constant(0),
+ line_program_offset: Some(line_program_offset),
+ line_program_files: line_program_files.clone(),
+ entry_ids: &HashMap::new(),
+ };
+
+ let convert_attr =
+ Attribute::from(&mut context, &read_attr).unwrap().unwrap();
+ assert_eq!(convert_attr, attr);
+ }
+ }
+ }
+ }
+ }
+
+ #[test]
+ fn test_line_program_used() {
+ for used in vec![false, true] {
+ let encoding = Encoding {
+ format: Format::Dwarf32,
+ version: 5,
+ address_size: 8,
+ };
+
+ let line_program = LineProgram::new(
+ encoding,
+ LineEncoding::default(),
+ LineString::String(b"comp_dir".to_vec()),
+ LineString::String(b"comp_name".to_vec()),
+ None,
+ );
+
+ let mut unit = Unit::new(encoding, line_program);
+ let file_id = if used { Some(FileId::new(0)) } else { None };
+ let root = unit.root();
+ unit.get_mut(root).set(
+ constants::DW_AT_decl_file,
+ AttributeValue::FileIndex(file_id),
+ );
+
+ let mut units = UnitTable::default();
+ units.add(unit);
+
+ let debug_line_str_offsets = DebugLineStrOffsets::none();
+ let debug_str_offsets = DebugStrOffsets::none();
+ let mut sections = Sections::new(EndianVec::new(LittleEndian));
+ units
+ .write(&mut sections, &debug_line_str_offsets, &debug_str_offsets)
+ .unwrap();
+ assert_eq!(!used, sections.debug_line.slice().is_empty());
+ }
+ }
+
+ #[test]
+ fn test_delete_child() {
+ fn set_name(unit: &mut Unit, id: UnitEntryId, name: &str) {
+ let entry = unit.get_mut(id);
+ entry.set(constants::DW_AT_name, AttributeValue::String(name.into()));
+ }
+ fn check_name<R: read::Reader>(
+ entry: &read::DebuggingInformationEntry<R>,
+ debug_str: &read::DebugStr<R>,
+ name: &str,
+ ) {
+ let name_attr = entry.attr(constants::DW_AT_name).unwrap().unwrap();
+ let entry_name = name_attr.string_value(debug_str).unwrap();
+ let entry_name_str = entry_name.to_string().unwrap();
+ assert_eq!(entry_name_str, name);
+ }
+ let encoding = Encoding {
+ format: Format::Dwarf32,
+ version: 4,
+ address_size: 8,
+ };
+ let mut dwarf = DwarfUnit::new(encoding);
+ let root = dwarf.unit.root();
+
+ // Add and delete entries in the root unit
+ let child1 = dwarf.unit.add(root, constants::DW_TAG_subprogram);
+ set_name(&mut dwarf.unit, child1, "child1");
+ let grandchild1 = dwarf.unit.add(child1, constants::DW_TAG_variable);
+ set_name(&mut dwarf.unit, grandchild1, "grandchild1");
+ let child2 = dwarf.unit.add(root, constants::DW_TAG_subprogram);
+ set_name(&mut dwarf.unit, child2, "child2");
+ // This deletes both `child1` and its child `grandchild1`
+ dwarf.unit.get_mut(root).delete_child(child1);
+ let child3 = dwarf.unit.add(root, constants::DW_TAG_subprogram);
+ set_name(&mut dwarf.unit, child3, "child3");
+ let child4 = dwarf.unit.add(root, constants::DW_TAG_subprogram);
+ set_name(&mut dwarf.unit, child4, "child4");
+ let grandchild4 = dwarf.unit.add(child4, constants::DW_TAG_variable);
+ set_name(&mut dwarf.unit, grandchild4, "grandchild4");
+ dwarf.unit.get_mut(child4).delete_child(grandchild4);
+
+ let mut sections = Sections::new(EndianVec::new(LittleEndian));
+
+ // Write DWARF data which should only include `child2`, `child3` and `child4`
+ dwarf.write(&mut sections).unwrap();
+
+ let read_debug_info = read::DebugInfo::new(sections.debug_info.slice(), LittleEndian);
+ let read_debug_abbrev = read::DebugAbbrev::new(sections.debug_abbrev.slice(), LittleEndian);
+ let read_debug_str = read::DebugStr::new(sections.debug_str.slice(), LittleEndian);
+ let read_unit = read_debug_info.units().next().unwrap().unwrap();
+ let abbrevs = read_unit.abbreviations(&read_debug_abbrev).unwrap();
+ let mut entries = read_unit.entries(&abbrevs);
+ // root
+ entries.next_dfs().unwrap().unwrap();
+ // child2
+ let (_, read_child2) = entries.next_dfs().unwrap().unwrap();
+ check_name(read_child2, &read_debug_str, "child2");
+ // child3
+ let (_, read_child3) = entries.next_dfs().unwrap().unwrap();
+ check_name(read_child3, &read_debug_str, "child3");
+ // child4
+ let (_, read_child4) = entries.next_dfs().unwrap().unwrap();
+ check_name(read_child4, &read_debug_str, "child4");
+ // There should be no more entries
+ assert!(entries.next_dfs().unwrap().is_none());
+ }
+}
diff --git a/vendor/gimli-0.26.2/src/write/writer.rs b/vendor/gimli-0.26.2/src/write/writer.rs
new file mode 100644
index 000000000..0785d1686
--- /dev/null
+++ b/vendor/gimli-0.26.2/src/write/writer.rs
@@ -0,0 +1,497 @@
+use crate::common::{Format, SectionId};
+use crate::constants;
+use crate::endianity::Endianity;
+use crate::leb128;
+use crate::write::{Address, Error, Result};
+
+/// A trait for writing the data to a DWARF section.
+///
+/// All write operations append to the section unless otherwise specified.
+#[allow(clippy::len_without_is_empty)]
+pub trait Writer {
+ /// The endianity of bytes that are written.
+ type Endian: Endianity;
+
+ /// Return the endianity of bytes that are written.
+ fn endian(&self) -> Self::Endian;
+
+ /// Return the current section length.
+ ///
+ /// This may be used as an offset for future `write_at` calls.
+ fn len(&self) -> usize;
+
+ /// Write a slice.
+ fn write(&mut self, bytes: &[u8]) -> Result<()>;
+
+ /// Write a slice at a given offset.
+ ///
+ /// The write must not extend past the current section length.
+ fn write_at(&mut self, offset: usize, bytes: &[u8]) -> Result<()>;
+
+ /// Write an address.
+ ///
+ /// If the writer supports relocations, then it must provide its own implementation
+ /// of this method.
+ // TODO: use write_reference instead?
+ fn write_address(&mut self, address: Address, size: u8) -> Result<()> {
+ match address {
+ Address::Constant(val) => self.write_udata(val, size),
+ Address::Symbol { .. } => Err(Error::InvalidAddress),
+ }
+ }
+
+ /// Write an address with a `.eh_frame` pointer encoding.
+ ///
+ /// The given size is only used for `DW_EH_PE_absptr` formats.
+ ///
+ /// If the writer supports relocations, then it must provide its own implementation
+ /// of this method.
+ fn write_eh_pointer(
+ &mut self,
+ address: Address,
+ eh_pe: constants::DwEhPe,
+ size: u8,
+ ) -> Result<()> {
+ match address {
+ Address::Constant(val) => {
+ // Indirect doesn't matter here.
+ let val = match eh_pe.application() {
+ constants::DW_EH_PE_absptr => val,
+ constants::DW_EH_PE_pcrel => {
+ // TODO: better handling of sign
+ let offset = self.len() as u64;
+ val.wrapping_sub(offset)
+ }
+ _ => {
+ return Err(Error::UnsupportedPointerEncoding(eh_pe));
+ }
+ };
+ self.write_eh_pointer_data(val, eh_pe.format(), size)
+ }
+ Address::Symbol { .. } => Err(Error::InvalidAddress),
+ }
+ }
+
+ /// Write a value with a `.eh_frame` pointer format.
+ ///
+ /// The given size is only used for `DW_EH_PE_absptr` formats.
+ ///
+ /// This must not be used directly for values that may require relocation.
+ fn write_eh_pointer_data(
+ &mut self,
+ val: u64,
+ format: constants::DwEhPe,
+ size: u8,
+ ) -> Result<()> {
+ match format {
+ constants::DW_EH_PE_absptr => self.write_udata(val, size),
+ constants::DW_EH_PE_uleb128 => self.write_uleb128(val),
+ constants::DW_EH_PE_udata2 => self.write_udata(val, 2),
+ constants::DW_EH_PE_udata4 => self.write_udata(val, 4),
+ constants::DW_EH_PE_udata8 => self.write_udata(val, 8),
+ constants::DW_EH_PE_sleb128 => self.write_sleb128(val as i64),
+ constants::DW_EH_PE_sdata2 => self.write_sdata(val as i64, 2),
+ constants::DW_EH_PE_sdata4 => self.write_sdata(val as i64, 4),
+ constants::DW_EH_PE_sdata8 => self.write_sdata(val as i64, 8),
+ _ => {
+ return Err(Error::UnsupportedPointerEncoding(format));
+ }
+ }
+ }
+
+ /// Write an offset that is relative to the start of the given section.
+ ///
+ /// If the writer supports relocations, then it must provide its own implementation
+ /// of this method.
+ fn write_offset(&mut self, val: usize, _section: SectionId, size: u8) -> Result<()> {
+ self.write_udata(val as u64, size)
+ }
+
+ /// Write an offset that is relative to the start of the given section.
+ ///
+ /// If the writer supports relocations, then it must provide its own implementation
+ /// of this method.
+ fn write_offset_at(
+ &mut self,
+ offset: usize,
+ val: usize,
+ _section: SectionId,
+ size: u8,
+ ) -> Result<()> {
+ self.write_udata_at(offset, val as u64, size)
+ }
+
+ /// Write a reference to a symbol.
+ ///
+ /// If the writer supports symbols, then it must provide its own implementation
+ /// of this method.
+ fn write_reference(&mut self, _symbol: usize, _size: u8) -> Result<()> {
+ Err(Error::InvalidReference)
+ }
+
+ /// Write a u8.
+ fn write_u8(&mut self, val: u8) -> Result<()> {
+ let bytes = [val];
+ self.write(&bytes)
+ }
+
+ /// Write a u16.
+ fn write_u16(&mut self, val: u16) -> Result<()> {
+ let mut bytes = [0; 2];
+ self.endian().write_u16(&mut bytes, val);
+ self.write(&bytes)
+ }
+
+ /// Write a u32.
+ fn write_u32(&mut self, val: u32) -> Result<()> {
+ let mut bytes = [0; 4];
+ self.endian().write_u32(&mut bytes, val);
+ self.write(&bytes)
+ }
+
+ /// Write a u64.
+ fn write_u64(&mut self, val: u64) -> Result<()> {
+ let mut bytes = [0; 8];
+ self.endian().write_u64(&mut bytes, val);
+ self.write(&bytes)
+ }
+
+ /// Write a u8 at the given offset.
+ fn write_u8_at(&mut self, offset: usize, val: u8) -> Result<()> {
+ let bytes = [val];
+ self.write_at(offset, &bytes)
+ }
+
+ /// Write a u16 at the given offset.
+ fn write_u16_at(&mut self, offset: usize, val: u16) -> Result<()> {
+ let mut bytes = [0; 2];
+ self.endian().write_u16(&mut bytes, val);
+ self.write_at(offset, &bytes)
+ }
+
+ /// Write a u32 at the given offset.
+ fn write_u32_at(&mut self, offset: usize, val: u32) -> Result<()> {
+ let mut bytes = [0; 4];
+ self.endian().write_u32(&mut bytes, val);
+ self.write_at(offset, &bytes)
+ }
+
+ /// Write a u64 at the given offset.
+ fn write_u64_at(&mut self, offset: usize, val: u64) -> Result<()> {
+ let mut bytes = [0; 8];
+ self.endian().write_u64(&mut bytes, val);
+ self.write_at(offset, &bytes)
+ }
+
+ /// Write unsigned data of the given size.
+ ///
+ /// Returns an error if the value is too large for the size.
+ /// This must not be used directly for values that may require relocation.
+ fn write_udata(&mut self, val: u64, size: u8) -> Result<()> {
+ match size {
+ 1 => {
+ let write_val = val as u8;
+ if val != u64::from(write_val) {
+ return Err(Error::ValueTooLarge);
+ }
+ self.write_u8(write_val)
+ }
+ 2 => {
+ let write_val = val as u16;
+ if val != u64::from(write_val) {
+ return Err(Error::ValueTooLarge);
+ }
+ self.write_u16(write_val)
+ }
+ 4 => {
+ let write_val = val as u32;
+ if val != u64::from(write_val) {
+ return Err(Error::ValueTooLarge);
+ }
+ self.write_u32(write_val)
+ }
+ 8 => self.write_u64(val),
+ otherwise => Err(Error::UnsupportedWordSize(otherwise)),
+ }
+ }
+
+ /// Write signed data of the given size.
+ ///
+ /// Returns an error if the value is too large for the size.
+ /// This must not be used directly for values that may require relocation.
+ fn write_sdata(&mut self, val: i64, size: u8) -> Result<()> {
+ match size {
+ 1 => {
+ let write_val = val as i8;
+ if val != i64::from(write_val) {
+ return Err(Error::ValueTooLarge);
+ }
+ self.write_u8(write_val as u8)
+ }
+ 2 => {
+ let write_val = val as i16;
+ if val != i64::from(write_val) {
+ return Err(Error::ValueTooLarge);
+ }
+ self.write_u16(write_val as u16)
+ }
+ 4 => {
+ let write_val = val as i32;
+ if val != i64::from(write_val) {
+ return Err(Error::ValueTooLarge);
+ }
+ self.write_u32(write_val as u32)
+ }
+ 8 => self.write_u64(val as u64),
+ otherwise => Err(Error::UnsupportedWordSize(otherwise)),
+ }
+ }
+
+ /// Write a word of the given size at the given offset.
+ ///
+ /// Returns an error if the value is too large for the size.
+ /// This must not be used directly for values that may require relocation.
+ fn write_udata_at(&mut self, offset: usize, val: u64, size: u8) -> Result<()> {
+ match size {
+ 1 => {
+ let write_val = val as u8;
+ if val != u64::from(write_val) {
+ return Err(Error::ValueTooLarge);
+ }
+ self.write_u8_at(offset, write_val)
+ }
+ 2 => {
+ let write_val = val as u16;
+ if val != u64::from(write_val) {
+ return Err(Error::ValueTooLarge);
+ }
+ self.write_u16_at(offset, write_val)
+ }
+ 4 => {
+ let write_val = val as u32;
+ if val != u64::from(write_val) {
+ return Err(Error::ValueTooLarge);
+ }
+ self.write_u32_at(offset, write_val)
+ }
+ 8 => self.write_u64_at(offset, val),
+ otherwise => Err(Error::UnsupportedWordSize(otherwise)),
+ }
+ }
+
+ /// Write an unsigned LEB128 encoded integer.
+ fn write_uleb128(&mut self, val: u64) -> Result<()> {
+ let mut bytes = [0u8; 10];
+ // bytes is long enough so this will never fail.
+ let len = leb128::write::unsigned(&mut { &mut bytes[..] }, val).unwrap();
+ self.write(&bytes[..len])
+ }
+
+ /// Read an unsigned LEB128 encoded integer.
+ fn write_sleb128(&mut self, val: i64) -> Result<()> {
+ let mut bytes = [0u8; 10];
+ // bytes is long enough so this will never fail.
+ let len = leb128::write::signed(&mut { &mut bytes[..] }, val).unwrap();
+ self.write(&bytes[..len])
+ }
+
+ /// Write an initial length according to the given DWARF format.
+ ///
+ /// This will only write a length of zero, since the length isn't
+ /// known yet, and a subsequent call to `write_initial_length_at`
+ /// will write the actual length.
+ fn write_initial_length(&mut self, format: Format) -> Result<InitialLengthOffset> {
+ if format == Format::Dwarf64 {
+ self.write_u32(0xffff_ffff)?;
+ }
+ let offset = InitialLengthOffset(self.len());
+ self.write_udata(0, format.word_size())?;
+ Ok(offset)
+ }
+
+ /// Write an initial length at the given offset according to the given DWARF format.
+ ///
+ /// `write_initial_length` must have previously returned the offset.
+ fn write_initial_length_at(
+ &mut self,
+ offset: InitialLengthOffset,
+ length: u64,
+ format: Format,
+ ) -> Result<()> {
+ self.write_udata_at(offset.0, length, format.word_size())
+ }
+}
+
+/// The offset at which an initial length should be written.
+#[derive(Debug, Clone, Copy)]
+pub struct InitialLengthOffset(usize);
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+ use crate::write;
+ use crate::{BigEndian, LittleEndian};
+ use std::{i64, u64};
+
+ #[test]
+ #[allow(clippy::cyclomatic_complexity)]
+ fn test_writer() {
+ let mut w = write::EndianVec::new(LittleEndian);
+ w.write_address(Address::Constant(0x1122_3344), 4).unwrap();
+ assert_eq!(w.slice(), &[0x44, 0x33, 0x22, 0x11]);
+ assert_eq!(
+ w.write_address(
+ Address::Symbol {
+ symbol: 0,
+ addend: 0
+ },
+ 4
+ ),
+ Err(Error::InvalidAddress)
+ );
+
+ let mut w = write::EndianVec::new(LittleEndian);
+ w.write_offset(0x1122_3344, SectionId::DebugInfo, 4)
+ .unwrap();
+ assert_eq!(w.slice(), &[0x44, 0x33, 0x22, 0x11]);
+ w.write_offset_at(1, 0x5566, SectionId::DebugInfo, 2)
+ .unwrap();
+ assert_eq!(w.slice(), &[0x44, 0x66, 0x55, 0x11]);
+
+ let mut w = write::EndianVec::new(LittleEndian);
+ w.write_u8(0x11).unwrap();
+ w.write_u16(0x2233).unwrap();
+ w.write_u32(0x4455_6677).unwrap();
+ w.write_u64(0x8081_8283_8485_8687).unwrap();
+ #[rustfmt::skip]
+ assert_eq!(w.slice(), &[
+ 0x11,
+ 0x33, 0x22,
+ 0x77, 0x66, 0x55, 0x44,
+ 0x87, 0x86, 0x85, 0x84, 0x83, 0x82, 0x81, 0x80,
+ ]);
+ w.write_u8_at(14, 0x11).unwrap();
+ w.write_u16_at(12, 0x2233).unwrap();
+ w.write_u32_at(8, 0x4455_6677).unwrap();
+ w.write_u64_at(0, 0x8081_8283_8485_8687).unwrap();
+ #[rustfmt::skip]
+ assert_eq!(w.slice(), &[
+ 0x87, 0x86, 0x85, 0x84, 0x83, 0x82, 0x81, 0x80,
+ 0x77, 0x66, 0x55, 0x44,
+ 0x33, 0x22,
+ 0x11,
+ ]);
+
+ let mut w = write::EndianVec::new(BigEndian);
+ w.write_u8(0x11).unwrap();
+ w.write_u16(0x2233).unwrap();
+ w.write_u32(0x4455_6677).unwrap();
+ w.write_u64(0x8081_8283_8485_8687).unwrap();
+ #[rustfmt::skip]
+ assert_eq!(w.slice(), &[
+ 0x11,
+ 0x22, 0x33,
+ 0x44, 0x55, 0x66, 0x77,
+ 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
+ ]);
+ w.write_u8_at(14, 0x11).unwrap();
+ w.write_u16_at(12, 0x2233).unwrap();
+ w.write_u32_at(8, 0x4455_6677).unwrap();
+ w.write_u64_at(0, 0x8081_8283_8485_8687).unwrap();
+ #[rustfmt::skip]
+ assert_eq!(w.slice(), &[
+ 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
+ 0x44, 0x55, 0x66, 0x77,
+ 0x22, 0x33,
+ 0x11,
+ ]);
+
+ let mut w = write::EndianVec::new(LittleEndian);
+ w.write_udata(0x11, 1).unwrap();
+ w.write_udata(0x2233, 2).unwrap();
+ w.write_udata(0x4455_6677, 4).unwrap();
+ w.write_udata(0x8081_8283_8485_8687, 8).unwrap();
+ #[rustfmt::skip]
+ assert_eq!(w.slice(), &[
+ 0x11,
+ 0x33, 0x22,
+ 0x77, 0x66, 0x55, 0x44,
+ 0x87, 0x86, 0x85, 0x84, 0x83, 0x82, 0x81, 0x80,
+ ]);
+ assert_eq!(w.write_udata(0x100, 1), Err(Error::ValueTooLarge));
+ assert_eq!(w.write_udata(0x1_0000, 2), Err(Error::ValueTooLarge));
+ assert_eq!(w.write_udata(0x1_0000_0000, 4), Err(Error::ValueTooLarge));
+ assert_eq!(w.write_udata(0x00, 3), Err(Error::UnsupportedWordSize(3)));
+ w.write_udata_at(14, 0x11, 1).unwrap();
+ w.write_udata_at(12, 0x2233, 2).unwrap();
+ w.write_udata_at(8, 0x4455_6677, 4).unwrap();
+ w.write_udata_at(0, 0x8081_8283_8485_8687, 8).unwrap();
+ #[rustfmt::skip]
+ assert_eq!(w.slice(), &[
+ 0x87, 0x86, 0x85, 0x84, 0x83, 0x82, 0x81, 0x80,
+ 0x77, 0x66, 0x55, 0x44,
+ 0x33, 0x22,
+ 0x11,
+ ]);
+ assert_eq!(w.write_udata_at(0, 0x100, 1), Err(Error::ValueTooLarge));
+ assert_eq!(w.write_udata_at(0, 0x1_0000, 2), Err(Error::ValueTooLarge));
+ assert_eq!(
+ w.write_udata_at(0, 0x1_0000_0000, 4),
+ Err(Error::ValueTooLarge)
+ );
+ assert_eq!(
+ w.write_udata_at(0, 0x00, 3),
+ Err(Error::UnsupportedWordSize(3))
+ );
+
+ let mut w = write::EndianVec::new(LittleEndian);
+ w.write_uleb128(0).unwrap();
+ assert_eq!(w.slice(), &[0]);
+
+ let mut w = write::EndianVec::new(LittleEndian);
+ w.write_uleb128(u64::MAX).unwrap();
+ assert_eq!(
+ w.slice(),
+ &[0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 1]
+ );
+
+ let mut w = write::EndianVec::new(LittleEndian);
+ w.write_sleb128(0).unwrap();
+ assert_eq!(w.slice(), &[0]);
+
+ let mut w = write::EndianVec::new(LittleEndian);
+ w.write_sleb128(i64::MAX).unwrap();
+ assert_eq!(
+ w.slice(),
+ &[0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0]
+ );
+
+ let mut w = write::EndianVec::new(LittleEndian);
+ w.write_sleb128(i64::MIN).unwrap();
+ assert_eq!(
+ w.slice(),
+ &[0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x7f]
+ );
+
+ let mut w = write::EndianVec::new(LittleEndian);
+ let offset = w.write_initial_length(Format::Dwarf32).unwrap();
+ assert_eq!(w.slice(), &[0, 0, 0, 0]);
+ w.write_initial_length_at(offset, 0x1122_3344, Format::Dwarf32)
+ .unwrap();
+ assert_eq!(w.slice(), &[0x44, 0x33, 0x22, 0x11]);
+ assert_eq!(
+ w.write_initial_length_at(offset, 0x1_0000_0000, Format::Dwarf32),
+ Err(Error::ValueTooLarge)
+ );
+
+ let mut w = write::EndianVec::new(LittleEndian);
+ let offset = w.write_initial_length(Format::Dwarf64).unwrap();
+ assert_eq!(w.slice(), &[0xff, 0xff, 0xff, 0xff, 0, 0, 0, 0, 0, 0, 0, 0]);
+ w.write_initial_length_at(offset, 0x1122_3344_5566_7788, Format::Dwarf64)
+ .unwrap();
+ assert_eq!(
+ w.slice(),
+ &[0xff, 0xff, 0xff, 0xff, 0x88, 0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11]
+ );
+ }
+}
diff --git a/vendor/gimli-0.26.2/tests/convert_self.rs b/vendor/gimli-0.26.2/tests/convert_self.rs
new file mode 100644
index 000000000..7c069ebd6
--- /dev/null
+++ b/vendor/gimli-0.26.2/tests/convert_self.rs
@@ -0,0 +1,158 @@
+#![cfg(all(feature = "read", feature = "write"))]
+
+use std::env;
+use std::fs::File;
+use std::io::Read;
+use std::path::PathBuf;
+
+use gimli::read;
+use gimli::write::{self, Address, EndianVec};
+use gimli::LittleEndian;
+
+fn read_section(section: &str) -> Vec<u8> {
+ let mut path = PathBuf::new();
+ if let Ok(dir) = env::var("CARGO_MANIFEST_DIR") {
+ path.push(dir);
+ }
+ path.push("fixtures/self");
+ path.push(section);
+
+ println!("Reading section \"{}\" at path {:?}", section, path);
+ assert!(path.is_file());
+ let mut file = File::open(path).unwrap();
+
+ let mut buf = Vec::new();
+ file.read_to_end(&mut buf).unwrap();
+ buf
+}
+
+#[test]
+fn test_convert_debug_info() {
+ // Convert existing sections
+ let debug_abbrev = read_section("debug_abbrev");
+ let debug_abbrev = read::DebugAbbrev::new(&debug_abbrev, LittleEndian);
+
+ let debug_info = read_section("debug_info");
+ let debug_info = read::DebugInfo::new(&debug_info, LittleEndian);
+
+ let debug_line = read_section("debug_line");
+ let debug_line = read::DebugLine::new(&debug_line, LittleEndian);
+
+ let debug_str = read_section("debug_str");
+ let debug_str = read::DebugStr::new(&debug_str, LittleEndian);
+
+ let debug_ranges = read_section("debug_ranges");
+ let debug_ranges = read::DebugRanges::new(&debug_ranges, LittleEndian);
+
+ let debug_rnglists = read::DebugRngLists::new(&[], LittleEndian);
+
+ let ranges = gimli::RangeLists::new(debug_ranges, debug_rnglists);
+
+ let debug_loc = read_section("debug_loc");
+ let debug_loc = read::DebugLoc::new(&debug_loc, LittleEndian);
+
+ let debug_loclists = read::DebugLocLists::new(&[], LittleEndian);
+
+ let locations = gimli::LocationLists::new(debug_loc, debug_loclists);
+
+ let dwarf = read::Dwarf {
+ debug_abbrev,
+ debug_info,
+ debug_line,
+ debug_str,
+ ranges,
+ locations,
+ ..Default::default()
+ };
+
+ let mut dwarf = write::Dwarf::from(&dwarf, &|address| Some(Address::Constant(address)))
+ .expect("Should convert DWARF information");
+
+ assert_eq!(dwarf.units.count(), 23);
+ let entries: usize = (0..dwarf.units.count())
+ .map(|i| dwarf.units.get(dwarf.units.id(i)).count())
+ .sum();
+ assert_eq!(entries, 29_560);
+ assert_eq!(dwarf.line_strings.count(), 0);
+ assert_eq!(dwarf.strings.count(), 3921);
+
+ // Write to new sections
+ let mut write_sections = write::Sections::new(EndianVec::new(LittleEndian));
+ dwarf
+ .write(&mut write_sections)
+ .expect("Should write DWARF information");
+ let debug_info_data = write_sections.debug_info.slice();
+ let debug_abbrev_data = write_sections.debug_abbrev.slice();
+ let debug_line_data = write_sections.debug_line.slice();
+ let debug_ranges_data = write_sections.debug_ranges.slice();
+ let debug_loc_data = write_sections.debug_loc.slice();
+ let debug_str_data = write_sections.debug_str.slice();
+ assert_eq!(debug_info_data.len(), 394_930);
+ assert_eq!(debug_abbrev_data.len(), 9701);
+ assert_eq!(debug_line_data.len(), 105_797);
+ assert_eq!(debug_ranges_data.len(), 155_712);
+ assert_eq!(debug_loc_data.len(), 245_168);
+ assert_eq!(debug_str_data.len(), 144_731);
+
+ // Convert new sections
+ let debug_abbrev = read::DebugAbbrev::new(debug_abbrev_data, LittleEndian);
+ let debug_info = read::DebugInfo::new(debug_info_data, LittleEndian);
+ let debug_line = read::DebugLine::new(debug_line_data, LittleEndian);
+ let debug_str = read::DebugStr::new(debug_str_data, LittleEndian);
+ let debug_ranges = read::DebugRanges::new(debug_ranges_data, LittleEndian);
+ let debug_rnglists = read::DebugRngLists::new(&[], LittleEndian);
+ let debug_loc = read::DebugLoc::new(debug_loc_data, LittleEndian);
+ let debug_loclists = read::DebugLocLists::new(&[], LittleEndian);
+
+ let ranges = gimli::RangeLists::new(debug_ranges, debug_rnglists);
+ let locations = gimli::LocationLists::new(debug_loc, debug_loclists);
+
+ let dwarf = read::Dwarf {
+ debug_abbrev,
+ debug_info,
+ debug_line,
+ debug_str,
+ ranges,
+ locations,
+ ..Default::default()
+ };
+
+ let dwarf = write::Dwarf::from(&dwarf, &|address| Some(Address::Constant(address)))
+ .expect("Should convert DWARF information");
+
+ assert_eq!(dwarf.units.count(), 23);
+ let entries: usize = (0..dwarf.units.count())
+ .map(|i| dwarf.units.get(dwarf.units.id(i)).count())
+ .sum();
+ assert_eq!(entries, 29_560);
+ assert_eq!(dwarf.strings.count(), 3921);
+}
+
+#[test]
+fn test_convert_eh_frame() {
+ // Convert existing section
+ let eh_frame = read_section("eh_frame");
+ let mut eh_frame = read::EhFrame::new(&eh_frame, LittleEndian);
+ // The `.eh_frame` fixture data was created on a 64-bit machine.
+ eh_frame.set_address_size(8);
+ let frames = write::FrameTable::from(&eh_frame, &|address| Some(Address::Constant(address)))
+ .expect("Should convert eh_frame information");
+ assert_eq!(frames.cie_count(), 2);
+ assert_eq!(frames.fde_count(), 3482);
+
+ // Write to new section
+ let mut write_eh_frame = write::EhFrame(EndianVec::new(LittleEndian));
+ frames
+ .write_eh_frame(&mut write_eh_frame)
+ .expect("Should write eh_frame information");
+ let eh_frame = write_eh_frame.slice();
+ assert_eq!(eh_frame.len(), 147144);
+
+ // Convert new section
+ let mut eh_frame = read::EhFrame::new(&eh_frame, LittleEndian);
+ eh_frame.set_address_size(8);
+ let frames = write::FrameTable::from(&eh_frame, &|address| Some(Address::Constant(address)))
+ .expect("Should convert eh_frame information");
+ assert_eq!(frames.cie_count(), 2);
+ assert_eq!(frames.fde_count(), 3482);
+}
diff --git a/vendor/gimli-0.26.2/tests/parse_self.rs b/vendor/gimli-0.26.2/tests/parse_self.rs
new file mode 100755
index 000000000..fb316314e
--- /dev/null
+++ b/vendor/gimli-0.26.2/tests/parse_self.rs
@@ -0,0 +1,431 @@
+#![cfg(all(feature = "read", feature = "std", feature = "endian-reader"))]
+
+use gimli::{
+ AttributeValue, DebugAbbrev, DebugAddr, DebugAddrBase, DebugAranges, DebugInfo, DebugLine,
+ DebugLoc, DebugLocLists, DebugPubNames, DebugPubTypes, DebugRanges, DebugRngLists, DebugStr,
+ Encoding, EndianSlice, Expression, LittleEndian, LocationLists, Operation, RangeLists,
+ RangeListsOffset, Reader,
+};
+use std::collections::hash_map::HashMap;
+use std::env;
+use std::fs::File;
+use std::io::Read;
+use std::path::PathBuf;
+use std::rc::Rc;
+
+fn read_section(section: &str) -> Vec<u8> {
+ let mut path = PathBuf::new();
+ if let Ok(dir) = env::var("CARGO_MANIFEST_DIR") {
+ path.push(dir);
+ }
+ path.push("fixtures/self");
+ path.push(section);
+
+ println!("Reading section \"{}\" at path {:?}", section, path);
+ assert!(path.is_file());
+ let mut file = File::open(path).unwrap();
+
+ let mut buf = Vec::new();
+ file.read_to_end(&mut buf).unwrap();
+ buf
+}
+
+fn parse_expression<R: Reader>(expr: Expression<R>, encoding: Encoding) {
+ let mut pc = expr.0.clone();
+ while !pc.is_empty() {
+ Operation::parse(&mut pc, encoding).expect("Should parse operation");
+ }
+
+ // Also attempt to evaluate some of it.
+ let mut eval = expr.evaluation(encoding);
+ eval.set_initial_value(0);
+ eval.evaluate().expect("Should evaluate expression");
+}
+
+fn impl_parse_self_debug_info<R: gimli::Reader>(
+ debug_info: &DebugInfo<R>,
+ debug_abbrev: &DebugAbbrev<R>,
+) {
+ let mut iter = debug_info.units();
+ while let Some(unit) = iter.next().expect("Should parse compilation unit") {
+ let abbrevs = unit
+ .abbreviations(&debug_abbrev)
+ .expect("Should parse abbreviations");
+
+ let mut cursor = unit.entries(&abbrevs);
+
+ while cursor.next_dfs().expect("Should parse next dfs").is_some() {
+ let entry = cursor.current().expect("Should have a current entry");
+
+ let mut attrs = entry.attrs();
+ while let Some(attr) = attrs.next().expect("Should parse entry's attribute") {
+ if let AttributeValue::Exprloc(expression) = attr.value() {
+ parse_expression(expression, unit.encoding());
+ }
+ }
+ }
+ }
+}
+
+#[test]
+fn test_parse_self_debug_info() {
+ let debug_info = read_section("debug_info");
+ let debug_info = DebugInfo::new(&debug_info, LittleEndian);
+
+ let debug_abbrev = read_section("debug_abbrev");
+ let debug_abbrev = DebugAbbrev::new(&debug_abbrev, LittleEndian);
+
+ impl_parse_self_debug_info(&debug_info, &debug_abbrev);
+}
+
+#[test]
+fn test_parse_self_debug_info_with_endian_rc_slice() {
+ let debug_info = read_section("debug_info");
+ let debug_info = Rc::from(&debug_info[..]);
+ let debug_info = gimli::EndianRcSlice::new(debug_info, LittleEndian);
+ let debug_info = DebugInfo::from(debug_info);
+
+ let debug_abbrev = read_section("debug_abbrev");
+ let debug_abbrev = Rc::from(&debug_abbrev[..]);
+ let debug_abbrev = gimli::EndianRcSlice::new(debug_abbrev, LittleEndian);
+ let debug_abbrev = DebugAbbrev::from(debug_abbrev);
+
+ impl_parse_self_debug_info(&debug_info, &debug_abbrev);
+}
+
+#[test]
+fn test_parse_self_debug_line() {
+ let debug_info = read_section("debug_info");
+ let debug_info = DebugInfo::new(&debug_info, LittleEndian);
+
+ let debug_abbrev = read_section("debug_abbrev");
+ let debug_abbrev = DebugAbbrev::new(&debug_abbrev, LittleEndian);
+
+ let debug_line = read_section("debug_line");
+ let debug_line = DebugLine::new(&debug_line, LittleEndian);
+
+ let debug_str = read_section("debug_str");
+ let debug_str = DebugStr::new(&debug_str, LittleEndian);
+
+ let mut iter = debug_info.units();
+ while let Some(unit) = iter.next().expect("Should parse compilation unit") {
+ let abbrevs = unit
+ .abbreviations(&debug_abbrev)
+ .expect("Should parse abbreviations");
+
+ let mut cursor = unit.entries(&abbrevs);
+ cursor.next_dfs().expect("Should parse next dfs");
+
+ let unit_entry = cursor.current().expect("Should have a root entry");
+
+ let comp_dir = unit_entry
+ .attr_value(gimli::DW_AT_comp_dir)
+ .expect("Should parse comp_dir attribute")
+ .and_then(|val| val.string_value(&debug_str));
+ let comp_name = unit_entry
+ .attr_value(gimli::DW_AT_name)
+ .expect("Should parse name attribute")
+ .and_then(|val| val.string_value(&debug_str));
+
+ if let Some(AttributeValue::DebugLineRef(offset)) = unit_entry
+ .attr_value(gimli::DW_AT_stmt_list)
+ .expect("Should parse stmt_list")
+ {
+ let program = debug_line
+ .program(offset, unit.address_size(), comp_dir, comp_name)
+ .expect("should parse line number program header");
+
+ let mut results = Vec::new();
+ let mut rows = program.rows();
+ while let Some((_, row)) = rows
+ .next_row()
+ .expect("Should parse and execute all rows in the line number program")
+ {
+ results.push(*row);
+ }
+ results.reverse();
+
+ let program = debug_line
+ .program(offset, unit.address_size(), comp_dir, comp_name)
+ .expect("should parse line number program header");
+ let (program, sequences) = program
+ .sequences()
+ .expect("should parse and execute the entire line number program");
+ assert!(!sequences.is_empty()); // Should be at least one sequence.
+ for sequence in sequences {
+ let mut rows = program.resume_from(&sequence);
+ while let Some((_, row)) = rows
+ .next_row()
+ .expect("Should parse and execute all rows after resuming")
+ {
+ let other_row = results.pop().unwrap();
+ assert!(row.address() >= sequence.start);
+ assert!(row.address() <= sequence.end);
+ assert_eq!(row.address(), other_row.address());
+ assert_eq!(row.line(), other_row.line());
+ }
+ }
+ assert!(results.is_empty());
+ }
+ }
+}
+
+#[test]
+fn test_parse_self_debug_loc() {
+ let debug_info = read_section("debug_info");
+ let debug_info = DebugInfo::new(&debug_info, LittleEndian);
+
+ let debug_abbrev = read_section("debug_abbrev");
+ let debug_abbrev = DebugAbbrev::new(&debug_abbrev, LittleEndian);
+
+ let debug_addr = DebugAddr::from(EndianSlice::new(&[], LittleEndian));
+ let debug_addr_base = DebugAddrBase(0);
+
+ let debug_loc = read_section("debug_loc");
+ let debug_loc = DebugLoc::new(&debug_loc, LittleEndian);
+ let debug_loclists = DebugLocLists::new(&[], LittleEndian);
+ let loclists = LocationLists::new(debug_loc, debug_loclists);
+
+ let mut iter = debug_info.units();
+ while let Some(unit) = iter.next().expect("Should parse compilation unit") {
+ let abbrevs = unit
+ .abbreviations(&debug_abbrev)
+ .expect("Should parse abbreviations");
+
+ let mut cursor = unit.entries(&abbrevs);
+ cursor.next_dfs().expect("Should parse next dfs");
+
+ let mut low_pc = 0;
+
+ {
+ let unit_entry = cursor.current().expect("Should have a root entry");
+ let low_pc_attr = unit_entry
+ .attr_value(gimli::DW_AT_low_pc)
+ .expect("Should parse low_pc");
+ if let Some(gimli::AttributeValue::Addr(address)) = low_pc_attr {
+ low_pc = address;
+ }
+ }
+
+ while cursor.next_dfs().expect("Should parse next dfs").is_some() {
+ let entry = cursor.current().expect("Should have a current entry");
+ let mut attrs = entry.attrs();
+ while let Some(attr) = attrs.next().expect("Should parse entry's attribute") {
+ if let AttributeValue::LocationListsRef(offset) = attr.value() {
+ let mut locs = loclists
+ .locations(
+ offset,
+ unit.encoding(),
+ low_pc,
+ &debug_addr,
+ debug_addr_base,
+ )
+ .expect("Should parse locations OK");
+ while let Some(loc) = locs.next().expect("Should parse next location") {
+ assert!(loc.range.begin <= loc.range.end);
+ parse_expression(loc.data, unit.encoding());
+ }
+ }
+ }
+ }
+ }
+}
+
+#[test]
+fn test_parse_self_debug_ranges() {
+ let debug_info = read_section("debug_info");
+ let debug_info = DebugInfo::new(&debug_info, LittleEndian);
+
+ let debug_abbrev = read_section("debug_abbrev");
+ let debug_abbrev = DebugAbbrev::new(&debug_abbrev, LittleEndian);
+
+ let debug_addr = DebugAddr::from(EndianSlice::new(&[], LittleEndian));
+ let debug_addr_base = DebugAddrBase(0);
+
+ let debug_ranges = read_section("debug_ranges");
+ let debug_ranges = DebugRanges::new(&debug_ranges, LittleEndian);
+ let debug_rnglists = DebugRngLists::new(&[], LittleEndian);
+ let rnglists = RangeLists::new(debug_ranges, debug_rnglists);
+
+ let mut iter = debug_info.units();
+ while let Some(unit) = iter.next().expect("Should parse compilation unit") {
+ let abbrevs = unit
+ .abbreviations(&debug_abbrev)
+ .expect("Should parse abbreviations");
+
+ let mut cursor = unit.entries(&abbrevs);
+ cursor.next_dfs().expect("Should parse next dfs");
+
+ let mut low_pc = 0;
+
+ {
+ let unit_entry = cursor.current().expect("Should have a root entry");
+ let low_pc_attr = unit_entry
+ .attr_value(gimli::DW_AT_low_pc)
+ .expect("Should parse low_pc");
+ if let Some(gimli::AttributeValue::Addr(address)) = low_pc_attr {
+ low_pc = address;
+ }
+ }
+
+ while cursor.next_dfs().expect("Should parse next dfs").is_some() {
+ let entry = cursor.current().expect("Should have a current entry");
+ let mut attrs = entry.attrs();
+ while let Some(attr) = attrs.next().expect("Should parse entry's attribute") {
+ if let AttributeValue::RangeListsRef(offset) = attr.value() {
+ let mut ranges = rnglists
+ .ranges(
+ RangeListsOffset(offset.0),
+ unit.encoding(),
+ low_pc,
+ &debug_addr,
+ debug_addr_base,
+ )
+ .expect("Should parse ranges OK");
+ while let Some(range) = ranges.next().expect("Should parse next range") {
+ assert!(range.begin <= range.end);
+ }
+ }
+ }
+ }
+ }
+}
+
+#[test]
+fn test_parse_self_debug_aranges() {
+ let debug_aranges = read_section("debug_aranges");
+ let debug_aranges = DebugAranges::new(&debug_aranges, LittleEndian);
+
+ let mut headers = debug_aranges.headers();
+ while let Some(header) = headers.next().expect("Should parse arange header OK") {
+ let mut entries = header.entries();
+ while let Some(_) = entries.next().expect("Should parse arange entry OK") {
+ // Not really anything else we can check right now.
+ }
+ }
+}
+
+#[test]
+fn test_parse_self_debug_pubnames() {
+ let debug_info = read_section("debug_info");
+ let debug_info = DebugInfo::new(&debug_info, LittleEndian);
+
+ let debug_abbrev = read_section("debug_abbrev");
+ let debug_abbrev = DebugAbbrev::new(&debug_abbrev, LittleEndian);
+
+ let debug_pubnames = read_section("debug_pubnames");
+ let debug_pubnames = DebugPubNames::new(&debug_pubnames, LittleEndian);
+
+ let mut units = HashMap::new();
+ let mut abbrevs = HashMap::new();
+ let mut pubnames = debug_pubnames.items();
+ while let Some(entry) = pubnames.next().expect("Should parse pubname OK") {
+ let unit_offset = entry.unit_header_offset();
+ let unit = units.entry(unit_offset).or_insert_with(|| {
+ debug_info
+ .header_from_offset(unit_offset)
+ .expect("Should parse unit header OK")
+ });
+ let abbrev_offset = unit.debug_abbrev_offset();
+ let abbrevs = abbrevs.entry(abbrev_offset).or_insert_with(|| {
+ debug_abbrev
+ .abbreviations(abbrev_offset)
+ .expect("Should parse abbreviations OK")
+ });
+ let mut cursor = unit
+ .entries_at_offset(abbrevs, entry.die_offset())
+ .expect("DIE offset should be valid");
+ assert!(cursor.next_dfs().expect("Should parse DIE").is_some());
+ }
+}
+
+#[test]
+fn test_parse_self_debug_pubtypes() {
+ let debug_info = read_section("debug_info");
+ let debug_info = DebugInfo::new(&debug_info, LittleEndian);
+
+ let debug_abbrev = read_section("debug_abbrev");
+ let debug_abbrev = DebugAbbrev::new(&debug_abbrev, LittleEndian);
+
+ let debug_pubtypes = read_section("debug_pubtypes");
+ let debug_pubtypes = DebugPubTypes::new(&debug_pubtypes, LittleEndian);
+
+ let mut units = HashMap::new();
+ let mut abbrevs = HashMap::new();
+ let mut pubtypes = debug_pubtypes.items();
+ while let Some(entry) = pubtypes.next().expect("Should parse pubtype OK") {
+ let unit_offset = entry.unit_header_offset();
+ let unit = units.entry(unit_offset).or_insert_with(|| {
+ debug_info
+ .header_from_offset(unit_offset)
+ .expect("Should parse unit header OK")
+ });
+ let abbrev_offset = unit.debug_abbrev_offset();
+ let abbrevs = abbrevs.entry(abbrev_offset).or_insert_with(|| {
+ debug_abbrev
+ .abbreviations(abbrev_offset)
+ .expect("Should parse abbreviations OK")
+ });
+ let mut cursor = unit
+ .entries_at_offset(abbrevs, entry.die_offset())
+ .expect("DIE offset should be valid");
+ assert!(cursor.next_dfs().expect("Should parse DIE").is_some());
+ }
+}
+
+#[test]
+fn test_parse_self_eh_frame() {
+ use gimli::{BaseAddresses, CieOrFde, EhFrame, UnwindSection};
+
+ let eh_frame = read_section("eh_frame");
+ let mut eh_frame = EhFrame::new(&eh_frame, LittleEndian);
+ // The `.eh_frame` fixture data was created on a 64-bit machine.
+ eh_frame.set_address_size(8);
+
+ let bases = BaseAddresses::default()
+ .set_eh_frame(0)
+ .set_text(0)
+ .set_got(0);
+ let mut entries = eh_frame.entries(&bases);
+ while let Some(entry) = entries.next().expect("Should parse CFI entry OK") {
+ match entry {
+ CieOrFde::Cie(cie) => {
+ let mut instrs = cie.instructions(&eh_frame, &bases);
+ while let Some(_) = instrs.next().expect("Can parse next CFI instruction OK") {
+ // TODO FITZGEN
+ }
+ }
+ CieOrFde::Fde(partial) => {
+ let fde = partial
+ .parse(UnwindSection::cie_from_offset)
+ .expect("Should be able to get CIE for FDE");
+
+ let mut instrs = fde.instructions(&eh_frame, &bases);
+ while let Some(_) = instrs.next().expect("Can parse next CFI instruction OK") {
+ // TODO FITZGEN
+ }
+ }
+ }
+ }
+}
+
+#[test]
+fn test_parse_self_eh_frame_hdr() {
+ use gimli::{BaseAddresses, EhFrameHdr};
+
+ let eh_frame_hdr = read_section("eh_frame_hdr");
+ let eh_frame_hdr = EhFrameHdr::new(&eh_frame_hdr, LittleEndian);
+
+ let bases = BaseAddresses::default()
+ .set_eh_frame(0)
+ .set_eh_frame_hdr(0)
+ .set_text(0)
+ .set_got(0);
+
+ // `.eh_frame_hdr` was generated on a 64 bit machine.
+ let address_size = 8;
+
+ let _parsed_header = eh_frame_hdr
+ .parse(&bases, address_size)
+ .expect("we can parse the `.eh_frame_hdr` section OK");
+}
diff --git a/vendor/gimli/.cargo-checksum.json b/vendor/gimli/.cargo-checksum.json
index 759ec93de..944895d6b 100644
--- a/vendor/gimli/.cargo-checksum.json
+++ b/vendor/gimli/.cargo-checksum.json
@@ -1 +1 @@
-{"files":{"CHANGELOG.md":"789a696803d3f1bed3ff3566cac8e7cf15c4bf9428242d637d0ce7f3a0ad57a3","CONTRIBUTING.md":"5f513ec06013e4f6f097e9c9492da5a47b9f25c94c6ecadfb655a77405fe912c","Cargo.lock":"284bff6b09ef0fd214c34492417778d6d5b9f75dc54557015af01a95696c752a","Cargo.toml":"92dccbeaa61bc8c65da53917fbf32900b3cb2549f90b67b67e1c67672bac205e","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"7b63ecd5f1902af1b63729947373683c32745c16a10e8e6292e2e2dcd7e90ae0","README.md":"57e36d344dabe1c52a9c81eafb28787c309b86c47437abf8589ef17bf383fc5f","benches/bench.rs":"e0045b989683794951563aa91b37069b2f6ae55f95e288d23f5c984b46e3a7eb","examples/dwarf-validate.rs":"4aac1045e3c08bf00878eeff75c0cfc30c06171c5eab2e71d757505786729687","examples/dwarfdump.rs":"d74323c037689b32825efa9bf69614ee26a444513b266e819ecf486956ee3299","examples/simple.rs":"4c3425e8bd1880d9522f5ed2581fb5ccd452d4be678eebc0e147c48722a7be1d","examples/simple_line.rs":"ac795f859a17650dde466b5b23b8c161b2e3b8eb57e32f5b6718a3072f6bfad0","fixtures/self/README.md":"7cfd76031ec5a4b38cc4eb56ccbfe1bb590fb54c333d037550bdeaaeacfc20cb","fixtures/self/debug_abbrev":"7c0faa940d9c68d196d03ad55a20e5c746040fa428ff323277fa381deff82bba","fixtures/self/debug_aranges":"8c2aeb2335f61d04ecb7b747070d24f83a6517cbee79dc5c96d97fb6c53d6b6d","fixtures/self/debug_info":"42028a5983006e0703f9ca9515cd27d891ae4af70279fae5011d547f581e2661","fixtures/self/debug_inlined":"89d9516f06ff835621936037f5884fc56712bf304c1dcde52251ddd510fe8710","fixtures/self/debug_line":"b29aebcca3b38bb2bb8aa708cbe74a0dce5a3b0c18916b63d6d17282c017bec7","fixtures/self/debug_loc":"8906ccb9c204f233eb74c1d069dee97a19d18c2051f9147795d7b5364a9266aa","fixtures/self/debug_pubnames":"cf58e237f89c68afba724597fa7e260448636b45f2e69dc6f1bfe34006e27c48","fixtures/self/debug_pubtypes":"d43c1bed71c9d14d1683294cdc1833f069cf131d6e95ee808547919b4f352d81","fixtures/self/debug_ranges":"6d765ac18d33accd89186d077eeb505cbdf97d990c9201d63d9463cd7787ce7a","fixtures/self/debug_str":"9ed904b68eee77b8558b80b3b7ca03e8527f6c64483e9d6d845f40270eb21183","fixtures/self/eh_frame":"6dc3d84351cac42cf73d03452fbb532470dd94d08715154c48417e3f62095f17","fixtures/self/eh_frame_hdr":"afba7a0aa233c9a8c81c986495bd2505164844adb93272d6bc0c9e592e684716","rustfmt.toml":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855","src/arch.rs":"1c4cb3e2a322f3f42fe0b82875c9d0ce060d9af2388990139bdce9a4487c32da","src/common.rs":"392f52a58db6101187ca5525bbeafca9bda2342debd058cabca37350cd9db619","src/constants.rs":"358cf7924c79bc72de59d23d1fa02b2047d6c763c8fbd8be263ab8cd3e3ba7ec","src/endianity.rs":"1f7e62ae34f540c06bedf1e7948739211556eea7dd83731a5ca52c7d687ed0fc","src/leb128.rs":"996d5c79d027f97c010ca487bc4ff5f8265f4b9e63d62b4e4fa291383c259ee9","src/lib.rs":"6863b9a9d1eddf34b4095dfe60318aae56914fbf515ba5601b29024cc963f27c","src/read/abbrev.rs":"a3f550c32f1eb880d82bdb5257d35e10d32cfd039050e8131cbeedac346cc1d9","src/read/addr.rs":"f63f289edf889e87107bb2090fb1c50b48af7015f31b7c39c3d6ea09630a38e9","src/read/aranges.rs":"ba3302f87cffb7ee15f48b0530ebd707f45ad056934223078d25ae2a1b034f1c","src/read/cfi.rs":"b1064ed9b4b87169a148cc86adc7443c5a771dc2d1799129f7883f1ef6adc165","src/read/dwarf.rs":"a39c24429b437ae3a1cd17bae2f01c973c9ce39f7b5f2b3435982d6860944e0e","src/read/endian_reader.rs":"320983a859c2bb0dd44a3e6fae55ff0a84dba3fa80c2edbc64aa8135c44eddf0","src/read/endian_slice.rs":"ae1c52499728f6a85648f1bf87c02dcf43bebecb5ad4e835a1246938ba4338bf","src/read/index.rs":"e79b8d591b8e2007a37f5ea85a6d71b69d56ca3739a85cf7bf361724c5b829fa","src/read/line.rs":"af7a1520777e56632970fc5fe7377fdcd12d078eb88eeb2b0f2cc95b73ff68a7","src/read/lists.rs":"67ca9e1a36a91feb4996d035211de845205212bfda02163685d217818567ff93","src/read/loclists.rs":"1b4ea85c0dd8c6eae492a60cb70810185d56ba579df7986cb8a36385031b10fd","src/read/lookup.rs":"0cf89ba12b9d48b1fe035dd3a497730323acb9427a9457abbc2f7c58c4c71165","src/read/mod.rs":"3bafc747c31a575bcc92d3e7d5ea5a15f5acc01918a4377cec1dced0f85b5d2b","src/read/op.rs":"e5dce6520dfc90ec74c3b070ca374b89fcf55ff23101471591458175a72c79e6","src/read/pubnames.rs":"ed752ee1a7017e6d3be42d81e4ddaaac960ef08081463a19106c9f041526d4a3","src/read/pubtypes.rs":"5e75b32c0923e827aff0bb2db456797a0e8d38ba46be992558a7990b3196bcf5","src/read/reader.rs":"b10ff3e77b54347e96b1f3cff30da104dfdd0c4d7a55b672950788f1f1ae3478","src/read/rnglists.rs":"af637d283d76514382ee0556463cccab4e6f0ea4d061db9a44a594b5d57d1fd7","src/read/str.rs":"4c2f50014451621fea45969cd313f6840fcd3a99d7a2d081bfa1f8e0e434133a","src/read/unit.rs":"6ed00ba004c329008bf295d9c7d724afe961750f0c7b08430fc213fd5d998003","src/read/util.rs":"0b7d0d2225a98618070dc472ccba49a5411aa8beed5ff6696da079d06156d363","src/read/value.rs":"5a91e03ad3d41f679b264753498434b91948c6b89955e4beb4522498386d9b1d","src/test_util.rs":"291eefa6b51c6d934ba2f4a4c9bc7c403046fc1cccf4d43487820f0154bb89e2","src/write/abbrev.rs":"fa02163389e92e804d139cf84f833ab6af932083f0eb2d74464b4a70bd3237ff","src/write/cfi.rs":"3b04b0ebd82363738199cc673f64e0ceb60506a67c4f18b435a109caa62840f3","src/write/dwarf.rs":"8a1a0893e31134ad68993994594f3024ad0c8af7c1188b29e0ffc26b42edef21","src/write/endian_vec.rs":"1d5811986648816a677580b22630f5059757a381487d73e9adbb3008c9ae0c58","src/write/line.rs":"df7d2082c71b5e523cd52745700aae3dcfa5800f0b280e831ef5d8eb8035d6a7","src/write/loc.rs":"bb5b750c04f6603e18225db72652ea00239234ba674a8a8627c99d4ab07b47a9","src/write/mod.rs":"d8aa1da854cdee629d470d00d87e00dc6998e4bec1ca951f8d2f277730ab9d69","src/write/op.rs":"7b1d49b10c8c92b2d5b259e83119ff7dc95bc552535bb7b1a82ca9556a35c589","src/write/range.rs":"5bac01e372c08e3cc19e1e07e40492d8214cdfa8881737920cb792f4aa2ba80b","src/write/section.rs":"3ce781d5e82ba365ff54fdd36e0ef58c58a2215b09a8861eb0b038efac82b77f","src/write/str.rs":"4850cc2fee55980f9cbb6b4169f9861ab9d05c2b28a85c2b790480b83a66f514","src/write/unit.rs":"213c881736f8c87fcb2f921e379791eaba2915e8d077139965a9c6211001fe44","src/write/writer.rs":"304181287f90445bbfb33349c26b34bd87002d6844fc5686bfc0756fd0a1ecd8","tests/convert_self.rs":"180909b562969e1691b64628ded8654e6e0b10b3357f39917bd8ac288c5826dd","tests/parse_self.rs":"f2da1c7daef7139545c9367c2f26199e8b4623b31d4ec6480ddd851e6980f2dc"},"package":"22030e2c5a68ec659fde1e949a745124b48e6fa8b045b7ed5bd1fe4ccc5c4e5d"} \ No newline at end of file
+{"files":{"CHANGELOG.md":"26652aa86933dfc6d8368788a6c8b3f44bc5787cb3a9773778dbd8beb376cab5","CONTRIBUTING.md":"5f513ec06013e4f6f097e9c9492da5a47b9f25c94c6ecadfb655a77405fe912c","Cargo.lock":"526ec45724cfe5dba367ac5a6aaac87223dcc0a76393cf87582be63e349b437b","Cargo.toml":"dccff39f1b698a28646c5af7bbe35fc08606b4dbf848f9e02bbf78b0daf967e6","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"7b63ecd5f1902af1b63729947373683c32745c16a10e8e6292e2e2dcd7e90ae0","README.md":"8b35e78ea98d87b6b818feea83863cbf16fe5b024ba71641c6ce9fe9c68f32c7","benches/bench.rs":"e0045b989683794951563aa91b37069b2f6ae55f95e288d23f5c984b46e3a7eb","clippy.toml":"50fd0cdaae995561b1d688c9410fe99335fc7ac3916a400dafd25ff63f8215f7","examples/dwarf-validate.rs":"4aac1045e3c08bf00878eeff75c0cfc30c06171c5eab2e71d757505786729687","examples/dwarfdump.rs":"5192233994233aabc1f359f9b50746a5703f528c4e22f2573d8e39e0c35cd32a","examples/simple.rs":"4c3425e8bd1880d9522f5ed2581fb5ccd452d4be678eebc0e147c48722a7be1d","examples/simple_line.rs":"ac795f859a17650dde466b5b23b8c161b2e3b8eb57e32f5b6718a3072f6bfad0","fixtures/self/README.md":"7cfd76031ec5a4b38cc4eb56ccbfe1bb590fb54c333d037550bdeaaeacfc20cb","fixtures/self/debug_abbrev":"7c0faa940d9c68d196d03ad55a20e5c746040fa428ff323277fa381deff82bba","fixtures/self/debug_aranges":"8c2aeb2335f61d04ecb7b747070d24f83a6517cbee79dc5c96d97fb6c53d6b6d","fixtures/self/debug_info":"42028a5983006e0703f9ca9515cd27d891ae4af70279fae5011d547f581e2661","fixtures/self/debug_inlined":"89d9516f06ff835621936037f5884fc56712bf304c1dcde52251ddd510fe8710","fixtures/self/debug_line":"b29aebcca3b38bb2bb8aa708cbe74a0dce5a3b0c18916b63d6d17282c017bec7","fixtures/self/debug_loc":"8906ccb9c204f233eb74c1d069dee97a19d18c2051f9147795d7b5364a9266aa","fixtures/self/debug_pubnames":"cf58e237f89c68afba724597fa7e260448636b45f2e69dc6f1bfe34006e27c48","fixtures/self/debug_pubtypes":"d43c1bed71c9d14d1683294cdc1833f069cf131d6e95ee808547919b4f352d81","fixtures/self/debug_ranges":"6d765ac18d33accd89186d077eeb505cbdf97d990c9201d63d9463cd7787ce7a","fixtures/self/debug_str":"9ed904b68eee77b8558b80b3b7ca03e8527f6c64483e9d6d845f40270eb21183","fixtures/self/eh_frame":"6dc3d84351cac42cf73d03452fbb532470dd94d08715154c48417e3f62095f17","fixtures/self/eh_frame_hdr":"afba7a0aa233c9a8c81c986495bd2505164844adb93272d6bc0c9e592e684716","rustfmt.toml":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855","src/arch.rs":"3a9b44d51a770b83e19c5420c7a6c090cf895fe668cbecea4e3c20acdfef871c","src/common.rs":"392f52a58db6101187ca5525bbeafca9bda2342debd058cabca37350cd9db619","src/constants.rs":"358cf7924c79bc72de59d23d1fa02b2047d6c763c8fbd8be263ab8cd3e3ba7ec","src/endianity.rs":"1f7e62ae34f540c06bedf1e7948739211556eea7dd83731a5ca52c7d687ed0fc","src/leb128.rs":"996d5c79d027f97c010ca487bc4ff5f8265f4b9e63d62b4e4fa291383c259ee9","src/lib.rs":"9a307a6d1fbebeae581df014b4f2b8bd16399fa883209fbdcc4d85eb9ec1dfd5","src/read/abbrev.rs":"31f7e9544a30e35f49dca355981730c2eb145e55ddbf281161d842a566d0a88d","src/read/addr.rs":"f63f289edf889e87107bb2090fb1c50b48af7015f31b7c39c3d6ea09630a38e9","src/read/aranges.rs":"ba3302f87cffb7ee15f48b0530ebd707f45ad056934223078d25ae2a1b034f1c","src/read/cfi.rs":"85cb294cf6a932d31769a747c58d1767b83e64831d8c633ab0b517014fe1cdec","src/read/dwarf.rs":"50cd674f17e81bca57f6ba69600a7a24bd7d13632c165f2a40f2a23fd328a2c9","src/read/endian_reader.rs":"320983a859c2bb0dd44a3e6fae55ff0a84dba3fa80c2edbc64aa8135c44eddf0","src/read/endian_slice.rs":"476055ef571d53fbb890545fe5893b9083b10b90ec9e538bd82216bbe8bc45fd","src/read/index.rs":"e79b8d591b8e2007a37f5ea85a6d71b69d56ca3739a85cf7bf361724c5b829fa","src/read/lazy.rs":"85642e886ab3a94cea53534d1e133d1c4c17d2deaf291facdc316507e499ce22","src/read/line.rs":"ff3aeb1c719a3440ece2a8b2394d790f0987640d77fc4b30bee73f291f027803","src/read/lists.rs":"67ca9e1a36a91feb4996d035211de845205212bfda02163685d217818567ff93","src/read/loclists.rs":"857701a9e86aee809bfca3fd661e283b4f05038764dfc9c3cb1a349acc00bc47","src/read/lookup.rs":"0cf89ba12b9d48b1fe035dd3a497730323acb9427a9457abbc2f7c58c4c71165","src/read/mod.rs":"e3e831fab7570c97f58fb5e3931e6965f4a361b66292944f79f85bf3fe1b1d00","src/read/op.rs":"57aba989cc3d49772a51de7d487cbd10458f688487d3ae4e5efae4c84adb4e39","src/read/pubnames.rs":"ed752ee1a7017e6d3be42d81e4ddaaac960ef08081463a19106c9f041526d4a3","src/read/pubtypes.rs":"5e75b32c0923e827aff0bb2db456797a0e8d38ba46be992558a7990b3196bcf5","src/read/reader.rs":"b10ff3e77b54347e96b1f3cff30da104dfdd0c4d7a55b672950788f1f1ae3478","src/read/rnglists.rs":"4ec166e73fdfc85efa97b3b005b514bb64d454edb1ba0f201c45df4f2127e745","src/read/str.rs":"4c2f50014451621fea45969cd313f6840fcd3a99d7a2d081bfa1f8e0e434133a","src/read/unit.rs":"4e8af3c654faf8dc42b8bc62edf2f2402c6b42b31889662b0b48753c08b9893a","src/read/util.rs":"40f07a7b6623f29d03e15e41cda625a613ab1973969a4ddbb42365a8550b7e79","src/read/value.rs":"5a91e03ad3d41f679b264753498434b91948c6b89955e4beb4522498386d9b1d","src/test_util.rs":"291eefa6b51c6d934ba2f4a4c9bc7c403046fc1cccf4d43487820f0154bb89e2","src/write/abbrev.rs":"fa02163389e92e804d139cf84f833ab6af932083f0eb2d74464b4a70bd3237ff","src/write/cfi.rs":"3b04b0ebd82363738199cc673f64e0ceb60506a67c4f18b435a109caa62840f3","src/write/dwarf.rs":"8a1a0893e31134ad68993994594f3024ad0c8af7c1188b29e0ffc26b42edef21","src/write/endian_vec.rs":"1d5811986648816a677580b22630f5059757a381487d73e9adbb3008c9ae0c58","src/write/line.rs":"73bf3bab57433fe1dc891c48303cbc4e482306a1b9425f3483ad2985a9676ee9","src/write/loc.rs":"5c1f8d97d8e871a6663ad704f5e15694bddd54b85f2d801b52a520522f1258fd","src/write/mod.rs":"d8aa1da854cdee629d470d00d87e00dc6998e4bec1ca951f8d2f277730ab9d69","src/write/op.rs":"08fec7613aaa9061aae6e31d8b49933c812a6b7609f69e611a2a953af09aa18a","src/write/range.rs":"259e21e32bebbf7cdd8027d401862dee95cb5111e45bc4ff30bf54e3306d0262","src/write/section.rs":"effefef0d5e4557cb099431a20a7304392e6bf4ce04941d72b8bd2df9100e297","src/write/str.rs":"4850cc2fee55980f9cbb6b4169f9861ab9d05c2b28a85c2b790480b83a66f514","src/write/unit.rs":"8876c88dc3529d32e9894acc3194ed99fe437bb7520821c18f9f9f638db08d81","src/write/writer.rs":"7d5dd07b82ec3becebb060c106d4ea697cbd8b9b64a5de78403511a5244e08b1","tests/convert_self.rs":"180909b562969e1691b64628ded8654e6e0b10b3357f39917bd8ac288c5826dd","tests/parse_self.rs":"f2da1c7daef7139545c9367c2f26199e8b4623b31d4ec6480ddd851e6980f2dc"},"package":"dec7af912d60cdbd3677c1af9352ebae6fb8394d165568a2234df0fa00f87793"} \ No newline at end of file
diff --git a/vendor/gimli/CHANGELOG.md b/vendor/gimli/CHANGELOG.md
index 9ca6d70a8..9c3817750 100644
--- a/vendor/gimli/CHANGELOG.md
+++ b/vendor/gimli/CHANGELOG.md
@@ -2,6 +2,27 @@
--------------------------------------------------------------------------------
+## 0.27.0
+
+Released 2022/11/23.
+
+### Breaking changes
+
+* Added `read::Dwarf::abbreviations_cache` to cache abbreviations at offset 0.
+ Changed `read::Dwarf::abbreviations` to return `Result<Arc<Abbreviations>>`,
+ and changed `read::Unit::abbreviations` to `Arc<Abbreviations>`.
+ [#628](https://github.com/gimli-rs/gimli/pull/628)
+
+### Added
+
+* Added LoongArch register definitions.
+ [#624](https://github.com/gimli-rs/gimli/pull/624)
+
+* Added support for tombstones in `read::LocListIter` and `read::RngListIter`.
+ [#631](https://github.com/gimli-rs/gimli/pull/631)
+
+--------------------------------------------------------------------------------
+
## 0.26.2
Released 2022/07/16.
diff --git a/vendor/gimli/Cargo.lock b/vendor/gimli/Cargo.lock
index b4a719a0c..1d8bdf9f4 100644
--- a/vendor/gimli/Cargo.lock
+++ b/vendor/gimli/Cargo.lock
@@ -10,18 +10,18 @@ checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
[[package]]
name = "aho-corasick"
-version = "0.7.18"
+version = "0.7.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1e37cfd5e7657ada45f742d6e99ca5788580b5c529dc78faf11ece6dc702656f"
+checksum = "cc936419f96fa211c1b9166887b38e5e40b19958e5b895be7c1f93adec7071ac"
dependencies = [
"memchr",
]
[[package]]
name = "autocfg"
-version = "1.0.1"
+version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a"
+checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
[[package]]
name = "byteorder"
@@ -37,24 +37,24 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "compiler_builtins"
-version = "0.1.51"
+version = "0.1.84"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3587b3669d6f2c1cfd34c475272dabcfef29d52703933f6f72ebb36d6bd81a97"
+checksum = "989b2c1ca6e90ad06fdc69d1d1862fa28d27a977be6d92ae2fa762cf61fe0b10"
[[package]]
name = "crc32fast"
-version = "1.2.1"
+version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "81156fece84ab6a9f2afdb109ce3ae577e42b1228441eded99bd77f627953b1a"
+checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d"
dependencies = [
"cfg-if",
]
[[package]]
name = "crossbeam"
-version = "0.8.1"
+version = "0.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4ae5588f6b3c3cb05239e90bd110f257254aecd01e4635400391aeae07497845"
+checksum = "2801af0d36612ae591caa9568261fddce32ce6e08a7275ea334a06a4ad021a2c"
dependencies = [
"cfg-if",
"crossbeam-channel",
@@ -66,9 +66,9 @@ dependencies = [
[[package]]
name = "crossbeam-channel"
-version = "0.5.1"
+version = "0.5.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "06ed27e177f16d65f0f0c22a213e17c696ace5dd64b14258b52f9417ccb52db4"
+checksum = "c2dd04ddaf88237dc3b8d8f9a3c1004b506b54b3313403944054d23c0870c521"
dependencies = [
"cfg-if",
"crossbeam-utils",
@@ -76,9 +76,9 @@ dependencies = [
[[package]]
name = "crossbeam-deque"
-version = "0.8.1"
+version = "0.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6455c0ca19f0d2fbf751b908d5c55c1f5cbc65e03c4225427254b46890bdde1e"
+checksum = "715e8152b692bba2d374b53d4875445368fdf21a94751410af607a5ac677d1fc"
dependencies = [
"cfg-if",
"crossbeam-epoch",
@@ -87,22 +87,22 @@ dependencies = [
[[package]]
name = "crossbeam-epoch"
-version = "0.9.5"
+version = "0.9.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4ec02e091aa634e2c3ada4a392989e7c3116673ef0ac5b72232439094d73b7fd"
+checksum = "01a9af1f4c2ef74bb8aa1f7e19706bc72d03598c8a570bb5de72243c7a9d9d5a"
dependencies = [
+ "autocfg",
"cfg-if",
"crossbeam-utils",
- "lazy_static",
"memoffset",
"scopeguard",
]
[[package]]
name = "crossbeam-queue"
-version = "0.3.2"
+version = "0.3.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9b10ddc024425c88c2ad148c1b0fd53f4c6d38db9697c9f1588381212fa657c9"
+checksum = "d1cfb3ea8a53f37c40dea2c7bedcbd88bdfae54f5e2175d6ecaff1c988353add"
dependencies = [
"cfg-if",
"crossbeam-utils",
@@ -110,19 +110,18 @@ dependencies = [
[[package]]
name = "crossbeam-utils"
-version = "0.8.5"
+version = "0.8.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d82cfc11ce7f2c3faef78d8a684447b40d503d9681acebed6cb728d45940c4db"
+checksum = "4fb766fa798726286dbbb842f174001dab8abc7b627a1dd86e0b7222a95d929f"
dependencies = [
"cfg-if",
- "lazy_static",
]
[[package]]
name = "either"
-version = "1.6.1"
+version = "1.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457"
+checksum = "90e5c1c8368803113bf0c9584fc495a58b86dc8a29edbf8fe877d21d9507e797"
[[package]]
name = "fallible-iterator"
@@ -132,13 +131,11 @@ checksum = "4443176a9f2c162692bd3d352d745ef9413eec5782a80d8fd6f8a1ac692a07f7"
[[package]]
name = "flate2"
-version = "1.0.22"
+version = "1.0.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1e6988e897c1c9c485f43b47a529cef42fde0547f9d8d41a7062518f1d8fc53f"
+checksum = "f82b0f4c27ad9f8bfd1f3208d882da2b09c301bc1c828fd3a00d0216d2fbbff6"
dependencies = [
- "cfg-if",
"crc32fast",
- "libc",
"miniz_oxide",
]
@@ -153,7 +150,7 @@ dependencies = [
[[package]]
name = "gimli"
-version = "0.26.2"
+version = "0.27.0"
dependencies = [
"compiler_builtins",
"crossbeam",
@@ -174,9 +171,9 @@ dependencies = [
[[package]]
name = "hashbrown"
-version = "0.11.2"
+version = "0.12.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e"
+checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"
[[package]]
name = "hermit-abi"
@@ -189,65 +186,58 @@ dependencies = [
[[package]]
name = "indexmap"
-version = "1.7.0"
+version = "1.9.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bc633605454125dec4b66843673f01c7df2b89479b32e0ed634e43a91cff62a5"
+checksum = "1885e79c1fc4b10f0e172c475f458b7f7b93061064d98c3293e98c5ba0c8b399"
dependencies = [
"autocfg",
"hashbrown",
]
[[package]]
-name = "lazy_static"
-version = "1.4.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
-
-[[package]]
name = "libc"
-version = "0.2.105"
+version = "0.2.137"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "869d572136620d55835903746bcb5cdc54cb2851fd0aeec53220b4bb65ef3013"
+checksum = "fc7fcc620a3bff7cdd7a365be3376c97191aeaccc2a603e600951e452615bf89"
[[package]]
name = "memchr"
-version = "2.4.1"
+version = "2.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a"
+checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
[[package]]
name = "memmap2"
-version = "0.5.5"
+version = "0.5.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3a79b39c93a7a5a27eeaf9a23b5ff43f1b9e0ad6b1cdd441140ae53c35613fc7"
+checksum = "4b182332558b18d807c4ce1ca8ca983b34c3ee32765e47b3f0f69b90355cc1dc"
dependencies = [
"libc",
]
[[package]]
name = "memoffset"
-version = "0.6.4"
+version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "59accc507f1338036a0477ef61afdae33cde60840f4dfe481319ce3ad116ddf9"
+checksum = "5de893c32cde5f383baa4c04c5d6dbdd735cfd4a794b0debdb2bb1b421da5ff4"
dependencies = [
"autocfg",
]
[[package]]
name = "miniz_oxide"
-version = "0.4.4"
+version = "0.5.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a92518e98c078586bc6c934028adcca4c92a53d6a958196de835170a01d84e4b"
+checksum = "96590ba8f175222643a85693f33d26e9c8a015f599c216509b1a6894af675d34"
dependencies = [
"adler",
- "autocfg",
]
[[package]]
name = "num_cpus"
-version = "1.13.0"
+version = "1.14.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "05499f3756671c15885fee9034446956fff3f243d6077b91e5767df161f766b3"
+checksum = "f6058e64324c71e02bc2b150e4f3bc8286db6c83092132ffa3f6b1eab0f9def5"
dependencies = [
"hermit-abi",
"libc",
@@ -255,9 +245,9 @@ dependencies = [
[[package]]
name = "object"
-version = "0.29.0"
+version = "0.30.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "21158b2c33aa6d4561f1c0a6ea283ca92bc54802a93b263e910746d679a7eb53"
+checksum = "239da7f290cfa979f43f85a8efeee9a8a76d0827c356d37f9d3d7254d6b537fb"
dependencies = [
"flate2",
"memchr",
@@ -266,11 +256,10 @@ dependencies = [
[[package]]
name = "rayon"
-version = "1.5.1"
+version = "1.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c06aca804d41dbc8ba42dfd964f0d01334eceb64314b9ecf7c5fad5188a06d90"
+checksum = "1e060280438193c554f654141c9ea9417886713b7acd75974c85b18a69a88e0b"
dependencies = [
- "autocfg",
"crossbeam-deque",
"either",
"rayon-core",
@@ -278,22 +267,21 @@ dependencies = [
[[package]]
name = "rayon-core"
-version = "1.9.1"
+version = "1.10.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d78120e2c850279833f1dd3582f730c4ab53ed95aeaaaa862a2a5c71b1656d8e"
+checksum = "cac410af5d00ab6884528b4ab69d1e8e146e8d471201800fa1b4524126de6ad3"
dependencies = [
"crossbeam-channel",
"crossbeam-deque",
"crossbeam-utils",
- "lazy_static",
"num_cpus",
]
[[package]]
name = "regex"
-version = "1.5.4"
+version = "1.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d07a8629359eb56f1e2fb1652bb04212c072a87ba68546a04065d525673ac461"
+checksum = "e076559ef8e241f2ae3479e36f97bd5741c0330689e217ad51ce2c76808b868a"
dependencies = [
"aho-corasick",
"memchr",
@@ -302,9 +290,9 @@ dependencies = [
[[package]]
name = "regex-syntax"
-version = "0.6.25"
+version = "0.6.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b"
+checksum = "456c603be3e8d448b072f410900c09faf164fbce2d480456f50eea6e25f9c848"
[[package]]
name = "rustc-std-workspace-alloc"
@@ -347,9 +335,9 @@ checksum = "0685c84d5d54d1c26f7d3eb96cd41550adb97baed141a761cf335d3d33bcd0ae"
[[package]]
name = "unicode-width"
-version = "0.1.9"
+version = "0.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3ed742d4ea2bd1176e236172c8429aaf54486e7ac098db29ffe6529e0ce50973"
+checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b"
[[package]]
name = "wasmparser"
diff --git a/vendor/gimli/Cargo.toml b/vendor/gimli/Cargo.toml
index f36ccd936..2c6004eb9 100644
--- a/vendor/gimli/Cargo.toml
+++ b/vendor/gimli/Cargo.toml
@@ -12,7 +12,7 @@
[package]
edition = "2018"
name = "gimli"
-version = "0.26.2"
+version = "0.27.0"
exclude = [
"/releases/*",
"/.github",
@@ -105,7 +105,7 @@ version = "0.5.5"
version = "1"
[dev-dependencies.object]
-version = "0.29.0"
+version = "0.30.0"
features = ["wasm"]
[dev-dependencies.rayon]
diff --git a/vendor/gimli/README.md b/vendor/gimli/README.md
index 19e7bbd0e..f0d31fbe1 100644
--- a/vendor/gimli/README.md
+++ b/vendor/gimli/README.md
@@ -5,7 +5,7 @@
[![Build Status](https://github.com/gimli-rs/gimli/workflows/Rust/badge.svg)](https://github.com/gimli-rs/gimli/actions)
[![Coverage Status](https://coveralls.io/repos/github/gimli-rs/gimli/badge.svg?branch=master)](https://coveralls.io/github/gimli-rs/gimli?branch=master)
-`gimli` is a blazing fast library for consuming the
+`gimli` is a library for reading and writing the
[DWARF debugging format](https://dwarfstd.org/).
* **Zero copy:** everything is just a reference to the original input buffer. No
@@ -30,7 +30,7 @@ Add this to your `Cargo.toml`:
```toml
[dependencies]
-gimli = "0.26.2"
+gimli = "0.27.0"
```
The minimum supported Rust version is 1.42.0.
diff --git a/vendor/gimli/clippy.toml b/vendor/gimli/clippy.toml
new file mode 100644
index 000000000..f97e544b6
--- /dev/null
+++ b/vendor/gimli/clippy.toml
@@ -0,0 +1 @@
+msrv = "1.42.0"
diff --git a/vendor/gimli/examples/dwarfdump.rs b/vendor/gimli/examples/dwarfdump.rs
index 4b61fd572..22458fa8f 100644
--- a/vendor/gimli/examples/dwarfdump.rs
+++ b/vendor/gimli/examples/dwarfdump.rs
@@ -1859,35 +1859,46 @@ fn dump_op<R: Reader, W: Write>(
Ok(())
}
+fn dump_range<W: Write>(w: &mut W, range: Option<gimli::Range>) -> Result<()> {
+ if let Some(range) = range {
+ write!(w, " [0x{:08x}, 0x{:08x}]", range.begin, range.end)?;
+ } else {
+ write!(w, " [ignored]")?;
+ }
+ Ok(())
+}
+
fn dump_loc_list<R: Reader, W: Write>(
w: &mut W,
offset: gimli::LocationListsOffset<R::Offset>,
unit: &gimli::Unit<R>,
dwarf: &gimli::Dwarf<R>,
) -> Result<()> {
- let raw_locations = dwarf.raw_locations(unit, offset)?;
- let raw_locations: Vec<_> = raw_locations.collect()?;
let mut locations = dwarf.locations(unit, offset)?;
writeln!(
w,
- "<loclist at {}+0x{:08x} with {} entries>",
+ "<loclist at {}+0x{:08x}>",
if unit.encoding().version < 5 {
".debug_loc"
} else {
".debug_loclists"
},
offset.0,
- raw_locations.len()
)?;
- for (i, raw) in raw_locations.iter().enumerate() {
+ let mut i = 0;
+ while let Some(raw) = locations.next_raw()? {
write!(w, "\t\t\t[{:2}]", i)?;
- match *raw {
+ i += 1;
+ let range = locations
+ .convert_raw(raw.clone())?
+ .map(|location| location.range);
+ match raw {
gimli::RawLocListEntry::BaseAddress { addr } => {
- writeln!(w, "<new base address 0x{:08x}>", addr)?;
+ writeln!(w, "<base-address 0x{:08x}>", addr)?;
}
gimli::RawLocListEntry::BaseAddressx { addr } => {
let addr_val = dwarf.address(unit, addr)?;
- writeln!(w, "<new base addressx [{}]0x{:08x}>", addr.0, addr_val)?;
+ writeln!(w, "<base-addressx [{}]0x{:08x}>", addr.0, addr_val)?;
}
gimli::RawLocListEntry::StartxEndx {
begin,
@@ -1896,14 +1907,12 @@ fn dump_loc_list<R: Reader, W: Write>(
} => {
let begin_val = dwarf.address(unit, begin)?;
let end_val = dwarf.address(unit, end)?;
- let location = locations.next()?.unwrap();
write!(
w,
- "<startx-endx \
- low-off: [{}]0x{:08x} addr 0x{:08x} \
- high-off: [{}]0x{:08x} addr 0x{:08x}>",
- begin.0, begin_val, location.range.begin, end.0, end_val, location.range.end
+ "<startx-endx [{}]0x{:08x}, [{}]0x{:08x}>",
+ begin.0, begin_val, end.0, end_val,
)?;
+ dump_range(w, range)?;
dump_exprloc(w, unit.encoding(), data)?;
writeln!(w)?;
}
@@ -1913,14 +1922,12 @@ fn dump_loc_list<R: Reader, W: Write>(
ref data,
} => {
let begin_val = dwarf.address(unit, begin)?;
- let location = locations.next()?.unwrap();
write!(
w,
- "<start-length \
- low-off: [{}]0x{:08x} addr 0x{:08x} \
- high-off: 0x{:08x} addr 0x{:08x}>",
- begin.0, begin_val, location.range.begin, length, location.range.end
+ "<startx-length [{}]0x{:08x}, 0x{:08x}>",
+ begin.0, begin_val, length,
)?;
+ dump_range(w, range)?;
dump_exprloc(w, unit.encoding(), data)?;
writeln!(w)?;
}
@@ -1934,14 +1941,8 @@ fn dump_loc_list<R: Reader, W: Write>(
end,
ref data,
} => {
- let location = locations.next()?.unwrap();
- write!(
- w,
- "<offset pair \
- low-off: 0x{:08x} addr 0x{:08x} \
- high-off: 0x{:08x} addr 0x{:08x}>",
- begin, location.range.begin, end, location.range.end
- )?;
+ write!(w, "<offset-pair 0x{:08x}, 0x{:08x}>", begin, end)?;
+ dump_range(w, range)?;
dump_exprloc(w, unit.encoding(), data)?;
writeln!(w)?;
}
@@ -1955,14 +1956,8 @@ fn dump_loc_list<R: Reader, W: Write>(
end,
ref data,
} => {
- let location = locations.next()?.unwrap();
- write!(
- w,
- "<start-end \
- low-off: 0x{:08x} addr 0x{:08x} \
- high-off: 0x{:08x} addr 0x{:08x}>",
- begin, location.range.begin, end, location.range.end
- )?;
+ write!(w, "<start-end 0x{:08x}, 0x{:08x}>", begin, end)?;
+ dump_range(w, range)?;
dump_exprloc(w, unit.encoding(), data)?;
writeln!(w)?;
}
@@ -1971,14 +1966,8 @@ fn dump_loc_list<R: Reader, W: Write>(
length,
ref data,
} => {
- let location = locations.next()?.unwrap();
- write!(
- w,
- "<start-length \
- low-off: 0x{:08x} addr 0x{:08x} \
- high-off: 0x{:08x} addr 0x{:08x}>",
- begin, location.range.begin, length, location.range.end
- )?;
+ write!(w, "<start-length 0x{:08x}, 0x{:08x}>", begin, length)?;
+ dump_range(w, range)?;
dump_exprloc(w, unit.encoding(), data)?;
writeln!(w)?;
}
@@ -1993,33 +1982,23 @@ fn dump_range_list<R: Reader, W: Write>(
unit: &gimli::Unit<R>,
dwarf: &gimli::Dwarf<R>,
) -> Result<()> {
- let raw_ranges = dwarf.raw_ranges(unit, offset)?;
- let raw_ranges: Vec<_> = raw_ranges.collect()?;
let mut ranges = dwarf.ranges(unit, offset)?;
writeln!(
w,
- "<rnglist at {}+0x{:08x} with {} entries>",
+ "<rnglist at {}+0x{:08x}>",
if unit.encoding().version < 5 {
".debug_ranges"
} else {
".debug_rnglists"
},
offset.0,
- raw_ranges.len()
)?;
- for (i, raw) in raw_ranges.iter().enumerate() {
+ let mut i = 0;
+ while let Some(raw) = ranges.next_raw()? {
write!(w, "\t\t\t[{:2}] ", i)?;
- match *raw {
- gimli::RawRngListEntry::AddressOrOffsetPair { begin, end } => {
- let range = ranges.next()?.unwrap();
- writeln!(
- w,
- "<address pair \
- low-off: 0x{:08x} addr 0x{:08x} \
- high-off: 0x{:08x} addr 0x{:08x}>",
- begin, range.begin, end, range.end
- )?;
- }
+ i += 1;
+ let range = ranges.convert_raw(raw.clone())?;
+ match raw {
gimli::RawRngListEntry::BaseAddress { addr } => {
writeln!(w, "<new base address 0x{:08x}>", addr)?;
}
@@ -2030,66 +2009,39 @@ fn dump_range_list<R: Reader, W: Write>(
gimli::RawRngListEntry::StartxEndx { begin, end } => {
let begin_val = dwarf.address(unit, begin)?;
let end_val = dwarf.address(unit, end)?;
- let range = if begin_val == end_val {
- gimli::Range {
- begin: begin_val,
- end: end_val,
- }
- } else {
- ranges.next()?.unwrap()
- };
- writeln!(
+ write!(
w,
- "<startx-endx \
- low-off: [{}]0x{:08x} addr 0x{:08x} \
- high-off: [{}]0x{:08x} addr 0x{:08x}>",
- begin.0, begin_val, range.begin, end.0, end_val, range.end
+ "<startx-endx [{}]0x{:08x}, [{}]0x{:08x}>",
+ begin.0, begin_val, end.0, end_val,
)?;
+ dump_range(w, range)?;
+ writeln!(w)?;
}
gimli::RawRngListEntry::StartxLength { begin, length } => {
let begin_val = dwarf.address(unit, begin)?;
- let range = ranges.next()?.unwrap();
- writeln!(
+ write!(
w,
- "<startx-length \
- low-off: [{}]0x{:08x} addr 0x{:08x} \
- high-off: 0x{:08x} addr 0x{:08x}>",
- begin.0, begin_val, range.begin, length, range.end
+ "<startx-length [{}]0x{:08x}, 0x{:08x}>",
+ begin.0, begin_val, length,
)?;
+ dump_range(w, range)?;
+ writeln!(w)?;
}
- gimli::RawRngListEntry::OffsetPair { begin, end } => {
- let range = ranges.next()?.unwrap();
- writeln!(
- w,
- "<offset pair \
- low-off: 0x{:08x} addr 0x{:08x} \
- high-off: 0x{:08x} addr 0x{:08x}>",
- begin, range.begin, end, range.end
- )?;
+ gimli::RawRngListEntry::AddressOrOffsetPair { begin, end }
+ | gimli::RawRngListEntry::OffsetPair { begin, end } => {
+ write!(w, "<offset-pair 0x{:08x}, 0x{:08x}>", begin, end)?;
+ dump_range(w, range)?;
+ writeln!(w)?;
}
gimli::RawRngListEntry::StartEnd { begin, end } => {
- let range = if begin == end {
- gimli::Range { begin, end }
- } else {
- ranges.next()?.unwrap()
- };
- writeln!(
- w,
- "<start-end \
- low-off: 0x{:08x} addr 0x{:08x} \
- high-off: 0x{:08x} addr 0x{:08x}>",
- begin, range.begin, end, range.end
- )?;
+ write!(w, "<start-end 0x{:08x}, 0x{:08x}>", begin, end)?;
+ dump_range(w, range)?;
+ writeln!(w)?;
}
gimli::RawRngListEntry::StartLength { begin, length } => {
- let range = ranges.next()?.unwrap();
- writeln!(
- w,
- "<start-length \
- low-off: 0x{:08x} addr 0x{:08x} \
- high-off: 0x{:08x} addr 0x{:08x}>",
- begin, range.begin, length, range.end
- )?;
+ write!(w, "<start-length 0x{:08x}, 0x{:08x}>", begin, length)?;
+ dump_range(w, range)?;
+ writeln!(w)?;
}
};
}
diff --git a/vendor/gimli/src/arch.rs b/vendor/gimli/src/arch.rs
index f5b2e5ed8..abc872d83 100644
--- a/vendor/gimli/src/arch.rs
+++ b/vendor/gimli/src/arch.rs
@@ -291,6 +291,154 @@ registers!(AArch64, {
V31 = (95, "V31"),
});
+/// LoongArch architecture specific definitions.
+///
+/// See [LoongArch ELF psABI specification](https://loongson.github.io/LoongArch-Documentation/LoongArch-ELF-ABI-EN.html).
+#[derive(Debug, Clone, Copy)]
+pub struct LoongArch;
+
+registers!(LoongArch, {
+ R0 = (0, "$r0"),
+ R1 = (1, "$r1"),
+ R2 = (2, "$r2"),
+ R3 = (3, "$r3"),
+ R4 = (4, "$r4"),
+ R5 = (5, "$r5"),
+ R6 = (6, "$r6"),
+ R7 = (7, "$r7"),
+ R8 = (8, "$r8"),
+ R9 = (9, "$r9"),
+ R10 = (10, "$r10"),
+ R11 = (11, "$r11"),
+ R12 = (12, "$r12"),
+ R13 = (13, "$r13"),
+ R14 = (14, "$r14"),
+ R15 = (15, "$r15"),
+ R16 = (16, "$r16"),
+ R17 = (17, "$r17"),
+ R18 = (18, "$r18"),
+ R19 = (19, "$r19"),
+ R20 = (20, "$r20"),
+ R21 = (21, "$r21"),
+ R22 = (22, "$r22"),
+ R23 = (23, "$r23"),
+ R24 = (24, "$r24"),
+ R25 = (25, "$r25"),
+ R26 = (26, "$r26"),
+ R27 = (27, "$r27"),
+ R28 = (28, "$r28"),
+ R29 = (29, "$r29"),
+ R30 = (30, "$r30"),
+ R31 = (31, "$r31"),
+
+ F0 = (32, "$f0"),
+ F1 = (33, "$f1"),
+ F2 = (34, "$f2"),
+ F3 = (35, "$f3"),
+ F4 = (36, "$f4"),
+ F5 = (37, "$f5"),
+ F6 = (38, "$f6"),
+ F7 = (39, "$f7"),
+ F8 = (40, "$f8"),
+ F9 = (41, "$f9"),
+ F10 = (42, "$f10"),
+ F11 = (43, "$f11"),
+ F12 = (44, "$f12"),
+ F13 = (45, "$f13"),
+ F14 = (46, "$f14"),
+ F15 = (47, "$f15"),
+ F16 = (48, "$f16"),
+ F17 = (49, "$f17"),
+ F18 = (50, "$f18"),
+ F19 = (51, "$f19"),
+ F20 = (52, "$f20"),
+ F21 = (53, "$f21"),
+ F22 = (54, "$f22"),
+ F23 = (55, "$f23"),
+ F24 = (56, "$f24"),
+ F25 = (57, "$f25"),
+ F26 = (58, "$f26"),
+ F27 = (59, "$f27"),
+ F28 = (60, "$f28"),
+ F29 = (61, "$f29"),
+ F30 = (62, "$f30"),
+ F31 = (63, "$f31"),
+ FCC0 = (64, "$fcc0"),
+ FCC1 = (65, "$fcc1"),
+ FCC2 = (66, "$fcc2"),
+ FCC3 = (67, "$fcc3"),
+ FCC4 = (68, "$fcc4"),
+ FCC5 = (69, "$fcc5"),
+ FCC6 = (70, "$fcc6"),
+ FCC7 = (71, "$fcc7"),
+},
+aliases {
+ ZERO = (0, "$zero"),
+ RA = (1, "$ra"),
+ TP = (2, "$tp"),
+ SP = (3, "$sp"),
+ A0 = (4, "$a0"),
+ A1 = (5, "$a1"),
+ A2 = (6, "$a2"),
+ A3 = (7, "$a3"),
+ A4 = (8, "$a4"),
+ A5 = (9, "$a5"),
+ A6 = (10, "$a6"),
+ A7 = (11, "$a7"),
+ T0 = (12, "$t0"),
+ T1 = (13, "$t1"),
+ T2 = (14, "$t2"),
+ T3 = (15, "$t3"),
+ T4 = (16, "$t4"),
+ T5 = (17, "$t5"),
+ T6 = (18, "$t6"),
+ T7 = (19, "$t7"),
+ T8 = (20, "$t8"),
+ FP = (22, "$fp"),
+ S0 = (23, "$s0"),
+ S1 = (24, "$s1"),
+ S2 = (25, "$s2"),
+ S3 = (26, "$s3"),
+ S4 = (27, "$s4"),
+ S5 = (28, "$s5"),
+ S6 = (29, "$s6"),
+ S7 = (30, "$s7"),
+ S8 = (31, "$s8"),
+
+ FA0 = (32, "$fa0"),
+ FA1 = (33, "$fa1"),
+ FA2 = (34, "$fa2"),
+ FA3 = (35, "$fa3"),
+ FA4 = (36, "$fa4"),
+ FA5 = (37, "$fa5"),
+ FA6 = (38, "$fa6"),
+ FA7 = (39, "$fa7"),
+ FT0 = (40, "$ft0"),
+ FT1 = (41, "$ft1"),
+ FT2 = (42, "$ft2"),
+ FT3 = (43, "$ft3"),
+ FT4 = (44, "$ft4"),
+ FT5 = (45, "$ft5"),
+ FT6 = (46, "$ft6"),
+ FT7 = (47, "$ft7"),
+ FT8 = (48, "$ft8"),
+ FT9 = (49, "$ft9"),
+ FT10 = (50, "$ft10"),
+ FT11 = (51, "$ft11"),
+ FT12 = (52, "$ft12"),
+ FT13 = (53, "$ft13"),
+ FT14 = (54, "$ft14"),
+ FT15 = (55, "$ft15"),
+ FS0 = (56, "$fs0"),
+ FS1 = (57, "$fs1"),
+ FS2 = (58, "$fs2"),
+ FS3 = (59, "$fs3"),
+ FS4 = (60, "$fs4"),
+ FS5 = (61, "$fs5"),
+ FS6 = (62, "$fs6"),
+ FS7 = (63, "$fs7"),
+});
+
/// RISC-V architecture specific definitions.
///
/// See [RISC-V ELF psABI specification](https://github.com/riscv/riscv-elf-psabi-doc).
diff --git a/vendor/gimli/src/lib.rs b/vendor/gimli/src/lib.rs
index ed1af9cbd..db30375aa 100644
--- a/vendor/gimli/src/lib.rs
+++ b/vendor/gimli/src/lib.rs
@@ -26,14 +26,17 @@
#![warn(ellipsis_inclusive_range_patterns)]
//#![warn(elided_lifetimes_in_paths)]
#![warn(explicit_outlives_requirements)]
-// Allow clippy warnings when we aren't building with clippy.
-#![allow(unknown_lints)]
+// Style.
+#![allow(clippy::bool_to_int_with_if)]
+#![allow(clippy::collapsible_else_if)]
+#![allow(clippy::comparison_chain)]
+#![allow(clippy::manual_range_contains)]
+#![allow(clippy::needless_late_init)]
+#![allow(clippy::too_many_arguments)]
// False positives with `fallible_iterator`.
#![allow(clippy::should_implement_trait)]
-// Many false positives involving `continue`.
-#![allow(clippy::never_loop)]
-// False positives when block expressions are used inside an assertion.
-#![allow(clippy::panic_params)]
+// False positives.
+#![allow(clippy::derive_partial_eq_without_eq)]
#![no_std]
#[allow(unused_imports)]
diff --git a/vendor/gimli/src/read/abbrev.rs b/vendor/gimli/src/read/abbrev.rs
index 1a24835a7..54f5cf8e5 100644
--- a/vendor/gimli/src/read/abbrev.rs
+++ b/vendor/gimli/src/read/abbrev.rs
@@ -1,6 +1,7 @@
//! Functions for parsing DWARF debugging abbreviations.
use alloc::collections::btree_map;
+use alloc::sync::Arc;
use alloc::vec::Vec;
use core::convert::TryFrom;
use core::fmt::{self, Debug};
@@ -10,7 +11,8 @@ use core::ops::Deref;
use crate::common::{DebugAbbrevOffset, Encoding, SectionId};
use crate::constants;
use crate::endianity::Endianity;
-use crate::read::{EndianSlice, Error, Reader, Result, Section, UnitHeader};
+use crate::read::lazy::LazyArc;
+use crate::read::{EndianSlice, Error, Reader, ReaderOffset, Result, Section, UnitHeader};
/// The `DebugAbbrev` struct represents the abbreviations describing
/// `DebuggingInformationEntry`s' attribute names and forms found in the
@@ -100,6 +102,38 @@ impl<R> From<R> for DebugAbbrev<R> {
}
}
+/// A cache of previously parsed `Abbreviations`.
+///
+/// Currently this only caches the abbreviations for offset 0,
+/// since this is a common case in which abbreviations are reused.
+/// This strategy may change in future if there is sufficient need.
+#[derive(Debug, Default)]
+pub struct AbbreviationsCache {
+ abbreviations: LazyArc<Abbreviations>,
+}
+
+impl AbbreviationsCache {
+ /// Create an empty abbreviations cache.
+ pub fn new() -> Self {
+ Self::default()
+ }
+
+ /// Parse the abbreviations at the given offset.
+ ///
+ /// This uses or updates the cache as required.
+ pub fn get<R: Reader>(
+ &self,
+ debug_abbrev: &DebugAbbrev<R>,
+ offset: DebugAbbrevOffset<R::Offset>,
+ ) -> Result<Arc<Abbreviations>> {
+ if offset.0 != R::Offset::from_u8(0) {
+ return debug_abbrev.abbreviations(offset).map(Arc::new);
+ }
+ self.abbreviations
+ .get(|| debug_abbrev.abbreviations(offset))
+ }
+}
+
/// A set of type abbreviations.
///
/// Construct an `Abbreviations` instance with the
@@ -310,7 +344,7 @@ impl Attributes {
/// Pushes a new value onto this list of attributes.
fn push(&mut self, attr: AttributeSpecification) {
match self {
- Attributes::Heap(list) => return list.push(attr),
+ Attributes::Heap(list) => list.push(attr),
Attributes::Inline {
buf,
len: MAX_ATTRIBUTES_INLINE,
@@ -329,13 +363,13 @@ impl Attributes {
impl Debug for Attributes {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- (&**self).fmt(f)
+ (**self).fmt(f)
}
}
impl PartialEq for Attributes {
fn eq(&self, other: &Attributes) -> bool {
- &**self == &**other
+ **self == **other
}
}
@@ -360,7 +394,7 @@ impl FromIterator<AttributeSpecification> for Attributes {
for item in iter {
list.push(item);
}
- return list;
+ list
}
}
@@ -470,8 +504,7 @@ pub(crate) fn get_attribute_size(form: constants::DwForm, encoding: Encoding) ->
match form {
constants::DW_FORM_addr => Some(encoding.address_size),
- constants::DW_FORM_implicit_const |
- constants::DW_FORM_flag_present => Some(0),
+ constants::DW_FORM_implicit_const | constants::DW_FORM_flag_present => Some(0),
constants::DW_FORM_data1
| constants::DW_FORM_flag
@@ -497,7 +530,7 @@ pub(crate) fn get_attribute_size(form: constants::DwForm, encoding: Encoding) ->
| constants::DW_FORM_ref_sig8
| constants::DW_FORM_ref_sup8 => Some(8),
- constants::DW_FORM_data16 => Some(16),
+ constants::DW_FORM_data16 => Some(16),
constants::DW_FORM_sec_offset
| constants::DW_FORM_GNU_ref_alt
@@ -518,16 +551,16 @@ pub(crate) fn get_attribute_size(form: constants::DwForm, encoding: Encoding) ->
}
// Variably sized forms.
- constants::DW_FORM_block |
- constants::DW_FORM_block1 |
- constants::DW_FORM_block2 |
- constants::DW_FORM_block4 |
- constants::DW_FORM_exprloc |
- constants::DW_FORM_ref_udata |
- constants::DW_FORM_string |
- constants::DW_FORM_sdata |
- constants::DW_FORM_udata |
- constants::DW_FORM_indirect |
+ constants::DW_FORM_block
+ | constants::DW_FORM_block1
+ | constants::DW_FORM_block2
+ | constants::DW_FORM_block4
+ | constants::DW_FORM_exprloc
+ | constants::DW_FORM_ref_udata
+ | constants::DW_FORM_string
+ | constants::DW_FORM_sdata
+ | constants::DW_FORM_udata
+ | constants::DW_FORM_indirect => None,
// We don't know the size of unknown forms.
_ => None,
@@ -993,4 +1026,64 @@ pub mod tests {
.unwrap();
assert!(abbrevs.get(0).is_none());
}
+
+ #[test]
+ fn abbreviations_cache() {
+ #[rustfmt::skip]
+ let buf = Section::new()
+ .abbrev(1, constants::DW_TAG_subprogram, constants::DW_CHILDREN_no)
+ .abbrev_attr(constants::DW_AT_name, constants::DW_FORM_string)
+ .abbrev_attr_null()
+ .abbrev_null()
+ .abbrev(1, constants::DW_TAG_compile_unit, constants::DW_CHILDREN_yes)
+ .abbrev_attr(constants::DW_AT_producer, constants::DW_FORM_strp)
+ .abbrev_attr(constants::DW_AT_language, constants::DW_FORM_data2)
+ .abbrev_attr_null()
+ .abbrev_null()
+ .get_contents()
+ .unwrap();
+
+ let abbrev1 = Abbreviation::new(
+ 1,
+ constants::DW_TAG_subprogram,
+ constants::DW_CHILDREN_no,
+ vec![AttributeSpecification::new(
+ constants::DW_AT_name,
+ constants::DW_FORM_string,
+ None,
+ )]
+ .into(),
+ );
+
+ let abbrev2 = Abbreviation::new(
+ 1,
+ constants::DW_TAG_compile_unit,
+ constants::DW_CHILDREN_yes,
+ vec![
+ AttributeSpecification::new(
+ constants::DW_AT_producer,
+ constants::DW_FORM_strp,
+ None,
+ ),
+ AttributeSpecification::new(
+ constants::DW_AT_language,
+ constants::DW_FORM_data2,
+ None,
+ ),
+ ]
+ .into(),
+ );
+
+ let debug_abbrev = DebugAbbrev::new(&buf, LittleEndian);
+ let cache = AbbreviationsCache::new();
+ let abbrevs1 = cache.get(&debug_abbrev, DebugAbbrevOffset(0)).unwrap();
+ assert_eq!(abbrevs1.get(1), Some(&abbrev1));
+ let abbrevs2 = cache.get(&debug_abbrev, DebugAbbrevOffset(8)).unwrap();
+ assert_eq!(abbrevs2.get(1), Some(&abbrev2));
+ let abbrevs3 = cache.get(&debug_abbrev, DebugAbbrevOffset(0)).unwrap();
+ assert_eq!(abbrevs3.get(1), Some(&abbrev1));
+
+ assert!(!Arc::ptr_eq(&abbrevs1, &abbrevs2));
+ assert!(Arc::ptr_eq(&abbrevs1, &abbrevs3));
+ }
}
diff --git a/vendor/gimli/src/read/cfi.rs b/vendor/gimli/src/read/cfi.rs
index 2e5167349..5e9befac1 100644
--- a/vendor/gimli/src/read/cfi.rs
+++ b/vendor/gimli/src/read/cfi.rs
@@ -1058,7 +1058,6 @@ where
Fde(PartialFrameDescriptionEntry<'bases, Section, R>),
}
-#[allow(clippy::type_complexity)]
fn parse_cfi_entry<'bases, Section, R>(
bases: &'bases BaseAddresses,
section: &Section,
@@ -1617,7 +1616,6 @@ where
}
impl<R: Reader> FrameDescriptionEntry<R> {
- #[allow(clippy::too_many_arguments)]
fn parse_rest<Section, F>(
offset: R::Offset,
length: R::Offset,
@@ -1982,7 +1980,7 @@ impl<R: Reader, A: UnwindContextStorage<R>> UnwindContext<R, A> {
}
let mut table = UnwindTable::new_for_cie(section, bases, self, cie);
- while let Some(_) = table.next_row()? {}
+ while table.next_row()?.is_some() {}
self.save_initial_rules()?;
Ok(())
@@ -2005,7 +2003,7 @@ impl<R: Reader, A: UnwindContextStorage<R>> UnwindContext<R, A> {
}
fn save_initial_rules(&mut self) -> Result<()> {
- assert_eq!(self.is_initialized, false);
+ debug_assert!(!self.is_initialized);
self.initial_rule = match *self.stack.last().unwrap().registers.rules {
// All rules are default (undefined). In this case just synthesize
// an undefined rule.
@@ -2821,10 +2819,7 @@ pub enum RegisterRule<R: Reader> {
impl<R: Reader> RegisterRule<R> {
fn is_defined(&self) -> bool {
- match *self {
- RegisterRule::Undefined => false,
- _ => true,
- }
+ !matches!(*self, RegisterRule::Undefined)
}
}
@@ -3394,10 +3389,10 @@ impl Default for Pointer {
}
}
-impl Into<u64> for Pointer {
+impl From<Pointer> for u64 {
#[inline]
- fn into(self) -> u64 {
- match self {
+ fn from(p: Pointer) -> u64 {
+ match p {
Pointer::Direct(p) | Pointer::Indirect(p) => p,
}
}
@@ -3762,8 +3757,6 @@ mod tests {
}
}
- #[allow(clippy::type_complexity)]
- #[allow(clippy::needless_pass_by_value)]
fn assert_parse_cie<'input, E>(
kind: SectionKind<DebugFrame<EndianSlice<'input, E>>>,
section: Section,
@@ -5118,7 +5111,6 @@ mod tests {
assert_eq!(iter.next(), Ok(None));
}
- #[allow(clippy::needless_pass_by_value)]
fn assert_eval<'a, I>(
mut initial_ctx: UnwindContext<EndianSlice<'a, LittleEndian>>,
expected_ctx: UnwindContext<EndianSlice<'a, LittleEndian>>,
@@ -5598,7 +5590,6 @@ mod tests {
#[test]
fn test_unwind_table_cie_no_rule() {
- #[allow(clippy::identity_op)]
let initial_instructions = Section::with_endian(Endian::Little)
// The CFA is -12 from register 4.
.D8(constants::DW_CFA_def_cfa_sf.0)
@@ -5671,7 +5662,6 @@ mod tests {
#[test]
fn test_unwind_table_cie_single_rule() {
- #[allow(clippy::identity_op)]
let initial_instructions = Section::with_endian(Endian::Little)
// The CFA is -12 from register 4.
.D8(constants::DW_CFA_def_cfa_sf.0)
@@ -5747,7 +5737,6 @@ mod tests {
#[test]
fn test_unwind_table_next_row() {
- #[allow(clippy::identity_op)]
let initial_instructions = Section::with_endian(Endian::Little)
// The CFA is -12 from register 4.
.D8(constants::DW_CFA_def_cfa_sf.0)
diff --git a/vendor/gimli/src/read/dwarf.rs b/vendor/gimli/src/read/dwarf.rs
index b63526941..cce364c2b 100644
--- a/vendor/gimli/src/read/dwarf.rs
+++ b/vendor/gimli/src/read/dwarf.rs
@@ -9,11 +9,11 @@ use crate::common::{
};
use crate::constants;
use crate::read::{
- Abbreviations, AttributeValue, DebugAbbrev, DebugAddr, DebugAranges, DebugCuIndex, DebugInfo,
- DebugInfoUnitHeadersIter, DebugLine, DebugLineStr, DebugLoc, DebugLocLists, DebugRngLists,
- DebugStr, DebugStrOffsets, DebugTuIndex, DebugTypes, DebugTypesUnitHeadersIter,
- DebuggingInformationEntry, EntriesCursor, EntriesRaw, EntriesTree, Error,
- IncompleteLineProgram, LocListIter, LocationLists, Range, RangeLists, RawLocListIter,
+ Abbreviations, AbbreviationsCache, AttributeValue, DebugAbbrev, DebugAddr, DebugAranges,
+ DebugCuIndex, DebugInfo, DebugInfoUnitHeadersIter, DebugLine, DebugLineStr, DebugLoc,
+ DebugLocLists, DebugRngLists, DebugStr, DebugStrOffsets, DebugTuIndex, DebugTypes,
+ DebugTypesUnitHeadersIter, DebuggingInformationEntry, EntriesCursor, EntriesRaw, EntriesTree,
+ Error, IncompleteLineProgram, LocListIter, LocationLists, Range, RangeLists, RawLocListIter,
RawRngListIter, Reader, ReaderOffset, ReaderOffsetId, Result, RngListIter, Section, UnitHeader,
UnitIndex, UnitIndexSectionIterator, UnitOffset, UnitType,
};
@@ -59,6 +59,9 @@ pub struct Dwarf<R> {
/// The DWARF sections for a supplementary object file.
pub sup: Option<Arc<Dwarf<R>>>,
+
+ /// A cache of previously parsed abbreviations for units in this file.
+ pub abbreviations_cache: AbbreviationsCache,
}
impl<T> Dwarf<T> {
@@ -96,6 +99,7 @@ impl<T> Dwarf<T> {
ranges: RangeLists::new(debug_ranges, debug_rnglists),
file_type: DwarfFileType::Main,
sup: None,
+ abbreviations_cache: AbbreviationsCache::new(),
})
}
@@ -157,6 +161,7 @@ impl<T> Dwarf<T> {
ranges: self.ranges.borrow(&mut borrow),
file_type: self.file_type,
sup: self.sup().map(|sup| Arc::new(sup.borrow(borrow))),
+ abbreviations_cache: AbbreviationsCache::new(),
}
}
@@ -192,10 +197,10 @@ impl<R: Reader> Dwarf<R> {
}
/// Parse the abbreviations for a compilation unit.
- // TODO: provide caching of abbreviations
#[inline]
- pub fn abbreviations(&self, unit: &UnitHeader<R>) -> Result<Abbreviations> {
- unit.abbreviations(&self.debug_abbrev)
+ pub fn abbreviations(&self, unit: &UnitHeader<R>) -> Result<Arc<Abbreviations>> {
+ self.abbreviations_cache
+ .get(&self.debug_abbrev, unit.debug_abbrev_offset())
}
/// Return the string offset at the given index.
@@ -783,6 +788,7 @@ impl<R: Reader> DwarfPackage<R> {
ranges: RangeLists::new(debug_ranges, debug_rnglists),
file_type: DwarfFileType::Dwo,
sup: None,
+ abbreviations_cache: AbbreviationsCache::new(),
})
}
}
@@ -799,7 +805,7 @@ where
pub header: UnitHeader<R, Offset>,
/// The parsed abbreviations for the unit.
- pub abbreviations: Abbreviations,
+ pub abbreviations: Arc<Abbreviations>,
/// The `DW_AT_name` attribute of the unit.
pub name: Option<R>,
@@ -833,7 +839,7 @@ impl<R: Reader> Unit<R> {
/// Construct a new `Unit` from the given unit header.
#[inline]
pub fn new(dwarf: &Dwarf<R>, header: UnitHeader<R>) -> Result<Self> {
- let abbreviations = header.abbreviations(&dwarf.debug_abbrev)?;
+ let abbreviations = dwarf.abbreviations(&header)?;
let mut unit = Unit {
abbreviations,
name: None,
diff --git a/vendor/gimli/src/read/endian_slice.rs b/vendor/gimli/src/read/endian_slice.rs
index 05262cdec..d0fd67c0b 100644
--- a/vendor/gimli/src/read/endian_slice.rs
+++ b/vendor/gimli/src/read/endian_slice.rs
@@ -197,12 +197,12 @@ where
}
}
-impl<'input, Endian> Into<&'input [u8]> for EndianSlice<'input, Endian>
+impl<'input, Endian> From<EndianSlice<'input, Endian>> for &'input [u8]
where
Endian: Endianity,
{
- fn into(self) -> &'input [u8] {
- self.slice
+ fn from(endian_slice: EndianSlice<'input, Endian>) -> &'input [u8] {
+ endian_slice.slice
}
}
diff --git a/vendor/gimli/src/read/lazy.rs b/vendor/gimli/src/read/lazy.rs
new file mode 100644
index 000000000..6138735c8
--- /dev/null
+++ b/vendor/gimli/src/read/lazy.rs
@@ -0,0 +1,116 @@
+pub(crate) use imp::*;
+
+#[cfg(not(feature = "std"))]
+mod imp {
+ use alloc::sync::Arc;
+ use core::sync::atomic::{AtomicPtr, Ordering};
+ use core::{mem, ptr};
+
+ #[derive(Debug, Default)]
+ pub(crate) struct LazyArc<T> {
+ // Only written once with a value obtained from `Arc<T>::into_raw`.
+ // This holds a ref count for the `Arc`, so it is always safe to
+ // clone the `Arc` given a reference to the `LazyArc`.
+ value: AtomicPtr<T>,
+ }
+
+ impl<T> Drop for LazyArc<T> {
+ fn drop(&mut self) {
+ let value_ptr = self.value.load(Ordering::Acquire);
+ if !value_ptr.is_null() {
+ // SAFETY: all writes to `self.value` are pointers obtained from `Arc::into_raw`.
+ drop(unsafe { Arc::from_raw(value_ptr) });
+ }
+ }
+ }
+
+ impl<T> LazyArc<T> {
+ pub(crate) fn get<E, F: FnOnce() -> Result<T, E>>(&self, f: F) -> Result<Arc<T>, E> {
+ // Clone an `Arc` given a pointer obtained from `Arc::into_raw`.
+ // SAFETY: `value_ptr` must be a valid pointer obtained from `Arc<T>::into_raw`.
+ unsafe fn clone_arc_ptr<T>(value_ptr: *const T) -> Arc<T> {
+ let value = Arc::from_raw(value_ptr);
+ let clone = Arc::clone(&value);
+ mem::forget(value);
+ clone
+ }
+
+ // Return the existing value if already computed.
+ // `Ordering::Acquire` is needed so that the content of the loaded `Arc` is
+ // visible to this thread.
+ let value_ptr = self.value.load(Ordering::Acquire);
+ if !value_ptr.is_null() {
+ // SAFETY: all writes to `self.value` are pointers obtained from `Arc::into_raw`.
+ return Ok(unsafe { clone_arc_ptr(value_ptr) });
+ }
+
+ // Race to compute and set the value.
+ let value = f().map(Arc::new)?;
+ let value_ptr = Arc::into_raw(value);
+ match self.value.compare_exchange(
+ ptr::null_mut(),
+ value_ptr as *mut T,
+ // Success: `Ordering::Release` is needed so that the content of the stored `Arc`
+ // is visible to other threads. No ordering is required for the null ptr that is
+ // loaded, but older rust versions (< 1.64) require that its ordering must not
+ // be weaker than the failure ordering, so we use `Ordering::AcqRel`.
+ Ordering::AcqRel,
+ // Failure: `Ordering::Acquire` is needed so that the content of the loaded `Arc`
+ // is visible to this thread.
+ Ordering::Acquire,
+ ) {
+ Ok(_) => {
+ // Return the value we computed.
+ // SAFETY: `value_ptr` was obtained from `Arc::into_raw`.
+ Ok(unsafe { clone_arc_ptr(value_ptr) })
+ }
+ Err(existing_value_ptr) => {
+ // We lost the race, drop unneeded `value_ptr`.
+ // SAFETY: `value_ptr` was obtained from `Arc::into_raw`.
+ drop(unsafe { Arc::from_raw(value_ptr) });
+ // Return the existing value.
+ // SAFETY: all writes to `self.value` are pointers obtained from `Arc::into_raw`.
+ Ok(unsafe { clone_arc_ptr(existing_value_ptr) })
+ }
+ }
+ }
+ }
+}
+
+#[cfg(feature = "std")]
+mod imp {
+ use std::sync::{Arc, Mutex};
+
+ #[derive(Debug, Default)]
+ pub(crate) struct LazyArc<T> {
+ value: Mutex<Option<Arc<T>>>,
+ }
+
+ impl<T> LazyArc<T> {
+ pub(crate) fn get<E, F: FnOnce() -> Result<T, E>>(&self, f: F) -> Result<Arc<T>, E> {
+ let mut lock = self.value.lock().unwrap();
+ if let Some(value) = &*lock {
+ return Ok(value.clone());
+ }
+ let value = f().map(Arc::new)?;
+ *lock = Some(value.clone());
+ Ok(value)
+ }
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+
+ #[test]
+ fn lazy_arc() {
+ let lazy = LazyArc::default();
+ let value = lazy.get(|| Err(()));
+ assert_eq!(value, Err(()));
+ let value = lazy.get(|| Ok::<i32, ()>(3)).unwrap();
+ assert_eq!(*value, 3);
+ let value = lazy.get(|| Err(())).unwrap();
+ assert_eq!(*value, 3);
+ }
+}
diff --git a/vendor/gimli/src/read/line.rs b/vendor/gimli/src/read/line.rs
index 0e7380bb9..f7f44b2b5 100644
--- a/vendor/gimli/src/read/line.rs
+++ b/vendor/gimli/src/read/line.rs
@@ -198,7 +198,6 @@ where
R: Reader<Offset = Offset>,
Offset: ReaderOffset,
{
- #[allow(clippy::new_ret_no_self)]
fn new(program: IncompleteLineProgram<R, Offset>) -> OneShotLineRows<R, Offset> {
let row = LineRow::new(program.header());
let instructions = LineInstructions {
@@ -606,7 +605,6 @@ impl<R: Reader> LineInstructions<R> {
///
/// Unfortunately, the `header` parameter means that this cannot be a
/// `FallibleIterator`.
- #[allow(clippy::inline_always)]
#[inline(always)]
pub fn next_instruction(
&mut self,
diff --git a/vendor/gimli/src/read/loclists.rs b/vendor/gimli/src/read/loclists.rs
index 3902c181b..5cba675d2 100644
--- a/vendor/gimli/src/read/loclists.rs
+++ b/vendor/gimli/src/read/loclists.rs
@@ -233,7 +233,7 @@ impl<R: Reader> LocationLists<R> {
let (mut input, format) = if unit_encoding.version <= 4 {
(self.debug_loc.section.clone(), LocListsFormat::Bare)
} else {
- (self.debug_loclists.section.clone(), LocListsFormat::LLE)
+ (self.debug_loclists.section.clone(), LocListsFormat::Lle)
};
input.skip(offset.0)?;
Ok(RawLocListIter::new(input, unit_encoding, format))
@@ -259,7 +259,7 @@ impl<R: Reader> LocationLists<R> {
Ok(RawLocListIter::new(
input,
unit_encoding,
- LocListsFormat::LLE,
+ LocListsFormat::Lle,
))
}
@@ -300,7 +300,7 @@ enum LocListsFormat {
Bare,
/// The DW_LLE encoded range list format used in DWARF 5 and the non-standard GNU
/// split dwarf extension.
- LLE,
+ Lle,
}
/// A raw iterator over a location list.
@@ -402,10 +402,10 @@ fn parse_data<R: Reader>(input: &mut R, encoding: Encoding) -> Result<Expression
impl<R: Reader> RawLocListEntry<R> {
/// Parse a location list entry from `.debug_loclists`
fn parse(input: &mut R, encoding: Encoding, format: LocListsFormat) -> Result<Option<Self>> {
- match format {
+ Ok(match format {
LocListsFormat::Bare => {
let range = RawRange::parse(input, encoding.address_size)?;
- return Ok(if range.is_end() {
+ if range.is_end() {
None
} else if range.is_base_address(encoding.address_size) {
Some(RawLocListEntry::BaseAddress { addr: range.end })
@@ -417,9 +417,9 @@ impl<R: Reader> RawLocListEntry<R> {
end: range.end,
data,
})
- });
+ }
}
- LocListsFormat::LLE => Ok(match constants::DwLle(input.read_u8()?) {
+ LocListsFormat::Lle => match constants::DwLle(input.read_u8()?) {
constants::DW_LLE_end_of_list => None,
constants::DW_LLE_base_addressx => Some(RawLocListEntry::BaseAddressx {
addr: DebugAddrIndex(input.read_uleb128().and_then(R::Offset::from_u64)?),
@@ -463,8 +463,8 @@ impl<R: Reader> RawLocListEntry<R> {
_ => {
return Err(Error::InvalidAddressRange);
}
- }),
- }
+ },
+ })
}
}
@@ -552,63 +552,96 @@ impl<R: Reader> LocListIter<R> {
None => return Ok(None),
};
- let (range, data) = match raw_loc {
- RawLocListEntry::BaseAddress { addr } => {
- self.base_address = addr;
- continue;
- }
- RawLocListEntry::BaseAddressx { addr } => {
- self.base_address = self.get_address(addr)?;
- continue;
- }
- RawLocListEntry::StartxEndx { begin, end, data } => {
- let begin = self.get_address(begin)?;
- let end = self.get_address(end)?;
- (Range { begin, end }, data)
- }
- RawLocListEntry::StartxLength {
- begin,
- length,
- data,
- } => {
- let begin = self.get_address(begin)?;
- let end = begin + length;
- (Range { begin, end }, data)
- }
- RawLocListEntry::DefaultLocation { data } => (
- Range {
- begin: 0,
- end: u64::max_value(),
- },
- data,
- ),
- RawLocListEntry::AddressOrOffsetPair { begin, end, data }
- | RawLocListEntry::OffsetPair { begin, end, data } => {
- let mut range = Range { begin, end };
- range.add_base_address(self.base_address, self.raw.encoding.address_size);
- (range, data)
- }
- RawLocListEntry::StartEnd { begin, end, data } => (Range { begin, end }, data),
- RawLocListEntry::StartLength {
- begin,
- length,
- data,
- } => (
- Range {
- begin,
- end: begin + length,
- },
- data,
- ),
- };
+ let loc = self.convert_raw(raw_loc)?;
+ if loc.is_some() {
+ return Ok(loc);
+ }
+ }
+ }
- if range.begin > range.end {
- self.raw.input.empty();
- return Err(Error::InvalidLocationAddressRange);
+ /// Return the next raw location.
+ ///
+ /// The raw location should be passed to `convert_raw`.
+ #[doc(hidden)]
+ pub fn next_raw(&mut self) -> Result<Option<RawLocListEntry<R>>> {
+ self.raw.next()
+ }
+
+ /// Convert a raw location into a location, and update the state of the iterator.
+ ///
+ /// The raw location should have been obtained from `next_raw`.
+ #[doc(hidden)]
+ pub fn convert_raw(
+ &mut self,
+ raw_loc: RawLocListEntry<R>,
+ ) -> Result<Option<LocationListEntry<R>>> {
+ let mask = !0 >> (64 - self.raw.encoding.address_size * 8);
+ let tombstone = if self.raw.encoding.version <= 4 {
+ mask - 1
+ } else {
+ mask
+ };
+
+ let (range, data) = match raw_loc {
+ RawLocListEntry::BaseAddress { addr } => {
+ self.base_address = addr;
+ return Ok(None);
+ }
+ RawLocListEntry::BaseAddressx { addr } => {
+ self.base_address = self.get_address(addr)?;
+ return Ok(None);
+ }
+ RawLocListEntry::StartxEndx { begin, end, data } => {
+ let begin = self.get_address(begin)?;
+ let end = self.get_address(end)?;
+ (Range { begin, end }, data)
+ }
+ RawLocListEntry::StartxLength {
+ begin,
+ length,
+ data,
+ } => {
+ let begin = self.get_address(begin)?;
+ let end = begin.wrapping_add(length) & mask;
+ (Range { begin, end }, data)
+ }
+ RawLocListEntry::DefaultLocation { data } => (
+ Range {
+ begin: 0,
+ end: u64::max_value(),
+ },
+ data,
+ ),
+ RawLocListEntry::AddressOrOffsetPair { begin, end, data }
+ | RawLocListEntry::OffsetPair { begin, end, data } => {
+ if self.base_address == tombstone {
+ return Ok(None);
+ }
+ let mut range = Range { begin, end };
+ range.add_base_address(self.base_address, self.raw.encoding.address_size);
+ (range, data)
+ }
+ RawLocListEntry::StartEnd { begin, end, data } => (Range { begin, end }, data),
+ RawLocListEntry::StartLength {
+ begin,
+ length,
+ data,
+ } => {
+ let end = begin.wrapping_add(length) & mask;
+ (Range { begin, end }, data)
}
+ };
- return Ok(Some(LocationListEntry { range, data }));
+ if range.begin == tombstone {
+ return Ok(None);
}
+
+ if range.begin > range.end {
+ self.raw.input.empty();
+ return Err(Error::InvalidLocationAddressRange);
+ }
+
+ Ok(Some(LocationListEntry { range, data }))
}
}
@@ -643,6 +676,7 @@ mod tests {
#[test]
fn test_loclists_32() {
+ let tombstone = !0u32;
let encoding = Encoding {
format: Format::Dwarf32,
version: 5,
@@ -653,7 +687,9 @@ mod tests {
.L32(0x0300_0000)
.L32(0x0301_0300)
.L32(0x0301_0400)
- .L32(0x0301_0500);
+ .L32(0x0301_0500)
+ .L32(tombstone)
+ .L32(0x0301_0600);
let buf = section.get_contents().unwrap();
let debug_addr = &DebugAddr::from(EndianSlice::new(&buf, LittleEndian));
let debug_addr_base = DebugAddrBase(0);
@@ -697,6 +733,25 @@ mod tests {
.L8(2).uleb(1).uleb(2).uleb(4).L32(12)
// A StartxLength
.L8(3).uleb(3).uleb(0x100).uleb(4).L32(13)
+
+ // Tombstone entries, all of which should be ignored.
+ // A BaseAddressx that is a tombstone.
+ .L8(1).uleb(4)
+ .L8(4).uleb(0x11100).uleb(0x11200).uleb(4).L32(20)
+ // A BaseAddress that is a tombstone.
+ .L8(6).L32(tombstone)
+ .L8(4).uleb(0x11300).uleb(0x11400).uleb(4).L32(21)
+ // A StartxEndx that is a tombstone.
+ .L8(2).uleb(4).uleb(5).uleb(4).L32(22)
+ // A StartxLength that is a tombstone.
+ .L8(3).uleb(4).uleb(0x100).uleb(4).L32(23)
+ // A StartEnd that is a tombstone.
+ .L8(7).L32(tombstone).L32(0x201_1500).uleb(4).L32(24)
+ // A StartLength that is a tombstone.
+ .L8(8).L32(tombstone).uleb(0x100).uleb(4).L32(25)
+ // A StartEnd (not ignored)
+ .L8(7).L32(0x201_1600).L32(0x201_1700).uleb(4).L32(26)
+
// A range end.
.L8(0)
// Some extra data.
@@ -854,6 +909,18 @@ mod tests {
}))
);
+ // A StartEnd location following the tombstones
+ assert_eq!(
+ locations.next(),
+ Ok(Some(LocationListEntry {
+ range: Range {
+ begin: 0x0201_1600,
+ end: 0x0201_1700,
+ },
+ data: Expression(EndianSlice::new(&[26, 0, 0, 0], LittleEndian)),
+ }))
+ );
+
// A location list end.
assert_eq!(locations.next(), Ok(None));
@@ -872,6 +939,7 @@ mod tests {
#[test]
fn test_loclists_64() {
+ let tombstone = !0u64;
let encoding = Encoding {
format: Format::Dwarf64,
version: 5,
@@ -882,7 +950,9 @@ mod tests {
.L64(0x0300_0000)
.L64(0x0301_0300)
.L64(0x0301_0400)
- .L64(0x0301_0500);
+ .L64(0x0301_0500)
+ .L64(tombstone)
+ .L64(0x0301_0600);
let buf = section.get_contents().unwrap();
let debug_addr = &DebugAddr::from(EndianSlice::new(&buf, LittleEndian));
let debug_addr_base = DebugAddrBase(0);
@@ -927,6 +997,25 @@ mod tests {
.L8(2).uleb(1).uleb(2).uleb(4).L32(12)
// A StartxLength
.L8(3).uleb(3).uleb(0x100).uleb(4).L32(13)
+
+ // Tombstone entries, all of which should be ignored.
+ // A BaseAddressx that is a tombstone.
+ .L8(1).uleb(4)
+ .L8(4).uleb(0x11100).uleb(0x11200).uleb(4).L32(20)
+ // A BaseAddress that is a tombstone.
+ .L8(6).L64(tombstone)
+ .L8(4).uleb(0x11300).uleb(0x11400).uleb(4).L32(21)
+ // A StartxEndx that is a tombstone.
+ .L8(2).uleb(4).uleb(5).uleb(4).L32(22)
+ // A StartxLength that is a tombstone.
+ .L8(3).uleb(4).uleb(0x100).uleb(4).L32(23)
+ // A StartEnd that is a tombstone.
+ .L8(7).L64(tombstone).L64(0x201_1500).uleb(4).L32(24)
+ // A StartLength that is a tombstone.
+ .L8(8).L64(tombstone).uleb(0x100).uleb(4).L32(25)
+ // A StartEnd (not ignored)
+ .L8(7).L64(0x201_1600).L64(0x201_1700).uleb(4).L32(26)
+
// A range end.
.L8(0)
// Some extra data.
@@ -1084,6 +1173,18 @@ mod tests {
}))
);
+ // A StartEnd location following the tombstones
+ assert_eq!(
+ locations.next(),
+ Ok(Some(LocationListEntry {
+ range: Range {
+ begin: 0x0201_1600,
+ end: 0x0201_1700,
+ },
+ data: Expression(EndianSlice::new(&[26, 0, 0, 0], LittleEndian)),
+ }))
+ );
+
// A location list end.
assert_eq!(locations.next(), Ok(None));
@@ -1102,6 +1203,7 @@ mod tests {
#[test]
fn test_location_list_32() {
+ let tombstone = !0u32 - 1;
let start = Label::new();
let first = Label::new();
#[rustfmt::skip]
@@ -1123,6 +1225,11 @@ mod tests {
// A location range that ends at -1.
.L32(0xffff_ffff).L32(0x0000_0000)
.L32(0).L32(0xffff_ffff).L16(4).L32(7)
+ // A normal location with tombstone.
+ .L32(tombstone).L32(tombstone).L16(4).L32(8)
+ // A base address selection with tombstone followed by a normal location.
+ .L32(0xffff_ffff).L32(tombstone)
+ .L32(0x10a00).L32(0x10b00).L16(4).L32(9)
// A location list end.
.L32(0).L32(0)
// Some extra data.
@@ -1232,6 +1339,7 @@ mod tests {
#[test]
fn test_location_list_64() {
+ let tombstone = !0u64 - 1;
let start = Label::new();
let first = Label::new();
#[rustfmt::skip]
@@ -1253,6 +1361,11 @@ mod tests {
// A location range that ends at -1.
.L64(0xffff_ffff_ffff_ffff).L64(0x0000_0000)
.L64(0).L64(0xffff_ffff_ffff_ffff).L16(4).L32(7)
+ // A normal location with tombstone.
+ .L64(tombstone).L64(tombstone).L16(4).L32(8)
+ // A base address selection with tombstone followed by a normal location.
+ .L64(0xffff_ffff_ffff_ffff).L64(tombstone)
+ .L64(0x10a00).L64(0x10b00).L16(4).L32(9)
// A location list end.
.L64(0).L64(0)
// Some extra data.
diff --git a/vendor/gimli/src/read/mod.rs b/vendor/gimli/src/read/mod.rs
index 3110957c2..b2828d5f9 100644
--- a/vendor/gimli/src/read/mod.rs
+++ b/vendor/gimli/src/read/mod.rs
@@ -214,6 +214,9 @@ mod index;
pub use self::index::*;
#[cfg(feature = "read")]
+mod lazy;
+
+#[cfg(feature = "read")]
mod line;
#[cfg(feature = "read")]
pub use self::line::*;
diff --git a/vendor/gimli/src/read/op.rs b/vendor/gimli/src/read/op.rs
index 88ea20297..670d1ad21 100644
--- a/vendor/gimli/src/read/op.rs
+++ b/vendor/gimli/src/read/op.rs
@@ -346,10 +346,7 @@ where
{
/// Return true if the piece is empty.
pub fn is_empty(&self) -> bool {
- match *self {
- Location::Empty => true,
- _ => false,
- }
+ matches!(*self, Location::Empty)
}
}
@@ -1225,7 +1222,6 @@ impl<R: Reader, S: EvaluationStorage<R>> Evaluation<R, S> {
self.stack.try_push(value).map_err(|_| Error::StackFull)
}
- #[allow(clippy::cyclomatic_complexity)]
fn evaluate_one_operation(&mut self) -> Result<OperationEvaluationResult<R>> {
let operation = Operation::parse(&mut self.pc, self.encoding)?;
@@ -2889,7 +2885,6 @@ mod tests {
result
}
- #[allow(clippy::too_many_arguments)]
fn check_eval_with_args<F>(
program: &[AssemblerEntry],
expect: Result<&[Piece<EndianSlice<LittleEndian>>]>,
diff --git a/vendor/gimli/src/read/rnglists.rs b/vendor/gimli/src/read/rnglists.rs
index d8d49042f..12e3e04ee 100644
--- a/vendor/gimli/src/read/rnglists.rs
+++ b/vendor/gimli/src/read/rnglists.rs
@@ -232,7 +232,7 @@ impl<R: Reader> RangeLists<R> {
let (mut input, format) = if unit_encoding.version <= 4 {
(self.debug_ranges.section.clone(), RangeListsFormat::Bare)
} else {
- (self.debug_rnglists.section.clone(), RangeListsFormat::RLE)
+ (self.debug_rnglists.section.clone(), RangeListsFormat::Rle)
};
input.skip(offset.0)?;
Ok(RawRngListIter::new(input, unit_encoding, format))
@@ -277,7 +277,7 @@ enum RangeListsFormat {
/// The bare range list format used before DWARF 5.
Bare,
/// The DW_RLE encoded range list format used in DWARF 5.
- RLE,
+ Rle,
}
/// A raw iterator over an address range list.
@@ -355,10 +355,10 @@ impl<T: ReaderOffset> RawRngListEntry<T> {
encoding: Encoding,
format: RangeListsFormat,
) -> Result<Option<Self>> {
- match format {
+ Ok(match format {
RangeListsFormat::Bare => {
let range = RawRange::parse(input, encoding.address_size)?;
- return Ok(if range.is_end() {
+ if range.is_end() {
None
} else if range.is_base_address(encoding.address_size) {
Some(RawRngListEntry::BaseAddress { addr: range.end })
@@ -367,9 +367,9 @@ impl<T: ReaderOffset> RawRngListEntry<T> {
begin: range.begin,
end: range.end,
})
- });
+ }
}
- RangeListsFormat::RLE => Ok(match constants::DwRle(input.read_u8()?) {
+ RangeListsFormat::Rle => match constants::DwRle(input.read_u8()?) {
constants::DW_RLE_end_of_list => None,
constants::DW_RLE_base_addressx => Some(RawRngListEntry::BaseAddressx {
addr: DebugAddrIndex(input.read_uleb128().and_then(R::Offset::from_u64)?),
@@ -400,8 +400,8 @@ impl<T: ReaderOffset> RawRngListEntry<T> {
_ => {
return Err(Error::InvalidAddressRange);
}
- }),
- }
+ },
+ })
}
}
@@ -489,45 +489,78 @@ impl<R: Reader> RngListIter<R> {
None => return Ok(None),
};
- let range = match raw_range {
- RawRngListEntry::BaseAddress { addr } => {
- self.base_address = addr;
- continue;
- }
- RawRngListEntry::BaseAddressx { addr } => {
- self.base_address = self.get_address(addr)?;
- continue;
- }
- RawRngListEntry::StartxEndx { begin, end } => {
- let begin = self.get_address(begin)?;
- let end = self.get_address(end)?;
- Range { begin, end }
- }
- RawRngListEntry::StartxLength { begin, length } => {
- let begin = self.get_address(begin)?;
- let end = begin + length;
- Range { begin, end }
- }
- RawRngListEntry::AddressOrOffsetPair { begin, end }
- | RawRngListEntry::OffsetPair { begin, end } => {
- let mut range = Range { begin, end };
- range.add_base_address(self.base_address, self.raw.encoding.address_size);
- range
- }
- RawRngListEntry::StartEnd { begin, end } => Range { begin, end },
- RawRngListEntry::StartLength { begin, length } => Range {
- begin,
- end: begin + length,
- },
- };
+ let range = self.convert_raw(raw_range)?;
+ if range.is_some() {
+ return Ok(range);
+ }
+ }
+ }
- if range.begin > range.end {
- self.raw.input.empty();
- return Err(Error::InvalidAddressRange);
+ /// Return the next raw range.
+ ///
+ /// The raw range should be passed to `convert_range`.
+ #[doc(hidden)]
+ pub fn next_raw(&mut self) -> Result<Option<RawRngListEntry<R::Offset>>> {
+ self.raw.next()
+ }
+
+ /// Convert a raw range into a range, and update the state of the iterator.
+ ///
+ /// The raw range should have been obtained from `next_raw`.
+ #[doc(hidden)]
+ pub fn convert_raw(&mut self, raw_range: RawRngListEntry<R::Offset>) -> Result<Option<Range>> {
+ let mask = !0 >> (64 - self.raw.encoding.address_size * 8);
+ let tombstone = if self.raw.encoding.version <= 4 {
+ mask - 1
+ } else {
+ mask
+ };
+
+ let range = match raw_range {
+ RawRngListEntry::BaseAddress { addr } => {
+ self.base_address = addr;
+ return Ok(None);
+ }
+ RawRngListEntry::BaseAddressx { addr } => {
+ self.base_address = self.get_address(addr)?;
+ return Ok(None);
+ }
+ RawRngListEntry::StartxEndx { begin, end } => {
+ let begin = self.get_address(begin)?;
+ let end = self.get_address(end)?;
+ Range { begin, end }
+ }
+ RawRngListEntry::StartxLength { begin, length } => {
+ let begin = self.get_address(begin)?;
+ let end = begin.wrapping_add(length) & mask;
+ Range { begin, end }
+ }
+ RawRngListEntry::AddressOrOffsetPair { begin, end }
+ | RawRngListEntry::OffsetPair { begin, end } => {
+ if self.base_address == tombstone {
+ return Ok(None);
+ }
+ let mut range = Range { begin, end };
+ range.add_base_address(self.base_address, self.raw.encoding.address_size);
+ range
}
+ RawRngListEntry::StartEnd { begin, end } => Range { begin, end },
+ RawRngListEntry::StartLength { begin, length } => {
+ let end = begin.wrapping_add(length) & mask;
+ Range { begin, end }
+ }
+ };
+
+ if range.begin == tombstone {
+ return Ok(None);
+ }
- return Ok(Some(range));
+ if range.begin > range.end {
+ self.raw.input.empty();
+ return Err(Error::InvalidAddressRange);
}
+
+ Ok(Some(range))
}
}
@@ -553,8 +586,6 @@ pub(crate) struct RawRange {
impl RawRange {
/// Check if this is a range end entry.
- ///
- /// This will only occur for raw ranges.
#[inline]
pub fn is_end(&self) -> bool {
self.begin == 0 && self.end == 0
@@ -563,14 +594,13 @@ impl RawRange {
/// Check if this is a base address selection entry.
///
/// A base address selection entry changes the base address that subsequent
- /// range entries are relative to. This will only occur for raw ranges.
+ /// range entries are relative to.
#[inline]
pub fn is_base_address(&self, address_size: u8) -> bool {
self.begin == !0 >> (64 - address_size * 8)
}
/// Parse an address range entry from `.debug_ranges` or `.debug_loc`.
- #[doc(hidden)]
#[inline]
pub fn parse<R: Reader>(input: &mut R, address_size: u8) -> Result<RawRange> {
let begin = input.read_address(address_size)?;
@@ -610,6 +640,7 @@ mod tests {
#[test]
fn test_rnglists_32() {
+ let tombstone = !0u32;
let encoding = Encoding {
format: Format::Dwarf32,
version: 5,
@@ -619,7 +650,9 @@ mod tests {
.L32(0x0300_0000)
.L32(0x0301_0300)
.L32(0x0301_0400)
- .L32(0x0301_0500);
+ .L32(0x0301_0500)
+ .L32(tombstone)
+ .L32(0x0301_0600);
let buf = section.get_contents().unwrap();
let debug_addr = &DebugAddr::from(EndianSlice::new(&buf, LittleEndian));
let debug_addr_base = DebugAddrBase(0);
@@ -637,7 +670,7 @@ mod tests {
.L8(0)
.L32(0)
.mark(&first)
- // OffsetPair
+ // An OffsetPair using the unit base address.
.L8(4).uleb(0x10200).uleb(0x10300)
// A base address selection followed by an OffsetPair.
.L8(5).L32(0x0200_0000)
@@ -663,6 +696,25 @@ mod tests {
.L8(2).uleb(1).uleb(2)
// A StartxLength
.L8(3).uleb(3).uleb(0x100)
+
+ // Tombstone entries, all of which should be ignored.
+ // A BaseAddressx that is a tombstone.
+ .L8(1).uleb(4)
+ .L8(4).uleb(0x11100).uleb(0x11200)
+ // A BaseAddress that is a tombstone.
+ .L8(5).L32(tombstone)
+ .L8(4).uleb(0x11300).uleb(0x11400)
+ // A StartxEndx that is a tombstone.
+ .L8(2).uleb(4).uleb(5)
+ // A StartxLength that is a tombstone.
+ .L8(3).uleb(4).uleb(0x100)
+ // A StartEnd that is a tombstone.
+ .L8(6).L32(tombstone).L32(0x201_1500)
+ // A StartLength that is a tombstone.
+ .L8(7).L32(tombstone).uleb(0x100)
+ // A StartEnd (not ignored)
+ .L8(6).L32(0x201_1600).L32(0x201_1700)
+
// A range end.
.L8(0)
// Some extra data.
@@ -784,6 +836,15 @@ mod tests {
}))
);
+ // A StartEnd range following the tombstones
+ assert_eq!(
+ ranges.next(),
+ Ok(Some(Range {
+ begin: 0x0201_1600,
+ end: 0x0201_1700,
+ }))
+ );
+
// A range end.
assert_eq!(ranges.next(), Ok(None));
@@ -802,6 +863,7 @@ mod tests {
#[test]
fn test_rnglists_64() {
+ let tombstone = !0u64;
let encoding = Encoding {
format: Format::Dwarf64,
version: 5,
@@ -811,7 +873,9 @@ mod tests {
.L64(0x0300_0000)
.L64(0x0301_0300)
.L64(0x0301_0400)
- .L64(0x0301_0500);
+ .L64(0x0301_0500)
+ .L64(tombstone)
+ .L64(0x0301_0600);
let buf = section.get_contents().unwrap();
let debug_addr = &DebugAddr::from(EndianSlice::new(&buf, LittleEndian));
let debug_addr_base = DebugAddrBase(0);
@@ -830,7 +894,7 @@ mod tests {
.L8(0)
.L32(0)
.mark(&first)
- // OffsetPair
+ // An OffsetPair using the unit base address.
.L8(4).uleb(0x10200).uleb(0x10300)
// A base address selection followed by an OffsetPair.
.L8(5).L64(0x0200_0000)
@@ -856,6 +920,25 @@ mod tests {
.L8(2).uleb(1).uleb(2)
// A StartxLength
.L8(3).uleb(3).uleb(0x100)
+
+ // Tombstone entries, all of which should be ignored.
+ // A BaseAddressx that is a tombstone.
+ .L8(1).uleb(4)
+ .L8(4).uleb(0x11100).uleb(0x11200)
+ // A BaseAddress that is a tombstone.
+ .L8(5).L64(tombstone)
+ .L8(4).uleb(0x11300).uleb(0x11400)
+ // A StartxEndx that is a tombstone.
+ .L8(2).uleb(4).uleb(5)
+ // A StartxLength that is a tombstone.
+ .L8(3).uleb(4).uleb(0x100)
+ // A StartEnd that is a tombstone.
+ .L8(6).L64(tombstone).L64(0x201_1500)
+ // A StartLength that is a tombstone.
+ .L8(7).L64(tombstone).uleb(0x100)
+ // A StartEnd (not ignored)
+ .L8(6).L64(0x201_1600).L64(0x201_1700)
+
// A range end.
.L8(0)
// Some extra data.
@@ -977,6 +1060,15 @@ mod tests {
}))
);
+ // A StartEnd range following the tombstones
+ assert_eq!(
+ ranges.next(),
+ Ok(Some(Range {
+ begin: 0x0201_1600,
+ end: 0x0201_1700,
+ }))
+ );
+
// A range end.
assert_eq!(ranges.next(), Ok(None));
@@ -1027,6 +1119,7 @@ mod tests {
#[test]
fn test_ranges_32() {
+ let tombstone = !0u32 - 1;
let start = Label::new();
let first = Label::new();
#[rustfmt::skip]
@@ -1048,6 +1141,11 @@ mod tests {
// A range that ends at -1.
.L32(0xffff_ffff).L32(0x0000_0000)
.L32(0).L32(0xffff_ffff)
+ // A normal range with tombstone.
+ .L32(tombstone).L32(tombstone)
+ // A base address selection with tombstone followed by a normal range.
+ .L32(0xffff_ffff).L32(tombstone)
+ .L32(0x10a00).L32(0x10b00)
// A range end.
.L32(0).L32(0)
// Some extra data.
@@ -1139,6 +1237,7 @@ mod tests {
#[test]
fn test_ranges_64() {
+ let tombstone = !0u64 - 1;
let start = Label::new();
let first = Label::new();
#[rustfmt::skip]
@@ -1160,6 +1259,11 @@ mod tests {
// A range that ends at -1.
.L64(0xffff_ffff_ffff_ffff).L64(0x0000_0000)
.L64(0).L64(0xffff_ffff_ffff_ffff)
+ // A normal range with tombstone.
+ .L64(tombstone).L64(tombstone)
+ // A base address selection with tombstone followed by a normal range.
+ .L64(0xffff_ffff_ffff_ffff).L64(tombstone)
+ .L64(0x10a00).L64(0x10b00)
// A range end.
.L64(0).L64(0)
// Some extra data.
diff --git a/vendor/gimli/src/read/unit.rs b/vendor/gimli/src/read/unit.rs
index 670e55efd..672435330 100644
--- a/vendor/gimli/src/read/unit.rs
+++ b/vendor/gimli/src/read/unit.rs
@@ -883,7 +883,6 @@ where
}
/// Return the input buffer after the last attribute.
- #[allow(clippy::inline_always)]
#[inline(always)]
fn after_attrs(&self) -> Result<R> {
if let Some(attrs_len) = self.attrs_len.get() {
@@ -892,7 +891,7 @@ where
Ok(input)
} else {
let mut attrs = self.attrs();
- while let Some(_) = attrs.next()? {}
+ while attrs.next()?.is_some() {}
Ok(attrs.input)
}
}
@@ -912,7 +911,6 @@ where
}
/// Parse an entry. Returns `Ok(None)` for null entries.
- #[allow(clippy::inline_always)]
#[inline(always)]
fn parse(
input: &mut R,
@@ -1143,8 +1141,6 @@ impl<R: Reader> Attribute<R> {
/// name.
///
/// See "Table 7.5: Attribute encodings" and "Table 7.6: Attribute form encodings".
- #[allow(clippy::cyclomatic_complexity)]
- #[allow(clippy::match_same_arms)]
pub fn value(&self) -> AttributeValue<R> {
// Table 7.5 shows the possible attribute classes for each name.
// Table 7.6 shows the possible attribute classes for each form.
@@ -1980,7 +1976,7 @@ fn allow_section_offset(name: constants::DwAt, version: u16) -> bool {
}
}
-pub(crate) fn parse_attribute<'unit, R: Reader>(
+pub(crate) fn parse_attribute<R: Reader>(
input: &mut R,
encoding: Encoding,
spec: AttributeSpecification,
@@ -2205,7 +2201,7 @@ pub(crate) fn parse_attribute<'unit, R: Reader>(
}
}
-pub(crate) fn skip_attributes<'unit, R: Reader>(
+pub(crate) fn skip_attributes<R: Reader>(
input: &mut R,
encoding: Encoding,
specs: &[AttributeSpecification],
@@ -2294,7 +2290,6 @@ impl<'abbrev, 'entry, 'unit, R: Reader> AttrsIter<'abbrev, 'entry, 'unit, R> {
/// Returns `None` when iteration is finished. If an error
/// occurs while parsing the next attribute, then this error
/// is returned, and all subsequent calls return `None`.
- #[allow(clippy::inline_always)]
#[inline(always)]
pub fn next(&mut self) -> Result<Option<Attribute<R>>> {
if self.attributes.is_empty() {
@@ -2647,7 +2642,6 @@ impl<'abbrev, 'unit, R: Reader> EntriesCursor<'abbrev, 'unit, R> {
/// println!("The first entry with no children is {:?}",
/// first_entry_with_no_children.unwrap());
/// ```
- #[allow(clippy::type_complexity)]
pub fn next_dfs(
&mut self,
) -> Result<Option<(isize, &DebuggingInformationEntry<'abbrev, 'unit, R>)>> {
@@ -4213,7 +4207,6 @@ mod tests {
#[test]
fn test_attribute_udata_sdata_value() {
- #[allow(clippy::type_complexity)]
let tests: &[(
AttributeValue<EndianSlice<LittleEndian>>,
Option<u64>,
diff --git a/vendor/gimli/src/read/util.rs b/vendor/gimli/src/read/util.rs
index 16eafdde4..747418bab 100644
--- a/vendor/gimli/src/read/util.rs
+++ b/vendor/gimli/src/read/util.rs
@@ -9,7 +9,8 @@ use core::ptr;
use core::slice;
mod sealed {
- // SAFETY: Implementer must not modify the content in storage.
+ /// # Safety
+ /// Implementer must not modify the content in storage.
pub unsafe trait Sealed {
type Storage;
@@ -161,7 +162,7 @@ impl<A: ArrayLike> ArrayVec<A> {
} else {
self.len -= 1;
// SAFETY: this element is valid and we "forget" it by setting the length.
- Some(unsafe { A::as_slice(&mut self.storage)[self.len].as_ptr().read() })
+ Some(unsafe { A::as_slice(&self.storage)[self.len].as_ptr().read() })
}
}
diff --git a/vendor/gimli/src/write/line.rs b/vendor/gimli/src/write/line.rs
index 310170d9a..c88b735bc 100644
--- a/vendor/gimli/src/write/line.rs
+++ b/vendor/gimli/src/write/line.rs
@@ -94,8 +94,6 @@ impl LineProgram {
/// Panics if `comp_dir` is empty or contains a null byte.
///
/// Panics if `comp_file` is empty or contains a null byte.
- #[allow(clippy::too_many_arguments)]
- #[allow(clippy::new_ret_no_self)]
pub fn new(
encoding: Encoding,
line_encoding: LineEncoding,
@@ -261,7 +259,7 @@ impl LineProgram {
} else {
let entry = self.files.entry(key);
let index = entry.index();
- entry.or_insert(FileInfo::default());
+ entry.or_default();
index
};
FileId::new(index)
@@ -1723,7 +1721,6 @@ mod tests {
// Test that the address/line advance is correct. We don't test for optimality.
#[test]
- #[allow(clippy::useless_vec)]
fn test_advance() {
let encoding = Encoding {
format: Format::Dwarf32,
diff --git a/vendor/gimli/src/write/loc.rs b/vendor/gimli/src/write/loc.rs
index ea0ecb1cf..6dfe45a6c 100644
--- a/vendor/gimli/src/write/loc.rs
+++ b/vendor/gimli/src/write/loc.rs
@@ -436,6 +436,7 @@ mod tests {
};
use crate::LittleEndian;
use std::collections::HashMap;
+ use std::sync::Arc;
#[test]
fn test_loc_list() {
@@ -508,7 +509,7 @@ mod tests {
DebugInfoOffset(0).into(),
read::EndianSlice::default(),
),
- abbreviations: read::Abbreviations::default(),
+ abbreviations: Arc::new(read::Abbreviations::default()),
name: None,
comp_dir: None,
low_pc: 0,
diff --git a/vendor/gimli/src/write/op.rs b/vendor/gimli/src/write/op.rs
index c70eec2dd..287083b3e 100644
--- a/vendor/gimli/src/write/op.rs
+++ b/vendor/gimli/src/write/op.rs
@@ -279,12 +279,8 @@ impl Expression {
}
offsets.push(offset);
for (operation, offset) in self.operations.iter().zip(offsets.iter().copied()) {
- let refs = match refs {
- Some(ref mut refs) => Some(&mut **refs),
- None => None,
- };
debug_assert_eq!(w.len(), offset);
- operation.write(w, refs, encoding, unit_offsets, &offsets)?;
+ operation.write(w, refs.as_deref_mut(), encoding, unit_offsets, &offsets)?;
}
Ok(())
}
@@ -630,7 +626,7 @@ impl Operation {
}
w.write_uleb128(entry_offset(base)?)?;
w.write_udata(value.len() as u64, 1)?;
- w.write(&value)?;
+ w.write(value)?;
}
Operation::FrameOffset(offset) => {
w.write_u8(constants::DW_OP_fbreg.0)?;
@@ -770,7 +766,7 @@ impl Operation {
Operation::ImplicitValue(ref data) => {
w.write_u8(constants::DW_OP_implicit_value.0)?;
w.write_uleb128(data.len() as u64)?;
- w.write(&data)?;
+ w.write(data)?;
}
Operation::ImplicitPointer { entry, byte_offset } => {
if encoding.version >= 5 {
@@ -872,7 +868,7 @@ pub(crate) mod convert {
let mut offsets = Vec::new();
let mut offset = 0;
let mut from_operations = from_expression.clone().operations(encoding);
- while let Some(_) = from_operations.next()? {
+ while from_operations.next()?.is_some() {
offsets.push(offset);
offset = from_operations.offset_from(&from_expression);
}
@@ -1071,6 +1067,7 @@ mod tests {
};
use crate::LittleEndian;
use std::collections::HashMap;
+ use std::sync::Arc;
#[test]
fn test_operation() {
@@ -1578,7 +1575,7 @@ mod tests {
DebugInfoOffset(0).into(),
read::EndianSlice::new(&[], LittleEndian),
),
- abbreviations: read::Abbreviations::default(),
+ abbreviations: Arc::new(read::Abbreviations::default()),
name: None,
comp_dir: None,
low_pc: 0,
diff --git a/vendor/gimli/src/write/range.rs b/vendor/gimli/src/write/range.rs
index b44ce1b7b..c707e1eab 100644
--- a/vendor/gimli/src/write/range.rs
+++ b/vendor/gimli/src/write/range.rs
@@ -315,6 +315,7 @@ mod tests {
};
use crate::LittleEndian;
use std::collections::HashMap;
+ use std::sync::Arc;
#[test]
fn test_range() {
@@ -375,7 +376,7 @@ mod tests {
DebugInfoOffset(0).into(),
read::EndianSlice::default(),
),
- abbreviations: read::Abbreviations::default(),
+ abbreviations: Arc::new(read::Abbreviations::default()),
name: None,
comp_dir: None,
low_pc: 0,
diff --git a/vendor/gimli/src/write/section.rs b/vendor/gimli/src/write/section.rs
index e8f3378cd..db5eb9a28 100644
--- a/vendor/gimli/src/write/section.rs
+++ b/vendor/gimli/src/write/section.rs
@@ -111,7 +111,7 @@ impl<W: Writer + Clone> Sections<W> {
debug_loclists: DebugLocLists(section.clone()),
debug_str: DebugStr(section.clone()),
debug_frame: DebugFrame(section.clone()),
- eh_frame: EhFrame(section.clone()),
+ eh_frame: EhFrame(section),
debug_info_refs: Vec::new(),
debug_loc_refs: Vec::new(),
debug_loclists_refs: Vec::new(),
diff --git a/vendor/gimli/src/write/unit.rs b/vendor/gimli/src/write/unit.rs
index bf85ff421..23027bc2c 100644
--- a/vendor/gimli/src/write/unit.rs
+++ b/vendor/gimli/src/write/unit.rs
@@ -365,7 +365,6 @@ impl Unit {
&mut unit_refs,
self,
&mut offsets,
- abbrevs,
line_program,
line_strings,
strings,
@@ -605,7 +604,6 @@ impl DebuggingInformationEntry {
}
/// Write the entry to the given sections.
- #[allow(clippy::too_many_arguments)]
fn write<W: Writer>(
&self,
w: &mut DebugInfo<W>,
@@ -613,7 +611,6 @@ impl DebuggingInformationEntry {
unit_refs: &mut Vec<(DebugInfoOffset, UnitEntryId)>,
unit: &Unit,
offsets: &mut UnitOffsets,
- abbrevs: &mut AbbreviationTable,
line_program: Option<DebugLineOffset>,
line_strings: &DebugLineStrOffsets,
strings: &DebugStrOffsets,
@@ -654,7 +651,6 @@ impl DebuggingInformationEntry {
unit_refs,
unit,
offsets,
- abbrevs,
line_program,
line_strings,
strings,
@@ -1128,7 +1124,6 @@ impl AttributeValue {
}
/// Write the attribute value to the given sections.
- #[allow(clippy::cyclomatic_complexity, clippy::too_many_arguments)]
fn write<W: Writer>(
&self,
w: &mut DebugInfo<W>,
@@ -1155,7 +1150,7 @@ impl AttributeValue {
AttributeValue::Block(ref val) => {
debug_assert_form!(constants::DW_FORM_block);
w.write_uleb128(val.len() as u64)?;
- w.write(&val)?;
+ w.write(val)?;
}
AttributeValue::Data1(val) => {
debug_assert_form!(constants::DW_FORM_data1);
@@ -1308,7 +1303,7 @@ impl AttributeValue {
}
AttributeValue::String(ref val) => {
debug_assert_form!(constants::DW_FORM_string);
- w.write(&val)?;
+ w.write(val)?;
w.write_u8(0)?;
}
AttributeValue::Encoding(val) => {
@@ -1558,7 +1553,6 @@ pub(crate) mod convert {
/// Create a unit by reading the data in the input sections.
///
/// Does not add entry attributes.
- #[allow(clippy::too_many_arguments)]
pub(crate) fn convert_entries<R: Reader<Offset = usize>>(
from_header: read::UnitHeader<R>,
unit_id: UnitId,
@@ -1931,9 +1925,9 @@ mod tests {
use crate::LittleEndian;
use std::collections::HashMap;
use std::mem;
+ use std::sync::Arc;
#[test]
- #[allow(clippy::cyclomatic_complexity)]
fn test_unit_table() {
let mut strings = StringTable::default();
@@ -2542,7 +2536,7 @@ mod tests {
let unit = read::Unit {
header: from_unit,
- abbreviations: read::Abbreviations::default(),
+ abbreviations: Arc::new(read::Abbreviations::default()),
name: None,
comp_dir: None,
low_pc: 0,
@@ -2578,7 +2572,6 @@ mod tests {
}
#[test]
- #[allow(clippy::cyclomatic_complexity)]
fn test_unit_ref() {
let mut units = UnitTable::default();
let unit_id1 = units.add(Unit::new(
@@ -3015,7 +3008,7 @@ mod tests {
let unit = read::Unit {
header: from_unit,
- abbreviations: read::Abbreviations::default(),
+ abbreviations: Arc::new(read::Abbreviations::default()),
name: None,
comp_dir: None,
low_pc: 0,
diff --git a/vendor/gimli/src/write/writer.rs b/vendor/gimli/src/write/writer.rs
index 0785d1686..1ce3641fc 100644
--- a/vendor/gimli/src/write/writer.rs
+++ b/vendor/gimli/src/write/writer.rs
@@ -93,9 +93,7 @@ pub trait Writer {
constants::DW_EH_PE_sdata2 => self.write_sdata(val as i64, 2),
constants::DW_EH_PE_sdata4 => self.write_sdata(val as i64, 4),
constants::DW_EH_PE_sdata8 => self.write_sdata(val as i64, 8),
- _ => {
- return Err(Error::UnsupportedPointerEncoding(format));
- }
+ _ => Err(Error::UnsupportedPointerEncoding(format)),
}
}
@@ -334,7 +332,6 @@ mod tests {
use std::{i64, u64};
#[test]
- #[allow(clippy::cyclomatic_complexity)]
fn test_writer() {
let mut w = write::EndianVec::new(LittleEndian);
w.write_address(Address::Constant(0x1122_3344), 4).unwrap();
diff --git a/vendor/hermit-abi/.cargo-checksum.json b/vendor/hermit-abi/.cargo-checksum.json
index 3ccd7931e..cf3c5dd1a 100644
--- a/vendor/hermit-abi/.cargo-checksum.json
+++ b/vendor/hermit-abi/.cargo-checksum.json
@@ -1 +1 @@
-{"files":{"Cargo.toml":"6fdf8fefd46c33cc6492ca69c19c9f49f0704401f3b1aaf0b3fbdbb828d2ddcf","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"23f18e03dc49df91622fe2a76176497404e46ced8a715d9d2b67a7446571cca3","README.md":"322fadd63e558e5a10caf980cbedf83ac1546ba40fd992f54492e21ce54205af","src/errno.rs":"1c0680ead2ddf26b12d34bd7fa3e1dab386df761d6ac1901889ece26682dc465","src/lib.rs":"f4a52715b97d947e3768368c3d8882d0d049a89e01600c4de396f3ffcc7911b9","src/tcplistener.rs":"1fb1c0c232d4f24afb6cff63a7541d00029b7159da8d25b2eb257dff078940a0","src/tcpstream.rs":"fce8a598c6331b82e40982eda079d758be324b8941bf76f1031cea8d01632823"},"package":"fed44880c466736ef9a5c5b5facefb5ed0785676d0c02d612db14e54f0d84286"} \ No newline at end of file
+{"files":{"Cargo.toml":"4ffc8dbf9b604af97a6da408705aab39a38ad95c89f617b7edba629f4e759456","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"23f18e03dc49df91622fe2a76176497404e46ced8a715d9d2b67a7446571cca3","README.md":"322fadd63e558e5a10caf980cbedf83ac1546ba40fd992f54492e21ce54205af","src/errno.rs":"1c0680ead2ddf26b12d34bd7fa3e1dab386df761d6ac1901889ece26682dc465","src/lib.rs":"f4a52715b97d947e3768368c3d8882d0d049a89e01600c4de396f3ffcc7911b9","src/net.rs":"b0c15011336f9469859ff537a1803c004b0f41c81a967d97dbaff5bb75c71f14","src/net_old.rs":"6cec0b9b50a0602848df05ea64e3fa7cf63be4ea40a634f64211e4a5463068f3","src/tcplistener.rs":"1fb1c0c232d4f24afb6cff63a7541d00029b7159da8d25b2eb257dff078940a0","src/tcpstream.rs":"fce8a598c6331b82e40982eda079d758be324b8941bf76f1031cea8d01632823"},"package":"856b5cb0902c2b6d65d5fd97dfa30f9b70c7538e770b98eab5ed52d8db923e01"} \ No newline at end of file
diff --git a/vendor/hermit-abi/Cargo.toml b/vendor/hermit-abi/Cargo.toml
index 6ec8e2aa7..30bb616ed 100644
--- a/vendor/hermit-abi/Cargo.toml
+++ b/vendor/hermit-abi/Cargo.toml
@@ -12,9 +12,13 @@
[package]
edition = "2021"
name = "hermit-abi"
-version = "0.3.1"
+version = "0.3.0"
authors = ["Stefan Lankes"]
-description = "Hermit system calls definitions."
+description = """
+hermit-abi is small interface to call functions from the unikernel RustyHermit.
+It is used to build the target `x86_64-unknown-hermit`.
+"""
+documentation = "https://hermitcore.github.io/rusty-hermit/hermit_abi"
readme = "README.md"
keywords = [
"unikernel",
@@ -25,6 +29,10 @@ license = "MIT OR Apache-2.0"
repository = "https://github.com/hermitcore/rusty-hermit"
resolver = "1"
+[package.metadata.docs.rs]
+features = ["docs"]
+default-target = "x86_64-unknown-hermit"
+
[dependencies.alloc]
version = "1.0.0"
optional = true
@@ -41,6 +49,7 @@ package = "rustc-std-workspace-core"
[features]
default = []
+docs = []
rustc-dep-of-std = [
"core",
"alloc",
diff --git a/vendor/hermit-abi/src/net.rs b/vendor/hermit-abi/src/net.rs
new file mode 100644
index 000000000..05ee2ca58
--- /dev/null
+++ b/vendor/hermit-abi/src/net.rs
@@ -0,0 +1,232 @@
+#![allow(nonstandard_style)]
+
+pub const AF_INET: i32 = 0;
+pub const AF_INET6: i32 = 1;
+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: i32 = 1;
+pub const FIONBIO: i32 = 0x8008667eu32 as i32;
+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;
+pub type nfds_t = usize;
+
+#[repr(C)]
+#[derive(Debug, Copy, Clone)]
+pub struct in_addr {
+ pub s_addr: u32,
+}
+
+#[repr(C)]
+#[derive(Debug, Copy, Clone)]
+pub struct in6_addr {
+ pub s6_addr: [u8; 16],
+}
+
+#[repr(C)]
+#[derive(Debug, Copy, Clone)]
+pub struct sockaddr {
+ pub sa_len: u8,
+ pub sa_family: sa_family_t,
+ pub sa_data: [u8; 14],
+}
+
+#[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: [u8; 8],
+}
+
+#[repr(C)]
+#[derive(Debug, Copy, Clone)]
+pub struct sockaddr_in6 {
+ pub sin6_family: sa_family_t,
+ pub sin6_port: in_port_t,
+ pub sin6_addr: in6_addr,
+ pub sin6_flowinfo: u32,
+ pub sin6_scope_id: u32,
+}
+
+#[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: u32,
+}
+
+#[repr(C)]
+#[derive(Debug, Copy, Clone)]
+pub struct addrinfo {
+ pub ai_flags: i32,
+ pub ai_family: i32,
+ pub ai_socktype: i32,
+ pub ai_protocol: i32,
+ pub ai_addrlen: socklen_t,
+ pub ai_addr: *mut sockaddr,
+ pub ai_canonname: *mut u8,
+ pub ai_next: *mut addrinfo,
+}
+
+extern "C" {
+ #[link_name = "sys_accept"]
+ pub fn accept(s: i32, addr: *mut sockaddr, addrlen: *mut socklen_t) -> i32;
+
+ #[link_name = "sys_bind"]
+ pub fn bind(s: i32, name: *const sockaddr, namelen: socklen_t) -> i32;
+
+ #[link_name = "sys_connect"]
+ pub fn connect(s: i32, name: *const sockaddr, namelen: socklen_t) -> i32;
+
+ #[link_name = "sys_close"]
+ pub fn close(s: i32) -> i32;
+
+ #[link_name = "sys_dup"]
+ pub fn dup(s: i32) -> i32;
+
+ #[link_name = "sys:getpeername"]
+ pub fn getpeername(s: i32, name: *mut sockaddr, namelen: *mut socklen_t) -> i32;
+
+ #[link_name = "sys_getsockname"]
+ pub fn getsockname(s: i32, name: *mut sockaddr, namelen: *mut socklen_t) -> i32;
+
+ #[link_name = "sys_getsockopt"]
+ pub fn getsockopt(
+ s: i32,
+ level: i32,
+ optname: i32,
+ optval: *mut c_void,
+ optlen: *mut socklen_t,
+ ) -> i32;
+
+ #[link_name = "sys_setsockopt"]
+ pub fn setsockopt(
+ s: i32,
+ level: i32,
+ optname: i32,
+ optval: *const c_void,
+ optlen: socklen_t,
+ ) -> i32;
+
+ #[link_name = "sys_ioctl"]
+ pub fn ioctl(s: i32, cmd: c_long, argp: *mut c_void) -> i32;
+
+ #[link_name = "sys_listen"]
+ pub fn listen(s: i32, backlog: c_int) -> i32;
+
+ #[link_name = "sys_poll"]
+ pub fn pollfd(fds: *mut pollfd, nfds: nfds_t, timeout: i32);
+
+ #[link_name = "sys_recv"]
+ pub fn recv(s: c_int, mem: *mut c_void, len: size_t, flags: c_int) -> isize;
+
+ #[link_name = "sys_read"]
+ pub fn read(s: c_int, mem: *mut c_void, len: size_t) -> isize;
+
+ #[link_name = "sys_readv"]
+ pub fn readv(s: c_int, bufs: *const iovec, bufcnt: c_int) -> isize;
+
+ #[link_name = "sys_recvfrom"]
+ pub fn recvfrom(
+ s: c_int,
+ mem: *mut c_void,
+ len: size_t,
+ flags: c_int,
+ from: *mut sockaddr,
+ fromlen: *mut socklen_t,
+ ) -> isize;
+
+ #[link_name = "sys_send"]
+ pub fn send(s: i32, mem: *const c_void, len: usize, flags: i32) -> isize;
+
+ #[link_name = "sys_sendmsg"]
+ pub fn sendmsg(s: c_int, message: *const msghdr, flags: c_int) -> isize;
+
+ #[link_name = "sys_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 = "sys_shutdown"]
+ pub fn shutdown(s: i32, how: i32) -> i32;
+
+ #[link_name = "sys_socket"]
+ pub fn socket(domain: i32, type_: i32, protocol: i32) -> i32;
+
+ #[link_name = "sys_write"]
+ pub fn write(s: c_int, mem: *const c_void, len: size_t) -> ssize_t;
+
+ #[link_name = "sys_writev"]
+ pub fn writev(s: c_int, bufs: *const iovec, bufcnt: c_int) -> ssize_t;
+
+ #[link_name = "sys_freeaddrinfo"]
+ pub fn freeaddrinfo(ai: *mut addrinfo);
+
+ #[link_name = "sys_getaddrinfo"]
+ pub fn getaddrinfo(
+ nodename: *const u8,
+ servname: *const u8,
+ hints: *const addrinfo,
+ res: *mut *mut addrinfo,
+ ) -> i32;
+
+ #[link_name = "sys_select"]
+ pub fn select(
+ maxfdp1: i32,
+ readset: *mut fd_set,
+ writeset: *mut fd_set,
+ exceptset: *mut fd_set,
+ timeout: *mut timeval,
+ ) -> i32;
+
+ #[link_name = "sys_pool"]
+ pub fn poll(
+ fds: *mut pollfd,
+ nfds: nfds_t,
+ timeout: i32
+ ) -> i32;
+}
diff --git a/vendor/hermit-abi/src/net_old.rs b/vendor/hermit-abi/src/net_old.rs
new file mode 100644
index 000000000..93bfd55f0
--- /dev/null
+++ b/vendor/hermit-abi/src/net_old.rs
@@ -0,0 +1,302 @@
+#![allow(nonstandard_style)]
+use crate::errno::EINVAL;
+use crate::FileDescriptor;
+use libc::{c_char, c_int, c_uint, c_void, size_t, ssize_t};
+
+extern "C" {
+ fn sys_hermit_socket(domain: i32, type_: i32, protocol: i32) -> FileDescriptor;
+ fn sys_hermit_accept(
+ s: FileDescriptor,
+ addr: *mut sockaddr,
+ addrlen: *mut socklen_t,
+ ) -> FileDescriptor;
+ fn sys_hermit_bind(s: FileDescriptor, name: *const sockaddr, namelen: socklen_t) -> i32;
+ fn sys_hermit_listen(s: FileDescriptor, backlog: i32) -> i32;
+ fn sys_hermit_shutdown(s: FileDescriptor, how: i32) -> i32;
+ fn sys_hermit_getpeername(
+ s: FileDescriptor,
+ name: *mut sockaddr,
+ namelen: *mut socklen_t,
+ ) -> i32;
+ fn sys_hermit_getsockname(
+ s: FileDescriptor,
+ name: *mut sockaddr,
+ namelen: *mut socklen_t,
+ ) -> i32;
+ fn sys_hermit_getsockopt(
+ s: FileDescriptor,
+ level: i32,
+ optname: i32,
+ optval: *mut c_void,
+ optlen: *const socklen_t,
+ ) -> i32;
+ fn sys_hermit_setsockopt(
+ s: FileDescriptor,
+ level: i32,
+ optname: i32,
+ optval: *const c_void,
+ optlen: socklen_t,
+ ) -> i32;
+ fn sys_hermit_connect(s: FileDescriptor, name: *const sockaddr, namelen: socklen_t) -> i32;
+ fn sys_hermit_getaddrinfo(
+ nodename: *const c_char,
+ servname: *const i8,
+ hints: *const addrinfo,
+ res: *mut *mut addrinfo,
+ ) -> i32;
+}
+
+pub const AF_INET: i32 = 10;
+pub const AF_INET6: 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_READ: i32 = 0;
+pub const SHUT_WRITE: i32 = 1;
+pub const SHUT_BOTH: i32 = 2;
+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: i32 = 1;
+
+pub type sa_family_t = u8;
+pub type socklen_t = usize;
+pub type in_addr_t = u32;
+pub type in_port_t = u16;
+
+#[derive(Debug, Copy, Clone)]
+#[repr(C)]
+pub struct in_addr {
+ pub s_addr: u32,
+}
+
+#[derive(Debug, Copy, Clone)]
+#[repr(C)]
+pub struct in6_addr {
+ pub s6_addr: [u8; 16],
+}
+
+#[repr(C)]
+#[derive(Debug, Copy, Clone)]
+pub struct sockaddr {
+ pub sa_len: u8,
+ pub sa_family: sa_family_t,
+ pub sa_data: [u8; 14usize],
+}
+
+#[derive(Copy, Clone)]
+#[repr(C)]
+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_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: [u8; 8usize],
+}
+
+#[repr(C)]
+#[derive(Debug, Copy, Clone)]
+pub struct iovec {
+ pub iov_base: *mut c_void,
+ pub iov_len: usize,
+}
+
+#[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_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: i32,
+ pub l_linger: i32,
+}
+
+#[inline]
+pub unsafe fn socket(domain: c_int, type_: c_int, protocol: c_int) -> FileDescriptor {
+ sys_hermit_socket(domain, type_, protocol)
+}
+
+#[inline]
+pub unsafe fn accept(
+ s: FileDescriptor,
+ addr: *mut sockaddr,
+ addrlen: *mut socklen_t,
+) -> FileDescriptor {
+ sys_hermit_accept(s, addr, addrlen)
+}
+
+#[inline]
+pub unsafe fn bind(s: FileDescriptor, name: *const sockaddr, namelen: socklen_t) -> i32 {
+ sys_hermit_bind(s, name, namelen)
+}
+
+#[inline]
+pub unsafe fn shutdown(s: FileDescriptor, how: c_int) -> i32 {
+ sys_hermit_shutdown(s, how)
+}
+
+#[inline]
+pub unsafe fn getpeername(s: FileDescriptor, name: *mut sockaddr, namelen: *mut socklen_t) -> i32 {
+ sys_hermit_getpeername(s, name, namelen)
+}
+
+#[inline]
+pub unsafe fn getsockname(s: FileDescriptor, name: *mut sockaddr, namelen: *mut socklen_t) -> i32 {
+ sys_hermit_getsockname(s, name, namelen)
+}
+
+#[inline]
+pub unsafe fn getsockopt(
+ s: FileDescriptor,
+ level: c_int,
+ optname: c_int,
+ optval: *mut c_void,
+ optlen: *const socklen_t,
+) -> i32 {
+ sys_hermit_getsockopt(s, level, optname, optval, optlen)
+}
+
+#[inline]
+pub unsafe fn setsockopt(
+ s: FileDescriptor,
+ level: c_int,
+ optname: c_int,
+ optval: *const c_void,
+ optlen: socklen_t,
+) -> i32 {
+ sys_hermit_setsockopt(s, level, optname, optval, optlen)
+}
+
+#[inline]
+pub unsafe fn connect(s: FileDescriptor, name: *const sockaddr, namelen: socklen_t) -> i32 {
+ sys_hermit_connect(s, name, namelen)
+}
+
+#[inline]
+pub unsafe fn listen(s: FileDescriptor, backlog: c_int) -> i32 {
+ sys_hermit_listen(s, backlog)
+}
+
+#[inline]
+pub unsafe fn recv(s: FileDescriptor, mem: *mut c_void, len: size_t, flags: c_int) -> ssize_t {
+ (-EINVAL).try_into().unwrap()
+}
+
+#[inline]
+pub unsafe fn recvfrom(
+ s: FileDescriptor,
+ mem: *mut c_void,
+ len: size_t,
+ flags: c_int,
+ from: *mut sockaddr,
+ fromlen: *mut socklen_t,
+) -> ssize_t {
+ (-EINVAL).try_into().unwrap()
+}
+
+#[inline]
+pub unsafe fn send(s: FileDescriptor, mem: *const c_void, len: size_t, flags: c_int) -> ssize_t {
+ (-EINVAL).try_into().unwrap()
+}
+
+#[inline]
+pub unsafe fn sendmsg(s: FileDescriptor, message: *const msghdr, flags: c_int) -> ssize_t {
+ (-EINVAL).try_into().unwrap()
+}
+
+#[inline]
+pub unsafe fn sendto(
+ s: FileDescriptor,
+ mem: *const c_void,
+ len: size_t,
+ flags: c_int,
+ to: *const sockaddr,
+ tolen: socklen_t,
+) -> ssize_t {
+ (-EINVAL).try_into().unwrap()
+}
+
+#[inline]
+pub unsafe fn freeaddrinfo(ai: *mut addrinfo) {}
+
+#[inline]
+pub unsafe fn getaddrinfo(
+ nodename: *const c_char,
+ servname: *const c_char,
+ hints: *const addrinfo,
+ res: *mut *mut addrinfo,
+) -> i32 {
+ sys_hermit_getaddrinfo(nodename, servname, hints, res)
+}
diff --git a/vendor/icu_list/.cargo-checksum.json b/vendor/icu_list/.cargo-checksum.json
index 31667c731..0a33455b4 100644
--- a/vendor/icu_list/.cargo-checksum.json
+++ b/vendor/icu_list/.cargo-checksum.json
@@ -1 +1 @@
-{"files":{"Cargo.lock":"f650478383a2f1a7aed551b2d4650d83a2e8cc3d44c749a0e4fcfc649130b9da","Cargo.toml":"ac843eda0523eadb2d7c3bb39ea34ca5c45648f2e00c1aca87607a427f583e73","LICENSE":"4ad7541d66a407234e2c84902124cef325c29f3e966353efdb800bedb8b8da21","README.md":"33b424bdceea5edc4d3638592b007bf825e25a96e7fe9101a3ad04ea63637150","examples/and_list.rs":"2cf046f8af9892949db8c8b259ac060b9de5781a5941bec5d346cf82e9371774","src/error.rs":"3cf8a7962af6b43a91d9227e4d97824e4b2852d3d50fc00fb29c779768c1b915","src/lib.rs":"c0bd00a3d83d4285d33cef2af12bd9cae380ad9c81702ba7552ce14283e9651d","src/list_formatter.rs":"a5f6f9c8bf35c6e1d4cb712a73b31454c0d081572bbc0efd9997bf6013346825","src/provider.rs":"1ca4026dbc00c901763a41a4b4ad0083c32888b95d11f464a9e3389c7d976fec","src/string_matcher.rs":"6ce2a72cd61e3d87715dafb396d8e6ea4189a3e7dcb84d4188657a477b67b1e6"},"package":"c40218275f081c4493f190357c5395647b06734c2dc3dcb41cc099a0f60168b1"} \ No newline at end of file
+{"files":{"Cargo.lock":"11c80ad227499af3696bc71b715a91d202e3b178d24fd37776ca4221438d36ce","Cargo.toml":"2a69f60d480d23b4cfcba46039d83efe1eba24bd7ecf9cb6e7b08e7448a57b65","LICENSE":"4ad7541d66a407234e2c84902124cef325c29f3e966353efdb800bedb8b8da21","README.md":"33b424bdceea5edc4d3638592b007bf825e25a96e7fe9101a3ad04ea63637150","examples/and_list.rs":"76af2fbe31c6641a360726b201bfb043a35ee8dcf37b626640221fe889b194e4","src/error.rs":"3cf8a7962af6b43a91d9227e4d97824e4b2852d3d50fc00fb29c779768c1b915","src/lazy_automaton.rs":"eff2e95ae5c889908ba71480e73fc31d9cb2e793e9dc6dee8683c686e8ed8019","src/lib.rs":"24090cea0e42067e06fc9d5248c1ae6a03f12bd62ec0e9e2c237d2fc1251dcdb","src/list_formatter.rs":"a21de479a5ec86ed46ce0ad508e8059efb9ecd95ce869523be30118ed6a86660","src/patterns.rs":"3013aca1dd51d1b9a98e8573abac9116650635b2931157e9fb16ee10c8d3ab9c","src/provider/mod.rs":"0dbd37b8b83d40a2f5d7945cc55b4aa8477cec98442472c4b7a6875b226c8195","src/provider/serde_dfa.rs":"4f0489d176e87ad463efd36b4ead93b0b6bb0a39d26b1f96413bfb00576f7bac"},"package":"01a65ff0cab77c33c7e165c858eaa6e84a09f1e485dd495d9d0ae61083c6f786"} \ No newline at end of file
diff --git a/vendor/icu_list/Cargo.lock b/vendor/icu_list/Cargo.lock
index 8d049ce78..759405aa8 100644
--- a/vendor/icu_list/Cargo.lock
+++ b/vendor/icu_list/Cargo.lock
@@ -3,258 +3,43 @@
version = 3
[[package]]
-name = "aho-corasick"
-version = "0.7.19"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b4f55bd91a0978cbfd91c457a164bab8b4001c833b7f323132c0a4e1922dd44e"
-dependencies = [
- "memchr",
-]
-
-[[package]]
name = "atomic-polyfill"
-version = "0.1.10"
+version = "0.1.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9c041a8d9751a520ee19656232a18971f18946a7900f1520ee4400002244dd89"
+checksum = "e3ff7eb3f316534d83a8a2c3d1674ace8a5a71198eba31e2e2b597833f699b28"
dependencies = [
"critical-section",
]
[[package]]
-name = "atty"
-version = "0.2.14"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
-dependencies = [
- "hermit-abi",
- "libc",
- "winapi",
-]
-
-[[package]]
name = "autocfg"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
[[package]]
-name = "bare-metal"
-version = "0.2.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5deb64efa5bd81e31fcd1938615a6d98c82eafcbcd787162b6f63b91d6bac5b3"
-dependencies = [
- "rustc_version 0.2.3",
-]
-
-[[package]]
-name = "bare-metal"
-version = "1.0.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f8fe8f5a8a398345e52358e18ff07cc17a568fbca5c6f73873d3a62056309603"
-
-[[package]]
-name = "bit_field"
-version = "0.10.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dcb6dd1c2376d2e096796e234a70e17e94cc2d5d54ff8ce42b28cef1d0d359a4"
-
-[[package]]
-name = "bitfield"
-version = "0.13.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "46afbd2983a5d5a7bd740ccb198caf5b82f45c40c09c0eed36052d91cb92e719"
-
-[[package]]
-name = "bitflags"
-version = "1.3.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
-
-[[package]]
-name = "bstr"
-version = "0.2.17"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ba3569f383e8f1598449f1a423e72e99569137b47740b1da11ef19af3d5c3223"
-dependencies = [
- "lazy_static",
- "memchr",
- "regex-automata 0.1.10",
- "serde",
-]
-
-[[package]]
-name = "bumpalo"
-version = "3.11.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c1ad822118d20d2c234f427000d5acc36eabe1e29a348c89b63dd60b13f28e5d"
-
-[[package]]
name = "byteorder"
version = "1.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"
[[package]]
-name = "cast"
-version = "0.3.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5"
-
-[[package]]
-name = "cfg-if"
-version = "1.0.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
-
-[[package]]
-name = "clap"
-version = "2.34.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a0610544180c38b88101fecf2dd634b174a62eef6946f84dfc6a7127512b381c"
-dependencies = [
- "bitflags",
- "textwrap",
- "unicode-width",
-]
-
-[[package]]
name = "cobs"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "67ba02a97a2bd10f4b59b25c7973101c79642302776489e030cd13cdab09ed15"
[[package]]
-name = "cortex-m"
-version = "0.7.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "70858629a458fdfd39f9675c4dc309411f2a3f83bede76988d81bf1a0ecee9e0"
-dependencies = [
- "bare-metal 0.2.5",
- "bitfield",
- "embedded-hal",
- "volatile-register",
-]
-
-[[package]]
-name = "criterion"
-version = "0.3.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b01d6de93b2b6c65e17c634a26653a29d107b3c98c607c765bf38d041531cd8f"
-dependencies = [
- "atty",
- "cast",
- "clap",
- "criterion-plot",
- "csv",
- "itertools",
- "lazy_static",
- "num-traits",
- "oorandom",
- "plotters",
- "rayon",
- "regex",
- "serde",
- "serde_cbor",
- "serde_derive",
- "serde_json",
- "tinytemplate",
- "walkdir",
-]
-
-[[package]]
-name = "criterion-plot"
-version = "0.4.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2673cc8207403546f45f5fd319a974b1e6983ad1a3ee7e6041650013be041876"
-dependencies = [
- "cast",
- "itertools",
-]
-
-[[package]]
name = "critical-section"
-version = "0.2.7"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "95da181745b56d4bd339530ec393508910c909c784e8962d15d722bacf0bcbcd"
-dependencies = [
- "bare-metal 1.0.0",
- "cfg-if",
- "cortex-m",
- "riscv",
-]
-
-[[package]]
-name = "crossbeam-channel"
-version = "0.5.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c2dd04ddaf88237dc3b8d8f9a3c1004b506b54b3313403944054d23c0870c521"
-dependencies = [
- "cfg-if",
- "crossbeam-utils",
-]
-
-[[package]]
-name = "crossbeam-deque"
-version = "0.8.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "715e8152b692bba2d374b53d4875445368fdf21a94751410af607a5ac677d1fc"
-dependencies = [
- "cfg-if",
- "crossbeam-epoch",
- "crossbeam-utils",
-]
-
-[[package]]
-name = "crossbeam-epoch"
-version = "0.9.10"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "045ebe27666471bb549370b4b0b3e51b07f56325befa4284db65fc89c02511b1"
-dependencies = [
- "autocfg",
- "cfg-if",
- "crossbeam-utils",
- "memoffset",
- "once_cell",
- "scopeguard",
-]
-
-[[package]]
-name = "crossbeam-utils"
-version = "0.8.11"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "51887d4adc7b564537b15adcfb307936f8075dfcd5f00dde9a9f1d29383682bc"
-dependencies = [
- "cfg-if",
- "once_cell",
-]
-
-[[package]]
-name = "csv"
-version = "1.1.6"
+version = "1.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "22813a6dc45b335f9bade10bf7271dc477e81113e89eb251a0bc2a8a81c536e1"
-dependencies = [
- "bstr",
- "csv-core",
- "itoa 0.4.8",
- "ryu",
- "serde",
-]
-
-[[package]]
-name = "csv-core"
-version = "0.1.10"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2b2466559f260f48ad25fe6317b3c8dac77b5bdb5763ac7d9d6103530663bc90"
-dependencies = [
- "memchr",
-]
+checksum = "6548a0ad5d2549e111e1f6a11a6c2e2d00ce6a3dafe22948d67c2b443f775e52"
[[package]]
name = "databake"
-version = "0.1.2"
+version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c87777d6d7bde863ba217aa87521dc857239de1f36d66aac46fd173fb0495858"
+checksum = "df626c4717e455cd7a70a82c4358630554a07e4341f86dd095c625f1474a2857"
dependencies = [
"databake-derive",
"proc-macro2",
@@ -264,9 +49,9 @@ dependencies = [
[[package]]
name = "databake-derive"
-version = "0.1.1"
+version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "905c7a060fc0c84c0452d97473b1177dd7a5cbc7670cfbae4a7fe22e42f6432e"
+checksum = "be51a53c468489ae1ef0efa9f6b10706f426c0dde06d66122ffef1f0c51e87dc"
dependencies = [
"proc-macro2",
"quote",
@@ -276,9 +61,9 @@ dependencies = [
[[package]]
name = "deduplicating_array"
-version = "0.1.2"
+version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1e7f0807b2feeeda87369e8b4cf467f250f39841c8f9427bf3a972b878588937"
+checksum = "135a278b07263e55438c15a3021b4947288f981ae387666f5015add8fbc76f5b"
dependencies = [
"serde",
]
@@ -295,28 +80,6 @@ dependencies = [
]
[[package]]
-name = "either"
-version = "1.8.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "90e5c1c8368803113bf0c9584fc495a58b86dc8a29edbf8fe877d21d9507e797"
-
-[[package]]
-name = "embedded-hal"
-version = "0.2.7"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "35949884794ad573cf46071e41c9b60efb0cb311e3ca01f7af807af1debc66ff"
-dependencies = [
- "nb 0.1.3",
- "void",
-]
-
-[[package]]
-name = "half"
-version = "1.8.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "eabb4a44450da02c90444cf74558da904edde8fb4e9035a9a6a4e15445af0bd7"
-
-[[package]]
name = "hash32"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -333,51 +96,32 @@ checksum = "db04bc24a18b9ea980628ecf00e6c0264f3c1426dac36c00cb49b6fbad8b0743"
dependencies = [
"atomic-polyfill",
"hash32",
- "rustc_version 0.4.0",
+ "rustc_version",
"serde",
"spin",
"stable_deref_trait",
]
[[package]]
-name = "hermit-abi"
-version = "0.1.19"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33"
-dependencies = [
- "libc",
-]
-
-[[package]]
-name = "icu_benchmark_macros"
-version = "0.7.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6c867656f2d9c90b13709ac88e710a9d6afe33998c1dfa22384bab8804e8b3d4"
-
-[[package]]
name = "icu_list"
-version = "1.0.0"
+version = "1.1.0"
dependencies = [
- "criterion",
"databake",
"deduplicating_array",
"displaydoc",
- "icu_benchmark_macros",
- "icu_locid",
"icu_provider",
"postcard",
- "regex-automata 0.2.0",
+ "regex-automata",
"serde",
"serde_json",
"writeable",
- "zerovec",
]
[[package]]
name = "icu_locid"
-version = "1.0.0"
+version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "34b3de5d99a0e275fe6193b9586dbf37364daebc0d39c89b5cf8376a53b789e8"
+checksum = "71d7a98ecb812760b5f077e55a4763edeefa7ccc30d6eb5680a70841ede81928"
dependencies = [
"displaydoc",
"litemap",
@@ -387,9 +131,9 @@ dependencies = [
[[package]]
name = "icu_provider"
-version = "1.0.0"
+version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e629bc2b6591ed9e4467d8a0fa2a597b70cff64ff8170e54a3f0f3257b99873f"
+checksum = "a86816c97bc4e613086497f9479f63e120315e056763e8c4435604f98d21d82d"
dependencies = [
"displaydoc",
"icu_locid",
@@ -404,9 +148,9 @@ dependencies = [
[[package]]
name = "icu_provider_macros"
-version = "1.0.0"
+version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "38cf6f5b65cf81f0b4298da647101acbfe6ae0e25263f92bd7a22597e9d6d606"
+checksum = "9ddb07844c2ffc4c28840e799e9e54ff054393cf090740decf25624e9d94b93a"
dependencies = [
"proc-macro2",
"quote",
@@ -414,52 +158,16 @@ dependencies = [
]
[[package]]
-name = "itertools"
-version = "0.10.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473"
-dependencies = [
- "either",
-]
-
-[[package]]
-name = "itoa"
-version = "0.4.8"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4"
-
-[[package]]
name = "itoa"
-version = "1.0.3"
+version = "1.0.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6c8af84674fe1f223a982c933a0ee1086ac4d4052aa0fb8060c12c6ad838e754"
-
-[[package]]
-name = "js-sys"
-version = "0.3.60"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "49409df3e3bf0856b916e2ceaca09ee28e6871cf7d9ce97a692cacfdb2a25a47"
-dependencies = [
- "wasm-bindgen",
-]
-
-[[package]]
-name = "lazy_static"
-version = "1.4.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
-
-[[package]]
-name = "libc"
-version = "0.2.133"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c0f80d65747a3e43d1596c7c5492d95d5edddaabd45a7fcdb02b95f644164966"
+checksum = "fad582f4b9e86b6caa621cabeb0963332d92eea04729ab12892c2533951e6440"
[[package]]
name = "litemap"
-version = "0.6.0"
+version = "0.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f34a3f4798fac63fb48cf277eefa38f94d3443baff555bb98e4f56bc9092368e"
+checksum = "575d8a551c59104b4df91269921e5eab561aa1b77c618dac0414b5d44a4617de"
[[package]]
name = "lock_api"
@@ -472,104 +180,12 @@ dependencies = [
]
[[package]]
-name = "log"
-version = "0.4.17"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e"
-dependencies = [
- "cfg-if",
-]
-
-[[package]]
name = "memchr"
version = "2.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
[[package]]
-name = "memoffset"
-version = "0.6.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce"
-dependencies = [
- "autocfg",
-]
-
-[[package]]
-name = "nb"
-version = "0.1.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "801d31da0513b6ec5214e9bf433a77966320625a37860f910be265be6e18d06f"
-dependencies = [
- "nb 1.0.0",
-]
-
-[[package]]
-name = "nb"
-version = "1.0.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "546c37ac5d9e56f55e73b677106873d9d9f5190605e41a856503623648488cae"
-
-[[package]]
-name = "num-traits"
-version = "0.2.15"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd"
-dependencies = [
- "autocfg",
-]
-
-[[package]]
-name = "num_cpus"
-version = "1.13.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "19e64526ebdee182341572e50e9ad03965aa510cd94427a4549448f285e957a1"
-dependencies = [
- "hermit-abi",
- "libc",
-]
-
-[[package]]
-name = "once_cell"
-version = "1.15.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e82dad04139b71a90c080c8463fe0dc7902db5192d939bd0950f074d014339e1"
-
-[[package]]
-name = "oorandom"
-version = "11.1.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0ab1bc2a289d34bd04a330323ac98a1b4bc82c9d9fcb1e66b63caa84da26b575"
-
-[[package]]
-name = "plotters"
-version = "0.3.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2538b639e642295546c50fcd545198c9d64ee2a38620a628724a3b266d5fbf97"
-dependencies = [
- "num-traits",
- "plotters-backend",
- "plotters-svg",
- "wasm-bindgen",
- "web-sys",
-]
-
-[[package]]
-name = "plotters-backend"
-version = "0.3.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "193228616381fecdc1224c62e96946dfbc73ff4384fba576e052ff8c1bea8142"
-
-[[package]]
-name = "plotters-svg"
-version = "0.3.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f9a81d2759aae1dae668f783c308bc5c8ebd191ff4184aaa1b37f65a6ae5a56f"
-dependencies = [
- "plotters-backend",
-]
-
-[[package]]
name = "postcard"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -582,64 +198,23 @@ dependencies = [
[[package]]
name = "proc-macro2"
-version = "1.0.44"
+version = "1.0.50"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7bd7356a8122b6c4a24a82b278680c73357984ca2fc79a0f9fa6dea7dced7c58"
+checksum = "6ef7d57beacfaf2d8aee5937dab7b7f28de3cb8b1828479bb5de2a7106f2bae2"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
-version = "1.0.21"
+version = "1.0.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179"
+checksum = "8856d8364d252a14d474036ea1358d63c9e6965c8e5c1885c18f73d70bff9c7b"
dependencies = [
"proc-macro2",
]
[[package]]
-name = "rayon"
-version = "1.5.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bd99e5772ead8baa5215278c9b15bf92087709e9c1b2d1f97cdb5a183c933a7d"
-dependencies = [
- "autocfg",
- "crossbeam-deque",
- "either",
- "rayon-core",
-]
-
-[[package]]
-name = "rayon-core"
-version = "1.9.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "258bcdb5ac6dad48491bb2992db6b7cf74878b0384908af124823d118c99683f"
-dependencies = [
- "crossbeam-channel",
- "crossbeam-deque",
- "crossbeam-utils",
- "num_cpus",
-]
-
-[[package]]
-name = "regex"
-version = "1.6.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4c4eb3267174b8c6c2f654116623910a0fef09c4753f8dd83db29c48a0df988b"
-dependencies = [
- "aho-corasick",
- "memchr",
- "regex-syntax",
-]
-
-[[package]]
-name = "regex-automata"
-version = "0.1.10"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132"
-
-[[package]]
name = "regex-automata"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -651,39 +226,9 @@ dependencies = [
[[package]]
name = "regex-syntax"
-version = "0.6.27"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a3f87b73ce11b1619a3c6332f45341e0047173771e8b8b73f87bfeefb7b56244"
-
-[[package]]
-name = "riscv"
-version = "0.7.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6907ccdd7a31012b70faf2af85cd9e5ba97657cc3987c4f13f8e4d2c2a088aba"
-dependencies = [
- "bare-metal 1.0.0",
- "bit_field",
- "riscv-target",
-]
-
-[[package]]
-name = "riscv-target"
-version = "0.1.2"
+version = "0.6.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "88aa938cda42a0cf62a20cfe8d139ff1af20c2e681212b5b34adb5a58333f222"
-dependencies = [
- "lazy_static",
- "regex",
-]
-
-[[package]]
-name = "rustc_version"
-version = "0.2.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a"
-dependencies = [
- "semver 0.9.0",
-]
+checksum = "456c603be3e8d448b072f410900c09faf164fbce2d480456f50eea6e25f9c848"
[[package]]
name = "rustc_version"
@@ -691,23 +236,14 @@ version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366"
dependencies = [
- "semver 1.0.14",
+ "semver",
]
[[package]]
name = "ryu"
-version = "1.0.11"
+version = "1.0.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4501abdff3ae82a1c1b477a17252eb69cee9e66eb915c1abaa4f44d873df9f09"
-
-[[package]]
-name = "same-file"
-version = "1.0.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502"
-dependencies = [
- "winapi-util",
-]
+checksum = "7b4b9743ed687d4b4bcedf9ff5eaa7398495ae14e61cba0a295704edbc7decde"
[[package]]
name = "scopeguard"
@@ -717,49 +253,24 @@ checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
[[package]]
name = "semver"
-version = "0.9.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403"
-dependencies = [
- "semver-parser",
-]
-
-[[package]]
-name = "semver"
-version = "1.0.14"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e25dfac463d778e353db5be2449d1cce89bd6fd23c9f1ea21310ce6e5a1b29c4"
-
-[[package]]
-name = "semver-parser"
-version = "0.7.0"
+version = "1.0.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
+checksum = "58bc9567378fc7690d6b2addae4e60ac2eeea07becb2c64b9f218b53865cba2a"
[[package]]
name = "serde"
-version = "1.0.145"
+version = "1.0.152"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "728eb6351430bccb993660dfffc5a72f91ccc1295abaa8ce19b27ebe4f75568b"
+checksum = "bb7d1f0d3021d347a83e556fc4683dea2ea09d87bccdf88ff5c12545d89d5efb"
dependencies = [
"serde_derive",
]
[[package]]
-name = "serde_cbor"
-version = "0.11.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2bef2ebfde456fb76bbcf9f59315333decc4fda0b2b44b420243c11e0f5ec1f5"
-dependencies = [
- "half",
- "serde",
-]
-
-[[package]]
name = "serde_derive"
-version = "1.0.145"
+version = "1.0.152"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "81fa1584d3d1bcacd84c277a0dfe21f5b0f6accf4a23d04d4c6d61f1af522b4c"
+checksum = "af487d118eecd09402d70a5d72551860e788df87b464af30e5ea6a38c75c541e"
dependencies = [
"proc-macro2",
"quote",
@@ -768,11 +279,11 @@ dependencies = [
[[package]]
name = "serde_json"
-version = "1.0.85"
+version = "1.0.91"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e55a28e3aaef9d5ce0506d0a14dbba8054ddc7e499ef522dd8b26859ec9d4a44"
+checksum = "877c235533714907a8c2464236f5c4b2a17262ef1bd71f38f35ea592c8da6883"
dependencies = [
- "itoa 1.0.3",
+ "itoa",
"ryu",
"serde",
]
@@ -794,9 +305,9 @@ checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3"
[[package]]
name = "syn"
-version = "1.0.101"
+version = "1.0.107"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e90cde112c4b9690b8cbe810cba9ddd8bc1d7472e2cae317b69e9438c1cba7d2"
+checksum = "1f4064b5b16e03ae50984a5a8ed5d4f8803e6bc1fd170a3cda91a1be4b18e3f5"
dependencies = [
"proc-macro2",
"quote",
@@ -816,44 +327,19 @@ dependencies = [
]
[[package]]
-name = "textwrap"
-version = "0.11.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060"
-dependencies = [
- "unicode-width",
-]
-
-[[package]]
name = "tinystr"
-version = "0.7.0"
+version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f8aeafdfd935e4a7fe16a91ab711fa52d54df84f9c8f7ca5837a9d1d902ef4c2"
+checksum = "7ac3f5b6856e931e15e07b478e98c8045239829a65f9156d4fa7e7788197a5ef"
dependencies = [
"displaydoc",
]
[[package]]
-name = "tinytemplate"
-version = "1.2.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "be4d6b5f19ff7664e8c98d03e2139cb510db9b0a60b55f8e8709b689d939b6bc"
-dependencies = [
- "serde",
- "serde_json",
-]
-
-[[package]]
name = "unicode-ident"
-version = "1.0.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dcc811dc4066ac62f84f11307873c4850cb653bfa9b1719cee2bd2204a4bc5dd"
-
-[[package]]
-name = "unicode-width"
-version = "0.1.10"
+version = "1.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b"
+checksum = "84a22b9f218b40614adcb3f4ff08b703773ad44fa9423e4e0d346d5db86e4ebc"
[[package]]
name = "unicode-xid"
@@ -862,143 +348,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c"
[[package]]
-name = "vcell"
-version = "0.1.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "77439c1b53d2303b20d9459b1ade71a83c716e3f9c34f3228c00e6f185d6c002"
-
-[[package]]
-name = "void"
-version = "1.0.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d"
-
-[[package]]
-name = "volatile-register"
-version = "0.2.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9ee8f19f9d74293faf70901bc20ad067dc1ad390d2cbf1e3f75f721ffee908b6"
-dependencies = [
- "vcell",
-]
-
-[[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 = "wasm-bindgen"
-version = "0.2.83"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "eaf9f5aceeec8be17c128b2e93e031fb8a4d469bb9c4ae2d7dc1888b26887268"
-dependencies = [
- "cfg-if",
- "wasm-bindgen-macro",
-]
-
-[[package]]
-name = "wasm-bindgen-backend"
-version = "0.2.83"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4c8ffb332579b0557b52d268b91feab8df3615f265d5270fec2a8c95b17c1142"
-dependencies = [
- "bumpalo",
- "log",
- "once_cell",
- "proc-macro2",
- "quote",
- "syn",
- "wasm-bindgen-shared",
-]
-
-[[package]]
-name = "wasm-bindgen-macro"
-version = "0.2.83"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "052be0f94026e6cbc75cdefc9bae13fd6052cdcaf532fa6c45e7ae33a1e6c810"
-dependencies = [
- "quote",
- "wasm-bindgen-macro-support",
-]
-
-[[package]]
-name = "wasm-bindgen-macro-support"
-version = "0.2.83"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "07bc0c051dc5f23e307b13285f9d75df86bfdf816c5721e573dec1f9b8aa193c"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn",
- "wasm-bindgen-backend",
- "wasm-bindgen-shared",
-]
-
-[[package]]
-name = "wasm-bindgen-shared"
-version = "0.2.83"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1c38c045535d93ec4f0b4defec448e4291638ee608530863b1e2ba115d4fff7f"
-
-[[package]]
-name = "web-sys"
-version = "0.3.60"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bcda906d8be16e728fd5adc5b729afad4e444e106ab28cd1c7256e54fa61510f"
-dependencies = [
- "js-sys",
- "wasm-bindgen",
-]
-
-[[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"
-
-[[package]]
name = "writeable"
-version = "0.5.0"
+version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f8e6ab4f5da1b24daf2c590cfac801bacb27b15b4f050e84eb60149ea726f06b"
+checksum = "92d74a687e3b9a7a129db0a8c82b4d464eb9c36f5a66ca68572a7e5f1cfdb5bc"
[[package]]
name = "yoke"
-version = "0.6.2"
+version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1fe1d55ca72c32d573bfbd5cb2f0ca65a497854c44762957a6d3da96041a5184"
+checksum = "222180af14a6b54ef2c33493c1eff77ae95a3687a21b243e752624006fb8f26e"
dependencies = [
"serde",
"stable_deref_trait",
@@ -1008,9 +367,9 @@ dependencies = [
[[package]]
name = "yoke-derive"
-version = "0.6.0"
+version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "58c2c5bb7c929b85c1b9ec69091b0d835f0878b4fd9eb67973b25936e06c4374"
+checksum = "ca800d73d6b7a7ee54f2608205c98b549fca71c9500c1abcb3abdc7708b4a8cb"
dependencies = [
"proc-macro2",
"quote",
@@ -1029,9 +388,9 @@ dependencies = [
[[package]]
name = "zerofrom-derive"
-version = "0.1.0"
+version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8785f47d6062c1932866147f91297286a9f350b3070e9d9f0b6078e37d623c1a"
+checksum = "2e8aa86add9ddbd2409c1ed01e033cd457d79b1b1229b64922c25095c595e829"
dependencies = [
"proc-macro2",
"quote",
@@ -1041,21 +400,19 @@ dependencies = [
[[package]]
name = "zerovec"
-version = "0.9.0"
+version = "0.9.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b9d919a74c17749ccb17beaf6405562e413cd94e98ba52ca1e64bbe7eefbd8b8"
+checksum = "154df60c74c4a844bc04a53cef4fc18a909d3ea07e19f5225eaba86209da3aa6"
dependencies = [
- "serde",
- "yoke",
"zerofrom",
"zerovec-derive",
]
[[package]]
name = "zerovec-derive"
-version = "0.9.0"
+version = "0.9.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "490e5f878c2856225e884c35927e7ea6db3c24cdb7229b72542c7526ad7ed49e"
+checksum = "c630983d26a5f0c061dad3bf22df69a7329b4939a9752bc5f19f1cbd8e2263db"
dependencies = [
"proc-macro2",
"quote",
diff --git a/vendor/icu_list/Cargo.toml b/vendor/icu_list/Cargo.toml
index 805f2aea4..2d3f3feb1 100644
--- a/vendor/icu_list/Cargo.toml
+++ b/vendor/icu_list/Cargo.toml
@@ -12,7 +12,7 @@
[package]
edition = "2018"
name = "icu_list"
-version = "1.0.0"
+version = "1.1.0"
authors = ["The ICU4X Project Developers"]
include = [
"src/**/*",
@@ -30,30 +30,30 @@ license = "Unicode-DFS-2016"
repository = "https://github.com/unicode-org/icu4x"
resolver = "2"
-[lib]
-path = "src/lib.rs"
+[package.metadata.docs.rs]
+all-features = true
+
+[package.metadata.cargo-all-features]
+denylist = ["bench"]
[[example]]
name = "and_list"
[dependencies.databake]
-version = "0.1.0"
+version = "0.1.3"
features = ["derive"]
optional = true
[dependencies.deduplicating_array]
-version = "0.1"
+version = "0.1.3"
optional = true
[dependencies.displaydoc]
version = "0.2.3"
default-features = false
-[dependencies.icu_locid]
-version = "1.0.0"
-
[dependencies.icu_provider]
-version = "1.0.0"
+version = "1.1.0"
features = ["macros"]
[dependencies.regex-automata]
@@ -70,17 +70,7 @@ optional = true
default-features = false
[dependencies.writeable]
-version = "0.5"
-
-[dependencies.zerovec]
-version = "0.9"
-features = ["yoke"]
-
-[dev-dependencies.criterion]
-version = "0.3.3"
-
-[dev-dependencies.icu_benchmark_macros]
-version = "0.7"
+version = "0.5.1"
[dev-dependencies.postcard]
version = "1.0.0"
@@ -94,21 +84,16 @@ bench = []
datagen = [
"serde",
"std",
- "databake",
+ "dep:databake",
+ "regex-automata/alloc",
]
serde = [
+ "dep:deduplicating_array",
"dep:serde",
"icu_provider/serde",
- "zerovec/serde",
- "deduplicating_array",
]
serde_human = [
"serde",
"regex-automata/alloc",
]
-std = [
- "icu_provider/std",
- "icu_locid/std",
- "regex-automata/std",
- "regex-automata/alloc",
-]
+std = ["icu_provider/std"]
diff --git a/vendor/icu_list/examples/and_list.rs b/vendor/icu_list/examples/and_list.rs
index 9d869d9fb..08cfa3bda 100644
--- a/vendor/icu_list/examples/and_list.rs
+++ b/vendor/icu_list/examples/and_list.rs
@@ -6,8 +6,8 @@
icu_benchmark_macros::static_setup!();
-use icu_list::{ListFormatter, ListLength};
-use icu_locid::locale;
+use icu::list::{ListFormatter, ListLength};
+use icu::locid::locale;
#[no_mangle]
fn main(_argc: isize, _argv: *const *const u8) -> isize {
diff --git a/vendor/icu_list/src/lazy_automaton.rs b/vendor/icu_list/src/lazy_automaton.rs
new file mode 100644
index 000000000..3431b3c9d
--- /dev/null
+++ b/vendor/icu_list/src/lazy_automaton.rs
@@ -0,0 +1,79 @@
+// This file is part of ICU4X. For terms of use, please see the file
+// called LICENSE at the top level of the ICU4X source tree
+// (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ).
+
+use regex_automata::dfa::sparse::DFA;
+use regex_automata::dfa::Automaton;
+use regex_automata::util::id::StateID;
+use writeable::Writeable;
+
+pub trait LazyAutomaton: Automaton {
+ // Like Automaton::find_earliest_fwd, but doesn't require a materialized string.
+ fn matches_earliest_fwd_lazy<S: Writeable + ?Sized>(&self, haystack: &S) -> bool;
+}
+
+impl<T: AsRef<[u8]>> LazyAutomaton for DFA<T> {
+ fn matches_earliest_fwd_lazy<S: Writeable + ?Sized>(&self, haystack: &S) -> bool {
+ struct DFAStepper<'a> {
+ dfa: &'a DFA<&'a [u8]>,
+ state: StateID,
+ }
+
+ impl core::fmt::Write for DFAStepper<'_> {
+ fn write_str(&mut self, s: &str) -> core::fmt::Result {
+ for &byte in s.as_bytes() {
+ self.state = self.dfa.next_state(self.state, byte);
+ if self.dfa.is_match_state(self.state) || self.dfa.is_dead_state(self.state) {
+ // We matched or are in a no-match-cycle, return early
+ return Err(core::fmt::Error);
+ }
+ }
+ Ok(())
+ }
+ }
+
+ let mut stepper = DFAStepper {
+ // If start == 0 the start state does not depend on the actual string, so
+ // we can just pass an empty slice.
+ state: self.start_state_forward(None, &[], 0, 0),
+ dfa: &self.as_ref(),
+ };
+
+ if haystack.write_to(&mut stepper).is_ok() {
+ stepper.state = self.next_eoi_state(stepper.state);
+ }
+
+ self.is_match_state(stepper.state)
+ }
+}
+
+#[cfg(test)]
+#[test]
+fn test() {
+ use crate::provider::SerdeDFA;
+ use alloc::borrow::Cow;
+
+ let matcher = SerdeDFA::new(Cow::Borrowed("11(000)*$")).unwrap();
+
+ for writeable in [1i32, 11, 110, 11000, 211000] {
+ assert_eq!(
+ matcher
+ .deref()
+ .find_earliest_fwd(writeable.write_to_string().as_bytes())
+ .unwrap()
+ .is_some(),
+ matcher.deref().matches_earliest_fwd_lazy(&writeable)
+ );
+ }
+
+ struct ExitEarlyTest;
+
+ impl writeable::Writeable for ExitEarlyTest {
+ fn write_to<W: core::fmt::Write + ?Sized>(&self, sink: &mut W) -> core::fmt::Result {
+ sink.write_str("12")?;
+ unreachable!()
+ }
+ }
+
+ assert!(!matcher.deref().matches_earliest_fwd_lazy(&ExitEarlyTest));
+}
diff --git a/vendor/icu_list/src/lib.rs b/vendor/icu_list/src/lib.rs
index 18f2156a6..61aec0fa3 100644
--- a/vendor/icu_list/src/lib.rs
+++ b/vendor/icu_list/src/lib.rs
@@ -93,8 +93,9 @@
extern crate alloc;
mod error;
+mod lazy_automaton;
mod list_formatter;
-mod string_matcher;
+mod patterns;
pub mod provider;
diff --git a/vendor/icu_list/src/list_formatter.rs b/vendor/icu_list/src/list_formatter.rs
index 36f5fbb7b..93f035eab 100644
--- a/vendor/icu_list/src/list_formatter.rs
+++ b/vendor/icu_list/src/list_formatter.rs
@@ -72,8 +72,39 @@ impl ListFormatter {
);
/// Returns a [`Writeable`] composed of the input [`Writeable`]s and the language-dependent
- /// formatting. The first layer of parts contains [`parts::ELEMENT`] for input
- /// elements, and [`parts::LITERAL`] for list literals.
+ /// formatting.
+ ///
+ /// The [`Writeable`] is annotated with [`parts::ELEMENT`] for input elements,
+ /// and [`parts::LITERAL`] for list literals.
+ ///
+ /// # Example
+ ///
+ /// ```
+ /// use icu::list::*;
+ /// # use icu::locid::locale;
+ /// # use writeable::*;
+ /// let formatteur = ListFormatter::try_new_and_with_length_unstable(
+ /// &icu_testdata::unstable(),
+ /// &locale!("fr").into(),
+ /// ListLength::Wide,
+ /// )
+ /// .unwrap();
+ /// let pays = ["Italie", "France", "Espagne", "Allemagne"];
+ ///
+ /// assert_writeable_parts_eq!(
+ /// formatteur.format(pays.iter()),
+ /// "Italie, France, Espagne et Allemagne",
+ /// [
+ /// (0, 6, parts::ELEMENT),
+ /// (6, 8, parts::LITERAL),
+ /// (8, 14, parts::ELEMENT),
+ /// (14, 16, parts::LITERAL),
+ /// (16, 23, parts::ELEMENT),
+ /// (23, 27, parts::LITERAL),
+ /// (27, 36, parts::ELEMENT),
+ /// ]
+ /// );
+ /// ```
pub fn format<'a, W: Writeable + 'a, I: Iterator<Item = W> + Clone + 'a>(
&'a self,
values: I,
@@ -99,6 +130,9 @@ pub mod parts {
use writeable::Part;
/// The [`Part`] used by [`FormattedList`](super::FormattedList) to mark the part of the string that is an element.
+ ///
+ /// * `category`: `"list"`
+ /// * `value`: `"element"`
pub const ELEMENT: Part = Part {
category: "list",
value: "element",
@@ -106,6 +140,9 @@ pub mod parts {
/// The [`Part`] used by [`FormattedList`](super::FormattedList) to mark the part of the string that is a list literal,
/// such as ", " or " and ".
+ ///
+ /// * `category`: `"list"`
+ /// * `value`: `"literal"`
pub const LITERAL: Part = Part {
category: "list",
value: "literal",
@@ -234,7 +271,7 @@ mod tests {
fn formatter(length: ListLength) -> ListFormatter {
ListFormatter {
- data: DataPayload::from_owned(crate::provider::test::test_patterns()),
+ data: DataPayload::from_owned(crate::patterns::test::test_patterns()),
length,
}
}
diff --git a/vendor/icu_list/src/patterns.rs b/vendor/icu_list/src/patterns.rs
new file mode 100644
index 000000000..8cfcb98c1
--- /dev/null
+++ b/vendor/icu_list/src/patterns.rs
@@ -0,0 +1,283 @@
+// This file is part of ICU4X. For terms of use, please see the file
+// called LICENSE at the top level of the ICU4X source tree
+// (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ).
+
+use crate::lazy_automaton::LazyAutomaton;
+use crate::provider::*;
+use crate::ListLength;
+#[cfg(feature = "datagen")]
+use alloc::borrow::Cow;
+#[cfg(feature = "datagen")]
+use icu_provider::DataError;
+use writeable::{LengthHint, Writeable};
+
+impl<'data> ListFormatterPatternsV1<'data> {
+ /// Creates a new [`ListFormatterPatternsV1`] from the given patterns. Fails if any pattern is invalid.
+ ///
+ /// See [`ListJoinerPattern::from_str`]. `allow_prefix` will be true for `pair` and `end` patterns,
+ /// `allow_suffix` for `start` and `pair` patterns.
+ #[cfg(feature = "datagen")]
+ pub fn try_new(
+ [start, middle, end, pair, short_start, short_middle, short_end, short_pair, narrow_start, narrow_middle, narrow_end, narrow_pair]: [&str; 12],
+ ) -> Result<Self, DataError> {
+ Ok(Self([
+ ListJoinerPattern::from_str(start, true, false)?.into(),
+ ListJoinerPattern::from_str(middle, false, false)?.into(),
+ ListJoinerPattern::from_str(end, false, true)?.into(),
+ ListJoinerPattern::from_str(pair, true, true)?.into(),
+ ListJoinerPattern::from_str(short_start, true, false)?.into(),
+ ListJoinerPattern::from_str(short_middle, false, false)?.into(),
+ ListJoinerPattern::from_str(short_end, false, true)?.into(),
+ ListJoinerPattern::from_str(short_pair, true, true)?.into(),
+ ListJoinerPattern::from_str(narrow_start, true, false)?.into(),
+ ListJoinerPattern::from_str(narrow_middle, false, false)?.into(),
+ ListJoinerPattern::from_str(narrow_end, false, true)?.into(),
+ ListJoinerPattern::from_str(narrow_pair, true, true)?.into(),
+ ]))
+ }
+
+ /// Adds a special case to all `pattern`s that will evaluate to
+ /// `alternative_pattern` when `regex` matches the following element.
+ /// The regex is interpreted case-insensitive and anchored to the beginning, but
+ /// to improve efficiency does not search for full matches. If a full match is
+ /// required, use `$`.
+ #[cfg(feature = "datagen")]
+ pub fn make_conditional(
+ &mut self,
+ pattern: &str,
+ regex: &SerdeDFA<'static>,
+ alternative_pattern: &str,
+ ) -> Result<(), DataError> {
+ let old = ListJoinerPattern::from_str(pattern, true, true)?;
+ for i in 0..12 {
+ #[allow(clippy::indexing_slicing)] // self.0 is &[_; 12]
+ if self.0[i].default == old {
+ self.0[i].special_case = Some(SpecialCasePattern {
+ condition: regex.clone(),
+ pattern: ListJoinerPattern::from_str(
+ alternative_pattern,
+ i % 4 == 0 || i % 4 == 3, // allow_prefix = start or pair
+ i % 4 == 2 || i % 4 == 3, // allow_suffix = end or pair
+ )?,
+ });
+ }
+ }
+ Ok(())
+ }
+
+ /// The range of the number of bytes required by the list literals to join a
+ /// list of length `len`. If none of the patterns are conditional, this is exact.
+ pub(crate) fn size_hint(&self, style: ListLength, len: usize) -> LengthHint {
+ match len {
+ 0 | 1 => LengthHint::exact(0),
+ 2 => self.pair(style).size_hint(),
+ n => {
+ self.start(style).size_hint()
+ + self.middle(style).size_hint() * (n - 3)
+ + self.end(style).size_hint()
+ }
+ }
+ }
+}
+
+type PatternParts<'a> = (&'a str, &'a str, &'a str);
+
+impl<'a> ConditionalListJoinerPattern<'a> {
+ pub(crate) fn parts<'b, W: Writeable + ?Sized>(
+ &'a self,
+ following_value: &'b W,
+ ) -> PatternParts<'a> {
+ match &self.special_case {
+ Some(SpecialCasePattern { condition, pattern })
+ if condition.deref().matches_earliest_fwd_lazy(following_value) =>
+ {
+ pattern.borrow_tuple()
+ }
+ _ => self.default.borrow_tuple(),
+ }
+ }
+
+ /// The expected length of this pattern
+ fn size_hint(&'a self) -> LengthHint {
+ let mut hint = self.default.size_hint();
+ if let Some(special_case) = &self.special_case {
+ hint |= special_case.pattern.size_hint()
+ }
+ hint
+ }
+}
+
+impl<'data> ListJoinerPattern<'data> {
+ /// Construct the pattern from a CLDR pattern string
+ #[cfg(feature = "datagen")]
+ pub fn from_str(
+ pattern: &str,
+ allow_prefix: bool,
+ allow_suffix: bool,
+ ) -> Result<Self, DataError> {
+ match (pattern.find("{0}"), pattern.find("{1}")) {
+ (Some(index_0), Some(index_1))
+ if index_0 < index_1
+ && (allow_prefix || index_0 == 0)
+ && (allow_suffix || index_1 == pattern.len() - 3) =>
+ {
+ if (index_0 > 0 && !cfg!(test)) || index_1 - 3 >= 256 {
+ return Err(DataError::custom(
+ "Found valid pattern that cannot be stored in ListFormatterPatternsV1",
+ )
+ .with_debug_context(pattern));
+ }
+ #[allow(clippy::indexing_slicing)] // find
+ Ok(ListJoinerPattern {
+ string: Cow::Owned(alloc::format!(
+ "{}{}{}",
+ &pattern[0..index_0],
+ &pattern[index_0 + 3..index_1],
+ &pattern[index_1 + 3..]
+ )),
+ index_0: index_0 as u8,
+ index_1: (index_1 - 3) as u8,
+ })
+ }
+ _ => Err(DataError::custom("Invalid list pattern").with_debug_context(pattern)),
+ }
+ }
+
+ fn borrow_tuple(&'data self) -> PatternParts<'data> {
+ #![allow(clippy::indexing_slicing)] // by invariant
+ let index_0 = self.index_0 as usize;
+ let index_1 = self.index_1 as usize;
+ (
+ &self.string[0..index_0],
+ &self.string[index_0..index_1],
+ &self.string[index_1..],
+ )
+ }
+
+ fn size_hint(&self) -> LengthHint {
+ LengthHint::exact(self.string.len())
+ }
+}
+
+#[cfg(feature = "datagen")]
+impl<'data> From<ListJoinerPattern<'data>> for ConditionalListJoinerPattern<'data> {
+ fn from(default: ListJoinerPattern<'data>) -> Self {
+ Self {
+ default,
+ special_case: None,
+ }
+ }
+}
+
+#[cfg(all(test, feature = "datagen"))]
+pub mod test {
+ use super::*;
+
+ pub fn test_patterns() -> ListFormatterPatternsV1<'static> {
+ let mut patterns = ListFormatterPatternsV1::try_new([
+ // Wide: general
+ "@{0}:{1}",
+ "{0},{1}",
+ "{0}.{1}!",
+ "${0};{1}+",
+ // Short: different pattern lengths
+ "{0}1{1}",
+ "{0}12{1}",
+ "{0}12{1}34",
+ "{0}123{1}456",
+ // Narrow: conditionals
+ "{0}: {1}",
+ "{0}, {1}",
+ "{0}. {1}",
+ "{0}. {1}",
+ ])
+ .unwrap();
+ patterns
+ .make_conditional(
+ "{0}. {1}",
+ &SerdeDFA::new(Cow::Borrowed("A")).unwrap(),
+ "{0} :o {1}",
+ )
+ .unwrap();
+ patterns
+ }
+
+ #[test]
+ fn rejects_bad_patterns() {
+ assert!(ListJoinerPattern::from_str("{0} and", true, true).is_err());
+ assert!(ListJoinerPattern::from_str("and {1}", true, true).is_err());
+ assert!(ListJoinerPattern::from_str("{1} and {0}", true, true).is_err());
+ assert!(ListJoinerPattern::from_str("{1{0}}", true, true).is_err());
+ assert!(ListJoinerPattern::from_str("{0\u{202e}} and {1}", true, true).is_err());
+ assert!(ListJoinerPattern::from_str("{{0}} {{1}}", true, true).is_ok());
+
+ assert!(ListJoinerPattern::from_str("{0} and {1} ", true, true).is_ok());
+ assert!(ListJoinerPattern::from_str("{0} and {1} ", true, false).is_err());
+ assert!(ListJoinerPattern::from_str(" {0} and {1}", true, true).is_ok());
+ assert!(ListJoinerPattern::from_str(" {0} and {1}", false, true).is_err());
+ }
+
+ #[test]
+ fn produces_correct_parts() {
+ assert_eq!(
+ test_patterns().pair(ListLength::Wide).parts(""),
+ ("$", ";", "+")
+ );
+ }
+
+ #[test]
+ fn produces_correct_parts_conditionally() {
+ assert_eq!(
+ test_patterns().end(ListLength::Narrow).parts("A"),
+ ("", " :o ", "")
+ );
+ assert_eq!(
+ test_patterns().end(ListLength::Narrow).parts("a"),
+ ("", " :o ", "")
+ );
+ assert_eq!(
+ test_patterns().end(ListLength::Narrow).parts("ab"),
+ ("", " :o ", "")
+ );
+ assert_eq!(
+ test_patterns().end(ListLength::Narrow).parts("B"),
+ ("", ". ", "")
+ );
+ assert_eq!(
+ test_patterns().end(ListLength::Narrow).parts("BA"),
+ ("", ". ", "")
+ );
+ }
+
+ #[test]
+ fn size_hint_works() {
+ let pattern = test_patterns();
+
+ assert_eq!(
+ pattern.size_hint(ListLength::Short, 0),
+ LengthHint::exact(0)
+ );
+ assert_eq!(
+ pattern.size_hint(ListLength::Short, 1),
+ LengthHint::exact(0)
+ );
+
+ // pair pattern "{0}123{1}456"
+ assert_eq!(
+ pattern.size_hint(ListLength::Short, 2),
+ LengthHint::exact(6)
+ );
+
+ // patterns "{0}1{1}", "{0}12{1}" (x197), and "{0}12{1}34"
+ assert_eq!(
+ pattern.size_hint(ListLength::Short, 200),
+ LengthHint::exact(1 + 2 * 197 + 4)
+ );
+
+ // patterns "{0}: {1}", "{0}, {1}" (x197), and "{0} :o {1}" or "{0}. {1}"
+ assert_eq!(
+ pattern.size_hint(ListLength::Narrow, 200),
+ LengthHint::exact(2 + 197 * 2) + LengthHint::between(2, 4)
+ );
+ }
+}
diff --git a/vendor/icu_list/src/provider.rs b/vendor/icu_list/src/provider.rs
deleted file mode 100644
index 27f3e4fec..000000000
--- a/vendor/icu_list/src/provider.rs
+++ /dev/null
@@ -1,465 +0,0 @@
-// This file is part of ICU4X. For terms of use, please see the file
-// called LICENSE at the top level of the ICU4X source tree
-// (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ).
-
-// Provider structs must be stable
-#![allow(clippy::exhaustive_structs, clippy::exhaustive_enums)]
-
-//! Data provider struct definitions for this ICU4X component.
-//!
-//! Read more about data providers: [`icu_provider`]
-
-use crate::ListLength;
-use alloc::borrow::Cow;
-use icu_provider::DataMarker;
-use icu_provider::{yoke, zerofrom};
-use writeable::{LengthHint, Writeable};
-
-pub use crate::string_matcher::StringMatcher;
-
-/// Symbols and metadata required for [`ListFormatter`](crate::ListFormatter).
-#[icu_provider::data_struct(
- AndListV1Marker = "list/and@1",
- OrListV1Marker = "list/or@1",
- UnitListV1Marker = "list/unit@1"
-)]
-#[derive(Clone, Debug)]
-#[cfg_attr(
- feature = "datagen",
- derive(serde::Serialize, databake::Bake),
- databake(path = icu_list::provider),
-)]
-pub struct ListFormatterPatternsV1<'data>(
- #[cfg_attr(feature = "datagen", serde(with = "deduplicating_array"))]
- /// The patterns in the order start, middle, end, pair, short_start, short_middle,
- /// short_end, short_pair, narrow_start, narrow_middle, narrow_end, narrow_pair,
- pub [ConditionalListJoinerPattern<'data>; 12],
-);
-
-#[cfg(feature = "serde")]
-impl<'de> serde::Deserialize<'de> for ListFormatterPatternsV1<'de> {
- fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
- where
- D: serde::de::Deserializer<'de>,
- {
- #[cfg(not(feature = "serde_human"))]
- if deserializer.is_human_readable() {
- use serde::de::Error;
- return Err(D::Error::custom(
- "Deserializing human-readable ListFormatter data requires the 'serde_human' feature",
- ));
- }
-
- Ok(ListFormatterPatternsV1(deduplicating_array::deserialize(
- deserializer,
- )?))
- }
-}
-
-pub(crate) struct ErasedListV1Marker;
-
-impl DataMarker for ErasedListV1Marker {
- type Yokeable = ListFormatterPatternsV1<'static>;
-}
-
-impl<'data> ListFormatterPatternsV1<'data> {
- pub(crate) fn start(&self, style: ListLength) -> &ConditionalListJoinerPattern<'data> {
- #![allow(clippy::indexing_slicing)] // style as usize < 3
- &self.0[4 * (style as usize)]
- }
-
- pub(crate) fn middle(&self, style: ListLength) -> &ConditionalListJoinerPattern<'data> {
- #![allow(clippy::indexing_slicing)] // style as usize < 3
- &self.0[4 * (style as usize) + 1]
- }
-
- pub(crate) fn end(&self, style: ListLength) -> &ConditionalListJoinerPattern<'data> {
- #![allow(clippy::indexing_slicing)] // style as usize < 3
- &self.0[4 * (style as usize) + 2]
- }
-
- pub(crate) fn pair(&self, style: ListLength) -> &ConditionalListJoinerPattern<'data> {
- #![allow(clippy::indexing_slicing)] // style as usize < 3
- &self.0[4 * (style as usize) + 3]
- }
-
- /// The range of the number of bytes required by the list literals to join a
- /// list of length `len`. If none of the patterns are conditional, this is exact.
- pub(crate) fn size_hint(&self, style: ListLength, len: usize) -> LengthHint {
- match len {
- 0 | 1 => LengthHint::exact(0),
- 2 => self.pair(style).size_hint(),
- n => {
- self.start(style).size_hint()
- + self.middle(style).size_hint() * (n - 3)
- + self.end(style).size_hint()
- }
- }
- }
-}
-
-/// A pattern that can behave conditionally on the next element.
-#[derive(Clone, Debug, PartialEq, yoke::Yokeable, zerofrom::ZeroFrom)]
-#[cfg_attr(
- feature = "datagen",
- derive(serde::Serialize, databake::Bake),
- databake(path = icu_list::provider),
-)]
-#[cfg_attr(feature = "serde", derive(serde::Deserialize))]
-pub struct ConditionalListJoinerPattern<'data> {
- /// The default pattern
- #[cfg_attr(feature = "serde", serde(borrow))]
- pub default: ListJoinerPattern<'data>,
- /// And optional special case
- #[cfg_attr(feature = "serde", serde(borrow))]
- pub special_case: Option<SpecialCasePattern<'data>>,
-}
-
-/// The special case of a [`ConditionalListJoinerPattern`]
-#[derive(Clone, Debug, PartialEq, yoke::Yokeable, zerofrom::ZeroFrom)]
-#[cfg_attr(
- feature = "datagen",
- derive(serde::Serialize, databake::Bake),
- databake(path = icu_list::provider),
-)]
-#[cfg_attr(feature = "serde", derive(serde::Deserialize))]
-pub struct SpecialCasePattern<'data> {
- /// The condition on the following element
- #[cfg_attr(feature = "serde", serde(borrow))]
- pub condition: StringMatcher<'data>,
- /// The pattern if the condition matches
- #[cfg_attr(feature = "serde", serde(borrow))]
- pub pattern: ListJoinerPattern<'data>,
-}
-
-/// A pattern containing two numeric placeholders ("{0}, and {1}.")
-#[derive(Clone, Debug, PartialEq, yoke::Yokeable, zerofrom::ZeroFrom)]
-#[cfg_attr(feature = "datagen", derive(serde::Serialize))]
-pub struct ListJoinerPattern<'data> {
- /// The pattern string without the placeholders
- string: Cow<'data, str>,
- /// The index of the first placeholder. Always <= index_1.
- // Always 0 for CLDR data, so we don't need to serialize it.
- // In-memory we have free space for it as index_1 doesn't
- // fill a word.
- #[cfg_attr(feature = "datagen", serde(skip))]
- index_0: u8,
- /// The index of the second placeholder. Always < string.len().
- index_1: u8,
-}
-
-#[cfg(feature = "serde")]
-impl<'de: 'data, 'data> serde::Deserialize<'de> for ListJoinerPattern<'data> {
- fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
- where
- D: serde::Deserializer<'de>,
- {
- #[derive(serde::Deserialize)]
- struct Dummy<'data> {
- #[cfg_attr(feature = "serde", serde(borrow))]
- string: Cow<'data, str>,
- index_1: u8,
- }
- let Dummy { string, index_1 } = Dummy::deserialize(deserializer)?;
-
- if index_1 as usize > string.len() {
- use serde::de::Error;
- Err(D::Error::custom("invalid index_1"))
- } else {
- Ok(ListJoinerPattern {
- string,
- index_0: 0,
- index_1,
- })
- }
- }
-}
-
-impl<'a> ListJoinerPattern<'a> {
- /// Constructs a [`ListJoinerPattern`] from raw parts. Used by databake.
- ///
- /// # Safety
- /// index_1 may be at most string.len()
- pub const unsafe fn from_parts_unchecked(string: &'a str, index_1: u8) -> Self {
- Self {
- string: Cow::Borrowed(string),
- index_0: 0,
- index_1,
- }
- }
-}
-
-pub(crate) type PatternParts<'a> = (&'a str, &'a str, &'a str);
-
-impl<'a> ConditionalListJoinerPattern<'a> {
- pub(crate) fn parts<'b, W: Writeable + ?Sized>(
- &'a self,
- following_value: &'b W,
- ) -> PatternParts<'a> {
- match &self.special_case {
- Some(SpecialCasePattern { condition, pattern })
- // TODO: Implement lookahead instead of materializing here.
- if condition.test(&*following_value.write_to_string()) =>
- {
- pattern.borrow_tuple()
- }
- _ => self.default.borrow_tuple(),
- }
- }
-
- /// The expected length of this pattern
- pub fn size_hint(&'a self) -> LengthHint {
- let mut hint = self.default.size_hint();
- if let Some(special_case) = &self.special_case {
- hint |= special_case.pattern.size_hint()
- }
- hint
- }
-}
-
-impl<'data> ListJoinerPattern<'data> {
- fn borrow_tuple(&'data self) -> PatternParts<'data> {
- #![allow(clippy::indexing_slicing)] // by invariant
- let index_0 = self.index_0 as usize;
- let index_1 = self.index_1 as usize;
- (
- &self.string[0..index_0],
- &self.string[index_0..index_1],
- &self.string[index_1..],
- )
- }
-
- fn size_hint(&self) -> LengthHint {
- LengthHint::exact(self.string.len())
- }
-}
-
-#[cfg(feature = "datagen")]
-mod datagen {
- #![allow(clippy::indexing_slicing)] // datagen
-
- use super::*;
- use icu_provider::DataError;
-
- impl<'data> ListFormatterPatternsV1<'data> {
- /// The patterns in the order start, middle, end, pair, short_start, short_middle,
- /// short_end, short_pair, narrow_start, narrow_middle, narrow_end, narrow_pair,
- pub fn try_new(patterns: [&str; 12]) -> Result<Self, DataError> {
- Ok(Self([
- ListJoinerPattern::from_str(patterns[0], true, false)?.into(),
- ListJoinerPattern::from_str(patterns[1], false, false)?.into(),
- ListJoinerPattern::from_str(patterns[2], false, true)?.into(),
- ListJoinerPattern::from_str(patterns[3], true, true)?.into(),
- ListJoinerPattern::from_str(patterns[4], true, false)?.into(),
- ListJoinerPattern::from_str(patterns[5], false, false)?.into(),
- ListJoinerPattern::from_str(patterns[6], false, true)?.into(),
- ListJoinerPattern::from_str(patterns[7], true, true)?.into(),
- ListJoinerPattern::from_str(patterns[8], true, false)?.into(),
- ListJoinerPattern::from_str(patterns[9], false, false)?.into(),
- ListJoinerPattern::from_str(patterns[10], false, true)?.into(),
- ListJoinerPattern::from_str(patterns[11], true, true)?.into(),
- ]))
- }
-
- /// Adds a special case to all `pattern`s that will evaluate to
- /// `alternative_pattern` when `regex` matches the following element.
- /// The regex is interpreted case-insensitive and anchored to the beginning, but
- /// to improve efficiency does not search for full matches. If a full match is
- /// required, use `$`.
- pub fn make_conditional(
- &mut self,
- pattern: &str,
- regex: &StringMatcher<'static>,
- alternative_pattern: &str,
- ) -> Result<(), DataError> {
- let old = ListJoinerPattern::from_str(pattern, true, true)?;
- for i in 0..12 {
- if self.0[i].default == old {
- self.0[i].special_case = Some(SpecialCasePattern {
- condition: regex.clone(),
- pattern: ListJoinerPattern::from_str(
- alternative_pattern,
- i % 4 == 0 || i % 4 == 3, // allow_prefix = start or pair
- i % 4 == 2 || i % 4 == 3, // allow_suffix = end or pair
- )?,
- });
- }
- }
- Ok(())
- }
- }
-
- impl<'data> ListJoinerPattern<'data> {
- /// Construct the pattern from a CLDR pattern string
- pub fn from_str(
- pattern: &str,
- allow_prefix: bool,
- allow_suffix: bool,
- ) -> Result<Self, DataError> {
- match (pattern.find("{0}"), pattern.find("{1}")) {
- (Some(index_0), Some(index_1))
- if index_0 < index_1
- && (allow_prefix || index_0 == 0)
- && (allow_suffix || index_1 == pattern.len() - 3) =>
- {
- if (index_0 > 0 && !cfg!(test)) || index_1 - 3 >= 256 {
- return Err(DataError::custom(
- "Found valid pattern that cannot be stored in ListFormatterPatternsV1",
- )
- .with_debug_context(pattern));
- }
- Ok(ListJoinerPattern {
- string: Cow::Owned(alloc::format!(
- "{}{}{}",
- &pattern[0..index_0],
- &pattern[index_0 + 3..index_1],
- &pattern[index_1 + 3..]
- )),
- index_0: index_0 as u8,
- index_1: (index_1 - 3) as u8,
- })
- }
- _ => Err(DataError::custom("Invalid list pattern").with_debug_context(pattern)),
- }
- }
- }
-
- impl<'data> From<ListJoinerPattern<'data>> for ConditionalListJoinerPattern<'data> {
- fn from(default: ListJoinerPattern<'data>) -> Self {
- Self {
- default,
- special_case: None,
- }
- }
- }
-
- impl databake::Bake for ListJoinerPattern<'_> {
- fn bake(&self, env: &databake::CrateEnv) -> databake::TokenStream {
- env.insert("icu_list");
- let string = (&*self.string).bake(env);
- let index_1 = self.index_1.bake(env);
- // Safe because our own data is safe
- databake::quote! { unsafe {
- ::icu_list::provider::ListJoinerPattern::from_parts_unchecked(#string, #index_1)
- }}
- }
- }
-}
-
-#[cfg(all(test, feature = "datagen"))]
-pub(crate) mod test {
- use super::*;
-
- pub fn test_patterns() -> ListFormatterPatternsV1<'static> {
- let mut patterns = ListFormatterPatternsV1::try_new([
- // Wide: general
- "@{0}:{1}",
- "{0},{1}",
- "{0}.{1}!",
- "${0};{1}+",
- // Short: different pattern lengths
- "{0}1{1}",
- "{0}12{1}",
- "{0}12{1}34",
- "{0}123{1}456",
- // Narrow: conditionals
- "{0}: {1}",
- "{0}, {1}",
- "{0}. {1}",
- "{0}. {1}",
- ])
- .unwrap();
- patterns
- .make_conditional("{0}. {1}", &StringMatcher::new("A").unwrap(), "{0} :o {1}")
- .unwrap();
- patterns
- }
-
- #[test]
- fn rejects_bad_patterns() {
- assert!(ListJoinerPattern::from_str("{0} and", true, true).is_err());
- assert!(ListJoinerPattern::from_str("and {1}", true, true).is_err());
- assert!(ListJoinerPattern::from_str("{1} and {0}", true, true).is_err());
- assert!(ListJoinerPattern::from_str("{1{0}}", true, true).is_err());
- assert!(ListJoinerPattern::from_str("{0\u{202e}} and {1}", true, true).is_err());
- assert!(ListJoinerPattern::from_str("{{0}} {{1}}", true, true).is_ok());
-
- assert!(ListJoinerPattern::from_str("{0} and {1} ", true, true).is_ok());
- assert!(ListJoinerPattern::from_str("{0} and {1} ", true, false).is_err());
- assert!(ListJoinerPattern::from_str(" {0} and {1}", true, true).is_ok());
- assert!(ListJoinerPattern::from_str(" {0} and {1}", false, true).is_err());
- }
-
- #[test]
- fn produces_correct_parts() {
- assert_eq!(
- test_patterns().pair(ListLength::Wide).parts(""),
- ("$", ";", "+")
- );
- }
-
- #[test]
- fn produces_correct_parts_conditionally() {
- assert_eq!(
- test_patterns().end(ListLength::Narrow).parts("A"),
- ("", " :o ", "")
- );
- assert_eq!(
- test_patterns().end(ListLength::Narrow).parts("a"),
- ("", " :o ", "")
- );
- assert_eq!(
- test_patterns().end(ListLength::Narrow).parts("ab"),
- ("", " :o ", "")
- );
- assert_eq!(
- test_patterns().end(ListLength::Narrow).parts("B"),
- ("", ". ", "")
- );
- assert_eq!(
- test_patterns().end(ListLength::Narrow).parts("BA"),
- ("", ". ", "")
- );
- }
-
- #[test]
- fn size_hint_works() {
- let pattern = test_patterns();
-
- assert_eq!(
- pattern.size_hint(ListLength::Short, 0),
- LengthHint::exact(0)
- );
- assert_eq!(
- pattern.size_hint(ListLength::Short, 1),
- LengthHint::exact(0)
- );
-
- // pair pattern "{0}123{1}456"
- assert_eq!(
- pattern.size_hint(ListLength::Short, 2),
- LengthHint::exact(6)
- );
-
- // patterns "{0}1{1}", "{0}12{1}" (x197), and "{0}12{1}34"
- assert_eq!(
- pattern.size_hint(ListLength::Short, 200),
- LengthHint::exact(1 + 2 * 197 + 4)
- );
-
- // patterns "{0}: {1}", "{0}, {1}" (x197), and "{0} :o {1}" or "{0}. {1}"
- assert_eq!(
- pattern.size_hint(ListLength::Narrow, 200),
- LengthHint::exact(2 + 197 * 2) + LengthHint::between(2, 4)
- );
- }
-
- #[test]
- fn databake() {
- databake::test_bake!(
- ListJoinerPattern,
- const: unsafe { crate::provider::ListJoinerPattern::from_parts_unchecked(", ", 2u8) },
- icu_list
- );
- }
-}
diff --git a/vendor/icu_list/src/provider/mod.rs b/vendor/icu_list/src/provider/mod.rs
new file mode 100644
index 000000000..efab7c8bc
--- /dev/null
+++ b/vendor/icu_list/src/provider/mod.rs
@@ -0,0 +1,261 @@
+// This file is part of ICU4X. For terms of use, please see the file
+// called LICENSE at the top level of the ICU4X source tree
+// (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ).
+
+// Provider structs must be stable
+#![allow(clippy::exhaustive_structs, clippy::exhaustive_enums)]
+
+//! 🚧 \[Unstable\] Data provider struct definitions for this ICU4X component.
+//!
+//! <div class="stab unstable">
+//! 🚧 This code is considered unstable; it may change at any time, in breaking or non-breaking ways,
+//! including in SemVer minor releases. While the serde representation of data structs is guaranteed
+//! to be stable, their Rust representation might not be. Use with caution.
+//! </div>
+//!
+//! Read more about data providers: [`icu_provider`]
+
+use crate::ListLength;
+use alloc::borrow::Cow;
+use icu_provider::DataMarker;
+use icu_provider::{yoke, zerofrom};
+
+mod serde_dfa;
+pub use serde_dfa::SerdeDFA;
+
+/// Symbols and metadata required for [`ListFormatter`](crate::ListFormatter).
+///
+/// <div class="stab unstable">
+/// 🚧 This code is considered unstable; it may change at any time, in breaking or non-breaking ways,
+/// including in SemVer minor releases. While the serde representation of data structs is guaranteed
+/// to be stable, their Rust representation might not be. Use with caution.
+/// </div>
+#[icu_provider::data_struct(
+ AndListV1Marker = "list/and@1",
+ OrListV1Marker = "list/or@1",
+ UnitListV1Marker = "list/unit@1"
+)]
+#[derive(Clone, Debug)]
+#[cfg_attr(
+ feature = "datagen",
+ derive(serde::Serialize, databake::Bake),
+ databake(path = icu_list::provider),
+)]
+pub struct ListFormatterPatternsV1<'data>(
+ #[cfg_attr(feature = "datagen", serde(with = "deduplicating_array"))]
+ /// The patterns in the order start, middle, end, pair, short_start, short_middle,
+ /// short_end, short_pair, narrow_start, narrow_middle, narrow_end, narrow_pair,
+ pub [ConditionalListJoinerPattern<'data>; 12],
+);
+
+#[cfg(feature = "serde")]
+impl<'de> serde::Deserialize<'de> for ListFormatterPatternsV1<'de> {
+ fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
+ where
+ D: serde::de::Deserializer<'de>,
+ {
+ #[cfg(not(feature = "serde_human"))]
+ if deserializer.is_human_readable() {
+ use serde::de::Error;
+ return Err(D::Error::custom(
+ "Deserializing human-readable ListFormatter data requires the 'serde_human' feature",
+ ));
+ }
+
+ Ok(ListFormatterPatternsV1(deduplicating_array::deserialize(
+ deserializer,
+ )?))
+ }
+}
+
+pub(crate) struct ErasedListV1Marker;
+
+impl DataMarker for ErasedListV1Marker {
+ type Yokeable = ListFormatterPatternsV1<'static>;
+}
+
+impl<'data> ListFormatterPatternsV1<'data> {
+ pub(crate) fn start(&self, style: ListLength) -> &ConditionalListJoinerPattern<'data> {
+ #![allow(clippy::indexing_slicing)] // style as usize < 3
+ &self.0[4 * (style as usize)]
+ }
+
+ pub(crate) fn middle(&self, style: ListLength) -> &ConditionalListJoinerPattern<'data> {
+ #![allow(clippy::indexing_slicing)] // style as usize < 3
+ &self.0[4 * (style as usize) + 1]
+ }
+
+ pub(crate) fn end(&self, style: ListLength) -> &ConditionalListJoinerPattern<'data> {
+ #![allow(clippy::indexing_slicing)] // style as usize < 3
+ &self.0[4 * (style as usize) + 2]
+ }
+
+ pub(crate) fn pair(&self, style: ListLength) -> &ConditionalListJoinerPattern<'data> {
+ #![allow(clippy::indexing_slicing)] // style as usize < 3
+ &self.0[4 * (style as usize) + 3]
+ }
+}
+
+/// A pattern that can behave conditionally on the next element.
+///
+/// <div class="stab unstable">
+/// 🚧 This code is considered unstable; it may change at any time, in breaking or non-breaking ways,
+/// including in SemVer minor releases. While the serde representation of data structs is guaranteed
+/// to be stable, their Rust representation might not be. Use with caution.
+/// </div>
+#[derive(Clone, Debug, yoke::Yokeable, zerofrom::ZeroFrom)]
+#[cfg_attr(
+ feature = "datagen",
+ derive(PartialEq, serde::Serialize, databake::Bake),
+ databake(path = icu_list::provider),
+)]
+#[cfg_attr(feature = "serde", derive(serde::Deserialize))]
+pub struct ConditionalListJoinerPattern<'data> {
+ /// The default pattern
+ #[cfg_attr(feature = "serde", serde(borrow))]
+ pub default: ListJoinerPattern<'data>,
+ /// And optional special case
+ #[cfg_attr(
+ feature = "serde",
+ serde(borrow, deserialize_with = "SpecialCasePattern::deserialize_option")
+ )]
+ pub special_case: Option<SpecialCasePattern<'data>>,
+}
+
+/// The special case of a [`ConditionalListJoinerPattern`]
+///
+/// <div class="stab unstable">
+/// 🚧 This code is considered unstable; it may change at any time, in breaking or non-breaking ways,
+/// including in SemVer minor releases. While the serde representation of data structs is guaranteed
+/// to be stable, their Rust representation might not be. Use with caution.
+/// </div>
+#[derive(Clone, Debug, yoke::Yokeable, zerofrom::ZeroFrom)]
+#[cfg_attr(
+ feature = "datagen",
+ derive(PartialEq, serde::Serialize, databake::Bake),
+ databake(path = icu_list::provider),
+)]
+pub struct SpecialCasePattern<'data> {
+ /// The condition on the following element
+ pub condition: SerdeDFA<'data>,
+ /// The pattern if the condition matches
+ pub pattern: ListJoinerPattern<'data>,
+}
+
+#[cfg(feature = "serde")]
+impl<'data> SpecialCasePattern<'data> {
+ // If the condition doesn't deserialize, the whole special case becomes `None`
+ fn deserialize_option<'de: 'data, D>(deserializer: D) -> Result<Option<Self>, D::Error>
+ where
+ D: serde::de::Deserializer<'de>,
+ {
+ use serde::Deserialize;
+
+ #[derive(Deserialize)]
+ struct SpecialCasePatternOptionalDfa<'data> {
+ #[cfg_attr(
+ feature = "serde",
+ serde(borrow, deserialize_with = "SerdeDFA::maybe_deserialize")
+ )]
+ pub condition: Option<SerdeDFA<'data>>,
+ #[cfg_attr(feature = "serde", serde(borrow))]
+ pub pattern: ListJoinerPattern<'data>,
+ }
+
+ Ok(
+ match Option::<SpecialCasePatternOptionalDfa<'data>>::deserialize(deserializer)? {
+ Some(SpecialCasePatternOptionalDfa {
+ condition: Some(condition),
+ pattern,
+ }) => Some(SpecialCasePattern { condition, pattern }),
+ _ => None,
+ },
+ )
+ }
+}
+
+/// A pattern containing two numeric placeholders ("{0}, and {1}.")
+///
+/// <div class="stab unstable">
+/// 🚧 This code is considered unstable; it may change at any time, in breaking or non-breaking ways,
+/// including in SemVer minor releases. While the serde representation of data structs is guaranteed
+/// to be stable, their Rust representation might not be. Use with caution.
+/// </div>
+#[derive(Clone, Debug, PartialEq, yoke::Yokeable, zerofrom::ZeroFrom)]
+#[cfg_attr(feature = "datagen", derive(serde::Serialize))]
+pub struct ListJoinerPattern<'data> {
+ /// The pattern string without the placeholders
+ pub(crate) string: Cow<'data, str>,
+ /// The index of the first placeholder. Always <= index_1.
+ // Always 0 for CLDR data, so we don't need to serialize it.
+ // In-memory we have free space for it as index_1 doesn't
+ // fill a word.
+ #[cfg_attr(feature = "datagen", serde(skip))]
+ pub(crate) index_0: u8,
+ /// The index of the second placeholder. Always < string.len().
+ pub(crate) index_1: u8,
+}
+
+#[cfg(feature = "serde")]
+impl<'de: 'data, 'data> serde::Deserialize<'de> for ListJoinerPattern<'data> {
+ fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
+ where
+ D: serde::Deserializer<'de>,
+ {
+ #[derive(serde::Deserialize)]
+ struct Dummy<'data> {
+ #[cfg_attr(feature = "serde", serde(borrow))]
+ string: Cow<'data, str>,
+ index_1: u8,
+ }
+ let Dummy { string, index_1 } = Dummy::deserialize(deserializer)?;
+
+ if index_1 as usize > string.len() {
+ use serde::de::Error;
+ Err(D::Error::custom("invalid index_1"))
+ } else {
+ Ok(ListJoinerPattern {
+ string,
+ index_0: 0,
+ index_1,
+ })
+ }
+ }
+}
+
+impl<'a> ListJoinerPattern<'a> {
+ /// Constructs a [`ListJoinerPattern`] from raw parts. Used by databake.
+ ///
+ /// # Safety
+ /// index_1 may be at most string.len()
+ pub const unsafe fn from_parts_unchecked(string: &'a str, index_1: u8) -> Self {
+ Self {
+ string: Cow::Borrowed(string),
+ index_0: 0,
+ index_1,
+ }
+ }
+}
+
+#[cfg(feature = "datagen")]
+impl databake::Bake for ListJoinerPattern<'_> {
+ fn bake(&self, env: &databake::CrateEnv) -> databake::TokenStream {
+ env.insert("icu_list");
+ let string = (&*self.string).bake(env);
+ let index_1 = self.index_1.bake(env);
+ // Safe because our own data is safe
+ databake::quote! { unsafe {
+ ::icu_list::provider::ListJoinerPattern::from_parts_unchecked(#string, #index_1)
+ }}
+ }
+}
+
+#[cfg(all(test, feature = "datagen"))]
+#[test]
+fn databake() {
+ databake::test_bake!(
+ ListJoinerPattern,
+ const: unsafe { crate::provider::ListJoinerPattern::from_parts_unchecked(", ", 2u8) },
+ icu_list
+ );
+}
diff --git a/vendor/icu_list/src/provider/serde_dfa.rs b/vendor/icu_list/src/provider/serde_dfa.rs
new file mode 100644
index 000000000..e2424e1e9
--- /dev/null
+++ b/vendor/icu_list/src/provider/serde_dfa.rs
@@ -0,0 +1,244 @@
+// This file is part of ICU4X. For terms of use, please see the file
+// called LICENSE at the top level of the ICU4X source tree
+// (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ).
+
+use alloc::borrow::Cow;
+use icu_provider::{yoke, zerofrom};
+use regex_automata::dfa::sparse::DFA;
+
+/// A serde-compatible version of [regex_automata::dfa::sparse::DFA]. This does not implement
+/// [`serde::Deserialize`] directly, as binary deserialization is not supported in big-endian
+/// platforms. `Self::maybe_deserialize` can be used to deserialize to `Option<SerdeDFA>`.
+///
+/// <div class="stab unstable">
+/// 🚧 This code is considered unstable; it may change at any time, in breaking or non-breaking ways,
+/// including in SemVer minor releases. While the serde representation of data structs is guaranteed
+/// to be stable, their Rust representation might not be. Use with caution.
+/// </div>
+#[derive(Clone, Debug, yoke::Yokeable, zerofrom::ZeroFrom)]
+pub struct SerdeDFA<'data> {
+ // Safety: These always represent a valid DFA (DFA::from_bytes(dfa_bytes).is_ok())
+ dfa_bytes: Cow<'data, [u8]>,
+ pattern: Option<Cow<'data, str>>,
+}
+
+#[cfg(feature = "datagen")]
+impl PartialEq for SerdeDFA<'_> {
+ fn eq(&self, other: &Self) -> bool {
+ self.dfa_bytes == other.dfa_bytes
+ }
+}
+
+#[cfg(feature = "datagen")]
+impl databake::Bake for SerdeDFA<'_> {
+ fn bake(&self, env: &databake::CrateEnv) -> databake::TokenStream {
+ env.insert("icu_list");
+ let le_bytes = self.deref().to_bytes_little_endian().as_slice().bake(env);
+ let be_bytes = self.deref().to_bytes_big_endian().as_slice().bake(env);
+ // Safe because of `to_bytes_little_endian`/`to_bytes_big_endian`'s invariant.
+ databake::quote! {
+ unsafe {
+ ::icu_list::provider::SerdeDFA::from_dfa_bytes_unchecked(
+ if cfg!(target_endian = "little") {
+ &#le_bytes
+ } else {
+ &#be_bytes
+ }
+ )
+ }
+ }
+ }
+}
+
+#[cfg(feature = "datagen")]
+impl serde::Serialize for SerdeDFA<'_> {
+ fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
+ where
+ S: serde::ser::Serializer,
+ {
+ if serializer.is_human_readable() {
+ self.pattern
+ .as_ref()
+ .map(|pattern| pattern.serialize(serializer))
+ .unwrap_or_else(|| {
+ use serde::ser::Error;
+ Err(S::Error::custom(
+ "cannot serialize a deserialized bincode SerdeDFA to JSON",
+ ))
+ })
+ } else {
+ self.deref().to_bytes_little_endian().serialize(serializer)
+ }
+ }
+}
+
+#[cfg(feature = "serde")]
+impl<'data> SerdeDFA<'data> {
+ /// Deserializes to `Option<Self>`. Will return `None` for non-human-readable serialization
+ /// formats on big-endian systems, as `regex_automata` serialization is endian-sensitive.
+ pub fn maybe_deserialize<'de: 'data, D>(deserializer: D) -> Result<Option<Self>, D::Error>
+ where
+ D: serde::de::Deserializer<'de>,
+ {
+ use icu_provider::serde::borrow_de_utils::CowBytesWrap;
+ use serde::Deserialize;
+
+ #[cfg(feature = "serde_human")]
+ if deserializer.is_human_readable() {
+ #[cfg(not(feature = "std"))]
+ use alloc::string::ToString;
+ use serde::de::Error;
+ return SerdeDFA::new(Cow::<str>::deserialize(deserializer)?)
+ .map(Some)
+ .map_err(|e| D::Error::custom(e.to_string()));
+ }
+
+ let dfa_bytes = <CowBytesWrap<'de>>::deserialize(deserializer)?.0;
+
+ if cfg!(target_endian = "big") {
+ return Ok(None);
+ }
+
+ // Verify safety invariant
+ DFA::from_bytes(&dfa_bytes).map_err(|e| {
+ use serde::de::Error;
+ D::Error::custom(alloc::format!("Invalid DFA bytes: {}", e))
+ })?;
+
+ Ok(Some(SerdeDFA {
+ dfa_bytes,
+ pattern: None,
+ }))
+ }
+}
+
+impl<'data> SerdeDFA<'data> {
+ /// Creates a `SerdeDFA` from raw bytes. Used internally by databake.
+ ///
+ /// # Safety
+ ///
+ /// `dfa_bytes` has to be a valid DFA (regex_automata::dfa::sparse::DFA::from_bytes(dfa_bytes).is_ok())
+ pub const unsafe fn from_dfa_bytes_unchecked(dfa_bytes: &'data [u8]) -> Self {
+ Self {
+ dfa_bytes: Cow::Borrowed(dfa_bytes),
+ pattern: None,
+ }
+ }
+
+ /// Creates a `SerdeDFA` from a regex.
+ #[cfg(any(feature = "datagen", feature = "serde_human",))]
+ pub fn new(pattern: Cow<'data, str>) -> Result<Self, icu_provider::DataError> {
+ use regex_automata::{
+ dfa::dense::{Builder, Config},
+ SyntaxConfig,
+ };
+
+ let mut builder = Builder::new();
+ let dfa = builder
+ .syntax(SyntaxConfig::new().case_insensitive(true))
+ .configure(Config::new().anchored(true).minimize(true))
+ .build(&pattern)
+ .map_err(|_| {
+ icu_provider::DataError::custom("Cannot build DFA").with_display_context(&pattern)
+ })?
+ .to_sparse()
+ .map_err(|_| {
+ icu_provider::DataError::custom("Cannot sparsify DFA")
+ .with_display_context(&pattern)
+ })?;
+
+ Ok(Self {
+ dfa_bytes: dfa.to_bytes_native_endian().into(),
+ pattern: Some(pattern),
+ })
+ }
+
+ /// Returns the represented [`DFA`]
+ #[allow(clippy::unwrap_used)] // by invariant
+ pub fn deref(&'data self) -> DFA<&'data [u8]> {
+ // Safe due to struct invariant.
+ unsafe { DFA::from_bytes_unchecked(&self.dfa_bytes).unwrap().0 }
+ }
+}
+
+#[cfg(all(test, feature = "datagen"))]
+mod test {
+ use super::*;
+
+ #[test]
+ fn test_serde_dfa() {
+ use regex_automata::dfa::Automaton;
+
+ let matcher = SerdeDFA::new(Cow::Borrowed("abc")).unwrap();
+
+ assert!(matcher.deref().find_earliest_fwd(b"ab").unwrap().is_none());
+ assert!(matcher.deref().find_earliest_fwd(b"abc").unwrap().is_some());
+ assert!(matcher
+ .deref()
+ .find_earliest_fwd(b"abcde")
+ .unwrap()
+ .is_some());
+ assert!(matcher
+ .deref()
+ .find_earliest_fwd(b" abcde")
+ .unwrap()
+ .is_none());
+ }
+
+ #[derive(serde::Deserialize)]
+ struct OptionSerdeDFA<'data>(
+ #[serde(borrow, deserialize_with = "SerdeDFA::maybe_deserialize")] Option<SerdeDFA<'data>>,
+ );
+
+ #[test]
+ #[cfg(target_endian = "little")]
+ fn test_postcard_serialization() {
+ let matcher = SerdeDFA::new(Cow::Borrowed("abc*")).unwrap();
+
+ let mut bytes = postcard::to_stdvec(&matcher).unwrap();
+ assert_eq!(
+ postcard::from_bytes::<OptionSerdeDFA>(&bytes).unwrap().0,
+ Some(matcher)
+ );
+
+ // A corrupted byte leads to an error
+ bytes[17] ^= 255;
+ assert!(postcard::from_bytes::<OptionSerdeDFA>(&bytes).is_err());
+ bytes[17] ^= 255;
+
+ // An extra byte leads to an error
+ bytes.insert(123, 40);
+ assert!(postcard::from_bytes::<OptionSerdeDFA>(&bytes).is_err());
+ bytes.remove(123);
+
+ // Missing bytes lead to an error
+ assert!(postcard::from_bytes::<OptionSerdeDFA>(&bytes[0..bytes.len() - 5]).is_err());
+ }
+
+ #[test]
+ #[cfg(feature = "serde_human")]
+ fn test_json_serialization() {
+ let matcher = SerdeDFA::new(Cow::Borrowed("abc*")).unwrap();
+
+ let json = serde_json::to_string(&matcher).unwrap();
+ assert_eq!(
+ serde_json::from_str::<OptionSerdeDFA>(&json).unwrap().0,
+ Some(matcher)
+ );
+ assert!(serde_json::from_str::<OptionSerdeDFA>(".*[").is_err());
+ }
+
+ #[test]
+ #[ignore] // https://github.com/rust-lang/rust/issues/98906
+ fn databake() {
+ databake::test_bake!(
+ SerdeDFA,
+ const: unsafe { crate::provider::SerdeDFA::from_dfa_bytes_unchecked(if cfg!(target_endian = "little") {
+ &[1] // TODO: set this when activating the test
+ } else {
+ &[2] // TODO: set this when activating the test
+ })},
+ icu_list
+ );
+ }
+}
diff --git a/vendor/icu_list/src/string_matcher.rs b/vendor/icu_list/src/string_matcher.rs
deleted file mode 100644
index ba4833605..000000000
--- a/vendor/icu_list/src/string_matcher.rs
+++ /dev/null
@@ -1,213 +0,0 @@
-// This file is part of ICU4X. For terms of use, please see the file
-// called LICENSE at the top level of the ICU4X source tree
-// (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ).
-
-use alloc::borrow::Cow;
-#[cfg(any(feature = "serde_human", feature = "datagen"))]
-use alloc::string::ToString;
-use icu_provider::{yoke, zerofrom};
-use regex_automata::dfa::sparse::DFA;
-use regex_automata::dfa::Automaton;
-
-/// A precompiled regex
-#[derive(Clone, Debug, yoke::Yokeable, zerofrom::ZeroFrom)]
-#[allow(clippy::exhaustive_structs)] // not a public API
-pub struct StringMatcher<'data> {
- // Safety: These always represent a valid DFA (DFA::from_bytes(dfa_bytes).is_ok())
- dfa_bytes: Cow<'data, [u8]>,
- pattern: Option<Cow<'data, str>>,
-}
-
-impl PartialEq for StringMatcher<'_> {
- fn eq(&self, other: &Self) -> bool {
- self.dfa_bytes == other.dfa_bytes
- }
-}
-
-#[cfg(feature = "datagen")]
-impl databake::Bake for StringMatcher<'_> {
- fn bake(&self, env: &databake::CrateEnv) -> databake::TokenStream {
- env.insert("icu_list");
- let bytes = (&&*self.dfa_bytes).bake(env);
- // Safe because our own data is safe
- databake::quote! {
- unsafe { ::icu_list::provider::StringMatcher::from_dfa_bytes_unchecked(#bytes) }
- }
- }
-}
-
-#[cfg(feature = "datagen")]
-impl serde::Serialize for StringMatcher<'_> {
- fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
- where
- S: serde::ser::Serializer,
- {
- if serializer.is_human_readable() {
- self.pattern
- .as_ref()
- .map(|pattern| pattern.serialize(serializer))
- .unwrap_or_else(|| {
- use serde::ser::Error;
- Err(S::Error::custom(
- "cannot serialize a deserialized bincode StringMatcher to JSON",
- ))
- })
- } else {
- self.dfa_bytes.serialize(serializer)
- }
- }
-}
-
-#[cfg(feature = "serde")]
-impl<'de: 'data, 'data> serde::Deserialize<'de> for StringMatcher<'data> {
- fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
- where
- D: serde::de::Deserializer<'de>,
- {
- use icu_provider::serde::borrow_de_utils::CowBytesWrap;
-
- #[cfg(feature = "serde_human")]
- if deserializer.is_human_readable() {
- use serde::de::Error;
- return StringMatcher::new(<&str>::deserialize(deserializer)?)
- .map_err(|e| D::Error::custom(e.to_string()));
- }
-
- if cfg!(target_endian = "big") {
- // TODO: Convert LE to BE. For now we just behave like the
- // accept-nothing DFA on BE systems.
- return Ok(StringMatcher {
- dfa_bytes: Cow::Borrowed(&[]),
- pattern: None,
- });
- }
-
- let dfa_bytes = <CowBytesWrap<'de>>::deserialize(deserializer)?.0;
-
- // Verify safety invariant
- DFA::from_bytes(&dfa_bytes).map_err(|e| {
- use serde::de::Error;
- D::Error::custom(alloc::format!("Invalid DFA bytes: {}", e))
- })?;
-
- Ok(StringMatcher {
- dfa_bytes,
- pattern: None,
- })
- }
-}
-
-impl<'data> StringMatcher<'data> {
- /// Creates a `StringMatcher` from a serialized DFA. Used internally by databake.
- ///
- /// # Safety
- ///
- /// `dfa_bytes` has to be a valid DFA (regex_automata::dfa::sparse::DFA::from_bytes(dfa_bytes).is_ok())
- pub const unsafe fn from_dfa_bytes_unchecked(dfa_bytes: &'data [u8]) -> Self {
- Self {
- dfa_bytes: Cow::Borrowed(dfa_bytes),
- pattern: None,
- }
- }
-
- /// Creates a `StringMatcher` from regex.
- #[cfg(any(feature = "datagen", feature = "serde_human",))]
- pub fn new(pattern: &str) -> Result<Self, icu_provider::DataError> {
- use regex_automata::{
- dfa::dense::{Builder, Config},
- SyntaxConfig,
- };
-
- let mut builder = Builder::new();
- let dfa = builder
- .syntax(SyntaxConfig::new().case_insensitive(true))
- .configure(Config::new().anchored(true).minimize(true))
- .build(pattern)
- .map_err(|_| {
- icu_provider::DataError::custom("Cannot build DFA").with_display_context(&pattern)
- })?
- .to_sparse()
- .map_err(|_| {
- icu_provider::DataError::custom("Cannot sparsify DFA")
- .with_display_context(&pattern)
- })?;
-
- Ok(Self {
- dfa_bytes: dfa.to_bytes_little_endian().into(),
- pattern: Some(pattern.to_string().into()),
- })
- }
-
- #[allow(clippy::unwrap_used)] // by invariant
- pub(crate) fn test(&self, string: &str) -> bool {
- cfg!(target_endian = "little")
- && matches!(
- // Safe due to struct invariant.
- unsafe { DFA::from_bytes_unchecked(&self.dfa_bytes).unwrap().0 }
- .find_earliest_fwd(string.as_bytes()),
- Ok(Some(_))
- )
- }
-}
-
-#[cfg(all(test, feature = "datagen"))]
-mod test {
- use super::*;
-
- #[test]
- fn test_string_matcher() {
- let matcher = StringMatcher::new("abc.*").unwrap();
- assert!(!matcher.test("ab"));
- assert!(matcher.test("abc"));
- assert!(matcher.test("abcde"));
- }
-
- #[test]
- fn test_postcard_serialization() {
- let matcher = StringMatcher::new("abc*").unwrap();
-
- let mut bytes = postcard::to_stdvec(&matcher).unwrap();
- assert_eq!(
- postcard::from_bytes::<StringMatcher>(&bytes).unwrap(),
- matcher
- );
-
- // A corrupted byte leads to an error
- bytes[17] ^= 255;
- assert!(postcard::from_bytes::<StringMatcher>(&bytes).is_err());
- bytes[17] ^= 255;
-
- // An extra byte leads to an error
- bytes.insert(123, 40);
- assert!(postcard::from_bytes::<StringMatcher>(&bytes).is_err());
- bytes.remove(123);
-
- // Missing bytes lead to an error
- assert!(postcard::from_bytes::<StringMatcher>(&bytes[0..bytes.len() - 5]).is_err());
- }
-
- #[test]
- #[cfg(feature = "serde_human")]
- fn test_json_serialization() {
- let matcher = StringMatcher::new("abc*").unwrap();
-
- let json = serde_json::to_string(&matcher).unwrap();
- assert_eq!(
- serde_json::from_str::<StringMatcher>(&json).unwrap(),
- matcher
- );
- assert!(serde_json::from_str::<StringMatcher>(".*[").is_err());
- }
-
- #[test]
- #[ignore] // https://github.com/rust-lang/rust/issues/98906
- fn databake() {
- databake::test_bake!(
- StringMatcher,
- const: unsafe {
- crate::provider::StringMatcher::from_dfa_bytes_unchecked(&[49u8, 50u8, 51u8, ])
- },
- icu_list
- );
- }
-}
diff --git a/vendor/icu_locid/.cargo-checksum.json b/vendor/icu_locid/.cargo-checksum.json
index 1f1097bd7..1ea6414e8 100644
--- a/vendor/icu_locid/.cargo-checksum.json
+++ b/vendor/icu_locid/.cargo-checksum.json
@@ -1 +1 @@
-{"files":{"Cargo.lock":"6bf9c8304a3fe9f99d7189f9a082be2c7859ea164976975069f8fd2f7f80bbbd","Cargo.toml":"44c6bcdc448226df67e425cb00bf02596c96d0a0bfcb3951d3a5d0998afaa60d","LICENSE":"4ad7541d66a407234e2c84902124cef325c29f3e966353efdb800bedb8b8da21","README.md":"d0e5ced27519cf715a66dc4fece18c8cacece8dbb81eb1e03ab82dd57f0bc7f5","benches/fixtures/langid.json":"373c11527653c63c685c9e229a8de5ae2b557c25b686a9d891c59e1f603232d8","benches/fixtures/locale.json":"669b19db933094290a45bf856559920f4e92401072e364ac82c482119dc9233a","benches/fixtures/mod.rs":"9a9671eddcf38a6faa10cb814949f8abc15d89f5e70f3ad6f684f1bc3ffe72ea","benches/fixtures/subtags.json":"28be3a639e452d713e807d5779b6819e06277e2dbbf67801ef34964fb9b074b6","benches/helpers/macros.rs":"bba0945a826bc083156bc302507c48c0c99c4d965e2a84352644d768591b0339","benches/helpers/mod.rs":"c98167d866fdb7f66c8cab41e8d57b5aab9e9707dfc66c37ef136e088dac6fef","benches/iai_langid.rs":"675ab67edc2820894e1179e97e3aad6037957084efa07e494c17c40f3c0bbe35","benches/langid.rs":"4e3d307d48fd9071308a567a0ef927b229814978abd2ba29f57c65edd51f38e4","benches/locale.rs":"b8d5b1e3f8b5578c549a5149229656fb60de26b76a1bf66b6c1abce75042d674","benches/subtags.rs":"e7e80dabaf31bf031779456614f139cafcdadb805986e71b49133ac964928432","examples/filter_langids.rs":"28bea5b7dc715d6c00694437c3f12a72cf68dc984bb13acbb7b1ce5f97c5726a","examples/syntatically_canonicalize_locales.rs":"de97579c82f1670629d077a6216ecce06761da28715387f46250f81b8172ae6b","src/extensions/mod.rs":"76efffe1c99da3ef61a93f8174267e4b0b63abc3283ec8e0c5170ebc582263fe","src/extensions/other/mod.rs":"4216cd8a4dcef13105b48e507659920feaaa3fa3aebc2ba8d7702b40bbec2881","src/extensions/other/subtag.rs":"cb52ec1acec55e4c0e1d37cc5a552d11010051d827786202702257c8fcd96c49","src/extensions/private/mod.rs":"961bfb455114ad7166beb5acb36a1b182d2e81d99cccbfd3b3bf68853cae490d","src/extensions/private/other.rs":"586fd24398e78c5fda0afdb98de28a6467afd2d702683daf5dfab2a6c45af1e9","src/extensions/transform/fields.rs":"376ae5862329709d54b262a6d91be97bb02fc5e0198f30be8a2f4b0adc420c8b","src/extensions/transform/key.rs":"53e8c9ce13f00f678c2322855cc1d90afd91cd33a2af3758d098b7bbcc7090e5","src/extensions/transform/mod.rs":"c932d7e4484ac3bf3c9fe0c63b17847d8cb29f8874d71cd17070e63b8bca5998","src/extensions/transform/value.rs":"153c4edeb987e052dafe0790bcda560da4dcfa6897e5aaf3f62ae772b0605009","src/extensions/unicode/attribute.rs":"d558a193b72f54cdb03afe8e023a145ac74832c8416ca55401cd417ebba2431c","src/extensions/unicode/attributes.rs":"f2f13714750035ff805455b43ba665710978d13b90a53358314e798662c436b6","src/extensions/unicode/key.rs":"6c8694527079c5dd5f03f8e85f23ae6b5aa4b47899d1047036960e8400dca7de","src/extensions/unicode/keywords.rs":"58a2eca7c5e6ac6ad6812538a5b8118e35274c6b5de8029d55cbe1b4cd0a4abb","src/extensions/unicode/mod.rs":"e81db13fdb2db8d6cf7cfcd7c0d926b929fceca500894e688768b3494d02d0c3","src/extensions/unicode/value.rs":"02876ed95059d21d09ff2b986776d6bf0cb14c698237a86a9be24886ffd7a1cd","src/helpers.rs":"a6b8c22ef40a57339e4051fad54e724320851f827bc6f888187f30371024d04a","src/langid.rs":"b3258b1be6566dc117295a525dcb04237f0049c59dc91f460d939cd162ef8b39","src/lib.rs":"6f6248e20709be74b9e186b45810a4963ffa91c680be4ad78be9a6af5a10da5c","src/locale.rs":"a1ff7500d17581fe06524f6d70d59f0765c5d5ca89cb64b42953b286b20727b4","src/macros.rs":"f7154fc103ea1120a55bb5898540b20df80de6eec42e70ce15f339d997f2bf52","src/ordering.rs":"c70aa4e33d5cbab8d75d2833641141b71984a93648634cfc57fc25c3f79a5f58","src/parser/errors.rs":"ccea5e49c109db3766a71ac4aab1d759e2351c4cd31816b6abdca166699c7f3e","src/parser/langid.rs":"ef5c3dc233a5cea1953688e69152c601a3260196caa9327dd07edc7b6be7b0b8","src/parser/locale.rs":"b7d4cd4ed80b0acae9e77046a3b4943ee19e4aec395e36951750da32366b9a8e","src/parser/mod.rs":"c65268221fc67a692a2a647b08dd81b244a9186c04f5ab0837383dcaa983b740","src/serde.rs":"06e940e4f2d15f02d313b4e2b233aea3e74c93c6c43076f5ffe52d49c133608f","src/subtags/language.rs":"e9dc6de6c6aebb6d8bf6e55f1ae9fab41844a52e681b4309e625a5076c02f9f3","src/subtags/mod.rs":"0257f746ed368ea3fa675054c9e7e40d972ec31cd7cc525be655a16a83c9d17b","src/subtags/region.rs":"4f4120f4910d0a4496f29c193d00313e71be4c646867d97ebd0e9a7438693847","src/subtags/script.rs":"6b1a68783cb90409bdd39b0184dfb2cb1c302fdee7202e3b6f7c7c8941bc7dfe","src/subtags/variant.rs":"956f1ea3d98172b6ead333411f010cf4e84404584a3051cb775d148d79beb4f8","src/subtags/variants.rs":"7740d1b20f596b04f509db917e9c2fffba80a013ffc42f0046cdc2d32b088aeb","src/zerovec.rs":"9d01a235d18296fbf0c2e89d188459e9446df0e63aaedc7e150165604af885b9","tests/fixtures/canonicalize.json":"9f2b7cbef72c24944cd4dc50de368c6e3ef69949f29c9ce1aa8807de767a4d0a","tests/fixtures/invalid-extensions.json":"0af95f38e458c8f52760f76c6540993beb9ba9421a3967df0cd6abb9fe2ce21a","tests/fixtures/invalid.json":"1f1ae207f1ce886b3f57cfcdfb2525aa3e58d538f997b2bda4088062de7aa68d","tests/fixtures/langid.json":"960fd01722217ef1ea9077e2e0821d7089fe318a241bd7fb7918f50bf8f3f5c3","tests/fixtures/locale.json":"8606e0569fc6ea0e50a1fecb9295b911fbef7d8dbfde3c585476284a751baccf","tests/fixtures/mod.rs":"28dec3e5c9d766e148adbff6857dce884d9ff94f7ef8aee17fde0084cc78a7ee","tests/helpers/mod.rs":"d3bf59e7eed6230f340bef6c87a7b8de3a387ec391f60afc1b15a0d001cbfb67","tests/langid.rs":"2e21d576a6eaba000fbe88d52362384f460ba350cac1e7034a1661302000ac58","tests/locale.rs":"91af0a738ca5def89fdb4d7f8d3504ad7b757e1d7c8e4d24dc246de610b46a04"},"package":"34b3de5d99a0e275fe6193b9586dbf37364daebc0d39c89b5cf8376a53b789e8"} \ No newline at end of file
+{"files":{"Cargo.lock":"332fcd0f371d9ef54006d7525bfc6a8adae7433754a3fbc0328530f421d92d0d","Cargo.toml":"c60a23e3795ec4820118fc5dec6ffb9bdca684d95511de01ea5a04d6d8272bc8","LICENSE":"4ad7541d66a407234e2c84902124cef325c29f3e966353efdb800bedb8b8da21","README.md":"16472983782c836d9e97b4df4754baab7bb247d0a945d1a97cafb3210e951d8f","benches/fixtures/langid.json":"373c11527653c63c685c9e229a8de5ae2b557c25b686a9d891c59e1f603232d8","benches/fixtures/locale.json":"669b19db933094290a45bf856559920f4e92401072e364ac82c482119dc9233a","benches/fixtures/mod.rs":"9a9671eddcf38a6faa10cb814949f8abc15d89f5e70f3ad6f684f1bc3ffe72ea","benches/fixtures/subtags.json":"28be3a639e452d713e807d5779b6819e06277e2dbbf67801ef34964fb9b074b6","benches/helpers/macros.rs":"bba0945a826bc083156bc302507c48c0c99c4d965e2a84352644d768591b0339","benches/helpers/mod.rs":"c98167d866fdb7f66c8cab41e8d57b5aab9e9707dfc66c37ef136e088dac6fef","benches/iai_langid.rs":"7984d12b78a0e2ecfa1eac74ccf7310627285de821c13fab2fe000f0e961a136","benches/langid.rs":"4e3d307d48fd9071308a567a0ef927b229814978abd2ba29f57c65edd51f38e4","benches/locale.rs":"b8d5b1e3f8b5578c549a5149229656fb60de26b76a1bf66b6c1abce75042d674","benches/subtags.rs":"e7e80dabaf31bf031779456614f139cafcdadb805986e71b49133ac964928432","examples/filter_langids.rs":"f36f6732b08a954d41ea95dfb3f07963f7c120e80ed29f4de7c9ec562c0151d6","examples/syntatically_canonicalize_locales.rs":"de97579c82f1670629d077a6216ecce06761da28715387f46250f81b8172ae6b","src/extensions/mod.rs":"106af2b8186202aa8c654acc085619d99fdbdbc467c276ead8283b9938c75ba7","src/extensions/other/mod.rs":"ee377c2eeaa6b622a2c80807bffdd307800030fe2ec8a99a9729bdde45452635","src/extensions/other/subtag.rs":"431d27a0a5adca7d56c7ea3a6de2a0412e1e14ad2dd8a8e09a548849984b84b6","src/extensions/private/mod.rs":"5d53d32adb79386416b6eb4a9de218423f3bee4000e96e4899b78462f609531c","src/extensions/private/other.rs":"586fd24398e78c5fda0afdb98de28a6467afd2d702683daf5dfab2a6c45af1e9","src/extensions/transform/fields.rs":"9221478ce7565738bb27951a6be25b3ebc5c11d63afb2ca744fd4c587d155e9b","src/extensions/transform/key.rs":"53e8c9ce13f00f678c2322855cc1d90afd91cd33a2af3758d098b7bbcc7090e5","src/extensions/transform/mod.rs":"111ebf59ad6cd9a09a8eb84367a0053ff03fff8329f07310131784a457d07b61","src/extensions/transform/value.rs":"577b642b32f7a74e98ba5bee8e30700021c8b0e6da63538398aaf95d13edfd65","src/extensions/unicode/attribute.rs":"d558a193b72f54cdb03afe8e023a145ac74832c8416ca55401cd417ebba2431c","src/extensions/unicode/attributes.rs":"ddc0361968151e28cc1e6a3d91056a0f71f2c42f22dacecd339aaa67dfdcf899","src/extensions/unicode/key.rs":"6c8694527079c5dd5f03f8e85f23ae6b5aa4b47899d1047036960e8400dca7de","src/extensions/unicode/keywords.rs":"d98b0799c171557c9d042bcc06389ac9742ae0a4910d9ceb1612d1ac5045222c","src/extensions/unicode/mod.rs":"e066cbdabf567a40c777428d071e2e82389a043bd552bc1e83202401c86e0b2e","src/extensions/unicode/value.rs":"38b96501db9ebc3da583162d68279de30096b896209874ff052dcc10f874d98a","src/helpers.rs":"54272463a938a04fd2cf5a663128ea08f36744180f0eb49fa2ad7de105c0c19a","src/langid.rs":"77dce95dd5549c15cbfa9f34f3521f7ad1d1c1b16c3d972f28023f59283bd56f","src/lib.rs":"661efd6459894a1821861a8b7e0a7e73484c49f5d297810aed401f7a66c45985","src/locale.rs":"98c5389226e3dd2ae9378225c129d0eb264d5b1d712111f2587489d01feeb546","src/macros.rs":"f7154fc103ea1120a55bb5898540b20df80de6eec42e70ce15f339d997f2bf52","src/ordering.rs":"c70aa4e33d5cbab8d75d2833641141b71984a93648634cfc57fc25c3f79a5f58","src/parser/errors.rs":"44a25385a2dc7d537b3ce482fc02169eda1e5e727ee99b00f0fd85cb501ee939","src/parser/langid.rs":"749ac36945e7b5e24cbc82f04900f10f770fc24f7ce007af4c3be7a325ccc631","src/parser/locale.rs":"075c74803891894ad50bbedc69366931b8e76c0992b3caa1a5632f0a6816ccfd","src/parser/mod.rs":"5182392624876a419b1469d135d175aba680bb13d14e4f6ea0cfc4e071fbc743","src/serde.rs":"06e940e4f2d15f02d313b4e2b233aea3e74c93c6c43076f5ffe52d49c133608f","src/subtags/language.rs":"2ebc98952bd4a6b4077c77da1895225faacc17020af8a47675b8b41b05b9e7eb","src/subtags/mod.rs":"0257f746ed368ea3fa675054c9e7e40d972ec31cd7cc525be655a16a83c9d17b","src/subtags/region.rs":"4f4120f4910d0a4496f29c193d00313e71be4c646867d97ebd0e9a7438693847","src/subtags/script.rs":"6b1a68783cb90409bdd39b0184dfb2cb1c302fdee7202e3b6f7c7c8941bc7dfe","src/subtags/variant.rs":"956f1ea3d98172b6ead333411f010cf4e84404584a3051cb775d148d79beb4f8","src/subtags/variants.rs":"511aca7f5b75509b6b1b095e3465ab096430cc97b38e0bcb5956e71fa01c3189","src/zerovec.rs":"9d01a235d18296fbf0c2e89d188459e9446df0e63aaedc7e150165604af885b9","tests/fixtures/canonicalize.json":"9f2b7cbef72c24944cd4dc50de368c6e3ef69949f29c9ce1aa8807de767a4d0a","tests/fixtures/invalid-extensions.json":"4b7888006360b216030597257de8c301e22877e75216818967bbd8c83b6dbb0b","tests/fixtures/invalid.json":"5247849a6eb805619b8e70254c855227f7bdaf71431b071c91c6cc378ae9766e","tests/fixtures/langid.json":"960fd01722217ef1ea9077e2e0821d7089fe318a241bd7fb7918f50bf8f3f5c3","tests/fixtures/locale.json":"8606e0569fc6ea0e50a1fecb9295b911fbef7d8dbfde3c585476284a751baccf","tests/fixtures/mod.rs":"aea619960540b92199345cbd20ff03d2cb451aa2ce9aa6cf7915223ee9f812a3","tests/helpers/mod.rs":"d3bf59e7eed6230f340bef6c87a7b8de3a387ec391f60afc1b15a0d001cbfb67","tests/langid.rs":"43a0d381bdd9a8567898c137337a1563bea6db6fb36ecb853f496366faf8ff79","tests/locale.rs":"0cd3f09e83f6c093bca9676845612343a1e179d8584735e069008248e126eccf"},"package":"71d7a98ecb812760b5f077e55a4763edeefa7ccc30d6eb5680a70841ede81928"} \ No newline at end of file
diff --git a/vendor/icu_locid/Cargo.lock b/vendor/icu_locid/Cargo.lock
index 9940858d2..401f5d44d 100644
--- a/vendor/icu_locid/Cargo.lock
+++ b/vendor/icu_locid/Cargo.lock
@@ -8,7 +8,7 @@ version = "0.2.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
dependencies = [
- "hermit-abi",
+ "hermit-abi 0.1.19",
"libc",
"winapi",
]
@@ -39,9 +39,9 @@ dependencies = [
[[package]]
name = "bumpalo"
-version = "3.11.0"
+version = "3.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c1ad822118d20d2c234f427000d5acc36eabe1e29a348c89b63dd60b13f28e5d"
+checksum = "0d261e256854913907f67ed06efbc3338dfe6179796deefc1ff763fc1aee5535"
[[package]]
name = "cast"
@@ -131,26 +131,24 @@ dependencies = [
[[package]]
name = "crossbeam-epoch"
-version = "0.9.10"
+version = "0.9.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "045ebe27666471bb549370b4b0b3e51b07f56325befa4284db65fc89c02511b1"
+checksum = "01a9af1f4c2ef74bb8aa1f7e19706bc72d03598c8a570bb5de72243c7a9d9d5a"
dependencies = [
"autocfg",
"cfg-if",
"crossbeam-utils",
"memoffset",
- "once_cell",
"scopeguard",
]
[[package]]
name = "crossbeam-utils"
-version = "0.8.11"
+version = "0.8.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "51887d4adc7b564537b15adcfb307936f8075dfcd5f00dde9a9f1d29383682bc"
+checksum = "4fb766fa798726286dbbb842f174001dab8abc7b627a1dd86e0b7222a95d929f"
dependencies = [
"cfg-if",
- "once_cell",
]
[[package]]
@@ -177,9 +175,9 @@ dependencies = [
[[package]]
name = "databake"
-version = "0.1.2"
+version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c87777d6d7bde863ba217aa87521dc857239de1f36d66aac46fd173fb0495858"
+checksum = "df626c4717e455cd7a70a82c4358630554a07e4341f86dd095c625f1474a2857"
dependencies = [
"databake-derive",
"proc-macro2",
@@ -189,9 +187,9 @@ dependencies = [
[[package]]
name = "databake-derive"
-version = "0.1.1"
+version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "905c7a060fc0c84c0452d97473b1177dd7a5cbc7670cfbae4a7fe22e42f6432e"
+checksum = "be51a53c468489ae1ef0efa9f6b10706f426c0dde06d66122ffef1f0c51e87dc"
dependencies = [
"proc-macro2",
"quote",
@@ -232,26 +230,28 @@ dependencies = [
]
[[package]]
-name = "iai"
-version = "0.1.1"
+name = "hermit-abi"
+version = "0.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "71a816c97c42258aa5834d07590b718b4c9a598944cd39a52dc25b351185d678"
+checksum = "ee512640fe35acbfb4bb779db6f0d80704c2cacfa2e39b601ef3e3f47d1ae4c7"
+dependencies = [
+ "libc",
+]
[[package]]
-name = "icu_benchmark_macros"
-version = "0.7.0"
+name = "iai"
+version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6c867656f2d9c90b13709ac88e710a9d6afe33998c1dfa22384bab8804e8b3d4"
+checksum = "71a816c97c42258aa5834d07590b718b4c9a598944cd39a52dc25b351185d678"
[[package]]
name = "icu_locid"
-version = "1.0.0"
+version = "1.1.0"
dependencies = [
"criterion",
"databake",
"displaydoc",
"iai",
- "icu_benchmark_macros",
"litemap",
"postcard",
"serde",
@@ -278,9 +278,9 @@ checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4"
[[package]]
name = "itoa"
-version = "1.0.3"
+version = "1.0.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6c8af84674fe1f223a982c933a0ee1086ac4d4052aa0fb8060c12c6ad838e754"
+checksum = "fad582f4b9e86b6caa621cabeb0963332d92eea04729ab12892c2533951e6440"
[[package]]
name = "js-sys"
@@ -299,15 +299,15 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
[[package]]
name = "libc"
-version = "0.2.133"
+version = "0.2.139"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c0f80d65747a3e43d1596c7c5492d95d5edddaabd45a7fcdb02b95f644164966"
+checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79"
[[package]]
name = "litemap"
-version = "0.6.0"
+version = "0.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f34a3f4798fac63fb48cf277eefa38f94d3443baff555bb98e4f56bc9092368e"
+checksum = "575d8a551c59104b4df91269921e5eab561aa1b77c618dac0414b5d44a4617de"
[[package]]
name = "log"
@@ -326,9 +326,9 @@ checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
[[package]]
name = "memoffset"
-version = "0.6.5"
+version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce"
+checksum = "5de893c32cde5f383baa4c04c5d6dbdd735cfd4a794b0debdb2bb1b421da5ff4"
dependencies = [
"autocfg",
]
@@ -344,19 +344,19 @@ dependencies = [
[[package]]
name = "num_cpus"
-version = "1.13.1"
+version = "1.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "19e64526ebdee182341572e50e9ad03965aa510cd94427a4549448f285e957a1"
+checksum = "0fac9e2da13b5eb447a6ce3d392f23a29d8694bff781bf03a16cd9ac8697593b"
dependencies = [
- "hermit-abi",
+ "hermit-abi 0.2.6",
"libc",
]
[[package]]
name = "once_cell"
-version = "1.15.0"
+version = "1.17.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e82dad04139b71a90c080c8463fe0dc7902db5192d939bd0950f074d014339e1"
+checksum = "6f61fba1741ea2b3d6a1e3178721804bb716a68a6aeba1149b5d52e3d464ea66"
[[package]]
name = "oorandom"
@@ -404,39 +404,37 @@ dependencies = [
[[package]]
name = "proc-macro2"
-version = "1.0.44"
+version = "1.0.50"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7bd7356a8122b6c4a24a82b278680c73357984ca2fc79a0f9fa6dea7dced7c58"
+checksum = "6ef7d57beacfaf2d8aee5937dab7b7f28de3cb8b1828479bb5de2a7106f2bae2"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
-version = "1.0.21"
+version = "1.0.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179"
+checksum = "8856d8364d252a14d474036ea1358d63c9e6965c8e5c1885c18f73d70bff9c7b"
dependencies = [
"proc-macro2",
]
[[package]]
name = "rayon"
-version = "1.5.3"
+version = "1.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bd99e5772ead8baa5215278c9b15bf92087709e9c1b2d1f97cdb5a183c933a7d"
+checksum = "6db3a213adf02b3bcfd2d3846bb41cb22857d131789e01df434fb7e7bc0759b7"
dependencies = [
- "autocfg",
- "crossbeam-deque",
"either",
"rayon-core",
]
[[package]]
name = "rayon-core"
-version = "1.9.3"
+version = "1.10.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "258bcdb5ac6dad48491bb2992db6b7cf74878b0384908af124823d118c99683f"
+checksum = "356a0625f1954f730c0201cdab48611198dc6ce21f4acff55089b5a78e6e835b"
dependencies = [
"crossbeam-channel",
"crossbeam-deque",
@@ -446,9 +444,9 @@ dependencies = [
[[package]]
name = "regex"
-version = "1.6.0"
+version = "1.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4c4eb3267174b8c6c2f654116623910a0fef09c4753f8dd83db29c48a0df988b"
+checksum = "48aaa5748ba571fb95cd2c85c09f629215d3a6ece942baa100950af03a34f733"
dependencies = [
"regex-syntax",
]
@@ -461,15 +459,15 @@ checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132"
[[package]]
name = "regex-syntax"
-version = "0.6.27"
+version = "0.6.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a3f87b73ce11b1619a3c6332f45341e0047173771e8b8b73f87bfeefb7b56244"
+checksum = "456c603be3e8d448b072f410900c09faf164fbce2d480456f50eea6e25f9c848"
[[package]]
name = "ryu"
-version = "1.0.11"
+version = "1.0.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4501abdff3ae82a1c1b477a17252eb69cee9e66eb915c1abaa4f44d873df9f09"
+checksum = "7b4b9743ed687d4b4bcedf9ff5eaa7398495ae14e61cba0a295704edbc7decde"
[[package]]
name = "same-file"
@@ -488,9 +486,9 @@ checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
[[package]]
name = "serde"
-version = "1.0.145"
+version = "1.0.152"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "728eb6351430bccb993660dfffc5a72f91ccc1295abaa8ce19b27ebe4f75568b"
+checksum = "bb7d1f0d3021d347a83e556fc4683dea2ea09d87bccdf88ff5c12545d89d5efb"
dependencies = [
"serde_derive",
]
@@ -507,9 +505,9 @@ dependencies = [
[[package]]
name = "serde_derive"
-version = "1.0.145"
+version = "1.0.152"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "81fa1584d3d1bcacd84c277a0dfe21f5b0f6accf4a23d04d4c6d61f1af522b4c"
+checksum = "af487d118eecd09402d70a5d72551860e788df87b464af30e5ea6a38c75c541e"
dependencies = [
"proc-macro2",
"quote",
@@ -518,20 +516,20 @@ dependencies = [
[[package]]
name = "serde_json"
-version = "1.0.85"
+version = "1.0.91"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e55a28e3aaef9d5ce0506d0a14dbba8054ddc7e499ef522dd8b26859ec9d4a44"
+checksum = "877c235533714907a8c2464236f5c4b2a17262ef1bd71f38f35ea592c8da6883"
dependencies = [
- "itoa 1.0.3",
+ "itoa 1.0.5",
"ryu",
"serde",
]
[[package]]
name = "syn"
-version = "1.0.101"
+version = "1.0.107"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e90cde112c4b9690b8cbe810cba9ddd8bc1d7472e2cae317b69e9438c1cba7d2"
+checksum = "1f4064b5b16e03ae50984a5a8ed5d4f8803e6bc1fd170a3cda91a1be4b18e3f5"
dependencies = [
"proc-macro2",
"quote",
@@ -561,9 +559,9 @@ dependencies = [
[[package]]
name = "tinystr"
-version = "0.7.0"
+version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f8aeafdfd935e4a7fe16a91ab711fa52d54df84f9c8f7ca5837a9d1d902ef4c2"
+checksum = "7ac3f5b6856e931e15e07b478e98c8045239829a65f9156d4fa7e7788197a5ef"
dependencies = [
"displaydoc",
"serde",
@@ -581,9 +579,9 @@ dependencies = [
[[package]]
name = "unicode-ident"
-version = "1.0.4"
+version = "1.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dcc811dc4066ac62f84f11307873c4850cb653bfa9b1719cee2bd2204a4bc5dd"
+checksum = "84a22b9f218b40614adcb3f4ff08b703773ad44fa9423e4e0d346d5db86e4ebc"
[[package]]
name = "unicode-width"
@@ -705,9 +703,9 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
[[package]]
name = "writeable"
-version = "0.5.0"
+version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f8e6ab4f5da1b24daf2c590cfac801bacb27b15b4f050e84eb60149ea726f06b"
+checksum = "92d74a687e3b9a7a129db0a8c82b4d464eb9c36f5a66ca68572a7e5f1cfdb5bc"
[[package]]
name = "zerofrom"
@@ -717,9 +715,9 @@ checksum = "79e9355fccf72b04b7deaa99ce7a0f6630530acf34045391b74460fcd714de54"
[[package]]
name = "zerovec"
-version = "0.9.0"
+version = "0.9.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b9d919a74c17749ccb17beaf6405562e413cd94e98ba52ca1e64bbe7eefbd8b8"
+checksum = "154df60c74c4a844bc04a53cef4fc18a909d3ea07e19f5225eaba86209da3aa6"
dependencies = [
"zerofrom",
]
diff --git a/vendor/icu_locid/Cargo.toml b/vendor/icu_locid/Cargo.toml
index 3ce7066e7..dbbe6ed2b 100644
--- a/vendor/icu_locid/Cargo.toml
+++ b/vendor/icu_locid/Cargo.toml
@@ -12,7 +12,7 @@
[package]
edition = "2021"
name = "icu_locid"
-version = "1.0.0"
+version = "1.1.0"
authors = ["The ICU4X Project Developers"]
include = [
"src/**/*",
@@ -30,14 +30,12 @@ license = "Unicode-DFS-2016"
repository = "https://github.com/unicode-org/icu4x"
resolver = "2"
-[package.metadata.cargo-all-features]
-skip_optional_dependencies = true
-denylist = ["bench"]
-extra_features = ["serde"]
-
[package.metadata.docs.rs]
all-features = true
+[package.metadata.cargo-all-features]
+denylist = ["bench"]
+
[lib]
path = "src/lib.rs"
bench = false
@@ -69,7 +67,7 @@ harness = false
required-features = ["bench"]
[dependencies.databake]
-version = "0.1.0"
+version = "0.1.3"
features = ["derive"]
optional = true
@@ -78,7 +76,7 @@ version = "0.2.3"
default-features = false
[dependencies.litemap]
-version = "0.6"
+version = "0.6.1"
[dependencies.serde]
version = "1.0"
@@ -90,15 +88,15 @@ optional = true
default-features = false
[dependencies.tinystr]
-version = "0.7"
+version = "0.7.1"
features = ["alloc"]
default-features = false
[dependencies.writeable]
-version = "0.5"
+version = "0.5.1"
[dependencies.zerovec]
-version = "0.9"
+version = "0.9.2"
optional = true
[dev-dependencies.criterion]
@@ -107,13 +105,6 @@ version = "0.3.3"
[dev-dependencies.iai]
version = "0.1.1"
-[dev-dependencies.icu_benchmark_macros]
-version = "0.7"
-
-[dev-dependencies.litemap]
-version = "0.6"
-features = ["testing"]
-
[dev-dependencies.postcard]
version = "1.0.0"
features = ["use-std"]
@@ -128,9 +119,10 @@ version = "1.0"
[features]
bench = ["serde"]
-default = []
+databake = ["dep:databake"]
serde = [
"dep:serde",
"tinystr/serde",
]
std = []
+zerovec = ["dep:zerovec"]
diff --git a/vendor/icu_locid/README.md b/vendor/icu_locid/README.md
index cc2a0b023..5f49c35f5 100644
--- a/vendor/icu_locid/README.md
+++ b/vendor/icu_locid/README.md
@@ -20,36 +20,21 @@ If in doubt, use [`Locale`].
## Examples
```rust
-use icu::locid::subtags::{Language, Region};
use icu::locid::Locale;
+use icu::locid::{
+ locale, subtags_language as language, subtags_region as region,
+};
-let mut loc: Locale = "en-US".parse().expect("Parsing failed.");
-
-let lang: Language = "en".parse().expect("Parsing failed.");
-let region: Region = "US".parse().expect("Parsing failed.");
+let mut loc: Locale = locale!("en-US");
-assert_eq!(loc.id.language, lang);
+assert_eq!(loc.id.language, language!("en"));
assert_eq!(loc.id.script, None);
-assert_eq!(loc.id.region, Some(region));
+assert_eq!(loc.id.region, Some(region!("US")));
assert_eq!(loc.id.variants.len(), 0);
-let region: Region = "GB".parse().expect("Parsing failed.");
-loc.id.region = Some(region);
-
-assert_eq!(loc.to_string(), "en-GB");
-```
-
-### Macros
-
-```rust
-use icu::locid::{
- langid, subtags_language as language, subtags_region as region,
-};
-
-let lid = langid!("EN_US");
+loc.id.region = Some(region!("GB"));
-assert_eq!(lid.language, language!("en"));
-assert_eq!(lid.region, Some(region!("US")));
+assert_eq!(loc, locale!("en-GB"));
```
For more details, see [`Locale`] and [`LanguageIdentifier`].
diff --git a/vendor/icu_locid/benches/iai_langid.rs b/vendor/icu_locid/benches/iai_langid.rs
index f964d1462..bf3b911cf 100644
--- a/vendor/icu_locid/benches/iai_langid.rs
+++ b/vendor/icu_locid/benches/iai_langid.rs
@@ -5,6 +5,7 @@
use icu_locid::{
langid, subtags_language as language, subtags_region as region, LanguageIdentifier,
};
+use writeable::Writeable;
const LIDS: &[LanguageIdentifier] = &[
langid!("en"),
@@ -97,6 +98,12 @@ fn bench_langid_serialize() {
let _: Vec<String> = LIDS.iter().map(|l| l.to_string()).collect();
}
+fn bench_langid_serialize_writeable() {
+ // Tests serialization of LIDs.
+
+ let _: Vec<_> = LIDS.iter().map(|l| l.write_to_string()).collect();
+}
+
fn bench_langid_canonicalize() {
// Tests canonicalization of strings.
@@ -114,5 +121,6 @@ iai::main!(
bench_langid_matching,
bench_langid_matching_str,
bench_langid_serialize,
+ bench_langid_serialize_writeable,
bench_langid_canonicalize,
);
diff --git a/vendor/icu_locid/examples/filter_langids.rs b/vendor/icu_locid/examples/filter_langids.rs
index 9e5b54e39..215df4eb3 100644
--- a/vendor/icu_locid/examples/filter_langids.rs
+++ b/vendor/icu_locid/examples/filter_langids.rs
@@ -16,6 +16,7 @@ icu_benchmark_macros::static_setup!();
use std::env;
use icu_locid::{subtags, LanguageIdentifier};
+use writeable::Writeable;
const DEFAULT_INPUT: &str =
"de, en-us, zh-hant, sr-cyrl, fr-ca, es-cl, pl, en-latn-us, ca-valencia, und-arab";
@@ -30,7 +31,9 @@ fn filter_input(input: &str) -> String {
let en_langids = langids.filter(|langid: &LanguageIdentifier| langid.language == en_lang);
// 3. Serialize the output.
- let en_strs: Vec<String> = en_langids.map(|langid| langid.to_string()).collect();
+ let en_strs: Vec<String> = en_langids
+ .map(|langid| langid.write_to_string().into_owned())
+ .collect();
en_strs.join(", ")
}
diff --git a/vendor/icu_locid/src/extensions/mod.rs b/vendor/icu_locid/src/extensions/mod.rs
index 42bfcd3c9..a6a189b11 100644
--- a/vendor/icu_locid/src/extensions/mod.rs
+++ b/vendor/icu_locid/src/extensions/mod.rs
@@ -102,11 +102,11 @@ impl ExtensionType {
#[derive(Debug, Default, PartialEq, Eq, Clone, Hash)]
#[non_exhaustive]
pub struct Extensions {
- /// A representation of the data for a Unicode extension, when present in the locale identifer.
+ /// A representation of the data for a Unicode extension, when present in the locale identifier.
pub unicode: Unicode,
- /// A representation of the data for a transform extension, when present in the locale identifer.
+ /// A representation of the data for a transform extension, when present in the locale identifier.
pub transform: Transform,
- /// A representation of the data for a private-use extension, when present in the locale identifer.
+ /// A representation of the data for a private-use extension, when present in the locale identifier.
pub private: Private,
/// A sequence of any other extensions that are present in the locale identifier but are not formally
/// [defined](https://unicode.org/reports/tr35/) and represented explicitly as [`Unicode`], [`Transform`],
@@ -210,19 +210,33 @@ impl Extensions {
let mut private = None;
let mut other = Vec::new();
- let mut st = iter.next();
- while let Some(subtag) = st {
+ while let Some(subtag) = iter.next() {
+ if subtag.is_empty() {
+ return Err(ParserError::InvalidExtension);
+ }
match subtag.get(0).map(|b| ExtensionType::try_from_byte(*b)) {
Some(Ok(ExtensionType::Unicode)) => {
+ if unicode.is_some() {
+ return Err(ParserError::DuplicatedExtension);
+ }
unicode = Some(Unicode::try_from_iter(iter)?);
}
Some(Ok(ExtensionType::Transform)) => {
+ if transform.is_some() {
+ return Err(ParserError::DuplicatedExtension);
+ }
transform = Some(Transform::try_from_iter(iter)?);
}
Some(Ok(ExtensionType::Private)) => {
+ if private.is_some() {
+ return Err(ParserError::DuplicatedExtension);
+ }
private = Some(Private::try_from_iter(iter)?);
}
Some(Ok(ExtensionType::Other(ext))) => {
+ if other.iter().any(|o: &Other| o.get_ext_byte() == ext) {
+ return Err(ParserError::DuplicatedExtension);
+ }
let parsed = Other::try_from_iter(ext, iter)?;
if let Err(idx) = other.binary_search(&parsed) {
other.insert(idx, parsed);
@@ -230,11 +244,8 @@ impl Extensions {
return Err(ParserError::InvalidExtension);
}
}
- None => {}
_ => return Err(ParserError::InvalidExtension),
}
-
- st = iter.next();
}
Ok(Self {
@@ -283,7 +294,7 @@ impl_writeable_for_each_subtag_str_no_test!(Extensions);
fn test_writeable() {
use crate::Locale;
use writeable::assert_writeable_eq;
- assert_writeable_eq!(Extensions::new(), "",);
+ assert_writeable_eq!(Extensions::new(), "");
assert_writeable_eq!(
"my-t-my-d0-zawgyi".parse::<Locale>().unwrap().extensions,
"t-my-d0-zawgyi",
diff --git a/vendor/icu_locid/src/extensions/other/mod.rs b/vendor/icu_locid/src/extensions/other/mod.rs
index 36dbc49b6..44d5c9cf8 100644
--- a/vendor/icu_locid/src/extensions/other/mod.rs
+++ b/vendor/icu_locid/src/extensions/other/mod.rs
@@ -41,13 +41,16 @@ pub use subtag::Subtag;
/// let subtag2: Subtag = "bar".parse().expect("Failed to parse a Subtag.");
///
/// let other = Other::from_vec_unchecked(b'a', vec![subtag1, subtag2]);
-/// assert_eq!(&other.to_string(), "-a-foo-bar");
+/// assert_eq!(&other.to_string(), "a-foo-bar");
/// ```
///
/// [`Other Use Extensions`]: https://unicode.org/reports/tr35/#other_extensions
/// [`Unicode Locale Identifier`]: https://unicode.org/reports/tr35/#Unicode_locale_identifier
#[derive(Clone, PartialEq, Eq, Debug, Default, Hash, PartialOrd, Ord)]
-pub struct Other((u8, Vec<Subtag>));
+pub struct Other {
+ ext: u8,
+ keys: Vec<Subtag>,
+}
impl Other {
/// A constructor which takes a pre-sorted list of [`Subtag`].
@@ -65,11 +68,11 @@ impl Other {
/// let subtag2: Subtag = "bar".parse().expect("Failed to parse a Subtag.");
///
/// let other = Other::from_vec_unchecked(b'a', vec![subtag1, subtag2]);
- /// assert_eq!(&other.to_string(), "-a-foo-bar");
+ /// assert_eq!(&other.to_string(), "a-foo-bar");
/// ```
- pub fn from_vec_unchecked(ext: u8, input: Vec<Subtag>) -> Self {
+ pub fn from_vec_unchecked(ext: u8, keys: Vec<Subtag>) -> Self {
assert!(ext.is_ascii_alphabetic());
- Self((ext, input))
+ Self { ext, keys }
}
pub(crate) fn try_from_iter(ext: u8, iter: &mut SubtagIterator) -> Result<Self, ParserError> {
@@ -89,6 +92,22 @@ impl Other {
Ok(Self::from_vec_unchecked(ext, keys))
}
+ /// Gets the tag character for this extension as a &str.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use icu::locid::Locale;
+ ///
+ /// let loc: Locale = "und-a-hello-world".parse().unwrap();
+ /// let other_ext = &loc.extensions.other[0];
+ /// assert_eq!(other_ext.get_ext_str(), "a");
+ /// ```
+ pub fn get_ext_str(&self) -> &str {
+ debug_assert!(self.ext.is_ascii_alphabetic());
+ unsafe { core::str::from_utf8_unchecked(core::slice::from_ref(&self.ext)) }
+ }
+
/// Gets the tag character for this extension as a char.
///
/// # Examples
@@ -101,7 +120,7 @@ impl Other {
/// assert_eq!(other_ext.get_ext(), 'a');
/// ```
pub fn get_ext(&self) -> char {
- self.get_ext_byte() as char
+ self.ext as char
}
/// Gets the tag character for this extension as a byte.
@@ -116,19 +135,15 @@ impl Other {
/// assert_eq!(other_ext.get_ext_byte(), b'a');
/// ```
pub fn get_ext_byte(&self) -> u8 {
- self.0 .0
+ self.ext
}
pub(crate) fn for_each_subtag_str<E, F>(&self, f: &mut F) -> Result<(), E>
where
F: FnMut(&str) -> Result<(), E>,
{
- let (ext, keys) = &self.0;
- debug_assert!(ext.is_ascii_alphabetic());
- // Safety: ext is ascii_alphabetic, so it is valid UTF-8
- let ext_str = unsafe { core::str::from_utf8_unchecked(core::slice::from_ref(ext)) };
- f(ext_str)?;
- keys.iter().map(|t| t.as_str()).try_for_each(f)
+ f(self.get_ext_str())?;
+ self.keys.iter().map(|t| t.as_str()).try_for_each(f)
}
}
@@ -136,10 +151,8 @@ writeable::impl_display_with_writeable!(Other);
impl writeable::Writeable for Other {
fn write_to<W: core::fmt::Write + ?Sized>(&self, sink: &mut W) -> core::fmt::Result {
- let (ext, keys) = &self.0;
- sink.write_char('-')?;
- sink.write_char(*ext as char)?;
- for key in keys.iter() {
+ sink.write_str(self.get_ext_str())?;
+ for key in self.keys.iter() {
sink.write_char('-')?;
writeable::Writeable::write_to(key, sink)?;
}
@@ -148,10 +161,20 @@ impl writeable::Writeable for Other {
}
fn writeable_length_hint(&self) -> writeable::LengthHint {
- let mut result = writeable::LengthHint::exact(2);
- for key in self.0 .1.iter() {
+ let mut result = writeable::LengthHint::exact(1);
+ for key in self.keys.iter() {
result += writeable::Writeable::writeable_length_hint(key) + 1;
}
result
}
+
+ fn write_to_string(&self) -> alloc::borrow::Cow<str> {
+ if self.keys.is_empty() {
+ return alloc::borrow::Cow::Borrowed(self.get_ext_str());
+ }
+ let mut string =
+ alloc::string::String::with_capacity(self.writeable_length_hint().capacity());
+ let _ = self.write_to(&mut string);
+ alloc::borrow::Cow::Owned(string)
+ }
}
diff --git a/vendor/icu_locid/src/extensions/other/subtag.rs b/vendor/icu_locid/src/extensions/other/subtag.rs
index 60995c395..ad4d6a0f2 100644
--- a/vendor/icu_locid/src/extensions/other/subtag.rs
+++ b/vendor/icu_locid/src/extensions/other/subtag.rs
@@ -11,11 +11,9 @@ impl_tinystr_subtag!(
/// # Examples
///
/// ```
- /// use icu::locid::extensions::other::Subtag;
+ /// use icu::locid::extensions_other_subtag as subtag;
///
- /// let subtag: Subtag = "Foo".parse().expect("Failed to parse a Subtag.");
- ///
- /// assert_eq!(subtag.as_str(), "foo");
+ /// assert_eq!(subtag!("Foo").as_str(), "foo");
/// ```
Subtag,
extensions::other::Subtag,
diff --git a/vendor/icu_locid/src/extensions/private/mod.rs b/vendor/icu_locid/src/extensions/private/mod.rs
index 13090c94a..8382d166f 100644
--- a/vendor/icu_locid/src/extensions/private/mod.rs
+++ b/vendor/icu_locid/src/extensions/private/mod.rs
@@ -13,16 +13,18 @@
//! # Examples
//!
//! ```
-//! use icu::locid::extensions::private::{Private, Subtag};
-//! use icu::locid::Locale;
+//! use icu::locid::extensions_private_subtag as subtag;
+//! use icu::locid::{locale, Locale};
//!
//! let mut loc: Locale = "en-US-x-foo-faa".parse().expect("Parsing failed.");
//!
-//! let subtag: Subtag = "foo".parse().expect("Parsing subtag failed.");
-//! assert!(loc.extensions.private.contains(&subtag));
-//! assert_eq!(loc.extensions.private.iter().next(), Some(&subtag));
+//! assert!(loc.extensions.private.contains(&subtag!("foo")));
+//! assert_eq!(loc.extensions.private.iter().next(), Some(&subtag!("foo")));
+//!
//! loc.extensions.private.clear();
-//! assert_eq!(loc.to_string(), "en-US");
+//!
+//! assert!(loc.extensions.private.is_empty());
+//! assert_eq!(loc, locale!("en-US"));
//! ```
mod other;
@@ -50,7 +52,7 @@ use crate::parser::SubtagIterator;
/// let subtag2: Subtag = "bar".parse().expect("Failed to parse a Subtag.");
///
/// let private = Private::from_vec_unchecked(vec![subtag1, subtag2]);
-/// assert_eq!(&private.to_string(), "-x-foo-bar");
+/// assert_eq!(&private.to_string(), "x-foo-bar");
/// ```
///
/// [`Private Use Extensions`]: https://unicode.org/reports/tr35/#pu_extensions
@@ -84,7 +86,7 @@ impl Private {
/// let subtag2: Subtag = "bar".parse().expect("Failed to parse a Subtag.");
///
/// let private = Private::from_vec_unchecked(vec![subtag1, subtag2]);
- /// assert_eq!(&private.to_string(), "-x-foo-bar");
+ /// assert_eq!(&private.to_string(), "x-foo-bar");
/// ```
pub fn from_vec_unchecked(input: Vec<Subtag>) -> Self {
Self(input)
@@ -101,11 +103,11 @@ impl Private {
/// let subtag2: Subtag = "bar".parse().expect("Failed to parse a Subtag.");
/// let mut private = Private::from_vec_unchecked(vec![subtag1, subtag2]);
///
- /// assert_eq!(&private.to_string(), "-x-foo-bar");
+ /// assert_eq!(&private.to_string(), "x-foo-bar");
///
/// private.clear();
///
- /// assert_eq!(&private.to_string(), "");
+ /// assert_eq!(private, Private::new());
/// ```
pub fn clear(&mut self) {
self.0.clear();
@@ -138,7 +140,7 @@ impl writeable::Writeable for Private {
if self.is_empty() {
return Ok(());
}
- sink.write_str("-x")?;
+ sink.write_str("x")?;
for key in self.iter() {
sink.write_char('-')?;
writeable::Writeable::write_to(key, sink)?;
@@ -150,7 +152,7 @@ impl writeable::Writeable for Private {
if self.is_empty() {
return writeable::LengthHint::exact(0);
}
- let mut result = writeable::LengthHint::exact(2);
+ let mut result = writeable::LengthHint::exact(1);
for key in self.iter() {
result += writeable::Writeable::writeable_length_hint(key) + 1;
}
diff --git a/vendor/icu_locid/src/extensions/transform/fields.rs b/vendor/icu_locid/src/extensions/transform/fields.rs
index ca10000a7..f08581a87 100644
--- a/vendor/icu_locid/src/extensions/transform/fields.rs
+++ b/vendor/icu_locid/src/extensions/transform/fields.rs
@@ -25,10 +25,10 @@ use super::Value;
///
/// ```
/// use icu::locid::extensions::transform::{Fields, Key, Value};
+/// use icu::locid::extensions_transform_key as key;
///
-/// let key: Key = "h0".parse().expect("Failed to parse a Key.");
-/// let value: Value = "hybrid".parse().expect("Failed to parse a Value.");
-/// let fields: Fields = vec![(key, value)].into_iter().collect();
+/// let value = "hybrid".parse::<Value>().expect("Failed to parse a Value.");
+/// let fields = vec![(key!("h0"), value)].into_iter().collect::<Fields>();
///
/// assert_eq!(&fields.to_string(), "h0-hybrid");
/// ```
@@ -76,17 +76,17 @@ impl Fields {
/// # Examples
///
/// ```
- /// use icu::locid::extensions::transform::{Fields, Key, Value};
+ /// use icu::locid::extensions::transform::{Fields, Value};
+ /// use icu::locid::extensions_transform_key as key;
///
- /// let key: Key = "h0".parse().expect("Failed to parse a Key.");
- /// let value: Value = "hybrid".parse().expect("Failed to parse a Value.");
- /// let mut fields: Fields = vec![(key, value)].into_iter().collect();
+ /// let value = "hybrid".parse::<Value>().expect("Failed to parse a Value.");
+ /// let mut fields = vec![(key!("h0"), value)].into_iter().collect::<Fields>();
///
/// assert_eq!(&fields.to_string(), "h0-hybrid");
///
/// fields.clear();
///
- /// assert_eq!(&fields.to_string(), "");
+ /// assert_eq!(fields, Fields::new());
/// ```
pub fn clear(&mut self) -> Self {
core::mem::take(self)
@@ -122,16 +122,14 @@ impl Fields {
///
/// ```
/// use icu::locid::extensions::transform::{Fields, Key, Value};
+ /// use icu::locid::extensions_transform_key as key;
///
- /// let key: Key = "h0".parse().expect("Failed to parse a Key.");
- /// let value: Value = "hybrid".parse().expect("Failed to parse a Value.");
- /// let mut fields: Fields = vec![(key, value)].into_iter().collect();
+ /// let value = "hybrid".parse::<Value>().unwrap();
+ /// let fields = vec![(key!("h0"), value.clone())]
+ /// .into_iter()
+ /// .collect::<Fields>();
///
- /// let key: Key = "h0".parse().expect("Failed to parse a Key.");
- /// assert_eq!(
- /// fields.get(&key).map(|v| v.to_string()),
- /// Some("hybrid".to_string())
- /// );
+ /// assert_eq!(fields.get(&key!("h0")), Some(&value));
/// ```
pub fn get<Q>(&self, key: &Q) -> Option<&Value>
where
diff --git a/vendor/icu_locid/src/extensions/transform/mod.rs b/vendor/icu_locid/src/extensions/transform/mod.rs
index a8c605146..7b97d87f6 100644
--- a/vendor/icu_locid/src/extensions/transform/mod.rs
+++ b/vendor/icu_locid/src/extensions/transform/mod.rs
@@ -28,7 +28,7 @@
//! assert!(loc.extensions.transform.fields.contains_key(&key));
//! assert_eq!(loc.extensions.transform.fields.get(&key), Some(&value));
//!
-//! assert_eq!(&loc.extensions.transform.to_string(), "-t-es-AR-h0-hybrid");
+//! assert_eq!(&loc.extensions.transform.to_string(), "t-es-AR-h0-hybrid");
//! ```
mod fields;
mod key;
@@ -208,7 +208,7 @@ impl writeable::Writeable for Transform {
if self.is_empty() {
return Ok(());
}
- sink.write_str("-t")?;
+ sink.write_str("t")?;
if let Some(lang) = &self.lang {
sink.write_char('-')?;
writeable::Writeable::write_to(lang, sink)?;
@@ -224,7 +224,7 @@ impl writeable::Writeable for Transform {
if self.is_empty() {
return writeable::LengthHint::exact(0);
}
- let mut result = writeable::LengthHint::exact(2);
+ let mut result = writeable::LengthHint::exact(1);
if let Some(lang) = &self.lang {
result += writeable::Writeable::writeable_length_hint(lang) + 1;
}
diff --git a/vendor/icu_locid/src/extensions/transform/value.rs b/vendor/icu_locid/src/extensions/transform/value.rs
index 84468361a..f908b0208 100644
--- a/vendor/icu_locid/src/extensions/transform/value.rs
+++ b/vendor/icu_locid/src/extensions/transform/value.rs
@@ -2,7 +2,7 @@
// called LICENSE at the top level of the ICU4X source tree
// (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ).
-use crate::parser::{get_subtag_iterator, ParserError};
+use crate::parser::{ParserError, SubtagIterator};
use alloc::vec;
use alloc::vec::Vec;
use core::ops::RangeInclusive;
@@ -16,20 +16,18 @@ use tinystr::TinyAsciiStr;
/// Each part of the sequence has to be no shorter than three characters and no
/// longer than 8.
///
-///
/// # Examples
///
/// ```
/// use icu::locid::extensions::transform::Value;
///
-/// let value1: Value = "hybrid".parse().expect("Failed to parse a Value.");
-/// let value2: Value =
-/// "hybrid-foobar".parse().expect("Failed to parse a Value.");
+/// "hybrid".parse::<Value>().expect("Valid Value.");
+///
+/// "hybrid-foobar".parse::<Value>().expect("Valid Value.");
///
-/// assert_eq!(&value1.to_string(), "hybrid");
-/// assert_eq!(&value2.to_string(), "hybrid-foobar");
+/// "no".parse::<Value>().expect_err("Invalid Value.");
/// ```
-#[derive(Debug, PartialEq, Eq, Clone, Hash, PartialOrd, Ord)]
+#[derive(Debug, PartialEq, Eq, Clone, Hash, PartialOrd, Ord, Default)]
pub struct Value(Vec<TinyAsciiStr<{ *TYPE_LENGTH.end() }>>);
const TYPE_LENGTH: RangeInclusive<usize> = 3..=8;
@@ -45,14 +43,12 @@ impl Value {
/// use icu::locid::extensions::transform::Value;
///
/// let value = Value::try_from_bytes(b"hybrid").expect("Parsing failed.");
- ///
- /// assert_eq!(&value.to_string(), "hybrid");
/// ```
pub fn try_from_bytes(input: &[u8]) -> Result<Self, ParserError> {
let mut v = vec![];
let mut has_value = false;
- for subtag in get_subtag_iterator(input) {
+ for subtag in SubtagIterator::new(input) {
if !Self::is_type_subtag(subtag) {
return Err(ParserError::InvalidExtension);
}
@@ -116,4 +112,19 @@ impl FromStr for Value {
}
}
-impl_writeable_for_tinystr_list!(Value, "true", "hybrid", "foobar");
+impl_writeable_for_each_subtag_str_no_test!(Value, selff, selff.0.is_empty() => alloc::borrow::Cow::Borrowed("true"));
+
+#[test]
+fn test_writeable() {
+ use writeable::assert_writeable_eq;
+
+ let hybrid = "hybrid".parse().unwrap();
+ let foobar = "foobar".parse().unwrap();
+
+ assert_writeable_eq!(Value::default(), "true");
+ assert_writeable_eq!(Value::from_vec_unchecked(vec![hybrid]), "hybrid");
+ assert_writeable_eq!(
+ Value::from_vec_unchecked(vec![hybrid, foobar]),
+ "hybrid-foobar"
+ );
+}
diff --git a/vendor/icu_locid/src/extensions/unicode/attributes.rs b/vendor/icu_locid/src/extensions/unicode/attributes.rs
index 1f9536bfa..e58fb04da 100644
--- a/vendor/icu_locid/src/extensions/unicode/attributes.rs
+++ b/vendor/icu_locid/src/extensions/unicode/attributes.rs
@@ -79,18 +79,19 @@ impl Attributes {
///
/// ```
/// use icu::locid::extensions::unicode::{Attribute, Attributes};
+ /// use icu::locid::extensions_unicode_attribute as attribute;
+ /// use writeable::assert_writeable_eq;
///
- /// let attribute1: Attribute = "foobar".parse().expect("Parsing failed.");
- /// let attribute2: Attribute = "testing".parse().expect("Parsing failed.");
- /// let mut v = vec![attribute1, attribute2];
- ///
- /// let mut attributes: Attributes = Attributes::from_vec_unchecked(v);
+ /// let mut attributes = Attributes::from_vec_unchecked(vec![
+ /// attribute!("foobar"),
+ /// attribute!("testing"),
+ /// ]);
///
- /// assert_eq!(attributes.to_string(), "foobar-testing");
+ /// assert_writeable_eq!(attributes, "foobar-testing");
///
/// attributes.clear();
///
- /// assert_eq!(attributes.to_string(), "");
+ /// assert_writeable_eq!(attributes, "");
/// ```
pub fn clear(&mut self) -> Self {
core::mem::take(self)
diff --git a/vendor/icu_locid/src/extensions/unicode/keywords.rs b/vendor/icu_locid/src/extensions/unicode/keywords.rs
index dc9a15921..580cacaf1 100644
--- a/vendor/icu_locid/src/extensions/unicode/keywords.rs
+++ b/vendor/icu_locid/src/extensions/unicode/keywords.rs
@@ -29,11 +29,14 @@ use crate::ordering::SubtagOrderingResult;
/// Manually build up a [`Keywords`] object:
///
/// ```
-/// use icu::locid::extensions::unicode::{Key, Keywords, Value};
+/// use icu::locid::{
+/// extensions::unicode::Keywords, extensions_unicode_key as key,
+/// extensions_unicode_value as value, locale,
+/// };
///
-/// let key: Key = "hc".parse().expect("Failed to parse a Key.");
-/// let value: Value = "h23".parse().expect("Failed to parse a Value.");
-/// let keywords: Keywords = vec![(key, value)].into_iter().collect();
+/// let keywords = vec![(key!("hc"), value!("h23"))]
+/// .into_iter()
+/// .collect::<Keywords>();
///
/// assert_eq!(&keywords.to_string(), "hc-h23");
/// ```
@@ -113,15 +116,16 @@ impl Keywords {
/// # Examples
///
/// ```
- /// use icu::locid::extensions::unicode::{Key, Keywords, Value};
- /// use litemap::LiteMap;
+ /// use icu::locid::{
+ /// extensions::unicode::Keywords, extensions_unicode_key as key,
+ /// extensions_unicode_value as value,
+ /// };
///
- /// let key: Key = "ca".parse().expect("Failed to parse a Key.");
- /// let value: Value = "gregory".parse().expect("Failed to parse a Value.");
- /// let keywords: Keywords = vec![(key, value)].into_iter().collect();
+ /// let keywords = vec![(key!("ca"), value!("gregory"))]
+ /// .into_iter()
+ /// .collect::<Keywords>();
///
- /// let key: Key = "ca".parse().expect("Failed to parse a Key.");
- /// assert!(&keywords.contains_key(&key));
+ /// assert!(&keywords.contains_key(&key!("ca")));
/// ```
pub fn contains_key<Q>(&self, key: &Q) -> bool
where
@@ -137,17 +141,16 @@ impl Keywords {
/// # Examples
///
/// ```
- /// use icu::locid::extensions::unicode::{Key, Keywords, Value};
+ /// use icu::locid::{
+ /// extensions::unicode::Keywords, extensions_unicode_key as key,
+ /// extensions_unicode_value as value,
+ /// };
///
- /// let key: Key = "ca".parse().expect("Failed to parse a Key.");
- /// let value: Value = "buddhist".parse().expect("Failed to parse a Value.");
- /// let keywords: Keywords = vec![(key, value)].into_iter().collect();
+ /// let keywords = vec![(key!("ca"), value!("buddhist"))]
+ /// .into_iter()
+ /// .collect::<Keywords>();
///
- /// let key: Key = "ca".parse().expect("Failed to parse a Key.");
- /// assert_eq!(
- /// keywords.get(&key).map(|v| v.to_string()),
- /// Some("buddhist".to_string())
- /// );
+ /// assert_eq!(keywords.get(&key!("ca")), Some(&value!("buddhist")));
/// ```
pub fn get<Q>(&self, key: &Q) -> Option<&Value>
where
@@ -164,20 +167,19 @@ impl Keywords {
/// # Examples
///
/// ```
- /// use icu::locid::extensions::unicode::{Key, Keywords, Value};
+ /// use icu::locid::{
+ /// extensions::unicode::Keywords, extensions_unicode_key as key,
+ /// extensions_unicode_value as value,
+ /// };
///
- /// let key: Key = "ca".parse().expect("Failed to parse a Key.");
- /// let value: Value = "buddhist".parse().expect("Failed to parse a Value.");
- /// let mut keywords: Keywords = vec![(key, value)].into_iter().collect();
+ /// let mut keywords = vec![(key!("ca"), value!("buddhist"))]
+ /// .into_iter()
+ /// .collect::<Keywords>();
///
- /// let key: Key = "ca".parse().expect("Failed to parse a Key.");
- /// if let Some(value) = keywords.get_mut(&key) {
- /// *value = "gregory".parse().expect("Failed to parse a Value.");
+ /// if let Some(value) = keywords.get_mut(&key!("ca")) {
+ /// *value = value!("gregory");
/// }
- /// assert_eq!(
- /// keywords.get(&key).map(|v| v.to_string()),
- /// Some("gregory".to_string())
- /// );
+ /// assert_eq!(keywords.get(&key!("ca")), Some(&value!("gregory")));
/// ```
pub fn get_mut<Q>(&mut self, key: &Q) -> Option<&mut Value>
where
@@ -308,7 +310,6 @@ impl Keywords {
/// .extensions
/// .unicode
/// .keywords;
- /// assert_eq!(a, a_kwds.to_string());
/// assert!(a_kwds.strict_cmp(a.as_bytes()) == Ordering::Equal);
/// assert!(a_kwds.strict_cmp(b.as_bytes()) == Ordering::Less);
/// }
diff --git a/vendor/icu_locid/src/extensions/unicode/mod.rs b/vendor/icu_locid/src/extensions/unicode/mod.rs
index fabf1036c..687a8c383 100644
--- a/vendor/icu_locid/src/extensions/unicode/mod.rs
+++ b/vendor/icu_locid/src/extensions/unicode/mod.rs
@@ -11,21 +11,24 @@
//! # Examples
//!
//! ```
-//! use icu::locid::extensions::unicode::{Attribute, Key, Unicode, Value};
-//! use icu::locid::{LanguageIdentifier, Locale};
+//! use icu::locid::Locale;
+//! use icu::locid::{
+//! extensions::unicode::Unicode,
+//! extensions_unicode_attribute as attribute,
+//! extensions_unicode_key as key, extensions_unicode_value as value,
+//! };
//!
-//! let mut loc: Locale =
-//! "en-US-u-foobar-hc-h12".parse().expect("Parsing failed.");
+//! let loc: Locale = "en-US-u-foobar-hc-h12".parse().expect("Parsing failed.");
//!
-//! let key: Key = "hc".parse().expect("Parsing key failed.");
-//! let value: Value = "h12".parse().expect("Parsing value failed.");
-//! let attribute: Attribute =
-//! "foobar".parse().expect("Parsing attribute failed.");
-//!
-//! assert_eq!(loc.extensions.unicode.keywords.get(&key), Some(&value));
-//! assert!(loc.extensions.unicode.attributes.contains(&attribute));
-//!
-//! assert_eq!(&loc.extensions.unicode.to_string(), "-u-foobar-hc-h12");
+//! assert_eq!(
+//! loc.extensions.unicode.keywords.get(&key!("hc")),
+//! Some(&value!("h12"))
+//! );
+//! assert!(loc
+//! .extensions
+//! .unicode
+//! .attributes
+//! .contains(&attribute!("foobar")));
//! ```
mod attribute;
mod attributes;
@@ -60,15 +63,18 @@ use litemap::LiteMap;
/// # Examples
///
/// ```
-/// use icu::locid::extensions::unicode::{Key, Value};
/// use icu::locid::Locale;
+/// use icu::locid::{
+/// extensions_unicode_key as key, extensions_unicode_value as value,
+/// };
///
-/// let mut loc: Locale =
+/// let loc: Locale =
/// "de-u-hc-h12-ca-buddhist".parse().expect("Parsing failed.");
///
-/// let key: Key = "ca".parse().expect("Parsing key failed.");
-/// let value: Value = "buddhist".parse().expect("Parsing value failed.");
-/// assert_eq!(loc.extensions.unicode.keywords.get(&key), Some(&value));
+/// assert_eq!(
+/// loc.extensions.unicode.keywords.get(&key!("ca")),
+/// Some(&value!("buddhist"))
+/// );
/// ```
#[derive(Clone, PartialEq, Eq, Debug, Default, Hash, PartialOrd, Ord)]
#[allow(clippy::exhaustive_structs)] // spec-backed stable datastructure
@@ -205,7 +211,7 @@ impl writeable::Writeable for Unicode {
if self.is_empty() {
return Ok(());
}
- sink.write_str("-u")?;
+ sink.write_str("u")?;
if !self.attributes.is_empty() {
sink.write_char('-')?;
writeable::Writeable::write_to(&self.attributes, sink)?;
@@ -221,7 +227,7 @@ impl writeable::Writeable for Unicode {
if self.is_empty() {
return writeable::LengthHint::exact(0);
}
- let mut result = writeable::LengthHint::exact(2);
+ let mut result = writeable::LengthHint::exact(1);
if !self.attributes.is_empty() {
result += writeable::Writeable::writeable_length_hint(&self.attributes) + 1;
}
diff --git a/vendor/icu_locid/src/extensions/unicode/value.rs b/vendor/icu_locid/src/extensions/unicode/value.rs
index ce9982a4c..e6374372c 100644
--- a/vendor/icu_locid/src/extensions/unicode/value.rs
+++ b/vendor/icu_locid/src/extensions/unicode/value.rs
@@ -3,7 +3,7 @@
// (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ).
use crate::helpers::ShortVec;
-use crate::parser::{get_subtag_iterator, ParserError};
+use crate::parser::{ParserError, SubtagIterator};
use alloc::vec::Vec;
use core::ops::RangeInclusive;
use core::str::FromStr;
@@ -20,20 +20,21 @@ use tinystr::TinyAsciiStr;
/// # Examples
///
/// ```
-/// use icu::locid::extensions::unicode::Value;
-///
-/// let value1: Value = "gregory".parse().expect("Failed to parse a Value.");
-/// let value2: Value =
-/// "islamic-civil".parse().expect("Failed to parse a Value.");
-/// let value3: Value = "true".parse().expect("Failed to parse a Value.");
+/// use icu::locid::{
+/// extensions::unicode::Value, extensions_unicode_value as value,
+/// };
+/// use writeable::assert_writeable_eq;
///
-/// assert_eq!(&value1.to_string(), "gregory");
-/// assert_eq!(&value2.to_string(), "islamic-civil");
+/// assert_writeable_eq!(value!("gregory"), "gregory");
+/// assert_writeable_eq!(
+/// "islamic-civil".parse::<Value>().unwrap(),
+/// "islamic-civil"
+/// );
///
-/// // The value "true" is special-cased to an empty value
-/// assert_eq!(&value3.to_string(), "");
+/// // The value "true" has the special, empty string representation
+/// assert_eq!(value!("true").to_string(), "");
/// ```
-#[derive(Debug, PartialEq, Eq, Clone, Hash, PartialOrd, Ord)]
+#[derive(Debug, PartialEq, Eq, Clone, Hash, PartialOrd, Ord, Default)]
pub struct Value(ShortVec<TinyAsciiStr<{ *VALUE_LENGTH.end() }>>);
const VALUE_LENGTH: RangeInclusive<usize> = 3..=8;
@@ -48,15 +49,13 @@ impl Value {
/// ```
/// use icu::locid::extensions::unicode::Value;
///
- /// let value = Value::try_from_bytes(b"buddhist").expect("Parsing failed.");
- ///
- /// assert_eq!(&value.to_string(), "buddhist");
+ /// Value::try_from_bytes(b"buddhist").expect("Parsing failed.");
/// ```
pub fn try_from_bytes(input: &[u8]) -> Result<Self, ParserError> {
let mut v = ShortVec::new();
if !input.is_empty() {
- for subtag in get_subtag_iterator(input) {
+ for subtag in SubtagIterator::new(input) {
let val = Self::subtag_from_bytes(subtag)?;
if let Some(val) = val {
v.push(val);
@@ -153,7 +152,7 @@ impl FromStr for Value {
}
}
-impl_writeable_for_tinystr_list!(Value, "", "islamic", "civil");
+impl_writeable_for_subtag_list!(Value, "islamic", "civil");
/// A macro allowing for compile-time construction of valid Unicode [`Value`] subtag.
///
diff --git a/vendor/icu_locid/src/helpers.rs b/vendor/icu_locid/src/helpers.rs
index e617ded5d..e5889a7b0 100644
--- a/vendor/icu_locid/src/helpers.rs
+++ b/vendor/icu_locid/src/helpers.rs
@@ -115,7 +115,7 @@ impl<T> ShortVec<T> {
#[allow(clippy::unwrap_used)]
// we know that the vec has exactly one element left
1 => (ShortVec::Single(v.pop().unwrap()), removed_item),
- // v has atleast 2 elements, create a Multi variant
+ // v has at least 2 elements, create a Multi variant
_ => (ShortVec::Multi(v), removed_item),
}
}
@@ -387,6 +387,7 @@ macro_rules! impl_tinystr_subtag {
}
impl writeable::Writeable for $name {
+ #[inline]
fn write_to<W: core::fmt::Write + ?Sized>(&self, sink: &mut W) -> core::fmt::Result {
sink.write_str(self.as_str())
}
@@ -394,6 +395,10 @@ macro_rules! impl_tinystr_subtag {
fn writeable_length_hint(&self) -> writeable::LengthHint {
writeable::LengthHint::exact(self.0.len())
}
+ #[inline]
+ fn write_to_string(&self) -> alloc::borrow::Cow<str> {
+ alloc::borrow::Cow::Borrowed(self.0.as_str())
+ }
}
writeable::impl_display_with_writeable!($name);
@@ -546,7 +551,7 @@ macro_rules! impl_tinystr_subtag {
}
macro_rules! impl_writeable_for_each_subtag_str_no_test {
- ($type:tt) => {
+ ($type:tt $(, $self:ident, $borrow_cond:expr => $borrow:expr)?) => {
impl writeable::Writeable for $type {
fn write_to<W: core::fmt::Write + ?Sized>(&self, sink: &mut W) -> core::fmt::Result {
let mut initial = true;
@@ -576,6 +581,20 @@ macro_rules! impl_writeable_for_each_subtag_str_no_test {
.expect("infallible");
result
}
+
+ $(
+ fn write_to_string(&self) -> alloc::borrow::Cow<str> {
+ #[allow(clippy::unwrap_used)] // impl_writeable_for_subtag_list's $borrow uses unwrap
+ let $self = self;
+ if $borrow_cond {
+ $borrow
+ } else {
+ let mut output = alloc::string::String::with_capacity(self.writeable_length_hint().capacity());
+ let _ = self.write_to(&mut output);
+ alloc::borrow::Cow::Owned(output)
+ }
+ }
+ )?
}
writeable::impl_display_with_writeable!($type);
@@ -584,7 +603,7 @@ macro_rules! impl_writeable_for_each_subtag_str_no_test {
macro_rules! impl_writeable_for_subtag_list {
($type:tt, $sample1:literal, $sample2:literal) => {
- impl_writeable_for_each_subtag_str_no_test!($type);
+ impl_writeable_for_each_subtag_str_no_test!($type, selff, selff.0.len() == 1 => alloc::borrow::Cow::Borrowed(selff.0.as_slice().get(0).unwrap().as_str()));
#[test]
fn test_writeable() {
@@ -594,27 +613,6 @@ macro_rules! impl_writeable_for_subtag_list {
$sample1,
);
writeable::assert_writeable_eq!(
- &$type::from_vec_unchecked(alloc::vec![
- $sample1.parse().unwrap(),
- $sample2.parse().unwrap()
- ]),
- core::concat!($sample1, "-", $sample2),
- );
- }
- };
-}
-
-macro_rules! impl_writeable_for_tinystr_list {
- ($type:tt, $if_empty:literal, $sample1:literal, $sample2:literal) => {
- impl_writeable_for_each_subtag_str_no_test!($type);
-
- #[test]
- fn test_writeable() {
- writeable::assert_writeable_eq!(
- &$type::from_vec_unchecked(vec![$sample1.parse().unwrap()]),
- $sample1,
- );
- writeable::assert_writeable_eq!(
&$type::from_vec_unchecked(vec![
$sample1.parse().unwrap(),
$sample2.parse().unwrap()
diff --git a/vendor/icu_locid/src/langid.rs b/vendor/icu_locid/src/langid.rs
index fc5435766..b6858c91b 100644
--- a/vendor/icu_locid/src/langid.rs
+++ b/vendor/icu_locid/src/langid.rs
@@ -7,27 +7,28 @@ use core::str::FromStr;
use crate::ordering::SubtagOrderingResult;
use crate::parser::{
- get_subtag_iterator, parse_language_identifier, parse_language_identifier_with_single_variant,
- ParserError, ParserMode,
+ parse_language_identifier, parse_language_identifier_with_single_variant, ParserError,
+ ParserMode, SubtagIterator,
};
use crate::subtags;
use alloc::string::String;
-use alloc::string::ToString;
+use writeable::Writeable;
/// A core struct representing a [`Unicode BCP47 Language Identifier`].
///
/// # Examples
///
/// ```
-/// use icu::locid::{subtags::*, LanguageIdentifier};
+/// use icu::locid::{
+/// langid, subtags_language as language, subtags_region as region,
+/// };
///
-/// let li: LanguageIdentifier = "en-US".parse().expect("Failed to parse.");
+/// let li = langid!("en-US");
///
-/// assert_eq!(li.language, "en".parse::<Language>().unwrap());
+/// assert_eq!(li.language, language!("en"));
/// assert_eq!(li.script, None);
-/// assert_eq!(li.region.unwrap(), "US".parse::<Region>().unwrap());
+/// assert_eq!(li.region, Some(region!("US")));
/// assert_eq!(li.variants.len(), 0);
-/// assert_eq!(li.to_string(), "en-US");
/// ```
///
/// # Parsing
@@ -47,18 +48,17 @@ use alloc::string::ToString;
/// # Examples
///
/// ```
-/// use icu::locid::{subtags::*, LanguageIdentifier};
+/// use icu::locid::{
+/// langid, subtags_language as language, subtags_region as region,
+/// subtags_script as script, subtags_variant as variant,
+/// };
///
-/// let li: LanguageIdentifier =
-/// "eN_latn_Us-Valencia".parse().expect("Failed to parse.");
+/// let li = langid!("eN_latn_Us-Valencia");
///
-/// assert_eq!(li.language, "en".parse::<Language>().unwrap());
-/// assert_eq!(li.script, "Latn".parse::<Script>().ok());
-/// assert_eq!(li.region, "US".parse::<Region>().ok());
-/// assert_eq!(
-/// li.variants.get(0),
-/// "valencia".parse::<Variant>().ok().as_ref()
-/// );
+/// assert_eq!(li.language, language!("en"));
+/// assert_eq!(li.script, Some(script!("Latn")));
+/// assert_eq!(li.region, Some(region!("US")));
+/// assert_eq!(li.variants.get(0), Some(&variant!("valencia")));
/// ```
///
/// [`Unicode BCP47 Language Identifier`]: https://unicode.org/reports/tr35/tr35.html#Unicode_language_identifier
@@ -84,10 +84,7 @@ impl LanguageIdentifier {
/// ```
/// use icu::locid::LanguageIdentifier;
///
- /// let li =
- /// LanguageIdentifier::try_from_bytes(b"en-US").expect("Parsing failed.");
- ///
- /// assert_eq!(li.to_string(), "en-US");
+ /// LanguageIdentifier::try_from_bytes(b"en-US").expect("Parsing failed");
/// ```
pub fn try_from_bytes(v: &[u8]) -> Result<Self, ParserError> {
parse_language_identifier(v, ParserMode::LanguageIdentifier)
@@ -117,12 +114,12 @@ impl LanguageIdentifier {
/// # Examples
///
/// ```
- /// use icu::locid::LanguageIdentifier;
+ /// use icu::locid::{langid, LanguageIdentifier};
///
/// let li = LanguageIdentifier::try_from_locale_bytes(b"en-US-x-posix")
/// .expect("Parsing failed.");
///
- /// assert_eq!(li.to_string(), "en-US");
+ /// assert_eq!(li, langid!("en-US"));
/// ```
///
/// This method should be used for input that may be a locale identifier.
@@ -139,7 +136,6 @@ impl LanguageIdentifier {
/// use icu::locid::LanguageIdentifier;
///
/// assert_eq!(LanguageIdentifier::default(), LanguageIdentifier::UND);
- /// assert_eq!("und", LanguageIdentifier::UND.to_string());
/// ```
pub const UND: Self = Self {
language: subtags::Language::UND,
@@ -159,13 +155,13 @@ impl LanguageIdentifier {
/// use icu::locid::LanguageIdentifier;
///
/// assert_eq!(
- /// LanguageIdentifier::canonicalize("pL_latn_pl"),
- /// Ok("pl-Latn-PL".to_string())
+ /// LanguageIdentifier::canonicalize("pL_latn_pl").as_deref(),
+ /// Ok("pl-Latn-PL")
/// );
/// ```
pub fn canonicalize<S: AsRef<[u8]>>(input: S) -> Result<String, ParserError> {
let lang_id = Self::try_from_bytes(input.as_ref())?;
- Ok(lang_id.to_string())
+ Ok(lang_id.write_to_string().into_owned())
}
/// Compare this [`LanguageIdentifier`] with BCP-47 bytes.
@@ -197,7 +193,6 @@ impl LanguageIdentifier {
/// let b = ab[1];
/// assert!(a.cmp(b) == Ordering::Less);
/// let a_langid = a.parse::<LanguageIdentifier>().unwrap();
- /// assert_eq!(a, a_langid.to_string());
/// assert!(a_langid.strict_cmp(a.as_bytes()) == Ordering::Equal);
/// assert!(a_langid.strict_cmp(b.as_bytes()) == Ordering::Less);
/// }
@@ -293,7 +288,7 @@ impl LanguageIdentifier {
};
}
- let mut iter = get_subtag_iterator(other.as_bytes());
+ let mut iter = SubtagIterator::new(other.as_bytes());
if !subtag_matches!(subtags::Language, iter, self.language) {
return false;
}
@@ -359,7 +354,7 @@ impl FromStr for LanguageIdentifier {
}
}
-impl_writeable_for_each_subtag_str_no_test!(LanguageIdentifier);
+impl_writeable_for_each_subtag_str_no_test!(LanguageIdentifier, selff, selff.script.is_none() && selff.region.is_none() && selff.variants.is_empty() => selff.language.write_to_string());
#[test]
fn test_writeable() {
@@ -387,14 +382,11 @@ fn test_writeable() {
/// # Examples
///
/// ```
-/// use icu::locid::subtags_language as language;
-/// use icu::locid::LanguageIdentifier;
-///
-/// let language = language!("en");
-/// let li = LanguageIdentifier::from(language);
+/// use icu::locid::{
+/// langid, subtags_language as language, LanguageIdentifier,
+/// };
///
-/// assert_eq!(li.language, language);
-/// assert_eq!(li.to_string(), "en");
+/// assert_eq!(LanguageIdentifier::from(language!("en")), langid!("en"));
/// ```
impl From<subtags::Language> for LanguageIdentifier {
fn from(language: subtags::Language) -> Self {
@@ -408,14 +400,12 @@ impl From<subtags::Language> for LanguageIdentifier {
/// # Examples
///
/// ```
-/// use icu::locid::subtags_script as script;
-/// use icu::locid::LanguageIdentifier;
+/// use icu::locid::{langid, subtags_script as script, LanguageIdentifier};
///
-/// let script = script!("latn");
-/// let li = LanguageIdentifier::from(Some(script));
-///
-/// assert_eq!(li.script.unwrap(), script);
-/// assert_eq!(li.to_string(), "und-Latn");
+/// assert_eq!(
+/// LanguageIdentifier::from(Some(script!("latn"))),
+/// langid!("und-Latn")
+/// );
/// ```
impl From<Option<subtags::Script>> for LanguageIdentifier {
fn from(script: Option<subtags::Script>) -> Self {
@@ -429,14 +419,12 @@ impl From<Option<subtags::Script>> for LanguageIdentifier {
/// # Examples
///
/// ```
-/// use icu::locid::subtags_region as region;
-/// use icu::locid::LanguageIdentifier;
+/// use icu::locid::{langid, subtags_region as region, LanguageIdentifier};
///
-/// let region = region!("US");
-/// let li = LanguageIdentifier::from(Some(region));
-///
-/// assert_eq!(li.region.unwrap(), region);
-/// assert_eq!(li.to_string(), "und-US");
+/// assert_eq!(
+/// LanguageIdentifier::from(Some(region!("US"))),
+/// langid!("und-US")
+/// );
/// ```
impl From<Option<subtags::Region>> for LanguageIdentifier {
fn from(region: Option<subtags::Region>) -> Self {
@@ -452,22 +440,18 @@ impl From<Option<subtags::Region>> for LanguageIdentifier {
/// # Examples
///
/// ```
-/// use icu::locid::LanguageIdentifier;
/// use icu::locid::{
-/// subtags_language as language, subtags_region as region,
-/// subtags_script as script,
+/// langid, subtags_language as language, subtags_region as region,
+/// subtags_script as script, LanguageIdentifier,
/// };
///
/// let lang = language!("en");
/// let script = script!("Latn");
/// let region = region!("US");
-/// let li = LanguageIdentifier::from((lang, Some(script), Some(region)));
-///
-/// assert_eq!(li.language, lang);
-/// assert_eq!(li.script.unwrap(), script);
-/// assert_eq!(li.region.unwrap(), region);
-/// assert_eq!(li.variants.len(), 0);
-/// assert_eq!(li.to_string(), "en-Latn-US");
+/// assert_eq!(
+/// LanguageIdentifier::from((lang, Some(script), Some(region))),
+/// langid!("en-Latn-US")
+/// );
/// ```
impl
From<(
@@ -497,7 +481,6 @@ impl
/// # Examples
///
/// ```
-/// use icu::locid::LanguageIdentifier;
/// use icu::locid::{
/// langid, subtags_language as language, subtags_region as region,
/// subtags_script as script,
diff --git a/vendor/icu_locid/src/lib.rs b/vendor/icu_locid/src/lib.rs
index 885c4b743..226a8e53c 100644
--- a/vendor/icu_locid/src/lib.rs
+++ b/vendor/icu_locid/src/lib.rs
@@ -22,39 +22,23 @@
//! # Examples
//!
//! ```
-//! use icu::locid::subtags::{Language, Region};
//! use icu::locid::Locale;
+//! use icu::locid::{
+//! locale, subtags_language as language, subtags_region as region,
+//! };
//!
-//! let mut loc: Locale = "en-US".parse().expect("Parsing failed.");
-//!
-//! let lang: Language = "en".parse().expect("Parsing failed.");
-//! let region: Region = "US".parse().expect("Parsing failed.");
+//! let mut loc: Locale = locale!("en-US");
//!
-//! assert_eq!(loc.id.language, lang);
+//! assert_eq!(loc.id.language, language!("en"));
//! assert_eq!(loc.id.script, None);
-//! assert_eq!(loc.id.region, Some(region));
+//! assert_eq!(loc.id.region, Some(region!("US")));
//! assert_eq!(loc.id.variants.len(), 0);
//!
-//! let region: Region = "GB".parse().expect("Parsing failed.");
-//! loc.id.region = Some(region);
+//! loc.id.region = Some(region!("GB"));
//!
-//! assert_eq!(loc.to_string(), "en-GB");
+//! assert_eq!(loc, locale!("en-GB"));
//! ```
//!
-//! ## Macros
-//!
-//! ```rust
-//! use icu::locid::{
-//! langid, subtags_language as language, subtags_region as region,
-//! };
-//!
-//! let lid = langid!("EN_US");
-//!
-//! assert_eq!(lid.language, language!("en"));
-//! assert_eq!(lid.region, Some(region!("US")));
-//! ```
-
-//!
//! For more details, see [`Locale`] and [`LanguageIdentifier`].
//!
//! [`UTS #35: Unicode LDML 3. Unicode Language and Locale Identifiers`]: https://unicode.org/reports/tr35/tr35.html#Unicode_Language_and_Locale_Identifiers
diff --git a/vendor/icu_locid/src/locale.rs b/vendor/icu_locid/src/locale.rs
index d7040d31a..5d9109fee 100644
--- a/vendor/icu_locid/src/locale.rs
+++ b/vendor/icu_locid/src/locale.rs
@@ -4,16 +4,15 @@
use crate::ordering::SubtagOrderingResult;
use crate::parser::{
- get_subtag_iterator, parse_locale,
- parse_locale_with_single_variant_single_keyword_unicode_keyword_extension, ParserError,
- ParserMode,
+ parse_locale, parse_locale_with_single_variant_single_keyword_unicode_keyword_extension,
+ ParserError, ParserMode, SubtagIterator,
};
use crate::{extensions, subtags, LanguageIdentifier};
use alloc::string::String;
-use alloc::string::ToString;
use core::cmp::Ordering;
use core::str::FromStr;
use tinystr::TinyAsciiStr;
+use writeable::Writeable;
/// A core struct representing a [`Unicode Locale Identifier`].
///
@@ -28,20 +27,21 @@ use tinystr::TinyAsciiStr;
/// # Examples
///
/// ```
-/// use icu::locid::extensions::unicode::{Key, Value};
-/// use icu::locid::{subtags::*, Locale};
+/// use icu_locid::{
+/// extensions_unicode_key as key, extensions_unicode_value as value,
+/// locale, subtags_language as language, subtags_region as region,
+/// };
///
-/// let loc: Locale = "en-US-u-ca-buddhist".parse().expect("Failed to parse.");
+/// let loc = locale!("en-US-u-ca-buddhist");
///
-/// assert_eq!(loc.id.language, "en".parse::<Language>().unwrap());
+/// assert_eq!(loc.id.language, language!("en"));
/// assert_eq!(loc.id.script, None);
-/// assert_eq!(loc.id.region, "US".parse::<Region>().ok());
+/// assert_eq!(loc.id.region, Some(region!("US")));
/// assert_eq!(loc.id.variants.len(), 0);
-/// assert_eq!(loc.to_string(), "en-US-u-ca-buddhist");
-///
-/// let key: Key = "ca".parse().expect("Parsing key failed.");
-/// let value: Value = "buddhist".parse().expect("Parsing value failed.");
-/// assert_eq!(loc.extensions.unicode.keywords.get(&key), Some(&value));
+/// assert_eq!(
+/// loc.extensions.unicode.keywords.get(&key!("ca")),
+/// Some(&value!("buddhist"))
+/// );
/// ```
///
/// # Parsing
@@ -87,6 +87,8 @@ pub struct Locale {
#[test]
fn test_sizes() {
+ // Remove when we upgrade to a compiler where the new sizes are default
+ let forced_nightly = std::env::var("ICU4X_BUILDING_WITH_FORCED_NIGHTLY").is_ok();
assert_eq!(core::mem::size_of::<subtags::Language>(), 3);
assert_eq!(core::mem::size_of::<subtags::Script>(), 4);
assert_eq!(core::mem::size_of::<subtags::Region>(), 3);
@@ -99,12 +101,21 @@ fn test_sizes() {
assert_eq!(core::mem::size_of::<extensions::transform::Fields>(), 24);
assert_eq!(core::mem::size_of::<extensions::unicode::Attributes>(), 24);
- assert_eq!(core::mem::size_of::<extensions::unicode::Keywords>(), 48);
+ assert_eq!(
+ core::mem::size_of::<extensions::unicode::Keywords>(),
+ if forced_nightly { 40 } else { 48 }
+ );
assert_eq!(core::mem::size_of::<Vec<extensions::other::Other>>(), 24);
assert_eq!(core::mem::size_of::<extensions::private::Private>(), 24);
- assert_eq!(core::mem::size_of::<extensions::Extensions>(), 192);
+ assert_eq!(
+ core::mem::size_of::<extensions::Extensions>(),
+ if forced_nightly { 184 } else { 192 }
+ );
- assert_eq!(core::mem::size_of::<Locale>(), 240);
+ assert_eq!(
+ core::mem::size_of::<Locale>(),
+ if forced_nightly { 232 } else { 240 }
+ );
}
impl Locale {
@@ -116,10 +127,7 @@ impl Locale {
/// ```
/// use icu::locid::Locale;
///
- /// let loc = Locale::try_from_bytes("en-US-u-hc-h12".as_bytes())
- /// .expect("Parsing failed.");
- ///
- /// assert_eq!(loc.to_string(), "en-US-u-hc-h12");
+ /// Locale::try_from_bytes(b"en-US-u-hc-h12").unwrap();
/// ```
pub fn try_from_bytes(v: &[u8]) -> Result<Self, ParserError> {
parse_locale(v)
@@ -133,7 +141,6 @@ impl Locale {
/// use icu::locid::Locale;
///
/// assert_eq!(Locale::default(), Locale::UND);
- /// assert_eq!("und", Locale::UND.to_string());
/// ```
pub const UND: Self = Self {
id: LanguageIdentifier::UND,
@@ -151,13 +158,13 @@ impl Locale {
/// use icu::locid::Locale;
///
/// assert_eq!(
- /// Locale::canonicalize("pL_latn_pl-U-HC-H12"),
- /// Ok("pl-Latn-PL-u-hc-h12".to_string())
+ /// Locale::canonicalize("pL_latn_pl-U-HC-H12").as_deref(),
+ /// Ok("pl-Latn-PL-u-hc-h12")
/// );
/// ```
pub fn canonicalize<S: AsRef<[u8]>>(input: S) -> Result<String, ParserError> {
let locale = Self::try_from_bytes(input.as_ref())?;
- Ok(locale.to_string())
+ Ok(locale.write_to_string().into_owned())
}
/// Compare this [`Locale`] with BCP-47 bytes.
@@ -189,7 +196,6 @@ impl Locale {
/// let b = ab[1];
/// assert!(a.cmp(b) == Ordering::Less);
/// let a_loc = a.parse::<Locale>().unwrap();
- /// assert_eq!(a, a_loc.to_string());
/// assert!(a_loc.strict_cmp(a.as_bytes()) == Ordering::Equal);
/// assert!(a_loc.strict_cmp(b.as_bytes()) == Ordering::Less);
/// }
@@ -286,7 +292,7 @@ impl Locale {
};
}
- let mut iter = get_subtag_iterator(other.as_bytes());
+ let mut iter = SubtagIterator::new(other.as_bytes());
if !subtag_matches!(subtags::Language, iter, self.id.language) {
return false;
}
@@ -391,7 +397,7 @@ impl core::fmt::Debug for Locale {
}
}
-impl_writeable_for_each_subtag_str_no_test!(Locale);
+impl_writeable_for_each_subtag_str_no_test!(Locale, selff, selff.extensions.is_empty() => selff.id.write_to_string());
#[test]
fn test_writeable() {
@@ -426,14 +432,10 @@ fn test_writeable() {
/// # Examples
///
/// ```
-/// use icu::locid::subtags_language as language;
/// use icu::locid::Locale;
+/// use icu::locid::{locale, subtags_language as language};
///
-/// let language = language!("en");
-/// let loc = Locale::from(language);
-///
-/// assert_eq!(loc.id.language, language);
-/// assert_eq!(loc.to_string(), "en");
+/// assert_eq!(Locale::from(language!("en")), locale!("en"));
/// ```
impl From<subtags::Language> for Locale {
fn from(language: subtags::Language) -> Self {
@@ -447,14 +449,10 @@ impl From<subtags::Language> for Locale {
/// # Examples
///
/// ```
-/// use icu::locid::subtags_script as script;
/// use icu::locid::Locale;
+/// use icu::locid::{locale, subtags_script as script};
///
-/// let script = script!("latn");
-/// let loc = Locale::from(Some(script));
-///
-/// assert_eq!(loc.id.script.unwrap(), script);
-/// assert_eq!(loc.to_string(), "und-Latn");
+/// assert_eq!(Locale::from(Some(script!("latn"))), locale!("und-Latn"));
/// ```
impl From<Option<subtags::Script>> for Locale {
fn from(script: Option<subtags::Script>) -> Self {
@@ -468,14 +466,10 @@ impl From<Option<subtags::Script>> for Locale {
/// # Examples
///
/// ```
-/// use icu::locid::subtags_region as region;
/// use icu::locid::Locale;
+/// use icu::locid::{locale, subtags_region as region};
///
-/// let region = region!("US");
-/// let loc = Locale::from(Some(region));
-///
-/// assert_eq!(loc.id.region.unwrap(), region);
-/// assert_eq!(loc.to_string(), "und-US");
+/// assert_eq!(Locale::from(Some(region!("US"))), locale!("und-US"));
/// ```
impl From<Option<subtags::Region>> for Locale {
fn from(region: Option<subtags::Region>) -> Self {
@@ -491,20 +485,18 @@ impl From<Option<subtags::Region>> for Locale {
/// ```
/// use icu::locid::Locale;
/// use icu::locid::{
-/// subtags_language as language, subtags_region as region,
+/// locale, subtags_language as language, subtags_region as region,
/// subtags_script as script,
/// };
///
-/// let lang = language!("en");
-/// let script = script!("Latn");
-/// let region = region!("US");
-/// let loc = Locale::from((lang, Some(script), Some(region)));
-///
-/// assert_eq!(loc.id.language, lang);
-/// assert_eq!(loc.id.script.unwrap(), script);
-/// assert_eq!(loc.id.region.unwrap(), region);
-/// assert_eq!(loc.id.variants.len(), 0);
-/// assert_eq!(loc.to_string(), "en-Latn-US");
+/// assert_eq!(
+/// Locale::from((
+/// language!("en"),
+/// Some(script!("Latn")),
+/// Some(region!("US"))
+/// )),
+/// locale!("en-Latn-US")
+/// );
/// ```
impl
From<(
diff --git a/vendor/icu_locid/src/parser/errors.rs b/vendor/icu_locid/src/parser/errors.rs
index a989bcc60..5cbbb2bd4 100644
--- a/vendor/icu_locid/src/parser/errors.rs
+++ b/vendor/icu_locid/src/parser/errors.rs
@@ -48,6 +48,22 @@ pub enum ParserError {
/// ```
#[displaydoc("Invalid extension")]
InvalidExtension,
+
+ /// Duplicated extension.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use icu::locid::Locale;
+ /// use icu::locid::ParserError;
+ ///
+ /// assert_eq!(
+ /// "und-u-hc-h12-u-ca-calendar".parse::<Locale>(),
+ /// Err(ParserError::DuplicatedExtension)
+ /// );
+ /// ```
+ #[displaydoc("Duplicated extension")]
+ DuplicatedExtension,
}
#[cfg(feature = "std")]
diff --git a/vendor/icu_locid/src/parser/langid.rs b/vendor/icu_locid/src/parser/langid.rs
index 9efa078ac..653ca7e6e 100644
--- a/vendor/icu_locid/src/parser/langid.rs
+++ b/vendor/icu_locid/src/parser/langid.rs
@@ -5,7 +5,7 @@
pub use super::errors::ParserError;
use crate::extensions::unicode::{Attribute, Key, Value};
use crate::extensions::ExtensionType;
-use crate::parser::{get_subtag_iterator, SubtagIterator};
+use crate::parser::SubtagIterator;
use crate::LanguageIdentifier;
use crate::{extensions, subtags};
use alloc::vec::Vec;
@@ -103,7 +103,7 @@ pub fn parse_language_identifier(
t: &[u8],
mode: ParserMode,
) -> Result<LanguageIdentifier, ParserError> {
- let mut iter = get_subtag_iterator(t);
+ let mut iter = SubtagIterator::new(t);
parse_language_identifier_from_iter(&mut iter, mode)
}
@@ -127,9 +127,9 @@ pub const fn parse_locale_with_single_variant_single_keyword_unicode_extension_f
let mut variant = None;
let mut keyword = None;
- if let (i, Some((t, start, end))) = iter.next_manual() {
+ if let (i, Some((start, end))) = iter.next_manual() {
iter = i;
- match subtags::Language::try_from_bytes_manual_slice(t, start, end) {
+ match subtags::Language::try_from_bytes_manual_slice(iter.slice, start, end) {
Ok(l) => language = l,
Err(e) => return Err(e),
}
@@ -139,19 +139,23 @@ pub const fn parse_locale_with_single_variant_single_keyword_unicode_extension_f
let mut position = ParserPosition::Script;
- while let Some((t, start, end)) = iter.peek_manual() {
+ while let Some((start, end)) = iter.peek_manual() {
if !matches!(mode, ParserMode::LanguageIdentifier) && end - start == 1 {
break;
}
if matches!(position, ParserPosition::Script) {
- if let Ok(s) = subtags::Script::try_from_bytes_manual_slice(t, start, end) {
+ if let Ok(s) = subtags::Script::try_from_bytes_manual_slice(iter.slice, start, end) {
script = Some(s);
position = ParserPosition::Region;
- } else if let Ok(r) = subtags::Region::try_from_bytes_manual_slice(t, start, end) {
+ } else if let Ok(r) =
+ subtags::Region::try_from_bytes_manual_slice(iter.slice, start, end)
+ {
region = Some(r);
position = ParserPosition::Variant;
- } else if let Ok(v) = subtags::Variant::try_from_bytes_manual_slice(t, start, end) {
+ } else if let Ok(v) =
+ subtags::Variant::try_from_bytes_manual_slice(iter.slice, start, end)
+ {
// We cannot handle multiple variants in a const context
debug_assert!(variant.is_none());
variant = Some(v);
@@ -162,10 +166,12 @@ pub const fn parse_locale_with_single_variant_single_keyword_unicode_extension_f
return Err(ParserError::InvalidSubtag);
}
} else if matches!(position, ParserPosition::Region) {
- if let Ok(s) = subtags::Region::try_from_bytes_manual_slice(t, start, end) {
+ if let Ok(s) = subtags::Region::try_from_bytes_manual_slice(iter.slice, start, end) {
region = Some(s);
position = ParserPosition::Variant;
- } else if let Ok(v) = subtags::Variant::try_from_bytes_manual_slice(t, start, end) {
+ } else if let Ok(v) =
+ subtags::Variant::try_from_bytes_manual_slice(iter.slice, start, end)
+ {
// We cannot handle multiple variants in a const context
debug_assert!(variant.is_none());
variant = Some(v);
@@ -175,7 +181,8 @@ pub const fn parse_locale_with_single_variant_single_keyword_unicode_extension_f
} else {
return Err(ParserError::InvalidSubtag);
}
- } else if let Ok(v) = subtags::Variant::try_from_bytes_manual_slice(t, start, end) {
+ } else if let Ok(v) = subtags::Variant::try_from_bytes_manual_slice(iter.slice, start, end)
+ {
debug_assert!(matches!(position, ParserPosition::Variant));
if variant.is_some() {
// We cannot handle multiple variants in a const context
@@ -192,12 +199,12 @@ pub const fn parse_locale_with_single_variant_single_keyword_unicode_extension_f
}
if matches!(mode, ParserMode::Locale) {
- if let Some((bytes, start, end)) = iter.peek_manual() {
- match ExtensionType::try_from_bytes_manual_slice(bytes, start, end) {
+ if let Some((start, end)) = iter.peek_manual() {
+ match ExtensionType::try_from_bytes_manual_slice(iter.slice, start, end) {
Ok(ExtensionType::Unicode) => {
iter = iter.next_manual().0;
- if let Some((bytes, start, end)) = iter.peek_manual() {
- if Attribute::try_from_bytes_manual_slice(bytes, start, end).is_ok() {
+ if let Some((start, end)) = iter.peek_manual() {
+ if Attribute::try_from_bytes_manual_slice(iter.slice, start, end).is_ok() {
// We cannot handle Attributes in a const context
return Err(ParserError::InvalidSubtag);
}
@@ -206,19 +213,21 @@ pub const fn parse_locale_with_single_variant_single_keyword_unicode_extension_f
let mut key = None;
let mut current_type = None;
- while let Some((bytes, start, end)) = iter.peek_manual() {
+ while let Some((start, end)) = iter.peek_manual() {
let slen = end - start;
if slen == 2 {
if key.is_some() {
// We cannot handle more than one Key in a const context
return Err(ParserError::InvalidSubtag);
}
- match Key::try_from_bytes_manual_slice(bytes, start, end) {
+ match Key::try_from_bytes_manual_slice(iter.slice, start, end) {
Ok(k) => key = Some(k),
Err(e) => return Err(e),
};
} else if key.is_some() {
- match Value::parse_subtag_from_bytes_manual_slice(bytes, start, end) {
+ match Value::parse_subtag_from_bytes_manual_slice(
+ iter.slice, start, end,
+ ) {
Ok(Some(t)) => {
if current_type.is_some() {
// We cannot handle more than one type in a const context
@@ -261,7 +270,7 @@ pub const fn parse_language_identifier_with_single_variant(
),
ParserError,
> {
- let iter = get_subtag_iterator(t);
+ let iter = SubtagIterator::new(t);
match parse_locale_with_single_variant_single_keyword_unicode_extension_from_iter(iter, mode) {
Ok((l, s, r, v, _)) => Ok((l, s, r, v)),
Err(e) => Err(e),
diff --git a/vendor/icu_locid/src/parser/locale.rs b/vendor/icu_locid/src/parser/locale.rs
index 805b6c290..175fd3a05 100644
--- a/vendor/icu_locid/src/parser/locale.rs
+++ b/vendor/icu_locid/src/parser/locale.rs
@@ -6,13 +6,13 @@ use tinystr::TinyAsciiStr;
use crate::extensions::{self, Extensions};
use crate::parser::errors::ParserError;
-use crate::parser::{get_subtag_iterator, parse_language_identifier_from_iter, ParserMode};
+use crate::parser::{parse_language_identifier_from_iter, ParserMode, SubtagIterator};
use crate::{subtags, Locale};
use super::parse_locale_with_single_variant_single_keyword_unicode_extension_from_iter;
pub fn parse_locale(t: &[u8]) -> Result<Locale, ParserError> {
- let mut iter = get_subtag_iterator(t);
+ let mut iter = SubtagIterator::new(t);
let id = parse_language_identifier_from_iter(&mut iter, ParserMode::Locale)?;
let extensions = if iter.peek().is_some() {
@@ -37,6 +37,6 @@ pub const fn parse_locale_with_single_variant_single_keyword_unicode_keyword_ext
),
ParserError,
> {
- let iter = get_subtag_iterator(t);
+ let iter = SubtagIterator::new(t);
parse_locale_with_single_variant_single_keyword_unicode_extension_from_iter(iter, mode)
}
diff --git a/vendor/icu_locid/src/parser/mod.rs b/vendor/icu_locid/src/parser/mod.rs
index fef10b0ab..4b02f71c9 100644
--- a/vendor/icu_locid/src/parser/mod.rs
+++ b/vendor/icu_locid/src/parser/mod.rs
@@ -17,72 +17,93 @@ pub use locale::{
parse_locale, parse_locale_with_single_variant_single_keyword_unicode_keyword_extension,
};
-pub const fn get_subtag_iterator(slice: &[u8]) -> SubtagIterator {
- let mut current_start = 0;
+#[inline]
+const fn is_separator(slice: &[u8], idx: usize) -> bool {
#[allow(clippy::indexing_slicing)]
- while current_start < slice.len()
- && (slice[current_start] == b'-' || slice[current_start] == b'_')
- {
- current_start += 1;
- }
- let mut current_end = current_start;
- #[allow(clippy::indexing_slicing)]
- while current_end < slice.len() && slice[current_end] != b'-' && slice[current_end] != b'_' {
- current_end += 1;
- }
- SubtagIterator {
- slice,
- current_start,
- current_end,
+ let b = slice[idx];
+ b == b'-' || b == b'_'
+}
+
+const fn get_current_subtag(slice: &[u8], idx: usize) -> (usize, usize) {
+ debug_assert!(idx < slice.len());
+
+ // This function is called only on the idx == 0 or on a separator.
+ let (start, mut end) = if is_separator(slice, idx) {
+ // If it's a separator, set the start to idx+1 and advance the idx to the next char.
+ (idx + 1, idx + 1)
+ } else {
+ // If it's idx=0, start is 0 and end is set to 1
+ debug_assert!(idx == 0);
+ (0, 1)
+ };
+
+ while end < slice.len() && !is_separator(slice, end) {
+ // Advance until we reach end of slice or a separator.
+ end += 1;
}
+ // Notice: this slice may be empty (start == end) for cases like `"en-"` or `"en--US"`
+ (start, end)
}
+// `SubtagIterator` is a helper iterator for [`LanguageIdentifier`] and [`Locale`] parsing.
+//
+// It is quite extraordinary due to focus on performance and Rust limitations for `const`
+// functions.
+//
+// The iterator is eager and fallible allowing it to reject invalid slices such as `"-"`, `"-en"`,
+// `"en-"` etc.
+//
+// The iterator provides methods available for static users - `next_manual` and `peek_manual`,
+// as well as typical `Peekable` iterator APIs - `next` and `peek`.
+//
+// All methods return an `Option` of a `Result`.
#[derive(Copy, Clone, Debug)]
pub struct SubtagIterator<'a> {
- slice: &'a [u8],
- current_start: usize,
- current_end: usize,
+ pub slice: &'a [u8],
+ done: bool,
+ // done + subtag is faster than Option<(usize, usize)>
+ // at the time of writing.
+ subtag: (usize, usize),
}
-pub type ManualSlice<'a> = (&'a [u8], usize, usize);
-
impl<'a> SubtagIterator<'a> {
- pub const fn next_manual(mut self) -> (Self, Option<ManualSlice<'a>>) {
- if self.current_start == self.current_end {
- (self, None)
+ pub const fn new(slice: &'a [u8]) -> Self {
+ let subtag = if slice.is_empty() || is_separator(slice, 0) {
+ // This returns (0, 0) which returns Some(b"") for slices like `"-en"` or `"-"`
+ (0, 0)
} else {
- let r = (self.slice, self.current_start, self.current_end);
- self.current_start = self.current_end;
- #[allow(clippy::indexing_slicing)]
- while self.current_start < self.slice.len()
- && (self.slice[self.current_start] == b'-'
- || self.slice[self.current_start] == b'_')
- {
- self.current_start += 1;
- }
- self.current_end = self.current_start;
- #[allow(clippy::indexing_slicing)]
- while self.current_end < self.slice.len()
- && self.slice[self.current_end] != b'-'
- && self.slice[self.current_end] != b'_'
- {
- self.current_end += 1;
- }
- (self, Some(r))
+ get_current_subtag(slice, 0)
+ };
+ Self {
+ slice,
+ done: false,
+ subtag,
}
}
- pub const fn peek_manual(&self) -> Option<ManualSlice<'a>> {
- if self.current_start == self.current_end {
- None
+ pub const fn next_manual(mut self) -> (Self, Option<(usize, usize)>) {
+ if self.done {
+ return (self, None);
+ }
+ let result = self.subtag;
+ if result.1 < self.slice.len() {
+ self.subtag = get_current_subtag(self.slice, result.1);
} else {
- Some((self.slice, self.current_start, self.current_end))
+ self.done = true;
}
+ (self, Some(result))
+ }
+
+ pub const fn peek_manual(&self) -> Option<(usize, usize)> {
+ if self.done {
+ return None;
+ }
+ Some(self.subtag)
}
pub fn peek(&self) -> Option<&'a [u8]> {
#[allow(clippy::indexing_slicing)] // peek_manual returns valid indices
- self.peek_manual().map(|(t, s, e)| &t[s..e])
+ self.peek_manual().map(|(s, e)| &self.slice[s..e])
}
}
@@ -91,8 +112,120 @@ impl<'a> Iterator for SubtagIterator<'a> {
fn next(&mut self) -> Option<Self::Item> {
let (s, res) = self.next_manual();
- self.clone_from(&s);
+ *self = s;
#[allow(clippy::indexing_slicing)] // next_manual returns valid indices
- res.map(|(t, s, e)| &t[s..e])
+ res.map(|(s, e)| &self.slice[s..e])
+ }
+}
+
+#[cfg(test)]
+mod test {
+ use super::*;
+
+ fn slice_to_str(input: &[u8]) -> &str {
+ std::str::from_utf8(input).unwrap()
+ }
+
+ #[test]
+ fn subtag_iterator_peek_test() {
+ let slice = "de_at-u-ca-foobar";
+ let mut si = SubtagIterator::new(slice.as_bytes());
+
+ assert_eq!(si.peek().map(slice_to_str), Some("de"));
+ assert_eq!(si.peek().map(slice_to_str), Some("de"));
+ assert_eq!(si.next().map(slice_to_str), Some("de"));
+
+ assert_eq!(si.peek().map(slice_to_str), Some("at"));
+ assert_eq!(si.peek().map(slice_to_str), Some("at"));
+ assert_eq!(si.next().map(slice_to_str), Some("at"));
+ }
+
+ #[test]
+ fn subtag_iterator_test() {
+ let slice = "";
+ let mut si = SubtagIterator::new(slice.as_bytes());
+ assert_eq!(si.next().map(slice_to_str), Some(""));
+
+ let slice = "-";
+ let mut si = SubtagIterator::new(slice.as_bytes());
+ assert_eq!(si.next().map(slice_to_str), Some(""));
+
+ let slice = "-en";
+ let mut si = SubtagIterator::new(slice.as_bytes());
+ assert_eq!(si.next().map(slice_to_str), Some(""));
+ assert_eq!(si.next().map(slice_to_str), Some("en"));
+ assert_eq!(si.next(), None);
+
+ let slice = "en";
+ let si = SubtagIterator::new(slice.as_bytes());
+ assert_eq!(si.map(slice_to_str).collect::<Vec<_>>(), vec!["en",]);
+
+ let slice = "en-";
+ let si = SubtagIterator::new(slice.as_bytes());
+ assert_eq!(si.map(slice_to_str).collect::<Vec<_>>(), vec!["en", "",]);
+
+ let slice = "--";
+ let mut si = SubtagIterator::new(slice.as_bytes());
+ assert_eq!(si.next().map(slice_to_str), Some(""));
+ assert_eq!(si.next().map(slice_to_str), Some(""));
+ assert_eq!(si.next().map(slice_to_str), Some(""));
+ assert_eq!(si.next(), None);
+
+ let slice = "-en-";
+ let mut si = SubtagIterator::new(slice.as_bytes());
+ assert_eq!(si.next().map(slice_to_str), Some(""));
+ assert_eq!(si.next().map(slice_to_str), Some("en"));
+ assert_eq!(si.next().map(slice_to_str), Some(""));
+ assert_eq!(si.next(), None);
+
+ let slice = "de_at-u-ca-foobar";
+ let si = SubtagIterator::new(slice.as_bytes());
+ assert_eq!(
+ si.map(slice_to_str).collect::<Vec<_>>(),
+ vec!["de", "at", "u", "ca", "foobar",]
+ );
+ }
+
+ #[test]
+ fn get_current_subtag_test() {
+ let slice = "-";
+ let current = get_current_subtag(slice.as_bytes(), 0);
+ assert_eq!(current, (1, 1));
+
+ let slice = "-en";
+ let current = get_current_subtag(slice.as_bytes(), 0);
+ assert_eq!(current, (1, 3));
+
+ let slice = "-en-";
+ let current = get_current_subtag(slice.as_bytes(), 3);
+ assert_eq!(current, (4, 4));
+
+ let slice = "en-";
+ let current = get_current_subtag(slice.as_bytes(), 0);
+ assert_eq!(current, (0, 2));
+
+ let current = get_current_subtag(slice.as_bytes(), 2);
+ assert_eq!(current, (3, 3));
+
+ let slice = "en--US";
+ let current = get_current_subtag(slice.as_bytes(), 0);
+ assert_eq!(current, (0, 2));
+
+ let current = get_current_subtag(slice.as_bytes(), 2);
+ assert_eq!(current, (3, 3));
+
+ let current = get_current_subtag(slice.as_bytes(), 3);
+ assert_eq!(current, (4, 6));
+
+ let slice = "--";
+ let current = get_current_subtag(slice.as_bytes(), 0);
+ assert_eq!(current, (1, 1));
+
+ let current = get_current_subtag(slice.as_bytes(), 1);
+ assert_eq!(current, (2, 2));
+
+ let slice = "-";
+ let current = get_current_subtag(slice.as_bytes(), 0);
+ assert_eq!(current, (1, 1));
}
}
diff --git a/vendor/icu_locid/src/subtags/language.rs b/vendor/icu_locid/src/subtags/language.rs
index a5ec8d76e..86b51b93a 100644
--- a/vendor/icu_locid/src/subtags/language.rs
+++ b/vendor/icu_locid/src/subtags/language.rs
@@ -55,7 +55,6 @@ impl Language {
/// use icu::locid::subtags::Language;
///
/// assert_eq!(Language::default(), Language::UND);
- /// assert_eq!("und", Language::UND.to_string());
/// ```
pub const UND: Self = unsafe { Self::from_raw_unchecked(*b"und") };
@@ -64,15 +63,15 @@ impl Language {
/// # Examples
///
/// ```
- /// use icu::locid::subtags::Language;
+ /// use icu::locid::{subtags::Language, subtags_language as language};
///
- /// let mut lang: Language = "csb".parse().expect("Parsing failed.");
+ /// let mut lang = language!("csb");
///
- /// assert_eq!(lang.as_str(), "csb");
+ /// assert_ne!(lang, Language::UND);
///
/// lang.clear();
///
- /// assert_eq!(lang.as_str(), "und");
+ /// assert_eq!(lang, Language::UND);
/// ```
#[inline]
pub fn clear(&mut self) {
@@ -86,7 +85,7 @@ impl Language {
/// ```
/// use icu::locid::subtags::Language;
///
- /// let mut lang: Language = "und".parse().expect("Parsing failed.");
+ /// let mut lang = Language::UND;
///
/// assert!(lang.is_empty());
///
diff --git a/vendor/icu_locid/src/subtags/variants.rs b/vendor/icu_locid/src/subtags/variants.rs
index bbff9ebac..3bd83f149 100644
--- a/vendor/icu_locid/src/subtags/variants.rs
+++ b/vendor/icu_locid/src/subtags/variants.rs
@@ -16,14 +16,9 @@ use core::ops::Deref;
/// # Examples
///
/// ```
-/// use icu::locid::subtags::{Variant, Variants};
+/// use icu::locid::{subtags::Variants, subtags_variant as variant};
///
-/// let variant1: Variant =
-/// "posix".parse().expect("Failed to parse a variant subtag.");
-///
-/// let variant2: Variant =
-/// "macos".parse().expect("Failed to parse a variant subtag.");
-/// let mut v = vec![variant1, variant2];
+/// let mut v = vec![variant!("posix"), variant!("macos")];
/// v.sort();
/// v.dedup();
///
@@ -53,10 +48,9 @@ impl Variants {
/// # Examples
///
/// ```
- /// use icu::locid::subtags::{Variant, Variants};
+ /// use icu::locid::{subtags::Variants, subtags_variant as variant};
///
- /// let variant: Variant = "posix".parse().expect("Parsing failed.");
- /// let variants = Variants::from_variant(variant);
+ /// let variants = Variants::from_variant(variant!("posix"));
/// ```
#[inline]
pub const fn from_variant(variant: Variant) -> Self {
@@ -70,11 +64,9 @@ impl Variants {
/// # Examples
///
/// ```
- /// use icu::locid::subtags::{Variant, Variants};
+ /// use icu::locid::{subtags::Variants, subtags_variant as variant};
///
- /// let variant1: Variant = "posix".parse().expect("Parsing failed.");
- /// let variant2: Variant = "macos".parse().expect("Parsing failed.");
- /// let mut v = vec![variant1, variant2];
+ /// let mut v = vec![variant!("posix"), variant!("macos")];
/// v.sort();
/// v.dedup();
///
@@ -95,11 +87,9 @@ impl Variants {
/// # Examples
///
/// ```
- /// use icu::locid::subtags::{Variant, Variants};
+ /// use icu::locid::{subtags::Variants, subtags_variant as variant};
///
- /// let variant1: Variant = "posix".parse().expect("Parsing failed.");
- /// let variant2: Variant = "macos".parse().expect("Parsing failed.");
- /// let mut v = vec![variant1, variant2];
+ /// let mut v = vec![variant!("posix"), variant!("macos")];
/// v.sort();
/// v.dedup();
///
@@ -109,7 +99,7 @@ impl Variants {
///
/// variants.clear();
///
- /// assert_eq!(variants.to_string(), "");
+ /// assert_eq!(variants, Variants::default());
/// ```
pub fn clear(&mut self) -> Self {
core::mem::take(self)
diff --git a/vendor/icu_locid/tests/fixtures/invalid-extensions.json b/vendor/icu_locid/tests/fixtures/invalid-extensions.json
index a5f3a923d..3aff2636b 100644
--- a/vendor/icu_locid/tests/fixtures/invalid-extensions.json
+++ b/vendor/icu_locid/tests/fixtures/invalid-extensions.json
@@ -108,5 +108,45 @@
"error": "InvalidExtension",
"text": "Invalid subtag"
}
+ },
+ {
+ "input": {
+ "type": "Locale",
+ "identifier": "de-u-ca-"
+ },
+ "output": {
+ "error": "InvalidExtension",
+ "text": "Invalid subtag"
+ }
+ },
+ {
+ "input": {
+ "type": "Locale",
+ "identifier": "de-u-ca-gregory-"
+ },
+ "output": {
+ "error": "InvalidExtension",
+ "text": "Invalid subtag"
+ }
+ },
+ {
+ "input": {
+ "type": "Locale",
+ "identifier": "de-u-ca-gregory-u-hc-hc24"
+ },
+ "output": {
+ "error": "DuplicatedExtension",
+ "text": "Duplicated extension"
+ }
+ },
+ {
+ "input": {
+ "type": "Locale",
+ "identifier": "de-l-foo-l-bar"
+ },
+ "output": {
+ "error": "DuplicatedExtension",
+ "text": "Duplicated extension"
+ }
}
]
diff --git a/vendor/icu_locid/tests/fixtures/invalid.json b/vendor/icu_locid/tests/fixtures/invalid.json
index d44007596..c22459e65 100644
--- a/vendor/icu_locid/tests/fixtures/invalid.json
+++ b/vendor/icu_locid/tests/fixtures/invalid.json
@@ -1,5 +1,54 @@
[
{
+ "input": "-",
+ "output": {
+ "error": "InvalidLanguage",
+ "text": "The given language subtag is invalid"
+ }
+ },
+ {
+ "input": "--",
+ "output": {
+ "error": "InvalidLanguage",
+ "text": "The given subtag is invalid"
+ }
+ },
+ {
+ "input": "en-",
+ "output": {
+ "error": "InvalidSubtag",
+ "text": "The given subtag is invalid"
+ }
+ },
+ {
+ "input": "-en",
+ "output": {
+ "error": "InvalidLanguage",
+ "text": "The given subtag is invalid"
+ }
+ },
+ {
+ "input": "en-us-",
+ "output": {
+ "error": "InvalidSubtag",
+ "text": "The given subtag is invalid"
+ }
+ },
+ {
+ "input": "en--US",
+ "output": {
+ "error": "InvalidSubtag",
+ "text": "The given subtag is invalid"
+ }
+ },
+ {
+ "input": "-e-",
+ "output": {
+ "error": "InvalidLanguage",
+ "text": "The given subtag is invalid"
+ }
+ },
+ {
"input": "a1a",
"output": {
"error": "InvalidLanguage",
diff --git a/vendor/icu_locid/tests/fixtures/mod.rs b/vendor/icu_locid/tests/fixtures/mod.rs
index b688632ba..f00fd6c3b 100644
--- a/vendor/icu_locid/tests/fixtures/mod.rs
+++ b/vendor/icu_locid/tests/fixtures/mod.rs
@@ -248,6 +248,7 @@ impl From<LocaleError> for ParserError {
"InvalidLanguage" => ParserError::InvalidLanguage,
"InvalidSubtag" => ParserError::InvalidSubtag,
"InvalidExtension" => ParserError::InvalidExtension,
+ "DuplicatedExtension" => ParserError::DuplicatedExtension,
_ => unreachable!("Unknown error name"),
}
}
diff --git a/vendor/icu_locid/tests/langid.rs b/vendor/icu_locid/tests/langid.rs
index 96d022a9b..60414e087 100644
--- a/vendor/icu_locid/tests/langid.rs
+++ b/vendor/icu_locid/tests/langid.rs
@@ -6,6 +6,7 @@ mod fixtures;
mod helpers;
use std::convert::TryInto;
+use writeable::*;
use icu_locid::{subtags, LanguageIdentifier, ParserError};
@@ -21,7 +22,7 @@ fn test_langid_fixtures(tests: Vec<fixtures::LocaleTest>) {
}
}
let input: LanguageIdentifier = test.input.try_into().expect("Parsing failed.");
- assert_eq!(input.to_string(), s);
+ assert_writeable_eq!(input, s);
}
fixtures::LocaleInfo::Error(err) => {
let err: ParserError = err.into();
@@ -83,28 +84,28 @@ fn test_langid_subtag_language() {
assert_eq!(lang, subtags::Language::UND);
assert!(lang.is_empty());
- assert_eq!(lang.to_string(), "und");
+ assert_writeable_eq!(lang, "und");
}
#[test]
fn test_langid_subtag_region() {
let region: subtags::Region = "en".parse().expect("Failed to parse a region.");
assert_eq!(region.as_str(), "EN");
- assert_eq!(region.to_string(), "EN");
+ assert_writeable_eq!(region, "EN");
}
#[test]
fn test_langid_subtag_script() {
let script: subtags::Script = "Latn".parse().expect("Failed to parse a script.");
assert_eq!(script.as_str(), "Latn");
- assert_eq!(script.to_string(), "Latn");
+ assert_writeable_eq!(script, "Latn");
}
#[test]
fn test_langid_subtag_variant() {
let variant: subtags::Variant = "macos".parse().expect("Failed to parse a variant.");
assert_eq!(variant.as_str(), "macos");
- assert_eq!(variant.to_string(), "macos");
+ assert_writeable_eq!(variant, "macos");
}
#[test]
@@ -123,7 +124,7 @@ fn test_langid_normalizing_eq_str() {
helpers::read_fixture(path).expect("Failed to read a fixture");
for test in tests {
let parsed: LanguageIdentifier = test.input.try_into().expect("Parsing failed.");
- assert!(parsed.normalizing_eq(parsed.to_string().as_str()));
+ assert!(parsed.normalizing_eq(&*parsed.write_to_string()));
}
// Check that trailing characters are not ignored
@@ -148,7 +149,7 @@ fn test_langid_strict_cmp() {
let a_langid = a
.parse::<LanguageIdentifier>()
.expect("Invalid BCP-47 in fixture");
- let a_normalized = a_langid.to_string();
+ let a_normalized = a_langid.write_to_string();
let string_cmp = a_normalized.as_bytes().cmp(b.as_bytes());
let test_cmp = a_langid.strict_cmp(b.as_bytes());
assert_eq!(string_cmp, test_cmp, "{:?}/{:?}", a, b);
diff --git a/vendor/icu_locid/tests/locale.rs b/vendor/icu_locid/tests/locale.rs
index 37c43181e..cd3448983 100644
--- a/vendor/icu_locid/tests/locale.rs
+++ b/vendor/icu_locid/tests/locale.rs
@@ -6,6 +6,7 @@ mod fixtures;
mod helpers;
use std::convert::TryInto;
+use writeable::*;
use icu_locid::{LanguageIdentifier, Locale, ParserError};
@@ -16,7 +17,7 @@ fn test_langid_fixtures(tests: Vec<fixtures::LocaleTest>) {
match test.output {
fixtures::LocaleInfo::String(s) => {
let input: Locale = test.input.try_into().expect("Parsing failed.");
- assert_eq!(input.to_string(), s);
+ assert_writeable_eq!(input, s);
}
fixtures::LocaleInfo::Error(err) => {
let err: ParserError = err.into();
@@ -27,7 +28,7 @@ fn test_langid_fixtures(tests: Vec<fixtures::LocaleTest>) {
let input: Locale = test.input.try_into().expect("Parsing failed.");
let output: Locale = ident.clone().try_into().expect("Parsing failed.");
assert_eq!(input, output);
- assert_eq!(input.to_string(), ident.identifier);
+ assert_writeable_eq!(input, ident.identifier);
}
fixtures::LocaleInfo::Object(o) => {
let input: Locale = test.input.try_into().expect("Parsing failed.");
@@ -58,7 +59,7 @@ fn test_langid_invalid() {
fn test_locale_is_empty() {
let locale: Locale = Locale::default();
assert!(locale.extensions.is_empty());
- assert_eq!(locale.to_string(), "und".to_string());
+ assert_writeable_eq!(locale, "und");
}
#[test]
@@ -74,10 +75,7 @@ fn test_locale_canonicalize() {
let locale: Locale = "En-latn-US-MacOS"
.parse()
.expect("Failed to parse a locale.");
- assert_eq!(
- locale.to_string(),
- Locale::canonicalize("eN-latN-uS-macOS").unwrap()
- );
+ assert_writeable_eq!(locale, Locale::canonicalize("eN-latN-uS-macOS").unwrap());
}
#[test]
@@ -87,7 +85,7 @@ fn test_locale_normalizing_eq_str() {
helpers::read_fixture(path).expect("Failed to read a fixture");
for test in tests {
let parsed: Locale = test.input.try_into().expect("Parsing failed.");
- assert!(parsed.normalizing_eq(parsed.to_string().as_str()));
+ assert!(parsed.normalizing_eq(&*parsed.write_to_string()));
}
// Check that trailing characters are not ignored
@@ -113,7 +111,7 @@ fn test_locale_strict_cmp() {
for a in bcp47_strings.iter() {
for b in bcp47_strings.iter() {
let a_langid = a.parse::<Locale>().expect("Invalid BCP-47 in fixture");
- let a_normalized = a_langid.to_string();
+ let a_normalized = a_langid.write_to_string();
let string_cmp = a_normalized.as_bytes().cmp(b.as_bytes());
let test_cmp = a_langid.strict_cmp(b.as_bytes());
assert_eq!(string_cmp, test_cmp, "{:?}/{:?}", a, b);
diff --git a/vendor/icu_provider/.cargo-checksum.json b/vendor/icu_provider/.cargo-checksum.json
index fd85bb931..079ffc8f3 100644
--- a/vendor/icu_provider/.cargo-checksum.json
+++ b/vendor/icu_provider/.cargo-checksum.json
@@ -1 +1 @@
-{"files":{"Cargo.toml":"2b5b03ef885db4858645deae855ec7347fda3b8b18ce326521d11dd5fa5e7f0d","LICENSE":"4ad7541d66a407234e2c84902124cef325c29f3e966353efdb800bedb8b8da21","README.md":"97887d230a6a85aa40110bf2bb9356a69b8762f64bdbf66d019f2cdf9f8fee0e","src/any.rs":"f347c91b6ad34d330d69e60f276716c595c32ca7abf591340ba659a54ba73415","src/buf.rs":"ed8d68fc8facae65294f648bca8dad2ad6e75fbea6250212a2f6fc8f1147a015","src/constructors.rs":"895162fc4f3ceeff9236a765b6caf41a343794af2fc0d9cc686487e6980ff111","src/data_provider.rs":"088fa10caeec785777366d543d8622ae4ac52fa0721de25281456d8346371e56","src/datagen/data_conversion.rs":"21c21bb300557f158f77155397a023e1eda22413d66ac0c4f8ce04184fd90b20","src/datagen/heap_measure.rs":"14f3224d071d0c9695720b53257a60da19c3355c4bff272f9a9e3c3a9711f27a","src/datagen/iter.rs":"6353ec6476596ae6dfd5aee5f3f420c3a1c1c6e71911fa7dae49e17564e1930f","src/datagen/mod.rs":"0ed8676ad23d5acf622b9b971195c44976eaa41320f86627ad2c3f506c064d4e","src/datagen/payload.rs":"d9b1e5ceb07bdadc01d200f712b556d37a325cfad8fc6c7c17ceecaab4ef57e2","src/dynutil.rs":"bff12a7000298a1f46c98bb66f94492a88f9111afb59e8accea6b83d95e83af2","src/error.rs":"d01b45212c1c3bf5e904c631a26d0c5f91802575e55675f73d3591a1d0da8f25","src/hello_world.rs":"57fd467793374d66ed05982ae04b72983b3d67744fa81cf7ddde1174d1d2e741","src/helpers.rs":"1712d389dfda2a9c2d5d973f212209ecb4a16f27998d893a2f1a4cf96cb44e10","src/key.rs":"286d271012fc2eb8b34bfa843a5783b4a3ce5a1e23a63234ca11a8f82f2c13cc","src/lib.rs":"26b72a010db444d339d3803b7e598842efe52fff97b56fb3c6ddf632fc70ecdc","src/marker.rs":"58d770fb28e696c33192b9ecc5a86e1dca01f206d62656b45787375d69168852","src/request.rs":"141b12da429c5dcc2577d0911a4b09b6d579d173510eac6d3cd997fd986020f4","src/response.rs":"71e078dabcc91c822c315ae89f499b7d9724b40addc89786320ca658979e2f6c","src/serde/borrow_de_utils.rs":"30936d0ac69a9edc1a4935dcf777f1c1161d3f8d8d3a997b80744cf6c62bc4b5","src/serde/mod.rs":"b7033686b2f6d72fbdab6388b65c29651fd3b6ac45a37981421dab03a73c5ef5"},"package":"2f911086e3c521a8a824d4f8bfd87769645ced2f07ff913b521c0d793be07100"} \ No newline at end of file
+{"files":{"Cargo.toml":"5eb9543e4ba0986f30237d8e026704143a75c1d197292f370294abd5a45bd10b","LICENSE":"4ad7541d66a407234e2c84902124cef325c29f3e966353efdb800bedb8b8da21","README.md":"bb2790cbf8d6109a07f4f0fe38aedfba0258637b1a28e67d35057eb57362fc41","src/any.rs":"7a6678e693e6090ebee04366dcf47a0449ce9006cca1f2ac429bd87eb9a0bbf2","src/buf.rs":"c1cb09ef992f6cefb65c8a0131d3f1e30332f093bd714429bba67e82fc3ee145","src/constructors.rs":"bbb8e0b82d8be54b6992d82df6738c20468e97af5910a22ceda437415ece9c13","src/data_provider.rs":"088fa10caeec785777366d543d8622ae4ac52fa0721de25281456d8346371e56","src/datagen/data_conversion.rs":"21c21bb300557f158f77155397a023e1eda22413d66ac0c4f8ce04184fd90b20","src/datagen/heap_measure.rs":"14f3224d071d0c9695720b53257a60da19c3355c4bff272f9a9e3c3a9711f27a","src/datagen/iter.rs":"6353ec6476596ae6dfd5aee5f3f420c3a1c1c6e71911fa7dae49e17564e1930f","src/datagen/mod.rs":"47e5b36432d27af3ff2662efceebe7dfb9b875f776e162dc547bb8ce2893e3a3","src/datagen/payload.rs":"d9b1e5ceb07bdadc01d200f712b556d37a325cfad8fc6c7c17ceecaab4ef57e2","src/dynutil.rs":"bff12a7000298a1f46c98bb66f94492a88f9111afb59e8accea6b83d95e83af2","src/error.rs":"c25cf6969feb7097edfc831a7d1aa6a3e3ba31c97e637f8f382bd3ec7905d5a7","src/hello_world.rs":"ff99a920ca8ef84d29129f1c8563fa96e963848532f9dbbddd02d634b8d6c0fb","src/helpers.rs":"1712d389dfda2a9c2d5d973f212209ecb4a16f27998d893a2f1a4cf96cb44e10","src/key.rs":"59d2d89107a24ee3f92f085715a1ba8c1222eced384969534fbcd43c68e2a658","src/lib.rs":"dcae8affb71e51095eab6180e08194e87a5aa6e339b8f3f18c4e1ce45a8c714a","src/marker.rs":"58d770fb28e696c33192b9ecc5a86e1dca01f206d62656b45787375d69168852","src/request.rs":"9ab23e38f941a4abc54be028888db6e787557088fc290d67b4f112db77c45521","src/response.rs":"9d93b42a1dda53f71195f1371c8a0a50755488af1fa20262fb703d60a6e1359e","src/serde/borrow_de_utils.rs":"30936d0ac69a9edc1a4935dcf777f1c1161d3f8d8d3a997b80744cf6c62bc4b5","src/serde/mod.rs":"a65937b6501a8106ae6036a7ba09977707b5268d2a6bdc3f2e43088610170da8"},"package":"a86816c97bc4e613086497f9479f63e120315e056763e8c4435604f98d21d82d"} \ No newline at end of file
diff --git a/vendor/icu_provider/Cargo.toml b/vendor/icu_provider/Cargo.toml
index 4ed67b0c0..84f561096 100644
--- a/vendor/icu_provider/Cargo.toml
+++ b/vendor/icu_provider/Cargo.toml
@@ -12,7 +12,7 @@
[package]
edition = "2021"
name = "icu_provider"
-version = "1.0.1"
+version = "1.1.0"
authors = ["The ICU4X Project Developers"]
include = [
"src/**/*",
@@ -30,23 +30,18 @@ license = "Unicode-DFS-2016"
repository = "https://github.com/unicode-org/icu4x"
resolver = "2"
-[package.metadata.cargo-all-features]
-skip_optional_dependencies = true
-denylist = [
- "bench",
- "macros",
-]
-extra_features = ["serde"]
-
[package.metadata.docs.rs]
all-features = true
+[package.metadata.cargo-all-features]
+denylist = ["macros"]
+
[dependencies.bincode]
version = "1.3"
optional = true
[dependencies.databake]
-version = "0.1.0"
+version = "0.1.3"
features = ["derive"]
optional = true
@@ -65,10 +60,10 @@ optional = true
default-features = false
[dependencies.icu_locid]
-version = "1.0.0"
+version = "1.1.0"
[dependencies.icu_provider_macros]
-version = "1.0.0"
+version = "1.1.0"
optional = true
[dependencies.log]
@@ -100,53 +95,47 @@ version = "1.2.0"
default-features = false
[dependencies.writeable]
-version = "0.5"
+version = "0.5.1"
[dependencies.yoke]
-version = "0.6.2"
+version = "0.7.0"
features = ["derive"]
[dependencies.zerofrom]
-version = "0.1.0"
+version = "0.1.1"
features = ["derive"]
[dependencies.zerovec]
-version = "0.9"
+version = "0.9.2"
features = ["derive"]
[dev-dependencies.serde_json]
version = "1.0"
-[dev-dependencies.static_assertions]
-version = "1.1"
-
[features]
datagen = [
- "dhat",
+ "dep:dhat",
"serde",
- "erased-serde",
- "databake",
+ "dep:erased-serde",
+ "dep:databake",
"std",
- "serde_json",
"sync",
- "yoke/serde",
]
-default = []
deserialize_bincode_1 = [
"serde",
- "bincode",
+ "dep:bincode",
"std",
]
deserialize_json = [
"serde",
- "serde_json",
+ "dep:serde_json",
]
deserialize_postcard_1 = [
"serde",
- "postcard",
+ "dep:postcard",
]
-log_error_context = ["log"]
-macros = ["icu_provider_macros"]
+log_error_context = ["dep:log"]
+macros = ["dep:icu_provider_macros"]
serde = [
"dep:serde",
"yoke/serde",
diff --git a/vendor/icu_provider/README.md b/vendor/icu_provider/README.md
index 19d73a1a2..5692fa6b3 100644
--- a/vendor/icu_provider/README.md
+++ b/vendor/icu_provider/README.md
@@ -92,7 +92,7 @@ structs to borrow zero-copy data.
### Data generation API
-*This functionality is enabled with the "datagen" feature*
+*This functionality is enabled with the "datagen" Cargo feature*
The [`datagen`] module contains several APIs for data generation. See [`icu_datagen`] for the reference
data generation implementation.
diff --git a/vendor/icu_provider/src/any.rs b/vendor/icu_provider/src/any.rs
index 1c7a60435..989438c6b 100644
--- a/vendor/icu_provider/src/any.rs
+++ b/vendor/icu_provider/src/any.rs
@@ -18,7 +18,7 @@ use alloc::rc::Rc as SelectedRc;
use alloc::sync::Arc as SelectedRc;
/// A trait that allows to specify `Send + Sync` bounds that are only required when
-/// the `sync` feature is enabled. Without the feature, this is an empty bound.
+/// the `sync` Cargo feature is enabled. Without the Cargo feature, this is an empty bound.
#[cfg(feature = "sync")]
pub trait MaybeSendSync: Send + Sync {}
#[cfg(feature = "sync")]
@@ -115,6 +115,19 @@ impl AnyPayload {
}
}
+ /// Clones and then transforms a type-erased `AnyPayload` into a concrete `DataPayload<M>`.
+ pub fn downcast_cloned<M>(&self) -> Result<DataPayload<M>, DataError>
+ where
+ M: DataMarker + 'static,
+ // For the StructRef case:
+ M::Yokeable: ZeroFrom<'static, M::Yokeable>,
+ // For the PayloadRc case:
+ M::Yokeable: MaybeSendSync,
+ for<'a> YokeTraitHack<<M::Yokeable as Yokeable<'a>>::Output>: Clone,
+ {
+ self.clone().downcast()
+ }
+
/// Creates an `AnyPayload` from a static reference to a data struct.
///
/// # Examples
@@ -230,7 +243,7 @@ impl From<AnyResponse> for DataResponse<AnyMarker> {
}
impl AnyResponse {
- /// Transforms a type-erased `DataResponse<AnyMarker>` into a concrete `DataResponse<M>`.
+ /// Transforms a type-erased `AnyResponse` into a concrete `DataResponse<M>`.
#[inline]
pub fn downcast<M>(self) -> Result<DataResponse<M>, DataError>
where
@@ -244,6 +257,39 @@ impl AnyResponse {
payload: self.payload.map(|p| p.downcast()).transpose()?,
})
}
+
+ /// Clones and then transforms a type-erased `AnyResponse` into a concrete `DataResponse<M>`.
+ pub fn downcast_cloned<M>(&self) -> Result<DataResponse<M>, DataError>
+ where
+ M: DataMarker + 'static,
+ M::Yokeable: ZeroFrom<'static, M::Yokeable>,
+ M::Yokeable: MaybeSendSync,
+ for<'a> YokeTraitHack<<M::Yokeable as Yokeable<'a>>::Output>: Clone,
+ {
+ Ok(DataResponse {
+ metadata: self.metadata.clone(),
+ payload: self
+ .payload
+ .as_ref()
+ .map(|p| p.downcast_cloned())
+ .transpose()?,
+ })
+ }
+}
+
+impl<M> DataResponse<M>
+where
+ M: DataMarker + 'static,
+ M::Yokeable: MaybeSendSync,
+{
+ /// Moves the inner DataPayload to the heap (requiring an allocation) and returns it as an
+ /// erased `AnyResponse`.
+ pub fn wrap_into_any_response(self) -> AnyResponse {
+ AnyResponse {
+ metadata: self.metadata,
+ payload: self.payload.map(|p| p.wrap_into_any_payload()),
+ }
+ }
}
/// An object-safe data provider that returns data structs cast to `dyn Any` trait objects.
@@ -345,7 +391,10 @@ where
{
#[inline]
fn load(&self, req: DataRequest) -> Result<DataResponse<M>, DataError> {
- self.0.load_any(M::KEY, req)?.downcast()
+ self.0
+ .load_any(M::KEY, req)?
+ .downcast()
+ .map_err(|e| e.with_req(M::KEY, req))
}
}
@@ -359,7 +408,10 @@ where
{
#[inline]
fn load_data(&self, key: DataKey, req: DataRequest) -> Result<DataResponse<M>, DataError> {
- self.0.load_any(key, req)?.downcast()
+ self.0
+ .load_any(key, req)?
+ .downcast()
+ .map_err(|e| e.with_req(key, req))
}
}
diff --git a/vendor/icu_provider/src/buf.rs b/vendor/icu_provider/src/buf.rs
index 73bc0f165..796ad32f3 100644
--- a/vendor/icu_provider/src/buf.rs
+++ b/vendor/icu_provider/src/buf.rs
@@ -21,7 +21,11 @@ impl DataMarker for BufferMarker {
///
/// Generally, these bytes are expected to be deserializable with Serde. To get an object
/// implementing [`DataProvider`] via Serde, use [`as_deserializing()`], which requires
-/// enabling at least one of the Serde features.
+/// enabling at least one of the deserialization Cargo features:
+///
+/// - `deserialize_json`
+/// - `deserialize_postcard_1`
+/// - `deserialize_bincode_1`
///
/// Along with [`DataProvider`], this is one of the two foundational traits in this crate.
///
diff --git a/vendor/icu_provider/src/constructors.rs b/vendor/icu_provider/src/constructors.rs
index a9330c3f2..053da0320 100644
--- a/vendor/icu_provider/src/constructors.rs
+++ b/vendor/icu_provider/src/constructors.rs
@@ -54,7 +54,7 @@
//! 2. [`FsDataProvider`]
//! 3. [`ForkByKeyProvider`] between any of the above
//!
-//! Please note that you must enable the `"serde"` feature on each crate in which you use the
+//! Please note that you must enable the `"serde"` Cargo feature on each crate in which you use the
//! `*_with_buffer_provider` constructor.
//!
//! # Data Versioning Policy
@@ -78,8 +78,8 @@
//! Over FFI, there is only one data provider type: [`ICU4XDataProvider`]. Internally, it is an
//! `enum` between `dyn `[`AnyProvider`] and `dyn `[`BufferProvider`].
//!
-//! To control for code size, there are two features, `any_provider` and `buffer_provider`, that
-//! enable the corresponding items in the enum.
+//! To control for code size, there are two Cargo features, `any_provider` and `buffer_provider`,
+//! that enable the corresponding items in the enum.
//!
//! In Rust ICU4X, a similar buffer/any enum approach was not taken because:
//!
diff --git a/vendor/icu_provider/src/datagen/mod.rs b/vendor/icu_provider/src/datagen/mod.rs
index 5ede82275..e52a19c4d 100644
--- a/vendor/icu_provider/src/datagen/mod.rs
+++ b/vendor/icu_provider/src/datagen/mod.rs
@@ -6,7 +6,7 @@
//! via the `icu_datagen` reference crate. End users should not need to consume anything in
//! this module as a library unless defining new types that integrate with `icu_datagen`.
//!
-//! This module can be enabled with the `datagen` feature on `icu_provider`.
+//! This module can be enabled with the `datagen` Cargo feature on `icu_provider`.
mod data_conversion;
mod heap_measure;
diff --git a/vendor/icu_provider/src/error.rs b/vendor/icu_provider/src/error.rs
index 39bd1d0bb..05a48f9b7 100644
--- a/vendor/icu_provider/src/error.rs
+++ b/vendor/icu_provider/src/error.rs
@@ -64,8 +64,8 @@ pub enum DataErrorKind {
MissingSourceData,
/// An error indicating that the desired buffer format is not available. This usually
- /// means that a required feature was not enabled
- #[displaydoc("Unavailable buffer format: {0:?} (does icu_provider need to be compiled with an additional feature?)")]
+ /// means that a required Cargo feature was not enabled
+ #[displaydoc("Unavailable buffer format: {0:?} (does icu_provider need to be compiled with an additional Cargo feature?)")]
UnavailableBufferFormat(BufferFormat),
}
@@ -196,7 +196,7 @@ impl DataError {
/// Logs the data error with the given request, returning an error containing the resource key.
///
- /// If the "log_error_context" feature is enabled, this logs the whole request. Either way,
+ /// If the "log_error_context" Cargo feature is enabled, this logs the whole request. Either way,
/// it returns an error with the resource key portion of the request as context.
#[cfg_attr(not(feature = "log_error_context"), allow(unused_variables))]
pub fn with_req(self, key: DataKey, req: DataRequest) -> Self {
@@ -210,7 +210,7 @@ impl DataError {
/// Logs the data error with the given context, then return self.
///
- /// This does not modify the error, but if the "log_error_context" feature is enabled,
+ /// This does not modify the error, but if the "log_error_context" Cargo feature is enabled,
/// it will print out the context.
#[cfg(feature = "std")]
#[cfg_attr(not(feature = "log_error_context"), allow(unused_variables))]
@@ -222,7 +222,7 @@ impl DataError {
/// Logs the data error with the given context, then return self.
///
- /// This does not modify the error, but if the "log_error_context" feature is enabled,
+ /// This does not modify the error, but if the "log_error_context" Cargo feature is enabled,
/// it will print out the context.
#[cfg_attr(not(feature = "log_error_context"), allow(unused_variables))]
#[inline]
@@ -234,7 +234,7 @@ impl DataError {
/// Logs the data error with the given context, then return self.
///
- /// This does not modify the error, but if the "log_error_context" feature is enabled,
+ /// This does not modify the error, but if the "log_error_context" Cargo feature is enabled,
/// it will print out the context.
#[cfg_attr(not(feature = "log_error_context"), allow(unused_variables))]
#[inline]
diff --git a/vendor/icu_provider/src/hello_world.rs b/vendor/icu_provider/src/hello_world.rs
index 5fa671d84..7fd8289df 100644
--- a/vendor/icu_provider/src/hello_world.rs
+++ b/vendor/icu_provider/src/hello_world.rs
@@ -266,6 +266,8 @@ impl<'l> Writeable for FormattedHelloWorld<'l> {
}
}
+writeable::impl_display_with_writeable!(FormattedHelloWorld<'_>);
+
#[cfg(feature = "datagen")]
impl IterableDataProvider<HelloWorldV1Marker> for HelloWorldProvider {
fn supported_locales(&self) -> Result<Vec<DataLocale>, DataError> {
diff --git a/vendor/icu_provider/src/key.rs b/vendor/icu_provider/src/key.rs
index 2f55e4d46..d4d6905c9 100644
--- a/vendor/icu_provider/src/key.rs
+++ b/vendor/icu_provider/src/key.rs
@@ -140,11 +140,6 @@ impl DataKeyPath {
/// Gets the path as a static string slice.
#[inline]
pub const fn get(self) -> &'static str {
- /// core::slice::from_raw_parts(a, b) = core::mem::transmute((a, b)) hack
- /// ```compile_fail
- /// const unsafe fn canary() { core::slice::from_raw_parts(0 as *const u8, 0); }
- /// ```
- const _: () = ();
unsafe {
// Safe due to invariant that self.path is tagged correctly
core::str::from_utf8_unchecked(core::mem::transmute((
@@ -624,7 +619,6 @@ fn test_key_to_string() {
expected: "core/cardinal@65535",
},
] {
- assert_eq!(cas.expected, cas.key.to_string());
writeable::assert_writeable_eq!(&cas.key, cas.expected);
}
}
diff --git a/vendor/icu_provider/src/lib.rs b/vendor/icu_provider/src/lib.rs
index 594e872f4..7ee5b34e2 100644
--- a/vendor/icu_provider/src/lib.rs
+++ b/vendor/icu_provider/src/lib.rs
@@ -94,7 +94,7 @@
//!
//! ## Data generation API
//!
-//! *This functionality is enabled with the "datagen" feature*
+//! *This functionality is enabled with the "datagen" Cargo feature*
//!
//! The [`datagen`] module contains several APIs for data generation. See [`icu_datagen`] for the reference
//! data generation implementation.
diff --git a/vendor/icu_provider/src/request.rs b/vendor/icu_provider/src/request.rs
index 7f6bb5911..5f51f3a2c 100644
--- a/vendor/icu_provider/src/request.rs
+++ b/vendor/icu_provider/src/request.rs
@@ -53,11 +53,11 @@ pub struct DataRequestMetadata;
/// use icu_locid::locale;
/// use icu_provider::DataLocale;
///
-/// let locale1 = locale!("en-u-ca-buddhist");
-/// let data_locale = DataLocale::from(locale1);
-/// let locale2 = data_locale.into_locale();
+/// let locale = locale!("en-u-ca-buddhist");
+/// let data_locale = DataLocale::from(locale);
+/// let locale = data_locale.into_locale();
///
-/// assert_eq!(locale2.to_string(), "en-u-ca-buddhist");
+/// assert_eq!(locale, locale!("en-u-ca-buddhist"));
/// ```
///
/// You can alternatively create a [`DataLocale`] from a borrowed [`Locale`], which is more
@@ -81,18 +81,18 @@ pub struct DataRequestMetadata;
/// use icu_locid::langid;
/// use icu_provider::DataLocale;
///
-/// let langid1 = langid!("es-CA-valencia");
-/// let data_locale = DataLocale::from(langid1);
-/// let langid2 = data_locale.get_langid();
+/// let langid = langid!("es-CA-valencia");
+/// let data_locale = DataLocale::from(langid);
+/// let langid = data_locale.get_langid();
///
-/// assert_eq!(langid2.to_string(), "es-CA-valencia");
+/// assert_eq!(langid, langid!("es-CA-valencia"));
/// ```
///
/// [`DataLocale`] only supports `-u` keywords, to reflect the current state of CLDR data
/// lookup and fallback. This may change in the future.
///
/// ```
-/// use icu_locid::Locale;
+/// use icu_locid::{locale, Locale};
/// use icu_provider::DataLocale;
///
/// let locale = "hi-t-en-h0-hybrid-u-attr-ca-buddhist"
@@ -100,7 +100,7 @@ pub struct DataRequestMetadata;
/// .unwrap();
/// let data_locale = DataLocale::from(locale);
///
-/// assert_eq!(data_locale.to_string(), "hi-u-ca-buddhist");
+/// assert_eq!(data_locale.into_locale(), locale!("hi-u-ca-buddhist"));
/// ```
#[derive(PartialEq, Clone, Default, Eq, Hash)]
pub struct DataLocale {
@@ -225,7 +225,6 @@ impl DataLocale {
/// let b = ab[1];
/// assert!(a.cmp(b) == Ordering::Less);
/// let a_loc: DataLocale = a.parse::<Locale>().unwrap().into();
- /// assert_eq!(a, a_loc.to_string());
/// assert!(
/// a_loc.strict_cmp(a.as_bytes()) == Ordering::Equal,
/// "{} == {}",
@@ -239,7 +238,6 @@ impl DataLocale {
/// b
/// );
/// let b_loc: DataLocale = b.parse::<Locale>().unwrap().into();
- /// assert_eq!(b, b_loc.to_string());
/// assert!(
/// b_loc.strict_cmp(b.as_bytes()) == Ordering::Equal,
/// "{} == {}",
@@ -338,21 +336,20 @@ impl DataLocale {
///
/// ```
/// use icu_locid::{
- /// langid, subtags_language as language, subtags_region as region, Locale,
+ /// langid, locale, subtags_language as language, subtags_region as region,
+ /// Locale,
/// };
/// use icu_provider::prelude::*;
///
- /// let locale: Locale = "it-IT-u-ca-coptic".parse().expect("Valid BCP-47");
- /// let locale: DataLocale = locale.into();
+ /// let locale: DataLocale = locale!("it-IT-u-ca-coptic").into();
///
- /// assert_eq!(locale.to_string(), "it-IT-u-ca-coptic");
/// assert_eq!(locale.get_langid(), langid!("it-IT"));
/// assert_eq!(locale.language(), language!("it"));
/// assert_eq!(locale.script(), None);
/// assert_eq!(locale.region(), Some(region!("IT")));
///
/// let locale = locale.into_locale();
- /// assert_eq!(locale.to_string(), "it-IT-u-ca-coptic");
+ /// assert_eq!(locale, locale!("it-IT-u-ca-coptic"));
/// ```
pub fn into_locale(self) -> Locale {
let mut loc = Locale {
@@ -488,6 +485,8 @@ impl DataLocale {
#[test]
fn test_data_locale_to_string() {
+ use icu_locid::locale;
+
struct TestCase {
pub locale: DataLocale,
pub expected: &'static str,
@@ -499,15 +498,14 @@ fn test_data_locale_to_string() {
expected: "und",
},
TestCase {
- locale: "und-u-cu-gbp".parse::<Locale>().unwrap().into(),
+ locale: locale!("und-u-cu-gbp").into(),
expected: "und-u-cu-gbp",
},
TestCase {
- locale: "en-ZA-u-cu-gbp".parse::<Locale>().unwrap().into(),
+ locale: locale!("en-ZA-u-cu-gbp").into(),
expected: "en-ZA-u-cu-gbp",
},
] {
- assert_eq!(cas.expected, cas.locale.to_string());
- writeable::assert_writeable_eq!(&cas.locale, cas.expected);
+ writeable::assert_writeable_eq!(cas.locale, cas.expected);
}
}
diff --git a/vendor/icu_provider/src/response.rs b/vendor/icu_provider/src/response.rs
index 653d20a68..1ea6c8a76 100644
--- a/vendor/icu_provider/src/response.rs
+++ b/vendor/icu_provider/src/response.rs
@@ -51,10 +51,10 @@ pub struct DataResponseMetadata {
/// To transform a [`DataPayload`] to a different type backed by the same data store (cart), use
/// [`DataPayload::map_project()`] or one of its sister methods.
///
-/// # `sync` feature
+/// # Cargo feature: `sync`
///
/// By default, the payload uses non-concurrent reference counting internally, and hence is neither
-/// [`Sync`] nor [`Send`]; if these traits are required, the `sync` feature can be enabled.
+/// [`Sync`] nor [`Send`]; if these traits are required, the `sync` Cargo feature can be enabled.
///
/// # Examples
///
@@ -183,7 +183,7 @@ where
/// use std::borrow::Cow;
///
/// let local_struct = HelloWorldV1 {
- /// message: Cow::Owned("example".to_string()),
+ /// message: Cow::Owned("example".to_owned()),
/// };
///
/// let payload =
@@ -236,8 +236,8 @@ where
/// let mut payload =
/// DataPayload::<HelloWorldV1Marker>::from_static_str("Hello");
///
- /// let suffix = " World".to_string();
- /// payload.with_mut(move |s| s.message.to_mut().push_str(&suffix));
+ /// let suffix = " World";
+ /// payload.with_mut(move |s| s.message.to_mut().push_str(suffix));
///
/// assert_eq!("Hello World", payload.get().message);
/// ```
diff --git a/vendor/icu_provider/src/serde/mod.rs b/vendor/icu_provider/src/serde/mod.rs
index d32148f02..2e96b3cb3 100644
--- a/vendor/icu_provider/src/serde/mod.rs
+++ b/vendor/icu_provider/src/serde/mod.rs
@@ -94,7 +94,7 @@ impl DataPayload<BufferMarker> {
///
/// # Examples
///
- /// Requires the `deserialize_json` feature:
+ /// Requires the `deserialize_json` Cargo feature:
///
/// ```
/// use icu_provider::buf::BufferFormat;
@@ -136,16 +136,16 @@ where
{
fn load_data(&self, key: DataKey, req: DataRequest) -> Result<DataResponse<M>, DataError> {
let buffer_response = BufferProvider::load_buffer(self.0, key, req)?;
- let buffer_format = buffer_response
- .metadata
- .buffer_format
- .ok_or_else(|| DataError::custom("BufferProvider didn't set BufferFormat"))?;
+ let buffer_format = buffer_response.metadata.buffer_format.ok_or_else(|| {
+ DataError::custom("BufferProvider didn't set BufferFormat").with_req(key, req)
+ })?;
Ok(DataResponse {
metadata: buffer_response.metadata,
payload: buffer_response
.payload
.map(|p| p.into_deserialized(buffer_format))
- .transpose()?,
+ .transpose()
+ .map_err(|e| e.with_req(key, req))?,
})
}
}
@@ -165,21 +165,21 @@ where
}
}
-#[cfg(feature = "serde_json")]
+#[cfg(feature = "deserialize_json")]
impl From<serde_json::error::Error> for crate::DataError {
fn from(e: serde_json::error::Error) -> Self {
crate::DataError::custom("JSON deserialize").with_display_context(&e)
}
}
-#[cfg(feature = "bincode")]
+#[cfg(feature = "deserialize_bincode_1")]
impl From<bincode::Error> for crate::DataError {
fn from(e: bincode::Error) -> Self {
crate::DataError::custom("Bincode deserialize").with_display_context(&e)
}
}
-#[cfg(feature = "postcard")]
+#[cfg(feature = "deserialize_postcard_1")]
impl From<postcard::Error> for crate::DataError {
fn from(e: postcard::Error) -> Self {
crate::DataError::custom("Postcard deserialize").with_display_context(&e)
diff --git a/vendor/icu_provider_adapters/.cargo-checksum.json b/vendor/icu_provider_adapters/.cargo-checksum.json
index 82805760b..292541e8f 100644
--- a/vendor/icu_provider_adapters/.cargo-checksum.json
+++ b/vendor/icu_provider_adapters/.cargo-checksum.json
@@ -1 +1 @@
-{"files":{"Cargo.toml":"5ecb7cc7b9f229262dc3694db154ab479591430d0d10e03b5aed677067c16d09","LICENSE":"4ad7541d66a407234e2c84902124cef325c29f3e966353efdb800bedb8b8da21","README.md":"e6a08c2bc307b66c93de20c2c366da896f7fd3f5e5eb402edd2eeba79476b600","src/any_payload.rs":"55336b0a861be2da125a411924a3597de5593135c8ff589420237189b77311f8","src/either.rs":"aa309c26deafcb9470bb9eb15e629fc53f2fb5d7e412d1a2317bc170f0652588","src/empty.rs":"2ef71bb0eb3b81cf8cbb9f93c37bb0b7a106b4db941ffdefc8e88b944bee90d2","src/fallback/adapter.rs":"31d851e1d2adda59c06510cdfc43846a107ee706b731b3019b7c28571f0398ff","src/fallback/algorithms.rs":"bc8d17fb957f8f9ada8e13d6f0d35af248caa621441ffb3fcd273ff97e39e4a4","src/fallback/mod.rs":"ec165267f61c722300cc4a44be7561e31a5c65007f8a4c11fa074f31d768797a","src/fallback/provider.rs":"ef8a835e3ed2b7871b6f6e78ae2e73575b26adc9e8e0b5a7170c8513e7fe3269","src/filter/impls.rs":"58fcc1f03454769a3c11a92cb4b7b9f7833a0c042ea80b4e863609e2414eed0f","src/filter/mod.rs":"960e1c22d7d2323bf73c3ff6ea2d34158ff767f2a6b4fc8c40e982bf8c2dd500","src/fork/by_error.rs":"67742b78a80ff9765fd83fc28390687ed6e07f71afc0964b20221ff1f508e380","src/fork/macros.rs":"5aebb0134923fa9fa0fe7c16d2d85a1a29cf4ea49505187db56bf0bc8e984ad0","src/fork/mod.rs":"7378895128bf1ccc9de7f5675668ef922d3df7b84b04f68af4d5b49efe60341e","src/fork/predicates.rs":"314bf33144c6827cd3df05877d7c20fb64c9b18f6230e229340b8f04f4ccf4d3","src/helpers.rs":"008af3aa36ebf43ec249dd9162ff36c150fa00fe78b3065b023d59acbe218b7b","src/lib.rs":"7499b4bcb40453bc4678d6ae3febf05f5c1e351120513ddd694983e6da56f268","tests/data/langtest/de/core/helloworld@1/de.json":"5a45b1d80567de8c4ff754f7dbe20c22477c1e00a9400b38397eb034f295b8f8","tests/data/langtest/de/manifest.json":"fa2f848cff051fd12a909389fbbc44b93ae1feb92cce466cc4381f9548443ea9","tests/data/langtest/ro/core/helloworld@1/ro.json":"b6b68292746dd6bb2d92d9c08e2753db556ec9c954a3b593b0b8999df550f298","tests/data/langtest/ro/manifest.json":"fa2f848cff051fd12a909389fbbc44b93ae1feb92cce466cc4381f9548443ea9"},"package":"980c71d8a91b246ebbb97847178a4b816eea39d1d550c70ee566384555bb6545"} \ No newline at end of file
+{"files":{"Cargo.toml":"2546ca7ab46e2bd189ae3821948d10fdd46634138784d8b3c373c90ae9b1fe27","LICENSE":"4ad7541d66a407234e2c84902124cef325c29f3e966353efdb800bedb8b8da21","README.md":"e6a08c2bc307b66c93de20c2c366da896f7fd3f5e5eb402edd2eeba79476b600","src/any_payload.rs":"55336b0a861be2da125a411924a3597de5593135c8ff589420237189b77311f8","src/either.rs":"aa309c26deafcb9470bb9eb15e629fc53f2fb5d7e412d1a2317bc170f0652588","src/empty.rs":"3b55431437af04aaed5dcfc524d42c51a35bb7213274327cb1df70cb69d5a5c5","src/fallback/adapter.rs":"2e51f50215e9020f2e84a926227054e61fc001f44170bf27e1366c66097f2c83","src/fallback/algorithms.rs":"9409ad6f6f617d4433b9f6b303d131782877a0a10470533e3864b97355b9a3f1","src/fallback/mod.rs":"b2aa936b64ac0498c815683d5f3d151154fca9f962f56b172fd2582ff4b639ae","src/fallback/provider.rs":"ef8a835e3ed2b7871b6f6e78ae2e73575b26adc9e8e0b5a7170c8513e7fe3269","src/filter/impls.rs":"58fcc1f03454769a3c11a92cb4b7b9f7833a0c042ea80b4e863609e2414eed0f","src/filter/mod.rs":"960e1c22d7d2323bf73c3ff6ea2d34158ff767f2a6b4fc8c40e982bf8c2dd500","src/fork/by_error.rs":"4f89ba3b019f6ab36784577a664fece042ad2318026038cecb23c6f62fc63aa0","src/fork/macros.rs":"5aebb0134923fa9fa0fe7c16d2d85a1a29cf4ea49505187db56bf0bc8e984ad0","src/fork/mod.rs":"7378895128bf1ccc9de7f5675668ef922d3df7b84b04f68af4d5b49efe60341e","src/fork/predicates.rs":"314bf33144c6827cd3df05877d7c20fb64c9b18f6230e229340b8f04f4ccf4d3","src/helpers.rs":"008af3aa36ebf43ec249dd9162ff36c150fa00fe78b3065b023d59acbe218b7b","src/lib.rs":"7499b4bcb40453bc4678d6ae3febf05f5c1e351120513ddd694983e6da56f268","tests/data/langtest/de/core/helloworld@1/de.json":"5a45b1d80567de8c4ff754f7dbe20c22477c1e00a9400b38397eb034f295b8f8","tests/data/langtest/de/manifest.json":"fa2f848cff051fd12a909389fbbc44b93ae1feb92cce466cc4381f9548443ea9","tests/data/langtest/ro/core/helloworld@1/ro.json":"b6b68292746dd6bb2d92d9c08e2753db556ec9c954a3b593b0b8999df550f298","tests/data/langtest/ro/manifest.json":"fa2f848cff051fd12a909389fbbc44b93ae1feb92cce466cc4381f9548443ea9"},"package":"8e89bf33962b24bb48a4a21330c20c9ff17949338ea376360dd9eda2c209dca1"} \ No newline at end of file
diff --git a/vendor/icu_provider_adapters/Cargo.toml b/vendor/icu_provider_adapters/Cargo.toml
index 365a2a69b..6de64fe8b 100644
--- a/vendor/icu_provider_adapters/Cargo.toml
+++ b/vendor/icu_provider_adapters/Cargo.toml
@@ -12,7 +12,7 @@
[package]
edition = "2018"
name = "icu_provider_adapters"
-version = "1.0.0"
+version = "1.1.0"
authors = ["The ICU4X Project Developers"]
include = [
"src/**/*",
@@ -31,16 +31,16 @@ repository = "https://github.com/unicode-org/icu4x"
resolver = "2"
[dependencies.databake]
-version = "0.1.0"
+version = "0.1.3"
features = ["derive"]
optional = true
[dependencies.icu_locid]
-version = "1.0.0"
+version = "1.1.0"
features = ["zerovec"]
[dependencies.icu_provider]
-version = "1.0.0"
+version = "1.1.0"
features = ["macros"]
[dependencies.serde]
@@ -53,28 +53,23 @@ optional = true
default-features = false
[dependencies.tinystr]
-version = "0.7"
+version = "0.7.1"
features = ["zerovec"]
[dependencies.yoke]
-version = "0.6"
+version = "0.7.0"
[dependencies.zerovec]
-version = "0.9"
+version = "0.9.2"
features = ["yoke"]
-[dev-dependencies.icu_provider]
-version = "1.0.0"
-features = [
- "macros",
- "deserialize_json",
-]
+[dev-dependencies]
[features]
datagen = [
"std",
"serde",
- "databake",
+ "dep:databake",
"icu_provider/datagen",
"icu_locid/databake",
"zerovec/databake",
@@ -85,4 +80,7 @@ serde = [
"icu_locid/serde",
"icu_provider/serde",
]
-std = ["icu_locid/std"]
+std = [
+ "icu_locid/std",
+ "icu_provider/std",
+]
diff --git a/vendor/icu_provider_adapters/src/empty.rs b/vendor/icu_provider_adapters/src/empty.rs
index 31a6c42aa..85c6b9bc1 100644
--- a/vendor/icu_provider_adapters/src/empty.rs
+++ b/vendor/icu_provider_adapters/src/empty.rs
@@ -86,3 +86,26 @@ where
Err(self.error_kind.with_req(M::KEY, base_req))
}
}
+
+#[cfg(feature = "datagen")]
+impl<M> icu_provider::datagen::IterableDataProvider<M> for EmptyDataProvider
+where
+ M: KeyedDataMarker,
+{
+ fn supported_locales(&self) -> Result<alloc::vec::Vec<DataLocale>, DataError> {
+ Ok(vec![])
+ }
+}
+
+#[cfg(feature = "datagen")]
+impl<M> icu_provider::datagen::IterableDynamicDataProvider<M> for EmptyDataProvider
+where
+ M: DataMarker,
+{
+ fn supported_locales_for_key(
+ &self,
+ _: DataKey,
+ ) -> Result<alloc::vec::Vec<DataLocale>, DataError> {
+ Ok(vec![])
+ }
+}
diff --git a/vendor/icu_provider_adapters/src/fallback/adapter.rs b/vendor/icu_provider_adapters/src/fallback/adapter.rs
index 4d1f79255..f7cc10fe6 100644
--- a/vendor/icu_provider_adapters/src/fallback/adapter.rs
+++ b/vendor/icu_provider_adapters/src/fallback/adapter.rs
@@ -35,14 +35,15 @@ use crate::helpers::result_is_err_missing_data_options;
/// DataProvider::<HelloWorldV1Marker>::load(&provider, req).expect("successful with vertical fallback");
///
/// assert_eq!(
-/// "ja",
-/// response.metadata.locale.unwrap().to_string()
+/// response.metadata.locale.unwrap(),
+/// locale!("ja").into(),
/// );
/// assert_eq!(
+/// response.payload.unwrap().get().message,
/// "こんにちは世界",
-/// response.payload.unwrap().get().message
/// );
/// ```
+#[derive(Clone)]
pub struct LocaleFallbackProvider<P> {
inner: P,
fallbacker: LocaleFallbacker,
@@ -161,6 +162,11 @@ impl<P> LocaleFallbackProvider<P> {
&self.inner
}
+ /// Returns a mutable reference to the inner provider.
+ pub fn inner_mut(&mut self) -> &mut P {
+ &mut self.inner
+ }
+
/// Returns ownership of the inner provider to the caller.
pub fn into_inner(self) -> P {
self.inner
diff --git a/vendor/icu_provider_adapters/src/fallback/algorithms.rs b/vendor/icu_provider_adapters/src/fallback/algorithms.rs
index 9af52ef6d..0edc59304 100644
--- a/vendor/icu_provider_adapters/src/fallback/algorithms.rs
+++ b/vendor/icu_provider_adapters/src/fallback/algorithms.rs
@@ -207,6 +207,7 @@ mod tests {
use super::*;
use icu_locid::Locale;
use std::str::FromStr;
+ use writeable::Writeable;
struct TestCase {
input: &'static str,
@@ -355,6 +356,25 @@ mod tests {
expected_region_chain: &["hi-Latn-IN", "und-IN"],
},
TestCase {
+ input: "zh-CN",
+ requires_data: true,
+ extension_key: None,
+ fallback_supplement: None,
+ // Note: "zh-Hans" is not reachable because it is the default script for "zh".
+ // The fallback algorithm does not visit the language-script bundle when the
+ // script is the default for the language
+ expected_language_chain: &["zh-CN", "zh"],
+ expected_region_chain: &["zh-CN", "und-CN"],
+ },
+ TestCase {
+ input: "zh-TW",
+ requires_data: true,
+ extension_key: None,
+ fallback_supplement: None,
+ expected_language_chain: &["zh-TW", "zh-Hant-TW", "zh-Hant"],
+ expected_region_chain: &["zh-TW", "und-TW"],
+ },
+ TestCase {
input: "yue-HK",
requires_data: true,
extension_key: None,
@@ -396,10 +416,10 @@ mod tests {
};
let locale = DataLocale::from(Locale::from_str(cas.input).unwrap());
let mut it = key_fallbacker.fallback_for(locale);
- for expected in expected_chain {
+ for &expected in expected_chain {
assert_eq!(
expected,
- &it.get().to_string(),
+ &*it.get().write_to_string(),
"{:?} ({:?})",
cas.input,
priority
@@ -408,7 +428,7 @@ mod tests {
}
assert_eq!(
"und",
- it.get().to_string(),
+ &*it.get().write_to_string(),
"{:?} ({:?})",
cas.input,
priority
diff --git a/vendor/icu_provider_adapters/src/fallback/mod.rs b/vendor/icu_provider_adapters/src/fallback/mod.rs
index 6ec636a09..81adad41c 100644
--- a/vendor/icu_provider_adapters/src/fallback/mod.rs
+++ b/vendor/icu_provider_adapters/src/fallback/mod.rs
@@ -15,6 +15,7 @@
//! Run the locale fallback algorithm:
//!
//! ```
+//! use icu_locid::locale;
//! use icu_provider_adapters::fallback::LocaleFallbacker;
//! use icu_provider::prelude::*;
//!
@@ -26,20 +27,20 @@
//! let key_fallbacker = fallbacker.for_config(Default::default());
//!
//! // Set up the fallback iterator.
-//! let mut fallback_iterator = key_fallbacker.fallback_for(icu_locid::locale!("hi-Latn-IN").into());
+//! let mut fallback_iterator = key_fallbacker.fallback_for(DataLocale::from(locale!("hi-Latn-IN")));
//!
//! // Run the algorithm and check the results.
-//! assert_eq!(fallback_iterator.get().to_string(), "hi-Latn-IN");
+//! assert_eq!(fallback_iterator.get(), &DataLocale::from(locale!("hi-Latn-IN")));
//! fallback_iterator.step();
-//! assert_eq!(fallback_iterator.get().to_string(), "hi-Latn");
+//! assert_eq!(fallback_iterator.get(), &DataLocale::from(locale!("hi-Latn")));
//! fallback_iterator.step();
-//! assert_eq!(fallback_iterator.get().to_string(), "en-IN");
+//! assert_eq!(fallback_iterator.get(), &DataLocale::from(locale!("en-IN")));
//! fallback_iterator.step();
-//! assert_eq!(fallback_iterator.get().to_string(), "en-001");
+//! assert_eq!(fallback_iterator.get(), &DataLocale::from(locale!("en-001")));
//! fallback_iterator.step();
-//! assert_eq!(fallback_iterator.get().to_string(), "en");
+//! assert_eq!(fallback_iterator.get(), &DataLocale::from(locale!("en")));
//! fallback_iterator.step();
-//! assert_eq!(fallback_iterator.get().to_string(), "und");
+//! assert_eq!(fallback_iterator.get(), &DataLocale::from(locale!("und")));
//! ```
use icu_locid::extensions::unicode::{Key, Value};
@@ -67,6 +68,7 @@ pub struct LocaleFallbackConfig {
/// Retain the language and script subtags until the final step:
///
/// ```
+ /// use icu_locid::locale;
/// use icu_provider::prelude::*;
/// use icu_provider::FallbackPriority;
/// use icu_provider_adapters::fallback::LocaleFallbackConfig;
@@ -80,21 +82,25 @@ pub struct LocaleFallbackConfig {
/// config.priority = FallbackPriority::Language;
/// let key_fallbacker = fallbacker.for_config(config);
/// let mut fallback_iterator = key_fallbacker
- /// .fallback_for(icu_locid::locale!("ca-ES-valencia").into());
+ /// .fallback_for(DataLocale::from(locale!("ca-ES-valencia")));
///
/// // Run the algorithm and check the results.
- /// assert_eq!(fallback_iterator.get().to_string(), "ca-ES-valencia");
+ /// assert_eq!(
+ /// fallback_iterator.get(),
+ /// &DataLocale::from(locale!("ca-ES-valencia"))
+ /// );
/// fallback_iterator.step();
- /// assert_eq!(fallback_iterator.get().to_string(), "ca-ES");
+ /// assert_eq!(fallback_iterator.get(), &DataLocale::from(locale!("ca-ES")));
/// fallback_iterator.step();
- /// assert_eq!(fallback_iterator.get().to_string(), "ca");
+ /// assert_eq!(fallback_iterator.get(), &DataLocale::from(locale!("ca")));
/// fallback_iterator.step();
- /// assert_eq!(fallback_iterator.get().to_string(), "und");
+ /// assert_eq!(fallback_iterator.get(), &DataLocale::from(locale!("und")));
/// ```
///
/// Retain the region subtag until the final step:
///
/// ```
+ /// use icu_locid::locale;
/// use icu_provider::prelude::*;
/// use icu_provider::FallbackPriority;
/// use icu_provider_adapters::fallback::LocaleFallbackConfig;
@@ -108,18 +114,27 @@ pub struct LocaleFallbackConfig {
/// config.priority = FallbackPriority::Region;
/// let key_fallbacker = fallbacker.for_config(config);
/// let mut fallback_iterator = key_fallbacker
- /// .fallback_for(icu_locid::locale!("ca-ES-valencia").into());
+ /// .fallback_for(DataLocale::from(locale!("ca-ES-valencia")));
///
/// // Run the algorithm and check the results.
- /// assert_eq!(fallback_iterator.get().to_string(), "ca-ES-valencia");
+ /// assert_eq!(
+ /// fallback_iterator.get(),
+ /// &DataLocale::from(locale!("ca-ES-valencia"))
+ /// );
/// fallback_iterator.step();
- /// assert_eq!(fallback_iterator.get().to_string(), "ca-ES");
+ /// assert_eq!(fallback_iterator.get(), &DataLocale::from(locale!("ca-ES")));
/// fallback_iterator.step();
- /// assert_eq!(fallback_iterator.get().to_string(), "und-ES-valencia");
+ /// assert_eq!(
+ /// fallback_iterator.get(),
+ /// &DataLocale::from(locale!("und-ES-valencia"))
+ /// );
/// fallback_iterator.step();
- /// assert_eq!(fallback_iterator.get().to_string(), "und-ES");
+ /// assert_eq!(
+ /// fallback_iterator.get(),
+ /// &DataLocale::from(locale!("und-ES"))
+ /// );
/// fallback_iterator.step();
- /// assert_eq!(fallback_iterator.get().to_string(), "und");
+ /// assert_eq!(fallback_iterator.get(), &DataLocale::from(locale!("und")));
/// ```
pub priority: FallbackPriority,
/// An extension keyword to retain during locale fallback.
@@ -127,6 +142,7 @@ pub struct LocaleFallbackConfig {
/// # Examples
///
/// ```
+ /// use icu_locid::locale;
/// use icu_provider::prelude::*;
/// use icu_provider_adapters::fallback::LocaleFallbackConfig;
/// use icu_provider_adapters::fallback::LocaleFallbacker;
@@ -139,16 +155,19 @@ pub struct LocaleFallbackConfig {
/// config.extension_key = Some(icu_locid::extensions_unicode_key!("nu"));
/// let key_fallbacker = fallbacker.for_config(config);
/// let mut fallback_iterator = key_fallbacker
- /// .fallback_for(icu_locid::locale!("ar-EG-u-nu-latn").into());
+ /// .fallback_for(DataLocale::from(locale!("ar-EG-u-nu-latn")));
///
/// // Run the algorithm and check the results.
- /// assert_eq!(fallback_iterator.get().to_string(), "ar-EG-u-nu-latn");
+ /// assert_eq!(
+ /// fallback_iterator.get(),
+ /// &DataLocale::from(locale!("ar-EG-u-nu-latn"))
+ /// );
/// fallback_iterator.step();
- /// assert_eq!(fallback_iterator.get().to_string(), "ar-EG");
+ /// assert_eq!(fallback_iterator.get(), &DataLocale::from(locale!("ar-EG")));
/// fallback_iterator.step();
- /// assert_eq!(fallback_iterator.get().to_string(), "ar");
+ /// assert_eq!(fallback_iterator.get(), &DataLocale::from(locale!("ar")));
/// fallback_iterator.step();
- /// assert_eq!(fallback_iterator.get().to_string(), "und");
+ /// assert_eq!(fallback_iterator.get(), &DataLocale::from(locale!("und")));
/// ```
pub extension_key: Option<Key>,
/// Fallback supplement data key to customize fallback rules.
@@ -162,6 +181,7 @@ pub struct LocaleFallbackConfig {
/// # Examples
///
/// ```
+ /// use icu_locid::locale;
/// use icu_provider::prelude::*;
/// use icu_provider::FallbackPriority;
/// use icu_provider::FallbackSupplement;
@@ -178,17 +198,23 @@ pub struct LocaleFallbackConfig {
/// config.fallback_supplement = Some(FallbackSupplement::Collation);
/// let key_fallbacker = fallbacker.for_config(config);
/// let mut fallback_iterator =
- /// key_fallbacker.fallback_for(icu_locid::locale!("yue-HK").into());
+ /// key_fallbacker.fallback_for(DataLocale::from(locale!("yue-HK")));
///
/// // Run the algorithm and check the results.
/// // TODO(#1964): add "zh" as a target.
- /// assert_eq!(fallback_iterator.get().to_string(), "yue-HK");
+ /// assert_eq!(
+ /// fallback_iterator.get(),
+ /// &DataLocale::from(locale!("yue-HK"))
+ /// );
/// fallback_iterator.step();
- /// assert_eq!(fallback_iterator.get().to_string(), "yue");
+ /// assert_eq!(fallback_iterator.get(), &DataLocale::from(locale!("yue")));
/// fallback_iterator.step();
- /// assert_eq!(fallback_iterator.get().to_string(), "zh-Hant");
+ /// assert_eq!(
+ /// fallback_iterator.get(),
+ /// &DataLocale::from(locale!("zh-Hant"))
+ /// );
/// fallback_iterator.step();
- /// assert_eq!(fallback_iterator.get().to_string(), "und");
+ /// assert_eq!(fallback_iterator.get(), &DataLocale::from(locale!("und")));
/// ```
pub fallback_supplement: Option<FallbackSupplement>,
}
@@ -303,6 +329,7 @@ impl LocaleFallbacker {
/// # Examples
///
/// ```
+ /// use icu_locid::locale;
/// use icu_provider::prelude::*;
/// use icu_provider_adapters::fallback::LocaleFallbacker;
/// use std::borrow::Cow;
@@ -323,14 +350,17 @@ impl LocaleFallbacker {
/// .expect("data");
/// let key_fallbacker = fallbacker.for_key(FooV1Marker::KEY);
/// let mut fallback_iterator =
- /// key_fallbacker.fallback_for(icu_locid::locale!("en-GB").into());
+ /// key_fallbacker.fallback_for(DataLocale::from(locale!("en-GB")));
///
/// // Run the algorithm and check the results.
- /// assert_eq!(fallback_iterator.get().to_string(), "en-GB");
+ /// assert_eq!(fallback_iterator.get(), &DataLocale::from(locale!("en-GB")));
/// fallback_iterator.step();
- /// assert_eq!(fallback_iterator.get().to_string(), "und-GB");
+ /// assert_eq!(
+ /// fallback_iterator.get(),
+ /// &DataLocale::from(locale!("und-GB"))
+ /// );
/// fallback_iterator.step();
- /// assert_eq!(fallback_iterator.get().to_string(), "und");
+ /// assert_eq!(fallback_iterator.get(), &DataLocale::from(locale!("und")));
/// ```
///
/// [`DataRequestMetadata`]: icu_provider::DataRequestMetadata
diff --git a/vendor/icu_provider_adapters/src/fork/by_error.rs b/vendor/icu_provider_adapters/src/fork/by_error.rs
index 5069229fa..b3badb147 100644
--- a/vendor/icu_provider_adapters/src/fork/by_error.rs
+++ b/vendor/icu_provider_adapters/src/fork/by_error.rs
@@ -32,6 +32,11 @@ impl<P0, P1, F> ForkByErrorProvider<P0, P1, F> {
(&self.0, &self.1)
}
+ /// Returns mutable references to the inner providers.
+ pub fn inner_mut(&mut self) -> (&mut P0, &mut P1) {
+ (&mut self.0, &mut self.1)
+ }
+
/// Returns ownership of the inner providers to the caller.
pub fn into_inner(self) -> (P0, P1) {
(self.0, self.1)
@@ -142,10 +147,20 @@ impl<P, F> MultiForkByErrorProvider<P, F> {
&self.providers
}
+ /// Exposes a mutable vector of providers to a closure so it can be mutated.
+ pub fn with_inner_mut(&mut self, f: impl FnOnce(&mut Vec<P>)) {
+ f(&mut self.providers)
+ }
+
/// Returns ownership of the inner providers to the caller.
pub fn into_inner(self) -> Vec<P> {
self.providers
}
+
+ /// Adds an additional child provider.
+ pub fn push(&mut self, provider: P) {
+ self.providers.push(provider);
+ }
}
impl<P, F> BufferProvider for MultiForkByErrorProvider<P, F>
@@ -158,15 +173,16 @@ where
key: DataKey,
req: DataRequest,
) -> Result<DataResponse<BufferMarker>, DataError> {
+ let mut last_error = DataErrorKind::MissingDataKey.with_key(key);
for provider in self.providers.iter() {
let result = provider.load_buffer(key, req);
match result {
Ok(ok) => return Ok(ok),
Err(err) if !self.predicate.test(key, Some(req), err) => return Err(err),
- _ => (),
+ Err(err) => last_error = err,
};
}
- Err(DataErrorKind::MissingDataKey.with_key(key))
+ Err(last_error)
}
}
@@ -176,15 +192,16 @@ where
F: ForkByErrorPredicate,
{
fn load_any(&self, key: DataKey, req: DataRequest) -> Result<AnyResponse, DataError> {
+ let mut last_error = DataErrorKind::MissingDataKey.with_key(key);
for provider in self.providers.iter() {
let result = provider.load_any(key, req);
match result {
Ok(ok) => return Ok(ok),
Err(err) if !self.predicate.test(key, Some(req), err) => return Err(err),
- _ => (),
+ Err(err) => last_error = err,
};
}
- Err(DataErrorKind::MissingDataKey.with_key(key))
+ Err(last_error)
}
}
@@ -195,15 +212,16 @@ where
F: ForkByErrorPredicate,
{
fn load_data(&self, key: DataKey, req: DataRequest) -> Result<DataResponse<M>, DataError> {
+ let mut last_error = DataErrorKind::MissingDataKey.with_key(key);
for provider in self.providers.iter() {
let result = provider.load_data(key, req);
match result {
Ok(ok) => return Ok(ok),
Err(err) if !self.predicate.test(key, Some(req), err) => return Err(err),
- _ => (),
+ Err(err) => last_error = err,
};
}
- Err(DataErrorKind::MissingDataKey.with_key(key))
+ Err(last_error)
}
}
@@ -215,15 +233,16 @@ where
F: ForkByErrorPredicate,
{
fn supported_locales_for_key(&self, key: DataKey) -> Result<Vec<DataLocale>, DataError> {
+ let mut last_error = DataErrorKind::MissingDataKey.with_key(key);
for provider in self.providers.iter() {
let result = provider.supported_locales_for_key(key);
match result {
Ok(ok) => return Ok(ok),
Err(err) if !self.predicate.test(key, None, err) => return Err(err),
- _ => (),
+ Err(err) => last_error = err,
};
}
- Err(DataErrorKind::MissingDataKey.with_key(key))
+ Err(last_error)
}
}
@@ -240,6 +259,7 @@ where
key: DataKey,
mut from: DataPayload<MFrom>,
) -> Result<DataPayload<MTo>, (DataPayload<MFrom>, DataError)> {
+ let mut last_error = DataErrorKind::MissingDataKey.with_key(key);
for provider in self.providers.iter() {
let result = provider.convert(key, from);
match result {
@@ -250,10 +270,11 @@ where
return Err((returned, err));
}
from = returned;
+ last_error = err;
}
};
}
- Err((from, DataErrorKind::MissingDataKey.with_key(key)))
+ Err((from, last_error))
}
}
diff --git a/vendor/icu_provider_macros/.cargo-checksum.json b/vendor/icu_provider_macros/.cargo-checksum.json
index 21caa79bb..67fb422f7 100644
--- a/vendor/icu_provider_macros/.cargo-checksum.json
+++ b/vendor/icu_provider_macros/.cargo-checksum.json
@@ -1 +1 @@
-{"files":{"Cargo.toml":"5c2656c9d6a8256494d0d58648ba09110cb602fa81b59580e758695704299664","LICENSE":"4ad7541d66a407234e2c84902124cef325c29f3e966353efdb800bedb8b8da21","README.md":"f9f95075851c9c3b7d0559c25794ebcad5dee957c7fb27c343418a3324f15b8a","src/lib.rs":"e3f9092950ee1db12dbbd5b3fea39aead909896ee317f5b38a6442c209e37d03","src/tests.rs":"729a551b69f368100b142a3260573307b653931228cdc803eeffbb81910134f7"},"package":"38cf6f5b65cf81f0b4298da647101acbfe6ae0e25263f92bd7a22597e9d6d606"} \ No newline at end of file
+{"files":{"Cargo.toml":"8f35af4529f0a10bf10dc6ba2ad5fffcfb78d29c78d1e3d4e1d737839480f7a1","LICENSE":"4ad7541d66a407234e2c84902124cef325c29f3e966353efdb800bedb8b8da21","README.md":"f9f95075851c9c3b7d0559c25794ebcad5dee957c7fb27c343418a3324f15b8a","src/lib.rs":"c6675b847fb5a2fd0a686460598c4e76b55eff51df792da0386be9b02156db5f","src/tests.rs":"c0f93af328a3e15e93ca5914a14adacf73274eff821f2f849c5b96ce884547b1"},"package":"9ddb07844c2ffc4c28840e799e9e54ff054393cf090740decf25624e9d94b93a"} \ No newline at end of file
diff --git a/vendor/icu_provider_macros/Cargo.toml b/vendor/icu_provider_macros/Cargo.toml
index 1f2350f36..289aad854 100644
--- a/vendor/icu_provider_macros/Cargo.toml
+++ b/vendor/icu_provider_macros/Cargo.toml
@@ -12,7 +12,7 @@
[package]
edition = "2018"
name = "icu_provider_macros"
-version = "1.0.0"
+version = "1.1.0"
authors = ["The ICU4X Project Developers"]
include = [
"src/**/*",
diff --git a/vendor/icu_provider_macros/src/lib.rs b/vendor/icu_provider_macros/src/lib.rs
index e43cebfce..8d39f0f87 100644
--- a/vendor/icu_provider_macros/src/lib.rs
+++ b/vendor/icu_provider_macros/src/lib.rs
@@ -129,7 +129,7 @@ fn data_struct_impl(attr: AttributeArgs, input: DeriveInput) -> TokenStream2 {
.find(|a| a.path.is_ident("databake"))
.map(|a| {
quote! {
- #[derive(Default, databake::Bake)]
+ #[derive(databake::Bake)]
#a
}
})
diff --git a/vendor/icu_provider_macros/src/tests.rs b/vendor/icu_provider_macros/src/tests.rs
index 51411852b..c7ca63530 100644
--- a/vendor/icu_provider_macros/src/tests.rs
+++ b/vendor/icu_provider_macros/src/tests.rs
@@ -144,7 +144,7 @@ fn test_databake() {
),
quote!(
#[doc = "Marker type for [`FooV1`]: \"demo/bar@1\"\n\n- Fallback priority: language (default)\n- Extension keyword: none (default)"]
- #[derive(Default, databake::Bake)]
+ #[derive(databake::Bake)]
#[databake(path = test::path)]
pub struct BarV1Marker;
impl icu_provider::DataMarker for BarV1Marker {
diff --git a/vendor/itoa/.cargo-checksum.json b/vendor/itoa/.cargo-checksum.json
index 5c464a6c5..5ab0879bb 100644
--- a/vendor/itoa/.cargo-checksum.json
+++ b/vendor/itoa/.cargo-checksum.json
@@ -1 +1 @@
-{"files":{"Cargo.toml":"895c75445c305a4d56486a2ca7312a85a486469492286e277f41601be418bcd4","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"23f18e03dc49df91622fe2a76176497404e46ced8a715d9d2b67a7446571cca3","README.md":"4bc11375d5c1c2c7cf4988b94d44c0f1fe8cdf2d68755fef127cd5ba0d70b939","benches/bench.rs":"636f3093bd461210ad3063289d455f90669c4a1be3273bcd30898de39f02c641","src/lib.rs":"9438cd2cfcf95e4a6719816580e209c3873beb75074ca756118f8723d336141b","src/udiv128.rs":"d28c1872c37ee2185931babcb20a221b8706a5aa8abc4963419763888023ff17","tests/test.rs":"f7404fc5f7cd1bdaf74a3b64a70d5b30586241ddc1ce2c82bd1b564999fcce0e"},"package":"4217ad341ebadf8d8e724e264f13e593e0648f5b3e94b3896a5df283be015ecc"} \ No newline at end of file
+{"files":{"Cargo.toml":"bb96760f2d45e86313dbec93a3210e5073c4ee74116097bb5ca45ba9c5b049a6","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"23f18e03dc49df91622fe2a76176497404e46ced8a715d9d2b67a7446571cca3","README.md":"48573443063fa4e0786c3b46f42b6efd1f171c6b73408a64afc1b34de89f31fe","benches/bench.rs":"636f3093bd461210ad3063289d455f90669c4a1be3273bcd30898de39f02c641","src/lib.rs":"da13f0d5dcba3bb2971f67b6856ea6f2e3cbdc31d47f7042d7f131b08bb7de85","src/udiv128.rs":"d28c1872c37ee2185931babcb20a221b8706a5aa8abc4963419763888023ff17","tests/test.rs":"f7404fc5f7cd1bdaf74a3b64a70d5b30586241ddc1ce2c82bd1b564999fcce0e"},"package":"fad582f4b9e86b6caa621cabeb0963332d92eea04729ab12892c2533951e6440"} \ No newline at end of file
diff --git a/vendor/itoa/Cargo.toml b/vendor/itoa/Cargo.toml
index bab03ecf7..86c10b644 100644
--- a/vendor/itoa/Cargo.toml
+++ b/vendor/itoa/Cargo.toml
@@ -13,7 +13,7 @@
edition = "2018"
rust-version = "1.36"
name = "itoa"
-version = "1.0.4"
+version = "1.0.5"
authors = ["David Tolnay <dtolnay@gmail.com>"]
exclude = [
"performance.png",
diff --git a/vendor/itoa/README.md b/vendor/itoa/README.md
index 914d1ff30..5728fb726 100644
--- a/vendor/itoa/README.md
+++ b/vendor/itoa/README.md
@@ -4,7 +4,7 @@ itoa
[<img alt="github" src="https://img.shields.io/badge/github-dtolnay/itoa-8da0cb?style=for-the-badge&labelColor=555555&logo=github" height="20">](https://github.com/dtolnay/itoa)
[<img alt="crates.io" src="https://img.shields.io/crates/v/itoa.svg?style=for-the-badge&color=fc8d62&logo=rust" height="20">](https://crates.io/crates/itoa)
[<img alt="docs.rs" src="https://img.shields.io/badge/docs.rs-itoa-66c2a5?style=for-the-badge&labelColor=555555&logo=docs.rs" height="20">](https://docs.rs/itoa)
-[<img alt="build status" src="https://img.shields.io/github/workflow/status/dtolnay/itoa/CI/master?style=for-the-badge" height="20">](https://github.com/dtolnay/itoa/actions?query=branch%3Amaster)
+[<img alt="build status" src="https://img.shields.io/github/actions/workflow/status/dtolnay/itoa/ci.yml?branch=master&style=for-the-badge" height="20">](https://github.com/dtolnay/itoa/actions?query=branch%3Amaster)
This crate provides a fast conversion of integer primitives to decimal strings.
The implementation comes straight from [libcore] but avoids the performance
diff --git a/vendor/itoa/src/lib.rs b/vendor/itoa/src/lib.rs
index 7c3616e51..168407f06 100644
--- a/vendor/itoa/src/lib.rs
+++ b/vendor/itoa/src/lib.rs
@@ -30,7 +30,7 @@
//!
//! ![performance](https://raw.githubusercontent.com/dtolnay/itoa/master/performance.png)
-#![doc(html_root_url = "https://docs.rs/itoa/1.0.4")]
+#![doc(html_root_url = "https://docs.rs/itoa/1.0.5")]
#![no_std]
#![allow(
clippy::cast_lossless,
diff --git a/vendor/jobserver/.cargo-checksum.json b/vendor/jobserver/.cargo-checksum.json
index 09c948a8e..734fd6db9 100644
--- a/vendor/jobserver/.cargo-checksum.json
+++ b/vendor/jobserver/.cargo-checksum.json
@@ -1 +1 @@
-{"files":{"Cargo.toml":"9d5e9bc3aa927124431914287d2830ff03ca5a80931a3b44b3f057b92d09e850","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"378f5840b258e2779c39418f3f2d7b2ba96f1c7917dd6be0713f88305dbda397","README.md":"07d8d79f8f6b6a94321fe8db78d26ed409de47cee49290947bd6bbfa29d05e9c","src/lib.rs":"891d9c9cf2d75eee30c02ffa8ae7fa8fb1f7675dccddb0cc79a067e1a87a9850","src/unix.rs":"5802f031e80295c5498a2ddb95b5ee6e39b7294f25b35075302fb978b8d4c409","src/wasm.rs":"bb67f97bccd0b0c1762917de342d721e319a3a204604ab1517285c59b5e2a369","src/windows.rs":"f886175abbf75ff45ea3fc09396bbcc3048e7daf732ed78149377f7b8e9148b2","tests/client-of-myself.rs":"ca09bf398f69df4bac1730999e954dbbc3faf3c6512678c136e0938e7e9cd0ab","tests/client.rs":"64547b780edce5ebcd397db1160fd86baab030c530c6976fa013bca9f07a85ff","tests/helper.rs":"c0e6c00eaf849295d8ec23e374690b6645c0f7d993e91abf7ad53ac960f71762","tests/make-as-a-client.rs":"ec09a7cdbf78d6c3b16f26de15766c4bd62d44a913ada6b86b66e067e6c484ba","tests/server.rs":"9a260f1302ae4908479df0bd34b46edb9d2b8b9b3dbc3e2b6666296d9e1b2b84"},"package":"af25a77299a7f711a01975c35a6a424eb6862092cc2d6c72c4ed6cbc56dfc1fa"} \ No newline at end of file
+{"files":{"Cargo.toml":"0f712c94e98313fc5833521e1dc0c42a57e5603ea54d1e05a004b95b52fb39b7","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"378f5840b258e2779c39418f3f2d7b2ba96f1c7917dd6be0713f88305dbda397","README.md":"07d8d79f8f6b6a94321fe8db78d26ed409de47cee49290947bd6bbfa29d05e9c","src/lib.rs":"be789fda33a51375fcc87e4bf9bf1256930d718f698f700bbec5e335c83e0659","src/unix.rs":"1e1efc5cd1f381fea83bdaaee474ad3530b396305a9bbdc9da08b0c36baced31","src/wasm.rs":"65d3d8ed45972b4459581505906481d32a50d2f7514cd7ff2a595fceeaa672f0","src/windows.rs":"8e0fa3ab29757d809d4fa03c8101870435ce8c4ceaebe491df3144d62fe0aaaf","tests/client-of-myself.rs":"ca09bf398f69df4bac1730999e954dbbc3faf3c6512678c136e0938e7e9cd0ab","tests/client.rs":"d4745cdd650c86d19bc81f6c9b35df498996deffb86ae6412ad040af96a19183","tests/helper.rs":"c0e6c00eaf849295d8ec23e374690b6645c0f7d993e91abf7ad53ac960f71762","tests/make-as-a-client.rs":"8be1f3fef1e9e65c7904dbaa04364bf0f44e9deab84a2a247a5a94b5cf0df9bc","tests/server.rs":"da15bf12e1df1883f660892b996c9e0d92485aace3f7b50ee70c4a8e6deae8da"},"package":"936cfd212a0155903bcbc060e316fb6cc7cbf2e1907329391ebadc1fe0ce77c2"} \ No newline at end of file
diff --git a/vendor/jobserver/Cargo.toml b/vendor/jobserver/Cargo.toml
index d9a878266..938371008 100644
--- a/vendor/jobserver/Cargo.toml
+++ b/vendor/jobserver/Cargo.toml
@@ -3,21 +3,23 @@
# When uploading crates to the registry Cargo will automatically
# "normalize" Cargo.toml files for maximal compatibility
# with all versions of Cargo and also rewrite `path` dependencies
-# to registry (e.g., crates.io) dependencies
+# to registry (e.g., crates.io) dependencies.
#
-# If you believe there's an error in this file please file an
-# issue against the rust-lang/cargo repository. If you're
-# editing this file be aware that the upstream Cargo.toml
-# will likely look very different (and much more reasonable)
+# If you are reading this file be aware that the original Cargo.toml
+# will likely look very different (and much more reasonable).
+# See Cargo.toml.orig for the original contents.
[package]
edition = "2018"
name = "jobserver"
-version = "0.1.24"
+version = "0.1.26"
authors = ["Alex Crichton <alex@alexcrichton.com>"]
-description = "An implementation of the GNU make jobserver for Rust\n"
+description = """
+An implementation of the GNU make jobserver for Rust
+"""
homepage = "https://github.com/alexcrichton/jobserver-rs"
documentation = "https://docs.rs/jobserver"
+readme = "README.md"
license = "MIT/Apache-2.0"
repository = "https://github.com/alexcrichton/jobserver-rs"
@@ -43,19 +45,21 @@ harness = false
[[test]]
name = "helper"
path = "tests/helper.rs"
+
[dev-dependencies.futures]
version = "0.1"
[dev-dependencies.num_cpus]
version = "1.0"
-[dev-dependencies.tempdir]
-version = "0.3"
+[dev-dependencies.tempfile]
+version = "3"
[dev-dependencies.tokio-core]
version = "0.1"
[dev-dependencies.tokio-process]
version = "0.2"
+
[target."cfg(unix)".dependencies.libc]
version = "0.2.50"
diff --git a/vendor/jobserver/src/lib.rs b/vendor/jobserver/src/lib.rs
index 72c02c120..cd0cdd749 100644
--- a/vendor/jobserver/src/lib.rs
+++ b/vendor/jobserver/src/lib.rs
@@ -11,7 +11,10 @@
//! The jobserver implementation can be found in [detail online][docs] but
//! basically boils down to a cross-process semaphore. On Unix this is
//! implemented with the `pipe` syscall and read/write ends of a pipe and on
-//! Windows this is implemented literally with IPC semaphores.
+//! Windows this is implemented literally with IPC semaphores. Starting from
+//! GNU `make` version 4.4, named pipe becomes the default way in communication
+//! on Unix. This crate also supports that feature in the sense of inheriting
+//! and forwarding the correct environment.
//!
//! The jobserver protocol in `make` also dictates when tokens are acquired to
//! run child work, and clients using this crate should take care to implement
@@ -208,7 +211,7 @@ impl Client {
/// with `CLOEXEC` so they're not automatically inherited by spawned
/// children.
///
- /// # Unsafety
+ /// # Safety
///
/// This function is `unsafe` to call on Unix specifically as it
/// transitively requires usage of the `from_raw_fd` function, which is
@@ -273,6 +276,19 @@ impl Client {
})
}
+ /// Returns amount of tokens in the read-side pipe.
+ ///
+ /// # Return value
+ ///
+ /// Number of bytes available to be read from the jobserver pipe
+ ///
+ /// # Errors
+ ///
+ /// Underlying errors from the ioctl will be passed up.
+ pub fn available(&self) -> io::Result<usize> {
+ self.inner.available()
+ }
+
/// Configures a child process to have access to this client's jobserver as
/// well.
///
@@ -290,13 +306,41 @@ impl Client {
///
/// On platforms other than Unix and Windows this panics.
pub fn configure(&self, cmd: &mut Command) {
+ cmd.env("CARGO_MAKEFLAGS", &self.mflags_env());
+ self.inner.configure(cmd);
+ }
+
+ /// Configures a child process to have access to this client's jobserver as
+ /// well.
+ ///
+ /// This function is required to be called to ensure that a jobserver is
+ /// properly inherited to a child process. If this function is *not* called
+ /// then this `Client` will not be accessible in the child process. In other
+ /// words, if not called, then `Client::from_env` will return `None` in the
+ /// child process (or the equivalent of `Child::from_env` that `make` uses).
+ ///
+ /// ## Platform-specific behavior
+ ///
+ /// On Unix and Windows this will clobber the `CARGO_MAKEFLAGS`,
+ /// `MAKEFLAGS` and `MFLAGS` environment variables for the child process,
+ /// and on Unix this will also allow the two file descriptors for
+ /// this client to be inherited to the child.
+ ///
+ /// On platforms other than Unix and Windows this panics.
+ pub fn configure_make(&self, cmd: &mut Command) {
+ let value = self.mflags_env();
+ cmd.env("CARGO_MAKEFLAGS", &value);
+ cmd.env("MAKEFLAGS", &value);
+ cmd.env("MFLAGS", &value);
+ self.inner.configure(cmd);
+ }
+
+ fn mflags_env(&self) -> String {
let arg = self.inner.string_arg();
// Older implementations of make use `--jobserver-fds` and newer
// implementations use `--jobserver-auth`, pass both to try to catch
// both implementations.
- let value = format!("-j --jobserver-fds={0} --jobserver-auth={0}", arg);
- cmd.env("CARGO_MAKEFLAGS", &value);
- self.inner.configure(cmd);
+ format!("-j --jobserver-fds={0} --jobserver-auth={0}", arg)
}
/// Converts this `Client` into a helper thread to deal with a blocking
diff --git a/vendor/jobserver/src/unix.rs b/vendor/jobserver/src/unix.rs
index d69ae88e3..e4b143505 100644
--- a/vendor/jobserver/src/unix.rs
+++ b/vendor/jobserver/src/unix.rs
@@ -1,8 +1,11 @@
use libc::c_int;
-use std::fs::File;
+
+use std::fs::{File, OpenOptions};
use std::io::{self, Read, Write};
use std::mem;
+use std::mem::MaybeUninit;
use std::os::unix::prelude::*;
+use std::path::{Path, PathBuf};
use std::process::Command;
use std::ptr;
use std::sync::{Arc, Once};
@@ -10,9 +13,11 @@ use std::thread::{self, Builder, JoinHandle};
use std::time::Duration;
#[derive(Debug)]
-pub struct Client {
- read: File,
- write: File,
+pub enum Client {
+ /// `--jobserver-auth=R,W`
+ Pipe { read: File, write: File },
+ /// `--jobserver-auth=fifo:PATH`
+ Fifo { file: File, path: PathBuf },
}
#[derive(Debug)]
@@ -21,13 +26,26 @@ pub struct Acquired {
}
impl Client {
- pub fn new(limit: usize) -> io::Result<Client> {
+ pub fn new(mut limit: usize) -> io::Result<Client> {
let client = unsafe { Client::mk()? };
+
// I don't think the character written here matters, but I could be
// wrong!
- for _ in 0..limit {
- (&client.write).write_all(&[b'|'])?;
+ const BUFFER: [u8; 128] = [b'|'; 128];
+
+ let mut write = client.write();
+
+ set_nonblocking(write.as_raw_fd(), true)?;
+
+ while limit > 0 {
+ let n = limit.min(BUFFER.len());
+
+ write.write_all(&BUFFER[..n])?;
+ limit -= n;
}
+
+ set_nonblocking(write.as_raw_fd(), false)?;
+
Ok(client)
}
@@ -64,6 +82,31 @@ impl Client {
}
pub unsafe fn open(s: &str) -> Option<Client> {
+ Client::from_fifo(s).or_else(|| Client::from_pipe(s))
+ }
+
+ /// `--jobserver-auth=fifo:PATH`
+ fn from_fifo(s: &str) -> Option<Client> {
+ let mut parts = s.splitn(2, ':');
+ if parts.next().unwrap() != "fifo" {
+ return None;
+ }
+ let path = match parts.next() {
+ Some(p) => Path::new(p),
+ None => return None,
+ };
+ let file = match OpenOptions::new().read(true).write(true).open(path) {
+ Ok(f) => f,
+ Err(_) => return None,
+ };
+ Some(Client::Fifo {
+ file,
+ path: path.into(),
+ })
+ }
+
+ /// `--jobserver-auth=R,W`
+ unsafe fn from_pipe(s: &str) -> Option<Client> {
let mut parts = s.splitn(2, ',');
let read = parts.next().unwrap();
let write = match parts.next() {
@@ -97,12 +140,28 @@ impl Client {
}
unsafe fn from_fds(read: c_int, write: c_int) -> Client {
- Client {
+ Client::Pipe {
read: File::from_raw_fd(read),
write: File::from_raw_fd(write),
}
}
+ /// Gets the read end of our jobserver client.
+ fn read(&self) -> &File {
+ match self {
+ Client::Pipe { read, .. } => read,
+ Client::Fifo { file, .. } => file,
+ }
+ }
+
+ /// Gets the write end of our jobserver client.
+ fn write(&self) -> &File {
+ match self {
+ Client::Pipe { write, .. } => write,
+ Client::Fifo { file, .. } => file,
+ }
+ }
+
pub fn acquire(&self) -> io::Result<Acquired> {
// Ignore interrupts and keep trying if that happens
loop {
@@ -137,11 +196,12 @@ impl Client {
// to shut us down, so we otherwise punt all errors upwards.
unsafe {
let mut fd: libc::pollfd = mem::zeroed();
- fd.fd = self.read.as_raw_fd();
+ let mut read = self.read();
+ fd.fd = read.as_raw_fd();
fd.events = libc::POLLIN;
loop {
let mut buf = [0];
- match (&self.read).read(&mut buf) {
+ match read.read(&mut buf) {
Ok(1) => return Ok(Some(Acquired { byte: buf[0] })),
Ok(_) => {
return Err(io::Error::new(
@@ -179,7 +239,7 @@ impl Client {
// always quickly release a token). If that turns out to not be the
// case we'll get an error anyway!
let byte = data.map(|d| d.byte).unwrap_or(b'+');
- match (&self.write).write(&[byte])? {
+ match self.write().write(&[byte])? {
1 => Ok(()),
_ => Err(io::Error::new(
io::ErrorKind::Other,
@@ -189,16 +249,31 @@ impl Client {
}
pub fn string_arg(&self) -> String {
- format!("{},{}", self.read.as_raw_fd(), self.write.as_raw_fd())
+ match self {
+ Client::Pipe { read, write } => format!("{},{}", read.as_raw_fd(), write.as_raw_fd()),
+ Client::Fifo { path, .. } => format!("fifo:{}", path.to_str().unwrap()),
+ }
+ }
+
+ pub fn available(&self) -> io::Result<usize> {
+ let mut len = MaybeUninit::<c_int>::uninit();
+ cvt(unsafe { libc::ioctl(self.read().as_raw_fd(), libc::FIONREAD, len.as_mut_ptr()) })?;
+ Ok(unsafe { len.assume_init() } as usize)
}
pub fn configure(&self, cmd: &mut Command) {
+ match self {
+ // We `File::open`ed it when inheriting from environment,
+ // so no need to set cloexec for fifo.
+ Client::Fifo { .. } => return,
+ Client::Pipe { .. } => {}
+ };
// Here we basically just want to say that in the child process
// we'll configure the read/write file descriptors to *not* be
// cloexec, so they're inherited across the exec and specified as
// integers through `string_arg` above.
- let read = self.read.as_raw_fd();
- let write = self.write.as_raw_fd();
+ let read = self.read().as_raw_fd();
+ let write = self.write().as_raw_fd();
unsafe {
cmd.pre_exec(move || {
set_cloexec(read, false)?;
@@ -224,7 +299,14 @@ pub(crate) fn spawn_helper(
let mut err = None;
USR1_INIT.call_once(|| unsafe {
let mut new: libc::sigaction = mem::zeroed();
- new.sa_sigaction = sigusr1_handler as usize;
+ #[cfg(target_os = "aix")]
+ {
+ new.sa_union.__su_sigaction = sigusr1_handler;
+ }
+ #[cfg(not(target_os = "aix"))]
+ {
+ new.sa_sigaction = sigusr1_handler as usize;
+ }
new.sa_flags = libc::SA_SIGINFO as _;
if libc::sigaction(libc::SIGUSR1, &new, ptr::null_mut()) != 0 {
err = Some(io::Error::last_os_error());
@@ -322,6 +404,16 @@ fn set_cloexec(fd: c_int, set: bool) -> io::Result<()> {
}
}
+fn set_nonblocking(fd: c_int, set: bool) -> io::Result<()> {
+ let status_flag = if set { libc::O_NONBLOCK } else { 0 };
+
+ unsafe {
+ cvt(libc::fcntl(fd, libc::F_SETFL, status_flag))?;
+ }
+
+ Ok(())
+}
+
fn cvt(t: c_int) -> io::Result<c_int> {
if t == -1 {
Err(io::Error::last_os_error())
diff --git a/vendor/jobserver/src/wasm.rs b/vendor/jobserver/src/wasm.rs
index b88a9d952..3793bd67c 100644
--- a/vendor/jobserver/src/wasm.rs
+++ b/vendor/jobserver/src/wasm.rs
@@ -59,6 +59,11 @@ impl Client {
);
}
+ pub fn available(&self) -> io::Result<usize> {
+ let lock = self.inner.count.lock().unwrap_or_else(|e| e.into_inner());
+ Ok(*lock)
+ }
+
pub fn configure(&self, _cmd: &mut Command) {
unreachable!();
}
diff --git a/vendor/jobserver/src/windows.rs b/vendor/jobserver/src/windows.rs
index d795c1cee..6791efea4 100644
--- a/vendor/jobserver/src/windows.rs
+++ b/vendor/jobserver/src/windows.rs
@@ -170,6 +170,26 @@ impl Client {
self.name.clone()
}
+ pub fn available(&self) -> io::Result<usize> {
+ // Can't read value of a semaphore on Windows, so
+ // try to acquire without sleeping, since we can find out the
+ // old value on release. If acquisiton fails, then available is 0.
+ unsafe {
+ let r = WaitForSingleObject(self.sem.0, 0);
+ if r != WAIT_OBJECT_0 {
+ Ok(0)
+ } else {
+ let mut prev: LONG = 0;
+ let r = ReleaseSemaphore(self.sem.0, 1, &mut prev);
+ if r != 0 {
+ Ok(prev as usize + 1)
+ } else {
+ Err(io::Error::last_os_error())
+ }
+ }
+ }
+ }
+
pub fn configure(&self, _cmd: &mut Command) {
// nothing to do here, we gave the name of our semaphore to the
// child above
diff --git a/vendor/jobserver/tests/client.rs b/vendor/jobserver/tests/client.rs
index 7f319c09c..2516b8ccf 100644
--- a/vendor/jobserver/tests/client.rs
+++ b/vendor/jobserver/tests/client.rs
@@ -10,7 +10,6 @@ use std::thread;
use futures::future::{self, Future};
use futures::stream::{self, Stream};
use jobserver::Client;
-use tempdir::TempDir;
use tokio_core::reactor::Core;
use tokio_process::CommandExt;
@@ -128,7 +127,7 @@ fn main() {
None => true,
})
.map(|test| {
- let td = t!(TempDir::new("foo"));
+ let td = t!(tempfile::tempdir());
let makefile = format!(
"\
all: export TEST_TO_RUN={}
diff --git a/vendor/jobserver/tests/make-as-a-client.rs b/vendor/jobserver/tests/make-as-a-client.rs
index e530211b0..4faac5b88 100644
--- a/vendor/jobserver/tests/make-as-a-client.rs
+++ b/vendor/jobserver/tests/make-as-a-client.rs
@@ -5,7 +5,6 @@ use std::net::{TcpListener, TcpStream};
use std::process::Command;
use jobserver::Client;
-use tempdir::TempDir;
macro_rules! t {
($e:expr) => {
@@ -37,7 +36,7 @@ fn main() {
}
let c = t!(Client::new(1));
- let td = TempDir::new("foo").unwrap();
+ let td = tempfile::tempdir().unwrap();
let prog = env::var("MAKE").unwrap_or_else(|_| "make".to_string());
diff --git a/vendor/jobserver/tests/server.rs b/vendor/jobserver/tests/server.rs
index fcdd12ca2..70ea218fc 100644
--- a/vendor/jobserver/tests/server.rs
+++ b/vendor/jobserver/tests/server.rs
@@ -8,7 +8,6 @@ use std::sync::Arc;
use std::thread;
use jobserver::Client;
-use tempdir::TempDir;
macro_rules! t {
($e:expr) => {
@@ -35,6 +34,30 @@ fn server_multiple() {
}
#[test]
+fn server_available() {
+ let c = t!(Client::new(10));
+ assert_eq!(c.available().unwrap(), 10);
+ let a = c.acquire().unwrap();
+ assert_eq!(c.available().unwrap(), 9);
+ drop(a);
+ assert_eq!(c.available().unwrap(), 10);
+}
+
+#[test]
+fn server_none_available() {
+ let c = t!(Client::new(2));
+ assert_eq!(c.available().unwrap(), 2);
+ let a = c.acquire().unwrap();
+ assert_eq!(c.available().unwrap(), 1);
+ let b = c.acquire().unwrap();
+ assert_eq!(c.available().unwrap(), 0);
+ drop(a);
+ assert_eq!(c.available().unwrap(), 1);
+ drop(b);
+ assert_eq!(c.available().unwrap(), 2);
+}
+
+#[test]
fn server_blocks() {
let c = t!(Client::new(1));
let a = c.acquire().unwrap();
@@ -56,7 +79,7 @@ fn server_blocks() {
#[test]
fn make_as_a_single_thread_client() {
let c = t!(Client::new(1));
- let td = TempDir::new("foo").unwrap();
+ let td = tempfile::tempdir().unwrap();
let prog = env::var("MAKE").unwrap_or_else(|_| "make".to_string());
let mut cmd = Command::new(prog);
@@ -110,7 +133,7 @@ foo
#[test]
fn make_as_a_multi_thread_client() {
let c = t!(Client::new(1));
- let td = TempDir::new("foo").unwrap();
+ let td = tempfile::tempdir().unwrap();
let prog = env::var("MAKE").unwrap_or_else(|_| "make".to_string());
let mut cmd = Command::new(prog);
diff --git a/vendor/libc/.cargo-checksum.json b/vendor/libc/.cargo-checksum.json
index 979f0dec2..e90619c72 100644
--- a/vendor/libc/.cargo-checksum.json
+++ b/vendor/libc/.cargo-checksum.json
@@ -1 +1 @@
-{"files":{"CONTRIBUTING.md":"bdc90b52cf803faac96e594069a86dd8ea150d5ba7fb3e6cadfc08dac4c7b0ce","Cargo.toml":"89e8938bf82dadf7854b0831c879ef1c66708a3917b0c48079aadbc2855b18b8","LICENSE-APACHE":"62c7a1e35f56406896d7aa7ca52d0cc0d272ac022b5d2796e7d6905db8a3636a","LICENSE-MIT":"a8d47ff51ca256f56a8932dba07660672dbfe3004257ca8de708aac1415937a1","README.md":"776affa26b66843a2b4f1a1c8f88d92f6461b74568911450fea717e9db6f877b","build.rs":"cecfa3f926ab4a9c87cd59cc0d687f98eceb6035b0dde185152e5206d090f8d0","rustfmt.toml":"eaa2ea84fc1ba0359b77680804903e07bb38d257ab11986b95b158e460f787b2","src/fixed_width_ints.rs":"7f986e5f5e68d25ef04d386fd2f640e8be8f15427a8d4a458ea01d26b8dca0ca","src/fuchsia/aarch64.rs":"378776a9e40766154a54c94c2a7b4675b5c302a38e6e42da99e67bfbaee60e56","src/fuchsia/align.rs":"ae1cf8f011a99737eabeb14ffff768e60f13b13363d7646744dbb0f443dab3d6","src/fuchsia/mod.rs":"e54e72e15cf4ab2df88da9ac3b69fa12e918b0bcfeadc81843b2a838b43d9547","src/fuchsia/no_align.rs":"303f3f1b255e0088b5715094353cf00476131d8e94e6aebb3f469557771c8b8a","src/fuchsia/x86_64.rs":"93a3632b5cf67d2a6bcb7dc0a558605252d5fe689e0f38d8aa2ec5852255ac87","src/hermit/aarch64.rs":"86048676e335944c37a63d0083d0f368ae10ceccefeed9debb3bbe08777fc682","src/hermit/mod.rs":"d3bfce41e4463d4be8020a2d063c9bfa8b665f45f1cc6cbf3163f5d01e7cb21f","src/hermit/x86_64.rs":"ab832b7524e5fb15c49ff7431165ab1a37dc4667ae0b58e8306f4c539bfa110c","src/lib.rs":"ce753ef318b300bbd441feabdd77d00322dfb6ce9eee8c78a38afe02b57aa4c0","src/macros.rs":"b457eb028b8e8ab3c24bb7292b874ad4e491edbb83594f6a3da024df5348c088","src/psp.rs":"dd31aabd46171d474ec5828372e28588935120e7355c90c105360d8fa9264c1c","src/sgx.rs":"16a95cdefc81c5ee00d8353a60db363c4cc3e0f75abcd5d0144723f2a306ed1b","src/solid/aarch64.rs":"a726e47f324adf73a4a0b67a2c183408d0cad105ae66acf36db37a42ab7f8707","src/solid/arm.rs":"e39a4f74ebbef3b97b8c95758ad741123d84ed3eb48d9cf4f1f4872097fc27fe","src/solid/mod.rs":"5f4151dca5132e4b4e4c23ab9737e12856dddbdc0ca3f7dbc004328ef3c8acde","src/switch.rs":"9da3dd39b3de45a7928789926e8572d00e1e11a39e6f7289a1349aadce90edba","src/unix/align.rs":"2cdc7c826ef7ae61f5171c5ae8c445a743d86f1a7f2d9d7e4ceeec56d6874f65","src/unix/bsd/apple/b32/align.rs":"ec833a747866fe19ca2d9b4d3c9ff0385faba5edf4bd0d15fa68884c40b0e26c","src/unix/bsd/apple/b32/mod.rs":"2546ad3eb6aecb95f916648bc63264117c92b4b4859532b34cb011e4c75a5a72","src/unix/bsd/apple/b64/aarch64/align.rs":"e8eb38d064b5fefec6f37d42873820a0483e7c758ed336cc59a7155455ca89c9","src/unix/bsd/apple/b64/aarch64/mod.rs":"44c217a4f263afe7a97435de9323d20a96c37836f899ca0925306d4b7e073c27","src/unix/bsd/apple/b64/align.rs":"ec833a747866fe19ca2d9b4d3c9ff0385faba5edf4bd0d15fa68884c40b0e26c","src/unix/bsd/apple/b64/mod.rs":"f5e278a1af7fb358891d1c9be4eb7e815aaca0c5cb738d0c3604ba2208a856f7","src/unix/bsd/apple/b64/x86_64/align.rs":"ec833a747866fe19ca2d9b4d3c9ff0385faba5edf4bd0d15fa68884c40b0e26c","src/unix/bsd/apple/b64/x86_64/mod.rs":"8c87c5855038aae5d433c8f5eb3b29b0a175879a0245342b3bfd83bdf4cfd936","src/unix/bsd/apple/mod.rs":"1cc76b056d5925aedae04ead411057dc5c6c9bd3948609fdb30164ac1fb6565e","src/unix/bsd/freebsdlike/dragonfly/errno.rs":"8295b8bb0dfd38d2cdb4d9192cdeeb534cc6c3b208170e64615fa3e0edb3e578","src/unix/bsd/freebsdlike/dragonfly/mod.rs":"8986a8c79bcadfbdb58ec1a72e1aff8ce9b341c9392d7b0b7449bddf6db59058","src/unix/bsd/freebsdlike/freebsd/aarch64.rs":"6c8e216385f53a4bf5f171749b57602fc34a4e4b160a44ca31c058cb0c8a2126","src/unix/bsd/freebsdlike/freebsd/arm.rs":"59d6a670eea562fb87686e243e0a84603d29a2028a3d4b3f99ccc01bd04d2f47","src/unix/bsd/freebsdlike/freebsd/freebsd11/b64.rs":"9808d152c1196aa647f1b0f0cf84dac8c930da7d7f897a44975545e3d9d17681","src/unix/bsd/freebsdlike/freebsd/freebsd11/mod.rs":"badda6f0f7666f38345b1f4ca78817a47bc92bbdcdc3a1377f376f4e08c316e5","src/unix/bsd/freebsdlike/freebsd/freebsd12/b64.rs":"61cbe45f8499bedb168106b686d4f8239472f25c7553b069eec2afe197ff2df6","src/unix/bsd/freebsdlike/freebsd/freebsd12/mod.rs":"327700c5668be863f1fea205c82b0402e2936b883df63dda677716c30a50a284","src/unix/bsd/freebsdlike/freebsd/freebsd12/x86_64.rs":"2df36a7f122f6d6e5753cfb4d22e915cc80f6bc91c0161b3daae55a481bfd052","src/unix/bsd/freebsdlike/freebsd/freebsd13/b64.rs":"61cbe45f8499bedb168106b686d4f8239472f25c7553b069eec2afe197ff2df6","src/unix/bsd/freebsdlike/freebsd/freebsd13/mod.rs":"7f689e9a944c919834ec852b30c224f98e14b4b4087571adefeea5abad5d6374","src/unix/bsd/freebsdlike/freebsd/freebsd13/x86_64.rs":"2df36a7f122f6d6e5753cfb4d22e915cc80f6bc91c0161b3daae55a481bfd052","src/unix/bsd/freebsdlike/freebsd/freebsd14/b64.rs":"61cbe45f8499bedb168106b686d4f8239472f25c7553b069eec2afe197ff2df6","src/unix/bsd/freebsdlike/freebsd/freebsd14/mod.rs":"9b6fa1c3f5217f9482e0bed3bd0ea2905cdf56d628307cea48e49d8e00a6b09d","src/unix/bsd/freebsdlike/freebsd/freebsd14/x86_64.rs":"2df36a7f122f6d6e5753cfb4d22e915cc80f6bc91c0161b3daae55a481bfd052","src/unix/bsd/freebsdlike/freebsd/mod.rs":"26bda8cf730ab4868523a6ed7c513f51885cad30cdd02da905ff35b597576415","src/unix/bsd/freebsdlike/freebsd/powerpc.rs":"9ca3f82f88974e6db5569f2d76a5a3749b248a31747a6c0da5820492bdfeca42","src/unix/bsd/freebsdlike/freebsd/powerpc64.rs":"2dae3ecc87eac3b11657aa98915def55fc4b5c0de11fe26aae23329a54628a9a","src/unix/bsd/freebsdlike/freebsd/riscv64.rs":"fa4bed4c58cad24ba3395941c7fa6b11e089551a04714f9561078e400f5b2b62","src/unix/bsd/freebsdlike/freebsd/x86.rs":"c5005e3249eb7c93cfbac72a9e9272320d80ce7983da990ceb05a447f59a02c5","src/unix/bsd/freebsdlike/freebsd/x86_64/align.rs":"0e1f69a88fca1c32874b1daf5db3d446fefbe518dca497f096cc9168c39dde70","src/unix/bsd/freebsdlike/freebsd/x86_64/mod.rs":"51e4dd0c8ae247bb652feda5adad9333ea3bb30c750c3a3935e0b0e47d7803eb","src/unix/bsd/freebsdlike/mod.rs":"bd80ce2ff628ed5eaa856ebe8b6a8fb0e89d1c9728040b9ee6b967beb4bcf3a7","src/unix/bsd/mod.rs":"6f7e4f0affa04e5c26375875389a9891f69930bb56842cf20526aad3a0f64299","src/unix/bsd/netbsdlike/mod.rs":"34f60d73631f3c59936c87db1f62ddb8f693901c3cb199f7f370882e84d509fa","src/unix/bsd/netbsdlike/netbsd/aarch64.rs":"65dcb58d11e8d8028401a9d07ca3eb4cb4f053e04249cc877353449d84ccc4cb","src/unix/bsd/netbsdlike/netbsd/arm.rs":"58cdbb70b0d6f536551f0f3bb3725d2d75c4690db12c26c034e7d6ec4a924452","src/unix/bsd/netbsdlike/netbsd/mod.rs":"107a4aa396b8383c66e0ace2f941450b4b69146558cdc4d9fbe33eeab51760f1","src/unix/bsd/netbsdlike/netbsd/powerpc.rs":"ee7ff5d89d0ed22f531237b5059aa669df93a3b5c489fa641465ace8d405bf41","src/unix/bsd/netbsdlike/netbsd/sparc64.rs":"9489f4b3e4566f43bb12dfb92238960613dac7f6a45cc13068a8d152b902d7d9","src/unix/bsd/netbsdlike/netbsd/x86.rs":"20692320e36bfe028d1a34d16fe12ca77aa909cb02bda167376f98f1a09aefe7","src/unix/bsd/netbsdlike/netbsd/x86_64.rs":"1afe5ef46b14397cdd68664b5b232e4f5b035b6db1d4cf411c899d51ebca9f30","src/unix/bsd/netbsdlike/openbsd/aarch64.rs":"dd91931d373b7ecaf6e2de25adadee10d16fa9b12c2cbacdff3eb291e1ba36af","src/unix/bsd/netbsdlike/openbsd/arm.rs":"01580d261bc6447bb327a0d982181b7bdabfa066cee65a30373d3ced729ad307","src/unix/bsd/netbsdlike/openbsd/mips64.rs":"8532a189ae10c7d668d9d4065da8b05d124e09bd39442c9f74a7f231c43eca48","src/unix/bsd/netbsdlike/openbsd/mod.rs":"38b7d65a86701a75a9047a3ef3b006f09ffbb33ab2312174bcee889efb74e100","src/unix/bsd/netbsdlike/openbsd/powerpc.rs":"01580d261bc6447bb327a0d982181b7bdabfa066cee65a30373d3ced729ad307","src/unix/bsd/netbsdlike/openbsd/powerpc64.rs":"1dd5449dd1fd3d51e30ffdeeaece91d0aaf05c710e0ac699fecc5461cfa2c28e","src/unix/bsd/netbsdlike/openbsd/riscv64.rs":"1dd5449dd1fd3d51e30ffdeeaece91d0aaf05c710e0ac699fecc5461cfa2c28e","src/unix/bsd/netbsdlike/openbsd/sparc64.rs":"d04fd287afbaa2c5df9d48c94e8374a532a3ba491b424ddf018270c7312f4085","src/unix/bsd/netbsdlike/openbsd/x86.rs":"6f7f5c4fde2a2259eb547890cbd86570cea04ef85347d7569e94e679448bec87","src/unix/bsd/netbsdlike/openbsd/x86_64.rs":"d31db31630289c85af3339dbe357998a21ca584cbae31607448fe2cf7675a4e1","src/unix/haiku/b32.rs":"a2efdbf7158a6da341e1db9176b0ab193ba88b449616239ed95dced11f54d87b","src/unix/haiku/b64.rs":"ff8115367d3d7d354f792d6176dfaaa26353f57056197b563bf4681f91ff7985","src/unix/haiku/mod.rs":"14171bbff41ad7f112198064b80f7b86a78c2c36c689d5cc04a748f2186c6bf3","src/unix/haiku/native.rs":"dbfcbf4954a79d1df2ff58e0590bbcb8c57dfc7a32392aa73ee4726b66bd6cc8","src/unix/haiku/x86_64.rs":"3ec3aeeb7ed208b8916f3e32d42bfd085ff5e16936a1a35d9a52789f043b7237","src/unix/hermit/aarch64.rs":"86048676e335944c37a63d0083d0f368ae10ceccefeed9debb3bbe08777fc682","src/unix/hermit/mod.rs":"859814f5df89e28fd4b345db399d181e11e7ed413841b6ff703a1fcbdbf013ae","src/unix/hermit/x86_64.rs":"ab832b7524e5fb15c49ff7431165ab1a37dc4667ae0b58e8306f4c539bfa110c","src/unix/linux_like/android/b32/arm.rs":"433c1530f602cc5ed26610c58055dde0c4ceea5e00150063b24ddc60768332a4","src/unix/linux_like/android/b32/mod.rs":"7c173e0375119bf06a3081652faede95e5bcd6858e7576b7533d037978737c8f","src/unix/linux_like/android/b32/x86/align.rs":"812914e4241df82e32b12375ca3374615dc3a4bdd4cf31f0423c5815320c0dab","src/unix/linux_like/android/b32/x86/mod.rs":"8388bd3a0fcb5636bf965eee6dc95ae6860b85a2b555b387c868aa4d4e01ec89","src/unix/linux_like/android/b64/aarch64/align.rs":"2179c3b1608fa4bf68840482bfc2b2fa3ee2faf6fcae3770f9e505cddca35c7b","src/unix/linux_like/android/b64/aarch64/int128.rs":"1735f6f5c56770d20dd426442f09724d9b2052b46a7cd82f23f3288a4a7276de","src/unix/linux_like/android/b64/aarch64/mod.rs":"ef230d49fd0d182adf2dae6f8e10babf18d72259d65980bf1c4c2dc8a4f84501","src/unix/linux_like/android/b64/mod.rs":"71e4fcbe952bfa4a5f9022f3972e906917b38f729b9d8ef57cd5d179104894ac","src/unix/linux_like/android/b64/riscv64/align.rs":"0bf138f84e5327d8339bcd4adf071a6832b516445e597552c82bbd881095e3a8","src/unix/linux_like/android/b64/riscv64/mod.rs":"80e9f93fed838a48b4e2e8d77b95c72cfd7c0647bcce63851555c5ad16dad143","src/unix/linux_like/android/b64/x86_64/align.rs":"7169d07a9fd4716f7512719aec9fda5d8bed306dc0720ffc1b21696c9951e3c6","src/unix/linux_like/android/b64/x86_64/mod.rs":"e10d19bea39f719723ab6666a5ddbd378b6958769441c5904629e1df173b1dc2","src/unix/linux_like/android/mod.rs":"fbfcd29a13b58a89841ea23737b45d1a3d69e8ec72bd168755297c4d0eb701f3","src/unix/linux_like/emscripten/align.rs":"86c95cbed7a7161b1f23ee06843e7b0e2340ad92b2cb86fe2a8ef3e0e8c36216","src/unix/linux_like/emscripten/mod.rs":"6ef4652dfb94e3c58aed5133ece982ad30569d46b6b1054552cd61905fa61690","src/unix/linux_like/emscripten/no_align.rs":"0128e4aa721a9902754828b61b5ec7d8a86619983ed1e0544a85d35b1051fad6","src/unix/linux_like/linux/align.rs":"d6c259942c8e843373accd180fc8f4f45f03544dfd21b93a8d02641ead3ef63e","src/unix/linux_like/linux/arch/generic/mod.rs":"46dd6634e564fb1b60c8a2d1018ef8f365d1a8ed26f162c99528922d06d14134","src/unix/linux_like/linux/arch/mips/mod.rs":"2d166054a586bb4bf6e4a4ba35f7574907b217225eff8f1a43adc4277e142460","src/unix/linux_like/linux/arch/mod.rs":"466a29622e47c6c7f1500682b2eb17f5566dd81b322cd6348f0fdd355cec593a","src/unix/linux_like/linux/arch/powerpc/mod.rs":"3f6da7b0fa7b394c7d4eea2bb3caa7a7729ab0d6c1491fef02206a912c41b815","src/unix/linux_like/linux/arch/sparc/mod.rs":"91593ec0440f1dd8f8e612028f432c44c14089286e2aca50e10511ab942db8c3","src/unix/linux_like/linux/gnu/align.rs":"e4a3c27fe20a57b8d612c34cb05bc70646edb5cec7251957315afa53a7b9f936","src/unix/linux_like/linux/gnu/b32/arm/align.rs":"6ec0eb3ee93f7ae99fd714b4deabfb5e97fbcefd8c26f5a45fb8e7150899cdeb","src/unix/linux_like/linux/gnu/b32/arm/mod.rs":"5bd3f6b3484e049ddaac95f411b0d82cbf1cd28e6a5defbc927bd917f5f7d299","src/unix/linux_like/linux/gnu/b32/m68k/align.rs":"8faa92f77a9232c035418d45331774e64a9a841d99c91791570a203bf2b45bcb","src/unix/linux_like/linux/gnu/b32/m68k/mod.rs":"a2a0a9400dae44086ebf579e0448e0676d4a3214d1ae7d13a024857251e23b6b","src/unix/linux_like/linux/gnu/b32/mips/align.rs":"429fb5e005cb7143602d430098b6ebfb7d360685b194f333dfd587472ae954ee","src/unix/linux_like/linux/gnu/b32/mips/mod.rs":"6b9a5dac6f937ddc1453e808e3c43502c87143332df9e43ac64fb8b1eda6c116","src/unix/linux_like/linux/gnu/b32/mod.rs":"8da281da578cdee972e952b118b903b370320897a7e335342a15e1359864bef2","src/unix/linux_like/linux/gnu/b32/powerpc.rs":"5c5d90326b54b57b98eff4745fe7a3fb02f053b2dc782241a73e807b491936a3","src/unix/linux_like/linux/gnu/b32/riscv32/align.rs":"d321491612be8d5c61b6ec2dc0111beb3a22e58803f99cd37543efe86621b119","src/unix/linux_like/linux/gnu/b32/riscv32/mod.rs":"5e7c1e29aeb82fc422f45b73fb0cf3d13d0902300f9150d2755a9074f8d96999","src/unix/linux_like/linux/gnu/b32/sparc/align.rs":"21adbed27df73e2d1ed934aaf733a643003d7baf2bde9c48ea440895bcca6d41","src/unix/linux_like/linux/gnu/b32/sparc/mod.rs":"80894eece66e9348f45d1b07ad37c757ea694bbd10ed49d3f920b34e9f51a9a3","src/unix/linux_like/linux/gnu/b32/x86/align.rs":"e4bafdc4a519a7922a81b37a62bbfd1177a2f620890eef8f1fbc47162e9eb413","src/unix/linux_like/linux/gnu/b32/x86/mod.rs":"c703cc5e9de2dc31d9e5831bfb6f354d6e3518b2ae02263f68a9a70f1c0167e2","src/unix/linux_like/linux/gnu/b64/aarch64/align.rs":"ea39d5fd8ca5a71314127d1e1f542bca34ac566eac9a95662076d91ea4bee548","src/unix/linux_like/linux/gnu/b64/aarch64/ilp32.rs":"21a21503ef2e095f4371044915d4bfb07a8578011cb5c713cd9f45947b0b5730","src/unix/linux_like/linux/gnu/b64/aarch64/int128.rs":"1735f6f5c56770d20dd426442f09724d9b2052b46a7cd82f23f3288a4a7276de","src/unix/linux_like/linux/gnu/b64/aarch64/lp64.rs":"e78c3cd197f44832338b414d1a9bc0d194f44c74db77bd7bf830c1fff62b2690","src/unix/linux_like/linux/gnu/b64/aarch64/mod.rs":"666beae35371cb54a4ad091764e0e3ca4983d5205179c119a8ff97d3ae301869","src/unix/linux_like/linux/gnu/b64/loongarch64/align.rs":"6616c38bf8cab53034dce9f968adae8fb7771334445a93876d000cfd08f117a8","src/unix/linux_like/linux/gnu/b64/loongarch64/mod.rs":"17e9478b6a5830f6b8f6bea4ccab712cfd1972cdfb43b97408a068e4ea924106","src/unix/linux_like/linux/gnu/b64/mips64/align.rs":"7169d07a9fd4716f7512719aec9fda5d8bed306dc0720ffc1b21696c9951e3c6","src/unix/linux_like/linux/gnu/b64/mips64/mod.rs":"80b4b97a41564290c510e68a1fb20cfd8424206f010e71a596f12877de886a71","src/unix/linux_like/linux/gnu/b64/mod.rs":"3c6555f30a7a8852757b31a542ea73fb6a16a6e27e838397e819278ad56e57a4","src/unix/linux_like/linux/gnu/b64/powerpc64/align.rs":"e29c4868bbecfa4a6cd8a2ad06193f3bbc78a468cc1dc9df83f002f1268130d9","src/unix/linux_like/linux/gnu/b64/powerpc64/mod.rs":"a595e37c2325ceb40ef66c634bd3c255ad184a1d70ff8025e98a075f0ec67704","src/unix/linux_like/linux/gnu/b64/riscv64/align.rs":"d321491612be8d5c61b6ec2dc0111beb3a22e58803f99cd37543efe86621b119","src/unix/linux_like/linux/gnu/b64/riscv64/mod.rs":"ef4b13477ffd8532fb6705ca3fa63a1f13e8d19ee39b083c5355dfce430c1a5b","src/unix/linux_like/linux/gnu/b64/s390x.rs":"788fde4fa1919859cc028b59da31de00449edd2b2c1530ae76134beac418b73c","src/unix/linux_like/linux/gnu/b64/sparc64/align.rs":"e29c4868bbecfa4a6cd8a2ad06193f3bbc78a468cc1dc9df83f002f1268130d9","src/unix/linux_like/linux/gnu/b64/sparc64/mod.rs":"c4fa0ede3f78b21a9982667922cccd0681bee3cb6d42208ea9958f65e93d6308","src/unix/linux_like/linux/gnu/b64/x86_64/align.rs":"62e822478356db4a73b6bbd1b36d825b893939ab4b308ec11b0578bcc4b49769","src/unix/linux_like/linux/gnu/b64/x86_64/mod.rs":"e37e0421290b152fe508883181c41225e09dd5452a6b085e8d807b3b54823028","src/unix/linux_like/linux/gnu/b64/x86_64/not_x32.rs":"c1b6345ce14f67d1b2e2f7f2c0ff9a074c07acbd348df69cb4558bda8c8fb9ae","src/unix/linux_like/linux/gnu/b64/x86_64/x32.rs":"3f4d2aeadb7d2620cad09564abdbfc5cf02eeb5a27f2bab8a4e9b4bdbdb258a5","src/unix/linux_like/linux/gnu/mod.rs":"e31aa4bd147c83d05dcd13baca4b9f676320a7713ff50de08b51d0c88f8241a3","src/unix/linux_like/linux/gnu/no_align.rs":"9cd223135de75315840ff9c3fd5441ba1cb632b96b5c85a76f8316c86653db25","src/unix/linux_like/linux/mod.rs":"ddd008ff6304dca5d6fe9b452eb7a69745098bce47834d0999abdedd5978c2b3","src/unix/linux_like/linux/musl/b32/arm/align.rs":"3e8ac052c1043764776b54c93ba4260e061df998631737a897d9d47d54f7b80c","src/unix/linux_like/linux/musl/b32/arm/mod.rs":"f5b217a93f99c2852f7fd1459f529798372fa7df84ee0cfd3d8cdd5b2021b8cf","src/unix/linux_like/linux/musl/b32/hexagon.rs":"226a8b64ce9c75abbbee6d2dceb0b44f7b6c750c4102ebd4d015194afee6666e","src/unix/linux_like/linux/musl/b32/mips/align.rs":"429fb5e005cb7143602d430098b6ebfb7d360685b194f333dfd587472ae954ee","src/unix/linux_like/linux/musl/b32/mips/mod.rs":"16a7a03d998a5db11be9ee81525c7faec4623383260e8bc125b1c53a050fde75","src/unix/linux_like/linux/musl/b32/mod.rs":"580e27c5ce3344df686f1ffc08fdfa2c282d1ceb623d778c50d210d4bd65ec7e","src/unix/linux_like/linux/musl/b32/powerpc.rs":"dc52adc264c34bce80753d6bd064e8fc4b8237fa1e5c5315ccb6c72df74c2813","src/unix/linux_like/linux/musl/b32/riscv32/align.rs":"efd2accf33b87de7c7547903359a5da896edc33cd6c719552c7474b60d4a5d48","src/unix/linux_like/linux/musl/b32/riscv32/mod.rs":"e57dc5562553aab6d0765e0ec266254aa52975f8757bfe97e0c6028fa7d5d37c","src/unix/linux_like/linux/musl/b32/x86/align.rs":"08e77fbd7435d7dec2ff56932433bece3f02e47ce810f89004a275a86d39cbe1","src/unix/linux_like/linux/musl/b32/x86/mod.rs":"7a1586f77bb693f0b319ec720c35963da056287fc42f8e2ccf1d5b2bcccf4fd6","src/unix/linux_like/linux/musl/b64/aarch64/align.rs":"6ba32725d24d7d8e6aa111f3b57aafa318f83b606abe96561329151829821133","src/unix/linux_like/linux/musl/b64/aarch64/int128.rs":"1735f6f5c56770d20dd426442f09724d9b2052b46a7cd82f23f3288a4a7276de","src/unix/linux_like/linux/musl/b64/aarch64/mod.rs":"31e75179cbb4e26425b3f5b052e358f593153da662884655e60801d852e55dc2","src/unix/linux_like/linux/musl/b64/mips64.rs":"9a5d29f666332bb056d0e2951e9de989aa1dc016075f009db3f2f628e0cdda8c","src/unix/linux_like/linux/musl/b64/mod.rs":"8c10627bd582cb272514e7350ae4743a65d489356eae039d2e7e55cd533fbbc8","src/unix/linux_like/linux/musl/b64/powerpc64.rs":"455dc0ffa55afc1db6ffaf461f6f2a7b49d31658bfebe0bb4efac5967a6f956c","src/unix/linux_like/linux/musl/b64/riscv64/align.rs":"d321491612be8d5c61b6ec2dc0111beb3a22e58803f99cd37543efe86621b119","src/unix/linux_like/linux/musl/b64/riscv64/mod.rs":"42d4b6d36807f37759094a732a321080cccdf498b174d632cebba147051de294","src/unix/linux_like/linux/musl/b64/s390x.rs":"d8a4fdfea0960ec284cae4facb8b0fb342e8aa41544cffacdcaf08c5a92a43f8","src/unix/linux_like/linux/musl/b64/x86_64/align.rs":"77309276ad7a42cbe59ca381f23590b7a143aded05555b34a5b307b808cbca6e","src/unix/linux_like/linux/musl/b64/x86_64/mod.rs":"7a877cd23b64be66d28e6b8dddae32d59a88d69115637539daf19381f4e39330","src/unix/linux_like/linux/musl/mod.rs":"8d8b50a0bf7ec53bd4d2ea92e8bfae14529f0beb3f22a65b55623f7086fee8ac","src/unix/linux_like/linux/no_align.rs":"da2a8721becaaaa528781f97f5d9aae6a982ae5d4f5f6d2ffc0150bed72319b3","src/unix/linux_like/linux/non_exhaustive.rs":"181a05bf94fdb911db83ce793b993bd6548a4115b306a7ef3c10f745a8fea3e9","src/unix/linux_like/linux/uclibc/align.rs":"9ed16138d8e439bd90930845a65eafa7ebd67366e6bf633936d44014f6e4c959","src/unix/linux_like/linux/uclibc/arm/align.rs":"e4a3c27fe20a57b8d612c34cb05bc70646edb5cec7251957315afa53a7b9f936","src/unix/linux_like/linux/uclibc/arm/mod.rs":"bf2dcf0a468f386899f572324f3bc14be1974f570afdfff1075ca6c5dd57710d","src/unix/linux_like/linux/uclibc/arm/no_align.rs":"9cd223135de75315840ff9c3fd5441ba1cb632b96b5c85a76f8316c86653db25","src/unix/linux_like/linux/uclibc/mips/mips32/align.rs":"e4a3c27fe20a57b8d612c34cb05bc70646edb5cec7251957315afa53a7b9f936","src/unix/linux_like/linux/uclibc/mips/mips32/mod.rs":"d2fc251754458b697ef6e599f0a670ebca18f61e4026bf681be4e2baa896b9df","src/unix/linux_like/linux/uclibc/mips/mips32/no_align.rs":"9cd223135de75315840ff9c3fd5441ba1cb632b96b5c85a76f8316c86653db25","src/unix/linux_like/linux/uclibc/mips/mips64/align.rs":"a7bdcb18a37a2d91e64d5fad83ea3edc78f5412adb28f77ab077dbb26dd08b2d","src/unix/linux_like/linux/uclibc/mips/mips64/mod.rs":"256a428290a560163ef7dc7d18b27bd3c6ce9748a0f28d5dc7f82203ee228220","src/unix/linux_like/linux/uclibc/mips/mips64/no_align.rs":"4a18e3875698c85229599225ac3401a2a40da87e77b2ad4ef47c6fcd5a24ed30","src/unix/linux_like/linux/uclibc/mips/mod.rs":"367ec5483ad317e6ccba1ac0888da6cf088a8d32689214cc8d16129aa692260c","src/unix/linux_like/linux/uclibc/mod.rs":"1c3d25cddcfefa2bd17bdc81550826be31a08eef235e13f825f169a5029c8bca","src/unix/linux_like/linux/uclibc/no_align.rs":"3f28637046524618adaa1012e26cb7ffe94b9396e6b518cccdc69d59f274d709","src/unix/linux_like/linux/uclibc/x86_64/l4re.rs":"024eba5753e852dbdd212427351affe7e83f9916c1864bce414d7aa2618f192e","src/unix/linux_like/linux/uclibc/x86_64/mod.rs":"420dbea99e99091f333641e202960fa4bed0733de2a834e610708555be6bab4c","src/unix/linux_like/linux/uclibc/x86_64/other.rs":"42c3f71e58cabba373f6a55a623f3c31b85049eb64824c09c2b082b3b2d6a0a8","src/unix/linux_like/mod.rs":"03ae2e1f8113ed650e1c9691e715254dd6b6d13cc829b639d5857336ecd11b24","src/unix/mod.rs":"4647dc713fb4208df76fe6009b9716eef1d9e09a77f6b2f1b793d63537b4c670","src/unix/newlib/aarch64/mod.rs":"bac93836a9a57b2c710f32f852e92a4d11ad6759ab0fb6ad33e71d60e53278af","src/unix/newlib/align.rs":"28aaf87fafbc6b312622719d472d8cf65f9e5467d15339df5f73e66d8502b28a","src/unix/newlib/arm/mod.rs":"cbba6b3e957eceb496806e60de8725a23ff3fa0015983b4b4fa27b233732b526","src/unix/newlib/espidf/mod.rs":"816f235f4aa4baabba7f2606b31d0fdb03988c52194c966728de8690bf17299d","src/unix/newlib/generic.rs":"eab066d9f0a0f3eb53cc1073d01496bba0110989e1f6a59838afd19f870cd599","src/unix/newlib/horizon/mod.rs":"7cc5cc120437421db139bfa6a90b18168cd3070bdd0f5be96d40fe4c996f3ca1","src/unix/newlib/mod.rs":"494e56628d4408bf66ad30ff71fbd21bc33d9037935c411dff7bf73dd3f1070b","src/unix/newlib/no_align.rs":"e0743b2179495a9514bc3a4d1781e492878c4ec834ee0085d0891dd1712e82fb","src/unix/newlib/powerpc/mod.rs":"0202ffd57caf75b6afa2c9717750ffb96e375ac33df0ae9609a3f831be393b67","src/unix/no_align.rs":"c06e95373b9088266e0b14bba0954eef95f93fb2b01d951855e382d22de78e53","src/unix/redox/mod.rs":"c8afea39f81e73ad4e9bf8a8f25138a200e616048e189debad80a6b7e08f710f","src/unix/solarish/compat.rs":"00f1ee3faec9da69204e42f025f6735dd13d894071a154425dcc43ecbdd06e7f","src/unix/solarish/illumos.rs":"cd93c2d84722bbf9933a92842a8998eb0b2afc962f50bc2546ad127b82809fa7","src/unix/solarish/mod.rs":"eace25beaa4874bfc2451f8136efc261f9dfb7a30caab3c97c708068d5431bbf","src/unix/solarish/solaris.rs":"41b350a89ddf01cd12a10f93640f92be53be0b0d976021cdc08da17bf3e72edf","src/unix/solarish/x86.rs":"e86e806df0caed72765040eaa2f3c883198d1aa91508540adf9b7008c77f522e","src/unix/solarish/x86_64.rs":"ec2b01f194eb8a6a27133c57681da195a949e03098f3ea1e847227a9c09ef5fc","src/unix/solarish/x86_common.rs":"ac869d9c3c95645c22460468391eb1982023c3a8e02b9e06a72e3aef3d5f1eac","src/vxworks/aarch64.rs":"98f0afdc511cd02557e506c21fed6737585490a1dce7a9d4941d08c437762b99","src/vxworks/arm.rs":"acb7968ce99fe3f4abdf39d98f8133d21a4fba435b8ef7084777cb181d788e88","src/vxworks/mod.rs":"aea3da66f2140f2a82dfc9c58f6e6531d2dd9c15ea696e0f95a0d4a2a187b5b6","src/vxworks/powerpc.rs":"acb7968ce99fe3f4abdf39d98f8133d21a4fba435b8ef7084777cb181d788e88","src/vxworks/powerpc64.rs":"98f0afdc511cd02557e506c21fed6737585490a1dce7a9d4941d08c437762b99","src/vxworks/x86.rs":"552f007f38317620b23889cb7c49d1d115841252439060122f52f434fbc6e5ba","src/vxworks/x86_64.rs":"018d92be3ad628a129eff9f2f5dfbc0883d8b8e5f2fa917b900a7f98ed6b514a","src/wasi.rs":"3f6219f036ac1d917ab5fa7323e3770857f566bc4189a9d4c4ea8ca6517b8953","src/windows/gnu/align.rs":"b2c13ec1b9f3b39a75c452c80c951dff9d0215e31d77e883b4502afb31794647","src/windows/gnu/mod.rs":"3c8c7edb7cdf5d0c44af936db2a94869585c69dfabeef30571b4f4e38375767a","src/windows/mod.rs":"7fe35c1f5e6272acfba059a1ad7a78b144f5bc63456f6377d58bbc42cc23f509","src/windows/msvc/mod.rs":"c068271e00fca6b62bc4bf44bcf142cfc38caeded9b6c4e01d1ceef3ccf986f4","tests/const_fn.rs":"cb75a1f0864f926aebe79118fc34d51a0d1ade2c20a394e7774c7e545f21f1f4"},"package":"db6d7e329c562c5dfab7a46a2afabc8b987ab9a4834c9d1ca04dc54c1546cef8"} \ No newline at end of file
+{"files":{"CONTRIBUTING.md":"bdc90b52cf803faac96e594069a86dd8ea150d5ba7fb3e6cadfc08dac4c7b0ce","Cargo.toml":"cec0b42b20e776ac9165b5a5eedfbd8fc033700cacabfa4209c60d35833e42f1","LICENSE-APACHE":"62c7a1e35f56406896d7aa7ca52d0cc0d272ac022b5d2796e7d6905db8a3636a","LICENSE-MIT":"a8d47ff51ca256f56a8932dba07660672dbfe3004257ca8de708aac1415937a1","README.md":"776affa26b66843a2b4f1a1c8f88d92f6461b74568911450fea717e9db6f877b","build.rs":"cecfa3f926ab4a9c87cd59cc0d687f98eceb6035b0dde185152e5206d090f8d0","rustfmt.toml":"eaa2ea84fc1ba0359b77680804903e07bb38d257ab11986b95b158e460f787b2","src/fixed_width_ints.rs":"7f986e5f5e68d25ef04d386fd2f640e8be8f15427a8d4a458ea01d26b8dca0ca","src/fuchsia/aarch64.rs":"378776a9e40766154a54c94c2a7b4675b5c302a38e6e42da99e67bfbaee60e56","src/fuchsia/align.rs":"ae1cf8f011a99737eabeb14ffff768e60f13b13363d7646744dbb0f443dab3d6","src/fuchsia/mod.rs":"1b4e6c34b01b4c970f4d4c044d1642020e0fc2ea1b8442e8f1a9b698569ab1f6","src/fuchsia/no_align.rs":"303f3f1b255e0088b5715094353cf00476131d8e94e6aebb3f469557771c8b8a","src/fuchsia/x86_64.rs":"93a3632b5cf67d2a6bcb7dc0a558605252d5fe689e0f38d8aa2ec5852255ac87","src/hermit/aarch64.rs":"86048676e335944c37a63d0083d0f368ae10ceccefeed9debb3bbe08777fc682","src/hermit/mod.rs":"d3bfce41e4463d4be8020a2d063c9bfa8b665f45f1cc6cbf3163f5d01e7cb21f","src/hermit/x86_64.rs":"ab832b7524e5fb15c49ff7431165ab1a37dc4667ae0b58e8306f4c539bfa110c","src/lib.rs":"ce753ef318b300bbd441feabdd77d00322dfb6ce9eee8c78a38afe02b57aa4c0","src/macros.rs":"b457eb028b8e8ab3c24bb7292b874ad4e491edbb83594f6a3da024df5348c088","src/psp.rs":"dd31aabd46171d474ec5828372e28588935120e7355c90c105360d8fa9264c1c","src/sgx.rs":"16a95cdefc81c5ee00d8353a60db363c4cc3e0f75abcd5d0144723f2a306ed1b","src/solid/aarch64.rs":"a726e47f324adf73a4a0b67a2c183408d0cad105ae66acf36db37a42ab7f8707","src/solid/arm.rs":"e39a4f74ebbef3b97b8c95758ad741123d84ed3eb48d9cf4f1f4872097fc27fe","src/solid/mod.rs":"5f4151dca5132e4b4e4c23ab9737e12856dddbdc0ca3f7dbc004328ef3c8acde","src/switch.rs":"9da3dd39b3de45a7928789926e8572d00e1e11a39e6f7289a1349aadce90edba","src/unix/align.rs":"2cdc7c826ef7ae61f5171c5ae8c445a743d86f1a7f2d9d7e4ceeec56d6874f65","src/unix/bsd/apple/b32/align.rs":"ec833a747866fe19ca2d9b4d3c9ff0385faba5edf4bd0d15fa68884c40b0e26c","src/unix/bsd/apple/b32/mod.rs":"2546ad3eb6aecb95f916648bc63264117c92b4b4859532b34cb011e4c75a5a72","src/unix/bsd/apple/b64/aarch64/align.rs":"e8eb38d064b5fefec6f37d42873820a0483e7c758ed336cc59a7155455ca89c9","src/unix/bsd/apple/b64/aarch64/mod.rs":"44c217a4f263afe7a97435de9323d20a96c37836f899ca0925306d4b7e073c27","src/unix/bsd/apple/b64/align.rs":"ec833a747866fe19ca2d9b4d3c9ff0385faba5edf4bd0d15fa68884c40b0e26c","src/unix/bsd/apple/b64/mod.rs":"f5e278a1af7fb358891d1c9be4eb7e815aaca0c5cb738d0c3604ba2208a856f7","src/unix/bsd/apple/b64/x86_64/align.rs":"ec833a747866fe19ca2d9b4d3c9ff0385faba5edf4bd0d15fa68884c40b0e26c","src/unix/bsd/apple/b64/x86_64/mod.rs":"8c87c5855038aae5d433c8f5eb3b29b0a175879a0245342b3bfd83bdf4cfd936","src/unix/bsd/apple/mod.rs":"1cc76b056d5925aedae04ead411057dc5c6c9bd3948609fdb30164ac1fb6565e","src/unix/bsd/freebsdlike/dragonfly/errno.rs":"8295b8bb0dfd38d2cdb4d9192cdeeb534cc6c3b208170e64615fa3e0edb3e578","src/unix/bsd/freebsdlike/dragonfly/mod.rs":"8986a8c79bcadfbdb58ec1a72e1aff8ce9b341c9392d7b0b7449bddf6db59058","src/unix/bsd/freebsdlike/freebsd/aarch64.rs":"6c8e216385f53a4bf5f171749b57602fc34a4e4b160a44ca31c058cb0c8a2126","src/unix/bsd/freebsdlike/freebsd/arm.rs":"59d6a670eea562fb87686e243e0a84603d29a2028a3d4b3f99ccc01bd04d2f47","src/unix/bsd/freebsdlike/freebsd/freebsd11/b64.rs":"9808d152c1196aa647f1b0f0cf84dac8c930da7d7f897a44975545e3d9d17681","src/unix/bsd/freebsdlike/freebsd/freebsd11/mod.rs":"badda6f0f7666f38345b1f4ca78817a47bc92bbdcdc3a1377f376f4e08c316e5","src/unix/bsd/freebsdlike/freebsd/freebsd12/b64.rs":"61cbe45f8499bedb168106b686d4f8239472f25c7553b069eec2afe197ff2df6","src/unix/bsd/freebsdlike/freebsd/freebsd12/mod.rs":"327700c5668be863f1fea205c82b0402e2936b883df63dda677716c30a50a284","src/unix/bsd/freebsdlike/freebsd/freebsd12/x86_64.rs":"2df36a7f122f6d6e5753cfb4d22e915cc80f6bc91c0161b3daae55a481bfd052","src/unix/bsd/freebsdlike/freebsd/freebsd13/b64.rs":"61cbe45f8499bedb168106b686d4f8239472f25c7553b069eec2afe197ff2df6","src/unix/bsd/freebsdlike/freebsd/freebsd13/mod.rs":"7f689e9a944c919834ec852b30c224f98e14b4b4087571adefeea5abad5d6374","src/unix/bsd/freebsdlike/freebsd/freebsd13/x86_64.rs":"2df36a7f122f6d6e5753cfb4d22e915cc80f6bc91c0161b3daae55a481bfd052","src/unix/bsd/freebsdlike/freebsd/freebsd14/b64.rs":"61cbe45f8499bedb168106b686d4f8239472f25c7553b069eec2afe197ff2df6","src/unix/bsd/freebsdlike/freebsd/freebsd14/mod.rs":"9b6fa1c3f5217f9482e0bed3bd0ea2905cdf56d628307cea48e49d8e00a6b09d","src/unix/bsd/freebsdlike/freebsd/freebsd14/x86_64.rs":"2df36a7f122f6d6e5753cfb4d22e915cc80f6bc91c0161b3daae55a481bfd052","src/unix/bsd/freebsdlike/freebsd/mod.rs":"26bda8cf730ab4868523a6ed7c513f51885cad30cdd02da905ff35b597576415","src/unix/bsd/freebsdlike/freebsd/powerpc.rs":"9ca3f82f88974e6db5569f2d76a5a3749b248a31747a6c0da5820492bdfeca42","src/unix/bsd/freebsdlike/freebsd/powerpc64.rs":"2dae3ecc87eac3b11657aa98915def55fc4b5c0de11fe26aae23329a54628a9a","src/unix/bsd/freebsdlike/freebsd/riscv64.rs":"fa4bed4c58cad24ba3395941c7fa6b11e089551a04714f9561078e400f5b2b62","src/unix/bsd/freebsdlike/freebsd/x86.rs":"c5005e3249eb7c93cfbac72a9e9272320d80ce7983da990ceb05a447f59a02c5","src/unix/bsd/freebsdlike/freebsd/x86_64/align.rs":"0e1f69a88fca1c32874b1daf5db3d446fefbe518dca497f096cc9168c39dde70","src/unix/bsd/freebsdlike/freebsd/x86_64/mod.rs":"51e4dd0c8ae247bb652feda5adad9333ea3bb30c750c3a3935e0b0e47d7803eb","src/unix/bsd/freebsdlike/mod.rs":"bd80ce2ff628ed5eaa856ebe8b6a8fb0e89d1c9728040b9ee6b967beb4bcf3a7","src/unix/bsd/mod.rs":"0c672b075b5616fca2cc56c00ee31c3f554dcbd2e88a7c2ba1437aa6e5604319","src/unix/bsd/netbsdlike/mod.rs":"34f60d73631f3c59936c87db1f62ddb8f693901c3cb199f7f370882e84d509fa","src/unix/bsd/netbsdlike/netbsd/aarch64.rs":"65dcb58d11e8d8028401a9d07ca3eb4cb4f053e04249cc877353449d84ccc4cb","src/unix/bsd/netbsdlike/netbsd/arm.rs":"58cdbb70b0d6f536551f0f3bb3725d2d75c4690db12c26c034e7d6ec4a924452","src/unix/bsd/netbsdlike/netbsd/mod.rs":"107a4aa396b8383c66e0ace2f941450b4b69146558cdc4d9fbe33eeab51760f1","src/unix/bsd/netbsdlike/netbsd/powerpc.rs":"ee7ff5d89d0ed22f531237b5059aa669df93a3b5c489fa641465ace8d405bf41","src/unix/bsd/netbsdlike/netbsd/sparc64.rs":"9489f4b3e4566f43bb12dfb92238960613dac7f6a45cc13068a8d152b902d7d9","src/unix/bsd/netbsdlike/netbsd/x86.rs":"20692320e36bfe028d1a34d16fe12ca77aa909cb02bda167376f98f1a09aefe7","src/unix/bsd/netbsdlike/netbsd/x86_64.rs":"1afe5ef46b14397cdd68664b5b232e4f5b035b6db1d4cf411c899d51ebca9f30","src/unix/bsd/netbsdlike/openbsd/aarch64.rs":"dd91931d373b7ecaf6e2de25adadee10d16fa9b12c2cbacdff3eb291e1ba36af","src/unix/bsd/netbsdlike/openbsd/arm.rs":"01580d261bc6447bb327a0d982181b7bdabfa066cee65a30373d3ced729ad307","src/unix/bsd/netbsdlike/openbsd/mips64.rs":"8532a189ae10c7d668d9d4065da8b05d124e09bd39442c9f74a7f231c43eca48","src/unix/bsd/netbsdlike/openbsd/mod.rs":"38b7d65a86701a75a9047a3ef3b006f09ffbb33ab2312174bcee889efb74e100","src/unix/bsd/netbsdlike/openbsd/powerpc.rs":"01580d261bc6447bb327a0d982181b7bdabfa066cee65a30373d3ced729ad307","src/unix/bsd/netbsdlike/openbsd/powerpc64.rs":"1dd5449dd1fd3d51e30ffdeeaece91d0aaf05c710e0ac699fecc5461cfa2c28e","src/unix/bsd/netbsdlike/openbsd/riscv64.rs":"1dd5449dd1fd3d51e30ffdeeaece91d0aaf05c710e0ac699fecc5461cfa2c28e","src/unix/bsd/netbsdlike/openbsd/sparc64.rs":"d04fd287afbaa2c5df9d48c94e8374a532a3ba491b424ddf018270c7312f4085","src/unix/bsd/netbsdlike/openbsd/x86.rs":"6f7f5c4fde2a2259eb547890cbd86570cea04ef85347d7569e94e679448bec87","src/unix/bsd/netbsdlike/openbsd/x86_64.rs":"d31db31630289c85af3339dbe357998a21ca584cbae31607448fe2cf7675a4e1","src/unix/haiku/b32.rs":"a2efdbf7158a6da341e1db9176b0ab193ba88b449616239ed95dced11f54d87b","src/unix/haiku/b64.rs":"ff8115367d3d7d354f792d6176dfaaa26353f57056197b563bf4681f91ff7985","src/unix/haiku/mod.rs":"891f77891349938ffb2048db0446e28f2b7f78a0286042d0f0a9af6c2d4570af","src/unix/haiku/native.rs":"dbfcbf4954a79d1df2ff58e0590bbcb8c57dfc7a32392aa73ee4726b66bd6cc8","src/unix/haiku/x86_64.rs":"3ec3aeeb7ed208b8916f3e32d42bfd085ff5e16936a1a35d9a52789f043b7237","src/unix/hermit/aarch64.rs":"86048676e335944c37a63d0083d0f368ae10ceccefeed9debb3bbe08777fc682","src/unix/hermit/mod.rs":"a1494a0bddf301cceb0d9b8529a84b5882fe855ceae77a1c4e8d6034e705e26c","src/unix/hermit/x86_64.rs":"ab832b7524e5fb15c49ff7431165ab1a37dc4667ae0b58e8306f4c539bfa110c","src/unix/linux_like/android/b32/arm.rs":"007391f35663762d8097a8a5ae301accb82c729713da0dfd9631c4bc69d9305e","src/unix/linux_like/android/b32/mod.rs":"7c173e0375119bf06a3081652faede95e5bcd6858e7576b7533d037978737c8f","src/unix/linux_like/android/b32/x86/align.rs":"812914e4241df82e32b12375ca3374615dc3a4bdd4cf31f0423c5815320c0dab","src/unix/linux_like/android/b32/x86/mod.rs":"81b4ab3ffc347e819f2f62c09dcd923d9d12d14b3d0e66ddc06ab78fa75a4b88","src/unix/linux_like/android/b64/aarch64/align.rs":"2179c3b1608fa4bf68840482bfc2b2fa3ee2faf6fcae3770f9e505cddca35c7b","src/unix/linux_like/android/b64/aarch64/int128.rs":"1735f6f5c56770d20dd426442f09724d9b2052b46a7cd82f23f3288a4a7276de","src/unix/linux_like/android/b64/aarch64/mod.rs":"f12594f7a57654ea63794822761c1ef9029ee5cef6bbad498c928a5bff2dfade","src/unix/linux_like/android/b64/mod.rs":"71e4fcbe952bfa4a5f9022f3972e906917b38f729b9d8ef57cd5d179104894ac","src/unix/linux_like/android/b64/riscv64/align.rs":"0bf138f84e5327d8339bcd4adf071a6832b516445e597552c82bbd881095e3a8","src/unix/linux_like/android/b64/riscv64/mod.rs":"80e9f93fed838a48b4e2e8d77b95c72cfd7c0647bcce63851555c5ad16dad143","src/unix/linux_like/android/b64/x86_64/align.rs":"7169d07a9fd4716f7512719aec9fda5d8bed306dc0720ffc1b21696c9951e3c6","src/unix/linux_like/android/b64/x86_64/mod.rs":"40be3b9dac9b52f3fd341fae4593a8c8c11a79ed694bcccf82f8810253c77492","src/unix/linux_like/android/mod.rs":"bf37384b99034eb1817303d9e1b35fe895da1010b024ada128e84059dad2c73b","src/unix/linux_like/emscripten/align.rs":"86c95cbed7a7161b1f23ee06843e7b0e2340ad92b2cb86fe2a8ef3e0e8c36216","src/unix/linux_like/emscripten/mod.rs":"24a6b0eadc011ee75c5bcbd18fe9f30d64006b71ec1416f6352e6015917240fc","src/unix/linux_like/emscripten/no_align.rs":"0128e4aa721a9902754828b61b5ec7d8a86619983ed1e0544a85d35b1051fad6","src/unix/linux_like/linux/align.rs":"d6c259942c8e843373accd180fc8f4f45f03544dfd21b93a8d02641ead3ef63e","src/unix/linux_like/linux/arch/generic/mod.rs":"46dd6634e564fb1b60c8a2d1018ef8f365d1a8ed26f162c99528922d06d14134","src/unix/linux_like/linux/arch/mips/mod.rs":"2d166054a586bb4bf6e4a4ba35f7574907b217225eff8f1a43adc4277e142460","src/unix/linux_like/linux/arch/mod.rs":"466a29622e47c6c7f1500682b2eb17f5566dd81b322cd6348f0fdd355cec593a","src/unix/linux_like/linux/arch/powerpc/mod.rs":"3f6da7b0fa7b394c7d4eea2bb3caa7a7729ab0d6c1491fef02206a912c41b815","src/unix/linux_like/linux/arch/sparc/mod.rs":"91593ec0440f1dd8f8e612028f432c44c14089286e2aca50e10511ab942db8c3","src/unix/linux_like/linux/gnu/align.rs":"e4a3c27fe20a57b8d612c34cb05bc70646edb5cec7251957315afa53a7b9f936","src/unix/linux_like/linux/gnu/b32/arm/align.rs":"6ec0eb3ee93f7ae99fd714b4deabfb5e97fbcefd8c26f5a45fb8e7150899cdeb","src/unix/linux_like/linux/gnu/b32/arm/mod.rs":"5bd3f6b3484e049ddaac95f411b0d82cbf1cd28e6a5defbc927bd917f5f7d299","src/unix/linux_like/linux/gnu/b32/m68k/align.rs":"8faa92f77a9232c035418d45331774e64a9a841d99c91791570a203bf2b45bcb","src/unix/linux_like/linux/gnu/b32/m68k/mod.rs":"a2a0a9400dae44086ebf579e0448e0676d4a3214d1ae7d13a024857251e23b6b","src/unix/linux_like/linux/gnu/b32/mips/align.rs":"429fb5e005cb7143602d430098b6ebfb7d360685b194f333dfd587472ae954ee","src/unix/linux_like/linux/gnu/b32/mips/mod.rs":"6b9a5dac6f937ddc1453e808e3c43502c87143332df9e43ac64fb8b1eda6c116","src/unix/linux_like/linux/gnu/b32/mod.rs":"8da281da578cdee972e952b118b903b370320897a7e335342a15e1359864bef2","src/unix/linux_like/linux/gnu/b32/powerpc.rs":"5c5d90326b54b57b98eff4745fe7a3fb02f053b2dc782241a73e807b491936a3","src/unix/linux_like/linux/gnu/b32/riscv32/align.rs":"d321491612be8d5c61b6ec2dc0111beb3a22e58803f99cd37543efe86621b119","src/unix/linux_like/linux/gnu/b32/riscv32/mod.rs":"5e7c1e29aeb82fc422f45b73fb0cf3d13d0902300f9150d2755a9074f8d96999","src/unix/linux_like/linux/gnu/b32/sparc/align.rs":"21adbed27df73e2d1ed934aaf733a643003d7baf2bde9c48ea440895bcca6d41","src/unix/linux_like/linux/gnu/b32/sparc/mod.rs":"80894eece66e9348f45d1b07ad37c757ea694bbd10ed49d3f920b34e9f51a9a3","src/unix/linux_like/linux/gnu/b32/x86/align.rs":"e4bafdc4a519a7922a81b37a62bbfd1177a2f620890eef8f1fbc47162e9eb413","src/unix/linux_like/linux/gnu/b32/x86/mod.rs":"c703cc5e9de2dc31d9e5831bfb6f354d6e3518b2ae02263f68a9a70f1c0167e2","src/unix/linux_like/linux/gnu/b64/aarch64/align.rs":"ea39d5fd8ca5a71314127d1e1f542bca34ac566eac9a95662076d91ea4bee548","src/unix/linux_like/linux/gnu/b64/aarch64/ilp32.rs":"21a21503ef2e095f4371044915d4bfb07a8578011cb5c713cd9f45947b0b5730","src/unix/linux_like/linux/gnu/b64/aarch64/int128.rs":"1735f6f5c56770d20dd426442f09724d9b2052b46a7cd82f23f3288a4a7276de","src/unix/linux_like/linux/gnu/b64/aarch64/lp64.rs":"e78c3cd197f44832338b414d1a9bc0d194f44c74db77bd7bf830c1fff62b2690","src/unix/linux_like/linux/gnu/b64/aarch64/mod.rs":"666beae35371cb54a4ad091764e0e3ca4983d5205179c119a8ff97d3ae301869","src/unix/linux_like/linux/gnu/b64/loongarch64/align.rs":"6616c38bf8cab53034dce9f968adae8fb7771334445a93876d000cfd08f117a8","src/unix/linux_like/linux/gnu/b64/loongarch64/mod.rs":"17e9478b6a5830f6b8f6bea4ccab712cfd1972cdfb43b97408a068e4ea924106","src/unix/linux_like/linux/gnu/b64/mips64/align.rs":"7169d07a9fd4716f7512719aec9fda5d8bed306dc0720ffc1b21696c9951e3c6","src/unix/linux_like/linux/gnu/b64/mips64/mod.rs":"80b4b97a41564290c510e68a1fb20cfd8424206f010e71a596f12877de886a71","src/unix/linux_like/linux/gnu/b64/mod.rs":"3c6555f30a7a8852757b31a542ea73fb6a16a6e27e838397e819278ad56e57a4","src/unix/linux_like/linux/gnu/b64/powerpc64/align.rs":"e29c4868bbecfa4a6cd8a2ad06193f3bbc78a468cc1dc9df83f002f1268130d9","src/unix/linux_like/linux/gnu/b64/powerpc64/mod.rs":"a595e37c2325ceb40ef66c634bd3c255ad184a1d70ff8025e98a075f0ec67704","src/unix/linux_like/linux/gnu/b64/riscv64/align.rs":"d321491612be8d5c61b6ec2dc0111beb3a22e58803f99cd37543efe86621b119","src/unix/linux_like/linux/gnu/b64/riscv64/mod.rs":"ef4b13477ffd8532fb6705ca3fa63a1f13e8d19ee39b083c5355dfce430c1a5b","src/unix/linux_like/linux/gnu/b64/s390x.rs":"788fde4fa1919859cc028b59da31de00449edd2b2c1530ae76134beac418b73c","src/unix/linux_like/linux/gnu/b64/sparc64/align.rs":"e29c4868bbecfa4a6cd8a2ad06193f3bbc78a468cc1dc9df83f002f1268130d9","src/unix/linux_like/linux/gnu/b64/sparc64/mod.rs":"c4fa0ede3f78b21a9982667922cccd0681bee3cb6d42208ea9958f65e93d6308","src/unix/linux_like/linux/gnu/b64/x86_64/align.rs":"62e822478356db4a73b6bbd1b36d825b893939ab4b308ec11b0578bcc4b49769","src/unix/linux_like/linux/gnu/b64/x86_64/mod.rs":"e37e0421290b152fe508883181c41225e09dd5452a6b085e8d807b3b54823028","src/unix/linux_like/linux/gnu/b64/x86_64/not_x32.rs":"c1b6345ce14f67d1b2e2f7f2c0ff9a074c07acbd348df69cb4558bda8c8fb9ae","src/unix/linux_like/linux/gnu/b64/x86_64/x32.rs":"3f4d2aeadb7d2620cad09564abdbfc5cf02eeb5a27f2bab8a4e9b4bdbdb258a5","src/unix/linux_like/linux/gnu/mod.rs":"e31aa4bd147c83d05dcd13baca4b9f676320a7713ff50de08b51d0c88f8241a3","src/unix/linux_like/linux/gnu/no_align.rs":"9cd223135de75315840ff9c3fd5441ba1cb632b96b5c85a76f8316c86653db25","src/unix/linux_like/linux/mod.rs":"8862912e65ae64dd26728ced492eacbdd3753b7a19432fc8fdf5a673ff7526c9","src/unix/linux_like/linux/musl/b32/arm/align.rs":"3e8ac052c1043764776b54c93ba4260e061df998631737a897d9d47d54f7b80c","src/unix/linux_like/linux/musl/b32/arm/mod.rs":"f5b217a93f99c2852f7fd1459f529798372fa7df84ee0cfd3d8cdd5b2021b8cf","src/unix/linux_like/linux/musl/b32/hexagon.rs":"226a8b64ce9c75abbbee6d2dceb0b44f7b6c750c4102ebd4d015194afee6666e","src/unix/linux_like/linux/musl/b32/mips/align.rs":"429fb5e005cb7143602d430098b6ebfb7d360685b194f333dfd587472ae954ee","src/unix/linux_like/linux/musl/b32/mips/mod.rs":"16a7a03d998a5db11be9ee81525c7faec4623383260e8bc125b1c53a050fde75","src/unix/linux_like/linux/musl/b32/mod.rs":"580e27c5ce3344df686f1ffc08fdfa2c282d1ceb623d778c50d210d4bd65ec7e","src/unix/linux_like/linux/musl/b32/powerpc.rs":"dc52adc264c34bce80753d6bd064e8fc4b8237fa1e5c5315ccb6c72df74c2813","src/unix/linux_like/linux/musl/b32/riscv32/align.rs":"efd2accf33b87de7c7547903359a5da896edc33cd6c719552c7474b60d4a5d48","src/unix/linux_like/linux/musl/b32/riscv32/mod.rs":"e57dc5562553aab6d0765e0ec266254aa52975f8757bfe97e0c6028fa7d5d37c","src/unix/linux_like/linux/musl/b32/x86/align.rs":"08e77fbd7435d7dec2ff56932433bece3f02e47ce810f89004a275a86d39cbe1","src/unix/linux_like/linux/musl/b32/x86/mod.rs":"7a1586f77bb693f0b319ec720c35963da056287fc42f8e2ccf1d5b2bcccf4fd6","src/unix/linux_like/linux/musl/b64/aarch64/align.rs":"6ba32725d24d7d8e6aa111f3b57aafa318f83b606abe96561329151829821133","src/unix/linux_like/linux/musl/b64/aarch64/int128.rs":"1735f6f5c56770d20dd426442f09724d9b2052b46a7cd82f23f3288a4a7276de","src/unix/linux_like/linux/musl/b64/aarch64/mod.rs":"31e75179cbb4e26425b3f5b052e358f593153da662884655e60801d852e55dc2","src/unix/linux_like/linux/musl/b64/mips64.rs":"9a5d29f666332bb056d0e2951e9de989aa1dc016075f009db3f2f628e0cdda8c","src/unix/linux_like/linux/musl/b64/mod.rs":"8c10627bd582cb272514e7350ae4743a65d489356eae039d2e7e55cd533fbbc8","src/unix/linux_like/linux/musl/b64/powerpc64.rs":"455dc0ffa55afc1db6ffaf461f6f2a7b49d31658bfebe0bb4efac5967a6f956c","src/unix/linux_like/linux/musl/b64/riscv64/align.rs":"d321491612be8d5c61b6ec2dc0111beb3a22e58803f99cd37543efe86621b119","src/unix/linux_like/linux/musl/b64/riscv64/mod.rs":"42d4b6d36807f37759094a732a321080cccdf498b174d632cebba147051de294","src/unix/linux_like/linux/musl/b64/s390x.rs":"d8a4fdfea0960ec284cae4facb8b0fb342e8aa41544cffacdcaf08c5a92a43f8","src/unix/linux_like/linux/musl/b64/x86_64/align.rs":"77309276ad7a42cbe59ca381f23590b7a143aded05555b34a5b307b808cbca6e","src/unix/linux_like/linux/musl/b64/x86_64/mod.rs":"7a877cd23b64be66d28e6b8dddae32d59a88d69115637539daf19381f4e39330","src/unix/linux_like/linux/musl/mod.rs":"8d8b50a0bf7ec53bd4d2ea92e8bfae14529f0beb3f22a65b55623f7086fee8ac","src/unix/linux_like/linux/no_align.rs":"da2a8721becaaaa528781f97f5d9aae6a982ae5d4f5f6d2ffc0150bed72319b3","src/unix/linux_like/linux/non_exhaustive.rs":"181a05bf94fdb911db83ce793b993bd6548a4115b306a7ef3c10f745a8fea3e9","src/unix/linux_like/linux/uclibc/align.rs":"9ed16138d8e439bd90930845a65eafa7ebd67366e6bf633936d44014f6e4c959","src/unix/linux_like/linux/uclibc/arm/align.rs":"e4a3c27fe20a57b8d612c34cb05bc70646edb5cec7251957315afa53a7b9f936","src/unix/linux_like/linux/uclibc/arm/mod.rs":"bf2dcf0a468f386899f572324f3bc14be1974f570afdfff1075ca6c5dd57710d","src/unix/linux_like/linux/uclibc/arm/no_align.rs":"9cd223135de75315840ff9c3fd5441ba1cb632b96b5c85a76f8316c86653db25","src/unix/linux_like/linux/uclibc/mips/mips32/align.rs":"e4a3c27fe20a57b8d612c34cb05bc70646edb5cec7251957315afa53a7b9f936","src/unix/linux_like/linux/uclibc/mips/mips32/mod.rs":"d2fc251754458b697ef6e599f0a670ebca18f61e4026bf681be4e2baa896b9df","src/unix/linux_like/linux/uclibc/mips/mips32/no_align.rs":"9cd223135de75315840ff9c3fd5441ba1cb632b96b5c85a76f8316c86653db25","src/unix/linux_like/linux/uclibc/mips/mips64/align.rs":"a7bdcb18a37a2d91e64d5fad83ea3edc78f5412adb28f77ab077dbb26dd08b2d","src/unix/linux_like/linux/uclibc/mips/mips64/mod.rs":"256a428290a560163ef7dc7d18b27bd3c6ce9748a0f28d5dc7f82203ee228220","src/unix/linux_like/linux/uclibc/mips/mips64/no_align.rs":"4a18e3875698c85229599225ac3401a2a40da87e77b2ad4ef47c6fcd5a24ed30","src/unix/linux_like/linux/uclibc/mips/mod.rs":"367ec5483ad317e6ccba1ac0888da6cf088a8d32689214cc8d16129aa692260c","src/unix/linux_like/linux/uclibc/mod.rs":"1c3d25cddcfefa2bd17bdc81550826be31a08eef235e13f825f169a5029c8bca","src/unix/linux_like/linux/uclibc/no_align.rs":"3f28637046524618adaa1012e26cb7ffe94b9396e6b518cccdc69d59f274d709","src/unix/linux_like/linux/uclibc/x86_64/l4re.rs":"024eba5753e852dbdd212427351affe7e83f9916c1864bce414d7aa2618f192e","src/unix/linux_like/linux/uclibc/x86_64/mod.rs":"420dbea99e99091f333641e202960fa4bed0733de2a834e610708555be6bab4c","src/unix/linux_like/linux/uclibc/x86_64/other.rs":"42c3f71e58cabba373f6a55a623f3c31b85049eb64824c09c2b082b3b2d6a0a8","src/unix/linux_like/mod.rs":"759e65c13f7e49a6efd1a979c821c53c478648f7f00cb29da65d92904c7c6814","src/unix/mod.rs":"a55d80aae47b642e25810c2321626f4cc5168170230a1d73953dfca58709b774","src/unix/newlib/aarch64/mod.rs":"bac93836a9a57b2c710f32f852e92a4d11ad6759ab0fb6ad33e71d60e53278af","src/unix/newlib/align.rs":"28aaf87fafbc6b312622719d472d8cf65f9e5467d15339df5f73e66d8502b28a","src/unix/newlib/arm/mod.rs":"cbba6b3e957eceb496806e60de8725a23ff3fa0015983b4b4fa27b233732b526","src/unix/newlib/espidf/mod.rs":"816f235f4aa4baabba7f2606b31d0fdb03988c52194c966728de8690bf17299d","src/unix/newlib/generic.rs":"eab066d9f0a0f3eb53cc1073d01496bba0110989e1f6a59838afd19f870cd599","src/unix/newlib/horizon/mod.rs":"7cc5cc120437421db139bfa6a90b18168cd3070bdd0f5be96d40fe4c996f3ca1","src/unix/newlib/mod.rs":"47d853beaa42b4aa17532d7687715e00e1da6632fccbcdcb079382dbde5412ff","src/unix/newlib/no_align.rs":"e0743b2179495a9514bc3a4d1781e492878c4ec834ee0085d0891dd1712e82fb","src/unix/newlib/powerpc/mod.rs":"0202ffd57caf75b6afa2c9717750ffb96e375ac33df0ae9609a3f831be393b67","src/unix/no_align.rs":"c06e95373b9088266e0b14bba0954eef95f93fb2b01d951855e382d22de78e53","src/unix/nto/aarch64.rs":"4709c9afdc8d583be876598e7c238499ee3e8da5bd2baa614d9c7dd414851555","src/unix/nto/mod.rs":"a4ed355f33ab18041cf642e2f4d1a50dc96b5bce778715f04352c34d020961b5","src/unix/nto/neutrino.rs":"62198d95ccc0fe7ece6f9d5c0b29fc22303ef458886efb5e09aad524eca2ab7b","src/unix/nto/x86_64.rs":"a3e18e93c2999da1cd7a6f748a4b60c07aefb73d8ea2aafec19a84cfb040bc8e","src/unix/redox/mod.rs":"c8afea39f81e73ad4e9bf8a8f25138a200e616048e189debad80a6b7e08f710f","src/unix/solarish/compat.rs":"00f1ee3faec9da69204e42f025f6735dd13d894071a154425dcc43ecbdd06e7f","src/unix/solarish/illumos.rs":"cd93c2d84722bbf9933a92842a8998eb0b2afc962f50bc2546ad127b82809fa7","src/unix/solarish/mod.rs":"b1c0a1d347b30d45c85429b7236d234f5b2c86b9eec439e897c9371d856c187a","src/unix/solarish/solaris.rs":"41b350a89ddf01cd12a10f93640f92be53be0b0d976021cdc08da17bf3e72edf","src/unix/solarish/x86.rs":"e86e806df0caed72765040eaa2f3c883198d1aa91508540adf9b7008c77f522e","src/unix/solarish/x86_64.rs":"ec2b01f194eb8a6a27133c57681da195a949e03098f3ea1e847227a9c09ef5fc","src/unix/solarish/x86_common.rs":"ac869d9c3c95645c22460468391eb1982023c3a8e02b9e06a72e3aef3d5f1eac","src/vxworks/aarch64.rs":"98f0afdc511cd02557e506c21fed6737585490a1dce7a9d4941d08c437762b99","src/vxworks/arm.rs":"acb7968ce99fe3f4abdf39d98f8133d21a4fba435b8ef7084777cb181d788e88","src/vxworks/mod.rs":"ff063860fc4fe3bca6332742764e29c1506884added21aa7722144c1fb3f4018","src/vxworks/powerpc.rs":"acb7968ce99fe3f4abdf39d98f8133d21a4fba435b8ef7084777cb181d788e88","src/vxworks/powerpc64.rs":"98f0afdc511cd02557e506c21fed6737585490a1dce7a9d4941d08c437762b99","src/vxworks/x86.rs":"552f007f38317620b23889cb7c49d1d115841252439060122f52f434fbc6e5ba","src/vxworks/x86_64.rs":"018d92be3ad628a129eff9f2f5dfbc0883d8b8e5f2fa917b900a7f98ed6b514a","src/wasi.rs":"b9a2ecc75fd2359a2484e93fdd1c539d2abc109cd9455d8f566476bcfb19df3d","src/windows/gnu/align.rs":"b2c13ec1b9f3b39a75c452c80c951dff9d0215e31d77e883b4502afb31794647","src/windows/gnu/mod.rs":"3c8c7edb7cdf5d0c44af936db2a94869585c69dfabeef30571b4f4e38375767a","src/windows/mod.rs":"5421b92f47cb69845f4323b1a14e533d8a17acc6412c58e67f4d41def749de2f","src/windows/msvc/mod.rs":"c068271e00fca6b62bc4bf44bcf142cfc38caeded9b6c4e01d1ceef3ccf986f4","tests/const_fn.rs":"cb75a1f0864f926aebe79118fc34d51a0d1ade2c20a394e7774c7e545f21f1f4"},"package":"201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79"} \ No newline at end of file
diff --git a/vendor/libc/Cargo.toml b/vendor/libc/Cargo.toml
index 5c6208353..60e7b1674 100644
--- a/vendor/libc/Cargo.toml
+++ b/vendor/libc/Cargo.toml
@@ -11,7 +11,7 @@
[package]
name = "libc"
-version = "0.2.138"
+version = "0.2.139"
authors = ["The Rust Project Developers"]
build = "build.rs"
exclude = [
diff --git a/vendor/libc/src/fuchsia/mod.rs b/vendor/libc/src/fuchsia/mod.rs
index 7a9edada1..5c6aebde2 100644
--- a/vendor/libc/src/fuchsia/mod.rs
+++ b/vendor/libc/src/fuchsia/mod.rs
@@ -3402,11 +3402,16 @@ extern "C" {
pub fn feof(stream: *mut FILE) -> c_int;
pub fn ferror(stream: *mut FILE) -> c_int;
pub fn perror(s: *const c_char);
+ pub fn atof(s: *const c_char) -> c_double;
pub fn atoi(s: *const c_char) -> c_int;
+ pub fn atol(s: *const c_char) -> c_long;
+ pub fn atoll(s: *const c_char) -> c_longlong;
pub fn strtod(s: *const c_char, endp: *mut *mut c_char) -> c_double;
pub fn strtof(s: *const c_char, endp: *mut *mut c_char) -> c_float;
pub fn strtol(s: *const c_char, endp: *mut *mut c_char, base: c_int) -> c_long;
+ pub fn strtoll(s: *const c_char, endp: *mut *mut c_char, base: c_int) -> c_longlong;
pub fn strtoul(s: *const c_char, endp: *mut *mut c_char, base: c_int) -> c_ulong;
+ pub fn strtoull(s: *const c_char, endp: *mut *mut c_char, base: c_int) -> c_ulonglong;
pub fn calloc(nobj: size_t, size: size_t) -> *mut c_void;
pub fn malloc(size: size_t) -> *mut c_void;
pub fn realloc(p: *mut c_void, size: size_t) -> *mut c_void;
@@ -3448,7 +3453,6 @@ extern "C" {
pub fn memset(dest: *mut c_void, c: c_int, n: size_t) -> *mut c_void;
pub fn abs(i: c_int) -> c_int;
- pub fn atof(s: *const c_char) -> c_double;
pub fn labs(i: c_long) -> c_long;
pub fn rand() -> c_int;
pub fn srand(seed: c_uint);
diff --git a/vendor/libc/src/unix/bsd/mod.rs b/vendor/libc/src/unix/bsd/mod.rs
index d49e3c440..84e572eda 100644
--- a/vendor/libc/src/unix/bsd/mod.rs
+++ b/vendor/libc/src/unix/bsd/mod.rs
@@ -613,7 +613,6 @@ extern "C" {
pub fn strerror_r(errnum: ::c_int, buf: *mut c_char, buflen: ::size_t) -> ::c_int;
pub fn abs(i: ::c_int) -> ::c_int;
- pub fn atof(s: *const ::c_char) -> ::c_double;
pub fn labs(i: ::c_long) -> ::c_long;
#[cfg_attr(
all(target_os = "freebsd", any(freebsd12, freebsd11, freebsd10)),
diff --git a/vendor/libc/src/unix/haiku/mod.rs b/vendor/libc/src/unix/haiku/mod.rs
index 005b1d9df..95ddadaee 100644
--- a/vendor/libc/src/unix/haiku/mod.rs
+++ b/vendor/libc/src/unix/haiku/mod.rs
@@ -1592,7 +1592,6 @@ extern "C" {
pub fn _errnop() -> *mut ::c_int;
pub fn abs(i: ::c_int) -> ::c_int;
- pub fn atof(s: *const ::c_char) -> ::c_double;
pub fn labs(i: ::c_long) -> ::c_long;
pub fn rand() -> ::c_int;
pub fn srand(seed: ::c_uint);
diff --git a/vendor/libc/src/unix/hermit/mod.rs b/vendor/libc/src/unix/hermit/mod.rs
index eedfd28a4..6a656a859 100644
--- a/vendor/libc/src/unix/hermit/mod.rs
+++ b/vendor/libc/src/unix/hermit/mod.rs
@@ -966,7 +966,6 @@ extern "C" {
pub fn sem_init(sem: *mut sem_t, pshared: ::c_int, value: ::c_uint) -> ::c_int;
pub fn abs(i: ::c_int) -> ::c_int;
- pub fn atof(s: *const ::c_char) -> ::c_double;
pub fn labs(i: ::c_long) -> ::c_long;
pub fn rand() -> ::c_int;
pub fn srand(seed: ::c_uint);
diff --git a/vendor/libc/src/unix/linux_like/android/b32/arm.rs b/vendor/libc/src/unix/linux_like/android/b32/arm.rs
index 33d2fa070..8b8e54955 100644
--- a/vendor/libc/src/unix/linux_like/android/b32/arm.rs
+++ b/vendor/libc/src/unix/linux_like/android/b32/arm.rs
@@ -501,6 +501,9 @@ pub const SYS_pwritev2: ::c_long = 393;
pub const SYS_pkey_mprotect: ::c_long = 394;
pub const SYS_pkey_alloc: ::c_long = 395;
pub const SYS_pkey_free: ::c_long = 396;
+pub const SYS_io_uring_setup: ::c_long = 425;
+pub const SYS_io_uring_enter: ::c_long = 426;
+pub const SYS_io_uring_register: ::c_long = 427;
// offsets in mcontext_t.gregs from sys/ucontext.h
pub const REG_R0: ::c_int = 0;
diff --git a/vendor/libc/src/unix/linux_like/android/b32/x86/mod.rs b/vendor/libc/src/unix/linux_like/android/b32/x86/mod.rs
index 6507cb4e0..9545ecbfb 100644
--- a/vendor/libc/src/unix/linux_like/android/b32/x86/mod.rs
+++ b/vendor/libc/src/unix/linux_like/android/b32/x86/mod.rs
@@ -533,6 +533,9 @@ pub const SYS_pwritev2: ::c_long = 379;
pub const SYS_pkey_mprotect: ::c_long = 380;
pub const SYS_pkey_alloc: ::c_long = 381;
pub const SYS_pkey_free: ::c_long = 382;
+pub const SYS_io_uring_setup: ::c_long = 425;
+pub const SYS_io_uring_enter: ::c_long = 426;
+pub const SYS_io_uring_register: ::c_long = 427;
// offsets in user_regs_structs, from sys/reg.h
pub const EBX: ::c_int = 0;
diff --git a/vendor/libc/src/unix/linux_like/android/b64/aarch64/mod.rs b/vendor/libc/src/unix/linux_like/android/b64/aarch64/mod.rs
index c4d442060..36871b084 100644
--- a/vendor/libc/src/unix/linux_like/android/b64/aarch64/mod.rs
+++ b/vendor/libc/src/unix/linux_like/android/b64/aarch64/mod.rs
@@ -374,6 +374,9 @@ pub const SYS_pwritev2: ::c_long = 287;
pub const SYS_pkey_mprotect: ::c_long = 288;
pub const SYS_pkey_alloc: ::c_long = 289;
pub const SYS_pkey_free: ::c_long = 290;
+pub const SYS_io_uring_setup: ::c_long = 425;
+pub const SYS_io_uring_enter: ::c_long = 426;
+pub const SYS_io_uring_register: ::c_long = 427;
pub const SYS_syscalls: ::c_long = 436;
cfg_if! {
diff --git a/vendor/libc/src/unix/linux_like/android/b64/x86_64/mod.rs b/vendor/libc/src/unix/linux_like/android/b64/x86_64/mod.rs
index d25b50775..1e3ee31c5 100644
--- a/vendor/libc/src/unix/linux_like/android/b64/x86_64/mod.rs
+++ b/vendor/libc/src/unix/linux_like/android/b64/x86_64/mod.rs
@@ -728,6 +728,9 @@ pub const SYS_pwritev2: ::c_long = 328;
pub const SYS_pkey_mprotect: ::c_long = 329;
pub const SYS_pkey_alloc: ::c_long = 330;
pub const SYS_pkey_free: ::c_long = 331;
+pub const SYS_io_uring_setup: ::c_long = 425;
+pub const SYS_io_uring_enter: ::c_long = 426;
+pub const SYS_io_uring_register: ::c_long = 427;
// offsets in user_regs_structs, from sys/reg.h
pub const R15: ::c_int = 0;
diff --git a/vendor/libc/src/unix/linux_like/android/mod.rs b/vendor/libc/src/unix/linux_like/android/mod.rs
index 61885582a..adec24a0a 100644
--- a/vendor/libc/src/unix/linux_like/android/mod.rs
+++ b/vendor/libc/src/unix/linux_like/android/mod.rs
@@ -2421,9 +2421,20 @@ pub const SND_CNT: usize = SND_MAX as usize + 1;
pub const UINPUT_VERSION: ::c_uint = 5;
pub const UINPUT_MAX_NAME_SIZE: usize = 80;
+// bionic/libc/kernel/uapi/linux/if_tun.h
pub const IFF_TUN: ::c_int = 0x0001;
pub const IFF_TAP: ::c_int = 0x0002;
+pub const IFF_NAPI: ::c_int = 0x0010;
+pub const IFF_NAPI_FRAGS: ::c_int = 0x0020;
pub const IFF_NO_PI: ::c_int = 0x1000;
+pub const IFF_ONE_QUEUE: ::c_int = 0x2000;
+pub const IFF_VNET_HDR: ::c_int = 0x4000;
+pub const IFF_TUN_EXCL: ::c_int = 0x8000;
+pub const IFF_MULTI_QUEUE: ::c_int = 0x0100;
+pub const IFF_ATTACH_QUEUE: ::c_int = 0x0200;
+pub const IFF_DETACH_QUEUE: ::c_int = 0x0400;
+pub const IFF_PERSIST: ::c_int = 0x0800;
+pub const IFF_NOFILTER: ::c_int = 0x1000;
// start android/platform/bionic/libc/kernel/uapi/linux/if_ether.h
// from https://android.googlesource.com/
@@ -2615,10 +2626,10 @@ pub const IN_Q_OVERFLOW: u32 = 0x0000_4000;
pub const IN_IGNORED: u32 = 0x0000_8000;
pub const IN_ONLYDIR: u32 = 0x0100_0000;
pub const IN_DONT_FOLLOW: u32 = 0x0200_0000;
-// pub const IN_EXCL_UNLINK: u32 = 0x0400_0000;
+pub const IN_EXCL_UNLINK: u32 = 0x0400_0000;
-// pub const IN_MASK_CREATE: u32 = 0x1000_0000;
-// pub const IN_MASK_ADD: u32 = 0x2000_0000;
+pub const IN_MASK_CREATE: u32 = 0x1000_0000;
+pub const IN_MASK_ADD: u32 = 0x2000_0000;
pub const IN_ISDIR: u32 = 0x4000_0000;
pub const IN_ONESHOT: u32 = 0x8000_0000;
@@ -2739,6 +2750,12 @@ pub const PF_VSOCK: ::c_int = AF_VSOCK;
pub const SOMAXCONN: ::c_int = 128;
+// sys/prctl.h
+pub const PR_SET_PDEATHSIG: ::c_int = 1;
+pub const PR_GET_PDEATHSIG: ::c_int = 2;
+pub const PR_GET_SECUREBITS: ::c_int = 27;
+pub const PR_SET_SECUREBITS: ::c_int = 28;
+
// sys/system_properties.h
pub const PROP_VALUE_MAX: ::c_int = 92;
pub const PROP_NAME_MAX: ::c_int = 32;
@@ -3446,6 +3463,10 @@ extern "C" {
pub fn gettid() -> ::pid_t;
+ pub fn getrandom(buf: *mut ::c_void, buflen: ::size_t, flags: ::c_uint) -> ::ssize_t;
+
+ pub fn pthread_setname_np(thread: ::pthread_t, name: *const ::c_char) -> ::c_int;
+
pub fn __system_property_set(__name: *const ::c_char, __value: *const ::c_char) -> ::c_int;
pub fn __system_property_get(__name: *const ::c_char, __value: *mut ::c_char) -> ::c_int;
pub fn __system_property_find(__name: *const ::c_char) -> *const prop_info;
diff --git a/vendor/libc/src/unix/linux_like/emscripten/mod.rs b/vendor/libc/src/unix/linux_like/emscripten/mod.rs
index 11fbb31c3..f2024900c 100644
--- a/vendor/libc/src/unix/linux_like/emscripten/mod.rs
+++ b/vendor/libc/src/unix/linux_like/emscripten/mod.rs
@@ -1763,7 +1763,6 @@ extern "C" {
pub fn strerror_r(errnum: ::c_int, buf: *mut c_char, buflen: ::size_t) -> ::c_int;
pub fn abs(i: ::c_int) -> ::c_int;
- pub fn atof(s: *const ::c_char) -> ::c_double;
pub fn labs(i: ::c_long) -> ::c_long;
pub fn rand() -> ::c_int;
pub fn srand(seed: ::c_uint);
diff --git a/vendor/libc/src/unix/linux_like/linux/mod.rs b/vendor/libc/src/unix/linux_like/linux/mod.rs
index f0a0820c3..9658f0744 100644
--- a/vendor/libc/src/unix/linux_like/linux/mod.rs
+++ b/vendor/libc/src/unix/linux_like/linux/mod.rs
@@ -1583,6 +1583,10 @@ pub const AT_HWCAP2: ::c_ulong = 26;
pub const AT_EXECFN: ::c_ulong = 31;
+// defined in arch/<arch>/include/uapi/asm/auxvec.h but has the same value
+// wherever it is defined.
+pub const AT_SYSINFO_EHDR: ::c_ulong = 33;
+
pub const GLOB_ERR: ::c_int = 1 << 0;
pub const GLOB_MARK: ::c_int = 1 << 1;
pub const GLOB_NOSORT: ::c_int = 1 << 2;
@@ -3061,7 +3065,7 @@ pub const IN_Q_OVERFLOW: u32 = 0x0000_4000;
pub const IN_IGNORED: u32 = 0x0000_8000;
pub const IN_ONLYDIR: u32 = 0x0100_0000;
pub const IN_DONT_FOLLOW: u32 = 0x0200_0000;
-// pub const IN_EXCL_UNLINK: u32 = 0x0400_0000;
+pub const IN_EXCL_UNLINK: u32 = 0x0400_0000;
// linux/keyctl.h
pub const KEY_SPEC_THREAD_KEYRING: i32 = -1;
@@ -3107,8 +3111,8 @@ pub const KEYCTL_INSTANTIATE_IOV: u32 = 20;
pub const KEYCTL_INVALIDATE: u32 = 21;
pub const KEYCTL_GET_PERSISTENT: u32 = 22;
-// pub const IN_MASK_CREATE: u32 = 0x1000_0000;
-// pub const IN_MASK_ADD: u32 = 0x2000_0000;
+pub const IN_MASK_CREATE: u32 = 0x1000_0000;
+pub const IN_MASK_ADD: u32 = 0x2000_0000;
pub const IN_ISDIR: u32 = 0x4000_0000;
pub const IN_ONESHOT: u32 = 0x8000_0000;
@@ -3800,7 +3804,6 @@ extern "C" {
pub fn strerror_r(errnum: ::c_int, buf: *mut c_char, buflen: ::size_t) -> ::c_int;
pub fn abs(i: ::c_int) -> ::c_int;
- pub fn atof(s: *const ::c_char) -> ::c_double;
pub fn labs(i: ::c_long) -> ::c_long;
pub fn rand() -> ::c_int;
pub fn srand(seed: ::c_uint);
diff --git a/vendor/libc/src/unix/linux_like/mod.rs b/vendor/libc/src/unix/linux_like/mod.rs
index 8e738d87b..e2e73b330 100644
--- a/vendor/libc/src/unix/linux_like/mod.rs
+++ b/vendor/libc/src/unix/linux_like/mod.rs
@@ -1615,6 +1615,14 @@ safe_f! {
pub {const} fn IPTOS_ECN(x: u8) -> u8 {
x & ::IPTOS_ECN_MASK
}
+
+ #[allow(ellipsis_inclusive_range_patterns)]
+ pub {const} fn KERNEL_VERSION(a: u32, b: u32, c: u32) -> u32 {
+ ((a << 16) + (b << 8)) + match c {
+ 0 ... 255 => c,
+ _ => 255,
+ }
+ }
}
extern "C" {
diff --git a/vendor/libc/src/unix/mod.rs b/vendor/libc/src/unix/mod.rs
index fb9ebf792..826b83518 100644
--- a/vendor/libc/src/unix/mod.rs
+++ b/vendor/libc/src/unix/mod.rs
@@ -32,6 +32,9 @@ cfg_if! {
if #[cfg(any(target_os = "espidf", target_os = "horizon"))] {
pub type uid_t = ::c_ushort;
pub type gid_t = ::c_ushort;
+ } else if #[cfg(target_os = "nto")] {
+ pub type uid_t = i32;
+ pub type gid_t = i32;
} else {
pub type uid_t = u32;
pub type gid_t = u32;
@@ -209,25 +212,31 @@ pub const INT_MAX: c_int = 2147483647;
pub const SIG_DFL: sighandler_t = 0 as sighandler_t;
pub const SIG_IGN: sighandler_t = 1 as sighandler_t;
pub const SIG_ERR: sighandler_t = !0 as sighandler_t;
-
-pub const DT_UNKNOWN: u8 = 0;
-pub const DT_FIFO: u8 = 1;
-pub const DT_CHR: u8 = 2;
-pub const DT_DIR: u8 = 4;
-pub const DT_BLK: u8 = 6;
-pub const DT_REG: u8 = 8;
-pub const DT_LNK: u8 = 10;
-pub const DT_SOCK: u8 = 12;
-
+cfg_if! {
+ if #[cfg(not(target_os = "nto"))] {
+ pub const DT_UNKNOWN: u8 = 0;
+ pub const DT_FIFO: u8 = 1;
+ pub const DT_CHR: u8 = 2;
+ pub const DT_DIR: u8 = 4;
+ pub const DT_BLK: u8 = 6;
+ pub const DT_REG: u8 = 8;
+ pub const DT_LNK: u8 = 10;
+ pub const DT_SOCK: u8 = 12;
+ }
+}
cfg_if! {
if #[cfg(not(target_os = "redox"))] {
pub const FD_CLOEXEC: ::c_int = 0x1;
}
}
-pub const USRQUOTA: ::c_int = 0;
-pub const GRPQUOTA: ::c_int = 1;
-
+cfg_if! {
+ if #[cfg(not(target_os = "nto"))]
+ {
+ pub const USRQUOTA: ::c_int = 0;
+ pub const GRPQUOTA: ::c_int = 1;
+ }
+}
pub const SIGIOT: ::c_int = 6;
pub const S_ISUID: ::mode_t = 0x800;
@@ -281,9 +290,13 @@ cfg_if! {
pub const LOG_PRIMASK: ::c_int = 7;
pub const LOG_FACMASK: ::c_int = 0x3f8;
-pub const PRIO_MIN: ::c_int = -20;
-pub const PRIO_MAX: ::c_int = 20;
-
+cfg_if! {
+ if #[cfg(not(target_os = "nto"))]
+ {
+ pub const PRIO_MIN: ::c_int = -20;
+ pub const PRIO_MAX: ::c_int = 20;
+ }
+}
pub const IPPROTO_ICMP: ::c_int = 1;
pub const IPPROTO_ICMPV6: ::c_int = 58;
pub const IPPROTO_TCP: ::c_int = 6;
@@ -361,7 +374,9 @@ cfg_if! {
target_os = "tvos",
target_os = "watchos",
target_os = "android",
- target_os = "openbsd"))] {
+ target_os = "openbsd",
+ target_os = "nto",
+ ))] {
#[link(name = "c")]
#[link(name = "m")]
extern {}
@@ -453,8 +468,6 @@ extern "C" {
link_name = "freopen$UNIX2003"
)]
pub fn freopen(filename: *const c_char, mode: *const c_char, file: *mut FILE) -> *mut FILE;
- pub fn fmemopen(buf: *mut c_void, size: size_t, mode: *const c_char) -> *mut FILE;
- pub fn open_memstream(ptr: *mut *mut c_char, sizeloc: *mut size_t) -> *mut FILE;
pub fn fflush(file: *mut FILE) -> c_int;
pub fn fclose(file: *mut FILE) -> c_int;
@@ -492,7 +505,10 @@ extern "C" {
pub fn ferror(stream: *mut FILE) -> c_int;
pub fn clearerr(stream: *mut FILE);
pub fn perror(s: *const c_char);
+ pub fn atof(s: *const c_char) -> c_double;
pub fn atoi(s: *const c_char) -> c_int;
+ pub fn atol(s: *const c_char) -> c_long;
+ pub fn atoll(s: *const c_char) -> c_longlong;
#[cfg_attr(
all(target_os = "macos", target_arch = "x86"),
link_name = "strtod$UNIX2003"
@@ -500,7 +516,9 @@ extern "C" {
pub fn strtod(s: *const c_char, endp: *mut *mut c_char) -> c_double;
pub fn strtof(s: *const c_char, endp: *mut *mut c_char) -> c_float;
pub fn strtol(s: *const c_char, endp: *mut *mut c_char, base: c_int) -> c_long;
+ pub fn strtoll(s: *const c_char, endp: *mut *mut c_char, base: c_int) -> c_longlong;
pub fn strtoul(s: *const c_char, endp: *mut *mut c_char, base: c_int) -> c_ulong;
+ pub fn strtoull(s: *const c_char, endp: *mut *mut c_char, base: c_int) -> c_ulonglong;
pub fn calloc(nobj: size_t, size: size_t) -> *mut c_void;
pub fn malloc(size: size_t) -> *mut c_void;
pub fn realloc(p: *mut c_void, size: size_t) -> *mut c_void;
@@ -508,7 +526,6 @@ extern "C" {
pub fn abort() -> !;
pub fn exit(status: c_int) -> !;
pub fn _exit(status: c_int) -> !;
- pub fn atexit(cb: extern "C" fn()) -> c_int;
#[cfg_attr(
all(target_os = "macos", target_arch = "x86"),
link_name = "system$UNIX2003"
@@ -1162,8 +1179,6 @@ extern "C" {
optlen: *mut ::socklen_t,
) -> ::c_int;
pub fn raise(signum: ::c_int) -> ::c_int;
- #[cfg_attr(target_os = "netbsd", link_name = "__sigaction14")]
- pub fn sigaction(signum: ::c_int, act: *const sigaction, oldact: *mut sigaction) -> ::c_int;
#[cfg_attr(target_os = "netbsd", link_name = "__utimes50")]
pub fn utimes(filename: *const ::c_char, times: *const ::timeval) -> ::c_int;
@@ -1325,8 +1340,6 @@ extern "C" {
pub fn statvfs(path: *const c_char, buf: *mut statvfs) -> ::c_int;
pub fn fstatvfs(fd: ::c_int, buf: *mut statvfs) -> ::c_int;
- pub fn readlink(path: *const c_char, buf: *mut c_char, bufsz: ::size_t) -> ::ssize_t;
-
#[cfg_attr(target_os = "netbsd", link_name = "__sigemptyset14")]
pub fn sigemptyset(set: *mut sigset_t) -> ::c_int;
#[cfg_attr(target_os = "netbsd", link_name = "__sigaddset14")]
@@ -1347,23 +1360,6 @@ extern "C" {
pub fn mkfifo(path: *const c_char, mode: mode_t) -> ::c_int;
- #[cfg_attr(
- all(target_os = "macos", target_arch = "x86_64"),
- link_name = "pselect$1050"
- )]
- #[cfg_attr(
- all(target_os = "macos", target_arch = "x86"),
- link_name = "pselect$UNIX2003"
- )]
- #[cfg_attr(target_os = "netbsd", link_name = "__pselect50")]
- pub fn pselect(
- nfds: ::c_int,
- readfds: *mut fd_set,
- writefds: *mut fd_set,
- errorfds: *mut fd_set,
- timeout: *const timespec,
- sigmask: *const sigset_t,
- ) -> ::c_int;
pub fn fseeko(stream: *mut ::FILE, offset: ::off_t, whence: ::c_int) -> ::c_int;
pub fn ftello(stream: *mut ::FILE) -> ::off_t;
#[cfg_attr(
@@ -1411,7 +1407,8 @@ extern "C" {
cfg_if! {
if #[cfg(not(any(target_os = "emscripten",
target_os = "android",
- target_os = "haiku")))] {
+ target_os = "haiku",
+ target_os = "nto")))] {
extern "C" {
pub fn adjtime(delta: *const timeval, olddelta: *mut timeval) -> ::c_int;
pub fn stpncpy(dst: *mut c_char, src: *const c_char, n: size_t) -> *mut c_char;
@@ -1420,7 +1417,7 @@ cfg_if! {
}
cfg_if! {
- if #[cfg(not(target_env = "uclibc"))] {
+ if #[cfg(not(any(target_env = "uclibc", target_os = "nto")))] {
extern "C" {
pub fn open_wmemstream(
ptr: *mut *mut wchar_t,
@@ -1439,12 +1436,8 @@ cfg_if! {
link_name = "pause$UNIX2003")]
pub fn pause() -> ::c_int;
- pub fn readlinkat(dirfd: ::c_int,
- pathname: *const ::c_char,
- buf: *mut ::c_char,
- bufsiz: ::size_t) -> ::ssize_t;
pub fn mkdirat(dirfd: ::c_int, pathname: *const ::c_char,
- mode: ::mode_t) -> ::c_int;
+ mode: ::mode_t) -> ::c_int;
pub fn openat(dirfd: ::c_int, pathname: *const ::c_char,
flags: ::c_int, ...) -> ::c_int;
@@ -1475,7 +1468,64 @@ cfg_if! {
}
cfg_if! {
- if #[cfg(not(any(target_os = "solaris", target_os = "illumos")))] {
+ if #[cfg(target_os = "nto")] {
+ extern {
+ pub fn readlinkat(dirfd: ::c_int,
+ pathname: *const ::c_char,
+ buf: *mut ::c_char,
+ bufsiz: ::size_t) -> ::c_int;
+ pub fn readlink(path: *const c_char, buf: *mut c_char, bufsz: ::size_t) -> ::c_int;
+ pub fn pselect(
+ nfds: ::c_int,
+ readfds: *mut fd_set,
+ writefds: *mut fd_set,
+ errorfds: *mut fd_set,
+ timeout: *mut timespec,
+ sigmask: *const sigset_t,
+ ) -> ::c_int;
+ }
+ } else {
+ extern {
+ pub fn readlinkat(dirfd: ::c_int,
+ pathname: *const ::c_char,
+ buf: *mut ::c_char,
+ bufsiz: ::size_t) -> ::ssize_t;
+ pub fn fmemopen(buf: *mut c_void, size: size_t, mode: *const c_char) -> *mut FILE;
+ pub fn open_memstream(ptr: *mut *mut c_char, sizeloc: *mut size_t) -> *mut FILE;
+ pub fn atexit(cb: extern "C" fn()) -> c_int;
+ #[cfg_attr(target_os = "netbsd", link_name = "__sigaction14")]
+ pub fn sigaction(
+ signum: ::c_int,
+ act: *const sigaction,
+ oldact: *mut sigaction
+ ) -> ::c_int;
+ pub fn readlink(path: *const c_char, buf: *mut c_char, bufsz: ::size_t) -> ::ssize_t;
+ #[cfg_attr(
+ all(target_os = "macos", target_arch = "x86_64"),
+ link_name = "pselect$1050"
+ )]
+ #[cfg_attr(
+ all(target_os = "macos", target_arch = "x86"),
+ link_name = "pselect$UNIX2003"
+ )]
+ #[cfg_attr(target_os = "netbsd", link_name = "__pselect50")]
+ pub fn pselect(
+ nfds: ::c_int,
+ readfds: *mut fd_set,
+ writefds: *mut fd_set,
+ errorfds: *mut fd_set,
+ timeout: *const timespec,
+ sigmask: *const sigset_t,
+ ) -> ::c_int;
+ }
+ }
+}
+
+cfg_if! {
+ if #[cfg(not(any(target_os = "solaris",
+ target_os = "illumos",
+ target_os = "nto",
+ )))] {
extern {
pub fn cfmakeraw(termios: *mut ::termios);
pub fn cfsetspeed(termios: *mut ::termios,
@@ -1517,6 +1567,9 @@ cfg_if! {
} else if #[cfg(target_os = "redox")] {
mod redox;
pub use self::redox::*;
+ } else if #[cfg(target_os = "nto")] {
+ mod nto;
+ pub use self::nto::*;
} else {
// Unknown target_os
}
diff --git a/vendor/libc/src/unix/newlib/mod.rs b/vendor/libc/src/unix/newlib/mod.rs
index 1a694691a..3875f1cb4 100644
--- a/vendor/libc/src/unix/newlib/mod.rs
+++ b/vendor/libc/src/unix/newlib/mod.rs
@@ -621,7 +621,6 @@ extern "C" {
pub fn sem_init(sem: *mut sem_t, pshared: ::c_int, value: ::c_uint) -> ::c_int;
pub fn abs(i: ::c_int) -> ::c_int;
- pub fn atof(s: *const ::c_char) -> ::c_double;
pub fn labs(i: ::c_long) -> ::c_long;
pub fn rand() -> ::c_int;
pub fn srand(seed: ::c_uint);
diff --git a/vendor/libc/src/unix/nto/aarch64.rs b/vendor/libc/src/unix/nto/aarch64.rs
new file mode 100644
index 000000000..6faf8159c
--- /dev/null
+++ b/vendor/libc/src/unix/nto/aarch64.rs
@@ -0,0 +1,36 @@
+pub type c_char = u8;
+pub type wchar_t = u32;
+pub type c_long = i64;
+pub type c_ulong = u64;
+pub type time_t = i64;
+
+s! {
+ pub struct aarch64_qreg_t {
+ pub qlo: u64,
+ pub qhi: u64,
+ }
+
+ pub struct aarch64_fpu_registers {
+ pub reg: [::aarch64_qreg_t; 32],
+ pub fpsr: u32,
+ pub fpcr: u32,
+ }
+
+ pub struct aarch64_cpu_registers {
+ pub gpr: [u64; 32],
+ pub elr: u64,
+ pub pstate: u64,
+ }
+
+ #[repr(align(16))]
+ pub struct mcontext_t {
+ pub cpu: ::aarch64_cpu_registers,
+ pub fpu: ::aarch64_fpu_registers,
+ }
+
+ pub struct stack_t {
+ pub ss_sp: *mut ::c_void,
+ pub ss_size: ::size_t,
+ pub ss_flags: ::c_int,
+ }
+}
diff --git a/vendor/libc/src/unix/nto/mod.rs b/vendor/libc/src/unix/nto/mod.rs
new file mode 100644
index 000000000..45e97ceac
--- /dev/null
+++ b/vendor/libc/src/unix/nto/mod.rs
@@ -0,0 +1,3286 @@
+pub type clock_t = u32;
+
+pub type sa_family_t = u8;
+pub type speed_t = ::c_uint;
+pub type tcflag_t = ::c_uint;
+pub type clockid_t = ::c_int;
+pub type timer_t = ::c_int;
+pub type key_t = ::c_uint;
+pub type id_t = ::c_int;
+
+pub type useconds_t = u32;
+pub type dev_t = u32;
+pub type socklen_t = u32;
+pub type mode_t = u32;
+pub type rlim64_t = u64;
+pub type mqd_t = ::c_int;
+pub type nfds_t = ::c_uint;
+pub type idtype_t = ::c_uint;
+pub type errno_t = ::c_int;
+pub type rsize_t = c_ulong;
+
+pub type Elf32_Half = u16;
+pub type Elf32_Word = u32;
+pub type Elf32_Off = u32;
+pub type Elf32_Addr = u32;
+pub type Elf32_Lword = u64;
+pub type Elf32_Sword = i32;
+
+pub type Elf64_Half = u16;
+pub type Elf64_Word = u32;
+pub type Elf64_Off = u64;
+pub type Elf64_Addr = u64;
+pub type Elf64_Xword = u64;
+pub type Elf64_Sxword = i64;
+pub type Elf64_Lword = u64;
+pub type Elf64_Sword = i32;
+
+pub type Elf32_Section = u16;
+pub type Elf64_Section = u16;
+
+pub type _Time32t = u32;
+
+pub type pthread_t = ::c_int;
+pub type regoff_t = ::ssize_t;
+
+pub type nlink_t = u32;
+pub type blksize_t = u32;
+pub type suseconds_t = i32;
+
+pub type ino_t = u64;
+pub type off_t = i64;
+pub type blkcnt_t = u64;
+pub type msgqnum_t = u64;
+pub type msglen_t = u64;
+pub type fsblkcnt_t = u64;
+pub type fsfilcnt_t = u64;
+pub type rlim_t = u64;
+pub type posix_spawn_file_actions_t = *mut ::c_void;
+pub type posix_spawnattr_t = ::uintptr_t;
+
+pub type pthread_mutex_t = ::sync_t;
+pub type pthread_mutexattr_t = ::_sync_attr;
+pub type pthread_cond_t = ::sync_t;
+pub type pthread_condattr_t = ::_sync_attr;
+pub type pthread_rwlockattr_t = ::_sync_attr;
+pub type pthread_key_t = ::c_int;
+pub type pthread_spinlock_t = sync_t;
+pub type pthread_barrierattr_t = _sync_attr;
+pub type sem_t = sync_t;
+
+pub type nl_item = ::c_int;
+
+#[cfg_attr(feature = "extra_traits", derive(Debug))]
+pub enum timezone {}
+impl ::Copy for timezone {}
+impl ::Clone for timezone {
+ fn clone(&self) -> timezone {
+ *self
+ }
+}
+
+s! {
+ pub struct ip_mreq {
+ pub imr_multiaddr: in_addr,
+ pub imr_interface: in_addr,
+ }
+
+ #[repr(packed)]
+ pub struct in_addr {
+ pub s_addr: ::in_addr_t,
+ }
+
+ pub struct sockaddr {
+ pub sa_len: u8,
+ pub sa_family: sa_family_t,
+ pub sa_data: [::c_char; 14],
+ }
+
+ 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: [i8; 8],
+ }
+
+ 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,
+ }
+
+ // The order of the `ai_addr` field in this struct is crucial
+ // for converting between the Rust and C types.
+ 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_canonname: *mut c_char,
+ pub ai_addr: *mut ::sockaddr,
+ pub ai_next: *mut addrinfo,
+ }
+
+ pub struct fd_set {
+ fds_bits: [::c_uint; 2 * FD_SETSIZE / ULONG_SIZE],
+ }
+
+ pub struct tm {
+ pub tm_sec: ::c_int,
+ pub tm_min: ::c_int,
+ pub tm_hour: ::c_int,
+ pub tm_mday: ::c_int,
+ pub tm_mon: ::c_int,
+ pub tm_year: ::c_int,
+ pub tm_wday: ::c_int,
+ pub tm_yday: ::c_int,
+ pub tm_isdst: ::c_int,
+ pub tm_gmtoff: ::c_long,
+ pub tm_zone: *const ::c_char,
+ }
+
+ #[repr(align(8))]
+ pub struct sched_param {
+ pub sched_priority: ::c_int,
+ pub sched_curpriority: ::c_int,
+ pub reserved: [::c_int; 10],
+ }
+
+ #[repr(align(8))]
+ pub struct __sched_param {
+ pub __sched_priority: ::c_int,
+ pub __sched_curpriority: ::c_int,
+ pub reserved: [::c_int; 10],
+ }
+
+ pub struct Dl_info {
+ pub dli_fname: *const ::c_char,
+ pub dli_fbase: *mut ::c_void,
+ pub dli_sname: *const ::c_char,
+ pub dli_saddr: *mut ::c_void,
+ }
+
+ pub struct lconv {
+ pub currency_symbol: *mut ::c_char,
+ pub int_curr_symbol: *mut ::c_char,
+ pub mon_decimal_point: *mut ::c_char,
+ pub mon_grouping: *mut ::c_char,
+ pub mon_thousands_sep: *mut ::c_char,
+ pub negative_sign: *mut ::c_char,
+ pub positive_sign: *mut ::c_char,
+ pub frac_digits: ::c_char,
+ pub int_frac_digits: ::c_char,
+ pub n_cs_precedes: ::c_char,
+ pub n_sep_by_space: ::c_char,
+ pub n_sign_posn: ::c_char,
+ pub p_cs_precedes: ::c_char,
+ pub p_sep_by_space: ::c_char,
+ pub p_sign_posn: ::c_char,
+
+ pub int_n_cs_precedes: ::c_char,
+ pub int_n_sep_by_space: ::c_char,
+ pub int_n_sign_posn: ::c_char,
+ pub int_p_cs_precedes: ::c_char,
+ pub int_p_sep_by_space: ::c_char,
+ pub int_p_sign_posn: ::c_char,
+
+ pub decimal_point: *mut ::c_char,
+ pub grouping: *mut ::c_char,
+ pub thousands_sep: *mut ::c_char,
+
+ pub _Frac_grouping: *mut ::c_char,
+ pub _Frac_sep: *mut ::c_char,
+ pub _False: *mut ::c_char,
+ pub _True: *mut ::c_char,
+
+ pub _No: *mut ::c_char,
+ pub _Yes: *mut ::c_char,
+ pub _Nostr: *mut ::c_char,
+ pub _Yesstr: *mut ::c_char,
+ pub _Reserved: [*mut ::c_char; 8],
+ }
+
+ pub struct in_pktinfo {
+ pub ipi_addr: ::in_addr,
+ pub ipi_ifindex: ::c_uint,
+ }
+
+ pub struct ifaddrs {
+ pub ifa_next: *mut ifaddrs,
+ pub ifa_name: *mut c_char,
+ pub ifa_flags: ::c_uint,
+ pub ifa_addr: *mut ::sockaddr,
+ pub ifa_netmask: *mut ::sockaddr,
+ pub ifa_dstaddr: *mut ::sockaddr,
+ pub ifa_data: *mut ::c_void
+ }
+
+ pub struct arpreq {
+ pub arp_pa: ::sockaddr,
+ pub arp_ha: ::sockaddr,
+ pub arp_flags: ::c_int,
+ }
+
+ #[repr(packed)]
+ pub struct arphdr {
+ pub ar_hrd: u16,
+ pub ar_pro: u16,
+ pub ar_hln: u8,
+ pub ar_pln: u8,
+ pub ar_op: u16,
+ }
+
+ pub struct mmsghdr {
+ pub msg_hdr: ::msghdr,
+ pub msg_len: ::c_uint,
+ }
+
+ #[repr(align(8))]
+ pub struct siginfo_t {
+ pub si_signo: ::c_int,
+ pub si_code: ::c_int,
+ pub si_errno: ::c_int,
+ __data: [u8; 36], // union
+ }
+
+ pub struct sigaction {
+ pub sa_sigaction: ::sighandler_t,
+ pub sa_flags: ::c_int,
+ pub sa_mask: ::sigset_t,
+ }
+
+ pub struct _sync {
+ _union: ::c_uint,
+ __owner: ::c_uint,
+ }
+ pub struct rlimit64 {
+ pub rlim_cur: rlim64_t,
+ pub rlim_max: rlim64_t,
+ }
+
+ pub struct glob_t {
+ pub gl_pathc: ::size_t,
+ pub gl_matchc: ::c_int,
+ pub gl_pathv: *mut *mut c_char,
+ pub gl_offs: ::size_t,
+ pub gl_flags: ::c_int,
+ pub gl_errfunc: extern "C" fn(*const ::c_char, ::c_int) -> ::c_int,
+
+ __unused1: *mut ::c_void,
+ __unused2: *mut ::c_void,
+ __unused3: *mut ::c_void,
+ __unused4: *mut ::c_void,
+ __unused5: *mut ::c_void,
+ }
+
+ pub struct passwd {
+ pub pw_name: *mut ::c_char,
+ pub pw_passwd: *mut ::c_char,
+ pub pw_uid: ::uid_t,
+ pub pw_gid: ::gid_t,
+ pub pw_age: *mut ::c_char,
+ pub pw_comment: *mut ::c_char,
+ pub pw_gecos: *mut ::c_char,
+ pub pw_dir: *mut ::c_char,
+ pub pw_shell: *mut ::c_char,
+ }
+
+ pub struct if_nameindex {
+ pub if_index: ::c_uint,
+ pub if_name: *mut ::c_char,
+ }
+
+ pub struct sembuf {
+ pub sem_num: ::c_ushort,
+ pub sem_op: ::c_short,
+ pub sem_flg: ::c_short,
+ }
+
+ pub struct Elf32_Ehdr {
+ pub e_ident: [::c_uchar; 16],
+ pub e_type: Elf32_Half,
+ pub e_machine: Elf32_Half,
+ pub e_version: Elf32_Word,
+ pub e_entry: Elf32_Addr,
+ pub e_phoff: Elf32_Off,
+ pub e_shoff: Elf32_Off,
+ pub e_flags: Elf32_Word,
+ pub e_ehsize: Elf32_Half,
+ pub e_phentsize: Elf32_Half,
+ pub e_phnum: Elf32_Half,
+ pub e_shentsize: Elf32_Half,
+ pub e_shnum: Elf32_Half,
+ pub e_shstrndx: Elf32_Half,
+ }
+
+ pub struct Elf64_Ehdr {
+ pub e_ident: [::c_uchar; 16],
+ pub e_type: Elf64_Half,
+ pub e_machine: Elf64_Half,
+ pub e_version: Elf64_Word,
+ pub e_entry: Elf64_Addr,
+ pub e_phoff: Elf64_Off,
+ pub e_shoff: Elf64_Off,
+ pub e_flags: Elf64_Word,
+ pub e_ehsize: Elf64_Half,
+ pub e_phentsize: Elf64_Half,
+ pub e_phnum: Elf64_Half,
+ pub e_shentsize: Elf64_Half,
+ pub e_shnum: Elf64_Half,
+ pub e_shstrndx: Elf64_Half,
+ }
+
+ pub struct Elf32_Sym {
+ pub st_name: Elf32_Word,
+ pub st_value: Elf32_Addr,
+ pub st_size: Elf32_Word,
+ pub st_info: ::c_uchar,
+ pub st_other: ::c_uchar,
+ pub st_shndx: Elf32_Section,
+ }
+
+ pub struct Elf64_Sym {
+ pub st_name: Elf64_Word,
+ pub st_info: ::c_uchar,
+ pub st_other: ::c_uchar,
+ pub st_shndx: Elf64_Section,
+ pub st_value: Elf64_Addr,
+ pub st_size: Elf64_Xword,
+ }
+
+ pub struct Elf32_Phdr {
+ pub p_type: Elf32_Word,
+ pub p_offset: Elf32_Off,
+ pub p_vaddr: Elf32_Addr,
+ pub p_paddr: Elf32_Addr,
+ pub p_filesz: Elf32_Word,
+ pub p_memsz: Elf32_Word,
+ pub p_flags: Elf32_Word,
+ pub p_align: Elf32_Word,
+ }
+
+ pub struct Elf64_Phdr {
+ pub p_type: Elf64_Word,
+ pub p_flags: Elf64_Word,
+ pub p_offset: Elf64_Off,
+ pub p_vaddr: Elf64_Addr,
+ pub p_paddr: Elf64_Addr,
+ pub p_filesz: Elf64_Xword,
+ pub p_memsz: Elf64_Xword,
+ pub p_align: Elf64_Xword,
+ }
+
+ pub struct Elf32_Shdr {
+ pub sh_name: Elf32_Word,
+ pub sh_type: Elf32_Word,
+ pub sh_flags: Elf32_Word,
+ pub sh_addr: Elf32_Addr,
+ pub sh_offset: Elf32_Off,
+ pub sh_size: Elf32_Word,
+ pub sh_link: Elf32_Word,
+ pub sh_info: Elf32_Word,
+ pub sh_addralign: Elf32_Word,
+ pub sh_entsize: Elf32_Word,
+ }
+
+ pub struct Elf64_Shdr {
+ pub sh_name: Elf64_Word,
+ pub sh_type: Elf64_Word,
+ pub sh_flags: Elf64_Xword,
+ pub sh_addr: Elf64_Addr,
+ pub sh_offset: Elf64_Off,
+ pub sh_size: Elf64_Xword,
+ pub sh_link: Elf64_Word,
+ pub sh_info: Elf64_Word,
+ pub sh_addralign: Elf64_Xword,
+ pub sh_entsize: Elf64_Xword,
+ }
+
+ pub struct in6_pktinfo {
+ pub ipi6_addr: ::in6_addr,
+ pub ipi6_ifindex: ::c_uint,
+ }
+
+ pub struct inotify_event {
+ pub wd: ::c_int,
+ pub mask: u32,
+ pub cookie: u32,
+ pub len: u32
+ }
+
+ pub struct regmatch_t {
+ pub rm_so: regoff_t,
+ pub rm_eo: regoff_t,
+ }
+
+ 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,
+ }
+
+ pub struct cmsghdr {
+ pub cmsg_len: ::socklen_t,
+ pub cmsg_level: ::c_int,
+ pub cmsg_type: ::c_int,
+ }
+
+ pub struct termios {
+ pub c_iflag: ::tcflag_t,
+ pub c_oflag: ::tcflag_t,
+ pub c_cflag: ::tcflag_t,
+ pub c_lflag: ::tcflag_t,
+ pub c_cc: [::cc_t; ::NCCS],
+ __reserved: [::c_uint; 3],
+ pub c_ispeed: ::speed_t,
+ pub c_ospeed: ::speed_t,
+ }
+
+ pub struct mallinfo {
+ pub arena: ::c_int,
+ pub ordblks: ::c_int,
+ pub smblks: ::c_int,
+ pub hblks: ::c_int,
+ pub hblkhd: ::c_int,
+ pub usmblks: ::c_int,
+ pub fsmblks: ::c_int,
+ pub uordblks: ::c_int,
+ pub fordblks: ::c_int,
+ pub keepcost: ::c_int,
+ }
+
+ pub struct flock {
+ pub l_type: i16,
+ pub l_whence: i16,
+ pub l_zero1: i32,
+ pub l_start: ::off_t,
+ pub l_len: ::off_t,
+ pub l_pid: ::pid_t,
+ pub l_sysid: u32,
+ }
+
+ pub struct statvfs {
+ pub f_bsize: ::c_ulong,
+ pub f_frsize: ::c_ulong,
+ pub f_blocks: ::fsblkcnt_t,
+ pub f_bfree: ::fsblkcnt_t,
+ pub f_bavail: ::fsblkcnt_t,
+ pub f_files: ::fsfilcnt_t,
+ pub f_ffree: ::fsfilcnt_t,
+ pub f_favail: ::fsfilcnt_t,
+ pub f_fsid: ::c_ulong,
+ pub f_basetype: [::c_char; 16],
+ pub f_flag: ::c_ulong,
+ pub f_namemax: ::c_ulong,
+ f_filler: [::c_uint; 21],
+ }
+
+ pub struct aiocb {
+ pub aio_fildes: ::c_int,
+ pub aio_reqprio: ::c_int,
+ pub aio_offset: off_t,
+ pub aio_buf: *mut ::c_void,
+ pub aio_nbytes: ::size_t,
+ pub aio_sigevent: ::sigevent,
+ pub aio_lio_opcode: ::c_int,
+ pub _aio_lio_state: *mut ::c_void,
+ _aio_pad: [::c_int; 3],
+ pub _aio_next: *mut ::aiocb,
+ pub _aio_flag: ::c_uint,
+ pub _aio_iotype: ::c_uint,
+ pub _aio_result: ::ssize_t,
+ pub _aio_error: ::c_uint,
+ pub _aio_suspend: *mut ::c_void,
+ pub _aio_plist: *mut ::c_void,
+ pub _aio_policy: ::c_int,
+ pub _aio_param: ::__sched_param,
+ }
+
+ pub struct pthread_attr_t {
+ __data1: ::c_long,
+ __data2: [u8; 96]
+ }
+
+ pub struct ipc_perm {
+ pub uid: ::uid_t,
+ pub gid: ::gid_t,
+ pub cuid: ::uid_t,
+ pub cgid: ::gid_t,
+ pub mode: ::mode_t,
+ pub seq: ::c_uint,
+ pub key: ::key_t,
+ _reserved: [::c_int; 4],
+ }
+
+ pub struct regex_t {
+ re_magic: ::c_int,
+ re_nsub: ::size_t,
+ re_endp: *const ::c_char,
+ re_g: *mut ::c_void,
+ }
+
+ pub struct _thread_attr {
+ pub __flags: ::c_int,
+ pub __stacksize: ::size_t,
+ pub __stackaddr: *mut ::c_void,
+ pub __exitfunc: ::Option<unsafe extern "C" fn(_fake: *mut ::c_void)>,
+ pub __policy: ::c_int,
+ pub __param: ::__sched_param,
+ pub __guardsize: ::c_uint,
+ pub __prealloc: ::c_uint,
+ __spare: [::c_int; 2],
+ }
+
+ pub struct _sync_attr {
+ pub __protocol: ::c_int,
+ pub __flags: ::c_int,
+ pub __prioceiling: ::c_int,
+ pub __clockid: ::c_int,
+ pub __count: ::c_int,
+ __reserved: [::c_int; 3],
+ }
+
+ pub struct sockcred {
+ pub sc_uid: ::uid_t,
+ pub sc_euid: ::uid_t,
+ pub sc_gid: ::gid_t,
+ pub sc_egid: ::gid_t,
+ pub sc_ngroups: ::c_int,
+ pub sc_groups: [::gid_t; 1],
+ }
+
+ pub struct bpf_program {
+ pub bf_len: ::c_uint,
+ pub bf_insns: *mut ::bpf_insn,
+ }
+
+ pub struct bpf_stat {
+ pub bs_recv: u64,
+ pub bs_drop: u64,
+ pub bs_capt: u64,
+ bs_padding: [u64; 13],
+ }
+
+ pub struct bpf_version {
+ pub bv_major: ::c_ushort,
+ pub bv_minor: ::c_ushort,
+ }
+
+ pub struct bpf_hdr {
+ pub bh_tstamp: ::timeval,
+ pub bh_caplen: u32,
+ pub bh_datalen: u32,
+ pub bh_hdrlen: u16,
+ }
+
+ pub struct bpf_insn {
+ pub code: u16,
+ pub jt: ::c_uchar,
+ pub jf: ::c_uchar,
+ pub k: u32,
+ }
+
+ pub struct bpf_dltlist {
+ pub bfl_len: ::c_uint,
+ pub bfl_list: *mut ::c_uint,
+ }
+
+ pub struct unpcbid {
+ pub unp_pid: ::pid_t,
+ pub unp_euid: ::uid_t,
+ pub unp_egid: ::gid_t,
+ }
+
+ pub struct dl_phdr_info {
+ pub dlpi_addr: ::Elf64_Addr,
+ pub dlpi_name: *const ::c_char,
+ pub dlpi_phdr: *const ::Elf64_Phdr,
+ pub dlpi_phnum: ::Elf64_Half,
+ }
+
+ #[repr(align(8))]
+ pub struct ucontext_t {
+ pub uc_link: *mut ucontext_t,
+ pub uc_sigmask: ::sigset_t,
+ pub uc_stack: stack_t,
+ pub uc_mcontext: mcontext_t,
+ }
+}
+
+s_no_extra_traits! {
+ pub struct sockaddr_un {
+ pub sun_len: u8,
+ pub sun_family: sa_family_t,
+ pub sun_path: [::c_char; 104]
+ }
+
+ pub struct sockaddr_storage {
+ pub ss_len: u8,
+ pub ss_family: sa_family_t,
+ __ss_pad1: [::c_char; 6],
+ __ss_align: i64,
+ __ss_pad2: [::c_char; 112],
+ }
+
+ pub struct utsname {
+ pub sysname: [::c_char; _SYSNAME_SIZE],
+ pub nodename: [::c_char; _SYSNAME_SIZE],
+ pub release: [::c_char; _SYSNAME_SIZE],
+ pub version: [::c_char; _SYSNAME_SIZE],
+ pub machine: [::c_char; _SYSNAME_SIZE],
+ }
+
+ pub struct sigevent {
+ pub sigev_notify: ::c_int,
+ __sigev_un1: usize, // union
+ pub sigev_value: ::sigval,
+ __sigev_un2: usize, // union
+
+ }
+ pub struct dirent {
+ pub d_ino: ::ino_t,
+ pub d_offset: ::off_t,
+ pub d_reclen: ::c_short,
+ pub d_namelen: ::c_short,
+ pub d_name: [::c_char; 1], // flex array
+ }
+
+ pub struct dirent_extra {
+ pub d_datalen: u16,
+ pub d_type: u16,
+ pub d_reserved: u32,
+ }
+
+ pub struct stat {
+ pub st_ino: ::ino_t,
+ pub st_size: ::off_t,
+ pub st_dev: ::dev_t,
+ pub st_rdev: ::dev_t,
+ pub st_uid: ::uid_t,
+ pub st_gid: ::gid_t,
+ pub __old_st_mtime: ::_Time32t,
+ pub __old_st_atime: ::_Time32t,
+ pub __old_st_ctime: ::_Time32t,
+ pub st_mode: ::mode_t,
+ pub st_nlink: ::nlink_t,
+ pub st_blocksize: ::blksize_t,
+ pub st_nblocks: i32,
+ pub st_blksize: ::blksize_t,
+ pub st_blocks: ::blkcnt_t,
+ pub st_mtim: ::timespec,
+ pub st_atim: ::timespec,
+ pub st_ctim: ::timespec,
+ }
+
+ pub struct sigset_t {
+ __val: [u32; 2],
+ }
+
+ pub struct mq_attr {
+ pub mq_maxmsg: ::c_long,
+ pub mq_msgsize: ::c_long,
+ pub mq_flags: ::c_long,
+ pub mq_curmsgs: ::c_long,
+ pub mq_sendwait: ::c_long,
+ pub mq_recvwait: ::c_long,
+ }
+
+ pub struct msg {
+ pub msg_next: *mut ::msg,
+ pub msg_type: ::c_long,
+ pub msg_ts: ::c_ushort,
+ pub msg_spot: ::c_short,
+ _pad: [u8; 4],
+ }
+
+ pub struct msqid_ds {
+ pub msg_perm: ::ipc_perm,
+ pub msg_first: *mut ::msg,
+ pub msg_last: *mut ::msg,
+ pub msg_cbytes: ::msglen_t,
+ pub msg_qnum: ::msgqnum_t,
+ pub msg_qbytes: ::msglen_t,
+ pub msg_lspid: ::pid_t,
+ pub msg_lrpid: ::pid_t,
+ pub msg_stime: ::time_t,
+ msg_pad1: ::c_long,
+ pub msg_rtime: ::time_t,
+ msg_pad2: ::c_long,
+ pub msg_ctime: ::time_t,
+ msg_pad3: ::c_long,
+ msg_pad4: [::c_long; 4],
+ }
+
+ pub struct sockaddr_dl {
+ pub sdl_len: ::c_uchar,
+ pub sdl_family: ::sa_family_t,
+ pub sdl_index: u16,
+ pub sdl_type: ::c_uchar,
+ pub sdl_nlen: ::c_uchar,
+ pub sdl_alen: ::c_uchar,
+ pub sdl_slen: ::c_uchar,
+ pub sdl_data: [::c_char; 12],
+ }
+
+ pub struct sync_t {
+ __u: ::c_uint, // union
+ pub __owner: ::c_uint,
+ }
+
+ #[repr(align(4))]
+ pub struct pthread_barrier_t { // union
+ __pad: [u8; 28], // union
+ }
+
+ pub struct pthread_rwlock_t {
+ pub __active: ::c_int,
+ pub __blockedwriters: ::c_int,
+ pub __blockedreaders: ::c_int,
+ pub __heavy: ::c_int,
+ pub __lock: ::pthread_mutex_t, // union
+ pub __rcond: ::pthread_cond_t, // union
+ pub __wcond: ::pthread_cond_t, // union
+ pub __owner: ::c_uint,
+ pub __spare: ::c_uint,
+ }
+}
+
+cfg_if! {
+ if #[cfg(feature = "extra_traits")] {
+ impl PartialEq for sockaddr_un {
+ fn eq(&self, other: &sockaddr_un) -> bool {
+ self.sun_len == other.sun_len
+ && self.sun_family == other.sun_family
+ && self
+ .sun_path
+ .iter()
+ .zip(other.sun_path.iter())
+ .all(|(a,b)| a == b)
+ }
+ }
+
+ impl Eq for sockaddr_un {}
+
+ impl ::fmt::Debug for sockaddr_un {
+ fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result {
+ f.debug_struct("sockaddr_un")
+ .field("sun_len", &self.sun_len)
+ .field("sun_family", &self.sun_family)
+ // FIXME: .field("sun_path", &self.sun_path)
+ .finish()
+ }
+ }
+
+ impl ::hash::Hash for sockaddr_un {
+ fn hash<H: ::hash::Hasher>(&self, state: &mut H) {
+ self.sun_len.hash(state);
+ self.sun_family.hash(state);
+ self.sun_path.hash(state);
+ }
+ }
+
+ impl PartialEq for utsname {
+ fn eq(&self, other: &utsname) -> bool {
+ self.sysname
+ .iter()
+ .zip(other.sysname.iter())
+ .all(|(a,b)| a == b)
+ && self
+ .nodename
+ .iter()
+ .zip(other.nodename.iter())
+ .all(|(a,b)| a == b)
+ && self
+ .release
+ .iter()
+ .zip(other.release.iter())
+ .all(|(a,b)| a == b)
+ && self
+ .version
+ .iter()
+ .zip(other.version.iter())
+ .all(|(a,b)| a == b)
+ && self
+ .machine
+ .iter()
+ .zip(other.machine.iter())
+ .all(|(a,b)| a == b)
+ }
+ }
+
+ impl Eq for utsname {}
+
+ impl ::fmt::Debug for utsname {
+ fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result {
+ f.debug_struct("utsname")
+ // FIXME: .field("sysname", &self.sysname)
+ // FIXME: .field("nodename", &self.nodename)
+ // FIXME: .field("release", &self.release)
+ // FIXME: .field("version", &self.version)
+ // FIXME: .field("machine", &self.machine)
+ .finish()
+ }
+ }
+
+ impl ::hash::Hash for utsname {
+ fn hash<H: ::hash::Hasher>(&self, state: &mut H) {
+ self.sysname.hash(state);
+ self.nodename.hash(state);
+ self.release.hash(state);
+ self.version.hash(state);
+ self.machine.hash(state);
+ }
+ }
+
+ impl PartialEq for mq_attr {
+ fn eq(&self, other: &mq_attr) -> bool {
+ self.mq_maxmsg == other.mq_maxmsg &&
+ self.mq_msgsize == other.mq_msgsize &&
+ self.mq_flags == other.mq_flags &&
+ self.mq_curmsgs == other.mq_curmsgs &&
+ self.mq_msgsize == other.mq_msgsize &&
+ self.mq_sendwait == other.mq_sendwait &&
+ self.mq_recvwait == other.mq_recvwait
+ }
+ }
+
+ impl Eq for mq_attr {}
+
+ impl ::fmt::Debug for mq_attr {
+ fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result {
+ f.debug_struct("mq_attr")
+ .field("mq_maxmsg", &self.mq_maxmsg)
+ .field("mq_msgsize", &self.mq_msgsize)
+ .field("mq_flags", &self.mq_flags)
+ .field("mq_curmsgs", &self.mq_curmsgs)
+ .field("mq_msgsize", &self.mq_msgsize)
+ .field("mq_sendwait", &self.mq_sendwait)
+ .field("mq_recvwait", &self.mq_recvwait)
+ .finish()
+ }
+ }
+
+ impl PartialEq for sockaddr_storage {
+ fn eq(&self, other: &sockaddr_storage) -> bool {
+ self.ss_len == other.ss_len
+ && self.ss_family == other.ss_family
+ && self.__ss_pad1 == other.__ss_pad1
+ && self.__ss_align == other.__ss_align
+ && self
+ .__ss_pad2
+ .iter()
+ .zip(other.__ss_pad2.iter())
+ .all(|(a, b)| a == b)
+ }
+ }
+
+ impl Eq for sockaddr_storage {}
+
+ impl ::fmt::Debug for sockaddr_storage {
+ fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result {
+ f.debug_struct("sockaddr_storage")
+ .field("ss_len", &self.ss_len)
+ .field("ss_family", &self.ss_family)
+ .field("__ss_pad1", &self.__ss_pad1)
+ .field("__ss_align", &self.__ss_align)
+ // FIXME: .field("__ss_pad2", &self.__ss_pad2)
+ .finish()
+ }
+ }
+
+ impl ::hash::Hash for sockaddr_storage {
+ fn hash<H: ::hash::Hasher>(&self, state: &mut H) {
+ self.ss_len.hash(state);
+ self.ss_family.hash(state);
+ self.__ss_pad1.hash(state);
+ self.__ss_align.hash(state);
+ self.__ss_pad2.hash(state);
+ }
+ }
+
+ impl PartialEq for dirent {
+ fn eq(&self, other: &dirent) -> bool {
+ self.d_ino == other.d_ino
+ && self.d_offset == other.d_offset
+ && self.d_reclen == other.d_reclen
+ && self.d_namelen == other.d_namelen
+ && self
+ .d_name[..self.d_namelen as _]
+ .iter()
+ .zip(other.d_name.iter())
+ .all(|(a,b)| a == b)
+ }
+ }
+
+ impl Eq for dirent {}
+
+ impl ::fmt::Debug for dirent {
+ fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result {
+ f.debug_struct("dirent")
+ .field("d_ino", &self.d_ino)
+ .field("d_offset", &self.d_offset)
+ .field("d_reclen", &self.d_reclen)
+ .field("d_namelen", &self.d_namelen)
+ .field("d_name", &&self.d_name[..self.d_namelen as _])
+ .finish()
+ }
+ }
+
+ impl ::hash::Hash for dirent {
+ fn hash<H: ::hash::Hasher>(&self, state: &mut H) {
+ self.d_ino.hash(state);
+ self.d_offset.hash(state);
+ self.d_reclen.hash(state);
+ self.d_namelen.hash(state);
+ self.d_name[..self.d_namelen as _].hash(state);
+ }
+ }
+ }
+}
+
+pub const _SYSNAME_SIZE: usize = 256 + 1;
+pub const RLIM_INFINITY: ::rlim_t = 0xfffffffffffffffd;
+pub const O_LARGEFILE: ::c_int = 0o0100000;
+
+// intentionally not public, only used for fd_set
+cfg_if! {
+ if #[cfg(target_pointer_width = "32")] {
+ const ULONG_SIZE: usize = 32;
+ } else if #[cfg(target_pointer_width = "64")] {
+ const ULONG_SIZE: usize = 64;
+ } else {
+ // Unknown target_pointer_width
+ }
+}
+
+pub const EXIT_FAILURE: ::c_int = 1;
+pub const EXIT_SUCCESS: ::c_int = 0;
+pub const RAND_MAX: ::c_int = 32767;
+pub const EOF: ::c_int = -1;
+pub const SEEK_SET: ::c_int = 0;
+pub const SEEK_CUR: ::c_int = 1;
+pub const SEEK_END: ::c_int = 2;
+pub const _IOFBF: ::c_int = 0;
+pub const _IONBF: ::c_int = 2;
+pub const _IOLBF: ::c_int = 1;
+
+pub const F_DUPFD: ::c_int = 0;
+pub const F_GETFD: ::c_int = 1;
+pub const F_SETFD: ::c_int = 2;
+pub const F_GETFL: ::c_int = 3;
+pub const F_SETFL: ::c_int = 4;
+
+pub const F_DUPFD_CLOEXEC: ::c_int = 5;
+
+pub const SIGTRAP: ::c_int = 5;
+
+pub const CLOCK_REALTIME: ::clockid_t = 0;
+pub const CLOCK_MONOTONIC: ::clockid_t = 2;
+pub const CLOCK_PROCESS_CPUTIME_ID: ::clockid_t = 3;
+pub const CLOCK_THREAD_CPUTIME_ID: ::clockid_t = 4;
+pub const TIMER_ABSTIME: ::c_uint = 0x80000000;
+
+pub const RUSAGE_SELF: ::c_int = 0;
+
+pub const F_OK: ::c_int = 0;
+pub const X_OK: ::c_int = 1;
+pub const W_OK: ::c_int = 2;
+pub const R_OK: ::c_int = 4;
+
+pub const STDIN_FILENO: ::c_int = 0;
+pub const STDOUT_FILENO: ::c_int = 1;
+pub const STDERR_FILENO: ::c_int = 2;
+
+pub const SIGHUP: ::c_int = 1;
+pub const SIGINT: ::c_int = 2;
+pub const SIGQUIT: ::c_int = 3;
+pub const SIGILL: ::c_int = 4;
+pub const SIGABRT: ::c_int = 6;
+pub const SIGFPE: ::c_int = 8;
+pub const SIGKILL: ::c_int = 9;
+pub const SIGSEGV: ::c_int = 11;
+pub const SIGPIPE: ::c_int = 13;
+pub const SIGALRM: ::c_int = 14;
+pub const SIGTERM: ::c_int = 15;
+
+pub const PROT_NONE: ::c_int = 0x00000000;
+pub const PROT_READ: ::c_int = 0x00000100;
+pub const PROT_WRITE: ::c_int = 0x00000200;
+pub const PROT_EXEC: ::c_int = 0x00000400;
+
+pub const MAP_FILE: ::c_int = 0;
+pub const MAP_SHARED: ::c_int = 1;
+pub const MAP_PRIVATE: ::c_int = 2;
+pub const MAP_FIXED: ::c_int = 0x10;
+
+pub const MAP_FAILED: *mut ::c_void = !0 as *mut ::c_void;
+
+pub const MS_ASYNC: ::c_int = 1;
+pub const MS_INVALIDATE: ::c_int = 4;
+pub const MS_SYNC: ::c_int = 2;
+
+pub const SCM_RIGHTS: ::c_int = 0x01;
+pub const SCM_TIMESTAMP: ::c_int = 0x02;
+pub const SCM_CREDS: ::c_int = 0x04;
+
+pub const MAP_TYPE: ::c_int = 0x3;
+
+pub const IFF_UP: ::c_int = 0x00000001;
+pub const IFF_BROADCAST: ::c_int = 0x00000002;
+pub const IFF_DEBUG: ::c_int = 0x00000004;
+pub const IFF_LOOPBACK: ::c_int = 0x00000008;
+pub const IFF_POINTOPOINT: ::c_int = 0x00000010;
+pub const IFF_NOTRAILERS: ::c_int = 0x00000020;
+pub const IFF_RUNNING: ::c_int = 0x00000040;
+pub const IFF_NOARP: ::c_int = 0x00000080;
+pub const IFF_PROMISC: ::c_int = 0x00000100;
+pub const IFF_ALLMULTI: ::c_int = 0x00000200;
+pub const IFF_MULTICAST: ::c_int = 0x00008000;
+
+pub const AF_UNSPEC: ::c_int = 0;
+pub const AF_UNIX: ::c_int = AF_LOCAL;
+pub const AF_LOCAL: ::c_int = 1;
+pub const AF_INET: ::c_int = 2;
+pub const AF_IPX: ::c_int = 23;
+pub const AF_APPLETALK: ::c_int = 16;
+pub const AF_INET6: ::c_int = 24;
+pub const AF_ROUTE: ::c_int = 17;
+pub const AF_SNA: ::c_int = 11;
+pub const AF_BLUETOOTH: ::c_int = 31;
+pub const AF_ISDN: ::c_int = 26;
+
+pub const PF_UNSPEC: ::c_int = AF_UNSPEC;
+pub const PF_UNIX: ::c_int = PF_LOCAL;
+pub const PF_LOCAL: ::c_int = AF_LOCAL;
+pub const PF_INET: ::c_int = AF_INET;
+pub const PF_IPX: ::c_int = AF_IPX;
+pub const PF_APPLETALK: ::c_int = AF_APPLETALK;
+pub const PF_INET6: ::c_int = AF_INET6;
+pub const pseudo_AF_KEY: ::c_int = 29;
+pub const PF_KEY: ::c_int = pseudo_AF_KEY;
+pub const PF_ROUTE: ::c_int = AF_ROUTE;
+pub const PF_SNA: ::c_int = AF_SNA;
+
+pub const PF_BLUETOOTH: ::c_int = AF_BLUETOOTH;
+pub const PF_ISDN: ::c_int = AF_ISDN;
+
+pub const SOMAXCONN: ::c_int = 128;
+
+pub const MSG_OOB: ::c_int = 0x0001;
+pub const MSG_PEEK: ::c_int = 0x0002;
+pub const MSG_DONTROUTE: ::c_int = 0x0004;
+pub const MSG_CTRUNC: ::c_int = 0x0020;
+pub const MSG_TRUNC: ::c_int = 0x0010;
+pub const MSG_DONTWAIT: ::c_int = 0x0080;
+pub const MSG_EOR: ::c_int = 0x0008;
+pub const MSG_WAITALL: ::c_int = 0x0040;
+pub const MSG_NOSIGNAL: ::c_int = 0x0800;
+pub const MSG_WAITFORONE: ::c_int = 0x2000;
+
+pub const IP_TOS: ::c_int = 3;
+pub const IP_TTL: ::c_int = 4;
+pub const IP_HDRINCL: ::c_int = 2;
+pub const IP_OPTIONS: ::c_int = 1;
+pub const IP_RECVOPTS: ::c_int = 5;
+pub const IP_RETOPTS: ::c_int = 8;
+pub const IP_PKTINFO: ::c_int = 25;
+pub const IP_IPSEC_POLICY_COMPAT: ::c_int = 22;
+pub const IP_MULTICAST_IF: ::c_int = 9;
+pub const IP_MULTICAST_TTL: ::c_int = 10;
+pub const IP_MULTICAST_LOOP: ::c_int = 11;
+pub const IP_ADD_MEMBERSHIP: ::c_int = 12;
+pub const IP_DROP_MEMBERSHIP: ::c_int = 13;
+pub const IP_DEFAULT_MULTICAST_TTL: ::c_int = 1;
+pub const IP_DEFAULT_MULTICAST_LOOP: ::c_int = 1;
+
+pub const IPPROTO_HOPOPTS: ::c_int = 0;
+pub const IPPROTO_IGMP: ::c_int = 2;
+pub const IPPROTO_IPIP: ::c_int = 4;
+pub const IPPROTO_EGP: ::c_int = 8;
+pub const IPPROTO_PUP: ::c_int = 12;
+pub const IPPROTO_IDP: ::c_int = 22;
+pub const IPPROTO_TP: ::c_int = 29;
+pub const IPPROTO_ROUTING: ::c_int = 43;
+pub const IPPROTO_FRAGMENT: ::c_int = 44;
+pub const IPPROTO_RSVP: ::c_int = 46;
+pub const IPPROTO_GRE: ::c_int = 47;
+pub const IPPROTO_ESP: ::c_int = 50;
+pub const IPPROTO_AH: ::c_int = 51;
+pub const IPPROTO_NONE: ::c_int = 59;
+pub const IPPROTO_DSTOPTS: ::c_int = 60;
+pub const IPPROTO_ENCAP: ::c_int = 98;
+pub const IPPROTO_PIM: ::c_int = 103;
+pub const IPPROTO_SCTP: ::c_int = 132;
+pub const IPPROTO_RAW: ::c_int = 255;
+pub const IPPROTO_MAX: ::c_int = 256;
+pub const IPPROTO_CARP: ::c_int = 112;
+pub const IPPROTO_DIVERT: ::c_int = 259;
+pub const IPPROTO_DONE: ::c_int = 257;
+pub const IPPROTO_EON: ::c_int = 80;
+pub const IPPROTO_ETHERIP: ::c_int = 97;
+pub const IPPROTO_GGP: ::c_int = 3;
+pub const IPPROTO_IPCOMP: ::c_int = 108;
+pub const IPPROTO_MOBILE: ::c_int = 55;
+
+pub const IPV6_RTHDR_LOOSE: ::c_int = 0;
+pub const IPV6_RTHDR_STRICT: ::c_int = 1;
+pub const IPV6_UNICAST_HOPS: ::c_int = 4;
+pub const IPV6_MULTICAST_IF: ::c_int = 9;
+pub const IPV6_MULTICAST_HOPS: ::c_int = 10;
+pub const IPV6_MULTICAST_LOOP: ::c_int = 11;
+pub const IPV6_JOIN_GROUP: ::c_int = 12;
+pub const IPV6_LEAVE_GROUP: ::c_int = 13;
+pub const IPV6_CHECKSUM: ::c_int = 26;
+pub const IPV6_V6ONLY: ::c_int = 27;
+pub const IPV6_IPSEC_POLICY_COMPAT: ::c_int = 28;
+pub const IPV6_RTHDRDSTOPTS: ::c_int = 35;
+pub const IPV6_RECVPKTINFO: ::c_int = 36;
+pub const IPV6_RECVHOPLIMIT: ::c_int = 37;
+pub const IPV6_RECVRTHDR: ::c_int = 38;
+pub const IPV6_RECVHOPOPTS: ::c_int = 39;
+pub const IPV6_RECVDSTOPTS: ::c_int = 40;
+pub const IPV6_RECVPATHMTU: ::c_int = 43;
+pub const IPV6_PATHMTU: ::c_int = 44;
+pub const IPV6_PKTINFO: ::c_int = 46;
+pub const IPV6_HOPLIMIT: ::c_int = 47;
+pub const IPV6_NEXTHOP: ::c_int = 48;
+pub const IPV6_HOPOPTS: ::c_int = 49;
+pub const IPV6_DSTOPTS: ::c_int = 50;
+pub const IPV6_RECVTCLASS: ::c_int = 57;
+pub const IPV6_TCLASS: ::c_int = 61;
+pub const IPV6_DONTFRAG: ::c_int = 62;
+
+pub const TCP_NODELAY: ::c_int = 0x01;
+pub const TCP_MAXSEG: ::c_int = 0x02;
+pub const TCP_MD5SIG: ::c_int = 0x10;
+pub const TCP_KEEPALIVE: ::c_int = 0x04;
+
+pub const SHUT_RD: ::c_int = 0;
+pub const SHUT_WR: ::c_int = 1;
+pub const SHUT_RDWR: ::c_int = 2;
+
+pub const LOCK_SH: ::c_int = 0x1;
+pub const LOCK_EX: ::c_int = 0x2;
+pub const LOCK_NB: ::c_int = 0x4;
+pub const LOCK_UN: ::c_int = 0x8;
+
+pub const SS_ONSTACK: ::c_int = 1;
+pub const SS_DISABLE: ::c_int = 2;
+
+pub const PATH_MAX: ::c_int = 1024;
+
+pub const UIO_MAXIOV: ::c_int = 1024;
+
+pub const FD_SETSIZE: usize = 256;
+
+pub const TCIOFF: ::c_int = 0x0002;
+pub const TCION: ::c_int = 0x0003;
+pub const TCOOFF: ::c_int = 0x0000;
+pub const TCOON: ::c_int = 0x0001;
+pub const TCIFLUSH: ::c_int = 0;
+pub const TCOFLUSH: ::c_int = 1;
+pub const TCIOFLUSH: ::c_int = 2;
+pub const NL0: ::tcflag_t = 0x000;
+pub const NL1: ::tcflag_t = 0x100;
+pub const TAB0: ::tcflag_t = 0x0000;
+pub const CR0: ::tcflag_t = 0x000;
+pub const FF0: ::tcflag_t = 0x0000;
+pub const BS0: ::tcflag_t = 0x0000;
+pub const VT0: ::tcflag_t = 0x0000;
+pub const VERASE: usize = 2;
+pub const VKILL: usize = 3;
+pub const VINTR: usize = 0;
+pub const VQUIT: usize = 1;
+pub const VLNEXT: usize = 15;
+pub const IGNBRK: ::tcflag_t = 0x00000001;
+pub const BRKINT: ::tcflag_t = 0x00000002;
+pub const IGNPAR: ::tcflag_t = 0x00000004;
+pub const PARMRK: ::tcflag_t = 0x00000008;
+pub const INPCK: ::tcflag_t = 0x00000010;
+pub const ISTRIP: ::tcflag_t = 0x00000020;
+pub const INLCR: ::tcflag_t = 0x00000040;
+pub const IGNCR: ::tcflag_t = 0x00000080;
+pub const ICRNL: ::tcflag_t = 0x00000100;
+pub const IXANY: ::tcflag_t = 0x00000800;
+pub const IMAXBEL: ::tcflag_t = 0x00002000;
+pub const OPOST: ::tcflag_t = 0x00000001;
+pub const CS5: ::tcflag_t = 0x00;
+pub const ECHO: ::tcflag_t = 0x00000008;
+pub const OCRNL: ::tcflag_t = 0x00000008;
+pub const ONOCR: ::tcflag_t = 0x00000010;
+pub const ONLRET: ::tcflag_t = 0x00000020;
+pub const OFILL: ::tcflag_t = 0x00000040;
+pub const OFDEL: ::tcflag_t = 0x00000080;
+
+pub const WNOHANG: ::c_int = 0x0040;
+pub const WUNTRACED: ::c_int = 0x0004;
+pub const WSTOPPED: ::c_int = WUNTRACED;
+pub const WEXITED: ::c_int = 0x0001;
+pub const WCONTINUED: ::c_int = 0x0008;
+pub const WNOWAIT: ::c_int = 0x0080;
+pub const WTRAPPED: ::c_int = 0x0002;
+
+pub const RTLD_LOCAL: ::c_int = 0x0200;
+pub const RTLD_LAZY: ::c_int = 0x0001;
+
+pub const POSIX_FADV_NORMAL: ::c_int = 0;
+pub const POSIX_FADV_RANDOM: ::c_int = 2;
+pub const POSIX_FADV_SEQUENTIAL: ::c_int = 1;
+pub const POSIX_FADV_WILLNEED: ::c_int = 3;
+
+pub const AT_FDCWD: ::c_int = -100;
+pub const AT_EACCESS: ::c_int = 0x0001;
+pub const AT_SYMLINK_NOFOLLOW: ::c_int = 0x0002;
+pub const AT_SYMLINK_FOLLOW: ::c_int = 0x0004;
+pub const AT_REMOVEDIR: ::c_int = 0x0008;
+
+pub const LOG_CRON: ::c_int = 9 << 3;
+pub const LOG_AUTHPRIV: ::c_int = 10 << 3;
+pub const LOG_FTP: ::c_int = 11 << 3;
+pub const LOG_PERROR: ::c_int = 0x20;
+
+pub const PIPE_BUF: usize = 5120;
+
+pub const CLD_EXITED: ::c_int = 1;
+pub const CLD_KILLED: ::c_int = 2;
+pub const CLD_DUMPED: ::c_int = 3;
+pub const CLD_TRAPPED: ::c_int = 4;
+pub const CLD_STOPPED: ::c_int = 5;
+pub const CLD_CONTINUED: ::c_int = 6;
+
+pub const UTIME_OMIT: c_long = 0x40000002;
+pub const UTIME_NOW: c_long = 0x40000001;
+
+pub const POLLIN: ::c_short = POLLRDNORM | POLLRDBAND;
+pub const POLLPRI: ::c_short = 0x0008;
+pub const POLLOUT: ::c_short = 0x0002;
+pub const POLLERR: ::c_short = 0x0020;
+pub const POLLHUP: ::c_short = 0x0040;
+pub const POLLNVAL: ::c_short = 0x1000;
+pub const POLLRDNORM: ::c_short = 0x0001;
+pub const POLLRDBAND: ::c_short = 0x0004;
+
+pub const IPTOS_LOWDELAY: u8 = 0x10;
+pub const IPTOS_THROUGHPUT: u8 = 0x08;
+pub const IPTOS_RELIABILITY: u8 = 0x04;
+pub const IPTOS_MINCOST: u8 = 0x02;
+
+pub const IPTOS_PREC_NETCONTROL: u8 = 0xe0;
+pub const IPTOS_PREC_INTERNETCONTROL: u8 = 0xc0;
+pub const IPTOS_PREC_CRITIC_ECP: u8 = 0xa0;
+pub const IPTOS_PREC_FLASHOVERRIDE: u8 = 0x80;
+pub const IPTOS_PREC_FLASH: u8 = 0x60;
+pub const IPTOS_PREC_IMMEDIATE: u8 = 0x40;
+pub const IPTOS_PREC_PRIORITY: u8 = 0x20;
+pub const IPTOS_PREC_ROUTINE: u8 = 0x00;
+
+pub const IPTOS_ECN_MASK: u8 = 0x03;
+pub const IPTOS_ECN_ECT1: u8 = 0x01;
+pub const IPTOS_ECN_ECT0: u8 = 0x02;
+pub const IPTOS_ECN_CE: u8 = 0x03;
+
+pub const IPOPT_CONTROL: u8 = 0x00;
+pub const IPOPT_RESERVED1: u8 = 0x20;
+pub const IPOPT_RESERVED2: u8 = 0x60;
+pub const IPOPT_LSRR: u8 = 131;
+pub const IPOPT_RR: u8 = 7;
+pub const IPOPT_SSRR: u8 = 137;
+pub const IPDEFTTL: u8 = 64;
+pub const IPOPT_OPTVAL: u8 = 0;
+pub const IPOPT_OLEN: u8 = 1;
+pub const IPOPT_OFFSET: u8 = 2;
+pub const IPOPT_MINOFF: u8 = 4;
+pub const IPOPT_NOP: u8 = 1;
+pub const IPOPT_EOL: u8 = 0;
+pub const IPOPT_TS: u8 = 68;
+pub const IPOPT_TS_TSONLY: u8 = 0;
+pub const IPOPT_TS_TSANDADDR: u8 = 1;
+pub const IPOPT_TS_PRESPEC: u8 = 3;
+
+pub const MAX_IPOPTLEN: u8 = 40;
+pub const IPVERSION: u8 = 4;
+pub const MAXTTL: u8 = 255;
+
+pub const ARPHRD_ETHER: u16 = 1;
+pub const ARPHRD_IEEE802: u16 = 6;
+pub const ARPHRD_ARCNET: u16 = 7;
+pub const ARPHRD_IEEE1394: u16 = 24;
+
+pub const SOL_SOCKET: ::c_int = 0xffff;
+
+pub const SO_DEBUG: ::c_int = 0x0001;
+pub const SO_REUSEADDR: ::c_int = 0x0004;
+pub const SO_TYPE: ::c_int = 0x1008;
+pub const SO_ERROR: ::c_int = 0x1007;
+pub const SO_DONTROUTE: ::c_int = 0x0010;
+pub const SO_BROADCAST: ::c_int = 0x0020;
+pub const SO_SNDBUF: ::c_int = 0x1001;
+pub const SO_RCVBUF: ::c_int = 0x1002;
+pub const SO_KEEPALIVE: ::c_int = 0x0008;
+pub const SO_OOBINLINE: ::c_int = 0x0100;
+pub const SO_LINGER: ::c_int = 0x0080;
+pub const SO_REUSEPORT: ::c_int = 0x0200;
+pub const SO_RCVLOWAT: ::c_int = 0x1004;
+pub const SO_SNDLOWAT: ::c_int = 0x1003;
+pub const SO_RCVTIMEO: ::c_int = 0x1006;
+pub const SO_SNDTIMEO: ::c_int = 0x1005;
+pub const SO_BINDTODEVICE: ::c_int = 0x0800;
+pub const SO_TIMESTAMP: ::c_int = 0x0400;
+pub const SO_ACCEPTCONN: ::c_int = 0x0002;
+
+pub const TIOCM_LE: ::c_int = 0x0100;
+pub const TIOCM_DTR: ::c_int = 0x0001;
+pub const TIOCM_RTS: ::c_int = 0x0002;
+pub const TIOCM_ST: ::c_int = 0x0200;
+pub const TIOCM_SR: ::c_int = 0x0400;
+pub const TIOCM_CTS: ::c_int = 0x1000;
+pub const TIOCM_CAR: ::c_int = TIOCM_CD;
+pub const TIOCM_CD: ::c_int = 0x8000;
+pub const TIOCM_RNG: ::c_int = TIOCM_RI;
+pub const TIOCM_RI: ::c_int = 0x4000;
+pub const TIOCM_DSR: ::c_int = 0x2000;
+
+pub const SCHED_OTHER: ::c_int = 3;
+pub const SCHED_FIFO: ::c_int = 1;
+pub const SCHED_RR: ::c_int = 2;
+
+pub const IPC_PRIVATE: ::key_t = 0;
+
+pub const IPC_CREAT: ::c_int = 0o001000;
+pub const IPC_EXCL: ::c_int = 0o002000;
+pub const IPC_NOWAIT: ::c_int = 0o004000;
+
+pub const IPC_RMID: ::c_int = 0;
+pub const IPC_SET: ::c_int = 1;
+pub const IPC_STAT: ::c_int = 2;
+
+pub const MSG_NOERROR: ::c_int = 0o010000;
+
+pub const LOG_NFACILITIES: ::c_int = 24;
+
+pub const SEM_FAILED: *mut ::sem_t = 0xFFFFFFFFFFFFFFFF as *mut sem_t;
+
+pub const AI_PASSIVE: ::c_int = 0x00000001;
+pub const AI_CANONNAME: ::c_int = 0x00000002;
+pub const AI_NUMERICHOST: ::c_int = 0x00000004;
+
+pub const AI_NUMERICSERV: ::c_int = 0x00000008;
+
+pub const EAI_BADFLAGS: ::c_int = 3;
+pub const EAI_NONAME: ::c_int = 8;
+pub const EAI_AGAIN: ::c_int = 2;
+pub const EAI_FAIL: ::c_int = 4;
+pub const EAI_NODATA: ::c_int = 7;
+pub const EAI_FAMILY: ::c_int = 5;
+pub const EAI_SOCKTYPE: ::c_int = 10;
+pub const EAI_SERVICE: ::c_int = 9;
+pub const EAI_MEMORY: ::c_int = 6;
+pub const EAI_SYSTEM: ::c_int = 11;
+pub const EAI_OVERFLOW: ::c_int = 14;
+
+pub const NI_NUMERICHOST: ::c_int = 0x00000002;
+pub const NI_NUMERICSERV: ::c_int = 0x00000008;
+pub const NI_NOFQDN: ::c_int = 0x00000001;
+pub const NI_NAMEREQD: ::c_int = 0x00000004;
+pub const NI_DGRAM: ::c_int = 0x00000010;
+
+pub const AIO_CANCELED: ::c_int = 0;
+pub const AIO_NOTCANCELED: ::c_int = 2;
+pub const AIO_ALLDONE: ::c_int = 1;
+pub const LIO_READ: ::c_int = 1;
+pub const LIO_WRITE: ::c_int = 2;
+pub const LIO_NOP: ::c_int = 0;
+pub const LIO_WAIT: ::c_int = 1;
+pub const LIO_NOWAIT: ::c_int = 0;
+
+pub const ITIMER_REAL: ::c_int = 0;
+pub const ITIMER_VIRTUAL: ::c_int = 1;
+pub const ITIMER_PROF: ::c_int = 2;
+
+pub const POSIX_SPAWN_RESETIDS: ::c_int = 0x00000010;
+pub const POSIX_SPAWN_SETPGROUP: ::c_int = 0x00000001;
+pub const POSIX_SPAWN_SETSIGDEF: ::c_int = 0x00000004;
+pub const POSIX_SPAWN_SETSIGMASK: ::c_int = 0x00000002;
+pub const POSIX_SPAWN_SETSCHEDPARAM: ::c_int = 0x00000400;
+pub const POSIX_SPAWN_SETSCHEDULER: ::c_int = 0x00000040;
+
+pub const IPTOS_ECN_NOT_ECT: u8 = 0x00;
+
+pub const RTF_UP: ::c_ushort = 0x0001;
+pub const RTF_GATEWAY: ::c_ushort = 0x0002;
+
+pub const RTF_HOST: ::c_ushort = 0x0004;
+pub const RTF_DYNAMIC: ::c_ushort = 0x0010;
+pub const RTF_MODIFIED: ::c_ushort = 0x0020;
+pub const RTF_REJECT: ::c_ushort = 0x0008;
+pub const RTF_STATIC: ::c_ushort = 0x0800;
+pub const RTF_XRESOLVE: ::c_ushort = 0x0200;
+pub const RTF_BROADCAST: u32 = 0x80000;
+pub const RTM_NEWADDR: u16 = 0xc;
+pub const RTM_DELADDR: u16 = 0xd;
+pub const RTA_DST: ::c_ushort = 0x1;
+pub const RTA_GATEWAY: ::c_ushort = 0x2;
+
+pub const UDP_ENCAP: ::c_int = 100;
+
+pub const IN_ACCESS: u32 = 0x00000001;
+pub const IN_MODIFY: u32 = 0x00000002;
+pub const IN_ATTRIB: u32 = 0x00000004;
+pub const IN_CLOSE_WRITE: u32 = 0x00000008;
+pub const IN_CLOSE_NOWRITE: u32 = 0x00000010;
+pub const IN_CLOSE: u32 = IN_CLOSE_WRITE | IN_CLOSE_NOWRITE;
+pub const IN_OPEN: u32 = 0x00000020;
+pub const IN_MOVED_FROM: u32 = 0x00000040;
+pub const IN_MOVED_TO: u32 = 0x00000080;
+pub const IN_MOVE: u32 = IN_MOVED_FROM | IN_MOVED_TO;
+pub const IN_CREATE: u32 = 0x00000100;
+pub const IN_DELETE: u32 = 0x00000200;
+pub const IN_DELETE_SELF: u32 = 0x00000400;
+pub const IN_MOVE_SELF: u32 = 0x00000800;
+pub const IN_UNMOUNT: u32 = 0x00002000;
+pub const IN_Q_OVERFLOW: u32 = 0x00004000;
+pub const IN_IGNORED: u32 = 0x00008000;
+pub const IN_ONLYDIR: u32 = 0x01000000;
+pub const IN_DONT_FOLLOW: u32 = 0x02000000;
+
+pub const IN_ISDIR: u32 = 0x40000000;
+pub const IN_ONESHOT: u32 = 0x80000000;
+
+pub const REG_EXTENDED: ::c_int = 0o0001;
+pub const REG_ICASE: ::c_int = 0o0002;
+pub const REG_NEWLINE: ::c_int = 0o0010;
+pub const REG_NOSUB: ::c_int = 0o0004;
+
+pub const REG_NOTBOL: ::c_int = 0o00001;
+pub const REG_NOTEOL: ::c_int = 0o00002;
+
+pub const REG_ENOSYS: ::c_int = 17;
+pub const REG_NOMATCH: ::c_int = 1;
+pub const REG_BADPAT: ::c_int = 2;
+pub const REG_ECOLLATE: ::c_int = 3;
+pub const REG_ECTYPE: ::c_int = 4;
+pub const REG_EESCAPE: ::c_int = 5;
+pub const REG_ESUBREG: ::c_int = 6;
+pub const REG_EBRACK: ::c_int = 7;
+pub const REG_EPAREN: ::c_int = 8;
+pub const REG_EBRACE: ::c_int = 9;
+pub const REG_BADBR: ::c_int = 10;
+pub const REG_ERANGE: ::c_int = 11;
+pub const REG_ESPACE: ::c_int = 12;
+pub const REG_BADRPT: ::c_int = 13;
+
+// errno.h
+pub const EOK: ::c_int = 0;
+pub const EWOULDBLOCK: ::c_int = EAGAIN;
+pub const EPERM: ::c_int = 1;
+pub const ENOENT: ::c_int = 2;
+pub const ESRCH: ::c_int = 3;
+pub const EINTR: ::c_int = 4;
+pub const EIO: ::c_int = 5;
+pub const ENXIO: ::c_int = 6;
+pub const E2BIG: ::c_int = 7;
+pub const ENOEXEC: ::c_int = 8;
+pub const EBADF: ::c_int = 9;
+pub const ECHILD: ::c_int = 10;
+pub const EAGAIN: ::c_int = 11;
+pub const ENOMEM: ::c_int = 12;
+pub const EACCES: ::c_int = 13;
+pub const EFAULT: ::c_int = 14;
+pub const ENOTBLK: ::c_int = 15;
+pub const EBUSY: ::c_int = 16;
+pub const EEXIST: ::c_int = 17;
+pub const EXDEV: ::c_int = 18;
+pub const ENODEV: ::c_int = 19;
+pub const ENOTDIR: ::c_int = 20;
+pub const EISDIR: ::c_int = 21;
+pub const EINVAL: ::c_int = 22;
+pub const ENFILE: ::c_int = 23;
+pub const EMFILE: ::c_int = 24;
+pub const ENOTTY: ::c_int = 25;
+pub const ETXTBSY: ::c_int = 26;
+pub const EFBIG: ::c_int = 27;
+pub const ENOSPC: ::c_int = 28;
+pub const ESPIPE: ::c_int = 29;
+pub const EROFS: ::c_int = 30;
+pub const EMLINK: ::c_int = 31;
+pub const EPIPE: ::c_int = 32;
+pub const EDOM: ::c_int = 33;
+pub const ERANGE: ::c_int = 34;
+pub const ENOMSG: ::c_int = 35;
+pub const EIDRM: ::c_int = 36;
+pub const ECHRNG: ::c_int = 37;
+pub const EL2NSYNC: ::c_int = 38;
+pub const EL3HLT: ::c_int = 39;
+pub const EL3RST: ::c_int = 40;
+pub const ELNRNG: ::c_int = 41;
+pub const EUNATCH: ::c_int = 42;
+pub const ENOCSI: ::c_int = 43;
+pub const EL2HLT: ::c_int = 44;
+pub const EDEADLK: ::c_int = 45;
+pub const ENOLCK: ::c_int = 46;
+pub const ECANCELED: ::c_int = 47;
+pub const EDQUOT: ::c_int = 49;
+pub const EBADE: ::c_int = 50;
+pub const EBADR: ::c_int = 51;
+pub const EXFULL: ::c_int = 52;
+pub const ENOANO: ::c_int = 53;
+pub const EBADRQC: ::c_int = 54;
+pub const EBADSLT: ::c_int = 55;
+pub const EDEADLOCK: ::c_int = 56;
+pub const EBFONT: ::c_int = 57;
+pub const EOWNERDEAD: ::c_int = 58;
+pub const ENOSTR: ::c_int = 60;
+pub const ENODATA: ::c_int = 61;
+pub const ETIME: ::c_int = 62;
+pub const ENOSR: ::c_int = 63;
+pub const ENONET: ::c_int = 64;
+pub const ENOPKG: ::c_int = 65;
+pub const EREMOTE: ::c_int = 66;
+pub const ENOLINK: ::c_int = 67;
+pub const EADV: ::c_int = 68;
+pub const ESRMNT: ::c_int = 69;
+pub const ECOMM: ::c_int = 70;
+pub const EPROTO: ::c_int = 71;
+pub const EMULTIHOP: ::c_int = 74;
+pub const EBADMSG: ::c_int = 77;
+pub const ENAMETOOLONG: ::c_int = 78;
+pub const EOVERFLOW: ::c_int = 79;
+pub const ENOTUNIQ: ::c_int = 80;
+pub const EBADFD: ::c_int = 81;
+pub const EREMCHG: ::c_int = 82;
+pub const ELIBACC: ::c_int = 83;
+pub const ELIBBAD: ::c_int = 84;
+pub const ELIBSCN: ::c_int = 85;
+pub const ELIBMAX: ::c_int = 86;
+pub const ELIBEXEC: ::c_int = 87;
+pub const EILSEQ: ::c_int = 88;
+pub const ENOSYS: ::c_int = 89;
+pub const ELOOP: ::c_int = 90;
+pub const ERESTART: ::c_int = 91;
+pub const ESTRPIPE: ::c_int = 92;
+pub const ENOTEMPTY: ::c_int = 93;
+pub const EUSERS: ::c_int = 94;
+pub const ENOTRECOVERABLE: ::c_int = 95;
+pub const EOPNOTSUPP: ::c_int = 103;
+pub const EFPOS: ::c_int = 110;
+pub const ESTALE: ::c_int = 122;
+pub const EINPROGRESS: ::c_int = 236;
+pub const EALREADY: ::c_int = 237;
+pub const ENOTSOCK: ::c_int = 238;
+pub const EDESTADDRREQ: ::c_int = 239;
+pub const EMSGSIZE: ::c_int = 240;
+pub const EPROTOTYPE: ::c_int = 241;
+pub const ENOPROTOOPT: ::c_int = 242;
+pub const EPROTONOSUPPORT: ::c_int = 243;
+pub const ESOCKTNOSUPPORT: ::c_int = 244;
+pub const EPFNOSUPPORT: ::c_int = 246;
+pub const EAFNOSUPPORT: ::c_int = 247;
+pub const EADDRINUSE: ::c_int = 248;
+pub const EADDRNOTAVAIL: ::c_int = 249;
+pub const ENETDOWN: ::c_int = 250;
+pub const ENETUNREACH: ::c_int = 251;
+pub const ENETRESET: ::c_int = 252;
+pub const ECONNABORTED: ::c_int = 253;
+pub const ECONNRESET: ::c_int = 254;
+pub const ENOBUFS: ::c_int = 255;
+pub const EISCONN: ::c_int = 256;
+pub const ENOTCONN: ::c_int = 257;
+pub const ESHUTDOWN: ::c_int = 258;
+pub const ETOOMANYREFS: ::c_int = 259;
+pub const ETIMEDOUT: ::c_int = 260;
+pub const ECONNREFUSED: ::c_int = 261;
+pub const EHOSTDOWN: ::c_int = 264;
+pub const EHOSTUNREACH: ::c_int = 265;
+pub const EBADRPC: ::c_int = 272;
+pub const ERPCMISMATCH: ::c_int = 273;
+pub const EPROGUNAVAIL: ::c_int = 274;
+pub const EPROGMISMATCH: ::c_int = 275;
+pub const EPROCUNAVAIL: ::c_int = 276;
+pub const ENOREMOTE: ::c_int = 300;
+pub const ENONDP: ::c_int = 301;
+pub const EBADFSYS: ::c_int = 302;
+pub const EMORE: ::c_int = 309;
+pub const ECTRLTERM: ::c_int = 310;
+pub const ENOLIC: ::c_int = 311;
+pub const ESRVRFAULT: ::c_int = 312;
+pub const EENDIAN: ::c_int = 313;
+pub const ESECTYPEINVAL: ::c_int = 314;
+
+pub const RUSAGE_CHILDREN: ::c_int = -1;
+pub const L_tmpnam: ::c_uint = 255;
+
+pub const _PC_LINK_MAX: ::c_int = 1;
+pub const _PC_MAX_CANON: ::c_int = 2;
+pub const _PC_MAX_INPUT: ::c_int = 3;
+pub const _PC_NAME_MAX: ::c_int = 4;
+pub const _PC_PATH_MAX: ::c_int = 5;
+pub const _PC_PIPE_BUF: ::c_int = 6;
+pub const _PC_CHOWN_RESTRICTED: ::c_int = 9;
+pub const _PC_NO_TRUNC: ::c_int = 7;
+pub const _PC_VDISABLE: ::c_int = 8;
+pub const _PC_SYNC_IO: ::c_int = 14;
+pub const _PC_ASYNC_IO: ::c_int = 12;
+pub const _PC_PRIO_IO: ::c_int = 13;
+pub const _PC_SOCK_MAXBUF: ::c_int = 15;
+pub const _PC_FILESIZEBITS: ::c_int = 16;
+pub const _PC_REC_INCR_XFER_SIZE: ::c_int = 22;
+pub const _PC_REC_MAX_XFER_SIZE: ::c_int = 23;
+pub const _PC_REC_MIN_XFER_SIZE: ::c_int = 24;
+pub const _PC_REC_XFER_ALIGN: ::c_int = 25;
+pub const _PC_ALLOC_SIZE_MIN: ::c_int = 21;
+pub const _PC_SYMLINK_MAX: ::c_int = 17;
+pub const _PC_2_SYMLINKS: ::c_int = 20;
+
+pub const _SC_PAGE_SIZE: ::c_int = _SC_PAGESIZE;
+pub const _SC_ARG_MAX: ::c_int = 1;
+pub const _SC_CHILD_MAX: ::c_int = 2;
+pub const _SC_CLK_TCK: ::c_int = 3;
+pub const _SC_NGROUPS_MAX: ::c_int = 4;
+pub const _SC_OPEN_MAX: ::c_int = 5;
+pub const _SC_JOB_CONTROL: ::c_int = 6;
+pub const _SC_SAVED_IDS: ::c_int = 7;
+pub const _SC_VERSION: ::c_int = 8;
+pub const _SC_PASS_MAX: ::c_int = 9;
+pub const _SC_PAGESIZE: ::c_int = 11;
+pub const _SC_XOPEN_VERSION: ::c_int = 12;
+pub const _SC_STREAM_MAX: ::c_int = 13;
+pub const _SC_TZNAME_MAX: ::c_int = 14;
+pub const _SC_AIO_LISTIO_MAX: ::c_int = 15;
+pub const _SC_AIO_MAX: ::c_int = 16;
+pub const _SC_AIO_PRIO_DELTA_MAX: ::c_int = 17;
+pub const _SC_DELAYTIMER_MAX: ::c_int = 18;
+pub const _SC_MQ_OPEN_MAX: ::c_int = 19;
+pub const _SC_MQ_PRIO_MAX: ::c_int = 20;
+pub const _SC_RTSIG_MAX: ::c_int = 21;
+pub const _SC_SEM_NSEMS_MAX: ::c_int = 22;
+pub const _SC_SEM_VALUE_MAX: ::c_int = 23;
+pub const _SC_SIGQUEUE_MAX: ::c_int = 24;
+pub const _SC_TIMER_MAX: ::c_int = 25;
+pub const _SC_ASYNCHRONOUS_IO: ::c_int = 26;
+pub const _SC_FSYNC: ::c_int = 27;
+pub const _SC_MAPPED_FILES: ::c_int = 28;
+pub const _SC_MEMLOCK: ::c_int = 29;
+pub const _SC_MEMLOCK_RANGE: ::c_int = 30;
+pub const _SC_MEMORY_PROTECTION: ::c_int = 31;
+pub const _SC_MESSAGE_PASSING: ::c_int = 32;
+pub const _SC_PRIORITIZED_IO: ::c_int = 33;
+pub const _SC_PRIORITY_SCHEDULING: ::c_int = 34;
+pub const _SC_REALTIME_SIGNALS: ::c_int = 35;
+pub const _SC_SEMAPHORES: ::c_int = 36;
+pub const _SC_SHARED_MEMORY_OBJECTS: ::c_int = 37;
+pub const _SC_SYNCHRONIZED_IO: ::c_int = 38;
+pub const _SC_TIMERS: ::c_int = 39;
+pub const _SC_GETGR_R_SIZE_MAX: ::c_int = 40;
+pub const _SC_GETPW_R_SIZE_MAX: ::c_int = 41;
+pub const _SC_LOGIN_NAME_MAX: ::c_int = 42;
+pub const _SC_THREAD_DESTRUCTOR_ITERATIONS: ::c_int = 43;
+pub const _SC_THREAD_KEYS_MAX: ::c_int = 44;
+pub const _SC_THREAD_STACK_MIN: ::c_int = 45;
+pub const _SC_THREAD_THREADS_MAX: ::c_int = 46;
+pub const _SC_TTY_NAME_MAX: ::c_int = 47;
+pub const _SC_THREADS: ::c_int = 48;
+pub const _SC_THREAD_ATTR_STACKADDR: ::c_int = 49;
+pub const _SC_THREAD_ATTR_STACKSIZE: ::c_int = 50;
+pub const _SC_THREAD_PRIORITY_SCHEDULING: ::c_int = 51;
+pub const _SC_THREAD_PRIO_INHERIT: ::c_int = 52;
+pub const _SC_THREAD_PRIO_PROTECT: ::c_int = 53;
+pub const _SC_THREAD_PROCESS_SHARED: ::c_int = 54;
+pub const _SC_THREAD_SAFE_FUNCTIONS: ::c_int = 55;
+pub const _SC_2_CHAR_TERM: ::c_int = 56;
+pub const _SC_2_C_BIND: ::c_int = 57;
+pub const _SC_2_C_DEV: ::c_int = 58;
+pub const _SC_2_C_VERSION: ::c_int = 59;
+pub const _SC_2_FORT_DEV: ::c_int = 60;
+pub const _SC_2_FORT_RUN: ::c_int = 61;
+pub const _SC_2_LOCALEDEF: ::c_int = 62;
+pub const _SC_2_SW_DEV: ::c_int = 63;
+pub const _SC_2_UPE: ::c_int = 64;
+pub const _SC_2_VERSION: ::c_int = 65;
+pub const _SC_ATEXIT_MAX: ::c_int = 66;
+pub const _SC_AVPHYS_PAGES: ::c_int = 67;
+pub const _SC_BC_BASE_MAX: ::c_int = 68;
+pub const _SC_BC_DIM_MAX: ::c_int = 69;
+pub const _SC_BC_SCALE_MAX: ::c_int = 70;
+pub const _SC_BC_STRING_MAX: ::c_int = 71;
+pub const _SC_CHARCLASS_NAME_MAX: ::c_int = 72;
+pub const _SC_CHAR_BIT: ::c_int = 73;
+pub const _SC_CHAR_MAX: ::c_int = 74;
+pub const _SC_CHAR_MIN: ::c_int = 75;
+pub const _SC_COLL_WEIGHTS_MAX: ::c_int = 76;
+pub const _SC_EQUIV_CLASS_MAX: ::c_int = 77;
+pub const _SC_EXPR_NEST_MAX: ::c_int = 78;
+pub const _SC_INT_MAX: ::c_int = 79;
+pub const _SC_INT_MIN: ::c_int = 80;
+pub const _SC_LINE_MAX: ::c_int = 81;
+pub const _SC_LONG_BIT: ::c_int = 82;
+pub const _SC_MB_LEN_MAX: ::c_int = 83;
+pub const _SC_NL_ARGMAX: ::c_int = 84;
+pub const _SC_NL_LANGMAX: ::c_int = 85;
+pub const _SC_NL_MSGMAX: ::c_int = 86;
+pub const _SC_NL_NMAX: ::c_int = 87;
+pub const _SC_NL_SETMAX: ::c_int = 88;
+pub const _SC_NL_TEXTMAX: ::c_int = 89;
+pub const _SC_NPROCESSORS_CONF: ::c_int = 90;
+pub const _SC_NPROCESSORS_ONLN: ::c_int = 91;
+pub const _SC_NZERO: ::c_int = 92;
+pub const _SC_PHYS_PAGES: ::c_int = 93;
+pub const _SC_PII: ::c_int = 94;
+pub const _SC_PII_INTERNET: ::c_int = 95;
+pub const _SC_PII_INTERNET_DGRAM: ::c_int = 96;
+pub const _SC_PII_INTERNET_STREAM: ::c_int = 97;
+pub const _SC_PII_OSI: ::c_int = 98;
+pub const _SC_PII_OSI_CLTS: ::c_int = 99;
+pub const _SC_PII_OSI_COTS: ::c_int = 100;
+pub const _SC_PII_OSI_M: ::c_int = 101;
+pub const _SC_PII_SOCKET: ::c_int = 102;
+pub const _SC_PII_XTI: ::c_int = 103;
+pub const _SC_POLL: ::c_int = 104;
+pub const _SC_RE_DUP_MAX: ::c_int = 105;
+pub const _SC_SCHAR_MAX: ::c_int = 106;
+pub const _SC_SCHAR_MIN: ::c_int = 107;
+pub const _SC_SELECT: ::c_int = 108;
+pub const _SC_SHRT_MAX: ::c_int = 109;
+pub const _SC_SHRT_MIN: ::c_int = 110;
+pub const _SC_SSIZE_MAX: ::c_int = 111;
+pub const _SC_T_IOV_MAX: ::c_int = 112;
+pub const _SC_UCHAR_MAX: ::c_int = 113;
+pub const _SC_UINT_MAX: ::c_int = 114;
+pub const _SC_UIO_MAXIOV: ::c_int = 115;
+pub const _SC_ULONG_MAX: ::c_int = 116;
+pub const _SC_USHRT_MAX: ::c_int = 117;
+pub const _SC_WORD_BIT: ::c_int = 118;
+pub const _SC_XOPEN_CRYPT: ::c_int = 119;
+pub const _SC_XOPEN_ENH_I18N: ::c_int = 120;
+pub const _SC_XOPEN_SHM: ::c_int = 121;
+pub const _SC_XOPEN_UNIX: ::c_int = 122;
+pub const _SC_XOPEN_XCU_VERSION: ::c_int = 123;
+pub const _SC_XOPEN_XPG2: ::c_int = 124;
+pub const _SC_XOPEN_XPG3: ::c_int = 125;
+pub const _SC_XOPEN_XPG4: ::c_int = 126;
+pub const _SC_XBS5_ILP32_OFF32: ::c_int = 127;
+pub const _SC_XBS5_ILP32_OFFBIG: ::c_int = 128;
+pub const _SC_XBS5_LP64_OFF64: ::c_int = 129;
+pub const _SC_XBS5_LPBIG_OFFBIG: ::c_int = 130;
+pub const _SC_ADVISORY_INFO: ::c_int = 131;
+pub const _SC_CPUTIME: ::c_int = 132;
+pub const _SC_SPAWN: ::c_int = 133;
+pub const _SC_SPORADIC_SERVER: ::c_int = 134;
+pub const _SC_THREAD_CPUTIME: ::c_int = 135;
+pub const _SC_THREAD_SPORADIC_SERVER: ::c_int = 136;
+pub const _SC_TIMEOUTS: ::c_int = 137;
+pub const _SC_BARRIERS: ::c_int = 138;
+pub const _SC_CLOCK_SELECTION: ::c_int = 139;
+pub const _SC_MONOTONIC_CLOCK: ::c_int = 140;
+pub const _SC_READER_WRITER_LOCKS: ::c_int = 141;
+pub const _SC_SPIN_LOCKS: ::c_int = 142;
+pub const _SC_TYPED_MEMORY_OBJECTS: ::c_int = 143;
+pub const _SC_TRACE_EVENT_FILTER: ::c_int = 144;
+pub const _SC_TRACE: ::c_int = 145;
+pub const _SC_TRACE_INHERIT: ::c_int = 146;
+pub const _SC_TRACE_LOG: ::c_int = 147;
+pub const _SC_2_PBS: ::c_int = 148;
+pub const _SC_2_PBS_ACCOUNTING: ::c_int = 149;
+pub const _SC_2_PBS_CHECKPOINT: ::c_int = 150;
+pub const _SC_2_PBS_LOCATE: ::c_int = 151;
+pub const _SC_2_PBS_MESSAGE: ::c_int = 152;
+pub const _SC_2_PBS_TRACK: ::c_int = 153;
+pub const _SC_HOST_NAME_MAX: ::c_int = 154;
+pub const _SC_IOV_MAX: ::c_int = 155;
+pub const _SC_IPV6: ::c_int = 156;
+pub const _SC_RAW_SOCKETS: ::c_int = 157;
+pub const _SC_REGEXP: ::c_int = 158;
+pub const _SC_SHELL: ::c_int = 159;
+pub const _SC_SS_REPL_MAX: ::c_int = 160;
+pub const _SC_SYMLOOP_MAX: ::c_int = 161;
+pub const _SC_TRACE_EVENT_NAME_MAX: ::c_int = 162;
+pub const _SC_TRACE_NAME_MAX: ::c_int = 163;
+pub const _SC_TRACE_SYS_MAX: ::c_int = 164;
+pub const _SC_TRACE_USER_EVENT_MAX: ::c_int = 165;
+pub const _SC_V6_ILP32_OFF32: ::c_int = 166;
+pub const _SC_V6_ILP32_OFFBIG: ::c_int = 167;
+pub const _SC_V6_LP64_OFF64: ::c_int = 168;
+pub const _SC_V6_LPBIG_OFFBIG: ::c_int = 169;
+pub const _SC_XOPEN_REALTIME: ::c_int = 170;
+pub const _SC_XOPEN_REALTIME_THREADS: ::c_int = 171;
+pub const _SC_XOPEN_LEGACY: ::c_int = 172;
+pub const _SC_XOPEN_STREAMS: ::c_int = 173;
+pub const _SC_V7_ILP32_OFF32: ::c_int = 176;
+pub const _SC_V7_ILP32_OFFBIG: ::c_int = 177;
+pub const _SC_V7_LP64_OFF64: ::c_int = 178;
+pub const _SC_V7_LPBIG_OFFBIG: ::c_int = 179;
+
+pub const GLOB_ERR: ::c_int = 0x0001;
+pub const GLOB_MARK: ::c_int = 0x0002;
+pub const GLOB_NOSORT: ::c_int = 0x0004;
+pub const GLOB_DOOFFS: ::c_int = 0x0008;
+pub const GLOB_NOCHECK: ::c_int = 0x0010;
+pub const GLOB_APPEND: ::c_int = 0x0020;
+pub const GLOB_NOESCAPE: ::c_int = 0x0040;
+
+pub const GLOB_NOSPACE: ::c_int = 1;
+pub const GLOB_ABORTED: ::c_int = 2;
+pub const GLOB_NOMATCH: ::c_int = 3;
+
+pub const S_IEXEC: mode_t = ::S_IXUSR;
+pub const S_IWRITE: mode_t = ::S_IWUSR;
+pub const S_IREAD: mode_t = ::S_IRUSR;
+
+pub const S_IFIFO: ::mode_t = 0x1000;
+pub const S_IFCHR: ::mode_t = 0x2000;
+pub const S_IFDIR: ::mode_t = 0x4000;
+pub const S_IFBLK: ::mode_t = 0x6000;
+pub const S_IFREG: ::mode_t = 0x8000;
+pub const S_IFLNK: ::mode_t = 0xA000;
+pub const S_IFSOCK: ::mode_t = 0xC000;
+pub const S_IFMT: ::mode_t = 0xF000;
+
+pub const S_IXOTH: ::mode_t = 0o000001;
+pub const S_IWOTH: ::mode_t = 0o000002;
+pub const S_IROTH: ::mode_t = 0o000004;
+pub const S_IRWXO: ::mode_t = 0o000007;
+pub const S_IXGRP: ::mode_t = 0o000010;
+pub const S_IWGRP: ::mode_t = 0o000020;
+pub const S_IRGRP: ::mode_t = 0o000040;
+pub const S_IRWXG: ::mode_t = 0o000070;
+pub const S_IXUSR: ::mode_t = 0o000100;
+pub const S_IWUSR: ::mode_t = 0o000200;
+pub const S_IRUSR: ::mode_t = 0o000400;
+pub const S_IRWXU: ::mode_t = 0o000700;
+
+pub const F_LOCK: ::c_int = 1;
+pub const F_TEST: ::c_int = 3;
+pub const F_TLOCK: ::c_int = 2;
+pub const F_ULOCK: ::c_int = 0;
+
+pub const ST_RDONLY: ::c_ulong = 0x01;
+pub const ST_NOSUID: ::c_ulong = 0x04;
+pub const ST_NOEXEC: ::c_ulong = 0x02;
+pub const ST_NOATIME: ::c_ulong = 0x20;
+
+pub const RTLD_NEXT: *mut ::c_void = -3i64 as *mut ::c_void;
+pub const RTLD_DEFAULT: *mut ::c_void = -2i64 as *mut ::c_void;
+pub const RTLD_NODELETE: ::c_int = 0x1000;
+pub const RTLD_NOW: ::c_int = 0x0002;
+
+pub const EMPTY: ::c_short = 0;
+pub const RUN_LVL: ::c_short = 1;
+pub const BOOT_TIME: ::c_short = 2;
+pub const NEW_TIME: ::c_short = 4;
+pub const OLD_TIME: ::c_short = 3;
+pub const INIT_PROCESS: ::c_short = 5;
+pub const LOGIN_PROCESS: ::c_short = 6;
+pub const USER_PROCESS: ::c_short = 7;
+pub const DEAD_PROCESS: ::c_short = 8;
+pub const ACCOUNTING: ::c_short = 9;
+
+pub const ENOTSUP: ::c_int = 48;
+
+pub const BUFSIZ: ::c_uint = 1024;
+pub const TMP_MAX: ::c_uint = 26 * 26 * 26;
+pub const FOPEN_MAX: ::c_uint = 16;
+pub const FILENAME_MAX: ::c_uint = 255;
+
+pub const NI_MAXHOST: ::socklen_t = 1025;
+pub const M_KEEP: ::c_int = 4;
+pub const REG_STARTEND: ::c_int = 0o00004;
+pub const VEOF: usize = 4;
+
+pub const RTLD_GLOBAL: ::c_int = 0x0100;
+pub const RTLD_NOLOAD: ::c_int = 0x0004;
+
+pub const O_RDONLY: ::c_int = 0o000000;
+pub const O_WRONLY: ::c_int = 0o000001;
+pub const O_RDWR: ::c_int = 0o000002;
+
+pub const O_EXEC: ::c_int = 0o00003;
+pub const O_ASYNC: ::c_int = 0o0200000;
+pub const O_NDELAY: ::c_int = O_NONBLOCK;
+pub const O_TRUNC: ::c_int = 0o001000;
+pub const O_CLOEXEC: ::c_int = 0o020000;
+pub const O_DIRECTORY: ::c_int = 0o4000000;
+pub const O_ACCMODE: ::c_int = 0o000007;
+pub const O_APPEND: ::c_int = 0o000010;
+pub const O_CREAT: ::c_int = 0o000400;
+pub const O_EXCL: ::c_int = 0o002000;
+pub const O_NOCTTY: ::c_int = 0o004000;
+pub const O_NONBLOCK: ::c_int = 0o000200;
+pub const O_SYNC: ::c_int = 0o000040;
+pub const O_RSYNC: ::c_int = 0o000100;
+pub const O_DSYNC: ::c_int = 0o000020;
+pub const O_NOFOLLOW: ::c_int = 0o010000;
+
+pub const POSIX_FADV_DONTNEED: ::c_int = 4;
+pub const POSIX_FADV_NOREUSE: ::c_int = 5;
+
+pub const SOCK_SEQPACKET: ::c_int = 5;
+pub const SOCK_STREAM: ::c_int = 1;
+pub const SOCK_DGRAM: ::c_int = 2;
+pub const SOCK_RAW: ::c_int = 3;
+pub const SOCK_RDM: ::c_int = 4;
+pub const SOCK_CLOEXEC: ::c_int = 0x10000000;
+
+pub const SA_SIGINFO: ::c_int = 0x0002;
+pub const SA_NOCLDWAIT: ::c_int = 0x0020;
+pub const SA_NODEFER: ::c_int = 0x0010;
+pub const SA_RESETHAND: ::c_int = 0x0004;
+pub const SA_NOCLDSTOP: ::c_int = 0x0001;
+
+pub const SIGTTIN: ::c_int = 26;
+pub const SIGTTOU: ::c_int = 27;
+pub const SIGXCPU: ::c_int = 30;
+pub const SIGXFSZ: ::c_int = 31;
+pub const SIGVTALRM: ::c_int = 28;
+pub const SIGPROF: ::c_int = 29;
+pub const SIGWINCH: ::c_int = 20;
+pub const SIGCHLD: ::c_int = 18;
+pub const SIGBUS: ::c_int = 10;
+pub const SIGUSR1: ::c_int = 16;
+pub const SIGUSR2: ::c_int = 17;
+pub const SIGCONT: ::c_int = 25;
+pub const SIGSTOP: ::c_int = 23;
+pub const SIGTSTP: ::c_int = 24;
+pub const SIGURG: ::c_int = 21;
+pub const SIGIO: ::c_int = SIGPOLL;
+pub const SIGSYS: ::c_int = 12;
+pub const SIGPOLL: ::c_int = 22;
+pub const SIGPWR: ::c_int = 19;
+pub const SIG_SETMASK: ::c_int = 2;
+pub const SIG_BLOCK: ::c_int = 0;
+pub const SIG_UNBLOCK: ::c_int = 1;
+
+pub const POLLWRNORM: ::c_short = ::POLLOUT;
+pub const POLLWRBAND: ::c_short = 0x0010;
+
+pub const F_SETLK: ::c_int = 106;
+pub const F_SETLKW: ::c_int = 107;
+pub const F_ALLOCSP: ::c_int = 110;
+pub const F_FREESP: ::c_int = 111;
+pub const F_GETLK: ::c_int = 114;
+
+pub const F_RDLCK: ::c_int = 1;
+pub const F_WRLCK: ::c_int = 2;
+pub const F_UNLCK: ::c_int = 3;
+
+pub const NCCS: usize = 40;
+
+pub const MAP_ANON: ::c_int = MAP_ANONYMOUS;
+pub const MAP_ANONYMOUS: ::c_int = 0x00080000;
+
+pub const MCL_CURRENT: ::c_int = 0x000000001;
+pub const MCL_FUTURE: ::c_int = 0x000000002;
+
+pub const _TIO_CBAUD: ::tcflag_t = 15;
+pub const CBAUD: ::tcflag_t = _TIO_CBAUD;
+pub const TAB1: ::tcflag_t = 0x0800;
+pub const TAB2: ::tcflag_t = 0x1000;
+pub const TAB3: ::tcflag_t = 0x1800;
+pub const CR1: ::tcflag_t = 0x200;
+pub const CR2: ::tcflag_t = 0x400;
+pub const CR3: ::tcflag_t = 0x600;
+pub const FF1: ::tcflag_t = 0x8000;
+pub const BS1: ::tcflag_t = 0x2000;
+pub const VT1: ::tcflag_t = 0x4000;
+pub const VWERASE: usize = 14;
+pub const VREPRINT: usize = 12;
+pub const VSUSP: usize = 10;
+pub const VSTART: usize = 8;
+pub const VSTOP: usize = 9;
+pub const VDISCARD: usize = 13;
+pub const VTIME: usize = 17;
+pub const IXON: ::tcflag_t = 0x00000400;
+pub const IXOFF: ::tcflag_t = 0x00001000;
+pub const ONLCR: ::tcflag_t = 0x00000004;
+pub const CSIZE: ::tcflag_t = 0x00000030;
+pub const CS6: ::tcflag_t = 0x10;
+pub const CS7: ::tcflag_t = 0x20;
+pub const CS8: ::tcflag_t = 0x30;
+pub const CSTOPB: ::tcflag_t = 0x00000040;
+pub const CREAD: ::tcflag_t = 0x00000080;
+pub const PARENB: ::tcflag_t = 0x00000100;
+pub const PARODD: ::tcflag_t = 0x00000200;
+pub const HUPCL: ::tcflag_t = 0x00000400;
+pub const CLOCAL: ::tcflag_t = 0x00000800;
+pub const ECHOKE: ::tcflag_t = 0x00000800;
+pub const ECHOE: ::tcflag_t = 0x00000010;
+pub const ECHOK: ::tcflag_t = 0x00000020;
+pub const ECHONL: ::tcflag_t = 0x00000040;
+pub const ECHOCTL: ::tcflag_t = 0x00000200;
+pub const ISIG: ::tcflag_t = 0x00000001;
+pub const ICANON: ::tcflag_t = 0x00000002;
+pub const NOFLSH: ::tcflag_t = 0x00000080;
+pub const OLCUC: ::tcflag_t = 0x00000002;
+pub const NLDLY: ::tcflag_t = 0x00000100;
+pub const CRDLY: ::tcflag_t = 0x00000600;
+pub const TABDLY: ::tcflag_t = 0x00001800;
+pub const BSDLY: ::tcflag_t = 0x00002000;
+pub const FFDLY: ::tcflag_t = 0x00008000;
+pub const VTDLY: ::tcflag_t = 0x00004000;
+pub const XTABS: ::tcflag_t = 0x1800;
+
+pub const B0: ::speed_t = 0;
+pub const B50: ::speed_t = 1;
+pub const B75: ::speed_t = 2;
+pub const B110: ::speed_t = 3;
+pub const B134: ::speed_t = 4;
+pub const B150: ::speed_t = 5;
+pub const B200: ::speed_t = 6;
+pub const B300: ::speed_t = 7;
+pub const B600: ::speed_t = 8;
+pub const B1200: ::speed_t = 9;
+pub const B1800: ::speed_t = 10;
+pub const B2400: ::speed_t = 11;
+pub const B4800: ::speed_t = 12;
+pub const B9600: ::speed_t = 13;
+pub const B19200: ::speed_t = 14;
+pub const B38400: ::speed_t = 15;
+pub const EXTA: ::speed_t = 14;
+pub const EXTB: ::speed_t = 15;
+pub const B57600: ::speed_t = 57600;
+pub const B115200: ::speed_t = 115200;
+
+pub const VEOL: usize = 5;
+pub const VEOL2: usize = 6;
+pub const VMIN: usize = 16;
+pub const IEXTEN: ::tcflag_t = 0x00008000;
+pub const TOSTOP: ::tcflag_t = 0x00000100;
+
+pub const TCSANOW: ::c_int = 0x0001;
+pub const TCSADRAIN: ::c_int = 0x0002;
+pub const TCSAFLUSH: ::c_int = 0x0004;
+
+pub const HW_MACHINE: ::c_int = 1;
+pub const HW_MODEL: ::c_int = 2;
+pub const HW_NCPU: ::c_int = 3;
+pub const HW_BYTEORDER: ::c_int = 4;
+pub const HW_PHYSMEM: ::c_int = 5;
+pub const HW_USERMEM: ::c_int = 6;
+pub const HW_PAGESIZE: ::c_int = 7;
+pub const HW_DISKNAMES: ::c_int = 8;
+pub const HW_IOSTATS: ::c_int = 9;
+pub const HW_MACHINE_ARCH: ::c_int = 10;
+pub const HW_ALIGNBYTES: ::c_int = 11;
+pub const HW_CNMAGIC: ::c_int = 12;
+pub const HW_PHYSMEM64: ::c_int = 13;
+pub const HW_USERMEM64: ::c_int = 14;
+pub const HW_IOSTATNAMES: ::c_int = 15;
+pub const HW_MAXID: ::c_int = 15;
+
+pub const CTL_UNSPEC: ::c_int = 0;
+pub const CTL_KERN: ::c_int = 1;
+pub const CTL_VM: ::c_int = 2;
+pub const CTL_VFS: ::c_int = 3;
+pub const CTL_NET: ::c_int = 4;
+pub const CTL_DEBUG: ::c_int = 5;
+pub const CTL_HW: ::c_int = 6;
+pub const CTL_MACHDEP: ::c_int = 7;
+pub const CTL_USER: ::c_int = 8;
+pub const CTL_QNX: ::c_int = 9;
+pub const CTL_PROC: ::c_int = 10;
+pub const CTL_VENDOR: ::c_int = 11;
+pub const CTL_EMUL: ::c_int = 12;
+pub const CTL_SECURITY: ::c_int = 13;
+pub const CTL_MAXID: ::c_int = 14;
+
+pub const DAY_1: ::nl_item = 8;
+pub const DAY_2: ::nl_item = 9;
+pub const DAY_3: ::nl_item = 10;
+pub const DAY_4: ::nl_item = 11;
+pub const DAY_5: ::nl_item = 12;
+pub const DAY_6: ::nl_item = 13;
+pub const DAY_7: ::nl_item = 14;
+
+pub const MON_1: ::nl_item = 22;
+pub const MON_2: ::nl_item = 23;
+pub const MON_3: ::nl_item = 24;
+pub const MON_4: ::nl_item = 25;
+pub const MON_5: ::nl_item = 26;
+pub const MON_6: ::nl_item = 27;
+pub const MON_7: ::nl_item = 28;
+pub const MON_8: ::nl_item = 29;
+pub const MON_9: ::nl_item = 30;
+pub const MON_10: ::nl_item = 31;
+pub const MON_11: ::nl_item = 32;
+pub const MON_12: ::nl_item = 33;
+
+pub const ABDAY_1: ::nl_item = 15;
+pub const ABDAY_2: ::nl_item = 16;
+pub const ABDAY_3: ::nl_item = 17;
+pub const ABDAY_4: ::nl_item = 18;
+pub const ABDAY_5: ::nl_item = 19;
+pub const ABDAY_6: ::nl_item = 20;
+pub const ABDAY_7: ::nl_item = 21;
+
+pub const ABMON_1: ::nl_item = 34;
+pub const ABMON_2: ::nl_item = 35;
+pub const ABMON_3: ::nl_item = 36;
+pub const ABMON_4: ::nl_item = 37;
+pub const ABMON_5: ::nl_item = 38;
+pub const ABMON_6: ::nl_item = 39;
+pub const ABMON_7: ::nl_item = 40;
+pub const ABMON_8: ::nl_item = 41;
+pub const ABMON_9: ::nl_item = 42;
+pub const ABMON_10: ::nl_item = 43;
+pub const ABMON_11: ::nl_item = 44;
+pub const ABMON_12: ::nl_item = 45;
+
+pub const AF_ARP: ::c_int = 28;
+pub const AF_CCITT: ::c_int = 10;
+pub const AF_CHAOS: ::c_int = 5;
+pub const AF_CNT: ::c_int = 21;
+pub const AF_COIP: ::c_int = 20;
+pub const AF_DATAKIT: ::c_int = 9;
+pub const AF_DECnet: ::c_int = 12;
+pub const AF_DLI: ::c_int = 13;
+pub const AF_E164: ::c_int = 26;
+pub const AF_ECMA: ::c_int = 8;
+pub const AF_HYLINK: ::c_int = 15;
+pub const AF_IEEE80211: ::c_int = 32;
+pub const AF_IMPLINK: ::c_int = 3;
+pub const AF_ISO: ::c_int = 7;
+pub const AF_LAT: ::c_int = 14;
+pub const AF_LINK: ::c_int = 18;
+pub const AF_NATM: ::c_int = 27;
+pub const AF_NS: ::c_int = 6;
+pub const AF_OSI: ::c_int = 7;
+pub const AF_PUP: ::c_int = 4;
+pub const ALT_DIGITS: ::nl_item = 50;
+pub const AM_STR: ::nl_item = 6;
+pub const B76800: ::speed_t = 76800;
+
+pub const BIOCFLUSH: ::c_int = 17000;
+pub const BIOCGBLEN: ::c_int = 1074020966;
+pub const BIOCGDLT: ::c_int = 1074020970;
+pub const BIOCGDLTLIST: ::c_int = -1072676233;
+pub const BIOCGETIF: ::c_int = 1083196011;
+pub const BIOCGHDRCMPLT: ::c_int = 1074020980;
+pub const BIOCGRTIMEOUT: ::c_int = 1074807406;
+pub const BIOCGSEESENT: ::c_int = 1074020984;
+pub const BIOCGSTATS: ::c_int = 1082147439;
+pub const BIOCIMMEDIATE: ::c_int = -2147204496;
+pub const BIOCPROMISC: ::c_int = 17001;
+pub const BIOCSBLEN: ::c_int = -1073462682;
+pub const BIOCSDLT: ::c_int = -2147204490;
+pub const BIOCSETF: ::c_int = -2146418073;
+pub const BIOCSETIF: ::c_int = -2138029460;
+pub const BIOCSHDRCMPLT: ::c_int = -2147204491;
+pub const BIOCSRTIMEOUT: ::c_int = -2146418067;
+pub const BIOCSSEESENT: ::c_int = -2147204487;
+pub const BIOCVERSION: ::c_int = 1074020977;
+
+pub const BPF_ALIGNMENT: usize = ::mem::size_of::<::c_long>();
+pub const CHAR_BIT: usize = 8;
+pub const CODESET: ::nl_item = 1;
+pub const CRNCYSTR: ::nl_item = 55;
+
+pub const D_FLAG_FILTER: ::c_int = 0x00000001;
+pub const D_FLAG_STAT: ::c_int = 0x00000002;
+pub const D_FLAG_STAT_FORM_MASK: ::c_int = 0x000000f0;
+pub const D_FLAG_STAT_FORM_T32_2001: ::c_int = 0x00000010;
+pub const D_FLAG_STAT_FORM_T32_2008: ::c_int = 0x00000020;
+pub const D_FLAG_STAT_FORM_T64_2008: ::c_int = 0x00000030;
+pub const D_FLAG_STAT_FORM_UNSET: ::c_int = 0x00000000;
+
+pub const D_FMT: ::nl_item = 3;
+pub const D_GETFLAG: ::c_int = 1;
+pub const D_SETFLAG: ::c_int = 2;
+pub const D_T_FMT: ::nl_item = 2;
+pub const ERA: ::nl_item = 46;
+pub const ERA_D_FMT: ::nl_item = 47;
+pub const ERA_D_T_FMT: ::nl_item = 48;
+pub const ERA_T_FMT: ::nl_item = 49;
+pub const RADIXCHAR: ::nl_item = 51;
+pub const THOUSEP: ::nl_item = 52;
+pub const YESEXPR: ::nl_item = 53;
+pub const NOEXPR: ::nl_item = 54;
+pub const F_GETOWN: ::c_int = 35;
+
+pub const FIONBIO: ::c_int = -2147195266;
+pub const FIOASYNC: ::c_int = -2147195267;
+pub const FIOCLEX: ::c_int = 26113;
+pub const FIOGETOWN: ::c_int = 1074030203;
+pub const FIONCLEX: ::c_int = 26114;
+pub const FIONREAD: ::c_int = 1074030207;
+pub const FIONSPACE: ::c_int = 1074030200;
+pub const FIONWRITE: ::c_int = 1074030201;
+pub const FIOSETOWN: ::c_int = -2147195268;
+
+pub const F_SETOWN: ::c_int = 36;
+pub const IFF_ACCEPTRTADV: ::c_int = 0x40000000;
+pub const IFF_IP6FORWARDING: ::c_int = 0x20000000;
+pub const IFF_LINK0: ::c_int = 0x00001000;
+pub const IFF_LINK1: ::c_int = 0x00002000;
+pub const IFF_LINK2: ::c_int = 0x00004000;
+pub const IFF_OACTIVE: ::c_int = 0x00000400;
+pub const IFF_SHIM: ::c_int = 0x80000000;
+pub const IFF_SIMPLEX: ::c_int = 0x00000800;
+pub const IHFLOW: tcflag_t = 0x00000001;
+pub const IIDLE: tcflag_t = 0x00000008;
+pub const IP_RECVDSTADDR: ::c_int = 7;
+pub const IP_RECVIF: ::c_int = 20;
+pub const IPTOS_ECN_NOTECT: u8 = 0x00;
+pub const IUCLC: tcflag_t = 0x00000200;
+pub const IUTF8: tcflag_t = 0x0004000;
+
+pub const KERN_ARGMAX: ::c_int = 8;
+pub const KERN_ARND: ::c_int = 81;
+pub const KERN_BOOTTIME: ::c_int = 21;
+pub const KERN_CLOCKRATE: ::c_int = 12;
+pub const KERN_FILE: ::c_int = 15;
+pub const KERN_HOSTID: ::c_int = 11;
+pub const KERN_HOSTNAME: ::c_int = 10;
+pub const KERN_IOV_MAX: ::c_int = 38;
+pub const KERN_JOB_CONTROL: ::c_int = 19;
+pub const KERN_LOGSIGEXIT: ::c_int = 46;
+pub const KERN_MAXFILES: ::c_int = 7;
+pub const KERN_MAXID: ::c_int = 83;
+pub const KERN_MAXPROC: ::c_int = 6;
+pub const KERN_MAXVNODES: ::c_int = 5;
+pub const KERN_NGROUPS: ::c_int = 18;
+pub const KERN_OSRELEASE: ::c_int = 2;
+pub const KERN_OSREV: ::c_int = 3;
+pub const KERN_OSTYPE: ::c_int = 1;
+pub const KERN_POSIX1: ::c_int = 17;
+pub const KERN_PROC: ::c_int = 14;
+pub const KERN_PROC_ALL: ::c_int = 0;
+pub const KERN_PROC_ARGS: ::c_int = 48;
+pub const KERN_PROC_ENV: ::c_int = 3;
+pub const KERN_PROC_GID: ::c_int = 7;
+pub const KERN_PROC_PGRP: ::c_int = 2;
+pub const KERN_PROC_PID: ::c_int = 1;
+pub const KERN_PROC_RGID: ::c_int = 8;
+pub const KERN_PROC_RUID: ::c_int = 6;
+pub const KERN_PROC_SESSION: ::c_int = 3;
+pub const KERN_PROC_TTY: ::c_int = 4;
+pub const KERN_PROC_UID: ::c_int = 5;
+pub const KERN_PROF: ::c_int = 16;
+pub const KERN_SAVED_IDS: ::c_int = 20;
+pub const KERN_SECURELVL: ::c_int = 9;
+pub const KERN_VERSION: ::c_int = 4;
+pub const KERN_VNODE: ::c_int = 13;
+
+pub const LC_ALL: ::c_int = 63;
+pub const LC_COLLATE: ::c_int = 1;
+pub const LC_CTYPE: ::c_int = 2;
+pub const LC_MESSAGES: ::c_int = 32;
+pub const LC_MONETARY: ::c_int = 4;
+pub const LC_NUMERIC: ::c_int = 8;
+pub const LC_TIME: ::c_int = 16;
+
+pub const LOCAL_CONNWAIT: ::c_int = 0x0002;
+pub const LOCAL_CREDS: ::c_int = 0x0001;
+pub const LOCAL_PEEREID: ::c_int = 0x0003;
+
+pub const MAP_STACK: ::c_int = 0x00001000;
+pub const MNT_NOEXEC: ::c_int = 0x02;
+pub const MNT_NOSUID: ::c_int = 0x04;
+pub const MNT_RDONLY: ::c_int = 0x01;
+
+pub const MSG_NOTIFICATION: ::c_int = 0x0400;
+
+pub const NET_RT_DUMP: ::c_int = 1;
+pub const NET_RT_FLAGS: ::c_int = 2;
+pub const NET_RT_IFLIST: ::c_int = 4;
+pub const NI_NUMERICSCOPE: ::c_int = 0x00000040;
+pub const OHFLOW: tcflag_t = 0x00000002;
+pub const P_ALL: idtype_t = 0;
+pub const PARSTK: tcflag_t = 0x00000004;
+pub const PF_ARP: ::c_int = 28;
+pub const PF_CCITT: ::c_int = 10;
+pub const PF_CHAOS: ::c_int = 5;
+pub const PF_CNT: ::c_int = 21;
+pub const PF_COIP: ::c_int = 20;
+pub const PF_DATAKIT: ::c_int = 9;
+pub const PF_DECnet: ::c_int = 12;
+pub const PF_DLI: ::c_int = 13;
+pub const PF_ECMA: ::c_int = 8;
+pub const PF_HYLINK: ::c_int = 15;
+pub const PF_IMPLINK: ::c_int = 3;
+pub const PF_ISO: ::c_int = 7;
+pub const PF_LAT: ::c_int = 14;
+pub const PF_LINK: ::c_int = 18;
+pub const PF_NATM: ::c_int = 27;
+pub const PF_OSI: ::c_int = 7;
+pub const PF_PIP: ::c_int = 25;
+pub const PF_PUP: ::c_int = 4;
+pub const PF_RTIP: ::c_int = 22;
+pub const PF_XTP: ::c_int = 19;
+pub const PM_STR: ::nl_item = 7;
+pub const POSIX_MADV_DONTNEED: ::c_int = 4;
+pub const POSIX_MADV_NORMAL: ::c_int = 0;
+pub const POSIX_MADV_RANDOM: ::c_int = 2;
+pub const POSIX_MADV_SEQUENTIAL: ::c_int = 1;
+pub const POSIX_MADV_WILLNEED: ::c_int = 3;
+pub const _POSIX_VDISABLE: ::c_int = 0;
+pub const P_PGID: idtype_t = 2;
+pub const P_PID: idtype_t = 1;
+pub const PRIO_PGRP: ::c_int = 1;
+pub const PRIO_PROCESS: ::c_int = 0;
+pub const PRIO_USER: ::c_int = 2;
+pub const pseudo_AF_HDRCMPLT: ::c_int = 30;
+pub const pseudo_AF_PIP: ::c_int = 25;
+pub const pseudo_AF_RTIP: ::c_int = 22;
+pub const pseudo_AF_XTP: ::c_int = 19;
+pub const REG_ASSERT: ::c_int = 15;
+pub const REG_ATOI: ::c_int = 255;
+pub const REG_BACKR: ::c_int = 0x400;
+pub const REG_BASIC: ::c_int = 0x00;
+pub const REG_DUMP: ::c_int = 0x80;
+pub const REG_EMPTY: ::c_int = 14;
+pub const REG_INVARG: ::c_int = 16;
+pub const REG_ITOA: ::c_int = 0o400;
+pub const REG_LARGE: ::c_int = 0x200;
+pub const REG_NOSPEC: ::c_int = 0x10;
+pub const REG_OK: ::c_int = 0;
+pub const REG_PEND: ::c_int = 0x20;
+pub const REG_TRACE: ::c_int = 0x100;
+
+pub const RLIMIT_AS: ::c_int = 6;
+pub const RLIMIT_CORE: ::c_int = 4;
+pub const RLIMIT_CPU: ::c_int = 0;
+pub const RLIMIT_DATA: ::c_int = 2;
+pub const RLIMIT_FSIZE: ::c_int = 1;
+pub const RLIMIT_MEMLOCK: ::c_int = 7;
+pub const RLIMIT_NOFILE: ::c_int = 5;
+pub const RLIMIT_NPROC: ::c_int = 8;
+pub const RLIMIT_RSS: ::c_int = 6;
+pub const RLIMIT_STACK: ::c_int = 3;
+pub const RLIMIT_VMEM: ::c_int = 6;
+pub const RLIM_NLIMITS: ::c_int = 14;
+
+pub const SCHED_ADJTOHEAD: ::c_int = 5;
+pub const SCHED_ADJTOTAIL: ::c_int = 6;
+pub const SCHED_MAXPOLICY: ::c_int = 7;
+pub const SCHED_SETPRIO: ::c_int = 7;
+pub const SCHED_SPORADIC: ::c_int = 4;
+
+pub const SHM_ANON: *mut ::c_char = -1isize as *mut ::c_char;
+pub const SIGCLD: ::c_int = SIGCHLD;
+pub const SIGDEADLK: ::c_int = 7;
+pub const SIGEMT: ::c_int = 7;
+pub const SIGEV_NONE: ::c_int = 0;
+pub const SIGEV_SIGNAL: ::c_int = 129;
+pub const SIGEV_THREAD: ::c_int = 135;
+pub const SIOCGIFADDR: ::c_int = -1064277727;
+pub const SO_FIB: ::c_int = 0x100a;
+pub const SO_OVERFLOWED: ::c_int = 0x1009;
+pub const SO_SETFIB: ::c_int = 0x100a;
+pub const SO_TXPRIO: ::c_int = 0x100b;
+pub const SO_USELOOPBACK: ::c_int = 0x0040;
+pub const SO_VLANPRIO: ::c_int = 0x100c;
+pub const _SS_ALIGNSIZE: usize = ::mem::size_of::<i64>();
+pub const _SS_MAXSIZE: usize = 128;
+pub const _SS_PAD1SIZE: usize = _SS_ALIGNSIZE - 2;
+pub const _SS_PAD2SIZE: usize = _SS_MAXSIZE - 2 - _SS_PAD1SIZE - _SS_ALIGNSIZE;
+pub const TC_CPOSIX: tcflag_t = CLOCAL | CREAD | CSIZE | CSTOPB | HUPCL | PARENB | PARODD;
+pub const TCGETS: ::c_int = 0x404c540d;
+pub const TC_IPOSIX: tcflag_t =
+ BRKINT | ICRNL | IGNBRK | IGNPAR | INLCR | INPCK | ISTRIP | IXOFF | IXON | PARMRK;
+pub const TC_LPOSIX: tcflag_t =
+ ECHO | ECHOE | ECHOK | ECHONL | ICANON | IEXTEN | ISIG | NOFLSH | TOSTOP;
+pub const TC_OPOSIX: tcflag_t = OPOST;
+pub const T_FMT_AMPM: ::nl_item = 5;
+
+pub const TIOCCBRK: ::c_int = 29818;
+pub const TIOCCDTR: ::c_int = 29816;
+pub const TIOCDRAIN: ::c_int = 29790;
+pub const TIOCEXCL: ::c_int = 29709;
+pub const TIOCFLUSH: ::c_int = -2147191792;
+pub const TIOCGETA: ::c_int = 1078752275;
+pub const TIOCGPGRP: ::c_int = 1074033783;
+pub const TIOCGWINSZ: ::c_int = 1074295912;
+pub const TIOCMBIC: ::c_int = -2147191701;
+pub const TIOCMBIS: ::c_int = -2147191700;
+pub const TIOCMGET: ::c_int = 1074033770;
+pub const TIOCMSET: ::c_int = -2147191699;
+pub const TIOCNOTTY: ::c_int = 29809;
+pub const TIOCNXCL: ::c_int = 29710;
+pub const TIOCOUTQ: ::c_int = 1074033779;
+pub const TIOCPKT: ::c_int = -2147191696;
+pub const TIOCPKT_DATA: ::c_int = 0x00;
+pub const TIOCPKT_DOSTOP: ::c_int = 0x20;
+pub const TIOCPKT_FLUSHREAD: ::c_int = 0x01;
+pub const TIOCPKT_FLUSHWRITE: ::c_int = 0x02;
+pub const TIOCPKT_IOCTL: ::c_int = 0x40;
+pub const TIOCPKT_NOSTOP: ::c_int = 0x10;
+pub const TIOCPKT_START: ::c_int = 0x08;
+pub const TIOCPKT_STOP: ::c_int = 0x04;
+pub const TIOCSBRK: ::c_int = 29819;
+pub const TIOCSCTTY: ::c_int = 29793;
+pub const TIOCSDTR: ::c_int = 29817;
+pub const TIOCSETA: ::c_int = -2142473196;
+pub const TIOCSETAF: ::c_int = -2142473194;
+pub const TIOCSETAW: ::c_int = -2142473195;
+pub const TIOCSPGRP: ::c_int = -2147191690;
+pub const TIOCSTART: ::c_int = 29806;
+pub const TIOCSTI: ::c_int = -2147388302;
+pub const TIOCSTOP: ::c_int = 29807;
+pub const TIOCSWINSZ: ::c_int = -2146929561;
+
+pub const USER_CS_PATH: ::c_int = 1;
+pub const USER_BC_BASE_MAX: ::c_int = 2;
+pub const USER_BC_DIM_MAX: ::c_int = 3;
+pub const USER_BC_SCALE_MAX: ::c_int = 4;
+pub const USER_BC_STRING_MAX: ::c_int = 5;
+pub const USER_COLL_WEIGHTS_MAX: ::c_int = 6;
+pub const USER_EXPR_NEST_MAX: ::c_int = 7;
+pub const USER_LINE_MAX: ::c_int = 8;
+pub const USER_RE_DUP_MAX: ::c_int = 9;
+pub const USER_POSIX2_VERSION: ::c_int = 10;
+pub const USER_POSIX2_C_BIND: ::c_int = 11;
+pub const USER_POSIX2_C_DEV: ::c_int = 12;
+pub const USER_POSIX2_CHAR_TERM: ::c_int = 13;
+pub const USER_POSIX2_FORT_DEV: ::c_int = 14;
+pub const USER_POSIX2_FORT_RUN: ::c_int = 15;
+pub const USER_POSIX2_LOCALEDEF: ::c_int = 16;
+pub const USER_POSIX2_SW_DEV: ::c_int = 17;
+pub const USER_POSIX2_UPE: ::c_int = 18;
+pub const USER_STREAM_MAX: ::c_int = 19;
+pub const USER_TZNAME_MAX: ::c_int = 20;
+pub const USER_ATEXIT_MAX: ::c_int = 21;
+pub const USER_MAXID: ::c_int = 22;
+
+pub const VDOWN: usize = 31;
+pub const VINS: usize = 32;
+pub const VDEL: usize = 33;
+pub const VRUB: usize = 34;
+pub const VCAN: usize = 35;
+pub const VHOME: usize = 36;
+pub const VEND: usize = 37;
+pub const VSPARE3: usize = 38;
+pub const VSPARE4: usize = 39;
+pub const VSWTCH: usize = 7;
+pub const VDSUSP: usize = 11;
+pub const VFWD: usize = 18;
+pub const VLOGIN: usize = 19;
+pub const VPREFIX: usize = 20;
+pub const VSUFFIX: usize = 24;
+pub const VLEFT: usize = 28;
+pub const VRIGHT: usize = 29;
+pub const VUP: usize = 30;
+pub const XCASE: tcflag_t = 0x00000004;
+
+pub const PTHREAD_CREATE_JOINABLE: ::c_int = 0x00;
+pub const PTHREAD_CREATE_DETACHED: ::c_int = 0x01;
+
+pub const PTHREAD_MUTEX_ERRORCHECK: ::c_int = 1;
+pub const PTHREAD_MUTEX_RECURSIVE: ::c_int = 2;
+pub const PTHREAD_MUTEX_NORMAL: ::c_int = 3;
+pub const PTHREAD_STACK_MIN: ::size_t = 256;
+pub const PTHREAD_MUTEX_DEFAULT: ::c_int = 0;
+pub const PTHREAD_MUTEX_STALLED: ::c_int = 0x00;
+pub const PTHREAD_MUTEX_ROBUST: ::c_int = 0x10;
+pub const PTHREAD_PROCESS_PRIVATE: ::c_int = 0x00;
+pub const PTHREAD_PROCESS_SHARED: ::c_int = 0x01;
+
+pub const PTHREAD_KEYS_MAX: usize = 128;
+
+pub const PTHREAD_MUTEX_INITIALIZER: pthread_mutex_t = pthread_mutex_t {
+ __u: 0x80000000,
+ __owner: 0xffffffff,
+};
+pub const PTHREAD_COND_INITIALIZER: pthread_cond_t = pthread_cond_t {
+ __u: CLOCK_REALTIME as u32,
+ __owner: 0xfffffffb,
+};
+pub const PTHREAD_RWLOCK_INITIALIZER: pthread_rwlock_t = pthread_rwlock_t {
+ __active: 0,
+ __blockedwriters: 0,
+ __blockedreaders: 0,
+ __heavy: 0,
+ __lock: PTHREAD_MUTEX_INITIALIZER,
+ __rcond: PTHREAD_COND_INITIALIZER,
+ __wcond: PTHREAD_COND_INITIALIZER,
+ __owner: -2i32 as ::c_uint,
+ __spare: 0,
+};
+
+const_fn! {
+ {const} fn _CMSG_ALIGN(len: usize) -> usize {
+ len + ::mem::size_of::<usize>() - 1 & !(::mem::size_of::<usize>() - 1)
+ }
+
+ {const} fn _ALIGN(p: usize, b: usize) -> usize {
+ (p + b - 1) & !(b-1)
+ }
+}
+
+f! {
+ pub fn CMSG_FIRSTHDR(mhdr: *const msghdr) -> *mut cmsghdr {
+ if (*mhdr).msg_controllen as usize >= ::mem::size_of::<cmsghdr>() {
+ (*mhdr).msg_control as *mut cmsghdr
+ } else {
+ 0 as *mut cmsghdr
+ }
+ }
+
+ pub fn CMSG_NXTHDR(mhdr: *const ::msghdr, cmsg: *const ::cmsghdr)
+ -> *mut ::cmsghdr
+ {
+ let msg = _CMSG_ALIGN((*cmsg).cmsg_len as usize);
+ let next = cmsg as usize + msg + _CMSG_ALIGN(::mem::size_of::<::cmsghdr>());
+ if next > (*mhdr).msg_control as usize + (*mhdr).msg_controllen as usize {
+ 0 as *mut ::cmsghdr
+ } else {
+ (cmsg as usize + msg) as *mut ::cmsghdr
+ }
+ }
+
+ pub fn CMSG_DATA(cmsg: *const ::cmsghdr) -> *mut ::c_uchar {
+ (cmsg as *mut ::c_uchar)
+ .offset(_CMSG_ALIGN(::mem::size_of::<::cmsghdr>()) as isize)
+ }
+
+ pub fn CMSG_LEN(length: ::c_uint) -> ::c_uint {
+ _CMSG_ALIGN(::mem::size_of::<::cmsghdr>()) as ::c_uint + length
+ }
+
+ pub {const} fn CMSG_SPACE(length: ::c_uint) -> ::c_uint {
+ (_CMSG_ALIGN(::mem::size_of::<cmsghdr>()) + _CMSG_ALIGN(length as usize) )
+ as ::c_uint
+ }
+
+ pub fn FD_CLR(fd: ::c_int, set: *mut fd_set) -> () {
+ let fd = fd as usize;
+ let size = ::mem::size_of_val(&(*set).fds_bits[0]) * 8;
+ (*set).fds_bits[fd / size] &= !(1 << (fd % size));
+ return
+ }
+
+ pub fn FD_ISSET(fd: ::c_int, set: *const fd_set) -> bool {
+ let fd = fd as usize;
+ let size = ::mem::size_of_val(&(*set).fds_bits[0]) * 8;
+ return ((*set).fds_bits[fd / size] & (1 << (fd % size))) != 0
+ }
+
+ pub fn FD_SET(fd: ::c_int, set: *mut fd_set) -> () {
+ let fd = fd as usize;
+ let size = ::mem::size_of_val(&(*set).fds_bits[0]) * 8;
+ (*set).fds_bits[fd / size] |= 1 << (fd % size);
+ return
+ }
+
+ pub fn FD_ZERO(set: *mut fd_set) -> () {
+ for slot in (*set).fds_bits.iter_mut() {
+ *slot = 0;
+ }
+ }
+
+ pub fn _DEXTRA_FIRST(_d: *const dirent) -> *mut ::dirent_extra {
+ let _f = &((*(_d)).d_name) as *const _;
+ let _s = _d as usize;
+
+ _ALIGN(_s + _f as usize - _s + (*_d).d_namelen as usize + 1, 8) as *mut ::dirent_extra
+ }
+
+ pub fn _DEXTRA_VALID(_x: *const ::dirent_extra, _d: *const dirent) -> bool {
+ let sz = _x as usize - _d as usize + ::mem::size_of::<::dirent_extra>();
+ let rsz = (*_d).d_reclen as usize;
+
+ if sz > rsz || sz + (*_x).d_datalen as usize > rsz {
+ false
+ } else {
+ true
+ }
+ }
+
+ pub fn _DEXTRA_NEXT(_x: *const ::dirent_extra) -> *mut ::dirent_extra {
+ _ALIGN(
+ _x as usize + ::mem::size_of::<::dirent_extra>() + (*_x).d_datalen as usize, 8
+ ) as *mut ::dirent_extra
+ }
+
+ pub fn SOCKCREDSIZE(ngrps: usize) -> usize {
+ let ngrps = if ngrps > 0 {
+ ngrps - 1
+ } else {
+ 0
+ };
+ ::mem::size_of::<sockcred>() + ::mem::size_of::<::gid_t>() * ngrps
+ }
+}
+
+safe_f! {
+ pub {const} fn WIFSTOPPED(status: ::c_int) -> bool {
+ (status & 0xff) == 0x7f
+ }
+
+ pub {const} fn WSTOPSIG(status: ::c_int) -> ::c_int {
+ (status >> 8) & 0xff
+ }
+
+ pub {const} fn WIFCONTINUED(status: ::c_int) -> bool {
+ status == 0xffff
+ }
+
+ pub {const} fn WIFSIGNALED(status: ::c_int) -> bool {
+ ((status & 0x7f) + 1) as i8 >= 2
+ }
+
+ pub {const} fn WTERMSIG(status: ::c_int) -> ::c_int {
+ status & 0x7f
+ }
+
+ pub {const} fn WIFEXITED(status: ::c_int) -> bool {
+ (status & 0x7f) == 0
+ }
+
+ pub {const} fn WEXITSTATUS(status: ::c_int) -> ::c_int {
+ (status >> 8) & 0xff
+ }
+
+ pub {const} fn WCOREDUMP(status: ::c_int) -> bool {
+ (status & 0x80) != 0
+ }
+
+ pub {const} fn IPTOS_ECN(x: u8) -> u8 {
+ x & ::IPTOS_ECN_MASK
+ }
+}
+
+// Network related functions are provided by libsocket and regex
+// functions are provided by libregex.
+#[link(name = "socket")]
+#[link(name = "regex")]
+
+extern "C" {
+ pub fn sem_destroy(sem: *mut sem_t) -> ::c_int;
+ pub fn sem_init(sem: *mut sem_t, pshared: ::c_int, value: ::c_uint) -> ::c_int;
+ pub fn fdatasync(fd: ::c_int) -> ::c_int;
+ pub fn getpriority(which: ::c_int, who: ::id_t) -> ::c_int;
+ pub fn setpriority(which: ::c_int, who: ::id_t, prio: ::c_int) -> ::c_int;
+ pub fn mkfifoat(dirfd: ::c_int, pathname: *const ::c_char, mode: ::mode_t) -> ::c_int;
+
+ pub fn clock_getres(clk_id: ::clockid_t, tp: *mut ::timespec) -> ::c_int;
+ pub fn clock_gettime(clk_id: ::clockid_t, tp: *mut ::timespec) -> ::c_int;
+ pub fn clock_settime(clk_id: ::clockid_t, tp: *const ::timespec) -> ::c_int;
+ pub fn clock_getcpuclockid(pid: ::pid_t, clk_id: *mut ::clockid_t) -> ::c_int;
+
+ pub fn pthread_attr_getstack(
+ attr: *const ::pthread_attr_t,
+ stackaddr: *mut *mut ::c_void,
+ stacksize: *mut ::size_t,
+ ) -> ::c_int;
+ pub fn memalign(align: ::size_t, size: ::size_t) -> *mut ::c_void;
+ pub fn setgroups(ngroups: ::c_int, ptr: *const ::gid_t) -> ::c_int;
+
+ pub fn posix_fadvise(fd: ::c_int, offset: ::off_t, len: ::off_t, advise: ::c_int) -> ::c_int;
+ pub fn futimens(fd: ::c_int, times: *const ::timespec) -> ::c_int;
+ pub fn nl_langinfo(item: ::nl_item) -> *mut ::c_char;
+
+ pub fn utimensat(
+ dirfd: ::c_int,
+ path: *const ::c_char,
+ times: *const ::timespec,
+ flag: ::c_int,
+ ) -> ::c_int;
+
+ pub fn pthread_condattr_getclock(
+ attr: *const pthread_condattr_t,
+ clock_id: *mut clockid_t,
+ ) -> ::c_int;
+ pub fn pthread_condattr_setclock(
+ attr: *mut pthread_condattr_t,
+ clock_id: ::clockid_t,
+ ) -> ::c_int;
+ pub fn pthread_condattr_setpshared(attr: *mut pthread_condattr_t, pshared: ::c_int) -> ::c_int;
+ pub fn pthread_mutexattr_setpshared(
+ attr: *mut pthread_mutexattr_t,
+ pshared: ::c_int,
+ ) -> ::c_int;
+ pub fn pthread_rwlockattr_getpshared(
+ attr: *const pthread_rwlockattr_t,
+ val: *mut ::c_int,
+ ) -> ::c_int;
+ pub fn pthread_rwlockattr_setpshared(attr: *mut pthread_rwlockattr_t, val: ::c_int) -> ::c_int;
+ pub fn ptsname_r(fd: ::c_int, buf: *mut ::c_char, buflen: ::size_t) -> *mut ::c_char;
+ pub fn clearenv() -> ::c_int;
+ pub fn waitid(idtype: idtype_t, id: id_t, infop: *mut ::siginfo_t, options: ::c_int)
+ -> ::c_int;
+ pub fn wait4(
+ pid: ::pid_t,
+ status: *mut ::c_int,
+ options: ::c_int,
+ rusage: *mut ::rusage,
+ ) -> ::pid_t;
+ pub fn execvpe(
+ file: *const ::c_char,
+ argv: *const *const ::c_char,
+ envp: *const *const ::c_char,
+ ) -> ::c_int;
+
+ pub fn getifaddrs(ifap: *mut *mut ::ifaddrs) -> ::c_int;
+ pub fn freeifaddrs(ifa: *mut ::ifaddrs);
+ pub fn bind(socket: ::c_int, address: *const ::sockaddr, address_len: ::socklen_t) -> ::c_int;
+
+ pub fn writev(fd: ::c_int, iov: *const ::iovec, iovcnt: ::c_int) -> ::ssize_t;
+ pub fn readv(fd: ::c_int, iov: *const ::iovec, iovcnt: ::c_int) -> ::ssize_t;
+
+ pub fn sendmsg(fd: ::c_int, msg: *const ::msghdr, flags: ::c_int) -> ::ssize_t;
+ pub fn recvmsg(fd: ::c_int, msg: *mut ::msghdr, flags: ::c_int) -> ::ssize_t;
+ pub fn openpty(
+ amaster: *mut ::c_int,
+ aslave: *mut ::c_int,
+ name: *mut ::c_char,
+ termp: *mut termios,
+ winp: *mut ::winsize,
+ ) -> ::c_int;
+ pub fn forkpty(
+ amaster: *mut ::c_int,
+ name: *mut ::c_char,
+ termp: *mut termios,
+ winp: *mut ::winsize,
+ ) -> ::pid_t;
+ pub fn login_tty(fd: ::c_int) -> ::c_int;
+
+ pub fn uname(buf: *mut ::utsname) -> ::c_int;
+
+ pub fn getpeereid(socket: ::c_int, euid: *mut ::uid_t, egid: *mut ::gid_t) -> ::c_int;
+
+ pub fn strerror_r(errnum: ::c_int, buf: *mut c_char, buflen: ::size_t) -> ::c_int;
+
+ pub fn abs(i: ::c_int) -> ::c_int;
+ pub fn atof(s: *const ::c_char) -> ::c_double;
+ pub fn labs(i: ::c_long) -> ::c_long;
+ pub fn rand() -> ::c_int;
+ pub fn srand(seed: ::c_uint);
+
+ pub fn setpwent();
+ pub fn endpwent();
+ pub fn getpwent() -> *mut passwd;
+ pub fn setgrent();
+ pub fn endgrent();
+ pub fn getgrent() -> *mut ::group;
+ pub fn setspent();
+ pub fn endspent();
+
+ pub fn shm_open(name: *const c_char, oflag: ::c_int, mode: mode_t) -> ::c_int;
+
+ pub fn ftok(pathname: *const ::c_char, proj_id: ::c_int) -> ::key_t;
+ pub fn mprotect(addr: *mut ::c_void, len: ::size_t, prot: ::c_int) -> ::c_int;
+
+ pub fn posix_fallocate(fd: ::c_int, offset: ::off_t, len: ::off_t) -> ::c_int;
+ pub fn mkostemp(template: *mut ::c_char, flags: ::c_int) -> ::c_int;
+ pub fn mkostemps(template: *mut ::c_char, suffixlen: ::c_int, flags: ::c_int) -> ::c_int;
+ pub fn sigtimedwait(
+ set: *const sigset_t,
+ info: *mut siginfo_t,
+ timeout: *const ::timespec,
+ ) -> ::c_int;
+ pub fn sigwaitinfo(set: *const sigset_t, info: *mut siginfo_t) -> ::c_int;
+ pub fn pthread_setschedprio(native: ::pthread_t, priority: ::c_int) -> ::c_int;
+
+ pub fn if_nameindex() -> *mut if_nameindex;
+ pub fn if_freenameindex(ptr: *mut if_nameindex);
+
+ pub fn glob(
+ pattern: *const c_char,
+ flags: ::c_int,
+ errfunc: ::Option<extern "C" fn(epath: *const c_char, errno: ::c_int) -> ::c_int>,
+ pglob: *mut ::glob_t,
+ ) -> ::c_int;
+ pub fn globfree(pglob: *mut ::glob_t);
+
+ pub fn posix_madvise(addr: *mut ::c_void, len: ::size_t, advice: ::c_int) -> ::c_int;
+
+ pub fn shm_unlink(name: *const ::c_char) -> ::c_int;
+
+ pub fn seekdir(dirp: *mut ::DIR, loc: ::c_long);
+
+ pub fn telldir(dirp: *mut ::DIR) -> ::c_long;
+
+ pub fn msync(addr: *mut ::c_void, len: ::size_t, flags: ::c_int) -> ::c_int;
+
+ pub fn recvfrom(
+ socket: ::c_int,
+ buf: *mut ::c_void,
+ len: ::size_t,
+ flags: ::c_int,
+ addr: *mut ::sockaddr,
+ addrlen: *mut ::socklen_t,
+ ) -> ::ssize_t;
+ pub fn mkstemps(template: *mut ::c_char, suffixlen: ::c_int) -> ::c_int;
+
+ pub fn getdomainname(name: *mut ::c_char, len: ::size_t) -> ::c_int;
+ pub fn setdomainname(name: *const ::c_char, len: ::size_t) -> ::c_int;
+ pub fn sync();
+ pub fn pthread_getschedparam(
+ native: ::pthread_t,
+ policy: *mut ::c_int,
+ param: *mut ::sched_param,
+ ) -> ::c_int;
+ pub fn umount(target: *const ::c_char, flags: ::c_int) -> ::c_int;
+ pub fn sched_get_priority_max(policy: ::c_int) -> ::c_int;
+ pub fn settimeofday(tv: *const ::timeval, tz: *const ::c_void) -> ::c_int;
+ pub fn sched_rr_get_interval(pid: ::pid_t, tp: *mut ::timespec) -> ::c_int;
+ pub fn sem_timedwait(sem: *mut sem_t, abstime: *const ::timespec) -> ::c_int;
+ pub fn sem_getvalue(sem: *mut sem_t, sval: *mut ::c_int) -> ::c_int;
+ pub fn sched_setparam(pid: ::pid_t, param: *const ::sched_param) -> ::c_int;
+ pub fn mount(
+ special_device: *const ::c_char,
+ mount_directory: *const ::c_char,
+ flags: ::c_int,
+ mount_type: *const ::c_char,
+ mount_data: *const ::c_void,
+ mount_datalen: ::c_int,
+ ) -> ::c_int;
+ pub fn sched_getparam(pid: ::pid_t, param: *mut ::sched_param) -> ::c_int;
+ pub fn pthread_mutex_consistent(mutex: *mut pthread_mutex_t) -> ::c_int;
+ pub fn pthread_mutex_timedlock(
+ lock: *mut pthread_mutex_t,
+ abstime: *const ::timespec,
+ ) -> ::c_int;
+ pub fn pthread_spin_init(lock: *mut ::pthread_spinlock_t, pshared: ::c_int) -> ::c_int;
+ pub fn pthread_spin_destroy(lock: *mut ::pthread_spinlock_t) -> ::c_int;
+ pub fn pthread_spin_lock(lock: *mut ::pthread_spinlock_t) -> ::c_int;
+ pub fn pthread_spin_trylock(lock: *mut ::pthread_spinlock_t) -> ::c_int;
+ pub fn pthread_spin_unlock(lock: *mut ::pthread_spinlock_t) -> ::c_int;
+ pub fn pthread_barrierattr_init(__attr: *mut ::pthread_barrierattr_t) -> ::c_int;
+ pub fn pthread_barrierattr_destroy(__attr: *mut ::pthread_barrierattr_t) -> ::c_int;
+ pub fn pthread_barrierattr_getpshared(
+ __attr: *const ::pthread_barrierattr_t,
+ __pshared: *mut ::c_int,
+ ) -> ::c_int;
+ pub fn pthread_barrierattr_setpshared(
+ __attr: *mut ::pthread_barrierattr_t,
+ __pshared: ::c_int,
+ ) -> ::c_int;
+ pub fn pthread_barrier_init(
+ __barrier: *mut ::pthread_barrier_t,
+ __attr: *const ::pthread_barrierattr_t,
+ __count: ::c_uint,
+ ) -> ::c_int;
+ pub fn pthread_barrier_destroy(__barrier: *mut ::pthread_barrier_t) -> ::c_int;
+ pub fn pthread_barrier_wait(__barrier: *mut ::pthread_barrier_t) -> ::c_int;
+
+ pub fn sched_getscheduler(pid: ::pid_t) -> ::c_int;
+ pub fn clock_nanosleep(
+ clk_id: ::clockid_t,
+ flags: ::c_int,
+ rqtp: *const ::timespec,
+ rmtp: *mut ::timespec,
+ ) -> ::c_int;
+ pub fn pthread_attr_getguardsize(
+ attr: *const ::pthread_attr_t,
+ guardsize: *mut ::size_t,
+ ) -> ::c_int;
+ pub fn sethostname(name: *const ::c_char, len: ::size_t) -> ::c_int;
+ pub fn sched_get_priority_min(policy: ::c_int) -> ::c_int;
+ pub fn pthread_condattr_getpshared(
+ attr: *const pthread_condattr_t,
+ pshared: *mut ::c_int,
+ ) -> ::c_int;
+ pub fn pthread_setschedparam(
+ native: ::pthread_t,
+ policy: ::c_int,
+ param: *const ::sched_param,
+ ) -> ::c_int;
+ pub fn sched_setscheduler(
+ pid: ::pid_t,
+ policy: ::c_int,
+ param: *const ::sched_param,
+ ) -> ::c_int;
+ pub fn sigsuspend(mask: *const ::sigset_t) -> ::c_int;
+ pub fn getgrgid_r(
+ gid: ::gid_t,
+ grp: *mut ::group,
+ buf: *mut ::c_char,
+ buflen: ::size_t,
+ result: *mut *mut ::group,
+ ) -> ::c_int;
+ pub fn sem_close(sem: *mut sem_t) -> ::c_int;
+ pub fn getdtablesize() -> ::c_int;
+ pub fn getgrnam_r(
+ name: *const ::c_char,
+ grp: *mut ::group,
+ buf: *mut ::c_char,
+ buflen: ::size_t,
+ result: *mut *mut ::group,
+ ) -> ::c_int;
+ pub fn initgroups(user: *const ::c_char, group: ::gid_t) -> ::c_int;
+ pub fn pthread_sigmask(how: ::c_int, set: *const sigset_t, oldset: *mut sigset_t) -> ::c_int;
+ pub fn sem_open(name: *const ::c_char, oflag: ::c_int, ...) -> *mut sem_t;
+ pub fn getgrnam(name: *const ::c_char) -> *mut ::group;
+ pub fn pthread_cancel(thread: ::pthread_t) -> ::c_int;
+ pub fn pthread_kill(thread: ::pthread_t, sig: ::c_int) -> ::c_int;
+ pub fn sem_unlink(name: *const ::c_char) -> ::c_int;
+ pub fn daemon(nochdir: ::c_int, noclose: ::c_int) -> ::c_int;
+ pub fn getpwnam_r(
+ name: *const ::c_char,
+ pwd: *mut passwd,
+ buf: *mut ::c_char,
+ buflen: ::size_t,
+ result: *mut *mut passwd,
+ ) -> ::c_int;
+ pub fn getpwuid_r(
+ uid: ::uid_t,
+ pwd: *mut passwd,
+ buf: *mut ::c_char,
+ buflen: ::size_t,
+ result: *mut *mut passwd,
+ ) -> ::c_int;
+ pub fn sigwait(set: *const sigset_t, sig: *mut ::c_int) -> ::c_int;
+ pub fn pthread_atfork(
+ prepare: ::Option<unsafe extern "C" fn()>,
+ parent: ::Option<unsafe extern "C" fn()>,
+ child: ::Option<unsafe extern "C" fn()>,
+ ) -> ::c_int;
+ pub fn getgrgid(gid: ::gid_t) -> *mut ::group;
+ pub fn getgrouplist(
+ user: *const ::c_char,
+ group: ::gid_t,
+ groups: *mut ::gid_t,
+ ngroups: *mut ::c_int,
+ ) -> ::c_int;
+ pub fn pthread_mutexattr_getpshared(
+ attr: *const pthread_mutexattr_t,
+ pshared: *mut ::c_int,
+ ) -> ::c_int;
+ pub fn pthread_mutexattr_getrobust(
+ attr: *const pthread_mutexattr_t,
+ robustness: *mut ::c_int,
+ ) -> ::c_int;
+ pub fn pthread_mutexattr_setrobust(
+ attr: *mut pthread_mutexattr_t,
+ robustness: ::c_int,
+ ) -> ::c_int;
+ pub fn 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;
+ pub fn getitimer(which: ::c_int, curr_value: *mut ::itimerval) -> ::c_int;
+ pub fn setitimer(
+ which: ::c_int,
+ value: *const ::itimerval,
+ ovalue: *mut ::itimerval,
+ ) -> ::c_int;
+ pub fn posix_spawn(
+ pid: *mut ::pid_t,
+ path: *const ::c_char,
+ file_actions: *const ::posix_spawn_file_actions_t,
+ attrp: *const ::posix_spawnattr_t,
+ argv: *const *mut ::c_char,
+ envp: *const *mut ::c_char,
+ ) -> ::c_int;
+ pub fn posix_spawnp(
+ pid: *mut ::pid_t,
+ file: *const ::c_char,
+ file_actions: *const ::posix_spawn_file_actions_t,
+ attrp: *const ::posix_spawnattr_t,
+ argv: *const *mut ::c_char,
+ envp: *const *mut ::c_char,
+ ) -> ::c_int;
+ pub fn posix_spawnattr_init(attr: *mut posix_spawnattr_t) -> ::c_int;
+ pub fn posix_spawnattr_destroy(attr: *mut posix_spawnattr_t) -> ::c_int;
+ pub fn posix_spawnattr_getsigdefault(
+ attr: *const posix_spawnattr_t,
+ default: *mut ::sigset_t,
+ ) -> ::c_int;
+ pub fn posix_spawnattr_setsigdefault(
+ attr: *mut posix_spawnattr_t,
+ default: *const ::sigset_t,
+ ) -> ::c_int;
+ pub fn posix_spawnattr_getsigmask(
+ attr: *const posix_spawnattr_t,
+ default: *mut ::sigset_t,
+ ) -> ::c_int;
+ pub fn posix_spawnattr_setsigmask(
+ attr: *mut posix_spawnattr_t,
+ default: *const ::sigset_t,
+ ) -> ::c_int;
+ pub fn posix_spawnattr_getflags(
+ attr: *const posix_spawnattr_t,
+ flags: *mut ::c_short,
+ ) -> ::c_int;
+ pub fn posix_spawnattr_setflags(attr: *mut posix_spawnattr_t, flags: ::c_short) -> ::c_int;
+ pub fn posix_spawnattr_getpgroup(
+ attr: *const posix_spawnattr_t,
+ flags: *mut ::pid_t,
+ ) -> ::c_int;
+ pub fn posix_spawnattr_setpgroup(attr: *mut posix_spawnattr_t, flags: ::pid_t) -> ::c_int;
+ pub fn posix_spawnattr_getschedpolicy(
+ attr: *const posix_spawnattr_t,
+ flags: *mut ::c_int,
+ ) -> ::c_int;
+ pub fn posix_spawnattr_setschedpolicy(attr: *mut posix_spawnattr_t, flags: ::c_int) -> ::c_int;
+ pub fn posix_spawnattr_getschedparam(
+ attr: *const posix_spawnattr_t,
+ param: *mut ::sched_param,
+ ) -> ::c_int;
+ pub fn posix_spawnattr_setschedparam(
+ attr: *mut posix_spawnattr_t,
+ param: *const ::sched_param,
+ ) -> ::c_int;
+
+ pub fn posix_spawn_file_actions_init(actions: *mut posix_spawn_file_actions_t) -> ::c_int;
+ pub fn posix_spawn_file_actions_destroy(actions: *mut posix_spawn_file_actions_t) -> ::c_int;
+ pub fn posix_spawn_file_actions_addopen(
+ actions: *mut posix_spawn_file_actions_t,
+ fd: ::c_int,
+ path: *const ::c_char,
+ oflag: ::c_int,
+ mode: ::mode_t,
+ ) -> ::c_int;
+ pub fn posix_spawn_file_actions_addclose(
+ actions: *mut posix_spawn_file_actions_t,
+ fd: ::c_int,
+ ) -> ::c_int;
+ pub fn posix_spawn_file_actions_adddup2(
+ actions: *mut posix_spawn_file_actions_t,
+ fd: ::c_int,
+ newfd: ::c_int,
+ ) -> ::c_int;
+ pub fn popen(command: *const c_char, mode: *const c_char) -> *mut ::FILE;
+ pub fn faccessat(
+ dirfd: ::c_int,
+ pathname: *const ::c_char,
+ mode: ::c_int,
+ flags: ::c_int,
+ ) -> ::c_int;
+ pub fn inotify_rm_watch(fd: ::c_int, wd: ::c_int) -> ::c_int;
+ pub fn inotify_init() -> ::c_int;
+ pub fn inotify_add_watch(fd: ::c_int, path: *const ::c_char, mask: u32) -> ::c_int;
+
+ pub fn gettid() -> ::pid_t;
+
+ pub fn pthread_getcpuclockid(thread: ::pthread_t, clk_id: *mut ::clockid_t) -> ::c_int;
+
+ pub fn getnameinfo(
+ sa: *const ::sockaddr,
+ salen: ::socklen_t,
+ host: *mut ::c_char,
+ hostlen: ::socklen_t,
+ serv: *mut ::c_char,
+ sevlen: ::socklen_t,
+ flags: ::c_int,
+ ) -> ::c_int;
+
+ pub fn sendmmsg(
+ sockfd: ::c_int,
+ msgvec: *mut ::mmsghdr,
+ vlen: ::c_uint,
+ flags: ::c_uint,
+ ) -> ::c_int;
+ pub fn recvmmsg(
+ sockfd: ::c_int,
+ msgvec: *mut ::mmsghdr,
+ vlen: ::c_uint,
+ flags: ::c_uint,
+ timeout: *mut ::timespec,
+ ) -> ::c_int;
+
+ pub fn mallopt(param: ::c_int, value: i64) -> ::c_int;
+ pub fn gettimeofday(tp: *mut ::timeval, tz: *mut ::c_void) -> ::c_int;
+
+ pub fn ctermid(s: *mut ::c_char) -> *mut ::c_char;
+ pub fn ioctl(fd: ::c_int, request: ::c_int, ...) -> ::c_int;
+
+ pub fn mallinfo() -> ::mallinfo;
+ pub fn getpwent_r(
+ pwd: *mut ::passwd,
+ buf: *mut ::c_char,
+ __bufsize: ::c_int,
+ __result: *mut *mut ::passwd,
+ ) -> ::c_int;
+ pub fn pthread_getname_np(thread: ::pthread_t, name: *mut ::c_char, len: ::c_int) -> ::c_int;
+ pub fn pthread_setname_np(thread: ::pthread_t, name: *const ::c_char) -> ::c_int;
+
+ pub fn sysctl(
+ _: *const ::c_int,
+ _: ::c_uint,
+ _: *mut ::c_void,
+ _: *mut ::size_t,
+ _: *const ::c_void,
+ _: ::size_t,
+ ) -> ::c_int;
+
+ pub fn getrlimit(resource: ::c_int, rlim: *mut ::rlimit) -> ::c_int;
+ pub fn setrlimit(resource: ::c_int, rlp: *const ::rlimit) -> ::c_int;
+
+ pub fn lio_listio(
+ __mode: ::c_int,
+ __list: *const *mut aiocb,
+ __nent: ::c_int,
+ __sig: *mut sigevent,
+ ) -> ::c_int;
+
+ pub fn dl_iterate_phdr(
+ callback: ::Option<
+ unsafe extern "C" fn(
+ info: *const dl_phdr_info,
+ size: ::size_t,
+ data: *mut ::c_void,
+ ) -> ::c_int,
+ >,
+ data: *mut ::c_void,
+ ) -> ::c_int;
+
+ pub fn memset_s(s: *mut ::c_void, smax: ::size_t, c: ::c_int, n: ::size_t) -> ::c_int;
+
+ pub fn regcomp(
+ __preg: *mut ::regex_t,
+ __pattern: *const ::c_char,
+ __cflags: ::c_int,
+ ) -> ::c_int;
+ pub fn regexec(
+ __preg: *const ::regex_t,
+ __str: *const ::c_char,
+ __nmatch: ::size_t,
+ __pmatch: *mut ::regmatch_t,
+ __eflags: ::c_int,
+ ) -> ::c_int;
+ pub fn regerror(
+ __errcode: ::c_int,
+ __preg: *const ::regex_t,
+ __errbuf: *mut ::c_char,
+ __errbuf_size: ::size_t,
+ ) -> ::size_t;
+ pub fn regfree(__preg: *mut ::regex_t);
+ pub fn dirfd(__dirp: *mut ::DIR) -> ::c_int;
+ pub fn dircntl(dir: *mut ::DIR, cmd: ::c_int, ...) -> ::c_int;
+
+ pub fn aio_cancel(__fd: ::c_int, __aiocbp: *mut ::aiocb) -> ::c_int;
+ pub fn aio_error(__aiocbp: *const ::aiocb) -> ::c_int;
+ pub fn aio_fsync(__operation: ::c_int, __aiocbp: *mut ::aiocb) -> ::c_int;
+ pub fn aio_read(__aiocbp: *mut ::aiocb) -> ::c_int;
+ pub fn aio_return(__aiocpb: *mut ::aiocb) -> ::ssize_t;
+ pub fn aio_suspend(
+ __list: *const *const ::aiocb,
+ __nent: ::c_int,
+ __timeout: *const ::timespec,
+ ) -> ::c_int;
+ pub fn aio_write(__aiocpb: *mut ::aiocb) -> ::c_int;
+
+ pub fn mq_close(__mqdes: ::mqd_t) -> ::c_int;
+ pub fn mq_getattr(__mqdes: ::mqd_t, __mqstat: *mut ::mq_attr) -> ::c_int;
+ pub fn mq_notify(__mqdes: ::mqd_t, __notification: *const ::sigevent) -> ::c_int;
+ pub fn mq_open(__name: *const ::c_char, __oflag: ::c_int, ...) -> ::mqd_t;
+ pub fn mq_receive(
+ __mqdes: ::mqd_t,
+ __msg_ptr: *mut ::c_char,
+ __msg_len: ::size_t,
+ __msg_prio: *mut ::c_uint,
+ ) -> ::ssize_t;
+ pub fn mq_send(
+ __mqdes: ::mqd_t,
+ __msg_ptr: *const ::c_char,
+ __msg_len: ::size_t,
+ __msg_prio: ::c_uint,
+ ) -> ::c_int;
+ pub fn mq_setattr(
+ __mqdes: ::mqd_t,
+ __mqstat: *const mq_attr,
+ __omqstat: *mut mq_attr,
+ ) -> ::c_int;
+ pub fn mq_timedreceive(
+ __mqdes: ::mqd_t,
+ __msg_ptr: *mut ::c_char,
+ __msg_len: ::size_t,
+ __msg_prio: *mut ::c_uint,
+ __abs_timeout: *const ::timespec,
+ ) -> ::ssize_t;
+ pub fn mq_timedsend(
+ __mqdes: ::mqd_t,
+ __msg_ptr: *const ::c_char,
+ __msg_len: ::size_t,
+ __msg_prio: ::c_uint,
+ __abs_timeout: *const ::timespec,
+ ) -> ::c_int;
+ pub fn mq_unlink(__name: *const ::c_char) -> ::c_int;
+ pub fn __get_errno_ptr() -> *mut ::c_int;
+
+ // System page, see https://www.qnx.com/developers/docs/7.1#com.qnx.doc.neutrino.building/topic/syspage/syspage_about.html
+ pub static mut _syspage_ptr: *mut syspage_entry;
+
+ // Function on the stack after a call to pthread_create(). This is used
+ // as a sentinel to work around an infitnite loop in the unwinding code.
+ pub fn __my_thread_exit(value_ptr: *mut *const ::c_void);
+}
+
+// Models the implementation in stdlib.h. Ctest will fail if trying to use the
+// default symbol from libc
+pub unsafe fn atexit(cb: extern "C" fn()) -> ::c_int {
+ extern "C" {
+ static __dso_handle: *mut ::c_void;
+ pub fn __cxa_atexit(
+ cb: extern "C" fn(),
+ __arg: *mut ::c_void,
+ __dso: *mut ::c_void,
+ ) -> ::c_int;
+ }
+ __cxa_atexit(cb, 0 as *mut ::c_void, __dso_handle)
+}
+
+impl siginfo_t {
+ pub unsafe fn si_addr(&self) -> *mut ::c_void {
+ #[repr(C)]
+ struct siginfo_si_addr {
+ _pad: [u8; 32],
+ si_addr: *mut ::c_void,
+ }
+ (*(self as *const siginfo_t as *const siginfo_si_addr)).si_addr
+ }
+
+ pub unsafe fn si_value(&self) -> ::sigval {
+ #[repr(C)]
+ struct siginfo_si_value {
+ _pad: [u8; 32],
+ si_value: ::sigval,
+ }
+ (*(self as *const siginfo_t as *const siginfo_si_value)).si_value
+ }
+
+ pub unsafe fn si_pid(&self) -> ::pid_t {
+ #[repr(C)]
+ struct siginfo_si_pid {
+ _pad: [u8; 16],
+ si_pid: ::pid_t,
+ }
+ (*(self as *const siginfo_t as *const siginfo_si_pid)).si_pid
+ }
+
+ pub unsafe fn si_uid(&self) -> ::uid_t {
+ #[repr(C)]
+ struct siginfo_si_uid {
+ _pad: [u8; 24],
+ si_uid: ::uid_t,
+ }
+ (*(self as *const siginfo_t as *const siginfo_si_uid)).si_uid
+ }
+
+ pub unsafe fn si_status(&self) -> ::c_int {
+ #[repr(C)]
+ struct siginfo_si_status {
+ _pad: [u8; 28],
+ si_status: ::c_int,
+ }
+ (*(self as *const siginfo_t as *const siginfo_si_status)).si_status
+ }
+}
+
+cfg_if! {
+ if #[cfg(target_arch = "x86_64")] {
+ mod x86_64;
+ pub use self::x86_64::*;
+ }
+ else if #[cfg(target_arch = "aarch64")] {
+ mod aarch64;
+ pub use self::aarch64::*;
+ }
+ else {
+ panic!("Unsupported arch");
+ }
+}
+
+mod neutrino;
+pub use self::neutrino::*;
diff --git a/vendor/libc/src/unix/nto/neutrino.rs b/vendor/libc/src/unix/nto/neutrino.rs
new file mode 100644
index 000000000..cedd21659
--- /dev/null
+++ b/vendor/libc/src/unix/nto/neutrino.rs
@@ -0,0 +1,1288 @@
+pub type nto_job_t = ::sync_t;
+
+s! {
+ pub struct intrspin {
+ pub value: ::c_uint, // volatile
+ }
+
+ pub struct iov_t {
+ pub iov_base: *mut ::c_void, // union
+ pub iov_len: ::size_t,
+ }
+
+ pub struct _itimer {
+ pub nsec: u64,
+ pub interval_nsec: u64,
+ }
+
+ pub struct _msg_info64 {
+ pub nd: u32,
+ pub srcnd: u32,
+ pub pid: ::pid_t,
+ pub tid: i32,
+ pub chid: i32,
+ pub scoid: i32,
+ pub coid: i32,
+ pub priority: i16,
+ pub flags: i16,
+ pub msglen: isize,
+ pub srcmsglen: isize,
+ pub dstmsglen: isize,
+ pub type_id: u32,
+ reserved: u32,
+ }
+
+ pub struct _cred_info {
+ pub ruid: ::uid_t,
+ pub euid: ::uid_t,
+ pub suid: ::uid_t,
+ pub rgid: ::gid_t,
+ pub egid: ::gid_t,
+ pub sgid: ::gid_t,
+ pub ngroups: u32,
+ pub grouplist: [::gid_t; 8],
+ }
+
+ pub struct _client_info {
+ pub nd: u32,
+ pub pid: ::pid_t,
+ pub sid: ::pid_t,
+ pub flags: u32,
+ pub cred: ::_cred_info,
+ }
+
+ pub struct _client_able {
+ pub ability: u32,
+ pub flags: u32,
+ pub range_lo: u64,
+ pub range_hi: u64,
+ }
+
+ pub struct nto_channel_config {
+ pub event: ::sigevent,
+ pub num_pulses: ::c_uint,
+ pub rearm_threshold: ::c_uint,
+ pub options: ::c_uint,
+ reserved: [::c_uint; 3],
+ }
+
+ // TODO: The following structures are defined in a header file which doesn't
+ // appear as part of the default headers found in a standard installation
+ // of Neutrino 7.1 SDP. Commented out for now.
+ //pub struct _asyncmsg_put_header {
+ // pub err: ::c_int,
+ // pub iov: *mut ::iov_t,
+ // pub parts: ::c_int,
+ // pub handle: ::c_uint,
+ // pub cb: ::Option<
+ // unsafe extern "C" fn(
+ // err: ::c_int,
+ // buf: *mut ::c_void,
+ // handle: ::c_uint,
+ // ) -> ::c_int>,
+ // pub put_hdr_flags: ::c_uint,
+ //}
+
+ //pub struct _asyncmsg_connection_attr {
+ // pub call_back: ::Option<
+ // unsafe extern "C" fn(
+ // err: ::c_int,
+ // buff: *mut ::c_void,
+ // handle: ::c_uint,
+ // ) -> ::c_int>,
+ // pub buffer_size: ::size_t,
+ // pub max_num_buffer: ::c_uint,
+ // pub trigger_num_msg: ::c_uint,
+ // pub trigger_time: ::_itimer,
+ // reserve: ::c_uint,
+ //}
+
+ //pub struct _asyncmsg_connection_descriptor {
+ // pub flags: ::c_uint,
+ // pub sendq_size: ::c_uint,
+ // pub sendq_head: ::c_uint,
+ // pub sendq_tail: ::c_uint,
+ // pub sendq_free: ::c_uint,
+ // pub err: ::c_int,
+ // pub ev: ::sigevent,
+ // pub num_curmsg: ::c_uint,
+ // pub ttimer: ::timer_t,
+ // pub block_con: ::pthread_cond_t,
+ // pub mu: ::pthread_mutex_t,
+ // reserved: ::c_uint,
+ // pub attr: ::_asyncmsg_connection_attr,
+ // pub reserves: [::c_uint; 3],
+ // pub sendq: [::_asyncmsg_put_header; 1], // flexarray
+ //}
+
+ pub struct __c_anonymous_struct_ev {
+ pub event: ::sigevent,
+ pub coid: ::c_int,
+ }
+
+ pub struct _channel_connect_attr { // union
+ pub ev: ::__c_anonymous_struct_ev,
+ }
+
+ pub struct _sighandler_info {
+ pub siginfo: ::siginfo_t,
+ pub handler: ::Option<unsafe extern "C" fn(value: ::c_int)>,
+ pub context: *mut ::c_void,
+ }
+
+ pub struct __c_anonymous_struct_time {
+ pub length: ::c_uint,
+ pub scale: ::c_uint,
+ }
+
+ pub struct _idle_hook {
+ pub hook_size: ::c_uint,
+ pub cmd: ::c_uint,
+ pub mode: ::c_uint,
+ pub latency: ::c_uint,
+ pub next_fire: u64,
+ pub curr_time: u64,
+ pub tod_adjust: u64,
+ pub resp: ::c_uint,
+ pub time: __c_anonymous_struct_time,
+ pub trigger: ::sigevent,
+ pub intrs: *mut ::c_uint,
+ pub block_stack_size: ::c_uint,
+ }
+
+ pub struct _clockadjust {
+ pub tick_count: u32,
+ pub tick_nsec_inc: i32,
+ }
+
+ pub struct qtime_entry {
+ pub cycles_per_sec: u64,
+ pub nsec_tod_adjust: u64, // volatile
+ pub nsec: u64, // volatile
+ pub nsec_inc: u32,
+ pub boot_time: u32,
+ pub adjust: _clockadjust,
+ pub timer_rate: u32,
+ pub timer_scale: i32,
+ pub timer_load: u32,
+ pub intr: i32,
+ pub epoch: u32,
+ pub flags: u32,
+ pub rr_interval_mul: u32,
+ pub timer_load_hi: u32,
+ pub nsec_stable: u64, // volatile
+ pub timer_load_max: u64,
+ pub timer_prog_time: u32,
+ spare: [u32; 7],
+ }
+
+ pub struct _sched_info {
+ pub priority_min: ::c_int,
+ pub priority_max: ::c_int,
+ pub interval: u64,
+ pub priority_priv: ::c_int,
+ reserved: [::c_int; 11],
+ }
+
+ pub struct _timer_info {
+ pub itime: ::_itimer,
+ pub otime: ::_itimer,
+ pub flags: u32,
+ pub tid: i32,
+ pub notify: i32,
+ pub clockid: ::clockid_t,
+ pub overruns: u32,
+ pub event: ::sigevent, // union
+ }
+
+ pub struct _clockperiod {
+ pub nsec: u32,
+ pub fract: i32,
+ }
+}
+
+s_no_extra_traits! {
+ pub struct syspage_entry_info {
+ pub entry_off: u16,
+ pub entry_size: u16,
+ }
+
+ pub struct syspage_array_info {
+ entry_off: u16,
+ entry_size: u16,
+ element_size: u16,
+ }
+
+ #[repr(align(8))]
+ pub struct syspage_entry {
+ pub size: u16,
+ pub total_size: u16,
+ pub type_: u16,
+ pub num_cpu: u16,
+ pub system_private: syspage_entry_info,
+ pub old_asinfo: syspage_entry_info,
+ pub __mangle_name_to_cause_compilation_errs_meminfo: syspage_entry_info,
+ pub hwinfo: syspage_entry_info,
+ pub old_cpuinfo: syspage_entry_info,
+ pub old_cacheattr: syspage_entry_info,
+ pub qtime: syspage_entry_info,
+ pub callout: syspage_entry_info,
+ pub callin: syspage_entry_info,
+ pub typed_strings: syspage_entry_info,
+ pub strings: syspage_entry_info,
+ pub old_intrinfo: syspage_entry_info,
+ pub smp: syspage_entry_info,
+ pub pminfo: syspage_entry_info,
+ pub old_mdriver: syspage_entry_info,
+ spare0: [u32; 1],
+ __reserved: [u8; 160], // anonymous union with architecture dependent structs
+ pub new_asinfo: syspage_array_info,
+ pub new_cpuinfo: syspage_array_info,
+ pub new_cacheattr: syspage_array_info,
+ pub new_intrinfo: syspage_array_info,
+ pub new_mdriver: syspage_array_info,
+ }
+}
+
+pub const SYSMGR_PID: u32 = 1;
+pub const SYSMGR_CHID: u32 = 1;
+pub const SYSMGR_COID: u32 = _NTO_SIDE_CHANNEL;
+pub const SYSMGR_HANDLE: u32 = 0;
+
+pub const STATE_DEAD: ::c_int = 0x00;
+pub const STATE_RUNNING: ::c_int = 0x01;
+pub const STATE_READY: ::c_int = 0x02;
+pub const STATE_STOPPED: ::c_int = 0x03;
+pub const STATE_SEND: ::c_int = 0x04;
+pub const STATE_RECEIVE: ::c_int = 0x05;
+pub const STATE_REPLY: ::c_int = 0x06;
+pub const STATE_STACK: ::c_int = 0x07;
+pub const STATE_WAITTHREAD: ::c_int = 0x08;
+pub const STATE_WAITPAGE: ::c_int = 0x09;
+pub const STATE_SIGSUSPEND: ::c_int = 0x0a;
+pub const STATE_SIGWAITINFO: ::c_int = 0x0b;
+pub const STATE_NANOSLEEP: ::c_int = 0x0c;
+pub const STATE_MUTEX: ::c_int = 0x0d;
+pub const STATE_CONDVAR: ::c_int = 0x0e;
+pub const STATE_JOIN: ::c_int = 0x0f;
+pub const STATE_INTR: ::c_int = 0x10;
+pub const STATE_SEM: ::c_int = 0x11;
+pub const STATE_WAITCTX: ::c_int = 0x12;
+pub const STATE_NET_SEND: ::c_int = 0x13;
+pub const STATE_NET_REPLY: ::c_int = 0x14;
+pub const STATE_MAX: ::c_int = 0x18;
+
+pub const _NTO_TIMEOUT_RECEIVE: i32 = 1 << STATE_RECEIVE;
+pub const _NTO_TIMEOUT_SEND: i32 = 1 << STATE_SEND;
+pub const _NTO_TIMEOUT_REPLY: i32 = 1 << STATE_REPLY;
+pub const _NTO_TIMEOUT_SIGSUSPEND: i32 = 1 << STATE_SIGSUSPEND;
+pub const _NTO_TIMEOUT_SIGWAITINFO: i32 = 1 << STATE_SIGWAITINFO;
+pub const _NTO_TIMEOUT_NANOSLEEP: i32 = 1 << STATE_NANOSLEEP;
+pub const _NTO_TIMEOUT_MUTEX: i32 = 1 << STATE_MUTEX;
+pub const _NTO_TIMEOUT_CONDVAR: i32 = 1 << STATE_CONDVAR;
+pub const _NTO_TIMEOUT_JOIN: i32 = 1 << STATE_JOIN;
+pub const _NTO_TIMEOUT_INTR: i32 = 1 << STATE_INTR;
+pub const _NTO_TIMEOUT_SEM: i32 = 1 << STATE_SEM;
+
+pub const _NTO_MI_ENDIAN_BIG: u32 = 1;
+pub const _NTO_MI_ENDIAN_DIFF: u32 = 2;
+pub const _NTO_MI_UNBLOCK_REQ: u32 = 256;
+pub const _NTO_MI_NET_CRED_DIRTY: u32 = 512;
+pub const _NTO_MI_CONSTRAINED: u32 = 1024;
+pub const _NTO_MI_CHROOT: u32 = 2048;
+pub const _NTO_MI_BITS_64: u32 = 4096;
+pub const _NTO_MI_BITS_DIFF: u32 = 8192;
+pub const _NTO_MI_SANDBOX: u32 = 16384;
+
+pub const _NTO_CI_ENDIAN_BIG: u32 = 1;
+pub const _NTO_CI_BKGND_PGRP: u32 = 4;
+pub const _NTO_CI_ORPHAN_PGRP: u32 = 8;
+pub const _NTO_CI_STOPPED: u32 = 128;
+pub const _NTO_CI_UNABLE: u32 = 256;
+pub const _NTO_CI_TYPE_ID: u32 = 512;
+pub const _NTO_CI_CHROOT: u32 = 2048;
+pub const _NTO_CI_BITS_64: u32 = 4096;
+pub const _NTO_CI_SANDBOX: u32 = 16384;
+pub const _NTO_CI_LOADER: u32 = 32768;
+pub const _NTO_CI_FULL_GROUPS: u32 = 2147483648;
+
+pub const _NTO_TI_ACTIVE: u32 = 1;
+pub const _NTO_TI_ABSOLUTE: u32 = 2;
+pub const _NTO_TI_EXPIRED: u32 = 4;
+pub const _NTO_TI_TOD_BASED: u32 = 8;
+pub const _NTO_TI_TARGET_PROCESS: u32 = 16;
+pub const _NTO_TI_REPORT_TOLERANCE: u32 = 32;
+pub const _NTO_TI_PRECISE: u32 = 64;
+pub const _NTO_TI_TOLERANT: u32 = 128;
+pub const _NTO_TI_WAKEUP: u32 = 256;
+pub const _NTO_TI_PROCESS_TOLERANT: u32 = 512;
+pub const _NTO_TI_HIGH_RESOLUTION: u32 = 1024;
+
+pub const _PULSE_TYPE: u32 = 0;
+pub const _PULSE_SUBTYPE: u32 = 0;
+pub const _PULSE_CODE_UNBLOCK: i32 = -32;
+pub const _PULSE_CODE_DISCONNECT: i32 = -33;
+pub const _PULSE_CODE_THREADDEATH: i32 = -34;
+pub const _PULSE_CODE_COIDDEATH: i32 = -35;
+pub const _PULSE_CODE_NET_ACK: i32 = -36;
+pub const _PULSE_CODE_NET_UNBLOCK: i32 = -37;
+pub const _PULSE_CODE_NET_DETACH: i32 = -38;
+pub const _PULSE_CODE_RESTART: i32 = -39;
+pub const _PULSE_CODE_NORESTART: i32 = -40;
+pub const _PULSE_CODE_UNBLOCK_RESTART: i32 = -41;
+pub const _PULSE_CODE_UNBLOCK_TIMER: i32 = -42;
+pub const _PULSE_CODE_MINAVAIL: u32 = 0;
+pub const _PULSE_CODE_MAXAVAIL: u32 = 127;
+
+pub const _NTO_HARD_FLAGS_END: u32 = 1;
+
+pub const _NTO_PULSE_IF_UNIQUE: u32 = 4096;
+pub const _NTO_PULSE_REPLACE: u32 = 8192;
+
+pub const _NTO_PF_NOCLDSTOP: u32 = 1;
+pub const _NTO_PF_LOADING: u32 = 2;
+pub const _NTO_PF_TERMING: u32 = 4;
+pub const _NTO_PF_ZOMBIE: u32 = 8;
+pub const _NTO_PF_NOZOMBIE: u32 = 16;
+pub const _NTO_PF_FORKED: u32 = 32;
+pub const _NTO_PF_ORPHAN_PGRP: u32 = 64;
+pub const _NTO_PF_STOPPED: u32 = 128;
+pub const _NTO_PF_DEBUG_STOPPED: u32 = 256;
+pub const _NTO_PF_BKGND_PGRP: u32 = 512;
+pub const _NTO_PF_NOISYNC: u32 = 1024;
+pub const _NTO_PF_CONTINUED: u32 = 2048;
+pub const _NTO_PF_CHECK_INTR: u32 = 4096;
+pub const _NTO_PF_COREDUMP: u32 = 8192;
+pub const _NTO_PF_RING0: u32 = 32768;
+pub const _NTO_PF_SLEADER: u32 = 65536;
+pub const _NTO_PF_WAITINFO: u32 = 131072;
+pub const _NTO_PF_DESTROYALL: u32 = 524288;
+pub const _NTO_PF_NOCOREDUMP: u32 = 1048576;
+pub const _NTO_PF_WAITDONE: u32 = 4194304;
+pub const _NTO_PF_TERM_WAITING: u32 = 8388608;
+pub const _NTO_PF_ASLR: u32 = 16777216;
+pub const _NTO_PF_EXECED: u32 = 33554432;
+pub const _NTO_PF_APP_STOPPED: u32 = 67108864;
+pub const _NTO_PF_64BIT: u32 = 134217728;
+pub const _NTO_PF_NET: u32 = 268435456;
+pub const _NTO_PF_NOLAZYSTACK: u32 = 536870912;
+pub const _NTO_PF_NOEXEC_STACK: u32 = 1073741824;
+pub const _NTO_PF_LOADER_PERMS: u32 = 2147483648;
+
+pub const _NTO_TF_INTR_PENDING: u32 = 65536;
+pub const _NTO_TF_DETACHED: u32 = 131072;
+pub const _NTO_TF_SHR_MUTEX: u32 = 262144;
+pub const _NTO_TF_SHR_MUTEX_EUID: u32 = 524288;
+pub const _NTO_TF_THREADS_HOLD: u32 = 1048576;
+pub const _NTO_TF_UNBLOCK_REQ: u32 = 4194304;
+pub const _NTO_TF_ALIGN_FAULT: u32 = 16777216;
+pub const _NTO_TF_SSTEP: u32 = 33554432;
+pub const _NTO_TF_ALLOCED_STACK: u32 = 67108864;
+pub const _NTO_TF_NOMULTISIG: u32 = 134217728;
+pub const _NTO_TF_LOW_LATENCY: u32 = 268435456;
+pub const _NTO_TF_IOPRIV: u32 = 2147483648;
+
+pub const _NTO_TCTL_IO_PRIV: u32 = 1;
+pub const _NTO_TCTL_THREADS_HOLD: u32 = 2;
+pub const _NTO_TCTL_THREADS_CONT: u32 = 3;
+pub const _NTO_TCTL_RUNMASK: u32 = 4;
+pub const _NTO_TCTL_ALIGN_FAULT: u32 = 5;
+pub const _NTO_TCTL_RUNMASK_GET_AND_SET: u32 = 6;
+pub const _NTO_TCTL_PERFCOUNT: u32 = 7;
+pub const _NTO_TCTL_ONE_THREAD_HOLD: u32 = 8;
+pub const _NTO_TCTL_ONE_THREAD_CONT: u32 = 9;
+pub const _NTO_TCTL_RUNMASK_GET_AND_SET_INHERIT: u32 = 10;
+pub const _NTO_TCTL_NAME: u32 = 11;
+pub const _NTO_TCTL_RCM_GET_AND_SET: u32 = 12;
+pub const _NTO_TCTL_SHR_MUTEX: u32 = 13;
+pub const _NTO_TCTL_IO: u32 = 14;
+pub const _NTO_TCTL_NET_KIF_GET_AND_SET: u32 = 15;
+pub const _NTO_TCTL_LOW_LATENCY: u32 = 16;
+pub const _NTO_TCTL_ADD_EXIT_EVENT: u32 = 17;
+pub const _NTO_TCTL_DEL_EXIT_EVENT: u32 = 18;
+pub const _NTO_TCTL_IO_LEVEL: u32 = 19;
+pub const _NTO_TCTL_RESERVED: u32 = 2147483648;
+pub const _NTO_TCTL_IO_LEVEL_INHERIT: u32 = 1073741824;
+pub const _NTO_IO_LEVEL_NONE: u32 = 1;
+pub const _NTO_IO_LEVEL_1: u32 = 2;
+pub const _NTO_IO_LEVEL_2: u32 = 3;
+
+pub const _NTO_THREAD_NAME_MAX: u32 = 100;
+
+pub const _NTO_CHF_FIXED_PRIORITY: u32 = 1;
+pub const _NTO_CHF_UNBLOCK: u32 = 2;
+pub const _NTO_CHF_THREAD_DEATH: u32 = 4;
+pub const _NTO_CHF_DISCONNECT: u32 = 8;
+pub const _NTO_CHF_NET_MSG: u32 = 16;
+pub const _NTO_CHF_SENDER_LEN: u32 = 32;
+pub const _NTO_CHF_COID_DISCONNECT: u32 = 64;
+pub const _NTO_CHF_REPLY_LEN: u32 = 128;
+pub const _NTO_CHF_PULSE_POOL: u32 = 256;
+pub const _NTO_CHF_ASYNC_NONBLOCK: u32 = 512;
+pub const _NTO_CHF_ASYNC: u32 = 1024;
+pub const _NTO_CHF_GLOBAL: u32 = 2048;
+pub const _NTO_CHF_PRIVATE: u32 = 4096;
+pub const _NTO_CHF_MSG_PAUSING: u32 = 8192;
+pub const _NTO_CHF_INHERIT_RUNMASK: u32 = 16384;
+pub const _NTO_CHF_UNBLOCK_TIMER: u32 = 32768;
+
+pub const _NTO_CHO_CUSTOM_EVENT: u32 = 1;
+
+pub const _NTO_COF_CLOEXEC: u32 = 1;
+pub const _NTO_COF_DEAD: u32 = 2;
+pub const _NTO_COF_NOSHARE: u32 = 64;
+pub const _NTO_COF_NETCON: u32 = 128;
+pub const _NTO_COF_NONBLOCK: u32 = 256;
+pub const _NTO_COF_ASYNC: u32 = 512;
+pub const _NTO_COF_GLOBAL: u32 = 1024;
+pub const _NTO_COF_NOEVENT: u32 = 2048;
+pub const _NTO_COF_INSECURE: u32 = 4096;
+pub const _NTO_COF_REG_EVENTS: u32 = 8192;
+pub const _NTO_COF_UNREG_EVENTS: u32 = 16384;
+pub const _NTO_COF_MASK: u32 = 65535;
+
+pub const _NTO_SIDE_CHANNEL: u32 = 1073741824;
+
+pub const _NTO_CONNECTION_SCOID: u32 = 65536;
+pub const _NTO_GLOBAL_CHANNEL: u32 = 1073741824;
+
+pub const _NTO_TIMEOUT_MASK: u32 = (1 << STATE_MAX) - 1;
+pub const _NTO_TIMEOUT_ACTIVE: u32 = 1 << STATE_MAX;
+pub const _NTO_TIMEOUT_IMMEDIATE: u32 = 1 << (STATE_MAX + 1);
+
+pub const _NTO_IC_LATENCY: u32 = 0;
+
+pub const _NTO_INTR_FLAGS_END: u32 = 1;
+pub const _NTO_INTR_FLAGS_NO_UNMASK: u32 = 2;
+pub const _NTO_INTR_FLAGS_PROCESS: u32 = 4;
+pub const _NTO_INTR_FLAGS_TRK_MSK: u32 = 8;
+pub const _NTO_INTR_FLAGS_ARRAY: u32 = 16;
+pub const _NTO_INTR_FLAGS_EXCLUSIVE: u32 = 32;
+pub const _NTO_INTR_FLAGS_FPU: u32 = 64;
+
+pub const _NTO_INTR_CLASS_EXTERNAL: u32 = 0;
+pub const _NTO_INTR_CLASS_SYNTHETIC: u32 = 2147418112;
+
+pub const _NTO_INTR_SPARE: u32 = 2147483647;
+
+pub const _NTO_HOOK_IDLE: u32 = 2147418113;
+pub const _NTO_HOOK_OVERDRIVE: u32 = 2147418114;
+pub const _NTO_HOOK_LAST: u32 = 2147418114;
+pub const _NTO_HOOK_IDLE2_FLAG: u32 = 32768;
+
+pub const _NTO_IH_CMD_SLEEP_SETUP: u32 = 1;
+pub const _NTO_IH_CMD_SLEEP_BLOCK: u32 = 2;
+pub const _NTO_IH_CMD_SLEEP_WAKEUP: u32 = 4;
+pub const _NTO_IH_CMD_SLEEP_ONLINE: u32 = 8;
+pub const _NTO_IH_RESP_NEEDS_BLOCK: u32 = 1;
+pub const _NTO_IH_RESP_NEEDS_WAKEUP: u32 = 2;
+pub const _NTO_IH_RESP_NEEDS_ONLINE: u32 = 4;
+pub const _NTO_IH_RESP_SYNC_TIME: u32 = 16;
+pub const _NTO_IH_RESP_SYNC_TLB: u32 = 32;
+pub const _NTO_IH_RESP_SUGGEST_OFFLINE: u32 = 256;
+pub const _NTO_IH_RESP_SLEEP_MODE_REACHED: u32 = 512;
+pub const _NTO_IH_RESP_DELIVER_INTRS: u32 = 1024;
+
+pub const _NTO_READIOV_SEND: u32 = 0;
+pub const _NTO_READIOV_REPLY: u32 = 1;
+
+pub const _NTO_KEYDATA_VTID: u32 = 2147483648;
+
+pub const _NTO_KEYDATA_PATHSIGN: u32 = 32768;
+pub const _NTO_KEYDATA_OP_MASK: u32 = 255;
+pub const _NTO_KEYDATA_VERIFY: u32 = 0;
+pub const _NTO_KEYDATA_CALCULATE: u32 = 1;
+pub const _NTO_KEYDATA_CALCULATE_REUSE: u32 = 2;
+pub const _NTO_KEYDATA_PATHSIGN_VERIFY: u32 = 32768;
+pub const _NTO_KEYDATA_PATHSIGN_CALCULATE: u32 = 32769;
+pub const _NTO_KEYDATA_PATHSIGN_CALCULATE_REUSE: u32 = 32770;
+
+pub const _NTO_SCTL_SETPRIOCEILING: u32 = 1;
+pub const _NTO_SCTL_GETPRIOCEILING: u32 = 2;
+pub const _NTO_SCTL_SETEVENT: u32 = 3;
+pub const _NTO_SCTL_MUTEX_WAKEUP: u32 = 4;
+pub const _NTO_SCTL_MUTEX_CONSISTENT: u32 = 5;
+pub const _NTO_SCTL_SEM_VALUE: u32 = 6;
+
+pub const _NTO_CLIENTINFO_GETGROUPS: u32 = 1;
+pub const _NTO_CLIENTINFO_GETTYPEID: u32 = 2;
+
+extern "C" {
+ pub fn ChannelCreate(__flags: ::c_uint) -> ::c_int;
+ pub fn ChannelCreate_r(__flags: ::c_uint) -> ::c_int;
+ pub fn ChannelCreatePulsePool(
+ __flags: ::c_uint,
+ __config: *const nto_channel_config,
+ ) -> ::c_int;
+ pub fn ChannelCreateExt(
+ __flags: ::c_uint,
+ __mode: ::mode_t,
+ __bufsize: usize,
+ __maxnumbuf: ::c_uint,
+ __ev: *const ::sigevent,
+ __cred: *mut _cred_info,
+ ) -> ::c_int;
+ pub fn ChannelDestroy(__chid: ::c_int) -> ::c_int;
+ pub fn ChannelDestroy_r(__chid: ::c_int) -> ::c_int;
+ pub fn ConnectAttach(
+ __nd: u32,
+ __pid: ::pid_t,
+ __chid: ::c_int,
+ __index: ::c_uint,
+ __flags: ::c_int,
+ ) -> ::c_int;
+ pub fn ConnectAttach_r(
+ __nd: u32,
+ __pid: ::pid_t,
+ __chid: ::c_int,
+ __index: ::c_uint,
+ __flags: ::c_int,
+ ) -> ::c_int;
+
+ // TODO: The following function uses a structure defined in a header file
+ // which doesn't appear as part of the default headers found in a
+ // standard installation of Neutrino 7.1 SDP. Commented out for now.
+ //pub fn ConnectAttachExt(
+ // __nd: u32,
+ // __pid: ::pid_t,
+ // __chid: ::c_int,
+ // __index: ::c_uint,
+ // __flags: ::c_int,
+ // __cd: *mut _asyncmsg_connection_descriptor,
+ //) -> ::c_int;
+ pub fn ConnectDetach(__coid: ::c_int) -> ::c_int;
+ pub fn ConnectDetach_r(__coid: ::c_int) -> ::c_int;
+ pub fn ConnectServerInfo(__pid: ::pid_t, __coid: ::c_int, __info: *mut _msg_info64) -> ::c_int;
+ pub fn ConnectServerInfo_r(
+ __pid: ::pid_t,
+ __coid: ::c_int,
+ __info: *mut _msg_info64,
+ ) -> ::c_int;
+ pub fn ConnectClientInfoExtraArgs(
+ __scoid: ::c_int,
+ __info_pp: *mut _client_info,
+ __ngroups: ::c_int,
+ __abilities: *mut _client_able,
+ __nable: ::c_int,
+ __type_id: *mut ::c_uint,
+ ) -> ::c_int;
+ pub fn ConnectClientInfoExtraArgs_r(
+ __scoid: ::c_int,
+ __info_pp: *mut _client_info,
+ __ngroups: ::c_int,
+ __abilities: *mut _client_able,
+ __nable: ::c_int,
+ __type_id: *mut ::c_uint,
+ ) -> ::c_int;
+ pub fn ConnectClientInfo(
+ __scoid: ::c_int,
+ __info: *mut _client_info,
+ __ngroups: ::c_int,
+ ) -> ::c_int;
+ pub fn ConnectClientInfo_r(
+ __scoid: ::c_int,
+ __info: *mut _client_info,
+ __ngroups: ::c_int,
+ ) -> ::c_int;
+ pub fn ConnectClientInfoExt(
+ __scoid: ::c_int,
+ __info_pp: *mut *mut _client_info,
+ flags: ::c_int,
+ ) -> ::c_int;
+ pub fn ClientInfoExtFree(__info_pp: *mut *mut _client_info) -> ::c_int;
+ pub fn ConnectClientInfoAble(
+ __scoid: ::c_int,
+ __info_pp: *mut *mut _client_info,
+ flags: ::c_int,
+ abilities: *mut _client_able,
+ nable: ::c_int,
+ ) -> ::c_int;
+ pub fn ConnectFlags(
+ __pid: ::pid_t,
+ __coid: ::c_int,
+ __mask: ::c_uint,
+ __bits: ::c_uint,
+ ) -> ::c_int;
+ pub fn ConnectFlags_r(
+ __pid: ::pid_t,
+ __coid: ::c_int,
+ __mask: ::c_uint,
+ __bits: ::c_uint,
+ ) -> ::c_int;
+ pub fn ChannelConnectAttr(
+ __id: ::c_uint,
+ __old_attr: *mut _channel_connect_attr,
+ __new_attr: *mut _channel_connect_attr,
+ __flags: ::c_uint,
+ ) -> ::c_int;
+ pub fn MsgSend(
+ __coid: ::c_int,
+ __smsg: *const ::c_void,
+ __sbytes: usize,
+ __rmsg: *mut ::c_void,
+ __rbytes: usize,
+ ) -> ::c_long;
+ pub fn MsgSend_r(
+ __coid: ::c_int,
+ __smsg: *const ::c_void,
+ __sbytes: usize,
+ __rmsg: *mut ::c_void,
+ __rbytes: usize,
+ ) -> ::c_long;
+ pub fn MsgSendnc(
+ __coid: ::c_int,
+ __smsg: *const ::c_void,
+ __sbytes: usize,
+ __rmsg: *mut ::c_void,
+ __rbytes: usize,
+ ) -> ::c_long;
+ pub fn MsgSendnc_r(
+ __coid: ::c_int,
+ __smsg: *const ::c_void,
+ __sbytes: usize,
+ __rmsg: *mut ::c_void,
+ __rbytes: usize,
+ ) -> ::c_long;
+ pub fn MsgSendsv(
+ __coid: ::c_int,
+ __smsg: *const ::c_void,
+ __sbytes: usize,
+ __riov: *const ::iovec,
+ __rparts: usize,
+ ) -> ::c_long;
+ pub fn MsgSendsv_r(
+ __coid: ::c_int,
+ __smsg: *const ::c_void,
+ __sbytes: usize,
+ __riov: *const ::iovec,
+ __rparts: usize,
+ ) -> ::c_long;
+ pub fn MsgSendsvnc(
+ __coid: ::c_int,
+ __smsg: *const ::c_void,
+ __sbytes: usize,
+ __riov: *const ::iovec,
+ __rparts: usize,
+ ) -> ::c_long;
+ pub fn MsgSendsvnc_r(
+ __coid: ::c_int,
+ __smsg: *const ::c_void,
+ __sbytes: usize,
+ __riov: *const ::iovec,
+ __rparts: usize,
+ ) -> ::c_long;
+ pub fn MsgSendvs(
+ __coid: ::c_int,
+ __siov: *const ::iovec,
+ __sparts: usize,
+ __rmsg: *mut ::c_void,
+ __rbytes: usize,
+ ) -> ::c_long;
+ pub fn MsgSendvs_r(
+ __coid: ::c_int,
+ __siov: *const ::iovec,
+ __sparts: usize,
+ __rmsg: *mut ::c_void,
+ __rbytes: usize,
+ ) -> ::c_long;
+ pub fn MsgSendvsnc(
+ __coid: ::c_int,
+ __siov: *const ::iovec,
+ __sparts: usize,
+ __rmsg: *mut ::c_void,
+ __rbytes: usize,
+ ) -> ::c_long;
+ pub fn MsgSendvsnc_r(
+ __coid: ::c_int,
+ __siov: *const ::iovec,
+ __sparts: usize,
+ __rmsg: *mut ::c_void,
+ __rbytes: usize,
+ ) -> ::c_long;
+ pub fn MsgSendv(
+ __coid: ::c_int,
+ __siov: *const ::iovec,
+ __sparts: usize,
+ __riov: *const ::iovec,
+ __rparts: usize,
+ ) -> ::c_long;
+ pub fn MsgSendv_r(
+ __coid: ::c_int,
+ __siov: *const ::iovec,
+ __sparts: usize,
+ __riov: *const ::iovec,
+ __rparts: usize,
+ ) -> ::c_long;
+ pub fn MsgSendvnc(
+ __coid: ::c_int,
+ __siov: *const ::iovec,
+ __sparts: usize,
+ __riov: *const ::iovec,
+ __rparts: usize,
+ ) -> ::c_long;
+ pub fn MsgSendvnc_r(
+ __coid: ::c_int,
+ __siov: *const ::iovec,
+ __sparts: usize,
+ __riov: *const ::iovec,
+ __rparts: usize,
+ ) -> ::c_long;
+ pub fn MsgReceive(
+ __chid: ::c_int,
+ __msg: *mut ::c_void,
+ __bytes: usize,
+ __info: *mut _msg_info64,
+ ) -> ::c_int;
+ pub fn MsgReceive_r(
+ __chid: ::c_int,
+ __msg: *mut ::c_void,
+ __bytes: usize,
+ __info: *mut _msg_info64,
+ ) -> ::c_int;
+ pub fn MsgReceivev(
+ __chid: ::c_int,
+ __iov: *const ::iovec,
+ __parts: usize,
+ __info: *mut _msg_info64,
+ ) -> ::c_int;
+ pub fn MsgReceivev_r(
+ __chid: ::c_int,
+ __iov: *const ::iovec,
+ __parts: usize,
+ __info: *mut _msg_info64,
+ ) -> ::c_int;
+ pub fn MsgReceivePulse(
+ __chid: ::c_int,
+ __pulse: *mut ::c_void,
+ __bytes: usize,
+ __info: *mut _msg_info64,
+ ) -> ::c_int;
+ pub fn MsgReceivePulse_r(
+ __chid: ::c_int,
+ __pulse: *mut ::c_void,
+ __bytes: usize,
+ __info: *mut _msg_info64,
+ ) -> ::c_int;
+ pub fn MsgReceivePulsev(
+ __chid: ::c_int,
+ __iov: *const ::iovec,
+ __parts: usize,
+ __info: *mut _msg_info64,
+ ) -> ::c_int;
+ pub fn MsgReceivePulsev_r(
+ __chid: ::c_int,
+ __iov: *const ::iovec,
+ __parts: usize,
+ __info: *mut _msg_info64,
+ ) -> ::c_int;
+ pub fn MsgReply(
+ __rcvid: ::c_int,
+ __status: ::c_long,
+ __msg: *const ::c_void,
+ __bytes: usize,
+ ) -> ::c_int;
+ pub fn MsgReply_r(
+ __rcvid: ::c_int,
+ __status: ::c_long,
+ __msg: *const ::c_void,
+ __bytes: usize,
+ ) -> ::c_int;
+ pub fn MsgReplyv(
+ __rcvid: ::c_int,
+ __status: ::c_long,
+ __iov: *const ::iovec,
+ __parts: usize,
+ ) -> ::c_int;
+ pub fn MsgReplyv_r(
+ __rcvid: ::c_int,
+ __status: ::c_long,
+ __iov: *const ::iovec,
+ __parts: usize,
+ ) -> ::c_int;
+ pub fn MsgReadiov(
+ __rcvid: ::c_int,
+ __iov: *const ::iovec,
+ __parts: usize,
+ __offset: usize,
+ __flags: ::c_int,
+ ) -> isize;
+ pub fn MsgReadiov_r(
+ __rcvid: ::c_int,
+ __iov: *const ::iovec,
+ __parts: usize,
+ __offset: usize,
+ __flags: ::c_int,
+ ) -> isize;
+ pub fn MsgRead(
+ __rcvid: ::c_int,
+ __msg: *mut ::c_void,
+ __bytes: usize,
+ __offset: usize,
+ ) -> isize;
+ pub fn MsgRead_r(
+ __rcvid: ::c_int,
+ __msg: *mut ::c_void,
+ __bytes: usize,
+ __offset: usize,
+ ) -> isize;
+ pub fn MsgReadv(
+ __rcvid: ::c_int,
+ __iov: *const ::iovec,
+ __parts: usize,
+ __offset: usize,
+ ) -> isize;
+ pub fn MsgReadv_r(
+ __rcvid: ::c_int,
+ __iov: *const ::iovec,
+ __parts: usize,
+ __offset: usize,
+ ) -> isize;
+ pub fn MsgWrite(
+ __rcvid: ::c_int,
+ __msg: *const ::c_void,
+ __bytes: usize,
+ __offset: usize,
+ ) -> isize;
+ pub fn MsgWrite_r(
+ __rcvid: ::c_int,
+ __msg: *const ::c_void,
+ __bytes: usize,
+ __offset: usize,
+ ) -> isize;
+ pub fn MsgWritev(
+ __rcvid: ::c_int,
+ __iov: *const ::iovec,
+ __parts: usize,
+ __offset: usize,
+ ) -> isize;
+ pub fn MsgWritev_r(
+ __rcvid: ::c_int,
+ __iov: *const ::iovec,
+ __parts: usize,
+ __offset: usize,
+ ) -> isize;
+ pub fn MsgSendPulse(
+ __coid: ::c_int,
+ __priority: ::c_int,
+ __code: ::c_int,
+ __value: ::c_int,
+ ) -> ::c_int;
+ pub fn MsgSendPulse_r(
+ __coid: ::c_int,
+ __priority: ::c_int,
+ __code: ::c_int,
+ __value: ::c_int,
+ ) -> ::c_int;
+ pub fn MsgSendPulsePtr(
+ __coid: ::c_int,
+ __priority: ::c_int,
+ __code: ::c_int,
+ __value: *mut ::c_void,
+ ) -> ::c_int;
+ pub fn MsgSendPulsePtr_r(
+ __coid: ::c_int,
+ __priority: ::c_int,
+ __code: ::c_int,
+ __value: *mut ::c_void,
+ ) -> ::c_int;
+ pub fn MsgDeliverEvent(__rcvid: ::c_int, __event: *const ::sigevent) -> ::c_int;
+ pub fn MsgDeliverEvent_r(__rcvid: ::c_int, __event: *const ::sigevent) -> ::c_int;
+ pub fn MsgVerifyEvent(__rcvid: ::c_int, __event: *const ::sigevent) -> ::c_int;
+ pub fn MsgVerifyEvent_r(__rcvid: ::c_int, __event: *const ::sigevent) -> ::c_int;
+ pub fn MsgRegisterEvent(__event: *mut ::sigevent, __coid: ::c_int) -> ::c_int;
+ pub fn MsgRegisterEvent_r(__event: *mut ::sigevent, __coid: ::c_int) -> ::c_int;
+ pub fn MsgUnregisterEvent(__event: *const ::sigevent) -> ::c_int;
+ pub fn MsgUnregisterEvent_r(__event: *const ::sigevent) -> ::c_int;
+ pub fn MsgInfo(__rcvid: ::c_int, __info: *mut _msg_info64) -> ::c_int;
+ pub fn MsgInfo_r(__rcvid: ::c_int, __info: *mut _msg_info64) -> ::c_int;
+ pub fn MsgKeyData(
+ __rcvid: ::c_int,
+ __oper: ::c_int,
+ __key: u32,
+ __newkey: *mut u32,
+ __iov: *const ::iovec,
+ __parts: ::c_int,
+ ) -> ::c_int;
+ pub fn MsgKeyData_r(
+ __rcvid: ::c_int,
+ __oper: ::c_int,
+ __key: u32,
+ __newkey: *mut u32,
+ __iov: *const ::iovec,
+ __parts: ::c_int,
+ ) -> ::c_int;
+ pub fn MsgError(__rcvid: ::c_int, __err: ::c_int) -> ::c_int;
+ pub fn MsgError_r(__rcvid: ::c_int, __err: ::c_int) -> ::c_int;
+ pub fn MsgCurrent(__rcvid: ::c_int) -> ::c_int;
+ pub fn MsgCurrent_r(__rcvid: ::c_int) -> ::c_int;
+ pub fn MsgSendAsyncGbl(
+ __coid: ::c_int,
+ __smsg: *const ::c_void,
+ __sbytes: usize,
+ __msg_prio: ::c_uint,
+ ) -> ::c_int;
+ pub fn MsgSendAsync(__coid: ::c_int) -> ::c_int;
+ pub fn MsgReceiveAsyncGbl(
+ __chid: ::c_int,
+ __rmsg: *mut ::c_void,
+ __rbytes: usize,
+ __info: *mut _msg_info64,
+ __coid: ::c_int,
+ ) -> ::c_int;
+ pub fn MsgReceiveAsync(__chid: ::c_int, __iov: *const ::iovec, __parts: ::c_uint) -> ::c_int;
+ pub fn MsgPause(__rcvid: ::c_int, __cookie: ::c_uint) -> ::c_int;
+ pub fn MsgPause_r(__rcvid: ::c_int, __cookie: ::c_uint) -> ::c_int;
+
+ pub fn SignalKill(
+ __nd: u32,
+ __pid: ::pid_t,
+ __tid: ::c_int,
+ __signo: ::c_int,
+ __code: ::c_int,
+ __value: ::c_int,
+ ) -> ::c_int;
+ pub fn SignalKill_r(
+ __nd: u32,
+ __pid: ::pid_t,
+ __tid: ::c_int,
+ __signo: ::c_int,
+ __code: ::c_int,
+ __value: ::c_int,
+ ) -> ::c_int;
+ pub fn SignalKillSigval(
+ __nd: u32,
+ __pid: ::pid_t,
+ __tid: ::c_int,
+ __signo: ::c_int,
+ __code: ::c_int,
+ __value: *const ::sigval,
+ ) -> ::c_int;
+ pub fn SignalKillSigval_r(
+ __nd: u32,
+ __pid: ::pid_t,
+ __tid: ::c_int,
+ __signo: ::c_int,
+ __code: ::c_int,
+ __value: *const ::sigval,
+ ) -> ::c_int;
+ pub fn SignalReturn(__info: *mut _sighandler_info) -> ::c_int;
+ pub fn SignalFault(__sigcode: ::c_uint, __regs: *mut ::c_void, __refaddr: usize) -> ::c_int;
+ pub fn SignalAction(
+ __pid: ::pid_t,
+ __sigstub: unsafe extern "C" fn(),
+ __signo: ::c_int,
+ __act: *const ::sigaction,
+ __oact: *mut ::sigaction,
+ ) -> ::c_int;
+ pub fn SignalAction_r(
+ __pid: ::pid_t,
+ __sigstub: unsafe extern "C" fn(),
+ __signo: ::c_int,
+ __act: *const ::sigaction,
+ __oact: *mut ::sigaction,
+ ) -> ::c_int;
+ pub fn SignalProcmask(
+ __pid: ::pid_t,
+ __tid: ::c_int,
+ __how: ::c_int,
+ __set: *const ::sigset_t,
+ __oldset: *mut ::sigset_t,
+ ) -> ::c_int;
+ pub fn SignalProcmask_r(
+ __pid: ::pid_t,
+ __tid: ::c_int,
+ __how: ::c_int,
+ __set: *const ::sigset_t,
+ __oldset: *mut ::sigset_t,
+ ) -> ::c_int;
+ pub fn SignalSuspend(__set: *const ::sigset_t) -> ::c_int;
+ pub fn SignalSuspend_r(__set: *const ::sigset_t) -> ::c_int;
+ pub fn SignalWaitinfo(__set: *const ::sigset_t, __info: *mut ::siginfo_t) -> ::c_int;
+ pub fn SignalWaitinfo_r(__set: *const ::sigset_t, __info: *mut ::siginfo_t) -> ::c_int;
+ pub fn SignalWaitinfoMask(
+ __set: *const ::sigset_t,
+ __info: *mut ::siginfo_t,
+ __mask: *const ::sigset_t,
+ ) -> ::c_int;
+ pub fn SignalWaitinfoMask_r(
+ __set: *const ::sigset_t,
+ __info: *mut ::siginfo_t,
+ __mask: *const ::sigset_t,
+ ) -> ::c_int;
+ pub fn ThreadCreate(
+ __pid: ::pid_t,
+ __func: unsafe extern "C" fn(__arg: *mut ::c_void) -> *mut ::c_void,
+ __arg: *mut ::c_void,
+ __attr: *const ::_thread_attr,
+ ) -> ::c_int;
+ pub fn ThreadCreate_r(
+ __pid: ::pid_t,
+ __func: unsafe extern "C" fn(__arg: *mut ::c_void) -> *mut ::c_void,
+ __arg: *mut ::c_void,
+ __attr: *const ::_thread_attr,
+ ) -> ::c_int;
+
+ pub fn ThreadDestroy(__tid: ::c_int, __priority: ::c_int, __status: *mut ::c_void) -> ::c_int;
+ pub fn ThreadDestroy_r(__tid: ::c_int, __priority: ::c_int, __status: *mut ::c_void)
+ -> ::c_int;
+ pub fn ThreadDetach(__tid: ::c_int) -> ::c_int;
+ pub fn ThreadDetach_r(__tid: ::c_int) -> ::c_int;
+ pub fn ThreadJoin(__tid: ::c_int, __status: *mut *mut ::c_void) -> ::c_int;
+ pub fn ThreadJoin_r(__tid: ::c_int, __status: *mut *mut ::c_void) -> ::c_int;
+ pub fn ThreadCancel(__tid: ::c_int, __canstub: unsafe extern "C" fn()) -> ::c_int;
+ pub fn ThreadCancel_r(__tid: ::c_int, __canstub: unsafe extern "C" fn()) -> ::c_int;
+ pub fn ThreadCtl(__cmd: ::c_int, __data: *mut ::c_void) -> ::c_int;
+ pub fn ThreadCtl_r(__cmd: ::c_int, __data: *mut ::c_void) -> ::c_int;
+ pub fn ThreadCtlExt(
+ __pid: ::pid_t,
+ __tid: ::c_int,
+ __cmd: ::c_int,
+ __data: *mut ::c_void,
+ ) -> ::c_int;
+ pub fn ThreadCtlExt_r(
+ __pid: ::pid_t,
+ __tid: ::c_int,
+ __cmd: ::c_int,
+ __data: *mut ::c_void,
+ ) -> ::c_int;
+
+ pub fn InterruptHookTrace(
+ __handler: ::Option<unsafe extern "C" fn(arg1: ::c_int) -> *const ::sigevent>,
+ __flags: ::c_uint,
+ ) -> ::c_int;
+ pub fn InterruptHookIdle(
+ __handler: ::Option<unsafe extern "C" fn(arg1: *mut u64, arg2: *mut qtime_entry)>,
+ __flags: ::c_uint,
+ ) -> ::c_int;
+ pub fn InterruptHookIdle2(
+ __handler: ::Option<
+ unsafe extern "C" fn(arg1: ::c_uint, arg2: *mut syspage_entry, arg3: *mut _idle_hook),
+ >,
+ __flags: ::c_uint,
+ ) -> ::c_int;
+ pub fn InterruptHookOverdriveEvent(__event: *const ::sigevent, __flags: ::c_uint) -> ::c_int;
+ pub fn InterruptAttachEvent(
+ __intr: ::c_int,
+ __event: *const ::sigevent,
+ __flags: ::c_uint,
+ ) -> ::c_int;
+ pub fn InterruptAttachEvent_r(
+ __intr: ::c_int,
+ __event: *const ::sigevent,
+ __flags: ::c_uint,
+ ) -> ::c_int;
+ pub fn InterruptAttach(
+ __intr: ::c_int,
+ __handler: ::Option<
+ unsafe extern "C" fn(__area: *mut ::c_void, __id: ::c_int) -> *const ::sigevent,
+ >,
+ __area: *const ::c_void,
+ __size: ::c_int,
+ __flags: ::c_uint,
+ ) -> ::c_int;
+ pub fn InterruptAttach_r(
+ __intr: ::c_int,
+ __handler: ::Option<
+ unsafe extern "C" fn(__area: *mut ::c_void, __id: ::c_int) -> *const ::sigevent,
+ >,
+ __area: *const ::c_void,
+ __size: ::c_int,
+ __flags: ::c_uint,
+ ) -> ::c_int;
+ pub fn InterruptAttachArray(
+ __intr: ::c_int,
+ __handler: ::Option<
+ unsafe extern "C" fn(__area: *mut ::c_void, __id: ::c_int) -> *const *const ::sigevent,
+ >,
+ __area: *const ::c_void,
+ __size: ::c_int,
+ __flags: ::c_uint,
+ ) -> ::c_int;
+ pub fn InterruptAttachArray_r(
+ __intr: ::c_int,
+ __handler: ::Option<
+ unsafe extern "C" fn(__area: *mut ::c_void, __id: ::c_int) -> *const *const ::sigevent,
+ >,
+ __area: *const ::c_void,
+ __size: ::c_int,
+ __flags: ::c_uint,
+ ) -> ::c_int;
+ pub fn InterruptDetach(__id: ::c_int) -> ::c_int;
+ pub fn InterruptDetach_r(__id: ::c_int) -> ::c_int;
+ pub fn InterruptWait(__flags: ::c_int, __timeout: *const u64) -> ::c_int;
+ pub fn InterruptWait_r(__flags: ::c_int, __timeout: *const u64) -> ::c_int;
+ pub fn InterruptCharacteristic(
+ __type: ::c_int,
+ __id: ::c_int,
+ __new: *mut ::c_uint,
+ __old: *mut ::c_uint,
+ ) -> ::c_int;
+ pub fn InterruptCharacteristic_r(
+ __type: ::c_int,
+ __id: ::c_int,
+ __new: *mut ::c_uint,
+ __old: *mut ::c_uint,
+ ) -> ::c_int;
+
+ pub fn SchedGet(__pid: ::pid_t, __tid: ::c_int, __param: *mut ::sched_param) -> ::c_int;
+ pub fn SchedGet_r(__pid: ::pid_t, __tid: ::c_int, __param: *mut ::sched_param) -> ::c_int;
+ pub fn SchedGetCpuNum() -> ::c_uint;
+ pub fn SchedSet(
+ __pid: ::pid_t,
+ __tid: ::c_int,
+ __algorithm: ::c_int,
+ __param: *const ::sched_param,
+ ) -> ::c_int;
+ pub fn SchedSet_r(
+ __pid: ::pid_t,
+ __tid: ::c_int,
+ __algorithm: ::c_int,
+ __param: *const ::sched_param,
+ ) -> ::c_int;
+ pub fn SchedInfo(__pid: ::pid_t, __algorithm: ::c_int, __info: *mut ::_sched_info) -> ::c_int;
+ pub fn SchedInfo_r(__pid: ::pid_t, __algorithm: ::c_int, __info: *mut ::_sched_info)
+ -> ::c_int;
+ pub fn SchedYield() -> ::c_int;
+ pub fn SchedYield_r() -> ::c_int;
+ pub fn SchedCtl(__cmd: ::c_int, __data: *mut ::c_void, __length: usize) -> ::c_int;
+ pub fn SchedCtl_r(__cmd: ::c_int, __data: *mut ::c_void, __length: usize) -> ::c_int;
+ pub fn SchedJobCreate(__job: *mut nto_job_t) -> ::c_int;
+ pub fn SchedJobCreate_r(__job: *mut nto_job_t) -> ::c_int;
+ pub fn SchedJobDestroy(__job: *mut nto_job_t) -> ::c_int;
+ pub fn SchedJobDestroy_r(__job: *mut nto_job_t) -> ::c_int;
+ pub fn SchedWaypoint(
+ __job: *mut nto_job_t,
+ __new: *const i64,
+ __max: *const i64,
+ __old: *mut i64,
+ ) -> ::c_int;
+ pub fn SchedWaypoint_r(
+ __job: *mut nto_job_t,
+ __new: *const i64,
+ __max: *const i64,
+ __old: *mut i64,
+ ) -> ::c_int;
+
+ pub fn TimerCreate(__id: ::clockid_t, __notify: *const ::sigevent) -> ::c_int;
+ pub fn TimerCreate_r(__id: ::clockid_t, __notify: *const ::sigevent) -> ::c_int;
+ pub fn TimerDestroy(__id: ::timer_t) -> ::c_int;
+ pub fn TimerDestroy_r(__id: ::timer_t) -> ::c_int;
+ pub fn TimerSettime(
+ __id: ::timer_t,
+ __flags: ::c_int,
+ __itime: *const ::_itimer,
+ __oitime: *mut ::_itimer,
+ ) -> ::c_int;
+ pub fn TimerSettime_r(
+ __id: ::timer_t,
+ __flags: ::c_int,
+ __itime: *const ::_itimer,
+ __oitime: *mut ::_itimer,
+ ) -> ::c_int;
+ pub fn TimerInfo(
+ __pid: ::pid_t,
+ __id: ::timer_t,
+ __flags: ::c_int,
+ __info: *mut ::_timer_info,
+ ) -> ::c_int;
+ pub fn TimerInfo_r(
+ __pid: ::pid_t,
+ __id: ::timer_t,
+ __flags: ::c_int,
+ __info: *mut ::_timer_info,
+ ) -> ::c_int;
+ pub fn TimerAlarm(
+ __id: ::clockid_t,
+ __itime: *const ::_itimer,
+ __otime: *mut ::_itimer,
+ ) -> ::c_int;
+ pub fn TimerAlarm_r(
+ __id: ::clockid_t,
+ __itime: *const ::_itimer,
+ __otime: *mut ::_itimer,
+ ) -> ::c_int;
+ pub fn TimerTimeout(
+ __id: ::clockid_t,
+ __flags: ::c_int,
+ __notify: *const ::sigevent,
+ __ntime: *const u64,
+ __otime: *mut u64,
+ ) -> ::c_int;
+ pub fn TimerTimeout_r(
+ __id: ::clockid_t,
+ __flags: ::c_int,
+ __notify: *const ::sigevent,
+ __ntime: *const u64,
+ __otime: *mut u64,
+ ) -> ::c_int;
+
+ pub fn SyncTypeCreate(
+ __type: ::c_uint,
+ __sync: *mut ::sync_t,
+ __attr: *const ::_sync_attr,
+ ) -> ::c_int;
+ pub fn SyncTypeCreate_r(
+ __type: ::c_uint,
+ __sync: *mut ::sync_t,
+ __attr: *const ::_sync_attr,
+ ) -> ::c_int;
+ pub fn SyncDestroy(__sync: *mut ::sync_t) -> ::c_int;
+ pub fn SyncDestroy_r(__sync: *mut ::sync_t) -> ::c_int;
+ pub fn SyncCtl(__cmd: ::c_int, __sync: *mut ::sync_t, __data: *mut ::c_void) -> ::c_int;
+ pub fn SyncCtl_r(__cmd: ::c_int, __sync: *mut ::sync_t, __data: *mut ::c_void) -> ::c_int;
+ pub fn SyncMutexEvent(__sync: *mut ::sync_t, event: *const ::sigevent) -> ::c_int;
+ pub fn SyncMutexEvent_r(__sync: *mut ::sync_t, event: *const ::sigevent) -> ::c_int;
+ pub fn SyncMutexLock(__sync: *mut ::sync_t) -> ::c_int;
+ pub fn SyncMutexLock_r(__sync: *mut ::sync_t) -> ::c_int;
+ pub fn SyncMutexUnlock(__sync: *mut ::sync_t) -> ::c_int;
+ pub fn SyncMutexUnlock_r(__sync: *mut ::sync_t) -> ::c_int;
+ pub fn SyncMutexRevive(__sync: *mut ::sync_t) -> ::c_int;
+ pub fn SyncMutexRevive_r(__sync: *mut ::sync_t) -> ::c_int;
+ pub fn SyncCondvarWait(__sync: *mut ::sync_t, __mutex: *mut ::sync_t) -> ::c_int;
+ pub fn SyncCondvarWait_r(__sync: *mut ::sync_t, __mutex: *mut ::sync_t) -> ::c_int;
+ pub fn SyncCondvarSignal(__sync: *mut ::sync_t, __all: ::c_int) -> ::c_int;
+ pub fn SyncCondvarSignal_r(__sync: *mut ::sync_t, __all: ::c_int) -> ::c_int;
+ pub fn SyncSemPost(__sync: *mut ::sync_t) -> ::c_int;
+ pub fn SyncSemPost_r(__sync: *mut ::sync_t) -> ::c_int;
+ pub fn SyncSemWait(__sync: *mut ::sync_t, __tryto: ::c_int) -> ::c_int;
+ pub fn SyncSemWait_r(__sync: *mut ::sync_t, __tryto: ::c_int) -> ::c_int;
+
+ pub fn ClockTime(__id: ::clockid_t, _new: *const u64, __old: *mut u64) -> ::c_int;
+ pub fn ClockTime_r(__id: ::clockid_t, _new: *const u64, __old: *mut u64) -> ::c_int;
+ pub fn ClockAdjust(
+ __id: ::clockid_t,
+ _new: *const ::_clockadjust,
+ __old: *mut ::_clockadjust,
+ ) -> ::c_int;
+ pub fn ClockAdjust_r(
+ __id: ::clockid_t,
+ _new: *const ::_clockadjust,
+ __old: *mut ::_clockadjust,
+ ) -> ::c_int;
+ pub fn ClockPeriod(
+ __id: ::clockid_t,
+ _new: *const ::_clockperiod,
+ __old: *mut ::_clockperiod,
+ __reserved: ::c_int,
+ ) -> ::c_int;
+ pub fn ClockPeriod_r(
+ __id: ::clockid_t,
+ _new: *const ::_clockperiod,
+ __old: *mut ::_clockperiod,
+ __reserved: ::c_int,
+ ) -> ::c_int;
+ pub fn ClockId(__pid: ::pid_t, __tid: ::c_int) -> ::c_int;
+ pub fn ClockId_r(__pid: ::pid_t, __tid: ::c_int) -> ::c_int;
+
+ //
+ //TODO: The following commented out functions are implemented in assembly.
+ // We can implmement them either via a C stub or rust's inline assembly.
+ //
+ //pub fn InterruptEnable();
+ //pub fn InterruptDisable();
+ pub fn InterruptMask(__intr: ::c_int, __id: ::c_int) -> ::c_int;
+ pub fn InterruptUnmask(__intr: ::c_int, __id: ::c_int) -> ::c_int;
+ //pub fn InterruptLock(__spin: *mut ::intrspin);
+ //pub fn InterruptUnlock(__spin: *mut ::intrspin);
+ //pub fn InterruptStatus() -> ::c_uint;
+}
diff --git a/vendor/libc/src/unix/nto/x86_64.rs b/vendor/libc/src/unix/nto/x86_64.rs
new file mode 100644
index 000000000..3a1d230bb
--- /dev/null
+++ b/vendor/libc/src/unix/nto/x86_64.rs
@@ -0,0 +1,132 @@
+pub type c_char = i8;
+pub type wchar_t = u32;
+pub type c_long = i64;
+pub type c_ulong = u64;
+pub type time_t = i64;
+
+s! {
+ #[repr(align(8))]
+ pub struct x86_64_cpu_registers {
+ pub rdi: u64,
+ pub rsi: u64,
+ pub rdx: u64,
+ pub r10: u64,
+ pub r8: u64,
+ pub r9: u64,
+ pub rax: u64,
+ pub rbx: u64,
+ pub rbp: u64,
+ pub rcx: u64,
+ pub r11: u64,
+ pub r12: u64,
+ pub r13: u64,
+ pub r14: u64,
+ pub r15: u64,
+ pub rip: u64,
+ pub cs: u32,
+ rsvd1: u32,
+ pub rflags: u64,
+ pub rsp: u64,
+ pub ss: u32,
+ rsvd2: u32,
+ }
+
+ #[repr(align(8))]
+ pub struct mcontext_t {
+ pub cpu: x86_64_cpu_registers,
+ #[cfg(libc_union)]
+ pub fpu: x86_64_fpu_registers,
+ #[cfg(not(libc_union))]
+ __reserved: [u8; 1024],
+ }
+
+ pub struct stack_t {
+ pub ss_sp: *mut ::c_void,
+ pub ss_size: ::size_t,
+ pub ss_flags: ::c_int,
+ }
+
+ pub struct fsave_area_64 {
+ pub fpu_control_word: u32,
+ pub fpu_status_word: u32,
+ pub fpu_tag_word: u32,
+ pub fpu_ip: u32,
+ pub fpu_cs: u32,
+ pub fpu_op: u32,
+ pub fpu_ds: u32,
+ pub st_regs: [u8; 80],
+ }
+
+ pub struct fxsave_area_64 {
+ pub fpu_control_word: u16,
+ pub fpu_status_word: u16,
+ pub fpu_tag_word: u16,
+ pub fpu_operand: u16,
+ pub fpu_rip: u64,
+ pub fpu_rdp: u64,
+ pub mxcsr: u32,
+ pub mxcsr_mask: u32,
+ pub st_regs: [u8; 128],
+ pub xmm_regs: [u8; 128],
+ reserved2: [u8; 224],
+ }
+
+ pub struct fpu_extention_savearea_64 {
+ pub other: [u8; 512],
+ pub xstate_bv: u64,
+ pub xstate_undef: [u64; 7],
+ pub xstate_info: [u8; 224],
+ }
+}
+
+s_no_extra_traits! {
+ #[cfg(libc_union)]
+ pub union x86_64_fpu_registers {
+ pub fsave_area: fsave_area_64,
+ pub fxsave_area: fxsave_area_64,
+ pub xsave_area: fpu_extention_savearea_64,
+ pub data: [u8; 1024],
+ }
+}
+
+cfg_if! {
+ if #[cfg(feature = "extra_traits")] {
+ #[cfg(libc_union)]
+ impl Eq for x86_64_fpu_registers {}
+
+ #[cfg(libc_union)]
+ impl PartialEq for x86_64_fpu_registers {
+ fn eq(&self, other: &x86_64_fpu_registers) -> bool {
+ unsafe {
+ self.fsave_area == other.fsave_area
+ || self.fxsave_area == other.fxsave_area
+ || self.xsave_area == other.xsave_area
+ }
+ }
+ }
+
+ #[cfg(libc_union)]
+ impl ::fmt::Debug for x86_64_fpu_registers {
+ fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result {
+ unsafe {
+ f.debug_struct("x86_64_fpu_registers")
+ .field("fsave_area", &self.fsave_area)
+ .field("fxsave_area", &self.fxsave_area)
+ .field("xsave_area", &self.xsave_area)
+ .finish()
+ }
+ }
+ }
+
+ #[cfg(libc_union)]
+ impl ::hash::Hash for x86_64_fpu_registers {
+ fn hash<H: ::hash::Hasher>(&self, state: &mut H) {
+ unsafe {
+ self.fsave_area.hash(state);
+ self.fxsave_area.hash(state);
+ self.xsave_area.hash(state);
+ }
+ }
+ }
+ }
+}
diff --git a/vendor/libc/src/unix/solarish/mod.rs b/vendor/libc/src/unix/solarish/mod.rs
index abe304e8e..99135d5f5 100644
--- a/vendor/libc/src/unix/solarish/mod.rs
+++ b/vendor/libc/src/unix/solarish/mod.rs
@@ -2710,7 +2710,6 @@ extern "C" {
pub fn abs(i: ::c_int) -> ::c_int;
pub fn acct(filename: *const ::c_char) -> ::c_int;
- pub fn atof(s: *const ::c_char) -> ::c_double;
pub fn dirfd(dirp: *mut ::DIR) -> ::c_int;
pub fn labs(i: ::c_long) -> ::c_long;
pub fn rand() -> ::c_int;
diff --git a/vendor/libc/src/vxworks/mod.rs b/vendor/libc/src/vxworks/mod.rs
index 2772d68d2..6b705e8a2 100644
--- a/vendor/libc/src/vxworks/mod.rs
+++ b/vendor/libc/src/vxworks/mod.rs
@@ -1119,11 +1119,16 @@ extern "C" {
pub fn feof(stream: *mut FILE) -> c_int;
pub fn ferror(stream: *mut FILE) -> c_int;
pub fn perror(s: *const c_char);
+ pub fn atof(s: *const c_char) -> c_double;
pub fn atoi(s: *const c_char) -> c_int;
+ pub fn atol(s: *const c_char) -> c_long;
+ pub fn atoll(s: *const c_char) -> c_longlong;
pub fn strtod(s: *const c_char, endp: *mut *mut c_char) -> c_double;
pub fn strtof(s: *const c_char, endp: *mut *mut c_char) -> c_float;
pub fn strtol(s: *const c_char, endp: *mut *mut c_char, base: c_int) -> c_long;
+ pub fn strtoll(s: *const c_char, endp: *mut *mut c_char, base: c_int) -> c_longlong;
pub fn strtoul(s: *const c_char, endp: *mut *mut c_char, base: c_int) -> c_ulong;
+ pub fn strtoull(s: *const c_char, endp: *mut *mut c_char, base: c_int) -> c_ulonglong;
pub fn calloc(nobj: size_t, size: size_t) -> *mut c_void;
pub fn malloc(size: size_t) -> *mut c_void;
pub fn realloc(p: *mut c_void, size: size_t) -> *mut c_void;
diff --git a/vendor/libc/src/wasi.rs b/vendor/libc/src/wasi.rs
index c5dd67047..abfebd643 100644
--- a/vendor/libc/src/wasi.rs
+++ b/vendor/libc/src/wasi.rs
@@ -540,12 +540,16 @@ extern "C" {
pub fn setvbuf(stream: *mut FILE, buffer: *mut c_char, mode: c_int, size: size_t) -> c_int;
pub fn setbuf(stream: *mut FILE, buf: *mut c_char);
pub fn fgets(buf: *mut c_char, n: c_int, stream: *mut FILE) -> *mut c_char;
- pub fn atoi(s: *const c_char) -> c_int;
pub fn atof(s: *const c_char) -> c_double;
+ pub fn atoi(s: *const c_char) -> c_int;
+ pub fn atol(s: *const c_char) -> c_long;
+ pub fn atoll(s: *const c_char) -> c_longlong;
pub fn strtod(s: *const c_char, endp: *mut *mut c_char) -> c_double;
pub fn strtof(s: *const c_char, endp: *mut *mut c_char) -> c_float;
pub fn strtol(s: *const c_char, endp: *mut *mut c_char, base: c_int) -> c_long;
+ pub fn strtoll(s: *const c_char, endp: *mut *mut c_char, base: c_int) -> c_longlong;
pub fn strtoul(s: *const c_char, endp: *mut *mut c_char, base: c_int) -> c_ulong;
+ pub fn strtoull(s: *const c_char, endp: *mut *mut c_char, base: c_int) -> c_ulonglong;
pub fn strcpy(dst: *mut c_char, src: *const c_char) -> *mut c_char;
pub fn strncpy(dst: *mut c_char, src: *const c_char, n: size_t) -> *mut c_char;
diff --git a/vendor/libc/src/windows/mod.rs b/vendor/libc/src/windows/mod.rs
index 916019b1f..7f2f1ded1 100644
--- a/vendor/libc/src/windows/mod.rs
+++ b/vendor/libc/src/windows/mod.rs
@@ -329,11 +329,16 @@ extern "C" {
pub fn feof(stream: *mut FILE) -> c_int;
pub fn ferror(stream: *mut FILE) -> c_int;
pub fn perror(s: *const c_char);
+ pub fn atof(s: *const c_char) -> c_double;
pub fn atoi(s: *const c_char) -> c_int;
+ pub fn atol(s: *const c_char) -> c_long;
+ pub fn atoll(s: *const c_char) -> c_longlong;
pub fn strtod(s: *const c_char, endp: *mut *mut c_char) -> c_double;
pub fn strtof(s: *const c_char, endp: *mut *mut c_char) -> c_float;
pub fn strtol(s: *const c_char, endp: *mut *mut c_char, base: c_int) -> c_long;
+ pub fn strtoll(s: *const c_char, endp: *mut *mut c_char, base: c_int) -> c_longlong;
pub fn strtoul(s: *const c_char, endp: *mut *mut c_char, base: c_int) -> c_ulong;
+ pub fn strtoull(s: *const c_char, endp: *mut *mut c_char, base: c_int) -> c_ulonglong;
pub fn calloc(nobj: size_t, size: size_t) -> *mut c_void;
pub fn malloc(size: size_t) -> *mut c_void;
pub fn realloc(p: *mut c_void, size: size_t) -> *mut c_void;
@@ -374,7 +379,6 @@ extern "C" {
pub fn memset(dest: *mut c_void, c: c_int, n: size_t) -> *mut c_void;
pub fn abs(i: c_int) -> c_int;
- pub fn atof(s: *const c_char) -> c_double;
pub fn labs(i: c_long) -> c_long;
pub fn rand() -> c_int;
pub fn srand(seed: c_uint);
diff --git a/vendor/litemap/.cargo-checksum.json b/vendor/litemap/.cargo-checksum.json
index 1ff02fee7..46a4f357e 100644
--- a/vendor/litemap/.cargo-checksum.json
+++ b/vendor/litemap/.cargo-checksum.json
@@ -1 +1 @@
-{"files":{"Cargo.lock":"46b05d0a550d86bc76aecd44a1d744c6390eda4765c98ceb4924bf0bb1caa970","Cargo.toml":"3cc1ad5a8dcfe5aed44bee3fc06fd5d2a13b739bc5ca7e4f6a64887ffbd0446e","LICENSE":"4ad7541d66a407234e2c84902124cef325c29f3e966353efdb800bedb8b8da21","README.md":"021453bdd013041c191ed05243145d6fcd69d4b2e3c34685d80ee1bb96014495","benches/bin/litemap_bincode.rs":"f68c78c5438173355270560bc7fcc0b1cabc5a9a3001b13e03feb29ba8de60d1","benches/bin/litemap_postcard.rs":"2864ffc0caad3e51e67a1dd2edf23b8e924b3143b683a1101fb5113eccb4efa6","benches/litemap.rs":"56af028c07cd83d7018bcbce19855f31697ed940b508fbf5f8e49bedf52c87bc","benches/testdata/large_litemap.postcard":"7316edaf9b1b618eaa33a22cdc1f02474d53bea4fdd664ad10099235e4de5f0d","examples/language_names_hash_map.rs":"705d1049e64d6080571806f8a06330c6a3b126945bcf3bc341e1c707aad4e8f5","examples/language_names_lite_map.rs":"767246fa90005d2450f60fe1cb92c4431610a44b6e861f6146562595214996d8","src/lib.rs":"cf9c3d91961f85b96680d935f44ec0650c8963ecca4c7c80261840cc2e7b9ce5","src/map.rs":"54695e4232c2f9719586fd121aeafc342ac4c259505285c15eef2ac59f0c5198","src/serde.rs":"4308da055ada25f8fd8b1d5a9398a4bfa58936971b638148b45b2d4beb3f0c7d","src/serde_helpers.rs":"72787005972b93e49b9dc17aa47d30699364e6da9dc95aadb820ce58e4bf5c54","src/store/mod.rs":"a35aa4837c80af61cd9e0d27b7120cc26cc2fbe0e215a14fe15eed980bc4757f","src/store/slice_impl.rs":"34d46f5e3db0f81f391444b764f2fce7592efe1b758bef3f56a283dc24bf041d","src/store/vec_impl.rs":"c94cf9402fb6710500c0b193a476c705ed10cea9121e8c784bbacc88842539e4","src/testing.rs":"5ecf1642fed31150b29451987a89d0b134d94d62078c7f343fa9754a02f4bd90","tests/rkyv.rs":"6400df6740aa5a3f3831ffc4559ada8a431f33e1a48924fcd2b168cda442d835","tests/serde.rs":"0051274f8490c5837d88447bf72fc7266e970fa95c6e4ca540eeba45b7947ce6","tests/store.rs":"6f9506b301d82c9c1bdd737515d476002d06bd89e2f77fd00bc498653a67a629"},"package":"f34a3f4798fac63fb48cf277eefa38f94d3443baff555bb98e4f56bc9092368e"} \ No newline at end of file
+{"files":{"Cargo.lock":"33b6362389865144374a4952e3df4580aa90e25ccd6e141da42211158c667a34","Cargo.toml":"f8d7c3287cac0d53910dd611de6d0b1b883f43415bcfdbbd3e9396b75e9989c0","LICENSE":"4ad7541d66a407234e2c84902124cef325c29f3e966353efdb800bedb8b8da21","README.md":"021453bdd013041c191ed05243145d6fcd69d4b2e3c34685d80ee1bb96014495","benches/bin/litemap_bincode.rs":"f68c78c5438173355270560bc7fcc0b1cabc5a9a3001b13e03feb29ba8de60d1","benches/bin/litemap_postcard.rs":"2864ffc0caad3e51e67a1dd2edf23b8e924b3143b683a1101fb5113eccb4efa6","benches/litemap.rs":"dc4ca991b9f0ce618005e0e3133738459c7db580744756a0568da7a0f4f6d1be","benches/testdata/large_litemap.postcard":"7316edaf9b1b618eaa33a22cdc1f02474d53bea4fdd664ad10099235e4de5f0d","examples/language_names_hash_map.rs":"705d1049e64d6080571806f8a06330c6a3b126945bcf3bc341e1c707aad4e8f5","examples/language_names_lite_map.rs":"767246fa90005d2450f60fe1cb92c4431610a44b6e861f6146562595214996d8","src/lib.rs":"cf9c3d91961f85b96680d935f44ec0650c8963ecca4c7c80261840cc2e7b9ce5","src/map.rs":"ff8aece659756a8818be30e28a08d4196de8ed1add81e6782bfd776d158276a2","src/serde.rs":"4308da055ada25f8fd8b1d5a9398a4bfa58936971b638148b45b2d4beb3f0c7d","src/serde_helpers.rs":"72787005972b93e49b9dc17aa47d30699364e6da9dc95aadb820ce58e4bf5c54","src/store/mod.rs":"6a8463f1e93c404f2564b6127dd49e85c9587bb2ec74ae6d0c621447e7642b6e","src/store/slice_impl.rs":"34d46f5e3db0f81f391444b764f2fce7592efe1b758bef3f56a283dc24bf041d","src/store/vec_impl.rs":"c94cf9402fb6710500c0b193a476c705ed10cea9121e8c784bbacc88842539e4","src/testing.rs":"5ecf1642fed31150b29451987a89d0b134d94d62078c7f343fa9754a02f4bd90","tests/rkyv.rs":"b19d91eda9105699a4340340f0a8961de5f02673599dd8eddb43269634777cc4","tests/serde.rs":"0051274f8490c5837d88447bf72fc7266e970fa95c6e4ca540eeba45b7947ce6","tests/store.rs":"6f9506b301d82c9c1bdd737515d476002d06bd89e2f77fd00bc498653a67a629"},"package":"575d8a551c59104b4df91269921e5eab561aa1b77c618dac0414b5d44a4617de"} \ No newline at end of file
diff --git a/vendor/litemap/Cargo.lock b/vendor/litemap/Cargo.lock
index 3d0f04dca..28af8845a 100644
--- a/vendor/litemap/Cargo.lock
+++ b/vendor/litemap/Cargo.lock
@@ -14,19 +14,10 @@ dependencies = [
]
[[package]]
-name = "aho-corasick"
-version = "0.7.19"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b4f55bd91a0978cbfd91c457a164bab8b4001c833b7f323132c0a4e1922dd44e"
-dependencies = [
- "memchr",
-]
-
-[[package]]
name = "atomic-polyfill"
-version = "0.1.10"
+version = "0.1.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9c041a8d9751a520ee19656232a18971f18946a7900f1520ee4400002244dd89"
+checksum = "e3ff7eb3f316534d83a8a2c3d1674ace8a5a71198eba31e2e2b597833f699b28"
dependencies = [
"critical-section",
]
@@ -37,7 +28,7 @@ version = "0.2.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
dependencies = [
- "hermit-abi",
+ "hermit-abi 0.1.19",
"libc",
"winapi",
]
@@ -49,21 +40,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
[[package]]
-name = "bare-metal"
-version = "0.2.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5deb64efa5bd81e31fcd1938615a6d98c82eafcbcd787162b6f63b91d6bac5b3"
-dependencies = [
- "rustc_version 0.2.3",
-]
-
-[[package]]
-name = "bare-metal"
-version = "1.0.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f8fe8f5a8a398345e52358e18ff07cc17a568fbca5c6f73873d3a62056309603"
-
-[[package]]
name = "bincode"
version = "1.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -73,18 +49,6 @@ dependencies = [
]
[[package]]
-name = "bit_field"
-version = "0.10.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dcb6dd1c2376d2e096796e234a70e17e94cc2d5d54ff8ce42b28cef1d0d359a4"
-
-[[package]]
-name = "bitfield"
-version = "0.13.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "46afbd2983a5d5a7bd740ccb198caf5b82f45c40c09c0eed36052d91cb92e719"
-
-[[package]]
name = "bitflags"
version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -104,9 +68,9 @@ dependencies = [
[[package]]
name = "bumpalo"
-version = "3.11.0"
+version = "3.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c1ad822118d20d2c234f427000d5acc36eabe1e29a348c89b63dd60b13f28e5d"
+checksum = "0d261e256854913907f67ed06efbc3338dfe6179796deefc1ff763fc1aee5535"
[[package]]
name = "bytecheck"
@@ -165,18 +129,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "67ba02a97a2bd10f4b59b25c7973101c79642302776489e030cd13cdab09ed15"
[[package]]
-name = "cortex-m"
-version = "0.7.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "70858629a458fdfd39f9675c4dc309411f2a3f83bede76988d81bf1a0ecee9e0"
-dependencies = [
- "bare-metal 0.2.5",
- "bitfield",
- "embedded-hal",
- "volatile-register",
-]
-
-[[package]]
name = "criterion"
version = "0.3.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -214,15 +166,9 @@ dependencies = [
[[package]]
name = "critical-section"
-version = "0.2.7"
+version = "1.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "95da181745b56d4bd339530ec393508910c909c784e8962d15d722bacf0bcbcd"
-dependencies = [
- "bare-metal 1.0.0",
- "cfg-if",
- "cortex-m",
- "riscv",
-]
+checksum = "6548a0ad5d2549e111e1f6a11a6c2e2d00ce6a3dafe22948d67c2b443f775e52"
[[package]]
name = "crossbeam-channel"
@@ -247,26 +193,24 @@ dependencies = [
[[package]]
name = "crossbeam-epoch"
-version = "0.9.10"
+version = "0.9.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "045ebe27666471bb549370b4b0b3e51b07f56325befa4284db65fc89c02511b1"
+checksum = "01a9af1f4c2ef74bb8aa1f7e19706bc72d03598c8a570bb5de72243c7a9d9d5a"
dependencies = [
"autocfg",
"cfg-if",
"crossbeam-utils",
"memoffset",
- "once_cell",
"scopeguard",
]
[[package]]
name = "crossbeam-utils"
-version = "0.8.11"
+version = "0.8.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "51887d4adc7b564537b15adcfb307936f8075dfcd5f00dde9a9f1d29383682bc"
+checksum = "4fb766fa798726286dbbb842f174001dab8abc7b627a1dd86e0b7222a95d929f"
dependencies = [
"cfg-if",
- "once_cell",
]
[[package]]
@@ -292,37 +236,16 @@ dependencies = [
]
[[package]]
-name = "displaydoc"
-version = "0.2.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3bf95dc3f046b9da4f2d51833c0d3547d8564ef6910f5c1ed130306a75b92886"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn",
-]
-
-[[package]]
name = "either"
version = "1.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "90e5c1c8368803113bf0c9584fc495a58b86dc8a29edbf8fe877d21d9507e797"
[[package]]
-name = "embedded-hal"
-version = "0.2.7"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "35949884794ad573cf46071e41c9b60efb0cb311e3ca01f7af807af1debc66ff"
-dependencies = [
- "nb 0.1.3",
- "void",
-]
-
-[[package]]
name = "getrandom"
-version = "0.2.7"
+version = "0.2.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4eb1a864a501629691edf6c15a593b7a51eebaa1e8468e9ddc623de7c9b58ec6"
+checksum = "c05aeb6a22b8f62540c194aac980f2115af067bfe15a0734d7277a768d396b31"
dependencies = [
"cfg-if",
"libc",
@@ -361,7 +284,7 @@ checksum = "db04bc24a18b9ea980628ecf00e6c0264f3c1426dac36c00cb49b6fbad8b0743"
dependencies = [
"atomic-polyfill",
"hash32",
- "rustc_version 0.4.0",
+ "rustc_version",
"serde",
"spin",
"stable_deref_trait",
@@ -377,21 +300,12 @@ dependencies = [
]
[[package]]
-name = "icu_benchmark_macros"
-version = "0.7.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6c867656f2d9c90b13709ac88e710a9d6afe33998c1dfa22384bab8804e8b3d4"
-
-[[package]]
-name = "icu_locid"
-version = "1.0.0-beta1"
+name = "hermit-abi"
+version = "0.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "db60d0dabdf1536b34f43f05ba3a98a7fd09de82a08c58104f3f218b8f027b67"
+checksum = "ee512640fe35acbfb4bb779db6f0d80704c2cacfa2e39b601ef3e3f47d1ae4c7"
dependencies = [
- "displaydoc",
- "litemap 0.5.0",
- "tinystr",
- "writeable",
+ "libc",
]
[[package]]
@@ -411,9 +325,9 @@ checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4"
[[package]]
name = "itoa"
-version = "1.0.3"
+version = "1.0.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6c8af84674fe1f223a982c933a0ee1086ac4d4052aa0fb8060c12c6ad838e754"
+checksum = "fad582f4b9e86b6caa621cabeb0963332d92eea04729ab12892c2533951e6440"
[[package]]
name = "js-sys"
@@ -432,25 +346,17 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
[[package]]
name = "libc"
-version = "0.2.133"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c0f80d65747a3e43d1596c7c5492d95d5edddaabd45a7fcdb02b95f644164966"
-
-[[package]]
-name = "litemap"
-version = "0.5.0"
+version = "0.2.139"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9cf53a06d08341da913058f6a23488788a8bebc4773e72a43a2243e28a282942"
+checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79"
[[package]]
name = "litemap"
-version = "0.6.0"
+version = "0.6.1"
dependencies = [
"bincode",
"bytecheck",
"criterion",
- "icu_benchmark_macros",
- "icu_locid",
"postcard",
"rkyv",
"serde",
@@ -485,29 +391,14 @@ checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
[[package]]
name = "memoffset"
-version = "0.6.5"
+version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce"
+checksum = "5de893c32cde5f383baa4c04c5d6dbdd735cfd4a794b0debdb2bb1b421da5ff4"
dependencies = [
"autocfg",
]
[[package]]
-name = "nb"
-version = "0.1.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "801d31da0513b6ec5214e9bf433a77966320625a37860f910be265be6e18d06f"
-dependencies = [
- "nb 1.0.0",
-]
-
-[[package]]
-name = "nb"
-version = "1.0.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "546c37ac5d9e56f55e73b677106873d9d9f5190605e41a856503623648488cae"
-
-[[package]]
name = "num-traits"
version = "0.2.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -518,19 +409,19 @@ dependencies = [
[[package]]
name = "num_cpus"
-version = "1.13.1"
+version = "1.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "19e64526ebdee182341572e50e9ad03965aa510cd94427a4549448f285e957a1"
+checksum = "0fac9e2da13b5eb447a6ce3d392f23a29d8694bff781bf03a16cd9ac8697593b"
dependencies = [
- "hermit-abi",
+ "hermit-abi 0.2.6",
"libc",
]
[[package]]
name = "once_cell"
-version = "1.15.0"
+version = "1.17.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e82dad04139b71a90c080c8463fe0dc7902db5192d939bd0950f074d014339e1"
+checksum = "6f61fba1741ea2b3d6a1e3178721804bb716a68a6aeba1149b5d52e3d464ea66"
[[package]]
name = "oorandom"
@@ -579,9 +470,9 @@ dependencies = [
[[package]]
name = "proc-macro2"
-version = "1.0.44"
+version = "1.0.50"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7bd7356a8122b6c4a24a82b278680c73357984ca2fc79a0f9fa6dea7dced7c58"
+checksum = "6ef7d57beacfaf2d8aee5937dab7b7f28de3cb8b1828479bb5de2a7106f2bae2"
dependencies = [
"unicode-ident",
]
@@ -608,30 +499,28 @@ dependencies = [
[[package]]
name = "quote"
-version = "1.0.21"
+version = "1.0.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179"
+checksum = "8856d8364d252a14d474036ea1358d63c9e6965c8e5c1885c18f73d70bff9c7b"
dependencies = [
"proc-macro2",
]
[[package]]
name = "rayon"
-version = "1.5.3"
+version = "1.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bd99e5772ead8baa5215278c9b15bf92087709e9c1b2d1f97cdb5a183c933a7d"
+checksum = "6db3a213adf02b3bcfd2d3846bb41cb22857d131789e01df434fb7e7bc0759b7"
dependencies = [
- "autocfg",
- "crossbeam-deque",
"either",
"rayon-core",
]
[[package]]
name = "rayon-core"
-version = "1.9.3"
+version = "1.10.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "258bcdb5ac6dad48491bb2992db6b7cf74878b0384908af124823d118c99683f"
+checksum = "356a0625f1954f730c0201cdab48611198dc6ce21f4acff55089b5a78e6e835b"
dependencies = [
"crossbeam-channel",
"crossbeam-deque",
@@ -641,12 +530,10 @@ dependencies = [
[[package]]
name = "regex"
-version = "1.6.0"
+version = "1.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4c4eb3267174b8c6c2f654116623910a0fef09c4753f8dd83db29c48a0df988b"
+checksum = "48aaa5748ba571fb95cd2c85c09f629215d3a6ece942baa100950af03a34f733"
dependencies = [
- "aho-corasick",
- "memchr",
"regex-syntax",
]
@@ -658,9 +545,9 @@ checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132"
[[package]]
name = "regex-syntax"
-version = "0.6.27"
+version = "0.6.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a3f87b73ce11b1619a3c6332f45341e0047173771e8b8b73f87bfeefb7b56244"
+checksum = "456c603be3e8d448b072f410900c09faf164fbce2d480456f50eea6e25f9c848"
[[package]]
name = "rend"
@@ -672,27 +559,6 @@ dependencies = [
]
[[package]]
-name = "riscv"
-version = "0.7.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6907ccdd7a31012b70faf2af85cd9e5ba97657cc3987c4f13f8e4d2c2a088aba"
-dependencies = [
- "bare-metal 1.0.0",
- "bit_field",
- "riscv-target",
-]
-
-[[package]]
-name = "riscv-target"
-version = "0.1.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "88aa938cda42a0cf62a20cfe8d139ff1af20c2e681212b5b34adb5a58333f222"
-dependencies = [
- "lazy_static",
- "regex",
-]
-
-[[package]]
name = "rkyv"
version = "0.7.39"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -719,27 +585,18 @@ dependencies = [
[[package]]
name = "rustc_version"
-version = "0.2.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a"
-dependencies = [
- "semver 0.9.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.14",
+ "semver",
]
[[package]]
name = "ryu"
-version = "1.0.11"
+version = "1.0.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4501abdff3ae82a1c1b477a17252eb69cee9e66eb915c1abaa4f44d873df9f09"
+checksum = "7b4b9743ed687d4b4bcedf9ff5eaa7398495ae14e61cba0a295704edbc7decde"
[[package]]
name = "same-file"
@@ -764,30 +621,15 @@ checksum = "1c107b6f4780854c8b126e228ea8869f4d7b71260f962fefb57b996b8959ba6b"
[[package]]
name = "semver"
-version = "0.9.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403"
-dependencies = [
- "semver-parser",
-]
-
-[[package]]
-name = "semver"
-version = "1.0.14"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e25dfac463d778e353db5be2449d1cce89bd6fd23c9f1ea21310ce6e5a1b29c4"
-
-[[package]]
-name = "semver-parser"
-version = "0.7.0"
+version = "1.0.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
+checksum = "58bc9567378fc7690d6b2addae4e60ac2eeea07becb2c64b9f218b53865cba2a"
[[package]]
name = "serde"
-version = "1.0.145"
+version = "1.0.152"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "728eb6351430bccb993660dfffc5a72f91ccc1295abaa8ce19b27ebe4f75568b"
+checksum = "bb7d1f0d3021d347a83e556fc4683dea2ea09d87bccdf88ff5c12545d89d5efb"
dependencies = [
"serde_derive",
]
@@ -804,9 +646,9 @@ dependencies = [
[[package]]
name = "serde_derive"
-version = "1.0.145"
+version = "1.0.152"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "81fa1584d3d1bcacd84c277a0dfe21f5b0f6accf4a23d04d4c6d61f1af522b4c"
+checksum = "af487d118eecd09402d70a5d72551860e788df87b464af30e5ea6a38c75c541e"
dependencies = [
"proc-macro2",
"quote",
@@ -815,11 +657,11 @@ dependencies = [
[[package]]
name = "serde_json"
-version = "1.0.85"
+version = "1.0.91"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e55a28e3aaef9d5ce0506d0a14dbba8054ddc7e499ef522dd8b26859ec9d4a44"
+checksum = "877c235533714907a8c2464236f5c4b2a17262ef1bd71f38f35ea592c8da6883"
dependencies = [
- "itoa 1.0.3",
+ "itoa 1.0.5",
"ryu",
"serde",
]
@@ -841,9 +683,9 @@ checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3"
[[package]]
name = "syn"
-version = "1.0.101"
+version = "1.0.107"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e90cde112c4b9690b8cbe810cba9ddd8bc1d7472e2cae317b69e9438c1cba7d2"
+checksum = "1f4064b5b16e03ae50984a5a8ed5d4f8803e6bc1fd170a3cda91a1be4b18e3f5"
dependencies = [
"proc-macro2",
"quote",
@@ -872,15 +714,6 @@ dependencies = [
]
[[package]]
-name = "tinystr"
-version = "0.6.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4dfb77d2490072fb5616d67686f55481b3d97701e383e208a7225843eba1aae6"
-dependencies = [
- "displaydoc",
-]
-
-[[package]]
name = "tinytemplate"
version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -892,9 +725,9 @@ dependencies = [
[[package]]
name = "unicode-ident"
-version = "1.0.4"
+version = "1.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dcc811dc4066ac62f84f11307873c4850cb653bfa9b1719cee2bd2204a4bc5dd"
+checksum = "84a22b9f218b40614adcb3f4ff08b703773ad44fa9423e4e0d346d5db86e4ebc"
[[package]]
name = "unicode-width"
@@ -909,33 +742,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c"
[[package]]
-name = "vcell"
-version = "0.1.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "77439c1b53d2303b20d9459b1ade71a83c716e3f9c34f3228c00e6f185d6c002"
-
-[[package]]
name = "version_check"
version = "0.9.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
[[package]]
-name = "void"
-version = "1.0.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d"
-
-[[package]]
-name = "volatile-register"
-version = "0.2.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9ee8f19f9d74293faf70901bc20ad067dc1ad390d2cbf1e3f75f721ffee908b6"
-dependencies = [
- "vcell",
-]
-
-[[package]]
name = "walkdir"
version = "2.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1048,16 +860,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
[[package]]
-name = "writeable"
-version = "0.4.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d8ab608ef0f68f7b5e1f17a38342cbc2725bf212f6ba9f103b0e05f675c41d83"
-
-[[package]]
name = "yoke"
-version = "0.6.1"
+version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "620cda8a59740b1e9313dad314848c6ffe15792c38cc4ac2def245ee77a6cae2"
+checksum = "222180af14a6b54ef2c33493c1eff77ae95a3687a21b243e752624006fb8f26e"
dependencies = [
"serde",
"stable_deref_trait",
@@ -1067,9 +873,9 @@ dependencies = [
[[package]]
name = "yoke-derive"
-version = "0.6.0"
+version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "58c2c5bb7c929b85c1b9ec69091b0d835f0878b4fd9eb67973b25936e06c4374"
+checksum = "ca800d73d6b7a7ee54f2608205c98b549fca71c9500c1abcb3abdc7708b4a8cb"
dependencies = [
"proc-macro2",
"quote",
@@ -1088,9 +894,9 @@ dependencies = [
[[package]]
name = "zerofrom-derive"
-version = "0.1.0"
+version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8785f47d6062c1932866147f91297286a9f350b3070e9d9f0b6078e37d623c1a"
+checksum = "2e8aa86add9ddbd2409c1ed01e033cd457d79b1b1229b64922c25095c595e829"
dependencies = [
"proc-macro2",
"quote",
diff --git a/vendor/litemap/Cargo.toml b/vendor/litemap/Cargo.toml
index 315056b05..01ee597a8 100644
--- a/vendor/litemap/Cargo.toml
+++ b/vendor/litemap/Cargo.toml
@@ -10,9 +10,9 @@
# See Cargo.toml.orig for the original contents.
[package]
-edition = "2018"
+edition = "2021"
name = "litemap"
-version = "0.6.0"
+version = "0.6.1"
authors = ["The ICU4X Project Developers"]
include = [
"src/**/*",
@@ -37,9 +37,15 @@ license = "Unicode-DFS-2016"
repository = "https://github.com/unicode-org/icu4x"
resolver = "2"
+[package.metadata.workspaces]
+independent = true
+
[package.metadata.docs.rs]
all-features = true
+[package.metadata.cargo-all-features]
+denylist = ["bench"]
+
[[example]]
name = "litemap_bincode"
path = "benches/bin/litemap_bincode.rs"
@@ -70,7 +76,7 @@ optional = true
default-features = false
[dependencies.yoke]
-version = "0.6.0"
+version = "0.7.0"
features = ["derive"]
optional = true
@@ -83,12 +89,6 @@ version = "0.6"
[dev-dependencies.criterion]
version = "0.3.4"
-[dev-dependencies.icu_benchmark_macros]
-version = "0.7"
-
-[dev-dependencies.icu_locid]
-version = "1.0.0-beta1"
-
[dev-dependencies.postcard]
version = "1.0.0"
features = ["use-std"]
diff --git a/vendor/litemap/benches/litemap.rs b/vendor/litemap/benches/litemap.rs
index bf005c4f8..353f03a86 100644
--- a/vendor/litemap/benches/litemap.rs
+++ b/vendor/litemap/benches/litemap.rs
@@ -39,7 +39,8 @@ const POSTCARD: [u8; 176] = [
105, 110, 101, 115, 101,
];
-/// Run this function to print new data to the console. Requires the optional `serde` feature.
+/// Run this function to print new data to the console.
+/// Requires the optional `serde` Cargo feature.
#[allow(dead_code)]
fn generate() {
let map = build_litemap(false);
@@ -69,13 +70,13 @@ fn overview_bench(c: &mut Criterion) {
fn build_litemap(large: bool) -> LiteMap<String, String> {
let mut map: LiteMap<String, String> = LiteMap::new();
- for (key, value) in DATA.iter() {
+ for (key, value) in DATA.into_iter() {
if large {
for n in 0..8192 {
- map.insert(format!("{}{}", key, n), value.to_string());
+ map.insert(format!("{}{}", key, n), value.to_owned());
}
} else {
- map.insert(key.to_string(), value.to_string());
+ map.insert(key.to_owned(), value.to_owned());
}
}
map
@@ -85,7 +86,7 @@ fn bench_deserialize(c: &mut Criterion) {
c.bench_function("litemap/deserialize/small", |b| {
b.iter(|| {
let map: LiteMap<String, String> = postcard::from_bytes(black_box(&POSTCARD)).unwrap();
- assert_eq!(map.get("iu"), Some(&"Inuktitut".to_string()));
+ assert_eq!(map.get("iu"), Some(&"Inuktitut".to_owned()));
})
});
}
@@ -95,7 +96,7 @@ fn bench_deserialize_large(c: &mut Criterion) {
c.bench_function("litemap/deseralize/large", |b| {
b.iter(|| {
let map: LiteMap<String, String> = postcard::from_bytes(black_box(&buf)).unwrap();
- assert_eq!(map.get("iu3333"), Some(&"Inuktitut".to_string()));
+ assert_eq!(map.get("iu3333"), Some(&"Inuktitut".to_owned()));
});
});
}
@@ -104,7 +105,7 @@ fn bench_lookup(c: &mut Criterion) {
let map: LiteMap<String, String> = postcard::from_bytes(&POSTCARD).unwrap();
c.bench_function("litemap/lookup/small", |b| {
b.iter(|| {
- assert_eq!(map.get(black_box("iu")), Some(&"Inuktitut".to_string()));
+ assert_eq!(map.get(black_box("iu")), Some(&"Inuktitut".to_owned()));
assert_eq!(map.get(black_box("zz")), None);
});
});
@@ -115,7 +116,7 @@ fn bench_lookup_large(c: &mut Criterion) {
let map: LiteMap<String, String> = postcard::from_bytes(&buf).unwrap();
c.bench_function("litemap/lookup/large", |b| {
b.iter(|| {
- assert_eq!(map.get(black_box("iu3333")), Some(&"Inuktitut".to_string()));
+ assert_eq!(map.get(black_box("iu3333")), Some(&"Inuktitut".to_owned()));
assert_eq!(map.get(black_box("zz")), None);
});
});
diff --git a/vendor/litemap/src/map.rs b/vendor/litemap/src/map.rs
index f86383337..669dc464d 100644
--- a/vendor/litemap/src/map.rs
+++ b/vendor/litemap/src/map.rs
@@ -135,8 +135,8 @@ where
/// let mut map = LiteMap::new_vec();
/// map.insert(1, "one");
/// map.insert(2, "two");
- /// assert_eq!(map.contains_key(&1), true);
- /// assert_eq!(map.contains_key(&3), false);
+ /// assert!(map.contains_key(&1));
+ /// assert!(!map.contains_key(&3));
/// ```
pub fn contains_key<Q: ?Sized>(&self, key: &Q) -> bool
where
diff --git a/vendor/litemap/src/store/mod.rs b/vendor/litemap/src/store/mod.rs
index e4ba6f7b9..7f4386783 100644
--- a/vendor/litemap/src/store/mod.rs
+++ b/vendor/litemap/src/store/mod.rs
@@ -18,7 +18,7 @@
//! - [`StoreIterable`] for methods that return iterators
//! - [`StoreFromIterator`] to enable `FromIterator` for LiteMap
//!
-//! To test your implementation, enable the `"testing"` feature and use [`check_store()`].
+//! To test your implementation, enable the `"testing"` Cargo feature and use [`check_store()`].
//!
//! [`check_store()`]: crate::testing::check_store
diff --git a/vendor/litemap/tests/rkyv.rs b/vendor/litemap/tests/rkyv.rs
index 2d6438dc7..7ab1eb3f5 100644
--- a/vendor/litemap/tests/rkyv.rs
+++ b/vendor/litemap/tests/rkyv.rs
@@ -41,17 +41,14 @@ type LiteMapOfStrings = LiteMap<String, String>;
type TupleVecOfStrings = Vec<(String, String)>;
fn generate() -> AlignedVec {
- let mut map: LiteMapOfStrings = LiteMap::new();
- for (lang, name) in DATA.iter() {
- map.try_append(lang.to_string(), name.to_string())
- .ok_or(())
- .unwrap_err();
- }
- let tuple_vec = map.into_tuple_vec();
+ let map = DATA
+ .iter()
+ .map(|&(k, v)| (k.to_owned(), v.to_owned()))
+ .collect::<LiteMapOfStrings>();
let mut serializer = AllocSerializer::<4096>::default();
serializer
- .serialize_value(&tuple_vec)
+ .serialize_value(&map.into_tuple_vec())
.expect("failed to archive test");
serializer.into_serializer().into_inner()
}
@@ -82,5 +79,5 @@ fn rkyv_deserialize() {
let deserialized = archived.deserialize(&mut Infallible).unwrap();
// Safe because we are deserializing a buffer from a trusted source
let deserialized: LiteMapOfStrings = LiteMap::from_sorted_store_unchecked(deserialized);
- assert_eq!(deserialized.get("tr"), Some(&"Turkish".to_string()));
+ assert_eq!(deserialized.get("tr").map(String::as_str), Some("Turkish"));
}
diff --git a/vendor/lsp-types/.cargo-checksum.json b/vendor/lsp-types/.cargo-checksum.json
index fe0d2bb53..a3fa12007 100644
--- a/vendor/lsp-types/.cargo-checksum.json
+++ b/vendor/lsp-types/.cargo-checksum.json
@@ -1 +1 @@
-{"files":{"CHANGELOG.md":"fb3c66afb33dcad9d43aa5cb5e34de28ab8dcecdcef4f449ec5a4a5ad9a045cf","Cargo.toml":"3fa7da96cf40b1b3ba29a479dc428f2c43ecb3fd6e78bf3987639730dc96fa8f","LICENSE":"a11232911aa0d746688b560af367728021184084eeb6328a1922d60925c5eda0","README.md":"6814882daa9018d1d99ebdb7861d9759b3c96f976683fabfc8f4b9c9a05b032a","release.sh":"3bfea9a6cd08e825f3247a868338f3844d7f72f4342671898a6326a5df3c4e42","release.toml":"d4f0fecf904b64d9fc9babd3afeff77d3c102d8555b43ef83902c143e3becf16","src/call_hierarchy.rs":"a64967af04133a9c08838db19d2de665d2062ed294f6ca7d1d97edb49dc4096f","src/code_action.rs":"78813e0095a78e89a74d897e8dcb5876e1e1480c5e9e37d6f2fb22fdaecb6045","src/code_lens.rs":"169cc96d4ee9690d0e2e119aee7949006f0123c4a6b919bf7ac484258c93fa95","src/color.rs":"72846c6cda18691f5f9eaa29cb8df87bb4a10ae4e0803916244b250c68dc7701","src/completion.rs":"96681827c185732730e6b352e6259430a0585f92e34ff446b43b8d36e366a6db","src/document_highlight.rs":"491aad4beeb72ecc986d9f4cb43202d440304df3be861c41ab4e892b129212b5","src/document_link.rs":"8aab0d78081aa624290c712bacd30215553e7f0f99b300d3fefd103179fdfad0","src/document_symbols.rs":"063c29bf761c17f6f55c6812da0aad4a6aa04c6db3efbb6ca01b646b7757aabe","src/error_codes.rs":"60d4a1d00e797fe3f3f2c5ffd11be7fbaad82f4fc247ff98285566d6b777f0f7","src/file_operations.rs":"bfc413d4bbfd311c7a178863961e6cde6e8cc7a654370b3848ffd64941fea82a","src/folding_range.rs":"3dc85496b6f5b8c11f3a57f888c2febdac71c997010b13eec34736b29fb86965","src/formatting.rs":"548df3c2da1dec8a3a578b381249b6812f92e73c22257459653980492b21a2a2","src/hover.rs":"fece13f93144dfea0b3c3204f19fc7fc366b25a614515825a20a2596c88966c8","src/inlay_hint.rs":"26671f81e045b3dcca6af3222fd3d8095f061e46b8ff7fc738b6f481a0b631d4","src/lib.rs":"0c990f697238cf37f11fcbb3bc20690a90a0aaaed427d79bdbae3ffda0d38c3f","src/linked_editing.rs":"a840ee445fbcfe32e37191197fb37b19732260462a73cc4ba350b8d9a2c4e607","src/lsif.rs":"c3966583d9b0afc64e93d301c8e20f84ba875ffb6b5d4bbacf4ca4a12cc58e99","src/moniker.rs":"8d8c37daca1d2504c74c17e7195969efcfb42641392026a8e507490adf49d043","src/notification.rs":"67e831168d9e7898965d83a503a33ac10f36561bcdb07195f99769f8ff00340c","src/progress.rs":"2b2189b094fbe7b790a0895f96c29615b9375538760d413413c47ce882af2007","src/references.rs":"e824f6861f67c66af04f8f08afc174793a9662a0a67cc23ccd5240ac0d408212","src/rename.rs":"2980e9452a27868a972fc09d52ac7c000361be9f1efc2de4e20c9b99100010c8","src/request.rs":"3abac2c2390c82bf89180b1305984db2986c5bc716ae9f5dbbd0af0a783ab0f7","src/selection_range.rs":"238b14ba6ac2e45ec66fea32d8ebe5f1d235bde9bc69777a794e10d519bcac9c","src/semantic_tokens.rs":"e6af4475567efb67df53b756bb9b0c5d469f83ea0eba863209e4c151f8c60704","src/signature_help.rs":"02d6c70a6c803badd22a8a474233d1be0b169eb39a6ae668f744dcaee71045ab","src/trace.rs":"81ca45bf188452d074cb879060a88f6d6ec087d6e31e29c37db542fdb5363f5c","src/window.rs":"b380ed57b4a700514ec043310253f3fc57c51d35df18fff8283b685ee8aa17d2","src/workspace_folders.rs":"79b75c1d75a1d57892d515efd8a5cbf7c8fddce1b49dc7dfbd94e685b30fce27","src/workspace_symbols.rs":"a1f18eecc09c352b342c5cc011805457eb836432d5b8688dd2e447ac9bda407a","tests/lsif.rs":"89c7c7fa06a8b108f7519a9860d0e2a049ac66d35db3630697f2f33038513898","tests/tsc-unix.lsif":"5a85759de361285d806c8147cfc9f9cb5235a6a2253bacd8243174713419facd"},"package":"9be6e9c7e2d18f651974370d7aff703f9513e0df6e464fd795660edc77e6ca51"} \ No newline at end of file
+{"files":{"CHANGELOG.md":"a404456dd81ff6bd6aacece55d460556fd5f923db0103d8a3d395761cb2fb2c2","Cargo.toml":"2fb86fa2dd87571fb8e625b68ada491b3c44aa7c2c3a1b739773664d50b44bf3","LICENSE":"005b90a7238f92fd39eaef0b4329a47e1cab351958d9e9bbed9b9c60b76bb2bb","README.md":"aa7b801527c8ed7d06285e86ea1ab224d4f314937631fa390fbcd5558088636e","release.sh":"a8f3c599bdb68a5fa47ec50b6d056ad8b0dcd6dda94b7fc9a7a1899ef4b86c1e","release.toml":"b5c002516befc380e4bf3712b06470fb74689cb0fb9fadb8a36478c596fe621a","src/call_hierarchy.rs":"31567e72d30c3939eb68fb492b6781e31ed0da56bbb4179e3176222f66bb1357","src/code_action.rs":"ace85a0ee6a3735d91d6c7c63ccb23fea8f1c22e0997337ea7fcdb0d235e5859","src/code_lens.rs":"6f0586b780950854d3c1ffbed414d1d9db8a111480f2e99132b4520d0b3a8f07","src/color.rs":"60549c5b20bcc87c954da32c58b00856ac4ab2b1a8b42fed0225d451d7c2f274","src/completion.rs":"3b2a72e3c8d709bd1b0c80035783502e647fd6da205376ecee7afa770e45f061","src/document_highlight.rs":"83c531ba4087538145fc7ff7d3e19bfc8e38441895f885296ea9e0925484dbd0","src/document_link.rs":"ef5ea30b8e761365cdf34666432567d9e5baf08469c4e4d9a51b5a500ffee4b7","src/document_symbols.rs":"fc1097290f9704550f75703524258c121484a9091284065c5318305f67179339","src/error_codes.rs":"06380abbd2970756a6f5c68ed4a47a9226403710b1beb014a790fffb23f6bdf1","src/file_operations.rs":"049b37d961522befc2df6df7f8172d4a122969c87873d4b9750746c46589db66","src/folding_range.rs":"f38500fbd7fa92b4b97c6092b2a2b4ca8649ad09a5a4ef7c532c551d7f70b872","src/formatting.rs":"79d8579fea1f582a4e09f1a63dacf5e504d41ce835a3a9de2ffe9d2ca9b4d686","src/hover.rs":"9feddaed11504a11f8d9cad5733ed3006c04300c2d75c8baee170ec0d68c14f5","src/inlay_hint.rs":"f5ee63e0e4c3c5877620d4c3d2942c8070bed66b6aeace6c2f7578084ff2a9ba","src/inline_value.rs":"34499bb445526b70ff370d507b098439f918b4007663761398af0b7c77d781bb","src/lib.rs":"ded25d5e58499d7e4e2f11665fde4d196fb80f85eee8939c6e8237c7e5019786","src/linked_editing.rs":"1a010996ff20012be72e2c611e5eb57d22f37a969216be4e6fc7b62c4281971e","src/lsif.rs":"747b9552ca4065fb56b887e9f40df8e8cc2502c68ffd305e0d9ca44eae377622","src/moniker.rs":"d59c8ce30f3babd86a7e3f0eac680be5111bf47e879f514afc3d894ddc874fe8","src/notification.rs":"c00b675ae519271827d15e9a8569b55e11233bd4db362110b98fccf65c00b68a","src/progress.rs":"2aaa8f5fb0cb14deb17b09ee29bc092f00ba23024fb0ec81138bb72abea91e4c","src/references.rs":"8d2d3b4622f680343da3622156df656495b3fa67ca4f3f6ecf673e77ec4d2cb8","src/rename.rs":"3f5f1106e9c926c09dadee03c1118e332c5e4fb59c0a71c7bb43800a6322c5bd","src/request.rs":"1a4703fecf7c459a6ed4f13658ecdeca44a2bb42a634e2077c183bb0f54fdc4d","src/selection_range.rs":"7e5d3cd207810f2a2f266960569d5b0adb3aff939b9b9aa0721c91f106a9f6e6","src/semantic_tokens.rs":"9cba9968aebd931de3e31d31564d0bc2c79a1bf28ac4b761b8cc59f3193326fa","src/signature_help.rs":"93440d96f04c01cd81ba13b0b7cb5859a4e8698a7007022f811d300f77090281","src/trace.rs":"338aa8faa6b8cec523d5d8bd08ad87f7a76fca7df64e2db6b2139a879f68bffd","src/type_hierarchy.rs":"d134db897e7cc8c3fb7b494ca8c36547421c46df780e63186d2bfcbac386a866","src/window.rs":"34b9e49217a44f2098708a4d256bab1ffafa13da8d7268fe9a234f427ab40525","src/workspace_folders.rs":"006216c7e0f8b3c50fab89c18231a4d08bf0994d1d8097564d6c1bec882f2975","src/workspace_symbols.rs":"48c9edfbb87b105925d1cd0956f456faa2b289fea7f7ebe85b0739170796b162","tests/lsif.rs":"075ebcdc8bbad2172fdeb72ce41656822e13153ef7b72bfed0b5cceba84fa090","tests/tsc-unix.lsif":"a6b171427afa74a648b0c633272958506ea7cf690b7ab8ba2548229fffd9c403"},"package":"0b63735a13a1f9cd4f4835223d828ed9c2e35c8c5e61837774399f558b6a1237"} \ No newline at end of file
diff --git a/vendor/lsp-types/CHANGELOG.md b/vendor/lsp-types/CHANGELOG.md
index 35655f7fc..584b8ec8b 100644
--- a/vendor/lsp-types/CHANGELOG.md
+++ b/vendor/lsp-types/CHANGELOG.md
@@ -1,289 +1,295 @@
-<a name="v0.93.2"></a>
-### v0.93.2 (2022-10-21)
-
-
-
-
-<a name="v0.93.1"></a>
-### v0.93.1 (2022-08-23)
-
-
-
-
-<a name="v0.93.0"></a>
-## v0.93.0 (2022-04-08)
-
-
-#### Features
-
-* **helperTypes:** implement new JSON types ([bd9bb2e7](https://github.com/gluon-lang/lsp-types/commit/bd9bb2e74171b0194be51085c822c3ccbbb68b7b))
-
-
-
-<a name="v0.92.1"></a>
-### v0.92.1 (2022-03-21)
-
-
-#### Bug Fixes
-
-* **inlayHint:** typo in prop name ([7f7ada31](https://github.com/gluon-lang/lsp-types/commit/7f7ada310fa045ef628dc36f97b8564408fcec6a))
-
-#### Features
-
-* **inlayHint:**
- * add request impls ([393aefa1](https://github.com/gluon-lang/lsp-types/commit/393aefa18b3c900c3f1ac8f6337b7098bdc4365a))
- * add inlayHint provider ([69f21e71](https://github.com/gluon-lang/lsp-types/commit/69f21e714df305643aa727cbf745b439bbd8c112))
- * implement inlayHint basic types ([29a50e71](https://github.com/gluon-lang/lsp-types/commit/29a50e71461f72d2fa2aea90fa03f61adf062074))
-
-
-
-<a name="v0.92.0"></a>
-## v0.92.0 (2022-02-07)
-
-
-
-
-<a name="v0.91.2"></a>
-### v0.91.2 (2022-02-07)
-
-
-#### Features
-
-* Add a TryFrom<&str> implementation for enumerations ([19b85cf4](https://github.com/gluon-lang/lsp-types/commit/19b85cf4a7b5396a89d364e271c3867eb6c840e4), closes [#223](https://github.com/gluon-lang/lsp-types/issues/223))
-
-#### Bug Fixes
-
-* Ensure that the pascal_case_name is evaluated at compile time ([7337535b](https://github.com/gluon-lang/lsp-types/commit/7337535b79000912f859319455cd371af77d1899))
-
-
-
-<a name="v0.91.1"></a>
-### v0.91.1 (2021-11-01)
-
-
-#### Features
-
-* Print the name of know enumerations ([2877b6a1](https://github.com/gluon-lang/lsp-types/commit/2877b6a131ef5c28310b972126f6d1b23cd97788))
-
-
-
-<a name="v0.91.0"></a>
-## v0.91.0 (2021-10-18)
-
-
-
-
-<a name="v0.90.1"></a>
-### v0.90.1 (2021-10-11)
-
-
-#### Bug Fixes
-
-* add missing rename_all serde attribute ([b403cba5](https://github.com/gluon-lang/lsp-types/commit/b403cba5fb568f7f1bda3ea2929822269797f7f3))
-
-
-
-<a name="v0.90.1"></a>
-### v0.90.1 (2021-10-11)
-
-
-#### Bug Fixes
-
-* add missing rename_all serde attribute ([b403cba5](https://github.com/gluon-lang/lsp-types/commit/b403cba5fb568f7f1bda3ea2929822269797f7f3))
-
-
-
-<a name="v0.90.1"></a>
-### v0.90.1 (2021-10-11)
-
-
-#### Bug Fixes
-
-* add missing rename_all serde attribute ([b403cba5](https://github.com/gluon-lang/lsp-types/commit/b403cba5fb568f7f1bda3ea2929822269797f7f3))
-
-
-
-<a name="v0.90.1"></a>
-### v0.90.1 (2021-10-11)
-
-
-#### Bug Fixes
-
-* add missing rename_all serde attribute ([b403cba5](https://github.com/gluon-lang/lsp-types/commit/b403cba5fb568f7f1bda3ea2929822269797f7f3))
-
-
-
-<a name="v0.90.0"></a>
-## v0.90.0 (2021-09-25)
-
-
-
-
-<a name="v0.61.1"></a>
-### v0.61.1 (2021-06-10)
-
-
-#### Features
-
-* Add DeserializeOwned + Serialize bounds on request/notifications ([fb945a93](https://github.com/gluon-lang/lsp-types/commit/fb945a9347b353dd9bc5aab99a86731bebd94c15), closes [#140](https://github.com/gluon-lang/lsp-types/issues/140))
-
-
-
-<a name="v0.89.1"></a>
-### v0.89.1 (2021-05-22)
-
-
-
-
-<a name="v0.89.0"></a>
-## v0.89.0 (2021-04-07)
-
-
-
-
-<a name="v0.88.0"></a>
-## v0.88.0 (2021-02-16)
-
-
-
-
-<a name="v0.87.0"></a>
-## v0.87.0 (2021-02-14)
-
-
-
-
-<a name="v0.86.0"></a>
-## v0.86.0 (2020-12-17)
-
-
-
-
-<a name="v0.85.0"></a>
-## v0.85.0 (2020-12-01)
-
-
-
-
-<a name="v0.84.0"></a>
-## v0.84.0 (2020-11-24)
-
-
-
-
-<a name="v0.83.1"></a>
-### v0.83.1 (2020-11-16)
-
-
-
-
-<a name="v0.82.0"></a>
-## v0.82.0 (2020-09-23)
-
-
-
-
-<a name="v0.80.0"></a>
-## v0.80.0 (2020-09-18)
-
-
-
-
-<a name="v0.80.0"></a>
-## v0.80.0 (2020-09-02)
-
-
-
-
-<a name="v0.79.0"></a>
-## v0.79.0 (2020-07-26)
-
-
-
-
-<a name="v0.77.0"></a>
-## v0.77.0 (2020-07-15)
-
-
-
-
-<a name="v0.76.1"></a>
-### v0.76.1 (2020-07-14)
-
-
-
-
-<a name="v0.74.2"></a>
-### v0.74.2 (2020-05-30)
-
-
-
-
-<a name="v0.74.1"></a>
-### v0.74.1 (2020-05-01)
-
-
-
-
-<a name="v0.74.0"></a>
-## v0.74.0 (2020-04-26)
-
-
-
-
-<a name="v0.74.0"></a>
-## v0.74.0 (2020-04-26)
-
-
-
-
-<a name="v0.72.0"></a>
-## v0.72.0 (2020-03-02)
-
-
-#### Features
-
-* Add DeserializeOwned + Serialize bounds on request/notifications ([fb945a93](https://github.com/gluon-lang/lsp-types/commit/fb945a9347b353dd9bc5aab99a86731bebd94c15), closes [#140](https://github.com/gluon-lang/lsp-types/issues/140))
-
-
-
-<a name="v0.72.0"></a>
-## v0.72.0 (2020-03-02)
-
-
-#### Features
-
-* Add DeserializeOwned + Serialize bounds on request/notifications ([fb945a93](https://github.com/gluon-lang/lsp-types/commit/fb945a9347b353dd9bc5aab99a86731bebd94c15), closes [#140](https://github.com/gluon-lang/lsp-types/issues/140))
-
-
-
-<a name="v0.72.0"></a>
-## v0.72.0 (2020-03-02)
-
-
-#### Features
-
-* Add DeserializeOwned + Serialize bounds on request/notifications ([fb945a93](https://github.com/gluon-lang/lsp-types/commit/fb945a9347b353dd9bc5aab99a86731bebd94c15), closes [#140](https://github.com/gluon-lang/lsp-types/issues/140))
-
-
-
-<a name="v0.72.0"></a>
-## v0.72.0 (2020-03-02)
-
-
-#### Features
-
-* Add DeserializeOwned + Serialize bounds on request/notifications ([fb945a93](https://github.com/gluon-lang/lsp-types/commit/fb945a9347b353dd9bc5aab99a86731bebd94c15), closes [#140](https://github.com/gluon-lang/lsp-types/issues/140))
-
-
-
-<a name="v0.72.0"></a>
-## v0.72.0 (2020-03-02)
-
-
-#### Features
-
-* Add DeserializeOwned + Serialize bounds on request/notifications ([fb945a93](https://github.com/gluon-lang/lsp-types/commit/fb945a9347b353dd9bc5aab99a86731bebd94c15), closes [#140](https://github.com/gluon-lang/lsp-types/issues/140))
-
-
-
+<a name="v0.94.0"></a>
+## v0.94.0 (2023-02-08)
+
+
+
+
+<a name="v0.93.2"></a>
+### v0.93.2 (2022-10-21)
+
+
+
+
+<a name="v0.93.1"></a>
+### v0.93.1 (2022-08-23)
+
+
+
+
+<a name="v0.93.0"></a>
+## v0.93.0 (2022-04-08)
+
+
+#### Features
+
+* **helperTypes:** implement new JSON types ([bd9bb2e7](https://github.com/gluon-lang/lsp-types/commit/bd9bb2e74171b0194be51085c822c3ccbbb68b7b))
+
+
+
+<a name="v0.92.1"></a>
+### v0.92.1 (2022-03-21)
+
+
+#### Bug Fixes
+
+* **inlayHint:** typo in prop name ([7f7ada31](https://github.com/gluon-lang/lsp-types/commit/7f7ada310fa045ef628dc36f97b8564408fcec6a))
+
+#### Features
+
+* **inlayHint:**
+ * add request impls ([393aefa1](https://github.com/gluon-lang/lsp-types/commit/393aefa18b3c900c3f1ac8f6337b7098bdc4365a))
+ * add inlayHint provider ([69f21e71](https://github.com/gluon-lang/lsp-types/commit/69f21e714df305643aa727cbf745b439bbd8c112))
+ * implement inlayHint basic types ([29a50e71](https://github.com/gluon-lang/lsp-types/commit/29a50e71461f72d2fa2aea90fa03f61adf062074))
+
+
+
+<a name="v0.92.0"></a>
+## v0.92.0 (2022-02-07)
+
+
+
+
+<a name="v0.91.2"></a>
+### v0.91.2 (2022-02-07)
+
+
+#### Features
+
+* Add a TryFrom<&str> implementation for enumerations ([19b85cf4](https://github.com/gluon-lang/lsp-types/commit/19b85cf4a7b5396a89d364e271c3867eb6c840e4), closes [#223](https://github.com/gluon-lang/lsp-types/issues/223))
+
+#### Bug Fixes
+
+* Ensure that the pascal_case_name is evaluated at compile time ([7337535b](https://github.com/gluon-lang/lsp-types/commit/7337535b79000912f859319455cd371af77d1899))
+
+
+
+<a name="v0.91.1"></a>
+### v0.91.1 (2021-11-01)
+
+
+#### Features
+
+* Print the name of know enumerations ([2877b6a1](https://github.com/gluon-lang/lsp-types/commit/2877b6a131ef5c28310b972126f6d1b23cd97788))
+
+
+
+<a name="v0.91.0"></a>
+## v0.91.0 (2021-10-18)
+
+
+
+
+<a name="v0.90.1"></a>
+### v0.90.1 (2021-10-11)
+
+
+#### Bug Fixes
+
+* add missing rename_all serde attribute ([b403cba5](https://github.com/gluon-lang/lsp-types/commit/b403cba5fb568f7f1bda3ea2929822269797f7f3))
+
+
+
+<a name="v0.90.1"></a>
+### v0.90.1 (2021-10-11)
+
+
+#### Bug Fixes
+
+* add missing rename_all serde attribute ([b403cba5](https://github.com/gluon-lang/lsp-types/commit/b403cba5fb568f7f1bda3ea2929822269797f7f3))
+
+
+
+<a name="v0.90.1"></a>
+### v0.90.1 (2021-10-11)
+
+
+#### Bug Fixes
+
+* add missing rename_all serde attribute ([b403cba5](https://github.com/gluon-lang/lsp-types/commit/b403cba5fb568f7f1bda3ea2929822269797f7f3))
+
+
+
+<a name="v0.90.1"></a>
+### v0.90.1 (2021-10-11)
+
+
+#### Bug Fixes
+
+* add missing rename_all serde attribute ([b403cba5](https://github.com/gluon-lang/lsp-types/commit/b403cba5fb568f7f1bda3ea2929822269797f7f3))
+
+
+
+<a name="v0.90.0"></a>
+## v0.90.0 (2021-09-25)
+
+
+
+
+<a name="v0.61.1"></a>
+### v0.61.1 (2021-06-10)
+
+
+#### Features
+
+* Add DeserializeOwned + Serialize bounds on request/notifications ([fb945a93](https://github.com/gluon-lang/lsp-types/commit/fb945a9347b353dd9bc5aab99a86731bebd94c15), closes [#140](https://github.com/gluon-lang/lsp-types/issues/140))
+
+
+
+<a name="v0.89.1"></a>
+### v0.89.1 (2021-05-22)
+
+
+
+
+<a name="v0.89.0"></a>
+## v0.89.0 (2021-04-07)
+
+
+
+
+<a name="v0.88.0"></a>
+## v0.88.0 (2021-02-16)
+
+
+
+
+<a name="v0.87.0"></a>
+## v0.87.0 (2021-02-14)
+
+
+
+
+<a name="v0.86.0"></a>
+## v0.86.0 (2020-12-17)
+
+
+
+
+<a name="v0.85.0"></a>
+## v0.85.0 (2020-12-01)
+
+
+
+
+<a name="v0.84.0"></a>
+## v0.84.0 (2020-11-24)
+
+
+
+
+<a name="v0.83.1"></a>
+### v0.83.1 (2020-11-16)
+
+
+
+
+<a name="v0.82.0"></a>
+## v0.82.0 (2020-09-23)
+
+
+
+
+<a name="v0.80.0"></a>
+## v0.80.0 (2020-09-18)
+
+
+
+
+<a name="v0.80.0"></a>
+## v0.80.0 (2020-09-02)
+
+
+
+
+<a name="v0.79.0"></a>
+## v0.79.0 (2020-07-26)
+
+
+
+
+<a name="v0.77.0"></a>
+## v0.77.0 (2020-07-15)
+
+
+
+
+<a name="v0.76.1"></a>
+### v0.76.1 (2020-07-14)
+
+
+
+
+<a name="v0.74.2"></a>
+### v0.74.2 (2020-05-30)
+
+
+
+
+<a name="v0.74.1"></a>
+### v0.74.1 (2020-05-01)
+
+
+
+
+<a name="v0.74.0"></a>
+## v0.74.0 (2020-04-26)
+
+
+
+
+<a name="v0.74.0"></a>
+## v0.74.0 (2020-04-26)
+
+
+
+
+<a name="v0.72.0"></a>
+## v0.72.0 (2020-03-02)
+
+
+#### Features
+
+* Add DeserializeOwned + Serialize bounds on request/notifications ([fb945a93](https://github.com/gluon-lang/lsp-types/commit/fb945a9347b353dd9bc5aab99a86731bebd94c15), closes [#140](https://github.com/gluon-lang/lsp-types/issues/140))
+
+
+
+<a name="v0.72.0"></a>
+## v0.72.0 (2020-03-02)
+
+
+#### Features
+
+* Add DeserializeOwned + Serialize bounds on request/notifications ([fb945a93](https://github.com/gluon-lang/lsp-types/commit/fb945a9347b353dd9bc5aab99a86731bebd94c15), closes [#140](https://github.com/gluon-lang/lsp-types/issues/140))
+
+
+
+<a name="v0.72.0"></a>
+## v0.72.0 (2020-03-02)
+
+
+#### Features
+
+* Add DeserializeOwned + Serialize bounds on request/notifications ([fb945a93](https://github.com/gluon-lang/lsp-types/commit/fb945a9347b353dd9bc5aab99a86731bebd94c15), closes [#140](https://github.com/gluon-lang/lsp-types/issues/140))
+
+
+
+<a name="v0.72.0"></a>
+## v0.72.0 (2020-03-02)
+
+
+#### Features
+
+* Add DeserializeOwned + Serialize bounds on request/notifications ([fb945a93](https://github.com/gluon-lang/lsp-types/commit/fb945a9347b353dd9bc5aab99a86731bebd94c15), closes [#140](https://github.com/gluon-lang/lsp-types/issues/140))
+
+
+
+<a name="v0.72.0"></a>
+## v0.72.0 (2020-03-02)
+
+
+#### Features
+
+* Add DeserializeOwned + Serialize bounds on request/notifications ([fb945a93](https://github.com/gluon-lang/lsp-types/commit/fb945a9347b353dd9bc5aab99a86731bebd94c15), closes [#140](https://github.com/gluon-lang/lsp-types/issues/140))
+
+
+
diff --git a/vendor/lsp-types/Cargo.toml b/vendor/lsp-types/Cargo.toml
index fa39192e8..46a883b36 100644
--- a/vendor/lsp-types/Cargo.toml
+++ b/vendor/lsp-types/Cargo.toml
@@ -12,7 +12,7 @@
[package]
edition = "2018"
name = "lsp-types"
-version = "0.93.2"
+version = "0.94.0"
authors = [
"Markus Westerlind <marwes91@gmail.com>",
"Bruno Medeiros <bruno.do.medeiros@gmail.com>",
@@ -29,7 +29,6 @@ keywords = [
]
license = "MIT"
repository = "https://github.com/gluon-lang/lsp-types"
-resolver = "1"
[dependencies.bitflags]
version = "1.0.1"
diff --git a/vendor/lsp-types/LICENSE b/vendor/lsp-types/LICENSE
index 32781d976..968950bbb 100644
--- a/vendor/lsp-types/LICENSE
+++ b/vendor/lsp-types/LICENSE
@@ -1,22 +1,22 @@
-The MIT License (MIT)
-
-Copyright (c) 2016 Markus Westerlind
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-THE SOFTWARE.
-
+The MIT License (MIT)
+
+Copyright (c) 2016 Markus Westerlind
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+
diff --git a/vendor/lsp-types/README.md b/vendor/lsp-types/README.md
index d46701166..86203e609 100644
--- a/vendor/lsp-types/README.md
+++ b/vendor/lsp-types/README.md
@@ -1,14 +1,14 @@
-# lsp-types [![Build Status](https://travis-ci.org/gluon-lang/lsp-types.svg?branch=master)](https://travis-ci.org/gluon-lang/lsp-types) [![Documentation](https://docs.rs/lsp-types/badge.svg)](https://docs.rs/crate/lsp-types)
-
-Types useful for interacting with a [language server](https://code.visualstudio.com/blogs/2016/06/27/common-language-protocol).
-
-Supports Language Server Protocol (LSP) version 3.16.0.
-
-Proposed 3.17 features can be activated using the `proposed` feature flag.
-- **NOTE** that these are unstable and may change between releases.
-
-## Links
-
-[Stable Protocol reference](https://github.com/microsoft/language-server-protocol/blob/gh-pages/_specifications/specification-3-16.md)
-
-[Proposed Protocol reference](https://github.com/microsoft/language-server-protocol/blob/gh-pages/_specifications/lsp/3.17/specification.md)
+# lsp-types [![Build Status](https://travis-ci.org/gluon-lang/lsp-types.svg?branch=master)](https://travis-ci.org/gluon-lang/lsp-types) [![Documentation](https://docs.rs/lsp-types/badge.svg)](https://docs.rs/crate/lsp-types)
+
+Types useful for interacting with a [language server](https://code.visualstudio.com/blogs/2016/06/27/common-language-protocol).
+
+Supports Language Server Protocol (LSP) version 3.16.0.
+
+Proposed 3.17 features can be activated using the `proposed` feature flag.
+- **NOTE** that these are unstable and may change between releases.
+
+## Links
+
+[Stable Protocol reference](https://github.com/microsoft/language-server-protocol/tree/gh-pages/_specifications/lsp/3.17/specification.md)
+
+[Proposed Protocol reference](https://github.com/microsoft/language-server-protocol/blob/gh-pages/_specifications/lsp/3.18/specification.md)
diff --git a/vendor/lsp-types/release.sh b/vendor/lsp-types/release.sh
index 68e484455..642c5ec0d 100755..100644
--- a/vendor/lsp-types/release.sh
+++ b/vendor/lsp-types/release.sh
@@ -1,15 +1,15 @@
-#!/bin/sh
-set -ex
-
-LEVEL=$1
-if [ -z "$LEVEL" ]; then
- echo "Expected patch, minor or major"
- exit 1
-fi
-
-clog --$LEVEL
-
-git add CHANGELOG.md
-git commit -m "Update changelog"
-
-cargo release $LEVEL --execute
+#!/bin/sh
+set -ex
+
+LEVEL=$1
+if [ -z "$LEVEL" ]; then
+ echo "Expected patch, minor or major"
+ exit 1
+fi
+
+clog --$LEVEL
+
+git add CHANGELOG.md
+git commit -m "Update changelog"
+
+cargo release $LEVEL --execute
diff --git a/vendor/lsp-types/release.toml b/vendor/lsp-types/release.toml
index b4a3d205e..a1d785e19 100644
--- a/vendor/lsp-types/release.toml
+++ b/vendor/lsp-types/release.toml
@@ -1,2 +1 @@
-dev-version = false
-tag-message = "Version {{version}}"
+tag-message = "Version {{version}}"
diff --git a/vendor/lsp-types/src/call_hierarchy.rs b/vendor/lsp-types/src/call_hierarchy.rs
index 21d3ec462..e59f0d00b 100644
--- a/vendor/lsp-types/src/call_hierarchy.rs
+++ b/vendor/lsp-types/src/call_hierarchy.rs
@@ -1,127 +1,127 @@
-use serde::{Deserialize, Serialize};
-use serde_json::Value;
-use url::Url;
-
-use crate::{
- DynamicRegistrationClientCapabilities, PartialResultParams, Range, SymbolKind, SymbolTag,
- TextDocumentPositionParams, WorkDoneProgressOptions, WorkDoneProgressParams,
-};
-
-pub type CallHierarchyClientCapabilities = DynamicRegistrationClientCapabilities;
-
-#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
-#[serde(rename_all = "camelCase")]
-pub struct CallHierarchyOptions {
- #[serde(flatten)]
- pub work_done_progress_options: WorkDoneProgressOptions,
-}
-
-#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
-#[serde(untagged)]
-pub enum CallHierarchyServerCapability {
- Simple(bool),
- Options(CallHierarchyOptions),
-}
-
-impl From<CallHierarchyOptions> for CallHierarchyServerCapability {
- fn from(from: CallHierarchyOptions) -> Self {
- Self::Options(from)
- }
-}
-
-impl From<bool> for CallHierarchyServerCapability {
- fn from(from: bool) -> Self {
- Self::Simple(from)
- }
-}
-
-#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
-#[serde(rename_all = "camelCase")]
-pub struct CallHierarchyPrepareParams {
- #[serde(flatten)]
- pub text_document_position_params: TextDocumentPositionParams,
-
- #[serde(flatten)]
- pub work_done_progress_params: WorkDoneProgressParams,
-}
-
-#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)]
-#[serde(rename_all = "camelCase")]
-pub struct CallHierarchyItem {
- /// The name of this item.
- pub name: String,
-
- /// The kind of this item.
- pub kind: SymbolKind,
-
- /// Tags for this item.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub tags: Option<Vec<SymbolTag>>,
-
- /// More detail for this item, e.g. the signature of a function.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub detail: Option<String>,
-
- /// The resource identifier of this item.
- pub uri: Url,
-
- /// The range enclosing this symbol not including leading/trailing whitespace but everything else, e.g. comments and code.
- pub range: Range,
-
- /// The range that should be selected and revealed when this symbol is being picked, e.g. the name of a function.
- /// Must be contained by the [`range`](#CallHierarchyItem.range).
- pub selection_range: Range,
-
- /// A data entry field that is preserved between a call hierarchy prepare and incloming calls or outgoing calls requests.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub data: Option<Value>,
-}
-
-#[derive(Debug, PartialEq, Clone, Deserialize, Serialize)]
-#[serde(rename_all = "camelCase")]
-pub struct CallHierarchyIncomingCallsParams {
- pub item: CallHierarchyItem,
-
- #[serde(flatten)]
- pub work_done_progress_params: WorkDoneProgressParams,
-
- #[serde(flatten)]
- pub partial_result_params: PartialResultParams,
-}
-
-/// Represents an incoming call, e.g. a caller of a method or constructor.
-#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)]
-#[serde(rename_all = "camelCase")]
-pub struct CallHierarchyIncomingCall {
- /// The item that makes the call.
- pub from: CallHierarchyItem,
-
- /// The range at which at which the calls appears. This is relative to the caller
- /// denoted by [`this.from`](#CallHierarchyIncomingCall.from).
- pub from_ranges: Vec<Range>,
-}
-
-#[derive(Debug, PartialEq, Clone, Deserialize, Serialize)]
-#[serde(rename_all = "camelCase")]
-pub struct CallHierarchyOutgoingCallsParams {
- pub item: CallHierarchyItem,
-
- #[serde(flatten)]
- pub work_done_progress_params: WorkDoneProgressParams,
-
- #[serde(flatten)]
- pub partial_result_params: PartialResultParams,
-}
-
-/// Represents an outgoing call, e.g. calling a getter from a method or a method from a constructor etc.
-#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)]
-#[serde(rename_all = "camelCase")]
-pub struct CallHierarchyOutgoingCall {
- /// The item that is called.
- pub to: CallHierarchyItem,
-
- /// The range at which this item is called. This is the range relative to the caller, e.g the item
- /// passed to [`provideCallHierarchyOutgoingCalls`](#CallHierarchyItemProvider.provideCallHierarchyOutgoingCalls)
- /// and not [`this.to`](#CallHierarchyOutgoingCall.to).
- pub from_ranges: Vec<Range>,
-}
+use serde::{Deserialize, Serialize};
+use serde_json::Value;
+use url::Url;
+
+use crate::{
+ DynamicRegistrationClientCapabilities, PartialResultParams, Range, SymbolKind, SymbolTag,
+ TextDocumentPositionParams, WorkDoneProgressOptions, WorkDoneProgressParams,
+};
+
+pub type CallHierarchyClientCapabilities = DynamicRegistrationClientCapabilities;
+
+#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct CallHierarchyOptions {
+ #[serde(flatten)]
+ pub work_done_progress_options: WorkDoneProgressOptions,
+}
+
+#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
+#[serde(untagged)]
+pub enum CallHierarchyServerCapability {
+ Simple(bool),
+ Options(CallHierarchyOptions),
+}
+
+impl From<CallHierarchyOptions> for CallHierarchyServerCapability {
+ fn from(from: CallHierarchyOptions) -> Self {
+ Self::Options(from)
+ }
+}
+
+impl From<bool> for CallHierarchyServerCapability {
+ fn from(from: bool) -> Self {
+ Self::Simple(from)
+ }
+}
+
+#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct CallHierarchyPrepareParams {
+ #[serde(flatten)]
+ pub text_document_position_params: TextDocumentPositionParams,
+
+ #[serde(flatten)]
+ pub work_done_progress_params: WorkDoneProgressParams,
+}
+
+#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)]
+#[serde(rename_all = "camelCase")]
+pub struct CallHierarchyItem {
+ /// The name of this item.
+ pub name: String,
+
+ /// The kind of this item.
+ pub kind: SymbolKind,
+
+ /// Tags for this item.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub tags: Option<Vec<SymbolTag>>,
+
+ /// More detail for this item, e.g. the signature of a function.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub detail: Option<String>,
+
+ /// The resource identifier of this item.
+ pub uri: Url,
+
+ /// The range enclosing this symbol not including leading/trailing whitespace but everything else, e.g. comments and code.
+ pub range: Range,
+
+ /// The range that should be selected and revealed when this symbol is being picked, e.g. the name of a function.
+ /// Must be contained by the [`range`](#CallHierarchyItem.range).
+ pub selection_range: Range,
+
+ /// A data entry field that is preserved between a call hierarchy prepare and incloming calls or outgoing calls requests.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub data: Option<Value>,
+}
+
+#[derive(Debug, PartialEq, Clone, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct CallHierarchyIncomingCallsParams {
+ pub item: CallHierarchyItem,
+
+ #[serde(flatten)]
+ pub work_done_progress_params: WorkDoneProgressParams,
+
+ #[serde(flatten)]
+ pub partial_result_params: PartialResultParams,
+}
+
+/// Represents an incoming call, e.g. a caller of a method or constructor.
+#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)]
+#[serde(rename_all = "camelCase")]
+pub struct CallHierarchyIncomingCall {
+ /// The item that makes the call.
+ pub from: CallHierarchyItem,
+
+ /// The range at which at which the calls appears. This is relative to the caller
+ /// denoted by [`this.from`](#CallHierarchyIncomingCall.from).
+ pub from_ranges: Vec<Range>,
+}
+
+#[derive(Debug, PartialEq, Clone, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct CallHierarchyOutgoingCallsParams {
+ pub item: CallHierarchyItem,
+
+ #[serde(flatten)]
+ pub work_done_progress_params: WorkDoneProgressParams,
+
+ #[serde(flatten)]
+ pub partial_result_params: PartialResultParams,
+}
+
+/// Represents an outgoing call, e.g. calling a getter from a method or a method from a constructor etc.
+#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)]
+#[serde(rename_all = "camelCase")]
+pub struct CallHierarchyOutgoingCall {
+ /// The item that is called.
+ pub to: CallHierarchyItem,
+
+ /// The range at which this item is called. This is the range relative to the caller, e.g the item
+ /// passed to [`provideCallHierarchyOutgoingCalls`](#CallHierarchyItemProvider.provideCallHierarchyOutgoingCalls)
+ /// and not [`this.to`](#CallHierarchyOutgoingCall.to).
+ pub from_ranges: Vec<Range>,
+}
diff --git a/vendor/lsp-types/src/code_action.rs b/vendor/lsp-types/src/code_action.rs
index 8859743d2..859fc1c02 100644
--- a/vendor/lsp-types/src/code_action.rs
+++ b/vendor/lsp-types/src/code_action.rs
@@ -1,360 +1,395 @@
-use crate::{
- Command, Diagnostic, PartialResultParams, Range, TextDocumentIdentifier,
- WorkDoneProgressOptions, WorkDoneProgressParams, WorkspaceEdit,
-};
-use serde::{Deserialize, Serialize};
-
-use serde_json::Value;
-
-use std::borrow::Cow;
-#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
-#[serde(untagged)]
-pub enum CodeActionProviderCapability {
- Simple(bool),
- Options(CodeActionOptions),
-}
-
-impl From<CodeActionOptions> for CodeActionProviderCapability {
- fn from(from: CodeActionOptions) -> Self {
- Self::Options(from)
- }
-}
-
-impl From<bool> for CodeActionProviderCapability {
- fn from(from: bool) -> Self {
- Self::Simple(from)
- }
-}
-
-#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
-#[serde(rename_all = "camelCase")]
-pub struct CodeActionClientCapabilities {
- ///
- /// This capability supports dynamic registration.
- ///
- #[serde(skip_serializing_if = "Option::is_none")]
- pub dynamic_registration: Option<bool>,
-
- /// The client support code action literals as a valid
- /// response of the `textDocument/codeAction` request.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub code_action_literal_support: Option<CodeActionLiteralSupport>,
-
- /// Whether code action supports the `isPreferred` property.
- ///
- /// since 3.15.0
- #[serde(skip_serializing_if = "Option::is_none")]
- pub is_preferred_support: Option<bool>,
-
- /// Whether code action supports the `disabled` property.
- ///
- /// since 3.16.0
- #[serde(skip_serializing_if = "Option::is_none")]
- pub disabled_support: Option<bool>,
-
- /// Whether code action supports the `data` property which is
- /// preserved between a `textDocument/codeAction` and a
- /// `codeAction/resolve` request.
- ///
- /// since 3.16.0
- #[serde(skip_serializing_if = "Option::is_none")]
- pub data_support: Option<bool>,
-
- /// Whether the client supports resolving additional code action
- /// properties via a separate `codeAction/resolve` request.
- ///
- /// since 3.16.0
- #[serde(skip_serializing_if = "Option::is_none")]
- pub resolve_support: Option<CodeActionCapabilityResolveSupport>,
-
- /// Whether the client honors the change annotations in
- /// text edits and resource operations returned via the
- /// `CodeAction#edit` property by for example presenting
- /// the workspace edit in the user interface and asking
- /// for confirmation.
- ///
- /// @since 3.16.0
- #[serde(skip_serializing_if = "Option::is_none")]
- pub honors_change_annotations: Option<bool>,
-}
-
-/// Whether the client supports resolving additional code action
-/// properties via a separate `codeAction/resolve` request.
-///
-/// since 3.16.0
-#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
-#[serde(rename_all = "camelCase")]
-pub struct CodeActionCapabilityResolveSupport {
- /// The properties that a client can resolve lazily.
- pub properties: Vec<String>,
-}
-
-#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
-#[serde(rename_all = "camelCase")]
-pub struct CodeActionLiteralSupport {
- /// The code action kind is support with the following value set.
- pub code_action_kind: CodeActionKindLiteralSupport,
-}
-
-#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
-#[serde(rename_all = "camelCase")]
-pub struct CodeActionKindLiteralSupport {
- /// The code action kind values the client supports. When this
- /// property exists the client also guarantees that it will
- /// handle values outside its set gracefully and falls back
- /// to a default value when unknown.
- pub value_set: Vec<String>,
-}
-
-/// Params for the CodeActionRequest
-#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
-#[serde(rename_all = "camelCase")]
-pub struct CodeActionParams {
- /// The document in which the command was invoked.
- pub text_document: TextDocumentIdentifier,
-
- /// The range for which the command was invoked.
- pub range: Range,
-
- /// Context carrying additional information.
- pub context: CodeActionContext,
-
- #[serde(flatten)]
- pub work_done_progress_params: WorkDoneProgressParams,
-
- #[serde(flatten)]
- pub partial_result_params: PartialResultParams,
-}
-
-/// response for CodeActionRequest
-pub type CodeActionResponse = Vec<CodeActionOrCommand>;
-
-#[derive(Debug, Clone, PartialEq, Deserialize, Serialize)]
-#[serde(untagged)]
-pub enum CodeActionOrCommand {
- Command(Command),
- CodeAction(CodeAction),
-}
-
-impl From<Command> for CodeActionOrCommand {
- fn from(comand: Command) -> Self {
- CodeActionOrCommand::Command(comand)
- }
-}
-
-impl From<CodeAction> for CodeActionOrCommand {
- fn from(action: CodeAction) -> Self {
- CodeActionOrCommand::CodeAction(action)
- }
-}
-
-#[derive(Debug, Eq, PartialEq, Hash, PartialOrd, Clone, Deserialize, Serialize)]
-pub struct CodeActionKind(Cow<'static, str>);
-
-impl CodeActionKind {
- /// Empty kind.
- pub const EMPTY: CodeActionKind = CodeActionKind::new("");
-
- /// Base kind for quickfix actions: 'quickfix'
- pub const QUICKFIX: CodeActionKind = CodeActionKind::new("quickfix");
-
- /// Base kind for refactoring actions: 'refactor'
- pub const REFACTOR: CodeActionKind = CodeActionKind::new("refactor");
-
- /// Base kind for refactoring extraction actions: 'refactor.extract'
- ///
- /// Example extract actions:
- ///
- /// - Extract method
- /// - Extract function
- /// - Extract variable
- /// - Extract interface from class
- /// - ...
- pub const REFACTOR_EXTRACT: CodeActionKind = CodeActionKind::new("refactor.extract");
-
- /// Base kind for refactoring inline actions: 'refactor.inline'
- ///
- /// Example inline actions:
- ///
- /// - Inline function
- /// - Inline variable
- /// - Inline constant
- /// - ...
- pub const REFACTOR_INLINE: CodeActionKind = CodeActionKind::new("refactor.inline");
-
- /// Base kind for refactoring rewrite actions: 'refactor.rewrite'
- ///
- /// Example rewrite actions:
- ///
- /// - Convert JavaScript function to class
- /// - Add or remove parameter
- /// - Encapsulate field
- /// - Make method static
- /// - Move method to base class
- /// - ...
- pub const REFACTOR_REWRITE: CodeActionKind = CodeActionKind::new("refactor.rewrite");
-
- /// Base kind for source actions: `source`
- ///
- /// Source code actions apply to the entire file.
- pub const SOURCE: CodeActionKind = CodeActionKind::new("source");
-
- /// Base kind for an organize imports source action: `source.organizeImports`
- pub const SOURCE_ORGANIZE_IMPORTS: CodeActionKind =
- CodeActionKind::new("source.organizeImports");
-
- pub const fn new(tag: &'static str) -> Self {
- CodeActionKind(Cow::Borrowed(tag))
- }
-
- pub fn as_str(&self) -> &str {
- &self.0
- }
-}
-
-impl From<String> for CodeActionKind {
- fn from(from: String) -> Self {
- CodeActionKind(Cow::from(from))
- }
-}
-
-impl From<&'static str> for CodeActionKind {
- fn from(from: &'static str) -> Self {
- CodeActionKind::new(from)
- }
-}
-
-#[derive(Debug, PartialEq, Clone, Default, Deserialize, Serialize)]
-#[serde(rename_all = "camelCase")]
-pub struct CodeAction {
- /// A short, human-readable, title for this code action.
- pub title: String,
-
- /// The kind of the code action.
- /// Used to filter code actions.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub kind: Option<CodeActionKind>,
-
- /// The diagnostics that this code action resolves.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub diagnostics: Option<Vec<Diagnostic>>,
-
- /// The workspace edit this code action performs.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub edit: Option<WorkspaceEdit>,
-
- /// A command this code action executes. If a code action
- /// provides an edit and a command, first the edit is
- /// executed and then the command.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub command: Option<Command>,
-
- /// Marks this as a preferred action. Preferred actions are used by the `auto fix` command and can be targeted
- /// by keybindings.
- /// A quick fix should be marked preferred if it properly addresses the underlying error.
- /// A refactoring should be marked preferred if it is the most reasonable choice of actions to take.
- ///
- /// since 3.15.0
- #[serde(skip_serializing_if = "Option::is_none")]
- pub is_preferred: Option<bool>,
-
- /// Marks that the code action cannot currently be applied.
- ///
- /// Clients should follow the following guidelines regarding disabled code actions:
- ///
- /// - Disabled code actions are not shown in automatic
- /// [lightbulb](https://code.visualstudio.com/docs/editor/editingevolved#_code-action)
- /// code action menu.
- ///
- /// - Disabled actions are shown as faded out in the code action menu when the user request
- /// a more specific type of code action, such as refactorings.
- ///
- /// - If the user has a keybinding that auto applies a code action and only a disabled code
- /// actions are returned, the client should show the user an error message with `reason`
- /// in the editor.
- ///
- /// since 3.16.0
- #[serde(skip_serializing_if = "Option::is_none")]
- pub disabled: Option<CodeActionDisabled>,
-
- /// A data entry field that is preserved on a code action between
- /// a `textDocument/codeAction` and a `codeAction/resolve` request.
- ///
- /// since 3.16.0
- #[serde(skip_serializing_if = "Option::is_none")]
- pub data: Option<Value>,
-}
-
-#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
-#[serde(rename_all = "camelCase")]
-pub struct CodeActionDisabled {
- /// Human readable description of why the code action is currently disabled.
- ///
- /// This is displayed in the code actions UI.
- pub reason: String,
-}
-
-/// Contains additional diagnostic information about the context in which
-/// a code action is run.
-#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
-pub struct CodeActionContext {
- /// An array of diagnostics.
- pub diagnostics: Vec<Diagnostic>,
-
- /// Requested kind of actions to return.
- ///
- /// Actions not of this kind are filtered out by the client before being shown. So servers
- /// can omit computing them.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub only: Option<Vec<CodeActionKind>>,
-}
-
-#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
-#[serde(rename_all = "camelCase")]
-pub struct CodeActionOptions {
- /// CodeActionKinds that this server may return.
- ///
- /// The list of kinds may be generic, such as `CodeActionKind.Refactor`, or the server
- /// may list out every specific kind they provide.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub code_action_kinds: Option<Vec<CodeActionKind>>,
-
- #[serde(flatten)]
- pub work_done_progress_options: WorkDoneProgressOptions,
-
- /// The server provides support to resolve additional
- /// information for a code action.
- ///
- /// since 3.16.0
- #[serde(skip_serializing_if = "Option::is_none")]
- pub resolve_provider: Option<bool>,
-}
-
-#[cfg(test)]
-mod tests {
- use super::*;
- use crate::tests::test_serialization;
-
- #[test]
- fn test_code_action_response() {
- test_serialization(
- &vec![
- CodeActionOrCommand::Command(Command {
- title: "title".to_string(),
- command: "command".to_string(),
- arguments: None,
- }),
- CodeActionOrCommand::CodeAction(CodeAction {
- title: "title".to_string(),
- kind: Some(CodeActionKind::QUICKFIX),
- command: None,
- diagnostics: None,
- edit: None,
- is_preferred: None,
- ..CodeAction::default()
- }),
- ],
- r#"[{"title":"title","command":"command"},{"title":"title","kind":"quickfix"}]"#,
- )
- }
-}
+use crate::{
+ Command, Diagnostic, PartialResultParams, Range, TextDocumentIdentifier,
+ WorkDoneProgressOptions, WorkDoneProgressParams, WorkspaceEdit,
+};
+use serde::{Deserialize, Serialize};
+
+use serde_json::Value;
+
+use std::borrow::Cow;
+#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
+#[serde(untagged)]
+pub enum CodeActionProviderCapability {
+ Simple(bool),
+ Options(CodeActionOptions),
+}
+
+impl From<CodeActionOptions> for CodeActionProviderCapability {
+ fn from(from: CodeActionOptions) -> Self {
+ Self::Options(from)
+ }
+}
+
+impl From<bool> for CodeActionProviderCapability {
+ fn from(from: bool) -> Self {
+ Self::Simple(from)
+ }
+}
+
+#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct CodeActionClientCapabilities {
+ ///
+ /// This capability supports dynamic registration.
+ ///
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub dynamic_registration: Option<bool>,
+
+ /// The client support code action literals as a valid
+ /// response of the `textDocument/codeAction` request.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub code_action_literal_support: Option<CodeActionLiteralSupport>,
+
+ /// Whether code action supports the `isPreferred` property.
+ ///
+ /// since 3.15.0
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub is_preferred_support: Option<bool>,
+
+ /// Whether code action supports the `disabled` property.
+ ///
+ /// since 3.16.0
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub disabled_support: Option<bool>,
+
+ /// Whether code action supports the `data` property which is
+ /// preserved between a `textDocument/codeAction` and a
+ /// `codeAction/resolve` request.
+ ///
+ /// since 3.16.0
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub data_support: Option<bool>,
+
+ /// Whether the client supports resolving additional code action
+ /// properties via a separate `codeAction/resolve` request.
+ ///
+ /// since 3.16.0
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub resolve_support: Option<CodeActionCapabilityResolveSupport>,
+
+ /// Whether the client honors the change annotations in
+ /// text edits and resource operations returned via the
+ /// `CodeAction#edit` property by for example presenting
+ /// the workspace edit in the user interface and asking
+ /// for confirmation.
+ ///
+ /// @since 3.16.0
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub honors_change_annotations: Option<bool>,
+}
+
+/// Whether the client supports resolving additional code action
+/// properties via a separate `codeAction/resolve` request.
+///
+/// since 3.16.0
+#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct CodeActionCapabilityResolveSupport {
+ /// The properties that a client can resolve lazily.
+ pub properties: Vec<String>,
+}
+
+#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct CodeActionLiteralSupport {
+ /// The code action kind is support with the following value set.
+ pub code_action_kind: CodeActionKindLiteralSupport,
+}
+
+#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct CodeActionKindLiteralSupport {
+ /// The code action kind values the client supports. When this
+ /// property exists the client also guarantees that it will
+ /// handle values outside its set gracefully and falls back
+ /// to a default value when unknown.
+ pub value_set: Vec<String>,
+}
+
+/// Params for the CodeActionRequest
+#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct CodeActionParams {
+ /// The document in which the command was invoked.
+ pub text_document: TextDocumentIdentifier,
+
+ /// The range for which the command was invoked.
+ pub range: Range,
+
+ /// Context carrying additional information.
+ pub context: CodeActionContext,
+
+ #[serde(flatten)]
+ pub work_done_progress_params: WorkDoneProgressParams,
+
+ #[serde(flatten)]
+ pub partial_result_params: PartialResultParams,
+}
+
+/// response for CodeActionRequest
+pub type CodeActionResponse = Vec<CodeActionOrCommand>;
+
+#[derive(Debug, Clone, PartialEq, Deserialize, Serialize)]
+#[serde(untagged)]
+pub enum CodeActionOrCommand {
+ Command(Command),
+ CodeAction(CodeAction),
+}
+
+impl From<Command> for CodeActionOrCommand {
+ fn from(comand: Command) -> Self {
+ CodeActionOrCommand::Command(comand)
+ }
+}
+
+impl From<CodeAction> for CodeActionOrCommand {
+ fn from(action: CodeAction) -> Self {
+ CodeActionOrCommand::CodeAction(action)
+ }
+}
+
+#[derive(Debug, Eq, PartialEq, Hash, PartialOrd, Clone, Deserialize, Serialize)]
+pub struct CodeActionKind(Cow<'static, str>);
+
+impl CodeActionKind {
+ /// Empty kind.
+ pub const EMPTY: CodeActionKind = CodeActionKind::new("");
+
+ /// Base kind for quickfix actions: 'quickfix'
+ pub const QUICKFIX: CodeActionKind = CodeActionKind::new("quickfix");
+
+ /// Base kind for refactoring actions: 'refactor'
+ pub const REFACTOR: CodeActionKind = CodeActionKind::new("refactor");
+
+ /// Base kind for refactoring extraction actions: 'refactor.extract'
+ ///
+ /// Example extract actions:
+ ///
+ /// - Extract method
+ /// - Extract function
+ /// - Extract variable
+ /// - Extract interface from class
+ /// - ...
+ pub const REFACTOR_EXTRACT: CodeActionKind = CodeActionKind::new("refactor.extract");
+
+ /// Base kind for refactoring inline actions: 'refactor.inline'
+ ///
+ /// Example inline actions:
+ ///
+ /// - Inline function
+ /// - Inline variable
+ /// - Inline constant
+ /// - ...
+ pub const REFACTOR_INLINE: CodeActionKind = CodeActionKind::new("refactor.inline");
+
+ /// Base kind for refactoring rewrite actions: 'refactor.rewrite'
+ ///
+ /// Example rewrite actions:
+ ///
+ /// - Convert JavaScript function to class
+ /// - Add or remove parameter
+ /// - Encapsulate field
+ /// - Make method static
+ /// - Move method to base class
+ /// - ...
+ pub const REFACTOR_REWRITE: CodeActionKind = CodeActionKind::new("refactor.rewrite");
+
+ /// Base kind for source actions: `source`
+ ///
+ /// Source code actions apply to the entire file.
+ pub const SOURCE: CodeActionKind = CodeActionKind::new("source");
+
+ /// Base kind for an organize imports source action: `source.organizeImports`
+ pub const SOURCE_ORGANIZE_IMPORTS: CodeActionKind =
+ CodeActionKind::new("source.organizeImports");
+
+ /// Base kind for a 'fix all' source action: `source.fixAll`.
+ ///
+ /// 'Fix all' actions automatically fix errors that have a clear fix that
+ /// do not require user input. They should not suppress errors or perform
+ /// unsafe fixes such as generating new types or classes.
+ ///
+ /// @since 3.17.0
+ pub const SOURCE_FIX_ALL: CodeActionKind = CodeActionKind::new("source.fixAll");
+
+ pub const fn new(tag: &'static str) -> Self {
+ CodeActionKind(Cow::Borrowed(tag))
+ }
+
+ pub fn as_str(&self) -> &str {
+ &self.0
+ }
+}
+
+impl From<String> for CodeActionKind {
+ fn from(from: String) -> Self {
+ CodeActionKind(Cow::from(from))
+ }
+}
+
+impl From<&'static str> for CodeActionKind {
+ fn from(from: &'static str) -> Self {
+ CodeActionKind::new(from)
+ }
+}
+
+#[derive(Debug, PartialEq, Clone, Default, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct CodeAction {
+ /// A short, human-readable, title for this code action.
+ pub title: String,
+
+ /// The kind of the code action.
+ /// Used to filter code actions.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub kind: Option<CodeActionKind>,
+
+ /// The diagnostics that this code action resolves.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub diagnostics: Option<Vec<Diagnostic>>,
+
+ /// The workspace edit this code action performs.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub edit: Option<WorkspaceEdit>,
+
+ /// A command this code action executes. If a code action
+ /// provides an edit and a command, first the edit is
+ /// executed and then the command.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub command: Option<Command>,
+
+ /// Marks this as a preferred action. Preferred actions are used by the `auto fix` command and can be targeted
+ /// by keybindings.
+ /// A quick fix should be marked preferred if it properly addresses the underlying error.
+ /// A refactoring should be marked preferred if it is the most reasonable choice of actions to take.
+ ///
+ /// since 3.15.0
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub is_preferred: Option<bool>,
+
+ /// Marks that the code action cannot currently be applied.
+ ///
+ /// Clients should follow the following guidelines regarding disabled code actions:
+ ///
+ /// - Disabled code actions are not shown in automatic
+ /// [lightbulb](https://code.visualstudio.com/docs/editor/editingevolved#_code-action)
+ /// code action menu.
+ ///
+ /// - Disabled actions are shown as faded out in the code action menu when the user request
+ /// a more specific type of code action, such as refactorings.
+ ///
+ /// - If the user has a keybinding that auto applies a code action and only a disabled code
+ /// actions are returned, the client should show the user an error message with `reason`
+ /// in the editor.
+ ///
+ /// since 3.16.0
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub disabled: Option<CodeActionDisabled>,
+
+ /// A data entry field that is preserved on a code action between
+ /// a `textDocument/codeAction` and a `codeAction/resolve` request.
+ ///
+ /// since 3.16.0
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub data: Option<Value>,
+}
+
+#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct CodeActionDisabled {
+ /// Human readable description of why the code action is currently disabled.
+ ///
+ /// This is displayed in the code actions UI.
+ pub reason: String,
+}
+
+/// The reason why code actions were requested.
+///
+/// @since 3.17.0
+#[derive(Eq, PartialEq, Clone, Copy, Deserialize, Serialize)]
+#[serde(transparent)]
+pub struct CodeActionTriggerKind(i32);
+lsp_enum! {
+impl CodeActionTriggerKind {
+ /// Code actions were explicitly requested by the user or by an extension.
+ pub const INVOKED: CodeActionTriggerKind = CodeActionTriggerKind(1);
+
+ /// Code actions were requested automatically.
+ ///
+ /// This typically happens when current selection in a file changes, but can
+ /// also be triggered when file content changes.
+ pub const AUTOMATIC: CodeActionTriggerKind = CodeActionTriggerKind(2);
+}
+}
+
+/// Contains additional diagnostic information about the context in which
+/// a code action is run.
+#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct CodeActionContext {
+ /// An array of diagnostics.
+ pub diagnostics: Vec<Diagnostic>,
+
+ /// Requested kind of actions to return.
+ ///
+ /// Actions not of this kind are filtered out by the client before being shown. So servers
+ /// can omit computing them.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub only: Option<Vec<CodeActionKind>>,
+
+ /// The reason why code actions were requested.
+ ///
+ /// @since 3.17.0
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub trigger_kind: Option<CodeActionTriggerKind>,
+}
+
+#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct CodeActionOptions {
+ /// CodeActionKinds that this server may return.
+ ///
+ /// The list of kinds may be generic, such as `CodeActionKind.Refactor`, or the server
+ /// may list out every specific kind they provide.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub code_action_kinds: Option<Vec<CodeActionKind>>,
+
+ #[serde(flatten)]
+ pub work_done_progress_options: WorkDoneProgressOptions,
+
+ /// The server provides support to resolve additional
+ /// information for a code action.
+ ///
+ /// since 3.16.0
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub resolve_provider: Option<bool>,
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+ use crate::tests::test_serialization;
+
+ #[test]
+ fn test_code_action_response() {
+ test_serialization(
+ &vec![
+ CodeActionOrCommand::Command(Command {
+ title: "title".to_string(),
+ command: "command".to_string(),
+ arguments: None,
+ }),
+ CodeActionOrCommand::CodeAction(CodeAction {
+ title: "title".to_string(),
+ kind: Some(CodeActionKind::QUICKFIX),
+ command: None,
+ diagnostics: None,
+ edit: None,
+ is_preferred: None,
+ ..CodeAction::default()
+ }),
+ ],
+ r#"[{"title":"title","command":"command"},{"title":"title","kind":"quickfix"}]"#,
+ )
+ }
+}
diff --git a/vendor/lsp-types/src/code_lens.rs b/vendor/lsp-types/src/code_lens.rs
index 2e4fa790f..e4f35c722 100644
--- a/vendor/lsp-types/src/code_lens.rs
+++ b/vendor/lsp-types/src/code_lens.rs
@@ -1,66 +1,66 @@
-use serde::{Deserialize, Serialize};
-use serde_json::Value;
-
-use crate::{
- Command, DynamicRegistrationClientCapabilities, PartialResultParams, Range,
- TextDocumentIdentifier, WorkDoneProgressParams,
-};
-
-pub type CodeLensClientCapabilities = DynamicRegistrationClientCapabilities;
-
-/// Code Lens options.
-#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
-#[serde(rename_all = "camelCase")]
-pub struct CodeLensOptions {
- /// Code lens has a resolve provider as well.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub resolve_provider: Option<bool>,
-}
-
-#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
-#[serde(rename_all = "camelCase")]
-pub struct CodeLensParams {
- /// The document to request code lens for.
- pub text_document: TextDocumentIdentifier,
-
- #[serde(flatten)]
- pub work_done_progress_params: WorkDoneProgressParams,
-
- #[serde(flatten)]
- pub partial_result_params: PartialResultParams,
-}
-
-/// A code lens represents a command that should be shown along with
-/// source text, like the number of references, a way to run tests, etc.
-///
-/// A code lens is _unresolved_ when no command is associated to it. For performance
-/// reasons the creation of a code lens and resolving should be done in two stages.
-#[derive(Debug, Clone, PartialEq, Deserialize, Serialize)]
-#[serde(rename_all = "camelCase")]
-pub struct CodeLens {
- /// The range in which this code lens is valid. Should only span a single line.
- pub range: Range,
-
- /// The command this code lens represents.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub command: Option<Command>,
-
- /// A data entry field that is preserved on a code lens item between
- /// a code lens and a code lens resolve request.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub data: Option<Value>,
-}
-
-#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)]
-#[serde(rename_all = "camelCase")]
-pub struct CodeLensWorkspaceClientCapabilities {
- /// Whether the client implementation supports a refresh request sent from the
- /// server to the client.
- ///
- /// Note that this event is global and will force the client to refresh all
- /// code lenses currently shown. It should be used with absolute care and is
- /// useful for situation where a server for example detect a project wide
- /// change that requires such a calculation.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub refresh_support: Option<bool>,
-}
+use serde::{Deserialize, Serialize};
+use serde_json::Value;
+
+use crate::{
+ Command, DynamicRegistrationClientCapabilities, PartialResultParams, Range,
+ TextDocumentIdentifier, WorkDoneProgressParams,
+};
+
+pub type CodeLensClientCapabilities = DynamicRegistrationClientCapabilities;
+
+/// Code Lens options.
+#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct CodeLensOptions {
+ /// Code lens has a resolve provider as well.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub resolve_provider: Option<bool>,
+}
+
+#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct CodeLensParams {
+ /// The document to request code lens for.
+ pub text_document: TextDocumentIdentifier,
+
+ #[serde(flatten)]
+ pub work_done_progress_params: WorkDoneProgressParams,
+
+ #[serde(flatten)]
+ pub partial_result_params: PartialResultParams,
+}
+
+/// A code lens represents a command that should be shown along with
+/// source text, like the number of references, a way to run tests, etc.
+///
+/// A code lens is _unresolved_ when no command is associated to it. For performance
+/// reasons the creation of a code lens and resolving should be done in two stages.
+#[derive(Debug, Clone, PartialEq, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct CodeLens {
+ /// The range in which this code lens is valid. Should only span a single line.
+ pub range: Range,
+
+ /// The command this code lens represents.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub command: Option<Command>,
+
+ /// A data entry field that is preserved on a code lens item between
+ /// a code lens and a code lens resolve request.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub data: Option<Value>,
+}
+
+#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct CodeLensWorkspaceClientCapabilities {
+ /// Whether the client implementation supports a refresh request sent from the
+ /// server to the client.
+ ///
+ /// Note that this event is global and will force the client to refresh all
+ /// code lenses currently shown. It should be used with absolute care and is
+ /// useful for situation where a server for example detect a project wide
+ /// change that requires such a calculation.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub refresh_support: Option<bool>,
+}
diff --git a/vendor/lsp-types/src/color.rs b/vendor/lsp-types/src/color.rs
index ef9e858af..a3999683a 100644
--- a/vendor/lsp-types/src/color.rs
+++ b/vendor/lsp-types/src/color.rs
@@ -1,122 +1,122 @@
-use crate::{
- DocumentSelector, DynamicRegistrationClientCapabilities, PartialResultParams, Range,
- TextDocumentIdentifier, TextEdit, WorkDoneProgressParams,
-};
-use serde::{Deserialize, Serialize};
-
-pub type DocumentColorClientCapabilities = DynamicRegistrationClientCapabilities;
-
-#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
-#[serde(rename_all = "camelCase")]
-pub struct ColorProviderOptions {}
-
-#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
-#[serde(rename_all = "camelCase")]
-pub struct StaticTextDocumentColorProviderOptions {
- /// A document selector to identify the scope of the registration. If set to null
- /// the document selector provided on the client side will be used.
- pub document_selector: Option<DocumentSelector>,
-
- #[serde(skip_serializing_if = "Option::is_none")]
- pub id: Option<String>,
-}
-
-#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
-#[serde(untagged)]
-pub enum ColorProviderCapability {
- Simple(bool),
- ColorProvider(ColorProviderOptions),
- Options(StaticTextDocumentColorProviderOptions),
-}
-
-impl From<ColorProviderOptions> for ColorProviderCapability {
- fn from(from: ColorProviderOptions) -> Self {
- Self::ColorProvider(from)
- }
-}
-
-impl From<StaticTextDocumentColorProviderOptions> for ColorProviderCapability {
- fn from(from: StaticTextDocumentColorProviderOptions) -> Self {
- Self::Options(from)
- }
-}
-
-impl From<bool> for ColorProviderCapability {
- fn from(from: bool) -> Self {
- Self::Simple(from)
- }
-}
-
-#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
-#[serde(rename_all = "camelCase")]
-pub struct DocumentColorParams {
- /// The text document
- pub text_document: TextDocumentIdentifier,
-
- #[serde(flatten)]
- pub work_done_progress_params: WorkDoneProgressParams,
-
- #[serde(flatten)]
- pub partial_result_params: PartialResultParams,
-}
-
-#[derive(Debug, PartialEq, Clone, Deserialize, Serialize)]
-#[serde(rename_all = "camelCase")]
-pub struct ColorInformation {
- /// The range in the document where this color appears.
- pub range: Range,
- /// The actual color value for this color range.
- pub color: Color,
-}
-
-#[derive(Debug, PartialEq, Clone, Deserialize, Serialize)]
-#[serde(rename_all = "camelCase")]
-pub struct Color {
- /// The red component of this color in the range [0-1].
- pub red: f32,
- /// The green component of this color in the range [0-1].
- pub green: f32,
- /// The blue component of this color in the range [0-1].
- pub blue: f32,
- /// The alpha component of this color in the range [0-1].
- pub alpha: f32,
-}
-
-#[derive(Debug, PartialEq, Clone, Deserialize, Serialize)]
-#[serde(rename_all = "camelCase")]
-pub struct ColorPresentationParams {
- /// The text document.
- pub text_document: TextDocumentIdentifier,
-
- /// The color information to request presentations for.
- pub color: Color,
-
- /// The range where the color would be inserted. Serves as a context.
- pub range: Range,
-
- #[serde(flatten)]
- pub work_done_progress_params: WorkDoneProgressParams,
-
- #[serde(flatten)]
- pub partial_result_params: PartialResultParams,
-}
-
-#[derive(Debug, PartialEq, Eq, Deserialize, Serialize, Default, Clone)]
-#[serde(rename_all = "camelCase")]
-pub struct ColorPresentation {
- /// The label of this color presentation. It will be shown on the color
- /// picker header. By default this is also the text that is inserted when selecting
- /// this color presentation.
- pub label: String,
-
- /// An [edit](#TextEdit) which is applied to a document when selecting
- /// this presentation for the color. When `falsy` the [label](#ColorPresentation.label)
- /// is used.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub text_edit: Option<TextEdit>,
-
- /// An optional array of additional [text edits](#TextEdit) that are applied when
- /// selecting this color presentation. Edits must not overlap with the main [edit](#ColorPresentation.textEdit) nor with themselves.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub additional_text_edits: Option<Vec<TextEdit>>,
-}
+use crate::{
+ DocumentSelector, DynamicRegistrationClientCapabilities, PartialResultParams, Range,
+ TextDocumentIdentifier, TextEdit, WorkDoneProgressParams,
+};
+use serde::{Deserialize, Serialize};
+
+pub type DocumentColorClientCapabilities = DynamicRegistrationClientCapabilities;
+
+#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct ColorProviderOptions {}
+
+#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct StaticTextDocumentColorProviderOptions {
+ /// A document selector to identify the scope of the registration. If set to null
+ /// the document selector provided on the client side will be used.
+ pub document_selector: Option<DocumentSelector>,
+
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub id: Option<String>,
+}
+
+#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
+#[serde(untagged)]
+pub enum ColorProviderCapability {
+ Simple(bool),
+ ColorProvider(ColorProviderOptions),
+ Options(StaticTextDocumentColorProviderOptions),
+}
+
+impl From<ColorProviderOptions> for ColorProviderCapability {
+ fn from(from: ColorProviderOptions) -> Self {
+ Self::ColorProvider(from)
+ }
+}
+
+impl From<StaticTextDocumentColorProviderOptions> for ColorProviderCapability {
+ fn from(from: StaticTextDocumentColorProviderOptions) -> Self {
+ Self::Options(from)
+ }
+}
+
+impl From<bool> for ColorProviderCapability {
+ fn from(from: bool) -> Self {
+ Self::Simple(from)
+ }
+}
+
+#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct DocumentColorParams {
+ /// The text document
+ pub text_document: TextDocumentIdentifier,
+
+ #[serde(flatten)]
+ pub work_done_progress_params: WorkDoneProgressParams,
+
+ #[serde(flatten)]
+ pub partial_result_params: PartialResultParams,
+}
+
+#[derive(Debug, PartialEq, Clone, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct ColorInformation {
+ /// The range in the document where this color appears.
+ pub range: Range,
+ /// The actual color value for this color range.
+ pub color: Color,
+}
+
+#[derive(Debug, PartialEq, Clone, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct Color {
+ /// The red component of this color in the range [0-1].
+ pub red: f32,
+ /// The green component of this color in the range [0-1].
+ pub green: f32,
+ /// The blue component of this color in the range [0-1].
+ pub blue: f32,
+ /// The alpha component of this color in the range [0-1].
+ pub alpha: f32,
+}
+
+#[derive(Debug, PartialEq, Clone, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct ColorPresentationParams {
+ /// The text document.
+ pub text_document: TextDocumentIdentifier,
+
+ /// The color information to request presentations for.
+ pub color: Color,
+
+ /// The range where the color would be inserted. Serves as a context.
+ pub range: Range,
+
+ #[serde(flatten)]
+ pub work_done_progress_params: WorkDoneProgressParams,
+
+ #[serde(flatten)]
+ pub partial_result_params: PartialResultParams,
+}
+
+#[derive(Debug, PartialEq, Eq, Deserialize, Serialize, Default, Clone)]
+#[serde(rename_all = "camelCase")]
+pub struct ColorPresentation {
+ /// The label of this color presentation. It will be shown on the color
+ /// picker header. By default this is also the text that is inserted when selecting
+ /// this color presentation.
+ pub label: String,
+
+ /// An [edit](#TextEdit) which is applied to a document when selecting
+ /// this presentation for the color. When `falsy` the [label](#ColorPresentation.label)
+ /// is used.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub text_edit: Option<TextEdit>,
+
+ /// An optional array of additional [text edits](#TextEdit) that are applied when
+ /// selecting this color presentation. Edits must not overlap with the main [edit](#ColorPresentation.textEdit) nor with themselves.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub additional_text_edits: Option<Vec<TextEdit>>,
+}
diff --git a/vendor/lsp-types/src/completion.rs b/vendor/lsp-types/src/completion.rs
index 5f9277a35..4884960a0 100644
--- a/vendor/lsp-types/src/completion.rs
+++ b/vendor/lsp-types/src/completion.rs
@@ -1,600 +1,616 @@
-use serde::{Deserialize, Serialize};
-
-use crate::{
- Command, Documentation, MarkupKind, PartialResultParams, TagSupport,
- TextDocumentPositionParams, TextDocumentRegistrationOptions, TextEdit, WorkDoneProgressOptions,
- WorkDoneProgressParams,
-};
-
-use crate::Range;
-use serde_json::Value;
-use std::fmt::Debug;
-
-/// Defines how to interpret the insert text in a completion item
-#[derive(Eq, PartialEq, Clone, Copy, Serialize, Deserialize)]
-#[serde(transparent)]
-pub struct InsertTextFormat(i32);
-lsp_enum! {
-impl InsertTextFormat {
- pub const PLAIN_TEXT: InsertTextFormat = InsertTextFormat(1);
- pub const SNIPPET: InsertTextFormat = InsertTextFormat(2);
-}
-}
-
-/// The kind of a completion entry.
-#[derive(Eq, PartialEq, Clone, Copy, Serialize, Deserialize)]
-#[serde(transparent)]
-pub struct CompletionItemKind(i32);
-lsp_enum! {
-impl CompletionItemKind {
- pub const TEXT: CompletionItemKind = CompletionItemKind(1);
- pub const METHOD: CompletionItemKind = CompletionItemKind(2);
- pub const FUNCTION: CompletionItemKind = CompletionItemKind(3);
- pub const CONSTRUCTOR: CompletionItemKind = CompletionItemKind(4);
- pub const FIELD: CompletionItemKind = CompletionItemKind(5);
- pub const VARIABLE: CompletionItemKind = CompletionItemKind(6);
- pub const CLASS: CompletionItemKind = CompletionItemKind(7);
- pub const INTERFACE: CompletionItemKind = CompletionItemKind(8);
- pub const MODULE: CompletionItemKind = CompletionItemKind(9);
- pub const PROPERTY: CompletionItemKind = CompletionItemKind(10);
- pub const UNIT: CompletionItemKind = CompletionItemKind(11);
- pub const VALUE: CompletionItemKind = CompletionItemKind(12);
- pub const ENUM: CompletionItemKind = CompletionItemKind(13);
- pub const KEYWORD: CompletionItemKind = CompletionItemKind(14);
- pub const SNIPPET: CompletionItemKind = CompletionItemKind(15);
- pub const COLOR: CompletionItemKind = CompletionItemKind(16);
- pub const FILE: CompletionItemKind = CompletionItemKind(17);
- pub const REFERENCE: CompletionItemKind = CompletionItemKind(18);
- pub const FOLDER: CompletionItemKind = CompletionItemKind(19);
- pub const ENUM_MEMBER: CompletionItemKind = CompletionItemKind(20);
- pub const CONSTANT: CompletionItemKind = CompletionItemKind(21);
- pub const STRUCT: CompletionItemKind = CompletionItemKind(22);
- pub const EVENT: CompletionItemKind = CompletionItemKind(23);
- pub const OPERATOR: CompletionItemKind = CompletionItemKind(24);
- pub const TYPE_PARAMETER: CompletionItemKind = CompletionItemKind(25);
-}
-}
-
-#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
-#[serde(rename_all = "camelCase")]
-pub struct CompletionItemCapability {
- /// Client supports snippets as insert text.
- ///
- /// A snippet can define tab stops and placeholders with `$1`, `$2`
- /// and `${3:foo}`. `$0` defines the final tab stop, it defaults to
- /// the end of the snippet. Placeholders with equal identifiers are linked,
- /// that is typing in one will update others too.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub snippet_support: Option<bool>,
-
- /// Client supports commit characters on a completion item.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub commit_characters_support: Option<bool>,
-
- /// Client supports the follow content formats for the documentation
- /// property. The order describes the preferred format of the client.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub documentation_format: Option<Vec<MarkupKind>>,
-
- /// Client supports the deprecated property on a completion item.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub deprecated_support: Option<bool>,
-
- /// Client supports the preselect property on a completion item.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub preselect_support: Option<bool>,
-
- /// Client supports the tag property on a completion item. Clients supporting
- /// tags have to handle unknown tags gracefully. Clients especially need to
- /// preserve unknown tags when sending a completion item back to the server in
- /// a resolve call.
- #[serde(
- default,
- skip_serializing_if = "Option::is_none",
- deserialize_with = "TagSupport::deserialize_compat"
- )]
- pub tag_support: Option<TagSupport<CompletionItemTag>>,
-
- /// Client support insert replace edit to control different behavior if a
- /// completion item is inserted in the text or should replace text.
- ///
- /// @since 3.16.0
- #[serde(skip_serializing_if = "Option::is_none")]
- pub insert_replace_support: Option<bool>,
-
- /// Indicates which properties a client can resolve lazily on a completion
- /// item. Before version 3.16.0 only the predefined properties `documentation`
- /// and `details` could be resolved lazily.
- ///
- /// @since 3.16.0
- #[serde(skip_serializing_if = "Option::is_none")]
- pub resolve_support: Option<CompletionItemCapabilityResolveSupport>,
-
- /// The client supports the `insertTextMode` property on
- /// a completion item to override the whitespace handling mode
- /// as defined by the client.
- ///
- /// @since 3.16.0
- #[serde(skip_serializing_if = "Option::is_none")]
- pub insert_text_mode_support: Option<InsertTextModeSupport>,
-
- /// The client has support for completion item label
- /// details (see also `CompletionItemLabelDetails`).
- ///
- /// @since 3.17.0 - proposed state
- ///
- #[cfg(feature = "proposed")]
- #[serde(skip_serializing_if = "Option::is_none")]
- pub label_details_support: Option<bool>,
-}
-
-#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
-#[serde(rename_all = "camelCase")]
-pub struct CompletionItemCapabilityResolveSupport {
- /// The properties that a client can resolve lazily.
- pub properties: Vec<String>,
-}
-
-#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
-#[serde(rename_all = "camelCase")]
-pub struct InsertTextModeSupport {
- pub value_set: Vec<InsertTextMode>,
-}
-
-/// How whitespace and indentation is handled during completion
-/// item insertion.
-///
-/// @since 3.16.0
-#[derive(Eq, PartialEq, Clone, Copy, Serialize, Deserialize)]
-#[serde(transparent)]
-pub struct InsertTextMode(i32);
-lsp_enum! {
-impl InsertTextMode {
- /// The insertion or replace strings is taken as it is. If the
- /// value is multi line the lines below the cursor will be
- /// inserted using the indentation defined in the string value.
- /// The client will not apply any kind of adjustments to the
- /// string.
- pub const AS_IS: InsertTextMode = InsertTextMode(1);
-
- /// The editor adjusts leading whitespace of new lines so that
- /// they match the indentation up to the cursor of the line for
- /// which the item is accepted.
- ///
- /// Consider a line like this: <2tabs><cursor><3tabs>foo. Accepting a
- /// multi line completion item is indented using 2 tabs all
- /// following lines inserted will be indented using 2 tabs as well.
- pub const ADJUST_INDENTATION: InsertTextMode = InsertTextMode(2);
-}
-}
-
-#[derive(Eq, PartialEq, Clone, Deserialize, Serialize)]
-#[serde(transparent)]
-pub struct CompletionItemTag(i32);
-lsp_enum! {
-impl CompletionItemTag {
- pub const DEPRECATED: CompletionItemTag = CompletionItemTag(1);
-}
-}
-
-#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
-#[serde(rename_all = "camelCase")]
-pub struct CompletionItemKindCapability {
- /// The completion item kind values the client supports. When this
- /// property exists the client also guarantees that it will
- /// handle values outside its set gracefully and falls back
- /// to a default value when unknown.
- ///
- /// If this property is not present the client only supports
- /// the completion items kinds from `Text` to `Reference` as defined in
- /// the initial version of the protocol.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub value_set: Option<Vec<CompletionItemKind>>,
-}
-
-#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
-#[serde(rename_all = "camelCase")]
-pub struct CompletionClientCapabilities {
- /// Whether completion supports dynamic registration.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub dynamic_registration: Option<bool>,
-
- /// The client supports the following `CompletionItem` specific
- /// capabilities.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub completion_item: Option<CompletionItemCapability>,
-
- #[serde(skip_serializing_if = "Option::is_none")]
- pub completion_item_kind: Option<CompletionItemKindCapability>,
-
- /// The client supports to send additional context information for a
- /// `textDocument/completion` requestion.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub context_support: Option<bool>,
-
- /// The client's default when the completion item doesn't provide a
- /// `insertTextMode` property.
- ///
- /// @since 3.17.0
- #[cfg(feature = "proposed")]
- #[serde(skip_serializing_if = "Option::is_none")]
- pub insert_text_mode: Option<InsertTextMode>,
-}
-
-/// A special text edit to provide an insert and a replace operation.
-///
-/// @since 3.16.0
-#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
-#[serde(rename_all = "camelCase")]
-pub struct InsertReplaceEdit {
- /// The string to be inserted.
- pub new_text: String,
-
- /// The range if the insert is requested
- pub insert: Range,
-
- /// The range if the replace is requested.
- pub replace: Range,
-}
-
-#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
-#[serde(untagged)]
-pub enum CompletionTextEdit {
- Edit(TextEdit),
- InsertAndReplace(InsertReplaceEdit),
-}
-
-impl From<TextEdit> for CompletionTextEdit {
- fn from(edit: TextEdit) -> Self {
- CompletionTextEdit::Edit(edit)
- }
-}
-
-impl From<InsertReplaceEdit> for CompletionTextEdit {
- fn from(edit: InsertReplaceEdit) -> Self {
- CompletionTextEdit::InsertAndReplace(edit)
- }
-}
-
-/// Completion options.
-#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
-#[serde(rename_all = "camelCase")]
-pub struct CompletionOptions {
- /// The server provides support to resolve additional information for a completion item.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub resolve_provider: Option<bool>,
-
- /// Most tools trigger completion request automatically without explicitly
- /// requesting it using a keyboard shortcut (e.g. Ctrl+Space). Typically they
- /// do so when the user starts to type an identifier. For example if the user
- /// types `c` in a JavaScript file code complete will automatically pop up
- /// present `console` besides others as a completion item. Characters that
- /// make up identifiers don't need to be listed here.
- ///
- /// If code complete should automatically be trigger on characters not being
- /// valid inside an identifier (for example `.` in JavaScript) list them in
- /// `triggerCharacters`.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub trigger_characters: Option<Vec<String>>,
-
- /// The list of all possible characters that commit a completion. This field
- /// can be used if clients don't support individual commit characters per
- /// completion item. See client capability
- /// `completion.completionItem.commitCharactersSupport`.
- ///
- /// If a server provides both `allCommitCharacters` and commit characters on
- /// an individual completion item the ones on the completion item win.
- ///
- /// @since 3.2.0
- #[serde(skip_serializing_if = "Option::is_none")]
- pub all_commit_characters: Option<Vec<String>>,
-
- #[serde(flatten)]
- pub work_done_progress_options: WorkDoneProgressOptions,
-
- /// The server supports the following `CompletionItem` specific
- /// capabilities.
- ///
- /// @since 3.17.0 - proposed state
- #[cfg(feature = "proposed")]
- #[serde(skip_serializing_if = "Option::is_none")]
- pub completion_item: Option<CompletionOptionsCompletionItem>,
-}
-
-#[cfg(feature = "proposed")]
-#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
-#[serde(rename_all = "camelCase")]
-pub struct CompletionOptionsCompletionItem {
- /// The server has support for completion item label
- /// details (see also `CompletionItemLabelDetails`) when receiving
- /// a completion item in a resolve call.
- ///
- /// @since 3.17.0 - proposed state
- #[serde(skip_serializing_if = "Option::is_none")]
- pub label_details_support: Option<bool>,
-}
-
-#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)]
-pub struct CompletionRegistrationOptions {
- #[serde(flatten)]
- pub text_document_registration_options: TextDocumentRegistrationOptions,
-
- #[serde(flatten)]
- pub completion_options: CompletionOptions,
-}
-
-#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)]
-#[serde(untagged)]
-pub enum CompletionResponse {
- Array(Vec<CompletionItem>),
- List(CompletionList),
-}
-
-impl From<Vec<CompletionItem>> for CompletionResponse {
- fn from(items: Vec<CompletionItem>) -> Self {
- CompletionResponse::Array(items)
- }
-}
-
-impl From<CompletionList> for CompletionResponse {
- fn from(list: CompletionList) -> Self {
- CompletionResponse::List(list)
- }
-}
-
-#[derive(Debug, PartialEq, Clone, Deserialize, Serialize)]
-#[serde(rename_all = "camelCase")]
-pub struct CompletionParams {
- // This field was "mixed-in" from TextDocumentPositionParams
- #[serde(flatten)]
- pub text_document_position: TextDocumentPositionParams,
-
- #[serde(flatten)]
- pub work_done_progress_params: WorkDoneProgressParams,
-
- #[serde(flatten)]
- pub partial_result_params: PartialResultParams,
-
- // CompletionParams properties:
- #[serde(skip_serializing_if = "Option::is_none")]
- pub context: Option<CompletionContext>,
-}
-
-#[derive(Debug, PartialEq, Clone, Deserialize, Serialize)]
-#[serde(rename_all = "camelCase")]
-pub struct CompletionContext {
- /// How the completion was triggered.
- pub trigger_kind: CompletionTriggerKind,
-
- /// The trigger character (a single character) that has trigger code complete.
- /// Is undefined if `triggerKind !== CompletionTriggerKind.TriggerCharacter`
- #[serde(skip_serializing_if = "Option::is_none")]
- pub trigger_character: Option<String>,
-}
-
-/// How a completion was triggered.
-#[derive(Eq, PartialEq, Clone, Copy, Deserialize, Serialize)]
-#[serde(transparent)]
-pub struct CompletionTriggerKind(i32);
-lsp_enum! {
-impl CompletionTriggerKind {
- pub const INVOKED: CompletionTriggerKind = CompletionTriggerKind(1);
- pub const TRIGGER_CHARACTER: CompletionTriggerKind = CompletionTriggerKind(2);
- pub const TRIGGER_FOR_INCOMPLETE_COMPLETIONS: CompletionTriggerKind = CompletionTriggerKind(3);
-}
-}
-
-/// Represents a collection of [completion items](#CompletionItem) to be presented
-/// in the editor.
-#[derive(Debug, PartialEq, Clone, Default, Deserialize, Serialize)]
-#[serde(rename_all = "camelCase")]
-pub struct CompletionList {
- /// This list it not complete. Further typing should result in recomputing
- /// this list.
- pub is_incomplete: bool,
-
- /// The completion items.
- pub items: Vec<CompletionItem>,
-}
-
-#[derive(Debug, PartialEq, Default, Deserialize, Serialize, Clone)]
-#[serde(rename_all = "camelCase")]
-pub struct CompletionItem {
- /// The label of this completion item. By default
- /// also the text that is inserted when selecting
- /// this completion.
- pub label: String,
-
- /// Additional details for the label
- ///
- /// @since 3.17.0 - proposed state
- ///
- #[cfg(feature = "proposed")]
- #[serde(skip_serializing_if = "Option::is_none")]
- pub label_details: Option<CompletionItemLabelDetails>,
-
- /// The kind of this completion item. Based of the kind
- /// an icon is chosen by the editor.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub kind: Option<CompletionItemKind>,
-
- /// A human-readable string with additional information
- /// about this item, like type or symbol information.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub detail: Option<String>,
-
- /// A human-readable string that represents a doc-comment.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub documentation: Option<Documentation>,
-
- /// Indicates if this item is deprecated.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub deprecated: Option<bool>,
-
- /// Select this item when showing.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub preselect: Option<bool>,
-
- /// A string that should be used when comparing this item
- /// with other items. When `falsy` the label is used
- /// as the sort text for this item.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub sort_text: Option<String>,
-
- /// A string that should be used when filtering a set of
- /// completion items. When `falsy` the label is used as the
- /// filter text for this item.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub filter_text: Option<String>,
-
- /// A string that should be inserted into a document when selecting
- /// this completion. When `falsy` the label is used as the insert text
- /// for this item.
- ///
- /// The `insertText` is subject to interpretation by the client side.
- /// Some tools might not take the string literally. For example
- /// VS Code when code complete is requested in this example
- /// `con<cursor position>` and a completion item with an `insertText` of
- /// `console` is provided it will only insert `sole`. Therefore it is
- /// recommended to use `textEdit` instead since it avoids additional client
- /// side interpretation.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub insert_text: Option<String>,
-
- /// The format of the insert text. The format applies to both the `insertText` property
- /// and the `newText` property of a provided `textEdit`. If omitted defaults to `InsertTextFormat.PlainText`.
- ///
- /// @since 3.16.0
- #[serde(skip_serializing_if = "Option::is_none")]
- pub insert_text_format: Option<InsertTextFormat>,
-
- /// How whitespace and indentation is handled during completion
- /// item insertion. If not provided the client's default value is used.
- ///
- /// @since 3.16.0
- #[serde(skip_serializing_if = "Option::is_none")]
- pub insert_text_mode: Option<InsertTextMode>,
-
- /// An edit which is applied to a document when selecting
- /// this completion. When an edit is provided the value of
- /// insertText is ignored.
- ///
- /// Most editors support two different operation when accepting a completion item. One is to insert a
-
- /// completion text and the other is to replace an existing text with a completion text. Since this can
- /// usually not predetermined by a server it can report both ranges. Clients need to signal support for
- /// `InsertReplaceEdits` via the `textDocument.completion.insertReplaceSupport` client capability
- /// property.
- ///
- /// *Note 1:* The text edit's range as well as both ranges from a insert replace edit must be a
- /// [single line] and they must contain the position at which completion has been requested.
- /// *Note 2:* If an `InsertReplaceEdit` is returned the edit's insert range must be a prefix of
- /// the edit's replace range, that means it must be contained and starting at the same position.
- ///
- /// @since 3.16.0 additional type `InsertReplaceEdit`
- #[serde(skip_serializing_if = "Option::is_none")]
- pub text_edit: Option<CompletionTextEdit>,
-
- /// An optional array of additional text edits that are applied when
- /// selecting this completion. Edits must not overlap with the main edit
- /// nor with themselves.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub additional_text_edits: Option<Vec<TextEdit>>,
-
- /// An optional command that is executed *after* inserting this completion. *Note* that
- /// additional modifications to the current document should be described with the
- /// additionalTextEdits-property.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub command: Option<Command>,
-
- /// An optional set of characters that when pressed while this completion is
- /// active will accept it first and then type that character. *Note* that all
- /// commit characters should have `length=1` and that superfluous characters
- /// will be ignored.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub commit_characters: Option<Vec<String>>,
-
- /// An data entry field that is preserved on a completion item between
- /// a completion and a completion resolve request.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub data: Option<Value>,
-
- /// Tags for this completion item.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub tags: Option<Vec<CompletionItemTag>>,
-}
-
-impl CompletionItem {
- /// Create a CompletionItem with the minimum possible info (label and detail).
- pub fn new_simple(label: String, detail: String) -> CompletionItem {
- CompletionItem {
- label,
- detail: Some(detail),
- ..Self::default()
- }
- }
-}
-
-/// Additional details for a completion item label.
-///
-/// @since 3.17.0 - proposed state
-#[cfg(feature = "proposed")]
-#[derive(Debug, PartialEq, Default, Deserialize, Serialize, Clone)]
-#[serde(rename_all = "camelCase")]
-pub struct CompletionItemLabelDetails {
- /// An optional string which is rendered less prominently directly after
- /// {@link CompletionItemLabel.label label}, without any spacing. Should be
- /// used for function signatures or type annotations.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub detail: Option<String>,
-
- /// An optional string which is rendered less prominently after
- /// {@link CompletionItemLabel.detail}. Should be used for fully qualified
- /// names or file path.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub description: Option<String>,
-}
-
-#[cfg(test)]
-mod tests {
- use super::*;
- use crate::tests::test_deserialization;
-
- #[test]
- fn test_tag_support_deserialization() {
- let mut empty = CompletionItemCapability::default();
- empty.tag_support = None;
-
- test_deserialization(r#"{}"#, &empty);
- test_deserialization(r#"{"tagSupport": false}"#, &empty);
-
- let mut t = CompletionItemCapability::default();
- t.tag_support = Some(TagSupport { value_set: vec![] });
- test_deserialization(r#"{"tagSupport": true}"#, &t);
-
- let mut t = CompletionItemCapability::default();
- t.tag_support = Some(TagSupport {
- value_set: vec![CompletionItemTag::DEPRECATED],
- });
- test_deserialization(r#"{"tagSupport": {"valueSet": [1]}}"#, &t);
- }
-
- #[test]
- fn test_debug_enum() {
- assert_eq!(format!("{:?}", CompletionItemKind::TEXT), "Text");
- assert_eq!(
- format!("{:?}", CompletionItemKind::TYPE_PARAMETER),
- "TypeParameter"
- );
- }
-
- #[test]
- fn test_try_from_enum() {
- use std::convert::TryInto;
- assert_eq!("Text".try_into(), Ok(CompletionItemKind::TEXT));
- assert_eq!(
- "TypeParameter".try_into(),
- Ok(CompletionItemKind::TYPE_PARAMETER)
- );
- }
-}
+use serde::{Deserialize, Serialize};
+
+use crate::{
+ Command, Documentation, MarkupKind, PartialResultParams, TagSupport,
+ TextDocumentPositionParams, TextDocumentRegistrationOptions, TextEdit, WorkDoneProgressOptions,
+ WorkDoneProgressParams,
+};
+
+use crate::Range;
+use serde_json::Value;
+use std::fmt::Debug;
+
+/// Defines how to interpret the insert text in a completion item
+#[derive(Eq, PartialEq, Clone, Copy, Serialize, Deserialize)]
+#[serde(transparent)]
+pub struct InsertTextFormat(i32);
+lsp_enum! {
+impl InsertTextFormat {
+ pub const PLAIN_TEXT: InsertTextFormat = InsertTextFormat(1);
+ pub const SNIPPET: InsertTextFormat = InsertTextFormat(2);
+}
+}
+
+/// The kind of a completion entry.
+#[derive(Eq, PartialEq, Clone, Copy, Serialize, Deserialize)]
+#[serde(transparent)]
+pub struct CompletionItemKind(i32);
+lsp_enum! {
+impl CompletionItemKind {
+ pub const TEXT: CompletionItemKind = CompletionItemKind(1);
+ pub const METHOD: CompletionItemKind = CompletionItemKind(2);
+ pub const FUNCTION: CompletionItemKind = CompletionItemKind(3);
+ pub const CONSTRUCTOR: CompletionItemKind = CompletionItemKind(4);
+ pub const FIELD: CompletionItemKind = CompletionItemKind(5);
+ pub const VARIABLE: CompletionItemKind = CompletionItemKind(6);
+ pub const CLASS: CompletionItemKind = CompletionItemKind(7);
+ pub const INTERFACE: CompletionItemKind = CompletionItemKind(8);
+ pub const MODULE: CompletionItemKind = CompletionItemKind(9);
+ pub const PROPERTY: CompletionItemKind = CompletionItemKind(10);
+ pub const UNIT: CompletionItemKind = CompletionItemKind(11);
+ pub const VALUE: CompletionItemKind = CompletionItemKind(12);
+ pub const ENUM: CompletionItemKind = CompletionItemKind(13);
+ pub const KEYWORD: CompletionItemKind = CompletionItemKind(14);
+ pub const SNIPPET: CompletionItemKind = CompletionItemKind(15);
+ pub const COLOR: CompletionItemKind = CompletionItemKind(16);
+ pub const FILE: CompletionItemKind = CompletionItemKind(17);
+ pub const REFERENCE: CompletionItemKind = CompletionItemKind(18);
+ pub const FOLDER: CompletionItemKind = CompletionItemKind(19);
+ pub const ENUM_MEMBER: CompletionItemKind = CompletionItemKind(20);
+ pub const CONSTANT: CompletionItemKind = CompletionItemKind(21);
+ pub const STRUCT: CompletionItemKind = CompletionItemKind(22);
+ pub const EVENT: CompletionItemKind = CompletionItemKind(23);
+ pub const OPERATOR: CompletionItemKind = CompletionItemKind(24);
+ pub const TYPE_PARAMETER: CompletionItemKind = CompletionItemKind(25);
+}
+}
+
+#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct CompletionItemCapability {
+ /// Client supports snippets as insert text.
+ ///
+ /// A snippet can define tab stops and placeholders with `$1`, `$2`
+ /// and `${3:foo}`. `$0` defines the final tab stop, it defaults to
+ /// the end of the snippet. Placeholders with equal identifiers are linked,
+ /// that is typing in one will update others too.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub snippet_support: Option<bool>,
+
+ /// Client supports commit characters on a completion item.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub commit_characters_support: Option<bool>,
+
+ /// Client supports the follow content formats for the documentation
+ /// property. The order describes the preferred format of the client.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub documentation_format: Option<Vec<MarkupKind>>,
+
+ /// Client supports the deprecated property on a completion item.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub deprecated_support: Option<bool>,
+
+ /// Client supports the preselect property on a completion item.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub preselect_support: Option<bool>,
+
+ /// Client supports the tag property on a completion item. Clients supporting
+ /// tags have to handle unknown tags gracefully. Clients especially need to
+ /// preserve unknown tags when sending a completion item back to the server in
+ /// a resolve call.
+ #[serde(
+ default,
+ skip_serializing_if = "Option::is_none",
+ deserialize_with = "TagSupport::deserialize_compat"
+ )]
+ pub tag_support: Option<TagSupport<CompletionItemTag>>,
+
+ /// Client support insert replace edit to control different behavior if a
+ /// completion item is inserted in the text or should replace text.
+ ///
+ /// @since 3.16.0
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub insert_replace_support: Option<bool>,
+
+ /// Indicates which properties a client can resolve lazily on a completion
+ /// item. Before version 3.16.0 only the predefined properties `documentation`
+ /// and `details` could be resolved lazily.
+ ///
+ /// @since 3.16.0
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub resolve_support: Option<CompletionItemCapabilityResolveSupport>,
+
+ /// The client supports the `insertTextMode` property on
+ /// a completion item to override the whitespace handling mode
+ /// as defined by the client.
+ ///
+ /// @since 3.16.0
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub insert_text_mode_support: Option<InsertTextModeSupport>,
+
+ /// The client has support for completion item label
+ /// details (see also `CompletionItemLabelDetails`).
+ ///
+ /// @since 3.17.0
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub label_details_support: Option<bool>,
+}
+
+#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct CompletionItemCapabilityResolveSupport {
+ /// The properties that a client can resolve lazily.
+ pub properties: Vec<String>,
+}
+
+#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct InsertTextModeSupport {
+ pub value_set: Vec<InsertTextMode>,
+}
+
+/// How whitespace and indentation is handled during completion
+/// item insertion.
+///
+/// @since 3.16.0
+#[derive(Eq, PartialEq, Clone, Copy, Serialize, Deserialize)]
+#[serde(transparent)]
+pub struct InsertTextMode(i32);
+lsp_enum! {
+impl InsertTextMode {
+ /// The insertion or replace strings is taken as it is. If the
+ /// value is multi line the lines below the cursor will be
+ /// inserted using the indentation defined in the string value.
+ /// The client will not apply any kind of adjustments to the
+ /// string.
+ pub const AS_IS: InsertTextMode = InsertTextMode(1);
+
+ /// The editor adjusts leading whitespace of new lines so that
+ /// they match the indentation up to the cursor of the line for
+ /// which the item is accepted.
+ ///
+ /// Consider a line like this: <2tabs><cursor><3tabs>foo. Accepting a
+ /// multi line completion item is indented using 2 tabs all
+ /// following lines inserted will be indented using 2 tabs as well.
+ pub const ADJUST_INDENTATION: InsertTextMode = InsertTextMode(2);
+}
+}
+
+#[derive(Eq, PartialEq, Clone, Deserialize, Serialize)]
+#[serde(transparent)]
+pub struct CompletionItemTag(i32);
+lsp_enum! {
+impl CompletionItemTag {
+ pub const DEPRECATED: CompletionItemTag = CompletionItemTag(1);
+}
+}
+
+#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct CompletionItemKindCapability {
+ /// The completion item kind values the client supports. When this
+ /// property exists the client also guarantees that it will
+ /// handle values outside its set gracefully and falls back
+ /// to a default value when unknown.
+ ///
+ /// If this property is not present the client only supports
+ /// the completion items kinds from `Text` to `Reference` as defined in
+ /// the initial version of the protocol.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub value_set: Option<Vec<CompletionItemKind>>,
+}
+
+#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct CompletionListCapability {
+ /// The client supports the following itemDefaults on
+ /// a completion list.
+ ///
+ /// The value lists the supported property names of the
+ /// `CompletionList.itemDefaults` object. If omitted
+ /// no properties are supported.
+ ///
+ /// @since 3.17.0
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub item_defaults: Option<Vec<String>>,
+}
+
+#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct CompletionClientCapabilities {
+ /// Whether completion supports dynamic registration.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub dynamic_registration: Option<bool>,
+
+ /// The client supports the following `CompletionItem` specific
+ /// capabilities.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub completion_item: Option<CompletionItemCapability>,
+
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub completion_item_kind: Option<CompletionItemKindCapability>,
+
+ /// The client supports to send additional context information for a
+ /// `textDocument/completion` requestion.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub context_support: Option<bool>,
+
+ /// The client's default when the completion item doesn't provide a
+ /// `insertTextMode` property.
+ ///
+ /// @since 3.17.0
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub insert_text_mode: Option<InsertTextMode>,
+
+ /// The client supports the following `CompletionList` specific
+ /// capabilities.
+ ///
+ /// @since 3.17.0
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub completion_list: Option<CompletionListCapability>,
+}
+
+/// A special text edit to provide an insert and a replace operation.
+///
+/// @since 3.16.0
+#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct InsertReplaceEdit {
+ /// The string to be inserted.
+ pub new_text: String,
+
+ /// The range if the insert is requested
+ pub insert: Range,
+
+ /// The range if the replace is requested.
+ pub replace: Range,
+}
+
+#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
+#[serde(untagged)]
+pub enum CompletionTextEdit {
+ Edit(TextEdit),
+ InsertAndReplace(InsertReplaceEdit),
+}
+
+impl From<TextEdit> for CompletionTextEdit {
+ fn from(edit: TextEdit) -> Self {
+ CompletionTextEdit::Edit(edit)
+ }
+}
+
+impl From<InsertReplaceEdit> for CompletionTextEdit {
+ fn from(edit: InsertReplaceEdit) -> Self {
+ CompletionTextEdit::InsertAndReplace(edit)
+ }
+}
+
+/// Completion options.
+#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct CompletionOptions {
+ /// The server provides support to resolve additional information for a completion item.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub resolve_provider: Option<bool>,
+
+ /// Most tools trigger completion request automatically without explicitly
+ /// requesting it using a keyboard shortcut (e.g. Ctrl+Space). Typically they
+ /// do so when the user starts to type an identifier. For example if the user
+ /// types `c` in a JavaScript file code complete will automatically pop up
+ /// present `console` besides others as a completion item. Characters that
+ /// make up identifiers don't need to be listed here.
+ ///
+ /// If code complete should automatically be trigger on characters not being
+ /// valid inside an identifier (for example `.` in JavaScript) list them in
+ /// `triggerCharacters`.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub trigger_characters: Option<Vec<String>>,
+
+ /// The list of all possible characters that commit a completion. This field
+ /// can be used if clients don't support individual commit characters per
+ /// completion item. See client capability
+ /// `completion.completionItem.commitCharactersSupport`.
+ ///
+ /// If a server provides both `allCommitCharacters` and commit characters on
+ /// an individual completion item the ones on the completion item win.
+ ///
+ /// @since 3.2.0
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub all_commit_characters: Option<Vec<String>>,
+
+ #[serde(flatten)]
+ pub work_done_progress_options: WorkDoneProgressOptions,
+
+ /// The server supports the following `CompletionItem` specific
+ /// capabilities.
+ ///
+ /// @since 3.17.0
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub completion_item: Option<CompletionOptionsCompletionItem>,
+}
+
+#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct CompletionOptionsCompletionItem {
+ /// The server has support for completion item label
+ /// details (see also `CompletionItemLabelDetails`) when receiving
+ /// a completion item in a resolve call.
+ ///
+ /// @since 3.17.0
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub label_details_support: Option<bool>,
+}
+
+#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)]
+pub struct CompletionRegistrationOptions {
+ #[serde(flatten)]
+ pub text_document_registration_options: TextDocumentRegistrationOptions,
+
+ #[serde(flatten)]
+ pub completion_options: CompletionOptions,
+}
+
+#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)]
+#[serde(untagged)]
+pub enum CompletionResponse {
+ Array(Vec<CompletionItem>),
+ List(CompletionList),
+}
+
+impl From<Vec<CompletionItem>> for CompletionResponse {
+ fn from(items: Vec<CompletionItem>) -> Self {
+ CompletionResponse::Array(items)
+ }
+}
+
+impl From<CompletionList> for CompletionResponse {
+ fn from(list: CompletionList) -> Self {
+ CompletionResponse::List(list)
+ }
+}
+
+#[derive(Debug, PartialEq, Clone, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct CompletionParams {
+ // This field was "mixed-in" from TextDocumentPositionParams
+ #[serde(flatten)]
+ pub text_document_position: TextDocumentPositionParams,
+
+ #[serde(flatten)]
+ pub work_done_progress_params: WorkDoneProgressParams,
+
+ #[serde(flatten)]
+ pub partial_result_params: PartialResultParams,
+
+ // CompletionParams properties:
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub context: Option<CompletionContext>,
+}
+
+#[derive(Debug, PartialEq, Clone, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct CompletionContext {
+ /// How the completion was triggered.
+ pub trigger_kind: CompletionTriggerKind,
+
+ /// The trigger character (a single character) that has trigger code complete.
+ /// Is undefined if `triggerKind !== CompletionTriggerKind.TriggerCharacter`
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub trigger_character: Option<String>,
+}
+
+/// How a completion was triggered.
+#[derive(Eq, PartialEq, Clone, Copy, Deserialize, Serialize)]
+#[serde(transparent)]
+pub struct CompletionTriggerKind(i32);
+lsp_enum! {
+impl CompletionTriggerKind {
+ pub const INVOKED: CompletionTriggerKind = CompletionTriggerKind(1);
+ pub const TRIGGER_CHARACTER: CompletionTriggerKind = CompletionTriggerKind(2);
+ pub const TRIGGER_FOR_INCOMPLETE_COMPLETIONS: CompletionTriggerKind = CompletionTriggerKind(3);
+}
+}
+
+/// Represents a collection of [completion items](#CompletionItem) to be presented
+/// in the editor.
+#[derive(Debug, PartialEq, Clone, Default, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct CompletionList {
+ /// This list it not complete. Further typing should result in recomputing
+ /// this list.
+ pub is_incomplete: bool,
+
+ /// The completion items.
+ pub items: Vec<CompletionItem>,
+}
+
+#[derive(Debug, PartialEq, Default, Deserialize, Serialize, Clone)]
+#[serde(rename_all = "camelCase")]
+pub struct CompletionItem {
+ /// The label of this completion item. By default
+ /// also the text that is inserted when selecting
+ /// this completion.
+ pub label: String,
+
+ /// Additional details for the label
+ ///
+ /// @since 3.17.0
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub label_details: Option<CompletionItemLabelDetails>,
+
+ /// The kind of this completion item. Based of the kind
+ /// an icon is chosen by the editor.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub kind: Option<CompletionItemKind>,
+
+ /// A human-readable string with additional information
+ /// about this item, like type or symbol information.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub detail: Option<String>,
+
+ /// A human-readable string that represents a doc-comment.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub documentation: Option<Documentation>,
+
+ /// Indicates if this item is deprecated.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub deprecated: Option<bool>,
+
+ /// Select this item when showing.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub preselect: Option<bool>,
+
+ /// A string that should be used when comparing this item
+ /// with other items. When `falsy` the label is used
+ /// as the sort text for this item.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub sort_text: Option<String>,
+
+ /// A string that should be used when filtering a set of
+ /// completion items. When `falsy` the label is used as the
+ /// filter text for this item.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub filter_text: Option<String>,
+
+ /// A string that should be inserted into a document when selecting
+ /// this completion. When `falsy` the label is used as the insert text
+ /// for this item.
+ ///
+ /// The `insertText` is subject to interpretation by the client side.
+ /// Some tools might not take the string literally. For example
+ /// VS Code when code complete is requested in this example
+ /// `con<cursor position>` and a completion item with an `insertText` of
+ /// `console` is provided it will only insert `sole`. Therefore it is
+ /// recommended to use `textEdit` instead since it avoids additional client
+ /// side interpretation.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub insert_text: Option<String>,
+
+ /// The format of the insert text. The format applies to both the `insertText` property
+ /// and the `newText` property of a provided `textEdit`. If omitted defaults to `InsertTextFormat.PlainText`.
+ ///
+ /// @since 3.16.0
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub insert_text_format: Option<InsertTextFormat>,
+
+ /// How whitespace and indentation is handled during completion
+ /// item insertion. If not provided the client's default value depends on
+ /// the `textDocument.completion.insertTextMode` client capability.
+ ///
+ /// @since 3.16.0
+ /// @since 3.17.0 - support for `textDocument.completion.insertTextMode`
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub insert_text_mode: Option<InsertTextMode>,
+
+ /// An edit which is applied to a document when selecting
+ /// this completion. When an edit is provided the value of
+ /// insertText is ignored.
+ ///
+ /// Most editors support two different operation when accepting a completion item. One is to insert a
+
+ /// completion text and the other is to replace an existing text with a completion text. Since this can
+ /// usually not predetermined by a server it can report both ranges. Clients need to signal support for
+ /// `InsertReplaceEdits` via the `textDocument.completion.insertReplaceSupport` client capability
+ /// property.
+ ///
+ /// *Note 1:* The text edit's range as well as both ranges from a insert replace edit must be a
+ /// [single line] and they must contain the position at which completion has been requested.
+ /// *Note 2:* If an `InsertReplaceEdit` is returned the edit's insert range must be a prefix of
+ /// the edit's replace range, that means it must be contained and starting at the same position.
+ ///
+ /// @since 3.16.0 additional type `InsertReplaceEdit`
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub text_edit: Option<CompletionTextEdit>,
+
+ /// An optional array of additional text edits that are applied when
+ /// selecting this completion. Edits must not overlap with the main edit
+ /// nor with themselves.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub additional_text_edits: Option<Vec<TextEdit>>,
+
+ /// An optional command that is executed *after* inserting this completion. *Note* that
+ /// additional modifications to the current document should be described with the
+ /// additionalTextEdits-property.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub command: Option<Command>,
+
+ /// An optional set of characters that when pressed while this completion is
+ /// active will accept it first and then type that character. *Note* that all
+ /// commit characters should have `length=1` and that superfluous characters
+ /// will be ignored.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub commit_characters: Option<Vec<String>>,
+
+ /// An data entry field that is preserved on a completion item between
+ /// a completion and a completion resolve request.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub data: Option<Value>,
+
+ /// Tags for this completion item.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub tags: Option<Vec<CompletionItemTag>>,
+}
+
+impl CompletionItem {
+ /// Create a CompletionItem with the minimum possible info (label and detail).
+ pub fn new_simple(label: String, detail: String) -> CompletionItem {
+ CompletionItem {
+ label,
+ detail: Some(detail),
+ ..Self::default()
+ }
+ }
+}
+
+/// Additional details for a completion item label.
+///
+/// @since 3.17.0
+#[derive(Debug, PartialEq, Default, Deserialize, Serialize, Clone)]
+#[serde(rename_all = "camelCase")]
+pub struct CompletionItemLabelDetails {
+ /// An optional string which is rendered less prominently directly after
+ /// {@link CompletionItemLabel.label label}, without any spacing. Should be
+ /// used for function signatures or type annotations.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub detail: Option<String>,
+
+ /// An optional string which is rendered less prominently after
+ /// {@link CompletionItemLabel.detail}. Should be used for fully qualified
+ /// names or file path.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub description: Option<String>,
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+ use crate::tests::test_deserialization;
+
+ #[test]
+ fn test_tag_support_deserialization() {
+ let mut empty = CompletionItemCapability::default();
+ empty.tag_support = None;
+
+ test_deserialization(r#"{}"#, &empty);
+ test_deserialization(r#"{"tagSupport": false}"#, &empty);
+
+ let mut t = CompletionItemCapability::default();
+ t.tag_support = Some(TagSupport { value_set: vec![] });
+ test_deserialization(r#"{"tagSupport": true}"#, &t);
+
+ let mut t = CompletionItemCapability::default();
+ t.tag_support = Some(TagSupport {
+ value_set: vec![CompletionItemTag::DEPRECATED],
+ });
+ test_deserialization(r#"{"tagSupport": {"valueSet": [1]}}"#, &t);
+ }
+
+ #[test]
+ fn test_debug_enum() {
+ assert_eq!(format!("{:?}", CompletionItemKind::TEXT), "Text");
+ assert_eq!(
+ format!("{:?}", CompletionItemKind::TYPE_PARAMETER),
+ "TypeParameter"
+ );
+ }
+
+ #[test]
+ fn test_try_from_enum() {
+ use std::convert::TryInto;
+ assert_eq!("Text".try_into(), Ok(CompletionItemKind::TEXT));
+ assert_eq!(
+ "TypeParameter".try_into(),
+ Ok(CompletionItemKind::TYPE_PARAMETER)
+ );
+ }
+}
diff --git a/vendor/lsp-types/src/document_highlight.rs b/vendor/lsp-types/src/document_highlight.rs
index 9a97c104b..d7cd1ae18 100644
--- a/vendor/lsp-types/src/document_highlight.rs
+++ b/vendor/lsp-types/src/document_highlight.rs
@@ -1,51 +1,51 @@
-use serde::{Deserialize, Serialize};
-
-use crate::{
- DynamicRegistrationClientCapabilities, PartialResultParams, Range, TextDocumentPositionParams,
- WorkDoneProgressParams,
-};
-
-pub type DocumentHighlightClientCapabilities = DynamicRegistrationClientCapabilities;
-
-#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
-#[serde(rename_all = "camelCase")]
-pub struct DocumentHighlightParams {
- #[serde(flatten)]
- pub text_document_position_params: TextDocumentPositionParams,
-
- #[serde(flatten)]
- pub work_done_progress_params: WorkDoneProgressParams,
-
- #[serde(flatten)]
- pub partial_result_params: PartialResultParams,
-}
-
-/// A document highlight is a range inside a text document which deserves
-/// special attention. Usually a document highlight is visualized by changing
-/// the background color of its range.
-#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
-pub struct DocumentHighlight {
- /// The range this highlight applies to.
- pub range: Range,
-
- /// The highlight kind, default is DocumentHighlightKind.Text.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub kind: Option<DocumentHighlightKind>,
-}
-
-/// A document highlight kind.
-#[derive(Eq, PartialEq, Copy, Clone, Deserialize, Serialize)]
-#[serde(transparent)]
-pub struct DocumentHighlightKind(i32);
-lsp_enum! {
-impl DocumentHighlightKind {
- /// A textual occurrance.
- pub const TEXT: DocumentHighlightKind = DocumentHighlightKind(1);
-
- /// Read-access of a symbol, like reading a variable.
- pub const READ: DocumentHighlightKind = DocumentHighlightKind(2);
-
- /// Write-access of a symbol, like writing to a variable.
- pub const WRITE: DocumentHighlightKind = DocumentHighlightKind(3);
-}
-}
+use serde::{Deserialize, Serialize};
+
+use crate::{
+ DynamicRegistrationClientCapabilities, PartialResultParams, Range, TextDocumentPositionParams,
+ WorkDoneProgressParams,
+};
+
+pub type DocumentHighlightClientCapabilities = DynamicRegistrationClientCapabilities;
+
+#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct DocumentHighlightParams {
+ #[serde(flatten)]
+ pub text_document_position_params: TextDocumentPositionParams,
+
+ #[serde(flatten)]
+ pub work_done_progress_params: WorkDoneProgressParams,
+
+ #[serde(flatten)]
+ pub partial_result_params: PartialResultParams,
+}
+
+/// A document highlight is a range inside a text document which deserves
+/// special attention. Usually a document highlight is visualized by changing
+/// the background color of its range.
+#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
+pub struct DocumentHighlight {
+ /// The range this highlight applies to.
+ pub range: Range,
+
+ /// The highlight kind, default is DocumentHighlightKind.Text.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub kind: Option<DocumentHighlightKind>,
+}
+
+/// A document highlight kind.
+#[derive(Eq, PartialEq, Copy, Clone, Deserialize, Serialize)]
+#[serde(transparent)]
+pub struct DocumentHighlightKind(i32);
+lsp_enum! {
+impl DocumentHighlightKind {
+ /// A textual occurrance.
+ pub const TEXT: DocumentHighlightKind = DocumentHighlightKind(1);
+
+ /// Read-access of a symbol, like reading a variable.
+ pub const READ: DocumentHighlightKind = DocumentHighlightKind(2);
+
+ /// Write-access of a symbol, like writing to a variable.
+ pub const WRITE: DocumentHighlightKind = DocumentHighlightKind(3);
+}
+}
diff --git a/vendor/lsp-types/src/document_link.rs b/vendor/lsp-types/src/document_link.rs
index 1400dd96b..df57df29f 100644
--- a/vendor/lsp-types/src/document_link.rs
+++ b/vendor/lsp-types/src/document_link.rs
@@ -1,67 +1,67 @@
-use crate::{
- PartialResultParams, Range, TextDocumentIdentifier, WorkDoneProgressOptions,
- WorkDoneProgressParams,
-};
-use serde::{Deserialize, Serialize};
-use serde_json::Value;
-use url::Url;
-
-#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
-#[serde(rename_all = "camelCase")]
-pub struct DocumentLinkClientCapabilities {
- /// Whether document link supports dynamic registration.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub dynamic_registration: Option<bool>,
-
- /// Whether the client support the `tooltip` property on `DocumentLink`.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub tooltip_support: Option<bool>,
-}
-
-#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
-#[serde(rename_all = "camelCase")]
-pub struct DocumentLinkOptions {
- /// Document links have a resolve provider as well.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub resolve_provider: Option<bool>,
-
- #[serde(flatten)]
- pub work_done_progress_options: WorkDoneProgressOptions,
-}
-
-#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
-#[serde(rename_all = "camelCase")]
-pub struct DocumentLinkParams {
- /// The document to provide document links for.
- pub text_document: TextDocumentIdentifier,
-
- #[serde(flatten)]
- pub work_done_progress_params: WorkDoneProgressParams,
-
- #[serde(flatten)]
- pub partial_result_params: PartialResultParams,
-}
-
-/// A document link is a range in a text document that links to an internal or external resource, like another
-/// text document or a web site.
-#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
-pub struct DocumentLink {
- /// The range this link applies to.
- pub range: Range,
- /// The uri this link points to.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub target: Option<Url>,
-
- /// The tooltip text when you hover over this link.
- ///
- /// If a tooltip is provided, is will be displayed in a string that includes instructions on how to
- /// trigger the link, such as `{0} (ctrl + click)`. The specific instructions vary depending on OS,
- /// user settings, and localization.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub tooltip: Option<String>,
-
- /// A data entry field that is preserved on a document link between a DocumentLinkRequest
- /// and a DocumentLinkResolveRequest.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub data: Option<Value>,
-}
+use crate::{
+ PartialResultParams, Range, TextDocumentIdentifier, WorkDoneProgressOptions,
+ WorkDoneProgressParams,
+};
+use serde::{Deserialize, Serialize};
+use serde_json::Value;
+use url::Url;
+
+#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct DocumentLinkClientCapabilities {
+ /// Whether document link supports dynamic registration.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub dynamic_registration: Option<bool>,
+
+ /// Whether the client support the `tooltip` property on `DocumentLink`.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub tooltip_support: Option<bool>,
+}
+
+#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct DocumentLinkOptions {
+ /// Document links have a resolve provider as well.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub resolve_provider: Option<bool>,
+
+ #[serde(flatten)]
+ pub work_done_progress_options: WorkDoneProgressOptions,
+}
+
+#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct DocumentLinkParams {
+ /// The document to provide document links for.
+ pub text_document: TextDocumentIdentifier,
+
+ #[serde(flatten)]
+ pub work_done_progress_params: WorkDoneProgressParams,
+
+ #[serde(flatten)]
+ pub partial_result_params: PartialResultParams,
+}
+
+/// A document link is a range in a text document that links to an internal or external resource, like another
+/// text document or a web site.
+#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
+pub struct DocumentLink {
+ /// The range this link applies to.
+ pub range: Range,
+ /// The uri this link points to.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub target: Option<Url>,
+
+ /// The tooltip text when you hover over this link.
+ ///
+ /// If a tooltip is provided, is will be displayed in a string that includes instructions on how to
+ /// trigger the link, such as `{0} (ctrl + click)`. The specific instructions vary depending on OS,
+ /// user settings, and localization.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub tooltip: Option<String>,
+
+ /// A data entry field that is preserved on a document link between a DocumentLinkRequest
+ /// and a DocumentLinkResolveRequest.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub data: Option<Value>,
+}
diff --git a/vendor/lsp-types/src/document_symbols.rs b/vendor/lsp-types/src/document_symbols.rs
index f8b166f57..61d0c2520 100644
--- a/vendor/lsp-types/src/document_symbols.rs
+++ b/vendor/lsp-types/src/document_symbols.rs
@@ -1,132 +1,132 @@
-use crate::{
- Location, PartialResultParams, Range, SymbolKind, SymbolKindCapability, TextDocumentIdentifier,
- WorkDoneProgressParams,
-};
-
-use crate::{SymbolTag, TagSupport};
-
-use serde::{Deserialize, Serialize};
-
-#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
-#[serde(rename_all = "camelCase")]
-pub struct DocumentSymbolClientCapabilities {
- /// This capability supports dynamic registration.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub dynamic_registration: Option<bool>,
-
- /// Specific capabilities for the `SymbolKind`.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub symbol_kind: Option<SymbolKindCapability>,
-
- /// The client support hierarchical document symbols.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub hierarchical_document_symbol_support: Option<bool>,
-
- /// The client supports tags on `SymbolInformation`. Tags are supported on
- /// `DocumentSymbol` if `hierarchicalDocumentSymbolSupport` is set to true.
- /// Clients supporting tags have to handle unknown tags gracefully.
- ///
- /// @since 3.16.0
- #[serde(
- default,
- skip_serializing_if = "Option::is_none",
- deserialize_with = "TagSupport::deserialize_compat"
- )]
- pub tag_support: Option<TagSupport<SymbolTag>>,
-}
-
-#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)]
-#[serde(untagged)]
-pub enum DocumentSymbolResponse {
- Flat(Vec<SymbolInformation>),
- Nested(Vec<DocumentSymbol>),
-}
-
-impl From<Vec<SymbolInformation>> for DocumentSymbolResponse {
- fn from(info: Vec<SymbolInformation>) -> Self {
- DocumentSymbolResponse::Flat(info)
- }
-}
-
-impl From<Vec<DocumentSymbol>> for DocumentSymbolResponse {
- fn from(symbols: Vec<DocumentSymbol>) -> Self {
- DocumentSymbolResponse::Nested(symbols)
- }
-}
-
-#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
-#[serde(rename_all = "camelCase")]
-pub struct DocumentSymbolParams {
- /// The text document.
- pub text_document: TextDocumentIdentifier,
-
- #[serde(flatten)]
- pub work_done_progress_params: WorkDoneProgressParams,
-
- #[serde(flatten)]
- pub partial_result_params: PartialResultParams,
-}
-
-/// Represents programming constructs like variables, classes, interfaces etc.
-/// that appear in a document. Document symbols can be hierarchical and they have two ranges:
-/// one that encloses its definition and one that points to its most interesting range,
-/// e.g. the range of an identifier.
-#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
-#[serde(rename_all = "camelCase")]
-pub struct DocumentSymbol {
- /// The name of this symbol.
- pub name: String,
- /// More detail for this symbol, e.g the signature of a function. If not provided the
- /// name is used.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub detail: Option<String>,
- /// The kind of this symbol.
- pub kind: SymbolKind,
- /// Tags for this completion item.
- /// since 3.16.0
- #[serde(skip_serializing_if = "Option::is_none")]
- pub tags: Option<Vec<SymbolTag>>,
- /// Indicates if this symbol is deprecated.
- #[serde(skip_serializing_if = "Option::is_none")]
- #[deprecated(note = "Use tags instead")]
- pub deprecated: Option<bool>,
- /// The range enclosing this symbol not including leading/trailing whitespace but everything else
- /// like comments. This information is typically used to determine if the the clients cursor is
- /// inside the symbol to reveal in the symbol in the UI.
- pub range: Range,
- /// The range that should be selected and revealed when this symbol is being picked, e.g the name of a function.
- /// Must be contained by the the `range`.
- pub selection_range: Range,
- /// Children of this symbol, e.g. properties of a class.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub children: Option<Vec<DocumentSymbol>>,
-}
-
-/// Represents information about programming constructs like variables, classes,
-/// interfaces etc.
-#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
-#[serde(rename_all = "camelCase")]
-pub struct SymbolInformation {
- /// The name of this symbol.
- pub name: String,
-
- /// The kind of this symbol.
- pub kind: SymbolKind,
-
- /// Tags for this completion item.
- /// since 3.16.0
- #[serde(skip_serializing_if = "Option::is_none")]
- pub tags: Option<Vec<SymbolTag>>,
-
- /// Indicates if this symbol is deprecated.
- #[serde(skip_serializing_if = "Option::is_none")]
- #[deprecated(note = "Use tags instead")]
- pub deprecated: Option<bool>,
-
- /// The location of this symbol.
- pub location: Location,
-
- /// The name of the symbol containing this symbol.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub container_name: Option<String>,
-}
+use crate::{
+ Location, PartialResultParams, Range, SymbolKind, SymbolKindCapability, TextDocumentIdentifier,
+ WorkDoneProgressParams,
+};
+
+use crate::{SymbolTag, TagSupport};
+
+use serde::{Deserialize, Serialize};
+
+#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct DocumentSymbolClientCapabilities {
+ /// This capability supports dynamic registration.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub dynamic_registration: Option<bool>,
+
+ /// Specific capabilities for the `SymbolKind`.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub symbol_kind: Option<SymbolKindCapability>,
+
+ /// The client support hierarchical document symbols.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub hierarchical_document_symbol_support: Option<bool>,
+
+ /// The client supports tags on `SymbolInformation`. Tags are supported on
+ /// `DocumentSymbol` if `hierarchicalDocumentSymbolSupport` is set to true.
+ /// Clients supporting tags have to handle unknown tags gracefully.
+ ///
+ /// @since 3.16.0
+ #[serde(
+ default,
+ skip_serializing_if = "Option::is_none",
+ deserialize_with = "TagSupport::deserialize_compat"
+ )]
+ pub tag_support: Option<TagSupport<SymbolTag>>,
+}
+
+#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)]
+#[serde(untagged)]
+pub enum DocumentSymbolResponse {
+ Flat(Vec<SymbolInformation>),
+ Nested(Vec<DocumentSymbol>),
+}
+
+impl From<Vec<SymbolInformation>> for DocumentSymbolResponse {
+ fn from(info: Vec<SymbolInformation>) -> Self {
+ DocumentSymbolResponse::Flat(info)
+ }
+}
+
+impl From<Vec<DocumentSymbol>> for DocumentSymbolResponse {
+ fn from(symbols: Vec<DocumentSymbol>) -> Self {
+ DocumentSymbolResponse::Nested(symbols)
+ }
+}
+
+#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct DocumentSymbolParams {
+ /// The text document.
+ pub text_document: TextDocumentIdentifier,
+
+ #[serde(flatten)]
+ pub work_done_progress_params: WorkDoneProgressParams,
+
+ #[serde(flatten)]
+ pub partial_result_params: PartialResultParams,
+}
+
+/// Represents programming constructs like variables, classes, interfaces etc.
+/// that appear in a document. Document symbols can be hierarchical and they have two ranges:
+/// one that encloses its definition and one that points to its most interesting range,
+/// e.g. the range of an identifier.
+#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct DocumentSymbol {
+ /// The name of this symbol.
+ pub name: String,
+ /// More detail for this symbol, e.g the signature of a function. If not provided the
+ /// name is used.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub detail: Option<String>,
+ /// The kind of this symbol.
+ pub kind: SymbolKind,
+ /// Tags for this completion item.
+ /// since 3.16.0
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub tags: Option<Vec<SymbolTag>>,
+ /// Indicates if this symbol is deprecated.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ #[deprecated(note = "Use tags instead")]
+ pub deprecated: Option<bool>,
+ /// The range enclosing this symbol not including leading/trailing whitespace but everything else
+ /// like comments. This information is typically used to determine if the the clients cursor is
+ /// inside the symbol to reveal in the symbol in the UI.
+ pub range: Range,
+ /// The range that should be selected and revealed when this symbol is being picked, e.g the name of a function.
+ /// Must be contained by the the `range`.
+ pub selection_range: Range,
+ /// Children of this symbol, e.g. properties of a class.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub children: Option<Vec<DocumentSymbol>>,
+}
+
+/// Represents information about programming constructs like variables, classes,
+/// interfaces etc.
+#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct SymbolInformation {
+ /// The name of this symbol.
+ pub name: String,
+
+ /// The kind of this symbol.
+ pub kind: SymbolKind,
+
+ /// Tags for this completion item.
+ /// since 3.16.0
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub tags: Option<Vec<SymbolTag>>,
+
+ /// Indicates if this symbol is deprecated.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ #[deprecated(note = "Use tags instead")]
+ pub deprecated: Option<bool>,
+
+ /// The location of this symbol.
+ pub location: Location,
+
+ /// The name of the symbol containing this symbol.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub container_name: Option<String>,
+}
diff --git a/vendor/lsp-types/src/error_codes.rs b/vendor/lsp-types/src/error_codes.rs
index 9435a7261..1d0c1d571 100644
--- a/vendor/lsp-types/src/error_codes.rs
+++ b/vendor/lsp-types/src/error_codes.rs
@@ -1,37 +1,36 @@
-//! In this module we only define constants for lsp specific error codes.
-//! There are other error codes that are defined in the
-//! [JSON RPC specification](https://www.jsonrpc.org/specification#error_object).
-
-// This is the start range of LSP reserved error codes.
-// It doesn't denote a real error code.
-//
-// @since 3.16.0
-pub const LSP_RESERVED_ERROR_RANGE_START: i64 = -32899;
-
-// The server cancelled the request. This error code should
-// only be used for requests that explicitly support being
-// server cancellable.
-//
-// @since 3.17.0
-#[cfg(feature = "proposed")]
-pub const SERVER_CANCELLED: i64 = -32802;
-
-// The server detected that the content of a document got
-// modified outside normal conditions. A server should
-// NOT send this error code if it detects a content change
-// in it unprocessed messages. The result even computed
-// on an older state might still be useful for the client.
-//
-// If a client decides that a result is not of any use anymore
-// the client should cancel the request.
-pub const CONTENT_MODIFIED: i64 = -32801;
-
-// The client has canceled a request and a server as detected
-// the cancel.
-pub const REQUEST_CANCELLED: i64 = -32800;
-
-// This is the end range of LSP reserved error codes.
-// It doesn't denote a real error code.
-//
-// @since 3.16.0
-pub const LSP_RESERVED_ERROR_RANGE_END: i64 = -32800;
+//! In this module we only define constants for lsp specific error codes.
+//! There are other error codes that are defined in the
+//! [JSON RPC specification](https://www.jsonrpc.org/specification#error_object).
+
+// This is the start range of LSP reserved error codes.
+// It doesn't denote a real error code.
+//
+// @since 3.16.0
+pub const LSP_RESERVED_ERROR_RANGE_START: i64 = -32899;
+
+// The server cancelled the request. This error code should
+// only be used for requests that explicitly support being
+// server cancellable.
+//
+// @since 3.17.0
+pub const SERVER_CANCELLED: i64 = -32802;
+
+// The server detected that the content of a document got
+// modified outside normal conditions. A server should
+// NOT send this error code if it detects a content change
+// in it unprocessed messages. The result even computed
+// on an older state might still be useful for the client.
+//
+// If a client decides that a result is not of any use anymore
+// the client should cancel the request.
+pub const CONTENT_MODIFIED: i64 = -32801;
+
+// The client has canceled a request and a server as detected
+// the cancel.
+pub const REQUEST_CANCELLED: i64 = -32800;
+
+// This is the end range of LSP reserved error codes.
+// It doesn't denote a real error code.
+//
+// @since 3.16.0
+pub const LSP_RESERVED_ERROR_RANGE_END: i64 = -32800;
diff --git a/vendor/lsp-types/src/file_operations.rs b/vendor/lsp-types/src/file_operations.rs
index 4092d931b..5adcb9838 100644
--- a/vendor/lsp-types/src/file_operations.rs
+++ b/vendor/lsp-types/src/file_operations.rs
@@ -1,213 +1,213 @@
-use serde::{Deserialize, Serialize};
-
-#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
-#[serde(rename_all = "camelCase")]
-pub struct WorkspaceFileOperationsClientCapabilities {
- /// Whether the client supports dynamic registration for file
- /// requests/notifications.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub dynamic_registration: Option<bool>,
-
- /// The client has support for sending didCreateFiles notifications.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub did_create: Option<bool>,
-
- /// The server is interested in receiving willCreateFiles requests.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub will_create: Option<bool>,
-
- /// The server is interested in receiving didRenameFiles requests.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub did_rename: Option<bool>,
-
- /// The server is interested in receiving willRenameFiles requests.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub will_rename: Option<bool>,
-
- /// The server is interested in receiving didDeleteFiles requests.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub did_delete: Option<bool>,
-
- /// The server is interested in receiving willDeleteFiles requests.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub will_delete: Option<bool>,
-}
-
-#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
-#[serde(rename_all = "camelCase")]
-pub struct WorkspaceFileOperationsServerCapabilities {
- /// The server is interested in receiving didCreateFiles
- /// notifications.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub did_create: Option<FileOperationRegistrationOptions>,
-
- /// The server is interested in receiving willCreateFiles requests.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub will_create: Option<FileOperationRegistrationOptions>,
-
- /// The server is interested in receiving didRenameFiles
- /// notifications.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub did_rename: Option<FileOperationRegistrationOptions>,
-
- /// The server is interested in receiving willRenameFiles requests.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub will_rename: Option<FileOperationRegistrationOptions>,
-
- /// The server is interested in receiving didDeleteFiles file
- /// notifications.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub did_delete: Option<FileOperationRegistrationOptions>,
-
- /// The server is interested in receiving willDeleteFiles file
- /// requests.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub will_delete: Option<FileOperationRegistrationOptions>,
-}
-
-/// The options to register for file operations.
-///
-/// @since 3.16.0
-#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
-#[serde(rename_all = "camelCase")]
-pub struct FileOperationRegistrationOptions {
- /// The actual filters.
- pub filters: Vec<FileOperationFilter>,
-}
-
-/// A filter to describe in which file operation requests or notifications
-/// the server is interested in.
-///
-/// @since 3.16.0
-#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
-#[serde(rename_all = "camelCase")]
-pub struct FileOperationFilter {
- /// A Uri like `file` or `untitled`.
- pub scheme: Option<String>,
-
- /// The actual file operation pattern.
- pub pattern: FileOperationPattern,
-}
-
-/// A pattern kind describing if a glob pattern matches a file a folder or
-/// both.
-///
-/// @since 3.16.0
-#[derive(Debug, Eq, PartialEq, Deserialize, Serialize, Clone)]
-#[serde(rename_all = "lowercase")]
-pub enum FileOperationPatternKind {
- /// The pattern matches a file only.
- File,
-
- /// The pattern matches a folder only.
- Folder,
-}
-
-/// Matching options for the file operation pattern.
-///
-/// @since 3.16.0
-///
-#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
-#[serde(rename_all = "camelCase")]
-pub struct FileOperationPatternOptions {
- /// The pattern should be matched ignoring casing.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub ignore_case: Option<bool>,
-}
-
-/// A pattern to describe in which file operation requests or notifications
-/// the server is interested in.
-///
-/// @since 3.16.0
-#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
-#[serde(rename_all = "camelCase")]
-pub struct FileOperationPattern {
- /// The glob pattern to match. Glob patterns can have the following syntax:
- /// - `*` to match one or more characters in a path segment
- /// - `?` to match on one character in a path segment
- /// - `**` to match any number of path segments, including none
- /// - `{}` to group conditions (e.g. `**​/*.{ts,js}` matches all TypeScript
- /// and JavaScript files)
- /// - `[]` to declare a range of characters to match in a path segment
- /// (e.g., `example.[0-9]` to match on `example.0`, `example.1`, …)
- /// - `[!...]` to negate a range of characters to match in a path segment
- /// (e.g., `example.[!0-9]` to match on `example.a`, `example.b`, but
- /// not `example.0`)
- pub glob: String,
-
- /// Whether to match files or folders with this pattern.
- ///
- /// Matches both if undefined.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub matches: Option<FileOperationPatternKind>,
-
- /// Additional options used during matching.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub options: Option<FileOperationPatternOptions>,
-}
-
-/// The parameters sent in notifications/requests for user-initiated creation
-/// of files.
-///
-/// @since 3.16.0
-#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
-#[serde(rename_all = "camelCase")]
-pub struct CreateFilesParams {
- /// An array of all files/folders created in this operation.
- pub files: Vec<FileCreate>,
-}
-/// Represents information on a file/folder create.
-///
-/// @since 3.16.0
-#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
-#[serde(rename_all = "camelCase")]
-pub struct FileCreate {
- /// A file:// URI for the location of the file/folder being created.
- pub uri: String,
-}
-
-/// The parameters sent in notifications/requests for user-initiated renames
-/// of files.
-///
-/// @since 3.16.0
-#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
-#[serde(rename_all = "camelCase")]
-pub struct RenameFilesParams {
- /// An array of all files/folders renamed in this operation. When a folder
- /// is renamed, only the folder will be included, and not its children.
- pub files: Vec<FileRename>,
-}
-
-/// Represents information on a file/folder rename.
-///
-/// @since 3.16.0
-#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
-#[serde(rename_all = "camelCase")]
-pub struct FileRename {
- /// A file:// URI for the original location of the file/folder being renamed.
- pub old_uri: String,
-
- /// A file:// URI for the new location of the file/folder being renamed.
- pub new_uri: String,
-}
-
-/// The parameters sent in notifications/requests for user-initiated deletes
-/// of files.
-///
-/// @since 3.16.0
-#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
-#[serde(rename_all = "camelCase")]
-pub struct DeleteFilesParams {
- /// An array of all files/folders deleted in this operation.
- pub files: Vec<FileDelete>,
-}
-
-/// Represents information on a file/folder delete.
-///
-/// @since 3.16.0
-#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
-#[serde(rename_all = "camelCase")]
-pub struct FileDelete {
- /// A file:// URI for the location of the file/folder being deleted.
- pub uri: String,
-}
+use serde::{Deserialize, Serialize};
+
+#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct WorkspaceFileOperationsClientCapabilities {
+ /// Whether the client supports dynamic registration for file
+ /// requests/notifications.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub dynamic_registration: Option<bool>,
+
+ /// The client has support for sending didCreateFiles notifications.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub did_create: Option<bool>,
+
+ /// The server is interested in receiving willCreateFiles requests.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub will_create: Option<bool>,
+
+ /// The server is interested in receiving didRenameFiles requests.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub did_rename: Option<bool>,
+
+ /// The server is interested in receiving willRenameFiles requests.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub will_rename: Option<bool>,
+
+ /// The server is interested in receiving didDeleteFiles requests.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub did_delete: Option<bool>,
+
+ /// The server is interested in receiving willDeleteFiles requests.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub will_delete: Option<bool>,
+}
+
+#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct WorkspaceFileOperationsServerCapabilities {
+ /// The server is interested in receiving didCreateFiles
+ /// notifications.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub did_create: Option<FileOperationRegistrationOptions>,
+
+ /// The server is interested in receiving willCreateFiles requests.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub will_create: Option<FileOperationRegistrationOptions>,
+
+ /// The server is interested in receiving didRenameFiles
+ /// notifications.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub did_rename: Option<FileOperationRegistrationOptions>,
+
+ /// The server is interested in receiving willRenameFiles requests.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub will_rename: Option<FileOperationRegistrationOptions>,
+
+ /// The server is interested in receiving didDeleteFiles file
+ /// notifications.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub did_delete: Option<FileOperationRegistrationOptions>,
+
+ /// The server is interested in receiving willDeleteFiles file
+ /// requests.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub will_delete: Option<FileOperationRegistrationOptions>,
+}
+
+/// The options to register for file operations.
+///
+/// @since 3.16.0
+#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct FileOperationRegistrationOptions {
+ /// The actual filters.
+ pub filters: Vec<FileOperationFilter>,
+}
+
+/// A filter to describe in which file operation requests or notifications
+/// the server is interested in.
+///
+/// @since 3.16.0
+#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct FileOperationFilter {
+ /// A Uri like `file` or `untitled`.
+ pub scheme: Option<String>,
+
+ /// The actual file operation pattern.
+ pub pattern: FileOperationPattern,
+}
+
+/// A pattern kind describing if a glob pattern matches a file a folder or
+/// both.
+///
+/// @since 3.16.0
+#[derive(Debug, Eq, PartialEq, Deserialize, Serialize, Clone)]
+#[serde(rename_all = "lowercase")]
+pub enum FileOperationPatternKind {
+ /// The pattern matches a file only.
+ File,
+
+ /// The pattern matches a folder only.
+ Folder,
+}
+
+/// Matching options for the file operation pattern.
+///
+/// @since 3.16.0
+///
+#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct FileOperationPatternOptions {
+ /// The pattern should be matched ignoring casing.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub ignore_case: Option<bool>,
+}
+
+/// A pattern to describe in which file operation requests or notifications
+/// the server is interested in.
+///
+/// @since 3.16.0
+#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct FileOperationPattern {
+ /// The glob pattern to match. Glob patterns can have the following syntax:
+ /// - `*` to match one or more characters in a path segment
+ /// - `?` to match on one character in a path segment
+ /// - `**` to match any number of path segments, including none
+ /// - `{}` to group conditions (e.g. `**​/*.{ts,js}` matches all TypeScript
+ /// and JavaScript files)
+ /// - `[]` to declare a range of characters to match in a path segment
+ /// (e.g., `example.[0-9]` to match on `example.0`, `example.1`, …)
+ /// - `[!...]` to negate a range of characters to match in a path segment
+ /// (e.g., `example.[!0-9]` to match on `example.a`, `example.b`, but
+ /// not `example.0`)
+ pub glob: String,
+
+ /// Whether to match files or folders with this pattern.
+ ///
+ /// Matches both if undefined.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub matches: Option<FileOperationPatternKind>,
+
+ /// Additional options used during matching.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub options: Option<FileOperationPatternOptions>,
+}
+
+/// The parameters sent in notifications/requests for user-initiated creation
+/// of files.
+///
+/// @since 3.16.0
+#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct CreateFilesParams {
+ /// An array of all files/folders created in this operation.
+ pub files: Vec<FileCreate>,
+}
+/// Represents information on a file/folder create.
+///
+/// @since 3.16.0
+#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct FileCreate {
+ /// A file:// URI for the location of the file/folder being created.
+ pub uri: String,
+}
+
+/// The parameters sent in notifications/requests for user-initiated renames
+/// of files.
+///
+/// @since 3.16.0
+#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct RenameFilesParams {
+ /// An array of all files/folders renamed in this operation. When a folder
+ /// is renamed, only the folder will be included, and not its children.
+ pub files: Vec<FileRename>,
+}
+
+/// Represents information on a file/folder rename.
+///
+/// @since 3.16.0
+#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct FileRename {
+ /// A file:// URI for the original location of the file/folder being renamed.
+ pub old_uri: String,
+
+ /// A file:// URI for the new location of the file/folder being renamed.
+ pub new_uri: String,
+}
+
+/// The parameters sent in notifications/requests for user-initiated deletes
+/// of files.
+///
+/// @since 3.16.0
+#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct DeleteFilesParams {
+ /// An array of all files/folders deleted in this operation.
+ pub files: Vec<FileDelete>,
+}
+
+/// Represents information on a file/folder delete.
+///
+/// @since 3.16.0
+#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct FileDelete {
+ /// A file:// URI for the location of the file/folder being deleted.
+ pub uri: String,
+}
diff --git a/vendor/lsp-types/src/folding_range.rs b/vendor/lsp-types/src/folding_range.rs
index 60adaaa18..d3cd01f4f 100644
--- a/vendor/lsp-types/src/folding_range.rs
+++ b/vendor/lsp-types/src/folding_range.rs
@@ -1,102 +1,144 @@
-use crate::{
- PartialResultParams, StaticTextDocumentColorProviderOptions, TextDocumentIdentifier,
- WorkDoneProgressParams,
-};
-use serde::{Deserialize, Serialize};
-#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
-#[serde(rename_all = "camelCase")]
-pub struct FoldingRangeParams {
- /// The text document.
- pub text_document: TextDocumentIdentifier,
-
- #[serde(flatten)]
- pub work_done_progress_params: WorkDoneProgressParams,
-
- #[serde(flatten)]
- pub partial_result_params: PartialResultParams,
-}
-
-#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
-#[serde(untagged)]
-pub enum FoldingRangeProviderCapability {
- Simple(bool),
- FoldingProvider(FoldingProviderOptions),
- Options(StaticTextDocumentColorProviderOptions),
-}
-
-impl From<StaticTextDocumentColorProviderOptions> for FoldingRangeProviderCapability {
- fn from(from: StaticTextDocumentColorProviderOptions) -> Self {
- Self::Options(from)
- }
-}
-
-impl From<FoldingProviderOptions> for FoldingRangeProviderCapability {
- fn from(from: FoldingProviderOptions) -> Self {
- Self::FoldingProvider(from)
- }
-}
-
-impl From<bool> for FoldingRangeProviderCapability {
- fn from(from: bool) -> Self {
- Self::Simple(from)
- }
-}
-
-#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
-pub struct FoldingProviderOptions {}
-
-#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
-#[serde(rename_all = "camelCase")]
-pub struct FoldingRangeClientCapabilities {
- /// Whether implementation supports dynamic registration for folding range providers. If this is set to `true`
- /// the client supports the new `(FoldingRangeProviderOptions & TextDocumentRegistrationOptions & StaticRegistrationOptions)`
- /// return value for the corresponding server capability as well.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub dynamic_registration: Option<bool>,
-
- /// The maximum number of folding ranges that the client prefers to receive per document. The value serves as a
- /// hint, servers are free to follow the limit.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub range_limit: Option<u32>,
- /// If set, the client signals that it only supports folding complete lines. If set, client will
- /// ignore specified `startCharacter` and `endCharacter` properties in a FoldingRange.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub line_folding_only: Option<bool>,
-}
-
-/// Enum of known range kinds
-#[derive(Debug, Eq, PartialEq, Deserialize, Serialize, Clone)]
-#[serde(rename_all = "lowercase")]
-pub enum FoldingRangeKind {
- /// Folding range for a comment
- Comment,
- /// Folding range for a imports or includes
- Imports,
- /// Folding range for a region (e.g. `#region`)
- Region,
-}
-
-/// Represents a folding range.
-#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
-#[serde(rename_all = "camelCase")]
-pub struct FoldingRange {
- /// The zero-based line number from where the folded range starts.
- pub start_line: u32,
-
- /// The zero-based character offset from where the folded range starts. If not defined, defaults to the length of the start line.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub start_character: Option<u32>,
-
- /// The zero-based line number where the folded range ends.
- pub end_line: u32,
-
- /// The zero-based character offset before the folded range ends. If not defined, defaults to the length of the end line.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub end_character: Option<u32>,
-
- /// Describes the kind of the folding range such as `comment' or 'region'. The kind
- /// is used to categorize folding ranges and used by commands like 'Fold all comments'. See
- /// [FoldingRangeKind](#FoldingRangeKind) for an enumeration of standardized kinds.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub kind: Option<FoldingRangeKind>,
-}
+use crate::{
+ PartialResultParams, StaticTextDocumentColorProviderOptions, TextDocumentIdentifier,
+ WorkDoneProgressParams,
+};
+use serde::{Deserialize, Serialize};
+#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct FoldingRangeParams {
+ /// The text document.
+ pub text_document: TextDocumentIdentifier,
+
+ #[serde(flatten)]
+ pub work_done_progress_params: WorkDoneProgressParams,
+
+ #[serde(flatten)]
+ pub partial_result_params: PartialResultParams,
+}
+
+#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
+#[serde(untagged)]
+pub enum FoldingRangeProviderCapability {
+ Simple(bool),
+ FoldingProvider(FoldingProviderOptions),
+ Options(StaticTextDocumentColorProviderOptions),
+}
+
+impl From<StaticTextDocumentColorProviderOptions> for FoldingRangeProviderCapability {
+ fn from(from: StaticTextDocumentColorProviderOptions) -> Self {
+ Self::Options(from)
+ }
+}
+
+impl From<FoldingProviderOptions> for FoldingRangeProviderCapability {
+ fn from(from: FoldingProviderOptions) -> Self {
+ Self::FoldingProvider(from)
+ }
+}
+
+impl From<bool> for FoldingRangeProviderCapability {
+ fn from(from: bool) -> Self {
+ Self::Simple(from)
+ }
+}
+
+#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
+pub struct FoldingProviderOptions {}
+
+#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct FoldingRangeKindCapability {
+ /// The folding range kind values the client supports. When this
+ /// property exists the client also guarantees that it will
+ /// handle values outside its set gracefully and falls back
+ /// to a default value when unknown.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub value_set: Option<Vec<FoldingRangeKind>>,
+}
+
+#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct FoldingRangeCapability {
+ /// If set, the client signals that it supports setting collapsedText on
+ /// folding ranges to display custom labels instead of the default text.
+ ///
+ /// @since 3.17.0
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub collapsed_text: Option<bool>,
+}
+
+#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct FoldingRangeClientCapabilities {
+ /// Whether implementation supports dynamic registration for folding range providers. If this is set to `true`
+ /// the client supports the new `(FoldingRangeProviderOptions & TextDocumentRegistrationOptions & StaticRegistrationOptions)`
+ /// return value for the corresponding server capability as well.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub dynamic_registration: Option<bool>,
+
+ /// The maximum number of folding ranges that the client prefers to receive per document. The value serves as a
+ /// hint, servers are free to follow the limit.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub range_limit: Option<u32>,
+
+ /// If set, the client signals that it only supports folding complete lines. If set, client will
+ /// ignore specified `startCharacter` and `endCharacter` properties in a FoldingRange.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub line_folding_only: Option<bool>,
+
+ /// Specific options for the folding range kind.
+ ///
+ /// @since 3.17.0
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub folding_range_kind: Option<FoldingRangeKindCapability>,
+
+ /// Specific options for the folding range.
+ /// @since 3.17.0
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub folding_range: Option<FoldingRangeCapability>,
+}
+
+/// Enum of known range kinds
+#[derive(Debug, Eq, PartialEq, Deserialize, Serialize, Clone)]
+#[serde(rename_all = "lowercase")]
+pub enum FoldingRangeKind {
+ /// Folding range for a comment
+ Comment,
+ /// Folding range for a imports or includes
+ Imports,
+ /// Folding range for a region (e.g. `#region`)
+ Region,
+}
+
+/// Represents a folding range.
+#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct FoldingRange {
+ /// The zero-based line number from where the folded range starts.
+ pub start_line: u32,
+
+ /// The zero-based character offset from where the folded range starts. If not defined, defaults to the length of the start line.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub start_character: Option<u32>,
+
+ /// The zero-based line number where the folded range ends.
+ pub end_line: u32,
+
+ /// The zero-based character offset before the folded range ends. If not defined, defaults to the length of the end line.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub end_character: Option<u32>,
+
+ /// Describes the kind of the folding range such as `comment' or 'region'. The kind
+ /// is used to categorize folding ranges and used by commands like 'Fold all comments'. See
+ /// [FoldingRangeKind](#FoldingRangeKind) for an enumeration of standardized kinds.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub kind: Option<FoldingRangeKind>,
+
+ /// The text that the client should show when the specified range is
+ /// collapsed. If not defined or not supported by the client, a default
+ /// will be chosen by the client.
+ ///
+ /// @since 3.17.0
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub collapsed_text: Option<String>,
+}
diff --git a/vendor/lsp-types/src/formatting.rs b/vendor/lsp-types/src/formatting.rs
index 2fb5e6b63..4c9a5b45a 100644
--- a/vendor/lsp-types/src/formatting.rs
+++ b/vendor/lsp-types/src/formatting.rs
@@ -1,153 +1,153 @@
-use serde::{Deserialize, Serialize};
-
-use crate::{
- DocumentSelector, DynamicRegistrationClientCapabilities, Range, TextDocumentIdentifier,
- TextDocumentPositionParams, WorkDoneProgressParams,
-};
-
-use std::collections::HashMap;
-
-pub type DocumentFormattingClientCapabilities = DynamicRegistrationClientCapabilities;
-pub type DocumentRangeFormattingClientCapabilities = DynamicRegistrationClientCapabilities;
-pub type DocumentOnTypeFormattingClientCapabilities = DynamicRegistrationClientCapabilities;
-
-/// Format document on type options
-#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
-#[serde(rename_all = "camelCase")]
-pub struct DocumentOnTypeFormattingOptions {
- /// A character on which formatting should be triggered, like `}`.
- pub first_trigger_character: String,
-
- /// More trigger characters.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub more_trigger_character: Option<Vec<String>>,
-}
-
-#[derive(Debug, PartialEq, Clone, Deserialize, Serialize)]
-#[serde(rename_all = "camelCase")]
-pub struct DocumentFormattingParams {
- /// The document to format.
- pub text_document: TextDocumentIdentifier,
-
- /// The format options.
- pub options: FormattingOptions,
-
- #[serde(flatten)]
- pub work_done_progress_params: WorkDoneProgressParams,
-}
-
-/// Value-object describing what options formatting should use.
-#[derive(Debug, PartialEq, Clone, Default, Serialize, Deserialize)]
-#[serde(rename_all = "camelCase")]
-pub struct FormattingOptions {
- /// Size of a tab in spaces.
- pub tab_size: u32,
-
- /// Prefer spaces over tabs.
- pub insert_spaces: bool,
-
- /// Signature for further properties.
- #[serde(flatten)]
- pub properties: HashMap<String, FormattingProperty>,
-
- /// Trim trailing whitespaces on a line.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub trim_trailing_whitespace: Option<bool>,
-
- /// Insert a newline character at the end of the file if one does not exist.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub insert_final_newline: Option<bool>,
-
- /// Trim all newlines after the final newline at the end of the file.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub trim_final_newlines: Option<bool>,
-}
-
-#[derive(Debug, PartialEq, Clone, Deserialize, Serialize)]
-#[serde(untagged)]
-pub enum FormattingProperty {
- Bool(bool),
- Number(i32),
- String(String),
-}
-
-#[derive(Debug, PartialEq, Clone, Deserialize, Serialize)]
-#[serde(rename_all = "camelCase")]
-pub struct DocumentRangeFormattingParams {
- /// The document to format.
- pub text_document: TextDocumentIdentifier,
-
- /// The range to format
- pub range: Range,
-
- /// The format options
- pub options: FormattingOptions,
-
- #[serde(flatten)]
- pub work_done_progress_params: WorkDoneProgressParams,
-}
-
-#[derive(Debug, PartialEq, Clone, Deserialize, Serialize)]
-#[serde(rename_all = "camelCase")]
-pub struct DocumentOnTypeFormattingParams {
- /// Text Document and Position fields.
- #[serde(flatten)]
- pub text_document_position: TextDocumentPositionParams,
-
- /// The character that has been typed.
- pub ch: String,
-
- /// The format options.
- pub options: FormattingOptions,
-}
-
-/// Extends TextDocumentRegistrationOptions
-#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
-#[serde(rename_all = "camelCase")]
-pub struct DocumentOnTypeFormattingRegistrationOptions {
- /// A document selector to identify the scope of the registration. If set to null
- /// the document selector provided on the client side will be used.
- pub document_selector: Option<DocumentSelector>,
-
- /// A character on which formatting should be triggered, like `}`.
- pub first_trigger_character: String,
-
- /// More trigger characters.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub more_trigger_character: Option<Vec<String>>,
-}
-
-#[cfg(test)]
-mod tests {
- use super::*;
- use crate::tests::test_serialization;
-
- #[test]
- fn formatting_options() {
- test_serialization(
- &FormattingOptions {
- tab_size: 123,
- insert_spaces: true,
- properties: HashMap::new(),
- trim_trailing_whitespace: None,
- insert_final_newline: None,
- trim_final_newlines: None,
- },
- r#"{"tabSize":123,"insertSpaces":true}"#,
- );
-
- test_serialization(
- &FormattingOptions {
- tab_size: 123,
- insert_spaces: true,
- properties: vec![("prop".to_string(), FormattingProperty::Number(1))]
- .into_iter()
- .collect(),
- trim_trailing_whitespace: None,
- insert_final_newline: None,
- trim_final_newlines: None,
- },
- r#"{"tabSize":123,"insertSpaces":true,"prop":1}"#,
- );
- }
-}
+use serde::{Deserialize, Serialize};
+
+use crate::{
+ DocumentSelector, DynamicRegistrationClientCapabilities, Range, TextDocumentIdentifier,
+ TextDocumentPositionParams, WorkDoneProgressParams,
+};
+
+use std::collections::HashMap;
+
+pub type DocumentFormattingClientCapabilities = DynamicRegistrationClientCapabilities;
+pub type DocumentRangeFormattingClientCapabilities = DynamicRegistrationClientCapabilities;
+pub type DocumentOnTypeFormattingClientCapabilities = DynamicRegistrationClientCapabilities;
+
+/// Format document on type options
+#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct DocumentOnTypeFormattingOptions {
+ /// A character on which formatting should be triggered, like `}`.
+ pub first_trigger_character: String,
+
+ /// More trigger characters.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub more_trigger_character: Option<Vec<String>>,
+}
+
+#[derive(Debug, PartialEq, Clone, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct DocumentFormattingParams {
+ /// The document to format.
+ pub text_document: TextDocumentIdentifier,
+
+ /// The format options.
+ pub options: FormattingOptions,
+
+ #[serde(flatten)]
+ pub work_done_progress_params: WorkDoneProgressParams,
+}
+
+/// Value-object describing what options formatting should use.
+#[derive(Debug, PartialEq, Clone, Default, Serialize, Deserialize)]
+#[serde(rename_all = "camelCase")]
+pub struct FormattingOptions {
+ /// Size of a tab in spaces.
+ pub tab_size: u32,
+
+ /// Prefer spaces over tabs.
+ pub insert_spaces: bool,
+
+ /// Signature for further properties.
+ #[serde(flatten)]
+ pub properties: HashMap<String, FormattingProperty>,
+
+ /// Trim trailing whitespaces on a line.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub trim_trailing_whitespace: Option<bool>,
+
+ /// Insert a newline character at the end of the file if one does not exist.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub insert_final_newline: Option<bool>,
+
+ /// Trim all newlines after the final newline at the end of the file.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub trim_final_newlines: Option<bool>,
+}
+
+#[derive(Debug, PartialEq, Clone, Deserialize, Serialize)]
+#[serde(untagged)]
+pub enum FormattingProperty {
+ Bool(bool),
+ Number(i32),
+ String(String),
+}
+
+#[derive(Debug, PartialEq, Clone, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct DocumentRangeFormattingParams {
+ /// The document to format.
+ pub text_document: TextDocumentIdentifier,
+
+ /// The range to format
+ pub range: Range,
+
+ /// The format options
+ pub options: FormattingOptions,
+
+ #[serde(flatten)]
+ pub work_done_progress_params: WorkDoneProgressParams,
+}
+
+#[derive(Debug, PartialEq, Clone, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct DocumentOnTypeFormattingParams {
+ /// Text Document and Position fields.
+ #[serde(flatten)]
+ pub text_document_position: TextDocumentPositionParams,
+
+ /// The character that has been typed.
+ pub ch: String,
+
+ /// The format options.
+ pub options: FormattingOptions,
+}
+
+/// Extends TextDocumentRegistrationOptions
+#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct DocumentOnTypeFormattingRegistrationOptions {
+ /// A document selector to identify the scope of the registration. If set to null
+ /// the document selector provided on the client side will be used.
+ pub document_selector: Option<DocumentSelector>,
+
+ /// A character on which formatting should be triggered, like `}`.
+ pub first_trigger_character: String,
+
+ /// More trigger characters.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub more_trigger_character: Option<Vec<String>>,
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+ use crate::tests::test_serialization;
+
+ #[test]
+ fn formatting_options() {
+ test_serialization(
+ &FormattingOptions {
+ tab_size: 123,
+ insert_spaces: true,
+ properties: HashMap::new(),
+ trim_trailing_whitespace: None,
+ insert_final_newline: None,
+ trim_final_newlines: None,
+ },
+ r#"{"tabSize":123,"insertSpaces":true}"#,
+ );
+
+ test_serialization(
+ &FormattingOptions {
+ tab_size: 123,
+ insert_spaces: true,
+ properties: vec![("prop".to_string(), FormattingProperty::Number(1))]
+ .into_iter()
+ .collect(),
+ trim_trailing_whitespace: None,
+ insert_final_newline: None,
+ trim_final_newlines: None,
+ },
+ r#"{"tabSize":123,"insertSpaces":true,"prop":1}"#,
+ );
+ }
+}
diff --git a/vendor/lsp-types/src/hover.rs b/vendor/lsp-types/src/hover.rs
index 01bd2f8d1..4c94055e6 100644
--- a/vendor/lsp-types/src/hover.rs
+++ b/vendor/lsp-types/src/hover.rs
@@ -1,86 +1,86 @@
-use serde::{Deserialize, Serialize};
-
-use crate::{
- MarkedString, MarkupContent, MarkupKind, Range, TextDocumentPositionParams,
- TextDocumentRegistrationOptions, WorkDoneProgressOptions, WorkDoneProgressParams,
-};
-
-#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
-#[serde(rename_all = "camelCase")]
-pub struct HoverClientCapabilities {
- /// Whether completion supports dynamic registration.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub dynamic_registration: Option<bool>,
-
- /// Client supports the follow content formats for the content
- /// property. The order describes the preferred format of the client.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub content_format: Option<Vec<MarkupKind>>,
-}
-
-/// Hover options.
-#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
-#[serde(rename_all = "camelCase")]
-pub struct HoverOptions {
- #[serde(flatten)]
- pub work_done_progress_options: WorkDoneProgressOptions,
-}
-
-#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
-#[serde(rename_all = "camelCase")]
-pub struct HoverRegistrationOptions {
- #[serde(flatten)]
- pub text_document_registration_options: TextDocumentRegistrationOptions,
-
- #[serde(flatten)]
- pub hover_options: HoverOptions,
-}
-
-#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
-#[serde(untagged)]
-pub enum HoverProviderCapability {
- Simple(bool),
- Options(HoverOptions),
-}
-
-impl From<HoverOptions> for HoverProviderCapability {
- fn from(from: HoverOptions) -> Self {
- Self::Options(from)
- }
-}
-
-impl From<bool> for HoverProviderCapability {
- fn from(from: bool) -> Self {
- Self::Simple(from)
- }
-}
-
-#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
-#[serde(rename_all = "camelCase")]
-pub struct HoverParams {
- #[serde(flatten)]
- pub text_document_position_params: TextDocumentPositionParams,
-
- #[serde(flatten)]
- pub work_done_progress_params: WorkDoneProgressParams,
-}
-
-/// The result of a hover request.
-#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
-pub struct Hover {
- /// The hover's content
- pub contents: HoverContents,
- /// An optional range is a range inside a text document
- /// that is used to visualize a hover, e.g. by changing the background color.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub range: Option<Range>,
-}
-
-/// Hover contents could be single entry or multiple entries.
-#[derive(Debug, Eq, PartialEq, Clone, Serialize, Deserialize)]
-#[serde(untagged)]
-pub enum HoverContents {
- Scalar(MarkedString),
- Array(Vec<MarkedString>),
- Markup(MarkupContent),
-}
+use serde::{Deserialize, Serialize};
+
+use crate::{
+ MarkedString, MarkupContent, MarkupKind, Range, TextDocumentPositionParams,
+ TextDocumentRegistrationOptions, WorkDoneProgressOptions, WorkDoneProgressParams,
+};
+
+#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct HoverClientCapabilities {
+ /// Whether completion supports dynamic registration.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub dynamic_registration: Option<bool>,
+
+ /// Client supports the follow content formats for the content
+ /// property. The order describes the preferred format of the client.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub content_format: Option<Vec<MarkupKind>>,
+}
+
+/// Hover options.
+#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct HoverOptions {
+ #[serde(flatten)]
+ pub work_done_progress_options: WorkDoneProgressOptions,
+}
+
+#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct HoverRegistrationOptions {
+ #[serde(flatten)]
+ pub text_document_registration_options: TextDocumentRegistrationOptions,
+
+ #[serde(flatten)]
+ pub hover_options: HoverOptions,
+}
+
+#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
+#[serde(untagged)]
+pub enum HoverProviderCapability {
+ Simple(bool),
+ Options(HoverOptions),
+}
+
+impl From<HoverOptions> for HoverProviderCapability {
+ fn from(from: HoverOptions) -> Self {
+ Self::Options(from)
+ }
+}
+
+impl From<bool> for HoverProviderCapability {
+ fn from(from: bool) -> Self {
+ Self::Simple(from)
+ }
+}
+
+#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct HoverParams {
+ #[serde(flatten)]
+ pub text_document_position_params: TextDocumentPositionParams,
+
+ #[serde(flatten)]
+ pub work_done_progress_params: WorkDoneProgressParams,
+}
+
+/// The result of a hover request.
+#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
+pub struct Hover {
+ /// The hover's content
+ pub contents: HoverContents,
+ /// An optional range is a range inside a text document
+ /// that is used to visualize a hover, e.g. by changing the background color.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub range: Option<Range>,
+}
+
+/// Hover contents could be single entry or multiple entries.
+#[derive(Debug, Eq, PartialEq, Clone, Serialize, Deserialize)]
+#[serde(untagged)]
+pub enum HoverContents {
+ Scalar(MarkedString),
+ Array(Vec<MarkedString>),
+ Markup(MarkupContent),
+}
diff --git a/vendor/lsp-types/src/inlay_hint.rs b/vendor/lsp-types/src/inlay_hint.rs
index c1482c907..cdc9a0b70 100644
--- a/vendor/lsp-types/src/inlay_hint.rs
+++ b/vendor/lsp-types/src/inlay_hint.rs
@@ -1,279 +1,281 @@
-#![cfg(feature = "proposed")]
-
-use crate::{
- Command, LSPAny, Location, MarkupContent, Position, Range, StaticRegistrationOptions,
- TextDocumentIdentifier, TextDocumentRegistrationOptions, TextEdit, WorkDoneProgressOptions,
- WorkDoneProgressParams,
-};
-use serde::{Deserialize, Serialize};
-
-#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
-#[serde(rename_all = "camelCase")]
-#[serde(untagged)]
-pub enum InlayHintServerCapabilities {
- Options(InlayHintOptions),
- RegistrationOptions(InlayHintRegistrationOptions),
-}
-
-/// Inlay hint client capabilities.
-///
-/// @since 3.17.0 - proposed state
-#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
-#[serde(rename_all = "camelCase")]
-pub struct InlayHintClientCapabilities {
- /// Whether inlay hints support dynamic registration.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub dynamic_registration: Option<bool>,
-
- /// Indicates which properties a client can resolve lazily on a inlay
- /// hint.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub resolve_support: Option<InlayHintResolveClientCapabilities>,
-}
-
-/// Inlay hint options used during static registration.
-///
-/// @since 3.17.0 - proposed state
-#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
-#[serde(rename_all = "camelCase")]
-pub struct InlayHintOptions {
- #[serde(flatten)]
- pub work_done_progress_options: WorkDoneProgressOptions,
-
- /// The server provides support to resolve additional
- /// information for an inlay hint item.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub resolve_provider: Option<bool>,
-}
-
-/// Inlay hint options used during static or dynamic registration.
-///
-/// @since 3.17.0 - proposed state
-#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
-#[serde(rename_all = "camelCase")]
-pub struct InlayHintRegistrationOptions {
- #[serde(flatten)]
- pub inlay_hint_options: InlayHintOptions,
-
- #[serde(flatten)]
- pub text_document_registration_options: TextDocumentRegistrationOptions,
-
- #[serde(flatten)]
- pub static_registration_options: StaticRegistrationOptions,
-}
-
-/// A parameter literal used in inlay hint requests.
-///
-/// @since 3.17.0 - proposed state
-#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
-#[serde(rename_all = "camelCase")]
-pub struct InlayHintParams {
- #[serde(flatten)]
- pub work_done_progress_params: WorkDoneProgressParams,
-
- /// The text document.
- pub text_document: TextDocumentIdentifier,
-
- /// The visible document range for which inlay hints should be computed.
- pub range: Range,
-}
-
-/// Inlay hint information.
-///
-/// @since 3.17.0 - proposed state
-#[derive(Debug, Clone, Deserialize, Serialize)]
-#[serde(rename_all = "camelCase")]
-pub struct InlayHint {
- /// The position of this hint.
- pub position: Position,
-
- /// The label of this hint. A human readable string or an array of
- /// InlayHintLabelPart label parts.
- ///
- /// *Note* that neither the string nor the label part can be empty.
- pub label: InlayHintLabel,
-
- /// The kind of this hint. Can be omitted in which case the client
- /// should fall back to a reasonable default.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub kind: Option<InlayHintKind>,
-
- /// Optional text edits that are performed when accepting this inlay hint.
- ///
- /// *Note* that edits are expected to change the document so that the inlay
- /// hint (or its nearest variant) is now part of the document and the inlay
- /// hint itself is now obsolete.
- ///
- /// Depending on the client capability `inlayHint.resolveSupport` clients
- /// might resolve this property late using the resolve request.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub text_edits: Option<Vec<TextEdit>>,
-
- /// The tooltip text when you hover over this item.
- ///
- /// Depending on the client capability `inlayHint.resolveSupport` clients
- /// might resolve this property late using the resolve request.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub tooltip: Option<InlayHintTooltip>,
-
- /// Render padding before the hint.
- ///
- /// Note: Padding should use the editor's background color, not the
- /// background color of the hint itself. That means padding can be used
- /// to visually align/separate an inlay hint.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub padding_left: Option<bool>,
-
- /// Render padding after the hint.
- ///
- /// Note: Padding should use the editor's background color, not the
- /// background color of the hint itself. That means padding can be used
- /// to visually align/separate an inlay hint.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub padding_right: Option<bool>,
-
- /// A data entry field that is preserved on a inlay hint between
- /// a `textDocument/inlayHint` and a `inlayHint/resolve` request.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub data: Option<LSPAny>,
-}
-
-#[derive(Debug, Clone, Deserialize, Serialize)]
-#[serde(untagged)]
-pub enum InlayHintLabel {
- String(String),
- LabelParts(Vec<InlayHintLabelPart>),
-}
-
-impl From<String> for InlayHintLabel {
- #[inline]
- fn from(from: String) -> Self {
- Self::String(from)
- }
-}
-
-impl From<Vec<InlayHintLabelPart>> for InlayHintLabel {
- #[inline]
- fn from(from: Vec<InlayHintLabelPart>) -> Self {
- Self::LabelParts(from)
- }
-}
-
-#[derive(Debug, Clone, Deserialize, Serialize)]
-#[serde(untagged)]
-pub enum InlayHintTooltip {
- String(String),
- MarkupContent(MarkupContent),
-}
-
-impl From<String> for InlayHintTooltip {
- #[inline]
- fn from(from: String) -> Self {
- Self::String(from)
- }
-}
-
-impl From<MarkupContent> for InlayHintTooltip {
- #[inline]
- fn from(from: MarkupContent) -> Self {
- Self::MarkupContent(from)
- }
-}
-
-/// An inlay hint label part allows for interactive and composite labels
-/// of inlay hints.
-#[derive(Debug, Clone, Default, Deserialize, Serialize)]
-#[serde(rename_all = "camelCase")]
-pub struct InlayHintLabelPart {
- /// The value of this label part.
- pub value: String,
-
- /// The tooltip text when you hover over this label part. Depending on
- /// the client capability `inlayHint.resolveSupport` clients might resolve
- /// this property late using the resolve request.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub tooltip: Option<InlayHintLabelPartTooltip>,
-
- /// An optional source code location that represents this
- /// label part.
- ///
- /// The editor will use this location for the hover and for code navigation
- /// features: This part will become a clickable link that resolves to the
- /// definition of the symbol at the given location (not necessarily the
- /// location itself), it shows the hover that shows at the given location,
- /// and it shows a context menu with further code navigation commands.
- ///
- /// Depending on the client capability `inlayHint.resolveSupport` clients
- /// might resolve this property late using the resolve request.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub location: Option<Location>,
-
- /// An optional command for this label part.
- ///
- /// Depending on the client capability `inlayHint.resolveSupport` clients
- /// might resolve this property late using the resolve request.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub command: Option<Command>,
-}
-
-#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
-#[serde(untagged)]
-pub enum InlayHintLabelPartTooltip {
- String(String),
- MarkupContent(MarkupContent),
-}
-
-impl From<String> for InlayHintLabelPartTooltip {
- #[inline]
- fn from(from: String) -> Self {
- Self::String(from)
- }
-}
-
-impl From<MarkupContent> for InlayHintLabelPartTooltip {
- #[inline]
- fn from(from: MarkupContent) -> Self {
- Self::MarkupContent(from)
- }
-}
-
-/// Inlay hint kinds.
-///
-/// @since 3.17.0 - proposed state
-#[derive(Eq, PartialEq, Copy, Clone, Serialize, Deserialize)]
-#[serde(transparent)]
-pub struct InlayHintKind(i32);
-lsp_enum! {
-impl InlayHintKind {
- /// An inlay hint that for a type annotation.
- pub const TYPE: InlayHintKind = InlayHintKind(1);
-
- /// An inlay hint that is for a parameter.
- pub const PARAMETER: InlayHintKind = InlayHintKind(2);
-}
-}
-
-#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
-#[serde(rename_all = "camelCase")]
-pub struct InlayHintResolveClientCapabilities {
- pub properties: Vec<String>,
-}
-
-/// Client workspace capabilities specific to inlay hints.
-///
-/// @since 3.17.0 - proposed state
-#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
-#[serde(rename_all = "camelCase")]
-pub struct InlayHintWorkspaceClientCapabilities {
- /// Whether the client implementation supports a refresh request sent from
- /// the server to the client.
- ///
- /// Note that this event is global and will force the client to refresh all
- /// inlay hints currently shown. It should be used with absolute care and
- /// is useful for situation where a server for example detects a project wide
- /// change that requires such a calculation.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub refresh_support: Option<bool>,
-}
-
-// TODO(sno2): add tests once stabilized
+use crate::{
+ Command, LSPAny, Location, MarkupContent, Position, Range, StaticRegistrationOptions,
+ TextDocumentIdentifier, TextDocumentRegistrationOptions, TextEdit, WorkDoneProgressOptions,
+ WorkDoneProgressParams,
+};
+use serde::{Deserialize, Serialize};
+
+#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+#[serde(untagged)]
+pub enum InlayHintServerCapabilities {
+ Options(InlayHintOptions),
+ RegistrationOptions(InlayHintRegistrationOptions),
+}
+
+/// Inlay hint client capabilities.
+///
+/// @since 3.17.0
+#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct InlayHintClientCapabilities {
+ /// Whether inlay hints support dynamic registration.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub dynamic_registration: Option<bool>,
+
+ /// Indicates which properties a client can resolve lazily on a inlay
+ /// hint.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub resolve_support: Option<InlayHintResolveClientCapabilities>,
+}
+
+/// Inlay hint options used during static registration.
+///
+/// @since 3.17.0
+#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct InlayHintOptions {
+ #[serde(flatten)]
+ pub work_done_progress_options: WorkDoneProgressOptions,
+
+ /// The server provides support to resolve additional
+ /// information for an inlay hint item.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub resolve_provider: Option<bool>,
+}
+
+/// Inlay hint options used during static or dynamic registration.
+///
+/// @since 3.17.0
+#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct InlayHintRegistrationOptions {
+ #[serde(flatten)]
+ pub inlay_hint_options: InlayHintOptions,
+
+ #[serde(flatten)]
+ pub text_document_registration_options: TextDocumentRegistrationOptions,
+
+ #[serde(flatten)]
+ pub static_registration_options: StaticRegistrationOptions,
+}
+
+/// A parameter literal used in inlay hint requests.
+///
+/// @since 3.17.0
+#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct InlayHintParams {
+ #[serde(flatten)]
+ pub work_done_progress_params: WorkDoneProgressParams,
+
+ /// The text document.
+ pub text_document: TextDocumentIdentifier,
+
+ /// The visible document range for which inlay hints should be computed.
+ pub range: Range,
+}
+
+/// Inlay hint information.
+///
+/// @since 3.17.0
+#[derive(Debug, Clone, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct InlayHint {
+ /// The position of this hint.
+ pub position: Position,
+
+ /// The label of this hint. A human readable string or an array of
+ /// InlayHintLabelPart label parts.
+ ///
+ /// *Note* that neither the string nor the label part can be empty.
+ pub label: InlayHintLabel,
+
+ /// The kind of this hint. Can be omitted in which case the client
+ /// should fall back to a reasonable default.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub kind: Option<InlayHintKind>,
+
+ /// Optional text edits that are performed when accepting this inlay hint.
+ ///
+ /// *Note* that edits are expected to change the document so that the inlay
+ /// hint (or its nearest variant) is now part of the document and the inlay
+ /// hint itself is now obsolete.
+ ///
+ /// Depending on the client capability `inlayHint.resolveSupport` clients
+ /// might resolve this property late using the resolve request.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub text_edits: Option<Vec<TextEdit>>,
+
+ /// The tooltip text when you hover over this item.
+ ///
+ /// Depending on the client capability `inlayHint.resolveSupport` clients
+ /// might resolve this property late using the resolve request.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub tooltip: Option<InlayHintTooltip>,
+
+ /// Render padding before the hint.
+ ///
+ /// Note: Padding should use the editor's background color, not the
+ /// background color of the hint itself. That means padding can be used
+ /// to visually align/separate an inlay hint.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub padding_left: Option<bool>,
+
+ /// Render padding after the hint.
+ ///
+ /// Note: Padding should use the editor's background color, not the
+ /// background color of the hint itself. That means padding can be used
+ /// to visually align/separate an inlay hint.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub padding_right: Option<bool>,
+
+ /// A data entry field that is preserved on a inlay hint between
+ /// a `textDocument/inlayHint` and a `inlayHint/resolve` request.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub data: Option<LSPAny>,
+}
+
+#[derive(Debug, Clone, Deserialize, Serialize)]
+#[serde(untagged)]
+pub enum InlayHintLabel {
+ String(String),
+ LabelParts(Vec<InlayHintLabelPart>),
+}
+
+impl From<String> for InlayHintLabel {
+ #[inline]
+ fn from(from: String) -> Self {
+ Self::String(from)
+ }
+}
+
+impl From<Vec<InlayHintLabelPart>> for InlayHintLabel {
+ #[inline]
+ fn from(from: Vec<InlayHintLabelPart>) -> Self {
+ Self::LabelParts(from)
+ }
+}
+
+#[derive(Debug, Clone, Deserialize, Serialize)]
+#[serde(untagged)]
+pub enum InlayHintTooltip {
+ String(String),
+ MarkupContent(MarkupContent),
+}
+
+impl From<String> for InlayHintTooltip {
+ #[inline]
+ fn from(from: String) -> Self {
+ Self::String(from)
+ }
+}
+
+impl From<MarkupContent> for InlayHintTooltip {
+ #[inline]
+ fn from(from: MarkupContent) -> Self {
+ Self::MarkupContent(from)
+ }
+}
+
+/// An inlay hint label part allows for interactive and composite labels
+/// of inlay hints.
+#[derive(Debug, Clone, Default, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct InlayHintLabelPart {
+ /// The value of this label part.
+ pub value: String,
+
+ /// The tooltip text when you hover over this label part. Depending on
+ /// the client capability `inlayHint.resolveSupport` clients might resolve
+ /// this property late using the resolve request.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub tooltip: Option<InlayHintLabelPartTooltip>,
+
+ /// An optional source code location that represents this
+ /// label part.
+ ///
+ /// The editor will use this location for the hover and for code navigation
+ /// features: This part will become a clickable link that resolves to the
+ /// definition of the symbol at the given location (not necessarily the
+ /// location itself), it shows the hover that shows at the given location,
+ /// and it shows a context menu with further code navigation commands.
+ ///
+ /// Depending on the client capability `inlayHint.resolveSupport` clients
+ /// might resolve this property late using the resolve request.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub location: Option<Location>,
+
+ /// An optional command for this label part.
+ ///
+ /// Depending on the client capability `inlayHint.resolveSupport` clients
+ /// might resolve this property late using the resolve request.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub command: Option<Command>,
+}
+
+#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
+#[serde(untagged)]
+pub enum InlayHintLabelPartTooltip {
+ String(String),
+ MarkupContent(MarkupContent),
+}
+
+impl From<String> for InlayHintLabelPartTooltip {
+ #[inline]
+ fn from(from: String) -> Self {
+ Self::String(from)
+ }
+}
+
+impl From<MarkupContent> for InlayHintLabelPartTooltip {
+ #[inline]
+ fn from(from: MarkupContent) -> Self {
+ Self::MarkupContent(from)
+ }
+}
+
+/// Inlay hint kinds.
+///
+/// @since 3.17.0
+#[derive(Eq, PartialEq, Copy, Clone, Serialize, Deserialize)]
+#[serde(transparent)]
+pub struct InlayHintKind(i32);
+lsp_enum! {
+impl InlayHintKind {
+ /// An inlay hint that for a type annotation.
+ pub const TYPE: InlayHintKind = InlayHintKind(1);
+
+ /// An inlay hint that is for a parameter.
+ pub const PARAMETER: InlayHintKind = InlayHintKind(2);
+}
+}
+
+/// Inlay hint client capabilities.
+///
+/// @since 3.17.0
+#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct InlayHintResolveClientCapabilities {
+ /// The properties that a client can resolve lazily.
+ pub properties: Vec<String>,
+}
+
+/// Client workspace capabilities specific to inlay hints.
+///
+/// @since 3.17.0
+#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct InlayHintWorkspaceClientCapabilities {
+ /// Whether the client implementation supports a refresh request sent from
+ /// the server to the client.
+ ///
+ /// Note that this event is global and will force the client to refresh all
+ /// inlay hints currently shown. It should be used with absolute care and
+ /// is useful for situation where a server for example detects a project wide
+ /// change that requires such a calculation.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub refresh_support: Option<bool>,
+}
+
+// TODO(sno2): add tests once stabilized
diff --git a/vendor/lsp-types/src/inline_value.rs b/vendor/lsp-types/src/inline_value.rs
new file mode 100644
index 000000000..35dae188f
--- /dev/null
+++ b/vendor/lsp-types/src/inline_value.rs
@@ -0,0 +1,217 @@
+use crate::{
+ DynamicRegistrationClientCapabilities, Range, StaticRegistrationOptions,
+ TextDocumentIdentifier, TextDocumentRegistrationOptions, WorkDoneProgressOptions,
+ WorkDoneProgressParams,
+};
+use serde::{Deserialize, Serialize};
+
+pub type InlineValueClientCapabilities = DynamicRegistrationClientCapabilities;
+
+#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
+#[serde(untagged)]
+pub enum InlineValueServerCapabilities {
+ Options(InlineValueOptions),
+ RegistrationOptions(InlineValueRegistrationOptions),
+}
+
+/// Inline value options used during static registration.
+///
+/// @since 3.17.0
+#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
+pub struct InlineValueOptions {
+ #[serde(flatten)]
+ pub work_done_progress_options: WorkDoneProgressOptions,
+}
+
+/// Inline value options used during static or dynamic registration.
+///
+/// @since 3.17.0
+#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
+pub struct InlineValueRegistrationOptions {
+ #[serde(flatten)]
+ pub inline_value_options: InlineValueOptions,
+
+ #[serde(flatten)]
+ pub text_document_registration_options: TextDocumentRegistrationOptions,
+
+ #[serde(flatten)]
+ pub static_registration_options: StaticRegistrationOptions,
+}
+
+/// A parameter literal used in inline value requests.
+///
+/// @since 3.17.0
+#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct InlineValueParams {
+ #[serde(flatten)]
+ pub work_done_progress_params: WorkDoneProgressParams,
+
+ /// The text document.
+ pub text_document: TextDocumentIdentifier,
+
+ /// The document range for which inline values should be computed.
+ pub range: Range,
+
+ /// Additional information about the context in which inline values were
+ /// requested.
+ pub context: InlineValueContext,
+}
+
+/// @since 3.17.0
+#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct InlineValueContext {
+ /// The stack frame (as a DAP Id) where the execution has stopped.
+ pub frame_id: i32,
+
+ /// The document range where execution has stopped.
+ /// Typically the end position of the range denotes the line where the
+ /// inline values are shown.
+ pub stopped_location: Range,
+}
+
+/// Provide inline value as text.
+///
+/// @since 3.17.0
+#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
+pub struct InlineValueText {
+ /// The document range for which the inline value applies.
+ pub range: Range,
+
+ /// The text of the inline value.
+ pub text: String,
+}
+
+/// Provide inline value through a variable lookup.
+///
+/// If only a range is specified, the variable name will be extracted from
+/// the underlying document.
+///
+/// An optional variable name can be used to override the extracted name.
+///
+/// @since 3.17.0
+#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct InlineValueVariableLookup {
+ /// The document range for which the inline value applies.
+ /// The range is used to extract the variable name from the underlying
+ /// document.
+ pub range: Range,
+
+ /// If specified the name of the variable to look up.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub variable_name: Option<String>,
+
+ /// How to perform the lookup.
+ pub case_sensitive_lookup: bool,
+}
+
+/// Provide an inline value through an expression evaluation.
+///
+/// If only a range is specified, the expression will be extracted from the
+/// underlying document.
+///
+/// An optional expression can be used to override the extracted expression.
+///
+/// @since 3.17.0
+#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct InlineValueEvaluatableExpression {
+ /// The document range for which the inline value applies.
+ /// The range is used to extract the evaluatable expression from the
+ /// underlying document.
+ pub range: Range,
+
+ /// If specified the expression overrides the extracted expression.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub expression: Option<String>,
+}
+
+/// Inline value information can be provided by different means:
+/// - directly as a text value (class InlineValueText).
+/// - as a name to use for a variable lookup (class InlineValueVariableLookup)
+/// - as an evaluatable expression (class InlineValueEvaluatableExpression)
+/// The InlineValue types combines all inline value types into one type.
+///
+/// @since 3.17.0
+#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
+#[serde(untagged)]
+pub enum InlineValue {
+ Text(InlineValueText),
+ VariableLookup(InlineValueVariableLookup),
+ EvaluatableExpression(InlineValueEvaluatableExpression),
+}
+
+impl From<InlineValueText> for InlineValue {
+ #[inline]
+ fn from(from: InlineValueText) -> Self {
+ Self::Text(from)
+ }
+}
+
+impl From<InlineValueVariableLookup> for InlineValue {
+ #[inline]
+ fn from(from: InlineValueVariableLookup) -> Self {
+ Self::VariableLookup(from)
+ }
+}
+
+impl From<InlineValueEvaluatableExpression> for InlineValue {
+ #[inline]
+ fn from(from: InlineValueEvaluatableExpression) -> Self {
+ Self::EvaluatableExpression(from)
+ }
+}
+
+/// Client workspace capabilities specific to inline values.
+#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
+///
+/// @since 3.17.0
+#[serde(rename_all = "camelCase")]
+pub struct InlineValueWorkspaceClientCapabilities {
+ /// Whether the client implementation supports a refresh request sent from
+ /// the server to the client.
+ ///
+ /// Note that this event is global and will force the client to refresh all
+ /// inline values currently shown. It should be used with absolute care and
+ /// is useful for situation where a server for example detect a project wide
+ /// change that requires such a calculation.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub refresh_support: Option<bool>,
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+ use crate::tests::test_serialization;
+ use crate::Position;
+
+ #[test]
+ fn inline_values() {
+ test_serialization(
+ &InlineValueText {
+ range: Range::new(Position::new(0, 0), Position::new(0, 4)),
+ text: "one".to_owned(),
+ },
+ r#"{"range":{"start":{"line":0,"character":0},"end":{"line":0,"character":4}},"text":"one"}"#,
+ );
+
+ test_serialization(
+ &InlineValue::VariableLookup(InlineValueVariableLookup {
+ range: Range::new(Position::new(1, 0), Position::new(1, 4)),
+ variable_name: None,
+ case_sensitive_lookup: false,
+ }),
+ r#"{"range":{"start":{"line":1,"character":0},"end":{"line":1,"character":4}},"caseSensitiveLookup":false}"#,
+ );
+
+ test_serialization(
+ &InlineValue::EvaluatableExpression(InlineValueEvaluatableExpression {
+ range: Range::new(Position::new(2, 0), Position::new(2, 4)),
+ expression: None,
+ }),
+ r#"{"range":{"start":{"line":2,"character":0},"end":{"line":2,"character":4}}}"#,
+ );
+ }
+}
diff --git a/vendor/lsp-types/src/lib.rs b/vendor/lsp-types/src/lib.rs
index 7469e67a6..027e9ef89 100644
--- a/vendor/lsp-types/src/lib.rs
+++ b/vendor/lsp-types/src/lib.rs
@@ -1,2692 +1,2798 @@
-/*!
-
-Language Server Protocol types for Rust.
-
-Based on: <https://microsoft.github.io/language-server-protocol/specification>
-
-This library uses the URL crate for parsing URIs. Note that there is
-some confusion on the meaning of URLs vs URIs:
-<http://stackoverflow.com/a/28865728/393898>. According to that
-information, on the classical sense of "URLs", "URLs" are a subset of
-URIs, But on the modern/new meaning of URLs, they are the same as
-URIs. The important take-away aspect is that the URL crate should be
-able to parse any URI, such as `urn:isbn:0451450523`.
-
-
-*/
-#![allow(non_upper_case_globals)]
-#[forbid(unsafe_code)]
-#[macro_use]
-extern crate bitflags;
-
-use std::{collections::HashMap, fmt::Debug};
-
-use serde::{de, de::Error as Error_, Deserialize, Serialize};
-use serde_json::Value;
-pub use url::Url;
-
-// Large enough to contain any enumeration name defined in this crate
-type PascalCaseBuf = [u8; 32];
-const fn fmt_pascal_case_const(name: &str) -> (PascalCaseBuf, usize) {
- let mut buf = [0; 32];
- let mut buf_i = 0;
- let mut name_i = 0;
- let name = name.as_bytes();
- while name_i < name.len() {
- let first = name[name_i];
- name_i += 1;
-
- buf[buf_i] = first;
- buf_i += 1;
-
- while name_i < name.len() {
- let rest = name[name_i];
- name_i += 1;
- if rest == b'_' {
- break;
- }
-
- buf[buf_i] = rest.to_ascii_lowercase();
- buf_i += 1;
- }
- }
- (buf, buf_i)
-}
-
-fn fmt_pascal_case(f: &mut std::fmt::Formatter<'_>, name: &str) -> std::fmt::Result {
- for word in name.split('_') {
- let mut chars = word.chars();
- let first = chars.next().unwrap();
- write!(f, "{}", first)?;
- for rest in chars {
- write!(f, "{}", rest.to_lowercase())?;
- }
- }
- Ok(())
-}
-
-macro_rules! lsp_enum {
- (impl $typ: ident { $( $(#[$attr:meta])* pub const $name: ident : $enum_type: ty = $value: expr; )* }) => {
- impl $typ {
- $(
- $(#[$attr])*
- pub const $name: $enum_type = $value;
- )*
- }
-
- impl std::fmt::Debug for $typ {
- fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
- match *self {
- $(
- Self::$name => crate::fmt_pascal_case(f, stringify!($name)),
- )*
- _ => write!(f, "{}({})", stringify!($typ), self.0),
- }
- }
- }
-
- impl std::convert::TryFrom<&str> for $typ {
- type Error = &'static str;
- fn try_from(value: &str) -> Result<Self, Self::Error> {
- match () {
- $(
- _ if {
- const X: (crate::PascalCaseBuf, usize) = crate::fmt_pascal_case_const(stringify!($name));
- let (buf, len) = X;
- &buf[..len] == value.as_bytes()
- } => Ok(Self::$name),
- )*
- _ => Err("unknown enum variant"),
- }
- }
- }
-
- }
-}
-
-pub mod error_codes;
-pub mod notification;
-pub mod request;
-
-mod call_hierarchy;
-pub use call_hierarchy::*;
-
-mod code_action;
-pub use code_action::*;
-
-mod code_lens;
-pub use code_lens::*;
-
-mod color;
-pub use color::*;
-
-mod completion;
-pub use completion::*;
-
-mod document_highlight;
-pub use document_highlight::*;
-
-mod document_link;
-pub use document_link::*;
-
-mod document_symbols;
-pub use document_symbols::*;
-
-mod file_operations;
-pub use file_operations::*;
-
-mod folding_range;
-pub use folding_range::*;
-
-mod formatting;
-pub use formatting::*;
-
-mod hover;
-pub use hover::*;
-
-#[cfg(feature = "proposed")]
-mod inlay_hint;
-#[cfg(feature = "proposed")]
-pub use inlay_hint::*;
-
-mod moniker;
-pub use moniker::*;
-
-mod progress;
-pub use progress::*;
-
-mod references;
-pub use references::*;
-
-mod rename;
-pub use rename::*;
-
-pub mod selection_range;
-pub use selection_range::*;
-
-mod semantic_tokens;
-pub use semantic_tokens::*;
-
-mod signature_help;
-pub use signature_help::*;
-
-mod linked_editing;
-pub use linked_editing::*;
-
-mod window;
-pub use window::*;
-
-mod workspace_folders;
-pub use workspace_folders::*;
-
-mod workspace_symbols;
-pub use workspace_symbols::*;
-
-pub mod lsif;
-
-mod trace;
-pub use trace::*;
-
-/* ----------------- Auxiliary types ----------------- */
-
-#[derive(Debug, Eq, Hash, PartialEq, Clone, Deserialize, Serialize)]
-#[serde(untagged)]
-pub enum NumberOrString {
- Number(i32),
- String(String),
-}
-
-/* ----------------- Cancel support ----------------- */
-
-#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
-pub struct CancelParams {
- /// The request id to cancel.
- pub id: NumberOrString,
-}
-
-/* ----------------- Basic JSON Structures ----------------- */
-
-/// The LSP any type
-///
-/// @since 3.17.0
-#[cfg(feature = "proposed")]
-pub type LSPAny = serde_json::Value;
-
-/// LSP object definition.
-///
-/// @since 3.17.0
-#[cfg(feature = "proposed")]
-pub type LSPObject = serde_json::Map<String, serde_json::Value>;
-
-/// LSP arrays.
-///
-/// @since 3.17.0
-#[cfg(feature = "proposed")]
-pub type LSPArray = Vec<serde_json::Value>;
-
-/// Position in a text document expressed as zero-based line and character offset.
-/// A position is between two characters like an 'insert' cursor in a editor.
-#[derive(Debug, Eq, PartialEq, Ord, PartialOrd, Copy, Clone, Default, Deserialize, Serialize)]
-pub struct Position {
- /// Line position in a document (zero-based).
- pub line: u32,
- /// Character offset on a line in a document (zero-based). The meaning of this
- /// offset is determined by the negotiated `PositionEncodingKind`.
- ///
- /// If the character value is greater than the line length it defaults back
- /// to the line length.
- pub character: u32,
-}
-
-impl Position {
- pub fn new(line: u32, character: u32) -> Position {
- Position { line, character }
- }
-}
-
-/// A range in a text document expressed as (zero-based) start and end positions.
-/// A range is comparable to a selection in an editor. Therefore the end position is exclusive.
-#[derive(Debug, Eq, PartialEq, Copy, Clone, Default, Deserialize, Serialize)]
-pub struct Range {
- /// The range's start position.
- pub start: Position,
- /// The range's end position.
- pub end: Position,
-}
-
-impl Range {
- pub fn new(start: Position, end: Position) -> Range {
- Range { start, end }
- }
-}
-
-/// Represents a location inside a resource, such as a line inside a text file.
-#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
-pub struct Location {
- pub uri: Url,
- pub range: Range,
-}
-
-impl Location {
- pub fn new(uri: Url, range: Range) -> Location {
- Location { uri, range }
- }
-}
-
-/// Represents a link between a source and a target location.
-#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
-#[serde(rename_all = "camelCase")]
-pub struct LocationLink {
- /// Span of the origin of this link.
- ///
- /// Used as the underlined span for mouse interaction. Defaults to the word range at
- /// the mouse position.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub origin_selection_range: Option<Range>,
-
- /// The target resource identifier of this link.
- pub target_uri: Url,
-
- /// The full target range of this link.
- pub target_range: Range,
-
- /// The span of this link.
- pub target_selection_range: Range,
-}
-
-/// A type indicating how positions are encoded,
-/// specifically what column offsets mean.
-///
-/// @since 3.17.0
-#[derive(Debug, Eq, PartialEq, Hash, PartialOrd, Clone, Deserialize, Serialize)]
-#[cfg(feature = "proposed")]
-pub struct PositionEncodingKind(std::borrow::Cow<'static, str>);
-
-#[cfg(feature = "proposed")]
-impl PositionEncodingKind {
- /// Character offsets count UTF-8 code units.
- pub const UTF8: PositionEncodingKind = PositionEncodingKind::new("utf-8");
-
- /// Character offsets count UTF-16 code units.
- ///
- /// This is the default and must always be supported
- /// by servers
- pub const UTF16: PositionEncodingKind = PositionEncodingKind::new("utf-16");
-
- /// Character offsets count UTF-32 code units.
- ///
- /// Implementation note: these are the same as Unicode code points,
- /// so this `PositionEncodingKind` may also be used for an
- /// encoding-agnostic representation of character offsets.
- pub const UTF32: PositionEncodingKind = PositionEncodingKind::new("utf-32");
-
- pub const fn new(tag: &'static str) -> Self {
- PositionEncodingKind(std::borrow::Cow::Borrowed(tag))
- }
-
- pub fn as_str(&self) -> &str {
- &self.0
- }
-}
-
-#[cfg(feature = "proposed")]
-impl From<String> for PositionEncodingKind {
- fn from(from: String) -> Self {
- PositionEncodingKind(std::borrow::Cow::from(from))
- }
-}
-
-#[cfg(feature = "proposed")]
-impl From<&'static str> for PositionEncodingKind {
- fn from(from: &'static str) -> Self {
- PositionEncodingKind::new(from)
- }
-}
-
-/// Represents a diagnostic, such as a compiler error or warning.
-/// Diagnostic objects are only valid in the scope of a resource.
-#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
-#[serde(rename_all = "camelCase")]
-pub struct Diagnostic {
- /// The range at which the message applies.
- pub range: Range,
-
- /// The diagnostic's severity. Can be omitted. If omitted it is up to the
- /// client to interpret diagnostics as error, warning, info or hint.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub severity: Option<DiagnosticSeverity>,
-
- /// The diagnostic's code. Can be omitted.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub code: Option<NumberOrString>,
-
- /// An optional property to describe the error code.
- ///
- /// since 3.16.0
- #[serde(skip_serializing_if = "Option::is_none")]
- pub code_description: Option<CodeDescription>,
-
- /// A human-readable string describing the source of this
- /// diagnostic, e.g. 'typescript' or 'super lint'.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub source: Option<String>,
-
- /// The diagnostic's message.
- pub message: String,
-
- /// An array of related diagnostic information, e.g. when symbol-names within
- /// a scope collide all definitions can be marked via this property.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub related_information: Option<Vec<DiagnosticRelatedInformation>>,
-
- /// Additional metadata about the diagnostic.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub tags: Option<Vec<DiagnosticTag>>,
-
- /// A data entry field that is preserved between a `textDocument/publishDiagnostics`
- /// notification and `textDocument/codeAction` request.
- ///
- /// since 3.16.0
- #[serde(skip_serializing_if = "Option::is_none")]
- pub data: Option<serde_json::Value>,
-}
-
-#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
-#[serde(rename_all = "camelCase")]
-pub struct CodeDescription {
- pub href: Url,
-}
-
-impl Diagnostic {
- pub fn new(
- range: Range,
- severity: Option<DiagnosticSeverity>,
- code: Option<NumberOrString>,
- source: Option<String>,
- message: String,
- related_information: Option<Vec<DiagnosticRelatedInformation>>,
- tags: Option<Vec<DiagnosticTag>>,
- ) -> Diagnostic {
- Diagnostic {
- range,
- severity,
- code,
- source,
- message,
- related_information,
- tags,
- ..Diagnostic::default()
- }
- }
-
- pub fn new_simple(range: Range, message: String) -> Diagnostic {
- Self::new(range, None, None, None, message, None, None)
- }
-
- pub fn new_with_code_number(
- range: Range,
- severity: DiagnosticSeverity,
- code_number: i32,
- source: Option<String>,
- message: String,
- ) -> Diagnostic {
- let code = Some(NumberOrString::Number(code_number));
- Self::new(range, Some(severity), code, source, message, None, None)
- }
-}
-
-/// The protocol currently supports the following diagnostic severities:
-#[derive(Eq, PartialEq, Ord, PartialOrd, Clone, Copy, Deserialize, Serialize)]
-#[serde(transparent)]
-pub struct DiagnosticSeverity(i32);
-lsp_enum! {
-impl DiagnosticSeverity {
- /// Reports an error.
- pub const ERROR: DiagnosticSeverity = DiagnosticSeverity(1);
- /// Reports a warning.
- pub const WARNING: DiagnosticSeverity = DiagnosticSeverity(2);
- /// Reports an information.
- pub const INFORMATION: DiagnosticSeverity = DiagnosticSeverity(3);
- /// Reports a hint.
- pub const HINT: DiagnosticSeverity = DiagnosticSeverity(4);
-}
-}
-
-/// Represents a related message and source code location for a diagnostic. This
-/// should be used to point to code locations that cause or related to a
-/// diagnostics, e.g when duplicating a symbol in a scope.
-#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
-pub struct DiagnosticRelatedInformation {
- /// The location of this related diagnostic information.
- pub location: Location,
-
- /// The message of this related diagnostic information.
- pub message: String,
-}
-
-/// The diagnostic tags.
-#[derive(Eq, PartialEq, Clone, Deserialize, Serialize)]
-#[serde(transparent)]
-pub struct DiagnosticTag(i32);
-lsp_enum! {
-impl DiagnosticTag {
- /// Unused or unnecessary code.
- /// Clients are allowed to render diagnostics with this tag faded out instead of having
- /// an error squiggle.
- pub const UNNECESSARY: DiagnosticTag = DiagnosticTag(1);
-
- /// Deprecated or obsolete code.
- /// Clients are allowed to rendered diagnostics with this tag strike through.
- pub const DEPRECATED: DiagnosticTag = DiagnosticTag(2);
-}
-}
-
-/// Represents a reference to a command. Provides a title which will be used to represent a command in the UI.
-/// Commands are identitifed using a string identifier and the protocol currently doesn't specify a set of
-/// well known commands. So executing a command requires some tool extension code.
-#[derive(Debug, PartialEq, Clone, Default, Deserialize, Serialize)]
-pub struct Command {
- /// Title of the command, like `save`.
- pub title: String,
- /// The identifier of the actual command handler.
- pub command: String,
- /// Arguments that the command handler should be
- /// invoked with.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub arguments: Option<Vec<Value>>,
-}
-
-impl Command {
- pub fn new(title: String, command: String, arguments: Option<Vec<Value>>) -> Command {
- Command {
- title,
- command,
- arguments,
- }
- }
-}
-
-/// A textual edit applicable to a text document.
-///
-/// If n `TextEdit`s are applied to a text document all text edits describe changes to the initial document version.
-/// Execution wise text edits should applied from the bottom to the top of the text document. Overlapping text edits
-/// are not supported.
-#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
-#[serde(rename_all = "camelCase")]
-pub struct TextEdit {
- /// The range of the text document to be manipulated. To insert
- /// text into a document create a range where start === end.
- pub range: Range,
- /// The string to be inserted. For delete operations use an
- /// empty string.
- pub new_text: String,
-}
-
-impl TextEdit {
- pub fn new(range: Range, new_text: String) -> TextEdit {
- TextEdit { range, new_text }
- }
-}
-
-/// An identifier referring to a change annotation managed by a workspace
-/// edit.
-///
-/// @since 3.16.0.
-pub type ChangeAnnotationIdentifier = String;
-
-/// A special text edit with an additional change annotation.
-///
-/// @since 3.16.0.
-#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
-#[serde(rename_all = "camelCase")]
-pub struct AnnotatedTextEdit {
- #[serde(flatten)]
- pub text_edit: TextEdit,
-
- /// The actual annotation
- pub annotation_id: ChangeAnnotationIdentifier,
-}
-
-/// Describes textual changes on a single text document. The text document is referred to as a
-/// `OptionalVersionedTextDocumentIdentifier` to allow clients to check the text document version before an
-/// edit is applied. A `TextDocumentEdit` describes all changes on a version Si and after they are
-/// applied move the document to version Si+1. So the creator of a `TextDocumentEdit` doesn't need to
-/// sort the array or do any kind of ordering. However the edits must be non overlapping.
-#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
-#[serde(rename_all = "camelCase")]
-pub struct TextDocumentEdit {
- /// The text document to change.
- pub text_document: OptionalVersionedTextDocumentIdentifier,
-
- /// The edits to be applied.
- ///
- /// @since 3.16.0 - support for AnnotatedTextEdit. This is guarded by the
- /// client capability `workspace.workspaceEdit.changeAnnotationSupport`
- pub edits: Vec<OneOf<TextEdit, AnnotatedTextEdit>>,
-}
-
-/// Additional information that describes document changes.
-///
-/// @since 3.16.0.
-#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
-#[serde(rename_all = "camelCase")]
-pub struct ChangeAnnotation {
- /// A human-readable string describing the actual change. The string
- /// is rendered prominent in the user interface.
- pub label: String,
-
- /// A flag which indicates that user confirmation is needed
- /// before applying the change.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub needs_confirmation: Option<bool>,
-
- /// A human-readable string which is rendered less prominent in
- /// the user interface.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub description: Option<String>,
-}
-
-#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
-#[serde(rename_all = "camelCase")]
-pub struct ChangeAnnotationWorkspaceEditClientCapabilities {
- /// Whether the client groups edits with equal labels into tree nodes,
- /// for instance all edits labelled with "Changes in Strings" would
- /// be a tree node.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub groups_on_label: Option<bool>,
-}
-
-/// Options to create a file.
-#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
-#[serde(rename_all = "camelCase")]
-pub struct CreateFileOptions {
- /// Overwrite existing file. Overwrite wins over `ignoreIfExists`
- #[serde(skip_serializing_if = "Option::is_none")]
- pub overwrite: Option<bool>,
- /// Ignore if exists.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub ignore_if_exists: Option<bool>,
-}
-
-/// Create file operation
-#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
-#[serde(rename_all = "camelCase")]
-pub struct CreateFile {
- /// The resource to create.
- pub uri: Url,
- /// Additional options
- #[serde(skip_serializing_if = "Option::is_none")]
- pub options: Option<CreateFileOptions>,
-
- /// An optional annotation identifer describing the operation.
- ///
- /// @since 3.16.0
- #[serde(skip_serializing_if = "Option::is_none")]
- pub annotation_id: Option<ChangeAnnotationIdentifier>,
-}
-
-/// Rename file options
-#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
-#[serde(rename_all = "camelCase")]
-pub struct RenameFileOptions {
- /// Overwrite target if existing. Overwrite wins over `ignoreIfExists`
- #[serde(skip_serializing_if = "Option::is_none")]
- pub overwrite: Option<bool>,
- /// Ignores if target exists.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub ignore_if_exists: Option<bool>,
-}
-
-/// Rename file operation
-#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
-#[serde(rename_all = "camelCase")]
-pub struct RenameFile {
- /// The old (existing) location.
- pub old_uri: Url,
- /// The new location.
- pub new_uri: Url,
- /// Rename options.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub options: Option<RenameFileOptions>,
-
- /// An optional annotation identifer describing the operation.
- ///
- /// @since 3.16.0
- #[serde(skip_serializing_if = "Option::is_none")]
- pub annotation_id: Option<ChangeAnnotationIdentifier>,
-}
-
-/// Delete file options
-#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
-#[serde(rename_all = "camelCase")]
-pub struct DeleteFileOptions {
- /// Delete the content recursively if a folder is denoted.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub recursive: Option<bool>,
- /// Ignore the operation if the file doesn't exist.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub ignore_if_not_exists: Option<bool>,
-
- /// An optional annotation identifer describing the operation.
- ///
- /// @since 3.16.0
- #[serde(skip_serializing_if = "Option::is_none")]
- pub annotation_id: Option<ChangeAnnotationIdentifier>,
-}
-
-/// Delete file operation
-#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
-#[serde(rename_all = "camelCase")]
-pub struct DeleteFile {
- /// The file to delete.
- pub uri: Url,
- /// Delete options.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub options: Option<DeleteFileOptions>,
-}
-
-/// A workspace edit represents changes to many resources managed in the workspace.
-/// The edit should either provide `changes` or `documentChanges`.
-/// If the client can handle versioned document edits and if `documentChanges` are present,
-/// the latter are preferred over `changes`.
-#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
-#[serde(rename_all = "camelCase")]
-pub struct WorkspaceEdit {
- /// Holds changes to existing resources.
- #[serde(with = "url_map")]
- #[serde(skip_serializing_if = "Option::is_none")]
- #[serde(default)]
- pub changes: Option<HashMap<Url, Vec<TextEdit>>>, // changes?: { [uri: string]: TextEdit[]; };
-
- /// Depending on the client capability `workspace.workspaceEdit.resourceOperations` document changes
- /// are either an array of `TextDocumentEdit`s to express changes to n different text documents
- /// where each text document edit addresses a specific version of a text document. Or it can contain
- /// above `TextDocumentEdit`s mixed with create, rename and delete file / folder operations.
- ///
- /// Whether a client supports versioned document edits is expressed via
- /// `workspace.workspaceEdit.documentChanges` client capability.
- ///
- /// If a client neither supports `documentChanges` nor `workspace.workspaceEdit.resourceOperations` then
- /// only plain `TextEdit`s using the `changes` property are supported.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub document_changes: Option<DocumentChanges>,
-
- /// A map of change annotations that can be referenced in
- /// `AnnotatedTextEdit`s or create, rename and delete file / folder
- /// operations.
- ///
- /// Whether clients honor this property depends on the client capability
- /// `workspace.changeAnnotationSupport`.
- ///
- /// @since 3.16.0
- ///
- #[serde(skip_serializing_if = "Option::is_none")]
- pub change_annotations: Option<HashMap<ChangeAnnotationIdentifier, ChangeAnnotation>>,
-}
-
-#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
-#[serde(untagged)]
-pub enum DocumentChanges {
- Edits(Vec<TextDocumentEdit>),
- Operations(Vec<DocumentChangeOperation>),
-}
-
-// TODO: Once https://github.com/serde-rs/serde/issues/912 is solved
-// we can remove ResourceOp and switch to the following implementation
-// of DocumentChangeOperation:
-//
-// #[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
-// #[serde(tag = "kind", rename_all="lowercase" )]
-// pub enum DocumentChangeOperation {
-// Create(CreateFile),
-// Rename(RenameFile),
-// Delete(DeleteFile),
-//
-// #[serde(other)]
-// Edit(TextDocumentEdit),
-// }
-
-#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
-#[serde(untagged, rename_all = "lowercase")]
-pub enum DocumentChangeOperation {
- Op(ResourceOp),
- Edit(TextDocumentEdit),
-}
-
-#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
-#[serde(tag = "kind", rename_all = "lowercase")]
-pub enum ResourceOp {
- Create(CreateFile),
- Rename(RenameFile),
- Delete(DeleteFile),
-}
-
-pub type DidChangeConfigurationClientCapabilities = DynamicRegistrationClientCapabilities;
-
-#[derive(Debug, Default, Eq, PartialEq, Clone, Deserialize, Serialize)]
-#[serde(rename_all = "camelCase")]
-pub struct ConfigurationParams {
- pub items: Vec<ConfigurationItem>,
-}
-
-#[derive(Debug, Default, Eq, PartialEq, Clone, Deserialize, Serialize)]
-#[serde(rename_all = "camelCase")]
-pub struct ConfigurationItem {
- /// The scope to get the configuration section for.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub scope_uri: Option<Url>,
-
- ///The configuration section asked for.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub section: Option<String>,
-}
-
-mod url_map {
- use std::fmt;
-
- use super::*;
-
- pub fn deserialize<'de, D>(
- deserializer: D,
- ) -> Result<Option<HashMap<Url, Vec<TextEdit>>>, D::Error>
- where
- D: serde::Deserializer<'de>,
- {
- struct UrlMapVisitor;
- impl<'de> de::Visitor<'de> for UrlMapVisitor {
- type Value = HashMap<Url, Vec<TextEdit>>;
-
- fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
- formatter.write_str("map")
- }
-
- fn visit_map<M>(self, mut visitor: M) -> Result<Self::Value, M::Error>
- where
- M: de::MapAccess<'de>,
- {
- let mut values = HashMap::with_capacity(visitor.size_hint().unwrap_or(0));
-
- // While there are entries remaining in the input, add them
- // into our map.
- while let Some((key, value)) = visitor.next_entry::<Url, _>()? {
- values.insert(key, value);
- }
-
- Ok(values)
- }
- }
-
- struct OptionUrlMapVisitor;
- impl<'de> de::Visitor<'de> for OptionUrlMapVisitor {
- type Value = Option<HashMap<Url, Vec<TextEdit>>>;
-
- fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
- formatter.write_str("option")
- }
-
- #[inline]
- fn visit_unit<E>(self) -> Result<Self::Value, E>
- where
- E: serde::de::Error,
- {
- Ok(None)
- }
-
- #[inline]
- fn visit_none<E>(self) -> Result<Self::Value, E>
- where
- E: serde::de::Error,
- {
- Ok(None)
- }
-
- #[inline]
- fn visit_some<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
- where
- D: serde::Deserializer<'de>,
- {
- deserializer.deserialize_map(UrlMapVisitor).map(Some)
- }
- }
-
- // Instantiate our Visitor and ask the Deserializer to drive
- // it over the input data, resulting in an instance of MyMap.
- deserializer.deserialize_option(OptionUrlMapVisitor)
- }
-
- pub fn serialize<S>(
- changes: &Option<HashMap<Url, Vec<TextEdit>>>,
- serializer: S,
- ) -> Result<S::Ok, S::Error>
- where
- S: serde::Serializer,
- {
- use serde::ser::SerializeMap;
-
- match *changes {
- Some(ref changes) => {
- let mut map = serializer.serialize_map(Some(changes.len()))?;
- for (k, v) in changes {
- map.serialize_entry(k.as_str(), v)?;
- }
- map.end()
- }
- None => serializer.serialize_none(),
- }
- }
-}
-
-impl WorkspaceEdit {
- pub fn new(changes: HashMap<Url, Vec<TextEdit>>) -> WorkspaceEdit {
- WorkspaceEdit {
- changes: Some(changes),
- document_changes: None,
- ..Default::default()
- }
- }
-}
-
-/// Text documents are identified using a URI. On the protocol level, URIs are passed as strings.
-#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
-pub struct TextDocumentIdentifier {
- // !!!!!! Note:
- // In the spec VersionedTextDocumentIdentifier extends TextDocumentIdentifier
- // This modelled by "mixing-in" TextDocumentIdentifier in VersionedTextDocumentIdentifier,
- // so any changes to this type must be effected in the sub-type as well.
- /// The text document's URI.
- pub uri: Url,
-}
-
-impl TextDocumentIdentifier {
- pub fn new(uri: Url) -> TextDocumentIdentifier {
- TextDocumentIdentifier { uri }
- }
-}
-
-/// An item to transfer a text document from the client to the server.
-#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
-#[serde(rename_all = "camelCase")]
-pub struct TextDocumentItem {
- /// The text document's URI.
- pub uri: Url,
-
- /// The text document's language identifier.
- pub language_id: String,
-
- /// The version number of this document (it will strictly increase after each
- /// change, including undo/redo).
- pub version: i32,
-
- /// The content of the opened text document.
- pub text: String,
-}
-
-impl TextDocumentItem {
- pub fn new(uri: Url, language_id: String, version: i32, text: String) -> TextDocumentItem {
- TextDocumentItem {
- uri,
- language_id,
- version,
- text,
- }
- }
-}
-
-/// An identifier to denote a specific version of a text document. This information usually flows from the client to the server.
-#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
-pub struct VersionedTextDocumentIdentifier {
- // This field was "mixed-in" from TextDocumentIdentifier
- /// The text document's URI.
- pub uri: Url,
-
- /// The version number of this document.
- ///
- /// The version number of a document will increase after each change,
- /// including undo/redo. The number doesn't need to be consecutive.
- pub version: i32,
-}
-
-impl VersionedTextDocumentIdentifier {
- pub fn new(uri: Url, version: i32) -> VersionedTextDocumentIdentifier {
- VersionedTextDocumentIdentifier { uri, version }
- }
-}
-
-/// An identifier which optionally denotes a specific version of a text document. This information usually flows from the server to the client
-#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
-pub struct OptionalVersionedTextDocumentIdentifier {
- // This field was "mixed-in" from TextDocumentIdentifier
- /// The text document's URI.
- pub uri: Url,
-
- /// The version number of this document. If an optional versioned text document
- /// identifier is sent from the server to the client and the file is not
- /// open in the editor (the server has not received an open notification
- /// before) the server can send `null` to indicate that the version is
- /// known and the content on disk is the master (as specified with document
- /// content ownership).
- ///
- /// The version number of a document will increase after each change,
- /// including undo/redo. The number doesn't need to be consecutive.
- pub version: Option<i32>,
-}
-
-impl OptionalVersionedTextDocumentIdentifier {
- pub fn new(uri: Url, version: i32) -> OptionalVersionedTextDocumentIdentifier {
- OptionalVersionedTextDocumentIdentifier {
- uri,
- version: Some(version),
- }
- }
-}
-
-/// A parameter literal used in requests to pass a text document and a position inside that document.
-#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
-#[serde(rename_all = "camelCase")]
-pub struct TextDocumentPositionParams {
- // !!!!!! Note:
- // In the spec ReferenceParams extends TextDocumentPositionParams
- // This modelled by "mixing-in" TextDocumentPositionParams in ReferenceParams,
- // so any changes to this type must be effected in sub-type as well.
- /// The text document.
- pub text_document: TextDocumentIdentifier,
-
- /// The position inside the text document.
- pub position: Position,
-}
-
-impl TextDocumentPositionParams {
- pub fn new(
- text_document: TextDocumentIdentifier,
- position: Position,
- ) -> TextDocumentPositionParams {
- TextDocumentPositionParams {
- text_document,
- position,
- }
- }
-}
-
-/// A document filter denotes a document through properties like language, schema or pattern.
-/// Examples are a filter that applies to TypeScript files on disk or a filter the applies to JSON
-/// files with name package.json:
-///
-/// { language: 'typescript', scheme: 'file' }
-/// { language: 'json', pattern: '**/package.json' }
-#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
-pub struct DocumentFilter {
- /// A language id, like `typescript`.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub language: Option<String>,
-
- /// A Uri [scheme](#Uri.scheme), like `file` or `untitled`.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub scheme: Option<String>,
-
- /// A glob pattern, like `*.{ts,js}`.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub pattern: Option<String>,
-}
-
-/// A document selector is the combination of one or many document filters.
-pub type DocumentSelector = Vec<DocumentFilter>;
-
-// ========================= Actual Protocol =========================
-
-#[derive(Debug, PartialEq, Clone, Deserialize, Serialize, Default)]
-#[serde(rename_all = "camelCase")]
-pub struct InitializeParams {
- /// The process Id of the parent process that started
- /// the server. Is null if the process has not been started by another process.
- /// If the parent process is not alive then the server should exit (see exit notification) its process.
- pub process_id: Option<u32>,
-
- /// The rootPath of the workspace. Is null
- /// if no folder is open.
- #[serde(skip_serializing_if = "Option::is_none")]
- #[deprecated(note = "Use `root_uri` instead when possible")]
- pub root_path: Option<String>,
-
- /// The rootUri of the workspace. Is null if no
- /// folder is open. If both `rootPath` and `rootUri` are set
- /// `rootUri` wins.
- ///
- /// Deprecated in favour of `workspaceFolders`
- #[serde(default)]
- pub root_uri: Option<Url>,
-
- /// User provided initialization options.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub initialization_options: Option<Value>,
-
- /// The capabilities provided by the client (editor or tool)
- pub capabilities: ClientCapabilities,
-
- /// The initial trace setting. If omitted trace is disabled ('off').
- #[serde(default)]
- #[serde(skip_serializing_if = "Option::is_none")]
- pub trace: Option<TraceValue>,
-
- /// The workspace folders configured in the client when the server starts.
- /// This property is only available if the client supports workspace folders.
- /// It can be `null` if the client supports workspace folders but none are
- /// configured.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub workspace_folders: Option<Vec<WorkspaceFolder>>,
-
- /// Information about the client.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub client_info: Option<ClientInfo>,
-
- /// The locale the client is currently showing the user interface
- /// in. This must not necessarily be the locale of the operating
- /// system.
- ///
- /// Uses IETF language tags as the value's syntax
- /// (See <https://en.wikipedia.org/wiki/IETF_language_tag>)
- ///
- /// @since 3.16.0
- #[serde(skip_serializing_if = "Option::is_none")]
- pub locale: Option<String>,
-}
-
-#[derive(Debug, PartialEq, Clone, Deserialize, Serialize)]
-pub struct ClientInfo {
- /// The name of the client as defined by the client.
- pub name: String,
- /// The client's version as defined by the client.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub version: Option<String>,
-}
-
-#[derive(Debug, PartialEq, Clone, Copy, Deserialize, Serialize)]
-pub struct InitializedParams {}
-
-#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
-pub struct GenericRegistrationOptions {
- #[serde(flatten)]
- pub text_document_registration_options: TextDocumentRegistrationOptions,
-
- #[serde(flatten)]
- pub options: GenericOptions,
-
- #[serde(flatten)]
- pub static_registration_options: StaticRegistrationOptions,
-}
-
-#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
-pub struct GenericOptions {
- #[serde(flatten)]
- pub work_done_progress_options: WorkDoneProgressOptions,
-}
-
-#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
-pub struct GenericParams {
- #[serde(flatten)]
- pub text_document_position_params: TextDocumentPositionParams,
-
- #[serde(flatten)]
- pub work_done_progress_params: WorkDoneProgressParams,
-
- #[serde(flatten)]
- pub partial_result_params: PartialResultParams,
-}
-
-#[derive(Debug, Eq, PartialEq, Clone, Copy, Default, Deserialize, Serialize)]
-#[serde(rename_all = "camelCase")]
-pub struct DynamicRegistrationClientCapabilities {
- /// This capability supports dynamic registration.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub dynamic_registration: Option<bool>,
-}
-
-#[derive(Debug, Eq, PartialEq, Clone, Copy, Default, Deserialize, Serialize)]
-#[serde(rename_all = "camelCase")]
-pub struct GotoCapability {
- #[serde(skip_serializing_if = "Option::is_none")]
- pub dynamic_registration: Option<bool>,
-
- /// The client supports additional metadata in the form of definition links.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub link_support: Option<bool>,
-}
-
-#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
-#[serde(rename_all = "camelCase")]
-pub struct WorkspaceEditClientCapabilities {
- /// The client supports versioned document changes in `WorkspaceEdit`s
- #[serde(skip_serializing_if = "Option::is_none")]
- pub document_changes: Option<bool>,
-
- /// The resource operations the client supports. Clients should at least
- /// support 'create', 'rename' and 'delete' files and folders.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub resource_operations: Option<Vec<ResourceOperationKind>>,
-
- /// The failure handling strategy of a client if applying the workspace edit
- /// failes.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub failure_handling: Option<FailureHandlingKind>,
-
- /// Whether the client normalizes line endings to the client specific
- /// setting.
- /// If set to `true` the client will normalize line ending characters
- /// in a workspace edit containg to the client specific new line
- /// character.
- ///
- /// @since 3.16.0
- #[serde(skip_serializing_if = "Option::is_none")]
- pub normalizes_line_endings: Option<bool>,
-
- /// Whether the client in general supports change annotations on text edits,
- /// create file, rename file and delete file changes.
- ///
- /// @since 3.16.0
- #[serde(skip_serializing_if = "Option::is_none")]
- pub change_annotation_support: Option<ChangeAnnotationWorkspaceEditClientCapabilities>,
-}
-
-#[derive(Debug, Eq, PartialEq, Deserialize, Serialize, Copy, Clone)]
-#[serde(rename_all = "lowercase")]
-pub enum ResourceOperationKind {
- Create,
- Rename,
- Delete,
-}
-
-#[derive(Debug, Eq, PartialEq, Deserialize, Serialize, Copy, Clone)]
-#[serde(rename_all = "camelCase")]
-pub enum FailureHandlingKind {
- Abort,
- Transactional,
- TextOnlyTransactional,
- Undo,
-}
-
-/// A symbol kind.
-#[derive(Eq, PartialEq, Copy, Clone, Serialize, Deserialize)]
-#[serde(transparent)]
-pub struct SymbolKind(i32);
-lsp_enum! {
-impl SymbolKind {
- pub const FILE: SymbolKind = SymbolKind(1);
- pub const MODULE: SymbolKind = SymbolKind(2);
- pub const NAMESPACE: SymbolKind = SymbolKind(3);
- pub const PACKAGE: SymbolKind = SymbolKind(4);
- pub const CLASS: SymbolKind = SymbolKind(5);
- pub const METHOD: SymbolKind = SymbolKind(6);
- pub const PROPERTY: SymbolKind = SymbolKind(7);
- pub const FIELD: SymbolKind = SymbolKind(8);
- pub const CONSTRUCTOR: SymbolKind = SymbolKind(9);
- pub const ENUM: SymbolKind = SymbolKind(10);
- pub const INTERFACE: SymbolKind = SymbolKind(11);
- pub const FUNCTION: SymbolKind = SymbolKind(12);
- pub const VARIABLE: SymbolKind = SymbolKind(13);
- pub const CONSTANT: SymbolKind = SymbolKind(14);
- pub const STRING: SymbolKind = SymbolKind(15);
- pub const NUMBER: SymbolKind = SymbolKind(16);
- pub const BOOLEAN: SymbolKind = SymbolKind(17);
- pub const ARRAY: SymbolKind = SymbolKind(18);
- pub const OBJECT: SymbolKind = SymbolKind(19);
- pub const KEY: SymbolKind = SymbolKind(20);
- pub const NULL: SymbolKind = SymbolKind(21);
- pub const ENUM_MEMBER: SymbolKind = SymbolKind(22);
- pub const STRUCT: SymbolKind = SymbolKind(23);
- pub const EVENT: SymbolKind = SymbolKind(24);
- pub const OPERATOR: SymbolKind = SymbolKind(25);
- pub const TYPE_PARAMETER: SymbolKind = SymbolKind(26);
-}
-}
-
-/// Specific capabilities for the `SymbolKind` in the `workspace/symbol` request.
-#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
-#[serde(rename_all = "camelCase")]
-pub struct SymbolKindCapability {
- /// The symbol kind values the client supports. When this
- /// property exists the client also guarantees that it will
- /// handle values outside its set gracefully and falls back
- /// to a default value when unknown.
- ///
- /// If this property is not present the client only supports
- /// the symbol kinds from `File` to `Array` as defined in
- /// the initial version of the protocol.
- pub value_set: Option<Vec<SymbolKind>>,
-}
-
-/// Workspace specific client capabilities.
-#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
-#[serde(rename_all = "camelCase")]
-pub struct WorkspaceClientCapabilities {
- /// The client supports applying batch edits to the workspace by supporting
- /// the request 'workspace/applyEdit'
- #[serde(skip_serializing_if = "Option::is_none")]
- pub apply_edit: Option<bool>,
-
- /// Capabilities specific to `WorkspaceEdit`s
- #[serde(skip_serializing_if = "Option::is_none")]
- pub workspace_edit: Option<WorkspaceEditClientCapabilities>,
-
- /// Capabilities specific to the `workspace/didChangeConfiguration` notification.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub did_change_configuration: Option<DidChangeConfigurationClientCapabilities>,
-
- /// Capabilities specific to the `workspace/didChangeWatchedFiles` notification.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub did_change_watched_files: Option<DidChangeWatchedFilesClientCapabilities>,
-
- /// Capabilities specific to the `workspace/symbol` request.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub symbol: Option<WorkspaceSymbolClientCapabilities>,
-
- /// Capabilities specific to the `workspace/executeCommand` request.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub execute_command: Option<ExecuteCommandClientCapabilities>,
-
- /// The client has support for workspace folders.
- /// since 3.6.0
- #[serde(skip_serializing_if = "Option::is_none")]
- pub workspace_folders: Option<bool>,
-
- /// The client supports `workspace/configuration` requests.
- /// since 3.6.0
- #[serde(skip_serializing_if = "Option::is_none")]
- pub configuration: Option<bool>,
-
- /// Capabilities specific to the semantic token requsts scoped to the workspace.
- /// since 3.16.0
- #[serde(skip_serializing_if = "Option::is_none")]
- pub semantic_tokens: Option<SemanticTokensWorkspaceClientCapabilities>,
-
- /// Capabilities specific to the code lens requests scoped to the workspace.
- /// since 3.16.0
- #[serde(skip_serializing_if = "Option::is_none")]
- pub code_lens: Option<CodeLensWorkspaceClientCapabilities>,
-
- /// The client has support for file requests/notifications.
- /// since 3.16.0
- #[serde(skip_serializing_if = "Option::is_none")]
- pub file_operations: Option<WorkspaceFileOperationsClientCapabilities>,
-
- #[serde(skip_serializing_if = "Option::is_none")]
- #[cfg(feature = "proposed")]
- pub inlay_hint: Option<InlayHintWorkspaceClientCapabilities>,
-}
-
-#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
-#[serde(rename_all = "camelCase")]
-pub struct TextDocumentSyncClientCapabilities {
- /// Whether text document synchronization supports dynamic registration.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub dynamic_registration: Option<bool>,
-
- /// The client supports sending will save notifications.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub will_save: Option<bool>,
-
- /// The client supports sending a will save request and
- /// waits for a response providing text edits which will
- /// be applied to the document before it is saved.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub will_save_wait_until: Option<bool>,
-
- /// The client supports did save notifications.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub did_save: Option<bool>,
-}
-
-#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
-#[serde(rename_all = "camelCase")]
-pub struct PublishDiagnosticsClientCapabilities {
- /// Whether the clients accepts diagnostics with related information.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub related_information: Option<bool>,
-
- /// Client supports the tag property to provide meta data about a diagnostic.
- /// Clients supporting tags have to handle unknown tags gracefully.
- #[serde(
- default,
- skip_serializing_if = "Option::is_none",
- deserialize_with = "TagSupport::deserialize_compat"
- )]
- pub tag_support: Option<TagSupport<DiagnosticTag>>,
-
- /// Whether the client interprets the version property of the
- /// `textDocument/publishDiagnostics` notification's parameter.
- ///
- /// 3.15.0
- #[serde(skip_serializing_if = "Option::is_none")]
- pub version_support: Option<bool>,
-
- /// Client supports a codeDescription property
- ///
- /// 3.16.0
- #[serde(skip_serializing_if = "Option::is_none")]
- pub code_description_support: Option<bool>,
-
- /// Whether code action supports the `data` property which is
- /// preserved between a `textDocument/publishDiagnostics` and
- /// `textDocument/codeAction` request.
- ///
- /// 3.16.0
- #[serde(skip_serializing_if = "Option::is_none")]
- pub data_support: Option<bool>,
-}
-
-#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
-#[serde(rename_all = "camelCase")]
-pub struct TagSupport<T> {
- /// The tags supported by the client.
- pub value_set: Vec<T>,
-}
-
-impl<T> TagSupport<T> {
- /// Support for deserializing a boolean tag Support, in case it's present.
- ///
- /// This is currently the case for vscode 1.41.1
- fn deserialize_compat<'de, S>(serializer: S) -> Result<Option<TagSupport<T>>, S::Error>
- where
- S: serde::Deserializer<'de>,
- T: serde::Deserialize<'de>,
- {
- Ok(
- match Option::<Value>::deserialize(serializer).map_err(serde::de::Error::custom)? {
- Some(Value::Bool(false)) => None,
- Some(Value::Bool(true)) => Some(TagSupport { value_set: vec![] }),
- Some(other) => {
- Some(TagSupport::<T>::deserialize(other).map_err(serde::de::Error::custom)?)
- }
- None => None,
- },
- )
- }
-}
-
-/// Text document specific client capabilities.
-#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
-#[serde(rename_all = "camelCase")]
-pub struct TextDocumentClientCapabilities {
- #[serde(skip_serializing_if = "Option::is_none")]
- pub synchronization: Option<TextDocumentSyncClientCapabilities>,
- /// Capabilities specific to the `textDocument/completion`
- #[serde(skip_serializing_if = "Option::is_none")]
- pub completion: Option<CompletionClientCapabilities>,
-
- /// Capabilities specific to the `textDocument/hover`
- #[serde(skip_serializing_if = "Option::is_none")]
- pub hover: Option<HoverClientCapabilities>,
-
- /// Capabilities specific to the `textDocument/signatureHelp`
- #[serde(skip_serializing_if = "Option::is_none")]
- pub signature_help: Option<SignatureHelpClientCapabilities>,
-
- /// Capabilities specific to the `textDocument/references`
- #[serde(skip_serializing_if = "Option::is_none")]
- pub references: Option<ReferenceClientCapabilities>,
-
- /// Capabilities specific to the `textDocument/documentHighlight`
- #[serde(skip_serializing_if = "Option::is_none")]
- pub document_highlight: Option<DocumentHighlightClientCapabilities>,
-
- /// Capabilities specific to the `textDocument/documentSymbol`
- #[serde(skip_serializing_if = "Option::is_none")]
- pub document_symbol: Option<DocumentSymbolClientCapabilities>,
- /// Capabilities specific to the `textDocument/formatting`
- #[serde(skip_serializing_if = "Option::is_none")]
- pub formatting: Option<DocumentFormattingClientCapabilities>,
-
- /// Capabilities specific to the `textDocument/rangeFormatting`
- #[serde(skip_serializing_if = "Option::is_none")]
- pub range_formatting: Option<DocumentRangeFormattingClientCapabilities>,
-
- /// Capabilities specific to the `textDocument/onTypeFormatting`
- #[serde(skip_serializing_if = "Option::is_none")]
- pub on_type_formatting: Option<DocumentOnTypeFormattingClientCapabilities>,
-
- /// Capabilities specific to the `textDocument/declaration`
- #[serde(skip_serializing_if = "Option::is_none")]
- pub declaration: Option<GotoCapability>,
-
- /// Capabilities specific to the `textDocument/definition`
- #[serde(skip_serializing_if = "Option::is_none")]
- pub definition: Option<GotoCapability>,
-
- /// Capabilities specific to the `textDocument/typeDefinition`
- #[serde(skip_serializing_if = "Option::is_none")]
- pub type_definition: Option<GotoCapability>,
-
- /// Capabilities specific to the `textDocument/implementation`
- #[serde(skip_serializing_if = "Option::is_none")]
- pub implementation: Option<GotoCapability>,
-
- /// Capabilities specific to the `textDocument/codeAction`
- #[serde(skip_serializing_if = "Option::is_none")]
- pub code_action: Option<CodeActionClientCapabilities>,
-
- /// Capabilities specific to the `textDocument/codeLens`
- #[serde(skip_serializing_if = "Option::is_none")]
- pub code_lens: Option<CodeLensClientCapabilities>,
-
- /// Capabilities specific to the `textDocument/documentLink`
- #[serde(skip_serializing_if = "Option::is_none")]
- pub document_link: Option<DocumentLinkClientCapabilities>,
-
- /// Capabilities specific to the `textDocument/documentColor` and the
- /// `textDocument/colorPresentation` request.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub color_provider: Option<DocumentColorClientCapabilities>,
-
- /// Capabilities specific to the `textDocument/rename`
- #[serde(skip_serializing_if = "Option::is_none")]
- pub rename: Option<RenameClientCapabilities>,
-
- /// Capabilities specific to `textDocument/publishDiagnostics`.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub publish_diagnostics: Option<PublishDiagnosticsClientCapabilities>,
-
- /// Capabilities specific to `textDocument/foldingRange` requests.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub folding_range: Option<FoldingRangeClientCapabilities>,
-
- /// Capabilities specific to the `textDocument/selectionRange` request.
- ///
- /// @since 3.15.0
- #[serde(skip_serializing_if = "Option::is_none")]
- pub selection_range: Option<SelectionRangeClientCapabilities>,
-
- /// Capabilities specific to `textDocument/linkedEditingRange` requests.
- ///
- /// @since 3.16.0
- #[serde(skip_serializing_if = "Option::is_none")]
- pub linked_editing_range: Option<LinkedEditingRangeClientCapabilities>,
-
- /// Capabilities specific to the various call hierarchy requests.
- ///
- /// @since 3.16.0
- #[serde(skip_serializing_if = "Option::is_none")]
- pub call_hierarchy: Option<CallHierarchyClientCapabilities>,
-
- /// Capabilities specific to the `textDocument/semanticTokens/*` requests.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub semantic_tokens: Option<SemanticTokensClientCapabilities>,
-
- /// Capabilities specific to the `textDocument/moniker` request.
- ///
- /// @since 3.16.0
- #[serde(skip_serializing_if = "Option::is_none")]
- pub moniker: Option<MonikerClientCapabilities>,
-
- /// Capabilities specific to the `textDocument/inlayHint` request.
- ///
- /// @since 3.17.0 - proposed state
- #[serde(skip_serializing_if = "Option::is_none")]
- #[cfg(feature = "proposed")]
- pub inlay_hint: Option<InlayHintClientCapabilities>,
-}
-
-/// Where ClientCapabilities are currently empty:
-#[derive(Debug, PartialEq, Clone, Default, Deserialize, Serialize)]
-#[serde(rename_all = "camelCase")]
-pub struct ClientCapabilities {
- /// Workspace specific client capabilities.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub workspace: Option<WorkspaceClientCapabilities>,
-
- /// Text document specific client capabilities.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub text_document: Option<TextDocumentClientCapabilities>,
-
- /// Window specific client capabilities.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub window: Option<WindowClientCapabilities>,
-
- /// General client capabilities.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub general: Option<GeneralClientCapabilities>,
-
- /// Unofficial UT8-offsets extension.
- ///
- /// See https://clangd.llvm.org/extensions.html#utf-8-offsets.
- #[serde(skip_serializing_if = "Option::is_none")]
- #[cfg(feature = "proposed")]
- pub offset_encoding: Option<Vec<String>>,
-
- /// Experimental client capabilities.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub experimental: Option<Value>,
-}
-
-#[derive(Debug, PartialEq, Clone, Default, Deserialize, Serialize)]
-#[serde(rename_all = "camelCase")]
-pub struct GeneralClientCapabilities {
- /// Client capabilities specific to regular expressions.
- /// @since 3.16.0
- #[serde(skip_serializing_if = "Option::is_none")]
- pub regular_expressions: Option<RegularExpressionsClientCapabilities>,
-
- /// Client capabilities specific to the client's markdown parser.
- /// @since 3.16.0
- #[serde(skip_serializing_if = "Option::is_none")]
- pub markdown: Option<MarkdownClientCapabilities>,
-
- /// @since 3.17.0
- #[cfg(feature = "proposed")]
- #[serde(skip_serializing_if = "Option::is_none")]
- pub stale_request_support: Option<StaleRequestSupportClientCapabilities>,
-
- /// The position encodings supported by the client. Client and server
- /// have to agree on the same position encoding to ensure that offsets
- /// (e.g. character position in a line) are interpreted the same on both
- /// side.
- ///
- /// To keep the protocol backwards compatible the following applies: if
- /// the value 'utf-16' is missing from the array of position encodings
- /// servers can assume that the client supports UTF-16. UTF-16 is
- /// therefore a mandatory encoding.
- ///
- /// If omitted it defaults to ['utf-16'].
- ///
- /// Implementation considerations: since the conversion from one encoding
- /// into another requires the content of the file / line the conversion
- /// is best done where the file is read which is usually on the server
- /// side.
- ///
- /// @since 3.17.0
- #[cfg(feature = "proposed")]
- #[serde(skip_serializing_if = "Option::is_none")]
- pub position_encodings: Option<Vec<PositionEncodingKind>>,
-}
-
-/// Client capability that signals how the client
-/// handles stale requests (e.g. a request
-/// for which the client will not process the response
-/// anymore since the information is outdated).
-///
-/// @since 3.17.0
-#[cfg(feature = "proposed")]
-#[derive(Debug, PartialEq, Clone, Default, Deserialize, Serialize)]
-#[serde(rename_all = "camelCase")]
-pub struct StaleRequestSupportClientCapabilities {
- /// The client will actively cancel the request.
- pub cancel: bool,
-
- /// The list of requests for which the client
- /// will retry the request if it receives a
- /// response with error code `ContentModified``
- pub retry_on_content_modified: Vec<String>,
-}
-
-#[derive(Debug, PartialEq, Clone, Default, Deserialize, Serialize)]
-#[serde(rename_all = "camelCase")]
-pub struct RegularExpressionsClientCapabilities {
- /// The engine's name.
- pub engine: String,
-
- /// The engine's version
- #[serde(skip_serializing_if = "Option::is_none")]
- pub version: Option<String>,
-}
-
-#[derive(Debug, PartialEq, Clone, Default, Deserialize, Serialize)]
-#[serde(rename_all = "camelCase")]
-pub struct MarkdownClientCapabilities {
- /// The name of the parser.
- pub parser: String,
-
- /// The version of the parser.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub version: Option<String>,
-}
-
-#[derive(Debug, PartialEq, Clone, Default, Deserialize, Serialize)]
-#[serde(rename_all = "camelCase")]
-pub struct InitializeResult {
- /// The capabilities the language server provides.
- pub capabilities: ServerCapabilities,
-
- /// Information about the server.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub server_info: Option<ServerInfo>,
-
- /// Unofficial UT8-offsets extension.
- ///
- /// See https://clangd.llvm.org/extensions.html#utf-8-offsets.
- #[serde(skip_serializing_if = "Option::is_none")]
- #[cfg(feature = "proposed")]
- pub offset_encoding: Option<String>,
-}
-
-#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
-pub struct ServerInfo {
- /// The name of the server as defined by the server.
- pub name: String,
- /// The servers's version as defined by the server.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub version: Option<String>,
-}
-
-#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
-pub struct InitializeError {
- /// Indicates whether the client should retry to send the
- /// initilize request after showing the message provided
- /// in the ResponseError.
- pub retry: bool,
-}
-
-// The server can signal the following capabilities:
-
-/// Defines how the host (editor) should sync document changes to the language server.
-#[derive(Eq, PartialEq, Clone, Copy, Deserialize, Serialize)]
-#[serde(transparent)]
-pub struct TextDocumentSyncKind(i32);
-lsp_enum! {
-impl TextDocumentSyncKind {
- /// Documents should not be synced at all.
- pub const NONE: TextDocumentSyncKind = TextDocumentSyncKind(0);
-
- /// Documents are synced by always sending the full content of the document.
- pub const FULL: TextDocumentSyncKind = TextDocumentSyncKind(1);
-
- /// Documents are synced by sending the full content on open. After that only
- /// incremental updates to the document are sent.
- pub const INCREMENTAL: TextDocumentSyncKind = TextDocumentSyncKind(2);
-}
-}
-
-pub type ExecuteCommandClientCapabilities = DynamicRegistrationClientCapabilities;
-
-/// Execute command options.
-#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
-pub struct ExecuteCommandOptions {
- /// The commands to be executed on the server
- pub commands: Vec<String>,
-
- #[serde(flatten)]
- pub work_done_progress_options: WorkDoneProgressOptions,
-}
-
-/// Save options.
-#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
-#[serde(rename_all = "camelCase")]
-pub struct SaveOptions {
- /// The client is supposed to include the content on save.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub include_text: Option<bool>,
-}
-
-#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
-#[serde(untagged)]
-pub enum TextDocumentSyncSaveOptions {
- Supported(bool),
- SaveOptions(SaveOptions),
-}
-
-impl From<SaveOptions> for TextDocumentSyncSaveOptions {
- fn from(from: SaveOptions) -> Self {
- Self::SaveOptions(from)
- }
-}
-
-impl From<bool> for TextDocumentSyncSaveOptions {
- fn from(from: bool) -> Self {
- Self::Supported(from)
- }
-}
-
-#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
-#[serde(rename_all = "camelCase")]
-pub struct TextDocumentSyncOptions {
- /// Open and close notifications are sent to the server.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub open_close: Option<bool>,
-
- /// Change notifications are sent to the server. See TextDocumentSyncKind.None, TextDocumentSyncKind.Full
- /// and TextDocumentSyncKindIncremental.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub change: Option<TextDocumentSyncKind>,
-
- /// Will save notifications are sent to the server.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub will_save: Option<bool>,
-
- /// Will save wait until requests are sent to the server.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub will_save_wait_until: Option<bool>,
-
- /// Save notifications are sent to the server.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub save: Option<TextDocumentSyncSaveOptions>,
-}
-
-#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
-#[serde(untagged)]
-pub enum OneOf<A, B> {
- Left(A),
- Right(B),
-}
-
-#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
-#[serde(untagged)]
-pub enum TextDocumentSyncCapability {
- Kind(TextDocumentSyncKind),
- Options(TextDocumentSyncOptions),
-}
-
-impl From<TextDocumentSyncOptions> for TextDocumentSyncCapability {
- fn from(from: TextDocumentSyncOptions) -> Self {
- Self::Options(from)
- }
-}
-
-impl From<TextDocumentSyncKind> for TextDocumentSyncCapability {
- fn from(from: TextDocumentSyncKind) -> Self {
- Self::Kind(from)
- }
-}
-
-#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
-#[serde(untagged)]
-pub enum ImplementationProviderCapability {
- Simple(bool),
- Options(StaticTextDocumentRegistrationOptions),
-}
-
-impl From<StaticTextDocumentRegistrationOptions> for ImplementationProviderCapability {
- fn from(from: StaticTextDocumentRegistrationOptions) -> Self {
- Self::Options(from)
- }
-}
-
-impl From<bool> for ImplementationProviderCapability {
- fn from(from: bool) -> Self {
- Self::Simple(from)
- }
-}
-
-#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
-#[serde(untagged)]
-pub enum TypeDefinitionProviderCapability {
- Simple(bool),
- Options(StaticTextDocumentRegistrationOptions),
-}
-
-impl From<StaticTextDocumentRegistrationOptions> for TypeDefinitionProviderCapability {
- fn from(from: StaticTextDocumentRegistrationOptions) -> Self {
- Self::Options(from)
- }
-}
-
-impl From<bool> for TypeDefinitionProviderCapability {
- fn from(from: bool) -> Self {
- Self::Simple(from)
- }
-}
-
-#[derive(Debug, PartialEq, Clone, Default, Deserialize, Serialize)]
-#[serde(rename_all = "camelCase")]
-pub struct ServerCapabilities {
- /// The position encoding the server picked from the encodings offered
- /// by the client via the client capability `general.positionEncodings`.
- ///
- /// If the client didn't provide any position encodings the only valid
- /// value that a server can return is 'utf-16'.
- ///
- /// If omitted it defaults to 'utf-16'.
- ///
- /// @since 3.17.0
- #[serde(skip_serializing_if = "Option::is_none")]
- #[cfg(feature = "proposed")]
- pub position_encoding: Option<PositionEncodingKind>,
-
- /// Defines how text documents are synced.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub text_document_sync: Option<TextDocumentSyncCapability>,
-
- /// Capabilities specific to `textDocument/selectionRange` requests.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub selection_range_provider: Option<SelectionRangeProviderCapability>,
-
- /// The server provides hover support.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub hover_provider: Option<HoverProviderCapability>,
-
- /// The server provides completion support.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub completion_provider: Option<CompletionOptions>,
-
- /// The server provides signature help support.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub signature_help_provider: Option<SignatureHelpOptions>,
-
- /// The server provides goto definition support.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub definition_provider: Option<OneOf<bool, DefinitionOptions>>,
-
- /// The server provides goto type definition support.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub type_definition_provider: Option<TypeDefinitionProviderCapability>,
-
- /// The server provides goto implementation support.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub implementation_provider: Option<ImplementationProviderCapability>,
-
- /// The server provides find references support.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub references_provider: Option<OneOf<bool, ReferencesOptions>>,
-
- /// The server provides document highlight support.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub document_highlight_provider: Option<OneOf<bool, DocumentHighlightOptions>>,
-
- /// The server provides document symbol support.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub document_symbol_provider: Option<OneOf<bool, DocumentSymbolOptions>>,
-
- /// The server provides workspace symbol support.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub workspace_symbol_provider: Option<OneOf<bool, WorkspaceSymbolOptions>>,
-
- /// The server provides code actions.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub code_action_provider: Option<CodeActionProviderCapability>,
-
- /// The server provides code lens.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub code_lens_provider: Option<CodeLensOptions>,
-
- /// The server provides document formatting.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub document_formatting_provider: Option<OneOf<bool, DocumentFormattingOptions>>,
-
- /// The server provides document range formatting.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub document_range_formatting_provider: Option<OneOf<bool, DocumentRangeFormattingOptions>>,
-
- /// The server provides document formatting on typing.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub document_on_type_formatting_provider: Option<DocumentOnTypeFormattingOptions>,
-
- /// The server provides rename support.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub rename_provider: Option<OneOf<bool, RenameOptions>>,
-
- /// The server provides document link support.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub document_link_provider: Option<DocumentLinkOptions>,
-
- /// The server provides color provider support.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub color_provider: Option<ColorProviderCapability>,
-
- /// The server provides folding provider support.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub folding_range_provider: Option<FoldingRangeProviderCapability>,
-
- /// The server provides go to declaration support.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub declaration_provider: Option<DeclarationCapability>,
-
- /// The server provides execute command support.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub execute_command_provider: Option<ExecuteCommandOptions>,
-
- /// Workspace specific server capabilities
- #[serde(skip_serializing_if = "Option::is_none")]
- pub workspace: Option<WorkspaceServerCapabilities>,
-
- /// Call hierarchy provider capabilities.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub call_hierarchy_provider: Option<CallHierarchyServerCapability>,
-
- /// Semantic tokens server capabilities.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub semantic_tokens_provider: Option<SemanticTokensServerCapabilities>,
-
- /// Whether server provides moniker support.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub moniker_provider: Option<OneOf<bool, MonikerServerCapabilities>>,
-
- /// The server provides inlay hints.
- ///
- /// @since 3.17.0 - proposed state
- #[serde(skip_serializing_if = "Option::is_none")]
- #[cfg(feature = "proposed")]
- pub inlay_hint_provider: Option<OneOf<bool, InlayHintServerCapabilities>>,
-
- /// The server provides linked editing range support.
- ///
- /// @since 3.16.0
- #[serde(skip_serializing_if = "Option::is_none")]
- pub linked_editing_range_provider: Option<LinkedEditingRangeServerCapabilities>,
-
- /// Experimental server capabilities.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub experimental: Option<Value>,
-}
-
-#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
-#[serde(rename_all = "camelCase")]
-pub struct WorkspaceServerCapabilities {
- /// The server supports workspace folder.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub workspace_folders: Option<WorkspaceFoldersServerCapabilities>,
-
- #[serde(skip_serializing_if = "Option::is_none")]
- pub file_operations: Option<WorkspaceFileOperationsServerCapabilities>,
-}
-
-/// General parameters to to register for a capability.
-#[derive(Debug, PartialEq, Clone, Deserialize, Serialize)]
-#[serde(rename_all = "camelCase")]
-pub struct Registration {
- /// The id used to register the request. The id can be used to deregister
- /// the request again.
- pub id: String,
-
- /// The method / capability to register for.
- pub method: String,
-
- /// Options necessary for the registration.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub register_options: Option<Value>,
-}
-
-#[derive(Debug, PartialEq, Clone, Deserialize, Serialize)]
-pub struct RegistrationParams {
- pub registrations: Vec<Registration>,
-}
-
-/// Since most of the registration options require to specify a document selector there is a base
-/// interface that can be used.
-#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
-#[serde(rename_all = "camelCase")]
-pub struct TextDocumentRegistrationOptions {
- /// A document selector to identify the scope of the registration. If set to null
- /// the document selector provided on the client side will be used.
- pub document_selector: Option<DocumentSelector>,
-}
-
-#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
-#[serde(untagged)]
-pub enum DeclarationCapability {
- Simple(bool),
- RegistrationOptions(DeclarationRegistrationOptions),
- Options(DeclarationOptions),
-}
-
-#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
-#[serde(rename_all = "camelCase")]
-pub struct DeclarationRegistrationOptions {
- #[serde(flatten)]
- pub declaration_options: DeclarationOptions,
-
- #[serde(flatten)]
- pub text_document_registration_options: TextDocumentRegistrationOptions,
-
- #[serde(flatten)]
- pub static_registration_options: StaticRegistrationOptions,
-}
-
-#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
-#[serde(rename_all = "camelCase")]
-pub struct DeclarationOptions {
- #[serde(flatten)]
- pub work_done_progress_options: WorkDoneProgressOptions,
-}
-
-#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
-#[serde(rename_all = "camelCase")]
-pub struct StaticRegistrationOptions {
- #[serde(skip_serializing_if = "Option::is_none")]
- pub id: Option<String>,
-}
-
-#[derive(Debug, Default, Eq, PartialEq, Clone, Deserialize, Serialize)]
-#[serde(rename_all = "camelCase")]
-pub struct WorkDoneProgressOptions {
- #[serde(skip_serializing_if = "Option::is_none")]
- pub work_done_progress: Option<bool>,
-}
-
-#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
-#[serde(rename_all = "camelCase")]
-pub struct DocumentFormattingOptions {
- #[serde(flatten)]
- pub work_done_progress_options: WorkDoneProgressOptions,
-}
-
-#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
-#[serde(rename_all = "camelCase")]
-pub struct DocumentRangeFormattingOptions {
- #[serde(flatten)]
- pub work_done_progress_options: WorkDoneProgressOptions,
-}
-
-#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
-#[serde(rename_all = "camelCase")]
-pub struct DefinitionOptions {
- #[serde(flatten)]
- pub work_done_progress_options: WorkDoneProgressOptions,
-}
-
-#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
-#[serde(rename_all = "camelCase")]
-pub struct DocumentSymbolOptions {
- /// A human-readable string that is shown when multiple outlines trees are
- /// shown for the same document.
- ///
- /// @since 3.16.0
- #[serde(skip_serializing_if = "Option::is_none")]
- pub label: Option<String>,
-
- #[serde(flatten)]
- pub work_done_progress_options: WorkDoneProgressOptions,
-}
-
-#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
-#[serde(rename_all = "camelCase")]
-pub struct ReferencesOptions {
- #[serde(flatten)]
- pub work_done_progress_options: WorkDoneProgressOptions,
-}
-
-#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
-#[serde(rename_all = "camelCase")]
-pub struct DocumentHighlightOptions {
- #[serde(flatten)]
- pub work_done_progress_options: WorkDoneProgressOptions,
-}
-
-#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
-#[serde(rename_all = "camelCase")]
-pub struct WorkspaceSymbolOptions {
- #[serde(flatten)]
- pub work_done_progress_options: WorkDoneProgressOptions,
-}
-
-#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
-#[serde(rename_all = "camelCase")]
-pub struct StaticTextDocumentRegistrationOptions {
- /// A document selector to identify the scope of the registration. If set to null
- /// the document selector provided on the client side will be used.
- pub document_selector: Option<DocumentSelector>,
-
- #[serde(skip_serializing_if = "Option::is_none")]
- pub id: Option<String>,
-}
-
-/// General parameters to unregister a capability.
-#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
-pub struct Unregistration {
- /// The id used to unregister the request or notification. Usually an id
- /// provided during the register request.
- pub id: String,
-
- /// The method / capability to unregister for.
- pub method: String,
-}
-
-#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
-pub struct UnregistrationParams {
- pub unregisterations: Vec<Unregistration>,
-}
-
-#[derive(Debug, PartialEq, Clone, Deserialize, Serialize)]
-pub struct DidChangeConfigurationParams {
- /// The actual changed settings
- pub settings: Value,
-}
-
-#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
-#[serde(rename_all = "camelCase")]
-pub struct DidOpenTextDocumentParams {
- /// The document that was opened.
- pub text_document: TextDocumentItem,
-}
-
-#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
-#[serde(rename_all = "camelCase")]
-pub struct DidChangeTextDocumentParams {
- /// The document that did change. The version number points
- /// to the version after all provided content changes have
- /// been applied.
- pub text_document: VersionedTextDocumentIdentifier,
- /// The actual content changes.
- pub content_changes: Vec<TextDocumentContentChangeEvent>,
-}
-
-/// An event describing a change to a text document. If range and rangeLength are omitted
-/// the new text is considered to be the full content of the document.
-#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
-#[serde(rename_all = "camelCase")]
-pub struct TextDocumentContentChangeEvent {
- /// The range of the document that changed.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub range: Option<Range>,
-
- /// The length of the range that got replaced.
- ///
- /// Deprecated: Use range instead
- #[serde(skip_serializing_if = "Option::is_none")]
- pub range_length: Option<u32>,
-
- /// The new text of the document.
- pub text: String,
-}
-
-/// Descibe options to be used when registered for text document change events.
-///
-/// Extends TextDocumentRegistrationOptions
-#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
-#[serde(rename_all = "camelCase")]
-pub struct TextDocumentChangeRegistrationOptions {
- /// A document selector to identify the scope of the registration. If set to null
- /// the document selector provided on the client side will be used.
- pub document_selector: Option<DocumentSelector>,
-
- /// How documents are synced to the server. See TextDocumentSyncKind.Full
- /// and TextDocumentSyncKindIncremental.
- pub sync_kind: i32,
-}
-
-/// The parameters send in a will save text document notification.
-#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
-#[serde(rename_all = "camelCase")]
-pub struct WillSaveTextDocumentParams {
- /// The document that will be saved.
- pub text_document: TextDocumentIdentifier,
-
- /// The 'TextDocumentSaveReason'.
- pub reason: TextDocumentSaveReason,
-}
-
-/// Represents reasons why a text document is saved.
-#[derive(Copy, Eq, PartialEq, Clone, Deserialize, Serialize)]
-#[serde(transparent)]
-pub struct TextDocumentSaveReason(i32);
-lsp_enum! {
-impl TextDocumentSaveReason {
- /// Manually triggered, e.g. by the user pressing save, by starting debugging,
- /// or by an API call.
- pub const MANUAL: TextDocumentSaveReason = TextDocumentSaveReason(1);
-
- /// Automatic after a delay.
- pub const AFTER_DELAY: TextDocumentSaveReason = TextDocumentSaveReason(2);
-
- /// When the editor lost focus.
- pub const FOCUS_OUT: TextDocumentSaveReason = TextDocumentSaveReason(3);
-}
-}
-
-#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
-#[serde(rename_all = "camelCase")]
-pub struct DidCloseTextDocumentParams {
- /// The document that was closed.
- pub text_document: TextDocumentIdentifier,
-}
-
-#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
-#[serde(rename_all = "camelCase")]
-pub struct DidSaveTextDocumentParams {
- /// The document that was saved.
- pub text_document: TextDocumentIdentifier,
-
- /// Optional the content when saved. Depends on the includeText value
- /// when the save notification was requested.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub text: Option<String>,
-}
-
-#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
-#[serde(rename_all = "camelCase")]
-pub struct TextDocumentSaveRegistrationOptions {
- /// The client is supposed to include the content on save.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub include_text: Option<bool>,
-
- #[serde(flatten)]
- pub text_document_registration_options: TextDocumentRegistrationOptions,
-}
-
-pub type DidChangeWatchedFilesClientCapabilities = DynamicRegistrationClientCapabilities;
-
-#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
-pub struct DidChangeWatchedFilesParams {
- /// The actual file events.
- pub changes: Vec<FileEvent>,
-}
-
-/// The file event type.
-#[derive(Eq, PartialEq, Copy, Clone, Deserialize, Serialize)]
-#[serde(transparent)]
-pub struct FileChangeType(i32);
-lsp_enum! {
-impl FileChangeType {
- /// The file got created.
- pub const CREATED: FileChangeType = FileChangeType(1);
-
- /// The file got changed.
- pub const CHANGED: FileChangeType = FileChangeType(2);
-
- /// The file got deleted.
- pub const DELETED: FileChangeType = FileChangeType(3);
-}
-}
-
-/// An event describing a file change.
-#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
-pub struct FileEvent {
- /// The file's URI.
- pub uri: Url,
-
- /// The change type.
- #[serde(rename = "type")]
- pub typ: FileChangeType,
-}
-
-impl FileEvent {
- pub fn new(uri: Url, typ: FileChangeType) -> FileEvent {
- FileEvent { uri, typ }
- }
-}
-
-/// Describe options to be used when registered for text document change events.
-#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Deserialize, Serialize)]
-pub struct DidChangeWatchedFilesRegistrationOptions {
- /// The watchers to register.
- pub watchers: Vec<FileSystemWatcher>,
-}
-
-#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Deserialize, Serialize)]
-#[serde(rename_all = "camelCase")]
-pub struct FileSystemWatcher {
- /// The glob pattern to watch
- pub glob_pattern: String,
-
- /// The kind of events of interest. If omitted it defaults to WatchKind.Create |
- /// WatchKind.Change | WatchKind.Delete which is 7.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub kind: Option<WatchKind>,
-}
-
-bitflags! {
-pub struct WatchKind: u8 {
- /// Interested in create events.
- const Create = 1;
- /// Interested in change events
- const Change = 2;
- /// Interested in delete events
- const Delete = 4;
-}
-}
-
-impl<'de> serde::Deserialize<'de> for WatchKind {
- fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
- where
- D: serde::Deserializer<'de>,
- {
- let i = u8::deserialize(deserializer)?;
- WatchKind::from_bits(i).ok_or_else(|| {
- D::Error::invalid_value(de::Unexpected::Unsigned(u64::from(i)), &"Unknown flag")
- })
- }
-}
-
-impl serde::Serialize for WatchKind {
- fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
- where
- S: serde::Serializer,
- {
- serializer.serialize_u8(self.bits())
- }
-}
-
-#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
-pub struct PublishDiagnosticsParams {
- /// The URI for which diagnostic information is reported.
- pub uri: Url,
-
- /// An array of diagnostic information items.
- pub diagnostics: Vec<Diagnostic>,
-
- /// Optional the version number of the document the diagnostics are published for.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub version: Option<i32>,
-}
-
-impl PublishDiagnosticsParams {
- pub fn new(
- uri: Url,
- diagnostics: Vec<Diagnostic>,
- version: Option<i32>,
- ) -> PublishDiagnosticsParams {
- PublishDiagnosticsParams {
- uri,
- diagnostics,
- version,
- }
- }
-}
-
-#[derive(Debug, Eq, PartialEq, Deserialize, Serialize, Clone)]
-#[serde(untagged)]
-pub enum Documentation {
- String(String),
- MarkupContent(MarkupContent),
-}
-
-/// The marked string is rendered:
-/// - as markdown if it is represented as a string
-/// - as code block of the given langauge if it is represented as a pair of a language and a value
-///
-/// The pair of a language and a value is an equivalent to markdown:
-/// ```${language}
-/// ${value}
-/// ```
-#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
-#[serde(untagged)]
-pub enum MarkedString {
- String(String),
- LanguageString(LanguageString),
-}
-
-#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
-pub struct LanguageString {
- pub language: String,
- pub value: String,
-}
-
-impl MarkedString {
- pub fn from_markdown(markdown: String) -> MarkedString {
- MarkedString::String(markdown)
- }
-
- pub fn from_language_code(language: String, code_block: String) -> MarkedString {
- MarkedString::LanguageString(LanguageString {
- language,
- value: code_block,
- })
- }
-}
-
-#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
-#[serde(rename_all = "camelCase")]
-pub struct GotoDefinitionParams {
- #[serde(flatten)]
- pub text_document_position_params: TextDocumentPositionParams,
-
- #[serde(flatten)]
- pub work_done_progress_params: WorkDoneProgressParams,
-
- #[serde(flatten)]
- pub partial_result_params: PartialResultParams,
-}
-
-/// GotoDefinition response can be single location, or multiple Locations or a link.
-#[derive(Debug, PartialEq, Serialize, Deserialize, Clone)]
-#[serde(untagged)]
-pub enum GotoDefinitionResponse {
- Scalar(Location),
- Array(Vec<Location>),
- Link(Vec<LocationLink>),
-}
-
-impl From<Location> for GotoDefinitionResponse {
- fn from(location: Location) -> Self {
- GotoDefinitionResponse::Scalar(location)
- }
-}
-
-impl From<Vec<Location>> for GotoDefinitionResponse {
- fn from(locations: Vec<Location>) -> Self {
- GotoDefinitionResponse::Array(locations)
- }
-}
-
-impl From<Vec<LocationLink>> for GotoDefinitionResponse {
- fn from(locations: Vec<LocationLink>) -> Self {
- GotoDefinitionResponse::Link(locations)
- }
-}
-
-#[derive(Debug, PartialEq, Clone, Default, Deserialize, Serialize)]
-pub struct ExecuteCommandParams {
- /// The identifier of the actual command handler.
- pub command: String,
- /// Arguments that the command should be invoked with.
- #[serde(default)]
- pub arguments: Vec<Value>,
-
- #[serde(flatten)]
- pub work_done_progress_params: WorkDoneProgressParams,
-}
-
-/// Execute command registration options.
-#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
-pub struct ExecuteCommandRegistrationOptions {
- /// The commands to be executed on the server
- pub commands: Vec<String>,
-
- #[serde(flatten)]
- pub execute_command_options: ExecuteCommandOptions,
-}
-
-#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
-#[serde(rename_all = "camelCase")]
-pub struct ApplyWorkspaceEditParams {
- /// An optional label of the workspace edit. This label is
- /// presented in the user interface for example on an undo
- /// stack to undo the workspace edit.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub label: Option<String>,
-
- /// The edits to apply.
- pub edit: WorkspaceEdit,
-}
-
-#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
-#[serde(rename_all = "camelCase")]
-pub struct ApplyWorkspaceEditResponse {
- /// Indicates whether the edit was applied or not.
- pub applied: bool,
-
- /// An optional textual description for why the edit was not applied.
- /// This may be used may be used by the server for diagnostic
- /// logging or to provide a suitable error for a request that
- /// triggered the edit
- #[serde(skip_serializing_if = "Option::is_none")]
- pub failure_reason: Option<String>,
-
- /// Depending on the client's failure handling strategy `failedChange` might
- /// contain the index of the change that failed. This property is only available
- /// if the client signals a `failureHandlingStrategy` in its client capabilities.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub failed_change: Option<u32>,
-}
-
-/// Describes the content type that a client supports in various
-/// result literals like `Hover`, `ParameterInfo` or `CompletionItem`.
-///
-/// Please note that `MarkupKinds` must not start with a `$`. This kinds
-/// are reserved for internal usage.
-#[derive(Debug, Eq, PartialEq, Deserialize, Serialize, Clone)]
-#[serde(rename_all = "lowercase")]
-pub enum MarkupKind {
- /// Plain text is supported as a content format
- PlainText,
- /// Markdown is supported as a content format
- Markdown,
-}
-
-/// A `MarkupContent` literal represents a string value which content can be represented in different formats.
-/// Currently `plaintext` and `markdown` are supported formats. A `MarkupContent` is usually used in
-/// documentation properties of result literals like `CompletionItem` or `SignatureInformation`.
-/// If the format is `markdown` the content should follow the [GitHub Flavored Markdown Specification](https://github.github.com/gfm/).
-///
-/// Here is an example how such a string can be constructed using JavaScript / TypeScript:
-/// ```ignore
-/// let markdown: MarkupContent = {
-/// kind: MarkupKind::Markdown,
-/// value: [
-/// "# Header",
-/// "Some text",
-/// "```typescript",
-/// "someCode();",
-/// "```"
-/// ]
-/// .join("\n"),
-/// };
-/// ```
-///
-/// Please Note* that clients might sanitize the return markdown. A client could decide to
-/// remove HTML from the markdown to avoid script execution.
-#[derive(Debug, Eq, PartialEq, Deserialize, Serialize, Clone)]
-pub struct MarkupContent {
- pub kind: MarkupKind,
- pub value: String,
-}
-
-/// A parameter literal used to pass a partial result token.
-#[derive(Debug, Eq, PartialEq, Default, Deserialize, Serialize, Clone)]
-#[serde(rename_all = "camelCase")]
-pub struct PartialResultParams {
- #[serde(skip_serializing_if = "Option::is_none")]
- pub partial_result_token: Option<ProgressToken>,
-}
-
-/// Symbol tags are extra annotations that tweak the rendering of a symbol.
-/// Since 3.15
-#[derive(Eq, PartialEq, Clone, Deserialize, Serialize)]
-#[serde(transparent)]
-pub struct SymbolTag(i32);
-lsp_enum! {
-impl SymbolTag {
- /// Render a symbol as obsolete, usually using a strike-out.
- pub const DEPRECATED: SymbolTag = SymbolTag(1);
-}
-}
-
-#[cfg(test)]
-mod tests {
- use serde::{Deserialize, Serialize};
-
- use super::*;
-
- pub(crate) fn test_serialization<SER>(ms: &SER, expected: &str)
- where
- SER: Serialize + for<'de> Deserialize<'de> + PartialEq + std::fmt::Debug,
- {
- let json_str = serde_json::to_string(ms).unwrap();
- assert_eq!(&json_str, expected);
- let deserialized: SER = serde_json::from_str(&json_str).unwrap();
- assert_eq!(&deserialized, ms);
- }
-
- pub(crate) fn test_deserialization<T>(json: &str, expected: &T)
- where
- T: for<'de> Deserialize<'de> + PartialEq + std::fmt::Debug,
- {
- let value = serde_json::from_str::<T>(json).unwrap();
- assert_eq!(&value, expected);
- }
-
- #[test]
- fn one_of() {
- test_serialization(&OneOf::<bool, ()>::Left(true), r#"true"#);
- test_serialization(&OneOf::<String, ()>::Left("abcd".into()), r#""abcd""#);
- test_serialization(
- &OneOf::<String, WorkDoneProgressOptions>::Right(WorkDoneProgressOptions {
- work_done_progress: Some(false),
- }),
- r#"{"workDoneProgress":false}"#,
- );
- }
-
- #[test]
- fn number_or_string() {
- test_serialization(&NumberOrString::Number(123), r#"123"#);
-
- test_serialization(&NumberOrString::String("abcd".into()), r#""abcd""#);
- }
-
- #[test]
- fn marked_string() {
- test_serialization(&MarkedString::from_markdown("xxx".into()), r#""xxx""#);
-
- test_serialization(
- &MarkedString::from_language_code("lang".into(), "code".into()),
- r#"{"language":"lang","value":"code"}"#,
- );
- }
-
- #[test]
- fn language_string() {
- test_serialization(
- &LanguageString {
- language: "LL".into(),
- value: "VV".into(),
- },
- r#"{"language":"LL","value":"VV"}"#,
- );
- }
-
- #[test]
- fn workspace_edit() {
- test_serialization(
- &WorkspaceEdit {
- changes: Some(vec![].into_iter().collect()),
- document_changes: None,
- ..Default::default()
- },
- r#"{"changes":{}}"#,
- );
-
- test_serialization(
- &WorkspaceEdit {
- changes: None,
- document_changes: None,
- ..Default::default()
- },
- r#"{}"#,
- );
-
- test_serialization(
- &WorkspaceEdit {
- changes: Some(
- vec![(Url::parse("file://test").unwrap(), vec![])]
- .into_iter()
- .collect(),
- ),
- document_changes: None,
- ..Default::default()
- },
- r#"{"changes":{"file://test/":[]}}"#,
- );
- }
-
- #[test]
- fn root_uri_can_be_missing() {
- serde_json::from_str::<InitializeParams>(r#"{ "capabilities": {} }"#).unwrap();
- }
-
- #[test]
- fn test_watch_kind() {
- test_serialization(&WatchKind::Create, "1");
- test_serialization(&(WatchKind::Create | WatchKind::Change), "3");
- test_serialization(
- &(WatchKind::Create | WatchKind::Change | WatchKind::Delete),
- "7",
- );
- }
-
- #[test]
- fn test_resource_operation_kind() {
- test_serialization(
- &vec![
- ResourceOperationKind::Create,
- ResourceOperationKind::Rename,
- ResourceOperationKind::Delete,
- ],
- r#"["create","rename","delete"]"#,
- );
- }
-}
+/*!
+
+Language Server Protocol types for Rust.
+
+Based on: <https://microsoft.github.io/language-server-protocol/specification>
+
+This library uses the URL crate for parsing URIs. Note that there is
+some confusion on the meaning of URLs vs URIs:
+<http://stackoverflow.com/a/28865728/393898>. According to that
+information, on the classical sense of "URLs", "URLs" are a subset of
+URIs, But on the modern/new meaning of URLs, they are the same as
+URIs. The important take-away aspect is that the URL crate should be
+able to parse any URI, such as `urn:isbn:0451450523`.
+
+
+*/
+#![allow(non_upper_case_globals)]
+#[forbid(unsafe_code)]
+#[macro_use]
+extern crate bitflags;
+
+use std::{collections::HashMap, fmt::Debug};
+
+use serde::{de, de::Error as Error_, Deserialize, Serialize};
+use serde_json::Value;
+pub use url::Url;
+
+// Large enough to contain any enumeration name defined in this crate
+type PascalCaseBuf = [u8; 32];
+const fn fmt_pascal_case_const(name: &str) -> (PascalCaseBuf, usize) {
+ let mut buf = [0; 32];
+ let mut buf_i = 0;
+ let mut name_i = 0;
+ let name = name.as_bytes();
+ while name_i < name.len() {
+ let first = name[name_i];
+ name_i += 1;
+
+ buf[buf_i] = first;
+ buf_i += 1;
+
+ while name_i < name.len() {
+ let rest = name[name_i];
+ name_i += 1;
+ if rest == b'_' {
+ break;
+ }
+
+ buf[buf_i] = rest.to_ascii_lowercase();
+ buf_i += 1;
+ }
+ }
+ (buf, buf_i)
+}
+
+fn fmt_pascal_case(f: &mut std::fmt::Formatter<'_>, name: &str) -> std::fmt::Result {
+ for word in name.split('_') {
+ let mut chars = word.chars();
+ let first = chars.next().unwrap();
+ write!(f, "{}", first)?;
+ for rest in chars {
+ write!(f, "{}", rest.to_lowercase())?;
+ }
+ }
+ Ok(())
+}
+
+macro_rules! lsp_enum {
+ (impl $typ: ident { $( $(#[$attr:meta])* pub const $name: ident : $enum_type: ty = $value: expr; )* }) => {
+ impl $typ {
+ $(
+ $(#[$attr])*
+ pub const $name: $enum_type = $value;
+ )*
+ }
+
+ impl std::fmt::Debug for $typ {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ match *self {
+ $(
+ Self::$name => crate::fmt_pascal_case(f, stringify!($name)),
+ )*
+ _ => write!(f, "{}({})", stringify!($typ), self.0),
+ }
+ }
+ }
+
+ impl std::convert::TryFrom<&str> for $typ {
+ type Error = &'static str;
+ fn try_from(value: &str) -> Result<Self, Self::Error> {
+ match () {
+ $(
+ _ if {
+ const X: (crate::PascalCaseBuf, usize) = crate::fmt_pascal_case_const(stringify!($name));
+ let (buf, len) = X;
+ &buf[..len] == value.as_bytes()
+ } => Ok(Self::$name),
+ )*
+ _ => Err("unknown enum variant"),
+ }
+ }
+ }
+
+ }
+}
+
+pub mod error_codes;
+pub mod notification;
+pub mod request;
+
+mod call_hierarchy;
+pub use call_hierarchy::*;
+
+mod code_action;
+pub use code_action::*;
+
+mod code_lens;
+pub use code_lens::*;
+
+mod color;
+pub use color::*;
+
+mod completion;
+pub use completion::*;
+
+mod document_highlight;
+pub use document_highlight::*;
+
+mod document_link;
+pub use document_link::*;
+
+mod document_symbols;
+pub use document_symbols::*;
+
+mod file_operations;
+pub use file_operations::*;
+
+mod folding_range;
+pub use folding_range::*;
+
+mod formatting;
+pub use formatting::*;
+
+mod hover;
+pub use hover::*;
+
+mod inlay_hint;
+pub use inlay_hint::*;
+
+mod inline_value;
+pub use inline_value::*;
+
+mod moniker;
+pub use moniker::*;
+
+mod progress;
+pub use progress::*;
+
+mod references;
+pub use references::*;
+
+mod rename;
+pub use rename::*;
+
+pub mod selection_range;
+pub use selection_range::*;
+
+mod semantic_tokens;
+pub use semantic_tokens::*;
+
+mod signature_help;
+pub use signature_help::*;
+
+mod type_hierarchy;
+pub use type_hierarchy::*;
+
+mod linked_editing;
+pub use linked_editing::*;
+
+mod window;
+pub use window::*;
+
+mod workspace_folders;
+pub use workspace_folders::*;
+
+mod workspace_symbols;
+pub use workspace_symbols::*;
+
+pub mod lsif;
+
+mod trace;
+pub use trace::*;
+
+/* ----------------- Auxiliary types ----------------- */
+
+#[derive(Debug, Eq, Hash, PartialEq, Clone, Deserialize, Serialize)]
+#[serde(untagged)]
+pub enum NumberOrString {
+ Number(i32),
+ String(String),
+}
+
+/* ----------------- Cancel support ----------------- */
+
+#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
+pub struct CancelParams {
+ /// The request id to cancel.
+ pub id: NumberOrString,
+}
+
+/* ----------------- Basic JSON Structures ----------------- */
+
+/// The LSP any type
+///
+/// @since 3.17.0
+pub type LSPAny = serde_json::Value;
+
+/// LSP object definition.
+///
+/// @since 3.17.0
+pub type LSPObject = serde_json::Map<String, serde_json::Value>;
+
+/// LSP arrays.
+///
+/// @since 3.17.0
+pub type LSPArray = Vec<serde_json::Value>;
+
+/// Position in a text document expressed as zero-based line and character offset.
+/// A position is between two characters like an 'insert' cursor in a editor.
+#[derive(Debug, Eq, PartialEq, Ord, PartialOrd, Copy, Clone, Default, Deserialize, Serialize)]
+pub struct Position {
+ /// Line position in a document (zero-based).
+ pub line: u32,
+ /// Character offset on a line in a document (zero-based). The meaning of this
+ /// offset is determined by the negotiated `PositionEncodingKind`.
+ ///
+ /// If the character value is greater than the line length it defaults back
+ /// to the line length.
+ pub character: u32,
+}
+
+impl Position {
+ pub fn new(line: u32, character: u32) -> Position {
+ Position { line, character }
+ }
+}
+
+/// A range in a text document expressed as (zero-based) start and end positions.
+/// A range is comparable to a selection in an editor. Therefore the end position is exclusive.
+#[derive(Debug, Eq, PartialEq, Copy, Clone, Default, Deserialize, Serialize)]
+pub struct Range {
+ /// The range's start position.
+ pub start: Position,
+ /// The range's end position.
+ pub end: Position,
+}
+
+impl Range {
+ pub fn new(start: Position, end: Position) -> Range {
+ Range { start, end }
+ }
+}
+
+/// Represents a location inside a resource, such as a line inside a text file.
+#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
+pub struct Location {
+ pub uri: Url,
+ pub range: Range,
+}
+
+impl Location {
+ pub fn new(uri: Url, range: Range) -> Location {
+ Location { uri, range }
+ }
+}
+
+/// Represents a link between a source and a target location.
+#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct LocationLink {
+ /// Span of the origin of this link.
+ ///
+ /// Used as the underlined span for mouse interaction. Defaults to the word range at
+ /// the mouse position.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub origin_selection_range: Option<Range>,
+
+ /// The target resource identifier of this link.
+ pub target_uri: Url,
+
+ /// The full target range of this link.
+ pub target_range: Range,
+
+ /// The span of this link.
+ pub target_selection_range: Range,
+}
+
+/// A type indicating how positions are encoded,
+/// specifically what column offsets mean.
+///
+/// @since 3.17.0
+#[derive(Debug, Eq, PartialEq, Hash, PartialOrd, Clone, Deserialize, Serialize)]
+pub struct PositionEncodingKind(std::borrow::Cow<'static, str>);
+
+impl PositionEncodingKind {
+ /// Character offsets count UTF-8 code units.
+ pub const UTF8: PositionEncodingKind = PositionEncodingKind::new("utf-8");
+
+ /// Character offsets count UTF-16 code units.
+ ///
+ /// This is the default and must always be supported
+ /// by servers
+ pub const UTF16: PositionEncodingKind = PositionEncodingKind::new("utf-16");
+
+ /// Character offsets count UTF-32 code units.
+ ///
+ /// Implementation note: these are the same as Unicode code points,
+ /// so this `PositionEncodingKind` may also be used for an
+ /// encoding-agnostic representation of character offsets.
+ pub const UTF32: PositionEncodingKind = PositionEncodingKind::new("utf-32");
+
+ pub const fn new(tag: &'static str) -> Self {
+ PositionEncodingKind(std::borrow::Cow::Borrowed(tag))
+ }
+
+ pub fn as_str(&self) -> &str {
+ &self.0
+ }
+}
+
+impl From<String> for PositionEncodingKind {
+ fn from(from: String) -> Self {
+ PositionEncodingKind(std::borrow::Cow::from(from))
+ }
+}
+
+impl From<&'static str> for PositionEncodingKind {
+ fn from(from: &'static str) -> Self {
+ PositionEncodingKind::new(from)
+ }
+}
+
+/// Represents a diagnostic, such as a compiler error or warning.
+/// Diagnostic objects are only valid in the scope of a resource.
+#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct Diagnostic {
+ /// The range at which the message applies.
+ pub range: Range,
+
+ /// The diagnostic's severity. Can be omitted. If omitted it is up to the
+ /// client to interpret diagnostics as error, warning, info or hint.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub severity: Option<DiagnosticSeverity>,
+
+ /// The diagnostic's code. Can be omitted.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub code: Option<NumberOrString>,
+
+ /// An optional property to describe the error code.
+ ///
+ /// since 3.16.0
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub code_description: Option<CodeDescription>,
+
+ /// A human-readable string describing the source of this
+ /// diagnostic, e.g. 'typescript' or 'super lint'.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub source: Option<String>,
+
+ /// The diagnostic's message.
+ pub message: String,
+
+ /// An array of related diagnostic information, e.g. when symbol-names within
+ /// a scope collide all definitions can be marked via this property.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub related_information: Option<Vec<DiagnosticRelatedInformation>>,
+
+ /// Additional metadata about the diagnostic.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub tags: Option<Vec<DiagnosticTag>>,
+
+ /// A data entry field that is preserved between a `textDocument/publishDiagnostics`
+ /// notification and `textDocument/codeAction` request.
+ ///
+ /// since 3.16.0
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub data: Option<serde_json::Value>,
+}
+
+#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct CodeDescription {
+ pub href: Url,
+}
+
+impl Diagnostic {
+ pub fn new(
+ range: Range,
+ severity: Option<DiagnosticSeverity>,
+ code: Option<NumberOrString>,
+ source: Option<String>,
+ message: String,
+ related_information: Option<Vec<DiagnosticRelatedInformation>>,
+ tags: Option<Vec<DiagnosticTag>>,
+ ) -> Diagnostic {
+ Diagnostic {
+ range,
+ severity,
+ code,
+ source,
+ message,
+ related_information,
+ tags,
+ ..Diagnostic::default()
+ }
+ }
+
+ pub fn new_simple(range: Range, message: String) -> Diagnostic {
+ Self::new(range, None, None, None, message, None, None)
+ }
+
+ pub fn new_with_code_number(
+ range: Range,
+ severity: DiagnosticSeverity,
+ code_number: i32,
+ source: Option<String>,
+ message: String,
+ ) -> Diagnostic {
+ let code = Some(NumberOrString::Number(code_number));
+ Self::new(range, Some(severity), code, source, message, None, None)
+ }
+}
+
+/// The protocol currently supports the following diagnostic severities:
+#[derive(Eq, PartialEq, Ord, PartialOrd, Clone, Copy, Deserialize, Serialize)]
+#[serde(transparent)]
+pub struct DiagnosticSeverity(i32);
+lsp_enum! {
+impl DiagnosticSeverity {
+ /// Reports an error.
+ pub const ERROR: DiagnosticSeverity = DiagnosticSeverity(1);
+ /// Reports a warning.
+ pub const WARNING: DiagnosticSeverity = DiagnosticSeverity(2);
+ /// Reports an information.
+ pub const INFORMATION: DiagnosticSeverity = DiagnosticSeverity(3);
+ /// Reports a hint.
+ pub const HINT: DiagnosticSeverity = DiagnosticSeverity(4);
+}
+}
+
+/// Represents a related message and source code location for a diagnostic. This
+/// should be used to point to code locations that cause or related to a
+/// diagnostics, e.g when duplicating a symbol in a scope.
+#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
+pub struct DiagnosticRelatedInformation {
+ /// The location of this related diagnostic information.
+ pub location: Location,
+
+ /// The message of this related diagnostic information.
+ pub message: String,
+}
+
+/// The diagnostic tags.
+#[derive(Eq, PartialEq, Clone, Deserialize, Serialize)]
+#[serde(transparent)]
+pub struct DiagnosticTag(i32);
+lsp_enum! {
+impl DiagnosticTag {
+ /// Unused or unnecessary code.
+ /// Clients are allowed to render diagnostics with this tag faded out instead of having
+ /// an error squiggle.
+ pub const UNNECESSARY: DiagnosticTag = DiagnosticTag(1);
+
+ /// Deprecated or obsolete code.
+ /// Clients are allowed to rendered diagnostics with this tag strike through.
+ pub const DEPRECATED: DiagnosticTag = DiagnosticTag(2);
+}
+}
+
+/// Represents a reference to a command. Provides a title which will be used to represent a command in the UI.
+/// Commands are identitifed using a string identifier and the protocol currently doesn't specify a set of
+/// well known commands. So executing a command requires some tool extension code.
+#[derive(Debug, PartialEq, Clone, Default, Deserialize, Serialize)]
+pub struct Command {
+ /// Title of the command, like `save`.
+ pub title: String,
+ /// The identifier of the actual command handler.
+ pub command: String,
+ /// Arguments that the command handler should be
+ /// invoked with.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub arguments: Option<Vec<Value>>,
+}
+
+impl Command {
+ pub fn new(title: String, command: String, arguments: Option<Vec<Value>>) -> Command {
+ Command {
+ title,
+ command,
+ arguments,
+ }
+ }
+}
+
+/// A textual edit applicable to a text document.
+///
+/// If n `TextEdit`s are applied to a text document all text edits describe changes to the initial document version.
+/// Execution wise text edits should applied from the bottom to the top of the text document. Overlapping text edits
+/// are not supported.
+#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct TextEdit {
+ /// The range of the text document to be manipulated. To insert
+ /// text into a document create a range where start === end.
+ pub range: Range,
+ /// The string to be inserted. For delete operations use an
+ /// empty string.
+ pub new_text: String,
+}
+
+impl TextEdit {
+ pub fn new(range: Range, new_text: String) -> TextEdit {
+ TextEdit { range, new_text }
+ }
+}
+
+/// An identifier referring to a change annotation managed by a workspace
+/// edit.
+///
+/// @since 3.16.0.
+pub type ChangeAnnotationIdentifier = String;
+
+/// A special text edit with an additional change annotation.
+///
+/// @since 3.16.0.
+#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct AnnotatedTextEdit {
+ #[serde(flatten)]
+ pub text_edit: TextEdit,
+
+ /// The actual annotation
+ pub annotation_id: ChangeAnnotationIdentifier,
+}
+
+/// Describes textual changes on a single text document. The text document is referred to as a
+/// `OptionalVersionedTextDocumentIdentifier` to allow clients to check the text document version before an
+/// edit is applied. A `TextDocumentEdit` describes all changes on a version Si and after they are
+/// applied move the document to version Si+1. So the creator of a `TextDocumentEdit` doesn't need to
+/// sort the array or do any kind of ordering. However the edits must be non overlapping.
+#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct TextDocumentEdit {
+ /// The text document to change.
+ pub text_document: OptionalVersionedTextDocumentIdentifier,
+
+ /// The edits to be applied.
+ ///
+ /// @since 3.16.0 - support for AnnotatedTextEdit. This is guarded by the
+ /// client capability `workspace.workspaceEdit.changeAnnotationSupport`
+ pub edits: Vec<OneOf<TextEdit, AnnotatedTextEdit>>,
+}
+
+/// Additional information that describes document changes.
+///
+/// @since 3.16.0.
+#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct ChangeAnnotation {
+ /// A human-readable string describing the actual change. The string
+ /// is rendered prominent in the user interface.
+ pub label: String,
+
+ /// A flag which indicates that user confirmation is needed
+ /// before applying the change.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub needs_confirmation: Option<bool>,
+
+ /// A human-readable string which is rendered less prominent in
+ /// the user interface.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub description: Option<String>,
+}
+
+#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct ChangeAnnotationWorkspaceEditClientCapabilities {
+ /// Whether the client groups edits with equal labels into tree nodes,
+ /// for instance all edits labelled with "Changes in Strings" would
+ /// be a tree node.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub groups_on_label: Option<bool>,
+}
+
+/// Options to create a file.
+#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct CreateFileOptions {
+ /// Overwrite existing file. Overwrite wins over `ignoreIfExists`
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub overwrite: Option<bool>,
+ /// Ignore if exists.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub ignore_if_exists: Option<bool>,
+}
+
+/// Create file operation
+#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct CreateFile {
+ /// The resource to create.
+ pub uri: Url,
+ /// Additional options
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub options: Option<CreateFileOptions>,
+
+ /// An optional annotation identifer describing the operation.
+ ///
+ /// @since 3.16.0
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub annotation_id: Option<ChangeAnnotationIdentifier>,
+}
+
+/// Rename file options
+#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct RenameFileOptions {
+ /// Overwrite target if existing. Overwrite wins over `ignoreIfExists`
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub overwrite: Option<bool>,
+ /// Ignores if target exists.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub ignore_if_exists: Option<bool>,
+}
+
+/// Rename file operation
+#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct RenameFile {
+ /// The old (existing) location.
+ pub old_uri: Url,
+ /// The new location.
+ pub new_uri: Url,
+ /// Rename options.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub options: Option<RenameFileOptions>,
+
+ /// An optional annotation identifer describing the operation.
+ ///
+ /// @since 3.16.0
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub annotation_id: Option<ChangeAnnotationIdentifier>,
+}
+
+/// Delete file options
+#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct DeleteFileOptions {
+ /// Delete the content recursively if a folder is denoted.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub recursive: Option<bool>,
+ /// Ignore the operation if the file doesn't exist.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub ignore_if_not_exists: Option<bool>,
+
+ /// An optional annotation identifer describing the operation.
+ ///
+ /// @since 3.16.0
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub annotation_id: Option<ChangeAnnotationIdentifier>,
+}
+
+/// Delete file operation
+#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct DeleteFile {
+ /// The file to delete.
+ pub uri: Url,
+ /// Delete options.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub options: Option<DeleteFileOptions>,
+}
+
+/// A workspace edit represents changes to many resources managed in the workspace.
+/// The edit should either provide `changes` or `documentChanges`.
+/// If the client can handle versioned document edits and if `documentChanges` are present,
+/// the latter are preferred over `changes`.
+#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct WorkspaceEdit {
+ /// Holds changes to existing resources.
+ #[serde(with = "url_map")]
+ #[serde(skip_serializing_if = "Option::is_none")]
+ #[serde(default)]
+ pub changes: Option<HashMap<Url, Vec<TextEdit>>>, // changes?: { [uri: string]: TextEdit[]; };
+
+ /// Depending on the client capability `workspace.workspaceEdit.resourceOperations` document changes
+ /// are either an array of `TextDocumentEdit`s to express changes to n different text documents
+ /// where each text document edit addresses a specific version of a text document. Or it can contain
+ /// above `TextDocumentEdit`s mixed with create, rename and delete file / folder operations.
+ ///
+ /// Whether a client supports versioned document edits is expressed via
+ /// `workspace.workspaceEdit.documentChanges` client capability.
+ ///
+ /// If a client neither supports `documentChanges` nor `workspace.workspaceEdit.resourceOperations` then
+ /// only plain `TextEdit`s using the `changes` property are supported.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub document_changes: Option<DocumentChanges>,
+
+ /// A map of change annotations that can be referenced in
+ /// `AnnotatedTextEdit`s or create, rename and delete file / folder
+ /// operations.
+ ///
+ /// Whether clients honor this property depends on the client capability
+ /// `workspace.changeAnnotationSupport`.
+ ///
+ /// @since 3.16.0
+ ///
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub change_annotations: Option<HashMap<ChangeAnnotationIdentifier, ChangeAnnotation>>,
+}
+
+#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
+#[serde(untagged)]
+pub enum DocumentChanges {
+ Edits(Vec<TextDocumentEdit>),
+ Operations(Vec<DocumentChangeOperation>),
+}
+
+// TODO: Once https://github.com/serde-rs/serde/issues/912 is solved
+// we can remove ResourceOp and switch to the following implementation
+// of DocumentChangeOperation:
+//
+// #[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
+// #[serde(tag = "kind", rename_all="lowercase" )]
+// pub enum DocumentChangeOperation {
+// Create(CreateFile),
+// Rename(RenameFile),
+// Delete(DeleteFile),
+//
+// #[serde(other)]
+// Edit(TextDocumentEdit),
+// }
+
+#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
+#[serde(untagged, rename_all = "lowercase")]
+pub enum DocumentChangeOperation {
+ Op(ResourceOp),
+ Edit(TextDocumentEdit),
+}
+
+#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
+#[serde(tag = "kind", rename_all = "lowercase")]
+pub enum ResourceOp {
+ Create(CreateFile),
+ Rename(RenameFile),
+ Delete(DeleteFile),
+}
+
+pub type DidChangeConfigurationClientCapabilities = DynamicRegistrationClientCapabilities;
+
+#[derive(Debug, Default, Eq, PartialEq, Clone, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct ConfigurationParams {
+ pub items: Vec<ConfigurationItem>,
+}
+
+#[derive(Debug, Default, Eq, PartialEq, Clone, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct ConfigurationItem {
+ /// The scope to get the configuration section for.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub scope_uri: Option<Url>,
+
+ ///The configuration section asked for.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub section: Option<String>,
+}
+
+mod url_map {
+ use std::fmt;
+
+ use super::*;
+
+ pub fn deserialize<'de, D>(
+ deserializer: D,
+ ) -> Result<Option<HashMap<Url, Vec<TextEdit>>>, D::Error>
+ where
+ D: serde::Deserializer<'de>,
+ {
+ struct UrlMapVisitor;
+ impl<'de> de::Visitor<'de> for UrlMapVisitor {
+ type Value = HashMap<Url, Vec<TextEdit>>;
+
+ fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ formatter.write_str("map")
+ }
+
+ fn visit_map<M>(self, mut visitor: M) -> Result<Self::Value, M::Error>
+ where
+ M: de::MapAccess<'de>,
+ {
+ let mut values = HashMap::with_capacity(visitor.size_hint().unwrap_or(0));
+
+ // While there are entries remaining in the input, add them
+ // into our map.
+ while let Some((key, value)) = visitor.next_entry::<Url, _>()? {
+ values.insert(key, value);
+ }
+
+ Ok(values)
+ }
+ }
+
+ struct OptionUrlMapVisitor;
+ impl<'de> de::Visitor<'de> for OptionUrlMapVisitor {
+ type Value = Option<HashMap<Url, Vec<TextEdit>>>;
+
+ fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ formatter.write_str("option")
+ }
+
+ #[inline]
+ fn visit_unit<E>(self) -> Result<Self::Value, E>
+ where
+ E: serde::de::Error,
+ {
+ Ok(None)
+ }
+
+ #[inline]
+ fn visit_none<E>(self) -> Result<Self::Value, E>
+ where
+ E: serde::de::Error,
+ {
+ Ok(None)
+ }
+
+ #[inline]
+ fn visit_some<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
+ where
+ D: serde::Deserializer<'de>,
+ {
+ deserializer.deserialize_map(UrlMapVisitor).map(Some)
+ }
+ }
+
+ // Instantiate our Visitor and ask the Deserializer to drive
+ // it over the input data, resulting in an instance of MyMap.
+ deserializer.deserialize_option(OptionUrlMapVisitor)
+ }
+
+ pub fn serialize<S>(
+ changes: &Option<HashMap<Url, Vec<TextEdit>>>,
+ serializer: S,
+ ) -> Result<S::Ok, S::Error>
+ where
+ S: serde::Serializer,
+ {
+ use serde::ser::SerializeMap;
+
+ match *changes {
+ Some(ref changes) => {
+ let mut map = serializer.serialize_map(Some(changes.len()))?;
+ for (k, v) in changes {
+ map.serialize_entry(k.as_str(), v)?;
+ }
+ map.end()
+ }
+ None => serializer.serialize_none(),
+ }
+ }
+}
+
+impl WorkspaceEdit {
+ pub fn new(changes: HashMap<Url, Vec<TextEdit>>) -> WorkspaceEdit {
+ WorkspaceEdit {
+ changes: Some(changes),
+ document_changes: None,
+ ..Default::default()
+ }
+ }
+}
+
+/// Text documents are identified using a URI. On the protocol level, URIs are passed as strings.
+#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
+pub struct TextDocumentIdentifier {
+ // !!!!!! Note:
+ // In the spec VersionedTextDocumentIdentifier extends TextDocumentIdentifier
+ // This modelled by "mixing-in" TextDocumentIdentifier in VersionedTextDocumentIdentifier,
+ // so any changes to this type must be effected in the sub-type as well.
+ /// The text document's URI.
+ pub uri: Url,
+}
+
+impl TextDocumentIdentifier {
+ pub fn new(uri: Url) -> TextDocumentIdentifier {
+ TextDocumentIdentifier { uri }
+ }
+}
+
+/// An item to transfer a text document from the client to the server.
+#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct TextDocumentItem {
+ /// The text document's URI.
+ pub uri: Url,
+
+ /// The text document's language identifier.
+ pub language_id: String,
+
+ /// The version number of this document (it will strictly increase after each
+ /// change, including undo/redo).
+ pub version: i32,
+
+ /// The content of the opened text document.
+ pub text: String,
+}
+
+impl TextDocumentItem {
+ pub fn new(uri: Url, language_id: String, version: i32, text: String) -> TextDocumentItem {
+ TextDocumentItem {
+ uri,
+ language_id,
+ version,
+ text,
+ }
+ }
+}
+
+/// An identifier to denote a specific version of a text document. This information usually flows from the client to the server.
+#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
+pub struct VersionedTextDocumentIdentifier {
+ // This field was "mixed-in" from TextDocumentIdentifier
+ /// The text document's URI.
+ pub uri: Url,
+
+ /// The version number of this document.
+ ///
+ /// The version number of a document will increase after each change,
+ /// including undo/redo. The number doesn't need to be consecutive.
+ pub version: i32,
+}
+
+impl VersionedTextDocumentIdentifier {
+ pub fn new(uri: Url, version: i32) -> VersionedTextDocumentIdentifier {
+ VersionedTextDocumentIdentifier { uri, version }
+ }
+}
+
+/// An identifier which optionally denotes a specific version of a text document. This information usually flows from the server to the client
+#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
+pub struct OptionalVersionedTextDocumentIdentifier {
+ // This field was "mixed-in" from TextDocumentIdentifier
+ /// The text document's URI.
+ pub uri: Url,
+
+ /// The version number of this document. If an optional versioned text document
+ /// identifier is sent from the server to the client and the file is not
+ /// open in the editor (the server has not received an open notification
+ /// before) the server can send `null` to indicate that the version is
+ /// known and the content on disk is the master (as specified with document
+ /// content ownership).
+ ///
+ /// The version number of a document will increase after each change,
+ /// including undo/redo. The number doesn't need to be consecutive.
+ pub version: Option<i32>,
+}
+
+impl OptionalVersionedTextDocumentIdentifier {
+ pub fn new(uri: Url, version: i32) -> OptionalVersionedTextDocumentIdentifier {
+ OptionalVersionedTextDocumentIdentifier {
+ uri,
+ version: Some(version),
+ }
+ }
+}
+
+/// A parameter literal used in requests to pass a text document and a position inside that document.
+#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct TextDocumentPositionParams {
+ // !!!!!! Note:
+ // In the spec ReferenceParams extends TextDocumentPositionParams
+ // This modelled by "mixing-in" TextDocumentPositionParams in ReferenceParams,
+ // so any changes to this type must be effected in sub-type as well.
+ /// The text document.
+ pub text_document: TextDocumentIdentifier,
+
+ /// The position inside the text document.
+ pub position: Position,
+}
+
+impl TextDocumentPositionParams {
+ pub fn new(
+ text_document: TextDocumentIdentifier,
+ position: Position,
+ ) -> TextDocumentPositionParams {
+ TextDocumentPositionParams {
+ text_document,
+ position,
+ }
+ }
+}
+
+/// A document filter denotes a document through properties like language, schema or pattern.
+/// Examples are a filter that applies to TypeScript files on disk or a filter the applies to JSON
+/// files with name package.json:
+///
+/// { language: 'typescript', scheme: 'file' }
+/// { language: 'json', pattern: '**/package.json' }
+#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
+pub struct DocumentFilter {
+ /// A language id, like `typescript`.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub language: Option<String>,
+
+ /// A Uri [scheme](#Uri.scheme), like `file` or `untitled`.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub scheme: Option<String>,
+
+ /// A glob pattern, like `*.{ts,js}`.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub pattern: Option<String>,
+}
+
+/// A document selector is the combination of one or many document filters.
+pub type DocumentSelector = Vec<DocumentFilter>;
+
+// ========================= Actual Protocol =========================
+
+#[derive(Debug, PartialEq, Clone, Deserialize, Serialize, Default)]
+#[serde(rename_all = "camelCase")]
+pub struct InitializeParams {
+ /// The process Id of the parent process that started
+ /// the server. Is null if the process has not been started by another process.
+ /// If the parent process is not alive then the server should exit (see exit notification) its process.
+ pub process_id: Option<u32>,
+
+ /// The rootPath of the workspace. Is null
+ /// if no folder is open.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ #[deprecated(note = "Use `root_uri` instead when possible")]
+ pub root_path: Option<String>,
+
+ /// The rootUri of the workspace. Is null if no
+ /// folder is open. If both `rootPath` and `rootUri` are set
+ /// `rootUri` wins.
+ ///
+ /// Deprecated in favour of `workspaceFolders`
+ #[serde(default)]
+ pub root_uri: Option<Url>,
+
+ /// User provided initialization options.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub initialization_options: Option<Value>,
+
+ /// The capabilities provided by the client (editor or tool)
+ pub capabilities: ClientCapabilities,
+
+ /// The initial trace setting. If omitted trace is disabled ('off').
+ #[serde(default)]
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub trace: Option<TraceValue>,
+
+ /// The workspace folders configured in the client when the server starts.
+ /// This property is only available if the client supports workspace folders.
+ /// It can be `null` if the client supports workspace folders but none are
+ /// configured.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub workspace_folders: Option<Vec<WorkspaceFolder>>,
+
+ /// Information about the client.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub client_info: Option<ClientInfo>,
+
+ /// The locale the client is currently showing the user interface
+ /// in. This must not necessarily be the locale of the operating
+ /// system.
+ ///
+ /// Uses IETF language tags as the value's syntax
+ /// (See <https://en.wikipedia.org/wiki/IETF_language_tag>)
+ ///
+ /// @since 3.16.0
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub locale: Option<String>,
+}
+
+#[derive(Debug, PartialEq, Clone, Deserialize, Serialize)]
+pub struct ClientInfo {
+ /// The name of the client as defined by the client.
+ pub name: String,
+ /// The client's version as defined by the client.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub version: Option<String>,
+}
+
+#[derive(Debug, PartialEq, Clone, Copy, Deserialize, Serialize)]
+pub struct InitializedParams {}
+
+#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
+pub struct GenericRegistrationOptions {
+ #[serde(flatten)]
+ pub text_document_registration_options: TextDocumentRegistrationOptions,
+
+ #[serde(flatten)]
+ pub options: GenericOptions,
+
+ #[serde(flatten)]
+ pub static_registration_options: StaticRegistrationOptions,
+}
+
+#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
+pub struct GenericOptions {
+ #[serde(flatten)]
+ pub work_done_progress_options: WorkDoneProgressOptions,
+}
+
+#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
+pub struct GenericParams {
+ #[serde(flatten)]
+ pub text_document_position_params: TextDocumentPositionParams,
+
+ #[serde(flatten)]
+ pub work_done_progress_params: WorkDoneProgressParams,
+
+ #[serde(flatten)]
+ pub partial_result_params: PartialResultParams,
+}
+
+#[derive(Debug, Eq, PartialEq, Clone, Copy, Default, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct DynamicRegistrationClientCapabilities {
+ /// This capability supports dynamic registration.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub dynamic_registration: Option<bool>,
+}
+
+#[derive(Debug, Eq, PartialEq, Clone, Copy, Default, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct GotoCapability {
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub dynamic_registration: Option<bool>,
+
+ /// The client supports additional metadata in the form of definition links.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub link_support: Option<bool>,
+}
+
+#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct WorkspaceEditClientCapabilities {
+ /// The client supports versioned document changes in `WorkspaceEdit`s
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub document_changes: Option<bool>,
+
+ /// The resource operations the client supports. Clients should at least
+ /// support 'create', 'rename' and 'delete' files and folders.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub resource_operations: Option<Vec<ResourceOperationKind>>,
+
+ /// The failure handling strategy of a client if applying the workspace edit
+ /// failes.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub failure_handling: Option<FailureHandlingKind>,
+
+ /// Whether the client normalizes line endings to the client specific
+ /// setting.
+ /// If set to `true` the client will normalize line ending characters
+ /// in a workspace edit containg to the client specific new line
+ /// character.
+ ///
+ /// @since 3.16.0
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub normalizes_line_endings: Option<bool>,
+
+ /// Whether the client in general supports change annotations on text edits,
+ /// create file, rename file and delete file changes.
+ ///
+ /// @since 3.16.0
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub change_annotation_support: Option<ChangeAnnotationWorkspaceEditClientCapabilities>,
+}
+
+#[derive(Debug, Eq, PartialEq, Deserialize, Serialize, Copy, Clone)]
+#[serde(rename_all = "lowercase")]
+pub enum ResourceOperationKind {
+ Create,
+ Rename,
+ Delete,
+}
+
+#[derive(Debug, Eq, PartialEq, Deserialize, Serialize, Copy, Clone)]
+#[serde(rename_all = "camelCase")]
+pub enum FailureHandlingKind {
+ Abort,
+ Transactional,
+ TextOnlyTransactional,
+ Undo,
+}
+
+/// A symbol kind.
+#[derive(Eq, PartialEq, Copy, Clone, Serialize, Deserialize)]
+#[serde(transparent)]
+pub struct SymbolKind(i32);
+lsp_enum! {
+impl SymbolKind {
+ pub const FILE: SymbolKind = SymbolKind(1);
+ pub const MODULE: SymbolKind = SymbolKind(2);
+ pub const NAMESPACE: SymbolKind = SymbolKind(3);
+ pub const PACKAGE: SymbolKind = SymbolKind(4);
+ pub const CLASS: SymbolKind = SymbolKind(5);
+ pub const METHOD: SymbolKind = SymbolKind(6);
+ pub const PROPERTY: SymbolKind = SymbolKind(7);
+ pub const FIELD: SymbolKind = SymbolKind(8);
+ pub const CONSTRUCTOR: SymbolKind = SymbolKind(9);
+ pub const ENUM: SymbolKind = SymbolKind(10);
+ pub const INTERFACE: SymbolKind = SymbolKind(11);
+ pub const FUNCTION: SymbolKind = SymbolKind(12);
+ pub const VARIABLE: SymbolKind = SymbolKind(13);
+ pub const CONSTANT: SymbolKind = SymbolKind(14);
+ pub const STRING: SymbolKind = SymbolKind(15);
+ pub const NUMBER: SymbolKind = SymbolKind(16);
+ pub const BOOLEAN: SymbolKind = SymbolKind(17);
+ pub const ARRAY: SymbolKind = SymbolKind(18);
+ pub const OBJECT: SymbolKind = SymbolKind(19);
+ pub const KEY: SymbolKind = SymbolKind(20);
+ pub const NULL: SymbolKind = SymbolKind(21);
+ pub const ENUM_MEMBER: SymbolKind = SymbolKind(22);
+ pub const STRUCT: SymbolKind = SymbolKind(23);
+ pub const EVENT: SymbolKind = SymbolKind(24);
+ pub const OPERATOR: SymbolKind = SymbolKind(25);
+ pub const TYPE_PARAMETER: SymbolKind = SymbolKind(26);
+}
+}
+
+/// Specific capabilities for the `SymbolKind` in the `workspace/symbol` request.
+#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct SymbolKindCapability {
+ /// The symbol kind values the client supports. When this
+ /// property exists the client also guarantees that it will
+ /// handle values outside its set gracefully and falls back
+ /// to a default value when unknown.
+ ///
+ /// If this property is not present the client only supports
+ /// the symbol kinds from `File` to `Array` as defined in
+ /// the initial version of the protocol.
+ pub value_set: Option<Vec<SymbolKind>>,
+}
+
+/// Workspace specific client capabilities.
+#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct WorkspaceClientCapabilities {
+ /// The client supports applying batch edits to the workspace by supporting
+ /// the request 'workspace/applyEdit'
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub apply_edit: Option<bool>,
+
+ /// Capabilities specific to `WorkspaceEdit`s
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub workspace_edit: Option<WorkspaceEditClientCapabilities>,
+
+ /// Capabilities specific to the `workspace/didChangeConfiguration` notification.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub did_change_configuration: Option<DidChangeConfigurationClientCapabilities>,
+
+ /// Capabilities specific to the `workspace/didChangeWatchedFiles` notification.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub did_change_watched_files: Option<DidChangeWatchedFilesClientCapabilities>,
+
+ /// Capabilities specific to the `workspace/symbol` request.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub symbol: Option<WorkspaceSymbolClientCapabilities>,
+
+ /// Capabilities specific to the `workspace/executeCommand` request.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub execute_command: Option<ExecuteCommandClientCapabilities>,
+
+ /// The client has support for workspace folders.
+ /// since 3.6.0
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub workspace_folders: Option<bool>,
+
+ /// The client supports `workspace/configuration` requests.
+ /// since 3.6.0
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub configuration: Option<bool>,
+
+ /// Capabilities specific to the semantic token requsts scoped to the workspace.
+ /// since 3.16.0
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub semantic_tokens: Option<SemanticTokensWorkspaceClientCapabilities>,
+
+ /// Capabilities specific to the code lens requests scoped to the workspace.
+ /// since 3.16.0
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub code_lens: Option<CodeLensWorkspaceClientCapabilities>,
+
+ /// The client has support for file requests/notifications.
+ /// since 3.16.0
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub file_operations: Option<WorkspaceFileOperationsClientCapabilities>,
+
+ /// Client workspace capabilities specific to inline values.
+ /// since 3.17.0
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub inline_value: Option<InlineValueWorkspaceClientCapabilities>,
+
+ /// Client workspace capabilities specific to inlay hints.
+ /// since 3.17.0
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub inlay_hint: Option<InlayHintWorkspaceClientCapabilities>,
+}
+
+#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct TextDocumentSyncClientCapabilities {
+ /// Whether text document synchronization supports dynamic registration.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub dynamic_registration: Option<bool>,
+
+ /// The client supports sending will save notifications.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub will_save: Option<bool>,
+
+ /// The client supports sending a will save request and
+ /// waits for a response providing text edits which will
+ /// be applied to the document before it is saved.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub will_save_wait_until: Option<bool>,
+
+ /// The client supports did save notifications.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub did_save: Option<bool>,
+}
+
+#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct PublishDiagnosticsClientCapabilities {
+ /// Whether the clients accepts diagnostics with related information.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub related_information: Option<bool>,
+
+ /// Client supports the tag property to provide meta data about a diagnostic.
+ /// Clients supporting tags have to handle unknown tags gracefully.
+ #[serde(
+ default,
+ skip_serializing_if = "Option::is_none",
+ deserialize_with = "TagSupport::deserialize_compat"
+ )]
+ pub tag_support: Option<TagSupport<DiagnosticTag>>,
+
+ /// Whether the client interprets the version property of the
+ /// `textDocument/publishDiagnostics` notification's parameter.
+ ///
+ /// 3.15.0
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub version_support: Option<bool>,
+
+ /// Client supports a codeDescription property
+ ///
+ /// 3.16.0
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub code_description_support: Option<bool>,
+
+ /// Whether code action supports the `data` property which is
+ /// preserved between a `textDocument/publishDiagnostics` and
+ /// `textDocument/codeAction` request.
+ ///
+ /// 3.16.0
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub data_support: Option<bool>,
+}
+
+#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct TagSupport<T> {
+ /// The tags supported by the client.
+ pub value_set: Vec<T>,
+}
+
+impl<T> TagSupport<T> {
+ /// Support for deserializing a boolean tag Support, in case it's present.
+ ///
+ /// This is currently the case for vscode 1.41.1
+ fn deserialize_compat<'de, S>(serializer: S) -> Result<Option<TagSupport<T>>, S::Error>
+ where
+ S: serde::Deserializer<'de>,
+ T: serde::Deserialize<'de>,
+ {
+ Ok(
+ match Option::<Value>::deserialize(serializer).map_err(serde::de::Error::custom)? {
+ Some(Value::Bool(false)) => None,
+ Some(Value::Bool(true)) => Some(TagSupport { value_set: vec![] }),
+ Some(other) => {
+ Some(TagSupport::<T>::deserialize(other).map_err(serde::de::Error::custom)?)
+ }
+ None => None,
+ },
+ )
+ }
+}
+
+/// Text document specific client capabilities.
+#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct TextDocumentClientCapabilities {
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub synchronization: Option<TextDocumentSyncClientCapabilities>,
+ /// Capabilities specific to the `textDocument/completion`
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub completion: Option<CompletionClientCapabilities>,
+
+ /// Capabilities specific to the `textDocument/hover`
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub hover: Option<HoverClientCapabilities>,
+
+ /// Capabilities specific to the `textDocument/signatureHelp`
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub signature_help: Option<SignatureHelpClientCapabilities>,
+
+ /// Capabilities specific to the `textDocument/references`
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub references: Option<ReferenceClientCapabilities>,
+
+ /// Capabilities specific to the `textDocument/documentHighlight`
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub document_highlight: Option<DocumentHighlightClientCapabilities>,
+
+ /// Capabilities specific to the `textDocument/documentSymbol`
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub document_symbol: Option<DocumentSymbolClientCapabilities>,
+ /// Capabilities specific to the `textDocument/formatting`
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub formatting: Option<DocumentFormattingClientCapabilities>,
+
+ /// Capabilities specific to the `textDocument/rangeFormatting`
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub range_formatting: Option<DocumentRangeFormattingClientCapabilities>,
+
+ /// Capabilities specific to the `textDocument/onTypeFormatting`
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub on_type_formatting: Option<DocumentOnTypeFormattingClientCapabilities>,
+
+ /// Capabilities specific to the `textDocument/declaration`
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub declaration: Option<GotoCapability>,
+
+ /// Capabilities specific to the `textDocument/definition`
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub definition: Option<GotoCapability>,
+
+ /// Capabilities specific to the `textDocument/typeDefinition`
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub type_definition: Option<GotoCapability>,
+
+ /// Capabilities specific to the `textDocument/implementation`
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub implementation: Option<GotoCapability>,
+
+ /// Capabilities specific to the `textDocument/codeAction`
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub code_action: Option<CodeActionClientCapabilities>,
+
+ /// Capabilities specific to the `textDocument/codeLens`
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub code_lens: Option<CodeLensClientCapabilities>,
+
+ /// Capabilities specific to the `textDocument/documentLink`
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub document_link: Option<DocumentLinkClientCapabilities>,
+
+ /// Capabilities specific to the `textDocument/documentColor` and the
+ /// `textDocument/colorPresentation` request.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub color_provider: Option<DocumentColorClientCapabilities>,
+
+ /// Capabilities specific to the `textDocument/rename`
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub rename: Option<RenameClientCapabilities>,
+
+ /// Capabilities specific to `textDocument/publishDiagnostics`.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub publish_diagnostics: Option<PublishDiagnosticsClientCapabilities>,
+
+ /// Capabilities specific to `textDocument/foldingRange` requests.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub folding_range: Option<FoldingRangeClientCapabilities>,
+
+ /// Capabilities specific to the `textDocument/selectionRange` request.
+ ///
+ /// @since 3.15.0
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub selection_range: Option<SelectionRangeClientCapabilities>,
+
+ /// Capabilities specific to `textDocument/linkedEditingRange` requests.
+ ///
+ /// @since 3.16.0
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub linked_editing_range: Option<LinkedEditingRangeClientCapabilities>,
+
+ /// Capabilities specific to the various call hierarchy requests.
+ ///
+ /// @since 3.16.0
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub call_hierarchy: Option<CallHierarchyClientCapabilities>,
+
+ /// Capabilities specific to the `textDocument/semanticTokens/*` requests.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub semantic_tokens: Option<SemanticTokensClientCapabilities>,
+
+ /// Capabilities specific to the `textDocument/moniker` request.
+ ///
+ /// @since 3.16.0
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub moniker: Option<MonikerClientCapabilities>,
+
+ /// Capabilities specific to the various type hierarchy requests.
+ ///
+ /// @since 3.17.0
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub type_hierarchy: Option<TypeHierarchyClientCapabilities>,
+
+ /// Capabilities specific to the `textDocument/inlineValue` request.
+ ///
+ /// @since 3.17.0
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub inline_value: Option<InlineValueClientCapabilities>,
+
+ /// Capabilities specific to the `textDocument/inlayHint` request.
+ ///
+ /// @since 3.17.0
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub inlay_hint: Option<InlayHintClientCapabilities>,
+}
+
+/// Where ClientCapabilities are currently empty:
+#[derive(Debug, PartialEq, Clone, Default, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct ClientCapabilities {
+ /// Workspace specific client capabilities.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub workspace: Option<WorkspaceClientCapabilities>,
+
+ /// Text document specific client capabilities.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub text_document: Option<TextDocumentClientCapabilities>,
+
+ /// Window specific client capabilities.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub window: Option<WindowClientCapabilities>,
+
+ /// General client capabilities.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub general: Option<GeneralClientCapabilities>,
+
+ /// Unofficial UT8-offsets extension.
+ ///
+ /// See https://clangd.llvm.org/extensions.html#utf-8-offsets.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ #[cfg(feature = "proposed")]
+ pub offset_encoding: Option<Vec<String>>,
+
+ /// Experimental client capabilities.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub experimental: Option<Value>,
+}
+
+#[derive(Debug, PartialEq, Clone, Default, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct GeneralClientCapabilities {
+ /// Client capabilities specific to regular expressions.
+ /// @since 3.16.0
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub regular_expressions: Option<RegularExpressionsClientCapabilities>,
+
+ /// Client capabilities specific to the client's markdown parser.
+ /// @since 3.16.0
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub markdown: Option<MarkdownClientCapabilities>,
+
+ /// Client capability that signals how the client handles stale requests (e.g. a request for
+ /// which the client will not process the response anymore since the information is outdated).
+ ///
+ /// @since 3.17.0
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub stale_request_support: Option<StaleRequestSupportClientCapabilities>,
+
+ /// The position encodings supported by the client. Client and server
+ /// have to agree on the same position encoding to ensure that offsets
+ /// (e.g. character position in a line) are interpreted the same on both
+ /// side.
+ ///
+ /// To keep the protocol backwards compatible the following applies: if
+ /// the value 'utf-16' is missing from the array of position encodings
+ /// servers can assume that the client supports UTF-16. UTF-16 is
+ /// therefore a mandatory encoding.
+ ///
+ /// If omitted it defaults to ['utf-16'].
+ ///
+ /// Implementation considerations: since the conversion from one encoding
+ /// into another requires the content of the file / line the conversion
+ /// is best done where the file is read which is usually on the server
+ /// side.
+ ///
+ /// @since 3.17.0
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub position_encodings: Option<Vec<PositionEncodingKind>>,
+}
+
+/// Client capability that signals how the client
+/// handles stale requests (e.g. a request
+/// for which the client will not process the response
+/// anymore since the information is outdated).
+///
+/// @since 3.17.0
+#[derive(Debug, PartialEq, Clone, Default, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct StaleRequestSupportClientCapabilities {
+ /// The client will actively cancel the request.
+ pub cancel: bool,
+
+ /// The list of requests for which the client
+ /// will retry the request if it receives a
+ /// response with error code `ContentModified``
+ pub retry_on_content_modified: Vec<String>,
+}
+
+#[derive(Debug, PartialEq, Clone, Default, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct RegularExpressionsClientCapabilities {
+ /// The engine's name.
+ pub engine: String,
+
+ /// The engine's version
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub version: Option<String>,
+}
+
+#[derive(Debug, PartialEq, Clone, Default, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct MarkdownClientCapabilities {
+ /// The name of the parser.
+ pub parser: String,
+
+ /// The version of the parser.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub version: Option<String>,
+
+ /// A list of HTML tags that the client allows / supports in
+ /// Markdown.
+ ///
+ /// @since 3.17.0
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub allowed_tags: Option<Vec<String>>,
+}
+
+#[derive(Debug, PartialEq, Clone, Default, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct InitializeResult {
+ /// The capabilities the language server provides.
+ pub capabilities: ServerCapabilities,
+
+ /// Information about the server.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub server_info: Option<ServerInfo>,
+
+ /// Unofficial UT8-offsets extension.
+ ///
+ /// See https://clangd.llvm.org/extensions.html#utf-8-offsets.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ #[cfg(feature = "proposed")]
+ pub offset_encoding: Option<String>,
+}
+
+#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
+pub struct ServerInfo {
+ /// The name of the server as defined by the server.
+ pub name: String,
+ /// The servers's version as defined by the server.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub version: Option<String>,
+}
+
+#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
+pub struct InitializeError {
+ /// Indicates whether the client should retry to send the
+ /// initilize request after showing the message provided
+ /// in the ResponseError.
+ pub retry: bool,
+}
+
+// The server can signal the following capabilities:
+
+/// Defines how the host (editor) should sync document changes to the language server.
+#[derive(Eq, PartialEq, Clone, Copy, Deserialize, Serialize)]
+#[serde(transparent)]
+pub struct TextDocumentSyncKind(i32);
+lsp_enum! {
+impl TextDocumentSyncKind {
+ /// Documents should not be synced at all.
+ pub const NONE: TextDocumentSyncKind = TextDocumentSyncKind(0);
+
+ /// Documents are synced by always sending the full content of the document.
+ pub const FULL: TextDocumentSyncKind = TextDocumentSyncKind(1);
+
+ /// Documents are synced by sending the full content on open. After that only
+ /// incremental updates to the document are sent.
+ pub const INCREMENTAL: TextDocumentSyncKind = TextDocumentSyncKind(2);
+}
+}
+
+pub type ExecuteCommandClientCapabilities = DynamicRegistrationClientCapabilities;
+
+/// Execute command options.
+#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
+pub struct ExecuteCommandOptions {
+ /// The commands to be executed on the server
+ pub commands: Vec<String>,
+
+ #[serde(flatten)]
+ pub work_done_progress_options: WorkDoneProgressOptions,
+}
+
+/// Save options.
+#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct SaveOptions {
+ /// The client is supposed to include the content on save.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub include_text: Option<bool>,
+}
+
+#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
+#[serde(untagged)]
+pub enum TextDocumentSyncSaveOptions {
+ Supported(bool),
+ SaveOptions(SaveOptions),
+}
+
+impl From<SaveOptions> for TextDocumentSyncSaveOptions {
+ fn from(from: SaveOptions) -> Self {
+ Self::SaveOptions(from)
+ }
+}
+
+impl From<bool> for TextDocumentSyncSaveOptions {
+ fn from(from: bool) -> Self {
+ Self::Supported(from)
+ }
+}
+
+#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct TextDocumentSyncOptions {
+ /// Open and close notifications are sent to the server.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub open_close: Option<bool>,
+
+ /// Change notifications are sent to the server. See TextDocumentSyncKind.None, TextDocumentSyncKind.Full
+ /// and TextDocumentSyncKindIncremental.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub change: Option<TextDocumentSyncKind>,
+
+ /// Will save notifications are sent to the server.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub will_save: Option<bool>,
+
+ /// Will save wait until requests are sent to the server.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub will_save_wait_until: Option<bool>,
+
+ /// Save notifications are sent to the server.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub save: Option<TextDocumentSyncSaveOptions>,
+}
+
+#[derive(Debug, Eq, PartialEq, Ord, PartialOrd, Clone, Deserialize, Serialize)]
+#[serde(untagged)]
+pub enum OneOf<A, B> {
+ Left(A),
+ Right(B),
+}
+
+#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
+#[serde(untagged)]
+pub enum TextDocumentSyncCapability {
+ Kind(TextDocumentSyncKind),
+ Options(TextDocumentSyncOptions),
+}
+
+impl From<TextDocumentSyncOptions> for TextDocumentSyncCapability {
+ fn from(from: TextDocumentSyncOptions) -> Self {
+ Self::Options(from)
+ }
+}
+
+impl From<TextDocumentSyncKind> for TextDocumentSyncCapability {
+ fn from(from: TextDocumentSyncKind) -> Self {
+ Self::Kind(from)
+ }
+}
+
+#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
+#[serde(untagged)]
+pub enum ImplementationProviderCapability {
+ Simple(bool),
+ Options(StaticTextDocumentRegistrationOptions),
+}
+
+impl From<StaticTextDocumentRegistrationOptions> for ImplementationProviderCapability {
+ fn from(from: StaticTextDocumentRegistrationOptions) -> Self {
+ Self::Options(from)
+ }
+}
+
+impl From<bool> for ImplementationProviderCapability {
+ fn from(from: bool) -> Self {
+ Self::Simple(from)
+ }
+}
+
+#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
+#[serde(untagged)]
+pub enum TypeDefinitionProviderCapability {
+ Simple(bool),
+ Options(StaticTextDocumentRegistrationOptions),
+}
+
+impl From<StaticTextDocumentRegistrationOptions> for TypeDefinitionProviderCapability {
+ fn from(from: StaticTextDocumentRegistrationOptions) -> Self {
+ Self::Options(from)
+ }
+}
+
+impl From<bool> for TypeDefinitionProviderCapability {
+ fn from(from: bool) -> Self {
+ Self::Simple(from)
+ }
+}
+
+#[derive(Debug, PartialEq, Clone, Default, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct ServerCapabilities {
+ /// The position encoding the server picked from the encodings offered
+ /// by the client via the client capability `general.positionEncodings`.
+ ///
+ /// If the client didn't provide any position encodings the only valid
+ /// value that a server can return is 'utf-16'.
+ ///
+ /// If omitted it defaults to 'utf-16'.
+ ///
+ /// @since 3.17.0
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub position_encoding: Option<PositionEncodingKind>,
+
+ /// Defines how text documents are synced.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub text_document_sync: Option<TextDocumentSyncCapability>,
+
+ /// Capabilities specific to `textDocument/selectionRange` requests.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub selection_range_provider: Option<SelectionRangeProviderCapability>,
+
+ /// The server provides hover support.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub hover_provider: Option<HoverProviderCapability>,
+
+ /// The server provides completion support.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub completion_provider: Option<CompletionOptions>,
+
+ /// The server provides signature help support.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub signature_help_provider: Option<SignatureHelpOptions>,
+
+ /// The server provides goto definition support.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub definition_provider: Option<OneOf<bool, DefinitionOptions>>,
+
+ /// The server provides goto type definition support.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub type_definition_provider: Option<TypeDefinitionProviderCapability>,
+
+ /// The server provides goto implementation support.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub implementation_provider: Option<ImplementationProviderCapability>,
+
+ /// The server provides find references support.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub references_provider: Option<OneOf<bool, ReferencesOptions>>,
+
+ /// The server provides document highlight support.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub document_highlight_provider: Option<OneOf<bool, DocumentHighlightOptions>>,
+
+ /// The server provides document symbol support.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub document_symbol_provider: Option<OneOf<bool, DocumentSymbolOptions>>,
+
+ /// The server provides workspace symbol support.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub workspace_symbol_provider: Option<OneOf<bool, WorkspaceSymbolOptions>>,
+
+ /// The server provides code actions.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub code_action_provider: Option<CodeActionProviderCapability>,
+
+ /// The server provides code lens.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub code_lens_provider: Option<CodeLensOptions>,
+
+ /// The server provides document formatting.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub document_formatting_provider: Option<OneOf<bool, DocumentFormattingOptions>>,
+
+ /// The server provides document range formatting.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub document_range_formatting_provider: Option<OneOf<bool, DocumentRangeFormattingOptions>>,
+
+ /// The server provides document formatting on typing.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub document_on_type_formatting_provider: Option<DocumentOnTypeFormattingOptions>,
+
+ /// The server provides rename support.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub rename_provider: Option<OneOf<bool, RenameOptions>>,
+
+ /// The server provides document link support.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub document_link_provider: Option<DocumentLinkOptions>,
+
+ /// The server provides color provider support.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub color_provider: Option<ColorProviderCapability>,
+
+ /// The server provides folding provider support.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub folding_range_provider: Option<FoldingRangeProviderCapability>,
+
+ /// The server provides go to declaration support.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub declaration_provider: Option<DeclarationCapability>,
+
+ /// The server provides execute command support.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub execute_command_provider: Option<ExecuteCommandOptions>,
+
+ /// Workspace specific server capabilities
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub workspace: Option<WorkspaceServerCapabilities>,
+
+ /// Call hierarchy provider capabilities.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub call_hierarchy_provider: Option<CallHierarchyServerCapability>,
+
+ /// Semantic tokens server capabilities.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub semantic_tokens_provider: Option<SemanticTokensServerCapabilities>,
+
+ /// Whether server provides moniker support.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub moniker_provider: Option<OneOf<bool, MonikerServerCapabilities>>,
+
+ /// The server provides inline values.
+ ///
+ /// @since 3.17.0
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub inline_value_provider: Option<OneOf<bool, InlineValueServerCapabilities>>,
+
+ /// The server provides inlay hints.
+ ///
+ /// @since 3.17.0
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub inlay_hint_provider: Option<OneOf<bool, InlayHintServerCapabilities>>,
+
+ /// The server provides linked editing range support.
+ ///
+ /// @since 3.16.0
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub linked_editing_range_provider: Option<LinkedEditingRangeServerCapabilities>,
+
+ /// Experimental server capabilities.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub experimental: Option<Value>,
+}
+
+#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct WorkspaceServerCapabilities {
+ /// The server supports workspace folder.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub workspace_folders: Option<WorkspaceFoldersServerCapabilities>,
+
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub file_operations: Option<WorkspaceFileOperationsServerCapabilities>,
+}
+
+/// General parameters to to register for a capability.
+#[derive(Debug, PartialEq, Clone, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct Registration {
+ /// The id used to register the request. The id can be used to deregister
+ /// the request again.
+ pub id: String,
+
+ /// The method / capability to register for.
+ pub method: String,
+
+ /// Options necessary for the registration.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub register_options: Option<Value>,
+}
+
+#[derive(Debug, PartialEq, Clone, Deserialize, Serialize)]
+pub struct RegistrationParams {
+ pub registrations: Vec<Registration>,
+}
+
+/// Since most of the registration options require to specify a document selector there is a base
+/// interface that can be used.
+#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct TextDocumentRegistrationOptions {
+ /// A document selector to identify the scope of the registration. If set to null
+ /// the document selector provided on the client side will be used.
+ pub document_selector: Option<DocumentSelector>,
+}
+
+#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
+#[serde(untagged)]
+pub enum DeclarationCapability {
+ Simple(bool),
+ RegistrationOptions(DeclarationRegistrationOptions),
+ Options(DeclarationOptions),
+}
+
+#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct DeclarationRegistrationOptions {
+ #[serde(flatten)]
+ pub declaration_options: DeclarationOptions,
+
+ #[serde(flatten)]
+ pub text_document_registration_options: TextDocumentRegistrationOptions,
+
+ #[serde(flatten)]
+ pub static_registration_options: StaticRegistrationOptions,
+}
+
+#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct DeclarationOptions {
+ #[serde(flatten)]
+ pub work_done_progress_options: WorkDoneProgressOptions,
+}
+
+#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct StaticRegistrationOptions {
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub id: Option<String>,
+}
+
+#[derive(Debug, Default, Eq, PartialEq, Clone, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct WorkDoneProgressOptions {
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub work_done_progress: Option<bool>,
+}
+
+#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct DocumentFormattingOptions {
+ #[serde(flatten)]
+ pub work_done_progress_options: WorkDoneProgressOptions,
+}
+
+#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct DocumentRangeFormattingOptions {
+ #[serde(flatten)]
+ pub work_done_progress_options: WorkDoneProgressOptions,
+}
+
+#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct DefinitionOptions {
+ #[serde(flatten)]
+ pub work_done_progress_options: WorkDoneProgressOptions,
+}
+
+#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct DocumentSymbolOptions {
+ /// A human-readable string that is shown when multiple outlines trees are
+ /// shown for the same document.
+ ///
+ /// @since 3.16.0
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub label: Option<String>,
+
+ #[serde(flatten)]
+ pub work_done_progress_options: WorkDoneProgressOptions,
+}
+
+#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct ReferencesOptions {
+ #[serde(flatten)]
+ pub work_done_progress_options: WorkDoneProgressOptions,
+}
+
+#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct DocumentHighlightOptions {
+ #[serde(flatten)]
+ pub work_done_progress_options: WorkDoneProgressOptions,
+}
+
+#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct WorkspaceSymbolOptions {
+ #[serde(flatten)]
+ pub work_done_progress_options: WorkDoneProgressOptions,
+
+ /// The server provides support to resolve additional
+ /// information for a workspace symbol.
+ ///
+ /// @since 3.17.0
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub resolve_provider: Option<bool>,
+}
+
+#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct StaticTextDocumentRegistrationOptions {
+ /// A document selector to identify the scope of the registration. If set to null
+ /// the document selector provided on the client side will be used.
+ pub document_selector: Option<DocumentSelector>,
+
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub id: Option<String>,
+}
+
+/// General parameters to unregister a capability.
+#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
+pub struct Unregistration {
+ /// The id used to unregister the request or notification. Usually an id
+ /// provided during the register request.
+ pub id: String,
+
+ /// The method / capability to unregister for.
+ pub method: String,
+}
+
+#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
+pub struct UnregistrationParams {
+ pub unregisterations: Vec<Unregistration>,
+}
+
+#[derive(Debug, PartialEq, Clone, Deserialize, Serialize)]
+pub struct DidChangeConfigurationParams {
+ /// The actual changed settings
+ pub settings: Value,
+}
+
+#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct DidOpenTextDocumentParams {
+ /// The document that was opened.
+ pub text_document: TextDocumentItem,
+}
+
+#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct DidChangeTextDocumentParams {
+ /// The document that did change. The version number points
+ /// to the version after all provided content changes have
+ /// been applied.
+ pub text_document: VersionedTextDocumentIdentifier,
+ /// The actual content changes.
+ pub content_changes: Vec<TextDocumentContentChangeEvent>,
+}
+
+/// An event describing a change to a text document. If range and rangeLength are omitted
+/// the new text is considered to be the full content of the document.
+#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct TextDocumentContentChangeEvent {
+ /// The range of the document that changed.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub range: Option<Range>,
+
+ /// The length of the range that got replaced.
+ ///
+ /// Deprecated: Use range instead
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub range_length: Option<u32>,
+
+ /// The new text of the document.
+ pub text: String,
+}
+
+/// Descibe options to be used when registered for text document change events.
+///
+/// Extends TextDocumentRegistrationOptions
+#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct TextDocumentChangeRegistrationOptions {
+ /// A document selector to identify the scope of the registration. If set to null
+ /// the document selector provided on the client side will be used.
+ pub document_selector: Option<DocumentSelector>,
+
+ /// How documents are synced to the server. See TextDocumentSyncKind.Full
+ /// and TextDocumentSyncKindIncremental.
+ pub sync_kind: i32,
+}
+
+/// The parameters send in a will save text document notification.
+#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct WillSaveTextDocumentParams {
+ /// The document that will be saved.
+ pub text_document: TextDocumentIdentifier,
+
+ /// The 'TextDocumentSaveReason'.
+ pub reason: TextDocumentSaveReason,
+}
+
+/// Represents reasons why a text document is saved.
+#[derive(Copy, Eq, PartialEq, Clone, Deserialize, Serialize)]
+#[serde(transparent)]
+pub struct TextDocumentSaveReason(i32);
+lsp_enum! {
+impl TextDocumentSaveReason {
+ /// Manually triggered, e.g. by the user pressing save, by starting debugging,
+ /// or by an API call.
+ pub const MANUAL: TextDocumentSaveReason = TextDocumentSaveReason(1);
+
+ /// Automatic after a delay.
+ pub const AFTER_DELAY: TextDocumentSaveReason = TextDocumentSaveReason(2);
+
+ /// When the editor lost focus.
+ pub const FOCUS_OUT: TextDocumentSaveReason = TextDocumentSaveReason(3);
+}
+}
+
+#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct DidCloseTextDocumentParams {
+ /// The document that was closed.
+ pub text_document: TextDocumentIdentifier,
+}
+
+#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct DidSaveTextDocumentParams {
+ /// The document that was saved.
+ pub text_document: TextDocumentIdentifier,
+
+ /// Optional the content when saved. Depends on the includeText value
+ /// when the save notification was requested.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub text: Option<String>,
+}
+
+#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct TextDocumentSaveRegistrationOptions {
+ /// The client is supposed to include the content on save.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub include_text: Option<bool>,
+
+ #[serde(flatten)]
+ pub text_document_registration_options: TextDocumentRegistrationOptions,
+}
+
+#[derive(Debug, Eq, PartialEq, Clone, Copy, Default, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct DidChangeWatchedFilesClientCapabilities {
+ /// Did change watched files notification supports dynamic registration.
+ /// Please note that the current protocol doesn't support static
+ /// configuration for file changes from the server side.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub dynamic_registration: Option<bool>,
+
+ /// Whether the client has support for relative patterns
+ /// or not.
+ ///
+ /// @since 3.17.0
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub relative_pattern_support: Option<bool>,
+}
+
+#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
+pub struct DidChangeWatchedFilesParams {
+ /// The actual file events.
+ pub changes: Vec<FileEvent>,
+}
+
+/// The file event type.
+#[derive(Eq, PartialEq, Hash, Copy, Clone, Deserialize, Serialize)]
+#[serde(transparent)]
+pub struct FileChangeType(i32);
+lsp_enum! {
+impl FileChangeType {
+ /// The file got created.
+ pub const CREATED: FileChangeType = FileChangeType(1);
+
+ /// The file got changed.
+ pub const CHANGED: FileChangeType = FileChangeType(2);
+
+ /// The file got deleted.
+ pub const DELETED: FileChangeType = FileChangeType(3);
+}
+}
+
+/// An event describing a file change.
+#[derive(Debug, Eq, Hash, PartialEq, Clone, Deserialize, Serialize)]
+pub struct FileEvent {
+ /// The file's URI.
+ pub uri: Url,
+
+ /// The change type.
+ #[serde(rename = "type")]
+ pub typ: FileChangeType,
+}
+
+impl FileEvent {
+ pub fn new(uri: Url, typ: FileChangeType) -> FileEvent {
+ FileEvent { uri, typ }
+ }
+}
+
+/// Describe options to be used when registered for text document change events.
+#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Deserialize, Serialize)]
+pub struct DidChangeWatchedFilesRegistrationOptions {
+ /// The watchers to register.
+ pub watchers: Vec<FileSystemWatcher>,
+}
+
+#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct FileSystemWatcher {
+ /// The glob pattern to watch. See {@link GlobPattern glob pattern}
+ /// for more detail.
+ ///
+ /// @since 3.17.0 support for relative patterns.
+ pub glob_pattern: GlobPattern,
+
+ /// The kind of events of interest. If omitted it defaults to WatchKind.Create |
+ /// WatchKind.Change | WatchKind.Delete which is 7.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub kind: Option<WatchKind>,
+}
+
+/// The glob pattern. Either a string pattern or a relative pattern.
+///
+/// @since 3.17.0
+#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Deserialize, Serialize)]
+#[serde(untagged)]
+pub enum GlobPattern {
+ String(Pattern),
+ Relative(RelativePattern),
+}
+
+impl From<Pattern> for GlobPattern {
+ #[inline]
+ fn from(from: Pattern) -> Self {
+ Self::String(from)
+ }
+}
+
+impl From<RelativePattern> for GlobPattern {
+ #[inline]
+ fn from(from: RelativePattern) -> Self {
+ Self::Relative(from)
+ }
+}
+
+/// A relative pattern is a helper to construct glob patterns that are matched
+/// relatively to a base URI. The common value for a `baseUri` is a workspace
+/// folder root, but it can be another absolute URI as well.
+///
+/// @since 3.17.0
+#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct RelativePattern {
+ /// A workspace folder or a base URI to which this pattern will be matched
+ /// against relatively.
+ pub base_uri: OneOf<WorkspaceFolder, Url>,
+
+ /// The actual glob pattern.
+ pub pattern: Pattern,
+}
+
+/// The glob pattern to watch relative to the base path. Glob patterns can have
+/// the following syntax:
+/// - `*` to match one or more characters in a path segment
+/// - `?` to match on one character in a path segment
+/// - `**` to match any number of path segments, including none
+/// - `{}` to group conditions (e.g. `**​/*.{ts,js}` matches all TypeScript
+/// and JavaScript files)
+/// - `[]` to declare a range of characters to match in a path segment
+/// (e.g., `example.[0-9]` to match on `example.0`, `example.1`, …)
+/// - `[!...]` to negate a range of characters to match in a path segment
+/// (e.g., `example.[!0-9]` to match on `example.a`, `example.b`,
+/// but not `example.0`)
+///
+/// @since 3.17.0
+pub type Pattern = String;
+
+bitflags! {
+pub struct WatchKind: u8 {
+ /// Interested in create events.
+ const Create = 1;
+ /// Interested in change events
+ const Change = 2;
+ /// Interested in delete events
+ const Delete = 4;
+}
+}
+
+impl<'de> serde::Deserialize<'de> for WatchKind {
+ fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
+ where
+ D: serde::Deserializer<'de>,
+ {
+ let i = u8::deserialize(deserializer)?;
+ WatchKind::from_bits(i).ok_or_else(|| {
+ D::Error::invalid_value(de::Unexpected::Unsigned(u64::from(i)), &"Unknown flag")
+ })
+ }
+}
+
+impl serde::Serialize for WatchKind {
+ fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
+ where
+ S: serde::Serializer,
+ {
+ serializer.serialize_u8(self.bits())
+ }
+}
+
+#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
+pub struct PublishDiagnosticsParams {
+ /// The URI for which diagnostic information is reported.
+ pub uri: Url,
+
+ /// An array of diagnostic information items.
+ pub diagnostics: Vec<Diagnostic>,
+
+ /// Optional the version number of the document the diagnostics are published for.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub version: Option<i32>,
+}
+
+impl PublishDiagnosticsParams {
+ pub fn new(
+ uri: Url,
+ diagnostics: Vec<Diagnostic>,
+ version: Option<i32>,
+ ) -> PublishDiagnosticsParams {
+ PublishDiagnosticsParams {
+ uri,
+ diagnostics,
+ version,
+ }
+ }
+}
+
+#[derive(Debug, Eq, PartialEq, Deserialize, Serialize, Clone)]
+#[serde(untagged)]
+pub enum Documentation {
+ String(String),
+ MarkupContent(MarkupContent),
+}
+
+/// The marked string is rendered:
+/// - as markdown if it is represented as a string
+/// - as code block of the given langauge if it is represented as a pair of a language and a value
+///
+/// The pair of a language and a value is an equivalent to markdown:
+/// ```${language}
+/// ${value}
+/// ```
+#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
+#[serde(untagged)]
+pub enum MarkedString {
+ String(String),
+ LanguageString(LanguageString),
+}
+
+#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
+pub struct LanguageString {
+ pub language: String,
+ pub value: String,
+}
+
+impl MarkedString {
+ pub fn from_markdown(markdown: String) -> MarkedString {
+ MarkedString::String(markdown)
+ }
+
+ pub fn from_language_code(language: String, code_block: String) -> MarkedString {
+ MarkedString::LanguageString(LanguageString {
+ language,
+ value: code_block,
+ })
+ }
+}
+
+#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct GotoDefinitionParams {
+ #[serde(flatten)]
+ pub text_document_position_params: TextDocumentPositionParams,
+
+ #[serde(flatten)]
+ pub work_done_progress_params: WorkDoneProgressParams,
+
+ #[serde(flatten)]
+ pub partial_result_params: PartialResultParams,
+}
+
+/// GotoDefinition response can be single location, or multiple Locations or a link.
+#[derive(Debug, PartialEq, Serialize, Deserialize, Clone)]
+#[serde(untagged)]
+pub enum GotoDefinitionResponse {
+ Scalar(Location),
+ Array(Vec<Location>),
+ Link(Vec<LocationLink>),
+}
+
+impl From<Location> for GotoDefinitionResponse {
+ fn from(location: Location) -> Self {
+ GotoDefinitionResponse::Scalar(location)
+ }
+}
+
+impl From<Vec<Location>> for GotoDefinitionResponse {
+ fn from(locations: Vec<Location>) -> Self {
+ GotoDefinitionResponse::Array(locations)
+ }
+}
+
+impl From<Vec<LocationLink>> for GotoDefinitionResponse {
+ fn from(locations: Vec<LocationLink>) -> Self {
+ GotoDefinitionResponse::Link(locations)
+ }
+}
+
+#[derive(Debug, PartialEq, Clone, Default, Deserialize, Serialize)]
+pub struct ExecuteCommandParams {
+ /// The identifier of the actual command handler.
+ pub command: String,
+ /// Arguments that the command should be invoked with.
+ #[serde(default)]
+ pub arguments: Vec<Value>,
+
+ #[serde(flatten)]
+ pub work_done_progress_params: WorkDoneProgressParams,
+}
+
+/// Execute command registration options.
+#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
+pub struct ExecuteCommandRegistrationOptions {
+ /// The commands to be executed on the server
+ pub commands: Vec<String>,
+
+ #[serde(flatten)]
+ pub execute_command_options: ExecuteCommandOptions,
+}
+
+#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct ApplyWorkspaceEditParams {
+ /// An optional label of the workspace edit. This label is
+ /// presented in the user interface for example on an undo
+ /// stack to undo the workspace edit.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub label: Option<String>,
+
+ /// The edits to apply.
+ pub edit: WorkspaceEdit,
+}
+
+#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct ApplyWorkspaceEditResponse {
+ /// Indicates whether the edit was applied or not.
+ pub applied: bool,
+
+ /// An optional textual description for why the edit was not applied.
+ /// This may be used may be used by the server for diagnostic
+ /// logging or to provide a suitable error for a request that
+ /// triggered the edit
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub failure_reason: Option<String>,
+
+ /// Depending on the client's failure handling strategy `failedChange` might
+ /// contain the index of the change that failed. This property is only available
+ /// if the client signals a `failureHandlingStrategy` in its client capabilities.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub failed_change: Option<u32>,
+}
+
+/// Describes the content type that a client supports in various
+/// result literals like `Hover`, `ParameterInfo` or `CompletionItem`.
+///
+/// Please note that `MarkupKinds` must not start with a `$`. This kinds
+/// are reserved for internal usage.
+#[derive(Debug, Eq, PartialEq, Deserialize, Serialize, Clone)]
+#[serde(rename_all = "lowercase")]
+pub enum MarkupKind {
+ /// Plain text is supported as a content format
+ PlainText,
+ /// Markdown is supported as a content format
+ Markdown,
+}
+
+/// A `MarkupContent` literal represents a string value which content can be represented in different formats.
+/// Currently `plaintext` and `markdown` are supported formats. A `MarkupContent` is usually used in
+/// documentation properties of result literals like `CompletionItem` or `SignatureInformation`.
+/// If the format is `markdown` the content should follow the [GitHub Flavored Markdown Specification](https://github.github.com/gfm/).
+///
+/// Here is an example how such a string can be constructed using JavaScript / TypeScript:
+/// ```ignore
+/// let markdown: MarkupContent = {
+/// kind: MarkupKind::Markdown,
+/// value: [
+/// "# Header",
+/// "Some text",
+/// "```typescript",
+/// "someCode();",
+/// "```"
+/// ]
+/// .join("\n"),
+/// };
+/// ```
+///
+/// Please Note* that clients might sanitize the return markdown. A client could decide to
+/// remove HTML from the markdown to avoid script execution.
+#[derive(Debug, Eq, PartialEq, Deserialize, Serialize, Clone)]
+pub struct MarkupContent {
+ pub kind: MarkupKind,
+ pub value: String,
+}
+
+/// A parameter literal used to pass a partial result token.
+#[derive(Debug, Eq, PartialEq, Default, Deserialize, Serialize, Clone)]
+#[serde(rename_all = "camelCase")]
+pub struct PartialResultParams {
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub partial_result_token: Option<ProgressToken>,
+}
+
+/// Symbol tags are extra annotations that tweak the rendering of a symbol.
+/// Since 3.15
+#[derive(Eq, PartialEq, Clone, Deserialize, Serialize)]
+#[serde(transparent)]
+pub struct SymbolTag(i32);
+lsp_enum! {
+impl SymbolTag {
+ /// Render a symbol as obsolete, usually using a strike-out.
+ pub const DEPRECATED: SymbolTag = SymbolTag(1);
+}
+}
+
+#[cfg(test)]
+mod tests {
+ use serde::{Deserialize, Serialize};
+
+ use super::*;
+
+ pub(crate) fn test_serialization<SER>(ms: &SER, expected: &str)
+ where
+ SER: Serialize + for<'de> Deserialize<'de> + PartialEq + std::fmt::Debug,
+ {
+ let json_str = serde_json::to_string(ms).unwrap();
+ assert_eq!(&json_str, expected);
+ let deserialized: SER = serde_json::from_str(&json_str).unwrap();
+ assert_eq!(&deserialized, ms);
+ }
+
+ pub(crate) fn test_deserialization<T>(json: &str, expected: &T)
+ where
+ T: for<'de> Deserialize<'de> + PartialEq + std::fmt::Debug,
+ {
+ let value = serde_json::from_str::<T>(json).unwrap();
+ assert_eq!(&value, expected);
+ }
+
+ #[test]
+ fn one_of() {
+ test_serialization(&OneOf::<bool, ()>::Left(true), r#"true"#);
+ test_serialization(&OneOf::<String, ()>::Left("abcd".into()), r#""abcd""#);
+ test_serialization(
+ &OneOf::<String, WorkDoneProgressOptions>::Right(WorkDoneProgressOptions {
+ work_done_progress: Some(false),
+ }),
+ r#"{"workDoneProgress":false}"#,
+ );
+ }
+
+ #[test]
+ fn number_or_string() {
+ test_serialization(&NumberOrString::Number(123), r#"123"#);
+
+ test_serialization(&NumberOrString::String("abcd".into()), r#""abcd""#);
+ }
+
+ #[test]
+ fn marked_string() {
+ test_serialization(&MarkedString::from_markdown("xxx".into()), r#""xxx""#);
+
+ test_serialization(
+ &MarkedString::from_language_code("lang".into(), "code".into()),
+ r#"{"language":"lang","value":"code"}"#,
+ );
+ }
+
+ #[test]
+ fn language_string() {
+ test_serialization(
+ &LanguageString {
+ language: "LL".into(),
+ value: "VV".into(),
+ },
+ r#"{"language":"LL","value":"VV"}"#,
+ );
+ }
+
+ #[test]
+ fn workspace_edit() {
+ test_serialization(
+ &WorkspaceEdit {
+ changes: Some(vec![].into_iter().collect()),
+ document_changes: None,
+ ..Default::default()
+ },
+ r#"{"changes":{}}"#,
+ );
+
+ test_serialization(
+ &WorkspaceEdit {
+ changes: None,
+ document_changes: None,
+ ..Default::default()
+ },
+ r#"{}"#,
+ );
+
+ test_serialization(
+ &WorkspaceEdit {
+ changes: Some(
+ vec![(Url::parse("file://test").unwrap(), vec![])]
+ .into_iter()
+ .collect(),
+ ),
+ document_changes: None,
+ ..Default::default()
+ },
+ r#"{"changes":{"file://test/":[]}}"#,
+ );
+ }
+
+ #[test]
+ fn root_uri_can_be_missing() {
+ serde_json::from_str::<InitializeParams>(r#"{ "capabilities": {} }"#).unwrap();
+ }
+
+ #[test]
+ fn test_watch_kind() {
+ test_serialization(&WatchKind::Create, "1");
+ test_serialization(&(WatchKind::Create | WatchKind::Change), "3");
+ test_serialization(
+ &(WatchKind::Create | WatchKind::Change | WatchKind::Delete),
+ "7",
+ );
+ }
+
+ #[test]
+ fn test_resource_operation_kind() {
+ test_serialization(
+ &vec![
+ ResourceOperationKind::Create,
+ ResourceOperationKind::Rename,
+ ResourceOperationKind::Delete,
+ ],
+ r#"["create","rename","delete"]"#,
+ );
+ }
+}
diff --git a/vendor/lsp-types/src/linked_editing.rs b/vendor/lsp-types/src/linked_editing.rs
index b23fb141f..615ca5a24 100644
--- a/vendor/lsp-types/src/linked_editing.rs
+++ b/vendor/lsp-types/src/linked_editing.rs
@@ -1,61 +1,61 @@
-use serde::{Deserialize, Serialize};
-
-use crate::{
- DynamicRegistrationClientCapabilities, Range, StaticRegistrationOptions,
- TextDocumentPositionParams, TextDocumentRegistrationOptions, WorkDoneProgressOptions,
- WorkDoneProgressParams,
-};
-
-pub type LinkedEditingRangeClientCapabilities = DynamicRegistrationClientCapabilities;
-
-#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
-#[serde(rename_all = "camelCase")]
-pub struct LinkedEditingRangeOptions {
- #[serde(flatten)]
- pub work_done_progress_options: WorkDoneProgressOptions,
-}
-
-#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
-#[serde(rename_all = "camelCase")]
-pub struct LinkedEditingRangeRegistrationOptions {
- #[serde(flatten)]
- pub text_document_registration_options: TextDocumentRegistrationOptions,
-
- #[serde(flatten)]
- pub linked_editing_range_options: LinkedEditingRangeOptions,
-
- #[serde(flatten)]
- pub static_registration_options: StaticRegistrationOptions,
-}
-
-#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
-#[serde(untagged)]
-pub enum LinkedEditingRangeServerCapabilities {
- Simple(bool),
- Options(LinkedEditingRangeOptions),
- RegistrationOptions(LinkedEditingRangeRegistrationOptions),
-}
-
-#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
-#[serde(rename_all = "camelCase")]
-pub struct LinkedEditingRangeParams {
- #[serde(flatten)]
- pub text_document_position_params: TextDocumentPositionParams,
-
- #[serde(flatten)]
- pub work_done_progress_params: WorkDoneProgressParams,
-}
-
-#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
-#[serde(rename_all = "camelCase")]
-pub struct LinkedEditingRanges {
- /// A list of ranges that can be renamed together. The ranges must have
- /// identical length and contain identical text content. The ranges cannot overlap.
- pub ranges: Vec<Range>,
-
- /// An optional word pattern (regular expression) that describes valid contents for
- /// the given ranges. If no pattern is provided, the client configuration's word
- /// pattern will be used.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub word_pattern: Option<String>,
-}
+use serde::{Deserialize, Serialize};
+
+use crate::{
+ DynamicRegistrationClientCapabilities, Range, StaticRegistrationOptions,
+ TextDocumentPositionParams, TextDocumentRegistrationOptions, WorkDoneProgressOptions,
+ WorkDoneProgressParams,
+};
+
+pub type LinkedEditingRangeClientCapabilities = DynamicRegistrationClientCapabilities;
+
+#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct LinkedEditingRangeOptions {
+ #[serde(flatten)]
+ pub work_done_progress_options: WorkDoneProgressOptions,
+}
+
+#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct LinkedEditingRangeRegistrationOptions {
+ #[serde(flatten)]
+ pub text_document_registration_options: TextDocumentRegistrationOptions,
+
+ #[serde(flatten)]
+ pub linked_editing_range_options: LinkedEditingRangeOptions,
+
+ #[serde(flatten)]
+ pub static_registration_options: StaticRegistrationOptions,
+}
+
+#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
+#[serde(untagged)]
+pub enum LinkedEditingRangeServerCapabilities {
+ Simple(bool),
+ Options(LinkedEditingRangeOptions),
+ RegistrationOptions(LinkedEditingRangeRegistrationOptions),
+}
+
+#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct LinkedEditingRangeParams {
+ #[serde(flatten)]
+ pub text_document_position_params: TextDocumentPositionParams,
+
+ #[serde(flatten)]
+ pub work_done_progress_params: WorkDoneProgressParams,
+}
+
+#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct LinkedEditingRanges {
+ /// A list of ranges that can be renamed together. The ranges must have
+ /// identical length and contain identical text content. The ranges cannot overlap.
+ pub ranges: Vec<Range>,
+
+ /// An optional word pattern (regular expression) that describes valid contents for
+ /// the given ranges. If no pattern is provided, the client configuration's word
+ /// pattern will be used.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub word_pattern: Option<String>,
+}
diff --git a/vendor/lsp-types/src/lsif.rs b/vendor/lsp-types/src/lsif.rs
index 164d4eb4a..a28256308 100644
--- a/vendor/lsp-types/src/lsif.rs
+++ b/vendor/lsp-types/src/lsif.rs
@@ -1,338 +1,338 @@
-//! Types of Language Server Index Format (LSIF). LSIF is a standard format
-//! for language servers or other programming tools to dump their knowledge
-//! about a workspace.
-//!
-//! Based on <https://microsoft.github.io/language-server-protocol/specifications/lsif/0.6.0/specification/>
-
-use serde::{Deserialize, Serialize};
-use crate::{Url, Range};
-
-pub type Id = crate::NumberOrString;
-
-#[derive(Debug, PartialEq, Serialize, Deserialize)]
-#[serde(untagged)]
-pub enum LocationOrRangeId {
- Location(crate::Location),
- RangeId(Id),
-}
-
-#[derive(Debug, PartialEq, Serialize, Deserialize)]
-#[serde(rename_all = "camelCase")]
-pub struct Entry {
- pub id: Id,
- #[serde(flatten)]
- pub data: Element,
-}
-
-#[derive(Debug, PartialEq, Serialize, Deserialize)]
-#[serde(rename_all = "camelCase")]
-#[serde(tag = "type")]
-pub enum Element {
- Vertex(Vertex),
- Edge(Edge),
-}
-
-#[derive(Debug, PartialEq, Serialize, Deserialize)]
-pub struct ToolInfo {
- pub name: String,
- #[serde(default = "Default::default")]
- #[serde(skip_serializing_if = "Vec::is_empty")]
- pub args: Vec<String>,
- #[serde(skip_serializing_if = "Option::is_none")]
- pub version: Option<String>,
-}
-
-#[derive(Debug, PartialEq, Serialize, Deserialize)]
-pub enum Encoding {
- /// Currently only 'utf-16' is supported due to the limitations in LSP.
- #[serde(rename = "utf-16")]
- Utf16,
-}
-
-#[derive(Debug, PartialEq, Serialize, Deserialize)]
-pub struct RangeBasedDocumentSymbol {
- pub id: Id,
- #[serde(default = "Default::default")]
- #[serde(skip_serializing_if = "Vec::is_empty")]
- pub children: Vec<RangeBasedDocumentSymbol>,
-}
-
-#[derive(Debug, PartialEq, Serialize, Deserialize)]
-#[serde(rename_all = "camelCase")]
-#[serde(untagged)]
-pub enum DocumentSymbolOrRangeBasedVec {
- DocumentSymbol(Vec<crate::DocumentSymbol>),
- RangeBased(Vec<RangeBasedDocumentSymbol>),
-}
-
-#[derive(Debug, PartialEq, Serialize, Deserialize)]
-#[serde(rename_all = "camelCase")]
-pub struct DefinitionTag {
- /// The text covered by the range
- text: String,
- /// The symbol kind.
- kind: crate::SymbolKind,
- /// Indicates if this symbol is deprecated.
- #[serde(default)]
- #[serde(skip_serializing_if = "std::ops::Not::not")]
- deprecated: bool,
- /// The full range of the definition not including leading/trailing whitespace but everything else, e.g comments and code.
- /// The range must be included in fullRange.
- full_range: Range,
- /// Optional detail information for the definition.
- #[serde(skip_serializing_if = "Option::is_none")]
- detail: Option<String>,
-}
-
-
-#[derive(Debug, PartialEq, Serialize, Deserialize)]
-#[serde(rename_all = "camelCase")]
-pub struct DeclarationTag {
- /// The text covered by the range
- text: String,
- /// The symbol kind.
- kind: crate::SymbolKind,
- /// Indicates if this symbol is deprecated.
- #[serde(default)]
- deprecated: bool,
- /// The full range of the definition not including leading/trailing whitespace but everything else, e.g comments and code.
- /// The range must be included in fullRange.
- full_range: Range,
- /// Optional detail information for the definition.
- #[serde(skip_serializing_if = "Option::is_none")]
- detail: Option<String>,
-}
-
-#[derive(Debug, PartialEq, Serialize, Deserialize)]
-#[serde(rename_all = "camelCase")]
-pub struct ReferenceTag {
- text: String,
-}
-
-#[derive(Debug, PartialEq, Serialize, Deserialize)]
-#[serde(rename_all = "camelCase")]
-pub struct UnknownTag {
- text: String,
-}
-
-#[derive(Debug, PartialEq, Serialize, Deserialize)]
-#[serde(rename_all = "camelCase")]
-#[serde(tag = "type")]
-pub enum RangeTag {
- Definition(DefinitionTag),
- Declaration(DeclarationTag),
- Reference(ReferenceTag),
- Unknown(UnknownTag),
-}
-
-#[derive(Debug, PartialEq, Serialize, Deserialize)]
-#[serde(rename_all = "camelCase")]
-#[serde(tag = "label")]
-pub enum Vertex {
- MetaData(MetaData),
- /// <https://github.com/Microsoft/language-server-protocol/blob/master/indexFormat/specification.md#the-project-vertex>
- Project(Project),
- Document(Document),
- /// <https://github.com/Microsoft/language-server-protocol/blob/master/indexFormat/specification.md#ranges>
- Range {
- #[serde(flatten)]
- range: Range,
- #[serde(skip_serializing_if = "Option::is_none")]
- tag: Option<RangeTag>,
- },
- /// <https://github.com/Microsoft/language-server-protocol/blob/master/indexFormat/specification.md#result-set>
- ResultSet(ResultSet),
- Moniker(crate::Moniker),
- PackageInformation(PackageInformation),
-
- #[serde(rename = "$event")]
- Event(Event),
-
- DefinitionResult,
- DeclarationResult,
- TypeDefinitionResult,
- ReferenceResult,
- ImplementationResult,
- FoldingRangeResult {
- result: Vec<crate::FoldingRange>,
- },
- HoverResult {
- result: crate::Hover,
- },
- DocumentSymbolResult {
- result: DocumentSymbolOrRangeBasedVec,
- },
- DocumentLinkResult {
- result: Vec<crate::DocumentLink>,
- },
- DiagnosticResult {
- result: Vec<crate::Diagnostic>,
- },
-}
-
-#[derive(Debug, PartialEq, Serialize, Deserialize)]
-#[serde(rename_all = "camelCase")]
-pub enum EventKind {
- Begin,
- End,
-}
-
-#[derive(Debug, PartialEq, Serialize, Deserialize)]
-#[serde(rename_all = "camelCase")]
-pub enum EventScope {
- Document,
- Project,
-}
-
-
-#[derive(Debug, PartialEq, Serialize, Deserialize)]
-pub struct Event {
- pub kind: EventKind,
- pub scope: EventScope,
- pub data: Id,
-}
-
-#[derive(Debug, PartialEq, Serialize, Deserialize)]
-#[serde(rename_all = "camelCase")]
-#[serde(tag = "label")]
-pub enum Edge {
- Contains(EdgeDataMultiIn),
- Moniker(EdgeData),
- NextMoniker(EdgeData),
- Next(EdgeData),
- PackageInformation(EdgeData),
- Item(Item),
-
- // Methods
- #[serde(rename = "textDocument/definition")]
- Definition(EdgeData),
- #[serde(rename = "textDocument/declaration")]
- Declaration(EdgeData),
- #[serde(rename = "textDocument/hover")]
- Hover(EdgeData),
- #[serde(rename = "textDocument/references")]
- References(EdgeData),
- #[serde(rename = "textDocument/implementation")]
- Implementation(EdgeData),
- #[serde(rename = "textDocument/typeDefinition")]
- TypeDefinition(EdgeData),
- #[serde(rename = "textDocument/foldingRange")]
- FoldingRange(EdgeData),
- #[serde(rename = "textDocument/documentLink")]
- DocumentLink(EdgeData),
- #[serde(rename = "textDocument/documentSymbol")]
- DocumentSymbol(EdgeData),
- #[serde(rename = "textDocument/diagnostic")]
- Diagnostic(EdgeData),
-}
-
-#[derive(Debug, PartialEq, Serialize, Deserialize)]
-#[serde(rename_all = "camelCase")]
-pub struct EdgeData {
- pub in_v: Id,
- pub out_v: Id,
-}
-
-#[derive(Debug, PartialEq, Serialize, Deserialize)]
-#[serde(rename_all = "camelCase")]
-pub struct EdgeDataMultiIn {
- pub in_vs: Vec<Id>,
- pub out_v: Id,
-}
-
-#[derive(Debug, PartialEq, Serialize, Deserialize)]
-#[serde(untagged)]
-pub enum DefinitionResultType {
- Scalar(LocationOrRangeId),
- Array(LocationOrRangeId),
-}
-
-#[derive(Debug, PartialEq, Serialize, Deserialize)]
-#[serde(rename_all = "camelCase")]
-pub enum ItemKind {
- Declarations,
- Definitions,
- References,
- ReferenceResults,
- ImplementationResults,
-}
-
-#[derive(Debug, PartialEq, Serialize, Deserialize)]
-#[serde(rename_all = "camelCase")]
-pub struct Item {
- pub document: Id,
- #[serde(skip_serializing_if = "Option::is_none")]
- pub property: Option<ItemKind>,
- #[serde(flatten)]
- pub edge_data: EdgeDataMultiIn,
-}
-
-#[derive(Debug, PartialEq, Serialize, Deserialize)]
-#[serde(rename_all = "camelCase")]
-pub struct Document {
- pub uri: Url,
- pub language_id: String,
-}
-
-/// <https://github.com/Microsoft/language-server-protocol/blob/master/indexFormat/specification.md#result-set>
-#[derive(Debug, PartialEq, Serialize, Deserialize)]
-#[serde(rename_all = "camelCase")]
-pub struct ResultSet {
- #[serde(skip_serializing_if = "Option::is_none")]
- pub key: Option<String>,
-}
-
-/// <https://github.com/Microsoft/language-server-protocol/blob/master/indexFormat/specification.md#the-project-vertex>
-#[derive(Debug, PartialEq, Serialize, Deserialize)]
-#[serde(rename_all = "camelCase")]
-pub struct Project {
- #[serde(skip_serializing_if = "Option::is_none")]
- pub resource: Option<Url>,
- #[serde(skip_serializing_if = "Option::is_none")]
- pub content: Option<String>,
- pub kind: String,
-}
-
-#[derive(Debug, PartialEq, Serialize, Deserialize)]
-#[serde(rename_all = "camelCase")]
-pub struct MetaData {
- /// The version of the LSIF format using semver notation. See <https://semver.org/>. Please note
- /// the version numbers starting with 0 don't adhere to semver and adopters have to assume
- /// that each new version is breaking.
- pub version: String,
-
- /// The project root (in form of an URI) used to compute this dump.
- pub project_root: Url,
-
- /// The string encoding used to compute line and character values in
- /// positions and ranges.
- pub position_encoding: Encoding,
-
- /// Information about the tool that created the dump
- #[serde(skip_serializing_if = "Option::is_none")]
- pub tool_info: Option<ToolInfo>,
-}
-
-#[derive(Debug, PartialEq, Serialize, Deserialize)]
-#[serde(rename_all = "camelCase")]
-pub struct Repository {
- pub r#type: String,
- pub url: String,
- #[serde(skip_serializing_if = "Option::is_none")]
- pub commit_id: Option<String>,
-}
-
-#[derive(Debug, PartialEq, Serialize, Deserialize)]
-#[serde(rename_all = "camelCase")]
-pub struct PackageInformation {
- pub name: String,
- pub manager: String,
- #[serde(skip_serializing_if = "Option::is_none")]
- pub uri: Option<Url>,
- #[serde(skip_serializing_if = "Option::is_none")]
- pub content: Option<String>,
- #[serde(skip_serializing_if = "Option::is_none")]
- pub repository: Option<Repository>,
- #[serde(skip_serializing_if = "Option::is_none")]
- pub version: Option<String>,
-}
+//! Types of Language Server Index Format (LSIF). LSIF is a standard format
+//! for language servers or other programming tools to dump their knowledge
+//! about a workspace.
+//!
+//! Based on <https://microsoft.github.io/language-server-protocol/specifications/lsif/0.6.0/specification/>
+
+use serde::{Deserialize, Serialize};
+use crate::{Url, Range};
+
+pub type Id = crate::NumberOrString;
+
+#[derive(Debug, PartialEq, Serialize, Deserialize)]
+#[serde(untagged)]
+pub enum LocationOrRangeId {
+ Location(crate::Location),
+ RangeId(Id),
+}
+
+#[derive(Debug, PartialEq, Serialize, Deserialize)]
+#[serde(rename_all = "camelCase")]
+pub struct Entry {
+ pub id: Id,
+ #[serde(flatten)]
+ pub data: Element,
+}
+
+#[derive(Debug, PartialEq, Serialize, Deserialize)]
+#[serde(rename_all = "camelCase")]
+#[serde(tag = "type")]
+pub enum Element {
+ Vertex(Vertex),
+ Edge(Edge),
+}
+
+#[derive(Debug, PartialEq, Serialize, Deserialize)]
+pub struct ToolInfo {
+ pub name: String,
+ #[serde(default = "Default::default")]
+ #[serde(skip_serializing_if = "Vec::is_empty")]
+ pub args: Vec<String>,
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub version: Option<String>,
+}
+
+#[derive(Debug, PartialEq, Serialize, Deserialize)]
+pub enum Encoding {
+ /// Currently only 'utf-16' is supported due to the limitations in LSP.
+ #[serde(rename = "utf-16")]
+ Utf16,
+}
+
+#[derive(Debug, PartialEq, Serialize, Deserialize)]
+pub struct RangeBasedDocumentSymbol {
+ pub id: Id,
+ #[serde(default = "Default::default")]
+ #[serde(skip_serializing_if = "Vec::is_empty")]
+ pub children: Vec<RangeBasedDocumentSymbol>,
+}
+
+#[derive(Debug, PartialEq, Serialize, Deserialize)]
+#[serde(rename_all = "camelCase")]
+#[serde(untagged)]
+pub enum DocumentSymbolOrRangeBasedVec {
+ DocumentSymbol(Vec<crate::DocumentSymbol>),
+ RangeBased(Vec<RangeBasedDocumentSymbol>),
+}
+
+#[derive(Debug, PartialEq, Serialize, Deserialize)]
+#[serde(rename_all = "camelCase")]
+pub struct DefinitionTag {
+ /// The text covered by the range
+ text: String,
+ /// The symbol kind.
+ kind: crate::SymbolKind,
+ /// Indicates if this symbol is deprecated.
+ #[serde(default)]
+ #[serde(skip_serializing_if = "std::ops::Not::not")]
+ deprecated: bool,
+ /// The full range of the definition not including leading/trailing whitespace but everything else, e.g comments and code.
+ /// The range must be included in fullRange.
+ full_range: Range,
+ /// Optional detail information for the definition.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ detail: Option<String>,
+}
+
+
+#[derive(Debug, PartialEq, Serialize, Deserialize)]
+#[serde(rename_all = "camelCase")]
+pub struct DeclarationTag {
+ /// The text covered by the range
+ text: String,
+ /// The symbol kind.
+ kind: crate::SymbolKind,
+ /// Indicates if this symbol is deprecated.
+ #[serde(default)]
+ deprecated: bool,
+ /// The full range of the definition not including leading/trailing whitespace but everything else, e.g comments and code.
+ /// The range must be included in fullRange.
+ full_range: Range,
+ /// Optional detail information for the definition.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ detail: Option<String>,
+}
+
+#[derive(Debug, PartialEq, Serialize, Deserialize)]
+#[serde(rename_all = "camelCase")]
+pub struct ReferenceTag {
+ text: String,
+}
+
+#[derive(Debug, PartialEq, Serialize, Deserialize)]
+#[serde(rename_all = "camelCase")]
+pub struct UnknownTag {
+ text: String,
+}
+
+#[derive(Debug, PartialEq, Serialize, Deserialize)]
+#[serde(rename_all = "camelCase")]
+#[serde(tag = "type")]
+pub enum RangeTag {
+ Definition(DefinitionTag),
+ Declaration(DeclarationTag),
+ Reference(ReferenceTag),
+ Unknown(UnknownTag),
+}
+
+#[derive(Debug, PartialEq, Serialize, Deserialize)]
+#[serde(rename_all = "camelCase")]
+#[serde(tag = "label")]
+pub enum Vertex {
+ MetaData(MetaData),
+ /// <https://github.com/Microsoft/language-server-protocol/blob/master/indexFormat/specification.md#the-project-vertex>
+ Project(Project),
+ Document(Document),
+ /// <https://github.com/Microsoft/language-server-protocol/blob/master/indexFormat/specification.md#ranges>
+ Range {
+ #[serde(flatten)]
+ range: Range,
+ #[serde(skip_serializing_if = "Option::is_none")]
+ tag: Option<RangeTag>,
+ },
+ /// <https://github.com/Microsoft/language-server-protocol/blob/master/indexFormat/specification.md#result-set>
+ ResultSet(ResultSet),
+ Moniker(crate::Moniker),
+ PackageInformation(PackageInformation),
+
+ #[serde(rename = "$event")]
+ Event(Event),
+
+ DefinitionResult,
+ DeclarationResult,
+ TypeDefinitionResult,
+ ReferenceResult,
+ ImplementationResult,
+ FoldingRangeResult {
+ result: Vec<crate::FoldingRange>,
+ },
+ HoverResult {
+ result: crate::Hover,
+ },
+ DocumentSymbolResult {
+ result: DocumentSymbolOrRangeBasedVec,
+ },
+ DocumentLinkResult {
+ result: Vec<crate::DocumentLink>,
+ },
+ DiagnosticResult {
+ result: Vec<crate::Diagnostic>,
+ },
+}
+
+#[derive(Debug, PartialEq, Serialize, Deserialize)]
+#[serde(rename_all = "camelCase")]
+pub enum EventKind {
+ Begin,
+ End,
+}
+
+#[derive(Debug, PartialEq, Serialize, Deserialize)]
+#[serde(rename_all = "camelCase")]
+pub enum EventScope {
+ Document,
+ Project,
+}
+
+
+#[derive(Debug, PartialEq, Serialize, Deserialize)]
+pub struct Event {
+ pub kind: EventKind,
+ pub scope: EventScope,
+ pub data: Id,
+}
+
+#[derive(Debug, PartialEq, Serialize, Deserialize)]
+#[serde(rename_all = "camelCase")]
+#[serde(tag = "label")]
+pub enum Edge {
+ Contains(EdgeDataMultiIn),
+ Moniker(EdgeData),
+ NextMoniker(EdgeData),
+ Next(EdgeData),
+ PackageInformation(EdgeData),
+ Item(Item),
+
+ // Methods
+ #[serde(rename = "textDocument/definition")]
+ Definition(EdgeData),
+ #[serde(rename = "textDocument/declaration")]
+ Declaration(EdgeData),
+ #[serde(rename = "textDocument/hover")]
+ Hover(EdgeData),
+ #[serde(rename = "textDocument/references")]
+ References(EdgeData),
+ #[serde(rename = "textDocument/implementation")]
+ Implementation(EdgeData),
+ #[serde(rename = "textDocument/typeDefinition")]
+ TypeDefinition(EdgeData),
+ #[serde(rename = "textDocument/foldingRange")]
+ FoldingRange(EdgeData),
+ #[serde(rename = "textDocument/documentLink")]
+ DocumentLink(EdgeData),
+ #[serde(rename = "textDocument/documentSymbol")]
+ DocumentSymbol(EdgeData),
+ #[serde(rename = "textDocument/diagnostic")]
+ Diagnostic(EdgeData),
+}
+
+#[derive(Debug, PartialEq, Serialize, Deserialize)]
+#[serde(rename_all = "camelCase")]
+pub struct EdgeData {
+ pub in_v: Id,
+ pub out_v: Id,
+}
+
+#[derive(Debug, PartialEq, Serialize, Deserialize)]
+#[serde(rename_all = "camelCase")]
+pub struct EdgeDataMultiIn {
+ pub in_vs: Vec<Id>,
+ pub out_v: Id,
+}
+
+#[derive(Debug, PartialEq, Serialize, Deserialize)]
+#[serde(untagged)]
+pub enum DefinitionResultType {
+ Scalar(LocationOrRangeId),
+ Array(LocationOrRangeId),
+}
+
+#[derive(Debug, PartialEq, Serialize, Deserialize)]
+#[serde(rename_all = "camelCase")]
+pub enum ItemKind {
+ Declarations,
+ Definitions,
+ References,
+ ReferenceResults,
+ ImplementationResults,
+}
+
+#[derive(Debug, PartialEq, Serialize, Deserialize)]
+#[serde(rename_all = "camelCase")]
+pub struct Item {
+ pub document: Id,
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub property: Option<ItemKind>,
+ #[serde(flatten)]
+ pub edge_data: EdgeDataMultiIn,
+}
+
+#[derive(Debug, PartialEq, Serialize, Deserialize)]
+#[serde(rename_all = "camelCase")]
+pub struct Document {
+ pub uri: Url,
+ pub language_id: String,
+}
+
+/// <https://github.com/Microsoft/language-server-protocol/blob/master/indexFormat/specification.md#result-set>
+#[derive(Debug, PartialEq, Serialize, Deserialize)]
+#[serde(rename_all = "camelCase")]
+pub struct ResultSet {
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub key: Option<String>,
+}
+
+/// <https://github.com/Microsoft/language-server-protocol/blob/master/indexFormat/specification.md#the-project-vertex>
+#[derive(Debug, PartialEq, Serialize, Deserialize)]
+#[serde(rename_all = "camelCase")]
+pub struct Project {
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub resource: Option<Url>,
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub content: Option<String>,
+ pub kind: String,
+}
+
+#[derive(Debug, PartialEq, Serialize, Deserialize)]
+#[serde(rename_all = "camelCase")]
+pub struct MetaData {
+ /// The version of the LSIF format using semver notation. See <https://semver.org/>. Please note
+ /// the version numbers starting with 0 don't adhere to semver and adopters have to assume
+ /// that each new version is breaking.
+ pub version: String,
+
+ /// The project root (in form of an URI) used to compute this dump.
+ pub project_root: Url,
+
+ /// The string encoding used to compute line and character values in
+ /// positions and ranges.
+ pub position_encoding: Encoding,
+
+ /// Information about the tool that created the dump
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub tool_info: Option<ToolInfo>,
+}
+
+#[derive(Debug, PartialEq, Serialize, Deserialize)]
+#[serde(rename_all = "camelCase")]
+pub struct Repository {
+ pub r#type: String,
+ pub url: String,
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub commit_id: Option<String>,
+}
+
+#[derive(Debug, PartialEq, Serialize, Deserialize)]
+#[serde(rename_all = "camelCase")]
+pub struct PackageInformation {
+ pub name: String,
+ pub manager: String,
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub uri: Option<Url>,
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub content: Option<String>,
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub repository: Option<Repository>,
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub version: Option<String>,
+}
diff --git a/vendor/lsp-types/src/moniker.rs b/vendor/lsp-types/src/moniker.rs
index 74bf89553..5a888bc5d 100644
--- a/vendor/lsp-types/src/moniker.rs
+++ b/vendor/lsp-types/src/moniker.rs
@@ -1,92 +1,92 @@
-use serde::{Deserialize, Serialize};
-
-use crate::{
- DynamicRegistrationClientCapabilities, PartialResultParams, TextDocumentPositionParams,
- TextDocumentRegistrationOptions, WorkDoneProgressOptions, WorkDoneProgressParams,
-};
-
-pub type MonikerClientCapabilities = DynamicRegistrationClientCapabilities;
-
-#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
-#[serde(untagged)]
-pub enum MonikerServerCapabilities {
- Options(MonikerOptions),
- RegistrationOptions(MonikerRegistrationOptions),
-}
-
-#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
-pub struct MonikerOptions {
- #[serde(flatten)]
- pub work_done_progress_options: WorkDoneProgressOptions,
-}
-
-#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
-#[serde(rename_all = "camelCase")]
-pub struct MonikerRegistrationOptions {
- #[serde(flatten)]
- pub text_document_registration_options: TextDocumentRegistrationOptions,
-
- #[serde(flatten)]
- pub moniker_options: MonikerOptions,
-}
-
-/// Moniker uniqueness level to define scope of the moniker.
-#[derive(Debug, Eq, PartialEq, Deserialize, Serialize, Copy, Clone)]
-#[serde(rename_all = "camelCase")]
-pub enum UniquenessLevel {
- /// The moniker is only unique inside a document
- Document,
- /// The moniker is unique inside a project for which a dump got created
- Project,
- /// The moniker is unique inside the group to which a project belongs
- Group,
- /// The moniker is unique inside the moniker scheme.
- Scheme,
- /// The moniker is globally unique
- Global,
-}
-
-/// The moniker kind.
-#[derive(Debug, Eq, PartialEq, Deserialize, Serialize, Copy, Clone)]
-#[serde(rename_all = "camelCase")]
-pub enum MonikerKind {
- /// The moniker represent a symbol that is imported into a project
- Import,
- /// The moniker represent a symbol that is exported into a project
- Export,
- /// The moniker represents a symbol that is local to a project (e.g. a local
- /// variable of a function, a class not visible outside the project, ...)
- Local,
-}
-
-#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
-#[serde(rename_all = "camelCase")]
-pub struct MonikerParams {
- #[serde(flatten)]
- pub text_document_position_params: TextDocumentPositionParams,
-
- #[serde(flatten)]
- pub work_done_progress_params: WorkDoneProgressParams,
-
- #[serde(flatten)]
- pub partial_result_params: PartialResultParams,
-}
-
-/// Moniker definition to match LSIF 0.5 moniker definition.
-#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
-#[serde(rename_all = "camelCase")]
-pub struct Moniker {
- /// The scheme of the moniker. For example tsc or .Net
- pub scheme: String,
-
- /// The identifier of the moniker. The value is opaque in LSIF however
- /// schema owners are allowed to define the structure if they want.
- pub identifier: String,
-
- /// The scope in which the moniker is unique
- pub unique: UniquenessLevel,
-
- /// The moniker kind if known.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub kind: Option<MonikerKind>,
-}
+use serde::{Deserialize, Serialize};
+
+use crate::{
+ DynamicRegistrationClientCapabilities, PartialResultParams, TextDocumentPositionParams,
+ TextDocumentRegistrationOptions, WorkDoneProgressOptions, WorkDoneProgressParams,
+};
+
+pub type MonikerClientCapabilities = DynamicRegistrationClientCapabilities;
+
+#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
+#[serde(untagged)]
+pub enum MonikerServerCapabilities {
+ Options(MonikerOptions),
+ RegistrationOptions(MonikerRegistrationOptions),
+}
+
+#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
+pub struct MonikerOptions {
+ #[serde(flatten)]
+ pub work_done_progress_options: WorkDoneProgressOptions,
+}
+
+#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct MonikerRegistrationOptions {
+ #[serde(flatten)]
+ pub text_document_registration_options: TextDocumentRegistrationOptions,
+
+ #[serde(flatten)]
+ pub moniker_options: MonikerOptions,
+}
+
+/// Moniker uniqueness level to define scope of the moniker.
+#[derive(Debug, Eq, PartialEq, Deserialize, Serialize, Copy, Clone)]
+#[serde(rename_all = "camelCase")]
+pub enum UniquenessLevel {
+ /// The moniker is only unique inside a document
+ Document,
+ /// The moniker is unique inside a project for which a dump got created
+ Project,
+ /// The moniker is unique inside the group to which a project belongs
+ Group,
+ /// The moniker is unique inside the moniker scheme.
+ Scheme,
+ /// The moniker is globally unique
+ Global,
+}
+
+/// The moniker kind.
+#[derive(Debug, Eq, PartialEq, Deserialize, Serialize, Copy, Clone)]
+#[serde(rename_all = "camelCase")]
+pub enum MonikerKind {
+ /// The moniker represent a symbol that is imported into a project
+ Import,
+ /// The moniker represent a symbol that is exported into a project
+ Export,
+ /// The moniker represents a symbol that is local to a project (e.g. a local
+ /// variable of a function, a class not visible outside the project, ...)
+ Local,
+}
+
+#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct MonikerParams {
+ #[serde(flatten)]
+ pub text_document_position_params: TextDocumentPositionParams,
+
+ #[serde(flatten)]
+ pub work_done_progress_params: WorkDoneProgressParams,
+
+ #[serde(flatten)]
+ pub partial_result_params: PartialResultParams,
+}
+
+/// Moniker definition to match LSIF 0.5 moniker definition.
+#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct Moniker {
+ /// The scheme of the moniker. For example tsc or .Net
+ pub scheme: String,
+
+ /// The identifier of the moniker. The value is opaque in LSIF however
+ /// schema owners are allowed to define the structure if they want.
+ pub identifier: String,
+
+ /// The scope in which the moniker is unique
+ pub unique: UniquenessLevel,
+
+ /// The moniker kind if known.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub kind: Option<MonikerKind>,
+}
diff --git a/vendor/lsp-types/src/notification.rs b/vendor/lsp-types/src/notification.rs
index 6417707b8..53cfaea89 100644
--- a/vendor/lsp-types/src/notification.rs
+++ b/vendor/lsp-types/src/notification.rs
@@ -1,361 +1,361 @@
-use super::*;
-
-use serde::{de::DeserializeOwned, Serialize};
-
-pub trait Notification {
- type Params: DeserializeOwned + Serialize;
- const METHOD: &'static str;
-}
-
-#[macro_export]
-macro_rules! lsp_notification {
- ("$/cancelRequest") => {
- $crate::notification::Cancel
- };
- ("$/setTrace") => {
- $crate::notification::SetTrace
- };
- ("$/logTrace") => {
- $crate::notification::LogTrace
- };
- ("initialized") => {
- $crate::notification::Initialized
- };
- ("exit") => {
- $crate::notification::Exit
- };
-
- ("window/showMessage") => {
- $crate::notification::ShowMessage
- };
- ("window/logMessage") => {
- $crate::notification::LogMessage
- };
- ("window/workDoneProgress/cancel") => {
- $crate::notification::WorkDoneProgressCancel
- };
-
- ("telemetry/event") => {
- $crate::notification::TelemetryEvent
- };
-
- ("textDocument/didOpen") => {
- $crate::notification::DidOpenTextDocument
- };
- ("textDocument/didChange") => {
- $crate::notification::DidChangeTextDocument
- };
- ("textDocument/willSave") => {
- $crate::notification::WillSaveTextDocument
- };
- ("textDocument/didSave") => {
- $crate::notification::DidSaveTextDocument
- };
- ("textDocument/didClose") => {
- $crate::notification::DidCloseTextDocument
- };
- ("textDocument/publishDiagnostics") => {
- $crate::notification::PublishDiagnostics
- };
-
- ("workspace/didChangeConfiguration") => {
- $crate::notification::DidChangeConfiguration
- };
- ("workspace/didChangeWatchedFiles") => {
- $crate::notification::DidChangeWatchedFiles
- };
- ("workspace/didChangeWorkspaceFolders") => {
- $crate::notification::DidChangeWorkspaceFolders
- };
- ("$/progress") => {
- $crate::notification::Progress
- };
- ("workspace/didCreateFiles") => {
- $crate::notification::DidCreateFiles
- };
- ("workspace/didRenameFiles") => {
- $crate::notification::DidRenameFiles
- };
- ("workspace/didDeleteFiles") => {
- $crate::notification::DidDeleteFiles
- };
-}
-
-/// The base protocol now offers support for request cancellation. To cancel a request,
-/// a notification message with the following properties is sent:
-///
-/// A request that got canceled still needs to return from the server and send a response back.
-/// It can not be left open / hanging. This is in line with the JSON RPC protocol that requires
-/// that every request sends a response back. In addition it allows for returning partial results on cancel.
-#[derive(Debug)]
-pub enum Cancel {}
-
-impl Notification for Cancel {
- type Params = CancelParams;
- const METHOD: &'static str = "$/cancelRequest";
-}
-
-/// A notification that should be used by the client to modify the trace
-/// setting of the server.
-#[derive(Debug)]
-pub enum SetTrace {}
-
-impl Notification for SetTrace {
- type Params = SetTraceParams;
- const METHOD: &'static str = "$/setTrace";
-}
-
-/// A notification to log the trace of the server’s execution.
-/// The amount and content of these notifications depends on the current trace configuration.
-///
-/// `LogTrace` should be used for systematic trace reporting. For single debugging messages,
-/// the server should send `LogMessage` notifications.
-#[derive(Debug)]
-pub enum LogTrace {}
-
-impl Notification for LogTrace {
- type Params = LogTraceParams;
- const METHOD: &'static str = "$/logTrace";
-}
-
-/// The initialized notification is sent from the client to the server after the client received
-/// the result of the initialize request but before the client is sending any other request or
-/// notification to the server. The server can use the initialized notification for example to
-/// dynamically register capabilities.
-#[derive(Debug)]
-pub enum Initialized {}
-
-impl Notification for Initialized {
- type Params = InitializedParams;
- const METHOD: &'static str = "initialized";
-}
-
-/// A notification to ask the server to exit its process.
-/// The server should exit with success code 0 if the shutdown request has been received before;
-/// otherwise with error code 1.
-#[derive(Debug)]
-pub enum Exit {}
-
-impl Notification for Exit {
- type Params = ();
- const METHOD: &'static str = "exit";
-}
-
-/// The show message notification is sent from a server to a client to ask the client to display a particular message
-/// in the user interface.
-#[derive(Debug)]
-pub enum ShowMessage {}
-
-impl Notification for ShowMessage {
- type Params = ShowMessageParams;
- const METHOD: &'static str = "window/showMessage";
-}
-
-/// The log message notification is sent from the server to the client to ask the client to log a particular message.
-#[derive(Debug)]
-pub enum LogMessage {}
-
-impl Notification for LogMessage {
- type Params = LogMessageParams;
- const METHOD: &'static str = "window/logMessage";
-}
-
-/// The telemetry notification is sent from the server to the client to ask the client to log a telemetry event.
-/// The protocol doesn't specify the payload since no interpretation of the data happens in the protocol. Most clients even don't handle
-/// the event directly but forward them to the extensions owning the corresponding server issuing the event.
-#[derive(Debug)]
-pub enum TelemetryEvent {}
-
-impl Notification for TelemetryEvent {
- type Params = serde_json::Value;
- const METHOD: &'static str = "telemetry/event";
-}
-
-/// A notification sent from the client to the server to signal the change of configuration settings.
-#[derive(Debug)]
-pub enum DidChangeConfiguration {}
-
-impl Notification for DidChangeConfiguration {
- type Params = DidChangeConfigurationParams;
- const METHOD: &'static str = "workspace/didChangeConfiguration";
-}
-
-/// The document open notification is sent from the client to the server to signal newly opened text documents.
-/// The document's truth is now managed by the client and the server must not try to read the document's truth
-/// using the document's uri.
-#[derive(Debug)]
-pub enum DidOpenTextDocument {}
-
-impl Notification for DidOpenTextDocument {
- type Params = DidOpenTextDocumentParams;
- const METHOD: &'static str = "textDocument/didOpen";
-}
-
-/// The document change notification is sent from the client to the server to signal changes to a text document.
-/// In 2.0 the shape of the params has changed to include proper version numbers and language ids.
-#[derive(Debug)]
-pub enum DidChangeTextDocument {}
-
-impl Notification for DidChangeTextDocument {
- type Params = DidChangeTextDocumentParams;
- const METHOD: &'static str = "textDocument/didChange";
-}
-
-/// The document will save notification is sent from the client to the server before the document
-/// is actually saved.
-#[derive(Debug)]
-pub enum WillSaveTextDocument {}
-
-impl Notification for WillSaveTextDocument {
- type Params = WillSaveTextDocumentParams;
- const METHOD: &'static str = "textDocument/willSave";
-}
-
-/// The document close notification is sent from the client to the server when the document got closed in the client.
-/// The document's truth now exists where the document's uri points to (e.g. if the document's uri is a file uri
-/// the truth now exists on disk).
-#[derive(Debug)]
-pub enum DidCloseTextDocument {}
-
-impl Notification for DidCloseTextDocument {
- type Params = DidCloseTextDocumentParams;
- const METHOD: &'static str = "textDocument/didClose";
-}
-
-/// The document save notification is sent from the client to the server when the document was saved in the client.
-#[derive(Debug)]
-pub enum DidSaveTextDocument {}
-
-impl Notification for DidSaveTextDocument {
- type Params = DidSaveTextDocumentParams;
- const METHOD: &'static str = "textDocument/didSave";
-}
-
-/// The watched files notification is sent from the client to the server when the client detects changes to files and folders
-/// watched by the language client (note although the name suggest that only file events are sent it is about file system events which include folders as well).
-/// It is recommended that servers register for these file system events using the registration mechanism.
-/// In former implementations clients pushed file events without the server actively asking for it.
-#[derive(Debug)]
-pub enum DidChangeWatchedFiles {}
-
-impl Notification for DidChangeWatchedFiles {
- type Params = DidChangeWatchedFilesParams;
- const METHOD: &'static str = "workspace/didChangeWatchedFiles";
-}
-
-/// The workspace/didChangeWorkspaceFolders notification is sent from the client to the server to inform the server
-/// about workspace folder configuration changes
-#[derive(Debug)]
-pub enum DidChangeWorkspaceFolders {}
-
-impl Notification for DidChangeWorkspaceFolders {
- type Params = DidChangeWorkspaceFoldersParams;
- const METHOD: &'static str = "workspace/didChangeWorkspaceFolders";
-}
-
-/// Diagnostics notification are sent from the server to the client to signal results of validation runs.
-#[derive(Debug)]
-pub enum PublishDiagnostics {}
-
-impl Notification for PublishDiagnostics {
- type Params = PublishDiagnosticsParams;
- const METHOD: &'static str = "textDocument/publishDiagnostics";
-}
-
-/// The progress notification is sent from the server to the client to ask
-/// the client to indicate progress.
-#[derive(Debug)]
-pub enum Progress {}
-
-impl Notification for Progress {
- type Params = ProgressParams;
- const METHOD: &'static str = "$/progress";
-}
-
-/// The `window/workDoneProgress/cancel` notification is sent from the client
-/// to the server to cancel a progress initiated on the server side using the `window/workDoneProgress/create`.
-#[derive(Debug)]
-pub enum WorkDoneProgressCancel {}
-
-impl Notification for WorkDoneProgressCancel {
- type Params = WorkDoneProgressCancelParams;
- const METHOD: &'static str = "window/workDoneProgress/cancel";
-}
-
-/// The did create files notification is sent from the client to the server when files were created from within the client.
-#[derive(Debug)]
-pub enum DidCreateFiles {}
-
-impl Notification for DidCreateFiles {
- type Params = CreateFilesParams;
- const METHOD: &'static str = "workspace/didCreateFiles";
-}
-
-/// The did rename files notification is sent from the client to the server when files were renamed from within the client.
-#[derive(Debug)]
-pub enum DidRenameFiles {}
-
-impl Notification for DidRenameFiles {
- type Params = RenameFilesParams;
- const METHOD: &'static str = "workspace/didRenameFiles";
-}
-
-/// The did delete files notification is sent from the client to the server when files were deleted from within the client.
-#[derive(Debug)]
-pub enum DidDeleteFiles {}
-
-impl Notification for DidDeleteFiles {
- type Params = DeleteFilesParams;
- const METHOD: &'static str = "workspace/didDeleteFiles";
-}
-
-#[cfg(test)]
-mod test {
- use super::*;
-
- fn fake_call<N>()
- where
- N: Notification,
- N::Params: serde::Serialize,
- {
- }
-
- macro_rules! check_macro {
- ($name:tt) => {
- // check whether the macro name matches the method
- assert_eq!(<lsp_notification!($name) as Notification>::METHOD, $name);
- // test whether type checking passes for each component
- fake_call::<lsp_notification!($name)>();
- };
- }
-
- #[test]
- fn check_macro_definitions() {
- check_macro!("$/cancelRequest");
- check_macro!("$/progress");
- check_macro!("$/logTrace");
- check_macro!("$/setTrace");
- check_macro!("initialized");
- check_macro!("exit");
- check_macro!("window/showMessage");
- check_macro!("window/logMessage");
- check_macro!("window/workDoneProgress/cancel");
- check_macro!("telemetry/event");
- check_macro!("textDocument/didOpen");
- check_macro!("textDocument/didChange");
- check_macro!("textDocument/willSave");
- check_macro!("textDocument/didSave");
- check_macro!("textDocument/didClose");
- check_macro!("textDocument/publishDiagnostics");
- check_macro!("workspace/didChangeConfiguration");
- check_macro!("workspace/didChangeWatchedFiles");
- check_macro!("workspace/didChangeWorkspaceFolders");
- check_macro!("workspace/didCreateFiles");
- check_macro!("workspace/didRenameFiles");
- check_macro!("workspace/didDeleteFiles");
- }
-
- #[test]
- #[cfg(feature = "proposed")]
- fn check_proposed_macro_definitions() {}
-}
+use super::*;
+
+use serde::{de::DeserializeOwned, Serialize};
+
+pub trait Notification {
+ type Params: DeserializeOwned + Serialize;
+ const METHOD: &'static str;
+}
+
+#[macro_export]
+macro_rules! lsp_notification {
+ ("$/cancelRequest") => {
+ $crate::notification::Cancel
+ };
+ ("$/setTrace") => {
+ $crate::notification::SetTrace
+ };
+ ("$/logTrace") => {
+ $crate::notification::LogTrace
+ };
+ ("initialized") => {
+ $crate::notification::Initialized
+ };
+ ("exit") => {
+ $crate::notification::Exit
+ };
+
+ ("window/showMessage") => {
+ $crate::notification::ShowMessage
+ };
+ ("window/logMessage") => {
+ $crate::notification::LogMessage
+ };
+ ("window/workDoneProgress/cancel") => {
+ $crate::notification::WorkDoneProgressCancel
+ };
+
+ ("telemetry/event") => {
+ $crate::notification::TelemetryEvent
+ };
+
+ ("textDocument/didOpen") => {
+ $crate::notification::DidOpenTextDocument
+ };
+ ("textDocument/didChange") => {
+ $crate::notification::DidChangeTextDocument
+ };
+ ("textDocument/willSave") => {
+ $crate::notification::WillSaveTextDocument
+ };
+ ("textDocument/didSave") => {
+ $crate::notification::DidSaveTextDocument
+ };
+ ("textDocument/didClose") => {
+ $crate::notification::DidCloseTextDocument
+ };
+ ("textDocument/publishDiagnostics") => {
+ $crate::notification::PublishDiagnostics
+ };
+
+ ("workspace/didChangeConfiguration") => {
+ $crate::notification::DidChangeConfiguration
+ };
+ ("workspace/didChangeWatchedFiles") => {
+ $crate::notification::DidChangeWatchedFiles
+ };
+ ("workspace/didChangeWorkspaceFolders") => {
+ $crate::notification::DidChangeWorkspaceFolders
+ };
+ ("$/progress") => {
+ $crate::notification::Progress
+ };
+ ("workspace/didCreateFiles") => {
+ $crate::notification::DidCreateFiles
+ };
+ ("workspace/didRenameFiles") => {
+ $crate::notification::DidRenameFiles
+ };
+ ("workspace/didDeleteFiles") => {
+ $crate::notification::DidDeleteFiles
+ };
+}
+
+/// The base protocol now offers support for request cancellation. To cancel a request,
+/// a notification message with the following properties is sent:
+///
+/// A request that got canceled still needs to return from the server and send a response back.
+/// It can not be left open / hanging. This is in line with the JSON RPC protocol that requires
+/// that every request sends a response back. In addition it allows for returning partial results on cancel.
+#[derive(Debug)]
+pub enum Cancel {}
+
+impl Notification for Cancel {
+ type Params = CancelParams;
+ const METHOD: &'static str = "$/cancelRequest";
+}
+
+/// A notification that should be used by the client to modify the trace
+/// setting of the server.
+#[derive(Debug)]
+pub enum SetTrace {}
+
+impl Notification for SetTrace {
+ type Params = SetTraceParams;
+ const METHOD: &'static str = "$/setTrace";
+}
+
+/// A notification to log the trace of the server’s execution.
+/// The amount and content of these notifications depends on the current trace configuration.
+///
+/// `LogTrace` should be used for systematic trace reporting. For single debugging messages,
+/// the server should send `LogMessage` notifications.
+#[derive(Debug)]
+pub enum LogTrace {}
+
+impl Notification for LogTrace {
+ type Params = LogTraceParams;
+ const METHOD: &'static str = "$/logTrace";
+}
+
+/// The initialized notification is sent from the client to the server after the client received
+/// the result of the initialize request but before the client is sending any other request or
+/// notification to the server. The server can use the initialized notification for example to
+/// dynamically register capabilities.
+#[derive(Debug)]
+pub enum Initialized {}
+
+impl Notification for Initialized {
+ type Params = InitializedParams;
+ const METHOD: &'static str = "initialized";
+}
+
+/// A notification to ask the server to exit its process.
+/// The server should exit with success code 0 if the shutdown request has been received before;
+/// otherwise with error code 1.
+#[derive(Debug)]
+pub enum Exit {}
+
+impl Notification for Exit {
+ type Params = ();
+ const METHOD: &'static str = "exit";
+}
+
+/// The show message notification is sent from a server to a client to ask the client to display a particular message
+/// in the user interface.
+#[derive(Debug)]
+pub enum ShowMessage {}
+
+impl Notification for ShowMessage {
+ type Params = ShowMessageParams;
+ const METHOD: &'static str = "window/showMessage";
+}
+
+/// The log message notification is sent from the server to the client to ask the client to log a particular message.
+#[derive(Debug)]
+pub enum LogMessage {}
+
+impl Notification for LogMessage {
+ type Params = LogMessageParams;
+ const METHOD: &'static str = "window/logMessage";
+}
+
+/// The telemetry notification is sent from the server to the client to ask the client to log a telemetry event.
+/// The protocol doesn't specify the payload since no interpretation of the data happens in the protocol. Most clients even don't handle
+/// the event directly but forward them to the extensions owning the corresponding server issuing the event.
+#[derive(Debug)]
+pub enum TelemetryEvent {}
+
+impl Notification for TelemetryEvent {
+ type Params = serde_json::Value;
+ const METHOD: &'static str = "telemetry/event";
+}
+
+/// A notification sent from the client to the server to signal the change of configuration settings.
+#[derive(Debug)]
+pub enum DidChangeConfiguration {}
+
+impl Notification for DidChangeConfiguration {
+ type Params = DidChangeConfigurationParams;
+ const METHOD: &'static str = "workspace/didChangeConfiguration";
+}
+
+/// The document open notification is sent from the client to the server to signal newly opened text documents.
+/// The document's truth is now managed by the client and the server must not try to read the document's truth
+/// using the document's uri.
+#[derive(Debug)]
+pub enum DidOpenTextDocument {}
+
+impl Notification for DidOpenTextDocument {
+ type Params = DidOpenTextDocumentParams;
+ const METHOD: &'static str = "textDocument/didOpen";
+}
+
+/// The document change notification is sent from the client to the server to signal changes to a text document.
+/// In 2.0 the shape of the params has changed to include proper version numbers and language ids.
+#[derive(Debug)]
+pub enum DidChangeTextDocument {}
+
+impl Notification for DidChangeTextDocument {
+ type Params = DidChangeTextDocumentParams;
+ const METHOD: &'static str = "textDocument/didChange";
+}
+
+/// The document will save notification is sent from the client to the server before the document
+/// is actually saved.
+#[derive(Debug)]
+pub enum WillSaveTextDocument {}
+
+impl Notification for WillSaveTextDocument {
+ type Params = WillSaveTextDocumentParams;
+ const METHOD: &'static str = "textDocument/willSave";
+}
+
+/// The document close notification is sent from the client to the server when the document got closed in the client.
+/// The document's truth now exists where the document's uri points to (e.g. if the document's uri is a file uri
+/// the truth now exists on disk).
+#[derive(Debug)]
+pub enum DidCloseTextDocument {}
+
+impl Notification for DidCloseTextDocument {
+ type Params = DidCloseTextDocumentParams;
+ const METHOD: &'static str = "textDocument/didClose";
+}
+
+/// The document save notification is sent from the client to the server when the document was saved in the client.
+#[derive(Debug)]
+pub enum DidSaveTextDocument {}
+
+impl Notification for DidSaveTextDocument {
+ type Params = DidSaveTextDocumentParams;
+ const METHOD: &'static str = "textDocument/didSave";
+}
+
+/// The watched files notification is sent from the client to the server when the client detects changes to files and folders
+/// watched by the language client (note although the name suggest that only file events are sent it is about file system events which include folders as well).
+/// It is recommended that servers register for these file system events using the registration mechanism.
+/// In former implementations clients pushed file events without the server actively asking for it.
+#[derive(Debug)]
+pub enum DidChangeWatchedFiles {}
+
+impl Notification for DidChangeWatchedFiles {
+ type Params = DidChangeWatchedFilesParams;
+ const METHOD: &'static str = "workspace/didChangeWatchedFiles";
+}
+
+/// The workspace/didChangeWorkspaceFolders notification is sent from the client to the server to inform the server
+/// about workspace folder configuration changes
+#[derive(Debug)]
+pub enum DidChangeWorkspaceFolders {}
+
+impl Notification for DidChangeWorkspaceFolders {
+ type Params = DidChangeWorkspaceFoldersParams;
+ const METHOD: &'static str = "workspace/didChangeWorkspaceFolders";
+}
+
+/// Diagnostics notification are sent from the server to the client to signal results of validation runs.
+#[derive(Debug)]
+pub enum PublishDiagnostics {}
+
+impl Notification for PublishDiagnostics {
+ type Params = PublishDiagnosticsParams;
+ const METHOD: &'static str = "textDocument/publishDiagnostics";
+}
+
+/// The progress notification is sent from the server to the client to ask
+/// the client to indicate progress.
+#[derive(Debug)]
+pub enum Progress {}
+
+impl Notification for Progress {
+ type Params = ProgressParams;
+ const METHOD: &'static str = "$/progress";
+}
+
+/// The `window/workDoneProgress/cancel` notification is sent from the client
+/// to the server to cancel a progress initiated on the server side using the `window/workDoneProgress/create`.
+#[derive(Debug)]
+pub enum WorkDoneProgressCancel {}
+
+impl Notification for WorkDoneProgressCancel {
+ type Params = WorkDoneProgressCancelParams;
+ const METHOD: &'static str = "window/workDoneProgress/cancel";
+}
+
+/// The did create files notification is sent from the client to the server when files were created from within the client.
+#[derive(Debug)]
+pub enum DidCreateFiles {}
+
+impl Notification for DidCreateFiles {
+ type Params = CreateFilesParams;
+ const METHOD: &'static str = "workspace/didCreateFiles";
+}
+
+/// The did rename files notification is sent from the client to the server when files were renamed from within the client.
+#[derive(Debug)]
+pub enum DidRenameFiles {}
+
+impl Notification for DidRenameFiles {
+ type Params = RenameFilesParams;
+ const METHOD: &'static str = "workspace/didRenameFiles";
+}
+
+/// The did delete files notification is sent from the client to the server when files were deleted from within the client.
+#[derive(Debug)]
+pub enum DidDeleteFiles {}
+
+impl Notification for DidDeleteFiles {
+ type Params = DeleteFilesParams;
+ const METHOD: &'static str = "workspace/didDeleteFiles";
+}
+
+#[cfg(test)]
+mod test {
+ use super::*;
+
+ fn fake_call<N>()
+ where
+ N: Notification,
+ N::Params: serde::Serialize,
+ {
+ }
+
+ macro_rules! check_macro {
+ ($name:tt) => {
+ // check whether the macro name matches the method
+ assert_eq!(<lsp_notification!($name) as Notification>::METHOD, $name);
+ // test whether type checking passes for each component
+ fake_call::<lsp_notification!($name)>();
+ };
+ }
+
+ #[test]
+ fn check_macro_definitions() {
+ check_macro!("$/cancelRequest");
+ check_macro!("$/progress");
+ check_macro!("$/logTrace");
+ check_macro!("$/setTrace");
+ check_macro!("initialized");
+ check_macro!("exit");
+ check_macro!("window/showMessage");
+ check_macro!("window/logMessage");
+ check_macro!("window/workDoneProgress/cancel");
+ check_macro!("telemetry/event");
+ check_macro!("textDocument/didOpen");
+ check_macro!("textDocument/didChange");
+ check_macro!("textDocument/willSave");
+ check_macro!("textDocument/didSave");
+ check_macro!("textDocument/didClose");
+ check_macro!("textDocument/publishDiagnostics");
+ check_macro!("workspace/didChangeConfiguration");
+ check_macro!("workspace/didChangeWatchedFiles");
+ check_macro!("workspace/didChangeWorkspaceFolders");
+ check_macro!("workspace/didCreateFiles");
+ check_macro!("workspace/didRenameFiles");
+ check_macro!("workspace/didDeleteFiles");
+ }
+
+ #[test]
+ #[cfg(feature = "proposed")]
+ fn check_proposed_macro_definitions() {}
+}
diff --git a/vendor/lsp-types/src/progress.rs b/vendor/lsp-types/src/progress.rs
index 97d30e1a0..b16e5a981 100644
--- a/vendor/lsp-types/src/progress.rs
+++ b/vendor/lsp-types/src/progress.rs
@@ -1,134 +1,134 @@
-use serde::{Deserialize, Serialize};
-
-use crate::NumberOrString;
-
-pub type ProgressToken = NumberOrString;
-
-/// The progress notification is sent from the server to the client to ask
-/// the client to indicate progress.
-#[derive(Debug, PartialEq, Deserialize, Serialize, Clone)]
-#[serde(rename_all = "camelCase")]
-pub struct ProgressParams {
- /// The progress token provided by the client.
- pub token: ProgressToken,
-
- /// The progress data.
- pub value: ProgressParamsValue,
-}
-
-#[derive(Debug, PartialEq, Deserialize, Serialize, Clone)]
-#[serde(untagged)]
-pub enum ProgressParamsValue {
- WorkDone(WorkDoneProgress),
-}
-
-/// The `window/workDoneProgress/create` request is sent from the server
-/// to the clientto ask the client to create a work done progress.
-#[derive(Debug, PartialEq, Deserialize, Serialize, Clone)]
-#[serde(rename_all = "camelCase")]
-pub struct WorkDoneProgressCreateParams {
- /// The token to be used to report progress.
- pub token: ProgressToken,
-}
-
-/// The `window/workDoneProgress/cancel` notification is sent from the client
-/// to the server to cancel a progress initiated on the server side using the `window/workDoneProgress/create`.
-#[derive(Debug, PartialEq, Deserialize, Serialize, Clone)]
-#[serde(rename_all = "camelCase")]
-pub struct WorkDoneProgressCancelParams {
- /// The token to be used to report progress.
- pub token: ProgressToken,
-}
-
-/// Options to signal work done progress support in server capabilities.
-#[derive(Debug, Eq, PartialEq, Default, Deserialize, Serialize, Clone)]
-#[serde(rename_all = "camelCase")]
-pub struct WorkDoneProgressOptions {
- #[serde(skip_serializing_if = "Option::is_none")]
- pub work_done_progress: Option<bool>,
-}
-
-/// An optional token that a server can use to report work done progress
-#[derive(Debug, Eq, PartialEq, Default, Deserialize, Serialize, Clone)]
-#[serde(rename_all = "camelCase")]
-pub struct WorkDoneProgressParams {
- #[serde(skip_serializing_if = "Option::is_none")]
- pub work_done_token: Option<ProgressToken>,
-}
-
-#[derive(Debug, PartialEq, Default, Deserialize, Serialize, Clone)]
-#[serde(rename_all = "camelCase")]
-pub struct WorkDoneProgressBegin {
- /// Mandatory title of the progress operation. Used to briefly inform
- /// about the kind of operation being performed.
- /// Examples: "Indexing" or "Linking dependencies".
- pub title: String,
-
- /// Controls if a cancel button should show to allow the user to cancel the
- /// long running operation. Clients that don't support cancellation are allowed
- /// to ignore the setting.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub cancellable: Option<bool>,
-
- /// Optional, more detailed associated progress message. Contains
- /// complementary information to the `title`.
- ///
- /// Examples: "3/25 files", "project/src/module2", "node_modules/some_dep".
- /// If unset, the previous progress message (if any) is still valid.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub message: Option<String>,
-
- /// Optional progress percentage to display (value 100 is considered 100%).
- /// If not provided infinite progress is assumed and clients are allowed
- /// to ignore the `percentage` value in subsequent in report notifications.
- ///
- /// The value should be steadily rising. Clients are free to ignore values
- /// that are not following this rule. The value range is [0, 100]
- #[serde(skip_serializing_if = "Option::is_none")]
- pub percentage: Option<u32>,
-}
-
-#[derive(Debug, PartialEq, Default, Deserialize, Serialize, Clone)]
-#[serde(rename_all = "camelCase")]
-pub struct WorkDoneProgressReport {
- /// Controls if a cancel button should show to allow the user to cancel the
- /// long running operation. Clients that don't support cancellation are allowed
- /// to ignore the setting.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub cancellable: Option<bool>,
-
- /// Optional, more detailed associated progress message. Contains
- /// complementary information to the `title`.
- /// Examples: "3/25 files", "project/src/module2", "node_modules/some_dep".
- /// If unset, the previous progress message (if any) is still valid.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub message: Option<String>,
-
- /// Optional progress percentage to display (value 100 is considered 100%).
- /// If not provided infinite progress is assumed and clients are allowed
- /// to ignore the `percentage` value in subsequent in report notifications.
- ///
- /// The value should be steadily rising. Clients are free to ignore values
- /// that are not following this rule. The value range is [0, 100]
- #[serde(skip_serializing_if = "Option::is_none")]
- pub percentage: Option<u32>,
-}
-
-#[derive(Debug, PartialEq, Default, Deserialize, Serialize, Clone)]
-#[serde(rename_all = "camelCase")]
-pub struct WorkDoneProgressEnd {
- /// Optional, more detailed associated progress message. Contains
- /// complementary information to the `title`.
- /// Examples: "3/25 files", "project/src/module2", "node_modules/some_dep".
- /// If unset, the previous progress message (if any) is still valid.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub message: Option<String>,
-}
-
-#[derive(Debug, PartialEq, Deserialize, Serialize, Clone)]
-#[serde(tag = "kind", rename_all = "lowercase")]
-pub enum WorkDoneProgress {
- Begin(WorkDoneProgressBegin),
- Report(WorkDoneProgressReport),
- End(WorkDoneProgressEnd),
-}
+use serde::{Deserialize, Serialize};
+
+use crate::NumberOrString;
+
+pub type ProgressToken = NumberOrString;
+
+/// The progress notification is sent from the server to the client to ask
+/// the client to indicate progress.
+#[derive(Debug, PartialEq, Deserialize, Serialize, Clone)]
+#[serde(rename_all = "camelCase")]
+pub struct ProgressParams {
+ /// The progress token provided by the client.
+ pub token: ProgressToken,
+
+ /// The progress data.
+ pub value: ProgressParamsValue,
+}
+
+#[derive(Debug, PartialEq, Deserialize, Serialize, Clone)]
+#[serde(untagged)]
+pub enum ProgressParamsValue {
+ WorkDone(WorkDoneProgress),
+}
+
+/// The `window/workDoneProgress/create` request is sent from the server
+/// to the clientto ask the client to create a work done progress.
+#[derive(Debug, PartialEq, Deserialize, Serialize, Clone)]
+#[serde(rename_all = "camelCase")]
+pub struct WorkDoneProgressCreateParams {
+ /// The token to be used to report progress.
+ pub token: ProgressToken,
+}
+
+/// The `window/workDoneProgress/cancel` notification is sent from the client
+/// to the server to cancel a progress initiated on the server side using the `window/workDoneProgress/create`.
+#[derive(Debug, PartialEq, Deserialize, Serialize, Clone)]
+#[serde(rename_all = "camelCase")]
+pub struct WorkDoneProgressCancelParams {
+ /// The token to be used to report progress.
+ pub token: ProgressToken,
+}
+
+/// Options to signal work done progress support in server capabilities.
+#[derive(Debug, Eq, PartialEq, Default, Deserialize, Serialize, Clone)]
+#[serde(rename_all = "camelCase")]
+pub struct WorkDoneProgressOptions {
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub work_done_progress: Option<bool>,
+}
+
+/// An optional token that a server can use to report work done progress
+#[derive(Debug, Eq, PartialEq, Default, Deserialize, Serialize, Clone)]
+#[serde(rename_all = "camelCase")]
+pub struct WorkDoneProgressParams {
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub work_done_token: Option<ProgressToken>,
+}
+
+#[derive(Debug, PartialEq, Default, Deserialize, Serialize, Clone)]
+#[serde(rename_all = "camelCase")]
+pub struct WorkDoneProgressBegin {
+ /// Mandatory title of the progress operation. Used to briefly inform
+ /// about the kind of operation being performed.
+ /// Examples: "Indexing" or "Linking dependencies".
+ pub title: String,
+
+ /// Controls if a cancel button should show to allow the user to cancel the
+ /// long running operation. Clients that don't support cancellation are allowed
+ /// to ignore the setting.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub cancellable: Option<bool>,
+
+ /// Optional, more detailed associated progress message. Contains
+ /// complementary information to the `title`.
+ ///
+ /// Examples: "3/25 files", "project/src/module2", "node_modules/some_dep".
+ /// If unset, the previous progress message (if any) is still valid.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub message: Option<String>,
+
+ /// Optional progress percentage to display (value 100 is considered 100%).
+ /// If not provided infinite progress is assumed and clients are allowed
+ /// to ignore the `percentage` value in subsequent in report notifications.
+ ///
+ /// The value should be steadily rising. Clients are free to ignore values
+ /// that are not following this rule. The value range is [0, 100]
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub percentage: Option<u32>,
+}
+
+#[derive(Debug, PartialEq, Default, Deserialize, Serialize, Clone)]
+#[serde(rename_all = "camelCase")]
+pub struct WorkDoneProgressReport {
+ /// Controls if a cancel button should show to allow the user to cancel the
+ /// long running operation. Clients that don't support cancellation are allowed
+ /// to ignore the setting.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub cancellable: Option<bool>,
+
+ /// Optional, more detailed associated progress message. Contains
+ /// complementary information to the `title`.
+ /// Examples: "3/25 files", "project/src/module2", "node_modules/some_dep".
+ /// If unset, the previous progress message (if any) is still valid.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub message: Option<String>,
+
+ /// Optional progress percentage to display (value 100 is considered 100%).
+ /// If not provided infinite progress is assumed and clients are allowed
+ /// to ignore the `percentage` value in subsequent in report notifications.
+ ///
+ /// The value should be steadily rising. Clients are free to ignore values
+ /// that are not following this rule. The value range is [0, 100]
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub percentage: Option<u32>,
+}
+
+#[derive(Debug, PartialEq, Default, Deserialize, Serialize, Clone)]
+#[serde(rename_all = "camelCase")]
+pub struct WorkDoneProgressEnd {
+ /// Optional, more detailed associated progress message. Contains
+ /// complementary information to the `title`.
+ /// Examples: "3/25 files", "project/src/module2", "node_modules/some_dep".
+ /// If unset, the previous progress message (if any) is still valid.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub message: Option<String>,
+}
+
+#[derive(Debug, PartialEq, Deserialize, Serialize, Clone)]
+#[serde(tag = "kind", rename_all = "lowercase")]
+pub enum WorkDoneProgress {
+ Begin(WorkDoneProgressBegin),
+ Report(WorkDoneProgressReport),
+ End(WorkDoneProgressEnd),
+}
diff --git a/vendor/lsp-types/src/references.rs b/vendor/lsp-types/src/references.rs
index cb590d58e..4926bb771 100644
--- a/vendor/lsp-types/src/references.rs
+++ b/vendor/lsp-types/src/references.rs
@@ -1,30 +1,30 @@
-use crate::{
- DynamicRegistrationClientCapabilities, PartialResultParams, TextDocumentPositionParams,
- WorkDoneProgressParams,
-};
-use serde::{Deserialize, Serialize};
-
-pub type ReferenceClientCapabilities = DynamicRegistrationClientCapabilities;
-#[derive(Debug, Eq, PartialEq, Clone, Copy, Deserialize, Serialize)]
-#[serde(rename_all = "camelCase")]
-pub struct ReferenceContext {
- /// Include the declaration of the current symbol.
- pub include_declaration: bool,
-}
-
-#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
-#[serde(rename_all = "camelCase")]
-pub struct ReferenceParams {
- // Text Document and Position fields
- #[serde(flatten)]
- pub text_document_position: TextDocumentPositionParams,
-
- #[serde(flatten)]
- pub work_done_progress_params: WorkDoneProgressParams,
-
- #[serde(flatten)]
- pub partial_result_params: PartialResultParams,
-
- // ReferenceParams properties:
- pub context: ReferenceContext,
-}
+use crate::{
+ DynamicRegistrationClientCapabilities, PartialResultParams, TextDocumentPositionParams,
+ WorkDoneProgressParams,
+};
+use serde::{Deserialize, Serialize};
+
+pub type ReferenceClientCapabilities = DynamicRegistrationClientCapabilities;
+#[derive(Debug, Eq, PartialEq, Clone, Copy, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct ReferenceContext {
+ /// Include the declaration of the current symbol.
+ pub include_declaration: bool,
+}
+
+#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct ReferenceParams {
+ // Text Document and Position fields
+ #[serde(flatten)]
+ pub text_document_position: TextDocumentPositionParams,
+
+ #[serde(flatten)]
+ pub work_done_progress_params: WorkDoneProgressParams,
+
+ #[serde(flatten)]
+ pub partial_result_params: PartialResultParams,
+
+ // ReferenceParams properties:
+ pub context: ReferenceContext,
+}
diff --git a/vendor/lsp-types/src/rename.rs b/vendor/lsp-types/src/rename.rs
index b84bdcf6d..4645035a4 100644
--- a/vendor/lsp-types/src/rename.rs
+++ b/vendor/lsp-types/src/rename.rs
@@ -1,88 +1,88 @@
-use crate::{Range, TextDocumentPositionParams, WorkDoneProgressOptions, WorkDoneProgressParams};
-use serde::{Deserialize, Serialize};
-
-#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
-#[serde(rename_all = "camelCase")]
-pub struct RenameParams {
- /// Text Document and Position fields
- #[serde(flatten)]
- pub text_document_position: TextDocumentPositionParams,
-
- /// The new name of the symbol. If the given name is not valid the
- /// request must return a [ResponseError](#ResponseError) with an
- /// appropriate message set.
- pub new_name: String,
-
- #[serde(flatten)]
- pub work_done_progress_params: WorkDoneProgressParams,
-}
-
-#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
-#[serde(rename_all = "camelCase")]
-pub struct RenameOptions {
- /// Renames should be checked and tested before being executed.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub prepare_provider: Option<bool>,
-
- #[serde(flatten)]
- pub work_done_progress_options: WorkDoneProgressOptions,
-}
-
-#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
-#[serde(rename_all = "camelCase")]
-pub struct RenameClientCapabilities {
- /// Whether rename supports dynamic registration.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub dynamic_registration: Option<bool>,
-
- /// Client supports testing for validity of rename operations before execution.
- ///
- /// since 3.12.0
- #[serde(skip_serializing_if = "Option::is_none")]
- pub prepare_support: Option<bool>,
-
- /// Client supports the default behavior result.
- ///
- /// The value indicates the default behavior used by the
- /// client.
- ///
- /// since 3.16.0
- #[serde(skip_serializing_if = "Option::is_none")]
- pub prepare_support_default_behavior: Option<PrepareSupportDefaultBehavior>,
-
- /// Whether the client honors the change annotations in
- /// text edits and resource operations returned via the
- /// rename request's workspace edit by for example presenting
- /// the workspace edit in the user interface and asking
- /// for confirmation.
- ///
- /// @since 3.16.0
- #[serde(skip_serializing_if = "Option::is_none")]
- pub honors_change_annotations: Option<bool>,
-}
-
-#[derive(Eq, PartialEq, Copy, Clone, Serialize, Deserialize)]
-#[serde(transparent)]
-pub struct PrepareSupportDefaultBehavior(i32);
-lsp_enum! {
-impl PrepareSupportDefaultBehavior {
- /// The client's default behavior is to select the identifier
- /// according the to language's syntax rule
- pub const IDENTIFIER: PrepareSupportDefaultBehavior = PrepareSupportDefaultBehavior(1);
-}
-}
-
-#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
-#[serde(untagged)]
-#[serde(rename_all = "camelCase")]
-pub enum PrepareRenameResponse {
- Range(Range),
- RangeWithPlaceholder {
- range: Range,
- placeholder: String,
- },
- #[serde(rename_all = "camelCase")]
- DefaultBehavior {
- default_behavior: bool,
- },
-}
+use crate::{Range, TextDocumentPositionParams, WorkDoneProgressOptions, WorkDoneProgressParams};
+use serde::{Deserialize, Serialize};
+
+#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct RenameParams {
+ /// Text Document and Position fields
+ #[serde(flatten)]
+ pub text_document_position: TextDocumentPositionParams,
+
+ /// The new name of the symbol. If the given name is not valid the
+ /// request must return a [ResponseError](#ResponseError) with an
+ /// appropriate message set.
+ pub new_name: String,
+
+ #[serde(flatten)]
+ pub work_done_progress_params: WorkDoneProgressParams,
+}
+
+#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct RenameOptions {
+ /// Renames should be checked and tested before being executed.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub prepare_provider: Option<bool>,
+
+ #[serde(flatten)]
+ pub work_done_progress_options: WorkDoneProgressOptions,
+}
+
+#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct RenameClientCapabilities {
+ /// Whether rename supports dynamic registration.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub dynamic_registration: Option<bool>,
+
+ /// Client supports testing for validity of rename operations before execution.
+ ///
+ /// since 3.12.0
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub prepare_support: Option<bool>,
+
+ /// Client supports the default behavior result.
+ ///
+ /// The value indicates the default behavior used by the
+ /// client.
+ ///
+ /// since 3.16.0
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub prepare_support_default_behavior: Option<PrepareSupportDefaultBehavior>,
+
+ /// Whether the client honors the change annotations in
+ /// text edits and resource operations returned via the
+ /// rename request's workspace edit by for example presenting
+ /// the workspace edit in the user interface and asking
+ /// for confirmation.
+ ///
+ /// @since 3.16.0
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub honors_change_annotations: Option<bool>,
+}
+
+#[derive(Eq, PartialEq, Copy, Clone, Serialize, Deserialize)]
+#[serde(transparent)]
+pub struct PrepareSupportDefaultBehavior(i32);
+lsp_enum! {
+impl PrepareSupportDefaultBehavior {
+ /// The client's default behavior is to select the identifier
+ /// according the to language's syntax rule
+ pub const IDENTIFIER: PrepareSupportDefaultBehavior = PrepareSupportDefaultBehavior(1);
+}
+}
+
+#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
+#[serde(untagged)]
+#[serde(rename_all = "camelCase")]
+pub enum PrepareRenameResponse {
+ Range(Range),
+ RangeWithPlaceholder {
+ range: Range,
+ placeholder: String,
+ },
+ #[serde(rename_all = "camelCase")]
+ DefaultBehavior {
+ default_behavior: bool,
+ },
+}
diff --git a/vendor/lsp-types/src/request.rs b/vendor/lsp-types/src/request.rs
index aa03be4a4..da2efd74b 100644
--- a/vendor/lsp-types/src/request.rs
+++ b/vendor/lsp-types/src/request.rs
@@ -1,889 +1,1001 @@
-use super::*;
-
-use serde::{de::DeserializeOwned, Serialize};
-
-pub trait Request {
- type Params: DeserializeOwned + Serialize;
- type Result: DeserializeOwned + Serialize;
- const METHOD: &'static str;
-}
-
-#[macro_export]
-macro_rules! lsp_request {
- ("initialize") => {
- $crate::request::Initialize
- };
- ("shutdown") => {
- $crate::request::Shutdown
- };
-
- ("window/showMessageRequest") => {
- $crate::request::ShowMessageRequest
- };
-
- ("client/registerCapability") => {
- $crate::request::RegisterCapability
- };
- ("client/unregisterCapability") => {
- $crate::request::UnregisterCapability
- };
-
- ("workspace/symbol") => {
- $crate::request::WorkspaceSymbol
- };
- ("workspace/executeCommand") => {
- $crate::request::ExecuteCommand
- };
-
- ("textDocument/willSaveWaitUntil") => {
- $crate::request::WillSaveWaitUntil
- };
-
- ("textDocument/completion") => {
- $crate::request::Completion
- };
- ("completionItem/resolve") => {
- $crate::request::ResolveCompletionItem
- };
- ("textDocument/hover") => {
- $crate::request::HoverRequest
- };
- ("textDocument/signatureHelp") => {
- $crate::request::SignatureHelpRequest
- };
- ("textDocument/declaration") => {
- $crate::request::GotoDeclaration
- };
- ("textDocument/definition") => {
- $crate::request::GotoDefinition
- };
- ("textDocument/references") => {
- $crate::request::References
- };
- ("textDocument/documentHighlight") => {
- $crate::request::DocumentHighlightRequest
- };
- ("textDocument/documentSymbol") => {
- $crate::request::DocumentSymbolRequest
- };
- ("textDocument/codeAction") => {
- $crate::request::CodeActionRequest
- };
- ("textDocument/codeLens") => {
- $crate::request::CodeLensRequest
- };
- ("codeLens/resolve") => {
- $crate::request::CodeLensResolve
- };
- ("textDocument/documentLink") => {
- $crate::request::DocumentLinkRequest
- };
- ("documentLink/resolve") => {
- $crate::request::DocumentLinkResolve
- };
- ("workspace/applyEdit") => {
- $crate::request::ApplyWorkspaceEdit
- };
- ("textDocument/rangeFormatting") => {
- $crate::request::RangeFormatting
- };
- ("textDocument/onTypeFormatting") => {
- $crate::request::OnTypeFormatting
- };
- ("textDocument/formatting") => {
- $crate::request::Formatting
- };
- ("textDocument/rename") => {
- $crate::request::Rename
- };
- ("textDocument/documentColor") => {
- $crate::request::DocumentColor
- };
- ("textDocument/colorPresentation") => {
- $crate::request::ColorPresentationRequest
- };
- ("textDocument/foldingRange") => {
- $crate::request::FoldingRangeRequest
- };
- ("textDocument/prepareRename") => {
- $crate::request::PrepareRenameRequest
- };
- ("textDocument/implementation") => {
- $crate::request::GotoImplementation
- };
- ("textDocument/typeDefinition") => {
- $crate::request::GotoTypeDefinition
- };
- ("textDocument/selectionRange") => {
- $crate::request::SelectionRangeRequest
- };
- ("workspace/workspaceFolders") => {
- $crate::request::WorkspaceFoldersRequest
- };
- ("workspace/configuration") => {
- $crate::request::WorkspaceConfiguration
- };
- ("window/workDoneProgress/create") => {
- $crate::request::WorkDoneProgressCreate
- };
- ("callHierarchy/incomingCalls") => {
- $crate::request::CallHierarchyIncomingCalls
- };
- ("callHierarchy/outgoingCalls") => {
- $crate::request::CallHierarchyOutgoingCalls
- };
- ("textDocument/moniker") => {
- $crate::request::MonikerRequest
- };
- ("textDocument/linkedEditingRange") => {
- $crate::request::LinkedEditingRange
- };
- ("textDocument/prepareCallHierarchy") => {
- $crate::request::CallHierarchyPrepare
- };
- ("textDocument/semanticTokens/full") => {
- $crate::request::SemanticTokensFullRequest
- };
- ("textDocument/semanticTokens/full/delta") => {
- $crate::request::SemanticTokensFullDeltaRequest
- };
- ("textDocument/semanticTokens/range") => {
- $crate::request::SemanticTokensRangeRequest
- };
- ("workspace/willCreateFiles") => {
- $crate::request::WillCreateFiles
- };
- ("workspace/willRenameFiles") => {
- $crate::request::WillRenameFiles
- };
- ("workspace/willDeleteFiles") => {
- $crate::request::WillDeleteFiles
- };
- ("workspace/semanticTokens/refresh") => {
- $crate::request::SemanticTokensRefresh
- };
- ("workspace/codeLens/refresh") => {
- $crate::request::CodeLensRefresh
- };
- ("codeAction/resolve") => {
- $crate::request::CodeActionResolveRequest
- };
- ("window/showDocument") => {
- $crate::request::ShowDocument
- };
-}
-
-/// The initialize request is sent as the first request from the client to the server.
-/// If the server receives request or notification before the `initialize` request it should act as follows:
-///
-/// * for a request the respond should be errored with `code: -32001`. The message can be picked by the server.
-/// * notifications should be dropped.
-#[derive(Debug)]
-pub enum Initialize {}
-
-impl Request for Initialize {
- type Params = InitializeParams;
- type Result = InitializeResult;
- const METHOD: &'static str = "initialize";
-}
-
-/// The shutdown request is sent from the client to the server. It asks the server to shut down,
-/// but to not exit (otherwise the response might not be delivered correctly to the client).
-/// There is a separate exit notification that asks the server to exit.
-#[derive(Debug)]
-pub enum Shutdown {}
-
-impl Request for Shutdown {
- type Params = ();
- type Result = ();
- const METHOD: &'static str = "shutdown";
-}
-
-/// The show message request is sent from a server to a client to ask the client to display a particular message
-/// in the user interface. In addition to the show message notification the request allows to pass actions and to
-/// wait for an answer from the client.
-#[derive(Debug)]
-pub enum ShowMessageRequest {}
-
-impl Request for ShowMessageRequest {
- type Params = ShowMessageRequestParams;
- type Result = Option<MessageActionItem>;
- const METHOD: &'static str = "window/showMessageRequest";
-}
-
-/// The client/registerCapability request is sent from the server to the client to register for a new capability
-/// on the client side. Not all clients need to support dynamic capability registration. A client opts in via the
-/// ClientCapabilities.GenericCapability property.
-#[derive(Debug)]
-pub enum RegisterCapability {}
-
-impl Request for RegisterCapability {
- type Params = RegistrationParams;
- type Result = ();
- const METHOD: &'static str = "client/registerCapability";
-}
-
-/// The client/unregisterCapability request is sent from the server to the client to unregister a
-/// previously register capability.
-#[derive(Debug)]
-pub enum UnregisterCapability {}
-
-impl Request for UnregisterCapability {
- type Params = UnregistrationParams;
- type Result = ();
- const METHOD: &'static str = "client/unregisterCapability";
-}
-
-/// The Completion request is sent from the client to the server to compute completion items at a given cursor position.
-/// Completion items are presented in the IntelliSense user interface. If computing full completion items is expensive,
-/// servers can additionally provide a handler for the completion item resolve request ('completionItem/resolve').
-/// This request is sent when a completion item is selected in the user interface. A typical use case is for example:
-/// the 'textDocument/completion' request doesn’t fill in the documentation property for returned completion items
-/// since it is expensive to compute. When the item is selected in the user interface then a ‘completionItem/resolve’
-/// request is sent with the selected completion item as a param. The returned completion item should have the
-/// documentation property filled in. The request can delay the computation of the detail and documentation properties.
-/// However, properties that are needed for the initial sorting and filtering, like sortText, filterText, insertText,
-/// and textEdit must be provided in the textDocument/completion request and must not be changed during resolve.
-#[derive(Debug)]
-pub enum Completion {}
-
-impl Request for Completion {
- type Params = CompletionParams;
- type Result = Option<CompletionResponse>;
- const METHOD: &'static str = "textDocument/completion";
-}
-
-/// The request is sent from the client to the server to resolve additional information for a given completion item.
-#[derive(Debug)]
-pub enum ResolveCompletionItem {}
-
-impl Request for ResolveCompletionItem {
- type Params = CompletionItem;
- type Result = CompletionItem;
- const METHOD: &'static str = "completionItem/resolve";
-}
-
-/// The hover request is sent from the client to the server to request hover information at a given text
-/// document position.
-#[derive(Debug)]
-pub enum HoverRequest {}
-
-impl Request for HoverRequest {
- type Params = HoverParams;
- type Result = Option<Hover>;
- const METHOD: &'static str = "textDocument/hover";
-}
-
-/// The signature help request is sent from the client to the server to request signature information at
-/// a given cursor position.
-#[derive(Debug)]
-pub enum SignatureHelpRequest {}
-
-impl Request for SignatureHelpRequest {
- type Params = SignatureHelpParams;
- type Result = Option<SignatureHelp>;
- const METHOD: &'static str = "textDocument/signatureHelp";
-}
-
-#[derive(Debug)]
-pub enum GotoDeclaration {}
-pub type GotoDeclarationParams = GotoDefinitionParams;
-pub type GotoDeclarationResponse = GotoDefinitionResponse;
-
-/// The goto declaration request is sent from the client to the server to resolve the declaration location of
-/// a symbol at a given text document position.
-impl Request for GotoDeclaration {
- type Params = GotoDeclarationParams;
- type Result = Option<GotoDeclarationResponse>;
- const METHOD: &'static str = "textDocument/declaration";
-}
-
-/// The goto definition request is sent from the client to the server to resolve the definition location of
-/// a symbol at a given text document position.
-#[derive(Debug)]
-pub enum GotoDefinition {}
-
-impl Request for GotoDefinition {
- type Params = GotoDefinitionParams;
- type Result = Option<GotoDefinitionResponse>;
- const METHOD: &'static str = "textDocument/definition";
-}
-
-/// The references request is sent from the client to the server to resolve project-wide references for the
-/// symbol denoted by the given text document position.
-#[derive(Debug)]
-pub enum References {}
-
-impl Request for References {
- type Params = ReferenceParams;
- type Result = Option<Vec<Location>>;
- const METHOD: &'static str = "textDocument/references";
-}
-
-/// The goto type definition request is sent from the client to the
-/// server to resolve the type definition location of a symbol at a
-/// given text document position.
-#[derive(Debug)]
-pub enum GotoTypeDefinition {}
-
-pub type GotoTypeDefinitionParams = GotoDefinitionParams;
-pub type GotoTypeDefinitionResponse = GotoDefinitionResponse;
-
-impl Request for GotoTypeDefinition {
- type Params = GotoTypeDefinitionParams;
- type Result = Option<GotoTypeDefinitionResponse>;
- const METHOD: &'static str = "textDocument/typeDefinition";
-}
-
-/// The goto implementation request is sent from the client to the
-/// server to resolve the implementation location of a symbol at a
-/// given text document position.
-#[derive(Debug)]
-pub enum GotoImplementation {}
-
-pub type GotoImplementationParams = GotoTypeDefinitionParams;
-pub type GotoImplementationResponse = GotoDefinitionResponse;
-
-impl Request for GotoImplementation {
- type Params = GotoImplementationParams;
- type Result = Option<GotoImplementationResponse>;
- const METHOD: &'static str = "textDocument/implementation";
-}
-
-/// The document highlight request is sent from the client to the server to resolve a document highlights
-/// for a given text document position.
-/// For programming languages this usually highlights all references to the symbol scoped to this file.
-/// However we kept 'textDocument/documentHighlight' and 'textDocument/references' separate requests since
-/// the first one is allowed to be more fuzzy.
-/// Symbol matches usually have a DocumentHighlightKind of Read or Write whereas fuzzy or textual matches
-/// use Text as the kind.
-#[derive(Debug)]
-pub enum DocumentHighlightRequest {}
-
-impl Request for DocumentHighlightRequest {
- type Params = DocumentHighlightParams;
- type Result = Option<Vec<DocumentHighlight>>;
- const METHOD: &'static str = "textDocument/documentHighlight";
-}
-
-/// The document symbol request is sent from the client to the server to list all symbols found in a given
-/// text document.
-#[derive(Debug)]
-pub enum DocumentSymbolRequest {}
-
-impl Request for DocumentSymbolRequest {
- type Params = DocumentSymbolParams;
- type Result = Option<DocumentSymbolResponse>;
- const METHOD: &'static str = "textDocument/documentSymbol";
-}
-
-/// The workspace symbol request is sent from the client to the server to list project-wide symbols
-/// matching the query string.
-#[derive(Debug)]
-pub enum WorkspaceSymbol {}
-
-impl Request for WorkspaceSymbol {
- type Params = WorkspaceSymbolParams;
- type Result = Option<Vec<SymbolInformation>>;
- const METHOD: &'static str = "workspace/symbol";
-}
-
-/// The workspace/executeCommand request is sent from the client to the server to trigger command execution on the server.
-/// In most cases the server creates a WorkspaceEdit structure and applies the changes to the workspace using the request
-/// workspace/applyEdit which is sent from the server to the client.
-#[derive(Debug)]
-pub enum ExecuteCommand {}
-
-impl Request for ExecuteCommand {
- type Params = ExecuteCommandParams;
- type Result = Option<Value>;
- const METHOD: &'static str = "workspace/executeCommand";
-}
-
-/// The document will save request is sent from the client to the server before the document is
-/// actually saved. The request can return an array of TextEdits which will be applied to the text
-/// document before it is saved. Please note that clients might drop results if computing the text
-/// edits took too long or if a server constantly fails on this request. This is done to keep the
-/// save fast and reliable.
-#[derive(Debug)]
-pub enum WillSaveWaitUntil {}
-
-impl Request for WillSaveWaitUntil {
- type Params = WillSaveTextDocumentParams;
- type Result = Option<Vec<TextEdit>>;
- const METHOD: &'static str = "textDocument/willSaveWaitUntil";
-}
-
-/// The workspace/applyEdit request is sent from the server to the client to modify resource on the
-/// client side.
-#[derive(Debug)]
-pub enum ApplyWorkspaceEdit {}
-
-impl Request for ApplyWorkspaceEdit {
- type Params = ApplyWorkspaceEditParams;
- type Result = ApplyWorkspaceEditResponse;
- const METHOD: &'static str = "workspace/applyEdit";
-}
-
-/// The workspace/configuration request is sent from the server to the client to fetch configuration settings
-/// from the client. The request can fetch several configuration settings in one roundtrip.
-/// The order of the returned configuration settings correspond to the order of the passed ConfigurationItems
-/// (e.g. the first item in the response is the result for the first configuration item in the params).
-///
-/// A ConfigurationItem consists of the configuration section to ask for and an additional scope URI.
-/// The configuration section ask for is defined by the server and doesn’t necessarily need to correspond to
-/// the configuration store used be the client. So a server might ask for a configuration cpp.formatterOptions
-/// but the client stores the configuration in a XML store layout differently.
-/// It is up to the client to do the necessary conversion. If a scope URI is provided the client should return
-/// the setting scoped to the provided resource. If the client for example uses EditorConfig to manage its
-/// settings the configuration should be returned for the passed resource URI. If the client can’t provide a
-/// configuration setting for a given scope then null need to be present in the returned array.
-#[derive(Debug)]
-pub enum WorkspaceConfiguration {}
-
-impl Request for WorkspaceConfiguration {
- type Params = ConfigurationParams;
- type Result = Vec<Value>;
- const METHOD: &'static str = "workspace/configuration";
-}
-
-/// The code action request is sent from the client to the server to compute commands for a given text document
-/// and range. The request is triggered when the user moves the cursor into a problem marker in the editor or
-/// presses the lightbulb associated with a marker.
-#[derive(Debug)]
-pub enum CodeActionRequest {}
-
-impl Request for CodeActionRequest {
- type Params = CodeActionParams;
- type Result = Option<CodeActionResponse>;
- const METHOD: &'static str = "textDocument/codeAction";
-}
-
-/// The request is sent from the client to the server to resolve additional information for a given code action.
-/// This is usually used to compute the `edit` property of a code action to avoid its unnecessary computation
-/// during the `textDocument/codeAction` request.
-///
-/// since 3.16.0
-#[derive(Debug)]
-pub enum CodeActionResolveRequest {}
-
-impl Request for CodeActionResolveRequest {
- type Params = CodeAction;
- type Result = CodeAction;
- const METHOD: &'static str = "codeAction/resolve";
-}
-
-/// The code lens request is sent from the client to the server to compute code lenses for a given text document.
-#[derive(Debug)]
-pub enum CodeLensRequest {}
-
-impl Request for CodeLensRequest {
- type Params = CodeLensParams;
- type Result = Option<Vec<CodeLens>>;
- const METHOD: &'static str = "textDocument/codeLens";
-}
-
-/// The code lens resolve request is sent from the client to the server to resolve the command for a
-/// given code lens item.
-#[derive(Debug)]
-pub enum CodeLensResolve {}
-
-impl Request for CodeLensResolve {
- type Params = CodeLens;
- type Result = CodeLens;
- const METHOD: &'static str = "codeLens/resolve";
-}
-
-/// The document links request is sent from the client to the server to request the location of links in a document.
-#[derive(Debug)]
-pub enum DocumentLinkRequest {}
-
-impl Request for DocumentLinkRequest {
- type Params = DocumentLinkParams;
- type Result = Option<Vec<DocumentLink>>;
- const METHOD: &'static str = "textDocument/documentLink";
-}
-
-/// The document link resolve request is sent from the client to the server to resolve the target of
-/// a given document link.
-#[derive(Debug)]
-pub enum DocumentLinkResolve {}
-
-impl Request for DocumentLinkResolve {
- type Params = DocumentLink;
- type Result = DocumentLink;
- const METHOD: &'static str = "documentLink/resolve";
-}
-
-/// The document formatting request is sent from the server to the client to format a whole document.
-#[derive(Debug)]
-pub enum Formatting {}
-
-impl Request for Formatting {
- type Params = DocumentFormattingParams;
- type Result = Option<Vec<TextEdit>>;
- const METHOD: &'static str = "textDocument/formatting";
-}
-
-/// The document range formatting request is sent from the client to the server to format a given range in a document.
-#[derive(Debug)]
-pub enum RangeFormatting {}
-
-impl Request for RangeFormatting {
- type Params = DocumentRangeFormattingParams;
- type Result = Option<Vec<TextEdit>>;
- const METHOD: &'static str = "textDocument/rangeFormatting";
-}
-
-/// The document on type formatting request is sent from the client to the server to format parts of
-/// the document during typing.
-#[derive(Debug)]
-pub enum OnTypeFormatting {}
-
-impl Request for OnTypeFormatting {
- type Params = DocumentOnTypeFormattingParams;
- type Result = Option<Vec<TextEdit>>;
- const METHOD: &'static str = "textDocument/onTypeFormatting";
-}
-
-/// The linked editing request is sent from the client to the server to return for a given position in a document
-/// the range of the symbol at the position and all ranges that have the same content.
-/// Optionally a word pattern can be returned to describe valid contents. A rename to one of the ranges can be applied
-/// to all other ranges if the new content is valid. If no result-specific word pattern is provided, the word pattern from
-/// the client’s language configuration is used.
-#[derive(Debug)]
-pub enum LinkedEditingRange {}
-
-impl Request for LinkedEditingRange {
- type Params = LinkedEditingRangeParams;
- type Result = Option<LinkedEditingRanges>;
- const METHOD: &'static str = "textDocument/linkedEditingRange";
-}
-
-/// The rename request is sent from the client to the server to perform a workspace-wide rename of a symbol.
-#[derive(Debug)]
-pub enum Rename {}
-
-impl Request for Rename {
- type Params = RenameParams;
- type Result = Option<WorkspaceEdit>;
- const METHOD: &'static str = "textDocument/rename";
-}
-
-/// The document color request is sent from the client to the server to list all color references found in a given text document.
-/// Along with the range, a color value in RGB is returned.
-#[derive(Debug)]
-pub enum DocumentColor {}
-
-impl Request for DocumentColor {
- type Params = DocumentColorParams;
- type Result = Vec<ColorInformation>;
- const METHOD: &'static str = "textDocument/documentColor";
-}
-
-/// The color presentation request is sent from the client to the server to obtain a list of presentations for a color value
-/// at a given location.
-#[derive(Debug)]
-pub enum ColorPresentationRequest {}
-
-impl Request for ColorPresentationRequest {
- type Params = ColorPresentationParams;
- type Result = Vec<ColorPresentation>;
- const METHOD: &'static str = "textDocument/colorPresentation";
-}
-
-/// The folding range request is sent from the client to the server to return all folding ranges found in a given text document.
-#[derive(Debug)]
-pub enum FoldingRangeRequest {}
-
-impl Request for FoldingRangeRequest {
- type Params = FoldingRangeParams;
- type Result = Option<Vec<FoldingRange>>;
- const METHOD: &'static str = "textDocument/foldingRange";
-}
-
-/// The prepare rename request is sent from the client to the server to setup and test the validity of a rename operation
-/// at a given location.
-#[derive(Debug)]
-pub enum PrepareRenameRequest {}
-
-impl Request for PrepareRenameRequest {
- type Params = TextDocumentPositionParams;
- type Result = Option<PrepareRenameResponse>;
- const METHOD: &'static str = "textDocument/prepareRename";
-}
-
-/// The workspace/workspaceFolders request is sent from the server to the client to fetch the current open list of
-/// workspace folders. Returns null in the response if only a single file is open in the tool.
-/// Returns an empty array if a workspace is open but no folders are configured.
-#[derive(Debug)]
-pub enum WorkspaceFoldersRequest {}
-
-impl Request for WorkspaceFoldersRequest {
- type Params = ();
- type Result = Option<Vec<WorkspaceFolder>>;
- const METHOD: &'static str = "workspace/workspaceFolders";
-}
-
-/// The `window/workDoneProgress/create` request is sent from the server
-/// to the clientto ask the client to create a work done progress.
-#[derive(Debug)]
-pub enum WorkDoneProgressCreate {}
-
-impl Request for WorkDoneProgressCreate {
- type Params = WorkDoneProgressCreateParams;
- type Result = ();
- const METHOD: &'static str = "window/workDoneProgress/create";
-}
-
-/// The selection range request is sent from the client to the server to return
-/// suggested selection ranges at given positions. A selection range is a range
-/// around the cursor position which the user might be interested in selecting.
-///
-/// A selection range in the return array is for the position in the provided parameters at the same index.
-/// Therefore `positions[i]` must be contained in `result[i].range`.
-///
-/// Typically, but not necessary, selection ranges correspond to the nodes of the
-/// syntax tree.
-pub enum SelectionRangeRequest {}
-
-impl Request for SelectionRangeRequest {
- type Params = SelectionRangeParams;
- type Result = Option<Vec<SelectionRange>>;
- const METHOD: &'static str = "textDocument/selectionRange";
-}
-
-pub enum CallHierarchyPrepare {}
-
-impl Request for CallHierarchyPrepare {
- type Params = CallHierarchyPrepareParams;
- type Result = Option<Vec<CallHierarchyItem>>;
- const METHOD: &'static str = "textDocument/prepareCallHierarchy";
-}
-
-pub enum CallHierarchyIncomingCalls {}
-
-impl Request for CallHierarchyIncomingCalls {
- type Params = CallHierarchyIncomingCallsParams;
- type Result = Option<Vec<CallHierarchyIncomingCall>>;
- const METHOD: &'static str = "callHierarchy/incomingCalls";
-}
-
-pub enum CallHierarchyOutgoingCalls {}
-
-impl Request for CallHierarchyOutgoingCalls {
- type Params = CallHierarchyOutgoingCallsParams;
- type Result = Option<Vec<CallHierarchyOutgoingCall>>;
- const METHOD: &'static str = "callHierarchy/outgoingCalls";
-}
-
-pub enum SemanticTokensFullRequest {}
-
-impl Request for SemanticTokensFullRequest {
- type Params = SemanticTokensParams;
- type Result = Option<SemanticTokensResult>;
- const METHOD: &'static str = "textDocument/semanticTokens/full";
-}
-
-pub enum SemanticTokensFullDeltaRequest {}
-
-impl Request for SemanticTokensFullDeltaRequest {
- type Params = SemanticTokensDeltaParams;
- type Result = Option<SemanticTokensFullDeltaResult>;
- const METHOD: &'static str = "textDocument/semanticTokens/full/delta";
-}
-
-pub enum SemanticTokensRangeRequest {}
-
-impl Request for SemanticTokensRangeRequest {
- type Params = SemanticTokensRangeParams;
- type Result = Option<SemanticTokensRangeResult>;
- const METHOD: &'static str = "textDocument/semanticTokens/range";
-}
-
-/// The `workspace/semanticTokens/refresh` request is sent from the server to the client.
-/// Servers can use it to ask clients to refresh the editors for which this server provides semantic tokens.
-/// As a result the client should ask the server to recompute the semantic tokens for these editors.
-/// This is useful if a server detects a project wide configuration change which requires a re-calculation of all semantic tokens.
-/// Note that the client still has the freedom to delay the re-calculation of the semantic tokens if for example an editor is currently not visible.
-pub enum SemanticTokensRefresh {}
-
-impl Request for SemanticTokensRefresh {
- type Params = ();
- type Result = ();
- const METHOD: &'static str = "workspace/semanticTokens/refresh";
-}
-
-/// The workspace/codeLens/refresh request is sent from the server to the client.
-/// Servers can use it to ask clients to refresh the code lenses currently shown in editors.
-/// As a result the client should ask the server to recompute the code lenses for these editors.
-/// This is useful if a server detects a configuration change which requires a re-calculation of all code lenses.
-/// Note that the client still has the freedom to delay the re-calculation of the code lenses if for example an editor is currently not visible.
-pub enum CodeLensRefresh {}
-
-impl Request for CodeLensRefresh {
- type Params = ();
- type Result = ();
- const METHOD: &'static str = "workspace/codeLens/refresh";
-}
-
-/// The will create files request is sent from the client to the server before files are actually created as long as the creation is triggered from within the client. The request can return a WorkspaceEdit which will be applied to workspace before the files are created. Please note that clients might drop results if computing the edit took too long or if a server constantly fails on this request. This is done to keep creates fast and reliable.
-pub enum WillCreateFiles {}
-
-impl Request for WillCreateFiles {
- type Params = CreateFilesParams;
- type Result = Option<WorkspaceEdit>;
- const METHOD: &'static str = "workspace/willCreateFiles";
-}
-
-/// The will rename files request is sent from the client to the server before files are actually renamed as long as the rename is triggered from within the client. The request can return a WorkspaceEdit which will be applied to workspace before the files are renamed. Please note that clients might drop results if computing the edit took too long or if a server constantly fails on this request. This is done to keep renames fast and reliable.
-pub enum WillRenameFiles {}
-
-impl Request for WillRenameFiles {
- type Params = RenameFilesParams;
- type Result = Option<WorkspaceEdit>;
- const METHOD: &'static str = "workspace/willRenameFiles";
-}
-
-/// The will delete files request is sent from the client to the server before files are actually deleted as long as the deletion is triggered from within the client. The request can return a WorkspaceEdit which will be applied to workspace before the files are deleted. Please note that clients might drop results if computing the edit took too long or if a server constantly fails on this request. This is done to keep deletes fast and reliable.
-pub enum WillDeleteFiles {}
-
-impl Request for WillDeleteFiles {
- type Params = DeleteFilesParams;
- type Result = Option<WorkspaceEdit>;
- const METHOD: &'static str = "workspace/willDeleteFiles";
-}
-
-/// The show document request is sent from a server to a client to ask the client to display a particular document in the user interface.
-pub enum ShowDocument {}
-
-impl Request for ShowDocument {
- type Params = ShowDocumentParams;
- type Result = ShowDocumentResult;
- const METHOD: &'static str = "window/showDocument";
-}
-
-pub enum MonikerRequest {}
-
-impl Request for MonikerRequest {
- type Params = MonikerParams;
- type Result = Option<Vec<Moniker>>;
- const METHOD: &'static str = "textDocument/moniker";
-}
-
-#[cfg(feature = "proposed")]
-pub enum InlayHintRequest {}
-
-#[cfg(feature = "proposed")]
-impl Request for InlayHintRequest {
- type Params = InlayHintParams;
- type Result = Option<Vec<InlayHint>>;
- const METHOD: &'static str = "textDocument/inlayHint";
-}
-
-#[cfg(feature = "proposed")]
-pub enum InlayHintResolveRequest {}
-
-#[cfg(feature = "proposed")]
-impl Request for InlayHintResolveRequest {
- type Params = InlayHint;
- type Result = InlayHint;
- const METHOD: &'static str = "inlayHint/resolve";
-}
-
-#[cfg(feature = "proposed")]
-pub enum InlayHintRefreshRequest {}
-
-#[cfg(feature = "proposed")]
-impl Request for InlayHintRefreshRequest {
- type Params = ();
- type Result = ();
- const METHOD: &'static str = "workspace/inlayHint/refresh";
-}
-
-#[cfg(test)]
-mod test {
- use super::*;
-
- fn fake_call<R>()
- where
- R: Request,
- R::Params: serde::Serialize,
- R::Result: serde::de::DeserializeOwned,
- {
- }
-
- macro_rules! check_macro {
- ($name:tt) => {
- // check whethe the macro name matches the method
- assert_eq!(<lsp_request!($name) as Request>::METHOD, $name);
- // test whether type checking passes for each component
- fake_call::<lsp_request!($name)>();
- };
- }
-
- #[test]
- fn check_macro_definitions() {
- check_macro!("initialize");
- check_macro!("shutdown");
-
- check_macro!("window/showDocument");
- check_macro!("window/showMessageRequest");
- check_macro!("window/workDoneProgress/create");
-
- check_macro!("client/registerCapability");
- check_macro!("client/unregisterCapability");
-
- check_macro!("textDocument/willSaveWaitUntil");
- check_macro!("textDocument/completion");
- check_macro!("textDocument/hover");
- check_macro!("textDocument/signatureHelp");
- check_macro!("textDocument/declaration");
- check_macro!("textDocument/definition");
- check_macro!("textDocument/references");
- check_macro!("textDocument/documentHighlight");
- check_macro!("textDocument/documentSymbol");
- check_macro!("textDocument/codeAction");
- check_macro!("textDocument/codeLens");
- check_macro!("textDocument/documentLink");
- check_macro!("textDocument/rangeFormatting");
- check_macro!("textDocument/onTypeFormatting");
- check_macro!("textDocument/formatting");
- check_macro!("textDocument/rename");
- check_macro!("textDocument/documentColor");
- check_macro!("textDocument/colorPresentation");
- check_macro!("textDocument/foldingRange");
- check_macro!("textDocument/prepareRename");
- check_macro!("textDocument/implementation");
- check_macro!("textDocument/selectionRange");
- check_macro!("textDocument/typeDefinition");
- check_macro!("textDocument/moniker");
- check_macro!("textDocument/linkedEditingRange");
- check_macro!("textDocument/prepareCallHierarchy");
- check_macro!("textDocument/semanticTokens/full");
- check_macro!("textDocument/semanticTokens/full/delta");
- check_macro!("textDocument/semanticTokens/range");
-
- check_macro!("workspace/applyEdit");
- check_macro!("workspace/symbol");
- check_macro!("workspace/executeCommand");
- check_macro!("workspace/configuration");
- check_macro!("workspace/willCreateFiles");
- check_macro!("workspace/willRenameFiles");
- check_macro!("workspace/willDeleteFiles");
- check_macro!("workspace/workspaceFolders");
- check_macro!("workspace/semanticTokens/refresh");
- check_macro!("workspace/codeLens/refresh");
-
- check_macro!("codeAction/resolve");
- check_macro!("codeLens/resolve");
- check_macro!("completionItem/resolve");
- check_macro!("documentLink/resolve");
- check_macro!("callHierarchy/incomingCalls");
- check_macro!("callHierarchy/outgoingCalls");
- }
-
- #[test]
- #[cfg(feature = "proposed")]
- fn check_proposed_macro_definitions() {}
-}
+use super::*;
+
+use serde::{de::DeserializeOwned, Serialize};
+
+pub trait Request {
+ type Params: DeserializeOwned + Serialize;
+ type Result: DeserializeOwned + Serialize;
+ const METHOD: &'static str;
+}
+
+#[macro_export]
+macro_rules! lsp_request {
+ ("initialize") => {
+ $crate::request::Initialize
+ };
+ ("shutdown") => {
+ $crate::request::Shutdown
+ };
+
+ ("window/showMessageRequest") => {
+ $crate::request::ShowMessageRequest
+ };
+
+ ("client/registerCapability") => {
+ $crate::request::RegisterCapability
+ };
+ ("client/unregisterCapability") => {
+ $crate::request::UnregisterCapability
+ };
+
+ ("workspace/symbol") => {
+ $crate::request::WorkspaceSymbolRequest
+ };
+ ("workspace/executeCommand") => {
+ $crate::request::ExecuteCommand
+ };
+
+ ("textDocument/willSaveWaitUntil") => {
+ $crate::request::WillSaveWaitUntil
+ };
+
+ ("textDocument/completion") => {
+ $crate::request::Completion
+ };
+ ("completionItem/resolve") => {
+ $crate::request::ResolveCompletionItem
+ };
+ ("textDocument/hover") => {
+ $crate::request::HoverRequest
+ };
+ ("textDocument/signatureHelp") => {
+ $crate::request::SignatureHelpRequest
+ };
+ ("textDocument/declaration") => {
+ $crate::request::GotoDeclaration
+ };
+ ("textDocument/definition") => {
+ $crate::request::GotoDefinition
+ };
+ ("textDocument/references") => {
+ $crate::request::References
+ };
+ ("textDocument/documentHighlight") => {
+ $crate::request::DocumentHighlightRequest
+ };
+ ("textDocument/documentSymbol") => {
+ $crate::request::DocumentSymbolRequest
+ };
+ ("textDocument/codeAction") => {
+ $crate::request::CodeActionRequest
+ };
+ ("textDocument/codeLens") => {
+ $crate::request::CodeLensRequest
+ };
+ ("codeLens/resolve") => {
+ $crate::request::CodeLensResolve
+ };
+ ("textDocument/documentLink") => {
+ $crate::request::DocumentLinkRequest
+ };
+ ("documentLink/resolve") => {
+ $crate::request::DocumentLinkResolve
+ };
+ ("workspace/applyEdit") => {
+ $crate::request::ApplyWorkspaceEdit
+ };
+ ("textDocument/rangeFormatting") => {
+ $crate::request::RangeFormatting
+ };
+ ("textDocument/onTypeFormatting") => {
+ $crate::request::OnTypeFormatting
+ };
+ ("textDocument/formatting") => {
+ $crate::request::Formatting
+ };
+ ("textDocument/rename") => {
+ $crate::request::Rename
+ };
+ ("textDocument/documentColor") => {
+ $crate::request::DocumentColor
+ };
+ ("textDocument/colorPresentation") => {
+ $crate::request::ColorPresentationRequest
+ };
+ ("textDocument/foldingRange") => {
+ $crate::request::FoldingRangeRequest
+ };
+ ("textDocument/prepareRename") => {
+ $crate::request::PrepareRenameRequest
+ };
+ ("textDocument/implementation") => {
+ $crate::request::GotoImplementation
+ };
+ ("textDocument/typeDefinition") => {
+ $crate::request::GotoTypeDefinition
+ };
+ ("textDocument/selectionRange") => {
+ $crate::request::SelectionRangeRequest
+ };
+ ("workspace/workspaceFolders") => {
+ $crate::request::WorkspaceFoldersRequest
+ };
+ ("workspace/configuration") => {
+ $crate::request::WorkspaceConfiguration
+ };
+ ("window/workDoneProgress/create") => {
+ $crate::request::WorkDoneProgressCreate
+ };
+ ("callHierarchy/incomingCalls") => {
+ $crate::request::CallHierarchyIncomingCalls
+ };
+ ("callHierarchy/outgoingCalls") => {
+ $crate::request::CallHierarchyOutgoingCalls
+ };
+ ("textDocument/moniker") => {
+ $crate::request::MonikerRequest
+ };
+ ("textDocument/linkedEditingRange") => {
+ $crate::request::LinkedEditingRange
+ };
+ ("textDocument/prepareCallHierarchy") => {
+ $crate::request::CallHierarchyPrepare
+ };
+ ("textDocument/prepareTypeHierarchy") => {
+ $crate::request::TypeHierarchyPrepare
+ };
+ ("textDocument/semanticTokens/full") => {
+ $crate::request::SemanticTokensFullRequest
+ };
+ ("textDocument/semanticTokens/full/delta") => {
+ $crate::request::SemanticTokensFullDeltaRequest
+ };
+ ("textDocument/semanticTokens/range") => {
+ $crate::request::SemanticTokensRangeRequest
+ };
+ ("textDocument/inlayHint") => {
+ $crate::request::InlayHintRequest
+ };
+ ("textDocument/inlineValue") => {
+ $crate::request::InlineValueRequest
+ };
+ ("typeHierarchy/supertypes") => {
+ $crate::request::TypeHierarchySupertypes
+ };
+ ("typeHierarchy/subtypes") => {
+ $crate::request::TypeHierarchySubtypes
+ };
+ ("workspace/willCreateFiles") => {
+ $crate::request::WillCreateFiles
+ };
+ ("workspace/willRenameFiles") => {
+ $crate::request::WillRenameFiles
+ };
+ ("workspace/willDeleteFiles") => {
+ $crate::request::WillDeleteFiles
+ };
+ ("workspace/semanticTokens/refresh") => {
+ $crate::request::SemanticTokensRefresh
+ };
+ ("workspace/codeLens/refresh") => {
+ $crate::request::CodeLensRefresh
+ };
+ ("workspace/inlayHint/refresh") => {
+ $crate::request::InlayHintRefreshRequest
+ };
+ ("workspace/inlineValue/refresh") => {
+ $crate::request::InlineValueRefreshRequest
+ };
+ ("codeAction/resolve") => {
+ $crate::request::CodeActionResolveRequest
+ };
+ ("inlayHint/resolve") => {
+ $crate::request::InlayHintResolveRequest
+ };
+ ("window/showDocument") => {
+ $crate::request::ShowDocument
+ };
+}
+
+/// The initialize request is sent as the first request from the client to the server.
+/// If the server receives request or notification before the `initialize` request it should act as follows:
+///
+/// * for a request the respond should be errored with `code: -32001`. The message can be picked by the server.
+/// * notifications should be dropped.
+#[derive(Debug)]
+pub enum Initialize {}
+
+impl Request for Initialize {
+ type Params = InitializeParams;
+ type Result = InitializeResult;
+ const METHOD: &'static str = "initialize";
+}
+
+/// The shutdown request is sent from the client to the server. It asks the server to shut down,
+/// but to not exit (otherwise the response might not be delivered correctly to the client).
+/// There is a separate exit notification that asks the server to exit.
+#[derive(Debug)]
+pub enum Shutdown {}
+
+impl Request for Shutdown {
+ type Params = ();
+ type Result = ();
+ const METHOD: &'static str = "shutdown";
+}
+
+/// The show message request is sent from a server to a client to ask the client to display a particular message
+/// in the user interface. In addition to the show message notification the request allows to pass actions and to
+/// wait for an answer from the client.
+#[derive(Debug)]
+pub enum ShowMessageRequest {}
+
+impl Request for ShowMessageRequest {
+ type Params = ShowMessageRequestParams;
+ type Result = Option<MessageActionItem>;
+ const METHOD: &'static str = "window/showMessageRequest";
+}
+
+/// The client/registerCapability request is sent from the server to the client to register for a new capability
+/// on the client side. Not all clients need to support dynamic capability registration. A client opts in via the
+/// ClientCapabilities.GenericCapability property.
+#[derive(Debug)]
+pub enum RegisterCapability {}
+
+impl Request for RegisterCapability {
+ type Params = RegistrationParams;
+ type Result = ();
+ const METHOD: &'static str = "client/registerCapability";
+}
+
+/// The client/unregisterCapability request is sent from the server to the client to unregister a
+/// previously register capability.
+#[derive(Debug)]
+pub enum UnregisterCapability {}
+
+impl Request for UnregisterCapability {
+ type Params = UnregistrationParams;
+ type Result = ();
+ const METHOD: &'static str = "client/unregisterCapability";
+}
+
+/// The Completion request is sent from the client to the server to compute completion items at a given cursor position.
+/// Completion items are presented in the IntelliSense user interface. If computing full completion items is expensive,
+/// servers can additionally provide a handler for the completion item resolve request ('completionItem/resolve').
+/// This request is sent when a completion item is selected in the user interface. A typical use case is for example:
+/// the 'textDocument/completion' request doesn’t fill in the documentation property for returned completion items
+/// since it is expensive to compute. When the item is selected in the user interface then a ‘completionItem/resolve’
+/// request is sent with the selected completion item as a param. The returned completion item should have the
+/// documentation property filled in. The request can delay the computation of the detail and documentation properties.
+/// However, properties that are needed for the initial sorting and filtering, like sortText, filterText, insertText,
+/// and textEdit must be provided in the textDocument/completion request and must not be changed during resolve.
+#[derive(Debug)]
+pub enum Completion {}
+
+impl Request for Completion {
+ type Params = CompletionParams;
+ type Result = Option<CompletionResponse>;
+ const METHOD: &'static str = "textDocument/completion";
+}
+
+/// The request is sent from the client to the server to resolve additional information for a given completion item.
+#[derive(Debug)]
+pub enum ResolveCompletionItem {}
+
+impl Request for ResolveCompletionItem {
+ type Params = CompletionItem;
+ type Result = CompletionItem;
+ const METHOD: &'static str = "completionItem/resolve";
+}
+
+/// The hover request is sent from the client to the server to request hover information at a given text
+/// document position.
+#[derive(Debug)]
+pub enum HoverRequest {}
+
+impl Request for HoverRequest {
+ type Params = HoverParams;
+ type Result = Option<Hover>;
+ const METHOD: &'static str = "textDocument/hover";
+}
+
+/// The signature help request is sent from the client to the server to request signature information at
+/// a given cursor position.
+#[derive(Debug)]
+pub enum SignatureHelpRequest {}
+
+impl Request for SignatureHelpRequest {
+ type Params = SignatureHelpParams;
+ type Result = Option<SignatureHelp>;
+ const METHOD: &'static str = "textDocument/signatureHelp";
+}
+
+#[derive(Debug)]
+pub enum GotoDeclaration {}
+pub type GotoDeclarationParams = GotoDefinitionParams;
+pub type GotoDeclarationResponse = GotoDefinitionResponse;
+
+/// The goto declaration request is sent from the client to the server to resolve the declaration location of
+/// a symbol at a given text document position.
+impl Request for GotoDeclaration {
+ type Params = GotoDeclarationParams;
+ type Result = Option<GotoDeclarationResponse>;
+ const METHOD: &'static str = "textDocument/declaration";
+}
+
+/// The goto definition request is sent from the client to the server to resolve the definition location of
+/// a symbol at a given text document position.
+#[derive(Debug)]
+pub enum GotoDefinition {}
+
+impl Request for GotoDefinition {
+ type Params = GotoDefinitionParams;
+ type Result = Option<GotoDefinitionResponse>;
+ const METHOD: &'static str = "textDocument/definition";
+}
+
+/// The references request is sent from the client to the server to resolve project-wide references for the
+/// symbol denoted by the given text document position.
+#[derive(Debug)]
+pub enum References {}
+
+impl Request for References {
+ type Params = ReferenceParams;
+ type Result = Option<Vec<Location>>;
+ const METHOD: &'static str = "textDocument/references";
+}
+
+/// The goto type definition request is sent from the client to the
+/// server to resolve the type definition location of a symbol at a
+/// given text document position.
+#[derive(Debug)]
+pub enum GotoTypeDefinition {}
+
+pub type GotoTypeDefinitionParams = GotoDefinitionParams;
+pub type GotoTypeDefinitionResponse = GotoDefinitionResponse;
+
+impl Request for GotoTypeDefinition {
+ type Params = GotoTypeDefinitionParams;
+ type Result = Option<GotoTypeDefinitionResponse>;
+ const METHOD: &'static str = "textDocument/typeDefinition";
+}
+
+/// The goto implementation request is sent from the client to the
+/// server to resolve the implementation location of a symbol at a
+/// given text document position.
+#[derive(Debug)]
+pub enum GotoImplementation {}
+
+pub type GotoImplementationParams = GotoTypeDefinitionParams;
+pub type GotoImplementationResponse = GotoDefinitionResponse;
+
+impl Request for GotoImplementation {
+ type Params = GotoImplementationParams;
+ type Result = Option<GotoImplementationResponse>;
+ const METHOD: &'static str = "textDocument/implementation";
+}
+
+/// The document highlight request is sent from the client to the server to resolve a document highlights
+/// for a given text document position.
+/// For programming languages this usually highlights all references to the symbol scoped to this file.
+/// However we kept 'textDocument/documentHighlight' and 'textDocument/references' separate requests since
+/// the first one is allowed to be more fuzzy.
+/// Symbol matches usually have a DocumentHighlightKind of Read or Write whereas fuzzy or textual matches
+/// use Text as the kind.
+#[derive(Debug)]
+pub enum DocumentHighlightRequest {}
+
+impl Request for DocumentHighlightRequest {
+ type Params = DocumentHighlightParams;
+ type Result = Option<Vec<DocumentHighlight>>;
+ const METHOD: &'static str = "textDocument/documentHighlight";
+}
+
+/// The document symbol request is sent from the client to the server to list all symbols found in a given
+/// text document.
+#[derive(Debug)]
+pub enum DocumentSymbolRequest {}
+
+impl Request for DocumentSymbolRequest {
+ type Params = DocumentSymbolParams;
+ type Result = Option<DocumentSymbolResponse>;
+ const METHOD: &'static str = "textDocument/documentSymbol";
+}
+
+/// The workspace symbol request is sent from the client to the server to list project-wide symbols
+/// matching the query string.
+#[derive(Debug)]
+pub enum WorkspaceSymbolRequest {}
+
+impl Request for WorkspaceSymbolRequest {
+ type Params = WorkspaceSymbolParams;
+ type Result = Option<WorkspaceSymbolResponse>;
+ const METHOD: &'static str = "workspace/symbol";
+}
+
+/// The `workspaceSymbol/resolve` request is sent from the client to the server to resolve
+/// additional information for a given workspace symbol.
+#[derive(Debug)]
+pub enum WorkspaceSymbolResolve {}
+
+impl Request for WorkspaceSymbolResolve {
+ type Params = WorkspaceSymbol;
+ type Result = WorkspaceSymbol;
+ const METHOD: &'static str = "workspaceSymbol/resolve";
+}
+
+/// The workspace/executeCommand request is sent from the client to the server to trigger command execution on the server.
+/// In most cases the server creates a WorkspaceEdit structure and applies the changes to the workspace using the request
+/// workspace/applyEdit which is sent from the server to the client.
+#[derive(Debug)]
+pub enum ExecuteCommand {}
+
+impl Request for ExecuteCommand {
+ type Params = ExecuteCommandParams;
+ type Result = Option<Value>;
+ const METHOD: &'static str = "workspace/executeCommand";
+}
+
+/// The document will save request is sent from the client to the server before the document is
+/// actually saved. The request can return an array of TextEdits which will be applied to the text
+/// document before it is saved. Please note that clients might drop results if computing the text
+/// edits took too long or if a server constantly fails on this request. This is done to keep the
+/// save fast and reliable.
+#[derive(Debug)]
+pub enum WillSaveWaitUntil {}
+
+impl Request for WillSaveWaitUntil {
+ type Params = WillSaveTextDocumentParams;
+ type Result = Option<Vec<TextEdit>>;
+ const METHOD: &'static str = "textDocument/willSaveWaitUntil";
+}
+
+/// The workspace/applyEdit request is sent from the server to the client to modify resource on the
+/// client side.
+#[derive(Debug)]
+pub enum ApplyWorkspaceEdit {}
+
+impl Request for ApplyWorkspaceEdit {
+ type Params = ApplyWorkspaceEditParams;
+ type Result = ApplyWorkspaceEditResponse;
+ const METHOD: &'static str = "workspace/applyEdit";
+}
+
+/// The workspace/configuration request is sent from the server to the client to fetch configuration settings
+/// from the client. The request can fetch several configuration settings in one roundtrip.
+/// The order of the returned configuration settings correspond to the order of the passed ConfigurationItems
+/// (e.g. the first item in the response is the result for the first configuration item in the params).
+///
+/// A ConfigurationItem consists of the configuration section to ask for and an additional scope URI.
+/// The configuration section ask for is defined by the server and doesn’t necessarily need to correspond to
+/// the configuration store used be the client. So a server might ask for a configuration cpp.formatterOptions
+/// but the client stores the configuration in a XML store layout differently.
+/// It is up to the client to do the necessary conversion. If a scope URI is provided the client should return
+/// the setting scoped to the provided resource. If the client for example uses EditorConfig to manage its
+/// settings the configuration should be returned for the passed resource URI. If the client can’t provide a
+/// configuration setting for a given scope then null need to be present in the returned array.
+#[derive(Debug)]
+pub enum WorkspaceConfiguration {}
+
+impl Request for WorkspaceConfiguration {
+ type Params = ConfigurationParams;
+ type Result = Vec<Value>;
+ const METHOD: &'static str = "workspace/configuration";
+}
+
+/// The code action request is sent from the client to the server to compute commands for a given text document
+/// and range. The request is triggered when the user moves the cursor into a problem marker in the editor or
+/// presses the lightbulb associated with a marker.
+#[derive(Debug)]
+pub enum CodeActionRequest {}
+
+impl Request for CodeActionRequest {
+ type Params = CodeActionParams;
+ type Result = Option<CodeActionResponse>;
+ const METHOD: &'static str = "textDocument/codeAction";
+}
+
+/// The request is sent from the client to the server to resolve additional information for a given code action.
+/// This is usually used to compute the `edit` property of a code action to avoid its unnecessary computation
+/// during the `textDocument/codeAction` request.
+///
+/// since 3.16.0
+#[derive(Debug)]
+pub enum CodeActionResolveRequest {}
+
+impl Request for CodeActionResolveRequest {
+ type Params = CodeAction;
+ type Result = CodeAction;
+ const METHOD: &'static str = "codeAction/resolve";
+}
+
+/// The code lens request is sent from the client to the server to compute code lenses for a given text document.
+#[derive(Debug)]
+pub enum CodeLensRequest {}
+
+impl Request for CodeLensRequest {
+ type Params = CodeLensParams;
+ type Result = Option<Vec<CodeLens>>;
+ const METHOD: &'static str = "textDocument/codeLens";
+}
+
+/// The code lens resolve request is sent from the client to the server to resolve the command for a
+/// given code lens item.
+#[derive(Debug)]
+pub enum CodeLensResolve {}
+
+impl Request for CodeLensResolve {
+ type Params = CodeLens;
+ type Result = CodeLens;
+ const METHOD: &'static str = "codeLens/resolve";
+}
+
+/// The document links request is sent from the client to the server to request the location of links in a document.
+#[derive(Debug)]
+pub enum DocumentLinkRequest {}
+
+impl Request for DocumentLinkRequest {
+ type Params = DocumentLinkParams;
+ type Result = Option<Vec<DocumentLink>>;
+ const METHOD: &'static str = "textDocument/documentLink";
+}
+
+/// The document link resolve request is sent from the client to the server to resolve the target of
+/// a given document link.
+#[derive(Debug)]
+pub enum DocumentLinkResolve {}
+
+impl Request for DocumentLinkResolve {
+ type Params = DocumentLink;
+ type Result = DocumentLink;
+ const METHOD: &'static str = "documentLink/resolve";
+}
+
+/// The document formatting request is sent from the server to the client to format a whole document.
+#[derive(Debug)]
+pub enum Formatting {}
+
+impl Request for Formatting {
+ type Params = DocumentFormattingParams;
+ type Result = Option<Vec<TextEdit>>;
+ const METHOD: &'static str = "textDocument/formatting";
+}
+
+/// The document range formatting request is sent from the client to the server to format a given range in a document.
+#[derive(Debug)]
+pub enum RangeFormatting {}
+
+impl Request for RangeFormatting {
+ type Params = DocumentRangeFormattingParams;
+ type Result = Option<Vec<TextEdit>>;
+ const METHOD: &'static str = "textDocument/rangeFormatting";
+}
+
+/// The document on type formatting request is sent from the client to the server to format parts of
+/// the document during typing.
+#[derive(Debug)]
+pub enum OnTypeFormatting {}
+
+impl Request for OnTypeFormatting {
+ type Params = DocumentOnTypeFormattingParams;
+ type Result = Option<Vec<TextEdit>>;
+ const METHOD: &'static str = "textDocument/onTypeFormatting";
+}
+
+/// The linked editing request is sent from the client to the server to return for a given position in a document
+/// the range of the symbol at the position and all ranges that have the same content.
+/// Optionally a word pattern can be returned to describe valid contents. A rename to one of the ranges can be applied
+/// to all other ranges if the new content is valid. If no result-specific word pattern is provided, the word pattern from
+/// the client’s language configuration is used.
+#[derive(Debug)]
+pub enum LinkedEditingRange {}
+
+impl Request for LinkedEditingRange {
+ type Params = LinkedEditingRangeParams;
+ type Result = Option<LinkedEditingRanges>;
+ const METHOD: &'static str = "textDocument/linkedEditingRange";
+}
+
+/// The rename request is sent from the client to the server to perform a workspace-wide rename of a symbol.
+#[derive(Debug)]
+pub enum Rename {}
+
+impl Request for Rename {
+ type Params = RenameParams;
+ type Result = Option<WorkspaceEdit>;
+ const METHOD: &'static str = "textDocument/rename";
+}
+
+/// The document color request is sent from the client to the server to list all color references found in a given text document.
+/// Along with the range, a color value in RGB is returned.
+#[derive(Debug)]
+pub enum DocumentColor {}
+
+impl Request for DocumentColor {
+ type Params = DocumentColorParams;
+ type Result = Vec<ColorInformation>;
+ const METHOD: &'static str = "textDocument/documentColor";
+}
+
+/// The color presentation request is sent from the client to the server to obtain a list of presentations for a color value
+/// at a given location.
+#[derive(Debug)]
+pub enum ColorPresentationRequest {}
+
+impl Request for ColorPresentationRequest {
+ type Params = ColorPresentationParams;
+ type Result = Vec<ColorPresentation>;
+ const METHOD: &'static str = "textDocument/colorPresentation";
+}
+
+/// The folding range request is sent from the client to the server to return all folding ranges found in a given text document.
+#[derive(Debug)]
+pub enum FoldingRangeRequest {}
+
+impl Request for FoldingRangeRequest {
+ type Params = FoldingRangeParams;
+ type Result = Option<Vec<FoldingRange>>;
+ const METHOD: &'static str = "textDocument/foldingRange";
+}
+
+/// The prepare rename request is sent from the client to the server to setup and test the validity of a rename operation
+/// at a given location.
+#[derive(Debug)]
+pub enum PrepareRenameRequest {}
+
+impl Request for PrepareRenameRequest {
+ type Params = TextDocumentPositionParams;
+ type Result = Option<PrepareRenameResponse>;
+ const METHOD: &'static str = "textDocument/prepareRename";
+}
+
+/// The workspace/workspaceFolders request is sent from the server to the client to fetch the current open list of
+/// workspace folders. Returns null in the response if only a single file is open in the tool.
+/// Returns an empty array if a workspace is open but no folders are configured.
+#[derive(Debug)]
+pub enum WorkspaceFoldersRequest {}
+
+impl Request for WorkspaceFoldersRequest {
+ type Params = ();
+ type Result = Option<Vec<WorkspaceFolder>>;
+ const METHOD: &'static str = "workspace/workspaceFolders";
+}
+
+/// The `window/workDoneProgress/create` request is sent from the server
+/// to the clientto ask the client to create a work done progress.
+#[derive(Debug)]
+pub enum WorkDoneProgressCreate {}
+
+impl Request for WorkDoneProgressCreate {
+ type Params = WorkDoneProgressCreateParams;
+ type Result = ();
+ const METHOD: &'static str = "window/workDoneProgress/create";
+}
+
+/// The selection range request is sent from the client to the server to return
+/// suggested selection ranges at given positions. A selection range is a range
+/// around the cursor position which the user might be interested in selecting.
+///
+/// A selection range in the return array is for the position in the provided parameters at the same index.
+/// Therefore `positions[i]` must be contained in `result[i].range`.
+///
+/// Typically, but not necessary, selection ranges correspond to the nodes of the
+/// syntax tree.
+pub enum SelectionRangeRequest {}
+
+impl Request for SelectionRangeRequest {
+ type Params = SelectionRangeParams;
+ type Result = Option<Vec<SelectionRange>>;
+ const METHOD: &'static str = "textDocument/selectionRange";
+}
+
+pub enum CallHierarchyPrepare {}
+
+impl Request for CallHierarchyPrepare {
+ type Params = CallHierarchyPrepareParams;
+ type Result = Option<Vec<CallHierarchyItem>>;
+ const METHOD: &'static str = "textDocument/prepareCallHierarchy";
+}
+
+pub enum CallHierarchyIncomingCalls {}
+
+impl Request for CallHierarchyIncomingCalls {
+ type Params = CallHierarchyIncomingCallsParams;
+ type Result = Option<Vec<CallHierarchyIncomingCall>>;
+ const METHOD: &'static str = "callHierarchy/incomingCalls";
+}
+
+pub enum CallHierarchyOutgoingCalls {}
+
+impl Request for CallHierarchyOutgoingCalls {
+ type Params = CallHierarchyOutgoingCallsParams;
+ type Result = Option<Vec<CallHierarchyOutgoingCall>>;
+ const METHOD: &'static str = "callHierarchy/outgoingCalls";
+}
+
+pub enum SemanticTokensFullRequest {}
+
+impl Request for SemanticTokensFullRequest {
+ type Params = SemanticTokensParams;
+ type Result = Option<SemanticTokensResult>;
+ const METHOD: &'static str = "textDocument/semanticTokens/full";
+}
+
+pub enum SemanticTokensFullDeltaRequest {}
+
+impl Request for SemanticTokensFullDeltaRequest {
+ type Params = SemanticTokensDeltaParams;
+ type Result = Option<SemanticTokensFullDeltaResult>;
+ const METHOD: &'static str = "textDocument/semanticTokens/full/delta";
+}
+
+pub enum SemanticTokensRangeRequest {}
+
+impl Request for SemanticTokensRangeRequest {
+ type Params = SemanticTokensRangeParams;
+ type Result = Option<SemanticTokensRangeResult>;
+ const METHOD: &'static str = "textDocument/semanticTokens/range";
+}
+
+/// The `workspace/semanticTokens/refresh` request is sent from the server to the client.
+/// Servers can use it to ask clients to refresh the editors for which this server provides semantic tokens.
+/// As a result the client should ask the server to recompute the semantic tokens for these editors.
+/// This is useful if a server detects a project wide configuration change which requires a re-calculation of all semantic tokens.
+/// Note that the client still has the freedom to delay the re-calculation of the semantic tokens if for example an editor is currently not visible.
+pub enum SemanticTokensRefresh {}
+
+impl Request for SemanticTokensRefresh {
+ type Params = ();
+ type Result = ();
+ const METHOD: &'static str = "workspace/semanticTokens/refresh";
+}
+
+/// The workspace/codeLens/refresh request is sent from the server to the client.
+/// Servers can use it to ask clients to refresh the code lenses currently shown in editors.
+/// As a result the client should ask the server to recompute the code lenses for these editors.
+/// This is useful if a server detects a configuration change which requires a re-calculation of all code lenses.
+/// Note that the client still has the freedom to delay the re-calculation of the code lenses if for example an editor is currently not visible.
+pub enum CodeLensRefresh {}
+
+impl Request for CodeLensRefresh {
+ type Params = ();
+ type Result = ();
+ const METHOD: &'static str = "workspace/codeLens/refresh";
+}
+
+/// The will create files request is sent from the client to the server before files are actually created as long as the creation is triggered from within the client. The request can return a WorkspaceEdit which will be applied to workspace before the files are created. Please note that clients might drop results if computing the edit took too long or if a server constantly fails on this request. This is done to keep creates fast and reliable.
+pub enum WillCreateFiles {}
+
+impl Request for WillCreateFiles {
+ type Params = CreateFilesParams;
+ type Result = Option<WorkspaceEdit>;
+ const METHOD: &'static str = "workspace/willCreateFiles";
+}
+
+/// The will rename files request is sent from the client to the server before files are actually renamed as long as the rename is triggered from within the client. The request can return a WorkspaceEdit which will be applied to workspace before the files are renamed. Please note that clients might drop results if computing the edit took too long or if a server constantly fails on this request. This is done to keep renames fast and reliable.
+pub enum WillRenameFiles {}
+
+impl Request for WillRenameFiles {
+ type Params = RenameFilesParams;
+ type Result = Option<WorkspaceEdit>;
+ const METHOD: &'static str = "workspace/willRenameFiles";
+}
+
+/// The will delete files request is sent from the client to the server before files are actually deleted as long as the deletion is triggered from within the client. The request can return a WorkspaceEdit which will be applied to workspace before the files are deleted. Please note that clients might drop results if computing the edit took too long or if a server constantly fails on this request. This is done to keep deletes fast and reliable.
+pub enum WillDeleteFiles {}
+
+impl Request for WillDeleteFiles {
+ type Params = DeleteFilesParams;
+ type Result = Option<WorkspaceEdit>;
+ const METHOD: &'static str = "workspace/willDeleteFiles";
+}
+
+/// The show document request is sent from a server to a client to ask the client to display a particular document in the user interface.
+pub enum ShowDocument {}
+
+impl Request for ShowDocument {
+ type Params = ShowDocumentParams;
+ type Result = ShowDocumentResult;
+ const METHOD: &'static str = "window/showDocument";
+}
+
+pub enum MonikerRequest {}
+
+impl Request for MonikerRequest {
+ type Params = MonikerParams;
+ type Result = Option<Vec<Moniker>>;
+ const METHOD: &'static str = "textDocument/moniker";
+}
+
+/// The inlay hints request is sent from the client to the server to compute inlay hints for a given
+/// [text document, range] tuple that may be rendered in the editor in place with other text.
+pub enum InlayHintRequest {}
+
+impl Request for InlayHintRequest {
+ type Params = InlayHintParams;
+ type Result = Option<Vec<InlayHint>>;
+ const METHOD: &'static str = "textDocument/inlayHint";
+}
+
+/// The `inlayHint/resolve` request is sent from the client to the server to resolve additional
+/// information for a given inlay hint. This is usually used to compute the tooltip, location or
+/// command properties of a inlay hint’s label part to avoid its unnecessary computation during the
+/// `textDocument/inlayHint` request.
+pub enum InlayHintResolveRequest {}
+
+impl Request for InlayHintResolveRequest {
+ type Params = InlayHint;
+ type Result = InlayHint;
+ const METHOD: &'static str = "inlayHint/resolve";
+}
+
+/// The `workspace/inlayHint/refresh` request is sent from the server to the client. Servers can use
+/// it to ask clients to refresh the inlay hints currently shown in editors. As a result the client
+/// should ask the server to recompute the inlay hints for these editors. This is useful if a server
+/// detects a configuration change which requires a re-calculation of all inlay hints. Note that the
+/// client still has the freedom to delay the re-calculation of the inlay hints if for example an
+/// editor is currently not visible.
+pub enum InlayHintRefreshRequest {}
+
+impl Request for InlayHintRefreshRequest {
+ type Params = ();
+ type Result = ();
+ const METHOD: &'static str = "workspace/inlayHint/refresh";
+}
+
+/// The inline value request is sent from the client to the server to compute inline values for a
+/// given text document that may be rendered in the editor at the end of lines.
+pub enum InlineValueRequest {}
+
+impl Request for InlineValueRequest {
+ type Params = InlineValueParams;
+ type Result = Option<InlineValue>;
+ const METHOD: &'static str = "textDocument/inlineValue";
+}
+
+/// The `workspace/inlineValue/refresh` request is sent from the server to the client. Servers can
+/// use it to ask clients to refresh the inline values currently shown in editors. As a result the
+/// client should ask the server to recompute the inline values for these editors. This is useful if
+/// a server detects a configuration change which requires a re-calculation of all inline values.
+/// Note that the client still has the freedom to delay the re-calculation of the inline values if
+/// for example an editor is currently not visible.
+pub enum InlineValueRefreshRequest {}
+
+impl Request for InlineValueRefreshRequest {
+ type Params = ();
+ type Result = ();
+ const METHOD: &'static str = "workspace/inlineValue/refresh";
+}
+
+/// The type hierarchy request is sent from the client to the server to return a type hierarchy for
+/// the language element of given text document positions. Will return null if the server couldn’t
+/// infer a valid type from the position. The type hierarchy requests are executed in two steps:
+///
+/// 1. first a type hierarchy item is prepared for the given text document position.
+/// 2. for a type hierarchy item the supertype or subtype type hierarchy items are resolved.
+pub enum TypeHierarchyPrepare {}
+
+impl Request for TypeHierarchyPrepare {
+ type Params = TypeHierarchyPrepareParams;
+ type Result = Option<Vec<TypeHierarchyItem>>;
+ const METHOD: &'static str = "textDocument/prepareTypeHierarchy";
+}
+
+/// The `typeHierarchy/supertypes` request is sent from the client to the server to resolve the
+/// supertypes for a given type hierarchy item. Will return null if the server couldn’t infer a
+/// valid type from item in the params. The request doesn’t define its own client and server
+/// capabilities. It is only issued if a server registers for the
+/// `textDocument/prepareTypeHierarchy` request.
+pub enum TypeHierarchySupertypes {}
+
+impl Request for TypeHierarchySupertypes {
+ type Params = TypeHierarchySupertypesParams;
+ type Result = Option<Vec<TypeHierarchyItem>>;
+ const METHOD: &'static str = "typeHierarchy/supertypes";
+}
+
+/// The `typeHierarchy/subtypes` request is sent from the client to the server to resolve the
+/// subtypes for a given type hierarchy item. Will return null if the server couldn’t infer a valid
+/// type from item in the params. The request doesn’t define its own client and server capabilities.
+/// It is only issued if a server registers for the textDocument/prepareTypeHierarchy request.
+pub enum TypeHierarchySubtypes {}
+
+impl Request for TypeHierarchySubtypes {
+ type Params = TypeHierarchySubtypesParams;
+ type Result = Option<Vec<TypeHierarchyItem>>;
+ const METHOD: &'static str = "typeHierarchy/subtypes";
+}
+
+#[cfg(test)]
+mod test {
+ use super::*;
+
+ fn fake_call<R>()
+ where
+ R: Request,
+ R::Params: serde::Serialize,
+ R::Result: serde::de::DeserializeOwned,
+ {
+ }
+
+ macro_rules! check_macro {
+ ($name:tt) => {
+ // check whethe the macro name matches the method
+ assert_eq!(<lsp_request!($name) as Request>::METHOD, $name);
+ // test whether type checking passes for each component
+ fake_call::<lsp_request!($name)>();
+ };
+ }
+
+ #[test]
+ fn check_macro_definitions() {
+ check_macro!("initialize");
+ check_macro!("shutdown");
+
+ check_macro!("window/showDocument");
+ check_macro!("window/showMessageRequest");
+ check_macro!("window/workDoneProgress/create");
+
+ check_macro!("client/registerCapability");
+ check_macro!("client/unregisterCapability");
+
+ check_macro!("textDocument/willSaveWaitUntil");
+ check_macro!("textDocument/completion");
+ check_macro!("textDocument/hover");
+ check_macro!("textDocument/signatureHelp");
+ check_macro!("textDocument/declaration");
+ check_macro!("textDocument/definition");
+ check_macro!("textDocument/references");
+ check_macro!("textDocument/documentHighlight");
+ check_macro!("textDocument/documentSymbol");
+ check_macro!("textDocument/codeAction");
+ check_macro!("textDocument/codeLens");
+ check_macro!("textDocument/documentLink");
+ check_macro!("textDocument/rangeFormatting");
+ check_macro!("textDocument/onTypeFormatting");
+ check_macro!("textDocument/formatting");
+ check_macro!("textDocument/rename");
+ check_macro!("textDocument/documentColor");
+ check_macro!("textDocument/colorPresentation");
+ check_macro!("textDocument/foldingRange");
+ check_macro!("textDocument/prepareRename");
+ check_macro!("textDocument/implementation");
+ check_macro!("textDocument/selectionRange");
+ check_macro!("textDocument/typeDefinition");
+ check_macro!("textDocument/moniker");
+ check_macro!("textDocument/linkedEditingRange");
+ check_macro!("textDocument/prepareCallHierarchy");
+ check_macro!("textDocument/prepareTypeHierarchy");
+ check_macro!("textDocument/semanticTokens/full");
+ check_macro!("textDocument/semanticTokens/full/delta");
+ check_macro!("textDocument/semanticTokens/range");
+ check_macro!("textDocument/inlayHint");
+ check_macro!("textDocument/inlineValue");
+
+ check_macro!("workspace/applyEdit");
+ check_macro!("workspace/symbol");
+ check_macro!("workspace/executeCommand");
+ check_macro!("workspace/configuration");
+ check_macro!("workspace/willCreateFiles");
+ check_macro!("workspace/willRenameFiles");
+ check_macro!("workspace/willDeleteFiles");
+ check_macro!("workspace/workspaceFolders");
+ check_macro!("workspace/semanticTokens/refresh");
+ check_macro!("workspace/codeLens/refresh");
+ check_macro!("workspace/inlayHint/refresh");
+ check_macro!("workspace/inlineValue/refresh");
+
+ check_macro!("callHierarchy/incomingCalls");
+ check_macro!("callHierarchy/outgoingCalls");
+ check_macro!("codeAction/resolve");
+ check_macro!("codeLens/resolve");
+ check_macro!("completionItem/resolve");
+ check_macro!("documentLink/resolve");
+ check_macro!("inlayHint/resolve");
+ check_macro!("typeHierarchy/subtypes");
+ check_macro!("typeHierarchy/supertypes");
+ }
+
+ #[test]
+ #[cfg(feature = "proposed")]
+ fn check_proposed_macro_definitions() {}
+}
diff --git a/vendor/lsp-types/src/selection_range.rs b/vendor/lsp-types/src/selection_range.rs
index 048df6f99..9ad110678 100644
--- a/vendor/lsp-types/src/selection_range.rs
+++ b/vendor/lsp-types/src/selection_range.rs
@@ -1,86 +1,86 @@
-use serde::{Deserialize, Serialize};
-
-use crate::{
- PartialResultParams, Position, Range, StaticTextDocumentRegistrationOptions,
- TextDocumentIdentifier, WorkDoneProgressOptions, WorkDoneProgressParams,
-};
-#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
-#[serde(rename_all = "camelCase")]
-pub struct SelectionRangeClientCapabilities {
- /// Whether implementation supports dynamic registration for selection range
- /// providers. If this is set to `true` the client supports the new
- /// `SelectionRangeRegistrationOptions` return value for the corresponding
- /// server capability as well.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub dynamic_registration: Option<bool>,
-}
-
-#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
-pub struct SelectionRangeOptions {
- #[serde(flatten)]
- pub work_done_progress_options: WorkDoneProgressOptions,
-}
-
-#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
-pub struct SelectionRangeRegistrationOptions {
- #[serde(flatten)]
- pub selection_range_options: SelectionRangeOptions,
-
- #[serde(flatten)]
- pub registration_options: StaticTextDocumentRegistrationOptions,
-}
-
-#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
-#[serde(untagged)]
-pub enum SelectionRangeProviderCapability {
- Simple(bool),
- Options(SelectionRangeOptions),
- RegistrationOptions(SelectionRangeRegistrationOptions),
-}
-
-impl From<SelectionRangeRegistrationOptions> for SelectionRangeProviderCapability {
- fn from(from: SelectionRangeRegistrationOptions) -> Self {
- Self::RegistrationOptions(from)
- }
-}
-
-impl From<SelectionRangeOptions> for SelectionRangeProviderCapability {
- fn from(from: SelectionRangeOptions) -> Self {
- Self::Options(from)
- }
-}
-
-impl From<bool> for SelectionRangeProviderCapability {
- fn from(from: bool) -> Self {
- Self::Simple(from)
- }
-}
-
-/// A parameter literal used in selection range requests.
-#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
-#[serde(rename_all = "camelCase")]
-pub struct SelectionRangeParams {
- /// The text document.
- pub text_document: TextDocumentIdentifier,
-
- /// The positions inside the text document.
- pub positions: Vec<Position>,
-
- #[serde(flatten)]
- pub work_done_progress_params: WorkDoneProgressParams,
-
- #[serde(flatten)]
- pub partial_result_params: PartialResultParams,
-}
-
-/// Represents a selection range.
-#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
-#[serde(rename_all = "camelCase")]
-pub struct SelectionRange {
- /// Range of the selection.
- pub range: Range,
-
- /// The parent selection range containing this range.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub parent: Option<Box<SelectionRange>>,
-}
+use serde::{Deserialize, Serialize};
+
+use crate::{
+ PartialResultParams, Position, Range, StaticTextDocumentRegistrationOptions,
+ TextDocumentIdentifier, WorkDoneProgressOptions, WorkDoneProgressParams,
+};
+#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct SelectionRangeClientCapabilities {
+ /// Whether implementation supports dynamic registration for selection range
+ /// providers. If this is set to `true` the client supports the new
+ /// `SelectionRangeRegistrationOptions` return value for the corresponding
+ /// server capability as well.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub dynamic_registration: Option<bool>,
+}
+
+#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
+pub struct SelectionRangeOptions {
+ #[serde(flatten)]
+ pub work_done_progress_options: WorkDoneProgressOptions,
+}
+
+#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
+pub struct SelectionRangeRegistrationOptions {
+ #[serde(flatten)]
+ pub selection_range_options: SelectionRangeOptions,
+
+ #[serde(flatten)]
+ pub registration_options: StaticTextDocumentRegistrationOptions,
+}
+
+#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
+#[serde(untagged)]
+pub enum SelectionRangeProviderCapability {
+ Simple(bool),
+ Options(SelectionRangeOptions),
+ RegistrationOptions(SelectionRangeRegistrationOptions),
+}
+
+impl From<SelectionRangeRegistrationOptions> for SelectionRangeProviderCapability {
+ fn from(from: SelectionRangeRegistrationOptions) -> Self {
+ Self::RegistrationOptions(from)
+ }
+}
+
+impl From<SelectionRangeOptions> for SelectionRangeProviderCapability {
+ fn from(from: SelectionRangeOptions) -> Self {
+ Self::Options(from)
+ }
+}
+
+impl From<bool> for SelectionRangeProviderCapability {
+ fn from(from: bool) -> Self {
+ Self::Simple(from)
+ }
+}
+
+/// A parameter literal used in selection range requests.
+#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct SelectionRangeParams {
+ /// The text document.
+ pub text_document: TextDocumentIdentifier,
+
+ /// The positions inside the text document.
+ pub positions: Vec<Position>,
+
+ #[serde(flatten)]
+ pub work_done_progress_params: WorkDoneProgressParams,
+
+ #[serde(flatten)]
+ pub partial_result_params: PartialResultParams,
+}
+
+/// Represents a selection range.
+#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct SelectionRange {
+ /// Range of the selection.
+ pub range: Range,
+
+ /// The parent selection range containing this range.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub parent: Option<Box<SelectionRange>>,
+}
diff --git a/vendor/lsp-types/src/semantic_tokens.rs b/vendor/lsp-types/src/semantic_tokens.rs
index f1b6d53d2..0b881850c 100644
--- a/vendor/lsp-types/src/semantic_tokens.rs
+++ b/vendor/lsp-types/src/semantic_tokens.rs
@@ -1,739 +1,733 @@
-use std::borrow::Cow;
-
-use serde::ser::SerializeSeq;
-use serde::{Deserialize, Serialize};
-
-use crate::{
- PartialResultParams, Range, StaticRegistrationOptions, TextDocumentIdentifier,
- TextDocumentRegistrationOptions, WorkDoneProgressOptions, WorkDoneProgressParams,
-};
-/// A set of predefined token types. This set is not fixed
-/// and clients can specify additional token types via the
-/// corresponding client capabilities.
-/// since @3.16.0
-#[derive(Debug, Eq, PartialEq, Hash, PartialOrd, Clone, Deserialize, Serialize)]
-pub struct SemanticTokenType(Cow<'static, str>);
-
-impl SemanticTokenType {
- pub const NAMESPACE: SemanticTokenType = SemanticTokenType::new("namespace");
- pub const TYPE: SemanticTokenType = SemanticTokenType::new("type");
- pub const CLASS: SemanticTokenType = SemanticTokenType::new("class");
- pub const ENUM: SemanticTokenType = SemanticTokenType::new("enum");
- pub const INTERFACE: SemanticTokenType = SemanticTokenType::new("interface");
- pub const STRUCT: SemanticTokenType = SemanticTokenType::new("struct");
- pub const TYPE_PARAMETER: SemanticTokenType = SemanticTokenType::new("typeParameter");
- pub const PARAMETER: SemanticTokenType = SemanticTokenType::new("parameter");
- pub const VARIABLE: SemanticTokenType = SemanticTokenType::new("variable");
- pub const PROPERTY: SemanticTokenType = SemanticTokenType::new("property");
- pub const ENUM_MEMBER: SemanticTokenType = SemanticTokenType::new("enumMember");
- pub const EVENT: SemanticTokenType = SemanticTokenType::new("event");
- pub const FUNCTION: SemanticTokenType = SemanticTokenType::new("function");
- pub const METHOD: SemanticTokenType = SemanticTokenType::new("method");
- pub const MACRO: SemanticTokenType = SemanticTokenType::new("macro");
- pub const KEYWORD: SemanticTokenType = SemanticTokenType::new("keyword");
- pub const MODIFIER: SemanticTokenType = SemanticTokenType::new("modifier");
- pub const COMMENT: SemanticTokenType = SemanticTokenType::new("comment");
- pub const STRING: SemanticTokenType = SemanticTokenType::new("string");
- pub const NUMBER: SemanticTokenType = SemanticTokenType::new("number");
- pub const REGEXP: SemanticTokenType = SemanticTokenType::new("regexp");
- pub const OPERATOR: SemanticTokenType = SemanticTokenType::new("operator");
-
- /// since @3.17.0
- #[cfg(feature = "proposed")]
- pub const DECORATOR: SemanticTokenType = SemanticTokenType::new("decorator");
-
- pub const fn new(tag: &'static str) -> Self {
- SemanticTokenType(Cow::Borrowed(tag))
- }
-
- pub fn as_str(&self) -> &str {
- &self.0
- }
-}
-
-impl From<String> for SemanticTokenType {
- fn from(from: String) -> Self {
- SemanticTokenType(Cow::from(from))
- }
-}
-
-impl From<&'static str> for SemanticTokenType {
- fn from(from: &'static str) -> Self {
- SemanticTokenType::new(from)
- }
-}
-
-/// A set of predefined token modifiers. This set is not fixed
-/// and clients can specify additional token types via the
-/// corresponding client capabilities.
-///
-/// @since 3.16.0
-#[derive(Debug, Eq, PartialEq, Hash, PartialOrd, Clone, Deserialize, Serialize)]
-pub struct SemanticTokenModifier(Cow<'static, str>);
-
-impl SemanticTokenModifier {
- pub const DECLARATION: SemanticTokenModifier = SemanticTokenModifier::new("declaration");
- pub const DEFINITION: SemanticTokenModifier = SemanticTokenModifier::new("definition");
- pub const READONLY: SemanticTokenModifier = SemanticTokenModifier::new("readonly");
- pub const STATIC: SemanticTokenModifier = SemanticTokenModifier::new("static");
- pub const DEPRECATED: SemanticTokenModifier = SemanticTokenModifier::new("deprecated");
- pub const ABSTRACT: SemanticTokenModifier = SemanticTokenModifier::new("abstract");
- pub const ASYNC: SemanticTokenModifier = SemanticTokenModifier::new("async");
- pub const MODIFICATION: SemanticTokenModifier = SemanticTokenModifier::new("modification");
- pub const DOCUMENTATION: SemanticTokenModifier = SemanticTokenModifier::new("documentation");
- pub const DEFAULT_LIBRARY: SemanticTokenModifier = SemanticTokenModifier::new("defaultLibrary");
-
- pub const fn new(tag: &'static str) -> Self {
- SemanticTokenModifier(Cow::Borrowed(tag))
- }
-
- pub fn as_str(&self) -> &str {
- &self.0
- }
-}
-
-impl From<String> for SemanticTokenModifier {
- fn from(from: String) -> Self {
- SemanticTokenModifier(Cow::from(from))
- }
-}
-
-impl From<&'static str> for SemanticTokenModifier {
- fn from(from: &'static str) -> Self {
- SemanticTokenModifier::new(from)
- }
-}
-
-#[derive(Debug, Eq, PartialEq, Hash, PartialOrd, Clone, Deserialize, Serialize)]
-pub struct TokenFormat(Cow<'static, str>);
-
-impl TokenFormat {
- pub const RELATIVE: TokenFormat = TokenFormat::new("relative");
-
- pub const fn new(tag: &'static str) -> Self {
- TokenFormat(Cow::Borrowed(tag))
- }
-
- pub fn as_str(&self) -> &str {
- &self.0
- }
-}
-
-impl From<String> for TokenFormat {
- fn from(from: String) -> Self {
- TokenFormat(Cow::from(from))
- }
-}
-
-impl From<&'static str> for TokenFormat {
- fn from(from: &'static str) -> Self {
- TokenFormat::new(from)
- }
-}
-
-/// @since 3.16.0
-#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
-#[serde(rename_all = "camelCase")]
-pub struct SemanticTokensLegend {
- /// The token types a server uses.
- pub token_types: Vec<SemanticTokenType>,
-
- /// The token modifiers a server uses.
- pub token_modifiers: Vec<SemanticTokenModifier>,
-}
-
-/// The actual tokens. For a detailed description about how the data is
-/// structured please see
-/// <https://github.com/microsoft/vscode-extension-samples/blob/5ae1f7787122812dcc84e37427ca90af5ee09f14/semantic-tokens-sample/vscode.proposed.d.ts#L71>
-#[derive(Debug, Eq, PartialEq, Copy, Clone, Default)]
-pub struct SemanticToken {
- pub delta_line: u32,
- pub delta_start: u32,
- pub length: u32,
- pub token_type: u32,
- pub token_modifiers_bitset: u32,
-}
-
-impl SemanticToken {
- fn deserialize_tokens<'de, D>(deserializer: D) -> Result<Vec<SemanticToken>, D::Error>
- where
- D: serde::Deserializer<'de>,
- {
- let data = Vec::<u32>::deserialize(deserializer)?;
- let chunks = data.chunks_exact(5);
-
- if !chunks.remainder().is_empty() {
- return Result::Err(serde::de::Error::custom("Length is not divisible by 5"));
- }
-
- Result::Ok(
- chunks
- .map(|chunk| SemanticToken {
- delta_line: chunk[0],
- delta_start: chunk[1],
- length: chunk[2],
- token_type: chunk[3],
- token_modifiers_bitset: chunk[4],
- })
- .collect(),
- )
- }
-
- fn serialize_tokens<S>(tokens: &[SemanticToken], serializer: S) -> Result<S::Ok, S::Error>
- where
- S: serde::Serializer,
- {
- let mut seq = serializer.serialize_seq(Some(tokens.len() * 5))?;
- for token in tokens.iter() {
- seq.serialize_element(&token.delta_line)?;
- seq.serialize_element(&token.delta_start)?;
- seq.serialize_element(&token.length)?;
- seq.serialize_element(&token.token_type)?;
- seq.serialize_element(&token.token_modifiers_bitset)?;
- }
- seq.end()
- }
-
- fn deserialize_tokens_opt<'de, D>(
- deserializer: D,
- ) -> Result<Option<Vec<SemanticToken>>, D::Error>
- where
- D: serde::Deserializer<'de>,
- {
- #[derive(Deserialize)]
- #[serde(transparent)]
- struct Wrapper {
- #[serde(deserialize_with = "SemanticToken::deserialize_tokens")]
- tokens: Vec<SemanticToken>,
- }
-
- Ok(Option::<Wrapper>::deserialize(deserializer)?.map(|wrapper| wrapper.tokens))
- }
-
- fn serialize_tokens_opt<S>(
- data: &Option<Vec<SemanticToken>>,
- serializer: S,
- ) -> Result<S::Ok, S::Error>
- where
- S: serde::Serializer,
- {
- #[derive(Serialize)]
- #[serde(transparent)]
- struct Wrapper {
- #[serde(serialize_with = "SemanticToken::serialize_tokens")]
- tokens: Vec<SemanticToken>,
- }
-
- let opt = data.as_ref().map(|t| Wrapper { tokens: t.to_vec() });
-
- opt.serialize(serializer)
- }
-}
-
-/// @since 3.16.0
-#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
-#[serde(rename_all = "camelCase")]
-pub struct SemanticTokens {
- /// An optional result id. If provided and clients support delta updating
- /// the client will include the result id in the next semantic token request.
- /// A server can then instead of computing all semantic tokens again simply
- /// send a delta.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub result_id: Option<String>,
-
- /// The actual tokens. For a detailed description about how the data is
- /// structured please see
- /// <https://github.com/microsoft/vscode-extension-samples/blob/5ae1f7787122812dcc84e37427ca90af5ee09f14/semantic-tokens-sample/vscode.proposed.d.ts#L71>
- #[serde(
- deserialize_with = "SemanticToken::deserialize_tokens",
- serialize_with = "SemanticToken::serialize_tokens"
- )]
- pub data: Vec<SemanticToken>,
-}
-
-/// @since 3.16.0
-#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
-#[serde(rename_all = "camelCase")]
-pub struct SemanticTokensPartialResult {
- #[serde(
- deserialize_with = "SemanticToken::deserialize_tokens",
- serialize_with = "SemanticToken::serialize_tokens"
- )]
- pub data: Vec<SemanticToken>,
-}
-
-#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
-#[serde(rename_all = "camelCase")]
-#[serde(untagged)]
-pub enum SemanticTokensResult {
- Tokens(SemanticTokens),
- Partial(SemanticTokensPartialResult),
-}
-
-impl From<SemanticTokens> for SemanticTokensResult {
- fn from(from: SemanticTokens) -> Self {
- SemanticTokensResult::Tokens(from)
- }
-}
-
-impl From<SemanticTokensPartialResult> for SemanticTokensResult {
- fn from(from: SemanticTokensPartialResult) -> Self {
- SemanticTokensResult::Partial(from)
- }
-}
-
-/// @since 3.16.0
-#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
-#[serde(rename_all = "camelCase")]
-pub struct SemanticTokensEdit {
- pub start: u32,
- pub delete_count: u32,
-
- #[serde(
- default,
- skip_serializing_if = "Option::is_none",
- deserialize_with = "SemanticToken::deserialize_tokens_opt",
- serialize_with = "SemanticToken::serialize_tokens_opt"
- )]
- pub data: Option<Vec<SemanticToken>>,
-}
-
-#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
-#[serde(rename_all = "camelCase")]
-#[serde(untagged)]
-pub enum SemanticTokensFullDeltaResult {
- Tokens(SemanticTokens),
- TokensDelta(SemanticTokensDelta),
- PartialTokensDelta { edits: Vec<SemanticTokensEdit> },
-}
-
-impl From<SemanticTokens> for SemanticTokensFullDeltaResult {
- fn from(from: SemanticTokens) -> Self {
- SemanticTokensFullDeltaResult::Tokens(from)
- }
-}
-
-impl From<SemanticTokensDelta> for SemanticTokensFullDeltaResult {
- fn from(from: SemanticTokensDelta) -> Self {
- SemanticTokensFullDeltaResult::TokensDelta(from)
- }
-}
-
-/// @since 3.16.0
-#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
-#[serde(rename_all = "camelCase")]
-pub struct SemanticTokensDelta {
- #[serde(skip_serializing_if = "Option::is_none")]
- pub result_id: Option<String>,
- /// For a detailed description how these edits are structured please see
- /// <https://github.com/microsoft/vscode-extension-samples/blob/5ae1f7787122812dcc84e37427ca90af5ee09f14/semantic-tokens-sample/vscode.proposed.d.ts#L131>
- pub edits: Vec<SemanticTokensEdit>,
-}
-
-/// Capabilities specific to the `textDocument/semanticTokens/*` requests.
-///
-/// @since 3.16.0
-#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
-#[serde(rename_all = "camelCase")]
-pub struct SemanticTokensClientCapabilities {
- /// Whether implementation supports dynamic registration. If this is set to `true`
- /// the client supports the new `(TextDocumentRegistrationOptions & StaticRegistrationOptions)`
- /// return value for the corresponding server capability as well.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub dynamic_registration: Option<bool>,
-
- /// Which requests the client supports and might send to the server
- /// depending on the server's capability. Please note that clients might not
- /// show semantic tokens or degrade some of the user experience if a range
- /// or full request is advertised by the client but not provided by the
- /// server. If for example the client capability `requests.full` and
- /// `request.range` are both set to true but the server only provides a
- /// range provider the client might not render a minimap correctly or might
- /// even decide to not show any semantic tokens at all.
- pub requests: SemanticTokensClientCapabilitiesRequests,
-
- /// The token types that the client supports.
- pub token_types: Vec<SemanticTokenType>,
-
- /// The token modifiers that the client supports.
- pub token_modifiers: Vec<SemanticTokenModifier>,
-
- /// The token formats the clients supports.
- pub formats: Vec<TokenFormat>,
-
- /// Whether the client supports tokens that can overlap each other.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub overlapping_token_support: Option<bool>,
-
- /// Whether the client supports tokens that can span multiple lines.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub multiline_token_support: Option<bool>,
-
- /// Whether the client allows the server to actively cancel a
- /// semantic token request, e.g. supports returning
- /// ErrorCodes.ServerCancelled. If a server does the client
- /// needs to retrigger the request.
- ///
- /// since @3.17.0
- #[cfg(feature = "proposed")]
- #[serde(skip_serializing_if = "Option::is_none")]
- pub server_cancel_support: Option<bool>,
-
-
- /// Whether the client uses semantic tokens to augment existing
- /// syntax tokens. If set to `true` client side created syntax
- /// tokens and semantic tokens are both used for colorization. If
- /// set to `false` the client only uses the returned semantic tokens
- /// for colorization.
- ///
- /// If the value is `undefined` then the client behavior is not
- /// specified.
- ///
- /// @since 3.17.0
- #[cfg(feature = "proposed")]
- #[serde(skip_serializing_if = "Option::is_none")]
- pub augments_syntax_tokens: Option<bool>,
-}
-
-#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
-#[serde(rename_all = "camelCase")]
-pub struct SemanticTokensClientCapabilitiesRequests {
- /// The client will send the `textDocument/semanticTokens/range` request if the server provides a corresponding handler.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub range: Option<bool>,
-
- /// The client will send the `textDocument/semanticTokens/full` request if the server provides a corresponding handler.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub full: Option<SemanticTokensFullOptions>,
-}
-
-#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
-#[serde(rename_all = "camelCase")]
-#[serde(untagged)]
-pub enum SemanticTokensFullOptions {
- Bool(bool),
- Delta {
- /// The client will send the `textDocument/semanticTokens/full/delta` request if the server provides a corresponding handler.
- /// The server supports deltas for full documents.
- #[serde(skip_serializing_if = "Option::is_none")]
- delta: Option<bool>,
- },
-}
-
-/// @since 3.16.0
-#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
-#[serde(rename_all = "camelCase")]
-pub struct SemanticTokensOptions {
- #[serde(flatten)]
- pub work_done_progress_options: WorkDoneProgressOptions,
-
- /// The legend used by the server
- pub legend: SemanticTokensLegend,
-
- /// Server supports providing semantic tokens for a sepcific range
- /// of a document.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub range: Option<bool>,
-
- /// Server supports providing semantic tokens for a full document.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub full: Option<SemanticTokensFullOptions>,
-}
-
-#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
-#[serde(rename_all = "camelCase")]
-pub struct SemanticTokensRegistrationOptions {
- #[serde(flatten)]
- pub text_document_registration_options: TextDocumentRegistrationOptions,
-
- #[serde(flatten)]
- pub semantic_tokens_options: SemanticTokensOptions,
-
- #[serde(flatten)]
- pub static_registration_options: StaticRegistrationOptions,
-}
-
-#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
-#[serde(rename_all = "camelCase")]
-#[serde(untagged)]
-pub enum SemanticTokensServerCapabilities {
- SemanticTokensOptions(SemanticTokensOptions),
- SemanticTokensRegistrationOptions(SemanticTokensRegistrationOptions),
-}
-
-impl From<SemanticTokensOptions> for SemanticTokensServerCapabilities {
- fn from(from: SemanticTokensOptions) -> Self {
- SemanticTokensServerCapabilities::SemanticTokensOptions(from)
- }
-}
-
-impl From<SemanticTokensRegistrationOptions> for SemanticTokensServerCapabilities {
- fn from(from: SemanticTokensRegistrationOptions) -> Self {
- SemanticTokensServerCapabilities::SemanticTokensRegistrationOptions(from)
- }
-}
-
-#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
-#[serde(rename_all = "camelCase")]
-pub struct SemanticTokensWorkspaceClientCapabilities {
- /// Whether the client implementation supports a refresh request sent from
- /// the server to the client.
- ///
- /// Note that this event is global and will force the client to refresh all
- /// semantic tokens currently shown. It should be used with absolute care
- /// and is useful for situation where a server for example detect a project
- /// wide change that requires such a calculation.
- pub refresh_support: Option<bool>,
-}
-
-#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
-#[serde(rename_all = "camelCase")]
-pub struct SemanticTokensParams {
- #[serde(flatten)]
- pub work_done_progress_params: WorkDoneProgressParams,
-
- #[serde(flatten)]
- pub partial_result_params: PartialResultParams,
-
- /// The text document.
- pub text_document: TextDocumentIdentifier,
-}
-
-#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
-#[serde(rename_all = "camelCase")]
-pub struct SemanticTokensDeltaParams {
- #[serde(flatten)]
- pub work_done_progress_params: WorkDoneProgressParams,
-
- #[serde(flatten)]
- pub partial_result_params: PartialResultParams,
-
- /// The text document.
- pub text_document: TextDocumentIdentifier,
-
- /// The result id of a previous response. The result Id can either point to a full response
- /// or a delta response depending on what was recevied last.
- pub previous_result_id: String,
-}
-
-#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
-#[serde(rename_all = "camelCase")]
-pub struct SemanticTokensRangeParams {
- #[serde(flatten)]
- pub work_done_progress_params: WorkDoneProgressParams,
-
- #[serde(flatten)]
- pub partial_result_params: PartialResultParams,
-
- /// The text document.
- pub text_document: TextDocumentIdentifier,
-
- /// The range the semantic tokens are requested for.
- pub range: Range,
-}
-
-#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
-#[serde(rename_all = "camelCase")]
-#[serde(untagged)]
-pub enum SemanticTokensRangeResult {
- Tokens(SemanticTokens),
- Partial(SemanticTokensPartialResult),
-}
-
-impl From<SemanticTokens> for SemanticTokensRangeResult {
- fn from(tokens: SemanticTokens) -> Self {
- SemanticTokensRangeResult::Tokens(tokens)
- }
-}
-
-impl From<SemanticTokensPartialResult> for SemanticTokensRangeResult {
- fn from(partial: SemanticTokensPartialResult) -> Self {
- SemanticTokensRangeResult::Partial(partial)
- }
-}
-
-#[cfg(test)]
-mod tests {
- use super::*;
- use crate::tests::{test_deserialization, test_serialization};
-
- #[test]
- fn test_semantic_tokens_support_serialization() {
- test_serialization(
- &SemanticTokens {
- result_id: None,
- data: vec![],
- },
- r#"{"data":[]}"#,
- );
-
- test_serialization(
- &SemanticTokens {
- result_id: None,
- data: vec![SemanticToken {
- delta_line: 2,
- delta_start: 5,
- length: 3,
- token_type: 0,
- token_modifiers_bitset: 3,
- }],
- },
- r#"{"data":[2,5,3,0,3]}"#,
- );
-
- test_serialization(
- &SemanticTokens {
- result_id: None,
- data: vec![
- SemanticToken {
- delta_line: 2,
- delta_start: 5,
- length: 3,
- token_type: 0,
- token_modifiers_bitset: 3,
- },
- SemanticToken {
- delta_line: 0,
- delta_start: 5,
- length: 4,
- token_type: 1,
- token_modifiers_bitset: 0,
- },
- ],
- },
- r#"{"data":[2,5,3,0,3,0,5,4,1,0]}"#,
- );
- }
-
- #[test]
- fn test_semantic_tokens_support_deserialization() {
- test_deserialization(
- r#"{"data":[]}"#,
- &SemanticTokens {
- result_id: None,
- data: vec![],
- },
- );
-
- test_deserialization(
- r#"{"data":[2,5,3,0,3]}"#,
- &SemanticTokens {
- result_id: None,
- data: vec![SemanticToken {
- delta_line: 2,
- delta_start: 5,
- length: 3,
- token_type: 0,
- token_modifiers_bitset: 3,
- }],
- },
- );
-
- test_deserialization(
- r#"{"data":[2,5,3,0,3,0,5,4,1,0]}"#,
- &SemanticTokens {
- result_id: None,
- data: vec![
- SemanticToken {
- delta_line: 2,
- delta_start: 5,
- length: 3,
- token_type: 0,
- token_modifiers_bitset: 3,
- },
- SemanticToken {
- delta_line: 0,
- delta_start: 5,
- length: 4,
- token_type: 1,
- token_modifiers_bitset: 0,
- },
- ],
- },
- );
- }
-
- #[test]
- #[should_panic]
- fn test_semantic_tokens_support_deserialization_err() {
- test_deserialization(
- r#"{"data":[1]}"#,
- &SemanticTokens {
- result_id: None,
- data: vec![],
- },
- );
- }
-
- #[test]
- fn test_semantic_tokens_edit_support_deserialization() {
- test_deserialization(
- r#"{"start":0,"deleteCount":1,"data":[2,5,3,0,3,0,5,4,1,0]}"#,
- &SemanticTokensEdit {
- start: 0,
- delete_count: 1,
- data: Some(vec![
- SemanticToken {
- delta_line: 2,
- delta_start: 5,
- length: 3,
- token_type: 0,
- token_modifiers_bitset: 3,
- },
- SemanticToken {
- delta_line: 0,
- delta_start: 5,
- length: 4,
- token_type: 1,
- token_modifiers_bitset: 0,
- },
- ]),
- },
- );
-
- test_deserialization(
- r#"{"start":0,"deleteCount":1}"#,
- &SemanticTokensEdit {
- start: 0,
- delete_count: 1,
- data: None,
- },
- );
- }
-
- #[test]
- fn test_semantic_tokens_edit_support_serialization() {
- test_serialization(
- &SemanticTokensEdit {
- start: 0,
- delete_count: 1,
- data: Some(vec![
- SemanticToken {
- delta_line: 2,
- delta_start: 5,
- length: 3,
- token_type: 0,
- token_modifiers_bitset: 3,
- },
- SemanticToken {
- delta_line: 0,
- delta_start: 5,
- length: 4,
- token_type: 1,
- token_modifiers_bitset: 0,
- },
- ]),
- },
- r#"{"start":0,"deleteCount":1,"data":[2,5,3,0,3,0,5,4,1,0]}"#,
- );
-
- test_serialization(
- &SemanticTokensEdit {
- start: 0,
- delete_count: 1,
- data: None,
- },
- r#"{"start":0,"deleteCount":1}"#,
- );
- }
-}
+use std::borrow::Cow;
+
+use serde::ser::SerializeSeq;
+use serde::{Deserialize, Serialize};
+
+use crate::{
+ PartialResultParams, Range, StaticRegistrationOptions, TextDocumentIdentifier,
+ TextDocumentRegistrationOptions, WorkDoneProgressOptions, WorkDoneProgressParams,
+};
+/// A set of predefined token types. This set is not fixed
+/// and clients can specify additional token types via the
+/// corresponding client capabilities.
+/// since @3.16.0
+#[derive(Debug, Eq, PartialEq, Hash, PartialOrd, Clone, Deserialize, Serialize)]
+pub struct SemanticTokenType(Cow<'static, str>);
+
+impl SemanticTokenType {
+ pub const NAMESPACE: SemanticTokenType = SemanticTokenType::new("namespace");
+ pub const TYPE: SemanticTokenType = SemanticTokenType::new("type");
+ pub const CLASS: SemanticTokenType = SemanticTokenType::new("class");
+ pub const ENUM: SemanticTokenType = SemanticTokenType::new("enum");
+ pub const INTERFACE: SemanticTokenType = SemanticTokenType::new("interface");
+ pub const STRUCT: SemanticTokenType = SemanticTokenType::new("struct");
+ pub const TYPE_PARAMETER: SemanticTokenType = SemanticTokenType::new("typeParameter");
+ pub const PARAMETER: SemanticTokenType = SemanticTokenType::new("parameter");
+ pub const VARIABLE: SemanticTokenType = SemanticTokenType::new("variable");
+ pub const PROPERTY: SemanticTokenType = SemanticTokenType::new("property");
+ pub const ENUM_MEMBER: SemanticTokenType = SemanticTokenType::new("enumMember");
+ pub const EVENT: SemanticTokenType = SemanticTokenType::new("event");
+ pub const FUNCTION: SemanticTokenType = SemanticTokenType::new("function");
+ pub const METHOD: SemanticTokenType = SemanticTokenType::new("method");
+ pub const MACRO: SemanticTokenType = SemanticTokenType::new("macro");
+ pub const KEYWORD: SemanticTokenType = SemanticTokenType::new("keyword");
+ pub const MODIFIER: SemanticTokenType = SemanticTokenType::new("modifier");
+ pub const COMMENT: SemanticTokenType = SemanticTokenType::new("comment");
+ pub const STRING: SemanticTokenType = SemanticTokenType::new("string");
+ pub const NUMBER: SemanticTokenType = SemanticTokenType::new("number");
+ pub const REGEXP: SemanticTokenType = SemanticTokenType::new("regexp");
+ pub const OPERATOR: SemanticTokenType = SemanticTokenType::new("operator");
+
+ /// since @3.17.0
+ pub const DECORATOR: SemanticTokenType = SemanticTokenType::new("decorator");
+
+ pub const fn new(tag: &'static str) -> Self {
+ SemanticTokenType(Cow::Borrowed(tag))
+ }
+
+ pub fn as_str(&self) -> &str {
+ &self.0
+ }
+}
+
+impl From<String> for SemanticTokenType {
+ fn from(from: String) -> Self {
+ SemanticTokenType(Cow::from(from))
+ }
+}
+
+impl From<&'static str> for SemanticTokenType {
+ fn from(from: &'static str) -> Self {
+ SemanticTokenType::new(from)
+ }
+}
+
+/// A set of predefined token modifiers. This set is not fixed
+/// and clients can specify additional token types via the
+/// corresponding client capabilities.
+///
+/// @since 3.16.0
+#[derive(Debug, Eq, PartialEq, Hash, PartialOrd, Clone, Deserialize, Serialize)]
+pub struct SemanticTokenModifier(Cow<'static, str>);
+
+impl SemanticTokenModifier {
+ pub const DECLARATION: SemanticTokenModifier = SemanticTokenModifier::new("declaration");
+ pub const DEFINITION: SemanticTokenModifier = SemanticTokenModifier::new("definition");
+ pub const READONLY: SemanticTokenModifier = SemanticTokenModifier::new("readonly");
+ pub const STATIC: SemanticTokenModifier = SemanticTokenModifier::new("static");
+ pub const DEPRECATED: SemanticTokenModifier = SemanticTokenModifier::new("deprecated");
+ pub const ABSTRACT: SemanticTokenModifier = SemanticTokenModifier::new("abstract");
+ pub const ASYNC: SemanticTokenModifier = SemanticTokenModifier::new("async");
+ pub const MODIFICATION: SemanticTokenModifier = SemanticTokenModifier::new("modification");
+ pub const DOCUMENTATION: SemanticTokenModifier = SemanticTokenModifier::new("documentation");
+ pub const DEFAULT_LIBRARY: SemanticTokenModifier = SemanticTokenModifier::new("defaultLibrary");
+
+ pub const fn new(tag: &'static str) -> Self {
+ SemanticTokenModifier(Cow::Borrowed(tag))
+ }
+
+ pub fn as_str(&self) -> &str {
+ &self.0
+ }
+}
+
+impl From<String> for SemanticTokenModifier {
+ fn from(from: String) -> Self {
+ SemanticTokenModifier(Cow::from(from))
+ }
+}
+
+impl From<&'static str> for SemanticTokenModifier {
+ fn from(from: &'static str) -> Self {
+ SemanticTokenModifier::new(from)
+ }
+}
+
+#[derive(Debug, Eq, PartialEq, Hash, PartialOrd, Clone, Deserialize, Serialize)]
+pub struct TokenFormat(Cow<'static, str>);
+
+impl TokenFormat {
+ pub const RELATIVE: TokenFormat = TokenFormat::new("relative");
+
+ pub const fn new(tag: &'static str) -> Self {
+ TokenFormat(Cow::Borrowed(tag))
+ }
+
+ pub fn as_str(&self) -> &str {
+ &self.0
+ }
+}
+
+impl From<String> for TokenFormat {
+ fn from(from: String) -> Self {
+ TokenFormat(Cow::from(from))
+ }
+}
+
+impl From<&'static str> for TokenFormat {
+ fn from(from: &'static str) -> Self {
+ TokenFormat::new(from)
+ }
+}
+
+/// @since 3.16.0
+#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct SemanticTokensLegend {
+ /// The token types a server uses.
+ pub token_types: Vec<SemanticTokenType>,
+
+ /// The token modifiers a server uses.
+ pub token_modifiers: Vec<SemanticTokenModifier>,
+}
+
+/// The actual tokens.
+#[derive(Debug, Eq, PartialEq, Copy, Clone, Default)]
+pub struct SemanticToken {
+ pub delta_line: u32,
+ pub delta_start: u32,
+ pub length: u32,
+ pub token_type: u32,
+ pub token_modifiers_bitset: u32,
+}
+
+impl SemanticToken {
+ fn deserialize_tokens<'de, D>(deserializer: D) -> Result<Vec<SemanticToken>, D::Error>
+ where
+ D: serde::Deserializer<'de>,
+ {
+ let data = Vec::<u32>::deserialize(deserializer)?;
+ let chunks = data.chunks_exact(5);
+
+ if !chunks.remainder().is_empty() {
+ return Result::Err(serde::de::Error::custom("Length is not divisible by 5"));
+ }
+
+ Result::Ok(
+ chunks
+ .map(|chunk| SemanticToken {
+ delta_line: chunk[0],
+ delta_start: chunk[1],
+ length: chunk[2],
+ token_type: chunk[3],
+ token_modifiers_bitset: chunk[4],
+ })
+ .collect(),
+ )
+ }
+
+ fn serialize_tokens<S>(tokens: &[SemanticToken], serializer: S) -> Result<S::Ok, S::Error>
+ where
+ S: serde::Serializer,
+ {
+ let mut seq = serializer.serialize_seq(Some(tokens.len() * 5))?;
+ for token in tokens.iter() {
+ seq.serialize_element(&token.delta_line)?;
+ seq.serialize_element(&token.delta_start)?;
+ seq.serialize_element(&token.length)?;
+ seq.serialize_element(&token.token_type)?;
+ seq.serialize_element(&token.token_modifiers_bitset)?;
+ }
+ seq.end()
+ }
+
+ fn deserialize_tokens_opt<'de, D>(
+ deserializer: D,
+ ) -> Result<Option<Vec<SemanticToken>>, D::Error>
+ where
+ D: serde::Deserializer<'de>,
+ {
+ #[derive(Deserialize)]
+ #[serde(transparent)]
+ struct Wrapper {
+ #[serde(deserialize_with = "SemanticToken::deserialize_tokens")]
+ tokens: Vec<SemanticToken>,
+ }
+
+ Ok(Option::<Wrapper>::deserialize(deserializer)?.map(|wrapper| wrapper.tokens))
+ }
+
+ fn serialize_tokens_opt<S>(
+ data: &Option<Vec<SemanticToken>>,
+ serializer: S,
+ ) -> Result<S::Ok, S::Error>
+ where
+ S: serde::Serializer,
+ {
+ #[derive(Serialize)]
+ #[serde(transparent)]
+ struct Wrapper {
+ #[serde(serialize_with = "SemanticToken::serialize_tokens")]
+ tokens: Vec<SemanticToken>,
+ }
+
+ let opt = data.as_ref().map(|t| Wrapper { tokens: t.to_vec() });
+
+ opt.serialize(serializer)
+ }
+}
+
+/// @since 3.16.0
+#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct SemanticTokens {
+ /// An optional result id. If provided and clients support delta updating
+ /// the client will include the result id in the next semantic token request.
+ /// A server can then instead of computing all semantic tokens again simply
+ /// send a delta.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub result_id: Option<String>,
+
+ /// The actual tokens. For a detailed description about how the data is
+ /// structured please see
+ /// <https://github.com/microsoft/vscode-extension-samples/blob/5ae1f7787122812dcc84e37427ca90af5ee09f14/semantic-tokens-sample/vscode.proposed.d.ts#L71>
+ #[serde(
+ deserialize_with = "SemanticToken::deserialize_tokens",
+ serialize_with = "SemanticToken::serialize_tokens"
+ )]
+ pub data: Vec<SemanticToken>,
+}
+
+/// @since 3.16.0
+#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct SemanticTokensPartialResult {
+ #[serde(
+ deserialize_with = "SemanticToken::deserialize_tokens",
+ serialize_with = "SemanticToken::serialize_tokens"
+ )]
+ pub data: Vec<SemanticToken>,
+}
+
+#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+#[serde(untagged)]
+pub enum SemanticTokensResult {
+ Tokens(SemanticTokens),
+ Partial(SemanticTokensPartialResult),
+}
+
+impl From<SemanticTokens> for SemanticTokensResult {
+ fn from(from: SemanticTokens) -> Self {
+ SemanticTokensResult::Tokens(from)
+ }
+}
+
+impl From<SemanticTokensPartialResult> for SemanticTokensResult {
+ fn from(from: SemanticTokensPartialResult) -> Self {
+ SemanticTokensResult::Partial(from)
+ }
+}
+
+/// @since 3.16.0
+#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct SemanticTokensEdit {
+ pub start: u32,
+ pub delete_count: u32,
+
+ #[serde(
+ default,
+ skip_serializing_if = "Option::is_none",
+ deserialize_with = "SemanticToken::deserialize_tokens_opt",
+ serialize_with = "SemanticToken::serialize_tokens_opt"
+ )]
+ pub data: Option<Vec<SemanticToken>>,
+}
+
+#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+#[serde(untagged)]
+pub enum SemanticTokensFullDeltaResult {
+ Tokens(SemanticTokens),
+ TokensDelta(SemanticTokensDelta),
+ PartialTokensDelta { edits: Vec<SemanticTokensEdit> },
+}
+
+impl From<SemanticTokens> for SemanticTokensFullDeltaResult {
+ fn from(from: SemanticTokens) -> Self {
+ SemanticTokensFullDeltaResult::Tokens(from)
+ }
+}
+
+impl From<SemanticTokensDelta> for SemanticTokensFullDeltaResult {
+ fn from(from: SemanticTokensDelta) -> Self {
+ SemanticTokensFullDeltaResult::TokensDelta(from)
+ }
+}
+
+/// @since 3.16.0
+#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct SemanticTokensDelta {
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub result_id: Option<String>,
+ /// For a detailed description how these edits are structured please see
+ /// <https://github.com/microsoft/vscode-extension-samples/blob/5ae1f7787122812dcc84e37427ca90af5ee09f14/semantic-tokens-sample/vscode.proposed.d.ts#L131>
+ pub edits: Vec<SemanticTokensEdit>,
+}
+
+/// Capabilities specific to the `textDocument/semanticTokens/*` requests.
+///
+/// @since 3.16.0
+#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct SemanticTokensClientCapabilities {
+ /// Whether implementation supports dynamic registration. If this is set to `true`
+ /// the client supports the new `(TextDocumentRegistrationOptions & StaticRegistrationOptions)`
+ /// return value for the corresponding server capability as well.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub dynamic_registration: Option<bool>,
+
+ /// Which requests the client supports and might send to the server
+ /// depending on the server's capability. Please note that clients might not
+ /// show semantic tokens or degrade some of the user experience if a range
+ /// or full request is advertised by the client but not provided by the
+ /// server. If for example the client capability `requests.full` and
+ /// `request.range` are both set to true but the server only provides a
+ /// range provider the client might not render a minimap correctly or might
+ /// even decide to not show any semantic tokens at all.
+ pub requests: SemanticTokensClientCapabilitiesRequests,
+
+ /// The token types that the client supports.
+ pub token_types: Vec<SemanticTokenType>,
+
+ /// The token modifiers that the client supports.
+ pub token_modifiers: Vec<SemanticTokenModifier>,
+
+ /// The token formats the clients supports.
+ pub formats: Vec<TokenFormat>,
+
+ /// Whether the client supports tokens that can overlap each other.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub overlapping_token_support: Option<bool>,
+
+ /// Whether the client supports tokens that can span multiple lines.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub multiline_token_support: Option<bool>,
+
+ /// Whether the client allows the server to actively cancel a
+ /// semantic token request, e.g. supports returning
+ /// ErrorCodes.ServerCancelled. If a server does the client
+ /// needs to retrigger the request.
+ ///
+ /// since @3.17.0
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub server_cancel_support: Option<bool>,
+
+ /// Whether the client uses semantic tokens to augment existing
+ /// syntax tokens. If set to `true` client side created syntax
+ /// tokens and semantic tokens are both used for colorization. If
+ /// set to `false` the client only uses the returned semantic tokens
+ /// for colorization.
+ ///
+ /// If the value is `undefined` then the client behavior is not
+ /// specified.
+ ///
+ /// @since 3.17.0
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub augments_syntax_tokens: Option<bool>,
+}
+
+#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct SemanticTokensClientCapabilitiesRequests {
+ /// The client will send the `textDocument/semanticTokens/range` request if the server provides a corresponding handler.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub range: Option<bool>,
+
+ /// The client will send the `textDocument/semanticTokens/full` request if the server provides a corresponding handler.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub full: Option<SemanticTokensFullOptions>,
+}
+
+#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+#[serde(untagged)]
+pub enum SemanticTokensFullOptions {
+ Bool(bool),
+ Delta {
+ /// The client will send the `textDocument/semanticTokens/full/delta` request if the server provides a corresponding handler.
+ /// The server supports deltas for full documents.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ delta: Option<bool>,
+ },
+}
+
+/// @since 3.16.0
+#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct SemanticTokensOptions {
+ #[serde(flatten)]
+ pub work_done_progress_options: WorkDoneProgressOptions,
+
+ /// The legend used by the server
+ pub legend: SemanticTokensLegend,
+
+ /// Server supports providing semantic tokens for a sepcific range
+ /// of a document.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub range: Option<bool>,
+
+ /// Server supports providing semantic tokens for a full document.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub full: Option<SemanticTokensFullOptions>,
+}
+
+#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct SemanticTokensRegistrationOptions {
+ #[serde(flatten)]
+ pub text_document_registration_options: TextDocumentRegistrationOptions,
+
+ #[serde(flatten)]
+ pub semantic_tokens_options: SemanticTokensOptions,
+
+ #[serde(flatten)]
+ pub static_registration_options: StaticRegistrationOptions,
+}
+
+#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+#[serde(untagged)]
+pub enum SemanticTokensServerCapabilities {
+ SemanticTokensOptions(SemanticTokensOptions),
+ SemanticTokensRegistrationOptions(SemanticTokensRegistrationOptions),
+}
+
+impl From<SemanticTokensOptions> for SemanticTokensServerCapabilities {
+ fn from(from: SemanticTokensOptions) -> Self {
+ SemanticTokensServerCapabilities::SemanticTokensOptions(from)
+ }
+}
+
+impl From<SemanticTokensRegistrationOptions> for SemanticTokensServerCapabilities {
+ fn from(from: SemanticTokensRegistrationOptions) -> Self {
+ SemanticTokensServerCapabilities::SemanticTokensRegistrationOptions(from)
+ }
+}
+
+#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct SemanticTokensWorkspaceClientCapabilities {
+ /// Whether the client implementation supports a refresh request sent from
+ /// the server to the client.
+ ///
+ /// Note that this event is global and will force the client to refresh all
+ /// semantic tokens currently shown. It should be used with absolute care
+ /// and is useful for situation where a server for example detect a project
+ /// wide change that requires such a calculation.
+ pub refresh_support: Option<bool>,
+}
+
+#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct SemanticTokensParams {
+ #[serde(flatten)]
+ pub work_done_progress_params: WorkDoneProgressParams,
+
+ #[serde(flatten)]
+ pub partial_result_params: PartialResultParams,
+
+ /// The text document.
+ pub text_document: TextDocumentIdentifier,
+}
+
+#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct SemanticTokensDeltaParams {
+ #[serde(flatten)]
+ pub work_done_progress_params: WorkDoneProgressParams,
+
+ #[serde(flatten)]
+ pub partial_result_params: PartialResultParams,
+
+ /// The text document.
+ pub text_document: TextDocumentIdentifier,
+
+ /// The result id of a previous response. The result Id can either point to a full response
+ /// or a delta response depending on what was recevied last.
+ pub previous_result_id: String,
+}
+
+#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct SemanticTokensRangeParams {
+ #[serde(flatten)]
+ pub work_done_progress_params: WorkDoneProgressParams,
+
+ #[serde(flatten)]
+ pub partial_result_params: PartialResultParams,
+
+ /// The text document.
+ pub text_document: TextDocumentIdentifier,
+
+ /// The range the semantic tokens are requested for.
+ pub range: Range,
+}
+
+#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+#[serde(untagged)]
+pub enum SemanticTokensRangeResult {
+ Tokens(SemanticTokens),
+ Partial(SemanticTokensPartialResult),
+}
+
+impl From<SemanticTokens> for SemanticTokensRangeResult {
+ fn from(tokens: SemanticTokens) -> Self {
+ SemanticTokensRangeResult::Tokens(tokens)
+ }
+}
+
+impl From<SemanticTokensPartialResult> for SemanticTokensRangeResult {
+ fn from(partial: SemanticTokensPartialResult) -> Self {
+ SemanticTokensRangeResult::Partial(partial)
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+ use crate::tests::{test_deserialization, test_serialization};
+
+ #[test]
+ fn test_semantic_tokens_support_serialization() {
+ test_serialization(
+ &SemanticTokens {
+ result_id: None,
+ data: vec![],
+ },
+ r#"{"data":[]}"#,
+ );
+
+ test_serialization(
+ &SemanticTokens {
+ result_id: None,
+ data: vec![SemanticToken {
+ delta_line: 2,
+ delta_start: 5,
+ length: 3,
+ token_type: 0,
+ token_modifiers_bitset: 3,
+ }],
+ },
+ r#"{"data":[2,5,3,0,3]}"#,
+ );
+
+ test_serialization(
+ &SemanticTokens {
+ result_id: None,
+ data: vec![
+ SemanticToken {
+ delta_line: 2,
+ delta_start: 5,
+ length: 3,
+ token_type: 0,
+ token_modifiers_bitset: 3,
+ },
+ SemanticToken {
+ delta_line: 0,
+ delta_start: 5,
+ length: 4,
+ token_type: 1,
+ token_modifiers_bitset: 0,
+ },
+ ],
+ },
+ r#"{"data":[2,5,3,0,3,0,5,4,1,0]}"#,
+ );
+ }
+
+ #[test]
+ fn test_semantic_tokens_support_deserialization() {
+ test_deserialization(
+ r#"{"data":[]}"#,
+ &SemanticTokens {
+ result_id: None,
+ data: vec![],
+ },
+ );
+
+ test_deserialization(
+ r#"{"data":[2,5,3,0,3]}"#,
+ &SemanticTokens {
+ result_id: None,
+ data: vec![SemanticToken {
+ delta_line: 2,
+ delta_start: 5,
+ length: 3,
+ token_type: 0,
+ token_modifiers_bitset: 3,
+ }],
+ },
+ );
+
+ test_deserialization(
+ r#"{"data":[2,5,3,0,3,0,5,4,1,0]}"#,
+ &SemanticTokens {
+ result_id: None,
+ data: vec![
+ SemanticToken {
+ delta_line: 2,
+ delta_start: 5,
+ length: 3,
+ token_type: 0,
+ token_modifiers_bitset: 3,
+ },
+ SemanticToken {
+ delta_line: 0,
+ delta_start: 5,
+ length: 4,
+ token_type: 1,
+ token_modifiers_bitset: 0,
+ },
+ ],
+ },
+ );
+ }
+
+ #[test]
+ #[should_panic]
+ fn test_semantic_tokens_support_deserialization_err() {
+ test_deserialization(
+ r#"{"data":[1]}"#,
+ &SemanticTokens {
+ result_id: None,
+ data: vec![],
+ },
+ );
+ }
+
+ #[test]
+ fn test_semantic_tokens_edit_support_deserialization() {
+ test_deserialization(
+ r#"{"start":0,"deleteCount":1,"data":[2,5,3,0,3,0,5,4,1,0]}"#,
+ &SemanticTokensEdit {
+ start: 0,
+ delete_count: 1,
+ data: Some(vec![
+ SemanticToken {
+ delta_line: 2,
+ delta_start: 5,
+ length: 3,
+ token_type: 0,
+ token_modifiers_bitset: 3,
+ },
+ SemanticToken {
+ delta_line: 0,
+ delta_start: 5,
+ length: 4,
+ token_type: 1,
+ token_modifiers_bitset: 0,
+ },
+ ]),
+ },
+ );
+
+ test_deserialization(
+ r#"{"start":0,"deleteCount":1}"#,
+ &SemanticTokensEdit {
+ start: 0,
+ delete_count: 1,
+ data: None,
+ },
+ );
+ }
+
+ #[test]
+ fn test_semantic_tokens_edit_support_serialization() {
+ test_serialization(
+ &SemanticTokensEdit {
+ start: 0,
+ delete_count: 1,
+ data: Some(vec![
+ SemanticToken {
+ delta_line: 2,
+ delta_start: 5,
+ length: 3,
+ token_type: 0,
+ token_modifiers_bitset: 3,
+ },
+ SemanticToken {
+ delta_line: 0,
+ delta_start: 5,
+ length: 4,
+ token_type: 1,
+ token_modifiers_bitset: 0,
+ },
+ ]),
+ },
+ r#"{"start":0,"deleteCount":1,"data":[2,5,3,0,3,0,5,4,1,0]}"#,
+ );
+
+ test_serialization(
+ &SemanticTokensEdit {
+ start: 0,
+ delete_count: 1,
+ data: None,
+ },
+ r#"{"start":0,"deleteCount":1}"#,
+ );
+ }
+}
diff --git a/vendor/lsp-types/src/signature_help.rs b/vendor/lsp-types/src/signature_help.rs
index 151f3bf7f..569417c2a 100644
--- a/vendor/lsp-types/src/signature_help.rs
+++ b/vendor/lsp-types/src/signature_help.rs
@@ -1,207 +1,207 @@
-use serde::{Deserialize, Serialize};
-
-use crate::{
- Documentation, MarkupKind, TextDocumentPositionParams, TextDocumentRegistrationOptions,
- WorkDoneProgressOptions, WorkDoneProgressParams,
-};
-
-#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
-#[serde(rename_all = "camelCase")]
-pub struct SignatureInformationSettings {
- /// Client supports the follow content formats for the documentation
- /// property. The order describes the preferred format of the client.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub documentation_format: Option<Vec<MarkupKind>>,
-
- #[serde(skip_serializing_if = "Option::is_none")]
- pub parameter_information: Option<ParameterInformationSettings>,
-
- /// The client support the `activeParameter` property on `SignatureInformation`
- /// literal.
- ///
- /// @since 3.16.0
- #[serde(skip_serializing_if = "Option::is_none")]
- pub active_parameter_support: Option<bool>,
-}
-
-#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
-#[serde(rename_all = "camelCase")]
-pub struct ParameterInformationSettings {
- /// The client supports processing label offsets instead of a
- /// simple label string.
- ///
- /// @since 3.14.0
- #[serde(skip_serializing_if = "Option::is_none")]
- pub label_offset_support: Option<bool>,
-}
-
-#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
-#[serde(rename_all = "camelCase")]
-pub struct SignatureHelpClientCapabilities {
- /// Whether completion supports dynamic registration.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub dynamic_registration: Option<bool>,
-
- /// The client supports the following `SignatureInformation`
- /// specific properties.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub signature_information: Option<SignatureInformationSettings>,
-
- /// The client supports to send additional context information for a
- /// `textDocument/signatureHelp` request. A client that opts into
- /// contextSupport will also support the `retriggerCharacters` on
- /// `SignatureHelpOptions`.
- ///
- /// @since 3.15.0
- #[serde(skip_serializing_if = "Option::is_none")]
- pub context_support: Option<bool>,
-}
-
-/// Signature help options.
-#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
-#[serde(rename_all = "camelCase")]
-pub struct SignatureHelpOptions {
- /// The characters that trigger signature help automatically.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub trigger_characters: Option<Vec<String>>,
-
- /// List of characters that re-trigger signature help.
- /// These trigger characters are only active when signature help is already showing. All trigger characters
- /// are also counted as re-trigger characters.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub retrigger_characters: Option<Vec<String>>,
-
- #[serde(flatten)]
- pub work_done_progress_options: WorkDoneProgressOptions,
-}
-
-/// Signature help options.
-#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
-pub struct SignatureHelpRegistrationOptions {
- #[serde(flatten)]
- pub text_document_registration_options: TextDocumentRegistrationOptions,
-}
-
-/// Signature help options.
-#[derive(Eq, PartialEq, Clone, Deserialize, Serialize)]
-#[serde(transparent)]
-pub struct SignatureHelpTriggerKind(i32);
-lsp_enum! {
-impl SignatureHelpTriggerKind {
- /// Signature help was invoked manually by the user or by a command.
- pub const INVOKED: SignatureHelpTriggerKind = SignatureHelpTriggerKind(1);
- /// Signature help was triggered by a trigger character.
- pub const TRIGGER_CHARACTER: SignatureHelpTriggerKind = SignatureHelpTriggerKind(2);
- /// Signature help was triggered by the cursor moving or by the document content changing.
- pub const CONTENT_CHANGE: SignatureHelpTriggerKind = SignatureHelpTriggerKind(3);
-}
-}
-
-#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
-#[serde(rename_all = "camelCase")]
-pub struct SignatureHelpParams {
- /// The signature help context. This is only available if the client specifies
- /// to send this using the client capability `textDocument.signatureHelp.contextSupport === true`
- #[serde(skip_serializing_if = "Option::is_none")]
- pub context: Option<SignatureHelpContext>,
-
- #[serde(flatten)]
- pub text_document_position_params: TextDocumentPositionParams,
-
- #[serde(flatten)]
- pub work_done_progress_params: WorkDoneProgressParams,
-}
-
-#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
-#[serde(rename_all = "camelCase")]
-pub struct SignatureHelpContext {
- /// Action that caused signature help to be triggered.
- pub trigger_kind: SignatureHelpTriggerKind,
-
- /// Character that caused signature help to be triggered.
- /// This is undefined when `triggerKind !== SignatureHelpTriggerKind.TriggerCharacter`
- #[serde(skip_serializing_if = "Option::is_none")]
- pub trigger_character: Option<String>,
-
- /// `true` if signature help was already showing when it was triggered.
- /// Retriggers occur when the signature help is already active and can be caused by actions such as
- /// typing a trigger character, a cursor move, or document content changes.
- pub is_retrigger: bool,
-
- /// The currently active `SignatureHelp`.
- /// The `activeSignatureHelp` has its `SignatureHelp.activeSignature` field updated based on
- /// the user navigating through available signatures.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub active_signature_help: Option<SignatureHelp>,
-}
-
-/// Signature help represents the signature of something
-/// callable. There can be multiple signature but only one
-/// active and only one active parameter.
-#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
-#[serde(rename_all = "camelCase")]
-pub struct SignatureHelp {
- /// One or more signatures.
- pub signatures: Vec<SignatureInformation>,
-
- /// The active signature.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub active_signature: Option<u32>,
-
- /// The active parameter of the active signature.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub active_parameter: Option<u32>,
-}
-
-/// Represents the signature of something callable. A signature
-/// can have a label, like a function-name, a doc-comment, and
-/// a set of parameters.
-#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
-#[serde(rename_all = "camelCase")]
-pub struct SignatureInformation {
- /// The label of this signature. Will be shown in
- /// the UI.
- pub label: String,
-
- /// The human-readable doc-comment of this signature. Will be shown
- /// in the UI but can be omitted.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub documentation: Option<Documentation>,
-
- /// The parameters of this signature.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub parameters: Option<Vec<ParameterInformation>>,
-
- /// The index of the active parameter.
- ///
- /// If provided, this is used in place of `SignatureHelp.activeParameter`.
- ///
- /// @since 3.16.0
- #[serde(skip_serializing_if = "Option::is_none")]
- pub active_parameter: Option<u32>,
-}
-
-/// Represents a parameter of a callable-signature. A parameter can
-/// have a label and a doc-comment.
-#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
-#[serde(rename_all = "camelCase")]
-pub struct ParameterInformation {
- /// The label of this parameter information.
- ///
- /// Either a string or an inclusive start and exclusive end offsets within its containing
- /// signature label. (see SignatureInformation.label). *Note*: A label of type string must be
- /// a substring of its containing signature label.
- pub label: ParameterLabel,
-
- /// The human-readable doc-comment of this parameter. Will be shown
- /// in the UI but can be omitted.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub documentation: Option<Documentation>,
-}
-
-#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
-#[serde(untagged)]
-pub enum ParameterLabel {
- Simple(String),
- LabelOffsets([u32; 2]),
-}
+use serde::{Deserialize, Serialize};
+
+use crate::{
+ Documentation, MarkupKind, TextDocumentPositionParams, TextDocumentRegistrationOptions,
+ WorkDoneProgressOptions, WorkDoneProgressParams,
+};
+
+#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct SignatureInformationSettings {
+ /// Client supports the follow content formats for the documentation
+ /// property. The order describes the preferred format of the client.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub documentation_format: Option<Vec<MarkupKind>>,
+
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub parameter_information: Option<ParameterInformationSettings>,
+
+ /// The client support the `activeParameter` property on `SignatureInformation`
+ /// literal.
+ ///
+ /// @since 3.16.0
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub active_parameter_support: Option<bool>,
+}
+
+#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct ParameterInformationSettings {
+ /// The client supports processing label offsets instead of a
+ /// simple label string.
+ ///
+ /// @since 3.14.0
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub label_offset_support: Option<bool>,
+}
+
+#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct SignatureHelpClientCapabilities {
+ /// Whether completion supports dynamic registration.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub dynamic_registration: Option<bool>,
+
+ /// The client supports the following `SignatureInformation`
+ /// specific properties.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub signature_information: Option<SignatureInformationSettings>,
+
+ /// The client supports to send additional context information for a
+ /// `textDocument/signatureHelp` request. A client that opts into
+ /// contextSupport will also support the `retriggerCharacters` on
+ /// `SignatureHelpOptions`.
+ ///
+ /// @since 3.15.0
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub context_support: Option<bool>,
+}
+
+/// Signature help options.
+#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct SignatureHelpOptions {
+ /// The characters that trigger signature help automatically.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub trigger_characters: Option<Vec<String>>,
+
+ /// List of characters that re-trigger signature help.
+ /// These trigger characters are only active when signature help is already showing. All trigger characters
+ /// are also counted as re-trigger characters.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub retrigger_characters: Option<Vec<String>>,
+
+ #[serde(flatten)]
+ pub work_done_progress_options: WorkDoneProgressOptions,
+}
+
+/// Signature help options.
+#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
+pub struct SignatureHelpRegistrationOptions {
+ #[serde(flatten)]
+ pub text_document_registration_options: TextDocumentRegistrationOptions,
+}
+
+/// Signature help options.
+#[derive(Eq, PartialEq, Clone, Deserialize, Serialize)]
+#[serde(transparent)]
+pub struct SignatureHelpTriggerKind(i32);
+lsp_enum! {
+impl SignatureHelpTriggerKind {
+ /// Signature help was invoked manually by the user or by a command.
+ pub const INVOKED: SignatureHelpTriggerKind = SignatureHelpTriggerKind(1);
+ /// Signature help was triggered by a trigger character.
+ pub const TRIGGER_CHARACTER: SignatureHelpTriggerKind = SignatureHelpTriggerKind(2);
+ /// Signature help was triggered by the cursor moving or by the document content changing.
+ pub const CONTENT_CHANGE: SignatureHelpTriggerKind = SignatureHelpTriggerKind(3);
+}
+}
+
+#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct SignatureHelpParams {
+ /// The signature help context. This is only available if the client specifies
+ /// to send this using the client capability `textDocument.signatureHelp.contextSupport === true`
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub context: Option<SignatureHelpContext>,
+
+ #[serde(flatten)]
+ pub text_document_position_params: TextDocumentPositionParams,
+
+ #[serde(flatten)]
+ pub work_done_progress_params: WorkDoneProgressParams,
+}
+
+#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct SignatureHelpContext {
+ /// Action that caused signature help to be triggered.
+ pub trigger_kind: SignatureHelpTriggerKind,
+
+ /// Character that caused signature help to be triggered.
+ /// This is undefined when `triggerKind !== SignatureHelpTriggerKind.TriggerCharacter`
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub trigger_character: Option<String>,
+
+ /// `true` if signature help was already showing when it was triggered.
+ /// Retriggers occur when the signature help is already active and can be caused by actions such as
+ /// typing a trigger character, a cursor move, or document content changes.
+ pub is_retrigger: bool,
+
+ /// The currently active `SignatureHelp`.
+ /// The `activeSignatureHelp` has its `SignatureHelp.activeSignature` field updated based on
+ /// the user navigating through available signatures.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub active_signature_help: Option<SignatureHelp>,
+}
+
+/// Signature help represents the signature of something
+/// callable. There can be multiple signature but only one
+/// active and only one active parameter.
+#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct SignatureHelp {
+ /// One or more signatures.
+ pub signatures: Vec<SignatureInformation>,
+
+ /// The active signature.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub active_signature: Option<u32>,
+
+ /// The active parameter of the active signature.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub active_parameter: Option<u32>,
+}
+
+/// Represents the signature of something callable. A signature
+/// can have a label, like a function-name, a doc-comment, and
+/// a set of parameters.
+#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct SignatureInformation {
+ /// The label of this signature. Will be shown in
+ /// the UI.
+ pub label: String,
+
+ /// The human-readable doc-comment of this signature. Will be shown
+ /// in the UI but can be omitted.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub documentation: Option<Documentation>,
+
+ /// The parameters of this signature.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub parameters: Option<Vec<ParameterInformation>>,
+
+ /// The index of the active parameter.
+ ///
+ /// If provided, this is used in place of `SignatureHelp.activeParameter`.
+ ///
+ /// @since 3.16.0
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub active_parameter: Option<u32>,
+}
+
+/// Represents a parameter of a callable-signature. A parameter can
+/// have a label and a doc-comment.
+#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct ParameterInformation {
+ /// The label of this parameter information.
+ ///
+ /// Either a string or an inclusive start and exclusive end offsets within its containing
+ /// signature label. (see SignatureInformation.label). *Note*: A label of type string must be
+ /// a substring of its containing signature label.
+ pub label: ParameterLabel,
+
+ /// The human-readable doc-comment of this parameter. Will be shown
+ /// in the UI but can be omitted.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub documentation: Option<Documentation>,
+}
+
+#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
+#[serde(untagged)]
+pub enum ParameterLabel {
+ Simple(String),
+ LabelOffsets([u32; 2]),
+}
diff --git a/vendor/lsp-types/src/trace.rs b/vendor/lsp-types/src/trace.rs
index 3272925bb..7cd42de07 100644
--- a/vendor/lsp-types/src/trace.rs
+++ b/vendor/lsp-types/src/trace.rs
@@ -1,82 +1,82 @@
-use serde::{Deserialize, Serialize};
-
-#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
-pub struct SetTraceParams {
- /// The new value that should be assigned to the trace setting.
- pub value: TraceValue,
-}
-
-/// A TraceValue represents the level of verbosity with which the server systematically
-/// reports its execution trace using `LogTrace` notifications.
-///
-/// The initial trace value is set by the client at initialization and can be modified
-/// later using the `SetTrace` notification.
-#[derive(Debug, Eq, PartialEq, Clone, Copy, Deserialize, Serialize)]
-#[serde(rename_all = "camelCase")]
-pub enum TraceValue {
- /// The server should not send any `$/logTrace` notification
- Off,
- /// The server should not add the 'verbose' field in the `LogTraceParams`
- Messages,
- Verbose,
-}
-
-impl Default for TraceValue {
- fn default() -> TraceValue {
- TraceValue::Off
- }
-}
-
-#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
-#[serde(rename_all = "camelCase")]
-pub struct LogTraceParams {
- /// The message to be logged.
- pub message: String,
- /// Additional information that can be computed if the `trace` configuration
- /// is set to `'verbose'`
- #[serde(skip_serializing_if = "Option::is_none")]
- pub verbose: Option<String>,
-}
-
-#[cfg(test)]
-mod tests {
- use super::*;
- use crate::tests::test_serialization;
-
- #[test]
- fn test_set_trace_params() {
- test_serialization(
- &SetTraceParams {
- value: TraceValue::Off,
- },
- r#"{"value":"off"}"#,
- );
- }
-
- #[test]
- fn test_log_trace_params() {
- test_serialization(
- &LogTraceParams {
- message: "message".into(),
- verbose: None,
- },
- r#"{"message":"message"}"#,
- );
-
- test_serialization(
- &LogTraceParams {
- message: "message".into(),
- verbose: Some("verbose".into()),
- },
- r#"{"message":"message","verbose":"verbose"}"#,
- );
- }
-
- #[test]
- fn test_trace_value() {
- test_serialization(
- &vec![TraceValue::Off, TraceValue::Messages, TraceValue::Verbose],
- r#"["off","messages","verbose"]"#,
- );
- }
-}
+use serde::{Deserialize, Serialize};
+
+#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
+pub struct SetTraceParams {
+ /// The new value that should be assigned to the trace setting.
+ pub value: TraceValue,
+}
+
+/// A TraceValue represents the level of verbosity with which the server systematically
+/// reports its execution trace using `LogTrace` notifications.
+///
+/// The initial trace value is set by the client at initialization and can be modified
+/// later using the `SetTrace` notification.
+#[derive(Debug, Eq, PartialEq, Clone, Copy, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub enum TraceValue {
+ /// The server should not send any `$/logTrace` notification
+ Off,
+ /// The server should not add the 'verbose' field in the `LogTraceParams`
+ Messages,
+ Verbose,
+}
+
+impl Default for TraceValue {
+ fn default() -> TraceValue {
+ TraceValue::Off
+ }
+}
+
+#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct LogTraceParams {
+ /// The message to be logged.
+ pub message: String,
+ /// Additional information that can be computed if the `trace` configuration
+ /// is set to `'verbose'`
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub verbose: Option<String>,
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+ use crate::tests::test_serialization;
+
+ #[test]
+ fn test_set_trace_params() {
+ test_serialization(
+ &SetTraceParams {
+ value: TraceValue::Off,
+ },
+ r#"{"value":"off"}"#,
+ );
+ }
+
+ #[test]
+ fn test_log_trace_params() {
+ test_serialization(
+ &LogTraceParams {
+ message: "message".into(),
+ verbose: None,
+ },
+ r#"{"message":"message"}"#,
+ );
+
+ test_serialization(
+ &LogTraceParams {
+ message: "message".into(),
+ verbose: Some("verbose".into()),
+ },
+ r#"{"message":"message","verbose":"verbose"}"#,
+ );
+ }
+
+ #[test]
+ fn test_trace_value() {
+ test_serialization(
+ &vec![TraceValue::Off, TraceValue::Messages, TraceValue::Verbose],
+ r#"["off","messages","verbose"]"#,
+ );
+ }
+}
diff --git a/vendor/lsp-types/src/type_hierarchy.rs b/vendor/lsp-types/src/type_hierarchy.rs
new file mode 100644
index 000000000..6cc9812ba
--- /dev/null
+++ b/vendor/lsp-types/src/type_hierarchy.rs
@@ -0,0 +1,90 @@
+use crate::{
+ DynamicRegistrationClientCapabilities, LSPAny, PartialResultParams, Range,
+ StaticRegistrationOptions, SymbolKind, SymbolTag, TextDocumentPositionParams,
+ TextDocumentRegistrationOptions, Url, WorkDoneProgressOptions, WorkDoneProgressParams,
+};
+
+use serde::{Deserialize, Serialize};
+
+pub type TypeHierarchyClientCapabilities = DynamicRegistrationClientCapabilities;
+
+#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
+pub struct TypeHierarchyOptions {
+ #[serde(flatten)]
+ pub work_done_progress_options: WorkDoneProgressOptions,
+}
+
+#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
+pub struct TypeHierarchyRegistrationOptions {
+ #[serde(flatten)]
+ pub text_document_registration_options: TextDocumentRegistrationOptions,
+ #[serde(flatten)]
+ pub type_hierarchy_options: TypeHierarchyOptions,
+ #[serde(flatten)]
+ pub static_registration_options: StaticRegistrationOptions,
+}
+
+#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
+pub struct TypeHierarchyPrepareParams {
+ #[serde(flatten)]
+ pub text_document_position_params: TextDocumentPositionParams,
+ #[serde(flatten)]
+ pub work_done_progress_params: WorkDoneProgressParams,
+}
+
+#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
+pub struct TypeHierarchySupertypesParams {
+ pub item: TypeHierarchyItem,
+
+ #[serde(flatten)]
+ pub work_done_progress_params: WorkDoneProgressParams,
+ #[serde(flatten)]
+ pub partial_result_params: PartialResultParams,
+}
+
+#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
+pub struct TypeHierarchySubtypesParams {
+ pub item: TypeHierarchyItem,
+
+ #[serde(flatten)]
+ pub work_done_progress_params: WorkDoneProgressParams,
+ #[serde(flatten)]
+ pub partial_result_params: PartialResultParams,
+}
+
+#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct TypeHierarchyItem {
+ /// The name of this item.
+ pub name: String,
+
+ /// The kind of this item.
+ pub kind: SymbolKind,
+
+ /// Tags for this item.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub tags: Option<SymbolTag>,
+
+ /// More detail for this item, e.g. the signature of a function.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub detail: Option<String>,
+
+ /// The resource identifier of this item.
+ pub uri: Url,
+
+ /// The range enclosing this symbol not including leading/trailing whitespace
+ /// but everything else, e.g. comments and code.
+ pub range: Range,
+
+ /// The range that should be selected and revealed when this symbol is being
+ /// picked, e.g. the name of a function. Must be contained by the
+ /// [`range`](#TypeHierarchyItem.range).
+ pub selection_range: Range,
+
+ /// A data entry field that is preserved between a type hierarchy prepare and
+ /// supertypes or subtypes requests. It could also be used to identify the
+ /// type hierarchy in the server, helping improve the performance on
+ /// resolving supertypes and subtypes.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub data: Option<LSPAny>,
+}
diff --git a/vendor/lsp-types/src/window.rs b/vendor/lsp-types/src/window.rs
index 89d28aaaf..d4dbdf169 100644
--- a/vendor/lsp-types/src/window.rs
+++ b/vendor/lsp-types/src/window.rs
@@ -1,176 +1,176 @@
-use std::collections::HashMap;
-
-use serde::{Deserialize, Serialize};
-
-use serde_json::Value;
-
-use url::Url;
-
-use crate::Range;
-
-#[derive(Eq, PartialEq, Clone, Copy, Deserialize, Serialize)]
-#[serde(transparent)]
-pub struct MessageType(i32);
-lsp_enum! {
-impl MessageType {
- /// An error message.
- pub const ERROR: MessageType = MessageType(1);
- /// A warning message.
- pub const WARNING: MessageType = MessageType(2);
- /// An information message;
- pub const INFO: MessageType = MessageType(3);
- /// A log message.
- pub const LOG: MessageType = MessageType(4);
-}
-}
-
-/// Window specific client capabilities.
-#[derive(Debug, PartialEq, Clone, Default, Deserialize, Serialize)]
-#[serde(rename_all = "camelCase")]
-pub struct WindowClientCapabilities {
- /// Whether client supports handling progress notifications. If set
- /// servers are allowed to report in `workDoneProgress` property in the
- /// request specific server capabilities.
- ///
- /// @since 3.15.0
- #[serde(skip_serializing_if = "Option::is_none")]
- pub work_done_progress: Option<bool>,
-
- /// Capabilities specific to the showMessage request.
- ///
- /// @since 3.16.0
- ///
- #[serde(skip_serializing_if = "Option::is_none")]
- pub show_message: Option<ShowMessageRequestClientCapabilities>,
-
- /// Client capabilities for the show document request.
- ///
- /// @since 3.16.0
- ///
- #[serde(skip_serializing_if = "Option::is_none")]
- pub show_document: Option<ShowDocumentClientCapabilities>,
-}
-
-/// Show message request client capabilities
-#[derive(Debug, PartialEq, Clone, Default, Deserialize, Serialize)]
-#[serde(rename_all = "camelCase")]
-pub struct ShowMessageRequestClientCapabilities {
- /// Capabilities specific to the `MessageActionItem` type.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub message_action_item: Option<MessageActionItemCapabilities>,
-}
-
-#[derive(Debug, PartialEq, Clone, Default, Deserialize, Serialize)]
-#[serde(rename_all = "camelCase")]
-pub struct MessageActionItemCapabilities {
- /// Whether the client supports additional attribues which
- /// are preserved and send back to the server in the
- /// request's response.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub additional_properties_support: Option<bool>,
-}
-
-#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
-#[serde(rename_all = "camelCase")]
-pub struct MessageActionItem {
- /// A short title like 'Retry', 'Open Log' etc.
- pub title: String,
-
- /// Additional attributes that the client preserves and
- /// sends back to the server. This depends on the client
- /// capability window.messageActionItem.additionalPropertiesSupport
- #[serde(flatten)]
- pub properties: HashMap<String, MessageActionItemProperty>,
-}
-
-#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
-#[serde(untagged)]
-pub enum MessageActionItemProperty {
- String(String),
- Boolean(bool),
- Integer(i32),
- Object(Value),
-}
-
-#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
-pub struct LogMessageParams {
- /// The message type. See {@link MessageType}
- #[serde(rename = "type")]
- pub typ: MessageType,
-
- /// The actual message
- pub message: String,
-}
-
-#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
-pub struct ShowMessageParams {
- /// The message type. See {@link MessageType}.
- #[serde(rename = "type")]
- pub typ: MessageType,
-
- /// The actual message.
- pub message: String,
-}
-
-#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
-pub struct ShowMessageRequestParams {
- /// The message type. See {@link MessageType}
- #[serde(rename = "type")]
- pub typ: MessageType,
-
- /// The actual message
- pub message: String,
-
- /// The message action items to present.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub actions: Option<Vec<MessageActionItem>>,
-}
-
-/// Client capabilities for the show document request.
-#[derive(Debug, PartialEq, Clone, Default, Deserialize, Serialize)]
-#[serde(rename_all = "camelCase")]
-pub struct ShowDocumentClientCapabilities {
- /// The client has support for the show document request.
- pub support: bool,
-}
-
-/// Params to show a document.
-///
-/// @since 3.16.0
-///
-#[derive(Debug, PartialEq, Clone, Deserialize, Serialize)]
-#[serde(rename_all = "camelCase")]
-pub struct ShowDocumentParams {
- /// The document uri to show.
- pub uri: Url,
-
- /// Indicates to show the resource in an external program.
- /// To show for example `https://code.visualstudio.com/`
- /// in the default WEB browser set `external` to `true`.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub external: Option<bool>,
-
- /// An optional property to indicate whether the editor
- /// showing the document should take focus or not.
- /// Clients might ignore this property if an external
- /// program in started.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub take_focus: Option<bool>,
-
- /// An optional selection range if the document is a text
- /// document. Clients might ignore the property if an
- /// external program is started or the file is not a text
- /// file.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub selection: Option<Range>,
-}
-
-/// The result of an show document request.
-///
-/// @since 3.16.0
-#[derive(Debug, PartialEq, Clone, Deserialize, Serialize)]
-#[serde(rename_all = "camelCase")]
-pub struct ShowDocumentResult {
- /// A boolean indicating if the show was successful.
- pub success: bool,
-}
+use std::collections::HashMap;
+
+use serde::{Deserialize, Serialize};
+
+use serde_json::Value;
+
+use url::Url;
+
+use crate::Range;
+
+#[derive(Eq, PartialEq, Clone, Copy, Deserialize, Serialize)]
+#[serde(transparent)]
+pub struct MessageType(i32);
+lsp_enum! {
+impl MessageType {
+ /// An error message.
+ pub const ERROR: MessageType = MessageType(1);
+ /// A warning message.
+ pub const WARNING: MessageType = MessageType(2);
+ /// An information message;
+ pub const INFO: MessageType = MessageType(3);
+ /// A log message.
+ pub const LOG: MessageType = MessageType(4);
+}
+}
+
+/// Window specific client capabilities.
+#[derive(Debug, PartialEq, Clone, Default, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct WindowClientCapabilities {
+ /// Whether client supports handling progress notifications. If set
+ /// servers are allowed to report in `workDoneProgress` property in the
+ /// request specific server capabilities.
+ ///
+ /// @since 3.15.0
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub work_done_progress: Option<bool>,
+
+ /// Capabilities specific to the showMessage request.
+ ///
+ /// @since 3.16.0
+ ///
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub show_message: Option<ShowMessageRequestClientCapabilities>,
+
+ /// Client capabilities for the show document request.
+ ///
+ /// @since 3.16.0
+ ///
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub show_document: Option<ShowDocumentClientCapabilities>,
+}
+
+/// Show message request client capabilities
+#[derive(Debug, PartialEq, Clone, Default, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct ShowMessageRequestClientCapabilities {
+ /// Capabilities specific to the `MessageActionItem` type.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub message_action_item: Option<MessageActionItemCapabilities>,
+}
+
+#[derive(Debug, PartialEq, Clone, Default, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct MessageActionItemCapabilities {
+ /// Whether the client supports additional attribues which
+ /// are preserved and send back to the server in the
+ /// request's response.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub additional_properties_support: Option<bool>,
+}
+
+#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct MessageActionItem {
+ /// A short title like 'Retry', 'Open Log' etc.
+ pub title: String,
+
+ /// Additional attributes that the client preserves and
+ /// sends back to the server. This depends on the client
+ /// capability window.messageActionItem.additionalPropertiesSupport
+ #[serde(flatten)]
+ pub properties: HashMap<String, MessageActionItemProperty>,
+}
+
+#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
+#[serde(untagged)]
+pub enum MessageActionItemProperty {
+ String(String),
+ Boolean(bool),
+ Integer(i32),
+ Object(Value),
+}
+
+#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
+pub struct LogMessageParams {
+ /// The message type. See {@link MessageType}
+ #[serde(rename = "type")]
+ pub typ: MessageType,
+
+ /// The actual message
+ pub message: String,
+}
+
+#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
+pub struct ShowMessageParams {
+ /// The message type. See {@link MessageType}.
+ #[serde(rename = "type")]
+ pub typ: MessageType,
+
+ /// The actual message.
+ pub message: String,
+}
+
+#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
+pub struct ShowMessageRequestParams {
+ /// The message type. See {@link MessageType}
+ #[serde(rename = "type")]
+ pub typ: MessageType,
+
+ /// The actual message
+ pub message: String,
+
+ /// The message action items to present.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub actions: Option<Vec<MessageActionItem>>,
+}
+
+/// Client capabilities for the show document request.
+#[derive(Debug, PartialEq, Clone, Default, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct ShowDocumentClientCapabilities {
+ /// The client has support for the show document request.
+ pub support: bool,
+}
+
+/// Params to show a document.
+///
+/// @since 3.16.0
+///
+#[derive(Debug, PartialEq, Clone, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct ShowDocumentParams {
+ /// The document uri to show.
+ pub uri: Url,
+
+ /// Indicates to show the resource in an external program.
+ /// To show for example `https://code.visualstudio.com/`
+ /// in the default WEB browser set `external` to `true`.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub external: Option<bool>,
+
+ /// An optional property to indicate whether the editor
+ /// showing the document should take focus or not.
+ /// Clients might ignore this property if an external
+ /// program in started.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub take_focus: Option<bool>,
+
+ /// An optional selection range if the document is a text
+ /// document. Clients might ignore the property if an
+ /// external program is started or the file is not a text
+ /// file.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub selection: Option<Range>,
+}
+
+/// The result of an show document request.
+///
+/// @since 3.16.0
+#[derive(Debug, PartialEq, Clone, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct ShowDocumentResult {
+ /// A boolean indicating if the show was successful.
+ pub success: bool,
+}
diff --git a/vendor/lsp-types/src/workspace_folders.rs b/vendor/lsp-types/src/workspace_folders.rs
index ae30d3a0b..677e6f696 100644
--- a/vendor/lsp-types/src/workspace_folders.rs
+++ b/vendor/lsp-types/src/workspace_folders.rs
@@ -1,49 +1,49 @@
-use serde::{Deserialize, Serialize};
-use url::Url;
-
-use crate::OneOf;
-
-#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
-#[serde(rename_all = "camelCase")]
-pub struct WorkspaceFoldersServerCapabilities {
- /// The server has support for workspace folders
- #[serde(skip_serializing_if = "Option::is_none")]
- pub supported: Option<bool>,
-
- /// Whether the server wants to receive workspace folder
- /// change notifications.
- ///
- /// If a string is provided, the string is treated as an ID
- /// under which the notification is registered on the client
- /// side. The ID can be used to unregister for these events
- /// using the `client/unregisterCapability` request.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub change_notifications: Option<OneOf<bool, String>>,
-}
-
-#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
-#[serde(rename_all = "camelCase")]
-pub struct WorkspaceFolder {
- /// The associated URI for this workspace folder.
- pub uri: Url,
- /// The name of the workspace folder. Defaults to the uri's basename.
- pub name: String,
-}
-
-#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
-#[serde(rename_all = "camelCase")]
-pub struct DidChangeWorkspaceFoldersParams {
- /// The actual workspace folder change event.
- pub event: WorkspaceFoldersChangeEvent,
-}
-
-/// The workspace folder change event.
-#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
-#[serde(rename_all = "camelCase")]
-pub struct WorkspaceFoldersChangeEvent {
- /// The array of added workspace folders
- pub added: Vec<WorkspaceFolder>,
-
- /// The array of the removed workspace folders
- pub removed: Vec<WorkspaceFolder>,
-}
+use serde::{Deserialize, Serialize};
+use url::Url;
+
+use crate::OneOf;
+
+#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct WorkspaceFoldersServerCapabilities {
+ /// The server has support for workspace folders
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub supported: Option<bool>,
+
+ /// Whether the server wants to receive workspace folder
+ /// change notifications.
+ ///
+ /// If a string is provided, the string is treated as an ID
+ /// under which the notification is registered on the client
+ /// side. The ID can be used to unregister for these events
+ /// using the `client/unregisterCapability` request.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub change_notifications: Option<OneOf<bool, String>>,
+}
+
+#[derive(Debug, Eq, PartialEq, Ord, PartialOrd, Clone, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct WorkspaceFolder {
+ /// The associated URI for this workspace folder.
+ pub uri: Url,
+ /// The name of the workspace folder. Defaults to the uri's basename.
+ pub name: String,
+}
+
+#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct DidChangeWorkspaceFoldersParams {
+ /// The actual workspace folder change event.
+ pub event: WorkspaceFoldersChangeEvent,
+}
+
+/// The workspace folder change event.
+#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct WorkspaceFoldersChangeEvent {
+ /// The array of added workspace folders
+ pub added: Vec<WorkspaceFolder>,
+
+ /// The array of the removed workspace folders
+ pub removed: Vec<WorkspaceFolder>,
+}
diff --git a/vendor/lsp-types/src/workspace_symbols.rs b/vendor/lsp-types/src/workspace_symbols.rs
index 6b4143a54..8540bb46f 100644
--- a/vendor/lsp-types/src/workspace_symbols.rs
+++ b/vendor/lsp-types/src/workspace_symbols.rs
@@ -1,42 +1,106 @@
-use crate::{PartialResultParams, SymbolKindCapability, WorkDoneProgressParams};
-
-use crate::{SymbolTag, TagSupport};
-
-use serde::{Deserialize, Serialize};
-
-#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
-#[serde(rename_all = "camelCase")]
-pub struct WorkspaceSymbolClientCapabilities {
- /// This capability supports dynamic registration.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub dynamic_registration: Option<bool>,
-
- /// Specific capabilities for the `SymbolKind` in the `workspace/symbol` request.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub symbol_kind: Option<SymbolKindCapability>,
-
- /// The client supports tags on `SymbolInformation`.
- /// Clients supporting tags have to handle unknown tags gracefully.
- ///
- /// @since 3.16.0
- ///
- #[serde(
- default,
- skip_serializing_if = "Option::is_none",
- deserialize_with = "TagSupport::deserialize_compat"
- )]
- pub tag_support: Option<TagSupport<SymbolTag>>,
-}
-
-/// The parameters of a Workspace Symbol Request.
-#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
-pub struct WorkspaceSymbolParams {
- #[serde(flatten)]
- pub partial_result_params: PartialResultParams,
-
- #[serde(flatten)]
- pub work_done_progress_params: WorkDoneProgressParams,
-
- /// A non-empty query string
- pub query: String,
-}
+use crate::{
+ LSPAny, Location, OneOf, PartialResultParams, SymbolInformation, SymbolKind,
+ SymbolKindCapability, SymbolTag, TagSupport, Url, WorkDoneProgressParams,
+};
+
+use serde::{Deserialize, Serialize};
+
+#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct WorkspaceSymbolClientCapabilities {
+ /// This capability supports dynamic registration.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub dynamic_registration: Option<bool>,
+
+ /// Specific capabilities for the `SymbolKind` in the `workspace/symbol` request.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub symbol_kind: Option<SymbolKindCapability>,
+
+ /// The client supports tags on `SymbolInformation`.
+ /// Clients supporting tags have to handle unknown tags gracefully.
+ ///
+ /// @since 3.16.0
+ ///
+ #[serde(
+ default,
+ skip_serializing_if = "Option::is_none",
+ deserialize_with = "TagSupport::deserialize_compat"
+ )]
+ pub tag_support: Option<TagSupport<SymbolTag>>,
+
+ /// The client support partial workspace symbols. The client will send the
+ /// request `workspaceSymbol/resolve` to the server to resolve additional
+ /// properties.
+ ///
+ /// @since 3.17.0
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub resolve_support: Option<WorkspaceSymbolResolveSupportCapability>,
+}
+
+/// The parameters of a Workspace Symbol Request.
+#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
+pub struct WorkspaceSymbolParams {
+ #[serde(flatten)]
+ pub partial_result_params: PartialResultParams,
+
+ #[serde(flatten)]
+ pub work_done_progress_params: WorkDoneProgressParams,
+
+ /// A non-empty query string
+ pub query: String,
+}
+
+#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
+pub struct WorkspaceSymbolResolveSupportCapability {
+ /// The properties that a client can resolve lazily. Usually
+ /// `location.range`
+ pub properties: Vec<String>,
+}
+
+/// A special workspace symbol that supports locations without a range
+///
+/// @since 3.17.0
+#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct WorkspaceSymbol {
+ /// The name of this symbol.
+ pub name: String,
+
+ /// The kind of this symbol.
+ pub kind: SymbolKind,
+
+ /// Tags for this completion item.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub tags: Option<Vec<SymbolTag>>,
+
+ /// The name of the symbol containing this symbol. This information is for
+ /// user interface purposes (e.g. to render a qualifier in the user interface
+ /// if necessary). It can't be used to re-infer a hierarchy for the document
+ /// symbols.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub container_name: Option<String>,
+
+ /// The location of this symbol. Whether a server is allowed to
+ /// return a location without a range depends on the client
+ /// capability `workspace.symbol.resolveSupport`.
+ ///
+ /// See also `SymbolInformation.location`.
+ pub location: OneOf<Location, WorkspaceLocation>,
+
+ /// A data entry field that is preserved on a workspace symbol between a
+ /// workspace symbol request and a workspace symbol resolve request.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub data: Option<LSPAny>,
+}
+
+#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
+pub struct WorkspaceLocation {
+ pub uri: Url,
+}
+
+#[derive(Debug, Eq, PartialEq, Clone, Serialize, Deserialize)]
+#[serde(untagged)]
+pub enum WorkspaceSymbolResponse {
+ Flat(Vec<SymbolInformation>),
+ Nested(Vec<WorkspaceSymbol>),
+}
diff --git a/vendor/lsp-types/tests/lsif.rs b/vendor/lsp-types/tests/lsif.rs
index dd4a7230a..9f5c97798 100644
--- a/vendor/lsp-types/tests/lsif.rs
+++ b/vendor/lsp-types/tests/lsif.rs
@@ -1,16 +1,16 @@
-use lsp_types::lsif::Entry;
-
-#[test]
-#[cfg(unix)]
-fn run() {
- let jsonl = include_str!("tsc-unix.lsif");
- for json in jsonl.lines() {
- let r = serde_json::from_str::<Entry>(&json).expect(&format!("can not parse {}", json));
- let x = serde_json::to_string(&r).expect(&format!("can not serialize {}", json));
- assert_eq!(
- serde_json::from_str::<serde_json::Value>(&x).unwrap(),
- serde_json::from_str::<serde_json::Value>(json).unwrap(),
- "and strings:\ntheir: {}\n our: {}", json, x,
- );
- }
-}
+use lsp_types::lsif::Entry;
+
+#[test]
+#[cfg(unix)]
+fn run() {
+ let jsonl = include_str!("tsc-unix.lsif");
+ for json in jsonl.lines() {
+ let r = serde_json::from_str::<Entry>(&json).expect(&format!("can not parse {}", json));
+ let x = serde_json::to_string(&r).expect(&format!("can not serialize {}", json));
+ assert_eq!(
+ serde_json::from_str::<serde_json::Value>(&x).unwrap(),
+ serde_json::from_str::<serde_json::Value>(json).unwrap(),
+ "and strings:\ntheir: {}\n our: {}", json, x,
+ );
+ }
+}
diff --git a/vendor/lsp-types/tests/tsc-unix.lsif b/vendor/lsp-types/tests/tsc-unix.lsif
index 24c4dc046..27f6d5135 100644
--- a/vendor/lsp-types/tests/tsc-unix.lsif
+++ b/vendor/lsp-types/tests/tsc-unix.lsif
@@ -1,135 +1,135 @@
-{"id":1,"type":"vertex","label":"metaData","version":"0.4.3","projectRoot":"file:///media/hamid/nv1/garbage","positionEncoding":"utf-16","toolInfo":{"name":"lsif-tsc","args":["-p","."],"version":"0.7.2"}}
-{"id":2,"type":"vertex","label":"project","kind":"typescript"}
-{"id":3,"type":"vertex","label":"$event","kind":"begin","scope":"project","data":2}
-{"id":4,"type":"vertex","label":"document","uri":"file:///media/hamid/nv1/garbage/a.ts","languageId":"typescript"}
-{"id":5,"type":"vertex","label":"$event","kind":"begin","scope":"document","data":4}
-{"id":6,"type":"vertex","label":"resultSet"}
-{"id":7,"type":"vertex","label":"moniker","kind":"export","unique":"document","scheme":"tsc","identifier":"a:"}
-{"id":8,"type":"edge","label":"moniker","outV":6,"inV":7}
-{"id":9,"type":"vertex","label":"packageInformation","name":"garbage","manager":"npm","version":"1.0.0"}
-{"id":10,"type":"vertex","label":"moniker","kind":"export","unique":"global","scheme":"npm","identifier":"garbage:a:"}
-{"id":11,"type":"edge","label":"packageInformation","outV":10,"inV":9}
-{"id":12,"type":"edge","label":"nextMoniker","outV":7,"inV":10}
-{"id":13,"type":"vertex","label":"range","start":{"line":0,"character":0},"end":{"line":0,"character":0},"tag":{"type":"definition","text":"","kind":7,"fullRange":{"start":{"line":0,"character":0},"end":{"line":3,"character":0}}}}
-{"id":14,"type":"edge","label":"next","outV":13,"inV":6}
-{"id":15,"type":"vertex","label":"resultSet"}
-{"id":16,"type":"vertex","label":"moniker","kind":"export","unique":"document","scheme":"tsc","identifier":"a:a"}
-{"id":17,"type":"edge","label":"moniker","outV":15,"inV":16}
-{"id":18,"type":"vertex","label":"moniker","kind":"export","unique":"global","scheme":"npm","identifier":"garbage:a:a"}
-{"id":19,"type":"edge","label":"packageInformation","outV":18,"inV":9}
-{"id":20,"type":"edge","label":"nextMoniker","outV":16,"inV":18}
-{"id":21,"type":"vertex","label":"range","start":{"line":0,"character":13},"end":{"line":0,"character":14},"tag":{"type":"definition","text":"a","kind":7,"fullRange":{"start":{"line":0,"character":13},"end":{"line":2,"character":1}}}}
-{"id":22,"type":"edge","label":"next","outV":21,"inV":15}
-{"id":23,"type":"vertex","label":"hoverResult","result":{"contents":[{"language":"typescript","value":"const a: (x: number, y: string) => string"}]}}
-{"id":24,"type":"edge","label":"textDocument/hover","outV":15,"inV":23}
-{"id":25,"type":"vertex","label":"resultSet"}
-{"id":26,"type":"vertex","label":"moniker","kind":"local","unique":"document","scheme":"tsc","identifier":"dW50H+qRDGdPj+RYWpwLSg=="}
-{"id":27,"type":"edge","label":"moniker","outV":25,"inV":26}
-{"id":28,"type":"vertex","label":"range","start":{"line":0,"character":18},"end":{"line":0,"character":19},"tag":{"type":"definition","text":"x","kind":7,"fullRange":{"start":{"line":0,"character":18},"end":{"line":0,"character":27}}}}
-{"id":29,"type":"edge","label":"next","outV":28,"inV":25}
-{"id":30,"type":"vertex","label":"hoverResult","result":{"contents":[{"language":"typescript","value":"(parameter) x: number"}]}}
-{"id":31,"type":"edge","label":"textDocument/hover","outV":25,"inV":30}
-{"id":32,"type":"vertex","label":"resultSet"}
-{"id":33,"type":"vertex","label":"moniker","kind":"local","unique":"document","scheme":"tsc","identifier":"W2CLXh2PW8+ib7xga5YF4A=="}
-{"id":34,"type":"edge","label":"moniker","outV":32,"inV":33}
-{"id":35,"type":"vertex","label":"range","start":{"line":0,"character":29},"end":{"line":0,"character":30},"tag":{"type":"definition","text":"y","kind":7,"fullRange":{"start":{"line":0,"character":29},"end":{"line":0,"character":38}}}}
-{"id":36,"type":"edge","label":"next","outV":35,"inV":32}
-{"id":37,"type":"vertex","label":"hoverResult","result":{"contents":[{"language":"typescript","value":"(parameter) y: string"}]}}
-{"id":38,"type":"edge","label":"textDocument/hover","outV":32,"inV":37}
-{"id":39,"type":"vertex","label":"resultSet"}
-{"id":40,"type":"vertex","label":"moniker","kind":"local","unique":"document","scheme":"tsc","identifier":"WLUBvuhxsSADYrjTwQnBoA=="}
-{"id":41,"type":"edge","label":"moniker","outV":39,"inV":40}
-{"id":42,"type":"vertex","label":"range","start":{"line":0,"character":40},"end":{"line":0,"character":42},"tag":{"type":"reference","text":"=>"}}
-{"id":43,"type":"edge","label":"next","outV":42,"inV":39}
-{"id":44,"type":"vertex","label":"range","start":{"line":1,"character":18},"end":{"line":1,"character":19},"tag":{"type":"reference","text":"y"}}
-{"id":45,"type":"edge","label":"next","outV":44,"inV":32}
-{"id":46,"type":"vertex","label":"document","uri":"file:///media/hamid/nv1/garbage/node_modules/typescript-lsif/lib/lib.es2015.core.d.ts","languageId":"typescript"}
-{"id":47,"type":"vertex","label":"$event","kind":"begin","scope":"document","data":46}
-{"id":48,"type":"vertex","label":"resultSet"}
-{"id":49,"type":"vertex","label":"moniker","kind":"export","unique":"document","scheme":"tsc","identifier":"node_modules/typescript-lsif/lib/lib.es2015.core:String.repeat"}
-{"id":50,"type":"edge","label":"moniker","outV":48,"inV":49}
-{"id":51,"type":"vertex","label":"moniker","kind":"export","unique":"global","scheme":"npm","identifier":"garbage:node_modules/typescript-lsif/lib/lib.es2015.core:String.repeat"}
-{"id":52,"type":"edge","label":"packageInformation","outV":51,"inV":9}
-{"id":53,"type":"edge","label":"nextMoniker","outV":49,"inV":51}
-{"id":54,"type":"vertex","label":"range","start":{"line":446,"character":4},"end":{"line":446,"character":10},"tag":{"type":"definition","text":"repeat","kind":7,"fullRange":{"start":{"line":446,"character":4},"end":{"line":446,"character":34}}}}
-{"id":55,"type":"edge","label":"next","outV":54,"inV":48}
-{"id":56,"type":"vertex","label":"hoverResult","result":{"contents":[{"language":"typescript","value":"(method) String.repeat(count: number): string"},"Returns a String value that is made from count copies appended together. If count is 0,\nthe empty string is returned."]}}
-{"id":57,"type":"edge","label":"textDocument/hover","outV":48,"inV":56}
-{"id":58,"type":"vertex","label":"range","start":{"line":1,"character":20},"end":{"line":1,"character":26},"tag":{"type":"reference","text":"repeat"}}
-{"id":59,"type":"edge","label":"next","outV":58,"inV":48}
-{"id":60,"type":"vertex","label":"range","start":{"line":1,"character":27},"end":{"line":1,"character":28},"tag":{"type":"reference","text":"x"}}
-{"id":61,"type":"edge","label":"next","outV":60,"inV":25}
-{"id":62,"type":"vertex","label":"definitionResult"}
-{"id":63,"type":"edge","label":"textDocument/definition","outV":6,"inV":62}
-{"id":64,"type":"edge","label":"item","outV":62,"inVs":[13],"document":4}
-{"id":65,"type":"vertex","label":"referenceResult"}
-{"id":66,"type":"edge","label":"textDocument/references","outV":6,"inV":65}
-{"id":67,"type":"edge","label":"item","outV":65,"inVs":[13],"document":4,"property":"definitions"}
-{"id":68,"type":"vertex","label":"definitionResult"}
-{"id":69,"type":"edge","label":"textDocument/definition","outV":15,"inV":68}
-{"id":70,"type":"edge","label":"item","outV":68,"inVs":[21],"document":4}
-{"id":71,"type":"vertex","label":"referenceResult"}
-{"id":72,"type":"edge","label":"textDocument/references","outV":15,"inV":71}
-{"id":73,"type":"edge","label":"item","outV":71,"inVs":[21],"document":4,"property":"definitions"}
-{"id":74,"type":"vertex","label":"definitionResult"}
-{"id":75,"type":"edge","label":"textDocument/definition","outV":25,"inV":74}
-{"id":76,"type":"edge","label":"item","outV":74,"inVs":[28],"document":4}
-{"id":77,"type":"vertex","label":"referenceResult"}
-{"id":78,"type":"edge","label":"textDocument/references","outV":25,"inV":77}
-{"id":79,"type":"edge","label":"item","outV":77,"inVs":[28],"document":4,"property":"definitions"}
-{"id":80,"type":"edge","label":"item","outV":77,"inVs":[60],"document":4,"property":"references"}
-{"id":81,"type":"vertex","label":"definitionResult"}
-{"id":82,"type":"edge","label":"textDocument/definition","outV":32,"inV":81}
-{"id":83,"type":"edge","label":"item","outV":81,"inVs":[35],"document":4}
-{"id":84,"type":"vertex","label":"referenceResult"}
-{"id":85,"type":"edge","label":"textDocument/references","outV":32,"inV":84}
-{"id":86,"type":"edge","label":"item","outV":84,"inVs":[35],"document":4,"property":"definitions"}
-{"id":87,"type":"edge","label":"item","outV":84,"inVs":[44],"document":4,"property":"references"}
-{"id":88,"type":"vertex","label":"referenceResult"}
-{"id":89,"type":"edge","label":"textDocument/references","outV":39,"inV":88}
-{"id":90,"type":"edge","label":"item","outV":88,"inVs":[42],"document":4,"property":"references"}
-{"id":91,"type":"vertex","label":"referenceResult"}
-{"id":92,"type":"edge","label":"textDocument/references","outV":48,"inV":91}
-{"id":93,"type":"edge","label":"item","outV":91,"inVs":[58],"document":4,"property":"references"}
-{"id":94,"type":"vertex","label":"document","uri":"file:///media/hamid/nv1/garbage/b.ts","languageId":"typescript"}
-{"id":95,"type":"vertex","label":"$event","kind":"begin","scope":"document","data":94}
-{"id":96,"type":"vertex","label":"resultSet"}
-{"id":97,"type":"vertex","label":"moniker","kind":"export","unique":"document","scheme":"tsc","identifier":"b:"}
-{"id":98,"type":"edge","label":"moniker","outV":96,"inV":97}
-{"id":99,"type":"vertex","label":"moniker","kind":"export","unique":"global","scheme":"npm","identifier":"garbage:b:"}
-{"id":100,"type":"edge","label":"packageInformation","outV":99,"inV":9}
-{"id":101,"type":"edge","label":"nextMoniker","outV":97,"inV":99}
-{"id":102,"type":"vertex","label":"range","start":{"line":0,"character":0},"end":{"line":0,"character":0},"tag":{"type":"definition","text":"","kind":7,"fullRange":{"start":{"line":0,"character":0},"end":{"line":3,"character":0}}}}
-{"id":103,"type":"edge","label":"next","outV":102,"inV":96}
-{"id":104,"type":"vertex","label":"resultSet"}
-{"id":105,"type":"edge","label":"next","outV":104,"inV":15}
-{"id":106,"type":"vertex","label":"moniker","kind":"local","unique":"document","scheme":"tsc","identifier":"sNwThRvTZlfLwz6po1s2Zg=="}
-{"id":107,"type":"edge","label":"moniker","outV":104,"inV":106}
-{"id":108,"type":"vertex","label":"range","start":{"line":0,"character":9},"end":{"line":0,"character":10},"tag":{"type":"definition","text":"a","kind":7,"fullRange":{"start":{"line":0,"character":9},"end":{"line":0,"character":10}}}}
-{"id":109,"type":"edge","label":"next","outV":108,"inV":104}
-{"id":110,"type":"vertex","label":"hoverResult","result":{"contents":[{"language":"typescript","value":"(alias) const a: (x: number, y: string) => string\nimport a"}]}}
-{"id":111,"type":"edge","label":"textDocument/hover","outV":104,"inV":110}
-{"id":112,"type":"vertex","label":"range","start":{"line":0,"character":18},"end":{"line":0,"character":23},"tag":{"type":"reference","text":"\"./a\""}}
-{"id":113,"type":"edge","label":"next","outV":112,"inV":6}
-{"id":114,"type":"vertex","label":"range","start":{"line":2,"character":0},"end":{"line":2,"character":1},"tag":{"type":"reference","text":"a"}}
-{"id":115,"type":"edge","label":"next","outV":114,"inV":104}
-{"id":116,"type":"vertex","label":"definitionResult"}
-{"id":117,"type":"edge","label":"textDocument/definition","outV":96,"inV":116}
-{"id":118,"type":"edge","label":"item","outV":116,"inVs":[102],"document":94}
-{"id":119,"type":"vertex","label":"referenceResult"}
-{"id":120,"type":"edge","label":"textDocument/references","outV":96,"inV":119}
-{"id":121,"type":"edge","label":"item","outV":119,"inVs":[102],"document":94,"property":"definitions"}
-{"id":122,"type":"edge","label":"item","outV":71,"inVs":[108,114],"document":94,"property":"references"}
-{"id":123,"type":"edge","label":"item","outV":65,"inVs":[112],"document":94,"property":"references"}
-{"id":124,"type":"vertex","label":"definitionResult"}
-{"id":125,"type":"edge","label":"textDocument/definition","outV":48,"inV":124}
-{"id":126,"type":"edge","label":"item","outV":124,"inVs":[54],"document":46}
-{"id":127,"type":"edge","label":"item","outV":91,"inVs":[54],"document":46,"property":"definitions"}
-{"id":128,"type":"edge","label":"contains","outV":4,"inVs":[13,21,28,35,42,44,58,60]}
-{"id":129,"type":"vertex","label":"$event","kind":"end","scope":"document","data":4}
-{"id":130,"type":"edge","label":"contains","outV":46,"inVs":[54]}
-{"id":131,"type":"vertex","label":"$event","kind":"end","scope":"document","data":46}
-{"id":132,"type":"edge","label":"contains","outV":94,"inVs":[102,108,112,114]}
-{"id":133,"type":"vertex","label":"$event","kind":"end","scope":"document","data":94}
-{"id":134,"type":"edge","label":"contains","outV":2,"inVs":[4,46,94]}
-{"id":135,"type":"vertex","label":"$event","kind":"end","scope":"project","data":2}
+{"id":1,"type":"vertex","label":"metaData","version":"0.4.3","projectRoot":"file:///media/hamid/nv1/garbage","positionEncoding":"utf-16","toolInfo":{"name":"lsif-tsc","args":["-p","."],"version":"0.7.2"}}
+{"id":2,"type":"vertex","label":"project","kind":"typescript"}
+{"id":3,"type":"vertex","label":"$event","kind":"begin","scope":"project","data":2}
+{"id":4,"type":"vertex","label":"document","uri":"file:///media/hamid/nv1/garbage/a.ts","languageId":"typescript"}
+{"id":5,"type":"vertex","label":"$event","kind":"begin","scope":"document","data":4}
+{"id":6,"type":"vertex","label":"resultSet"}
+{"id":7,"type":"vertex","label":"moniker","kind":"export","unique":"document","scheme":"tsc","identifier":"a:"}
+{"id":8,"type":"edge","label":"moniker","outV":6,"inV":7}
+{"id":9,"type":"vertex","label":"packageInformation","name":"garbage","manager":"npm","version":"1.0.0"}
+{"id":10,"type":"vertex","label":"moniker","kind":"export","unique":"global","scheme":"npm","identifier":"garbage:a:"}
+{"id":11,"type":"edge","label":"packageInformation","outV":10,"inV":9}
+{"id":12,"type":"edge","label":"nextMoniker","outV":7,"inV":10}
+{"id":13,"type":"vertex","label":"range","start":{"line":0,"character":0},"end":{"line":0,"character":0},"tag":{"type":"definition","text":"","kind":7,"fullRange":{"start":{"line":0,"character":0},"end":{"line":3,"character":0}}}}
+{"id":14,"type":"edge","label":"next","outV":13,"inV":6}
+{"id":15,"type":"vertex","label":"resultSet"}
+{"id":16,"type":"vertex","label":"moniker","kind":"export","unique":"document","scheme":"tsc","identifier":"a:a"}
+{"id":17,"type":"edge","label":"moniker","outV":15,"inV":16}
+{"id":18,"type":"vertex","label":"moniker","kind":"export","unique":"global","scheme":"npm","identifier":"garbage:a:a"}
+{"id":19,"type":"edge","label":"packageInformation","outV":18,"inV":9}
+{"id":20,"type":"edge","label":"nextMoniker","outV":16,"inV":18}
+{"id":21,"type":"vertex","label":"range","start":{"line":0,"character":13},"end":{"line":0,"character":14},"tag":{"type":"definition","text":"a","kind":7,"fullRange":{"start":{"line":0,"character":13},"end":{"line":2,"character":1}}}}
+{"id":22,"type":"edge","label":"next","outV":21,"inV":15}
+{"id":23,"type":"vertex","label":"hoverResult","result":{"contents":[{"language":"typescript","value":"const a: (x: number, y: string) => string"}]}}
+{"id":24,"type":"edge","label":"textDocument/hover","outV":15,"inV":23}
+{"id":25,"type":"vertex","label":"resultSet"}
+{"id":26,"type":"vertex","label":"moniker","kind":"local","unique":"document","scheme":"tsc","identifier":"dW50H+qRDGdPj+RYWpwLSg=="}
+{"id":27,"type":"edge","label":"moniker","outV":25,"inV":26}
+{"id":28,"type":"vertex","label":"range","start":{"line":0,"character":18},"end":{"line":0,"character":19},"tag":{"type":"definition","text":"x","kind":7,"fullRange":{"start":{"line":0,"character":18},"end":{"line":0,"character":27}}}}
+{"id":29,"type":"edge","label":"next","outV":28,"inV":25}
+{"id":30,"type":"vertex","label":"hoverResult","result":{"contents":[{"language":"typescript","value":"(parameter) x: number"}]}}
+{"id":31,"type":"edge","label":"textDocument/hover","outV":25,"inV":30}
+{"id":32,"type":"vertex","label":"resultSet"}
+{"id":33,"type":"vertex","label":"moniker","kind":"local","unique":"document","scheme":"tsc","identifier":"W2CLXh2PW8+ib7xga5YF4A=="}
+{"id":34,"type":"edge","label":"moniker","outV":32,"inV":33}
+{"id":35,"type":"vertex","label":"range","start":{"line":0,"character":29},"end":{"line":0,"character":30},"tag":{"type":"definition","text":"y","kind":7,"fullRange":{"start":{"line":0,"character":29},"end":{"line":0,"character":38}}}}
+{"id":36,"type":"edge","label":"next","outV":35,"inV":32}
+{"id":37,"type":"vertex","label":"hoverResult","result":{"contents":[{"language":"typescript","value":"(parameter) y: string"}]}}
+{"id":38,"type":"edge","label":"textDocument/hover","outV":32,"inV":37}
+{"id":39,"type":"vertex","label":"resultSet"}
+{"id":40,"type":"vertex","label":"moniker","kind":"local","unique":"document","scheme":"tsc","identifier":"WLUBvuhxsSADYrjTwQnBoA=="}
+{"id":41,"type":"edge","label":"moniker","outV":39,"inV":40}
+{"id":42,"type":"vertex","label":"range","start":{"line":0,"character":40},"end":{"line":0,"character":42},"tag":{"type":"reference","text":"=>"}}
+{"id":43,"type":"edge","label":"next","outV":42,"inV":39}
+{"id":44,"type":"vertex","label":"range","start":{"line":1,"character":18},"end":{"line":1,"character":19},"tag":{"type":"reference","text":"y"}}
+{"id":45,"type":"edge","label":"next","outV":44,"inV":32}
+{"id":46,"type":"vertex","label":"document","uri":"file:///media/hamid/nv1/garbage/node_modules/typescript-lsif/lib/lib.es2015.core.d.ts","languageId":"typescript"}
+{"id":47,"type":"vertex","label":"$event","kind":"begin","scope":"document","data":46}
+{"id":48,"type":"vertex","label":"resultSet"}
+{"id":49,"type":"vertex","label":"moniker","kind":"export","unique":"document","scheme":"tsc","identifier":"node_modules/typescript-lsif/lib/lib.es2015.core:String.repeat"}
+{"id":50,"type":"edge","label":"moniker","outV":48,"inV":49}
+{"id":51,"type":"vertex","label":"moniker","kind":"export","unique":"global","scheme":"npm","identifier":"garbage:node_modules/typescript-lsif/lib/lib.es2015.core:String.repeat"}
+{"id":52,"type":"edge","label":"packageInformation","outV":51,"inV":9}
+{"id":53,"type":"edge","label":"nextMoniker","outV":49,"inV":51}
+{"id":54,"type":"vertex","label":"range","start":{"line":446,"character":4},"end":{"line":446,"character":10},"tag":{"type":"definition","text":"repeat","kind":7,"fullRange":{"start":{"line":446,"character":4},"end":{"line":446,"character":34}}}}
+{"id":55,"type":"edge","label":"next","outV":54,"inV":48}
+{"id":56,"type":"vertex","label":"hoverResult","result":{"contents":[{"language":"typescript","value":"(method) String.repeat(count: number): string"},"Returns a String value that is made from count copies appended together. If count is 0,\nthe empty string is returned."]}}
+{"id":57,"type":"edge","label":"textDocument/hover","outV":48,"inV":56}
+{"id":58,"type":"vertex","label":"range","start":{"line":1,"character":20},"end":{"line":1,"character":26},"tag":{"type":"reference","text":"repeat"}}
+{"id":59,"type":"edge","label":"next","outV":58,"inV":48}
+{"id":60,"type":"vertex","label":"range","start":{"line":1,"character":27},"end":{"line":1,"character":28},"tag":{"type":"reference","text":"x"}}
+{"id":61,"type":"edge","label":"next","outV":60,"inV":25}
+{"id":62,"type":"vertex","label":"definitionResult"}
+{"id":63,"type":"edge","label":"textDocument/definition","outV":6,"inV":62}
+{"id":64,"type":"edge","label":"item","outV":62,"inVs":[13],"document":4}
+{"id":65,"type":"vertex","label":"referenceResult"}
+{"id":66,"type":"edge","label":"textDocument/references","outV":6,"inV":65}
+{"id":67,"type":"edge","label":"item","outV":65,"inVs":[13],"document":4,"property":"definitions"}
+{"id":68,"type":"vertex","label":"definitionResult"}
+{"id":69,"type":"edge","label":"textDocument/definition","outV":15,"inV":68}
+{"id":70,"type":"edge","label":"item","outV":68,"inVs":[21],"document":4}
+{"id":71,"type":"vertex","label":"referenceResult"}
+{"id":72,"type":"edge","label":"textDocument/references","outV":15,"inV":71}
+{"id":73,"type":"edge","label":"item","outV":71,"inVs":[21],"document":4,"property":"definitions"}
+{"id":74,"type":"vertex","label":"definitionResult"}
+{"id":75,"type":"edge","label":"textDocument/definition","outV":25,"inV":74}
+{"id":76,"type":"edge","label":"item","outV":74,"inVs":[28],"document":4}
+{"id":77,"type":"vertex","label":"referenceResult"}
+{"id":78,"type":"edge","label":"textDocument/references","outV":25,"inV":77}
+{"id":79,"type":"edge","label":"item","outV":77,"inVs":[28],"document":4,"property":"definitions"}
+{"id":80,"type":"edge","label":"item","outV":77,"inVs":[60],"document":4,"property":"references"}
+{"id":81,"type":"vertex","label":"definitionResult"}
+{"id":82,"type":"edge","label":"textDocument/definition","outV":32,"inV":81}
+{"id":83,"type":"edge","label":"item","outV":81,"inVs":[35],"document":4}
+{"id":84,"type":"vertex","label":"referenceResult"}
+{"id":85,"type":"edge","label":"textDocument/references","outV":32,"inV":84}
+{"id":86,"type":"edge","label":"item","outV":84,"inVs":[35],"document":4,"property":"definitions"}
+{"id":87,"type":"edge","label":"item","outV":84,"inVs":[44],"document":4,"property":"references"}
+{"id":88,"type":"vertex","label":"referenceResult"}
+{"id":89,"type":"edge","label":"textDocument/references","outV":39,"inV":88}
+{"id":90,"type":"edge","label":"item","outV":88,"inVs":[42],"document":4,"property":"references"}
+{"id":91,"type":"vertex","label":"referenceResult"}
+{"id":92,"type":"edge","label":"textDocument/references","outV":48,"inV":91}
+{"id":93,"type":"edge","label":"item","outV":91,"inVs":[58],"document":4,"property":"references"}
+{"id":94,"type":"vertex","label":"document","uri":"file:///media/hamid/nv1/garbage/b.ts","languageId":"typescript"}
+{"id":95,"type":"vertex","label":"$event","kind":"begin","scope":"document","data":94}
+{"id":96,"type":"vertex","label":"resultSet"}
+{"id":97,"type":"vertex","label":"moniker","kind":"export","unique":"document","scheme":"tsc","identifier":"b:"}
+{"id":98,"type":"edge","label":"moniker","outV":96,"inV":97}
+{"id":99,"type":"vertex","label":"moniker","kind":"export","unique":"global","scheme":"npm","identifier":"garbage:b:"}
+{"id":100,"type":"edge","label":"packageInformation","outV":99,"inV":9}
+{"id":101,"type":"edge","label":"nextMoniker","outV":97,"inV":99}
+{"id":102,"type":"vertex","label":"range","start":{"line":0,"character":0},"end":{"line":0,"character":0},"tag":{"type":"definition","text":"","kind":7,"fullRange":{"start":{"line":0,"character":0},"end":{"line":3,"character":0}}}}
+{"id":103,"type":"edge","label":"next","outV":102,"inV":96}
+{"id":104,"type":"vertex","label":"resultSet"}
+{"id":105,"type":"edge","label":"next","outV":104,"inV":15}
+{"id":106,"type":"vertex","label":"moniker","kind":"local","unique":"document","scheme":"tsc","identifier":"sNwThRvTZlfLwz6po1s2Zg=="}
+{"id":107,"type":"edge","label":"moniker","outV":104,"inV":106}
+{"id":108,"type":"vertex","label":"range","start":{"line":0,"character":9},"end":{"line":0,"character":10},"tag":{"type":"definition","text":"a","kind":7,"fullRange":{"start":{"line":0,"character":9},"end":{"line":0,"character":10}}}}
+{"id":109,"type":"edge","label":"next","outV":108,"inV":104}
+{"id":110,"type":"vertex","label":"hoverResult","result":{"contents":[{"language":"typescript","value":"(alias) const a: (x: number, y: string) => string\nimport a"}]}}
+{"id":111,"type":"edge","label":"textDocument/hover","outV":104,"inV":110}
+{"id":112,"type":"vertex","label":"range","start":{"line":0,"character":18},"end":{"line":0,"character":23},"tag":{"type":"reference","text":"\"./a\""}}
+{"id":113,"type":"edge","label":"next","outV":112,"inV":6}
+{"id":114,"type":"vertex","label":"range","start":{"line":2,"character":0},"end":{"line":2,"character":1},"tag":{"type":"reference","text":"a"}}
+{"id":115,"type":"edge","label":"next","outV":114,"inV":104}
+{"id":116,"type":"vertex","label":"definitionResult"}
+{"id":117,"type":"edge","label":"textDocument/definition","outV":96,"inV":116}
+{"id":118,"type":"edge","label":"item","outV":116,"inVs":[102],"document":94}
+{"id":119,"type":"vertex","label":"referenceResult"}
+{"id":120,"type":"edge","label":"textDocument/references","outV":96,"inV":119}
+{"id":121,"type":"edge","label":"item","outV":119,"inVs":[102],"document":94,"property":"definitions"}
+{"id":122,"type":"edge","label":"item","outV":71,"inVs":[108,114],"document":94,"property":"references"}
+{"id":123,"type":"edge","label":"item","outV":65,"inVs":[112],"document":94,"property":"references"}
+{"id":124,"type":"vertex","label":"definitionResult"}
+{"id":125,"type":"edge","label":"textDocument/definition","outV":48,"inV":124}
+{"id":126,"type":"edge","label":"item","outV":124,"inVs":[54],"document":46}
+{"id":127,"type":"edge","label":"item","outV":91,"inVs":[54],"document":46,"property":"definitions"}
+{"id":128,"type":"edge","label":"contains","outV":4,"inVs":[13,21,28,35,42,44,58,60]}
+{"id":129,"type":"vertex","label":"$event","kind":"end","scope":"document","data":4}
+{"id":130,"type":"edge","label":"contains","outV":46,"inVs":[54]}
+{"id":131,"type":"vertex","label":"$event","kind":"end","scope":"document","data":46}
+{"id":132,"type":"edge","label":"contains","outV":94,"inVs":[102,108,112,114]}
+{"id":133,"type":"vertex","label":"$event","kind":"end","scope":"document","data":94}
+{"id":134,"type":"edge","label":"contains","outV":2,"inVs":[4,46,94]}
+{"id":135,"type":"vertex","label":"$event","kind":"end","scope":"project","data":2}
diff --git a/vendor/memmap2/.cargo-checksum.json b/vendor/memmap2/.cargo-checksum.json
index c189c8a9c..656d284c6 100644
--- a/vendor/memmap2/.cargo-checksum.json
+++ b/vendor/memmap2/.cargo-checksum.json
@@ -1 +1 @@
-{"files":{"CHANGELOG.md":"fb280b4d71ea601557e7ab637a7f82f73eb519dd9d16d38684bf6fe4e800a020","Cargo.lock":"80c9c7be560eee59e3eded68a49b53278198fc23495807c6a22e9c5190914ebe","Cargo.toml":"4738a7e9e1f236b95d41ef8837c351f895fcb1cc1cb82ab7e3bf39c72849cba4","LICENSE-APACHE":"04ea4849dba9dcae07113850c6f1b1a69052c625210639914eee352023f750ad","LICENSE-MIT":"0d25d03b5ab49576178ad0cae7a2648d12c17ad0452fe49c07e55e4b59aa5257","README.md":"c7b3cd928f0d1a10faa255e2f84a2a06636e55ea3e7edd4f6334dd9215151205","examples/cat.rs":"ab0b575d19662e2d5b6c7cea2756b57530e495d56acdb4fd2b56c0ba4d768dfd","src/advice.rs":"194bfd6a32495f6b0c739d083b06230ae656927767f15c1b49b245b63431cc4d","src/lib.rs":"ea214bce1c2409b8ee7a390c85f5114bc681a551d02aba23280030fe58588eb9","src/stub.rs":"f276bb5e4bc29c2129ebc660b01a1de173b9575e2e866ea5a34e0ee6318f1177","src/unix.rs":"03fe91a320d0146993019ea51e486275b8c8e13e42a995e649b8c76690e3f167","src/windows.rs":"bbb39200ac35b5517626c12efad4886f7b5d34e56256284914c556dec1567e38"},"package":"95af15f345b17af2efc8ead6080fb8bc376f8cec1b35277b935637595fe77498"} \ No newline at end of file
+{"files":{"CHANGELOG.md":"2c44b332748c22db37c7bc17f8c90edd5616c084a9b7238eef5067f3dd287813","Cargo.lock":"ed33b2c7bd22c158bd527fefa4079e62a3e98a63c2b653ba50d977a8a43f92c2","Cargo.toml":"cad69c38d627420a71d549945b9bbc4b21323b2855d63e3b98d344d2fe3ea07e","LICENSE-APACHE":"04ea4849dba9dcae07113850c6f1b1a69052c625210639914eee352023f750ad","LICENSE-MIT":"0d25d03b5ab49576178ad0cae7a2648d12c17ad0452fe49c07e55e4b59aa5257","README.md":"c7b3cd928f0d1a10faa255e2f84a2a06636e55ea3e7edd4f6334dd9215151205","examples/cat.rs":"ab0b575d19662e2d5b6c7cea2756b57530e495d56acdb4fd2b56c0ba4d768dfd","src/advice.rs":"194bfd6a32495f6b0c739d083b06230ae656927767f15c1b49b245b63431cc4d","src/lib.rs":"4f345df103c78344e07454da7b8f3941af094efd599e3d51a29ea735fab19dba","src/stub.rs":"f276bb5e4bc29c2129ebc660b01a1de173b9575e2e866ea5a34e0ee6318f1177","src/unix.rs":"03fe91a320d0146993019ea51e486275b8c8e13e42a995e649b8c76690e3f167","src/windows.rs":"bbb39200ac35b5517626c12efad4886f7b5d34e56256284914c556dec1567e38"},"package":"4b182332558b18d807c4ce1ca8ca983b34c3ee32765e47b3f0f69b90355cc1dc"} \ No newline at end of file
diff --git a/vendor/memmap2/CHANGELOG.md b/vendor/memmap2/CHANGELOG.md
index 14f481c4e..07b4eb270 100644
--- a/vendor/memmap2/CHANGELOG.md
+++ b/vendor/memmap2/CHANGELOG.md
@@ -6,6 +6,12 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
## [Unreleased]
+## [0.5.8] - 2022-11-09
+### Added
+- `MmapRaw::advise`, `MmapRaw::lock` and `MmapRaw::unlock`.
+ [@diwic](https://github.com/diwic)
+- Improve `MmapMut::make_exec` documentation.
+
## [0.5.7] - 2022-08-15
### Changed
- Simplify file size retrieving code.
@@ -117,7 +123,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
### Removed
- `winapi` dependency. [memmap-rs/pull/89](https://github.com/danburkert/memmap-rs/pull/89)
-[Unreleased]: https://github.com/RazrFalcon/memmap2-rs/compare/v0.5.7...HEAD
+[Unreleased]: https://github.com/RazrFalcon/memmap2-rs/compare/v0.5.8...HEAD
+[0.5.8]: https://github.com/RazrFalcon/memmap2-rs/compare/v0.5.7...v0.5.8
[0.5.7]: https://github.com/RazrFalcon/memmap2-rs/compare/v0.5.6...v0.5.7
[0.5.6]: https://github.com/RazrFalcon/memmap2-rs/compare/v0.5.5...v0.5.6
[0.5.5]: https://github.com/RazrFalcon/memmap2-rs/compare/v0.5.4...v0.5.5
diff --git a/vendor/memmap2/Cargo.lock b/vendor/memmap2/Cargo.lock
index 5a4a2b5f2..f5fe93bb2 100644
--- a/vendor/memmap2/Cargo.lock
+++ b/vendor/memmap2/Cargo.lock
@@ -40,7 +40,7 @@ checksum = "a7f823d141fe0a24df1e23b4af4e3c7ba9e5966ec514ea068c93024aa7deb765"
[[package]]
name = "memmap2"
-version = "0.5.7"
+version = "0.5.8"
dependencies = [
"libc",
"owning_ref",
diff --git a/vendor/memmap2/Cargo.toml b/vendor/memmap2/Cargo.toml
index 29d796270..9c3575f9b 100644
--- a/vendor/memmap2/Cargo.toml
+++ b/vendor/memmap2/Cargo.toml
@@ -12,7 +12,7 @@
[package]
edition = "2018"
name = "memmap2"
-version = "0.5.7"
+version = "0.5.8"
authors = [
"Dan Burkert <dan@danburkert.com>",
"Yevhenii Reizner <razrfalcon@gmail.com>",
@@ -26,7 +26,7 @@ keywords = [
"io",
"file",
]
-license = "MIT/Apache-2.0"
+license = "MIT OR Apache-2.0"
repository = "https://github.com/RazrFalcon/memmap2-rs"
[dependencies.stable_deref_trait]
diff --git a/vendor/memmap2/src/lib.rs b/vendor/memmap2/src/lib.rs
index 0b92ea0e1..58df7589b 100644
--- a/vendor/memmap2/src/lib.rs
+++ b/vendor/memmap2/src/lib.rs
@@ -800,6 +800,30 @@ impl MmapRaw {
pub fn flush_async_range(&self, offset: usize, len: usize) -> Result<()> {
self.inner.flush_async(offset, len)
}
+
+ /// Advise OS how this memory map will be accessed. Only supported on Unix.
+ ///
+ /// See [madvise()](https://man7.org/linux/man-pages/man2/madvise.2.html) map page.
+ #[cfg(unix)]
+ pub fn advise(&self, advice: Advice) -> Result<()> {
+ self.inner.advise(advice)
+ }
+
+ /// Lock the whole memory map into RAM. Only supported on Unix.
+ ///
+ /// See [mlock()](https://man7.org/linux/man-pages/man2/mlock.2.html) map page.
+ #[cfg(unix)]
+ pub fn lock(&mut self) -> Result<()> {
+ self.inner.lock()
+ }
+
+ /// Unlock the whole memory map. Only supported on Unix.
+ ///
+ /// See [munlock()](https://man7.org/linux/man-pages/man2/munlock.2.html) map page.
+ #[cfg(unix)]
+ pub fn unlock(&mut self) -> Result<()> {
+ self.inner.unlock()
+ }
}
impl fmt::Debug for MmapRaw {
@@ -1006,6 +1030,12 @@ impl MmapMut {
///
/// If the memory map is file-backed, the file must have been opened with execute permissions.
///
+ /// On systems with separate instructions and data caches (a category that includes many ARM
+ /// chips), a platform-specific call may be needed to ensure that the changes are visible to the
+ /// execution unit (e.g. when using this function to implement a JIT compiler). For more
+ /// details, see [this ARM write-up](https://community.arm.com/arm-community-blogs/b/architectures-and-processors-blog/posts/caches-and-self-modifying-code)
+ /// or the `man` page for [`sys_icache_invalidate`](https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man3/sys_icache_invalidate.3.html).
+ ///
/// # Errors
///
/// This method returns an error when the underlying system call fails, which can happen for a
@@ -1088,7 +1118,7 @@ mod test {
#[cfg(unix)]
use crate::advice::Advice;
- use std::fs::{self, OpenOptions};
+ use std::fs::OpenOptions;
use std::io::{Read, Write};
#[cfg(unix)]
use std::os::unix::io::AsRawFd;
@@ -1622,7 +1652,7 @@ mod test {
/// Returns true if a non-zero amount of memory is locked.
#[cfg(target_os = "linux")]
fn is_locked() -> bool {
- let status = &fs::read_to_string("/proc/self/status")
+ let status = &std::fs::read_to_string("/proc/self/status")
.expect("/proc/self/status should be available");
for line in status.lines() {
if line.starts_with("VmLck:") {
diff --git a/vendor/miniz_oxide-0.5.3/.cargo-checksum.json b/vendor/miniz_oxide-0.5.3/.cargo-checksum.json
new file mode 100644
index 000000000..a30f6d5ad
--- /dev/null
+++ b/vendor/miniz_oxide-0.5.3/.cargo-checksum.json
@@ -0,0 +1 @@
+{"files":{"Cargo.toml":"bdec209313b683bf315ff5134fde0322e46a27ae8ec9de303ffa22cc67826365","LICENSE":"e190940e8ad3cdd4fca962a6508ed6865d589d314b1cb055f86000e124b88d8d","LICENSE-APACHE.md":"0d542e0c8804e39aa7f37eb00da5a762149dc682d7829451287e11b938e94594","LICENSE-MIT.md":"e190940e8ad3cdd4fca962a6508ed6865d589d314b1cb055f86000e124b88d8d","LICENSE-ZLIB.md":"c89bcc058da12a0fb24402b8ea4542a21515dd1da2e8c67bba4ed9bd269f1c96","Readme.md":"b6a6668b073a3356748b642ce51b31233b6408ffcca3e52801ef473a9f7925c7","src/deflate/buffer.rs":"76bcca4e79bef412eeebdd06d2d0a4348ed9ee17edbdaa6d451d8bf03b1cde85","src/deflate/core.rs":"8087c155cb47f57a9747565857dcef59fff0a7a499abbfdb0c60e694d3234db8","src/deflate/mod.rs":"8ade5b9683b8d728fe5e8f5c23e0630165bfdbef3e56a18b1b729f9bbd4a4b1d","src/deflate/stream.rs":"016c82b09a989492c8c8ea89027d339fcf59a5ca2155e7026ac094ca74344712","src/inflate/core.rs":"49bd596d5255ac88b486f6f978ab7b26663cdab01a6ebaa41bf4559f12b0fed8","src/inflate/mod.rs":"8b65692f1bb71b4973df8da7ca9ffc8c4e4e439f6b5993e16a96d20dc3a08f52","src/inflate/output_buffer.rs":"1ae90d03ba8c9d667fe248b6066731774afdf93cc79cd3bf90e0711b963b0b72","src/inflate/stream.rs":"f82c44ffdff054aff05307ed5709e432b54d5997bb4bbfff8f760171c33c76c3","src/lib.rs":"a9d6a889415ffe3d800c8516fb0ac0bae3585010966d1fdf3b06a85330c36854","src/shared.rs":"a8c47fcb566591e39fcd50d44f3b4d0f567318b8ca36c8d732ee0d8c99a14906"},"package":"6f5c75688da582b8ffc1f1799e9db273f32133c49e048f614d22ec3256773ccc"} \ No newline at end of file
diff --git a/vendor/miniz_oxide-0.5.3/Cargo.toml b/vendor/miniz_oxide-0.5.3/Cargo.toml
new file mode 100644
index 000000000..7546128ce
--- /dev/null
+++ b/vendor/miniz_oxide-0.5.3/Cargo.toml
@@ -0,0 +1,55 @@
+# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
+#
+# When uploading crates to the registry Cargo will automatically
+# "normalize" Cargo.toml files for maximal compatibility
+# with all versions of Cargo and also rewrite `path` dependencies
+# to registry (e.g., crates.io) dependencies.
+#
+# If you are reading this file be aware that the original Cargo.toml
+# will likely look very different (and much more reasonable).
+# See Cargo.toml.orig for the original contents.
+
+[package]
+edition = "2018"
+name = "miniz_oxide"
+version = "0.5.3"
+authors = ["Frommi <daniil.liferenko@gmail.com>", "oyvindln <oyvindln@users.noreply.github.com>"]
+exclude = ["benches/*", "tests/*"]
+description = "DEFLATE compression and decompression library rewritten in Rust based on miniz"
+homepage = "https://github.com/Frommi/miniz_oxide/tree/master/miniz_oxide"
+documentation = "https://docs.rs/miniz_oxide"
+readme = "Readme.md"
+keywords = ["zlib", "miniz", "deflate", "encoding"]
+categories = ["compression"]
+license = "MIT OR Zlib OR Apache-2.0"
+repository = "https://github.com/Frommi/miniz_oxide/tree/master/miniz_oxide"
+
+[lib]
+name = "miniz_oxide"
+[dependencies.adler]
+version = "1.0"
+default-features = false
+
+[dependencies.alloc]
+version = "1.0.0"
+optional = true
+package = "rustc-std-workspace-alloc"
+
+[dependencies.compiler_builtins]
+version = "0.1.2"
+optional = true
+
+[dependencies.core]
+version = "1.0.0"
+optional = true
+package = "rustc-std-workspace-core"
+
+[dependencies.simd-adler32]
+version = "0.3"
+optional = true
+default-features = false
+
+[features]
+default = []
+rustc-dep-of-std = ["core", "alloc", "compiler_builtins", "adler/rustc-dep-of-std"]
+simd = ["simd-adler32"]
diff --git a/vendor/time-macros/LICENSE-MIT b/vendor/miniz_oxide-0.5.3/LICENSE
index a11a75573..64c53792c 100644
--- a/vendor/time-macros/LICENSE-MIT
+++ b/vendor/miniz_oxide-0.5.3/LICENSE
@@ -1,4 +1,6 @@
-Copyright (c) 2022 Jacob Pratt et al.
+MIT License
+
+Copyright (c) 2017 Frommi
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
diff --git a/vendor/time-macros/LICENSE-Apache b/vendor/miniz_oxide-0.5.3/LICENSE-APACHE.md
index 7646f21e3..f433b1a53 100644
--- a/vendor/time-macros/LICENSE-Apache
+++ b/vendor/miniz_oxide-0.5.3/LICENSE-APACHE.md
@@ -175,28 +175,3 @@
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
-
- APPENDIX: How to apply the Apache License to your work.
-
- To apply the Apache License to your work, attach the following
- boilerplate notice, with the fields enclosed by brackets "[]"
- replaced with your own identifying information. (Don't include
- the brackets!) The text should be enclosed in the appropriate
- comment syntax for the file format. We also recommend that a
- file or class name and description of purpose be included on the
- same "printed page" as the copyright notice for easier
- identification within third-party archives.
-
- Copyright 2022 Jacob Pratt et al.
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
diff --git a/vendor/miniz_oxide-0.5.3/LICENSE-MIT.md b/vendor/miniz_oxide-0.5.3/LICENSE-MIT.md
new file mode 100644
index 000000000..64c53792c
--- /dev/null
+++ b/vendor/miniz_oxide-0.5.3/LICENSE-MIT.md
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2017 Frommi
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/vendor/miniz_oxide-0.5.3/LICENSE-ZLIB.md b/vendor/miniz_oxide-0.5.3/LICENSE-ZLIB.md
new file mode 100644
index 000000000..7f513d1ac
--- /dev/null
+++ b/vendor/miniz_oxide-0.5.3/LICENSE-ZLIB.md
@@ -0,0 +1,11 @@
+Copyright (c) 2020 Frommi
+
+This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software.
+
+Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+
+3. This notice may not be removed or altered from any source distribution.
diff --git a/vendor/miniz_oxide-0.5.3/Readme.md b/vendor/miniz_oxide-0.5.3/Readme.md
new file mode 100644
index 000000000..0eac176e8
--- /dev/null
+++ b/vendor/miniz_oxide-0.5.3/Readme.md
@@ -0,0 +1,35 @@
+# miniz_oxide
+
+A fully safe, pure rust replacement for the [miniz](https://github.com/richgel999/miniz) DEFLATE/zlib encoder/decoder.
+The main intention of this crate is to be used as a back-end for the [flate2](https://github.com/alexcrichton/flate2-rs), but it can also be used on it's own. Using flate2 with the ```rust_backend``` feature provides an easy to use streaming API for miniz_oxide.
+
+The library is fully [no_std](https://docs.rust-embedded.org/book/intro/no-std.html), though it requires the use of the `alloc` and `collection` crates as it allocates memory.
+
+miniz_oxide 0.5.x Requires at least rust 1.40.0 0.3.x requires at least rust 0.36.0.
+
+miniz_oxide features no use of unsafe code.
+
+miniz_oxide can optionally be made to use a simd-accelerated version of adler32 via the [simd-adler32](https://crates.io/crates/simd-adler32) crate by enabling the 'simd' feature. This is not enabled by default as due to the use of simd intrinsics, the simd-adler32 has to use unsafe. The default setup uses the [adler](https://crates.io/crates/adler) crate which features no unsafe code.
+
+## Usage
+Simple compression/decompression:
+```rust
+
+use miniz_oxide::deflate::compress_to_vec;
+use miniz_oxide::inflate::decompress_to_vec;
+
+fn roundtrip(data: &[u8]) {
+ // Compress the input
+ let compressed = compress_to_vec(data, 6);
+ // Decompress the compressed input
+ let decompressed = decompress_to_vec(compressed.as_slice()).expect("Failed to decompress!");
+ // Check roundtrip succeeded
+ assert_eq!(data, decompressed);
+}
+
+fn main() {
+ roundtrip("Hello, world!".as_bytes());
+}
+
+```
+These simple functions will do everything in one go and are thus not recommended for use cases where the input size may be large or unknown, for that use case consider using miniz_oxide via flate2 or the low-level streaming functions instead.
diff --git a/vendor/miniz_oxide-0.5.3/src/deflate/buffer.rs b/vendor/miniz_oxide-0.5.3/src/deflate/buffer.rs
new file mode 100644
index 000000000..f246c07df
--- /dev/null
+++ b/vendor/miniz_oxide-0.5.3/src/deflate/buffer.rs
@@ -0,0 +1,58 @@
+//! Buffer wrappers implementing default so we can allocate the buffers with `Box::default()`
+//! to avoid stack copies. Box::new() doesn't at the moment, and using a vec means we would lose
+//! static length info.
+
+use crate::deflate::core::{LZ_DICT_SIZE, MAX_MATCH_LEN};
+
+/// Size of the buffer of lz77 encoded data.
+pub const LZ_CODE_BUF_SIZE: usize = 64 * 1024;
+/// Size of the output buffer.
+pub const OUT_BUF_SIZE: usize = (LZ_CODE_BUF_SIZE * 13) / 10;
+pub const LZ_DICT_FULL_SIZE: usize = LZ_DICT_SIZE + MAX_MATCH_LEN - 1 + 1;
+
+/// Size of hash values in the hash chains.
+pub const LZ_HASH_BITS: i32 = 15;
+/// How many bits to shift when updating the current hash value.
+pub const LZ_HASH_SHIFT: i32 = (LZ_HASH_BITS + 2) / 3;
+/// Size of the chained hash tables.
+pub const LZ_HASH_SIZE: usize = 1 << LZ_HASH_BITS;
+
+#[inline]
+pub fn update_hash(current_hash: u16, byte: u8) -> u16 {
+ ((current_hash << LZ_HASH_SHIFT) ^ u16::from(byte)) & (LZ_HASH_SIZE as u16 - 1)
+}
+
+pub struct HashBuffers {
+ pub dict: [u8; LZ_DICT_FULL_SIZE],
+ pub next: [u16; LZ_DICT_SIZE],
+ pub hash: [u16; LZ_DICT_SIZE],
+}
+
+impl HashBuffers {
+ #[inline]
+ pub fn reset(&mut self) {
+ *self = HashBuffers::default();
+ }
+}
+
+impl Default for HashBuffers {
+ fn default() -> HashBuffers {
+ HashBuffers {
+ dict: [0; LZ_DICT_FULL_SIZE],
+ next: [0; LZ_DICT_SIZE],
+ hash: [0; LZ_DICT_SIZE],
+ }
+ }
+}
+
+pub struct LocalBuf {
+ pub b: [u8; OUT_BUF_SIZE],
+}
+
+impl Default for LocalBuf {
+ fn default() -> LocalBuf {
+ LocalBuf {
+ b: [0; OUT_BUF_SIZE],
+ }
+ }
+}
diff --git a/vendor/miniz_oxide-0.5.3/src/deflate/core.rs b/vendor/miniz_oxide-0.5.3/src/deflate/core.rs
new file mode 100644
index 000000000..91a9bf8b8
--- /dev/null
+++ b/vendor/miniz_oxide-0.5.3/src/deflate/core.rs
@@ -0,0 +1,2463 @@
+//! Streaming compression functionality.
+
+use alloc::boxed::Box;
+use core::convert::TryInto;
+use core::{cmp, mem};
+
+use super::super::*;
+use super::deflate_flags::*;
+use super::CompressionLevel;
+use crate::deflate::buffer::{
+ update_hash, HashBuffers, LocalBuf, LZ_CODE_BUF_SIZE, LZ_DICT_FULL_SIZE, LZ_HASH_BITS,
+ LZ_HASH_SHIFT, LZ_HASH_SIZE, OUT_BUF_SIZE,
+};
+use crate::shared::{update_adler32, HUFFMAN_LENGTH_ORDER, MZ_ADLER32_INIT};
+use crate::DataFormat;
+
+// Currently not bubbled up outside this module, so can fill in with more
+// context eventually if needed.
+type Result<T, E = Error> = core::result::Result<T, E>;
+struct Error {}
+
+const MAX_PROBES_MASK: i32 = 0xFFF;
+
+const MAX_SUPPORTED_HUFF_CODESIZE: usize = 32;
+
+/// Length code for length values.
+#[rustfmt::skip]
+const LEN_SYM: [u16; 256] = [
+ 257, 258, 259, 260, 261, 262, 263, 264, 265, 265, 266, 266, 267, 267, 268, 268,
+ 269, 269, 269, 269, 270, 270, 270, 270, 271, 271, 271, 271, 272, 272, 272, 272,
+ 273, 273, 273, 273, 273, 273, 273, 273, 274, 274, 274, 274, 274, 274, 274, 274,
+ 275, 275, 275, 275, 275, 275, 275, 275, 276, 276, 276, 276, 276, 276, 276, 276,
+ 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277,
+ 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278,
+ 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279,
+ 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280,
+ 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281,
+ 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281,
+ 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282,
+ 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282,
+ 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283,
+ 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283,
+ 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284,
+ 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 285
+];
+
+/// Number of extra bits for length values.
+#[rustfmt::skip]
+const LEN_EXTRA: [u8; 256] = [
+ 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+ 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, 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, 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, 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, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0
+];
+
+/// Distance codes for distances smaller than 512.
+#[rustfmt::skip]
+const SMALL_DIST_SYM: [u8; 512] = [
+ 0, 1, 2, 3, 4, 4, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7,
+ 8, 8, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9,
+ 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+ 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
+ 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+ 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+ 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+ 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+ 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+ 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+ 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+ 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+ 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+ 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+ 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+ 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+ 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+ 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+ 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+ 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17
+];
+
+/// Number of extra bits for distances smaller than 512.
+#[rustfmt::skip]
+const SMALL_DIST_EXTRA: [u8; 512] = [
+ 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+ 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, 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, 5, 5, 5, 5, 5, 5,
+ 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, 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, 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, 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, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7
+];
+
+/// Base values to calculate distances above 512.
+#[rustfmt::skip]
+const LARGE_DIST_SYM: [u8; 128] = [
+ 0, 0, 18, 19, 20, 20, 21, 21, 22, 22, 22, 22, 23, 23, 23, 23,
+ 24, 24, 24, 24, 24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 25,
+ 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
+ 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
+ 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
+ 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
+ 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
+ 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29
+];
+
+/// Number of extra bits distances above 512.
+#[rustfmt::skip]
+const LARGE_DIST_EXTRA: [u8; 128] = [
+ 0, 0, 8, 8, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10,
+ 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
+ 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13
+];
+
+#[rustfmt::skip]
+const BITMASKS: [u32; 17] = [
+ 0x0000, 0x0001, 0x0003, 0x0007, 0x000F, 0x001F, 0x003F, 0x007F, 0x00FF,
+ 0x01FF, 0x03FF, 0x07FF, 0x0FFF, 0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF
+];
+
+/// The maximum number of checks for matches in the hash table the compressor will make for each
+/// compression level.
+const NUM_PROBES: [u32; 11] = [0, 1, 6, 32, 16, 32, 128, 256, 512, 768, 1500];
+
+#[derive(Copy, Clone)]
+struct SymFreq {
+ key: u16,
+ sym_index: u16,
+}
+
+pub mod deflate_flags {
+ /// Whether to use a zlib wrapper.
+ pub const TDEFL_WRITE_ZLIB_HEADER: u32 = 0x0000_1000;
+ /// Should we compute the adler32 checksum.
+ pub const TDEFL_COMPUTE_ADLER32: u32 = 0x0000_2000;
+ /// Should we use greedy parsing (as opposed to lazy parsing where look ahead one or more
+ /// bytes to check for better matches.)
+ pub const TDEFL_GREEDY_PARSING_FLAG: u32 = 0x0000_4000;
+ /// Used in miniz to skip zero-initializing hash and dict. We don't do this here, so
+ /// this flag is ignored.
+ pub const TDEFL_NONDETERMINISTIC_PARSING_FLAG: u32 = 0x0000_8000;
+ /// Only look for matches with a distance of 0.
+ pub const TDEFL_RLE_MATCHES: u32 = 0x0001_0000;
+ /// Only use matches that are at least 6 bytes long.
+ pub const TDEFL_FILTER_MATCHES: u32 = 0x0002_0000;
+ /// Force the compressor to only output static blocks. (Blocks using the default huffman codes
+ /// specified in the deflate specification.)
+ pub const TDEFL_FORCE_ALL_STATIC_BLOCKS: u32 = 0x0004_0000;
+ /// Force the compressor to only output raw/uncompressed blocks.
+ pub const TDEFL_FORCE_ALL_RAW_BLOCKS: u32 = 0x0008_0000;
+}
+
+/// Strategy setting for compression.
+///
+/// The non-default settings offer some special-case compression variants.
+#[repr(i32)]
+#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
+pub enum CompressionStrategy {
+ /// Don't use any of the special strategies.
+ Default = 0,
+ /// Only use matches that are at least 5 bytes long.
+ Filtered = 1,
+ /// Don't look for matches, only huffman encode the literals.
+ HuffmanOnly = 2,
+ /// Only look for matches with a distance of 1, i.e do run-length encoding only.
+ RLE = 3,
+ /// Only use static/fixed blocks. (Blocks using the default huffman codes
+ /// specified in the deflate specification.)
+ Fixed = 4,
+}
+
+/// A list of deflate flush types.
+#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
+pub enum TDEFLFlush {
+ /// Normal operation.
+ ///
+ /// Compress as much as there is space for, and then return waiting for more input.
+ None = 0,
+
+ /// Try to flush all the current data and output an empty raw block.
+ Sync = 2,
+
+ /// Same as [`Sync`][Self::Sync], but reset the dictionary so that the following data does not
+ /// depend on previous data.
+ Full = 3,
+
+ /// Try to flush everything and end the deflate stream.
+ ///
+ /// On success this will yield a [`TDEFLStatus::Done`] return status.
+ Finish = 4,
+}
+
+impl From<MZFlush> for TDEFLFlush {
+ fn from(flush: MZFlush) -> Self {
+ match flush {
+ MZFlush::None => TDEFLFlush::None,
+ MZFlush::Sync => TDEFLFlush::Sync,
+ MZFlush::Full => TDEFLFlush::Full,
+ MZFlush::Finish => TDEFLFlush::Finish,
+ _ => TDEFLFlush::None, // TODO: ??? What to do ???
+ }
+ }
+}
+
+impl TDEFLFlush {
+ pub fn new(flush: i32) -> Result<Self, MZError> {
+ match flush {
+ 0 => Ok(TDEFLFlush::None),
+ 2 => Ok(TDEFLFlush::Sync),
+ 3 => Ok(TDEFLFlush::Full),
+ 4 => Ok(TDEFLFlush::Finish),
+ _ => Err(MZError::Param),
+ }
+ }
+}
+
+/// Return status of compression.
+#[repr(i32)]
+#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
+pub enum TDEFLStatus {
+ /// Usage error.
+ ///
+ /// This indicates that either the [`CompressorOxide`] experienced a previous error, or the
+ /// stream has already been [`TDEFLFlush::Finish`]'d.
+ BadParam = -2,
+
+ /// Error putting data into output buffer.
+ ///
+ /// This usually indicates a too-small buffer.
+ PutBufFailed = -1,
+
+ /// Compression succeeded normally.
+ Okay = 0,
+
+ /// Compression succeeded and the deflate stream was ended.
+ ///
+ /// This is the result of calling compression with [`TDEFLFlush::Finish`].
+ Done = 1,
+}
+
+const MAX_HUFF_SYMBOLS: usize = 288;
+/// Size of hash chain for fast compression mode.
+const LEVEL1_HASH_SIZE_MASK: u32 = 4095;
+/// The number of huffman tables used by the compressor.
+/// Literal/length, Distances and Length of the huffman codes for the other two tables.
+const MAX_HUFF_TABLES: usize = 3;
+/// Literal/length codes
+const MAX_HUFF_SYMBOLS_0: usize = 288;
+/// Distance codes.
+const MAX_HUFF_SYMBOLS_1: usize = 32;
+/// Huffman length values.
+const MAX_HUFF_SYMBOLS_2: usize = 19;
+/// Size of the chained hash table.
+pub(crate) const LZ_DICT_SIZE: usize = 32_768;
+/// Mask used when stepping through the hash chains.
+const LZ_DICT_SIZE_MASK: usize = (LZ_DICT_SIZE as u32 - 1) as usize;
+/// The minimum length of a match.
+const MIN_MATCH_LEN: u8 = 3;
+/// The maximum length of a match.
+pub(crate) const MAX_MATCH_LEN: usize = 258;
+
+const DEFAULT_FLAGS: u32 = NUM_PROBES[4] | TDEFL_WRITE_ZLIB_HEADER;
+
+mod zlib {
+ const DEFAULT_CM: u8 = 8;
+ const DEFAULT_CINFO: u8 = 7 << 4;
+ const _DEFAULT_FDICT: u8 = 0;
+ const DEFAULT_CMF: u8 = DEFAULT_CM | DEFAULT_CINFO;
+ /// The 16-bit value consisting of CMF and FLG must be divisible by this to be valid.
+ const FCHECK_DIVISOR: u8 = 31;
+
+ /// Generate FCHECK from CMF and FLG (without FCKECH )so that they are correct according to the
+ /// specification, i.e (CMF*256 + FCHK) % 31 = 0.
+ /// Returns flg with the FCHKECK bits added (any existing FCHECK bits are ignored).
+ fn add_fcheck(cmf: u8, flg: u8) -> u8 {
+ let rem = ((usize::from(cmf) * 256) + usize::from(flg)) % usize::from(FCHECK_DIVISOR);
+
+ // Clear existing FCHECK if any
+ let flg = flg & 0b11100000;
+
+ // Casting is safe as rem can't overflow since it is a value mod 31
+ // We can simply add the value to flg as (31 - rem) will never be above 2^5
+ flg + (FCHECK_DIVISOR - rem as u8)
+ }
+
+ fn zlib_level_from_flags(flags: u32) -> u8 {
+ use super::NUM_PROBES;
+
+ let num_probes = flags & (super::MAX_PROBES_MASK as u32);
+ if flags & super::TDEFL_GREEDY_PARSING_FLAG != 0 {
+ if num_probes <= 1 {
+ 0
+ } else {
+ 1
+ }
+ } else if num_probes >= NUM_PROBES[9] {
+ 3
+ } else {
+ 2
+ }
+ }
+
+ /// Get the zlib header for the level using the default window size and no
+ /// dictionary.
+ fn header_from_level(level: u8) -> [u8; 2] {
+ let cmf = DEFAULT_CMF;
+ [cmf, add_fcheck(cmf, (level as u8) << 6)]
+ }
+
+ /// Create a zlib header from the given compression flags.
+ /// Only level is considered.
+ pub fn header_from_flags(flags: u32) -> [u8; 2] {
+ let level = zlib_level_from_flags(flags);
+ header_from_level(level)
+ }
+
+ #[cfg(test)]
+ mod test {
+ #[test]
+ fn zlib() {
+ use super::super::*;
+ use super::*;
+
+ let test_level = |level, expected| {
+ let flags = create_comp_flags_from_zip_params(
+ level,
+ MZ_DEFAULT_WINDOW_BITS,
+ CompressionStrategy::Default as i32,
+ );
+ assert_eq!(zlib_level_from_flags(flags), expected);
+ };
+
+ assert_eq!(zlib_level_from_flags(DEFAULT_FLAGS), 2);
+ test_level(0, 0);
+ test_level(1, 0);
+ test_level(2, 1);
+ test_level(3, 1);
+ for i in 4..=8 {
+ test_level(i, 2)
+ }
+ test_level(9, 3);
+ test_level(10, 3);
+ }
+
+ #[test]
+ fn test_header() {
+ let header = super::header_from_level(3);
+ assert_eq!(
+ ((usize::from(header[0]) * 256) + usize::from(header[1])) % 31,
+ 0
+ );
+ }
+ }
+}
+
+fn memset<T: Copy>(slice: &mut [T], val: T) {
+ for x in slice {
+ *x = val
+ }
+}
+
+#[cfg(test)]
+#[inline]
+fn write_u16_le(val: u16, slice: &mut [u8], pos: usize) {
+ slice[pos] = val as u8;
+ slice[pos + 1] = (val >> 8) as u8;
+}
+
+// Read the two bytes starting at pos and interpret them as an u16.
+#[inline]
+const fn read_u16_le(slice: &[u8], pos: usize) -> u16 {
+ // The compiler is smart enough to optimize this into an unaligned load.
+ slice[pos] as u16 | ((slice[pos + 1] as u16) << 8)
+}
+
+/// Main compression struct.
+pub struct CompressorOxide {
+ lz: LZOxide,
+ params: ParamsOxide,
+ huff: Box<HuffmanOxide>,
+ dict: DictOxide,
+}
+
+impl CompressorOxide {
+ /// Create a new `CompressorOxide` with the given flags.
+ ///
+ /// # Notes
+ /// This function may be changed to take different parameters in the future.
+ pub fn new(flags: u32) -> Self {
+ CompressorOxide {
+ lz: LZOxide::new(),
+ params: ParamsOxide::new(flags),
+ /// Put HuffmanOxide on the heap with default trick to avoid
+ /// excessive stack copies.
+ huff: Box::default(),
+ dict: DictOxide::new(flags),
+ }
+ }
+
+ /// Get the adler32 checksum of the currently encoded data.
+ pub const fn adler32(&self) -> u32 {
+ self.params.adler32
+ }
+
+ /// Get the return status of the previous [`compress`](fn.compress.html)
+ /// call with this compressor.
+ pub const fn prev_return_status(&self) -> TDEFLStatus {
+ self.params.prev_return_status
+ }
+
+ /// Get the raw compressor flags.
+ ///
+ /// # Notes
+ /// This function may be deprecated or changed in the future to use more rust-style flags.
+ pub const fn flags(&self) -> i32 {
+ self.params.flags as i32
+ }
+
+ /// Returns whether the compressor is wrapping the data in a zlib format or not.
+ pub fn data_format(&self) -> DataFormat {
+ if (self.params.flags & TDEFL_WRITE_ZLIB_HEADER) != 0 {
+ DataFormat::Zlib
+ } else {
+ DataFormat::Raw
+ }
+ }
+
+ /// Reset the state of the compressor, keeping the same parameters.
+ ///
+ /// This avoids re-allocating data.
+ pub fn reset(&mut self) {
+ // LZ buf and huffman has no settings or dynamic memory
+ // that needs to be saved, so we simply replace them.
+ self.lz = LZOxide::new();
+ self.params.reset();
+ *self.huff = HuffmanOxide::default();
+ self.dict.reset();
+ }
+
+ /// Set the compression level of the compressor.
+ ///
+ /// Using this to change level after compression has started is supported.
+ /// # Notes
+ /// The compression strategy will be reset to the default one when this is called.
+ pub fn set_compression_level(&mut self, level: CompressionLevel) {
+ let format = self.data_format();
+ self.set_format_and_level(format, level as u8);
+ }
+
+ /// Set the compression level of the compressor using an integer value.
+ ///
+ /// Using this to change level after compression has started is supported.
+ /// # Notes
+ /// The compression strategy will be reset to the default one when this is called.
+ pub fn set_compression_level_raw(&mut self, level: u8) {
+ let format = self.data_format();
+ self.set_format_and_level(format, level);
+ }
+
+ /// Update the compression settings of the compressor.
+ ///
+ /// Changing the `DataFormat` after compression has started will result in
+ /// a corrupted stream.
+ ///
+ /// # Notes
+ /// This function mainly intended for setting the initial settings after e.g creating with
+ /// `default` or after calling `CompressorOxide::reset()`, and behaviour may be changed
+ /// to disallow calling it after starting compression in the future.
+ pub fn set_format_and_level(&mut self, data_format: DataFormat, level: u8) {
+ let flags = create_comp_flags_from_zip_params(
+ level.into(),
+ data_format.to_window_bits(),
+ CompressionStrategy::Default as i32,
+ );
+ self.params.update_flags(flags);
+ self.dict.update_flags(flags);
+ }
+}
+
+impl Default for CompressorOxide {
+ /// Initialize the compressor with a level of 4, zlib wrapper and
+ /// the default strategy.
+ #[inline(always)]
+ fn default() -> Self {
+ CompressorOxide {
+ lz: LZOxide::new(),
+ params: ParamsOxide::new(DEFAULT_FLAGS),
+ /// Put HuffmanOxide on the heap with default trick to avoid
+ /// excessive stack copies.
+ huff: Box::default(),
+ dict: DictOxide::new(DEFAULT_FLAGS),
+ }
+ }
+}
+
+/// Callback function and user used in `compress_to_output`.
+pub struct CallbackFunc<'a> {
+ pub put_buf_func: &'a mut dyn FnMut(&[u8]) -> bool,
+}
+
+impl<'a> CallbackFunc<'a> {
+ fn flush_output(
+ &mut self,
+ saved_output: SavedOutputBufferOxide,
+ params: &mut ParamsOxide,
+ ) -> i32 {
+ // TODO: As this could be unsafe since
+ // we can't verify the function pointer
+ // this whole function should maybe be unsafe as well.
+ let call_success = (self.put_buf_func)(&params.local_buf.b[0..saved_output.pos as usize]);
+
+ if !call_success {
+ params.prev_return_status = TDEFLStatus::PutBufFailed;
+ return params.prev_return_status as i32;
+ }
+
+ params.flush_remaining as i32
+ }
+}
+
+struct CallbackBuf<'a> {
+ pub out_buf: &'a mut [u8],
+}
+
+impl<'a> CallbackBuf<'a> {
+ fn flush_output(
+ &mut self,
+ saved_output: SavedOutputBufferOxide,
+ params: &mut ParamsOxide,
+ ) -> i32 {
+ if saved_output.local {
+ let n = cmp::min(
+ saved_output.pos as usize,
+ self.out_buf.len() - params.out_buf_ofs,
+ );
+ (&mut self.out_buf[params.out_buf_ofs..params.out_buf_ofs + n])
+ .copy_from_slice(&params.local_buf.b[..n]);
+
+ params.out_buf_ofs += n;
+ if saved_output.pos != n {
+ params.flush_ofs = n as u32;
+ params.flush_remaining = (saved_output.pos - n) as u32;
+ }
+ } else {
+ params.out_buf_ofs += saved_output.pos;
+ }
+
+ params.flush_remaining as i32
+ }
+}
+
+enum CallbackOut<'a> {
+ Func(CallbackFunc<'a>),
+ Buf(CallbackBuf<'a>),
+}
+
+impl<'a> CallbackOut<'a> {
+ fn new_output_buffer<'b>(
+ &'b mut self,
+ local_buf: &'b mut [u8],
+ out_buf_ofs: usize,
+ ) -> OutputBufferOxide<'b> {
+ let is_local;
+ let buf_len = OUT_BUF_SIZE - 16;
+ let chosen_buffer = match *self {
+ CallbackOut::Buf(ref mut cb) if cb.out_buf.len() - out_buf_ofs >= OUT_BUF_SIZE => {
+ is_local = false;
+ &mut cb.out_buf[out_buf_ofs..out_buf_ofs + buf_len]
+ }
+ _ => {
+ is_local = true;
+ &mut local_buf[..buf_len]
+ }
+ };
+
+ OutputBufferOxide {
+ inner: chosen_buffer,
+ inner_pos: 0,
+ local: is_local,
+ bit_buffer: 0,
+ bits_in: 0,
+ }
+ }
+}
+
+struct CallbackOxide<'a> {
+ in_buf: Option<&'a [u8]>,
+ in_buf_size: Option<&'a mut usize>,
+ out_buf_size: Option<&'a mut usize>,
+ out: CallbackOut<'a>,
+}
+
+impl<'a> CallbackOxide<'a> {
+ fn new_callback_buf(in_buf: &'a [u8], out_buf: &'a mut [u8]) -> Self {
+ CallbackOxide {
+ in_buf: Some(in_buf),
+ in_buf_size: None,
+ out_buf_size: None,
+ out: CallbackOut::Buf(CallbackBuf { out_buf }),
+ }
+ }
+
+ fn new_callback_func(in_buf: &'a [u8], callback_func: CallbackFunc<'a>) -> Self {
+ CallbackOxide {
+ in_buf: Some(in_buf),
+ in_buf_size: None,
+ out_buf_size: None,
+ out: CallbackOut::Func(callback_func),
+ }
+ }
+
+ fn update_size(&mut self, in_size: Option<usize>, out_size: Option<usize>) {
+ if let (Some(in_size), Some(size)) = (in_size, self.in_buf_size.as_mut()) {
+ **size = in_size;
+ }
+
+ if let (Some(out_size), Some(size)) = (out_size, self.out_buf_size.as_mut()) {
+ **size = out_size
+ }
+ }
+
+ fn flush_output(
+ &mut self,
+ saved_output: SavedOutputBufferOxide,
+ params: &mut ParamsOxide,
+ ) -> i32 {
+ if saved_output.pos == 0 {
+ return params.flush_remaining as i32;
+ }
+
+ self.update_size(Some(params.src_pos), None);
+ match self.out {
+ CallbackOut::Func(ref mut cf) => cf.flush_output(saved_output, params),
+ CallbackOut::Buf(ref mut cb) => cb.flush_output(saved_output, params),
+ }
+ }
+}
+
+struct OutputBufferOxide<'a> {
+ pub inner: &'a mut [u8],
+ pub inner_pos: usize,
+ pub local: bool,
+
+ pub bit_buffer: u32,
+ pub bits_in: u32,
+}
+
+impl<'a> OutputBufferOxide<'a> {
+ fn put_bits(&mut self, bits: u32, len: u32) {
+ assert!(bits <= ((1u32 << len) - 1u32));
+ self.bit_buffer |= bits << self.bits_in;
+ self.bits_in += len;
+ while self.bits_in >= 8 {
+ self.inner[self.inner_pos] = self.bit_buffer as u8;
+ self.inner_pos += 1;
+ self.bit_buffer >>= 8;
+ self.bits_in -= 8;
+ }
+ }
+
+ const fn save(&self) -> SavedOutputBufferOxide {
+ SavedOutputBufferOxide {
+ pos: self.inner_pos,
+ bit_buffer: self.bit_buffer,
+ bits_in: self.bits_in,
+ local: self.local,
+ }
+ }
+
+ fn load(&mut self, saved: SavedOutputBufferOxide) {
+ self.inner_pos = saved.pos;
+ self.bit_buffer = saved.bit_buffer;
+ self.bits_in = saved.bits_in;
+ self.local = saved.local;
+ }
+
+ fn pad_to_bytes(&mut self) {
+ if self.bits_in != 0 {
+ let len = 8 - self.bits_in;
+ self.put_bits(0, len);
+ }
+ }
+}
+
+struct SavedOutputBufferOxide {
+ pub pos: usize,
+ pub bit_buffer: u32,
+ pub bits_in: u32,
+ pub local: bool,
+}
+
+struct BitBuffer {
+ pub bit_buffer: u64,
+ pub bits_in: u32,
+}
+
+impl BitBuffer {
+ fn put_fast(&mut self, bits: u64, len: u32) {
+ self.bit_buffer |= bits << self.bits_in;
+ self.bits_in += len;
+ }
+
+ fn flush(&mut self, output: &mut OutputBufferOxide) -> Result<()> {
+ let pos = output.inner_pos;
+ {
+ // isolation to please borrow checker
+ let inner = &mut output.inner[pos..pos + 8];
+ let bytes = u64::to_le_bytes(self.bit_buffer);
+ inner.copy_from_slice(&bytes);
+ }
+ match output.inner_pos.checked_add((self.bits_in >> 3) as usize) {
+ Some(n) if n <= output.inner.len() => output.inner_pos = n,
+ _ => return Err(Error {}),
+ }
+ self.bit_buffer >>= self.bits_in & !7;
+ self.bits_in &= 7;
+ Ok(())
+ }
+}
+
+/// A struct containing data about huffman codes and symbol frequencies.
+///
+/// NOTE: Only the literal/lengths have enough symbols to actually use
+/// the full array. It's unclear why it's defined like this in miniz,
+/// it could be for cache/alignment reasons.
+struct HuffmanOxide {
+ /// Number of occurrences of each symbol.
+ pub count: [[u16; MAX_HUFF_SYMBOLS]; MAX_HUFF_TABLES],
+ /// The bits of the huffman code assigned to the symbol
+ pub codes: [[u16; MAX_HUFF_SYMBOLS]; MAX_HUFF_TABLES],
+ /// The length of the huffman code assigned to the symbol.
+ pub code_sizes: [[u8; MAX_HUFF_SYMBOLS]; MAX_HUFF_TABLES],
+}
+
+/// Tables used for literal/lengths in `HuffmanOxide`.
+const LITLEN_TABLE: usize = 0;
+/// Tables for distances.
+const DIST_TABLE: usize = 1;
+/// Tables for the run-length encoded huffman lengths for literals/lengths/distances.
+const HUFF_CODES_TABLE: usize = 2;
+
+/// Status of RLE encoding of huffman code lengths.
+struct Rle {
+ pub z_count: u32,
+ pub repeat_count: u32,
+ pub prev_code_size: u8,
+}
+
+impl Rle {
+ fn prev_code_size(
+ &mut self,
+ packed_code_sizes: &mut [u8],
+ packed_pos: &mut usize,
+ h: &mut HuffmanOxide,
+ ) -> Result<()> {
+ let mut write = |buf| write(buf, packed_code_sizes, packed_pos);
+ let counts = &mut h.count[HUFF_CODES_TABLE];
+ if self.repeat_count != 0 {
+ if self.repeat_count < 3 {
+ counts[self.prev_code_size as usize] =
+ counts[self.prev_code_size as usize].wrapping_add(self.repeat_count as u16);
+ let code = self.prev_code_size;
+ write(&[code, code, code][..self.repeat_count as usize])?;
+ } else {
+ counts[16] = counts[16].wrapping_add(1);
+ write(&[16, (self.repeat_count - 3) as u8][..])?;
+ }
+ self.repeat_count = 0;
+ }
+
+ Ok(())
+ }
+
+ fn zero_code_size(
+ &mut self,
+ packed_code_sizes: &mut [u8],
+ packed_pos: &mut usize,
+ h: &mut HuffmanOxide,
+ ) -> Result<()> {
+ let mut write = |buf| write(buf, packed_code_sizes, packed_pos);
+ let counts = &mut h.count[HUFF_CODES_TABLE];
+ if self.z_count != 0 {
+ if self.z_count < 3 {
+ counts[0] = counts[0].wrapping_add(self.z_count as u16);
+ write(&[0, 0, 0][..self.z_count as usize])?;
+ } else if self.z_count <= 10 {
+ counts[17] = counts[17].wrapping_add(1);
+ write(&[17, (self.z_count - 3) as u8][..])?;
+ } else {
+ counts[18] = counts[18].wrapping_add(1);
+ write(&[18, (self.z_count - 11) as u8][..])?;
+ }
+ self.z_count = 0;
+ }
+
+ Ok(())
+ }
+}
+
+fn write(src: &[u8], dst: &mut [u8], dst_pos: &mut usize) -> Result<()> {
+ match dst.get_mut(*dst_pos..*dst_pos + src.len()) {
+ Some(s) => s.copy_from_slice(src),
+ None => return Err(Error {}),
+ }
+ *dst_pos += src.len();
+ Ok(())
+}
+
+impl Default for HuffmanOxide {
+ fn default() -> Self {
+ HuffmanOxide {
+ count: [[0; MAX_HUFF_SYMBOLS]; MAX_HUFF_TABLES],
+ codes: [[0; MAX_HUFF_SYMBOLS]; MAX_HUFF_TABLES],
+ code_sizes: [[0; MAX_HUFF_SYMBOLS]; MAX_HUFF_TABLES],
+ }
+ }
+}
+
+impl HuffmanOxide {
+ fn radix_sort_symbols<'a>(
+ symbols0: &'a mut [SymFreq],
+ symbols1: &'a mut [SymFreq],
+ ) -> &'a mut [SymFreq] {
+ let mut hist = [[0; 256]; 2];
+
+ for freq in symbols0.iter() {
+ hist[0][(freq.key & 0xFF) as usize] += 1;
+ hist[1][((freq.key >> 8) & 0xFF) as usize] += 1;
+ }
+
+ let mut n_passes = 2;
+ if symbols0.len() == hist[1][0] {
+ n_passes -= 1;
+ }
+
+ let mut current_symbols = symbols0;
+ let mut new_symbols = symbols1;
+
+ for (pass, hist_item) in hist.iter().enumerate().take(n_passes) {
+ let mut offsets = [0; 256];
+ let mut offset = 0;
+ for i in 0..256 {
+ offsets[i] = offset;
+ offset += hist_item[i];
+ }
+
+ for sym in current_symbols.iter() {
+ let j = ((sym.key >> (pass * 8)) & 0xFF) as usize;
+ new_symbols[offsets[j]] = *sym;
+ offsets[j] += 1;
+ }
+
+ mem::swap(&mut current_symbols, &mut new_symbols);
+ }
+
+ current_symbols
+ }
+
+ fn calculate_minimum_redundancy(symbols: &mut [SymFreq]) {
+ match symbols.len() {
+ 0 => (),
+ 1 => symbols[0].key = 1,
+ n => {
+ symbols[0].key += symbols[1].key;
+ let mut root = 0;
+ let mut leaf = 2;
+ for next in 1..n - 1 {
+ if (leaf >= n) || (symbols[root].key < symbols[leaf].key) {
+ symbols[next].key = symbols[root].key;
+ symbols[root].key = next as u16;
+ root += 1;
+ } else {
+ symbols[next].key = symbols[leaf].key;
+ leaf += 1;
+ }
+
+ if (leaf >= n) || (root < next && symbols[root].key < symbols[leaf].key) {
+ symbols[next].key = symbols[next].key.wrapping_add(symbols[root].key);
+ symbols[root].key = next as u16;
+ root += 1;
+ } else {
+ symbols[next].key = symbols[next].key.wrapping_add(symbols[leaf].key);
+ leaf += 1;
+ }
+ }
+
+ symbols[n - 2].key = 0;
+ for next in (0..n - 2).rev() {
+ symbols[next].key = symbols[symbols[next].key as usize].key + 1;
+ }
+
+ let mut avbl = 1;
+ let mut used = 0;
+ let mut dpth = 0;
+ let mut root = (n - 2) as i32;
+ let mut next = (n - 1) as i32;
+ while avbl > 0 {
+ while (root >= 0) && (symbols[root as usize].key == dpth) {
+ used += 1;
+ root -= 1;
+ }
+ while avbl > used {
+ symbols[next as usize].key = dpth;
+ next -= 1;
+ avbl -= 1;
+ }
+ avbl = 2 * used;
+ dpth += 1;
+ used = 0;
+ }
+ }
+ }
+ }
+
+ fn enforce_max_code_size(num_codes: &mut [i32], code_list_len: usize, max_code_size: usize) {
+ if code_list_len <= 1 {
+ return;
+ }
+
+ num_codes[max_code_size] += num_codes[max_code_size + 1..].iter().sum::<i32>();
+ let total = num_codes[1..=max_code_size]
+ .iter()
+ .rev()
+ .enumerate()
+ .fold(0u32, |total, (i, &x)| total + ((x as u32) << i));
+
+ for _ in (1 << max_code_size)..total {
+ num_codes[max_code_size] -= 1;
+ for i in (1..max_code_size).rev() {
+ if num_codes[i] != 0 {
+ num_codes[i] -= 1;
+ num_codes[i + 1] += 2;
+ break;
+ }
+ }
+ }
+ }
+
+ fn optimize_table(
+ &mut self,
+ table_num: usize,
+ table_len: usize,
+ code_size_limit: usize,
+ static_table: bool,
+ ) {
+ let mut num_codes = [0i32; MAX_SUPPORTED_HUFF_CODESIZE + 1];
+ let mut next_code = [0u32; MAX_SUPPORTED_HUFF_CODESIZE + 1];
+
+ if static_table {
+ for &code_size in &self.code_sizes[table_num][..table_len] {
+ num_codes[code_size as usize] += 1;
+ }
+ } else {
+ let mut symbols0 = [SymFreq {
+ key: 0,
+ sym_index: 0,
+ }; MAX_HUFF_SYMBOLS];
+ let mut symbols1 = [SymFreq {
+ key: 0,
+ sym_index: 0,
+ }; MAX_HUFF_SYMBOLS];
+
+ let mut num_used_symbols = 0;
+ for i in 0..table_len {
+ if self.count[table_num][i] != 0 {
+ symbols0[num_used_symbols] = SymFreq {
+ key: self.count[table_num][i],
+ sym_index: i as u16,
+ };
+ num_used_symbols += 1;
+ }
+ }
+
+ let symbols = Self::radix_sort_symbols(
+ &mut symbols0[..num_used_symbols],
+ &mut symbols1[..num_used_symbols],
+ );
+ Self::calculate_minimum_redundancy(symbols);
+
+ for symbol in symbols.iter() {
+ num_codes[symbol.key as usize] += 1;
+ }
+
+ Self::enforce_max_code_size(&mut num_codes, num_used_symbols, code_size_limit);
+
+ memset(&mut self.code_sizes[table_num][..], 0);
+ memset(&mut self.codes[table_num][..], 0);
+
+ let mut last = num_used_symbols;
+ for (i, &num_item) in num_codes
+ .iter()
+ .enumerate()
+ .take(code_size_limit + 1)
+ .skip(1)
+ {
+ let first = last - num_item as usize;
+ for symbol in &symbols[first..last] {
+ self.code_sizes[table_num][symbol.sym_index as usize] = i as u8;
+ }
+ last = first;
+ }
+ }
+
+ let mut j = 0;
+ next_code[1] = 0;
+ for i in 2..=code_size_limit {
+ j = (j + num_codes[i - 1]) << 1;
+ next_code[i] = j as u32;
+ }
+
+ for (&code_size, huff_code) in self.code_sizes[table_num]
+ .iter()
+ .take(table_len)
+ .zip(self.codes[table_num].iter_mut().take(table_len))
+ {
+ if code_size == 0 {
+ continue;
+ }
+
+ let mut code = next_code[code_size as usize];
+ next_code[code_size as usize] += 1;
+
+ let mut rev_code = 0;
+ for _ in 0..code_size {
+ rev_code = (rev_code << 1) | (code & 1);
+ code >>= 1;
+ }
+ *huff_code = rev_code as u16;
+ }
+ }
+
+ fn start_static_block(&mut self, output: &mut OutputBufferOxide) {
+ memset(&mut self.code_sizes[LITLEN_TABLE][0..144], 8);
+ memset(&mut self.code_sizes[LITLEN_TABLE][144..256], 9);
+ memset(&mut self.code_sizes[LITLEN_TABLE][256..280], 7);
+ memset(&mut self.code_sizes[LITLEN_TABLE][280..288], 8);
+
+ memset(&mut self.code_sizes[DIST_TABLE][..32], 5);
+
+ self.optimize_table(LITLEN_TABLE, 288, 15, true);
+ self.optimize_table(DIST_TABLE, 32, 15, true);
+
+ output.put_bits(0b01, 2)
+ }
+
+ fn start_dynamic_block(&mut self, output: &mut OutputBufferOxide) -> Result<()> {
+ // There will always be one, and only one end of block code.
+ self.count[0][256] = 1;
+
+ self.optimize_table(0, MAX_HUFF_SYMBOLS_0, 15, false);
+ self.optimize_table(1, MAX_HUFF_SYMBOLS_1, 15, false);
+
+ let num_lit_codes = 286
+ - &self.code_sizes[0][257..286]
+ .iter()
+ .rev()
+ .take_while(|&x| *x == 0)
+ .count();
+
+ let num_dist_codes = 30
+ - &self.code_sizes[1][1..30]
+ .iter()
+ .rev()
+ .take_while(|&x| *x == 0)
+ .count();
+
+ let mut code_sizes_to_pack = [0u8; MAX_HUFF_SYMBOLS_0 + MAX_HUFF_SYMBOLS_1];
+ let mut packed_code_sizes = [0u8; MAX_HUFF_SYMBOLS_0 + MAX_HUFF_SYMBOLS_1];
+
+ let total_code_sizes_to_pack = num_lit_codes + num_dist_codes;
+
+ code_sizes_to_pack[..num_lit_codes].copy_from_slice(&self.code_sizes[0][..num_lit_codes]);
+
+ code_sizes_to_pack[num_lit_codes..total_code_sizes_to_pack]
+ .copy_from_slice(&self.code_sizes[1][..num_dist_codes]);
+
+ let mut rle = Rle {
+ z_count: 0,
+ repeat_count: 0,
+ prev_code_size: 0xFF,
+ };
+
+ memset(&mut self.count[HUFF_CODES_TABLE][..MAX_HUFF_SYMBOLS_2], 0);
+
+ let mut packed_pos = 0;
+ for &code_size in &code_sizes_to_pack[..total_code_sizes_to_pack] {
+ if code_size == 0 {
+ rle.prev_code_size(&mut packed_code_sizes, &mut packed_pos, self)?;
+ rle.z_count += 1;
+ if rle.z_count == 138 {
+ rle.zero_code_size(&mut packed_code_sizes, &mut packed_pos, self)?;
+ }
+ } else {
+ rle.zero_code_size(&mut packed_code_sizes, &mut packed_pos, self)?;
+ if code_size != rle.prev_code_size {
+ rle.prev_code_size(&mut packed_code_sizes, &mut packed_pos, self)?;
+ self.count[HUFF_CODES_TABLE][code_size as usize] =
+ self.count[HUFF_CODES_TABLE][code_size as usize].wrapping_add(1);
+ write(&[code_size], &mut packed_code_sizes, &mut packed_pos)?;
+ } else {
+ rle.repeat_count += 1;
+ if rle.repeat_count == 6 {
+ rle.prev_code_size(&mut packed_code_sizes, &mut packed_pos, self)?;
+ }
+ }
+ }
+ rle.prev_code_size = code_size;
+ }
+
+ if rle.repeat_count != 0 {
+ rle.prev_code_size(&mut packed_code_sizes, &mut packed_pos, self)?;
+ } else {
+ rle.zero_code_size(&mut packed_code_sizes, &mut packed_pos, self)?;
+ }
+
+ self.optimize_table(2, MAX_HUFF_SYMBOLS_2, 7, false);
+
+ output.put_bits(2, 2);
+
+ output.put_bits((num_lit_codes - 257) as u32, 5);
+ output.put_bits((num_dist_codes - 1) as u32, 5);
+
+ let mut num_bit_lengths = 18
+ - HUFFMAN_LENGTH_ORDER
+ .iter()
+ .rev()
+ .take_while(|&swizzle| self.code_sizes[HUFF_CODES_TABLE][*swizzle as usize] == 0)
+ .count();
+
+ num_bit_lengths = cmp::max(4, num_bit_lengths + 1);
+ output.put_bits(num_bit_lengths as u32 - 4, 4);
+ for &swizzle in &HUFFMAN_LENGTH_ORDER[..num_bit_lengths] {
+ output.put_bits(
+ u32::from(self.code_sizes[HUFF_CODES_TABLE][swizzle as usize]),
+ 3,
+ );
+ }
+
+ let mut packed_code_size_index = 0;
+ while packed_code_size_index < packed_pos {
+ let code = packed_code_sizes[packed_code_size_index] as usize;
+ packed_code_size_index += 1;
+ assert!(code < MAX_HUFF_SYMBOLS_2);
+ output.put_bits(
+ u32::from(self.codes[HUFF_CODES_TABLE][code]),
+ u32::from(self.code_sizes[HUFF_CODES_TABLE][code]),
+ );
+ if code >= 16 {
+ output.put_bits(
+ u32::from(packed_code_sizes[packed_code_size_index]),
+ [2, 3, 7][code - 16],
+ );
+ packed_code_size_index += 1;
+ }
+ }
+
+ Ok(())
+ }
+}
+
+struct DictOxide {
+ /// The maximum number of checks in the hash chain, for the initial,
+ /// and the lazy match respectively.
+ pub max_probes: [u32; 2],
+ /// Buffer of input data.
+ /// Padded with 1 byte to simplify matching code in `compress_fast`.
+ pub b: Box<HashBuffers>,
+
+ pub code_buf_dict_pos: usize,
+ pub lookahead_size: usize,
+ pub lookahead_pos: usize,
+ pub size: usize,
+}
+
+const fn probes_from_flags(flags: u32) -> [u32; 2] {
+ [
+ 1 + ((flags & 0xFFF) + 2) / 3,
+ 1 + (((flags & 0xFFF) >> 2) + 2) / 3,
+ ]
+}
+
+impl DictOxide {
+ fn new(flags: u32) -> Self {
+ DictOxide {
+ max_probes: probes_from_flags(flags),
+ b: Box::default(),
+ code_buf_dict_pos: 0,
+ lookahead_size: 0,
+ lookahead_pos: 0,
+ size: 0,
+ }
+ }
+
+ fn update_flags(&mut self, flags: u32) {
+ self.max_probes = probes_from_flags(flags);
+ }
+
+ fn reset(&mut self) {
+ self.b.reset();
+ self.code_buf_dict_pos = 0;
+ self.lookahead_size = 0;
+ self.lookahead_pos = 0;
+ self.size = 0;
+ }
+
+ /// Do an unaligned read of the data at `pos` in the dictionary and treat it as if it was of
+ /// type T.
+ #[inline]
+ fn read_unaligned_u32(&self, pos: usize) -> u32 {
+ // Masking the value here helps avoid bounds checks.
+ let pos = (pos & LZ_DICT_SIZE_MASK) as usize;
+ let end = pos + 4;
+ // Somehow this assertion makes things faster.
+ assert!(end < LZ_DICT_FULL_SIZE);
+
+ let bytes: [u8; 4] = self.b.dict[pos..end].try_into().unwrap();
+ u32::from_le_bytes(bytes)
+ }
+
+ /// Do an unaligned read of the data at `pos` in the dictionary and treat it as if it was of
+ /// type T.
+ #[inline]
+ fn read_unaligned_u64(&self, pos: usize) -> u64 {
+ let pos = pos as usize;
+ let bytes: [u8; 8] = self.b.dict[pos..pos + 8].try_into().unwrap();
+ u64::from_le_bytes(bytes)
+ }
+
+ /// Do an unaligned read of the data at `pos` in the dictionary and treat it as if it was of
+ /// type T.
+ #[inline]
+ fn read_as_u16(&self, pos: usize) -> u16 {
+ read_u16_le(&self.b.dict[..], pos)
+ }
+
+ /// Try to find a match for the data at lookahead_pos in the dictionary that is
+ /// longer than `match_len`.
+ /// Returns a tuple containing (match_distance, match_length). Will be equal to the input
+ /// values if no better matches were found.
+ fn find_match(
+ &self,
+ lookahead_pos: usize,
+ max_dist: usize,
+ max_match_len: u32,
+ mut match_dist: u32,
+ mut match_len: u32,
+ ) -> (u32, u32) {
+ // Clamp the match len and max_match_len to be valid. (It should be when this is called, but
+ // do it for now just in case for safety reasons.)
+ // This should normally end up as at worst conditional moves,
+ // so it shouldn't slow us down much.
+ // TODO: Statically verify these so we don't need to do this.
+ let max_match_len = cmp::min(MAX_MATCH_LEN as u32, max_match_len);
+ match_len = cmp::max(match_len, 1);
+
+ let pos = lookahead_pos as usize & LZ_DICT_SIZE_MASK;
+ let mut probe_pos = pos;
+ // Number of probes into the hash chains.
+ let mut num_probes_left = self.max_probes[(match_len >= 32) as usize];
+
+ // If we already have a match of the full length don't bother searching for another one.
+ if max_match_len <= match_len {
+ return (match_dist, match_len);
+ }
+
+ // Read the last byte of the current match, and the next one, used to compare matches.
+ let mut c01: u16 = self.read_as_u16(pos as usize + match_len as usize - 1);
+ // Read the two bytes at the end position of the current match.
+ let s01: u16 = self.read_as_u16(pos as usize);
+
+ 'outer: loop {
+ let mut dist;
+ 'found: loop {
+ num_probes_left -= 1;
+ if num_probes_left == 0 {
+ // We have done as many probes in the hash chain as the current compression
+ // settings allow, so return the best match we found, if any.
+ return (match_dist, match_len);
+ }
+
+ for _ in 0..3 {
+ let next_probe_pos = self.b.next[probe_pos as usize] as usize;
+
+ dist = (lookahead_pos - next_probe_pos) & 0xFFFF;
+ if next_probe_pos == 0 || dist > max_dist {
+ // We reached the end of the hash chain, or the next value is further away
+ // than the maximum allowed distance, so return the best match we found, if
+ // any.
+ return (match_dist, match_len);
+ }
+
+ // Mask the position value to get the position in the hash chain of the next
+ // position to match against.
+ probe_pos = next_probe_pos & LZ_DICT_SIZE_MASK;
+
+ if self.read_as_u16((probe_pos + match_len as usize - 1) as usize) == c01 {
+ break 'found;
+ }
+ }
+ }
+
+ if dist == 0 {
+ // We've looked through the whole match range, so return the best match we
+ // found.
+ return (match_dist, match_len);
+ }
+
+ // Check if the two first bytes match.
+ if self.read_as_u16(probe_pos as usize) != s01 {
+ continue;
+ }
+
+ let mut p = pos + 2;
+ let mut q = probe_pos + 2;
+ // The first two bytes matched, so check the full length of the match.
+ for _ in 0..32 {
+ let p_data: u64 = self.read_unaligned_u64(p);
+ let q_data: u64 = self.read_unaligned_u64(q);
+ // Compare of 8 bytes at a time by using unaligned loads of 64-bit integers.
+ let xor_data = p_data ^ q_data;
+ if xor_data == 0 {
+ p += 8;
+ q += 8;
+ } else {
+ // If not all of the last 8 bytes matched, check how may of them did.
+ let trailing = xor_data.trailing_zeros();
+
+ let probe_len = p - pos + (trailing as usize >> 3);
+ if probe_len > match_len as usize {
+ match_dist = dist as u32;
+ match_len = cmp::min(max_match_len, probe_len as u32);
+ if match_len == max_match_len {
+ // We found a match that had the maximum allowed length,
+ // so there is now point searching further.
+ return (match_dist, match_len);
+ }
+ // We found a better match, so save the last two bytes for further match
+ // comparisons.
+ c01 = self.read_as_u16(pos + match_len as usize - 1)
+ }
+ continue 'outer;
+ }
+ }
+
+ return (dist as u32, cmp::min(max_match_len, MAX_MATCH_LEN as u32));
+ }
+ }
+}
+
+struct ParamsOxide {
+ pub flags: u32,
+ pub greedy_parsing: bool,
+ pub block_index: u32,
+
+ pub saved_match_dist: u32,
+ pub saved_match_len: u32,
+ pub saved_lit: u8,
+
+ pub flush: TDEFLFlush,
+ pub flush_ofs: u32,
+ pub flush_remaining: u32,
+ pub finished: bool,
+
+ pub adler32: u32,
+
+ pub src_pos: usize,
+
+ pub out_buf_ofs: usize,
+ pub prev_return_status: TDEFLStatus,
+
+ pub saved_bit_buffer: u32,
+ pub saved_bits_in: u32,
+
+ pub local_buf: Box<LocalBuf>,
+}
+
+impl ParamsOxide {
+ fn new(flags: u32) -> Self {
+ ParamsOxide {
+ flags,
+ greedy_parsing: flags & TDEFL_GREEDY_PARSING_FLAG != 0,
+ block_index: 0,
+ saved_match_dist: 0,
+ saved_match_len: 0,
+ saved_lit: 0,
+ flush: TDEFLFlush::None,
+ flush_ofs: 0,
+ flush_remaining: 0,
+ finished: false,
+ adler32: MZ_ADLER32_INIT,
+ src_pos: 0,
+ out_buf_ofs: 0,
+ prev_return_status: TDEFLStatus::Okay,
+ saved_bit_buffer: 0,
+ saved_bits_in: 0,
+ local_buf: Box::default(),
+ }
+ }
+
+ fn update_flags(&mut self, flags: u32) {
+ self.flags = flags;
+ self.greedy_parsing = self.flags & TDEFL_GREEDY_PARSING_FLAG != 0;
+ }
+
+ /// Reset state, saving settings.
+ fn reset(&mut self) {
+ self.block_index = 0;
+ self.saved_match_len = 0;
+ self.saved_match_dist = 0;
+ self.saved_lit = 0;
+ self.flush = TDEFLFlush::None;
+ self.flush_ofs = 0;
+ self.flush_remaining = 0;
+ self.finished = false;
+ self.adler32 = MZ_ADLER32_INIT;
+ self.src_pos = 0;
+ self.out_buf_ofs = 0;
+ self.prev_return_status = TDEFLStatus::Okay;
+ self.saved_bit_buffer = 0;
+ self.saved_bits_in = 0;
+ self.local_buf.b = [0; OUT_BUF_SIZE];
+ }
+}
+
+struct LZOxide {
+ pub codes: [u8; LZ_CODE_BUF_SIZE],
+ pub code_position: usize,
+ pub flag_position: usize,
+
+ // The total number of bytes in the current block.
+ // (Could maybe use usize, but it's not possible to exceed a block size of )
+ pub total_bytes: u32,
+ pub num_flags_left: u32,
+}
+
+impl LZOxide {
+ const fn new() -> Self {
+ LZOxide {
+ codes: [0; LZ_CODE_BUF_SIZE],
+ code_position: 1,
+ flag_position: 0,
+ total_bytes: 0,
+ num_flags_left: 8,
+ }
+ }
+
+ fn write_code(&mut self, val: u8) {
+ self.codes[self.code_position] = val;
+ self.code_position += 1;
+ }
+
+ fn init_flag(&mut self) {
+ if self.num_flags_left == 8 {
+ *self.get_flag() = 0;
+ self.code_position -= 1;
+ } else {
+ *self.get_flag() >>= self.num_flags_left;
+ }
+ }
+
+ fn get_flag(&mut self) -> &mut u8 {
+ &mut self.codes[self.flag_position]
+ }
+
+ fn plant_flag(&mut self) {
+ self.flag_position = self.code_position;
+ self.code_position += 1;
+ }
+
+ fn consume_flag(&mut self) {
+ self.num_flags_left -= 1;
+ if self.num_flags_left == 0 {
+ self.num_flags_left = 8;
+ self.plant_flag();
+ }
+ }
+}
+
+fn compress_lz_codes(
+ huff: &HuffmanOxide,
+ output: &mut OutputBufferOxide,
+ lz_code_buf: &[u8],
+) -> Result<bool> {
+ let mut flags = 1;
+ let mut bb = BitBuffer {
+ bit_buffer: u64::from(output.bit_buffer),
+ bits_in: output.bits_in,
+ };
+
+ let mut i: usize = 0;
+ while i < lz_code_buf.len() {
+ if flags == 1 {
+ flags = u32::from(lz_code_buf[i]) | 0x100;
+ i += 1;
+ }
+
+ // The lz code was a length code
+ if flags & 1 == 1 {
+ flags >>= 1;
+
+ let sym;
+ let num_extra_bits;
+
+ let match_len = lz_code_buf[i] as usize;
+
+ let match_dist = read_u16_le(lz_code_buf, i + 1);
+
+ i += 3;
+
+ debug_assert!(huff.code_sizes[0][LEN_SYM[match_len] as usize] != 0);
+ bb.put_fast(
+ u64::from(huff.codes[0][LEN_SYM[match_len] as usize]),
+ u32::from(huff.code_sizes[0][LEN_SYM[match_len] as usize]),
+ );
+ bb.put_fast(
+ match_len as u64 & u64::from(BITMASKS[LEN_EXTRA[match_len] as usize]),
+ u32::from(LEN_EXTRA[match_len]),
+ );
+
+ if match_dist < 512 {
+ sym = SMALL_DIST_SYM[match_dist as usize] as usize;
+ num_extra_bits = SMALL_DIST_EXTRA[match_dist as usize] as usize;
+ } else {
+ sym = LARGE_DIST_SYM[(match_dist >> 8) as usize] as usize;
+ num_extra_bits = LARGE_DIST_EXTRA[(match_dist >> 8) as usize] as usize;
+ }
+
+ debug_assert!(huff.code_sizes[1][sym] != 0);
+ bb.put_fast(
+ u64::from(huff.codes[1][sym]),
+ u32::from(huff.code_sizes[1][sym]),
+ );
+ bb.put_fast(
+ u64::from(match_dist) & u64::from(BITMASKS[num_extra_bits as usize]),
+ num_extra_bits as u32,
+ );
+ } else {
+ // The lz code was a literal
+ for _ in 0..3 {
+ flags >>= 1;
+ let lit = lz_code_buf[i];
+ i += 1;
+
+ debug_assert!(huff.code_sizes[0][lit as usize] != 0);
+ bb.put_fast(
+ u64::from(huff.codes[0][lit as usize]),
+ u32::from(huff.code_sizes[0][lit as usize]),
+ );
+
+ if flags & 1 == 1 || i >= lz_code_buf.len() {
+ break;
+ }
+ }
+ }
+
+ bb.flush(output)?;
+ }
+
+ output.bits_in = 0;
+ output.bit_buffer = 0;
+ while bb.bits_in != 0 {
+ let n = cmp::min(bb.bits_in, 16);
+ output.put_bits(bb.bit_buffer as u32 & BITMASKS[n as usize], n);
+ bb.bit_buffer >>= n;
+ bb.bits_in -= n;
+ }
+
+ // Output the end of block symbol.
+ output.put_bits(
+ u32::from(huff.codes[0][256]),
+ u32::from(huff.code_sizes[0][256]),
+ );
+
+ Ok(true)
+}
+
+fn compress_block(
+ huff: &mut HuffmanOxide,
+ output: &mut OutputBufferOxide,
+ lz: &LZOxide,
+ static_block: bool,
+) -> Result<bool> {
+ if static_block {
+ huff.start_static_block(output);
+ } else {
+ huff.start_dynamic_block(output)?;
+ }
+
+ compress_lz_codes(huff, output, &lz.codes[..lz.code_position])
+}
+
+fn flush_block(
+ d: &mut CompressorOxide,
+ callback: &mut CallbackOxide,
+ flush: TDEFLFlush,
+) -> Result<i32> {
+ let mut saved_buffer;
+ {
+ let mut output = callback
+ .out
+ .new_output_buffer(&mut d.params.local_buf.b, d.params.out_buf_ofs);
+ output.bit_buffer = d.params.saved_bit_buffer;
+ output.bits_in = d.params.saved_bits_in;
+
+ let use_raw_block = (d.params.flags & TDEFL_FORCE_ALL_RAW_BLOCKS != 0)
+ && (d.dict.lookahead_pos - d.dict.code_buf_dict_pos) <= d.dict.size;
+
+ assert!(d.params.flush_remaining == 0);
+ d.params.flush_ofs = 0;
+ d.params.flush_remaining = 0;
+
+ d.lz.init_flag();
+
+ // If we are at the start of the stream, write the zlib header if requested.
+ if d.params.flags & TDEFL_WRITE_ZLIB_HEADER != 0 && d.params.block_index == 0 {
+ let header = zlib::header_from_flags(d.params.flags as u32);
+ output.put_bits(header[0].into(), 8);
+ output.put_bits(header[1].into(), 8);
+ }
+
+ // Output the block header.
+ output.put_bits((flush == TDEFLFlush::Finish) as u32, 1);
+
+ saved_buffer = output.save();
+
+ let comp_success = if !use_raw_block {
+ let use_static =
+ (d.params.flags & TDEFL_FORCE_ALL_STATIC_BLOCKS != 0) || (d.lz.total_bytes < 48);
+ compress_block(&mut d.huff, &mut output, &d.lz, use_static)?
+ } else {
+ false
+ };
+
+ // If we failed to compress anything and the output would take up more space than the output
+ // data, output a stored block instead, which has at most 5 bytes of overhead.
+ // We only use some simple heuristics for now.
+ // A stored block will have an overhead of at least 4 bytes containing the block length
+ // but usually more due to the length parameters having to start at a byte boundary and thus
+ // requiring up to 5 bytes of padding.
+ // As a static block will have an overhead of at most 1 bit per byte
+ // (as literals are either 8 or 9 bytes), a raw block will
+ // never take up less space if the number of input bytes are less than 32.
+ let expanded = (d.lz.total_bytes > 32)
+ && (output.inner_pos - saved_buffer.pos + 1 >= (d.lz.total_bytes as usize))
+ && (d.dict.lookahead_pos - d.dict.code_buf_dict_pos <= d.dict.size);
+
+ if use_raw_block || expanded {
+ output.load(saved_buffer);
+
+ // Block header.
+ output.put_bits(0, 2);
+
+ // Block length has to start on a byte boundary, s opad.
+ output.pad_to_bytes();
+
+ // Block length and ones complement of block length.
+ output.put_bits(d.lz.total_bytes & 0xFFFF, 16);
+ output.put_bits(!d.lz.total_bytes & 0xFFFF, 16);
+
+ // Write the actual bytes.
+ for i in 0..d.lz.total_bytes {
+ let pos = (d.dict.code_buf_dict_pos + i as usize) & LZ_DICT_SIZE_MASK;
+ output.put_bits(u32::from(d.dict.b.dict[pos as usize]), 8);
+ }
+ } else if !comp_success {
+ output.load(saved_buffer);
+ compress_block(&mut d.huff, &mut output, &d.lz, true)?;
+ }
+
+ if flush != TDEFLFlush::None {
+ if flush == TDEFLFlush::Finish {
+ output.pad_to_bytes();
+ if d.params.flags & TDEFL_WRITE_ZLIB_HEADER != 0 {
+ let mut adler = d.params.adler32;
+ for _ in 0..4 {
+ output.put_bits((adler >> 24) & 0xFF, 8);
+ adler <<= 8;
+ }
+ }
+ } else {
+ // Sync or Full flush.
+ // Output an empty raw block.
+ output.put_bits(0, 3);
+ output.pad_to_bytes();
+ output.put_bits(0, 16);
+ output.put_bits(0xFFFF, 16);
+ }
+ }
+
+ memset(&mut d.huff.count[0][..MAX_HUFF_SYMBOLS_0], 0);
+ memset(&mut d.huff.count[1][..MAX_HUFF_SYMBOLS_1], 0);
+
+ d.lz.code_position = 1;
+ d.lz.flag_position = 0;
+ d.lz.num_flags_left = 8;
+ d.dict.code_buf_dict_pos += d.lz.total_bytes as usize;
+ d.lz.total_bytes = 0;
+ d.params.block_index += 1;
+
+ saved_buffer = output.save();
+
+ d.params.saved_bit_buffer = saved_buffer.bit_buffer;
+ d.params.saved_bits_in = saved_buffer.bits_in;
+ }
+
+ Ok(callback.flush_output(saved_buffer, &mut d.params))
+}
+
+fn record_literal(h: &mut HuffmanOxide, lz: &mut LZOxide, lit: u8) {
+ lz.total_bytes += 1;
+ lz.write_code(lit);
+
+ *lz.get_flag() >>= 1;
+ lz.consume_flag();
+
+ h.count[0][lit as usize] += 1;
+}
+
+fn record_match(h: &mut HuffmanOxide, lz: &mut LZOxide, mut match_len: u32, mut match_dist: u32) {
+ assert!(match_len >= MIN_MATCH_LEN.into());
+ assert!(match_dist >= 1);
+ assert!(match_dist as usize <= LZ_DICT_SIZE);
+
+ lz.total_bytes += match_len;
+ match_dist -= 1;
+ match_len -= u32::from(MIN_MATCH_LEN);
+ lz.write_code(match_len as u8);
+ lz.write_code(match_dist as u8);
+ lz.write_code((match_dist >> 8) as u8);
+
+ *lz.get_flag() >>= 1;
+ *lz.get_flag() |= 0x80;
+ lz.consume_flag();
+
+ let symbol = if match_dist < 512 {
+ SMALL_DIST_SYM[match_dist as usize]
+ } else {
+ LARGE_DIST_SYM[((match_dist >> 8) & 127) as usize]
+ } as usize;
+ h.count[1][symbol] += 1;
+ h.count[0][LEN_SYM[match_len as usize] as usize] += 1;
+}
+
+fn compress_normal(d: &mut CompressorOxide, callback: &mut CallbackOxide) -> bool {
+ let mut src_pos = d.params.src_pos;
+ let in_buf = match callback.in_buf {
+ None => return true,
+ Some(in_buf) => in_buf,
+ };
+
+ let mut lookahead_size = d.dict.lookahead_size;
+ let mut lookahead_pos = d.dict.lookahead_pos;
+ let mut saved_lit = d.params.saved_lit;
+ let mut saved_match_dist = d.params.saved_match_dist;
+ let mut saved_match_len = d.params.saved_match_len;
+
+ while src_pos < in_buf.len() || (d.params.flush != TDEFLFlush::None && lookahead_size != 0) {
+ let src_buf_left = in_buf.len() - src_pos;
+ let num_bytes_to_process = cmp::min(src_buf_left, MAX_MATCH_LEN - lookahead_size as usize);
+
+ if lookahead_size + d.dict.size >= usize::from(MIN_MATCH_LEN) - 1
+ && num_bytes_to_process > 0
+ {
+ let dictb = &mut d.dict.b;
+
+ let mut dst_pos = (lookahead_pos + lookahead_size as usize) & LZ_DICT_SIZE_MASK;
+ let mut ins_pos = lookahead_pos + lookahead_size as usize - 2;
+ // Start the hash value from the first two bytes
+ let mut hash = update_hash(
+ u16::from(dictb.dict[(ins_pos & LZ_DICT_SIZE_MASK) as usize]),
+ dictb.dict[((ins_pos + 1) & LZ_DICT_SIZE_MASK) as usize],
+ );
+
+ lookahead_size += num_bytes_to_process;
+
+ for &c in &in_buf[src_pos..src_pos + num_bytes_to_process] {
+ // Add byte to input buffer.
+ dictb.dict[dst_pos as usize] = c;
+ if (dst_pos as usize) < MAX_MATCH_LEN - 1 {
+ dictb.dict[LZ_DICT_SIZE + dst_pos as usize] = c;
+ }
+
+ // Generate hash from the current byte,
+ hash = update_hash(hash, c);
+ dictb.next[(ins_pos & LZ_DICT_SIZE_MASK) as usize] = dictb.hash[hash as usize];
+ // and insert it into the hash chain.
+ dictb.hash[hash as usize] = ins_pos as u16;
+ dst_pos = (dst_pos + 1) & LZ_DICT_SIZE_MASK;
+ ins_pos += 1;
+ }
+ src_pos += num_bytes_to_process;
+ } else {
+ let dictb = &mut d.dict.b;
+ for &c in &in_buf[src_pos..src_pos + num_bytes_to_process] {
+ let dst_pos = (lookahead_pos + lookahead_size) & LZ_DICT_SIZE_MASK;
+ dictb.dict[dst_pos as usize] = c;
+ if (dst_pos as usize) < MAX_MATCH_LEN - 1 {
+ dictb.dict[LZ_DICT_SIZE + dst_pos as usize] = c;
+ }
+
+ lookahead_size += 1;
+ if lookahead_size + d.dict.size >= MIN_MATCH_LEN.into() {
+ let ins_pos = lookahead_pos + lookahead_size - 3;
+ let hash = ((u32::from(dictb.dict[(ins_pos & LZ_DICT_SIZE_MASK) as usize])
+ << (LZ_HASH_SHIFT * 2))
+ ^ ((u32::from(dictb.dict[((ins_pos + 1) & LZ_DICT_SIZE_MASK) as usize])
+ << LZ_HASH_SHIFT)
+ ^ u32::from(c)))
+ & (LZ_HASH_SIZE as u32 - 1);
+
+ dictb.next[(ins_pos & LZ_DICT_SIZE_MASK) as usize] = dictb.hash[hash as usize];
+ dictb.hash[hash as usize] = ins_pos as u16;
+ }
+ }
+
+ src_pos += num_bytes_to_process;
+ }
+
+ d.dict.size = cmp::min(LZ_DICT_SIZE - lookahead_size, d.dict.size);
+ if d.params.flush == TDEFLFlush::None && (lookahead_size as usize) < MAX_MATCH_LEN {
+ break;
+ }
+
+ let mut len_to_move = 1;
+ let mut cur_match_dist = 0;
+ let mut cur_match_len = if saved_match_len != 0 {
+ saved_match_len
+ } else {
+ u32::from(MIN_MATCH_LEN) - 1
+ };
+ let cur_pos = lookahead_pos & LZ_DICT_SIZE_MASK;
+ if d.params.flags & (TDEFL_RLE_MATCHES | TDEFL_FORCE_ALL_RAW_BLOCKS) != 0 {
+ // If TDEFL_RLE_MATCHES is set, we only look for repeating sequences of the current byte.
+ if d.dict.size != 0 && d.params.flags & TDEFL_FORCE_ALL_RAW_BLOCKS == 0 {
+ let c = d.dict.b.dict[((cur_pos.wrapping_sub(1)) & LZ_DICT_SIZE_MASK) as usize];
+ cur_match_len = d.dict.b.dict[cur_pos as usize..(cur_pos + lookahead_size) as usize]
+ .iter()
+ .take_while(|&x| *x == c)
+ .count() as u32;
+ if cur_match_len < MIN_MATCH_LEN.into() {
+ cur_match_len = 0
+ } else {
+ cur_match_dist = 1
+ }
+ }
+ } else {
+ // Try to find a match for the bytes at the current position.
+ let dist_len = d.dict.find_match(
+ lookahead_pos,
+ d.dict.size,
+ lookahead_size as u32,
+ cur_match_dist,
+ cur_match_len,
+ );
+ cur_match_dist = dist_len.0;
+ cur_match_len = dist_len.1;
+ }
+
+ let far_and_small = cur_match_len == MIN_MATCH_LEN.into() && cur_match_dist >= 8 * 1024;
+ let filter_small = d.params.flags & TDEFL_FILTER_MATCHES != 0 && cur_match_len <= 5;
+ if far_and_small || filter_small || cur_pos == cur_match_dist as usize {
+ cur_match_dist = 0;
+ cur_match_len = 0;
+ }
+
+ if saved_match_len != 0 {
+ if cur_match_len > saved_match_len {
+ record_literal(&mut d.huff, &mut d.lz, saved_lit);
+ if cur_match_len >= 128 {
+ record_match(&mut d.huff, &mut d.lz, cur_match_len, cur_match_dist);
+ saved_match_len = 0;
+ len_to_move = cur_match_len as usize;
+ } else {
+ saved_lit = d.dict.b.dict[cur_pos as usize];
+ saved_match_dist = cur_match_dist;
+ saved_match_len = cur_match_len;
+ }
+ } else {
+ record_match(&mut d.huff, &mut d.lz, saved_match_len, saved_match_dist);
+ len_to_move = (saved_match_len - 1) as usize;
+ saved_match_len = 0;
+ }
+ } else if cur_match_dist == 0 {
+ record_literal(
+ &mut d.huff,
+ &mut d.lz,
+ d.dict.b.dict[cmp::min(cur_pos as usize, d.dict.b.dict.len() - 1)],
+ );
+ } else if d.params.greedy_parsing
+ || (d.params.flags & TDEFL_RLE_MATCHES != 0)
+ || cur_match_len >= 128
+ {
+ // If we are using lazy matching, check for matches at the next byte if the current
+ // match was shorter than 128 bytes.
+ record_match(&mut d.huff, &mut d.lz, cur_match_len, cur_match_dist);
+ len_to_move = cur_match_len as usize;
+ } else {
+ saved_lit = d.dict.b.dict[cmp::min(cur_pos as usize, d.dict.b.dict.len() - 1)];
+ saved_match_dist = cur_match_dist;
+ saved_match_len = cur_match_len;
+ }
+
+ lookahead_pos += len_to_move;
+ assert!(lookahead_size >= len_to_move);
+ lookahead_size -= len_to_move;
+ d.dict.size = cmp::min(d.dict.size + len_to_move, LZ_DICT_SIZE);
+
+ let lz_buf_tight = d.lz.code_position > LZ_CODE_BUF_SIZE - 8;
+ let raw = d.params.flags & TDEFL_FORCE_ALL_RAW_BLOCKS != 0;
+ let fat = ((d.lz.code_position * 115) >> 7) >= d.lz.total_bytes as usize;
+ let fat_or_raw = (d.lz.total_bytes > 31 * 1024) && (fat || raw);
+
+ if lz_buf_tight || fat_or_raw {
+ d.params.src_pos = src_pos;
+ // These values are used in flush_block, so we need to write them back here.
+ d.dict.lookahead_size = lookahead_size;
+ d.dict.lookahead_pos = lookahead_pos;
+
+ let n = flush_block(d, callback, TDEFLFlush::None)
+ .unwrap_or(TDEFLStatus::PutBufFailed as i32);
+ if n != 0 {
+ d.params.saved_lit = saved_lit;
+ d.params.saved_match_dist = saved_match_dist;
+ d.params.saved_match_len = saved_match_len;
+ return n > 0;
+ }
+ }
+ }
+
+ d.params.src_pos = src_pos;
+ d.dict.lookahead_size = lookahead_size;
+ d.dict.lookahead_pos = lookahead_pos;
+ d.params.saved_lit = saved_lit;
+ d.params.saved_match_dist = saved_match_dist;
+ d.params.saved_match_len = saved_match_len;
+ true
+}
+
+const COMP_FAST_LOOKAHEAD_SIZE: usize = 4096;
+
+fn compress_fast(d: &mut CompressorOxide, callback: &mut CallbackOxide) -> bool {
+ let mut src_pos = d.params.src_pos;
+ let mut lookahead_size = d.dict.lookahead_size;
+ let mut lookahead_pos = d.dict.lookahead_pos;
+
+ let mut cur_pos = lookahead_pos & LZ_DICT_SIZE_MASK;
+ let in_buf = match callback.in_buf {
+ None => return true,
+ Some(in_buf) => in_buf,
+ };
+
+ debug_assert!(d.lz.code_position < LZ_CODE_BUF_SIZE - 2);
+
+ while src_pos < in_buf.len() || (d.params.flush != TDEFLFlush::None && lookahead_size > 0) {
+ let mut dst_pos = ((lookahead_pos + lookahead_size) & LZ_DICT_SIZE_MASK) as usize;
+ let mut num_bytes_to_process = cmp::min(
+ in_buf.len() - src_pos,
+ (COMP_FAST_LOOKAHEAD_SIZE - lookahead_size) as usize,
+ );
+ lookahead_size += num_bytes_to_process;
+
+ while num_bytes_to_process != 0 {
+ let n = cmp::min(LZ_DICT_SIZE - dst_pos, num_bytes_to_process);
+ d.dict.b.dict[dst_pos..dst_pos + n].copy_from_slice(&in_buf[src_pos..src_pos + n]);
+
+ if dst_pos < MAX_MATCH_LEN - 1 {
+ let m = cmp::min(n, MAX_MATCH_LEN - 1 - dst_pos);
+ d.dict.b.dict[dst_pos + LZ_DICT_SIZE..dst_pos + LZ_DICT_SIZE + m]
+ .copy_from_slice(&in_buf[src_pos..src_pos + m]);
+ }
+
+ src_pos += n;
+ dst_pos = (dst_pos + n) & LZ_DICT_SIZE_MASK as usize;
+ num_bytes_to_process -= n;
+ }
+
+ d.dict.size = cmp::min(LZ_DICT_SIZE - lookahead_size, d.dict.size);
+ if d.params.flush == TDEFLFlush::None && lookahead_size < COMP_FAST_LOOKAHEAD_SIZE {
+ break;
+ }
+
+ while lookahead_size >= 4 {
+ let mut cur_match_len = 1;
+
+ let first_trigram = d.dict.read_unaligned_u32(cur_pos) & 0xFF_FFFF;
+
+ let hash = (first_trigram ^ (first_trigram >> (24 - (LZ_HASH_BITS - 8))))
+ & LEVEL1_HASH_SIZE_MASK;
+
+ let mut probe_pos = usize::from(d.dict.b.hash[hash as usize]);
+ d.dict.b.hash[hash as usize] = lookahead_pos as u16;
+
+ let mut cur_match_dist = (lookahead_pos - probe_pos as usize) as u16;
+ if cur_match_dist as usize <= d.dict.size {
+ probe_pos &= LZ_DICT_SIZE_MASK;
+
+ let trigram = d.dict.read_unaligned_u32(probe_pos) & 0xFF_FFFF;
+
+ if first_trigram == trigram {
+ // Trigram was tested, so we can start with "+ 3" displacement.
+ let mut p = cur_pos + 3;
+ let mut q = probe_pos + 3;
+ cur_match_len = (|| {
+ for _ in 0..32 {
+ let p_data: u64 = d.dict.read_unaligned_u64(p);
+ let q_data: u64 = d.dict.read_unaligned_u64(q);
+ let xor_data = p_data ^ q_data;
+ if xor_data == 0 {
+ p += 8;
+ q += 8;
+ } else {
+ let trailing = xor_data.trailing_zeros();
+ return p as u32 - cur_pos as u32 + (trailing >> 3);
+ }
+ }
+
+ if cur_match_dist == 0 {
+ 0
+ } else {
+ MAX_MATCH_LEN as u32
+ }
+ })();
+
+ if cur_match_len < MIN_MATCH_LEN.into()
+ || (cur_match_len == MIN_MATCH_LEN.into() && cur_match_dist >= 8 * 1024)
+ {
+ let lit = first_trigram as u8;
+ cur_match_len = 1;
+ d.lz.write_code(lit);
+ *d.lz.get_flag() >>= 1;
+ d.huff.count[0][lit as usize] += 1;
+ } else {
+ // Limit the match to the length of the lookahead so we don't create a match
+ // that ends after the end of the input data.
+ cur_match_len = cmp::min(cur_match_len, lookahead_size as u32);
+ debug_assert!(cur_match_len >= MIN_MATCH_LEN.into());
+ debug_assert!(cur_match_dist >= 1);
+ debug_assert!(cur_match_dist as usize <= LZ_DICT_SIZE);
+ cur_match_dist -= 1;
+
+ d.lz.write_code((cur_match_len - u32::from(MIN_MATCH_LEN)) as u8);
+ d.lz.write_code(cur_match_dist as u8);
+ d.lz.write_code((cur_match_dist >> 8) as u8);
+
+ *d.lz.get_flag() >>= 1;
+ *d.lz.get_flag() |= 0x80;
+ if cur_match_dist < 512 {
+ d.huff.count[1][SMALL_DIST_SYM[cur_match_dist as usize] as usize] += 1;
+ } else {
+ d.huff.count[1]
+ [LARGE_DIST_SYM[(cur_match_dist >> 8) as usize] as usize] += 1;
+ }
+
+ d.huff.count[0][LEN_SYM[(cur_match_len - u32::from(MIN_MATCH_LEN)) as usize]
+ as usize] += 1;
+ }
+ } else {
+ d.lz.write_code(first_trigram as u8);
+ *d.lz.get_flag() >>= 1;
+ d.huff.count[0][first_trigram as u8 as usize] += 1;
+ }
+
+ d.lz.consume_flag();
+ d.lz.total_bytes += cur_match_len;
+ lookahead_pos += cur_match_len as usize;
+ d.dict.size = cmp::min(d.dict.size + cur_match_len as usize, LZ_DICT_SIZE);
+ cur_pos = (cur_pos + cur_match_len as usize) & LZ_DICT_SIZE_MASK;
+ lookahead_size -= cur_match_len as usize;
+
+ if d.lz.code_position > LZ_CODE_BUF_SIZE - 8 {
+ // These values are used in flush_block, so we need to write them back here.
+ d.dict.lookahead_size = lookahead_size;
+ d.dict.lookahead_pos = lookahead_pos;
+
+ let n = match flush_block(d, callback, TDEFLFlush::None) {
+ Err(_) => {
+ d.params.src_pos = src_pos;
+ d.params.prev_return_status = TDEFLStatus::PutBufFailed;
+ return false;
+ }
+ Ok(status) => status,
+ };
+ if n != 0 {
+ d.params.src_pos = src_pos;
+ return n > 0;
+ }
+ debug_assert!(d.lz.code_position < LZ_CODE_BUF_SIZE - 2);
+
+ lookahead_size = d.dict.lookahead_size;
+ lookahead_pos = d.dict.lookahead_pos;
+ }
+ }
+ }
+
+ while lookahead_size != 0 {
+ let lit = d.dict.b.dict[cur_pos as usize];
+ d.lz.total_bytes += 1;
+ d.lz.write_code(lit);
+ *d.lz.get_flag() >>= 1;
+ d.lz.consume_flag();
+
+ d.huff.count[0][lit as usize] += 1;
+ lookahead_pos += 1;
+ d.dict.size = cmp::min(d.dict.size + 1, LZ_DICT_SIZE);
+ cur_pos = (cur_pos + 1) & LZ_DICT_SIZE_MASK;
+ lookahead_size -= 1;
+
+ if d.lz.code_position > LZ_CODE_BUF_SIZE - 8 {
+ // These values are used in flush_block, so we need to write them back here.
+ d.dict.lookahead_size = lookahead_size;
+ d.dict.lookahead_pos = lookahead_pos;
+
+ let n = match flush_block(d, callback, TDEFLFlush::None) {
+ Err(_) => {
+ d.params.prev_return_status = TDEFLStatus::PutBufFailed;
+ d.params.src_pos = src_pos;
+ return false;
+ }
+ Ok(status) => status,
+ };
+ if n != 0 {
+ d.params.src_pos = src_pos;
+ return n > 0;
+ }
+
+ lookahead_size = d.dict.lookahead_size;
+ lookahead_pos = d.dict.lookahead_pos;
+ }
+ }
+ }
+
+ d.params.src_pos = src_pos;
+ d.dict.lookahead_size = lookahead_size;
+ d.dict.lookahead_pos = lookahead_pos;
+ true
+}
+
+fn flush_output_buffer(c: &mut CallbackOxide, p: &mut ParamsOxide) -> (TDEFLStatus, usize, usize) {
+ let mut res = (TDEFLStatus::Okay, p.src_pos, 0);
+ if let CallbackOut::Buf(ref mut cb) = c.out {
+ let n = cmp::min(cb.out_buf.len() - p.out_buf_ofs, p.flush_remaining as usize);
+ if n != 0 {
+ (&mut cb.out_buf[p.out_buf_ofs..p.out_buf_ofs + n])
+ .copy_from_slice(&p.local_buf.b[p.flush_ofs as usize..p.flush_ofs as usize + n]);
+ }
+ p.flush_ofs += n as u32;
+ p.flush_remaining -= n as u32;
+ p.out_buf_ofs += n;
+ res.2 = p.out_buf_ofs;
+ }
+
+ if p.finished && p.flush_remaining == 0 {
+ res.0 = TDEFLStatus::Done
+ }
+ res
+}
+
+/// Main compression function. Tries to compress as much as possible from `in_buf` and
+/// puts compressed output into `out_buf`.
+///
+/// The value of `flush` determines if the compressor should attempt to flush all output
+/// and alternatively try to finish the stream.
+///
+/// Use [`TDEFLFlush::Finish`] on the final call to signal that the stream is finishing.
+///
+/// Note that this function does not keep track of whether a flush marker has been output, so
+/// if called using [`TDEFLFlush::Sync`], the caller needs to ensure there is enough space in the
+/// output buffer if they want to avoid repeated flush markers.
+/// See #105 for details.
+///
+/// # Returns
+/// Returns a tuple containing the current status of the compressor, the current position
+/// in the input buffer and the current position in the output buffer.
+pub fn compress(
+ d: &mut CompressorOxide,
+ in_buf: &[u8],
+ out_buf: &mut [u8],
+ flush: TDEFLFlush,
+) -> (TDEFLStatus, usize, usize) {
+ compress_inner(
+ d,
+ &mut CallbackOxide::new_callback_buf(in_buf, out_buf),
+ flush,
+ )
+}
+
+/// Main compression function. Callbacks output.
+///
+/// # Returns
+/// Returns a tuple containing the current status of the compressor, the current position
+/// in the input buffer.
+///
+/// The caller is responsible for ensuring the `CallbackFunc` struct will not cause undefined
+/// behaviour.
+pub fn compress_to_output(
+ d: &mut CompressorOxide,
+ in_buf: &[u8],
+ flush: TDEFLFlush,
+ mut callback_func: impl FnMut(&[u8]) -> bool,
+) -> (TDEFLStatus, usize) {
+ let res = compress_inner(
+ d,
+ &mut CallbackOxide::new_callback_func(
+ in_buf,
+ CallbackFunc {
+ put_buf_func: &mut callback_func,
+ },
+ ),
+ flush,
+ );
+
+ (res.0, res.1)
+}
+
+fn compress_inner(
+ d: &mut CompressorOxide,
+ callback: &mut CallbackOxide,
+ flush: TDEFLFlush,
+) -> (TDEFLStatus, usize, usize) {
+ d.params.out_buf_ofs = 0;
+ d.params.src_pos = 0;
+
+ let prev_ok = d.params.prev_return_status == TDEFLStatus::Okay;
+ let flush_finish_once = d.params.flush != TDEFLFlush::Finish || flush == TDEFLFlush::Finish;
+
+ d.params.flush = flush;
+ if !prev_ok || !flush_finish_once {
+ d.params.prev_return_status = TDEFLStatus::BadParam;
+ return (d.params.prev_return_status, 0, 0);
+ }
+
+ if d.params.flush_remaining != 0 || d.params.finished {
+ let res = flush_output_buffer(callback, &mut d.params);
+ d.params.prev_return_status = res.0;
+ return res;
+ }
+
+ let one_probe = d.params.flags & MAX_PROBES_MASK as u32 == 1;
+ let greedy = d.params.flags & TDEFL_GREEDY_PARSING_FLAG != 0;
+ let filter_or_rle_or_raw = d.params.flags
+ & (TDEFL_FILTER_MATCHES | TDEFL_FORCE_ALL_RAW_BLOCKS | TDEFL_RLE_MATCHES)
+ != 0;
+
+ let compress_success = if one_probe && greedy && !filter_or_rle_or_raw {
+ compress_fast(d, callback)
+ } else {
+ compress_normal(d, callback)
+ };
+
+ if !compress_success {
+ return (
+ d.params.prev_return_status,
+ d.params.src_pos,
+ d.params.out_buf_ofs,
+ );
+ }
+
+ if let Some(in_buf) = callback.in_buf {
+ if d.params.flags & (TDEFL_WRITE_ZLIB_HEADER | TDEFL_COMPUTE_ADLER32) != 0 {
+ d.params.adler32 = update_adler32(d.params.adler32, &in_buf[..d.params.src_pos]);
+ }
+ }
+
+ let flush_none = d.params.flush == TDEFLFlush::None;
+ let in_left = callback.in_buf.map_or(0, |buf| buf.len()) - d.params.src_pos;
+ let remaining = in_left != 0 || d.params.flush_remaining != 0;
+ if !flush_none && d.dict.lookahead_size == 0 && !remaining {
+ let flush = d.params.flush;
+ match flush_block(d, callback, flush) {
+ Err(_) => {
+ d.params.prev_return_status = TDEFLStatus::PutBufFailed;
+ return (
+ d.params.prev_return_status,
+ d.params.src_pos,
+ d.params.out_buf_ofs,
+ );
+ }
+ Ok(x) if x < 0 => {
+ return (
+ d.params.prev_return_status,
+ d.params.src_pos,
+ d.params.out_buf_ofs,
+ )
+ }
+ _ => {
+ d.params.finished = d.params.flush == TDEFLFlush::Finish;
+ if d.params.flush == TDEFLFlush::Full {
+ memset(&mut d.dict.b.hash[..], 0);
+ memset(&mut d.dict.b.next[..], 0);
+ d.dict.size = 0;
+ }
+ }
+ }
+ }
+
+ let res = flush_output_buffer(callback, &mut d.params);
+ d.params.prev_return_status = res.0;
+
+ res
+}
+
+/// Create a set of compression flags using parameters used by zlib and other compressors.
+/// Mainly intended for use with transition from c libraries as it deals with raw integers.
+///
+/// # Parameters
+/// `level` determines compression level. Clamped to maximum of 10. Negative values result in
+/// `CompressionLevel::DefaultLevel`.
+/// `window_bits`: Above 0, wraps the stream in a zlib wrapper, 0 or negative for a raw deflate
+/// stream.
+/// `strategy`: Sets the strategy if this conforms to any of the values in `CompressionStrategy`.
+///
+/// # Notes
+/// This function may be removed or moved to the `miniz_oxide_c_api` in the future.
+pub fn create_comp_flags_from_zip_params(level: i32, window_bits: i32, strategy: i32) -> u32 {
+ let num_probes = (if level >= 0 {
+ cmp::min(10, level)
+ } else {
+ CompressionLevel::DefaultLevel as i32
+ }) as usize;
+ let greedy = if level <= 3 {
+ TDEFL_GREEDY_PARSING_FLAG
+ } else {
+ 0
+ };
+ let mut comp_flags = NUM_PROBES[num_probes] | greedy;
+
+ if window_bits > 0 {
+ comp_flags |= TDEFL_WRITE_ZLIB_HEADER;
+ }
+
+ if level == 0 {
+ comp_flags |= TDEFL_FORCE_ALL_RAW_BLOCKS;
+ } else if strategy == CompressionStrategy::Filtered as i32 {
+ comp_flags |= TDEFL_FILTER_MATCHES;
+ } else if strategy == CompressionStrategy::HuffmanOnly as i32 {
+ comp_flags &= !MAX_PROBES_MASK as u32;
+ } else if strategy == CompressionStrategy::Fixed as i32 {
+ comp_flags |= TDEFL_FORCE_ALL_STATIC_BLOCKS;
+ } else if strategy == CompressionStrategy::RLE as i32 {
+ comp_flags |= TDEFL_RLE_MATCHES;
+ }
+
+ comp_flags
+}
+
+#[cfg(test)]
+mod test {
+ use super::{
+ compress_to_output, create_comp_flags_from_zip_params, read_u16_le, write_u16_le,
+ CompressionStrategy, CompressorOxide, TDEFLFlush, TDEFLStatus, DEFAULT_FLAGS,
+ MZ_DEFAULT_WINDOW_BITS,
+ };
+ use crate::inflate::decompress_to_vec;
+ use alloc::vec;
+
+ #[test]
+ fn u16_to_slice() {
+ let mut slice = [0, 0];
+ write_u16_le(2000, &mut slice, 0);
+ assert_eq!(slice, [208, 7]);
+ }
+
+ #[test]
+ fn u16_from_slice() {
+ let mut slice = [208, 7];
+ assert_eq!(read_u16_le(&mut slice, 0), 2000);
+ }
+
+ #[test]
+ fn compress_output() {
+ assert_eq!(
+ DEFAULT_FLAGS,
+ create_comp_flags_from_zip_params(
+ 4,
+ MZ_DEFAULT_WINDOW_BITS,
+ CompressionStrategy::Default as i32
+ )
+ );
+
+ let slice = [
+ 1, 2, 3, 4, 1, 2, 3, 1, 2, 3, 1, 2, 6, 1, 2, 3, 1, 2, 3, 2, 3, 1, 2, 3,
+ ];
+ let mut encoded = vec![];
+ let flags = create_comp_flags_from_zip_params(6, 0, 0);
+ let mut d = CompressorOxide::new(flags);
+ let (status, in_consumed) =
+ compress_to_output(&mut d, &slice, TDEFLFlush::Finish, |out: &[u8]| {
+ encoded.extend_from_slice(out);
+ true
+ });
+
+ assert_eq!(status, TDEFLStatus::Done);
+ assert_eq!(in_consumed, slice.len());
+
+ let decoded = decompress_to_vec(&encoded[..]).unwrap();
+ assert_eq!(&decoded[..], &slice[..]);
+ }
+
+ #[test]
+ /// Check fast compress mode
+ fn compress_fast() {
+ let slice = [
+ 1, 2, 3, 4, 1, 2, 3, 1, 2, 3, 1, 2, 6, 1, 2, 3, 1, 2, 3, 2, 3, 1, 2, 3,
+ ];
+ let mut encoded = vec![];
+ let flags = create_comp_flags_from_zip_params(1, 0, 0);
+ let mut d = CompressorOxide::new(flags);
+ let (status, in_consumed) =
+ compress_to_output(&mut d, &slice, TDEFLFlush::Finish, |out: &[u8]| {
+ encoded.extend_from_slice(out);
+ true
+ });
+
+ assert_eq!(status, TDEFLStatus::Done);
+ assert_eq!(in_consumed, slice.len());
+
+ // Needs to be altered if algorithm improves.
+ assert_eq!(
+ &encoded[..],
+ [99, 100, 98, 102, 1, 98, 48, 98, 3, 147, 204, 76, 204, 140, 76, 204, 0]
+ );
+
+ let decoded = decompress_to_vec(&encoded[..]).unwrap();
+ assert_eq!(&decoded[..], &slice[..]);
+ }
+}
diff --git a/vendor/miniz_oxide-0.5.3/src/deflate/mod.rs b/vendor/miniz_oxide-0.5.3/src/deflate/mod.rs
new file mode 100644
index 000000000..471b94b9d
--- /dev/null
+++ b/vendor/miniz_oxide-0.5.3/src/deflate/mod.rs
@@ -0,0 +1,227 @@
+//! This module contains functionality for compression.
+
+use crate::alloc::vec;
+use crate::alloc::vec::Vec;
+
+mod buffer;
+pub mod core;
+pub mod stream;
+use self::core::*;
+
+/// How much processing the compressor should do to compress the data.
+/// `NoCompression` and `Bestspeed` have special meanings, the other levels determine the number
+/// of checks for matches in the hash chains and whether to use lazy or greedy parsing.
+#[repr(i32)]
+#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
+pub enum CompressionLevel {
+ /// Don't do any compression, only output uncompressed blocks.
+ NoCompression = 0,
+ /// Fast compression. Uses a special compression routine that is optimized for speed.
+ BestSpeed = 1,
+ /// Slow/high compression. Do a lot of checks to try to find good matches.
+ BestCompression = 9,
+ /// Even more checks, can be very slow.
+ UberCompression = 10,
+ /// Default compromise between speed and compression.
+ DefaultLevel = 6,
+ /// Use the default compression level.
+ DefaultCompression = -1,
+}
+
+// Missing safe rust analogue (this and mem-to-mem are quite similar)
+/*
+fn tdefl_compress(
+ d: Option<&mut CompressorOxide>,
+ in_buf: *const c_void,
+ in_size: Option<&mut usize>,
+ out_buf: *mut c_void,
+ out_size: Option<&mut usize>,
+ flush: TDEFLFlush,
+) -> TDEFLStatus {
+ let res = match d {
+ None => {
+ in_size.map(|size| *size = 0);
+ out_size.map(|size| *size = 0);
+ (TDEFLStatus::BadParam, 0, 0)
+ },
+ Some(compressor) => {
+ let callback_res = CallbackOxide::new(
+ compressor.callback_func.clone(),
+ in_buf,
+ in_size,
+ out_buf,
+ out_size,
+ );
+
+ if let Ok(mut callback) = callback_res {
+ let res = compress(compressor, &mut callback, flush);
+ callback.update_size(Some(res.1), Some(res.2));
+ res
+ } else {
+ (TDEFLStatus::BadParam, 0, 0)
+ }
+ }
+ };
+ res.0
+}*/
+
+// Missing safe rust analogue
+/*
+fn tdefl_init(
+ d: Option<&mut CompressorOxide>,
+ put_buf_func: PutBufFuncPtr,
+ put_buf_user: *mut c_void,
+ flags: c_int,
+) -> TDEFLStatus {
+ if let Some(d) = d {
+ *d = CompressorOxide::new(
+ put_buf_func.map(|func|
+ CallbackFunc { put_buf_func: func, put_buf_user: put_buf_user }
+ ),
+ flags as u32,
+ );
+ TDEFLStatus::Okay
+ } else {
+ TDEFLStatus::BadParam
+ }
+}*/
+
+// Missing safe rust analogue (though maybe best served by flate2 front-end instead)
+/*
+fn tdefl_compress_mem_to_output(
+ buf: *const c_void,
+ buf_len: usize,
+ put_buf_func: PutBufFuncPtr,
+ put_buf_user: *mut c_void,
+ flags: c_int,
+) -> bool*/
+
+// Missing safe Rust analogue
+/*
+fn tdefl_compress_mem_to_mem(
+ out_buf: *mut c_void,
+ out_buf_len: usize,
+ src_buf: *const c_void,
+ src_buf_len: usize,
+ flags: c_int,
+) -> usize*/
+
+/// Compress the input data to a vector, using the specified compression level (0-10).
+pub fn compress_to_vec(input: &[u8], level: u8) -> Vec<u8> {
+ compress_to_vec_inner(input, level, 0, 0)
+}
+
+/// Compress the input data to a vector, using the specified compression level (0-10), and with a
+/// zlib wrapper.
+pub fn compress_to_vec_zlib(input: &[u8], level: u8) -> Vec<u8> {
+ compress_to_vec_inner(input, level, 1, 0)
+}
+
+/// Simple function to compress data to a vec.
+fn compress_to_vec_inner(input: &[u8], level: u8, window_bits: i32, strategy: i32) -> Vec<u8> {
+ // The comp flags function sets the zlib flag if the window_bits parameter is > 0.
+ let flags = create_comp_flags_from_zip_params(level.into(), window_bits, strategy);
+ let mut compressor = CompressorOxide::new(flags);
+ let mut output = vec![0; ::core::cmp::max(input.len() / 2, 2)];
+
+ let mut in_pos = 0;
+ let mut out_pos = 0;
+ loop {
+ let (status, bytes_in, bytes_out) = compress(
+ &mut compressor,
+ &input[in_pos..],
+ &mut output[out_pos..],
+ TDEFLFlush::Finish,
+ );
+
+ out_pos += bytes_out;
+ in_pos += bytes_in;
+
+ match status {
+ TDEFLStatus::Done => {
+ output.truncate(out_pos);
+ break;
+ }
+ TDEFLStatus::Okay => {
+ // We need more space, so resize the vector.
+ if output.len().saturating_sub(out_pos) < 30 {
+ output.resize(output.len() * 2, 0)
+ }
+ }
+ // Not supposed to happen unless there is a bug.
+ _ => panic!("Bug! Unexpectedly failed to compress!"),
+ }
+ }
+
+ output
+}
+
+#[cfg(test)]
+mod test {
+ use super::{compress_to_vec, compress_to_vec_inner, CompressionStrategy};
+ use crate::inflate::decompress_to_vec;
+ use alloc::vec;
+
+ /// Test deflate example.
+ ///
+ /// Check if the encoder produces the same code as the example given by Mark Adler here:
+ /// https://stackoverflow.com/questions/17398931/deflate-encoding-with-static-huffman-codes/17415203
+ #[test]
+ fn compress_small() {
+ let test_data = b"Deflate late";
+ let check = [
+ 0x73, 0x49, 0x4d, 0xcb, 0x49, 0x2c, 0x49, 0x55, 0x00, 0x11, 0x00,
+ ];
+
+ let res = compress_to_vec(test_data, 1);
+ assert_eq!(&check[..], res.as_slice());
+
+ let res = compress_to_vec(test_data, 9);
+ assert_eq!(&check[..], res.as_slice());
+ }
+
+ #[test]
+ fn compress_huff_only() {
+ let test_data = b"Deflate late";
+
+ let res = compress_to_vec_inner(test_data, 1, 0, CompressionStrategy::HuffmanOnly as i32);
+ let d = decompress_to_vec(res.as_slice()).expect("Failed to decompress!");
+ assert_eq!(test_data, d.as_slice());
+ }
+
+ /// Test that a raw block compresses fine.
+ #[test]
+ fn compress_raw() {
+ let text = b"Hello, zlib!";
+ let encoded = {
+ let len = text.len();
+ let notlen = !len;
+ let mut encoded = vec![
+ 1,
+ len as u8,
+ (len >> 8) as u8,
+ notlen as u8,
+ (notlen >> 8) as u8,
+ ];
+ encoded.extend_from_slice(&text[..]);
+ encoded
+ };
+
+ let res = compress_to_vec(text, 0);
+ assert_eq!(encoded, res.as_slice());
+ }
+
+ #[test]
+ fn short() {
+ let test_data = [10, 10, 10, 10, 10, 55];
+ let c = compress_to_vec(&test_data, 9);
+
+ let d = decompress_to_vec(c.as_slice()).expect("Failed to decompress!");
+ assert_eq!(&test_data, d.as_slice());
+ // Check that a static block is used here, rather than a raw block
+ // , so the data is actually compressed.
+ // (The optimal compressed length would be 5, but neither miniz nor zlib manages that either
+ // as neither checks matches against the byte at index 0.)
+ assert!(c.len() <= 6);
+ }
+}
diff --git a/vendor/miniz_oxide-0.5.3/src/deflate/stream.rs b/vendor/miniz_oxide-0.5.3/src/deflate/stream.rs
new file mode 100644
index 000000000..39aa82d92
--- /dev/null
+++ b/vendor/miniz_oxide-0.5.3/src/deflate/stream.rs
@@ -0,0 +1,121 @@
+//! Extra streaming compression functionality.
+//!
+//! As of now this is mainly intended for use to build a higher-level wrapper.
+//!
+//! There is no DeflateState as the needed state is contained in the compressor struct itself.
+
+use crate::deflate::core::{compress, CompressorOxide, TDEFLFlush, TDEFLStatus};
+use crate::{MZError, MZFlush, MZStatus, StreamResult};
+
+/// Try to compress from input to output with the given [`CompressorOxide`].
+///
+/// # Errors
+///
+/// Returns [`MZError::Buf`] If the size of the `output` slice is empty or no progress was made due
+/// to lack of expected input data, or if called without [`MZFlush::Finish`] after the compression
+/// was already finished.
+///
+/// Returns [`MZError::Param`] if the compressor parameters are set wrong.
+///
+/// Returns [`MZError::Stream`] when lower-level decompressor returns a
+/// [`TDEFLStatus::PutBufFailed`]; may not actually be possible.
+pub fn deflate(
+ compressor: &mut CompressorOxide,
+ input: &[u8],
+ output: &mut [u8],
+ flush: MZFlush,
+) -> StreamResult {
+ if output.is_empty() {
+ return StreamResult::error(MZError::Buf);
+ }
+
+ if compressor.prev_return_status() == TDEFLStatus::Done {
+ return if flush == MZFlush::Finish {
+ StreamResult {
+ bytes_written: 0,
+ bytes_consumed: 0,
+ status: Ok(MZStatus::StreamEnd),
+ }
+ } else {
+ StreamResult::error(MZError::Buf)
+ };
+ }
+
+ let mut bytes_written = 0;
+ let mut bytes_consumed = 0;
+
+ let mut next_in = input;
+ let mut next_out = output;
+
+ let status = loop {
+ let in_bytes;
+ let out_bytes;
+ let defl_status = {
+ let res = compress(compressor, next_in, next_out, TDEFLFlush::from(flush));
+ in_bytes = res.1;
+ out_bytes = res.2;
+ res.0
+ };
+
+ next_in = &next_in[in_bytes..];
+ next_out = &mut next_out[out_bytes..];
+ bytes_consumed += in_bytes;
+ bytes_written += out_bytes;
+
+ // Check if we are done, or compression failed.
+ match defl_status {
+ TDEFLStatus::BadParam => break Err(MZError::Param),
+ // Don't think this can happen as we're not using a custom callback.
+ TDEFLStatus::PutBufFailed => break Err(MZError::Stream),
+ TDEFLStatus::Done => break Ok(MZStatus::StreamEnd),
+ _ => (),
+ };
+
+ // All the output space was used, so wait for more.
+ if next_out.is_empty() {
+ break Ok(MZStatus::Ok);
+ }
+
+ if next_in.is_empty() && (flush != MZFlush::Finish) {
+ let total_changed = bytes_written > 0 || bytes_consumed > 0;
+
+ break if (flush != MZFlush::None) || total_changed {
+ // We wrote or consumed something, and/or did a flush (sync/partial etc.).
+ Ok(MZStatus::Ok)
+ } else {
+ // No more input data, not flushing, and nothing was consumed or written,
+ // so couldn't make any progress.
+ Err(MZError::Buf)
+ };
+ }
+ };
+ StreamResult {
+ bytes_consumed,
+ bytes_written,
+ status,
+ }
+}
+
+#[cfg(test)]
+mod test {
+ use super::deflate;
+ use crate::deflate::CompressorOxide;
+ use crate::inflate::decompress_to_vec_zlib;
+ use crate::{MZFlush, MZStatus};
+ use alloc::boxed::Box;
+ use alloc::vec;
+
+ #[test]
+ fn test_state() {
+ let data = b"Hello zlib!";
+ let mut compressed = vec![0; 50];
+ let mut compressor = Box::<CompressorOxide>::default();
+ let res = deflate(&mut compressor, data, &mut compressed, MZFlush::Finish);
+ let status = res.status.expect("Failed to compress!");
+ let decomp =
+ decompress_to_vec_zlib(&compressed).expect("Failed to decompress compressed data");
+ assert_eq!(status, MZStatus::StreamEnd);
+ assert_eq!(decomp[..], data[..]);
+ assert_eq!(res.bytes_consumed, data.len());
+ }
+}
diff --git a/vendor/miniz_oxide-0.5.3/src/inflate/core.rs b/vendor/miniz_oxide-0.5.3/src/inflate/core.rs
new file mode 100644
index 000000000..38bdacbbd
--- /dev/null
+++ b/vendor/miniz_oxide-0.5.3/src/inflate/core.rs
@@ -0,0 +1,1931 @@
+//! Streaming decompression functionality.
+
+use super::*;
+use crate::shared::{update_adler32, HUFFMAN_LENGTH_ORDER};
+
+use ::core::convert::TryInto;
+use ::core::{cmp, slice};
+
+use self::output_buffer::OutputBuffer;
+
+pub const TINFL_LZ_DICT_SIZE: usize = 32_768;
+
+/// A struct containing huffman code lengths and the huffman code tree used by the decompressor.
+struct HuffmanTable {
+ /// Length of the code at each index.
+ pub code_size: [u8; MAX_HUFF_SYMBOLS_0],
+ /// Fast lookup table for shorter huffman codes.
+ ///
+ /// See `HuffmanTable::fast_lookup`.
+ pub look_up: [i16; FAST_LOOKUP_SIZE as usize],
+ /// Full huffman tree.
+ ///
+ /// Positive values are edge nodes/symbols, negative values are
+ /// parent nodes/references to other nodes.
+ pub tree: [i16; MAX_HUFF_TREE_SIZE],
+}
+
+impl HuffmanTable {
+ const fn new() -> HuffmanTable {
+ HuffmanTable {
+ code_size: [0; MAX_HUFF_SYMBOLS_0],
+ look_up: [0; FAST_LOOKUP_SIZE as usize],
+ tree: [0; MAX_HUFF_TREE_SIZE],
+ }
+ }
+
+ /// Look for a symbol in the fast lookup table.
+ /// The symbol is stored in the lower 9 bits, the length in the next 6.
+ /// If the returned value is negative, the code wasn't found in the
+ /// fast lookup table and the full tree has to be traversed to find the code.
+ #[inline]
+ fn fast_lookup(&self, bit_buf: BitBuffer) -> i16 {
+ self.look_up[(bit_buf & BitBuffer::from(FAST_LOOKUP_SIZE - 1)) as usize]
+ }
+
+ /// Get the symbol and the code length from the huffman tree.
+ #[inline]
+ fn tree_lookup(&self, fast_symbol: i32, bit_buf: BitBuffer, mut code_len: u32) -> (i32, u32) {
+ let mut symbol = fast_symbol;
+ // We step through the tree until we encounter a positive value, which indicates a
+ // symbol.
+ loop {
+ // symbol here indicates the position of the left (0) node, if the next bit is 1
+ // we add 1 to the lookup position to get the right node.
+ symbol = i32::from(self.tree[(!symbol + ((bit_buf >> code_len) & 1) as i32) as usize]);
+ code_len += 1;
+ if symbol >= 0 {
+ break;
+ }
+ }
+ (symbol, code_len)
+ }
+
+ #[inline]
+ /// Look up a symbol and code length from the bits in the provided bit buffer.
+ ///
+ /// Returns Some(symbol, length) on success,
+ /// None if the length is 0.
+ ///
+ /// It's possible we could avoid checking for 0 if we can guarantee a sane table.
+ /// TODO: Check if a smaller type for code_len helps performance.
+ fn lookup(&self, bit_buf: BitBuffer) -> Option<(i32, u32)> {
+ let symbol = self.fast_lookup(bit_buf).into();
+ if symbol >= 0 {
+ if (symbol >> 9) as u32 != 0 {
+ Some((symbol, (symbol >> 9) as u32))
+ } else {
+ // Zero-length code.
+ None
+ }
+ } else {
+ // We didn't get a symbol from the fast lookup table, so check the tree instead.
+ Some(self.tree_lookup(symbol, bit_buf, FAST_LOOKUP_BITS.into()))
+ }
+ }
+}
+
+/// The number of huffman tables used.
+const MAX_HUFF_TABLES: usize = 3;
+/// The length of the first (literal/length) huffman table.
+const MAX_HUFF_SYMBOLS_0: usize = 288;
+/// The length of the second (distance) huffman table.
+const MAX_HUFF_SYMBOLS_1: usize = 32;
+/// The length of the last (huffman code length) huffman table.
+const _MAX_HUFF_SYMBOLS_2: usize = 19;
+/// The maximum length of a code that can be looked up in the fast lookup table.
+const FAST_LOOKUP_BITS: u8 = 10;
+/// The size of the fast lookup table.
+const FAST_LOOKUP_SIZE: u32 = 1 << FAST_LOOKUP_BITS;
+const MAX_HUFF_TREE_SIZE: usize = MAX_HUFF_SYMBOLS_0 * 2;
+const LITLEN_TABLE: usize = 0;
+const DIST_TABLE: usize = 1;
+const HUFFLEN_TABLE: usize = 2;
+
+/// Flags to [`decompress()`] to control how inflation works.
+///
+/// These define bits for a bitmask argument.
+pub mod inflate_flags {
+ /// Should we try to parse a zlib header?
+ ///
+ /// If unset, [`decompress()`] will expect an RFC1951 deflate stream. If set, it will expect an
+ /// RFC1950 zlib wrapper around the deflate stream.
+ pub const TINFL_FLAG_PARSE_ZLIB_HEADER: u32 = 1;
+
+ /// There will be more input that hasn't been given to the decompressor yet.
+ ///
+ /// This is useful when you want to decompress what you have so far,
+ /// even if you know there is probably more input that hasn't gotten here yet (_e.g._, over a
+ /// network connection). When [`decompress()`][super::decompress] reaches the end of the input
+ /// without finding the end of the compressed stream, it will return
+ /// [`TINFLStatus::NeedsMoreInput`][super::TINFLStatus::NeedsMoreInput] if this is set,
+ /// indicating that you should get more data before calling again. If not set, it will return
+ /// [`TINFLStatus::FailedCannotMakeProgress`][super::TINFLStatus::FailedCannotMakeProgress]
+ /// suggesting the stream is corrupt, since you claimed it was all there.
+ pub const TINFL_FLAG_HAS_MORE_INPUT: u32 = 2;
+
+ /// The output buffer should not wrap around.
+ pub const TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF: u32 = 4;
+
+ /// Calculate the adler32 checksum of the output data even if we're not inflating a zlib stream.
+ ///
+ /// If [`TINFL_FLAG_IGNORE_ADLER32`] is specified, it will override this.
+ ///
+ /// NOTE: Enabling/disabling this between calls to decompress will result in an incorect
+ /// checksum.
+ pub const TINFL_FLAG_COMPUTE_ADLER32: u32 = 8;
+
+ /// Ignore adler32 checksum even if we are inflating a zlib stream.
+ ///
+ /// Overrides [`TINFL_FLAG_COMPUTE_ADLER32`] if both are enabled.
+ ///
+ /// NOTE: This flag does not exist in miniz as it does not support this and is a
+ /// custom addition for miniz_oxide.
+ ///
+ /// NOTE: Should not be changed from enabled to disabled after decompression has started,
+ /// this will result in checksum failure (outside the unlikely event where the checksum happens
+ /// to match anyway).
+ pub const TINFL_FLAG_IGNORE_ADLER32: u32 = 64;
+}
+
+use self::inflate_flags::*;
+
+const MIN_TABLE_SIZES: [u16; 3] = [257, 1, 4];
+
+#[cfg(target_pointer_width = "64")]
+type BitBuffer = u64;
+
+#[cfg(not(target_pointer_width = "64"))]
+type BitBuffer = u32;
+
+/// Main decompression struct.
+///
+pub struct DecompressorOxide {
+ /// Current state of the decompressor.
+ state: core::State,
+ /// Number of bits in the bit buffer.
+ num_bits: u32,
+ /// Zlib CMF
+ z_header0: u32,
+ /// Zlib FLG
+ z_header1: u32,
+ /// Adler32 checksum from the zlib header.
+ z_adler32: u32,
+ /// 1 if the current block is the last block, 0 otherwise.
+ finish: u32,
+ /// The type of the current block.
+ block_type: u32,
+ /// 1 if the adler32 value should be checked.
+ check_adler32: u32,
+ /// Last match distance.
+ dist: u32,
+ /// Variable used for match length, symbols, and a number of other things.
+ counter: u32,
+ /// Number of extra bits for the last length or distance code.
+ num_extra: u32,
+ /// Number of entries in each huffman table.
+ table_sizes: [u32; MAX_HUFF_TABLES],
+ /// Buffer of input data.
+ bit_buf: BitBuffer,
+ /// Huffman tables.
+ tables: [HuffmanTable; MAX_HUFF_TABLES],
+ /// Raw block header.
+ raw_header: [u8; 4],
+ /// Huffman length codes.
+ len_codes: [u8; MAX_HUFF_SYMBOLS_0 + MAX_HUFF_SYMBOLS_1 + 137],
+}
+
+impl DecompressorOxide {
+ /// Create a new tinfl_decompressor with all fields set to 0.
+ pub fn new() -> DecompressorOxide {
+ DecompressorOxide::default()
+ }
+
+ /// Set the current state to `Start`.
+ #[inline]
+ pub fn init(&mut self) {
+ // The rest of the data is reset or overwritten when used.
+ self.state = core::State::Start;
+ }
+
+ /// Returns the adler32 checksum of the currently decompressed data.
+ /// Note: Will return Some(1) if decompressing zlib but ignoring adler32.
+ #[inline]
+ pub fn adler32(&self) -> Option<u32> {
+ if self.state != State::Start && !self.state.is_failure() && self.z_header0 != 0 {
+ Some(self.check_adler32)
+ } else {
+ None
+ }
+ }
+
+ /// Returns the adler32 that was read from the zlib header if it exists.
+ #[inline]
+ pub fn adler32_header(&self) -> Option<u32> {
+ if self.state != State::Start && self.state != State::BadZlibHeader && self.z_header0 != 0 {
+ Some(self.z_adler32)
+ } else {
+ None
+ }
+ }
+}
+
+impl Default for DecompressorOxide {
+ /// Create a new tinfl_decompressor with all fields set to 0.
+ #[inline(always)]
+ fn default() -> Self {
+ DecompressorOxide {
+ state: core::State::Start,
+ num_bits: 0,
+ z_header0: 0,
+ z_header1: 0,
+ z_adler32: 0,
+ finish: 0,
+ block_type: 0,
+ check_adler32: 0,
+ dist: 0,
+ counter: 0,
+ num_extra: 0,
+ table_sizes: [0; MAX_HUFF_TABLES],
+ bit_buf: 0,
+ // TODO:(oyvindln) Check that copies here are optimized out in release mode.
+ tables: [
+ HuffmanTable::new(),
+ HuffmanTable::new(),
+ HuffmanTable::new(),
+ ],
+ raw_header: [0; 4],
+ len_codes: [0; MAX_HUFF_SYMBOLS_0 + MAX_HUFF_SYMBOLS_1 + 137],
+ }
+ }
+}
+
+#[derive(Copy, Clone, PartialEq, Eq, Debug)]
+enum State {
+ Start = 0,
+ ReadZlibCmf,
+ ReadZlibFlg,
+ ReadBlockHeader,
+ BlockTypeNoCompression,
+ RawHeader,
+ RawMemcpy1,
+ RawMemcpy2,
+ ReadTableSizes,
+ ReadHufflenTableCodeSize,
+ ReadLitlenDistTablesCodeSize,
+ ReadExtraBitsCodeSize,
+ DecodeLitlen,
+ WriteSymbol,
+ ReadExtraBitsLitlen,
+ DecodeDistance,
+ ReadExtraBitsDistance,
+ RawReadFirstByte,
+ RawStoreFirstByte,
+ WriteLenBytesToEnd,
+ BlockDone,
+ HuffDecodeOuterLoop1,
+ HuffDecodeOuterLoop2,
+ ReadAdler32,
+
+ DoneForever,
+
+ // Failure states.
+ BlockTypeUnexpected,
+ BadCodeSizeSum,
+ BadTotalSymbols,
+ BadZlibHeader,
+ DistanceOutOfBounds,
+ BadRawLength,
+ BadCodeSizeDistPrevLookup,
+ InvalidLitlen,
+ InvalidDist,
+ InvalidCodeLen,
+}
+
+impl State {
+ fn is_failure(self) -> bool {
+ match self {
+ BlockTypeUnexpected => true,
+ BadCodeSizeSum => true,
+ BadTotalSymbols => true,
+ BadZlibHeader => true,
+ DistanceOutOfBounds => true,
+ BadRawLength => true,
+ BadCodeSizeDistPrevLookup => true,
+ InvalidLitlen => true,
+ InvalidDist => true,
+ _ => false,
+ }
+ }
+
+ #[inline]
+ fn begin(&mut self, new_state: State) {
+ *self = new_state;
+ }
+}
+
+use self::State::*;
+
+// Not sure why miniz uses 32-bit values for these, maybe alignment/cache again?
+// # Optimization
+// We add a extra value at the end and make the tables 32 elements long
+// so we can use a mask to avoid bounds checks.
+// The invalid values are set to something high enough to avoid underflowing
+// the match length.
+/// Base length for each length code.
+///
+/// The base is used together with the value of the extra bits to decode the actual
+/// length/distance values in a match.
+#[rustfmt::skip]
+const LENGTH_BASE: [u16; 32] = [
+ 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31,
+ 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 512, 512, 512
+];
+
+/// Number of extra bits for each length code.
+#[rustfmt::skip]
+const LENGTH_EXTRA: [u8; 32] = [
+ 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2,
+ 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, 0, 0, 0
+];
+
+/// Base length for each distance code.
+#[rustfmt::skip]
+const DIST_BASE: [u16; 32] = [
+ 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33,
+ 49, 65, 97, 129, 193, 257, 385, 513, 769, 1025, 1537,
+ 2049, 3073, 4097, 6145, 8193, 12_289, 16_385, 24_577, 32_768, 32_768
+];
+
+/// Number of extra bits for each distance code.
+#[rustfmt::skip]
+const DIST_EXTRA: [u8; 32] = [
+ 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6,
+ 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, 13, 13
+];
+
+/// The mask used when indexing the base/extra arrays.
+const BASE_EXTRA_MASK: usize = 32 - 1;
+
+/// Sets the value of all the elements of the slice to `val`.
+#[inline]
+fn memset<T: Copy>(slice: &mut [T], val: T) {
+ for x in slice {
+ *x = val
+ }
+}
+
+/// Read an le u16 value from the slice iterator.
+///
+/// # Panics
+/// Panics if there are less than two bytes left.
+#[inline]
+fn read_u16_le(iter: &mut slice::Iter<u8>) -> u16 {
+ let ret = {
+ let two_bytes = iter.as_ref()[..2].try_into().unwrap();
+ u16::from_le_bytes(two_bytes)
+ };
+ iter.nth(1);
+ ret
+}
+
+/// Read an le u32 value from the slice iterator.
+///
+/// # Panics
+/// Panics if there are less than four bytes left.
+#[inline(always)]
+#[cfg(target_pointer_width = "64")]
+fn read_u32_le(iter: &mut slice::Iter<u8>) -> u32 {
+ let ret = {
+ let four_bytes: [u8; 4] = iter.as_ref()[..4].try_into().unwrap();
+ u32::from_le_bytes(four_bytes)
+ };
+ iter.nth(3);
+ ret
+}
+
+/// Ensure that there is data in the bit buffer.
+///
+/// On 64-bit platform, we use a 64-bit value so this will
+/// result in there being at least 32 bits in the bit buffer.
+/// This function assumes that there is at least 4 bytes left in the input buffer.
+#[inline(always)]
+#[cfg(target_pointer_width = "64")]
+fn fill_bit_buffer(l: &mut LocalVars, in_iter: &mut slice::Iter<u8>) {
+ // Read four bytes into the buffer at once.
+ if l.num_bits < 30 {
+ l.bit_buf |= BitBuffer::from(read_u32_le(in_iter)) << l.num_bits;
+ l.num_bits += 32;
+ }
+}
+
+/// Same as previous, but for non-64-bit platforms.
+/// Ensures at least 16 bits are present, requires at least 2 bytes in the in buffer.
+#[inline(always)]
+#[cfg(not(target_pointer_width = "64"))]
+fn fill_bit_buffer(l: &mut LocalVars, in_iter: &mut slice::Iter<u8>) {
+ // If the buffer is 32-bit wide, read 2 bytes instead.
+ if l.num_bits < 15 {
+ l.bit_buf |= BitBuffer::from(read_u16_le(in_iter)) << l.num_bits;
+ l.num_bits += 16;
+ }
+}
+
+/// Check that the zlib header is correct and that there is enough space in the buffer
+/// for the window size specified in the header.
+///
+/// See https://tools.ietf.org/html/rfc1950
+#[inline]
+fn validate_zlib_header(cmf: u32, flg: u32, flags: u32, mask: usize) -> Action {
+ let mut failed =
+ // cmf + flg should be divisible by 31.
+ (((cmf * 256) + flg) % 31 != 0) ||
+ // If this flag is set, a dictionary was used for this zlib compressed data.
+ // This is currently not supported by miniz or miniz-oxide
+ ((flg & 0b0010_0000) != 0) ||
+ // Compression method. Only 8(DEFLATE) is defined by the standard.
+ ((cmf & 15) != 8);
+
+ let window_size = 1 << ((cmf >> 4) + 8);
+ if (flags & TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF) == 0 {
+ // Bail if the buffer is wrapping and the window size is larger than the buffer.
+ failed |= (mask + 1) < window_size;
+ }
+
+ // Zlib doesn't allow window sizes above 32 * 1024.
+ failed |= window_size > 32_768;
+
+ if failed {
+ Action::Jump(BadZlibHeader)
+ } else {
+ Action::Jump(ReadBlockHeader)
+ }
+}
+
+enum Action {
+ None,
+ Jump(State),
+ End(TINFLStatus),
+}
+
+/// Try to decode the next huffman code, and puts it in the counter field of the decompressor
+/// if successful.
+///
+/// # Returns
+/// The specified action returned from `f` on success,
+/// `Action::End` if there are not enough data left to decode a symbol.
+fn decode_huffman_code<F>(
+ r: &mut DecompressorOxide,
+ l: &mut LocalVars,
+ table: usize,
+ flags: u32,
+ in_iter: &mut slice::Iter<u8>,
+ f: F,
+) -> Action
+where
+ F: FnOnce(&mut DecompressorOxide, &mut LocalVars, i32) -> Action,
+{
+ // As the huffman codes can be up to 15 bits long we need at least 15 bits
+ // ready in the bit buffer to start decoding the next huffman code.
+ if l.num_bits < 15 {
+ // First, make sure there is enough data in the bit buffer to decode a huffman code.
+ if in_iter.len() < 2 {
+ // If there is less than 2 bytes left in the input buffer, we try to look up
+ // the huffman code with what's available, and return if that doesn't succeed.
+ // Original explanation in miniz:
+ // /* TINFL_HUFF_BITBUF_FILL() is only used rarely, when the number of bytes
+ // * remaining in the input buffer falls below 2. */
+ // /* It reads just enough bytes from the input stream that are needed to decode
+ // * the next Huffman code (and absolutely no more). It works by trying to fully
+ // * decode a */
+ // /* Huffman code by using whatever bits are currently present in the bit buffer.
+ // * If this fails, it reads another byte, and tries again until it succeeds or
+ // * until the */
+ // /* bit buffer contains >=15 bits (deflate's max. Huffman code size). */
+ loop {
+ let mut temp = i32::from(r.tables[table].fast_lookup(l.bit_buf));
+
+ if temp >= 0 {
+ let code_len = (temp >> 9) as u32;
+ if (code_len != 0) && (l.num_bits >= code_len) {
+ break;
+ }
+ } else if l.num_bits > FAST_LOOKUP_BITS.into() {
+ let mut code_len = u32::from(FAST_LOOKUP_BITS);
+ loop {
+ temp = i32::from(
+ r.tables[table].tree
+ [(!temp + ((l.bit_buf >> code_len) & 1) as i32) as usize],
+ );
+ code_len += 1;
+ if temp >= 0 || l.num_bits < code_len + 1 {
+ break;
+ }
+ }
+ if temp >= 0 {
+ break;
+ }
+ }
+
+ // TODO: miniz jumps straight to here after getting here again after failing to read
+ // a byte.
+ // Doing that lets miniz avoid re-doing the lookup that that was done in the
+ // previous call.
+ let mut byte = 0;
+ if let a @ Action::End(_) = read_byte(in_iter, flags, |b| {
+ byte = b;
+ Action::None
+ }) {
+ return a;
+ };
+
+ // Do this outside closure for now to avoid borrowing r.
+ l.bit_buf |= BitBuffer::from(byte) << l.num_bits;
+ l.num_bits += 8;
+
+ if l.num_bits >= 15 {
+ break;
+ }
+ }
+ } else {
+ // There is enough data in the input buffer, so read the next two bytes
+ // and add them to the bit buffer.
+ // Unwrapping here is fine since we just checked that there are at least two
+ // bytes left.
+ l.bit_buf |= BitBuffer::from(read_u16_le(in_iter)) << l.num_bits;
+ l.num_bits += 16;
+ }
+ }
+
+ // We now have at least 15 bits in the input buffer.
+ let mut symbol = i32::from(r.tables[table].fast_lookup(l.bit_buf));
+ let code_len;
+ // If the symbol was found in the fast lookup table.
+ if symbol >= 0 {
+ // Get the length value from the top bits.
+ // As we shift down the sign bit, converting to an unsigned value
+ // shouldn't overflow.
+ code_len = (symbol >> 9) as u32;
+ // Mask out the length value.
+ symbol &= 511;
+ } else {
+ let res = r.tables[table].tree_lookup(symbol, l.bit_buf, u32::from(FAST_LOOKUP_BITS));
+ symbol = res.0;
+ code_len = res.1 as u32;
+ };
+
+ if code_len == 0 {
+ return Action::Jump(InvalidCodeLen);
+ }
+
+ l.bit_buf >>= code_len as u32;
+ l.num_bits -= code_len;
+ f(r, l, symbol)
+}
+
+/// Try to read one byte from `in_iter` and call `f` with the read byte as an argument,
+/// returning the result.
+/// If reading fails, `Action::End is returned`
+#[inline]
+fn read_byte<F>(in_iter: &mut slice::Iter<u8>, flags: u32, f: F) -> Action
+where
+ F: FnOnce(u8) -> Action,
+{
+ match in_iter.next() {
+ None => end_of_input(flags),
+ Some(&byte) => f(byte),
+ }
+}
+
+// TODO: `l: &mut LocalVars` may be slow similar to decompress_fast (even with inline(always))
+/// Try to read `amount` number of bits from `in_iter` and call the function `f` with the bits as an
+/// an argument after reading, returning the result of that function, or `Action::End` if there are
+/// not enough bytes left.
+#[inline]
+#[allow(clippy::while_immutable_condition)]
+fn read_bits<F>(
+ l: &mut LocalVars,
+ amount: u32,
+ in_iter: &mut slice::Iter<u8>,
+ flags: u32,
+ f: F,
+) -> Action
+where
+ F: FnOnce(&mut LocalVars, BitBuffer) -> Action,
+{
+ // Clippy gives a false positive warning here due to the closure.
+ // Read enough bytes from the input iterator to cover the number of bits we want.
+ while l.num_bits < amount {
+ match read_byte(in_iter, flags, |byte| {
+ l.bit_buf |= BitBuffer::from(byte) << l.num_bits;
+ l.num_bits += 8;
+ Action::None
+ }) {
+ Action::None => (),
+ // If there are not enough bytes in the input iterator, return and signal that we need
+ // more.
+ action => return action,
+ }
+ }
+
+ let bits = l.bit_buf & ((1 << amount) - 1);
+ l.bit_buf >>= amount;
+ l.num_bits -= amount;
+ f(l, bits)
+}
+
+#[inline]
+fn pad_to_bytes<F>(l: &mut LocalVars, in_iter: &mut slice::Iter<u8>, flags: u32, f: F) -> Action
+where
+ F: FnOnce(&mut LocalVars) -> Action,
+{
+ let num_bits = l.num_bits & 7;
+ read_bits(l, num_bits, in_iter, flags, |l, _| f(l))
+}
+
+#[inline]
+fn end_of_input(flags: u32) -> Action {
+ Action::End(if flags & TINFL_FLAG_HAS_MORE_INPUT != 0 {
+ TINFLStatus::NeedsMoreInput
+ } else {
+ TINFLStatus::FailedCannotMakeProgress
+ })
+}
+
+#[inline]
+fn undo_bytes(l: &mut LocalVars, max: u32) -> u32 {
+ let res = cmp::min(l.num_bits >> 3, max);
+ l.num_bits -= res << 3;
+ res
+}
+
+fn start_static_table(r: &mut DecompressorOxide) {
+ r.table_sizes[LITLEN_TABLE] = 288;
+ r.table_sizes[DIST_TABLE] = 32;
+ memset(&mut r.tables[LITLEN_TABLE].code_size[0..144], 8);
+ memset(&mut r.tables[LITLEN_TABLE].code_size[144..256], 9);
+ memset(&mut r.tables[LITLEN_TABLE].code_size[256..280], 7);
+ memset(&mut r.tables[LITLEN_TABLE].code_size[280..288], 8);
+ memset(&mut r.tables[DIST_TABLE].code_size[0..32], 5);
+}
+
+fn init_tree(r: &mut DecompressorOxide, l: &mut LocalVars) -> Action {
+ loop {
+ let table = &mut r.tables[r.block_type as usize];
+ let table_size = r.table_sizes[r.block_type as usize] as usize;
+ let mut total_symbols = [0u32; 16];
+ let mut next_code = [0u32; 17];
+ memset(&mut table.look_up[..], 0);
+ memset(&mut table.tree[..], 0);
+
+ for &code_size in &table.code_size[..table_size] {
+ total_symbols[code_size as usize] += 1;
+ }
+
+ let mut used_symbols = 0;
+ let mut total = 0;
+ for i in 1..16 {
+ used_symbols += total_symbols[i];
+ total += total_symbols[i];
+ total <<= 1;
+ next_code[i + 1] = total;
+ }
+
+ if total != 65_536 && used_symbols > 1 {
+ return Action::Jump(BadTotalSymbols);
+ }
+
+ let mut tree_next = -1;
+ for symbol_index in 0..table_size {
+ let mut rev_code = 0;
+ let code_size = table.code_size[symbol_index];
+ if code_size == 0 {
+ continue;
+ }
+
+ let mut cur_code = next_code[code_size as usize];
+ next_code[code_size as usize] += 1;
+
+ for _ in 0..code_size {
+ rev_code = (rev_code << 1) | (cur_code & 1);
+ cur_code >>= 1;
+ }
+
+ if code_size <= FAST_LOOKUP_BITS {
+ let k = (i16::from(code_size) << 9) | symbol_index as i16;
+ while rev_code < FAST_LOOKUP_SIZE {
+ table.look_up[rev_code as usize] = k;
+ rev_code += 1 << code_size;
+ }
+ continue;
+ }
+
+ let mut tree_cur = table.look_up[(rev_code & (FAST_LOOKUP_SIZE - 1)) as usize];
+ if tree_cur == 0 {
+ table.look_up[(rev_code & (FAST_LOOKUP_SIZE - 1)) as usize] = tree_next as i16;
+ tree_cur = tree_next;
+ tree_next -= 2;
+ }
+
+ rev_code >>= FAST_LOOKUP_BITS - 1;
+ for _ in FAST_LOOKUP_BITS + 1..code_size {
+ rev_code >>= 1;
+ tree_cur -= (rev_code & 1) as i16;
+ if table.tree[(-tree_cur - 1) as usize] == 0 {
+ table.tree[(-tree_cur - 1) as usize] = tree_next as i16;
+ tree_cur = tree_next;
+ tree_next -= 2;
+ } else {
+ tree_cur = table.tree[(-tree_cur - 1) as usize];
+ }
+ }
+
+ rev_code >>= 1;
+ tree_cur -= (rev_code & 1) as i16;
+ table.tree[(-tree_cur - 1) as usize] = symbol_index as i16;
+ }
+
+ if r.block_type == 2 {
+ l.counter = 0;
+ return Action::Jump(ReadLitlenDistTablesCodeSize);
+ }
+
+ if r.block_type == 0 {
+ break;
+ }
+ r.block_type -= 1;
+ }
+
+ l.counter = 0;
+ Action::Jump(DecodeLitlen)
+}
+
+// A helper macro for generating the state machine.
+//
+// As Rust doesn't have fallthrough on matches, we have to return to the match statement
+// and jump for each state change. (Which would ideally be optimized away, but often isn't.)
+macro_rules! generate_state {
+ ($state: ident, $state_machine: tt, $f: expr) => {
+ loop {
+ match $f {
+ Action::None => continue,
+ Action::Jump(new_state) => {
+ $state = new_state;
+ continue $state_machine;
+ },
+ Action::End(result) => break $state_machine result,
+ }
+ }
+ };
+}
+
+#[derive(Copy, Clone)]
+struct LocalVars {
+ pub bit_buf: BitBuffer,
+ pub num_bits: u32,
+ pub dist: u32,
+ pub counter: u32,
+ pub num_extra: u32,
+}
+
+#[inline]
+fn transfer(
+ out_slice: &mut [u8],
+ mut source_pos: usize,
+ mut out_pos: usize,
+ match_len: usize,
+ out_buf_size_mask: usize,
+) {
+ for _ in 0..match_len >> 2 {
+ out_slice[out_pos] = out_slice[source_pos & out_buf_size_mask];
+ out_slice[out_pos + 1] = out_slice[(source_pos + 1) & out_buf_size_mask];
+ out_slice[out_pos + 2] = out_slice[(source_pos + 2) & out_buf_size_mask];
+ out_slice[out_pos + 3] = out_slice[(source_pos + 3) & out_buf_size_mask];
+ source_pos += 4;
+ out_pos += 4;
+ }
+
+ match match_len & 3 {
+ 0 => (),
+ 1 => out_slice[out_pos] = out_slice[source_pos & out_buf_size_mask],
+ 2 => {
+ out_slice[out_pos] = out_slice[source_pos & out_buf_size_mask];
+ out_slice[out_pos + 1] = out_slice[(source_pos + 1) & out_buf_size_mask];
+ }
+ 3 => {
+ out_slice[out_pos] = out_slice[source_pos & out_buf_size_mask];
+ out_slice[out_pos + 1] = out_slice[(source_pos + 1) & out_buf_size_mask];
+ out_slice[out_pos + 2] = out_slice[(source_pos + 2) & out_buf_size_mask];
+ }
+ _ => unreachable!(),
+ }
+}
+
+/// Presumes that there is at least match_len bytes in output left.
+#[inline]
+fn apply_match(
+ out_slice: &mut [u8],
+ out_pos: usize,
+ dist: usize,
+ match_len: usize,
+ out_buf_size_mask: usize,
+) {
+ debug_assert!(out_pos + match_len <= out_slice.len());
+
+ let source_pos = out_pos.wrapping_sub(dist) & out_buf_size_mask;
+
+ if match_len == 3 {
+ // Fast path for match len 3.
+ out_slice[out_pos] = out_slice[source_pos];
+ out_slice[out_pos + 1] = out_slice[(source_pos + 1) & out_buf_size_mask];
+ out_slice[out_pos + 2] = out_slice[(source_pos + 2) & out_buf_size_mask];
+ return;
+ }
+
+ if cfg!(not(any(target_arch = "x86", target_arch = "x86_64"))) {
+ // We are not on x86 so copy manually.
+ transfer(out_slice, source_pos, out_pos, match_len, out_buf_size_mask);
+ return;
+ }
+
+ if source_pos >= out_pos && (source_pos - out_pos) < match_len {
+ transfer(out_slice, source_pos, out_pos, match_len, out_buf_size_mask);
+ } else if match_len <= dist && source_pos + match_len < out_slice.len() {
+ // Destination and source segments does not intersect and source does not wrap.
+ if source_pos < out_pos {
+ let (from_slice, to_slice) = out_slice.split_at_mut(out_pos);
+ to_slice[..match_len].copy_from_slice(&from_slice[source_pos..source_pos + match_len]);
+ } else {
+ let (to_slice, from_slice) = out_slice.split_at_mut(source_pos);
+ to_slice[out_pos..out_pos + match_len].copy_from_slice(&from_slice[..match_len]);
+ }
+ } else {
+ transfer(out_slice, source_pos, out_pos, match_len, out_buf_size_mask);
+ }
+}
+
+/// Fast inner decompression loop which is run while there is at least
+/// 259 bytes left in the output buffer, and at least 6 bytes left in the input buffer
+/// (The maximum one match would need + 1).
+///
+/// This was inspired by a similar optimization in zlib, which uses this info to do
+/// faster unchecked copies of multiple bytes at a time.
+/// Currently we don't do this here, but this function does avoid having to jump through the
+/// big match loop on each state change(as rust does not have fallthrough or gotos at the moment),
+/// and already improves decompression speed a fair bit.
+fn decompress_fast(
+ r: &mut DecompressorOxide,
+ in_iter: &mut slice::Iter<u8>,
+ out_buf: &mut OutputBuffer,
+ flags: u32,
+ local_vars: &mut LocalVars,
+ out_buf_size_mask: usize,
+) -> (TINFLStatus, State) {
+ // Make a local copy of the most used variables, to avoid having to update and read from values
+ // in a random memory location and to encourage more register use.
+ let mut l = *local_vars;
+ let mut state;
+
+ let status: TINFLStatus = 'o: loop {
+ state = State::DecodeLitlen;
+ loop {
+ // This function assumes that there is at least 259 bytes left in the output buffer,
+ // and that there is at least 14 bytes left in the input buffer. 14 input bytes:
+ // 15 (prev lit) + 15 (length) + 5 (length extra) + 15 (dist)
+ // + 29 + 32 (left in bit buf, including last 13 dist extra) = 111 bits < 14 bytes
+ // We need the one extra byte as we may write one length and one full match
+ // before checking again.
+ if out_buf.bytes_left() < 259 || in_iter.len() < 14 {
+ state = State::DecodeLitlen;
+ break 'o TINFLStatus::Done;
+ }
+
+ fill_bit_buffer(&mut l, in_iter);
+
+ if let Some((symbol, code_len)) = r.tables[LITLEN_TABLE].lookup(l.bit_buf) {
+ l.counter = symbol as u32;
+ l.bit_buf >>= code_len;
+ l.num_bits -= code_len;
+
+ if (l.counter & 256) != 0 {
+ // The symbol is not a literal.
+ break;
+ } else {
+ // If we have a 32-bit buffer we need to read another two bytes now
+ // to have enough bits to keep going.
+ if cfg!(not(target_pointer_width = "64")) {
+ fill_bit_buffer(&mut l, in_iter);
+ }
+
+ if let Some((symbol, code_len)) = r.tables[LITLEN_TABLE].lookup(l.bit_buf) {
+ l.bit_buf >>= code_len;
+ l.num_bits -= code_len;
+ // The previous symbol was a literal, so write it directly and check
+ // the next one.
+ out_buf.write_byte(l.counter as u8);
+ if (symbol & 256) != 0 {
+ l.counter = symbol as u32;
+ // The symbol is a length value.
+ break;
+ } else {
+ // The symbol is a literal, so write it directly and continue.
+ out_buf.write_byte(symbol as u8);
+ }
+ } else {
+ state.begin(InvalidCodeLen);
+ break 'o TINFLStatus::Failed;
+ }
+ }
+ } else {
+ state.begin(InvalidCodeLen);
+ break 'o TINFLStatus::Failed;
+ }
+ }
+
+ // Mask the top bits since they may contain length info.
+ l.counter &= 511;
+ if l.counter == 256 {
+ // We hit the end of block symbol.
+ state.begin(BlockDone);
+ break 'o TINFLStatus::Done;
+ } else if l.counter > 285 {
+ // Invalid code.
+ // We already verified earlier that the code is > 256.
+ state.begin(InvalidLitlen);
+ break 'o TINFLStatus::Failed;
+ } else {
+ // The symbol was a length code.
+ // # Optimization
+ // Mask the value to avoid bounds checks
+ // We could use get_unchecked later if can statically verify that
+ // this will never go out of bounds.
+ l.num_extra = u32::from(LENGTH_EXTRA[(l.counter - 257) as usize & BASE_EXTRA_MASK]);
+ l.counter = u32::from(LENGTH_BASE[(l.counter - 257) as usize & BASE_EXTRA_MASK]);
+ // Length and distance codes have a number of extra bits depending on
+ // the base, which together with the base gives us the exact value.
+
+ fill_bit_buffer(&mut l, in_iter);
+ if l.num_extra != 0 {
+ let extra_bits = l.bit_buf & ((1 << l.num_extra) - 1);
+ l.bit_buf >>= l.num_extra;
+ l.num_bits -= l.num_extra;
+ l.counter += extra_bits as u32;
+ }
+
+ // We found a length code, so a distance code should follow.
+
+ if cfg!(not(target_pointer_width = "64")) {
+ fill_bit_buffer(&mut l, in_iter);
+ }
+
+ if let Some((mut symbol, code_len)) = r.tables[DIST_TABLE].lookup(l.bit_buf) {
+ symbol &= 511;
+ l.bit_buf >>= code_len;
+ l.num_bits -= code_len;
+ if symbol > 29 {
+ state.begin(InvalidDist);
+ break 'o TINFLStatus::Failed;
+ }
+
+ l.num_extra = u32::from(DIST_EXTRA[symbol as usize]);
+ l.dist = u32::from(DIST_BASE[symbol as usize]);
+ } else {
+ state.begin(InvalidCodeLen);
+ break 'o TINFLStatus::Failed;
+ }
+
+ if l.num_extra != 0 {
+ fill_bit_buffer(&mut l, in_iter);
+ let extra_bits = l.bit_buf & ((1 << l.num_extra) - 1);
+ l.bit_buf >>= l.num_extra;
+ l.num_bits -= l.num_extra;
+ l.dist += extra_bits as u32;
+ }
+
+ let position = out_buf.position();
+ if l.dist as usize > out_buf.position()
+ && (flags & TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF != 0)
+ {
+ // We encountered a distance that refers a position before
+ // the start of the decoded data, so we can't continue.
+ state.begin(DistanceOutOfBounds);
+ break TINFLStatus::Failed;
+ }
+
+ apply_match(
+ out_buf.get_mut(),
+ position,
+ l.dist as usize,
+ l.counter as usize,
+ out_buf_size_mask,
+ );
+
+ out_buf.set_position(position + l.counter as usize);
+ }
+ };
+
+ *local_vars = l;
+ (status, state)
+}
+
+/// Main decompression function. Keeps decompressing data from `in_buf` until the `in_buf` is
+/// empty, `out` is full, the end of the deflate stream is hit, or there is an error in the
+/// deflate stream.
+///
+/// # Arguments
+///
+/// `r` is a [`DecompressorOxide`] struct with the state of this stream.
+///
+/// `in_buf` is a reference to the compressed data that is to be decompressed. The decompressor will
+/// start at the first byte of this buffer.
+///
+/// `out` is a reference to the buffer that will store the decompressed data, and that
+/// stores previously decompressed data if any.
+///
+/// * The offset given by `out_pos` indicates where in the output buffer slice writing should start.
+/// * If [`TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF`] is not set, the output buffer is used in a
+/// wrapping manner, and it's size is required to be a power of 2.
+/// * The decompression function normally needs access to 32KiB of the previously decompressed data
+///(or to the beginning of the decompressed data if less than 32KiB has been decompressed.)
+/// - If this data is not available, decompression may fail.
+/// - Some deflate compressors allow specifying a window size which limits match distances to
+/// less than this, or alternatively an RLE mode where matches will only refer to the previous byte
+/// and thus allows a smaller output buffer. The window size can be specified in the zlib
+/// header structure, however, the header data should not be relied on to be correct.
+///
+/// `flags` indicates settings and status to the decompression function.
+/// * The [`TINFL_FLAG_HAS_MORE_INPUT`] has to be specified if more compressed data is to be provided
+/// in a subsequent call to this function.
+/// * See the the [`inflate_flags`] module for details on other flags.
+///
+/// # Returns
+///
+/// Returns a tuple containing the status of the compressor, the number of input bytes read, and the
+/// number of bytes output to `out`.
+///
+/// This function shouldn't panic pending any bugs.
+pub fn decompress(
+ r: &mut DecompressorOxide,
+ in_buf: &[u8],
+ out: &mut [u8],
+ out_pos: usize,
+ flags: u32,
+) -> (TINFLStatus, usize, usize) {
+ let out_buf_size_mask = if flags & TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF != 0 {
+ usize::max_value()
+ } else {
+ // In the case of zero len, any attempt to write would produce HasMoreOutput,
+ // so to gracefully process the case of there really being no output,
+ // set the mask to all zeros.
+ out.len().saturating_sub(1)
+ };
+
+ // Ensure the output buffer's size is a power of 2, unless the output buffer
+ // is large enough to hold the entire output file (in which case it doesn't
+ // matter).
+ // Also make sure that the output buffer position is not past the end of the output buffer.
+ if (out_buf_size_mask.wrapping_add(1) & out_buf_size_mask) != 0 || out_pos > out.len() {
+ return (TINFLStatus::BadParam, 0, 0);
+ }
+
+ let mut in_iter = in_buf.iter();
+
+ let mut state = r.state;
+
+ let mut out_buf = OutputBuffer::from_slice_and_pos(out, out_pos);
+
+ // Make a local copy of the important variables here so we can work with them on the stack.
+ let mut l = LocalVars {
+ bit_buf: r.bit_buf,
+ num_bits: r.num_bits,
+ dist: r.dist,
+ counter: r.counter,
+ num_extra: r.num_extra,
+ };
+
+ let mut status = 'state_machine: loop {
+ match state {
+ Start => generate_state!(state, 'state_machine, {
+ l.bit_buf = 0;
+ l.num_bits = 0;
+ l.dist = 0;
+ l.counter = 0;
+ l.num_extra = 0;
+ r.z_header0 = 0;
+ r.z_header1 = 0;
+ r.z_adler32 = 1;
+ r.check_adler32 = 1;
+ if flags & TINFL_FLAG_PARSE_ZLIB_HEADER != 0 {
+ Action::Jump(State::ReadZlibCmf)
+ } else {
+ Action::Jump(State::ReadBlockHeader)
+ }
+ }),
+
+ ReadZlibCmf => generate_state!(state, 'state_machine, {
+ read_byte(&mut in_iter, flags, |cmf| {
+ r.z_header0 = u32::from(cmf);
+ Action::Jump(State::ReadZlibFlg)
+ })
+ }),
+
+ ReadZlibFlg => generate_state!(state, 'state_machine, {
+ read_byte(&mut in_iter, flags, |flg| {
+ r.z_header1 = u32::from(flg);
+ validate_zlib_header(r.z_header0, r.z_header1, flags, out_buf_size_mask)
+ })
+ }),
+
+ // Read the block header and jump to the relevant section depending on the block type.
+ ReadBlockHeader => generate_state!(state, 'state_machine, {
+ read_bits(&mut l, 3, &mut in_iter, flags, |l, bits| {
+ r.finish = (bits & 1) as u32;
+ r.block_type = (bits >> 1) as u32 & 3;
+ match r.block_type {
+ 0 => Action::Jump(BlockTypeNoCompression),
+ 1 => {
+ start_static_table(r);
+ init_tree(r, l)
+ },
+ 2 => {
+ l.counter = 0;
+ Action::Jump(ReadTableSizes)
+ },
+ 3 => Action::Jump(BlockTypeUnexpected),
+ _ => unreachable!()
+ }
+ })
+ }),
+
+ // Raw/Stored/uncompressed block.
+ BlockTypeNoCompression => generate_state!(state, 'state_machine, {
+ pad_to_bytes(&mut l, &mut in_iter, flags, |l| {
+ l.counter = 0;
+ Action::Jump(RawHeader)
+ })
+ }),
+
+ // Check that the raw block header is correct.
+ RawHeader => generate_state!(state, 'state_machine, {
+ if l.counter < 4 {
+ // Read block length and block length check.
+ if l.num_bits != 0 {
+ read_bits(&mut l, 8, &mut in_iter, flags, |l, bits| {
+ r.raw_header[l.counter as usize] = bits as u8;
+ l.counter += 1;
+ Action::None
+ })
+ } else {
+ read_byte(&mut in_iter, flags, |byte| {
+ r.raw_header[l.counter as usize] = byte;
+ l.counter += 1;
+ Action::None
+ })
+ }
+ } else {
+ // Check if the length value of a raw block is correct.
+ // The 2 first (2-byte) words in a raw header are the length and the
+ // ones complement of the length.
+ let length = u16::from(r.raw_header[0]) | (u16::from(r.raw_header[1]) << 8);
+ let check = u16::from(r.raw_header[2]) | (u16::from(r.raw_header[3]) << 8);
+ let valid = length == !check;
+ l.counter = length.into();
+
+ if !valid {
+ Action::Jump(BadRawLength)
+ } else if l.counter == 0 {
+ // Empty raw block. Sometimes used for synchronization.
+ Action::Jump(BlockDone)
+ } else if l.num_bits != 0 {
+ // There is some data in the bit buffer, so we need to write that first.
+ Action::Jump(RawReadFirstByte)
+ } else {
+ // The bit buffer is empty, so memcpy the rest of the uncompressed data from
+ // the block.
+ Action::Jump(RawMemcpy1)
+ }
+ }
+ }),
+
+ // Read the byte from the bit buffer.
+ RawReadFirstByte => generate_state!(state, 'state_machine, {
+ read_bits(&mut l, 8, &mut in_iter, flags, |l, bits| {
+ l.dist = bits as u32;
+ Action::Jump(RawStoreFirstByte)
+ })
+ }),
+
+ // Write the byte we just read to the output buffer.
+ RawStoreFirstByte => generate_state!(state, 'state_machine, {
+ if out_buf.bytes_left() == 0 {
+ Action::End(TINFLStatus::HasMoreOutput)
+ } else {
+ out_buf.write_byte(l.dist as u8);
+ l.counter -= 1;
+ if l.counter == 0 || l.num_bits == 0 {
+ Action::Jump(RawMemcpy1)
+ } else {
+ // There is still some data left in the bit buffer that needs to be output.
+ // TODO: Changed this to jump to `RawReadfirstbyte` rather than
+ // `RawStoreFirstByte` as that seemed to be the correct path, but this
+ // needs testing.
+ Action::Jump(RawReadFirstByte)
+ }
+ }
+ }),
+
+ RawMemcpy1 => generate_state!(state, 'state_machine, {
+ if l.counter == 0 {
+ Action::Jump(BlockDone)
+ } else if out_buf.bytes_left() == 0 {
+ Action::End(TINFLStatus::HasMoreOutput)
+ } else {
+ Action::Jump(RawMemcpy2)
+ }
+ }),
+
+ RawMemcpy2 => generate_state!(state, 'state_machine, {
+ if in_iter.len() > 0 {
+ // Copy as many raw bytes as possible from the input to the output using memcpy.
+ // Raw block lengths are limited to 64 * 1024, so casting through usize and u32
+ // is not an issue.
+ let space_left = out_buf.bytes_left();
+ let bytes_to_copy = cmp::min(cmp::min(
+ space_left,
+ in_iter.len()),
+ l.counter as usize
+ );
+
+ out_buf.write_slice(&in_iter.as_slice()[..bytes_to_copy]);
+
+ (&mut in_iter).nth(bytes_to_copy - 1);
+ l.counter -= bytes_to_copy as u32;
+ Action::Jump(RawMemcpy1)
+ } else {
+ end_of_input(flags)
+ }
+ }),
+
+ // Read how many huffman codes/symbols are used for each table.
+ ReadTableSizes => generate_state!(state, 'state_machine, {
+ if l.counter < 3 {
+ let num_bits = [5, 5, 4][l.counter as usize];
+ read_bits(&mut l, num_bits, &mut in_iter, flags, |l, bits| {
+ r.table_sizes[l.counter as usize] =
+ bits as u32 + u32::from(MIN_TABLE_SIZES[l.counter as usize]);
+ l.counter += 1;
+ Action::None
+ })
+ } else {
+ memset(&mut r.tables[HUFFLEN_TABLE].code_size[..], 0);
+ l.counter = 0;
+ Action::Jump(ReadHufflenTableCodeSize)
+ }
+ }),
+
+ // Read the 3-bit lengths of the huffman codes describing the huffman code lengths used
+ // to decode the lengths of the main tables.
+ ReadHufflenTableCodeSize => generate_state!(state, 'state_machine, {
+ if l.counter < r.table_sizes[HUFFLEN_TABLE] {
+ read_bits(&mut l, 3, &mut in_iter, flags, |l, bits| {
+ // These lengths are not stored in a normal ascending order, but rather one
+ // specified by the deflate specification intended to put the most used
+ // values at the front as trailing zero lengths do not have to be stored.
+ r.tables[HUFFLEN_TABLE]
+ .code_size[HUFFMAN_LENGTH_ORDER[l.counter as usize] as usize] =
+ bits as u8;
+ l.counter += 1;
+ Action::None
+ })
+ } else {
+ r.table_sizes[HUFFLEN_TABLE] = 19;
+ init_tree(r, &mut l)
+ }
+ }),
+
+ ReadLitlenDistTablesCodeSize => generate_state!(state, 'state_machine, {
+ if l.counter < r.table_sizes[LITLEN_TABLE] + r.table_sizes[DIST_TABLE] {
+ decode_huffman_code(
+ r, &mut l, HUFFLEN_TABLE,
+ flags, &mut in_iter, |r, l, symbol| {
+ l.dist = symbol as u32;
+ if l.dist < 16 {
+ r.len_codes[l.counter as usize] = l.dist as u8;
+ l.counter += 1;
+ Action::None
+ } else if l.dist == 16 && l.counter == 0 {
+ Action::Jump(BadCodeSizeDistPrevLookup)
+ } else {
+ l.num_extra = [2, 3, 7][l.dist as usize - 16];
+ Action::Jump(ReadExtraBitsCodeSize)
+ }
+ }
+ )
+ } else if l.counter != r.table_sizes[LITLEN_TABLE] + r.table_sizes[DIST_TABLE] {
+ Action::Jump(BadCodeSizeSum)
+ } else {
+ r.tables[LITLEN_TABLE].code_size[..r.table_sizes[LITLEN_TABLE] as usize]
+ .copy_from_slice(&r.len_codes[..r.table_sizes[LITLEN_TABLE] as usize]);
+
+ let dist_table_start = r.table_sizes[LITLEN_TABLE] as usize;
+ let dist_table_end = (r.table_sizes[LITLEN_TABLE] +
+ r.table_sizes[DIST_TABLE]) as usize;
+ r.tables[DIST_TABLE].code_size[..r.table_sizes[DIST_TABLE] as usize]
+ .copy_from_slice(&r.len_codes[dist_table_start..dist_table_end]);
+
+ r.block_type -= 1;
+ init_tree(r, &mut l)
+ }
+ }),
+
+ ReadExtraBitsCodeSize => generate_state!(state, 'state_machine, {
+ let num_extra = l.num_extra;
+ read_bits(&mut l, num_extra, &mut in_iter, flags, |l, mut extra_bits| {
+ // Mask to avoid a bounds check.
+ extra_bits += [3, 3, 11][(l.dist as usize - 16) & 3];
+ let val = if l.dist == 16 {
+ r.len_codes[l.counter as usize - 1]
+ } else {
+ 0
+ };
+
+ memset(
+ &mut r.len_codes[
+ l.counter as usize..l.counter as usize + extra_bits as usize
+ ],
+ val,
+ );
+ l.counter += extra_bits as u32;
+ Action::Jump(ReadLitlenDistTablesCodeSize)
+ })
+ }),
+
+ DecodeLitlen => generate_state!(state, 'state_machine, {
+ if in_iter.len() < 4 || out_buf.bytes_left() < 2 {
+ // See if we can decode a literal with the data we have left.
+ // Jumps to next state (WriteSymbol) if successful.
+ decode_huffman_code(
+ r,
+ &mut l,
+ LITLEN_TABLE,
+ flags,
+ &mut in_iter,
+ |_r, l, symbol| {
+ l.counter = symbol as u32;
+ Action::Jump(WriteSymbol)
+ },
+ )
+ } else if
+ // If there is enough space, use the fast inner decompression
+ // function.
+ out_buf.bytes_left() >= 259 &&
+ in_iter.len() >= 14
+ {
+ let (status, new_state) = decompress_fast(
+ r,
+ &mut in_iter,
+ &mut out_buf,
+ flags,
+ &mut l,
+ out_buf_size_mask,
+ );
+
+ state = new_state;
+ if status == TINFLStatus::Done {
+ Action::Jump(new_state)
+ } else {
+ Action::End(status)
+ }
+ } else {
+ fill_bit_buffer(&mut l, &mut in_iter);
+
+ if let Some((symbol, code_len)) = r.tables[LITLEN_TABLE].lookup(l.bit_buf) {
+
+ l.counter = symbol as u32;
+ l.bit_buf >>= code_len;
+ l.num_bits -= code_len;
+
+ if (l.counter & 256) != 0 {
+ // The symbol is not a literal.
+ Action::Jump(HuffDecodeOuterLoop1)
+ } else {
+ // If we have a 32-bit buffer we need to read another two bytes now
+ // to have enough bits to keep going.
+ if cfg!(not(target_pointer_width = "64")) {
+ fill_bit_buffer(&mut l, &mut in_iter);
+ }
+
+ if let Some((symbol, code_len)) = r.tables[LITLEN_TABLE].lookup(l.bit_buf) {
+
+ l.bit_buf >>= code_len;
+ l.num_bits -= code_len;
+ // The previous symbol was a literal, so write it directly and check
+ // the next one.
+ out_buf.write_byte(l.counter as u8);
+ if (symbol & 256) != 0 {
+ l.counter = symbol as u32;
+ // The symbol is a length value.
+ Action::Jump(HuffDecodeOuterLoop1)
+ } else {
+ // The symbol is a literal, so write it directly and continue.
+ out_buf.write_byte(symbol as u8);
+ Action::None
+ }
+ } else {
+ Action::Jump(InvalidCodeLen)
+ }
+ }
+ } else {
+ Action::Jump(InvalidCodeLen)
+ }
+ }
+ }),
+
+ WriteSymbol => generate_state!(state, 'state_machine, {
+ if l.counter >= 256 {
+ Action::Jump(HuffDecodeOuterLoop1)
+ } else if out_buf.bytes_left() > 0 {
+ out_buf.write_byte(l.counter as u8);
+ Action::Jump(DecodeLitlen)
+ } else {
+ Action::End(TINFLStatus::HasMoreOutput)
+ }
+ }),
+
+ HuffDecodeOuterLoop1 => generate_state!(state, 'state_machine, {
+ // Mask the top bits since they may contain length info.
+ l.counter &= 511;
+
+ if l.counter == 256 {
+ // We hit the end of block symbol.
+ Action::Jump(BlockDone)
+ } else if l.counter > 285 {
+ // Invalid code.
+ // We already verified earlier that the code is > 256.
+ Action::Jump(InvalidLitlen)
+ } else {
+ // # Optimization
+ // Mask the value to avoid bounds checks
+ // We could use get_unchecked later if can statically verify that
+ // this will never go out of bounds.
+ l.num_extra =
+ u32::from(LENGTH_EXTRA[(l.counter - 257) as usize & BASE_EXTRA_MASK]);
+ l.counter = u32::from(LENGTH_BASE[(l.counter - 257) as usize & BASE_EXTRA_MASK]);
+ // Length and distance codes have a number of extra bits depending on
+ // the base, which together with the base gives us the exact value.
+ if l.num_extra != 0 {
+ Action::Jump(ReadExtraBitsLitlen)
+ } else {
+ Action::Jump(DecodeDistance)
+ }
+ }
+ }),
+
+ ReadExtraBitsLitlen => generate_state!(state, 'state_machine, {
+ let num_extra = l.num_extra;
+ read_bits(&mut l, num_extra, &mut in_iter, flags, |l, extra_bits| {
+ l.counter += extra_bits as u32;
+ Action::Jump(DecodeDistance)
+ })
+ }),
+
+ DecodeDistance => generate_state!(state, 'state_machine, {
+ // Try to read a huffman code from the input buffer and look up what
+ // length code the decoded symbol refers to.
+ decode_huffman_code(r, &mut l, DIST_TABLE, flags, &mut in_iter, |_r, l, symbol| {
+ if symbol > 29 {
+ // Invalid distance code.
+ return Action::Jump(InvalidDist)
+ }
+ // # Optimization
+ // Mask the value to avoid bounds checks
+ // We could use get_unchecked later if can statically verify that
+ // this will never go out of bounds.
+ l.num_extra = u32::from(DIST_EXTRA[symbol as usize & BASE_EXTRA_MASK]);
+ l.dist = u32::from(DIST_BASE[symbol as usize & BASE_EXTRA_MASK]);
+ if l.num_extra != 0 {
+ // ReadEXTRA_BITS_DISTACNE
+ Action::Jump(ReadExtraBitsDistance)
+ } else {
+ Action::Jump(HuffDecodeOuterLoop2)
+ }
+ })
+ }),
+
+ ReadExtraBitsDistance => generate_state!(state, 'state_machine, {
+ let num_extra = l.num_extra;
+ read_bits(&mut l, num_extra, &mut in_iter, flags, |l, extra_bits| {
+ l.dist += extra_bits as u32;
+ Action::Jump(HuffDecodeOuterLoop2)
+ })
+ }),
+
+ HuffDecodeOuterLoop2 => generate_state!(state, 'state_machine, {
+ if l.dist as usize > out_buf.position() &&
+ (flags & TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF != 0)
+ {
+ // We encountered a distance that refers a position before
+ // the start of the decoded data, so we can't continue.
+ Action::Jump(DistanceOutOfBounds)
+ } else {
+ let out_pos = out_buf.position();
+ let source_pos = out_buf.position()
+ .wrapping_sub(l.dist as usize) & out_buf_size_mask;
+
+ let out_len = out_buf.get_ref().len() as usize;
+ let match_end_pos = out_buf.position() + l.counter as usize;
+
+ if match_end_pos > out_len ||
+ // miniz doesn't do this check here. Not sure how it makes sure
+ // that this case doesn't happen.
+ (source_pos >= out_pos && (source_pos - out_pos) < l.counter as usize)
+ {
+ // Not enough space for all of the data in the output buffer,
+ // so copy what we have space for.
+ if l.counter == 0 {
+ Action::Jump(DecodeLitlen)
+ } else {
+ Action::Jump(WriteLenBytesToEnd)
+ }
+ } else {
+ apply_match(
+ out_buf.get_mut(),
+ out_pos,
+ l.dist as usize,
+ l.counter as usize,
+ out_buf_size_mask
+ );
+ out_buf.set_position(out_pos + l.counter as usize);
+ Action::Jump(DecodeLitlen)
+ }
+ }
+ }),
+
+ WriteLenBytesToEnd => generate_state!(state, 'state_machine, {
+ if out_buf.bytes_left() > 0 {
+ let out_pos = out_buf.position();
+ let source_pos = out_buf.position()
+ .wrapping_sub(l.dist as usize) & out_buf_size_mask;
+
+
+ let len = cmp::min(out_buf.bytes_left(), l.counter as usize);
+
+ transfer(out_buf.get_mut(), source_pos, out_pos, len, out_buf_size_mask);
+
+ out_buf.set_position(out_pos + len);
+ l.counter -= len as u32;
+ if l.counter == 0 {
+ Action::Jump(DecodeLitlen)
+ } else {
+ Action::None
+ }
+ } else {
+ Action::End(TINFLStatus::HasMoreOutput)
+ }
+ }),
+
+ BlockDone => generate_state!(state, 'state_machine, {
+ // End once we've read the last block.
+ if r.finish != 0 {
+ pad_to_bytes(&mut l, &mut in_iter, flags, |_| Action::None);
+
+ let in_consumed = in_buf.len() - in_iter.len();
+ let undo = undo_bytes(&mut l, in_consumed as u32) as usize;
+ in_iter = in_buf[in_consumed - undo..].iter();
+
+ l.bit_buf &= ((1 as BitBuffer) << l.num_bits) - 1;
+ debug_assert_eq!(l.num_bits, 0);
+
+ if flags & TINFL_FLAG_PARSE_ZLIB_HEADER != 0 {
+ l.counter = 0;
+ Action::Jump(ReadAdler32)
+ } else {
+ Action::Jump(DoneForever)
+ }
+ } else {
+ Action::Jump(ReadBlockHeader)
+ }
+ }),
+
+ ReadAdler32 => generate_state!(state, 'state_machine, {
+ if l.counter < 4 {
+ if l.num_bits != 0 {
+ read_bits(&mut l, 8, &mut in_iter, flags, |l, bits| {
+ r.z_adler32 <<= 8;
+ r.z_adler32 |= bits as u32;
+ l.counter += 1;
+ Action::None
+ })
+ } else {
+ read_byte(&mut in_iter, flags, |byte| {
+ r.z_adler32 <<= 8;
+ r.z_adler32 |= u32::from(byte);
+ l.counter += 1;
+ Action::None
+ })
+ }
+ } else {
+ Action::Jump(DoneForever)
+ }
+ }),
+
+ // We are done.
+ DoneForever => break TINFLStatus::Done,
+
+ // Anything else indicates failure.
+ // BadZlibHeader | BadRawLength | BlockTypeUnexpected | DistanceOutOfBounds |
+ // BadTotalSymbols | BadCodeSizeDistPrevLookup | BadCodeSizeSum | InvalidLitlen |
+ // InvalidDist | InvalidCodeLen
+ _ => break TINFLStatus::Failed,
+ };
+ };
+
+ let in_undo = if status != TINFLStatus::NeedsMoreInput
+ && status != TINFLStatus::FailedCannotMakeProgress
+ {
+ undo_bytes(&mut l, (in_buf.len() - in_iter.len()) as u32) as usize
+ } else {
+ 0
+ };
+
+ // Make sure HasMoreOutput overrides NeedsMoreInput if the output buffer is full.
+ // (Unless the missing input is the adler32 value in which case we don't need to write anything.)
+ // TODO: May want to see if we can do this in a better way.
+ if status == TINFLStatus::NeedsMoreInput
+ && out_buf.bytes_left() == 0
+ && state != State::ReadAdler32
+ {
+ status = TINFLStatus::HasMoreOutput
+ }
+
+ r.state = state;
+ r.bit_buf = l.bit_buf;
+ r.num_bits = l.num_bits;
+ r.dist = l.dist;
+ r.counter = l.counter;
+ r.num_extra = l.num_extra;
+
+ r.bit_buf &= ((1 as BitBuffer) << r.num_bits) - 1;
+
+ // If this is a zlib stream, and update the adler32 checksum with the decompressed bytes if
+ // requested.
+ let need_adler = if (flags & TINFL_FLAG_IGNORE_ADLER32) == 0 {
+ flags & (TINFL_FLAG_PARSE_ZLIB_HEADER | TINFL_FLAG_COMPUTE_ADLER32) != 0
+ } else {
+ // If TINFL_FLAG_IGNORE_ADLER32 is enabled, ignore the checksum.
+ false
+ };
+ if need_adler && status as i32 >= 0 {
+ let out_buf_pos = out_buf.position();
+ r.check_adler32 = update_adler32(r.check_adler32, &out_buf.get_ref()[out_pos..out_buf_pos]);
+
+ // disabled so that random input from fuzzer would not be rejected early,
+ // before it has a chance to reach interesting parts of code
+ if !cfg!(fuzzing) {
+ // Once we are done, check if the checksum matches with the one provided in the zlib header.
+ if status == TINFLStatus::Done
+ && flags & TINFL_FLAG_PARSE_ZLIB_HEADER != 0
+ && r.check_adler32 != r.z_adler32
+ {
+ status = TINFLStatus::Adler32Mismatch;
+ }
+ }
+ }
+
+ (
+ status,
+ in_buf.len() - in_iter.len() - in_undo,
+ out_buf.position() - out_pos,
+ )
+}
+
+#[cfg(test)]
+mod test {
+ use super::*;
+
+ //TODO: Fix these.
+
+ fn tinfl_decompress_oxide<'i>(
+ r: &mut DecompressorOxide,
+ input_buffer: &'i [u8],
+ output_buffer: &mut [u8],
+ flags: u32,
+ ) -> (TINFLStatus, &'i [u8], usize) {
+ let (status, in_pos, out_pos) = decompress(r, input_buffer, output_buffer, 0, flags);
+ (status, &input_buffer[in_pos..], out_pos)
+ }
+
+ #[test]
+ fn decompress_zlib() {
+ let encoded = [
+ 120, 156, 243, 72, 205, 201, 201, 215, 81, 168, 202, 201, 76, 82, 4, 0, 27, 101, 4, 19,
+ ];
+ let flags = TINFL_FLAG_COMPUTE_ADLER32 | TINFL_FLAG_PARSE_ZLIB_HEADER;
+
+ let mut b = DecompressorOxide::new();
+ const LEN: usize = 32;
+ let mut b_buf = vec![0; LEN];
+
+ // This should fail with the out buffer being to small.
+ let b_status = tinfl_decompress_oxide(&mut b, &encoded[..], b_buf.as_mut_slice(), flags);
+
+ assert_eq!(b_status.0, TINFLStatus::Failed);
+
+ let flags = flags | TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF;
+
+ b = DecompressorOxide::new();
+
+ // With TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF set this should no longer fail.
+ let b_status = tinfl_decompress_oxide(&mut b, &encoded[..], b_buf.as_mut_slice(), flags);
+
+ assert_eq!(b_buf[..b_status.2], b"Hello, zlib!"[..]);
+ assert_eq!(b_status.0, TINFLStatus::Done);
+ }
+
+ #[test]
+ fn raw_block() {
+ const LEN: usize = 64;
+
+ let text = b"Hello, zlib!";
+ let encoded = {
+ let len = text.len();
+ let notlen = !len;
+ let mut encoded = vec![
+ 1,
+ len as u8,
+ (len >> 8) as u8,
+ notlen as u8,
+ (notlen >> 8) as u8,
+ ];
+ encoded.extend_from_slice(&text[..]);
+ encoded
+ };
+
+ //let flags = TINFL_FLAG_COMPUTE_ADLER32 | TINFL_FLAG_PARSE_ZLIB_HEADER |
+ let flags = TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF;
+
+ let mut b = DecompressorOxide::new();
+
+ let mut b_buf = vec![0; LEN];
+
+ let b_status = tinfl_decompress_oxide(&mut b, &encoded[..], b_buf.as_mut_slice(), flags);
+ assert_eq!(b_buf[..b_status.2], text[..]);
+ assert_eq!(b_status.0, TINFLStatus::Done);
+ }
+
+ fn masked_lookup(table: &HuffmanTable, bit_buf: BitBuffer) -> (i32, u32) {
+ let ret = table.lookup(bit_buf).unwrap();
+ (ret.0 & 511, ret.1)
+ }
+
+ #[test]
+ fn fixed_table_lookup() {
+ let mut d = DecompressorOxide::new();
+ d.block_type = 1;
+ start_static_table(&mut d);
+ let mut l = LocalVars {
+ bit_buf: d.bit_buf,
+ num_bits: d.num_bits,
+ dist: d.dist,
+ counter: d.counter,
+ num_extra: d.num_extra,
+ };
+ init_tree(&mut d, &mut l);
+ let llt = &d.tables[LITLEN_TABLE];
+ let dt = &d.tables[DIST_TABLE];
+ assert_eq!(masked_lookup(llt, 0b00001100), (0, 8));
+ assert_eq!(masked_lookup(llt, 0b00011110), (72, 8));
+ assert_eq!(masked_lookup(llt, 0b01011110), (74, 8));
+ assert_eq!(masked_lookup(llt, 0b11111101), (143, 8));
+ assert_eq!(masked_lookup(llt, 0b000010011), (144, 9));
+ assert_eq!(masked_lookup(llt, 0b111111111), (255, 9));
+ assert_eq!(masked_lookup(llt, 0b00000000), (256, 7));
+ assert_eq!(masked_lookup(llt, 0b1110100), (279, 7));
+ assert_eq!(masked_lookup(llt, 0b00000011), (280, 8));
+ assert_eq!(masked_lookup(llt, 0b11100011), (287, 8));
+
+ assert_eq!(masked_lookup(dt, 0), (0, 5));
+ assert_eq!(masked_lookup(dt, 20), (5, 5));
+ }
+
+ fn check_result(input: &[u8], expected_status: TINFLStatus, expected_state: State, zlib: bool) {
+ let mut r = DecompressorOxide::default();
+ let mut output_buf = vec![0; 1024 * 32];
+ let flags = if zlib {
+ inflate_flags::TINFL_FLAG_PARSE_ZLIB_HEADER
+ } else {
+ 0
+ } | TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF
+ | TINFL_FLAG_HAS_MORE_INPUT;
+ let (d_status, _in_bytes, _out_bytes) =
+ decompress(&mut r, input, &mut output_buf, 0, flags);
+ assert_eq!(expected_status, d_status);
+ assert_eq!(expected_state, r.state);
+ }
+
+ #[test]
+ fn bogus_input() {
+ use self::check_result as cr;
+ const F: TINFLStatus = TINFLStatus::Failed;
+ const OK: TINFLStatus = TINFLStatus::Done;
+ // Bad CM.
+ cr(&[0x77, 0x85], F, State::BadZlibHeader, true);
+ // Bad window size (but check is correct).
+ cr(&[0x88, 0x98], F, State::BadZlibHeader, true);
+ // Bad check bits.
+ cr(&[0x78, 0x98], F, State::BadZlibHeader, true);
+
+ // Too many code lengths. (From inflate library issues)
+ cr(
+ b"M\xff\xffM*\xad\xad\xad\xad\xad\xad\xad\xcd\xcd\xcdM",
+ F,
+ State::BadTotalSymbols,
+ false,
+ );
+ // Bad CLEN (also from inflate library issues)
+ cr(
+ b"\xdd\xff\xff*M\x94ffffffffff",
+ F,
+ State::BadTotalSymbols,
+ false,
+ );
+
+ // Port of inflate coverage tests from zlib-ng
+ // https://github.com/Dead2/zlib-ng/blob/develop/test/infcover.c
+ let c = |a, b, c| cr(a, b, c, false);
+
+ // Invalid uncompressed/raw block length.
+ c(&[0, 0, 0, 0, 0], F, State::BadRawLength);
+ // Ok empty uncompressed block.
+ c(&[3, 0], OK, State::DoneForever);
+ // Invalid block type.
+ c(&[6], F, State::BlockTypeUnexpected);
+ // Ok uncompressed block.
+ c(&[1, 1, 0, 0xfe, 0xff, 0], OK, State::DoneForever);
+ // Too many litlens, we handle this later than zlib, so this test won't
+ // give the same result.
+ // c(&[0xfc, 0, 0], F, State::BadTotalSymbols);
+ // Invalid set of code lengths - TODO Check if this is the correct error for this.
+ c(&[4, 0, 0xfe, 0xff], F, State::BadTotalSymbols);
+ // Invalid repeat in list of code lengths.
+ // (Try to repeat a non-existant code.)
+ c(&[4, 0, 0x24, 0x49, 0], F, State::BadCodeSizeDistPrevLookup);
+ // Missing end of block code (should we have a separate error for this?) - fails on futher input
+ // c(&[4, 0, 0x24, 0xe9, 0xff, 0x6d], F, State::BadTotalSymbols);
+ // Invalid set of literals/lengths
+ c(
+ &[
+ 4, 0x80, 0x49, 0x92, 0x24, 0x49, 0x92, 0x24, 0x71, 0xff, 0xff, 0x93, 0x11, 0,
+ ],
+ F,
+ State::BadTotalSymbols,
+ );
+ // Invalid set of distances _ needsmoreinput
+ // c(&[4, 0x80, 0x49, 0x92, 0x24, 0x49, 0x92, 0x24, 0x0f, 0xb4, 0xff, 0xff, 0xc3, 0x84], F, State::BadTotalSymbols);
+ // Invalid distance code
+ c(&[2, 0x7e, 0xff, 0xff], F, State::InvalidDist);
+
+ // Distance refers to position before the start
+ c(
+ &[0x0c, 0xc0, 0x81, 0, 0, 0, 0, 0, 0x90, 0xff, 0x6b, 0x4, 0],
+ F,
+ State::DistanceOutOfBounds,
+ );
+
+ // Trailer
+ // Bad gzip trailer checksum GZip header not handled by miniz_oxide
+ //cr(&[0x1f, 0x8b, 0x08 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0x03, 0, 0, 0, 0, 0x01], F, State::BadCRC, false)
+ // Bad gzip trailer length
+ //cr(&[0x1f, 0x8b, 0x08 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0x03, 0, 0, 0, 0, 0, 0, 0, 0, 0x01], F, State::BadCRC, false)
+ }
+
+ #[test]
+ fn empty_output_buffer_non_wrapping() {
+ let encoded = [
+ 120, 156, 243, 72, 205, 201, 201, 215, 81, 168, 202, 201, 76, 82, 4, 0, 27, 101, 4, 19,
+ ];
+ let flags = TINFL_FLAG_COMPUTE_ADLER32
+ | TINFL_FLAG_PARSE_ZLIB_HEADER
+ | TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF;
+ let mut r = DecompressorOxide::new();
+ let mut output_buf = vec![];
+ // Check that we handle an empty buffer properly and not panicking.
+ // https://github.com/Frommi/miniz_oxide/issues/23
+ let res = decompress(&mut r, &encoded, &mut output_buf, 0, flags);
+ assert_eq!(res, (TINFLStatus::HasMoreOutput, 4, 0));
+ }
+
+ #[test]
+ fn empty_output_buffer_wrapping() {
+ let encoded = [
+ 0x73, 0x49, 0x4d, 0xcb, 0x49, 0x2c, 0x49, 0x55, 0x00, 0x11, 0x00,
+ ];
+ let flags = TINFL_FLAG_COMPUTE_ADLER32;
+ let mut r = DecompressorOxide::new();
+ let mut output_buf = vec![];
+ // Check that we handle an empty buffer properly and not panicking.
+ // https://github.com/Frommi/miniz_oxide/issues/23
+ let res = decompress(&mut r, &encoded, &mut output_buf, 0, flags);
+ assert_eq!(res, (TINFLStatus::HasMoreOutput, 2, 0));
+ }
+}
diff --git a/vendor/miniz_oxide-0.5.3/src/inflate/mod.rs b/vendor/miniz_oxide-0.5.3/src/inflate/mod.rs
new file mode 100644
index 000000000..535392327
--- /dev/null
+++ b/vendor/miniz_oxide-0.5.3/src/inflate/mod.rs
@@ -0,0 +1,279 @@
+//! This module contains functionality for decompression.
+
+use crate::alloc::boxed::Box;
+use crate::alloc::vec;
+use crate::alloc::vec::Vec;
+use ::core::cmp::min;
+use ::core::usize;
+
+pub mod core;
+mod output_buffer;
+pub mod stream;
+use self::core::*;
+
+const TINFL_STATUS_FAILED_CANNOT_MAKE_PROGRESS: i32 = -4;
+const TINFL_STATUS_BAD_PARAM: i32 = -3;
+const TINFL_STATUS_ADLER32_MISMATCH: i32 = -2;
+const TINFL_STATUS_FAILED: i32 = -1;
+const TINFL_STATUS_DONE: i32 = 0;
+const TINFL_STATUS_NEEDS_MORE_INPUT: i32 = 1;
+const TINFL_STATUS_HAS_MORE_OUTPUT: i32 = 2;
+
+/// Return status codes.
+#[repr(i8)]
+#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
+pub enum TINFLStatus {
+ /// More input data was expected, but the caller indicated that there was no more data, so the
+ /// input stream is likely truncated.
+ ///
+ /// This can't happen if you have provided the
+ /// [`TINFL_FLAG_HAS_MORE_INPUT`][core::inflate_flags::TINFL_FLAG_HAS_MORE_INPUT] flag to the
+ /// decompression. By setting that flag, you indicate more input exists but is not provided,
+ /// and so reaching the end of the input data without finding the end of the compressed stream
+ /// would instead return a [`NeedsMoreInput`][Self::NeedsMoreInput] status.
+ FailedCannotMakeProgress = TINFL_STATUS_FAILED_CANNOT_MAKE_PROGRESS as i8,
+
+ /// The output buffer is an invalid size; consider the `flags` parameter.
+ BadParam = TINFL_STATUS_BAD_PARAM as i8,
+
+ /// The decompression went fine, but the adler32 checksum did not match the one
+ /// provided in the header.
+ Adler32Mismatch = TINFL_STATUS_ADLER32_MISMATCH as i8,
+
+ /// Failed to decompress due to invalid data.
+ Failed = TINFL_STATUS_FAILED as i8,
+
+ /// Finished decompression without issues.
+ ///
+ /// This indicates the end of the compressed stream has been reached.
+ Done = TINFL_STATUS_DONE as i8,
+
+ /// The decompressor needs more input data to continue decompressing.
+ ///
+ /// This occurs when there's no more consumable input, but the end of the stream hasn't been
+ /// reached, and you have supplied the
+ /// [`TINFL_FLAG_HAS_MORE_INPUT`][core::inflate_flags::TINFL_FLAG_HAS_MORE_INPUT] flag to the
+ /// decompressor. Had you not supplied that flag (which would mean you were asserting that you
+ /// believed all the data was available) you would have gotten a
+ /// [`FailedCannotMakeProcess`][Self::FailedCannotMakeProgress] instead.
+ NeedsMoreInput = TINFL_STATUS_NEEDS_MORE_INPUT as i8,
+
+ /// There is still pending data that didn't fit in the output buffer.
+ HasMoreOutput = TINFL_STATUS_HAS_MORE_OUTPUT as i8,
+}
+
+impl TINFLStatus {
+ pub fn from_i32(value: i32) -> Option<TINFLStatus> {
+ use self::TINFLStatus::*;
+ match value {
+ TINFL_STATUS_FAILED_CANNOT_MAKE_PROGRESS => Some(FailedCannotMakeProgress),
+ TINFL_STATUS_BAD_PARAM => Some(BadParam),
+ TINFL_STATUS_ADLER32_MISMATCH => Some(Adler32Mismatch),
+ TINFL_STATUS_FAILED => Some(Failed),
+ TINFL_STATUS_DONE => Some(Done),
+ TINFL_STATUS_NEEDS_MORE_INPUT => Some(NeedsMoreInput),
+ TINFL_STATUS_HAS_MORE_OUTPUT => Some(HasMoreOutput),
+ _ => None,
+ }
+ }
+}
+
+/// Decompress the deflate-encoded data in `input` to a vector.
+///
+/// Returns a tuple of the [`Vec`] of decompressed data and the [status result][TINFLStatus].
+#[inline]
+pub fn decompress_to_vec(input: &[u8]) -> Result<Vec<u8>, TINFLStatus> {
+ decompress_to_vec_inner(input, 0, usize::max_value())
+}
+
+/// Decompress the deflate-encoded data (with a zlib wrapper) in `input` to a vector.
+///
+/// Returns a tuple of the [`Vec`] of decompressed data and the [status result][TINFLStatus].
+#[inline]
+pub fn decompress_to_vec_zlib(input: &[u8]) -> Result<Vec<u8>, TINFLStatus> {
+ decompress_to_vec_inner(
+ input,
+ inflate_flags::TINFL_FLAG_PARSE_ZLIB_HEADER,
+ usize::max_value(),
+ )
+}
+
+/// Decompress the deflate-encoded data in `input` to a vector.
+/// The vector is grown to at most `max_size` bytes; if the data does not fit in that size,
+/// [`TINFLStatus::HasMoreOutput`] error is returned.
+///
+/// Returns a tuple of the [`Vec`] of decompressed data and the [status result][TINFLStatus].
+#[inline]
+pub fn decompress_to_vec_with_limit(input: &[u8], max_size: usize) -> Result<Vec<u8>, TINFLStatus> {
+ decompress_to_vec_inner(input, 0, max_size)
+}
+
+/// Decompress the deflate-encoded data (with a zlib wrapper) in `input` to a vector.
+/// The vector is grown to at most `max_size` bytes; if the data does not fit in that size,
+/// [`TINFLStatus::HasMoreOutput`] error is returned.
+///
+/// Returns a tuple of the [`Vec`] of decompressed data and the [status result][TINFLStatus].
+#[inline]
+pub fn decompress_to_vec_zlib_with_limit(
+ input: &[u8],
+ max_size: usize,
+) -> Result<Vec<u8>, TINFLStatus> {
+ decompress_to_vec_inner(input, inflate_flags::TINFL_FLAG_PARSE_ZLIB_HEADER, max_size)
+}
+
+/// Backend of various to-[`Vec`] decompressions.
+///
+/// Returns a tuple of the [`Vec`] of decompressed data and the [status result][TINFLStatus].
+fn decompress_to_vec_inner(
+ input: &[u8],
+ flags: u32,
+ max_output_size: usize,
+) -> Result<Vec<u8>, TINFLStatus> {
+ let flags = flags | inflate_flags::TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF;
+ let mut ret: Vec<u8> = vec![0; min(input.len().saturating_mul(2), max_output_size)];
+
+ let mut decomp = Box::<DecompressorOxide>::default();
+
+ let mut in_pos = 0;
+ let mut out_pos = 0;
+ loop {
+ // Wrap the whole output slice so we know we have enough of the
+ // decompressed data for matches.
+ let (status, in_consumed, out_consumed) =
+ decompress(&mut decomp, &input[in_pos..], &mut ret, out_pos, flags);
+ in_pos += in_consumed;
+ out_pos += out_consumed;
+
+ match status {
+ TINFLStatus::Done => {
+ ret.truncate(out_pos);
+ return Ok(ret);
+ }
+
+ TINFLStatus::HasMoreOutput => {
+ // We need more space, so check if we can resize the buffer and do it.
+ let new_len = ret
+ .len()
+ .checked_add(out_pos)
+ .ok_or(TINFLStatus::HasMoreOutput)?;
+ if new_len > max_output_size {
+ return Err(TINFLStatus::HasMoreOutput);
+ };
+ ret.resize(new_len, 0);
+ }
+
+ _ => return Err(status),
+ }
+ }
+}
+
+/// Decompress one or more source slices from an iterator into the output slice.
+///
+/// * On success, returns the number of bytes that were written.
+/// * On failure, returns the failure status code.
+///
+/// This will fail if the output buffer is not large enough, but in that case
+/// the output buffer will still contain the partial decompression.
+///
+/// * `out` the output buffer.
+/// * `it` the iterator of input slices.
+/// * `zlib_header` if the first slice out of the iterator is expected to have a
+/// Zlib header. Otherwise the slices are assumed to be the deflate data only.
+/// * `ignore_adler32` if the adler32 checksum should be calculated or not.
+pub fn decompress_slice_iter_to_slice<'out, 'inp>(
+ out: &'out mut [u8],
+ it: impl Iterator<Item = &'inp [u8]>,
+ zlib_header: bool,
+ ignore_adler32: bool,
+) -> Result<usize, TINFLStatus> {
+ use self::core::inflate_flags::*;
+
+ let mut it = it.peekable();
+ let r = &mut DecompressorOxide::new();
+ let mut out_pos = 0;
+ while let Some(in_buf) = it.next() {
+ let has_more = it.peek().is_some();
+ let flags = {
+ let mut f = TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF;
+ if zlib_header {
+ f |= TINFL_FLAG_PARSE_ZLIB_HEADER;
+ }
+ if ignore_adler32 {
+ f |= TINFL_FLAG_IGNORE_ADLER32;
+ }
+ if has_more {
+ f |= TINFL_FLAG_HAS_MORE_INPUT;
+ }
+ f
+ };
+ let (status, _input_read, bytes_written) = decompress(r, in_buf, out, out_pos, flags);
+ out_pos += bytes_written;
+ match status {
+ TINFLStatus::NeedsMoreInput => continue,
+ TINFLStatus::Done => return Ok(out_pos),
+ e => return Err(e),
+ }
+ }
+ // If we ran out of source slices without getting a `Done` from the
+ // decompression we can call it a failure.
+ Err(TINFLStatus::FailedCannotMakeProgress)
+}
+
+#[cfg(test)]
+mod test {
+ use super::{
+ decompress_slice_iter_to_slice, decompress_to_vec_zlib, decompress_to_vec_zlib_with_limit,
+ TINFLStatus,
+ };
+ const ENCODED: [u8; 20] = [
+ 120, 156, 243, 72, 205, 201, 201, 215, 81, 168, 202, 201, 76, 82, 4, 0, 27, 101, 4, 19,
+ ];
+
+ #[test]
+ fn decompress_vec() {
+ let res = decompress_to_vec_zlib(&ENCODED[..]).unwrap();
+ assert_eq!(res.as_slice(), &b"Hello, zlib!"[..]);
+ }
+
+ #[test]
+ fn decompress_vec_with_high_limit() {
+ let res = decompress_to_vec_zlib_with_limit(&ENCODED[..], 100_000).unwrap();
+ assert_eq!(res.as_slice(), &b"Hello, zlib!"[..]);
+ }
+
+ #[test]
+ fn fail_to_decompress_with_limit() {
+ let res = decompress_to_vec_zlib_with_limit(&ENCODED[..], 8);
+ match res {
+ Err(TINFLStatus::HasMoreOutput) => (), // expected result
+ _ => panic!("Decompression output size limit was not enforced"),
+ }
+ }
+
+ #[test]
+ fn test_decompress_slice_iter_to_slice() {
+ // one slice
+ let mut out = [0_u8; 12_usize];
+ let r =
+ decompress_slice_iter_to_slice(&mut out, Some(&ENCODED[..]).into_iter(), true, false);
+ assert_eq!(r, Ok(12));
+ assert_eq!(&out[..12], &b"Hello, zlib!"[..]);
+
+ // some chunks at a time
+ for chunk_size in 1..13 {
+ // Note: because of https://github.com/Frommi/miniz_oxide/issues/110 our
+ // out buffer needs to have +1 byte available when the chunk size cuts
+ // the adler32 data off from the last actual data.
+ let mut out = [0_u8; 12_usize + 1];
+ let r =
+ decompress_slice_iter_to_slice(&mut out, ENCODED.chunks(chunk_size), true, false);
+ assert_eq!(r, Ok(12));
+ assert_eq!(&out[..12], &b"Hello, zlib!"[..]);
+ }
+
+ // output buffer too small
+ let mut out = [0_u8; 3_usize];
+ let r = decompress_slice_iter_to_slice(&mut out, ENCODED.chunks(7), true, false);
+ assert!(r.is_err());
+ }
+}
diff --git a/vendor/miniz_oxide-0.5.3/src/inflate/output_buffer.rs b/vendor/miniz_oxide-0.5.3/src/inflate/output_buffer.rs
new file mode 100644
index 000000000..5218a807d
--- /dev/null
+++ b/vendor/miniz_oxide-0.5.3/src/inflate/output_buffer.rs
@@ -0,0 +1,60 @@
+/// A wrapper for the output slice used when decompressing.
+///
+/// Using this rather than `Cursor` lets us implement the writing methods directly on
+/// the buffer and lets us use a usize rather than u64 for the position which helps with
+/// performance on 32-bit systems.
+pub struct OutputBuffer<'a> {
+ slice: &'a mut [u8],
+ position: usize,
+}
+
+impl<'a> OutputBuffer<'a> {
+ #[inline]
+ pub fn from_slice_and_pos(slice: &'a mut [u8], position: usize) -> OutputBuffer<'a> {
+ OutputBuffer { slice, position }
+ }
+
+ #[inline]
+ pub const fn position(&self) -> usize {
+ self.position
+ }
+
+ #[inline]
+ pub fn set_position(&mut self, position: usize) {
+ self.position = position;
+ }
+
+ /// Write a byte to the current position and increment
+ ///
+ /// Assumes that there is space.
+ #[inline]
+ pub fn write_byte(&mut self, byte: u8) {
+ self.slice[self.position] = byte;
+ self.position += 1;
+ }
+
+ /// Write a slice to the current position and increment
+ ///
+ /// Assumes that there is space.
+ #[inline]
+ pub fn write_slice(&mut self, data: &[u8]) {
+ let len = data.len();
+ self.slice[self.position..self.position + len].copy_from_slice(data);
+ self.position += data.len();
+ }
+
+ #[inline]
+ pub const fn bytes_left(&self) -> usize {
+ self.slice.len() - self.position
+ }
+
+ #[inline]
+ pub const fn get_ref(&self) -> &[u8] {
+ self.slice
+ }
+
+ #[inline]
+ pub fn get_mut(&mut self) -> &mut [u8] {
+ self.slice
+ }
+}
diff --git a/vendor/miniz_oxide-0.5.3/src/inflate/stream.rs b/vendor/miniz_oxide-0.5.3/src/inflate/stream.rs
new file mode 100644
index 000000000..715747166
--- /dev/null
+++ b/vendor/miniz_oxide-0.5.3/src/inflate/stream.rs
@@ -0,0 +1,415 @@
+//! Extra streaming decompression functionality.
+//!
+//! As of now this is mainly intended for use to build a higher-level wrapper.
+use crate::alloc::boxed::Box;
+use core::{cmp, mem};
+
+use crate::inflate::core::{decompress, inflate_flags, DecompressorOxide, TINFL_LZ_DICT_SIZE};
+use crate::inflate::TINFLStatus;
+use crate::{DataFormat, MZError, MZFlush, MZResult, MZStatus, StreamResult};
+
+/// Tag that determines reset policy of [InflateState](struct.InflateState.html)
+pub trait ResetPolicy {
+ /// Performs reset
+ fn reset(&self, state: &mut InflateState);
+}
+
+/// Resets state, without performing expensive ops (e.g. zeroing buffer)
+///
+/// Note that not zeroing buffer can lead to security issues when dealing with untrusted input.
+pub struct MinReset;
+
+impl ResetPolicy for MinReset {
+ fn reset(&self, state: &mut InflateState) {
+ state.decompressor().init();
+ state.dict_ofs = 0;
+ state.dict_avail = 0;
+ state.first_call = true;
+ state.has_flushed = false;
+ state.last_status = TINFLStatus::NeedsMoreInput;
+ }
+}
+
+/// Resets state and zero memory, continuing to use the same data format.
+pub struct ZeroReset;
+
+impl ResetPolicy for ZeroReset {
+ #[inline]
+ fn reset(&self, state: &mut InflateState) {
+ MinReset.reset(state);
+ state.dict = [0; TINFL_LZ_DICT_SIZE];
+ }
+}
+
+/// Full reset of the state, including zeroing memory.
+///
+/// Requires to provide new data format.
+pub struct FullReset(pub DataFormat);
+
+impl ResetPolicy for FullReset {
+ #[inline]
+ fn reset(&self, state: &mut InflateState) {
+ ZeroReset.reset(state);
+ state.data_format = self.0;
+ }
+}
+
+/// A struct that compbines a decompressor with extra data for streaming decompression.
+///
+pub struct InflateState {
+ /// Inner decompressor struct
+ decomp: DecompressorOxide,
+
+ /// Buffer of input bytes for matches.
+ /// TODO: Could probably do this a bit cleaner with some
+ /// Cursor-like class.
+ /// We may also look into whether we need to keep a buffer here, or just one in the
+ /// decompressor struct.
+ dict: [u8; TINFL_LZ_DICT_SIZE],
+ /// Where in the buffer are we currently at?
+ dict_ofs: usize,
+ /// How many bytes of data to be flushed is there currently in the buffer?
+ dict_avail: usize,
+
+ first_call: bool,
+ has_flushed: bool,
+
+ /// Whether the input data is wrapped in a zlib header and checksum.
+ /// TODO: This should be stored in the decompressor.
+ data_format: DataFormat,
+ last_status: TINFLStatus,
+}
+
+impl Default for InflateState {
+ fn default() -> Self {
+ InflateState {
+ decomp: DecompressorOxide::default(),
+ dict: [0; TINFL_LZ_DICT_SIZE],
+ dict_ofs: 0,
+ dict_avail: 0,
+ first_call: true,
+ has_flushed: false,
+ data_format: DataFormat::Raw,
+ last_status: TINFLStatus::NeedsMoreInput,
+ }
+ }
+}
+impl InflateState {
+ /// Create a new state.
+ ///
+ /// Note that this struct is quite large due to internal buffers, and as such storing it on
+ /// the stack is not recommended.
+ ///
+ /// # Parameters
+ /// `data_format`: Determines whether the compressed data is assumed to wrapped with zlib
+ /// metadata.
+ pub fn new(data_format: DataFormat) -> InflateState {
+ InflateState {
+ data_format,
+ ..Default::default()
+ }
+ }
+
+ /// Create a new state on the heap.
+ ///
+ /// # Parameters
+ /// `data_format`: Determines whether the compressed data is assumed to wrapped with zlib
+ /// metadata.
+ pub fn new_boxed(data_format: DataFormat) -> Box<InflateState> {
+ let mut b: Box<InflateState> = Box::default();
+ b.data_format = data_format;
+ b
+ }
+
+ /// Access the innner decompressor.
+ pub fn decompressor(&mut self) -> &mut DecompressorOxide {
+ &mut self.decomp
+ }
+
+ /// Return the status of the last call to `inflate` with this `InflateState`.
+ pub const fn last_status(&self) -> TINFLStatus {
+ self.last_status
+ }
+
+ /// Create a new state using miniz/zlib style window bits parameter.
+ ///
+ /// The decompressor does not support different window sizes. As such,
+ /// any positive (>0) value will set the zlib header flag, while a negative one
+ /// will not.
+ pub fn new_boxed_with_window_bits(window_bits: i32) -> Box<InflateState> {
+ let mut b: Box<InflateState> = Box::default();
+ b.data_format = DataFormat::from_window_bits(window_bits);
+ b
+ }
+
+ #[inline]
+ /// Reset the decompressor without re-allocating memory, using the given
+ /// data format.
+ pub fn reset(&mut self, data_format: DataFormat) {
+ self.reset_as(FullReset(data_format));
+ }
+
+ #[inline]
+ /// Resets the state according to specified policy.
+ pub fn reset_as<T: ResetPolicy>(&mut self, policy: T) {
+ policy.reset(self)
+ }
+}
+
+/// Try to decompress from `input` to `output` with the given [`InflateState`]
+///
+/// # `flush`
+///
+/// Generally, the various [`MZFlush`] flags have meaning only on the compression side. They can be
+/// supplied here, but the only one that has any semantic meaning is [`MZFlush::Finish`], which is a
+/// signal that the stream is expected to finish, and failing to do so is an error. It isn't
+/// necessary to specify it when the stream ends; you'll still get returned a
+/// [`MZStatus::StreamEnd`] anyway. Other values either have no effect or cause errors. It's
+/// likely that you'll almost always just want to use [`MZFlush::None`].
+///
+/// # Errors
+///
+/// Returns [`MZError::Buf`] if the size of the `output` slice is empty or no progress was made due
+/// to lack of expected input data, or if called with [`MZFlush::Finish`] and input wasn't all
+/// consumed.
+///
+/// Returns [`MZError::Data`] if this or a a previous call failed with an error return from
+/// [`TINFLStatus`]; probably indicates corrupted data.
+///
+/// Returns [`MZError::Stream`] when called with [`MZFlush::Full`] (meaningless on
+/// decompression), or when called without [`MZFlush::Finish`] after an earlier call with
+/// [`MZFlush::Finish`] has been made.
+pub fn inflate(
+ state: &mut InflateState,
+ input: &[u8],
+ output: &mut [u8],
+ flush: MZFlush,
+) -> StreamResult {
+ let mut bytes_consumed = 0;
+ let mut bytes_written = 0;
+ let mut next_in = input;
+ let mut next_out = output;
+
+ if flush == MZFlush::Full {
+ return StreamResult::error(MZError::Stream);
+ }
+
+ let mut decomp_flags = if state.data_format == DataFormat::Zlib {
+ inflate_flags::TINFL_FLAG_COMPUTE_ADLER32
+ } else {
+ inflate_flags::TINFL_FLAG_IGNORE_ADLER32
+ };
+
+ if (state.data_format == DataFormat::Zlib)
+ | (state.data_format == DataFormat::ZLibIgnoreChecksum)
+ {
+ decomp_flags |= inflate_flags::TINFL_FLAG_PARSE_ZLIB_HEADER;
+ }
+
+ let first_call = state.first_call;
+ state.first_call = false;
+ if (state.last_status as i32) < 0 {
+ return StreamResult::error(MZError::Data);
+ }
+
+ if state.has_flushed && (flush != MZFlush::Finish) {
+ return StreamResult::error(MZError::Stream);
+ }
+ state.has_flushed |= flush == MZFlush::Finish;
+
+ if (flush == MZFlush::Finish) && first_call {
+ decomp_flags |= inflate_flags::TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF;
+
+ let status = decompress(&mut state.decomp, next_in, next_out, 0, decomp_flags);
+ let in_bytes = status.1;
+ let out_bytes = status.2;
+ let status = status.0;
+
+ state.last_status = status;
+
+ bytes_consumed += in_bytes;
+ bytes_written += out_bytes;
+
+ let ret_status = {
+ if (status as i32) < 0 {
+ Err(MZError::Data)
+ } else if status != TINFLStatus::Done {
+ state.last_status = TINFLStatus::Failed;
+ Err(MZError::Buf)
+ } else {
+ Ok(MZStatus::StreamEnd)
+ }
+ };
+ return StreamResult {
+ bytes_consumed,
+ bytes_written,
+ status: ret_status,
+ };
+ }
+
+ if flush != MZFlush::Finish {
+ decomp_flags |= inflate_flags::TINFL_FLAG_HAS_MORE_INPUT;
+ }
+
+ if state.dict_avail != 0 {
+ bytes_written += push_dict_out(state, &mut next_out);
+ return StreamResult {
+ bytes_consumed,
+ bytes_written,
+ status: Ok(
+ if (state.last_status == TINFLStatus::Done) && (state.dict_avail == 0) {
+ MZStatus::StreamEnd
+ } else {
+ MZStatus::Ok
+ },
+ ),
+ };
+ }
+
+ let status = inflate_loop(
+ state,
+ &mut next_in,
+ &mut next_out,
+ &mut bytes_consumed,
+ &mut bytes_written,
+ decomp_flags,
+ flush,
+ );
+ StreamResult {
+ bytes_consumed,
+ bytes_written,
+ status,
+ }
+}
+
+fn inflate_loop(
+ state: &mut InflateState,
+ next_in: &mut &[u8],
+ next_out: &mut &mut [u8],
+ total_in: &mut usize,
+ total_out: &mut usize,
+ decomp_flags: u32,
+ flush: MZFlush,
+) -> MZResult {
+ let orig_in_len = next_in.len();
+ loop {
+ let status = decompress(
+ &mut state.decomp,
+ *next_in,
+ &mut state.dict,
+ state.dict_ofs,
+ decomp_flags,
+ );
+
+ let in_bytes = status.1;
+ let out_bytes = status.2;
+ let status = status.0;
+
+ state.last_status = status;
+
+ *next_in = &next_in[in_bytes..];
+ *total_in += in_bytes;
+
+ state.dict_avail = out_bytes;
+ *total_out += push_dict_out(state, next_out);
+
+ // The stream was corrupted, and decompression failed.
+ if (status as i32) < 0 {
+ return Err(MZError::Data);
+ }
+
+ // The decompressor has flushed all it's data and is waiting for more input, but
+ // there was no more input provided.
+ if (status == TINFLStatus::NeedsMoreInput) && orig_in_len == 0 {
+ return Err(MZError::Buf);
+ }
+
+ if flush == MZFlush::Finish {
+ if status == TINFLStatus::Done {
+ // There is not enough space in the output buffer to flush the remaining
+ // decompressed data in the internal buffer.
+ return if state.dict_avail != 0 {
+ Err(MZError::Buf)
+ } else {
+ Ok(MZStatus::StreamEnd)
+ };
+ // No more space in the output buffer, but we're not done.
+ } else if next_out.is_empty() {
+ return Err(MZError::Buf);
+ }
+ } else {
+ // We're not expected to finish, so it's fine if we can't flush everything yet.
+ let empty_buf = next_in.is_empty() || next_out.is_empty();
+ if (status == TINFLStatus::Done) || empty_buf || (state.dict_avail != 0) {
+ return if (status == TINFLStatus::Done) && (state.dict_avail == 0) {
+ // No more data left, we're done.
+ Ok(MZStatus::StreamEnd)
+ } else {
+ // Ok for now, still waiting for more input data or output space.
+ Ok(MZStatus::Ok)
+ };
+ }
+ }
+ }
+}
+
+fn push_dict_out(state: &mut InflateState, next_out: &mut &mut [u8]) -> usize {
+ let n = cmp::min(state.dict_avail as usize, next_out.len());
+ (next_out[..n]).copy_from_slice(&state.dict[state.dict_ofs..state.dict_ofs + n]);
+ *next_out = &mut mem::take(next_out)[n..];
+ state.dict_avail -= n;
+ state.dict_ofs = (state.dict_ofs + (n)) & (TINFL_LZ_DICT_SIZE - 1);
+ n
+}
+
+#[cfg(test)]
+mod test {
+ use super::{inflate, InflateState};
+ use crate::{DataFormat, MZFlush, MZStatus};
+ use alloc::vec;
+
+ #[test]
+ fn test_state() {
+ let encoded = [
+ 120u8, 156, 243, 72, 205, 201, 201, 215, 81, 168, 202, 201, 76, 82, 4, 0, 27, 101, 4,
+ 19,
+ ];
+ let mut out = vec![0; 50];
+ let mut state = InflateState::new_boxed(DataFormat::Zlib);
+ let res = inflate(&mut state, &encoded, &mut out, MZFlush::Finish);
+ let status = res.status.expect("Failed to decompress!");
+ assert_eq!(status, MZStatus::StreamEnd);
+ assert_eq!(out[..res.bytes_written as usize], b"Hello, zlib!"[..]);
+ assert_eq!(res.bytes_consumed, encoded.len());
+
+ state.reset_as(super::ZeroReset);
+ out.iter_mut().map(|x| *x = 0).count();
+ let res = inflate(&mut state, &encoded, &mut out, MZFlush::Finish);
+ let status = res.status.expect("Failed to decompress!");
+ assert_eq!(status, MZStatus::StreamEnd);
+ assert_eq!(out[..res.bytes_written as usize], b"Hello, zlib!"[..]);
+ assert_eq!(res.bytes_consumed, encoded.len());
+
+ state.reset_as(super::MinReset);
+ out.iter_mut().map(|x| *x = 0).count();
+ let res = inflate(&mut state, &encoded, &mut out, MZFlush::Finish);
+ let status = res.status.expect("Failed to decompress!");
+ assert_eq!(status, MZStatus::StreamEnd);
+ assert_eq!(out[..res.bytes_written as usize], b"Hello, zlib!"[..]);
+ assert_eq!(res.bytes_consumed, encoded.len());
+ assert_eq!(state.decompressor().adler32(), Some(459605011));
+
+ // Test state when not computing adler.
+ state = InflateState::new_boxed(DataFormat::ZLibIgnoreChecksum);
+ out.iter_mut().map(|x| *x = 0).count();
+ let res = inflate(&mut state, &encoded, &mut out, MZFlush::Finish);
+ let status = res.status.expect("Failed to decompress!");
+ assert_eq!(status, MZStatus::StreamEnd);
+ assert_eq!(out[..res.bytes_written as usize], b"Hello, zlib!"[..]);
+ assert_eq!(res.bytes_consumed, encoded.len());
+ // Not computed, so should be Some(1)
+ assert_eq!(state.decompressor().adler32(), Some(1));
+ // Should still have the checksum read from the header file.
+ assert_eq!(state.decompressor().adler32_header(), Some(459605011))
+ }
+}
diff --git a/vendor/miniz_oxide-0.5.3/src/lib.rs b/vendor/miniz_oxide-0.5.3/src/lib.rs
new file mode 100644
index 000000000..8357c5200
--- /dev/null
+++ b/vendor/miniz_oxide-0.5.3/src/lib.rs
@@ -0,0 +1,208 @@
+//! A pure rust replacement for the [miniz](https://github.com/richgel999/miniz)
+//! DEFLATE/zlib encoder/decoder.
+//! The plan for this crate is to be used as a back-end for the
+//! [flate2](https://github.com/alexcrichton/flate2-rs) crate and eventually remove the
+//! need to depend on a C library.
+//!
+//! # Usage
+//! ## Simple compression/decompression:
+//! ``` rust
+//!
+//! use miniz_oxide::inflate::decompress_to_vec;
+//! use miniz_oxide::deflate::compress_to_vec;
+//!
+//! fn roundtrip(data: &[u8]) {
+//! let compressed = compress_to_vec(data, 6);
+//! let decompressed = decompress_to_vec(compressed.as_slice()).expect("Failed to decompress!");
+//! # let _ = decompressed;
+//! }
+//!
+//! # roundtrip(b"Test_data test data lalalal blabla");
+//!
+//! ```
+
+#![forbid(unsafe_code)]
+#![no_std]
+
+extern crate alloc;
+
+pub mod deflate;
+pub mod inflate;
+mod shared;
+
+pub use crate::shared::update_adler32 as mz_adler32_oxide;
+pub use crate::shared::{MZ_ADLER32_INIT, MZ_DEFAULT_WINDOW_BITS};
+
+/// A list of flush types.
+///
+/// See <http://www.bolet.org/~pornin/deflate-flush.html> for more in-depth info.
+#[repr(i32)]
+#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
+pub enum MZFlush {
+ /// Don't force any flushing.
+ /// Used when more input data is expected.
+ None = 0,
+ /// Zlib partial flush.
+ /// Currently treated as [`Sync`].
+ Partial = 1,
+ /// Finish compressing the currently buffered data, and output an empty raw block.
+ /// Has no use in decompression.
+ Sync = 2,
+ /// Same as [`Sync`], but resets the compression dictionary so that further compressed
+ /// data does not depend on data compressed before the flush.
+ ///
+ /// Has no use in decompression, and is an error to supply in that case.
+ Full = 3,
+ /// Attempt to flush the remaining data and end the stream.
+ Finish = 4,
+ /// Not implemented.
+ Block = 5,
+}
+
+impl MZFlush {
+ /// Create an MZFlush value from an integer value.
+ ///
+ /// Returns `MZError::Param` on invalid values.
+ pub fn new(flush: i32) -> Result<Self, MZError> {
+ match flush {
+ 0 => Ok(MZFlush::None),
+ 1 | 2 => Ok(MZFlush::Sync),
+ 3 => Ok(MZFlush::Full),
+ 4 => Ok(MZFlush::Finish),
+ _ => Err(MZError::Param),
+ }
+ }
+}
+
+/// A list of miniz successful status codes.
+///
+/// These are emitted as the [`Ok`] side of a [`MZResult`] in the [`StreamResult`] returned from
+/// [`deflate::stream::deflate()`] or [`inflate::stream::inflate()`].
+#[repr(i32)]
+#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
+pub enum MZStatus {
+ /// Operation succeeded.
+ ///
+ /// Some data was decompressed or compressed; see the byte counters in the [`StreamResult`] for
+ /// details.
+ Ok = 0,
+
+ /// Operation succeeded and end of deflate stream was found.
+ ///
+ /// X-ref [`TINFLStatus::Done`][inflate::TINFLStatus::Done] or
+ /// [`TDEFLStatus::Done`][deflate::core::TDEFLStatus::Done] for `inflate` or `deflate`
+ /// respectively.
+ StreamEnd = 1,
+
+ /// Unused
+ NeedDict = 2,
+}
+
+/// A list of miniz failed status codes.
+///
+/// These are emitted as the [`Err`] side of a [`MZResult`] in the [`StreamResult`] returned from
+/// [`deflate::stream::deflate()`] or [`inflate::stream::inflate()`].
+#[repr(i32)]
+#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
+pub enum MZError {
+ /// Unused
+ ErrNo = -1,
+
+ /// General stream error.
+ ///
+ /// See [`inflate::stream::inflate()`] docs for details of how it can occur there.
+ ///
+ /// See [`deflate::stream::deflate()`] docs for how it can in principle occur there, though it's
+ /// believed impossible in practice.
+ Stream = -2,
+
+ /// Error in inflation; see [`inflate::stream::inflate()`] for details.
+ ///
+ /// Not returned from [`deflate::stream::deflate()`].
+ Data = -3,
+
+ /// Unused
+ Mem = -4,
+
+ /// Buffer-related error.
+ ///
+ /// See the docs of [`deflate::stream::deflate()`] or [`inflate::stream::inflate()`] for details
+ /// of when it would trigger in the one you're using.
+ Buf = -5,
+
+ /// Unused
+ Version = -6,
+
+ /// Bad parameters.
+ ///
+ /// This can be returned from [`deflate::stream::deflate()`] in the case of bad parameters. See
+ /// [`TDEFLStatus::BadParam`][deflate::core::TDEFLStatus::BadParam].
+ Param = -10_000,
+}
+
+/// How compressed data is wrapped.
+#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
+#[non_exhaustive]
+pub enum DataFormat {
+ /// Wrapped using the [zlib](http://www.zlib.org/rfc-zlib.html) format.
+ Zlib,
+ /// Zlib wrapped but ignore and don't compute the adler32 checksum.
+ /// Currently only used for inflate, behaves the same as Zlib for compression.
+ ZLibIgnoreChecksum,
+ /// Raw DEFLATE.
+ Raw,
+}
+
+impl DataFormat {
+ pub(crate) fn from_window_bits(window_bits: i32) -> DataFormat {
+ if window_bits > 0 {
+ DataFormat::Zlib
+ } else {
+ DataFormat::Raw
+ }
+ }
+
+ pub(crate) fn to_window_bits(self) -> i32 {
+ match self {
+ DataFormat::Zlib | DataFormat::ZLibIgnoreChecksum => shared::MZ_DEFAULT_WINDOW_BITS,
+ DataFormat::Raw => -shared::MZ_DEFAULT_WINDOW_BITS,
+ }
+ }
+}
+
+/// `Result` alias for all miniz status codes both successful and failed.
+pub type MZResult = Result<MZStatus, MZError>;
+
+/// A structure containg the result of a call to the inflate or deflate streaming functions.
+#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
+pub struct StreamResult {
+ /// The number of bytes consumed from the input slice.
+ pub bytes_consumed: usize,
+ /// The number of bytes written to the output slice.
+ pub bytes_written: usize,
+ /// The return status of the call.
+ pub status: MZResult,
+}
+
+impl StreamResult {
+ #[inline]
+ pub(crate) const fn error(error: MZError) -> StreamResult {
+ StreamResult {
+ bytes_consumed: 0,
+ bytes_written: 0,
+ status: Err(error),
+ }
+ }
+}
+
+impl core::convert::From<StreamResult> for MZResult {
+ fn from(res: StreamResult) -> Self {
+ res.status
+ }
+}
+
+impl core::convert::From<&StreamResult> for MZResult {
+ fn from(res: &StreamResult) -> Self {
+ res.status
+ }
+}
diff --git a/vendor/miniz_oxide-0.5.3/src/shared.rs b/vendor/miniz_oxide-0.5.3/src/shared.rs
new file mode 100644
index 000000000..8b81fb112
--- /dev/null
+++ b/vendor/miniz_oxide-0.5.3/src/shared.rs
@@ -0,0 +1,25 @@
+#[doc(hidden)]
+pub const MZ_ADLER32_INIT: u32 = 1;
+
+#[doc(hidden)]
+pub const MZ_DEFAULT_WINDOW_BITS: i32 = 15;
+
+pub const HUFFMAN_LENGTH_ORDER: [u8; 19] = [
+ 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15,
+];
+
+#[doc(hidden)]
+#[cfg(not(feature = "simd"))]
+pub fn update_adler32(adler: u32, data: &[u8]) -> u32 {
+ let mut hash = adler::Adler32::from_checksum(adler);
+ hash.write_slice(data);
+ hash.checksum()
+}
+
+#[doc(hidden)]
+#[cfg(feature = "simd")]
+pub fn update_adler32(adler: u32, data: &[u8]) -> u32 {
+ let mut hash = simd_adler32::Adler32::from_checksum(adler);
+ hash.write(data);
+ hash.finish()
+}
diff --git a/vendor/miniz_oxide/.cargo-checksum.json b/vendor/miniz_oxide/.cargo-checksum.json
index 16e89c510..e237f121c 100644
--- a/vendor/miniz_oxide/.cargo-checksum.json
+++ b/vendor/miniz_oxide/.cargo-checksum.json
@@ -1 +1 @@
-{"files":{"Cargo.toml":"14ec71e104b90decb8b84170557138a51cc39a8b83b721d74eb476fb13f6bdd2","LICENSE":"e190940e8ad3cdd4fca962a6508ed6865d589d314b1cb055f86000e124b88d8d","LICENSE-APACHE.md":"0d542e0c8804e39aa7f37eb00da5a762149dc682d7829451287e11b938e94594","LICENSE-MIT.md":"e190940e8ad3cdd4fca962a6508ed6865d589d314b1cb055f86000e124b88d8d","LICENSE-ZLIB.md":"c89bcc058da12a0fb24402b8ea4542a21515dd1da2e8c67bba4ed9bd269f1c96","Readme.md":"b6a6668b073a3356748b642ce51b31233b6408ffcca3e52801ef473a9f7925c7","src/deflate/buffer.rs":"76bcca4e79bef412eeebdd06d2d0a4348ed9ee17edbdaa6d451d8bf03b1cde85","src/deflate/core.rs":"8087c155cb47f57a9747565857dcef59fff0a7a499abbfdb0c60e694d3234db8","src/deflate/mod.rs":"8ade5b9683b8d728fe5e8f5c23e0630165bfdbef3e56a18b1b729f9bbd4a4b1d","src/deflate/stream.rs":"016c82b09a989492c8c8ea89027d339fcf59a5ca2155e7026ac094ca74344712","src/inflate/core.rs":"49bd596d5255ac88b486f6f978ab7b26663cdab01a6ebaa41bf4559f12b0fed8","src/inflate/mod.rs":"690a8cd50a7da88672b750bb2c62d52d2a58efa41e6ddb2084589a17095cb875","src/inflate/output_buffer.rs":"1ae90d03ba8c9d667fe248b6066731774afdf93cc79cd3bf90e0711b963b0b72","src/inflate/stream.rs":"f82c44ffdff054aff05307ed5709e432b54d5997bb4bbfff8f760171c33c76c3","src/lib.rs":"a9d6a889415ffe3d800c8516fb0ac0bae3585010966d1fdf3b06a85330c36854","src/shared.rs":"a8c47fcb566591e39fcd50d44f3b4d0f567318b8ca36c8d732ee0d8c99a14906"},"package":"96590ba8f175222643a85693f33d26e9c8a015f599c216509b1a6894af675d34"} \ No newline at end of file
+{"files":{"Cargo.toml":"1a05b1f1b1cee9093e2d261931b86dcd92057289d5d8cd675381df52e029c797","LICENSE":"e190940e8ad3cdd4fca962a6508ed6865d589d314b1cb055f86000e124b88d8d","LICENSE-APACHE.md":"0d542e0c8804e39aa7f37eb00da5a762149dc682d7829451287e11b938e94594","LICENSE-MIT.md":"e190940e8ad3cdd4fca962a6508ed6865d589d314b1cb055f86000e124b88d8d","LICENSE-ZLIB.md":"c89bcc058da12a0fb24402b8ea4542a21515dd1da2e8c67bba4ed9bd269f1c96","Readme.md":"d9ae0e4192de8809293672397459f90bdb3cc6a6bd92f235edafbb0530181efb","src/deflate/buffer.rs":"76bcca4e79bef412eeebdd06d2d0a4348ed9ee17edbdaa6d451d8bf03b1cde85","src/deflate/core.rs":"8087c155cb47f57a9747565857dcef59fff0a7a499abbfdb0c60e694d3234db8","src/deflate/mod.rs":"8ade5b9683b8d728fe5e8f5c23e0630165bfdbef3e56a18b1b729f9bbd4a4b1d","src/deflate/stream.rs":"016c82b09a989492c8c8ea89027d339fcf59a5ca2155e7026ac094ca74344712","src/inflate/core.rs":"e7b8946db6a56834311b382fa1f8a3aba21a9ca42cf880c4ae1c97f699d22092","src/inflate/mod.rs":"6a6f658cd44c47f1ba402328fb78c27b24b8700a909ddac4c0c472b12046d1fa","src/inflate/output_buffer.rs":"1ae90d03ba8c9d667fe248b6066731774afdf93cc79cd3bf90e0711b963b0b72","src/inflate/stream.rs":"b1d96270d89b549bdc09352bfbd5a4fea24b479c0057c1f50b66b30ce2eb9cc1","src/lib.rs":"7cb7c0ebc61141f0e43a6edca97a22c93ca3b1550893007359007d4dfdeaa883","src/shared.rs":"a8c47fcb566591e39fcd50d44f3b4d0f567318b8ca36c8d732ee0d8c99a14906"},"package":"b275950c28b37e794e8c55d88aeb5e139d0ce23fdbbeda68f8d7174abdf9e8fa"} \ No newline at end of file
diff --git a/vendor/miniz_oxide/Cargo.toml b/vendor/miniz_oxide/Cargo.toml
index 7fa9d3e06..bbb3e9adb 100644
--- a/vendor/miniz_oxide/Cargo.toml
+++ b/vendor/miniz_oxide/Cargo.toml
@@ -12,7 +12,7 @@
[package]
edition = "2018"
name = "miniz_oxide"
-version = "0.5.4"
+version = "0.6.2"
authors = [
"Frommi <daniil.liferenko@gmail.com>",
"oyvindln <oyvindln@users.noreply.github.com>",
@@ -62,7 +62,7 @@ optional = true
default-features = false
[features]
-default = []
+default = ["with-alloc"]
rustc-dep-of-std = [
"core",
"alloc",
@@ -70,3 +70,5 @@ rustc-dep-of-std = [
"adler/rustc-dep-of-std",
]
simd = ["simd-adler32"]
+std = []
+with-alloc = []
diff --git a/vendor/miniz_oxide/Readme.md b/vendor/miniz_oxide/Readme.md
index 0eac176e8..51579f071 100644
--- a/vendor/miniz_oxide/Readme.md
+++ b/vendor/miniz_oxide/Readme.md
@@ -3,9 +3,18 @@
A fully safe, pure rust replacement for the [miniz](https://github.com/richgel999/miniz) DEFLATE/zlib encoder/decoder.
The main intention of this crate is to be used as a back-end for the [flate2](https://github.com/alexcrichton/flate2-rs), but it can also be used on it's own. Using flate2 with the ```rust_backend``` feature provides an easy to use streaming API for miniz_oxide.
-The library is fully [no_std](https://docs.rust-embedded.org/book/intro/no-std.html), though it requires the use of the `alloc` and `collection` crates as it allocates memory.
+The library is fully [no_std](https://docs.rust-embedded.org/book/intro/no-std.html). By default, the `with-alloc` feature is enabled, which requires the use of the `alloc` and `collection` crates as it allocates memory.
-miniz_oxide 0.5.x Requires at least rust 1.40.0 0.3.x requires at least rust 0.36.0.
+The `std` feature additionally turns on things only available if `no_std` is not used. Currently this only means implementing [Error](https://doc.rust-lang.org/stable/std/error/trait.Error.html) for the `DecompressError` error struct returned by the simple decompression functions if enabled together with `with-alloc`.
+
+Using the library with `default-features = false` removes the dependency on `alloc`
+and `collection` crates, making it suitable for systems without an allocator.
+Running without allocation reduces crate functionality:
+
+- The `deflate` module is removed complete
+- Some `inflate` functions which return a `Vec` are removed
+
+miniz_oxide 0.5.x and 0.6.x Requires at least rust 1.40.0 0.3.x requires at least rust 0.36.0.
miniz_oxide features no use of unsafe code.
@@ -21,8 +30,8 @@ use miniz_oxide::inflate::decompress_to_vec;
fn roundtrip(data: &[u8]) {
// Compress the input
let compressed = compress_to_vec(data, 6);
- // Decompress the compressed input
- let decompressed = decompress_to_vec(compressed.as_slice()).expect("Failed to decompress!");
+ // Decompress the compressed input and limit max output size to avoid going out of memory on large/malformed input.
+ let decompressed = decompress_to_vec_with_limit(compressed.as_slice(), 60000).expect("Failed to decompress!");
// Check roundtrip succeeded
assert_eq!(data, decompressed);
}
@@ -32,4 +41,4 @@ fn main() {
}
```
-These simple functions will do everything in one go and are thus not recommended for use cases where the input size may be large or unknown, for that use case consider using miniz_oxide via flate2 or the low-level streaming functions instead.
+These simple functions will do everything in one go and are thus not recommended for use cases outside of prototyping/testing as real world data can have any size and thus result in very large memory allocations for the output Vector. Consider using miniz_oxide via [flate2](https://github.com/alexcrichton/flate2-rs) which makes it easy to do streaming (de)compression or the low-level streaming functions instead.
diff --git a/vendor/miniz_oxide/src/inflate/core.rs b/vendor/miniz_oxide/src/inflate/core.rs
index 38bdacbbd..630e5e6fd 100644
--- a/vendor/miniz_oxide/src/inflate/core.rs
+++ b/vendor/miniz_oxide/src/inflate/core.rs
@@ -108,7 +108,7 @@ const HUFFLEN_TABLE: usize = 2;
pub mod inflate_flags {
/// Should we try to parse a zlib header?
///
- /// If unset, [`decompress()`] will expect an RFC1951 deflate stream. If set, it will expect an
+ /// If unset, the function will expect an RFC1951 deflate stream. If set, it will expect a
/// RFC1950 zlib wrapper around the deflate stream.
pub const TINFL_FLAG_PARSE_ZLIB_HEADER: u32 = 1;
@@ -1456,7 +1456,8 @@ pub fn decompress(
// Mask the top bits since they may contain length info.
l.counter &= 511;
- if l.counter == 256 {
+ if l.counter
+ == 256 {
// We hit the end of block symbol.
Action::Jump(BlockDone)
} else if l.counter > 285 {
diff --git a/vendor/miniz_oxide/src/inflate/mod.rs b/vendor/miniz_oxide/src/inflate/mod.rs
index 03b9dc988..bb19e379c 100644
--- a/vendor/miniz_oxide/src/inflate/mod.rs
+++ b/vendor/miniz_oxide/src/inflate/mod.rs
@@ -1,10 +1,10 @@
//! This module contains functionality for decompression.
-use crate::alloc::boxed::Box;
-use crate::alloc::vec;
-use crate::alloc::vec::Vec;
-use ::core::cmp::min;
+#[cfg(feature = "with-alloc")]
+use crate::alloc::{boxed::Box, vec, vec::Vec};
use ::core::usize;
+#[cfg(all(feature = "std", feature = "with-alloc"))]
+use std::error::Error;
pub mod core;
mod output_buffer;
@@ -78,19 +78,63 @@ impl TINFLStatus {
}
}
+/// Struct return when decompress_to_vec functions fail.
+#[cfg(feature = "with-alloc")]
+#[derive(Debug)]
+pub struct DecompressError {
+ /// Decompressor status on failure. See [TINFLStatus] for details.
+ pub status: TINFLStatus,
+ /// The currently decompressed data if any.
+ pub output: Vec<u8>,
+}
+
+#[cfg(feature = "with-alloc")]
+impl alloc::fmt::Display for DecompressError {
+ fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
+ f.write_str(match self.status {
+ TINFLStatus::FailedCannotMakeProgress => "Truncated input stream",
+ TINFLStatus::BadParam => "Invalid output buffer size",
+ TINFLStatus::Adler32Mismatch => "Adler32 checksum mismatch",
+ TINFLStatus::Failed => "Invalid input data",
+ TINFLStatus::Done => unreachable!(),
+ TINFLStatus::NeedsMoreInput => "Truncated input stream",
+ TINFLStatus::HasMoreOutput => "Output size exceeded the specified limit",
+ })
+ }
+}
+
+/// Implement Error trait only if std feature is requested as it requires std.
+#[cfg(all(feature = "std", feature = "with-alloc"))]
+impl Error for DecompressError {}
+
+#[cfg(feature = "with-alloc")]
+fn decompress_error(status: TINFLStatus, output: Vec<u8>) -> Result<Vec<u8>, DecompressError> {
+ Err(DecompressError { status, output })
+}
+
/// Decompress the deflate-encoded data in `input` to a vector.
///
-/// Returns a tuple of the [`Vec`] of decompressed data and the [status result][TINFLStatus].
+/// NOTE: This function will not bound the output, so if the output is large enough it can result in an out of memory error.
+/// It is therefore suggested to not use this for anything other than test programs, use the functions with a specified limit, or
+/// ideally streaming decompression via the [flate2](https://github.com/alexcrichton/flate2-rs) library instead.
+///
+/// Returns a [`Result`] containing the [`Vec`] of decompressed data on success, and a [struct][DecompressError] containing the status and so far decompressed data if any on failure.
#[inline]
-pub fn decompress_to_vec(input: &[u8]) -> Result<Vec<u8>, TINFLStatus> {
+#[cfg(feature = "with-alloc")]
+pub fn decompress_to_vec(input: &[u8]) -> Result<Vec<u8>, DecompressError> {
decompress_to_vec_inner(input, 0, usize::max_value())
}
/// Decompress the deflate-encoded data (with a zlib wrapper) in `input` to a vector.
///
-/// Returns a tuple of the [`Vec`] of decompressed data and the [status result][TINFLStatus].
+/// NOTE: This function will not bound the output, so if the output is large enough it can result in an out of memory error.
+/// It is therefore suggested to not use this for anything other than test programs, use the functions with a specified limit, or
+/// ideally streaming decompression via the [flate2](https://github.com/alexcrichton/flate2-rs) library instead.
+///
+/// Returns a [`Result`] containing the [`Vec`] of decompressed data on success, and a [struct][DecompressError] containing the status and so far decompressed data if any on failure.
#[inline]
-pub fn decompress_to_vec_zlib(input: &[u8]) -> Result<Vec<u8>, TINFLStatus> {
+#[cfg(feature = "with-alloc")]
+pub fn decompress_to_vec_zlib(input: &[u8]) -> Result<Vec<u8>, DecompressError> {
decompress_to_vec_inner(
input,
inflate_flags::TINFL_FLAG_PARSE_ZLIB_HEADER,
@@ -99,38 +143,51 @@ pub fn decompress_to_vec_zlib(input: &[u8]) -> Result<Vec<u8>, TINFLStatus> {
}
/// Decompress the deflate-encoded data in `input` to a vector.
+///
/// The vector is grown to at most `max_size` bytes; if the data does not fit in that size,
-/// [`TINFLStatus::HasMoreOutput`] error is returned.
+/// the error [struct][DecompressError] will contain the status [`TINFLStatus::HasMoreOutput`] and the data that was decompressed on failure.
+///
+/// As this function tries to decompress everything in one go, it's not ideal for general use outside of tests or where the output size is expected to be small.
+/// It is suggested to use streaming decompression via the [flate2](https://github.com/alexcrichton/flate2-rs) library instead.
///
-/// Returns a tuple of the [`Vec`] of decompressed data and the [status result][TINFLStatus].
+/// Returns a [`Result`] containing the [`Vec`] of decompressed data on success, and a [struct][DecompressError] on failure.
#[inline]
-pub fn decompress_to_vec_with_limit(input: &[u8], max_size: usize) -> Result<Vec<u8>, TINFLStatus> {
+#[cfg(feature = "with-alloc")]
+pub fn decompress_to_vec_with_limit(
+ input: &[u8],
+ max_size: usize,
+) -> Result<Vec<u8>, DecompressError> {
decompress_to_vec_inner(input, 0, max_size)
}
/// Decompress the deflate-encoded data (with a zlib wrapper) in `input` to a vector.
/// The vector is grown to at most `max_size` bytes; if the data does not fit in that size,
-/// [`TINFLStatus::HasMoreOutput`] error is returned.
+/// the error [struct][DecompressError] will contain the status [`TINFLStatus::HasMoreOutput`] and the data that was decompressed on failure.
+///
+/// As this function tries to decompress everything in one go, it's not ideal for general use outside of tests or where the output size is expected to be small.
+/// It is suggested to use streaming decompression via the [flate2](https://github.com/alexcrichton/flate2-rs) library instead.
///
-/// Returns a tuple of the [`Vec`] of decompressed data and the [status result][TINFLStatus].
+/// Returns a [`Result`] containing the [`Vec`] of decompressed data on success, and a [struct][DecompressError] on failure.
#[inline]
+#[cfg(feature = "with-alloc")]
pub fn decompress_to_vec_zlib_with_limit(
input: &[u8],
max_size: usize,
-) -> Result<Vec<u8>, TINFLStatus> {
+) -> Result<Vec<u8>, DecompressError> {
decompress_to_vec_inner(input, inflate_flags::TINFL_FLAG_PARSE_ZLIB_HEADER, max_size)
}
/// Backend of various to-[`Vec`] decompressions.
///
-/// Returns a tuple of the [`Vec`] of decompressed data and the [status result][TINFLStatus].
+/// Returns [`Vec`] of decompressed data on success and the [error struct][DecompressError] with details on failure.
+#[cfg(feature = "with-alloc")]
fn decompress_to_vec_inner(
input: &[u8],
flags: u32,
max_output_size: usize,
-) -> Result<Vec<u8>, TINFLStatus> {
+) -> Result<Vec<u8>, DecompressError> {
let flags = flags | inflate_flags::TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF;
- let mut ret: Vec<u8> = vec![0; min(input.len().saturating_mul(2), max_output_size)];
+ let mut ret: Vec<u8> = vec![0; input.len().saturating_mul(2).min(max_output_size)];
let mut decomp = Box::<DecompressorOxide>::default();
@@ -153,14 +210,14 @@ fn decompress_to_vec_inner(
TINFLStatus::HasMoreOutput => {
// if the buffer has already reached the size limit, return an error
if ret.len() >= max_output_size {
- return Err(TINFLStatus::HasMoreOutput);
+ return decompress_error(TINFLStatus::HasMoreOutput, ret);
}
// calculate the new length, capped at `max_output_size`
let new_len = ret.len().saturating_mul(2).min(max_output_size);
ret.resize(new_len, 0);
}
- _ => return Err(status),
+ _ => return decompress_error(status, ret),
}
}
}
@@ -221,7 +278,7 @@ pub fn decompress_slice_iter_to_slice<'out, 'inp>(
mod test {
use super::{
decompress_slice_iter_to_slice, decompress_to_vec_zlib, decompress_to_vec_zlib_with_limit,
- TINFLStatus,
+ DecompressError, TINFLStatus,
};
const ENCODED: [u8; 20] = [
120, 156, 243, 72, 205, 201, 201, 215, 81, 168, 202, 201, 76, 82, 4, 0, 27, 101, 4, 19,
@@ -243,7 +300,10 @@ mod test {
fn fail_to_decompress_with_limit() {
let res = decompress_to_vec_zlib_with_limit(&ENCODED[..], 8);
match res {
- Err(TINFLStatus::HasMoreOutput) => (), // expected result
+ Err(DecompressError {
+ status: TINFLStatus::HasMoreOutput,
+ ..
+ }) => (), // expected result
_ => panic!("Decompression output size limit was not enforced"),
}
}
diff --git a/vendor/miniz_oxide/src/inflate/stream.rs b/vendor/miniz_oxide/src/inflate/stream.rs
index 715747166..ee681b67b 100644
--- a/vendor/miniz_oxide/src/inflate/stream.rs
+++ b/vendor/miniz_oxide/src/inflate/stream.rs
@@ -1,6 +1,7 @@
//! Extra streaming decompression functionality.
//!
//! As of now this is mainly intended for use to build a higher-level wrapper.
+#[cfg(feature = "with-alloc")]
use crate::alloc::boxed::Box;
use core::{cmp, mem};
@@ -115,6 +116,7 @@ impl InflateState {
/// # Parameters
/// `data_format`: Determines whether the compressed data is assumed to wrapped with zlib
/// metadata.
+ #[cfg(feature = "with-alloc")]
pub fn new_boxed(data_format: DataFormat) -> Box<InflateState> {
let mut b: Box<InflateState> = Box::default();
b.data_format = data_format;
@@ -136,6 +138,7 @@ impl InflateState {
/// The decompressor does not support different window sizes. As such,
/// any positive (>0) value will set the zlib header flag, while a negative one
/// will not.
+ #[cfg(feature = "with-alloc")]
pub fn new_boxed_with_window_bits(window_bits: i32) -> Box<InflateState> {
let mut b: Box<InflateState> = Box::default();
b.data_format = DataFormat::from_window_bits(window_bits);
diff --git a/vendor/miniz_oxide/src/lib.rs b/vendor/miniz_oxide/src/lib.rs
index 8357c5200..fd64932b0 100644
--- a/vendor/miniz_oxide/src/lib.rs
+++ b/vendor/miniz_oxide/src/lib.rs
@@ -22,10 +22,12 @@
//! ```
#![forbid(unsafe_code)]
-#![no_std]
+#![cfg_attr(not(feature = "std"), no_std)]
+#[cfg(feature = "with-alloc")]
extern crate alloc;
+#[cfg(feature = "with-alloc")]
pub mod deflate;
pub mod inflate;
mod shared;
@@ -154,7 +156,7 @@ pub enum DataFormat {
}
impl DataFormat {
- pub(crate) fn from_window_bits(window_bits: i32) -> DataFormat {
+ pub fn from_window_bits(window_bits: i32) -> DataFormat {
if window_bits > 0 {
DataFormat::Zlib
} else {
@@ -162,7 +164,7 @@ impl DataFormat {
}
}
- pub(crate) fn to_window_bits(self) -> i32 {
+ pub fn to_window_bits(self) -> i32 {
match self {
DataFormat::Zlib | DataFormat::ZLibIgnoreChecksum => shared::MZ_DEFAULT_WINDOW_BITS,
DataFormat::Raw => -shared::MZ_DEFAULT_WINDOW_BITS,
@@ -186,7 +188,7 @@ pub struct StreamResult {
impl StreamResult {
#[inline]
- pub(crate) const fn error(error: MZError) -> StreamResult {
+ pub const fn error(error: MZError) -> StreamResult {
StreamResult {
bytes_consumed: 0,
bytes_written: 0,
diff --git a/vendor/nu-ansi-term/.cargo-checksum.json b/vendor/nu-ansi-term/.cargo-checksum.json
new file mode 100644
index 000000000..c60ea220b
--- /dev/null
+++ b/vendor/nu-ansi-term/.cargo-checksum.json
@@ -0,0 +1 @@
+{"files":{"Cargo.lock":"e8baa9206eac2b73eb3113774c173fc7901755e546d856968bc7e58754a933c9","Cargo.toml":"9d27d7698b15616188d02e77f724750e79906eedb77e5c4ef53b5b5179517011","LICENCE":"cfdb7491dfa8800a1d561957d6a072ad63a6305ffa48386d04eae8eac8d65e8a","README.md":"5c4b8a36f0d7d8faa41084d3b7506cf63cfe8a21fc307ff0721ab4bd9b2d79c9","examples/256_colors.rs":"11caedd6910b1364ed993d6e025b68bae848de495c06feab748ec3a5ed1f8eda","examples/basic_colors.rs":"70bae755aff194fd1dcc080dcb07df386347e391d09ea009e15ff2349189b43a","examples/gradient_colors.rs":"8f907b2f69a9e28bd62d2e459723c6c305e32caf398643e78a579b64a275a23a","examples/rgb_colors.rs":"10067365199a5832de093e199bb925e18f8b53f82ede7188f121532620af2bf9","src/ansi.rs":"cf1adf5347cc4497479f7e72f8382288bc2ea8dd8b40e5844d3113f775a22135","src/debug.rs":"ab14e28dc68d04263bf70b1bc79681ae3951fd5b836583d267d43e2a9799bb38","src/difference.rs":"a71797564e7d152c2c67f1c2a04f1fee6cea0a2a44babd91bb3e60463f89f9ca","src/display.rs":"9f4aeb98033a3854f59e6e4d03b6d6aebb487f6d7dda80c2b131bb6cdf14e79f","src/gradient.rs":"f5b4e2a90ea4fdfa63286fd353d6624cd8255826bac26e1e463f867b0f21874e","src/lib.rs":"a2a2b4cfadb0983dd18347b946cb3bdccf1eb343cf58cbbf5e9f573c7313b691","src/rgb.rs":"68ade941086450f2c86ba6697d6847b1b745cf4014aeb583b17d9e9a09ae20eb","src/style.rs":"4a0ec456a384b15340f65845f33ad989c955289d30858de169ce802089f8b51f","src/util.rs":"4a80587db74309c17d583cb72d08d2326a8550f59ce1543003ca8acacbd9a1dc","src/windows.rs":"4a869d522c1b087936260d1b5e4f8ed824a774b8db8bb8bb136d1a8ba460d089","src/write.rs":"b104f6b6d5e20002399065c7ed1f9e9b44b006ec72f73a6ad847bfab68f8f09a"},"package":"77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84"} \ No newline at end of file
diff --git a/vendor/nu-ansi-term/Cargo.lock b/vendor/nu-ansi-term/Cargo.lock
new file mode 100644
index 000000000..b29bf12b5
--- /dev/null
+++ b/vendor/nu-ansi-term/Cargo.lock
@@ -0,0 +1,159 @@
+# 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 = "doc-comment"
+version = "0.3.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10"
+
+[[package]]
+name = "itoa"
+version = "1.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1aab8fc367588b89dcee83ab0fd66b72b50b72fa1904d7095045ace2b0c81c35"
+
+[[package]]
+name = "memchr"
+version = "2.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a"
+
+[[package]]
+name = "nu-ansi-term"
+version = "0.46.0"
+dependencies = [
+ "doc-comment",
+ "overload",
+ "regex",
+ "serde",
+ "serde_json",
+ "winapi",
+]
+
+[[package]]
+name = "overload"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39"
+
+[[package]]
+name = "proc-macro2"
+version = "1.0.36"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c7342d5883fbccae1cc37a2353b09c87c9b0f3afd73f5fb9bba687a1f733b029"
+dependencies = [
+ "unicode-xid",
+]
+
+[[package]]
+name = "quote"
+version = "1.0.15"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "864d3e96a899863136fc6e99f3d7cae289dafe43bf2c5ac19b70df7210c0a145"
+dependencies = [
+ "proc-macro2",
+]
+
+[[package]]
+name = "regex"
+version = "1.5.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1a11647b6b25ff05a515cb92c365cec08801e83423a235b51e231e1808747286"
+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 = "ryu"
+version = "1.0.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "73b4b750c782965c211b42f022f59af1fbceabdd026623714f104152f1ec149f"
+
+[[package]]
+name = "serde"
+version = "1.0.136"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ce31e24b01e1e524df96f1c2fdd054405f8d7376249a5110886fb4b658484789"
+dependencies = [
+ "serde_derive",
+]
+
+[[package]]
+name = "serde_derive"
+version = "1.0.136"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "08597e7152fcd306f41838ed3e37be9eaeed2b61c42e2117266a554fab4662f9"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "serde_json"
+version = "1.0.79"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8e8d9fa5c3b304765ce1fd9c4c8a3de2c8db365a5b91be52f186efc675681d95"
+dependencies = [
+ "itoa",
+ "ryu",
+ "serde",
+]
+
+[[package]]
+name = "syn"
+version = "1.0.87"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1e59d925cf59d8151f25a3bedf97c9c157597c9df7324d32d68991cc399ed08b"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "unicode-xid",
+]
+
+[[package]]
+name = "unicode-xid"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3"
+
+[[package]]
+name = "winapi"
+version = "0.3.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
+dependencies = [
+ "winapi-i686-pc-windows-gnu",
+ "winapi-x86_64-pc-windows-gnu",
+]
+
+[[package]]
+name = "winapi-i686-pc-windows-gnu"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
+
+[[package]]
+name = "winapi-x86_64-pc-windows-gnu"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
diff --git a/vendor/nu-ansi-term/Cargo.toml b/vendor/nu-ansi-term/Cargo.toml
new file mode 100644
index 000000000..209e05511
--- /dev/null
+++ b/vendor/nu-ansi-term/Cargo.toml
@@ -0,0 +1,57 @@
+# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
+#
+# When uploading crates to the registry Cargo will automatically
+# "normalize" Cargo.toml files for maximal compatibility
+# with all versions of Cargo and also rewrite `path` dependencies
+# to registry (e.g., crates.io) dependencies.
+#
+# If you are reading this file be aware that the original Cargo.toml
+# will likely look very different (and much more reasonable).
+# See Cargo.toml.orig for the original contents.
+
+[package]
+edition = "2018"
+name = "nu-ansi-term"
+version = "0.46.0"
+authors = [
+ "ogham@bsago.me",
+ "Ryan Scheel (Havvy) <ryan.havvy@gmail.com>",
+ "Josh Triplett <josh@joshtriplett.org>",
+ "The Nushell Project Developers",
+]
+description = "Library for ANSI terminal colors and styles (bold, underline)"
+license = "MIT"
+repository = "https://github.com/nushell/nu-ansi-term"
+
+[lib]
+doctest = true
+
+[dependencies.overload]
+version = "0.1.1"
+
+[dependencies.serde]
+version = "1.0.90"
+features = ["derive"]
+optional = true
+
+[dev-dependencies.doc-comment]
+version = "0.3"
+
+[dev-dependencies.regex]
+version = "1.1.9"
+
+[dev-dependencies.serde_json]
+version = "1.0.39"
+
+[features]
+derive_serde_style = ["serde"]
+
+[target."cfg(target_os=\"windows\")".dependencies.winapi]
+version = "0.3.4"
+features = [
+ "consoleapi",
+ "errhandlingapi",
+ "fileapi",
+ "handleapi",
+ "processenv",
+]
diff --git a/vendor/ansi_term/LICENCE b/vendor/nu-ansi-term/LICENCE
index 3228cc99b..f392dfc93 100644
--- a/vendor/ansi_term/LICENCE
+++ b/vendor/nu-ansi-term/LICENCE
@@ -1,6 +1,7 @@
The MIT License (MIT)
Copyright (c) 2014 Benjamin Sago
+Copyright (c) 2021-2022 The Nushell Project Developers
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
diff --git a/vendor/ansi_term/README.md b/vendor/nu-ansi-term/README.md
index 30d52ab5f..51c6cc5f6 100644
--- a/vendor/ansi_term/README.md
+++ b/vendor/nu-ansi-term/README.md
@@ -1,47 +1,47 @@
-# rust-ansi-term [![ansi-term on crates.io](http://meritbadge.herokuapp.com/ansi-term)](https://crates.io/crates/ansi_term) [![Build status](https://img.shields.io/travis/ogham/rust-ansi-term/master.svg?style=flat)](https://travis-ci.org/ogham/rust-ansi-term) [![Build status](https://img.shields.io/appveyor/ci/ogham/rust-ansi-term/master.svg?style=flat&logo=AppVeyor&logoColor=silver)](https://ci.appveyor.com/project/ogham/rust-ansi-term) [![Coverage status](https://coveralls.io/repos/ogham/rust-ansi-term/badge.svg?branch=master&service=github)](https://coveralls.io/github/ogham/rust-ansi-term?branch=master)
+# nu-ansi-term
-This is a library for controlling colours and formatting, such as red bold text or blue underlined text, on ANSI terminals.
+> This is a copy of rust-ansi-term but with Color change to Color and light foreground colors added (90-97) as well as light background colors added (100-107).
-### [View the Rustdoc](https://docs.rs/ansi_term/)
+This is a library for controlling colors and formatting, such as red bold text or blue underlined text, on ANSI terminals.
+## [View the Rustdoc](https://docs.rs/nu_ansi_term/)
-# Installation
+## Installation
This crate works with [Cargo](http://crates.io). Add the following to your `Cargo.toml` dependencies section:
```toml
[dependencies]
-ansi_term = "0.12"
+nu_ansi_term = "0.46"
```
-
## Basic usage
-There are three main types in this crate that you need to be concerned with: `ANSIString`, `Style`, and `Colour`.
+There are three main types in this crate that you need to be concerned with: `AnsiString`, `Style`, and `Color`.
-A `Style` holds stylistic information: foreground and background colours, whether the text should be bold, or blinking, or other properties.
-The `Colour` enum represents the available colours.
-And an `ANSIString` is a string paired with a `Style`.
+A `Style` holds stylistic information: foreground and background colors, whether the text should be bold, or blinking, or other properties.
+The `Color` enum represents the available colors.
+And an `AnsiString` is a string paired with a `Style`.
-`Color` is also available as an alias to `Colour`.
+`Color` is also available as an alias to `Color`.
-To format a string, call the `paint` method on a `Style` or a `Colour`, passing in the string you want to format as the argument.
+To format a string, call the `paint` method on a `Style` or a `Color`, passing in the string you want to format as the argument.
For example, here’s how to get some red text:
```rust
-use ansi_term::Colour::Red;
+use nu_ansi_term::Color::Red;
println!("This is in red: {}", Red.paint("a red string"));
```
-It’s important to note that the `paint` method does *not* actually return a string with the ANSI control characters surrounding it.
-Instead, it returns an `ANSIString` value that has a `Display` implementation that, when formatted, returns the characters.
+It’s important to note that the `paint` method does _not_ actually return a string with the ANSI control characters surrounding it.
+Instead, it returns an `AnsiString` value that has a `Display` implementation that, when formatted, returns the characters.
This allows strings to be printed with a minimum of `String` allocations being performed behind the scenes.
-If you *do* want to get at the escape codes, then you can convert the `ANSIString` to a string as you would any other `Display` value:
+If you _do_ want to get at the escape codes, then you can convert the `AnsiString` to a string as you would any other `Display` value:
```rust
-use ansi_term::Colour::Red;
+use nu_ansi_term::Color::Red;
let red_string = Red.paint("a red string").to_string();
```
@@ -49,28 +49,28 @@ let red_string = Red.paint("a red string").to_string();
**Note for Windows 10 users:** On Windows 10, the application must enable ANSI support first:
```rust,ignore
-let enabled = ansi_term::enable_ansi_support();
+let enabled = nu_ansi_term::enable_ansi_support();
```
## Bold, underline, background, and other styles
-For anything more complex than plain foreground colour changes, you need to construct `Style` values themselves, rather than beginning with a `Colour`.
+For anything more complex than plain foreground color changes, you need to construct `Style` values themselves, rather than beginning with a `Color`.
You can do this by chaining methods based on a new `Style`, created with `Style::new()`.
Each method creates a new style that has that specific property set.
For example:
```rust
-use ansi_term::Style;
+use nu_ansi_term::Style;
println!("How about some {} and {}?",
Style::new().bold().paint("bold"),
Style::new().underline().paint("underline"));
```
-For brevity, these methods have also been implemented for `Colour` values, so you can give your styles a foreground colour without having to begin with an empty `Style` value:
+For brevity, these methods have also been implemented for `Color` values, so you can give your styles a foreground color without having to begin with an empty `Style` value:
```rust
-use ansi_term::Colour::{Blue, Yellow};
+use nu_ansi_term::Color::{Blue, Yellow};
println!("Demonstrating {} and {}!",
Blue.bold().paint("blue bold"),
@@ -80,103 +80,102 @@ println!("Yellow on blue: {}", Yellow.on(Blue).paint("wow!"));
```
The complete list of styles you can use are:
-`bold`, `dimmed`, `italic`, `underline`, `blink`, `reverse`, `hidden`, and `on` for background colours.
+`bold`, `dimmed`, `italic`, `underline`, `blink`, `reverse`, `hidden`, and `on` for background colors.
-In some cases, you may find it easier to change the foreground on an existing `Style` rather than starting from the appropriate `Colour`.
+In some cases, you may find it easier to change the foreground on an existing `Style` rather than starting from the appropriate `Color`.
You can do this using the `fg` method:
```rust
-use ansi_term::Style;
-use ansi_term::Colour::{Blue, Cyan, Yellow};
+use nu_ansi_term::Style;
+use nu_ansi_term::Color::{Blue, Cyan, Yellow};
println!("Yellow on blue: {}", Style::new().on(Blue).fg(Yellow).paint("yow!"));
println!("Also yellow on blue: {}", Cyan.on(Blue).fg(Yellow).paint("zow!"));
```
-You can turn a `Colour` into a `Style` with the `normal` method.
-This will produce the exact same `ANSIString` as if you just used the `paint` method on the `Colour` directly, but it’s useful in certain cases: for example, you may have a method that returns `Styles`, and need to represent both the “red bold” and “red, but not bold” styles with values of the same type. The `Style` struct also has a `Default` implementation if you want to have a style with *nothing* set.
+You can turn a `Color` into a `Style` with the `normal` method.
+This will produce the exact same `AnsiString` as if you just used the `paint` method on the `Color` directly, but it’s useful in certain cases: for example, you may have a method that returns `Styles`, and need to represent both the “red bold” and “red, but not bold” styles with values of the same type. The `Style` struct also has a `Default` implementation if you want to have a style with _nothing_ set.
```rust
-use ansi_term::Style;
-use ansi_term::Colour::Red;
+use nu_ansi_term::Style;
+use nu_ansi_term::Color::Red;
Red.normal().paint("yet another red string");
Style::default().paint("a completely regular string");
```
+## Extended colors
-## Extended colours
-
-You can access the extended range of 256 colours by using the `Colour::Fixed` variant, which takes an argument of the colour number to use.
-This can be included wherever you would use a `Colour`:
+You can access the extended range of 256 colors by using the `Color::Fixed` variant, which takes an argument of the color number to use.
+This can be included wherever you would use a `Color`:
```rust
-use ansi_term::Colour::Fixed;
+use nu_ansi_term::Color::Fixed;
Fixed(134).paint("A sort of light purple");
Fixed(221).on(Fixed(124)).paint("Mustard in the ketchup");
```
-The first sixteen of these values are the same as the normal and bold standard colour variants.
-There’s nothing stopping you from using these as `Fixed` colours instead, but there’s nothing to be gained by doing so either.
+The first sixteen of these values are the same as the normal and bold standard color variants.
+There’s nothing stopping you from using these as `Fixed` colors instead, but there’s nothing to be gained by doing so either.
-You can also access full 24-bit colour by using the `Colour::RGB` variant, which takes separate `u8` arguments for red, green, and blue:
+You can also access full 24-bit color by using the `Color::RGB` variant, which takes separate `u8` arguments for red, green, and blue:
```rust
-use ansi_term::Colour::RGB;
+use nu_ansi_term::Color::RGB;
RGB(70, 130, 180).paint("Steel blue");
```
## Combining successive coloured strings
-The benefit of writing ANSI escape codes to the terminal is that they *stack*: you do not need to end every coloured string with a reset code if the text that follows it is of a similar style.
+The benefit of writing ANSI escape codes to the terminal is that they _stack_: you do not need to end every coloured string with a reset code if the text that follows it is of a similar style.
For example, if you want to have some blue text followed by some blue bold text, it’s possible to send the ANSI code for blue, followed by the ANSI code for bold, and finishing with a reset code without having to have an extra one between the two strings.
This crate can optimise the ANSI codes that get printed in situations like this, making life easier for your terminal renderer.
-The `ANSIStrings` struct takes a slice of several `ANSIString` values, and will iterate over each of them, printing only the codes for the styles that need to be updated as part of its formatting routine.
+The `AnsiStrings` struct takes a slice of several `AnsiString` values, and will iterate over each of them, printing only the codes for the styles that need to be updated as part of its formatting routine.
The following code snippet uses this to enclose a binary number displayed in red bold text inside some red, but not bold, brackets:
```rust
-use ansi_term::Colour::Red;
-use ansi_term::{ANSIString, ANSIStrings};
+use nu_ansi_term::Color::Red;
+use nu_ansi_term::{AnsiString, AnsiStrings};
let some_value = format!("{:b}", 42);
-let strings: &[ANSIString<'static>] = &[
+let strings: &[AnsiString<'static>] = &[
Red.paint("["),
Red.bold().paint(some_value),
Red.paint("]"),
];
-println!("Value: {}", ANSIStrings(strings));
+println!("Value: {}", AnsiStrings(strings));
```
There are several things to note here.
-Firstly, the `paint` method can take *either* an owned `String` or a borrowed `&str`.
-Internally, an `ANSIString` holds a copy-on-write (`Cow`) string value to deal with both owned and borrowed strings at the same time.
+Firstly, the `paint` method can take _either_ an owned `String` or a borrowed `&str`.
+Internally, an `AnsiString` holds a copy-on-write (`Cow`) string value to deal with both owned and borrowed strings at the same time.
This is used here to display a `String`, the result of the `format!` call, using the same mechanism as some statically-available `&str` slices.
-Secondly, that the `ANSIStrings` value works in the same way as its singular counterpart, with a `Display` implementation that only performs the formatting when required.
+Secondly, that the `AnsiStrings` value works in the same way as its singular counterpart, with a `Display` implementation that only performs the formatting when required.
## Byte strings
This library also supports formatting `[u8]` byte strings; this supports applications working with text in an unknown encoding.
-`Style` and `Colour` support painting `[u8]` values, resulting in an `ANSIByteString`.
+`Style` and `Color` support painting `[u8]` values, resulting in an `AnsiByteString`.
This type does not implement `Display`, as it may not contain UTF-8, but it does provide a method `write_to` to write the result to any value that implements `Write`:
```rust
-use ansi_term::Colour::Green;
+use nu_ansi_term::Color::Green;
Green.paint("user data".as_bytes()).write_to(&mut std::io::stdout()).unwrap();
```
-Similarly, the type `ANSIByteStrings` supports writing a list of `ANSIByteString` values with minimal escape sequences:
+Similarly, the type `AnsiByteStrings` supports writing a list of `AnsiByteString` values with minimal escape sequences:
```rust
-use ansi_term::Colour::Green;
-use ansi_term::ANSIByteStrings;
+use nu_ansi_term::Color::Green;
+use nu_ansi_term::AnsiByteStrings;
-ANSIByteStrings(&[
+AnsiByteStrings(&[
Green.paint("user data 1\n".as_bytes()),
Green.bold().paint("user data 2\n".as_bytes()),
]).write_to(&mut std::io::stdout()).unwrap();
diff --git a/vendor/ansi_term/examples/256_colours.rs b/vendor/nu-ansi-term/examples/256_colors.rs
index 92fe2f1c1..4766dcdb6 100644
--- a/vendor/ansi_term/examples/256_colours.rs
+++ b/vendor/nu-ansi-term/examples/256_colors.rs
@@ -1,27 +1,26 @@
-extern crate ansi_term;
-use ansi_term::Colour;
+extern crate nu_ansi_term;
+use nu_ansi_term::Color;
-// This example prints out the 256 colours.
+// This example prints out the 256 colors.
// They're arranged like this:
//
-// - 0 to 8 are the eight standard colours.
-// - 9 to 15 are the eight bold colours.
-// - 16 to 231 are six blocks of six-by-six colour squares.
+// - 0 to 8 are the eight standard colors.
+// - 9 to 15 are the eight bold colors.
+// - 16 to 231 are six blocks of six-by-six color squares.
// - 232 to 255 are shades of grey.
fn main() {
-
// First two lines
for c in 0..8 {
glow(c, c != 0);
print!(" ");
}
- print!("\n");
+ println!();
for c in 8..16 {
glow(c, c != 8);
print!(" ");
}
- print!("\n\n");
+ println!("\n");
// Six lines of the first three squares
for row in 0..6 {
@@ -34,9 +33,9 @@ fn main() {
print!(" ");
}
- print!("\n");
+ println!();
}
- print!("\n");
+ println!();
// Six more lines of the other three squares
for row in 0..6 {
@@ -49,25 +48,25 @@ fn main() {
print!(" ");
}
- print!("\n");
+ println!();
}
- print!("\n");
+ println!();
// The last greyscale lines
for c in 232..=243 {
glow(c, false);
print!(" ");
}
- print!("\n");
+ println!();
for c in 244..=255 {
glow(c, true);
print!(" ");
}
- print!("\n");
+ println!();
}
fn glow(c: u8, light_bg: bool) {
- let base = if light_bg { Colour::Black } else { Colour::White };
- let style = base.on(Colour::Fixed(c));
+ let base = if light_bg { Color::Black } else { Color::White };
+ let style = base.on(Color::Fixed(c));
print!("{}", style.paint(&format!(" {:3} ", c)));
}
diff --git a/vendor/nu-ansi-term/examples/basic_colors.rs b/vendor/nu-ansi-term/examples/basic_colors.rs
new file mode 100644
index 000000000..3c2b6817f
--- /dev/null
+++ b/vendor/nu-ansi-term/examples/basic_colors.rs
@@ -0,0 +1,18 @@
+extern crate nu_ansi_term;
+use nu_ansi_term::{Color::*, Style};
+
+// This example prints out the 16 basic colors.
+
+fn main() {
+ let normal = Style::default();
+
+ println!("{} {}", normal.paint("Normal"), normal.bold().paint("bold"));
+ println!("{} {}", Black.paint("Black"), Black.bold().paint("bold"));
+ println!("{} {}", Red.paint("Red"), Red.bold().paint("bold"));
+ println!("{} {}", Green.paint("Green"), Green.bold().paint("bold"));
+ println!("{} {}", Yellow.paint("Yellow"), Yellow.bold().paint("bold"));
+ println!("{} {}", Blue.paint("Blue"), Blue.bold().paint("bold"));
+ println!("{} {}", Purple.paint("Purple"), Purple.bold().paint("bold"));
+ println!("{} {}", Cyan.paint("Cyan"), Cyan.bold().paint("bold"));
+ println!("{} {}", White.paint("White"), White.bold().paint("bold"));
+}
diff --git a/vendor/nu-ansi-term/examples/gradient_colors.rs b/vendor/nu-ansi-term/examples/gradient_colors.rs
new file mode 100644
index 000000000..1c9583865
--- /dev/null
+++ b/vendor/nu-ansi-term/examples/gradient_colors.rs
@@ -0,0 +1,37 @@
+use nu_ansi_term::{build_all_gradient_text, Color, Gradient, Rgb, TargetGround};
+
+fn main() {
+ let text = "lorem ipsum quia dolor sit amet, consectetur, adipisci velit";
+
+ // a gradient from hex colors
+ let start = Rgb::from_hex(0x40c9ff);
+ let end = Rgb::from_hex(0xe81cff);
+ let grad0 = Gradient::new(start, end);
+
+ // a gradient from color::rgb()
+ let start = Color::Rgb(64, 201, 255);
+ let end = Color::Rgb(232, 28, 255);
+ let gradient = Gradient::from_color_rgb(start, end);
+
+ // a slightly different gradient
+ let start2 = Color::Rgb(128, 64, 255);
+ let end2 = Color::Rgb(0, 28, 255);
+ let gradient2 = Gradient::from_color_rgb(start2, end2);
+
+ // reverse the gradient
+ let gradient3 = gradient.reverse();
+
+ let build_fg = gradient.build(text, TargetGround::Foreground);
+ println!("{}", build_fg);
+ let build_bg = gradient.build(text, TargetGround::Background);
+ println!("{}", build_bg);
+ let bgt = build_all_gradient_text(text, gradient, gradient2);
+ println!("{}", bgt);
+ let bgt2 = build_all_gradient_text(text, gradient, gradient3);
+ println!("{}", bgt2);
+
+ println!(
+ "{}",
+ grad0.build("nushell is awesome", TargetGround::Foreground)
+ );
+}
diff --git a/vendor/nu-ansi-term/examples/rgb_colors.rs b/vendor/nu-ansi-term/examples/rgb_colors.rs
new file mode 100644
index 000000000..4657d401f
--- /dev/null
+++ b/vendor/nu-ansi-term/examples/rgb_colors.rs
@@ -0,0 +1,23 @@
+extern crate nu_ansi_term;
+use nu_ansi_term::{Color, Style};
+
+// This example prints out a color gradient in a grid by calculating each
+// character’s red, green, and blue components, and using 24-bit color codes
+// to display them.
+
+const WIDTH: i32 = 80;
+const HEIGHT: i32 = 24;
+
+fn main() {
+ for row in 0..HEIGHT {
+ for col in 0..WIDTH {
+ let r = (row * 255 / HEIGHT) as u8;
+ let g = (col * 255 / WIDTH) as u8;
+ let b = 128;
+
+ print!("{}", Style::default().on(Color::Rgb(r, g, b)).paint(" "));
+ }
+
+ println!();
+ }
+}
diff --git a/vendor/ansi_term/src/ansi.rs b/vendor/nu-ansi-term/src/ansi.rs
index aaf215234..8f393fcdc 100644
--- a/vendor/ansi_term/src/ansi.rs
+++ b/vendor/nu-ansi-term/src/ansi.rs
@@ -1,17 +1,11 @@
-use style::{Colour, Style};
-
+#![allow(missing_docs)]
+use crate::style::{Color, Style};
+use crate::write::AnyWrite;
use std::fmt;
-use write::AnyWrite;
-
-
-// ---- generating ANSI codes ----
-
impl Style {
-
/// Write any bytes that go *before* a piece of text to the given writer.
fn write_prefix<W: AnyWrite + ?Sized>(&self, f: &mut W) -> Result<(), W::Error> {
-
// If there are actually no styles here, then don’t write *any* codes
// as the prefix. An empty ANSI code may not affect the terminal
// output at all, but a user may just want a code-free string.
@@ -26,33 +20,55 @@ impl Style {
{
let mut write_char = |c| {
- if written_anything { write!(f, ";")?; }
+ if written_anything {
+ write!(f, ";")?;
+ }
written_anything = true;
write!(f, "{}", c)?;
Ok(())
};
- if self.is_bold { write_char('1')? }
- if self.is_dimmed { write_char('2')? }
- if self.is_italic { write_char('3')? }
- if self.is_underline { write_char('4')? }
- if self.is_blink { write_char('5')? }
- if self.is_reverse { write_char('7')? }
- if self.is_hidden { write_char('8')? }
- if self.is_strikethrough { write_char('9')? }
+ if self.is_bold {
+ write_char('1')?
+ }
+ if self.is_dimmed {
+ write_char('2')?
+ }
+ if self.is_italic {
+ write_char('3')?
+ }
+ if self.is_underline {
+ write_char('4')?
+ }
+ if self.is_blink {
+ write_char('5')?
+ }
+ if self.is_reverse {
+ write_char('7')?
+ }
+ if self.is_hidden {
+ write_char('8')?
+ }
+ if self.is_strikethrough {
+ write_char('9')?
+ }
}
- // The foreground and background colours, if specified, need to be
+ // The foreground and background colors, if specified, need to be
// handled specially because the number codes are more complicated.
// (see `write_background_code` and `write_foreground_code`)
if let Some(bg) = self.background {
- if written_anything { write!(f, ";")?; }
+ if written_anything {
+ write!(f, ";")?;
+ }
written_anything = true;
bg.write_background_code(f)?;
}
if let Some(fg) = self.foreground {
- if written_anything { write!(f, ";")?; }
+ if written_anything {
+ write!(f, ";")?;
+ }
fg.write_foreground_code(f)?;
}
@@ -66,53 +82,70 @@ impl Style {
fn write_suffix<W: AnyWrite + ?Sized>(&self, f: &mut W) -> Result<(), W::Error> {
if self.is_plain() {
Ok(())
- }
- else {
+ } else {
write!(f, "{}", RESET)
}
}
}
-
/// The code to send to reset all styles and return to `Style::default()`.
pub static RESET: &str = "\x1B[0m";
-
-
-impl Colour {
+impl Color {
fn write_foreground_code<W: AnyWrite + ?Sized>(&self, f: &mut W) -> Result<(), W::Error> {
- match *self {
- Colour::Black => write!(f, "30"),
- Colour::Red => write!(f, "31"),
- Colour::Green => write!(f, "32"),
- Colour::Yellow => write!(f, "33"),
- Colour::Blue => write!(f, "34"),
- Colour::Purple => write!(f, "35"),
- Colour::Cyan => write!(f, "36"),
- Colour::White => write!(f, "37"),
- Colour::Fixed(num) => write!(f, "38;5;{}", &num),
- Colour::RGB(r,g,b) => write!(f, "38;2;{};{};{}", &r, &g, &b),
+ match self {
+ Color::Black => write!(f, "30"),
+ Color::Red => write!(f, "31"),
+ Color::Green => write!(f, "32"),
+ Color::Yellow => write!(f, "33"),
+ Color::Blue => write!(f, "34"),
+ Color::Purple => write!(f, "35"),
+ Color::Magenta => write!(f, "35"),
+ Color::Cyan => write!(f, "36"),
+ Color::White => write!(f, "37"),
+ Color::Fixed(num) => write!(f, "38;5;{}", num),
+ Color::Rgb(r, g, b) => write!(f, "38;2;{};{};{}", r, g, b),
+ Color::Default => write!(f, "39"),
+ Color::DarkGray => write!(f, "90"),
+ Color::LightRed => write!(f, "91"),
+ Color::LightGreen => write!(f, "92"),
+ Color::LightYellow => write!(f, "93"),
+ Color::LightBlue => write!(f, "94"),
+ Color::LightPurple => write!(f, "95"),
+ Color::LightMagenta => write!(f, "95"),
+ Color::LightCyan => write!(f, "96"),
+ Color::LightGray => write!(f, "97"),
}
}
fn write_background_code<W: AnyWrite + ?Sized>(&self, f: &mut W) -> Result<(), W::Error> {
- match *self {
- Colour::Black => write!(f, "40"),
- Colour::Red => write!(f, "41"),
- Colour::Green => write!(f, "42"),
- Colour::Yellow => write!(f, "43"),
- Colour::Blue => write!(f, "44"),
- Colour::Purple => write!(f, "45"),
- Colour::Cyan => write!(f, "46"),
- Colour::White => write!(f, "47"),
- Colour::Fixed(num) => write!(f, "48;5;{}", &num),
- Colour::RGB(r,g,b) => write!(f, "48;2;{};{};{}", &r, &g, &b),
+ match self {
+ Color::Black => write!(f, "40"),
+ Color::Red => write!(f, "41"),
+ Color::Green => write!(f, "42"),
+ Color::Yellow => write!(f, "43"),
+ Color::Blue => write!(f, "44"),
+ Color::Purple => write!(f, "45"),
+ Color::Magenta => write!(f, "45"),
+ Color::Cyan => write!(f, "46"),
+ Color::White => write!(f, "47"),
+ Color::Fixed(num) => write!(f, "48;5;{}", num),
+ Color::Rgb(r, g, b) => write!(f, "48;2;{};{};{}", r, g, b),
+ Color::Default => write!(f, "49"),
+ Color::DarkGray => write!(f, "100"),
+ Color::LightRed => write!(f, "101"),
+ Color::LightGreen => write!(f, "102"),
+ Color::LightYellow => write!(f, "103"),
+ Color::LightBlue => write!(f, "104"),
+ Color::LightPurple => write!(f, "105"),
+ Color::LightMagenta => write!(f, "105"),
+ Color::LightCyan => write!(f, "106"),
+ Color::LightGray => write!(f, "107"),
}
}
}
-
-/// Like `ANSIString`, but only displays the style prefix.
+/// Like `AnsiString`, but only displays the style prefix.
///
/// This type implements the `Display` trait, meaning it can be written to a
/// `std::fmt` formatting without doing any extra allocation, and written to a
@@ -121,7 +154,7 @@ impl Colour {
#[derive(Clone, Copy, Debug)]
pub struct Prefix(Style);
-/// Like `ANSIString`, but only displays the difference between two
+/// Like `AnsiString`, but only displays the difference between two
/// styles.
///
/// This type implements the `Display` trait, meaning it can be written to a
@@ -131,7 +164,7 @@ pub struct Prefix(Style);
#[derive(Clone, Copy, Debug)]
pub struct Infix(Style, Style);
-/// Like `ANSIString`, but only displays the style suffix.
+/// Like `AnsiString`, but only displays the style suffix.
///
/// This type implements the `Display` trait, meaning it can be written to a
/// `std::fmt` formatting without doing any extra allocation, and written to a
@@ -140,16 +173,14 @@ pub struct Infix(Style, Style);
#[derive(Clone, Copy, Debug)]
pub struct Suffix(Style);
-
impl Style {
-
/// The prefix bytes for this style. These are the bytes that tell the
- /// terminal to use a different colour or font style.
+ /// terminal to use a different color or font style.
///
/// # Examples
///
/// ```
- /// use ansi_term::{Style, Colour::Blue};
+ /// use nu_ansi_term::{Style, Color::Blue};
///
/// let style = Style::default().bold();
/// assert_eq!("\x1b[1m",
@@ -169,12 +200,12 @@ impl Style {
/// The infix bytes between this style and `next` style. These are the bytes
/// that tell the terminal to change the style to `next`. These may include
- /// a reset followed by the next colour and style, depending on the two styles.
+ /// a reset followed by the next color and style, depending on the two styles.
///
/// # Examples
///
/// ```
- /// use ansi_term::{Style, Colour::Green};
+ /// use nu_ansi_term::{Style, Color::Green};
///
/// let style = Style::default().bold();
/// assert_eq!("\x1b[32m",
@@ -193,12 +224,12 @@ impl Style {
}
/// The suffix for this style. These are the bytes that tell the terminal
- /// to reset back to its normal colour and font style.
+ /// to reset back to its normal color and font style.
///
/// # Examples
///
/// ```
- /// use ansi_term::{Style, Colour::Green};
+ /// use nu_ansi_term::{Style, Color::Green};
///
/// let style = Style::default().bold();
/// assert_eq!("\x1b[0m",
@@ -217,18 +248,16 @@ impl Style {
}
}
-
-impl Colour {
-
- /// The prefix bytes for this colour as a `Style`. These are the bytes
- /// that tell the terminal to use a different colour or font style.
+impl Color {
+ /// The prefix bytes for this color as a `Style`. These are the bytes
+ /// that tell the terminal to use a different color or font style.
///
/// See also [`Style::prefix`](struct.Style.html#method.prefix).
///
/// # Examples
///
/// ```
- /// use ansi_term::Colour::Green;
+ /// use nu_ansi_term::Color::Green;
///
/// assert_eq!("\x1b[0m",
/// Green.suffix().to_string());
@@ -237,33 +266,33 @@ impl Colour {
Prefix(self.normal())
}
- /// The infix bytes between this colour and `next` colour. These are the bytes
- /// that tell the terminal to use the `next` colour, or to do nothing if
- /// the two colours are equal.
+ /// The infix bytes between this color and `next` color. These are the bytes
+ /// that tell the terminal to use the `next` color, or to do nothing if
+ /// the two colors are equal.
///
/// See also [`Style::infix`](struct.Style.html#method.infix).
///
/// # Examples
///
/// ```
- /// use ansi_term::Colour::{Red, Yellow};
+ /// use nu_ansi_term::Color::{Red, Yellow};
///
/// assert_eq!("\x1b[33m",
/// Red.infix(Yellow).to_string());
/// ```
- pub fn infix(self, next: Colour) -> Infix {
+ pub fn infix(self, next: Color) -> Infix {
Infix(self.normal(), next.normal())
}
- /// The suffix for this colour as a `Style`. These are the bytes that
- /// tell the terminal to reset back to its normal colour and font style.
+ /// The suffix for this color as a `Style`. These are the bytes that
+ /// tell the terminal to reset back to its normal color and font style.
///
/// See also [`Style::suffix`](struct.Style.html#method.suffix).
///
/// # Examples
///
/// ```
- /// use ansi_term::Colour::Purple;
+ /// use nu_ansi_term::Color::Purple;
///
/// assert_eq!("\x1b[0m",
/// Purple.suffix().to_string());
@@ -273,49 +302,44 @@ impl Colour {
}
}
-
impl fmt::Display for Prefix {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- let f: &mut fmt::Write = f;
+ let f: &mut dyn fmt::Write = f;
self.0.write_prefix(f)
}
}
-
impl fmt::Display for Infix {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- use difference::Difference;
+ use crate::difference::Difference;
match Difference::between(&self.0, &self.1) {
Difference::ExtraStyles(style) => {
- let f: &mut fmt::Write = f;
+ let f: &mut dyn fmt::Write = f;
style.write_prefix(f)
- },
+ }
Difference::Reset => {
- let f: &mut fmt::Write = f;
+ let f: &mut dyn fmt::Write = f;
write!(f, "{}{}", RESET, self.1.prefix())
- },
- Difference::NoDifference => {
- Ok(()) // nothing to write
- },
+ }
+ Difference::Empty => {
+ Ok(()) // nothing to write
+ }
}
}
}
-
impl fmt::Display for Suffix {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- let f: &mut fmt::Write = f;
+ let f: &mut dyn fmt::Write = f;
self.0.write_suffix(f)
}
}
-
-
#[cfg(test)]
mod test {
- use style::Style;
- use style::Colour::*;
+ use crate::style::Color::*;
+ use crate::style::Style;
macro_rules! test {
($name: ident: $style: expr; $input: expr => $result: expr) => {
@@ -341,6 +365,8 @@ mod test {
test!(purple_on_white: Purple.on(White); "hi" => "\x1B[47;35mhi\x1B[0m");
test!(purple_on_white_2: Purple.normal().on(White); "hi" => "\x1B[47;35mhi\x1B[0m");
test!(yellow_on_blue: Style::new().on(Blue).fg(Yellow); "hi" => "\x1B[44;33mhi\x1B[0m");
+ test!(magenta_on_white: Magenta.on(White); "hi" => "\x1B[47;35mhi\x1B[0m");
+ test!(magenta_on_white_2: Magenta.normal().on(White); "hi" => "\x1B[47;35mhi\x1B[0m");
test!(yellow_on_blue_2: Cyan.on(Blue).fg(Yellow); "hi" => "\x1B[44;33mhi\x1B[0m");
test!(cyan_bold_on_white: Cyan.bold().on(White); "hi" => "\x1B[1;47;36mhi\x1B[0m");
test!(cyan_ul_on_white: Cyan.underline().on(White); "hi" => "\x1B[4;47;36mhi\x1B[0m");
@@ -349,10 +375,10 @@ mod test {
test!(fixed: Fixed(100); "hi" => "\x1B[38;5;100mhi\x1B[0m");
test!(fixed_on_purple: Fixed(100).on(Purple); "hi" => "\x1B[45;38;5;100mhi\x1B[0m");
test!(fixed_on_fixed: Fixed(100).on(Fixed(200)); "hi" => "\x1B[48;5;200;38;5;100mhi\x1B[0m");
- test!(rgb: RGB(70,130,180); "hi" => "\x1B[38;2;70;130;180mhi\x1B[0m");
- test!(rgb_on_blue: RGB(70,130,180).on(Blue); "hi" => "\x1B[44;38;2;70;130;180mhi\x1B[0m");
- test!(blue_on_rgb: Blue.on(RGB(70,130,180)); "hi" => "\x1B[48;2;70;130;180;34mhi\x1B[0m");
- test!(rgb_on_rgb: RGB(70,130,180).on(RGB(5,10,15)); "hi" => "\x1B[48;2;5;10;15;38;2;70;130;180mhi\x1B[0m");
+ test!(rgb: Rgb(70,130,180); "hi" => "\x1B[38;2;70;130;180mhi\x1B[0m");
+ test!(rgb_on_blue: Rgb(70,130,180).on(Blue); "hi" => "\x1B[44;38;2;70;130;180mhi\x1B[0m");
+ test!(blue_on_rgb: Blue.on(Rgb(70,130,180)); "hi" => "\x1B[48;2;70;130;180;34mhi\x1B[0m");
+ test!(rgb_on_rgb: Rgb(70,130,180).on(Rgb(5,10,15)); "hi" => "\x1B[48;2;5;10;15;38;2;70;130;180mhi\x1B[0m");
test!(bold: Style::new().bold(); "hi" => "\x1B[1mhi\x1B[0m");
test!(underline: Style::new().underline(); "hi" => "\x1B[4mhi\x1B[0m");
test!(bunderline: Style::new().bold().underline(); "hi" => "\x1B[1;4mhi\x1B[0m");
@@ -362,11 +388,18 @@ mod test {
test!(reverse: Style::new().reverse(); "hi" => "\x1B[7mhi\x1B[0m");
test!(hidden: Style::new().hidden(); "hi" => "\x1B[8mhi\x1B[0m");
test!(stricken: Style::new().strikethrough(); "hi" => "\x1B[9mhi\x1B[0m");
+ test!(lr_on_lr: LightRed.on(LightRed); "hi" => "\x1B[101;91mhi\x1B[0m");
#[test]
fn test_infix() {
- assert_eq!(Style::new().dimmed().infix(Style::new()).to_string(), "\x1B[0m");
- assert_eq!(White.dimmed().infix(White.normal()).to_string(), "\x1B[0m\x1B[37m");
+ assert_eq!(
+ Style::new().dimmed().infix(Style::new()).to_string(),
+ "\x1B[0m"
+ );
+ assert_eq!(
+ White.dimmed().infix(White.normal()).to_string(),
+ "\x1B[0m\x1B[37m"
+ );
assert_eq!(White.normal().infix(White.bold()).to_string(), "\x1B[1m");
assert_eq!(White.normal().infix(Blue.normal()).to_string(), "\x1B[34m");
assert_eq!(Blue.bold().infix(Blue.bold()).to_string(), "");
diff --git a/vendor/ansi_term/src/debug.rs b/vendor/nu-ansi-term/src/debug.rs
index 4877323ff..1dcde52be 100644
--- a/vendor/ansi_term/src/debug.rs
+++ b/vendor/nu-ansi-term/src/debug.rs
@@ -1,67 +1,86 @@
+use crate::style::Style;
use std::fmt;
-use style::Style;
-
/// Styles have a special `Debug` implementation that only shows the fields that
/// are set. Fields that haven’t been touched aren’t included in the output.
///
/// This behaviour gets bypassed when using the alternate formatting mode
/// `format!("{:#?}")`.
///
-/// use ansi_term::Colour::{Red, Blue};
+/// use nu_ansi_term::Color::{Red, Blue};
/// assert_eq!("Style { fg(Red), on(Blue), bold, italic }",
/// format!("{:?}", Red.on(Blue).bold().italic()));
impl fmt::Debug for Style {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
if fmt.alternate() {
fmt.debug_struct("Style")
- .field("foreground", &self.foreground)
- .field("background", &self.background)
- .field("blink", &self.is_blink)
- .field("bold", &self.is_bold)
- .field("dimmed", &self.is_dimmed)
- .field("hidden", &self.is_hidden)
- .field("italic", &self.is_italic)
- .field("reverse", &self.is_reverse)
- .field("strikethrough", &self.is_strikethrough)
- .field("underline", &self.is_underline)
- .finish()
- }
- else if self.is_plain() {
+ .field("foreground", &self.foreground)
+ .field("background", &self.background)
+ .field("blink", &self.is_blink)
+ .field("bold", &self.is_bold)
+ .field("dimmed", &self.is_dimmed)
+ .field("hidden", &self.is_hidden)
+ .field("italic", &self.is_italic)
+ .field("reverse", &self.is_reverse)
+ .field("strikethrough", &self.is_strikethrough)
+ .field("underline", &self.is_underline)
+ .finish()
+ } else if self.is_plain() {
fmt.write_str("Style {}")
- }
- else {
+ } else {
fmt.write_str("Style { ")?;
let mut written_anything = false;
if let Some(fg) = self.foreground {
- if written_anything { fmt.write_str(", ")? }
+ if written_anything {
+ fmt.write_str(", ")?
+ }
written_anything = true;
write!(fmt, "fg({:?})", fg)?
}
if let Some(bg) = self.background {
- if written_anything { fmt.write_str(", ")? }
+ if written_anything {
+ fmt.write_str(", ")?
+ }
written_anything = true;
write!(fmt, "on({:?})", bg)?
}
{
let mut write_flag = |name| {
- if written_anything { fmt.write_str(", ")? }
+ if written_anything {
+ fmt.write_str(", ")?
+ }
written_anything = true;
fmt.write_str(name)
};
- if self.is_blink { write_flag("blink")? }
- if self.is_bold { write_flag("bold")? }
- if self.is_dimmed { write_flag("dimmed")? }
- if self.is_hidden { write_flag("hidden")? }
- if self.is_italic { write_flag("italic")? }
- if self.is_reverse { write_flag("reverse")? }
- if self.is_strikethrough { write_flag("strikethrough")? }
- if self.is_underline { write_flag("underline")? }
+ if self.is_blink {
+ write_flag("blink")?
+ }
+ if self.is_bold {
+ write_flag("bold")?
+ }
+ if self.is_dimmed {
+ write_flag("dimmed")?
+ }
+ if self.is_hidden {
+ write_flag("hidden")?
+ }
+ if self.is_italic {
+ write_flag("italic")?
+ }
+ if self.is_reverse {
+ write_flag("reverse")?
+ }
+ if self.is_strikethrough {
+ write_flag("strikethrough")?
+ }
+ if self.is_underline {
+ write_flag("underline")?
+ }
}
write!(fmt, " }}")
@@ -69,11 +88,10 @@ impl fmt::Debug for Style {
}
}
-
#[cfg(test)]
mod test {
- use style::Colour::*;
- use style::Style;
+ use crate::style::Color::*;
+ use crate::style::Style;
fn style() -> Style {
Style::new()
@@ -94,7 +112,7 @@ mod test {
test!(both: style().bold().italic() => "Style { bold, italic }");
test!(red: Red.normal() => "Style { fg(Red) }");
- test!(redblue: Red.normal().on(RGB(3, 2, 4)) => "Style { fg(Red), on(RGB(3, 2, 4)) }");
+ test!(redblue: Red.normal().on(Rgb(3, 2, 4)) => "Style { fg(Red), on(Rgb(3, 2, 4)) }");
test!(everything:
Red.on(Blue).blink().bold().dimmed().hidden().italic().reverse().strikethrough().underline() =>
diff --git a/vendor/ansi_term/src/difference.rs b/vendor/nu-ansi-term/src/difference.rs
index b0de07f7e..beee8ea25 100644
--- a/vendor/ansi_term/src/difference.rs
+++ b/vendor/nu-ansi-term/src/difference.rs
@@ -1,11 +1,9 @@
use super::Style;
-
-/// When printing out one coloured string followed by another, use one of
+/// When printing out one colored string followed by another, use one of
/// these rules to figure out which *extra* control codes need to be sent.
#[derive(PartialEq, Clone, Copy, Debug)]
pub enum Difference {
-
/// Print out the control codes specified by this style to end up looking
/// like the second string's styles.
ExtraStyles(Style),
@@ -16,19 +14,17 @@ pub enum Difference {
/// The before style is exactly the same as the after style, so no further
/// control codes need to be printed.
- NoDifference,
+ Empty,
}
-
impl Difference {
-
/// Compute the 'style difference' required to turn an existing style into
/// the given, second style.
///
/// For example, to turn green text into green bold text, it's redundant
/// to write a reset command then a second green+bold command, instead of
/// just writing one bold command. This method should see that both styles
- /// use the foreground colour green, and reduce it to a single command.
+ /// use the foreground color green, and reduce it to a single command.
///
/// This method returns an enum value because it's not actually always
/// possible to turn one style into another: for example, text could be
@@ -44,7 +40,7 @@ impl Difference {
// it commented out for now, and defaulting to Reset.
if first == next {
- return NoDifference;
+ return Empty;
}
// Cannot un-bold, so must Reset.
@@ -137,13 +133,12 @@ impl Difference {
}
}
-
#[cfg(test)]
mod test {
- use super::*;
use super::Difference::*;
- use style::Colour::*;
- use style::Style;
+ use super::*;
+ use crate::style::Color::*;
+ use crate::style::Style;
fn style() -> Style {
Style::new()
@@ -158,12 +153,12 @@ mod test {
};
}
- test!(nothing: Green.normal(); Green.normal() => NoDifference);
+ test!(nothing: Green.normal(); Green.normal() => Empty);
test!(uppercase: Green.normal(); Green.bold() => ExtraStyles(style().bold()));
test!(lowercase: Green.bold(); Green.normal() => Reset);
- test!(nothing2: Green.bold(); Green.bold() => NoDifference);
+ test!(nothing2: Green.bold(); Green.bold() => Empty);
- test!(colour_change: Red.normal(); Blue.normal() => ExtraStyles(Blue.normal()));
+ test!(color_change: Red.normal(); Blue.normal() => ExtraStyles(Blue.normal()));
test!(addition_of_blink: style(); style().blink() => ExtraStyles(style().blink()));
test!(addition_of_dimmed: style(); style().dimmed() => ExtraStyles(style().dimmed()));
diff --git a/vendor/ansi_term/src/display.rs b/vendor/nu-ansi-term/src/display.rs
index 17c54f008..bed934cb3 100644
--- a/vendor/ansi_term/src/display.rs
+++ b/vendor/nu-ansi-term/src/display.rs
@@ -1,40 +1,40 @@
+use crate::ansi::RESET;
+use crate::difference::Difference;
+use crate::style::{Color, Style};
+use crate::write::AnyWrite;
use std::borrow::Cow;
use std::fmt;
use std::io;
-use std::ops::Deref;
-use ansi::RESET;
-use difference::Difference;
-use style::{Style, Colour};
-use write::AnyWrite;
-
-
-/// An `ANSIGenericString` includes a generic string type and a `Style` to
-/// display that string. `ANSIString` and `ANSIByteString` are aliases for
+/// An `AnsiGenericString` includes a generic string type and a `Style` to
+/// display that string. `AnsiString` and `AnsiByteString` are aliases for
/// this type on `str` and `\[u8]`, respectively.
#[derive(PartialEq, Debug)]
-pub struct ANSIGenericString<'a, S: 'a + ToOwned + ?Sized>
-where <S as ToOwned>::Owned: fmt::Debug {
- style: Style,
- string: Cow<'a, S>,
+pub struct AnsiGenericString<'a, S: 'a + ToOwned + ?Sized>
+where
+ <S as ToOwned>::Owned: fmt::Debug,
+{
+ pub(crate) style: Style,
+ pub(crate) string: Cow<'a, S>,
}
-
-/// Cloning an `ANSIGenericString` will clone its underlying string.
+/// Cloning an `AnsiGenericString` will clone its underlying string.
///
/// # Examples
///
/// ```
-/// use ansi_term::ANSIString;
+/// use nu_ansi_term::AnsiString;
///
-/// let plain_string = ANSIString::from("a plain string");
+/// let plain_string = AnsiString::from("a plain string");
/// let clone_string = plain_string.clone();
/// assert_eq!(clone_string, plain_string);
/// ```
-impl<'a, S: 'a + ToOwned + ?Sized> Clone for ANSIGenericString<'a, S>
-where <S as ToOwned>::Owned: fmt::Debug {
- fn clone(&self) -> ANSIGenericString<'a, S> {
- ANSIGenericString {
+impl<'a, S: 'a + ToOwned + ?Sized> Clone for AnsiGenericString<'a, S>
+where
+ <S as ToOwned>::Owned: fmt::Debug,
+{
+ fn clone(&self) -> AnsiGenericString<'a, S> {
+ AnsiGenericString {
style: self.style,
string: self.string.clone(),
}
@@ -56,14 +56,12 @@ where <S as ToOwned>::Owned: fmt::Debug {
// that used it:
//
// #[derive(PartialEq, Debug, Clone, Default)]
-// pub struct TextCellContents(Vec<ANSIString<'static>>);
+// pub struct TextCellContents(Vec<AnsiString<'static>>);
// ^^^^^^^^^^^^^^^^^^^^^^^^^
// error[E0277]: the trait `std::clone::Clone` is not implemented for `str`
//
// The hand-written impl above can ignore that constraint and still compile.
-
-
/// An ANSI String is a string coupled with the `Style` to display it
/// in a terminal.
///
@@ -73,39 +71,41 @@ where <S as ToOwned>::Owned: fmt::Debug {
/// # Examples
///
/// ```
-/// use ansi_term::ANSIString;
-/// use ansi_term::Colour::Red;
+/// use nu_ansi_term::AnsiString;
+/// use nu_ansi_term::Color::Red;
///
/// let red_string = Red.paint("a red string");
/// println!("{}", red_string);
/// ```
///
/// ```
-/// use ansi_term::ANSIString;
+/// use nu_ansi_term::AnsiString;
///
-/// let plain_string = ANSIString::from("a plain string");
-/// assert_eq!(&*plain_string, "a plain string");
+/// let plain_string = AnsiString::from("a plain string");
/// ```
-pub type ANSIString<'a> = ANSIGenericString<'a, str>;
-
-/// An `ANSIByteString` represents a formatted series of bytes. Use
-/// `ANSIByteString` when styling text with an unknown encoding.
-pub type ANSIByteString<'a> = ANSIGenericString<'a, [u8]>;
-
-impl<'a, I, S: 'a + ToOwned + ?Sized> From<I> for ANSIGenericString<'a, S>
-where I: Into<Cow<'a, S>>,
- <S as ToOwned>::Owned: fmt::Debug {
- fn from(input: I) -> ANSIGenericString<'a, S> {
- ANSIGenericString {
+pub type AnsiString<'a> = AnsiGenericString<'a, str>;
+
+/// An `AnsiByteString` represents a formatted series of bytes. Use
+/// `AnsiByteString` when styling text with an unknown encoding.
+pub type AnsiByteString<'a> = AnsiGenericString<'a, [u8]>;
+
+impl<'a, I, S: 'a + ToOwned + ?Sized> From<I> for AnsiGenericString<'a, S>
+where
+ I: Into<Cow<'a, S>>,
+ <S as ToOwned>::Owned: fmt::Debug,
+{
+ fn from(input: I) -> AnsiGenericString<'a, S> {
+ AnsiGenericString {
string: input.into(),
- style: Style::default(),
+ style: Style::default(),
}
}
}
-impl<'a, S: 'a + ToOwned + ?Sized> ANSIGenericString<'a, S>
- where <S as ToOwned>::Owned: fmt::Debug {
-
+impl<'a, S: 'a + ToOwned + ?Sized> AnsiGenericString<'a, S>
+where
+ <S as ToOwned>::Owned: fmt::Debug,
+{
/// Directly access the style
pub fn style_ref(&self) -> &Style {
&self.style
@@ -117,133 +117,128 @@ impl<'a, S: 'a + ToOwned + ?Sized> ANSIGenericString<'a, S>
}
}
-impl<'a, S: 'a + ToOwned + ?Sized> Deref for ANSIGenericString<'a, S>
-where <S as ToOwned>::Owned: fmt::Debug {
- type Target = S;
-
- fn deref(&self) -> &S {
- self.string.deref()
- }
-}
-
-
-/// A set of `ANSIGenericString`s collected together, in order to be
+/// A set of `AnsiGenericStrings`s collected together, in order to be
/// written with a minimum of control characters.
#[derive(Debug, PartialEq)]
-pub struct ANSIGenericStrings<'a, S: 'a + ToOwned + ?Sized>
- (pub &'a [ANSIGenericString<'a, S>])
- where <S as ToOwned>::Owned: fmt::Debug, S: PartialEq;
+pub struct AnsiGenericStrings<'a, S: 'a + ToOwned + ?Sized>(pub &'a [AnsiGenericString<'a, S>])
+where
+ <S as ToOwned>::Owned: fmt::Debug,
+ S: PartialEq;
-/// A set of `ANSIString`s collected together, in order to be written with a
+/// A set of `AnsiString`s collected together, in order to be written with a
/// minimum of control characters.
-pub type ANSIStrings<'a> = ANSIGenericStrings<'a, str>;
+pub type AnsiStrings<'a> = AnsiGenericStrings<'a, str>;
-/// A function to construct an `ANSIStrings` instance.
+/// A function to construct an `AnsiStrings` instance.
#[allow(non_snake_case)]
-pub fn ANSIStrings<'a>(arg: &'a [ANSIString<'a>]) -> ANSIStrings<'a> {
- ANSIGenericStrings(arg)
+pub fn AnsiStrings<'a>(arg: &'a [AnsiString<'a>]) -> AnsiStrings<'a> {
+ AnsiGenericStrings(arg)
}
-/// A set of `ANSIByteString`s collected together, in order to be
+/// A set of `AnsiByteString`s collected together, in order to be
/// written with a minimum of control characters.
-pub type ANSIByteStrings<'a> = ANSIGenericStrings<'a, [u8]>;
+pub type AnsiByteStrings<'a> = AnsiGenericStrings<'a, [u8]>;
-/// A function to construct an `ANSIByteStrings` instance.
+/// A function to construct an `AnsiByteStrings` instance.
#[allow(non_snake_case)]
-pub fn ANSIByteStrings<'a>(arg: &'a [ANSIByteString<'a>]) -> ANSIByteStrings<'a> {
- ANSIGenericStrings(arg)
+pub fn AnsiByteStrings<'a>(arg: &'a [AnsiByteString<'a>]) -> AnsiByteStrings<'a> {
+ AnsiGenericStrings(arg)
}
-
// ---- paint functions ----
impl Style {
-
- /// Paints the given text with this colour, returning an ANSI string.
+ /// Paints the given text with this color, returning an ANSI string.
#[must_use]
- pub fn paint<'a, I, S: 'a + ToOwned + ?Sized>(self, input: I) -> ANSIGenericString<'a, S>
- where I: Into<Cow<'a, S>>,
- <S as ToOwned>::Owned: fmt::Debug {
- ANSIGenericString {
+ pub fn paint<'a, I, S: 'a + ToOwned + ?Sized>(self, input: I) -> AnsiGenericString<'a, S>
+ where
+ I: Into<Cow<'a, S>>,
+ <S as ToOwned>::Owned: fmt::Debug,
+ {
+ AnsiGenericString {
string: input.into(),
- style: self,
+ style: self,
}
}
}
-
-impl Colour {
-
- /// Paints the given text with this colour, returning an ANSI string.
+impl Color {
+ /// Paints the given text with this color, returning an ANSI string.
/// This is a short-cut so you don’t have to use `Blue.normal()` just
/// to get blue text.
///
/// ```
- /// use ansi_term::Colour::Blue;
+ /// use nu_ansi_term::Color::Blue;
/// println!("{}", Blue.paint("da ba dee"));
/// ```
#[must_use]
- pub fn paint<'a, I, S: 'a + ToOwned + ?Sized>(self, input: I) -> ANSIGenericString<'a, S>
- where I: Into<Cow<'a, S>>,
- <S as ToOwned>::Owned: fmt::Debug {
- ANSIGenericString {
+ pub fn paint<'a, I, S: 'a + ToOwned + ?Sized>(self, input: I) -> AnsiGenericString<'a, S>
+ where
+ I: Into<Cow<'a, S>>,
+ <S as ToOwned>::Owned: fmt::Debug,
+ {
+ AnsiGenericString {
string: input.into(),
- style: self.normal(),
+ style: self.normal(),
}
}
}
-
// ---- writers for individual ANSI strings ----
-impl<'a> fmt::Display for ANSIString<'a> {
+impl<'a> fmt::Display for AnsiString<'a> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- let w: &mut fmt::Write = f;
+ let w: &mut dyn fmt::Write = f;
self.write_to_any(w)
}
}
-impl<'a> ANSIByteString<'a> {
- /// Write an `ANSIByteString` to an `io::Write`. This writes the escape
+impl<'a> AnsiByteString<'a> {
+ /// Write an `AnsiByteString` to an `io::Write`. This writes the escape
/// sequences for the associated `Style` around the bytes.
pub fn write_to<W: io::Write>(&self, w: &mut W) -> io::Result<()> {
- let w: &mut io::Write = w;
+ let w: &mut dyn io::Write = w;
self.write_to_any(w)
}
}
-impl<'a, S: 'a + ToOwned + ?Sized> ANSIGenericString<'a, S>
-where <S as ToOwned>::Owned: fmt::Debug, &'a S: AsRef<[u8]> {
- fn write_to_any<W: AnyWrite<wstr=S> + ?Sized>(&self, w: &mut W) -> Result<(), W::Error> {
+impl<'a, S: 'a + ToOwned + ?Sized> AnsiGenericString<'a, S>
+where
+ <S as ToOwned>::Owned: fmt::Debug,
+ &'a S: AsRef<[u8]>,
+{
+ fn write_to_any<W: AnyWrite<Wstr = S> + ?Sized>(&self, w: &mut W) -> Result<(), W::Error> {
write!(w, "{}", self.style.prefix())?;
w.write_str(self.string.as_ref())?;
write!(w, "{}", self.style.suffix())
}
}
-
// ---- writers for combined ANSI strings ----
-impl<'a> fmt::Display for ANSIStrings<'a> {
+impl<'a> fmt::Display for AnsiStrings<'a> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- let f: &mut fmt::Write = f;
+ let f: &mut dyn fmt::Write = f;
self.write_to_any(f)
}
}
-impl<'a> ANSIByteStrings<'a> {
- /// Write `ANSIByteStrings` to an `io::Write`. This writes the minimal
+impl<'a> AnsiByteStrings<'a> {
+ /// Write `AnsiByteStrings` to an `io::Write`. This writes the minimal
/// escape sequences for the associated `Style`s around each set of
/// bytes.
pub fn write_to<W: io::Write>(&self, w: &mut W) -> io::Result<()> {
- let w: &mut io::Write = w;
+ let w: &mut dyn io::Write = w;
self.write_to_any(w)
}
}
-impl<'a, S: 'a + ToOwned + ?Sized + PartialEq> ANSIGenericStrings<'a, S>
-where <S as ToOwned>::Owned: fmt::Debug, &'a S: AsRef<[u8]> {
- fn write_to_any<W: AnyWrite<wstr=S> + ?Sized>(&self, w: &mut W) -> Result<(), W::Error> {
+impl<'a, S: 'a + ToOwned + ?Sized + PartialEq> AnsiGenericStrings<'a, S>
+where
+ <S as ToOwned>::Owned: fmt::Debug,
+ &'a S: AsRef<[u8]>,
+{
+ fn write_to_any<W: AnyWrite<Wstr = S> + ?Sized>(&self, w: &mut W) -> Result<(), W::Error> {
use self::Difference::*;
let first = match self.0.first() {
@@ -257,14 +252,14 @@ where <S as ToOwned>::Owned: fmt::Debug, &'a S: AsRef<[u8]> {
for window in self.0.windows(2) {
match Difference::between(&window[0].style, &window[1].style) {
ExtraStyles(style) => write!(w, "{}", style.prefix())?,
- Reset => write!(w, "{}{}", RESET, window[1].style.prefix())?,
- NoDifference => {/* Do nothing! */},
+ Reset => write!(w, "{}{}", RESET, window[1].style.prefix())?,
+ Empty => { /* Do nothing! */ }
}
w.write_str(&window[1].string)?;
}
- // Write the final reset string after all of the ANSIStrings have been
+ // Write the final reset string after all of the AnsiStrings have been
// written, *except* if the last one has no styles, because it would
// have already been written by this point.
if let Some(last) = self.0.last() {
@@ -277,20 +272,19 @@ where <S as ToOwned>::Owned: fmt::Debug, &'a S: AsRef<[u8]> {
}
}
-
// ---- tests ----
#[cfg(test)]
mod tests {
- pub use super::super::ANSIStrings;
- pub use style::Style;
- pub use style::Colour::*;
+ pub use super::super::AnsiStrings;
+ pub use crate::style::Color::*;
+ pub use crate::style::Style;
#[test]
fn no_control_codes_for_plain() {
let one = Style::default().paint("one");
let two = Style::default().paint("two");
- let output = format!("{}", ANSIStrings( &[ one, two ] ));
- assert_eq!(&*output, "onetwo");
+ let output = AnsiStrings(&[one, two]).to_string();
+ assert_eq!(output, "onetwo");
}
}
diff --git a/vendor/nu-ansi-term/src/gradient.rs b/vendor/nu-ansi-term/src/gradient.rs
new file mode 100644
index 000000000..a0d94c8cd
--- /dev/null
+++ b/vendor/nu-ansi-term/src/gradient.rs
@@ -0,0 +1,105 @@
+use crate::{rgb::Rgb, Color};
+
+/// Linear color gradient between two color stops
+#[derive(Debug, Clone, Copy, PartialEq, Eq)]
+pub struct Gradient {
+ /// Start Color of Gradient
+ pub start: Rgb,
+
+ /// End Color of Gradient
+ pub end: Rgb,
+}
+
+impl Gradient {
+ /// Creates a new [Gradient] with two [Rgb] colors, `start` and `end`
+ #[inline]
+ pub const fn new(start: Rgb, end: Rgb) -> Self {
+ Self { start, end }
+ }
+ pub const fn from_color_rgb(start: Color, end: Color) -> Self {
+ let start_grad = match start {
+ Color::Rgb(r, g, b) => Rgb { r, g, b },
+ _ => Rgb { r: 0, g: 0, b: 0 },
+ };
+ let end_grad = match end {
+ Color::Rgb(r, g, b) => Rgb { r, g, b },
+ _ => Rgb { r: 0, g: 0, b: 0 },
+ };
+
+ Self {
+ start: start_grad,
+ end: end_grad,
+ }
+ }
+
+ /// Computes the [Rgb] color between `start` and `end` for `t`
+ pub fn at(&self, t: f32) -> Rgb {
+ self.start.lerp(self.end, t)
+ }
+
+ /// Returns the reverse of `self`
+ #[inline]
+ pub const fn reverse(&self) -> Self {
+ Self::new(self.end, self.start)
+ }
+
+ #[allow(dead_code)]
+ pub fn build(&self, text: &str, target: TargetGround) -> String {
+ let delta = 1.0 / text.len() as f32;
+ let mut result = text.char_indices().fold(String::new(), |mut acc, (i, c)| {
+ let temp = format!(
+ "\x1B[{}m{}",
+ self.at(i as f32 * delta).ansi_color_code(target),
+ c
+ );
+ acc.push_str(&temp);
+ acc
+ });
+
+ result.push_str("\x1B[0m");
+ result
+ }
+}
+
+#[allow(dead_code)]
+pub fn build_all_gradient_text(text: &str, foreground: Gradient, background: Gradient) -> String {
+ let delta = 1.0 / text.len() as f32;
+ let mut result = text.char_indices().fold(String::new(), |mut acc, (i, c)| {
+ let step = i as f32 * delta;
+ let temp = format!(
+ "\x1B[{};{}m{}",
+ foreground
+ .at(step)
+ .ansi_color_code(TargetGround::Foreground),
+ background
+ .at(step)
+ .ansi_color_code(TargetGround::Background),
+ c
+ );
+ acc.push_str(&temp);
+ acc
+ });
+
+ result.push_str("\x1B[0m");
+ result
+}
+
+#[derive(Debug, Clone, Copy, PartialEq, Eq)]
+pub enum TargetGround {
+ Foreground,
+ Background,
+}
+
+impl TargetGround {
+ #[inline]
+ pub const fn code(&self) -> u8 {
+ match self {
+ Self::Foreground => 30,
+ Self::Background => 40,
+ }
+ }
+}
+
+pub trait ANSIColorCode {
+ fn ansi_color_code(&self, target: TargetGround) -> String;
+}
diff --git a/vendor/ansi_term/src/lib.rs b/vendor/nu-ansi-term/src/lib.rs
index 2d2f83ae6..c04fd3276 100644
--- a/vendor/ansi_term/src/lib.rs
+++ b/vendor/nu-ansi-term/src/lib.rs
@@ -1,40 +1,40 @@
-//! This is a library for controlling colours and formatting, such as
+//! This is a library for controlling colors and formatting, such as
//! red bold text or blue underlined text, on ANSI terminals.
//!
//!
//! ## Basic usage
//!
//! There are three main types in this crate that you need to be
-//! concerned with: [`ANSIString`], [`Style`], and [`Colour`].
+//! concerned with: [`AnsiString`], [`Style`], and [`Color`].
//!
-//! A `Style` holds stylistic information: foreground and background colours,
+//! A `Style` holds stylistic information: foreground and background colors,
//! whether the text should be bold, or blinking, or other properties. The
-//! [`Colour`] enum represents the available colours. And an [`ANSIString`] is a
+//! [`Color`] enum represents the available colors. And an [`AnsiString`] is a
//! string paired with a [`Style`].
//!
-//! [`Color`] is also available as an alias to `Colour`.
+//! [`Color`] is also available as an alias to `Color`.
//!
-//! To format a string, call the `paint` method on a `Style` or a `Colour`,
+//! To format a string, call the `paint` method on a `Style` or a `Color`,
//! passing in the string you want to format as the argument. For example,
//! here’s how to get some red text:
//!
//! ```
-//! use ansi_term::Colour::Red;
+//! use nu_ansi_term::Color::Red;
//!
//! println!("This is in red: {}", Red.paint("a red string"));
//! ```
//!
//! It’s important to note that the `paint` method does *not* actually return a
//! string with the ANSI control characters surrounding it. Instead, it returns
-//! an [`ANSIString`] value that has a [`Display`] implementation that, when
+//! an [`AnsiString`] value that has a [`Display`] implementation that, when
//! formatted, returns the characters. This allows strings to be printed with a
//! minimum of [`String`] allocations being performed behind the scenes.
//!
//! If you *do* want to get at the escape codes, then you can convert the
-//! [`ANSIString`] to a string as you would any other `Display` value:
+//! [`AnsiString`] to a string as you would any other `Display` value:
//!
//! ```
-//! use ansi_term::Colour::Red;
+//! use nu_ansi_term::Color::Red;
//!
//! let red_string = Red.paint("a red string").to_string();
//! ```
@@ -42,26 +42,26 @@
//!
//! ## Bold, underline, background, and other styles
//!
-//! For anything more complex than plain foreground colour changes, you need to
-//! construct `Style` values themselves, rather than beginning with a `Colour`.
+//! For anything more complex than plain foreground color changes, you need to
+//! construct `Style` values themselves, rather than beginning with a `Color`.
//! You can do this by chaining methods based on a new `Style`, created with
//! [`Style::new()`]. Each method creates a new style that has that specific
//! property set. For example:
//!
//! ```
-//! use ansi_term::Style;
+//! use nu_ansi_term::Style;
//!
//! println!("How about some {} and {}?",
//! Style::new().bold().paint("bold"),
//! Style::new().underline().paint("underline"));
//! ```
//!
-//! For brevity, these methods have also been implemented for `Colour` values,
-//! so you can give your styles a foreground colour without having to begin with
+//! For brevity, these methods have also been implemented for `Color` values,
+//! so you can give your styles a foreground color without having to begin with
//! an empty `Style` value:
//!
//! ```
-//! use ansi_term::Colour::{Blue, Yellow};
+//! use nu_ansi_term::Color::{Blue, Yellow};
//!
//! println!("Demonstrating {} and {}!",
//! Blue.bold().paint("blue bold"),
@@ -72,68 +72,68 @@
//!
//! The complete list of styles you can use are: [`bold`], [`dimmed`], [`italic`],
//! [`underline`], [`blink`], [`reverse`], [`hidden`], [`strikethrough`], and [`on`] for
-//! background colours.
+//! background colors.
//!
//! In some cases, you may find it easier to change the foreground on an
-//! existing `Style` rather than starting from the appropriate `Colour`.
+//! existing `Style` rather than starting from the appropriate `Color`.
//! You can do this using the [`fg`] method:
//!
//! ```
-//! use ansi_term::Style;
-//! use ansi_term::Colour::{Blue, Cyan, Yellow};
+//! use nu_ansi_term::Style;
+//! use nu_ansi_term::Color::{Blue, Cyan, Yellow};
//!
//! println!("Yellow on blue: {}", Style::new().on(Blue).fg(Yellow).paint("yow!"));
//! println!("Also yellow on blue: {}", Cyan.on(Blue).fg(Yellow).paint("zow!"));
//! ```
//!
-//! You can turn a `Colour` into a `Style` with the [`normal`] method.
-//! This will produce the exact same `ANSIString` as if you just used the
-//! `paint` method on the `Colour` directly, but it’s useful in certain cases:
+//! You can turn a `Color` into a `Style` with the [`normal`] method.
+//! This will produce the exact same `AnsiString` as if you just used the
+//! `paint` method on the `Color` directly, but it’s useful in certain cases:
//! for example, you may have a method that returns `Styles`, and need to
//! represent both the “red bold” and “red, but not bold” styles with values of
//! the same type. The `Style` struct also has a [`Default`] implementation if you
//! want to have a style with *nothing* set.
//!
//! ```
-//! use ansi_term::Style;
-//! use ansi_term::Colour::Red;
+//! use nu_ansi_term::Style;
+//! use nu_ansi_term::Color::Red;
//!
//! Red.normal().paint("yet another red string");
//! Style::default().paint("a completely regular string");
//! ```
//!
//!
-//! ## Extended colours
+//! ## Extended colors
//!
-//! You can access the extended range of 256 colours by using the `Colour::Fixed`
-//! variant, which takes an argument of the colour number to use. This can be
-//! included wherever you would use a `Colour`:
+//! You can access the extended range of 256 colors by using the `Color::Fixed`
+//! variant, which takes an argument of the color number to use. This can be
+//! included wherever you would use a `Color`:
//!
//! ```
-//! use ansi_term::Colour::Fixed;
+//! use nu_ansi_term::Color::Fixed;
//!
//! Fixed(134).paint("A sort of light purple");
//! Fixed(221).on(Fixed(124)).paint("Mustard in the ketchup");
//! ```
//!
//! The first sixteen of these values are the same as the normal and bold
-//! standard colour variants. There’s nothing stopping you from using these as
-//! `Fixed` colours instead, but there’s nothing to be gained by doing so
+//! standard color variants. There’s nothing stopping you from using these as
+//! `Fixed` colors instead, but there’s nothing to be gained by doing so
//! either.
//!
-//! You can also access full 24-bit colour by using the `Colour::RGB` variant,
+//! You can also access full 24-bit color by using the `Color::Rgb` variant,
//! which takes separate `u8` arguments for red, green, and blue:
//!
//! ```
-//! use ansi_term::Colour::RGB;
+//! use nu_ansi_term::Color::Rgb;
//!
-//! RGB(70, 130, 180).paint("Steel blue");
+//! Rgb(70, 130, 180).paint("Steel blue");
//! ```
//!
-//! ## Combining successive coloured strings
+//! ## Combining successive colored strings
//!
//! The benefit of writing ANSI escape codes to the terminal is that they
-//! *stack*: you do not need to end every coloured string with a reset code if
+//! *stack*: you do not need to end every colored string with a reset code if
//! the text that follows it is of a similar style. For example, if you want to
//! have some blue text followed by some blue bold text, it’s possible to send
//! the ANSI code for blue, followed by the ANSI code for bold, and finishing
@@ -141,8 +141,8 @@
//! strings.
//!
//! This crate can optimise the ANSI codes that get printed in situations like
-//! this, making life easier for your terminal renderer. The [`ANSIStrings`]
-//! type takes a slice of several [`ANSIString`] values, and will iterate over
+//! this, making life easier for your terminal renderer. The [`AnsiStrings`]
+//! type takes a slice of several [`AnsiString`] values, and will iterate over
//! each of them, printing only the codes for the styles that need to be updated
//! as part of its formatting routine.
//!
@@ -150,25 +150,25 @@
//! red bold text inside some red, but not bold, brackets:
//!
//! ```
-//! use ansi_term::Colour::Red;
-//! use ansi_term::{ANSIString, ANSIStrings};
+//! use nu_ansi_term::Color::Red;
+//! use nu_ansi_term::{AnsiString, AnsiStrings};
//!
//! let some_value = format!("{:b}", 42);
-//! let strings: &[ANSIString<'static>] = &[
+//! let strings: &[AnsiString<'static>] = &[
//! Red.paint("["),
//! Red.bold().paint(some_value),
//! Red.paint("]"),
//! ];
//!
-//! println!("Value: {}", ANSIStrings(strings));
+//! println!("Value: {}", AnsiStrings(strings));
//! ```
//!
//! There are several things to note here. Firstly, the [`paint`] method can take
-//! *either* an owned [`String`] or a borrowed [`&str`]. Internally, an [`ANSIString`]
+//! *either* an owned [`String`] or a borrowed [`&str`]. Internally, an [`AnsiString`]
//! holds a copy-on-write ([`Cow`]) string value to deal with both owned and
//! borrowed strings at the same time. This is used here to display a `String`,
//! the result of the `format!` call, using the same mechanism as some
-//! statically-available `&str` slices. Secondly, that the [`ANSIStrings`] value
+//! statically-available `&str` slices. Secondly, that the [`AnsiStrings`] value
//! works in the same way as its singular counterpart, with a [`Display`]
//! implementation that only performs the formatting when required.
//!
@@ -176,25 +176,25 @@
//!
//! This library also supports formatting `\[u8]` byte strings; this supports
//! applications working with text in an unknown encoding. [`Style`] and
-//! [`Colour`] support painting `\[u8]` values, resulting in an [`ANSIByteString`].
+//! [`Color`] support painting `\[u8]` values, resulting in an [`AnsiByteString`].
//! This type does not implement [`Display`], as it may not contain UTF-8, but
//! it does provide a method [`write_to`] to write the result to any value that
//! implements [`Write`]:
//!
//! ```
-//! use ansi_term::Colour::Green;
+//! use nu_ansi_term::Color::Green;
//!
//! Green.paint("user data".as_bytes()).write_to(&mut std::io::stdout()).unwrap();
//! ```
//!
-//! Similarly, the type [`ANSIByteStrings`] supports writing a list of
-//! [`ANSIByteString`] values with minimal escape sequences:
+//! Similarly, the type [`AnsiByteStrings`] supports writing a list of
+//! [`AnsiByteString`] values with minimal escape sequences:
//!
//! ```
-//! use ansi_term::Colour::Green;
-//! use ansi_term::ANSIByteStrings;
+//! use nu_ansi_term::Color::Green;
+//! use nu_ansi_term::AnsiByteStrings;
//!
-//! ANSIByteStrings(&[
+//! AnsiByteStrings(&[
//! Green.paint("user data 1\n".as_bytes()),
//! Green.bold().paint("user data 2\n".as_bytes()),
//! ]).write_to(&mut std::io::stdout()).unwrap();
@@ -209,14 +209,14 @@
//! [`Style`]: struct.Style.html
//! [`Style::new()`]: struct.Style.html#method.new
//! [`Color`]: enum.Color.html
-//! [`Colour`]: enum.Colour.html
-//! [`ANSIString`]: type.ANSIString.html
-//! [`ANSIStrings`]: type.ANSIStrings.html
-//! [`ANSIByteString`]: type.ANSIByteString.html
-//! [`ANSIByteStrings`]: type.ANSIByteStrings.html
-//! [`write_to`]: type.ANSIByteString.html#method.write_to
-//! [`paint`]: type.ANSIByteString.html#method.write_to
-//! [`normal`]: enum.Colour.html#method.normal
+//! [`Color`]: enum.Color.html
+//! [`AnsiString`]: type.AnsiString.html
+//! [`AnsiStrings`]: type.AnsiStrings.html
+//! [`AnsiByteString`]: type.AnsiByteString.html
+//! [`AnsiByteStrings`]: type.AnsiByteStrings.html
+//! [`write_to`]: type.AnsiByteString.html#method.write_to
+//! [`paint`]: type.AnsiByteString.html#method.write_to
+//! [`normal`]: enum.Color.html#method.normal
//!
//! [`bold`]: struct.Style.html#method.bold
//! [`dimmed`]: struct.Style.html#method.dimmed
@@ -229,16 +229,14 @@
//! [`fg`]: struct.Style.html#method.fg
//! [`on`]: struct.Style.html#method.on
-#![crate_name = "ansi_term"]
+#![crate_name = "nu_ansi_term"]
#![crate_type = "rlib"]
-#![crate_type = "dylib"]
-
#![warn(missing_copy_implementations)]
-#![warn(missing_docs)]
+// #![warn(missing_docs)]
#![warn(trivial_casts, trivial_numeric_casts)]
-#![warn(unused_extern_crates, unused_qualifications)]
+// #![warn(unused_extern_crates, unused_qualifications)]
-#[cfg(target_os="windows")]
+#[cfg(target_os = "windows")]
extern crate winapi;
#[cfg(test)]
#[macro_use]
@@ -247,14 +245,11 @@ extern crate doc_comment;
#[cfg(test)]
doctest!("../README.md");
-mod ansi;
-pub use ansi::{Prefix, Infix, Suffix};
+pub mod ansi;
+pub use ansi::{Infix, Prefix, Suffix};
mod style;
-pub use style::{Colour, Style};
-
-/// Color is a type alias for `Colour`.
-pub use Colour as Color;
+pub use style::{Color, Style};
mod difference;
mod display;
@@ -269,3 +264,9 @@ mod util;
pub use util::*;
mod debug;
+
+pub mod gradient;
+pub use gradient::*;
+
+mod rgb;
+pub use rgb::*;
diff --git a/vendor/nu-ansi-term/src/rgb.rs b/vendor/nu-ansi-term/src/rgb.rs
new file mode 100644
index 000000000..19475c36b
--- /dev/null
+++ b/vendor/nu-ansi-term/src/rgb.rs
@@ -0,0 +1,173 @@
+// Code liberally borrowed from here
+// https://github.com/navierr/coloriz
+use std::ops;
+use std::u32;
+#[derive(Debug, Clone, Copy, PartialEq, Eq)]
+pub struct Rgb {
+ /// Red
+ pub r: u8,
+ /// Green
+ pub g: u8,
+ /// Blue
+ pub b: u8,
+}
+
+impl Rgb {
+ /// Creates a new [Rgb] color
+ #[inline]
+ pub const fn new(r: u8, g: u8, b: u8) -> Self {
+ Self { r, g, b }
+ }
+
+ /// Creates a new [Rgb] color with a hex code
+ #[inline]
+ pub const fn from_hex(hex: u32) -> Self {
+ Self::new((hex >> 16) as u8, (hex >> 8) as u8, hex as u8)
+ }
+
+ pub fn from_hex_string(hex: String) -> Self {
+ if hex.chars().count() == 8 && hex.starts_with("0x") {
+ // eprintln!("hex:{:?}", hex);
+ let (_, value_string) = hex.split_at(2);
+ // eprintln!("value_string:{:?}", value_string);
+ let int_val = u64::from_str_radix(value_string, 16);
+ match int_val {
+ Ok(num) => Self::new(
+ ((num & 0xff0000) >> 16) as u8,
+ ((num & 0xff00) >> 8) as u8,
+ (num & 0xff) as u8,
+ ),
+ // Don't fail, just make the color black
+ // Should we fail?
+ _ => Self::new(0, 0, 0),
+ }
+ } else {
+ // Don't fail, just make the color black.
+ // Should we fail?
+ Self::new(0, 0, 0)
+ }
+ }
+
+ /// Creates a new [Rgb] color with three [f32] values
+ pub fn from_f32(r: f32, g: f32, b: f32) -> Self {
+ Self::new(
+ (r.clamp(0.0, 1.0) * 255.0) as u8,
+ (g.clamp(0.0, 1.0) * 255.0) as u8,
+ (b.clamp(0.0, 1.0) * 255.0) as u8,
+ )
+ }
+
+ /// Creates a grayscale [Rgb] color
+ #[inline]
+ pub const fn gray(x: u8) -> Self {
+ Self::new(x, x, x)
+ }
+
+ /// Creates a grayscale [Rgb] color with a [f32] value
+ pub fn gray_f32(x: f32) -> Self {
+ Self::from_f32(x, x, x)
+ }
+
+ /// Creates a new [Rgb] color from a [HSL] color
+ // pub fn from_hsl(hsl: HSL) -> Self {
+ // if hsl.s == 0.0 {
+ // return Self::gray_f32(hsl.l);
+ // }
+
+ // let q = if hsl.l < 0.5 {
+ // hsl.l * (1.0 + hsl.s)
+ // } else {
+ // hsl.l + hsl.s - hsl.l * hsl.s
+ // };
+ // let p = 2.0 * hsl.l - q;
+ // let h2c = |t: f32| {
+ // let t = t.clamp(0.0, 1.0);
+ // if 6.0 * t < 1.0 {
+ // p + 6.0 * (q - p) * t
+ // } else if t < 0.5 {
+ // q
+ // } else if 1.0 < 1.5 * t {
+ // p + 6.0 * (q - p) * (1.0 / 1.5 - t)
+ // } else {
+ // p
+ // }
+ // };
+
+ // Self::from_f32(h2c(hsl.h + 1.0 / 3.0), h2c(hsl.h), h2c(hsl.h - 1.0 / 3.0))
+ // }
+
+ /// Computes the linear interpolation between `self` and `other` for `t`
+ pub fn lerp(&self, other: Self, t: f32) -> Self {
+ let t = t.clamp(0.0, 1.0);
+ self * (1.0 - t) + other * t
+ }
+}
+
+impl From<(u8, u8, u8)> for Rgb {
+ fn from((r, g, b): (u8, u8, u8)) -> Self {
+ Self::new(r, g, b)
+ }
+}
+
+impl From<(f32, f32, f32)> for Rgb {
+ fn from((r, g, b): (f32, f32, f32)) -> Self {
+ Self::from_f32(r, g, b)
+ }
+}
+
+use crate::ANSIColorCode;
+use crate::TargetGround;
+impl ANSIColorCode for Rgb {
+ fn ansi_color_code(&self, target: TargetGround) -> String {
+ format!("{};2;{};{};{}", target.code() + 8, self.r, self.g, self.b)
+ }
+}
+
+overload::overload!(
+ (lhs: ?Rgb) + (rhs: ?Rgb) -> Rgb {
+ Rgb::new(
+ lhs.r.saturating_add(rhs.r),
+ lhs.g.saturating_add(rhs.g),
+ lhs.b.saturating_add(rhs.b)
+ )
+ }
+);
+
+overload::overload!(
+ (lhs: ?Rgb) - (rhs: ?Rgb) -> Rgb {
+ Rgb::new(
+ lhs.r.saturating_sub(rhs.r),
+ lhs.g.saturating_sub(rhs.g),
+ lhs.b.saturating_sub(rhs.b)
+ )
+ }
+);
+
+overload::overload!(
+ (lhs: ?Rgb) * (rhs: ?f32) -> Rgb {
+ Rgb::new(
+ (lhs.r as f32 * rhs.clamp(0.0, 1.0)) as u8,
+ (lhs.g as f32 * rhs.clamp(0.0, 1.0)) as u8,
+ (lhs.b as f32 * rhs.clamp(0.0, 1.0)) as u8
+ )
+ }
+);
+
+overload::overload!(
+ (lhs: ?f32) * (rhs: ?Rgb) -> Rgb {
+ Rgb::new(
+ (rhs.r as f32 * lhs.clamp(0.0, 1.0)) as u8,
+ (rhs.g as f32 * lhs.clamp(0.0, 1.0)) as u8,
+ (rhs.b as f32 * lhs.clamp(0.0, 1.0)) as u8
+ )
+ }
+);
+
+overload::overload!(
+ -(rgb: ?Rgb) -> Rgb {
+ Rgb::new(
+ 255 - rgb.r,
+ 255 - rgb.g,
+ 255 - rgb.b)
+ }
+);
diff --git a/vendor/nu-ansi-term/src/style.rs b/vendor/nu-ansi-term/src/style.rs
new file mode 100644
index 000000000..3d47a79f7
--- /dev/null
+++ b/vendor/nu-ansi-term/src/style.rs
@@ -0,0 +1,629 @@
+/// A style is a collection of properties that can format a string
+/// using ANSI escape codes.
+///
+/// # Examples
+///
+/// ```
+/// use nu_ansi_term::{Style, Color};
+///
+/// let style = Style::new().bold().on(Color::Black);
+/// println!("{}", style.paint("Bold on black"));
+/// ```
+#[derive(PartialEq, Clone, Copy)]
+#[cfg_attr(
+ feature = "derive_serde_style",
+ derive(serde::Deserialize, serde::Serialize)
+)]
+pub struct Style {
+ /// The style's foreground color, if it has one.
+ pub foreground: Option<Color>,
+
+ /// The style's background color, if it has one.
+ pub background: Option<Color>,
+
+ /// Whether this style is bold.
+ pub is_bold: bool,
+
+ /// Whether this style is dimmed.
+ pub is_dimmed: bool,
+
+ /// Whether this style is italic.
+ pub is_italic: bool,
+
+ /// Whether this style is underlined.
+ pub is_underline: bool,
+
+ /// Whether this style is blinking.
+ pub is_blink: bool,
+
+ /// Whether this style has reverse colors.
+ pub is_reverse: bool,
+
+ /// Whether this style is hidden.
+ pub is_hidden: bool,
+
+ /// Whether this style is struckthrough.
+ pub is_strikethrough: bool,
+}
+
+impl Style {
+ /// Creates a new Style with no properties set.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use nu_ansi_term::Style;
+ ///
+ /// let style = Style::new();
+ /// println!("{}", style.paint("hi"));
+ /// ```
+ pub fn new() -> Style {
+ Style::default()
+ }
+
+ /// Returns a `Style` with the bold property set.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use nu_ansi_term::Style;
+ ///
+ /// let style = Style::new().bold();
+ /// println!("{}", style.paint("hey"));
+ /// ```
+ pub fn bold(&self) -> Style {
+ Style {
+ is_bold: true,
+ ..*self
+ }
+ }
+
+ /// Returns a `Style` with the dimmed property set.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use nu_ansi_term::Style;
+ ///
+ /// let style = Style::new().dimmed();
+ /// println!("{}", style.paint("sup"));
+ /// ```
+ pub fn dimmed(&self) -> Style {
+ Style {
+ is_dimmed: true,
+ ..*self
+ }
+ }
+
+ /// Returns a `Style` with the italic property set.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use nu_ansi_term::Style;
+ ///
+ /// let style = Style::new().italic();
+ /// println!("{}", style.paint("greetings"));
+ /// ```
+ pub fn italic(&self) -> Style {
+ Style {
+ is_italic: true,
+ ..*self
+ }
+ }
+
+ /// Returns a `Style` with the underline property set.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use nu_ansi_term::Style;
+ ///
+ /// let style = Style::new().underline();
+ /// println!("{}", style.paint("salutations"));
+ /// ```
+ pub fn underline(&self) -> Style {
+ Style {
+ is_underline: true,
+ ..*self
+ }
+ }
+
+ /// Returns a `Style` with the blink property set.
+ /// # Examples
+ ///
+ /// ```
+ /// use nu_ansi_term::Style;
+ ///
+ /// let style = Style::new().blink();
+ /// println!("{}", style.paint("wazzup"));
+ /// ```
+ pub fn blink(&self) -> Style {
+ Style {
+ is_blink: true,
+ ..*self
+ }
+ }
+
+ /// Returns a `Style` with the reverse property set.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use nu_ansi_term::Style;
+ ///
+ /// let style = Style::new().reverse();
+ /// println!("{}", style.paint("aloha"));
+ /// ```
+ pub fn reverse(&self) -> Style {
+ Style {
+ is_reverse: true,
+ ..*self
+ }
+ }
+
+ /// Returns a `Style` with the hidden property set.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use nu_ansi_term::Style;
+ ///
+ /// let style = Style::new().hidden();
+ /// println!("{}", style.paint("ahoy"));
+ /// ```
+ pub fn hidden(&self) -> Style {
+ Style {
+ is_hidden: true,
+ ..*self
+ }
+ }
+
+ /// Returns a `Style` with the strikethrough property set.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use nu_ansi_term::Style;
+ ///
+ /// let style = Style::new().strikethrough();
+ /// println!("{}", style.paint("yo"));
+ /// ```
+ pub fn strikethrough(&self) -> Style {
+ Style {
+ is_strikethrough: true,
+ ..*self
+ }
+ }
+
+ /// Returns a `Style` with the foreground color property set.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use nu_ansi_term::{Style, Color};
+ ///
+ /// let style = Style::new().fg(Color::Yellow);
+ /// println!("{}", style.paint("hi"));
+ /// ```
+ pub fn fg(&self, foreground: Color) -> Style {
+ Style {
+ foreground: Some(foreground),
+ ..*self
+ }
+ }
+
+ /// Returns a `Style` with the background color property set.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use nu_ansi_term::{Style, Color};
+ ///
+ /// let style = Style::new().on(Color::Blue);
+ /// println!("{}", style.paint("eyyyy"));
+ /// ```
+ pub fn on(&self, background: Color) -> Style {
+ Style {
+ background: Some(background),
+ ..*self
+ }
+ }
+
+ /// Return true if this `Style` has no actual styles, and can be written
+ /// without any control characters.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use nu_ansi_term::Style;
+ ///
+ /// assert_eq!(true, Style::default().is_plain());
+ /// assert_eq!(false, Style::default().bold().is_plain());
+ /// ```
+ pub fn is_plain(self) -> bool {
+ self == Style::default()
+ }
+}
+
+impl Default for Style {
+ /// Returns a style with *no* properties set. Formatting text using this
+ /// style returns the exact same text.
+ ///
+ /// ```
+ /// use nu_ansi_term::Style;
+ /// assert_eq!(None, Style::default().foreground);
+ /// assert_eq!(None, Style::default().background);
+ /// assert_eq!(false, Style::default().is_bold);
+ /// assert_eq!("txt", Style::default().paint("txt").to_string());
+ /// ```
+ fn default() -> Style {
+ Style {
+ foreground: None,
+ background: None,
+ is_bold: false,
+ is_dimmed: false,
+ is_italic: false,
+ is_underline: false,
+ is_blink: false,
+ is_reverse: false,
+ is_hidden: false,
+ is_strikethrough: false,
+ }
+ }
+}
+
+// ---- colors ----
+
+/// A color is one specific type of ANSI escape code, and can refer
+/// to either the foreground or background color.
+///
+/// These use the standard numeric sequences.
+/// See <http://invisible-island.net/xterm/ctlseqs/ctlseqs.html>
+#[derive(PartialEq, Clone, Copy, Debug)]
+#[cfg_attr(
+ feature = "derive_serde_style",
+ derive(serde::Deserialize, serde::Serialize)
+)]
+pub enum Color {
+ /// Color #0 (foreground code `30`, background code `40`).
+ ///
+ /// This is not necessarily the background color, and using it as one may
+ /// render the text hard to read on terminals with dark backgrounds.
+ Black,
+
+ /// Color #0 (foreground code `90`, background code `100`).
+ DarkGray,
+
+ /// Color #1 (foreground code `31`, background code `41`).
+ Red,
+
+ /// Color #1 (foreground code `91`, background code `101`).
+ LightRed,
+
+ /// Color #2 (foreground code `32`, background code `42`).
+ Green,
+
+ /// Color #2 (foreground code `92`, background code `102`).
+ LightGreen,
+
+ /// Color #3 (foreground code `33`, background code `43`).
+ Yellow,
+
+ /// Color #3 (foreground code `93`, background code `103`).
+ LightYellow,
+
+ /// Color #4 (foreground code `34`, background code `44`).
+ Blue,
+
+ /// Color #4 (foreground code `94`, background code `104`).
+ LightBlue,
+
+ /// Color #5 (foreground code `35`, background code `45`).
+ Purple,
+
+ /// Color #5 (foreground code `95`, background code `105`).
+ LightPurple,
+
+ /// Color #5 (foreground code `35`, background code `45`).
+ Magenta,
+
+ /// Color #5 (foreground code `95`, background code `105`).
+ LightMagenta,
+
+ /// Color #6 (foreground code `36`, background code `46`).
+ Cyan,
+
+ /// Color #6 (foreground code `96`, background code `106`).
+ LightCyan,
+
+ /// Color #7 (foreground code `37`, background code `47`).
+ ///
+ /// As above, this is not necessarily the foreground color, and may be
+ /// hard to read on terminals with light backgrounds.
+ White,
+
+ /// Color #7 (foreground code `97`, background code `107`).
+ LightGray,
+
+ /// A color number from 0 to 255, for use in 256-color terminal
+ /// environments.
+ ///
+ /// - colors 0 to 7 are the `Black` to `White` variants respectively.
+ /// These colors can usually be changed in the terminal emulator.
+ /// - colors 8 to 15 are brighter versions of the eight colors above.
+ /// These can also usually be changed in the terminal emulator, or it
+ /// could be configured to use the original colors and show the text in
+ /// bold instead. It varies depending on the program.
+ /// - colors 16 to 231 contain several palettes of bright colors,
+ /// arranged in six squares measuring six by six each.
+ /// - colors 232 to 255 are shades of grey from black to white.
+ ///
+ /// It might make more sense to look at a [color chart][cc].
+ ///
+ /// [cc]: https://upload.wikimedia.org/wikipedia/commons/1/15/Xterm_256color_chart.svg
+ Fixed(u8),
+
+ /// A 24-bit Rgb color, as specified by ISO-8613-3.
+ Rgb(u8, u8, u8),
+
+ /// The default color (foreground code `39`, background codr `49`).
+ Default,
+}
+
+impl Default for Color {
+ fn default() -> Self {
+ Color::White
+ }
+}
+
+impl Color {
+ /// Returns a `Style` with the foreground color set to this color.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use nu_ansi_term::Color;
+ ///
+ /// let style = Color::Red.normal();
+ /// println!("{}", style.paint("hi"));
+ /// ```
+ pub fn normal(self) -> Style {
+ Style {
+ foreground: Some(self),
+ ..Style::default()
+ }
+ }
+
+ /// Returns a `Style` with the foreground color set to this color and the
+ /// bold property set.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use nu_ansi_term::Color;
+ ///
+ /// let style = Color::Green.bold();
+ /// println!("{}", style.paint("hey"));
+ /// ```
+ pub fn bold(self) -> Style {
+ Style {
+ foreground: Some(self),
+ is_bold: true,
+ ..Style::default()
+ }
+ }
+
+ /// Returns a `Style` with the foreground color set to this color and the
+ /// dimmed property set.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use nu_ansi_term::Color;
+ ///
+ /// let style = Color::Yellow.dimmed();
+ /// println!("{}", style.paint("sup"));
+ /// ```
+ pub fn dimmed(self) -> Style {
+ Style {
+ foreground: Some(self),
+ is_dimmed: true,
+ ..Style::default()
+ }
+ }
+
+ /// Returns a `Style` with the foreground color set to this color and the
+ /// italic property set.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use nu_ansi_term::Color;
+ ///
+ /// let style = Color::Blue.italic();
+ /// println!("{}", style.paint("greetings"));
+ /// ```
+ pub fn italic(self) -> Style {
+ Style {
+ foreground: Some(self),
+ is_italic: true,
+ ..Style::default()
+ }
+ }
+
+ /// Returns a `Style` with the foreground color set to this color and the
+ /// underline property set.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use nu_ansi_term::Color;
+ ///
+ /// let style = Color::Purple.underline();
+ /// println!("{}", style.paint("salutations"));
+ /// ```
+ pub fn underline(self) -> Style {
+ Style {
+ foreground: Some(self),
+ is_underline: true,
+ ..Style::default()
+ }
+ }
+
+ /// Returns a `Style` with the foreground color set to this color and the
+ /// blink property set.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use nu_ansi_term::Color;
+ ///
+ /// let style = Color::Cyan.blink();
+ /// println!("{}", style.paint("wazzup"));
+ /// ```
+ pub fn blink(self) -> Style {
+ Style {
+ foreground: Some(self),
+ is_blink: true,
+ ..Style::default()
+ }
+ }
+
+ /// Returns a `Style` with the foreground color set to this color and the
+ /// reverse property set.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use nu_ansi_term::Color;
+ ///
+ /// let style = Color::Black.reverse();
+ /// println!("{}", style.paint("aloha"));
+ /// ```
+ pub fn reverse(self) -> Style {
+ Style {
+ foreground: Some(self),
+ is_reverse: true,
+ ..Style::default()
+ }
+ }
+
+ /// Returns a `Style` with the foreground color set to this color and the
+ /// hidden property set.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use nu_ansi_term::Color;
+ ///
+ /// let style = Color::White.hidden();
+ /// println!("{}", style.paint("ahoy"));
+ /// ```
+ pub fn hidden(self) -> Style {
+ Style {
+ foreground: Some(self),
+ is_hidden: true,
+ ..Style::default()
+ }
+ }
+
+ /// Returns a `Style` with the foreground color set to this color and the
+ /// strikethrough property set.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use nu_ansi_term::Color;
+ ///
+ /// let style = Color::Fixed(244).strikethrough();
+ /// println!("{}", style.paint("yo"));
+ /// ```
+ pub fn strikethrough(self) -> Style {
+ Style {
+ foreground: Some(self),
+ is_strikethrough: true,
+ ..Style::default()
+ }
+ }
+
+ /// Returns a `Style` with the foreground color set to this color and the
+ /// background color property set to the given color.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use nu_ansi_term::Color;
+ ///
+ /// let style = Color::Rgb(31, 31, 31).on(Color::White);
+ /// println!("{}", style.paint("eyyyy"));
+ /// ```
+ pub fn on(self, background: Color) -> Style {
+ Style {
+ foreground: Some(self),
+ background: Some(background),
+ ..Style::default()
+ }
+ }
+}
+
+impl From<Color> for Style {
+ /// You can turn a `Color` into a `Style` with the foreground color set
+ /// with the `From` trait.
+ ///
+ /// ```
+ /// use nu_ansi_term::{Style, Color};
+ /// let green_foreground = Style::default().fg(Color::Green);
+ /// assert_eq!(green_foreground, Color::Green.normal());
+ /// assert_eq!(green_foreground, Color::Green.into());
+ /// assert_eq!(green_foreground, Style::from(Color::Green));
+ /// ```
+ fn from(color: Color) -> Style {
+ color.normal()
+ }
+}
+
+#[cfg(test)]
+#[cfg(feature = "derive_serde_style")]
+mod serde_json_tests {
+ use super::{Color, Style};
+
+ #[test]
+ fn color_serialization() {
+ let colors = &[
+ Color::Red,
+ Color::Blue,
+ Color::Rgb(123, 123, 123),
+ Color::Fixed(255),
+ ];
+
+ assert_eq!(
+ serde_json::to_string(&colors).unwrap(),
+ String::from("[\"Red\",\"Blue\",{\"Rgb\":[123,123,123]},{\"Fixed\":255}]")
+ );
+ }
+
+ #[test]
+ fn color_deserialization() {
+ let colors = [
+ Color::Red,
+ Color::Blue,
+ Color::Rgb(123, 123, 123),
+ Color::Fixed(255),
+ ];
+
+ for color in colors {
+ let serialized = serde_json::to_string(&color).unwrap();
+ let deserialized: Color = serde_json::from_str(&serialized).unwrap();
+
+ assert_eq!(color, deserialized);
+ }
+ }
+
+ #[test]
+ fn style_serialization() {
+ let style = Style::default();
+
+ assert_eq!(serde_json::to_string(&style).unwrap(), "{\"foreground\":null,\"background\":null,\"is_bold\":false,\"is_dimmed\":false,\"is_italic\":false,\"is_underline\":false,\"is_blink\":false,\"is_reverse\":false,\"is_hidden\":false,\"is_strikethrough\":false}".to_string());
+ }
+}
diff --git a/vendor/ansi_term/src/util.rs b/vendor/nu-ansi-term/src/util.rs
index ba0f12a02..a35020137 100644
--- a/vendor/ansi_term/src/util.rs
+++ b/vendor/nu-ansi-term/src/util.rs
@@ -1,27 +1,30 @@
-use display::*;
+use crate::display::{AnsiString, AnsiStrings};
use std::ops::Deref;
-/// Return a substring of the given ANSIStrings sequence, while keeping the formatting.
-pub fn sub_string<'a>(start: usize, len: usize, strs: &ANSIStrings<'a>) -> Vec<ANSIString<'static>> {
+/// Return a substring of the given AnsiStrings sequence, while keeping the formatting.
+pub fn sub_string<'a>(
+ start: usize,
+ len: usize,
+ strs: &AnsiStrings<'a>,
+) -> Vec<AnsiString<'static>> {
let mut vec = Vec::new();
let mut pos = start;
let mut len_rem = len;
for i in strs.0.iter() {
- let fragment = i.deref();
- let frag_len = fragment.len();
+ let frag_len = i.string.len();
if pos >= frag_len {
pos -= frag_len;
continue;
}
- if len_rem <= 0 {
+ if len_rem == 0 {
break;
}
let end = pos + len_rem;
let pos_end = if end >= frag_len { frag_len } else { end };
- vec.push(i.style_ref().paint(String::from(&fragment[pos..pos_end])));
+ vec.push(i.style_ref().paint(String::from(&i.string[pos..pos_end])));
if end <= frag_len {
break;
@@ -35,30 +38,29 @@ pub fn sub_string<'a>(start: usize, len: usize, strs: &ANSIStrings<'a>) -> Vec<A
}
/// Return a concatenated copy of `strs` without the formatting, as an allocated `String`.
-pub fn unstyle(strs: &ANSIStrings) -> String {
+pub fn unstyle(strs: &AnsiStrings) -> String {
let mut s = String::new();
for i in strs.0.iter() {
- s += &i.deref();
+ s += i.string.deref();
}
s
}
-/// Return the unstyled length of ANSIStrings. This is equaivalent to `unstyle(strs).len()`.
-pub fn unstyled_len(strs: &ANSIStrings) -> usize {
+/// Return the unstyled length of AnsiStrings. This is equaivalent to `unstyle(strs).len()`.
+pub fn unstyled_len(strs: &AnsiStrings) -> usize {
let mut l = 0;
for i in strs.0.iter() {
- l += i.deref().len();
+ l += i.string.len();
}
l
}
#[cfg(test)]
mod test {
- use Colour::*;
- use display::*;
use super::*;
+ use crate::Color::*;
#[test]
fn test() {
@@ -67,15 +69,11 @@ mod test {
Red.paint("-second"),
White.paint("-third"),
];
- let a = ANSIStrings(&l);
+ let a = AnsiStrings(&l);
assert_eq!(unstyle(&a), "first-second-third");
assert_eq!(unstyled_len(&a), 18);
- let l2 = [
- Black.paint("st"),
- Red.paint("-second"),
- White.paint("-t"),
- ];
- assert_eq!(sub_string(3, 11, &a).as_slice(), &l2);
+ let l2 = [Black.paint("st"), Red.paint("-second"), White.paint("-t")];
+ assert_eq!(sub_string(3, 11, &a), l2);
}
}
diff --git a/vendor/ansi_term/src/windows.rs b/vendor/nu-ansi-term/src/windows.rs
index fcf02ecf6..828e35573 100644
--- a/vendor/ansi_term/src/windows.rs
+++ b/vendor/nu-ansi-term/src/windows.rs
@@ -25,7 +25,8 @@ pub fn enable_ansi_support() -> Result<(), u32> {
unsafe {
// ref: https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-createfilew
// Using `CreateFileW("CONOUT$", ...)` to retrieve the console handle works correctly even if STDOUT and/or STDERR are redirected
- let console_out_name: Vec<u16> = OsStr::new("CONOUT$").encode_wide().chain(once(0)).collect();
+ let console_out_name: Vec<u16> =
+ OsStr::new("CONOUT$").encode_wide().chain(once(0)).collect();
let console_handle = CreateFileW(
console_out_name.as_ptr(),
GENERIC_READ | GENERIC_WRITE,
@@ -35,27 +36,27 @@ pub fn enable_ansi_support() -> Result<(), u32> {
0,
null_mut(),
);
- if console_handle == INVALID_HANDLE_VALUE
- {
+ if console_handle == INVALID_HANDLE_VALUE {
return Err(GetLastError());
}
// ref: https://docs.microsoft.com/en-us/windows/console/getconsolemode
let mut console_mode: u32 = 0;
- if 0 == GetConsoleMode(console_handle, &mut console_mode)
- {
+ if 0 == GetConsoleMode(console_handle, &mut console_mode) {
return Err(GetLastError());
}
// VT processing not already enabled?
if console_mode & ENABLE_VIRTUAL_TERMINAL_PROCESSING == 0 {
// https://docs.microsoft.com/en-us/windows/console/setconsolemode
- if 0 == SetConsoleMode(console_handle, console_mode | ENABLE_VIRTUAL_TERMINAL_PROCESSING)
- {
+ if 0 == SetConsoleMode(
+ console_handle,
+ console_mode | ENABLE_VIRTUAL_TERMINAL_PROCESSING,
+ ) {
return Err(GetLastError());
}
}
}
- return Ok(());
+ Ok(())
}
diff --git a/vendor/ansi_term/src/write.rs b/vendor/nu-ansi-term/src/write.rs
index 65a64feb2..552771918 100644
--- a/vendor/ansi_term/src/write.rs
+++ b/vendor/nu-ansi-term/src/write.rs
@@ -1,40 +1,37 @@
use std::fmt;
use std::io;
-
pub trait AnyWrite {
- type wstr: ?Sized;
+ type Wstr: ?Sized;
type Error;
fn write_fmt(&mut self, fmt: fmt::Arguments) -> Result<(), Self::Error>;
- fn write_str(&mut self, s: &Self::wstr) -> Result<(), Self::Error>;
+ fn write_str(&mut self, s: &Self::Wstr) -> Result<(), Self::Error>;
}
-
-impl<'a> AnyWrite for fmt::Write + 'a {
- type wstr = str;
+impl<'a> AnyWrite for dyn fmt::Write + 'a {
+ type Wstr = str;
type Error = fmt::Error;
fn write_fmt(&mut self, fmt: fmt::Arguments) -> Result<(), Self::Error> {
fmt::Write::write_fmt(self, fmt)
}
- fn write_str(&mut self, s: &Self::wstr) -> Result<(), Self::Error> {
+ fn write_str(&mut self, s: &Self::Wstr) -> Result<(), Self::Error> {
fmt::Write::write_str(self, s)
}
}
-
-impl<'a> AnyWrite for io::Write + 'a {
- type wstr = [u8];
+impl<'a> AnyWrite for dyn io::Write + 'a {
+ type Wstr = [u8];
type Error = io::Error;
fn write_fmt(&mut self, fmt: fmt::Arguments) -> Result<(), Self::Error> {
io::Write::write_fmt(self, fmt)
}
- fn write_str(&mut self, s: &Self::wstr) -> Result<(), Self::Error> {
+ fn write_str(&mut self, s: &Self::Wstr) -> Result<(), Self::Error> {
io::Write::write_all(self, s)
}
}
diff --git a/vendor/num_cpus/.cargo-checksum.json b/vendor/num_cpus/.cargo-checksum.json
index e101b17c3..496119d1d 100644
--- a/vendor/num_cpus/.cargo-checksum.json
+++ b/vendor/num_cpus/.cargo-checksum.json
@@ -1 +1 @@
-{"files":{"CHANGELOG.md":"1b01434272c7e464f187eedc95522d9f5668f7f423459572fd33cd8eb5c4c5cf","CONTRIBUTING.md":"2390961aab1bba026135338da1216b6cc828dfaeed9357d9c155c55a252d3efb","Cargo.lock":"dabfb21d5ed9cefaf28e1fcbcaf253de08807ca3be33d0de4b06bb7a377d7b60","Cargo.toml":"885f8ecc8197bec06e151fde7769dc7c267d2f25a4b573240463e8a40a5be298","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"0593d22d122d4bfec6407115e3907546312976f75473417aaa4c57ecd2095ae6","README.md":"7760d315d3efd2306affa4c8e4dcdb3a245ae30b3c9cfb9cffed2f1116c86362","ci/cgroups/Dockerfile":"567f00918a6422b363e2c21e57bd47cef9dcc03d0ab109c9605e052f83af7e89","examples/values.rs":"46c833324b7339d359054c4f8e8284259e860df206c552c63b5893ade59c16a6","fixtures/cgroups/cgroups/ceil/cpu.cfs_period_us":"d2ace393dc9388863d75d8de140df516d7ffe4aa7ed2f9a545aa71c9930d6638","fixtures/cgroups/cgroups/ceil/cpu.cfs_quota_us":"7ccd86cde0b22ffc2318f2509726d2a13053f6973e96dc5ca6965a56497e485e","fixtures/cgroups/cgroups/good/cpu.cfs_period_us":"d2ace393dc9388863d75d8de140df516d7ffe4aa7ed2f9a545aa71c9930d6638","fixtures/cgroups/cgroups/good/cpu.cfs_quota_us":"cdc3397c35d915e5fe61f8d2bdedcae00a225d55cc6b090580cde1b71c63463b","fixtures/cgroups/cgroups/zero-period/cpu.cfs_period_us":"74d01a0c051c963d9a9b8ab9dbeab1723f0ad8534ea9fa6a942f358d7fa011b4","fixtures/cgroups/cgroups/zero-period/cpu.cfs_quota_us":"1e6ffd8a95fab538ddd645a767e8cc505722d5c8aaf008969f2ed8ab753ff61e","fixtures/cgroups/proc/cgroups/cgroup":"6812299a4409bfd831ed751fdbbfdd9c5749f69acd7b14c5b0a704271a1f74c6","fixtures/cgroups/proc/cgroups/mountinfo":"3187b0b1c0fa192790abced7d435190e8979059186055688e4c3c2ca013398c6","fixtures/cgroups/proc/cgroups/mountinfo_multi_opt":"d1e397752bc5c4558a3230ad847e89c6885362eab68a53b08dbf219de2e0138a","fixtures/cgroups/proc/cgroups/mountinfo_zero_opt":"91b03b270c76460bc19225aa4b743f893c7d32173e9609ef77e5a04814ab81ff","src/lib.rs":"81fc237964757a53689db848b1df4fed75bbd6a6e7a9063b6bb008161f8c22af","src/linux.rs":"a453e1056c130beaa7e2338222d04b5d3786f6325f5ca314ce9f4130079add2f"},"package":"19e64526ebdee182341572e50e9ad03965aa510cd94427a4549448f285e957a1"} \ No newline at end of file
+{"files":{"CHANGELOG.md":"66c7e8dedaa631c5e8d189b896efb691a97529358a56ad78282fbd4cbae3c638","CONTRIBUTING.md":"2390961aab1bba026135338da1216b6cc828dfaeed9357d9c155c55a252d3efb","Cargo.lock":"5a782f53bfc63c9ef7a901472c8ae3599d3f5ecb6f8bb9ce871235b4d9c8bfc1","Cargo.toml":"7a8fa6033b28607f305e144269902dc62c082cf02f76780fcce866810fcf931b","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"0593d22d122d4bfec6407115e3907546312976f75473417aaa4c57ecd2095ae6","README.md":"7760d315d3efd2306affa4c8e4dcdb3a245ae30b3c9cfb9cffed2f1116c86362","ci/cgroups/Dockerfile":"567f00918a6422b363e2c21e57bd47cef9dcc03d0ab109c9605e052f83af7e89","examples/values.rs":"46c833324b7339d359054c4f8e8284259e860df206c552c63b5893ade59c16a6","fixtures/cgroups/cgroups/ceil/cpu.cfs_period_us":"d2ace393dc9388863d75d8de140df516d7ffe4aa7ed2f9a545aa71c9930d6638","fixtures/cgroups/cgroups/ceil/cpu.cfs_quota_us":"7ccd86cde0b22ffc2318f2509726d2a13053f6973e96dc5ca6965a56497e485e","fixtures/cgroups/cgroups/good/cpu.cfs_period_us":"d2ace393dc9388863d75d8de140df516d7ffe4aa7ed2f9a545aa71c9930d6638","fixtures/cgroups/cgroups/good/cpu.cfs_quota_us":"cdc3397c35d915e5fe61f8d2bdedcae00a225d55cc6b090580cde1b71c63463b","fixtures/cgroups/cgroups/zero-period/cpu.cfs_period_us":"74d01a0c051c963d9a9b8ab9dbeab1723f0ad8534ea9fa6a942f358d7fa011b4","fixtures/cgroups/cgroups/zero-period/cpu.cfs_quota_us":"1e6ffd8a95fab538ddd645a767e8cc505722d5c8aaf008969f2ed8ab753ff61e","fixtures/cgroups/proc/cgroups/cgroup":"6812299a4409bfd831ed751fdbbfdd9c5749f69acd7b14c5b0a704271a1f74c6","fixtures/cgroups/proc/cgroups/mountinfo":"3187b0b1c0fa192790abced7d435190e8979059186055688e4c3c2ca013398c6","fixtures/cgroups/proc/cgroups/mountinfo_multi_opt":"d1e397752bc5c4558a3230ad847e89c6885362eab68a53b08dbf219de2e0138a","fixtures/cgroups/proc/cgroups/mountinfo_zero_opt":"91b03b270c76460bc19225aa4b743f893c7d32173e9609ef77e5a04814ab81ff","fixtures/cgroups2/cgroups/ceil/cpu.max":"d6eb496d0851963c9e6a9cf33c0a3ef2f08cbbee2a387c093b30ceca23239226","fixtures/cgroups2/cgroups/good/cpu.max":"2f8bd783be33cf80b6a2a0cf810f81ccf85f988c72c9bb76fa6172b6e4ec2b02","fixtures/cgroups2/cgroups/zero-period/cpu.max":"f42f2771a5f669873e0f45400ff64c481618029fe14a5bcb15d51b426646a9aa","fixtures/cgroups2/proc/cgroups/cgroup":"f8327c16331cc79ecbf875bd7bea6cf1831757589c39e16a149bfb3b6f81f7c8","fixtures/cgroups2/proc/cgroups/cgroup_multi":"96e107b552b1f51a8e96199c12e42dc3807e207d5a1be4a901f49db8e23ed869","fixtures/cgroups2/proc/cgroups/mountinfo":"7ac8cda160d4d80de73195fda560b46ed3826f43ef07fb513308549b32b08b56","src/lib.rs":"81fc237964757a53689db848b1df4fed75bbd6a6e7a9063b6bb008161f8c22af","src/linux.rs":"378ea174d00d560e16fda4b09fb523dda5f4c6f420e46af7d317393a39d88dd1"},"package":"0fac9e2da13b5eb447a6ce3d392f23a29d8694bff781bf03a16cd9ac8697593b"} \ No newline at end of file
diff --git a/vendor/num_cpus/CHANGELOG.md b/vendor/num_cpus/CHANGELOG.md
index 5496ace25..5be725c54 100644
--- a/vendor/num_cpus/CHANGELOG.md
+++ b/vendor/num_cpus/CHANGELOG.md
@@ -1,3 +1,16 @@
+## v1.15.0
+
+### Fixes
+
+- update hermit-abi
+
+## v1.14.0
+
+### Features
+
+- add support for cgroups v2
+- Skip reading files in Miri
+
## v1.13.1
### Fixes
diff --git a/vendor/num_cpus/Cargo.lock b/vendor/num_cpus/Cargo.lock
index 93137c3ea..1e955390a 100644
--- a/vendor/num_cpus/Cargo.lock
+++ b/vendor/num_cpus/Cargo.lock
@@ -4,9 +4,9 @@ version = 3
[[package]]
name = "hermit-abi"
-version = "0.1.3"
+version = "0.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "307c3c9f937f38e3534b1d6447ecf090cafcc9744e4a6360e8b037b2cf5af120"
+checksum = "ee512640fe35acbfb4bb779db6f0d80704c2cacfa2e39b601ef3e3f47d1ae4c7"
dependencies = [
"libc",
]
@@ -19,7 +19,7 @@ checksum = "1a31a0627fdf1f6a39ec0dd577e101440b7db22672c0901fe00a9a6fbb5c24e8"
[[package]]
name = "num_cpus"
-version = "1.13.1"
+version = "1.15.0"
dependencies = [
"hermit-abi",
"libc",
diff --git a/vendor/num_cpus/Cargo.toml b/vendor/num_cpus/Cargo.toml
index f708cc878..6d62e8626 100644
--- a/vendor/num_cpus/Cargo.toml
+++ b/vendor/num_cpus/Cargo.toml
@@ -11,16 +11,22 @@
[package]
name = "num_cpus"
-version = "1.13.1"
+version = "1.15.0"
authors = ["Sean McArthur <sean@seanmonstar.com>"]
description = "Get the number of CPUs on a machine."
documentation = "https://docs.rs/num_cpus"
readme = "README.md"
-keywords = ["cpu", "cpus", "cores"]
+keywords = [
+ "cpu",
+ "cpus",
+ "cores",
+]
categories = ["hardware-support"]
license = "MIT OR Apache-2.0"
repository = "https://github.com/seanmonstar/num_cpus"
+
[target."cfg(all(any(target_arch = \"x86_64\", target_arch = \"aarch64\"), target_os = \"hermit\"))".dependencies.hermit-abi]
-version = "0.1.3"
+version = "0.2.6"
+
[target."cfg(not(windows))".dependencies.libc]
version = "0.2.26"
diff --git a/vendor/num_cpus/fixtures/cgroups2/cgroups/ceil/cpu.max b/vendor/num_cpus/fixtures/cgroups2/cgroups/ceil/cpu.max
new file mode 100644
index 000000000..833a8f2d3
--- /dev/null
+++ b/vendor/num_cpus/fixtures/cgroups2/cgroups/ceil/cpu.max
@@ -0,0 +1 @@
+150000 100000
diff --git a/vendor/num_cpus/fixtures/cgroups2/cgroups/good/cpu.max b/vendor/num_cpus/fixtures/cgroups2/cgroups/good/cpu.max
new file mode 100644
index 000000000..e469067a6
--- /dev/null
+++ b/vendor/num_cpus/fixtures/cgroups2/cgroups/good/cpu.max
@@ -0,0 +1 @@
+600000 100000
diff --git a/vendor/num_cpus/fixtures/cgroups2/cgroups/zero-period/cpu.max b/vendor/num_cpus/fixtures/cgroups2/cgroups/zero-period/cpu.max
new file mode 100644
index 000000000..24e757f51
--- /dev/null
+++ b/vendor/num_cpus/fixtures/cgroups2/cgroups/zero-period/cpu.max
@@ -0,0 +1 @@
+600000 0
diff --git a/vendor/num_cpus/fixtures/cgroups2/proc/cgroups/cgroup b/vendor/num_cpus/fixtures/cgroups2/proc/cgroups/cgroup
new file mode 100644
index 000000000..35b49db2c
--- /dev/null
+++ b/vendor/num_cpus/fixtures/cgroups2/proc/cgroups/cgroup
@@ -0,0 +1,2 @@
+12::/
+3::/user.slice
diff --git a/vendor/num_cpus/fixtures/cgroups2/proc/cgroups/cgroup_multi b/vendor/num_cpus/fixtures/cgroups2/proc/cgroups/cgroup_multi
new file mode 100644
index 000000000..1a9282a6e
--- /dev/null
+++ b/vendor/num_cpus/fixtures/cgroups2/proc/cgroups/cgroup_multi
@@ -0,0 +1,3 @@
+12::/
+11:cpu,cpuacct:/
+3::/user.slice
diff --git a/vendor/num_cpus/fixtures/cgroups2/proc/cgroups/mountinfo b/vendor/num_cpus/fixtures/cgroups2/proc/cgroups/mountinfo
new file mode 100644
index 000000000..da36e4102
--- /dev/null
+++ b/vendor/num_cpus/fixtures/cgroups2/proc/cgroups/mountinfo
@@ -0,0 +1,5 @@
+1 0 8:1 / / rw,noatime shared:1 - ext4 /dev/sda1 rw,errors=remount-ro,data=reordered
+2 1 0:1 / /dev rw,relatime shared:2 - devtmpfs udev rw,size=10240k,nr_inodes=16487629,mode=755
+3 1 0:2 / /proc rw,nosuid,nodev,noexec,relatime shared:3 - proc proc rw
+4 1 0:3 / /sys rw,nosuid,nodev,noexec,relatime shared:4 - sysfs sysfs rw
+5 4 0:4 / /sys/fs/cgroup rw,nosuid,nodev,noexec,relatime shared:5 - cgroup2 cgroup2 rw,nsdelegate,memory_recursiveprot
diff --git a/vendor/num_cpus/src/linux.rs b/vendor/num_cpus/src/linux.rs
index 36f472717..295c925fb 100644
--- a/vendor/num_cpus/src/linux.rs
+++ b/vendor/num_cpus/src/linux.rs
@@ -126,6 +126,11 @@ fn init_cgroups() {
// Should only be called once
debug_assert!(CGROUPS_CPUS.load(Ordering::SeqCst) == 0);
+ // Fails in Miri by default (cannot open files), and Miri does not have parallelism anyway.
+ if cfg!(miri) {
+ return;
+ }
+
if let Some(quota) = load_cgroups("/proc/self/cgroup", "/proc/self/mountinfo") {
if quota == 0 {
return;
@@ -144,27 +149,36 @@ where
P2: AsRef<Path>,
{
let subsys = some!(Subsys::load_cpu(cgroup_proc));
- let mntinfo = some!(MountInfo::load_cpu(mountinfo_proc));
+ let mntinfo = some!(MountInfo::load_cpu(mountinfo_proc, subsys.version));
let cgroup = some!(Cgroup::translate(mntinfo, subsys));
cgroup.cpu_quota()
}
+#[derive(Debug, Clone, Copy, PartialEq, Eq)]
+enum CgroupVersion {
+ V1,
+ V2,
+}
+
struct Cgroup {
+ version: CgroupVersion,
base: PathBuf,
}
struct MountInfo {
+ version: CgroupVersion,
root: String,
mount_point: String,
}
struct Subsys {
+ version: CgroupVersion,
base: String,
}
impl Cgroup {
- fn new(dir: PathBuf) -> Cgroup {
- Cgroup { base: dir }
+ fn new(version: CgroupVersion, dir: PathBuf) -> Cgroup {
+ Cgroup { version: version, base: dir }
}
fn translate(mntinfo: MountInfo, subsys: Subsys) -> Option<Cgroup> {
@@ -181,12 +195,14 @@ impl Cgroup {
// join(mp.MountPoint, relPath)
let mut path = PathBuf::from(mntinfo.mount_point);
path.push(rel_from_root);
- Some(Cgroup::new(path))
+ Some(Cgroup::new(mntinfo.version, path))
}
fn cpu_quota(&self) -> Option<usize> {
- let quota_us = some!(self.quota_us());
- let period_us = some!(self.period_us());
+ let (quota_us, period_us) = match self.version {
+ CgroupVersion::V1 => (some!(self.quota_us()), some!(self.period_us())),
+ CgroupVersion::V2 => some!(self.max()),
+ };
// protect against dividing by zero
if period_us == 0 {
@@ -207,25 +223,41 @@ impl Cgroup {
self.param("cpu.cfs_period_us")
}
+ fn max(&self) -> Option<(usize, usize)> {
+ let max = some!(self.raw_param("cpu.max"));
+ let mut max = some!(max.lines().next()).split(' ');
+
+ let quota = some!(max.next().and_then(|quota| quota.parse().ok()));
+ let period = some!(max.next().and_then(|period| period.parse().ok()));
+
+ Some((quota, period))
+ }
+
fn param(&self, param: &str) -> Option<usize> {
+ let buf = some!(self.raw_param(param));
+
+ buf.trim().parse().ok()
+ }
+
+ fn raw_param(&self, param: &str) -> Option<String> {
let mut file = some!(File::open(self.base.join(param)).ok());
let mut buf = String::new();
some!(file.read_to_string(&mut buf).ok());
- buf.trim().parse().ok()
+ Some(buf)
}
}
impl MountInfo {
- fn load_cpu<P: AsRef<Path>>(proc_path: P) -> Option<MountInfo> {
+ fn load_cpu<P: AsRef<Path>>(proc_path: P, version: CgroupVersion) -> Option<MountInfo> {
let file = some!(File::open(proc_path).ok());
let file = BufReader::new(file);
file.lines()
.filter_map(|result| result.ok())
.filter_map(MountInfo::parse_line)
- .next()
+ .find(|mount_info| mount_info.version == version)
}
fn parse_line(line: String) -> Option<MountInfo> {
@@ -247,19 +279,25 @@ impl MountInfo {
};
// 7 5 0:6 / /sys/fs/cgroup/cpu,cpuacct rw,nosuid,nodev,noexec,relatime shared:7 - <cgroup> cgroup rw,cpu,cpuacct
- if fields.next() != Some("cgroup") {
- return None;
- }
+ let version = match fields.next() {
+ Some("cgroup") => CgroupVersion::V1,
+ Some("cgroup2") => CgroupVersion::V2,
+ _ => return None,
+ };
- // 7 5 0:6 / /sys/fs/cgroup/cpu,cpuacct rw,nosuid,nodev,noexec,relatime shared:7 - cgroup cgroup <rw,cpu,cpuacct>
- let super_opts = some!(fields.nth(1));
+ // cgroups2 only has a single mount point
+ if version == CgroupVersion::V1 {
+ // 7 5 0:6 / /sys/fs/cgroup/cpu,cpuacct rw,nosuid,nodev,noexec,relatime shared:7 - cgroup cgroup <rw,cpu,cpuacct>
+ let super_opts = some!(fields.nth(1));
- // We only care about the 'cpu' option
- if !super_opts.split(',').any(|opt| opt == "cpu") {
- return None;
+ // We only care about the 'cpu' option
+ if !super_opts.split(',').any(|opt| opt == "cpu") {
+ return None;
+ }
}
Some(MountInfo {
+ version: version,
root: mnt_root.to_owned(),
mount_point: mnt_point.to_owned(),
})
@@ -274,7 +312,14 @@ impl Subsys {
file.lines()
.filter_map(|result| result.ok())
.filter_map(Subsys::parse_line)
- .next()
+ .fold(None, |previous, line| {
+ // already-found v1 trumps v2 since it explicitly specifies its controllers
+ if previous.is_some() && line.version == CgroupVersion::V2 {
+ return previous;
+ }
+
+ Some(line)
+ })
}
fn parse_line(line: String) -> Option<Subsys> {
@@ -284,11 +329,18 @@ impl Subsys {
let sub_systems = some!(fields.nth(1));
- if !sub_systems.split(',').any(|sub| sub == "cpu") {
+ let version = if sub_systems.is_empty() {
+ CgroupVersion::V2
+ } else {
+ CgroupVersion::V1
+ };
+
+ if version == CgroupVersion::V1 && !sub_systems.split(',').any(|sub| sub == "cpu") {
return None;
}
fields.next().map(|path| Subsys {
+ version: version,
base: path.to_owned(),
})
}
@@ -296,123 +348,248 @@ impl Subsys {
#[cfg(test)]
mod tests {
- use super::{Cgroup, MountInfo, Subsys};
- use std::path::{Path, PathBuf};
+ mod v1 {
+ use super::super::{Cgroup, CgroupVersion, MountInfo, Subsys};
+ use std::path::{Path, PathBuf};
- // `static_in_const` feature is not stable in Rust 1.13.
- static FIXTURES_PROC: &'static str = "fixtures/cgroups/proc/cgroups";
+ // `static_in_const` feature is not stable in Rust 1.13.
+ static FIXTURES_PROC: &'static str = "fixtures/cgroups/proc/cgroups";
- static FIXTURES_CGROUPS: &'static str = "fixtures/cgroups/cgroups";
+ static FIXTURES_CGROUPS: &'static str = "fixtures/cgroups/cgroups";
- macro_rules! join {
- ($base:expr, $($path:expr),+) => ({
- Path::new($base)
- $(.join($path))+
- })
- }
+ macro_rules! join {
+ ($base:expr, $($path:expr),+) => ({
+ Path::new($base)
+ $(.join($path))+
+ })
+ }
- #[test]
- fn test_load_mountinfo() {
- // test only one optional fields
- let path = join!(FIXTURES_PROC, "mountinfo");
+ #[test]
+ fn test_load_mountinfo() {
+ // test only one optional fields
+ let path = join!(FIXTURES_PROC, "mountinfo");
- let mnt_info = MountInfo::load_cpu(path).unwrap();
+ let mnt_info = MountInfo::load_cpu(path, CgroupVersion::V1).unwrap();
- assert_eq!(mnt_info.root, "/");
- assert_eq!(mnt_info.mount_point, "/sys/fs/cgroup/cpu,cpuacct");
+ assert_eq!(mnt_info.root, "/");
+ assert_eq!(mnt_info.mount_point, "/sys/fs/cgroup/cpu,cpuacct");
- // test zero optional field
- let path = join!(FIXTURES_PROC, "mountinfo_zero_opt");
+ // test zero optional field
+ let path = join!(FIXTURES_PROC, "mountinfo_zero_opt");
- let mnt_info = MountInfo::load_cpu(path).unwrap();
+ let mnt_info = MountInfo::load_cpu(path, CgroupVersion::V1).unwrap();
- assert_eq!(mnt_info.root, "/");
- assert_eq!(mnt_info.mount_point, "/sys/fs/cgroup/cpu,cpuacct");
+ assert_eq!(mnt_info.root, "/");
+ assert_eq!(mnt_info.mount_point, "/sys/fs/cgroup/cpu,cpuacct");
- // test multi optional fields
- let path = join!(FIXTURES_PROC, "mountinfo_multi_opt");
+ // test multi optional fields
+ let path = join!(FIXTURES_PROC, "mountinfo_multi_opt");
- let mnt_info = MountInfo::load_cpu(path).unwrap();
+ let mnt_info = MountInfo::load_cpu(path, CgroupVersion::V1).unwrap();
- assert_eq!(mnt_info.root, "/");
- assert_eq!(mnt_info.mount_point, "/sys/fs/cgroup/cpu,cpuacct");
- }
+ assert_eq!(mnt_info.root, "/");
+ assert_eq!(mnt_info.mount_point, "/sys/fs/cgroup/cpu,cpuacct");
+ }
- #[test]
- fn test_load_subsys() {
- let path = join!(FIXTURES_PROC, "cgroup");
+ #[test]
+ fn test_load_subsys() {
+ let path = join!(FIXTURES_PROC, "cgroup");
- let subsys = Subsys::load_cpu(path).unwrap();
+ let subsys = Subsys::load_cpu(path).unwrap();
- assert_eq!(subsys.base, "/");
- }
+ assert_eq!(subsys.base, "/");
+ assert_eq!(subsys.version, CgroupVersion::V1);
+ }
- #[test]
- fn test_cgroup_mount() {
- let cases = &[
- ("/", "/sys/fs/cgroup/cpu", "/", Some("/sys/fs/cgroup/cpu")),
- (
- "/docker/01abcd",
- "/sys/fs/cgroup/cpu",
- "/docker/01abcd",
- Some("/sys/fs/cgroup/cpu"),
- ),
- (
- "/docker/01abcd",
- "/sys/fs/cgroup/cpu",
- "/docker/01abcd/",
- Some("/sys/fs/cgroup/cpu"),
- ),
- (
- "/docker/01abcd",
- "/sys/fs/cgroup/cpu",
- "/docker/01abcd/large",
- Some("/sys/fs/cgroup/cpu/large"),
- ),
- // fails
- ("/docker/01abcd", "/sys/fs/cgroup/cpu", "/", None),
- ("/docker/01abcd", "/sys/fs/cgroup/cpu", "/docker", None),
- ("/docker/01abcd", "/sys/fs/cgroup/cpu", "/elsewhere", None),
- (
- "/docker/01abcd",
- "/sys/fs/cgroup/cpu",
- "/docker/01abcd-other-dir",
- None,
- ),
- ];
-
- for &(root, mount_point, subsys, expected) in cases.iter() {
- let mnt_info = MountInfo {
- root: root.into(),
- mount_point: mount_point.into(),
- };
- let subsys = Subsys {
- base: subsys.into(),
- };
+ #[test]
+ fn test_cgroup_mount() {
+ let cases = &[
+ ("/", "/sys/fs/cgroup/cpu", "/", Some("/sys/fs/cgroup/cpu")),
+ (
+ "/docker/01abcd",
+ "/sys/fs/cgroup/cpu",
+ "/docker/01abcd",
+ Some("/sys/fs/cgroup/cpu"),
+ ),
+ (
+ "/docker/01abcd",
+ "/sys/fs/cgroup/cpu",
+ "/docker/01abcd/",
+ Some("/sys/fs/cgroup/cpu"),
+ ),
+ (
+ "/docker/01abcd",
+ "/sys/fs/cgroup/cpu",
+ "/docker/01abcd/large",
+ Some("/sys/fs/cgroup/cpu/large"),
+ ),
+ // fails
+ ("/docker/01abcd", "/sys/fs/cgroup/cpu", "/", None),
+ ("/docker/01abcd", "/sys/fs/cgroup/cpu", "/docker", None),
+ ("/docker/01abcd", "/sys/fs/cgroup/cpu", "/elsewhere", None),
+ (
+ "/docker/01abcd",
+ "/sys/fs/cgroup/cpu",
+ "/docker/01abcd-other-dir",
+ None,
+ ),
+ ];
+
+ for &(root, mount_point, subsys, expected) in cases.iter() {
+ let mnt_info = MountInfo {
+ version: CgroupVersion::V1,
+ root: root.into(),
+ mount_point: mount_point.into(),
+ };
+ let subsys = Subsys {
+ version: CgroupVersion::V1,
+ base: subsys.into(),
+ };
+
+ let actual = Cgroup::translate(mnt_info, subsys).map(|c| c.base);
+ let expected = expected.map(PathBuf::from);
+ assert_eq!(actual, expected);
+ }
+ }
- let actual = Cgroup::translate(mnt_info, subsys).map(|c| c.base);
- let expected = expected.map(PathBuf::from);
- assert_eq!(actual, expected);
+ #[test]
+ fn test_cgroup_cpu_quota() {
+ let cgroup = Cgroup::new(CgroupVersion::V1, join!(FIXTURES_CGROUPS, "good"));
+ assert_eq!(cgroup.cpu_quota(), Some(6));
}
- }
- #[test]
- fn test_cgroup_cpu_quota() {
- let cgroup = Cgroup::new(join!(FIXTURES_CGROUPS, "good"));
- assert_eq!(cgroup.cpu_quota(), Some(6));
- }
+ #[test]
+ fn test_cgroup_cpu_quota_divide_by_zero() {
+ let cgroup = Cgroup::new(CgroupVersion::V1, join!(FIXTURES_CGROUPS, "zero-period"));
+ assert!(cgroup.quota_us().is_some());
+ assert_eq!(cgroup.period_us(), Some(0));
+ assert_eq!(cgroup.cpu_quota(), None);
+ }
- #[test]
- fn test_cgroup_cpu_quota_divide_by_zero() {
- let cgroup = Cgroup::new(join!(FIXTURES_CGROUPS, "zero-period"));
- assert!(cgroup.quota_us().is_some());
- assert_eq!(cgroup.period_us(), Some(0));
- assert_eq!(cgroup.cpu_quota(), None);
+ #[test]
+ fn test_cgroup_cpu_quota_ceil() {
+ let cgroup = Cgroup::new(CgroupVersion::V1, join!(FIXTURES_CGROUPS, "ceil"));
+ assert_eq!(cgroup.cpu_quota(), Some(2));
+ }
}
- #[test]
- fn test_cgroup_cpu_quota_ceil() {
- let cgroup = Cgroup::new(join!(FIXTURES_CGROUPS, "ceil"));
- assert_eq!(cgroup.cpu_quota(), Some(2));
+ mod v2 {
+ use super::super::{Cgroup, CgroupVersion, MountInfo, Subsys};
+ use std::path::{Path, PathBuf};
+
+ // `static_in_const` feature is not stable in Rust 1.13.
+ static FIXTURES_PROC: &'static str = "fixtures/cgroups2/proc/cgroups";
+
+ static FIXTURES_CGROUPS: &'static str = "fixtures/cgroups2/cgroups";
+
+ macro_rules! join {
+ ($base:expr, $($path:expr),+) => ({
+ Path::new($base)
+ $(.join($path))+
+ })
+ }
+
+ #[test]
+ fn test_load_mountinfo() {
+ // test only one optional fields
+ let path = join!(FIXTURES_PROC, "mountinfo");
+
+ let mnt_info = MountInfo::load_cpu(path, CgroupVersion::V2).unwrap();
+
+ assert_eq!(mnt_info.root, "/");
+ assert_eq!(mnt_info.mount_point, "/sys/fs/cgroup");
+ }
+
+ #[test]
+ fn test_load_subsys() {
+ let path = join!(FIXTURES_PROC, "cgroup");
+
+ let subsys = Subsys::load_cpu(path).unwrap();
+
+ assert_eq!(subsys.base, "/");
+ assert_eq!(subsys.version, CgroupVersion::V2);
+ }
+
+ #[test]
+ fn test_load_subsys_multi() {
+ let path = join!(FIXTURES_PROC, "cgroup_multi");
+
+ let subsys = Subsys::load_cpu(path).unwrap();
+
+ assert_eq!(subsys.base, "/");
+ assert_eq!(subsys.version, CgroupVersion::V1);
+ }
+
+ #[test]
+ fn test_cgroup_mount() {
+ let cases = &[
+ ("/", "/sys/fs/cgroup/cpu", "/", Some("/sys/fs/cgroup/cpu")),
+ (
+ "/docker/01abcd",
+ "/sys/fs/cgroup/cpu",
+ "/docker/01abcd",
+ Some("/sys/fs/cgroup/cpu"),
+ ),
+ (
+ "/docker/01abcd",
+ "/sys/fs/cgroup/cpu",
+ "/docker/01abcd/",
+ Some("/sys/fs/cgroup/cpu"),
+ ),
+ (
+ "/docker/01abcd",
+ "/sys/fs/cgroup/cpu",
+ "/docker/01abcd/large",
+ Some("/sys/fs/cgroup/cpu/large"),
+ ),
+ // fails
+ ("/docker/01abcd", "/sys/fs/cgroup/cpu", "/", None),
+ ("/docker/01abcd", "/sys/fs/cgroup/cpu", "/docker", None),
+ ("/docker/01abcd", "/sys/fs/cgroup/cpu", "/elsewhere", None),
+ (
+ "/docker/01abcd",
+ "/sys/fs/cgroup/cpu",
+ "/docker/01abcd-other-dir",
+ None,
+ ),
+ ];
+
+ for &(root, mount_point, subsys, expected) in cases.iter() {
+ let mnt_info = MountInfo {
+ version: CgroupVersion::V1,
+ root: root.into(),
+ mount_point: mount_point.into(),
+ };
+ let subsys = Subsys {
+ version: CgroupVersion::V1,
+ base: subsys.into(),
+ };
+
+ let actual = Cgroup::translate(mnt_info, subsys).map(|c| c.base);
+ let expected = expected.map(PathBuf::from);
+ assert_eq!(actual, expected);
+ }
+ }
+
+ #[test]
+ fn test_cgroup_cpu_quota() {
+ let cgroup = Cgroup::new(CgroupVersion::V2, join!(FIXTURES_CGROUPS, "good"));
+ assert_eq!(cgroup.cpu_quota(), Some(6));
+ }
+
+ #[test]
+ fn test_cgroup_cpu_quota_divide_by_zero() {
+ let cgroup = Cgroup::new(CgroupVersion::V2, join!(FIXTURES_CGROUPS, "zero-period"));
+ let period = cgroup.max().map(|max| max.1);
+
+ assert_eq!(period, Some(0));
+ assert_eq!(cgroup.cpu_quota(), None);
+ }
+
+ #[test]
+ fn test_cgroup_cpu_quota_ceil() {
+ let cgroup = Cgroup::new(CgroupVersion::V2, join!(FIXTURES_CGROUPS, "ceil"));
+ assert_eq!(cgroup.cpu_quota(), Some(2));
+ }
}
}
diff --git a/vendor/object/.cargo-checksum.json b/vendor/object/.cargo-checksum.json
index 7453e6945..4b0e67365 100644
--- a/vendor/object/.cargo-checksum.json
+++ b/vendor/object/.cargo-checksum.json
@@ -1 +1 @@
-{"files":{"CHANGELOG.md":"e14387eeab6f5becbfb1fdaadd5056f5316a1b386620afeff1bc0553d3419ae6","Cargo.toml":"b21db34ed7541075cd178edf290ebe328217f94dd0347d425d900d3a1fb5f16a","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"0b74dfa0bcee5c420c6b7f67b4b2658f9ab8388c97b8e733975f2cecbdd668a6","README.md":"a91c65ccbcb9e5bb6344a537a28d43e6f8ff43f7a730493521371d69c7a07045","clippy.toml":"50fd0cdaae995561b1d688c9410fe99335fc7ac3916a400dafd25ff63f8215f7","src/archive.rs":"d6cead723242c26db2967b63385b79ed2008980a8c64b123a5eecffd7ed388fc","src/common.rs":"721281f967576b136bb66d368babc0e0497f61ca201208915f73f22ba9c24852","src/elf.rs":"50116decb5f2a05c5c2b12e287a0d41d6391c34549fd1188ee2b86bbb04c12bf","src/endian.rs":"ceaad1b651627ad9e6218a168f87353ae651f5d76c9f61bc8099dff25007405e","src/lib.rs":"d12d8b0b9ecb80ce0624c818acad1ce5d0a51b8e12960d913c1af31cec71ef50","src/macho.rs":"50f7afc1bba3c59542f55b7b5c7357fb71fef52235f1b568f08f3efb6780aaf5","src/pe.rs":"0e9f47653eb6255a04948a0494d453fd6d416bf7c4a0c43f0cfc4a2b86cc1ac8","src/pod.rs":"d2967732f0052e6cfa18a2dd62c57bc3b640a20eb9a6db9f39836000ceabb399","src/read/any.rs":"1057d642dd06b8d20c953ac1ef4e2c99ace06632283e9497925c48c28d58ea3d","src/read/archive.rs":"479574cff125a74fc5512d75c1531da3bb006005fe544ffd2531a7d4f35a9bb4","src/read/coff/comdat.rs":"36846a11b285ad560dc1f18c67b1659f19fe8b5f11a350fe8b7bc5d27d0afb65","src/read/coff/file.rs":"874b4b357dbcb1a6a29c993e908b4044c9f90b0acd402cc8504ab84c3a036e1d","src/read/coff/mod.rs":"5eed1c0ca7cf044b3173223b06afacc4961a0515ef2478fffa35641f4ee364ee","src/read/coff/relocation.rs":"3b8e1405921eb16b8d38da4639a81be0546dca51c7747c126729d7a15da93a17","src/read/coff/section.rs":"dcb5b697a9371b1de6584603266673badfcd5d7f82b5472ead37555d69449e19","src/read/coff/symbol.rs":"52872aa7f306dc28a21d039895dedf8f06e6ad4ee54ebde7aed9c759616e38d5","src/read/elf/comdat.rs":"d39155e00c10e3f76d6776e2604d2ecd5039929979c179131101887d54a0e494","src/read/elf/compression.rs":"097ff8bdc78d01a1532b11c1c0cae3b35905128c7d98b471de188d46da3ff970","src/read/elf/dynamic.rs":"8f59bd6d352f6810be6b6dc02c2f88229f15aa02a42f8fc09bcf3f284d4b1021","src/read/elf/file.rs":"add48c004fb2e93718a4a0cdd4d12f52a563854e46904e1f3d02c19cda7fb52a","src/read/elf/hash.rs":"82123642ba71d2e56acae5bdbb59253b16ced8f6defdc58f4c37cafb7154a7b0","src/read/elf/mod.rs":"98b5bd46778d3c33e9d19dee2d294f61677dec16b28f22aa73340008c241fe09","src/read/elf/note.rs":"33bf89a85bb7927fd0123cd6c2919f0b9b0f8935db1ae7b446b75ea2717a476d","src/read/elf/relocation.rs":"f710c7a6f8e743f8f4172141e03294399ea4d59f4726650168e3c66544fe2f5f","src/read/elf/section.rs":"2c535c3ccd4d333a4abdfe9d14eeee0afb7b11c536387ba2c150e4ead7fb51bd","src/read/elf/segment.rs":"cdc9740d996bb262d99db3e9a50e3fda2a5802cbd9864ebeae36e5f9f96d58bf","src/read/elf/symbol.rs":"34e0fc849ffe3ae9af6a43954eb817729186313ac5edcbb0eed030b6d451982c","src/read/elf/version.rs":"154510d6868730f2d2fae2e0d9bdb697907ed48ded51c55ba115edd98d819e82","src/read/macho/dyld_cache.rs":"1526f518dfdcc9e024e6c0284ff75018e33413c14ea2ee00c8a99c31ccce6413","src/read/macho/fat.rs":"d27a1052f2e47cd5b798a6359f33c3bfe7f7971b13259f6545118213ace7f5dd","src/read/macho/file.rs":"21fa6d56cc241881ee241d004c1bf4ac0a4b40e3fa0bac2d0da562c7c429e01d","src/read/macho/load_command.rs":"efaf1ab5fe22fddc30af03f9cbd2a076f373cba3aab29329050c27a5a94b581f","src/read/macho/mod.rs":"23b353da3b7e076c68a067776e6a5b346a746116ac42c2c90bafd95ad54a90b3","src/read/macho/relocation.rs":"77fa3e65ccf5884433c96cdc39c457b8a0c430432e5ff9cad22a8becf13f0183","src/read/macho/section.rs":"78e98624691ef9872cc090187d90e09f9a54b47b3b1f174fd4f57e0640f6ceeb","src/read/macho/segment.rs":"cd3727796b672adba03443fadc4f458e117c3f56c2ebb318e32c408329a40492","src/read/macho/symbol.rs":"a2e50bcc1ebb5ea356a6f08b9083533c62ae3b3af90de18e8c942bf06589e85a","src/read/mod.rs":"d4615cecc02fb051314b16b900ff0d2bff561848ce36a5fd1398d66ba0013d9a","src/read/pe/data_directory.rs":"0b358dd5c9df7db570efc9c69896b88e8d13560a51fd7385f18d9e5ad8ac955b","src/read/pe/export.rs":"07ac5ec7b67d4a09037d8f11eb4426d96515687ee299df2a3d8cd4fd93eb2036","src/read/pe/file.rs":"485528fa444b3c8a20884dbb934422d3c7381f9d0351a5d14ca0813b14c51fcc","src/read/pe/import.rs":"ea20dfc0d462ba20e149bf9408f4ec1d0b202abf1f15536f6d091f0c0e756ac8","src/read/pe/mod.rs":"69832b7f4ccd93b59e08bafcbd0d3226c450d7801ad49ab554b38b660c8997fd","src/read/pe/relocation.rs":"0335c06b6d37df4939c8b88044313e88661ee45e5a57d2eec40143f2fe481838","src/read/pe/resource.rs":"21cc2077ff6f20d854b94134af29062166cc561c7bb1e5e47371e7965221f011","src/read/pe/rich.rs":"abf005004e69a4533132358aa54df73d7cc3a744738518e5b11c6f6f861e9f00","src/read/pe/section.rs":"f936dd73dbb1838cf558483949acdfefce701cdc22c21c96db345062c1ce641d","src/read/read_cache.rs":"939b66cfc11fc022c4e4b78fcad63b375516967da2274da78fb200271d934a53","src/read/read_ref.rs":"5fe6f717c79b07fecac9ee8ba15740c7a9581c36f1e356119e99dd669af6c39c","src/read/traits.rs":"b0e4cf654301843fa4db05a6fb1e22c454eb45da6af99b66e631f2b49bab9e21","src/read/util.rs":"c329a240689b177613049e00faf7928e6cd6aad021542cd708cc06b598c6900e","src/read/wasm.rs":"e5bd4cf1282c877f55401b14bb92beb1a8b7f222e4facd2b8fcf6a8599c1ba7e","src/read/xcoff/comdat.rs":"e7a74ce2c5817f29d184d0be1fc1309ff843a648b1539689561d85d1410d0cd5","src/read/xcoff/file.rs":"17f751578d052cb8f74ee56a4e17b053b06e82e4efbe943907943bc561fb301e","src/read/xcoff/mod.rs":"d0179d3f95797464ca5919563454d1123ce8c35dfc5f40ecd6ca0d002a9824a8","src/read/xcoff/relocation.rs":"ff30373e33bf79f3c690933044762460d9d852d1ec80883ee7205e80c424d849","src/read/xcoff/section.rs":"9bccdcbc0aa26b90a4a0b1b125aee52628e599dce74a097d6668df14e95be1be","src/read/xcoff/segment.rs":"7bee1d20185df21b2e00a581053095a6bc071b0ff003e04c4a3ef881fe990f45","src/read/xcoff/symbol.rs":"bcb7a57a107a145fad85d2c5325113d828e30fa8255023a6234d8b17234461c4","src/write/coff.rs":"52b1b402975fc84a5095050ee5be47097e90daf1a5379f9fc081c07b2b9fa432","src/write/elf/mod.rs":"1bb945edad539b4f19dda5d46c9b86fa4ea3721eedda77ca2595b5519c3e30f2","src/write/elf/object.rs":"e72b159e1a03e7f37d87249d7f43cccd8291cc41e41ae711dda61927f4bf65ed","src/write/elf/writer.rs":"a0bf5bb8bcd9d25510ce14f3a070ad9f9bfed3becc70ee600b2c73bc1e0eccd8","src/write/macho.rs":"cfd3a1ee65c800c53fb6c878882e8ae853b68756cbd7624386f48f92b56ff49f","src/write/mod.rs":"4ee5a5f971a4a4b184169c6b8dc50d79eb89937316b4677a1f526fef4a0ed106","src/write/pe.rs":"6c72185705a3e067c481f2b9f81c64a84e062e67781928e58fd1150314dad8f9","src/write/string.rs":"674c5913d0702cbaebe79d2a7e91f6a04327ac30e370557f02928eee1b0bb0d0","src/write/util.rs":"0e96abed0e8aae33c2efd8b836f29647eac310b58fad4029b68894e9f57bf137","src/xcoff.rs":"3580336207bdfe01631f528678b72b6a13b876716f82ac789620011516c67051","tests/integration.rs":"0fa704827e4da1be38dac2e3820d92f6b20c4d415803b04f67c3516020b1de97","tests/parse_self.rs":"81b44b2dd1de9a5d8c18d9bd8926156e39fb83931837afa8ca344da0d309aeee","tests/read/coff.rs":"11bf5a1b5770a4312e334580975a7cac9d69f1b12a4d75f25aacc931df01c5c7","tests/read/mod.rs":"7833826f169ac3be2b4f274e5fc8cf4a51742bd0010803ff0dc20ea5643a7e61","tests/round_trip/bss.rs":"849d69b063fd757fed02219dd81e9d13b82068a2025d2cc5cfd40cf557e31bda","tests/round_trip/coff.rs":"8a25aab7164a5c8aa7a21279f8bae1f4d5f68a8d09c29a4ecd0d0c14564851cc","tests/round_trip/comdat.rs":"a8f729e218fee21e90b9f39b5cfcb4f80bc3ce26d3a297323667e6eb14f882cc","tests/round_trip/common.rs":"ced08ff559ca4d343ceef54bb4c581a3405cd96d6a1628ba43b7aab82070800b","tests/round_trip/elf.rs":"690015fb4d3e79ee6d41c4d3a8e89a6806f1a0c313804707b83e44fceefac472","tests/round_trip/macho.rs":"b23931f506345b26ce3b4908dc2ce02f704603c622d39f5e9e7c8529f2882818","tests/round_trip/mod.rs":"b0942a5e0ffff38c3c12276dfd96ca6b0516b48e86ede979e7da782b9e7530d2","tests/round_trip/section_flags.rs":"0e17639e5f86d576f039a294c274ce8db2e2a8add31a2fffc33a6e93a6d2791e","tests/round_trip/tls.rs":"23a49a1036b9173ece82a3080745930e5925e745280ab38866c9d3c29f463e63"},"package":"8d864c91689fdc196779b98dba0aceac6118594c2df6ee5d943eb6a8df4d107a"} \ No newline at end of file
+{"files":{"CHANGELOG.md":"598939c018d604e242cc44ebe3f192def44ab195fdc638b662e53f2c55435e4f","Cargo.toml":"b829ce9480a5feb1a27027bf6af9e6e09ba40f7aa2c7fd6c226cd8ea674f1646","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"0b74dfa0bcee5c420c6b7f67b4b2658f9ab8388c97b8e733975f2cecbdd668a6","README.md":"a91c65ccbcb9e5bb6344a537a28d43e6f8ff43f7a730493521371d69c7a07045","clippy.toml":"50fd0cdaae995561b1d688c9410fe99335fc7ac3916a400dafd25ff63f8215f7","src/archive.rs":"d6cead723242c26db2967b63385b79ed2008980a8c64b123a5eecffd7ed388fc","src/common.rs":"721281f967576b136bb66d368babc0e0497f61ca201208915f73f22ba9c24852","src/elf.rs":"f179b9de249e5a40d82161a14a176e2d5f6df94cf8b15b3dbab04ac824e9bbfa","src/endian.rs":"ceaad1b651627ad9e6218a168f87353ae651f5d76c9f61bc8099dff25007405e","src/lib.rs":"d12d8b0b9ecb80ce0624c818acad1ce5d0a51b8e12960d913c1af31cec71ef50","src/macho.rs":"50f7afc1bba3c59542f55b7b5c7357fb71fef52235f1b568f08f3efb6780aaf5","src/pe.rs":"0e9f47653eb6255a04948a0494d453fd6d416bf7c4a0c43f0cfc4a2b86cc1ac8","src/pod.rs":"d2967732f0052e6cfa18a2dd62c57bc3b640a20eb9a6db9f39836000ceabb399","src/read/any.rs":"1057d642dd06b8d20c953ac1ef4e2c99ace06632283e9497925c48c28d58ea3d","src/read/archive.rs":"479574cff125a74fc5512d75c1531da3bb006005fe544ffd2531a7d4f35a9bb4","src/read/coff/comdat.rs":"36846a11b285ad560dc1f18c67b1659f19fe8b5f11a350fe8b7bc5d27d0afb65","src/read/coff/file.rs":"874b4b357dbcb1a6a29c993e908b4044c9f90b0acd402cc8504ab84c3a036e1d","src/read/coff/mod.rs":"5eed1c0ca7cf044b3173223b06afacc4961a0515ef2478fffa35641f4ee364ee","src/read/coff/relocation.rs":"3b8e1405921eb16b8d38da4639a81be0546dca51c7747c126729d7a15da93a17","src/read/coff/section.rs":"dcb5b697a9371b1de6584603266673badfcd5d7f82b5472ead37555d69449e19","src/read/coff/symbol.rs":"52872aa7f306dc28a21d039895dedf8f06e6ad4ee54ebde7aed9c759616e38d5","src/read/elf/comdat.rs":"d39155e00c10e3f76d6776e2604d2ecd5039929979c179131101887d54a0e494","src/read/elf/compression.rs":"097ff8bdc78d01a1532b11c1c0cae3b35905128c7d98b471de188d46da3ff970","src/read/elf/dynamic.rs":"8f59bd6d352f6810be6b6dc02c2f88229f15aa02a42f8fc09bcf3f284d4b1021","src/read/elf/file.rs":"add48c004fb2e93718a4a0cdd4d12f52a563854e46904e1f3d02c19cda7fb52a","src/read/elf/hash.rs":"82123642ba71d2e56acae5bdbb59253b16ced8f6defdc58f4c37cafb7154a7b0","src/read/elf/mod.rs":"98b5bd46778d3c33e9d19dee2d294f61677dec16b28f22aa73340008c241fe09","src/read/elf/note.rs":"33bf89a85bb7927fd0123cd6c2919f0b9b0f8935db1ae7b446b75ea2717a476d","src/read/elf/relocation.rs":"f710c7a6f8e743f8f4172141e03294399ea4d59f4726650168e3c66544fe2f5f","src/read/elf/section.rs":"2c535c3ccd4d333a4abdfe9d14eeee0afb7b11c536387ba2c150e4ead7fb51bd","src/read/elf/segment.rs":"cdc9740d996bb262d99db3e9a50e3fda2a5802cbd9864ebeae36e5f9f96d58bf","src/read/elf/symbol.rs":"34e0fc849ffe3ae9af6a43954eb817729186313ac5edcbb0eed030b6d451982c","src/read/elf/version.rs":"154510d6868730f2d2fae2e0d9bdb697907ed48ded51c55ba115edd98d819e82","src/read/macho/dyld_cache.rs":"1526f518dfdcc9e024e6c0284ff75018e33413c14ea2ee00c8a99c31ccce6413","src/read/macho/fat.rs":"d27a1052f2e47cd5b798a6359f33c3bfe7f7971b13259f6545118213ace7f5dd","src/read/macho/file.rs":"21fa6d56cc241881ee241d004c1bf4ac0a4b40e3fa0bac2d0da562c7c429e01d","src/read/macho/load_command.rs":"efaf1ab5fe22fddc30af03f9cbd2a076f373cba3aab29329050c27a5a94b581f","src/read/macho/mod.rs":"23b353da3b7e076c68a067776e6a5b346a746116ac42c2c90bafd95ad54a90b3","src/read/macho/relocation.rs":"77fa3e65ccf5884433c96cdc39c457b8a0c430432e5ff9cad22a8becf13f0183","src/read/macho/section.rs":"78e98624691ef9872cc090187d90e09f9a54b47b3b1f174fd4f57e0640f6ceeb","src/read/macho/segment.rs":"cd3727796b672adba03443fadc4f458e117c3f56c2ebb318e32c408329a40492","src/read/macho/symbol.rs":"a2e50bcc1ebb5ea356a6f08b9083533c62ae3b3af90de18e8c942bf06589e85a","src/read/mod.rs":"d4615cecc02fb051314b16b900ff0d2bff561848ce36a5fd1398d66ba0013d9a","src/read/pe/data_directory.rs":"0b358dd5c9df7db570efc9c69896b88e8d13560a51fd7385f18d9e5ad8ac955b","src/read/pe/export.rs":"07ac5ec7b67d4a09037d8f11eb4426d96515687ee299df2a3d8cd4fd93eb2036","src/read/pe/file.rs":"485528fa444b3c8a20884dbb934422d3c7381f9d0351a5d14ca0813b14c51fcc","src/read/pe/import.rs":"ea20dfc0d462ba20e149bf9408f4ec1d0b202abf1f15536f6d091f0c0e756ac8","src/read/pe/mod.rs":"69832b7f4ccd93b59e08bafcbd0d3226c450d7801ad49ab554b38b660c8997fd","src/read/pe/relocation.rs":"0335c06b6d37df4939c8b88044313e88661ee45e5a57d2eec40143f2fe481838","src/read/pe/resource.rs":"21cc2077ff6f20d854b94134af29062166cc561c7bb1e5e47371e7965221f011","src/read/pe/rich.rs":"abf005004e69a4533132358aa54df73d7cc3a744738518e5b11c6f6f861e9f00","src/read/pe/section.rs":"f936dd73dbb1838cf558483949acdfefce701cdc22c21c96db345062c1ce641d","src/read/read_cache.rs":"939b66cfc11fc022c4e4b78fcad63b375516967da2274da78fb200271d934a53","src/read/read_ref.rs":"5fe6f717c79b07fecac9ee8ba15740c7a9581c36f1e356119e99dd669af6c39c","src/read/traits.rs":"b0e4cf654301843fa4db05a6fb1e22c454eb45da6af99b66e631f2b49bab9e21","src/read/util.rs":"c329a240689b177613049e00faf7928e6cd6aad021542cd708cc06b598c6900e","src/read/wasm.rs":"e5bd4cf1282c877f55401b14bb92beb1a8b7f222e4facd2b8fcf6a8599c1ba7e","src/read/xcoff/comdat.rs":"e7a74ce2c5817f29d184d0be1fc1309ff843a648b1539689561d85d1410d0cd5","src/read/xcoff/file.rs":"17f751578d052cb8f74ee56a4e17b053b06e82e4efbe943907943bc561fb301e","src/read/xcoff/mod.rs":"d0179d3f95797464ca5919563454d1123ce8c35dfc5f40ecd6ca0d002a9824a8","src/read/xcoff/relocation.rs":"ff30373e33bf79f3c690933044762460d9d852d1ec80883ee7205e80c424d849","src/read/xcoff/section.rs":"9bccdcbc0aa26b90a4a0b1b125aee52628e599dce74a097d6668df14e95be1be","src/read/xcoff/segment.rs":"7bee1d20185df21b2e00a581053095a6bc071b0ff003e04c4a3ef881fe990f45","src/read/xcoff/symbol.rs":"bcb7a57a107a145fad85d2c5325113d828e30fa8255023a6234d8b17234461c4","src/write/coff.rs":"52b1b402975fc84a5095050ee5be47097e90daf1a5379f9fc081c07b2b9fa432","src/write/elf/mod.rs":"1bb945edad539b4f19dda5d46c9b86fa4ea3721eedda77ca2595b5519c3e30f2","src/write/elf/object.rs":"e72b159e1a03e7f37d87249d7f43cccd8291cc41e41ae711dda61927f4bf65ed","src/write/elf/writer.rs":"a0bf5bb8bcd9d25510ce14f3a070ad9f9bfed3becc70ee600b2c73bc1e0eccd8","src/write/macho.rs":"cfd3a1ee65c800c53fb6c878882e8ae853b68756cbd7624386f48f92b56ff49f","src/write/mod.rs":"4ee5a5f971a4a4b184169c6b8dc50d79eb89937316b4677a1f526fef4a0ed106","src/write/pe.rs":"6c72185705a3e067c481f2b9f81c64a84e062e67781928e58fd1150314dad8f9","src/write/string.rs":"674c5913d0702cbaebe79d2a7e91f6a04327ac30e370557f02928eee1b0bb0d0","src/write/util.rs":"0e96abed0e8aae33c2efd8b836f29647eac310b58fad4029b68894e9f57bf137","src/xcoff.rs":"3580336207bdfe01631f528678b72b6a13b876716f82ac789620011516c67051","tests/integration.rs":"0fa704827e4da1be38dac2e3820d92f6b20c4d415803b04f67c3516020b1de97","tests/parse_self.rs":"81b44b2dd1de9a5d8c18d9bd8926156e39fb83931837afa8ca344da0d309aeee","tests/read/coff.rs":"11bf5a1b5770a4312e334580975a7cac9d69f1b12a4d75f25aacc931df01c5c7","tests/read/mod.rs":"7833826f169ac3be2b4f274e5fc8cf4a51742bd0010803ff0dc20ea5643a7e61","tests/round_trip/bss.rs":"849d69b063fd757fed02219dd81e9d13b82068a2025d2cc5cfd40cf557e31bda","tests/round_trip/coff.rs":"8a25aab7164a5c8aa7a21279f8bae1f4d5f68a8d09c29a4ecd0d0c14564851cc","tests/round_trip/comdat.rs":"a8f729e218fee21e90b9f39b5cfcb4f80bc3ce26d3a297323667e6eb14f882cc","tests/round_trip/common.rs":"ced08ff559ca4d343ceef54bb4c581a3405cd96d6a1628ba43b7aab82070800b","tests/round_trip/elf.rs":"690015fb4d3e79ee6d41c4d3a8e89a6806f1a0c313804707b83e44fceefac472","tests/round_trip/macho.rs":"b23931f506345b26ce3b4908dc2ce02f704603c622d39f5e9e7c8529f2882818","tests/round_trip/mod.rs":"b0942a5e0ffff38c3c12276dfd96ca6b0516b48e86ede979e7da782b9e7530d2","tests/round_trip/section_flags.rs":"0e17639e5f86d576f039a294c274ce8db2e2a8add31a2fffc33a6e93a6d2791e","tests/round_trip/tls.rs":"23a49a1036b9173ece82a3080745930e5925e745280ab38866c9d3c29f463e63"},"package":"2b8c786513eb403643f2a88c244c2aaa270ef2153f55094587d0c48a3cf22a83"} \ No newline at end of file
diff --git a/vendor/object/CHANGELOG.md b/vendor/object/CHANGELOG.md
index 66d789db1..3865c24d4 100644
--- a/vendor/object/CHANGELOG.md
+++ b/vendor/object/CHANGELOG.md
@@ -2,6 +2,17 @@
--------------------------------------------------------------------------------
+## 0.30.2
+
+Released 2023/01/11.
+
+### Added
+
+* Added more ELF constants for AVR flags and relocations.
+ [#500](https://github.com/gimli-rs/object/pull/500)
+
+--------------------------------------------------------------------------------
+
## 0.30.1
Released 2023/01/04.
diff --git a/vendor/object/Cargo.toml b/vendor/object/Cargo.toml
index 0d90ab271..84efba254 100644
--- a/vendor/object/Cargo.toml
+++ b/vendor/object/Cargo.toml
@@ -12,7 +12,7 @@
[package]
edition = "2018"
name = "object"
-version = "0.30.1"
+version = "0.30.2"
exclude = [
"/.github",
"/testfiles",
diff --git a/vendor/object/src/elf.rs b/vendor/object/src/elf.rs
index ac9742080..edbfd9e3d 100644
--- a/vendor/object/src/elf.rs
+++ b/vendor/object/src/elf.rs
@@ -4238,12 +4238,128 @@ pub const R_AARCH64_TLSDESC: u32 = 1031;
/// STT_GNU_IFUNC relocation.
pub const R_AARCH64_IRELATIVE: u32 = 1032;
+// AVR values for `FileHeader*::e_flags`.
+
+/// Bitmask for `EF_AVR_ARCH_*`.
+pub const EF_AVR_ARCH: u32 = 0x7F;
+
+/// If set, it is assumed that the elf file uses local symbols as reference
+/// for the relocations so that linker relaxation is possible.
+pub const EF_AVR_LINKRELAX_PREPARED: u32 = 0x80;
+
+#[allow(missing_docs)]
+pub const EF_AVR_ARCH_AVR1: u32 = 1;
+#[allow(missing_docs)]
+pub const EF_AVR_ARCH_AVR2: u32 = 2;
+#[allow(missing_docs)]
+pub const EF_AVR_ARCH_AVR25: u32 = 25;
+#[allow(missing_docs)]
+pub const EF_AVR_ARCH_AVR3: u32 = 3;
+#[allow(missing_docs)]
+pub const EF_AVR_ARCH_AVR31: u32 = 31;
+#[allow(missing_docs)]
+pub const EF_AVR_ARCH_AVR35: u32 = 35;
+#[allow(missing_docs)]
+pub const EF_AVR_ARCH_AVR4: u32 = 4;
+#[allow(missing_docs)]
+pub const EF_AVR_ARCH_AVR5: u32 = 5;
+#[allow(missing_docs)]
+pub const EF_AVR_ARCH_AVR51: u32 = 51;
+#[allow(missing_docs)]
+pub const EF_AVR_ARCH_AVR6: u32 = 6;
+#[allow(missing_docs)]
+pub const EF_AVR_ARCH_AVRTINY: u32 = 100;
+#[allow(missing_docs)]
+pub const EF_AVR_ARCH_XMEGA1: u32 = 101;
+#[allow(missing_docs)]
+pub const EF_AVR_ARCH_XMEGA2: u32 = 102;
+#[allow(missing_docs)]
+pub const EF_AVR_ARCH_XMEGA3: u32 = 103;
+#[allow(missing_docs)]
+pub const EF_AVR_ARCH_XMEGA4: u32 = 104;
+#[allow(missing_docs)]
+pub const EF_AVR_ARCH_XMEGA5: u32 = 105;
+#[allow(missing_docs)]
+pub const EF_AVR_ARCH_XMEGA6: u32 = 106;
+#[allow(missing_docs)]
+pub const EF_AVR_ARCH_XMEGA7: u32 = 107;
+
// AVR values for `Rel*::r_type`.
+#[allow(missing_docs)]
+pub const R_AVR_NONE: u32 = 0;
/// Direct 32 bit
pub const R_AVR_32: u32 = 1;
+#[allow(missing_docs)]
+pub const R_AVR_7_PCREL: u32 = 2;
+#[allow(missing_docs)]
+pub const R_AVR_13_PCREL: u32 = 3;
/// Direct 16 bit
pub const R_AVR_16: u32 = 4;
+#[allow(missing_docs)]
+pub const R_AVR_16_PM: u32 = 5;
+#[allow(missing_docs)]
+pub const R_AVR_LO8_LDI: u32 = 6;
+#[allow(missing_docs)]
+pub const R_AVR_HI8_LDI: u32 = 7;
+#[allow(missing_docs)]
+pub const R_AVR_HH8_LDI: u32 = 8;
+#[allow(missing_docs)]
+pub const R_AVR_LO8_LDI_NEG: u32 = 9;
+#[allow(missing_docs)]
+pub const R_AVR_HI8_LDI_NEG: u32 = 10;
+#[allow(missing_docs)]
+pub const R_AVR_HH8_LDI_NEG: u32 = 11;
+#[allow(missing_docs)]
+pub const R_AVR_LO8_LDI_PM: u32 = 12;
+#[allow(missing_docs)]
+pub const R_AVR_HI8_LDI_PM: u32 = 13;
+#[allow(missing_docs)]
+pub const R_AVR_HH8_LDI_PM: u32 = 14;
+#[allow(missing_docs)]
+pub const R_AVR_LO8_LDI_PM_NEG: u32 = 15;
+#[allow(missing_docs)]
+pub const R_AVR_HI8_LDI_PM_NEG: u32 = 16;
+#[allow(missing_docs)]
+pub const R_AVR_HH8_LDI_PM_NEG: u32 = 17;
+#[allow(missing_docs)]
+pub const R_AVR_CALL: u32 = 18;
+#[allow(missing_docs)]
+pub const R_AVR_LDI: u32 = 19;
+#[allow(missing_docs)]
+pub const R_AVR_6: u32 = 20;
+#[allow(missing_docs)]
+pub const R_AVR_6_ADIW: u32 = 21;
+#[allow(missing_docs)]
+pub const R_AVR_MS8_LDI: u32 = 22;
+#[allow(missing_docs)]
+pub const R_AVR_MS8_LDI_NEG: u32 = 23;
+#[allow(missing_docs)]
+pub const R_AVR_LO8_LDI_GS: u32 = 24;
+#[allow(missing_docs)]
+pub const R_AVR_HI8_LDI_GS: u32 = 25;
+#[allow(missing_docs)]
+pub const R_AVR_8: u32 = 26;
+#[allow(missing_docs)]
+pub const R_AVR_8_LO8: u32 = 27;
+#[allow(missing_docs)]
+pub const R_AVR_8_HI8: u32 = 28;
+#[allow(missing_docs)]
+pub const R_AVR_8_HLO8: u32 = 29;
+#[allow(missing_docs)]
+pub const R_AVR_DIFF8: u32 = 30;
+#[allow(missing_docs)]
+pub const R_AVR_DIFF16: u32 = 31;
+#[allow(missing_docs)]
+pub const R_AVR_DIFF32: u32 = 32;
+#[allow(missing_docs)]
+pub const R_AVR_LDS_STS_16: u32 = 33;
+#[allow(missing_docs)]
+pub const R_AVR_PORT6: u32 = 34;
+#[allow(missing_docs)]
+pub const R_AVR_PORT5: u32 = 35;
+#[allow(missing_docs)]
+pub const R_AVR_32_PCREL: u32 = 36;
// MSP430 values for `Rel*::r_type`.
diff --git a/vendor/once_cell/.cargo-checksum.json b/vendor/once_cell/.cargo-checksum.json
index 8fb4b41d7..bb03debe2 100644
--- a/vendor/once_cell/.cargo-checksum.json
+++ b/vendor/once_cell/.cargo-checksum.json
@@ -1 +1 @@
-{"files":{"CHANGELOG.md":"f624f016b8fa7e0f3aa46665f9fa7eb9ab46a02743fa14b29b3dad5bb9c57a9e","Cargo.lock":"f21b2f56fe0bd4911048ebeddc572a6ab6be3248a8de5f24f606bc4b96047455","Cargo.toml":"90819aab2f2f2696d640edcd5806293788279adf6b2f22edb04b25b37be82eb4","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"23f18e03dc49df91622fe2a76176497404e46ced8a715d9d2b67a7446571cca3","README.md":"813d262a320611ba874c4b2488256bdb2b4073649616a1471b389d464a704301","bors.toml":"ebd69f714a49dceb8fd10ebadfea6e2767be4732fdef49eddf6239151b4bc78c","examples/bench.rs":"1597a52529f75d6c5ad0b86759a775b1d723dfa810e2016317283b13594219da","examples/bench_acquire.rs":"9f4912ca262194cb55e893c33739c85c2f4868d07905b9dd3238552b6ce8a6e4","examples/bench_vs_lazy_static.rs":"d527294a2e73b53ac5faed8b316dfd1ae2a06adb31384134af21f10ce76333a5","examples/lazy_static.rs":"8bca1b264da21eceb1ccaf30477fc941bc71bedd030f1c6982ed3a7804abfb4f","examples/reentrant_init_deadlocks.rs":"ff84929de27a848e5b155549caa96db5db5f030afca975f8ba3f3da640083001","examples/regex.rs":"4a2e0fb093c7f5bbe0fff8689fc0c670c5334344a1bfda376f5faa98a05d459f","examples/test_synchronization.rs":"88abd5c16275bb2f2d77eaecf369d97681404a77b8edd0021f24bfd377c46be3","src/imp_cs.rs":"888fc76a1f4e55b1ece3ef748b0aa6a47be2d8d928c10f89ae6b4f12330c0e55","src/imp_pl.rs":"cd69042890c25fd3db97a4762abea4b814c961eadaf5d6ed7c7db17a6abd4c5b","src/imp_std.rs":"f13a5bfe08ac02eb0d5a0271cb5be9e8c534a81cddc3253aaca28b69bded8e65","src/lib.rs":"b1f8113fc779d6ea398ddb736fe5b3e3c4a63f23404569e4a08a5003bdd3774f","src/race.rs":"bb89ba6fe9420b8d3a173c1a484dde1b6a65289c5d72eb57cd3b0cca3ac23c04","tests/it.rs":"41f50496463a0036c45ed138f158d221d379e50a91ca452ba8ffe8caa7a59e3a"},"package":"86f0b0d4bf799edbc74508c1e8bf170ff5f41238e5f8225603ca7caaae2b7860"} \ No newline at end of file
+{"files":{"CHANGELOG.md":"ad20651be71bad8624d6fda2999d7766346dd8a286cdab4f1884eb8e6f2ac505","Cargo.lock":"a4f40f03460766a82f9baebfb58afc22970218bd7d4ab257f1c9c554e08bc74a","Cargo.toml":"3681ed9cbb458d0c95932843a5a7f96d84a61c50e8792a0c6950304ebd2f8c84","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"23f18e03dc49df91622fe2a76176497404e46ced8a715d9d2b67a7446571cca3","README.md":"e883909b29dc4d1c44270136fe2cfe7b2df6b416226b13928fdf9f1e15130be7","bors.toml":"ebd69f714a49dceb8fd10ebadfea6e2767be4732fdef49eddf6239151b4bc78c","examples/bench.rs":"1597a52529f75d6c5ad0b86759a775b1d723dfa810e2016317283b13594219da","examples/bench_acquire.rs":"9f4912ca262194cb55e893c33739c85c2f4868d07905b9dd3238552b6ce8a6e4","examples/bench_vs_lazy_static.rs":"d527294a2e73b53ac5faed8b316dfd1ae2a06adb31384134af21f10ce76333a5","examples/lazy_static.rs":"8bca1b264da21eceb1ccaf30477fc941bc71bedd030f1c6982ed3a7804abfb4f","examples/reentrant_init_deadlocks.rs":"ff84929de27a848e5b155549caa96db5db5f030afca975f8ba3f3da640083001","examples/regex.rs":"4a2e0fb093c7f5bbe0fff8689fc0c670c5334344a1bfda376f5faa98a05d459f","examples/test_synchronization.rs":"88abd5c16275bb2f2d77eaecf369d97681404a77b8edd0021f24bfd377c46be3","src/imp_cs.rs":"888fc76a1f4e55b1ece3ef748b0aa6a47be2d8d928c10f89ae6b4f12330c0e55","src/imp_pl.rs":"cd69042890c25fd3db97a4762abea4b814c961eadaf5d6ed7c7db17a6abd4c5b","src/imp_std.rs":"f13a5bfe08ac02eb0d5a0271cb5be9e8c534a81cddc3253aaca28b69bded8e65","src/lib.rs":"242f9f96e7efdeb5cc58d915514ad4ead96bb0616a004625a37f3eda0cb5ec45","src/race.rs":"0aea3dc70cc476a9da4d976e2e33052fef0cce3208e38dff52cfbf10a3a60ffb","tests/it.rs":"41f50496463a0036c45ed138f158d221d379e50a91ca452ba8ffe8caa7a59e3a"},"package":"6f61fba1741ea2b3d6a1e3178721804bb716a68a6aeba1149b5d52e3d464ea66"} \ No newline at end of file
diff --git a/vendor/once_cell/CHANGELOG.md b/vendor/once_cell/CHANGELOG.md
index 5cf6ea6b7..3f3a8623d 100644
--- a/vendor/once_cell/CHANGELOG.md
+++ b/vendor/once_cell/CHANGELOG.md
@@ -4,6 +4,10 @@
-
+## 1.17.0
+
+- Add `race::OnceRef` for storing a `&'a T`.
+
## 1.16.0
- Add `no_std` implementation based on `critical-section`,
diff --git a/vendor/once_cell/Cargo.lock b/vendor/once_cell/Cargo.lock
index b72bbabf5..1f838d5ec 100644
--- a/vendor/once_cell/Cargo.lock
+++ b/vendor/once_cell/Cargo.lock
@@ -74,7 +74,7 @@ checksum = "2f7254b99e31cad77da24b08ebf628882739a608578bb1bcdfc1f9c21260d7c0"
[[package]]
name = "once_cell"
-version = "1.16.0"
+version = "1.17.0"
dependencies = [
"atomic-polyfill",
"critical-section",
diff --git a/vendor/once_cell/Cargo.toml b/vendor/once_cell/Cargo.toml
index 6587f4e52..d2d7f1917 100644
--- a/vendor/once_cell/Cargo.toml
+++ b/vendor/once_cell/Cargo.toml
@@ -13,7 +13,7 @@
edition = "2021"
rust-version = "1.56"
name = "once_cell"
-version = "1.16.0"
+version = "1.17.0"
authors = ["Aleksey Kladov <aleksey.kladov@gmail.com>"]
exclude = [
"*.png",
diff --git a/vendor/once_cell/README.md b/vendor/once_cell/README.md
index de65dbbcc..737f2defd 100644
--- a/vendor/once_cell/README.md
+++ b/vendor/once_cell/README.md
@@ -51,6 +51,8 @@ More patterns and use-cases are in the [docs](https://docs.rs/once_cell/)!
* [lazycell](https://crates.io/crates/lazycell)
* [mitochondria](https://crates.io/crates/mitochondria)
* [lazy_static](https://crates.io/crates/lazy_static)
+* [async_once_cell](https://crates.io/crates/async_once_cell)
+* [generic_once_cell](https://crates.io/crates/generic_once_cell) (bring your own mutex)
The API of `once_cell` is being proposed for inclusion in
[`std`](https://github.com/rust-lang/rfcs/pull/2788).
diff --git a/vendor/once_cell/src/lib.rs b/vendor/once_cell/src/lib.rs
index 41313f736..83149ac4f 100644
--- a/vendor/once_cell/src/lib.rs
+++ b/vendor/once_cell/src/lib.rs
@@ -208,7 +208,6 @@
//! ```
//! use once_cell::sync::OnceCell;
//!
-//! #[derive(Debug)]
//! pub struct LateInit<T> { cell: OnceCell<T> }
//!
//! impl<T> LateInit<T> {
@@ -228,22 +227,24 @@
//! }
//! }
//!
-//! #[derive(Default, Debug)]
+//! #[derive(Default)]
//! struct A<'a> {
//! b: LateInit<&'a B<'a>>,
//! }
//!
-//! #[derive(Default, Debug)]
+//! #[derive(Default)]
//! struct B<'a> {
//! a: LateInit<&'a A<'a>>
//! }
//!
+//!
//! fn build_cycle() {
//! let a = A::default();
//! let b = B::default();
//! a.b.init(&b);
//! b.a.init(&a);
-//! println!("{:?}", a.b.a.b.a);
+//!
+//! let _a = &a.b.a.b.a;
//! }
//! ```
//!
@@ -315,6 +316,10 @@
//!
//! No, but you can use [`async_once_cell`](https://crates.io/crates/async_once_cell) instead.
//!
+//! **Can I bring my own mutex?**
+//!
+//! There is [generic_once_cell](https://crates.io/crates/generic_once_cell) to allow just that.
+//!
//! # Related crates
//!
//! * [double-checked-cell](https://github.com/niklasf/double-checked-cell)
@@ -323,6 +328,7 @@
//! * [mitochondria](https://crates.io/crates/mitochondria)
//! * [lazy_static](https://crates.io/crates/lazy_static)
//! * [async_once_cell](https://crates.io/crates/async_once_cell)
+//! * [generic_once_cell](https://crates.io/crates/generic_once_cell) (bring your own mutex)
//!
//! Most of this crate's functionality is available in `std` in nightly Rust.
//! See the [tracking issue](https://github.com/rust-lang/rust/issues/74465).
diff --git a/vendor/once_cell/src/race.rs b/vendor/once_cell/src/race.rs
index fd255c4c7..dff5847c8 100644
--- a/vendor/once_cell/src/race.rs
+++ b/vendor/once_cell/src/race.rs
@@ -25,6 +25,8 @@ use atomic_polyfill as atomic;
use core::sync::atomic;
use atomic::{AtomicUsize, Ordering};
+use core::cell::UnsafeCell;
+use core::marker::PhantomData;
use core::num::NonZeroUsize;
/// A thread-safe cell which can be written to only once.
@@ -172,6 +174,96 @@ impl OnceBool {
}
}
+/// A thread-safe cell which can be written to only once.
+pub struct OnceRef<'a, T> {
+ inner: OnceNonZeroUsize,
+ ghost: PhantomData<UnsafeCell<&'a T>>,
+}
+
+// TODO: Replace UnsafeCell with SyncUnsafeCell once stabilized
+unsafe impl<'a, T: Sync> Sync for OnceRef<'a, T> {}
+
+impl<'a, T> core::fmt::Debug for OnceRef<'a, T> {
+ fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
+ write!(f, "OnceRef({:?})", self.inner)
+ }
+}
+
+impl<'a, T> Default for OnceRef<'a, T> {
+ fn default() -> Self {
+ Self::new()
+ }
+}
+
+impl<'a, T> OnceRef<'a, T> {
+ /// Creates a new empty cell.
+ pub const fn new() -> OnceRef<'a, T> {
+ OnceRef { inner: OnceNonZeroUsize::new(), ghost: PhantomData }
+ }
+
+ /// Gets a reference to the underlying value.
+ pub fn get(&self) -> Option<&'a T> {
+ self.inner.get().map(|ptr| unsafe { &*(ptr.get() as *const T) })
+ }
+
+ /// Sets the contents of this cell to `value`.
+ ///
+ /// Returns `Ok(())` if the cell was empty and `Err(value)` if it was
+ /// full.
+ pub fn set(&self, value: &'a T) -> Result<(), ()> {
+ let ptr = NonZeroUsize::new(value as *const T as usize).unwrap();
+ self.inner.set(ptr)
+ }
+
+ /// Gets the contents of the cell, initializing it with `f` if the cell was
+ /// empty.
+ ///
+ /// If several threads concurrently run `get_or_init`, more than one `f` can
+ /// be called. However, all threads will return the same value, produced by
+ /// some `f`.
+ pub fn get_or_init<F>(&self, f: F) -> &'a T
+ where
+ F: FnOnce() -> &'a T,
+ {
+ let f = || NonZeroUsize::new(f() as *const T as usize).unwrap();
+ let ptr = self.inner.get_or_init(f);
+ unsafe { &*(ptr.get() as *const T) }
+ }
+
+ /// 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.
+ ///
+ /// If several threads concurrently run `get_or_init`, more than one `f` can
+ /// be called. However, all threads will return the same value, produced by
+ /// some `f`.
+ pub fn get_or_try_init<F, E>(&self, f: F) -> Result<&'a T, E>
+ where
+ F: FnOnce() -> Result<&'a T, E>,
+ {
+ let f = || f().map(|value| NonZeroUsize::new(value as *const T as usize).unwrap());
+ let ptr = self.inner.get_or_try_init(f)?;
+ unsafe { Ok(&*(ptr.get() as *const T)) }
+ }
+
+ /// ```compile_fail
+ /// use once_cell::race::OnceRef;
+ ///
+ /// let mut l = OnceRef::new();
+ ///
+ /// {
+ /// let y = 2;
+ /// let mut r = OnceRef::new();
+ /// r.set(&y).unwrap();
+ /// core::mem::swap(&mut l, &mut r);
+ /// }
+ ///
+ /// // l now contains a dangling reference to y
+ /// eprintln!("uaf: {}", l.get().unwrap());
+ /// ```
+ fn _dummy() {}
+}
+
#[cfg(feature = "alloc")]
pub use self::once_box::OnceBox;
diff --git a/vendor/overload/.cargo-checksum.json b/vendor/overload/.cargo-checksum.json
new file mode 100644
index 000000000..dfd877e5b
--- /dev/null
+++ b/vendor/overload/.cargo-checksum.json
@@ -0,0 +1 @@
+{"files":{"Cargo.toml":"7dae2c1f39fcd51345ecd0c84ff5ffd2544087b2fce175d253d388c4e61af61c","LICENSE":"0d1bdcc9f95914fc1709781e65a75b85db7f73fd1c335bf6f7b1aae618df322e","README.md":"163212683c01ec376c6fc1d4b6acb10cc1cb4af622e9ddbd869a48c7ac9c6169","logo.png":"6992807474a15bf663aeeb357b6038cdbaed7f5787a26941d1fc006176c3a6ae","src/assignment.rs":"f4ff0b288ed0d7cd03bd53d3c5f452ffdd36e20d816f6f68762ace1c2609a445","src/binary.rs":"321c474d28d7b8367ba71ad6b8691d023cefce4d2b9417c454e57ada42b618c6","src/lib.rs":"542d5b297d3b9039450dce66e58b89b8d3707ee322230f7e9cc25f367e6338a1","src/unary.rs":"f2f87399a153e225acc4899651ad079bf02b4fe426fb5c94799eb2747b84a870","tests/assignment.rs":"635f4a214ad9e725d2f46d12983a96167ac7bd8af979e69d20bdcd8739d9e3a9","tests/binary.rs":"1acc26022414a6d54f7fe18d85c41433dec2b6adb6615d04a261f9b47c438b88","tests/unary.rs":"4bc733e466c19296bc3738f866b710fc421a04f6dd0180348bd2fddecdc88c51"},"package":"b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39"} \ No newline at end of file
diff --git a/vendor/rls-data/Cargo.toml b/vendor/overload/Cargo.toml
index 54d416498..1e0fbc514 100644
--- a/vendor/rls-data/Cargo.toml
+++ b/vendor/overload/Cargo.toml
@@ -12,19 +12,11 @@
[package]
edition = "2018"
-name = "rls-data"
-version = "0.19.1"
-authors = ["Nick Cameron <ncameron@mozilla.com>"]
-description = "Data structures used by the RLS and Rust compiler"
-categories = ["development-tools"]
-license = "Apache-2.0/MIT"
-repository = "https://github.com/rust-lang/rls"
-[dependencies.rls-span]
-version = "0.5.0"
-
-[dependencies.serde]
-version = "1.0"
-
-[features]
-default = ["derive"]
-derive = ["serde/derive", "rls-span/derive"]
+name = "overload"
+version = "0.1.1"
+authors = ["Daniel Salvadori <danaugrs@gmail.com>"]
+description = "Provides a macro to simplify operator overloading."
+keywords = ["operator", "overloading", "macro", "op"]
+categories = ["rust-patterns"]
+license = "MIT"
+repository = "https://github.com/danaugrs/overload"
diff --git a/vendor/overload/LICENSE b/vendor/overload/LICENSE
new file mode 100644
index 000000000..0ed504b3c
--- /dev/null
+++ b/vendor/overload/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2019 Daniel Augusto Rizzi Salvadori
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE. \ No newline at end of file
diff --git a/vendor/overload/README.md b/vendor/overload/README.md
new file mode 100644
index 000000000..c40088ead
--- /dev/null
+++ b/vendor/overload/README.md
@@ -0,0 +1,64 @@
+<p align="center"><img width="460" src="https://github.com/danaugrs/overload/blob/master/logo.png"></p>
+<p align="center">
+ <a href="https://docs.rs/overload"><img src="https://docs.rs/overload/badge.svg"/></a>
+ <a href="https://crates.io/crates/overload"><img src="https://img.shields.io/crates/v/overload.svg"/></a>
+</p>
+
+Provides a macro to simplify operator overloading. See the [documentation](https://docs.rs/overload/) for details and supported operators.
+
+## Example
+
+```rust
+extern crate overload;
+use overload::overload;
+use std::ops; // <- don't forget this or you'll get nasty errors
+
+#[derive(PartialEq, Debug)]
+struct Val {
+ v: i32
+}
+
+overload!((a: ?Val) + (b: ?Val) -> Val { Val { v: a.v + b.v } });
+```
+
+The macro call in the snippet above generates the following code:
+
+```rust
+impl ops::Add<Val> for Val {
+ type Output = Val;
+ fn add(self, b: Val) -> Self::Output {
+ let a = self;
+ Val { v: a.v + b.v }
+ }
+}
+impl ops::Add<&Val> for Val {
+ type Output = Val;
+ fn add(self, b: &Val) -> Self::Output {
+ let a = self;
+ Val { v: a.v + b.v }
+ }
+}
+impl ops::Add<Val> for &Val {
+ type Output = Val;
+ fn add(self, b: Val) -> Self::Output {
+ let a = self;
+ Val { v: a.v + b.v }
+ }
+}
+impl ops::Add<&Val> for &Val {
+ type Output = Val;
+ fn add(self, b: &Val) -> Self::Output {
+ let a = self;
+ Val { v: a.v + b.v }
+ }
+}
+```
+
+We are now able to add `Val`s and `&Val`s in any combination:
+
+```rust
+assert_eq!(Val{v:3} + Val{v:5}, Val{v:8});
+assert_eq!(Val{v:3} + &Val{v:5}, Val{v:8});
+assert_eq!(&Val{v:3} + Val{v:5}, Val{v:8});
+assert_eq!(&Val{v:3} + &Val{v:5}, Val{v:8});
+```
diff --git a/vendor/overload/logo.png b/vendor/overload/logo.png
new file mode 100644
index 000000000..61d33090b
--- /dev/null
+++ b/vendor/overload/logo.png
Binary files differ
diff --git a/vendor/overload/src/assignment.rs b/vendor/overload/src/assignment.rs
new file mode 100644
index 000000000..550f07a96
--- /dev/null
+++ b/vendor/overload/src/assignment.rs
@@ -0,0 +1,27 @@
+#[doc(hidden)]
+#[macro_export(local_inner_macros)]
+macro_rules! _overload_assignment {
+ (+=, $($t:tt)+) => (_overload_assignment_internal!(AddAssign, add_assign, $($t)+););
+ (-=, $($t:tt)+) => (_overload_assignment_internal!(SubAssign, sub_assign, $($t)+););
+ (*=, $($t:tt)+) => (_overload_assignment_internal!(MulAssign, mul_assign, $($t)+););
+ (/=, $($t:tt)+) => (_overload_assignment_internal!(DivAssign, div_assign, $($t)+););
+ (%=, $($t:tt)+) => (_overload_assignment_internal!(RemAssign, rem_assign, $($t)+););
+ (&=, $($t:tt)+) => (_overload_assignment_internal!(BitAndAssign, bitand_assign, $($t)+););
+ (|=, $($t:tt)+) => (_overload_assignment_internal!(BitOrAssign, bitor_assign, $($t)+););
+ (^=, $($t:tt)+) => (_overload_assignment_internal!(BitXorAssign, bitxor_assign, $($t)+););
+ (<<=, $($t:tt)+) => (_overload_assignment_internal!(ShlAssign, shl_assign, $($t)+););
+ (>>=, $($t:tt)+) => (_overload_assignment_internal!(ShrAssign, shr_assign, $($t)+););
+}
+
+#[doc(hidden)]
+#[macro_export(local_inner_macros)]
+macro_rules! _overload_assignment_internal {
+ ($op_trait:ident, $op_fn:ident, $li:ident, $lt:ty, $ri:ident, $rt:ty, $body:block) => (
+ impl ops::$op_trait<$rt> for $lt {
+ fn $op_fn(&mut self, $ri: $rt) {
+ let $li = self;
+ $body
+ }
+ }
+ );
+}
diff --git a/vendor/overload/src/binary.rs b/vendor/overload/src/binary.rs
new file mode 100644
index 000000000..b4c781bff
--- /dev/null
+++ b/vendor/overload/src/binary.rs
@@ -0,0 +1,28 @@
+#[doc(hidden)]
+#[macro_export(local_inner_macros)]
+macro_rules! _overload_binary {
+ (+, $($t:tt)+) => (_overload_binary_internal!(Add, add, $($t)+););
+ (-, $($t:tt)+) => (_overload_binary_internal!(Sub, sub, $($t)+););
+ (*, $($t:tt)+) => (_overload_binary_internal!(Mul, mul, $($t)+););
+ (/, $($t:tt)+) => (_overload_binary_internal!(Div, div, $($t)+););
+ (%, $($t:tt)+) => (_overload_binary_internal!(Rem, rem, $($t)+););
+ (&, $($t:tt)+) => (_overload_binary_internal!(BitAnd, bitand, $($t)+););
+ (|, $($t:tt)+) => (_overload_binary_internal!(BitOr, bitor, $($t)+););
+ (^, $($t:tt)+) => (_overload_binary_internal!(BitXor, bitxor, $($t)+););
+ (<<, $($t:tt)+) => (_overload_binary_internal!(Shl, shl, $($t)+););
+ (>>, $($t:tt)+) => (_overload_binary_internal!(Shr, shr, $($t)+););
+}
+
+#[doc(hidden)]
+#[macro_export(local_inner_macros)]
+macro_rules! _overload_binary_internal {
+ ($op_trait:ident, $op_fn:ident, $li:ident, $lt:ty, $ri:ident, $rt:ty, $out:ty, $body:block) => (
+ impl ops::$op_trait<$rt> for $lt {
+ type Output = $out;
+ fn $op_fn(self, $ri: $rt) -> Self::Output {
+ let $li = self;
+ $body
+ }
+ }
+ );
+}
diff --git a/vendor/overload/src/lib.rs b/vendor/overload/src/lib.rs
new file mode 100644
index 000000000..9364d7a38
--- /dev/null
+++ b/vendor/overload/src/lib.rs
@@ -0,0 +1,257 @@
+//! Provides a macro to simplify operator overloading.
+//!
+//! To use, include the following:
+//! ```
+//! extern crate overload;
+//! use overload::overload;
+//! use std::ops; // <- don't forget this or you'll get nasty errors
+//! ```
+//!
+//! # Introduction
+//!
+//! Suppose we have the following `struct` definition:
+//! ```
+//! #[derive(PartialEq, Debug)]
+//! struct Val {
+//! v: i32
+//! }
+//! ```
+//! We can overload the addition of `Val`s like so:
+//! ```
+//! # extern crate overload;
+//! # use overload::overload;
+//! # use std::ops;
+//! # #[derive(PartialEq, Debug)]
+//! # struct Val {
+//! # v: i32
+//! # }
+//! overload!((a: Val) + (b: Val) -> Val { Val { v: a.v + b.v } });
+//! ```
+//! The macro call above generates the following code:
+//! ```ignore
+//! impl ops::Add<Val> for Val {
+//! type Output = Val;
+//! fn add(self, b: Val) -> Self::Output {
+//! let a = self;
+//! Val { v: a.v + b.v }
+//! }
+//! }
+//! ```
+//! We are now able to add `Val`s:
+//! ```
+//! # extern crate overload;
+//! # use overload::overload;
+//! # use std::ops;
+//! # #[derive(PartialEq, Debug)]
+//! # struct Val {
+//! # v: i32
+//! # }
+//! # overload!((a: Val) + (b: Val) -> Val { Val { v: a.v + b.v } });
+//! assert_eq!(Val{v:3} + Val{v:5}, Val{v:8});
+//! ```
+//!
+//! # Owned and borrowed types
+//!
+//! If we also wanted to overload addition for the borrowed type `&Val` we could write:
+//! ```
+//! # extern crate overload;
+//! # use overload::overload;
+//! # use std::ops;
+//! # #[derive(PartialEq, Debug)]
+//! # struct Val {
+//! # v: i32
+//! # }
+//! overload!((a: &Val) + (b: &Val) -> Val { Val { v: a.v + b.v } });
+//! ```
+//! We might also want to overload addition between the owned and borrowed types:
+//! ```
+//! # extern crate overload;
+//! # use overload::overload;
+//! # use std::ops;
+//! # #[derive(PartialEq, Debug)]
+//! # struct Val {
+//! # v: i32
+//! # }
+//! overload!((a: Val) + (b: &Val) -> Val { Val { v: a.v + b.v } });
+//! overload!((a: &Val) + (b: Val) -> Val { Val { v: a.v + b.v } });
+//! ```
+//! Let's see how we can write these combinations more concisely.
+//!
+//! We can include a `?` in front of a type to indicate that it should stand in for both the owned and borrowed type.
+//!
+//! To overload addition for all four combinations between `Val` and `&Val` we can therefore simply include a `?` in front of both types:
+//! ```
+//! # extern crate overload;
+//! # use overload::overload;
+//! # use std::ops;
+//! # #[derive(PartialEq, Debug)]
+//! # struct Val {
+//! # v: i32
+//! # }
+//! overload!((a: ?Val) + (b: ?Val) -> Val { Val { v: a.v + b.v } });
+//! ```
+//! The macro call above generates the following code:
+//! ```ignore
+//! impl ops::Add<Val> for Val {
+//! type Output = Val;
+//! fn add(self, b: Val) -> Self::Output {
+//! let a = self;
+//! Val { v: a.v + b.v }
+//! }
+//! }
+//!
+//! impl ops::Add<&Val> for Val {
+//! type Output = Val;
+//! fn add(self, b: &Val) -> Self::Output {
+//! let a = self;
+//! Val { v: a.v + b.v }
+//! }
+//! }
+//!
+//! impl ops::Add<Val> for &Val {
+//! type Output = Val;
+//! fn add(self, b: Val) -> Self::Output {
+//! let a = self;
+//! Val { v: a.v + b.v }
+//! }
+//! }
+//!
+//! impl ops::Add<&Val> for &Val {
+//! type Output = Val;
+//! fn add(self, b: &Val) -> Self::Output {
+//! let a = self;
+//! Val { v: a.v + b.v }
+//! }
+//! }
+//! ```
+//! We are now able to add `Val`s and `&Val`s in any combination:
+//! ```
+//! # extern crate overload;
+//! # use overload::overload;
+//! # use std::ops;
+//! # #[derive(PartialEq, Debug)]
+//! # struct Val {
+//! # v: i32
+//! # }
+//! # overload!((a: ?Val) + (b: ?Val) -> Val { Val { v: a.v + b.v } });
+//! assert_eq!(Val{v:3} + Val{v:5}, Val{v:8});
+//! assert_eq!(Val{v:3} + &Val{v:5}, Val{v:8});
+//! assert_eq!(&Val{v:3} + Val{v:5}, Val{v:8});
+//! assert_eq!(&Val{v:3} + &Val{v:5}, Val{v:8});
+//! ```
+//!
+//! # Binary operators
+//!
+//! The general syntax to overload a binary operator between types `<a_type>` and `<b_type>` is:
+//! ```ignore
+//! overload!((<a_ident>: <a_type>) <op> (<b_ident>: <b_type>) -> <out_type> { /*body*/ });
+//! ```
+//! Inside the body you can use `<a_ident>` and `<b_ident>` freely to perform any computation.
+//!
+//! The last line of the body needs to be an expression (i.e. no `;` at the end of the line) of type `<out_type>`.
+//!
+//! | Operator | Example | Trait |
+//! |----------|-----------------------------------------------------------------|--------|
+//! | + | `overload!((a: A) + (b: B) -> C { /*...*/ );` | Add |
+//! | - | `overload!((a: A) - (b: B) -> C { /*...*/ );` | Sub |
+//! | * | `overload!((a: A) * (b: B) -> C { /*...*/ );` | Mul |
+//! | / | `overload!((a: A) / (b: B) -> C { /*...*/ );` | Div |
+//! | % | `overload!((a: A) % (b: B) -> C { /*...*/ );` | Rem |
+//! | & | `overload!((a: A) & (b: B) -> C { /*...*/ );` | BitAnd |
+//! | \| | <code>overload!((a: A) &vert; (b: B) -> C { /\*...*\/ );</code> | BitOr |
+//! | ^ | `overload!((a: A) ^ (b: B) -> C { /*...*/ );` | BitXor |
+//! | << | `overload!((a: A) << (b: B) -> C { /*...*/ );` | Shl |
+//! | >> | `overload!((a: A) >> (b: B) -> C { /*...*/ );` | Shr |
+//!
+//! # Assignment operators
+//!
+//! The general syntax to overload an assignment operator between types `<a_type>` and `<b_type>` is:
+//! ```ignore
+//! overload!((<a_ident>: &mut <a_type>) <op> (<b_ident>: <b_type>) { /*body*/ });
+//! ```
+//! Inside the body you can use `<a_ident>` and `<b_ident>` freely to perform any computation and mutate `<a_ident>` as desired.
+//!
+//! | Operator | Example | Trait |
+//! |----------|------------------------------------------------------------------|--------------|
+//! | += | `overload!((a: &mut A) += (b: B) { /*...*/ );` | AddAssign |
+//! | -= | `overload!((a: &mut A) -= (b: B) { /*...*/ );` | SubAssign |
+//! | *= | `overload!((a: &mut A) *= (b: B) { /*...*/ );` | MulAssign |
+//! | /= | `overload!((a: &mut A) /= (b: B) { /*...*/ );` | DivAssign |
+//! | %= | `overload!((a: &mut A) %= (b: B) { /*...*/ );` | RemAssign |
+//! | &= | `overload!((a: &mut A) &= (b: B) { /*...*/ );` | BitAndAssign |
+//! | \|= | <code>overload!((a: &mut A) &vert;= (b: B) { /\*...*\/ );</code> | BitOrAssign |
+//! | ^= | `overload!((a: &mut A) ^= (b: B) { /*...*/ );` | BitXorAssign |
+//! | <<= | `overload!((a: &mut A) <<= (b: B) { /*...*/ );` | ShlAssign |
+//! | >>= | `overload!((a: &mut A) >>= (b: B) { /*...*/ );` | ShrAssign |
+//!
+//! # Unary operators
+//!
+//! The general syntax to overload a unary operator for type `<a_type>` is:
+//! ```ignore
+//! overload!(<op> (<a_ident>: <a_type>) -> <out_type> { /*body*/ });
+//! ```
+//! Inside the body you can use `<a_ident>` freely to perform any computation.
+//!
+//! The last line of the body needs to be an expression (i.e. no `;` at the end of the line) of type `<out_type>`.
+//!
+//! | Operator | Example | Trait |
+//! |----------|---------------------------------------------------------|-------|
+//! | - | `overload!(- (a: A) -> B { /*...*/ );` | Neg |
+//! | ! | `overload!(! (a: A) -> B { /*...*/ );` | Not |
+//!
+//! # Notes
+//!
+//! Remember that you can only overload operators between one or more types if at least one of the types is defined in the current crate.
+
+#[macro_use]
+mod unary;
+
+#[macro_use]
+mod assignment;
+
+#[macro_use]
+mod binary;
+
+/// Overloads an operator. See the [module level documentation](index.html) for more information.
+#[macro_export(local_inner_macros)]
+macro_rules! overload {
+ // Unary (both owned and borrowed)
+ ($op:tt ($i:ident : ? $t:ty) -> $out:ty $body:block) => (
+ _overload_unary!($op, $i, $t, $out, $body);
+ _overload_unary!($op, $i, &$t, $out, $body);
+ );
+ // Unary (either owned or borrowed)
+ ($op:tt ($i:ident : $t:ty) -> $out:ty $body:block) => (
+ _overload_unary!($op, $i, $t, $out, $body);
+ );
+ // Assignment (both owned and borrowed)
+ (($li:ident : &mut $lt:ty) $op:tt ($ri:ident : ? $rt:ty) $body:block) => (
+ _overload_assignment!($op, $li, $lt, $ri, $rt, $body);
+ _overload_assignment!($op, $li, $lt, $ri, &$rt, $body);
+ );
+ // Assignment (either owned or borrowed)
+ (($li:ident : &mut $lt:ty) $op:tt ($ri:ident : $rt:ty) $body:block) => (
+ _overload_assignment!($op, $li, $lt, $ri, $rt, $body);
+ );
+ // Binary (both - both)
+ (($li:ident : ? $lt:ty) $op:tt ($ri:ident : ? $rt:ty) -> $out:ty $body:block) => (
+ _overload_binary!($op, $li, $lt, $ri, $rt, $out, $body);
+ _overload_binary!($op, $li, $lt, $ri, &$rt, $out, $body);
+ _overload_binary!($op, $li, &$lt, $ri, $rt, $out, $body);
+ _overload_binary!($op, $li, &$lt, $ri, &$rt, $out, $body);
+ );
+ // Binary (both - either)
+ (($li:ident : ? $lt:ty) $op:tt ($ri:ident : $rt:ty) -> $out:ty $body:block) => (
+ _overload_binary!($op, $li, $lt, $ri, $rt, $out, $body);
+ _overload_binary!($op, $li, &$lt, $ri, $rt, $out, $body);
+ );
+ // Binary (either - both)
+ (($li:ident : $lt:ty) $op:tt ($ri:ident : ? $rt:ty) -> $out:ty $body:block) => (
+ _overload_binary!($op, $li, $lt, $ri, $rt, $out, $body);
+ _overload_binary!($op, $li, $lt, $ri, &$rt, $out, $body);
+ );
+ // Binary (either - either)
+ (($li:ident : $lt:ty) $op:tt ($ri:ident : $rt:ty) -> $out:ty $body:block) => (
+ _overload_binary!($op, $li, $lt, $ri, $rt, $out, $body);
+ );
+}
diff --git a/vendor/overload/src/unary.rs b/vendor/overload/src/unary.rs
new file mode 100644
index 000000000..da8f6b590
--- /dev/null
+++ b/vendor/overload/src/unary.rs
@@ -0,0 +1,20 @@
+#[doc(hidden)]
+#[macro_export(local_inner_macros)]
+macro_rules! _overload_unary {
+ (-, $($t:tt)+) => (_overload_unary_internal!(Neg, neg, $($t)+););
+ (!, $($t:tt)+) => (_overload_unary_internal!(Not, not, $($t)+););
+}
+
+#[doc(hidden)]
+#[macro_export(local_inner_macros)]
+macro_rules! _overload_unary_internal {
+ ($op_trait:ident, $op_fn:ident, $i:ident, $t:ty, $out:ty, $body:block) => (
+ impl ops::$op_trait for $t {
+ type Output = $out;
+ fn $op_fn(self) -> Self::Output {
+ let $i = self;
+ $body
+ }
+ }
+ );
+}
diff --git a/vendor/overload/tests/assignment.rs b/vendor/overload/tests/assignment.rs
new file mode 100644
index 000000000..9657b4bd4
--- /dev/null
+++ b/vendor/overload/tests/assignment.rs
@@ -0,0 +1,89 @@
+extern crate overload;
+use overload::overload;
+use std::ops;
+
+#[derive(PartialEq, Debug)]
+struct A(i32);
+
+#[derive(PartialEq, Debug)]
+struct B(i32);
+
+overload!((a: &mut A) += (b: B) { a.0 += b.0; });
+#[test]
+fn add_assign() {
+ let mut a = A(3);
+ a += B(4);
+ assert_eq!(A(3 + 4), a);
+}
+
+overload!((a: &mut A) -= (b: B) { a.0 -= b.0; });
+#[test]
+fn sub_assign() {
+ let mut a = A(3);
+ a -= B(4);
+ assert_eq!(A(3 - 4), a);
+}
+
+overload!((a: &mut A) *= (b: B) { a.0 *= b.0; });
+#[test]
+fn mul_assign() {
+ let mut a = A(3);
+ a *= B(4);
+ assert_eq!(A(3 * 4), a);
+}
+
+overload!((a: &mut A) /= (b: B) { a.0 /= b.0; });
+#[test]
+fn div_assign() {
+ let mut a = A(6);
+ a /= B(3);
+ assert_eq!(A(6 / 3), a);
+}
+
+overload!((a: &mut A) %= (b: B) { a.0 %= b.0; });
+#[test]
+fn rem_assign() {
+ let mut a = A(6);
+ a %= B(4);
+ assert_eq!(A(6 % 4), a);
+}
+
+overload!((a: &mut A) &= (b: B) { a.0 &= b.0; });
+#[test]
+fn bitand_assign() {
+ let mut a = A(6);
+ a &= B(4);
+ assert_eq!(A(6 & 4), a);
+}
+
+overload!((a: &mut A) |= (b: B) { a.0 |= b.0; });
+#[test]
+fn bitor_assign() {
+ let mut a = A(6);
+ a |= B(4);
+ assert_eq!(A(6 | 4), a);
+}
+
+overload!((a: &mut A) ^= (b: B) { a.0 ^= b.0; });
+#[test]
+fn bitxor_assign() {
+ let mut a = A(6);
+ a ^= B(4);
+ assert_eq!(A(6 ^ 4), a);
+}
+
+overload!((a: &mut A) <<= (b: B) { a.0 <<= b.0; });
+#[test]
+fn shl_assign() {
+ let mut a = A(6);
+ a <<= B(4);
+ assert_eq!(A(6 << 4), a);
+}
+
+overload!((a: &mut A) >>= (b: B) { a.0 >>= b.0; });
+#[test]
+fn shr_assign() {
+ let mut a = A(6);
+ a >>= B(4);
+ assert_eq!(A(6 >> 4), a);
+}
diff --git a/vendor/overload/tests/binary.rs b/vendor/overload/tests/binary.rs
new file mode 100644
index 000000000..2fb209ad3
--- /dev/null
+++ b/vendor/overload/tests/binary.rs
@@ -0,0 +1,72 @@
+extern crate overload;
+use overload::overload;
+use std::ops;
+
+#[derive(PartialEq, Debug)]
+struct A(i32);
+
+#[derive(PartialEq, Debug)]
+struct B(i32);
+
+#[derive(PartialEq, Debug)]
+struct C(i32);
+
+overload!((a: A) + (b: B) -> C { C(a.0 + b.0) });
+#[test]
+fn add() {
+ assert_eq!(A(3) + B(4), C(3 + 4));
+}
+
+overload!((a: A) - (b: B) -> C { C(a.0 - b.0) });
+#[test]
+fn sub() {
+ assert_eq!(A(3) - B(4), C(3 - 4));
+}
+
+overload!((a: A) * (b: B) -> C { C(a.0 * b.0) });
+#[test]
+fn mul() {
+ assert_eq!(A(3) * B(4), C(3 * 4));
+}
+
+overload!((a: A) / (b: B) -> C { C(a.0 / b.0) });
+#[test]
+fn div() {
+ assert_eq!(A(6) / B(3), C(6 / 3));
+}
+
+overload!((a: A) % (b: B) -> C { C(a.0 % b.0) });
+#[test]
+fn rem() {
+ assert_eq!(A(6) % B(4), C(6 % 4));
+}
+
+overload!((a: A) & (b: B) -> C { C(a.0 & b.0) });
+#[test]
+fn bitand() {
+ assert_eq!(A(6) & B(4), C(6 & 4));
+}
+
+overload!((a: A) | (b: B) -> C { C(a.0 | b.0) });
+#[test]
+fn bitor() {
+ assert_eq!(A(6) | B(4), C(6 | 4));
+}
+
+overload!((a: A) ^ (b: B) -> C { C(a.0 ^ b.0) });
+#[test]
+fn bitxor() {
+ assert_eq!(A(6) ^ B(4), C(6 ^ 4));
+}
+
+overload!((a: A) << (b: B) -> C { C(a.0 << b.0) });
+#[test]
+fn shl() {
+ assert_eq!(A(6) << B(4), C(6 << 4));
+}
+
+overload!((a: A) >> (b: B) -> C { C(a.0 >> b.0) });
+#[test]
+fn shr() {
+ assert_eq!(A(6) >> B(4), C(6 >> 4));
+}
diff --git a/vendor/overload/tests/unary.rs b/vendor/overload/tests/unary.rs
new file mode 100644
index 000000000..76a3925fe
--- /dev/null
+++ b/vendor/overload/tests/unary.rs
@@ -0,0 +1,21 @@
+extern crate overload;
+use overload::overload;
+use std::ops;
+
+#[derive(PartialEq, Debug)]
+struct A(i32);
+
+#[derive(PartialEq, Debug)]
+struct B(i32);
+
+overload!(- (a: A) -> B { B(-a.0) });
+#[test]
+fn neg() {
+ assert_eq!(-A(3), B(-3));
+}
+
+overload!(! (a: A) -> B { B(!a.0) });
+#[test]
+fn not() {
+ assert_eq!(!A(3), B(!3));
+}
diff --git a/vendor/parking_lot_core-0.8.5/.cargo-checksum.json b/vendor/parking_lot_core-0.8.6/.cargo-checksum.json
index 8eb5c0c8d..0306c5e78 100644
--- a/vendor/parking_lot_core-0.8.5/.cargo-checksum.json
+++ b/vendor/parking_lot_core-0.8.6/.cargo-checksum.json
@@ -1 +1 @@
-{"files":{"Cargo.toml":"fdba14f9aee05b55ba008685e1d3a9050d14a56251608b23cc0970caa6b9fae4","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"c9a75f18b9ab2927829a208fc6aa2cf4e63b8420887ba29cdb265d6619ae82d5","build.rs":"29e629057144d1238dcd8ea70ad6cbb6ec14ca742797af3fa9335710ff5cbaaa","src/lib.rs":"7baf09034aafc28f7dbb1550cdde89221e4eb5dfda51b55aeb652ee8710c715d","src/parking_lot.rs":"58125667bd78399e8753b6bd8acef84f180f369f0bc174c573887176bab9f9d3","src/spinwait.rs":"d568d8a81f9144ec4c4a139dc934d7d04ee1656a4a221eb548742fe7aba09ab1","src/thread_parker/generic.rs":"574aecb3c325012b683eca4135441ec73f44c33cc9955aa05db24d7e4c991cd7","src/thread_parker/linux.rs":"4a2c76b3dc09301ceb73d904460f49d91bc1a2492cc123ee26ca22ece3faae79","src/thread_parker/mod.rs":"9c675b7690bbde62e88d946fad218623d423edccff4e01e8e52b116d815c695c","src/thread_parker/redox.rs":"91ca107c4edffa57e87294cadec3b6010b584fb272c044e2557c925dbcb90f6a","src/thread_parker/sgx.rs":"898ced116fb7b0ac077b5977b5bcac610f1d55beffb613ec73e083b1ef09cc28","src/thread_parker/unix.rs":"02a17ad1241e8547cc7ee096318757b01d328354b639d0f799fca66ff2f07439","src/thread_parker/wasm.rs":"903b7eec240cdbe8a23467f6b41d042d93b35755bd1763be02f9cc55756c4aec","src/thread_parker/wasm_atomic.rs":"cf761157803256b18205e747bc99e30b18d5410c27121fa9595e12cb51bb6bef","src/thread_parker/windows/keyed_event.rs":"fc1cf4e592d814c4c949217d91317ec2afb6048430abebb3cea2e8487b369734","src/thread_parker/windows/mod.rs":"c99a3871e69800452a56928a9e870530b7f48a563a4d3efe6184103147899f0c","src/thread_parker/windows/waitaddress.rs":"8e037df2a5692905e2bc2d4ea955295ab92bcc7e26eea0bb7a4eaac9ce657321","src/util.rs":"285e6133150645525f2ca1ece41f6d35bad4e7c5e08b42b20c99d2a97e04a974","src/word_lock.rs":"9ba49082359c35ad5b4e8d219fede1ffca75225f9ccb971cbba01f20e2ed2738"},"package":"d76e8e1493bcac0d2766c42737f34458f1c8c50c0d23bcb24ea953affb273216"} \ No newline at end of file
+{"files":{"Cargo.toml":"eb7f5eba6c03746da0585ae4abdc3ce74103ac9b9fc6f0d1db02fe5bf786e810","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"c9a75f18b9ab2927829a208fc6aa2cf4e63b8420887ba29cdb265d6619ae82d5","build.rs":"29e629057144d1238dcd8ea70ad6cbb6ec14ca742797af3fa9335710ff5cbaaa","src/lib.rs":"7baf09034aafc28f7dbb1550cdde89221e4eb5dfda51b55aeb652ee8710c715d","src/parking_lot.rs":"58125667bd78399e8753b6bd8acef84f180f369f0bc174c573887176bab9f9d3","src/spinwait.rs":"d568d8a81f9144ec4c4a139dc934d7d04ee1656a4a221eb548742fe7aba09ab1","src/thread_parker/generic.rs":"574aecb3c325012b683eca4135441ec73f44c33cc9955aa05db24d7e4c991cd7","src/thread_parker/linux.rs":"98ee0cc037e2eea6bd92a5460ce8dad62d4c25dae209dfc638e69dba71e29c85","src/thread_parker/mod.rs":"9c675b7690bbde62e88d946fad218623d423edccff4e01e8e52b116d815c695c","src/thread_parker/redox.rs":"91ca107c4edffa57e87294cadec3b6010b584fb272c044e2557c925dbcb90f6a","src/thread_parker/sgx.rs":"898ced116fb7b0ac077b5977b5bcac610f1d55beffb613ec73e083b1ef09cc28","src/thread_parker/unix.rs":"02a17ad1241e8547cc7ee096318757b01d328354b639d0f799fca66ff2f07439","src/thread_parker/wasm.rs":"903b7eec240cdbe8a23467f6b41d042d93b35755bd1763be02f9cc55756c4aec","src/thread_parker/wasm_atomic.rs":"cf761157803256b18205e747bc99e30b18d5410c27121fa9595e12cb51bb6bef","src/thread_parker/windows/keyed_event.rs":"fc1cf4e592d814c4c949217d91317ec2afb6048430abebb3cea2e8487b369734","src/thread_parker/windows/mod.rs":"c99a3871e69800452a56928a9e870530b7f48a563a4d3efe6184103147899f0c","src/thread_parker/windows/waitaddress.rs":"8e037df2a5692905e2bc2d4ea955295ab92bcc7e26eea0bb7a4eaac9ce657321","src/util.rs":"285e6133150645525f2ca1ece41f6d35bad4e7c5e08b42b20c99d2a97e04a974","src/word_lock.rs":"9ba49082359c35ad5b4e8d219fede1ffca75225f9ccb971cbba01f20e2ed2738"},"package":"60a2cfe6f0ad2bfc16aefa463b497d5c7a5ecd44a23efa72aa342d90177356dc"} \ No newline at end of file
diff --git a/vendor/parking_lot_core-0.8.5/Cargo.toml b/vendor/parking_lot_core-0.8.6/Cargo.toml
index 7afeb4114..698151644 100644
--- a/vendor/parking_lot_core-0.8.5/Cargo.toml
+++ b/vendor/parking_lot_core-0.8.6/Cargo.toml
@@ -12,13 +12,20 @@
[package]
edition = "2018"
name = "parking_lot_core"
-version = "0.8.5"
+version = "0.8.6"
authors = ["Amanieu d'Antras <amanieu@gmail.com>"]
description = "An advanced API for creating custom synchronization primitives."
-keywords = ["mutex", "condvar", "rwlock", "once", "thread"]
+keywords = [
+ "mutex",
+ "condvar",
+ "rwlock",
+ "once",
+ "thread",
+]
categories = ["concurrency"]
license = "Apache-2.0/MIT"
repository = "https://github.com/Amanieu/parking_lot"
+
[dependencies.backtrace]
version = "0.3.60"
optional = true
@@ -41,12 +48,27 @@ version = "4.0.0"
optional = true
[features]
-deadlock_detection = ["petgraph", "thread-id", "backtrace"]
+deadlock_detection = [
+ "petgraph",
+ "thread-id",
+ "backtrace",
+]
nightly = []
+
[target."cfg(target_os = \"redox\")".dependencies.redox_syscall]
version = "0.2.8"
+
[target."cfg(unix)".dependencies.libc]
version = "0.2.95"
+
[target."cfg(windows)".dependencies.winapi]
version = "0.3.9"
-features = ["winnt", "ntstatus", "minwindef", "winerror", "winbase", "errhandlingapi", "handleapi"]
+features = [
+ "winnt",
+ "ntstatus",
+ "minwindef",
+ "winerror",
+ "winbase",
+ "errhandlingapi",
+ "handleapi",
+]
diff --git a/vendor/parking_lot_core-0.8.6/LICENSE-APACHE b/vendor/parking_lot_core-0.8.6/LICENSE-APACHE
new file mode 100644
index 000000000..16fe87b06
--- /dev/null
+++ b/vendor/parking_lot_core-0.8.6/LICENSE-APACHE
@@ -0,0 +1,201 @@
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+END OF TERMS AND CONDITIONS
+
+APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+Copyright [yyyy] [name of copyright owner]
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
diff --git a/vendor/parking_lot_core-0.8.5/LICENSE-MIT b/vendor/parking_lot_core-0.8.6/LICENSE-MIT
index 40b8817a4..40b8817a4 100644
--- a/vendor/parking_lot_core-0.8.5/LICENSE-MIT
+++ b/vendor/parking_lot_core-0.8.6/LICENSE-MIT
diff --git a/vendor/parking_lot_core-0.8.5/build.rs b/vendor/parking_lot_core-0.8.6/build.rs
index d29c769a8..d29c769a8 100644
--- a/vendor/parking_lot_core-0.8.5/build.rs
+++ b/vendor/parking_lot_core-0.8.6/build.rs
diff --git a/vendor/parking_lot_core-0.8.5/src/lib.rs b/vendor/parking_lot_core-0.8.6/src/lib.rs
index 27087f476..27087f476 100644
--- a/vendor/parking_lot_core-0.8.5/src/lib.rs
+++ b/vendor/parking_lot_core-0.8.6/src/lib.rs
diff --git a/vendor/parking_lot_core-0.8.5/src/parking_lot.rs b/vendor/parking_lot_core-0.8.6/src/parking_lot.rs
index 519ce9e34..519ce9e34 100644
--- a/vendor/parking_lot_core-0.8.5/src/parking_lot.rs
+++ b/vendor/parking_lot_core-0.8.6/src/parking_lot.rs
diff --git a/vendor/parking_lot_core-0.8.5/src/spinwait.rs b/vendor/parking_lot_core-0.8.6/src/spinwait.rs
index ad0327a3a..ad0327a3a 100644
--- a/vendor/parking_lot_core-0.8.5/src/spinwait.rs
+++ b/vendor/parking_lot_core-0.8.6/src/spinwait.rs
diff --git a/vendor/parking_lot_core-0.8.5/src/thread_parker/generic.rs b/vendor/parking_lot_core-0.8.6/src/thread_parker/generic.rs
index 5236e14ab..5236e14ab 100644
--- a/vendor/parking_lot_core-0.8.5/src/thread_parker/generic.rs
+++ b/vendor/parking_lot_core-0.8.6/src/thread_parker/generic.rs
diff --git a/vendor/parking_lot_core-0.8.5/src/thread_parker/linux.rs b/vendor/parking_lot_core-0.8.6/src/thread_parker/linux.rs
index 766e63b38..b22d0149f 100644
--- a/vendor/parking_lot_core-0.8.5/src/thread_parker/linux.rs
+++ b/vendor/parking_lot_core-0.8.6/src/thread_parker/linux.rs
@@ -80,10 +80,10 @@ impl super::ThreadParkerT for ThreadParker {
self.park();
return true;
}
- let ts = libc::timespec {
- tv_sec: diff.as_secs() as libc::time_t,
- tv_nsec: diff.subsec_nanos() as tv_nsec_t,
- };
+ // SAFETY: libc::timespec is zero initializable.
+ let mut ts: libc::timespec = std::mem::zeroed();
+ ts.tv_sec = diff.as_secs() as libc::time_t;
+ ts.tv_nsec = diff.subsec_nanos() as tv_nsec_t;
self.futex_wait(Some(ts));
}
true
diff --git a/vendor/parking_lot_core-0.8.5/src/thread_parker/mod.rs b/vendor/parking_lot_core-0.8.6/src/thread_parker/mod.rs
index a7e4bb69c..a7e4bb69c 100644
--- a/vendor/parking_lot_core-0.8.5/src/thread_parker/mod.rs
+++ b/vendor/parking_lot_core-0.8.6/src/thread_parker/mod.rs
diff --git a/vendor/parking_lot_core-0.8.5/src/thread_parker/redox.rs b/vendor/parking_lot_core-0.8.6/src/thread_parker/redox.rs
index cac06bcfe..cac06bcfe 100644
--- a/vendor/parking_lot_core-0.8.5/src/thread_parker/redox.rs
+++ b/vendor/parking_lot_core-0.8.6/src/thread_parker/redox.rs
diff --git a/vendor/parking_lot_core-0.8.5/src/thread_parker/sgx.rs b/vendor/parking_lot_core-0.8.6/src/thread_parker/sgx.rs
index 341efe2ba..341efe2ba 100644
--- a/vendor/parking_lot_core-0.8.5/src/thread_parker/sgx.rs
+++ b/vendor/parking_lot_core-0.8.6/src/thread_parker/sgx.rs
diff --git a/vendor/parking_lot_core-0.8.5/src/thread_parker/unix.rs b/vendor/parking_lot_core-0.8.6/src/thread_parker/unix.rs
index c2381e6df..c2381e6df 100644
--- a/vendor/parking_lot_core-0.8.5/src/thread_parker/unix.rs
+++ b/vendor/parking_lot_core-0.8.6/src/thread_parker/unix.rs
diff --git a/vendor/parking_lot_core-0.8.5/src/thread_parker/wasm.rs b/vendor/parking_lot_core-0.8.6/src/thread_parker/wasm.rs
index ba4118c01..ba4118c01 100644
--- a/vendor/parking_lot_core-0.8.5/src/thread_parker/wasm.rs
+++ b/vendor/parking_lot_core-0.8.6/src/thread_parker/wasm.rs
diff --git a/vendor/parking_lot_core-0.8.5/src/thread_parker/wasm_atomic.rs b/vendor/parking_lot_core-0.8.6/src/thread_parker/wasm_atomic.rs
index 2128e93cb..2128e93cb 100644
--- a/vendor/parking_lot_core-0.8.5/src/thread_parker/wasm_atomic.rs
+++ b/vendor/parking_lot_core-0.8.6/src/thread_parker/wasm_atomic.rs
diff --git a/vendor/parking_lot_core-0.8.5/src/thread_parker/windows/keyed_event.rs b/vendor/parking_lot_core-0.8.6/src/thread_parker/windows/keyed_event.rs
index 7c371537c..7c371537c 100644
--- a/vendor/parking_lot_core-0.8.5/src/thread_parker/windows/keyed_event.rs
+++ b/vendor/parking_lot_core-0.8.6/src/thread_parker/windows/keyed_event.rs
diff --git a/vendor/parking_lot_core-0.8.5/src/thread_parker/windows/mod.rs b/vendor/parking_lot_core-0.8.6/src/thread_parker/windows/mod.rs
index 76dbb5d49..76dbb5d49 100644
--- a/vendor/parking_lot_core-0.8.5/src/thread_parker/windows/mod.rs
+++ b/vendor/parking_lot_core-0.8.6/src/thread_parker/windows/mod.rs
diff --git a/vendor/parking_lot_core-0.8.5/src/thread_parker/windows/waitaddress.rs b/vendor/parking_lot_core-0.8.6/src/thread_parker/windows/waitaddress.rs
index 862c5c652..862c5c652 100644
--- a/vendor/parking_lot_core-0.8.5/src/thread_parker/windows/waitaddress.rs
+++ b/vendor/parking_lot_core-0.8.6/src/thread_parker/windows/waitaddress.rs
diff --git a/vendor/parking_lot_core-0.8.5/src/util.rs b/vendor/parking_lot_core-0.8.6/src/util.rs
index d7aaa8715..d7aaa8715 100644
--- a/vendor/parking_lot_core-0.8.5/src/util.rs
+++ b/vendor/parking_lot_core-0.8.6/src/util.rs
diff --git a/vendor/parking_lot_core-0.8.5/src/word_lock.rs b/vendor/parking_lot_core-0.8.6/src/word_lock.rs
index 1109401ae..1109401ae 100644
--- a/vendor/parking_lot_core-0.8.5/src/word_lock.rs
+++ b/vendor/parking_lot_core-0.8.6/src/word_lock.rs
diff --git a/vendor/parking_lot_core/.cargo-checksum.json b/vendor/parking_lot_core/.cargo-checksum.json
index 196164748..f1b0944e2 100644
--- a/vendor/parking_lot_core/.cargo-checksum.json
+++ b/vendor/parking_lot_core/.cargo-checksum.json
@@ -1 +1 @@
-{"files":{"Cargo.toml":"894a414fd99c9650a87b880fbc3b14e35e7bb33eb9c318404ec260a7a9b34fb9","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"c9a75f18b9ab2927829a208fc6aa2cf4e63b8420887ba29cdb265d6619ae82d5","build.rs":"29e629057144d1238dcd8ea70ad6cbb6ec14ca742797af3fa9335710ff5cbaaa","src/lib.rs":"def53c1ff1d4a05e6261aa9b75ac089a51ecc15642e1320202e5c6836e2bb732","src/parking_lot.rs":"b08d6c00de6fc342a1b4f0268b056789ad1300aa8a9c4fb7ad4d49514cfab72c","src/spinwait.rs":"0d73980c72e84fd75c73693f0b351e097353b46f4b8aaa67b3dde7c721817bf7","src/thread_parker/generic.rs":"414bd3114b40f7665efe59fa4c5033d2401eafc58b57a9ba5803949d26cc0454","src/thread_parker/linux.rs":"6837304ca62e1774b0d811f9a61f4a7a70b8914a905b69aa4808220fb9063879","src/thread_parker/mod.rs":"afaf652e242d5235d38f5749f3b12dc6def793dee40cd6c820e1dd45a70a5ac8","src/thread_parker/redox.rs":"38fbede41817b6606a5612ee9456940eaf627540a4aa39de8452e355ca1df306","src/thread_parker/sgx.rs":"3b6190eb90fd88d5eee5370213a1de408cce24ded04bfb0f374c3bbf10752187","src/thread_parker/unix.rs":"4a314ea3b0b2a22cd3857bedcd1d15d843365acbc085f0cdc9ae085d600760da","src/thread_parker/wasm.rs":"86e954d009d57d2dfdbca71e5c0f116a99a182af83b7e51ed5b14fc55b2f7b01","src/thread_parker/wasm_atomic.rs":"6fbc09accc9df9d42444cec6f55d3eed2c7078a474485fa269a9f503da2ee1c5","src/thread_parker/windows/keyed_event.rs":"758b475e6931d5cb8715786e8ef3b4e6b0d017fb163ea5d8cc8b6b728454238b","src/thread_parker/windows/mod.rs":"3073e82ecc46d713b2c4296459ead9f3788d29e7b5c9be4b68d29d98b5a803ce","src/thread_parker/windows/waitaddress.rs":"8eee4b444a00e7ad83bdc50eb4b4af36610dfa4690329e8947962fef04cb1000","src/util.rs":"285e6133150645525f2ca1ece41f6d35bad4e7c5e08b42b20c99d2a97e04a974","src/word_lock.rs":"9ba49082359c35ad5b4e8d219fede1ffca75225f9ccb971cbba01f20e2ed2738"},"package":"4dc9e0dc2adc1c69d09143aff38d3d30c5c3f0df0dad82e6d25547af174ebec0"} \ No newline at end of file
+{"files":{"Cargo.toml":"fdae8721cb66a7a3544ae5e2de3784c44c6f00a898c436132524693aba7aa22e","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"c9a75f18b9ab2927829a208fc6aa2cf4e63b8420887ba29cdb265d6619ae82d5","build.rs":"29e629057144d1238dcd8ea70ad6cbb6ec14ca742797af3fa9335710ff5cbaaa","src/lib.rs":"def53c1ff1d4a05e6261aa9b75ac089a51ecc15642e1320202e5c6836e2bb732","src/parking_lot.rs":"b08d6c00de6fc342a1b4f0268b056789ad1300aa8a9c4fb7ad4d49514cfab72c","src/spinwait.rs":"0d73980c72e84fd75c73693f0b351e097353b46f4b8aaa67b3dde7c721817bf7","src/thread_parker/generic.rs":"414bd3114b40f7665efe59fa4c5033d2401eafc58b57a9ba5803949d26cc0454","src/thread_parker/linux.rs":"70bfe6c168fc431965374d921e33b3e04536cb68fde3e807a837aa38a65772b0","src/thread_parker/mod.rs":"afaf652e242d5235d38f5749f3b12dc6def793dee40cd6c820e1dd45a70a5ac8","src/thread_parker/redox.rs":"38fbede41817b6606a5612ee9456940eaf627540a4aa39de8452e355ca1df306","src/thread_parker/sgx.rs":"3b6190eb90fd88d5eee5370213a1de408cce24ded04bfb0f374c3bbf10752187","src/thread_parker/unix.rs":"f1425cf5876d1f9be98979343fb3bcb2a25982bcff80e7399c86ce835d450143","src/thread_parker/wasm.rs":"86e954d009d57d2dfdbca71e5c0f116a99a182af83b7e51ed5b14fc55b2f7b01","src/thread_parker/wasm_atomic.rs":"6fbc09accc9df9d42444cec6f55d3eed2c7078a474485fa269a9f503da2ee1c5","src/thread_parker/windows/keyed_event.rs":"758b475e6931d5cb8715786e8ef3b4e6b0d017fb163ea5d8cc8b6b728454238b","src/thread_parker/windows/mod.rs":"3073e82ecc46d713b2c4296459ead9f3788d29e7b5c9be4b68d29d98b5a803ce","src/thread_parker/windows/waitaddress.rs":"8eee4b444a00e7ad83bdc50eb4b4af36610dfa4690329e8947962fef04cb1000","src/util.rs":"285e6133150645525f2ca1ece41f6d35bad4e7c5e08b42b20c99d2a97e04a974","src/word_lock.rs":"9ba49082359c35ad5b4e8d219fede1ffca75225f9ccb971cbba01f20e2ed2738"},"package":"ba1ef8814b5c993410bb3adfad7a5ed269563e4a2f90c41f5d85be7fb47133bf"} \ No newline at end of file
diff --git a/vendor/parking_lot_core/Cargo.toml b/vendor/parking_lot_core/Cargo.toml
index f4daf6f02..47529ad8d 100644
--- a/vendor/parking_lot_core/Cargo.toml
+++ b/vendor/parking_lot_core/Cargo.toml
@@ -12,7 +12,7 @@
[package]
edition = "2018"
name = "parking_lot_core"
-version = "0.9.4"
+version = "0.9.6"
authors = ["Amanieu d'Antras <amanieu@gmail.com>"]
description = "An advanced API for creating custom synchronization primitives."
keywords = [
diff --git a/vendor/parking_lot_core/src/thread_parker/linux.rs b/vendor/parking_lot_core/src/thread_parker/linux.rs
index 5d4e229ad..92601f62a 100644
--- a/vendor/parking_lot_core/src/thread_parker/linux.rs
+++ b/vendor/parking_lot_core/src/thread_parker/linux.rs
@@ -80,10 +80,10 @@ impl super::ThreadParkerT for ThreadParker {
self.park();
return true;
}
- let ts = libc::timespec {
- tv_sec: diff.as_secs() as libc::time_t,
- tv_nsec: diff.subsec_nanos() as tv_nsec_t,
- };
+ // SAFETY: libc::timespec is zero initializable.
+ let mut ts: libc::timespec = std::mem::zeroed();
+ ts.tv_sec = diff.as_secs() as libc::time_t;
+ ts.tv_nsec = diff.subsec_nanos() as tv_nsec_t;
self.futex_wait(Some(ts));
}
true
diff --git a/vendor/parking_lot_core/src/thread_parker/unix.rs b/vendor/parking_lot_core/src/thread_parker/unix.rs
index 88b6df839..7f2860372 100644
--- a/vendor/parking_lot_core/src/thread_parker/unix.rs
+++ b/vendor/parking_lot_core/src/thread_parker/unix.rs
@@ -5,7 +5,7 @@
// http://opensource.org/licenses/MIT>, at your option. This file may not be
// copied, modified, or distributed except according to those terms.
-#[cfg(any(target_os = "macos", target_os = "ios"))]
+#[cfg(any(target_os = "macos", target_os = "ios", target_os = "watchos"))]
use core::ptr;
use core::{
cell::{Cell, UnsafeCell},
@@ -130,6 +130,7 @@ impl ThreadParker {
#[cfg(any(
target_os = "macos",
target_os = "ios",
+ target_os = "watchos",
target_os = "android",
target_os = "espidf"
))]
@@ -140,6 +141,7 @@ impl ThreadParker {
#[cfg(not(any(
target_os = "macos",
target_os = "ios",
+ target_os = "watchos",
target_os = "android",
target_os = "espidf"
)))]
@@ -193,7 +195,7 @@ impl super::UnparkHandleT for UnparkHandle {
}
// Returns the current time on the clock used by pthread_cond_t as a timespec.
-#[cfg(any(target_os = "macos", target_os = "ios"))]
+#[cfg(any(target_os = "macos", target_os = "ios", target_os = "watchos"))]
#[inline]
fn timespec_now() -> libc::timespec {
let mut now = MaybeUninit::<libc::timeval>::uninit();
@@ -206,7 +208,7 @@ fn timespec_now() -> libc::timespec {
tv_nsec: now.tv_usec as tv_nsec_t * 1000,
}
}
-#[cfg(not(any(target_os = "macos", target_os = "ios")))]
+#[cfg(not(any(target_os = "macos", target_os = "ios", target_os = "watchos")))]
#[inline]
fn timespec_now() -> libc::timespec {
let mut now = MaybeUninit::<libc::timespec>::uninit();
diff --git a/vendor/proc-macro2/.cargo-checksum.json b/vendor/proc-macro2/.cargo-checksum.json
index b20fcaba3..de2b0c753 100644
--- a/vendor/proc-macro2/.cargo-checksum.json
+++ b/vendor/proc-macro2/.cargo-checksum.json
@@ -1 +1 @@
-{"files":{"Cargo.toml":"070b0704e5cdbac330b9cecee44e488a40b6daf6161215e4457bdfc3e7e9bf94","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"378f5840b258e2779c39418f3f2d7b2ba96f1c7917dd6be0713f88305dbda397","README.md":"0c17148c1957c3f721d99fc99aedaefee5f2f1ba7e2336a289b02f91609099fb","build.rs":"275f7a9ee0b9eff972124951de544ae17ee3e698a4e89b0f0393b334344f5e30","src/detection.rs":"ed9a5f9a979ab01247d7a68eeb1afa3c13209334c5bfff0f9289cb07e5bb4e8b","src/fallback.rs":"a9e6fa159d6a111a231fa9367d54859103e9d49f6662397baea951b5f3e7e983","src/lib.rs":"81865a868ef697987cafef5eb9512d3109da373456eead2a36c22d44e769c947","src/marker.rs":"344a8394f06a1d43355b514920e7e3c0c6dce507be767e3a590bbe3552edd110","src/parse.rs":"637a9fe6e3e21c36fa411b70674f617743fe0129787c17a559e78f86418d0da4","src/rcvec.rs":"49b6784c6ca5f32573cd8a83758b485d8acbfa126e5fb516ae439e429ef4c144","src/wrapper.rs":"8ea825cdac628570719a258419fcffd1c9d2ca1ca5e2fbbbf283dd9cc6695910","tests/comments.rs":"31115b3a56c83d93eef2fb4c9566bf4543e302560732986161b98aef504785ed","tests/features.rs":"a86deb8644992a4eb64d9fd493eff16f9cf9c5cb6ade3a634ce0c990cf87d559","tests/marker.rs":"cb6d776eba6a238d726b0f531883adf41957e06f2717ee8a069821c81e7081d6","tests/test.rs":"d7f21088314d1df25447fdc0a32feffae26d4d637e3ce68e23c0190060cb5652","tests/test_fmt.rs":"9357769945784354909259084ec8b34d2aa52081dd3967cac6dae3a5e3df3bc0"},"package":"5ea3d908b0e36316caf9e9e2c4625cdde190a7e6f440d794667ed17a1855e725"} \ No newline at end of file
+{"files":{"Cargo.toml":"a4f134ba553220d2d6a3ae778423be3e0223ad8b301a64c0e00ec97c65388de2","LICENSE-APACHE":"62c7a1e35f56406896d7aa7ca52d0cc0d272ac022b5d2796e7d6905db8a3636a","LICENSE-MIT":"23f18e03dc49df91622fe2a76176497404e46ced8a715d9d2b67a7446571cca3","README.md":"32cbd395594db59ecc43d7866cfa2663f3687bb7df631781d60ae83200dae8a8","build.rs":"275f7a9ee0b9eff972124951de544ae17ee3e698a4e89b0f0393b334344f5e30","src/detection.rs":"ed9a5f9a979ab01247d7a68eeb1afa3c13209334c5bfff0f9289cb07e5bb4e8b","src/fallback.rs":"7b581d52bea33e78542c230afb6ae5212b322f6a584244a63ddc28ed32939a12","src/lib.rs":"4a7358479655f388f11f2255783b97ee4caa9d63a59be6f60e50760a7d836b2c","src/location.rs":"f55d2e61f1bb1af65e14ed04c9e91eb1ddbf8430e8c05f2048d1cd538d27368e","src/marker.rs":"344a8394f06a1d43355b514920e7e3c0c6dce507be767e3a590bbe3552edd110","src/parse.rs":"637a9fe6e3e21c36fa411b70674f617743fe0129787c17a559e78f86418d0da4","src/rcvec.rs":"49b6784c6ca5f32573cd8a83758b485d8acbfa126e5fb516ae439e429ef4c144","src/wrapper.rs":"75fd4c805da3d384fb957f6ac76ec33398d45b121e49a3a5e5403301062c6619","tests/comments.rs":"31115b3a56c83d93eef2fb4c9566bf4543e302560732986161b98aef504785ed","tests/features.rs":"a86deb8644992a4eb64d9fd493eff16f9cf9c5cb6ade3a634ce0c990cf87d559","tests/marker.rs":"cb6d776eba6a238d726b0f531883adf41957e06f2717ee8a069821c81e7081d6","tests/test.rs":"d7f21088314d1df25447fdc0a32feffae26d4d637e3ce68e23c0190060cb5652","tests/test_fmt.rs":"9357769945784354909259084ec8b34d2aa52081dd3967cac6dae3a5e3df3bc0"},"package":"6ef7d57beacfaf2d8aee5937dab7b7f28de3cb8b1828479bb5de2a7106f2bae2"} \ No newline at end of file
diff --git a/vendor/proc-macro2/Cargo.toml b/vendor/proc-macro2/Cargo.toml
index 1bda7e36d..7fef345e4 100644
--- a/vendor/proc-macro2/Cargo.toml
+++ b/vendor/proc-macro2/Cargo.toml
@@ -13,7 +13,7 @@
edition = "2018"
rust-version = "1.31"
name = "proc-macro2"
-version = "1.0.47"
+version = "1.0.50"
authors = [
"David Tolnay <dtolnay@gmail.com>",
"Alex Crichton <alex@alexcrichton.com>",
@@ -46,6 +46,9 @@ targets = ["x86_64-unknown-linux-gnu"]
[package.metadata.playground]
features = ["span-locations"]
+[lib]
+doc-scrape-examples = false
+
[dependencies.unicode-ident]
version = "1.0"
diff --git a/vendor/proc-macro2/LICENSE-APACHE b/vendor/proc-macro2/LICENSE-APACHE
index 16fe87b06..1b5ec8b78 100644
--- a/vendor/proc-macro2/LICENSE-APACHE
+++ b/vendor/proc-macro2/LICENSE-APACHE
@@ -174,28 +174,3 @@ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
-
-APPENDIX: How to apply the Apache License to your work.
-
- To apply the Apache License to your work, attach the following
- boilerplate notice, with the fields enclosed by brackets "[]"
- replaced with your own identifying information. (Don't include
- the brackets!) The text should be enclosed in the appropriate
- comment syntax for the file format. We also recommend that a
- file or class name and description of purpose be included on the
- same "printed page" as the copyright notice for easier
- identification within third-party archives.
-
-Copyright [yyyy] [name of copyright owner]
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
diff --git a/vendor/proc-macro2/LICENSE-MIT b/vendor/proc-macro2/LICENSE-MIT
index 39e0ed660..31aa79387 100644
--- a/vendor/proc-macro2/LICENSE-MIT
+++ b/vendor/proc-macro2/LICENSE-MIT
@@ -1,5 +1,3 @@
-Copyright (c) 2014 Alex Crichton
-
Permission is hereby granted, free of charge, to any
person obtaining a copy of this software and associated
documentation files (the "Software"), to deal in the
diff --git a/vendor/proc-macro2/README.md b/vendor/proc-macro2/README.md
index 70b6c869e..131ba5130 100644
--- a/vendor/proc-macro2/README.md
+++ b/vendor/proc-macro2/README.md
@@ -3,7 +3,7 @@
[<img alt="github" src="https://img.shields.io/badge/github-dtolnay/proc--macro2-8da0cb?style=for-the-badge&labelColor=555555&logo=github" height="20">](https://github.com/dtolnay/proc-macro2)
[<img alt="crates.io" src="https://img.shields.io/crates/v/proc-macro2.svg?style=for-the-badge&color=fc8d62&logo=rust" height="20">](https://crates.io/crates/proc-macro2)
[<img alt="docs.rs" src="https://img.shields.io/badge/docs.rs-proc--macro2-66c2a5?style=for-the-badge&labelColor=555555&logo=docs.rs" height="20">](https://docs.rs/proc-macro2)
-[<img alt="build status" src="https://img.shields.io/github/workflow/status/dtolnay/proc-macro2/CI/master?style=for-the-badge" height="20">](https://github.com/dtolnay/proc-macro2/actions?query=branch%3Amaster)
+[<img alt="build status" src="https://img.shields.io/github/actions/workflow/status/dtolnay/proc-macro2/ci.yml?branch=master&style=for-the-badge" height="20">](https://github.com/dtolnay/proc-macro2/actions?query=branch%3Amaster)
A wrapper around the procedural macro API of the compiler's `proc_macro` crate.
This library serves two purposes:
diff --git a/vendor/proc-macro2/src/fallback.rs b/vendor/proc-macro2/src/fallback.rs
index fe4f248d3..5a4c350d5 100644
--- a/vendor/proc-macro2/src/fallback.rs
+++ b/vendor/proc-macro2/src/fallback.rs
@@ -1,3 +1,5 @@
+#[cfg(span_locations)]
+use crate::location::LineColumn;
use crate::parse::{self, Cursor};
use crate::rcvec::{RcVec, RcVecBuilder, RcVecIntoIter, RcVecMut};
use crate::{Delimiter, Spacing, TokenTree};
@@ -332,12 +334,6 @@ impl Debug for SourceFile {
}
}
-#[derive(Clone, Copy, Debug, PartialEq, Eq)]
-pub(crate) struct LineColumn {
- pub line: usize,
- pub column: usize,
-}
-
#[cfg(span_locations)]
thread_local! {
static SOURCE_MAP: RefCell<SourceMap> = RefCell::new(SourceMap {
diff --git a/vendor/proc-macro2/src/lib.rs b/vendor/proc-macro2/src/lib.rs
index 3fda02d5c..633333ba8 100644
--- a/vendor/proc-macro2/src/lib.rs
+++ b/vendor/proc-macro2/src/lib.rs
@@ -86,7 +86,7 @@
//! a different thread.
// Proc-macro2 types in rustdoc of other crates get linked to here.
-#![doc(html_root_url = "https://docs.rs/proc-macro2/1.0.47")]
+#![doc(html_root_url = "https://docs.rs/proc-macro2/1.0.50")]
#![cfg_attr(
any(proc_macro_span, super_unstable),
feature(proc_macro_span, proc_macro_span_shrink)
@@ -139,6 +139,9 @@ use crate::fallback as imp;
#[cfg(wrap_proc_macro)]
mod imp;
+#[cfg(span_locations)]
+mod location;
+
use crate::marker::Marker;
use core::cmp::Ordering;
use core::fmt::{self, Debug, Display};
@@ -150,6 +153,9 @@ use std::error::Error;
#[cfg(procmacro2_semver_exempt)]
use std::path::PathBuf;
+#[cfg(span_locations)]
+pub use crate::location::LineColumn;
+
/// An abstract stream of tokens, or more concretely a sequence of token trees.
///
/// This type provides interfaces for iterating over token trees and for
@@ -356,37 +362,6 @@ impl Debug for SourceFile {
}
}
-/// A line-column pair representing the start or end of a `Span`.
-///
-/// This type is semver exempt and not exposed by default.
-#[cfg(span_locations)]
-#[cfg_attr(doc_cfg, doc(cfg(feature = "span-locations")))]
-#[derive(Copy, Clone, Debug, PartialEq, Eq)]
-pub struct LineColumn {
- /// The 1-indexed line in the source file on which the span starts or ends
- /// (inclusive).
- pub line: usize,
- /// The 0-indexed column (in UTF-8 characters) in the source file on which
- /// the span starts or ends (inclusive).
- pub column: usize,
-}
-
-#[cfg(span_locations)]
-impl Ord for LineColumn {
- fn cmp(&self, other: &Self) -> Ordering {
- self.line
- .cmp(&other.line)
- .then(self.column.cmp(&other.column))
- }
-}
-
-#[cfg(span_locations)]
-impl PartialOrd for LineColumn {
- fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
- Some(self.cmp(other))
- }
-}
-
/// A region of source code, along with macro expansion information.
#[derive(Copy, Clone)]
pub struct Span {
@@ -492,8 +467,7 @@ impl Span {
#[cfg(span_locations)]
#[cfg_attr(doc_cfg, doc(cfg(feature = "span-locations")))]
pub fn start(&self) -> LineColumn {
- let imp::LineColumn { line, column } = self.inner.start();
- LineColumn { line, column }
+ self.inner.start()
}
/// Get the ending line/column in the source file for this span.
@@ -508,8 +482,7 @@ impl Span {
#[cfg(span_locations)]
#[cfg_attr(doc_cfg, doc(cfg(feature = "span-locations")))]
pub fn end(&self) -> LineColumn {
- let imp::LineColumn { line, column } = self.inner.end();
- LineColumn { line, column }
+ self.inner.end()
}
/// Creates an empty span pointing to directly before this span.
diff --git a/vendor/proc-macro2/src/location.rs b/vendor/proc-macro2/src/location.rs
new file mode 100644
index 000000000..463026c27
--- /dev/null
+++ b/vendor/proc-macro2/src/location.rs
@@ -0,0 +1,29 @@
+use core::cmp::Ordering;
+
+/// A line-column pair representing the start or end of a `Span`.
+///
+/// This type is semver exempt and not exposed by default.
+#[cfg_attr(doc_cfg, doc(cfg(feature = "span-locations")))]
+#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
+pub struct LineColumn {
+ /// The 1-indexed line in the source file on which the span starts or ends
+ /// (inclusive).
+ pub line: usize,
+ /// The 0-indexed column (in UTF-8 characters) in the source file on which
+ /// the span starts or ends (inclusive).
+ pub column: usize,
+}
+
+impl Ord for LineColumn {
+ fn cmp(&self, other: &Self) -> Ordering {
+ self.line
+ .cmp(&other.line)
+ .then(self.column.cmp(&other.column))
+ }
+}
+
+impl PartialOrd for LineColumn {
+ fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
+ Some(self.cmp(other))
+ }
+}
diff --git a/vendor/proc-macro2/src/wrapper.rs b/vendor/proc-macro2/src/wrapper.rs
index 47d149473..bc800d56d 100644
--- a/vendor/proc-macro2/src/wrapper.rs
+++ b/vendor/proc-macro2/src/wrapper.rs
@@ -1,4 +1,6 @@
use crate::detection::inside_proc_macro;
+#[cfg(span_locations)]
+use crate::location::LineColumn;
use crate::{fallback, Delimiter, Punct, Spacing, TokenTree};
use core::fmt::{self, Debug, Display};
use core::iter::FromIterator;
@@ -389,12 +391,6 @@ impl Debug for SourceFile {
}
}
-#[cfg(any(super_unstable, feature = "span-locations"))]
-pub(crate) struct LineColumn {
- pub line: usize,
- pub column: usize,
-}
-
#[derive(Copy, Clone)]
pub(crate) enum Span {
Compiler(proc_macro::Span),
@@ -471,7 +467,7 @@ impl Span {
}
}
- #[cfg(any(super_unstable, feature = "span-locations"))]
+ #[cfg(span_locations)]
pub fn start(&self) -> LineColumn {
match self {
#[cfg(proc_macro_span)]
@@ -481,14 +477,11 @@ impl Span {
}
#[cfg(not(proc_macro_span))]
Span::Compiler(_) => LineColumn { line: 0, column: 0 },
- Span::Fallback(s) => {
- let fallback::LineColumn { line, column } = s.start();
- LineColumn { line, column }
- }
+ Span::Fallback(s) => s.start(),
}
}
- #[cfg(any(super_unstable, feature = "span-locations"))]
+ #[cfg(span_locations)]
pub fn end(&self) -> LineColumn {
match self {
#[cfg(proc_macro_span)]
@@ -498,10 +491,7 @@ impl Span {
}
#[cfg(not(proc_macro_span))]
Span::Compiler(_) => LineColumn { line: 0, column: 0 },
- Span::Fallback(s) => {
- let fallback::LineColumn { line, column } = s.end();
- LineColumn { line, column }
- }
+ Span::Fallback(s) => s.end(),
}
}
diff --git a/vendor/quote/.cargo-checksum.json b/vendor/quote/.cargo-checksum.json
index dd217b081..990f0d7ad 100644
--- a/vendor/quote/.cargo-checksum.json
+++ b/vendor/quote/.cargo-checksum.json
@@ -1 +1 @@
-{"files":{"Cargo.toml":"f4cf791ed3ccb9a3d5840f63af9c8d6b60453d9cd2451bf71c98f413e639b5ac","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"c9a75f18b9ab2927829a208fc6aa2cf4e63b8420887ba29cdb265d6619ae82d5","README.md":"1aed9e312142718f8e1a37a0a982d8e45398dee835776b0ffa54639efdd75dfb","build.rs":"3733c86ae2733629f873f93c2f45da30164beee8de9ee0833099fac6a05a3e6b","rust-toolchain.toml":"6bbb61302978c736b2da03e4fb40e3beab908f85d533ab46fd541e637b5f3e0f","src/ext.rs":"9881576cac3e476a4bf04f9b601cf9a53b79399fb0ca9634e8b861ac91709843","src/format.rs":"c595015418f35e6992e710441b9999f09b2afe4678b138039d670d100c0bdd86","src/ident_fragment.rs":"66788c5f57681547d936a9bcf51873b658630c76b2e690df4b3158edf573384a","src/lib.rs":"17db85f0808d31a597ea7f56744b031b5bdba548d9474efd874cacfe6541ff60","src/runtime.rs":"79bbb2fe5b18bc3ec9f8f8143bd120b45680a3027c89f37b0a6a6b97bdaadb21","src/spanned.rs":"43ff919f1d2d27dff6b2db409539b1c697e913eb8c3131cf5de45a845752b7b5","src/to_tokens.rs":"99bb6f467289c32af6c1f7af0d45cc6ac7b31e2436774e616770152a49e6ac0f","tests/compiletest.rs":"022a8e400ef813d7ea1875b944549cee5125f6a995dc33e93b48cba3e1b57bd1","tests/test.rs":"29221bc5eb9497a2fcda1b44e9535c645f7c7ca84ffc32e6040e57d94dbda2c8","tests/ui/does-not-have-iter-interpolated-dup.rs":"ad13eea21d4cdd2ab6c082f633392e1ff20fb0d1af5f2177041e0bf7f30da695","tests/ui/does-not-have-iter-interpolated-dup.stderr":"be67a6c99eed689aa08b46afd0ab3ed4e71fde42e5efed41ab05741710f42fe5","tests/ui/does-not-have-iter-interpolated.rs":"83a5b3f240651adcbe4b6e51076d76d653ad439b37442cf4054f1fd3c073f3b7","tests/ui/does-not-have-iter-interpolated.stderr":"ed05bc229abf5a267ea3d194336a3a845a061bd10c1be7020b9351f81e737946","tests/ui/does-not-have-iter-separated.rs":"fe413c48331d5e3a7ae5fef6a5892a90c72f610d54595879eb49d0a94154ba3f","tests/ui/does-not-have-iter-separated.stderr":"873f4db0ec63606d64d46790f3ee24bdb4dd04379b8e57dc5ac1114cc3775fb3","tests/ui/does-not-have-iter.rs":"09dc9499d861b63cebb0848b855b78e2dc9497bfde37ba6339f3625ae009a62f","tests/ui/does-not-have-iter.stderr":"0e3de2635a79cce9226113fa8cb6bdbdc0ffcd487d7537d4dd0dc8222adf4a8a","tests/ui/not-quotable.rs":"5759d0884943417609f28faadc70254a3e2fd3d9bd6ff7297a3fb70a77fafd8a","tests/ui/not-quotable.stderr":"d55354e6a963b5eedce9bc68a1b04bf5b82f966c3c1bb987d1690e74c0c3d69c","tests/ui/not-repeatable.rs":"a4b115c04e4e41049a05f5b69450503fbffeba031218b4189cb931839f7f9a9c","tests/ui/not-repeatable.stderr":"27149da38cc074953f124e995d76e569e0f718a5431c321cb5d639b0065520b3","tests/ui/wrong-type-span.rs":"6195e35ea844c0c52ba1cff5d790c3a371af6915d137d377834ad984229ef9ea","tests/ui/wrong-type-span.stderr":"c986de5cb858272636c9e36ae5f57e5ee13589d4f1a73a050b21824010314f8d"},"package":"bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179"} \ No newline at end of file
+{"files":{"Cargo.toml":"b31678b5e9696b0320493f7120e873490183308fc5afb052dc23a265048b8e16","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"23f18e03dc49df91622fe2a76176497404e46ced8a715d9d2b67a7446571cca3","README.md":"66f3cf08338e47618fd23d810355b075da573815d9c1e158a7f7ab140decc16d","build.rs":"3733c86ae2733629f873f93c2f45da30164beee8de9ee0833099fac6a05a3e6b","rust-toolchain.toml":"6bbb61302978c736b2da03e4fb40e3beab908f85d533ab46fd541e637b5f3e0f","src/ext.rs":"9881576cac3e476a4bf04f9b601cf9a53b79399fb0ca9634e8b861ac91709843","src/format.rs":"c595015418f35e6992e710441b9999f09b2afe4678b138039d670d100c0bdd86","src/ident_fragment.rs":"66788c5f57681547d936a9bcf51873b658630c76b2e690df4b3158edf573384a","src/lib.rs":"5f0dac39c736d01c698745909c93efb7e701aed4493c488a32239a7efd7d4469","src/runtime.rs":"79bbb2fe5b18bc3ec9f8f8143bd120b45680a3027c89f37b0a6a6b97bdaadb21","src/spanned.rs":"43ff919f1d2d27dff6b2db409539b1c697e913eb8c3131cf5de45a845752b7b5","src/to_tokens.rs":"99bb6f467289c32af6c1f7af0d45cc6ac7b31e2436774e616770152a49e6ac0f","tests/compiletest.rs":"022a8e400ef813d7ea1875b944549cee5125f6a995dc33e93b48cba3e1b57bd1","tests/test.rs":"c4967a33fcf7c2effd1979bcb4c03ae797359eeab92c627ab4b609cd8678ff78","tests/ui/does-not-have-iter-interpolated-dup.rs":"ad13eea21d4cdd2ab6c082f633392e1ff20fb0d1af5f2177041e0bf7f30da695","tests/ui/does-not-have-iter-interpolated-dup.stderr":"be67a6c99eed689aa08b46afd0ab3ed4e71fde42e5efed41ab05741710f42fe5","tests/ui/does-not-have-iter-interpolated.rs":"83a5b3f240651adcbe4b6e51076d76d653ad439b37442cf4054f1fd3c073f3b7","tests/ui/does-not-have-iter-interpolated.stderr":"ed05bc229abf5a267ea3d194336a3a845a061bd10c1be7020b9351f81e737946","tests/ui/does-not-have-iter-separated.rs":"fe413c48331d5e3a7ae5fef6a5892a90c72f610d54595879eb49d0a94154ba3f","tests/ui/does-not-have-iter-separated.stderr":"873f4db0ec63606d64d46790f3ee24bdb4dd04379b8e57dc5ac1114cc3775fb3","tests/ui/does-not-have-iter.rs":"09dc9499d861b63cebb0848b855b78e2dc9497bfde37ba6339f3625ae009a62f","tests/ui/does-not-have-iter.stderr":"0e3de2635a79cce9226113fa8cb6bdbdc0ffcd487d7537d4dd0dc8222adf4a8a","tests/ui/not-quotable.rs":"d630ed8e5fe16f125015999d068569cc3fe5dc1033a56e622690ec2c080c13f4","tests/ui/not-quotable.stderr":"4b81ec7bb82ba197ede6d47c1b6e5cacc0999cc8c9e2fa77a46db5e29397153c","tests/ui/not-repeatable.rs":"dbfedcad67b57543aa7d6684b6549db90fbdb74ffebcae42323d31eb88e59c87","tests/ui/not-repeatable.stderr":"a578a6293fef33c54f8e8114bf72a933a1315b45e866e4bcef1e31ce2ce55dcd","tests/ui/wrong-type-span.rs":"6195e35ea844c0c52ba1cff5d790c3a371af6915d137d377834ad984229ef9ea","tests/ui/wrong-type-span.stderr":"c986de5cb858272636c9e36ae5f57e5ee13589d4f1a73a050b21824010314f8d"},"package":"8856d8364d252a14d474036ea1358d63c9e6965c8e5c1885c18f73d70bff9c7b"} \ No newline at end of file
diff --git a/vendor/quote/Cargo.toml b/vendor/quote/Cargo.toml
index b2abe6612..4d6b32670 100644
--- a/vendor/quote/Cargo.toml
+++ b/vendor/quote/Cargo.toml
@@ -13,7 +13,7 @@
edition = "2018"
rust-version = "1.31"
name = "quote"
-version = "1.0.21"
+version = "1.0.23"
authors = ["David Tolnay <dtolnay@gmail.com>"]
autobenches = false
description = "Quasi-quoting macro quote!(...)"
@@ -30,6 +30,9 @@ repository = "https://github.com/dtolnay/quote"
[package.metadata.docs.rs]
targets = ["x86_64-unknown-linux-gnu"]
+[lib]
+doc-scrape-examples = false
+
[dependencies.proc-macro2]
version = "1.0.40"
default-features = false
@@ -38,7 +41,7 @@ default-features = false
version = "1.0"
[dev-dependencies.trybuild]
-version = "1.0.52"
+version = "1.0.66"
features = ["diff"]
[features]
diff --git a/vendor/quote/LICENSE-MIT b/vendor/quote/LICENSE-MIT
index 40b8817a4..31aa79387 100644
--- a/vendor/quote/LICENSE-MIT
+++ b/vendor/quote/LICENSE-MIT
@@ -1,5 +1,3 @@
-Copyright (c) 2016 The Rust Project Developers
-
Permission is hereby granted, free of charge, to any
person obtaining a copy of this software and associated
documentation files (the "Software"), to deal in the
diff --git a/vendor/quote/README.md b/vendor/quote/README.md
index 2c21a50d2..74e99ce42 100644
--- a/vendor/quote/README.md
+++ b/vendor/quote/README.md
@@ -4,7 +4,7 @@ Rust Quasi-Quoting
[<img alt="github" src="https://img.shields.io/badge/github-dtolnay/quote-8da0cb?style=for-the-badge&labelColor=555555&logo=github" height="20">](https://github.com/dtolnay/quote)
[<img alt="crates.io" src="https://img.shields.io/crates/v/quote.svg?style=for-the-badge&color=fc8d62&logo=rust" height="20">](https://crates.io/crates/quote)
[<img alt="docs.rs" src="https://img.shields.io/badge/docs.rs-quote-66c2a5?style=for-the-badge&labelColor=555555&logo=docs.rs" height="20">](https://docs.rs/quote)
-[<img alt="build status" src="https://img.shields.io/github/workflow/status/dtolnay/quote/CI/master?style=for-the-badge" height="20">](https://github.com/dtolnay/quote/actions?query=branch%3Amaster)
+[<img alt="build status" src="https://img.shields.io/github/actions/workflow/status/dtolnay/quote/ci.yml?branch=master&style=for-the-badge" height="20">](https://github.com/dtolnay/quote/actions?query=branch%3Amaster)
This crate provides the [`quote!`] macro for turning Rust syntax tree data
structures into tokens of source code.
diff --git a/vendor/quote/src/lib.rs b/vendor/quote/src/lib.rs
index 35594827f..adc14c573 100644
--- a/vendor/quote/src/lib.rs
+++ b/vendor/quote/src/lib.rs
@@ -81,7 +81,7 @@
//! ```
// Quote types in rustdoc of other crates get linked to here.
-#![doc(html_root_url = "https://docs.rs/quote/1.0.21")]
+#![doc(html_root_url = "https://docs.rs/quote/1.0.23")]
#![allow(
clippy::doc_markdown,
clippy::missing_errors_doc,
diff --git a/vendor/quote/tests/test.rs b/vendor/quote/tests/test.rs
index 5bfcf4b45..52ec7bcfb 100644
--- a/vendor/quote/tests/test.rs
+++ b/vendor/quote/tests/test.rs
@@ -1,6 +1,5 @@
#![allow(
- clippy::blacklisted_name,
- clippy::let_underscore_drop,
+ clippy::disallowed_names,
clippy::shadow_unrelated,
clippy::unseparated_literal_suffix,
clippy::used_underscore_binding
diff --git a/vendor/quote/tests/ui/not-quotable.rs b/vendor/quote/tests/ui/not-quotable.rs
index f991c1883..220542d84 100644
--- a/vendor/quote/tests/ui/not-quotable.rs
+++ b/vendor/quote/tests/ui/not-quotable.rs
@@ -3,5 +3,5 @@ use std::net::Ipv4Addr;
fn main() {
let ip = Ipv4Addr::LOCALHOST;
- let _ = quote! { #ip };
+ _ = quote! { #ip };
}
diff --git a/vendor/quote/tests/ui/not-quotable.stderr b/vendor/quote/tests/ui/not-quotable.stderr
index 171cddd2b..c323d99b7 100644
--- a/vendor/quote/tests/ui/not-quotable.stderr
+++ b/vendor/quote/tests/ui/not-quotable.stderr
@@ -1,8 +1,11 @@
error[E0277]: the trait bound `Ipv4Addr: ToTokens` is not satisfied
- --> tests/ui/not-quotable.rs:6:13
+ --> tests/ui/not-quotable.rs:6:9
|
-6 | let _ = quote! { #ip };
- | ^^^^^^^^^^^^^^ the trait `ToTokens` is not implemented for `Ipv4Addr`
+6 | _ = quote! { #ip };
+ | ^^^^^^^^^^^^^^
+ | |
+ | the trait `ToTokens` is not implemented for `Ipv4Addr`
+ | required by a bound introduced by this call
|
= help: the following other types implement trait `ToTokens`:
&'a T
diff --git a/vendor/quote/tests/ui/not-repeatable.rs b/vendor/quote/tests/ui/not-repeatable.rs
index a8f0fe773..c1debf5f8 100644
--- a/vendor/quote/tests/ui/not-repeatable.rs
+++ b/vendor/quote/tests/ui/not-repeatable.rs
@@ -4,5 +4,5 @@ struct Ipv4Addr;
fn main() {
let ip = Ipv4Addr;
- let _ = quote! { #(#ip)* };
+ _ = quote! { #(#ip)* };
}
diff --git a/vendor/quote/tests/ui/not-repeatable.stderr b/vendor/quote/tests/ui/not-repeatable.stderr
index f75351e33..264a89f9e 100644
--- a/vendor/quote/tests/ui/not-repeatable.stderr
+++ b/vendor/quote/tests/ui/not-repeatable.stderr
@@ -1,35 +1,35 @@
error[E0599]: the method `quote_into_iter` exists for struct `Ipv4Addr`, but its trait bounds were not satisfied
- --> tests/ui/not-repeatable.rs:7:13
- |
-3 | struct Ipv4Addr;
- | ---------------
- | |
- | method `quote_into_iter` not found for this struct
- | doesn't satisfy `Ipv4Addr: Iterator`
- | doesn't satisfy `Ipv4Addr: ToTokens`
- | doesn't satisfy `Ipv4Addr: ext::RepIteratorExt`
- | doesn't satisfy `Ipv4Addr: ext::RepToTokensExt`
+ --> tests/ui/not-repeatable.rs:7:9
+ |
+3 | struct Ipv4Addr;
+ | ---------------
+ | |
+ | method `quote_into_iter` not found for this struct
+ | doesn't satisfy `Ipv4Addr: Iterator`
+ | doesn't satisfy `Ipv4Addr: ToTokens`
+ | doesn't satisfy `Ipv4Addr: ext::RepIteratorExt`
+ | doesn't satisfy `Ipv4Addr: ext::RepToTokensExt`
...
-7 | let _ = quote! { #(#ip)* };
- | ^^^^^^^^^^^^^^^^^^ method cannot be called on `Ipv4Addr` due to unsatisfied trait bounds
- |
- = note: the following trait bounds were not satisfied:
- `Ipv4Addr: Iterator`
- which is required by `Ipv4Addr: ext::RepIteratorExt`
- `&Ipv4Addr: Iterator`
- which is required by `&Ipv4Addr: ext::RepIteratorExt`
- `Ipv4Addr: ToTokens`
- which is required by `Ipv4Addr: ext::RepToTokensExt`
- `&mut Ipv4Addr: Iterator`
- which is required by `&mut Ipv4Addr: ext::RepIteratorExt`
-note: the following traits must be implemented
- --> $RUST/core/src/iter/traits/iterator.rs
- |
- | pub trait Iterator {
- | ^^^^^^^^^^^^^^^^^^
- |
- ::: src/to_tokens.rs
- |
- | pub trait ToTokens {
- | ^^^^^^^^^^^^^^^^^^
- = note: this error originates in the macro `$crate::quote_bind_into_iter` which comes from the expansion of the macro `quote` (in Nightly builds, run with -Z macro-backtrace for more info)
+7 | _ = quote! { #(#ip)* };
+ | ^^^^^^^^^^^^^^^^^^ method cannot be called on `Ipv4Addr` due to unsatisfied trait bounds
+ |
+ = note: the following trait bounds were not satisfied:
+ `Ipv4Addr: Iterator`
+ which is required by `Ipv4Addr: ext::RepIteratorExt`
+ `&Ipv4Addr: Iterator`
+ which is required by `&Ipv4Addr: ext::RepIteratorExt`
+ `Ipv4Addr: ToTokens`
+ which is required by `Ipv4Addr: ext::RepToTokensExt`
+ `&mut Ipv4Addr: Iterator`
+ which is required by `&mut Ipv4Addr: ext::RepIteratorExt`
+note: the traits `ToTokens` and `Iterator` must be implemented
+ --> src/to_tokens.rs
+ |
+ | pub trait ToTokens {
+ | ^^^^^^^^^^^^^^^^^^
+ |
+ ::: $RUST/core/src/iter/traits/iterator.rs
+ |
+ | pub trait Iterator {
+ | ^^^^^^^^^^^^^^^^^^
+ = note: this error originates in the macro `$crate::quote_bind_into_iter` which comes from the expansion of the macro `quote` (in Nightly builds, run with -Z macro-backtrace for more info)
diff --git a/vendor/rayon/.cargo-checksum.json b/vendor/rayon/.cargo-checksum.json
index 24bf4ae59..df73a32db 100644
--- a/vendor/rayon/.cargo-checksum.json
+++ b/vendor/rayon/.cargo-checksum.json
@@ -1 +1 @@
-{"files":{"Cargo.toml":"29c768a031b0c4c2b8012af25cee42f89d5e6d7bd89ec8cf8df4972420a55cc3","FAQ.md":"e963b051f6295a2944ff5abec368c7da914b913e21049978c2ef0017294abf8f","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"0621878e61f0d0fda054bcbe02df75192c28bde1ecc8289cbd86aeba2dd72720","README.md":"d972f524a7de70888a57ed63625272d4bbc24ecbdffcdb7ba8d3d520e60ab79e","RELEASES.md":"bb8dae2b0c1ec1b6c8ecd142097b4a3f11011397f7d327024936c33678851066","src/array.rs":"edd4442a74c08128284a242a6874686b25d539e8a57886fef82216e5ff31f851","src/collections/binary_heap.rs":"58e2590ff52fa2cfe7b5797fdc37902d0c111cca844aac21a4024add2f28a8db","src/collections/btree_map.rs":"d3094ed5c54620f81a86133f52e74164bae9f0137745eb66e6d31db2e942bcab","src/collections/btree_set.rs":"7de12e388d36cb2f8672bc3b68aed5b44d047c9f5fe262a7260584634299480f","src/collections/hash_map.rs":"cdaf1aa3bedf9bde591fcb323d64bee9366feb35fee6886bedb5fec8d0018564","src/collections/hash_set.rs":"685690108fc20eca2cf346e74e48d6c751f5ceb6028996366d49f1f1ad6051e0","src/collections/linked_list.rs":"bef7f32da49b55db76cfefa0afa4789a6979e08a69427e49bab2874967163fef","src/collections/mod.rs":"3978222720a2df20be7fd0856d8515b6f9fa40f6556662bd3c0726b1392970ca","src/collections/vec_deque.rs":"d14aa4edc858cd3469fff3597fc35ab83c27f3bdf66ede06d1dd25021f383109","src/compile_fail/cannot_collect_filtermap_data.rs":"f76e6727ae8bd0dc8fff5f4a79df3fc598daf5d7371bdf8b2e730fba4ba82719","src/compile_fail/cannot_zip_filtered_data.rs":"3588fcf72e804ea867ea525b6dfa7a3d45fe14e28088e849fa9ddb029acc8a7a","src/compile_fail/cell_par_iter.rs":"ebf8804993c103f9d8228aba0bb2a5f0aadb957de9f1eb59cf546dbace285201","src/compile_fail/mod.rs":"2c346e4b52941fe0ac2667eeb753c0c21a1f998a544bb9d9167f200caba0a7bb","src/compile_fail/must_use.rs":"42ae57ed7cb909fad8d079ce6e3742a92ca7f72a9cc209b149d1d88df568d757","src/compile_fail/no_send_par_iter.rs":"b241446439c659f35060df12ba91590ea4267f373ddc688e4ffc203321db24b3","src/compile_fail/rc_par_iter.rs":"938776b08612e35c85b99962024d54af5a8c87d45a050a76375d16ef6fe4299f","src/delegate.rs":"aad2a11998240fb7dd96bd054b588cac469df3b716b8dffb05239102b6507d05","src/iter/chain.rs":"f82a25577ca36bac93b5a13e75dcd70e8cee381b9baa5993dd645f0714fb9eb6","src/iter/chunks.rs":"9b901441bd8684782d4e50bf24c261bdf3392f576e7ab25b2b83be2fc9361545","src/iter/cloned.rs":"35e1c864f99f7bc93c258c4976d15ccfc1d04df969dc878fd03d35f6799377f7","src/iter/collect/consumer.rs":"5f9728fdf2db728a3ea37849c2fc43c417b221e580860be4dfc6cab526e57f8e","src/iter/collect/mod.rs":"ede28d59713c3291709a842cd54b17760008f6854a3982404eca973bdc3d2f23","src/iter/collect/test.rs":"975875022cf45f9a991040c60f3ed1f9df3805e27f64bbca5b446774793eddef","src/iter/copied.rs":"1a3457f3b0fb020593049b8b1f1be2f7a6684c2fcc66c02c911cb14e0a1943d7","src/iter/empty.rs":"3cb2d05721aab1a4d9e9c5813473e1646116c1ea570e26d9ac81e083688a0b7d","src/iter/enumerate.rs":"3204255723a93b3275cf0f208939de8960b13a9b13b8c2ba6b664e65da21cd87","src/iter/extend.rs":"6b93885d0bce6b1e01d9e220083e421436142b003dbe21f914dcf6b08abe7f10","src/iter/filter.rs":"e48f317ee4d66dea6f19ac2607c6f764d20c023d847b66c6c01826e6a46f96ab","src/iter/filter_map.rs":"2530b726b27fe3a678a34722b1baf8e223a65a0770fa8ed5dca13786ea454580","src/iter/find.rs":"896ddb05b2fa7368462e0ff2a73982ced5f93266c0e0e8c27bb3fc4ec737af21","src/iter/find_first_last/mod.rs":"fa7d7692d81ecdbecb178606ad3b1b00c80e5e4159c57d34929b012b0bea0c82","src/iter/find_first_last/test.rs":"2052eb8b87c5a0a0d49a76c83d9d74f81be18aad52ceb1b06d7e209f4fefba94","src/iter/flat_map.rs":"4db54dcda5f1f916497d0162268e6cd554478bc7ea0190709cc7c73941a0e20f","src/iter/flat_map_iter.rs":"81886d1d71f4991963ec9b6d767d9ef391c9e84807d27f6135cd92a451dc1b32","src/iter/flatten.rs":"93407a8f44f4a265f47d7fe568508d6ef922597c4ca4558e8945cf1aacdd6b30","src/iter/flatten_iter.rs":"23cf3ddc25b6cad117932c4bac2e8b945c6b56626730fd3b1787f233495d15e6","src/iter/fold.rs":"874259b408d7f8cdc376d34276d37c1837950c035ff780de8281d1edf65ded9f","src/iter/fold_chunks.rs":"78c267cc341fa71206a587b548480038a7a9bbb29d341b43733515b34e4cec48","src/iter/fold_chunks_with.rs":"fc3a49dd6a2027ec8e0c78e459ed80da1185b365909694bf1395af12b22648a8","src/iter/for_each.rs":"7af0e21ed8479eec65831d1409f61a88d45a31764f2385ec759eda1a46d388b2","src/iter/from_par_iter.rs":"9439b1ae01db2c7545d6416108700dfbafcff3f584e81704cf985ab1d986b660","src/iter/inspect.rs":"d502b6e435a44f34ba49dfe46aa809a1bad3dbaefa048540a98e3026437b1016","src/iter/interleave.rs":"3c6d82fe13b52e2ce5e1b3dba93c47f479ff44d232059cd88523b422c51dea96","src/iter/interleave_shortest.rs":"a2b1f31ea4cb29f4761d3724feddcf5a96e1f21fd623f95c85a8659294a6745a","src/iter/intersperse.rs":"6b5d3d826ed3499ba78f0ff07468d96a0e104c7ee142a2ced6be8143b43241a5","src/iter/len.rs":"1d890dffb912134402c4778b1635af713df23df8bd2a98890209926a936d8407","src/iter/map.rs":"f778f1bd0a71c962375d2ce886b40ac365afed4a032e2b9dd6c385712d3d75eb","src/iter/map_with.rs":"f83950016bb02addecec049fda73663861c80232477a7b89b7e8718291a4b481","src/iter/mod.rs":"e54fbede51a3a93c338a8d37edb47f78895f8f9a3b0760ad92ea5f4c3de09665","src/iter/multizip.rs":"10ec107f6673c9bc6d1d611e11b716c37e8601ab2f4257a460c4bc4962771347","src/iter/noop.rs":"5be6332ddfbb8fdbae1ffdb00983950a8b37a295bcb58e9a265b33806ee504e6","src/iter/once.rs":"fcebffc374dcdd206d13311dcc2e7d7a04da5687658b2f3ec3409f03ed12774b","src/iter/panic_fuse.rs":"2a4d43fa4e717629de7f69eb180f13db90ef95004975cfa20dcfaacc80435015","src/iter/par_bridge.rs":"0066e4f2ebec979cf912f27fdccd2a670bc7f387036c9bd3c8c1402ce3692139","src/iter/plumbing/README.md":"28050be91cbaf1932e65607939722bf9a0563d25d98a4e000c3a5a320488e4aa","src/iter/plumbing/mod.rs":"1156c55a15b651d161f463cb86b2f602f6246a3c7f8a82fb484db12aa6a60091","src/iter/positions.rs":"b7abfb59c12b6cceb5e539e85f9eca836054ae88225e16cfc0ba8e68177c7917","src/iter/product.rs":"da69f4781c2275c4a176432994c3fd80ea1f296afe47b329de61b1d733d990df","src/iter/reduce.rs":"2f5d6e07d7c0de2360505fa5d9198c31fd43ba7e58a6ec40f79edec19319e502","src/iter/repeat.rs":"ed46b17b79d8569f9d67b50585b116ee0293e1d6c17c0dc683c66644f6a58fd5","src/iter/rev.rs":"c4c796d7cb6398e74bef043a080403acccdf70f6a4e74b242e530d1718969b8f","src/iter/skip.rs":"93d54e17316ae15ff3cc30ca7144cb448569b18ea967dd2cd8913ac6f1334390","src/iter/splitter.rs":"0024db04b4430c2a1e8c921cec86af641f612f877f3675b15df0da9122de5f00","src/iter/step_by.rs":"be7abe2c2fba252a1b69c8cf18adfe510036c30f8ee2994404c18ae15dde317e","src/iter/sum.rs":"cf11d996507ceba39524a102559b84289e776f8fe5772114e00ae2112b38c47c","src/iter/take.rs":"e47eeca1249553b0dfaf54cd8f99026be68db76b42f1f29e09c07a98c165c50a","src/iter/test.rs":"dad5c78aa8bbd7d62cf0d76194f3c02d8f12236c5f90897f3f97f884ac1b5171","src/iter/try_fold.rs":"d4f40a00995273b8803031da4a4b139a5f462a174ef1d3c8ba54524b47ab8180","src/iter/try_reduce.rs":"12317a649f777e76e6ae610d205104d7946fbe45804fbf1caa0843118531baed","src/iter/try_reduce_with.rs":"9171563fc22110d7a359f19de7ca66a6823d8f712099d05d01560795781fdeec","src/iter/unzip.rs":"9a16ea1f3b3019a090b7189f6c42c75beb3537bc849bd4c51093120a907cea6b","src/iter/update.rs":"0362185a002cdda0e73b13237017ddc3d5e72390bba6cb2e2f021e947ed861dc","src/iter/while_some.rs":"a514891d7a07031354b48e377c239ff330d0955f184abc57a69d2a193e7fcb45","src/iter/zip.rs":"4d908f75a10b5e9b68d012bbba289f3e5e9d6a9570ce0f56fc1b4f9d96860499","src/iter/zip_eq.rs":"4c18d8f7a78e197a3268c9ef74d16690f8c960407c18bb63dc6905a2fe2bde62","src/lib.rs":"3607c5d8efce43560fff74dfa66668c1d85fd12f0ffd60aa5c7c545e8c8e77fa","src/math.rs":"040e82a4ba7a6680eb65b65f4d1fc3dc477d902855d8651105b138ae2e71c8e8","src/option.rs":"00979a9bb8f42629f2b956a6cfbd286fc8a41ffbbec85f1b5d0f0da5615dac9c","src/par_either.rs":"afa4b04ba6ea1d37aed2d68eca44d7ba0d1d09ea985c9091540dd8d3c51974f1","src/prelude.rs":"b1af578abff57f9c8a285c39e3793125cf40d9901d0f2a4f0c5f1bb9252a08de","src/private.rs":"152f6d65ce4741616a1dec796b9442f78a018d38bb040f76c4cd85008333a3bb","src/range.rs":"93bd821b851d334a365211e14b60e0fc5052a7ee09e9a26ea7dd4f018c9bf7ae","src/range_inclusive.rs":"1f18ee155ab46e7398203163d49b4dfa87135e578de3d80e2641877c5b037126","src/result.rs":"0656f0000efcea10e571df90247925dfd00a0c2194043fcbc009711fb2f7af02","src/slice/chunks.rs":"2bf07a3522381e7747e40f787727747b62fbe1f1504eac6c383f0608a335ec91","src/slice/mergesort.rs":"effe59ecc40b330c364a3da868182b72b487025d9ba0256079f8a284b85a05ef","src/slice/mod.rs":"d293c9105edc3e51b11f873ac816f28232dd708120901ce3a518e03d5b748bcf","src/slice/quicksort.rs":"355506e39eac03b18cf35a6fa01d8f126267e01736e03c85f22414ebf894a9be","src/slice/rchunks.rs":"23229976840da07e8fff6657ca626810ed380682719e4d1f0693ac08839e1b7c","src/slice/test.rs":"fca5e5e6bb5464c9332d14e7d963098ad9a072801ea508ae9eabf5d278b66bb2","src/split_producer.rs":"2b143e16bc6540792f861e215a86cfea7f4ee500d4faca2476d4165619eac90d","src/str.rs":"fe3fca9218fd17a265619551602001addf80f83187b086b3c65b4edd7857abd2","src/string.rs":"6691dd31264bd93a0528fc584585415c12f56cfb4baebbfd31ea2f1b21550f77","src/vec.rs":"c9d2f99d9a3577d57640f52e33c2d8f62b0637a8ec21bbc4aefa51ce12f7059d","tests/chars.rs":"5a2bef1cd8a7d1740a4e5403830da7bbdd584e97d602a07645c4986ee34c2ad3","tests/clones.rs":"8b1bd752d0b39b0722fa30583962940a68c917b2f7dbe6b479da5a3e7d3c5efb","tests/collect.rs":"27173f932d5c65932ad63c215c561ecf06fcbeb7253a7bb175b819e0a40107aa","tests/cross-pool.rs":"103c121c8684eef0868e3982219e406500009c26d7602167f5a514b1dfd3b4cc","tests/debug.rs":"de22193e15ac078a9952e42d255bce0f30ac7f4f69957aa6b0aada0eac146ca0","tests/drain_vec.rs":"305ca40ba41ed3b459a334386cd742c66586d62aadfb624278aabdf10b872a12","tests/intersperse.rs":"bda4fb2179086e32c77c8293b9bb85d55509c282441837ba1849c2d3aa3186a7","tests/issue671-unzip.rs":"d5eb38d8a6d8f66fdf1c40293abbf58f3ac42b5acfc5dca62b02c7ace5bfc1a4","tests/issue671.rs":"52914cac517074deaedcb81bd76b867f0b99cc7b65c3e01cfe12dc9fe38c0266","tests/iter_panic.rs":"61f0c036a2fa555303bf317ac15b4d25f1316a3beb313c8e2fca7f85228450b4","tests/named-threads.rs":"48dd0fa0de13b4554dfc1fc0adaee093e19df8b1fc601f5b9b4f15b1fc705249","tests/octillion.rs":"65e12a22f5bc6e22316b93c57c82c2556ef8a5afd4d846a6431ce8c0499ce804","tests/producer_split_at.rs":"fbb28da59e85e4c253cc314f35f113ced8db2981ceda9977145af540f9996837","tests/sort-panic-safe.rs":"290a37a1cf7e297e622fc84caa5c7c3d50e83643a3c4f67a05cf2e1f7d6f3fc0","tests/str.rs":"49059384999be57994841652718cc048389380741be5c493423f8bd2206e4453"},"package":"1e060280438193c554f654141c9ea9417886713b7acd75974c85b18a69a88e0b"} \ No newline at end of file
+{"files":{"Cargo.toml":"c992b587eb0ba53f9040697feac44d5bfd4c102f90410407e1c2215ae6602961","FAQ.md":"e963b051f6295a2944ff5abec368c7da914b913e21049978c2ef0017294abf8f","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"0621878e61f0d0fda054bcbe02df75192c28bde1ecc8289cbd86aeba2dd72720","README.md":"d972f524a7de70888a57ed63625272d4bbc24ecbdffcdb7ba8d3d520e60ab79e","RELEASES.md":"b040799ae385b37973176ba7ffea5f0b8a6434f94b99bca10ecf663f7ce80da2","src/array.rs":"edd4442a74c08128284a242a6874686b25d539e8a57886fef82216e5ff31f851","src/collections/binary_heap.rs":"58e2590ff52fa2cfe7b5797fdc37902d0c111cca844aac21a4024add2f28a8db","src/collections/btree_map.rs":"d3094ed5c54620f81a86133f52e74164bae9f0137745eb66e6d31db2e942bcab","src/collections/btree_set.rs":"7de12e388d36cb2f8672bc3b68aed5b44d047c9f5fe262a7260584634299480f","src/collections/hash_map.rs":"cdaf1aa3bedf9bde591fcb323d64bee9366feb35fee6886bedb5fec8d0018564","src/collections/hash_set.rs":"685690108fc20eca2cf346e74e48d6c751f5ceb6028996366d49f1f1ad6051e0","src/collections/linked_list.rs":"bef7f32da49b55db76cfefa0afa4789a6979e08a69427e49bab2874967163fef","src/collections/mod.rs":"3978222720a2df20be7fd0856d8515b6f9fa40f6556662bd3c0726b1392970ca","src/collections/vec_deque.rs":"d14aa4edc858cd3469fff3597fc35ab83c27f3bdf66ede06d1dd25021f383109","src/compile_fail/cannot_collect_filtermap_data.rs":"f76e6727ae8bd0dc8fff5f4a79df3fc598daf5d7371bdf8b2e730fba4ba82719","src/compile_fail/cannot_zip_filtered_data.rs":"3588fcf72e804ea867ea525b6dfa7a3d45fe14e28088e849fa9ddb029acc8a7a","src/compile_fail/cell_par_iter.rs":"ebf8804993c103f9d8228aba0bb2a5f0aadb957de9f1eb59cf546dbace285201","src/compile_fail/mod.rs":"2c346e4b52941fe0ac2667eeb753c0c21a1f998a544bb9d9167f200caba0a7bb","src/compile_fail/must_use.rs":"42ae57ed7cb909fad8d079ce6e3742a92ca7f72a9cc209b149d1d88df568d757","src/compile_fail/no_send_par_iter.rs":"b241446439c659f35060df12ba91590ea4267f373ddc688e4ffc203321db24b3","src/compile_fail/rc_par_iter.rs":"938776b08612e35c85b99962024d54af5a8c87d45a050a76375d16ef6fe4299f","src/delegate.rs":"aad2a11998240fb7dd96bd054b588cac469df3b716b8dffb05239102b6507d05","src/iter/chain.rs":"f82a25577ca36bac93b5a13e75dcd70e8cee381b9baa5993dd645f0714fb9eb6","src/iter/chunks.rs":"9b901441bd8684782d4e50bf24c261bdf3392f576e7ab25b2b83be2fc9361545","src/iter/cloned.rs":"35e1c864f99f7bc93c258c4976d15ccfc1d04df969dc878fd03d35f6799377f7","src/iter/collect/consumer.rs":"5f9728fdf2db728a3ea37849c2fc43c417b221e580860be4dfc6cab526e57f8e","src/iter/collect/mod.rs":"ede28d59713c3291709a842cd54b17760008f6854a3982404eca973bdc3d2f23","src/iter/collect/test.rs":"975875022cf45f9a991040c60f3ed1f9df3805e27f64bbca5b446774793eddef","src/iter/copied.rs":"1a3457f3b0fb020593049b8b1f1be2f7a6684c2fcc66c02c911cb14e0a1943d7","src/iter/empty.rs":"3cb2d05721aab1a4d9e9c5813473e1646116c1ea570e26d9ac81e083688a0b7d","src/iter/enumerate.rs":"3204255723a93b3275cf0f208939de8960b13a9b13b8c2ba6b664e65da21cd87","src/iter/extend.rs":"6b93885d0bce6b1e01d9e220083e421436142b003dbe21f914dcf6b08abe7f10","src/iter/filter.rs":"e48f317ee4d66dea6f19ac2607c6f764d20c023d847b66c6c01826e6a46f96ab","src/iter/filter_map.rs":"2530b726b27fe3a678a34722b1baf8e223a65a0770fa8ed5dca13786ea454580","src/iter/find.rs":"896ddb05b2fa7368462e0ff2a73982ced5f93266c0e0e8c27bb3fc4ec737af21","src/iter/find_first_last/mod.rs":"fa7d7692d81ecdbecb178606ad3b1b00c80e5e4159c57d34929b012b0bea0c82","src/iter/find_first_last/test.rs":"2052eb8b87c5a0a0d49a76c83d9d74f81be18aad52ceb1b06d7e209f4fefba94","src/iter/flat_map.rs":"4db54dcda5f1f916497d0162268e6cd554478bc7ea0190709cc7c73941a0e20f","src/iter/flat_map_iter.rs":"81886d1d71f4991963ec9b6d767d9ef391c9e84807d27f6135cd92a451dc1b32","src/iter/flatten.rs":"93407a8f44f4a265f47d7fe568508d6ef922597c4ca4558e8945cf1aacdd6b30","src/iter/flatten_iter.rs":"23cf3ddc25b6cad117932c4bac2e8b945c6b56626730fd3b1787f233495d15e6","src/iter/fold.rs":"874259b408d7f8cdc376d34276d37c1837950c035ff780de8281d1edf65ded9f","src/iter/fold_chunks.rs":"78c267cc341fa71206a587b548480038a7a9bbb29d341b43733515b34e4cec48","src/iter/fold_chunks_with.rs":"fc3a49dd6a2027ec8e0c78e459ed80da1185b365909694bf1395af12b22648a8","src/iter/for_each.rs":"7af0e21ed8479eec65831d1409f61a88d45a31764f2385ec759eda1a46d388b2","src/iter/from_par_iter.rs":"9439b1ae01db2c7545d6416108700dfbafcff3f584e81704cf985ab1d986b660","src/iter/inspect.rs":"d502b6e435a44f34ba49dfe46aa809a1bad3dbaefa048540a98e3026437b1016","src/iter/interleave.rs":"3c6d82fe13b52e2ce5e1b3dba93c47f479ff44d232059cd88523b422c51dea96","src/iter/interleave_shortest.rs":"a2b1f31ea4cb29f4761d3724feddcf5a96e1f21fd623f95c85a8659294a6745a","src/iter/intersperse.rs":"6b5d3d826ed3499ba78f0ff07468d96a0e104c7ee142a2ced6be8143b43241a5","src/iter/len.rs":"1d890dffb912134402c4778b1635af713df23df8bd2a98890209926a936d8407","src/iter/map.rs":"f778f1bd0a71c962375d2ce886b40ac365afed4a032e2b9dd6c385712d3d75eb","src/iter/map_with.rs":"f83950016bb02addecec049fda73663861c80232477a7b89b7e8718291a4b481","src/iter/mod.rs":"e54fbede51a3a93c338a8d37edb47f78895f8f9a3b0760ad92ea5f4c3de09665","src/iter/multizip.rs":"10ec107f6673c9bc6d1d611e11b716c37e8601ab2f4257a460c4bc4962771347","src/iter/noop.rs":"5be6332ddfbb8fdbae1ffdb00983950a8b37a295bcb58e9a265b33806ee504e6","src/iter/once.rs":"fcebffc374dcdd206d13311dcc2e7d7a04da5687658b2f3ec3409f03ed12774b","src/iter/panic_fuse.rs":"2a4d43fa4e717629de7f69eb180f13db90ef95004975cfa20dcfaacc80435015","src/iter/par_bridge.rs":"7b78e0180a95b6a6d429d2923cd48c07f9ae3137c7e5c8706eceaec029f77b48","src/iter/plumbing/README.md":"28050be91cbaf1932e65607939722bf9a0563d25d98a4e000c3a5a320488e4aa","src/iter/plumbing/mod.rs":"1156c55a15b651d161f463cb86b2f602f6246a3c7f8a82fb484db12aa6a60091","src/iter/positions.rs":"b7abfb59c12b6cceb5e539e85f9eca836054ae88225e16cfc0ba8e68177c7917","src/iter/product.rs":"da69f4781c2275c4a176432994c3fd80ea1f296afe47b329de61b1d733d990df","src/iter/reduce.rs":"2f5d6e07d7c0de2360505fa5d9198c31fd43ba7e58a6ec40f79edec19319e502","src/iter/repeat.rs":"ed46b17b79d8569f9d67b50585b116ee0293e1d6c17c0dc683c66644f6a58fd5","src/iter/rev.rs":"c4c796d7cb6398e74bef043a080403acccdf70f6a4e74b242e530d1718969b8f","src/iter/skip.rs":"93d54e17316ae15ff3cc30ca7144cb448569b18ea967dd2cd8913ac6f1334390","src/iter/splitter.rs":"0024db04b4430c2a1e8c921cec86af641f612f877f3675b15df0da9122de5f00","src/iter/step_by.rs":"be7abe2c2fba252a1b69c8cf18adfe510036c30f8ee2994404c18ae15dde317e","src/iter/sum.rs":"cf11d996507ceba39524a102559b84289e776f8fe5772114e00ae2112b38c47c","src/iter/take.rs":"e47eeca1249553b0dfaf54cd8f99026be68db76b42f1f29e09c07a98c165c50a","src/iter/test.rs":"dad5c78aa8bbd7d62cf0d76194f3c02d8f12236c5f90897f3f97f884ac1b5171","src/iter/try_fold.rs":"d4f40a00995273b8803031da4a4b139a5f462a174ef1d3c8ba54524b47ab8180","src/iter/try_reduce.rs":"12317a649f777e76e6ae610d205104d7946fbe45804fbf1caa0843118531baed","src/iter/try_reduce_with.rs":"9171563fc22110d7a359f19de7ca66a6823d8f712099d05d01560795781fdeec","src/iter/unzip.rs":"9a16ea1f3b3019a090b7189f6c42c75beb3537bc849bd4c51093120a907cea6b","src/iter/update.rs":"0362185a002cdda0e73b13237017ddc3d5e72390bba6cb2e2f021e947ed861dc","src/iter/while_some.rs":"a514891d7a07031354b48e377c239ff330d0955f184abc57a69d2a193e7fcb45","src/iter/zip.rs":"4d908f75a10b5e9b68d012bbba289f3e5e9d6a9570ce0f56fc1b4f9d96860499","src/iter/zip_eq.rs":"4c18d8f7a78e197a3268c9ef74d16690f8c960407c18bb63dc6905a2fe2bde62","src/lib.rs":"3607c5d8efce43560fff74dfa66668c1d85fd12f0ffd60aa5c7c545e8c8e77fa","src/math.rs":"040e82a4ba7a6680eb65b65f4d1fc3dc477d902855d8651105b138ae2e71c8e8","src/option.rs":"00979a9bb8f42629f2b956a6cfbd286fc8a41ffbbec85f1b5d0f0da5615dac9c","src/par_either.rs":"afa4b04ba6ea1d37aed2d68eca44d7ba0d1d09ea985c9091540dd8d3c51974f1","src/prelude.rs":"b1af578abff57f9c8a285c39e3793125cf40d9901d0f2a4f0c5f1bb9252a08de","src/private.rs":"152f6d65ce4741616a1dec796b9442f78a018d38bb040f76c4cd85008333a3bb","src/range.rs":"93bd821b851d334a365211e14b60e0fc5052a7ee09e9a26ea7dd4f018c9bf7ae","src/range_inclusive.rs":"1f18ee155ab46e7398203163d49b4dfa87135e578de3d80e2641877c5b037126","src/result.rs":"0656f0000efcea10e571df90247925dfd00a0c2194043fcbc009711fb2f7af02","src/slice/chunks.rs":"2bf07a3522381e7747e40f787727747b62fbe1f1504eac6c383f0608a335ec91","src/slice/mergesort.rs":"effe59ecc40b330c364a3da868182b72b487025d9ba0256079f8a284b85a05ef","src/slice/mod.rs":"d293c9105edc3e51b11f873ac816f28232dd708120901ce3a518e03d5b748bcf","src/slice/quicksort.rs":"355506e39eac03b18cf35a6fa01d8f126267e01736e03c85f22414ebf894a9be","src/slice/rchunks.rs":"23229976840da07e8fff6657ca626810ed380682719e4d1f0693ac08839e1b7c","src/slice/test.rs":"fca5e5e6bb5464c9332d14e7d963098ad9a072801ea508ae9eabf5d278b66bb2","src/split_producer.rs":"2b143e16bc6540792f861e215a86cfea7f4ee500d4faca2476d4165619eac90d","src/str.rs":"fe3fca9218fd17a265619551602001addf80f83187b086b3c65b4edd7857abd2","src/string.rs":"6691dd31264bd93a0528fc584585415c12f56cfb4baebbfd31ea2f1b21550f77","src/vec.rs":"c9d2f99d9a3577d57640f52e33c2d8f62b0637a8ec21bbc4aefa51ce12f7059d","tests/chars.rs":"5a2bef1cd8a7d1740a4e5403830da7bbdd584e97d602a07645c4986ee34c2ad3","tests/clones.rs":"8b1bd752d0b39b0722fa30583962940a68c917b2f7dbe6b479da5a3e7d3c5efb","tests/collect.rs":"27173f932d5c65932ad63c215c561ecf06fcbeb7253a7bb175b819e0a40107aa","tests/cross-pool.rs":"103c121c8684eef0868e3982219e406500009c26d7602167f5a514b1dfd3b4cc","tests/debug.rs":"de22193e15ac078a9952e42d255bce0f30ac7f4f69957aa6b0aada0eac146ca0","tests/drain_vec.rs":"305ca40ba41ed3b459a334386cd742c66586d62aadfb624278aabdf10b872a12","tests/intersperse.rs":"bda4fb2179086e32c77c8293b9bb85d55509c282441837ba1849c2d3aa3186a7","tests/issue671-unzip.rs":"d5eb38d8a6d8f66fdf1c40293abbf58f3ac42b5acfc5dca62b02c7ace5bfc1a4","tests/issue671.rs":"52914cac517074deaedcb81bd76b867f0b99cc7b65c3e01cfe12dc9fe38c0266","tests/iter_panic.rs":"61f0c036a2fa555303bf317ac15b4d25f1316a3beb313c8e2fca7f85228450b4","tests/named-threads.rs":"48dd0fa0de13b4554dfc1fc0adaee093e19df8b1fc601f5b9b4f15b1fc705249","tests/octillion.rs":"65e12a22f5bc6e22316b93c57c82c2556ef8a5afd4d846a6431ce8c0499ce804","tests/par_bridge_recursion.rs":"b8a3e1e48a14b6a98a797593487b63509c91ac961c603e3b3814110e296ae33d","tests/producer_split_at.rs":"fbb28da59e85e4c253cc314f35f113ced8db2981ceda9977145af540f9996837","tests/sort-panic-safe.rs":"290a37a1cf7e297e622fc84caa5c7c3d50e83643a3c4f67a05cf2e1f7d6f3fc0","tests/str.rs":"49059384999be57994841652718cc048389380741be5c493423f8bd2206e4453"},"package":"6db3a213adf02b3bcfd2d3846bb41cb22857d131789e01df434fb7e7bc0759b7"} \ No newline at end of file
diff --git a/vendor/rayon/Cargo.toml b/vendor/rayon/Cargo.toml
index 8b1075d7f..4a208bc77 100644
--- a/vendor/rayon/Cargo.toml
+++ b/vendor/rayon/Cargo.toml
@@ -13,7 +13,7 @@
edition = "2021"
rust-version = "1.56"
name = "rayon"
-version = "1.6.0"
+version = "1.6.1"
authors = [
"Niko Matsakis <niko@alum.mit.edu>",
"Josh Stone <cuviper@gmail.com>",
@@ -38,9 +38,6 @@ categories = ["concurrency"]
license = "MIT OR Apache-2.0"
repository = "https://github.com/rayon-rs/rayon"
-[dependencies.crossbeam-deque]
-version = "0.8.1"
-
[dependencies.either]
version = "1.0"
default-features = false
diff --git a/vendor/rayon/RELEASES.md b/vendor/rayon/RELEASES.md
index eed3445ee..f6757614c 100644
--- a/vendor/rayon/RELEASES.md
+++ b/vendor/rayon/RELEASES.md
@@ -1,3 +1,15 @@
+# Release rayon 1.6.1 (2022-12-09)
+
+- Simplified `par_bridge` to only pull one item at a time from the iterator,
+ without batching. Threads that are waiting for iterator items will now block
+ appropriately rather than spinning CPU. (Thanks @njaard!)
+- Added protection against recursion in `par_bridge`, so iterators that also
+ invoke rayon will not cause mutex recursion deadlocks.
+
+# Release rayon-core 1.10.1 (2022-11-18)
+
+- Fixed a race condition with threads going to sleep while a broadcast starts.
+
# Release rayon 1.6.0 / rayon-core 1.10.0 (2022-11-18)
- The minimum supported `rustc` is now 1.56.
diff --git a/vendor/rayon/src/iter/par_bridge.rs b/vendor/rayon/src/iter/par_bridge.rs
index 339ac1a32..8398274b3 100644
--- a/vendor/rayon/src/iter/par_bridge.rs
+++ b/vendor/rayon/src/iter/par_bridge.rs
@@ -1,12 +1,9 @@
-use crossbeam_deque::{Steal, Stealer, Worker};
-
use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering};
-use std::sync::{Mutex, TryLockError};
-use std::thread::yield_now;
+use std::sync::Mutex;
-use crate::current_num_threads;
use crate::iter::plumbing::{bridge_unindexed, Folder, UnindexedConsumer, UnindexedProducer};
use crate::iter::ParallelIterator;
+use crate::{current_num_threads, current_thread_index};
/// Conversion trait to convert an `Iterator` to a `ParallelIterator`.
///
@@ -78,71 +75,46 @@ where
where
C: UnindexedConsumer<Self::Item>,
{
- let split_count = AtomicUsize::new(current_num_threads());
- let worker = Worker::new_fifo();
- let stealer = worker.stealer();
- let done = AtomicBool::new(false);
- let iter = Mutex::new((self.iter, worker));
+ let num_threads = current_num_threads();
+ let threads_started: Vec<_> = (0..num_threads).map(|_| AtomicBool::new(false)).collect();
bridge_unindexed(
- IterParallelProducer {
- split_count: &split_count,
- done: &done,
- iter: &iter,
- items: stealer,
+ &IterParallelProducer {
+ split_count: AtomicUsize::new(num_threads),
+ iter: Mutex::new(self.iter.fuse()),
+ threads_started: &threads_started,
},
consumer,
)
}
}
-struct IterParallelProducer<'a, Iter: Iterator> {
- split_count: &'a AtomicUsize,
- done: &'a AtomicBool,
- iter: &'a Mutex<(Iter, Worker<Iter::Item>)>,
- items: Stealer<Iter::Item>,
-}
-
-// manual clone because T doesn't need to be Clone, but the derive assumes it should be
-impl<'a, Iter: Iterator + 'a> Clone for IterParallelProducer<'a, Iter> {
- fn clone(&self) -> Self {
- IterParallelProducer {
- split_count: self.split_count,
- done: self.done,
- iter: self.iter,
- items: self.items.clone(),
- }
- }
+struct IterParallelProducer<'a, Iter> {
+ split_count: AtomicUsize,
+ iter: Mutex<std::iter::Fuse<Iter>>,
+ threads_started: &'a [AtomicBool],
}
-impl<'a, Iter: Iterator + Send + 'a> UnindexedProducer for IterParallelProducer<'a, Iter>
-where
- Iter::Item: Send,
-{
+impl<Iter: Iterator + Send> UnindexedProducer for &IterParallelProducer<'_, Iter> {
type Item = Iter::Item;
fn split(self) -> (Self, Option<Self>) {
let mut count = self.split_count.load(Ordering::SeqCst);
loop {
- // Check if the iterator is exhausted *and* we've consumed every item from it.
- let done = self.done.load(Ordering::SeqCst) && self.items.is_empty();
-
- match count.checked_sub(1) {
- Some(new_count) if !done => {
- match self.split_count.compare_exchange_weak(
- count,
- new_count,
- Ordering::SeqCst,
- Ordering::SeqCst,
- ) {
- Ok(_) => return (self.clone(), Some(self)),
- Err(last_count) => count = last_count,
- }
- }
- _ => {
- return (self, None);
+ // Check if the iterator is exhausted
+ if let Some(new_count) = count.checked_sub(1) {
+ match self.split_count.compare_exchange_weak(
+ count,
+ new_count,
+ Ordering::SeqCst,
+ Ordering::SeqCst,
+ ) {
+ Ok(_) => return (self, Some(self)),
+ Err(last_count) => count = last_count,
}
+ } else {
+ return (self, None);
}
}
}
@@ -151,66 +123,39 @@ where
where
F: Folder<Self::Item>,
{
+ // Guard against work-stealing-induced recursion, in case `Iter::next()`
+ // calls rayon internally, so we don't deadlock our mutex. We might also
+ // be recursing via `folder` methods, which doesn't present a mutex hazard,
+ // but it's lower overhead for us to just check this once, rather than
+ // updating additional shared state on every mutex lock/unlock.
+ // (If this isn't a rayon thread, then there's no work-stealing anyway...)
+ if let Some(i) = current_thread_index() {
+ // Note: If the number of threads in the pool ever grows dynamically, then
+ // we'll end up sharing flags and may falsely detect recursion -- that's
+ // still fine for overall correctness, just not optimal for parallelism.
+ let thread_started = &self.threads_started[i % self.threads_started.len()];
+ if thread_started.swap(true, Ordering::Relaxed) {
+ // We can't make progress with a nested mutex, so just return and let
+ // the outermost loop continue with the rest of the iterator items.
+ return folder;
+ }
+ }
+
loop {
- match self.items.steal() {
- Steal::Success(it) => {
+ if let Ok(mut iter) = self.iter.lock() {
+ if let Some(it) = iter.next() {
+ drop(iter);
folder = folder.consume(it);
if folder.full() {
return folder;
}
+ } else {
+ return folder;
}
- Steal::Empty => {
- // Don't storm the mutex if we're already done.
- if self.done.load(Ordering::SeqCst) {
- // Someone might have pushed more between our `steal()` and `done.load()`
- if self.items.is_empty() {
- // The iterator is out of items, no use in continuing
- return folder;
- }
- } else {
- // our cache is out of items, time to load more from the iterator
- match self.iter.try_lock() {
- Ok(mut guard) => {
- // Check `done` again in case we raced with the previous lock
- // holder on its way out.
- if self.done.load(Ordering::SeqCst) {
- if self.items.is_empty() {
- return folder;
- }
- continue;
- }
-
- let count = current_num_threads();
- let count = (count * count) * 2;
-
- let (ref mut iter, ref worker) = *guard;
-
- // while worker.len() < count {
- // FIXME the new deque doesn't let us count items. We can just
- // push a number of items, but that doesn't consider active
- // stealers elsewhere.
- for _ in 0..count {
- if let Some(it) = iter.next() {
- worker.push(it);
- } else {
- self.done.store(true, Ordering::SeqCst);
- break;
- }
- }
- }
- Err(TryLockError::WouldBlock) => {
- // someone else has the mutex, just sit tight until it's ready
- yield_now(); //TODO: use a thread-pool-aware yield? (#548)
- }
- Err(TryLockError::Poisoned(_)) => {
- // any panics from other threads will have been caught by the pool,
- // and will be re-thrown when joined - just exit
- return folder;
- }
- }
- }
- }
- Steal::Retry => (),
+ } else {
+ // any panics from other threads will have been caught by the pool,
+ // and will be re-thrown when joined - just exit
+ return folder;
}
}
}
diff --git a/vendor/rayon/tests/par_bridge_recursion.rs b/vendor/rayon/tests/par_bridge_recursion.rs
new file mode 100644
index 000000000..4def0a9e4
--- /dev/null
+++ b/vendor/rayon/tests/par_bridge_recursion.rs
@@ -0,0 +1,30 @@
+use rayon::prelude::*;
+use std::iter::once_with;
+
+const N: usize = 100_000;
+
+#[test]
+fn par_bridge_recursion() {
+ let pool = rayon::ThreadPoolBuilder::new()
+ .num_threads(10)
+ .build()
+ .unwrap();
+
+ let seq: Vec<_> = (0..N).map(|i| (i, i.to_string())).collect();
+
+ pool.broadcast(|_| {
+ let mut par: Vec<_> = (0..N)
+ .into_par_iter()
+ .flat_map(|i| {
+ once_with(move || {
+ // Using rayon within the serial iterator creates an opportunity for
+ // work-stealing to make par_bridge's mutex accidentally recursive.
+ rayon::join(move || i, move || i.to_string())
+ })
+ .par_bridge()
+ })
+ .collect();
+ par.par_sort_unstable();
+ assert_eq!(seq, par);
+ });
+}
diff --git a/vendor/regex-syntax/.cargo-checksum.json b/vendor/regex-syntax/.cargo-checksum.json
index 881437810..9c05f32bc 100644
--- a/vendor/regex-syntax/.cargo-checksum.json
+++ b/vendor/regex-syntax/.cargo-checksum.json
@@ -1 +1 @@
-{"files":{"Cargo.toml":"91aed5795d8faeb9a9f43face557622d92417a17bb453b5f12ee87073040fb7d","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"6485b8ed310d3f0340bf1ad1f47645069ce4069dcc6bb46c7d5c6faf41de1fdb","README.md":"67a3e673a9da6826fd4db5be6902841c821b52b98dc22c300f6e327872392b0a","benches/bench.rs":"d2b6ae5b939abd6093064f144b981b7739d7f474ec0698a1268052fc92406635","src/ast/mod.rs":"91b277a9bb979f85a44a67e39f17f77bde033764eea1f1a93aad1b61f1250089","src/ast/parse.rs":"150b42e944f766fdca70d654dbe32f8a17498432729c78b9eb50b73ae7f91f86","src/ast/print.rs":"d12f2cc75cd62f35623e1eb7a77ab8ac804b971752082700d2c4f550f834b249","src/ast/visitor.rs":"1a7b473147e4f6b89623ef1744a9e87f665bcf160fe08a33ce8e35011811ba71","src/either.rs":"1758e3edd056884eccadd995708d1e374ba9aa65846bd0e13b1aae852607c560","src/error.rs":"b3c5903a8937d2aff229a3ec65d4571d01ec4d9874c9a242ed6562c32702bcbd","src/hir/interval.rs":"e767fed363bebe4bbda0d78b8f07e73f321eaf4f837e2d7bd14a1617387e9a89","src/hir/literal/mod.rs":"ffe9a0aff7827f97bffd29eb2f4ba96627b16953161dce6c50a2f760e76bbd98","src/hir/mod.rs":"7f83c828223a54d236d348e48d5cedf015c904812110b6c38e9d52039c2b1572","src/hir/print.rs":"651b5d9776532a78612a5f9081372a57bad693890639ac19e3128b4defa96662","src/hir/translate.rs":"c7cd9693f73760263fd49a968714d27e7985ebe840211b2d83bca6686b0602a8","src/hir/visitor.rs":"e5bf7f8c09f6155e59c9d676fe25437f7e3700f9bf5d91101d7e246a64c11d5a","src/lib.rs":"a004f65196dd5745b3112e4acc8c467b18495cecac64a58d6608b35de67371cb","src/parser.rs":"0dfb553a152e008b2755f115663e553ed99c4b8e6a4dcbcad1662737534de49d","src/unicode.rs":"2b575c75dcb8fd6becb06f2a8faa33d6f54779708bc6b103070b8acb2b3323bb","src/unicode_tables/LICENSE-UNICODE":"74db5baf44a41b1000312c673544b3374e4198af5605c7f9080a402cec42cfa3","src/unicode_tables/age.rs":"9b36dd7d359d2fa21e6ea9734a37415ba0ba9469e27b8536308f5b79139d4191","src/unicode_tables/case_folding_simple.rs":"52b74161fa1e8f2db66737156e081cece82c1f503dee604f901b2df095beb90d","src/unicode_tables/general_category.rs":"c10beb78cdab6ec14846573bfb7965b5b3a4c114d20352c21a666d8de740a049","src/unicode_tables/grapheme_cluster_break.rs":"10ba739e06f880570eaf90bddd78ec468d939c0be7cd6e39f52cfa68371a9885","src/unicode_tables/mod.rs":"26c837099cd934c8062e24bc9a0aaecf15fe1de03f9c6da3f3e1e5ac3ca24bee","src/unicode_tables/perl_decimal.rs":"2084b101c615ff368a47af72df760003a76e869dfc191e0224cd024bb88165ed","src/unicode_tables/perl_space.rs":"75b9f3c9e302fd0994ee6e9ee21ee0ab36efc513cfd083647aed9854b977a33d","src/unicode_tables/perl_word.rs":"c588d6b29b98c1160452b54e9275d43583bc3454e29aee1c07e6a18389011a9c","src/unicode_tables/property_bool.rs":"319740ac6074b2d4e6e22bf4dde7db2feb569f9b71467c893fb2553d149b9f1d","src/unicode_tables/property_names.rs":"f33b186d7d8ee5342d74ef214f7b2cfbb24345233fa49a2abf2578cae61fbdd3","src/unicode_tables/property_values.rs":"716eb87716a9a4b2a9ef2c2242d6831692564875c8e218ffa758266ca33c88b6","src/unicode_tables/script.rs":"f6020589e33bd3a058468a22ce51391f6e512f9eb88c8ac60635fae7cd641ee2","src/unicode_tables/script_extension.rs":"2ba03d13813161a064b11e9f87b87685fbf29699ef553acc6112606b7ca98169","src/unicode_tables/sentence_break.rs":"bf7635623e4dbe0195789ed8b21f83ce3394ed2c445a3005f929f4f75b2a83c3","src/unicode_tables/word_break.rs":"8f7e261a67d1adb32ea627e43cb61d6566c33a4e229113d911e86941e6997a41","src/utf8.rs":"de854b3bfb3f7dbefc422f6a25935aaeef55ead2c35386c712a1fe9bf81a7b6f","test":"8a9bd1bd9fb389e08288f951319a9bbb0d4c5284a2ba63cbdab7f6afa2c2f76e"},"package":"a3f87b73ce11b1619a3c6332f45341e0047173771e8b8b73f87bfeefb7b56244"} \ No newline at end of file
+{"files":{"Cargo.toml":"238d0bbc855edbecf9a6a6936efc20bd2759f36bc8fa4d53bdef33a1629a9a0f","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"6485b8ed310d3f0340bf1ad1f47645069ce4069dcc6bb46c7d5c6faf41de1fdb","README.md":"67a3e673a9da6826fd4db5be6902841c821b52b98dc22c300f6e327872392b0a","benches/bench.rs":"d2b6ae5b939abd6093064f144b981b7739d7f474ec0698a1268052fc92406635","src/ast/mod.rs":"91b277a9bb979f85a44a67e39f17f77bde033764eea1f1a93aad1b61f1250089","src/ast/parse.rs":"150b42e944f766fdca70d654dbe32f8a17498432729c78b9eb50b73ae7f91f86","src/ast/print.rs":"d12f2cc75cd62f35623e1eb7a77ab8ac804b971752082700d2c4f550f834b249","src/ast/visitor.rs":"1a7b473147e4f6b89623ef1744a9e87f665bcf160fe08a33ce8e35011811ba71","src/either.rs":"1758e3edd056884eccadd995708d1e374ba9aa65846bd0e13b1aae852607c560","src/error.rs":"b3c5903a8937d2aff229a3ec65d4571d01ec4d9874c9a242ed6562c32702bcbd","src/hir/interval.rs":"e767fed363bebe4bbda0d78b8f07e73f321eaf4f837e2d7bd14a1617387e9a89","src/hir/literal/mod.rs":"ffe9a0aff7827f97bffd29eb2f4ba96627b16953161dce6c50a2f760e76bbd98","src/hir/mod.rs":"7f83c828223a54d236d348e48d5cedf015c904812110b6c38e9d52039c2b1572","src/hir/print.rs":"651b5d9776532a78612a5f9081372a57bad693890639ac19e3128b4defa96662","src/hir/translate.rs":"c7cd9693f73760263fd49a968714d27e7985ebe840211b2d83bca6686b0602a8","src/hir/visitor.rs":"e5bf7f8c09f6155e59c9d676fe25437f7e3700f9bf5d91101d7e246a64c11d5a","src/lib.rs":"a004f65196dd5745b3112e4acc8c467b18495cecac64a58d6608b35de67371cb","src/parser.rs":"0dfb553a152e008b2755f115663e553ed99c4b8e6a4dcbcad1662737534de49d","src/unicode.rs":"2ad48193433fefbede0837bd645f4288f6b39b1facb59dbb7d541bce7bf19109","src/unicode_tables/LICENSE-UNICODE":"74db5baf44a41b1000312c673544b3374e4198af5605c7f9080a402cec42cfa3","src/unicode_tables/age.rs":"2a2599a4e406fbbd0efd16aa6ce385c3f97b87c34820d6686a9f9113a5231c67","src/unicode_tables/case_folding_simple.rs":"9583803d4a10486da372b76979dbd26349b40766229467238eff972c1d78e47b","src/unicode_tables/general_category.rs":"36a93ba1cdeed96a00ff29a5ab5afd2c578a89541bf4dd8b18478146cebda0aa","src/unicode_tables/grapheme_cluster_break.rs":"39c388e9805a8391d3d3e69d74d831ce4fb99aa7e13e52c64dd2bd16d4765301","src/unicode_tables/mod.rs":"26c837099cd934c8062e24bc9a0aaecf15fe1de03f9c6da3f3e1e5ac3ca24bee","src/unicode_tables/perl_decimal.rs":"a98ea4afe71c2947023ae12bd25c46bf4c7de48eeb40979eca5c96ba62cee02e","src/unicode_tables/perl_space.rs":"ea2b3b84b4a48334082dadc6c37d9fcc9c9ded84b40e8f5c9c9314898638967e","src/unicode_tables/perl_word.rs":"6f1156bd6af32151ecffea4abe07a38fa04b1fc1b227ec1a8dac5d5f08d9d74b","src/unicode_tables/property_bool.rs":"0bd64f6e3228eaecf47824e238bdf1f8a9eef113ace6e790a57f045a8106701c","src/unicode_tables/property_names.rs":"5ca25437927eb70c62adf7d038e99a601cfb8a718677fd6de832589664d3c481","src/unicode_tables/property_values.rs":"5b4cc02392d382cf7af60455fc87b9980e97409b62a4b8d6c5843190d2e2d21d","src/unicode_tables/script.rs":"ea1d771b6d0a4b12d143f9bad2ea9342a0887878cbbe3c11262b6eabedaf2dd4","src/unicode_tables/script_extension.rs":"beeb8349703d903ff861beb8401bfd2599e457dc25df872e69d6ad1615f8b5e9","src/unicode_tables/sentence_break.rs":"2befe2a27cc4e8aecb624e310ef9f371462470dd3b2f572cec1f5873a5e30aa9","src/unicode_tables/word_break.rs":"94679177731b515f0c360eff394286a1f99b59527bdbc826cbf51d32f9666187","src/utf8.rs":"de854b3bfb3f7dbefc422f6a25935aaeef55ead2c35386c712a1fe9bf81a7b6f","test":"8a9bd1bd9fb389e08288f951319a9bbb0d4c5284a2ba63cbdab7f6afa2c2f76e"},"package":"456c603be3e8d448b072f410900c09faf164fbce2d480456f50eea6e25f9c848"} \ No newline at end of file
diff --git a/vendor/regex-syntax/Cargo.toml b/vendor/regex-syntax/Cargo.toml
index 10e6bbf53..8d87f7a42 100644
--- a/vendor/regex-syntax/Cargo.toml
+++ b/vendor/regex-syntax/Cargo.toml
@@ -12,7 +12,7 @@
[package]
edition = "2018"
name = "regex-syntax"
-version = "0.6.27"
+version = "0.6.28"
authors = ["The Rust Project Developers"]
description = "A regular expression parser."
homepage = "https://github.com/rust-lang/regex"
diff --git a/vendor/regex-syntax/src/unicode.rs b/vendor/regex-syntax/src/unicode.rs
index 70d5954b7..8194d7f55 100644
--- a/vendor/regex-syntax/src/unicode.rs
+++ b/vendor/regex-syntax/src/unicode.rs
@@ -605,6 +605,7 @@ fn ages(canonical_age: &str) -> Result<impl Iterator<Item = Range>> {
("V12_1", age::V12_1),
("V13_0", age::V13_0),
("V14_0", age::V14_0),
+ ("V15_0", age::V15_0),
];
assert_eq!(AGES.len(), age::BY_NAME.len(), "ages are out of sync");
diff --git a/vendor/regex-syntax/src/unicode_tables/age.rs b/vendor/regex-syntax/src/unicode_tables/age.rs
index ffdfef316..71f4861e0 100644
--- a/vendor/regex-syntax/src/unicode_tables/age.rs
+++ b/vendor/regex-syntax/src/unicode_tables/age.rs
@@ -1,10 +1,10 @@
// DO NOT EDIT THIS FILE. IT WAS AUTOMATICALLY GENERATED BY:
//
-// ucd-generate age /tmp/ucd --chars
+// ucd-generate age ucd-15.0.0 --chars
//
-// Unicode version: 14.0.0.
+// Unicode version: 15.0.0.
//
-// ucd-generate 0.2.11 is available on crates.io.
+// ucd-generate 0.2.14 is available on crates.io.
pub const BY_NAME: &'static [(&'static str, &'static [(char, char)])] = &[
("V10_0", V10_0),
@@ -13,6 +13,7 @@ pub const BY_NAME: &'static [(&'static str, &'static [(char, char)])] = &[
("V12_1", V12_1),
("V13_0", V13_0),
("V14_0", V14_0),
+ ("V15_0", V15_0),
("V1_1", V1_1),
("V2_0", V2_0),
("V2_1", V2_1),
@@ -346,6 +347,41 @@ pub const V14_0: &'static [(char, char)] = &[
('𫜵', '𫜸'),
];
+pub const V15_0: &'static [(char, char)] = &[
+ ('ೳ', 'ೳ'),
+ ('\u{ece}', '\u{ece}'),
+ ('\u{10efd}', '\u{10eff}'),
+ ('𑈿', '\u{11241}'),
+ ('𑬀', '𑬉'),
+ ('\u{11f00}', '𑼐'),
+ ('𑼒', '\u{11f3a}'),
+ ('𑼾', '𑽙'),
+ ('𓐯', '𓐯'),
+ ('\u{13439}', '\u{13455}'),
+ ('𛄲', '𛄲'),
+ ('𛅕', '𛅕'),
+ ('𝋀', '𝋓'),
+ ('𝼥', '𝼪'),
+ ('𞀰', '𞁭'),
+ ('\u{1e08f}', '\u{1e08f}'),
+ ('𞓐', '𞓹'),
+ ('🛜', '🛜'),
+ ('🝴', '🝶'),
+ ('🝻', '🝿'),
+ ('🟙', '🟙'),
+ ('🩵', '🩷'),
+ ('🪇', '🪈'),
+ ('🪭', '🪯'),
+ ('🪻', '🪽'),
+ ('🪿', '🪿'),
+ ('🫎', '🫏'),
+ ('🫚', '🫛'),
+ ('🫨', '🫨'),
+ ('🫷', '🫸'),
+ ('𫜹', '𫜹'),
+ ('𱍐', '𲎯'),
+];
+
pub const V1_1: &'static [(char, char)] = &[
('\0', 'ǵ'),
('Ǻ', 'ȗ'),
diff --git a/vendor/regex-syntax/src/unicode_tables/case_folding_simple.rs b/vendor/regex-syntax/src/unicode_tables/case_folding_simple.rs
index 766d21b48..23f9364ce 100644
--- a/vendor/regex-syntax/src/unicode_tables/case_folding_simple.rs
+++ b/vendor/regex-syntax/src/unicode_tables/case_folding_simple.rs
@@ -1,10 +1,10 @@
// DO NOT EDIT THIS FILE. IT WAS AUTOMATICALLY GENERATED BY:
//
-// ucd-generate case-folding-simple /tmp/ucd --chars --all-pairs
+// ucd-generate case-folding-simple ucd-15.0.0 --chars --all-pairs
//
-// Unicode version: 14.0.0.
+// Unicode version: 15.0.0.
//
-// ucd-generate 0.2.11 is available on crates.io.
+// ucd-generate 0.2.14 is available on crates.io.
pub const CASE_FOLDING_SIMPLE: &'static [(char, &'static [char])] = &[
('A', &['a']),
diff --git a/vendor/regex-syntax/src/unicode_tables/general_category.rs b/vendor/regex-syntax/src/unicode_tables/general_category.rs
index 8aa6b0078..8fc928912 100644
--- a/vendor/regex-syntax/src/unicode_tables/general_category.rs
+++ b/vendor/regex-syntax/src/unicode_tables/general_category.rs
@@ -1,10 +1,10 @@
// DO NOT EDIT THIS FILE. IT WAS AUTOMATICALLY GENERATED BY:
//
-// ucd-generate general-category /tmp/ucd --chars --exclude surrogate
+// ucd-generate general-category ucd-15.0.0 --chars --exclude surrogate
//
-// Unicode version: 14.0.0.
+// Unicode version: 15.0.0.
//
-// ucd-generate 0.2.11 is available on crates.io.
+// ucd-generate 0.2.14 is available on crates.io.
pub const BY_NAME: &'static [(&'static str, &'static [(char, char)])] = &[
("Cased_Letter", CASED_LETTER),
@@ -188,6 +188,7 @@ pub const CASED_LETTER: &'static [(char, char)] = &[
('𝟄', '𝟋'),
('𝼀', '𝼉'),
('𝼋', '𝼞'),
+ ('𝼥', '𝼪'),
('𞤀', '𞥃'),
];
@@ -383,12 +384,14 @@ pub const DECIMAL_NUMBER: &'static [(char, char)] = &[
('𑱐', '𑱙'),
('𑵐', '𑵙'),
('𑶠', '𑶩'),
+ ('𑽐', '𑽙'),
('𖩠', '𖩩'),
('𖫀', '𖫉'),
('𖭐', '𖭙'),
('𝟎', '𝟿'),
('𞅀', '𞅉'),
('𞋰', '𞋹'),
+ ('𞓰', '𞓹'),
('𞥐', '𞥙'),
('🯰', '🯹'),
];
@@ -431,7 +434,7 @@ pub const FORMAT: &'static [(char, char)] = &[
('\u{fff9}', '\u{fffb}'),
('\u{110bd}', '\u{110bd}'),
('\u{110cd}', '\u{110cd}'),
- ('\u{13430}', '\u{13438}'),
+ ('\u{13430}', '\u{1343f}'),
('\u{1bca0}', '\u{1bca3}'),
('\u{1d173}', '\u{1d17a}'),
('\u{e0001}', '\u{e0001}'),
@@ -922,6 +925,7 @@ pub const LETTER: &'static [(char, char)] = &[
('𑇜', '𑇜'),
('𑈀', '𑈑'),
('𑈓', '𑈫'),
+ ('𑈿', '𑉀'),
('𑊀', '𑊆'),
('𑊈', '𑊈'),
('𑊊', '𑊍'),
@@ -984,11 +988,15 @@ pub const LETTER: &'static [(char, char)] = &[
('𑵪', '𑶉'),
('𑶘', '𑶘'),
('𑻠', '𑻲'),
+ ('𑼂', '𑼂'),
+ ('𑼄', '𑼐'),
+ ('𑼒', '𑼳'),
('𑾰', '𑾰'),
('𒀀', '𒎙'),
('𒒀', '𒕃'),
('𒾐', '𒿰'),
- ('𓀀', '𓐮'),
+ ('𓀀', '𓐯'),
+ ('𓑁', '𓑆'),
('𔐀', '𔙆'),
('𖠀', '𖨸'),
('𖩀', '𖩞'),
@@ -1011,7 +1019,9 @@ pub const LETTER: &'static [(char, char)] = &[
('𚿵', '𚿻'),
('𚿽', '𚿾'),
('𛀀', '𛄢'),
+ ('𛄲', '𛄲'),
('𛅐', '𛅒'),
+ ('𛅕', '𛅕'),
('𛅤', '𛅧'),
('𛅰', '𛋻'),
('𛰀', '𛱪'),
@@ -1049,11 +1059,14 @@ pub const LETTER: &'static [(char, char)] = &[
('𝞪', '𝟂'),
('𝟄', '𝟋'),
('𝼀', '𝼞'),
+ ('𝼥', '𝼪'),
+ ('𞀰', '𞁭'),
('𞄀', '𞄬'),
('𞄷', '𞄽'),
('𞅎', '𞅎'),
('𞊐', '𞊭'),
('𞋀', '𞋫'),
+ ('𞓐', '𞓫'),
('𞟠', '𞟦'),
('𞟨', '𞟫'),
('𞟭', '𞟮'),
@@ -1095,12 +1108,13 @@ pub const LETTER: &'static [(char, char)] = &[
('𞺥', '𞺩'),
('𞺫', '𞺻'),
('𠀀', '𪛟'),
- ('𪜀', '𫜸'),
+ ('𪜀', '𫜹'),
('𫝀', '𫠝'),
('𫠠', '𬺡'),
('𬺰', '𮯠'),
('丽', '𪘀'),
('𰀀', '𱍊'),
+ ('𱍐', '𲎯'),
];
pub const LETTER_NUMBER: &'static [(char, char)] = &[
@@ -1778,6 +1792,7 @@ pub const LOWERCASE_LETTER: &'static [(char, char)] = &[
('𝟋', '𝟋'),
('𝼀', '𝼉'),
('𝼋', '𝼞'),
+ ('𝼥', '𝼪'),
('𞤢', '𞥃'),
];
@@ -1862,6 +1877,7 @@ pub const MARK: &'static [(char, char)] = &[
('ೊ', '\u{ccd}'),
('\u{cd5}', '\u{cd6}'),
('\u{ce2}', '\u{ce3}'),
+ ('ೳ', 'ೳ'),
('\u{d00}', 'ഃ'),
('\u{d3b}', '\u{d3c}'),
('\u{d3e}', '\u{d44}'),
@@ -1880,7 +1896,7 @@ pub const MARK: &'static [(char, char)] = &[
('\u{e47}', '\u{e4e}'),
('\u{eb1}', '\u{eb1}'),
('\u{eb4}', '\u{ebc}'),
- ('\u{ec8}', '\u{ecd}'),
+ ('\u{ec8}', '\u{ece}'),
('\u{f18}', '\u{f19}'),
('\u{f35}', '\u{f35}'),
('\u{f37}', '\u{f37}'),
@@ -1982,6 +1998,7 @@ pub const MARK: &'static [(char, char)] = &[
('\u{10ae5}', '\u{10ae6}'),
('\u{10d24}', '\u{10d27}'),
('\u{10eab}', '\u{10eac}'),
+ ('\u{10efd}', '\u{10eff}'),
('\u{10f46}', '\u{10f50}'),
('\u{10f82}', '\u{10f85}'),
('𑀀', '𑀂'),
@@ -2001,6 +2018,7 @@ pub const MARK: &'static [(char, char)] = &[
('𑇎', '\u{111cf}'),
('𑈬', '\u{11237}'),
('\u{1123e}', '\u{1123e}'),
+ ('\u{11241}', '\u{11241}'),
('\u{112df}', '\u{112ea}'),
('\u{11300}', '𑌃'),
('\u{1133b}', '\u{1133c}'),
@@ -2048,6 +2066,12 @@ pub const MARK: &'static [(char, char)] = &[
('\u{11d90}', '\u{11d91}'),
('𑶓', '\u{11d97}'),
('\u{11ef3}', '𑻶'),
+ ('\u{11f00}', '\u{11f01}'),
+ ('𑼃', '𑼃'),
+ ('𑼴', '\u{11f3a}'),
+ ('𑼾', '\u{11f42}'),
+ ('\u{13440}', '\u{13440}'),
+ ('\u{13447}', '\u{13455}'),
('\u{16af0}', '\u{16af4}'),
('\u{16b30}', '\u{16b36}'),
('\u{16f4f}', '\u{16f4f}'),
@@ -2075,9 +2099,11 @@ pub const MARK: &'static [(char, char)] = &[
('\u{1e01b}', '\u{1e021}'),
('\u{1e023}', '\u{1e024}'),
('\u{1e026}', '\u{1e02a}'),
+ ('\u{1e08f}', '\u{1e08f}'),
('\u{1e130}', '\u{1e136}'),
('\u{1e2ae}', '\u{1e2ae}'),
('\u{1e2ec}', '\u{1e2ef}'),
+ ('\u{1e4ec}', '\u{1e4ef}'),
('\u{1e8d0}', '\u{1e8d6}'),
('\u{1e944}', '\u{1e94a}'),
('\u{e0100}', '\u{e01ef}'),
@@ -2218,7 +2244,9 @@ pub const MODIFIER_LETTER: &'static [(char, char)] = &[
('𚿰', '𚿳'),
('𚿵', '𚿻'),
('𚿽', '𚿾'),
+ ('𞀰', '𞁭'),
('𞄷', '𞄽'),
+ ('𞓫', '𞓫'),
('𞥋', '𞥋'),
];
@@ -2349,7 +2377,7 @@ pub const NONSPACING_MARK: &'static [(char, char)] = &[
('\u{e47}', '\u{e4e}'),
('\u{eb1}', '\u{eb1}'),
('\u{eb4}', '\u{ebc}'),
- ('\u{ec8}', '\u{ecd}'),
+ ('\u{ec8}', '\u{ece}'),
('\u{f18}', '\u{f19}'),
('\u{f35}', '\u{f35}'),
('\u{f37}', '\u{f37}'),
@@ -2480,6 +2508,7 @@ pub const NONSPACING_MARK: &'static [(char, char)] = &[
('\u{10ae5}', '\u{10ae6}'),
('\u{10d24}', '\u{10d27}'),
('\u{10eab}', '\u{10eac}'),
+ ('\u{10efd}', '\u{10eff}'),
('\u{10f46}', '\u{10f50}'),
('\u{10f82}', '\u{10f85}'),
('\u{11001}', '\u{11001}'),
@@ -2502,6 +2531,7 @@ pub const NONSPACING_MARK: &'static [(char, char)] = &[
('\u{11234}', '\u{11234}'),
('\u{11236}', '\u{11237}'),
('\u{1123e}', '\u{1123e}'),
+ ('\u{11241}', '\u{11241}'),
('\u{112df}', '\u{112df}'),
('\u{112e3}', '\u{112ea}'),
('\u{11300}', '\u{11301}'),
@@ -2563,6 +2593,12 @@ pub const NONSPACING_MARK: &'static [(char, char)] = &[
('\u{11d95}', '\u{11d95}'),
('\u{11d97}', '\u{11d97}'),
('\u{11ef3}', '\u{11ef4}'),
+ ('\u{11f00}', '\u{11f01}'),
+ ('\u{11f36}', '\u{11f3a}'),
+ ('\u{11f40}', '\u{11f40}'),
+ ('\u{11f42}', '\u{11f42}'),
+ ('\u{13440}', '\u{13440}'),
+ ('\u{13447}', '\u{13455}'),
('\u{16af0}', '\u{16af4}'),
('\u{16b30}', '\u{16b36}'),
('\u{16f4f}', '\u{16f4f}'),
@@ -2587,9 +2623,11 @@ pub const NONSPACING_MARK: &'static [(char, char)] = &[
('\u{1e01b}', '\u{1e021}'),
('\u{1e023}', '\u{1e024}'),
('\u{1e026}', '\u{1e02a}'),
+ ('\u{1e08f}', '\u{1e08f}'),
('\u{1e130}', '\u{1e136}'),
('\u{1e2ae}', '\u{1e2ae}'),
('\u{1e2ec}', '\u{1e2ef}'),
+ ('\u{1e4ec}', '\u{1e4ef}'),
('\u{1e8d0}', '\u{1e8d6}'),
('\u{1e944}', '\u{1e94a}'),
('\u{e0100}', '\u{e01ef}'),
@@ -2709,6 +2747,7 @@ pub const NUMBER: &'static [(char, char)] = &[
('𑱐', '𑱬'),
('𑵐', '𑵙'),
('𑶠', '𑶩'),
+ ('𑽐', '𑽙'),
('𑿀', '𑿔'),
('𒐀', '𒑮'),
('𖩠', '𖩩'),
@@ -2716,11 +2755,13 @@ pub const NUMBER: &'static [(char, char)] = &[
('𖭐', '𖭙'),
('𖭛', '𖭡'),
('𖺀', '𖺖'),
+ ('𝋀', '𝋓'),
('𝋠', '𝋳'),
('𝍠', '𝍸'),
('𝟎', '𝟿'),
('𞅀', '𞅉'),
('𞋰', '𞋹'),
+ ('𞓰', '𞓹'),
('𞣇', '𞣏'),
('𞥐', '𞥙'),
('𞱱', '𞲫'),
@@ -2941,7 +2982,7 @@ pub const OTHER: &'static [(char, char)] = &[
('\u{cdf}', '\u{cdf}'),
('\u{ce4}', '\u{ce5}'),
('\u{cf0}', '\u{cf0}'),
- ('\u{cf3}', '\u{cff}'),
+ ('\u{cf4}', '\u{cff}'),
('\u{d0d}', '\u{d0d}'),
('\u{d11}', '\u{d11}'),
('\u{d45}', '\u{d45}'),
@@ -2971,7 +3012,7 @@ pub const OTHER: &'static [(char, char)] = &[
('\u{ebe}', '\u{ebf}'),
('\u{ec5}', '\u{ec5}'),
('\u{ec7}', '\u{ec7}'),
- ('\u{ece}', '\u{ecf}'),
+ ('\u{ecf}', '\u{ecf}'),
('\u{eda}', '\u{edb}'),
('\u{ee0}', '\u{eff}'),
('\u{f48}', '\u{f48}'),
@@ -3243,7 +3284,7 @@ pub const OTHER: &'static [(char, char)] = &[
('\u{10e7f}', '\u{10e7f}'),
('\u{10eaa}', '\u{10eaa}'),
('\u{10eae}', '\u{10eaf}'),
- ('\u{10eb2}', '\u{10eff}'),
+ ('\u{10eb2}', '\u{10efc}'),
('\u{10f28}', '\u{10f2f}'),
('\u{10f5a}', '\u{10f6f}'),
('\u{10f8a}', '\u{10faf}'),
@@ -3261,7 +3302,7 @@ pub const OTHER: &'static [(char, char)] = &[
('\u{111e0}', '\u{111e0}'),
('\u{111f5}', '\u{111ff}'),
('\u{11212}', '\u{11212}'),
- ('\u{1123f}', '\u{1127f}'),
+ ('\u{11242}', '\u{1127f}'),
('\u{11287}', '\u{11287}'),
('\u{11289}', '\u{11289}'),
('\u{1128e}', '\u{1128e}'),
@@ -3313,7 +3354,8 @@ pub const OTHER: &'static [(char, char)] = &[
('\u{119e5}', '\u{119ff}'),
('\u{11a48}', '\u{11a4f}'),
('\u{11aa3}', '\u{11aaf}'),
- ('\u{11af9}', '\u{11bff}'),
+ ('\u{11af9}', '\u{11aff}'),
+ ('\u{11b0a}', '\u{11bff}'),
('\u{11c09}', '\u{11c09}'),
('\u{11c37}', '\u{11c37}'),
('\u{11c46}', '\u{11c4f}'),
@@ -3334,7 +3376,10 @@ pub const OTHER: &'static [(char, char)] = &[
('\u{11d92}', '\u{11d92}'),
('\u{11d99}', '\u{11d9f}'),
('\u{11daa}', '\u{11edf}'),
- ('\u{11ef9}', '\u{11faf}'),
+ ('\u{11ef9}', '\u{11eff}'),
+ ('\u{11f11}', '\u{11f11}'),
+ ('\u{11f3b}', '\u{11f3d}'),
+ ('\u{11f5a}', '\u{11faf}'),
('\u{11fb1}', '\u{11fbf}'),
('\u{11ff2}', '\u{11ffe}'),
('\u{1239a}', '\u{123ff}'),
@@ -3342,7 +3387,8 @@ pub const OTHER: &'static [(char, char)] = &[
('\u{12475}', '\u{1247f}'),
('\u{12544}', '\u{12f8f}'),
('\u{12ff3}', '\u{12fff}'),
- ('\u{1342f}', '\u{143ff}'),
+ ('\u{13430}', '\u{1343f}'),
+ ('\u{13456}', '\u{143ff}'),
('\u{14647}', '\u{167ff}'),
('\u{16a39}', '\u{16a3f}'),
('\u{16a5f}', '\u{16a5f}'),
@@ -3368,8 +3414,10 @@ pub const OTHER: &'static [(char, char)] = &[
('\u{1aff4}', '\u{1aff4}'),
('\u{1affc}', '\u{1affc}'),
('\u{1afff}', '\u{1afff}'),
- ('\u{1b123}', '\u{1b14f}'),
- ('\u{1b153}', '\u{1b163}'),
+ ('\u{1b123}', '\u{1b131}'),
+ ('\u{1b133}', '\u{1b14f}'),
+ ('\u{1b153}', '\u{1b154}'),
+ ('\u{1b156}', '\u{1b163}'),
('\u{1b168}', '\u{1b16f}'),
('\u{1b2fc}', '\u{1bbff}'),
('\u{1bc6b}', '\u{1bc6f}'),
@@ -3384,7 +3432,8 @@ pub const OTHER: &'static [(char, char)] = &[
('\u{1d127}', '\u{1d128}'),
('\u{1d173}', '\u{1d17a}'),
('\u{1d1eb}', '\u{1d1ff}'),
- ('\u{1d246}', '\u{1d2df}'),
+ ('\u{1d246}', '\u{1d2bf}'),
+ ('\u{1d2d4}', '\u{1d2df}'),
('\u{1d2f4}', '\u{1d2ff}'),
('\u{1d357}', '\u{1d35f}'),
('\u{1d379}', '\u{1d3ff}'),
@@ -3411,19 +3460,23 @@ pub const OTHER: &'static [(char, char)] = &[
('\u{1da8c}', '\u{1da9a}'),
('\u{1daa0}', '\u{1daa0}'),
('\u{1dab0}', '\u{1deff}'),
- ('\u{1df1f}', '\u{1dfff}'),
+ ('\u{1df1f}', '\u{1df24}'),
+ ('\u{1df2b}', '\u{1dfff}'),
('\u{1e007}', '\u{1e007}'),
('\u{1e019}', '\u{1e01a}'),
('\u{1e022}', '\u{1e022}'),
('\u{1e025}', '\u{1e025}'),
- ('\u{1e02b}', '\u{1e0ff}'),
+ ('\u{1e02b}', '\u{1e02f}'),
+ ('\u{1e06e}', '\u{1e08e}'),
+ ('\u{1e090}', '\u{1e0ff}'),
('\u{1e12d}', '\u{1e12f}'),
('\u{1e13e}', '\u{1e13f}'),
('\u{1e14a}', '\u{1e14d}'),
('\u{1e150}', '\u{1e28f}'),
('\u{1e2af}', '\u{1e2bf}'),
('\u{1e2fa}', '\u{1e2fe}'),
- ('\u{1e300}', '\u{1e7df}'),
+ ('\u{1e300}', '\u{1e4cf}'),
+ ('\u{1e4fa}', '\u{1e7df}'),
('\u{1e7e7}', '\u{1e7e7}'),
('\u{1e7ec}', '\u{1e7ec}'),
('\u{1e7ef}', '\u{1e7ef}'),
@@ -3481,11 +3534,11 @@ pub const OTHER: &'static [(char, char)] = &[
('\u{1f249}', '\u{1f24f}'),
('\u{1f252}', '\u{1f25f}'),
('\u{1f266}', '\u{1f2ff}'),
- ('\u{1f6d8}', '\u{1f6dc}'),
+ ('\u{1f6d8}', '\u{1f6db}'),
('\u{1f6ed}', '\u{1f6ef}'),
('\u{1f6fd}', '\u{1f6ff}'),
- ('\u{1f774}', '\u{1f77f}'),
- ('\u{1f7d9}', '\u{1f7df}'),
+ ('\u{1f777}', '\u{1f77a}'),
+ ('\u{1f7da}', '\u{1f7df}'),
('\u{1f7ec}', '\u{1f7ef}'),
('\u{1f7f1}', '\u{1f7ff}'),
('\u{1f80c}', '\u{1f80f}'),
@@ -3496,25 +3549,24 @@ pub const OTHER: &'static [(char, char)] = &[
('\u{1f8b2}', '\u{1f8ff}'),
('\u{1fa54}', '\u{1fa5f}'),
('\u{1fa6e}', '\u{1fa6f}'),
- ('\u{1fa75}', '\u{1fa77}'),
('\u{1fa7d}', '\u{1fa7f}'),
- ('\u{1fa87}', '\u{1fa8f}'),
- ('\u{1faad}', '\u{1faaf}'),
- ('\u{1fabb}', '\u{1fabf}'),
- ('\u{1fac6}', '\u{1facf}'),
- ('\u{1fada}', '\u{1fadf}'),
- ('\u{1fae8}', '\u{1faef}'),
- ('\u{1faf7}', '\u{1faff}'),
+ ('\u{1fa89}', '\u{1fa8f}'),
+ ('\u{1fabe}', '\u{1fabe}'),
+ ('\u{1fac6}', '\u{1facd}'),
+ ('\u{1fadc}', '\u{1fadf}'),
+ ('\u{1fae9}', '\u{1faef}'),
+ ('\u{1faf9}', '\u{1faff}'),
('\u{1fb93}', '\u{1fb93}'),
('\u{1fbcb}', '\u{1fbef}'),
('\u{1fbfa}', '\u{1ffff}'),
('\u{2a6e0}', '\u{2a6ff}'),
- ('\u{2b739}', '\u{2b73f}'),
+ ('\u{2b73a}', '\u{2b73f}'),
('\u{2b81e}', '\u{2b81f}'),
('\u{2cea2}', '\u{2ceaf}'),
('\u{2ebe1}', '\u{2f7ff}'),
('\u{2fa1e}', '\u{2ffff}'),
- ('\u{3134b}', '\u{e00ff}'),
+ ('\u{3134b}', '\u{3134f}'),
+ ('\u{323b0}', '\u{e00ff}'),
('\u{e01f0}', '\u{10ffff}'),
];
@@ -3883,6 +3935,7 @@ pub const OTHER_LETTER: &'static [(char, char)] = &[
('𑇜', '𑇜'),
('𑈀', '𑈑'),
('𑈓', '𑈫'),
+ ('𑈿', '𑉀'),
('𑊀', '𑊆'),
('𑊈', '𑊈'),
('𑊊', '𑊍'),
@@ -3944,11 +3997,15 @@ pub const OTHER_LETTER: &'static [(char, char)] = &[
('𑵪', '𑶉'),
('𑶘', '𑶘'),
('𑻠', '𑻲'),
+ ('𑼂', '𑼂'),
+ ('𑼄', '𑼐'),
+ ('𑼒', '𑼳'),
('𑾰', '𑾰'),
('𒀀', '𒎙'),
('𒒀', '𒕃'),
('𒾐', '𒿰'),
- ('𓀀', '𓐮'),
+ ('𓀀', '𓐯'),
+ ('𓑁', '𓑆'),
('𔐀', '𔙆'),
('𖠀', '𖨸'),
('𖩀', '𖩞'),
@@ -3963,7 +4020,9 @@ pub const OTHER_LETTER: &'static [(char, char)] = &[
('𘠀', '𘳕'),
('𘴀', '𘴈'),
('𛀀', '𛄢'),
+ ('𛄲', '𛄲'),
('𛅐', '𛅒'),
+ ('𛅕', '𛅕'),
('𛅤', '𛅧'),
('𛅰', '𛋻'),
('𛰀', '𛱪'),
@@ -3975,6 +4034,7 @@ pub const OTHER_LETTER: &'static [(char, char)] = &[
('𞅎', '𞅎'),
('𞊐', '𞊭'),
('𞋀', '𞋫'),
+ ('𞓐', '𞓪'),
('𞟠', '𞟦'),
('𞟨', '𞟫'),
('𞟭', '𞟮'),
@@ -4014,12 +4074,13 @@ pub const OTHER_LETTER: &'static [(char, char)] = &[
('𞺥', '𞺩'),
('𞺫', '𞺻'),
('𠀀', '𪛟'),
- ('𪜀', '𫜸'),
+ ('𪜀', '𫜹'),
('𫝀', '𫠝'),
('𫠠', '𬺡'),
('𬺰', '𮯠'),
('丽', '𪘀'),
('𰀀', '𱍊'),
+ ('𱍐', '𲎯'),
];
pub const OTHER_NUMBER: &'static [(char, char)] = &[
@@ -4085,6 +4146,7 @@ pub const OTHER_NUMBER: &'static [(char, char)] = &[
('𑿀', '𑿔'),
('𖭛', '𖭡'),
('𖺀', '𖺖'),
+ ('𝋀', '𝋓'),
('𝋠', '𝋳'),
('𝍠', '𝍸'),
('𞣇', '𞣏'),
@@ -4267,9 +4329,11 @@ pub const OTHER_PUNCTUATION: &'static [(char, char)] = &[
('𑨿', '𑩆'),
('𑪚', '𑪜'),
('𑪞', '𑪢'),
+ ('𑬀', '𑬉'),
('𑱁', '𑱅'),
('𑱰', '𑱱'),
('𑻷', '𑻸'),
+ ('𑽃', '𑽏'),
('𑿿', '𑿿'),
('𒑰', '𒑴'),
('𒿱', '𒿲'),
@@ -4446,10 +4510,10 @@ pub const OTHER_SYMBOL: &'static [(char, char)] = &[
('🉠', '🉥'),
('🌀', '🏺'),
('🐀', '🛗'),
- ('🛝', '🛬'),
+ ('🛜', '🛬'),
('🛰', '🛼'),
- ('🜀', '🝳'),
- ('🞀', '🟘'),
+ ('🜀', '🝶'),
+ ('🝻', '🟙'),
('🟠', '🟫'),
('🟰', '🟰'),
('🠀', '🠋'),
@@ -4460,15 +4524,13 @@ pub const OTHER_SYMBOL: &'static [(char, char)] = &[
('🢰', '🢱'),
('🤀', '🩓'),
('🩠', '🩭'),
- ('🩰', '🩴'),
- ('🩸', '🩼'),
- ('🪀', '🪆'),
- ('🪐', '🪬'),
- ('🪰', '🪺'),
- ('🫀', '🫅'),
- ('🫐', '🫙'),
- ('🫠', '🫧'),
- ('🫰', '🫶'),
+ ('🩰', '🩼'),
+ ('🪀', '🪈'),
+ ('🪐', '🪽'),
+ ('🪿', '🫅'),
+ ('🫎', '🫛'),
+ ('🫠', '🫨'),
+ ('🫰', '🫸'),
('🬀', '🮒'),
('🮔', '🯊'),
];
@@ -4657,9 +4719,11 @@ pub const PUNCTUATION: &'static [(char, char)] = &[
('𑨿', '𑩆'),
('𑪚', '𑪜'),
('𑪞', '𑪢'),
+ ('𑬀', '𑬉'),
('𑱁', '𑱅'),
('𑱰', '𑱱'),
('𑻷', '𑻸'),
+ ('𑽃', '𑽏'),
('𑿿', '𑿿'),
('𒑰', '𒑴'),
('𒿱', '𒿲'),
@@ -4731,6 +4795,7 @@ pub const SPACING_MARK: &'static [(char, char)] = &[
('ೇ', 'ೈ'),
('ೊ', 'ೋ'),
('\u{cd5}', '\u{cd6}'),
+ ('ೳ', 'ೳ'),
('ം', 'ഃ'),
('\u{d3e}', 'ീ'),
('െ', 'ൈ'),
@@ -4869,6 +4934,10 @@ pub const SPACING_MARK: &'static [(char, char)] = &[
('𑶓', '𑶔'),
('𑶖', '𑶖'),
('𑻵', '𑻶'),
+ ('𑼃', '𑼃'),
+ ('𑼴', '𑼵'),
+ ('𑼾', '𑼿'),
+ ('𑽁', '𑽁'),
('𖽑', '𖾇'),
('𖿰', '𖿱'),
('\u{1d165}', '𝅦'),
@@ -5085,10 +5154,10 @@ pub const SYMBOL: &'static [(char, char)] = &[
('🉐', '🉑'),
('🉠', '🉥'),
('🌀', '🛗'),
- ('🛝', '🛬'),
+ ('🛜', '🛬'),
('🛰', '🛼'),
- ('🜀', '🝳'),
- ('🞀', '🟘'),
+ ('🜀', '🝶'),
+ ('🝻', '🟙'),
('🟠', '🟫'),
('🟰', '🟰'),
('🠀', '🠋'),
@@ -5099,15 +5168,13 @@ pub const SYMBOL: &'static [(char, char)] = &[
('🢰', '🢱'),
('🤀', '🩓'),
('🩠', '🩭'),
- ('🩰', '🩴'),
- ('🩸', '🩼'),
- ('🪀', '🪆'),
- ('🪐', '🪬'),
- ('🪰', '🪺'),
- ('🫀', '🫅'),
- ('🫐', '🫙'),
- ('🫠', '🫧'),
- ('🫰', '🫶'),
+ ('🩰', '🩼'),
+ ('🪀', '🪈'),
+ ('🪐', '🪽'),
+ ('🪿', '🫅'),
+ ('🫎', '🫛'),
+ ('🫠', '🫨'),
+ ('🫰', '🫸'),
('🬀', '🮒'),
('🮔', '🯊'),
];
@@ -5247,7 +5314,7 @@ pub const UNASSIGNED: &'static [(char, char)] = &[
('\u{cdf}', '\u{cdf}'),
('\u{ce4}', '\u{ce5}'),
('\u{cf0}', '\u{cf0}'),
- ('\u{cf3}', '\u{cff}'),
+ ('\u{cf4}', '\u{cff}'),
('\u{d0d}', '\u{d0d}'),
('\u{d11}', '\u{d11}'),
('\u{d45}', '\u{d45}'),
@@ -5277,7 +5344,7 @@ pub const UNASSIGNED: &'static [(char, char)] = &[
('\u{ebe}', '\u{ebf}'),
('\u{ec5}', '\u{ec5}'),
('\u{ec7}', '\u{ec7}'),
- ('\u{ece}', '\u{ecf}'),
+ ('\u{ecf}', '\u{ecf}'),
('\u{eda}', '\u{edb}'),
('\u{ee0}', '\u{eff}'),
('\u{f48}', '\u{f48}'),
@@ -5547,7 +5614,7 @@ pub const UNASSIGNED: &'static [(char, char)] = &[
('\u{10e7f}', '\u{10e7f}'),
('\u{10eaa}', '\u{10eaa}'),
('\u{10eae}', '\u{10eaf}'),
- ('\u{10eb2}', '\u{10eff}'),
+ ('\u{10eb2}', '\u{10efc}'),
('\u{10f28}', '\u{10f2f}'),
('\u{10f5a}', '\u{10f6f}'),
('\u{10f8a}', '\u{10faf}'),
@@ -5565,7 +5632,7 @@ pub const UNASSIGNED: &'static [(char, char)] = &[
('\u{111e0}', '\u{111e0}'),
('\u{111f5}', '\u{111ff}'),
('\u{11212}', '\u{11212}'),
- ('\u{1123f}', '\u{1127f}'),
+ ('\u{11242}', '\u{1127f}'),
('\u{11287}', '\u{11287}'),
('\u{11289}', '\u{11289}'),
('\u{1128e}', '\u{1128e}'),
@@ -5617,7 +5684,8 @@ pub const UNASSIGNED: &'static [(char, char)] = &[
('\u{119e5}', '\u{119ff}'),
('\u{11a48}', '\u{11a4f}'),
('\u{11aa3}', '\u{11aaf}'),
- ('\u{11af9}', '\u{11bff}'),
+ ('\u{11af9}', '\u{11aff}'),
+ ('\u{11b0a}', '\u{11bff}'),
('\u{11c09}', '\u{11c09}'),
('\u{11c37}', '\u{11c37}'),
('\u{11c46}', '\u{11c4f}'),
@@ -5638,7 +5706,10 @@ pub const UNASSIGNED: &'static [(char, char)] = &[
('\u{11d92}', '\u{11d92}'),
('\u{11d99}', '\u{11d9f}'),
('\u{11daa}', '\u{11edf}'),
- ('\u{11ef9}', '\u{11faf}'),
+ ('\u{11ef9}', '\u{11eff}'),
+ ('\u{11f11}', '\u{11f11}'),
+ ('\u{11f3b}', '\u{11f3d}'),
+ ('\u{11f5a}', '\u{11faf}'),
('\u{11fb1}', '\u{11fbf}'),
('\u{11ff2}', '\u{11ffe}'),
('\u{1239a}', '\u{123ff}'),
@@ -5646,8 +5717,7 @@ pub const UNASSIGNED: &'static [(char, char)] = &[
('\u{12475}', '\u{1247f}'),
('\u{12544}', '\u{12f8f}'),
('\u{12ff3}', '\u{12fff}'),
- ('\u{1342f}', '\u{1342f}'),
- ('\u{13439}', '\u{143ff}'),
+ ('\u{13456}', '\u{143ff}'),
('\u{14647}', '\u{167ff}'),
('\u{16a39}', '\u{16a3f}'),
('\u{16a5f}', '\u{16a5f}'),
@@ -5673,8 +5743,10 @@ pub const UNASSIGNED: &'static [(char, char)] = &[
('\u{1aff4}', '\u{1aff4}'),
('\u{1affc}', '\u{1affc}'),
('\u{1afff}', '\u{1afff}'),
- ('\u{1b123}', '\u{1b14f}'),
- ('\u{1b153}', '\u{1b163}'),
+ ('\u{1b123}', '\u{1b131}'),
+ ('\u{1b133}', '\u{1b14f}'),
+ ('\u{1b153}', '\u{1b154}'),
+ ('\u{1b156}', '\u{1b163}'),
('\u{1b168}', '\u{1b16f}'),
('\u{1b2fc}', '\u{1bbff}'),
('\u{1bc6b}', '\u{1bc6f}'),
@@ -5688,7 +5760,8 @@ pub const UNASSIGNED: &'static [(char, char)] = &[
('\u{1d0f6}', '\u{1d0ff}'),
('\u{1d127}', '\u{1d128}'),
('\u{1d1eb}', '\u{1d1ff}'),
- ('\u{1d246}', '\u{1d2df}'),
+ ('\u{1d246}', '\u{1d2bf}'),
+ ('\u{1d2d4}', '\u{1d2df}'),
('\u{1d2f4}', '\u{1d2ff}'),
('\u{1d357}', '\u{1d35f}'),
('\u{1d379}', '\u{1d3ff}'),
@@ -5715,19 +5788,23 @@ pub const UNASSIGNED: &'static [(char, char)] = &[
('\u{1da8c}', '\u{1da9a}'),
('\u{1daa0}', '\u{1daa0}'),
('\u{1dab0}', '\u{1deff}'),
- ('\u{1df1f}', '\u{1dfff}'),
+ ('\u{1df1f}', '\u{1df24}'),
+ ('\u{1df2b}', '\u{1dfff}'),
('\u{1e007}', '\u{1e007}'),
('\u{1e019}', '\u{1e01a}'),
('\u{1e022}', '\u{1e022}'),
('\u{1e025}', '\u{1e025}'),
- ('\u{1e02b}', '\u{1e0ff}'),
+ ('\u{1e02b}', '\u{1e02f}'),
+ ('\u{1e06e}', '\u{1e08e}'),
+ ('\u{1e090}', '\u{1e0ff}'),
('\u{1e12d}', '\u{1e12f}'),
('\u{1e13e}', '\u{1e13f}'),
('\u{1e14a}', '\u{1e14d}'),
('\u{1e150}', '\u{1e28f}'),
('\u{1e2af}', '\u{1e2bf}'),
('\u{1e2fa}', '\u{1e2fe}'),
- ('\u{1e300}', '\u{1e7df}'),
+ ('\u{1e300}', '\u{1e4cf}'),
+ ('\u{1e4fa}', '\u{1e7df}'),
('\u{1e7e7}', '\u{1e7e7}'),
('\u{1e7ec}', '\u{1e7ec}'),
('\u{1e7ef}', '\u{1e7ef}'),
@@ -5785,11 +5862,11 @@ pub const UNASSIGNED: &'static [(char, char)] = &[
('\u{1f249}', '\u{1f24f}'),
('\u{1f252}', '\u{1f25f}'),
('\u{1f266}', '\u{1f2ff}'),
- ('\u{1f6d8}', '\u{1f6dc}'),
+ ('\u{1f6d8}', '\u{1f6db}'),
('\u{1f6ed}', '\u{1f6ef}'),
('\u{1f6fd}', '\u{1f6ff}'),
- ('\u{1f774}', '\u{1f77f}'),
- ('\u{1f7d9}', '\u{1f7df}'),
+ ('\u{1f777}', '\u{1f77a}'),
+ ('\u{1f7da}', '\u{1f7df}'),
('\u{1f7ec}', '\u{1f7ef}'),
('\u{1f7f1}', '\u{1f7ff}'),
('\u{1f80c}', '\u{1f80f}'),
@@ -5800,25 +5877,24 @@ pub const UNASSIGNED: &'static [(char, char)] = &[
('\u{1f8b2}', '\u{1f8ff}'),
('\u{1fa54}', '\u{1fa5f}'),
('\u{1fa6e}', '\u{1fa6f}'),
- ('\u{1fa75}', '\u{1fa77}'),
('\u{1fa7d}', '\u{1fa7f}'),
- ('\u{1fa87}', '\u{1fa8f}'),
- ('\u{1faad}', '\u{1faaf}'),
- ('\u{1fabb}', '\u{1fabf}'),
- ('\u{1fac6}', '\u{1facf}'),
- ('\u{1fada}', '\u{1fadf}'),
- ('\u{1fae8}', '\u{1faef}'),
- ('\u{1faf7}', '\u{1faff}'),
+ ('\u{1fa89}', '\u{1fa8f}'),
+ ('\u{1fabe}', '\u{1fabe}'),
+ ('\u{1fac6}', '\u{1facd}'),
+ ('\u{1fadc}', '\u{1fadf}'),
+ ('\u{1fae9}', '\u{1faef}'),
+ ('\u{1faf9}', '\u{1faff}'),
('\u{1fb93}', '\u{1fb93}'),
('\u{1fbcb}', '\u{1fbef}'),
('\u{1fbfa}', '\u{1ffff}'),
('\u{2a6e0}', '\u{2a6ff}'),
- ('\u{2b739}', '\u{2b73f}'),
+ ('\u{2b73a}', '\u{2b73f}'),
('\u{2b81e}', '\u{2b81f}'),
('\u{2cea2}', '\u{2ceaf}'),
('\u{2ebe1}', '\u{2f7ff}'),
('\u{2fa1e}', '\u{2ffff}'),
- ('\u{3134b}', '\u{e0000}'),
+ ('\u{3134b}', '\u{3134f}'),
+ ('\u{323b0}', '\u{e0000}'),
('\u{e0002}', '\u{e001f}'),
('\u{e0080}', '\u{e00ff}'),
('\u{e01f0}', '\u{effff}'),
diff --git a/vendor/regex-syntax/src/unicode_tables/grapheme_cluster_break.rs b/vendor/regex-syntax/src/unicode_tables/grapheme_cluster_break.rs
index 38cfc73af..294dfbdcc 100644
--- a/vendor/regex-syntax/src/unicode_tables/grapheme_cluster_break.rs
+++ b/vendor/regex-syntax/src/unicode_tables/grapheme_cluster_break.rs
@@ -1,10 +1,10 @@
// DO NOT EDIT THIS FILE. IT WAS AUTOMATICALLY GENERATED BY:
//
-// ucd-generate grapheme-cluster-break /tmp/ucd --chars
+// ucd-generate grapheme-cluster-break ucd-15.0.0 --chars
//
-// Unicode version: 14.0.0.
+// Unicode version: 15.0.0.
//
-// ucd-generate 0.2.11 is available on crates.io.
+// ucd-generate 0.2.14 is available on crates.io.
pub const BY_NAME: &'static [(&'static str, &'static [(char, char)])] = &[
("CR", CR),
@@ -38,7 +38,7 @@ pub const CONTROL: &'static [(char, char)] = &[
('\u{2060}', '\u{206f}'),
('\u{feff}', '\u{feff}'),
('\u{fff0}', '\u{fffb}'),
- ('\u{13430}', '\u{13438}'),
+ ('\u{13430}', '\u{1343f}'),
('\u{1bca0}', '\u{1bca3}'),
('\u{1d173}', '\u{1d17a}'),
('\u{e0000}', '\u{e001f}'),
@@ -149,7 +149,7 @@ pub const EXTEND: &'static [(char, char)] = &[
('\u{e47}', '\u{e4e}'),
('\u{eb1}', '\u{eb1}'),
('\u{eb4}', '\u{ebc}'),
- ('\u{ec8}', '\u{ecd}'),
+ ('\u{ec8}', '\u{ece}'),
('\u{f18}', '\u{f19}'),
('\u{f35}', '\u{f35}'),
('\u{f37}', '\u{f37}'),
@@ -278,6 +278,7 @@ pub const EXTEND: &'static [(char, char)] = &[
('\u{10ae5}', '\u{10ae6}'),
('\u{10d24}', '\u{10d27}'),
('\u{10eab}', '\u{10eac}'),
+ ('\u{10efd}', '\u{10eff}'),
('\u{10f46}', '\u{10f50}'),
('\u{10f82}', '\u{10f85}'),
('\u{11001}', '\u{11001}'),
@@ -300,6 +301,7 @@ pub const EXTEND: &'static [(char, char)] = &[
('\u{11234}', '\u{11234}'),
('\u{11236}', '\u{11237}'),
('\u{1123e}', '\u{1123e}'),
+ ('\u{11241}', '\u{11241}'),
('\u{112df}', '\u{112df}'),
('\u{112e3}', '\u{112ea}'),
('\u{11300}', '\u{11301}'),
@@ -367,6 +369,12 @@ pub const EXTEND: &'static [(char, char)] = &[
('\u{11d95}', '\u{11d95}'),
('\u{11d97}', '\u{11d97}'),
('\u{11ef3}', '\u{11ef4}'),
+ ('\u{11f00}', '\u{11f01}'),
+ ('\u{11f36}', '\u{11f3a}'),
+ ('\u{11f40}', '\u{11f40}'),
+ ('\u{11f42}', '\u{11f42}'),
+ ('\u{13440}', '\u{13440}'),
+ ('\u{13447}', '\u{13455}'),
('\u{16af0}', '\u{16af4}'),
('\u{16b30}', '\u{16b36}'),
('\u{16f4f}', '\u{16f4f}'),
@@ -393,9 +401,11 @@ pub const EXTEND: &'static [(char, char)] = &[
('\u{1e01b}', '\u{1e021}'),
('\u{1e023}', '\u{1e024}'),
('\u{1e026}', '\u{1e02a}'),
+ ('\u{1e08f}', '\u{1e08f}'),
('\u{1e130}', '\u{1e136}'),
('\u{1e2ae}', '\u{1e2ae}'),
('\u{1e2ec}', '\u{1e2ef}'),
+ ('\u{1e4ec}', '\u{1e4ef}'),
('\u{1e8d0}', '\u{1e8d6}'),
('\u{1e944}', '\u{1e94a}'),
('🏻', '🏿'),
@@ -1226,6 +1236,7 @@ pub const PREPEND: &'static [(char, char)] = &[
('𑨺', '𑨺'),
('𑪄', '𑪉'),
('𑵆', '𑵆'),
+ ('𑼂', '𑼂'),
];
pub const REGIONAL_INDICATOR: &'static [(char, char)] = &[('🇦', '🇿')];
@@ -1262,6 +1273,7 @@ pub const SPACINGMARK: &'static [(char, char)] = &[
('ೃ', 'ೄ'),
('ೇ', 'ೈ'),
('ೊ', 'ೋ'),
+ ('ೳ', 'ೳ'),
('ം', 'ഃ'),
('ി', 'ീ'),
('െ', 'ൈ'),
@@ -1387,6 +1399,10 @@ pub const SPACINGMARK: &'static [(char, char)] = &[
('𑶓', '𑶔'),
('𑶖', '𑶖'),
('𑻵', '𑻶'),
+ ('𑼃', '𑼃'),
+ ('𑼴', '𑼵'),
+ ('𑼾', '𑼿'),
+ ('𑽁', '𑽁'),
('𖽑', '𖾇'),
('𖿰', '𖿱'),
('𝅦', '𝅦'),
diff --git a/vendor/regex-syntax/src/unicode_tables/perl_decimal.rs b/vendor/regex-syntax/src/unicode_tables/perl_decimal.rs
index 9a14e4395..4f4c08a12 100644
--- a/vendor/regex-syntax/src/unicode_tables/perl_decimal.rs
+++ b/vendor/regex-syntax/src/unicode_tables/perl_decimal.rs
@@ -1,10 +1,10 @@
// DO NOT EDIT THIS FILE. IT WAS AUTOMATICALLY GENERATED BY:
//
-// ucd-generate general-category /tmp/ucd --chars --include decimalnumber
+// ucd-generate general-category ucd-15.0.0 --chars --include decimalnumber
//
-// Unicode version: 14.0.0.
+// Unicode version: 15.0.0.
//
-// ucd-generate 0.2.11 is available on crates.io.
+// ucd-generate 0.2.14 is available on crates.io.
pub const BY_NAME: &'static [(&'static str, &'static [(char, char)])] =
&[("Decimal_Number", DECIMAL_NUMBER)];
@@ -64,12 +64,14 @@ pub const DECIMAL_NUMBER: &'static [(char, char)] = &[
('𑱐', '𑱙'),
('𑵐', '𑵙'),
('𑶠', '𑶩'),
+ ('𑽐', '𑽙'),
('𖩠', '𖩩'),
('𖫀', '𖫉'),
('𖭐', '𖭙'),
('𝟎', '𝟿'),
('𞅀', '𞅉'),
('𞋰', '𞋹'),
+ ('𞓰', '𞓹'),
('𞥐', '𞥙'),
('🯰', '🯹'),
];
diff --git a/vendor/regex-syntax/src/unicode_tables/perl_space.rs b/vendor/regex-syntax/src/unicode_tables/perl_space.rs
index bb69ce1ba..174169579 100644
--- a/vendor/regex-syntax/src/unicode_tables/perl_space.rs
+++ b/vendor/regex-syntax/src/unicode_tables/perl_space.rs
@@ -1,10 +1,10 @@
// DO NOT EDIT THIS FILE. IT WAS AUTOMATICALLY GENERATED BY:
//
-// ucd-generate property-bool /tmp/ucd --chars --include whitespace
+// ucd-generate property-bool ucd-15.0.0 --chars --include whitespace
//
-// Unicode version: 14.0.0.
+// Unicode version: 15.0.0.
//
-// ucd-generate 0.2.11 is available on crates.io.
+// ucd-generate 0.2.14 is available on crates.io.
pub const BY_NAME: &'static [(&'static str, &'static [(char, char)])] =
&[("White_Space", WHITE_SPACE)];
diff --git a/vendor/regex-syntax/src/unicode_tables/perl_word.rs b/vendor/regex-syntax/src/unicode_tables/perl_word.rs
index 2c8171b2b..c1b66bd9a 100644
--- a/vendor/regex-syntax/src/unicode_tables/perl_word.rs
+++ b/vendor/regex-syntax/src/unicode_tables/perl_word.rs
@@ -1,10 +1,10 @@
// DO NOT EDIT THIS FILE. IT WAS AUTOMATICALLY GENERATED BY:
//
-// ucd-generate perl-word /tmp/ucd --chars
+// ucd-generate perl-word ucd-15.0.0 --chars
//
-// Unicode version: 14.0.0.
+// Unicode version: 15.0.0.
//
-// ucd-generate 0.2.11 is available on crates.io.
+// ucd-generate 0.2.14 is available on crates.io.
pub const PERL_WORD: &'static [(char, char)] = &[
('0', '9'),
@@ -164,7 +164,7 @@ pub const PERL_WORD: &'static [(char, char)] = &[
('ೝ', 'ೞ'),
('ೠ', '\u{ce3}'),
('೦', '೯'),
- ('ೱ', 'ೲ'),
+ ('ೱ', 'ೳ'),
('\u{d00}', 'ഌ'),
('എ', 'ഐ'),
('ഒ', '\u{d44}'),
@@ -197,7 +197,7 @@ pub const PERL_WORD: &'static [(char, char)] = &[
('ວ', 'ຽ'),
('ເ', 'ໄ'),
('ໆ', 'ໆ'),
- ('\u{ec8}', '\u{ecd}'),
+ ('\u{ec8}', '\u{ece}'),
('໐', '໙'),
('ໜ', 'ໟ'),
('ༀ', 'ༀ'),
@@ -511,7 +511,7 @@ pub const PERL_WORD: &'static [(char, char)] = &[
('𐺀', '𐺩'),
('\u{10eab}', '\u{10eac}'),
('𐺰', '𐺱'),
- ('𐼀', '𐼜'),
+ ('\u{10efd}', '𐼜'),
('𐼧', '𐼧'),
('𐼰', '\u{10f50}'),
('𐽰', '\u{10f85}'),
@@ -534,7 +534,7 @@ pub const PERL_WORD: &'static [(char, char)] = &[
('𑇜', '𑇜'),
('𑈀', '𑈑'),
('𑈓', '\u{11237}'),
- ('\u{1123e}', '\u{1123e}'),
+ ('\u{1123e}', '\u{11241}'),
('𑊀', '𑊆'),
('𑊈', '𑊈'),
('𑊊', '𑊍'),
@@ -615,12 +615,17 @@ pub const PERL_WORD: &'static [(char, char)] = &[
('𑶓', '𑶘'),
('𑶠', '𑶩'),
('𑻠', '𑻶'),
+ ('\u{11f00}', '𑼐'),
+ ('𑼒', '\u{11f3a}'),
+ ('𑼾', '\u{11f42}'),
+ ('𑽐', '𑽙'),
('𑾰', '𑾰'),
('𒀀', '𒎙'),
('𒐀', '𒑮'),
('𒒀', '𒕃'),
('𒾐', '𒿰'),
- ('𓀀', '𓐮'),
+ ('𓀀', '𓐯'),
+ ('\u{13440}', '\u{13455}'),
('𔐀', '𔙆'),
('𖠀', '𖨸'),
('𖩀', '𖩞'),
@@ -648,7 +653,9 @@ pub const PERL_WORD: &'static [(char, char)] = &[
('𚿵', '𚿻'),
('𚿽', '𚿾'),
('𛀀', '𛄢'),
+ ('𛄲', '𛄲'),
('𛅐', '𛅒'),
+ ('𛅕', '𛅕'),
('𛅤', '𛅧'),
('𛅰', '𛋻'),
('𛰀', '𛱪'),
@@ -702,17 +709,21 @@ pub const PERL_WORD: &'static [(char, char)] = &[
('\u{1da9b}', '\u{1da9f}'),
('\u{1daa1}', '\u{1daaf}'),
('𝼀', '𝼞'),
+ ('𝼥', '𝼪'),
('\u{1e000}', '\u{1e006}'),
('\u{1e008}', '\u{1e018}'),
('\u{1e01b}', '\u{1e021}'),
('\u{1e023}', '\u{1e024}'),
('\u{1e026}', '\u{1e02a}'),
+ ('𞀰', '𞁭'),
+ ('\u{1e08f}', '\u{1e08f}'),
('𞄀', '𞄬'),
('\u{1e130}', '𞄽'),
('𞅀', '𞅉'),
('𞅎', '𞅎'),
('𞊐', '\u{1e2ae}'),
('𞋀', '𞋹'),
+ ('𞓐', '𞓹'),
('𞟠', '𞟦'),
('𞟨', '𞟫'),
('𞟭', '𞟮'),
@@ -759,11 +770,12 @@ pub const PERL_WORD: &'static [(char, char)] = &[
('🅰', '🆉'),
('🯰', '🯹'),
('𠀀', '𪛟'),
- ('𪜀', '𫜸'),
+ ('𪜀', '𫜹'),
('𫝀', '𫠝'),
('𫠠', '𬺡'),
('𬺰', '𮯠'),
('丽', '𪘀'),
('𰀀', '𱍊'),
+ ('𱍐', '𲎯'),
('\u{e0100}', '\u{e01ef}'),
];
diff --git a/vendor/regex-syntax/src/unicode_tables/property_bool.rs b/vendor/regex-syntax/src/unicode_tables/property_bool.rs
index 8fb211030..a3e84b519 100644
--- a/vendor/regex-syntax/src/unicode_tables/property_bool.rs
+++ b/vendor/regex-syntax/src/unicode_tables/property_bool.rs
@@ -1,10 +1,10 @@
// DO NOT EDIT THIS FILE. IT WAS AUTOMATICALLY GENERATED BY:
//
-// ucd-generate property-bool /tmp/ucd --chars
+// ucd-generate property-bool ucd-15.0.0 --chars
//
-// Unicode version: 14.0.0.
+// Unicode version: 15.0.0.
//
-// ucd-generate 0.2.11 is available on crates.io.
+// ucd-generate 0.2.14 is available on crates.io.
pub const BY_NAME: &'static [(&'static str, &'static [(char, char)])] = &[
("ASCII_Hex_Digit", ASCII_HEX_DIGIT),
@@ -207,8 +207,7 @@ pub const ALPHABETIC: &'static [(char, char)] = &[
('ொ', 'ௌ'),
('ௐ', 'ௐ'),
('\u{bd7}', '\u{bd7}'),
- ('\u{c00}', 'ః'),
- ('అ', 'ఌ'),
+ ('\u{c00}', 'ఌ'),
('ఎ', 'ఐ'),
('ఒ', 'న'),
('ప', 'హ'),
@@ -231,7 +230,7 @@ pub const ALPHABETIC: &'static [(char, char)] = &[
('\u{cd5}', '\u{cd6}'),
('ೝ', 'ೞ'),
('ೠ', '\u{ce3}'),
- ('ೱ', 'ೲ'),
+ ('ೱ', 'ೳ'),
('\u{d00}', 'ഌ'),
('എ', 'ഐ'),
('ഒ', 'ഺ'),
@@ -269,7 +268,7 @@ pub const ALPHABETIC: &'static [(char, char)] = &[
('ༀ', 'ༀ'),
('ཀ', 'ཇ'),
('ཉ', 'ཬ'),
- ('\u{f71}', '\u{f81}'),
+ ('\u{f71}', '\u{f83}'),
('ྈ', '\u{f97}'),
('\u{f99}', '\u{fbc}'),
('က', '\u{1036}'),
@@ -571,7 +570,7 @@ pub const ALPHABETIC: &'static [(char, char)] = &[
('𐿠', '𐿶'),
('𑀀', '\u{11045}'),
('𑁱', '𑁵'),
- ('𑂂', '𑂸'),
+ ('\u{11080}', '𑂸'),
('\u{110c2}', '\u{110c2}'),
('𑃐', '𑃨'),
('\u{11100}', '\u{11132}'),
@@ -586,7 +585,7 @@ pub const ALPHABETIC: &'static [(char, char)] = &[
('𑈀', '𑈑'),
('𑈓', '\u{11234}'),
('\u{11237}', '\u{11237}'),
- ('\u{1123e}', '\u{1123e}'),
+ ('\u{1123e}', '\u{11241}'),
('𑊀', '𑊆'),
('𑊈', '𑊈'),
('𑊊', '𑊍'),
@@ -666,12 +665,16 @@ pub const ALPHABETIC: &'static [(char, char)] = &[
('𑶓', '𑶖'),
('𑶘', '𑶘'),
('𑻠', '𑻶'),
+ ('\u{11f00}', '𑼐'),
+ ('𑼒', '\u{11f3a}'),
+ ('𑼾', '\u{11f40}'),
('𑾰', '𑾰'),
('𒀀', '𒎙'),
('𒐀', '𒑮'),
('𒒀', '𒕃'),
('𒾐', '𒿰'),
- ('𓀀', '𓐮'),
+ ('𓀀', '𓐯'),
+ ('𓑁', '𓑆'),
('𔐀', '𔙆'),
('𖠀', '𖨸'),
('𖩀', '𖩞'),
@@ -695,7 +698,9 @@ pub const ALPHABETIC: &'static [(char, char)] = &[
('𚿵', '𚿻'),
('𚿽', '𚿾'),
('𛀀', '𛄢'),
+ ('𛄲', '𛄲'),
('𛅐', '𛅒'),
+ ('𛅕', '𛅕'),
('𛅤', '𛅧'),
('𛅰', '𛋻'),
('𛰀', '𛱪'),
@@ -734,16 +739,20 @@ pub const ALPHABETIC: &'static [(char, char)] = &[
('𝞪', '𝟂'),
('𝟄', '𝟋'),
('𝼀', '𝼞'),
+ ('𝼥', '𝼪'),
('\u{1e000}', '\u{1e006}'),
('\u{1e008}', '\u{1e018}'),
('\u{1e01b}', '\u{1e021}'),
('\u{1e023}', '\u{1e024}'),
('\u{1e026}', '\u{1e02a}'),
+ ('𞀰', '𞁭'),
+ ('\u{1e08f}', '\u{1e08f}'),
('𞄀', '𞄬'),
('𞄷', '𞄽'),
('𞅎', '𞅎'),
('𞊐', '𞊭'),
('𞋀', '𞋫'),
+ ('𞓐', '𞓫'),
('𞟠', '𞟦'),
('𞟨', '𞟫'),
('𞟭', '𞟮'),
@@ -789,12 +798,13 @@ pub const ALPHABETIC: &'static [(char, char)] = &[
('🅐', '🅩'),
('🅰', '🆉'),
('𠀀', '𪛟'),
- ('𪜀', '𫜸'),
+ ('𪜀', '𫜹'),
('𫝀', '𫠝'),
('𫠠', '𬺡'),
('𬺰', '𮯠'),
('丽', '𪘀'),
('𰀀', '𱍊'),
+ ('𱍐', '𲎯'),
];
pub const BIDI_CONTROL: &'static [(char, char)] = &[
@@ -1035,7 +1045,7 @@ pub const CASE_IGNORABLE: &'static [(char, char)] = &[
('\u{eb1}', '\u{eb1}'),
('\u{eb4}', '\u{ebc}'),
('ໆ', 'ໆ'),
- ('\u{ec8}', '\u{ecd}'),
+ ('\u{ec8}', '\u{ece}'),
('\u{f18}', '\u{f19}'),
('\u{f35}', '\u{f35}'),
('\u{f37}', '\u{f37}'),
@@ -1224,6 +1234,7 @@ pub const CASE_IGNORABLE: &'static [(char, char)] = &[
('\u{10ae5}', '\u{10ae6}'),
('\u{10d24}', '\u{10d27}'),
('\u{10eab}', '\u{10eac}'),
+ ('\u{10efd}', '\u{10eff}'),
('\u{10f46}', '\u{10f50}'),
('\u{10f82}', '\u{10f85}'),
('\u{11001}', '\u{11001}'),
@@ -1248,6 +1259,7 @@ pub const CASE_IGNORABLE: &'static [(char, char)] = &[
('\u{11234}', '\u{11234}'),
('\u{11236}', '\u{11237}'),
('\u{1123e}', '\u{1123e}'),
+ ('\u{11241}', '\u{11241}'),
('\u{112df}', '\u{112df}'),
('\u{112e3}', '\u{112ea}'),
('\u{11300}', '\u{11301}'),
@@ -1309,7 +1321,12 @@ pub const CASE_IGNORABLE: &'static [(char, char)] = &[
('\u{11d95}', '\u{11d95}'),
('\u{11d97}', '\u{11d97}'),
('\u{11ef3}', '\u{11ef4}'),
- ('\u{13430}', '\u{13438}'),
+ ('\u{11f00}', '\u{11f01}'),
+ ('\u{11f36}', '\u{11f3a}'),
+ ('\u{11f40}', '\u{11f40}'),
+ ('\u{11f42}', '\u{11f42}'),
+ ('\u{13430}', '\u{13440}'),
+ ('\u{13447}', '\u{13455}'),
('\u{16af0}', '\u{16af4}'),
('\u{16b30}', '\u{16b36}'),
('𖭀', '𖭃'),
@@ -1340,9 +1357,12 @@ pub const CASE_IGNORABLE: &'static [(char, char)] = &[
('\u{1e01b}', '\u{1e021}'),
('\u{1e023}', '\u{1e024}'),
('\u{1e026}', '\u{1e02a}'),
+ ('𞀰', '𞁭'),
+ ('\u{1e08f}', '\u{1e08f}'),
('\u{1e130}', '𞄽'),
('\u{1e2ae}', '\u{1e2ae}'),
('\u{1e2ec}', '\u{1e2ef}'),
+ ('𞓫', '\u{1e4ef}'),
('\u{1e8d0}', '\u{1e8d6}'),
('\u{1e944}', '𞥋'),
('🏻', '🏿'),
@@ -1383,7 +1403,7 @@ pub const CASED: &'static [(char, char)] = &[
('Ⴧ', 'Ⴧ'),
('Ⴭ', 'Ⴭ'),
('ა', 'ჺ'),
- ('ჽ', 'ჿ'),
+ ('ჼ', 'ჿ'),
('Ꭰ', 'Ᏽ'),
('ᏸ', 'ᏽ'),
('ᲀ', 'ᲈ'),
@@ -1443,10 +1463,10 @@ pub const CASED: &'static [(char, char)] = &[
('Ꟑ', 'ꟑ'),
('ꟓ', 'ꟓ'),
('ꟕ', 'ꟙ'),
- ('Ꟶ', 'ꟶ'),
+ ('ꟲ', 'ꟶ'),
('ꟸ', 'ꟺ'),
('ꬰ', 'ꭚ'),
- ('ꭜ', 'ꭨ'),
+ ('ꭜ', 'ꭩ'),
('ꭰ', 'ꮿ'),
('ff', 'st'),
('ﬓ', 'ﬗ'),
@@ -1503,6 +1523,8 @@ pub const CASED: &'static [(char, char)] = &[
('𝟄', '𝟋'),
('𝼀', '𝼉'),
('𝼋', '𝼞'),
+ ('𝼥', '𝼪'),
+ ('𞀰', '𞁭'),
('𞤀', '𞥃'),
('🄰', '🅉'),
('🅐', '🅩'),
@@ -4336,6 +4358,7 @@ pub const DIACRITIC: &'static [(char, char)] = &[
('𐞲', '𐞺'),
('\u{10ae5}', '\u{10ae6}'),
('𐴢', '\u{10d27}'),
+ ('\u{10efd}', '\u{10eff}'),
('\u{10f46}', '\u{10f50}'),
('\u{10f82}', '\u{10f85}'),
('\u{11046}', '\u{11046}'),
@@ -4369,6 +4392,7 @@ pub const DIACRITIC: &'static [(char, char)] = &[
('\u{11d42}', '\u{11d42}'),
('\u{11d44}', '\u{11d45}'),
('\u{11d97}', '\u{11d97}'),
+ ('\u{13447}', '\u{13455}'),
('\u{16af0}', '\u{16af4}'),
('\u{16b30}', '\u{16b36}'),
('\u{16f8f}', '𖾟'),
@@ -4383,6 +4407,7 @@ pub const DIACRITIC: &'static [(char, char)] = &[
('\u{1d17b}', '\u{1d182}'),
('\u{1d185}', '\u{1d18b}'),
('\u{1d1aa}', '\u{1d1ad}'),
+ ('𞀰', '𞁭'),
('\u{1e130}', '\u{1e136}'),
('\u{1e2ae}', '\u{1e2ae}'),
('\u{1e2ec}', '\u{1e2ef}'),
@@ -4526,7 +4551,7 @@ pub const EMOJI: &'static [(char, char)] = &[
('🚀', '🛅'),
('🛋', '🛒'),
('🛕', '🛗'),
- ('🛝', '🛥'),
+ ('🛜', '🛥'),
('🛩', '🛩'),
('🛫', '🛬'),
('🛰', '🛰'),
@@ -4536,15 +4561,13 @@ pub const EMOJI: &'static [(char, char)] = &[
('🤌', '🤺'),
('🤼', '🥅'),
('🥇', '🧿'),
- ('🩰', '🩴'),
- ('🩸', '🩼'),
- ('🪀', '🪆'),
- ('🪐', '🪬'),
- ('🪰', '🪺'),
- ('🫀', '🫅'),
- ('🫐', '🫙'),
- ('🫠', '🫧'),
- ('🫰', '🫶'),
+ ('🩰', '🩼'),
+ ('🪀', '🪈'),
+ ('🪐', '🪽'),
+ ('🪿', '🫅'),
+ ('🫎', '🫛'),
+ ('🫠', '🫨'),
+ ('🫰', '🫸'),
];
pub const EMOJI_COMPONENT: &'static [(char, char)] = &[
@@ -4602,7 +4625,7 @@ pub const EMOJI_MODIFIER_BASE: &'static [(char, char)] = &[
('🧍', '🧏'),
('🧑', '🧝'),
('🫃', '🫅'),
- ('🫰', '🫶'),
+ ('🫰', '🫸'),
];
pub const EMOJI_PRESENTATION: &'static [(char, char)] = &[
@@ -4672,7 +4695,7 @@ pub const EMOJI_PRESENTATION: &'static [(char, char)] = &[
('🛌', '🛌'),
('🛐', '🛒'),
('🛕', '🛗'),
- ('🛝', '🛟'),
+ ('🛜', '🛟'),
('🛫', '🛬'),
('🛴', '🛼'),
('🟠', '🟫'),
@@ -4680,15 +4703,13 @@ pub const EMOJI_PRESENTATION: &'static [(char, char)] = &[
('🤌', '🤺'),
('🤼', '🥅'),
('🥇', '🧿'),
- ('🩰', '🩴'),
- ('🩸', '🩼'),
- ('🪀', '🪆'),
- ('🪐', '🪬'),
- ('🪰', '🪺'),
- ('🫀', '🫅'),
- ('🫐', '🫙'),
- ('🫠', '🫧'),
- ('🫰', '🫶'),
+ ('🩰', '🩼'),
+ ('🪀', '🪈'),
+ ('🪐', '🪽'),
+ ('🪿', '🫅'),
+ ('🫎', '🫛'),
+ ('🫠', '🫨'),
+ ('🫰', '🫸'),
];
pub const EXTENDED_PICTOGRAPHIC: &'static [(char, char)] = &[
@@ -4759,7 +4780,7 @@ pub const EXTENDED_PICTOGRAPHIC: &'static [(char, char)] = &[
('🐀', '🔽'),
('🕆', '🙏'),
('🚀', '\u{1f6ff}'),
- ('\u{1f774}', '\u{1f77f}'),
+ ('🝴', '🝿'),
('🟕', '\u{1f7ff}'),
('\u{1f80c}', '\u{1f80f}'),
('\u{1f848}', '\u{1f84f}'),
@@ -4958,7 +4979,7 @@ pub const GRAPHEME_BASE: &'static [(char, char)] = &[
('ೝ', 'ೞ'),
('ೠ', 'ೡ'),
('೦', '೯'),
- ('ೱ', 'ೲ'),
+ ('ೱ', 'ೳ'),
('ം', 'ഌ'),
('എ', 'ഐ'),
('ഒ', 'ഺ'),
@@ -5377,6 +5398,7 @@ pub const GRAPHEME_BASE: &'static [(char, char)] = &[
('𑈲', '𑈳'),
('𑈵', '𑈵'),
('𑈸', '𑈽'),
+ ('𑈿', '𑉀'),
('𑊀', '𑊆'),
('𑊈', '𑊈'),
('𑊊', '𑊍'),
@@ -5463,6 +5485,7 @@ pub const GRAPHEME_BASE: &'static [(char, char)] = &[
('𑪗', '𑪗'),
('𑪚', '𑪢'),
('𑪰', '𑫸'),
+ ('𑬀', '𑬉'),
('𑰀', '𑰈'),
('𑰊', '𑰯'),
('𑰾', '𑰾'),
@@ -5486,6 +5509,11 @@ pub const GRAPHEME_BASE: &'static [(char, char)] = &[
('𑶠', '𑶩'),
('𑻠', '𑻲'),
('𑻵', '𑻸'),
+ ('𑼂', '𑼐'),
+ ('𑼒', '𑼵'),
+ ('𑼾', '𑼿'),
+ ('𑽁', '𑽁'),
+ ('𑽃', '𑽙'),
('𑾰', '𑾰'),
('𑿀', '𑿱'),
('𑿿', '𒎙'),
@@ -5493,7 +5521,8 @@ pub const GRAPHEME_BASE: &'static [(char, char)] = &[
('𒑰', '𒑴'),
('𒒀', '𒕃'),
('𒾐', '𒿲'),
- ('𓀀', '𓐮'),
+ ('𓀀', '𓐯'),
+ ('𓑁', '𓑆'),
('𔐀', '𔙆'),
('𖠀', '𖨸'),
('𖩀', '𖩞'),
@@ -5521,7 +5550,9 @@ pub const GRAPHEME_BASE: &'static [(char, char)] = &[
('𚿵', '𚿻'),
('𚿽', '𚿾'),
('𛀀', '𛄢'),
+ ('𛄲', '𛄲'),
('𛅐', '𛅒'),
+ ('𛅕', '𛅕'),
('𛅤', '𛅧'),
('𛅰', '𛋻'),
('𛰀', '𛱪'),
@@ -5541,6 +5572,7 @@ pub const GRAPHEME_BASE: &'static [(char, char)] = &[
('𝆮', '𝇪'),
('𝈀', '𝉁'),
('𝉅', '𝉅'),
+ ('𝋀', '𝋓'),
('𝋠', '𝋳'),
('𝌀', '𝍖'),
('𝍠', '𝍸'),
@@ -5570,6 +5602,8 @@ pub const GRAPHEME_BASE: &'static [(char, char)] = &[
('𝩶', '𝪃'),
('𝪅', '𝪋'),
('𝼀', '𝼞'),
+ ('𝼥', '𝼪'),
+ ('𞀰', '𞁭'),
('𞄀', '𞄬'),
('𞄷', '𞄽'),
('𞅀', '𞅉'),
@@ -5578,6 +5612,8 @@ pub const GRAPHEME_BASE: &'static [(char, char)] = &[
('𞋀', '𞋫'),
('𞋰', '𞋹'),
('𞋿', '𞋿'),
+ ('𞓐', '𞓫'),
+ ('𞓰', '𞓹'),
('𞟠', '𞟦'),
('𞟨', '𞟫'),
('𞟭', '𞟮'),
@@ -5637,10 +5673,10 @@ pub const GRAPHEME_BASE: &'static [(char, char)] = &[
('🉐', '🉑'),
('🉠', '🉥'),
('🌀', '🛗'),
- ('🛝', '🛬'),
+ ('🛜', '🛬'),
('🛰', '🛼'),
- ('🜀', '🝳'),
- ('🞀', '🟘'),
+ ('🜀', '🝶'),
+ ('🝻', '🟙'),
('🟠', '🟫'),
('🟰', '🟰'),
('🠀', '🠋'),
@@ -5651,25 +5687,24 @@ pub const GRAPHEME_BASE: &'static [(char, char)] = &[
('🢰', '🢱'),
('🤀', '🩓'),
('🩠', '🩭'),
- ('🩰', '🩴'),
- ('🩸', '🩼'),
- ('🪀', '🪆'),
- ('🪐', '🪬'),
- ('🪰', '🪺'),
- ('🫀', '🫅'),
- ('🫐', '🫙'),
- ('🫠', '🫧'),
- ('🫰', '🫶'),
+ ('🩰', '🩼'),
+ ('🪀', '🪈'),
+ ('🪐', '🪽'),
+ ('🪿', '🫅'),
+ ('🫎', '🫛'),
+ ('🫠', '🫨'),
+ ('🫰', '🫸'),
('🬀', '🮒'),
('🮔', '🯊'),
('🯰', '🯹'),
('𠀀', '𪛟'),
- ('𪜀', '𫜸'),
+ ('𪜀', '𫜹'),
('𫝀', '𫠝'),
('𫠠', '𬺡'),
('𬺰', '𮯠'),
('丽', '𪘀'),
('𰀀', '𱍊'),
+ ('𱍐', '𲎯'),
];
pub const GRAPHEME_EXTEND: &'static [(char, char)] = &[
@@ -5775,7 +5810,7 @@ pub const GRAPHEME_EXTEND: &'static [(char, char)] = &[
('\u{e47}', '\u{e4e}'),
('\u{eb1}', '\u{eb1}'),
('\u{eb4}', '\u{ebc}'),
- ('\u{ec8}', '\u{ecd}'),
+ ('\u{ec8}', '\u{ece}'),
('\u{f18}', '\u{f19}'),
('\u{f35}', '\u{f35}'),
('\u{f37}', '\u{f37}'),
@@ -5904,6 +5939,7 @@ pub const GRAPHEME_EXTEND: &'static [(char, char)] = &[
('\u{10ae5}', '\u{10ae6}'),
('\u{10d24}', '\u{10d27}'),
('\u{10eab}', '\u{10eac}'),
+ ('\u{10efd}', '\u{10eff}'),
('\u{10f46}', '\u{10f50}'),
('\u{10f82}', '\u{10f85}'),
('\u{11001}', '\u{11001}'),
@@ -5926,6 +5962,7 @@ pub const GRAPHEME_EXTEND: &'static [(char, char)] = &[
('\u{11234}', '\u{11234}'),
('\u{11236}', '\u{11237}'),
('\u{1123e}', '\u{1123e}'),
+ ('\u{11241}', '\u{11241}'),
('\u{112df}', '\u{112df}'),
('\u{112e3}', '\u{112ea}'),
('\u{11300}', '\u{11301}'),
@@ -5993,6 +6030,12 @@ pub const GRAPHEME_EXTEND: &'static [(char, char)] = &[
('\u{11d95}', '\u{11d95}'),
('\u{11d97}', '\u{11d97}'),
('\u{11ef3}', '\u{11ef4}'),
+ ('\u{11f00}', '\u{11f01}'),
+ ('\u{11f36}', '\u{11f3a}'),
+ ('\u{11f40}', '\u{11f40}'),
+ ('\u{11f42}', '\u{11f42}'),
+ ('\u{13440}', '\u{13440}'),
+ ('\u{13447}', '\u{13455}'),
('\u{16af0}', '\u{16af4}'),
('\u{16b30}', '\u{16b36}'),
('\u{16f4f}', '\u{16f4f}'),
@@ -6019,9 +6062,11 @@ pub const GRAPHEME_EXTEND: &'static [(char, char)] = &[
('\u{1e01b}', '\u{1e021}'),
('\u{1e023}', '\u{1e024}'),
('\u{1e026}', '\u{1e02a}'),
+ ('\u{1e08f}', '\u{1e08f}'),
('\u{1e130}', '\u{1e136}'),
('\u{1e2ae}', '\u{1e2ae}'),
('\u{1e2ec}', '\u{1e2ef}'),
+ ('\u{1e4ec}', '\u{1e4ef}'),
('\u{1e8d0}', '\u{1e8d6}'),
('\u{1e944}', '\u{1e94a}'),
('\u{e0020}', '\u{e007f}'),
@@ -6084,6 +6129,7 @@ pub const GRAPHEME_LINK: &'static [(char, char)] = &[
('\u{11c3f}', '\u{11c3f}'),
('\u{11d44}', '\u{11d45}'),
('\u{11d97}', '\u{11d97}'),
+ ('𑽁', '\u{11f42}'),
];
pub const HEX_DIGIT: &'static [(char, char)] = &[
@@ -6272,7 +6318,7 @@ pub const ID_CONTINUE: &'static [(char, char)] = &[
('ೝ', 'ೞ'),
('ೠ', '\u{ce3}'),
('೦', '೯'),
- ('ೱ', 'ೲ'),
+ ('ೱ', 'ೳ'),
('\u{d00}', 'ഌ'),
('എ', 'ഐ'),
('ഒ', '\u{d44}'),
@@ -6305,7 +6351,7 @@ pub const ID_CONTINUE: &'static [(char, char)] = &[
('ວ', 'ຽ'),
('ເ', 'ໄ'),
('ໆ', 'ໆ'),
- ('\u{ec8}', '\u{ecd}'),
+ ('\u{ec8}', '\u{ece}'),
('໐', '໙'),
('ໜ', 'ໟ'),
('ༀ', 'ༀ'),
@@ -6618,7 +6664,7 @@ pub const ID_CONTINUE: &'static [(char, char)] = &[
('𐺀', '𐺩'),
('\u{10eab}', '\u{10eac}'),
('𐺰', '𐺱'),
- ('𐼀', '𐼜'),
+ ('\u{10efd}', '𐼜'),
('𐼧', '𐼧'),
('𐼰', '\u{10f50}'),
('𐽰', '\u{10f85}'),
@@ -6641,7 +6687,7 @@ pub const ID_CONTINUE: &'static [(char, char)] = &[
('𑇜', '𑇜'),
('𑈀', '𑈑'),
('𑈓', '\u{11237}'),
- ('\u{1123e}', '\u{1123e}'),
+ ('\u{1123e}', '\u{11241}'),
('𑊀', '𑊆'),
('𑊈', '𑊈'),
('𑊊', '𑊍'),
@@ -6722,12 +6768,17 @@ pub const ID_CONTINUE: &'static [(char, char)] = &[
('𑶓', '𑶘'),
('𑶠', '𑶩'),
('𑻠', '𑻶'),
+ ('\u{11f00}', '𑼐'),
+ ('𑼒', '\u{11f3a}'),
+ ('𑼾', '\u{11f42}'),
+ ('𑽐', '𑽙'),
('𑾰', '𑾰'),
('𒀀', '𒎙'),
('𒐀', '𒑮'),
('𒒀', '𒕃'),
('𒾐', '𒿰'),
- ('𓀀', '𓐮'),
+ ('𓀀', '𓐯'),
+ ('\u{13440}', '\u{13455}'),
('𔐀', '𔙆'),
('𖠀', '𖨸'),
('𖩀', '𖩞'),
@@ -6755,7 +6806,9 @@ pub const ID_CONTINUE: &'static [(char, char)] = &[
('𚿵', '𚿻'),
('𚿽', '𚿾'),
('𛀀', '𛄢'),
+ ('𛄲', '𛄲'),
('𛅐', '𛅒'),
+ ('𛅕', '𛅕'),
('𛅤', '𛅧'),
('𛅰', '𛋻'),
('𛰀', '𛱪'),
@@ -6809,17 +6862,21 @@ pub const ID_CONTINUE: &'static [(char, char)] = &[
('\u{1da9b}', '\u{1da9f}'),
('\u{1daa1}', '\u{1daaf}'),
('𝼀', '𝼞'),
+ ('𝼥', '𝼪'),
('\u{1e000}', '\u{1e006}'),
('\u{1e008}', '\u{1e018}'),
('\u{1e01b}', '\u{1e021}'),
('\u{1e023}', '\u{1e024}'),
('\u{1e026}', '\u{1e02a}'),
+ ('𞀰', '𞁭'),
+ ('\u{1e08f}', '\u{1e08f}'),
('𞄀', '𞄬'),
('\u{1e130}', '𞄽'),
('𞅀', '𞅉'),
('𞅎', '𞅎'),
('𞊐', '\u{1e2ae}'),
('𞋀', '𞋹'),
+ ('𞓐', '𞓹'),
('𞟠', '𞟦'),
('𞟨', '𞟫'),
('𞟭', '𞟮'),
@@ -6863,12 +6920,13 @@ pub const ID_CONTINUE: &'static [(char, char)] = &[
('𞺫', '𞺻'),
('🯰', '🯹'),
('𠀀', '𪛟'),
- ('𪜀', '𫜸'),
+ ('𪜀', '𫜹'),
('𫝀', '𫠝'),
('𫠠', '𬺡'),
('𬺰', '𮯠'),
('丽', '𪘀'),
('𰀀', '𱍊'),
+ ('𱍐', '𲎯'),
('\u{e0100}', '\u{e01ef}'),
];
@@ -7341,6 +7399,7 @@ pub const ID_START: &'static [(char, char)] = &[
('𑇜', '𑇜'),
('𑈀', '𑈑'),
('𑈓', '𑈫'),
+ ('𑈿', '𑉀'),
('𑊀', '𑊆'),
('𑊈', '𑊈'),
('𑊊', '𑊍'),
@@ -7403,12 +7462,16 @@ pub const ID_START: &'static [(char, char)] = &[
('𑵪', '𑶉'),
('𑶘', '𑶘'),
('𑻠', '𑻲'),
+ ('𑼂', '𑼂'),
+ ('𑼄', '𑼐'),
+ ('𑼒', '𑼳'),
('𑾰', '𑾰'),
('𒀀', '𒎙'),
('𒐀', '𒑮'),
('𒒀', '𒕃'),
('𒾐', '𒿰'),
- ('𓀀', '𓐮'),
+ ('𓀀', '𓐯'),
+ ('𓑁', '𓑆'),
('𔐀', '𔙆'),
('𖠀', '𖨸'),
('𖩀', '𖩞'),
@@ -7431,7 +7494,9 @@ pub const ID_START: &'static [(char, char)] = &[
('𚿵', '𚿻'),
('𚿽', '𚿾'),
('𛀀', '𛄢'),
+ ('𛄲', '𛄲'),
('𛅐', '𛅒'),
+ ('𛅕', '𛅕'),
('𛅤', '𛅧'),
('𛅰', '𛋻'),
('𛰀', '𛱪'),
@@ -7469,11 +7534,14 @@ pub const ID_START: &'static [(char, char)] = &[
('𝞪', '𝟂'),
('𝟄', '𝟋'),
('𝼀', '𝼞'),
+ ('𝼥', '𝼪'),
+ ('𞀰', '𞁭'),
('𞄀', '𞄬'),
('𞄷', '𞄽'),
('𞅎', '𞅎'),
('𞊐', '𞊭'),
('𞋀', '𞋫'),
+ ('𞓐', '𞓫'),
('𞟠', '𞟦'),
('𞟨', '𞟫'),
('𞟭', '𞟮'),
@@ -7515,12 +7583,13 @@ pub const ID_START: &'static [(char, char)] = &[
('𞺥', '𞺩'),
('𞺫', '𞺻'),
('𠀀', '𪛟'),
- ('𪜀', '𫜸'),
+ ('𪜀', '𫜹'),
('𫝀', '𫠝'),
('𫠠', '𬺡'),
('𬺰', '𮯠'),
('丽', '𪘀'),
('𰀀', '𱍊'),
+ ('𱍐', '𲎯'),
];
pub const IDEOGRAPHIC: &'static [(char, char)] = &[
@@ -7537,12 +7606,13 @@ pub const IDEOGRAPHIC: &'static [(char, char)] = &[
('𘴀', '𘴈'),
('𛅰', '𛋻'),
('𠀀', '𪛟'),
- ('𪜀', '𫜸'),
+ ('𪜀', '𫜹'),
('𫝀', '𫠝'),
('𫠠', '𬺡'),
('𬺰', '𮯠'),
('丽', '𪘀'),
('𰀀', '𱍊'),
+ ('𱍐', '𲎯'),
];
pub const JOIN_CONTROL: &'static [(char, char)] = &[('\u{200c}', '\u{200d}')];
@@ -7834,7 +7904,7 @@ pub const LOWERCASE: &'static [(char, char)] = &[
('ԯ', 'ԯ'),
('ՠ', 'ֈ'),
('ა', 'ჺ'),
- ('ჽ', 'ჿ'),
+ ('ჼ', 'ჿ'),
('ᏸ', 'ᏽ'),
('ᲀ', 'ᲈ'),
('ᴀ', 'ᶿ'),
@@ -8174,10 +8244,11 @@ pub const LOWERCASE: &'static [(char, char)] = &[
('ꟕ', 'ꟕ'),
('ꟗ', 'ꟗ'),
('ꟙ', 'ꟙ'),
+ ('ꟲ', 'ꟴ'),
('ꟶ', 'ꟶ'),
('ꟸ', 'ꟺ'),
('ꬰ', 'ꭚ'),
- ('ꭜ', 'ꭨ'),
+ ('ꭜ', 'ꭩ'),
('ꭰ', 'ꮿ'),
('ff', 'st'),
('ﬓ', 'ﬗ'),
@@ -8225,6 +8296,8 @@ pub const LOWERCASE: &'static [(char, char)] = &[
('𝟋', '𝟋'),
('𝼀', '𝼉'),
('𝼋', '𝼞'),
+ ('𝼥', '𝼪'),
+ ('𞀰', '𞁭'),
('𞤢', '𞥃'),
];
@@ -8450,7 +8523,7 @@ pub const OTHER_ALPHABETIC: &'static [(char, char)] = &[
('ெ', 'ை'),
('ொ', 'ௌ'),
('\u{bd7}', '\u{bd7}'),
- ('\u{c00}', 'ః'),
+ ('\u{c00}', '\u{c04}'),
('\u{c3e}', 'ౄ'),
('\u{c46}', '\u{c48}'),
('\u{c4a}', '\u{c4c}'),
@@ -8462,6 +8535,7 @@ pub const OTHER_ALPHABETIC: &'static [(char, char)] = &[
('ೊ', '\u{ccc}'),
('\u{cd5}', '\u{cd6}'),
('\u{ce2}', '\u{ce3}'),
+ ('ೳ', 'ೳ'),
('\u{d00}', 'ഃ'),
('\u{d3e}', '\u{d44}'),
('െ', 'ൈ'),
@@ -8480,7 +8554,7 @@ pub const OTHER_ALPHABETIC: &'static [(char, char)] = &[
('\u{eb4}', '\u{eb9}'),
('\u{ebb}', '\u{ebc}'),
('\u{ecd}', '\u{ecd}'),
- ('\u{f71}', '\u{f81}'),
+ ('\u{f71}', '\u{f83}'),
('\u{f8d}', '\u{f97}'),
('\u{f99}', '\u{fbc}'),
('ါ', '\u{1036}'),
@@ -8553,7 +8627,7 @@ pub const OTHER_ALPHABETIC: &'static [(char, char)] = &[
('𑀀', '𑀂'),
('\u{11038}', '\u{11045}'),
('\u{11073}', '\u{11074}'),
- ('𑂂', '𑂂'),
+ ('\u{11080}', '𑂂'),
('𑂰', '𑂸'),
('\u{110c2}', '\u{110c2}'),
('\u{11100}', '\u{11102}'),
@@ -8565,6 +8639,7 @@ pub const OTHER_ALPHABETIC: &'static [(char, char)] = &[
('𑈬', '\u{11234}'),
('\u{11237}', '\u{11237}'),
('\u{1123e}', '\u{1123e}'),
+ ('\u{11241}', '\u{11241}'),
('\u{112df}', '\u{112e8}'),
('\u{11300}', '𑌃'),
('\u{1133e}', '𑍄'),
@@ -8610,6 +8685,10 @@ pub const OTHER_ALPHABETIC: &'static [(char, char)] = &[
('\u{11d90}', '\u{11d91}'),
('𑶓', '𑶖'),
('\u{11ef3}', '𑻶'),
+ ('\u{11f00}', '\u{11f01}'),
+ ('𑼃', '𑼃'),
+ ('𑼴', '\u{11f3a}'),
+ ('𑼾', '\u{11f40}'),
('\u{16f4f}', '\u{16f4f}'),
('𖽑', '𖾇'),
('\u{16f8f}', '\u{16f92}'),
@@ -8620,6 +8699,7 @@ pub const OTHER_ALPHABETIC: &'static [(char, char)] = &[
('\u{1e01b}', '\u{1e021}'),
('\u{1e023}', '\u{1e024}'),
('\u{1e026}', '\u{1e02a}'),
+ ('\u{1e08f}', '\u{1e08f}'),
('\u{1e947}', '\u{1e947}'),
('🄰', '🅉'),
('🅐', '🅩'),
@@ -8682,6 +8762,7 @@ pub const OTHER_LOWERCASE: &'static [(char, char)] = &[
('ˠ', 'ˤ'),
('\u{345}', '\u{345}'),
('ͺ', 'ͺ'),
+ ('ჼ', 'ჼ'),
('ᴬ', 'ᵪ'),
('ᵸ', 'ᵸ'),
('ᶛ', 'ᶿ'),
@@ -8693,12 +8774,15 @@ pub const OTHER_LOWERCASE: &'static [(char, char)] = &[
('ⱼ', 'ⱽ'),
('ꚜ', 'ꚝ'),
('ꝰ', 'ꝰ'),
+ ('ꟲ', 'ꟴ'),
('ꟸ', 'ꟹ'),
('ꭜ', 'ꭟ'),
+ ('ꭩ', 'ꭩ'),
('𐞀', '𐞀'),
('𐞃', '𐞅'),
('𐞇', '𐞰'),
('𐞲', '𐞺'),
+ ('𞀰', '𞁭'),
];
pub const OTHER_MATH: &'static [(char, char)] = &[
@@ -8984,6 +9068,7 @@ pub const SENTENCE_TERMINAL: &'static [(char, char)] = &[
('𑪛', '𑪜'),
('𑱁', '𑱂'),
('𑻷', '𑻸'),
+ ('𑽃', '𑽄'),
('𖩮', '𖩯'),
('𖫵', '𖫵'),
('𖬷', '𖬸'),
@@ -9026,6 +9111,8 @@ pub const SOFT_DOTTED: &'static [(char, char)] = &[
('𝙞', '𝙟'),
('𝚒', '𝚓'),
('𝼚', '𝼚'),
+ ('𞁌', '𞁍'),
+ ('𞁨', '𞁨'),
];
pub const TERMINAL_PUNCTUATION: &'static [(char, char)] = &[
@@ -9128,6 +9215,7 @@ pub const TERMINAL_PUNCTUATION: &'static [(char, char)] = &[
('𑱁', '𑱃'),
('𑱱', '𑱱'),
('𑻷', '𑻸'),
+ ('𑽃', '𑽄'),
('𒑰', '𒑴'),
('𖩮', '𖩯'),
('𖫵', '𖫵'),
@@ -9149,11 +9237,12 @@ pub const UNIFIED_IDEOGRAPH: &'static [(char, char)] = &[
('﨣', '﨤'),
('﨧', '﨩'),
('𠀀', '𪛟'),
- ('𪜀', '𫜸'),
+ ('𪜀', '𫜹'),
('𫝀', '𫠝'),
('𫠠', '𬺡'),
('𬺰', '𮯠'),
('𰀀', '𱍊'),
+ ('𱍐', '𲎯'),
];
pub const UPPERCASE: &'static [(char, char)] = &[
@@ -9989,7 +10078,7 @@ pub const XID_CONTINUE: &'static [(char, char)] = &[
('ೝ', 'ೞ'),
('ೠ', '\u{ce3}'),
('೦', '೯'),
- ('ೱ', 'ೲ'),
+ ('ೱ', 'ೳ'),
('\u{d00}', 'ഌ'),
('എ', 'ഐ'),
('ഒ', '\u{d44}'),
@@ -10022,7 +10111,7 @@ pub const XID_CONTINUE: &'static [(char, char)] = &[
('ວ', 'ຽ'),
('ເ', 'ໄ'),
('ໆ', 'ໆ'),
- ('\u{ec8}', '\u{ecd}'),
+ ('\u{ec8}', '\u{ece}'),
('໐', '໙'),
('ໜ', 'ໟ'),
('ༀ', 'ༀ'),
@@ -10342,7 +10431,7 @@ pub const XID_CONTINUE: &'static [(char, char)] = &[
('𐺀', '𐺩'),
('\u{10eab}', '\u{10eac}'),
('𐺰', '𐺱'),
- ('𐼀', '𐼜'),
+ ('\u{10efd}', '𐼜'),
('𐼧', '𐼧'),
('𐼰', '\u{10f50}'),
('𐽰', '\u{10f85}'),
@@ -10365,7 +10454,7 @@ pub const XID_CONTINUE: &'static [(char, char)] = &[
('𑇜', '𑇜'),
('𑈀', '𑈑'),
('𑈓', '\u{11237}'),
- ('\u{1123e}', '\u{1123e}'),
+ ('\u{1123e}', '\u{11241}'),
('𑊀', '𑊆'),
('𑊈', '𑊈'),
('𑊊', '𑊍'),
@@ -10446,12 +10535,17 @@ pub const XID_CONTINUE: &'static [(char, char)] = &[
('𑶓', '𑶘'),
('𑶠', '𑶩'),
('𑻠', '𑻶'),
+ ('\u{11f00}', '𑼐'),
+ ('𑼒', '\u{11f3a}'),
+ ('𑼾', '\u{11f42}'),
+ ('𑽐', '𑽙'),
('𑾰', '𑾰'),
('𒀀', '𒎙'),
('𒐀', '𒑮'),
('𒒀', '𒕃'),
('𒾐', '𒿰'),
- ('𓀀', '𓐮'),
+ ('𓀀', '𓐯'),
+ ('\u{13440}', '\u{13455}'),
('𔐀', '𔙆'),
('𖠀', '𖨸'),
('𖩀', '𖩞'),
@@ -10479,7 +10573,9 @@ pub const XID_CONTINUE: &'static [(char, char)] = &[
('𚿵', '𚿻'),
('𚿽', '𚿾'),
('𛀀', '𛄢'),
+ ('𛄲', '𛄲'),
('𛅐', '𛅒'),
+ ('𛅕', '𛅕'),
('𛅤', '𛅧'),
('𛅰', '𛋻'),
('𛰀', '𛱪'),
@@ -10533,17 +10629,21 @@ pub const XID_CONTINUE: &'static [(char, char)] = &[
('\u{1da9b}', '\u{1da9f}'),
('\u{1daa1}', '\u{1daaf}'),
('𝼀', '𝼞'),
+ ('𝼥', '𝼪'),
('\u{1e000}', '\u{1e006}'),
('\u{1e008}', '\u{1e018}'),
('\u{1e01b}', '\u{1e021}'),
('\u{1e023}', '\u{1e024}'),
('\u{1e026}', '\u{1e02a}'),
+ ('𞀰', '𞁭'),
+ ('\u{1e08f}', '\u{1e08f}'),
('𞄀', '𞄬'),
('\u{1e130}', '𞄽'),
('𞅀', '𞅉'),
('𞅎', '𞅎'),
('𞊐', '\u{1e2ae}'),
('𞋀', '𞋹'),
+ ('𞓐', '𞓹'),
('𞟠', '𞟦'),
('𞟨', '𞟫'),
('𞟭', '𞟮'),
@@ -10587,12 +10687,13 @@ pub const XID_CONTINUE: &'static [(char, char)] = &[
('𞺫', '𞺻'),
('🯰', '🯹'),
('𠀀', '𪛟'),
- ('𪜀', '𫜸'),
+ ('𪜀', '𫜹'),
('𫝀', '𫠝'),
('𫠠', '𬺡'),
('𬺰', '𮯠'),
('丽', '𪘀'),
('𰀀', '𱍊'),
+ ('𱍐', '𲎯'),
('\u{e0100}', '\u{e01ef}'),
];
@@ -11072,6 +11173,7 @@ pub const XID_START: &'static [(char, char)] = &[
('𑇜', '𑇜'),
('𑈀', '𑈑'),
('𑈓', '𑈫'),
+ ('𑈿', '𑉀'),
('𑊀', '𑊆'),
('𑊈', '𑊈'),
('𑊊', '𑊍'),
@@ -11134,12 +11236,16 @@ pub const XID_START: &'static [(char, char)] = &[
('𑵪', '𑶉'),
('𑶘', '𑶘'),
('𑻠', '𑻲'),
+ ('𑼂', '𑼂'),
+ ('𑼄', '𑼐'),
+ ('𑼒', '𑼳'),
('𑾰', '𑾰'),
('𒀀', '𒎙'),
('𒐀', '𒑮'),
('𒒀', '𒕃'),
('𒾐', '𒿰'),
- ('𓀀', '𓐮'),
+ ('𓀀', '𓐯'),
+ ('𓑁', '𓑆'),
('𔐀', '𔙆'),
('𖠀', '𖨸'),
('𖩀', '𖩞'),
@@ -11162,7 +11268,9 @@ pub const XID_START: &'static [(char, char)] = &[
('𚿵', '𚿻'),
('𚿽', '𚿾'),
('𛀀', '𛄢'),
+ ('𛄲', '𛄲'),
('𛅐', '𛅒'),
+ ('𛅕', '𛅕'),
('𛅤', '𛅧'),
('𛅰', '𛋻'),
('𛰀', '𛱪'),
@@ -11200,11 +11308,14 @@ pub const XID_START: &'static [(char, char)] = &[
('𝞪', '𝟂'),
('𝟄', '𝟋'),
('𝼀', '𝼞'),
+ ('𝼥', '𝼪'),
+ ('𞀰', '𞁭'),
('𞄀', '𞄬'),
('𞄷', '𞄽'),
('𞅎', '𞅎'),
('𞊐', '𞊭'),
('𞋀', '𞋫'),
+ ('𞓐', '𞓫'),
('𞟠', '𞟦'),
('𞟨', '𞟫'),
('𞟭', '𞟮'),
@@ -11246,10 +11357,11 @@ pub const XID_START: &'static [(char, char)] = &[
('𞺥', '𞺩'),
('𞺫', '𞺻'),
('𠀀', '𪛟'),
- ('𪜀', '𫜸'),
+ ('𪜀', '𫜹'),
('𫝀', '𫠝'),
('𫠠', '𬺡'),
('𬺰', '𮯠'),
('丽', '𪘀'),
('𰀀', '𱍊'),
+ ('𱍐', '𲎯'),
];
diff --git a/vendor/regex-syntax/src/unicode_tables/property_names.rs b/vendor/regex-syntax/src/unicode_tables/property_names.rs
index 3fce1bf03..599a123ae 100644
--- a/vendor/regex-syntax/src/unicode_tables/property_names.rs
+++ b/vendor/regex-syntax/src/unicode_tables/property_names.rs
@@ -1,10 +1,10 @@
// DO NOT EDIT THIS FILE. IT WAS AUTOMATICALLY GENERATED BY:
//
-// ucd-generate property-names /tmp/ucd
+// ucd-generate property-names ucd-15.0.0
//
-// Unicode version: 14.0.0.
+// Unicode version: 15.0.0.
//
-// ucd-generate 0.2.11 is available on crates.io.
+// ucd-generate 0.2.14 is available on crates.io.
pub const PROPERTY_NAMES: &'static [(&'static str, &'static str)] = &[
("age", "Age"),
diff --git a/vendor/regex-syntax/src/unicode_tables/property_values.rs b/vendor/regex-syntax/src/unicode_tables/property_values.rs
index 08a91477b..cb2d32fb7 100644
--- a/vendor/regex-syntax/src/unicode_tables/property_values.rs
+++ b/vendor/regex-syntax/src/unicode_tables/property_values.rs
@@ -1,10 +1,10 @@
// DO NOT EDIT THIS FILE. IT WAS AUTOMATICALLY GENERATED BY:
//
-// ucd-generate property-values /tmp/ucd --include gc,script,scx,age,gcb,wb,sb
+// ucd-generate property-values ucd-15.0.0 --include gc,script,scx,age,gcb,wb,sb
//
-// Unicode version: 14.0.0.
+// Unicode version: 15.0.0.
//
-// ucd-generate 0.2.11 is available on crates.io.
+// ucd-generate 0.2.14 is available on crates.io.
pub const PROPERTY_VALUES: &'static [(
&'static str,
@@ -20,6 +20,7 @@ pub const PROPERTY_VALUES: &'static [(
("12.1", "V12_1"),
("13.0", "V13_0"),
("14.0", "V14_0"),
+ ("15.0", "V15_0"),
("2.0", "V2_0"),
("2.1", "V2_1"),
("3.0", "V3_0"),
@@ -46,6 +47,7 @@ pub const PROPERTY_VALUES: &'static [(
("v121", "V12_1"),
("v130", "V13_0"),
("v140", "V14_0"),
+ ("v150", "V15_0"),
("v20", "V2_0"),
("v21", "V2_1"),
("v30", "V3_0"),
@@ -308,6 +310,7 @@ pub const PROPERTY_VALUES: &'static [(
("kannada", "Kannada"),
("katakana", "Katakana"),
("katakanaorhiragana", "Katakana_Or_Hiragana"),
+ ("kawi", "Kawi"),
("kayahli", "Kayah_Li"),
("khar", "Kharoshthi"),
("kharoshthi", "Kharoshthi"),
@@ -372,6 +375,8 @@ pub const PROPERTY_VALUES: &'static [(
("myanmar", "Myanmar"),
("mymr", "Myanmar"),
("nabataean", "Nabataean"),
+ ("nagm", "Nag_Mundari"),
+ ("nagmundari", "Nag_Mundari"),
("nand", "Nandinagari"),
("nandinagari", "Nandinagari"),
("narb", "Old_North_Arabian"),
@@ -634,6 +639,7 @@ pub const PROPERTY_VALUES: &'static [(
("kannada", "Kannada"),
("katakana", "Katakana"),
("katakanaorhiragana", "Katakana_Or_Hiragana"),
+ ("kawi", "Kawi"),
("kayahli", "Kayah_Li"),
("khar", "Kharoshthi"),
("kharoshthi", "Kharoshthi"),
@@ -698,6 +704,8 @@ pub const PROPERTY_VALUES: &'static [(
("myanmar", "Myanmar"),
("mymr", "Myanmar"),
("nabataean", "Nabataean"),
+ ("nagm", "Nag_Mundari"),
+ ("nagmundari", "Nag_Mundari"),
("nand", "Nandinagari"),
("nandinagari", "Nandinagari"),
("narb", "Old_North_Arabian"),
diff --git a/vendor/regex-syntax/src/unicode_tables/script.rs b/vendor/regex-syntax/src/unicode_tables/script.rs
index 3327b76ae..cc5c400dd 100644
--- a/vendor/regex-syntax/src/unicode_tables/script.rs
+++ b/vendor/regex-syntax/src/unicode_tables/script.rs
@@ -1,10 +1,10 @@
// DO NOT EDIT THIS FILE. IT WAS AUTOMATICALLY GENERATED BY:
//
-// ucd-generate script /tmp/ucd --chars
+// ucd-generate script ucd-15.0.0 --chars
//
-// Unicode version: 14.0.0.
+// Unicode version: 15.0.0.
//
-// ucd-generate 0.2.11 is available on crates.io.
+// ucd-generate 0.2.14 is available on crates.io.
pub const BY_NAME: &'static [(&'static str, &'static [(char, char)])] = &[
("Adlam", ADLAM),
@@ -69,6 +69,7 @@ pub const BY_NAME: &'static [(&'static str, &'static [(char, char)])] = &[
("Kaithi", KAITHI),
("Kannada", KANNADA),
("Katakana", KATAKANA),
+ ("Kawi", KAWI),
("Kayah_Li", KAYAH_LI),
("Kharoshthi", KHAROSHTHI),
("Khitan_Small_Script", KHITAN_SMALL_SCRIPT),
@@ -103,6 +104,7 @@ pub const BY_NAME: &'static [(&'static str, &'static [(char, char)])] = &[
("Multani", MULTANI),
("Myanmar", MYANMAR),
("Nabataean", NABATAEAN),
+ ("Nag_Mundari", NAG_MUNDARI),
("Nandinagari", NANDINAGARI),
("New_Tai_Lue", NEW_TAI_LUE),
("Newa", NEWA),
@@ -202,6 +204,7 @@ pub const ARABIC: &'static [(char, char)] = &[
('ﹰ', 'ﹴ'),
('ﹶ', 'ﻼ'),
('𐹠', '𐹾'),
+ ('\u{10efd}', '\u{10eff}'),
('𞸀', '𞸃'),
('𞸅', '𞸟'),
('𞸡', '𞸢'),
@@ -410,6 +413,7 @@ pub const COMMON: &'static [(char, char)] = &[
('𝆃', '𝆄'),
('𝆌', '𝆩'),
('𝆮', '𝇪'),
+ ('𝋀', '𝋓'),
('𝋠', '𝋳'),
('𝌀', '𝍖'),
('𝍠', '𝍸'),
@@ -450,10 +454,10 @@ pub const COMMON: &'static [(char, char)] = &[
('🉐', '🉑'),
('🉠', '🉥'),
('🌀', '🛗'),
- ('🛝', '🛬'),
+ ('🛜', '🛬'),
('🛰', '🛼'),
- ('🜀', '🝳'),
- ('🞀', '🟘'),
+ ('🜀', '🝶'),
+ ('🝻', '🟙'),
('🟠', '🟫'),
('🟰', '🟰'),
('🠀', '🠋'),
@@ -464,15 +468,13 @@ pub const COMMON: &'static [(char, char)] = &[
('🢰', '🢱'),
('🤀', '🩓'),
('🩠', '🩭'),
- ('🩰', '🩴'),
- ('🩸', '🩼'),
- ('🪀', '🪆'),
- ('🪐', '🪬'),
- ('🪰', '🪺'),
- ('🫀', '🫅'),
- ('🫐', '🫙'),
- ('🫠', '🫧'),
- ('🫰', '🫶'),
+ ('🩰', '🩼'),
+ ('🪀', '🪈'),
+ ('🪐', '🪽'),
+ ('🪿', '🫅'),
+ ('🫎', '🫛'),
+ ('🫠', '🫨'),
+ ('🫰', '🫸'),
('🬀', '🮒'),
('🮔', '🯊'),
('🯰', '🯹'),
@@ -500,6 +502,8 @@ pub const CYRILLIC: &'static [(char, char)] = &[
('\u{2de0}', '\u{2dff}'),
('Ꙁ', '\u{a69f}'),
('\u{fe2e}', '\u{fe2f}'),
+ ('𞀰', '𞁭'),
+ ('\u{1e08f}', '\u{1e08f}'),
];
pub const DESERET: &'static [(char, char)] = &[('𐐀', '𐑏')];
@@ -509,6 +513,7 @@ pub const DEVANAGARI: &'static [(char, char)] = &[
('\u{955}', '\u{963}'),
('०', 'ॿ'),
('\u{a8e0}', '\u{a8ff}'),
+ ('𑬀', '𑬉'),
];
pub const DIVES_AKURU: &'static [(char, char)] = &[
@@ -528,7 +533,7 @@ pub const DUPLOYAN: &'static [(char, char)] =
&[('𛰀', '𛱪'), ('𛱰', '𛱼'), ('𛲀', '𛲈'), ('𛲐', '𛲙'), ('𛲜', '𛲟')];
pub const EGYPTIAN_HIEROGLYPHS: &'static [(char, char)] =
- &[('𓀀', '𓐮'), ('\u{13430}', '\u{13438}')];
+ &[('𓀀', '\u{13455}')];
pub const ELBASAN: &'static [(char, char)] = &[('𐔀', '𐔧')];
@@ -714,12 +719,13 @@ pub const HAN: &'static [(char, char)] = &[
('𖿢', '𖿣'),
('𖿰', '𖿱'),
('𠀀', '𪛟'),
- ('𪜀', '𫜸'),
+ ('𪜀', '𫜹'),
('𫝀', '𫠝'),
('𫠠', '𬺡'),
('𬺰', '𮯠'),
('丽', '𪘀'),
('𰀀', '𱍊'),
+ ('𱍐', '𲎯'),
];
pub const HANGUL: &'static [(char, char)] = &[
@@ -759,8 +765,14 @@ pub const HEBREW: &'static [(char, char)] = &[
('צּ', 'ﭏ'),
];
-pub const HIRAGANA: &'static [(char, char)] =
- &[('ぁ', 'ゖ'), ('ゝ', 'ゟ'), ('𛀁', '𛄟'), ('𛅐', '𛅒'), ('🈀', '🈀')];
+pub const HIRAGANA: &'static [(char, char)] = &[
+ ('ぁ', 'ゖ'),
+ ('ゝ', 'ゟ'),
+ ('𛀁', '𛄟'),
+ ('𛄲', '𛄲'),
+ ('𛅐', '𛅒'),
+ ('🈀', '🈀'),
+];
pub const IMPERIAL_ARAMAIC: &'static [(char, char)] =
&[('𐡀', '𐡕'), ('𐡗', '𐡟')];
@@ -822,7 +834,7 @@ pub const KANNADA: &'static [(char, char)] = &[
('ೝ', 'ೞ'),
('ೠ', '\u{ce3}'),
('೦', '೯'),
- ('ೱ', 'ೲ'),
+ ('ೱ', 'ೳ'),
];
pub const KATAKANA: &'static [(char, char)] = &[
@@ -838,9 +850,13 @@ pub const KATAKANA: &'static [(char, char)] = &[
('𚿽', '𚿾'),
('𛀀', '𛀀'),
('𛄠', '𛄢'),
+ ('𛅕', '𛅕'),
('𛅤', '𛅧'),
];
+pub const KAWI: &'static [(char, char)] =
+ &[('\u{11f00}', '𑼐'), ('𑼒', '\u{11f3a}'), ('𑼾', '𑽙')];
+
pub const KAYAH_LI: &'static [(char, char)] = &[('꤀', '\u{a92d}'), ('꤯', '꤯')];
pub const KHAROSHTHI: &'static [(char, char)] = &[
@@ -860,7 +876,7 @@ pub const KHITAN_SMALL_SCRIPT: &'static [(char, char)] =
pub const KHMER: &'static [(char, char)] =
&[('ក', '\u{17dd}'), ('០', '៩'), ('៰', '៹'), ('᧠', '᧿')];
-pub const KHOJKI: &'static [(char, char)] = &[('𑈀', '𑈑'), ('𑈓', '\u{1123e}')];
+pub const KHOJKI: &'static [(char, char)] = &[('𑈀', '𑈑'), ('𑈓', '\u{11241}')];
pub const KHUDAWADI: &'static [(char, char)] =
&[('𑊰', '\u{112ea}'), ('𑋰', '𑋹')];
@@ -874,7 +890,7 @@ pub const LAO: &'static [(char, char)] = &[
('ວ', 'ຽ'),
('ເ', 'ໄ'),
('ໆ', 'ໆ'),
- ('\u{ec8}', '\u{ecd}'),
+ ('\u{ec8}', '\u{ece}'),
('໐', '໙'),
('ໜ', 'ໟ'),
];
@@ -918,6 +934,7 @@ pub const LATIN: &'static [(char, char)] = &[
('𐞇', '𐞰'),
('𐞲', '𐞺'),
('𝼀', '𝼞'),
+ ('𝼥', '𝼪'),
];
pub const LEPCHA: &'static [(char, char)] =
@@ -1013,6 +1030,8 @@ pub const MYANMAR: &'static [(char, char)] =
pub const NABATAEAN: &'static [(char, char)] = &[('𐢀', '𐢞'), ('𐢧', '𐢯')];
+pub const NAG_MUNDARI: &'static [(char, char)] = &[('𞓐', '𞓹')];
+
pub const NANDINAGARI: &'static [(char, char)] =
&[('𑦠', '𑦧'), ('𑦪', '\u{119d7}'), ('\u{119da}', '𑧤')];
diff --git a/vendor/regex-syntax/src/unicode_tables/script_extension.rs b/vendor/regex-syntax/src/unicode_tables/script_extension.rs
index c970e0104..42625e21b 100644
--- a/vendor/regex-syntax/src/unicode_tables/script_extension.rs
+++ b/vendor/regex-syntax/src/unicode_tables/script_extension.rs
@@ -1,10 +1,10 @@
// DO NOT EDIT THIS FILE. IT WAS AUTOMATICALLY GENERATED BY:
//
-// ucd-generate script-extension /tmp/ucd --chars
+// ucd-generate script-extension ucd-15.0.0 --chars
//
-// Unicode version: 14.0.0.
+// Unicode version: 15.0.0.
//
-// ucd-generate 0.2.11 is available on crates.io.
+// ucd-generate 0.2.14 is available on crates.io.
pub const BY_NAME: &'static [(&'static str, &'static [(char, char)])] = &[
("Adlam", ADLAM),
@@ -69,6 +69,7 @@ pub const BY_NAME: &'static [(&'static str, &'static [(char, char)])] = &[
("Kaithi", KAITHI),
("Kannada", KANNADA),
("Katakana", KATAKANA),
+ ("Kawi", KAWI),
("Kayah_Li", KAYAH_LI),
("Kharoshthi", KHAROSHTHI),
("Khitan_Small_Script", KHITAN_SMALL_SCRIPT),
@@ -103,6 +104,7 @@ pub const BY_NAME: &'static [(&'static str, &'static [(char, char)])] = &[
("Multani", MULTANI),
("Myanmar", MYANMAR),
("Nabataean", NABATAEAN),
+ ("Nag_Mundari", NAG_MUNDARI),
("Nandinagari", NANDINAGARI),
("New_Tai_Lue", NEW_TAI_LUE),
("Newa", NEWA),
@@ -196,6 +198,7 @@ pub const ARABIC: &'static [(char, char)] = &[
('ﹶ', 'ﻼ'),
('\u{102e0}', '𐋻'),
('𐹠', '𐹾'),
+ ('\u{10efd}', '\u{10eff}'),
('𞸀', '𞸃'),
('𞸅', '𞸟'),
('𞸡', '𞸢'),
@@ -404,6 +407,7 @@ pub const COMMON: &'static [(char, char)] = &[
('𝆃', '𝆄'),
('𝆌', '𝆩'),
('𝆮', '𝇪'),
+ ('𝋀', '𝋓'),
('𝋠', '𝋳'),
('𝌀', '𝍖'),
('𝍲', '𝍸'),
@@ -443,10 +447,10 @@ pub const COMMON: &'static [(char, char)] = &[
('🉀', '🉈'),
('🉠', '🉥'),
('🌀', '🛗'),
- ('🛝', '🛬'),
+ ('🛜', '🛬'),
('🛰', '🛼'),
- ('🜀', '🝳'),
- ('🞀', '🟘'),
+ ('🜀', '🝶'),
+ ('🝻', '🟙'),
('🟠', '🟫'),
('🟰', '🟰'),
('🠀', '🠋'),
@@ -457,15 +461,13 @@ pub const COMMON: &'static [(char, char)] = &[
('🢰', '🢱'),
('🤀', '🩓'),
('🩠', '🩭'),
- ('🩰', '🩴'),
- ('🩸', '🩼'),
- ('🪀', '🪆'),
- ('🪐', '🪬'),
- ('🪰', '🪺'),
- ('🫀', '🫅'),
- ('🫐', '🫙'),
- ('🫠', '🫧'),
- ('🫰', '🫶'),
+ ('🩰', '🩼'),
+ ('🪀', '🪈'),
+ ('🪐', '🪽'),
+ ('🪿', '🫅'),
+ ('🫎', '🫛'),
+ ('🫠', '🫨'),
+ ('🫰', '🫸'),
('🬀', '🮒'),
('🮔', '🯊'),
('🯰', '🯹'),
@@ -503,6 +505,8 @@ pub const CYRILLIC: &'static [(char, char)] = &[
('⹃', '⹃'),
('Ꙁ', '\u{a69f}'),
('\u{fe2e}', '\u{fe2f}'),
+ ('𞀰', '𞁭'),
+ ('\u{1e08f}', '\u{1e08f}'),
];
pub const DESERET: &'static [(char, char)] = &[('𐐀', '𐑏')];
@@ -515,6 +519,7 @@ pub const DEVANAGARI: &'static [(char, char)] = &[
('\u{20f0}', '\u{20f0}'),
('꠰', '꠹'),
('\u{a8e0}', '\u{a8ff}'),
+ ('𑬀', '𑬉'),
];
pub const DIVES_AKURU: &'static [(char, char)] = &[
@@ -535,7 +540,7 @@ pub const DUPLOYAN: &'static [(char, char)] =
&[('𛰀', '𛱪'), ('𛱰', '𛱼'), ('𛲀', '𛲈'), ('𛲐', '𛲙'), ('𛲜', '\u{1bca3}')];
pub const EGYPTIAN_HIEROGLYPHS: &'static [(char, char)] =
- &[('𓀀', '𓐮'), ('\u{13430}', '\u{13438}')];
+ &[('𓀀', '\u{13455}')];
pub const ELBASAN: &'static [(char, char)] = &[('𐔀', '𐔧')];
@@ -760,12 +765,13 @@ pub const HAN: &'static [(char, char)] = &[
('𝍠', '𝍱'),
('🉐', '🉑'),
('𠀀', '𪛟'),
- ('𪜀', '𫜸'),
+ ('𪜀', '𫜹'),
('𫝀', '𫠝'),
('𫠠', '𬺡'),
('𬺰', '𮯠'),
('丽', '𪘀'),
('𰀀', '𱍊'),
+ ('𱍐', '𲎯'),
];
pub const HANGUL: &'static [(char, char)] = &[
@@ -834,6 +840,7 @@ pub const HIRAGANA: &'static [(char, char)] = &[
('ー', 'ー'),
('\u{ff9e}', '\u{ff9f}'),
('𛀁', '𛄟'),
+ ('𛄲', '𛄲'),
('𛅐', '𛅒'),
('🈀', '🈀'),
];
@@ -895,7 +902,7 @@ pub const KANNADA: &'static [(char, char)] = &[
('ೝ', 'ೞ'),
('ೠ', '\u{ce3}'),
('೦', '೯'),
- ('ೱ', 'ೲ'),
+ ('ೱ', 'ೳ'),
('\u{1cd0}', '\u{1cd0}'),
('\u{1cd2}', '\u{1cd2}'),
('\u{1cda}', '\u{1cda}'),
@@ -923,9 +930,13 @@ pub const KATAKANA: &'static [(char, char)] = &[
('𚿽', '𚿾'),
('𛀀', '𛀀'),
('𛄠', '𛄢'),
+ ('𛅕', '𛅕'),
('𛅤', '𛅧'),
];
+pub const KAWI: &'static [(char, char)] =
+ &[('\u{11f00}', '𑼐'), ('𑼒', '\u{11f3a}'), ('𑼾', '𑽙')];
+
pub const KAYAH_LI: &'static [(char, char)] = &[('꤀', '꤯')];
pub const KHAROSHTHI: &'static [(char, char)] = &[
@@ -946,7 +957,7 @@ pub const KHMER: &'static [(char, char)] =
&[('ក', '\u{17dd}'), ('០', '៩'), ('៰', '៹'), ('᧠', '᧿')];
pub const KHOJKI: &'static [(char, char)] =
- &[('૦', '૯'), ('꠰', '꠹'), ('𑈀', '𑈑'), ('𑈓', '\u{1123e}')];
+ &[('૦', '૯'), ('꠰', '꠹'), ('𑈀', '𑈑'), ('𑈓', '\u{11241}')];
pub const KHUDAWADI: &'static [(char, char)] =
&[('।', '॥'), ('꠰', '꠹'), ('𑊰', '\u{112ea}'), ('𑋰', '𑋹')];
@@ -960,7 +971,7 @@ pub const LAO: &'static [(char, char)] = &[
('ວ', 'ຽ'),
('ເ', 'ໄ'),
('ໆ', 'ໆ'),
- ('\u{ec8}', '\u{ecd}'),
+ ('\u{ec8}', '\u{ece}'),
('໐', '໙'),
('ໜ', 'ໟ'),
];
@@ -1012,6 +1023,7 @@ pub const LATIN: &'static [(char, char)] = &[
('𐞇', '𐞰'),
('𐞲', '𐞺'),
('𝼀', '𝼞'),
+ ('𝼥', '𝼪'),
];
pub const LEPCHA: &'static [(char, char)] =
@@ -1124,6 +1136,8 @@ pub const MYANMAR: &'static [(char, char)] =
pub const NABATAEAN: &'static [(char, char)] = &[('𐢀', '𐢞'), ('𐢧', '𐢯')];
+pub const NAG_MUNDARI: &'static [(char, char)] = &[('𞓐', '𞓹')];
+
pub const NANDINAGARI: &'static [(char, char)] = &[
('।', '॥'),
('೦', '೯'),
diff --git a/vendor/regex-syntax/src/unicode_tables/sentence_break.rs b/vendor/regex-syntax/src/unicode_tables/sentence_break.rs
index db8ad282b..24348736f 100644
--- a/vendor/regex-syntax/src/unicode_tables/sentence_break.rs
+++ b/vendor/regex-syntax/src/unicode_tables/sentence_break.rs
@@ -1,10 +1,10 @@
// DO NOT EDIT THIS FILE. IT WAS AUTOMATICALLY GENERATED BY:
//
-// ucd-generate sentence-break /tmp/ucd --chars
+// ucd-generate sentence-break ucd-15.0.0 --chars
//
-// Unicode version: 14.0.0.
+// Unicode version: 15.0.0.
//
-// ucd-generate 0.2.11 is available on crates.io.
+// ucd-generate 0.2.14 is available on crates.io.
pub const BY_NAME: &'static [(&'static str, &'static [(char, char)])] = &[
("ATerm", ATERM),
@@ -157,6 +157,7 @@ pub const EXTEND: &'static [(char, char)] = &[
('ೊ', '\u{ccd}'),
('\u{cd5}', '\u{cd6}'),
('\u{ce2}', '\u{ce3}'),
+ ('ೳ', 'ೳ'),
('\u{d00}', 'ഃ'),
('\u{d3b}', '\u{d3c}'),
('\u{d3e}', '\u{d44}'),
@@ -175,7 +176,7 @@ pub const EXTEND: &'static [(char, char)] = &[
('\u{e47}', '\u{e4e}'),
('\u{eb1}', '\u{eb1}'),
('\u{eb4}', '\u{ebc}'),
- ('\u{ec8}', '\u{ecd}'),
+ ('\u{ec8}', '\u{ece}'),
('\u{f18}', '\u{f19}'),
('\u{f35}', '\u{f35}'),
('\u{f37}', '\u{f37}'),
@@ -279,6 +280,7 @@ pub const EXTEND: &'static [(char, char)] = &[
('\u{10ae5}', '\u{10ae6}'),
('\u{10d24}', '\u{10d27}'),
('\u{10eab}', '\u{10eac}'),
+ ('\u{10efd}', '\u{10eff}'),
('\u{10f46}', '\u{10f50}'),
('\u{10f82}', '\u{10f85}'),
('𑀀', '𑀂'),
@@ -298,6 +300,7 @@ pub const EXTEND: &'static [(char, char)] = &[
('𑇎', '\u{111cf}'),
('𑈬', '\u{11237}'),
('\u{1123e}', '\u{1123e}'),
+ ('\u{11241}', '\u{11241}'),
('\u{112df}', '\u{112ea}'),
('\u{11300}', '𑌃'),
('\u{1133b}', '\u{1133c}'),
@@ -345,6 +348,12 @@ pub const EXTEND: &'static [(char, char)] = &[
('\u{11d90}', '\u{11d91}'),
('𑶓', '\u{11d97}'),
('\u{11ef3}', '𑻶'),
+ ('\u{11f00}', '\u{11f01}'),
+ ('𑼃', '𑼃'),
+ ('𑼴', '\u{11f3a}'),
+ ('𑼾', '\u{11f42}'),
+ ('\u{13440}', '\u{13440}'),
+ ('\u{13447}', '\u{13455}'),
('\u{16af0}', '\u{16af4}'),
('\u{16b30}', '\u{16b36}'),
('\u{16f4f}', '\u{16f4f}'),
@@ -372,9 +381,11 @@ pub const EXTEND: &'static [(char, char)] = &[
('\u{1e01b}', '\u{1e021}'),
('\u{1e023}', '\u{1e024}'),
('\u{1e026}', '\u{1e02a}'),
+ ('\u{1e08f}', '\u{1e08f}'),
('\u{1e130}', '\u{1e136}'),
('\u{1e2ae}', '\u{1e2ae}'),
('\u{1e2ec}', '\u{1e2ef}'),
+ ('\u{1e4ec}', '\u{1e4ef}'),
('\u{1e8d0}', '\u{1e8d6}'),
('\u{1e944}', '\u{1e94a}'),
('\u{e0020}', '\u{e007f}'),
@@ -399,7 +410,7 @@ pub const FORMAT: &'static [(char, char)] = &[
('\u{fff9}', '\u{fffb}'),
('\u{110bd}', '\u{110bd}'),
('\u{110cd}', '\u{110cd}'),
- ('\u{13430}', '\u{13438}'),
+ ('\u{13430}', '\u{1343f}'),
('\u{1bca0}', '\u{1bca3}'),
('\u{1d173}', '\u{1d17a}'),
('\u{e0001}', '\u{e0001}'),
@@ -682,6 +693,7 @@ pub const LOWER: &'static [(char, char)] = &[
('ԭ', 'ԭ'),
('ԯ', 'ԯ'),
('ՠ', 'ֈ'),
+ ('ჼ', 'ჼ'),
('ᏸ', 'ᏽ'),
('ᲀ', 'ᲈ'),
('ᴀ', 'ᶿ'),
@@ -1021,10 +1033,11 @@ pub const LOWER: &'static [(char, char)] = &[
('ꟕ', 'ꟕ'),
('ꟗ', 'ꟗ'),
('ꟙ', 'ꟙ'),
+ ('ꟲ', 'ꟴ'),
('ꟶ', 'ꟶ'),
('ꟸ', 'ꟺ'),
('ꬰ', 'ꭚ'),
- ('ꭜ', 'ꭨ'),
+ ('ꭜ', 'ꭩ'),
('ꭰ', 'ꮿ'),
('ff', 'st'),
('ﬓ', 'ﬗ'),
@@ -1072,6 +1085,8 @@ pub const LOWER: &'static [(char, char)] = &[
('𝟋', '𝟋'),
('𝼀', '𝼉'),
('𝼋', '𝼞'),
+ ('𝼥', '𝼪'),
+ ('𞀰', '𞁭'),
('𞤢', '𞥃'),
];
@@ -1131,12 +1146,14 @@ pub const NUMERIC: &'static [(char, char)] = &[
('𑱐', '𑱙'),
('𑵐', '𑵙'),
('𑶠', '𑶩'),
+ ('𑽐', '𑽙'),
('𖩠', '𖩩'),
('𖫀', '𖫉'),
('𖭐', '𖭙'),
('𝟎', '𝟿'),
('𞅀', '𞅉'),
('𞋰', '𞋹'),
+ ('𞓰', '𞓹'),
('𞥐', '𞥙'),
('🯰', '🯹'),
];
@@ -1294,7 +1311,7 @@ pub const OLETTER: &'static [(char, char)] = &[
('ၵ', 'ႁ'),
('ႎ', 'ႎ'),
('ა', 'ჺ'),
- ('ჼ', 'ቈ'),
+ ('ჽ', 'ቈ'),
('ቊ', 'ቍ'),
('ቐ', 'ቖ'),
('ቘ', 'ቘ'),
@@ -1390,7 +1407,6 @@ pub const OLETTER: &'static [(char, char)] = &[
('ꜗ', 'ꜟ'),
('ꞈ', 'ꞈ'),
('ꞏ', 'ꞏ'),
- ('ꟲ', 'ꟴ'),
('ꟷ', 'ꟷ'),
('ꟻ', 'ꠁ'),
('ꠃ', 'ꠅ'),
@@ -1428,7 +1444,6 @@ pub const OLETTER: &'static [(char, char)] = &[
('ꬑ', 'ꬖ'),
('ꬠ', 'ꬦ'),
('ꬨ', 'ꬮ'),
- ('ꭩ', 'ꭩ'),
('ꯀ', 'ꯢ'),
('가', '힣'),
('ힰ', 'ퟆ'),
@@ -1531,6 +1546,7 @@ pub const OLETTER: &'static [(char, char)] = &[
('𑇜', '𑇜'),
('𑈀', '𑈑'),
('𑈓', '𑈫'),
+ ('𑈿', '𑉀'),
('𑊀', '𑊆'),
('𑊈', '𑊈'),
('𑊊', '𑊍'),
@@ -1592,12 +1608,16 @@ pub const OLETTER: &'static [(char, char)] = &[
('𑵪', '𑶉'),
('𑶘', '𑶘'),
('𑻠', '𑻲'),
+ ('𑼂', '𑼂'),
+ ('𑼄', '𑼐'),
+ ('𑼒', '𑼳'),
('𑾰', '𑾰'),
('𒀀', '𒎙'),
('𒐀', '𒑮'),
('𒒀', '𒕃'),
('𒾐', '𒿰'),
- ('𓀀', '𓐮'),
+ ('𓀀', '𓐯'),
+ ('𓑁', '𓑆'),
('𔐀', '𔙆'),
('𖠀', '𖨸'),
('𖩀', '𖩞'),
@@ -1619,7 +1639,9 @@ pub const OLETTER: &'static [(char, char)] = &[
('𚿵', '𚿻'),
('𚿽', '𚿾'),
('𛀀', '𛄢'),
+ ('𛄲', '𛄲'),
('𛅐', '𛅒'),
+ ('𛅕', '𛅕'),
('𛅤', '𛅧'),
('𛅰', '𛋻'),
('𛰀', '𛱪'),
@@ -1632,6 +1654,7 @@ pub const OLETTER: &'static [(char, char)] = &[
('𞅎', '𞅎'),
('𞊐', '𞊭'),
('𞋀', '𞋫'),
+ ('𞓐', '𞓫'),
('𞟠', '𞟦'),
('𞟨', '𞟫'),
('𞟭', '𞟮'),
@@ -1672,12 +1695,13 @@ pub const OLETTER: &'static [(char, char)] = &[
('𞺥', '𞺩'),
('𞺫', '𞺻'),
('𠀀', '𪛟'),
- ('𪜀', '𫜸'),
+ ('𪜀', '𫜹'),
('𫝀', '𫠝'),
('𫠠', '𬺡'),
('𬺰', '𮯠'),
('丽', '𪘀'),
('𰀀', '𱍊'),
+ ('𱍐', '𲎯'),
];
pub const SCONTINUE: &'static [(char, char)] = &[
@@ -1772,6 +1796,7 @@ pub const STERM: &'static [(char, char)] = &[
('𑪛', '𑪜'),
('𑱁', '𑱂'),
('𑻷', '𑻸'),
+ ('𑽃', '𑽄'),
('𖩮', '𖩯'),
('𖫵', '𖫵'),
('𖬷', '𖬸'),
diff --git a/vendor/regex-syntax/src/unicode_tables/word_break.rs b/vendor/regex-syntax/src/unicode_tables/word_break.rs
index 19b2a1c64..c0714956f 100644
--- a/vendor/regex-syntax/src/unicode_tables/word_break.rs
+++ b/vendor/regex-syntax/src/unicode_tables/word_break.rs
@@ -1,10 +1,10 @@
// DO NOT EDIT THIS FILE. IT WAS AUTOMATICALLY GENERATED BY:
//
-// ucd-generate word-break /tmp/ucd --chars
+// ucd-generate word-break ucd-15.0.0 --chars
//
-// Unicode version: 14.0.0.
+// Unicode version: 15.0.0.
//
-// ucd-generate 0.2.11 is available on crates.io.
+// ucd-generate 0.2.14 is available on crates.io.
pub const BY_NAME: &'static [(&'static str, &'static [(char, char)])] = &[
("ALetter", ALETTER),
@@ -434,6 +434,7 @@ pub const ALETTER: &'static [(char, char)] = &[
('𑇜', '𑇜'),
('𑈀', '𑈑'),
('𑈓', '𑈫'),
+ ('𑈿', '𑉀'),
('𑊀', '𑊆'),
('𑊈', '𑊈'),
('𑊊', '𑊍'),
@@ -494,12 +495,16 @@ pub const ALETTER: &'static [(char, char)] = &[
('𑵪', '𑶉'),
('𑶘', '𑶘'),
('𑻠', '𑻲'),
+ ('𑼂', '𑼂'),
+ ('𑼄', '𑼐'),
+ ('𑼒', '𑼳'),
('𑾰', '𑾰'),
('𒀀', '𒎙'),
('𒐀', '𒑮'),
('𒒀', '𒕃'),
('𒾐', '𒿰'),
- ('𓀀', '𓐮'),
+ ('𓀀', '𓐯'),
+ ('𓑁', '𓑆'),
('𔐀', '𔙆'),
('𖠀', '𖨸'),
('𖩀', '𖩞'),
@@ -550,11 +555,14 @@ pub const ALETTER: &'static [(char, char)] = &[
('𝞪', '𝟂'),
('𝟄', '𝟋'),
('𝼀', '𝼞'),
+ ('𝼥', '𝼪'),
+ ('𞀰', '𞁭'),
('𞄀', '𞄬'),
('𞄷', '𞄽'),
('𞅎', '𞅎'),
('𞊐', '𞊭'),
('𞋀', '𞋫'),
+ ('𞓐', '𞓫'),
('𞟠', '𞟦'),
('𞟨', '𞟫'),
('𞟭', '𞟮'),
@@ -685,6 +693,7 @@ pub const EXTEND: &'static [(char, char)] = &[
('ೊ', '\u{ccd}'),
('\u{cd5}', '\u{cd6}'),
('\u{ce2}', '\u{ce3}'),
+ ('ೳ', 'ೳ'),
('\u{d00}', 'ഃ'),
('\u{d3b}', '\u{d3c}'),
('\u{d3e}', '\u{d44}'),
@@ -703,7 +712,7 @@ pub const EXTEND: &'static [(char, char)] = &[
('\u{e47}', '\u{e4e}'),
('\u{eb1}', '\u{eb1}'),
('\u{eb4}', '\u{ebc}'),
- ('\u{ec8}', '\u{ecd}'),
+ ('\u{ec8}', '\u{ece}'),
('\u{f18}', '\u{f19}'),
('\u{f35}', '\u{f35}'),
('\u{f37}', '\u{f37}'),
@@ -807,6 +816,7 @@ pub const EXTEND: &'static [(char, char)] = &[
('\u{10ae5}', '\u{10ae6}'),
('\u{10d24}', '\u{10d27}'),
('\u{10eab}', '\u{10eac}'),
+ ('\u{10efd}', '\u{10eff}'),
('\u{10f46}', '\u{10f50}'),
('\u{10f82}', '\u{10f85}'),
('𑀀', '𑀂'),
@@ -826,6 +836,7 @@ pub const EXTEND: &'static [(char, char)] = &[
('𑇎', '\u{111cf}'),
('𑈬', '\u{11237}'),
('\u{1123e}', '\u{1123e}'),
+ ('\u{11241}', '\u{11241}'),
('\u{112df}', '\u{112ea}'),
('\u{11300}', '𑌃'),
('\u{1133b}', '\u{1133c}'),
@@ -873,6 +884,12 @@ pub const EXTEND: &'static [(char, char)] = &[
('\u{11d90}', '\u{11d91}'),
('𑶓', '\u{11d97}'),
('\u{11ef3}', '𑻶'),
+ ('\u{11f00}', '\u{11f01}'),
+ ('𑼃', '𑼃'),
+ ('𑼴', '\u{11f3a}'),
+ ('𑼾', '\u{11f42}'),
+ ('\u{13440}', '\u{13440}'),
+ ('\u{13447}', '\u{13455}'),
('\u{16af0}', '\u{16af4}'),
('\u{16b30}', '\u{16b36}'),
('\u{16f4f}', '\u{16f4f}'),
@@ -900,9 +917,11 @@ pub const EXTEND: &'static [(char, char)] = &[
('\u{1e01b}', '\u{1e021}'),
('\u{1e023}', '\u{1e024}'),
('\u{1e026}', '\u{1e02a}'),
+ ('\u{1e08f}', '\u{1e08f}'),
('\u{1e130}', '\u{1e136}'),
('\u{1e2ae}', '\u{1e2ae}'),
('\u{1e2ec}', '\u{1e2ef}'),
+ ('\u{1e4ec}', '\u{1e4ef}'),
('\u{1e8d0}', '\u{1e8d6}'),
('\u{1e944}', '\u{1e94a}'),
('🏻', '🏿'),
@@ -937,7 +956,7 @@ pub const FORMAT: &'static [(char, char)] = &[
('\u{fff9}', '\u{fffb}'),
('\u{110bd}', '\u{110bd}'),
('\u{110cd}', '\u{110cd}'),
- ('\u{13430}', '\u{13438}'),
+ ('\u{13430}', '\u{1343f}'),
('\u{1bca0}', '\u{1bca3}'),
('\u{1d173}', '\u{1d17a}'),
('\u{e0001}', '\u{e0001}'),
@@ -970,6 +989,7 @@ pub const KATAKANA: &'static [(char, char)] = &[
('𚿽', '𚿾'),
('𛀀', '𛀀'),
('𛄠', '𛄢'),
+ ('𛅕', '𛅕'),
('𛅤', '𛅧'),
];
@@ -1072,12 +1092,14 @@ pub const NUMERIC: &'static [(char, char)] = &[
('𑱐', '𑱙'),
('𑵐', '𑵙'),
('𑶠', '𑶩'),
+ ('𑽐', '𑽙'),
('𖩠', '𖩩'),
('𖫀', '𖫉'),
('𖭐', '𖭙'),
('𝟎', '𝟿'),
('𞅀', '𞅉'),
('𞋰', '𞋹'),
+ ('𞓰', '𞓹'),
('𞥐', '𞥙'),
('🯰', '🯹'),
];
diff --git a/vendor/regex/.cargo-checksum.json b/vendor/regex/.cargo-checksum.json
index 463368b15..1623d8918 100644
--- a/vendor/regex/.cargo-checksum.json
+++ b/vendor/regex/.cargo-checksum.json
@@ -1 +1 @@
-{"files":{"CHANGELOG.md":"1034edbdcb6cbd83b9e9a1dc3dfcdfd6c852112ab402a1cc83734191ea7b3a29","Cargo.lock":"27cdf849031e8c491581b3a436b119e2cd0106fcd94e159fc84751d3337b1684","Cargo.toml":"4a10b9986b5b858cb6ff3a8537492f4b6f7394289b991e182bfc10ad29c3323b","HACKING.md":"17818f7a17723608f6bdbe6388ad0a913d4f96f76a16649aaf4e274b1fa0ea97","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"6485b8ed310d3f0340bf1ad1f47645069ce4069dcc6bb46c7d5c6faf41de1fdb","PERFORMANCE.md":"0d5ef3866386918dfdefb1aa9a28cfe33cb3c8ceeb79f3f8ba5b88253dd95991","README.md":"6125b1c70b9b560412529c54dc6aacdfd39cc82f69b5ad7776fa86e4cb720347","UNICODE.md":"a8a8399540eed000d19420135a527f400247a04572e44d124c786b870f518776","examples/regexdna-input.txt":"156a49710bb3e1ed4bc2bbb0af0f383b747b3d0281453cfff39c296124c598f8","examples/regexdna-output.txt":"35e85b19b70a893d752fd43e54e1e9da08bac43559191cea85b33387c24c4cc1","examples/shootout-regex-dna-bytes.rs":"fa2daedb4e0a05f64f33f4af62fbb0176db998e3676f8637ab684b725367a7b4","examples/shootout-regex-dna-cheat.rs":"1f871a6eaaf8372299fa3c762051112fa89a14235b03f734fc50ebd51ecaee72","examples/shootout-regex-dna-replace.rs":"32ffdf13ac6c4ce3fc32116a048e9cc682aa34cdb8e5beaf565a22addbdcd9ab","examples/shootout-regex-dna-single-cheat.rs":"809f75bf1e1917a53623eb6f1a3ce3b7d2ed98a6a1dbc0bd4853bec49a0c6f94","examples/shootout-regex-dna-single.rs":"1ab14f5703cd4be2e75a2e792e0ba1d322b9e4b14535d396805a4316d577f5bb","examples/shootout-regex-dna.rs":"20ea46ab63f91e3ac6a64e997eadd436a9cbc2f1bdade28e4512052f0e25bc34","rustfmt.toml":"1ca600239a27401c4a43f363cf3f38183a212affc1f31bff3ae93234bbaec228","src/backtrack.rs":"52987d80448f3d7f5d4e3545ddfc09f1f30de7602d9b5489961db4b215a377fd","src/compile.rs":"79a59be2d2db650b5a322e15e9bf1d3227944410bc780fc6089da8f4d2609b77","src/dfa.rs":"10273980d1f08aaff495e11efa240249a2b2c08a4db7c49c8d6759bc65a3b174","src/error.rs":"71c85db839514f26ee024a689061743ea94a34eb7a3291e6c2b69b45a9682d09","src/exec.rs":"21495ab6813598204a444aeea3a0121674081389fd0f07fc3443eb8858b1c677","src/expand.rs":"71220309a3bac797f55129f49e79c03e96efec894ea338c735b78695367e04ca","src/find_byte.rs":"b387247b77e3269f057c3399aefe5a815032c3af918c876f80eb4b282e4eb95e","src/freqs.rs":"255555f3d95b08a5bb3bc2f38d5a06cc100a39c0f0127fe4f50c33afa1cadc65","src/input.rs":"13f49c1bce2fadd04a45b421d374cd0f8b72bef83f7e8fda958962aaccbe799a","src/lib.rs":"de28e1ad68d4b35750667c7fbb47915e6c159ef04b148f16c3507a0a7a682f96","src/literal/imp.rs":"b7f63a861c299bea4baaab17353a420ee339c2cf76d3858c95f39342bd4463e7","src/literal/mod.rs":"533f1d68af088e9485170145e27518368e541a0337fdb44f63249ebf97310300","src/pattern.rs":"993d8b6b4bcea5e02bee3c76e17c356a5a47f8fc53c5555edfd1ebb71c0878bf","src/pikevm.rs":"6c0eaa7e878c945ac4c3c545c98f5706ad04846fc432a5086c8ee78eb030dfa7","src/pool.rs":"942e991ae31ef349bd76efd78b2a712c01166dec965bf93742977ed0870d5a10","src/prog.rs":"bebb3e50745bbc05d6c8240d972ba55a1818c51b1161dc1c21f3fe13c11d4884","src/re_builder.rs":"943344bf6e2fc90902ee04b11b741c32418ac6814b21b7982cc0a3a817713f3e","src/re_bytes.rs":"e2eddc896cea1e878716e77798a8146a67d1d8d9bcf4d053155c1caf3b8f5518","src/re_set.rs":"7921ac4a919b7a5deffe82d099a9ccaf5487aebd890dfb7a661e602c6ad3f1a9","src/re_trait.rs":"d237121b6f6b606836c72305cbcb3bbdbc54d1f6827d19a19cd0fbb4372e0145","src/re_unicode.rs":"ba4d793ff194bfd33a3735e3664c7590f5f166c452e7632a25e4558ffba14e5a","src/sparse.rs":"0da3ddb7972109869248a764dbb10254555f4bb51c375e89fb3fab9cafa47320","src/testdata/LICENSE":"58cf078acc03da3e280a938c2bd9943f554fc9b6ced89ad93ba35ca436872899","src/testdata/README":"45f869e37f798905c773bfbe0ef19a5fb7e585cbf0b7c21b5b5a784e8cec3c14","src/testdata/basic.dat":"b5b33aa89d48a61cd67cb1fbfd8f70e62c83e30b86256f9f915a5190dd38ff06","src/testdata/nullsubexpr.dat":"496ac0278eec3b6d9170faace14554569032dd3d909618364d9326156de39ecf","src/testdata/repetition.dat":"1f7959063015b284b18a4a2c1c8b416d438a2d6c4b1a362da43406b865f50e69","src/utf8.rs":"f85a356ff5d5b19e417b73ce1dd84581b21d283f6dddd195547c30af9c60bd1a","test":"0d62fdca7da12fc19ea5306b5de1d83e68d9365a029c043d524334da138b0304","tests/api.rs":"7b2a0ef75e99b9776094967bd66e9cdeaa8e11359f5f0a12bd08ef0e8d0c11fc","tests/api_str.rs":"2ae38c04e7e8fac008b609a820d0b1561ba75f39b0edc0987d6d3d06132da77f","tests/bytes.rs":"edc50f526c5fee43df89d639ef18b237e4eb91e9d533bfc43f3cbab7417d38ba","tests/consistent.rs":"d69435154c09478076497216e43081a835ac65147181a4fbddad7bff469605b2","tests/crates_regex.rs":"91a59d470e0700b4bcb3ff735d06799f3107b8ef4875a2e9904607b164be0326","tests/crazy.rs":"c0d56380dff19bdd5d7a3eb731d0e2dc564e169a1b73c81e1879b1e87f5f5f77","tests/flags.rs":"05caace2c81a99d2168037f3a38035d4dffe9f85ef3ebd7ef18b1bc6612f1ea8","tests/fowler.rs":"d78cf914de40b1e125cc92b65ccb444d462586bd07b5e05de4e4a1b5de16aa76","tests/macros.rs":"6db70c16fc90df13e6b30d2b606f8b6dd4dc976697967f6ee001b15aab6d0b19","tests/macros_bytes.rs":"a049f528a93173a1bb176cd46932dce1880679f4a1752e099be920f0e4546fd0","tests/macros_str.rs":"e585b1461374c45a2eca44ca045bc3c1fe984b2b4212e432b0c695b420e708b7","tests/misc.rs":"395f52793fa022e4cdda78675b6a6fba1a3106b4b99c834c39f7801574054bd1","tests/multiline.rs":"1b1a3326ed976437c1357f01d81833ece7ea244f38826246eab55cacd5d0862a","tests/noparse.rs":"12b6be0eff3d80779d33c6459396c74c0f6ebf4ddc9f1d33c3e747ea9e3bf268","tests/regression.rs":"1c965fefb8c7a2b1dfdab3e3fdeebaf47846555c50c8005e5537f96a52a3e252","tests/regression_fuzz.rs":"a504ec563e0d23bd2039493b7b1767fe1f831d7d668f6f4b2ecd124fc7899bcd","tests/replace.rs":"0efa042c0d531911e8ac41ce98a6b60236cbf40954102c59f9f6dea78d9d74dd","tests/searcher.rs":"ce35e47b0a276a7e8c9060c6a0b225ffba163aebc61fbc15555a6897fa0e552c","tests/set.rs":"f1e2af6baeeaed3cc99ed347ff516fe7b2eb0027ef64b891502e1486598eaf8a","tests/shortest_match.rs":"a2c94390c0d61bc24796b4c1288c924e90c8c9c6156fdebb858175177a194a42","tests/suffix_reverse.rs":"b95f89397404871227d9efe6df23b9ded147f183db81597e608f693955c668b5","tests/test_backtrack.rs":"b70c5e5f1241efd76dd9f9dd4a4df8a7b38113bd407d1f5f56867f1176177a59","tests/test_backtrack_bytes.rs":"b8a111d4b4109c8bba7e2afb650572c495a14d357fb1f743c1076fb001f704b5","tests/test_backtrack_utf8bytes.rs":"c0c279785d18beac2b4e178e7bf6c14ed235d65f00ca467cfd9c333d79487649","tests/test_crates_regex.rs":"fd9525c2eef0e2f8cb7f787bc2b721bcd0b5d84f3bca49adfe48d657a99c721a","tests/test_default.rs":"c2dfa0298896f86f1be2abf6b0c347a7ca12f95aeac92bf614dc3b86bdfff269","tests/test_default_bytes.rs":"831d3e6bfb882feb15f700e30304bd34328f888fb4c15c7169371e25024ce9a7","tests/test_nfa.rs":"f119fc43a018249c39c813d57096b0654ff69f337345f2bbd9b0e61cc9137285","tests/test_nfa_bytes.rs":"89eae3bef6a1d0bcea6b5de5be35ad72f613f2ceb8b58fe82a6c6ef2ccdc07d0","tests/test_nfa_utf8bytes.rs":"7d830b4aa401887d7cf098b62fed4cd8017ef8b61f625c7c9a2159a6b4cfeb71","tests/unicode.rs":"1af9db7f09a6b0113b8a64733e06c8415fef720b2fdef227ae398d94332287cd","tests/word_boundary.rs":"7081317ddcec1e82dd4a2090a571c6abf2ff4bbfa8cd10395e1eb3f386157fae","tests/word_boundary_ascii.rs":"cd0be5b5b485de0ba7994b42e2864585556c3d2d8bf5eab05b58931d9aaf4b87","tests/word_boundary_unicode.rs":"75dbcc35d3abc0f9795c2ea99e216dc227b0a5b58e9ca5eef767815ff0513921"},"package":"4c4eb3267174b8c6c2f654116623910a0fef09c4753f8dd83db29c48a0df988b"} \ No newline at end of file
+{"files":{"CHANGELOG.md":"47b22859157339150c957dd72be9cf87aee341ebb3711efac5930efb10436368","Cargo.lock":"3445929e595d109e2f37d349ffad3dd6cb76e7203a029cf1955838d0438d68a4","Cargo.toml":"0abdf3ce883520254d94a04dcf831fb6f0b75bfda7bcf9c8500ca9a2d1f8ff44","HACKING.md":"17818f7a17723608f6bdbe6388ad0a913d4f96f76a16649aaf4e274b1fa0ea97","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"6485b8ed310d3f0340bf1ad1f47645069ce4069dcc6bb46c7d5c6faf41de1fdb","PERFORMANCE.md":"0d5ef3866386918dfdefb1aa9a28cfe33cb3c8ceeb79f3f8ba5b88253dd95991","README.md":"f69204a0f446047d8f4d1f3d84b75f235adb5c26477f3a37b671411bc954d14c","UNICODE.md":"a8a8399540eed000d19420135a527f400247a04572e44d124c786b870f518776","examples/regexdna-input.txt":"156a49710bb3e1ed4bc2bbb0af0f383b747b3d0281453cfff39c296124c598f8","examples/regexdna-output.txt":"35e85b19b70a893d752fd43e54e1e9da08bac43559191cea85b33387c24c4cc1","examples/shootout-regex-dna-bytes.rs":"fa2daedb4e0a05f64f33f4af62fbb0176db998e3676f8637ab684b725367a7b4","examples/shootout-regex-dna-cheat.rs":"1f871a6eaaf8372299fa3c762051112fa89a14235b03f734fc50ebd51ecaee72","examples/shootout-regex-dna-replace.rs":"32ffdf13ac6c4ce3fc32116a048e9cc682aa34cdb8e5beaf565a22addbdcd9ab","examples/shootout-regex-dna-single-cheat.rs":"809f75bf1e1917a53623eb6f1a3ce3b7d2ed98a6a1dbc0bd4853bec49a0c6f94","examples/shootout-regex-dna-single.rs":"1ab14f5703cd4be2e75a2e792e0ba1d322b9e4b14535d396805a4316d577f5bb","examples/shootout-regex-dna.rs":"20ea46ab63f91e3ac6a64e997eadd436a9cbc2f1bdade28e4512052f0e25bc34","rustfmt.toml":"1ca600239a27401c4a43f363cf3f38183a212affc1f31bff3ae93234bbaec228","src/backtrack.rs":"52987d80448f3d7f5d4e3545ddfc09f1f30de7602d9b5489961db4b215a377fd","src/compile.rs":"79a59be2d2db650b5a322e15e9bf1d3227944410bc780fc6089da8f4d2609b77","src/dfa.rs":"10273980d1f08aaff495e11efa240249a2b2c08a4db7c49c8d6759bc65a3b174","src/error.rs":"71c85db839514f26ee024a689061743ea94a34eb7a3291e6c2b69b45a9682d09","src/exec.rs":"21495ab6813598204a444aeea3a0121674081389fd0f07fc3443eb8858b1c677","src/expand.rs":"71220309a3bac797f55129f49e79c03e96efec894ea338c735b78695367e04ca","src/find_byte.rs":"b387247b77e3269f057c3399aefe5a815032c3af918c876f80eb4b282e4eb95e","src/freqs.rs":"255555f3d95b08a5bb3bc2f38d5a06cc100a39c0f0127fe4f50c33afa1cadc65","src/input.rs":"13f49c1bce2fadd04a45b421d374cd0f8b72bef83f7e8fda958962aaccbe799a","src/lib.rs":"982fadba415c4c5b93f4d7d4a73a23ec88e2d96daaa03b679d14490ea0f63197","src/literal/imp.rs":"b7f63a861c299bea4baaab17353a420ee339c2cf76d3858c95f39342bd4463e7","src/literal/mod.rs":"533f1d68af088e9485170145e27518368e541a0337fdb44f63249ebf97310300","src/pattern.rs":"993d8b6b4bcea5e02bee3c76e17c356a5a47f8fc53c5555edfd1ebb71c0878bf","src/pikevm.rs":"6c0eaa7e878c945ac4c3c545c98f5706ad04846fc432a5086c8ee78eb030dfa7","src/pool.rs":"942e991ae31ef349bd76efd78b2a712c01166dec965bf93742977ed0870d5a10","src/prog.rs":"bebb3e50745bbc05d6c8240d972ba55a1818c51b1161dc1c21f3fe13c11d4884","src/re_builder.rs":"943344bf6e2fc90902ee04b11b741c32418ac6814b21b7982cc0a3a817713f3e","src/re_bytes.rs":"63ee1db1637a3764addb10e27248129acffaf78bb0a69624add4d9d6f1e97040","src/re_set.rs":"7921ac4a919b7a5deffe82d099a9ccaf5487aebd890dfb7a661e602c6ad3f1a9","src/re_trait.rs":"d237121b6f6b606836c72305cbcb3bbdbc54d1f6827d19a19cd0fbb4372e0145","src/re_unicode.rs":"4ca66d6e835df7c0f570c8cde52667ef90ba1687d5285f12fedef2e38ae925b4","src/sparse.rs":"0da3ddb7972109869248a764dbb10254555f4bb51c375e89fb3fab9cafa47320","src/testdata/LICENSE":"58cf078acc03da3e280a938c2bd9943f554fc9b6ced89ad93ba35ca436872899","src/testdata/README":"45f869e37f798905c773bfbe0ef19a5fb7e585cbf0b7c21b5b5a784e8cec3c14","src/testdata/basic.dat":"b5b33aa89d48a61cd67cb1fbfd8f70e62c83e30b86256f9f915a5190dd38ff06","src/testdata/nullsubexpr.dat":"496ac0278eec3b6d9170faace14554569032dd3d909618364d9326156de39ecf","src/testdata/repetition.dat":"1f7959063015b284b18a4a2c1c8b416d438a2d6c4b1a362da43406b865f50e69","src/utf8.rs":"f85a356ff5d5b19e417b73ce1dd84581b21d283f6dddd195547c30af9c60bd1a","test":"0d62fdca7da12fc19ea5306b5de1d83e68d9365a029c043d524334da138b0304","tests/api.rs":"7b2a0ef75e99b9776094967bd66e9cdeaa8e11359f5f0a12bd08ef0e8d0c11fc","tests/api_str.rs":"2ae38c04e7e8fac008b609a820d0b1561ba75f39b0edc0987d6d3d06132da77f","tests/bytes.rs":"edc50f526c5fee43df89d639ef18b237e4eb91e9d533bfc43f3cbab7417d38ba","tests/consistent.rs":"d69435154c09478076497216e43081a835ac65147181a4fbddad7bff469605b2","tests/crates_regex.rs":"91a59d470e0700b4bcb3ff735d06799f3107b8ef4875a2e9904607b164be0326","tests/crazy.rs":"c0d56380dff19bdd5d7a3eb731d0e2dc564e169a1b73c81e1879b1e87f5f5f77","tests/flags.rs":"05caace2c81a99d2168037f3a38035d4dffe9f85ef3ebd7ef18b1bc6612f1ea8","tests/fowler.rs":"d78cf914de40b1e125cc92b65ccb444d462586bd07b5e05de4e4a1b5de16aa76","tests/macros.rs":"6db70c16fc90df13e6b30d2b606f8b6dd4dc976697967f6ee001b15aab6d0b19","tests/macros_bytes.rs":"a049f528a93173a1bb176cd46932dce1880679f4a1752e099be920f0e4546fd0","tests/macros_str.rs":"e585b1461374c45a2eca44ca045bc3c1fe984b2b4212e432b0c695b420e708b7","tests/misc.rs":"395f52793fa022e4cdda78675b6a6fba1a3106b4b99c834c39f7801574054bd1","tests/multiline.rs":"1b1a3326ed976437c1357f01d81833ece7ea244f38826246eab55cacd5d0862a","tests/noparse.rs":"12b6be0eff3d80779d33c6459396c74c0f6ebf4ddc9f1d33c3e747ea9e3bf268","tests/regression.rs":"1c965fefb8c7a2b1dfdab3e3fdeebaf47846555c50c8005e5537f96a52a3e252","tests/regression_fuzz.rs":"a504ec563e0d23bd2039493b7b1767fe1f831d7d668f6f4b2ecd124fc7899bcd","tests/replace.rs":"66f97532e40697934e2a77605b9002dfd22c46b6033ccb755e7660d855229f41","tests/searcher.rs":"ce35e47b0a276a7e8c9060c6a0b225ffba163aebc61fbc15555a6897fa0e552c","tests/set.rs":"f1e2af6baeeaed3cc99ed347ff516fe7b2eb0027ef64b891502e1486598eaf8a","tests/shortest_match.rs":"a2c94390c0d61bc24796b4c1288c924e90c8c9c6156fdebb858175177a194a42","tests/suffix_reverse.rs":"b95f89397404871227d9efe6df23b9ded147f183db81597e608f693955c668b5","tests/test_backtrack.rs":"b70c5e5f1241efd76dd9f9dd4a4df8a7b38113bd407d1f5f56867f1176177a59","tests/test_backtrack_bytes.rs":"b8a111d4b4109c8bba7e2afb650572c495a14d357fb1f743c1076fb001f704b5","tests/test_backtrack_utf8bytes.rs":"c0c279785d18beac2b4e178e7bf6c14ed235d65f00ca467cfd9c333d79487649","tests/test_crates_regex.rs":"fd9525c2eef0e2f8cb7f787bc2b721bcd0b5d84f3bca49adfe48d657a99c721a","tests/test_default.rs":"c2dfa0298896f86f1be2abf6b0c347a7ca12f95aeac92bf614dc3b86bdfff269","tests/test_default_bytes.rs":"831d3e6bfb882feb15f700e30304bd34328f888fb4c15c7169371e25024ce9a7","tests/test_nfa.rs":"f119fc43a018249c39c813d57096b0654ff69f337345f2bbd9b0e61cc9137285","tests/test_nfa_bytes.rs":"89eae3bef6a1d0bcea6b5de5be35ad72f613f2ceb8b58fe82a6c6ef2ccdc07d0","tests/test_nfa_utf8bytes.rs":"7d830b4aa401887d7cf098b62fed4cd8017ef8b61f625c7c9a2159a6b4cfeb71","tests/unicode.rs":"1af9db7f09a6b0113b8a64733e06c8415fef720b2fdef227ae398d94332287cd","tests/word_boundary.rs":"7081317ddcec1e82dd4a2090a571c6abf2ff4bbfa8cd10395e1eb3f386157fae","tests/word_boundary_ascii.rs":"cd0be5b5b485de0ba7994b42e2864585556c3d2d8bf5eab05b58931d9aaf4b87","tests/word_boundary_unicode.rs":"75dbcc35d3abc0f9795c2ea99e216dc227b0a5b58e9ca5eef767815ff0513921"},"package":"48aaa5748ba571fb95cd2c85c09f629215d3a6ece942baa100950af03a34f733"} \ No newline at end of file
diff --git a/vendor/regex/CHANGELOG.md b/vendor/regex/CHANGELOG.md
index f2d45ed73..466f5a9c9 100644
--- a/vendor/regex/CHANGELOG.md
+++ b/vendor/regex/CHANGELOG.md
@@ -1,3 +1,29 @@
+1.7.1 (2023-01-09)
+==================
+This release was done principally to try and fix the doc.rs rendering for the
+regex crate.
+
+Performance improvements:
+
+* [PERF #930](https://github.com/rust-lang/regex/pull/930):
+ Optimize `replacen`. This also applies to `replace`, but not `replace_all`.
+
+Bug fixes:
+
+* [BUG #945](https://github.com/rust-lang/regex/issues/945):
+ Maybe fix rustdoc rendering by just bumping a new release?
+
+
+1.7.0 (2022-11-05)
+==================
+This release principally includes an upgrade to Unicode 15.
+
+New features:
+
+* [FEATURE #832](https://github.com/rust-lang/regex/issues/916):
+ Upgrade to Unicode 15.
+
+
1.6.0 (2022-07-05)
==================
This release principally includes an upgrade to Unicode 14.
diff --git a/vendor/regex/Cargo.lock b/vendor/regex/Cargo.lock
index fd2c1101d..031b3647e 100644
--- a/vendor/regex/Cargo.lock
+++ b/vendor/regex/Cargo.lock
@@ -4,9 +4,9 @@ version = 3
[[package]]
name = "aho-corasick"
-version = "0.7.18"
+version = "0.7.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1e37cfd5e7657ada45f742d6e99ca5788580b5c529dc78faf11ece6dc702656f"
+checksum = "cc936419f96fa211c1b9166887b38e5e40b19958e5b895be7c1f93adec7071ac"
dependencies = [
"memchr",
]
@@ -19,9 +19,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "getrandom"
-version = "0.2.7"
+version = "0.2.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4eb1a864a501629691edf6c15a593b7a51eebaa1e8468e9ddc623de7c9b58ec6"
+checksum = "c05aeb6a22b8f62540c194aac980f2115af067bfe15a0734d7277a768d396b31"
dependencies = [
"cfg-if",
"libc",
@@ -36,9 +36,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
[[package]]
name = "libc"
-version = "0.2.126"
+version = "0.2.139"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "349d5a591cd28b49e1d1037471617a32ddcda5731b99419008085f72d5a53836"
+checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79"
[[package]]
name = "memchr"
@@ -66,16 +66,16 @@ dependencies = [
[[package]]
name = "rand_core"
-version = "0.6.3"
+version = "0.6.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7"
+checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
dependencies = [
"getrandom",
]
[[package]]
name = "regex"
-version = "1.6.0"
+version = "1.7.1"
dependencies = [
"aho-corasick",
"lazy_static",
@@ -87,9 +87,9 @@ dependencies = [
[[package]]
name = "regex-syntax"
-version = "0.6.27"
+version = "0.6.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a3f87b73ce11b1619a3c6332f45341e0047173771e8b8b73f87bfeefb7b56244"
+checksum = "456c603be3e8d448b072f410900c09faf164fbce2d480456f50eea6e25f9c848"
[[package]]
name = "wasi"
diff --git a/vendor/regex/Cargo.toml b/vendor/regex/Cargo.toml
index abe6ac033..4f8673ea9 100644
--- a/vendor/regex/Cargo.toml
+++ b/vendor/regex/Cargo.toml
@@ -12,7 +12,7 @@
[package]
edition = "2018"
name = "regex"
-version = "1.6.0"
+version = "1.7.1"
authors = ["The Rust Project Developers"]
exclude = [
"/scripts/*",
diff --git a/vendor/regex/README.md b/vendor/regex/README.md
index 9acd5bb4a..861417da6 100644
--- a/vendor/regex/README.md
+++ b/vendor/regex/README.md
@@ -23,12 +23,8 @@ can be found on the
### Usage
-Add this to your `Cargo.toml`:
-
-```toml
-[dependencies]
-regex = "1.5"
-```
+To bring this crate into your repository, either add `regex` to your
+`Cargo.toml`, or run `cargo add regex`.
Here's a simple example that matches a date in YYYY-MM-DD format and prints the
year, month and day:
diff --git a/vendor/regex/src/lib.rs b/vendor/regex/src/lib.rs
index 3e3b0a007..6b95739c5 100644
--- a/vendor/regex/src/lib.rs
+++ b/vendor/regex/src/lib.rs
@@ -353,6 +353,9 @@ $ the end of text (or end-of-line with multi-line mode)
\B not a Unicode word boundary
</pre>
+The empty regex is valid and matches the empty string. For example, the empty
+regex matches `abc` at positions `0`, `1`, `2` and `3`.
+
## Grouping and flags
<pre class="rust">
diff --git a/vendor/regex/src/re_bytes.rs b/vendor/regex/src/re_bytes.rs
index d71969257..07e9f98ac 100644
--- a/vendor/regex/src/re_bytes.rs
+++ b/vendor/regex/src/re_bytes.rs
@@ -496,12 +496,12 @@ impl Regex {
let mut new = Vec::with_capacity(text.len());
let mut last_match = 0;
for (i, m) in it {
- if limit > 0 && i >= limit {
- break;
- }
new.extend_from_slice(&text[last_match..m.start()]);
new.extend_from_slice(&rep);
last_match = m.end();
+ if limit > 0 && i >= limit - 1 {
+ break;
+ }
}
new.extend_from_slice(&text[last_match..]);
return Cow::Owned(new);
@@ -516,14 +516,14 @@ impl Regex {
let mut new = Vec::with_capacity(text.len());
let mut last_match = 0;
for (i, cap) in it {
- if limit > 0 && i >= limit {
- break;
- }
// unwrap on 0 is OK because captures only reports matches
let m = cap.get(0).unwrap();
new.extend_from_slice(&text[last_match..m.start()]);
rep.replace_append(&cap, &mut new);
last_match = m.end();
+ if limit > 0 && i >= limit - 1 {
+ break;
+ }
}
new.extend_from_slice(&text[last_match..]);
Cow::Owned(new)
diff --git a/vendor/regex/src/re_unicode.rs b/vendor/regex/src/re_unicode.rs
index 60d81a7d9..197510ea0 100644
--- a/vendor/regex/src/re_unicode.rs
+++ b/vendor/regex/src/re_unicode.rs
@@ -554,12 +554,12 @@ impl Regex {
let mut new = String::with_capacity(text.len());
let mut last_match = 0;
for (i, m) in it {
- if limit > 0 && i >= limit {
- break;
- }
new.push_str(&text[last_match..m.start()]);
new.push_str(&rep);
last_match = m.end();
+ if limit > 0 && i >= limit - 1 {
+ break;
+ }
}
new.push_str(&text[last_match..]);
return Cow::Owned(new);
@@ -574,14 +574,14 @@ impl Regex {
let mut new = String::with_capacity(text.len());
let mut last_match = 0;
for (i, cap) in it {
- if limit > 0 && i >= limit {
- break;
- }
// unwrap on 0 is OK because captures only reports matches
let m = cap.get(0).unwrap();
new.push_str(&text[last_match..m.start()]);
rep.replace_append(&cap, &mut new);
last_match = m.end();
+ if limit > 0 && i >= limit - 1 {
+ break;
+ }
}
new.push_str(&text[last_match..]);
Cow::Owned(new)
diff --git a/vendor/regex/tests/replace.rs b/vendor/regex/tests/replace.rs
index 1dc610635..d65be072f 100644
--- a/vendor/regex/tests/replace.rs
+++ b/vendor/regex/tests/replace.rs
@@ -228,3 +228,21 @@ replace!(
bytes!(&std::borrow::Cow::<'_, [u8]>::Owned(vec![b'Z'])),
"age: Z6"
);
+
+#[test]
+fn replacen_no_captures() {
+ let re = regex!(r"[0-9]");
+ assert_eq!(
+ re.replacen(text!("age: 1234"), 2, t!("Z")),
+ text!("age: ZZ34")
+ );
+}
+
+#[test]
+fn replacen_with_captures() {
+ let re = regex!(r"([0-9])");
+ assert_eq!(
+ re.replacen(text!("age: 1234"), 2, t!("${1}Z")),
+ text!("age: 1Z2Z34")
+ );
+}
diff --git a/vendor/rls-data/.cargo-checksum.json b/vendor/rls-data/.cargo-checksum.json
deleted file mode 100644
index 523d566f5..000000000
--- a/vendor/rls-data/.cargo-checksum.json
+++ /dev/null
@@ -1 +0,0 @@
-{"files":{"Cargo.toml":"74218651d16ab1b9a87db98ae2e88999a41df06e0e6e06fff7626a37dda4ad27","README.md":"7bbd124ce5419c1a600dc4d10091f3c822a1b9a7ab51713c53f900e34126ecdf","src/config.rs":"89199590ca29eefae416f815dbd320ea85944f41fdc10df76cf6f966006593a5","src/lib.rs":"740b35604810e91a3a76363e878ef819a629abc27ce76a330daffb345ee461b8"},"package":"a58135eb039f3a3279a33779192f0ee78b56f57ae636e25cec83530e41debb99"} \ No newline at end of file
diff --git a/vendor/rls-data/README.md b/vendor/rls-data/README.md
deleted file mode 100644
index c9c2638dc..000000000
--- a/vendor/rls-data/README.md
+++ /dev/null
@@ -1,11 +0,0 @@
-# RLS-data
-
-Data structures used by the RLS and the Rust compiler.
-
-These are used by the save-analysis functionality in the compiler
-(`rustc -Zsave-analysis`). In that use, the compiler translates info in its
-internal data structures to these data structures then serialises them as JSON.
-Clients (such as the RLS) can use this crate when deserialising.
-
-The data can also be passed directly from compiler to client if the compiler is
-used as a library.
diff --git a/vendor/rls-data/src/config.rs b/vendor/rls-data/src/config.rs
deleted file mode 100644
index 0b0f8ebb8..000000000
--- a/vendor/rls-data/src/config.rs
+++ /dev/null
@@ -1,24 +0,0 @@
-#[cfg(feature = "derive")]
-use serde::{Deserialize, Serialize};
-
-/// Used to configure save-analysis.
-#[derive(Debug, Clone, Default)]
-#[cfg_attr(feature = "derive", derive(Serialize, Deserialize))]
-pub struct Config {
- /// File to output save-analysis data to.
- pub output_file: Option<String>,
- /// Include all documentation for items. (If `false`, only includes the
- /// summary (first paragraph) for each item).
- pub full_docs: bool,
- /// If true only includes data for public items in a crate (useful for
- /// library crates).
- pub pub_only: bool,
- /// If true only includes data for items reachable from the crate root.
- pub reachable_only: bool,
- /// True if and only if the analysed crate is part of the standard Rust distro.
- pub distro_crate: bool,
- /// Include signature information.
- pub signatures: bool,
- /// Include experimental borrow data.
- pub borrow_data: bool,
-}
diff --git a/vendor/rls-data/src/lib.rs b/vendor/rls-data/src/lib.rs
deleted file mode 100644
index 8352a5bbc..000000000
--- a/vendor/rls-data/src/lib.rs
+++ /dev/null
@@ -1,272 +0,0 @@
-use rls_span as span;
-
-use std::path::PathBuf;
-
-#[cfg(feature = "derive")]
-use serde::{Deserialize, Serialize};
-
-pub mod config;
-pub use config::Config;
-
-#[derive(Debug, Clone, Default)]
-#[cfg_attr(feature = "derive", derive(Serialize, Deserialize))]
-#[repr(C)]
-pub struct Analysis {
- /// The Config used to generate this analysis data.
- pub config: Config,
- pub version: Option<String>,
- pub compilation: Option<CompilationOptions>,
- pub prelude: Option<CratePreludeData>,
- pub imports: Vec<Import>,
- pub defs: Vec<Def>,
- pub impls: Vec<Impl>,
- pub refs: Vec<Ref>,
- pub macro_refs: Vec<MacroRef>,
- pub relations: Vec<Relation>,
-}
-
-impl Analysis {
- /// Returns an initialized `Analysis` struct with `config` and also
- /// `version` field to Cargo package version.
- pub fn new(config: Config) -> Analysis {
- Analysis {
- config,
- version: option_env!("CARGO_PKG_VERSION").map(ToString::to_string),
- ..Analysis::default()
- }
- }
-}
-
-// DefId::index is a newtype and so the JSON serialisation is ugly. Therefore
-// we use our own Id which is the same, but without the newtype.
-#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
-#[cfg_attr(feature = "derive", derive(Serialize, Deserialize))]
-pub struct Id {
- pub krate: u32,
- pub index: u32,
-}
-
-/// Crate name, along with its disambiguator (128-bit hash) represents a globally
-/// unique crate identifier, which should allow for differentiation between
-/// different crate targets or versions and should point to the same crate when
-/// pulled by different other, dependent crates.
-#[derive(Debug, Clone, PartialEq, Eq, Hash)]
-#[cfg_attr(feature = "derive", derive(Serialize, Deserialize))]
-pub struct GlobalCrateId {
- pub name: String,
- pub disambiguator: (u64, u64),
-}
-
-#[derive(Debug, Clone)]
-#[cfg_attr(feature = "derive", derive(Serialize, Deserialize))]
-pub struct SpanData {
- pub file_name: PathBuf,
- pub byte_start: u32,
- pub byte_end: u32,
- pub line_start: span::Row<span::OneIndexed>,
- pub line_end: span::Row<span::OneIndexed>,
- // Character offset.
- pub column_start: span::Column<span::OneIndexed>,
- pub column_end: span::Column<span::OneIndexed>,
-}
-
-#[derive(Debug, Clone)]
-#[cfg_attr(feature = "derive", derive(Serialize, Deserialize))]
-pub struct CompilationOptions {
- pub directory: PathBuf,
- pub program: String,
- pub arguments: Vec<String>,
- pub output: PathBuf,
-}
-
-#[derive(Debug, Clone)]
-#[cfg_attr(feature = "derive", derive(Serialize, Deserialize))]
-pub struct CratePreludeData {
- pub crate_id: GlobalCrateId,
- pub crate_root: String,
- pub external_crates: Vec<ExternalCrateData>,
- pub span: SpanData,
-}
-
-/// Data for external crates in the prelude of a crate.
-#[derive(Debug, Clone)]
-#[cfg_attr(feature = "derive", derive(Serialize, Deserialize))]
-pub struct ExternalCrateData {
- /// Source file where the external crate is declared.
- pub file_name: String,
- /// A crate-local crate index of an external crate. Local crate index is
- /// always 0, so these should start from 1 and range should be contiguous,
- /// e.g. from 1 to n for n external crates.
- pub num: u32,
- pub id: GlobalCrateId,
-}
-
-#[derive(Debug, Clone)]
-#[cfg_attr(feature = "derive", derive(Serialize, Deserialize))]
-pub struct Import {
- pub kind: ImportKind,
- pub ref_id: Option<Id>,
- pub span: SpanData,
- pub alias_span: Option<SpanData>,
- pub name: String,
- pub value: String,
- pub parent: Option<Id>,
-}
-
-#[derive(Debug, Clone, Copy, PartialEq, Eq)]
-#[cfg_attr(feature = "derive", derive(Serialize, Deserialize))]
-pub enum ImportKind {
- ExternCrate,
- Use,
- GlobUse,
-}
-
-#[derive(Debug, Clone)]
-#[cfg_attr(feature = "derive", derive(Serialize, Deserialize))]
-pub struct Def {
- pub kind: DefKind,
- pub id: Id,
- pub span: SpanData,
- pub name: String,
- pub qualname: String,
- pub value: String,
- pub parent: Option<Id>,
- pub children: Vec<Id>,
- pub decl_id: Option<Id>,
- pub docs: String,
- pub sig: Option<Signature>,
- pub attributes: Vec<Attribute>,
-}
-
-#[derive(Debug, Clone, Copy, PartialEq, Eq)]
-#[cfg_attr(feature = "derive", derive(Serialize, Deserialize))]
-pub enum DefKind {
- // value = variant names
- Enum,
- // value = enum name + variant name + types
- TupleVariant,
- // value = enum name + name + fields
- StructVariant,
- // value = variant name + types
- Tuple,
- // value = name + fields
- Struct,
- Union,
- // value = signature
- Trait,
- // value = type + generics
- Function,
- ForeignFunction,
- // value = type + generics
- Method,
- // No id, no value.
- Macro,
- // value = file_name
- Mod,
- // value = aliased type
- Type,
- // value = type and init expression (for all variable kinds).
- Local,
- Static,
- ForeignStatic,
- Const,
- Field,
- // no value
- ExternType,
-}
-
-#[derive(Debug, Clone)]
-#[cfg_attr(feature = "derive", derive(Serialize, Deserialize))]
-pub struct Impl {
- pub id: u32,
- pub kind: ImplKind,
- pub span: SpanData,
- pub value: String,
- pub parent: Option<Id>,
- pub children: Vec<Id>,
- pub docs: String,
- pub sig: Option<Signature>,
- pub attributes: Vec<Attribute>,
-}
-
-#[derive(Debug, Clone, PartialEq, Eq)]
-#[cfg_attr(feature = "derive", derive(Serialize, Deserialize))]
-pub enum ImplKind {
- // impl Foo { ... }
- Inherent,
- // impl Bar for Foo { ... }
- Direct,
- // impl Bar for &Foo { ... }
- Indirect,
- // impl<T: Baz> Bar for T { ... }
- // where Foo: Baz
- Blanket,
- // impl Bar for Baz { ... } or impl Baz { ... }, etc.
- // where Foo: Deref<Target = Baz>
- // Args are name and id of Baz
- Deref(String, Id),
-}
-
-#[derive(Debug, Clone)]
-#[cfg_attr(feature = "derive", derive(Serialize, Deserialize))]
-pub struct Attribute {
- pub value: String,
- pub span: SpanData,
-}
-
-#[derive(Debug, Clone)]
-#[cfg_attr(feature = "derive", derive(Serialize, Deserialize))]
-pub struct Ref {
- pub kind: RefKind,
- pub span: SpanData,
- pub ref_id: Id,
-}
-
-#[derive(Debug, Clone, Copy, PartialEq, Eq)]
-#[cfg_attr(feature = "derive", derive(Serialize, Deserialize))]
-pub enum RefKind {
- Function,
- Mod,
- Type,
- Variable,
-}
-
-#[derive(Debug, Clone)]
-#[cfg_attr(feature = "derive", derive(Serialize, Deserialize))]
-pub struct MacroRef {
- pub span: SpanData,
- pub qualname: String,
- pub callee_span: SpanData,
-}
-
-#[derive(Debug, Clone)]
-#[cfg_attr(feature = "derive", derive(Serialize, Deserialize))]
-pub struct Relation {
- pub span: SpanData,
- pub kind: RelationKind,
- pub from: Id,
- pub to: Id,
-}
-
-#[derive(Debug, Clone, Copy, PartialEq, Eq)]
-#[cfg_attr(feature = "derive", derive(Serialize, Deserialize))]
-pub enum RelationKind {
- Impl { id: u32 },
- SuperTrait,
-}
-
-#[derive(Debug, Clone)]
-#[cfg_attr(feature = "derive", derive(Serialize, Deserialize))]
-pub struct Signature {
- pub text: String,
- pub defs: Vec<SigElement>,
- pub refs: Vec<SigElement>,
-}
-
-#[derive(Debug, Clone)]
-#[cfg_attr(feature = "derive", derive(Serialize, Deserialize))]
-pub struct SigElement {
- pub id: Id,
- pub start: usize,
- pub end: usize,
-}
diff --git a/vendor/rls-span/.cargo-checksum.json b/vendor/rls-span/.cargo-checksum.json
deleted file mode 100644
index c19eba924..000000000
--- a/vendor/rls-span/.cargo-checksum.json
+++ /dev/null
@@ -1 +0,0 @@
-{"files":{"Cargo.toml":"cf0c687986a67306e3bd71081f7386b15a92b9902683d387aa44cce8e4dc61ac","src/compiler.rs":"b313cdc064a940a5abc452ec0b92833b150ff9b4da9fb68e0c9900fea1d97cfc","src/lib.rs":"cbfe46ec5c42dfeb28fca214b26e034cb01e5f5b644abad68c838af7c7209d12"},"package":"f0eea58478fc06e15f71b03236612173a1b81e9770314edecfa664375e3e4c86"} \ No newline at end of file
diff --git a/vendor/rls-span/Cargo.toml b/vendor/rls-span/Cargo.toml
deleted file mode 100644
index ad48306e7..000000000
--- a/vendor/rls-span/Cargo.toml
+++ /dev/null
@@ -1,33 +0,0 @@
-# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
-#
-# When uploading crates to the registry Cargo will automatically
-# "normalize" Cargo.toml files for maximal compatibility
-# with all versions of Cargo and also rewrite `path` dependencies
-# to registry (e.g., crates.io) dependencies
-#
-# If you believe there's an error in this file please file an
-# issue against the rust-lang/cargo repository. If you're
-# editing this file be aware that the upstream Cargo.toml
-# will likely look very different (and much more reasonable)
-
-[package]
-edition = "2018"
-name = "rls-span"
-version = "0.5.3"
-authors = ["Nick Cameron <ncameron@mozilla.com>"]
-description = "Types for identifying code spans/ranges"
-categories = ["development-tools"]
-license = "Apache-2.0/MIT"
-repository = "https://github.com/rust-lang/rls"
-[dependencies.rustc-serialize]
-version = "0.3.24"
-optional = true
-
-[dependencies.serde]
-version = "1.0"
-
-[features]
-default = []
-derive = ["serde/derive"]
-nightly = []
-serialize-rustc = ["rustc-serialize"]
diff --git a/vendor/rls-span/src/compiler.rs b/vendor/rls-span/src/compiler.rs
deleted file mode 100644
index 60151a561..000000000
--- a/vendor/rls-span/src/compiler.rs
+++ /dev/null
@@ -1,78 +0,0 @@
-///! These are the structures emitted by the compiler as part of JSON errors.
-///! The original source can be found at
-///! https://github.com/rust-lang/rust/blob/master/src/librustc_errors/json.rs
-use std::path::PathBuf;
-
-#[cfg(feature = "derive")]
-use serde::Deserialize;
-
-use crate::{Column, OneIndexed, Row, Span};
-
-#[cfg_attr(feature = "derive", derive(Deserialize))]
-#[cfg_attr(feature = "serialize-rustc", derive(RustcDecodable))]
-#[derive(Debug, Clone)]
-pub struct DiagnosticSpan {
- pub file_name: String,
- pub byte_start: u32,
- pub byte_end: u32,
- /// 1-based.
- pub line_start: usize,
- pub line_end: usize,
- /// 1-based, character offset.
- pub column_start: usize,
- pub column_end: usize,
- /// Is this a "primary" span -- meaning the point, or one of the points,
- /// where the error occurred?
- pub is_primary: bool,
- /// Source text from the start of line_start to the end of line_end.
- pub text: Vec<DiagnosticSpanLine>,
- /// Label that should be placed at this location (if any)
- pub label: Option<String>,
- /// If we are suggesting a replacement, this will contain text
- /// that should be sliced in atop this span. You may prefer to
- /// load the fully rendered version from the parent `Diagnostic`,
- /// however.
- pub suggested_replacement: Option<String>,
- /// Macro invocations that created the code at this span, if any.
- pub expansion: Option<Box<DiagnosticSpanMacroExpansion>>,
-}
-
-impl DiagnosticSpan {
- pub fn rls_span(&self) -> Span<OneIndexed> {
- Span::new(
- Row::new(self.line_start as u32),
- Row::new(self.line_end as u32),
- Column::new(self.column_start as u32),
- Column::new(self.column_end as u32),
- PathBuf::from(&self.file_name),
- )
- }
-}
-
-#[cfg_attr(feature = "derive", derive(Deserialize))]
-#[cfg_attr(feature = "serialize-rustc", derive(RustcDecodable))]
-#[derive(Debug, Clone)]
-pub struct DiagnosticSpanLine {
- pub text: String,
-
- /// 1-based, character offset in self.text.
- pub highlight_start: usize,
-
- pub highlight_end: usize,
-}
-
-#[cfg_attr(feature = "derive", derive(Deserialize))]
-#[cfg_attr(feature = "serialize-rustc", derive(RustcDecodable))]
-#[derive(Debug, Clone)]
-pub struct DiagnosticSpanMacroExpansion {
- /// span where macro was applied to generate this code; note that
- /// this may itself derive from a macro (if
- /// `span.expansion.is_some()`)
- pub span: DiagnosticSpan,
-
- /// name of macro that was applied (e.g., "foo!" or "#[derive(Eq)]")
- pub macro_decl_name: String,
-
- /// span where macro was defined (if known)
- pub def_site_span: Option<DiagnosticSpan>,
-}
diff --git a/vendor/rls-span/src/lib.rs b/vendor/rls-span/src/lib.rs
deleted file mode 100644
index 1d997f605..000000000
--- a/vendor/rls-span/src/lib.rs
+++ /dev/null
@@ -1,383 +0,0 @@
-#![cfg_attr(feature = "nightly", feature(step_trait, step_trait_ext))]
-
-use std::marker::PhantomData;
-use std::path::PathBuf;
-
-#[cfg(feature = "nightly")]
-use std::iter::Step;
-
-use serde::{Deserialize, Serialize};
-
-pub mod compiler;
-
-#[derive(Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
-pub struct Column<I: Indexed>(pub u32, PhantomData<I>);
-
-impl<I: Indexed> Column<I> {
- fn new(c: u32) -> Column<I> {
- Column(c, PhantomData)
- }
-}
-
-impl<I: Indexed> Clone for Column<I> {
- fn clone(&self) -> Column<I> {
- *self
- }
-}
-
-impl<I: Indexed> Copy for Column<I> {}
-
-impl<I: Indexed> Serialize for Column<I> {
- fn serialize<S: serde::Serializer>(
- &self,
- s: S,
- ) -> Result<<S as serde::Serializer>::Ok, <S as serde::Serializer>::Error> {
- s.serialize_u32(self.0)
- }
-}
-
-impl<'dt, I: Indexed> Deserialize<'dt> for Column<I> {
- fn deserialize<D: serde::Deserializer<'dt>>(
- d: D,
- ) -> std::result::Result<Self, <D as serde::Deserializer<'dt>>::Error> {
- <u32 as Deserialize>::deserialize(d).map(Column::new)
- }
-}
-
-#[cfg(feature = "serialize-rustc")]
-impl<I: Indexed> rustc_serialize::Decodable for Column<I> {
- fn decode<D: rustc_serialize::Decoder>(d: &mut D) -> Result<Column<I>, D::Error> {
- d.read_u32().map(Column::new)
- }
-}
-
-#[cfg(feature = "serialize-rustc")]
-impl<I: Indexed> rustc_serialize::Encodable for Column<I> {
- fn encode<S: rustc_serialize::Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
- s.emit_u32(self.0)
- }
-}
-
-impl Column<OneIndexed> {
- pub fn new_one_indexed(c: u32) -> Column<OneIndexed> {
- Column(c, PhantomData)
- }
-
- pub fn zero_indexed(self) -> Column<ZeroIndexed> {
- Column(self.0 - 1, PhantomData)
- }
-}
-
-impl Column<ZeroIndexed> {
- pub fn new_zero_indexed(c: u32) -> Column<ZeroIndexed> {
- Column(c, PhantomData)
- }
-
- pub fn one_indexed(self) -> Column<OneIndexed> {
- Column(self.0 + 1, PhantomData)
- }
-}
-
-#[cfg(feature = "nightly")]
-macro_rules! impl_step {
- ($target: ty) => {
- unsafe impl Step for $target {
- fn steps_between(start: &Self, end: &Self) -> Option<usize> {
- Step::steps_between(&start.0, &end.0)
- }
- fn forward_checked(arg: Self, count: usize) -> Option<Self> {
- Step::forward_checked(arg.0, count).map(|x| Self(x, PhantomData))
- }
- fn backward_checked(arg: Self, count: usize) -> Option<Self> {
- Step::backward_checked(arg.0, count).map(|x| Self(x, PhantomData))
- }
- }
- };
-}
-
-#[cfg(feature = "nightly")]
-impl_step!(Column<ZeroIndexed>);
-#[cfg(feature = "nightly")]
-impl_step!(Column<OneIndexed>);
-#[cfg(feature = "nightly")]
-impl_step!(Row<ZeroIndexed>);
-#[cfg(feature = "nightly")]
-impl_step!(Row<OneIndexed>);
-
-#[derive(Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
-pub struct Row<I: Indexed>(pub u32, PhantomData<I>);
-
-impl<I: Indexed> Row<I> {
- fn new(c: u32) -> Row<I> {
- Row(c, PhantomData)
- }
-}
-
-impl<I: Indexed> Clone for Row<I> {
- fn clone(&self) -> Row<I> {
- *self
- }
-}
-
-impl<I: Indexed> Copy for Row<I> {}
-
-impl<I: Indexed> serde::Serialize for Row<I> {
- fn serialize<S: serde::Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
- s.serialize_u32(self.0)
- }
-}
-
-impl<'dt, I: Indexed> serde::Deserialize<'dt> for Row<I> {
- fn deserialize<D: serde::Deserializer<'dt>>(d: D) -> std::result::Result<Self, D::Error> {
- <u32 as Deserialize>::deserialize(d).map(Row::new)
- }
-}
-
-#[cfg(feature = "serialize-rustc")]
-impl<I: Indexed> rustc_serialize::Decodable for Row<I> {
- fn decode<D: rustc_serialize::Decoder>(d: &mut D) -> Result<Row<I>, D::Error> {
- d.read_u32().map(Row::new)
- }
-}
-
-#[cfg(feature = "serialize-rustc")]
-impl<I: Indexed> rustc_serialize::Encodable for Row<I> {
- fn encode<S: rustc_serialize::Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
- s.emit_u32(self.0)
- }
-}
-
-impl Row<OneIndexed> {
- pub fn new_one_indexed(c: u32) -> Row<OneIndexed> {
- Row(c, PhantomData)
- }
-
- pub fn zero_indexed(self) -> Row<ZeroIndexed> {
- Row(self.0 - 1, PhantomData)
- }
-}
-
-impl Row<ZeroIndexed> {
- pub fn new_zero_indexed(c: u32) -> Row<ZeroIndexed> {
- Row(c, PhantomData)
- }
-
- pub fn one_indexed(self) -> Row<OneIndexed> {
- Row(self.0 + 1, PhantomData)
- }
-}
-
-#[cfg_attr(feature = "derive", derive(Serialize, Deserialize))]
-#[cfg_attr(feature = "serialize-rustc", derive(RustcDecodable, RustcEncodable))]
-#[derive(Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
-pub struct Position<I: Indexed> {
- pub row: Row<I>,
- pub col: Column<I>,
-}
-
-impl<I: Indexed> Position<I> {
- pub fn new(row: Row<I>, col: Column<I>) -> Position<I> {
- Position { row, col }
- }
-}
-
-impl<I: Indexed> Clone for Position<I> {
- fn clone(&self) -> Position<I> {
- *self
- }
-}
-
-impl<I: Indexed> Copy for Position<I> {}
-
-impl Position<OneIndexed> {
- pub fn zero_indexed(self) -> Position<ZeroIndexed> {
- Position { row: self.row.zero_indexed(), col: self.col.zero_indexed() }
- }
-}
-
-impl Position<ZeroIndexed> {
- pub fn one_indexed(self) -> Position<OneIndexed> {
- Position { row: self.row.one_indexed(), col: self.col.one_indexed() }
- }
-}
-
-#[cfg_attr(feature = "derive", derive(Serialize, Deserialize))]
-#[cfg_attr(feature = "serialize-rustc", derive(RustcDecodable, RustcEncodable))]
-#[derive(Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
-pub struct Range<I: Indexed> {
- pub row_start: Row<I>,
- pub row_end: Row<I>,
- pub col_start: Column<I>,
- pub col_end: Column<I>,
-}
-
-impl<I: Indexed> Range<I> {
- pub fn new(
- row_start: Row<I>,
- row_end: Row<I>,
- col_start: Column<I>,
- col_end: Column<I>,
- ) -> Range<I> {
- Range { row_start, row_end, col_start, col_end }
- }
-
- pub fn from_positions(start: Position<I>, end: Position<I>) -> Range<I> {
- Range { row_start: start.row, row_end: end.row, col_start: start.col, col_end: end.col }
- }
-
- pub fn start(self) -> Position<I> {
- Position { row: self.row_start, col: self.col_start }
- }
-
- pub fn end(self) -> Position<I> {
- Position { row: self.row_end, col: self.col_end }
- }
-}
-
-impl<I: Indexed> Clone for Range<I> {
- fn clone(&self) -> Range<I> {
- *self
- }
-}
-
-impl<I: Indexed> Copy for Range<I> {}
-
-impl Range<OneIndexed> {
- pub fn zero_indexed(self) -> Range<ZeroIndexed> {
- Range {
- row_start: self.row_start.zero_indexed(),
- row_end: self.row_end.zero_indexed(),
- col_start: self.col_start.zero_indexed(),
- col_end: self.col_end.zero_indexed(),
- }
- }
-}
-
-impl Range<ZeroIndexed> {
- pub fn one_indexed(self) -> Range<OneIndexed> {
- Range {
- row_start: self.row_start.one_indexed(),
- row_end: self.row_end.one_indexed(),
- col_start: self.col_start.one_indexed(),
- col_end: self.col_end.one_indexed(),
- }
- }
-}
-
-#[cfg_attr(feature = "derive", derive(Serialize, Deserialize))]
-#[cfg_attr(feature = "serialize-rustc", derive(RustcDecodable, RustcEncodable))]
-#[derive(Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
-pub struct Location<I: Indexed> {
- pub file: PathBuf,
- pub position: Position<I>,
-}
-
-impl<I: Indexed> Location<I> {
- pub fn new<F: Into<PathBuf>>(row: Row<I>, col: Column<I>, file: F) -> Location<I> {
- Location { position: Position { row, col }, file: file.into() }
- }
-
- pub fn from_position<F: Into<PathBuf>>(position: Position<I>, file: F) -> Location<I> {
- Location { position, file: file.into() }
- }
-}
-
-impl<I: Indexed> Clone for Location<I> {
- fn clone(&self) -> Location<I> {
- Location { position: self.position, file: self.file.clone() }
- }
-}
-
-impl Location<OneIndexed> {
- pub fn zero_indexed(&self) -> Location<ZeroIndexed> {
- Location { position: self.position.zero_indexed(), file: self.file.clone() }
- }
-}
-
-impl Location<ZeroIndexed> {
- pub fn one_indexed(&self) -> Location<OneIndexed> {
- Location { position: self.position.one_indexed(), file: self.file.clone() }
- }
-}
-
-#[cfg_attr(feature = "derive", derive(Serialize, Deserialize))]
-#[cfg_attr(feature = "serialize-rustc", derive(RustcDecodable, RustcEncodable))]
-#[derive(Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
-pub struct Span<I: Indexed> {
- pub file: PathBuf,
- pub range: Range<I>,
-}
-
-impl<I: Indexed> Span<I> {
- pub fn new<F: Into<PathBuf>>(
- row_start: Row<I>,
- row_end: Row<I>,
- col_start: Column<I>,
- col_end: Column<I>,
- file: F,
- ) -> Span<I> {
- Span { range: Range { row_start, row_end, col_start, col_end }, file: file.into() }
- }
-
- pub fn from_range<F: Into<PathBuf>>(range: Range<I>, file: F) -> Span<I> {
- Span { range, file: file.into() }
- }
-
- pub fn from_positions<F: Into<PathBuf>>(
- start: Position<I>,
- end: Position<I>,
- file: F,
- ) -> Span<I> {
- Span { range: Range::from_positions(start, end), file: file.into() }
- }
-}
-
-impl<I: Indexed> Clone for Span<I> {
- fn clone(&self) -> Span<I> {
- Span { range: self.range, file: self.file.clone() }
- }
-}
-
-impl Span<OneIndexed> {
- pub fn zero_indexed(&self) -> Span<ZeroIndexed> {
- Span { range: self.range.zero_indexed(), file: self.file.clone() }
- }
-}
-
-impl Span<ZeroIndexed> {
- pub fn one_indexed(&self) -> Span<OneIndexed> {
- Span { range: self.range.one_indexed(), file: self.file.clone() }
- }
-}
-
-pub trait Indexed {}
-
-#[cfg_attr(feature = "derive", derive(Serialize, Deserialize))]
-#[cfg_attr(feature = "serialize-rustc", derive(RustcDecodable, RustcEncodable))]
-#[derive(Hash, PartialEq, Eq, Debug, PartialOrd, Ord)]
-pub struct ZeroIndexed;
-impl Indexed for ZeroIndexed {}
-
-#[cfg_attr(feature = "derive", derive(Serialize, Deserialize))]
-#[cfg_attr(feature = "serialize-rustc", derive(RustcDecodable, RustcEncodable))]
-#[derive(Hash, PartialEq, Eq, Debug, PartialOrd, Ord)]
-pub struct OneIndexed;
-impl Indexed for OneIndexed {}
-
-#[cfg(feature = "nightly")]
-#[cfg(test)]
-mod test {
- use super::*;
-
- #[test]
- fn iter_row() {
- assert_eq!((Row::new_one_indexed(4)..Row::new_one_indexed(8)).count(), 4);
- assert_eq!(
- &*(Row::new_zero_indexed(0)..=Row::new_zero_indexed(8))
- .filter(|r| r.0 < 3)
- .map(|r| r.0)
- .collect::<Vec<_>>(),
- &[0, 1, 2],
- );
- }
-}
diff --git a/vendor/rustc-ap-rustc_lexer/.cargo-checksum.json b/vendor/rustc-ap-rustc_lexer/.cargo-checksum.json
index b211139e8..3df6fdfb5 100644
--- a/vendor/rustc-ap-rustc_lexer/.cargo-checksum.json
+++ b/vendor/rustc-ap-rustc_lexer/.cargo-checksum.json
@@ -1 +1 @@
-{"files":{"Cargo.toml":"dc430a17d2d107587d485d97cd5f15bc1c5cb55d145435d4d7267223c1fd8d33","src/cursor.rs":"1b58d5746e41eb7c58212885260543a359a6aa825b3bc47d8cb9733a75e90158","src/lib.rs":"41ffa950ae7a03f68a0ef610e61faeadd81f7b3d90da0cc999ad18bf0769dd38","src/tests.rs":"0a8e21db0da8e336b41c145652a4a41d235e1c36d5284a10cf837dba2b471c4d","src/unescape.rs":"913036ef4cecc7735de8c2f576dda584b0ba976ca71723fc1590447676b60ac8","src/unescape/tests.rs":"5f73f809bbb287b116c7db1416f01bf54ccdb78882f5f22a1da42f2f48f63af3"},"package":"f950742ef8a203aa7661aad3ab880438ddeb7f95d4b837c30d65db1a2c5df68e"} \ No newline at end of file
+{"files":{"Cargo.toml":"7f25776fe1328d925567faf1db5afd37b8e4cd135492e0b5aece88059202ba81","src/cursor.rs":"1b58d5746e41eb7c58212885260543a359a6aa825b3bc47d8cb9733a75e90158","src/lib.rs":"630b5b8e8c1527912a854903ff8e4ddc10789904698db61f837cef7fc21f2181","src/tests.rs":"0a8e21db0da8e336b41c145652a4a41d235e1c36d5284a10cf837dba2b471c4d","src/unescape.rs":"913036ef4cecc7735de8c2f576dda584b0ba976ca71723fc1590447676b60ac8","src/unescape/tests.rs":"5f73f809bbb287b116c7db1416f01bf54ccdb78882f5f22a1da42f2f48f63af3"},"package":"8f40f26e7abdcd3b982f36c09a634cc6187988fbf6ec466c91f8d30a12ac0237"} \ No newline at end of file
diff --git a/vendor/rustc-ap-rustc_lexer/Cargo.toml b/vendor/rustc-ap-rustc_lexer/Cargo.toml
index f11e5ce15..fd16ad110 100644
--- a/vendor/rustc-ap-rustc_lexer/Cargo.toml
+++ b/vendor/rustc-ap-rustc_lexer/Cargo.toml
@@ -13,9 +13,9 @@
[package]
edition = "2018"
name = "rustc-ap-rustc_lexer"
-version = "725.0.0"
+version = "727.0.0"
authors = ["The Rust Project Developers"]
-description = "Automatically published version of the package `rustc_lexer` in the rust-lang/rust repository from commit c38111c4fb9c22a36f9a9195d1884052bb670af2 The publishing script for this crate lives at: https://github.com/alexcrichton/rustc-auto-publish\n "
+description = "Automatically published version of the package `rustc_lexer` in the rust-lang/rust repository from commit 9a27044f42ace9eb652781b53f598e25d4e7e918 The publishing script for this crate lives at: https://github.com/alexcrichton/rustc-auto-publish\n "
license = "MIT / Apache-2.0"
repository = "https://github.com/rust-lang/rust"
diff --git a/vendor/rustc-ap-rustc_lexer/src/lib.rs b/vendor/rustc-ap-rustc_lexer/src/lib.rs
index b9781581f..4cb2a6ca5 100644
--- a/vendor/rustc-ap-rustc_lexer/src/lib.rs
+++ b/vendor/rustc-ap-rustc_lexer/src/lib.rs
@@ -66,6 +66,13 @@ pub enum TokenKind {
Ident,
/// "r#ident"
RawIdent,
+ /// An unknown prefix like `foo#`, `foo'`, `foo"`. Note that only the
+ /// prefix (`foo`) is included in the token, not the separator (which is
+ /// lexed as its own distinct token). In Rust 2021 and later, reserved
+ /// prefixes are reported as errors; in earlier editions, they result in a
+ /// (allowed by default) lint, and are treated as regular identifier
+ /// tokens.
+ UnknownPrefix,
/// "12_u8", "1.0e-40", "b"123"". See `LiteralKind` for more details.
Literal { kind: LiteralKind, suffix_start: usize },
/// "'a"
@@ -323,7 +330,7 @@ impl Cursor<'_> {
let kind = RawStr { n_hashes, err };
Literal { kind, suffix_start }
}
- _ => self.ident(),
+ _ => self.ident_or_unknown_prefix(),
},
// Byte literal, byte string literal, raw byte string literal or identifier.
@@ -358,12 +365,12 @@ impl Cursor<'_> {
let kind = RawByteStr { n_hashes, err };
Literal { kind, suffix_start }
}
- _ => self.ident(),
+ _ => self.ident_or_unknown_prefix(),
},
// Identifier (this should be checked after other variant that can
// start as identifier).
- c if is_id_start(c) => self.ident(),
+ c if is_id_start(c) => self.ident_or_unknown_prefix(),
// Numeric literal.
c @ '0'..='9' => {
@@ -487,11 +494,16 @@ impl Cursor<'_> {
RawIdent
}
- fn ident(&mut self) -> TokenKind {
+ fn ident_or_unknown_prefix(&mut self) -> TokenKind {
debug_assert!(is_id_start(self.prev()));
// Start is already eaten, eat the rest of identifier.
self.eat_while(is_id_continue);
- Ident
+ // Known prefixes must have been handled earlier. So if
+ // we see a prefix here, it is definitely a unknown prefix.
+ match self.first() {
+ '#' | '"' | '\'' => UnknownPrefix,
+ _ => Ident,
+ }
}
fn number(&mut self, first_digit: char) -> LiteralKind {
diff --git a/vendor/ryu/.cargo-checksum.json b/vendor/ryu/.cargo-checksum.json
index f0feb1916..a2dcae08d 100644
--- a/vendor/ryu/.cargo-checksum.json
+++ b/vendor/ryu/.cargo-checksum.json
@@ -1 +1 @@
-{"files":{"Cargo.lock":"2717f9b8d4230094a8c92ce37bb7bf56f5f869da3904b5b8f177b0c44f32389f","Cargo.toml":"a022feb14dc0f3979da30277ecce957cfefe78e6638d27882bf4cd1f8106e15f","LICENSE-APACHE":"c71d239df91726fc519c6eb72d318ec65820627232b2f796219e87dcf35d0ab4","LICENSE-BOOST":"c9bff75738922193e67fa726fa225535870d2aa1059f91452c411736284ad566","README.md":"6f91d4158af93dccaf61aab14ba9db78cce0413a70c8d7e63bf2823c0262be28","benches/bench.rs":"703521c8cb9c6959ee305776a9971d24754b6fff5c1737741be04f956a3692e8","examples/upstream_benchmark.rs":"f702d3598a8fac59134a8058ebf74ba90163b1f23ebbd6c5978a7bd8a888d357","src/buffer/mod.rs":"c5adf9aa037271916e78c61c9fd98e3230a0fed1fca15694d4d57166fa697125","src/common.rs":"cae347e97fc30c50a964f80425e8c3e69ece2b8ab81f9b81b9baa7fcec64a001","src/d2s.rs":"83f821f17fd8d2cf72bcc47cc8c603ab24f2377db6cd0f08638031716f8dc17c","src/d2s_full_table.rs":"9b0186acbc6d65dc55c17e16125be707a2bfb920d22b35d33234b4cc38566a36","src/d2s_intrinsics.rs":"658d00a64ce2aca7f0780a1acc5939167e4a66d836b51c46de1047820992fec1","src/d2s_small_table.rs":"7b25cfbf0793d0662d83f5d92a9f880295652db9979b5acf702b313359996508","src/digit_table.rs":"02351ca54cb8cb3679f635115dd094f32fd91750e9f66103c1ee9ec3db507072","src/f2s.rs":"55320c2301680d8be3a908620cccd9d103b0cd3ad7a7d3378589e274ffc2587b","src/f2s_intrinsics.rs":"97bab98093838e30c60f5135f54f5ccb039ff7d9f35553ac8e74437743ca47e2","src/lib.rs":"b4d5d3d390511b01f81df6321aad564d457cf390e6e2276ad3974564a54527ec","src/parse.rs":"7f8aa7e007caf5dcb03abdc4238157724bb742d0823a3b8a01646fa1f1129154","src/pretty/exponent.rs":"6c9aa1c707c567ae338647056e37557a94e5120781ee9f6f64e9c7071ffb50d0","src/pretty/mantissa.rs":"a3eb97fd8928bfabef4523501f204fc7254e948318d727eff8327b9b06e76242","src/pretty/mod.rs":"169c57b14075295b07fa408963c300cefa94fd0b17e098d524ef46535bd84019","src/s2d.rs":"2f572603eedaa9efbe864105999a1ceac8aa4ff4e1d2fbd96127692460194d16","src/s2f.rs":"411b1e5acdeb3d7a29f4fddfdf9ce77e6395475d1c053a05e31482d49e6bf1ee","tests/common_test.rs":"275184cf366f80c11e5f33c2d53065a073e20d81bf71ca70478c89e47fb8da36","tests/d2s_table_test.rs":"54b3a7d40aa9bec03e9dc555d15fb4512ee16a16398b3098a97819fab50c81f3","tests/d2s_test.rs":"39014777edd6e3231095186174c4ef341fd9c12ecc5510765761713b6cac3bb4","tests/exhaustive.rs":"f475ed9008a2cd86ce95abb577a4b01e9fed23fc16f7e217ccffb3b834005fa0","tests/f2s_test.rs":"10940f005e73a42bb106ff498e7a6cc4665d04d82829fef8dc7d0eb36f574e6f","tests/macros/mod.rs":"8e90a674b3960f9516cb38f4eea0e0981ff902c3b33572ebdb6c5528d3ffa72c","tests/s2d_test.rs":"75c3a1044881718db65e05f25c9f6e1d005392dddb2e8dafb799668bb6a9a5c3","tests/s2f_test.rs":"1ec06646cb65229bfe866ec913901a0d8d736668f30b812fc4b00136a43f5142"},"package":"4501abdff3ae82a1c1b477a17252eb69cee9e66eb915c1abaa4f44d873df9f09"} \ No newline at end of file
+{"files":{"Cargo.lock":"aa8c35b390605eedd4a9c43615ca68a001cfdc5055ac2f09bec221a8f38c67ab","Cargo.toml":"490b9d1a775582ca920bdf5a9b2aa278425e72d240b0464c076b6374ad117137","LICENSE-APACHE":"c71d239df91726fc519c6eb72d318ec65820627232b2f796219e87dcf35d0ab4","LICENSE-BOOST":"c9bff75738922193e67fa726fa225535870d2aa1059f91452c411736284ad566","README.md":"df6a7a024b604ad98dd7603ad261150ef73a94a9de691bd5d2510e12a200021a","benches/bench.rs":"703521c8cb9c6959ee305776a9971d24754b6fff5c1737741be04f956a3692e8","examples/upstream_benchmark.rs":"f702d3598a8fac59134a8058ebf74ba90163b1f23ebbd6c5978a7bd8a888d357","src/buffer/mod.rs":"c5adf9aa037271916e78c61c9fd98e3230a0fed1fca15694d4d57166fa697125","src/common.rs":"cae347e97fc30c50a964f80425e8c3e69ece2b8ab81f9b81b9baa7fcec64a001","src/d2s.rs":"83f821f17fd8d2cf72bcc47cc8c603ab24f2377db6cd0f08638031716f8dc17c","src/d2s_full_table.rs":"9b0186acbc6d65dc55c17e16125be707a2bfb920d22b35d33234b4cc38566a36","src/d2s_intrinsics.rs":"658d00a64ce2aca7f0780a1acc5939167e4a66d836b51c46de1047820992fec1","src/d2s_small_table.rs":"7b25cfbf0793d0662d83f5d92a9f880295652db9979b5acf702b313359996508","src/digit_table.rs":"02351ca54cb8cb3679f635115dd094f32fd91750e9f66103c1ee9ec3db507072","src/f2s.rs":"55320c2301680d8be3a908620cccd9d103b0cd3ad7a7d3378589e274ffc2587b","src/f2s_intrinsics.rs":"97bab98093838e30c60f5135f54f5ccb039ff7d9f35553ac8e74437743ca47e2","src/lib.rs":"fb2239e04c0524db49077adbd6128b622f42239c9b9362289861487c6a530f9a","src/parse.rs":"7f8aa7e007caf5dcb03abdc4238157724bb742d0823a3b8a01646fa1f1129154","src/pretty/exponent.rs":"6c9aa1c707c567ae338647056e37557a94e5120781ee9f6f64e9c7071ffb50d0","src/pretty/mantissa.rs":"5e8d0a6bfdfd04e599a9fc8aefd638e3288651279e870e7cd44820717c3b6438","src/pretty/mod.rs":"731798246d414ca54df739c212f1cb8e05991a0472a7a1c28771e24d7a1cf09b","src/s2d.rs":"2f572603eedaa9efbe864105999a1ceac8aa4ff4e1d2fbd96127692460194d16","src/s2f.rs":"6ae7430fba61f59aa6010d446f5c1043974b6fadb8e4c75ce2ad56f73ee48f4a","tests/common_test.rs":"275184cf366f80c11e5f33c2d53065a073e20d81bf71ca70478c89e47fb8da36","tests/d2s_table_test.rs":"54b3a7d40aa9bec03e9dc555d15fb4512ee16a16398b3098a97819fab50c81f3","tests/d2s_test.rs":"39014777edd6e3231095186174c4ef341fd9c12ecc5510765761713b6cac3bb4","tests/exhaustive.rs":"f475ed9008a2cd86ce95abb577a4b01e9fed23fc16f7e217ccffb3b834005fa0","tests/f2s_test.rs":"10940f005e73a42bb106ff498e7a6cc4665d04d82829fef8dc7d0eb36f574e6f","tests/macros/mod.rs":"8e90a674b3960f9516cb38f4eea0e0981ff902c3b33572ebdb6c5528d3ffa72c","tests/s2d_test.rs":"75c3a1044881718db65e05f25c9f6e1d005392dddb2e8dafb799668bb6a9a5c3","tests/s2f_test.rs":"1ec06646cb65229bfe866ec913901a0d8d736668f30b812fc4b00136a43f5142"},"package":"7b4b9743ed687d4b4bcedf9ff5eaa7398495ae14e61cba0a295704edbc7decde"} \ No newline at end of file
diff --git a/vendor/ryu/Cargo.lock b/vendor/ryu/Cargo.lock
index 0b0ca716a..34a891d55 100644
--- a/vendor/ryu/Cargo.lock
+++ b/vendor/ryu/Cargo.lock
@@ -30,15 +30,15 @@ dependencies = [
[[package]]
name = "libc"
-version = "0.2.126"
+version = "0.2.134"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "349d5a591cd28b49e1d1037471617a32ddcda5731b99419008085f72d5a53836"
+checksum = "329c933548736bc49fd575ee68c89e8be4d260064184389a5b77517cddd99ffb"
[[package]]
name = "no-panic"
-version = "0.1.15"
+version = "0.1.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3b884e0f4a7a80970539a7757902675ce503d98615f5b564564b4bd0236f7f36"
+checksum = "12f10d4b6dcf2138f0fc171f4cc8f49517cc71ac57e29aa061c61aa57ec2dffc"
dependencies = [
"proc-macro2",
"quote",
@@ -63,18 +63,18 @@ checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872"
[[package]]
name = "proc-macro2"
-version = "1.0.42"
+version = "1.0.46"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c278e965f1d8cf32d6e0e96de3d3e79712178ae67986d9cf9151f51e95aac89b"
+checksum = "94e2ef8dbfc347b10c094890f778ee2e36ca9bb4262e86dc99cd217e35f3470b"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
-version = "1.0.20"
+version = "1.0.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3bcdf212e9776fbcb2d23ab029360416bb1706b1aea2d1a5ba002727cbcab804"
+checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179"
dependencies = [
"proc-macro2",
]
@@ -102,9 +102,9 @@ dependencies = [
[[package]]
name = "rand_core"
-version = "0.6.3"
+version = "0.6.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7"
+checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
dependencies = [
"getrandom",
]
@@ -120,7 +120,7 @@ dependencies = [
[[package]]
name = "ryu"
-version = "1.0.11"
+version = "1.0.12"
dependencies = [
"no-panic",
"num_cpus",
@@ -130,9 +130,9 @@ dependencies = [
[[package]]
name = "syn"
-version = "1.0.98"
+version = "1.0.102"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c50aef8a904de4c23c788f104b7dddc7d6f79c647c7c8ce4cc8f73eb0ca773dd"
+checksum = "3fcd952facd492f9be3ef0d0b7032a6e442ee9b361d4acc2b1d0c4aaa5f613a1"
dependencies = [
"proc-macro2",
"quote",
@@ -141,9 +141,9 @@ dependencies = [
[[package]]
name = "unicode-ident"
-version = "1.0.2"
+version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "15c61ba63f9235225a22310255a29b806b907c9b8c964bcbd0a2c70f3f2deea7"
+checksum = "dcc811dc4066ac62f84f11307873c4850cb653bfa9b1719cee2bd2204a4bc5dd"
[[package]]
name = "wasi"
diff --git a/vendor/ryu/Cargo.toml b/vendor/ryu/Cargo.toml
index 77181c0f6..0f37ef82b 100644
--- a/vendor/ryu/Cargo.toml
+++ b/vendor/ryu/Cargo.toml
@@ -13,7 +13,7 @@
edition = "2018"
rust-version = "1.36"
name = "ryu"
-version = "1.0.11"
+version = "1.0.12"
authors = ["David Tolnay <dtolnay@gmail.com>"]
exclude = [
"performance.png",
diff --git a/vendor/ryu/README.md b/vendor/ryu/README.md
index 1e2248978..0abd71fe9 100644
--- a/vendor/ryu/README.md
+++ b/vendor/ryu/README.md
@@ -3,7 +3,7 @@
[<img alt="github" src="https://img.shields.io/badge/github-dtolnay/ryu-8da0cb?style=for-the-badge&labelColor=555555&logo=github" height="20">](https://github.com/dtolnay/ryu)
[<img alt="crates.io" src="https://img.shields.io/crates/v/ryu.svg?style=for-the-badge&color=fc8d62&logo=rust" height="20">](https://crates.io/crates/ryu)
[<img alt="docs.rs" src="https://img.shields.io/badge/docs.rs-ryu-66c2a5?style=for-the-badge&labelColor=555555&logo=docs.rs" height="20">](https://docs.rs/ryu)
-[<img alt="build status" src="https://img.shields.io/github/workflow/status/dtolnay/ryu/CI/master?style=for-the-badge" height="20">](https://github.com/dtolnay/ryu/actions?query=branch%3Amaster)
+[<img alt="build status" src="https://img.shields.io/github/actions/workflow/status/dtolnay/ryu/ci.yml?branch=master&style=for-the-badge" height="20">](https://github.com/dtolnay/ryu/actions?query=branch%3Amaster)
Pure Rust implementation of Ryū, an algorithm to quickly convert floating point
numbers to decimal strings.
diff --git a/vendor/ryu/src/lib.rs b/vendor/ryu/src/lib.rs
index f69638ef1..59e0dcd0c 100644
--- a/vendor/ryu/src/lib.rs
+++ b/vendor/ryu/src/lib.rs
@@ -81,7 +81,7 @@
//! notation.
#![no_std]
-#![doc(html_root_url = "https://docs.rs/ryu/1.0.11")]
+#![doc(html_root_url = "https://docs.rs/ryu/1.0.12")]
#![allow(
clippy::cast_lossless,
clippy::cast_possible_truncation,
diff --git a/vendor/ryu/src/pretty/mantissa.rs b/vendor/ryu/src/pretty/mantissa.rs
index 150c79c12..0149f5cff 100644
--- a/vendor/ryu/src/pretty/mantissa.rs
+++ b/vendor/ryu/src/pretty/mantissa.rs
@@ -43,7 +43,7 @@ pub unsafe fn write_mantissa_long(mut output: u64, mut result: *mut u8) {
#[cfg_attr(feature = "no-panic", inline)]
pub unsafe fn write_mantissa(mut output: u32, mut result: *mut u8) {
while output >= 10_000 {
- let c = (output - 10_000 * (output / 10_000)) as u32;
+ let c = output - 10_000 * (output / 10_000);
output /= 10_000;
let c0 = (c % 100) << 1;
let c1 = (c / 100) << 1;
@@ -60,7 +60,7 @@ pub unsafe fn write_mantissa(mut output: u32, mut result: *mut u8) {
result = result.offset(-4);
}
if output >= 100 {
- let c = ((output % 100) << 1) as u32;
+ let c = (output % 100) << 1;
output /= 100;
ptr::copy_nonoverlapping(
DIGIT_TABLE.as_ptr().offset(c as isize),
@@ -70,7 +70,7 @@ pub unsafe fn write_mantissa(mut output: u32, mut result: *mut u8) {
result = result.offset(-2);
}
if output >= 10 {
- let c = (output << 1) as u32;
+ let c = output << 1;
ptr::copy_nonoverlapping(
DIGIT_TABLE.as_ptr().offset(c as isize),
result.offset(-2),
diff --git a/vendor/ryu/src/pretty/mod.rs b/vendor/ryu/src/pretty/mod.rs
index b196a11b4..da49e863e 100644
--- a/vendor/ryu/src/pretty/mod.rs
+++ b/vendor/ryu/src/pretty/mod.rs
@@ -160,8 +160,7 @@ pub unsafe fn format32(f: f32, result: *mut u8) -> usize {
let bits = f.to_bits();
let sign = ((bits >> (FLOAT_MANTISSA_BITS + FLOAT_EXPONENT_BITS)) & 1) != 0;
let ieee_mantissa = bits & ((1u32 << FLOAT_MANTISSA_BITS) - 1);
- let ieee_exponent =
- ((bits >> FLOAT_MANTISSA_BITS) & ((1u32 << FLOAT_EXPONENT_BITS) - 1)) as u32;
+ let ieee_exponent = (bits >> FLOAT_MANTISSA_BITS) & ((1u32 << FLOAT_EXPONENT_BITS) - 1);
let mut index = 0isize;
if sign {
diff --git a/vendor/ryu/src/s2f.rs b/vendor/ryu/src/s2f.rs
index 37c541784..959352815 100644
--- a/vendor/ryu/src/s2f.rs
+++ b/vendor/ryu/src/s2f.rs
@@ -220,7 +220,7 @@ pub fn s2f(buffer: &[u8]) -> Result<f32, Error> {
// for overflow here.
ieee_e2 += 1;
}
- let ieee = ((((signed_m as u32) << f2s::FLOAT_EXPONENT_BITS) | ieee_e2 as u32)
+ let ieee = ((((signed_m as u32) << f2s::FLOAT_EXPONENT_BITS) | ieee_e2)
<< f2s::FLOAT_MANTISSA_BITS)
| ieee_m2;
Ok(f32::from_bits(ieee))
diff --git a/vendor/scoped-tls/.cargo-checksum.json b/vendor/scoped-tls/.cargo-checksum.json
index a82babc4a..ab1c98519 100644
--- a/vendor/scoped-tls/.cargo-checksum.json
+++ b/vendor/scoped-tls/.cargo-checksum.json
@@ -1 +1 @@
-{"files":{"Cargo.toml":"9b7a3fdb45ac3847229254d53222ed393d5e5426e7d126dc3a1adfeb35b8b438","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"378f5840b258e2779c39418f3f2d7b2ba96f1c7917dd6be0713f88305dbda397","README.md":"5b42f802520064732b4097d9224cddffb6ad397536347bc996c95f433d893e85","appveyor.yml":"da991211b72fa6f231af7adb84c9fb72f5a9131d1c0a3d47b8ceffe5a82c8542","src/lib.rs":"03cafc877737e72e8bc6fed874c5b1154ec7a0579c5f875f1da66df54b642864"},"package":"ea6a9290e3c9cf0f18145ef7ffa62d68ee0bf5fcd651017e586dc7fd5da448c2"} \ No newline at end of file
+{"files":{"Cargo.toml":"34fd266d7e61276cf49fb2a9ea9887331ef4e72595fed99b7d8735c86cd13631","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"378f5840b258e2779c39418f3f2d7b2ba96f1c7917dd6be0713f88305dbda397","README.md":"0cf015ca6dd078c0f0e607508a4190c0a1328990069e6303c4709530960aab08","src/lib.rs":"ca804e29dde7dc843ab24f7f70c694eb43fac7c62194d85a58c8062caa0a84f4"},"package":"e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294"} \ No newline at end of file
diff --git a/vendor/scoped-tls/Cargo.toml b/vendor/scoped-tls/Cargo.toml
index 70c386117..08ec7b613 100644
--- a/vendor/scoped-tls/Cargo.toml
+++ b/vendor/scoped-tls/Cargo.toml
@@ -3,18 +3,22 @@
# When uploading crates to the registry Cargo will automatically
# "normalize" Cargo.toml files for maximal compatibility
# with all versions of Cargo and also rewrite `path` dependencies
-# to registry (e.g. crates.io) dependencies
+# to registry (e.g., crates.io) dependencies.
#
-# If you believe there's an error in this file please file an
-# issue against the rust-lang/cargo repository. If you're
-# editing this file be aware that the upstream Cargo.toml
-# will likely look very different (and much more reasonable)
+# If you are reading this file be aware that the original Cargo.toml
+# will likely look very different (and much more reasonable).
+# See Cargo.toml.orig for the original contents.
[package]
+rust-version = "1.59"
name = "scoped-tls"
-version = "1.0.0"
+version = "1.0.1"
authors = ["Alex Crichton <alex@alexcrichton.com>"]
-description = "Library implementation of the standard library's old `scoped_thread_local!`\nmacro for providing scoped access to thread local storage (TLS) so any type can\nbe stored into TLS.\n"
+description = """
+Library implementation of the standard library's old `scoped_thread_local!`
+macro for providing scoped access to thread local storage (TLS) so any type can
+be stored into TLS.
+"""
homepage = "https://github.com/alexcrichton/scoped-tls"
documentation = "https://docs.rs/scoped-tls"
readme = "README.md"
diff --git a/vendor/scoped-tls/README.md b/vendor/scoped-tls/README.md
index 88bd62401..36e6480e2 100644
--- a/vendor/scoped-tls/README.md
+++ b/vendor/scoped-tls/README.md
@@ -11,7 +11,7 @@ as a library implementation on crates.io.
```toml
# Cargo.toml
[dependencies]
-scoped-tls = "0.1"
+scoped-tls = "1.0"
```
# License
diff --git a/vendor/scoped-tls/appveyor.yml b/vendor/scoped-tls/appveyor.yml
deleted file mode 100644
index 6a1b8dc19..000000000
--- a/vendor/scoped-tls/appveyor.yml
+++ /dev/null
@@ -1,17 +0,0 @@
-environment:
- matrix:
- - TARGET: x86_64-pc-windows-msvc
- - TARGET: i686-pc-windows-msvc
- - TARGET: i686-pc-windows-gnu
-install:
- - ps: Start-FileDownload "https://static.rust-lang.org/dist/rust-nightly-${env:TARGET}.exe"
- - rust-nightly-%TARGET%.exe /VERYSILENT /NORESTART /DIR="C:\Program Files (x86)\Rust"
- - SET PATH=%PATH%;C:\Program Files (x86)\Rust\bin
- - SET PATH=%PATH%;C:\MinGW\bin
- - rustc -V
- - cargo -V
-
-build: false
-
-test_script:
- - cargo test --verbose
diff --git a/vendor/scoped-tls/src/lib.rs b/vendor/scoped-tls/src/lib.rs
index 6fbcf11e3..d4567c2bc 100644
--- a/vendor/scoped-tls/src/lib.rs
+++ b/vendor/scoped-tls/src/lib.rs
@@ -56,8 +56,8 @@ macro_rules! scoped_thread_local {
$(#[$attrs])*
$vis static $name: $crate::ScopedKey<$ty> = $crate::ScopedKey {
inner: {
- thread_local!(static FOO: ::std::cell::Cell<usize> = {
- ::std::cell::Cell::new(0)
+ ::std::thread_local!(static FOO: ::std::cell::Cell<*const ()> = const {
+ ::std::cell::Cell::new(::std::ptr::null())
});
&FOO
},
@@ -75,7 +75,7 @@ macro_rules! scoped_thread_local {
/// their contents.
pub struct ScopedKey<T> {
#[doc(hidden)]
- pub inner: &'static LocalKey<Cell<usize>>,
+ pub inner: &'static LocalKey<Cell<*const ()>>,
#[doc(hidden)]
pub _marker: marker::PhantomData<T>,
}
@@ -86,8 +86,8 @@ impl<T> ScopedKey<T> {
/// Inserts a value into this scoped thread local storage slot for a
/// duration of a closure.
///
- /// While `cb` is running, the value `t` will be returned by `get` unless
- /// this function is called recursively inside of `cb`.
+ /// While `f` is running, the value `t` will be returned by `get` unless
+ /// this function is called recursively inside of `f`.
///
/// Upon return, this function will restore the previous value, if any
/// was available.
@@ -120,8 +120,8 @@ impl<T> ScopedKey<T> {
where F: FnOnce() -> R
{
struct Reset {
- key: &'static LocalKey<Cell<usize>>,
- val: usize,
+ key: &'static LocalKey<Cell<*const ()>>,
+ val: *const (),
}
impl Drop for Reset {
fn drop(&mut self) {
@@ -130,7 +130,7 @@ impl<T> ScopedKey<T> {
}
let prev = self.inner.with(|c| {
let prev = c.get();
- c.set(t as *const T as usize);
+ c.set(t as *const T as *const ());
prev
});
let _reset = Reset { key: self.inner, val: prev };
@@ -165,8 +165,8 @@ impl<T> ScopedKey<T> {
where F: FnOnce(&T) -> R
{
let val = self.inner.with(|c| c.get());
- assert!(val != 0, "cannot access a scoped thread local \
- variable without calling `set` first");
+ assert!(!val.is_null(), "cannot access a scoped thread local \
+ variable without calling `set` first");
unsafe {
f(&*(val as *const T))
}
@@ -174,7 +174,7 @@ impl<T> ScopedKey<T> {
/// Test whether this TLS key has been `set` for the current thread.
pub fn is_set(&'static self) -> bool {
- self.inner.with(|c| c.get() != 0)
+ self.inner.with(|c| !c.get().is_null())
}
}
diff --git a/vendor/semver/.cargo-checksum.json b/vendor/semver/.cargo-checksum.json
index afd692226..3e0993c1a 100644
--- a/vendor/semver/.cargo-checksum.json
+++ b/vendor/semver/.cargo-checksum.json
@@ -1 +1 @@
-{"files":{"Cargo.toml":"2ef1bca69e829c310ba591cf769d26b9599343b5e8277607c810fcc27b08b507","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"23f18e03dc49df91622fe2a76176497404e46ced8a715d9d2b67a7446571cca3","README.md":"83e92a83348171f60d768651091803e69e4cb7ea3190cdfc45918d4637f38e1e","benches/parse.rs":"6531f66f80ce2fc83878f9bf84f94c42e96f1e709466f2b88be8d95a3cec1511","build.rs":"eedfc19afa205955347175916974cdad121b55cb940e40c61931e5e7629f0e65","src/backport.rs":"c1335129f4969ac887dcf4cdee7592d0854163ee3023c14649d1fba2ab5f08ba","src/display.rs":"9ba42f7a6579aa9c7dd72f2380036f5c9664592f3eacd09ea25cef291a3e64e5","src/error.rs":"3bb489f4a29f38d93370e64ae8d6e4e9b451a055cd7d392b6aeacab7eb3e1953","src/eval.rs":"b7e7ec976051b9f87ddf5cfdbaad64654d98d86ae0763f7d88b14eeaeac6013c","src/identifier.rs":"2fcc23896070ed0a658282a5c7053f1439a55c9e2ea927703408fea8321bfbee","src/impls.rs":"79b5a2ac6ca3d4cb46adfb1494756079f53bef780dd81c3a8d3adf86f91395c8","src/lib.rs":"4118a9d0aedfdbfb930fac79f6aa03771b7a3348b7fe2b4d3d02530dc8b6f387","src/parse.rs":"ffbb84081f0f66ec47b752a1e32f1bea5f206ca84f464b99d0497451305a92f8","src/serde.rs":"e2a9b9dc3cd2cccc250eaffad049de418ef791bf8c4a34111a48f068353e0a37","tests/node/mod.rs":"2710d9b8daace2038b66db0f8f4cc522dee938e7cbc42d7739c31995343c32f4","tests/test_autotrait.rs":"070500c32ceee14a8a0110c04a01f98278b24614a0aec8c382dcea3da0343f58","tests/test_identifier.rs":"6c3da46c73df210527b60f1069131b15e2c65eb7b5d11793940d00cf66812f4d","tests/test_version.rs":"09e37c3df162205acf3683d1c760a6001e34e1c709fd4a1a265d82450e340003","tests/test_version_req.rs":"b6eea0258cc3b6d567a9f6c42693a97316345083495236c47e85374fd45f7cf0","tests/util/mod.rs":"db61c2cd86af864d8be4f2a3d5f25c86d7712201cc6ab47b715facf5f7f275b7"},"package":"e25dfac463d778e353db5be2449d1cce89bd6fd23c9f1ea21310ce6e5a1b29c4"} \ No newline at end of file
+{"files":{"Cargo.toml":"84eaac27f969839e684c9cdf124748de0a8f0b0876a1eacc31cfaa105f35540f","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"23f18e03dc49df91622fe2a76176497404e46ced8a715d9d2b67a7446571cca3","README.md":"de1a03443ab8f147676199856a975ec00f3f7334fc5d5d5e056ec8f3fcb61dd5","benches/parse.rs":"6531f66f80ce2fc83878f9bf84f94c42e96f1e709466f2b88be8d95a3cec1511","build.rs":"9a3d42e37b665745044b5d91c6e02dd458152e336a7013654972f4a1a0b562d9","src/backport.rs":"66db55d15d0e2808bffe4cde7cd1d99bda999b26cbe40bb6b5e43b94f9b631d2","src/display.rs":"9ba42f7a6579aa9c7dd72f2380036f5c9664592f3eacd09ea25cef291a3e64e5","src/error.rs":"3bb489f4a29f38d93370e64ae8d6e4e9b451a055cd7d392b6aeacab7eb3e1953","src/eval.rs":"b7e7ec976051b9f87ddf5cfdbaad64654d98d86ae0763f7d88b14eeaeac6013c","src/identifier.rs":"459725383cbd0e2d769aa947decd1f031bdc8732339783ad24eb2b44f0f5d040","src/impls.rs":"79b5a2ac6ca3d4cb46adfb1494756079f53bef780dd81c3a8d3adf86f91395c8","src/lib.rs":"cc912c719047aa679429069a26679f681741b91ff66d847f60ddc519262d588c","src/parse.rs":"ffbb84081f0f66ec47b752a1e32f1bea5f206ca84f464b99d0497451305a92f8","src/serde.rs":"e2a9b9dc3cd2cccc250eaffad049de418ef791bf8c4a34111a48f068353e0a37","tests/node/mod.rs":"2710d9b8daace2038b66db0f8f4cc522dee938e7cbc42d7739c31995343c32f4","tests/test_autotrait.rs":"070500c32ceee14a8a0110c04a01f98278b24614a0aec8c382dcea3da0343f58","tests/test_identifier.rs":"6c3da46c73df210527b60f1069131b15e2c65eb7b5d11793940d00cf66812f4d","tests/test_version.rs":"09e37c3df162205acf3683d1c760a6001e34e1c709fd4a1a265d82450e340003","tests/test_version_req.rs":"b6eea0258cc3b6d567a9f6c42693a97316345083495236c47e85374fd45f7cf0","tests/util/mod.rs":"db61c2cd86af864d8be4f2a3d5f25c86d7712201cc6ab47b715facf5f7f275b7"},"package":"58bc9567378fc7690d6b2addae4e60ac2eeea07becb2c64b9f218b53865cba2a"} \ No newline at end of file
diff --git a/vendor/semver/Cargo.toml b/vendor/semver/Cargo.toml
index 68aa0b972..e0bfea20f 100644
--- a/vendor/semver/Cargo.toml
+++ b/vendor/semver/Cargo.toml
@@ -13,7 +13,7 @@
edition = "2018"
rust-version = "1.31"
name = "semver"
-version = "1.0.14"
+version = "1.0.16"
authors = ["David Tolnay <dtolnay@gmail.com>"]
description = "Parser and evaluator for Cargo's flavor of Semantic Versioning"
documentation = "https://docs.rs/semver"
@@ -31,10 +31,11 @@ targets = ["x86_64-unknown-linux-gnu"]
rustdoc-args = [
"--cfg",
"doc_cfg",
- "--cfg",
- "semver_rustdoc_workaround",
]
+[lib]
+doc-scrape-examples = false
+
[dependencies.serde]
version = "1.0"
optional = true
diff --git a/vendor/semver/README.md b/vendor/semver/README.md
index 84d227ea8..a9a1cb88b 100644
--- a/vendor/semver/README.md
+++ b/vendor/semver/README.md
@@ -4,7 +4,7 @@ semver
[<img alt="github" src="https://img.shields.io/badge/github-dtolnay/semver-8da0cb?style=for-the-badge&labelColor=555555&logo=github" height="20">](https://github.com/dtolnay/semver)
[<img alt="crates.io" src="https://img.shields.io/crates/v/semver.svg?style=for-the-badge&color=fc8d62&logo=rust" height="20">](https://crates.io/crates/semver)
[<img alt="docs.rs" src="https://img.shields.io/badge/docs.rs-semver-66c2a5?style=for-the-badge&labelColor=555555&logo=docs.rs" height="20">](https://docs.rs/semver)
-[<img alt="build status" src="https://img.shields.io/github/workflow/status/dtolnay/semver/CI/master?style=for-the-badge" height="20">](https://github.com/dtolnay/semver/actions?query=branch%3Amaster)
+[<img alt="build status" src="https://img.shields.io/github/actions/workflow/status/dtolnay/semver/ci.yml?branch=master&style=for-the-badge" height="20">](https://github.com/dtolnay/semver/actions?query=branch%3Amaster)
A parser and evaluator for Cargo's flavor of Semantic Versioning.
diff --git a/vendor/semver/build.rs b/vendor/semver/build.rs
index 2bf4418c1..81ad970d8 100644
--- a/vendor/semver/build.rs
+++ b/vendor/semver/build.rs
@@ -3,6 +3,8 @@ use std::process::Command;
use std::str;
fn main() {
+ println!("cargo:rerun-if-changed=build.rs");
+
let compiler = match rustc_minor_version() {
Some(compiler) => compiler,
None => return,
diff --git a/vendor/semver/src/backport.rs b/vendor/semver/src/backport.rs
index 4b67f56a5..b5e1d02be 100644
--- a/vendor/semver/src/backport.rs
+++ b/vendor/semver/src/backport.rs
@@ -18,43 +18,6 @@ pub(crate) use crate::alloc::vec::Vec;
#[cfg(no_alloc_crate)] // rustc <1.36
pub(crate) mod alloc {
+ pub use std::alloc;
pub use std::vec;
-
- pub mod alloc {
- use std::mem;
- use std::process;
-
- #[derive(Copy, Clone)]
- pub struct Layout {
- size: usize,
- }
-
- impl Layout {
- pub unsafe fn from_size_align_unchecked(size: usize, align: usize) -> Self {
- assert_eq!(align, 2);
- Layout { size }
- }
- }
-
- pub unsafe fn alloc(layout: Layout) -> *mut u8 {
- let len_u16 = (layout.size + 1) / 2;
- let mut vec = Vec::new();
- vec.reserve_exact(len_u16);
- let ptr: *mut u16 = vec.as_mut_ptr();
- mem::forget(vec);
- ptr as *mut u8
- }
-
- pub unsafe fn dealloc(ptr: *mut u8, layout: Layout) {
- let len_u16 = (layout.size + 1) / 2;
- unsafe { Vec::from_raw_parts(ptr as *mut u16, 0, len_u16) };
- }
-
- pub fn handle_alloc_error(_layout: Layout) -> ! {
- // This is unreachable because the alloc implementation above never
- // returns null; Vec::reserve_exact would already have called std's
- // internal handle_alloc_error.
- process::abort();
- }
- }
}
diff --git a/vendor/semver/src/identifier.rs b/vendor/semver/src/identifier.rs
index fbe1df020..0273ae62a 100644
--- a/vendor/semver/src/identifier.rs
+++ b/vendor/semver/src/identifier.rs
@@ -67,11 +67,13 @@
// allows size_of::<Version>() == size_of::<Option<Version>>().
use crate::alloc::alloc::{alloc, dealloc, handle_alloc_error, Layout};
+use core::isize;
use core::mem;
use core::num::{NonZeroU64, NonZeroUsize};
use core::ptr::{self, NonNull};
use core::slice;
use core::str;
+use core::usize;
const PTR_BYTES: usize = mem::size_of::<NonNull<u8>>();
@@ -103,6 +105,7 @@ impl Identifier {
// SAFETY: string must be ASCII and not contain \0 bytes.
pub(crate) unsafe fn new_unchecked(string: &str) -> Self {
let len = string.len();
+ debug_assert!(len <= isize::MAX as usize);
match len as u64 {
0 => Self::empty(),
1..=8 => {
@@ -118,8 +121,21 @@ impl Identifier {
// SAFETY: len is in a range that does not contain 0.
let size = bytes_for_varint(unsafe { NonZeroUsize::new_unchecked(len) }) + len;
let align = 2;
+ // On 32-bit and 16-bit architecture, check for size overflowing
+ // isize::MAX. Making an allocation request bigger than this to
+ // the allocator is considered UB. All allocations (including
+ // static ones) are limited to isize::MAX so we're guaranteed
+ // len <= isize::MAX, and we know bytes_for_varint(len) <= 5
+ // because 128**5 > isize::MAX, which means the only problem
+ // that can arise is when isize::MAX - 5 <= len <= isize::MAX.
+ // This is pretty much guaranteed to be malicious input so we
+ // don't need to care about returning a good error message.
+ if mem::size_of::<usize>() < 8 {
+ let max_alloc = usize::MAX / 2 - align;
+ assert!(size <= max_alloc);
+ }
// SAFETY: align is not zero, align is a power of two, and
- // rounding size up to align does not overflow usize::MAX.
+ // rounding size up to align does not overflow isize::MAX.
let layout = unsafe { Layout::from_size_align_unchecked(size, align) };
// SAFETY: layout's size is nonzero.
let ptr = unsafe { alloc(layout) };
@@ -200,7 +216,7 @@ impl Clone for Identifier {
let size = bytes_for_varint(len) + len.get();
let align = 2;
// SAFETY: align is not zero, align is a power of two, and rounding
- // size up to align does not overflow usize::MAX. This is just
+ // size up to align does not overflow isize::MAX. This is just
// duplicating a previous allocation where all of these guarantees
// were already made.
let layout = unsafe { Layout::from_size_align_unchecked(size, align) };
diff --git a/vendor/semver/src/lib.rs b/vendor/semver/src/lib.rs
index ca4d1119c..32ed96d1c 100644
--- a/vendor/semver/src/lib.rs
+++ b/vendor/semver/src/lib.rs
@@ -60,7 +60,7 @@
//!
//! [Specifying Dependencies]: https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html
-#![doc(html_root_url = "https://docs.rs/semver/1.0.14")]
+#![doc(html_root_url = "https://docs.rs/semver/1.0.16")]
#![cfg_attr(doc_cfg, feature(doc_cfg))]
#![cfg_attr(all(not(feature = "std"), not(no_alloc_crate)), no_std)]
#![cfg_attr(not(no_unsafe_op_in_unsafe_fn_lint), deny(unsafe_op_in_unsafe_fn))]
@@ -497,11 +497,6 @@ impl Comparator {
}
impl Prerelease {
- // Work around https://github.com/rust-lang/rust/issues/97933
- #[cfg(all(doc, semver_rustdoc_workaround))]
- pub const EMPTY: Self = "";
-
- #[cfg(not(all(doc, semver_rustdoc_workaround)))]
pub const EMPTY: Self = Prerelease {
identifier: Identifier::empty(),
};
@@ -520,11 +515,6 @@ impl Prerelease {
}
impl BuildMetadata {
- // Work around https://github.com/rust-lang/rust/issues/97933
- #[cfg(all(doc, semver_rustdoc_workaround))]
- pub const EMPTY: Self = "";
-
- #[cfg(not(all(doc, semver_rustdoc_workaround)))]
pub const EMPTY: Self = BuildMetadata {
identifier: Identifier::empty(),
};
diff --git a/vendor/serde/.cargo-checksum.json b/vendor/serde/.cargo-checksum.json
index 0aefd0d73..812d0d93c 100644
--- a/vendor/serde/.cargo-checksum.json
+++ b/vendor/serde/.cargo-checksum.json
@@ -1 +1 @@
-{"files":{"Cargo.toml":"7726b0fc6476d58de05dd5342dd517da6968c3b774cb2443b09f8c1e0926d347","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"23f18e03dc49df91622fe2a76176497404e46ced8a715d9d2b67a7446571cca3","README.md":"7049b88cb7366be0c8e593f3ffffa313803a5b382f35686c542b4a0da3b291f3","build.rs":"89cfc904243b611a8a2fc1c8724d6f1c2b61c166ca81676b903ddf80b8ff1c10","crates-io.md":"5c42406936cf9af6d4cd7fe0ac730c609e82fd3f15a54549518c72d0ded70c29","src/de/format.rs":"4b466a6a7f0070e884d14457759671c6ad7394fe9603708b7151ef6159258146","src/de/ignored_any.rs":"967184c86707c99b77a1cfb218dfc823f560fae227b6635aee6af19ee82962f5","src/de/impls.rs":"363f9f9400dcaf46176ab5c0a3592996abbed0618fddb51b090a7617a78eb5a0","src/de/mod.rs":"1dbddc2870da5cae0a725c7aacca83f0dabba55895f17849f2d5da254b1ebeb6","src/de/seed.rs":"e8cf0233afe0af5b8fb9e4c94f301c92729c5ba417280af9e2201b732e374a72","src/de/utf8.rs":"f17524ee0af98ec3abcfd7d0b812fbd1033263bd8e2ce2f57c1e1999ce153558","src/de/value.rs":"aa5055923e2c3fd1c1f1abdfb380a1d63d07cf4d602ef62d2df2b7da33dd8c81","src/integer128.rs":"ca49591abde2d8c4f582174533fee28f0fa9139e5d71bf22b25a6b175f8abccc","src/lib.rs":"66d086f0da93675b6d467814d593e03521007f5e319bcfdb1eb35eabb5974fa5","src/macros.rs":"3d695a51f0a07f9f719dcb5620012c21a1b084c06a6283349cabf574ceba8123","src/private/de.rs":"cc6f7fa8d0345db5918bcea549cd302a1159a7e4c5fe3e10027fbe57517ceb49","src/private/doc.rs":"e9801a43c3088fccd5f1fac76416698f948e65b647024aa9da17d673e1e8c217","src/private/mod.rs":"37b204775e572396515477b393ce793b2579de48e5971e6f596ba3723c489fd6","src/private/ser.rs":"087cf1141d1053f932f51b362ed08fd1fec43b4dbe5504bedc0c183fc8ce05e6","src/private/size_hint.rs":"605521227e9ba3100fbb9d5ea7fd5853385097c35015ce6908bd5f1ea20d59ad","src/ser/fmt.rs":"7827ed07fd8897e6324f75625ba0c926a4c4e7ec2914cd067391ce54d942ac7b","src/ser/impls.rs":"97288074fb0ff40f4178359a37879a996c7d0e5d5a7f173b9203f885d90d3ba0","src/ser/impossible.rs":"db17913522c1c27389c5a085113911353b9813c1b116518681362e7c8b692c3a","src/ser/mod.rs":"e5008f26bd6100f52c7223184802e63f4d046651c9db56f68602752cea20745c","src/std_error.rs":"3aac687856c035517fae44ed2906dd4a1e3184bae4bf613adcdeb73f74126c57"},"package":"d193d69bae983fc11a79df82342761dfbf28a99fc8d203dca4c3c1b590948965"} \ No newline at end of file
+{"files":{"Cargo.toml":"e390e019c701323f7a6f3b42dc1242445a0ea6c1188d91b1d3513fcebc7afe1d","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"23f18e03dc49df91622fe2a76176497404e46ced8a715d9d2b67a7446571cca3","README.md":"3c12b60b6c77a201665344a7612b42392e77ddc3e907f5a14e3f3a4bb6c4692e","build.rs":"bf6f7f791517c2d583457e74452c68a7308c5e5106d1a2cebcfa19c55a9c1a42","crates-io.md":"ee22254ee64c3189eef3e707c8d75dc66a8df2a7ee9e518d95238950780ec387","src/de/format.rs":"84f902fd4c3be66e81ac01d5b21cd876113c16f9890ff8bab5faa0d085386294","src/de/ignored_any.rs":"967184c86707c99b77a1cfb218dfc823f560fae227b6635aee6af19ee82962f5","src/de/impls.rs":"2d4d9985b1048f5f6371984c9bc8f273ad685901ba22ad27483dfb7cec65898c","src/de/mod.rs":"71198e80e4c64aa686b5ceb6e8bce10db20845a87a30fa14227ecbe365a046d5","src/de/seed.rs":"e8cf0233afe0af5b8fb9e4c94f301c92729c5ba417280af9e2201b732e374a72","src/de/utf8.rs":"f17524ee0af98ec3abcfd7d0b812fbd1033263bd8e2ce2f57c1e1999ce153558","src/de/value.rs":"aa5055923e2c3fd1c1f1abdfb380a1d63d07cf4d602ef62d2df2b7da33dd8c81","src/integer128.rs":"ca49591abde2d8c4f582174533fee28f0fa9139e5d71bf22b25a6b175f8abccc","src/lib.rs":"a359fe67a2d3a8bfe27219b35992c0ed390a65a409c69db75e3bf7e63fd16dde","src/macros.rs":"3d695a51f0a07f9f719dcb5620012c21a1b084c06a6283349cabf574ceba8123","src/private/de.rs":"a85efe9af4f5629ac7d946af56e20fbc184df6ac40a6cfe47bf3997a95b2ea20","src/private/doc.rs":"e9801a43c3088fccd5f1fac76416698f948e65b647024aa9da17d673e1e8c217","src/private/mod.rs":"37b204775e572396515477b393ce793b2579de48e5971e6f596ba3723c489fd6","src/private/ser.rs":"57fbff98429e870da86edcf61c0831caaa3b708c0c32e3038c4b2179e8dff73e","src/private/size_hint.rs":"605521227e9ba3100fbb9d5ea7fd5853385097c35015ce6908bd5f1ea20d59ad","src/ser/fmt.rs":"7827ed07fd8897e6324f75625ba0c926a4c4e7ec2914cd067391ce54d942ac7b","src/ser/impls.rs":"8cbe2b66ae950cbc5223e41ac82194cccfc2c26300acfe6328e5f20081f23af3","src/ser/impossible.rs":"db17913522c1c27389c5a085113911353b9813c1b116518681362e7c8b692c3a","src/ser/mod.rs":"e1e6c764837c70b6410dcf1949a0dae1b4b4ffce65b87607d3d173b612e9bccf","src/std_error.rs":"3aac687856c035517fae44ed2906dd4a1e3184bae4bf613adcdeb73f74126c57"},"package":"bb7d1f0d3021d347a83e556fc4683dea2ea09d87bccdf88ff5c12545d89d5efb"} \ No newline at end of file
diff --git a/vendor/serde/Cargo.toml b/vendor/serde/Cargo.toml
index a319d423d..93acff3a2 100644
--- a/vendor/serde/Cargo.toml
+++ b/vendor/serde/Cargo.toml
@@ -12,7 +12,7 @@
[package]
rust-version = "1.13"
name = "serde"
-version = "1.0.147"
+version = "1.0.152"
authors = [
"Erick Tryzelaar <erick.tryzelaar@gmail.com>",
"David Tolnay <dtolnay@gmail.com>",
@@ -28,7 +28,7 @@ include = [
]
description = "A generic serialization/deserialization framework"
homepage = "https://serde.rs"
-documentation = "https://docs.serde.rs/serde/"
+documentation = "https://docs.rs/serde"
readme = "crates-io.md"
keywords = [
"serde",
@@ -51,8 +51,11 @@ features = [
[package.metadata.docs.rs]
targets = ["x86_64-unknown-linux-gnu"]
+[lib]
+doc-scrape-examples = false
+
[dependencies.serde_derive]
-version = "=1.0.147"
+version = "=1.0.152"
optional = true
[dev-dependencies.serde_derive]
diff --git a/vendor/serde/README.md b/vendor/serde/README.md
index 79409a3fc..c3f6575ef 100644
--- a/vendor/serde/README.md
+++ b/vendor/serde/README.md
@@ -1,6 +1,6 @@
# Serde &emsp; [![Build Status]][actions] [![Latest Version]][crates.io] [![serde: rustc 1.13+]][Rust 1.13] [![serde_derive: rustc 1.31+]][Rust 1.31]
-[Build Status]: https://img.shields.io/github/workflow/status/serde-rs/serde/CI/master
+[Build Status]: https://img.shields.io/github/actions/workflow/status/serde-rs/serde/ci.yml?branch=master
[actions]: https://github.com/serde-rs/serde/actions?query=branch%3Amaster
[Latest Version]: https://img.shields.io/crates/v/serde.svg
[crates.io]: https://crates.io/crates/serde
@@ -19,7 +19,7 @@ You may be looking for:
- [Data formats supported by Serde](https://serde.rs/#data-formats)
- [Setting up `#[derive(Serialize, Deserialize)]`](https://serde.rs/derive.html)
- [Examples](https://serde.rs/examples.html)
-- [API documentation](https://docs.serde.rs/serde/)
+- [API documentation](https://docs.rs/serde)
- [Release notes](https://github.com/serde-rs/serde/releases)
## Serde in action
diff --git a/vendor/serde/build.rs b/vendor/serde/build.rs
index a1103b520..ccbddd273 100644
--- a/vendor/serde/build.rs
+++ b/vendor/serde/build.rs
@@ -6,6 +6,8 @@ use std::str::{self, FromStr};
// opening a GitHub issue if your build environment requires some way to enable
// these cfgs other than by executing our build script.
fn main() {
+ println!("cargo:rerun-if-changed=build.rs");
+
let minor = match rustc_minor_version() {
Some(minor) => minor,
None => return,
@@ -89,24 +91,28 @@ fn main() {
println!("cargo:rustc-cfg=no_core_try_from");
println!("cargo:rustc-cfg=no_num_nonzero_signed");
println!("cargo:rustc-cfg=no_systemtime_checked_add");
+ println!("cargo:rustc-cfg=no_relaxed_trait_bounds");
}
- // Whitelist of archs that support std::sync::atomic module. Ideally we
- // would use #[cfg(target_has_atomic = "...")] but it is not stable yet.
- // Instead this is based on rustc's compiler/rustc_target/src/spec/*.rs.
- let has_atomic64 = target.starts_with("x86_64")
- || target.starts_with("i686")
- || target.starts_with("aarch64")
- || target.starts_with("powerpc64")
- || target.starts_with("sparc64")
- || target.starts_with("mips64el")
- || target.starts_with("riscv64");
- let has_atomic32 = has_atomic64 || emscripten;
- if minor < 34 || !has_atomic64 {
- println!("cargo:rustc-cfg=no_std_atomic64");
- }
- if minor < 34 || !has_atomic32 {
- println!("cargo:rustc-cfg=no_std_atomic");
+ // Support for #[cfg(target_has_atomic = "...")] stabilized in Rust 1.60.
+ if minor < 60 {
+ println!("cargo:rustc-cfg=no_target_has_atomic");
+ // Allowlist of archs that support std::sync::atomic module. This is
+ // based on rustc's compiler/rustc_target/src/spec/*.rs.
+ let has_atomic64 = target.starts_with("x86_64")
+ || target.starts_with("i686")
+ || target.starts_with("aarch64")
+ || target.starts_with("powerpc64")
+ || target.starts_with("sparc64")
+ || target.starts_with("mips64el")
+ || target.starts_with("riscv64");
+ let has_atomic32 = has_atomic64 || emscripten;
+ if minor < 34 || !has_atomic64 {
+ println!("cargo:rustc-cfg=no_std_atomic64");
+ }
+ if minor < 34 || !has_atomic32 {
+ println!("cargo:rustc-cfg=no_std_atomic");
+ }
}
}
diff --git a/vendor/serde/crates-io.md b/vendor/serde/crates-io.md
index b57bc5fd0..6e0ec280c 100644
--- a/vendor/serde/crates-io.md
+++ b/vendor/serde/crates-io.md
@@ -10,7 +10,7 @@ You may be looking for:
- [Data formats supported by Serde](https://serde.rs/#data-formats)
- [Setting up `#[derive(Serialize, Deserialize)]`](https://serde.rs/derive.html)
- [Examples](https://serde.rs/examples.html)
-- [API documentation](https://docs.serde.rs/serde/)
+- [API documentation](https://docs.rs/serde)
- [Release notes](https://github.com/serde-rs/serde/releases)
## Serde in action
diff --git a/vendor/serde/src/de/format.rs b/vendor/serde/src/de/format.rs
index 58ec0968d..f14580b8d 100644
--- a/vendor/serde/src/de/format.rs
+++ b/vendor/serde/src/de/format.rs
@@ -1,7 +1,7 @@
use lib::fmt::{self, Write};
use lib::str;
-pub struct Buf<'a> {
+pub(super) struct Buf<'a> {
bytes: &'a mut [u8],
offset: usize,
}
diff --git a/vendor/serde/src/de/impls.rs b/vendor/serde/src/de/impls.rs
index c048f7145..a257d9e2f 100644
--- a/vendor/serde/src/de/impls.rs
+++ b/vendor/serde/src/de/impls.rs
@@ -733,7 +733,7 @@ impl<'de> Deserialize<'de> for CString {
macro_rules! forwarded_impl {
(
$(#[doc = $doc:tt])*
- ( $($id: ident),* ), $ty: ty, $func: expr
+ ($($id:ident),*), $ty:ty, $func:expr
) => {
$(#[doc = $doc])*
impl<'de $(, $id : Deserialize<'de>,)*> Deserialize<'de> for $ty {
@@ -860,7 +860,7 @@ impl<'de, T: ?Sized> Deserialize<'de> for PhantomData<T> {
#[cfg(any(feature = "std", feature = "alloc"))]
macro_rules! seq_impl {
(
- $ty:ident < T $(: $tbound1:ident $(+ $tbound2:ident)*)* $(, $typaram:ident : $bound1:ident $(+ $bound2:ident)*)* >,
+ $ty:ident <T $(: $tbound1:ident $(+ $tbound2:ident)*)* $(, $typaram:ident : $bound1:ident $(+ $bound2:ident)*)*>,
$access:ident,
$clear:expr,
$with_capacity:expr,
@@ -1353,7 +1353,7 @@ tuple_impls! {
#[cfg(any(feature = "std", feature = "alloc"))]
macro_rules! map_impl {
(
- $ty:ident < K $(: $kbound1:ident $(+ $kbound2:ident)*)*, V $(, $typaram:ident : $bound1:ident $(+ $bound2:ident)*)* >,
+ $ty:ident <K $(: $kbound1:ident $(+ $kbound2:ident)*)*, V $(, $typaram:ident : $bound1:ident $(+ $bound2:ident)*)*>,
$access:ident,
$with_capacity:expr
) => {
@@ -1440,15 +1440,15 @@ macro_rules! parse_ip_impl {
#[cfg(feature = "std")]
macro_rules! variant_identifier {
(
- $name_kind: ident ( $($variant: ident; $bytes: expr; $index: expr),* )
- $expecting_message: expr,
- $variants_name: ident
+ $name_kind:ident ($($variant:ident; $bytes:expr; $index:expr),*)
+ $expecting_message:expr,
+ $variants_name:ident
) => {
enum $name_kind {
- $( $variant ),*
+ $($variant),*
}
- static $variants_name: &'static [&'static str] = &[ $( stringify!($variant) ),*];
+ static $variants_name: &'static [&'static str] = &[$(stringify!($variant)),*];
impl<'de> Deserialize<'de> for $name_kind {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
@@ -1515,12 +1515,12 @@ macro_rules! variant_identifier {
#[cfg(feature = "std")]
macro_rules! deserialize_enum {
(
- $name: ident $name_kind: ident ( $($variant: ident; $bytes: expr; $index: expr),* )
- $expecting_message: expr,
- $deserializer: expr
+ $name:ident $name_kind:ident ($($variant:ident; $bytes:expr; $index:expr),*)
+ $expecting_message:expr,
+ $deserializer:expr
) => {
- variant_identifier!{
- $name_kind ( $($variant; $bytes; $index),* )
+ variant_identifier! {
+ $name_kind ($($variant; $bytes; $index),*)
$expecting_message,
VARIANTS
}
@@ -2662,8 +2662,9 @@ where
#[cfg(all(feature = "std", not(no_std_atomic)))]
macro_rules! atomic_impl {
- ($($ty:ident)*) => {
+ ($($ty:ident $size:expr)*) => {
$(
+ #[cfg(any(no_target_has_atomic, target_has_atomic = $size))]
impl<'de> Deserialize<'de> for $ty {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
@@ -2678,14 +2679,21 @@ macro_rules! atomic_impl {
#[cfg(all(feature = "std", not(no_std_atomic)))]
atomic_impl! {
- AtomicBool
- AtomicI8 AtomicI16 AtomicI32 AtomicIsize
- AtomicU8 AtomicU16 AtomicU32 AtomicUsize
+ AtomicBool "8"
+ AtomicI8 "8"
+ AtomicI16 "16"
+ AtomicI32 "32"
+ AtomicIsize "ptr"
+ AtomicU8 "8"
+ AtomicU16 "16"
+ AtomicU32 "32"
+ AtomicUsize "ptr"
}
#[cfg(all(feature = "std", not(no_std_atomic64)))]
atomic_impl! {
- AtomicI64 AtomicU64
+ AtomicI64 "64"
+ AtomicU64 "64"
}
#[cfg(feature = "std")]
diff --git a/vendor/serde/src/de/mod.rs b/vendor/serde/src/de/mod.rs
index d9dafbe1e..ca29ec610 100644
--- a/vendor/serde/src/de/mod.rs
+++ b/vendor/serde/src/de/mod.rs
@@ -501,8 +501,8 @@ impl<'a> Display for Expected + 'a {
/// by Serde.
///
/// Serde provides `Deserialize` implementations for many Rust primitive and
-/// standard library types. The complete list is [here][de]. All of these can
-/// be deserialized using Serde out of the box.
+/// standard library types. The complete list is [here][crate::de]. All of these
+/// can be deserialized using Serde out of the box.
///
/// Additionally, Serde provides a procedural macro called `serde_derive` to
/// automatically generate `Deserialize` implementations for structs and enums
@@ -518,7 +518,6 @@ impl<'a> Display for Expected + 'a {
/// `LinkedHashMap<K, V>` type that is deserializable by Serde because the crate
/// provides an implementation of `Deserialize` for it.
///
-/// [de]: https://docs.serde.rs/serde/de/index.html
/// [derive]: https://serde.rs/derive.html
/// [impl-deserialize]: https://serde.rs/impl-deserialize.html
///
diff --git a/vendor/serde/src/lib.rs b/vendor/serde/src/lib.rs
index 02c57ae9d..e4bc7c8f1 100644
--- a/vendor/serde/src/lib.rs
+++ b/vendor/serde/src/lib.rs
@@ -52,16 +52,22 @@
//! - [S-expressions], the textual representation of code and data used by the
//! Lisp language family.
//! - [D-Bus]'s binary wire format.
-//! - [FlexBuffers], the schemaless cousin of Google's FlatBuffers zero-copy serialization format.
+//! - [FlexBuffers], the schemaless cousin of Google's FlatBuffers zero-copy
+//! serialization format.
+//! - [Bencode], a simple binary format used in the BitTorrent protocol.
+//! - [Token streams], for processing Rust procedural macro input.
+//! *(deserialization only)*
//! - [DynamoDB Items], the format used by [rusoto_dynamodb] to transfer data to
//! and from DynamoDB.
+//! - [Hjson], a syntax extension to JSON designed around human reading and
+//! editing. *(deserialization only)*
//!
//! [JSON]: https://github.com/serde-rs/json
//! [Postcard]: https://github.com/jamesmunns/postcard
//! [CBOR]: https://github.com/enarx/ciborium
//! [YAML]: https://github.com/dtolnay/serde-yaml
//! [MessagePack]: https://github.com/3Hren/msgpack-rust
-//! [TOML]: https://github.com/alexcrichton/toml-rs
+//! [TOML]: https://docs.rs/toml
//! [Pickle]: https://github.com/birkenfeld/serde-pickle
//! [RON]: https://github.com/ron-rs/ron
//! [BSON]: https://github.com/mongodb/bson-rust
@@ -75,20 +81,23 @@
//! [S-expressions]: https://github.com/rotty/lexpr-rs
//! [D-Bus]: https://docs.rs/zvariant
//! [FlexBuffers]: https://github.com/google/flatbuffers/tree/master/rust/flexbuffers
+//! [Bencode]: https://github.com/P3KI/bendy
+//! [Token streams]: https://github.com/oxidecomputer/serde_tokenstream
//! [DynamoDB Items]: https://docs.rs/serde_dynamo
//! [rusoto_dynamodb]: https://docs.rs/rusoto_dynamodb
+//! [Hjson]: https://github.com/Canop/deser-hjson
////////////////////////////////////////////////////////////////////////////////
// Serde types in rustdoc of other crates get linked to here.
-#![doc(html_root_url = "https://docs.rs/serde/1.0.147")]
+#![doc(html_root_url = "https://docs.rs/serde/1.0.152")]
// Support using Serde without the standard library!
#![cfg_attr(not(feature = "std"), no_std)]
// Unstable functionality only if the user asks for it. For tracking and
// discussion of these features please refer to this issue:
//
// https://github.com/serde-rs/serde/issues/812
-#![cfg_attr(feature = "unstable", feature(never_type))]
+#![cfg_attr(feature = "unstable", feature(error_in_core, never_type))]
#![allow(unknown_lints, bare_trait_objects, deprecated)]
#![cfg_attr(feature = "cargo-clippy", allow(renamed_and_removed_lints))]
// Ignored clippy and clippy_pedantic lints
@@ -118,7 +127,6 @@
derive_partial_eq_without_eq,
enum_glob_use,
explicit_auto_deref,
- let_underscore_drop,
map_err_ignore,
new_without_default,
result_unit_err,
@@ -237,13 +245,26 @@ mod lib {
#[cfg(not(no_range_inclusive))]
pub use self::core::ops::RangeInclusive;
- #[cfg(all(feature = "std", not(no_std_atomic)))]
+ #[cfg(all(feature = "std", no_target_has_atomic, not(no_std_atomic)))]
pub use std::sync::atomic::{
AtomicBool, AtomicI16, AtomicI32, AtomicI8, AtomicIsize, AtomicU16, AtomicU32, AtomicU8,
AtomicUsize, Ordering,
};
- #[cfg(all(feature = "std", not(no_std_atomic64)))]
+ #[cfg(all(feature = "std", no_target_has_atomic, not(no_std_atomic64)))]
+ pub use std::sync::atomic::{AtomicI64, AtomicU64};
+
+ #[cfg(all(feature = "std", not(no_target_has_atomic)))]
+ pub use std::sync::atomic::Ordering;
+ #[cfg(all(feature = "std", not(no_target_has_atomic), target_has_atomic = "8"))]
+ pub use std::sync::atomic::{AtomicBool, AtomicI8, AtomicU8};
+ #[cfg(all(feature = "std", not(no_target_has_atomic), target_has_atomic = "16"))]
+ pub use std::sync::atomic::{AtomicI16, AtomicU16};
+ #[cfg(all(feature = "std", not(no_target_has_atomic), target_has_atomic = "32"))]
+ pub use std::sync::atomic::{AtomicI32, AtomicU32};
+ #[cfg(all(feature = "std", not(no_target_has_atomic), target_has_atomic = "64"))]
pub use std::sync::atomic::{AtomicI64, AtomicU64};
+ #[cfg(all(feature = "std", not(no_target_has_atomic), target_has_atomic = "ptr"))]
+ pub use std::sync::atomic::{AtomicIsize, AtomicUsize};
#[cfg(any(feature = "std", not(no_core_duration)))]
pub use self::core::time::Duration;
@@ -291,7 +312,7 @@ use self::__private as private;
#[path = "de/seed.rs"]
mod seed;
-#[cfg(not(feature = "std"))]
+#[cfg(not(any(feature = "std", feature = "unstable")))]
mod std_error;
// Re-export #[derive(Serialize, Deserialize)].
diff --git a/vendor/serde/src/private/de.rs b/vendor/serde/src/private/de.rs
index 01e5bf787..e9c693d4d 100644
--- a/vendor/serde/src/private/de.rs
+++ b/vendor/serde/src/private/de.rs
@@ -1810,7 +1810,7 @@ mod content {
V: Visitor<'de>,
E: de::Error,
{
- let map = content.iter().map(|&(ref k, ref v)| {
+ let map = content.iter().map(|(k, v)| {
(
ContentRefDeserializer::new(k),
ContentRefDeserializer::new(v),
@@ -2107,7 +2107,7 @@ mod content {
let (variant, value) = match *self.content {
Content::Map(ref value) => {
let mut iter = value.iter();
- let &(ref variant, ref value) = match iter.next() {
+ let (variant, value) = match iter.next() {
Some(v) => v,
None => {
return Err(de::Error::invalid_value(
@@ -2254,7 +2254,7 @@ mod content {
V: de::Visitor<'de>,
{
match self.value {
- Some(&Content::Seq(ref v)) => {
+ Some(Content::Seq(v)) => {
de::Deserializer::deserialize_any(SeqRefDeserializer::new(v), visitor)
}
Some(other) => Err(de::Error::invalid_type(
@@ -2277,10 +2277,10 @@ mod content {
V: de::Visitor<'de>,
{
match self.value {
- Some(&Content::Map(ref v)) => {
+ Some(Content::Map(v)) => {
de::Deserializer::deserialize_any(MapRefDeserializer::new(v), visitor)
}
- Some(&Content::Seq(ref v)) => {
+ Some(Content::Seq(v)) => {
de::Deserializer::deserialize_any(SeqRefDeserializer::new(v), visitor)
}
Some(other) => Err(de::Error::invalid_type(
@@ -2403,7 +2403,7 @@ mod content {
T: de::DeserializeSeed<'de>,
{
match self.iter.next() {
- Some(&(ref key, ref value)) => {
+ Some((key, value)) => {
self.value = Some(value);
seed.deserialize(ContentRefDeserializer::new(key)).map(Some)
}
@@ -2708,7 +2708,7 @@ where
#[cfg(any(feature = "std", feature = "alloc"))]
macro_rules! forward_to_deserialize_other {
- ($($func:ident ( $($arg:ty),* ))*) => {
+ ($($func:ident ($($arg:ty),*))*) => {
$(
fn $func<V>(self, $(_: $arg,)* _visitor: V) -> Result<V::Value, Self::Error>
where
diff --git a/vendor/serde/src/private/ser.rs b/vendor/serde/src/private/ser.rs
index 293d8a865..528e8c125 100644
--- a/vendor/serde/src/private/ser.rs
+++ b/vendor/serde/src/private/ser.rs
@@ -525,7 +525,7 @@ mod content {
Content::Map(ref entries) => {
use ser::SerializeMap;
let mut map = try!(serializer.serialize_map(Some(entries.len())));
- for &(ref k, ref v) in entries {
+ for (k, v) in entries {
try!(map.serialize_entry(k, v));
}
map.end()
diff --git a/vendor/serde/src/ser/impls.rs b/vendor/serde/src/ser/impls.rs
index 8e8655582..da2677261 100644
--- a/vendor/serde/src/ser/impls.rs
+++ b/vendor/serde/src/ser/impls.rs
@@ -182,9 +182,27 @@ where
}
}
-#[cfg(any(feature = "std", feature = "alloc"))]
+#[cfg(all(any(feature = "std", feature = "alloc"), not(no_relaxed_trait_bounds)))]
macro_rules! seq_impl {
- ($ty:ident < T $(: $tbound1:ident $(+ $tbound2:ident)*)* $(, $typaram:ident : $bound:ident)* >) => {
+ ($ty:ident <T $(: $tbound1:ident $(+ $tbound2:ident)*)* $(, $typaram:ident : $bound:ident)*>) => {
+ impl<T $(, $typaram)*> Serialize for $ty<T $(, $typaram)*>
+ where
+ T: Serialize,
+ {
+ #[inline]
+ fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
+ where
+ S: Serializer,
+ {
+ serializer.collect_seq(self)
+ }
+ }
+ }
+}
+
+#[cfg(all(any(feature = "std", feature = "alloc"), no_relaxed_trait_bounds))]
+macro_rules! seq_impl {
+ ($ty:ident <T $(: $tbound1:ident $(+ $tbound2:ident)*)* $(, $typaram:ident : $bound:ident)*>) => {
impl<T $(, $typaram)*> Serialize for $ty<T $(, $typaram)*>
where
T: Serialize $(+ $tbound1 $(+ $tbound2)*)*,
@@ -347,9 +365,28 @@ tuple_impls! {
////////////////////////////////////////////////////////////////////////////////
-#[cfg(any(feature = "std", feature = "alloc"))]
+#[cfg(all(any(feature = "std", feature = "alloc"), not(no_relaxed_trait_bounds)))]
+macro_rules! map_impl {
+ ($ty:ident <K $(: $kbound1:ident $(+ $kbound2:ident)*)*, V $(, $typaram:ident : $bound:ident)*>) => {
+ impl<K, V $(, $typaram)*> Serialize for $ty<K, V $(, $typaram)*>
+ where
+ K: Serialize,
+ V: Serialize,
+ {
+ #[inline]
+ fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
+ where
+ S: Serializer,
+ {
+ serializer.collect_map(self)
+ }
+ }
+ }
+}
+
+#[cfg(all(any(feature = "std", feature = "alloc"), no_relaxed_trait_bounds))]
macro_rules! map_impl {
- ($ty:ident < K $(: $kbound1:ident $(+ $kbound2:ident)*)*, V $(, $typaram:ident : $bound:ident)* >) => {
+ ($ty:ident <K $(: $kbound1:ident $(+ $kbound2:ident)*)*, V $(, $typaram:ident : $bound:ident)*>) => {
impl<K, V $(, $typaram)*> Serialize for $ty<K, V $(, $typaram)*>
where
K: Serialize $(+ $kbound1 $(+ $kbound2)*)*,
@@ -465,7 +502,7 @@ where
////////////////////////////////////////////////////////////////////////////////
macro_rules! nonzero_integers {
- ( $( $T: ident, )+ ) => {
+ ($($T:ident,)+) => {
$(
#[cfg(not(no_num_nonzero))]
impl Serialize for num::$T {
@@ -736,8 +773,9 @@ impl Serialize for net::Ipv4Addr {
// Skip over delimiters that we initialized buf with
written += format_u8(*oct, &mut buf[written + 1..]) + 1;
}
- // We've only written ASCII bytes to the buffer, so it is valid UTF-8
- serializer.serialize_str(unsafe { str::from_utf8_unchecked(&buf[..written]) })
+ // Safety: We've only written ASCII bytes to the buffer, so it is valid UTF-8
+ let buf = unsafe { str::from_utf8_unchecked(&buf[..written]) };
+ serializer.serialize_str(buf)
} else {
self.octets().serialize(serializer)
}
@@ -909,8 +947,9 @@ where
#[cfg(all(feature = "std", not(no_std_atomic)))]
macro_rules! atomic_impl {
- ($($ty:ident)*) => {
+ ($($ty:ident $size:expr)*) => {
$(
+ #[cfg(any(no_target_has_atomic, target_has_atomic = $size))]
impl Serialize for $ty {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
@@ -926,12 +965,19 @@ macro_rules! atomic_impl {
#[cfg(all(feature = "std", not(no_std_atomic)))]
atomic_impl! {
- AtomicBool
- AtomicI8 AtomicI16 AtomicI32 AtomicIsize
- AtomicU8 AtomicU16 AtomicU32 AtomicUsize
+ AtomicBool "8"
+ AtomicI8 "8"
+ AtomicI16 "16"
+ AtomicI32 "32"
+ AtomicIsize "ptr"
+ AtomicU8 "8"
+ AtomicU16 "16"
+ AtomicU32 "32"
+ AtomicUsize "ptr"
}
#[cfg(all(feature = "std", not(no_std_atomic64)))]
atomic_impl! {
- AtomicI64 AtomicU64
+ AtomicI64 "64"
+ AtomicU64 "64"
}
diff --git a/vendor/serde/src/ser/mod.rs b/vendor/serde/src/ser/mod.rs
index 9a21363d6..5c45426e8 100644
--- a/vendor/serde/src/ser/mod.rs
+++ b/vendor/serde/src/ser/mod.rs
@@ -115,10 +115,13 @@ mod impossible;
pub use self::impossible::Impossible;
+#[cfg(all(feature = "unstable", not(feature = "std")))]
+#[doc(inline)]
+pub use core::error::Error as StdError;
#[cfg(feature = "std")]
#[doc(no_inline)]
pub use std::error::Error as StdError;
-#[cfg(not(feature = "std"))]
+#[cfg(not(any(feature = "std", feature = "unstable")))]
#[doc(no_inline)]
pub use std_error::Error as StdError;
@@ -191,8 +194,8 @@ declare_error_trait!(Error: Sized + Debug + Display);
/// by Serde.
///
/// Serde provides `Serialize` implementations for many Rust primitive and
-/// standard library types. The complete list is [here][ser]. All of these can
-/// be serialized using Serde out of the box.
+/// standard library types. The complete list is [here][crate::ser]. All of
+/// these can be serialized using Serde out of the box.
///
/// Additionally, Serde provides a procedural macro called [`serde_derive`] to
/// automatically generate `Serialize` implementations for structs and enums in
@@ -212,7 +215,6 @@ declare_error_trait!(Error: Sized + Debug + Display);
/// [`linked-hash-map`]: https://crates.io/crates/linked-hash-map
/// [`serde_derive`]: https://crates.io/crates/serde_derive
/// [derive section of the manual]: https://serde.rs/derive.html
-/// [ser]: https://docs.serde.rs/serde/ser/index.html
pub trait Serialize {
/// Serialize this value into the given Serde serializer.
///
diff --git a/vendor/serde_derive/.cargo-checksum.json b/vendor/serde_derive/.cargo-checksum.json
index 55e1585d8..4f033d7fe 100644
--- a/vendor/serde_derive/.cargo-checksum.json
+++ b/vendor/serde_derive/.cargo-checksum.json
@@ -1 +1 @@
-{"files":{"Cargo.toml":"74849419177cf3d29dc77892c9519708ac38eecd3c2d4e4367de3c171cd2d410","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"23f18e03dc49df91622fe2a76176497404e46ced8a715d9d2b67a7446571cca3","README.md":"7049b88cb7366be0c8e593f3ffffa313803a5b382f35686c542b4a0da3b291f3","build.rs":"c01db20e19c31505b26b9e9a5aff1c5327a7501fc88917f372a9e718edcb50ab","crates-io.md":"5c42406936cf9af6d4cd7fe0ac730c609e82fd3f15a54549518c72d0ded70c29","src/bound.rs":"268b4995a5d0a129dcbd6e32ef11f587bd271df3f6c4f7230ed54bc99f5ce871","src/de.rs":"c5a41016ce15f8176a2d7a8445ba06d2eb8de0863c1fea0dab51c395dd7dccff","src/dummy.rs":"cb154465020973be8ab6079ab8574df46f38fbe028a5561cd6b1a8bfa1a35478","src/fragment.rs":"5548ba65a53d90a296f60c1328a7a7fb040db467f59c2f5210b2fb320457145d","src/internals/ast.rs":"b019865eef92c1ddbb9029423ac22179f132dc655a51c09fb2a42f4aaef172fd","src/internals/attr.rs":"778074380c4e353b77e03aff9edf15fda9e15a0e7ec25cdfc51d79a26636ddef","src/internals/case.rs":"9492f0c5142d7b7e8cd39c86d13a855e5ce4489425adb2b96aed89e1b7851ac0","src/internals/check.rs":"11ea94257d2a2ee2276938a6beb4ae11b74c39225c1e342e6df1e7d2b2924496","src/internals/ctxt.rs":"6fa544ae52914498a62a395818ebdc1b36ac2fb5903c60afb741a864ad559f1c","src/internals/mod.rs":"f32138ff19d57eb00f88ba11f6b015efab2102657804f71ebbf386a3698dad91","src/internals/receiver.rs":"cd125ba4a3dd6250ed4737555c58627bffd630a536cd7223068eed7c10a170d8","src/internals/respan.rs":"899753859c58ce5f532a3ec4584796a52f13ed5a0533191e48c953ba5c1b52ff","src/internals/symbol.rs":"3c9ce461773b7df3bb64d82aa5a0d93052c3bb0e60209db6c0b5c10ee9cfc9cf","src/lib.rs":"82c587dfec75c78b53fc64ab9366f61213f2776cefea256c9eaeb18193c8cbf4","src/pretend.rs":"4aa53bf6c1350fbcfc8c4997f720cde61a8eb3aab73bb8c101b0f0a74901892b","src/ser.rs":"0d99c841f6c7bc9751ab225fe42d1f8b7fe56e36903efcb4ff10bf6e35c390ba","src/try.rs":"b171b0088c23ebf4bfa07ba457881b41ac5e547d55dd16f737ea988d34badf61"},"package":"4f1d362ca8fc9c3e3a7484440752472d68a6caa98f1ab81d99b5dfe517cec852"} \ No newline at end of file
+{"files":{"Cargo.toml":"72ed2b0578c6c4fbbd14ab2062502092990c48f4687a01a4a07d7fdbb6330756","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"23f18e03dc49df91622fe2a76176497404e46ced8a715d9d2b67a7446571cca3","README.md":"3c12b60b6c77a201665344a7612b42392e77ddc3e907f5a14e3f3a4bb6c4692e","build.rs":"d9a0df0c4dd552ff7fd0c3b3828cb1fff4fc4ab15bd98539881929b76b98003b","crates-io.md":"ee22254ee64c3189eef3e707c8d75dc66a8df2a7ee9e518d95238950780ec387","src/bound.rs":"268b4995a5d0a129dcbd6e32ef11f587bd271df3f6c4f7230ed54bc99f5ce871","src/de.rs":"b28c2fcf5214d33ba1dc855b60634db18608a26f39f9f92bbedf62c456fa8d10","src/dummy.rs":"cb154465020973be8ab6079ab8574df46f38fbe028a5561cd6b1a8bfa1a35478","src/fragment.rs":"5548ba65a53d90a296f60c1328a7a7fb040db467f59c2f5210b2fb320457145d","src/internals/ast.rs":"b019865eef92c1ddbb9029423ac22179f132dc655a51c09fb2a42f4aaef172fd","src/internals/attr.rs":"778074380c4e353b77e03aff9edf15fda9e15a0e7ec25cdfc51d79a26636ddef","src/internals/case.rs":"9492f0c5142d7b7e8cd39c86d13a855e5ce4489425adb2b96aed89e1b7851ac0","src/internals/check.rs":"6b84278b034a156784fc56153df3def1660bcfcfde0cd59f8facce1750717c7d","src/internals/ctxt.rs":"6fa544ae52914498a62a395818ebdc1b36ac2fb5903c60afb741a864ad559f1c","src/internals/mod.rs":"f32138ff19d57eb00f88ba11f6b015efab2102657804f71ebbf386a3698dad91","src/internals/receiver.rs":"cd125ba4a3dd6250ed4737555c58627bffd630a536cd7223068eed7c10a170d8","src/internals/respan.rs":"899753859c58ce5f532a3ec4584796a52f13ed5a0533191e48c953ba5c1b52ff","src/internals/symbol.rs":"3c9ce461773b7df3bb64d82aa5a0d93052c3bb0e60209db6c0b5c10ee9cfc9cf","src/lib.rs":"6a80c0114dcf9924cbbbc03f443cfd0d299be9f89ba6c4fdc2867d990aba5063","src/pretend.rs":"4aa53bf6c1350fbcfc8c4997f720cde61a8eb3aab73bb8c101b0f0a74901892b","src/ser.rs":"8f9ffe1d8bcd28bd40e8d94d688547fa1d518cc722d0292f47d951152c406dd9","src/this.rs":"a2c128955324c2994ed7cdc3fe4eeceb7ad8a0f9d071665a8378c85c8df64ce2","src/try.rs":"b171b0088c23ebf4bfa07ba457881b41ac5e547d55dd16f737ea988d34badf61"},"package":"af487d118eecd09402d70a5d72551860e788df87b464af30e5ea6a38c75c541e"} \ No newline at end of file
diff --git a/vendor/serde_derive/Cargo.toml b/vendor/serde_derive/Cargo.toml
index dc5abf1b4..6258d9df1 100644
--- a/vendor/serde_derive/Cargo.toml
+++ b/vendor/serde_derive/Cargo.toml
@@ -12,7 +12,7 @@
[package]
rust-version = "1.31"
name = "serde_derive"
-version = "1.0.147"
+version = "1.0.152"
authors = [
"Erick Tryzelaar <erick.tryzelaar@gmail.com>",
"David Tolnay <dtolnay@gmail.com>",
@@ -53,7 +53,7 @@ version = "1.0"
version = "1.0"
[dependencies.syn]
-version = "1.0.90"
+version = "1.0.104"
[dev-dependencies.serde]
version = "1.0"
diff --git a/vendor/serde_derive/README.md b/vendor/serde_derive/README.md
index 79409a3fc..c3f6575ef 100644
--- a/vendor/serde_derive/README.md
+++ b/vendor/serde_derive/README.md
@@ -1,6 +1,6 @@
# Serde &emsp; [![Build Status]][actions] [![Latest Version]][crates.io] [![serde: rustc 1.13+]][Rust 1.13] [![serde_derive: rustc 1.31+]][Rust 1.31]
-[Build Status]: https://img.shields.io/github/workflow/status/serde-rs/serde/CI/master
+[Build Status]: https://img.shields.io/github/actions/workflow/status/serde-rs/serde/ci.yml?branch=master
[actions]: https://github.com/serde-rs/serde/actions?query=branch%3Amaster
[Latest Version]: https://img.shields.io/crates/v/serde.svg
[crates.io]: https://crates.io/crates/serde
@@ -19,7 +19,7 @@ You may be looking for:
- [Data formats supported by Serde](https://serde.rs/#data-formats)
- [Setting up `#[derive(Serialize, Deserialize)]`](https://serde.rs/derive.html)
- [Examples](https://serde.rs/examples.html)
-- [API documentation](https://docs.serde.rs/serde/)
+- [API documentation](https://docs.rs/serde)
- [Release notes](https://github.com/serde-rs/serde/releases)
## Serde in action
diff --git a/vendor/serde_derive/build.rs b/vendor/serde_derive/build.rs
index 2aece0469..1249dab59 100644
--- a/vendor/serde_derive/build.rs
+++ b/vendor/serde_derive/build.rs
@@ -6,6 +6,8 @@ use std::str;
// opening a GitHub issue if your build environment requires some way to enable
// these cfgs other than by executing our build script.
fn main() {
+ println!("cargo:rerun-if-changed=build.rs");
+
let minor = match rustc_minor_version() {
Some(minor) => minor,
None => return,
diff --git a/vendor/serde_derive/crates-io.md b/vendor/serde_derive/crates-io.md
index b57bc5fd0..6e0ec280c 100644
--- a/vendor/serde_derive/crates-io.md
+++ b/vendor/serde_derive/crates-io.md
@@ -10,7 +10,7 @@ You may be looking for:
- [Data formats supported by Serde](https://serde.rs/#data-formats)
- [Setting up `#[derive(Serialize, Deserialize)]`](https://serde.rs/derive.html)
- [Examples](https://serde.rs/examples.html)
-- [API documentation](https://docs.serde.rs/serde/)
+- [API documentation](https://docs.rs/serde)
- [Release notes](https://github.com/serde-rs/serde/releases)
## Serde in action
diff --git a/vendor/serde_derive/src/de.rs b/vendor/serde_derive/src/de.rs
index ff7bc42f4..a703adaf7 100644
--- a/vendor/serde_derive/src/de.rs
+++ b/vendor/serde_derive/src/de.rs
@@ -10,6 +10,7 @@ use fragment::{Expr, Fragment, Match, Stmts};
use internals::ast::{Container, Data, Field, Style, Variant};
use internals::{attr, replace_receiver, ungroup, Ctxt, Derive};
use pretend;
+use this;
use std::collections::BTreeSet;
use std::ptr;
@@ -111,9 +112,13 @@ struct Parameters {
local: syn::Ident,
/// Path to the type the impl is for. Either a single `Ident` for local
- /// types or `some::remote::Ident` for remote types. Does not include
- /// generic parameters.
- this: syn::Path,
+ /// types (does not include generic parameters) or `some::remote::Path` for
+ /// remote types.
+ this_type: syn::Path,
+
+ /// Same as `this_type` but using `::<T>` for generic parameters for use in
+ /// expression position.
+ this_value: syn::Path,
/// Generics including any explicit and inferred bounds for the impl.
generics: syn::Generics,
@@ -133,10 +138,8 @@ struct Parameters {
impl Parameters {
fn new(cont: &Container) -> Self {
let local = cont.ident.clone();
- let this = match cont.attrs.remote() {
- Some(remote) => remote.clone(),
- None => cont.ident.clone().into(),
- };
+ let this_type = this::this_type(cont);
+ let this_value = this::this_value(cont);
let borrowed = borrowed_lifetimes(cont);
let generics = build_generics(cont, &borrowed);
let has_getter = cont.data.has_getter();
@@ -144,7 +147,8 @@ impl Parameters {
Parameters {
local,
- this,
+ this_type,
+ this_value,
generics,
borrowed,
has_getter,
@@ -155,7 +159,7 @@ impl Parameters {
/// Type name to use in error messages and `&'static str` arguments to
/// various Deserializer methods.
fn type_name(&self) -> String {
- self.this.segments.last().unwrap().ident.to_string()
+ self.this_type.segments.last().unwrap().ident.to_string()
}
}
@@ -358,7 +362,7 @@ fn deserialize_transparent(cont: &Container, params: &Parameters) -> Fragment {
Data::Enum(_) => unreachable!(),
};
- let this = &params.this;
+ let this_value = &params.this_value;
let transparent_field = fields.iter().find(|f| f.attrs.transparent()).unwrap();
let path = match transparent_field.attrs.deserialize_with() {
@@ -386,7 +390,7 @@ fn deserialize_transparent(cont: &Container, params: &Parameters) -> Fragment {
quote_block! {
_serde::__private::Result::map(
#path(__deserializer),
- |__transparent| #this { #(#assign),* })
+ |__transparent| #this_value { #(#assign),* })
}
}
@@ -407,7 +411,8 @@ fn deserialize_try_from(type_try_from: &syn::Type) -> Fragment {
}
fn deserialize_unit_struct(params: &Parameters, cattrs: &attr::Container) -> Fragment {
- let this = &params.this;
+ let this_type = &params.this_type;
+ let this_value = &params.this_value;
let type_name = cattrs.name().deserialize_name();
let expecting = format!("unit struct {}", params.type_name());
@@ -417,7 +422,7 @@ fn deserialize_unit_struct(params: &Parameters, cattrs: &attr::Container) -> Fra
struct __Visitor;
impl<'de> _serde::de::Visitor<'de> for __Visitor {
- type Value = #this;
+ type Value = #this_type;
fn expecting(&self, __formatter: &mut _serde::__private::Formatter) -> _serde::__private::fmt::Result {
_serde::__private::Formatter::write_str(__formatter, #expecting)
@@ -428,7 +433,7 @@ fn deserialize_unit_struct(params: &Parameters, cattrs: &attr::Container) -> Fra
where
__E: _serde::de::Error,
{
- _serde::__private::Ok(#this)
+ _serde::__private::Ok(#this_value)
}
}
@@ -443,7 +448,8 @@ fn deserialize_tuple(
cattrs: &attr::Container,
deserializer: Option<TokenStream>,
) -> Fragment {
- let this = &params.this;
+ let this_type = &params.this_type;
+ let this_value = &params.this_value;
let (de_impl_generics, de_ty_generics, ty_generics, where_clause) =
split_with_de_lifetime(params);
let delife = params.borrowed.de_lifetime();
@@ -457,7 +463,7 @@ fn deserialize_tuple(
let local = &params.local;
quote!(#local)
} else {
- quote!(#this)
+ quote!(#this_value)
};
let is_enum = variant_ident.is_some();
@@ -485,7 +491,7 @@ fn deserialize_tuple(
let visitor_expr = quote! {
__Visitor {
- marker: _serde::__private::PhantomData::<#this #ty_generics>,
+ marker: _serde::__private::PhantomData::<#this_type #ty_generics>,
lifetime: _serde::__private::PhantomData,
}
};
@@ -510,12 +516,12 @@ fn deserialize_tuple(
quote_block! {
struct __Visitor #de_impl_generics #where_clause {
- marker: _serde::__private::PhantomData<#this #ty_generics>,
+ marker: _serde::__private::PhantomData<#this_type #ty_generics>,
lifetime: _serde::__private::PhantomData<&#delife ()>,
}
impl #de_impl_generics _serde::de::Visitor<#delife> for __Visitor #de_ty_generics #where_clause {
- type Value = #this #ty_generics;
+ type Value = #this_type #ty_generics;
fn expecting(&self, __formatter: &mut _serde::__private::Formatter) -> _serde::__private::fmt::Result {
_serde::__private::Formatter::write_str(__formatter, #expecting)
@@ -544,7 +550,7 @@ fn deserialize_tuple_in_place(
cattrs: &attr::Container,
deserializer: Option<TokenStream>,
) -> Fragment {
- let this = &params.this;
+ let this_type = &params.this_type;
let (de_impl_generics, de_ty_generics, ty_generics, where_clause) =
split_with_de_lifetime(params);
let delife = params.borrowed.de_lifetime();
@@ -600,7 +606,7 @@ fn deserialize_tuple_in_place(
quote_block! {
struct __Visitor #in_place_impl_generics #where_clause {
- place: &#place_life mut #this #ty_generics,
+ place: &#place_life mut #this_type #ty_generics,
lifetime: _serde::__private::PhantomData<&#delife ()>,
}
@@ -705,9 +711,10 @@ fn deserialize_seq(
};
if params.has_getter {
- let this = &params.this;
+ let this_type = &params.this_type;
+ let (_, ty_generics, _) = params.generics.split_for_impl();
result = quote! {
- _serde::__private::Into::<#this>::into(#result)
+ _serde::__private::Into::<#this_type #ty_generics>::into(#result)
};
}
@@ -801,14 +808,14 @@ fn deserialize_seq_in_place(
}
});
- let this = &params.this;
+ let this_type = &params.this_type;
let (_, ty_generics, _) = params.generics.split_for_impl();
let let_default = match cattrs.default() {
attr::Default::Default => Some(quote!(
- let __default: #this #ty_generics = _serde::__private::Default::default();
+ let __default: #this_type #ty_generics = _serde::__private::Default::default();
)),
attr::Default::Path(path) => Some(quote!(
- let __default: #this #ty_generics = #path();
+ let __default: #this_type #ty_generics = #path();
)),
attr::Default::None => {
// We don't need the default value, to prevent an unused variable warning
@@ -849,9 +856,10 @@ fn deserialize_newtype_struct(
let mut result = quote!(#type_path(__field0));
if params.has_getter {
- let this = &params.this;
+ let this_type = &params.this_type;
+ let (_, ty_generics, _) = params.generics.split_for_impl();
result = quote! {
- _serde::__private::Into::<#this>::into(#result)
+ _serde::__private::Into::<#this_type #ty_generics>::into(#result)
};
}
@@ -901,7 +909,8 @@ fn deserialize_struct(
) -> Fragment {
let is_enum = variant_ident.is_some();
- let this = &params.this;
+ let this_type = &params.this_type;
+ let this_value = &params.this_value;
let (de_impl_generics, de_ty_generics, ty_generics, where_clause) =
split_with_de_lifetime(params);
let delife = params.borrowed.de_lifetime();
@@ -913,7 +922,7 @@ fn deserialize_struct(
let local = &params.local;
quote!(#local)
} else {
- quote!(#this)
+ quote!(#this_value)
};
let type_path = match variant_ident {
@@ -941,7 +950,7 @@ fn deserialize_struct(
let visitor_expr = quote! {
__Visitor {
- marker: _serde::__private::PhantomData::<#this #ty_generics>,
+ marker: _serde::__private::PhantomData::<#this_type #ty_generics>,
lifetime: _serde::__private::PhantomData,
}
};
@@ -993,7 +1002,7 @@ fn deserialize_struct(
let visitor_seed = if is_enum && cattrs.has_flatten() {
Some(quote! {
impl #de_impl_generics _serde::de::DeserializeSeed<#delife> for __Visitor #de_ty_generics #where_clause {
- type Value = #this #ty_generics;
+ type Value = #this_type #ty_generics;
fn deserialize<__D>(self, __deserializer: __D) -> _serde::__private::Result<Self::Value, __D::Error>
where
@@ -1011,12 +1020,12 @@ fn deserialize_struct(
#field_visitor
struct __Visitor #de_impl_generics #where_clause {
- marker: _serde::__private::PhantomData<#this #ty_generics>,
+ marker: _serde::__private::PhantomData<#this_type #ty_generics>,
lifetime: _serde::__private::PhantomData<&#delife ()>,
}
impl #de_impl_generics _serde::de::Visitor<#delife> for __Visitor #de_ty_generics #where_clause {
- type Value = #this #ty_generics;
+ type Value = #this_type #ty_generics;
fn expecting(&self, __formatter: &mut _serde::__private::Formatter) -> _serde::__private::fmt::Result {
_serde::__private::Formatter::write_str(__formatter, #expecting)
@@ -1057,7 +1066,7 @@ fn deserialize_struct_in_place(
return None;
}
- let this = &params.this;
+ let this_type = &params.this_type;
let (de_impl_generics, de_ty_generics, ty_generics, where_clause) =
split_with_de_lifetime(params);
let delife = params.borrowed.de_lifetime();
@@ -1123,7 +1132,7 @@ fn deserialize_struct_in_place(
#field_visitor
struct __Visitor #in_place_impl_generics #where_clause {
- place: &#place_life mut #this #ty_generics,
+ place: &#place_life mut #this_type #ty_generics,
lifetime: _serde::__private::PhantomData<&#delife ()>,
}
@@ -1212,7 +1221,7 @@ fn deserialize_externally_tagged_enum(
variants: &[Variant],
cattrs: &attr::Container,
) -> Fragment {
- let this = &params.this;
+ let this_type = &params.this_type;
let (de_impl_generics, de_ty_generics, ty_generics, where_clause) =
split_with_de_lifetime(params);
let delife = params.borrowed.de_lifetime();
@@ -1266,12 +1275,12 @@ fn deserialize_externally_tagged_enum(
#variant_visitor
struct __Visitor #de_impl_generics #where_clause {
- marker: _serde::__private::PhantomData<#this #ty_generics>,
+ marker: _serde::__private::PhantomData<#this_type #ty_generics>,
lifetime: _serde::__private::PhantomData<&#delife ()>,
}
impl #de_impl_generics _serde::de::Visitor<#delife> for __Visitor #de_ty_generics #where_clause {
- type Value = #this #ty_generics;
+ type Value = #this_type #ty_generics;
fn expecting(&self, __formatter: &mut _serde::__private::Formatter) -> _serde::__private::fmt::Result {
_serde::__private::Formatter::write_str(__formatter, #expecting)
@@ -1292,7 +1301,7 @@ fn deserialize_externally_tagged_enum(
#type_name,
VARIANTS,
__Visitor {
- marker: _serde::__private::PhantomData::<#this #ty_generics>,
+ marker: _serde::__private::PhantomData::<#this_type #ty_generics>,
lifetime: _serde::__private::PhantomData,
},
)
@@ -1354,7 +1363,8 @@ fn deserialize_adjacently_tagged_enum(
tag: &str,
content: &str,
) -> Fragment {
- let this = &params.this;
+ let this_type = &params.this_type;
+ let this_value = &params.this_value;
let (de_impl_generics, de_ty_generics, ty_generics, where_clause) =
split_with_de_lifetime(params);
let delife = params.borrowed.de_lifetime();
@@ -1415,13 +1425,13 @@ fn deserialize_adjacently_tagged_enum(
let arm = match variant.style {
Style::Unit => quote! {
- _serde::__private::Ok(#this::#variant_ident)
+ _serde::__private::Ok(#this_value::#variant_ident)
},
Style::Newtype if variant.attrs.deserialize_with().is_none() => {
let span = variant.original.span();
let func = quote_spanned!(span=> _serde::__private::de::missing_field);
quote! {
- #func(#content).map(#this::#variant_ident)
+ #func(#content).map(#this_value::#variant_ident)
}
}
_ => {
@@ -1513,12 +1523,12 @@ fn deserialize_adjacently_tagged_enum(
struct __Seed #de_impl_generics #where_clause {
field: __Field,
- marker: _serde::__private::PhantomData<#this #ty_generics>,
+ marker: _serde::__private::PhantomData<#this_type #ty_generics>,
lifetime: _serde::__private::PhantomData<&#delife ()>,
}
impl #de_impl_generics _serde::de::DeserializeSeed<#delife> for __Seed #de_ty_generics #where_clause {
- type Value = #this #ty_generics;
+ type Value = #this_type #ty_generics;
fn deserialize<__D>(self, __deserializer: __D) -> _serde::__private::Result<Self::Value, __D::Error>
where
@@ -1531,12 +1541,12 @@ fn deserialize_adjacently_tagged_enum(
}
struct __Visitor #de_impl_generics #where_clause {
- marker: _serde::__private::PhantomData<#this #ty_generics>,
+ marker: _serde::__private::PhantomData<#this_type #ty_generics>,
lifetime: _serde::__private::PhantomData<&#delife ()>,
}
impl #de_impl_generics _serde::de::Visitor<#delife> for __Visitor #de_ty_generics #where_clause {
- type Value = #this #ty_generics;
+ type Value = #this_type #ty_generics;
fn expecting(&self, __formatter: &mut _serde::__private::Formatter) -> _serde::__private::fmt::Result {
_serde::__private::Formatter::write_str(__formatter, #expecting)
@@ -1638,7 +1648,7 @@ fn deserialize_adjacently_tagged_enum(
#type_name,
FIELDS,
__Visitor {
- marker: _serde::__private::PhantomData::<#this #ty_generics>,
+ marker: _serde::__private::PhantomData::<#this_type #ty_generics>,
lifetime: _serde::__private::PhantomData,
},
)
@@ -1707,10 +1717,10 @@ fn deserialize_externally_tagged_variant(
match variant.style {
Style::Unit => {
- let this = &params.this;
+ let this_value = &params.this_value;
quote_block! {
try!(_serde::de::VariantAccess::unit_variant(__variant));
- _serde::__private::Ok(#this::#variant_ident)
+ _serde::__private::Ok(#this_value::#variant_ident)
}
}
Style::Newtype => deserialize_externally_tagged_newtype_variant(
@@ -1749,7 +1759,7 @@ fn deserialize_internally_tagged_variant(
match effective_style(variant) {
Style::Unit => {
- let this = &params.this;
+ let this_value = &params.this_value;
let type_name = params.type_name();
let variant_name = variant.ident.to_string();
let default = variant.fields.get(0).map(|field| {
@@ -1758,7 +1768,7 @@ fn deserialize_internally_tagged_variant(
});
quote_block! {
try!(_serde::Deserializer::deserialize_any(#deserializer, _serde::__private::de::InternallyTaggedUnitVisitor::new(#type_name, #variant_name)));
- _serde::__private::Ok(#this::#variant_ident #default)
+ _serde::__private::Ok(#this_value::#variant_ident #default)
}
}
Style::Newtype => deserialize_untagged_newtype_variant(
@@ -1796,7 +1806,7 @@ fn deserialize_untagged_variant(
match effective_style(variant) {
Style::Unit => {
- let this = &params.this;
+ let this_value = &params.this_value;
let type_name = params.type_name();
let variant_name = variant.ident.to_string();
let default = variant.fields.get(0).map(|field| {
@@ -1808,7 +1818,7 @@ fn deserialize_untagged_variant(
#deserializer,
_serde::__private::de::UntaggedUnitVisitor::new(#type_name, #variant_name)
) {
- _serde::__private::Ok(()) => _serde::__private::Ok(#this::#variant_ident #default),
+ _serde::__private::Ok(()) => _serde::__private::Ok(#this_value::#variant_ident #default),
_serde::__private::Err(__err) => _serde::__private::Err(__err),
}
}
@@ -1843,14 +1853,13 @@ fn deserialize_externally_tagged_newtype_variant(
field: &Field,
cattrs: &attr::Container,
) -> Fragment {
- let this = &params.this;
+ let this_value = &params.this_value;
if field.attrs.skip_deserializing() {
- let this = &params.this;
let default = Expr(expr_is_missing(field, cattrs));
return quote_block! {
try!(_serde::de::VariantAccess::unit_variant(__variant));
- _serde::__private::Ok(#this::#variant_ident(#default))
+ _serde::__private::Ok(#this_value::#variant_ident(#default))
};
}
@@ -1861,7 +1870,7 @@ fn deserialize_externally_tagged_newtype_variant(
let func =
quote_spanned!(span=> _serde::de::VariantAccess::newtype_variant::<#field_ty>);
quote_expr! {
- _serde::__private::Result::map(#func(__variant), #this::#variant_ident)
+ _serde::__private::Result::map(#func(__variant), #this_value::#variant_ident)
}
}
Some(path) => {
@@ -1870,7 +1879,7 @@ fn deserialize_externally_tagged_newtype_variant(
#wrapper
_serde::__private::Result::map(
_serde::de::VariantAccess::newtype_variant::<#wrapper_ty>(__variant),
- |__wrapper| #this::#variant_ident(__wrapper.value))
+ |__wrapper| #this_value::#variant_ident(__wrapper.value))
}
}
}
@@ -1882,20 +1891,20 @@ fn deserialize_untagged_newtype_variant(
field: &Field,
deserializer: &TokenStream,
) -> Fragment {
- let this = &params.this;
+ let this_value = &params.this_value;
let field_ty = field.ty;
match field.attrs.deserialize_with() {
None => {
let span = field.original.span();
let func = quote_spanned!(span=> <#field_ty as _serde::Deserialize>::deserialize);
quote_expr! {
- _serde::__private::Result::map(#func(#deserializer), #this::#variant_ident)
+ _serde::__private::Result::map(#func(#deserializer), #this_value::#variant_ident)
}
}
Some(path) => {
quote_block! {
let __value: _serde::__private::Result<#field_ty, _> = #path(#deserializer);
- _serde::__private::Result::map(__value, #this::#variant_ident)
+ _serde::__private::Result::map(__value, #this_value::#variant_ident)
}
}
}
@@ -1907,7 +1916,7 @@ fn deserialize_generated_identifier(
is_variant: bool,
other_idx: Option<usize>,
) -> Fragment {
- let this = quote!(__Field);
+ let this_value = quote!(__Field);
let field_idents: &Vec<_> = &fields.iter().map(|(_, ident, _)| ident).collect();
let (ignore_variant, fallthrough) = if !is_variant && cattrs.has_flatten() {
@@ -1927,7 +1936,7 @@ fn deserialize_generated_identifier(
};
let visitor_impl = Stmts(deserialize_identifier(
- &this,
+ &this_value,
fields,
is_variant,
fallthrough,
@@ -1982,8 +1991,8 @@ fn deserialize_custom_identifier(
attr::Identifier::No => unreachable!(),
};
- let this = &params.this;
- let this = quote!(#this);
+ let this_type = params.this_type.to_token_stream();
+ let this_value = params.this_value.to_token_stream();
let (ordinary, fallthrough, fallthrough_borrowed) = if let Some(last) = variants.last() {
let last_ident = &last.ident;
@@ -1992,7 +2001,7 @@ fn deserialize_custom_identifier(
// last variant (checked in `check_identifier`), so all preceding
// are ordinary variants.
let ordinary = &variants[..variants.len() - 1];
- let fallthrough = quote!(_serde::__private::Ok(#this::#last_ident));
+ let fallthrough = quote!(_serde::__private::Ok(#this_value::#last_ident));
(ordinary, Some(fallthrough), None)
} else if let Style::Newtype = last.style {
let ordinary = &variants[..variants.len() - 1];
@@ -2002,7 +2011,7 @@ fn deserialize_custom_identifier(
_serde::Deserialize::deserialize(
_serde::__private::de::IdentifierDeserializer::from(#value)
),
- #this::#last_ident)
+ #this_value::#last_ident)
}
};
(
@@ -2050,7 +2059,7 @@ fn deserialize_custom_identifier(
split_with_de_lifetime(params);
let delife = params.borrowed.de_lifetime();
let visitor_impl = Stmts(deserialize_identifier(
- &this,
+ &this_value,
&names_idents,
is_variant,
fallthrough,
@@ -2063,18 +2072,18 @@ fn deserialize_custom_identifier(
#names_const
struct __FieldVisitor #de_impl_generics #where_clause {
- marker: _serde::__private::PhantomData<#this #ty_generics>,
+ marker: _serde::__private::PhantomData<#this_type #ty_generics>,
lifetime: _serde::__private::PhantomData<&#delife ()>,
}
impl #de_impl_generics _serde::de::Visitor<#delife> for __FieldVisitor #de_ty_generics #where_clause {
- type Value = #this #ty_generics;
+ type Value = #this_type #ty_generics;
#visitor_impl
}
let __visitor = __FieldVisitor {
- marker: _serde::__private::PhantomData::<#this #ty_generics>,
+ marker: _serde::__private::PhantomData::<#this_type #ty_generics>,
lifetime: _serde::__private::PhantomData,
};
_serde::Deserializer::deserialize_identifier(__deserializer, __visitor)
@@ -2082,7 +2091,7 @@ fn deserialize_custom_identifier(
}
fn deserialize_identifier(
- this: &TokenStream,
+ this_value: &TokenStream,
fields: &[(String, Ident, Vec<String>)],
is_variant: bool,
fallthrough: Option<TokenStream>,
@@ -2103,11 +2112,11 @@ fn deserialize_identifier(
let constructors: &Vec<_> = &flat_fields
.iter()
- .map(|(_, ident)| quote!(#this::#ident))
+ .map(|(_, ident)| quote!(#this_value::#ident))
.collect();
let main_constructors: &Vec<_> = &fields
.iter()
- .map(|(_, ident, _)| quote!(#this::#ident))
+ .map(|(_, ident, _)| quote!(#this_value::#ident))
.collect();
let expecting = expecting.unwrap_or(if is_variant {
@@ -2621,9 +2630,10 @@ fn deserialize_map(
let mut result = quote!(#struct_path { #(#result),* });
if params.has_getter {
- let this = &params.this;
+ let this_type = &params.this_type;
+ let (_, ty_generics, _) = params.generics.split_for_impl();
result = quote! {
- _serde::__private::Into::<#this>::into(#result)
+ _serde::__private::Into::<#this_type #ty_generics>::into(#result)
};
}
@@ -2803,15 +2813,15 @@ fn deserialize_map_in_place(
}
});
- let this = &params.this;
+ let this_type = &params.this_type;
let (_, _, ty_generics, _) = split_with_de_lifetime(params);
let let_default = match cattrs.default() {
attr::Default::Default => Some(quote!(
- let __default: #this #ty_generics = _serde::__private::Default::default();
+ let __default: #this_type #ty_generics = _serde::__private::Default::default();
)),
attr::Default::Path(path) => Some(quote!(
- let __default: #this #ty_generics = #path();
+ let __default: #this_type #ty_generics = #path();
)),
attr::Default::None => {
// We don't need the default value, to prevent an unused variable warning
@@ -2844,7 +2854,7 @@ fn wrap_deserialize_with(
value_ty: &TokenStream,
deserialize_with: &syn::ExprPath,
) -> (TokenStream, TokenStream) {
- let this = &params.this;
+ let this_type = &params.this_type;
let (de_impl_generics, de_ty_generics, ty_generics, where_clause) =
split_with_de_lifetime(params);
let delife = params.borrowed.de_lifetime();
@@ -2852,7 +2862,7 @@ fn wrap_deserialize_with(
let wrapper = quote! {
struct __DeserializeWith #de_impl_generics #where_clause {
value: #value_ty,
- phantom: _serde::__private::PhantomData<#this #ty_generics>,
+ phantom: _serde::__private::PhantomData<#this_type #ty_generics>,
lifetime: _serde::__private::PhantomData<&#delife ()>,
}
@@ -2903,7 +2913,7 @@ fn unwrap_to_variant_closure(
variant: &Variant,
with_wrapper: bool,
) -> TokenStream {
- let this = &params.this;
+ let this_value = &params.this_value;
let variant_ident = &variant.ident;
let (arg, wrapper) = if with_wrapper {
@@ -2924,23 +2934,23 @@ fn unwrap_to_variant_closure(
Style::Struct if variant.fields.len() == 1 => {
let member = &variant.fields[0].member;
quote! {
- |#arg| #this::#variant_ident { #member: #wrapper }
+ |#arg| #this_value::#variant_ident { #member: #wrapper }
}
}
Style::Struct => {
let members = variant.fields.iter().map(|field| &field.member);
quote! {
- |#arg| #this::#variant_ident { #(#members: #wrapper.#field_access),* }
+ |#arg| #this_value::#variant_ident { #(#members: #wrapper.#field_access),* }
}
}
Style::Tuple => quote! {
- |#arg| #this::#variant_ident(#(#wrapper.#field_access),*)
+ |#arg| #this_value::#variant_ident(#(#wrapper.#field_access),*)
},
Style::Newtype => quote! {
- |#arg| #this::#variant_ident(#wrapper)
+ |#arg| #this_value::#variant_ident(#wrapper)
},
Style::Unit => quote! {
- |#arg| #this::#variant_ident
+ |#arg| #this_value::#variant_ident
},
}
}
diff --git a/vendor/serde_derive/src/internals/check.rs b/vendor/serde_derive/src/internals/check.rs
index 0e2484a79..eb1297aa7 100644
--- a/vendor/serde_derive/src/internals/check.rs
+++ b/vendor/serde_derive/src/internals/check.rs
@@ -6,6 +6,7 @@ use syn::{Member, Type};
/// Cross-cutting checks that require looking at more than a single attrs
/// object. Simpler checks should happen when parsing and building the attrs.
pub fn check(cx: &Ctxt, cont: &mut Container, derive: Derive) {
+ check_remote_generic(cx, cont);
check_getter(cx, cont);
check_flatten(cx, cont);
check_identifier(cx, cont);
@@ -16,6 +17,28 @@ pub fn check(cx: &Ctxt, cont: &mut Container, derive: Derive) {
check_from_and_try_from(cx, cont);
}
+/// Remote derive definition type must have either all of the generics of the
+/// remote type:
+///
+/// #[serde(remote = "Generic")]
+/// struct Generic<T> {…}
+///
+/// or none of them, i.e. defining impls for one concrete instantiation of the
+/// remote type only:
+///
+/// #[serde(remote = "Generic<T>")]
+/// struct ConcreteDef {…}
+///
+fn check_remote_generic(cx: &Ctxt, cont: &Container) {
+ if let Some(remote) = cont.attrs.remote() {
+ let local_has_generic = !cont.generics.params.is_empty();
+ let remote_has_generic = !remote.segments.last().unwrap().arguments.is_none();
+ if local_has_generic && remote_has_generic {
+ cx.error_spanned_by(remote, "remove generic parameters from this path");
+ }
+ }
+}
+
/// Getters are only allowed inside structs (not enums) with the `remote`
/// attribute.
fn check_getter(cx: &Ctxt, cont: &Container) {
diff --git a/vendor/serde_derive/src/lib.rs b/vendor/serde_derive/src/lib.rs
index fc8529e40..410078911 100644
--- a/vendor/serde_derive/src/lib.rs
+++ b/vendor/serde_derive/src/lib.rs
@@ -13,7 +13,7 @@
//!
//! [https://serde.rs/derive.html]: https://serde.rs/derive.html
-#![doc(html_root_url = "https://docs.rs/serde_derive/1.0.147")]
+#![doc(html_root_url = "https://docs.rs/serde_derive/1.0.152")]
#![allow(unknown_lints, bare_trait_objects)]
// Ignored clippy lints
#![allow(
@@ -43,7 +43,6 @@
clippy::enum_glob_use,
clippy::indexing_slicing,
clippy::items_after_statements,
- clippy::let_underscore_drop,
clippy::manual_assert,
clippy::map_err_ignore,
clippy::match_same_arms,
@@ -85,6 +84,7 @@ mod de;
mod dummy;
mod pretend;
mod ser;
+mod this;
mod try;
#[proc_macro_derive(Serialize, attributes(serde))]
diff --git a/vendor/serde_derive/src/ser.rs b/vendor/serde_derive/src/ser.rs
index 529a20d79..43695dd0c 100644
--- a/vendor/serde_derive/src/ser.rs
+++ b/vendor/serde_derive/src/ser.rs
@@ -8,6 +8,7 @@ use fragment::{Fragment, Match, Stmts};
use internals::ast::{Container, Data, Field, Style, Variant};
use internals::{attr, replace_receiver, Ctxt, Derive};
use pretend;
+use this;
pub fn expand_derive_serialize(
input: &mut syn::DeriveInput,
@@ -82,9 +83,13 @@ struct Parameters {
self_var: Ident,
/// Path to the type the impl is for. Either a single `Ident` for local
- /// types or `some::remote::Ident` for remote types. Does not include
- /// generic parameters.
- this: syn::Path,
+ /// types (does not include generic parameters) or `some::remote::Path` for
+ /// remote types.
+ this_type: syn::Path,
+
+ /// Same as `this_type` but using `::<T>` for generic parameters for use in
+ /// expression position.
+ this_value: syn::Path,
/// Generics including any explicit and inferred bounds for the impl.
generics: syn::Generics,
@@ -105,18 +110,15 @@ impl Parameters {
Ident::new("self", Span::call_site())
};
- let this = match cont.attrs.remote() {
- Some(remote) => remote.clone(),
- None => cont.ident.clone().into(),
- };
-
+ let this_type = this::this_type(cont);
+ let this_value = this::this_value(cont);
let is_packed = cont.attrs.is_packed();
-
let generics = build_generics(cont);
Parameters {
self_var,
- this,
+ this_type,
+ this_value,
generics,
is_remote,
is_packed,
@@ -126,7 +128,7 @@ impl Parameters {
/// Type name to use in error messages and `&'static str` arguments to
/// various Serializer methods.
fn type_name(&self) -> String {
- self.this.segments.last().unwrap().ident.to_string()
+ self.this_type.segments.last().unwrap().ident.to_string()
}
}
@@ -427,7 +429,7 @@ fn serialize_variant(
variant_index: u32,
cattrs: &attr::Container,
) -> TokenStream {
- let this = &params.this;
+ let this_value = &params.this_value;
let variant_ident = &variant.ident;
if variant.attrs.skip_serializing() {
@@ -445,32 +447,32 @@ fn serialize_variant(
Style::Struct => quote!({ .. }),
};
quote! {
- #this::#variant_ident #fields_pat => #skipped_err,
+ #this_value::#variant_ident #fields_pat => #skipped_err,
}
} else {
// variant wasn't skipped
let case = match variant.style {
Style::Unit => {
quote! {
- #this::#variant_ident
+ #this_value::#variant_ident
}
}
Style::Newtype => {
quote! {
- #this::#variant_ident(ref __field0)
+ #this_value::#variant_ident(ref __field0)
}
}
Style::Tuple => {
let field_names = (0..variant.fields.len())
.map(|i| Ident::new(&format!("__field{}", i), Span::call_site()));
quote! {
- #this::#variant_ident(#(ref #field_names),*)
+ #this_value::#variant_ident(#(ref #field_names),*)
}
}
Style::Struct => {
let members = variant.fields.iter().map(|f| &f.member);
quote! {
- #this::#variant_ident { #(ref #members),* }
+ #this_value::#variant_ident { #(ref #members),* }
}
}
};
@@ -640,7 +642,7 @@ fn serialize_adjacently_tagged_variant(
tag: &str,
content: &str,
) -> Fragment {
- let this = &params.this;
+ let this_type = &params.this_type;
let type_name = cattrs.name().serialize_name();
let variant_name = variant.attrs.name().serialize_name();
@@ -719,7 +721,7 @@ fn serialize_adjacently_tagged_variant(
quote_block! {
struct __AdjacentlyTagged #wrapper_generics #where_clause {
data: (#(&'__a #fields_ty,)*),
- phantom: _serde::__private::PhantomData<#this #ty_generics>,
+ phantom: _serde::__private::PhantomData<#this_type #ty_generics>,
}
impl #wrapper_impl_generics _serde::Serialize for __AdjacentlyTagged #wrapper_ty_generics #where_clause {
@@ -741,7 +743,7 @@ fn serialize_adjacently_tagged_variant(
try!(_serde::ser::SerializeStruct::serialize_field(
&mut __struct, #content, &__AdjacentlyTagged {
data: (#(#fields_ident,)*),
- phantom: _serde::__private::PhantomData::<#this #ty_generics>,
+ phantom: _serde::__private::PhantomData::<#this_type #ty_generics>,
}));
_serde::ser::SerializeStruct::end(__struct)
}
@@ -866,8 +868,8 @@ enum StructVariant<'a> {
Untagged,
}
-fn serialize_struct_variant<'a>(
- context: StructVariant<'a>,
+fn serialize_struct_variant(
+ context: StructVariant,
params: &Parameters,
fields: &[Field],
name: &str,
@@ -950,8 +952,8 @@ fn serialize_struct_variant<'a>(
}
}
-fn serialize_struct_variant_with_flatten<'a>(
- context: StructVariant<'a>,
+fn serialize_struct_variant_with_flatten(
+ context: StructVariant,
params: &Parameters,
fields: &[Field],
name: &str,
@@ -971,7 +973,7 @@ fn serialize_struct_variant_with_flatten<'a>(
variant_index,
variant_name,
} => {
- let this = &params.this;
+ let this_type = &params.this_type;
let fields_ty = fields.iter().map(|f| &f.ty);
let members = &fields.iter().map(|f| &f.member).collect::<Vec<_>>();
@@ -982,7 +984,7 @@ fn serialize_struct_variant_with_flatten<'a>(
quote_block! {
struct __EnumFlatten #wrapper_generics #where_clause {
data: (#(&'__a #fields_ty,)*),
- phantom: _serde::__private::PhantomData<#this #ty_generics>,
+ phantom: _serde::__private::PhantomData<#this_type #ty_generics>,
}
impl #wrapper_impl_generics _serde::Serialize for __EnumFlatten #wrapper_ty_generics #where_clause {
@@ -1006,7 +1008,7 @@ fn serialize_struct_variant_with_flatten<'a>(
#variant_name,
&__EnumFlatten {
data: (#(#members,)*),
- phantom: _serde::__private::PhantomData::<#this #ty_generics>,
+ phantom: _serde::__private::PhantomData::<#this_type #ty_generics>,
})
}
}
@@ -1192,7 +1194,7 @@ fn wrap_serialize_with(
field_tys: &[&syn::Type],
field_exprs: &[TokenStream],
) -> TokenStream {
- let this = &params.this;
+ let this_type = &params.this_type;
let (_, ty_generics, where_clause) = params.generics.split_for_impl();
let wrapper_generics = if field_exprs.is_empty() {
@@ -1212,7 +1214,7 @@ fn wrap_serialize_with(
quote!({
struct __SerializeWith #wrapper_impl_generics #where_clause {
values: (#(&'__a #field_tys, )*),
- phantom: _serde::__private::PhantomData<#this #ty_generics>,
+ phantom: _serde::__private::PhantomData<#this_type #ty_generics>,
}
impl #wrapper_impl_generics _serde::Serialize for __SerializeWith #wrapper_ty_generics #where_clause {
@@ -1226,7 +1228,7 @@ fn wrap_serialize_with(
&__SerializeWith {
values: (#(#field_exprs, )*),
- phantom: _serde::__private::PhantomData::<#this #ty_generics>,
+ phantom: _serde::__private::PhantomData::<#this_type #ty_generics>,
}
})
}
diff --git a/vendor/serde_derive/src/this.rs b/vendor/serde_derive/src/this.rs
new file mode 100644
index 000000000..32731d089
--- /dev/null
+++ b/vendor/serde_derive/src/this.rs
@@ -0,0 +1,32 @@
+use internals::ast::Container;
+use syn::{Path, PathArguments, Token};
+
+pub fn this_type(cont: &Container) -> Path {
+ if let Some(remote) = cont.attrs.remote() {
+ let mut this = remote.clone();
+ for segment in &mut this.segments {
+ if let PathArguments::AngleBracketed(arguments) = &mut segment.arguments {
+ arguments.colon2_token = None;
+ }
+ }
+ this
+ } else {
+ Path::from(cont.ident.clone())
+ }
+}
+
+pub fn this_value(cont: &Container) -> Path {
+ if let Some(remote) = cont.attrs.remote() {
+ let mut this = remote.clone();
+ for segment in &mut this.segments {
+ if let PathArguments::AngleBracketed(arguments) = &mut segment.arguments {
+ if arguments.colon2_token.is_none() {
+ arguments.colon2_token = Some(Token![::](arguments.lt_token.span));
+ }
+ }
+ }
+ this
+ } else {
+ Path::from(cont.ident.clone())
+ }
+}
diff --git a/vendor/serde_json/.cargo-checksum.json b/vendor/serde_json/.cargo-checksum.json
index 69f778237..023247168 100644
--- a/vendor/serde_json/.cargo-checksum.json
+++ b/vendor/serde_json/.cargo-checksum.json
@@ -1 +1 @@
-{"files":{"CONTRIBUTING.md":"f5270cafba66223a7b51ffc0d286075a17bb7cd88762fc80d333d3102629f4d8","Cargo.toml":"6b32727a214b53c295b1c7ae174cee020957e5c7439ef842e94b391797098cba","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"23f18e03dc49df91622fe2a76176497404e46ced8a715d9d2b67a7446571cca3","README.md":"7c6217e41b058880a37e01cf8caf205daa397d33cc2199f9fa1634048bc088c5","build.rs":"20e23e5bfe6fc8155fef0e0da036ebc1f81b34078fe86f929c8247b6f4317b99","src/de.rs":"0048bb57f39c7014a491c044d527598270fe417f1676ec7ba4529fea337746bc","src/error.rs":"abb92a9bf62cb7f47141a733a9fd66ec8c369615d7e6f633d3536fd2a5ac74a2","src/features_check/error.rs":"d7359f864afbfe105a38abea9f563dc423036ebc4c956a5695a4beef144dc7ec","src/features_check/mod.rs":"2209f8d5c46b50c8a3b8dc22338dcaf0135d192e8b05d2f456cbe6a73104e958","src/io/core.rs":"9a4146802391fd202a36bebbf3b14b715ae09d8828cbe8e06a01214c470ebf5c","src/io/mod.rs":"fd1ed5080495cab21117f6f7d3c2c9e3687cad0c69a0cd087b08a145a9e672da","src/iter.rs":"f832c469cd7999d26ba9b76baa69b257a212a7edb3dfdf9b1d1bb35e8da85fa9","src/lexical/algorithm.rs":"4fbeb1994049348d1fc388dd1a29e481f8abb8fe1e28bfebf50f3bbce5fa5fbe","src/lexical/bhcomp.rs":"b7c68d74c0055eb67ec2c1bcf27bbc28bef8f1bbc43db8eb94ba69892230add6","src/lexical/bignum.rs":"4230cde10dc8eae456a713cf90ec4e48dff4b1d0c542621ce7f00f39ade2645e","src/lexical/cached.rs":"0e127398691f8042c19cde209e7f4b0161f0f3150342430145929f711e6fdac8","src/lexical/cached_float80.rs":"0f8f74a22cb7d871322a9893bffd0255ca10bf9dffd13afb2462dd3d7f51805f","src/lexical/digit.rs":"a265b9072194a62a67dfc4df3c86d4213097cf3f82280d025e0012a5a262fd9d","src/lexical/errors.rs":"6bc993febceb7dd96ac1c8c5c53b5f5a30297016c0f813ed8ff8d7938d01534d","src/lexical/exponent.rs":"387e945b97dc7ba48a7091c50d228a0dde3a1c4145703d4ab9c31191a91693b0","src/lexical/float.rs":"fe356213c92a049f4bef2f58bc0e3a26866ca06b8c1d74d0f961c5b883852cad","src/lexical/large_powers.rs":"34537f5c701afce1ec2a1fd3c14950381b2e27c9ad74f002c91f3708e8da9ca5","src/lexical/large_powers32.rs":"d533037c6141e6671102aee490c9cdeaba81e667ddca781b2b99db2c455e4a1a","src/lexical/large_powers64.rs":"745dd7c0cbe499eec027ef586248881011d9df20c7efab7929c1807b59886ba1","src/lexical/math.rs":"27e22b724cdf990cdacd0ccfc3749e6e2eb7529d43ebf6e95b1999560b9e199a","src/lexical/mod.rs":"4b4c5228779c0f135a4cb018700e3bcd495da48b74421a86f6b8b304acdef924","src/lexical/num.rs":"cf705c62612e31d704f43d94a633ea1243c6befad7ef5792e2e881a7fd21e809","src/lexical/parse.rs":"c2bfac4c70a19938ced61e991f4ec606764887cf12bac1a0978b5b5318a56aac","src/lexical/rounding.rs":"697207248ba17b7f4965aedb11d276261ada5b06d9c6265d8fd6246664ff6e3c","src/lexical/shift.rs":"bc1ed053dd63d45ac9c35302f18de9f00d94027f28af4ab749c9248439de832a","src/lexical/small_powers.rs":"4608dd218b8002435db7e1ec79d2d0fef5f47ae257b93353326d52ecc80cccda","src/lib.rs":"3787fa7e66342e654359ae6aa81c0683a1260f819ad0e3a803363407122937cd","src/macros.rs":"c9f23156faec8d5216d72b6a97eebd768efb3f75870a6e2beed824308587b998","src/map.rs":"54e5e8ba63cf12a24f2c0257b1ace12f1935ca6d862e7b657209ee6634bb771f","src/number.rs":"157378ce0c01700b99839b8d5578fa46e4d525e6ec7d49e1920537618f51768f","src/raw.rs":"ee2b4ed085d8488e72c5a19791aae9de569d6c1381e9e64ff71afa03d5cf902a","src/read.rs":"49b4b1d067b6485cbded28fb961666ab5df82c36661af722dbae756efb6b2891","src/ser.rs":"44a57aa347c2a3b234635622b675fa3b2c30b818212f5a5eef02027cf3406a84","src/value/de.rs":"64a86f6c14c2c04abc4b6f06b90bfcbda097b37b7f3e990576801f170d4af1e4","src/value/from.rs":"1968835c63dcd4058850162e3a8714b5a7e20eeec458fd4c200aa9ef0515f94c","src/value/index.rs":"8a99d8d50f5674181ced22f6e81dc529eaecb01e543e30346e51fe42cb4b8a5f","src/value/mod.rs":"47ff472a2426a135c7acdf59c4c83c7b7ce986269f10ec31c809a2b35152beda","src/value/partial_eq.rs":"95de799d57f7f4310b64a9488c0a7286dee76dba4329cb69a96298a887e58586","src/value/ser.rs":"3dafa51d46fa7d742398863c4f3a0251afc6193dac75e6231655c9c1690dcd54","tests/compiletest.rs":"022a8e400ef813d7ea1875b944549cee5125f6a995dc33e93b48cba3e1b57bd1","tests/debug.rs":"a8451217c1e127ad6e653ef11e0513525ee350e1e37dd575758a8ee9301b28fb","tests/lexical.rs":"383e06283e15e1db7c6b818da3c84a3afa0059f6e9fc994b069919d81346ab91","tests/lexical/algorithm.rs":"da378df9ee24bfa033968d5c94e91b58e52c39bf6c825dec51c3eb7250cc5874","tests/lexical/exponent.rs":"26ea92abc654a6a88a8281552bca2f76ea1fa4c17d66a1dd6defe14f7d89b666","tests/lexical/float.rs":"0440f2d85c993bcccd925096d7f4136bf624ffd66b3c7ee565d158390685eb11","tests/lexical/math.rs":"4874be2103be5fbe8b8015354414df271ffa00fd815546fc077f15fb4d7a5a37","tests/lexical/num.rs":"6e650c40de85ed72ac06b6bf1487ba161f3824e26d827df6cfdf2bbdb8d05a05","tests/lexical/parse.rs":"17c73e0a59d462716d974b8dd23a291eb6efdc3a933248874e5eab7e7209d67f","tests/lexical/rounding.rs":"6c56e39ba534616c1b2146e8efa6eb57aed322e683bf23183cd32a61fae6447e","tests/macros/mod.rs":"93aa1d54af20bc2c55b6ae8db73c1414cda2626eb9fa7bd57b9d613a3c6e6a19","tests/map.rs":"dcc5212242e4e93703c4335d54f5603b0211b33d6fb5ab410bb630cda6d46b09","tests/regression.rs":"86731134bfb9bb693d9a4fc62393027de80a8bf031109ea6c7ea475b1ebdde8d","tests/regression/issue520.rs":"d146be3472db902b48127d65fe83aa9f698143aca9074c83cd1a9d5dd28e3ec3","tests/regression/issue795.rs":"582e2e7c68113f05a4b1d2cb556a2df7cc77f2ce8164a32c5cc58ae68abb60ec","tests/regression/issue845.rs":"8bd64588fc344e119d0e9e5e7604236e7c168c574b0692033f15278e216a6b9c","tests/stream.rs":"c7d91014538ecd8f495b196d40e999ab2745f2e69fa2ff9e52521605dc6ce856","tests/test.rs":"809b07b6990004a389780fc45d7e81539bf95003a3f410873ce924153ae01ae0","tests/ui/missing_colon.rs":"d07e0c34d98eb43465f0a0310f2c0b5d5b0d26d243b352a1c6bbe6ad3b27eda9","tests/ui/missing_colon.stderr":"8dd5c769f36ede610172f69140a3faf603cd4590cb4abc8eaa1b499fe3537ad9","tests/ui/missing_comma.rs":"b8a9662f99c3e6dd2b6417892c37640578ce91d3a8365bf10c1f686a3227aa87","tests/ui/missing_comma.stderr":"c6acd42b41ee78b197c77ff513fc77a9495423bb912b188ce6ea2963b65dd82c","tests/ui/missing_value.rs":"bca25d67127fb88e7c191c7b03af5a4ce8a9abb630f3d2e6a6c1e77e213dc9a4","tests/ui/missing_value.stderr":"15727519f300c64d6968cd99398227f7fbbf660825459a0768f2bf947eadf752","tests/ui/not_found.rs":"d0a7adb309879ff65aee115b52cc33d36f4bad353cf97c4effc34a6128c2bee3","tests/ui/not_found.stderr":"359b751c0c21fab6d460daef4d5f73a265f7769c9b578f98ea3cb6cbf2387643","tests/ui/parse_expr.rs":"32e6d51f528db3d1ab0ed1e24765b865be393565c26f77413c5aa39d601ac563","tests/ui/parse_expr.stderr":"edfbaa14fa52f6fdb319c1e1aeac4f8870258930850e669d56aa94ef59ce4432","tests/ui/parse_key.rs":"18829b2af320d5cf8a0a5cd3aaf84c7e92cc874651c30e45a3acafb76c2d8b93","tests/ui/parse_key.stderr":"fcb44e060b804a4762b7291e128c41d7010ffa8ab820b8828fd13fbe6d405ca6","tests/ui/unexpected_after_array_element.rs":"a343fc3104431720bdfcf330bcc3cfcd98c8dec3e951133b495242478b0b7eb3","tests/ui/unexpected_after_array_element.stderr":"e0547b280bcc006155c481c66b49fbe2df577e9e741b7f75fcf6ab21e9e20969","tests/ui/unexpected_after_map_entry.rs":"6e3bd2def435ca610e346bbc75cdbaf61963eb2ef1885bb5f76781ba1fac37ef","tests/ui/unexpected_after_map_entry.stderr":"57b7fc4fbff089dd5e5d76f4eba56a3357273c3f4b7ce93eea60891762cc4275","tests/ui/unexpected_colon.rs":"a313cff3fed4be4c33f1eda5d0c5c98147fb835a56d36470d9f367352c1d61ef","tests/ui/unexpected_colon.stderr":"41585758c8764f485e5c98b0cf6f5ad796f5482839f8644189d980ff422316cd","tests/ui/unexpected_comma.rs":"55a8b684bde1ce905837cce719fd457d8898b61cebc27e5b420d05cb6be97256","tests/ui/unexpected_comma.stderr":"847bb88d0db4d8a89b2a339d57eeb2d75af7670f31fcfdc687373a8681cc1653"},"package":"41feea4228a6f1cd09ec7a3593a682276702cd67b5273544757dae23c096f074"} \ No newline at end of file
+{"files":{"CONTRIBUTING.md":"f5270cafba66223a7b51ffc0d286075a17bb7cd88762fc80d333d3102629f4d8","Cargo.toml":"ef162b674028e85093b301f43972c272bc879f5f27f18011fe7ac620c4e9632a","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"23f18e03dc49df91622fe2a76176497404e46ced8a715d9d2b67a7446571cca3","README.md":"96ca6cef9a39d6ba25578b28e5ae10b49fea2d6d4a00f088afc1d4656f087540","build.rs":"0dd97b63a07aa2d4bbb4c7d0e73b521da130769da9f49f28a7b63332781eb3de","src/de.rs":"5dba95fc6a564917289bf1e404d59c74f95772f22ec92cb91d55053b65e93032","src/error.rs":"abb92a9bf62cb7f47141a733a9fd66ec8c369615d7e6f633d3536fd2a5ac74a2","src/features_check/error.rs":"d7359f864afbfe105a38abea9f563dc423036ebc4c956a5695a4beef144dc7ec","src/features_check/mod.rs":"2209f8d5c46b50c8a3b8dc22338dcaf0135d192e8b05d2f456cbe6a73104e958","src/io/core.rs":"9a4146802391fd202a36bebbf3b14b715ae09d8828cbe8e06a01214c470ebf5c","src/io/mod.rs":"fd1ed5080495cab21117f6f7d3c2c9e3687cad0c69a0cd087b08a145a9e672da","src/iter.rs":"f832c469cd7999d26ba9b76baa69b257a212a7edb3dfdf9b1d1bb35e8da85fa9","src/lexical/algorithm.rs":"4fbeb1994049348d1fc388dd1a29e481f8abb8fe1e28bfebf50f3bbce5fa5fbe","src/lexical/bhcomp.rs":"b7c68d74c0055eb67ec2c1bcf27bbc28bef8f1bbc43db8eb94ba69892230add6","src/lexical/bignum.rs":"4230cde10dc8eae456a713cf90ec4e48dff4b1d0c542621ce7f00f39ade2645e","src/lexical/cached.rs":"0e127398691f8042c19cde209e7f4b0161f0f3150342430145929f711e6fdac8","src/lexical/cached_float80.rs":"0f8f74a22cb7d871322a9893bffd0255ca10bf9dffd13afb2462dd3d7f51805f","src/lexical/digit.rs":"a265b9072194a62a67dfc4df3c86d4213097cf3f82280d025e0012a5a262fd9d","src/lexical/errors.rs":"6bc993febceb7dd96ac1c8c5c53b5f5a30297016c0f813ed8ff8d7938d01534d","src/lexical/exponent.rs":"387e945b97dc7ba48a7091c50d228a0dde3a1c4145703d4ab9c31191a91693b0","src/lexical/float.rs":"fe356213c92a049f4bef2f58bc0e3a26866ca06b8c1d74d0f961c5b883852cad","src/lexical/large_powers.rs":"34537f5c701afce1ec2a1fd3c14950381b2e27c9ad74f002c91f3708e8da9ca5","src/lexical/large_powers32.rs":"d533037c6141e6671102aee490c9cdeaba81e667ddca781b2b99db2c455e4a1a","src/lexical/large_powers64.rs":"745dd7c0cbe499eec027ef586248881011d9df20c7efab7929c1807b59886ba1","src/lexical/math.rs":"27e22b724cdf990cdacd0ccfc3749e6e2eb7529d43ebf6e95b1999560b9e199a","src/lexical/mod.rs":"4b4c5228779c0f135a4cb018700e3bcd495da48b74421a86f6b8b304acdef924","src/lexical/num.rs":"cf705c62612e31d704f43d94a633ea1243c6befad7ef5792e2e881a7fd21e809","src/lexical/parse.rs":"c2bfac4c70a19938ced61e991f4ec606764887cf12bac1a0978b5b5318a56aac","src/lexical/rounding.rs":"697207248ba17b7f4965aedb11d276261ada5b06d9c6265d8fd6246664ff6e3c","src/lexical/shift.rs":"bc1ed053dd63d45ac9c35302f18de9f00d94027f28af4ab749c9248439de832a","src/lexical/small_powers.rs":"4608dd218b8002435db7e1ec79d2d0fef5f47ae257b93353326d52ecc80cccda","src/lib.rs":"61e0660b777318b649ada8e40583e668b80796b9a1b2013f77d0bdac3f8ec0eb","src/macros.rs":"c9f23156faec8d5216d72b6a97eebd768efb3f75870a6e2beed824308587b998","src/map.rs":"14fa16650b462ef138bebe1d18cb296b0e1ff404f12f2c212f72ed7c969b3a12","src/number.rs":"425f528c5ec2fcb4dd3c87a633d0b2cd505f7a305a40dffa1f022a643eda938b","src/raw.rs":"ee2b4ed085d8488e72c5a19791aae9de569d6c1381e9e64ff71afa03d5cf902a","src/read.rs":"49b4b1d067b6485cbded28fb961666ab5df82c36661af722dbae756efb6b2891","src/ser.rs":"566ae0b1860861ad70efd17fb0f6ae326e76d60453b6538c783a40d4ce616851","src/value/de.rs":"78f938d960e285f671f3b86ed173d598a815690a14512d6daa94dee43d3ce4cf","src/value/from.rs":"2dcfed837b040447a61eae50bd3938106b090f8a292206aea686022767006625","src/value/index.rs":"8a99d8d50f5674181ced22f6e81dc529eaecb01e543e30346e51fe42cb4b8a5f","src/value/mod.rs":"47ff472a2426a135c7acdf59c4c83c7b7ce986269f10ec31c809a2b35152beda","src/value/partial_eq.rs":"95de799d57f7f4310b64a9488c0a7286dee76dba4329cb69a96298a887e58586","src/value/ser.rs":"5f8eeff57e283527e1aabd89709ef8d6e006682be5929cbdb1d7d182fe185166","tests/compiletest.rs":"022a8e400ef813d7ea1875b944549cee5125f6a995dc33e93b48cba3e1b57bd1","tests/debug.rs":"a8451217c1e127ad6e653ef11e0513525ee350e1e37dd575758a8ee9301b28fb","tests/lexical.rs":"383e06283e15e1db7c6b818da3c84a3afa0059f6e9fc994b069919d81346ab91","tests/lexical/algorithm.rs":"da378df9ee24bfa033968d5c94e91b58e52c39bf6c825dec51c3eb7250cc5874","tests/lexical/exponent.rs":"26ea92abc654a6a88a8281552bca2f76ea1fa4c17d66a1dd6defe14f7d89b666","tests/lexical/float.rs":"0440f2d85c993bcccd925096d7f4136bf624ffd66b3c7ee565d158390685eb11","tests/lexical/math.rs":"4874be2103be5fbe8b8015354414df271ffa00fd815546fc077f15fb4d7a5a37","tests/lexical/num.rs":"6e650c40de85ed72ac06b6bf1487ba161f3824e26d827df6cfdf2bbdb8d05a05","tests/lexical/parse.rs":"17c73e0a59d462716d974b8dd23a291eb6efdc3a933248874e5eab7e7209d67f","tests/lexical/rounding.rs":"6c56e39ba534616c1b2146e8efa6eb57aed322e683bf23183cd32a61fae6447e","tests/macros/mod.rs":"93aa1d54af20bc2c55b6ae8db73c1414cda2626eb9fa7bd57b9d613a3c6e6a19","tests/map.rs":"dcc5212242e4e93703c4335d54f5603b0211b33d6fb5ab410bb630cda6d46b09","tests/regression.rs":"86731134bfb9bb693d9a4fc62393027de80a8bf031109ea6c7ea475b1ebdde8d","tests/regression/issue520.rs":"d146be3472db902b48127d65fe83aa9f698143aca9074c83cd1a9d5dd28e3ec3","tests/regression/issue795.rs":"582e2e7c68113f05a4b1d2cb556a2df7cc77f2ce8164a32c5cc58ae68abb60ec","tests/regression/issue845.rs":"8bd64588fc344e119d0e9e5e7604236e7c168c574b0692033f15278e216a6b9c","tests/regression/issue953.rs":"b2cddc761f5ca6639900c173765a8a5868528a896924e5e925db2696469208f7","tests/stream.rs":"c7d91014538ecd8f495b196d40e999ab2745f2e69fa2ff9e52521605dc6ce856","tests/test.rs":"cde57e6a0b2f23ca8b4ef83673955a0ba85da04db7875f47d37cc23773f32d28","tests/ui/missing_colon.rs":"d07e0c34d98eb43465f0a0310f2c0b5d5b0d26d243b352a1c6bbe6ad3b27eda9","tests/ui/missing_colon.stderr":"3732fd8f4e57b84efc07170cda5f9c5b2b17c707e23c1659222b5a46f652a8d8","tests/ui/missing_comma.rs":"b8a9662f99c3e6dd2b6417892c37640578ce91d3a8365bf10c1f686a3227aa87","tests/ui/missing_comma.stderr":"eae626cf93c97abd105066e624ca4e8cb096784413b9d2564cf9414a8492bc4d","tests/ui/missing_value.rs":"bca25d67127fb88e7c191c7b03af5a4ce8a9abb630f3d2e6a6c1e77e213dc9a4","tests/ui/missing_value.stderr":"b0df8add5cf74e5df30eedd3ca347e4862c04a01c54d802ff45392f2032065b1","tests/ui/not_found.rs":"d0a7adb309879ff65aee115b52cc33d36f4bad353cf97c4effc34a6128c2bee3","tests/ui/not_found.stderr":"359b751c0c21fab6d460daef4d5f73a265f7769c9b578f98ea3cb6cbf2387643","tests/ui/parse_expr.rs":"32e6d51f528db3d1ab0ed1e24765b865be393565c26f77413c5aa39d601ac563","tests/ui/parse_expr.stderr":"4fcd0a014fbce31c9266bab8527d6e6b6806a0e21d9e0275ce713137856073ce","tests/ui/parse_key.rs":"18829b2af320d5cf8a0a5cd3aaf84c7e92cc874651c30e45a3acafb76c2d8b93","tests/ui/parse_key.stderr":"fcb44e060b804a4762b7291e128c41d7010ffa8ab820b8828fd13fbe6d405ca6","tests/ui/unexpected_after_array_element.rs":"a343fc3104431720bdfcf330bcc3cfcd98c8dec3e951133b495242478b0b7eb3","tests/ui/unexpected_after_array_element.stderr":"8df615998fa3057bb9ed865981a35cdbb771625337048f0ad3fba7734e607adf","tests/ui/unexpected_after_map_entry.rs":"6e3bd2def435ca610e346bbc75cdbaf61963eb2ef1885bb5f76781ba1fac37ef","tests/ui/unexpected_after_map_entry.stderr":"b1985c89075ab48b2158bd1705ed766d37854b3d4620ab257cc8bc319d224f17","tests/ui/unexpected_colon.rs":"a313cff3fed4be4c33f1eda5d0c5c98147fb835a56d36470d9f367352c1d61ef","tests/ui/unexpected_colon.stderr":"b2288742fa6a4a7eb65d2ae899bcfed8795b57bd04958da227d60928a8df26c5","tests/ui/unexpected_comma.rs":"55a8b684bde1ce905837cce719fd457d8898b61cebc27e5b420d05cb6be97256","tests/ui/unexpected_comma.stderr":"4c103ca63ff15e2ca659242cc0eae0612bf050e7580da62f1cf50de8082aa7dc"},"package":"877c235533714907a8c2464236f5c4b2a17262ef1bd71f38f35ea592c8da6883"} \ No newline at end of file
diff --git a/vendor/serde_json/Cargo.toml b/vendor/serde_json/Cargo.toml
index 1e1aebb8e..08c94aacb 100644
--- a/vendor/serde_json/Cargo.toml
+++ b/vendor/serde_json/Cargo.toml
@@ -13,7 +13,7 @@
edition = "2018"
rust-version = "1.36"
name = "serde_json"
-version = "1.0.86"
+version = "1.0.91"
authors = [
"Erick Tryzelaar <erick.tryzelaar@gmail.com>",
"David Tolnay <dtolnay@gmail.com>",
@@ -48,6 +48,9 @@ rustdoc-args = [
[package.metadata.playground]
features = ["raw_value"]
+[lib]
+doc-scrape-examples = false
+
[dependencies.indexmap]
version = "1.5.2"
features = ["std"]
diff --git a/vendor/serde_json/README.md b/vendor/serde_json/README.md
index df58a47e4..50b5d458d 100644
--- a/vendor/serde_json/README.md
+++ b/vendor/serde_json/README.md
@@ -1,7 +1,7 @@
-# Serde JSON &emsp; [![Build Status]][travis] [![Latest Version]][crates.io] [![Rustc Version 1.36+]][rustc]
+# Serde JSON &emsp; [![Build Status]][actions] [![Latest Version]][crates.io] [![Rustc Version 1.36+]][rustc]
-[Build Status]: https://img.shields.io/github/workflow/status/serde-rs/json/CI/master
-[travis]: https://github.com/serde-rs/json/actions?query=branch%3Amaster
+[Build Status]: https://img.shields.io/github/actions/workflow/status/serde-rs/json/ci.yml?branch=master
+[actions]: https://github.com/serde-rs/json/actions?query=branch%3Amaster
[Latest Version]: https://img.shields.io/crates/v/serde_json.svg
[crates.io]: https://crates.io/crates/serde\_json
[Rustc Version 1.36+]: https://img.shields.io/badge/rustc-1.36+-lightgray.svg
@@ -350,8 +350,8 @@ closed without a response after some time.
## No-std support
As long as there is a memory allocator, it is possible to use serde_json without
-the rest of the Rust standard library. This is supported on Rust 1.36+. Disable
-the default "std" feature and enable the "alloc" feature:
+the rest of the Rust standard library. Disable the default "std" feature and
+enable the "alloc" feature:
```toml
[dependencies]
diff --git a/vendor/serde_json/build.rs b/vendor/serde_json/build.rs
index e9ec7d56a..0e12602e4 100644
--- a/vendor/serde_json/build.rs
+++ b/vendor/serde_json/build.rs
@@ -3,6 +3,8 @@ use std::process::Command;
use std::str::{self, FromStr};
fn main() {
+ println!("cargo:rerun-if-changed=build.rs");
+
// Decide ideal limb width for arithmetic in the float parser. Refer to
// src/lexical/math.rs for where this has an effect.
let target_arch = env::var("CARGO_CFG_TARGET_ARCH").unwrap();
diff --git a/vendor/serde_json/src/de.rs b/vendor/serde_json/src/de.rs
index ffd0d48c2..88d0f2624 100644
--- a/vendor/serde_json/src/de.rs
+++ b/vendor/serde_json/src/de.rs
@@ -14,7 +14,7 @@ use core::marker::PhantomData;
use core::result;
use core::str::FromStr;
use serde::de::{self, Expected, Unexpected};
-use serde::{forward_to_deserialize_any, serde_if_integer128};
+use serde::forward_to_deserialize_any;
#[cfg(feature = "arbitrary_precision")]
use crate::number::NumberDeserializer;
@@ -335,31 +335,25 @@ impl<'de, R: Read<'de>> Deserializer<R> {
}
}
- serde_if_integer128! {
- fn scan_integer128(&mut self, buf: &mut String) -> Result<()> {
- match tri!(self.next_char_or_null()) {
- b'0' => {
- buf.push('0');
- // There can be only one leading '0'.
- match tri!(self.peek_or_null()) {
- b'0'..=b'9' => {
- Err(self.peek_error(ErrorCode::InvalidNumber))
- }
- _ => Ok(()),
- }
+ fn scan_integer128(&mut self, buf: &mut String) -> Result<()> {
+ match tri!(self.next_char_or_null()) {
+ b'0' => {
+ buf.push('0');
+ // There can be only one leading '0'.
+ match tri!(self.peek_or_null()) {
+ b'0'..=b'9' => Err(self.peek_error(ErrorCode::InvalidNumber)),
+ _ => Ok(()),
}
- c @ b'1'..=b'9' => {
+ }
+ c @ b'1'..=b'9' => {
+ buf.push(c as char);
+ while let c @ b'0'..=b'9' = tri!(self.peek_or_null()) {
+ self.eat_char();
buf.push(c as char);
- while let c @ b'0'..=b'9' = tri!(self.peek_or_null()) {
- self.eat_char();
- buf.push(c as char);
- }
- Ok(())
- }
- _ => {
- Err(self.error(ErrorCode::InvalidNumber))
}
+ Ok(())
}
+ _ => Err(self.error(ErrorCode::InvalidNumber)),
}
}
@@ -457,30 +451,33 @@ impl<'de, R: Read<'de>> Deserializer<R> {
&mut self,
positive: bool,
mut significand: u64,
- mut exponent: i32,
+ exponent_before_decimal_point: i32,
) -> Result<f64> {
self.eat_char();
+ let mut exponent_after_decimal_point = 0;
while let c @ b'0'..=b'9' = tri!(self.peek_or_null()) {
let digit = (c - b'0') as u64;
if overflow!(significand * 10 + digit, u64::max_value()) {
+ let exponent = exponent_before_decimal_point + exponent_after_decimal_point;
return self.parse_decimal_overflow(positive, significand, exponent);
}
self.eat_char();
significand = significand * 10 + digit;
- exponent -= 1;
+ exponent_after_decimal_point -= 1;
}
// Error if there is not at least one digit after the decimal point.
- if exponent == 0 {
+ if exponent_after_decimal_point == 0 {
match tri!(self.peek()) {
Some(_) => return Err(self.peek_error(ErrorCode::InvalidNumber)),
None => return Err(self.peek_error(ErrorCode::EofWhileParsingValue)),
}
}
+ let exponent = exponent_before_decimal_point + exponent_after_decimal_point;
match tri!(self.peek_or_null()) {
b'e' | b'E' => self.parse_exponent(positive, significand, exponent),
_ => self.f64_from_parts(positive, significand, exponent),
@@ -1437,67 +1434,65 @@ impl<'de, 'a, R: Read<'de>> de::Deserializer<'de> for &'a mut Deserializer<R> {
val
}
- serde_if_integer128! {
- fn deserialize_i128<V>(self, visitor: V) -> Result<V::Value>
- where
- V: de::Visitor<'de>,
- {
- let mut buf = String::new();
-
- match tri!(self.parse_whitespace()) {
- Some(b'-') => {
- self.eat_char();
- buf.push('-');
- }
- Some(_) => {}
- None => {
- return Err(self.peek_error(ErrorCode::EofWhileParsingValue));
- }
- };
+ fn deserialize_i128<V>(self, visitor: V) -> Result<V::Value>
+ where
+ V: de::Visitor<'de>,
+ {
+ let mut buf = String::new();
- tri!(self.scan_integer128(&mut buf));
+ match tri!(self.parse_whitespace()) {
+ Some(b'-') => {
+ self.eat_char();
+ buf.push('-');
+ }
+ Some(_) => {}
+ None => {
+ return Err(self.peek_error(ErrorCode::EofWhileParsingValue));
+ }
+ };
- let value = match buf.parse() {
- Ok(int) => visitor.visit_i128(int),
- Err(_) => {
- return Err(self.error(ErrorCode::NumberOutOfRange));
- }
- };
+ tri!(self.scan_integer128(&mut buf));
- match value {
- Ok(value) => Ok(value),
- Err(err) => Err(self.fix_position(err)),
+ let value = match buf.parse() {
+ Ok(int) => visitor.visit_i128(int),
+ Err(_) => {
+ return Err(self.error(ErrorCode::NumberOutOfRange));
}
+ };
+
+ match value {
+ Ok(value) => Ok(value),
+ Err(err) => Err(self.fix_position(err)),
}
+ }
- fn deserialize_u128<V>(self, visitor: V) -> Result<V::Value>
- where
- V: de::Visitor<'de>,
- {
- match tri!(self.parse_whitespace()) {
- Some(b'-') => {
- return Err(self.peek_error(ErrorCode::NumberOutOfRange));
- }
- Some(_) => {}
- None => {
- return Err(self.peek_error(ErrorCode::EofWhileParsingValue));
- }
+ fn deserialize_u128<V>(self, visitor: V) -> Result<V::Value>
+ where
+ V: de::Visitor<'de>,
+ {
+ match tri!(self.parse_whitespace()) {
+ Some(b'-') => {
+ return Err(self.peek_error(ErrorCode::NumberOutOfRange));
}
+ Some(_) => {}
+ None => {
+ return Err(self.peek_error(ErrorCode::EofWhileParsingValue));
+ }
+ }
- let mut buf = String::new();
- tri!(self.scan_integer128(&mut buf));
-
- let value = match buf.parse() {
- Ok(int) => visitor.visit_u128(int),
- Err(_) => {
- return Err(self.error(ErrorCode::NumberOutOfRange));
- }
- };
+ let mut buf = String::new();
+ tri!(self.scan_integer128(&mut buf));
- match value {
- Ok(value) => Ok(value),
- Err(err) => Err(self.fix_position(err)),
+ let value = match buf.parse() {
+ Ok(int) => visitor.visit_u128(int),
+ Err(_) => {
+ return Err(self.error(ErrorCode::NumberOutOfRange));
}
+ };
+
+ match value {
+ Ok(value) => Ok(value),
+ Err(err) => Err(self.fix_position(err)),
}
}
@@ -2164,15 +2159,12 @@ where
deserialize_integer_key!(deserialize_i16 => visit_i16);
deserialize_integer_key!(deserialize_i32 => visit_i32);
deserialize_integer_key!(deserialize_i64 => visit_i64);
+ deserialize_integer_key!(deserialize_i128 => visit_i128);
deserialize_integer_key!(deserialize_u8 => visit_u8);
deserialize_integer_key!(deserialize_u16 => visit_u16);
deserialize_integer_key!(deserialize_u32 => visit_u32);
deserialize_integer_key!(deserialize_u64 => visit_u64);
-
- serde_if_integer128! {
- deserialize_integer_key!(deserialize_i128 => visit_i128);
- deserialize_integer_key!(deserialize_u128 => visit_u128);
- }
+ deserialize_integer_key!(deserialize_u128 => visit_u128);
#[inline]
fn deserialize_option<V>(self, visitor: V) -> Result<V::Value>
diff --git a/vendor/serde_json/src/lib.rs b/vendor/serde_json/src/lib.rs
index 3a1983c3f..fdd95a121 100644
--- a/vendor/serde_json/src/lib.rs
+++ b/vendor/serde_json/src/lib.rs
@@ -279,8 +279,8 @@
//! # No-std support
//!
//! As long as there is a memory allocator, it is possible to use serde_json
-//! without the rest of the Rust standard library. This is supported on Rust
-//! 1.36+. Disable the default "std" feature and enable the "alloc" feature:
+//! without the rest of the Rust standard library. Disable the default "std"
+//! feature and enable the "alloc" feature:
//!
//! ```toml
//! [dependencies]
@@ -300,7 +300,7 @@
//! [macro]: https://docs.serde.rs/serde_json/macro.json.html
//! [`serde-json-core`]: https://github.com/rust-embedded-community/serde-json-core
-#![doc(html_root_url = "https://docs.rs/serde_json/1.0.86")]
+#![doc(html_root_url = "https://docs.rs/serde_json/1.0.91")]
// Ignored clippy lints
#![allow(
clippy::collapsible_else_if,
diff --git a/vendor/serde_json/src/map.rs b/vendor/serde_json/src/map.rs
index 87cf54566..3e8a3814c 100644
--- a/vendor/serde_json/src/map.rs
+++ b/vendor/serde_json/src/map.rs
@@ -197,9 +197,8 @@ impl Map<String, Value> {
#[inline]
pub fn append(&mut self, other: &mut Self) {
#[cfg(feature = "preserve_order")]
- for (k, v) in mem::replace(&mut other.map, MapImpl::default()) {
- self.map.insert(k, v);
- }
+ self.map
+ .extend(mem::replace(&mut other.map, MapImpl::default()));
#[cfg(not(feature = "preserve_order"))]
self.map.append(&mut other.map);
}
@@ -304,6 +303,11 @@ impl Clone for Map<String, Value> {
map: self.map.clone(),
}
}
+
+ #[inline]
+ fn clone_from(&mut self, source: &Self) {
+ self.map.clone_from(&source.map);
+ }
}
impl PartialEq for Map<String, Value> {
diff --git a/vendor/serde_json/src/number.rs b/vendor/serde_json/src/number.rs
index 3c8f6f1bf..21a76411c 100644
--- a/vendor/serde_json/src/number.rs
+++ b/vendor/serde_json/src/number.rs
@@ -12,10 +12,7 @@ use core::hash::{Hash, Hasher};
use serde::de::{self, Unexpected, Visitor};
#[cfg(feature = "arbitrary_precision")]
use serde::de::{IntoDeserializer, MapAccess};
-use serde::{
- forward_to_deserialize_any, serde_if_integer128, Deserialize, Deserializer, Serialize,
- Serializer,
-};
+use serde::{forward_to_deserialize_any, Deserialize, Deserializer, Serialize, Serializer};
#[cfg(feature = "arbitrary_precision")]
pub(crate) const TOKEN: &str = "$serde_json::private::Number";
@@ -540,18 +537,15 @@ impl<'de> Deserializer<'de> for Number {
deserialize_number!(deserialize_i16 => visit_i16);
deserialize_number!(deserialize_i32 => visit_i32);
deserialize_number!(deserialize_i64 => visit_i64);
+ deserialize_number!(deserialize_i128 => visit_i128);
deserialize_number!(deserialize_u8 => visit_u8);
deserialize_number!(deserialize_u16 => visit_u16);
deserialize_number!(deserialize_u32 => visit_u32);
deserialize_number!(deserialize_u64 => visit_u64);
+ deserialize_number!(deserialize_u128 => visit_u128);
deserialize_number!(deserialize_f32 => visit_f32);
deserialize_number!(deserialize_f64 => visit_f64);
- serde_if_integer128! {
- deserialize_number!(deserialize_i128 => visit_i128);
- deserialize_number!(deserialize_u128 => visit_u128);
- }
-
forward_to_deserialize_any! {
bool char str string bytes byte_buf option unit unit_struct
newtype_struct seq tuple tuple_struct map struct enum identifier
@@ -568,18 +562,15 @@ impl<'de, 'a> Deserializer<'de> for &'a Number {
deserialize_number!(deserialize_i16 => visit_i16);
deserialize_number!(deserialize_i32 => visit_i32);
deserialize_number!(deserialize_i64 => visit_i64);
+ deserialize_number!(deserialize_i128 => visit_i128);
deserialize_number!(deserialize_u8 => visit_u8);
deserialize_number!(deserialize_u16 => visit_u16);
deserialize_number!(deserialize_u32 => visit_u32);
deserialize_number!(deserialize_u64 => visit_u64);
+ deserialize_number!(deserialize_u128 => visit_u128);
deserialize_number!(deserialize_f32 => visit_f32);
deserialize_number!(deserialize_f64 => visit_f64);
- serde_if_integer128! {
- deserialize_number!(deserialize_i128 => visit_i128);
- deserialize_number!(deserialize_u128 => visit_u128);
- }
-
forward_to_deserialize_any! {
bool char str string bytes byte_buf option unit unit_struct
newtype_struct seq tuple tuple_struct map struct enum identifier
@@ -731,21 +722,9 @@ impl_from_unsigned!(u8, u16, u32, u64, usize);
impl_from_signed!(i8, i16, i32, i64, isize);
#[cfg(feature = "arbitrary_precision")]
-serde_if_integer128! {
- impl From<i128> for Number {
- fn from(i: i128) -> Self {
- let n = itoa::Buffer::new().format(i).to_owned();
- Number { n }
- }
- }
-
- impl From<u128> for Number {
- fn from(u: u128) -> Self {
- let n = itoa::Buffer::new().format(u).to_owned();
- Number { n }
- }
- }
-}
+impl_from_unsigned!(u128);
+#[cfg(feature = "arbitrary_precision")]
+impl_from_signed!(i128);
impl Number {
#[cfg(not(feature = "arbitrary_precision"))]
diff --git a/vendor/serde_json/src/ser.rs b/vendor/serde_json/src/ser.rs
index 64cb00e1a..80c2deb0c 100644
--- a/vendor/serde_json/src/ser.rs
+++ b/vendor/serde_json/src/ser.rs
@@ -7,7 +7,6 @@ use alloc::vec::Vec;
use core::fmt::{self, Display};
use core::num::FpCategory;
use serde::ser::{self, Impossible, Serialize};
-use serde::serde_if_integer128;
/// A structure for serializing Rust values into JSON.
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
@@ -75,137 +74,105 @@ where
#[inline]
fn serialize_bool(self, value: bool) -> Result<()> {
- tri!(self
- .formatter
+ self.formatter
.write_bool(&mut self.writer, value)
- .map_err(Error::io));
- Ok(())
+ .map_err(Error::io)
}
#[inline]
fn serialize_i8(self, value: i8) -> Result<()> {
- tri!(self
- .formatter
+ self.formatter
.write_i8(&mut self.writer, value)
- .map_err(Error::io));
- Ok(())
+ .map_err(Error::io)
}
#[inline]
fn serialize_i16(self, value: i16) -> Result<()> {
- tri!(self
- .formatter
+ self.formatter
.write_i16(&mut self.writer, value)
- .map_err(Error::io));
- Ok(())
+ .map_err(Error::io)
}
#[inline]
fn serialize_i32(self, value: i32) -> Result<()> {
- tri!(self
- .formatter
+ self.formatter
.write_i32(&mut self.writer, value)
- .map_err(Error::io));
- Ok(())
+ .map_err(Error::io)
}
#[inline]
fn serialize_i64(self, value: i64) -> Result<()> {
- tri!(self
- .formatter
+ self.formatter
.write_i64(&mut self.writer, value)
- .map_err(Error::io));
- Ok(())
+ .map_err(Error::io)
}
- serde_if_integer128! {
- fn serialize_i128(self, value: i128) -> Result<()> {
- self.formatter
- .write_number_str(&mut self.writer, &value.to_string())
- .map_err(Error::io)
- }
+ fn serialize_i128(self, value: i128) -> Result<()> {
+ self.formatter
+ .write_i128(&mut self.writer, value)
+ .map_err(Error::io)
}
#[inline]
fn serialize_u8(self, value: u8) -> Result<()> {
- tri!(self
- .formatter
+ self.formatter
.write_u8(&mut self.writer, value)
- .map_err(Error::io));
- Ok(())
+ .map_err(Error::io)
}
#[inline]
fn serialize_u16(self, value: u16) -> Result<()> {
- tri!(self
- .formatter
+ self.formatter
.write_u16(&mut self.writer, value)
- .map_err(Error::io));
- Ok(())
+ .map_err(Error::io)
}
#[inline]
fn serialize_u32(self, value: u32) -> Result<()> {
- tri!(self
- .formatter
+ self.formatter
.write_u32(&mut self.writer, value)
- .map_err(Error::io));
- Ok(())
+ .map_err(Error::io)
}
#[inline]
fn serialize_u64(self, value: u64) -> Result<()> {
- tri!(self
- .formatter
+ self.formatter
.write_u64(&mut self.writer, value)
- .map_err(Error::io));
- Ok(())
+ .map_err(Error::io)
}
- serde_if_integer128! {
- fn serialize_u128(self, value: u128) -> Result<()> {
- self.formatter
- .write_number_str(&mut self.writer, &value.to_string())
- .map_err(Error::io)
- }
+ fn serialize_u128(self, value: u128) -> Result<()> {
+ self.formatter
+ .write_u128(&mut self.writer, value)
+ .map_err(Error::io)
}
#[inline]
fn serialize_f32(self, value: f32) -> Result<()> {
match value.classify() {
- FpCategory::Nan | FpCategory::Infinite => {
- tri!(self
- .formatter
- .write_null(&mut self.writer)
- .map_err(Error::io));
- }
- _ => {
- tri!(self
- .formatter
- .write_f32(&mut self.writer, value)
- .map_err(Error::io));
- }
+ FpCategory::Nan | FpCategory::Infinite => self
+ .formatter
+ .write_null(&mut self.writer)
+ .map_err(Error::io),
+ _ => self
+ .formatter
+ .write_f32(&mut self.writer, value)
+ .map_err(Error::io),
}
- Ok(())
}
#[inline]
fn serialize_f64(self, value: f64) -> Result<()> {
match value.classify() {
- FpCategory::Nan | FpCategory::Infinite => {
- tri!(self
- .formatter
- .write_null(&mut self.writer)
- .map_err(Error::io));
- }
- _ => {
- tri!(self
- .formatter
- .write_f64(&mut self.writer, value)
- .map_err(Error::io));
- }
+ FpCategory::Nan | FpCategory::Infinite => self
+ .formatter
+ .write_null(&mut self.writer)
+ .map_err(Error::io),
+ _ => self
+ .formatter
+ .write_f64(&mut self.writer, value)
+ .map_err(Error::io),
}
- Ok(())
}
#[inline]
@@ -217,8 +184,7 @@ where
#[inline]
fn serialize_str(self, value: &str) -> Result<()> {
- tri!(format_escaped_str(&mut self.writer, &mut self.formatter, value).map_err(Error::io));
- Ok(())
+ format_escaped_str(&mut self.writer, &mut self.formatter, value).map_err(Error::io)
}
#[inline]
@@ -233,11 +199,9 @@ where
#[inline]
fn serialize_unit(self) -> Result<()> {
- tri!(self
- .formatter
+ self.formatter
.write_null(&mut self.writer)
- .map_err(Error::io));
- Ok(())
+ .map_err(Error::io)
}
#[inline]
@@ -297,11 +261,9 @@ where
.formatter
.end_object_value(&mut self.writer)
.map_err(Error::io));
- tri!(self
- .formatter
+ self.formatter
.end_object(&mut self.writer)
- .map_err(Error::io));
- Ok(())
+ .map_err(Error::io)
}
#[inline]
@@ -490,11 +452,9 @@ where
}
}
}
- tri!(self
- .formatter
+ self.formatter
.end_string(&mut self.writer)
- .map_err(Error::io));
- Ok(())
+ .map_err(Error::io)
}
}
@@ -541,11 +501,9 @@ where
.map_err(Error::io));
*state = State::Rest;
tri!(value.serialize(&mut **ser));
- tri!(ser
- .formatter
+ ser.formatter
.end_array_value(&mut ser.writer)
- .map_err(Error::io));
- Ok(())
+ .map_err(Error::io)
}
#[cfg(feature = "arbitrary_precision")]
Compound::Number { .. } => unreachable!(),
@@ -557,13 +515,10 @@ where
#[inline]
fn end(self) -> Result<()> {
match self {
- Compound::Map { ser, state } => {
- match state {
- State::Empty => {}
- _ => tri!(ser.formatter.end_array(&mut ser.writer).map_err(Error::io)),
- }
- Ok(())
- }
+ Compound::Map { ser, state } => match state {
+ State::Empty => Ok(()),
+ _ => ser.formatter.end_array(&mut ser.writer).map_err(Error::io),
+ },
#[cfg(feature = "arbitrary_precision")]
Compound::Number { .. } => unreachable!(),
#[cfg(feature = "raw_value")]
@@ -644,8 +599,7 @@ where
.formatter
.end_object_value(&mut ser.writer)
.map_err(Error::io));
- tri!(ser.formatter.end_object(&mut ser.writer).map_err(Error::io));
- Ok(())
+ ser.formatter.end_object(&mut ser.writer).map_err(Error::io)
}
#[cfg(feature = "arbitrary_precision")]
Compound::Number { .. } => unreachable!(),
@@ -678,11 +632,9 @@ where
tri!(key.serialize(MapKeySerializer { ser: *ser }));
- tri!(ser
- .formatter
+ ser.formatter
.end_object_key(&mut ser.writer)
- .map_err(Error::io));
- Ok(())
+ .map_err(Error::io)
}
#[cfg(feature = "arbitrary_precision")]
Compound::Number { .. } => unreachable!(),
@@ -703,11 +655,9 @@ where
.begin_object_value(&mut ser.writer)
.map_err(Error::io));
tri!(value.serialize(&mut **ser));
- tri!(ser
- .formatter
+ ser.formatter
.end_object_value(&mut ser.writer)
- .map_err(Error::io));
- Ok(())
+ .map_err(Error::io)
}
#[cfg(feature = "arbitrary_precision")]
Compound::Number { .. } => unreachable!(),
@@ -719,13 +669,10 @@ where
#[inline]
fn end(self) -> Result<()> {
match self {
- Compound::Map { ser, state } => {
- match state {
- State::Empty => {}
- _ => tri!(ser.formatter.end_object(&mut ser.writer).map_err(Error::io)),
- }
- Ok(())
- }
+ Compound::Map { ser, state } => match state {
+ State::Empty => Ok(()),
+ _ => ser.formatter.end_object(&mut ser.writer).map_err(Error::io),
+ },
#[cfg(feature = "arbitrary_precision")]
Compound::Number { .. } => unreachable!(),
#[cfg(feature = "raw_value")]
@@ -752,8 +699,7 @@ where
#[cfg(feature = "arbitrary_precision")]
Compound::Number { ser, .. } => {
if key == crate::number::TOKEN {
- tri!(value.serialize(NumberStrEmitter(ser)));
- Ok(())
+ value.serialize(NumberStrEmitter(ser))
} else {
Err(invalid_number())
}
@@ -761,8 +707,7 @@ where
#[cfg(feature = "raw_value")]
Compound::RawValue { ser, .. } => {
if key == crate::raw::TOKEN {
- tri!(value.serialize(RawValueStrEmitter(ser)));
- Ok(())
+ value.serialize(RawValueStrEmitter(ser))
} else {
Err(invalid_raw_value())
}
@@ -816,8 +761,7 @@ where
.formatter
.end_object_value(&mut ser.writer)
.map_err(Error::io));
- tri!(ser.formatter.end_object(&mut ser.writer).map_err(Error::io));
- Ok(())
+ ser.formatter.end_object(&mut ser.writer).map_err(Error::io)
}
#[cfg(feature = "arbitrary_precision")]
Compound::Number { .. } => unreachable!(),
@@ -899,12 +843,10 @@ where
.formatter
.write_i8(&mut self.ser.writer, value)
.map_err(Error::io));
- tri!(self
- .ser
+ self.ser
.formatter
.end_string(&mut self.ser.writer)
- .map_err(Error::io));
- Ok(())
+ .map_err(Error::io)
}
fn serialize_i16(self, value: i16) -> Result<()> {
@@ -918,12 +860,10 @@ where
.formatter
.write_i16(&mut self.ser.writer, value)
.map_err(Error::io));
- tri!(self
- .ser
+ self.ser
.formatter
.end_string(&mut self.ser.writer)
- .map_err(Error::io));
- Ok(())
+ .map_err(Error::io)
}
fn serialize_i32(self, value: i32) -> Result<()> {
@@ -937,12 +877,10 @@ where
.formatter
.write_i32(&mut self.ser.writer, value)
.map_err(Error::io));
- tri!(self
- .ser
+ self.ser
.formatter
.end_string(&mut self.ser.writer)
- .map_err(Error::io));
- Ok(())
+ .map_err(Error::io)
}
fn serialize_i64(self, value: i64) -> Result<()> {
@@ -956,33 +894,27 @@ where
.formatter
.write_i64(&mut self.ser.writer, value)
.map_err(Error::io));
- tri!(self
- .ser
+ self.ser
.formatter
.end_string(&mut self.ser.writer)
- .map_err(Error::io));
- Ok(())
+ .map_err(Error::io)
}
- serde_if_integer128! {
- fn serialize_i128(self, value: i128) -> Result<()> {
- tri!(self
- .ser
- .formatter
- .begin_string(&mut self.ser.writer)
- .map_err(Error::io));
- tri!(self
- .ser
- .formatter
- .write_number_str(&mut self.ser.writer, &value.to_string())
- .map_err(Error::io));
- tri!(self
- .ser
- .formatter
- .end_string(&mut self.ser.writer)
- .map_err(Error::io));
- Ok(())
- }
+ fn serialize_i128(self, value: i128) -> Result<()> {
+ tri!(self
+ .ser
+ .formatter
+ .begin_string(&mut self.ser.writer)
+ .map_err(Error::io));
+ tri!(self
+ .ser
+ .formatter
+ .write_i128(&mut self.ser.writer, value)
+ .map_err(Error::io));
+ self.ser
+ .formatter
+ .end_string(&mut self.ser.writer)
+ .map_err(Error::io)
}
fn serialize_u8(self, value: u8) -> Result<()> {
@@ -996,12 +928,10 @@ where
.formatter
.write_u8(&mut self.ser.writer, value)
.map_err(Error::io));
- tri!(self
- .ser
+ self.ser
.formatter
.end_string(&mut self.ser.writer)
- .map_err(Error::io));
- Ok(())
+ .map_err(Error::io)
}
fn serialize_u16(self, value: u16) -> Result<()> {
@@ -1015,12 +945,10 @@ where
.formatter
.write_u16(&mut self.ser.writer, value)
.map_err(Error::io));
- tri!(self
- .ser
+ self.ser
.formatter
.end_string(&mut self.ser.writer)
- .map_err(Error::io));
- Ok(())
+ .map_err(Error::io)
}
fn serialize_u32(self, value: u32) -> Result<()> {
@@ -1034,12 +962,10 @@ where
.formatter
.write_u32(&mut self.ser.writer, value)
.map_err(Error::io));
- tri!(self
- .ser
+ self.ser
.formatter
.end_string(&mut self.ser.writer)
- .map_err(Error::io));
- Ok(())
+ .map_err(Error::io)
}
fn serialize_u64(self, value: u64) -> Result<()> {
@@ -1053,33 +979,27 @@ where
.formatter
.write_u64(&mut self.ser.writer, value)
.map_err(Error::io));
- tri!(self
- .ser
+ self.ser
.formatter
.end_string(&mut self.ser.writer)
- .map_err(Error::io));
- Ok(())
+ .map_err(Error::io)
}
- serde_if_integer128! {
- fn serialize_u128(self, value: u128) -> Result<()> {
- tri!(self
- .ser
- .formatter
- .begin_string(&mut self.ser.writer)
- .map_err(Error::io));
- tri!(self
- .ser
- .formatter
- .write_number_str(&mut self.ser.writer, &value.to_string())
- .map_err(Error::io));
- tri!(self
- .ser
- .formatter
- .end_string(&mut self.ser.writer)
- .map_err(Error::io));
- Ok(())
- }
+ fn serialize_u128(self, value: u128) -> Result<()> {
+ tri!(self
+ .ser
+ .formatter
+ .begin_string(&mut self.ser.writer)
+ .map_err(Error::io));
+ tri!(self
+ .ser
+ .formatter
+ .write_u128(&mut self.ser.writer, value)
+ .map_err(Error::io));
+ self.ser
+ .formatter
+ .end_string(&mut self.ser.writer)
+ .map_err(Error::io)
}
fn serialize_f32(self, _value: f32) -> Result<()> {
@@ -1218,10 +1138,8 @@ impl<'a, W: io::Write, F: Formatter> ser::Serializer for NumberStrEmitter<'a, W,
Err(invalid_number())
}
- serde_if_integer128! {
- fn serialize_i128(self, _v: i128) -> Result<()> {
- Err(invalid_number())
- }
+ fn serialize_i128(self, _v: i128) -> Result<()> {
+ Err(invalid_number())
}
fn serialize_u8(self, _v: u8) -> Result<()> {
@@ -1240,10 +1158,8 @@ impl<'a, W: io::Write, F: Formatter> ser::Serializer for NumberStrEmitter<'a, W,
Err(invalid_number())
}
- serde_if_integer128! {
- fn serialize_u128(self, _v: u128) -> Result<()> {
- Err(invalid_number())
- }
+ fn serialize_u128(self, _v: u128) -> Result<()> {
+ Err(invalid_number())
}
fn serialize_f32(self, _v: f32) -> Result<()> {
@@ -1399,10 +1315,8 @@ impl<'a, W: io::Write, F: Formatter> ser::Serializer for RawValueStrEmitter<'a,
Err(ser::Error::custom("expected RawValue"))
}
- serde_if_integer128! {
- fn serialize_i128(self, _v: i128) -> Result<()> {
- Err(ser::Error::custom("expected RawValue"))
- }
+ fn serialize_i128(self, _v: i128) -> Result<()> {
+ Err(ser::Error::custom("expected RawValue"))
}
fn serialize_u8(self, _v: u8) -> Result<()> {
@@ -1421,10 +1335,8 @@ impl<'a, W: io::Write, F: Formatter> ser::Serializer for RawValueStrEmitter<'a,
Err(ser::Error::custom("expected RawValue"))
}
- serde_if_integer128! {
- fn serialize_u128(self, _v: u128) -> Result<()> {
- Err(ser::Error::custom("expected RawValue"))
- }
+ fn serialize_u128(self, _v: u128) -> Result<()> {
+ Err(ser::Error::custom("expected RawValue"))
}
fn serialize_f32(self, _v: f32) -> Result<()> {
@@ -1661,6 +1573,17 @@ pub trait Formatter {
writer.write_all(s.as_bytes())
}
+ /// Writes an integer value like `-123` to the specified writer.
+ #[inline]
+ fn write_i128<W>(&mut self, writer: &mut W, value: i128) -> io::Result<()>
+ where
+ W: ?Sized + io::Write,
+ {
+ let mut buffer = itoa::Buffer::new();
+ let s = buffer.format(value);
+ writer.write_all(s.as_bytes())
+ }
+
/// Writes an integer value like `123` to the specified writer.
#[inline]
fn write_u8<W>(&mut self, writer: &mut W, value: u8) -> io::Result<()>
@@ -1705,6 +1628,17 @@ pub trait Formatter {
writer.write_all(s.as_bytes())
}
+ /// Writes an integer value like `123` to the specified writer.
+ #[inline]
+ fn write_u128<W>(&mut self, writer: &mut W, value: u128) -> io::Result<()>
+ where
+ W: ?Sized + io::Write,
+ {
+ let mut buffer = itoa::Buffer::new();
+ let s = buffer.format(value);
+ writer.write_all(s.as_bytes())
+ }
+
/// Writes a floating point value like `-31.26e+12` to the specified writer.
#[inline]
fn write_f32<W>(&mut self, writer: &mut W, value: f32) -> io::Result<()>
@@ -1985,13 +1919,8 @@ impl<'a> Formatter for PrettyFormatter<'a> {
where
W: ?Sized + io::Write,
{
- if first {
- tri!(writer.write_all(b"\n"));
- } else {
- tri!(writer.write_all(b",\n"));
- }
- tri!(indent(writer, self.current_indent, self.indent));
- Ok(())
+ tri!(writer.write_all(if first { b"\n" } else { b",\n" }));
+ indent(writer, self.current_indent, self.indent)
}
#[inline]
@@ -2033,11 +1962,7 @@ impl<'a> Formatter for PrettyFormatter<'a> {
where
W: ?Sized + io::Write,
{
- if first {
- tri!(writer.write_all(b"\n"));
- } else {
- tri!(writer.write_all(b",\n"));
- }
+ tri!(writer.write_all(if first { b"\n" } else { b",\n" }));
indent(writer, self.current_indent, self.indent)
}
@@ -2066,8 +1991,7 @@ where
{
tri!(formatter.begin_string(writer));
tri!(format_escaped_str_contents(writer, formatter, value));
- tri!(formatter.end_string(writer));
- Ok(())
+ formatter.end_string(writer)
}
fn format_escaped_str_contents<W, F>(
@@ -2099,11 +2023,11 @@ where
start = i + 1;
}
- if start != bytes.len() {
- tri!(formatter.write_string_fragment(writer, &value[start..]));
+ if start == bytes.len() {
+ return Ok(());
}
- Ok(())
+ formatter.write_string_fragment(writer, &value[start..])
}
const BB: u8 = b'b'; // \x08
@@ -2152,8 +2076,7 @@ where
T: ?Sized + Serialize,
{
let mut ser = Serializer::new(writer);
- tri!(value.serialize(&mut ser));
- Ok(())
+ value.serialize(&mut ser)
}
/// Serialize the given data structure as pretty-printed JSON into the IO
@@ -2171,8 +2094,7 @@ where
T: ?Sized + Serialize,
{
let mut ser = Serializer::pretty(writer);
- tri!(value.serialize(&mut ser));
- Ok(())
+ value.serialize(&mut ser)
}
/// Serialize the given data structure as a JSON byte vector.
diff --git a/vendor/serde_json/src/value/de.rs b/vendor/serde_json/src/value/de.rs
index cc1d38565..9c266d08a 100644
--- a/vendor/serde_json/src/value/de.rs
+++ b/vendor/serde_json/src/value/de.rs
@@ -14,7 +14,7 @@ use serde::de::{
self, Deserialize, DeserializeSeed, EnumAccess, Expected, IntoDeserializer, MapAccess,
SeqAccess, Unexpected, VariantAccess, Visitor,
};
-use serde::{forward_to_deserialize_any, serde_if_integer128};
+use serde::forward_to_deserialize_any;
#[cfg(feature = "arbitrary_precision")]
use crate::number::NumberFromString;
@@ -228,18 +228,15 @@ impl<'de> serde::Deserializer<'de> for Value {
deserialize_number!(deserialize_i16);
deserialize_number!(deserialize_i32);
deserialize_number!(deserialize_i64);
+ deserialize_number!(deserialize_i128);
deserialize_number!(deserialize_u8);
deserialize_number!(deserialize_u16);
deserialize_number!(deserialize_u32);
deserialize_number!(deserialize_u64);
+ deserialize_number!(deserialize_u128);
deserialize_number!(deserialize_f32);
deserialize_number!(deserialize_f64);
- serde_if_integer128! {
- deserialize_number!(deserialize_i128);
- deserialize_number!(deserialize_u128);
- }
-
#[inline]
fn deserialize_option<V>(self, visitor: V) -> Result<V::Value, Error>
where
@@ -724,18 +721,15 @@ impl<'de> serde::Deserializer<'de> for &'de Value {
deserialize_value_ref_number!(deserialize_i16);
deserialize_value_ref_number!(deserialize_i32);
deserialize_value_ref_number!(deserialize_i64);
+ deserialize_number!(deserialize_i128);
deserialize_value_ref_number!(deserialize_u8);
deserialize_value_ref_number!(deserialize_u16);
deserialize_value_ref_number!(deserialize_u32);
deserialize_value_ref_number!(deserialize_u64);
+ deserialize_number!(deserialize_u128);
deserialize_value_ref_number!(deserialize_f32);
deserialize_value_ref_number!(deserialize_f64);
- serde_if_integer128! {
- deserialize_number!(deserialize_i128);
- deserialize_number!(deserialize_u128);
- }
-
fn deserialize_option<V>(self, visitor: V) -> Result<V::Value, Error>
where
V: Visitor<'de>,
@@ -1000,7 +994,7 @@ impl<'de> VariantAccess<'de> for VariantRefDeserializer<'de> {
V: Visitor<'de>,
{
match self.value {
- Some(&Value::Array(ref v)) => {
+ Some(Value::Array(v)) => {
if v.is_empty() {
visitor.visit_unit()
} else {
@@ -1027,7 +1021,7 @@ impl<'de> VariantAccess<'de> for VariantRefDeserializer<'de> {
V: Visitor<'de>,
{
match self.value {
- Some(&Value::Object(ref v)) => visit_object_ref(v, visitor),
+ Some(Value::Object(v)) => visit_object_ref(v, visitor),
Some(other) => Err(serde::de::Error::invalid_type(
other.unexpected(),
&"struct variant",
@@ -1156,15 +1150,12 @@ impl<'de> serde::Deserializer<'de> for MapKeyDeserializer<'de> {
deserialize_integer_key!(deserialize_i16 => visit_i16);
deserialize_integer_key!(deserialize_i32 => visit_i32);
deserialize_integer_key!(deserialize_i64 => visit_i64);
+ deserialize_integer_key!(deserialize_i128 => visit_i128);
deserialize_integer_key!(deserialize_u8 => visit_u8);
deserialize_integer_key!(deserialize_u16 => visit_u16);
deserialize_integer_key!(deserialize_u32 => visit_u32);
deserialize_integer_key!(deserialize_u64 => visit_u64);
-
- serde_if_integer128! {
- deserialize_integer_key!(deserialize_i128 => visit_i128);
- deserialize_integer_key!(deserialize_u128 => visit_u128);
- }
+ deserialize_integer_key!(deserialize_u128 => visit_u128);
#[inline]
fn deserialize_option<V>(self, visitor: V) -> Result<V::Value, Error>
diff --git a/vendor/serde_json/src/value/from.rs b/vendor/serde_json/src/value/from.rs
index 858a6e48a..c5a6a3960 100644
--- a/vendor/serde_json/src/value/from.rs
+++ b/vendor/serde_json/src/value/from.rs
@@ -6,9 +6,6 @@ use alloc::string::{String, ToString};
use alloc::vec::Vec;
use core::iter::FromIterator;
-#[cfg(feature = "arbitrary_precision")]
-use serde::serde_if_integer128;
-
macro_rules! from_integer {
($($ty:ident)*) => {
$(
@@ -27,10 +24,8 @@ from_integer! {
}
#[cfg(feature = "arbitrary_precision")]
-serde_if_integer128! {
- from_integer! {
- i128 u128
- }
+from_integer! {
+ i128 u128
}
impl From<f32> for Value {
diff --git a/vendor/serde_json/src/value/ser.rs b/vendor/serde_json/src/value/ser.rs
index 37e495f65..892a63d5f 100644
--- a/vendor/serde_json/src/value/ser.rs
+++ b/vendor/serde_json/src/value/ser.rs
@@ -9,9 +9,6 @@ use core::fmt::Display;
use core::result;
use serde::ser::{Impossible, Serialize};
-#[cfg(feature = "arbitrary_precision")]
-use serde::serde_if_integer128;
-
impl Serialize for Value {
#[inline]
fn serialize<S>(&self, serializer: S) -> result::Result<S::Ok, S::Error>
@@ -96,10 +93,8 @@ impl serde::Serializer for Serializer {
}
#[cfg(feature = "arbitrary_precision")]
- serde_if_integer128! {
- fn serialize_i128(self, value: i128) -> Result<Value> {
- Ok(Value::Number(value.into()))
- }
+ fn serialize_i128(self, value: i128) -> Result<Value> {
+ Ok(Value::Number(value.into()))
}
#[inline]
@@ -123,10 +118,8 @@ impl serde::Serializer for Serializer {
}
#[cfg(feature = "arbitrary_precision")]
- serde_if_integer128! {
- fn serialize_u128(self, value: u128) -> Result<Value> {
- Ok(Value::Number(value.into()))
- }
+ fn serialize_u128(self, value: u128) -> Result<Value> {
+ Ok(Value::Number(value.into()))
}
#[inline]
diff --git a/vendor/serde_json/tests/regression/issue953.rs b/vendor/serde_json/tests/regression/issue953.rs
new file mode 100644
index 000000000..771aa5287
--- /dev/null
+++ b/vendor/serde_json/tests/regression/issue953.rs
@@ -0,0 +1,9 @@
+use serde_json::Value;
+
+#[test]
+fn test() {
+ let x1 = serde_json::from_str::<Value>("18446744073709551615.");
+ assert!(x1.is_err());
+ let x2 = serde_json::from_str::<Value>("18446744073709551616.");
+ assert!(x2.is_err());
+}
diff --git a/vendor/serde_json/tests/test.rs b/vendor/serde_json/tests/test.rs
index aa5b5caa0..c2050724b 100644
--- a/vendor/serde_json/tests/test.rs
+++ b/vendor/serde_json/tests/test.rs
@@ -6,7 +6,6 @@
clippy::excessive_precision,
clippy::float_cmp,
clippy::items_after_statements,
- clippy::let_underscore_drop,
clippy::shadow_unrelated,
clippy::too_many_lines,
clippy::unreadable_literal,
@@ -1928,7 +1927,7 @@ fn test_deny_float_key() {
// map with float key
let map = treemap!(Float => "x");
- assert!(serde_json::to_value(&map).is_err());
+ assert!(serde_json::to_value(map).is_err());
}
#[test]
diff --git a/vendor/serde_json/tests/ui/missing_colon.stderr b/vendor/serde_json/tests/ui/missing_colon.stderr
index 3cebc4fd3..1515211ad 100644
--- a/vendor/serde_json/tests/ui/missing_colon.stderr
+++ b/vendor/serde_json/tests/ui/missing_colon.stderr
@@ -4,4 +4,9 @@ error: unexpected end of macro invocation
4 | json!({ "a" });
| ^^^^^^^^^^^^^^ missing tokens in macro arguments
|
+note: while trying to match `@`
+ --> src/macros.rs
+ |
+ | (@array [$($elems:expr,)*]) => {
+ | ^
= note: this error originates in the macro `json_internal` which comes from the expansion of the macro `json` (in Nightly builds, run with -Z macro-backtrace for more info)
diff --git a/vendor/serde_json/tests/ui/missing_comma.stderr b/vendor/serde_json/tests/ui/missing_comma.stderr
index bd911d035..bafa0f891 100644
--- a/vendor/serde_json/tests/ui/missing_comma.stderr
+++ b/vendor/serde_json/tests/ui/missing_comma.stderr
@@ -5,3 +5,9 @@ error: no rules expected the token `"2"`
| -^^^ no rules expected this token in macro call
| |
| help: missing comma here
+ |
+note: while trying to match `,`
+ --> src/macros.rs
+ |
+ | ($e:expr , $($tt:tt)*) => {};
+ | ^
diff --git a/vendor/serde_json/tests/ui/missing_value.stderr b/vendor/serde_json/tests/ui/missing_value.stderr
index a1edbc37b..9c9de99ca 100644
--- a/vendor/serde_json/tests/ui/missing_value.stderr
+++ b/vendor/serde_json/tests/ui/missing_value.stderr
@@ -4,4 +4,9 @@ error: unexpected end of macro invocation
4 | json!({ "a" : });
| ^^^^^^^^^^^^^^^^ missing tokens in macro arguments
|
+note: while trying to match `@`
+ --> src/macros.rs
+ |
+ | (@array [$($elems:expr,)*]) => {
+ | ^
= note: this error originates in the macro `json_internal` which comes from the expansion of the macro `json` (in Nightly builds, run with -Z macro-backtrace for more info)
diff --git a/vendor/serde_json/tests/ui/parse_expr.stderr b/vendor/serde_json/tests/ui/parse_expr.stderr
index 6959673d9..cd3e1c94d 100644
--- a/vendor/serde_json/tests/ui/parse_expr.stderr
+++ b/vendor/serde_json/tests/ui/parse_expr.stderr
@@ -3,3 +3,9 @@ error: no rules expected the token `~`
|
4 | json!({ "a" : ~ });
| ^ no rules expected this token in macro call
+ |
+note: while trying to match meta-variable `$e:expr`
+ --> src/macros.rs
+ |
+ | ($e:expr , $($tt:tt)*) => {};
+ | ^^^^^^^
diff --git a/vendor/serde_json/tests/ui/unexpected_after_array_element.stderr b/vendor/serde_json/tests/ui/unexpected_after_array_element.stderr
index f745a212d..ef449f764 100644
--- a/vendor/serde_json/tests/ui/unexpected_after_array_element.stderr
+++ b/vendor/serde_json/tests/ui/unexpected_after_array_element.stderr
@@ -3,3 +3,5 @@ error: no rules expected the token `=>`
|
4 | json!([ true => ]);
| ^^ no rules expected this token in macro call
+ |
+ = note: while trying to match end of macro
diff --git a/vendor/serde_json/tests/ui/unexpected_after_map_entry.stderr b/vendor/serde_json/tests/ui/unexpected_after_map_entry.stderr
index a18c9b4cd..c62d90ba0 100644
--- a/vendor/serde_json/tests/ui/unexpected_after_map_entry.stderr
+++ b/vendor/serde_json/tests/ui/unexpected_after_map_entry.stderr
@@ -3,3 +3,5 @@ error: no rules expected the token `=>`
|
4 | json!({ "k": true => });
| ^^ no rules expected this token in macro call
+ |
+ = note: while trying to match end of macro
diff --git a/vendor/serde_json/tests/ui/unexpected_colon.stderr b/vendor/serde_json/tests/ui/unexpected_colon.stderr
index ed038f608..7e47726bc 100644
--- a/vendor/serde_json/tests/ui/unexpected_colon.stderr
+++ b/vendor/serde_json/tests/ui/unexpected_colon.stderr
@@ -3,3 +3,5 @@ error: no rules expected the token `:`
|
4 | json!({ : true });
| ^ no rules expected this token in macro call
+ |
+ = note: while trying to match end of macro
diff --git a/vendor/serde_json/tests/ui/unexpected_comma.stderr b/vendor/serde_json/tests/ui/unexpected_comma.stderr
index a4309c4e5..552f399a5 100644
--- a/vendor/serde_json/tests/ui/unexpected_comma.stderr
+++ b/vendor/serde_json/tests/ui/unexpected_comma.stderr
@@ -3,3 +3,5 @@ error: no rules expected the token `,`
|
4 | json!({ "a" , "b": true });
| ^ no rules expected this token in macro call
+ |
+ = note: while trying to match end of macro
diff --git a/vendor/serde_repr/.cargo-checksum.json b/vendor/serde_repr/.cargo-checksum.json
index fb30edebf..ac7ba6ea5 100644
--- a/vendor/serde_repr/.cargo-checksum.json
+++ b/vendor/serde_repr/.cargo-checksum.json
@@ -1 +1 @@
-{"files":{"Cargo.toml":"9c18626e7651c83a27fd830650fddfba5db26eecfb706efdf49a33b9dbd49376","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"23f18e03dc49df91622fe2a76176497404e46ced8a715d9d2b67a7446571cca3","README.md":"390805207b02b9766faf9df282ab0a6ee03c64c97a5af07ad516d5c6e095a011","src/lib.rs":"7acb4fb05f93dd98a0f2c83de6da38ed68e882c7b7ea244aa607c1c5113f8509","src/parse.rs":"687cf1436d12c0c26b1c6d06f80e56b4ec0d63a38d71e1f175b981c0fdc10c68","tests/compiletest.rs":"022a8e400ef813d7ea1875b944549cee5125f6a995dc33e93b48cba3e1b57bd1","tests/test.rs":"a4ddb956ee9eafc0b50694075497a2712a347f1a682f9038e2dd654c6605af44","tests/ui/empty_enum.rs":"fe1166f2f92ee213d26a23e57572a99c65c163d446fd8d67e1520bab34f4b859","tests/ui/empty_enum.stderr":"2c8907fc146bb4dcdb926b72de4f823dae4c1c0d8de8a636c512539408f26cc7","tests/ui/missing_repr.rs":"b7ba9341111582cad52e761b82f14778c60352014c4265566e4d4d01ccdcb306","tests/ui/missing_repr.stderr":"dfcb65527963fb8962e1442e10d3c71e141f238b1732483e1739b528ae0eca43","tests/ui/multiple_others.rs":"569658516619719f21e5071873a37125d5390edb77558e4381401f03efda0c83","tests/ui/multiple_others.stderr":"a300f94d2a2049d6718866d17b5673201edc275164b9e8eba25a9ffcd71fd30f","tests/ui/non_unit_variant.rs":"0d8295ae08d882fc3ef4164857240038c5b0674ff0811da9b6ea7343e8bb955c","tests/ui/non_unit_variant.stderr":"18f2900e501b8c64b980445758ca1cb59594dc8d24a1a76abb08a48d8beb3f35","tests/ui/not_enum.rs":"ada7637821c924a6b99175363c820375991be60223f96ca553d304fde2721386","tests/ui/not_enum.stderr":"814525f9a1495225511a02ad4149c9371ea622230b8002564fe83cf52300c728"},"package":"1fe39d9fbb0ebf5eb2c7cb7e2a47e4f462fad1379f1166b8ae49ad9eae89a7ca"} \ No newline at end of file
+{"files":{"Cargo.toml":"eeae9b55dbaecf1fbe4505c7a202da3143336766d2f6bc6880776d3a724884f5","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"23f18e03dc49df91622fe2a76176497404e46ced8a715d9d2b67a7446571cca3","README.md":"eeaecee94e896222307c54e647a2ca546e3f7a778f5a37f9a33300c9a3260324","src/lib.rs":"7acb4fb05f93dd98a0f2c83de6da38ed68e882c7b7ea244aa607c1c5113f8509","src/parse.rs":"687cf1436d12c0c26b1c6d06f80e56b4ec0d63a38d71e1f175b981c0fdc10c68","tests/compiletest.rs":"022a8e400ef813d7ea1875b944549cee5125f6a995dc33e93b48cba3e1b57bd1","tests/test.rs":"a4ddb956ee9eafc0b50694075497a2712a347f1a682f9038e2dd654c6605af44","tests/ui/empty_enum.rs":"fe1166f2f92ee213d26a23e57572a99c65c163d446fd8d67e1520bab34f4b859","tests/ui/empty_enum.stderr":"2c8907fc146bb4dcdb926b72de4f823dae4c1c0d8de8a636c512539408f26cc7","tests/ui/missing_repr.rs":"b7ba9341111582cad52e761b82f14778c60352014c4265566e4d4d01ccdcb306","tests/ui/missing_repr.stderr":"dfcb65527963fb8962e1442e10d3c71e141f238b1732483e1739b528ae0eca43","tests/ui/multiple_others.rs":"569658516619719f21e5071873a37125d5390edb77558e4381401f03efda0c83","tests/ui/multiple_others.stderr":"a300f94d2a2049d6718866d17b5673201edc275164b9e8eba25a9ffcd71fd30f","tests/ui/non_unit_variant.rs":"0d8295ae08d882fc3ef4164857240038c5b0674ff0811da9b6ea7343e8bb955c","tests/ui/non_unit_variant.stderr":"18f2900e501b8c64b980445758ca1cb59594dc8d24a1a76abb08a48d8beb3f35","tests/ui/not_enum.rs":"ada7637821c924a6b99175363c820375991be60223f96ca553d304fde2721386","tests/ui/not_enum.stderr":"814525f9a1495225511a02ad4149c9371ea622230b8002564fe83cf52300c728"},"package":"9a5ec9fa74a20ebbe5d9ac23dac1fc96ba0ecfe9f50f2843b52e537b10fbcb4e"} \ No newline at end of file
diff --git a/vendor/serde_repr/Cargo.toml b/vendor/serde_repr/Cargo.toml
index 6cbdafeae..d1a4916e0 100644
--- a/vendor/serde_repr/Cargo.toml
+++ b/vendor/serde_repr/Cargo.toml
@@ -13,7 +13,7 @@
edition = "2018"
rust-version = "1.31"
name = "serde_repr"
-version = "0.1.9"
+version = "0.1.10"
authors = ["David Tolnay <dtolnay@gmail.com>"]
description = "Derive Serialize and Deserialize that delegates to the underlying repr of a C-like enum."
documentation = "https://docs.rs/serde_repr"
diff --git a/vendor/serde_repr/README.md b/vendor/serde_repr/README.md
index 8c8dee1ea..a932449e5 100644
--- a/vendor/serde_repr/README.md
+++ b/vendor/serde_repr/README.md
@@ -4,7 +4,7 @@ Serde repr derive
[<img alt="github" src="https://img.shields.io/badge/github-dtolnay/serde--repr-8da0cb?style=for-the-badge&labelColor=555555&logo=github" height="20">](https://github.com/dtolnay/serde-repr)
[<img alt="crates.io" src="https://img.shields.io/crates/v/serde_repr.svg?style=for-the-badge&color=fc8d62&logo=rust" height="20">](https://crates.io/crates/serde_repr)
[<img alt="docs.rs" src="https://img.shields.io/badge/docs.rs-serde__repr-66c2a5?style=for-the-badge&labelColor=555555&logo=docs.rs" height="20">](https://docs.rs/serde_repr)
-[<img alt="build status" src="https://img.shields.io/github/workflow/status/dtolnay/serde-repr/CI/master?style=for-the-badge" height="20">](https://github.com/dtolnay/serde-repr/actions?query=branch%3Amaster)
+[<img alt="build status" src="https://img.shields.io/github/actions/workflow/status/dtolnay/serde-repr/ci.yml?branch=master&style=for-the-badge" height="20">](https://github.com/dtolnay/serde-repr/actions?query=branch%3Amaster)
This crate provides a derive macro to derive Serde's `Serialize` and
`Deserialize` traits in a way that delegates to the underlying repr of a C-like
diff --git a/vendor/snap/.cargo-checksum.json b/vendor/snap/.cargo-checksum.json
index 6fc40889e..ca9b28aad 100644
--- a/vendor/snap/.cargo-checksum.json
+++ b/vendor/snap/.cargo-checksum.json
@@ -1 +1 @@
-{"files":{"COPYING":"7ca1297d23644e30bd489193a82a33f324e5fe33f25df4195649b91b883df967","Cargo.lock":"5e2cad11e762a0ae36613c821b6ff8a8eb27001a676eed4a2a0d2f60ef276858","Cargo.toml":"82e6f46a064cad4d4fd5e0d9efcd6ccfa6500809d6b2654538866974e11de79c","README.md":"7519de7d11a582319372ec90bc12c41ed1bc4348a3d8ed10a07fc940c9810549","build.rs":"afae7dd3c45a9a46bcce096e9e0aa9e36ade171e8fd00309969478025b82cac1","examples/compress-escaped.rs":"cef1933dbc5d9b496587c4c1a596f26e326e73799ab9a0ede1c3d76b00676090","examples/compress.rs":"34bad60450e768ed4ac27edf8622abc4d918b17e57b8c286030203e2b3590c24","examples/decompress.rs":"87aa11875ec98f253c8b48ce3a202ac3412063ce2f64387074194151c11fff5e","rustfmt.toml":"1ca600239a27401c4a43f363cf3f38183a212affc1f31bff3ae93234bbaec228","src/bytes.rs":"2eb9783acdf949ef96a9031d2bd43ead65db50a41a60ad98dc117cd61655c7c4","src/compress.rs":"e6f3160be400c2a4869d71210a2558ba8b438b835b632a12b7ff487660db093f","src/crc32.rs":"9f3858bef802640c595705c496f462d0343c4adcff9bdf333a43306fb67db7ae","src/crc32_table.rs":"e999470ca10bb7914887747be838d05d0f5059ae99a8b8c57b0be7de3931e72a","src/decompress.rs":"05c4d0c0922b1ad084cf32f224722f2fe9d63128d6a4da0c44333742d681b80f","src/error.rs":"ba50d0652e50198d6ab42d23788f726d083ba69d8b2459a10a00cc83755dbbd0","src/frame.rs":"4f69a9526a5dd0367631fc7a764bea877f7f0b4c33ee30d4ece62913c42ea48d","src/lib.rs":"1f4dc31068bc60a327ecd632993eaa40feb0b2198affdb1a00a7a9538b23b527","src/raw.rs":"a7048da3a4b76b75e4b3d071ee9959dbf12c5b3a36dabb2f7878513507c80cb9","src/read.rs":"7528c6487d90c4f6170982e5393f56b3a01443b14abac3d4f41d94b7f3beb3f1","src/tag.rs":"9ac94977c5ab3ea687b9441ea3c615f64a23eac11a4bade19cfa3be5968cb718","src/varint.rs":"6d63fca6323c91f193628a41b6e75f5b3443777467e6a5665907bbbba549e6c7","src/write.rs":"086edd9fb1442b6bc8bf8c6a80023eccc4ca627de57ccc62279691c9ff7f0786"},"package":"45456094d1983e2ee2a18fdfebce3189fa451699d0502cb8e3b49dba5ba41451"} \ No newline at end of file
+{"files":{"COPYING":"7ca1297d23644e30bd489193a82a33f324e5fe33f25df4195649b91b883df967","Cargo.lock":"d6e31fa248a50ec25e0cf04bde1f74cadd620705b80dfb4fadd5eb7372cc6397","Cargo.toml":"5fd2ac1dc31bbbf63f2888183f142eafbb940b0dc9eff6b93552475a2e0af316","README.md":"7519de7d11a582319372ec90bc12c41ed1bc4348a3d8ed10a07fc940c9810549","build.rs":"afae7dd3c45a9a46bcce096e9e0aa9e36ade171e8fd00309969478025b82cac1","examples/compress-escaped.rs":"cef1933dbc5d9b496587c4c1a596f26e326e73799ab9a0ede1c3d76b00676090","examples/compress.rs":"34bad60450e768ed4ac27edf8622abc4d918b17e57b8c286030203e2b3590c24","examples/decompress.rs":"87aa11875ec98f253c8b48ce3a202ac3412063ce2f64387074194151c11fff5e","rustfmt.toml":"1ca600239a27401c4a43f363cf3f38183a212affc1f31bff3ae93234bbaec228","src/bytes.rs":"2eb9783acdf949ef96a9031d2bd43ead65db50a41a60ad98dc117cd61655c7c4","src/compress.rs":"e6f3160be400c2a4869d71210a2558ba8b438b835b632a12b7ff487660db093f","src/crc32.rs":"9f3858bef802640c595705c496f462d0343c4adcff9bdf333a43306fb67db7ae","src/crc32_table.rs":"e999470ca10bb7914887747be838d05d0f5059ae99a8b8c57b0be7de3931e72a","src/decompress.rs":"05c4d0c0922b1ad084cf32f224722f2fe9d63128d6a4da0c44333742d681b80f","src/error.rs":"61e474876cb019ccd34981d8fd5f491e6684d3bfe2e444f0752faddcdc5c0491","src/frame.rs":"4f69a9526a5dd0367631fc7a764bea877f7f0b4c33ee30d4ece62913c42ea48d","src/lib.rs":"1f4dc31068bc60a327ecd632993eaa40feb0b2198affdb1a00a7a9538b23b527","src/raw.rs":"a7048da3a4b76b75e4b3d071ee9959dbf12c5b3a36dabb2f7878513507c80cb9","src/read.rs":"500881e24c820f4fb3f63af1c1de3fc65b0e8aeaee136d4dab20fd15d11c466d","src/tag.rs":"9ac94977c5ab3ea687b9441ea3c615f64a23eac11a4bade19cfa3be5968cb718","src/varint.rs":"6d63fca6323c91f193628a41b6e75f5b3443777467e6a5665907bbbba549e6c7","src/write.rs":"086edd9fb1442b6bc8bf8c6a80023eccc4ca627de57ccc62279691c9ff7f0786"},"package":"5e9f0ab6ef7eb7353d9119c170a436d1bf248eea575ac42d19d12f4e34130831"} \ No newline at end of file
diff --git a/vendor/snap/Cargo.lock b/vendor/snap/Cargo.lock
index 8ddce9d43..4b58a3045 100644
--- a/vendor/snap/Cargo.lock
+++ b/vendor/snap/Cargo.lock
@@ -1,14 +1,16 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
+version = 3
+
[[package]]
name = "doc-comment"
-version = "0.3.1"
+version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "923dea538cea0aa3025e8685b20d6ee21ef99c4f77e954a30febbaac5ec73a97"
+checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10"
[[package]]
name = "snap"
-version = "1.0.5"
+version = "1.1.0"
dependencies = [
"doc-comment",
]
diff --git a/vendor/snap/Cargo.toml b/vendor/snap/Cargo.toml
index 8559a1e4b..12ad5ddeb 100644
--- a/vendor/snap/Cargo.toml
+++ b/vendor/snap/Cargo.toml
@@ -3,26 +3,35 @@
# When uploading crates to the registry Cargo will automatically
# "normalize" Cargo.toml files for maximal compatibility
# with all versions of Cargo and also rewrite `path` dependencies
-# to registry (e.g., crates.io) dependencies
+# to registry (e.g., crates.io) dependencies.
#
-# If you believe there's an error in this file please file an
-# issue against the rust-lang/cargo repository. If you're
-# editing this file be aware that the upstream Cargo.toml
-# will likely look very different (and much more reasonable)
+# If you are reading this file be aware that the original Cargo.toml
+# will likely look very different (and much more reasonable).
+# See Cargo.toml.orig for the original contents.
[package]
edition = "2018"
name = "snap"
-version = "1.0.5"
+version = "1.1.0"
authors = ["Andrew Gallant <jamslam@gmail.com>"]
exclude = ["data/*"]
-description = "A pure Rust implementation of the Snappy compression algorithm. Includes\nstreaming compression and decompression.\n"
+description = """
+A pure Rust implementation of the Snappy compression algorithm. Includes
+streaming compression and decompression.
+"""
homepage = "https://github.com/BurntSushi/rust-snappy"
documentation = "https://docs.rs/snap"
readme = "README.md"
-keywords = ["snappy", "compress", "compression", "decompress", "decompression"]
+keywords = [
+ "snappy",
+ "compress",
+ "compression",
+ "decompress",
+ "decompression",
+]
license = "BSD-3-Clause"
repository = "https://github.com/BurntSushi/rust-snappy"
+
[profile.release]
debug = true
@@ -31,5 +40,6 @@ opt-level = 3
[lib]
bench = false
+
[dev-dependencies.doc-comment]
version = "0.3.1"
diff --git a/vendor/snap/src/error.rs b/vendor/snap/src/error.rs
index 8f0b400a6..99073aa0a 100644
--- a/vendor/snap/src/error.rs
+++ b/vendor/snap/src/error.rs
@@ -29,6 +29,13 @@ impl<W> IntoInnerError<W> {
&self.err
}
+ /// Returns the error which caused the call to `into_inner` to fail.
+ ///
+ /// This error was returned when attempting to flush the internal buffer.
+ pub fn into_error(self) -> io::Error {
+ self.err
+ }
+
/// Returns the underlying writer which generated the error.
///
/// The returned value can be used for error recovery, such as
diff --git a/vendor/snap/src/read.rs b/vendor/snap/src/read.rs
index a924bf91d..b78939cc5 100644
--- a/vendor/snap/src/read.rs
+++ b/vendor/snap/src/read.rs
@@ -94,6 +94,11 @@ impl<R: io::Read> FrameDecoder<R> {
pub fn get_mut(&mut self) -> &mut R {
&mut self.r
}
+
+ /// Gets the underlying reader of this decoder.
+ pub fn into_inner(self) -> R {
+ self.r
+ }
}
impl<R: io::Read> io::Read for FrameDecoder<R> {
diff --git a/vendor/syn/.cargo-checksum.json b/vendor/syn/.cargo-checksum.json
index 8b90dae0f..edd04e5cd 100644
--- a/vendor/syn/.cargo-checksum.json
+++ b/vendor/syn/.cargo-checksum.json
@@ -1 +1 @@
-{"files":{"Cargo.toml":"8366f3b0e0c3a589f43424b1837bb43aa8b4dd224184d355ad38a63bac915210","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"23f18e03dc49df91622fe2a76176497404e46ced8a715d9d2b67a7446571cca3","README.md":"b1546652aefba564455c1ebbf0f276450d4fdb19755e08bfa03c13c8bab241fc","benches/file.rs":"3d737ef3878f6e242b003af9bd539e565f98439a12ee44d9548d84e3fdd7af0c","benches/rust.rs":"11ac9fe898a7bf1bd63e8a8cc9c08bd795b01f0248215cff99afaaf28ce87fab","build.rs":"b815649fd2929d3debd93a58f5da2fb8eba506047a6a5ba538347305828a87b0","src/attr.rs":"234d9cebe2c5e92cd0f5e1117bf5755037e2e905788a337000a65d4bd82b63aa","src/await.rs":"8aa22e3c201cb2bdb6b4817fa00901f308ab06817607aa7b884c58c957705969","src/bigint.rs":"efc7f64959980653d73fe4f8bc2a3a2904dc05f45b02c6dc15cd316fa3d7c338","src/buffer.rs":"2b48296087f096c9630e1e4b03a00ae703407d1b352902b3197370b2f56c62ff","src/custom_keyword.rs":"5c706fc3611e73d16b8c019d7ecb848a86b1ccfcd9e556f80bb6e6a4abe058a8","src/custom_punctuation.rs":"8a666298e774b0d326642f0f73284f6677d0d0a7c9e4a712c9c98d010b4d8a2c","src/data.rs":"75d2c2b5d6a01bf8a6fa2845e41663d8045a78b4b191f1a1bd7c93619d20017a","src/derive.rs":"ee24a202be2d36ccdff576dd9cd765e94b33ef2286946e6725d75b08e777d462","src/discouraged.rs":"6c6a9298f8d24f578da119557bc588f3bd928f7b79fca27d6bdfe3e786dd005f","src/error.rs":"e548cc5b7c6f742ab6c19788755980594c4cb8086f99e6709f1cbc982961102d","src/export.rs":"0cf50d70c32d5fddba8b1193032df62e560237c113df3e86ba26b565cc82838e","src/expr.rs":"5eea3828f3291b0ce5463ed5f0c23fc8a39aeceae68a3247ae02ae467dd35a98","src/ext.rs":"1f648cff1d705a1cea64b32b77482b97a82d2fe0aaf63b40cade91e5c02dc969","src/file.rs":"f86697655222ae294215114f4eae8e6b0b5e2a935d6c479ff8f8f889c4efd2e2","src/gen/clone.rs":"76e89fe155fedf43bc4a252af7e35319b82ce455f584bad8698fdc3f9b7f5d4e","src/gen/debug.rs":"4b05e474e864ce6bf1a5a6ab48ee6c0ecdf41a0d750237990cf2e31963bc1208","src/gen/eq.rs":"79f84836fdcd5cfa352f38055dab7c3246c7757650946c1c701234b11021652a","src/gen/fold.rs":"fcd6a05c8c8e0c36e7ede8593002528b553c8b648fbed452106fd6a8a8c9212a","src/gen/hash.rs":"575e8beae303c1eabda12bf76cbd82672268c502a8ebb8517aab18b40fdbc44e","src/gen/visit.rs":"ced9f6c17d2b3eb3553faab710cb2b3d44d6bca7d1862c8c5da09c3d45debecb","src/gen/visit_mut.rs":"966ea340c53461bf8a1c6bed3c882e4ab8b8907fd18ac35531266f7891ae5f46","src/gen_helper.rs":"ea6c66388365971db6a2fc86cbb208f7eacde77e245bc8623f27a3642a3d7741","src/generics.rs":"46ed41bf116448822ddfefcb62e803fd33264ca8ba672efc0612674d85b6dd11","src/group.rs":"166f0fbb365471ffa3e4f554b72c2b460cbf7e3a1f9bec6c01ef6bbbcd751041","src/ident.rs":"2443e43561abea7eea577b141422258237a663499c839923d8a5ca6fea2470db","src/item.rs":"419c4d6135a7ca7b8f94b5ba038b6af8fcb3939ae807153a19e3c82e9b01e0b7","src/lib.rs":"7875551b227d19f083115d48a83e8c35e3e6d31dbd749bdd03556e2762f7d4fd","src/lifetime.rs":"b18862ef1e690037a4f308ea897debad7bc5038584e3b26c6d8809752ea0e3c2","src/lit.rs":"fc06ddd523f7f9971d8abdb4c8d5d51030ffb3d6810615d5575ae210a7800695","src/lookahead.rs":"e2c2b6d55906421e83dab51463b58bc6dcb582f1bff9303c8b62afefb8d71e5f","src/mac.rs":"004cb89f9697564f6c9ee837e08ead68463ef946fb4c13c6c105adf2ba364b2b","src/macros.rs":"936f503c2fcde602f05220954ecaf87625c6138d0af13d33d56c7b6530110084","src/op.rs":"9d499022902743a6a0a19223b356449a979b90e60552d0446497d72750e646a4","src/parse.rs":"7b2f8caddf25a5734cbcdf7cbf043cbf9afbc07b484966cd59ddfcec9f970fb3","src/parse_macro_input.rs":"a5d16859b782bb6a2754c1066468a2f1ea05b57390caa32175bb84064973be7b","src/parse_quote.rs":"d7d996f1382c68b5fbfd4b7327ce1d389cd43c3bb3c4f382a35994d0bb79d8ab","src/pat.rs":"b2de04ae6c01df50eab9d1c3908287aca8424adc2007b926c7bcf74d1f64d40a","src/path.rs":"269d5d8b0c21eaf96e1c49bcb1ec2a03175a8adcc103c142e550b3f5e79825d8","src/print.rs":"da6529c1d9d21aaf6c835f66b4e67eacb7cf91a10eb5e9a2143b49bf99b3b5e1","src/punctuated.rs":"f687c23bd3ae512e7412c28ac68030d3bc7a384d1ca8b3da6620e364b0cbbb78","src/reserved.rs":"e70e028bd55cfa43e23cab4ba29e4dc53a3d91eff685ef2b6e57efc2b87a3428","src/sealed.rs":"896a495a5340eec898527f18bd4ddca408ea03ea0ee3af30074ff48deace778d","src/span.rs":"748c51c6feb223c26d3b1701f5bb98aee823666c775c98106cfa24fe29d8cec1","src/spanned.rs":"3ca016a943637653ab98e373dfb826a120f3c159867346fa38a844439944eb39","src/stmt.rs":"601a6914f1e0bf97ae0d31d474a531d195b8c251a4ded11aa8746ac0018d367b","src/thread.rs":"815eca6bd64f4eef7c447f0809e84108f5428ff50225224b373efd8fbb696874","src/token.rs":"5e423a696f80e281c322f37c87577f9fdc28607e9c007e24896a2b12da62d5ad","src/tt.rs":"32402645b6e82ef1e882945721b59b5fb7b0ee337d1972876362ecacef643d0f","src/ty.rs":"7e678749af18fc84ae9220435e467e520de05eea66adeeed3b5d634cd744561c","src/verbatim.rs":"802a97df997432f18cac6e6200ff6ea29fb2474986005e0fcdbc2b65197f87f7","src/whitespace.rs":"e63dd0aa3d34029f17766a8b09c1a6e4479e36c552c8b7023d710a399333aace","tests/common/eq.rs":"953f5db261a3334eba1d37df4247463e9234c7988da04f43028b5273d24bf2da","tests/common/mod.rs":"432ad35577f836a20b517d8c26ed994ac25fe73ef2f461c67688b61b99762015","tests/common/parse.rs":"81580f23583723f7a2a337c4d13ebc021057cd825562fb4e474caa7cc641fed9","tests/debug/gen.rs":"1b7f875344cb04a7dd3df62deac2f410a9d107c097986e68006d87465f5f5306","tests/debug/mod.rs":"3a6bb799f478101f71c84c6f1a854a58afe2f9db43c39017909346ca20262d94","tests/macros/mod.rs":"aff805b35cfd55aef6a1359ff747e4023afcb08d69d86aff4c19465d29dda088","tests/regression.rs":"f962ebf24007f631f7e702e34e142d07581da7c9a36321ac142cafed1a0afc69","tests/regression/issue1108.rs":"adcc55a42239d344da74216ed85fc14153ddd6ca4dec4872d8339604ba78c185","tests/repo/mod.rs":"1ea18f9430e75cabc4b23b826544c2bf2f950b679a04b237a11e17aabc16e2e9","tests/repo/progress.rs":"c08d0314a7f3ecf760d471f27da3cd2a500aeb9f1c8331bffb2aa648f9fabf3f","tests/test_asyncness.rs":"cff01db49d28ab23b0b258bc6c0a5cc4071be4fe7248eef344a5d79d2fb649b7","tests/test_attribute.rs":"0ffd99384e1a52ae17d9fed5c4053e411e8f9018decef07ffa621d1faa7329d8","tests/test_derive_input.rs":"62bb86aaaaf730187a46ff700a8e3b2d1a163039b109b6a483aa44ed2b6806fe","tests/test_expr.rs":"a639728866a063b590430965a4840c01755e398b89be12d8d09b0aa97837ecac","tests/test_generics.rs":"54b7d2afc19aa6e9049585f4c8f7d3f0c29ac3bd11a2c769e9df76f18a4f5ecb","tests/test_grouping.rs":"6276c3c73bba649dec5c97904ad2492879f918bc887a2c425d095c654ca0d925","tests/test_ident.rs":"9eb53d1e21edf23e7c9e14dc74dcc2b2538e9221e19dbcc0a44e3acc2e90f3f6","tests/test_item.rs":"a3642c80066f1e7787becfd0278af90a6b7968d6c1249e25e81663aa454cfb2a","tests/test_iterators.rs":"53ed6078d37550bd6765d2411e3660be401aef8a31a407350cc064a7d08c7c33","tests/test_lit.rs":"19740ea9cd4a980bcab9b0dcaa4b032bb6ebb137fa5e4237140b97da1d9679fa","tests/test_meta.rs":"65d4586d131f6cac66694ca5e936748ec4e7f7423af6d8da509240e6be14800b","tests/test_parse_buffer.rs":"68d857f776396d064fcc0023c37093c2fbf75ee68e8241d4014d00d1423c18e9","tests/test_parse_stream.rs":"bf1db6fab7ac396fa61012faccbe6ffbc9c3d795ed2900be75e91c5b09b0c62f","tests/test_pat.rs":"d4465f4fc3fd5d6e534ba8efabe1e0ed6da89de4ac7c96effa6bfb880c4287cf","tests/test_path.rs":"71092a5ae2c9143b92a8fe15a92d39958b3c28bd4d4275cfb2d22cbdd53ada07","tests/test_precedence.rs":"736eee861c4c7a3d7d4387d2fb1b5eced1541790d34974f72b0a5532797e73c3","tests/test_receiver.rs":"084eca59984b9a18651da52f2c4407355da3de1335916a12477652999e2d01cc","tests/test_round_trip.rs":"b47662e35be2729f28bacdbbea20f1879c111889430e735a7bcb5f2a5c0b9e5c","tests/test_shebang.rs":"f5772cadad5b56e3112cb16308b779f92bce1c3a48091fc9933deb2276a69331","tests/test_should_parse.rs":"1d3535698a446e2755bfc360676bdb161841a1f454cdef6e7556c6d06a95c89d","tests/test_size.rs":"697906d892ab8186eebdf6bc7696fde7a42376d50bee846ba69f031bdb847e01","tests/test_stmt.rs":"0601fc32131b5501dfcdc4b4248d46bf21e0a98a49eb19439e1a46869dfb30b7","tests/test_token_trees.rs":"43e56a701817e3c3bfd0cae54a457dd7a38ccb3ca19da41e2b995fdf20e6ed18","tests/test_ty.rs":"f71d7f7f1c038aaabea8dd4c03c0d5752c76d570f8b4885a81659825bbb4d576","tests/test_visibility.rs":"7456fcb3a6634db509748aededff9c2d8b242d511a3e5ee3022e40b232892704","tests/zzz_stable.rs":"2a862e59cb446235ed99aec0e6ada8e16d3ecc30229b29d825b7c0bbc2602989"},"package":"3fcd952facd492f9be3ef0d0b7032a6e442ee9b361d4acc2b1d0c4aaa5f613a1"} \ No newline at end of file
+{"files":{"Cargo.toml":"1ff565970239963d56cbfdd20476fd265fcf2d050fc5ed92a298686321985230","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"23f18e03dc49df91622fe2a76176497404e46ced8a715d9d2b67a7446571cca3","README.md":"ea9f2b6340b302b5608d2bedcda7e2d707f3eaebf4cc983c02d55071ead7096f","benches/file.rs":"3d737ef3878f6e242b003af9bd539e565f98439a12ee44d9548d84e3fdd7af0c","benches/rust.rs":"11ac9fe898a7bf1bd63e8a8cc9c08bd795b01f0248215cff99afaaf28ce87fab","build.rs":"b815649fd2929d3debd93a58f5da2fb8eba506047a6a5ba538347305828a87b0","src/attr.rs":"234d9cebe2c5e92cd0f5e1117bf5755037e2e905788a337000a65d4bd82b63aa","src/await.rs":"8aa22e3c201cb2bdb6b4817fa00901f308ab06817607aa7b884c58c957705969","src/bigint.rs":"efc7f64959980653d73fe4f8bc2a3a2904dc05f45b02c6dc15cd316fa3d7c338","src/buffer.rs":"4d15f35273d485261be4f1a765ae03abc1daee9fc9dac5fb4f9b624d6b22cb58","src/custom_keyword.rs":"5c706fc3611e73d16b8c019d7ecb848a86b1ccfcd9e556f80bb6e6a4abe058a8","src/custom_punctuation.rs":"8a666298e774b0d326642f0f73284f6677d0d0a7c9e4a712c9c98d010b4d8a2c","src/data.rs":"75d2c2b5d6a01bf8a6fa2845e41663d8045a78b4b191f1a1bd7c93619d20017a","src/derive.rs":"ee24a202be2d36ccdff576dd9cd765e94b33ef2286946e6725d75b08e777d462","src/discouraged.rs":"6c6a9298f8d24f578da119557bc588f3bd928f7b79fca27d6bdfe3e786dd005f","src/drops.rs":"013385f1dd95663f1afab41abc1e2eea04181998644828935ca564c74d6462ae","src/error.rs":"b30e738fdab7d10e126350e09f7ad907bf4dc14e684b9ed9eeea001c7ee356e0","src/export.rs":"0cf50d70c32d5fddba8b1193032df62e560237c113df3e86ba26b565cc82838e","src/expr.rs":"5eea3828f3291b0ce5463ed5f0c23fc8a39aeceae68a3247ae02ae467dd35a98","src/ext.rs":"1f648cff1d705a1cea64b32b77482b97a82d2fe0aaf63b40cade91e5c02dc969","src/file.rs":"f86697655222ae294215114f4eae8e6b0b5e2a935d6c479ff8f8f889c4efd2e2","src/gen/clone.rs":"76e89fe155fedf43bc4a252af7e35319b82ce455f584bad8698fdc3f9b7f5d4e","src/gen/debug.rs":"4b05e474e864ce6bf1a5a6ab48ee6c0ecdf41a0d750237990cf2e31963bc1208","src/gen/eq.rs":"79f84836fdcd5cfa352f38055dab7c3246c7757650946c1c701234b11021652a","src/gen/fold.rs":"fcd6a05c8c8e0c36e7ede8593002528b553c8b648fbed452106fd6a8a8c9212a","src/gen/hash.rs":"575e8beae303c1eabda12bf76cbd82672268c502a8ebb8517aab18b40fdbc44e","src/gen/visit.rs":"ced9f6c17d2b3eb3553faab710cb2b3d44d6bca7d1862c8c5da09c3d45debecb","src/gen/visit_mut.rs":"966ea340c53461bf8a1c6bed3c882e4ab8b8907fd18ac35531266f7891ae5f46","src/gen_helper.rs":"ea6c66388365971db6a2fc86cbb208f7eacde77e245bc8623f27a3642a3d7741","src/generics.rs":"b81ce0d3ea0f7accef4590d5181cecc4589395865abaea60b0470da727f17340","src/group.rs":"166f0fbb365471ffa3e4f554b72c2b460cbf7e3a1f9bec6c01ef6bbbcd751041","src/ident.rs":"2443e43561abea7eea577b141422258237a663499c839923d8a5ca6fea2470db","src/item.rs":"419c4d6135a7ca7b8f94b5ba038b6af8fcb3939ae807153a19e3c82e9b01e0b7","src/lib.rs":"8c152481907905472fc3e4aae63f82ed78d4d16cf8cc286675727668760c7f2e","src/lifetime.rs":"b18862ef1e690037a4f308ea897debad7bc5038584e3b26c6d8809752ea0e3c2","src/lit.rs":"fc06ddd523f7f9971d8abdb4c8d5d51030ffb3d6810615d5575ae210a7800695","src/lookahead.rs":"e2c2b6d55906421e83dab51463b58bc6dcb582f1bff9303c8b62afefb8d71e5f","src/mac.rs":"004cb89f9697564f6c9ee837e08ead68463ef946fb4c13c6c105adf2ba364b2b","src/macros.rs":"936f503c2fcde602f05220954ecaf87625c6138d0af13d33d56c7b6530110084","src/op.rs":"9d499022902743a6a0a19223b356449a979b90e60552d0446497d72750e646a4","src/parse.rs":"7b2f8caddf25a5734cbcdf7cbf043cbf9afbc07b484966cd59ddfcec9f970fb3","src/parse_macro_input.rs":"a5d16859b782bb6a2754c1066468a2f1ea05b57390caa32175bb84064973be7b","src/parse_quote.rs":"d7d996f1382c68b5fbfd4b7327ce1d389cd43c3bb3c4f382a35994d0bb79d8ab","src/pat.rs":"b2de04ae6c01df50eab9d1c3908287aca8424adc2007b926c7bcf74d1f64d40a","src/path.rs":"58a4fb3b1ff76d32cfd84a3914f8cadbf55b363c1929222b362b7465385520ac","src/print.rs":"da6529c1d9d21aaf6c835f66b4e67eacb7cf91a10eb5e9a2143b49bf99b3b5e1","src/punctuated.rs":"44c29523dee76605be2531674fe21ed2f1bbd02559aac8b7a49c70af23129ca1","src/reserved.rs":"e70e028bd55cfa43e23cab4ba29e4dc53a3d91eff685ef2b6e57efc2b87a3428","src/sealed.rs":"896a495a5340eec898527f18bd4ddca408ea03ea0ee3af30074ff48deace778d","src/span.rs":"748c51c6feb223c26d3b1701f5bb98aee823666c775c98106cfa24fe29d8cec1","src/spanned.rs":"3ca016a943637653ab98e373dfb826a120f3c159867346fa38a844439944eb39","src/stmt.rs":"601a6914f1e0bf97ae0d31d474a531d195b8c251a4ded11aa8746ac0018d367b","src/thread.rs":"815eca6bd64f4eef7c447f0809e84108f5428ff50225224b373efd8fbb696874","src/token.rs":"5e423a696f80e281c322f37c87577f9fdc28607e9c007e24896a2b12da62d5ad","src/tt.rs":"32402645b6e82ef1e882945721b59b5fb7b0ee337d1972876362ecacef643d0f","src/ty.rs":"9befd22f8c8ac731b7f68008552a1335797a3ef19184190eec0e103e4ebe18a7","src/verbatim.rs":"96d4280e4556a1841b8dcb306bc35a94d18f71dceb63f3c27a4fe7f776191760","src/whitespace.rs":"e63dd0aa3d34029f17766a8b09c1a6e4479e36c552c8b7023d710a399333aace","tests/common/eq.rs":"e930fb0bdcec3e787986b56785b1db580e5a26a5131df2f2b91a6da37069de15","tests/common/mod.rs":"432ad35577f836a20b517d8c26ed994ac25fe73ef2f461c67688b61b99762015","tests/common/parse.rs":"81580f23583723f7a2a337c4d13ebc021057cd825562fb4e474caa7cc641fed9","tests/debug/gen.rs":"1b7f875344cb04a7dd3df62deac2f410a9d107c097986e68006d87465f5f5306","tests/debug/mod.rs":"3a6bb799f478101f71c84c6f1a854a58afe2f9db43c39017909346ca20262d94","tests/macros/mod.rs":"aff805b35cfd55aef6a1359ff747e4023afcb08d69d86aff4c19465d29dda088","tests/regression.rs":"86731134bfb9bb693d9a4fc62393027de80a8bf031109ea6c7ea475b1ebdde8d","tests/regression/issue1108.rs":"adcc55a42239d344da74216ed85fc14153ddd6ca4dec4872d8339604ba78c185","tests/regression/issue1235.rs":"a2266b10c3f7c7af5734817ab0a3e8b309b51e7d177b63f26e67e6b744d280b0","tests/repo/mod.rs":"159c2c4b6416d26ac42ffc35f6cb587c4c1e2b0f24de9aa42b0337a534d7d86d","tests/repo/progress.rs":"c08d0314a7f3ecf760d471f27da3cd2a500aeb9f1c8331bffb2aa648f9fabf3f","tests/test_asyncness.rs":"cff01db49d28ab23b0b258bc6c0a5cc4071be4fe7248eef344a5d79d2fb649b7","tests/test_attribute.rs":"0ffd99384e1a52ae17d9fed5c4053e411e8f9018decef07ffa621d1faa7329d8","tests/test_derive_input.rs":"62bb86aaaaf730187a46ff700a8e3b2d1a163039b109b6a483aa44ed2b6806fe","tests/test_expr.rs":"41eb343829ad36cdea40cd06d45a90765e7fe6f1e47dd550daf1b6096c3a7b44","tests/test_generics.rs":"54b7d2afc19aa6e9049585f4c8f7d3f0c29ac3bd11a2c769e9df76f18a4f5ecb","tests/test_grouping.rs":"6276c3c73bba649dec5c97904ad2492879f918bc887a2c425d095c654ca0d925","tests/test_ident.rs":"9eb53d1e21edf23e7c9e14dc74dcc2b2538e9221e19dbcc0a44e3acc2e90f3f6","tests/test_item.rs":"a3642c80066f1e7787becfd0278af90a6b7968d6c1249e25e81663aa454cfb2a","tests/test_iterators.rs":"9cf6fde17853ce7d5617e1de9ef901c47ca35c0f1c2dd668c0d0604d7b48598c","tests/test_lit.rs":"19740ea9cd4a980bcab9b0dcaa4b032bb6ebb137fa5e4237140b97da1d9679fa","tests/test_meta.rs":"65d4586d131f6cac66694ca5e936748ec4e7f7423af6d8da509240e6be14800b","tests/test_parse_buffer.rs":"68d857f776396d064fcc0023c37093c2fbf75ee68e8241d4014d00d1423c18e9","tests/test_parse_stream.rs":"bf1db6fab7ac396fa61012faccbe6ffbc9c3d795ed2900be75e91c5b09b0c62f","tests/test_pat.rs":"d4465f4fc3fd5d6e534ba8efabe1e0ed6da89de4ac7c96effa6bfb880c4287cf","tests/test_path.rs":"71092a5ae2c9143b92a8fe15a92d39958b3c28bd4d4275cfb2d22cbdd53ada07","tests/test_precedence.rs":"736eee861c4c7a3d7d4387d2fb1b5eced1541790d34974f72b0a5532797e73c3","tests/test_receiver.rs":"084eca59984b9a18651da52f2c4407355da3de1335916a12477652999e2d01cc","tests/test_round_trip.rs":"c3c415413d5177a728c7cbbfb7ef44aebbc6a2c821dd56695156e9e33636fd57","tests/test_shebang.rs":"f5772cadad5b56e3112cb16308b779f92bce1c3a48091fc9933deb2276a69331","tests/test_should_parse.rs":"1d3535698a446e2755bfc360676bdb161841a1f454cdef6e7556c6d06a95c89d","tests/test_size.rs":"6720d55569808244ab011364c39931f06aa509cd05f98ab908b0670e8501b3c8","tests/test_stmt.rs":"0601fc32131b5501dfcdc4b4248d46bf21e0a98a49eb19439e1a46869dfb30b7","tests/test_token_trees.rs":"43e56a701817e3c3bfd0cae54a457dd7a38ccb3ca19da41e2b995fdf20e6ed18","tests/test_ty.rs":"f71d7f7f1c038aaabea8dd4c03c0d5752c76d570f8b4885a81659825bbb4d576","tests/test_visibility.rs":"7456fcb3a6634db509748aededff9c2d8b242d511a3e5ee3022e40b232892704","tests/zzz_stable.rs":"2a862e59cb446235ed99aec0e6ada8e16d3ecc30229b29d825b7c0bbc2602989"},"package":"1f4064b5b16e03ae50984a5a8ed5d4f8803e6bc1fd170a3cda91a1be4b18e3f5"} \ No newline at end of file
diff --git a/vendor/syn/Cargo.toml b/vendor/syn/Cargo.toml
index 7b1412593..c2a36013e 100644
--- a/vendor/syn/Cargo.toml
+++ b/vendor/syn/Cargo.toml
@@ -13,7 +13,7 @@
edition = "2018"
rust-version = "1.31"
name = "syn"
-version = "1.0.102"
+version = "1.0.107"
authors = ["David Tolnay <dtolnay@gmail.com>"]
include = [
"/benches/**",
@@ -56,6 +56,9 @@ features = [
"extra-traits",
]
+[lib]
+doc-scrape-examples = false
+
[[bench]]
name = "rust"
harness = false
diff --git a/vendor/syn/README.md b/vendor/syn/README.md
index 9c883ae2b..eeef83dd5 100644
--- a/vendor/syn/README.md
+++ b/vendor/syn/README.md
@@ -4,7 +4,7 @@ Parser for Rust source code
[<img alt="github" src="https://img.shields.io/badge/github-dtolnay/syn-8da0cb?style=for-the-badge&labelColor=555555&logo=github" height="20">](https://github.com/dtolnay/syn)
[<img alt="crates.io" src="https://img.shields.io/crates/v/syn.svg?style=for-the-badge&color=fc8d62&logo=rust" height="20">](https://crates.io/crates/syn)
[<img alt="docs.rs" src="https://img.shields.io/badge/docs.rs-syn-66c2a5?style=for-the-badge&labelColor=555555&logo=docs.rs" height="20">](https://docs.rs/syn)
-[<img alt="build status" src="https://img.shields.io/github/workflow/status/dtolnay/syn/CI/master?style=for-the-badge" height="20">](https://github.com/dtolnay/syn/actions?query=branch%3Amaster)
+[<img alt="build status" src="https://img.shields.io/github/actions/workflow/status/dtolnay/syn/ci.yml?branch=master&style=for-the-badge" height="20">](https://github.com/dtolnay/syn/actions?query=branch%3Amaster)
Syn is a parsing library for parsing a stream of Rust tokens into a syntax tree
of Rust source code.
diff --git a/vendor/syn/src/buffer.rs b/vendor/syn/src/buffer.rs
index 161b614c8..0d5cf30d5 100644
--- a/vendor/syn/src/buffer.rs
+++ b/vendor/syn/src/buffer.rs
@@ -14,6 +14,7 @@
use crate::proc_macro as pm;
use crate::Lifetime;
use proc_macro2::{Delimiter, Group, Ident, Literal, Punct, Spacing, Span, TokenStream, TokenTree};
+use std::cmp::Ordering;
use std::marker::PhantomData;
/// Internal type which is used instead of `TokenTree` to represent a token tree
@@ -25,7 +26,8 @@ enum Entry {
Ident(Ident),
Punct(Punct),
Literal(Literal),
- End,
+ // End entries contain the offset (negative) to the start of the buffer.
+ End(isize),
}
/// A buffer that can be efficiently traversed multiple times, unlike
@@ -48,10 +50,10 @@ impl TokenBuffer {
TokenTree::Literal(literal) => entries.push(Entry::Literal(literal)),
TokenTree::Group(group) => {
let group_start_index = entries.len();
- entries.push(Entry::End); // we replace this below
+ entries.push(Entry::End(0)); // we replace this below
Self::recursive_new(entries, group.stream());
let group_end_index = entries.len();
- entries.push(Entry::End);
+ entries.push(Entry::End(-(group_end_index as isize)));
let group_end_offset = group_end_index - group_start_index;
entries[group_start_index] = Entry::Group(group, group_end_offset);
}
@@ -77,7 +79,7 @@ impl TokenBuffer {
pub fn new2(stream: TokenStream) -> Self {
let mut entries = Vec::new();
Self::recursive_new(&mut entries, stream);
- entries.push(Entry::End);
+ entries.push(Entry::End(-(entries.len() as isize)));
Self {
entries: entries.into_boxed_slice(),
}
@@ -127,7 +129,7 @@ impl<'a> Cursor<'a> {
// object in global storage.
struct UnsafeSyncEntry(Entry);
unsafe impl Sync for UnsafeSyncEntry {}
- static EMPTY_ENTRY: UnsafeSyncEntry = UnsafeSyncEntry(Entry::End);
+ static EMPTY_ENTRY: UnsafeSyncEntry = UnsafeSyncEntry(Entry::End(0));
Cursor {
ptr: &EMPTY_ENTRY.0,
@@ -144,7 +146,7 @@ impl<'a> Cursor<'a> {
// past it, unless `ptr == scope`, which means that we're at the edge of
// our cursor's scope. We should only have `ptr != scope` at the exit
// from None-delimited groups entered with `ignore_none`.
- while let Entry::End = *ptr {
+ while let Entry::End(_) = *ptr {
if ptr == scope {
break;
}
@@ -292,7 +294,7 @@ impl<'a> Cursor<'a> {
Entry::Literal(literal) => (literal.clone().into(), 1),
Entry::Ident(ident) => (ident.clone().into(), 1),
Entry::Punct(punct) => (punct.clone().into(), 1),
- Entry::End => return None,
+ Entry::End(_) => return None,
};
let rest = unsafe { Cursor::create(self.ptr.add(len), self.scope) };
@@ -307,7 +309,7 @@ impl<'a> Cursor<'a> {
Entry::Literal(literal) => literal.span(),
Entry::Ident(ident) => ident.span(),
Entry::Punct(punct) => punct.span(),
- Entry::End => Span::call_site(),
+ Entry::End(_) => Span::call_site(),
}
}
@@ -317,7 +319,7 @@ impl<'a> Cursor<'a> {
/// This method treats `'lifetimes` as a single token.
pub(crate) fn skip(self) -> Option<Cursor<'a>> {
let len = match self.entry() {
- Entry::End => return None,
+ Entry::End(_) => return None,
// Treat lifetimes as a single tt for the purposes of 'skip'.
Entry::Punct(punct) if punct.as_char() == '\'' && punct.spacing() == Spacing::Joint => {
@@ -347,9 +349,17 @@ impl<'a> Eq for Cursor<'a> {}
impl<'a> PartialEq for Cursor<'a> {
fn eq(&self, other: &Self) -> bool {
- let Cursor { ptr, scope, marker } = self;
- let _ = marker;
- *ptr == other.ptr && *scope == other.scope
+ self.ptr == other.ptr
+ }
+}
+
+impl<'a> PartialOrd for Cursor<'a> {
+ fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
+ if same_buffer(*self, *other) {
+ Some(self.ptr.cmp(&other.ptr))
+ } else {
+ None
+ }
}
}
@@ -357,6 +367,22 @@ pub(crate) fn same_scope(a: Cursor, b: Cursor) -> bool {
a.scope == b.scope
}
+pub(crate) fn same_buffer(a: Cursor, b: Cursor) -> bool {
+ unsafe {
+ match (&*a.scope, &*b.scope) {
+ (Entry::End(a_offset), Entry::End(b_offset)) => {
+ a.scope.offset(*a_offset) == b.scope.offset(*b_offset)
+ }
+ _ => unreachable!(),
+ }
+ }
+}
+
+#[cfg(any(feature = "full", feature = "derive"))]
+pub(crate) fn cmp_assuming_same_buffer(a: Cursor, b: Cursor) -> Ordering {
+ a.ptr.cmp(&b.ptr)
+}
+
pub(crate) fn open_span_of_group(cursor: Cursor) -> Span {
match cursor.entry() {
Entry::Group(group, _) => group.span_open(),
diff --git a/vendor/syn/src/drops.rs b/vendor/syn/src/drops.rs
new file mode 100644
index 000000000..89b42d82e
--- /dev/null
+++ b/vendor/syn/src/drops.rs
@@ -0,0 +1,58 @@
+use std::iter;
+use std::mem::ManuallyDrop;
+use std::ops::{Deref, DerefMut};
+use std::option;
+use std::slice;
+
+#[repr(transparent)]
+pub(crate) struct NoDrop<T: ?Sized>(ManuallyDrop<T>);
+
+impl<T> NoDrop<T> {
+ pub(crate) fn new(value: T) -> Self
+ where
+ T: TrivialDrop,
+ {
+ NoDrop(ManuallyDrop::new(value))
+ }
+}
+
+impl<T: ?Sized> Deref for NoDrop<T> {
+ type Target = T;
+ fn deref(&self) -> &Self::Target {
+ &self.0
+ }
+}
+
+impl<T: ?Sized> DerefMut for NoDrop<T> {
+ fn deref_mut(&mut self) -> &mut Self::Target {
+ &mut self.0
+ }
+}
+
+pub(crate) trait TrivialDrop {}
+
+impl<T> TrivialDrop for iter::Empty<T> {}
+impl<'a, T> TrivialDrop for slice::Iter<'a, T> {}
+impl<'a, T> TrivialDrop for slice::IterMut<'a, T> {}
+impl<'a, T> TrivialDrop for option::IntoIter<&'a T> {}
+impl<'a, T> TrivialDrop for option::IntoIter<&'a mut T> {}
+
+#[test]
+fn test_needs_drop() {
+ use std::mem::needs_drop;
+
+ struct NeedsDrop;
+
+ impl Drop for NeedsDrop {
+ fn drop(&mut self) {}
+ }
+
+ assert!(needs_drop::<NeedsDrop>());
+
+ // Test each of the types with a handwritten TrivialDrop impl above.
+ assert!(!needs_drop::<iter::Empty<NeedsDrop>>());
+ assert!(!needs_drop::<slice::Iter<NeedsDrop>>());
+ assert!(!needs_drop::<slice::IterMut<NeedsDrop>>());
+ assert!(!needs_drop::<option::IntoIter<&NeedsDrop>>());
+ assert!(!needs_drop::<option::IntoIter<&mut NeedsDrop>>());
+}
diff --git a/vendor/syn/src/error.rs b/vendor/syn/src/error.rs
index 609cc086f..e301367d5 100644
--- a/vendor/syn/src/error.rs
+++ b/vendor/syn/src/error.rs
@@ -134,12 +134,16 @@ impl Error {
/// }
/// ```
pub fn new<T: Display>(span: Span, message: T) -> Self {
- Error {
- messages: vec![ErrorMessage {
- start_span: ThreadBound::new(span),
- end_span: ThreadBound::new(span),
- message: message.to_string(),
- }],
+ return new(span, message.to_string());
+
+ fn new(span: Span, message: String) -> Error {
+ Error {
+ messages: vec![ErrorMessage {
+ start_span: ThreadBound::new(span),
+ end_span: ThreadBound::new(span),
+ message,
+ }],
+ }
}
}
@@ -158,15 +162,19 @@ impl Error {
/// `ParseStream::error`)!
#[cfg(feature = "printing")]
pub fn new_spanned<T: ToTokens, U: Display>(tokens: T, message: U) -> Self {
- let mut iter = tokens.into_token_stream().into_iter();
- let start = iter.next().map_or_else(Span::call_site, |t| t.span());
- let end = iter.last().map_or(start, |t| t.span());
- Error {
- messages: vec![ErrorMessage {
- start_span: ThreadBound::new(start),
- end_span: ThreadBound::new(end),
- message: message.to_string(),
- }],
+ return new_spanned(tokens.into_token_stream(), message.to_string());
+
+ fn new_spanned(tokens: TokenStream, message: String) -> Error {
+ let mut iter = tokens.into_iter();
+ let start = iter.next().map_or_else(Span::call_site, |t| t.span());
+ let end = iter.last().map_or(start, |t| t.span());
+ Error {
+ messages: vec![ErrorMessage {
+ start_span: ThreadBound::new(start),
+ end_span: ThreadBound::new(end),
+ message,
+ }],
+ }
}
}
@@ -288,12 +296,16 @@ pub fn new_at<T: Display>(scope: Span, cursor: Cursor, message: T) -> Error {
#[cfg(all(feature = "parsing", any(feature = "full", feature = "derive")))]
pub fn new2<T: Display>(start: Span, end: Span, message: T) -> Error {
- Error {
- messages: vec![ErrorMessage {
- start_span: ThreadBound::new(start),
- end_span: ThreadBound::new(end),
- message: message.to_string(),
- }],
+ return new2(start, end, message.to_string());
+
+ fn new2(start: Span, end: Span, message: String) -> Error {
+ Error {
+ messages: vec![ErrorMessage {
+ start_span: ThreadBound::new(start),
+ end_span: ThreadBound::new(end),
+ message,
+ }],
+ }
}
}
diff --git a/vendor/syn/src/generics.rs b/vendor/syn/src/generics.rs
index 9c2802f87..6d4fe847e 100644
--- a/vendor/syn/src/generics.rs
+++ b/vendor/syn/src/generics.rs
@@ -828,6 +828,31 @@ pub mod parsing {
}
}
+ impl TypeParamBound {
+ pub(crate) fn parse_multiple(
+ input: ParseStream,
+ allow_plus: bool,
+ ) -> Result<Punctuated<Self, Token![+]>> {
+ let mut bounds = Punctuated::new();
+ loop {
+ bounds.push_value(input.parse()?);
+ if !(allow_plus && input.peek(Token![+])) {
+ break;
+ }
+ bounds.push_punct(input.parse()?);
+ if !(input.peek(Ident::peek_any)
+ || input.peek(Token![::])
+ || input.peek(Token![?])
+ || input.peek(Lifetime)
+ || input.peek(token::Paren))
+ {
+ break;
+ }
+ }
+ Ok(bounds)
+ }
+ }
+
#[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
impl Parse for TraitBound {
fn parse(input: ParseStream) -> Result<Self> {
diff --git a/vendor/syn/src/lib.rs b/vendor/syn/src/lib.rs
index 81f03e1b5..e47ba28c6 100644
--- a/vendor/syn/src/lib.rs
+++ b/vendor/syn/src/lib.rs
@@ -250,13 +250,14 @@
//! dynamic library libproc_macro from rustc toolchain.
// Syn types in rustdoc of other crates get linked to here.
-#![doc(html_root_url = "https://docs.rs/syn/1.0.102")]
+#![doc(html_root_url = "https://docs.rs/syn/1.0.107")]
#![cfg_attr(doc_cfg, feature(doc_cfg))]
#![allow(non_camel_case_types)]
#![allow(
clippy::bool_to_int_with_if,
clippy::cast_lossless,
clippy::cast_possible_truncation,
+ clippy::cast_possible_wrap,
clippy::cast_ptr_alignment,
clippy::default_trait_access,
clippy::doc_markdown,
@@ -264,8 +265,8 @@
clippy::explicit_auto_deref,
clippy::if_not_else,
clippy::inherent_to_string,
+ clippy::items_after_statements,
clippy::large_enum_variant,
- clippy::let_underscore_drop,
clippy::manual_assert,
clippy::match_on_vec_items,
clippy::match_same_arms,
@@ -428,6 +429,7 @@ pub use crate::path::{
#[cfg(feature = "parsing")]
#[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
pub mod buffer;
+mod drops;
#[cfg(feature = "parsing")]
#[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
pub mod ext;
diff --git a/vendor/syn/src/path.rs b/vendor/syn/src/path.rs
index 742273afd..6cdb43ac5 100644
--- a/vendor/syn/src/path.rs
+++ b/vendor/syn/src/path.rs
@@ -89,9 +89,8 @@ impl PathArguments {
}
}
- #[cfg(feature = "parsing")]
- fn is_none(&self) -> bool {
- match *self {
+ pub fn is_none(&self) -> bool {
+ match self {
PathArguments::None => true,
PathArguments::AngleBracketed(_) | PathArguments::Parenthesized(_) => false,
}
diff --git a/vendor/syn/src/punctuated.rs b/vendor/syn/src/punctuated.rs
index 0fe1078cf..b7d0185e8 100644
--- a/vendor/syn/src/punctuated.rs
+++ b/vendor/syn/src/punctuated.rs
@@ -32,6 +32,7 @@ use std::option;
use std::slice;
use std::vec;
+use crate::drops::{NoDrop, TrivialDrop};
#[cfg(feature = "parsing")]
use crate::parse::{Parse, ParseStream, Result};
#[cfg(feature = "parsing")]
@@ -104,10 +105,10 @@ impl<T, P> Punctuated<T, P> {
/// Returns an iterator over borrowed syntax tree nodes of type `&T`.
pub fn iter(&self) -> Iter<T> {
Iter {
- inner: Box::new(PrivateIter {
+ inner: Box::new(NoDrop::new(PrivateIter {
inner: self.inner.iter(),
last: self.last.as_ref().map(Box::as_ref).into_iter(),
- }),
+ })),
}
}
@@ -115,10 +116,10 @@ impl<T, P> Punctuated<T, P> {
/// `&mut T`.
pub fn iter_mut(&mut self) -> IterMut<T> {
IterMut {
- inner: Box::new(PrivateIterMut {
+ inner: Box::new(NoDrop::new(PrivateIterMut {
inner: self.inner.iter_mut(),
last: self.last.as_mut().map(Box::as_mut).into_iter(),
- }),
+ })),
}
}
@@ -721,13 +722,13 @@ pub struct Iter<'a, T: 'a> {
// The `Item = &'a T` needs to be specified to support rustc 1.31 and older.
// On modern compilers we would be able to write just IterTrait<'a, T> where
// Item can be inferred unambiguously from the supertrait.
- inner: Box<dyn IterTrait<'a, T, Item = &'a T> + 'a>,
+ inner: Box<NoDrop<dyn IterTrait<'a, T, Item = &'a T> + 'a>>,
}
trait IterTrait<'a, T: 'a>:
DoubleEndedIterator<Item = &'a T> + ExactSizeIterator<Item = &'a T>
{
- fn clone_box(&self) -> Box<dyn IterTrait<'a, T, Item = &'a T> + 'a>;
+ fn clone_box(&self) -> Box<NoDrop<dyn IterTrait<'a, T, Item = &'a T> + 'a>>;
}
struct PrivateIter<'a, T: 'a, P: 'a> {
@@ -735,10 +736,17 @@ struct PrivateIter<'a, T: 'a, P: 'a> {
last: option::IntoIter<&'a T>,
}
+impl<'a, T, P> TrivialDrop for PrivateIter<'a, T, P>
+where
+ slice::Iter<'a, (T, P)>: TrivialDrop,
+ option::IntoIter<&'a T>: TrivialDrop,
+{
+}
+
#[cfg(any(feature = "full", feature = "derive"))]
pub(crate) fn empty_punctuated_iter<'a, T>() -> Iter<'a, T> {
Iter {
- inner: Box::new(iter::empty()),
+ inner: Box::new(NoDrop::new(iter::empty())),
}
}
@@ -813,10 +821,14 @@ impl<'a, T, P> Clone for PrivateIter<'a, T, P> {
impl<'a, T, I> IterTrait<'a, T> for I
where
T: 'a,
- I: DoubleEndedIterator<Item = &'a T> + ExactSizeIterator<Item = &'a T> + Clone + 'a,
+ I: DoubleEndedIterator<Item = &'a T>
+ + ExactSizeIterator<Item = &'a T>
+ + Clone
+ + TrivialDrop
+ + 'a,
{
- fn clone_box(&self) -> Box<dyn IterTrait<'a, T, Item = &'a T> + 'a> {
- Box::new(self.clone())
+ fn clone_box(&self) -> Box<NoDrop<dyn IterTrait<'a, T, Item = &'a T> + 'a>> {
+ Box::new(NoDrop::new(self.clone()))
}
}
@@ -826,7 +838,7 @@ where
///
/// [module documentation]: self
pub struct IterMut<'a, T: 'a> {
- inner: Box<dyn IterMutTrait<'a, T, Item = &'a mut T> + 'a>,
+ inner: Box<NoDrop<dyn IterMutTrait<'a, T, Item = &'a mut T> + 'a>>,
}
trait IterMutTrait<'a, T: 'a>:
@@ -839,10 +851,17 @@ struct PrivateIterMut<'a, T: 'a, P: 'a> {
last: option::IntoIter<&'a mut T>,
}
+impl<'a, T, P> TrivialDrop for PrivateIterMut<'a, T, P>
+where
+ slice::IterMut<'a, (T, P)>: TrivialDrop,
+ option::IntoIter<&'a mut T>: TrivialDrop,
+{
+}
+
#[cfg(any(feature = "full", feature = "derive"))]
pub(crate) fn empty_punctuated_iter_mut<'a, T>() -> IterMut<'a, T> {
IterMut {
- inner: Box::new(iter::empty()),
+ inner: Box::new(NoDrop::new(iter::empty())),
}
}
diff --git a/vendor/syn/src/ty.rs b/vendor/syn/src/ty.rs
index 4068be3c7..8c841e2f7 100644
--- a/vendor/syn/src/ty.rs
+++ b/vendor/syn/src/ty.rs
@@ -337,7 +337,7 @@ pub mod parsing {
use crate::ext::IdentExt;
use crate::parse::{Parse, ParseStream, Result};
use crate::path;
- use proc_macro2::{Punct, Spacing, TokenTree};
+ use proc_macro2::{Punct, Spacing, Span, TokenTree};
#[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
impl Parse for Type {
@@ -546,13 +546,17 @@ pub mod parsing {
|| lookahead.peek(Token![<])
{
let dyn_token: Option<Token![dyn]> = input.parse()?;
- if dyn_token.is_some() {
+ if let Some(dyn_token) = dyn_token {
+ let dyn_span = dyn_token.span;
let star_token: Option<Token![*]> = input.parse()?;
- let bounds = TypeTraitObject::parse_bounds(input, allow_plus)?;
+ let bounds = TypeTraitObject::parse_bounds(dyn_span, input, allow_plus)?;
return Ok(if star_token.is_some() {
Type::Verbatim(verbatim::between(begin, input))
} else {
- Type::TraitObject(TypeTraitObject { dyn_token, bounds })
+ Type::TraitObject(TypeTraitObject {
+ dyn_token: Some(dyn_token),
+ bounds,
+ })
});
}
@@ -896,15 +900,6 @@ pub mod parsing {
}
}
- fn at_least_one_type(bounds: &Punctuated<TypeParamBound, Token![+]>) -> bool {
- for bound in bounds {
- if let TypeParamBound::Trait(_) = *bound {
- return true;
- }
- }
- false
- }
-
impl TypeTraitObject {
#[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
pub fn without_plus(input: ParseStream) -> Result<Self> {
@@ -914,35 +909,38 @@ pub mod parsing {
// Only allow multiple trait references if allow_plus is true.
pub(crate) fn parse(input: ParseStream, allow_plus: bool) -> Result<Self> {
- Ok(TypeTraitObject {
- dyn_token: input.parse()?,
- bounds: Self::parse_bounds(input, allow_plus)?,
- })
+ let dyn_token: Option<Token![dyn]> = input.parse()?;
+ let dyn_span = match &dyn_token {
+ Some(token) => token.span,
+ None => input.span(),
+ };
+ let bounds = Self::parse_bounds(dyn_span, input, allow_plus)?;
+ Ok(TypeTraitObject { dyn_token, bounds })
}
fn parse_bounds(
+ dyn_span: Span,
input: ParseStream,
allow_plus: bool,
) -> Result<Punctuated<TypeParamBound, Token![+]>> {
- let mut bounds = Punctuated::new();
- loop {
- bounds.push_value(input.parse()?);
- if !(allow_plus && input.peek(Token![+])) {
- break;
- }
- bounds.push_punct(input.parse()?);
- if !(input.peek(Ident::peek_any)
- || input.peek(Token![::])
- || input.peek(Token![?])
- || input.peek(Lifetime)
- || input.peek(token::Paren))
- {
- break;
+ let bounds = TypeParamBound::parse_multiple(input, allow_plus)?;
+ let mut last_lifetime_span = None;
+ let mut at_least_one_trait = false;
+ for bound in &bounds {
+ match bound {
+ TypeParamBound::Trait(_) => {
+ at_least_one_trait = true;
+ break;
+ }
+ TypeParamBound::Lifetime(lifetime) => {
+ last_lifetime_span = Some(lifetime.ident.span());
+ }
}
}
// Just lifetimes like `'a + 'b` is not a TraitObject.
- if !at_least_one_type(&bounds) {
- return Err(input.error("expected at least one type"));
+ if !at_least_one_trait {
+ let msg = "at least one trait is required for an object type";
+ return Err(error::new2(dyn_span, last_lifetime_span.unwrap(), msg));
}
Ok(bounds)
}
@@ -964,10 +962,30 @@ pub mod parsing {
}
pub(crate) fn parse(input: ParseStream, allow_plus: bool) -> Result<Self> {
- Ok(TypeImplTrait {
- impl_token: input.parse()?,
- bounds: TypeTraitObject::parse_bounds(input, allow_plus)?,
- })
+ let impl_token: Token![impl] = input.parse()?;
+ let bounds = TypeParamBound::parse_multiple(input, allow_plus)?;
+ let mut last_lifetime_span = None;
+ let mut at_least_one_trait = false;
+ for bound in &bounds {
+ match bound {
+ TypeParamBound::Trait(_) => {
+ at_least_one_trait = true;
+ break;
+ }
+ TypeParamBound::Lifetime(lifetime) => {
+ last_lifetime_span = Some(lifetime.ident.span());
+ }
+ }
+ }
+ if !at_least_one_trait {
+ let msg = "at least one trait must be specified";
+ return Err(error::new2(
+ impl_token.span,
+ last_lifetime_span.unwrap(),
+ msg,
+ ));
+ }
+ Ok(TypeImplTrait { impl_token, bounds })
}
}
diff --git a/vendor/syn/src/verbatim.rs b/vendor/syn/src/verbatim.rs
index 0686352f7..58cf68d17 100644
--- a/vendor/syn/src/verbatim.rs
+++ b/vendor/syn/src/verbatim.rs
@@ -1,13 +1,31 @@
use crate::parse::{ParseBuffer, ParseStream};
-use proc_macro2::TokenStream;
+use proc_macro2::{Delimiter, TokenStream};
+use std::cmp::Ordering;
use std::iter;
pub fn between<'a>(begin: ParseBuffer<'a>, end: ParseStream<'a>) -> TokenStream {
let end = end.cursor();
let mut cursor = begin.cursor();
+ assert!(crate::buffer::same_buffer(end, cursor));
+
let mut tokens = TokenStream::new();
while cursor != end {
let (tt, next) = cursor.token_tree().unwrap();
+
+ if crate::buffer::cmp_assuming_same_buffer(end, next) == Ordering::Less {
+ // A syntax node can cross the boundary of a None-delimited group
+ // due to such groups being transparent to the parser in most cases.
+ // Any time this occurs the group is known to be semantically
+ // irrelevant. https://github.com/dtolnay/syn/issues/1235
+ if let Some((inside, _span, after)) = cursor.group(Delimiter::None) {
+ assert!(next == after);
+ cursor = inside;
+ continue;
+ } else {
+ panic!("verbatim end must not be inside a delimited group");
+ }
+ }
+
tokens.extend(iter::once(tt));
cursor = next;
}
diff --git a/vendor/syn/tests/common/eq.rs b/vendor/syn/tests/common/eq.rs
index a53146241..41d6d4118 100644
--- a/vendor/syn/tests/common/eq.rs
+++ b/vendor/syn/tests/common/eq.rs
@@ -13,6 +13,8 @@ use rustc_ast::ast::AssocConstraint;
use rustc_ast::ast::AssocConstraintKind;
use rustc_ast::ast::AssocItemKind;
use rustc_ast::ast::Async;
+use rustc_ast::ast::AttrArgs;
+use rustc_ast::ast::AttrArgsEq;
use rustc_ast::ast::AttrId;
use rustc_ast::ast::AttrItem;
use rustc_ast::ast::AttrKind;
@@ -26,10 +28,12 @@ use rustc_ast::ast::BlockCheckMode;
use rustc_ast::ast::BorrowKind;
use rustc_ast::ast::ByRef;
use rustc_ast::ast::CaptureBy;
+use rustc_ast::ast::Closure;
use rustc_ast::ast::ClosureBinder;
use rustc_ast::ast::Const;
use rustc_ast::ast::Crate;
use rustc_ast::ast::Defaultness;
+use rustc_ast::ast::DelimArgs;
use rustc_ast::ast::EnumDef;
use rustc_ast::ast::Expr;
use rustc_ast::ast::ExprField;
@@ -65,19 +69,18 @@ use rustc_ast::ast::Item;
use rustc_ast::ast::ItemKind;
use rustc_ast::ast::Label;
use rustc_ast::ast::Lifetime;
-use rustc_ast::ast::Lit;
use rustc_ast::ast::LitFloatType;
use rustc_ast::ast::LitIntType;
use rustc_ast::ast::LitKind;
use rustc_ast::ast::Local;
use rustc_ast::ast::LocalKind;
-use rustc_ast::ast::MacArgs;
-use rustc_ast::ast::MacArgsEq;
use rustc_ast::ast::MacCall;
use rustc_ast::ast::MacCallStmt;
use rustc_ast::ast::MacDelimiter;
use rustc_ast::ast::MacStmtStyle;
use rustc_ast::ast::MacroDef;
+use rustc_ast::ast::MetaItemLit;
+use rustc_ast::ast::MethodCall;
use rustc_ast::ast::ModKind;
use rustc_ast::ast::ModSpans;
use rustc_ast::ast::Movability;
@@ -128,7 +131,7 @@ use rustc_ast::ast::WhereEqPredicate;
use rustc_ast::ast::WherePredicate;
use rustc_ast::ast::WhereRegionPredicate;
use rustc_ast::ptr::P;
-use rustc_ast::token::{self, CommentKind, Delimiter, Nonterminal, Token, TokenKind};
+use rustc_ast::token::{self, CommentKind, Delimiter, Lit, Nonterminal, Token, TokenKind};
use rustc_ast::tokenstream::{
AttrTokenStream, AttrTokenTree, AttributesData, DelimSpan, LazyAttrTokenStream, Spacing,
TokenStream, TokenTree,
@@ -411,7 +414,9 @@ spanless_eq_struct!(AttributesData; attrs tokens);
spanless_eq_struct!(BareFnTy; unsafety ext generic_params decl decl_span);
spanless_eq_struct!(BindingAnnotation; 0 1);
spanless_eq_struct!(Block; stmts id rules span tokens could_be_bare_literal);
+spanless_eq_struct!(Closure; binder capture_clause asyncness movability fn_decl body !fn_decl_span);
spanless_eq_struct!(Crate; attrs items spans id is_placeholder);
+spanless_eq_struct!(DelimArgs; dspan delim tokens);
spanless_eq_struct!(EnumDef; variants);
spanless_eq_struct!(Expr; id kind span attrs !tokens);
spanless_eq_struct!(ExprField; attrs id span ident expr is_shorthand is_placeholder);
@@ -429,11 +434,13 @@ spanless_eq_struct!(InlineAsmSym; id qself path);
spanless_eq_struct!(Item<K>; attrs id span vis ident kind !tokens);
spanless_eq_struct!(Label; ident);
spanless_eq_struct!(Lifetime; id ident);
-spanless_eq_struct!(Lit; token_lit kind span);
+spanless_eq_struct!(Lit; kind symbol suffix);
spanless_eq_struct!(Local; pat ty kind id span attrs !tokens);
spanless_eq_struct!(MacCall; path args prior_type_ascription);
spanless_eq_struct!(MacCallStmt; mac style attrs tokens);
spanless_eq_struct!(MacroDef; body macro_rules);
+spanless_eq_struct!(MetaItemLit; token_lit kind span);
+spanless_eq_struct!(MethodCall; seg receiver args !span);
spanless_eq_struct!(ModSpans; !inner_span !inject_use_span);
spanless_eq_struct!(MutTy; ty mutbl);
spanless_eq_struct!(NormalAttr; item tokens);
@@ -460,11 +467,12 @@ spanless_eq_struct!(WhereBoundPredicate; span bound_generic_params bounded_ty bo
spanless_eq_struct!(WhereClause; has_where_token predicates span);
spanless_eq_struct!(WhereEqPredicate; span lhs_ty rhs_ty);
spanless_eq_struct!(WhereRegionPredicate; span lifetime bounds);
-spanless_eq_struct!(token::Lit; kind symbol suffix);
spanless_eq_enum!(AngleBracketedArg; Arg(0) Constraint(0));
-spanless_eq_enum!(AssocItemKind; Const(0 1 2) Fn(0) TyAlias(0) MacCall(0));
+spanless_eq_enum!(AssocItemKind; Const(0 1 2) Fn(0) Type(0) MacCall(0));
spanless_eq_enum!(AssocConstraintKind; Equality(term) Bound(bounds));
spanless_eq_enum!(Async; Yes(span closure_id return_impl_trait_id) No);
+spanless_eq_enum!(AttrArgs; Empty Delimited(0) Eq(0 1));
+spanless_eq_enum!(AttrArgsEq; Ast(0) Hir(0));
spanless_eq_enum!(AttrStyle; Outer Inner);
spanless_eq_enum!(AttrTokenTree; Token(0 1) Delimited(0 1 2) Attributes(0));
spanless_eq_enum!(BinOpKind; Add Sub Mul Div Rem And Or BitXor BitAnd BitOr Shl Shr Eq Lt Le Ne Ge Gt);
@@ -492,8 +500,6 @@ spanless_eq_enum!(IsAuto; Yes No);
spanless_eq_enum!(LitFloatType; Suffixed(0) Unsuffixed);
spanless_eq_enum!(LitIntType; Signed(0) Unsigned(0) Unsuffixed);
spanless_eq_enum!(LocalKind; Decl Init(0) InitElse(0 1));
-spanless_eq_enum!(MacArgs; Empty Delimited(0 1 2) Eq(0 1));
-spanless_eq_enum!(MacArgsEq; Ast(0) Hir(0));
spanless_eq_enum!(MacDelimiter; Parenthesis Bracket Brace);
spanless_eq_enum!(MacStmtStyle; Semicolon Braces NoBraces);
spanless_eq_enum!(ModKind; Loaded(0 1 2) Unloaded);
@@ -512,18 +518,18 @@ spanless_eq_enum!(UintTy; Usize U8 U16 U32 U64 U128);
spanless_eq_enum!(UnOp; Deref Not Neg);
spanless_eq_enum!(Unsafe; Yes(0) No);
spanless_eq_enum!(UnsafeSource; CompilerGenerated UserProvided);
-spanless_eq_enum!(UseTreeKind; Simple(0 1 2) Nested(0) Glob);
+spanless_eq_enum!(UseTreeKind; Simple(0) Nested(0) Glob);
spanless_eq_enum!(VariantData; Struct(0 1) Tuple(0 1) Unit(0));
spanless_eq_enum!(VisibilityKind; Public Restricted(path id shorthand) Inherited);
spanless_eq_enum!(WherePredicate; BoundPredicate(0) RegionPredicate(0) EqPredicate(0));
spanless_eq_enum!(ExprKind; Box(0) Array(0) ConstBlock(0) Call(0 1)
- MethodCall(0 1 2 3) Tup(0) Binary(0 1 2) Unary(0 1) Lit(0) Cast(0 1)
- Type(0 1) Let(0 1 2) If(0 1 2) While(0 1 2) ForLoop(0 1 2 3) Loop(0 1)
- Match(0 1) Closure(0 1 2 3 4 5 6) Block(0 1) Async(0 1 2) Await(0)
- TryBlock(0) Assign(0 1 2) AssignOp(0 1 2) Field(0 1) Index(0 1) Underscore
- Range(0 1 2) Path(0 1) AddrOf(0 1 2) Break(0 1) Continue(0) Ret(0)
- InlineAsm(0) MacCall(0) Struct(0) Repeat(0 1) Paren(0) Try(0) Yield(0)
- Yeet(0) Err);
+ MethodCall(0) Tup(0) Binary(0 1 2) Unary(0 1) Lit(0) Cast(0 1) Type(0 1)
+ Let(0 1 2) If(0 1 2) While(0 1 2) ForLoop(0 1 2 3) Loop(0 1 2) Match(0 1)
+ Closure(0) Block(0 1) Async(0 1 2) Await(0) TryBlock(0) Assign(0 1 2)
+ AssignOp(0 1 2) Field(0 1) Index(0 1) Underscore Range(0 1 2) Path(0 1)
+ AddrOf(0 1 2) Break(0 1) Continue(0) Ret(0) InlineAsm(0) MacCall(0)
+ Struct(0) Repeat(0 1) Paren(0) Try(0) Yield(0) Yeet(0) IncludedBytes(0)
+ Err);
spanless_eq_enum!(InlineAsmOperand; In(reg expr) Out(reg late expr)
InOut(reg late expr) SplitInOut(reg late in_expr out_expr) Const(anon_const)
Sym(sym));
@@ -697,8 +703,8 @@ fn is_escaped_literal_token(token: &Token, unescaped: Symbol) -> bool {
Token {
kind: TokenKind::Literal(lit),
span: _,
- } => match Lit::from_token_lit(*lit, DUMMY_SP) {
- Ok(lit) => is_escaped_literal(&lit, unescaped),
+ } => match MetaItemLit::from_token_lit(*lit, DUMMY_SP) {
+ Ok(lit) => is_escaped_literal_meta_item_lit(&lit, unescaped),
Err(_) => false,
},
Token {
@@ -706,7 +712,7 @@ fn is_escaped_literal_token(token: &Token, unescaped: Symbol) -> bool {
span: _,
} => match nonterminal.as_ref() {
Nonterminal::NtExpr(expr) => match &expr.kind {
- ExprKind::Lit(lit) => is_escaped_literal(lit, unescaped),
+ ExprKind::Lit(lit) => is_escaped_lit(lit, unescaped),
_ => false,
},
_ => false,
@@ -715,28 +721,51 @@ fn is_escaped_literal_token(token: &Token, unescaped: Symbol) -> bool {
}
}
-fn is_escaped_literal_macro_arg(arg: &MacArgsEq, unescaped: Symbol) -> bool {
- match arg {
- MacArgsEq::Ast(expr) => match &expr.kind {
- ExprKind::Lit(lit) => is_escaped_literal(lit, unescaped),
+fn is_escaped_literal_attr_args(value: &AttrArgsEq, unescaped: Symbol) -> bool {
+ match value {
+ AttrArgsEq::Ast(expr) => match &expr.kind {
+ ExprKind::Lit(lit) => is_escaped_lit(lit, unescaped),
_ => false,
},
- MacArgsEq::Hir(lit) => is_escaped_literal(lit, unescaped),
+ AttrArgsEq::Hir(lit) => is_escaped_literal_meta_item_lit(lit, unescaped),
}
}
-fn is_escaped_literal(lit: &Lit, unescaped: Symbol) -> bool {
+fn is_escaped_literal_meta_item_lit(lit: &MetaItemLit, unescaped: Symbol) -> bool {
match lit {
- Lit {
+ MetaItemLit {
token_lit:
- token::Lit {
+ Lit {
kind: token::LitKind::Str,
symbol: _,
suffix: None,
},
- kind: LitKind::Str(symbol, StrStyle::Cooked),
+ kind,
span: _,
- } => symbol.as_str().replace('\r', "") == unescaped.as_str().replace('\r', ""),
+ } => is_escaped_lit_kind(kind, unescaped),
+ _ => false,
+ }
+}
+
+fn is_escaped_lit(lit: &Lit, unescaped: Symbol) -> bool {
+ match lit {
+ Lit {
+ kind: token::LitKind::Str,
+ symbol: _,
+ suffix: None,
+ } => match LitKind::from_token_lit(*lit) {
+ Ok(lit_kind) => is_escaped_lit_kind(&lit_kind, unescaped),
+ _ => false,
+ },
+ _ => false,
+ }
+}
+
+fn is_escaped_lit_kind(kind: &LitKind, unescaped: Symbol) -> bool {
+ match kind {
+ LitKind::Str(symbol, StrStyle::Cooked) => {
+ symbol.as_str().replace('\r', "") == unescaped.as_str().replace('\r', "")
+ }
_ => false,
}
}
@@ -765,9 +794,9 @@ impl SpanlessEq for AttrKind {
let path = Path::from_ident(Ident::with_dummy_span(sym::doc));
SpanlessEq::eq(&path, &normal2.item.path)
&& match &normal2.item.args {
- MacArgs::Empty | MacArgs::Delimited(..) => false,
- MacArgs::Eq(_span, token) => {
- is_escaped_literal_macro_arg(token, *unescaped)
+ AttrArgs::Empty | AttrArgs::Delimited(_) => false,
+ AttrArgs::Eq(_span, value) => {
+ is_escaped_literal_attr_args(value, *unescaped)
}
}
}
diff --git a/vendor/syn/tests/regression.rs b/vendor/syn/tests/regression.rs
index 8311a91bf..fb2b25c89 100644
--- a/vendor/syn/tests/regression.rs
+++ b/vendor/syn/tests/regression.rs
@@ -1,5 +1,3 @@
-#![allow(clippy::let_underscore_drop)]
-
mod regression {
automod::dir!("tests/regression");
}
diff --git a/vendor/syn/tests/regression/issue1235.rs b/vendor/syn/tests/regression/issue1235.rs
new file mode 100644
index 000000000..883603066
--- /dev/null
+++ b/vendor/syn/tests/regression/issue1235.rs
@@ -0,0 +1,32 @@
+use proc_macro2::{Delimiter, Group};
+use quote::quote;
+
+#[test]
+fn main() {
+ // Okay. Rustc allows top-level `static` with no value syntactically, but
+ // not semantically. Syn parses as Item::Verbatim.
+ let tokens = quote! {
+ pub static FOO: usize;
+ pub static BAR: usize;
+ };
+ let file = syn::parse2::<syn::File>(tokens).unwrap();
+ println!("{:#?}", file);
+
+ // Okay.
+ let inner = Group::new(
+ Delimiter::None,
+ quote!(static FOO: usize = 0; pub static BAR: usize = 0),
+ );
+ let tokens = quote!(pub #inner;);
+ let file = syn::parse2::<syn::File>(tokens).unwrap();
+ println!("{:#?}", file);
+
+ // Formerly parser crash.
+ let inner = Group::new(
+ Delimiter::None,
+ quote!(static FOO: usize; pub static BAR: usize),
+ );
+ let tokens = quote!(pub #inner;);
+ let file = syn::parse2::<syn::File>(tokens).unwrap();
+ println!("{:#?}", file);
+}
diff --git a/vendor/syn/tests/repo/mod.rs b/vendor/syn/tests/repo/mod.rs
index 4c7be853b..8418b8719 100644
--- a/vendor/syn/tests/repo/mod.rs
+++ b/vendor/syn/tests/repo/mod.rs
@@ -188,7 +188,7 @@ fn download_and_unpack() -> Result<()> {
"https://github.com/rust-lang/rust/archive/{}.tar.gz",
REVISION
);
- let response = reqwest::blocking::get(&url)?.error_for_status()?;
+ let response = reqwest::blocking::get(url)?.error_for_status()?;
let progress = Progress::new(response);
let decoder = GzDecoder::new(progress);
let mut archive = Archive::new(decoder);
diff --git a/vendor/syn/tests/test_expr.rs b/vendor/syn/tests/test_expr.rs
index 8fd911e2a..e5b151fd8 100644
--- a/vendor/syn/tests/test_expr.rs
+++ b/vendor/syn/tests/test_expr.rs
@@ -53,36 +53,37 @@ fn test_await() {
#[rustfmt::skip]
#[test]
fn test_tuple_multi_index() {
+ let expected = snapshot!("tuple.0.0" as Expr, @r###"
+ Expr::Field {
+ base: Expr::Field {
+ base: Expr::Path {
+ path: Path {
+ segments: [
+ PathSegment {
+ ident: "tuple",
+ arguments: None,
+ },
+ ],
+ },
+ },
+ member: Unnamed(Index {
+ index: 0,
+ }),
+ },
+ member: Unnamed(Index {
+ index: 0,
+ }),
+ }
+ "###);
+
for &input in &[
- "tuple.0.0",
"tuple .0.0",
"tuple. 0.0",
"tuple.0 .0",
"tuple.0. 0",
"tuple . 0 . 0",
] {
- snapshot!(input as Expr, @r###"
- Expr::Field {
- base: Expr::Field {
- base: Expr::Path {
- path: Path {
- segments: [
- PathSegment {
- ident: "tuple",
- arguments: None,
- },
- ],
- },
- },
- member: Unnamed(Index {
- index: 0,
- }),
- },
- member: Unnamed(Index {
- index: 0,
- }),
- }
- "###);
+ assert_eq!(expected, syn::parse_str(input).unwrap());
}
for tokens in vec![
@@ -93,28 +94,7 @@ fn test_tuple_multi_index() {
quote!(tuple.0. 0),
quote!(tuple . 0 . 0),
] {
- snapshot!(tokens as Expr, @r###"
- Expr::Field {
- base: Expr::Field {
- base: Expr::Path {
- path: Path {
- segments: [
- PathSegment {
- ident: "tuple",
- arguments: None,
- },
- ],
- },
- },
- member: Unnamed(Index {
- index: 0,
- }),
- },
- member: Unnamed(Index {
- index: 0,
- }),
- }
- "###);
+ assert_eq!(expected, syn::parse2(tokens).unwrap());
}
}
diff --git a/vendor/syn/tests/test_iterators.rs b/vendor/syn/tests/test_iterators.rs
index 2c8359c15..0ab0fb914 100644
--- a/vendor/syn/tests/test_iterators.rs
+++ b/vendor/syn/tests/test_iterators.rs
@@ -47,3 +47,22 @@ fn iter() {
assert_eq!(p.iter_mut().next_back(), Some(&mut 4));
assert_eq!(p.into_iter().next_back(), Some(4));
}
+
+#[test]
+fn may_dangle() {
+ let p: Punctuated<_, Token![,]> = punctuated!(2, 3, 4);
+ for element in &p {
+ if *element == 2 {
+ drop(p);
+ break;
+ }
+ }
+
+ let mut p: Punctuated<_, Token![,]> = punctuated!(2, 3, 4);
+ for element in &mut p {
+ if *element == 2 {
+ drop(p);
+ break;
+ }
+ }
+}
diff --git a/vendor/syn/tests/test_round_trip.rs b/vendor/syn/tests/test_round_trip.rs
index c7e6e488f..9a5801d44 100644
--- a/vendor/syn/tests/test_round_trip.rs
+++ b/vendor/syn/tests/test_round_trip.rs
@@ -21,8 +21,8 @@ use rustc_ast::ast::{
WhereClause,
};
use rustc_ast::mut_visit::{self, MutVisitor};
-use rustc_error_messages::{DiagnosticMessage, FluentArgs, LazyFallbackBundle};
-use rustc_errors::{Diagnostic, PResult};
+use rustc_error_messages::{DiagnosticMessage, LazyFallbackBundle};
+use rustc_errors::{translation, Diagnostic, PResult};
use rustc_session::parse::ParseSess;
use rustc_span::source_map::FilePathMapping;
use rustc_span::FileName;
@@ -168,10 +168,10 @@ fn translate_message(diagnostic: &Diagnostic) -> String {
}
let message = &diagnostic.message[0].0;
- let args = diagnostic.args().iter().cloned().collect::<FluentArgs>();
+ let args = translation::to_fluent_args(diagnostic.args());
let (identifier, attr) = match message {
- DiagnosticMessage::Str(msg) => return msg.clone(),
+ DiagnosticMessage::Str(msg) | DiagnosticMessage::Eager(msg) => return msg.clone(),
DiagnosticMessage::FluentIdentifier(identifier, attr) => (identifier, attr),
};
diff --git a/vendor/syn/tests/test_size.rs b/vendor/syn/tests/test_size.rs
index 02b0700f0..32c6edaed 100644
--- a/vendor/syn/tests/test_size.rs
+++ b/vendor/syn/tests/test_size.rs
@@ -5,7 +5,7 @@ use syn::{Expr, Item, Lit, Pat, Type};
#[test]
fn test_expr_size() {
- assert_eq!(mem::size_of::<Expr>(), 264);
+ assert_eq!(mem::size_of::<Expr>(), 272);
}
#[test]
@@ -15,7 +15,7 @@ fn test_item_size() {
#[test]
fn test_type_size() {
- assert_eq!(mem::size_of::<Type>(), 280);
+ assert_eq!(mem::size_of::<Type>(), 288);
}
#[test]
diff --git a/vendor/thin-vec/.cargo-checksum.json b/vendor/thin-vec/.cargo-checksum.json
index 33ca74234..9e4702880 100644
--- a/vendor/thin-vec/.cargo-checksum.json
+++ b/vendor/thin-vec/.cargo-checksum.json
@@ -1 +1 @@
-{"files":{"Cargo.toml":"49f429a38e2c6216dfddc1f23af64a3b06cf92217d75cae2a9ac389bc3f76e46","README.md":"9f102f13ccbabe9cdec7a206aa298d65e33dea84da9f08dd17b358ff44fe0286","src/lib.rs":"6a5451d75037e3cb12bde5198266a0db00432e1370cad74b0dda8df8fb64f067"},"package":"ceb05e71730d396f960f8f3901cdb41be2d339b303e9d7d3a07c5ff0536e671b"} \ No newline at end of file
+{"files":{"Cargo.toml":"391230d6db1276baa00856a9ded6ccc426a447d04a23661d7b4461137f398745","README.md":"9f102f13ccbabe9cdec7a206aa298d65e33dea84da9f08dd17b358ff44fe0286","src/lib.rs":"d3367f69119c46ac4ca8bb0a4c86c77606119200aebd56b7a30096c08a22ba40"},"package":"aac81b6fd6beb5884b0cf3321b8117e6e5d47ecb6fc89f414cfdcca8b2fe2dd8"} \ No newline at end of file
diff --git a/vendor/thin-vec/Cargo.toml b/vendor/thin-vec/Cargo.toml
index 8361d94d4..01b84e4ca 100644
--- a/vendor/thin-vec/Cargo.toml
+++ b/vendor/thin-vec/Cargo.toml
@@ -12,7 +12,7 @@
[package]
edition = "2018"
name = "thin-vec"
-version = "0.2.9"
+version = "0.2.12"
authors = ["Aria Beingessner <a.beingessner@gmail.com>"]
description = "A vec that takes up less space on the stack"
homepage = "https://github.com/gankra/thin-vec"
diff --git a/vendor/thin-vec/src/lib.rs b/vendor/thin-vec/src/lib.rs
index a2384c62e..ea24aed2e 100644
--- a/vendor/thin-vec/src/lib.rs
+++ b/vendor/thin-vec/src/lib.rs
@@ -1,30 +1,32 @@
-//! ThinVec is exactly the same as Vec, except that it stores its `len` and `capacity` in the buffer
+#![deny(missing_docs)]
+
+//! `ThinVec` is exactly the same as `Vec`, except that it stores its `len` and `capacity` in the buffer
//! it allocates.
//!
//! This makes the memory footprint of ThinVecs lower; notably in cases where space is reserved for
-//! a non-existence ThinVec<T>. So `Vec<ThinVec<T>>` and `Option<ThinVec<T>>::None` will waste less
+//! a non-existence `ThinVec<T>`. So `Vec<ThinVec<T>>` and `Option<ThinVec<T>>::None` will waste less
//! space. Being pointer-sized also means it can be passed/stored in registers.
//!
-//! Of course, any actually constructed ThinVec will theoretically have a bigger allocation, but
+//! Of course, any actually constructed `ThinVec` will theoretically have a bigger allocation, but
//! the fuzzy nature of allocators means that might not actually be the case.
//!
-//! Properties of Vec that are preserved:
+//! Properties of `Vec` that are preserved:
//! * `ThinVec::new()` doesn't allocate (it points to a statically allocated singleton)
//! * reallocation can be done in place
//! * `size_of::<ThinVec<T>>()` == `size_of::<Option<ThinVec<T>>>()`
//!
-//! Properties of Vec that aren't preserved:
+//! Properties of `Vec` that aren't preserved:
//! * `ThinVec<T>` can't ever be zero-cost roundtripped to a `Box<[T]>`, `String`, or `*mut T`
//! * `from_raw_parts` doesn't exist
-//! * ThinVec currently doesn't bother to not-allocate for Zero Sized Types (e.g. `ThinVec<()>`),
+//! * `ThinVec` currently doesn't bother to not-allocate for Zero Sized Types (e.g. `ThinVec<()>`),
//! but it could be done if someone cared enough to implement it.
//!
//!
//!
//! # Gecko FFI
//!
-//! If you enable the gecko-ffi feature, ThinVec will verbatim bridge with the nsTArray type in
-//! Gecko (Firefox). That is, ThinVec and nsTArray have identical layouts *but not ABIs*,
+//! If you enable the gecko-ffi feature, `ThinVec` will verbatim bridge with the nsTArray type in
+//! Gecko (Firefox). That is, `ThinVec` and nsTArray have identical layouts *but not ABIs*,
//! so nsTArrays/ThinVecs an be natively manipulated by C++ and Rust, and ownership can be
//! transferred across the FFI boundary (**IF YOU ARE CAREFUL, SEE BELOW!!**).
//!
@@ -105,17 +107,17 @@
//! While relocations are generally predictable if you're very careful, **you should avoid using
//! types with significant locations with Rust FFI**.
//!
-//! Specifically, ThinVec will trivially relocate its contents whenever it needs to reallocate its
+//! Specifically, `ThinVec` will trivially relocate its contents whenever it needs to reallocate its
//! buffer to change its capacity. This is the default reallocation strategy for nsTArray, and is
//! suitable for the vast majority of types. Just be aware of this limitation!
//!
//! ## Auto Arrays Are Dangerous
//!
-//! ThinVec has *some* support for handling auto arrays which store their buffer on the stack,
+//! `ThinVec` has *some* support for handling auto arrays which store their buffer on the stack,
//! but this isn't well tested.
//!
//! Regardless of how much support we provide, Rust won't be aware of the buffer's limited lifetime,
-//! so standard auto array safety caveats apply about returning/storing them! ThinVec won't ever
+//! so standard auto array safety caveats apply about returning/storing them! `ThinVec` won't ever
//! produce an auto array on its own, so this is only an issue for transferring an nsTArray into
//! Rust.
//!
@@ -133,7 +135,7 @@
//! defined. Specifically, we must share the symbol for nsTArray's empty singleton. You will get
//! linking errors if that isn't defined.
//!
-//! The gecko-ffi feature also limits ThinVec to the legacy behaviors of nsTArray. Most notably,
+//! The gecko-ffi feature also limits `ThinVec` to the legacy behaviors of nsTArray. Most notably,
//! nsTArray has a maximum capacity of i32::MAX (~2.1 billion items). Probably not an issue.
//! Probably.
//!
@@ -144,6 +146,8 @@
use std::alloc::*;
use std::borrow::*;
use std::cmp::*;
+use std::convert::TryFrom;
+use std::convert::TryInto;
use std::hash::*;
use std::iter::FromIterator;
use std::marker::PhantomData;
@@ -172,7 +176,7 @@ mod impl_details {
mod impl_details {
// Support for briding a gecko nsTArray verbatim into a ThinVec.
//
- // ThinVec can't see copy/move/delete implementations
+ // `ThinVec` can't see copy/move/delete implementations
// from C++
//
// The actual layout of an nsTArray is:
@@ -187,7 +191,7 @@ mod impl_details {
//
// Rust doesn't natively support bit-fields, so we manually mask
// and shift the bit. When the "auto" bit is set, the header and buffer
- // are actually on the stack, meaning the ThinVec pointer-to-header
+ // are actually on the stack, meaning the `ThinVec` pointer-to-header
// is essentially an "owned borrow", and therefore dangerous to handle.
// There are no safety guards for this situation.
//
@@ -195,7 +199,7 @@ mod impl_details {
// our capacity u32. On big-endian platforms, it will be the low bit.
// Hence we need some platform-specific CFGs for the necessary masking/shifting.
//
- // ThinVec won't ever construct an auto array. They only happen when
+ // `ThinVec` won't ever construct an auto array. They only happen when
// bridging from C++. This means we don't need to ever set/preserve the bit.
// We just need to be able to read and handle it if it happens to be there.
//
@@ -270,10 +274,13 @@ struct Header {
}
impl Header {
+ #[inline]
+ #[allow(clippy::unnecessary_cast)]
fn len(&self) -> usize {
self._len as usize
}
+ #[inline]
fn set_len(&mut self, len: usize) {
self._len = assert_size(len);
}
@@ -303,6 +310,7 @@ impl Header {
#[cfg(not(feature = "gecko-ffi"))]
impl Header {
+ #[allow(clippy::unnecessary_cast)]
fn cap(&self) -> usize {
self._cap as usize
}
@@ -326,24 +334,40 @@ extern "C" {
static EMPTY_HEADER: Header;
}
-// TODO: overflow checks everywhere
-
// Utils for computing layouts of allocations
+/// Gets the size necessary to allocate a `ThinVec<T>` with the give capacity.
+///
+/// # Panics
+///
+/// This will panic if isize::MAX is overflowed at any point.
fn alloc_size<T>(cap: usize) -> usize {
// Compute "real" header size with pointer math
- let header_size = mem::size_of::<Header>();
- let elem_size = mem::size_of::<T>();
- let padding = padding::<T>();
-
- // TODO: care about isize::MAX overflow?
- let data_size = elem_size.checked_mul(cap).expect("capacity overflow");
+ //
+ // We turn everything into isizes here so that we can catch isize::MAX overflow,
+ // we never want to allow allocations larger than that!
+ let header_size = mem::size_of::<Header>() as isize;
+ let padding = padding::<T>() as isize;
+
+ let data_size = if mem::size_of::<T>() == 0 {
+ // If we're allocating an array for ZSTs we need a header/padding but no actual
+ // space for items, so we don't care about the capacity that was requested!
+ 0
+ } else {
+ let cap: isize = cap.try_into().expect("capacity overflow");
+ let elem_size = mem::size_of::<T>() as isize;
+ elem_size.checked_mul(cap).expect("capacity overflow")
+ };
- data_size
+ let final_size = data_size
.checked_add(header_size + padding)
- .expect("capacity overflow")
+ .expect("capacity overflow");
+
+ // Ok now we can turn it back into a usize (don't need to worry about negatives)
+ final_size as usize
}
+/// Gets the padding necessary for the array of a `ThinVec<T>`
fn padding<T>() -> usize {
let alloc_align = alloc_align::<T>();
let header_size = mem::size_of::<Header>();
@@ -361,14 +385,25 @@ fn padding<T>() -> usize {
}
}
+/// Gets the align necessary to allocate a `ThinVec<T>`
fn alloc_align<T>() -> usize {
max(mem::align_of::<T>(), mem::align_of::<Header>())
}
+/// Gets the layout necessary to allocate a `ThinVec<T>`
+///
+/// # Panics
+///
+/// Panics if the required size overflows `isize::MAX`.
fn layout<T>(cap: usize) -> Layout {
unsafe { Layout::from_size_align_unchecked(alloc_size::<T>(cap), alloc_align::<T>()) }
}
+/// Allocates a header (and array) for a `ThinVec<T>` with the given capacity.
+///
+/// # Panics
+///
+/// Panics if the required size overflows `isize::MAX`.
fn header_with_capacity<T>(cap: usize) -> NonNull<Header> {
debug_assert!(cap > 0);
unsafe {
@@ -439,10 +474,67 @@ macro_rules! thin_vec {
}
impl<T> ThinVec<T> {
+ /// Creates a new empty ThinVec.
+ ///
+ /// This will not allocate.
pub fn new() -> ThinVec<T> {
ThinVec::with_capacity(0)
}
+ /// Constructs a new, empty `ThinVec<T>` with at least the specified capacity.
+ ///
+ /// The vector will be able to hold at least `capacity` elements without
+ /// reallocating. This method is allowed to allocate for more elements than
+ /// `capacity`. If `capacity` is 0, the vector will not allocate.
+ ///
+ /// It is important to note that although the returned vector has the
+ /// minimum *capacity* specified, the vector will have a zero *length*.
+ ///
+ /// If it is important to know the exact allocated capacity of a `ThinVec`,
+ /// always use the [`capacity`] method after construction.
+ ///
+ /// **NOTE**: unlike `Vec`, `ThinVec` **MUST** allocate once to keep track of non-zero
+ /// lengths. As such, we cannot provide the same guarantees about ThinVecs
+ /// of ZSTs not allocating. However the allocation never needs to be resized
+ /// to add more ZSTs, since the underlying array is still length 0.
+ ///
+ /// [Capacity and reallocation]: #capacity-and-reallocation
+ /// [`capacity`]: Vec::capacity
+ ///
+ /// # Panics
+ ///
+ /// Panics if the new capacity exceeds `isize::MAX` bytes.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use thin_vec::ThinVec;
+ ///
+ /// let mut vec = ThinVec::with_capacity(10);
+ ///
+ /// // The vector contains no items, even though it has capacity for more
+ /// assert_eq!(vec.len(), 0);
+ /// assert!(vec.capacity() >= 10);
+ ///
+ /// // These are all done without reallocating...
+ /// for i in 0..10 {
+ /// vec.push(i);
+ /// }
+ /// assert_eq!(vec.len(), 10);
+ /// assert!(vec.capacity() >= 10);
+ ///
+ /// // ...but this may make the vector reallocate
+ /// vec.push(11);
+ /// assert_eq!(vec.len(), 11);
+ /// assert!(vec.capacity() >= 11);
+ ///
+ /// // A vector of a zero-sized type will always over-allocate, since no
+ /// // space is needed to store the actual elements.
+ /// let vec_units = ThinVec::<()>::with_capacity(10);
+ ///
+ /// // Only true **without** the gecko-ffi feature!
+ /// // assert_eq!(vec_units.capacity(), usize::MAX);
+ /// ```
pub fn with_capacity(cap: usize) -> ThinVec<T> {
// `padding` contains ~static assertions against types that are
// incompatible with the current feature flags. We also call it to
@@ -525,16 +617,134 @@ impl<T> ThinVec<T> {
&mut *self.ptr()
}
+ /// Returns the number of elements in the vector, also referred to
+ /// as its 'length'.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use thin_vec::thin_vec;
+ ///
+ /// let a = thin_vec![1, 2, 3];
+ /// assert_eq!(a.len(), 3);
+ /// ```
pub fn len(&self) -> usize {
self.header().len()
}
+
+ /// Returns `true` if the vector contains no elements.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use thin_vec::ThinVec;
+ ///
+ /// let mut v = ThinVec::new();
+ /// assert!(v.is_empty());
+ ///
+ /// v.push(1);
+ /// assert!(!v.is_empty());
+ /// ```
pub fn is_empty(&self) -> bool {
self.len() == 0
}
+
+ /// Returns the number of elements the vector can hold without
+ /// reallocating.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use thin_vec::ThinVec;
+ ///
+ /// let vec: ThinVec<i32> = ThinVec::with_capacity(10);
+ /// assert_eq!(vec.capacity(), 10);
+ /// ```
pub fn capacity(&self) -> usize {
self.header().cap()
}
+ /// Forces the length of the vector to `new_len`.
+ ///
+ /// This is a low-level operation that maintains none of the normal
+ /// invariants of the type. Normally changing the length of a vector
+ /// is done using one of the safe operations instead, such as
+ /// [`truncate`], [`resize`], [`extend`], or [`clear`].
+ ///
+ /// [`truncate`]: ThinVec::truncate
+ /// [`resize`]: ThinVec::resize
+ /// [`extend`]: ThinVec::extend
+ /// [`clear`]: ThinVec::clear
+ ///
+ /// # Safety
+ ///
+ /// - `new_len` must be less than or equal to [`capacity()`].
+ /// - The elements at `old_len..new_len` must be initialized.
+ ///
+ /// [`capacity()`]: ThinVec::capacity
+ ///
+ /// # Examples
+ ///
+ /// This method can be useful for situations in which the vector
+ /// is serving as a buffer for other code, particularly over FFI:
+ ///
+ /// ```no_run
+ /// use thin_vec::ThinVec;
+ ///
+ /// # // This is just a minimal skeleton for the doc example;
+ /// # // don't use this as a starting point for a real library.
+ /// # pub struct StreamWrapper { strm: *mut std::ffi::c_void }
+ /// # const Z_OK: i32 = 0;
+ /// # extern "C" {
+ /// # fn deflateGetDictionary(
+ /// # strm: *mut std::ffi::c_void,
+ /// # dictionary: *mut u8,
+ /// # dictLength: *mut usize,
+ /// # ) -> i32;
+ /// # }
+ /// # impl StreamWrapper {
+ /// pub fn get_dictionary(&self) -> Option<ThinVec<u8>> {
+ /// // Per the FFI method's docs, "32768 bytes is always enough".
+ /// let mut dict = ThinVec::with_capacity(32_768);
+ /// let mut dict_length = 0;
+ /// // SAFETY: When `deflateGetDictionary` returns `Z_OK`, it holds that:
+ /// // 1. `dict_length` elements were initialized.
+ /// // 2. `dict_length` <= the capacity (32_768)
+ /// // which makes `set_len` safe to call.
+ /// unsafe {
+ /// // Make the FFI call...
+ /// let r = deflateGetDictionary(self.strm, dict.as_mut_ptr(), &mut dict_length);
+ /// if r == Z_OK {
+ /// // ...and update the length to what was initialized.
+ /// dict.set_len(dict_length);
+ /// Some(dict)
+ /// } else {
+ /// None
+ /// }
+ /// }
+ /// }
+ /// # }
+ /// ```
+ ///
+ /// While the following example is sound, there is a memory leak since
+ /// the inner vectors were not freed prior to the `set_len` call:
+ ///
+ /// ```no_run
+ /// use thin_vec::thin_vec;
+ ///
+ /// let mut vec = thin_vec![thin_vec![1, 0, 0],
+ /// thin_vec![0, 1, 0],
+ /// thin_vec![0, 0, 1]];
+ /// // SAFETY:
+ /// // 1. `old_len..0` is empty so no elements need to be initialized.
+ /// // 2. `0 <= capacity` always holds whatever `capacity` is.
+ /// unsafe {
+ /// vec.set_len(0);
+ /// }
+ /// ```
+ ///
+ /// Normally, here, one would use [`clear`] instead to correctly drop
+ /// the contents and thus not leak memory.
pub unsafe fn set_len(&mut self, len: usize) {
if self.is_singleton() {
// A prerequisite of `Vec::set_len` is that `new_len` must be
@@ -550,6 +760,21 @@ impl<T> ThinVec<T> {
self.header_mut().set_len(len)
}
+ /// Appends an element to the back of a collection.
+ ///
+ /// # Panics
+ ///
+ /// Panics if the new capacity exceeds `isize::MAX` bytes.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use thin_vec::thin_vec;
+ ///
+ /// let mut vec = thin_vec![1, 2];
+ /// vec.push(3);
+ /// assert_eq!(vec, [1, 2, 3]);
+ /// ```
pub fn push(&mut self, val: T) {
let old_len = self.len();
if old_len == self.capacity() {
@@ -561,6 +786,18 @@ impl<T> ThinVec<T> {
}
}
+ /// Removes the last element from a vector and returns it, or [`None`] if it
+ /// is empty.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use thin_vec::thin_vec;
+ ///
+ /// let mut vec = thin_vec![1, 2, 3];
+ /// assert_eq!(vec.pop(), Some(3));
+ /// assert_eq!(vec, [1, 2]);
+ /// ```
pub fn pop(&mut self) -> Option<T> {
let old_len = self.len();
if old_len == 0 {
@@ -573,6 +810,24 @@ impl<T> ThinVec<T> {
}
}
+ /// Inserts an element at position `index` within the vector, shifting all
+ /// elements after it to the right.
+ ///
+ /// # Panics
+ ///
+ /// Panics if `index > len`.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use thin_vec::thin_vec;
+ ///
+ /// let mut vec = thin_vec![1, 2, 3];
+ /// vec.insert(1, 4);
+ /// assert_eq!(vec, [1, 4, 2, 3]);
+ /// vec.insert(4, 5);
+ /// assert_eq!(vec, [1, 4, 2, 3, 5]);
+ /// ```
pub fn insert(&mut self, idx: usize, elem: T) {
let old_len = self.len();
@@ -588,6 +843,29 @@ impl<T> ThinVec<T> {
}
}
+ /// Removes and returns the element at position `index` within the vector,
+ /// shifting all elements after it to the left.
+ ///
+ /// Note: Because this shifts over the remaining elements, it has a
+ /// worst-case performance of *O*(*n*). If you don't need the order of elements
+ /// to be preserved, use [`swap_remove`] instead. If you'd like to remove
+ /// elements from the beginning of the `ThinVec`, consider using `std::collections::VecDeque`.
+ ///
+ /// [`swap_remove`]: ThinVec::swap_remove
+ ///
+ /// # Panics
+ ///
+ /// Panics if `index` is out of bounds.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use thin_vec::thin_vec;
+ ///
+ /// let mut v = thin_vec![1, 2, 3];
+ /// assert_eq!(v.remove(1), 2);
+ /// assert_eq!(v, [1, 3]);
+ /// ```
pub fn remove(&mut self, idx: usize) -> T {
let old_len = self.len();
@@ -602,6 +880,32 @@ impl<T> ThinVec<T> {
}
}
+ /// Removes an element from the vector and returns it.
+ ///
+ /// The removed element is replaced by the last element of the vector.
+ ///
+ /// This does not preserve ordering, but is *O*(1).
+ /// If you need to preserve the element order, use [`remove`] instead.
+ ///
+ /// [`remove`]: ThinVec::remove
+ ///
+ /// # Panics
+ ///
+ /// Panics if `index` is out of bounds.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use thin_vec::thin_vec;
+ ///
+ /// let mut v = thin_vec!["foo", "bar", "baz", "qux"];
+ ///
+ /// assert_eq!(v.swap_remove(1), "bar");
+ /// assert_eq!(v, ["foo", "qux", "baz"]);
+ ///
+ /// assert_eq!(v.swap_remove(0), "foo");
+ /// assert_eq!(v, ["baz", "qux"]);
+ /// ```
pub fn swap_remove(&mut self, idx: usize) -> T {
let old_len = self.len();
@@ -615,6 +919,54 @@ impl<T> ThinVec<T> {
}
}
+ /// Shortens the vector, keeping the first `len` elements and dropping
+ /// the rest.
+ ///
+ /// If `len` is greater than the vector's current length, this has no
+ /// effect.
+ ///
+ /// The [`drain`] method can emulate `truncate`, but causes the excess
+ /// elements to be returned instead of dropped.
+ ///
+ /// Note that this method has no effect on the allocated capacity
+ /// of the vector.
+ ///
+ /// # Examples
+ ///
+ /// Truncating a five element vector to two elements:
+ ///
+ /// ```
+ /// use thin_vec::thin_vec;
+ ///
+ /// let mut vec = thin_vec![1, 2, 3, 4, 5];
+ /// vec.truncate(2);
+ /// assert_eq!(vec, [1, 2]);
+ /// ```
+ ///
+ /// No truncation occurs when `len` is greater than the vector's current
+ /// length:
+ ///
+ /// ```
+ /// use thin_vec::thin_vec;
+ ///
+ /// let mut vec = thin_vec![1, 2, 3];
+ /// vec.truncate(8);
+ /// assert_eq!(vec, [1, 2, 3]);
+ /// ```
+ ///
+ /// Truncating when `len == 0` is equivalent to calling the [`clear`]
+ /// method.
+ ///
+ /// ```
+ /// use thin_vec::thin_vec;
+ ///
+ /// let mut vec = thin_vec![1, 2, 3];
+ /// vec.truncate(0);
+ /// assert_eq!(vec, []);
+ /// ```
+ ///
+ /// [`clear`]: ThinVec::clear
+ /// [`drain`]: ThinVec::drain
pub fn truncate(&mut self, len: usize) {
unsafe {
// drop any extra elements
@@ -628,6 +980,20 @@ impl<T> ThinVec<T> {
}
}
+ /// Clears the vector, removing all values.
+ ///
+ /// Note that this method has no effect on the allocated capacity
+ /// of the vector.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use thin_vec::thin_vec;
+ ///
+ /// let mut v = thin_vec![1, 2, 3];
+ /// v.clear();
+ /// assert!(v.is_empty());
+ /// ```
pub fn clear(&mut self) {
unsafe {
ptr::drop_in_place(&mut self[..]);
@@ -635,10 +1001,34 @@ impl<T> ThinVec<T> {
}
}
+ /// Extracts a slice containing the entire vector.
+ ///
+ /// Equivalent to `&s[..]`.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use thin_vec::thin_vec;
+ /// use std::io::{self, Write};
+ /// let buffer = thin_vec![1, 2, 3, 5, 8];
+ /// io::sink().write(buffer.as_slice()).unwrap();
+ /// ```
pub fn as_slice(&self) -> &[T] {
unsafe { slice::from_raw_parts(self.data_raw(), self.len()) }
}
+ /// Extracts a mutable slice of the entire vector.
+ ///
+ /// Equivalent to `&mut s[..]`.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use thin_vec::thin_vec;
+ /// use std::io::{self, Read};
+ /// let mut buffer = vec![0; 3];
+ /// io::repeat(0b101).read_exact(buffer.as_mut_slice()).unwrap();
+ /// ```
pub fn as_mut_slice(&mut self) -> &mut [T] {
unsafe { slice::from_raw_parts_mut(self.data_raw(), self.len()) }
}
@@ -751,6 +1141,22 @@ impl<T> ThinVec<T> {
}
}
+ /// Shrinks the capacity of the vector as much as possible.
+ ///
+ /// It will drop down as close as possible to the length but the allocator
+ /// may still inform the vector that there is space for a few more elements.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use thin_vec::ThinVec;
+ ///
+ /// let mut vec = ThinVec::with_capacity(10);
+ /// vec.extend([1, 2, 3]);
+ /// assert_eq!(vec.capacity(), 10);
+ /// vec.shrink_to_fit();
+ /// assert!(vec.capacity() >= 3);
+ /// ```
pub fn shrink_to_fit(&mut self) {
let old_cap = self.capacity();
let new_cap = self.len();
@@ -915,6 +1321,26 @@ impl<T> ThinVec<T> {
}
}
+ /// Splits the collection into two at the given index.
+ ///
+ /// Returns a newly allocated vector containing the elements in the range
+ /// `[at, len)`. After the call, the original vector will be left containing
+ /// the elements `[0, at)` with its previous capacity unchanged.
+ ///
+ /// # Panics
+ ///
+ /// Panics if `at > len`.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use thin_vec::thin_vec;
+ ///
+ /// let mut vec = thin_vec![1, 2, 3];
+ /// let vec2 = vec.split_off(1);
+ /// assert_eq!(vec, [1]);
+ /// assert_eq!(vec2, [2, 3]);
+ /// ```
pub fn split_off(&mut self, at: usize) -> ThinVec<T> {
let old_len = self.len();
let new_vec_len = old_len - at;
@@ -933,14 +1359,64 @@ impl<T> ThinVec<T> {
}
}
+ /// Moves all the elements of `other` into `self`, leaving `other` empty.
+ ///
+ /// # Panics
+ ///
+ /// Panics if the new capacity exceeds `isize::MAX` bytes.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use thin_vec::thin_vec;
+ ///
+ /// let mut vec = thin_vec![1, 2, 3];
+ /// let mut vec2 = thin_vec![4, 5, 6];
+ /// vec.append(&mut vec2);
+ /// assert_eq!(vec, [1, 2, 3, 4, 5, 6]);
+ /// assert_eq!(vec2, []);
+ /// ```
pub fn append(&mut self, other: &mut ThinVec<T>) {
self.extend(other.drain(..))
}
+ /// Removes the specified range from the vector in bulk, returning all
+ /// removed elements as an iterator. If the iterator is dropped before
+ /// being fully consumed, it drops the remaining removed elements.
+ ///
+ /// The returned iterator keeps a mutable borrow on the vector to optimize
+ /// its implementation.
+ ///
+ /// # 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.
+ ///
+ /// # Leaking
+ ///
+ /// If the returned iterator goes out of scope without being dropped (due to
+ /// [`mem::forget`], for example), the vector may have lost and leaked
+ /// elements arbitrarily, including elements outside the range.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use thin_vec::{ThinVec, thin_vec};
+ ///
+ /// let mut v = thin_vec![1, 2, 3];
+ /// let u: ThinVec<_> = v.drain(1..).collect();
+ /// assert_eq!(v, &[1]);
+ /// assert_eq!(u, &[2, 3]);
+ ///
+ /// // A full range clears the vector, like `clear()` does
+ /// v.drain(..);
+ /// assert_eq!(v, &[]);
+ /// ```
pub fn drain<R>(&mut self, range: R) -> Drain<'_, T>
where
R: RangeBounds<usize>,
{
+ // See comments in the Drain struct itself for details on this
let len = self.len();
let start = match range.start_bound() {
Bound::Included(&n) => n,
@@ -971,6 +1447,53 @@ impl<T> ThinVec<T> {
}
}
+ /// Creates a splicing iterator that replaces the specified range in the vector
+ /// with the given `replace_with` iterator and yields the removed items.
+ /// `replace_with` does not need to be the same length as `range`.
+ ///
+ /// `range` is removed even if the iterator is not consumed until the end.
+ ///
+ /// It is unspecified how many elements are removed from the vector
+ /// if the `Splice` value is leaked.
+ ///
+ /// The input iterator `replace_with` is only consumed when the `Splice` value is dropped.
+ ///
+ /// This is optimal if:
+ ///
+ /// * The tail (elements in the vector after `range`) is empty,
+ /// * or `replace_with` yields fewer or equal elements than `range`’s length
+ /// * or the lower bound of its `size_hint()` is exact.
+ ///
+ /// Otherwise, a temporary vector is allocated and the tail is moved twice.
+ ///
+ /// # 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
+ ///
+ /// ```
+ /// use thin_vec::{ThinVec, thin_vec};
+ ///
+ /// let mut v = thin_vec![1, 2, 3, 4];
+ /// let new = [7, 8, 9];
+ /// let u: ThinVec<_> = v.splice(1..3, new).collect();
+ /// assert_eq!(v, &[1, 7, 8, 9, 4]);
+ /// assert_eq!(u, &[2, 3]);
+ /// ```
+ #[inline]
+ pub fn splice<R, I>(&mut self, range: R, replace_with: I) -> Splice<'_, I::IntoIter>
+ where
+ R: RangeBounds<usize>,
+ I: IntoIterator<Item = T>,
+ {
+ Splice {
+ drain: self.drain(range),
+ replace_with: replace_with.into_iter(),
+ }
+ }
+
/// Resize the buffer and update its capacity, without changing the length.
/// Unsafe because it can cause length to be greater than capacity.
unsafe fn reallocate(&mut self, new_cap: usize) {
@@ -1018,7 +1541,12 @@ impl<T> ThinVec<T> {
#[cfg(feature = "gecko-ffi")]
#[inline]
+ #[allow(unused_unsafe)]
fn is_singleton(&self) -> bool {
+ // NOTE: the tests will complain that this "unsafe" isn't needed, but it *IS*!
+ // In production this refers to an *extern static* which *is* unsafe to reference.
+ // In tests this refers to a local static because we don't have Firefox's codebase
+ // providing the symbol!
unsafe { self.ptr.as_ptr() as *const Header == &EMPTY_HEADER }
}
@@ -1082,6 +1610,27 @@ impl<T: Clone> ThinVec<T> {
}
}
+ /// Clones and appends all elements in a slice to the `ThinVec`.
+ ///
+ /// Iterates over the slice `other`, clones each element, and then appends
+ /// it to this `ThinVec`. The `other` slice is traversed in-order.
+ ///
+ /// Note that this function is same as [`extend`] except that it is
+ /// specialized to work with slices instead. If and when Rust gets
+ /// specialization this function will likely be deprecated (but still
+ /// available).
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use thin_vec::thin_vec;
+ ///
+ /// let mut vec = thin_vec![1];
+ /// vec.extend_from_slice(&[2, 3, 4]);
+ /// assert_eq!(vec, [1, 2, 3, 4]);
+ /// ```
+ ///
+ /// [`extend`]: ThinVec::extend
pub fn extend_from_slice(&mut self, other: &[T]) {
self.extend(other.iter().cloned())
}
@@ -1415,16 +1964,256 @@ impl<T> FromIterator<T> for ThinVec<T> {
}
}
+impl<T: Clone> From<&[T]> for ThinVec<T> {
+ /// Allocate a `ThinVec<T>` and fill it by cloning `s`'s items.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use thin_vec::{ThinVec, thin_vec};
+ ///
+ /// assert_eq!(ThinVec::from(&[1, 2, 3][..]), thin_vec![1, 2, 3]);
+ /// ```
+ fn from(s: &[T]) -> ThinVec<T> {
+ s.iter().cloned().collect()
+ }
+}
+
+#[cfg(not(no_global_oom_handling))]
+impl<T: Clone> From<&mut [T]> for ThinVec<T> {
+ /// Allocate a `ThinVec<T>` and fill it by cloning `s`'s items.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use thin_vec::{ThinVec, thin_vec};
+ ///
+ /// assert_eq!(ThinVec::from(&mut [1, 2, 3][..]), thin_vec![1, 2, 3]);
+ /// ```
+ fn from(s: &mut [T]) -> ThinVec<T> {
+ s.iter().cloned().collect()
+ }
+}
+
+impl<T, const N: usize> From<[T; N]> for ThinVec<T> {
+ /// Allocate a `ThinVec<T>` and move `s`'s items into it.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use thin_vec::{ThinVec, thin_vec};
+ ///
+ /// assert_eq!(ThinVec::from([1, 2, 3]), thin_vec![1, 2, 3]);
+ /// ```
+ fn from(s: [T; N]) -> ThinVec<T> {
+ std::iter::IntoIterator::into_iter(s).collect()
+ }
+}
+
+impl<T> From<Box<[T]>> for ThinVec<T> {
+ /// Convert a boxed slice into a vector by transferring ownership of
+ /// the existing heap allocation.
+ ///
+ /// **NOTE:** unlike `std`, this must reallocate to change the layout!
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use thin_vec::{ThinVec, thin_vec};
+ ///
+ /// let b: Box<[i32]> = thin_vec![1, 2, 3].into_iter().collect();
+ /// assert_eq!(ThinVec::from(b), thin_vec![1, 2, 3]);
+ /// ```
+ fn from(s: Box<[T]>) -> Self {
+ // Can just lean on the fact that `Box<[T]>` -> `Vec<T>` is Free.
+ Vec::from(s).into_iter().collect()
+ }
+}
+
+impl<T> From<Vec<T>> for ThinVec<T> {
+ /// Convert a `std::Vec` into a `ThinVec`.
+ ///
+ /// **NOTE:** this must reallocate to change the layout!
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use thin_vec::{ThinVec, thin_vec};
+ ///
+ /// let b: Vec<i32> = vec![1, 2, 3];
+ /// assert_eq!(ThinVec::from(b), thin_vec![1, 2, 3]);
+ /// ```
+ fn from(s: Vec<T>) -> Self {
+ s.into_iter().collect()
+ }
+}
+
+impl<T> From<ThinVec<T>> for Vec<T> {
+ /// Convert a `ThinVec` into a `std::Vec`.
+ ///
+ /// **NOTE:** this must reallocate to change the layout!
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use thin_vec::{ThinVec, thin_vec};
+ ///
+ /// let b: ThinVec<i32> = thin_vec![1, 2, 3];
+ /// assert_eq!(Vec::from(b), vec![1, 2, 3]);
+ /// ```
+ fn from(s: ThinVec<T>) -> Self {
+ s.into_iter().collect()
+ }
+}
+
+impl<T> From<ThinVec<T>> for Box<[T]> {
+ /// Convert a vector into a boxed slice.
+ ///
+ /// If `v` has excess capacity, its items will be moved into a
+ /// newly-allocated buffer with exactly the right capacity.
+ ///
+ /// **NOTE:** unlike `std`, this must reallocate to change the layout!
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use thin_vec::{ThinVec, thin_vec};
+ /// assert_eq!(Box::from(thin_vec![1, 2, 3]), thin_vec![1, 2, 3].into_iter().collect());
+ /// ```
+ fn from(v: ThinVec<T>) -> Self {
+ v.into_iter().collect()
+ }
+}
+
+impl From<&str> for ThinVec<u8> {
+ /// Allocate a `ThinVec<u8>` and fill it with a UTF-8 string.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use thin_vec::{ThinVec, thin_vec};
+ ///
+ /// assert_eq!(ThinVec::from("123"), thin_vec![b'1', b'2', b'3']);
+ /// ```
+ fn from(s: &str) -> ThinVec<u8> {
+ From::from(s.as_bytes())
+ }
+}
+
+impl<T, const N: usize> TryFrom<ThinVec<T>> for [T; N] {
+ type Error = ThinVec<T>;
+
+ /// Gets the entire contents of the `ThinVec<T>` as an array,
+ /// if its size exactly matches that of the requested array.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use thin_vec::{ThinVec, thin_vec};
+ /// use std::convert::TryInto;
+ ///
+ /// assert_eq!(thin_vec![1, 2, 3].try_into(), Ok([1, 2, 3]));
+ /// assert_eq!(<ThinVec<i32>>::new().try_into(), Ok([]));
+ /// ```
+ ///
+ /// If the length doesn't match, the input comes back in `Err`:
+ /// ```
+ /// use thin_vec::{ThinVec, thin_vec};
+ /// use std::convert::TryInto;
+ ///
+ /// let r: Result<[i32; 4], _> = (0..10).collect::<ThinVec<_>>().try_into();
+ /// assert_eq!(r, Err(thin_vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9]));
+ /// ```
+ ///
+ /// If you're fine with just getting a prefix of the `ThinVec<T>`,
+ /// you can call [`.truncate(N)`](ThinVec::truncate) first.
+ /// ```
+ /// use thin_vec::{ThinVec, thin_vec};
+ /// use std::convert::TryInto;
+ ///
+ /// let mut v = ThinVec::from("hello world");
+ /// v.sort();
+ /// v.truncate(2);
+ /// let [a, b]: [_; 2] = v.try_into().unwrap();
+ /// assert_eq!(a, b' ');
+ /// assert_eq!(b, b'd');
+ /// ```
+ fn try_from(mut vec: ThinVec<T>) -> Result<[T; N], ThinVec<T>> {
+ if vec.len() != N {
+ return Err(vec);
+ }
+
+ // SAFETY: `.set_len(0)` is always sound.
+ unsafe { vec.set_len(0) };
+
+ // SAFETY: A `ThinVec`'s pointer is always aligned properly, and
+ // the alignment the array needs is the same as the items.
+ // We checked earlier that we have sufficient items.
+ // The items will not double-drop as the `set_len`
+ // tells the `ThinVec` not to also drop them.
+ let array = unsafe { ptr::read(vec.data_raw() as *const [T; N]) };
+ Ok(array)
+ }
+}
+
+/// An iterator that moves out of a vector.
+///
+/// This `struct` is created by the [`ThinVec::into_iter`][]
+/// (provided by the [`IntoIterator`] trait).
+///
+/// # Example
+///
+/// ```
+/// use thin_vec::thin_vec;
+///
+/// let v = thin_vec![0, 1, 2];
+/// let iter: thin_vec::IntoIter<_> = v.into_iter();
+/// ```
pub struct IntoIter<T> {
vec: ThinVec<T>,
start: usize,
}
-pub struct Drain<'a, T> {
- iter: IterMut<'a, T>,
- vec: *mut ThinVec<T>,
- end: usize,
- tail: usize,
+impl<T> IntoIter<T> {
+ /// Returns the remaining items of this iterator as a slice.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use thin_vec::thin_vec;
+ ///
+ /// let vec = thin_vec!['a', 'b', 'c'];
+ /// let mut into_iter = vec.into_iter();
+ /// assert_eq!(into_iter.as_slice(), &['a', 'b', 'c']);
+ /// let _ = into_iter.next().unwrap();
+ /// assert_eq!(into_iter.as_slice(), &['b', 'c']);
+ /// ```
+ pub fn as_slice(&self) -> &[T] {
+ unsafe { slice::from_raw_parts(self.vec.data_raw().add(self.start), self.len()) }
+ }
+
+ /// Returns the remaining items of this iterator as a mutable slice.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use thin_vec::thin_vec;
+ ///
+ /// let vec = thin_vec!['a', 'b', 'c'];
+ /// let mut into_iter = vec.into_iter();
+ /// assert_eq!(into_iter.as_slice(), &['a', 'b', 'c']);
+ /// into_iter.as_mut_slice()[2] = 'z';
+ /// assert_eq!(into_iter.next().unwrap(), 'a');
+ /// assert_eq!(into_iter.next().unwrap(), 'b');
+ /// assert_eq!(into_iter.next().unwrap(), 'z');
+ /// ```
+ pub fn as_mut_slice(&mut self) -> &mut [T] {
+ unsafe { &mut *self.as_raw_mut_slice() }
+ }
+
+ fn as_raw_mut_slice(&mut self) -> *mut [T] {
+ unsafe { ptr::slice_from_raw_parts_mut(self.vec.data_raw().add(self.start), self.len()) }
+ }
}
impl<T> Iterator for IntoIter<T> {
@@ -1452,12 +2241,19 @@ impl<T> DoubleEndedIterator for IntoIter<T> {
if self.start == self.vec.len() {
None
} else {
- // FIXME?: extra bounds check
self.vec.pop()
}
}
}
+impl<T> ExactSizeIterator for IntoIter<T> {}
+
+impl<T> std::iter::FusedIterator for IntoIter<T> {}
+
+// SAFETY: the length calculation is trivial, we're an array! And if it's wrong we're So Screwed.
+#[cfg(feature = "unstable")]
+unsafe impl<T> std::iter::TrustedLen for IntoIter<T> {}
+
impl<T> Drop for IntoIter<T> {
#[inline]
fn drop(&mut self) {
@@ -1477,6 +2273,126 @@ impl<T> Drop for IntoIter<T> {
}
}
+impl<T: fmt::Debug> fmt::Debug for IntoIter<T> {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ f.debug_tuple("IntoIter").field(&self.as_slice()).finish()
+ }
+}
+
+impl<T> AsRef<[T]> for IntoIter<T> {
+ fn as_ref(&self) -> &[T] {
+ self.as_slice()
+ }
+}
+
+impl<T: Clone> Clone for IntoIter<T> {
+ #[allow(clippy::into_iter_on_ref)]
+ fn clone(&self) -> Self {
+ // Just create a new `ThinVec` from the remaining elements and IntoIter it
+ self.as_slice()
+ .into_iter()
+ .cloned()
+ .collect::<ThinVec<_>>()
+ .into_iter()
+ }
+}
+
+/// A draining iterator for `ThinVec<T>`.
+///
+/// This `struct` is created by [`ThinVec::drain`].
+/// See its documentation for more.
+///
+/// # Example
+///
+/// ```
+/// use thin_vec::thin_vec;
+///
+/// let mut v = thin_vec![0, 1, 2];
+/// let iter: thin_vec::Drain<_> = v.drain(..);
+/// ```
+pub struct Drain<'a, T> {
+ // Ok so ThinVec::drain takes a range of the ThinVec and yields the contents by-value,
+ // then backshifts the array. During iteration the array is in an unsound state
+ // (big deinitialized hole in it), and this is very dangerous.
+ //
+ // Our first line of defense is the borrow checker: we have a mutable borrow, so nothing
+ // can access the ThinVec while we exist. As long as we make sure the ThinVec is in a valid
+ // state again before we release the borrow, everything should be A-OK! We do this cleanup
+ // in our Drop impl.
+ //
+ // Unfortunately, that's unsound, because mem::forget exists and The Leakpocalypse Is Real.
+ // So we can't actually guarantee our destructor runs before our borrow expires. Thankfully
+ // this isn't fatal: we can just set the ThinVec's len to 0 at the start, so if anyone
+ // leaks the Drain, we just leak everything the ThinVec contained out of spite! If they
+ // *don't* leak us then we can properly repair the len in our Drop impl. This is known
+ // as "leak amplification", and is the same approach std uses.
+ //
+ // But we can do slightly better than setting the len to 0! The drain breaks us up into
+ // these parts:
+ //
+ // ```text
+ //
+ // [A, B, C, D, E, F, G, H, _, _]
+ // ____ __________ ____ ____
+ // | | | |
+ // prefix drain tail spare-cap
+ // ```
+ //
+ // As the drain iterator is consumed from both ends (DoubleEnded!), we'll start to look
+ // like this:
+ //
+ // ```text
+ // [A, B, _, _, E, _, G, H, _, _]
+ // ____ __________ ____ ____
+ // | | | |
+ // prefix drain tail spare-cap
+ // ```
+ //
+ // Note that the prefix is always valid and untouched, as such we can set the len
+ // to the prefix when doing leak-amplification. As a bonus, we can use this value
+ // to remember where the drain range starts. At the end we'll look like this
+ // (we exhaust ourselves in our Drop impl):
+ //
+ // ```text
+ // [A, B, _, _, _, _, G, H, _, _]
+ // _____ __________ _____ ____
+ // | | | |
+ // len drain tail spare-cap
+ // ```
+ //
+ // And need to become this:
+ //
+ // ```text
+ // [A, B, G, H, _, _, _, _, _, _]
+ // ___________ ________________
+ // | |
+ // len spare-cap
+ // ```
+ //
+ // All this requires is moving the tail back to the prefix (stored in `len`)
+ // and setting `len` to `len + tail_len` to undo the leak amplification.
+ /// An iterator over the elements we're removing.
+ ///
+ /// As we go we'll be `read`ing out of the mutable refs yielded by this.
+ /// It's ok to use IterMut here because it promises to only take mutable
+ /// refs to the parts we haven't yielded yet.
+ ///
+ /// A downside of this (and the *mut below) is that it makes this type invariant, when
+ /// technically it could be covariant?
+ iter: IterMut<'a, T>,
+ /// The actual ThinVec, which we need to hold onto to undo the leak amplification
+ /// and backshift the tail into place. This should only be accessed when we're
+ /// completely done with the IterMut in the `drop` impl of this type (or miri will get mad).
+ ///
+ /// Since we set the `len` of this to be before `IterMut`, we can use that `len`
+ /// to retrieve the index of the start of the drain range later.
+ vec: *mut ThinVec<T>,
+ /// The one-past-the-end index of the drain range, or equivalently the start of the tail.
+ end: usize,
+ /// The length of the tail.
+ tail: usize,
+}
+
impl<'a, T> Iterator for Drain<'a, T> {
type Item = T;
fn next(&mut self) -> Option<T> {
@@ -1496,6 +2412,12 @@ impl<'a, T> DoubleEndedIterator for Drain<'a, T> {
impl<'a, T> ExactSizeIterator for Drain<'a, T> {}
+// SAFETY: we need to keep track of this perfectly Or Else anyway!
+#[cfg(feature = "unstable")]
+unsafe impl<T> std::iter::TrustedLen for Drain<'_, T> {}
+
+impl<T> std::iter::FusedIterator for Drain<'_, T> {}
+
impl<'a, T> Drop for Drain<'a, T> {
fn drop(&mut self) {
// Consume the rest of the iterator.
@@ -1517,6 +2439,167 @@ impl<'a, T> Drop for Drain<'a, T> {
}
}
+impl<T: fmt::Debug> fmt::Debug for Drain<'_, T> {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ f.debug_tuple("Drain").field(&self.iter.as_slice()).finish()
+ }
+}
+
+impl<'a, T> Drain<'a, T> {
+ /// Returns the remaining items of this iterator as a slice.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use thin_vec::thin_vec;
+ ///
+ /// let mut vec = thin_vec!['a', 'b', 'c'];
+ /// let mut drain = vec.drain(..);
+ /// assert_eq!(drain.as_slice(), &['a', 'b', 'c']);
+ /// let _ = drain.next().unwrap();
+ /// assert_eq!(drain.as_slice(), &['b', 'c']);
+ /// ```
+ #[must_use]
+ pub fn as_slice(&self) -> &[T] {
+ // SAFETY: this is A-OK because the elements that the underlying
+ // iterator still points at are still logically initialized and contiguous.
+ self.iter.as_slice()
+ }
+}
+
+impl<'a, T> AsRef<[T]> for Drain<'a, T> {
+ fn as_ref(&self) -> &[T] {
+ self.as_slice()
+ }
+}
+
+/// A splicing iterator for `ThinVec`.
+///
+/// This struct is created by [`ThinVec::splice`][].
+/// See its documentation for more.
+///
+/// # Example
+///
+/// ```
+/// use thin_vec::thin_vec;
+///
+/// let mut v = thin_vec![0, 1, 2];
+/// let new = [7, 8];
+/// let iter: thin_vec::Splice<_> = v.splice(1.., new);
+/// ```
+#[derive(Debug)]
+pub struct Splice<'a, I: Iterator + 'a> {
+ drain: Drain<'a, I::Item>,
+ replace_with: I,
+}
+
+impl<I: Iterator> Iterator for Splice<'_, I> {
+ type Item = I::Item;
+
+ fn next(&mut self) -> Option<Self::Item> {
+ self.drain.next()
+ }
+
+ fn size_hint(&self) -> (usize, Option<usize>) {
+ self.drain.size_hint()
+ }
+}
+
+impl<I: Iterator> DoubleEndedIterator for Splice<'_, I> {
+ fn next_back(&mut self) -> Option<Self::Item> {
+ self.drain.next_back()
+ }
+}
+
+impl<I: Iterator> ExactSizeIterator for Splice<'_, I> {}
+
+impl<I: Iterator> Drop for Splice<'_, I> {
+ fn drop(&mut self) {
+ // Ensure we've fully drained out the range
+ self.drain.by_ref().for_each(drop);
+
+ unsafe {
+ // If there's no tail elements, then the inner ThinVec is already
+ // correct and we can just extend it like normal.
+ if self.drain.tail == 0 {
+ (*self.drain.vec).extend(self.replace_with.by_ref());
+ return;
+ }
+
+ // First fill the range left by drain().
+ if !self.drain.fill(&mut self.replace_with) {
+ return;
+ }
+
+ // There may be more elements. Use the lower bound as an estimate.
+ let (lower_bound, _upper_bound) = self.replace_with.size_hint();
+ if lower_bound > 0 {
+ self.drain.move_tail(lower_bound);
+ if !self.drain.fill(&mut self.replace_with) {
+ return;
+ }
+ }
+
+ // Collect any remaining elements.
+ // This is a zero-length vector which does not allocate if `lower_bound` was exact.
+ let mut collected = self
+ .replace_with
+ .by_ref()
+ .collect::<Vec<I::Item>>()
+ .into_iter();
+ // Now we have an exact count.
+ if collected.len() > 0 {
+ self.drain.move_tail(collected.len());
+ let filled = self.drain.fill(&mut collected);
+ debug_assert!(filled);
+ debug_assert_eq!(collected.len(), 0);
+ }
+ }
+ // Let `Drain::drop` move the tail back if necessary and restore `vec.len`.
+ }
+}
+
+/// Private helper methods for `Splice::drop`
+impl<T> Drain<'_, T> {
+ /// The range from `self.vec.len` to `self.tail_start` contains elements
+ /// that have been moved out.
+ /// Fill that range as much as possible with new elements from the `replace_with` iterator.
+ /// Returns `true` if we filled the entire range. (`replace_with.next()` didn’t return `None`.)
+ unsafe fn fill<I: Iterator<Item = T>>(&mut self, replace_with: &mut I) -> bool {
+ let vec = unsafe { &mut *self.vec };
+ let range_start = vec.len();
+ let range_end = self.end;
+ let range_slice = unsafe {
+ slice::from_raw_parts_mut(vec.data_raw().add(range_start), range_end - range_start)
+ };
+
+ for place in range_slice {
+ if let Some(new_item) = replace_with.next() {
+ unsafe { ptr::write(place, new_item) };
+ vec.set_len(vec.len() + 1);
+ } else {
+ return false;
+ }
+ }
+ true
+ }
+
+ /// Makes room for inserting more elements before the tail.
+ unsafe fn move_tail(&mut self, additional: usize) {
+ let vec = unsafe { &mut *self.vec };
+ let len = self.end + self.tail;
+ vec.reserve(len.checked_add(additional).expect("capacity overflow"));
+
+ let new_tail_start = self.end + additional;
+ unsafe {
+ let src = vec.data_raw().add(self.end);
+ let dst = vec.data_raw().add(new_tail_start);
+ ptr::copy(src, dst, self.tail);
+ }
+ self.end = new_tail_start;
+ }
+}
+
/// Write is implemented for `ThinVec<u8>` by appending to the vector.
/// The vector will grow as needed.
/// This implementation is identical to the one for `Vec<u8>`.
@@ -1755,6 +2838,19 @@ mod tests {
{
let mut v = ThinVec::<i32>::new();
+ assert_eq!(v.splice(.., []).len(), 0);
+
+ for _ in v.splice(.., []) {
+ unreachable!()
+ }
+
+ assert_eq!(v.len(), 0);
+ assert_eq!(v.capacity(), 0);
+ assert_eq!(&v[..], &[]);
+ }
+
+ {
+ let mut v = ThinVec::<i32>::new();
v.truncate(1);
assert_eq!(v.len(), 0);
assert_eq!(v.capacity(), 0);
@@ -2507,70 +3603,76 @@ mod std_tests {
v.drain(5..=5);
}
- /* TODO: implement splice?
- #[test]
- fn test_splice() {
- let mut v = thin_vec![1, 2, 3, 4, 5];
- let a = [10, 11, 12];
- v.splice(2..4, a.iter().cloned());
- assert_eq!(v, &[1, 2, 10, 11, 12, 5]);
- v.splice(1..3, Some(20));
- assert_eq!(v, &[1, 20, 11, 12, 5]);
- }
+ #[test]
+ fn test_splice() {
+ let mut v = thin_vec![1, 2, 3, 4, 5];
+ let a = [10, 11, 12];
+ v.splice(2..4, a.iter().cloned());
+ assert_eq!(v, &[1, 2, 10, 11, 12, 5]);
+ v.splice(1..3, Some(20));
+ assert_eq!(v, &[1, 20, 11, 12, 5]);
+ }
- #[test]
- fn test_splice_inclusive_range() {
- let mut v = thin_vec![1, 2, 3, 4, 5];
- let a = [10, 11, 12];
- let t1: ThinVec<_> = v.splice(2..=3, a.iter().cloned()).collect();
- assert_eq!(v, &[1, 2, 10, 11, 12, 5]);
- assert_eq!(t1, &[3, 4]);
- let t2: ThinVec<_> = v.splice(1..=2, Some(20)).collect();
- assert_eq!(v, &[1, 20, 11, 12, 5]);
- assert_eq!(t2, &[2, 10]);
- }
+ #[test]
+ fn test_splice_inclusive_range() {
+ let mut v = thin_vec![1, 2, 3, 4, 5];
+ let a = [10, 11, 12];
+ let t1: ThinVec<_> = v.splice(2..=3, a.iter().cloned()).collect();
+ assert_eq!(v, &[1, 2, 10, 11, 12, 5]);
+ assert_eq!(t1, &[3, 4]);
+ let t2: ThinVec<_> = v.splice(1..=2, Some(20)).collect();
+ assert_eq!(v, &[1, 20, 11, 12, 5]);
+ assert_eq!(t2, &[2, 10]);
+ }
- #[test]
- #[should_panic]
- fn test_splice_out_of_bounds() {
- let mut v = thin_vec![1, 2, 3, 4, 5];
- let a = [10, 11, 12];
- v.splice(5..6, a.iter().cloned());
- }
+ #[test]
+ #[should_panic]
+ fn test_splice_out_of_bounds() {
+ let mut v = thin_vec![1, 2, 3, 4, 5];
+ let a = [10, 11, 12];
+ v.splice(5..6, a.iter().cloned());
+ }
- #[test]
- #[should_panic]
- fn test_splice_inclusive_out_of_bounds() {
- let mut v = thin_vec![1, 2, 3, 4, 5];
- let a = [10, 11, 12];
- v.splice(5..=5, a.iter().cloned());
- }
+ #[test]
+ #[should_panic]
+ fn test_splice_inclusive_out_of_bounds() {
+ let mut v = thin_vec![1, 2, 3, 4, 5];
+ let a = [10, 11, 12];
+ v.splice(5..=5, a.iter().cloned());
+ }
- #[test]
- fn test_splice_items_zero_sized() {
- let mut vec = thin_vec![(), (), ()];
- let vec2 = thin_vec![];
- let t: ThinVec<_> = vec.splice(1..2, vec2.iter().cloned()).collect();
- assert_eq!(vec, &[(), ()]);
- assert_eq!(t, &[()]);
- }
+ #[test]
+ fn test_splice_items_zero_sized() {
+ let mut vec = thin_vec![(), (), ()];
+ let vec2 = thin_vec![];
+ let t: ThinVec<_> = vec.splice(1..2, vec2.iter().cloned()).collect();
+ assert_eq!(vec, &[(), ()]);
+ assert_eq!(t, &[()]);
+ }
- #[test]
- fn test_splice_unbounded() {
- let mut vec = thin_vec![1, 2, 3, 4, 5];
- let t: ThinVec<_> = vec.splice(.., None).collect();
- assert_eq!(vec, &[]);
- assert_eq!(t, &[1, 2, 3, 4, 5]);
- }
+ #[test]
+ fn test_splice_unbounded() {
+ let mut vec = thin_vec![1, 2, 3, 4, 5];
+ let t: ThinVec<_> = vec.splice(.., None).collect();
+ assert_eq!(vec, &[]);
+ assert_eq!(t, &[1, 2, 3, 4, 5]);
+ }
- #[test]
- fn test_splice_forget() {
- let mut v = thin_vec![1, 2, 3, 4, 5];
- let a = [10, 11, 12];
- ::std::mem::forget(v.splice(2..4, a.iter().cloned()));
- assert_eq!(v, &[1, 2]);
- }
- */
+ #[test]
+ fn test_splice_forget() {
+ let mut v = thin_vec![1, 2, 3, 4, 5];
+ let a = [10, 11, 12];
+ ::std::mem::forget(v.splice(2..4, a.iter().cloned()));
+ assert_eq!(v, &[1, 2]);
+ }
+
+ #[test]
+ fn test_splice_from_empty() {
+ let mut v = thin_vec![];
+ let a = [10, 11, 12];
+ v.splice(.., a.iter().cloned());
+ assert_eq!(v, &[10, 11, 12]);
+ }
/* probs won't ever impl this
#[test]
@@ -2598,81 +3700,59 @@ mod std_tests {
assert_eq!(vec2, [5, 6]);
}
- /* TODO: implement into_iter methods?
- #[test]
- fn test_into_iter_as_slice() {
- let vec = thin_vec!['a', 'b', 'c'];
- let mut into_iter = vec.into_iter();
- assert_eq!(into_iter.as_slice(), &['a', 'b', 'c']);
- let _ = into_iter.next().unwrap();
- assert_eq!(into_iter.as_slice(), &['b', 'c']);
- let _ = into_iter.next().unwrap();
- let _ = into_iter.next().unwrap();
- assert_eq!(into_iter.as_slice(), &[]);
- }
-
- #[test]
- fn test_into_iter_as_mut_slice() {
- let vec = thin_vec!['a', 'b', 'c'];
- let mut into_iter = vec.into_iter();
- assert_eq!(into_iter.as_slice(), &['a', 'b', 'c']);
- into_iter.as_mut_slice()[0] = 'x';
- into_iter.as_mut_slice()[1] = 'y';
- assert_eq!(into_iter.next().unwrap(), 'x');
- assert_eq!(into_iter.as_slice(), &['y', 'c']);
- }
-
- #[test]
- fn test_into_iter_debug() {
- let vec = thin_vec!['a', 'b', 'c'];
- let into_iter = vec.into_iter();
- let debug = format!("{:?}", into_iter);
- assert_eq!(debug, "IntoIter(['a', 'b', 'c'])");
- }
+ #[test]
+ fn test_into_iter_as_slice() {
+ let vec = thin_vec!['a', 'b', 'c'];
+ let mut into_iter = vec.into_iter();
+ assert_eq!(into_iter.as_slice(), &['a', 'b', 'c']);
+ let _ = into_iter.next().unwrap();
+ assert_eq!(into_iter.as_slice(), &['b', 'c']);
+ let _ = into_iter.next().unwrap();
+ let _ = into_iter.next().unwrap();
+ assert_eq!(into_iter.as_slice(), &[]);
+ }
- #[test]
- fn test_into_iter_count() {
- assert_eq!(thin_vec![1, 2, 3].into_iter().count(), 3);
- }
+ #[test]
+ fn test_into_iter_as_mut_slice() {
+ let vec = thin_vec!['a', 'b', 'c'];
+ let mut into_iter = vec.into_iter();
+ assert_eq!(into_iter.as_slice(), &['a', 'b', 'c']);
+ into_iter.as_mut_slice()[0] = 'x';
+ into_iter.as_mut_slice()[1] = 'y';
+ assert_eq!(into_iter.next().unwrap(), 'x');
+ assert_eq!(into_iter.as_slice(), &['y', 'c']);
+ }
- #[test]
- fn test_into_iter_clone() {
- fn iter_equal<I: Iterator<Item = i32>>(it: I, slice: &[i32]) {
- let v: ThinVec<i32> = it.collect();
- assert_eq!(&v[..], slice);
- }
- let mut it = thin_vec![1, 2, 3].into_iter();
- iter_equal(it.clone(), &[1, 2, 3]);
- assert_eq!(it.next(), Some(1));
- let mut it = it.rev();
- iter_equal(it.clone(), &[3, 2]);
- assert_eq!(it.next(), Some(3));
- iter_equal(it.clone(), &[2]);
- assert_eq!(it.next(), Some(2));
- iter_equal(it.clone(), &[]);
- assert_eq!(it.next(), None);
- }
- */
+ #[test]
+ fn test_into_iter_debug() {
+ let vec = thin_vec!['a', 'b', 'c'];
+ let into_iter = vec.into_iter();
+ let debug = format!("{:?}", into_iter);
+ assert_eq!(debug, "IntoIter(['a', 'b', 'c'])");
+ }
- /* TODO: implement CoW interop?
- #[test]
- fn test_cow_from() {
- let borrowed: &[_] = &["borrowed", "(slice)"];
- let owned = thin_vec!["owned", "(vec)"];
- match (Cow::from(owned.clone()), Cow::from(borrowed)) {
- (Cow::Owned(o), Cow::Borrowed(b)) => assert!(o == owned && b == borrowed),
- _ => panic!("invalid `Cow::from`"),
- }
- }
+ #[test]
+ fn test_into_iter_count() {
+ assert_eq!(thin_vec![1, 2, 3].into_iter().count(), 3);
+ }
- #[test]
- fn test_from_cow() {
- let borrowed: &[_] = &["borrowed", "(slice)"];
- let owned = thin_vec!["owned", "(vec)"];
- assert_eq!(ThinVec::from(Cow::Borrowed(borrowed)), thin_vec!["borrowed", "(slice)"]);
- assert_eq!(ThinVec::from(Cow::Owned(owned)), thin_vec!["owned", "(vec)"]);
+ #[test]
+ fn test_into_iter_clone() {
+ fn iter_equal<I: Iterator<Item = i32>>(it: I, slice: &[i32]) {
+ let v: ThinVec<i32> = it.collect();
+ assert_eq!(&v[..], slice);
}
- */
+ let mut it = thin_vec![1, 2, 3].into_iter();
+ iter_equal(it.clone(), &[1, 2, 3]);
+ assert_eq!(it.next(), Some(1));
+ let mut it = it.rev();
+ iter_equal(it.clone(), &[3, 2]);
+ assert_eq!(it.next(), Some(3));
+ iter_equal(it.clone(), &[2]);
+ assert_eq!(it.next(), Some(2));
+ iter_equal(it.clone(), &[]);
+ assert_eq!(it.next(), None);
+ }
/* TODO: make drain covariant
#[allow(dead_code)]
@@ -2704,22 +3784,21 @@ mod std_tests {
}
*/
- /* TODO: implement higher than 16 alignment
- #[test]
- fn overaligned_allocations() {
- #[repr(align(256))]
- struct Foo(usize);
- let mut v = thin_vec![Foo(273)];
- for i in 0..0x1000 {
- v.reserve_exact(i);
- assert!(v[0].0 == 273);
- assert!(v.as_ptr() as usize & 0xff == 0);
- v.shrink_to_fit();
- assert!(v[0].0 == 273);
- assert!(v.as_ptr() as usize & 0xff == 0);
- }
+ #[test]
+ #[cfg_attr(feature = "gecko-ffi", ignore)]
+ fn overaligned_allocations() {
+ #[repr(align(256))]
+ struct Foo(usize);
+ let mut v = thin_vec![Foo(273)];
+ for i in 0..0x1000 {
+ v.reserve_exact(i);
+ assert!(v[0].0 == 273);
+ assert!(v.as_ptr() as usize & 0xff == 0);
+ v.shrink_to_fit();
+ assert!(v[0].0 == 273);
+ assert!(v.as_ptr() as usize & 0xff == 0);
}
- */
+ }
/* TODO: implement drain_filter?
#[test]
@@ -3175,4 +4254,35 @@ mod std_tests {
vec.set_len(1);
}
}
+
+ #[test]
+ #[should_panic(expected = "capacity overflow")]
+ fn test_capacity_overflow_header_too_big() {
+ let vec: ThinVec<u8> = ThinVec::with_capacity(isize::MAX as usize - 2);
+ assert!(vec.capacity() > 0);
+ }
+ #[test]
+ #[should_panic(expected = "capacity overflow")]
+ fn test_capacity_overflow_cap_too_big() {
+ let vec: ThinVec<u8> = ThinVec::with_capacity(isize::MAX as usize + 1);
+ assert!(vec.capacity() > 0);
+ }
+ #[test]
+ #[should_panic(expected = "capacity overflow")]
+ fn test_capacity_overflow_size_mul1() {
+ let vec: ThinVec<u16> = ThinVec::with_capacity(isize::MAX as usize + 1);
+ assert!(vec.capacity() > 0);
+ }
+ #[test]
+ #[should_panic(expected = "capacity overflow")]
+ fn test_capacity_overflow_size_mul2() {
+ let vec: ThinVec<u16> = ThinVec::with_capacity(isize::MAX as usize / 2 + 1);
+ assert!(vec.capacity() > 0);
+ }
+ #[test]
+ #[should_panic(expected = "capacity overflow")]
+ fn test_capacity_overflow_cap_really_isnt_isize() {
+ let vec: ThinVec<u8> = ThinVec::with_capacity(isize::MAX as usize);
+ assert!(vec.capacity() > 0);
+ }
}
diff --git a/vendor/time-macros/.cargo-checksum.json b/vendor/time-macros/.cargo-checksum.json
deleted file mode 100644
index 98cc1d644..000000000
--- a/vendor/time-macros/.cargo-checksum.json
+++ /dev/null
@@ -1 +0,0 @@
-{"files":{"Cargo.toml":"eb16c06efbfbf2ff5f48260785d4ecefbae6873d9d55c0ba2d388c6762e69b1f","LICENSE-Apache":"b8929fea28678da67251fb2daf9438f67503814211051861612441806d8edb05","LICENSE-MIT":"04620bf27e4a643dd47bf27652320c205acdb776c1f9f24bb8c3bfaba10804c5","src/date.rs":"ffcd3d0998ec67abb43a3f8eccc6104172f5061b855312b89d53bb82fece2460","src/datetime.rs":"5c7f6e07dc2f0dcfcd86216664df53bc008dbc86f346df57a9ff57f52fe43bc6","src/error.rs":"b597f98f425f1628b93ffea19f5f32163aa204e4cd25351bc114853a798e14b0","src/format_description/component.rs":"a05e7549db9bab4f3836f5fd5af18cacbfa6b323d0106b027e21bf438a5885e5","src/format_description/error.rs":"41253d7a02e14597915cf588811a272a90d1ce0f857f7769914e076dd5a66774","src/format_description/mod.rs":"da47af329408e9428753ad98ce433eaf026cfdd6e73e3142b23285251d32d0dd","src/format_description/modifier.rs":"c252c8a7d6608b594a6f715210ff67e804ae2f308025f62c8dd99d707627e4a9","src/format_description/parse.rs":"d65d6e7008030414ce6a860ff37c462c07ed89176a3f1462eeb46468a38fce7e","src/helpers/mod.rs":"54ce8e93512e18ef8761687eaac898a8227852a732f92aa5e80c28e23315bd0c","src/helpers/string.rs":"ba5699a4df344cbd71c4143f642f6bc07591f53978a9800d4b49ca1f461f87d9","src/lib.rs":"f99bded51bb861be5d708a3f756407f5b936a5febb719760c253a15113687e0d","src/offset.rs":"fc9341648e091b4d8f7bec47006c01c21cb038c7ef98bd36a492cf78e7533023","src/quote.rs":"b40251b0ca68e2362aff4297b87a027e48053f1a419113d3d0f7fe089a845a9c","src/serde_format_description.rs":"aa279c8005005fc87c52fa5e8be8ef8fc13ef456a18e3cd5d702ae81194ba4d9","src/time.rs":"3c06562358aed7ef624319c96e3f9c150a069606ab930de98ac379ef16b08100","src/to_tokens.rs":"825150a92396a019fee44f21da0bd257349e276d5e75a23ff86cfc625bef6f10"},"package":"d967f99f534ca7e495c575c62638eebc2898a8c84c119b89e250477bc4ba16b2"} \ No newline at end of file
diff --git a/vendor/time-macros/Cargo.toml b/vendor/time-macros/Cargo.toml
deleted file mode 100644
index c770e23ad..000000000
--- a/vendor/time-macros/Cargo.toml
+++ /dev/null
@@ -1,45 +0,0 @@
-# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
-#
-# When uploading crates to the registry Cargo will automatically
-# "normalize" Cargo.toml files for maximal compatibility
-# with all versions of Cargo and also rewrite `path` dependencies
-# to registry (e.g., crates.io) dependencies.
-#
-# If you are reading this file be aware that the original Cargo.toml
-# will likely look very different (and much more reasonable).
-# See Cargo.toml.orig for the original contents.
-
-[package]
-edition = "2021"
-rust-version = "1.60.0"
-name = "time-macros"
-version = "0.2.6"
-authors = [
- "Jacob Pratt <open-source@jhpratt.dev>",
- "Time contributors",
-]
-description = """
- Procedural macros for the time crate.
- This crate is an implementation detail and should not be relied upon directly.
-"""
-keywords = [
- "date",
- "time",
- "calendar",
- "duration",
-]
-categories = ["date-and-time"]
-license = "MIT OR Apache-2.0"
-repository = "https://github.com/time-rs/time"
-
-[lib]
-proc-macro = true
-
-[dependencies.time-core]
-version = "=0.1.0"
-
-[features]
-formatting = []
-large-dates = []
-parsing = []
-serde = []
diff --git a/vendor/time-macros/src/date.rs b/vendor/time-macros/src/date.rs
deleted file mode 100644
index 574ef8ce6..000000000
--- a/vendor/time-macros/src/date.rs
+++ /dev/null
@@ -1,137 +0,0 @@
-use std::iter::Peekable;
-
-use proc_macro::{token_stream, TokenTree};
-use time_core::util::{days_in_year, weeks_in_year};
-
-use crate::helpers::{
- consume_any_ident, consume_number, consume_punct, days_in_year_month, ymd_to_yo, ywd_to_yo,
-};
-use crate::to_tokens::ToTokenTree;
-use crate::Error;
-
-#[cfg(feature = "large-dates")]
-const MAX_YEAR: i32 = 999_999;
-#[cfg(not(feature = "large-dates"))]
-const MAX_YEAR: i32 = 9_999;
-
-pub(crate) struct Date {
- pub(crate) year: i32,
- pub(crate) ordinal: u16,
-}
-
-pub(crate) fn parse(chars: &mut Peekable<token_stream::IntoIter>) -> Result<Date, Error> {
- let (year_sign_span, year_sign, explicit_sign) = if let Ok(span) = consume_punct('-', chars) {
- (Some(span), -1, true)
- } else if let Ok(span) = consume_punct('+', chars) {
- (Some(span), 1, true)
- } else {
- (None, 1, false)
- };
- let (year_span, mut year) = consume_number::<i32>("year", chars)?;
- year *= year_sign;
- if year.abs() > MAX_YEAR {
- return Err(Error::InvalidComponent {
- name: "year",
- value: year.to_string(),
- span_start: Some(year_sign_span.unwrap_or(year_span)),
- span_end: Some(year_span),
- });
- }
- if !explicit_sign && year.abs() >= 10_000 {
- return Err(Error::Custom {
- message: "years with more than four digits must have an explicit sign".into(),
- span_start: Some(year_sign_span.unwrap_or(year_span)),
- span_end: Some(year_span),
- });
- }
-
- consume_punct('-', chars)?;
-
- // year-week-day
- if let Ok(w_span) = consume_any_ident(&["W"], chars) {
- let (week_span, week) = consume_number::<u8>("week", chars)?;
- consume_punct('-', chars)?;
- let (day_span, day) = consume_number::<u8>("day", chars)?;
-
- if week > weeks_in_year(year) {
- return Err(Error::InvalidComponent {
- name: "week",
- value: week.to_string(),
- span_start: Some(w_span),
- span_end: Some(week_span),
- });
- }
- if day == 0 || day > 7 {
- return Err(Error::InvalidComponent {
- name: "day",
- value: day.to_string(),
- span_start: Some(day_span),
- span_end: Some(day_span),
- });
- }
-
- let (year, ordinal) = ywd_to_yo(year, week, day);
-
- return Ok(Date { year, ordinal });
- }
-
- // We don't yet know whether it's year-month-day or year-ordinal.
- let (month_or_ordinal_span, month_or_ordinal) =
- consume_number::<u16>("month or ordinal", chars)?;
-
- // year-month-day
- #[allow(clippy::branches_sharing_code)] // clarity
- if consume_punct('-', chars).is_ok() {
- let (month_span, month) = (month_or_ordinal_span, month_or_ordinal);
- let (day_span, day) = consume_number::<u8>("day", chars)?;
-
- if month == 0 || month > 12 {
- return Err(Error::InvalidComponent {
- name: "month",
- value: month.to_string(),
- span_start: Some(month_span),
- span_end: Some(month_span),
- });
- }
- let month = month as _;
- if day == 0 || day > days_in_year_month(year, month) {
- return Err(Error::InvalidComponent {
- name: "day",
- value: day.to_string(),
- span_start: Some(day_span),
- span_end: Some(day_span),
- });
- }
-
- let (year, ordinal) = ymd_to_yo(year, month, day);
-
- Ok(Date { year, ordinal })
- }
- // year-ordinal
- else {
- let (ordinal_span, ordinal) = (month_or_ordinal_span, month_or_ordinal);
-
- if ordinal == 0 || ordinal > days_in_year(year) {
- return Err(Error::InvalidComponent {
- name: "ordinal",
- value: ordinal.to_string(),
- span_start: Some(ordinal_span),
- span_end: Some(ordinal_span),
- });
- }
-
- Ok(Date { year, ordinal })
- }
-}
-
-impl ToTokenTree for Date {
- fn into_token_tree(self) -> TokenTree {
- quote_group! {{
- const DATE: ::time::Date = ::time::Date::__from_ordinal_date_unchecked(
- #(self.year),
- #(self.ordinal),
- );
- DATE
- }}
- }
-}
diff --git a/vendor/time-macros/src/datetime.rs b/vendor/time-macros/src/datetime.rs
deleted file mode 100644
index 2d41e9a53..000000000
--- a/vendor/time-macros/src/datetime.rs
+++ /dev/null
@@ -1,57 +0,0 @@
-use std::iter::Peekable;
-
-use proc_macro::{token_stream, Ident, Span, TokenTree};
-
-use crate::date::Date;
-use crate::error::Error;
-use crate::offset::Offset;
-use crate::time::Time;
-use crate::to_tokens::ToTokenTree;
-use crate::{date, offset, time};
-
-pub(crate) struct DateTime {
- date: Date,
- time: Time,
- offset: Option<Offset>,
-}
-
-pub(crate) fn parse(chars: &mut Peekable<token_stream::IntoIter>) -> Result<DateTime, Error> {
- let date = date::parse(chars)?;
- let time = time::parse(chars)?;
- let offset = match offset::parse(chars) {
- Ok(offset) => Some(offset),
- Err(Error::UnexpectedEndOfInput | Error::MissingComponent { name: "sign", .. }) => None,
- Err(err) => return Err(err),
- };
-
- if let Some(token) = chars.peek() {
- return Err(Error::UnexpectedToken {
- tree: token.clone(),
- });
- }
-
- Ok(DateTime { date, time, offset })
-}
-
-impl ToTokenTree for DateTime {
- fn into_token_tree(self) -> TokenTree {
- let (type_name, maybe_offset) = match self.offset {
- Some(offset) => (
- Ident::new("OffsetDateTime", Span::mixed_site()),
- quote!(.assume_offset(#(offset))),
- ),
- None => (
- Ident::new("PrimitiveDateTime", Span::mixed_site()),
- quote!(),
- ),
- };
-
- quote_group! {{
- const DATE_TIME: ::time::#(type_name) = ::time::PrimitiveDateTime::new(
- #(self.date),
- #(self.time),
- ) #S(maybe_offset);
- DATE_TIME
- }}
- }
-}
diff --git a/vendor/time-macros/src/error.rs b/vendor/time-macros/src/error.rs
deleted file mode 100644
index 4de369daf..000000000
--- a/vendor/time-macros/src/error.rs
+++ /dev/null
@@ -1,136 +0,0 @@
-use std::borrow::Cow;
-use std::fmt;
-
-use proc_macro::{Delimiter, Group, Ident, Literal, Punct, Spacing, Span, TokenStream, TokenTree};
-
-#[cfg(any(feature = "formatting", feature = "parsing"))]
-use crate::format_description::error::InvalidFormatDescription;
-
-trait WithSpan {
- fn with_span(self, span: Span) -> Self;
-}
-
-impl WithSpan for TokenTree {
- fn with_span(mut self, span: Span) -> Self {
- self.set_span(span);
- self
- }
-}
-
-pub(crate) enum Error {
- MissingComponent {
- name: &'static str,
- span_start: Option<Span>,
- span_end: Option<Span>,
- },
- InvalidComponent {
- name: &'static str,
- value: String,
- span_start: Option<Span>,
- span_end: Option<Span>,
- },
- #[cfg(any(feature = "formatting", feature = "parsing"))]
- ExpectedString {
- span_start: Option<Span>,
- span_end: Option<Span>,
- },
- UnexpectedToken {
- tree: TokenTree,
- },
- UnexpectedEndOfInput,
- #[cfg(any(feature = "formatting", feature = "parsing"))]
- InvalidFormatDescription {
- error: InvalidFormatDescription,
- span_start: Option<Span>,
- span_end: Option<Span>,
- },
- Custom {
- message: Cow<'static, str>,
- span_start: Option<Span>,
- span_end: Option<Span>,
- },
-}
-
-impl fmt::Display for Error {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- match self {
- Self::MissingComponent { name, .. } => write!(f, "missing component: {name}"),
- Self::InvalidComponent { name, value, .. } => {
- write!(f, "invalid component: {name} was {value}")
- }
- #[cfg(any(feature = "formatting", feature = "parsing"))]
- Self::ExpectedString { .. } => f.write_str("expected string"),
- Self::UnexpectedToken { tree } => write!(f, "unexpected token: {tree}"),
- Self::UnexpectedEndOfInput => f.write_str("unexpected end of input"),
- #[cfg(any(feature = "formatting", feature = "parsing"))]
- Self::InvalidFormatDescription { error, .. } => error.fmt(f),
- Self::Custom { message, .. } => f.write_str(message),
- }
- }
-}
-
-impl Error {
- fn span_start(&self) -> Span {
- match self {
- Self::MissingComponent { span_start, .. }
- | Self::InvalidComponent { span_start, .. }
- | Self::Custom { span_start, .. } => *span_start,
- #[cfg(any(feature = "formatting", feature = "parsing"))]
- Self::ExpectedString { span_start, .. }
- | Self::InvalidFormatDescription { span_start, .. } => *span_start,
- Self::UnexpectedToken { tree } => Some(tree.span()),
- Self::UnexpectedEndOfInput => Some(Span::mixed_site()),
- }
- .unwrap_or_else(Span::mixed_site)
- }
-
- fn span_end(&self) -> Span {
- match self {
- Self::MissingComponent { span_end, .. }
- | Self::InvalidComponent { span_end, .. }
- | Self::Custom { span_end, .. } => *span_end,
- #[cfg(any(feature = "formatting", feature = "parsing"))]
- Self::ExpectedString { span_end, .. }
- | Self::InvalidFormatDescription { span_end, .. } => *span_end,
- Self::UnexpectedToken { tree, .. } => Some(tree.span()),
- Self::UnexpectedEndOfInput => Some(Span::mixed_site()),
- }
- .unwrap_or_else(|| self.span_start())
- }
-
- pub(crate) fn to_compile_error(&self) -> TokenStream {
- let (start, end) = (self.span_start(), self.span_end());
-
- [
- TokenTree::from(Punct::new(':', Spacing::Joint)).with_span(start),
- TokenTree::from(Punct::new(':', Spacing::Alone)).with_span(start),
- TokenTree::from(Ident::new("core", start)),
- TokenTree::from(Punct::new(':', Spacing::Joint)).with_span(start),
- TokenTree::from(Punct::new(':', Spacing::Alone)).with_span(start),
- TokenTree::from(Ident::new("compile_error", start)),
- TokenTree::from(Punct::new('!', Spacing::Alone)).with_span(start),
- TokenTree::from(Group::new(
- Delimiter::Parenthesis,
- TokenStream::from(
- TokenTree::from(Literal::string(&self.to_string())).with_span(end),
- ),
- ))
- .with_span(end),
- ]
- .iter()
- .cloned()
- .collect()
- }
-
- /// Like `to_compile_error`, but for use in macros that produce items.
- #[cfg(all(feature = "serde", any(feature = "formatting", feature = "parsing")))]
- pub(crate) fn to_compile_error_standalone(&self) -> TokenStream {
- let end = self.span_end();
- self.to_compile_error()
- .into_iter()
- .chain(std::iter::once(
- TokenTree::from(Punct::new(';', Spacing::Alone)).with_span(end),
- ))
- .collect()
- }
-}
diff --git a/vendor/time-macros/src/format_description/component.rs b/vendor/time-macros/src/format_description/component.rs
deleted file mode 100644
index 850da91d2..000000000
--- a/vendor/time-macros/src/format_description/component.rs
+++ /dev/null
@@ -1,168 +0,0 @@
-use proc_macro::{Ident, Span, TokenStream};
-
-use crate::format_description::error::InvalidFormatDescription;
-use crate::format_description::modifier;
-use crate::format_description::modifier::Modifiers;
-use crate::to_tokens::ToTokenStream;
-
-pub(crate) enum Component {
- Day(modifier::Day),
- Month(modifier::Month),
- Ordinal(modifier::Ordinal),
- Weekday(modifier::Weekday),
- WeekNumber(modifier::WeekNumber),
- Year(modifier::Year),
- Hour(modifier::Hour),
- Minute(modifier::Minute),
- Period(modifier::Period),
- Second(modifier::Second),
- Subsecond(modifier::Subsecond),
- OffsetHour(modifier::OffsetHour),
- OffsetMinute(modifier::OffsetMinute),
- OffsetSecond(modifier::OffsetSecond),
-}
-
-impl ToTokenStream for Component {
- fn append_to(self, ts: &mut TokenStream) {
- let mut mts = TokenStream::new();
-
- macro_rules! component_name_and_append {
- ($($name:ident)*) => {
- match self {
- $(Self::$name(modifier) => {
- modifier.append_to(&mut mts);
- stringify!($name)
- })*
- }
- };
- }
-
- let component = component_name_and_append![
- Day
- Month
- Ordinal
- Weekday
- WeekNumber
- Year
- Hour
- Minute
- Period
- Second
- Subsecond
- OffsetHour
- OffsetMinute
- OffsetSecond
- ];
- let component = Ident::new(component, Span::mixed_site());
-
- quote_append! { ts
- ::time::format_description::Component::#(component)(#S(mts))
- }
- }
-}
-
-pub(crate) enum NakedComponent {
- Day,
- Month,
- Ordinal,
- Weekday,
- WeekNumber,
- Year,
- Hour,
- Minute,
- Period,
- Second,
- Subsecond,
- OffsetHour,
- OffsetMinute,
- OffsetSecond,
-}
-
-impl NakedComponent {
- pub(crate) fn parse(
- component_name: &[u8],
- component_index: usize,
- ) -> Result<Self, InvalidFormatDescription> {
- match component_name {
- b"day" => Ok(Self::Day),
- b"month" => Ok(Self::Month),
- b"ordinal" => Ok(Self::Ordinal),
- b"weekday" => Ok(Self::Weekday),
- b"week_number" => Ok(Self::WeekNumber),
- b"year" => Ok(Self::Year),
- b"hour" => Ok(Self::Hour),
- b"minute" => Ok(Self::Minute),
- b"period" => Ok(Self::Period),
- b"second" => Ok(Self::Second),
- b"subsecond" => Ok(Self::Subsecond),
- b"offset_hour" => Ok(Self::OffsetHour),
- b"offset_minute" => Ok(Self::OffsetMinute),
- b"offset_second" => Ok(Self::OffsetSecond),
- b"" => Err(InvalidFormatDescription::MissingComponentName {
- index: component_index,
- }),
- _ => Err(InvalidFormatDescription::InvalidComponentName {
- name: String::from_utf8_lossy(component_name).into_owned(),
- index: component_index,
- }),
- }
- }
-
- pub(crate) fn attach_modifiers(self, modifiers: Modifiers) -> Component {
- match self {
- Self::Day => Component::Day(modifier::Day {
- padding: modifiers.padding.unwrap_or_default(),
- }),
- Self::Month => Component::Month(modifier::Month {
- padding: modifiers.padding.unwrap_or_default(),
- repr: modifiers.month_repr.unwrap_or_default(),
- case_sensitive: modifiers.case_sensitive.unwrap_or(true),
- }),
- Self::Ordinal => Component::Ordinal(modifier::Ordinal {
- padding: modifiers.padding.unwrap_or_default(),
- }),
- Self::Weekday => Component::Weekday(modifier::Weekday {
- repr: modifiers.weekday_repr.unwrap_or_default(),
- one_indexed: modifiers.weekday_is_one_indexed.unwrap_or(true),
- case_sensitive: modifiers.case_sensitive.unwrap_or(true),
- }),
- Self::WeekNumber => Component::WeekNumber(modifier::WeekNumber {
- padding: modifiers.padding.unwrap_or_default(),
- repr: modifiers.week_number_repr.unwrap_or_default(),
- }),
- Self::Year => Component::Year(modifier::Year {
- padding: modifiers.padding.unwrap_or_default(),
- repr: modifiers.year_repr.unwrap_or_default(),
- iso_week_based: modifiers.year_is_iso_week_based.unwrap_or_default(),
- sign_is_mandatory: modifiers.sign_is_mandatory.unwrap_or_default(),
- }),
- Self::Hour => Component::Hour(modifier::Hour {
- padding: modifiers.padding.unwrap_or_default(),
- is_12_hour_clock: modifiers.hour_is_12_hour_clock.unwrap_or_default(),
- }),
- Self::Minute => Component::Minute(modifier::Minute {
- padding: modifiers.padding.unwrap_or_default(),
- }),
- Self::Period => Component::Period(modifier::Period {
- is_uppercase: modifiers.period_is_uppercase.unwrap_or(true),
- case_sensitive: modifiers.case_sensitive.unwrap_or(true),
- }),
- Self::Second => Component::Second(modifier::Second {
- padding: modifiers.padding.unwrap_or_default(),
- }),
- Self::Subsecond => Component::Subsecond(modifier::Subsecond {
- digits: modifiers.subsecond_digits.unwrap_or_default(),
- }),
- Self::OffsetHour => Component::OffsetHour(modifier::OffsetHour {
- sign_is_mandatory: modifiers.sign_is_mandatory.unwrap_or_default(),
- padding: modifiers.padding.unwrap_or_default(),
- }),
- Self::OffsetMinute => Component::OffsetMinute(modifier::OffsetMinute {
- padding: modifiers.padding.unwrap_or_default(),
- }),
- Self::OffsetSecond => Component::OffsetSecond(modifier::OffsetSecond {
- padding: modifiers.padding.unwrap_or_default(),
- }),
- }
- }
-}
diff --git a/vendor/time-macros/src/format_description/error.rs b/vendor/time-macros/src/format_description/error.rs
deleted file mode 100644
index 9aacd7dc9..000000000
--- a/vendor/time-macros/src/format_description/error.rs
+++ /dev/null
@@ -1,29 +0,0 @@
-use std::fmt;
-
-pub(crate) enum InvalidFormatDescription {
- UnclosedOpeningBracket { index: usize },
- InvalidComponentName { name: String, index: usize },
- InvalidModifier { value: String, index: usize },
- MissingComponentName { index: usize },
-}
-
-impl fmt::Display for InvalidFormatDescription {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- #[allow(clippy::enum_glob_use)]
- use InvalidFormatDescription::*;
- match self {
- UnclosedOpeningBracket { index } => {
- write!(f, "unclosed opening bracket at byte index {index}")
- }
- InvalidComponentName { name, index } => {
- write!(f, "invalid component name `{name}` at byte index {index}",)
- }
- InvalidModifier { value, index } => {
- write!(f, "invalid modifier `{value}` at byte index {index}")
- }
- MissingComponentName { index } => {
- write!(f, "missing component name at byte index {index}")
- }
- }
- }
-}
diff --git a/vendor/time-macros/src/format_description/mod.rs b/vendor/time-macros/src/format_description/mod.rs
deleted file mode 100644
index dd32db74d..000000000
--- a/vendor/time-macros/src/format_description/mod.rs
+++ /dev/null
@@ -1,40 +0,0 @@
-mod component;
-pub(crate) mod error;
-pub(crate) mod modifier;
-pub(crate) mod parse;
-
-use proc_macro::{Literal, TokenStream};
-
-pub(crate) use self::component::Component;
-pub(crate) use self::parse::parse;
-use crate::to_tokens::ToTokenStream;
-
-mod helper {
- #[must_use = "This does not modify the original slice."]
- pub(crate) fn consume_whitespace<'a>(bytes: &'a [u8], index: &mut usize) -> &'a [u8] {
- let first_non_whitespace = bytes
- .iter()
- .position(|c| !c.is_ascii_whitespace())
- .unwrap_or(bytes.len());
- *index += first_non_whitespace;
- &bytes[first_non_whitespace..]
- }
-}
-
-#[allow(single_use_lifetimes)] // false positive
-#[allow(variant_size_differences)]
-pub(crate) enum FormatItem<'a> {
- Literal(&'a [u8]),
- Component(Component),
-}
-
-impl ToTokenStream for FormatItem<'_> {
- fn append_to(self, ts: &mut TokenStream) {
- quote_append! { ts
- ::time::format_description::FormatItem::#S(match self {
- FormatItem::Literal(bytes) => quote! { Literal(#(Literal::byte_string(bytes))) },
- FormatItem::Component(component) => quote! { Component(#S(component)) },
- })
- }
- }
-}
diff --git a/vendor/time-macros/src/format_description/modifier.rs b/vendor/time-macros/src/format_description/modifier.rs
deleted file mode 100644
index f4e641a7b..000000000
--- a/vendor/time-macros/src/format_description/modifier.rs
+++ /dev/null
@@ -1,417 +0,0 @@
-use core::mem;
-
-use proc_macro::{Ident, Span, TokenStream, TokenTree};
-
-use crate::format_description::error::InvalidFormatDescription;
-use crate::format_description::helper;
-use crate::to_tokens::{ToTokenStream, ToTokenTree};
-
-macro_rules! to_tokens {
- (
- $(#[$struct_attr:meta])*
- $struct_vis:vis struct $struct_name:ident {$(
- $(#[$field_attr:meta])*
- $field_vis:vis $field_name:ident : $field_ty:ty
- ),+ $(,)?}
- ) => {
- $(#[$struct_attr])*
- $struct_vis struct $struct_name {$(
- $(#[$field_attr])*
- $field_vis $field_name: $field_ty
- ),+}
-
- impl ToTokenTree for $struct_name {
- fn into_token_tree(self) -> TokenTree {
- let mut tokens = TokenStream::new();
- let Self {$($field_name),+} = self;
-
- quote_append! { tokens
- let mut value = ::time::format_description::modifier::$struct_name::default();
- };
- $(
- quote_append!(tokens value.$field_name =);
- $field_name.append_to(&mut tokens);
- quote_append!(tokens ;);
- )+
- quote_append!(tokens value);
-
- proc_macro::TokenTree::Group(proc_macro::Group::new(
- proc_macro::Delimiter::Brace,
- tokens,
- ))
- }
- }
- };
-
- (
- $(#[$enum_attr:meta])*
- $enum_vis:vis enum $enum_name:ident {$(
- $(#[$variant_attr:meta])*
- $variant_name:ident
- ),+ $(,)?}
- ) => {
- $(#[$enum_attr])*
- $enum_vis enum $enum_name {$(
- $(#[$variant_attr])*
- $variant_name
- ),+}
-
- impl ToTokenStream for $enum_name {
- fn append_to(self, ts: &mut TokenStream) {
- quote_append! { ts
- ::time::format_description::modifier::$enum_name::
- };
- let name = match self {
- $(Self::$variant_name => stringify!($variant_name)),+
- };
- ts.extend([TokenTree::Ident(Ident::new(name, Span::mixed_site()))]);
- }
- }
- }
-}
-
-to_tokens! {
- pub(crate) struct Day {
- pub(crate) padding: Padding,
- }
-}
-
-to_tokens! {
- pub(crate) enum MonthRepr {
- Numerical,
- Long,
- Short,
- }
-}
-
-to_tokens! {
- pub(crate) struct Month {
- pub(crate) padding: Padding,
- pub(crate) repr: MonthRepr,
- pub(crate) case_sensitive: bool,
- }
-}
-
-to_tokens! {
- pub(crate) struct Ordinal {
- pub(crate) padding: Padding,
- }
-}
-
-to_tokens! {
- pub(crate) enum WeekdayRepr {
- Short,
- Long,
- Sunday,
- Monday,
- }
-}
-
-to_tokens! {
- pub(crate) struct Weekday {
- pub(crate) repr: WeekdayRepr,
- pub(crate) one_indexed: bool,
- pub(crate) case_sensitive: bool,
- }
-}
-
-to_tokens! {
- pub(crate) enum WeekNumberRepr {
- Iso,
- Sunday,
- Monday,
- }
-}
-
-to_tokens! {
- pub(crate) struct WeekNumber {
- pub(crate) padding: Padding,
- pub(crate) repr: WeekNumberRepr,
- }
-}
-
-to_tokens! {
- pub(crate) enum YearRepr {
- Full,
- LastTwo,
- }
-}
-
-to_tokens! {
- pub(crate) struct Year {
- pub(crate) padding: Padding,
- pub(crate) repr: YearRepr,
- pub(crate) iso_week_based: bool,
- pub(crate) sign_is_mandatory: bool,
- }
-}
-
-to_tokens! {
- pub(crate) struct Hour {
- pub(crate) padding: Padding,
- pub(crate) is_12_hour_clock: bool,
- }
-}
-
-to_tokens! {
- pub(crate) struct Minute {
- pub(crate) padding: Padding,
- }
-}
-
-to_tokens! {
- pub(crate) struct Period {
- pub(crate) is_uppercase: bool,
- pub(crate) case_sensitive: bool,
- }
-}
-
-to_tokens! {
- pub(crate) struct Second {
- pub(crate) padding: Padding,
- }
-}
-
-to_tokens! {
- pub(crate) enum SubsecondDigits {
- One,
- Two,
- Three,
- Four,
- Five,
- Six,
- Seven,
- Eight,
- Nine,
- OneOrMore,
- }
-}
-
-to_tokens! {
- pub(crate) struct Subsecond {
- pub(crate) digits: SubsecondDigits,
- }
-}
-
-to_tokens! {
- pub(crate) struct OffsetHour {
- pub(crate) sign_is_mandatory: bool,
- pub(crate) padding: Padding,
- }
-}
-
-to_tokens! {
- pub(crate) struct OffsetMinute {
- pub(crate) padding: Padding,
- }
-}
-
-to_tokens! {
- pub(crate) struct OffsetSecond {
- pub(crate) padding: Padding,
- }
-}
-
-to_tokens! {
- pub(crate) enum Padding {
- Space,
- Zero,
- None,
- }
-}
-
-macro_rules! impl_default {
- ($($type:ty => $default:expr;)*) => {$(
- impl Default for $type {
- fn default() -> Self {
- $default
- }
- }
- )*};
-}
-
-impl_default! {
- Day => Self { padding: Padding::default() };
- MonthRepr => Self::Numerical;
- Month => Self {
- padding: Padding::default(),
- repr: MonthRepr::default(),
- case_sensitive: true,
- };
- Ordinal => Self { padding: Padding::default() };
- WeekdayRepr => Self::Long;
- Weekday => Self {
- repr: WeekdayRepr::default(),
- one_indexed: true,
- case_sensitive: true,
- };
- WeekNumberRepr => Self::Iso;
- WeekNumber => Self {
- padding: Padding::default(),
- repr: WeekNumberRepr::default(),
- };
- YearRepr => Self::Full;
- Year => Self {
- padding: Padding::default(),
- repr: YearRepr::default(),
- iso_week_based: false,
- sign_is_mandatory: false,
- };
- Hour => Self {
- padding: Padding::default(),
- is_12_hour_clock: false,
- };
- Minute => Self { padding: Padding::default() };
- Period => Self { is_uppercase: true, case_sensitive: true };
- Second => Self { padding: Padding::default() };
- SubsecondDigits => Self::OneOrMore;
- Subsecond => Self { digits: SubsecondDigits::default() };
- OffsetHour => Self {
- sign_is_mandatory: true,
- padding: Padding::default(),
- };
- OffsetMinute => Self { padding: Padding::default() };
- OffsetSecond => Self { padding: Padding::default() };
- Padding => Self::Zero;
-}
-
-#[derive(Default)]
-pub(crate) struct Modifiers {
- pub(crate) padding: Option<Padding>,
- pub(crate) hour_is_12_hour_clock: Option<bool>,
- pub(crate) period_is_uppercase: Option<bool>,
- pub(crate) month_repr: Option<MonthRepr>,
- pub(crate) subsecond_digits: Option<SubsecondDigits>,
- pub(crate) weekday_repr: Option<WeekdayRepr>,
- pub(crate) weekday_is_one_indexed: Option<bool>,
- pub(crate) week_number_repr: Option<WeekNumberRepr>,
- pub(crate) year_repr: Option<YearRepr>,
- pub(crate) year_is_iso_week_based: Option<bool>,
- pub(crate) sign_is_mandatory: Option<bool>,
- pub(crate) case_sensitive: Option<bool>,
-}
-
-impl Modifiers {
- #[allow(clippy::too_many_lines)]
- pub(crate) fn parse(
- component_name: &[u8],
- mut bytes: &[u8],
- index: &mut usize,
- ) -> Result<Self, InvalidFormatDescription> {
- let mut modifiers = Self::default();
-
- while !bytes.is_empty() {
- // Trim any whitespace between modifiers.
- bytes = helper::consume_whitespace(bytes, index);
-
- let modifier;
- if let Some(whitespace_loc) = bytes.iter().position(u8::is_ascii_whitespace) {
- *index += whitespace_loc;
- modifier = &bytes[..whitespace_loc];
- bytes = &bytes[whitespace_loc..];
- } else {
- modifier = mem::take(&mut bytes);
- }
-
- if modifier.is_empty() {
- break;
- }
-
- match (component_name, modifier) {
- (
- b"day" | b"hour" | b"minute" | b"month" | b"offset_hour" | b"offset_minute"
- | b"offset_second" | b"ordinal" | b"second" | b"week_number" | b"year",
- b"padding:space",
- ) => modifiers.padding = Some(Padding::Space),
- (
- b"day" | b"hour" | b"minute" | b"month" | b"offset_hour" | b"offset_minute"
- | b"offset_second" | b"ordinal" | b"second" | b"week_number" | b"year",
- b"padding:zero",
- ) => modifiers.padding = Some(Padding::Zero),
- (
- b"day" | b"hour" | b"minute" | b"month" | b"offset_hour" | b"offset_minute"
- | b"offset_second" | b"ordinal" | b"second" | b"week_number" | b"year",
- b"padding:none",
- ) => modifiers.padding = Some(Padding::None),
- (b"hour", b"repr:24") => modifiers.hour_is_12_hour_clock = Some(false),
- (b"hour", b"repr:12") => modifiers.hour_is_12_hour_clock = Some(true),
- (b"month" | b"period" | b"weekday", b"case_sensitive:true") => {
- modifiers.case_sensitive = Some(true)
- }
- (b"month" | b"period" | b"weekday", b"case_sensitive:false") => {
- modifiers.case_sensitive = Some(false)
- }
- (b"month", b"repr:numerical") => modifiers.month_repr = Some(MonthRepr::Numerical),
- (b"month", b"repr:long") => modifiers.month_repr = Some(MonthRepr::Long),
- (b"month", b"repr:short") => modifiers.month_repr = Some(MonthRepr::Short),
- (b"offset_hour" | b"year", b"sign:automatic") => {
- modifiers.sign_is_mandatory = Some(false);
- }
- (b"offset_hour" | b"year", b"sign:mandatory") => {
- modifiers.sign_is_mandatory = Some(true);
- }
- (b"period", b"case:upper") => modifiers.period_is_uppercase = Some(true),
- (b"period", b"case:lower") => modifiers.period_is_uppercase = Some(false),
- (b"subsecond", b"digits:1") => {
- modifiers.subsecond_digits = Some(SubsecondDigits::One);
- }
- (b"subsecond", b"digits:2") => {
- modifiers.subsecond_digits = Some(SubsecondDigits::Two);
- }
- (b"subsecond", b"digits:3") => {
- modifiers.subsecond_digits = Some(SubsecondDigits::Three);
- }
- (b"subsecond", b"digits:4") => {
- modifiers.subsecond_digits = Some(SubsecondDigits::Four);
- }
- (b"subsecond", b"digits:5") => {
- modifiers.subsecond_digits = Some(SubsecondDigits::Five);
- }
- (b"subsecond", b"digits:6") => {
- modifiers.subsecond_digits = Some(SubsecondDigits::Six);
- }
- (b"subsecond", b"digits:7") => {
- modifiers.subsecond_digits = Some(SubsecondDigits::Seven);
- }
- (b"subsecond", b"digits:8") => {
- modifiers.subsecond_digits = Some(SubsecondDigits::Eight);
- }
- (b"subsecond", b"digits:9") => {
- modifiers.subsecond_digits = Some(SubsecondDigits::Nine);
- }
- (b"subsecond", b"digits:1+") => {
- modifiers.subsecond_digits = Some(SubsecondDigits::OneOrMore);
- }
- (b"weekday", b"repr:short") => modifiers.weekday_repr = Some(WeekdayRepr::Short),
- (b"weekday", b"repr:long") => modifiers.weekday_repr = Some(WeekdayRepr::Long),
- (b"weekday", b"repr:sunday") => modifiers.weekday_repr = Some(WeekdayRepr::Sunday),
- (b"weekday", b"repr:monday") => modifiers.weekday_repr = Some(WeekdayRepr::Monday),
- (b"weekday", b"one_indexed:true") => modifiers.weekday_is_one_indexed = Some(true),
- (b"weekday", b"one_indexed:false") => {
- modifiers.weekday_is_one_indexed = Some(false);
- }
- (b"week_number", b"repr:iso") => {
- modifiers.week_number_repr = Some(WeekNumberRepr::Iso);
- }
- (b"week_number", b"repr:sunday") => {
- modifiers.week_number_repr = Some(WeekNumberRepr::Sunday);
- }
- (b"week_number", b"repr:monday") => {
- modifiers.week_number_repr = Some(WeekNumberRepr::Monday);
- }
- (b"year", b"repr:full") => modifiers.year_repr = Some(YearRepr::Full),
- (b"year", b"repr:last_two") => modifiers.year_repr = Some(YearRepr::LastTwo),
- (b"year", b"base:calendar") => modifiers.year_is_iso_week_based = Some(false),
- (b"year", b"base:iso_week") => modifiers.year_is_iso_week_based = Some(true),
- _ => {
- return Err(InvalidFormatDescription::InvalidModifier {
- value: String::from_utf8_lossy(modifier).into_owned(),
- index: *index,
- });
- }
- }
- }
-
- Ok(modifiers)
- }
-}
diff --git a/vendor/time-macros/src/format_description/parse.rs b/vendor/time-macros/src/format_description/parse.rs
deleted file mode 100644
index 19c7bf608..000000000
--- a/vendor/time-macros/src/format_description/parse.rs
+++ /dev/null
@@ -1,84 +0,0 @@
-use proc_macro::Span;
-
-use crate::format_description::component::{Component, NakedComponent};
-use crate::format_description::error::InvalidFormatDescription;
-use crate::format_description::{helper, modifier, FormatItem};
-use crate::Error;
-
-struct ParsedItem<'a> {
- item: FormatItem<'a>,
- remaining: &'a [u8],
-}
-
-fn parse_component(mut s: &[u8], index: &mut usize) -> Result<Component, InvalidFormatDescription> {
- s = helper::consume_whitespace(s, index);
-
- let component_index = *index;
- let whitespace_loc = s
- .iter()
- .position(u8::is_ascii_whitespace)
- .unwrap_or(s.len());
- *index += whitespace_loc;
- let component_name = &s[..whitespace_loc];
- s = &s[whitespace_loc..];
- s = helper::consume_whitespace(s, index);
-
- Ok(NakedComponent::parse(component_name, component_index)?
- .attach_modifiers(modifier::Modifiers::parse(component_name, s, index)?))
-}
-
-fn parse_literal<'a>(s: &'a [u8], index: &mut usize) -> ParsedItem<'a> {
- let loc = s.iter().position(|&c| c == b'[').unwrap_or(s.len());
- *index += loc;
- ParsedItem {
- item: FormatItem::Literal(&s[..loc]),
- remaining: &s[loc..],
- }
-}
-
-fn parse_item<'a>(
- s: &'a [u8],
- index: &mut usize,
-) -> Result<ParsedItem<'a>, InvalidFormatDescription> {
- if let [b'[', b'[', remaining @ ..] = s {
- *index += 2;
- return Ok(ParsedItem {
- item: FormatItem::Literal(b"["),
- remaining,
- });
- };
-
- if s.starts_with(b"[") {
- if let Some(bracket_index) = s.iter().position(|&c| c == b']') {
- *index += 1; // opening bracket
- let ret_val = ParsedItem {
- item: FormatItem::Component(parse_component(&s[1..bracket_index], index)?),
- remaining: &s[bracket_index + 1..],
- };
- *index += 1; // closing bracket
- Ok(ret_val)
- } else {
- Err(InvalidFormatDescription::UnclosedOpeningBracket { index: *index })
- }
- } else {
- Ok(parse_literal(s, index))
- }
-}
-
-pub(crate) fn parse(mut s: &[u8], span: Span) -> Result<Vec<FormatItem<'_>>, Error> {
- let mut compound = Vec::new();
- let mut loc = 0;
-
- while !s.is_empty() {
- let ParsedItem { item, remaining } =
- parse_item(s, &mut loc).map_err(|error| Error::InvalidFormatDescription {
- error,
- span_start: Some(span),
- span_end: Some(span),
- })?;
- s = remaining;
- compound.push(item);
- }
-
- Ok(compound)
-}
diff --git a/vendor/time-macros/src/helpers/mod.rs b/vendor/time-macros/src/helpers/mod.rs
deleted file mode 100644
index cbf3ba3ed..000000000
--- a/vendor/time-macros/src/helpers/mod.rs
+++ /dev/null
@@ -1,129 +0,0 @@
-#[cfg(any(feature = "formatting", feature = "parsing"))]
-mod string;
-
-use std::iter::Peekable;
-use std::str::FromStr;
-
-#[cfg(any(feature = "formatting", feature = "parsing"))]
-use proc_macro::TokenStream;
-use proc_macro::{token_stream, Span, TokenTree};
-use time_core::util::{days_in_year, is_leap_year};
-
-use crate::Error;
-
-#[cfg(any(feature = "formatting", feature = "parsing"))]
-pub(crate) fn get_string_literal(tokens: TokenStream) -> Result<(Span, Vec<u8>), Error> {
- let mut tokens = tokens.into_iter();
-
- match (tokens.next(), tokens.next()) {
- (Some(TokenTree::Literal(literal)), None) => string::parse(&literal),
- (Some(tree), None) => Err(Error::ExpectedString {
- span_start: Some(tree.span()),
- span_end: Some(tree.span()),
- }),
- (_, Some(tree)) => Err(Error::UnexpectedToken { tree }),
- (None, None) => Err(Error::ExpectedString {
- span_start: None,
- span_end: None,
- }),
- }
-}
-
-pub(crate) fn consume_number<T: FromStr>(
- component_name: &'static str,
- chars: &mut Peekable<token_stream::IntoIter>,
-) -> Result<(Span, T), Error> {
- let (span, digits) = match chars.next() {
- Some(TokenTree::Literal(literal)) => (literal.span(), literal.to_string()),
- Some(tree) => return Err(Error::UnexpectedToken { tree }),
- None => return Err(Error::UnexpectedEndOfInput),
- };
-
- if let Ok(value) = digits.replace('_', "").parse() {
- Ok((span, value))
- } else {
- Err(Error::InvalidComponent {
- name: component_name,
- value: digits,
- span_start: Some(span),
- span_end: Some(span),
- })
- }
-}
-
-pub(crate) fn consume_any_ident(
- idents: &[&str],
- chars: &mut Peekable<token_stream::IntoIter>,
-) -> Result<Span, Error> {
- match chars.peek() {
- Some(TokenTree::Ident(char)) if idents.contains(&char.to_string().as_str()) => {
- let ret = Ok(char.span());
- drop(chars.next());
- ret
- }
- Some(tree) => Err(Error::UnexpectedToken { tree: tree.clone() }),
- None => Err(Error::UnexpectedEndOfInput),
- }
-}
-
-pub(crate) fn consume_punct(
- c: char,
- chars: &mut Peekable<token_stream::IntoIter>,
-) -> Result<Span, Error> {
- match chars.peek() {
- Some(TokenTree::Punct(punct)) if *punct == c => {
- let ret = Ok(punct.span());
- drop(chars.next());
- ret
- }
- Some(tree) => Err(Error::UnexpectedToken { tree: tree.clone() }),
- None => Err(Error::UnexpectedEndOfInput),
- }
-}
-
-fn jan_weekday(year: i32, ordinal: i32) -> u8 {
- macro_rules! div_floor {
- ($a:expr, $b:expr) => {{
- let (_quotient, _remainder) = ($a / $b, $a % $b);
- if (_remainder > 0 && $b < 0) || (_remainder < 0 && $b > 0) {
- _quotient - 1
- } else {
- _quotient
- }
- }};
- }
-
- let adj_year = year - 1;
- ((ordinal + adj_year + div_floor!(adj_year, 4) - div_floor!(adj_year, 100)
- + div_floor!(adj_year, 400)
- + 6)
- .rem_euclid(7)) as _
-}
-
-pub(crate) fn days_in_year_month(year: i32, month: u8) -> u8 {
- [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31][month as usize - 1]
- + (month == 2 && is_leap_year(year)) as u8
-}
-
-pub(crate) fn ywd_to_yo(year: i32, week: u8, iso_weekday_number: u8) -> (i32, u16) {
- let (ordinal, overflow) = (u16::from(week) * 7 + u16::from(iso_weekday_number))
- .overflowing_sub(u16::from(jan_weekday(year, 4)) + 4);
-
- if overflow || ordinal == 0 {
- return (year - 1, (ordinal.wrapping_add(days_in_year(year - 1))));
- }
-
- let days_in_cur_year = days_in_year(year);
- if ordinal > days_in_cur_year {
- (year + 1, ordinal - days_in_cur_year)
- } else {
- (year, ordinal)
- }
-}
-
-pub(crate) fn ymd_to_yo(year: i32, month: u8, day: u8) -> (i32, u16) {
- let ordinal = [0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334][month as usize - 1]
- + (month > 2 && is_leap_year(year)) as u16;
-
- (year, ordinal + u16::from(day))
-}
diff --git a/vendor/time-macros/src/helpers/string.rs b/vendor/time-macros/src/helpers/string.rs
deleted file mode 100644
index fa3780f5e..000000000
--- a/vendor/time-macros/src/helpers/string.rs
+++ /dev/null
@@ -1,188 +0,0 @@
-use std::ops::{Index, RangeFrom};
-
-use proc_macro::Span;
-
-use crate::Error;
-
-pub(crate) fn parse(token: &proc_macro::Literal) -> Result<(Span, Vec<u8>), Error> {
- let span = token.span();
- let repr = token.to_string();
-
- match repr.as_bytes() {
- [b'"', ..] => Ok((span, parse_lit_str_cooked(&repr[1..]))),
- [b'b', b'"', rest @ ..] => Ok((span, parse_lit_byte_str_cooked(rest))),
- [b'r', rest @ ..] | [b'b', b'r', rest @ ..] => Ok((span, parse_lit_str_raw(rest))),
- _ => Err(Error::ExpectedString {
- span_start: Some(span),
- span_end: Some(span),
- }),
- }
-}
-
-fn byte(s: impl AsRef<[u8]>, idx: usize) -> u8 {
- s.as_ref().get(idx).copied().unwrap_or_default()
-}
-
-fn parse_lit_str_cooked(mut s: &str) -> Vec<u8> {
- let mut content = String::new();
- 'outer: loop {
- let ch = match byte(s, 0) {
- b'"' => break,
- b'\\' => {
- let b = byte(s, 1);
- s = &s[2..];
- match b {
- b'x' => {
- let (byte, rest) = backslash_x(s);
- s = rest;
- char::from_u32(u32::from(byte)).expect("byte was just validated")
- }
- b'u' => {
- let (chr, rest) = backslash_u(s);
- s = rest;
- chr
- }
- b'n' => '\n',
- b'r' => '\r',
- b't' => '\t',
- b'\\' => '\\',
- b'0' => '\0',
- b'\'' => '\'',
- b'"' => '"',
- b'\r' | b'\n' => loop {
- let ch = s.chars().next().unwrap_or_default();
- if ch.is_whitespace() {
- s = &s[ch.len_utf8()..];
- } else {
- continue 'outer;
- }
- },
- _ => unreachable!("invalid escape"),
- }
- }
- b'\r' => {
- // bare CR not permitted
- s = &s[2..];
- '\n'
- }
- _ => {
- let ch = s.chars().next().unwrap_or_default();
- s = &s[ch.len_utf8()..];
- ch
- }
- };
- content.push(ch);
- }
-
- content.into_bytes()
-}
-
-fn parse_lit_str_raw(s: &[u8]) -> Vec<u8> {
- let mut pounds = 0;
- while byte(s, pounds) == b'#' {
- pounds += 1;
- }
- let close = s
- .iter()
- .rposition(|&b| b == b'"')
- .expect("had a string without trailing \"");
-
- s[pounds + 1..close].to_owned()
-}
-
-fn parse_lit_byte_str_cooked(mut v: &[u8]) -> Vec<u8> {
- let mut out = Vec::new();
- 'outer: loop {
- let byte = match byte(v, 0) {
- b'"' => break,
- b'\\' => {
- let b = byte(v, 1);
- v = &v[2..];
- match b {
- b'x' => {
- let (byte, rest) = backslash_x(v);
- v = rest;
- byte
- }
- b'n' => b'\n',
- b'r' => b'\r',
- b't' => b'\t',
- b'\\' => b'\\',
- b'0' => b'\0',
- b'\'' => b'\'',
- b'"' => b'"',
- b'\r' | b'\n' => loop {
- let byte = byte(v, 0);
- let ch = char::from_u32(u32::from(byte)).expect("invalid byte");
- if ch.is_whitespace() {
- v = &v[1..];
- } else {
- continue 'outer;
- }
- },
- _ => unreachable!("invalid escape"),
- }
- }
- b'\r' => {
- // bare CR not permitted
- v = &v[2..];
- b'\n'
- }
- b => {
- v = &v[1..];
- b
- }
- };
- out.push(byte);
- }
-
- out
-}
-
-fn backslash_x<S>(s: &S) -> (u8, &S)
-where
- S: Index<RangeFrom<usize>, Output = S> + AsRef<[u8]> + ?Sized,
-{
- let mut ch = 0;
- let b0 = byte(s, 0);
- let b1 = byte(s, 1);
- ch += 0x10 * (b0 - b'0');
- ch += match b1 {
- b'0'..=b'9' => b1 - b'0',
- b'a'..=b'f' => 10 + (b1 - b'a'),
- b'A'..=b'F' => 10 + (b1 - b'A'),
- _ => unreachable!("invalid hex escape"),
- };
- (ch, &s[2..])
-}
-
-fn backslash_u(mut s: &str) -> (char, &str) {
- s = &s[1..];
-
- let mut ch = 0;
- let mut digits = 0;
- loop {
- let b = byte(s, 0);
- let digit = match b {
- b'0'..=b'9' => b - b'0',
- b'a'..=b'f' => 10 + b - b'a',
- b'A'..=b'F' => 10 + b - b'A',
- b'_' if digits > 0 => {
- s = &s[1..];
- continue;
- }
- b'}' if digits != 0 => break,
- _ => unreachable!("invalid unicode escape"),
- };
- ch *= 0x10;
- ch += u32::from(digit);
- digits += 1;
- s = &s[1..];
- }
- s = &s[1..];
-
- (
- char::from_u32(ch).expect("invalid unicode escape passed by compiler"),
- s,
- )
-}
diff --git a/vendor/time-macros/src/lib.rs b/vendor/time-macros/src/lib.rs
deleted file mode 100644
index 1afc313ea..000000000
--- a/vendor/time-macros/src/lib.rs
+++ /dev/null
@@ -1,167 +0,0 @@
-#![deny(
- anonymous_parameters,
- clippy::all,
- const_err,
- illegal_floating_point_literal_pattern,
- late_bound_lifetime_arguments,
- path_statements,
- patterns_in_fns_without_body,
- rust_2018_idioms,
- trivial_casts,
- trivial_numeric_casts,
- unreachable_pub,
- unsafe_code,
- unused_extern_crates
-)]
-#![warn(
- clippy::dbg_macro,
- clippy::decimal_literal_representation,
- clippy::get_unwrap,
- clippy::nursery,
- clippy::print_stdout,
- clippy::todo,
- clippy::unimplemented,
- clippy::unnested_or_patterns,
- clippy::unwrap_used,
- clippy::use_debug,
- single_use_lifetimes,
- unused_qualifications,
- variant_size_differences
-)]
-#![allow(
- clippy::missing_const_for_fn, // useless in proc macro
- clippy::redundant_pub_crate, // suggests bad style
- clippy::option_if_let_else, // suggests terrible code
-)]
-
-#[macro_use]
-mod quote;
-
-mod date;
-mod datetime;
-mod error;
-#[cfg(any(feature = "formatting", feature = "parsing"))]
-mod format_description;
-mod helpers;
-mod offset;
-#[cfg(all(feature = "serde", any(feature = "formatting", feature = "parsing")))]
-mod serde_format_description;
-mod time;
-mod to_tokens;
-
-use proc_macro::TokenStream;
-#[cfg(all(feature = "serde", any(feature = "formatting", feature = "parsing")))]
-use proc_macro::TokenTree;
-
-use self::error::Error;
-
-macro_rules! impl_macros {
- ($($name:ident)*) => {$(
- #[proc_macro]
- pub fn $name(input: TokenStream) -> TokenStream {
- use crate::to_tokens::ToTokenTree;
-
- let mut iter = input.into_iter().peekable();
- match $name::parse(&mut iter) {
- Ok(value) => match iter.peek() {
- Some(tree) => Error::UnexpectedToken { tree: tree.clone() }.to_compile_error(),
- None => TokenStream::from(value.into_token_tree()),
- },
- Err(err) => err.to_compile_error(),
- }
- }
- )*};
-}
-
-impl_macros![date datetime offset time];
-
-#[cfg(any(feature = "formatting", feature = "parsing"))]
-#[proc_macro]
-pub fn format_description(input: TokenStream) -> TokenStream {
- (|| {
- let (span, string) = helpers::get_string_literal(input)?;
- let items = format_description::parse(&string, span)?;
-
- Ok(quote! {{
- const DESCRIPTION: &[::time::format_description::FormatItem<'_>] = &[#S(
- items
- .into_iter()
- .map(|item| quote! { #S(item), })
- .collect::<TokenStream>()
- )];
- DESCRIPTION
- }})
- })()
- .unwrap_or_else(|err: Error| err.to_compile_error())
-}
-
-#[cfg(all(feature = "serde", any(feature = "formatting", feature = "parsing")))]
-#[proc_macro]
-pub fn serde_format_description(input: TokenStream) -> TokenStream {
- (|| {
- let mut tokens = input.into_iter().peekable();
- // First, an identifier (the desired module name)
- let mod_name = match tokens.next() {
- Some(TokenTree::Ident(ident)) => Ok(ident),
- Some(tree) => Err(Error::UnexpectedToken { tree }),
- None => Err(Error::UnexpectedEndOfInput),
- }?;
-
- // Followed by a comma
- helpers::consume_punct(',', &mut tokens)?;
-
- // Then, the type to create serde serializers for (e.g., `OffsetDateTime`).
- let formattable = match tokens.next() {
- Some(tree @ TokenTree::Ident(_)) => Ok(tree),
- Some(tree) => Err(Error::UnexpectedToken { tree }),
- None => Err(Error::UnexpectedEndOfInput),
- }?;
-
- // Another comma
- helpers::consume_punct(',', &mut tokens)?;
-
- // We now have two options. The user can either provide a format description as a string or
- // they can provide a path to a format description. If the latter, all remaining tokens are
- // assumed to be part of the path.
- let (format, raw_format_string) = match tokens.peek() {
- // string literal
- Some(TokenTree::Literal(_)) => {
- let (span, format_string) = helpers::get_string_literal(tokens.collect())?;
- let items = format_description::parse(&format_string, span)?;
- let items: TokenStream =
- items.into_iter().map(|item| quote! { #S(item), }).collect();
- let items = quote! { &[#S(items)] };
-
- (
- items,
- Some(String::from_utf8_lossy(&format_string).into_owned()),
- )
- }
- // path
- Some(_) => (
- quote! {{
- // We can't just do `super::path` because the path could be an absolute path. In
- // that case, we'd be generating `super::::path`, which is invalid. Even if we
- // took that into account, it's not possible to know if it's an external crate,
- // which would just require emitting `path` directly. By taking this approach,
- // we can leave it to the compiler to do the actual resolution.
- mod __path_hack {
- pub(super) use super::super::*;
- pub(super) use #S(tokens.collect::<TokenStream>()) as FORMAT;
- }
- __path_hack::FORMAT
- }},
- None,
- ),
- None => return Err(Error::UnexpectedEndOfInput),
- };
-
- Ok(serde_format_description::build(
- mod_name,
- formattable,
- format,
- raw_format_string,
- ))
- })()
- .unwrap_or_else(|err: Error| err.to_compile_error_standalone())
-}
diff --git a/vendor/time-macros/src/offset.rs b/vendor/time-macros/src/offset.rs
deleted file mode 100644
index c2099073f..000000000
--- a/vendor/time-macros/src/offset.rs
+++ /dev/null
@@ -1,95 +0,0 @@
-use std::iter::Peekable;
-
-use proc_macro::{token_stream, Span, TokenTree};
-
-use crate::helpers::{consume_any_ident, consume_number, consume_punct};
-use crate::to_tokens::ToTokenTree;
-use crate::Error;
-
-pub(crate) struct Offset {
- pub(crate) hours: i8,
- pub(crate) minutes: i8,
- pub(crate) seconds: i8,
-}
-
-pub(crate) fn parse(chars: &mut Peekable<token_stream::IntoIter>) -> Result<Offset, Error> {
- if consume_any_ident(&["utc", "UTC"], chars).is_ok() {
- return Ok(Offset {
- hours: 0,
- minutes: 0,
- seconds: 0,
- });
- }
-
- let sign = if consume_punct('+', chars).is_ok() {
- 1
- } else if consume_punct('-', chars).is_ok() {
- -1
- } else if let Some(tree) = chars.next() {
- return Err(Error::UnexpectedToken { tree });
- } else {
- return Err(Error::MissingComponent {
- name: "sign",
- span_start: None,
- span_end: None,
- });
- };
-
- let (hours_span, hours) = consume_number::<i8>("hour", chars)?;
- let (mut minutes_span, mut minutes) = (Span::mixed_site(), 0);
- let (mut seconds_span, mut seconds) = (Span::mixed_site(), 0);
-
- if consume_punct(':', chars).is_ok() {
- let min = consume_number::<i8>("minute", chars)?;
- minutes_span = min.0;
- minutes = min.1;
-
- if consume_punct(':', chars).is_ok() {
- let sec = consume_number::<i8>("second", chars)?;
- seconds_span = sec.0;
- seconds = sec.1;
- }
- }
-
- if hours >= 24 {
- Err(Error::InvalidComponent {
- name: "hour",
- value: hours.to_string(),
- span_start: Some(hours_span),
- span_end: Some(hours_span),
- })
- } else if minutes >= 60 {
- Err(Error::InvalidComponent {
- name: "minute",
- value: minutes.to_string(),
- span_start: Some(minutes_span),
- span_end: Some(minutes_span),
- })
- } else if seconds >= 60 {
- Err(Error::InvalidComponent {
- name: "second",
- value: seconds.to_string(),
- span_start: Some(seconds_span),
- span_end: Some(seconds_span),
- })
- } else {
- Ok(Offset {
- hours: sign * hours,
- minutes: sign * minutes,
- seconds: sign * seconds,
- })
- }
-}
-
-impl ToTokenTree for Offset {
- fn into_token_tree(self) -> TokenTree {
- quote_group! {{
- const OFFSET: ::time::UtcOffset = ::time::UtcOffset::__from_hms_unchecked(
- #(self.hours),
- #(self.minutes),
- #(self.seconds),
- );
- OFFSET
- }}
- }
-}
diff --git a/vendor/time-macros/src/quote.rs b/vendor/time-macros/src/quote.rs
deleted file mode 100644
index 2fe86cc98..000000000
--- a/vendor/time-macros/src/quote.rs
+++ /dev/null
@@ -1,134 +0,0 @@
-macro_rules! quote {
- () => (::proc_macro::TokenStream::new());
- ($($x:tt)*) => {{
- let mut ts = ::proc_macro::TokenStream::new();
- let ts_mut = &mut ts;
- quote_inner!(ts_mut $($x)*);
- ts
- }};
-}
-
-#[cfg(any(feature = "formatting", feature = "parsing"))]
-macro_rules! quote_append {
- ($ts:ident $($x:tt)*) => {{
- quote_inner!($ts $($x)*);
- }};
-}
-
-macro_rules! quote_group {
- ({ $($x:tt)* }) => {
- ::proc_macro::TokenTree::Group(::proc_macro::Group::new(
- ::proc_macro::Delimiter::Brace,
- quote!($($x)*)
- ))
- };
-}
-
-macro_rules! sym {
- ($ts:ident $x:tt $y:tt) => {
- $ts.extend([
- ::proc_macro::TokenTree::from(::proc_macro::Punct::new(
- $x,
- ::proc_macro::Spacing::Joint,
- )),
- ::proc_macro::TokenTree::from(::proc_macro::Punct::new(
- $y,
- ::proc_macro::Spacing::Alone,
- )),
- ]);
- };
- ($ts:ident $x:tt) => {
- $ts.extend([::proc_macro::TokenTree::from(::proc_macro::Punct::new(
- $x,
- ::proc_macro::Spacing::Alone,
- ))]);
- };
-}
-
-macro_rules! quote_inner {
- // Base case
- ($ts:ident) => {};
-
- // Single or double symbols
- ($ts:ident :: $($tail:tt)*) => { sym!($ts ':' ':'); quote_inner!($ts $($tail)*); };
- ($ts:ident .. $($tail:tt)*) => { sym!($ts '.' '.'); quote_inner!($ts $($tail)*); };
- ($ts:ident : $($tail:tt)*) => { sym!($ts ':'); quote_inner!($ts $($tail)*); };
- ($ts:ident = $($tail:tt)*) => { sym!($ts '='); quote_inner!($ts $($tail)*); };
- ($ts:ident ; $($tail:tt)*) => { sym!($ts ';'); quote_inner!($ts $($tail)*); };
- ($ts:ident , $($tail:tt)*) => { sym!($ts ','); quote_inner!($ts $($tail)*); };
- ($ts:ident . $($tail:tt)*) => { sym!($ts '.'); quote_inner!($ts $($tail)*); };
- ($ts:ident & $($tail:tt)*) => { sym!($ts '&'); quote_inner!($ts $($tail)*); };
- ($ts:ident << $($tail:tt)*) => { sym!($ts '<' '<'); quote_inner!($ts $($tail)*); };
- ($ts:ident < $($tail:tt)*) => { sym!($ts '<'); quote_inner!($ts $($tail)*); };
- ($ts:ident >> $($tail:tt)*) => { sym!($ts '>' '>'); quote_inner!($ts $($tail)*); };
- ($ts:ident > $($tail:tt)*) => { sym!($ts '>'); quote_inner!($ts $($tail)*); };
- ($ts:ident -> $($tail:tt)*) => { sym!($ts '-' '>'); quote_inner!($ts $($tail)*); };
- ($ts:ident ? $($tail:tt)*) => { sym!($ts '?'); quote_inner!($ts $($tail)*); };
- ($ts:ident ! $($tail:tt)*) => { sym!($ts '!'); quote_inner!($ts $($tail)*); };
- ($ts:ident | $($tail:tt)*) => { sym!($ts '|'); quote_inner!($ts $($tail)*); };
- ($ts:ident * $($tail:tt)*) => { sym!($ts '*'); quote_inner!($ts $($tail)*); };
-
- // Identifier
- ($ts:ident $i:ident $($tail:tt)*) => {
- $ts.extend([::proc_macro::TokenTree::from(::proc_macro::Ident::new(
- &stringify!($i),
- ::proc_macro::Span::mixed_site(),
- ))]);
- quote_inner!($ts $($tail)*);
- };
-
- // Literal
- ($ts:ident $l:literal $($tail:tt)*) => {
- $ts.extend([::proc_macro::TokenTree::from(::proc_macro::Literal::string(&$l))]);
- quote_inner!($ts $($tail)*);
- };
-
- // Lifetime
- ($ts:ident $l:lifetime $($tail:tt)*) => {
- $ts.extend([
- ::proc_macro::TokenTree::from(
- ::proc_macro::Punct::new('\'', ::proc_macro::Spacing::Joint)
- ),
- ::proc_macro::TokenTree::from(::proc_macro::Ident::new(
- stringify!($l).trim_start_matches(|c| c == '\''),
- ::proc_macro::Span::mixed_site(),
- )),
- ]);
- quote_inner!($ts $($tail)*);
- };
-
- // Groups
- ($ts:ident ($($inner:tt)*) $($tail:tt)*) => {
- $ts.extend([::proc_macro::TokenTree::Group(::proc_macro::Group::new(
- ::proc_macro::Delimiter::Parenthesis,
- quote!($($inner)*)
- ))]);
- quote_inner!($ts $($tail)*);
- };
- ($ts:ident [$($inner:tt)*] $($tail:tt)*) => {
- $ts.extend([::proc_macro::TokenTree::Group(::proc_macro::Group::new(
- ::proc_macro::Delimiter::Bracket,
- quote!($($inner)*)
- ))]);
- quote_inner!($ts $($tail)*);
- };
- ($ts:ident {$($inner:tt)*} $($tail:tt)*) => {
- $ts.extend([::proc_macro::TokenTree::Group(::proc_macro::Group::new(
- ::proc_macro::Delimiter::Brace,
- quote!($($inner)*)
- ))]);
- quote_inner!($ts $($tail)*);
- };
-
- // Interpolated values
- // TokenTree by default
- ($ts:ident #($e:expr) $($tail:tt)*) => {
- $ts.extend([$crate::to_tokens::ToTokenTree::into_token_tree($e)]);
- quote_inner!($ts $($tail)*);
- };
- // Allow a TokenStream by request. It's more expensive, so avoid if possible.
- ($ts:ident #S($e:expr) $($tail:tt)*) => {
- $crate::to_tokens::ToTokenStream::append_to($e, $ts);
- quote_inner!($ts $($tail)*);
- };
-}
diff --git a/vendor/time-macros/src/serde_format_description.rs b/vendor/time-macros/src/serde_format_description.rs
deleted file mode 100644
index c09a4e9e2..000000000
--- a/vendor/time-macros/src/serde_format_description.rs
+++ /dev/null
@@ -1,163 +0,0 @@
-use proc_macro::{Ident, TokenStream, TokenTree};
-
-pub(crate) fn build(
- mod_name: Ident,
- ty: TokenTree,
- format: TokenStream,
- raw_format_string: Option<String>,
-) -> TokenStream {
- let ty_s = &*ty.to_string();
-
- let format_description_display = raw_format_string.unwrap_or_else(|| format.to_string());
-
- let visitor = if cfg!(feature = "parsing") {
- quote! {
- struct Visitor;
- struct OptionVisitor;
-
- impl<'a> ::serde::de::Visitor<'a> for Visitor {
- type Value = __TimeSerdeType;
-
- fn expecting(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
- write!(
- f,
- concat!(
- "a(n) `",
- #(ty_s),
- "` in the format \"{}\"",
- ),
- #(format_description_display.as_str())
- )
- }
-
- fn visit_str<E: ::serde::de::Error>(
- self,
- value: &str
- ) -> Result<__TimeSerdeType, E> {
- __TimeSerdeType::parse(value, &DESCRIPTION).map_err(E::custom)
- }
- }
-
- impl<'a> ::serde::de::Visitor<'a> for OptionVisitor {
- type Value = Option<__TimeSerdeType>;
-
- fn expecting(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
- write!(
- f,
- concat!(
- "an `Option<",
- #(ty_s),
- ">` in the format \"{}\"",
- ),
- #(format_description_display.as_str())
- )
- }
-
- fn visit_some<D: ::serde::de::Deserializer<'a>>(
- self,
- deserializer: D
- ) -> Result<Option<__TimeSerdeType>, D::Error> {
- deserializer
- .deserialize_any(Visitor)
- .map(Some)
- }
-
- fn visit_none<E: ::serde::de::Error>(
- self
- ) -> Result<Option<__TimeSerdeType>, E> {
- Ok(None)
- }
- }
- }
- } else {
- quote!()
- };
-
- let serialize_primary = if cfg!(feature = "formatting") {
- quote! {
- pub fn serialize<S: ::serde::Serializer>(
- datetime: &__TimeSerdeType,
- serializer: S,
- ) -> Result<S::Ok, S::Error> {
- use ::serde::Serialize;
- datetime
- .format(&DESCRIPTION)
- .map_err(::time::error::Format::into_invalid_serde_value::<S>)?
- .serialize(serializer)
- }
- }
- } else {
- quote!()
- };
-
- let deserialize_primary = if cfg!(feature = "parsing") {
- quote! {
- pub fn deserialize<'a, D: ::serde::Deserializer<'a>>(
- deserializer: D
- ) -> Result<__TimeSerdeType, D::Error> {
- use ::serde::Deserialize;
- deserializer.deserialize_any(Visitor)
- }
- }
- } else {
- quote!()
- };
-
- let serialize_option = if cfg!(feature = "formatting") {
- quote! {
- pub fn serialize<S: ::serde::Serializer>(
- option: &Option<__TimeSerdeType>,
- serializer: S,
- ) -> Result<S::Ok, S::Error> {
- use ::serde::Serialize;
- option.map(|datetime| datetime.format(&DESCRIPTION))
- .transpose()
- .map_err(::time::error::Format::into_invalid_serde_value::<S>)?
- .serialize(serializer)
- }
- }
- } else {
- quote!()
- };
-
- let deserialize_option = if cfg!(feature = "parsing") {
- quote! {
- pub fn deserialize<'a, D: ::serde::Deserializer<'a>>(
- deserializer: D
- ) -> Result<Option<__TimeSerdeType>, D::Error> {
- use ::serde::Deserialize;
- deserializer.deserialize_option(OptionVisitor)
- }
- }
- } else {
- quote!()
- };
-
- let deserialize_option_imports = if cfg!(feature = "parsing") {
- quote! {
- use super::{OptionVisitor, Visitor};
- }
- } else {
- quote!()
- };
-
- quote! {
- mod #(mod_name) {
- use ::time::#(ty) as __TimeSerdeType;
-
- const DESCRIPTION: &[::time::format_description::FormatItem<'_>] = #S(format);
-
- #S(visitor)
- #S(serialize_primary)
- #S(deserialize_primary)
-
- pub(super) mod option {
- use super::{DESCRIPTION, __TimeSerdeType};
- #S(deserialize_option_imports)
-
- #S(serialize_option)
- #S(deserialize_option)
- }
- }
- }
-}
diff --git a/vendor/time-macros/src/time.rs b/vendor/time-macros/src/time.rs
deleted file mode 100644
index 719e2051f..000000000
--- a/vendor/time-macros/src/time.rs
+++ /dev/null
@@ -1,118 +0,0 @@
-use std::iter::Peekable;
-
-use proc_macro::{token_stream, Span, TokenTree};
-
-use crate::helpers::{consume_any_ident, consume_number, consume_punct};
-use crate::to_tokens::ToTokenTree;
-use crate::Error;
-
-enum Period {
- Am,
- Pm,
- _24,
-}
-
-pub(crate) struct Time {
- pub(crate) hour: u8,
- pub(crate) minute: u8,
- pub(crate) second: u8,
- pub(crate) nanosecond: u32,
-}
-
-pub(crate) fn parse(chars: &mut Peekable<token_stream::IntoIter>) -> Result<Time, Error> {
- fn consume_period(chars: &mut Peekable<token_stream::IntoIter>) -> (Option<Span>, Period) {
- if let Ok(span) = consume_any_ident(&["am", "AM"], chars) {
- (Some(span), Period::Am)
- } else if let Ok(span) = consume_any_ident(&["pm", "PM"], chars) {
- (Some(span), Period::Pm)
- } else {
- (None, Period::_24)
- }
- }
-
- let (hour_span, hour) = consume_number("hour", chars)?;
-
- let ((minute_span, minute), (second_span, second), (period_span, period)) =
- match consume_period(chars) {
- // Nothing but the 12-hour clock hour and AM/PM
- (period_span @ Some(_), period) => (
- (Span::mixed_site(), 0),
- (Span::mixed_site(), 0.),
- (period_span, period),
- ),
- (None, _) => {
- consume_punct(':', chars)?;
- let (minute_span, minute) = consume_number::<u8>("minute", chars)?;
- let (second_span, second): (_, f64) = if consume_punct(':', chars).is_ok() {
- consume_number("second", chars)?
- } else {
- (Span::mixed_site(), 0.)
- };
- let (period_span, period) = consume_period(chars);
- (
- (minute_span, minute),
- (second_span, second),
- (period_span, period),
- )
- }
- };
-
- let hour = match (hour, period) {
- (0, Period::Am | Period::Pm) => {
- return Err(Error::InvalidComponent {
- name: "hour",
- value: hour.to_string(),
- span_start: Some(hour_span),
- span_end: Some(period_span.unwrap_or(hour_span)),
- });
- }
- (12, Period::Am) => 0,
- (12, Period::Pm) => 12,
- (hour, Period::Am | Period::_24) => hour,
- (hour, Period::Pm) => hour + 12,
- };
-
- if hour >= 24 {
- Err(Error::InvalidComponent {
- name: "hour",
- value: hour.to_string(),
- span_start: Some(hour_span),
- span_end: Some(period_span.unwrap_or(hour_span)),
- })
- } else if minute >= 60 {
- Err(Error::InvalidComponent {
- name: "minute",
- value: minute.to_string(),
- span_start: Some(minute_span),
- span_end: Some(minute_span),
- })
- } else if second >= 60. {
- Err(Error::InvalidComponent {
- name: "second",
- value: second.to_string(),
- span_start: Some(second_span),
- span_end: Some(second_span),
- })
- } else {
- Ok(Time {
- hour,
- minute,
- second: second.trunc() as _,
- nanosecond: (second.fract() * 1_000_000_000.).round() as _,
- })
- }
-}
-
-impl ToTokenTree for Time {
- fn into_token_tree(self) -> TokenTree {
- quote_group! {{
- const TIME: ::time::Time = ::time::Time::__from_hms_nanos_unchecked(
- #(self.hour),
- #(self.minute),
- #(self.second),
- #(self.nanosecond),
- );
- TIME
- }}
- }
-}
diff --git a/vendor/time-macros/src/to_tokens.rs b/vendor/time-macros/src/to_tokens.rs
deleted file mode 100644
index 3a293925c..000000000
--- a/vendor/time-macros/src/to_tokens.rs
+++ /dev/null
@@ -1,68 +0,0 @@
-use proc_macro::{Group, Ident, Literal, Punct, Span, TokenStream, TokenTree};
-
-pub(crate) trait ToTokenStream: Sized {
- fn append_to(self, ts: &mut TokenStream);
-}
-
-pub(crate) trait ToTokenTree: Sized {
- fn into_token_tree(self) -> TokenTree;
-}
-
-impl<T: ToTokenTree> ToTokenStream for T {
- fn append_to(self, ts: &mut TokenStream) {
- ts.extend([self.into_token_tree()])
- }
-}
-
-impl ToTokenTree for bool {
- fn into_token_tree(self) -> TokenTree {
- let lit = if self { "true" } else { "false" };
- TokenTree::Ident(Ident::new(lit, Span::mixed_site()))
- }
-}
-
-impl ToTokenStream for TokenStream {
- fn append_to(self, ts: &mut TokenStream) {
- ts.extend(self)
- }
-}
-
-impl ToTokenTree for TokenTree {
- fn into_token_tree(self) -> TokenTree {
- self
- }
-}
-
-impl ToTokenTree for &str {
- fn into_token_tree(self) -> TokenTree {
- TokenTree::Literal(Literal::string(self))
- }
-}
-
-macro_rules! impl_for_tree_types {
- ($($type:ty)*) => {$(
- impl ToTokenTree for $type {
- fn into_token_tree(self) -> TokenTree {
- TokenTree::from(self)
- }
- }
- )*};
-}
-impl_for_tree_types![Ident Literal Group Punct];
-
-macro_rules! impl_for_int {
- ($($type:ty => $method:ident)*) => {$(
- impl ToTokenTree for $type {
- fn into_token_tree(self) -> TokenTree {
- TokenTree::from(Literal::$method(self))
- }
- }
- )*};
-}
-impl_for_int! {
- i8 => i8_unsuffixed
- u8 => u8_unsuffixed
- u16 => u16_unsuffixed
- i32 => i32_unsuffixed
- u32 => u32_unsuffixed
-}
diff --git a/vendor/tinystr/.cargo-checksum.json b/vendor/tinystr/.cargo-checksum.json
index 36b7cede5..86027edd3 100644
--- a/vendor/tinystr/.cargo-checksum.json
+++ b/vendor/tinystr/.cargo-checksum.json
@@ -1 +1 @@
-{"files":{"Cargo.toml":"279fef44ae26d0bda43cc629cbe22795d696b36635fcb7ca484e74b9d72b9eb4","LICENSE":"4ad7541d66a407234e2c84902124cef325c29f3e966353efdb800bedb8b8da21","README.md":"ce7d4b009ab4878b4b647fa5c01037b4d3e8bf72e44942dbf6cf1ef217d10b4d","benches/common/mod.rs":"7a31f89cb68cec2574287636ac22fe3fc86a66688b8b1e99700a5da692bd485e","benches/construct.rs":"0e0e7c1459dd3efea0c734a999318078b53e18c3389c74a1ff5a226cd3d05cca","benches/overview.rs":"296d19b32a2d52e449140771d89f9c099d19177eb84e1395c942469d51c4c3f8","benches/read.rs":"cbf349393a50eb90e7ba53906f98a689d585242292f867a37acf6842263af4d9","benches/serde.rs":"5c88866d08c07088b82dbd5472e6276c632d11e064417f5d8f2025a5ade867f0","src/ascii.rs":"ca84603237893d515cf4d3cc5bf61470a81c499956b8bdf51239433c0d49785e","src/asciibyte.rs":"fa29de7403c0424c52c2f30bb47002b9abf4bd08b302c411ffe679d3decfb8de","src/databake.rs":"9f29e30e6deec989822cbdf01f5165e098fa544cf7e49ccea3f5de827648fc1e","src/error.rs":"859d03faa3e98d979e0d6b5d232810d42b58f9c6ef69403d442545327053265e","src/int_ops.rs":"c2be314d19dd41cf18fb3589901d7e58ee32fe3f764fb6a66b08a1e005336406","src/lib.rs":"41db27f31650945dbf41b72a21d42fa4de0722b6f0717a45a3569c3dd4f1e148","src/macros.rs":"3fe76e258b0db2896284bcf4f50a4ac35b7efc542649b4c9f13c6e71c5957ae4","src/serde.rs":"0bd6bbe2ee8195aea68dd235d59b94faa3419aaeb8939e3220dd64bd888873f5","src/ule.rs":"139543634949a95405bc49862840b0794db089abed6efe66533858376cae180f","tests/serde.rs":"cf8cee82f731928375888d1b5e7e5e50368d3e16ce372fced230c9b1ee2a7451"},"package":"f8aeafdfd935e4a7fe16a91ab711fa52d54df84f9c8f7ca5837a9d1d902ef4c2"} \ No newline at end of file
+{"files":{"Cargo.toml":"b28bb188b7c3b68f9d9a710921a42f337bd2e07eb7588d983b20724f64d6a8c8","LICENSE":"4ad7541d66a407234e2c84902124cef325c29f3e966353efdb800bedb8b8da21","README.md":"8e79e986c696d6010a578b2872ee4144d86e26d30a409167ff2cf2af551ef231","benches/common/mod.rs":"7a31f89cb68cec2574287636ac22fe3fc86a66688b8b1e99700a5da692bd485e","benches/construct.rs":"0e0e7c1459dd3efea0c734a999318078b53e18c3389c74a1ff5a226cd3d05cca","benches/overview.rs":"296d19b32a2d52e449140771d89f9c099d19177eb84e1395c942469d51c4c3f8","benches/read.rs":"cbf349393a50eb90e7ba53906f98a689d585242292f867a37acf6842263af4d9","benches/serde.rs":"5c88866d08c07088b82dbd5472e6276c632d11e064417f5d8f2025a5ade867f0","src/ascii.rs":"403408b47d813110e840d4db688145c37a17fbcbff173038d9e3743aa712b321","src/asciibyte.rs":"fa29de7403c0424c52c2f30bb47002b9abf4bd08b302c411ffe679d3decfb8de","src/databake.rs":"9f29e30e6deec989822cbdf01f5165e098fa544cf7e49ccea3f5de827648fc1e","src/error.rs":"e0cbc912258d6e56aad148404d7cc3213d89736fa9ebe56c41f6cb0df7b2dd63","src/int_ops.rs":"c2be314d19dd41cf18fb3589901d7e58ee32fe3f764fb6a66b08a1e005336406","src/lib.rs":"7ddbd83bcb9091495de3c4a7eb7ecc25313c54991be8b463d67a7c2e97c076b6","src/macros.rs":"3fe76e258b0db2896284bcf4f50a4ac35b7efc542649b4c9f13c6e71c5957ae4","src/serde.rs":"0bd6bbe2ee8195aea68dd235d59b94faa3419aaeb8939e3220dd64bd888873f5","src/ule.rs":"139543634949a95405bc49862840b0794db089abed6efe66533858376cae180f","tests/serde.rs":"cf8cee82f731928375888d1b5e7e5e50368d3e16ce372fced230c9b1ee2a7451"},"package":"7ac3f5b6856e931e15e07b478e98c8045239829a65f9156d4fa7e7788197a5ef"} \ No newline at end of file
diff --git a/vendor/tinystr/Cargo.toml b/vendor/tinystr/Cargo.toml
index 64682f74e..284ce6d2d 100644
--- a/vendor/tinystr/Cargo.toml
+++ b/vendor/tinystr/Cargo.toml
@@ -12,7 +12,7 @@
[package]
edition = "2021"
name = "tinystr"
-version = "0.7.0"
+version = "0.7.1"
authors = ["The ICU4X Project Developers"]
include = [
"src/**/*",
@@ -36,9 +36,15 @@ license = "Unicode-DFS-2016"
repository = "https://github.com/unicode-org/icu4x"
resolver = "2"
+[package.metadata.workspaces]
+independent = true
+
[package.metadata.docs.rs]
all-features = true
+[package.metadata.cargo-all-features]
+denylist = ["bench"]
+
[[test]]
name = "serde"
required-features = ["serde"]
@@ -66,7 +72,7 @@ required-features = [
]
[dependencies.databake]
-version = "0.1"
+version = "0.1.3"
optional = true
[dependencies.displaydoc]
@@ -80,7 +86,7 @@ optional = true
default-features = false
[dependencies.zerovec]
-version = "0.9"
+version = "0.9.2"
optional = true
[dev-dependencies.bincode]
@@ -111,4 +117,4 @@ package = "tinystr"
alloc = []
bench = []
default = ["alloc"]
-zerovec = ["dep:zerovec"]
+std = []
diff --git a/vendor/tinystr/README.md b/vendor/tinystr/README.md
index 96b3f955f..5f9a8142b 100644
--- a/vendor/tinystr/README.md
+++ b/vendor/tinystr/README.md
@@ -19,8 +19,8 @@ assert_eq!(s1, "tEsT");
assert_eq!(s1.to_ascii_uppercase(), "TEST");
assert_eq!(s1.to_ascii_lowercase(), "test");
assert_eq!(s1.to_ascii_titlecase(), "Test");
-assert_eq!(s1.is_ascii_alphanumeric(), true);
-assert_eq!(s1.is_ascii_numeric(), false);
+assert!(s1.is_ascii_alphanumeric());
+assert!(!s1.is_ascii_numeric());
let s2 = TinyAsciiStr::<8>::try_from_raw(*b"New York")
.expect("Failed to parse.");
@@ -29,7 +29,7 @@ assert_eq!(s2, "New York");
assert_eq!(s2.to_ascii_uppercase(), "NEW YORK");
assert_eq!(s2.to_ascii_lowercase(), "new york");
assert_eq!(s2.to_ascii_titlecase(), "New york");
-assert_eq!(s2.is_ascii_alphanumeric(), false);
+assert!(!s2.is_ascii_alphanumeric());
```
## Details
diff --git a/vendor/tinystr/src/ascii.rs b/vendor/tinystr/src/ascii.rs
index 0be1125e3..f39f39b73 100644
--- a/vendor/tinystr/src/ascii.rs
+++ b/vendor/tinystr/src/ascii.rs
@@ -138,11 +138,6 @@ impl<const N: usize> TinyAsciiStr<N> {
#[inline]
#[must_use]
pub const fn as_bytes(&self) -> &[u8] {
- /// core::slice::from_raw_parts(a, b) = core::mem::transmute((a, b)) hack
- /// ```compile_fail
- /// const unsafe fn canary() { core::slice::from_raw_parts(0 as *const u8, 0); }
- /// ```
- const _: () = ();
// Safe because `self.bytes.as_slice()` pointer-casts to `&[u8]`,
// and changing the length of that slice to self.len() < N is safe.
unsafe { core::mem::transmute((self.bytes.as_slice().as_ptr(), self.len())) }
@@ -668,7 +663,7 @@ mod test {
use rand::seq::SliceRandom;
use rand::SeedableRng;
- const STRINGS: &[&str] = &[
+ const STRINGS: [&str; 26] = [
"Latn",
"laTn",
"windows",
@@ -723,8 +718,8 @@ mod test {
T: core::fmt::Debug + core::cmp::PartialEq,
{
for s in STRINGS
- .iter()
- .map(|s| s.to_string())
+ .into_iter()
+ .map(str::to_owned)
.chain(gen_strings(100, &[3, 4, 5, 8, 12]))
{
let t = match TinyAsciiStr::<N>::from_str(&s) {
@@ -930,7 +925,7 @@ mod test {
.map(|c| c.to_ascii_lowercase())
.collect::<String>()
},
- |t: TinyAsciiStr<N>| TinyAsciiStr::to_ascii_lowercase(t).to_string(),
+ |t: TinyAsciiStr<N>| TinyAsciiStr::to_ascii_lowercase(t).as_str().to_owned(),
)
}
check::<2>();
@@ -954,7 +949,7 @@ mod test {
unsafe { r.as_bytes_mut()[0].make_ascii_uppercase() };
r
},
- |t: TinyAsciiStr<N>| TinyAsciiStr::to_ascii_titlecase(t).to_string(),
+ |t: TinyAsciiStr<N>| TinyAsciiStr::to_ascii_titlecase(t).as_str().to_owned(),
)
}
check::<2>();
@@ -974,7 +969,7 @@ mod test {
.map(|c| c.to_ascii_uppercase())
.collect::<String>()
},
- |t: TinyAsciiStr<N>| TinyAsciiStr::to_ascii_uppercase(t).to_string(),
+ |t: TinyAsciiStr<N>| TinyAsciiStr::to_ascii_uppercase(t).as_str().to_owned(),
)
}
check::<2>();
diff --git a/vendor/tinystr/src/error.rs b/vendor/tinystr/src/error.rs
index 03901431c..7910f8b48 100644
--- a/vendor/tinystr/src/error.rs
+++ b/vendor/tinystr/src/error.rs
@@ -4,6 +4,9 @@
use displaydoc::Display;
+#[cfg(feature = "std")]
+impl std::error::Error for TinyStrError {}
+
#[derive(Display, Debug, PartialEq, Eq)]
#[non_exhaustive]
pub enum TinyStrError {
diff --git a/vendor/tinystr/src/lib.rs b/vendor/tinystr/src/lib.rs
index 96018b8b2..7745da0e5 100644
--- a/vendor/tinystr/src/lib.rs
+++ b/vendor/tinystr/src/lib.rs
@@ -21,8 +21,8 @@
//! assert_eq!(s1.to_ascii_uppercase(), "TEST");
//! assert_eq!(s1.to_ascii_lowercase(), "test");
//! assert_eq!(s1.to_ascii_titlecase(), "Test");
-//! assert_eq!(s1.is_ascii_alphanumeric(), true);
-//! assert_eq!(s1.is_ascii_numeric(), false);
+//! assert!(s1.is_ascii_alphanumeric());
+//! assert!(!s1.is_ascii_numeric());
//!
//! let s2 = TinyAsciiStr::<8>::try_from_raw(*b"New York")
//! .expect("Failed to parse.");
@@ -31,7 +31,7 @@
//! assert_eq!(s2.to_ascii_uppercase(), "NEW YORK");
//! assert_eq!(s2.to_ascii_lowercase(), "new york");
//! assert_eq!(s2.to_ascii_titlecase(), "New york");
-//! assert_eq!(s2.is_ascii_alphanumeric(), false);
+//! assert!(!s2.is_ascii_alphanumeric());
//! ```
//!
//! # Details
@@ -52,7 +52,7 @@
//! [`ICU4X`]: ../icu/index.html
// https://github.com/unicode-org/icu4x/blob/main/docs/process/boilerplate.md#library-annotations
-#![cfg_attr(not(test), no_std)]
+#![cfg_attr(not(any(test, feature = "std")), no_std)]
#![cfg_attr(
not(test),
deny(
diff --git a/vendor/toml/.cargo-checksum.json b/vendor/toml-0.5.9/.cargo-checksum.json
index fc3af5a18..fc3af5a18 100644
--- a/vendor/toml/.cargo-checksum.json
+++ b/vendor/toml-0.5.9/.cargo-checksum.json
diff --git a/vendor/toml/Cargo.lock b/vendor/toml-0.5.9/Cargo.lock
index 1f4de004a..1f4de004a 100644
--- a/vendor/toml/Cargo.lock
+++ b/vendor/toml-0.5.9/Cargo.lock
diff --git a/vendor/toml/Cargo.toml b/vendor/toml-0.5.9/Cargo.toml
index 2e30a900a..2e30a900a 100644
--- a/vendor/toml/Cargo.toml
+++ b/vendor/toml-0.5.9/Cargo.toml
diff --git a/vendor/toml-0.5.9/LICENSE-APACHE b/vendor/toml-0.5.9/LICENSE-APACHE
new file mode 100644
index 000000000..16fe87b06
--- /dev/null
+++ b/vendor/toml-0.5.9/LICENSE-APACHE
@@ -0,0 +1,201 @@
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+END OF TERMS AND CONDITIONS
+
+APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+Copyright [yyyy] [name of copyright owner]
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
diff --git a/vendor/toml/LICENSE-MIT b/vendor/toml-0.5.9/LICENSE-MIT
index 39e0ed660..39e0ed660 100644
--- a/vendor/toml/LICENSE-MIT
+++ b/vendor/toml-0.5.9/LICENSE-MIT
diff --git a/vendor/toml/README.md b/vendor/toml-0.5.9/README.md
index 21dd1088a..21dd1088a 100644
--- a/vendor/toml/README.md
+++ b/vendor/toml-0.5.9/README.md
diff --git a/vendor/toml/examples/decode.rs b/vendor/toml-0.5.9/examples/decode.rs
index 256069b35..256069b35 100644
--- a/vendor/toml/examples/decode.rs
+++ b/vendor/toml-0.5.9/examples/decode.rs
diff --git a/vendor/toml/examples/enum_external.rs b/vendor/toml-0.5.9/examples/enum_external.rs
index 7de061f61..7de061f61 100644
--- a/vendor/toml/examples/enum_external.rs
+++ b/vendor/toml-0.5.9/examples/enum_external.rs
diff --git a/vendor/toml/examples/toml2json.rs b/vendor/toml-0.5.9/examples/toml2json.rs
index 1b90c9fde..1b90c9fde 100644
--- a/vendor/toml/examples/toml2json.rs
+++ b/vendor/toml-0.5.9/examples/toml2json.rs
diff --git a/vendor/toml/src/datetime.rs b/vendor/toml-0.5.9/src/datetime.rs
index a68b07568..a68b07568 100644
--- a/vendor/toml/src/datetime.rs
+++ b/vendor/toml-0.5.9/src/datetime.rs
diff --git a/vendor/toml/src/de.rs b/vendor/toml-0.5.9/src/de.rs
index 40d88ae7d..40d88ae7d 100644
--- a/vendor/toml/src/de.rs
+++ b/vendor/toml-0.5.9/src/de.rs
diff --git a/vendor/toml/src/lib.rs b/vendor/toml-0.5.9/src/lib.rs
index 00421b118..00421b118 100644
--- a/vendor/toml/src/lib.rs
+++ b/vendor/toml-0.5.9/src/lib.rs
diff --git a/vendor/toml/src/macros.rs b/vendor/toml-0.5.9/src/macros.rs
index 0731afefd..0731afefd 100644
--- a/vendor/toml/src/macros.rs
+++ b/vendor/toml-0.5.9/src/macros.rs
diff --git a/vendor/toml/src/map.rs b/vendor/toml-0.5.9/src/map.rs
index d130a1d54..d130a1d54 100644
--- a/vendor/toml/src/map.rs
+++ b/vendor/toml-0.5.9/src/map.rs
diff --git a/vendor/toml/src/ser.rs b/vendor/toml-0.5.9/src/ser.rs
index 90c5acf61..90c5acf61 100644
--- a/vendor/toml/src/ser.rs
+++ b/vendor/toml-0.5.9/src/ser.rs
diff --git a/vendor/toml/src/spanned.rs b/vendor/toml-0.5.9/src/spanned.rs
index 9ee56ae6d..9ee56ae6d 100644
--- a/vendor/toml/src/spanned.rs
+++ b/vendor/toml-0.5.9/src/spanned.rs
diff --git a/vendor/toml/src/tokens.rs b/vendor/toml-0.5.9/src/tokens.rs
index c2422828e..c2422828e 100644
--- a/vendor/toml/src/tokens.rs
+++ b/vendor/toml-0.5.9/src/tokens.rs
diff --git a/vendor/toml/src/value.rs b/vendor/toml-0.5.9/src/value.rs
index 1a1756d10..1a1756d10 100644
--- a/vendor/toml/src/value.rs
+++ b/vendor/toml-0.5.9/src/value.rs
diff --git a/vendor/toml/tests/enum_external_deserialize.rs b/vendor/toml-0.5.9/tests/enum_external_deserialize.rs
index 6d45b4848..6d45b4848 100644
--- a/vendor/toml/tests/enum_external_deserialize.rs
+++ b/vendor/toml-0.5.9/tests/enum_external_deserialize.rs
diff --git a/vendor/tracing-subscriber-0.3.3/.cargo-checksum.json b/vendor/tracing-subscriber-0.3.3/.cargo-checksum.json
deleted file mode 100644
index 3fd14355e..000000000
--- a/vendor/tracing-subscriber-0.3.3/.cargo-checksum.json
+++ /dev/null
@@ -1 +0,0 @@
-{"files":{"CHANGELOG.md":"fd7a732ca8d5997cf09a6ffbde0dda0667873031884aa3549d6044971dc00a66","Cargo.toml":"4908f04be83f94bc75fbcf4244fa57b8a52c984928a3320550b692c1038d5448","LICENSE":"898b1ae9821e98daf8964c8d6c7f61641f5f5aa78ad500020771c0939ee0dea1","README.md":"803714740b5ad75ac31a0f9dafd10e0d4d62f7c27c2c0e182d2076a313b0649b","benches/enter.rs":"4a94a04e2abd07950ef2f0b646f4dcdf4ff00abf6396edb5a53c8b41b7691b1a","benches/filter.rs":"6374005ffa47fa19880bb95e3e37406f40ea72a02c5136f4d5eb4c663d452b18","benches/filter_log.rs":"612716bdf9a188093e84d014a4847f18157f148f7d64e54150cd5c91ac709a8a","benches/fmt.rs":"5a0ff37967ffef3a221eebb78855d031e2e883a8a67528c8e794cc6f16cbee8a","benches/support/mod.rs":"72bef51154da9c9b3d81300195c1929a818858fa4b4fc2aa07b49ca586f4cd39","src/field/debug.rs":"4ab50198a0b042d92fefa77b5cac0aef7ba6936149fa555f4b6e2036dcd7f2d7","src/field/delimited.rs":"e6b2dcbf9cb1e9b5e862b462f91190adaf8e14f9c2c5d2048ad651f49cfa2007","src/field/display.rs":"9c06a52919dbe9bfd4cf7eec39293240c9facebe052a2fecc2f21184beb5195f","src/field/mod.rs":"35e3dd4ad7b49c99a24e80c6a40a00b3189a114488793657d6d733a90d2e10f6","src/filter/directive.rs":"7ecf87b17afbddadbc385764c2d9c1fda4b020a08d75f741f8e34c7dc475bd74","src/filter/env/directive.rs":"628f9f566ccee924d43d79b287c569abfc32c2fb74e078958aed6cb8285cfb4f","src/filter/env/field.rs":"9f2ceaedf2e2ecefaff863347ef8dfa85cd5f64a0fd09a0f77f64f412c9bb548","src/filter/env/mod.rs":"7f864a5ef0c008c7fe9a21d0a94bb87dd72746e628ff3e68c18b0fd173763918","src/filter/filter_fn.rs":"0debbc4a4b4d2a57b2a06905017ac908bf34b0a64aaf961535fbf6f4d5a700a9","src/filter/layer_filters.rs":"16ff19fed003b913de4f85a03b31864d71ee73c7ce86b07c80da07fe633f682e","src/filter/level.rs":"cc449757aac47caaf19dd5ba4d74c8efbcd7531fcd6c13da0c5f6fdda12cc9ca","src/filter/mod.rs":"8ebfd0dc92415ff27ec552f20919e598842a87186f13f120449053a96e1e3307","src/filter/targets.rs":"5cec882366d7f12de0a88f7daaac8499785ce9e3832619f251876a02ae19a6bf","src/fmt/fmt_layer.rs":"486264d810ab6b28428bd48e00774fc822762fc9f991332a2d94a42b3168f2e6","src/fmt/format/json.rs":"1a38c049e1bf99efaf7db1f1fd26d3a5bb1e768fc1524c95816708e5d39fca35","src/fmt/format/mod.rs":"ff92f7910bed4f3c0c2ce798333d273d6b5b5fc09cc78031f52d13e043986227","src/fmt/format/pretty.rs":"eecf278b15cc60b35c3f6aa5d05452401c7a4a29195357e92318d684fcfe3072","src/fmt/mod.rs":"270ffa0a9e6543a602247fccef276a3012daa558181f24cd9032292edbc8dc2c","src/fmt/time/datetime.rs":"778d4604d800e46b940087394e7b72750738b554e02aea523fa9820ab0768c08","src/fmt/time/mod.rs":"304c9383e5cfc0c42d79f47a10323ed5a98585e018b127924b0925ec067f0739","src/fmt/time/time_crate.rs":"bacec2c8bb31175b85f2fb3ae40155a08b2aab7a04adaf4c88679147dc651c58","src/fmt/writer.rs":"1d7a4e2dddddff1bfd1344f2cecdb6b2b69b015c9869d95987d26e177dffa793","src/layer/context.rs":"2478693e2faffdf2e519b6d37e1c3aa3dd75088185accc2b68ffa8612bf73195","src/layer/layered.rs":"ba918a9b944f2c083cbb75d6d7f99f90083aa0a29cf3f4f1dd78aa034e09ade6","src/layer/mod.rs":"e1804cfe91051020cac63fb1067d196552ebb844b6c6d1d2279b97dbec1c64df","src/layer/tests.rs":"3e974d627c4bc4269cfa10c82c890e596c9d46af8e6bc03c6c117bde1237e948","src/lib.rs":"cb362279b3c6d23645cda6d768707576f460e275d332d5350a036437cd5404e0","src/macros.rs":"e184bffc6b5999c48e365ad08343dca764a5fb711b789beb26bd1d5f1d767726","src/prelude.rs":"088635def33be9a4c4b6ed934dc22540c555e27d62f7625a43aa9c0e525ca467","src/registry/extensions.rs":"7333aefd69c767212a7924c57283442430edccb17092c91e02a7d13b2d312b11","src/registry/mod.rs":"4f0108e75e0f6e239b8eb69fcad052f25e3b887e412e951e0cbec02cf13f05d5","src/registry/sharded.rs":"972bdd94f43a33ef1f2ebf96ea69ebe4c1d4b0215e69315a3b525783c2025696","src/registry/stack.rs":"9ef333d6a8a28a064e80ff1e376dbb07bc597009010ec332b2dc3ab435d737c2","src/reload.rs":"41fa9a1a28fef626e302a80a68d665492e73ef6d1a2a3c2a7aac5d6c9a0bb496","src/sync.rs":"7f78f3de5b618a999be0e61f936a233975e7769f1ebb55a0e48c3d199e9c45e3","src/util.rs":"55b4e9d63112f9d5a12a287273a9b1212741058384332d3edc024168cacfd627","tests/cached_layer_filters_dont_break_other_layers.rs":"b2084542a014abeff821b30b2b8c21e32bfdcffae53ce5335fb588f557fa4244","tests/duplicate_spans.rs":"48f596bbfabcc6618244afddcf3c3f2e915b9d79284f17bdd0e0616ad29929be","tests/field_filter.rs":"c44d88ab711164a2b1b3a09377284b469f79ddf4651416515a035782c7c64b79","tests/filter.rs":"a43d23e867af779031b6245047092aca57ee26980a8f3faa19036542bcd37f06","tests/filter_log.rs":"e0cd9d394dbfeeb80570a7686bc7f588c5489657980436810711ed8852f86169","tests/fmt_max_level_hint.rs":"d4c6d6f976ae41ab8052fa610a7337ad7150802cbd5634cb30fc45c1f215cfcd","tests/hinted_layer_filters_dont_break_other_layers.rs":"d5ba9cfb6784cf59f007e673ad549dc722d109f6b3d4a69f6aa11b25ca10b469","tests/layer_filter_interests_are_cached.rs":"d036d1c4bc3754e94ebfdda9c841f4858ccec40aba0720f3fbf26c817bfe5a83","tests/layer_filters/boxed.rs":"04db459721a26d6502a2b3fbe42154c5a451021a9374a18c017d10971f44e0c0","tests/layer_filters/downcast_raw.rs":"9b90ead571543cbe14e89b4fe637360d9baf3069f6f656ed3bdf65e7318648f1","tests/layer_filters/filter_scopes.rs":"02611bc58d0d8a67a127eca8cab1b2d9a9901bd2c8a8daad41adf6089b28aee0","tests/layer_filters/main.rs":"0316d611c740e234b78ed9a9dae392fe80472c1e8b004a007ad2dd87d068c67b","tests/layer_filters/targets.rs":"138e3f9ddd68571d94c5aff9d54ee2fbc5f44724c6ee42477a411740ccb79ee6","tests/layer_filters/trees.rs":"4df7b5cf12da44a9255c56e5b80e2b0cf84820230ba916f324c67bc3ee4e4605","tests/multiple_layer_filter_interests_cached.rs":"1ea195f03e58d715228ec1b604f85bda2fc82812d05b2f6370d5edd34a035f32","tests/registry_max_level_hint.rs":"ba386d32b8d13832d7009163241c3d0723488c0393d85647eb9368776251e4fc","tests/registry_with_subscriber.rs":"13b92ed68d9013aefefbc4c73e695c690630e4460634206d214db4c19abb7c0f","tests/reload.rs":"4566386b1b26e6609f5a4bf0e6bef1c2245a591d12417cee189b26dfa14f7f95","tests/same_len_filters.rs":"50c8f5fa1494773410a9f52a56b303534a01a023b186cf2f3131e5e7706eb156","tests/support.rs":"75559505af8018012739d24b3c8743dd079b4d3a8ae28f08b4586a961720aa7b","tests/unhinted_layer_filters_dont_break_other_layers.rs":"519cfef4977e511af938546d4208c645a28248c8ed8666daf180f0ad32f0a261","tests/utils.rs":"2b04ce2d8b56a9062a025900104853e081eae8e3f113f990a915d5f9dea6577b"},"package":"245da694cc7fc4729f3f418b304cb57789f1bed2a78c575407ab8a23f53cb4d3"} \ No newline at end of file
diff --git a/vendor/tracing-subscriber-0.3.3/src/fmt/format/pretty.rs b/vendor/tracing-subscriber-0.3.3/src/fmt/format/pretty.rs
deleted file mode 100644
index 3e47e2d93..000000000
--- a/vendor/tracing-subscriber-0.3.3/src/fmt/format/pretty.rs
+++ /dev/null
@@ -1,415 +0,0 @@
-use super::*;
-use crate::{
- field::{VisitFmt, VisitOutput},
- fmt::fmt_layer::{FmtContext, FormattedFields},
- registry::LookupSpan,
-};
-
-use std::fmt;
-use tracing_core::{
- field::{self, Field},
- Event, Level, Subscriber,
-};
-
-#[cfg(feature = "tracing-log")]
-use tracing_log::NormalizeEvent;
-
-use ansi_term::{Colour, Style};
-
-/// An excessively pretty, human-readable event formatter.
-#[derive(Debug, Clone, Eq, PartialEq)]
-pub struct Pretty {
- display_location: bool,
-}
-
-/// The [visitor] produced by [`Pretty`]'s [`MakeVisitor`] implementation.
-///
-/// [visitor]: field::Visit
-/// [`MakeVisitor`]: crate::field::MakeVisitor
-#[derive(Debug)]
-pub struct PrettyVisitor<'a> {
- writer: Writer<'a>,
- is_empty: bool,
- style: Style,
- result: fmt::Result,
-}
-
-/// An excessively pretty, human-readable [`MakeVisitor`] implementation.
-///
-/// [`MakeVisitor`]: crate::field::MakeVisitor
-#[derive(Debug)]
-pub struct PrettyFields {
- /// A value to override the provided `Writer`'s ANSI formatting
- /// configuration.
- ///
- /// If this is `Some`, we override the `Writer`'s ANSI setting. This is
- /// necessary in order to continue supporting the deprecated
- /// `PrettyFields::with_ansi` method. If it is `None`, we don't override the
- /// ANSI formatting configuration (because the deprecated method was not
- /// called).
- // TODO: when `PrettyFields::with_ansi` is removed, we can get rid
- // of this entirely.
- ansi: Option<bool>,
-}
-
-// === impl Pretty ===
-
-impl Default for Pretty {
- fn default() -> Self {
- Self {
- display_location: true,
- }
- }
-}
-
-impl Pretty {
- fn style_for(level: &Level) -> Style {
- match *level {
- Level::TRACE => Style::new().fg(Colour::Purple),
- Level::DEBUG => Style::new().fg(Colour::Blue),
- Level::INFO => Style::new().fg(Colour::Green),
- Level::WARN => Style::new().fg(Colour::Yellow),
- Level::ERROR => Style::new().fg(Colour::Red),
- }
- }
-
- /// Sets whether the event's source code location is displayed.
- ///
- /// This defaults to `true`.
- pub fn with_source_location(self, display_location: bool) -> Self {
- Self {
- display_location,
- ..self
- }
- }
-}
-
-impl<T> Format<Pretty, T> {
- /// Sets whether or not the source code location from which an event
- /// originated is displayed.
- ///
- /// This defaults to `true`.
- pub fn with_source_location(mut self, display_location: bool) -> Self {
- self.format = self.format.with_source_location(display_location);
- self
- }
-}
-
-impl<C, N, T> FormatEvent<C, N> for Format<Pretty, T>
-where
- C: Subscriber + for<'a> LookupSpan<'a>,
- N: for<'a> FormatFields<'a> + 'static,
- T: FormatTime,
-{
- fn format_event(
- &self,
- ctx: &FmtContext<'_, C, N>,
- mut writer: Writer<'_>,
- event: &Event<'_>,
- ) -> fmt::Result {
- #[cfg(feature = "tracing-log")]
- let normalized_meta = event.normalized_metadata();
- #[cfg(feature = "tracing-log")]
- let meta = normalized_meta.as_ref().unwrap_or_else(|| event.metadata());
- #[cfg(not(feature = "tracing-log"))]
- let meta = event.metadata();
- write!(&mut writer, " ")?;
-
- // if the `Format` struct *also* has an ANSI color configuration,
- // override the writer...the API for configuring ANSI color codes on the
- // `Format` struct is deprecated, but we still need to honor those
- // configurations.
- if let Some(ansi) = self.ansi {
- writer = writer.with_ansi(ansi);
- }
-
- self.format_timestamp(&mut writer)?;
-
- let style = if self.display_level && writer.has_ansi_escapes() {
- Pretty::style_for(meta.level())
- } else {
- Style::new()
- };
-
- if self.display_level {
- write!(
- writer,
- "{} ",
- super::FmtLevel::new(meta.level(), writer.has_ansi_escapes())
- )?;
- }
-
- if self.display_target {
- let target_style = if writer.has_ansi_escapes() {
- style.bold()
- } else {
- style
- };
- write!(
- writer,
- "{}{}{}: ",
- target_style.prefix(),
- meta.target(),
- target_style.infix(style)
- )?;
- }
- let mut v = PrettyVisitor::new(writer.by_ref(), true).with_style(style);
- event.record(&mut v);
- v.finish()?;
- writer.write_char('\n')?;
-
- let dimmed = if writer.has_ansi_escapes() {
- Style::new().dimmed().italic()
- } else {
- Style::new()
- };
- let thread = self.display_thread_name || self.display_thread_id;
- if let (true, Some(file), Some(line)) =
- (self.format.display_location, meta.file(), meta.line())
- {
- write!(
- writer,
- " {} {}:{}{}",
- dimmed.paint("at"),
- file,
- line,
- dimmed.paint(if thread { " " } else { "\n" })
- )?;
- } else if thread {
- write!(writer, " ")?;
- }
-
- if thread {
- write!(writer, "{} ", dimmed.paint("on"))?;
- let thread = std::thread::current();
- if self.display_thread_name {
- if let Some(name) = thread.name() {
- write!(writer, "{}", name)?;
- if self.display_thread_id {
- write!(writer, " ({:?})", thread.id())?;
- }
- } else if !self.display_thread_id {
- write!(writer, " {:?}", thread.id())?;
- }
- } else if self.display_thread_id {
- write!(writer, " {:?}", thread.id())?;
- }
- writer.write_char('\n')?;
- }
-
- let bold = writer.bold();
- let span = event
- .parent()
- .and_then(|id| ctx.span(id))
- .or_else(|| ctx.lookup_current());
-
- let scope = span.into_iter().flat_map(|span| span.scope());
-
- for span in scope {
- let meta = span.metadata();
- if self.display_target {
- write!(
- writer,
- " {} {}::{}",
- dimmed.paint("in"),
- meta.target(),
- bold.paint(meta.name()),
- )?;
- } else {
- write!(
- writer,
- " {} {}",
- dimmed.paint("in"),
- bold.paint(meta.name()),
- )?;
- }
-
- let ext = span.extensions();
- let fields = &ext
- .get::<FormattedFields<N>>()
- .expect("Unable to find FormattedFields in extensions; this is a bug");
- if !fields.is_empty() {
- write!(writer, " {} {}", dimmed.paint("with"), fields)?;
- }
- writer.write_char('\n')?;
- }
-
- writer.write_char('\n')
- }
-}
-
-impl<'writer> FormatFields<'writer> for Pretty {
- fn format_fields<R: RecordFields>(&self, writer: Writer<'writer>, fields: R) -> fmt::Result {
- let mut v = PrettyVisitor::new(writer, false);
- fields.record(&mut v);
- v.finish()
- }
-
- fn add_fields(
- &self,
- current: &'writer mut FormattedFields<Self>,
- fields: &span::Record<'_>,
- ) -> fmt::Result {
- let empty = current.is_empty();
- let writer = current.as_writer();
- let mut v = PrettyVisitor::new(writer, empty);
- fields.record(&mut v);
- v.finish()
- }
-}
-
-// === impl PrettyFields ===
-
-impl Default for PrettyFields {
- fn default() -> Self {
- Self::new()
- }
-}
-
-impl PrettyFields {
- /// Returns a new default [`PrettyFields`] implementation.
- pub fn new() -> Self {
- // By default, don't override the `Writer`'s ANSI colors
- // configuration. We'll only do this if the user calls the
- // deprecated `PrettyFields::with_ansi` method.
- Self { ansi: None }
- }
-
- /// Enable ANSI encoding for formatted fields.
- #[deprecated(
- since = "0.3.3",
- note = "Use `fmt::Subscriber::with_ansi` or `fmt::Layer::with_ansi` instead."
- )]
- pub fn with_ansi(self, ansi: bool) -> Self {
- Self {
- ansi: Some(ansi),
- ..self
- }
- }
-}
-
-impl<'a> MakeVisitor<Writer<'a>> for PrettyFields {
- type Visitor = PrettyVisitor<'a>;
-
- #[inline]
- fn make_visitor(&self, mut target: Writer<'a>) -> Self::Visitor {
- if let Some(ansi) = self.ansi {
- target = target.with_ansi(ansi);
- }
- PrettyVisitor::new(target, true)
- }
-}
-
-// === impl PrettyVisitor ===
-
-impl<'a> PrettyVisitor<'a> {
- /// Returns a new default visitor that formats to the provided `writer`.
- ///
- /// # Arguments
- /// - `writer`: the writer to format to.
- /// - `is_empty`: whether or not any fields have been previously written to
- /// that writer.
- pub fn new(writer: Writer<'a>, is_empty: bool) -> Self {
- Self {
- writer,
- is_empty,
- style: Style::default(),
- result: Ok(()),
- }
- }
-
- pub(crate) fn with_style(self, style: Style) -> Self {
- Self { style, ..self }
- }
-
- fn write_padded(&mut self, value: &impl fmt::Debug) {
- let padding = if self.is_empty {
- self.is_empty = false;
- ""
- } else {
- ", "
- };
- self.result = write!(self.writer, "{}{:?}", padding, value);
- }
-
- fn bold(&self) -> Style {
- if self.writer.has_ansi_escapes() {
- self.style.bold()
- } else {
- Style::new()
- }
- }
-}
-
-impl<'a> field::Visit for PrettyVisitor<'a> {
- fn record_str(&mut self, field: &Field, value: &str) {
- if self.result.is_err() {
- return;
- }
-
- if field.name() == "message" {
- self.record_debug(field, &format_args!("{}", value))
- } else {
- self.record_debug(field, &value)
- }
- }
-
- fn record_error(&mut self, field: &Field, value: &(dyn std::error::Error + 'static)) {
- if let Some(source) = value.source() {
- let bold = self.bold();
- self.record_debug(
- field,
- &format_args!(
- "{}, {}{}.sources{}: {}",
- value,
- bold.prefix(),
- field,
- bold.infix(self.style),
- ErrorSourceList(source),
- ),
- )
- } else {
- self.record_debug(field, &format_args!("{}", value))
- }
- }
-
- fn record_debug(&mut self, field: &Field, value: &dyn fmt::Debug) {
- if self.result.is_err() {
- return;
- }
- let bold = self.bold();
- match field.name() {
- "message" => self.write_padded(&format_args!("{}{:?}", self.style.prefix(), value,)),
- // Skip fields that are actually log metadata that have already been handled
- #[cfg(feature = "tracing-log")]
- name if name.starts_with("log.") => self.result = Ok(()),
- name if name.starts_with("r#") => self.write_padded(&format_args!(
- "{}{}{}: {:?}",
- bold.prefix(),
- &name[2..],
- bold.infix(self.style),
- value
- )),
- name => self.write_padded(&format_args!(
- "{}{}{}: {:?}",
- bold.prefix(),
- name,
- bold.infix(self.style),
- value
- )),
- };
- }
-}
-
-impl<'a> VisitOutput<fmt::Result> for PrettyVisitor<'a> {
- fn finish(mut self) -> fmt::Result {
- write!(&mut self.writer, "{}", self.style.suffix())?;
- self.result
- }
-}
-
-impl<'a> VisitFmt for PrettyVisitor<'a> {
- fn writer(&mut self) -> &mut dyn fmt::Write {
- &mut self.writer
- }
-}
diff --git a/vendor/tracing-subscriber-0.3.3/src/fmt/time/time_crate.rs b/vendor/tracing-subscriber-0.3.3/src/fmt/time/time_crate.rs
deleted file mode 100644
index 64d274365..000000000
--- a/vendor/tracing-subscriber-0.3.3/src/fmt/time/time_crate.rs
+++ /dev/null
@@ -1,276 +0,0 @@
-use crate::fmt::{format::Writer, time::FormatTime, writer::WriteAdaptor};
-use std::fmt;
-use time::{format_description::well_known, formatting::Formattable, OffsetDateTime};
-
-/// Formats the current [local time] using a [formatter] from the [`time` crate].
-///
-/// To format the current [UTC time] instead, use the [`UtcTime`] type.
-///
-/// [local time]: https://docs.rs/time/0.3/time/struct.OffsetDateTime.html#method.now_local
-/// [UTC time]: https://docs.rs/time/0.3/time/struct.OffsetDateTime.html#method.now_utc
-/// [formatter]: https://docs.rs/time/0.3/time/formatting/trait.Formattable.html
-/// [`time` crate]: https://docs.rs/time/0.3/time/
-#[derive(Clone, Debug)]
-#[cfg_attr(docsrs, doc(cfg(all(feature = "time", feature = "local-time"))))]
-#[cfg(feature = "local-time")]
-pub struct LocalTime<F> {
- format: F,
-}
-
-/// Formats the current [UTC time] using a [formatter] from the [`time` crate].
-///
-/// To format the current [local time] instead, use the [`LocalTime`] type.
-///
-/// [local time]: https://docs.rs/time/0.3/time/struct.OffsetDateTime.html#method.now_local
-/// [UTC time]: https://docs.rs/time/0.3/time/struct.OffsetDateTime.html#method.now_utc
-/// [formatter]: https://docs.rs/time/0.3/time/formatting/trait.Formattable.html
-/// [`time` crate]: https://docs.rs/time/0.3/time/
-#[cfg_attr(docsrs, doc(cfg(feature = "time")))]
-#[derive(Clone, Debug)]
-pub struct UtcTime<F> {
- format: F,
-}
-
-// === impl LocalTime ===
-
-#[cfg(feature = "local-time")]
-impl LocalTime<well_known::Rfc3339> {
- /// Returns a formatter that formats the current [local time] in the
- /// [RFC 3339] format (a subset of the [ISO 8601] timestamp format).
- ///
- /// # Examples
- ///
- /// ```
- /// use tracing_subscriber::fmt::{self, time};
- ///
- /// let collector = tracing_subscriber::fmt()
- /// .with_timer(time::LocalTime::rfc_3339());
- /// # drop(collector);
- /// ```
- ///
- /// [local time]: https://docs.rs/time/0.3/time/struct.OffsetDateTime.html#method.now_local
- /// [RFC 3339]: https://datatracker.ietf.org/doc/html/rfc3339
- /// [ISO 8601]: https://en.wikipedia.org/wiki/ISO_8601
- pub fn rfc_3339() -> Self {
- Self::new(well_known::Rfc3339)
- }
-}
-
-#[cfg(feature = "local-time")]
-impl<F: Formattable> LocalTime<F> {
- /// Returns a formatter that formats the current [local time] using the
- /// [`time` crate] with the provided provided format. The format may be any
- /// type that implements the [`Formattable`] trait.
- ///
- /// Typically, the format will be a format description string, or one of the
- /// `time` crate's [well-known formats].
- ///
- /// If the format description is statically known, then the
- /// [`format_description!`] macro should be used. This is identical to the
- /// [`time::format_description::parse`] method, but runs at compile-time,
- /// throwing an error if the format description is invalid. If the desired format
- /// is not known statically (e.g., a user is providing a format string), then the
- /// [`time::format_description::parse`] method should be used. Note that this
- /// method is fallible.
- ///
- /// See the [`time` book] for details on the format description syntax.
- ///
- /// # Examples
- ///
- /// Using the [`format_description!`] macro:
- ///
- /// ```
- /// use tracing_subscriber::fmt::{self, time::LocalTime};
- /// use time::macros::format_description;
- ///
- /// let timer = LocalTime::new(format_description!("[hour]:[minute]:[second]"));
- /// let collector = tracing_subscriber::fmt()
- /// .with_timer(timer);
- /// # drop(collector);
- /// ```
- ///
- /// Using [`time::format_description::parse`]:
- ///
- /// ```
- /// use tracing_subscriber::fmt::{self, time::LocalTime};
- ///
- /// let time_format = time::format_description::parse("[hour]:[minute]:[second]")
- /// .expect("format string should be valid!");
- /// let timer = LocalTime::new(time_format);
- /// let collector = tracing_subscriber::fmt()
- /// .with_timer(timer);
- /// # drop(collector);
- /// ```
- ///
- /// Using the [`format_description!`] macro requires enabling the `time`
- /// crate's "macros" feature flag.
- ///
- /// Using a [well-known format][well-known formats] (this is equivalent to
- /// [`LocalTime::rfc_3339`]):
- ///
- /// ```
- /// use tracing_subscriber::fmt::{self, time::LocalTime};
- ///
- /// let timer = LocalTime::new(time::format_description::well_known::Rfc3339);
- /// let collector = tracing_subscriber::fmt()
- /// .with_timer(timer);
- /// # drop(collector);
- /// ```
- ///
- /// [local time]: https://docs.rs/time/latest/time/struct.OffsetDateTime.html#method.now_local
- /// [`time` crate]: https://docs.rs/time/0.3/time/
- /// [`Formattable`]: https://docs.rs/time/0.3/time/formatting/trait.Formattable.html
- /// [well-known formats]: https://docs.rs/time/0.3/time/format_description/well_known/index.html
- /// [`format_description!`]: https://docs.rs/time/0.3/time/macros/macro.format_description.html
- /// [`time::format_description::parse`]: https://docs.rs/time/0.3/time/format_description/fn.parse.html
- /// [`time` book]: https://time-rs.github.io/book/api/format-description.html
- pub fn new(format: F) -> Self {
- Self { format }
- }
-}
-
-#[cfg(feature = "local-time")]
-impl<F> FormatTime for LocalTime<F>
-where
- F: Formattable,
-{
- fn format_time(&self, w: &mut Writer<'_>) -> fmt::Result {
- let now = OffsetDateTime::now_local().map_err(|_| fmt::Error)?;
- format_datetime(now, w, &self.format)
- }
-}
-
-#[cfg(feature = "local-time")]
-impl<F> Default for LocalTime<F>
-where
- F: Formattable + Default,
-{
- fn default() -> Self {
- Self::new(F::default())
- }
-}
-
-// === impl UtcTime ===
-
-impl UtcTime<well_known::Rfc3339> {
- /// Returns a formatter that formats the current [UTC time] in the
- /// [RFC 3339] format, which is a subset of the [ISO 8601] timestamp format.
- ///
- /// # Examples
- ///
- /// ```
- /// use tracing_subscriber::fmt::{self, time};
- ///
- /// let collector = tracing_subscriber::fmt()
- /// .with_timer(time::UtcTime::rfc_3339());
- /// # drop(collector);
- /// ```
- ///
- /// [local time]: https://docs.rs/time/0.3/time/struct.OffsetDateTime.html#method.now_utc
- /// [RFC 3339]: https://datatracker.ietf.org/doc/html/rfc3339
- /// [ISO 8601]: https://en.wikipedia.org/wiki/ISO_8601
- pub fn rfc_3339() -> Self {
- Self::new(well_known::Rfc3339)
- }
-}
-
-impl<F: Formattable> UtcTime<F> {
- /// Returns a formatter that formats the current [UTC time] using the
- /// [`time` crate], with the provided provided format. The format may be any
- /// type that implements the [`Formattable`] trait.
- ///
- /// Typically, the format will be a format description string, or one of the
- /// `time` crate's [well-known formats].
- ///
- /// If the format description is statically known, then the
- /// [`format_description!`] macro should be used. This is identical to the
- /// [`time::format_description::parse`] method, but runs at compile-time,
- /// failing an error if the format description is invalid. If the desired format
- /// is not known statically (e.g., a user is providing a format string), then the
- /// [`time::format_description::parse`] method should be used. Note that this
- /// method is fallible.
- ///
- /// See the [`time` book] for details on the format description syntax.
- ///
- /// # Examples
- ///
- /// Using the [`format_description!`] macro:
- ///
- /// ```
- /// use tracing_subscriber::fmt::{self, time::UtcTime};
- /// use time::macros::format_description;
- ///
- /// let timer = UtcTime::new(format_description!("[hour]:[minute]:[second]"));
- /// let collector = tracing_subscriber::fmt()
- /// .with_timer(timer);
- /// # drop(collector);
- /// ```
- ///
- /// Using the [`format_description!`] macro requires enabling the `time`
- /// crate's "macros" feature flag.
- ///
- /// Using [`time::format_description::parse`]:
- ///
- /// ```
- /// use tracing_subscriber::fmt::{self, time::UtcTime};
- ///
- /// let time_format = time::format_description::parse("[hour]:[minute]:[second]")
- /// .expect("format string should be valid!");
- /// let timer = UtcTime::new(time_format);
- /// let collector = tracing_subscriber::fmt()
- /// .with_timer(timer);
- /// # drop(collector);
- /// ```
- ///
- /// Using a [well-known format][well-known formats] (this is equivalent to
- /// [`UtcTime::rfc_3339`]):
- ///
- /// ```
- /// use tracing_subscriber::fmt::{self, time::UtcTime};
- ///
- /// let timer = UtcTime::new(time::format_description::well_known::Rfc3339);
- /// let collector = tracing_subscriber::fmt()
- /// .with_timer(timer);
- /// # drop(collector);
- /// ```
- ///
- /// [UTC time]: https://docs.rs/time/latest/time/struct.OffsetDateTime.html#method.now_utc
- /// [`time` crate]: https://docs.rs/time/0.3/time/
- /// [`Formattable`]: https://docs.rs/time/0.3/time/formatting/trait.Formattable.html
- /// [well-known formats]: https://docs.rs/time/0.3/time/format_description/well_known/index.html
- /// [`format_description!`]: https://docs.rs/time/0.3/time/macros/macro.format_description.html
- /// [`time::format_description::parse`]: https://docs.rs/time/0.3/time/format_description/fn.parse.html
- /// [`time` book]: https://time-rs.github.io/book/api/format-description.html
- pub fn new(format: F) -> Self {
- Self { format }
- }
-}
-
-impl<F> FormatTime for UtcTime<F>
-where
- F: Formattable,
-{
- fn format_time(&self, w: &mut Writer<'_>) -> fmt::Result {
- format_datetime(OffsetDateTime::now_utc(), w, &self.format)
- }
-}
-
-impl<F> Default for UtcTime<F>
-where
- F: Formattable + Default,
-{
- fn default() -> Self {
- Self::new(F::default())
- }
-}
-
-fn format_datetime(
- now: OffsetDateTime,
- into: &mut Writer<'_>,
- fmt: &impl Formattable,
-) -> fmt::Result {
- let mut into = WriteAdaptor::new(into);
- now.format_into(&mut into, fmt)
- .map_err(|_| fmt::Error)
- .map(|_| ())
-}
diff --git a/vendor/tracing-subscriber-0.3.3/src/reload.rs b/vendor/tracing-subscriber-0.3.3/src/reload.rs
deleted file mode 100644
index b8ec67dfa..000000000
--- a/vendor/tracing-subscriber-0.3.3/src/reload.rs
+++ /dev/null
@@ -1,237 +0,0 @@
-//! Wrapper for a `Layer` to allow it to be dynamically reloaded.
-//!
-//! This module provides a [`Layer` type] which wraps another type implementing
-//! the [`Layer` trait], allowing the wrapped type to be replaced with another
-//! instance of that type at runtime.
-//!
-//! This can be used in cases where a subset of `Subscriber` functionality
-//! should be dynamically reconfigured, such as when filtering directives may
-//! change at runtime. Note that this layer introduces a (relatively small)
-//! amount of overhead, and should thus only be used as needed.
-//!
-//! [`Layer` type]: struct.Layer.html
-//! [`Layer` trait]: ../layer/trait.Layer.html
-use crate::layer;
-use crate::sync::RwLock;
-
-use std::{
- error, fmt,
- marker::PhantomData,
- sync::{Arc, Weak},
-};
-use tracing_core::{
- callsite, span,
- subscriber::{Interest, Subscriber},
- Event, Metadata,
-};
-
-/// Wraps a `Layer`, allowing it to be reloaded dynamically at runtime.
-#[derive(Debug)]
-pub struct Layer<L, S> {
- // TODO(eliza): this once used a `crossbeam_util::ShardedRwLock`. We may
- // eventually wish to replace it with a sharded lock implementation on top
- // of our internal `RwLock` wrapper type. If possible, we should profile
- // this first to determine if it's necessary.
- inner: Arc<RwLock<L>>,
- _s: PhantomData<fn(S)>,
-}
-
-/// Allows reloading the state of an associated `Layer`.
-#[derive(Debug)]
-pub struct Handle<L, S> {
- inner: Weak<RwLock<L>>,
- _s: PhantomData<fn(S)>,
-}
-
-/// Indicates that an error occurred when reloading a layer.
-#[derive(Debug)]
-pub struct Error {
- kind: ErrorKind,
-}
-
-#[derive(Debug)]
-enum ErrorKind {
- SubscriberGone,
- Poisoned,
-}
-
-// ===== impl Layer =====
-
-impl<L, S> crate::Layer<S> for Layer<L, S>
-where
- L: crate::Layer<S> + 'static,
- S: Subscriber,
-{
- fn on_layer(&mut self, subscriber: &mut S) {
- try_lock!(self.inner.write(), else return).on_layer(subscriber);
- }
-
- #[inline]
- fn register_callsite(&self, metadata: &'static Metadata<'static>) -> Interest {
- try_lock!(self.inner.read(), else return Interest::sometimes()).register_callsite(metadata)
- }
-
- #[inline]
- fn enabled(&self, metadata: &Metadata<'_>, ctx: layer::Context<'_, S>) -> bool {
- try_lock!(self.inner.read(), else return false).enabled(metadata, ctx)
- }
-
- #[inline]
- fn on_new_span(&self, attrs: &span::Attributes<'_>, id: &span::Id, ctx: layer::Context<'_, S>) {
- try_lock!(self.inner.read()).on_new_span(attrs, id, ctx)
- }
-
- #[inline]
- fn on_record(&self, span: &span::Id, values: &span::Record<'_>, ctx: layer::Context<'_, S>) {
- try_lock!(self.inner.read()).on_record(span, values, ctx)
- }
-
- #[inline]
- fn on_follows_from(&self, span: &span::Id, follows: &span::Id, ctx: layer::Context<'_, S>) {
- try_lock!(self.inner.read()).on_follows_from(span, follows, ctx)
- }
-
- #[inline]
- fn on_event(&self, event: &Event<'_>, ctx: layer::Context<'_, S>) {
- try_lock!(self.inner.read()).on_event(event, ctx)
- }
-
- #[inline]
- fn on_enter(&self, id: &span::Id, ctx: layer::Context<'_, S>) {
- try_lock!(self.inner.read()).on_enter(id, ctx)
- }
-
- #[inline]
- fn on_exit(&self, id: &span::Id, ctx: layer::Context<'_, S>) {
- try_lock!(self.inner.read()).on_exit(id, ctx)
- }
-
- #[inline]
- fn on_close(&self, id: span::Id, ctx: layer::Context<'_, S>) {
- try_lock!(self.inner.read()).on_close(id, ctx)
- }
-
- #[inline]
- fn on_id_change(&self, old: &span::Id, new: &span::Id, ctx: layer::Context<'_, S>) {
- try_lock!(self.inner.read()).on_id_change(old, new, ctx)
- }
-}
-
-impl<L, S> Layer<L, S>
-where
- L: crate::Layer<S> + 'static,
- S: Subscriber,
-{
- /// Wraps the given `Layer`, returning a `Layer` and a `Handle` that allows
- /// the inner type to be modified at runtime.
- pub fn new(inner: L) -> (Self, Handle<L, S>) {
- let this = Self {
- inner: Arc::new(RwLock::new(inner)),
- _s: PhantomData,
- };
- let handle = this.handle();
- (this, handle)
- }
-
- /// Returns a `Handle` that can be used to reload the wrapped `Layer`.
- pub fn handle(&self) -> Handle<L, S> {
- Handle {
- inner: Arc::downgrade(&self.inner),
- _s: PhantomData,
- }
- }
-}
-
-// ===== impl Handle =====
-
-impl<L, S> Handle<L, S>
-where
- L: crate::Layer<S> + 'static,
- S: Subscriber,
-{
- /// Replace the current layer with the provided `new_layer`.
- pub fn reload(&self, new_layer: impl Into<L>) -> Result<(), Error> {
- self.modify(|layer| {
- *layer = new_layer.into();
- })
- }
-
- /// Invokes a closure with a mutable reference to the current layer,
- /// allowing it to be modified in place.
- pub fn modify(&self, f: impl FnOnce(&mut L)) -> Result<(), Error> {
- let inner = self.inner.upgrade().ok_or(Error {
- kind: ErrorKind::SubscriberGone,
- })?;
-
- let mut lock = try_lock!(inner.write(), else return Err(Error::poisoned()));
- f(&mut *lock);
- // Release the lock before rebuilding the interest cache, as that
- // function will lock the new layer.
- drop(lock);
-
- callsite::rebuild_interest_cache();
- Ok(())
- }
-
- /// Returns a clone of the layer's current value if it still exists.
- /// Otherwise, if the subscriber has been dropped, returns `None`.
- pub fn clone_current(&self) -> Option<L>
- where
- L: Clone,
- {
- self.with_current(L::clone).ok()
- }
-
- /// Invokes a closure with a borrowed reference to the current layer,
- /// returning the result (or an error if the subscriber no longer exists).
- pub fn with_current<T>(&self, f: impl FnOnce(&L) -> T) -> Result<T, Error> {
- let inner = self.inner.upgrade().ok_or(Error {
- kind: ErrorKind::SubscriberGone,
- })?;
- let inner = try_lock!(inner.read(), else return Err(Error::poisoned()));
- Ok(f(&*inner))
- }
-}
-
-impl<L, S> Clone for Handle<L, S> {
- fn clone(&self) -> Self {
- Handle {
- inner: self.inner.clone(),
- _s: PhantomData,
- }
- }
-}
-
-// ===== impl Error =====
-
-impl Error {
- fn poisoned() -> Self {
- Self {
- kind: ErrorKind::Poisoned,
- }
- }
-
- /// Returns `true` if this error occurred because the layer was poisoned by
- /// a panic on another thread.
- pub fn is_poisoned(&self) -> bool {
- matches!(self.kind, ErrorKind::Poisoned)
- }
-
- /// Returns `true` if this error occurred because the `Subscriber`
- /// containing the reloadable layer was dropped.
- pub fn is_dropped(&self) -> bool {
- matches!(self.kind, ErrorKind::SubscriberGone)
- }
-}
-
-impl fmt::Display for Error {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- let msg = match self.kind {
- ErrorKind::SubscriberGone => "subscriber no longer exists",
- ErrorKind::Poisoned => "lock poisoned",
- };
- f.pad(msg)
- }
-}
-
-impl error::Error for Error {}
diff --git a/vendor/tracing-subscriber-0.3.3/tests/filter.rs b/vendor/tracing-subscriber-0.3.3/tests/filter.rs
deleted file mode 100644
index 8386d34d2..000000000
--- a/vendor/tracing-subscriber-0.3.3/tests/filter.rs
+++ /dev/null
@@ -1,187 +0,0 @@
-#![cfg(feature = "env-filter")]
-
-mod support;
-use self::support::*;
-use tracing::{self, subscriber::with_default, Level};
-use tracing_subscriber::{
- filter::{EnvFilter, LevelFilter},
- prelude::*,
-};
-
-#[test]
-fn level_filter_event() {
- let filter: EnvFilter = "info".parse().expect("filter should parse");
- let (subscriber, finished) = subscriber::mock()
- .event(event::mock().at_level(Level::INFO))
- .event(event::mock().at_level(Level::WARN))
- .event(event::mock().at_level(Level::ERROR))
- .done()
- .run_with_handle();
- let subscriber = subscriber.with(filter);
-
- with_default(subscriber, || {
- tracing::trace!("this should be disabled");
- tracing::info!("this shouldn't be");
- tracing::debug!(target: "foo", "this should also be disabled");
- tracing::warn!(target: "foo", "this should be enabled");
- tracing::error!("this should be enabled too");
- });
-
- finished.assert_finished();
-}
-
-#[test]
-fn same_name_spans() {
- let filter: EnvFilter = "[foo{bar}]=trace,[foo{baz}]=trace"
- .parse()
- .expect("filter should parse");
- let (subscriber, finished) = subscriber::mock()
- .new_span(
- span::mock()
- .named("foo")
- .at_level(Level::TRACE)
- .with_field(field::mock("bar")),
- )
- .new_span(
- span::mock()
- .named("foo")
- .at_level(Level::TRACE)
- .with_field(field::mock("baz")),
- )
- .done()
- .run_with_handle();
- let subscriber = subscriber.with(filter);
- with_default(subscriber, || {
- tracing::trace_span!("foo", bar = 1);
- tracing::trace_span!("foo", baz = 1);
- });
-
- finished.assert_finished();
-}
-
-#[test]
-fn level_filter_event_with_target() {
- let filter: EnvFilter = "info,stuff=debug".parse().expect("filter should parse");
- let (subscriber, finished) = subscriber::mock()
- .event(event::mock().at_level(Level::INFO))
- .event(event::mock().at_level(Level::DEBUG).with_target("stuff"))
- .event(event::mock().at_level(Level::WARN).with_target("stuff"))
- .event(event::mock().at_level(Level::ERROR))
- .event(event::mock().at_level(Level::ERROR).with_target("stuff"))
- .done()
- .run_with_handle();
- let subscriber = subscriber.with(filter);
-
- with_default(subscriber, || {
- tracing::trace!("this should be disabled");
- tracing::info!("this shouldn't be");
- tracing::debug!(target: "stuff", "this should be enabled");
- tracing::debug!("but this shouldn't");
- tracing::trace!(target: "stuff", "and neither should this");
- tracing::warn!(target: "stuff", "this should be enabled");
- tracing::error!("this should be enabled too");
- tracing::error!(target: "stuff", "this should be enabled also");
- });
-
- finished.assert_finished();
-}
-
-#[test]
-fn not_order_dependent() {
- // this test reproduces tokio-rs/tracing#623
-
- let filter: EnvFilter = "stuff=debug,info".parse().expect("filter should parse");
- let (subscriber, finished) = subscriber::mock()
- .event(event::mock().at_level(Level::INFO))
- .event(event::mock().at_level(Level::DEBUG).with_target("stuff"))
- .event(event::mock().at_level(Level::WARN).with_target("stuff"))
- .event(event::mock().at_level(Level::ERROR))
- .event(event::mock().at_level(Level::ERROR).with_target("stuff"))
- .done()
- .run_with_handle();
- let subscriber = subscriber.with(filter);
-
- with_default(subscriber, || {
- tracing::trace!("this should be disabled");
- tracing::info!("this shouldn't be");
- tracing::debug!(target: "stuff", "this should be enabled");
- tracing::debug!("but this shouldn't");
- tracing::trace!(target: "stuff", "and neither should this");
- tracing::warn!(target: "stuff", "this should be enabled");
- tracing::error!("this should be enabled too");
- tracing::error!(target: "stuff", "this should be enabled also");
- });
-
- finished.assert_finished();
-}
-
-#[test]
-fn add_directive_enables_event() {
- // this test reproduces tokio-rs/tracing#591
-
- // by default, use info level
- let mut filter = EnvFilter::new(LevelFilter::INFO.to_string());
-
- // overwrite with a more specific directive
- filter = filter.add_directive("hello=trace".parse().expect("directive should parse"));
-
- let (subscriber, finished) = subscriber::mock()
- .event(event::mock().at_level(Level::INFO).with_target("hello"))
- .event(event::mock().at_level(Level::TRACE).with_target("hello"))
- .done()
- .run_with_handle();
- let subscriber = subscriber.with(filter);
-
- with_default(subscriber, || {
- tracing::info!(target: "hello", "hello info");
- tracing::trace!(target: "hello", "hello trace");
- });
-
- finished.assert_finished();
-}
-
-#[test]
-fn span_name_filter_is_dynamic() {
- let filter: EnvFilter = "info,[cool_span]=debug"
- .parse()
- .expect("filter should parse");
- let (subscriber, finished) = subscriber::mock()
- .event(event::mock().at_level(Level::INFO))
- .enter(span::mock().named("cool_span"))
- .event(event::mock().at_level(Level::DEBUG))
- .enter(span::mock().named("uncool_span"))
- .event(event::mock().at_level(Level::WARN))
- .event(event::mock().at_level(Level::DEBUG))
- .exit(span::mock().named("uncool_span"))
- .exit(span::mock().named("cool_span"))
- .enter(span::mock().named("uncool_span"))
- .event(event::mock().at_level(Level::WARN))
- .event(event::mock().at_level(Level::ERROR))
- .exit(span::mock().named("uncool_span"))
- .done()
- .run_with_handle();
- let subscriber = subscriber.with(filter);
-
- with_default(subscriber, || {
- tracing::trace!("this should be disabled");
- tracing::info!("this shouldn't be");
- let cool_span = tracing::info_span!("cool_span");
- let uncool_span = tracing::info_span!("uncool_span");
-
- {
- let _enter = cool_span.enter();
- tracing::debug!("i'm a cool event");
- tracing::trace!("i'm cool, but not cool enough");
- let _enter2 = uncool_span.enter();
- tracing::warn!("warning: extremely cool!");
- tracing::debug!("i'm still cool");
- }
-
- let _enter = uncool_span.enter();
- tracing::warn!("warning: not that cool");
- tracing::trace!("im not cool enough");
- tracing::error!("uncool error");
- });
-
- finished.assert_finished();
-}
diff --git a/vendor/tracing-subscriber-0.3.3/tests/reload.rs b/vendor/tracing-subscriber-0.3.3/tests/reload.rs
deleted file mode 100644
index 5fe422e08..000000000
--- a/vendor/tracing-subscriber-0.3.3/tests/reload.rs
+++ /dev/null
@@ -1,81 +0,0 @@
-#![cfg(feature = "reload")]
-use std::sync::atomic::{AtomicUsize, Ordering};
-use tracing_core::{
- span::{Attributes, Id, Record},
- subscriber::Interest,
- Event, Metadata, Subscriber,
-};
-use tracing_subscriber::{layer, prelude::*, reload::*};
-
-pub struct NopSubscriber;
-
-impl Subscriber for NopSubscriber {
- fn register_callsite(&self, _: &'static Metadata<'static>) -> Interest {
- Interest::never()
- }
-
- fn enabled(&self, _: &Metadata<'_>) -> bool {
- false
- }
-
- fn new_span(&self, _: &Attributes<'_>) -> Id {
- Id::from_u64(1)
- }
-
- fn record(&self, _: &Id, _: &Record<'_>) {}
- fn record_follows_from(&self, _: &Id, _: &Id) {}
- fn event(&self, _: &Event<'_>) {}
- fn enter(&self, _: &Id) {}
- fn exit(&self, _: &Id) {}
-}
-
-#[test]
-fn reload_handle() {
- static FILTER1_CALLS: AtomicUsize = AtomicUsize::new(0);
- static FILTER2_CALLS: AtomicUsize = AtomicUsize::new(0);
-
- enum Filter {
- One,
- Two,
- }
-
- impl<S: Subscriber> tracing_subscriber::Layer<S> for Filter {
- fn register_callsite(&self, m: &Metadata<'_>) -> Interest {
- println!("REGISTER: {:?}", m);
- Interest::sometimes()
- }
-
- fn enabled(&self, m: &Metadata<'_>, _: layer::Context<'_, S>) -> bool {
- println!("ENABLED: {:?}", m);
- match self {
- Filter::One => FILTER1_CALLS.fetch_add(1, Ordering::SeqCst),
- Filter::Two => FILTER2_CALLS.fetch_add(1, Ordering::SeqCst),
- };
- true
- }
- }
- fn event() {
- tracing::trace!("my event");
- }
-
- let (layer, handle) = Layer::new(Filter::One);
-
- let subscriber = tracing_core::dispatcher::Dispatch::new(layer.with_subscriber(NopSubscriber));
-
- tracing_core::dispatcher::with_default(&subscriber, || {
- assert_eq!(FILTER1_CALLS.load(Ordering::SeqCst), 0);
- assert_eq!(FILTER2_CALLS.load(Ordering::SeqCst), 0);
-
- event();
-
- assert_eq!(FILTER1_CALLS.load(Ordering::SeqCst), 1);
- assert_eq!(FILTER2_CALLS.load(Ordering::SeqCst), 0);
-
- handle.reload(Filter::Two).expect("should reload");
-
- event();
-
- assert_eq!(FILTER1_CALLS.load(Ordering::SeqCst), 1);
- assert_eq!(FILTER2_CALLS.load(Ordering::SeqCst), 1);
- })
-}
diff --git a/vendor/tracing-subscriber/.cargo-checksum.json b/vendor/tracing-subscriber/.cargo-checksum.json
new file mode 100644
index 000000000..c4ac8776d
--- /dev/null
+++ b/vendor/tracing-subscriber/.cargo-checksum.json
@@ -0,0 +1 @@
+{"files":{"CHANGELOG.md":"b7eafabf247da01abf02b9b4aab602fd4f66c0da2ce0c8bcf9aa5fb030002180","Cargo.toml":"cb66c58bf1b31f81c8a6e6e394ba5c125a432c280e6559c052bbafc243694005","LICENSE":"898b1ae9821e98daf8964c8d6c7f61641f5f5aa78ad500020771c0939ee0dea1","README.md":"3a06b39f4d699fbc8d8edccea3afdc29b702f79a208abef04411b5c139c607cc","benches/enter.rs":"4a94a04e2abd07950ef2f0b646f4dcdf4ff00abf6396edb5a53c8b41b7691b1a","benches/filter.rs":"6374005ffa47fa19880bb95e3e37406f40ea72a02c5136f4d5eb4c663d452b18","benches/filter_log.rs":"612716bdf9a188093e84d014a4847f18157f148f7d64e54150cd5c91ac709a8a","benches/fmt.rs":"5a0ff37967ffef3a221eebb78855d031e2e883a8a67528c8e794cc6f16cbee8a","benches/support/mod.rs":"72bef51154da9c9b3d81300195c1929a818858fa4b4fc2aa07b49ca586f4cd39","src/field/debug.rs":"4ab50198a0b042d92fefa77b5cac0aef7ba6936149fa555f4b6e2036dcd7f2d7","src/field/delimited.rs":"5e7967637dc3181c097637dcb2a95f35db16583b5fc293b30211db5779ab21ab","src/field/display.rs":"da8cfcb22a39f451f075e2c3a9ce5193c6afe19853cdbd643239657cac5b7e47","src/field/mod.rs":"cb8ab273159f42fc8ebe71c82acc63c962e546328fc4aa9fd5948ce996ef9e05","src/filter/directive.rs":"6341c3a1c8b6d33171647964c35816317c81b03bb098b493f1f1a22222f6ce84","src/filter/env/builder.rs":"57c3706a21e87d2ce73aac305cd55def268c5acb9bfc08f68423c150fd058e76","src/filter/env/directive.rs":"ecd2a7ffb882869f8ea9b0398f5af58ce1797a216b9dc9086c21363d1d500e77","src/filter/env/field.rs":"e1e32a2fc39884c9a5df1d5047128e43f1d0720c0b9daa6bf1e08ca9bcc5f537","src/filter/env/mod.rs":"8403df3f061a1c266b6ab6b30b03c6eb32c1c9354037a2d1eeb36817932e6ea5","src/filter/filter_fn.rs":"0debbc4a4b4d2a57b2a06905017ac908bf34b0a64aaf961535fbf6f4d5a700a9","src/filter/layer_filters/combinator.rs":"695de9d8b0a04df09bea08cc40403e09ff66613c07f72c403f7bc65b89e1fd36","src/filter/layer_filters/mod.rs":"2f23fa79561248255a60d1948423a21bfac5bb8651e6c2ab29d311f4e387a8dc","src/filter/level.rs":"cc449757aac47caaf19dd5ba4d74c8efbcd7531fcd6c13da0c5f6fdda12cc9ca","src/filter/mod.rs":"8ebfd0dc92415ff27ec552f20919e598842a87186f13f120449053a96e1e3307","src/filter/targets.rs":"8fafbbaeb4023f498e64a2831be02fefb825345fbd58065fc7f6129dd70eae4b","src/fmt/fmt_layer.rs":"a596e32e196895866cbd867d52ca13edcdd7651aec971b39f10f9285322823b0","src/fmt/format/json.rs":"554985ed40f7c59787aae87626144241ca973929e33979c54f821b673b71fec9","src/fmt/format/mod.rs":"4e920ab448b1dd4b8c2679261dd337273620fd4f20b6439a4aab341c4d2b08e0","src/fmt/format/pretty.rs":"d4b61d70d1e5b9e01b856acc9db7b23dd27697c587e424f699fb586dd29f73a4","src/fmt/mod.rs":"94239bfefe2bd80722eb4c30f7d10cabe7b9319172a73a7ab5943092e84660fa","src/fmt/time/datetime.rs":"778d4604d800e46b940087394e7b72750738b554e02aea523fa9820ab0768c08","src/fmt/time/mod.rs":"30c97a9d3abd099f52c4c91c7b5f0d29ed9d54d80d1718c6fb74bfd664589de1","src/fmt/time/time_crate.rs":"1bfd59516a583e396afc1770250aa8c06b52f6162a6e7b2cadb860b7eebd9d76","src/fmt/writer.rs":"fa796f0afa3653bf9f666099c65df85d4f74ad1aa412ffc9058b0614632cf12b","src/layer/context.rs":"77137d8b2810c9059ce7838c3b665748bcb9765487d6103b92596e08b0e9e84b","src/layer/layered.rs":"6f08c9662a041652578054ba67b79c457029cc8c29301e8961b0d0e737a3e873","src/layer/mod.rs":"9c84a8260914c8ce7097c101c5be676b64952cf85bc1618d185729443aaabb03","src/layer/tests.rs":"3e974d627c4bc4269cfa10c82c890e596c9d46af8e6bc03c6c117bde1237e948","src/lib.rs":"81ecd4288bdbae864b1627de207779bd674081085d33ee1ff0c23b7df4e7f136","src/macros.rs":"e184bffc6b5999c48e365ad08343dca764a5fb711b789beb26bd1d5f1d767726","src/prelude.rs":"088635def33be9a4c4b6ed934dc22540c555e27d62f7625a43aa9c0e525ca467","src/registry/extensions.rs":"0418b39287bbc06cc95b8cecd6a25aa808b8e04714d842340ff75db458cafe5b","src/registry/mod.rs":"76627b056ce39d006708a6273b6418d001b688f016f58aa546e7821d1ef7f3bb","src/registry/sharded.rs":"1b18f7eaf05bfb9ce6bcd1572dcf9bac352cc69d8ba4633f9679163546bc1d01","src/registry/stack.rs":"9ef333d6a8a28a064e80ff1e376dbb07bc597009010ec332b2dc3ab435d737c2","src/reload.rs":"c9522d15d5cd2b840d37e2bbf366e55c1372df5c75781fde12c8bd092e9e21d1","src/sync.rs":"7f78f3de5b618a999be0e61f936a233975e7769f1ebb55a0e48c3d199e9c45e3","src/util.rs":"55b4e9d63112f9d5a12a287273a9b1212741058384332d3edc024168cacfd627","tests/cached_layer_filters_dont_break_other_layers.rs":"b2084542a014abeff821b30b2b8c21e32bfdcffae53ce5335fb588f557fa4244","tests/duplicate_spans.rs":"3bf35184fb7d1dc5f33e5098820febbec37ef3ccd06b693d11b5585affb60ff4","tests/env_filter/main.rs":"b2d89ee7aaf94f0563e4e5b025cf43186ec61657b763b7c0ae010ff548635251","tests/env_filter/per_layer.rs":"19e9998922f24ec368fcbcda406f43a95335551c4c1669b509bbfc1ef216432a","tests/event_enabling.rs":"15e301a8ff6c74c454547dad15a47b5f11fc54e539162191f21462b6d5080830","tests/field_filter.rs":"fb8735801ba7ecabb421ca361bd1c846841aee63eecbdd665f9544a1cec70f67","tests/filter_log.rs":"086f1e708a2e7389024d7e36d963947909d94c1975db92f4fc425b5cba2af533","tests/fmt_max_level_hint.rs":"d4c6d6f976ae41ab8052fa610a7337ad7150802cbd5634cb30fc45c1f215cfcd","tests/hinted_layer_filters_dont_break_other_layers.rs":"d5ba9cfb6784cf59f007e673ad549dc722d109f6b3d4a69f6aa11b25ca10b469","tests/layer_filter_interests_are_cached.rs":"d036d1c4bc3754e94ebfdda9c841f4858ccec40aba0720f3fbf26c817bfe5a83","tests/layer_filters/boxed.rs":"04db459721a26d6502a2b3fbe42154c5a451021a9374a18c017d10971f44e0c0","tests/layer_filters/combinators.rs":"cdbfaa37fa5b0439ec2ae8028601d22120ff2a42867a2af8a3b27fc58e70cb6c","tests/layer_filters/downcast_raw.rs":"9b90ead571543cbe14e89b4fe637360d9baf3069f6f656ed3bdf65e7318648f1","tests/layer_filters/filter_scopes.rs":"02611bc58d0d8a67a127eca8cab1b2d9a9901bd2c8a8daad41adf6089b28aee0","tests/layer_filters/main.rs":"e9c3f5af7c65b41cde882d5a11a89bf8221e611f1ad881849546c4caf9a494c0","tests/layer_filters/per_event.rs":"424a027e5332e21e734a1833444352b7fbdeeecdc7a82b57f4efd6429bcfb14f","tests/layer_filters/targets.rs":"138e3f9ddd68571d94c5aff9d54ee2fbc5f44724c6ee42477a411740ccb79ee6","tests/layer_filters/trees.rs":"4df7b5cf12da44a9255c56e5b80e2b0cf84820230ba916f324c67bc3ee4e4605","tests/layer_filters/vec.rs":"eaf2e7fe0a76633cc02bc729513202a5fb169e2bdb5a8042d8c7bd1f7092691d","tests/multiple_layer_filter_interests_cached.rs":"1ea195f03e58d715228ec1b604f85bda2fc82812d05b2f6370d5edd34a035f32","tests/option.rs":"0268ca64fb3068bfa95126a477009611253130f902fc558a4605649945bdae29","tests/registry_max_level_hint.rs":"ba386d32b8d13832d7009163241c3d0723488c0393d85647eb9368776251e4fc","tests/registry_with_subscriber.rs":"61a545e1bf3f75efd0dd18c20bb93e8a1f2e0158b342179a94228c4cbd5bb9cc","tests/reload.rs":"8f169b60ab67bbc171dd7e576236b901293b5baa08ea469765a042375855e0f4","tests/same_len_filters.rs":"eceb745f7f5b6c8737c1860a58e2cf98a048fc486dee4379e94485f41c92c925","tests/support.rs":"d5d8ae7a143bda971e24dcba01137be0efea957d732b43502fd845c3bc952f8b","tests/unhinted_layer_filters_dont_break_other_layers.rs":"519cfef4977e511af938546d4208c645a28248c8ed8666daf180f0ad32f0a261","tests/utils.rs":"2c37d9f39010767190f72cb2b3faa3131985764aa547027197108299a9a6bb9e","tests/vec.rs":"d1176f3e1b0954129792a28282b95084d417143b0cc4e35887b95cee3c675392","tests/vec_subscriber_filter_interests_cached.rs":"115a0f097cd649c570eabe74f82791bbe15b2de32a2eef403575661798aadd82"},"package":"a6176eae26dd70d0c919749377897b54a9276bd7061339665dd68777926b5a70"} \ No newline at end of file
diff --git a/vendor/tracing-subscriber-0.3.3/CHANGELOG.md b/vendor/tracing-subscriber/CHANGELOG.md
index c380ff3b1..f283dc61e 100644
--- a/vendor/tracing-subscriber-0.3.3/CHANGELOG.md
+++ b/vendor/tracing-subscriber/CHANGELOG.md
@@ -1,3 +1,395 @@
+# 0.3.16 (October 6, 2022)
+
+This release of `tracing-subscriber` fixes a regression introduced in
+[v0.3.15][subscriber-0.3.15] where `Option::None`'s `Layer` implementation would
+set the max level hint to `OFF`. In addition, it adds several new APIs,
+including the `Filter::event_enabled` method for filtering events based on
+fields values, and the ability to log internal errors that occur when writing a
+log line.
+
+This release also replaces the dependency on the unmaintained [`ansi-term`]
+crate with the [`nu-ansi-term`] crate, resolving an *informational* security
+advisory ([RUSTSEC-2021-0139]) for [`ansi-term`]'s maintainance status. This
+increases the minimum supported Rust version (MSRV) to Rust 1.50+, although the
+crate should still compile for the previous MSRV of Rust 1.49+ when the `ansi`
+feature is not enabled.
+
+### Fixed
+
+- **layer**: `Option::None`'s `Layer` impl always setting the `max_level_hint`
+ to `LevelFilter::OFF` ([#2321])
+- Compilation with `-Z minimal versions` ([#2246])
+- **env-filter**: Clarify that disabled level warnings are emitted by
+ `tracing-subscriber` ([#2285])
+
+### Added
+
+- **fmt**: Log internal errors to `stderr` if writing a log line fails ([#2102])
+- **fmt**: `FmtLayer::log_internal_errors` and
+ `FmtSubscriber::log_internal_errors` methods for configuring whether internal
+ writer errors are printed to `stderr` ([#2102])
+- **fmt**: `#[must_use]` attributes on builders to warn if a `Subscriber` is
+ configured but not set as the default subscriber ([#2239])
+- **filter**: `Filter::event_enabled` method for filtering an event based on its
+ fields ([#2245], [#2251])
+- **filter**: `Targets::default_level` accessor ([#2242])
+
+### Changed
+
+- **ansi**: Replaced dependency on unmaintained `ansi-term` crate with
+ `nu-ansi-term` (([#2287], fixes informational advisory [RUSTSEC-2021-0139])
+- `tracing-core`: updated to [0.1.30][core-0.1.30]
+- Minimum Supported Rust Version (MSRV) increased to Rust 1.50+ (when the
+ `ansi`) feature flag is enabled ([#2287])
+
+### Documented
+
+- **fmt**: Correct inaccuracies in `fmt::init` documentation ([#2224])
+- **filter**: Fix incorrect doc link in `filter::Not` combinator ([#2249])
+
+Thanks to new contributors @cgbur, @DesmondWillowbrook, @RalfJung, and
+@poliorcetics, as well as returning contributors @CAD97, @connec, @jswrenn,
+@guswynn, and @bryangarza, for contributing to this release!
+
+[nu-ansi-term]: https://github.com/nushell/nu-ansi-term
+[ansi_term]: https://github.com/ogham/rust-ansi-term
+[RUSTSEC-2021-0139]: https://rustsec.org/advisories/RUSTSEC-2021-0139.html
+[core-0.1.30]: https://github.com/tokio-rs/tracing/releases/tag/tracing-core-0.1.30
+[subscriber-0.3.15]: https://github.com/tokio-rs/tracing/releases/tag/tracing-subscriber-0.3.15
+[#2321]: https://github.com/tokio-rs/tracing/pull/2321
+[#2246]: https://github.com/tokio-rs/tracing/pull/2246
+[#2285]: https://github.com/tokio-rs/tracing/pull/2285
+[#2102]: https://github.com/tokio-rs/tracing/pull/2102
+[#2239]: https://github.com/tokio-rs/tracing/pull/2239
+[#2245]: https://github.com/tokio-rs/tracing/pull/2245
+[#2251]: https://github.com/tokio-rs/tracing/pull/2251
+[#2287]: https://github.com/tokio-rs/tracing/pull/2287
+[#2224]: https://github.com/tokio-rs/tracing/pull/2224
+[#2249]: https://github.com/tokio-rs/tracing/pull/2249
+
+# 0.3.15 (Jul 20, 2022)
+
+This release fixes a bug where the `reload` layer would fail to pass through
+`max_level_hint` to the underlying layer, potentially breaking filtering.
+
+### Fixed
+
+- **reload**: pass through `max_level_hint` to the inner `Layer` ([#2204])
+
+Thanks to @guswynn for contributing to this release!
+
+[#2204]: https://github.com/tokio-rs/tracing/pull/2204
+
+# 0.3.14 (Jul 1, 2022)
+
+This release fixes multiple filtering bugs in the `Layer` implementations for
+`Option<impl Layer>` and `Vec<impl Layer>`.
+
+### Fixed
+
+- **layer**: `Layer::event_enabled` implementation for `Option<impl Layer<S>>`
+ returning `false` when the `Option` is `None`, disabling all events globally
+ ([#2193])
+- **layer**: `Layer::max_level_hint` implementation for `Option<impl Layer<S>>`
+ incorrectly disabling max level filtering when the option is `None` ([#2195])
+- **layer**: `Layer::max_level_hint` implementation for `Vec<impl Layer<S>>`
+ returning `LevelFilter::ERROR` rather than `LevelFilter::OFF` when the `Vec`
+ is empty ([#2195])
+
+Thanks to @CAD97 and @guswynn for contributing to this release!
+
+[#2193]: https://github.com/tokio-rs/tracing/pull/2193
+[#2195]: https://github.com/tokio-rs/tracing/pull/2195
+
+# 0.3.13 (Jun 30, 2022) (YANKED)
+
+This release of `tracing-subscriber` fixes a compilation failure due to an
+incorrect `tracing-core` dependency that was introduced in v0.3.12.
+
+### Changed
+
+- **tracing_core**: Updated minimum dependency version to 0.1.28 ([#2190])
+
+[#2190]: https://github.com/tokio-rs/tracing/pull/2190
+
+# 0.3.12 (Jun 29, 2022) (YANKED)
+
+This release of `tracing-subscriber` adds a new `Layer::event_enabled` method,
+which allows `Layer`s to filter events *after* their field values are recorded;
+a `Filter` implementation for `reload::Layer`, to make using `reload` with
+per-layer filtering more ergonomic, and additional inherent method downcasting
+APIs for the `Layered` type. In addition, it includes dependency updates, and
+minor fixes for documentation and feature flagging.
+
+### Added
+
+- **layer**: `Layer::event_enabled` method, which can be implemented to filter
+ events based on their field values ([#2008])
+- **reload**: `Filter` implementation for `reload::Layer` ([#2159])
+- **layer**: `Layered::downcast_ref` and `Layered::is` inherent methods
+ ([#2160])
+
+### Changed
+
+- **parking_lot**: Updated dependency on `parking_lot` to 0.13.0 ([#2143])
+- Replaced `lazy_static` dependency with `once_cell` ([#2147])
+
+### Fixed
+
+- Don't enable `tracing-core` features by default ([#2107])
+- Several documentation link and typo fixes ([#2064], [#2068], #[2077], [#2161],
+ [#1088])
+
+Thanks to @ben0x539, @jamesmunns, @georgemp, @james7132, @jswrenn, @CAD97, and
+@guswynn for contributing to this release!
+
+[#2008]: https://github.com/tokio-rs/tracing/pull/2008
+[#2159]: https://github.com/tokio-rs/tracing/pull/2159
+[#2160]: https://github.com/tokio-rs/tracing/pull/2160
+[#2143]: https://github.com/tokio-rs/tracing/pull/2143
+[#2107]: https://github.com/tokio-rs/tracing/pull/2107
+[#2064]: https://github.com/tokio-rs/tracing/pull/2064
+[#2068]: https://github.com/tokio-rs/tracing/pull/2068
+[#2077]: https://github.com/tokio-rs/tracing/pull/2077
+[#2161]: https://github.com/tokio-rs/tracing/pull/2161
+[#1088]: https://github.com/tokio-rs/tracing/pull/1088
+
+# 0.3.11 (Apr 9, 2022)
+
+This is a bugfix release for the `Filter` implementation for `EnvFilter` added
+in [v0.3.10].
+
+### Fixed
+
+- **env-filter**: Added missing `Filter::on_record` callback to `EnvFilter`'s
+ `Filter` impl ([#2058])
+- **env-filter**: Fixed method resolution issues when calling `EnvFilter`
+ methods with both the `Filter` and `Layer` traits in scope ([#2057])
+- **env-filter**: Fixed `EnvFilter::builder().parse()` and other parsing methods
+ returning an error when parsing an empty string ([#2052])
+
+Thanks to new contributor @Ma124 for contributing to this release!
+
+[v0.3.10]: https://github.com/tokio-rs/tracing/releases/tag/tracing-subscriber-0.3.10
+[#2058]: https://github.com/tokio-rs/tracing/pull/2058
+[#2057]: https://github.com/tokio-rs/tracing/pull/2057
+[#2052]: https://github.com/tokio-rs/tracing/pull/2052
+
+# 0.3.10 (Apr 1, 2022)
+
+This release adds several new features, including a `Filter` implementation and
+new builder API for `EnvFilter`, support for using a `Vec<L> where L: Layer` as
+a `Layer`, and a number of smaller API improvements to make working with dynamic
+and reloadable layers easier.
+
+### Added
+
+- **registry**: Implement `Filter` for `EnvFilter`, allowing it to be used with
+ per-layer filtering ([#1983])
+- **registry**: `Filter::on_new_span`, `Filter::on_enter`,
+ `Filter::on_exit`, `Filter::on_close` and `Filter::on_record` callbacks to
+ allow `Filter`s to track span states internally ([#1973], [#2017], [#2031])
+- **registry**: `Filtered::filter` and `Filtered::filter_mut` accessors
+ ([#1959])
+- **registry**: `Filtered::inner` and `Filtered::inner_mut` accessors to borrow
+ the wrapped `Layer` ([#2034])
+- **layer**: Implement `Layer` for `Vec<L: Layer>`, to allow composing together
+ a dynamically sized list of `Layer`s ([#2027])
+- **layer**: `Layer::boxed` method to make type-erasing `Layer`s easier
+ ([#2026])
+- **fmt**: `fmt::Layer::writer` and `fmt::Layer::writer_mut` accessors ([#2034])
+- **fmt**: `fmt::Layer::set_ansi` method to allow changing the ANSI formatting
+ configuration at runtime ([#2034])
+- **env-filter**: `EnvFilter::builder` to configure a new `EnvFilter` prior to
+ parsing it ([#2035])
+- Several documentation fixes and improvements ([#1972], [#1971], [#2023],
+ [#2023])
+
+### Fixed
+
+- **fmt**: `fmt::Layer`'s auto traits no longer depend on the `Subscriber` type
+ parameter's auto traits ([#2025])
+- **env-filter**: Fixed missing help text when the `ansi` feature is disabled
+ ([#2029])
+
+Thanks to new contributors @TimoFreiberg and @wagenet, as well as @CAD97 for
+contributing to this release!
+
+[#1983]: https://github.com/tokio-rs/tracing/pull/1983
+[#1973]: https://github.com/tokio-rs/tracing/pull/1973
+[#2017]: https://github.com/tokio-rs/tracing/pull/2017
+[#2031]: https://github.com/tokio-rs/tracing/pull/2031
+[#1959]: https://github.com/tokio-rs/tracing/pull/1959
+[#2034]: https://github.com/tokio-rs/tracing/pull/2034
+[#2027]: https://github.com/tokio-rs/tracing/pull/2027
+[#2026]: https://github.com/tokio-rs/tracing/pull/2026
+[#2035]: https://github.com/tokio-rs/tracing/pull/2035
+[#1972]: https://github.com/tokio-rs/tracing/pull/1972
+[#1971]: https://github.com/tokio-rs/tracing/pull/1971
+[#2023]: https://github.com/tokio-rs/tracing/pull/2023
+[#2025]: https://github.com/tokio-rs/tracing/pull/2025
+[#2029]: https://github.com/tokio-rs/tracing/pull/2029
+
+# 0.3.9 (Feb 17, 2022)
+
+This release updates the minimum supported Rust version (MSRV) to 1.49.0, and
+updates the (optional) dependency on `parking_lot` to v0.12.
+
+### Changed
+
+- Updated minimum supported Rust version (MSRV) to 1.49.0 ([#1913])
+- `parking_lot`: updated to v0.12 ([008339d])
+
+### Added
+
+- **fmt**: Documentation improvements ([#1926], [#1927])
+
+[#1913]: https://github.com/tokio-rs/tracing/pull/1913
+[#1926]: https://github.com/tokio-rs/tracing/pull/1926
+[#1927]: https://github.com/tokio-rs/tracing/pull/1927
+[008339d]: https://github.com/tokio-rs/tracing/commit/008339d1e8750ffe7b4634fc7789bda0c522424f
+
+# 0.3.8 (Feb 4, 2022)
+
+This release adds *experimental* support for recording structured field
+values using the [`valuable`] crate to the `format::Json` formatter. In
+particular, user-defined types which are recorded using their
+[`valuable::Valuable`] implementations will be serialized as JSON objects,
+rather than using their `fmt::Debug` representation. See [this blog post][post]
+for details on `valuable`.
+
+Note that `valuable` support currently requires `--cfg tracing_unstable`. See
+the documentation for details.
+
+Additionally, this release includes a number of other smaller API improvements.
+
+### Added
+
+- **json**: Experimental support for recording [`valuable`] values as structured
+ JSON ([#1862], [#1901])
+- **filter**: `Targets::would_enable` method for testing if a `Targets` filter
+ would enable a given target ([#1903])
+- **fmt**: `map_event_format`, `map_fmt_fields`, and `map_writer` methods to
+ `fmt::Layer` and `fmt::SubscriberBuilder` ([#1871])
+
+### Changed
+
+- `tracing-core`: updated to [0.1.22][core-0.1.22]
+
+### Fixed
+
+- Set `smallvec` minimal version to 1.2.0, to fix compilation errors with `-Z
+ minimal-versions` ([#1890])
+- Minor documentation fixes ([#1902], [#1893])
+
+Thanks to @guswynn, @glts, and @lilyball for contributing to this release!
+
+[`valuable`]: https://crates.io/crates/valuable
+[`valuable::Valuable`]: https://docs.rs/valuable/latest/valuable/trait.Valuable.html
+[post]: https://tokio.rs/blog/2021-05-valuable
+[core-0.1.22]: https://github.com/tokio-rs/tracing/releases/tag/tracing-core-0.1.22
+[#1862]: https://github.com/tokio-rs/tracing/pull/1862
+[#1901]: https://github.com/tokio-rs/tracing/pull/1901
+[#1903]: https://github.com/tokio-rs/tracing/pull/1903
+[#1871]: https://github.com/tokio-rs/tracing/pull/1871
+[#1890]: https://github.com/tokio-rs/tracing/pull/1890
+[#1902]: https://github.com/tokio-rs/tracing/pull/1902
+[#1893]: https://github.com/tokio-rs/tracing/pull/1893
+
+# 0.3.7 (Jan 25, 2022)
+
+This release adds combinators for combining filters.
+
+Additionally, this release also updates the `thread-local` crate to v1.1.4,
+fixing warnings for the security advisory [RUSTSEC-2022-0006]. Note that
+previous versions of `tracing-subscriber` did not use any of the `thread-local`
+crate's APIs effected by the vulnerability. However, updating the version fixes
+warnings emitted by `cargo audit` and similar tools.
+
+### Added
+
+- **filter**: Added combinators for combining filters ([#1578])
+
+### Fixed
+
+- **registry**: Updated `thread-local` to v1.1.4 ([#1858])
+
+Thanks to new contributor @matze for contributing to this release!
+
+[RUSTSEC-2022-0006]: https://rustsec.org/advisories/RUSTSEC-2022-0006
+[#1578]: https://github.com/tokio-rs/tracing/pull/1578
+[#1858]: https://github.com/tokio-rs/tracing/pull/1858
+
+# 0.3.6 (Jan 14, 2022)
+
+This release adds configuration options to `tracing_subscriber::fmt` to log
+source code locations for events.
+### Added
+
+- **fmt**: Added `with_file` and `with_line_number`
+ configuration methods to `fmt::Format`, `fmt::SubscriberBuilder`, and
+ `fmt::Layer` ([#1773])
+
+### Fixed
+
+- **fmt**: Removed incorrect leading comma from span fields with the `Pretty`
+ formatter ([#1833])
+
+### Deprecated
+
+- **fmt**: Deprecated `Pretty::with_source_location`, as it can now be replaced
+ by the more general `Format`, `SubscriberBuilder`, and `Layer` methods
+ ([#1773])
+
+Thanks to new contributor @renecouto for contributing to this release!
+
+[#1773]: https://github.com/tokio-rs/tracing/pull/1773
+[#1833]: https://github.com/tokio-rs/tracing/pull/1833
+
+# 0.3.5 (Dec 29, 2021)
+
+This release re-enables `RUST_LOG` filtering in `tracing_subscriber::fmt`'s
+default initialization methods, and adds an `OffsetLocalTime` formatter for
+using local timestamps with the `time` crate.
+
+### Added
+
+- **fmt**: Added `OffsetLocalTime` formatter to `fmt::time` for formatting local
+ timestamps with a fixed offset ([#1772])
+
+### Fixed
+
+- **fmt**: Added a `Targets` filter to `fmt::init()` and `fmt::try_init()` when
+ the "env-filter" feature is disabled, so that `RUST_LOG` is still honored
+ ([#1781])
+
+Thanks to @marienz and @ishitatsuyuki for contributing to this release!
+
+[#1772]: https://github.com/tokio-rs/tracing/pull/1772
+[#1781]: https://github.com/tokio-rs/tracing/pull/1781
+
+# 0.3.4 (Dec 23, 2021)
+
+This release contains bugfixes for the `fmt` module, as well as documentation
+improvements.
+
+### Fixed
+
+- **fmt**: Fixed `fmt` not emitting log lines when timestamp formatting fails
+ ([#1689])
+- **fmt**: Fixed double space before thread IDs with `Pretty` formatter
+ ([#1778])
+- Several documentation improvements ([#1608], [#1699], [#1701])
+
+[#1689]: https://github.com/tokio-rs/tracing/pull/1689
+[#1778]: https://github.com/tokio-rs/tracing/pull/1778
+[#1608]: https://github.com/tokio-rs/tracing/pull/1608
+[#1699]: https://github.com/tokio-rs/tracing/pull/1699
+[#1701]: https://github.com/tokio-rs/tracing/pull/1701
+
+Thanks to new contributors @Swatinem and @rukai for contributing to this
+release!
+
# 0.3.3 (Nov 29, 2021)
This release fixes a pair of regressions in `tracing-subscriber`'s `fmt` module.
diff --git a/vendor/tracing-subscriber-0.3.3/Cargo.toml b/vendor/tracing-subscriber/Cargo.toml
index b5e7ba7db..c65075964 100644
--- a/vendor/tracing-subscriber-0.3.3/Cargo.toml
+++ b/vendor/tracing-subscriber/Cargo.toml
@@ -11,20 +11,39 @@
[package]
edition = "2018"
-rust-version = "1.42.0"
+rust-version = "1.50.0"
name = "tracing-subscriber"
-version = "0.3.3"
-authors = ["Eliza Weisman <eliza@buoyant.io>", "David Barsky <me@davidbarsky.com>", "Tokio Contributors <team@tokio.rs>"]
-description = "Utilities for implementing and composing `tracing` subscribers.\n"
+version = "0.3.16"
+authors = [
+ "Eliza Weisman <eliza@buoyant.io>",
+ "David Barsky <me@davidbarsky.com>",
+ "Tokio Contributors <team@tokio.rs>",
+]
+description = """
+Utilities for implementing and composing `tracing` subscribers.
+"""
homepage = "https://tokio.rs"
readme = "README.md"
-keywords = ["logging", "tracing", "metrics", "subscriber"]
-categories = ["development-tools::debugging", "development-tools::profiling", "asynchronous"]
+keywords = [
+ "logging",
+ "tracing",
+ "metrics",
+ "subscriber",
+]
+categories = [
+ "development-tools::debugging",
+ "development-tools::profiling",
+ "asynchronous",
+]
license = "MIT"
repository = "https://github.com/tokio-rs/tracing"
+
[package.metadata.docs.rs]
all-features = true
-rustdoc-args = ["--cfg", "docsrs"]
+rustdoc-args = [
+ "--cfg",
+ "docsrs",
+]
[[bench]]
name = "filter"
@@ -41,20 +60,21 @@ harness = false
[[bench]]
name = "enter"
harness = false
-[dependencies.ansi_term]
-version = "0.12"
+
+[dependencies.matchers]
+version = "0.1.0"
optional = true
-[dependencies.lazy_static]
-version = "1"
+[dependencies.nu-ansi-term]
+version = "0.46.0"
optional = true
-[dependencies.matchers]
-version = "0.1.0"
+[dependencies.once_cell]
+version = "1.13.0"
optional = true
[dependencies.parking_lot]
-version = ">= 0.7, <= 0.11"
+version = "0.12.1"
optional = true
[dependencies.regex]
@@ -64,53 +84,58 @@ optional = true
default-features = false
[dependencies.serde]
-version = "1.0"
+version = "1.0.140"
optional = true
[dependencies.serde_json]
-version = "1.0"
+version = "1.0.82"
optional = true
[dependencies.sharded-slab]
-version = "0.1.0"
+version = "0.1.4"
optional = true
[dependencies.smallvec]
-version = "1"
+version = "1.9.0"
optional = true
[dependencies.thread_local]
-version = "1.0.1"
+version = "1.1.4"
optional = true
[dependencies.time]
-version = "0.3"
+version = "0.3.2"
features = ["formatting"]
optional = true
[dependencies.tracing]
-version = "0.1"
+version = "0.1.35"
optional = true
default-features = false
[dependencies.tracing-core]
-version = "0.1.20"
+version = "0.1.30"
+default-features = false
[dependencies.tracing-log]
-version = "0.1.2"
-features = ["log-tracer", "std"]
+version = "0.1.3"
+features = [
+ "log-tracer",
+ "std",
+]
optional = true
default-features = false
[dependencies.tracing-serde]
-version = "0.1.2"
+version = "0.1.3"
optional = true
+
[dev-dependencies.criterion]
-version = "0.3"
-default_features = false
+version = "0.3.6"
+default-features = false
[dev-dependencies.log]
-version = "0.4"
+version = "0.4.17"
[dev-dependencies.regex]
version = "1"
@@ -118,33 +143,90 @@ features = ["std"]
default-features = false
[dev-dependencies.time]
-version = "0.3"
-features = ["formatting", "macros"]
+version = "0.3.2"
+features = [
+ "formatting",
+ "macros",
+]
[dev-dependencies.tokio]
-version = "0.2"
-features = ["rt-core", "macros"]
+version = "1"
+features = [
+ "rt",
+ "macros",
+]
[dev-dependencies.tracing]
-version = "0.1"
+version = "0.1.35"
[dev-dependencies.tracing-futures]
-version = "0.2"
-features = ["std-future", "std"]
+version = "0.2.0"
+features = [
+ "std-future",
+ "std",
+]
default-features = false
[dev-dependencies.tracing-log]
-version = "0.1.2"
+version = "0.1.3"
[features]
alloc = []
-ansi = ["fmt", "ansi_term"]
-default = ["smallvec", "fmt", "ansi", "tracing-log", "std"]
-env-filter = ["matchers", "regex", "lazy_static", "tracing", "std"]
-fmt = ["registry", "std"]
-json = ["tracing-serde", "serde", "serde_json"]
+ansi = [
+ "fmt",
+ "nu-ansi-term",
+]
+default = [
+ "smallvec",
+ "fmt",
+ "ansi",
+ "tracing-log",
+ "std",
+]
+env-filter = [
+ "matchers",
+ "regex",
+ "once_cell",
+ "tracing",
+ "std",
+ "thread_local",
+]
+fmt = [
+ "registry",
+ "std",
+]
+json = [
+ "tracing-serde",
+ "serde",
+ "serde_json",
+]
local-time = ["time/local-offset"]
-registry = ["sharded-slab", "thread_local", "std"]
-std = ["alloc", "tracing-core/std"]
+registry = [
+ "sharded-slab",
+ "thread_local",
+ "std",
+]
+std = [
+ "alloc",
+ "tracing-core/std",
+]
+valuable = [
+ "tracing-core/valuable",
+ "valuable_crate",
+ "valuable-serde",
+ "tracing-serde/valuable",
+]
+
+[target."cfg(tracing_unstable)".dependencies.valuable-serde]
+version = "0.1.0"
+optional = true
+default-features = false
+
+[target."cfg(tracing_unstable)".dependencies.valuable_crate]
+version = "0.1.0"
+optional = true
+default-features = false
+package = "valuable"
+
[badges.maintenance]
status = "experimental"
diff --git a/vendor/tracing-subscriber-0.3.3/LICENSE b/vendor/tracing-subscriber/LICENSE
index cdb28b4b5..cdb28b4b5 100644
--- a/vendor/tracing-subscriber-0.3.3/LICENSE
+++ b/vendor/tracing-subscriber/LICENSE
diff --git a/vendor/tracing-subscriber-0.3.3/README.md b/vendor/tracing-subscriber/README.md
index 75c62e8ca..124fb956d 100644
--- a/vendor/tracing-subscriber-0.3.3/README.md
+++ b/vendor/tracing-subscriber/README.md
@@ -21,7 +21,7 @@ Utilities for implementing and composing [`tracing`][tracing] subscribers.
[crates-badge]: https://img.shields.io/crates/v/tracing-subscriber.svg
[crates-url]: https://crates.io/crates/tracing-subscriber
[docs-badge]: https://docs.rs/tracing-subscriber/badge.svg
-[docs-url]: https://docs.rs/tracing-subscriber/0.3.1
+[docs-url]: https://docs.rs/tracing-subscriber/0.3.15
[docs-master-badge]: https://img.shields.io/badge/docs-master-blue
[docs-master-url]: https://tracing-rs.netlify.com/tracing_subscriber
[mit-badge]: https://img.shields.io/badge/license-MIT-blue.svg
@@ -32,14 +32,14 @@ Utilities for implementing and composing [`tracing`][tracing] subscribers.
[discord-url]: https://discord.gg/EeF3cQw
[maint-badge]: https://img.shields.io/badge/maintenance-experimental-blue.svg
-*Compiler support: [requires `rustc` 1.42+][msrv]*
+*Compiler support: [requires `rustc` 1.50+][msrv]*
[msrv]: #supported-rust-versions
## Supported Rust Versions
Tracing is built against the latest stable release. The minimum supported
-version is 1.42. The current Tracing version is not guaranteed to build on Rust
+version is 1.50. The current Tracing version is not guaranteed to build on Rust
versions earlier than the minimum supported version.
Tracing follows the same compiler support policies as the rest of the Tokio
diff --git a/vendor/tracing-subscriber-0.3.3/benches/enter.rs b/vendor/tracing-subscriber/benches/enter.rs
index 49c6e730a..49c6e730a 100644
--- a/vendor/tracing-subscriber-0.3.3/benches/enter.rs
+++ b/vendor/tracing-subscriber/benches/enter.rs
diff --git a/vendor/tracing-subscriber-0.3.3/benches/filter.rs b/vendor/tracing-subscriber/benches/filter.rs
index 91ab9c91d..91ab9c91d 100644
--- a/vendor/tracing-subscriber-0.3.3/benches/filter.rs
+++ b/vendor/tracing-subscriber/benches/filter.rs
diff --git a/vendor/tracing-subscriber-0.3.3/benches/filter_log.rs b/vendor/tracing-subscriber/benches/filter_log.rs
index 4dcf3b4ec..4dcf3b4ec 100644
--- a/vendor/tracing-subscriber-0.3.3/benches/filter_log.rs
+++ b/vendor/tracing-subscriber/benches/filter_log.rs
diff --git a/vendor/tracing-subscriber-0.3.3/benches/fmt.rs b/vendor/tracing-subscriber/benches/fmt.rs
index a039e66d4..a039e66d4 100644
--- a/vendor/tracing-subscriber-0.3.3/benches/fmt.rs
+++ b/vendor/tracing-subscriber/benches/fmt.rs
diff --git a/vendor/tracing-subscriber-0.3.3/benches/support/mod.rs b/vendor/tracing-subscriber/benches/support/mod.rs
index 25e9e7e22..25e9e7e22 100644
--- a/vendor/tracing-subscriber-0.3.3/benches/support/mod.rs
+++ b/vendor/tracing-subscriber/benches/support/mod.rs
diff --git a/vendor/tracing-subscriber-0.3.3/src/field/debug.rs b/vendor/tracing-subscriber/src/field/debug.rs
index cc67d29fe..cc67d29fe 100644
--- a/vendor/tracing-subscriber-0.3.3/src/field/debug.rs
+++ b/vendor/tracing-subscriber/src/field/debug.rs
diff --git a/vendor/tracing-subscriber-0.3.3/src/field/delimited.rs b/vendor/tracing-subscriber/src/field/delimited.rs
index 8c78c4b20..98634cea9 100644
--- a/vendor/tracing-subscriber-0.3.3/src/field/delimited.rs
+++ b/vendor/tracing-subscriber/src/field/delimited.rs
@@ -41,7 +41,7 @@ impl<D, V> Delimited<D, V> {
/// Returns a new [`MakeVisitor`] implementation that wraps `inner` so that
/// it will format each visited field separated by the provided `delimiter`.
///
- /// [`MakeVisitor`]: ../trait.MakeVisitor.html
+ /// [`MakeVisitor`]: super::MakeVisitor
pub fn new(delimiter: D, inner: V) -> Self {
Self { delimiter, inner }
}
@@ -53,7 +53,7 @@ impl<D, V> VisitDelimited<D, V> {
/// Returns a new [`Visit`] implementation that wraps `inner` so that
/// each formatted field is separated by the provided `delimiter`.
///
- /// [`Visit`]: https://docs.rs/tracing-core/0.1.6/tracing_core/field/trait.Visit.html
+ /// [`Visit`]: tracing_core::field::Visit
pub fn new(delimiter: D, inner: V) -> Self {
Self {
delimiter,
diff --git a/vendor/tracing-subscriber-0.3.3/src/field/display.rs b/vendor/tracing-subscriber/src/field/display.rs
index e0bbc55ed..78a039ce1 100644
--- a/vendor/tracing-subscriber-0.3.3/src/field/display.rs
+++ b/vendor/tracing-subscriber/src/field/display.rs
@@ -18,7 +18,7 @@ impl<V> Messages<V> {
/// Returns a new [`MakeVisitor`] implementation that will wrap `inner` so
/// that any strings named `message` are formatted using `fmt::Display`.
///
- /// [`MakeVisitor`]: ../trait.MakeVisitor.html
+ /// [`MakeVisitor`]: super::MakeVisitor
pub fn new(inner: V) -> Self {
Messages(inner)
}
diff --git a/vendor/tracing-subscriber-0.3.3/src/field/mod.rs b/vendor/tracing-subscriber/src/field/mod.rs
index f7d03f2cc..5dfddb362 100644
--- a/vendor/tracing-subscriber-0.3.3/src/field/mod.rs
+++ b/vendor/tracing-subscriber/src/field/mod.rs
@@ -22,7 +22,7 @@ pub mod display;
/// data to, configuration variables that determine the visitor's behavior, or
/// `()` when no input is required to produce a visitor.
///
-/// [visitors]: https://docs.rs/tracing-core/latest/tracing_core/field/trait.Visit.html
+/// [visitors]: tracing_core::field::Visit
pub trait MakeVisitor<T> {
/// The visitor type produced by this `MakeVisitor`.
type Visitor: Visit;
@@ -33,7 +33,7 @@ pub trait MakeVisitor<T> {
/// A [visitor] that produces output once it has visited a set of fields.
///
-/// [visitor]: https://docs.rs/tracing-core/latest/tracing_core/field/trait.Visit.html
+/// [visitor]: tracing_core::field::Visit
pub trait VisitOutput<Out>: Visit {
/// Completes the visitor, returning any output.
///
@@ -82,10 +82,10 @@ pub trait VisitOutput<Out>: Visit {
/// r.record(&mut visitor);
/// }
/// ```
-/// [visitor]: https://docs.rs/tracing-core/latest/tracing_core/field/trait.Visit.html
-/// [attr]: https://docs.rs/tracing-core/latest/tracing_core/span/struct.Attributes.html
-/// [rec]: https://docs.rs/tracing-core/latest/tracing_core/span/struct.Record.html
-/// [event]: https://docs.rs/tracing-core/latest/tracing_core/event/struct.Event.html
+/// [visitor]: tracing_core::field::Visit
+/// [attr]: tracing_core::span::Attributes
+/// [rec]: tracing_core::span::Record
+/// [event]: tracing_core::event::Event
pub trait RecordFields: crate::sealed::Sealed<RecordFieldsMarker> {
/// Record all the fields in `self` with the provided `visitor`.
fn record(&self, visitor: &mut dyn Visit);
@@ -341,7 +341,7 @@ pub(in crate::field) mod test_util {
impl<'a> Visit for DebugVisitor<'a> {
fn record_debug(&mut self, field: &Field, value: &dyn fmt::Debug) {
- write!(&mut self.writer, "{}={:?}", field, value).unwrap();
+ write!(self.writer, "{}={:?}", field, value).unwrap();
}
}
diff --git a/vendor/tracing-subscriber-0.3.3/src/filter/directive.rs b/vendor/tracing-subscriber/src/filter/directive.rs
index dd6b063c4..2ae3f0f24 100644
--- a/vendor/tracing-subscriber-0.3.3/src/filter/directive.rs
+++ b/vendor/tracing-subscriber/src/filter/directive.rs
@@ -5,7 +5,7 @@ use alloc::vec;
use alloc::{string::String, vec::Vec};
use core::{cmp::Ordering, fmt, iter::FromIterator, slice, str::FromStr};
-use tracing_core::Metadata;
+use tracing_core::{Level, Metadata};
/// Indicates that a string could not be parsed as a filtering directive.
#[derive(Debug)]
pub struct ParseError {
@@ -142,6 +142,22 @@ impl DirectiveSet<StaticDirective> {
None => false,
}
}
+
+ /// Same as `enabled` above, but skips `Directive`'s with fields.
+ pub(crate) fn target_enabled(&self, target: &str, level: &Level) -> bool {
+ match self.directives_for_target(target).next() {
+ Some(d) => d.level >= *level,
+ None => false,
+ }
+ }
+
+ pub(crate) fn directives_for_target<'a>(
+ &'a self,
+ target: &'a str,
+ ) -> impl Iterator<Item = &'a StaticDirective> + 'a {
+ self.directives()
+ .filter(move |d| d.cares_about_target(target))
+ }
}
// === impl StaticDirective ===
@@ -158,6 +174,22 @@ impl StaticDirective {
level,
}
}
+
+ pub(in crate::filter) fn cares_about_target(&self, to_check: &str) -> bool {
+ // Does this directive have a target filter, and does it match the
+ // metadata's target?
+ if let Some(ref target) = self.target {
+ if !to_check.starts_with(&target[..]) {
+ return false;
+ }
+ }
+
+ if !self.field_names.is_empty() {
+ return false;
+ }
+
+ true
+ }
}
impl Ord for StaticDirective {
diff --git a/vendor/tracing-subscriber/src/filter/env/builder.rs b/vendor/tracing-subscriber/src/filter/env/builder.rs
new file mode 100644
index 000000000..c814707e6
--- /dev/null
+++ b/vendor/tracing-subscriber/src/filter/env/builder.rs
@@ -0,0 +1,325 @@
+use super::{
+ directive::{self, Directive},
+ EnvFilter, FromEnvError,
+};
+use crate::sync::RwLock;
+use std::env;
+use thread_local::ThreadLocal;
+use tracing::level_filters::STATIC_MAX_LEVEL;
+
+/// A [builder] for constructing new [`EnvFilter`]s.
+///
+/// [builder]: https://rust-unofficial.github.io/patterns/patterns/creational/builder.html
+#[derive(Debug, Clone)]
+#[must_use]
+pub struct Builder {
+ regex: bool,
+ env: Option<String>,
+ default_directive: Option<Directive>,
+}
+
+impl Builder {
+ /// Sets whether span field values can be matched with regular expressions.
+ ///
+ /// If this is `true`, field filter directives will be interpreted as
+ /// regular expressions if they are not able to be interpreted as a `bool`,
+ /// `i64`, `u64`, or `f64` literal. If this is `false,` those field values
+ /// will be interpreted as literal [`std::fmt::Debug`] output instead.
+ ///
+ /// By default, regular expressions are enabled.
+ ///
+ /// **Note**: when [`EnvFilter`]s are constructed from untrusted inputs,
+ /// disabling regular expressions is strongly encouraged.
+ pub fn with_regex(self, regex: bool) -> Self {
+ Self { regex, ..self }
+ }
+
+ /// Sets a default [filtering directive] that will be added to the filter if
+ /// the parsed string or environment variable contains no filter directives.
+ ///
+ /// By default, there is no default directive.
+ ///
+ /// # Examples
+ ///
+ /// If [`parse`], [`parse_lossy`], [`from_env`], or [`from_env_lossy`] are
+ /// called with an empty string or environment variable, the default
+ /// directive is used instead:
+ ///
+ /// ```rust
+ /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
+ /// use tracing_subscriber::filter::{EnvFilter, LevelFilter};
+ ///
+ /// let filter = EnvFilter::builder()
+ /// .with_default_directive(LevelFilter::INFO.into())
+ /// .parse("")?;
+ ///
+ /// assert_eq!(format!("{}", filter), "info");
+ /// # Ok(()) }
+ /// ```
+ ///
+ /// Note that the `lossy` variants ([`parse_lossy`] and [`from_env_lossy`])
+ /// will ignore any invalid directives. If all directives in a filter
+ /// string or environment variable are invalid, those methods will also use
+ /// the default directive:
+ ///
+ /// ```rust
+ /// use tracing_subscriber::filter::{EnvFilter, LevelFilter};
+ ///
+ /// let filter = EnvFilter::builder()
+ /// .with_default_directive(LevelFilter::INFO.into())
+ /// .parse_lossy("some_target=fake level,foo::bar=lolwut");
+ ///
+ /// assert_eq!(format!("{}", filter), "info");
+ /// ```
+ ///
+ ///
+ /// If the string or environment variable contains valid filtering
+ /// directives, the default directive is not used:
+ ///
+ /// ```rust
+ /// use tracing_subscriber::filter::{EnvFilter, LevelFilter};
+ ///
+ /// let filter = EnvFilter::builder()
+ /// .with_default_directive(LevelFilter::INFO.into())
+ /// .parse_lossy("foo=trace");
+ ///
+ /// // The default directive is *not* used:
+ /// assert_eq!(format!("{}", filter), "foo=trace");
+ /// ```
+ ///
+ /// Parsing a more complex default directive from a string:
+ ///
+ /// ```rust
+ /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
+ /// use tracing_subscriber::filter::{EnvFilter, LevelFilter};
+ ///
+ /// let default = "myapp=debug".parse()
+ /// .expect("hard-coded default directive should be valid");
+ ///
+ /// let filter = EnvFilter::builder()
+ /// .with_default_directive(default)
+ /// .parse("")?;
+ ///
+ /// assert_eq!(format!("{}", filter), "myapp=debug");
+ /// # Ok(()) }
+ /// ```
+ ///
+ /// [`parse_lossy`]: Self::parse_lossy
+ /// [`from_env_lossy`]: Self::from_env_lossy
+ /// [`parse`]: Self::parse
+ /// [`from_env`]: Self::from_env
+ pub fn with_default_directive(self, default_directive: Directive) -> Self {
+ Self {
+ default_directive: Some(default_directive),
+ ..self
+ }
+ }
+
+ /// Sets the name of the environment variable used by the [`from_env`],
+ /// [`from_env_lossy`], and [`try_from_env`] methods.
+ ///
+ /// By default, this is the value of [`EnvFilter::DEFAULT_ENV`]
+ /// (`RUST_LOG`).
+ ///
+ /// [`from_env`]: Self::from_env
+ /// [`from_env_lossy`]: Self::from_env_lossy
+ /// [`try_from_env`]: Self::try_from_env
+ pub fn with_env_var(self, var: impl ToString) -> Self {
+ Self {
+ env: Some(var.to_string()),
+ ..self
+ }
+ }
+
+ /// Returns a new [`EnvFilter`] from the directives in the given string,
+ /// *ignoring* any that are invalid.
+ pub fn parse_lossy<S: AsRef<str>>(&self, dirs: S) -> EnvFilter {
+ let directives = dirs
+ .as_ref()
+ .split(',')
+ .filter(|s| !s.is_empty())
+ .filter_map(|s| match Directive::parse(s, self.regex) {
+ Ok(d) => Some(d),
+ Err(err) => {
+ eprintln!("ignoring `{}`: {}", s, err);
+ None
+ }
+ });
+ self.from_directives(directives)
+ }
+
+ /// Returns a new [`EnvFilter`] from the directives in the given string,
+ /// or an error if any are invalid.
+ pub fn parse<S: AsRef<str>>(&self, dirs: S) -> Result<EnvFilter, directive::ParseError> {
+ let dirs = dirs.as_ref();
+ if dirs.is_empty() {
+ return Ok(self.from_directives(std::iter::empty()));
+ }
+ let directives = dirs
+ .split(',')
+ .filter(|s| !s.is_empty())
+ .map(|s| Directive::parse(s, self.regex))
+ .collect::<Result<Vec<_>, _>>()?;
+ Ok(self.from_directives(directives))
+ }
+
+ /// Returns a new [`EnvFilter`] from the directives in the configured
+ /// environment variable, ignoring any directives that are invalid.
+ pub fn from_env_lossy(&self) -> EnvFilter {
+ let var = env::var(self.env_var_name()).unwrap_or_default();
+ self.parse_lossy(var)
+ }
+
+ /// Returns a new [`EnvFilter`] from the directives in the in the configured
+ /// environment variable, or an error if the environment variable is not set
+ /// or contains invalid directives.
+ pub fn from_env(&self) -> Result<EnvFilter, FromEnvError> {
+ let var = env::var(self.env_var_name()).unwrap_or_default();
+ self.parse(var).map_err(Into::into)
+ }
+
+ /// Returns a new [`EnvFilter`] from the directives in the in the configured
+ /// environment variable, or an error if the environment variable is not set
+ /// or contains invalid directives.
+ pub fn try_from_env(&self) -> Result<EnvFilter, FromEnvError> {
+ let var = env::var(self.env_var_name())?;
+ self.parse(var).map_err(Into::into)
+ }
+
+ // TODO(eliza): consider making this a public API?
+ // Clippy doesn't love this naming, because it suggests that `from_` methods
+ // should not take a `Self`...but in this case, it's the `EnvFilter` that is
+ // being constructed "from" the directives, rather than the builder itself.
+ #[allow(clippy::wrong_self_convention)]
+ pub(super) fn from_directives(
+ &self,
+ directives: impl IntoIterator<Item = Directive>,
+ ) -> EnvFilter {
+ use tracing::Level;
+
+ let mut directives: Vec<_> = directives.into_iter().collect();
+ let mut disabled = Vec::new();
+ for directive in &mut directives {
+ if directive.level > STATIC_MAX_LEVEL {
+ disabled.push(directive.clone());
+ }
+ if !self.regex {
+ directive.deregexify();
+ }
+ }
+
+ if !disabled.is_empty() {
+ #[cfg(feature = "nu_ansi_term")]
+ use nu_ansi_term::{Color, Style};
+ // NOTE: We can't use a configured `MakeWriter` because the EnvFilter
+ // has no knowledge of any underlying subscriber or collector, which
+ // may or may not use a `MakeWriter`.
+ let warn = |msg: &str| {
+ #[cfg(not(feature = "nu_ansi_term"))]
+ let msg = format!("warning: {}", msg);
+ #[cfg(feature = "nu_ansi_term")]
+ let msg = {
+ let bold = Style::new().bold();
+ let mut warning = Color::Yellow.paint("warning");
+ warning.style_ref_mut().is_bold = true;
+ format!("{}{} {}", warning, bold.paint(":"), bold.paint(msg))
+ };
+ eprintln!("{}", msg);
+ };
+ let ctx_prefixed = |prefix: &str, msg: &str| {
+ #[cfg(not(feature = "nu_ansi_term"))]
+ let msg = format!("{} {}", prefix, msg);
+ #[cfg(feature = "nu_ansi_term")]
+ let msg = {
+ let mut equal = Color::Fixed(21).paint("="); // dark blue
+ equal.style_ref_mut().is_bold = true;
+ format!(" {} {} {}", equal, Style::new().bold().paint(prefix), msg)
+ };
+ eprintln!("{}", msg);
+ };
+ let ctx_help = |msg| ctx_prefixed("help:", msg);
+ let ctx_note = |msg| ctx_prefixed("note:", msg);
+ let ctx = |msg: &str| {
+ #[cfg(not(feature = "nu_ansi_term"))]
+ let msg = format!("note: {}", msg);
+ #[cfg(feature = "nu_ansi_term")]
+ let msg = {
+ let mut pipe = Color::Fixed(21).paint("|");
+ pipe.style_ref_mut().is_bold = true;
+ format!(" {} {}", pipe, msg)
+ };
+ eprintln!("{}", msg);
+ };
+ warn("some trace filter directives would enable traces that are disabled statically");
+ for directive in disabled {
+ let target = if let Some(target) = &directive.target {
+ format!("the `{}` target", target)
+ } else {
+ "all targets".into()
+ };
+ let level = directive
+ .level
+ .into_level()
+ .expect("=off would not have enabled any filters");
+ ctx(&format!(
+ "`{}` would enable the {} level for {}",
+ directive, level, target
+ ));
+ }
+ ctx_note(&format!("the static max level is `{}`", STATIC_MAX_LEVEL));
+ let help_msg = || {
+ let (feature, filter) = match STATIC_MAX_LEVEL.into_level() {
+ Some(Level::TRACE) => unreachable!(
+ "if the max level is trace, no static filtering features are enabled"
+ ),
+ Some(Level::DEBUG) => ("max_level_debug", Level::TRACE),
+ Some(Level::INFO) => ("max_level_info", Level::DEBUG),
+ Some(Level::WARN) => ("max_level_warn", Level::INFO),
+ Some(Level::ERROR) => ("max_level_error", Level::WARN),
+ None => return ("max_level_off", String::new()),
+ };
+ (feature, format!("{} ", filter))
+ };
+ let (feature, earlier_level) = help_msg();
+ ctx_help(&format!(
+ "to enable {}logging, remove the `{}` feature from the `tracing` crate",
+ earlier_level, feature
+ ));
+ }
+
+ let (dynamics, statics) = Directive::make_tables(directives);
+ let has_dynamics = !dynamics.is_empty();
+
+ let mut filter = EnvFilter {
+ statics,
+ dynamics,
+ has_dynamics,
+ by_id: RwLock::new(Default::default()),
+ by_cs: RwLock::new(Default::default()),
+ scope: ThreadLocal::new(),
+ regex: self.regex,
+ };
+
+ if !has_dynamics && filter.statics.is_empty() {
+ if let Some(ref default) = self.default_directive {
+ filter = filter.add_directive(default.clone());
+ }
+ }
+
+ filter
+ }
+
+ fn env_var_name(&self) -> &str {
+ self.env.as_deref().unwrap_or(EnvFilter::DEFAULT_ENV)
+ }
+}
+
+impl Default for Builder {
+ fn default() -> Self {
+ Self {
+ regex: true,
+ env: None,
+ default_directive: None,
+ }
+ }
+}
diff --git a/vendor/tracing-subscriber-0.3.3/src/filter/env/directive.rs b/vendor/tracing-subscriber/src/filter/env/directive.rs
index 66ca23dc4..f062e6ef9 100644
--- a/vendor/tracing-subscriber-0.3.3/src/filter/env/directive.rs
+++ b/vendor/tracing-subscriber/src/filter/env/directive.rs
@@ -4,14 +4,14 @@ use crate::filter::{
env::{field, FieldMap},
level::LevelFilter,
};
-use lazy_static::lazy_static;
+use once_cell::sync::Lazy;
use regex::Regex;
use std::{cmp::Ordering, fmt, iter::FromIterator, str::FromStr};
use tracing_core::{span, Level, Metadata};
/// A single filtering directive.
// TODO(eliza): add a builder for programmatically constructing directives?
-#[derive(Debug, Eq, PartialEq)]
+#[derive(Clone, Debug, Eq, PartialEq)]
#[cfg_attr(docsrs, doc(cfg(feature = "env-filter")))]
pub struct Directive {
in_span: Option<String>,
@@ -107,80 +107,52 @@ impl Directive {
.collect();
(Dynamics::from_iter(dyns), statics)
}
-}
-
-impl Match for Directive {
- fn cares_about(&self, meta: &Metadata<'_>) -> bool {
- // Does this directive have a target filter, and does it match the
- // metadata's target?
- if let Some(ref target) = self.target {
- if !meta.target().starts_with(&target[..]) {
- return false;
- }
- }
-
- // Do we have a name filter, and does it match the metadata's name?
- // TODO(eliza): put name globbing here?
- if let Some(ref name) = self.in_span {
- if name != meta.name() {
- return false;
- }
- }
- // Does the metadata define all the fields that this directive cares about?
- let fields = meta.fields();
- for field in &self.fields {
- if fields.field(&field.name).is_none() {
- return false;
+ pub(super) fn deregexify(&mut self) {
+ for field in &mut self.fields {
+ field.value = match field.value.take() {
+ Some(field::ValueMatch::Pat(pat)) => {
+ Some(field::ValueMatch::Debug(pat.into_debug_match()))
+ }
+ x => x,
}
}
-
- true
- }
-
- fn level(&self) -> &LevelFilter {
- &self.level
}
-}
-impl FromStr for Directive {
- type Err = ParseError;
- fn from_str(from: &str) -> Result<Self, Self::Err> {
- lazy_static! {
- static ref DIRECTIVE_RE: Regex = Regex::new(
- r"(?x)
- ^(?P<global_level>(?i:trace|debug|info|warn|error|off|[0-5]))$ |
- # ^^^.
- # `note: we match log level names case-insensitively
- ^
- (?: # target name or span name
- (?P<target>[\w:-]+)|(?P<span>\[[^\]]*\])
- ){1,2}
- (?: # level or nothing
- =(?P<level>(?i:trace|debug|info|warn|error|off|[0-5]))?
- # ^^^.
- # `note: we match log level names case-insensitively
- )?
- $
- "
- )
- .unwrap();
- static ref SPAN_PART_RE: Regex =
- Regex::new(r#"(?P<name>[^\]\{]+)?(?:\{(?P<fields>[^\}]*)\})?"#).unwrap();
- static ref FIELD_FILTER_RE: Regex =
- // TODO(eliza): this doesn't _currently_ handle value matchers that include comma
- // characters. We should fix that.
- Regex::new(r#"(?x)
- (
- # field name
- [[:word:]][[[:word:]]\.]*
- # value part (optional)
- (?:=[^,]+)?
- )
- # trailing comma or EOS
- (?:,\s?|$)
- "#).unwrap();
- }
+ pub(super) fn parse(from: &str, regex: bool) -> Result<Self, ParseError> {
+ static DIRECTIVE_RE: Lazy<Regex> = Lazy::new(|| Regex::new(
+ r"(?x)
+ ^(?P<global_level>(?i:trace|debug|info|warn|error|off|[0-5]))$ |
+ # ^^^.
+ # `note: we match log level names case-insensitively
+ ^
+ (?: # target name or span name
+ (?P<target>[\w:-]+)|(?P<span>\[[^\]]*\])
+ ){1,2}
+ (?: # level or nothing
+ =(?P<level>(?i:trace|debug|info|warn|error|off|[0-5]))?
+ # ^^^.
+ # `note: we match log level names case-insensitively
+ )?
+ $
+ "
+ )
+ .unwrap());
+ static SPAN_PART_RE: Lazy<Regex> =
+ Lazy::new(|| Regex::new(r#"(?P<name>[^\]\{]+)?(?:\{(?P<fields>[^\}]*)\})?"#).unwrap());
+ static FIELD_FILTER_RE: Lazy<Regex> =
+ // TODO(eliza): this doesn't _currently_ handle value matchers that include comma
+ // characters. We should fix that.
+ Lazy::new(|| Regex::new(r#"(?x)
+ (
+ # field name
+ [[:word:]][[[:word:]]\.]*
+ # value part (optional)
+ (?:=[^,]+)?
+ )
+ # trailing comma or EOS
+ (?:,\s?|$)
+ "#).unwrap());
let caps = DIRECTIVE_RE.captures(from).ok_or_else(ParseError::new)?;
@@ -214,7 +186,7 @@ impl FromStr for Directive {
.map(|c| {
FIELD_FILTER_RE
.find_iter(c.as_str())
- .map(|c| c.as_str().parse())
+ .map(|c| field::Match::parse(c.as_str(), regex))
.collect::<Result<Vec<_>, _>>()
})
.unwrap_or_else(|| Ok(Vec::new()));
@@ -228,7 +200,7 @@ impl FromStr for Directive {
// Setting the target without the level enables every level for that target
.unwrap_or(LevelFilter::TRACE);
- Ok(Directive {
+ Ok(Self {
level,
target,
in_span,
@@ -237,6 +209,48 @@ impl FromStr for Directive {
}
}
+impl Match for Directive {
+ fn cares_about(&self, meta: &Metadata<'_>) -> bool {
+ // Does this directive have a target filter, and does it match the
+ // metadata's target?
+ if let Some(ref target) = self.target {
+ if !meta.target().starts_with(&target[..]) {
+ return false;
+ }
+ }
+
+ // Do we have a name filter, and does it match the metadata's name?
+ // TODO(eliza): put name globbing here?
+ if let Some(ref name) = self.in_span {
+ if name != meta.name() {
+ return false;
+ }
+ }
+
+ // Does the metadata define all the fields that this directive cares about?
+ let actual_fields = meta.fields();
+ for expected_field in &self.fields {
+ // Does the actual field set (from the metadata) contain this field?
+ if actual_fields.field(&expected_field.name).is_none() {
+ return false;
+ }
+ }
+
+ true
+ }
+
+ fn level(&self) -> &LevelFilter {
+ &self.level
+ }
+}
+
+impl FromStr for Directive {
+ type Err = ParseError;
+ fn from_str(from: &str) -> Result<Self, Self::Err> {
+ Directive::parse(from, true)
+ }
+}
+
impl Default for Directive {
fn default() -> Self {
Directive {
diff --git a/vendor/tracing-subscriber-0.3.3/src/filter/env/field.rs b/vendor/tracing-subscriber/src/filter/env/field.rs
index 970850f92..1394fd04a 100644
--- a/vendor/tracing-subscriber-0.3.3/src/filter/env/field.rs
+++ b/vendor/tracing-subscriber/src/filter/env/field.rs
@@ -2,7 +2,7 @@ use matchers::Pattern;
use std::{
cmp::Ordering,
error::Error,
- fmt,
+ fmt::{self, Write},
str::FromStr,
sync::{
atomic::{AtomicBool, Ordering::*},
@@ -13,7 +13,7 @@ use std::{
use super::{FieldMap, LevelFilter};
use tracing_core::field::{Field, Visit};
-#[derive(Debug, Eq, PartialEq)]
+#[derive(Clone, Debug, Eq, PartialEq)]
pub(crate) struct Match {
pub(crate) name: String, // TODO: allow match patterns for names?
pub(crate) value: Option<ValueMatch>,
@@ -38,11 +38,20 @@ pub(crate) struct MatchVisitor<'a> {
#[derive(Debug, Clone)]
pub(crate) enum ValueMatch {
+ /// Matches a specific `bool` value.
Bool(bool),
+ /// Matches a specific `f64` value.
F64(f64),
+ /// Matches a specific `u64` value.
U64(u64),
+ /// Matches a specific `i64` value.
I64(i64),
+ /// Matches any `NaN` `f64` value.
NaN,
+ /// Matches any field whose `fmt::Debug` output is equal to a fixed string.
+ Debug(MatchDebug),
+ /// Matches any field whose `fmt::Debug` output matches a regular expression
+ /// pattern.
Pat(Box<MatchPattern>),
}
@@ -97,6 +106,9 @@ impl Ord for ValueMatch {
(Pat(this), Pat(that)) => this.cmp(that),
(Pat(_), _) => Ordering::Greater,
+
+ (Debug(this), Debug(that)) => this.cmp(that),
+ (Debug(_), _) => Ordering::Greater,
}
}
}
@@ -107,12 +119,25 @@ impl PartialOrd for ValueMatch {
}
}
+/// Matches a field's `fmt::Debug` output against a regular expression pattern.
+///
+/// This is used for matching all non-literal field value filters when regular
+/// expressions are enabled.
#[derive(Debug, Clone)]
pub(crate) struct MatchPattern {
pub(crate) matcher: Pattern,
pattern: Arc<str>,
}
+/// Matches a field's `fmt::Debug` output against a fixed string pattern.
+///
+/// This is used for matching all non-literal field value filters when regular
+/// expressions are disabled.
+#[derive(Debug, Clone)]
+pub(crate) struct MatchDebug {
+ pattern: Arc<str>,
+}
+
/// Indicates that a field name specified in a filter directive was invalid.
#[derive(Clone, Debug)]
#[cfg_attr(docsrs, doc(cfg(feature = "env-filter")))]
@@ -122,9 +147,17 @@ pub struct BadName {
// === impl Match ===
-impl FromStr for Match {
- type Err = Box<dyn Error + Send + Sync>;
- fn from_str(s: &str) -> Result<Self, Self::Err> {
+impl Match {
+ pub(crate) fn has_value(&self) -> bool {
+ self.value.is_some()
+ }
+
+ // TODO: reference count these strings?
+ pub(crate) fn name(&self) -> String {
+ self.name.clone()
+ }
+
+ pub(crate) fn parse(s: &str, regex: bool) -> Result<Self, Box<dyn Error + Send + Sync>> {
let mut parts = s.split('=');
let name = parts
.next()
@@ -133,22 +166,17 @@ impl FromStr for Match {
})?
// TODO: validate field name
.to_string();
- let value = parts.next().map(ValueMatch::from_str).transpose()?;
+ let value = parts
+ .next()
+ .map(|part| match regex {
+ true => ValueMatch::parse_regex(part),
+ false => Ok(ValueMatch::parse_non_regex(part)),
+ })
+ .transpose()?;
Ok(Match { name, value })
}
}
-impl Match {
- pub(crate) fn has_value(&self) -> bool {
- self.value.is_some()
- }
-
- // TODO: reference count these strings?
- pub(crate) fn name(&self) -> String {
- self.name.clone()
- }
-}
-
impl fmt::Display for Match {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Display::fmt(&self.name, f)?;
@@ -199,9 +227,14 @@ fn value_match_f64(v: f64) -> ValueMatch {
}
}
-impl FromStr for ValueMatch {
- type Err = matchers::Error;
- fn from_str(s: &str) -> Result<Self, Self::Err> {
+impl ValueMatch {
+ /// Parse a `ValueMatch` that will match `fmt::Debug` fields using regular
+ /// expressions.
+ ///
+ /// This returns an error if the string didn't contain a valid `bool`,
+ /// `u64`, `i64`, or `f64` literal, and couldn't be parsed as a regular
+ /// expression.
+ fn parse_regex(s: &str) -> Result<Self, matchers::Error> {
s.parse::<bool>()
.map(ValueMatch::Bool)
.or_else(|_| s.parse::<u64>().map(ValueMatch::U64))
@@ -212,6 +245,21 @@ impl FromStr for ValueMatch {
.map(|p| ValueMatch::Pat(Box::new(p)))
})
}
+
+ /// Parse a `ValueMatch` that will match `fmt::Debug` against a fixed
+ /// string.
+ ///
+ /// This does *not* return an error, because any string that isn't a valid
+ /// `bool`, `u64`, `i64`, or `f64` literal is treated as expected
+ /// `fmt::Debug` output.
+ fn parse_non_regex(s: &str) -> Self {
+ s.parse::<bool>()
+ .map(ValueMatch::Bool)
+ .or_else(|_| s.parse::<u64>().map(ValueMatch::U64))
+ .or_else(|_| s.parse::<i64>().map(ValueMatch::I64))
+ .or_else(|_| s.parse::<f64>().map(value_match_f64))
+ .unwrap_or_else(|_| ValueMatch::Debug(MatchDebug::new(s)))
+ }
}
impl fmt::Display for ValueMatch {
@@ -222,6 +270,7 @@ impl fmt::Display for ValueMatch {
ValueMatch::NaN => fmt::Display::fmt(&std::f64::NAN, f),
ValueMatch::I64(ref inner) => fmt::Display::fmt(inner, f),
ValueMatch::U64(ref inner) => fmt::Display::fmt(inner, f),
+ ValueMatch::Debug(ref inner) => fmt::Display::fmt(inner, f),
ValueMatch::Pat(ref inner) => fmt::Display::fmt(inner, f),
}
}
@@ -264,6 +313,12 @@ impl MatchPattern {
fn debug_matches(&self, d: &impl fmt::Debug) -> bool {
self.matcher.debug_matches(d)
}
+
+ pub(super) fn into_debug_match(self) -> MatchDebug {
+ MatchDebug {
+ pattern: self.pattern,
+ }
+ }
}
impl PartialEq for MatchPattern {
@@ -289,6 +344,102 @@ impl Ord for MatchPattern {
}
}
+// === impl MatchDebug ===
+
+impl MatchDebug {
+ fn new(s: &str) -> Self {
+ Self {
+ pattern: s.to_owned().into(),
+ }
+ }
+
+ #[inline]
+ fn debug_matches(&self, d: &impl fmt::Debug) -> bool {
+ // Naively, we would probably match a value's `fmt::Debug` output by
+ // formatting it to a string, and then checking if the string is equal
+ // to the expected pattern. However, this would require allocating every
+ // time we want to match a field value against a `Debug` matcher, which
+ // can be avoided.
+ //
+ // Instead, we implement `fmt::Write` for a type that, rather than
+ // actually _writing_ the strings to something, matches them against the
+ // expected pattern, and returns an error if the pattern does not match.
+ struct Matcher<'a> {
+ pattern: &'a str,
+ }
+
+ impl fmt::Write for Matcher<'_> {
+ fn write_str(&mut self, s: &str) -> fmt::Result {
+ // If the string is longer than the remaining expected string,
+ // we know it won't match, so bail.
+ if s.len() > self.pattern.len() {
+ return Err(fmt::Error);
+ }
+
+ // If the expected string begins with the string that was
+ // written, we are still potentially a match. Advance the
+ // position in the expected pattern to chop off the matched
+ // output, and continue.
+ if self.pattern.starts_with(s) {
+ self.pattern = &self.pattern[s.len()..];
+ return Ok(());
+ }
+
+ // Otherwise, the expected string doesn't include the string
+ // that was written at the current position, so the `fmt::Debug`
+ // output doesn't match! Return an error signalling that this
+ // doesn't match.
+ Err(fmt::Error)
+ }
+ }
+ let mut matcher = Matcher {
+ pattern: &self.pattern,
+ };
+
+ // Try to "write" the value's `fmt::Debug` output to a `Matcher`. This
+ // returns an error if the `fmt::Debug` implementation wrote any
+ // characters that did not match the expected pattern.
+ write!(matcher, "{:?}", d).is_ok()
+ }
+}
+
+impl fmt::Display for MatchDebug {
+ #[inline]
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ fmt::Display::fmt(&*self.pattern, f)
+ }
+}
+
+impl AsRef<str> for MatchDebug {
+ #[inline]
+ fn as_ref(&self) -> &str {
+ self.pattern.as_ref()
+ }
+}
+
+impl PartialEq for MatchDebug {
+ #[inline]
+ fn eq(&self, other: &Self) -> bool {
+ self.pattern == other.pattern
+ }
+}
+
+impl Eq for MatchDebug {}
+
+impl PartialOrd for MatchDebug {
+ #[inline]
+ fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
+ Some(self.pattern.cmp(&other.pattern))
+ }
+}
+
+impl Ord for MatchDebug {
+ #[inline]
+ fn cmp(&self, other: &Self) -> Ordering {
+ self.pattern.cmp(&other.pattern)
+ }
+}
+
// === impl BadName ===
impl Error for BadName {}
@@ -401,6 +552,9 @@ impl<'a> Visit for MatchVisitor<'a> {
Some((ValueMatch::Pat(ref e), ref matched)) if e.str_matches(&value) => {
matched.store(true, Release);
}
+ Some((ValueMatch::Debug(ref e), ref matched)) if e.debug_matches(&value) => {
+ matched.store(true, Release)
+ }
_ => {}
}
}
@@ -410,7 +564,63 @@ impl<'a> Visit for MatchVisitor<'a> {
Some((ValueMatch::Pat(ref e), ref matched)) if e.debug_matches(&value) => {
matched.store(true, Release);
}
+ Some((ValueMatch::Debug(ref e), ref matched)) if e.debug_matches(&value) => {
+ matched.store(true, Release)
+ }
_ => {}
}
}
}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+ #[derive(Debug)]
+ #[allow(dead_code)]
+ struct MyStruct {
+ answer: usize,
+ question: &'static str,
+ }
+
+ #[test]
+ fn debug_struct_match() {
+ let my_struct = MyStruct {
+ answer: 42,
+ question: "life, the universe, and everything",
+ };
+
+ let pattern = "MyStruct { answer: 42, question: \"life, the universe, and everything\" }";
+
+ assert_eq!(
+ format!("{:?}", my_struct),
+ pattern,
+ "`MyStruct`'s `Debug` impl doesn't output the expected string"
+ );
+
+ let matcher = MatchDebug {
+ pattern: pattern.into(),
+ };
+ assert!(matcher.debug_matches(&my_struct))
+ }
+
+ #[test]
+ fn debug_struct_not_match() {
+ let my_struct = MyStruct {
+ answer: 42,
+ question: "what shall we have for lunch?",
+ };
+
+ let pattern = "MyStruct { answer: 42, question: \"life, the universe, and everything\" }";
+
+ assert_eq!(
+ format!("{:?}", my_struct),
+ "MyStruct { answer: 42, question: \"what shall we have for lunch?\" }",
+ "`MyStruct`'s `Debug` impl doesn't output the expected string"
+ );
+
+ let matcher = MatchDebug {
+ pattern: pattern.into(),
+ };
+ assert!(!matcher.debug_matches(&my_struct))
+ }
+}
diff --git a/vendor/tracing-subscriber-0.3.3/src/filter/env/mod.rs b/vendor/tracing-subscriber/src/filter/env/mod.rs
index 81fe0e62d..81a9ae2bd 100644
--- a/vendor/tracing-subscriber-0.3.3/src/filter/env/mod.rs
+++ b/vendor/tracing-subscriber/src/filter/env/mod.rs
@@ -4,7 +4,8 @@
// these are publicly re-exported, but the compiler doesn't realize
// that for some reason.
#[allow(unreachable_pub)]
-pub use self::{directive::Directive, field::BadName as BadFieldName};
+pub use self::{builder::Builder, directive::Directive, field::BadName as BadFieldName};
+mod builder;
mod directive;
mod field;
@@ -15,6 +16,7 @@ use crate::{
};
use directive::ParseError;
use std::{cell::RefCell, collections::HashMap, env, error::Error, fmt, str::FromStr};
+use thread_local::ThreadLocal;
use tracing_core::{
callsite,
field::Field,
@@ -26,6 +28,16 @@ use tracing_core::{
/// A [`Layer`] which filters spans and events based on a set of filter
/// directives.
///
+/// `EnvFilter` implements both the [`Layer`](#impl-Layer<S>) and [`Filter`] traits, so it may
+/// be used for both [global filtering][global] and [per-layer filtering][plf],
+/// respectively. See [the documentation on filtering with `Layer`s][filtering]
+/// for details.
+///
+/// The [`Targets`] type implements a similar form of filtering, but without the
+/// ability to dynamically enable events based on the current span context, and
+/// without filtering on field values. When these features are not required,
+/// [`Targets`] provides a lighter-weight alternative to [`EnvFilter`].
+///
/// # Directives
///
/// A filter consists of one or more comma-separated directives which match on [`Span`]s and [`Event`]s.
@@ -52,10 +64,27 @@ use tracing_core::{
/// and will match on any [`Span`] or [`Event`] that has a field with that name.
/// For example: `[span{field=\"value\"}]=debug`, `[{field}]=trace`.
/// - `value` matches on the value of a span's field. If a value is a numeric literal or a bool,
-/// it will match _only_ on that value. Otherwise, this filter acts as a regex on
-/// the `std::fmt::Debug` output from the value.
+/// it will match _only_ on that value. Otherwise, this filter matches the
+/// [`std::fmt::Debug`] output from the value.
/// - `level` sets a maximum verbosity level accepted by this directive.
///
+/// When a field value directive (`[{<FIELD NAME>=<FIELD_VALUE>}]=...`) matches a
+/// value's [`std::fmt::Debug`] output (i.e., the field value in the directive
+/// is not a `bool`, `i64`, `u64`, or `f64` literal), the matched pattern may be
+/// interpreted as either a regular expression or as the precise expected
+/// output of the field's [`std::fmt::Debug`] implementation. By default, these
+/// filters are interpreted as regular expressions, but this can be disabled
+/// using the [`Builder::with_regex`] builder method to use precise matching
+/// instead.
+///
+/// When field value filters are interpreted as regular expressions, the
+/// [`regex-automata` crate's regular expression syntax][re-syntax] is
+/// supported.
+///
+/// **Note**: When filters are constructed from potentially untrusted inputs,
+/// [disabling regular expression matching](Builder::with_regex) is strongly
+/// recommended.
+///
/// ## Usage Notes
///
/// - The portion of the directive which is included within the square brackets is `tracing`-specific.
@@ -72,7 +101,7 @@ use tracing_core::{
/// - A dash in a target will only appear when being specified explicitly:
/// `tracing::info!(target: "target-name", ...);`
///
-/// ## Examples
+/// ## Example Syntax
///
/// - `tokio::net=info` will enable all spans or events that:
/// - have the `tokio::net` target,
@@ -89,10 +118,68 @@ use tracing_core::{
/// - which has a field named `name` with value `bob`,
/// - at _any_ level.
///
-/// The [`Targets`] type implements a similar form of filtering, but without the
-/// ability to dynamically enable events based on the current span context, and
-/// without filtering on field values. When these features are not required,
-/// [`Targets`] provides a lighter-weight alternative to [`EnvFilter`].
+/// # Examples
+///
+/// Parsing an `EnvFilter` from the [default environment
+/// variable](EnvFilter::from_default_env) (`RUST_LOG`):
+///
+/// ```
+/// use tracing_subscriber::{EnvFilter, fmt, prelude::*};
+///
+/// tracing_subscriber::registry()
+/// .with(fmt::layer())
+/// .with(EnvFilter::from_default_env())
+/// .init();
+/// ```
+///
+/// Parsing an `EnvFilter` [from a user-provided environment
+/// variable](EnvFilter::from_env):
+///
+/// ```
+/// use tracing_subscriber::{EnvFilter, fmt, prelude::*};
+///
+/// tracing_subscriber::registry()
+/// .with(fmt::layer())
+/// .with(EnvFilter::from_env("MYAPP_LOG"))
+/// .init();
+/// ```
+///
+/// Using `EnvFilter` as a [per-layer filter][plf] to filter only a single
+/// [`Layer`]:
+///
+/// ```
+/// use tracing_subscriber::{EnvFilter, fmt, prelude::*};
+///
+/// // Parse an `EnvFilter` configuration from the `RUST_LOG`
+/// // environment variable.
+/// let filter = EnvFilter::from_default_env();
+///
+/// // Apply the filter to this layer *only*.
+/// let filtered_layer = fmt::layer().with_filter(filter);
+///
+/// // Some other layer, whose output we don't want to filter.
+/// let unfiltered_layer = // ...
+/// # fmt::layer();
+///
+/// tracing_subscriber::registry()
+/// .with(filtered_layer)
+/// .with(unfiltered_layer)
+/// .init();
+/// ```
+/// # Constructing `EnvFilter`s
+///
+/// An `EnvFilter` is be constructed by parsing a string containing one or more
+/// directives. The [`EnvFilter::new`] constructor parses an `EnvFilter` from a
+/// string, ignoring any invalid directives, while [`EnvFilter::try_new`]
+/// returns an error if invalid directives are encountered. Similarly, the
+/// [`EnvFilter::from_env`] and [`EnvFilter::try_from_env`] constructors parse
+/// an `EnvFilter` from the value of the provided environment variable, with
+/// lossy and strict validation, respectively.
+///
+/// A [builder](EnvFilter::builder) interface is available to set additional
+/// configuration options prior to parsing an `EnvFilter`. See the [`Builder`
+/// type's documentation](Builder) for details on the options that can be
+/// configured using the builder.
///
/// [`Span`]: tracing_core::span
/// [fields]: tracing_core::Field
@@ -100,6 +187,11 @@ use tracing_core::{
/// [`level`]: tracing_core::Level
/// [`Metadata`]: tracing_core::Metadata
/// [`Targets`]: crate::filter::Targets
+/// [`env_logger`]: https://crates.io/crates/env_logger
+/// [`Filter`]: #impl-Filter<S>
+/// [global]: crate::layer#global-filtering
+/// [plf]: crate::layer#per-layer-filtering
+/// [filtering]: crate::layer#filtering-with-layers
#[cfg_attr(docsrs, doc(cfg(all(feature = "env-filter", feature = "std"))))]
#[derive(Debug)]
pub struct EnvFilter {
@@ -108,10 +200,8 @@ pub struct EnvFilter {
has_dynamics: bool,
by_id: RwLock<HashMap<span::Id, directive::SpanMatcher>>,
by_cs: RwLock<HashMap<callsite::Identifier, directive::CallsiteMatcher>>,
-}
-
-thread_local! {
- static SCOPE: RefCell<Vec<LevelFilter>> = RefCell::new(Vec::new());
+ scope: ThreadLocal<RefCell<Vec<LevelFilter>>>,
+ regex: bool,
}
type FieldMap<T> = HashMap<Field, T>;
@@ -134,58 +224,181 @@ impl EnvFilter {
/// `RUST_LOG` is the default environment variable used by
/// [`EnvFilter::from_default_env`] and [`EnvFilter::try_from_default_env`].
///
- /// [`EnvFilter::from_default_env`]: #method.from_default_env
- /// [`EnvFilter::try_from_default_env`]: #method.try_from_default_env
+ /// [`EnvFilter::from_default_env`]: EnvFilter::from_default_env()
+ /// [`EnvFilter::try_from_default_env`]: EnvFilter::try_from_default_env()
pub const DEFAULT_ENV: &'static str = "RUST_LOG";
+ // === constructors, etc ===
+
+ /// Returns a [builder] that can be used to configure a new [`EnvFilter`]
+ /// instance.
+ ///
+ /// The [`Builder`] type is used to set additional configurations, such as
+ /// [whether regular expressions are enabled](Builder::with_regex) or [the
+ /// default directive](Builder::with_default_directive) before parsing an
+ /// [`EnvFilter`] from a string or environment variable.
+ ///
+ /// [builder]: https://rust-unofficial.github.io/patterns/patterns/creational/builder.html
+ pub fn builder() -> Builder {
+ Builder::default()
+ }
+
/// Returns a new `EnvFilter` from the value of the `RUST_LOG` environment
/// variable, ignoring any invalid filter directives.
+ ///
+ /// If the environment variable is empty or not set, or if it contains only
+ /// invalid directives, a default directive enabling the [`ERROR`] level is
+ /// added.
+ ///
+ /// To set additional configuration options prior to parsing the filter, use
+ /// the [`Builder`] type instead.
+ ///
+ /// This function is equivalent to the following:
+ ///
+ /// ```rust
+ /// use tracing_subscriber::filter::{EnvFilter, LevelFilter};
+ ///
+ /// # fn docs() -> EnvFilter {
+ /// EnvFilter::builder()
+ /// .with_default_directive(LevelFilter::ERROR.into())
+ /// .from_env_lossy()
+ /// # }
+ /// ```
+ ///
+ /// [`ERROR`]: tracing::Level::ERROR
pub fn from_default_env() -> Self {
- Self::from_env(Self::DEFAULT_ENV)
+ Self::builder()
+ .with_default_directive(LevelFilter::ERROR.into())
+ .from_env_lossy()
}
/// Returns a new `EnvFilter` from the value of the given environment
/// variable, ignoring any invalid filter directives.
+ ///
+ /// If the environment variable is empty or not set, or if it contains only
+ /// invalid directives, a default directive enabling the [`ERROR`] level is
+ /// added.
+ ///
+ /// To set additional configuration options prior to parsing the filter, use
+ /// the [`Builder`] type instead.
+ ///
+ /// This function is equivalent to the following:
+ ///
+ /// ```rust
+ /// use tracing_subscriber::filter::{EnvFilter, LevelFilter};
+ ///
+ /// # fn docs() -> EnvFilter {
+ /// # let env = "";
+ /// EnvFilter::builder()
+ /// .with_default_directive(LevelFilter::ERROR.into())
+ /// .with_env_var(env)
+ /// .from_env_lossy()
+ /// # }
+ /// ```
+ ///
+ /// [`ERROR`]: tracing::Level::ERROR
pub fn from_env<A: AsRef<str>>(env: A) -> Self {
- env::var(env.as_ref()).map(Self::new).unwrap_or_default()
+ Self::builder()
+ .with_default_directive(LevelFilter::ERROR.into())
+ .with_env_var(env.as_ref())
+ .from_env_lossy()
}
/// Returns a new `EnvFilter` from the directives in the given string,
/// ignoring any that are invalid.
- pub fn new<S: AsRef<str>>(dirs: S) -> Self {
- let directives = dirs.as_ref().split(',').filter_map(|s| match s.parse() {
- Ok(d) => Some(d),
- Err(err) => {
- eprintln!("ignoring `{}`: {}", s, err);
- None
- }
- });
- Self::from_directives(directives)
+ ///
+ /// If the string is empty or contains only invalid directives, a default
+ /// directive enabling the [`ERROR`] level is added.
+ ///
+ /// To set additional configuration options prior to parsing the filter, use
+ /// the [`Builder`] type instead.
+ ///
+ /// This function is equivalent to the following:
+ ///
+ /// ```rust
+ /// use tracing_subscriber::filter::{EnvFilter, LevelFilter};
+ ///
+ /// # fn docs() -> EnvFilter {
+ /// # let directives = "";
+ /// EnvFilter::builder()
+ /// .with_default_directive(LevelFilter::ERROR.into())
+ /// .parse_lossy(directives)
+ /// # }
+ /// ```
+ ///
+ /// [`ERROR`]: tracing::Level::ERROR
+ pub fn new<S: AsRef<str>>(directives: S) -> Self {
+ Self::builder()
+ .with_default_directive(LevelFilter::ERROR.into())
+ .parse_lossy(directives)
}
/// Returns a new `EnvFilter` from the directives in the given string,
/// or an error if any are invalid.
+ ///
+ /// If the string is empty, a default directive enabling the [`ERROR`] level
+ /// is added.
+ ///
+ /// To set additional configuration options prior to parsing the filter, use
+ /// the [`Builder`] type instead.
+ ///
+ /// This function is equivalent to the following:
+ ///
+ /// ```rust
+ /// use tracing_subscriber::filter::{EnvFilter, LevelFilter};
+ ///
+ /// # fn docs() -> Result<EnvFilter, tracing_subscriber::filter::ParseError> {
+ /// # let directives = "";
+ /// EnvFilter::builder()
+ /// .with_default_directive(LevelFilter::ERROR.into())
+ /// .parse(directives)
+ /// # }
+ /// ```
+ ///
+ /// [`ERROR`]: tracing::Level::ERROR
pub fn try_new<S: AsRef<str>>(dirs: S) -> Result<Self, directive::ParseError> {
- let directives = dirs
- .as_ref()
- .split(',')
- .map(|s| s.parse())
- .collect::<Result<Vec<_>, _>>()?;
- Ok(Self::from_directives(directives))
+ Self::builder().parse(dirs)
}
/// Returns a new `EnvFilter` from the value of the `RUST_LOG` environment
- /// variable, or an error if the environment variable contains any invalid
- /// filter directives.
+ /// variable, or an error if the environment variable is unset or contains
+ /// any invalid filter directives.
+ ///
+ /// To set additional configuration options prior to parsing the filter, use
+ /// the [`Builder`] type instead.
+ ///
+ /// This function is equivalent to the following:
+ ///
+ /// ```rust
+ /// use tracing_subscriber::EnvFilter;
+ ///
+ /// # fn docs() -> Result<EnvFilter, tracing_subscriber::filter::FromEnvError> {
+ /// EnvFilter::builder().try_from_env()
+ /// # }
+ /// ```
pub fn try_from_default_env() -> Result<Self, FromEnvError> {
- Self::try_from_env(Self::DEFAULT_ENV)
+ Self::builder().try_from_env()
}
/// Returns a new `EnvFilter` from the value of the given environment
/// variable, or an error if the environment variable is unset or contains
/// any invalid filter directives.
+ ///
+ /// To set additional configuration options prior to parsing the filter, use
+ /// the [`Builder`] type instead.
+ ///
+ /// This function is equivalent to the following:
+ ///
+ /// ```rust
+ /// use tracing_subscriber::EnvFilter;
+ ///
+ /// # fn docs() -> Result<EnvFilter, tracing_subscriber::filter::FromEnvError> {
+ /// # let env = "";
+ /// EnvFilter::builder().with_env_var(env).try_from_env()
+ /// # }
+ /// ```
pub fn try_from_env<A: AsRef<str>>(env: A) -> Result<Self, FromEnvError> {
- env::var(env.as_ref())?.parse().map_err(Into::into)
+ Self::builder().with_env_var(env.as_ref()).try_from_env()
}
/// Add a filtering directive to this `EnvFilter`.
@@ -202,13 +415,13 @@ impl EnvFilter {
/// and events as a previous filter, but sets a different level for those
/// spans and events, the previous directive is overwritten.
///
- /// [`LevelFilter`]: ../filter/struct.LevelFilter.html
- /// [`Level`]: https://docs.rs/tracing-core/latest/tracing_core/struct.Level.html
+ /// [`LevelFilter`]: super::LevelFilter
+ /// [`Level`]: tracing_core::Level
///
/// # Examples
///
/// From [`LevelFilter`]:
- ////
+ ///
/// ```rust
/// use tracing_subscriber::filter::{EnvFilter, LevelFilter};
/// let mut filter = EnvFilter::from_default_env()
@@ -223,9 +436,9 @@ impl EnvFilter {
/// let mut filter = EnvFilter::from_default_env()
/// .add_directive(Level::INFO.into());
/// ```
- ////
+ ///
/// Parsed from a string:
- ////
+ ///
/// ```rust
/// use tracing_subscriber::filter::{EnvFilter, Directive};
///
@@ -236,7 +449,15 @@ impl EnvFilter {
/// # Ok(())
/// # }
/// ```
- pub fn add_directive(mut self, directive: Directive) -> Self {
+ /// In the above example, substitute `my_crate`, `module`, etc. with the
+ /// name your target crate/module is imported with. This might be
+ /// different from the package name in Cargo.toml (`-` is replaced by `_`).
+ /// Example, if the package name in your Cargo.toml is `MY-FANCY-LIB`, then
+ /// the corresponding Rust identifier would be `MY_FANCY_LIB`:
+ pub fn add_directive(mut self, mut directive: Directive) -> Self {
+ if !self.regex {
+ directive.deregexify();
+ }
if let Some(stat) = directive.to_static() {
self.statics.add(stat)
} else {
@@ -246,165 +467,19 @@ impl EnvFilter {
self
}
- fn from_directives(directives: impl IntoIterator<Item = Directive>) -> Self {
- use tracing::level_filters::STATIC_MAX_LEVEL;
- use tracing::Level;
-
- let directives: Vec<_> = directives.into_iter().collect();
-
- let disabled: Vec<_> = directives
- .iter()
- .filter(|directive| directive.level > STATIC_MAX_LEVEL)
- .collect();
-
- if !disabled.is_empty() {
- #[cfg(feature = "ansi_term")]
- use ansi_term::{Color, Style};
- // NOTE: We can't use a configured `MakeWriter` because the EnvFilter
- // has no knowledge of any underlying subscriber or subscriber, which
- // may or may not use a `MakeWriter`.
- let warn = |msg: &str| {
- #[cfg(not(feature = "ansi_term"))]
- let msg = format!("warning: {}", msg);
- #[cfg(feature = "ansi_term")]
- let msg = {
- let bold = Style::new().bold();
- let mut warning = Color::Yellow.paint("warning");
- warning.style_ref_mut().is_bold = true;
- format!("{}{} {}", warning, bold.paint(":"), bold.paint(msg))
- };
- eprintln!("{}", msg);
- };
- let ctx_prefixed = |prefix: &str, msg: &str| {
- #[cfg(not(feature = "ansi_term"))]
- let msg = format!("note: {}", msg);
- #[cfg(feature = "ansi_term")]
- let msg = {
- let mut equal = Color::Fixed(21).paint("="); // dark blue
- equal.style_ref_mut().is_bold = true;
- format!(" {} {} {}", equal, Style::new().bold().paint(prefix), msg)
- };
- eprintln!("{}", msg);
- };
- let ctx_help = |msg| ctx_prefixed("help:", msg);
- let ctx_note = |msg| ctx_prefixed("note:", msg);
- let ctx = |msg: &str| {
- #[cfg(not(feature = "ansi_term"))]
- let msg = format!("note: {}", msg);
- #[cfg(feature = "ansi_term")]
- let msg = {
- let mut pipe = Color::Fixed(21).paint("|");
- pipe.style_ref_mut().is_bold = true;
- format!(" {} {}", pipe, msg)
- };
- eprintln!("{}", msg);
- };
- warn("some trace filter directives would enable traces that are disabled statically");
- for directive in disabled {
- let target = if let Some(target) = &directive.target {
- format!("the `{}` target", target)
- } else {
- "all targets".into()
- };
- let level = directive
- .level
- .into_level()
- .expect("=off would not have enabled any filters");
- ctx(&format!(
- "`{}` would enable the {} level for {}",
- directive, level, target
- ));
- }
- ctx_note(&format!("the static max level is `{}`", STATIC_MAX_LEVEL));
- let help_msg = || {
- let (feature, filter) = match STATIC_MAX_LEVEL.into_level() {
- Some(Level::TRACE) => unreachable!(
- "if the max level is trace, no static filtering features are enabled"
- ),
- Some(Level::DEBUG) => ("max_level_debug", Level::TRACE),
- Some(Level::INFO) => ("max_level_info", Level::DEBUG),
- Some(Level::WARN) => ("max_level_warn", Level::INFO),
- Some(Level::ERROR) => ("max_level_error", Level::WARN),
- None => return ("max_level_off", String::new()),
- };
- (feature, format!("{} ", filter))
- };
- let (feature, earlier_level) = help_msg();
- ctx_help(&format!(
- "to enable {}logging, remove the `{}` feature",
- earlier_level, feature
- ));
- }
-
- let (dynamics, mut statics) = Directive::make_tables(directives);
- let has_dynamics = !dynamics.is_empty();
-
- if statics.is_empty() && !has_dynamics {
- statics.add(directive::StaticDirective::default());
- }
-
- Self {
- statics,
- dynamics,
- has_dynamics,
- by_id: RwLock::new(HashMap::new()),
- by_cs: RwLock::new(HashMap::new()),
- }
- }
-
- fn cares_about_span(&self, span: &span::Id) -> bool {
- let spans = try_lock!(self.by_id.read(), else return false);
- spans.contains_key(span)
- }
-
- fn base_interest(&self) -> Interest {
- if self.has_dynamics {
- Interest::sometimes()
- } else {
- Interest::never()
- }
- }
-}
-
-impl<S: Subscriber> Layer<S> for EnvFilter {
- fn register_callsite(&self, metadata: &'static Metadata<'static>) -> Interest {
- if self.has_dynamics && metadata.is_span() {
- // If this metadata describes a span, first, check if there is a
- // dynamic filter that should be constructed for it. If so, it
- // should always be enabled, since it influences filtering.
- if let Some(matcher) = self.dynamics.matcher(metadata) {
- let mut by_cs = try_lock!(self.by_cs.write(), else return self.base_interest());
- by_cs.insert(metadata.callsite(), matcher);
- return Interest::always();
- }
- }
-
- // Otherwise, check if any of our static filters enable this metadata.
- if self.statics.enabled(metadata) {
- Interest::always()
- } else {
- self.base_interest()
- }
- }
-
- fn max_level_hint(&self) -> Option<LevelFilter> {
- if self.dynamics.has_value_filters() {
- // If we perform any filtering on span field *values*, we will
- // enable *all* spans, because their field values are not known
- // until recording.
- return Some(LevelFilter::TRACE);
- }
- std::cmp::max(
- self.statics.max_level.into(),
- self.dynamics.max_level.into(),
- )
- }
+ // === filtering methods ===
- fn enabled(&self, metadata: &Metadata<'_>, _: Context<'_, S>) -> bool {
+ /// Returns `true` if this `EnvFilter` would enable the provided `metadata`
+ /// in the current context.
+ ///
+ /// This is equivalent to calling the [`Layer::enabled`] or
+ /// [`Filter::enabled`] methods on `EnvFilter`'s implementations of those
+ /// traits, but it does not require the trait to be in scope.
+ pub fn enabled<S>(&self, metadata: &Metadata<'_>, _: Context<'_, S>) -> bool {
let level = metadata.level();
// is it possible for a dynamic filter directive to enable this event?
- // if not, we can avoid the thread local access + iterating over the
+ // if not, we can avoid the thread loca'l access + iterating over the
// spans in the current scope.
if self.has_dynamics && self.dynamics.max_level >= *level {
if metadata.is_span() {
@@ -420,14 +495,15 @@ impl<S: Subscriber> Layer<S> for EnvFilter {
}
}
- let enabled_by_scope = SCOPE.with(|scope| {
- for filter in scope.borrow().iter() {
+ let enabled_by_scope = {
+ let scope = self.scope.get_or_default().borrow();
+ for filter in &*scope {
if filter >= level {
return true;
}
}
false
- });
+ };
if enabled_by_scope {
return true;
}
@@ -443,7 +519,33 @@ impl<S: Subscriber> Layer<S> for EnvFilter {
false
}
- fn on_new_span(&self, attrs: &span::Attributes<'_>, id: &span::Id, _: Context<'_, S>) {
+ /// Returns an optional hint of the highest [verbosity level][level] that
+ /// this `EnvFilter` will enable.
+ ///
+ /// This is equivalent to calling the [`Layer::max_level_hint`] or
+ /// [`Filter::max_level_hint`] methods on `EnvFilter`'s implementations of those
+ /// traits, but it does not require the trait to be in scope.
+ ///
+ /// [level]: tracing_core::metadata::Level
+ pub fn max_level_hint(&self) -> Option<LevelFilter> {
+ if self.dynamics.has_value_filters() {
+ // If we perform any filtering on span field *values*, we will
+ // enable *all* spans, because their field values are not known
+ // until recording.
+ return Some(LevelFilter::TRACE);
+ }
+ std::cmp::max(
+ self.statics.max_level.into(),
+ self.dynamics.max_level.into(),
+ )
+ }
+
+ /// Informs the filter that a new span was created.
+ ///
+ /// This is equivalent to calling the [`Layer::on_new_span`] or
+ /// [`Filter::on_new_span`] methods on `EnvFilter`'s implementations of those
+ /// traits, but it does not require the trait to be in scope.
+ pub fn on_new_span<S>(&self, attrs: &span::Attributes<'_>, id: &span::Id, _: Context<'_, S>) {
let by_cs = try_lock!(self.by_cs.read());
if let Some(cs) = by_cs.get(&attrs.metadata().callsite()) {
let span = cs.to_span_match(attrs);
@@ -451,28 +553,37 @@ impl<S: Subscriber> Layer<S> for EnvFilter {
}
}
- fn on_record(&self, id: &span::Id, values: &span::Record<'_>, _: Context<'_, S>) {
- if let Some(span) = try_lock!(self.by_id.read()).get(id) {
- span.record_update(values);
- }
- }
-
- fn on_enter(&self, id: &span::Id, _: Context<'_, S>) {
+ /// Informs the filter that the span with the provided `id` was entered.
+ ///
+ /// This is equivalent to calling the [`Layer::on_enter`] or
+ /// [`Filter::on_enter`] methods on `EnvFilter`'s implementations of those
+ /// traits, but it does not require the trait to be in scope.
+ pub fn on_enter<S>(&self, id: &span::Id, _: Context<'_, S>) {
// XXX: This is where _we_ could push IDs to the stack instead, and use
// that to allow changing the filter while a span is already entered.
// But that might be much less efficient...
if let Some(span) = try_lock!(self.by_id.read()).get(id) {
- SCOPE.with(|scope| scope.borrow_mut().push(span.level()));
+ self.scope.get_or_default().borrow_mut().push(span.level());
}
}
- fn on_exit(&self, id: &span::Id, _: Context<'_, S>) {
+ /// Informs the filter that the span with the provided `id` was exited.
+ ///
+ /// This is equivalent to calling the [`Layer::on_exit`] or
+ /// [`Filter::on_exit`] methods on `EnvFilter`'s implementations of those
+ /// traits, but it does not require the trait to be in scope.
+ pub fn on_exit<S>(&self, id: &span::Id, _: Context<'_, S>) {
if self.cares_about_span(id) {
- SCOPE.with(|scope| scope.borrow_mut().pop());
+ self.scope.get_or_default().borrow_mut().pop();
}
}
- fn on_close(&self, id: span::Id, _: Context<'_, S>) {
+ /// Informs the filter that the span with the provided `id` was closed.
+ ///
+ /// This is equivalent to calling the [`Layer::on_close`] or
+ /// [`Filter::on_close`] methods on `EnvFilter`'s implementations of those
+ /// traits, but it does not require the trait to be in scope.
+ pub fn on_close<S>(&self, id: span::Id, _: Context<'_, S>) {
// If we don't need to acquire a write lock, avoid doing so.
if !self.cares_about_span(&id) {
return;
@@ -481,6 +592,140 @@ impl<S: Subscriber> Layer<S> for EnvFilter {
let mut spans = try_lock!(self.by_id.write());
spans.remove(&id);
}
+
+ /// Informs the filter that the span with the provided `id` recorded the
+ /// provided field `values`.
+ ///
+ /// This is equivalent to calling the [`Layer::on_record`] or
+ /// [`Filter::on_record`] methods on `EnvFilter`'s implementations of those
+ /// traits, but it does not require the trait to be in scope
+ pub fn on_record<S>(&self, id: &span::Id, values: &span::Record<'_>, _: Context<'_, S>) {
+ if let Some(span) = try_lock!(self.by_id.read()).get(id) {
+ span.record_update(values);
+ }
+ }
+
+ fn cares_about_span(&self, span: &span::Id) -> bool {
+ let spans = try_lock!(self.by_id.read(), else return false);
+ spans.contains_key(span)
+ }
+
+ fn base_interest(&self) -> Interest {
+ if self.has_dynamics {
+ Interest::sometimes()
+ } else {
+ Interest::never()
+ }
+ }
+
+ fn register_callsite(&self, metadata: &'static Metadata<'static>) -> Interest {
+ if self.has_dynamics && metadata.is_span() {
+ // If this metadata describes a span, first, check if there is a
+ // dynamic filter that should be constructed for it. If so, it
+ // should always be enabled, since it influences filtering.
+ if let Some(matcher) = self.dynamics.matcher(metadata) {
+ let mut by_cs = try_lock!(self.by_cs.write(), else return self.base_interest());
+ by_cs.insert(metadata.callsite(), matcher);
+ return Interest::always();
+ }
+ }
+
+ // Otherwise, check if any of our static filters enable this metadata.
+ if self.statics.enabled(metadata) {
+ Interest::always()
+ } else {
+ self.base_interest()
+ }
+ }
+}
+
+impl<S: Subscriber> Layer<S> for EnvFilter {
+ #[inline]
+ fn register_callsite(&self, metadata: &'static Metadata<'static>) -> Interest {
+ EnvFilter::register_callsite(self, metadata)
+ }
+
+ #[inline]
+ fn max_level_hint(&self) -> Option<LevelFilter> {
+ EnvFilter::max_level_hint(self)
+ }
+
+ #[inline]
+ fn enabled(&self, metadata: &Metadata<'_>, ctx: Context<'_, S>) -> bool {
+ self.enabled(metadata, ctx)
+ }
+
+ #[inline]
+ fn on_new_span(&self, attrs: &span::Attributes<'_>, id: &span::Id, ctx: Context<'_, S>) {
+ self.on_new_span(attrs, id, ctx)
+ }
+
+ #[inline]
+ fn on_record(&self, id: &span::Id, values: &span::Record<'_>, ctx: Context<'_, S>) {
+ self.on_record(id, values, ctx);
+ }
+
+ #[inline]
+ fn on_enter(&self, id: &span::Id, ctx: Context<'_, S>) {
+ self.on_enter(id, ctx);
+ }
+
+ #[inline]
+ fn on_exit(&self, id: &span::Id, ctx: Context<'_, S>) {
+ self.on_exit(id, ctx);
+ }
+
+ #[inline]
+ fn on_close(&self, id: span::Id, ctx: Context<'_, S>) {
+ self.on_close(id, ctx);
+ }
+}
+
+feature! {
+ #![all(feature = "registry", feature = "std")]
+ use crate::layer::Filter;
+
+ impl<S> Filter<S> for EnvFilter {
+ #[inline]
+ fn enabled(&self, meta: &Metadata<'_>, ctx: &Context<'_, S>) -> bool {
+ self.enabled(meta, ctx.clone())
+ }
+
+ #[inline]
+ fn callsite_enabled(&self, meta: &'static Metadata<'static>) -> Interest {
+ self.register_callsite(meta)
+ }
+
+ #[inline]
+ fn max_level_hint(&self) -> Option<LevelFilter> {
+ EnvFilter::max_level_hint(self)
+ }
+
+ #[inline]
+ fn on_new_span(&self, attrs: &span::Attributes<'_>, id: &span::Id, ctx: Context<'_, S>) {
+ self.on_new_span(attrs, id, ctx)
+ }
+
+ #[inline]
+ fn on_record(&self, id: &span::Id, values: &span::Record<'_>, ctx: Context<'_, S>) {
+ self.on_record(id, values, ctx);
+ }
+
+ #[inline]
+ fn on_enter(&self, id: &span::Id, ctx: Context<'_, S>) {
+ self.on_enter(id, ctx);
+ }
+
+ #[inline]
+ fn on_exit(&self, id: &span::Id, ctx: Context<'_, S>) {
+ self.on_exit(id, ctx);
+ }
+
+ #[inline]
+ fn on_close(&self, id: span::Id, ctx: Context<'_, S>) {
+ self.on_close(id, ctx);
+ }
+ }
}
impl FromStr for EnvFilter {
@@ -502,7 +747,7 @@ where
impl Default for EnvFilter {
fn default() -> Self {
- Self::from_directives(std::iter::empty())
+ Builder::default().from_directives(std::iter::empty())
}
}
@@ -735,4 +980,12 @@ mod tests {
[span2{bar=2 baz=false}],crate2[{quux=\"quuux\"}]=debug",
);
}
+
+ #[test]
+ fn parse_empty_string() {
+ // There is no corresponding test for [`Builder::parse_lossy`] as failed
+ // parsing does not produce any observable side effects. If this test fails
+ // check that [`Builder::parse_lossy`] is behaving correctly as well.
+ assert!(EnvFilter::builder().parse("").is_ok());
+ }
}
diff --git a/vendor/tracing-subscriber-0.3.3/src/filter/filter_fn.rs b/vendor/tracing-subscriber/src/filter/filter_fn.rs
index 332bf860a..332bf860a 100644
--- a/vendor/tracing-subscriber-0.3.3/src/filter/filter_fn.rs
+++ b/vendor/tracing-subscriber/src/filter/filter_fn.rs
diff --git a/vendor/tracing-subscriber/src/filter/layer_filters/combinator.rs b/vendor/tracing-subscriber/src/filter/layer_filters/combinator.rs
new file mode 100644
index 000000000..3934a1326
--- /dev/null
+++ b/vendor/tracing-subscriber/src/filter/layer_filters/combinator.rs
@@ -0,0 +1,542 @@
+//! Filter combinators
+use crate::layer::{Context, Filter};
+use std::{cmp, fmt, marker::PhantomData};
+use tracing_core::{
+ span::{Attributes, Id, Record},
+ subscriber::Interest,
+ LevelFilter, Metadata,
+};
+
+/// Combines two [`Filter`]s so that spans and events are enabled if and only if
+/// *both* filters return `true`.
+///
+/// This type is typically returned by the [`FilterExt::and`] method. See that
+/// method's documentation for details.
+///
+/// [`Filter`]: crate::layer::Filter
+/// [`FilterExt::and`]: crate::filter::FilterExt::and
+pub struct And<A, B, S> {
+ a: A,
+ b: B,
+ _s: PhantomData<fn(S)>,
+}
+
+/// Combines two [`Filter`]s so that spans and events are enabled if *either* filter
+/// returns `true`.
+///
+/// This type is typically returned by the [`FilterExt::or`] method. See that
+/// method's documentation for details.
+///
+/// [`Filter`]: crate::layer::Filter
+/// [`FilterExt::or`]: crate::filter::FilterExt::or
+pub struct Or<A, B, S> {
+ a: A,
+ b: B,
+ _s: PhantomData<fn(S)>,
+}
+
+/// Inverts the result of a [`Filter`].
+///
+/// If the wrapped filter would enable a span or event, it will be disabled. If
+/// it would disable a span or event, that span or event will be enabled.
+///
+/// This type is typically returned by the [`FilterExt::not`] method. See that
+/// method's documentation for details.
+///
+/// [`Filter`]: crate::layer::Filter
+/// [`FilterExt::not`]: crate::filter::FilterExt::not
+pub struct Not<A, S> {
+ a: A,
+ _s: PhantomData<fn(S)>,
+}
+
+// === impl And ===
+
+impl<A, B, S> And<A, B, S>
+where
+ A: Filter<S>,
+ B: Filter<S>,
+{
+ /// Combines two [`Filter`]s so that spans and events are enabled if and only if
+ /// *both* filters return `true`.
+ ///
+ /// # Examples
+ ///
+ /// Enabling spans or events if they have both a particular target *and* are
+ /// above a certain level:
+ ///
+ /// ```ignore
+ /// use tracing_subscriber::{
+ /// filter::{filter_fn, LevelFilter, combinator::And},
+ /// prelude::*,
+ /// };
+ ///
+ /// // Enables spans and events with targets starting with `interesting_target`:
+ /// let target_filter = filter_fn(|meta| {
+ /// meta.target().starts_with("interesting_target")
+ /// });
+ ///
+ /// // Enables spans and events with levels `INFO` and below:
+ /// let level_filter = LevelFilter::INFO;
+ ///
+ /// // Combine the two filters together so that a span or event is only enabled
+ /// // if *both* filters would enable it:
+ /// let filter = And::new(level_filter, target_filter);
+ ///
+ /// tracing_subscriber::registry()
+ /// .with(tracing_subscriber::fmt::layer().with_filter(filter))
+ /// .init();
+ ///
+ /// // This event will *not* be enabled:
+ /// tracing::info!("an event with an uninteresting target");
+ ///
+ /// // This event *will* be enabled:
+ /// tracing::info!(target: "interesting_target", "a very interesting event");
+ ///
+ /// // This event will *not* be enabled:
+ /// tracing::debug!(target: "interesting_target", "interesting debug event...");
+ /// ```
+ ///
+ /// [`Filter`]: crate::layer::Filter
+ pub(crate) fn new(a: A, b: B) -> Self {
+ Self {
+ a,
+ b,
+ _s: PhantomData,
+ }
+ }
+}
+
+impl<A, B, S> Filter<S> for And<A, B, S>
+where
+ A: Filter<S>,
+ B: Filter<S>,
+{
+ #[inline]
+ fn enabled(&self, meta: &Metadata<'_>, cx: &Context<'_, S>) -> bool {
+ self.a.enabled(meta, cx) && self.b.enabled(meta, cx)
+ }
+
+ fn callsite_enabled(&self, meta: &'static Metadata<'static>) -> Interest {
+ let a = self.a.callsite_enabled(meta);
+ if a.is_never() {
+ return a;
+ }
+
+ let b = self.b.callsite_enabled(meta);
+
+ if !b.is_always() {
+ return b;
+ }
+
+ a
+ }
+
+ fn max_level_hint(&self) -> Option<LevelFilter> {
+ // If either hint is `None`, return `None`. Otherwise, return the most restrictive.
+ cmp::min(self.a.max_level_hint(), self.b.max_level_hint())
+ }
+
+ #[inline]
+ fn event_enabled(&self, event: &tracing_core::Event<'_>, cx: &Context<'_, S>) -> bool {
+ self.a.event_enabled(event, cx) && self.b.event_enabled(event, cx)
+ }
+
+ #[inline]
+ fn on_new_span(&self, attrs: &Attributes<'_>, id: &Id, ctx: Context<'_, S>) {
+ self.a.on_new_span(attrs, id, ctx.clone());
+ self.b.on_new_span(attrs, id, ctx)
+ }
+
+ #[inline]
+ fn on_record(&self, id: &Id, values: &Record<'_>, ctx: Context<'_, S>) {
+ self.a.on_record(id, values, ctx.clone());
+ self.b.on_record(id, values, ctx);
+ }
+
+ #[inline]
+ fn on_enter(&self, id: &Id, ctx: Context<'_, S>) {
+ self.a.on_enter(id, ctx.clone());
+ self.b.on_enter(id, ctx);
+ }
+
+ #[inline]
+ fn on_exit(&self, id: &Id, ctx: Context<'_, S>) {
+ self.a.on_exit(id, ctx.clone());
+ self.b.on_exit(id, ctx);
+ }
+
+ #[inline]
+ fn on_close(&self, id: Id, ctx: Context<'_, S>) {
+ self.a.on_close(id.clone(), ctx.clone());
+ self.b.on_close(id, ctx);
+ }
+}
+
+impl<A, B, S> Clone for And<A, B, S>
+where
+ A: Clone,
+ B: Clone,
+{
+ fn clone(&self) -> Self {
+ Self {
+ a: self.a.clone(),
+ b: self.b.clone(),
+ _s: PhantomData,
+ }
+ }
+}
+
+impl<A, B, S> fmt::Debug for And<A, B, S>
+where
+ A: fmt::Debug,
+ B: fmt::Debug,
+{
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ f.debug_struct("And")
+ .field("a", &self.a)
+ .field("b", &self.b)
+ .finish()
+ }
+}
+
+// === impl Or ===
+
+impl<A, B, S> Or<A, B, S>
+where
+ A: Filter<S>,
+ B: Filter<S>,
+{
+ /// Combines two [`Filter`]s so that spans and events are enabled if *either* filter
+ /// returns `true`.
+ ///
+ /// # Examples
+ ///
+ /// Enabling spans and events at the `INFO` level and above, and all spans
+ /// and events with a particular target:
+ ///
+ /// ```ignore
+ /// use tracing_subscriber::{
+ /// filter::{filter_fn, LevelFilter, combinator::Or},
+ /// prelude::*,
+ /// };
+ ///
+ /// // Enables spans and events with targets starting with `interesting_target`:
+ /// let target_filter = filter_fn(|meta| {
+ /// meta.target().starts_with("interesting_target")
+ /// });
+ ///
+ /// // Enables spans and events with levels `INFO` and below:
+ /// let level_filter = LevelFilter::INFO;
+ ///
+ /// // Combine the two filters together so that a span or event is enabled
+ /// // if it is at INFO or lower, or if it has a target starting with
+ /// // `interesting_target`.
+ /// let filter = Or::new(level_filter, target_filter);
+ ///
+ /// tracing_subscriber::registry()
+ /// .with(tracing_subscriber::fmt::layer().with_filter(filter))
+ /// .init();
+ ///
+ /// // This event will *not* be enabled:
+ /// tracing::debug!("an uninteresting event");
+ ///
+ /// // This event *will* be enabled:
+ /// tracing::info!("an uninteresting INFO event");
+ ///
+ /// // This event *will* be enabled:
+ /// tracing::info!(target: "interesting_target", "a very interesting event");
+ ///
+ /// // This event *will* be enabled:
+ /// tracing::debug!(target: "interesting_target", "interesting debug event...");
+ /// ```
+ ///
+ /// Enabling a higher level for a particular target by using `Or` in
+ /// conjunction with the [`And`] combinator:
+ ///
+ /// ```ignore
+ /// use tracing_subscriber::{
+ /// filter::{filter_fn, LevelFilter, combinator},
+ /// prelude::*,
+ /// };
+ ///
+ /// // This filter will enable spans and events with targets beginning with
+ /// // `my_crate`:
+ /// let my_crate = filter_fn(|meta| {
+ /// meta.target().starts_with("my_crate")
+ /// });
+ ///
+ /// // Combine the `my_crate` filter with a `LevelFilter` to produce a filter
+ /// // that will enable the `INFO` level and lower for spans and events with
+ /// // `my_crate` targets:
+ /// let filter = combinator::And::new(my_crate, LevelFilter::INFO);
+ ///
+ /// // If a span or event *doesn't* have a target beginning with
+ /// // `my_crate`, enable it if it has the `WARN` level or lower:
+ /// // let filter = combinator::Or::new(filter, LevelFilter::WARN);
+ ///
+ /// tracing_subscriber::registry()
+ /// .with(tracing_subscriber::fmt::layer().with_filter(filter))
+ /// .init();
+ /// ```
+ ///
+ /// [`Filter`]: crate::layer::Filter
+ pub(crate) fn new(a: A, b: B) -> Self {
+ Self {
+ a,
+ b,
+ _s: PhantomData,
+ }
+ }
+}
+
+impl<A, B, S> Filter<S> for Or<A, B, S>
+where
+ A: Filter<S>,
+ B: Filter<S>,
+{
+ #[inline]
+ fn enabled(&self, meta: &Metadata<'_>, cx: &Context<'_, S>) -> bool {
+ self.a.enabled(meta, cx) || self.b.enabled(meta, cx)
+ }
+
+ fn callsite_enabled(&self, meta: &'static Metadata<'static>) -> Interest {
+ let a = self.a.callsite_enabled(meta);
+ let b = self.b.callsite_enabled(meta);
+
+ // If either filter will always enable the span or event, return `always`.
+ if a.is_always() || b.is_always() {
+ return Interest::always();
+ }
+
+ // Okay, if either filter will sometimes enable the span or event,
+ // return `sometimes`.
+ if a.is_sometimes() || b.is_sometimes() {
+ return Interest::sometimes();
+ }
+
+ debug_assert!(
+ a.is_never() && b.is_never(),
+ "if neither filter was `always` or `sometimes`, both must be `never` (a={:?}; b={:?})",
+ a,
+ b,
+ );
+ Interest::never()
+ }
+
+ fn max_level_hint(&self) -> Option<LevelFilter> {
+ // If either hint is `None`, return `None`. Otherwise, return the less restrictive.
+ Some(cmp::max(self.a.max_level_hint()?, self.b.max_level_hint()?))
+ }
+
+ #[inline]
+ fn event_enabled(&self, event: &tracing_core::Event<'_>, cx: &Context<'_, S>) -> bool {
+ self.a.event_enabled(event, cx) || self.b.event_enabled(event, cx)
+ }
+
+ #[inline]
+ fn on_new_span(&self, attrs: &Attributes<'_>, id: &Id, ctx: Context<'_, S>) {
+ self.a.on_new_span(attrs, id, ctx.clone());
+ self.b.on_new_span(attrs, id, ctx)
+ }
+
+ #[inline]
+ fn on_record(&self, id: &Id, values: &Record<'_>, ctx: Context<'_, S>) {
+ self.a.on_record(id, values, ctx.clone());
+ self.b.on_record(id, values, ctx);
+ }
+
+ #[inline]
+ fn on_enter(&self, id: &Id, ctx: Context<'_, S>) {
+ self.a.on_enter(id, ctx.clone());
+ self.b.on_enter(id, ctx);
+ }
+
+ #[inline]
+ fn on_exit(&self, id: &Id, ctx: Context<'_, S>) {
+ self.a.on_exit(id, ctx.clone());
+ self.b.on_exit(id, ctx);
+ }
+
+ #[inline]
+ fn on_close(&self, id: Id, ctx: Context<'_, S>) {
+ self.a.on_close(id.clone(), ctx.clone());
+ self.b.on_close(id, ctx);
+ }
+}
+
+impl<A, B, S> Clone for Or<A, B, S>
+where
+ A: Clone,
+ B: Clone,
+{
+ fn clone(&self) -> Self {
+ Self {
+ a: self.a.clone(),
+ b: self.b.clone(),
+ _s: PhantomData,
+ }
+ }
+}
+
+impl<A, B, S> fmt::Debug for Or<A, B, S>
+where
+ A: fmt::Debug,
+ B: fmt::Debug,
+{
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ f.debug_struct("Or")
+ .field("a", &self.a)
+ .field("b", &self.b)
+ .finish()
+ }
+}
+
+// === impl Not ===
+
+impl<A, S> Not<A, S>
+where
+ A: Filter<S>,
+{
+ /// Inverts the result of a [`Filter`].
+ ///
+ /// If the wrapped filter would enable a span or event, it will be disabled. If
+ /// it would disable a span or event, that span or event will be enabled.
+ ///
+ /// This inverts the values returned by the [`enabled`] and [`callsite_enabled`]
+ /// methods on the wrapped filter; it does *not* invert [`event_enabled`], as
+ /// filters which do not implement filtering on event field values will return
+ /// the default `true` even for events that their [`enabled`] method disables.
+ ///
+ /// Consider a normal filter defined as:
+ ///
+ /// ```ignore (pseudo-code)
+ /// // for spans
+ /// match callsite_enabled() {
+ /// ALWAYS => on_span(),
+ /// SOMETIMES => if enabled() { on_span() },
+ /// NEVER => (),
+ /// }
+ /// // for events
+ /// match callsite_enabled() {
+ /// ALWAYS => on_event(),
+ /// SOMETIMES => if enabled() && event_enabled() { on_event() },
+ /// NEVER => (),
+ /// }
+ /// ```
+ ///
+ /// and an inverted filter defined as:
+ ///
+ /// ```ignore (pseudo-code)
+ /// // for spans
+ /// match callsite_enabled() {
+ /// ALWAYS => (),
+ /// SOMETIMES => if !enabled() { on_span() },
+ /// NEVER => on_span(),
+ /// }
+ /// // for events
+ /// match callsite_enabled() {
+ /// ALWAYS => (),
+ /// SOMETIMES => if !enabled() { on_event() },
+ /// NEVER => on_event(),
+ /// }
+ /// ```
+ ///
+ /// A proper inversion would do `!(enabled() && event_enabled())` (or
+ /// `!enabled() || !event_enabled()`), but because of the implicit `&&`
+ /// relation between `enabled` and `event_enabled`, it is difficult to
+ /// short circuit and not call the wrapped `event_enabled`.
+ ///
+ /// A combinator which remembers the result of `enabled` in order to call
+ /// `event_enabled` only when `enabled() == true` is possible, but requires
+ /// additional thread-local mutable state to support a very niche use case.
+ //
+ // Also, it'd mean the wrapped layer's `enabled()` always gets called and
+ // globally applied to events where it doesn't today, since we can't know
+ // what `event_enabled` will say until we have the event to call it with.
+ ///
+ /// [`Filter`]: crate::layer::Filter
+ /// [`enabled`]: crate::layer::Filter::enabled
+ /// [`event_enabled`]: crate::layer::Filter::event_enabled
+ /// [`callsite_enabled`]: crate::layer::Filter::callsite_enabled
+ pub(crate) fn new(a: A) -> Self {
+ Self { a, _s: PhantomData }
+ }
+}
+
+impl<A, S> Filter<S> for Not<A, S>
+where
+ A: Filter<S>,
+{
+ #[inline]
+ fn enabled(&self, meta: &Metadata<'_>, cx: &Context<'_, S>) -> bool {
+ !self.a.enabled(meta, cx)
+ }
+
+ fn callsite_enabled(&self, meta: &'static Metadata<'static>) -> Interest {
+ match self.a.callsite_enabled(meta) {
+ i if i.is_always() => Interest::never(),
+ i if i.is_never() => Interest::always(),
+ _ => Interest::sometimes(),
+ }
+ }
+
+ fn max_level_hint(&self) -> Option<LevelFilter> {
+ // TODO(eliza): figure this out???
+ None
+ }
+
+ #[inline]
+ fn event_enabled(&self, event: &tracing_core::Event<'_>, cx: &Context<'_, S>) -> bool {
+ // Never disable based on event_enabled; we "disabled" it in `enabled`,
+ // so the `not` has already been applied and filtered this not out.
+ let _ = (event, cx);
+ true
+ }
+
+ #[inline]
+ fn on_new_span(&self, attrs: &Attributes<'_>, id: &Id, ctx: Context<'_, S>) {
+ self.a.on_new_span(attrs, id, ctx);
+ }
+
+ #[inline]
+ fn on_record(&self, id: &Id, values: &Record<'_>, ctx: Context<'_, S>) {
+ self.a.on_record(id, values, ctx.clone());
+ }
+
+ #[inline]
+ fn on_enter(&self, id: &Id, ctx: Context<'_, S>) {
+ self.a.on_enter(id, ctx);
+ }
+
+ #[inline]
+ fn on_exit(&self, id: &Id, ctx: Context<'_, S>) {
+ self.a.on_exit(id, ctx);
+ }
+
+ #[inline]
+ fn on_close(&self, id: Id, ctx: Context<'_, S>) {
+ self.a.on_close(id, ctx);
+ }
+}
+
+impl<A, S> Clone for Not<A, S>
+where
+ A: Clone,
+{
+ fn clone(&self) -> Self {
+ Self {
+ a: self.a.clone(),
+ _s: PhantomData,
+ }
+ }
+}
+
+impl<A, S> fmt::Debug for Not<A, S>
+where
+ A: fmt::Debug,
+{
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ f.debug_tuple("Not").field(&self.a).finish()
+ }
+}
diff --git a/vendor/tracing-subscriber-0.3.3/src/filter/layer_filters.rs b/vendor/tracing-subscriber/src/filter/layer_filters/mod.rs
index e77fd3751..e50ee6f00 100644
--- a/vendor/tracing-subscriber-0.3.3/src/filter/layer_filters.rs
+++ b/vendor/tracing-subscriber/src/filter/layer_filters/mod.rs
@@ -37,14 +37,16 @@ use std::{
cell::{Cell, RefCell},
fmt,
marker::PhantomData,
+ ops::Deref,
sync::Arc,
thread_local,
};
use tracing_core::{
span,
subscriber::{Interest, Subscriber},
- Event, Metadata,
+ Dispatch, Event, Metadata,
};
+pub mod combinator;
/// A [`Layer`] that wraps an inner [`Layer`] and adds a [`Filter`] which
/// controls what spans and events are enabled for that layer.
@@ -158,7 +160,288 @@ thread_local! {
pub(crate) static FILTERING: FilterState = FilterState::new();
}
+/// Extension trait adding [combinators] for combining [`Filter`].
+///
+/// [combinators]: crate::filter::combinator
+/// [`Filter`]: crate::layer::Filter
+pub trait FilterExt<S>: layer::Filter<S> {
+ /// Combines this [`Filter`] with another [`Filter`] s so that spans and
+ /// events are enabled if and only if *both* filters return `true`.
+ ///
+ /// # Examples
+ ///
+ /// Enabling spans or events if they have both a particular target *and* are
+ /// above a certain level:
+ ///
+ /// ```
+ /// use tracing_subscriber::{
+ /// filter::{filter_fn, LevelFilter, FilterExt},
+ /// prelude::*,
+ /// };
+ ///
+ /// // Enables spans and events with targets starting with `interesting_target`:
+ /// let target_filter = filter_fn(|meta| {
+ /// meta.target().starts_with("interesting_target")
+ /// });
+ ///
+ /// // Enables spans and events with levels `INFO` and below:
+ /// let level_filter = LevelFilter::INFO;
+ ///
+ /// // Combine the two filters together, returning a filter that only enables
+ /// // spans and events that *both* filters will enable:
+ /// let filter = target_filter.and(level_filter);
+ ///
+ /// tracing_subscriber::registry()
+ /// .with(tracing_subscriber::fmt::layer().with_filter(filter))
+ /// .init();
+ ///
+ /// // This event will *not* be enabled:
+ /// tracing::info!("an event with an uninteresting target");
+ ///
+ /// // This event *will* be enabled:
+ /// tracing::info!(target: "interesting_target", "a very interesting event");
+ ///
+ /// // This event will *not* be enabled:
+ /// tracing::debug!(target: "interesting_target", "interesting debug event...");
+ /// ```
+ ///
+ /// [`Filter`]: crate::layer::Filter
+ fn and<B>(self, other: B) -> combinator::And<Self, B, S>
+ where
+ Self: Sized,
+ B: layer::Filter<S>,
+ {
+ combinator::And::new(self, other)
+ }
+
+ /// Combines two [`Filter`]s so that spans and events are enabled if *either* filter
+ /// returns `true`.
+ ///
+ /// # Examples
+ ///
+ /// Enabling spans and events at the `INFO` level and above, and all spans
+ /// and events with a particular target:
+ /// ```
+ /// use tracing_subscriber::{
+ /// filter::{filter_fn, LevelFilter, FilterExt},
+ /// prelude::*,
+ /// };
+ ///
+ /// // Enables spans and events with targets starting with `interesting_target`:
+ /// let target_filter = filter_fn(|meta| {
+ /// meta.target().starts_with("interesting_target")
+ /// });
+ ///
+ /// // Enables spans and events with levels `INFO` and below:
+ /// let level_filter = LevelFilter::INFO;
+ ///
+ /// // Combine the two filters together so that a span or event is enabled
+ /// // if it is at INFO or lower, or if it has a target starting with
+ /// // `interesting_target`.
+ /// let filter = level_filter.or(target_filter);
+ ///
+ /// tracing_subscriber::registry()
+ /// .with(tracing_subscriber::fmt::layer().with_filter(filter))
+ /// .init();
+ ///
+ /// // This event will *not* be enabled:
+ /// tracing::debug!("an uninteresting event");
+ ///
+ /// // This event *will* be enabled:
+ /// tracing::info!("an uninteresting INFO event");
+ ///
+ /// // This event *will* be enabled:
+ /// tracing::info!(target: "interesting_target", "a very interesting event");
+ ///
+ /// // This event *will* be enabled:
+ /// tracing::debug!(target: "interesting_target", "interesting debug event...");
+ /// ```
+ ///
+ /// Enabling a higher level for a particular target by using `or` in
+ /// conjunction with the [`and`] combinator:
+ ///
+ /// ```
+ /// use tracing_subscriber::{
+ /// filter::{filter_fn, LevelFilter, FilterExt},
+ /// prelude::*,
+ /// };
+ ///
+ /// // This filter will enable spans and events with targets beginning with
+ /// // `my_crate`:
+ /// let my_crate = filter_fn(|meta| {
+ /// meta.target().starts_with("my_crate")
+ /// });
+ ///
+ /// let filter = my_crate
+ /// // Combine the `my_crate` filter with a `LevelFilter` to produce a
+ /// // filter that will enable the `INFO` level and lower for spans and
+ /// // events with `my_crate` targets:
+ /// .and(LevelFilter::INFO)
+ /// // If a span or event *doesn't* have a target beginning with
+ /// // `my_crate`, enable it if it has the `WARN` level or lower:
+ /// .or(LevelFilter::WARN);
+ ///
+ /// tracing_subscriber::registry()
+ /// .with(tracing_subscriber::fmt::layer().with_filter(filter))
+ /// .init();
+ /// ```
+ ///
+ /// [`Filter`]: crate::layer::Filter
+ /// [`and`]: FilterExt::and
+ fn or<B>(self, other: B) -> combinator::Or<Self, B, S>
+ where
+ Self: Sized,
+ B: layer::Filter<S>,
+ {
+ combinator::Or::new(self, other)
+ }
+
+ /// Inverts `self`, returning a filter that enables spans and events only if
+ /// `self` would *not* enable them.
+ ///
+ /// This inverts the values returned by the [`enabled`] and [`callsite_enabled`]
+ /// methods on the wrapped filter; it does *not* invert [`event_enabled`], as
+ /// filters which do not implement filtering on event field values will return
+ /// the default `true` even for events that their [`enabled`] method disables.
+ ///
+ /// Consider a normal filter defined as:
+ ///
+ /// ```ignore (pseudo-code)
+ /// // for spans
+ /// match callsite_enabled() {
+ /// ALWAYS => on_span(),
+ /// SOMETIMES => if enabled() { on_span() },
+ /// NEVER => (),
+ /// }
+ /// // for events
+ /// match callsite_enabled() {
+ /// ALWAYS => on_event(),
+ /// SOMETIMES => if enabled() && event_enabled() { on_event() },
+ /// NEVER => (),
+ /// }
+ /// ```
+ ///
+ /// and an inverted filter defined as:
+ ///
+ /// ```ignore (pseudo-code)
+ /// // for spans
+ /// match callsite_enabled() {
+ /// ALWAYS => (),
+ /// SOMETIMES => if !enabled() { on_span() },
+ /// NEVER => on_span(),
+ /// }
+ /// // for events
+ /// match callsite_enabled() {
+ /// ALWAYS => (),
+ /// SOMETIMES => if !enabled() { on_event() },
+ /// NEVER => on_event(),
+ /// }
+ /// ```
+ ///
+ /// A proper inversion would do `!(enabled() && event_enabled())` (or
+ /// `!enabled() || !event_enabled()`), but because of the implicit `&&`
+ /// relation between `enabled` and `event_enabled`, it is difficult to
+ /// short circuit and not call the wrapped `event_enabled`.
+ ///
+ /// A combinator which remembers the result of `enabled` in order to call
+ /// `event_enabled` only when `enabled() == true` is possible, but requires
+ /// additional thread-local mutable state to support a very niche use case.
+ //
+ // Also, it'd mean the wrapped layer's `enabled()` always gets called and
+ // globally applied to events where it doesn't today, since we can't know
+ // what `event_enabled` will say until we have the event to call it with.
+ ///
+ /// [`Filter`]: crate::subscribe::Filter
+ /// [`enabled`]: crate::subscribe::Filter::enabled
+ /// [`event_enabled`]: crate::subscribe::Filter::event_enabled
+ /// [`callsite_enabled`]: crate::subscribe::Filter::callsite_enabled
+ fn not(self) -> combinator::Not<Self, S>
+ where
+ Self: Sized,
+ {
+ combinator::Not::new(self)
+ }
+
+ /// [Boxes] `self`, erasing its concrete type.
+ ///
+ /// This is equivalent to calling [`Box::new`], but in method form, so that
+ /// it can be used when chaining combinator methods.
+ ///
+ /// # Examples
+ ///
+ /// When different combinations of filters are used conditionally, they may
+ /// have different types. For example, the following code won't compile,
+ /// since the `if` and `else` clause produce filters of different types:
+ ///
+ /// ```compile_fail
+ /// use tracing_subscriber::{
+ /// filter::{filter_fn, LevelFilter, FilterExt},
+ /// prelude::*,
+ /// };
+ ///
+ /// let enable_bar_target: bool = // ...
+ /// # false;
+ ///
+ /// let filter = if enable_bar_target {
+ /// filter_fn(|meta| meta.target().starts_with("foo"))
+ /// // If `enable_bar_target` is true, add a `filter_fn` enabling
+ /// // spans and events with the target `bar`:
+ /// .or(filter_fn(|meta| meta.target().starts_with("bar")))
+ /// .and(LevelFilter::INFO)
+ /// } else {
+ /// filter_fn(|meta| meta.target().starts_with("foo"))
+ /// .and(LevelFilter::INFO)
+ /// };
+ ///
+ /// tracing_subscriber::registry()
+ /// .with(tracing_subscriber::fmt::layer().with_filter(filter))
+ /// .init();
+ /// ```
+ ///
+ /// By using `boxed`, the types of the two different branches can be erased,
+ /// so the assignment to the `filter` variable is valid (as both branches
+ /// have the type `Box<dyn Filter<S> + Send + Sync + 'static>`). The
+ /// following code *does* compile:
+ ///
+ /// ```
+ /// use tracing_subscriber::{
+ /// filter::{filter_fn, LevelFilter, FilterExt},
+ /// prelude::*,
+ /// };
+ ///
+ /// let enable_bar_target: bool = // ...
+ /// # false;
+ ///
+ /// let filter = if enable_bar_target {
+ /// filter_fn(|meta| meta.target().starts_with("foo"))
+ /// .or(filter_fn(|meta| meta.target().starts_with("bar")))
+ /// .and(LevelFilter::INFO)
+ /// // Boxing the filter erases its type, so both branches now
+ /// // have the same type.
+ /// .boxed()
+ /// } else {
+ /// filter_fn(|meta| meta.target().starts_with("foo"))
+ /// .and(LevelFilter::INFO)
+ /// .boxed()
+ /// };
+ ///
+ /// tracing_subscriber::registry()
+ /// .with(tracing_subscriber::fmt::layer().with_filter(filter))
+ /// .init();
+ /// ```
+ ///
+ /// [Boxes]: std::boxed
+ /// [`Box::new`]: std::boxed::Box::new
+ fn boxed(self) -> Box<dyn layer::Filter<S> + Send + Sync + 'static>
+ where
+ Self: Sized + Send + Sync + 'static,
+ {
+ Box::new(self)
+ }
+}
+
// === impl Filter ===
+
#[cfg(feature = "registry")]
#[cfg_attr(docsrs, doc(cfg(feature = "registry")))]
impl<S> layer::Filter<S> for LevelFilter {
@@ -179,38 +462,35 @@ impl<S> layer::Filter<S> for LevelFilter {
}
}
-impl<S> layer::Filter<S> for Arc<dyn layer::Filter<S> + Send + Sync + 'static> {
- #[inline]
- fn enabled(&self, meta: &Metadata<'_>, cx: &Context<'_, S>) -> bool {
- (**self).enabled(meta, cx)
- }
+macro_rules! filter_impl_body {
+ () => {
+ #[inline]
+ fn enabled(&self, meta: &Metadata<'_>, cx: &Context<'_, S>) -> bool {
+ self.deref().enabled(meta, cx)
+ }
- #[inline]
- fn callsite_enabled(&self, meta: &'static Metadata<'static>) -> Interest {
- (**self).callsite_enabled(meta)
- }
+ #[inline]
+ fn callsite_enabled(&self, meta: &'static Metadata<'static>) -> Interest {
+ self.deref().callsite_enabled(meta)
+ }
- #[inline]
- fn max_level_hint(&self) -> Option<LevelFilter> {
- (**self).max_level_hint()
- }
+ #[inline]
+ fn max_level_hint(&self) -> Option<LevelFilter> {
+ self.deref().max_level_hint()
+ }
+ };
}
-impl<S> layer::Filter<S> for Box<dyn layer::Filter<S> + Send + Sync + 'static> {
- #[inline]
- fn enabled(&self, meta: &Metadata<'_>, cx: &Context<'_, S>) -> bool {
- (**self).enabled(meta, cx)
- }
-
- #[inline]
- fn callsite_enabled(&self, meta: &'static Metadata<'static>) -> Interest {
- (**self).callsite_enabled(meta)
- }
+#[cfg(feature = "registry")]
+#[cfg_attr(docsrs, doc(cfg(feature = "registry")))]
+impl<S> layer::Filter<S> for Arc<dyn layer::Filter<S> + Send + Sync + 'static> {
+ filter_impl_body!();
+}
- #[inline]
- fn max_level_hint(&self) -> Option<LevelFilter> {
- (**self).max_level_hint()
- }
+#[cfg(feature = "registry")]
+#[cfg_attr(docsrs, doc(cfg(feature = "registry")))]
+impl<S> layer::Filter<S> for Box<dyn layer::Filter<S> + Send + Sync + 'static> {
+ filter_impl_body!();
}
// === impl Filtered ===
@@ -247,6 +527,78 @@ impl<L, F, S> Filtered<L, F, S> {
fn did_enable(&self, f: impl FnOnce()) {
FILTERING.with(|filtering| filtering.did_enable(self.id(), f))
}
+
+ /// Borrows the [`Filter`](crate::layer::Filter) used by this layer.
+ pub fn filter(&self) -> &F {
+ &self.filter
+ }
+
+ /// Mutably borrows the [`Filter`](crate::layer::Filter) used by this layer.
+ ///
+ /// When this layer can be mutably borrowed, this may be used to mutate the filter.
+ /// Generally, this will primarily be used with the
+ /// [`reload::Handle::modify`](crate::reload::Handle::modify) method.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// # use tracing::info;
+ /// # use tracing_subscriber::{filter,fmt,reload,Registry,prelude::*};
+ /// # fn main() {
+ /// let filtered_layer = fmt::Layer::default().with_filter(filter::LevelFilter::WARN);
+ /// let (filtered_layer, reload_handle) = reload::Layer::new(filtered_layer);
+ /// #
+ /// # // specifying the Registry type is required
+ /// # let _: &reload::Handle<filter::Filtered<fmt::Layer<Registry>,
+ /// # filter::LevelFilter, Registry>,Registry>
+ /// # = &reload_handle;
+ /// #
+ /// info!("This will be ignored");
+ /// reload_handle.modify(|layer| *layer.filter_mut() = filter::LevelFilter::INFO);
+ /// info!("This will be logged");
+ /// # }
+ /// ```
+ pub fn filter_mut(&mut self) -> &mut F {
+ &mut self.filter
+ }
+
+ /// Borrows the inner [`Layer`] wrapped by this `Filtered` layer.
+ pub fn inner(&self) -> &L {
+ &self.layer
+ }
+
+ /// Mutably borrows the inner [`Layer`] wrapped by this `Filtered` layer.
+ ///
+ /// This method is primarily expected to be used with the
+ /// [`reload::Handle::modify`](crate::reload::Handle::modify) method.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// # use tracing::info;
+ /// # use tracing_subscriber::{filter,fmt,reload,Registry,prelude::*};
+ /// # fn non_blocking<T: std::io::Write>(writer: T) -> (fn() -> std::io::Stdout) {
+ /// # std::io::stdout
+ /// # }
+ /// # fn main() {
+ /// let filtered_layer = fmt::layer().with_writer(non_blocking(std::io::stderr())).with_filter(filter::LevelFilter::INFO);
+ /// let (filtered_layer, reload_handle) = reload::Layer::new(filtered_layer);
+ /// #
+ /// # // specifying the Registry type is required
+ /// # let _: &reload::Handle<filter::Filtered<fmt::Layer<Registry, _, _, fn() -> std::io::Stdout>,
+ /// # filter::LevelFilter, Registry>, Registry>
+ /// # = &reload_handle;
+ /// #
+ /// info!("This will be logged to stderr");
+ /// reload_handle.modify(|layer| *layer.inner_mut().writer_mut() = non_blocking(std::io::stdout()));
+ /// info!("This will be logged to stdout");
+ /// # }
+ /// ```
+ ///
+ /// [subscriber]: Subscribe
+ pub fn inner_mut(&mut self) -> &mut L {
+ &mut self.layer
+ }
}
impl<S, L, F> Layer<S> for Filtered<L, F, S>
@@ -255,6 +607,10 @@ where
F: layer::Filter<S> + 'static,
L: Layer<S>,
{
+ fn on_register_dispatch(&self, collector: &Dispatch) {
+ self.layer.on_register_dispatch(collector);
+ }
+
fn on_layer(&mut self, subscriber: &mut S) {
self.id = MagicPlfDowncastMarker(subscriber.register_filter());
self.layer.on_layer(subscriber);
@@ -322,7 +678,9 @@ where
fn on_new_span(&self, attrs: &span::Attributes<'_>, id: &span::Id, cx: Context<'_, S>) {
self.did_enable(|| {
- self.layer.on_new_span(attrs, id, cx.with_filter(self.id()));
+ let cx = cx.with_filter(self.id());
+ self.filter.on_new_span(attrs, id, cx.clone());
+ self.layer.on_new_span(attrs, id, cx);
})
}
@@ -333,6 +691,7 @@ where
fn on_record(&self, span: &span::Id, values: &span::Record<'_>, cx: Context<'_, S>) {
if let Some(cx) = cx.if_enabled_for(span, self.id()) {
+ self.filter.on_record(span, values, cx.clone());
self.layer.on_record(span, values, cx)
}
}
@@ -345,6 +704,22 @@ where
}
}
+ fn event_enabled(&self, event: &Event<'_>, cx: Context<'_, S>) -> bool {
+ let cx = cx.with_filter(self.id());
+ let enabled = FILTERING
+ .with(|filtering| filtering.and(self.id(), || self.filter.event_enabled(event, &cx)));
+
+ if enabled {
+ // If the filter enabled this event, ask the wrapped subscriber if
+ // _it_ wants it --- it might have a global filter.
+ self.layer.event_enabled(event, cx)
+ } else {
+ // Otherwise, return `true`. See the comment in `enabled` for why this
+ // is necessary.
+ true
+ }
+ }
+
fn on_event(&self, event: &Event<'_>, cx: Context<'_, S>) {
self.did_enable(|| {
self.layer.on_event(event, cx.with_filter(self.id()));
@@ -353,19 +728,22 @@ where
fn on_enter(&self, id: &span::Id, cx: Context<'_, S>) {
if let Some(cx) = cx.if_enabled_for(id, self.id()) {
- self.layer.on_enter(id, cx)
+ self.filter.on_enter(id, cx.clone());
+ self.layer.on_enter(id, cx);
}
}
fn on_exit(&self, id: &span::Id, cx: Context<'_, S>) {
if let Some(cx) = cx.if_enabled_for(id, self.id()) {
- self.layer.on_exit(id, cx)
+ self.filter.on_exit(id, cx.clone());
+ self.layer.on_exit(id, cx);
}
}
fn on_close(&self, id: span::Id, cx: Context<'_, S>) {
if let Some(cx) = cx.if_enabled_for(&id, self.id()) {
- self.layer.on_close(id, cx)
+ self.filter.on_close(id.clone(), cx.clone());
+ self.layer.on_close(id, cx);
}
}
@@ -544,6 +922,10 @@ impl fmt::Binary for FilterId {
}
}
+// === impl FilterExt ===
+
+impl<F, S> FilterExt<S> for F where F: layer::Filter<S> {}
+
// === impl FilterMap ===
impl FilterMap {
@@ -709,6 +1091,14 @@ impl FilterState {
}
}
+ /// Run a second filtering pass, e.g. for Subscribe::event_enabled.
+ fn and(&self, filter: FilterId, f: impl FnOnce() -> bool) -> bool {
+ let map = self.enabled.get();
+ let enabled = map.is_enabled(filter) && f();
+ self.enabled.set(map.set(filter, enabled));
+ enabled
+ }
+
/// Clears the current in-progress filter state.
///
/// This resets the [`FilterMap`] and current [`Interest`] as well as
diff --git a/vendor/tracing-subscriber-0.3.3/src/filter/level.rs b/vendor/tracing-subscriber/src/filter/level.rs
index 0fa601260..0fa601260 100644
--- a/vendor/tracing-subscriber-0.3.3/src/filter/level.rs
+++ b/vendor/tracing-subscriber/src/filter/level.rs
diff --git a/vendor/tracing-subscriber-0.3.3/src/filter/mod.rs b/vendor/tracing-subscriber/src/filter/mod.rs
index 000a27195..000a27195 100644
--- a/vendor/tracing-subscriber-0.3.3/src/filter/mod.rs
+++ b/vendor/tracing-subscriber/src/filter/mod.rs
diff --git a/vendor/tracing-subscriber-0.3.3/src/filter/targets.rs b/vendor/tracing-subscriber/src/filter/targets.rs
index e0c7fcf82..e1407114b 100644
--- a/vendor/tracing-subscriber-0.3.3/src/filter/targets.rs
+++ b/vendor/tracing-subscriber/src/filter/targets.rs
@@ -20,7 +20,7 @@ use core::{
slice,
str::FromStr,
};
-use tracing_core::{Interest, Metadata, Subscriber};
+use tracing_core::{Interest, Level, Metadata, Subscriber};
/// A filter that enables or disables spans and events based on their [target]
/// and [level].
@@ -111,7 +111,7 @@ use tracing_core::{Interest, Metadata, Subscriber};
/// by the user at runtime.
///
/// The `Targets` filter can be used as a [per-layer filter][plf] *and* as a
-/// [global filter]:
+/// [global filter][global]:
///
/// ```rust
/// use tracing_subscriber::{
@@ -277,6 +277,62 @@ impl Targets {
self
}
+ /// Returns the default level for this filter, if one is set.
+ ///
+ /// The default level is used to filter any spans or events with targets
+ /// that do not match any of the configured set of prefixes.
+ ///
+ /// The default level can be set for a filter either by using
+ /// [`with_default`](Self::with_default) or when parsing from a filter string that includes a
+ /// level without a target (e.g. `"trace"`).
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use tracing_subscriber::filter::{LevelFilter, Targets};
+ ///
+ /// let filter = Targets::new().with_default(LevelFilter::INFO);
+ /// assert_eq!(filter.default_level(), Some(LevelFilter::INFO));
+ ///
+ /// let filter: Targets = "info".parse().unwrap();
+ /// assert_eq!(filter.default_level(), Some(LevelFilter::INFO));
+ /// ```
+ ///
+ /// The default level is `None` if no default is set:
+ ///
+ /// ```
+ /// use tracing_subscriber::filter::Targets;
+ ///
+ /// let filter = Targets::new();
+ /// assert_eq!(filter.default_level(), None);
+ ///
+ /// let filter: Targets = "my_crate=info".parse().unwrap();
+ /// assert_eq!(filter.default_level(), None);
+ /// ```
+ ///
+ /// Note that an unset default level (`None`) behaves like [`LevelFilter::OFF`] when the filter is
+ /// used, but it could also be set explicitly which may be useful to distinguish (such as when
+ /// merging multiple `Targets`).
+ ///
+ /// ```
+ /// use tracing_subscriber::filter::{LevelFilter, Targets};
+ ///
+ /// let filter = Targets::new().with_default(LevelFilter::OFF);
+ /// assert_eq!(filter.default_level(), Some(LevelFilter::OFF));
+ ///
+ /// let filter: Targets = "off".parse().unwrap();
+ /// assert_eq!(filter.default_level(), Some(LevelFilter::OFF));
+ /// ```
+ pub fn default_level(&self) -> Option<LevelFilter> {
+ self.0.directives().into_iter().find_map(|d| {
+ if d.target.is_none() {
+ Some(d.level)
+ } else {
+ None
+ }
+ })
+ }
+
/// Returns an iterator over the [target]-[`LevelFilter`] pairs in this filter.
///
/// The order of iteration is undefined.
@@ -313,6 +369,35 @@ impl Targets {
Interest::never()
}
}
+
+ /// Returns whether a [target]-[`Level`] pair would be enabled
+ /// by this `Targets`.
+ ///
+ /// This method can be used with [`module_path!`] from `std` as the target
+ /// in order to emulate the behavior of the [`tracing::event!`] and [`tracing::span!`]
+ /// macros.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use tracing_subscriber::filter::{Targets, LevelFilter};
+ /// use tracing_core::Level;
+ ///
+ /// let filter = Targets::new()
+ /// .with_target("my_crate", Level::INFO)
+ /// .with_target("my_crate::interesting_module", Level::DEBUG);
+ ///
+ /// assert!(filter.would_enable("my_crate", &Level::INFO));
+ /// assert!(!filter.would_enable("my_crate::interesting_module", &Level::TRACE));
+ /// ```
+ ///
+ /// [target]: tracing_core::Metadata::target
+ /// [`module_path!`]: std::module_path!
+ pub fn would_enable(&self, target: &str, level: &Level) -> bool {
+ // "Correct" to call because `Targets` only produces `StaticDirective`'s with NO
+ // fields
+ self.0.target_enabled(target, level)
+ }
}
impl<T, L> Extend<(T, L)> for Targets
@@ -657,6 +742,21 @@ mod tests {
}
#[test]
+ fn targets_default_level() {
+ let filter = expect_parse("crate1::mod1=error,crate1::mod2,crate2=debug,crate3=off");
+ assert_eq!(filter.default_level(), None);
+
+ let filter = expect_parse("crate1::mod1=error,crate1::mod2,crate2=debug,crate3=off")
+ .with_default(LevelFilter::OFF);
+ assert_eq!(filter.default_level(), Some(LevelFilter::OFF));
+
+ let filter = expect_parse("crate1::mod1=error,crate1::mod2,crate2=debug,crate3=off")
+ .with_default(LevelFilter::OFF)
+ .with_default(LevelFilter::INFO);
+ assert_eq!(filter.default_level(), Some(LevelFilter::INFO));
+ }
+
+ #[test]
// `println!` is only available with `libstd`.
#[cfg(feature = "std")]
fn size_of_filters() {
diff --git a/vendor/tracing-subscriber-0.3.3/src/fmt/fmt_layer.rs b/vendor/tracing-subscriber/src/fmt/fmt_layer.rs
index 0e0d5e0eb..6e4e2ac0b 100644
--- a/vendor/tracing-subscriber-0.3.3/src/fmt/fmt_layer.rs
+++ b/vendor/tracing-subscriber/src/fmt/fmt_layer.rs
@@ -56,7 +56,7 @@ use tracing_core::{
/// # tracing::subscriber::set_global_default(subscriber).unwrap();
/// ```
///
-/// [`Layer`]: ../layer/trait.Layer.html
+/// [`Layer`]: super::layer::Layer
#[cfg_attr(docsrs, doc(cfg(all(feature = "fmt", feature = "std"))))]
#[derive(Debug)]
pub struct Layer<
@@ -70,11 +70,12 @@ pub struct Layer<
fmt_event: E,
fmt_span: format::FmtSpanConfig,
is_ansi: bool,
- _inner: PhantomData<S>,
+ log_internal_errors: bool,
+ _inner: PhantomData<fn(S)>,
}
impl<S> Layer<S> {
- /// Returns a new [`Layer`](struct.Layer.html) with the default configuration.
+ /// Returns a new [`Layer`][self::Layer] with the default configuration.
pub fn new() -> Self {
Self::default()
}
@@ -87,8 +88,8 @@ where
N: for<'writer> FormatFields<'writer> + 'static,
W: for<'writer> MakeWriter<'writer> + 'static,
{
- /// Sets the [event formatter][`FormatEvent`] that the layer will use to
- /// format events.
+ /// Sets the [event formatter][`FormatEvent`] that the layer being built will
+ /// use to format events.
///
/// The event formatter may be any type implementing the [`FormatEvent`]
/// trait, which is implemented for all functions taking a [`FmtContext`], a
@@ -108,7 +109,7 @@ where
/// ```
/// [`FormatEvent`]: format::FormatEvent
/// [`Event`]: tracing::Event
- /// [`Writer`]: crate::format::Writer
+ /// [`Writer`]: format::Writer
pub fn event_format<E2>(self, e: E2) -> Layer<S, N, E2, W>
where
E2: FormatEvent<S, N> + 'static,
@@ -119,6 +120,37 @@ where
fmt_span: self.fmt_span,
make_writer: self.make_writer,
is_ansi: self.is_ansi,
+ log_internal_errors: self.log_internal_errors,
+ _inner: self._inner,
+ }
+ }
+
+ /// Updates the event formatter by applying a function to the existing event formatter.
+ ///
+ /// This sets the event formatter that the layer being built will use to record fields.
+ ///
+ /// # Examples
+ ///
+ /// Updating an event formatter:
+ ///
+ /// ```rust
+ /// let layer = tracing_subscriber::fmt::layer()
+ /// .map_event_format(|e| e.compact());
+ /// # // this is necessary for type inference.
+ /// # use tracing_subscriber::Layer as _;
+ /// # let _ = layer.with_subscriber(tracing_subscriber::registry::Registry::default());
+ /// ```
+ pub fn map_event_format<E2>(self, f: impl FnOnce(E) -> E2) -> Layer<S, N, E2, W>
+ where
+ E2: FormatEvent<S, N> + 'static,
+ {
+ Layer {
+ fmt_fields: self.fmt_fields,
+ fmt_event: f(self.fmt_event),
+ fmt_span: self.fmt_span,
+ make_writer: self.make_writer,
+ is_ansi: self.is_ansi,
+ log_internal_errors: self.log_internal_errors,
_inner: self._inner,
}
}
@@ -126,7 +158,7 @@ where
// This needs to be a seperate impl block because they place different bounds on the type parameters.
impl<S, N, E, W> Layer<S, N, E, W> {
- /// Sets the [`MakeWriter`] that the [`Layer`] being built will use to write events.
+ /// Sets the [`MakeWriter`] that the layer being built will use to write events.
///
/// # Examples
///
@@ -142,9 +174,6 @@ impl<S, N, E, W> Layer<S, N, E, W> {
/// # use tracing_subscriber::Layer as _;
/// # let _ = layer.with_subscriber(tracing_subscriber::registry::Registry::default());
/// ```
- ///
- /// [`MakeWriter`]: ../fmt/trait.MakeWriter.html
- /// [`Layer`]: ../layer/trait.Layer.html
pub fn with_writer<W2>(self, make_writer: W2) -> Layer<S, N, E, W2>
where
W2: for<'writer> MakeWriter<'writer> + 'static,
@@ -154,12 +183,63 @@ impl<S, N, E, W> Layer<S, N, E, W> {
fmt_event: self.fmt_event,
fmt_span: self.fmt_span,
is_ansi: self.is_ansi,
+ log_internal_errors: self.log_internal_errors,
make_writer,
_inner: self._inner,
}
}
- /// Configures the subscriber to support [`libtest`'s output capturing][capturing] when used in
+ /// Borrows the [writer] for this [`Layer`].
+ ///
+ /// [writer]: MakeWriter
+ pub fn writer(&self) -> &W {
+ &self.make_writer
+ }
+
+ /// Mutably borrows the [writer] for this [`Layer`].
+ ///
+ /// This method is primarily expected to be used with the
+ /// [`reload::Handle::modify`](crate::reload::Handle::modify) method.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// # use tracing::info;
+ /// # use tracing_subscriber::{fmt,reload,Registry,prelude::*};
+ /// # fn non_blocking<T: std::io::Write>(writer: T) -> (fn() -> std::io::Stdout) {
+ /// # std::io::stdout
+ /// # }
+ /// # fn main() {
+ /// let layer = fmt::layer().with_writer(non_blocking(std::io::stderr()));
+ /// let (layer, reload_handle) = reload::Layer::new(layer);
+ /// #
+ /// # // specifying the Registry type is required
+ /// # let _: &reload::Handle<fmt::Layer<Registry, _, _, _>, Registry> = &reload_handle;
+ /// #
+ /// info!("This will be logged to stderr");
+ /// reload_handle.modify(|layer| *layer.writer_mut() = non_blocking(std::io::stdout()));
+ /// info!("This will be logged to stdout");
+ /// # }
+ /// ```
+ ///
+ /// [writer]: MakeWriter
+ pub fn writer_mut(&mut self) -> &mut W {
+ &mut self.make_writer
+ }
+
+ /// Sets whether this layer should use ANSI terminal formatting
+ /// escape codes (such as colors).
+ ///
+ /// This method is primarily expected to be used with the
+ /// [`reload::Handle::modify`](crate::reload::Handle::modify) method when changing
+ /// the writer.
+ #[cfg(feature = "ansi")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "ansi")))]
+ pub fn set_ansi(&mut self, ansi: bool) {
+ self.is_ansi = ansi;
+ }
+
+ /// Configures the layer to support [`libtest`'s output capturing][capturing] when used in
/// unit tests.
///
/// See [`TestWriter`] for additional details.
@@ -180,13 +260,14 @@ impl<S, N, E, W> Layer<S, N, E, W> {
/// ```
/// [capturing]:
/// https://doc.rust-lang.org/book/ch11-02-running-tests.html#showing-function-output
- /// [`TestWriter`]: writer/struct.TestWriter.html
+ /// [`TestWriter`]: super::writer::TestWriter
pub fn with_test_writer(self) -> Layer<S, N, E, TestWriter> {
Layer {
fmt_fields: self.fmt_fields,
fmt_event: self.fmt_event,
fmt_span: self.fmt_span,
is_ansi: self.is_ansi,
+ log_internal_errors: self.log_internal_errors,
make_writer: TestWriter::default(),
_inner: self._inner,
}
@@ -201,6 +282,58 @@ impl<S, N, E, W> Layer<S, N, E, W> {
..self
}
}
+
+ /// Sets whether to write errors from [`FormatEvent`] to the writer.
+ /// Defaults to true.
+ ///
+ /// By default, `fmt::Layer` will write any `FormatEvent`-internal errors to
+ /// the writer. These errors are unlikely and will only occur if there is a
+ /// bug in the `FormatEvent` implementation or its dependencies.
+ ///
+ /// If writing to the writer fails, the error message is printed to stderr
+ /// as a fallback.
+ ///
+ /// [`FormatEvent`]: crate::fmt::FormatEvent
+ pub fn log_internal_errors(self, log_internal_errors: bool) -> Self {
+ Self {
+ log_internal_errors,
+ ..self
+ }
+ }
+
+ /// Updates the [`MakeWriter`] by applying a function to the existing [`MakeWriter`].
+ ///
+ /// This sets the [`MakeWriter`] that the layer being built will use to write events.
+ ///
+ /// # Examples
+ ///
+ /// Redirect output to stderr if level is <= WARN:
+ ///
+ /// ```rust
+ /// use tracing::Level;
+ /// use tracing_subscriber::fmt::{self, writer::MakeWriterExt};
+ ///
+ /// let stderr = std::io::stderr.with_max_level(Level::WARN);
+ /// let layer = fmt::layer()
+ /// .map_writer(move |w| stderr.or_else(w));
+ /// # // this is necessary for type inference.
+ /// # use tracing_subscriber::Layer as _;
+ /// # let _ = layer.with_subscriber(tracing_subscriber::registry::Registry::default());
+ /// ```
+ pub fn map_writer<W2>(self, f: impl FnOnce(W) -> W2) -> Layer<S, N, E, W2>
+ where
+ W2: for<'writer> MakeWriter<'writer> + 'static,
+ {
+ Layer {
+ fmt_fields: self.fmt_fields,
+ fmt_event: self.fmt_event,
+ fmt_span: self.fmt_span,
+ is_ansi: self.is_ansi,
+ log_internal_errors: self.log_internal_errors,
+ make_writer: f(self.make_writer),
+ _inner: self._inner,
+ }
+ }
}
impl<S, N, L, T, W> Layer<S, N, format::Format<L, T>, W>
@@ -228,6 +361,7 @@ where
fmt_span: self.fmt_span,
make_writer: self.make_writer,
is_ansi: self.is_ansi,
+ log_internal_errors: self.log_internal_errors,
_inner: self._inner,
}
}
@@ -240,6 +374,7 @@ where
fmt_span: self.fmt_span.without_time(),
make_writer: self.make_writer,
is_ansi: self.is_ansi,
+ log_internal_errors: self.log_internal_errors,
_inner: self._inner,
}
}
@@ -284,7 +419,7 @@ where
/// `Layer`s added to this subscriber.
///
/// [lifecycle]: https://docs.rs/tracing/latest/tracing/span/index.html#the-span-lifecycle
- /// [time]: #method.without_time
+ /// [time]: Layer::without_time()
pub fn with_span_events(self, kind: FmtSpan) -> Self {
Layer {
fmt_span: self.fmt_span.with_kind(kind),
@@ -299,6 +434,30 @@ where
..self
}
}
+ /// Sets whether or not an event's [source code file path][file] is
+ /// displayed.
+ ///
+ /// [file]: tracing_core::Metadata::file
+ pub fn with_file(self, display_filename: bool) -> Layer<S, N, format::Format<L, T>, W> {
+ Layer {
+ fmt_event: self.fmt_event.with_file(display_filename),
+ ..self
+ }
+ }
+
+ /// Sets whether or not an event's [source code line number][line] is
+ /// displayed.
+ ///
+ /// [line]: tracing_core::Metadata::line
+ pub fn with_line_number(
+ self,
+ display_line_number: bool,
+ ) -> Layer<S, N, format::Format<L, T>, W> {
+ Layer {
+ fmt_event: self.fmt_event.with_line_number(display_line_number),
+ ..self
+ }
+ }
/// Sets whether or not an event's level is displayed.
pub fn with_level(self, display_level: bool) -> Layer<S, N, format::Format<L, T>, W> {
@@ -309,9 +468,9 @@ where
}
/// Sets whether or not the [thread ID] of the current thread is displayed
- /// when formatting events
+ /// when formatting events.
///
- /// [thread ID]: https://doc.rust-lang.org/stable/std/thread/struct.ThreadId.html
+ /// [thread ID]: std::thread::ThreadId
pub fn with_thread_ids(self, display_thread_ids: bool) -> Layer<S, N, format::Format<L, T>, W> {
Layer {
fmt_event: self.fmt_event.with_thread_ids(display_thread_ids),
@@ -320,9 +479,9 @@ where
}
/// Sets whether or not the [name] of the current thread is displayed
- /// when formatting events
+ /// when formatting events.
///
- /// [name]: https://doc.rust-lang.org/stable/std/thread/index.html#naming-threads
+ /// [name]: std::thread#naming-threads
pub fn with_thread_names(
self,
display_thread_names: bool,
@@ -333,7 +492,7 @@ where
}
}
- /// Sets the layer being built to use a [less verbose formatter](../fmt/format/struct.Compact.html).
+ /// Sets the layer being built to use a [less verbose formatter][super::format::Compact].
pub fn compact(self) -> Layer<S, N, format::Format<format::Compact, T>, W>
where
N: for<'writer> FormatFields<'writer> + 'static,
@@ -344,6 +503,7 @@ where
fmt_span: self.fmt_span,
make_writer: self.make_writer,
is_ansi: self.is_ansi,
+ log_internal_errors: self.log_internal_errors,
_inner: self._inner,
}
}
@@ -358,11 +518,12 @@ where
fmt_span: self.fmt_span,
make_writer: self.make_writer,
is_ansi: self.is_ansi,
+ log_internal_errors: self.log_internal_errors,
_inner: self._inner,
}
}
- /// Sets the layer being built to use a [JSON formatter](../fmt/format/struct.Json.html).
+ /// Sets the layer being built to use a [JSON formatter][super::format::Json].
///
/// The full format includes fields from all entered spans.
///
@@ -377,7 +538,7 @@ where
/// - [`Layer::flatten_event`] can be used to enable flattening event fields into the root
/// object.
///
- /// [`Layer::flatten_event`]: #method.flatten_event
+ /// [`Layer::flatten_event`]: Layer::flatten_event()
#[cfg(feature = "json")]
#[cfg_attr(docsrs, doc(cfg(feature = "json")))]
pub fn json(self) -> Layer<S, format::JsonFields, format::Format<format::Json, T>, W> {
@@ -388,6 +549,7 @@ where
make_writer: self.make_writer,
// always disable ANSI escapes in JSON mode!
is_ansi: false,
+ log_internal_errors: self.log_internal_errors,
_inner: self._inner,
}
}
@@ -398,7 +560,7 @@ where
impl<S, T, W> Layer<S, format::JsonFields, format::Format<format::Json, T>, W> {
/// Sets the JSON layer being built to flatten event metadata.
///
- /// See [`format::Json`](../fmt/format/struct.Json.html)
+ /// See [`format::Json`][super::format::Json]
pub fn flatten_event(
self,
flatten_event: bool,
@@ -413,7 +575,7 @@ impl<S, T, W> Layer<S, format::JsonFields, format::Format<format::Json, T>, W> {
/// Sets whether or not the formatter will include the current span in
/// formatted events.
///
- /// See [`format::Json`](../fmt/format/struct.Json.html)
+ /// See [`format::Json`][super::format::Json]
pub fn with_current_span(
self,
display_current_span: bool,
@@ -428,7 +590,7 @@ impl<S, T, W> Layer<S, format::JsonFields, format::Format<format::Json, T>, W> {
/// Sets whether or not the formatter will include a list (from root to leaf)
/// of all currently entered spans in formatted events.
///
- /// See [`format::Json`](../fmt/format/struct.Json.html)
+ /// See [`format::Json`][super::format::Json]
pub fn with_span_list(
self,
display_span_list: bool,
@@ -454,6 +616,38 @@ impl<S, N, E, W> Layer<S, N, E, W> {
fmt_span: self.fmt_span,
make_writer: self.make_writer,
is_ansi: self.is_ansi,
+ log_internal_errors: self.log_internal_errors,
+ _inner: self._inner,
+ }
+ }
+
+ /// Updates the field formatter by applying a function to the existing field formatter.
+ ///
+ /// This sets the field formatter that the layer being built will use to record fields.
+ ///
+ /// # Examples
+ ///
+ /// Updating a field formatter:
+ ///
+ /// ```rust
+ /// use tracing_subscriber::field::MakeExt;
+ /// let layer = tracing_subscriber::fmt::layer()
+ /// .map_fmt_fields(|f| f.debug_alt());
+ /// # // this is necessary for type inference.
+ /// # use tracing_subscriber::Layer as _;
+ /// # let _ = layer.with_subscriber(tracing_subscriber::registry::Registry::default());
+ /// ```
+ pub fn map_fmt_fields<N2>(self, f: impl FnOnce(N) -> N2) -> Layer<S, N2, E, W>
+ where
+ N2: for<'writer> FormatFields<'writer> + 'static,
+ {
+ Layer {
+ fmt_event: self.fmt_event,
+ fmt_fields: f(self.fmt_fields),
+ fmt_span: self.fmt_span,
+ make_writer: self.make_writer,
+ is_ansi: self.is_ansi,
+ log_internal_errors: self.log_internal_errors,
_inner: self._inner,
}
}
@@ -467,6 +661,7 @@ impl<S> Default for Layer<S> {
fmt_span: format::FmtSpanConfig::default(),
make_writer: io::stdout,
is_ansi: cfg!(feature = "ansi"),
+ log_internal_errors: false,
_inner: PhantomData,
}
}
@@ -497,7 +692,7 @@ where
/// formatters are in use, each can store its own formatted representation
/// without conflicting.
///
-/// [extensions]: ../registry/struct.Extensions.html
+/// [extensions]: crate::registry::Extensions
#[derive(Default)]
pub struct FormattedFields<E: ?Sized> {
_format_fields: PhantomData<fn(E)>,
@@ -586,6 +781,11 @@ where
{
fields.was_ansi = self.is_ansi;
extensions.insert(fields);
+ } else {
+ eprintln!(
+ "[tracing-subscriber] Unable to format the following event, ignoring: {:?}",
+ attrs
+ );
}
}
@@ -732,7 +932,20 @@ where
.is_ok()
{
let mut writer = self.make_writer.make_writer_for(event.metadata());
- let _ = io::Write::write_all(&mut writer, buf.as_bytes());
+ let res = io::Write::write_all(&mut writer, buf.as_bytes());
+ if self.log_internal_errors {
+ if let Err(e) = res {
+ eprintln!("[tracing-subscriber] Unable to write an event to the Writer for this Subscriber! Error: {}\n", e);
+ }
+ }
+ } else if self.log_internal_errors {
+ let err_msg = format!("Unable to format the following event. Name: {}; Fields: {:?}\n",
+ event.metadata().name(), event.fields());
+ let mut writer = self.make_writer.make_writer_for(event.metadata());
+ let res = io::Write::write_all(&mut writer, err_msg.as_bytes());
+ if let Err(e) = res {
+ eprintln!("[tracing-subscriber] Unable to write an \"event formatting error\" to the Writer for this Subscriber! Error: {}\n", e);
+ }
}
buf.clear();
@@ -821,7 +1034,7 @@ where
/// If this returns `None`, then no span exists for that ID (either it has
/// closed or the ID is invalid).
///
- /// [stored data]: ../registry/struct.SpanRef.html
+ /// [stored data]: crate::registry::SpanRef
#[inline]
pub fn span(&self, id: &Id) -> Option<SpanRef<'_, S>>
where
@@ -844,7 +1057,7 @@ where
///
/// If this returns `None`, then we are not currently within a span.
///
- /// [stored data]: ../registry/struct.SpanRef.html
+ /// [stored data]: crate::registry::SpanRef
#[inline]
pub fn lookup_current(&self) -> Option<SpanRef<'_, S>>
where
@@ -1030,6 +1243,60 @@ mod test {
}
#[test]
+ fn format_error_print_to_stderr() {
+ struct AlwaysError;
+
+ impl std::fmt::Debug for AlwaysError {
+ fn fmt(&self, _f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
+ Err(std::fmt::Error)
+ }
+ }
+
+ let make_writer = MockMakeWriter::default();
+ let subscriber = crate::fmt::Subscriber::builder()
+ .with_writer(make_writer.clone())
+ .with_level(false)
+ .with_ansi(false)
+ .with_timer(MockTime)
+ .finish();
+
+ with_default(subscriber, || {
+ tracing::info!(?AlwaysError);
+ });
+ let actual = sanitize_timings(make_writer.get_string());
+
+ // Only assert the start because the line number and callsite may change.
+ let expected = concat!("Unable to format the following event. Name: event ", file!(), ":");
+ assert!(actual.as_str().starts_with(expected), "\nactual = {}\nshould start with expected = {}\n", actual, expected);
+ }
+
+ #[test]
+ fn format_error_ignore_if_log_internal_errors_is_false() {
+ struct AlwaysError;
+
+ impl std::fmt::Debug for AlwaysError {
+ fn fmt(&self, _f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
+ Err(std::fmt::Error)
+ }
+ }
+
+ let make_writer = MockMakeWriter::default();
+ let subscriber = crate::fmt::Subscriber::builder()
+ .with_writer(make_writer.clone())
+ .with_level(false)
+ .with_ansi(false)
+ .with_timer(MockTime)
+ .log_internal_errors(false)
+ .finish();
+
+ with_default(subscriber, || {
+ tracing::info!(?AlwaysError);
+ });
+ let actual = sanitize_timings(make_writer.get_string());
+ assert_eq!("", actual.as_str());
+ }
+
+ #[test]
fn synthesize_span_none() {
let make_writer = MockMakeWriter::default();
let subscriber = crate::fmt::Subscriber::builder()
diff --git a/vendor/tracing-subscriber-0.3.3/src/fmt/format/json.rs b/vendor/tracing-subscriber/src/fmt/format/json.rs
index cc86f03c7..c2f4d3755 100644
--- a/vendor/tracing-subscriber-0.3.3/src/fmt/format/json.rs
+++ b/vendor/tracing-subscriber/src/fmt/format/json.rs
@@ -23,25 +23,42 @@ use tracing_serde::AsSerde;
#[cfg(feature = "tracing-log")]
use tracing_log::NormalizeEvent;
-/// Marker for `Format` that indicates that the verbose JSON log format should be used.
+/// Marker for [`Format`] that indicates that the newline-delimited JSON log
+/// format should be used.
///
-/// The full format includes fields from all entered spans.
+/// This formatter is intended for production use with systems where structured
+/// logs are consumed as JSON by analysis and viewing tools. The JSON output is
+/// not optimized for human readability; instead, it should be pretty-printed
+/// using external JSON tools such as `jq`, or using a JSON log viewer.
///
/// # Example Output
///
-/// ```json
-/// {
-/// "timestamp":"Feb 20 11:28:15.096",
-/// "level":"INFO",
-/// "fields":{"message":"some message","key":"value"}
-/// "target":"mycrate",
-/// "span":{name":"leaf"},
-/// "spans":[{"name":"root"},{"name":"leaf"}],
-/// }
-/// ```
+/// <pre><font color="#4E9A06"><b>:;</b></font> <font color="#4E9A06">cargo</font> run --example fmt-json
+/// <font color="#4E9A06"><b> Finished</b></font> dev [unoptimized + debuginfo] target(s) in 0.08s
+/// <font color="#4E9A06"><b> Running</b></font> `target/debug/examples/fmt-json`
+/// {&quot;timestamp&quot;:&quot;2022-02-15T18:47:10.821315Z&quot;,&quot;level&quot;:&quot;INFO&quot;,&quot;fields&quot;:{&quot;message&quot;:&quot;preparing to shave yaks&quot;,&quot;number_of_yaks&quot;:3},&quot;target&quot;:&quot;fmt_json&quot;}
+/// {&quot;timestamp&quot;:&quot;2022-02-15T18:47:10.821422Z&quot;,&quot;level&quot;:&quot;INFO&quot;,&quot;fields&quot;:{&quot;message&quot;:&quot;shaving yaks&quot;},&quot;target&quot;:&quot;fmt_json::yak_shave&quot;,&quot;spans&quot;:[{&quot;yaks&quot;:3,&quot;name&quot;:&quot;shaving_yaks&quot;}]}
+/// {&quot;timestamp&quot;:&quot;2022-02-15T18:47:10.821495Z&quot;,&quot;level&quot;:&quot;TRACE&quot;,&quot;fields&quot;:{&quot;message&quot;:&quot;hello! I&apos;m gonna shave a yak&quot;,&quot;excitement&quot;:&quot;yay!&quot;},&quot;target&quot;:&quot;fmt_json::yak_shave&quot;,&quot;spans&quot;:[{&quot;yaks&quot;:3,&quot;name&quot;:&quot;shaving_yaks&quot;},{&quot;yak&quot;:1,&quot;name&quot;:&quot;shave&quot;}]}
+/// {&quot;timestamp&quot;:&quot;2022-02-15T18:47:10.821546Z&quot;,&quot;level&quot;:&quot;TRACE&quot;,&quot;fields&quot;:{&quot;message&quot;:&quot;yak shaved successfully&quot;},&quot;target&quot;:&quot;fmt_json::yak_shave&quot;,&quot;spans&quot;:[{&quot;yaks&quot;:3,&quot;name&quot;:&quot;shaving_yaks&quot;},{&quot;yak&quot;:1,&quot;name&quot;:&quot;shave&quot;}]}
+/// {&quot;timestamp&quot;:&quot;2022-02-15T18:47:10.821598Z&quot;,&quot;level&quot;:&quot;DEBUG&quot;,&quot;fields&quot;:{&quot;yak&quot;:1,&quot;shaved&quot;:true},&quot;target&quot;:&quot;yak_events&quot;,&quot;spans&quot;:[{&quot;yaks&quot;:3,&quot;name&quot;:&quot;shaving_yaks&quot;}]}
+/// {&quot;timestamp&quot;:&quot;2022-02-15T18:47:10.821637Z&quot;,&quot;level&quot;:&quot;TRACE&quot;,&quot;fields&quot;:{&quot;yaks_shaved&quot;:1},&quot;target&quot;:&quot;fmt_json::yak_shave&quot;,&quot;spans&quot;:[{&quot;yaks&quot;:3,&quot;name&quot;:&quot;shaving_yaks&quot;}]}
+/// {&quot;timestamp&quot;:&quot;2022-02-15T18:47:10.821684Z&quot;,&quot;level&quot;:&quot;TRACE&quot;,&quot;fields&quot;:{&quot;message&quot;:&quot;hello! I&apos;m gonna shave a yak&quot;,&quot;excitement&quot;:&quot;yay!&quot;},&quot;target&quot;:&quot;fmt_json::yak_shave&quot;,&quot;spans&quot;:[{&quot;yaks&quot;:3,&quot;name&quot;:&quot;shaving_yaks&quot;},{&quot;yak&quot;:2,&quot;name&quot;:&quot;shave&quot;}]}
+/// {&quot;timestamp&quot;:&quot;2022-02-15T18:47:10.821727Z&quot;,&quot;level&quot;:&quot;TRACE&quot;,&quot;fields&quot;:{&quot;message&quot;:&quot;yak shaved successfully&quot;},&quot;target&quot;:&quot;fmt_json::yak_shave&quot;,&quot;spans&quot;:[{&quot;yaks&quot;:3,&quot;name&quot;:&quot;shaving_yaks&quot;},{&quot;yak&quot;:2,&quot;name&quot;:&quot;shave&quot;}]}
+/// {&quot;timestamp&quot;:&quot;2022-02-15T18:47:10.821773Z&quot;,&quot;level&quot;:&quot;DEBUG&quot;,&quot;fields&quot;:{&quot;yak&quot;:2,&quot;shaved&quot;:true},&quot;target&quot;:&quot;yak_events&quot;,&quot;spans&quot;:[{&quot;yaks&quot;:3,&quot;name&quot;:&quot;shaving_yaks&quot;}]}
+/// {&quot;timestamp&quot;:&quot;2022-02-15T18:47:10.821806Z&quot;,&quot;level&quot;:&quot;TRACE&quot;,&quot;fields&quot;:{&quot;yaks_shaved&quot;:2},&quot;target&quot;:&quot;fmt_json::yak_shave&quot;,&quot;spans&quot;:[{&quot;yaks&quot;:3,&quot;name&quot;:&quot;shaving_yaks&quot;}]}
+/// {&quot;timestamp&quot;:&quot;2022-02-15T18:47:10.821909Z&quot;,&quot;level&quot;:&quot;TRACE&quot;,&quot;fields&quot;:{&quot;message&quot;:&quot;hello! I&apos;m gonna shave a yak&quot;,&quot;excitement&quot;:&quot;yay!&quot;},&quot;target&quot;:&quot;fmt_json::yak_shave&quot;,&quot;spans&quot;:[{&quot;yaks&quot;:3,&quot;name&quot;:&quot;shaving_yaks&quot;},{&quot;yak&quot;:3,&quot;name&quot;:&quot;shave&quot;}]}
+/// {&quot;timestamp&quot;:&quot;2022-02-15T18:47:10.821956Z&quot;,&quot;level&quot;:&quot;WARN&quot;,&quot;fields&quot;:{&quot;message&quot;:&quot;could not locate yak&quot;},&quot;target&quot;:&quot;fmt_json::yak_shave&quot;,&quot;spans&quot;:[{&quot;yaks&quot;:3,&quot;name&quot;:&quot;shaving_yaks&quot;},{&quot;yak&quot;:3,&quot;name&quot;:&quot;shave&quot;}]}
+/// {&quot;timestamp&quot;:&quot;2022-02-15T18:47:10.822006Z&quot;,&quot;level&quot;:&quot;DEBUG&quot;,&quot;fields&quot;:{&quot;yak&quot;:3,&quot;shaved&quot;:false},&quot;target&quot;:&quot;yak_events&quot;,&quot;spans&quot;:[{&quot;yaks&quot;:3,&quot;name&quot;:&quot;shaving_yaks&quot;}]}
+/// {&quot;timestamp&quot;:&quot;2022-02-15T18:47:10.822041Z&quot;,&quot;level&quot;:&quot;ERROR&quot;,&quot;fields&quot;:{&quot;message&quot;:&quot;failed to shave yak&quot;,&quot;yak&quot;:3,&quot;error&quot;:&quot;missing yak&quot;},&quot;target&quot;:&quot;fmt_json::yak_shave&quot;,&quot;spans&quot;:[{&quot;yaks&quot;:3,&quot;name&quot;:&quot;shaving_yaks&quot;}]}
+/// {&quot;timestamp&quot;:&quot;2022-02-15T18:47:10.822079Z&quot;,&quot;level&quot;:&quot;TRACE&quot;,&quot;fields&quot;:{&quot;yaks_shaved&quot;:2},&quot;target&quot;:&quot;fmt_json::yak_shave&quot;,&quot;spans&quot;:[{&quot;yaks&quot;:3,&quot;name&quot;:&quot;shaving_yaks&quot;}]}
+/// {&quot;timestamp&quot;:&quot;2022-02-15T18:47:10.822117Z&quot;,&quot;level&quot;:&quot;INFO&quot;,&quot;fields&quot;:{&quot;message&quot;:&quot;yak shaving completed&quot;,&quot;all_yaks_shaved&quot;:false},&quot;target&quot;:&quot;fmt_json&quot;}
+/// </pre>
///
/// # Options
///
+/// This formatter exposes additional options to configure the structure of the
+/// output JSON objects:
+///
/// - [`Json::flatten_event`] can be used to enable flattening event fields into
/// the root
/// - [`Json::with_current_span`] can be used to control logging of the current
@@ -52,9 +69,23 @@ use tracing_log::NormalizeEvent;
/// By default, event fields are not flattened, and both current span and span
/// list are logged.
///
-/// [`Json::flatten_event`]: #method.flatten_event
-/// [`Json::with_current_span`]: #method.with_current_span
-/// [`Json::with_span_list`]: #method.with_span_list
+/// # Valuable Support
+///
+/// Experimental support is available for using the [`valuable`] crate to record
+/// user-defined values as structured JSON. When the ["valuable" unstable
+/// feature][unstable] is enabled, types implementing [`valuable::Valuable`] will
+/// be recorded as structured JSON, rather than
+/// using their [`std::fmt::Debug`] implementations.
+///
+/// **Note**: This is an experimental feature. [Unstable features][unstable]
+/// must be enabled in order to use `valuable` support.
+///
+/// [`Json::flatten_event`]: Json::flatten_event()
+/// [`Json::with_current_span`]: Json::with_current_span()
+/// [`Json::with_span_list`]: Json::with_span_list()
+/// [`valuable`]: https://crates.io/crates/valuable
+/// [unstable]: crate#unstable-features
+/// [`valuable::Valuable`]: https://docs.rs/valuable/latest/valuable/trait.Valuable.html
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
pub struct Json {
pub(crate) flatten_event: bool,
@@ -243,6 +274,18 @@ where
serializer.serialize_entry("target", meta.target())?;
}
+ if self.display_filename {
+ if let Some(filename) = meta.file() {
+ serializer.serialize_entry("filename", filename)?;
+ }
+ }
+
+ if self.display_line_number {
+ if let Some(line_number) = meta.line() {
+ serializer.serialize_entry("line_number", &line_number)?;
+ }
+ }
+
if self.format.display_current_span {
if let Some(ref span) = current_span {
serializer
@@ -298,7 +341,6 @@ impl Default for Json {
/// The JSON [`FormatFields`] implementation.
///
-/// [`FormatFields`]: trait.FormatFields.html
#[derive(Debug)]
pub struct JsonFields {
// reserve the ability to add fields to this without causing a breaking
@@ -309,7 +351,6 @@ pub struct JsonFields {
impl JsonFields {
/// Returns a new JSON [`FormatFields`] implementation.
///
- /// [`FormatFields`]: trait.FormatFields.html
pub fn new() -> Self {
Self { _private: () }
}
@@ -378,9 +419,8 @@ impl<'a> FormatFields<'a> for JsonFields {
/// The [visitor] produced by [`JsonFields`]'s [`MakeVisitor`] implementation.
///
-/// [visitor]: ../../field/trait.Visit.html
-/// [`JsonFields`]: struct.JsonFields.html
-/// [`MakeVisitor`]: ../../field/trait.MakeVisitor.html
+/// [visitor]: crate::field::Visit
+/// [`MakeVisitor`]: crate::field::MakeVisitor
pub struct JsonVisitor<'a> {
values: BTreeMap<&'a str, serde_json::Value>,
writer: &'a mut dyn Write,
@@ -435,6 +475,26 @@ impl<'a> crate::field::VisitOutput<fmt::Result> for JsonVisitor<'a> {
}
impl<'a> field::Visit for JsonVisitor<'a> {
+ #[cfg(all(tracing_unstable, feature = "valuable"))]
+ fn record_value(&mut self, field: &Field, value: valuable_crate::Value<'_>) {
+ let value = match serde_json::to_value(valuable_serde::Serializable::new(value)) {
+ Ok(value) => value,
+ Err(_e) => {
+ #[cfg(debug_assertions)]
+ unreachable!(
+ "`valuable::Valuable` implementations should always serialize \
+ successfully, but an error occurred: {}",
+ _e,
+ );
+
+ #[cfg(not(debug_assertions))]
+ return;
+ }
+ };
+
+ self.values.insert(field.name(), value);
+ }
+
/// Visit a double precision floating point value.
fn record_f64(&mut self, field: &Field, value: f64) {
self.values
@@ -488,6 +548,7 @@ mod test {
use tracing::{self, subscriber::with_default};
use std::fmt;
+ use std::path::Path;
struct MockTime;
impl FormatTime for MockTime {
@@ -516,6 +577,50 @@ mod test {
}
#[test]
+ fn json_filename() {
+ let current_path = Path::new("tracing-subscriber")
+ .join("src")
+ .join("fmt")
+ .join("format")
+ .join("json.rs")
+ .to_str()
+ .expect("path must be valid unicode")
+ // escape windows backslashes
+ .replace('\\', "\\\\");
+ let expected =
+ &format!("{}{}{}",
+ "{\"timestamp\":\"fake time\",\"level\":\"INFO\",\"span\":{\"answer\":42,\"name\":\"json_span\",\"number\":3},\"spans\":[{\"answer\":42,\"name\":\"json_span\",\"number\":3}],\"target\":\"tracing_subscriber::fmt::format::json::test\",\"filename\":\"",
+ current_path,
+ "\",\"fields\":{\"message\":\"some json test\"}}\n");
+ let subscriber = subscriber()
+ .flatten_event(false)
+ .with_current_span(true)
+ .with_file(true)
+ .with_span_list(true);
+ test_json(expected, subscriber, || {
+ let span = tracing::span!(tracing::Level::INFO, "json_span", answer = 42, number = 3);
+ let _guard = span.enter();
+ tracing::info!("some json test");
+ });
+ }
+
+ #[test]
+ fn json_line_number() {
+ let expected =
+ "{\"timestamp\":\"fake time\",\"level\":\"INFO\",\"span\":{\"answer\":42,\"name\":\"json_span\",\"number\":3},\"spans\":[{\"answer\":42,\"name\":\"json_span\",\"number\":3}],\"target\":\"tracing_subscriber::fmt::format::json::test\",\"line_number\":42,\"fields\":{\"message\":\"some json test\"}}\n";
+ let subscriber = subscriber()
+ .flatten_event(false)
+ .with_current_span(true)
+ .with_line_number(true)
+ .with_span_list(true);
+ test_json_with_line_number(expected, subscriber, || {
+ let span = tracing::span!(tracing::Level::INFO, "json_span", answer = 42, number = 3);
+ let _guard = span.enter();
+ tracing::info!("some json test");
+ });
+ }
+
+ #[test]
fn json_flattened_event() {
let expected =
"{\"timestamp\":\"fake time\",\"level\":\"INFO\",\"span\":{\"answer\":42,\"name\":\"json_span\",\"number\":3},\"spans\":[{\"answer\":42,\"name\":\"json_span\",\"number\":3}],\"target\":\"tracing_subscriber::fmt::format::json::test\",\"message\":\"some json test\"}\n";
@@ -747,4 +852,34 @@ mod test {
serde_json::from_str(actual).unwrap()
);
}
+
+ fn test_json_with_line_number<T>(
+ expected: &str,
+ builder: crate::fmt::SubscriberBuilder<JsonFields, Format<Json>>,
+ producer: impl FnOnce() -> T,
+ ) {
+ let make_writer = MockMakeWriter::default();
+ let subscriber = builder
+ .with_writer(make_writer.clone())
+ .with_timer(MockTime)
+ .finish();
+
+ with_default(subscriber, producer);
+
+ let buf = make_writer.buf();
+ let actual = std::str::from_utf8(&buf[..]).unwrap();
+ let mut expected =
+ serde_json::from_str::<std::collections::HashMap<&str, serde_json::Value>>(expected)
+ .unwrap();
+ let expect_line_number = expected.remove("line_number").is_some();
+ let mut actual: std::collections::HashMap<&str, serde_json::Value> =
+ serde_json::from_str(actual).unwrap();
+ let line_number = actual.remove("line_number");
+ if expect_line_number {
+ assert_eq!(line_number.map(|x| x.is_number()), Some(true));
+ } else {
+ assert!(line_number.is_none());
+ }
+ assert_eq!(actual, expected);
+ }
}
diff --git a/vendor/tracing-subscriber-0.3.3/src/fmt/format/mod.rs b/vendor/tracing-subscriber/src/fmt/format/mod.rs
index 9001e102e..b8a482e55 100644
--- a/vendor/tracing-subscriber-0.3.3/src/fmt/format/mod.rs
+++ b/vendor/tracing-subscriber/src/fmt/format/mod.rs
@@ -1,4 +1,33 @@
//! Formatters for logging `tracing` events.
+//!
+//! This module provides several formatter implementations, as well as utilities
+//! for implementing custom formatters.
+//!
+//! # Formatters
+//! This module provides a number of formatter implementations:
+//!
+//! * [`Full`]: The default formatter. This emits human-readable,
+//! single-line logs for each event that occurs, with the current span context
+//! displayed before the formatted representation of the event. See
+//! [here](Full#example-output) for sample output.
+//!
+//! * [`Compact`]: A variant of the default formatter, optimized for
+//! short line lengths. Fields from the current span context are appended to
+//! the fields of the formatted event, and span names are not shown; the
+//! verbosity level is abbreviated to a single character. See
+//! [here](Compact#example-output) for sample output.
+//!
+//! * [`Pretty`]: Emits excessively pretty, multi-line logs, optimized
+//! for human readability. This is primarily intended to be used in local
+//! development and debugging, or for command-line applications, where
+//! automated analysis and compact storage of logs is less of a priority than
+//! readability and visual appeal. See [here](Pretty#example-output)
+//! for sample output.
+//!
+//! * [`Json`]: Outputs newline-delimited JSON logs. This is intended
+//! for production use with systems where structured logs are consumed as JSON
+//! by analysis and viewing tools. The JSON output is not optimized for human
+//! readability. See [here](Json#example-output) for sample output.
use super::time::{FormatTime, SystemTime};
use crate::{
field::{MakeOutput, MakeVisitor, RecordFields, VisitFmt, VisitOutput},
@@ -17,7 +46,7 @@ use tracing_core::{
use tracing_log::NormalizeEvent;
#[cfg(feature = "ansi")]
-use ansi_term::{Colour, Style};
+use nu_ansi_term::{Color, Style};
#[cfg(feature = "json")]
mod json;
@@ -72,7 +101,7 @@ pub use pretty::*;
/// does not support ANSI escape codes (such as a log file), and they should
/// not be emitted.
///
-/// Crates like [`ansi_term`] and [`owo-colors`] can be used to add ANSI
+/// Crates like [`nu_ansi_term`] and [`owo-colors`] can be used to add ANSI
/// escape codes to formatted output.
///
/// * The actual [`Event`] to be formatted.
@@ -153,13 +182,14 @@ pub use pretty::*;
/// DEBUG yak_shaving::shaver: some-span{field-on-span=foo}: started shaving yak
/// ```
///
+/// [`layer::Context`]: crate::layer::Context
/// [`fmt::Layer`]: super::Layer
/// [`fmt::Subscriber`]: super::Subscriber
/// [`Event`]: tracing::Event
/// [implements `FormatFields`]: super::FmtContext#impl-FormatFields<'writer>
/// [ANSI terminal escape codes]: https://en.wikipedia.org/wiki/ANSI_escape_code
/// [`Writer::has_ansi_escapes`]: Writer::has_ansi_escapes
-/// [`ansi_term`]: https://crates.io/crates/ansi_term
+/// [`nu_ansi_term`]: https://crates.io/crates/nu_ansi_term
/// [`owo-colors`]: https://crates.io/crates/owo-colors
/// [default formatter]: Full
pub trait FormatEvent<S, N>
@@ -197,8 +227,8 @@ where
/// time a span or event with fields is recorded, the subscriber will format
/// those fields with its associated `FormatFields` implementation.
///
-/// [set of fields]: ../field/trait.RecordFields.html
-/// [`FmtSubscriber`]: ../fmt/struct.Subscriber.html
+/// [set of fields]: crate::field::RecordFields
+/// [`FmtSubscriber`]: super::Subscriber
pub trait FormatFields<'writer> {
/// Format the provided `fields` to the provided [`Writer`], returning a result.
fn format_fields<R: RecordFields>(&self, writer: Writer<'writer>, fields: R) -> fmt::Result;
@@ -251,7 +281,6 @@ pub fn json() -> Format<Json> {
/// Returns a [`FormatFields`] implementation that formats fields using the
/// provided function or closure.
///
-/// [`FormatFields`]: trait.FormatFields.html
pub fn debug_fn<F>(f: F) -> FieldFn<F>
where
F: Fn(&mut Writer<'_>, &Field, &dyn fmt::Debug) -> fmt::Result + Clone,
@@ -272,6 +301,8 @@ where
///
/// Additionally, a `Writer` may expose additional `tracing`-specific
/// information to the formatter implementation.
+///
+/// [fields]: tracing_core::field
pub struct Writer<'writer> {
writer: &'writer mut dyn fmt::Write,
// TODO(eliza): add ANSI support
@@ -281,28 +312,76 @@ pub struct Writer<'writer> {
/// A [`FormatFields`] implementation that formats fields by calling a function
/// or closure.
///
-/// [`FormatFields`]: trait.FormatFields.html
#[derive(Debug, Clone)]
pub struct FieldFn<F>(F);
/// The [visitor] produced by [`FieldFn`]'s [`MakeVisitor`] implementation.
///
-/// [visitor]: ../../field/trait.Visit.html
-/// [`FieldFn`]: struct.FieldFn.html
-/// [`MakeVisitor`]: ../../field/trait.MakeVisitor.html
+/// [visitor]: super::super::field::Visit
+/// [`MakeVisitor`]: super::super::field::MakeVisitor
pub struct FieldFnVisitor<'a, F> {
f: F,
writer: Writer<'a>,
result: fmt::Result,
}
-/// Marker for `Format` that indicates that the compact log format should be used.
+/// Marker for [`Format`] that indicates that the compact log format should be used.
+///
+/// The compact format includes fields from all currently entered spans, after
+/// the event's fields. Span names are listed in order before fields are
+/// displayed.
+///
+/// # Example Output
///
-/// The compact format only includes the fields from the most recently entered span.
+/// <pre><font color="#4E9A06"><b>:;</b></font> <font color="#4E9A06">cargo</font> run --example fmt-compact
+/// <font color="#4E9A06"><b> Finished</b></font> dev [unoptimized + debuginfo] target(s) in 0.08s
+/// <font color="#4E9A06"><b> Running</b></font> `target/debug/examples/fmt-compact`
+/// <font color="#AAAAAA">2022-02-17T19:51:05.809287Z </font><font color="#4E9A06"> INFO</font> <b>fmt_compact</b><font color="#AAAAAA">: preparing to shave yaks </font><i>number_of_yaks</i><font color="#AAAAAA">=3</font>
+/// <font color="#AAAAAA">2022-02-17T19:51:05.809367Z </font><font color="#4E9A06"> INFO</font> <b>shaving_yaks</b>: <b>fmt_compact::yak_shave</b><font color="#AAAAAA">: shaving yaks </font><font color="#AAAAAA"><i>yaks</i></font><font color="#AAAAAA">=3</font>
+/// <font color="#AAAAAA">2022-02-17T19:51:05.809414Z </font><font color="#75507B">TRACE</font> <b>shaving_yaks</b>:<b>shave</b>: <b>fmt_compact::yak_shave</b><font color="#AAAAAA">: hello! I&apos;m gonna shave a yak </font><i>excitement</i><font color="#AAAAAA">=&quot;yay!&quot; </font><font color="#AAAAAA"><i>yaks</i></font><font color="#AAAAAA">=3 </font><font color="#AAAAAA"><i>yak</i></font><font color="#AAAAAA">=1</font>
+/// <font color="#AAAAAA">2022-02-17T19:51:05.809443Z </font><font color="#75507B">TRACE</font> <b>shaving_yaks</b>:<b>shave</b>: <b>fmt_compact::yak_shave</b><font color="#AAAAAA">: yak shaved successfully </font><font color="#AAAAAA"><i>yaks</i></font><font color="#AAAAAA">=3 </font><font color="#AAAAAA"><i>yak</i></font><font color="#AAAAAA">=1</font>
+/// <font color="#AAAAAA">2022-02-17T19:51:05.809477Z </font><font color="#3465A4">DEBUG</font> <b>shaving_yaks</b>: <b>yak_events</b><font color="#AAAAAA">: </font><i>yak</i><font color="#AAAAAA">=1 </font><i>shaved</i><font color="#AAAAAA">=true </font><font color="#AAAAAA"><i>yaks</i></font><font color="#AAAAAA">=3</font>
+/// <font color="#AAAAAA">2022-02-17T19:51:05.809500Z </font><font color="#75507B">TRACE</font> <b>shaving_yaks</b>: <b>fmt_compact::yak_shave</b><font color="#AAAAAA">: </font><i>yaks_shaved</i><font color="#AAAAAA">=1 </font><font color="#AAAAAA"><i>yaks</i></font><font color="#AAAAAA">=3</font>
+/// <font color="#AAAAAA">2022-02-17T19:51:05.809531Z </font><font color="#75507B">TRACE</font> <b>shaving_yaks</b>:<b>shave</b>: <b>fmt_compact::yak_shave</b><font color="#AAAAAA">: hello! I&apos;m gonna shave a yak </font><i>excitement</i><font color="#AAAAAA">=&quot;yay!&quot; </font><font color="#AAAAAA"><i>yaks</i></font><font color="#AAAAAA">=3 </font><font color="#AAAAAA"><i>yak</i></font><font color="#AAAAAA">=2</font>
+/// <font color="#AAAAAA">2022-02-17T19:51:05.809554Z </font><font color="#75507B">TRACE</font> <b>shaving_yaks</b>:<b>shave</b>: <b>fmt_compact::yak_shave</b><font color="#AAAAAA">: yak shaved successfully </font><font color="#AAAAAA"><i>yaks</i></font><font color="#AAAAAA">=3 </font><font color="#AAAAAA"><i>yak</i></font><font color="#AAAAAA">=2</font>
+/// <font color="#AAAAAA">2022-02-17T19:51:05.809581Z </font><font color="#3465A4">DEBUG</font> <b>shaving_yaks</b>: <b>yak_events</b><font color="#AAAAAA">: </font><i>yak</i><font color="#AAAAAA">=2 </font><i>shaved</i><font color="#AAAAAA">=true </font><font color="#AAAAAA"><i>yaks</i></font><font color="#AAAAAA">=3</font>
+/// <font color="#AAAAAA">2022-02-17T19:51:05.809606Z </font><font color="#75507B">TRACE</font> <b>shaving_yaks</b>: <b>fmt_compact::yak_shave</b><font color="#AAAAAA">: </font><i>yaks_shaved</i><font color="#AAAAAA">=2 </font><font color="#AAAAAA"><i>yaks</i></font><font color="#AAAAAA">=3</font>
+/// <font color="#AAAAAA">2022-02-17T19:51:05.809635Z </font><font color="#75507B">TRACE</font> <b>shaving_yaks</b>:<b>shave</b>: <b>fmt_compact::yak_shave</b><font color="#AAAAAA">: hello! I&apos;m gonna shave a yak </font><i>excitement</i><font color="#AAAAAA">=&quot;yay!&quot; </font><font color="#AAAAAA"><i>yaks</i></font><font color="#AAAAAA">=3 </font><font color="#AAAAAA"><i>yak</i></font><font color="#AAAAAA">=3</font>
+/// <font color="#AAAAAA">2022-02-17T19:51:05.809664Z </font><font color="#C4A000"> WARN</font> <b>shaving_yaks</b>:<b>shave</b>: <b>fmt_compact::yak_shave</b><font color="#AAAAAA">: could not locate yak </font><font color="#AAAAAA"><i>yaks</i></font><font color="#AAAAAA">=3 </font><font color="#AAAAAA"><i>yak</i></font><font color="#AAAAAA">=3</font>
+/// <font color="#AAAAAA">2022-02-17T19:51:05.809693Z </font><font color="#3465A4">DEBUG</font> <b>shaving_yaks</b>: <b>yak_events</b><font color="#AAAAAA">: </font><i>yak</i><font color="#AAAAAA">=3 </font><i>shaved</i><font color="#AAAAAA">=false </font><font color="#AAAAAA"><i>yaks</i></font><font color="#AAAAAA">=3</font>
+/// <font color="#AAAAAA">2022-02-17T19:51:05.809717Z </font><font color="#CC0000">ERROR</font> <b>shaving_yaks</b>: <b>fmt_compact::yak_shave</b><font color="#AAAAAA">: failed to shave yak </font><i>yak</i><font color="#AAAAAA">=3 </font><i>error</i><font color="#AAAAAA">=missing yak </font><i>error.sources</i><font color="#AAAAAA">=[out of space, out of cash] </font><font color="#AAAAAA"><i>yaks</i></font><font color="#AAAAAA">=3</font>
+/// <font color="#AAAAAA">2022-02-17T19:51:05.809743Z </font><font color="#75507B">TRACE</font> <b>shaving_yaks</b>: <b>fmt_compact::yak_shave</b><font color="#AAAAAA">: </font><i>yaks_shaved</i><font color="#AAAAAA">=2 </font><font color="#AAAAAA"><i>yaks</i></font><font color="#AAAAAA">=3</font>
+/// <font color="#AAAAAA">2022-02-17T19:51:05.809768Z </font><font color="#4E9A06"> INFO</font> <b>fmt_compact</b><font color="#AAAAAA">: yak shaving completed </font><i>all_yaks_shaved</i><font color="#AAAAAA">=false</font>
+///
+/// </pre>
#[derive(Default, Debug, Copy, Clone, Eq, PartialEq)]
pub struct Compact;
-/// Marker for `Format` that indicates that the verbose log format should be used.
+/// Marker for [`Format`] that indicates that the default log format should be used.
+///
+/// This formatter shows the span context before printing event data. Spans are
+/// displayed including their names and fields.
///
-/// The full format includes fields from all entered spans.
+/// # Example Output
+///
+/// <pre><font color="#4E9A06"><b>:;</b></font> <font color="#4E9A06">cargo</font> run --example fmt
+/// <font color="#4E9A06"><b> Finished</b></font> dev [unoptimized + debuginfo] target(s) in 0.08s
+/// <font color="#4E9A06"><b> Running</b></font> `target/debug/examples/fmt`
+/// <font color="#AAAAAA">2022-02-15T18:40:14.289898Z </font><font color="#4E9A06"> INFO</font> fmt: preparing to shave yaks <i>number_of_yaks</i><font color="#AAAAAA">=3</font>
+/// <font color="#AAAAAA">2022-02-15T18:40:14.289974Z </font><font color="#4E9A06"> INFO</font> <b>shaving_yaks{</b><i>yaks</i><font color="#AAAAAA">=3</font><b>}</b><font color="#AAAAAA">: fmt::yak_shave: shaving yaks</font>
+/// <font color="#AAAAAA">2022-02-15T18:40:14.290011Z </font><font color="#75507B">TRACE</font> <b>shaving_yaks{</b><i>yaks</i><font color="#AAAAAA">=3</font><b>}</b><font color="#AAAAAA">:</font><b>shave{</b><i>yak</i><font color="#AAAAAA">=1</font><b>}</b><font color="#AAAAAA">: fmt::yak_shave: hello! I&apos;m gonna shave a yak </font><i>excitement</i><font color="#AAAAAA">=&quot;yay!&quot;</font>
+/// <font color="#AAAAAA">2022-02-15T18:40:14.290038Z </font><font color="#75507B">TRACE</font> <b>shaving_yaks{</b><i>yaks</i><font color="#AAAAAA">=3</font><b>}</b><font color="#AAAAAA">:</font><b>shave{</b><i>yak</i><font color="#AAAAAA">=1</font><b>}</b><font color="#AAAAAA">: fmt::yak_shave: yak shaved successfully</font>
+/// <font color="#AAAAAA">2022-02-15T18:40:14.290070Z </font><font color="#3465A4">DEBUG</font> <b>shaving_yaks{</b><i>yaks</i><font color="#AAAAAA">=3</font><b>}</b><font color="#AAAAAA">: yak_events: </font><i>yak</i><font color="#AAAAAA">=1 </font><i>shaved</i><font color="#AAAAAA">=true</font>
+/// <font color="#AAAAAA">2022-02-15T18:40:14.290089Z </font><font color="#75507B">TRACE</font> <b>shaving_yaks{</b><i>yaks</i><font color="#AAAAAA">=3</font><b>}</b><font color="#AAAAAA">: fmt::yak_shave: </font><i>yaks_shaved</i><font color="#AAAAAA">=1</font>
+/// <font color="#AAAAAA">2022-02-15T18:40:14.290114Z </font><font color="#75507B">TRACE</font> <b>shaving_yaks{</b><i>yaks</i><font color="#AAAAAA">=3</font><b>}</b><font color="#AAAAAA">:</font><b>shave{</b><i>yak</i><font color="#AAAAAA">=2</font><b>}</b><font color="#AAAAAA">: fmt::yak_shave: hello! I&apos;m gonna shave a yak </font><i>excitement</i><font color="#AAAAAA">=&quot;yay!&quot;</font>
+/// <font color="#AAAAAA">2022-02-15T18:40:14.290134Z </font><font color="#75507B">TRACE</font> <b>shaving_yaks{</b><i>yaks</i><font color="#AAAAAA">=3</font><b>}</b><font color="#AAAAAA">:</font><b>shave{</b><i>yak</i><font color="#AAAAAA">=2</font><b>}</b><font color="#AAAAAA">: fmt::yak_shave: yak shaved successfully</font>
+/// <font color="#AAAAAA">2022-02-15T18:40:14.290157Z </font><font color="#3465A4">DEBUG</font> <b>shaving_yaks{</b><i>yaks</i><font color="#AAAAAA">=3</font><b>}</b><font color="#AAAAAA">: yak_events: </font><i>yak</i><font color="#AAAAAA">=2 </font><i>shaved</i><font color="#AAAAAA">=true</font>
+/// <font color="#AAAAAA">2022-02-15T18:40:14.290174Z </font><font color="#75507B">TRACE</font> <b>shaving_yaks{</b><i>yaks</i><font color="#AAAAAA">=3</font><b>}</b><font color="#AAAAAA">: fmt::yak_shave: </font><i>yaks_shaved</i><font color="#AAAAAA">=2</font>
+/// <font color="#AAAAAA">2022-02-15T18:40:14.290198Z </font><font color="#75507B">TRACE</font> <b>shaving_yaks{</b><i>yaks</i><font color="#AAAAAA">=3</font><b>}</b><font color="#AAAAAA">:</font><b>shave{</b><i>yak</i><font color="#AAAAAA">=3</font><b>}</b><font color="#AAAAAA">: fmt::yak_shave: hello! I&apos;m gonna shave a yak </font><i>excitement</i><font color="#AAAAAA">=&quot;yay!&quot;</font>
+/// <font color="#AAAAAA">2022-02-15T18:40:14.290222Z </font><font color="#C4A000"> WARN</font> <b>shaving_yaks{</b><i>yaks</i><font color="#AAAAAA">=3</font><b>}</b><font color="#AAAAAA">:</font><b>shave{</b><i>yak</i><font color="#AAAAAA">=3</font><b>}</b><font color="#AAAAAA">: fmt::yak_shave: could not locate yak</font>
+/// <font color="#AAAAAA">2022-02-15T18:40:14.290247Z </font><font color="#3465A4">DEBUG</font> <b>shaving_yaks{</b><i>yaks</i><font color="#AAAAAA">=3</font><b>}</b><font color="#AAAAAA">: yak_events: </font><i>yak</i><font color="#AAAAAA">=3 </font><i>shaved</i><font color="#AAAAAA">=false</font>
+/// <font color="#AAAAAA">2022-02-15T18:40:14.290268Z </font><font color="#CC0000">ERROR</font> <b>shaving_yaks{</b><i>yaks</i><font color="#AAAAAA">=3</font><b>}</b><font color="#AAAAAA">: fmt::yak_shave: failed to shave yak </font><i>yak</i><font color="#AAAAAA">=3 </font><i>error</i><font color="#AAAAAA">=missing yak </font><i>error.sources</i><font color="#AAAAAA">=[out of space, out of cash]</font>
+/// <font color="#AAAAAA">2022-02-15T18:40:14.290287Z </font><font color="#75507B">TRACE</font> <b>shaving_yaks{</b><i>yaks</i><font color="#AAAAAA">=3</font><b>}</b><font color="#AAAAAA">: fmt::yak_shave: </font><i>yaks_shaved</i><font color="#AAAAAA">=2</font>
+/// <font color="#AAAAAA">2022-02-15T18:40:14.290309Z </font><font color="#4E9A06"> INFO</font> fmt: yak shaving completed. <i>all_yaks_shaved</i><font color="#AAAAAA">=false</font>
+/// </pre>
#[derive(Default, Debug, Copy, Clone, Eq, PartialEq)]
pub struct Full;
@@ -311,8 +390,11 @@ pub struct Full;
/// You will usually want to use this as the `FormatEvent` for a `FmtSubscriber`.
///
/// The default logging format, [`Full`] includes all fields in each event and its containing
-/// spans. The [`Compact`] logging format includes only the fields from the most-recently-entered
-/// span.
+/// spans. The [`Compact`] logging format is intended to produce shorter log
+/// lines; it displays each event's fields, along with fields from the current
+/// span context, but other information is abbreviated. The [`Pretty`] logging
+/// format is an extra-verbose, multi-line human-readable logging format
+/// intended for use in development.
#[derive(Debug, Clone)]
pub struct Format<F = Full, T = SystemTime> {
format: F,
@@ -323,6 +405,8 @@ pub struct Format<F = Full, T = SystemTime> {
pub(crate) display_level: bool,
pub(crate) display_thread_id: bool,
pub(crate) display_thread_name: bool,
+ pub(crate) display_filename: bool,
+ pub(crate) display_line_number: bool,
}
// === impl Writer ===
@@ -499,6 +583,8 @@ impl Default for Format<Full, SystemTime> {
display_level: true,
display_thread_id: false,
display_thread_name: false,
+ display_filename: false,
+ display_line_number: false,
}
}
}
@@ -517,6 +603,8 @@ impl<F, T> Format<F, T> {
display_level: self.display_level,
display_thread_id: self.display_thread_id,
display_thread_name: self.display_thread_name,
+ display_filename: self.display_filename,
+ display_line_number: self.display_line_number,
}
}
@@ -554,6 +642,8 @@ impl<F, T> Format<F, T> {
display_level: self.display_level,
display_thread_id: self.display_thread_id,
display_thread_name: self.display_thread_name,
+ display_filename: true,
+ display_line_number: true,
}
}
@@ -571,8 +661,6 @@ impl<F, T> Format<F, T> {
///
/// - [`Format::flatten_event`] can be used to enable flattening event fields into the root
/// object.
- ///
- /// [`Format::flatten_event`]: #method.flatten_event
#[cfg(feature = "json")]
#[cfg_attr(docsrs, doc(cfg(feature = "json")))]
pub fn json(self) -> Format<Json, T> {
@@ -585,6 +673,8 @@ impl<F, T> Format<F, T> {
display_level: self.display_level,
display_thread_id: self.display_thread_id,
display_thread_name: self.display_thread_name,
+ display_filename: self.display_filename,
+ display_line_number: self.display_line_number,
}
}
@@ -612,6 +702,8 @@ impl<F, T> Format<F, T> {
display_level: self.display_level,
display_thread_id: self.display_thread_id,
display_thread_name: self.display_thread_name,
+ display_filename: self.display_filename,
+ display_line_number: self.display_line_number,
}
}
@@ -626,6 +718,8 @@ impl<F, T> Format<F, T> {
display_level: self.display_level,
display_thread_id: self.display_thread_id,
display_thread_name: self.display_thread_name,
+ display_filename: self.display_filename,
+ display_line_number: self.display_line_number,
}
}
@@ -654,9 +748,9 @@ impl<F, T> Format<F, T> {
}
/// Sets whether or not the [thread ID] of the current thread is displayed
- /// when formatting events
+ /// when formatting events.
///
- /// [thread ID]: https://doc.rust-lang.org/stable/std/thread/struct.ThreadId.html
+ /// [thread ID]: std::thread::ThreadId
pub fn with_thread_ids(self, display_thread_id: bool) -> Format<F, T> {
Format {
display_thread_id,
@@ -665,9 +759,9 @@ impl<F, T> Format<F, T> {
}
/// Sets whether or not the [name] of the current thread is displayed
- /// when formatting events
+ /// when formatting events.
///
- /// [name]: https://doc.rust-lang.org/stable/std/thread/index.html#naming-threads
+ /// [name]: std::thread#naming-threads
pub fn with_thread_names(self, display_thread_name: bool) -> Format<F, T> {
Format {
display_thread_name,
@@ -675,6 +769,38 @@ impl<F, T> Format<F, T> {
}
}
+ /// Sets whether or not an event's [source code file path][file] is
+ /// displayed.
+ ///
+ /// [file]: tracing_core::Metadata::file
+ pub fn with_file(self, display_filename: bool) -> Format<F, T> {
+ Format {
+ display_filename,
+ ..self
+ }
+ }
+
+ /// Sets whether or not an event's [source code line number][line] is
+ /// displayed.
+ ///
+ /// [line]: tracing_core::Metadata::line
+ pub fn with_line_number(self, display_line_number: bool) -> Format<F, T> {
+ Format {
+ display_line_number,
+ ..self
+ }
+ }
+
+ /// Sets whether or not the source code location from which an event
+ /// originated is displayed.
+ ///
+ /// This is equivalent to calling [`Format::with_file`] and
+ /// [`Format::with_line_number`] with the same value.
+ pub fn with_source_location(self, display_location: bool) -> Self {
+ self.with_line_number(display_location)
+ .with_file(display_location)
+ }
+
#[inline]
fn format_timestamp(&self, writer: &mut Writer<'_>) -> fmt::Result
where
@@ -692,14 +818,24 @@ impl<F, T> Format<F, T> {
if writer.has_ansi_escapes() {
let style = Style::new().dimmed();
write!(writer, "{}", style.prefix())?;
- self.timer.format_time(writer)?;
+
+ // If getting the timestamp failed, don't bail --- only bail on
+ // formatting errors.
+ if self.timer.format_time(writer).is_err() {
+ writer.write_str("<unknown time>")?;
+ }
+
write!(writer, "{} ", style.suffix())?;
return Ok(());
}
}
// Otherwise, just format the timestamp without ANSI formatting.
- self.timer.format_time(writer)?;
+ // If getting the timestamp failed, don't bail --- only bail on
+ // formatting errors.
+ if self.timer.format_time(writer).is_err() {
+ writer.write_str("<unknown time>")?;
+ }
writer.write_char(' ')
}
}
@@ -714,7 +850,7 @@ impl<T> Format<Json, T> {
/// ```ignore,json
/// {"timestamp":"Feb 20 11:28:15.096","level":"INFO","target":"mycrate", "message":"some message", "key": "value"}
/// ```
- /// See [`Json`](../format/struct.Json.html).
+ /// See [`Json`][super::format::Json].
#[cfg(feature = "json")]
#[cfg_attr(docsrs, doc(cfg(feature = "json")))]
pub fn flatten_event(mut self, flatten_event: bool) -> Format<Json, T> {
@@ -725,7 +861,7 @@ impl<T> Format<Json, T> {
/// Sets whether or not the formatter will include the current span in
/// formatted events.
///
- /// See [`format::Json`](../fmt/format/struct.Json.html)
+ /// See [`format::Json`][Json]
#[cfg(feature = "json")]
#[cfg_attr(docsrs, doc(cfg(feature = "json")))]
pub fn with_current_span(mut self, display_current_span: bool) -> Format<Json, T> {
@@ -736,7 +872,7 @@ impl<T> Format<Json, T> {
/// Sets whether or not the formatter will include a list (from root to
/// leaf) of all currently entered spans in formatted events.
///
- /// See [`format::Json`](../fmt/format/struct.Json.html)
+ /// See [`format::Json`][Json]
#[cfg(feature = "json")]
#[cfg_attr(docsrs, doc(cfg(feature = "json")))]
pub fn with_span_list(mut self, display_span_list: bool) -> Format<Json, T> {
@@ -840,6 +976,34 @@ where
)?;
}
+ let line_number = if self.display_line_number {
+ meta.line()
+ } else {
+ None
+ };
+
+ if self.display_filename {
+ if let Some(filename) = meta.file() {
+ write!(
+ writer,
+ "{}{}{}",
+ dimmed.paint(filename),
+ dimmed.paint(":"),
+ if line_number.is_some() { "" } else { " " }
+ )?;
+ }
+ }
+
+ if let Some(line_number) = line_number {
+ write!(
+ writer,
+ "{}{}:{} ",
+ dimmed.prefix(),
+ line_number,
+ dimmed.suffix()
+ )?;
+ }
+
ctx.format_fields(writer.by_ref(), event)?;
writeln!(writer)
}
@@ -918,23 +1082,49 @@ where
};
write!(writer, "{}", fmt_ctx)?;
+ let bold = writer.bold();
+ let dimmed = writer.dimmed();
+
+ let mut needs_space = false;
if self.display_target {
- write!(
- writer,
- "{}{} ",
- writer.bold().paint(meta.target()),
- writer.dimmed().paint(":")
- )?;
+ write!(writer, "{}{}", bold.paint(meta.target()), dimmed.paint(":"))?;
+ needs_space = true;
+ }
+
+ if self.display_filename {
+ if let Some(filename) = meta.file() {
+ if self.display_target {
+ writer.write_char(' ')?;
+ }
+ write!(writer, "{}{}", bold.paint(filename), dimmed.paint(":"))?;
+ needs_space = true;
+ }
+ }
+
+ if self.display_line_number {
+ if let Some(line_number) = meta.line() {
+ write!(
+ writer,
+ "{}{}{}{}",
+ bold.prefix(),
+ line_number,
+ bold.suffix(),
+ dimmed.paint(":")
+ )?;
+ needs_space = true;
+ }
+ }
+
+ if needs_space {
+ writer.write_char(' ')?;
}
ctx.format_fields(writer.by_ref(), event)?;
- let dimmed = writer.dimmed();
for span in ctx
.event_scope()
.into_iter()
- .map(crate::registry::Scope::from_root)
- .flatten()
+ .flat_map(crate::registry::Scope::from_root)
{
let exts = span.extensions();
if let Some(fields) = exts.get::<FormattedFields<N>>() {
@@ -962,7 +1152,6 @@ where
/// The default [`FormatFields`] implementation.
///
-/// [`FormatFields`]: trait.FormatFields.html
#[derive(Debug)]
pub struct DefaultFields {
// reserve the ability to add fields to this without causing a breaking
@@ -984,7 +1173,6 @@ pub struct DefaultVisitor<'a> {
impl DefaultFields {
/// Returns a new default [`FormatFields`] implementation.
///
- /// [`FormatFields`]: trait.FormatFields.html
pub fn new() -> Self {
Self { _private: () }
}
@@ -1201,6 +1389,14 @@ impl Style {
fn paint(&self, d: impl fmt::Display) -> impl fmt::Display {
d
}
+
+ fn prefix(&self) -> impl fmt::Display {
+ ""
+ }
+
+ fn suffix(&self) -> impl fmt::Display {
+ ""
+ }
}
struct FmtThreadName<'a> {
@@ -1288,11 +1484,11 @@ impl<'a> fmt::Display for FmtLevel<'a> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
if self.ansi {
match *self.level {
- Level::TRACE => write!(f, "{}", Colour::Purple.paint(TRACE_STR)),
- Level::DEBUG => write!(f, "{}", Colour::Blue.paint(DEBUG_STR)),
- Level::INFO => write!(f, "{}", Colour::Green.paint(INFO_STR)),
- Level::WARN => write!(f, "{}", Colour::Yellow.paint(WARN_STR)),
- Level::ERROR => write!(f, "{}", Colour::Red.paint(ERROR_STR)),
+ Level::TRACE => write!(f, "{}", Color::Purple.paint(TRACE_STR)),
+ Level::DEBUG => write!(f, "{}", Color::Blue.paint(DEBUG_STR)),
+ Level::INFO => write!(f, "{}", Color::Green.paint(INFO_STR)),
+ Level::WARN => write!(f, "{}", Color::Yellow.paint(WARN_STR)),
+ Level::ERROR => write!(f, "{}", Color::Red.paint(ERROR_STR)),
}
} else {
match *self.level {
@@ -1366,7 +1562,7 @@ impl<'a, F> fmt::Debug for FieldFnVisitor<'a, F> {
/// Configures what points in the span lifecycle are logged as events.
///
-/// See also [`with_span_events`](../struct.SubscriberBuilder.html#method.with_span_events).
+/// See also [`with_span_events`](super::SubscriberBuilder.html::with_span_events).
#[derive(Clone, Eq, PartialEq, Ord, PartialOrd)]
pub struct FmtSpan(u8);
@@ -1528,7 +1724,9 @@ pub(super) mod test {
};
use super::*;
- use std::fmt;
+
+ use regex::Regex;
+ use std::{fmt, path::Path};
pub(crate) struct MockTime;
impl FormatTime for MockTime {
@@ -1550,7 +1748,7 @@ pub(super) mod test {
.with_thread_names(false);
#[cfg(feature = "ansi")]
let subscriber = subscriber.with_ansi(false);
- run_test(subscriber, make_writer, "hello\n")
+ assert_info_hello(subscriber, make_writer, "hello\n")
}
fn test_ansi<T>(
@@ -1598,6 +1796,124 @@ pub(super) mod test {
run_test(subscriber, make_writer, expected);
}
+ #[test]
+ fn with_line_number_and_file_name() {
+ let make_writer = MockMakeWriter::default();
+ let subscriber = crate::fmt::Subscriber::builder()
+ .with_writer(make_writer.clone())
+ .with_file(true)
+ .with_line_number(true)
+ .with_level(false)
+ .with_ansi(false)
+ .with_timer(MockTime);
+
+ let expected = Regex::new(&format!(
+ "^fake time tracing_subscriber::fmt::format::test: {}:[0-9]+: hello\n$",
+ current_path()
+ // if we're on Windows, the path might contain backslashes, which
+ // have to be escpaed before compiling the regex.
+ .replace('\\', "\\\\")
+ ))
+ .unwrap();
+ let _default = set_default(&subscriber.into());
+ tracing::info!("hello");
+ let res = make_writer.get_string();
+ assert!(expected.is_match(&res));
+ }
+
+ #[test]
+ fn with_line_number() {
+ let make_writer = MockMakeWriter::default();
+ let subscriber = crate::fmt::Subscriber::builder()
+ .with_writer(make_writer.clone())
+ .with_line_number(true)
+ .with_level(false)
+ .with_ansi(false)
+ .with_timer(MockTime);
+
+ let expected =
+ Regex::new("^fake time tracing_subscriber::fmt::format::test: [0-9]+: hello\n$")
+ .unwrap();
+ let _default = set_default(&subscriber.into());
+ tracing::info!("hello");
+ let res = make_writer.get_string();
+ assert!(expected.is_match(&res));
+ }
+
+ #[test]
+ fn with_filename() {
+ let make_writer = MockMakeWriter::default();
+ let subscriber = crate::fmt::Subscriber::builder()
+ .with_writer(make_writer.clone())
+ .with_file(true)
+ .with_level(false)
+ .with_ansi(false)
+ .with_timer(MockTime);
+ let expected = &format!(
+ "fake time tracing_subscriber::fmt::format::test: {}: hello\n",
+ current_path(),
+ );
+ assert_info_hello(subscriber, make_writer, expected);
+ }
+
+ #[test]
+ fn with_thread_ids() {
+ let make_writer = MockMakeWriter::default();
+ let subscriber = crate::fmt::Subscriber::builder()
+ .with_writer(make_writer.clone())
+ .with_thread_ids(true)
+ .with_ansi(false)
+ .with_timer(MockTime);
+ let expected =
+ "fake time INFO ThreadId(NUMERIC) tracing_subscriber::fmt::format::test: hello\n";
+
+ assert_info_hello_ignore_numeric(subscriber, make_writer, expected);
+ }
+
+ #[test]
+ fn pretty_default() {
+ let make_writer = MockMakeWriter::default();
+ let subscriber = crate::fmt::Subscriber::builder()
+ .pretty()
+ .with_writer(make_writer.clone())
+ .with_ansi(false)
+ .with_timer(MockTime);
+ let expected = format!(
+ r#" fake time INFO tracing_subscriber::fmt::format::test: hello
+ at {}:NUMERIC
+
+"#,
+ file!()
+ );
+
+ assert_info_hello_ignore_numeric(subscriber, make_writer, &expected)
+ }
+
+ fn assert_info_hello(subscriber: impl Into<Dispatch>, buf: MockMakeWriter, expected: &str) {
+ let _default = set_default(&subscriber.into());
+ tracing::info!("hello");
+ let result = buf.get_string();
+
+ assert_eq!(expected, result)
+ }
+
+ // When numeric characters are used they often form a non-deterministic value as they usually represent things like a thread id or line number.
+ // This assert method should be used when non-deterministic numeric characters are present.
+ fn assert_info_hello_ignore_numeric(
+ subscriber: impl Into<Dispatch>,
+ buf: MockMakeWriter,
+ expected: &str,
+ ) {
+ let _default = set_default(&subscriber.into());
+ tracing::info!("hello");
+
+ let regex = Regex::new("[0-9]+").unwrap();
+ let result = buf.get_string();
+ let result_cleaned = regex.replace_all(&result, "NUMERIC");
+
+ assert_eq!(expected, result_cleaned)
+ }
+
fn test_overridden_parents<T>(
expected: &str,
builder: crate::fmt::SubscriberBuilder<DefaultFields, Format<T>>,
@@ -1606,14 +1922,14 @@ pub(super) mod test {
T: Send + Sync + 'static,
{
let make_writer = MockMakeWriter::default();
- let collector = builder
+ let subscriber = builder
.with_writer(make_writer.clone())
.with_level(false)
.with_ansi(false)
.with_timer(MockTime)
.finish();
- with_default(collector, || {
+ with_default(subscriber, || {
let span1 = tracing::info_span!("span1", span = 1);
let span2 = tracing::info_span!(parent: &span1, "span2", span = 2);
tracing::info!(parent: &span2, "hello");
@@ -1659,6 +1975,21 @@ pub(super) mod test {
mod default {
use super::*;
+
+ #[test]
+ fn with_thread_ids() {
+ let make_writer = MockMakeWriter::default();
+ let subscriber = crate::fmt::Subscriber::builder()
+ .with_writer(make_writer.clone())
+ .with_thread_ids(true)
+ .with_ansi(false)
+ .with_timer(MockTime);
+ let expected =
+ "fake time INFO ThreadId(NUMERIC) tracing_subscriber::fmt::format::test: hello\n";
+
+ assert_info_hello_ignore_numeric(subscriber, make_writer, expected);
+ }
+
#[cfg(feature = "ansi")]
#[test]
fn with_ansi_true() {
@@ -1748,6 +2079,26 @@ pub(super) mod test {
}
}
+ mod pretty {
+ use super::*;
+
+ #[test]
+ fn pretty_default() {
+ let make_writer = MockMakeWriter::default();
+ let subscriber = crate::fmt::Subscriber::builder()
+ .pretty()
+ .with_writer(make_writer.clone())
+ .with_ansi(false)
+ .with_timer(MockTime);
+ let expected = format!(
+ " fake time INFO tracing_subscriber::fmt::format::test: hello\n at {}:NUMERIC\n\n",
+ file!()
+ );
+
+ assert_info_hello_ignore_numeric(subscriber, make_writer, &expected)
+ }
+ }
+
#[test]
fn format_nanos() {
fn fmt(t: u64) -> String {
@@ -1795,4 +2146,16 @@ pub(super) mod test {
assert!(!f.contains(FmtSpan::EXIT));
assert!(f.contains(FmtSpan::CLOSE));
}
+
+ /// Returns the test's module path.
+ fn current_path() -> String {
+ Path::new("tracing-subscriber")
+ .join("src")
+ .join("fmt")
+ .join("format")
+ .join("mod.rs")
+ .to_str()
+ .expect("path must not contain invalid unicode")
+ .to_owned()
+ }
}
diff --git a/vendor/tracing-subscriber/src/fmt/format/pretty.rs b/vendor/tracing-subscriber/src/fmt/format/pretty.rs
new file mode 100644
index 000000000..12071de92
--- /dev/null
+++ b/vendor/tracing-subscriber/src/fmt/format/pretty.rs
@@ -0,0 +1,511 @@
+use super::*;
+use crate::{
+ field::{VisitFmt, VisitOutput},
+ fmt::fmt_layer::{FmtContext, FormattedFields},
+ registry::LookupSpan,
+};
+
+use std::fmt;
+use tracing_core::{
+ field::{self, Field},
+ Event, Level, Subscriber,
+};
+
+#[cfg(feature = "tracing-log")]
+use tracing_log::NormalizeEvent;
+
+use nu_ansi_term::{Color, Style};
+
+/// An excessively pretty, human-readable event formatter.
+///
+/// Unlike the [`Full`], [`Compact`], and [`Json`] formatters, this is a
+/// multi-line output format. Each individual event may output multiple lines of
+/// text.
+///
+/// # Example Output
+///
+/// <pre><font color="#4E9A06"><b>:;</b></font> <font color="#4E9A06">cargo</font> run --example fmt-pretty
+/// <font color="#4E9A06"><b> Finished</b></font> dev [unoptimized + debuginfo] target(s) in 0.08s
+/// <font color="#4E9A06"><b> Running</b></font> `target/debug/examples/fmt-pretty`
+/// 2022-02-15T18:44:24.535324Z <font color="#4E9A06"> INFO</font> <font color="#4E9A06"><b>fmt_pretty</b></font><font color="#4E9A06">: preparing to shave yaks, </font><font color="#4E9A06"><b>number_of_yaks</b></font><font color="#4E9A06">: 3</font>
+/// <font color="#AAAAAA"><i>at</i></font> examples/examples/fmt-pretty.rs:16 <font color="#AAAAAA"><i>on</i></font> main
+///
+/// 2022-02-15T18:44:24.535403Z <font color="#4E9A06"> INFO</font> <font color="#4E9A06"><b>fmt_pretty::yak_shave</b></font><font color="#4E9A06">: shaving yaks</font>
+/// <font color="#AAAAAA"><i>at</i></font> examples/examples/fmt/yak_shave.rs:41 <font color="#AAAAAA"><i>on</i></font> main
+/// <font color="#AAAAAA"><i>in</i></font> fmt_pretty::yak_shave::<b>shaving_yaks</b> <font color="#AAAAAA"><i>with</i></font> <b>yaks</b>: 3
+///
+/// 2022-02-15T18:44:24.535442Z <font color="#75507B">TRACE</font> <font color="#75507B"><b>fmt_pretty::yak_shave</b></font><font color="#75507B">: hello! I&apos;m gonna shave a yak, </font><font color="#75507B"><b>excitement</b></font><font color="#75507B">: &quot;yay!&quot;</font>
+/// <font color="#AAAAAA"><i>at</i></font> examples/examples/fmt/yak_shave.rs:16 <font color="#AAAAAA"><i>on</i></font> main
+/// <font color="#AAAAAA"><i>in</i></font> fmt_pretty::yak_shave::<b>shave</b> <font color="#AAAAAA"><i>with</i></font> <b>yak</b>: 1
+/// <font color="#AAAAAA"><i>in</i></font> fmt_pretty::yak_shave::<b>shaving_yaks</b> <font color="#AAAAAA"><i>with</i></font> <b>yaks</b>: 3
+///
+/// 2022-02-15T18:44:24.535469Z <font color="#75507B">TRACE</font> <font color="#75507B"><b>fmt_pretty::yak_shave</b></font><font color="#75507B">: yak shaved successfully</font>
+/// <font color="#AAAAAA"><i>at</i></font> examples/examples/fmt/yak_shave.rs:25 <font color="#AAAAAA"><i>on</i></font> main
+/// <font color="#AAAAAA"><i>in</i></font> fmt_pretty::yak_shave::<b>shave</b> <font color="#AAAAAA"><i>with</i></font> <b>yak</b>: 1
+/// <font color="#AAAAAA"><i>in</i></font> fmt_pretty::yak_shave::<b>shaving_yaks</b> <font color="#AAAAAA"><i>with</i></font> <b>yaks</b>: 3
+///
+/// 2022-02-15T18:44:24.535502Z <font color="#3465A4">DEBUG</font> <font color="#3465A4"><b>yak_events</b></font><font color="#3465A4">: </font><font color="#3465A4"><b>yak</b></font><font color="#3465A4">: 1, </font><font color="#3465A4"><b>shaved</b></font><font color="#3465A4">: true</font>
+/// <font color="#AAAAAA"><i>at</i></font> examples/examples/fmt/yak_shave.rs:46 <font color="#AAAAAA"><i>on</i></font> main
+/// <font color="#AAAAAA"><i>in</i></font> fmt_pretty::yak_shave::<b>shaving_yaks</b> <font color="#AAAAAA"><i>with</i></font> <b>yaks</b>: 3
+///
+/// 2022-02-15T18:44:24.535524Z <font color="#75507B">TRACE</font> <font color="#75507B"><b>fmt_pretty::yak_shave</b></font><font color="#75507B">: </font><font color="#75507B"><b>yaks_shaved</b></font><font color="#75507B">: 1</font>
+/// <font color="#AAAAAA"><i>at</i></font> examples/examples/fmt/yak_shave.rs:55 <font color="#AAAAAA"><i>on</i></font> main
+/// <font color="#AAAAAA"><i>in</i></font> fmt_pretty::yak_shave::<b>shaving_yaks</b> <font color="#AAAAAA"><i>with</i></font> <b>yaks</b>: 3
+///
+/// 2022-02-15T18:44:24.535551Z <font color="#75507B">TRACE</font> <font color="#75507B"><b>fmt_pretty::yak_shave</b></font><font color="#75507B">: hello! I&apos;m gonna shave a yak, </font><font color="#75507B"><b>excitement</b></font><font color="#75507B">: &quot;yay!&quot;</font>
+/// <font color="#AAAAAA"><i>at</i></font> examples/examples/fmt/yak_shave.rs:16 <font color="#AAAAAA"><i>on</i></font> main
+/// <font color="#AAAAAA"><i>in</i></font> fmt_pretty::yak_shave::<b>shave</b> <font color="#AAAAAA"><i>with</i></font> <b>yak</b>: 2
+/// <font color="#AAAAAA"><i>in</i></font> fmt_pretty::yak_shave::<b>shaving_yaks</b> <font color="#AAAAAA"><i>with</i></font> <b>yaks</b>: 3
+///
+/// 2022-02-15T18:44:24.535573Z <font color="#75507B">TRACE</font> <font color="#75507B"><b>fmt_pretty::yak_shave</b></font><font color="#75507B">: yak shaved successfully</font>
+/// <font color="#AAAAAA"><i>at</i></font> examples/examples/fmt/yak_shave.rs:25 <font color="#AAAAAA"><i>on</i></font> main
+/// <font color="#AAAAAA"><i>in</i></font> fmt_pretty::yak_shave::<b>shave</b> <font color="#AAAAAA"><i>with</i></font> <b>yak</b>: 2
+/// <font color="#AAAAAA"><i>in</i></font> fmt_pretty::yak_shave::<b>shaving_yaks</b> <font color="#AAAAAA"><i>with</i></font> <b>yaks</b>: 3
+///
+/// 2022-02-15T18:44:24.535600Z <font color="#3465A4">DEBUG</font> <font color="#3465A4"><b>yak_events</b></font><font color="#3465A4">: </font><font color="#3465A4"><b>yak</b></font><font color="#3465A4">: 2, </font><font color="#3465A4"><b>shaved</b></font><font color="#3465A4">: true</font>
+/// <font color="#AAAAAA"><i>at</i></font> examples/examples/fmt/yak_shave.rs:46 <font color="#AAAAAA"><i>on</i></font> main
+/// <font color="#AAAAAA"><i>in</i></font> fmt_pretty::yak_shave::<b>shaving_yaks</b> <font color="#AAAAAA"><i>with</i></font> <b>yaks</b>: 3
+///
+/// 2022-02-15T18:44:24.535618Z <font color="#75507B">TRACE</font> <font color="#75507B"><b>fmt_pretty::yak_shave</b></font><font color="#75507B">: </font><font color="#75507B"><b>yaks_shaved</b></font><font color="#75507B">: 2</font>
+/// <font color="#AAAAAA"><i>at</i></font> examples/examples/fmt/yak_shave.rs:55 <font color="#AAAAAA"><i>on</i></font> main
+/// <font color="#AAAAAA"><i>in</i></font> fmt_pretty::yak_shave::<b>shaving_yaks</b> <font color="#AAAAAA"><i>with</i></font> <b>yaks</b>: 3
+///
+/// 2022-02-15T18:44:24.535644Z <font color="#75507B">TRACE</font> <font color="#75507B"><b>fmt_pretty::yak_shave</b></font><font color="#75507B">: hello! I&apos;m gonna shave a yak, </font><font color="#75507B"><b>excitement</b></font><font color="#75507B">: &quot;yay!&quot;</font>
+/// <font color="#AAAAAA"><i>at</i></font> examples/examples/fmt/yak_shave.rs:16 <font color="#AAAAAA"><i>on</i></font> main
+/// <font color="#AAAAAA"><i>in</i></font> fmt_pretty::yak_shave::<b>shave</b> <font color="#AAAAAA"><i>with</i></font> <b>yak</b>: 3
+/// <font color="#AAAAAA"><i>in</i></font> fmt_pretty::yak_shave::<b>shaving_yaks</b> <font color="#AAAAAA"><i>with</i></font> <b>yaks</b>: 3
+///
+/// 2022-02-15T18:44:24.535670Z <font color="#C4A000"> WARN</font> <font color="#C4A000"><b>fmt_pretty::yak_shave</b></font><font color="#C4A000">: could not locate yak</font>
+/// <font color="#AAAAAA"><i>at</i></font> examples/examples/fmt/yak_shave.rs:18 <font color="#AAAAAA"><i>on</i></font> main
+/// <font color="#AAAAAA"><i>in</i></font> fmt_pretty::yak_shave::<b>shave</b> <font color="#AAAAAA"><i>with</i></font> <b>yak</b>: 3
+/// <font color="#AAAAAA"><i>in</i></font> fmt_pretty::yak_shave::<b>shaving_yaks</b> <font color="#AAAAAA"><i>with</i></font> <b>yaks</b>: 3
+///
+/// 2022-02-15T18:44:24.535698Z <font color="#3465A4">DEBUG</font> <font color="#3465A4"><b>yak_events</b></font><font color="#3465A4">: </font><font color="#3465A4"><b>yak</b></font><font color="#3465A4">: 3, </font><font color="#3465A4"><b>shaved</b></font><font color="#3465A4">: false</font>
+/// <font color="#AAAAAA"><i>at</i></font> examples/examples/fmt/yak_shave.rs:46 <font color="#AAAAAA"><i>on</i></font> main
+/// <font color="#AAAAAA"><i>in</i></font> fmt_pretty::yak_shave::<b>shaving_yaks</b> <font color="#AAAAAA"><i>with</i></font> <b>yaks</b>: 3
+///
+/// 2022-02-15T18:44:24.535720Z <font color="#CC0000">ERROR</font> <font color="#CC0000"><b>fmt_pretty::yak_shave</b></font><font color="#CC0000">: failed to shave yak, </font><font color="#CC0000"><b>yak</b></font><font color="#CC0000">: 3, </font><font color="#CC0000"><b>error</b></font><font color="#CC0000">: missing yak, </font><font color="#CC0000"><b>error.sources</b></font><font color="#CC0000">: [out of space, out of cash]</font>
+/// <font color="#AAAAAA"><i>at</i></font> examples/examples/fmt/yak_shave.rs:51 <font color="#AAAAAA"><i>on</i></font> main
+/// <font color="#AAAAAA"><i>in</i></font> fmt_pretty::yak_shave::<b>shaving_yaks</b> <font color="#AAAAAA"><i>with</i></font> <b>yaks</b>: 3
+///
+/// 2022-02-15T18:44:24.535742Z <font color="#75507B">TRACE</font> <font color="#75507B"><b>fmt_pretty::yak_shave</b></font><font color="#75507B">: </font><font color="#75507B"><b>yaks_shaved</b></font><font color="#75507B">: 2</font>
+/// <font color="#AAAAAA"><i>at</i></font> examples/examples/fmt/yak_shave.rs:55 <font color="#AAAAAA"><i>on</i></font> main
+/// <font color="#AAAAAA"><i>in</i></font> fmt_pretty::yak_shave::<b>shaving_yaks</b> <font color="#AAAAAA"><i>with</i></font> <b>yaks</b>: 3
+///
+/// 2022-02-15T18:44:24.535765Z <font color="#4E9A06"> INFO</font> <font color="#4E9A06"><b>fmt_pretty</b></font><font color="#4E9A06">: yak shaving completed, </font><font color="#4E9A06"><b>all_yaks_shaved</b></font><font color="#4E9A06">: false</font>
+/// <font color="#AAAAAA"><i>at</i></font> examples/examples/fmt-pretty.rs:19 <font color="#AAAAAA"><i>on</i></font> main
+/// </pre>
+#[derive(Debug, Clone, Eq, PartialEq)]
+pub struct Pretty {
+ display_location: bool,
+}
+
+/// The [visitor] produced by [`Pretty`]'s [`MakeVisitor`] implementation.
+///
+/// [visitor]: field::Visit
+/// [`MakeVisitor`]: crate::field::MakeVisitor
+#[derive(Debug)]
+pub struct PrettyVisitor<'a> {
+ writer: Writer<'a>,
+ is_empty: bool,
+ style: Style,
+ result: fmt::Result,
+}
+
+/// An excessively pretty, human-readable [`MakeVisitor`] implementation.
+///
+/// [`MakeVisitor`]: crate::field::MakeVisitor
+#[derive(Debug)]
+pub struct PrettyFields {
+ /// A value to override the provided `Writer`'s ANSI formatting
+ /// configuration.
+ ///
+ /// If this is `Some`, we override the `Writer`'s ANSI setting. This is
+ /// necessary in order to continue supporting the deprecated
+ /// `PrettyFields::with_ansi` method. If it is `None`, we don't override the
+ /// ANSI formatting configuration (because the deprecated method was not
+ /// called).
+ // TODO: when `PrettyFields::with_ansi` is removed, we can get rid
+ // of this entirely.
+ ansi: Option<bool>,
+}
+
+// === impl Pretty ===
+
+impl Default for Pretty {
+ fn default() -> Self {
+ Self {
+ display_location: true,
+ }
+ }
+}
+
+impl Pretty {
+ fn style_for(level: &Level) -> Style {
+ match *level {
+ Level::TRACE => Style::new().fg(Color::Purple),
+ Level::DEBUG => Style::new().fg(Color::Blue),
+ Level::INFO => Style::new().fg(Color::Green),
+ Level::WARN => Style::new().fg(Color::Yellow),
+ Level::ERROR => Style::new().fg(Color::Red),
+ }
+ }
+
+ /// Sets whether the event's source code location is displayed.
+ ///
+ /// This defaults to `true`.
+ #[deprecated(
+ since = "0.3.6",
+ note = "all formatters now support configurable source locations. Use `Format::with_source_location` instead."
+ )]
+ pub fn with_source_location(self, display_location: bool) -> Self {
+ Self {
+ display_location,
+ ..self
+ }
+ }
+}
+
+impl<C, N, T> FormatEvent<C, N> for Format<Pretty, T>
+where
+ C: Subscriber + for<'a> LookupSpan<'a>,
+ N: for<'a> FormatFields<'a> + 'static,
+ T: FormatTime,
+{
+ fn format_event(
+ &self,
+ ctx: &FmtContext<'_, C, N>,
+ mut writer: Writer<'_>,
+ event: &Event<'_>,
+ ) -> fmt::Result {
+ #[cfg(feature = "tracing-log")]
+ let normalized_meta = event.normalized_metadata();
+ #[cfg(feature = "tracing-log")]
+ let meta = normalized_meta.as_ref().unwrap_or_else(|| event.metadata());
+ #[cfg(not(feature = "tracing-log"))]
+ let meta = event.metadata();
+ write!(&mut writer, " ")?;
+
+ // if the `Format` struct *also* has an ANSI color configuration,
+ // override the writer...the API for configuring ANSI color codes on the
+ // `Format` struct is deprecated, but we still need to honor those
+ // configurations.
+ if let Some(ansi) = self.ansi {
+ writer = writer.with_ansi(ansi);
+ }
+
+ self.format_timestamp(&mut writer)?;
+
+ let style = if self.display_level && writer.has_ansi_escapes() {
+ Pretty::style_for(meta.level())
+ } else {
+ Style::new()
+ };
+
+ if self.display_level {
+ write!(
+ writer,
+ "{} ",
+ super::FmtLevel::new(meta.level(), writer.has_ansi_escapes())
+ )?;
+ }
+
+ if self.display_target {
+ let target_style = if writer.has_ansi_escapes() {
+ style.bold()
+ } else {
+ style
+ };
+ write!(
+ writer,
+ "{}{}{}:",
+ target_style.prefix(),
+ meta.target(),
+ target_style.infix(style)
+ )?;
+ }
+ let line_number = if self.display_line_number {
+ meta.line()
+ } else {
+ None
+ };
+
+ // If the file name is disabled, format the line number right after the
+ // target. Otherwise, if we also display the file, it'll go on a
+ // separate line.
+ if let (Some(line_number), false, true) = (
+ line_number,
+ self.display_filename,
+ self.format.display_location,
+ ) {
+ write!(
+ writer,
+ "{}{}{}:",
+ style.prefix(),
+ line_number,
+ style.infix(style)
+ )?;
+ }
+
+ writer.write_char(' ')?;
+
+ let mut v = PrettyVisitor::new(writer.by_ref(), true).with_style(style);
+ event.record(&mut v);
+ v.finish()?;
+ writer.write_char('\n')?;
+
+ let dimmed = if writer.has_ansi_escapes() {
+ Style::new().dimmed().italic()
+ } else {
+ Style::new()
+ };
+ let thread = self.display_thread_name || self.display_thread_id;
+
+ if let (Some(file), true, true) = (
+ meta.file(),
+ self.format.display_location,
+ self.display_filename,
+ ) {
+ write!(writer, " {} {}", dimmed.paint("at"), file,)?;
+
+ if let Some(line) = line_number {
+ write!(writer, ":{}", line)?;
+ }
+ writer.write_char(if thread { ' ' } else { '\n' })?;
+ } else if thread {
+ write!(writer, " ")?;
+ };
+
+ if thread {
+ write!(writer, "{} ", dimmed.paint("on"))?;
+ let thread = std::thread::current();
+ if self.display_thread_name {
+ if let Some(name) = thread.name() {
+ write!(writer, "{}", name)?;
+ if self.display_thread_id {
+ writer.write_char(' ')?;
+ }
+ }
+ }
+ if self.display_thread_id {
+ write!(writer, "{:?}", thread.id())?;
+ }
+ writer.write_char('\n')?;
+ }
+
+ let bold = writer.bold();
+ let span = event
+ .parent()
+ .and_then(|id| ctx.span(id))
+ .or_else(|| ctx.lookup_current());
+
+ let scope = span.into_iter().flat_map(|span| span.scope());
+
+ for span in scope {
+ let meta = span.metadata();
+ if self.display_target {
+ write!(
+ writer,
+ " {} {}::{}",
+ dimmed.paint("in"),
+ meta.target(),
+ bold.paint(meta.name()),
+ )?;
+ } else {
+ write!(
+ writer,
+ " {} {}",
+ dimmed.paint("in"),
+ bold.paint(meta.name()),
+ )?;
+ }
+
+ let ext = span.extensions();
+ let fields = &ext
+ .get::<FormattedFields<N>>()
+ .expect("Unable to find FormattedFields in extensions; this is a bug");
+ if !fields.is_empty() {
+ write!(writer, " {} {}", dimmed.paint("with"), fields)?;
+ }
+ writer.write_char('\n')?;
+ }
+
+ writer.write_char('\n')
+ }
+}
+
+impl<'writer> FormatFields<'writer> for Pretty {
+ fn format_fields<R: RecordFields>(&self, writer: Writer<'writer>, fields: R) -> fmt::Result {
+ let mut v = PrettyVisitor::new(writer, true);
+ fields.record(&mut v);
+ v.finish()
+ }
+
+ fn add_fields(
+ &self,
+ current: &'writer mut FormattedFields<Self>,
+ fields: &span::Record<'_>,
+ ) -> fmt::Result {
+ let empty = current.is_empty();
+ let writer = current.as_writer();
+ let mut v = PrettyVisitor::new(writer, empty);
+ fields.record(&mut v);
+ v.finish()
+ }
+}
+
+// === impl PrettyFields ===
+
+impl Default for PrettyFields {
+ fn default() -> Self {
+ Self::new()
+ }
+}
+
+impl PrettyFields {
+ /// Returns a new default [`PrettyFields`] implementation.
+ pub fn new() -> Self {
+ // By default, don't override the `Writer`'s ANSI colors
+ // configuration. We'll only do this if the user calls the
+ // deprecated `PrettyFields::with_ansi` method.
+ Self { ansi: None }
+ }
+
+ /// Enable ANSI encoding for formatted fields.
+ #[deprecated(
+ since = "0.3.3",
+ note = "Use `fmt::Subscriber::with_ansi` or `fmt::Layer::with_ansi` instead."
+ )]
+ pub fn with_ansi(self, ansi: bool) -> Self {
+ Self {
+ ansi: Some(ansi),
+ ..self
+ }
+ }
+}
+
+impl<'a> MakeVisitor<Writer<'a>> for PrettyFields {
+ type Visitor = PrettyVisitor<'a>;
+
+ #[inline]
+ fn make_visitor(&self, mut target: Writer<'a>) -> Self::Visitor {
+ if let Some(ansi) = self.ansi {
+ target = target.with_ansi(ansi);
+ }
+ PrettyVisitor::new(target, true)
+ }
+}
+
+// === impl PrettyVisitor ===
+
+impl<'a> PrettyVisitor<'a> {
+ /// Returns a new default visitor that formats to the provided `writer`.
+ ///
+ /// # Arguments
+ /// - `writer`: the writer to format to.
+ /// - `is_empty`: whether or not any fields have been previously written to
+ /// that writer.
+ pub fn new(writer: Writer<'a>, is_empty: bool) -> Self {
+ Self {
+ writer,
+ is_empty,
+ style: Style::default(),
+ result: Ok(()),
+ }
+ }
+
+ pub(crate) fn with_style(self, style: Style) -> Self {
+ Self { style, ..self }
+ }
+
+ fn write_padded(&mut self, value: &impl fmt::Debug) {
+ let padding = if self.is_empty {
+ self.is_empty = false;
+ ""
+ } else {
+ ", "
+ };
+ self.result = write!(self.writer, "{}{:?}", padding, value);
+ }
+
+ fn bold(&self) -> Style {
+ if self.writer.has_ansi_escapes() {
+ self.style.bold()
+ } else {
+ Style::new()
+ }
+ }
+}
+
+impl<'a> field::Visit for PrettyVisitor<'a> {
+ fn record_str(&mut self, field: &Field, value: &str) {
+ if self.result.is_err() {
+ return;
+ }
+
+ if field.name() == "message" {
+ self.record_debug(field, &format_args!("{}", value))
+ } else {
+ self.record_debug(field, &value)
+ }
+ }
+
+ fn record_error(&mut self, field: &Field, value: &(dyn std::error::Error + 'static)) {
+ if let Some(source) = value.source() {
+ let bold = self.bold();
+ self.record_debug(
+ field,
+ &format_args!(
+ "{}, {}{}.sources{}: {}",
+ value,
+ bold.prefix(),
+ field,
+ bold.infix(self.style),
+ ErrorSourceList(source),
+ ),
+ )
+ } else {
+ self.record_debug(field, &format_args!("{}", value))
+ }
+ }
+
+ fn record_debug(&mut self, field: &Field, value: &dyn fmt::Debug) {
+ if self.result.is_err() {
+ return;
+ }
+ let bold = self.bold();
+ match field.name() {
+ "message" => self.write_padded(&format_args!("{}{:?}", self.style.prefix(), value,)),
+ // Skip fields that are actually log metadata that have already been handled
+ #[cfg(feature = "tracing-log")]
+ name if name.starts_with("log.") => self.result = Ok(()),
+ name if name.starts_with("r#") => self.write_padded(&format_args!(
+ "{}{}{}: {:?}",
+ bold.prefix(),
+ &name[2..],
+ bold.infix(self.style),
+ value
+ )),
+ name => self.write_padded(&format_args!(
+ "{}{}{}: {:?}",
+ bold.prefix(),
+ name,
+ bold.infix(self.style),
+ value
+ )),
+ };
+ }
+}
+
+impl<'a> VisitOutput<fmt::Result> for PrettyVisitor<'a> {
+ fn finish(mut self) -> fmt::Result {
+ write!(&mut self.writer, "{}", self.style.suffix())?;
+ self.result
+ }
+}
+
+impl<'a> VisitFmt for PrettyVisitor<'a> {
+ fn writer(&mut self) -> &mut dyn fmt::Write {
+ &mut self.writer
+ }
+}
diff --git a/vendor/tracing-subscriber-0.3.3/src/fmt/mod.rs b/vendor/tracing-subscriber/src/fmt/mod.rs
index d5deb8f0c..025e17504 100644
--- a/vendor/tracing-subscriber-0.3.3/src/fmt/mod.rs
+++ b/vendor/tracing-subscriber/src/fmt/mod.rs
@@ -13,10 +13,12 @@
//!
//! ```toml
//! [dependencies]
-//! tracing-subscriber = "0.2"
+//! tracing-subscriber = "0.3"
//! ```
//!
-//! *Compiler support: requires rustc 1.39+*
+//! *Compiler support: [requires `rustc` 1.49+][msrv]*
+//!
+//! [msrv]: super#supported-rust-versions
//!
//! Add the following to your executable to initialize the default subscriber:
//! ```rust
@@ -68,132 +70,25 @@
//!
//! * [`format::Full`]: The default formatter. This emits human-readable,
//! single-line logs for each event that occurs, with the current span context
-//! displayed before the formatted representation of the event.
+//! displayed before the formatted representation of the event. See
+//! [here](format::Full#example-output) for sample output.
//!
-//! For example:
-//! <pre><font color="#4E9A06"><b> Finished</b></font> dev [unoptimized + debuginfo] target(s) in 1.59s
-//! <font color="#4E9A06"><b> Running</b></font> `target/debug/examples/fmt`
-//! <font color="#AAAAAA">Oct 24 12:55:47.814 </font><font color="#4E9A06"> INFO</font> fmt: preparing to shave yaks number_of_yaks=3
-//! <font color="#AAAAAA">Oct 24 12:55:47.814 </font><font color="#4E9A06"> INFO</font> <b>shaving_yaks{</b>yaks=3<b>}</b>: fmt::yak_shave: shaving yaks
-//! <font color="#AAAAAA">Oct 24 12:55:47.814 </font><font color="#75507B">TRACE</font> <b>shaving_yaks{</b>yaks=3<b>}</b>:<b>shave{</b>yak=1<b>}</b>: fmt::yak_shave: hello! I&apos;m gonna shave a yak excitement=&quot;yay!&quot;
-//! <font color="#AAAAAA">Oct 24 12:55:47.814 </font><font color="#75507B">TRACE</font> <b>shaving_yaks{</b>yaks=3<b>}</b>:<b>shave{</b>yak=1<b>}</b>: fmt::yak_shave: yak shaved successfully
-//! <font color="#AAAAAA">Oct 24 12:55:47.814 </font><font color="#3465A4">DEBUG</font> <b>shaving_yaks{</b>yaks=3<b>}</b>: yak_events: yak=1 shaved=true
-//! <font color="#AAAAAA">Oct 24 12:55:47.814 </font><font color="#75507B">TRACE</font> <b>shaving_yaks{</b>yaks=3<b>}</b>: fmt::yak_shave: yaks_shaved=1
-//! <font color="#AAAAAA">Oct 24 12:55:47.815 </font><font color="#75507B">TRACE</font> <b>shaving_yaks{</b>yaks=3<b>}</b>:<b>shave{</b>yak=2<b>}</b>: fmt::yak_shave: hello! I&apos;m gonna shave a yak excitement=&quot;yay!&quot;
-//! <font color="#AAAAAA">Oct 24 12:55:47.815 </font><font color="#75507B">TRACE</font> <b>shaving_yaks{</b>yaks=3<b>}</b>:<b>shave{</b>yak=2<b>}</b>: fmt::yak_shave: yak shaved successfully
-//! <font color="#AAAAAA">Oct 24 12:55:47.815 </font><font color="#3465A4">DEBUG</font> <b>shaving_yaks{</b>yaks=3<b>}</b>: yak_events: yak=2 shaved=true
-//! <font color="#AAAAAA">Oct 24 12:55:47.815 </font><font color="#75507B">TRACE</font> <b>shaving_yaks{</b>yaks=3<b>}</b>: fmt::yak_shave: yaks_shaved=2
-//! <font color="#AAAAAA">Oct 24 12:55:47.815 </font><font color="#75507B">TRACE</font> <b>shaving_yaks{</b>yaks=3<b>}</b>:<b>shave{</b>yak=3<b>}</b>: fmt::yak_shave: hello! I&apos;m gonna shave a yak excitement=&quot;yay!&quot;
-//! <font color="#AAAAAA">Oct 24 12:55:47.815 </font><font color="#C4A000"> WARN</font> <b>shaving_yaks{</b>yaks=3<b>}</b>:<b>shave{</b>yak=3<b>}</b>: fmt::yak_shave: could not locate yak
-//! <font color="#AAAAAA">Oct 24 12:55:47.815 </font><font color="#3465A4">DEBUG</font> <b>shaving_yaks{</b>yaks=3<b>}</b>: yak_events: yak=3 shaved=false
-//! <font color="#AAAAAA">Oct 24 12:55:47.815 </font><font color="#CC0000">ERROR</font> <b>shaving_yaks{</b>yaks=3<b>}</b>: fmt::yak_shave: failed to shave yak yak=3 error=missing yak
-//! <font color="#AAAAAA">Oct 24 12:55:47.815 </font><font color="#75507B">TRACE</font> <b>shaving_yaks{</b>yaks=3<b>}</b>: fmt::yak_shave: yaks_shaved=2
-//! <font color="#AAAAAA">Oct 24 12:55:47.815 </font><font color="#4E9A06"> INFO</font> fmt: yak shaving completed all_yaks_shaved=false
-//! </pre>
+//! * [`format::Compact`]: A variant of the default formatter, optimized for
+//! short line lengths. Fields from the current span context are appended to
+//! the fields of the formatted event. See
+//! [here](format::Compact#example-output) for sample output.
//!
//! * [`format::Pretty`]: Emits excessively pretty, multi-line logs, optimized
//! for human readability. This is primarily intended to be used in local
//! development and debugging, or for command-line applications, where
//! automated analysis and compact storage of logs is less of a priority than
-//! readability and visual appeal.
-//!
-//! For example:
-//! <pre><font color="#4E9A06"><b> Finished</b></font> dev [unoptimized + debuginfo] target(s) in 1.61s
-//! <font color="#4E9A06"><b> Running</b></font> `target/debug/examples/fmt-pretty`
-//! Oct 24 12:57:29.386 <font color="#4E9A06"><b>fmt_pretty</b></font><font color="#4E9A06">: preparing to shave yaks, </font><font color="#4E9A06"><b>number_of_yaks</b></font><font color="#4E9A06">: 3</font>
-//! <font color="#AAAAAA"><i>at</i></font> examples/examples/fmt-pretty.rs:16<font color="#AAAAAA"><i> on</i></font> main
-//!
-//! Oct 24 12:57:29.386 <font color="#4E9A06"><b>fmt_pretty::yak_shave</b></font><font color="#4E9A06">: shaving yaks</font>
-//! <font color="#AAAAAA"><i>at</i></font> examples/examples/fmt/yak_shave.rs:38<font color="#AAAAAA"><i> on</i></font> main
-//! <font color="#AAAAAA"><i>in</i></font> fmt_pretty::yak_shave::<b>shaving_yaks</b> <font color="#AAAAAA"><i>with</i></font> <b>yaks</b>: 3
-//!
-//! Oct 24 12:57:29.387 <font color="#75507B"><b>fmt_pretty::yak_shave</b></font><font color="#75507B">: hello! I&apos;m gonna shave a yak, </font><font color="#75507B"><b>excitement</b></font><font color="#75507B">: &quot;yay!&quot;</font>
-//! <font color="#AAAAAA"><i>at</i></font> examples/examples/fmt/yak_shave.rs:14<font color="#AAAAAA"><i> on</i></font> main
-//! <font color="#AAAAAA"><i>in</i></font> fmt_pretty::yak_shave::<b>shave</b> <font color="#AAAAAA"><i>with</i></font> <b>yak</b>: 1
-//! <font color="#AAAAAA"><i>in</i></font> fmt_pretty::yak_shave::<b>shaving_yaks</b> <font color="#AAAAAA"><i>with</i></font> <b>yaks</b>: 3
-//!
-//! Oct 24 12:57:29.387 <font color="#75507B"><b>fmt_pretty::yak_shave</b></font><font color="#75507B">: yak shaved successfully</font>
-//! <font color="#AAAAAA"><i>at</i></font> examples/examples/fmt/yak_shave.rs:22<font color="#AAAAAA"><i> on</i></font> main
-//! <font color="#AAAAAA"><i>in</i></font> fmt_pretty::yak_shave::<b>shave</b> <font color="#AAAAAA"><i>with</i></font> <b>yak</b>: 1
-//! <font color="#AAAAAA"><i>in</i></font> fmt_pretty::yak_shave::<b>shaving_yaks</b> <font color="#AAAAAA"><i>with</i></font> <b>yaks</b>: 3
-//!
-//! Oct 24 12:57:29.387 <font color="#3465A4"><b>yak_events</b></font><font color="#3465A4">: </font><font color="#3465A4"><b>yak</b></font><font color="#3465A4">: 1, </font><font color="#3465A4"><b>shaved</b></font><font color="#3465A4">: true</font>
-//! <font color="#AAAAAA"><i>at</i></font> examples/examples/fmt/yak_shave.rs:43<font color="#AAAAAA"><i> on</i></font> main
-//! <font color="#AAAAAA"><i>in</i></font> fmt_pretty::yak_shave::<b>shaving_yaks</b> <font color="#AAAAAA"><i>with</i></font> <b>yaks</b>: 3
-//!
-//! Oct 24 12:57:29.387 <font color="#75507B"><b>fmt_pretty::yak_shave</b></font><font color="#75507B">: </font><font color="#75507B"><b>yaks_shaved</b></font><font color="#75507B">: 1</font>
-//! <font color="#AAAAAA"><i>at</i></font> examples/examples/fmt/yak_shave.rs:52<font color="#AAAAAA"><i> on</i></font> main
-//! <font color="#AAAAAA"><i>in</i></font> fmt_pretty::yak_shave::<b>shaving_yaks</b> <font color="#AAAAAA"><i>with</i></font> <b>yaks</b>: 3
-//!
-//! Oct 24 12:57:29.387 <font color="#75507B"><b>fmt_pretty::yak_shave</b></font><font color="#75507B">: hello! I&apos;m gonna shave a yak, </font><font color="#75507B"><b>excitement</b></font><font color="#75507B">: &quot;yay!&quot;</font>
-//! <font color="#AAAAAA"><i>at</i></font> examples/examples/fmt/yak_shave.rs:14<font color="#AAAAAA"><i> on</i></font> main
-//! <font color="#AAAAAA"><i>in</i></font> fmt_pretty::yak_shave::<b>shave</b> <font color="#AAAAAA"><i>with</i></font> <b>yak</b>: 2
-//! <font color="#AAAAAA"><i>in</i></font> fmt_pretty::yak_shave::<b>shaving_yaks</b> <font color="#AAAAAA"><i>with</i></font> <b>yaks</b>: 3
-//!
-//! Oct 24 12:57:29.387 <font color="#75507B"><b>fmt_pretty::yak_shave</b></font><font color="#75507B">: yak shaved successfully</font>
-//! <font color="#AAAAAA"><i>at</i></font> examples/examples/fmt/yak_shave.rs:22<font color="#AAAAAA"><i> on</i></font> main
-//! <font color="#AAAAAA"><i>in</i></font> fmt_pretty::yak_shave::<b>shave</b> <font color="#AAAAAA"><i>with</i></font> <b>yak</b>: 2
-//! <font color="#AAAAAA"><i>in</i></font> fmt_pretty::yak_shave::<b>shaving_yaks</b> <font color="#AAAAAA"><i>with</i></font> <b>yaks</b>: 3
-//!
-//! Oct 24 12:57:29.387 <font color="#3465A4"><b>yak_events</b></font><font color="#3465A4">: </font><font color="#3465A4"><b>yak</b></font><font color="#3465A4">: 2, </font><font color="#3465A4"><b>shaved</b></font><font color="#3465A4">: true</font>
-//! <font color="#AAAAAA"><i>at</i></font> examples/examples/fmt/yak_shave.rs:43<font color="#AAAAAA"><i> on</i></font> main
-//! <font color="#AAAAAA"><i>in</i></font> fmt_pretty::yak_shave::<b>shaving_yaks</b> <font color="#AAAAAA"><i>with</i></font> <b>yaks</b>: 3
-//!
-//! Oct 24 12:57:29.387 <font color="#75507B"><b>fmt_pretty::yak_shave</b></font><font color="#75507B">: </font><font color="#75507B"><b>yaks_shaved</b></font><font color="#75507B">: 2</font>
-//! <font color="#AAAAAA"><i>at</i></font> examples/examples/fmt/yak_shave.rs:52<font color="#AAAAAA"><i> on</i></font> main
-//! <font color="#AAAAAA"><i>in</i></font> fmt_pretty::yak_shave::<b>shaving_yaks</b> <font color="#AAAAAA"><i>with</i></font> <b>yaks</b>: 3
-//!
-//! Oct 24 12:57:29.387 <font color="#75507B"><b>fmt_pretty::yak_shave</b></font><font color="#75507B">: hello! I&apos;m gonna shave a yak, </font><font color="#75507B"><b>excitement</b></font><font color="#75507B">: &quot;yay!&quot;</font>
-//! <font color="#AAAAAA"><i>at</i></font> examples/examples/fmt/yak_shave.rs:14<font color="#AAAAAA"><i> on</i></font> main
-//! <font color="#AAAAAA"><i>in</i></font> fmt_pretty::yak_shave::<b>shave</b> <font color="#AAAAAA"><i>with</i></font> <b>yak</b>: 3
-//! <font color="#AAAAAA"><i>in</i></font> fmt_pretty::yak_shave::<b>shaving_yaks</b> <font color="#AAAAAA"><i>with</i></font> <b>yaks</b>: 3
-//!
-//! Oct 24 12:57:29.387 <font color="#C4A000"><b>fmt_pretty::yak_shave</b></font><font color="#C4A000">: could not locate yak</font>
-//! <font color="#AAAAAA"><i>at</i></font> examples/examples/fmt/yak_shave.rs:16<font color="#AAAAAA"><i> on</i></font> main
-//! <font color="#AAAAAA"><i>in</i></font> fmt_pretty::yak_shave::<b>shave</b> <font color="#AAAAAA"><i>with</i></font> <b>yak</b>: 3
-//! <font color="#AAAAAA"><i>in</i></font> fmt_pretty::yak_shave::<b>shaving_yaks</b> <font color="#AAAAAA"><i>with</i></font> <b>yaks</b>: 3
-//!
-//! Oct 24 12:57:29.387 <font color="#3465A4"><b>yak_events</b></font><font color="#3465A4">: </font><font color="#3465A4"><b>yak</b></font><font color="#3465A4">: 3, </font><font color="#3465A4"><b>shaved</b></font><font color="#3465A4">: false</font>
-//! <font color="#AAAAAA"><i>at</i></font> examples/examples/fmt/yak_shave.rs:43<font color="#AAAAAA"><i> on</i></font> main
-//! <font color="#AAAAAA"><i>in</i></font> fmt_pretty::yak_shave::<b>shaving_yaks</b> <font color="#AAAAAA"><i>with</i></font> <b>yaks</b>: 3
-//!
-//! Oct 24 12:57:29.387 <font color="#CC0000"><b>fmt_pretty::yak_shave</b></font><font color="#CC0000">: failed to shave yak, </font><font color="#CC0000"><b>yak</b></font><font color="#CC0000">: 3, </font><font color="#CC0000"><b>error</b></font><font color="#CC0000">: missing yak</font>
-//! <font color="#AAAAAA"><i>at</i></font> examples/examples/fmt/yak_shave.rs:48<font color="#AAAAAA"><i> on</i></font> main
-//! <font color="#AAAAAA"><i>in</i></font> fmt_pretty::yak_shave::<b>shaving_yaks</b> <font color="#AAAAAA"><i>with</i></font> <b>yaks</b>: 3
-//!
-//! Oct 24 12:57:29.387 <font color="#75507B"><b>fmt_pretty::yak_shave</b></font><font color="#75507B">: </font><font color="#75507B"><b>yaks_shaved</b></font><font color="#75507B">: 2</font>
-//! <font color="#AAAAAA"><i>at</i></font> examples/examples/fmt/yak_shave.rs:52<font color="#AAAAAA"><i> on</i></font> main
-//! <font color="#AAAAAA"><i>in</i></font> fmt_pretty::yak_shave::<b>shaving_yaks</b> <font color="#AAAAAA"><i>with</i></font> <b>yaks</b>: 3
-//!
-//! Oct 24 12:57:29.387 <font color="#4E9A06"><b>fmt_pretty</b></font><font color="#4E9A06">: yak shaving completed, </font><font color="#4E9A06"><b>all_yaks_shaved</b></font><font color="#4E9A06">: false</font>
-//! <font color="#AAAAAA"><i>at</i></font> examples/examples/fmt-pretty.rs:19<font color="#AAAAAA"><i> on</i></font> main
-//! </pre>
+//! readability and visual appeal. See [here](format::Pretty#example-output)
+//! for sample output.
//!
//! * [`format::Json`]: Outputs newline-delimited JSON logs. This is intended
//! for production use with systems where structured logs are consumed as JSON
-//! by analysis and viewing tools. The JSON output, as seen below, is *not*
-//! optimized for human readability.
-//!
-//! For example:
-//! <pre><font color="#4E9A06"><b> Finished</b></font> dev [unoptimized + debuginfo] target(s) in 1.58s
-//! <font color="#4E9A06"><b> Running</b></font> `target/debug/examples/fmt-json`
-//! {&quot;timestamp&quot;:&quot;Oct 24 13:00:00.873&quot;,&quot;level&quot;:&quot;INFO&quot;,&quot;fields&quot;:{&quot;message&quot;:&quot;preparing to shave yaks&quot;,&quot;number_of_yaks&quot;:3},&quot;target&quot;:&quot;fmt_json&quot;}
-//! {&quot;timestamp&quot;:&quot;Oct 24 13:00:00.874&quot;,&quot;level&quot;:&quot;INFO&quot;,&quot;fields&quot;:{&quot;message&quot;:&quot;shaving yaks&quot;},&quot;target&quot;:&quot;fmt_json::yak_shave&quot;,&quot;spans&quot;:[{&quot;yaks&quot;:3,&quot;name&quot;:&quot;shaving_yaks&quot;}]}
-//! {&quot;timestamp&quot;:&quot;Oct 24 13:00:00.874&quot;,&quot;level&quot;:&quot;TRACE&quot;,&quot;fields&quot;:{&quot;message&quot;:&quot;hello! I&apos;m gonna shave a yak&quot;,&quot;excitement&quot;:&quot;yay!&quot;},&quot;target&quot;:&quot;fmt_json::yak_shave&quot;,&quot;spans&quot;:[{&quot;yaks&quot;:3,&quot;name&quot;:&quot;shaving_yaks&quot;},{&quot;yak&quot;:&quot;1&quot;,&quot;name&quot;:&quot;shave&quot;}]}
-//! {&quot;timestamp&quot;:&quot;Oct 24 13:00:00.874&quot;,&quot;level&quot;:&quot;TRACE&quot;,&quot;fields&quot;:{&quot;message&quot;:&quot;yak shaved successfully&quot;},&quot;target&quot;:&quot;fmt_json::yak_shave&quot;,&quot;spans&quot;:[{&quot;yaks&quot;:3,&quot;name&quot;:&quot;shaving_yaks&quot;},{&quot;yak&quot;:&quot;1&quot;,&quot;name&quot;:&quot;shave&quot;}]}
-//! {&quot;timestamp&quot;:&quot;Oct 24 13:00:00.874&quot;,&quot;level&quot;:&quot;DEBUG&quot;,&quot;fields&quot;:{&quot;yak&quot;:1,&quot;shaved&quot;:true},&quot;target&quot;:&quot;yak_events&quot;,&quot;spans&quot;:[{&quot;yaks&quot;:3,&quot;name&quot;:&quot;shaving_yaks&quot;}]}
-//! {&quot;timestamp&quot;:&quot;Oct 24 13:00:00.874&quot;,&quot;level&quot;:&quot;TRACE&quot;,&quot;fields&quot;:{&quot;yaks_shaved&quot;:1},&quot;target&quot;:&quot;fmt_json::yak_shave&quot;,&quot;spans&quot;:[{&quot;yaks&quot;:3,&quot;name&quot;:&quot;shaving_yaks&quot;}]}
-//! {&quot;timestamp&quot;:&quot;Oct 24 13:00:00.874&quot;,&quot;level&quot;:&quot;TRACE&quot;,&quot;fields&quot;:{&quot;message&quot;:&quot;hello! I&apos;m gonna shave a yak&quot;,&quot;excitement&quot;:&quot;yay!&quot;},&quot;target&quot;:&quot;fmt_json::yak_shave&quot;,&quot;spans&quot;:[{&quot;yaks&quot;:3,&quot;name&quot;:&quot;shaving_yaks&quot;},{&quot;yak&quot;:&quot;2&quot;,&quot;name&quot;:&quot;shave&quot;}]}
-//! {&quot;timestamp&quot;:&quot;Oct 24 13:00:00.874&quot;,&quot;level&quot;:&quot;TRACE&quot;,&quot;fields&quot;:{&quot;message&quot;:&quot;yak shaved successfully&quot;},&quot;target&quot;:&quot;fmt_json::yak_shave&quot;,&quot;spans&quot;:[{&quot;yaks&quot;:3,&quot;name&quot;:&quot;shaving_yaks&quot;},{&quot;yak&quot;:&quot;2&quot;,&quot;name&quot;:&quot;shave&quot;}]}
-//! {&quot;timestamp&quot;:&quot;Oct 24 13:00:00.874&quot;,&quot;level&quot;:&quot;DEBUG&quot;,&quot;fields&quot;:{&quot;yak&quot;:2,&quot;shaved&quot;:true},&quot;target&quot;:&quot;yak_events&quot;,&quot;spans&quot;:[{&quot;yaks&quot;:3,&quot;name&quot;:&quot;shaving_yaks&quot;}]}
-//! {&quot;timestamp&quot;:&quot;Oct 24 13:00:00.874&quot;,&quot;level&quot;:&quot;TRACE&quot;,&quot;fields&quot;:{&quot;yaks_shaved&quot;:2},&quot;target&quot;:&quot;fmt_json::yak_shave&quot;,&quot;spans&quot;:[{&quot;yaks&quot;:3,&quot;name&quot;:&quot;shaving_yaks&quot;}]}
-//! {&quot;timestamp&quot;:&quot;Oct 24 13:00:00.874&quot;,&quot;level&quot;:&quot;TRACE&quot;,&quot;fields&quot;:{&quot;message&quot;:&quot;hello! I&apos;m gonna shave a yak&quot;,&quot;excitement&quot;:&quot;yay!&quot;},&quot;target&quot;:&quot;fmt_json::yak_shave&quot;,&quot;spans&quot;:[{&quot;yaks&quot;:3,&quot;name&quot;:&quot;shaving_yaks&quot;},{&quot;yak&quot;:&quot;3&quot;,&quot;name&quot;:&quot;shave&quot;}]}
-//! {&quot;timestamp&quot;:&quot;Oct 24 13:00:00.875&quot;,&quot;level&quot;:&quot;WARN&quot;,&quot;fields&quot;:{&quot;message&quot;:&quot;could not locate yak&quot;},&quot;target&quot;:&quot;fmt_json::yak_shave&quot;,&quot;spans&quot;:[{&quot;yaks&quot;:3,&quot;name&quot;:&quot;shaving_yaks&quot;},{&quot;yak&quot;:&quot;3&quot;,&quot;name&quot;:&quot;shave&quot;}]}
-//! {&quot;timestamp&quot;:&quot;Oct 24 13:00:00.875&quot;,&quot;level&quot;:&quot;DEBUG&quot;,&quot;fields&quot;:{&quot;yak&quot;:3,&quot;shaved&quot;:false},&quot;target&quot;:&quot;yak_events&quot;,&quot;spans&quot;:[{&quot;yaks&quot;:3,&quot;name&quot;:&quot;shaving_yaks&quot;}]}
-//! {&quot;timestamp&quot;:&quot;Oct 24 13:00:00.875&quot;,&quot;level&quot;:&quot;ERROR&quot;,&quot;fields&quot;:{&quot;message&quot;:&quot;failed to shave yak&quot;,&quot;yak&quot;:3,&quot;error&quot;:&quot;missing yak&quot;},&quot;target&quot;:&quot;fmt_json::yak_shave&quot;,&quot;spans&quot;:[{&quot;yaks&quot;:3,&quot;name&quot;:&quot;shaving_yaks&quot;}]}
-//! {&quot;timestamp&quot;:&quot;Oct 24 13:00:00.875&quot;,&quot;level&quot;:&quot;TRACE&quot;,&quot;fields&quot;:{&quot;yaks_shaved&quot;:2},&quot;target&quot;:&quot;fmt_json::yak_shave&quot;,&quot;spans&quot;:[{&quot;yaks&quot;:3,&quot;name&quot;:&quot;shaving_yaks&quot;}]}
-//! {&quot;timestamp&quot;:&quot;Oct 24 13:00:00.875&quot;,&quot;level&quot;:&quot;INFO&quot;,&quot;fields&quot;:{&quot;message&quot;:&quot;yak shaving completed&quot;,&quot;all_yaks_shaved&quot;:false},&quot;target&quot;:&quot;fmt_json&quot;}
-//! </pre>
+//! by analysis and viewing tools. The JSON output is not optimized for human
+//! readability. See [here](format::Json#example-output) for sample output.
//!
//! ### Customizing Formatters
//!
@@ -221,7 +116,7 @@
//! .with_thread_names(true) // include the name of the current thread
//! .compact(); // use the `Compact` formatting style.
//!
-//! // Create a `fmt` collector that uses our custom event format, and set it
+//! // Create a `fmt` subscriber that uses our custom event format, and set it
//! // as the default.
//! tracing_subscriber::fmt()
//! .event_format(format)
@@ -268,7 +163,7 @@
//!
//! ### Composing Layers
//!
-//! Composing an [`EnvFilter`] `Layer` and a [format `Layer`](../fmt/struct.Layer.html):
+//! Composing an [`EnvFilter`] `Layer` and a [format `Layer`][super::fmt::Layer]:
//!
//! ```rust
//! use tracing_subscriber::{fmt, EnvFilter};
@@ -286,11 +181,10 @@
//! .init();
//! ```
//!
-//! [`EnvFilter`]: ../filter/struct.EnvFilter.html
+//! [`EnvFilter`]: super::filter::EnvFilter
//! [`env_logger`]: https://docs.rs/env_logger/
-//! [`filter`]: ../filter/index.html
-//! [`SubscriberBuilder`]: ./struct.SubscriberBuilder.html
-//! [`FmtSubscriber`]: ./struct.Subscriber.html
+//! [`filter`]: super::filter
+//! [`FmtSubscriber`]: Subscriber
//! [`Subscriber`]:
//! https://docs.rs/tracing/latest/tracing/trait.Subscriber.html
//! [`tracing`]: https://crates.io/crates/tracing
@@ -309,6 +203,7 @@ pub mod writer;
pub use fmt_layer::{FmtContext, FormattedFields, Layer};
use crate::layer::Layer as _;
+use crate::util::SubscriberInitExt;
use crate::{
filter::LevelFilter,
layer,
@@ -348,6 +243,7 @@ pub type Formatter<
/// Configures and constructs `Subscriber`s.
#[cfg_attr(docsrs, doc(cfg(all(feature = "fmt", feature = "std"))))]
#[derive(Debug)]
+#[must_use]
pub struct SubscriberBuilder<
N = format::DefaultFields,
E = format::Format<format::Full>,
@@ -417,7 +313,7 @@ pub struct SubscriberBuilder<
/// ```
///
/// [formatting subscriber]: Subscriber
-/// [`SubscriberBuilder::default()`]: SubscriberBuilder::default()
+/// [`SubscriberBuilder::default()`]: SubscriberBuilder::default
/// [`init`]: SubscriberBuilder::init()
/// [`try_init`]: SubscriberBuilder::try_init()
/// [`finish`]: SubscriberBuilder::finish()
@@ -429,10 +325,11 @@ pub fn fmt() -> SubscriberBuilder {
/// Returns a new [formatting layer] that can be [composed] with other layers to
/// construct a [`Subscriber`].
///
-/// This is a shorthand for the equivalent [`Layer::default`] function.
+/// This is a shorthand for the equivalent [`Layer::default()`] function.
///
/// [formatting layer]: Layer
/// [composed]: crate::layer
+/// [`Layer::default()`]: Layer::default
#[cfg_attr(docsrs, doc(cfg(all(feature = "fmt", feature = "std"))))]
pub fn layer<S>() -> Layer<S> {
Layer::default()
@@ -444,8 +341,8 @@ impl Subscriber {
///
/// This can be overridden with the [`SubscriberBuilder::with_max_level`] method.
///
- /// [verbosity level]: https://docs.rs/tracing-core/0.1.5/tracing_core/struct.Level.html
- /// [`SubscriberBuilder::with_max_level`]: struct.SubscriberBuilder.html#method.with_max_level
+ /// [verbosity level]: tracing_core::Level
+ /// [`SubscriberBuilder::with_max_level`]: SubscriberBuilder::with_max_level
pub const DEFAULT_MAX_LEVEL: LevelFilter = LevelFilter::INFO;
/// Returns a new `SubscriberBuilder` for configuring a format subscriber.
@@ -502,6 +399,11 @@ where
}
#[inline]
+ fn event_enabled(&self, event: &Event<'_>) -> bool {
+ self.inner.event_enabled(event)
+ }
+
+ #[inline]
fn event(&self, event: &Event<'_>) {
self.inner.event(event);
}
@@ -565,6 +467,7 @@ impl Default for SubscriberBuilder {
filter: Subscriber::DEFAULT_MAX_LEVEL,
inner: Default::default(),
}
+ .log_internal_errors(true)
}
}
@@ -701,7 +604,7 @@ where
/// `Layer`s added to this subscriber.
///
/// [lifecycle]: https://docs.rs/tracing/latest/tracing/span/index.html#the-span-lifecycle
- /// [time]: #method.without_time
+ /// [time]: SubscriberBuilder::without_time()
pub fn with_span_events(self, kind: format::FmtSpan) -> Self {
SubscriberBuilder {
inner: self.inner.with_span_events(kind),
@@ -719,6 +622,27 @@ where
}
}
+ /// Sets whether to write errors from [`FormatEvent`] to the writer.
+ /// Defaults to true.
+ ///
+ /// By default, `fmt::Layer` will write any `FormatEvent`-internal errors to
+ /// the writer. These errors are unlikely and will only occur if there is a
+ /// bug in the `FormatEvent` implementation or its dependencies.
+ ///
+ /// If writing to the writer fails, the error message is printed to stderr
+ /// as a fallback.
+ ///
+ /// [`FormatEvent`]: crate::fmt::FormatEvent
+ pub fn log_internal_errors(
+ self,
+ log_internal_errors: bool,
+ ) -> SubscriberBuilder<N, format::Format<L, T>, F, W> {
+ SubscriberBuilder {
+ inner: self.inner.log_internal_errors(log_internal_errors),
+ ..self
+ }
+ }
+
/// Sets whether or not an event's target is displayed.
pub fn with_target(
self,
@@ -730,6 +654,34 @@ where
}
}
+ /// Sets whether or not an event's [source code file path][file] is
+ /// displayed.
+ ///
+ /// [file]: tracing_core::Metadata::file
+ pub fn with_file(
+ self,
+ display_filename: bool,
+ ) -> SubscriberBuilder<N, format::Format<L, T>, F, W> {
+ SubscriberBuilder {
+ inner: self.inner.with_file(display_filename),
+ ..self
+ }
+ }
+
+ /// Sets whether or not an event's [source code line number][line] is
+ /// displayed.
+ ///
+ /// [line]: tracing_core::Metadata::line
+ pub fn with_line_number(
+ self,
+ display_line_number: bool,
+ ) -> SubscriberBuilder<N, format::Format<L, T>, F, W> {
+ SubscriberBuilder {
+ inner: self.inner.with_line_number(display_line_number),
+ ..self
+ }
+ }
+
/// Sets whether or not an event's level is displayed.
pub fn with_level(
self,
@@ -742,9 +694,9 @@ where
}
/// Sets whether or not the [name] of the current thread is displayed
- /// when formatting events
+ /// when formatting events.
///
- /// [name]: https://doc.rust-lang.org/stable/std/thread/index.html#naming-threads
+ /// [name]: std::thread#naming-threads
pub fn with_thread_names(
self,
display_thread_names: bool,
@@ -756,9 +708,9 @@ where
}
/// Sets whether or not the [thread ID] of the current thread is displayed
- /// when formatting events
+ /// when formatting events.
///
- /// [thread ID]: https://doc.rust-lang.org/stable/std/thread/struct.ThreadId.html
+ /// [thread ID]: std::thread::ThreadId
pub fn with_thread_ids(
self,
display_thread_ids: bool,
@@ -796,7 +748,7 @@ where
/// Sets the subscriber being built to use a JSON formatter.
///
- /// See [`format::Json`](../fmt/format/struct.Json.html)
+ /// See [`format::Json`][super::fmt::format::Json]
#[cfg(feature = "json")]
#[cfg_attr(docsrs, doc(cfg(feature = "json")))]
pub fn json(
@@ -817,7 +769,7 @@ where
impl<T, F, W> SubscriberBuilder<format::JsonFields, format::Format<format::Json, T>, F, W> {
/// Sets the json subscriber being built to flatten event metadata.
///
- /// See [`format::Json`](../fmt/format/struct.Json.html)
+ /// See [`format::Json`][super::fmt::format::Json]
pub fn flatten_event(
self,
flatten_event: bool,
@@ -831,7 +783,7 @@ impl<T, F, W> SubscriberBuilder<format::JsonFields, format::Format<format::Json,
/// Sets whether or not the JSON subscriber being built will include the current span
/// in formatted events.
///
- /// See [`format::Json`](../fmt/format/struct.Json.html)
+ /// See [`format::Json`][super::fmt::format::Json]
pub fn with_current_span(
self,
display_current_span: bool,
@@ -845,7 +797,7 @@ impl<T, F, W> SubscriberBuilder<format::JsonFields, format::Format<format::Json,
/// Sets whether or not the JSON subscriber being built will include a list (from
/// root to leaf) of all currently entered spans in formatted events.
///
- /// See [`format::Json`](../fmt/format/struct.Json.html)
+ /// See [`format::Json`][super::fmt::format::Json]
pub fn with_span_list(
self,
display_span_list: bool,
@@ -891,7 +843,7 @@ where
}
impl<N, E, F, W> SubscriberBuilder<N, E, F, W> {
- /// Sets the Visitor that the subscriber being built will use to record
+ /// Sets the field formatter that the subscriber being built will use to record
/// fields.
///
/// For example:
@@ -967,8 +919,8 @@ impl<N, E, F, W> SubscriberBuilder<N, E, F, W> {
/// .try_init()?;
/// # Ok(())}
/// ```
- /// [`EnvFilter`]: ../filter/struct.EnvFilter.html
- /// [`with_max_level`]: #method.with_max_level
+ /// [`EnvFilter`]: super::filter::EnvFilter
+ /// [`with_max_level`]: SubscriberBuilder::with_max_level()
#[cfg(feature = "env-filter")]
#[cfg_attr(docsrs, doc(cfg(feature = "env-filter")))]
pub fn with_env_filter(
@@ -989,7 +941,7 @@ impl<N, E, F, W> SubscriberBuilder<N, E, F, W> {
/// subscriber.
///
/// If the max level has already been set, or a [`EnvFilter`] was added by
- /// [`with_filter`], this replaces that configuration with the new
+ /// [`with_env_filter`], this replaces that configuration with the new
/// maximum level.
///
/// # Examples
@@ -1011,9 +963,9 @@ impl<N, E, F, W> SubscriberBuilder<N, E, F, W> {
/// .with_max_level(LevelFilter::OFF)
/// .finish();
/// ```
- /// [verbosity level]: https://docs.rs/tracing-core/0.1.5/tracing_core/struct.Level.html
- /// [`EnvFilter`]: ../filter/struct.EnvFilter.html
- /// [`with_filter`]: #method.with_filter
+ /// [verbosity level]: tracing_core::Level
+ /// [`EnvFilter`]: struct@crate::filter::EnvFilter
+ /// [`with_env_filter`]: fn@Self::with_env_filter
pub fn with_max_level(
self,
filter: impl Into<LevelFilter>,
@@ -1025,8 +977,26 @@ impl<N, E, F, W> SubscriberBuilder<N, E, F, W> {
}
}
- /// Sets the function that the subscriber being built should use to format
- /// events that occur.
+ /// Sets the [event formatter][`FormatEvent`] that the subscriber being built
+ /// will use to format events that occur.
+ ///
+ /// The event formatter may be any type implementing the [`FormatEvent`]
+ /// trait, which is implemented for all functions taking a [`FmtContext`], a
+ /// [`Writer`], and an [`Event`].
+ ///
+ /// # Examples
+ ///
+ /// Setting a type implementing [`FormatEvent`] as the formatter:
+ ///
+ /// ```rust
+ /// use tracing_subscriber::fmt::format;
+ ///
+ /// let subscriber = tracing_subscriber::fmt()
+ /// .event_format(format().compact())
+ /// .finish();
+ /// ```
+ ///
+ /// [`Writer`]: struct@self::format::Writer
pub fn event_format<E2>(self, fmt_event: E2) -> SubscriberBuilder<N, E2, F, W>
where
E2: FormatEvent<Registry, N> + 'static,
@@ -1053,8 +1023,6 @@ impl<N, E, F, W> SubscriberBuilder<N, E, F, W> {
/// .with_writer(io::stderr)
/// .init();
/// ```
- ///
- /// [`MakeWriter`]: trait.MakeWriter.html
pub fn with_writer<W2>(self, make_writer: W2) -> SubscriberBuilder<N, E, F, W2>
where
W2: for<'writer> MakeWriter<'writer> + 'static,
@@ -1088,13 +1056,89 @@ impl<N, E, F, W> SubscriberBuilder<N, E, F, W> {
///
/// [capturing]:
/// https://doc.rust-lang.org/book/ch11-02-running-tests.html#showing-function-output
- /// [`TestWriter`]: writer/struct.TestWriter.html
+ /// [`TestWriter`]: writer::TestWriter
pub fn with_test_writer(self) -> SubscriberBuilder<N, E, F, TestWriter> {
SubscriberBuilder {
filter: self.filter,
inner: self.inner.with_writer(TestWriter::default()),
}
}
+
+ /// Updates the event formatter by applying a function to the existing event formatter.
+ ///
+ /// This sets the event formatter that the subscriber being built will use to record fields.
+ ///
+ /// # Examples
+ ///
+ /// Updating an event formatter:
+ ///
+ /// ```rust
+ /// let subscriber = tracing_subscriber::fmt()
+ /// .map_event_format(|e| e.compact())
+ /// .finish();
+ /// ```
+ pub fn map_event_format<E2>(self, f: impl FnOnce(E) -> E2) -> SubscriberBuilder<N, E2, F, W>
+ where
+ E2: FormatEvent<Registry, N> + 'static,
+ N: for<'writer> FormatFields<'writer> + 'static,
+ W: for<'writer> MakeWriter<'writer> + 'static,
+ {
+ SubscriberBuilder {
+ filter: self.filter,
+ inner: self.inner.map_event_format(f),
+ }
+ }
+
+ /// Updates the field formatter by applying a function to the existing field formatter.
+ ///
+ /// This sets the field formatter that the subscriber being built will use to record fields.
+ ///
+ /// # Examples
+ ///
+ /// Updating a field formatter:
+ ///
+ /// ```rust
+ /// use tracing_subscriber::field::MakeExt;
+ /// let subscriber = tracing_subscriber::fmt()
+ /// .map_fmt_fields(|f| f.debug_alt())
+ /// .finish();
+ /// ```
+ pub fn map_fmt_fields<N2>(self, f: impl FnOnce(N) -> N2) -> SubscriberBuilder<N2, E, F, W>
+ where
+ N2: for<'writer> FormatFields<'writer> + 'static,
+ {
+ SubscriberBuilder {
+ filter: self.filter,
+ inner: self.inner.map_fmt_fields(f),
+ }
+ }
+
+ /// Updates the [`MakeWriter`] by applying a function to the existing [`MakeWriter`].
+ ///
+ /// This sets the [`MakeWriter`] that the subscriber being built will use to write events.
+ ///
+ /// # Examples
+ ///
+ /// Redirect output to stderr if level is <= WARN:
+ ///
+ /// ```rust
+ /// use tracing::Level;
+ /// use tracing_subscriber::fmt::{self, writer::MakeWriterExt};
+ ///
+ /// let stderr = std::io::stderr.with_max_level(Level::WARN);
+ /// let layer = tracing_subscriber::fmt()
+ /// .map_writer(move |w| stderr.or_else(w))
+ /// .finish();
+ /// ```
+ pub fn map_writer<W2>(self, f: impl FnOnce(W) -> W2) -> SubscriberBuilder<N, E, F, W2>
+ where
+ W2: for<'writer> MakeWriter<'writer> + 'static,
+ {
+ SubscriberBuilder {
+ filter: self.filter,
+ inner: self.inner.map_writer(f),
+ }
+ }
}
/// Install a global tracing subscriber that listens for events and
@@ -1121,35 +1165,69 @@ impl<N, E, F, W> SubscriberBuilder<N, E, F, W> {
///
/// [`LogTracer`]:
/// https://docs.rs/tracing-log/0.1.0/tracing_log/struct.LogTracer.html
-/// [`RUST_LOG` environment variable]:
-/// ../filter/struct.EnvFilter.html#associatedconstant.DEFAULT_ENV
+/// [`RUST_LOG` environment variable]: crate::filter::EnvFilter::DEFAULT_ENV
pub fn try_init() -> Result<(), Box<dyn Error + Send + Sync + 'static>> {
let builder = Subscriber::builder();
#[cfg(feature = "env-filter")]
let builder = builder.with_env_filter(crate::EnvFilter::from_default_env());
- builder.try_init()
+ // If `env-filter` is disabled, remove the default max level filter from the
+ // subscriber; it will be added to the `Targets` filter instead if no filter
+ // is set in `RUST_LOG`.
+ // Replacing the default `LevelFilter` with an `EnvFilter` would imply this,
+ // but we can't replace the builder's filter with a `Targets` filter yet.
+ #[cfg(not(feature = "env-filter"))]
+ let builder = builder.with_max_level(LevelFilter::TRACE);
+
+ let subscriber = builder.finish();
+ #[cfg(not(feature = "env-filter"))]
+ let subscriber = {
+ use crate::{filter::Targets, layer::SubscriberExt};
+ use std::{env, str::FromStr};
+ let targets = match env::var("RUST_LOG") {
+ Ok(var) => Targets::from_str(&var)
+ .map_err(|e| {
+ eprintln!("Ignoring `RUST_LOG={:?}`: {}", var, e);
+ })
+ .unwrap_or_default(),
+ Err(env::VarError::NotPresent) => {
+ Targets::new().with_default(Subscriber::DEFAULT_MAX_LEVEL)
+ }
+ Err(e) => {
+ eprintln!("Ignoring `RUST_LOG`: {}", e);
+ Targets::new().with_default(Subscriber::DEFAULT_MAX_LEVEL)
+ }
+ };
+ subscriber.with(targets)
+ };
+
+ subscriber.try_init().map_err(Into::into)
}
/// Install a global tracing subscriber that listens for events and
/// filters based on the value of the [`RUST_LOG` environment variable].
///
+/// The configuration of the subscriber initialized by this function
+/// depends on what [feature flags](crate#feature-flags) are enabled.
+///
/// If the `tracing-log` feature is enabled, this will also install
/// the LogTracer to convert `Log` records into `tracing` `Event`s.
///
-/// This is shorthand for
+/// If the `env-filter` feature is enabled, this is shorthand for
///
/// ```rust
-/// tracing_subscriber::fmt().init()
+/// # use tracing_subscriber::EnvFilter;
+/// tracing_subscriber::fmt()
+/// .with_env_filter(EnvFilter::from_default_env())
+/// .init();
/// ```
///
/// # Panics
/// Panics if the initialization was unsuccessful, likely because a
/// global subscriber was already installed by another call to `try_init`.
///
-/// [`RUST_LOG` environment variable]:
-/// ../filter/struct.EnvFilter.html#associatedconstant.DEFAULT_ENV
+/// [`RUST_LOG` environment variable]: crate::filter::EnvFilter::DEFAULT_ENV
pub fn init() {
try_init().expect("Unable to install global subscriber")
}
diff --git a/vendor/tracing-subscriber-0.3.3/src/fmt/time/datetime.rs b/vendor/tracing-subscriber/src/fmt/time/datetime.rs
index 531331687..531331687 100644
--- a/vendor/tracing-subscriber-0.3.3/src/fmt/time/datetime.rs
+++ b/vendor/tracing-subscriber/src/fmt/time/datetime.rs
diff --git a/vendor/tracing-subscriber-0.3.3/src/fmt/time/mod.rs b/vendor/tracing-subscriber/src/fmt/time/mod.rs
index 621df16e4..e5b7c83b0 100644
--- a/vendor/tracing-subscriber-0.3.3/src/fmt/time/mod.rs
+++ b/vendor/tracing-subscriber/src/fmt/time/mod.rs
@@ -12,9 +12,13 @@ mod time_crate;
pub use time_crate::UtcTime;
#[cfg(feature = "local-time")]
-#[cfg_attr(docsrs, doc(cfg(feature = "local-time")))]
+#[cfg_attr(docsrs, doc(cfg(unsound_local_offset, feature = "local-time")))]
pub use time_crate::LocalTime;
+#[cfg(feature = "time")]
+#[cfg_attr(docsrs, doc(cfg(feature = "time")))]
+pub use time_crate::OffsetTime;
+
/// A type that can measure and format the current time.
///
/// This trait is used by `Format` to include a timestamp with each `Event` when it is logged.
@@ -26,7 +30,7 @@ pub use time_crate::LocalTime;
///
/// The full list of provided implementations can be found in [`time`].
///
-/// [`time`]: ./index.html
+/// [`time`]: self
pub trait FormatTime {
/// Measure and write out the current time.
///
diff --git a/vendor/tracing-subscriber/src/fmt/time/time_crate.rs b/vendor/tracing-subscriber/src/fmt/time/time_crate.rs
new file mode 100644
index 000000000..60d57fd0b
--- /dev/null
+++ b/vendor/tracing-subscriber/src/fmt/time/time_crate.rs
@@ -0,0 +1,470 @@
+use crate::fmt::{format::Writer, time::FormatTime, writer::WriteAdaptor};
+use std::fmt;
+use time::{format_description::well_known, formatting::Formattable, OffsetDateTime, UtcOffset};
+
+/// Formats the current [local time] using a [formatter] from the [`time` crate].
+///
+/// To format the current [UTC time] instead, use the [`UtcTime`] type.
+///
+/// <div class="example-wrap" style="display:inline-block">
+/// <pre class="compile_fail" style="white-space:normal;font:inherit;">
+/// <strong>Warning</strong>: The <a href = "https://docs.rs/time/0.3/time/"><code>time</code>
+/// crate</a> must be compiled with <code>--cfg unsound_local_offset</code> in order to use
+/// local timestamps. When this cfg is not enabled, local timestamps cannot be recorded, and
+/// events will be logged without timestamps.
+///
+/// Alternatively, [`OffsetTime`] can log with a local offset if it is initialized early.
+///
+/// See the <a href="https://docs.rs/time/0.3.4/time/#feature-flags"><code>time</code>
+/// documentation</a> for more details.
+/// </pre></div>
+///
+/// [local time]: time::OffsetDateTime::now_local
+/// [UTC time]: time::OffsetDateTime::now_utc
+/// [formatter]: time::formatting::Formattable
+/// [`time` crate]: time
+#[derive(Clone, Debug)]
+#[cfg_attr(
+ docsrs,
+ doc(cfg(all(unsound_local_offset, feature = "time", feature = "local-time")))
+)]
+#[cfg(feature = "local-time")]
+pub struct LocalTime<F> {
+ format: F,
+}
+
+/// Formats the current [UTC time] using a [formatter] from the [`time` crate].
+///
+/// To format the current [local time] instead, use the [`LocalTime`] type.
+///
+/// [local time]: time::OffsetDateTime::now_local
+/// [UTC time]: time::OffsetDateTime::now_utc
+/// [formatter]: time::formatting::Formattable
+/// [`time` crate]: time
+#[cfg_attr(docsrs, doc(cfg(feature = "time")))]
+#[derive(Clone, Debug)]
+pub struct UtcTime<F> {
+ format: F,
+}
+
+/// Formats the current time using a fixed offset and a [formatter] from the [`time` crate].
+///
+/// This is typically used as an alternative to [`LocalTime`]. `LocalTime` determines the offset
+/// every time it formats a message, which may be unsound or fail. With `OffsetTime`, the offset is
+/// determined once. This makes it possible to do so while the program is still single-threaded and
+/// handle any errors. However, this also means the offset cannot change while the program is
+/// running (the offset will not change across DST changes).
+///
+/// [formatter]: time::formatting::Formattable
+/// [`time` crate]: time
+#[derive(Clone, Debug)]
+#[cfg_attr(docsrs, doc(cfg(feature = "time")))]
+pub struct OffsetTime<F> {
+ offset: time::UtcOffset,
+ format: F,
+}
+
+// === impl LocalTime ===
+
+#[cfg(feature = "local-time")]
+impl LocalTime<well_known::Rfc3339> {
+ /// Returns a formatter that formats the current [local time] in the
+ /// [RFC 3339] format (a subset of the [ISO 8601] timestamp format).
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use tracing_subscriber::fmt::{self, time};
+ ///
+ /// let collector = tracing_subscriber::fmt()
+ /// .with_timer(time::LocalTime::rfc_3339());
+ /// # drop(collector);
+ /// ```
+ ///
+ /// [local time]: time::OffsetDateTime::now_local
+ /// [RFC 3339]: https://datatracker.ietf.org/doc/html/rfc3339
+ /// [ISO 8601]: https://en.wikipedia.org/wiki/ISO_8601
+ pub fn rfc_3339() -> Self {
+ Self::new(well_known::Rfc3339)
+ }
+}
+
+#[cfg(feature = "local-time")]
+impl<F: Formattable> LocalTime<F> {
+ /// Returns a formatter that formats the current [local time] using the
+ /// [`time` crate] with the provided provided format. The format may be any
+ /// type that implements the [`Formattable`] trait.
+ ///
+ ///
+ /// <div class="example-wrap" style="display:inline-block">
+ /// <pre class="compile_fail" style="white-space:normal;font:inherit;">
+ /// <strong>Warning</strong>: The <a href = "https://docs.rs/time/0.3/time/">
+ /// <code>time</code> crate</a> must be compiled with <code>--cfg
+ /// unsound_local_offset</code> in order to use local timestamps. When this
+ /// cfg is not enabled, local timestamps cannot be recorded, and
+ /// events will be logged without timestamps.
+ ///
+ /// See the <a href="https://docs.rs/time/0.3.4/time/#feature-flags">
+ /// <code>time</code> documentation</a> for more details.
+ /// </pre></div>
+ ///
+ /// Typically, the format will be a format description string, or one of the
+ /// `time` crate's [well-known formats].
+ ///
+ /// If the format description is statically known, then the
+ /// [`format_description!`] macro should be used. This is identical to the
+ /// [`time::format_description::parse`] method, but runs at compile-time,
+ /// throwing an error if the format description is invalid. If the desired format
+ /// is not known statically (e.g., a user is providing a format string), then the
+ /// [`time::format_description::parse`] method should be used. Note that this
+ /// method is fallible.
+ ///
+ /// See the [`time` book] for details on the format description syntax.
+ ///
+ /// # Examples
+ ///
+ /// Using the [`format_description!`] macro:
+ ///
+ /// ```
+ /// use tracing_subscriber::fmt::{self, time::LocalTime};
+ /// use time::macros::format_description;
+ ///
+ /// let timer = LocalTime::new(format_description!("[hour]:[minute]:[second]"));
+ /// let collector = tracing_subscriber::fmt()
+ /// .with_timer(timer);
+ /// # drop(collector);
+ /// ```
+ ///
+ /// Using [`time::format_description::parse`]:
+ ///
+ /// ```
+ /// use tracing_subscriber::fmt::{self, time::LocalTime};
+ ///
+ /// let time_format = time::format_description::parse("[hour]:[minute]:[second]")
+ /// .expect("format string should be valid!");
+ /// let timer = LocalTime::new(time_format);
+ /// let collector = tracing_subscriber::fmt()
+ /// .with_timer(timer);
+ /// # drop(collector);
+ /// ```
+ ///
+ /// Using the [`format_description!`] macro requires enabling the `time`
+ /// crate's "macros" feature flag.
+ ///
+ /// Using a [well-known format][well-known formats] (this is equivalent to
+ /// [`LocalTime::rfc_3339`]):
+ ///
+ /// ```
+ /// use tracing_subscriber::fmt::{self, time::LocalTime};
+ ///
+ /// let timer = LocalTime::new(time::format_description::well_known::Rfc3339);
+ /// let collector = tracing_subscriber::fmt()
+ /// .with_timer(timer);
+ /// # drop(collector);
+ /// ```
+ ///
+ /// [local time]: time::OffsetDateTime::now_local()
+ /// [`time` crate]: time
+ /// [`Formattable`]: time::formatting::Formattable
+ /// [well-known formats]: time::format_description::well_known
+ /// [`format_description!`]: time::macros::format_description!
+ /// [`time::format_description::parse`]: time::format_description::parse()
+ /// [`time` book]: https://time-rs.github.io/book/api/format-description.html
+ pub fn new(format: F) -> Self {
+ Self { format }
+ }
+}
+
+#[cfg(feature = "local-time")]
+impl<F> FormatTime for LocalTime<F>
+where
+ F: Formattable,
+{
+ fn format_time(&self, w: &mut Writer<'_>) -> fmt::Result {
+ let now = OffsetDateTime::now_local().map_err(|_| fmt::Error)?;
+ format_datetime(now, w, &self.format)
+ }
+}
+
+#[cfg(feature = "local-time")]
+impl<F> Default for LocalTime<F>
+where
+ F: Formattable + Default,
+{
+ fn default() -> Self {
+ Self::new(F::default())
+ }
+}
+
+// === impl UtcTime ===
+
+impl UtcTime<well_known::Rfc3339> {
+ /// Returns a formatter that formats the current [UTC time] in the
+ /// [RFC 3339] format, which is a subset of the [ISO 8601] timestamp format.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use tracing_subscriber::fmt::{self, time};
+ ///
+ /// let collector = tracing_subscriber::fmt()
+ /// .with_timer(time::UtcTime::rfc_3339());
+ /// # drop(collector);
+ /// ```
+ ///
+ /// [local time]: time::OffsetDateTime::now_utc
+ /// [RFC 3339]: https://datatracker.ietf.org/doc/html/rfc3339
+ /// [ISO 8601]: https://en.wikipedia.org/wiki/ISO_8601
+ pub fn rfc_3339() -> Self {
+ Self::new(well_known::Rfc3339)
+ }
+}
+
+impl<F: Formattable> UtcTime<F> {
+ /// Returns a formatter that formats the current [UTC time] using the
+ /// [`time` crate], with the provided provided format. The format may be any
+ /// type that implements the [`Formattable`] trait.
+ ///
+ /// Typically, the format will be a format description string, or one of the
+ /// `time` crate's [well-known formats].
+ ///
+ /// If the format description is statically known, then the
+ /// [`format_description!`] macro should be used. This is identical to the
+ /// [`time::format_description::parse`] method, but runs at compile-time,
+ /// failing an error if the format description is invalid. If the desired format
+ /// is not known statically (e.g., a user is providing a format string), then the
+ /// [`time::format_description::parse`] method should be used. Note that this
+ /// method is fallible.
+ ///
+ /// See the [`time` book] for details on the format description syntax.
+ ///
+ /// # Examples
+ ///
+ /// Using the [`format_description!`] macro:
+ ///
+ /// ```
+ /// use tracing_subscriber::fmt::{self, time::UtcTime};
+ /// use time::macros::format_description;
+ ///
+ /// let timer = UtcTime::new(format_description!("[hour]:[minute]:[second]"));
+ /// let collector = tracing_subscriber::fmt()
+ /// .with_timer(timer);
+ /// # drop(collector);
+ /// ```
+ ///
+ /// Using the [`format_description!`] macro requires enabling the `time`
+ /// crate's "macros" feature flag.
+ ///
+ /// Using [`time::format_description::parse`]:
+ ///
+ /// ```
+ /// use tracing_subscriber::fmt::{self, time::UtcTime};
+ ///
+ /// let time_format = time::format_description::parse("[hour]:[minute]:[second]")
+ /// .expect("format string should be valid!");
+ /// let timer = UtcTime::new(time_format);
+ /// let collector = tracing_subscriber::fmt()
+ /// .with_timer(timer);
+ /// # drop(collector);
+ /// ```
+ ///
+ /// Using a [well-known format][well-known formats] (this is equivalent to
+ /// [`UtcTime::rfc_3339`]):
+ ///
+ /// ```
+ /// use tracing_subscriber::fmt::{self, time::UtcTime};
+ ///
+ /// let timer = UtcTime::new(time::format_description::well_known::Rfc3339);
+ /// let collector = tracing_subscriber::fmt()
+ /// .with_timer(timer);
+ /// # drop(collector);
+ /// ```
+ ///
+ /// [UTC time]: time::OffsetDateTime::now_utc()
+ /// [`time` crate]: time
+ /// [`Formattable`]: time::formatting::Formattable
+ /// [well-known formats]: time::format_description::well_known
+ /// [`format_description!`]: time::macros::format_description!
+ /// [`time::format_description::parse`]: time::format_description::parse
+ /// [`time` book]: https://time-rs.github.io/book/api/format-description.html
+ pub fn new(format: F) -> Self {
+ Self { format }
+ }
+}
+
+impl<F> FormatTime for UtcTime<F>
+where
+ F: Formattable,
+{
+ fn format_time(&self, w: &mut Writer<'_>) -> fmt::Result {
+ format_datetime(OffsetDateTime::now_utc(), w, &self.format)
+ }
+}
+
+impl<F> Default for UtcTime<F>
+where
+ F: Formattable + Default,
+{
+ fn default() -> Self {
+ Self::new(F::default())
+ }
+}
+
+// === impl OffsetTime ===
+
+#[cfg(feature = "local-time")]
+impl OffsetTime<well_known::Rfc3339> {
+ /// Returns a formatter that formats the current time using the [local time offset] in the [RFC
+ /// 3339] format (a subset of the [ISO 8601] timestamp format).
+ ///
+ /// Returns an error if the local time offset cannot be determined. This typically occurs in
+ /// multithreaded programs. To avoid this problem, initialize `OffsetTime` before forking
+ /// threads. When using Tokio, this means initializing `OffsetTime` before the Tokio runtime.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use tracing_subscriber::fmt::{self, time};
+ ///
+ /// let collector = tracing_subscriber::fmt()
+ /// .with_timer(time::OffsetTime::local_rfc_3339().expect("could not get local offset!"));
+ /// # drop(collector);
+ /// ```
+ ///
+ /// Using `OffsetTime` with Tokio:
+ ///
+ /// ```
+ /// use tracing_subscriber::fmt::time::OffsetTime;
+ ///
+ /// #[tokio::main]
+ /// async fn run() {
+ /// tracing::info!("runtime initialized");
+ ///
+ /// // At this point the Tokio runtime is initialized, and we can use both Tokio and Tracing
+ /// // normally.
+ /// }
+ ///
+ /// fn main() {
+ /// // Because we need to get the local offset before Tokio spawns any threads, our `main`
+ /// // function cannot use `tokio::main`.
+ /// tracing_subscriber::fmt()
+ /// .with_timer(OffsetTime::local_rfc_3339().expect("could not get local time offset"))
+ /// .init();
+ ///
+ /// // Even though `run` is written as an `async fn`, because we used `tokio::main` on it
+ /// // we can call it as a synchronous function.
+ /// run();
+ /// }
+ /// ```
+ ///
+ /// [local time offset]: time::UtcOffset::current_local_offset
+ /// [RFC 3339]: https://datatracker.ietf.org/doc/html/rfc3339
+ /// [ISO 8601]: https://en.wikipedia.org/wiki/ISO_8601
+ pub fn local_rfc_3339() -> Result<Self, time::error::IndeterminateOffset> {
+ Ok(Self::new(
+ UtcOffset::current_local_offset()?,
+ well_known::Rfc3339,
+ ))
+ }
+}
+
+impl<F: time::formatting::Formattable> OffsetTime<F> {
+ /// Returns a formatter that formats the current time using the [`time` crate] with the provided
+ /// provided format and [timezone offset]. The format may be any type that implements the
+ /// [`Formattable`] trait.
+ ///
+ ///
+ /// Typically, the offset will be the [local offset], and format will be a format description
+ /// string, or one of the `time` crate's [well-known formats].
+ ///
+ /// If the format description is statically known, then the
+ /// [`format_description!`] macro should be used. This is identical to the
+ /// [`time::format_description::parse`] method, but runs at compile-time,
+ /// throwing an error if the format description is invalid. If the desired format
+ /// is not known statically (e.g., a user is providing a format string), then the
+ /// [`time::format_description::parse`] method should be used. Note that this
+ /// method is fallible.
+ ///
+ /// See the [`time` book] for details on the format description syntax.
+ ///
+ /// # Examples
+ ///
+ /// Using the [`format_description!`] macro:
+ ///
+ /// ```
+ /// use tracing_subscriber::fmt::{self, time::OffsetTime};
+ /// use time::macros::format_description;
+ /// use time::UtcOffset;
+ ///
+ /// let offset = UtcOffset::current_local_offset().expect("should get local offset!");
+ /// let timer = OffsetTime::new(offset, format_description!("[hour]:[minute]:[second]"));
+ /// let collector = tracing_subscriber::fmt()
+ /// .with_timer(timer);
+ /// # drop(collector);
+ /// ```
+ ///
+ /// Using [`time::format_description::parse`]:
+ ///
+ /// ```
+ /// use tracing_subscriber::fmt::{self, time::OffsetTime};
+ /// use time::UtcOffset;
+ ///
+ /// let offset = UtcOffset::current_local_offset().expect("should get local offset!");
+ /// let time_format = time::format_description::parse("[hour]:[minute]:[second]")
+ /// .expect("format string should be valid!");
+ /// let timer = OffsetTime::new(offset, time_format);
+ /// let collector = tracing_subscriber::fmt()
+ /// .with_timer(timer);
+ /// # drop(collector);
+ /// ```
+ ///
+ /// Using the [`format_description!`] macro requires enabling the `time`
+ /// crate's "macros" feature flag.
+ ///
+ /// Using a [well-known format][well-known formats] (this is equivalent to
+ /// [`OffsetTime::local_rfc_3339`]):
+ ///
+ /// ```
+ /// use tracing_subscriber::fmt::{self, time::OffsetTime};
+ /// use time::UtcOffset;
+ ///
+ /// let offset = UtcOffset::current_local_offset().expect("should get local offset!");
+ /// let timer = OffsetTime::new(offset, time::format_description::well_known::Rfc3339);
+ /// let collector = tracing_subscriber::fmt()
+ /// .with_timer(timer);
+ /// # drop(collector);
+ /// ```
+ ///
+ /// [`time` crate]: time
+ /// [timezone offset]: time::UtcOffset
+ /// [`Formattable`]: time::formatting::Formattable
+ /// [local offset]: time::UtcOffset::current_local_offset()
+ /// [well-known formats]: time::format_description::well_known
+ /// [`format_description!`]: time::macros::format_description
+ /// [`time::format_description::parse`]: time::format_description::parse
+ /// [`time` book]: https://time-rs.github.io/book/api/format-description.html
+ pub fn new(offset: time::UtcOffset, format: F) -> Self {
+ Self { offset, format }
+ }
+}
+
+impl<F> FormatTime for OffsetTime<F>
+where
+ F: time::formatting::Formattable,
+{
+ fn format_time(&self, w: &mut Writer<'_>) -> fmt::Result {
+ let now = OffsetDateTime::now_utc().to_offset(self.offset);
+ format_datetime(now, w, &self.format)
+ }
+}
+
+fn format_datetime(
+ now: OffsetDateTime,
+ into: &mut Writer<'_>,
+ fmt: &impl Formattable,
+) -> fmt::Result {
+ let mut into = WriteAdaptor::new(into);
+ now.format_into(&mut into, fmt)
+ .map_err(|_| fmt::Error)
+ .map(|_| ())
+}
diff --git a/vendor/tracing-subscriber-0.3.3/src/fmt/writer.rs b/vendor/tracing-subscriber/src/fmt/writer.rs
index 0974891f7..3fe945566 100644
--- a/vendor/tracing-subscriber-0.3.3/src/fmt/writer.rs
+++ b/vendor/tracing-subscriber/src/fmt/writer.rs
@@ -1,6 +1,6 @@
//! Abstractions for creating [`io::Write`] instances.
//!
-//! [`io::Write`]: https://doc.rust-lang.org/std/io/trait.Write.html
+//! [`io::Write`]: std::io::Write
use std::{
fmt,
io::{self, Write},
@@ -96,8 +96,8 @@ use tracing_core::Metadata;
pub trait MakeWriter<'a> {
/// The concrete [`io::Write`] implementation returned by [`make_writer`].
///
- /// [`io::Write`]: https://doc.rust-lang.org/std/io/trait.Write.html
- /// [`make_writer`]: #tymethod.make_writer
+ /// [`io::Write`]: std::io::Write
+ /// [`make_writer`]: MakeWriter::make_writer
type Writer: io::Write;
/// Returns an instance of [`Writer`].
@@ -109,7 +109,7 @@ pub trait MakeWriter<'a> {
/// creating a [`io::Write`] instance is expensive, be sure to cache it when implementing
/// [`MakeWriter`] to improve performance.
///
- /// [`Writer`]: #associatedtype.Writer
+ /// [`Writer`]: MakeWriter::Writer
/// [`fmt::Layer`]: crate::fmt::Layer
/// [`fmt::Subscriber`]: crate::fmt::Subscriber
/// [`io::Write`]: std::io::Write
@@ -501,13 +501,13 @@ pub trait MakeWriterExt<'a>: MakeWriter<'a> {
/// Writing to [`io::stdout`] and [`io::stderr`] produces the same results as using
/// [`libtest`'s `--nocapture` option][nocapture] which may make the results look unreadable.
///
-/// [`fmt::Subscriber`]: ../struct.Subscriber.html
-/// [`fmt::Layer`]: ../struct.Layer.html
+/// [`fmt::Subscriber`]: super::Subscriber
+/// [`fmt::Layer`]: super::Layer
/// [capturing]: https://doc.rust-lang.org/book/ch11-02-running-tests.html#showing-function-output
/// [nocapture]: https://doc.rust-lang.org/cargo/commands/cargo-test.html
-/// [`io::stdout`]: https://doc.rust-lang.org/std/io/fn.stdout.html
-/// [`io::stderr`]: https://doc.rust-lang.org/std/io/fn.stderr.html
-/// [`print!`]: https://doc.rust-lang.org/std/macro.print.html
+/// [`io::stdout`]: std::io::stdout
+/// [`io::stderr`]: std::io::stderr
+/// [`print!`]: std::print!
#[derive(Default, Debug)]
pub struct TestWriter {
_p: (),
@@ -646,10 +646,9 @@ pub struct Tee<A, B> {
/// requires the `Writer` type to implement [`io::Write`], it's necessary to add
/// a newtype that forwards the trait implementation.
///
-/// [`io::Write`]: https://doc.rust-lang.org/std/io/trait.Write.html
-/// [`MutexGuard`]: https://doc.rust-lang.org/std/sync/struct.MutexGuard.html
-/// [`Mutex`]: https://doc.rust-lang.org/std/sync/struct.Mutex.html
-/// [`MakeWriter`]: trait.MakeWriter.html
+/// [`io::Write`]: std::io::Write
+/// [`MutexGuard`]: std::sync::MutexGuard
+/// [`Mutex`]: std::sync::Mutex
#[derive(Debug)]
pub struct MutexGuardWriter<'a, W>(MutexGuard<'a, W>);
@@ -689,7 +688,7 @@ where
{
type Writer = &'a W;
fn make_writer(&'a self) -> Self::Writer {
- &*self
+ self
}
}
@@ -734,7 +733,6 @@ impl<'a> MakeWriter<'a> for TestWriter {
impl BoxMakeWriter {
/// Constructs a `BoxMakeWriter` wrapping a type implementing [`MakeWriter`].
///
- /// [`MakeWriter`]: trait.MakeWriter.html
pub fn new<M>(make_writer: M) -> Self
where
M: for<'a> MakeWriter<'a> + Send + Sync + 'static,
@@ -1025,6 +1023,8 @@ impl<A, B> Tee<A, B> {
/// outputs.
///
/// See the documentation for [`MakeWriterExt::and`] for details.
+ ///
+ /// [writers]: std::io::Write
pub fn new(a: A, b: B) -> Self {
Self { a, b }
}
diff --git a/vendor/tracing-subscriber-0.3.3/src/layer/context.rs b/vendor/tracing-subscriber/src/layer/context.rs
index e11959526..46254994f 100644
--- a/vendor/tracing-subscriber-0.3.3/src/layer/context.rs
+++ b/vendor/tracing-subscriber/src/layer/context.rs
@@ -25,10 +25,10 @@ use crate::{filter::FilterId, registry::Registry};
/// }
/// ```
///
-/// [`Layer`]: ../layer/trait.Layer.html
-/// [`Subscriber`]: https://docs.rs/tracing-core/latest/tracing_core/trait.Subscriber.html
-/// [stored data]: ../registry/struct.SpanRef.html
-/// [`LookupSpan`]: "../registry/trait.LookupSpan.html
+/// [`Layer`]: super::Layer
+/// [`Subscriber`]: tracing_core::Subscriber
+/// [stored data]: crate::registry::SpanRef
+/// [`LookupSpan`]: crate::registry::LookupSpan
#[derive(Debug)]
pub struct Context<'a, S> {
subscriber: Option<&'a S>,
@@ -99,9 +99,9 @@ where
/// check whether the event would be enabled. This allows `Layer`s to
/// elide constructing the event if it would not be recorded.
///
- /// [register]: https://docs.rs/tracing-core/latest/tracing_core/subscriber/trait.Subscriber.html#method.register_callsite
- /// [`enabled`]: https://docs.rs/tracing-core/latest/tracing_core/subscriber/trait.Subscriber.html#method.enabled
- /// [`Context::enabled`]: #method.enabled
+ /// [register]: tracing_core::subscriber::Subscriber::register_callsite()
+ /// [`enabled`]: tracing_core::subscriber::Subscriber::enabled()
+ /// [`Context::enabled`]: Context::enabled()
#[inline]
pub fn event(&self, event: &Event<'_>) {
if let Some(subscriber) = self.subscriber {
@@ -206,7 +206,7 @@ where
/// declaration</a> for details.
/// </pre>
///
- /// [stored data]: ../registry/struct.SpanRef.html
+ /// [stored data]: crate::registry::SpanRef
#[inline]
pub fn span(&self, id: &span::Id) -> Option<registry::SpanRef<'_, S>>
where
@@ -251,7 +251,7 @@ where
/// declaration</a> for details.
/// </pre>
///
- /// [stored data]: ../registry/struct.SpanRef.html
+ /// [stored data]: crate::registry::SpanRef
#[inline]
pub fn lookup_current(&self) -> Option<registry::SpanRef<'_, S>>
where
@@ -333,7 +333,7 @@ where
/// declaration</a> for details.
/// </pre>
///
- /// [stored data]: ../registry/struct.SpanRef.html
+ /// [stored data]: crate::registry::SpanRef
pub fn span_scope(&self, id: &span::Id) -> Option<registry::Scope<'_, S>>
where
S: for<'lookup> LookupSpan<'lookup>,
@@ -360,7 +360,7 @@ where
/// declaration</a> for details.
/// </pre>
///
- /// [stored data]: ../registry/struct.SpanRef.html
+ /// [stored data]: crate::registry::SpanRef
pub fn event_scope(&self, event: &Event<'_>) -> Option<registry::Scope<'_, S>>
where
S: for<'lookup> LookupSpan<'lookup>,
diff --git a/vendor/tracing-subscriber-0.3.3/src/layer/layered.rs b/vendor/tracing-subscriber/src/layer/layered.rs
index c690764ad..f09c58c97 100644
--- a/vendor/tracing-subscriber-0.3.3/src/layer/layered.rs
+++ b/vendor/tracing-subscriber/src/layer/layered.rs
@@ -1,9 +1,4 @@
-use tracing_core::{
- metadata::Metadata,
- span,
- subscriber::{Interest, Subscriber},
- Event, LevelFilter,
-};
+use tracing_core::{metadata::Metadata, span, Dispatch, Event, Interest, LevelFilter, Subscriber};
use crate::{
filter,
@@ -12,13 +7,17 @@ use crate::{
};
#[cfg(all(feature = "registry", feature = "std"))]
use crate::{filter::FilterId, registry::Registry};
-use core::{any::TypeId, cmp, fmt, marker::PhantomData};
+use core::{
+ any::{Any, TypeId},
+ cmp, fmt,
+ marker::PhantomData,
+};
/// A [`Subscriber`] composed of a `Subscriber` wrapped by one or more
/// [`Layer`]s.
///
/// [`Layer`]: crate::Layer
-/// [`Subscriber`]: https://docs.rs/tracing-core/latest/tracing_core/trait.Subscriber.html
+/// [`Subscriber`]: tracing_core::Subscriber
#[derive(Clone)]
pub struct Layered<L, I, S = I> {
/// The layer.
@@ -63,6 +62,30 @@ pub struct Layered<L, I, S = I> {
// === impl Layered ===
+impl<L, S> Layered<L, S>
+where
+ L: Layer<S>,
+ S: Subscriber,
+{
+ /// Returns `true` if this [`Subscriber`] is the same type as `T`.
+ pub fn is<T: Any>(&self) -> bool {
+ self.downcast_ref::<T>().is_some()
+ }
+
+ /// Returns some reference to this [`Subscriber`] value if it is of type `T`,
+ /// or `None` if it isn't.
+ pub fn downcast_ref<T: Any>(&self) -> Option<&T> {
+ unsafe {
+ let raw = self.downcast_raw(TypeId::of::<T>())?;
+ if raw.is_null() {
+ None
+ } else {
+ Some(&*(raw as *const T))
+ }
+ }
+ }
+}
+
impl<L, S> Subscriber for Layered<L, S>
where
L: Layer<S>,
@@ -92,7 +115,11 @@ where
}
fn max_level_hint(&self) -> Option<LevelFilter> {
- self.pick_level_hint(self.layer.max_level_hint(), self.inner.max_level_hint())
+ self.pick_level_hint(
+ self.layer.max_level_hint(),
+ self.inner.max_level_hint(),
+ super::subscriber_is_none(&self.inner),
+ )
}
fn new_span(&self, span: &span::Attributes<'_>) -> span::Id {
@@ -111,6 +138,16 @@ where
self.layer.on_follows_from(span, follows, self.ctx());
}
+ fn event_enabled(&self, event: &Event<'_>) -> bool {
+ if self.layer.event_enabled(event, self.ctx()) {
+ // if the outer layer enables the event, ask the inner subscriber.
+ self.inner.event_enabled(event)
+ } else {
+ // otherwise, the event is disabled by this layer
+ false
+ }
+ }
+
fn event(&self, event: &Event<'_>) {
self.inner.event(event);
self.layer.on_event(event, self.ctx());
@@ -152,7 +189,7 @@ where
#[cfg(all(feature = "registry", feature = "std"))]
{
if let Some(g) = guard.as_mut() {
- g.is_closing()
+ g.set_closing()
};
}
@@ -207,6 +244,11 @@ where
B: Layer<S>,
S: Subscriber,
{
+ fn on_register_dispatch(&self, subscriber: &Dispatch) {
+ self.layer.on_register_dispatch(subscriber);
+ self.inner.on_register_dispatch(subscriber);
+ }
+
fn on_layer(&mut self, subscriber: &mut S) {
self.layer.on_layer(subscriber);
self.inner.on_layer(subscriber);
@@ -229,7 +271,11 @@ where
}
fn max_level_hint(&self) -> Option<LevelFilter> {
- self.pick_level_hint(self.layer.max_level_hint(), self.inner.max_level_hint())
+ self.pick_level_hint(
+ self.layer.max_level_hint(),
+ self.inner.max_level_hint(),
+ super::layer_is_none(&self.inner),
+ )
}
#[inline]
@@ -251,6 +297,17 @@ where
}
#[inline]
+ fn event_enabled(&self, event: &Event<'_>, ctx: Context<'_, S>) -> bool {
+ if self.layer.event_enabled(event, ctx.clone()) {
+ // if the outer layer enables the event, ask the inner subscriber.
+ self.inner.event_enabled(event, ctx)
+ } else {
+ // otherwise, the event is disabled by this layer
+ false
+ }
+ }
+
+ #[inline]
fn on_event(&self, event: &Event<'_>, ctx: Context<'_, S>) {
self.inner.on_event(event, ctx.clone());
self.layer.on_event(event, ctx);
@@ -386,7 +443,7 @@ where
// (rather than calling into the inner type), clear the current
// per-layer filter interest state.
#[cfg(feature = "registry")]
- drop(filter::FilterState::take_interest());
+ filter::FilterState::take_interest();
return outer;
}
@@ -421,6 +478,7 @@ where
&self,
outer_hint: Option<LevelFilter>,
inner_hint: Option<LevelFilter>,
+ inner_is_none: bool,
) -> Option<LevelFilter> {
if self.inner_is_registry {
return outer_hint;
@@ -438,6 +496,31 @@ where
return None;
}
+ // If the layer is `Option::None`, then we
+ // want to short-circuit the layer underneath, if it
+ // returns `None`, to override the `None` layer returning
+ // `Some(OFF)`, which should ONLY apply when there are
+ // no other layers that return `None`. Note this
+ // `None` does not == `Some(TRACE)`, it means
+ // something more like: "whatever all the other
+ // layers agree on, default to `TRACE` if none
+ // have an opinion". We also choose do this AFTER
+ // we check for per-layer filters, which
+ // have their own logic.
+ //
+ // Also note that this does come at some perf cost, but
+ // this function is only called on initialization and
+ // subscriber reloading.
+ if super::layer_is_none(&self.layer) {
+ return cmp::max(outer_hint, Some(inner_hint?));
+ }
+
+ // Similarly, if the layer on the inside is `None` and it returned an
+ // `Off` hint, we want to override that with the outer hint.
+ if inner_is_none && inner_hint == Some(LevelFilter::OFF) {
+ return outer_hint;
+ }
+
cmp::max(outer_hint, inner_hint)
}
}
diff --git a/vendor/tracing-subscriber-0.3.3/src/layer/mod.rs b/vendor/tracing-subscriber/src/layer/mod.rs
index f3f994490..bdc154301 100644
--- a/vendor/tracing-subscriber-0.3.3/src/layer/mod.rs
+++ b/vendor/tracing-subscriber/src/layer/mod.rs
@@ -19,7 +19,7 @@
//! [`Subscriber`] behavior; it can _observe_ events and spans, but does not
//! assign IDs.
//!
-//! ## Composing Layers
+//! # Composing Layers
//!
//! Since a [`Layer`] does not implement a complete strategy for collecting
//! traces, it must be composed with a `Subscriber` in order to be used. The
@@ -135,9 +135,245 @@
//! [`Layer::with_subscriber`] as an implementation detail, as `with_subscriber`
//! calls must be nested, leading to less clear code for the reader.
//!
+//! ## Runtime Configuration With `Layer`s
+//!
+//! In some cases, a particular [`Layer`] may be enabled or disabled based on
+//! runtime configuration. This can introduce challenges, because the type of a
+//! layered [`Subscriber`] depends on which layers are added to it: if an `if`
+//! or `match` expression adds some [`Layer`] implementation in one branch,
+//! and other layers in another, the [`Subscriber`] values returned by those
+//! branches will have different types. For example, the following _will not_
+//! work:
+//!
+//! ```compile_fail
+//! # fn docs() -> Result<(), Box<dyn std::error::Error + 'static>> {
+//! # struct Config {
+//! # is_prod: bool,
+//! # path: &'static str,
+//! # }
+//! # let cfg = Config { is_prod: false, path: "debug.log" };
+//! use std::fs::File;
+//! use tracing_subscriber::{Registry, prelude::*};
+//!
+//! let stdout_log = tracing_subscriber::fmt::layer().pretty();
+//! let subscriber = Registry::default().with(stdout_log);
+//!
+//! // The compile error will occur here because the if and else
+//! // branches have different (and therefore incompatible) types.
+//! let subscriber = if cfg.is_prod {
+//! let file = File::create(cfg.path)?;
+//! let layer = tracing_subscriber::fmt::layer()
+//! .json()
+//! .with_writer(Arc::new(file));
+//! layer.with(subscriber)
+//! } else {
+//! layer
+//! };
+//!
+//! tracing::subscriber::set_global_default(subscriber)
+//! .expect("Unable to set global subscriber");
+//! # Ok(()) }
+//! ```
+//!
+//! However, a [`Layer`] wrapped in an [`Option`] [also implements the `Layer`
+//! trait][option-impl]. This allows individual layers to be enabled or disabled at
+//! runtime while always producing a [`Subscriber`] of the same type. For
+//! example:
+//!
+//! ```
+//! # fn docs() -> Result<(), Box<dyn std::error::Error + 'static>> {
+//! # struct Config {
+//! # is_prod: bool,
+//! # path: &'static str,
+//! # }
+//! # let cfg = Config { is_prod: false, path: "debug.log" };
+//! use std::fs::File;
+//! use tracing_subscriber::{Registry, prelude::*};
+//!
+//! let stdout_log = tracing_subscriber::fmt::layer().pretty();
+//! let subscriber = Registry::default().with(stdout_log);
+//!
+//! // if `cfg.is_prod` is true, also log JSON-formatted logs to a file.
+//! let json_log = if cfg.is_prod {
+//! let file = File::create(cfg.path)?;
+//! let json_log = tracing_subscriber::fmt::layer()
+//! .json()
+//! .with_writer(file);
+//! Some(json_log)
+//! } else {
+//! None
+//! };
+//!
+//! // If `cfg.is_prod` is false, then `json` will be `None`, and this layer
+//! // will do nothing. However, the subscriber will still have the same type
+//! // regardless of whether the `Option`'s value is `None` or `Some`.
+//! let subscriber = subscriber.with(json_log);
+//!
+//! tracing::subscriber::set_global_default(subscriber)
+//! .expect("Unable to set global subscriber");
+//! # Ok(()) }
+//! ```
+//!
+//! If a [`Layer`] may be one of several different types, note that [`Box<dyn
+//! Layer<S> + Send + Sync>` implements `Layer`][box-impl].
+//! This may be used to erase the type of a [`Layer`].
+//!
+//! For example, a function that configures a [`Layer`] to log to one of
+//! several outputs might return a `Box<dyn Layer<S> + Send + Sync + 'static>`:
+//! ```
+//! use tracing_subscriber::{
+//! Layer,
+//! registry::LookupSpan,
+//! prelude::*,
+//! };
+//! use std::{path::PathBuf, fs::File, io};
+//!
+//! /// Configures whether logs are emitted to a file, to stdout, or to stderr.
+//! pub enum LogConfig {
+//! File(PathBuf),
+//! Stdout,
+//! Stderr,
+//! }
+//!
+//! impl LogConfig {
+//! pub fn layer<S>(self) -> Box<dyn Layer<S> + Send + Sync + 'static>
+//! where
+//! S: tracing_core::Subscriber,
+//! for<'a> S: LookupSpan<'a>,
+//! {
+//! // Shared configuration regardless of where logs are output to.
+//! let fmt = tracing_subscriber::fmt::layer()
+//! .with_target(true)
+//! .with_thread_names(true);
+//!
+//! // Configure the writer based on the desired log target:
+//! match self {
+//! LogConfig::File(path) => {
+//! let file = File::create(path).expect("failed to create log file");
+//! Box::new(fmt.with_writer(file))
+//! },
+//! LogConfig::Stdout => Box::new(fmt.with_writer(io::stdout)),
+//! LogConfig::Stderr => Box::new(fmt.with_writer(io::stderr)),
+//! }
+//! }
+//! }
+//!
+//! let config = LogConfig::Stdout;
+//! tracing_subscriber::registry()
+//! .with(config.layer())
+//! .init();
+//! ```
+//!
+//! The [`Layer::boxed`] method is provided to make boxing a `Layer`
+//! more convenient, but [`Box::new`] may be used as well.
+//!
+//! When the number of `Layer`s varies at runtime, note that a
+//! [`Vec<L> where L: Layer` also implements `Layer`][vec-impl]. This
+//! can be used to add a variable number of `Layer`s to a `Subscriber`:
+//!
+//! ```
+//! use tracing_subscriber::{Layer, prelude::*};
+//! struct MyLayer {
+//! // ...
+//! }
+//! # impl MyLayer { fn new() -> Self { Self {} }}
+//!
+//! impl<S: tracing_core::Subscriber> Layer<S> for MyLayer {
+//! // ...
+//! }
+//!
+//! /// Returns how many layers we need
+//! fn how_many_layers() -> usize {
+//! // ...
+//! # 3
+//! }
+//!
+//! // Create a variable-length `Vec` of layers
+//! let mut layers = Vec::new();
+//! for _ in 0..how_many_layers() {
+//! layers.push(MyLayer::new());
+//! }
+//!
+//! tracing_subscriber::registry()
+//! .with(layers)
+//! .init();
+//! ```
+//!
+//! If a variable number of `Layer` is needed and those `Layer`s have
+//! different types, a `Vec` of [boxed `Layer` trait objects][box-impl] may
+//! be used. For example:
+//!
+//! ```
+//! use tracing_subscriber::{filter::LevelFilter, Layer, prelude::*};
+//! use std::fs::File;
+//! # fn main() -> Result<(), Box<dyn std::error::Error>> {
+//! struct Config {
+//! enable_log_file: bool,
+//! enable_stdout: bool,
+//! enable_stderr: bool,
+//! // ...
+//! }
+//! # impl Config {
+//! # fn from_config_file()-> Result<Self, Box<dyn std::error::Error>> {
+//! # // don't enable the log file so that the example doesn't actually create it
+//! # Ok(Self { enable_log_file: false, enable_stdout: true, enable_stderr: true })
+//! # }
+//! # }
+//!
+//! let cfg = Config::from_config_file()?;
+//!
+//! // Based on our dynamically loaded config file, create any number of layers:
+//! let mut layers = Vec::new();
+//!
+//! if cfg.enable_log_file {
+//! let file = File::create("myapp.log")?;
+//! let layer = tracing_subscriber::fmt::layer()
+//! .with_thread_names(true)
+//! .with_target(true)
+//! .json()
+//! .with_writer(file)
+//! // Box the layer as a type-erased trait object, so that it can
+//! // be pushed to the `Vec`.
+//! .boxed();
+//! layers.push(layer);
+//! }
+//!
+//! if cfg.enable_stdout {
+//! let layer = tracing_subscriber::fmt::layer()
+//! .pretty()
+//! .with_filter(LevelFilter::INFO)
+//! // Box the layer as a type-erased trait object, so that it can
+//! // be pushed to the `Vec`.
+//! .boxed();
+//! layers.push(layer);
+//! }
+//!
+//! if cfg.enable_stdout {
+//! let layer = tracing_subscriber::fmt::layer()
+//! .with_target(false)
+//! .with_filter(LevelFilter::WARN)
+//! // Box the layer as a type-erased trait object, so that it can
+//! // be pushed to the `Vec`.
+//! .boxed();
+//! layers.push(layer);
+//! }
+//!
+//! tracing_subscriber::registry()
+//! .with(layers)
+//! .init();
+//!# Ok(()) }
+//! ```
+//!
+//! Finally, if the number of layers _changes_ at runtime, a `Vec` of
+//! subscribers can be used alongside the [`reload`](crate::reload) module to
+//! add or remove subscribers dynamically at runtime.
+//!
+//! [option-impl]: Layer#impl-Layer<S>-for-Option<L>
+//! [box-impl]: Layer#impl-Layer%3CS%3E-for-Box%3Cdyn%20Layer%3CS%3E%20+%20Send%20+%20Sync%3E
+//! [vec-impl]: Layer#impl-Layer<S>-for-Vec<L>
//! [prelude]: crate::prelude
//!
-//! ## Recording Traces
+//! # Recording Traces
//!
//! The [`Layer`] trait defines a set of methods for consuming notifications from
//! tracing instrumentation, which are generally equivalent to the similarly
@@ -146,7 +382,7 @@
//! information provided by the wrapped subscriber (such as [the current span])
//! to the layer.
//!
-//! ## Filtering with `Layer`s
+//! # Filtering with `Layer`s
//!
//! As well as strategies for handling trace events, the `Layer` trait may also
//! be used to represent composable _filters_. This allows the determination of
@@ -158,7 +394,7 @@
//! combined with _per-layer filters_ that control what spans and events are
//! recorded by those layers.
//!
-//! ### Global Filtering
+//! ## Global Filtering
//!
//! A `Layer` that implements a filtering strategy should override the
//! [`register_callsite`] and/or [`enabled`] methods. It may also choose to implement
@@ -179,7 +415,29 @@
//! [`Interest::never()`] from its [`register_callsite`] method, filter
//! evaluation will short-circuit and the span or event will be disabled.
//!
-//! ### Per-Layer Filtering
+//! ### Enabling Interest
+//!
+//! Whenever an tracing event (or span) is emitted, it goes through a number of
+//! steps to determine how and how much it should be processed. The earlier an
+//! event is disabled, the less work has to be done to process the event, so
+//! `Layer`s that implement filtering should attempt to disable unwanted
+//! events as early as possible. In order, each event checks:
+//!
+//! - [`register_callsite`], once per callsite (roughly: once per time that
+//! `event!` or `span!` is written in the source code; this is cached at the
+//! callsite). See [`Subscriber::register_callsite`] and
+//! [`tracing_core::callsite`] for a summary of how this behaves.
+//! - [`enabled`], once per emitted event (roughly: once per time that `event!`
+//! or `span!` is *executed*), and only if `register_callsite` regesters an
+//! [`Interest::sometimes`]. This is the main customization point to globally
+//! filter events based on their [`Metadata`]. If an event can be disabled
+//! based only on [`Metadata`], it should be, as this allows the construction
+//! of the actual `Event`/`Span` to be skipped.
+//! - For events only (and not spans), [`event_enabled`] is called just before
+//! processing the event. This gives layers one last chance to say that
+//! an event should be filtered out, now that the event's fields are known.
+//!
+//! ## Per-Layer Filtering
//!
//! **Note**: per-layer filtering APIs currently require the [`"registry"` crate
//! feature flag][feat] to be enabled.
@@ -393,94 +651,16 @@
//! # Ok(()) }
//! ```
//!
-//! ## Runtime Configuration With Layers
-//!
-//! In some cases, a particular [`Layer`] may be enabled or disabled based on
-//! runtime configuration. This can introduce challenges, because the type of a
-//! layered [`Subscriber`] depends on which layers are added to it: if an `if`
-//! or `match` expression adds some [`Layer`]s in one branch and other layers
-//! in another, the [`Subscriber`] values returned by those branches will have
-//! different types. For example, the following _will not_ work:
-//!
-//! ```compile_fail
-//! # fn docs() -> Result<(), Box<dyn std::error::Error + 'static>> {
-//! # struct Config {
-//! # is_prod: bool,
-//! # path: &'static str,
-//! # }
-//! # let cfg = Config { is_prod: false, path: "debug.log" };
-//! use std::{fs::File, sync::Arc};
-//! use tracing_subscriber::{Registry, prelude::*};
-//!
-//! let stdout_log = tracing_subscriber::fmt::layer().pretty();
-//! let subscriber = Registry::default().with(stdout_log);
-//!
-//! // The compile error will occur here because the if and else
-//! // branches have different (and therefore incompatible) types.
-//! let subscriber = if cfg.is_prod {
-//! let file = File::create(cfg.path)?;
-//! let layer = tracing_subscriber::fmt::layer()
-//! .json()
-//! .with_writer(Arc::new(file));
-//! subscriber.with(layer)
-//! } else {
-//! subscriber
-//! };
-//!
-//! tracing::subscriber::set_global_default(subscriber)
-//! .expect("Unable to set global subscriber");
-//! # Ok(()) }
-//! ```
-//!
-//! However, a [`Layer`] wrapped in an [`Option`] [also implements the `Layer`
-//! trait][option-impl]. This allows individual layers to be enabled or disabled at
-//! runtime while always producing a [`Subscriber`] of the same type. For
-//! example:
-//!
-//! ```
-//! # fn docs() -> Result<(), Box<dyn std::error::Error + 'static>> {
-//! # struct Config {
-//! # is_prod: bool,
-//! # path: &'static str,
-//! # }
-//! # let cfg = Config { is_prod: false, path: "debug.log" };
-//! use std::{fs::File, sync::Arc};
-//! use tracing_subscriber::{Registry, prelude::*};
-//!
-//! let stdout_log = tracing_subscriber::fmt::layer().pretty();
-//! let subscriber = Registry::default().with(stdout_log);
-//!
-//! // if `cfg.is_prod` is true, also log JSON-formatted logs to a file.
-//! let json_log = if cfg.is_prod {
-//! let file = File::create(cfg.path)?;
-//! let json_log = tracing_subscriber::fmt::layer()
-//! .json()
-//! .with_writer(Arc::new(file));
-//! Some(json_log)
-//! } else {
-//! None
-//! };
-//!
-//! // If `cfg.is_prod` is false, then `json` will be `None`, and this layer
-//! // will do nothing. However, the subscriber will still have the same type
-//! // regardless of whether the `Option`'s value is `None` or `Some`.
-//! let subscriber = subscriber.with(json_log);
-//!
-//! tracing::subscriber::set_global_default(subscriber)
-//! .expect("Unable to set global subscriber");
-//! # Ok(()) }
-//! ```
-//!
-//! [`Subscriber`]: https://docs.rs/tracing-core/latest/tracing_core/subscriber/trait.Subscriber.html
-//! [span IDs]: https://docs.rs/tracing-core/latest/tracing_core/span/struct.Id.html
+//! [`Subscriber`]: tracing_core::subscriber::Subscriber
+//! [span IDs]: tracing_core::span::Id
//! [the current span]: Context::current_span
//! [`register_callsite`]: Layer::register_callsite
//! [`enabled`]: Layer::enabled
+//! [`event_enabled`]: Layer::event_enabled
//! [`on_enter`]: Layer::on_enter
//! [`Layer::register_callsite`]: Layer::register_callsite
//! [`Layer::enabled`]: Layer::enabled
-//! [`Interest::never()`]: https://docs.rs/tracing-core/latest/tracing_core/subscriber/struct.Interest.html#method.never
-//! [option-impl]: crate::layer::Layer#impl-Layer<S>-for-Option<L>
+//! [`Interest::never()`]: tracing_core::subscriber::Interest::never()
//! [`Filtered`]: crate::filter::Filtered
//! [`filter`]: crate::filter
//! [`Targets`]: crate::filter::Targets
@@ -498,7 +678,7 @@ use tracing_core::{
metadata::Metadata,
span,
subscriber::{Interest, Subscriber},
- Event, LevelFilter,
+ Dispatch, Event, LevelFilter,
};
use core::any::TypeId;
@@ -531,6 +711,31 @@ where
S: Subscriber,
Self: 'static,
{
+ /// Performs late initialization when installing this layer as a
+ /// [`Subscriber`].
+ ///
+ /// ## Avoiding Memory Leaks
+ ///
+ /// `Layer`s should not store the [`Dispatch`] pointing to the [`Subscriber`]
+ /// that they are a part of. Because the `Dispatch` owns the `Subscriber`,
+ /// storing the `Dispatch` within the `Subscriber` will create a reference
+ /// count cycle, preventing the `Dispatch` from ever being dropped.
+ ///
+ /// Instead, when it is necessary to store a cyclical reference to the
+ /// `Dispatch` within a `Layer`, use [`Dispatch::downgrade`] to convert a
+ /// `Dispatch` into a [`WeakDispatch`]. This type is analogous to
+ /// [`std::sync::Weak`], and does not create a reference count cycle. A
+ /// [`WeakDispatch`] can be stored within a subscriber without causing a
+ /// memory leak, and can be [upgraded] into a `Dispatch` temporarily when
+ /// the `Dispatch` must be accessed by the subscriber.
+ ///
+ /// [`WeakDispatch`]: tracing_core::dispatcher::WeakDispatch
+ /// [upgraded]: tracing_core::dispatcher::WeakDispatch::upgrade
+ /// [`Subscriber`]: tracing_core::Subscriber
+ fn on_register_dispatch(&self, collector: &Dispatch) {
+ let _ = collector;
+ }
+
/// Performs late initialization when attaching a `Layer` to a
/// [`Subscriber`].
///
@@ -592,15 +797,15 @@ where
/// globally enable or disable those callsites, it should always return
/// [`Interest::always()`].
///
- /// [`Interest`]: https://docs.rs/tracing-core/latest/tracing_core/struct.Interest.html
- /// [`Subscriber::register_callsite`]: https://docs.rs/tracing-core/latest/tracing_core/trait.Subscriber.html#method.register_callsite
- /// [`Interest::never()`]: https://docs.rs/tracing-core/latest/tracing_core/subscriber/struct.Interest.html#method.never
- /// [`Interest::always()`]: https://docs.rs/tracing-core/latest/tracing_core/subscriber/struct.Interest.html#method.always
- /// [`self.enabled`]: #method.enabled
- /// [`Layer::enabled`]: #method.enabled
- /// [`on_event`]: #method.on_event
- /// [`on_enter`]: #method.on_enter
- /// [`on_exit`]: #method.on_exit
+ /// [`Interest`]: tracing_core::Interest
+ /// [`Subscriber::register_callsite`]: tracing_core::Subscriber::register_callsite()
+ /// [`Interest::never()`]: tracing_core::subscriber::Interest::never()
+ /// [`Interest::always()`]: tracing_core::subscriber::Interest::always()
+ /// [`self.enabled`]: Layer::enabled()
+ /// [`Layer::enabled`]: Layer::enabled()
+ /// [`on_event`]: Layer::on_event()
+ /// [`on_enter`]: Layer::on_enter()
+ /// [`on_exit`]: Layer::on_exit()
/// [the trait-level documentation]: #filtering-with-layers
fn register_callsite(&self, metadata: &'static Metadata<'static>) -> Interest {
if self.enabled(metadata, Context::none()) {
@@ -635,13 +840,12 @@ where
/// See [the trait-level documentation] for more information on filtering
/// with `Layer`s.
///
- /// [`Interest`]: https://docs.rs/tracing-core/latest/tracing_core/struct.Interest.html
- /// [`Context`]: ../struct.Context.html
- /// [`Subscriber::enabled`]: https://docs.rs/tracing-core/latest/tracing_core/trait.Subscriber.html#method.enabled
- /// [`Layer::register_callsite`]: #method.register_callsite
- /// [`on_event`]: #method.on_event
- /// [`on_enter`]: #method.on_enter
- /// [`on_exit`]: #method.on_exit
+ /// [`Interest`]: tracing_core::Interest
+ /// [`Subscriber::enabled`]: tracing_core::Subscriber::enabled()
+ /// [`Layer::register_callsite`]: Layer::register_callsite()
+ /// [`on_event`]: Layer::on_event()
+ /// [`on_enter`]: Layer::on_enter()
+ /// [`on_exit`]: Layer::on_exit()
/// [the trait-level documentation]: #filtering-with-layers
fn enabled(&self, metadata: &Metadata<'_>, ctx: Context<'_, S>) -> bool {
let _ = (metadata, ctx);
@@ -676,6 +880,31 @@ where
// seems like a good future-proofing measure as it may grow other methods later...
fn on_follows_from(&self, _span: &span::Id, _follows: &span::Id, _ctx: Context<'_, S>) {}
+ /// Called before [`on_event`], to determine if `on_event` should be called.
+ ///
+ /// <div class="example-wrap" style="display:inline-block">
+ /// <pre class="ignore" style="white-space:normal;font:inherit;">
+ ///
+ /// **Note**: This method determines whether an event is globally enabled,
+ /// *not* whether the individual `Layer` will be notified about the
+ /// event. This is intended to be used by `Layer`s that implement
+ /// filtering for the entire stack. `Layer`s which do not wish to be
+ /// notified about certain events but do not wish to globally disable them
+ /// should ignore those events in their [on_event][Self::on_event].
+ ///
+ /// </pre></div>
+ ///
+ /// See [the trait-level documentation] for more information on filtering
+ /// with `Layer`s.
+ ///
+ /// [`on_event`]: Self::on_event
+ /// [`Interest`]: tracing_core::Interest
+ /// [the trait-level documentation]: #filtering-with-layers
+ #[inline] // collapse this to a constant please mrs optimizer
+ fn event_enabled(&self, _event: &Event<'_>, _ctx: Context<'_, S>) -> bool {
+ true
+ }
+
/// Notifies this layer that an event has occurred.
fn on_event(&self, _event: &Event<'_>, _ctx: Context<'_, S>) {}
@@ -840,7 +1069,7 @@ where
/// .with_subscriber(MySubscriber::new());
///```
///
- /// [`Subscriber`]: https://docs.rs/tracing-core/latest/tracing_core/trait.Subscriber.html
+ /// [`Subscriber`]: tracing_core::Subscriber
fn with_subscriber(mut self, mut inner: S) -> Layered<Self, S>
where
Self: Sized,
@@ -857,7 +1086,7 @@ where
/// per-layer filtering.
///
/// [`Filtered`]: crate::filter::Filtered
- /// [plf]: #per-layer-filtering
+ /// [plf]: crate::layer#per-layer-filtering
#[cfg(all(feature = "registry", feature = "std"))]
#[cfg_attr(docsrs, doc(cfg(all(feature = "registry", feature = "std"))))]
fn with_filter<F>(self, filter: F) -> filter::Filtered<Self, F, S>
@@ -868,6 +1097,131 @@ where
filter::Filtered::new(self, filter)
}
+ /// Erases the type of this [`Layer`], returning a [`Box`]ed `dyn
+ /// Layer` trait object.
+ ///
+ /// This can be used when a function returns a `Layer` which may be of
+ /// one of several types, or when a `Layer` subscriber has a very long type
+ /// signature.
+ ///
+ /// # Examples
+ ///
+ /// The following example will *not* compile, because the value assigned to
+ /// `log_layer` may have one of several different types:
+ ///
+ /// ```compile_fail
+ /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
+ /// use tracing_subscriber::{Layer, filter::LevelFilter, prelude::*};
+ /// use std::{path::PathBuf, fs::File, io};
+ ///
+ /// /// Configures whether logs are emitted to a file, to stdout, or to stderr.
+ /// pub enum LogConfig {
+ /// File(PathBuf),
+ /// Stdout,
+ /// Stderr,
+ /// }
+ ///
+ /// let config = // ...
+ /// # LogConfig::Stdout;
+ ///
+ /// // Depending on the config, construct a layer of one of several types.
+ /// let log_layer = match config {
+ /// // If logging to a file, use a maximally-verbose configuration.
+ /// LogConfig::File(path) => {
+ /// let file = File::create(path)?;
+ /// tracing_subscriber::fmt::layer()
+ /// .with_thread_ids(true)
+ /// .with_thread_names(true)
+ /// // Selecting the JSON logging format changes the layer's
+ /// // type.
+ /// .json()
+ /// .with_span_list(true)
+ /// // Setting the writer to use our log file changes the
+ /// // layer's type again.
+ /// .with_writer(file)
+ /// },
+ ///
+ /// // If logging to stdout, use a pretty, human-readable configuration.
+ /// LogConfig::Stdout => tracing_subscriber::fmt::layer()
+ /// // Selecting the "pretty" logging format changes the
+ /// // layer's type!
+ /// .pretty()
+ /// .with_writer(io::stdout)
+ /// // Add a filter based on the RUST_LOG environment variable;
+ /// // this changes the type too!
+ /// .and_then(tracing_subscriber::EnvFilter::from_default_env()),
+ ///
+ /// // If logging to stdout, only log errors and warnings.
+ /// LogConfig::Stderr => tracing_subscriber::fmt::layer()
+ /// // Changing the writer changes the layer's type
+ /// .with_writer(io::stderr)
+ /// // Only log the `WARN` and `ERROR` levels. Adding a filter
+ /// // changes the layer's type to `Filtered<LevelFilter, ...>`.
+ /// .with_filter(LevelFilter::WARN),
+ /// };
+ ///
+ /// tracing_subscriber::registry()
+ /// .with(log_layer)
+ /// .init();
+ /// # Ok(()) }
+ /// ```
+ ///
+ /// However, adding a call to `.boxed()` after each match arm erases the
+ /// layer's type, so this code *does* compile:
+ ///
+ /// ```
+ /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
+ /// # use tracing_subscriber::{Layer, filter::LevelFilter, prelude::*};
+ /// # use std::{path::PathBuf, fs::File, io};
+ /// # pub enum LogConfig {
+ /// # File(PathBuf),
+ /// # Stdout,
+ /// # Stderr,
+ /// # }
+ /// # let config = LogConfig::Stdout;
+ /// let log_layer = match config {
+ /// LogConfig::File(path) => {
+ /// let file = File::create(path)?;
+ /// tracing_subscriber::fmt::layer()
+ /// .with_thread_ids(true)
+ /// .with_thread_names(true)
+ /// .json()
+ /// .with_span_list(true)
+ /// .with_writer(file)
+ /// // Erase the type by boxing the layer
+ /// .boxed()
+ /// },
+ ///
+ /// LogConfig::Stdout => tracing_subscriber::fmt::layer()
+ /// .pretty()
+ /// .with_writer(io::stdout)
+ /// .and_then(tracing_subscriber::EnvFilter::from_default_env())
+ /// // Erase the type by boxing the layer
+ /// .boxed(),
+ ///
+ /// LogConfig::Stderr => tracing_subscriber::fmt::layer()
+ /// .with_writer(io::stderr)
+ /// .with_filter(LevelFilter::WARN)
+ /// // Erase the type by boxing the layer
+ /// .boxed(),
+ /// };
+ ///
+ /// tracing_subscriber::registry()
+ /// .with(log_layer)
+ /// .init();
+ /// # Ok(()) }
+ /// ```
+ #[cfg(any(feature = "alloc", feature = "std"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "alloc", feature = "std"))))]
+ fn boxed(self) -> Box<dyn Layer<S> + Send + Sync + 'static>
+ where
+ Self: Sized,
+ Self: Layer<S> + Send + Sync + 'static,
+ S: Subscriber,
+ {
+ Box::new(self)
+ }
+
#[doc(hidden)]
unsafe fn downcast_raw(&self, id: TypeId) -> Option<*const ()> {
if id == TypeId::of::<Self>() {
@@ -880,6 +1234,7 @@ where
feature! {
#![all(feature = "registry", feature = "std")]
+
/// A per-[`Layer`] filter that determines whether a span or event is enabled
/// for an individual layer.
///
@@ -1022,6 +1377,26 @@ feature! {
Interest::sometimes()
}
+ /// Called before the filtered [`Layer]'s [`on_event`], to determine if
+ /// `on_event` should be called.
+ ///
+ /// This gives a chance to filter events based on their fields. Note,
+ /// however, that this *does not* override [`enabled`], and is not even
+ /// called if [`enabled`] returns `false`.
+ ///
+ /// ## Default Implementation
+ ///
+ /// By default, this method returns `true`, indicating that no events are
+ /// filtered out based on their fields.
+ ///
+ /// [`enabled`]: crate::layer::Filter::enabled
+ /// [`on_event`]: crate::layer::Layer::on_event
+ #[inline] // collapse this to a constant please mrs optimizer
+ fn event_enabled(&self, event: &Event<'_>, cx: &Context<'_, S>) -> bool {
+ let _ = (event, cx);
+ true
+ }
+
/// Returns an optional hint of the highest [verbosity level][level] that
/// this `Filter` will enable.
///
@@ -1054,6 +1429,51 @@ feature! {
fn max_level_hint(&self) -> Option<LevelFilter> {
None
}
+
+ /// Notifies this filter that a new span was constructed with the given
+ /// `Attributes` and `Id`.
+ ///
+ /// By default, this method does nothing. `Filter` implementations that
+ /// need to be notified when new spans are created can override this
+ /// method.
+ fn on_new_span(&self, attrs: &span::Attributes<'_>, id: &span::Id, ctx: Context<'_, S>) {
+ let _ = (attrs, id, ctx);
+ }
+
+
+ /// Notifies this filter that a span with the given `Id` recorded the given
+ /// `values`.
+ ///
+ /// By default, this method does nothing. `Filter` implementations that
+ /// need to be notified when new spans are created can override this
+ /// method.
+ fn on_record(&self, id: &span::Id, values: &span::Record<'_>, ctx: Context<'_, S>) {
+ let _ = (id, values, ctx);
+ }
+
+ /// Notifies this filter that a span with the given ID was entered.
+ ///
+ /// By default, this method does nothing. `Filter` implementations that
+ /// need to be notified when a span is entered can override this method.
+ fn on_enter(&self, id: &span::Id, ctx: Context<'_, S>) {
+ let _ = (id, ctx);
+ }
+
+ /// Notifies this filter that a span with the given ID was exited.
+ ///
+ /// By default, this method does nothing. `Filter` implementations that
+ /// need to be notified when a span is exited can override this method.
+ fn on_exit(&self, id: &span::Id, ctx: Context<'_, S>) {
+ let _ = (id, ctx);
+ }
+
+ /// Notifies this filter that a span with the given ID has been closed.
+ ///
+ /// By default, this method does nothing. `Filter` implementations that
+ /// need to be notified when a span is closed can override this method.
+ fn on_close(&self, id: span::Id, ctx: Context<'_, S>) {
+ let _ = (id, ctx);
+ }
}
}
@@ -1077,6 +1497,47 @@ pub struct Identity {
// === impl Layer ===
+#[derive(Clone, Copy)]
+pub(crate) struct NoneLayerMarker(());
+static NONE_LAYER_MARKER: NoneLayerMarker = NoneLayerMarker(());
+
+/// Is a type implementing `Layer` `Option::<_>::None`?
+pub(crate) fn layer_is_none<L, S>(layer: &L) -> bool
+where
+ L: Layer<S>,
+ S: Subscriber,
+{
+ unsafe {
+ // Safety: we're not actually *doing* anything with this pointer ---
+ // this only care about the `Option`, which is essentially being used
+ // as a bool. We can rely on the pointer being valid, because it is
+ // a crate-private type, and is only returned by the `Layer` impl
+ // for `Option`s. However, even if the layer *does* decide to be
+ // evil and give us an invalid pointer here, that's fine, because we'll
+ // never actually dereference it.
+ layer.downcast_raw(TypeId::of::<NoneLayerMarker>())
+ }
+ .is_some()
+}
+
+/// Is a type implementing `Subscriber` `Option::<_>::None`?
+pub(crate) fn subscriber_is_none<S>(subscriber: &S) -> bool
+where
+ S: Subscriber,
+{
+ unsafe {
+ // Safety: we're not actually *doing* anything with this pointer ---
+ // this only care about the `Option`, which is essentially being used
+ // as a bool. We can rely on the pointer being valid, because it is
+ // a crate-private type, and is only returned by the `Layer` impl
+ // for `Option`s. However, even if the subscriber *does* decide to be
+ // evil and give us an invalid pointer here, that's fine, because we'll
+ // never actually dereference it.
+ subscriber.downcast_raw(TypeId::of::<NoneLayerMarker>())
+ }
+ .is_some()
+}
+
impl<L, S> Layer<S> for Option<L>
where
L: Layer<S>,
@@ -1115,7 +1576,11 @@ where
fn max_level_hint(&self) -> Option<LevelFilter> {
match self {
Some(ref inner) => inner.max_level_hint(),
- None => None,
+ None => {
+ // There is no inner layer, so this layer will
+ // never enable anything.
+ Some(LevelFilter::OFF)
+ }
}
}
@@ -1134,6 +1599,14 @@ where
}
#[inline]
+ fn event_enabled(&self, event: &Event<'_>, ctx: Context<'_, S>) -> bool {
+ match self {
+ Some(ref inner) => inner.event_enabled(event, ctx),
+ None => true,
+ }
+ }
+
+ #[inline]
fn on_event(&self, event: &Event<'_>, ctx: Context<'_, S>) {
if let Some(ref inner) = self {
inner.on_event(event, ctx);
@@ -1173,6 +1646,8 @@ where
unsafe fn downcast_raw(&self, id: TypeId) -> Option<*const ()> {
if id == TypeId::of::<Self>() {
Some(self as *const _ as *const ())
+ } else if id == TypeId::of::<NoneLayerMarker>() && self.is_none() {
+ Some(&NONE_LAYER_MARKER as *const _ as *const ())
} else {
self.as_ref().and_then(|inner| inner.downcast_raw(id))
}
@@ -1181,10 +1656,17 @@ where
feature! {
#![any(feature = "std", feature = "alloc")]
+ #[cfg(not(feature = "std"))]
+ use alloc::vec::Vec;
macro_rules! layer_impl_body {
() => {
#[inline]
+ fn on_register_dispatch(&self, subscriber: &Dispatch) {
+ self.deref().on_register_dispatch(subscriber);
+ }
+
+ #[inline]
fn on_layer(&mut self, subscriber: &mut S) {
self.deref_mut().on_layer(subscriber);
}
@@ -1220,6 +1702,11 @@ feature! {
}
#[inline]
+ fn event_enabled(&self, event: &Event<'_>, ctx: Context<'_, S>) -> bool {
+ self.deref().event_enabled(event, ctx)
+ }
+
+ #[inline]
fn on_event(&self, event: &Event<'_>, ctx: Context<'_, S>) {
self.deref().on_event(event, ctx)
}
@@ -1266,6 +1753,125 @@ feature! {
{
layer_impl_body! {}
}
+
+
+
+ impl<S, L> Layer<S> for Vec<L>
+ where
+ L: Layer<S>,
+ S: Subscriber,
+ {
+
+ fn on_layer(&mut self, subscriber: &mut S) {
+ for l in self {
+ l.on_layer(subscriber);
+ }
+ }
+
+ fn register_callsite(&self, metadata: &'static Metadata<'static>) -> Interest {
+ // Return highest level of interest.
+ let mut interest = Interest::never();
+ for l in self {
+ let new_interest = l.register_callsite(metadata);
+ if (interest.is_sometimes() && new_interest.is_always())
+ || (interest.is_never() && !new_interest.is_never())
+ {
+ interest = new_interest;
+ }
+ }
+
+ interest
+ }
+
+ fn enabled(&self, metadata: &Metadata<'_>, ctx: Context<'_, S>) -> bool {
+ self.iter().all(|l| l.enabled(metadata, ctx.clone()))
+ }
+
+ fn event_enabled(&self, event: &Event<'_>, ctx: Context<'_, S>) -> bool {
+ self.iter().all(|l| l.event_enabled(event, ctx.clone()))
+ }
+
+ fn on_new_span(&self, attrs: &span::Attributes<'_>, id: &span::Id, ctx: Context<'_, S>) {
+ for l in self {
+ l.on_new_span(attrs, id, ctx.clone());
+ }
+ }
+
+ fn max_level_hint(&self) -> Option<LevelFilter> {
+ // Default to `OFF` if there are no inner layers.
+ let mut max_level = LevelFilter::OFF;
+ for l in self {
+ // NOTE(eliza): this is slightly subtle: if *any* layer
+ // returns `None`, we have to return `None`, assuming there is
+ // no max level hint, since that particular layer cannot
+ // provide a hint.
+ let hint = l.max_level_hint()?;
+ max_level = core::cmp::max(hint, max_level);
+ }
+ Some(max_level)
+ }
+
+ fn on_record(&self, span: &span::Id, values: &span::Record<'_>, ctx: Context<'_, S>) {
+ for l in self {
+ l.on_record(span, values, ctx.clone())
+ }
+ }
+
+ fn on_follows_from(&self, span: &span::Id, follows: &span::Id, ctx: Context<'_, S>) {
+ for l in self {
+ l.on_follows_from(span, follows, ctx.clone());
+ }
+ }
+
+ fn on_event(&self, event: &Event<'_>, ctx: Context<'_, S>) {
+ for l in self {
+ l.on_event(event, ctx.clone());
+ }
+ }
+
+ fn on_enter(&self, id: &span::Id, ctx: Context<'_, S>) {
+ for l in self {
+ l.on_enter(id, ctx.clone());
+ }
+ }
+
+ fn on_exit(&self, id: &span::Id, ctx: Context<'_, S>) {
+ for l in self {
+ l.on_exit(id, ctx.clone());
+ }
+ }
+
+ fn on_close(&self, id: span::Id, ctx: Context<'_, S>) {
+ for l in self {
+ l.on_close(id.clone(), ctx.clone());
+ }
+ }
+
+ #[doc(hidden)]
+ unsafe fn downcast_raw(&self, id: TypeId) -> Option<*const ()> {
+ // If downcasting to `Self`, return a pointer to `self`.
+ if id == TypeId::of::<Self>() {
+ return Some(self as *const _ as *const ());
+ }
+
+ // Someone is looking for per-layer filters. But, this `Vec`
+ // might contain layers with per-layer filters *and*
+ // layers without filters. It should only be treated as a
+ // per-layer-filtered layer if *all* its layers have
+ // per-layer filters.
+ // XXX(eliza): it's a bummer we have to do this linear search every
+ // time. It would be nice if this could be cached, but that would
+ // require replacing the `Vec` impl with an impl for a newtype...
+ if filter::is_plf_downcast_marker(id) && self.iter().any(|s| s.downcast_raw(id).is_none()) {
+ return None;
+ }
+
+ // Otherwise, return the first child of `self` that downcaasts to
+ // the selected type, if any.
+ // XXX(eliza): hope this is reasonable lol
+ self.iter().find_map(|l| l.downcast_raw(id))
+ }
+ }
}
// === impl SubscriberExt ===
diff --git a/vendor/tracing-subscriber-0.3.3/src/layer/tests.rs b/vendor/tracing-subscriber/src/layer/tests.rs
index d7ad61769..d7ad61769 100644
--- a/vendor/tracing-subscriber-0.3.3/src/layer/tests.rs
+++ b/vendor/tracing-subscriber/src/layer/tests.rs
diff --git a/vendor/tracing-subscriber-0.3.3/src/lib.rs b/vendor/tracing-subscriber/src/lib.rs
index 563a86dee..808923007 100644
--- a/vendor/tracing-subscriber-0.3.3/src/lib.rs
+++ b/vendor/tracing-subscriber/src/lib.rs
@@ -10,7 +10,7 @@
//! `tracing-subscriber` is intended for use by both `Subscriber` authors and
//! application authors using `tracing` to instrument their applications.
//!
-//! *Compiler support: [requires `rustc` 1.42+][msrv]*
+//! *Compiler support: [requires `rustc` 1.50+][msrv]*
//!
//! [msrv]: #supported-rust-versions
//!
@@ -60,9 +60,11 @@
//! **Requires "std"**.
//! - `json`: Enables `fmt` support for JSON output. In JSON output, the ANSI
//! feature does nothing. **Requires "fmt" and "std"**.
-//! - [`local-time`]: Enables local time formatting when using the [`time`
+//! - `local-time`: Enables local time formatting when using the [`time`
//! crate]'s timestamp formatters with the `fmt` subscriber.
//!
+//! [`registry`]: mod@registry
+//!
//! ### Optional Dependencies
//!
//! - [`tracing-log`]: Enables better formatting for events emitted by `log`
@@ -80,7 +82,7 @@
//! used without requiring the Rust standard library, although some features are
//! disabled. Although most of the APIs provided by `tracing-subscriber`, such
//! as [`fmt`] and [`EnvFilter`], require the standard library, some
-//! functionality, such as the [`Subscriber`] trait, can still be used in
+//! functionality, such as the [`Layer`] trait, can still be used in
//! `no_std` environments.
//!
//! The dependency on the standard library is controlled by two crate feature
@@ -102,10 +104,41 @@
//! tracing-subscriber = { version = "0.3", default-features = false, features = ["alloc"] }
//! ```
//!
+//! ### Unstable Features
+//!
+//! These feature flags enable **unstable** features. The public API may break in 0.1.x
+//! releases. To enable these features, the `--cfg tracing_unstable` must be passed to
+//! `rustc` when compiling.
+//!
+//! The following unstable feature flags are currently available:
+//!
+//! * `valuable`: Enables support for serializing values recorded using the
+//! [`valuable`] crate as structured JSON in the [`format::Json`] formatter.
+//!
+//! #### Enabling Unstable Features
+//!
+//! The easiest way to set the `tracing_unstable` cfg is to use the `RUSTFLAGS`
+//! env variable when running `cargo` commands:
+//!
+//! ```shell
+//! RUSTFLAGS="--cfg tracing_unstable" cargo build
+//! ```
+//! Alternatively, the following can be added to the `.cargo/config` file in a
+//! project to automatically enable the cfg flag for that project:
+//!
+//! ```toml
+//! [build]
+//! rustflags = ["--cfg", "tracing_unstable"]
+//! ```
+//!
+//! [feature flags]: https://doc.rust-lang.org/cargo/reference/manifest.html#the-features-section
+//! [`valuable`]: https://crates.io/crates/valuable
+//! [`format::Json`]: crate::fmt::format::Json
+//!
//! ## Supported Rust Versions
//!
//! Tracing is built against the latest stable release. The minimum supported
-//! version is 1.42. The current Tracing version is not guaranteed to build on
+//! version is 1.50. The current Tracing version is not guaranteed to build on
//! Rust versions earlier than the minimum supported version.
//!
//! Tracing follows the same compiler support policies as the rest of the Tokio
@@ -116,17 +149,18 @@
//! supported compiler version is not considered a semver breaking change as
//! long as doing so complies with this policy.
//!
-//! [`tracing`]: https://docs.rs/tracing/latest/tracing/
-//! [`Subscriber`]: https://docs.rs/tracing-core/latest/tracing_core/subscriber/trait.Subscriber.html
-//! [`EnvFilter`]: filter/struct.EnvFilter.html
-//! [`fmt`]: fmt/index.html
+//! [`Subscriber`]: tracing_core::subscriber::Subscriber
+//! [`tracing`]: https://docs.rs/tracing/latest/tracing
+//! [`EnvFilter`]: filter::EnvFilter
+//! [`fmt`]: mod@fmt
//! [`tracing-log`]: https://crates.io/crates/tracing-log
//! [`smallvec`]: https://crates.io/crates/smallvec
//! [`env_logger` crate]: https://crates.io/crates/env_logger
//! [`parking_lot`]: https://crates.io/crates/parking_lot
//! [`time` crate]: https://crates.io/crates/time
-//! [`liballoc`]: https://doc.rust-lang.org/alloc/index.html
-#![doc(html_root_url = "https://docs.rs/tracing-subscriber/0.3.1")]
+//! [`libstd`]: std
+//! [`liballoc`]: alloc
+#![doc(html_root_url = "https://docs.rs/tracing-subscriber/0.3.15")]
#![doc(
html_logo_url = "https://raw.githubusercontent.com/tokio-rs/tracing/master/assets/logo-type.png",
issue_tracker_base_url = "https://github.com/tokio-rs/tracing/issues/"
diff --git a/vendor/tracing-subscriber-0.3.3/src/macros.rs b/vendor/tracing-subscriber/src/macros.rs
index 81351132f..81351132f 100644
--- a/vendor/tracing-subscriber-0.3.3/src/macros.rs
+++ b/vendor/tracing-subscriber/src/macros.rs
diff --git a/vendor/tracing-subscriber-0.3.3/src/prelude.rs b/vendor/tracing-subscriber/src/prelude.rs
index c2230907b..c2230907b 100644
--- a/vendor/tracing-subscriber-0.3.3/src/prelude.rs
+++ b/vendor/tracing-subscriber/src/prelude.rs
diff --git a/vendor/tracing-subscriber-0.3.3/src/registry/extensions.rs b/vendor/tracing-subscriber/src/registry/extensions.rs
index 899e1549f..ff76fb599 100644
--- a/vendor/tracing-subscriber-0.3.3/src/registry/extensions.rs
+++ b/vendor/tracing-subscriber/src/registry/extensions.rs
@@ -78,7 +78,7 @@ impl<'a> ExtensionsMut<'a> {
/// should be able to reuse timestamp _x_.
///
/// Therefore, extensions should generally be newtypes, rather than common
- /// types like [`String`](https://doc.rust-lang.org/std/string/struct.String.html), to avoid accidental
+ /// types like [`String`](std::string::String), to avoid accidental
/// cross-`Layer` clobbering.
///
/// ## Panics
diff --git a/vendor/tracing-subscriber-0.3.3/src/registry/mod.rs b/vendor/tracing-subscriber/src/registry/mod.rs
index f3b77b6a9..38af53e8a 100644
--- a/vendor/tracing-subscriber-0.3.3/src/registry/mod.rs
+++ b/vendor/tracing-subscriber/src/registry/mod.rs
@@ -55,8 +55,7 @@
//! require the root subscriber to be a registry.
//!
//! [`Layer`]: crate::layer::Layer
-//! [`Subscriber`]:
-//! https://docs.rs/tracing-core/latest/tracing_core/subscriber/trait.Subscriber.html
+//! [`Subscriber`]: tracing_core::Subscriber
//! [ctx]: crate::layer::Context
//! [lookup]: crate::layer::Context::span()
use tracing_core::{field::FieldSet, span::Id, Metadata};
@@ -87,9 +86,9 @@ feature! {
/// implement this trait; if they do, any [`Layer`]s wrapping them can look up
/// metadata via the [`Context`] type's [`span()`] method.
///
-/// [`Layer`]: ../layer/trait.Layer.html
-/// [`Context`]: ../layer/struct.Context.html
-/// [`span()`]: ../layer/struct.Context.html#method.span
+/// [`Layer`]: super::layer::Layer
+/// [`Context`]: super::layer::Context
+/// [`span()`]: super::layer::Context::span
pub trait LookupSpan<'a> {
/// The type of span data stored in this registry.
type Data: SpanData<'a>;
@@ -104,7 +103,6 @@ pub trait LookupSpan<'a> {
/// capable of performing more sophisiticated queries.
/// </pre>
///
- /// [`SpanData`]: trait.SpanData.html
fn span_data(&'a self, id: &Id) -> Option<Self::Data>;
/// Returns a [`SpanRef`] for the span with the given `Id`, if it exists.
@@ -116,9 +114,7 @@ pub trait LookupSpan<'a> {
/// rather than the [`span_data`] method; while _implementors_ of this trait
/// should only implement `span_data`.
///
- /// [`SpanRef`]: struct.SpanRef.html
- /// [`SpanData`]: trait.SpanData.html
- /// [`span_data`]: #method.span_data
+ /// [`span_data`]: LookupSpan::span_data()
fn span(&'a self, id: &Id) -> Option<SpanRef<'_, Self>>
where
Self: Sized,
@@ -208,8 +204,8 @@ pub trait SpanData<'a> {
/// provides additional methods for querying the registry based on values from
/// the span.
///
-/// [span data]: trait.SpanData.html
-/// [registry]: trait.LookupSpan.html
+/// [span data]: SpanData
+/// [registry]: LookupSpan
#[derive(Debug)]
pub struct SpanRef<'a, R: LookupSpan<'a>> {
registry: &'a R,
@@ -360,7 +356,7 @@ where
/// Returns a list of [fields] defined by the span.
///
- /// [fields]: https://docs.rs/tracing-core/latest/tracing_core/field/index.html
+ /// [fields]: tracing_core::field
pub fn fields(&self) -> &FieldSet {
self.data.metadata().fields()
}
diff --git a/vendor/tracing-subscriber-0.3.3/src/registry/sharded.rs b/vendor/tracing-subscriber/src/registry/sharded.rs
index a6311cb71..797899767 100644
--- a/vendor/tracing-subscriber-0.3.3/src/registry/sharded.rs
+++ b/vendor/tracing-subscriber/src/registry/sharded.rs
@@ -75,16 +75,16 @@ use tracing_core::{
/// the distributed tracing system. These IDs can be associated with
/// `tracing` spans using [fields] and/or [stored span data].
///
-/// [span IDs]: https://docs.rs/tracing-core/latest/tracing_core/span/struct.Id.html
-/// [slab]: https://docs.rs/crate/sharded-slab/
+/// [span IDs]: tracing_core::span::Id
+/// [slab]: sharded_slab
/// [`Layer`]: crate::Layer
/// [added]: crate::layer::Layer#composing-layers
/// [extensions]: super::Extensions
/// [closed]: https://docs.rs/tracing/latest/tracing/span/index.html#closing-spans
-/// [considered closed]: https://docs.rs/tracing-core/latest/tracing_core/subscriber/trait.Subscriber.html#method.try_close
+/// [considered closed]: tracing_core::subscriber::Subscriber::try_close()
/// [`Span`]: https://docs.rs/tracing/latest/tracing/span/struct.Span.html
/// [ot]: https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/trace/api.md#spancontext
-/// [fields]: https://docs.rs/tracing-core/latest/tracing-core/field/index.html
+/// [fields]: tracing_core::field
/// [stored span data]: crate::registry::SpanData::extensions_mut
#[cfg(feature = "registry")]
#[cfg_attr(docsrs, doc(cfg(all(feature = "registry", feature = "std"))))]
@@ -102,9 +102,8 @@ pub struct Registry {
/// [`Layer`s], such as formatted fields, metrics, or distributed traces should
/// be stored in the [extensions] typemap.
///
-/// [`Registry`]: struct.Registry.html
-/// [`Layer`s]: ../layer/trait.Layer.html
-/// [extensions]: struct.Extensions.html
+/// [`Layer`s]: crate::layer::Layer
+/// [extensions]: Extensions
#[cfg(feature = "registry")]
#[cfg_attr(docsrs, doc(cfg(all(feature = "registry", feature = "std"))))]
#[derive(Debug)]
@@ -115,10 +114,11 @@ pub struct Data<'a> {
/// Stored data associated with a span.
///
-/// This type is pooled using `sharded_slab::Pool`; when a span is dropped, the
-/// `DataInner` entry at that span's slab index is cleared in place and reused
-/// by a future span. Thus, the `Default` and `sharded_slab::Clear`
-/// implementations for this type are load-bearing.
+/// This type is pooled using [`sharded_slab::Pool`]; when a span is
+/// dropped, the `DataInner` entry at that span's slab index is cleared
+/// in place and reused by a future span. Thus, the `Default` and
+/// [`sharded_slab::Clear`] implementations for this type are
+/// load-bearing.
#[derive(Debug)]
struct DataInner {
filter_map: FilterMap,
@@ -173,7 +173,6 @@ fn id_to_idx(id: &Id) -> usize {
/// greater than 0, `CloseGuard` decrements the counter by one and
/// _does not_ remove the span from the [`Registry`].
///
-/// [`Registry`]: ./struct.Registry.html
pub(crate) struct CloseGuard<'a> {
id: Id,
registry: &'a Registry,
@@ -189,7 +188,6 @@ impl Registry {
/// processed an `on_close` notification via the `CLOSE_COUNT` thread-local.
/// For additional details, see [`CloseGuard`].
///
- /// [`CloseGuard`]: ./struct.CloseGuard.html
pub(crate) fn start_close(&self, id: Id) -> CloseGuard<'_> {
CLOSE_COUNT.with(|count| {
let c = count.get();
@@ -216,7 +214,6 @@ thread_local! {
/// track how many layers have processed the close.
/// For additional details, see [`CloseGuard`].
///
- /// [`CloseGuard`]: ./struct.CloseGuard.html
static CLOSE_COUNT: Cell<usize> = Cell::new(0);
}
@@ -278,6 +275,13 @@ impl Subscriber for Registry {
fn record_follows_from(&self, _span: &span::Id, _follows: &span::Id) {}
+ fn event_enabled(&self, _event: &Event<'_>) -> bool {
+ if self.has_per_layer_filters() {
+ return FilterState::event_enabled();
+ }
+ true
+ }
+
/// This is intentionally not implemented, as recording events
/// is the responsibility of layers atop of this registry.
fn event(&self, _: &Event<'_>) {}
@@ -380,7 +384,7 @@ impl<'a> LookupSpan<'a> for Registry {
// === impl CloseGuard ===
impl<'a> CloseGuard<'a> {
- pub(crate) fn is_closing(&mut self) {
+ pub(crate) fn set_closing(&mut self) {
self.is_closing = true;
}
}
diff --git a/vendor/tracing-subscriber-0.3.3/src/registry/stack.rs b/vendor/tracing-subscriber/src/registry/stack.rs
index 4a3f7e59d..4a3f7e59d 100644
--- a/vendor/tracing-subscriber-0.3.3/src/registry/stack.rs
+++ b/vendor/tracing-subscriber/src/registry/stack.rs
diff --git a/vendor/tracing-subscriber/src/reload.rs b/vendor/tracing-subscriber/src/reload.rs
new file mode 100644
index 000000000..096f83d38
--- /dev/null
+++ b/vendor/tracing-subscriber/src/reload.rs
@@ -0,0 +1,384 @@
+//! Wrapper for a `Layer` to allow it to be dynamically reloaded.
+//!
+//! This module provides a [`Layer` type] implementing the [`Layer` trait] or [`Filter` trait]
+//! which wraps another type implementing the corresponding trait. This
+//! allows the wrapped type to be replaced with another
+//! instance of that type at runtime.
+//!
+//! This can be used in cases where a subset of `Layer` or `Filter` functionality
+//! should be dynamically reconfigured, such as when filtering directives may
+//! change at runtime. Note that this layer introduces a (relatively small)
+//! amount of overhead, and should thus only be used as needed.
+//!
+//! # Examples
+//!
+//! Reloading a [global filtering](crate::layer#global-filtering) layer:
+//!
+//! ```rust
+//! # use tracing::info;
+//! use tracing_subscriber::{filter, fmt, reload, prelude::*};
+//! let filter = filter::LevelFilter::WARN;
+//! let (filter, reload_handle) = reload::Layer::new(filter);
+//! tracing_subscriber::registry()
+//! .with(filter)
+//! .with(fmt::Layer::default())
+//! .init();
+//! #
+//! # // specifying the Registry type is required
+//! # let _: &reload::Handle<filter::LevelFilter, tracing_subscriber::Registry> = &reload_handle;
+//! #
+//! info!("This will be ignored");
+//! reload_handle.modify(|filter| *filter = filter::LevelFilter::INFO);
+//! info!("This will be logged");
+//! ```
+//!
+//! Reloading a [`Filtered`](crate::filter::Filtered) layer:
+//!
+//! ```rust
+//! # use tracing::info;
+//! use tracing_subscriber::{filter, fmt, reload, prelude::*};
+//! let filtered_layer = fmt::Layer::default().with_filter(filter::LevelFilter::WARN);
+//! let (filtered_layer, reload_handle) = reload::Layer::new(filtered_layer);
+//! #
+//! # // specifying the Registry type is required
+//! # let _: &reload::Handle<filter::Filtered<fmt::Layer<tracing_subscriber::Registry>,
+//! # filter::LevelFilter, tracing_subscriber::Registry>,tracing_subscriber::Registry>
+//! # = &reload_handle;
+//! #
+//! tracing_subscriber::registry()
+//! .with(filtered_layer)
+//! .init();
+//! info!("This will be ignored");
+//! reload_handle.modify(|layer| *layer.filter_mut() = filter::LevelFilter::INFO);
+//! info!("This will be logged");
+//! ```
+//!
+//! ## Note
+//!
+//! The [`Layer`] implementation is unable to implement downcasting functionality,
+//! so certain [`Layer`] will fail to downcast if wrapped in a `reload::Layer`.
+//!
+//! If you only want to be able to dynamically change the
+//! `Filter` on a layer, prefer wrapping that `Filter` in the `reload::Layer`.
+//!
+//! [`Filter` trait]: crate::layer::Filter
+//! [`Layer` type]: Layer
+//! [`Layer` trait]: super::layer::Layer
+use crate::layer;
+use crate::sync::RwLock;
+
+use core::any::TypeId;
+use std::{
+ error, fmt,
+ marker::PhantomData,
+ sync::{Arc, Weak},
+};
+use tracing_core::{
+ callsite, span,
+ subscriber::{Interest, Subscriber},
+ Dispatch, Event, LevelFilter, Metadata,
+};
+
+/// Wraps a `Layer` or `Filter`, allowing it to be reloaded dynamically at runtime.
+#[derive(Debug)]
+pub struct Layer<L, S> {
+ // TODO(eliza): this once used a `crossbeam_util::ShardedRwLock`. We may
+ // eventually wish to replace it with a sharded lock implementation on top
+ // of our internal `RwLock` wrapper type. If possible, we should profile
+ // this first to determine if it's necessary.
+ inner: Arc<RwLock<L>>,
+ _s: PhantomData<fn(S)>,
+}
+
+/// Allows reloading the state of an associated [`Layer`](crate::layer::Layer).
+#[derive(Debug)]
+pub struct Handle<L, S> {
+ inner: Weak<RwLock<L>>,
+ _s: PhantomData<fn(S)>,
+}
+
+/// Indicates that an error occurred when reloading a layer.
+#[derive(Debug)]
+pub struct Error {
+ kind: ErrorKind,
+}
+
+#[derive(Debug)]
+enum ErrorKind {
+ SubscriberGone,
+ Poisoned,
+}
+
+// ===== impl Layer =====
+
+impl<L, S> crate::Layer<S> for Layer<L, S>
+where
+ L: crate::Layer<S> + 'static,
+ S: Subscriber,
+{
+ fn on_register_dispatch(&self, subscriber: &Dispatch) {
+ try_lock!(self.inner.read()).on_register_dispatch(subscriber);
+ }
+
+ fn on_layer(&mut self, subscriber: &mut S) {
+ try_lock!(self.inner.write(), else return).on_layer(subscriber);
+ }
+
+ #[inline]
+ fn register_callsite(&self, metadata: &'static Metadata<'static>) -> Interest {
+ try_lock!(self.inner.read(), else return Interest::sometimes()).register_callsite(metadata)
+ }
+
+ #[inline]
+ fn enabled(&self, metadata: &Metadata<'_>, ctx: layer::Context<'_, S>) -> bool {
+ try_lock!(self.inner.read(), else return false).enabled(metadata, ctx)
+ }
+
+ #[inline]
+ fn on_new_span(&self, attrs: &span::Attributes<'_>, id: &span::Id, ctx: layer::Context<'_, S>) {
+ try_lock!(self.inner.read()).on_new_span(attrs, id, ctx)
+ }
+
+ #[inline]
+ fn on_record(&self, span: &span::Id, values: &span::Record<'_>, ctx: layer::Context<'_, S>) {
+ try_lock!(self.inner.read()).on_record(span, values, ctx)
+ }
+
+ #[inline]
+ fn on_follows_from(&self, span: &span::Id, follows: &span::Id, ctx: layer::Context<'_, S>) {
+ try_lock!(self.inner.read()).on_follows_from(span, follows, ctx)
+ }
+
+ #[inline]
+ fn event_enabled(&self, event: &Event<'_>, ctx: layer::Context<'_, S>) -> bool {
+ try_lock!(self.inner.read(), else return false).event_enabled(event, ctx)
+ }
+
+ #[inline]
+ fn on_event(&self, event: &Event<'_>, ctx: layer::Context<'_, S>) {
+ try_lock!(self.inner.read()).on_event(event, ctx)
+ }
+
+ #[inline]
+ fn on_enter(&self, id: &span::Id, ctx: layer::Context<'_, S>) {
+ try_lock!(self.inner.read()).on_enter(id, ctx)
+ }
+
+ #[inline]
+ fn on_exit(&self, id: &span::Id, ctx: layer::Context<'_, S>) {
+ try_lock!(self.inner.read()).on_exit(id, ctx)
+ }
+
+ #[inline]
+ fn on_close(&self, id: span::Id, ctx: layer::Context<'_, S>) {
+ try_lock!(self.inner.read()).on_close(id, ctx)
+ }
+
+ #[inline]
+ fn on_id_change(&self, old: &span::Id, new: &span::Id, ctx: layer::Context<'_, S>) {
+ try_lock!(self.inner.read()).on_id_change(old, new, ctx)
+ }
+
+ #[inline]
+ fn max_level_hint(&self) -> Option<LevelFilter> {
+ try_lock!(self.inner.read(), else return None).max_level_hint()
+ }
+
+ #[doc(hidden)]
+ unsafe fn downcast_raw(&self, id: TypeId) -> Option<*const ()> {
+ // Safety: it is generally unsafe to downcast through a reload, because
+ // the pointer can be invalidated after the lock is dropped.
+ // `NoneLayerMarker` is a special case because it
+ // is never dereferenced.
+ //
+ // Additionally, even if the marker type *is* dereferenced (which it
+ // never will be), the pointer should be valid even if the subscriber
+ // is reloaded, because all `NoneLayerMarker` pointers that we return
+ // actually point to the global static singleton `NoneLayerMarker`,
+ // rather than to a field inside the lock.
+ if id == TypeId::of::<layer::NoneLayerMarker>() {
+ return try_lock!(self.inner.read(), else return None).downcast_raw(id);
+ }
+
+ None
+ }
+}
+
+// ===== impl Filter =====
+
+#[cfg(all(feature = "registry", feature = "std"))]
+#[cfg_attr(docsrs, doc(cfg(all(feature = "registry", feature = "std"))))]
+impl<S, L> crate::layer::Filter<S> for Layer<L, S>
+where
+ L: crate::layer::Filter<S> + 'static,
+ S: Subscriber,
+{
+ #[inline]
+ fn callsite_enabled(&self, metadata: &'static Metadata<'static>) -> Interest {
+ try_lock!(self.inner.read(), else return Interest::sometimes()).callsite_enabled(metadata)
+ }
+
+ #[inline]
+ fn enabled(&self, metadata: &Metadata<'_>, ctx: &layer::Context<'_, S>) -> bool {
+ try_lock!(self.inner.read(), else return false).enabled(metadata, ctx)
+ }
+
+ #[inline]
+ fn on_new_span(&self, attrs: &span::Attributes<'_>, id: &span::Id, ctx: layer::Context<'_, S>) {
+ try_lock!(self.inner.read()).on_new_span(attrs, id, ctx)
+ }
+
+ #[inline]
+ fn on_record(&self, span: &span::Id, values: &span::Record<'_>, ctx: layer::Context<'_, S>) {
+ try_lock!(self.inner.read()).on_record(span, values, ctx)
+ }
+
+ #[inline]
+ fn on_enter(&self, id: &span::Id, ctx: layer::Context<'_, S>) {
+ try_lock!(self.inner.read()).on_enter(id, ctx)
+ }
+
+ #[inline]
+ fn on_exit(&self, id: &span::Id, ctx: layer::Context<'_, S>) {
+ try_lock!(self.inner.read()).on_exit(id, ctx)
+ }
+
+ #[inline]
+ fn on_close(&self, id: span::Id, ctx: layer::Context<'_, S>) {
+ try_lock!(self.inner.read()).on_close(id, ctx)
+ }
+
+ #[inline]
+ fn max_level_hint(&self) -> Option<LevelFilter> {
+ try_lock!(self.inner.read(), else return None).max_level_hint()
+ }
+}
+
+impl<L, S> Layer<L, S> {
+ /// Wraps the given [`Layer`] or [`Filter`], returning a `reload::Layer`
+ /// and a `Handle` that allows the inner value to be modified at runtime.
+ ///
+ /// [`Layer`]: crate::layer::Layer
+ /// [`Filter`]: crate::layer::Filter
+ pub fn new(inner: L) -> (Self, Handle<L, S>) {
+ let this = Self {
+ inner: Arc::new(RwLock::new(inner)),
+ _s: PhantomData,
+ };
+ let handle = this.handle();
+ (this, handle)
+ }
+
+ /// Returns a `Handle` that can be used to reload the wrapped [`Layer`] or [`Filter`].
+ ///
+ /// [`Layer`]: crate::layer::Layer
+ /// [`Filter`]: crate::filter::Filter
+ pub fn handle(&self) -> Handle<L, S> {
+ Handle {
+ inner: Arc::downgrade(&self.inner),
+ _s: PhantomData,
+ }
+ }
+}
+
+// ===== impl Handle =====
+
+impl<L, S> Handle<L, S> {
+ /// Replace the current [`Layer`] or [`Filter`] with the provided `new_value`.
+ ///
+ /// [`Handle::reload`] cannot be used with the [`Filtered`] layer; use
+ /// [`Handle::modify`] instead (see [this issue] for additional details).
+ ///
+ /// However, if the _only_ the [`Filter`] needs to be modified, use
+ /// `reload::Layer` to wrap the `Filter` directly.
+ ///
+ /// [`Layer`]: crate::layer::Layer
+ /// [`Filter`]: crate::layer::Filter
+ /// [`Filtered`]: crate::filter::Filtered
+ ///
+ /// [this issue]: https://github.com/tokio-rs/tracing/issues/1629
+ pub fn reload(&self, new_value: impl Into<L>) -> Result<(), Error> {
+ self.modify(|layer| {
+ *layer = new_value.into();
+ })
+ }
+
+ /// Invokes a closure with a mutable reference to the current layer or filter,
+ /// allowing it to be modified in place.
+ pub fn modify(&self, f: impl FnOnce(&mut L)) -> Result<(), Error> {
+ let inner = self.inner.upgrade().ok_or(Error {
+ kind: ErrorKind::SubscriberGone,
+ })?;
+
+ let mut lock = try_lock!(inner.write(), else return Err(Error::poisoned()));
+ f(&mut *lock);
+ // Release the lock before rebuilding the interest cache, as that
+ // function will lock the new layer.
+ drop(lock);
+
+ callsite::rebuild_interest_cache();
+ Ok(())
+ }
+
+ /// Returns a clone of the layer or filter's current value if it still exists.
+ /// Otherwise, if the subscriber has been dropped, returns `None`.
+ pub fn clone_current(&self) -> Option<L>
+ where
+ L: Clone,
+ {
+ self.with_current(L::clone).ok()
+ }
+
+ /// Invokes a closure with a borrowed reference to the current layer or filter,
+ /// returning the result (or an error if the subscriber no longer exists).
+ pub fn with_current<T>(&self, f: impl FnOnce(&L) -> T) -> Result<T, Error> {
+ let inner = self.inner.upgrade().ok_or(Error {
+ kind: ErrorKind::SubscriberGone,
+ })?;
+ let inner = try_lock!(inner.read(), else return Err(Error::poisoned()));
+ Ok(f(&*inner))
+ }
+}
+
+impl<L, S> Clone for Handle<L, S> {
+ fn clone(&self) -> Self {
+ Handle {
+ inner: self.inner.clone(),
+ _s: PhantomData,
+ }
+ }
+}
+
+// ===== impl Error =====
+
+impl Error {
+ fn poisoned() -> Self {
+ Self {
+ kind: ErrorKind::Poisoned,
+ }
+ }
+
+ /// Returns `true` if this error occurred because the layer was poisoned by
+ /// a panic on another thread.
+ pub fn is_poisoned(&self) -> bool {
+ matches!(self.kind, ErrorKind::Poisoned)
+ }
+
+ /// Returns `true` if this error occurred because the `Subscriber`
+ /// containing the reloadable layer was dropped.
+ pub fn is_dropped(&self) -> bool {
+ matches!(self.kind, ErrorKind::SubscriberGone)
+ }
+}
+
+impl fmt::Display for Error {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ let msg = match self.kind {
+ ErrorKind::SubscriberGone => "subscriber no longer exists",
+ ErrorKind::Poisoned => "lock poisoned",
+ };
+ f.pad(msg)
+ }
+}
+
+impl error::Error for Error {}
diff --git a/vendor/tracing-subscriber-0.3.3/src/sync.rs b/vendor/tracing-subscriber/src/sync.rs
index ec42b834a..ec42b834a 100644
--- a/vendor/tracing-subscriber-0.3.3/src/sync.rs
+++ b/vendor/tracing-subscriber/src/sync.rs
diff --git a/vendor/tracing-subscriber-0.3.3/src/util.rs b/vendor/tracing-subscriber/src/util.rs
index 1c98aa4d2..1c98aa4d2 100644
--- a/vendor/tracing-subscriber-0.3.3/src/util.rs
+++ b/vendor/tracing-subscriber/src/util.rs
diff --git a/vendor/tracing-subscriber-0.3.3/tests/cached_layer_filters_dont_break_other_layers.rs b/vendor/tracing-subscriber/tests/cached_layer_filters_dont_break_other_layers.rs
index 00e98a994..00e98a994 100644
--- a/vendor/tracing-subscriber-0.3.3/tests/cached_layer_filters_dont_break_other_layers.rs
+++ b/vendor/tracing-subscriber/tests/cached_layer_filters_dont_break_other_layers.rs
diff --git a/vendor/tracing-subscriber-0.3.3/tests/duplicate_spans.rs b/vendor/tracing-subscriber/tests/duplicate_spans.rs
index c4a736f74..5d4dc6a85 100644
--- a/vendor/tracing-subscriber-0.3.3/tests/duplicate_spans.rs
+++ b/vendor/tracing-subscriber/tests/duplicate_spans.rs
@@ -1,5 +1,4 @@
#![cfg(all(feature = "env-filter", feature = "fmt"))]
-mod support;
use tracing::{self, subscriber::with_default, Span};
use tracing_subscriber::{filter::EnvFilter, FmtSubscriber};
diff --git a/vendor/tracing-subscriber/tests/env_filter/main.rs b/vendor/tracing-subscriber/tests/env_filter/main.rs
new file mode 100644
index 000000000..3c3d4868b
--- /dev/null
+++ b/vendor/tracing-subscriber/tests/env_filter/main.rs
@@ -0,0 +1,547 @@
+#![cfg(feature = "env-filter")]
+
+#[path = "../support.rs"]
+mod support;
+use self::support::*;
+
+mod per_layer;
+
+use tracing::{self, subscriber::with_default, Level};
+use tracing_subscriber::{
+ filter::{EnvFilter, LevelFilter},
+ prelude::*,
+};
+
+#[test]
+fn level_filter_event() {
+ let filter: EnvFilter = "info".parse().expect("filter should parse");
+ let (subscriber, finished) = subscriber::mock()
+ .event(event::mock().at_level(Level::INFO))
+ .event(event::mock().at_level(Level::WARN))
+ .event(event::mock().at_level(Level::ERROR))
+ .done()
+ .run_with_handle();
+ let subscriber = subscriber.with(filter);
+
+ with_default(subscriber, || {
+ tracing::trace!("this should be disabled");
+ tracing::info!("this shouldn't be");
+ tracing::debug!(target: "foo", "this should also be disabled");
+ tracing::warn!(target: "foo", "this should be enabled");
+ tracing::error!("this should be enabled too");
+ });
+
+ finished.assert_finished();
+}
+
+#[test]
+fn same_name_spans() {
+ let filter: EnvFilter = "[foo{bar}]=trace,[foo{baz}]=trace"
+ .parse()
+ .expect("filter should parse");
+ let (subscriber, finished) = subscriber::mock()
+ .new_span(
+ span::mock()
+ .named("foo")
+ .at_level(Level::TRACE)
+ .with_field(field::mock("bar")),
+ )
+ .new_span(
+ span::mock()
+ .named("foo")
+ .at_level(Level::TRACE)
+ .with_field(field::mock("baz")),
+ )
+ .done()
+ .run_with_handle();
+ let subscriber = subscriber.with(filter);
+ with_default(subscriber, || {
+ tracing::trace_span!("foo", bar = 1);
+ tracing::trace_span!("foo", baz = 1);
+ });
+
+ finished.assert_finished();
+}
+
+#[test]
+fn level_filter_event_with_target() {
+ let filter: EnvFilter = "info,stuff=debug".parse().expect("filter should parse");
+ let (subscriber, finished) = subscriber::mock()
+ .event(event::mock().at_level(Level::INFO))
+ .event(event::mock().at_level(Level::DEBUG).with_target("stuff"))
+ .event(event::mock().at_level(Level::WARN).with_target("stuff"))
+ .event(event::mock().at_level(Level::ERROR))
+ .event(event::mock().at_level(Level::ERROR).with_target("stuff"))
+ .done()
+ .run_with_handle();
+ let subscriber = subscriber.with(filter);
+
+ with_default(subscriber, || {
+ tracing::trace!("this should be disabled");
+ tracing::info!("this shouldn't be");
+ tracing::debug!(target: "stuff", "this should be enabled");
+ tracing::debug!("but this shouldn't");
+ tracing::trace!(target: "stuff", "and neither should this");
+ tracing::warn!(target: "stuff", "this should be enabled");
+ tracing::error!("this should be enabled too");
+ tracing::error!(target: "stuff", "this should be enabled also");
+ });
+
+ finished.assert_finished();
+}
+
+#[test]
+fn level_filter_event_with_target_and_span_global() {
+ let filter: EnvFilter = "info,stuff[cool_span]=debug"
+ .parse()
+ .expect("filter should parse");
+
+ let cool_span = span::named("cool_span");
+ let uncool_span = span::named("uncool_span");
+ let (subscriber, handle) = subscriber::mock()
+ .enter(cool_span.clone())
+ .event(
+ event::mock()
+ .at_level(Level::DEBUG)
+ .in_scope(vec![cool_span.clone()]),
+ )
+ .exit(cool_span)
+ .enter(uncool_span.clone())
+ .exit(uncool_span)
+ .done()
+ .run_with_handle();
+
+ let subscriber = subscriber.with(filter);
+
+ with_default(subscriber, || {
+ {
+ let _span = tracing::info_span!(target: "stuff", "cool_span").entered();
+ tracing::debug!("this should be enabled");
+ }
+
+ tracing::debug!("should also be disabled");
+
+ {
+ let _span = tracing::info_span!("uncool_span").entered();
+ tracing::debug!("this should be disabled");
+ }
+ });
+
+ handle.assert_finished();
+}
+
+#[test]
+fn not_order_dependent() {
+ // this test reproduces tokio-rs/tracing#623
+
+ let filter: EnvFilter = "stuff=debug,info".parse().expect("filter should parse");
+ let (subscriber, finished) = subscriber::mock()
+ .event(event::mock().at_level(Level::INFO))
+ .event(event::mock().at_level(Level::DEBUG).with_target("stuff"))
+ .event(event::mock().at_level(Level::WARN).with_target("stuff"))
+ .event(event::mock().at_level(Level::ERROR))
+ .event(event::mock().at_level(Level::ERROR).with_target("stuff"))
+ .done()
+ .run_with_handle();
+ let subscriber = subscriber.with(filter);
+
+ with_default(subscriber, || {
+ tracing::trace!("this should be disabled");
+ tracing::info!("this shouldn't be");
+ tracing::debug!(target: "stuff", "this should be enabled");
+ tracing::debug!("but this shouldn't");
+ tracing::trace!(target: "stuff", "and neither should this");
+ tracing::warn!(target: "stuff", "this should be enabled");
+ tracing::error!("this should be enabled too");
+ tracing::error!(target: "stuff", "this should be enabled also");
+ });
+
+ finished.assert_finished();
+}
+
+#[test]
+fn add_directive_enables_event() {
+ // this test reproduces tokio-rs/tracing#591
+
+ // by default, use info level
+ let mut filter = EnvFilter::new(LevelFilter::INFO.to_string());
+
+ // overwrite with a more specific directive
+ filter = filter.add_directive("hello=trace".parse().expect("directive should parse"));
+
+ let (subscriber, finished) = subscriber::mock()
+ .event(event::mock().at_level(Level::INFO).with_target("hello"))
+ .event(event::mock().at_level(Level::TRACE).with_target("hello"))
+ .done()
+ .run_with_handle();
+ let subscriber = subscriber.with(filter);
+
+ with_default(subscriber, || {
+ tracing::info!(target: "hello", "hello info");
+ tracing::trace!(target: "hello", "hello trace");
+ });
+
+ finished.assert_finished();
+}
+
+#[test]
+fn span_name_filter_is_dynamic() {
+ let filter: EnvFilter = "info,[cool_span]=debug"
+ .parse()
+ .expect("filter should parse");
+ let (subscriber, finished) = subscriber::mock()
+ .event(event::mock().at_level(Level::INFO))
+ .enter(span::named("cool_span"))
+ .event(event::mock().at_level(Level::DEBUG))
+ .enter(span::named("uncool_span"))
+ .event(event::mock().at_level(Level::WARN))
+ .event(event::mock().at_level(Level::DEBUG))
+ .exit(span::named("uncool_span"))
+ .exit(span::named("cool_span"))
+ .enter(span::named("uncool_span"))
+ .event(event::mock().at_level(Level::WARN))
+ .event(event::mock().at_level(Level::ERROR))
+ .exit(span::named("uncool_span"))
+ .done()
+ .run_with_handle();
+ let subscriber = subscriber.with(filter);
+
+ with_default(subscriber, || {
+ tracing::trace!("this should be disabled");
+ tracing::info!("this shouldn't be");
+ let cool_span = tracing::info_span!("cool_span");
+ let uncool_span = tracing::info_span!("uncool_span");
+
+ {
+ let _enter = cool_span.enter();
+ tracing::debug!("i'm a cool event");
+ tracing::trace!("i'm cool, but not cool enough");
+ let _enter2 = uncool_span.enter();
+ tracing::warn!("warning: extremely cool!");
+ tracing::debug!("i'm still cool");
+ }
+
+ let _enter = uncool_span.enter();
+ tracing::warn!("warning: not that cool");
+ tracing::trace!("im not cool enough");
+ tracing::error!("uncool error");
+ });
+
+ finished.assert_finished();
+}
+
+#[test]
+fn method_name_resolution() {
+ #[allow(unused_imports)]
+ use tracing_subscriber::layer::{Filter, Layer};
+
+ let filter = EnvFilter::new("hello_world=info");
+ filter.max_level_hint();
+}
+
+// contains the same tests as the first half of this file
+// but using EnvFilter as a `Filter`, not as a `Layer`
+mod per_layer_filter {
+ use super::*;
+
+ #[test]
+ fn level_filter_event() {
+ let filter: EnvFilter = "info".parse().expect("filter should parse");
+ let (layer, handle) = layer::mock()
+ .event(event::mock().at_level(Level::INFO))
+ .event(event::mock().at_level(Level::WARN))
+ .event(event::mock().at_level(Level::ERROR))
+ .done()
+ .run_with_handle();
+
+ let _subscriber = tracing_subscriber::registry()
+ .with(layer.with_filter(filter))
+ .set_default();
+
+ tracing::trace!("this should be disabled");
+ tracing::info!("this shouldn't be");
+ tracing::debug!(target: "foo", "this should also be disabled");
+ tracing::warn!(target: "foo", "this should be enabled");
+ tracing::error!("this should be enabled too");
+
+ handle.assert_finished();
+ }
+
+ #[test]
+ fn same_name_spans() {
+ let filter: EnvFilter = "[foo{bar}]=trace,[foo{baz}]=trace"
+ .parse()
+ .expect("filter should parse");
+ let (layer, handle) = layer::mock()
+ .new_span(
+ span::mock()
+ .named("foo")
+ .at_level(Level::TRACE)
+ .with_field(field::mock("bar")),
+ )
+ .new_span(
+ span::mock()
+ .named("foo")
+ .at_level(Level::TRACE)
+ .with_field(field::mock("baz")),
+ )
+ .done()
+ .run_with_handle();
+
+ let _subscriber = tracing_subscriber::registry()
+ .with(layer.with_filter(filter))
+ .set_default();
+
+ tracing::trace_span!("foo", bar = 1);
+ tracing::trace_span!("foo", baz = 1);
+
+ handle.assert_finished();
+ }
+
+ #[test]
+ fn level_filter_event_with_target() {
+ let filter: EnvFilter = "info,stuff=debug".parse().expect("filter should parse");
+ let (layer, handle) = layer::mock()
+ .event(event::mock().at_level(Level::INFO))
+ .event(event::mock().at_level(Level::DEBUG).with_target("stuff"))
+ .event(event::mock().at_level(Level::WARN).with_target("stuff"))
+ .event(event::mock().at_level(Level::ERROR))
+ .event(event::mock().at_level(Level::ERROR).with_target("stuff"))
+ .done()
+ .run_with_handle();
+
+ let _subscriber = tracing_subscriber::registry()
+ .with(layer.with_filter(filter))
+ .set_default();
+
+ tracing::trace!("this should be disabled");
+ tracing::info!("this shouldn't be");
+ tracing::debug!(target: "stuff", "this should be enabled");
+ tracing::debug!("but this shouldn't");
+ tracing::trace!(target: "stuff", "and neither should this");
+ tracing::warn!(target: "stuff", "this should be enabled");
+ tracing::error!("this should be enabled too");
+ tracing::error!(target: "stuff", "this should be enabled also");
+
+ handle.assert_finished();
+ }
+
+ #[test]
+ fn level_filter_event_with_target_and_span() {
+ let filter: EnvFilter = "stuff[cool_span]=debug"
+ .parse()
+ .expect("filter should parse");
+
+ let cool_span = span::named("cool_span");
+ let (layer, handle) = layer::mock()
+ .enter(cool_span.clone())
+ .event(
+ event::mock()
+ .at_level(Level::DEBUG)
+ .in_scope(vec![cool_span.clone()]),
+ )
+ .exit(cool_span)
+ .done()
+ .run_with_handle();
+
+ let _subscriber = tracing_subscriber::registry()
+ .with(layer.with_filter(filter))
+ .set_default();
+
+ {
+ let _span = tracing::info_span!(target: "stuff", "cool_span").entered();
+ tracing::debug!("this should be enabled");
+ }
+
+ tracing::debug!("should also be disabled");
+
+ {
+ let _span = tracing::info_span!("uncool_span").entered();
+ tracing::debug!("this should be disabled");
+ }
+
+ handle.assert_finished();
+ }
+
+ #[test]
+ fn not_order_dependent() {
+ // this test reproduces tokio-rs/tracing#623
+
+ let filter: EnvFilter = "stuff=debug,info".parse().expect("filter should parse");
+ let (layer, finished) = layer::mock()
+ .event(event::mock().at_level(Level::INFO))
+ .event(event::mock().at_level(Level::DEBUG).with_target("stuff"))
+ .event(event::mock().at_level(Level::WARN).with_target("stuff"))
+ .event(event::mock().at_level(Level::ERROR))
+ .event(event::mock().at_level(Level::ERROR).with_target("stuff"))
+ .done()
+ .run_with_handle();
+
+ let _subscriber = tracing_subscriber::registry()
+ .with(layer.with_filter(filter))
+ .set_default();
+
+ tracing::trace!("this should be disabled");
+ tracing::info!("this shouldn't be");
+ tracing::debug!(target: "stuff", "this should be enabled");
+ tracing::debug!("but this shouldn't");
+ tracing::trace!(target: "stuff", "and neither should this");
+ tracing::warn!(target: "stuff", "this should be enabled");
+ tracing::error!("this should be enabled too");
+ tracing::error!(target: "stuff", "this should be enabled also");
+
+ finished.assert_finished();
+ }
+
+ #[test]
+ fn add_directive_enables_event() {
+ // this test reproduces tokio-rs/tracing#591
+
+ // by default, use info level
+ let mut filter = EnvFilter::new(LevelFilter::INFO.to_string());
+
+ // overwrite with a more specific directive
+ filter = filter.add_directive("hello=trace".parse().expect("directive should parse"));
+
+ let (layer, finished) = layer::mock()
+ .event(event::mock().at_level(Level::INFO).with_target("hello"))
+ .event(event::mock().at_level(Level::TRACE).with_target("hello"))
+ .done()
+ .run_with_handle();
+
+ let _subscriber = tracing_subscriber::registry()
+ .with(layer.with_filter(filter))
+ .set_default();
+
+ tracing::info!(target: "hello", "hello info");
+ tracing::trace!(target: "hello", "hello trace");
+
+ finished.assert_finished();
+ }
+
+ #[test]
+ fn span_name_filter_is_dynamic() {
+ let filter: EnvFilter = "info,[cool_span]=debug"
+ .parse()
+ .expect("filter should parse");
+ let cool_span = span::named("cool_span");
+ let uncool_span = span::named("uncool_span");
+ let (layer, finished) = layer::mock()
+ .event(event::mock().at_level(Level::INFO))
+ .enter(cool_span.clone())
+ .event(
+ event::mock()
+ .at_level(Level::DEBUG)
+ .in_scope(vec![cool_span.clone()]),
+ )
+ .enter(uncool_span.clone())
+ .event(
+ event::mock()
+ .at_level(Level::WARN)
+ .in_scope(vec![uncool_span.clone()]),
+ )
+ .event(
+ event::mock()
+ .at_level(Level::DEBUG)
+ .in_scope(vec![uncool_span.clone()]),
+ )
+ .exit(uncool_span.clone())
+ .exit(cool_span)
+ .enter(uncool_span.clone())
+ .event(
+ event::mock()
+ .at_level(Level::WARN)
+ .in_scope(vec![uncool_span.clone()]),
+ )
+ .event(
+ event::mock()
+ .at_level(Level::ERROR)
+ .in_scope(vec![uncool_span.clone()]),
+ )
+ .exit(uncool_span)
+ .done()
+ .run_with_handle();
+
+ let _subscriber = tracing_subscriber::registry()
+ .with(layer.with_filter(filter))
+ .set_default();
+
+ tracing::trace!("this should be disabled");
+ tracing::info!("this shouldn't be");
+ let cool_span = tracing::info_span!("cool_span");
+ let uncool_span = tracing::info_span!("uncool_span");
+
+ {
+ let _enter = cool_span.enter();
+ tracing::debug!("i'm a cool event");
+ tracing::trace!("i'm cool, but not cool enough");
+ let _enter2 = uncool_span.enter();
+ tracing::warn!("warning: extremely cool!");
+ tracing::debug!("i'm still cool");
+ }
+
+ {
+ let _enter = uncool_span.enter();
+ tracing::warn!("warning: not that cool");
+ tracing::trace!("im not cool enough");
+ tracing::error!("uncool error");
+ }
+
+ finished.assert_finished();
+ }
+
+ #[test]
+ fn multiple_dynamic_filters() {
+ // Test that multiple dynamic (span) filters only apply to the layers
+ // they're attached to.
+ let (layer1, handle1) = {
+ let span = span::named("span1");
+ let filter: EnvFilter = "[span1]=debug".parse().expect("filter 1 should parse");
+ let (layer, handle) = layer::named("layer1")
+ .enter(span.clone())
+ .event(
+ event::mock()
+ .at_level(Level::DEBUG)
+ .in_scope(vec![span.clone()]),
+ )
+ .exit(span)
+ .done()
+ .run_with_handle();
+ (layer.with_filter(filter), handle)
+ };
+
+ let (layer2, handle2) = {
+ let span = span::named("span2");
+ let filter: EnvFilter = "[span2]=info".parse().expect("filter 2 should parse");
+ let (layer, handle) = layer::named("layer2")
+ .enter(span.clone())
+ .event(
+ event::mock()
+ .at_level(Level::INFO)
+ .in_scope(vec![span.clone()]),
+ )
+ .exit(span)
+ .done()
+ .run_with_handle();
+ (layer.with_filter(filter), handle)
+ };
+
+ let _subscriber = tracing_subscriber::registry()
+ .with(layer1)
+ .with(layer2)
+ .set_default();
+
+ tracing::info_span!("span1").in_scope(|| {
+ tracing::debug!("hello from span 1");
+ tracing::trace!("not enabled");
+ });
+
+ tracing::info_span!("span2").in_scope(|| {
+ tracing::info!("hello from span 2");
+ tracing::debug!("not enabled");
+ });
+
+ handle1.assert_finished();
+ handle2.assert_finished();
+ }
+}
diff --git a/vendor/tracing-subscriber/tests/env_filter/per_layer.rs b/vendor/tracing-subscriber/tests/env_filter/per_layer.rs
new file mode 100644
index 000000000..8bf5698a4
--- /dev/null
+++ b/vendor/tracing-subscriber/tests/env_filter/per_layer.rs
@@ -0,0 +1,305 @@
+//! Tests for using `EnvFilter` as a per-layer filter (rather than a global
+//! `Layer` filter).
+#![cfg(feature = "registry")]
+use super::*;
+
+#[test]
+fn level_filter_event() {
+ let filter: EnvFilter = "info".parse().expect("filter should parse");
+ let (layer, handle) = layer::mock()
+ .event(event::mock().at_level(Level::INFO))
+ .event(event::mock().at_level(Level::WARN))
+ .event(event::mock().at_level(Level::ERROR))
+ .done()
+ .run_with_handle();
+
+ let _subscriber = tracing_subscriber::registry()
+ .with(layer.with_filter(filter))
+ .set_default();
+
+ tracing::trace!("this should be disabled");
+ tracing::info!("this shouldn't be");
+ tracing::debug!(target: "foo", "this should also be disabled");
+ tracing::warn!(target: "foo", "this should be enabled");
+ tracing::error!("this should be enabled too");
+
+ handle.assert_finished();
+}
+
+#[test]
+fn same_name_spans() {
+ let filter: EnvFilter = "[foo{bar}]=trace,[foo{baz}]=trace"
+ .parse()
+ .expect("filter should parse");
+ let (layer, handle) = layer::mock()
+ .new_span(
+ span::mock()
+ .named("foo")
+ .at_level(Level::TRACE)
+ .with_field(field::mock("bar")),
+ )
+ .new_span(
+ span::mock()
+ .named("foo")
+ .at_level(Level::TRACE)
+ .with_field(field::mock("baz")),
+ )
+ .done()
+ .run_with_handle();
+
+ let _subscriber = tracing_subscriber::registry()
+ .with(layer.with_filter(filter))
+ .set_default();
+
+ tracing::trace_span!("foo", bar = 1);
+ tracing::trace_span!("foo", baz = 1);
+
+ handle.assert_finished();
+}
+
+#[test]
+fn level_filter_event_with_target() {
+ let filter: EnvFilter = "info,stuff=debug".parse().expect("filter should parse");
+ let (layer, handle) = layer::mock()
+ .event(event::mock().at_level(Level::INFO))
+ .event(event::mock().at_level(Level::DEBUG).with_target("stuff"))
+ .event(event::mock().at_level(Level::WARN).with_target("stuff"))
+ .event(event::mock().at_level(Level::ERROR))
+ .event(event::mock().at_level(Level::ERROR).with_target("stuff"))
+ .done()
+ .run_with_handle();
+
+ let _subscriber = tracing_subscriber::registry()
+ .with(layer.with_filter(filter))
+ .set_default();
+
+ tracing::trace!("this should be disabled");
+ tracing::info!("this shouldn't be");
+ tracing::debug!(target: "stuff", "this should be enabled");
+ tracing::debug!("but this shouldn't");
+ tracing::trace!(target: "stuff", "and neither should this");
+ tracing::warn!(target: "stuff", "this should be enabled");
+ tracing::error!("this should be enabled too");
+ tracing::error!(target: "stuff", "this should be enabled also");
+
+ handle.assert_finished();
+}
+
+#[test]
+fn level_filter_event_with_target_and_span() {
+ let filter: EnvFilter = "stuff[cool_span]=debug"
+ .parse()
+ .expect("filter should parse");
+
+ let cool_span = span::named("cool_span");
+ let (layer, handle) = layer::mock()
+ .enter(cool_span.clone())
+ .event(
+ event::mock()
+ .at_level(Level::DEBUG)
+ .in_scope(vec![cool_span.clone()]),
+ )
+ .exit(cool_span)
+ .done()
+ .run_with_handle();
+
+ let _subscriber = tracing_subscriber::registry()
+ .with(layer.with_filter(filter))
+ .set_default();
+
+ {
+ let _span = tracing::info_span!(target: "stuff", "cool_span").entered();
+ tracing::debug!("this should be enabled");
+ }
+
+ tracing::debug!("should also be disabled");
+
+ {
+ let _span = tracing::info_span!("uncool_span").entered();
+ tracing::debug!("this should be disabled");
+ }
+
+ handle.assert_finished();
+}
+
+#[test]
+fn not_order_dependent() {
+ // this test reproduces tokio-rs/tracing#623
+
+ let filter: EnvFilter = "stuff=debug,info".parse().expect("filter should parse");
+ let (layer, finished) = layer::mock()
+ .event(event::mock().at_level(Level::INFO))
+ .event(event::mock().at_level(Level::DEBUG).with_target("stuff"))
+ .event(event::mock().at_level(Level::WARN).with_target("stuff"))
+ .event(event::mock().at_level(Level::ERROR))
+ .event(event::mock().at_level(Level::ERROR).with_target("stuff"))
+ .done()
+ .run_with_handle();
+
+ let _subscriber = tracing_subscriber::registry()
+ .with(layer.with_filter(filter))
+ .set_default();
+
+ tracing::trace!("this should be disabled");
+ tracing::info!("this shouldn't be");
+ tracing::debug!(target: "stuff", "this should be enabled");
+ tracing::debug!("but this shouldn't");
+ tracing::trace!(target: "stuff", "and neither should this");
+ tracing::warn!(target: "stuff", "this should be enabled");
+ tracing::error!("this should be enabled too");
+ tracing::error!(target: "stuff", "this should be enabled also");
+
+ finished.assert_finished();
+}
+
+#[test]
+fn add_directive_enables_event() {
+ // this test reproduces tokio-rs/tracing#591
+
+ // by default, use info level
+ let mut filter = EnvFilter::new(LevelFilter::INFO.to_string());
+
+ // overwrite with a more specific directive
+ filter = filter.add_directive("hello=trace".parse().expect("directive should parse"));
+
+ let (layer, finished) = layer::mock()
+ .event(event::mock().at_level(Level::INFO).with_target("hello"))
+ .event(event::mock().at_level(Level::TRACE).with_target("hello"))
+ .done()
+ .run_with_handle();
+
+ let _subscriber = tracing_subscriber::registry()
+ .with(layer.with_filter(filter))
+ .set_default();
+
+ tracing::info!(target: "hello", "hello info");
+ tracing::trace!(target: "hello", "hello trace");
+
+ finished.assert_finished();
+}
+
+#[test]
+fn span_name_filter_is_dynamic() {
+ let filter: EnvFilter = "info,[cool_span]=debug"
+ .parse()
+ .expect("filter should parse");
+ let cool_span = span::named("cool_span");
+ let uncool_span = span::named("uncool_span");
+ let (layer, finished) = layer::mock()
+ .event(event::mock().at_level(Level::INFO))
+ .enter(cool_span.clone())
+ .event(
+ event::mock()
+ .at_level(Level::DEBUG)
+ .in_scope(vec![cool_span.clone()]),
+ )
+ .enter(uncool_span.clone())
+ .event(
+ event::mock()
+ .at_level(Level::WARN)
+ .in_scope(vec![uncool_span.clone()]),
+ )
+ .event(
+ event::mock()
+ .at_level(Level::DEBUG)
+ .in_scope(vec![uncool_span.clone()]),
+ )
+ .exit(uncool_span.clone())
+ .exit(cool_span)
+ .enter(uncool_span.clone())
+ .event(
+ event::mock()
+ .at_level(Level::WARN)
+ .in_scope(vec![uncool_span.clone()]),
+ )
+ .event(
+ event::mock()
+ .at_level(Level::ERROR)
+ .in_scope(vec![uncool_span.clone()]),
+ )
+ .exit(uncool_span)
+ .done()
+ .run_with_handle();
+
+ let _subscriber = tracing_subscriber::registry()
+ .with(layer.with_filter(filter))
+ .set_default();
+
+ tracing::trace!("this should be disabled");
+ tracing::info!("this shouldn't be");
+ let cool_span = tracing::info_span!("cool_span");
+ let uncool_span = tracing::info_span!("uncool_span");
+
+ {
+ let _enter = cool_span.enter();
+ tracing::debug!("i'm a cool event");
+ tracing::trace!("i'm cool, but not cool enough");
+ let _enter2 = uncool_span.enter();
+ tracing::warn!("warning: extremely cool!");
+ tracing::debug!("i'm still cool");
+ }
+
+ {
+ let _enter = uncool_span.enter();
+ tracing::warn!("warning: not that cool");
+ tracing::trace!("im not cool enough");
+ tracing::error!("uncool error");
+ }
+
+ finished.assert_finished();
+}
+
+#[test]
+fn multiple_dynamic_filters() {
+ // Test that multiple dynamic (span) filters only apply to the layers
+ // they're attached to.
+ let (layer1, handle1) = {
+ let span = span::named("span1");
+ let filter: EnvFilter = "[span1]=debug".parse().expect("filter 1 should parse");
+ let (layer, handle) = layer::named("layer1")
+ .enter(span.clone())
+ .event(
+ event::mock()
+ .at_level(Level::DEBUG)
+ .in_scope(vec![span.clone()]),
+ )
+ .exit(span)
+ .done()
+ .run_with_handle();
+ (layer.with_filter(filter), handle)
+ };
+
+ let (layer2, handle2) = {
+ let span = span::named("span2");
+ let filter: EnvFilter = "[span2]=info".parse().expect("filter 2 should parse");
+ let (layer, handle) = layer::named("layer2")
+ .enter(span.clone())
+ .event(
+ event::mock()
+ .at_level(Level::INFO)
+ .in_scope(vec![span.clone()]),
+ )
+ .exit(span)
+ .done()
+ .run_with_handle();
+ (layer.with_filter(filter), handle)
+ };
+
+ let _subscriber = tracing_subscriber::registry()
+ .with(layer1)
+ .with(layer2)
+ .set_default();
+
+ tracing::info_span!("span1").in_scope(|| {
+ tracing::debug!("hello from span 1");
+ tracing::trace!("not enabled");
+ });
+
+ tracing::info_span!("span2").in_scope(|| {
+ tracing::info!("hello from span 2");
+ tracing::debug!("not enabled");
+ });
+
+ handle1.assert_finished();
+ handle2.assert_finished();
+}
diff --git a/vendor/tracing-subscriber/tests/event_enabling.rs b/vendor/tracing-subscriber/tests/event_enabling.rs
new file mode 100644
index 000000000..8f67cfcba
--- /dev/null
+++ b/vendor/tracing-subscriber/tests/event_enabling.rs
@@ -0,0 +1,81 @@
+#![cfg(feature = "registry")]
+
+use std::sync::{Arc, Mutex};
+use tracing::{subscriber::with_default, Event, Metadata, Subscriber};
+use tracing_subscriber::{layer::Context, prelude::*, registry, Layer};
+
+struct TrackingLayer {
+ enabled: bool,
+ event_enabled_count: Arc<Mutex<usize>>,
+ event_enabled: bool,
+ on_event_count: Arc<Mutex<usize>>,
+}
+
+impl<C> Layer<C> for TrackingLayer
+where
+ C: Subscriber + Send + Sync + 'static,
+{
+ fn enabled(&self, _metadata: &Metadata<'_>, _ctx: Context<'_, C>) -> bool {
+ self.enabled
+ }
+
+ fn event_enabled(&self, _event: &Event<'_>, _ctx: Context<'_, C>) -> bool {
+ *self.event_enabled_count.lock().unwrap() += 1;
+ self.event_enabled
+ }
+
+ fn on_event(&self, _event: &Event<'_>, _ctx: Context<'_, C>) {
+ *self.on_event_count.lock().unwrap() += 1;
+ }
+}
+
+#[test]
+fn event_enabled_is_only_called_once() {
+ let event_enabled_count = Arc::new(Mutex::default());
+ let count = event_enabled_count.clone();
+ let subscriber = registry().with(TrackingLayer {
+ enabled: true,
+ event_enabled_count,
+ event_enabled: true,
+ on_event_count: Arc::new(Mutex::default()),
+ });
+ with_default(subscriber, || {
+ tracing::error!("hiya!");
+ });
+
+ assert_eq!(1, *count.lock().unwrap());
+}
+
+#[test]
+fn event_enabled_not_called_when_not_enabled() {
+ let event_enabled_count = Arc::new(Mutex::default());
+ let count = event_enabled_count.clone();
+ let subscriber = registry().with(TrackingLayer {
+ enabled: false,
+ event_enabled_count,
+ event_enabled: true,
+ on_event_count: Arc::new(Mutex::default()),
+ });
+ with_default(subscriber, || {
+ tracing::error!("hiya!");
+ });
+
+ assert_eq!(0, *count.lock().unwrap());
+}
+
+#[test]
+fn event_disabled_does_disable_event() {
+ let on_event_count = Arc::new(Mutex::default());
+ let count = on_event_count.clone();
+ let subscriber = registry().with(TrackingLayer {
+ enabled: true,
+ event_enabled_count: Arc::new(Mutex::default()),
+ event_enabled: false,
+ on_event_count,
+ });
+ with_default(subscriber, || {
+ tracing::error!("hiya!");
+ });
+
+ assert_eq!(0, *count.lock().unwrap());
+}
diff --git a/vendor/tracing-subscriber-0.3.3/tests/field_filter.rs b/vendor/tracing-subscriber/tests/field_filter.rs
index 12b4053b6..f14a0626d 100644
--- a/vendor/tracing-subscriber-0.3.3/tests/field_filter.rs
+++ b/vendor/tracing-subscriber/tests/field_filter.rs
@@ -1,7 +1,7 @@
#![cfg(feature = "env-filter")]
-mod support;
-use self::support::*;
+
use tracing::{self, subscriber::with_default, Level};
+use tracing_mock::*;
use tracing_subscriber::{filter::EnvFilter, prelude::*};
#[test]
diff --git a/vendor/tracing-subscriber-0.3.3/tests/filter_log.rs b/vendor/tracing-subscriber/tests/filter_log.rs
index 28e742501..8d57ed600 100644
--- a/vendor/tracing-subscriber-0.3.3/tests/filter_log.rs
+++ b/vendor/tracing-subscriber/tests/filter_log.rs
@@ -1,7 +1,7 @@
#![cfg(all(feature = "env-filter", feature = "tracing-log"))]
-mod support;
-use self::support::*;
+
use tracing::{self, Level};
+use tracing_mock::*;
use tracing_subscriber::{filter::EnvFilter, prelude::*};
mod my_module {
diff --git a/vendor/tracing-subscriber-0.3.3/tests/fmt_max_level_hint.rs b/vendor/tracing-subscriber/tests/fmt_max_level_hint.rs
index 57a0f6e3f..57a0f6e3f 100644
--- a/vendor/tracing-subscriber-0.3.3/tests/fmt_max_level_hint.rs
+++ b/vendor/tracing-subscriber/tests/fmt_max_level_hint.rs
diff --git a/vendor/tracing-subscriber-0.3.3/tests/hinted_layer_filters_dont_break_other_layers.rs b/vendor/tracing-subscriber/tests/hinted_layer_filters_dont_break_other_layers.rs
index 897dae282..897dae282 100644
--- a/vendor/tracing-subscriber-0.3.3/tests/hinted_layer_filters_dont_break_other_layers.rs
+++ b/vendor/tracing-subscriber/tests/hinted_layer_filters_dont_break_other_layers.rs
diff --git a/vendor/tracing-subscriber-0.3.3/tests/layer_filter_interests_are_cached.rs b/vendor/tracing-subscriber/tests/layer_filter_interests_are_cached.rs
index d89d3bf17..d89d3bf17 100644
--- a/vendor/tracing-subscriber-0.3.3/tests/layer_filter_interests_are_cached.rs
+++ b/vendor/tracing-subscriber/tests/layer_filter_interests_are_cached.rs
diff --git a/vendor/tracing-subscriber-0.3.3/tests/layer_filters/boxed.rs b/vendor/tracing-subscriber/tests/layer_filters/boxed.rs
index 0fe37188e..0fe37188e 100644
--- a/vendor/tracing-subscriber-0.3.3/tests/layer_filters/boxed.rs
+++ b/vendor/tracing-subscriber/tests/layer_filters/boxed.rs
diff --git a/vendor/tracing-subscriber/tests/layer_filters/combinators.rs b/vendor/tracing-subscriber/tests/layer_filters/combinators.rs
new file mode 100644
index 000000000..6052a2d00
--- /dev/null
+++ b/vendor/tracing-subscriber/tests/layer_filters/combinators.rs
@@ -0,0 +1,42 @@
+use super::*;
+use tracing_subscriber::{
+ filter::{filter_fn, FilterExt, LevelFilter},
+ prelude::*,
+};
+
+#[test]
+fn and() {
+ let (layer, handle) = layer::mock()
+ .event(
+ event::msg("a very interesting event")
+ .at_level(tracing::Level::INFO)
+ .with_target("interesting_target"),
+ )
+ .done()
+ .run_with_handle();
+
+ // Enables spans and events with targets starting with `interesting_target`:
+ let target_filter = filter::filter_fn(|meta| meta.target().starts_with("interesting_target"));
+
+ // Enables spans and events with levels `INFO` and below:
+ let level_filter = LevelFilter::INFO;
+
+ // Combine the two filters together, returning a filter that only enables
+ // spans and events that *both* filters will enable:
+ let filter = target_filter.and(level_filter);
+
+ let _subscriber = tracing_subscriber::registry()
+ .with(layer.with_filter(filter))
+ .set_default();
+
+ // This event will *not* be enabled:
+ tracing::info!("an event with an uninteresting target");
+
+ // This event *will* be enabled:
+ tracing::info!(target: "interesting_target", "a very interesting event");
+
+ // This event will *not* be enabled:
+ tracing::debug!(target: "interesting_target", "interesting debug event...");
+
+ handle.assert_finished();
+}
diff --git a/vendor/tracing-subscriber-0.3.3/tests/layer_filters/downcast_raw.rs b/vendor/tracing-subscriber/tests/layer_filters/downcast_raw.rs
index b5f7e35ce..b5f7e35ce 100644
--- a/vendor/tracing-subscriber-0.3.3/tests/layer_filters/downcast_raw.rs
+++ b/vendor/tracing-subscriber/tests/layer_filters/downcast_raw.rs
diff --git a/vendor/tracing-subscriber-0.3.3/tests/layer_filters/filter_scopes.rs b/vendor/tracing-subscriber/tests/layer_filters/filter_scopes.rs
index 7fd7d843b..7fd7d843b 100644
--- a/vendor/tracing-subscriber-0.3.3/tests/layer_filters/filter_scopes.rs
+++ b/vendor/tracing-subscriber/tests/layer_filters/filter_scopes.rs
diff --git a/vendor/tracing-subscriber-0.3.3/tests/layer_filters/main.rs b/vendor/tracing-subscriber/tests/layer_filters/main.rs
index 2359584d7..10f06c24c 100644
--- a/vendor/tracing-subscriber-0.3.3/tests/layer_filters/main.rs
+++ b/vendor/tracing-subscriber/tests/layer_filters/main.rs
@@ -5,11 +5,13 @@ use self::support::*;
mod boxed;
mod downcast_raw;
mod filter_scopes;
+mod per_event;
mod targets;
mod trees;
+mod vec;
use tracing::{level_filters::LevelFilter, Level};
-use tracing_subscriber::{filter, prelude::*};
+use tracing_subscriber::{filter, prelude::*, Layer};
#[test]
fn basic_layer_filters() {
diff --git a/vendor/tracing-subscriber/tests/layer_filters/per_event.rs b/vendor/tracing-subscriber/tests/layer_filters/per_event.rs
new file mode 100644
index 000000000..9c785f9a2
--- /dev/null
+++ b/vendor/tracing-subscriber/tests/layer_filters/per_event.rs
@@ -0,0 +1,61 @@
+use crate::support::*;
+use tracing::Level;
+use tracing_subscriber::{field::Visit, layer::Filter, prelude::*};
+
+struct FilterEvent;
+
+impl<S> Filter<S> for FilterEvent {
+ fn enabled(
+ &self,
+ _meta: &tracing::Metadata<'_>,
+ _cx: &tracing_subscriber::layer::Context<'_, S>,
+ ) -> bool {
+ true
+ }
+
+ fn event_enabled(
+ &self,
+ event: &tracing::Event<'_>,
+ _cx: &tracing_subscriber::layer::Context<'_, S>,
+ ) -> bool {
+ struct ShouldEnable(bool);
+ impl Visit for ShouldEnable {
+ fn record_bool(&mut self, field: &tracing_core::Field, value: bool) {
+ if field.name() == "enable" {
+ self.0 = value;
+ }
+ }
+
+ fn record_debug(
+ &mut self,
+ _field: &tracing_core::Field,
+ _value: &dyn core::fmt::Debug,
+ ) {
+ }
+ }
+ let mut should_enable = ShouldEnable(false);
+ event.record(&mut should_enable);
+ should_enable.0
+ }
+}
+
+#[test]
+fn per_subscriber_event_field_filtering() {
+ let (expect, handle) = layer::mock()
+ .event(event::mock().at_level(Level::TRACE))
+ .event(event::mock().at_level(Level::INFO))
+ .done()
+ .run_with_handle();
+
+ let _subscriber = tracing_subscriber::registry()
+ .with(expect.with_filter(FilterEvent))
+ .set_default();
+
+ tracing::trace!(enable = true, "hello trace");
+ tracing::debug!("hello debug");
+ tracing::info!(enable = true, "hello info");
+ tracing::warn!(enable = false, "hello warn");
+ tracing::error!("hello error");
+
+ handle.assert_finished();
+}
diff --git a/vendor/tracing-subscriber-0.3.3/tests/layer_filters/targets.rs b/vendor/tracing-subscriber/tests/layer_filters/targets.rs
index c8133044b..c8133044b 100644
--- a/vendor/tracing-subscriber-0.3.3/tests/layer_filters/targets.rs
+++ b/vendor/tracing-subscriber/tests/layer_filters/targets.rs
diff --git a/vendor/tracing-subscriber-0.3.3/tests/layer_filters/trees.rs b/vendor/tracing-subscriber/tests/layer_filters/trees.rs
index 18cdd8ccc..18cdd8ccc 100644
--- a/vendor/tracing-subscriber-0.3.3/tests/layer_filters/trees.rs
+++ b/vendor/tracing-subscriber/tests/layer_filters/trees.rs
diff --git a/vendor/tracing-subscriber/tests/layer_filters/vec.rs b/vendor/tracing-subscriber/tests/layer_filters/vec.rs
new file mode 100644
index 000000000..87244e4ab
--- /dev/null
+++ b/vendor/tracing-subscriber/tests/layer_filters/vec.rs
@@ -0,0 +1,120 @@
+use super::*;
+use tracing::Subscriber;
+
+#[test]
+fn with_filters_unboxed() {
+ let (trace_layer, trace_handle) = layer::named("trace")
+ .event(event::mock().at_level(Level::TRACE))
+ .event(event::mock().at_level(Level::DEBUG))
+ .event(event::mock().at_level(Level::INFO))
+ .done()
+ .run_with_handle();
+ let trace_layer = trace_layer.with_filter(LevelFilter::TRACE);
+
+ let (debug_layer, debug_handle) = layer::named("debug")
+ .event(event::mock().at_level(Level::DEBUG))
+ .event(event::mock().at_level(Level::INFO))
+ .done()
+ .run_with_handle();
+ let debug_layer = debug_layer.with_filter(LevelFilter::DEBUG);
+
+ let (info_layer, info_handle) = layer::named("info")
+ .event(event::mock().at_level(Level::INFO))
+ .done()
+ .run_with_handle();
+ let info_layer = info_layer.with_filter(LevelFilter::INFO);
+
+ let _subscriber = tracing_subscriber::registry()
+ .with(vec![trace_layer, debug_layer, info_layer])
+ .set_default();
+
+ tracing::trace!("hello trace");
+ tracing::debug!("hello debug");
+ tracing::info!("hello info");
+
+ trace_handle.assert_finished();
+ debug_handle.assert_finished();
+ info_handle.assert_finished();
+}
+
+#[test]
+fn with_filters_boxed() {
+ let (unfiltered_layer, unfiltered_handle) = layer::named("unfiltered")
+ .event(event::mock().at_level(Level::TRACE))
+ .event(event::mock().at_level(Level::DEBUG))
+ .event(event::mock().at_level(Level::INFO))
+ .done()
+ .run_with_handle();
+ let unfiltered_layer = unfiltered_layer.boxed();
+
+ let (debug_layer, debug_handle) = layer::named("debug")
+ .event(event::mock().at_level(Level::DEBUG))
+ .event(event::mock().at_level(Level::INFO))
+ .done()
+ .run_with_handle();
+ let debug_layer = debug_layer.with_filter(LevelFilter::DEBUG).boxed();
+
+ let (target_layer, target_handle) = layer::named("target")
+ .event(event::mock().at_level(Level::INFO))
+ .done()
+ .run_with_handle();
+ let target_layer = target_layer
+ .with_filter(filter::filter_fn(|meta| meta.target() == "my_target"))
+ .boxed();
+
+ let _subscriber = tracing_subscriber::registry()
+ .with(vec![unfiltered_layer, debug_layer, target_layer])
+ .set_default();
+
+ tracing::trace!("hello trace");
+ tracing::debug!("hello debug");
+ tracing::info!(target: "my_target", "hello my target");
+
+ unfiltered_handle.assert_finished();
+ debug_handle.assert_finished();
+ target_handle.assert_finished();
+}
+
+#[test]
+fn mixed_max_level_hint() {
+ let unfiltered = layer::named("unfiltered").run().boxed();
+ let info = layer::named("info")
+ .run()
+ .with_filter(LevelFilter::INFO)
+ .boxed();
+ let debug = layer::named("debug")
+ .run()
+ .with_filter(LevelFilter::DEBUG)
+ .boxed();
+
+ let subscriber = tracing_subscriber::registry().with(vec![unfiltered, info, debug]);
+
+ assert_eq!(subscriber.max_level_hint(), None);
+}
+
+#[test]
+fn all_filtered_max_level_hint() {
+ let warn = layer::named("warn")
+ .run()
+ .with_filter(LevelFilter::WARN)
+ .boxed();
+ let info = layer::named("info")
+ .run()
+ .with_filter(LevelFilter::INFO)
+ .boxed();
+ let debug = layer::named("debug")
+ .run()
+ .with_filter(LevelFilter::DEBUG)
+ .boxed();
+
+ let subscriber = tracing_subscriber::registry().with(vec![warn, info, debug]);
+
+ assert_eq!(subscriber.max_level_hint(), Some(LevelFilter::DEBUG));
+}
+
+#[test]
+fn empty_vec() {
+ // Just a None means everything is off
+ let subscriber = tracing_subscriber::registry().with(Vec::<ExpectLayer>::new());
+ assert_eq!(subscriber.max_level_hint(), Some(LevelFilter::OFF));
+}
diff --git a/vendor/tracing-subscriber-0.3.3/tests/multiple_layer_filter_interests_cached.rs b/vendor/tracing-subscriber/tests/multiple_layer_filter_interests_cached.rs
index 5c25e7f03..5c25e7f03 100644
--- a/vendor/tracing-subscriber-0.3.3/tests/multiple_layer_filter_interests_cached.rs
+++ b/vendor/tracing-subscriber/tests/multiple_layer_filter_interests_cached.rs
diff --git a/vendor/tracing-subscriber/tests/option.rs b/vendor/tracing-subscriber/tests/option.rs
new file mode 100644
index 000000000..c87519c30
--- /dev/null
+++ b/vendor/tracing-subscriber/tests/option.rs
@@ -0,0 +1,262 @@
+#![cfg(feature = "registry")]
+use tracing_core::{subscriber::Interest, LevelFilter, Metadata, Subscriber};
+use tracing_subscriber::{layer, prelude::*};
+
+// A basic layer that returns its inner for `max_level_hint`
+#[derive(Debug)]
+struct BasicLayer(Option<LevelFilter>);
+impl<S: Subscriber> tracing_subscriber::Layer<S> for BasicLayer {
+ fn register_callsite(&self, _m: &Metadata<'_>) -> Interest {
+ Interest::sometimes()
+ }
+
+ fn enabled(&self, _m: &Metadata<'_>, _: layer::Context<'_, S>) -> bool {
+ true
+ }
+
+ fn max_level_hint(&self) -> Option<LevelFilter> {
+ self.0
+ }
+}
+
+// This test is just used to compare to the tests below
+#[test]
+fn just_layer() {
+ let subscriber = tracing_subscriber::registry().with(LevelFilter::INFO);
+ assert_eq!(subscriber.max_level_hint(), Some(LevelFilter::INFO));
+}
+
+#[test]
+fn subscriber_and_option_some_layer() {
+ let subscriber = tracing_subscriber::registry()
+ .with(LevelFilter::INFO)
+ .with(Some(LevelFilter::DEBUG));
+ assert_eq!(subscriber.max_level_hint(), Some(LevelFilter::DEBUG));
+}
+
+#[test]
+fn subscriber_and_option_none_layer() {
+ // None means the other layer takes control
+ let subscriber = tracing_subscriber::registry()
+ .with(LevelFilter::ERROR)
+ .with(None::<LevelFilter>);
+ assert_eq!(subscriber.max_level_hint(), Some(LevelFilter::ERROR));
+}
+
+#[test]
+fn just_option_some_layer() {
+ // Just a None means everything is off
+ let subscriber = tracing_subscriber::registry().with(None::<LevelFilter>);
+ assert_eq!(subscriber.max_level_hint(), Some(LevelFilter::OFF));
+}
+
+/// Tests that the logic tested in `doesnt_override_none` works through the reload subscriber
+#[test]
+fn just_option_none_layer() {
+ let subscriber = tracing_subscriber::registry().with(Some(LevelFilter::ERROR));
+ assert_eq!(subscriber.max_level_hint(), Some(LevelFilter::ERROR));
+}
+
+// Test that the `None` max level hint only applies if its the only layer
+#[test]
+fn none_outside_doesnt_override_max_level() {
+ // None means the other layer takes control
+ let subscriber = tracing_subscriber::registry()
+ .with(BasicLayer(None))
+ .with(None::<LevelFilter>);
+ assert_eq!(
+ subscriber.max_level_hint(),
+ None,
+ "\n stack: {:#?}",
+ subscriber
+ );
+
+ // The `None`-returning layer still wins
+ let subscriber = tracing_subscriber::registry()
+ .with(BasicLayer(None))
+ .with(Some(LevelFilter::ERROR));
+ assert_eq!(
+ subscriber.max_level_hint(),
+ Some(LevelFilter::ERROR),
+ "\n stack: {:#?}",
+ subscriber
+ );
+
+ // Check that we aren't doing anything truly wrong
+ let subscriber = tracing_subscriber::registry()
+ .with(BasicLayer(Some(LevelFilter::DEBUG)))
+ .with(None::<LevelFilter>);
+ assert_eq!(
+ subscriber.max_level_hint(),
+ Some(LevelFilter::DEBUG),
+ "\n stack: {:#?}",
+ subscriber
+ );
+
+ // Test that per-subscriber filters aren't affected
+
+ // One layer is None so it "wins"
+ let subscriber = tracing_subscriber::registry()
+ .with(BasicLayer(None))
+ .with(None::<LevelFilter>.with_filter(LevelFilter::DEBUG));
+ assert_eq!(
+ subscriber.max_level_hint(),
+ None,
+ "\n stack: {:#?}",
+ subscriber
+ );
+
+ // The max-levels wins
+ let subscriber = tracing_subscriber::registry()
+ .with(BasicLayer(Some(LevelFilter::INFO)))
+ .with(None::<LevelFilter>.with_filter(LevelFilter::DEBUG));
+ assert_eq!(
+ subscriber.max_level_hint(),
+ Some(LevelFilter::DEBUG),
+ "\n stack: {:#?}",
+ subscriber
+ );
+
+ // Test filter on the other layer
+ let subscriber = tracing_subscriber::registry()
+ .with(BasicLayer(Some(LevelFilter::INFO)).with_filter(LevelFilter::DEBUG))
+ .with(None::<LevelFilter>);
+ assert_eq!(
+ subscriber.max_level_hint(),
+ Some(LevelFilter::DEBUG),
+ "\n stack: {:#?}",
+ subscriber
+ );
+ let subscriber = tracing_subscriber::registry()
+ .with(BasicLayer(None).with_filter(LevelFilter::DEBUG))
+ .with(None::<LevelFilter>);
+ assert_eq!(
+ subscriber.max_level_hint(),
+ Some(LevelFilter::DEBUG),
+ "\n stack: {:#?}",
+ subscriber
+ );
+
+ // The `OFF` from `None` over overridden.
+ let subscriber = tracing_subscriber::registry()
+ .with(BasicLayer(Some(LevelFilter::INFO)))
+ .with(None::<LevelFilter>);
+ assert_eq!(
+ subscriber.max_level_hint(),
+ Some(LevelFilter::INFO),
+ "\n stack: {:#?}",
+ subscriber
+ );
+}
+
+// Test that the `None` max level hint only applies if its the only layer
+#[test]
+fn none_inside_doesnt_override_max_level() {
+ // None means the other layer takes control
+ let subscriber = tracing_subscriber::registry()
+ .with(None::<LevelFilter>)
+ .with(BasicLayer(None));
+ assert_eq!(
+ subscriber.max_level_hint(),
+ None,
+ "\n stack: {:#?}",
+ subscriber
+ );
+
+ // The `None`-returning layer still wins
+ let subscriber = tracing_subscriber::registry()
+ .with(Some(LevelFilter::ERROR))
+ .with(BasicLayer(None));
+ assert_eq!(
+ subscriber.max_level_hint(),
+ Some(LevelFilter::ERROR),
+ "\n stack: {:#?}",
+ subscriber
+ );
+
+ // Check that we aren't doing anything truly wrong
+ let subscriber = tracing_subscriber::registry()
+ .with(None::<LevelFilter>)
+ .with(BasicLayer(Some(LevelFilter::DEBUG)));
+ assert_eq!(
+ subscriber.max_level_hint(),
+ Some(LevelFilter::DEBUG),
+ "\n stack: {:#?}",
+ subscriber
+ );
+
+ // Test that per-subscriber filters aren't affected
+
+ // One layer is None so it "wins"
+ let subscriber = tracing_subscriber::registry()
+ .with(None::<LevelFilter>.with_filter(LevelFilter::DEBUG))
+ .with(BasicLayer(None));
+ assert_eq!(
+ subscriber.max_level_hint(),
+ None,
+ "\n stack: {:#?}",
+ subscriber
+ );
+
+ // The max-levels wins
+ let subscriber = tracing_subscriber::registry()
+ .with(None::<LevelFilter>.with_filter(LevelFilter::DEBUG))
+ .with(BasicLayer(Some(LevelFilter::INFO)));
+ assert_eq!(
+ subscriber.max_level_hint(),
+ Some(LevelFilter::DEBUG),
+ "\n stack: {:#?}",
+ subscriber
+ );
+
+ // Test filter on the other layer
+ let subscriber = tracing_subscriber::registry()
+ .with(None::<LevelFilter>)
+ .with(BasicLayer(Some(LevelFilter::INFO)).with_filter(LevelFilter::DEBUG));
+ assert_eq!(
+ subscriber.max_level_hint(),
+ Some(LevelFilter::DEBUG),
+ "\n stack: {:#?}",
+ subscriber
+ );
+ let subscriber = tracing_subscriber::registry()
+ .with(None::<LevelFilter>)
+ .with(BasicLayer(None).with_filter(LevelFilter::DEBUG));
+ assert_eq!(
+ subscriber.max_level_hint(),
+ Some(LevelFilter::DEBUG),
+ "\n stack: {:#?}",
+ subscriber
+ );
+
+ // The `OFF` from `None` over overridden.
+ let subscriber = tracing_subscriber::registry()
+ .with(None::<LevelFilter>)
+ .with(BasicLayer(Some(LevelFilter::INFO)));
+ assert_eq!(
+ subscriber.max_level_hint(),
+ Some(LevelFilter::INFO),
+ "\n stack: {:#?}",
+ subscriber
+ );
+}
+
+/// Tests that the logic tested in `doesnt_override_none` works through the reload layer
+#[test]
+fn reload_works_with_none() {
+ let (layer1, handle1) = tracing_subscriber::reload::Layer::new(None::<BasicLayer>);
+ let (layer2, _handle2) = tracing_subscriber::reload::Layer::new(None::<BasicLayer>);
+
+ let subscriber = tracing_subscriber::registry().with(layer1).with(layer2);
+ assert_eq!(subscriber.max_level_hint(), Some(LevelFilter::OFF));
+
+ // reloading one should pass through correctly.
+ handle1.reload(Some(BasicLayer(None))).unwrap();
+ assert_eq!(subscriber.max_level_hint(), None);
+
+ // Check pass-through of an actual level as well
+ handle1
+ .reload(Some(BasicLayer(Some(LevelFilter::DEBUG))))
+ .unwrap();
+ assert_eq!(subscriber.max_level_hint(), Some(LevelFilter::DEBUG));
+}
diff --git a/vendor/tracing-subscriber-0.3.3/tests/registry_max_level_hint.rs b/vendor/tracing-subscriber/tests/registry_max_level_hint.rs
index f94c8a1fb..f94c8a1fb 100644
--- a/vendor/tracing-subscriber-0.3.3/tests/registry_max_level_hint.rs
+++ b/vendor/tracing-subscriber/tests/registry_max_level_hint.rs
diff --git a/vendor/tracing-subscriber-0.3.3/tests/registry_with_subscriber.rs b/vendor/tracing-subscriber/tests/registry_with_subscriber.rs
index 3f8d99b1d..50d2f551d 100644
--- a/vendor/tracing-subscriber-0.3.3/tests/registry_with_subscriber.rs
+++ b/vendor/tracing-subscriber/tests/registry_with_subscriber.rs
@@ -4,7 +4,7 @@ use tracing_subscriber::prelude::*;
#[tokio::test]
async fn future_with_subscriber() {
- let _default = tracing_subscriber::registry().init();
+ tracing_subscriber::registry().init();
let span = tracing::info_span!("foo");
let _e = span.enter();
let span = tracing::info_span!("bar");
diff --git a/vendor/tracing-subscriber/tests/reload.rs b/vendor/tracing-subscriber/tests/reload.rs
new file mode 100644
index 000000000..28662e2e6
--- /dev/null
+++ b/vendor/tracing-subscriber/tests/reload.rs
@@ -0,0 +1,155 @@
+#![cfg(feature = "registry")]
+use std::sync::atomic::{AtomicUsize, Ordering};
+use tracing_core::{
+ span::{Attributes, Id, Record},
+ subscriber::Interest,
+ Event, LevelFilter, Metadata, Subscriber,
+};
+use tracing_subscriber::{layer, prelude::*, reload::*};
+
+pub struct NopSubscriber;
+fn event() {
+ tracing::info!("my event");
+}
+
+impl Subscriber for NopSubscriber {
+ fn register_callsite(&self, _: &'static Metadata<'static>) -> Interest {
+ Interest::never()
+ }
+
+ fn enabled(&self, _: &Metadata<'_>) -> bool {
+ false
+ }
+
+ fn new_span(&self, _: &Attributes<'_>) -> Id {
+ Id::from_u64(1)
+ }
+
+ fn record(&self, _: &Id, _: &Record<'_>) {}
+ fn record_follows_from(&self, _: &Id, _: &Id) {}
+ fn event(&self, _: &Event<'_>) {}
+ fn enter(&self, _: &Id) {}
+ fn exit(&self, _: &Id) {}
+}
+
+#[test]
+fn reload_handle() {
+ static FILTER1_CALLS: AtomicUsize = AtomicUsize::new(0);
+ static FILTER2_CALLS: AtomicUsize = AtomicUsize::new(0);
+
+ enum Filter {
+ One,
+ Two,
+ }
+
+ impl<S: Subscriber> tracing_subscriber::Layer<S> for Filter {
+ fn register_callsite(&self, m: &Metadata<'_>) -> Interest {
+ println!("REGISTER: {:?}", m);
+ Interest::sometimes()
+ }
+
+ fn enabled(&self, m: &Metadata<'_>, _: layer::Context<'_, S>) -> bool {
+ println!("ENABLED: {:?}", m);
+ match self {
+ Filter::One => FILTER1_CALLS.fetch_add(1, Ordering::SeqCst),
+ Filter::Two => FILTER2_CALLS.fetch_add(1, Ordering::SeqCst),
+ };
+ true
+ }
+
+ fn max_level_hint(&self) -> Option<LevelFilter> {
+ match self {
+ Filter::One => Some(LevelFilter::INFO),
+ Filter::Two => Some(LevelFilter::DEBUG),
+ }
+ }
+ }
+
+ let (layer, handle) = Layer::new(Filter::One);
+
+ let subscriber = tracing_core::dispatcher::Dispatch::new(layer.with_subscriber(NopSubscriber));
+
+ tracing_core::dispatcher::with_default(&subscriber, || {
+ assert_eq!(FILTER1_CALLS.load(Ordering::SeqCst), 0);
+ assert_eq!(FILTER2_CALLS.load(Ordering::SeqCst), 0);
+
+ event();
+
+ assert_eq!(FILTER1_CALLS.load(Ordering::SeqCst), 1);
+ assert_eq!(FILTER2_CALLS.load(Ordering::SeqCst), 0);
+
+ assert_eq!(LevelFilter::current(), LevelFilter::INFO);
+ handle.reload(Filter::Two).expect("should reload");
+ assert_eq!(LevelFilter::current(), LevelFilter::DEBUG);
+
+ event();
+
+ assert_eq!(FILTER1_CALLS.load(Ordering::SeqCst), 1);
+ assert_eq!(FILTER2_CALLS.load(Ordering::SeqCst), 1);
+ })
+}
+
+#[test]
+fn reload_filter() {
+ struct NopLayer;
+ impl<S: Subscriber> tracing_subscriber::Layer<S> for NopLayer {
+ fn register_callsite(&self, _m: &Metadata<'_>) -> Interest {
+ Interest::sometimes()
+ }
+
+ fn enabled(&self, _m: &Metadata<'_>, _: layer::Context<'_, S>) -> bool {
+ true
+ }
+ }
+
+ static FILTER1_CALLS: AtomicUsize = AtomicUsize::new(0);
+ static FILTER2_CALLS: AtomicUsize = AtomicUsize::new(0);
+
+ enum Filter {
+ One,
+ Two,
+ }
+
+ impl<S: Subscriber> tracing_subscriber::layer::Filter<S> for Filter {
+ fn enabled(&self, m: &Metadata<'_>, _: &layer::Context<'_, S>) -> bool {
+ println!("ENABLED: {:?}", m);
+ match self {
+ Filter::One => FILTER1_CALLS.fetch_add(1, Ordering::SeqCst),
+ Filter::Two => FILTER2_CALLS.fetch_add(1, Ordering::SeqCst),
+ };
+ true
+ }
+
+ fn max_level_hint(&self) -> Option<LevelFilter> {
+ match self {
+ Filter::One => Some(LevelFilter::INFO),
+ Filter::Two => Some(LevelFilter::DEBUG),
+ }
+ }
+ }
+
+ let (filter, handle) = Layer::new(Filter::One);
+
+ let dispatcher = tracing_core::Dispatch::new(
+ tracing_subscriber::registry().with(NopLayer.with_filter(filter)),
+ );
+
+ tracing_core::dispatcher::with_default(&dispatcher, || {
+ assert_eq!(FILTER1_CALLS.load(Ordering::SeqCst), 0);
+ assert_eq!(FILTER2_CALLS.load(Ordering::SeqCst), 0);
+
+ event();
+
+ assert_eq!(FILTER1_CALLS.load(Ordering::SeqCst), 1);
+ assert_eq!(FILTER2_CALLS.load(Ordering::SeqCst), 0);
+
+ assert_eq!(LevelFilter::current(), LevelFilter::INFO);
+ handle.reload(Filter::Two).expect("should reload");
+ assert_eq!(LevelFilter::current(), LevelFilter::DEBUG);
+
+ event();
+
+ assert_eq!(FILTER1_CALLS.load(Ordering::SeqCst), 1);
+ assert_eq!(FILTER2_CALLS.load(Ordering::SeqCst), 1);
+ })
+}
diff --git a/vendor/tracing-subscriber-0.3.3/tests/same_len_filters.rs b/vendor/tracing-subscriber/tests/same_len_filters.rs
index b525ea6fd..879e578d7 100644
--- a/vendor/tracing-subscriber-0.3.3/tests/same_len_filters.rs
+++ b/vendor/tracing-subscriber/tests/same_len_filters.rs
@@ -1,9 +1,9 @@
// These tests include field filters with no targets, so they have to go in a
// separate file.
#![cfg(feature = "env-filter")]
-mod support;
-use self::support::*;
+
use tracing::{self, subscriber::with_default, Level};
+use tracing_mock::*;
use tracing_subscriber::{filter::EnvFilter, prelude::*};
#[test]
diff --git a/vendor/tracing-subscriber-0.3.3/tests/support.rs b/vendor/tracing-subscriber/tests/support.rs
index 848ebdc63..50e0e6669 100644
--- a/vendor/tracing-subscriber-0.3.3/tests/support.rs
+++ b/vendor/tracing-subscriber/tests/support.rs
@@ -1,20 +1,15 @@
#![allow(missing_docs, dead_code)]
-pub use self::support::{event, field, span, subscriber};
-// This has to have the same name as the module in `tracing`.
-// path attribute requires referenced module to have same name so allow module inception here
-#[allow(clippy::module_inception)]
-#[path = "../../tracing/tests/support/mod.rs"]
-mod support;
-
-use self::{
- event::MockEvent,
- span::{MockSpan, NewSpan},
- subscriber::{Expect, MockHandle},
-};
+pub use tracing_mock::{event, field, span, subscriber};
+
use tracing_core::{
span::{Attributes, Id, Record},
Event, Subscriber,
};
+use tracing_mock::{
+ event::MockEvent,
+ span::{MockSpan, NewSpan},
+ subscriber::{Expect, MockHandle},
+};
use tracing_subscriber::{
layer::{Context, Layer},
registry::{LookupSpan, SpanRef},
diff --git a/vendor/tracing-subscriber-0.3.3/tests/unhinted_layer_filters_dont_break_other_layers.rs b/vendor/tracing-subscriber/tests/unhinted_layer_filters_dont_break_other_layers.rs
index 9fa5c6bd4..9fa5c6bd4 100644
--- a/vendor/tracing-subscriber-0.3.3/tests/unhinted_layer_filters_dont_break_other_layers.rs
+++ b/vendor/tracing-subscriber/tests/unhinted_layer_filters_dont_break_other_layers.rs
diff --git a/vendor/tracing-subscriber-0.3.3/tests/utils.rs b/vendor/tracing-subscriber/tests/utils.rs
index ff025a2a2..e95868d5e 100644
--- a/vendor/tracing-subscriber-0.3.3/tests/utils.rs
+++ b/vendor/tracing-subscriber/tests/utils.rs
@@ -1,6 +1,6 @@
#![cfg(feature = "std")]
-mod support;
-use self::support::*;
+
+use tracing_mock::*;
use tracing_subscriber::prelude::*;
#[test]
diff --git a/vendor/tracing-subscriber/tests/vec.rs b/vendor/tracing-subscriber/tests/vec.rs
new file mode 100644
index 000000000..92abf0bff
--- /dev/null
+++ b/vendor/tracing-subscriber/tests/vec.rs
@@ -0,0 +1,19 @@
+#![cfg(feature = "registry")]
+use tracing::level_filters::LevelFilter;
+use tracing::Subscriber;
+use tracing_subscriber::prelude::*;
+
+#[test]
+fn just_empty_vec() {
+ // Just a None means everything is off
+ let subscriber = tracing_subscriber::registry().with(Vec::<LevelFilter>::new());
+ assert_eq!(subscriber.max_level_hint(), Some(LevelFilter::OFF));
+}
+
+#[test]
+fn layer_and_empty_vec() {
+ let subscriber = tracing_subscriber::registry()
+ .with(LevelFilter::INFO)
+ .with(Vec::<LevelFilter>::new());
+ assert_eq!(subscriber.max_level_hint(), Some(LevelFilter::INFO));
+}
diff --git a/vendor/tracing-subscriber/tests/vec_subscriber_filter_interests_cached.rs b/vendor/tracing-subscriber/tests/vec_subscriber_filter_interests_cached.rs
new file mode 100644
index 000000000..10467cb7d
--- /dev/null
+++ b/vendor/tracing-subscriber/tests/vec_subscriber_filter_interests_cached.rs
@@ -0,0 +1,117 @@
+#![cfg(feature = "registry")]
+mod support;
+use self::support::*;
+
+use std::{
+ collections::HashMap,
+ sync::{Arc, Mutex},
+};
+use tracing::{Level, Subscriber};
+use tracing_subscriber::{filter, prelude::*};
+
+#[test]
+fn vec_layer_filter_interests_are_cached() {
+ let mk_filtered = |level: Level, subscriber: ExpectLayer| {
+ let seen = Arc::new(Mutex::new(HashMap::new()));
+ let filter = filter::filter_fn({
+ let seen = seen.clone();
+ move |meta| {
+ *seen.lock().unwrap().entry(*meta.level()).or_insert(0usize) += 1;
+ meta.level() <= &level
+ }
+ });
+ (subscriber.with_filter(filter).boxed(), seen)
+ };
+
+ // This layer will return Interest::always for INFO and lower.
+ let (info_layer, info_handle) = layer::named("info")
+ .event(event::mock().at_level(Level::INFO))
+ .event(event::mock().at_level(Level::WARN))
+ .event(event::mock().at_level(Level::ERROR))
+ .event(event::mock().at_level(Level::INFO))
+ .event(event::mock().at_level(Level::WARN))
+ .event(event::mock().at_level(Level::ERROR))
+ .done()
+ .run_with_handle();
+ let (info_layer, seen_info) = mk_filtered(Level::INFO, info_layer);
+
+ // This layer will return Interest::always for WARN and lower.
+ let (warn_layer, warn_handle) = layer::named("warn")
+ .event(event::mock().at_level(Level::WARN))
+ .event(event::mock().at_level(Level::ERROR))
+ .event(event::mock().at_level(Level::WARN))
+ .event(event::mock().at_level(Level::ERROR))
+ .done()
+ .run_with_handle();
+ let (warn_layer, seen_warn) = mk_filtered(Level::WARN, warn_layer);
+
+ let subscriber = tracing_subscriber::registry().with(vec![warn_layer, info_layer]);
+ assert!(subscriber.max_level_hint().is_none());
+
+ let _subscriber = subscriber.set_default();
+
+ fn events() {
+ tracing::trace!("hello trace");
+ tracing::debug!("hello debug");
+ tracing::info!("hello info");
+ tracing::warn!("hello warn");
+ tracing::error!("hello error");
+ }
+
+ events();
+ {
+ let lock = seen_info.lock().unwrap();
+ for (&level, &count) in lock.iter() {
+ if level == Level::INFO {
+ continue;
+ }
+ assert_eq!(
+ count, 1,
+ "level {:?} should have been seen 1 time by the INFO subscriber (after first set of events)",
+ level
+ );
+ }
+
+ let lock = seen_warn.lock().unwrap();
+ for (&level, &count) in lock.iter() {
+ if level == Level::INFO {
+ continue;
+ }
+ assert_eq!(
+ count, 1,
+ "level {:?} should have been seen 1 time by the WARN subscriber (after first set of events)",
+ level
+ );
+ }
+ }
+
+ events();
+ {
+ let lock = seen_info.lock().unwrap();
+ for (&level, &count) in lock.iter() {
+ if level == Level::INFO {
+ continue;
+ }
+ assert_eq!(
+ count, 1,
+ "level {:?} should have been seen 1 time by the INFO subscriber (after second set of events)",
+ level
+ );
+ }
+
+ let lock = seen_warn.lock().unwrap();
+ for (&level, &count) in lock.iter() {
+ if level == Level::INFO {
+ continue;
+ }
+ assert_eq!(
+ count, 1,
+ "level {:?} should have been seen 1 time by the WARN subscriber (after second set of events)",
+ level
+ );
+ }
+ }
+
+ info_handle.assert_finished();
+ warn_handle.assert_finished();
+}
diff --git a/vendor/tracing-tree/.cargo-checksum.json b/vendor/tracing-tree/.cargo-checksum.json
index c140e495f..215b14ece 100644
--- a/vendor/tracing-tree/.cargo-checksum.json
+++ b/vendor/tracing-tree/.cargo-checksum.json
@@ -1 +1 @@
-{"files":{"Cargo.lock":"e54b0301e8816a5e2d82ba08646102d89ee556d5e9150c571123a34013e6a79a","Cargo.toml":"734e1e9cf702e362c0661b968e92fd4599b732208a65634dd516d085449d45b2","LICENSE-APACHE":"c9c77d27bd737506eee1be90c11885fad935695714eafacd6725f41fff9ec8da","LICENSE-MIT":"d31139de68f7e19f9b32cd7de53dbb125b3c68522bbbb1d0c186c33112d34466","README.md":"589c2534836513b4edfa2811269767a9ac3c48da909c8ab936db3e646410dcf7","examples/basic.rs":"b56dad20aa283aae17a9c1364cc0326714cdc89d6a02a6329034e476b3597fd7","examples/basic.stdout":"49767873eb520f3e457b48d930fa86583d9ca5ef5571d67582b08dcb788ff6f2","examples/quiet.rs":"65a4cbb650cea4939ed274c2fd4d50c953151716fa6564b23393e1df6fb7afd7","examples/quiet.stdout":"d58a3240258279821b5d08e0d39ea60dee2dbd6a955f8639daf0d149ad0616fa","examples/stderr.rs":"ce0896f50be810908fb7083661bf39da6c9733ddef9188d40499313a40fe2c7a","examples/stderr.stderr":"8a0f6553fee903f159c6ea528dda6c5b193064ef9b58c765d1f3f60ecba5ac1f","examples/wraparound.rs":"7998f2e7b9e1f0dfc4b0cf11b1cdcf0f44c85aeaabbea9749113584ac7a3879f","examples/wraparound.stdout":"1c042231b3f8b20a843c18af063e43a51fcc852597dd1713f5878d4a8128271c","src/format.rs":"a986c0a259aec3135bcfd4908f6a80173dea03b3f57efe1dfa7c9d79f2b55257","src/lib.rs":"0a62652d641131ff67c31103331b977ca42ed268a1703aa7365180c70465f536","tests/ui.rs":"32a02ef41ae5cbabe13164f8d665b287b0bb764b2dc5bcb80443cb551df5289a"},"package":"d07e90b329c621ade432823988574e820212648aa40e7a2497777d58de0fb453"} \ No newline at end of file
+{"files":{"Cargo.lock":"a8a2a7ff05ca79c6ded4cf0625f6188d43625b8ba7358950eafa11b3af01dbda","Cargo.toml":"d883458574569e20468318abd1792c7312d9a31ba44dcc59203f6aa6b4bb3b01","LICENSE-APACHE":"c9c77d27bd737506eee1be90c11885fad935695714eafacd6725f41fff9ec8da","LICENSE-MIT":"d31139de68f7e19f9b32cd7de53dbb125b3c68522bbbb1d0c186c33112d34466","README.md":"589c2534836513b4edfa2811269767a9ac3c48da909c8ab936db3e646410dcf7","examples/basic.rs":"b56dad20aa283aae17a9c1364cc0326714cdc89d6a02a6329034e476b3597fd7","examples/basic.stdout":"49767873eb520f3e457b48d930fa86583d9ca5ef5571d67582b08dcb788ff6f2","examples/quiet.rs":"65a4cbb650cea4939ed274c2fd4d50c953151716fa6564b23393e1df6fb7afd7","examples/quiet.stdout":"d58a3240258279821b5d08e0d39ea60dee2dbd6a955f8639daf0d149ad0616fa","examples/stderr.rs":"ce0896f50be810908fb7083661bf39da6c9733ddef9188d40499313a40fe2c7a","examples/stderr.stderr":"8a0f6553fee903f159c6ea528dda6c5b193064ef9b58c765d1f3f60ecba5ac1f","examples/wraparound.rs":"7998f2e7b9e1f0dfc4b0cf11b1cdcf0f44c85aeaabbea9749113584ac7a3879f","examples/wraparound.stdout":"1c042231b3f8b20a843c18af063e43a51fcc852597dd1713f5878d4a8128271c","src/format.rs":"0dbfbe7a1939fefc3ade3ffa2113d382424f387130388fd3431210bbccef8b8b","src/lib.rs":"8a286a67ae3860d1c30cb336c1a6253920bf63b789e455a27d0e8b611228c1a6","tests/ui.rs":"32a02ef41ae5cbabe13164f8d665b287b0bb764b2dc5bcb80443cb551df5289a"},"package":"758e983ab7c54fee18403994507e7f212b9005e957ce7984996fac8d11facedb"} \ No newline at end of file
diff --git a/vendor/tracing-tree/Cargo.lock b/vendor/tracing-tree/Cargo.lock
index 82a94c9e0..2d4ae7226 100644
--- a/vendor/tracing-tree/Cargo.lock
+++ b/vendor/tracing-tree/Cargo.lock
@@ -3,15 +3,6 @@
version = 3
[[package]]
-name = "ansi_term"
-version = "0.12.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2"
-dependencies = [
- "winapi",
-]
-
-[[package]]
name = "assert_cmd"
version = "1.0.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -123,12 +114,28 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
[[package]]
+name = "nu-ansi-term"
+version = "0.46.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84"
+dependencies = [
+ "overload",
+ "winapi",
+]
+
+[[package]]
name = "once_cell"
version = "1.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7709cef83f0c1f58f666e746a08b21e0085f7440fa6a29cc194d68aac97a4225"
[[package]]
+name = "overload"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39"
+
+[[package]]
name = "pin-project-lite"
version = "0.2.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -277,13 +284,13 @@ dependencies = [
[[package]]
name = "tracing-tree"
-version = "0.2.1"
+version = "0.2.2"
dependencies = [
- "ansi_term",
"assert_cmd",
"atty",
"glob",
"log",
+ "nu-ansi-term",
"tracing",
"tracing-core",
"tracing-log",
diff --git a/vendor/tracing-tree/Cargo.toml b/vendor/tracing-tree/Cargo.toml
index 32c47092f..7e8799662 100644
--- a/vendor/tracing-tree/Cargo.toml
+++ b/vendor/tracing-tree/Cargo.toml
@@ -12,7 +12,7 @@
[package]
edition = "2018"
name = "tracing-tree"
-version = "0.2.1"
+version = "0.2.2"
authors = [
"David Barsky <me@davidbarsky.com>",
"Nathan Whitaker",
@@ -26,12 +26,12 @@ repository = "https://github.com/davidbarsky/tracing-tree"
name = "ui"
harness = false
-[dependencies.ansi_term]
-version = "0.12"
-
[dependencies.atty]
version = "0.2"
+[dependencies.nu-ansi-term]
+version = "0.46.0"
+
[dependencies.tracing-core]
version = "0.1"
diff --git a/vendor/tracing-tree/src/format.rs b/vendor/tracing-tree/src/format.rs
index 067ea9771..895c04be2 100644
--- a/vendor/tracing-tree/src/format.rs
+++ b/vendor/tracing-tree/src/format.rs
@@ -1,4 +1,4 @@
-use ansi_term::Color;
+use nu_ansi_term::Color;
use std::{
fmt::{self, Write as _},
io,
@@ -251,7 +251,7 @@ impl<'a> fmt::Display for ColorLevel<'a> {
Level::TRACE => Color::Purple.bold().paint("TRACE"),
Level::DEBUG => Color::Blue.bold().paint("DEBUG"),
Level::INFO => Color::Green.bold().paint(" INFO"),
- Level::WARN => Color::RGB(252, 234, 160).bold().paint(" WARN"), // orange
+ Level::WARN => Color::Rgb(252, 234, 160).bold().paint(" WARN"), // orange
Level::ERROR => Color::Red.bold().paint("ERROR"),
}
.fmt(f)
diff --git a/vendor/tracing-tree/src/lib.rs b/vendor/tracing-tree/src/lib.rs
index dbacaa57e..266523b73 100644
--- a/vendor/tracing-tree/src/lib.rs
+++ b/vendor/tracing-tree/src/lib.rs
@@ -1,7 +1,7 @@
pub(crate) mod format;
-use ansi_term::{Color, Style};
use format::{Buffers, ColorLevel, Config, FmtEvent, SpanMode};
+use nu_ansi_term::{Color, Style};
use std::{
fmt::{self, Write as _},
io,
diff --git a/vendor/unicode-bidi/.cargo-checksum.json b/vendor/unicode-bidi/.cargo-checksum.json
index 6dc5a203e..ab0bb707a 100644
--- a/vendor/unicode-bidi/.cargo-checksum.json
+++ b/vendor/unicode-bidi/.cargo-checksum.json
@@ -1 +1 @@
-{"files":{"AUTHORS":"1ff3a7c8519b29544bb28ba9b1e7502df0cb764051fb9a1172e60006aa2b8dcc","COPYRIGHT":"edb20b474f6cbd4f4db066b54a9e0f687d0009d309412a63431189b59b8e2a07","Cargo.toml":"c0862499053fc6c7d7c34bbcc5443d818a6d69c3e0f56a5ec1331a87895aaa1a","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"7b63ecd5f1902af1b63729947373683c32745c16a10e8e6292e2e2dcd7e90ae0","README.md":"81d3dc6d894a68894d982760b0a907f9dcbb0da179a8063ed9de1d2257518957","src/char_data/mod.rs":"eeef418c98739eed13f993c21cb2ed872b40c31f102d437e5b37cc7a97aeb5de","src/char_data/tables.rs":"ca8f4f579fe2ef81cb39b13ef6ea3c0bc78cdf1c51668a25ccc2447adf1c95e4","src/data_source.rs":"4c7831c47c85eaf0d7412ed3e6baea667ba3b44f87ddffef4e7b76b5bb5b1272","src/deprecated.rs":"3c8b465b827a487df7945cb928e1eae98f9929b71c4d0c99511a470704455a8c","src/explicit.rs":"808aec21bcaa86cb00721b3f61f5f98c3eba40fcc6bb3f8a18739ce6a35b7c1c","src/format_chars.rs":"678399fec3f4bfaf4093f38cfdb8956288313386dc3511dab9fb58164e8dc01b","src/implicit.rs":"167be5386315acefbe8a38918b1850b80beccc7485f759d12bc3f5b2c6870c21","src/level.rs":"9bf4943fe3f6c134640e37acbf1bfcaf8b074739c7625736823bf0bc185e1e0d","src/lib.rs":"671b8b4339f1ddcc262df0a3f774c2874e0b2428269dcecf63a003b7848fee9f","src/prepare.rs":"94b74379faa4d8d8d905ea848292a92ca3d93bef1a428fd92afe262b54912c10"},"package":"099b7128301d285f79ddd55b9a83d5e6b9e97c92e0ea0daebee7263e932de992"} \ No newline at end of file
+{"files":{"AUTHORS":"1ff3a7c8519b29544bb28ba9b1e7502df0cb764051fb9a1172e60006aa2b8dcc","COPYRIGHT":"edb20b474f6cbd4f4db066b54a9e0f687d0009d309412a63431189b59b8e2a07","Cargo.toml":"bac3b9c34e93bfab34060c48f493cd82eece9ae99d9b1c98df1d875a8266bfff","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"7b63ecd5f1902af1b63729947373683c32745c16a10e8e6292e2e2dcd7e90ae0","README.md":"81d3dc6d894a68894d982760b0a907f9dcbb0da179a8063ed9de1d2257518957","src/char_data/mod.rs":"0622df8ce4b4de60aea7e4787635d3187f79f7a3f9001e3d209f58fd07d03887","src/char_data/tables.rs":"50faf4eef73c831a38b735309ff3415e9f65992a0474ff5c055138f91c91ee16","src/data_source.rs":"36fa0785e51c549c1f72f09040cfe515b848d1b23fb30d469770a6b4b17b49df","src/deprecated.rs":"3c8b465b827a487df7945cb928e1eae98f9929b71c4d0c99511a470704455a8c","src/explicit.rs":"53428d618aef86c6790d195eb9477f09decc396772581427241d34139f886517","src/format_chars.rs":"678399fec3f4bfaf4093f38cfdb8956288313386dc3511dab9fb58164e8dc01b","src/implicit.rs":"454f35f0803ae7d1d7fdb2d1fb0cd675dd83c5dd92a8d31445847a5a2a16b6bf","src/level.rs":"9bf4943fe3f6c134640e37acbf1bfcaf8b074739c7625736823bf0bc185e1e0d","src/lib.rs":"33830f404ebdf3a0561c415ed3f0e5d8739e749db27f21f9e2644031afa511fa","src/prepare.rs":"7aa46ba8d0448a34be704cc3a1f49bc52ddfce62fa66af65618c2ac94cb88a4e"},"package":"d54675592c1dbefd78cbd98db9bacd89886e1ca50692a0692baefffdeb92dd58"} \ No newline at end of file
diff --git a/vendor/unicode-bidi/Cargo.toml b/vendor/unicode-bidi/Cargo.toml
index 9a8ca4a32..02ea8fabf 100644
--- a/vendor/unicode-bidi/Cargo.toml
+++ b/vendor/unicode-bidi/Cargo.toml
@@ -12,7 +12,7 @@
[package]
edition = "2018"
name = "unicode-bidi"
-version = "0.3.8"
+version = "0.3.10"
authors = ["The Servo Project Developers"]
exclude = [
"benches/**",
@@ -42,6 +42,11 @@ repository = "https://github.com/servo/unicode-bidi"
[lib]
name = "unicode_bidi"
+[[test]]
+name = "conformance_tests"
+path = "tests/conformance_tests.rs"
+required-features = ["hardcoded-data"]
+
[dependencies.flame]
version = "0.2"
optional = true
diff --git a/vendor/unicode-bidi/src/char_data/mod.rs b/vendor/unicode-bidi/src/char_data/mod.rs
index a8b452788..4edf5b8f4 100644
--- a/vendor/unicode-bidi/src/char_data/mod.rs
+++ b/vendor/unicode-bidi/src/char_data/mod.rs
@@ -19,10 +19,10 @@ use core::cmp::Ordering::{Equal, Greater, Less};
#[cfg(feature = "hardcoded-data")]
use self::tables::bidi_class_table;
+use crate::data_source::BidiMatchedOpeningBracket;
use crate::BidiClass::*;
#[cfg(feature = "hardcoded-data")]
use crate::BidiDataSource;
-
/// Hardcoded Bidi data that ships with the unicode-bidi crate.
///
/// This can be enabled with the default `hardcoded-data` Cargo feature.
@@ -42,6 +42,22 @@ pub fn bidi_class(c: char) -> BidiClass {
bsearch_range_value_table(c, bidi_class_table)
}
+/// If this character is a bracket according to BidiBrackets.txt,
+/// return the corresponding *normalized* *opening bracket* of the pair,
+/// and whether or not it itself is an opening bracket.
+pub(crate) fn bidi_matched_opening_bracket(c: char) -> Option<BidiMatchedOpeningBracket> {
+ for pair in self::tables::bidi_pairs_table {
+ if pair.0 == c || pair.1 == c {
+ let skeleton = pair.2.unwrap_or(pair.0);
+ return Some(BidiMatchedOpeningBracket {
+ opening: skeleton,
+ is_open: pair.0 == c,
+ });
+ }
+ }
+ None
+}
+
pub fn is_rtl(bidi_class: BidiClass) -> bool {
match bidi_class {
RLE | RLO | RLI => true,
diff --git a/vendor/unicode-bidi/src/char_data/tables.rs b/vendor/unicode-bidi/src/char_data/tables.rs
index 502ae9e90..ecdcf496d 100644
--- a/vendor/unicode-bidi/src/char_data/tables.rs
+++ b/vendor/unicode-bidi/src/char_data/tables.rs
@@ -5,7 +5,7 @@
#![cfg_attr(rustfmt, rustfmt_skip)]
/// The [Unicode version](http://www.unicode.org/versions/) of data
-pub const UNICODE_VERSION: (u64, u64, u64) = (14, 0, 0);
+pub const UNICODE_VERSION: (u64, u64, u64) = (15, 0, 0);
#[allow(non_camel_case_types)]
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
@@ -140,7 +140,7 @@ pub const bidi_class_table: &'static [(char, char, BidiClass)] = &[
'\u{cb9}', L), ('\u{cbc}', '\u{cbc}', NSM), ('\u{cbd}', '\u{cc4}', L), ('\u{cc6}', '\u{cc8}',
L), ('\u{cca}', '\u{ccb}', L), ('\u{ccc}', '\u{ccd}', NSM), ('\u{cd5}', '\u{cd6}', L),
('\u{cdd}', '\u{cde}', L), ('\u{ce0}', '\u{ce1}', L), ('\u{ce2}', '\u{ce3}', NSM), ('\u{ce6}',
- '\u{cef}', L), ('\u{cf1}', '\u{cf2}', L), ('\u{d00}', '\u{d01}', NSM), ('\u{d02}', '\u{d0c}',
+ '\u{cef}', L), ('\u{cf1}', '\u{cf3}', L), ('\u{d00}', '\u{d01}', NSM), ('\u{d02}', '\u{d0c}',
L), ('\u{d0e}', '\u{d10}', L), ('\u{d12}', '\u{d3a}', L), ('\u{d3b}', '\u{d3c}', NSM),
('\u{d3d}', '\u{d40}', L), ('\u{d41}', '\u{d44}', NSM), ('\u{d46}', '\u{d48}', L), ('\u{d4a}',
'\u{d4c}', L), ('\u{d4d}', '\u{d4d}', NSM), ('\u{d4e}', '\u{d4f}', L), ('\u{d54}', '\u{d61}',
@@ -154,7 +154,7 @@ pub const bidi_class_table: &'static [(char, char, BidiClass)] = &[
('\u{e4f}', '\u{e5b}', L), ('\u{e81}', '\u{e82}', L), ('\u{e84}', '\u{e84}', L), ('\u{e86}',
'\u{e8a}', L), ('\u{e8c}', '\u{ea3}', L), ('\u{ea5}', '\u{ea5}', L), ('\u{ea7}', '\u{eb0}', L),
('\u{eb1}', '\u{eb1}', NSM), ('\u{eb2}', '\u{eb3}', L), ('\u{eb4}', '\u{ebc}', NSM), ('\u{ebd}',
- '\u{ebd}', L), ('\u{ec0}', '\u{ec4}', L), ('\u{ec6}', '\u{ec6}', L), ('\u{ec8}', '\u{ecd}',
+ '\u{ebd}', L), ('\u{ec0}', '\u{ec4}', L), ('\u{ec6}', '\u{ec6}', L), ('\u{ec8}', '\u{ece}',
NSM), ('\u{ed0}', '\u{ed9}', L), ('\u{edc}', '\u{edf}', L), ('\u{f00}', '\u{f17}', L),
('\u{f18}', '\u{f19}', NSM), ('\u{f1a}', '\u{f34}', L), ('\u{f35}', '\u{f35}', NSM), ('\u{f36}',
'\u{f36}', L), ('\u{f37}', '\u{f37}', NSM), ('\u{f38}', '\u{f38}', L), ('\u{f39}', '\u{f39}',
@@ -361,96 +361,102 @@ pub const bidi_class_table: &'static [(char, char, BidiClass)] = &[
'\u{10cff}', R), ('\u{10d00}', '\u{10d23}', AL), ('\u{10d24}', '\u{10d27}', NSM), ('\u{10d28}',
'\u{10d2f}', R), ('\u{10d30}', '\u{10d39}', AN), ('\u{10d3a}', '\u{10e5f}', R), ('\u{10e60}',
'\u{10e7e}', AN), ('\u{10e7f}', '\u{10eaa}', R), ('\u{10eab}', '\u{10eac}', NSM), ('\u{10ead}',
- '\u{10f2f}', R), ('\u{10f30}', '\u{10f45}', AL), ('\u{10f46}', '\u{10f50}', NSM), ('\u{10f51}',
- '\u{10f59}', AL), ('\u{10f5a}', '\u{10f81}', R), ('\u{10f82}', '\u{10f85}', NSM), ('\u{10f86}',
- '\u{10fff}', R), ('\u{11000}', '\u{11000}', L), ('\u{11001}', '\u{11001}', NSM), ('\u{11002}',
- '\u{11037}', L), ('\u{11038}', '\u{11046}', NSM), ('\u{11047}', '\u{1104d}', L), ('\u{11052}',
- '\u{11065}', ON), ('\u{11066}', '\u{1106f}', L), ('\u{11070}', '\u{11070}', NSM), ('\u{11071}',
- '\u{11072}', L), ('\u{11073}', '\u{11074}', NSM), ('\u{11075}', '\u{11075}', L), ('\u{1107f}',
- '\u{11081}', NSM), ('\u{11082}', '\u{110b2}', L), ('\u{110b3}', '\u{110b6}', NSM), ('\u{110b7}',
- '\u{110b8}', L), ('\u{110b9}', '\u{110ba}', NSM), ('\u{110bb}', '\u{110c1}', L), ('\u{110c2}',
- '\u{110c2}', NSM), ('\u{110cd}', '\u{110cd}', L), ('\u{110d0}', '\u{110e8}', L), ('\u{110f0}',
- '\u{110f9}', L), ('\u{11100}', '\u{11102}', NSM), ('\u{11103}', '\u{11126}', L), ('\u{11127}',
- '\u{1112b}', NSM), ('\u{1112c}', '\u{1112c}', L), ('\u{1112d}', '\u{11134}', NSM), ('\u{11136}',
- '\u{11147}', L), ('\u{11150}', '\u{11172}', L), ('\u{11173}', '\u{11173}', NSM), ('\u{11174}',
- '\u{11176}', L), ('\u{11180}', '\u{11181}', NSM), ('\u{11182}', '\u{111b5}', L), ('\u{111b6}',
- '\u{111be}', NSM), ('\u{111bf}', '\u{111c8}', L), ('\u{111c9}', '\u{111cc}', NSM), ('\u{111cd}',
- '\u{111ce}', L), ('\u{111cf}', '\u{111cf}', NSM), ('\u{111d0}', '\u{111df}', L), ('\u{111e1}',
- '\u{111f4}', L), ('\u{11200}', '\u{11211}', L), ('\u{11213}', '\u{1122e}', L), ('\u{1122f}',
- '\u{11231}', NSM), ('\u{11232}', '\u{11233}', L), ('\u{11234}', '\u{11234}', NSM), ('\u{11235}',
- '\u{11235}', L), ('\u{11236}', '\u{11237}', NSM), ('\u{11238}', '\u{1123d}', L), ('\u{1123e}',
- '\u{1123e}', NSM), ('\u{11280}', '\u{11286}', L), ('\u{11288}', '\u{11288}', L), ('\u{1128a}',
- '\u{1128d}', L), ('\u{1128f}', '\u{1129d}', L), ('\u{1129f}', '\u{112a9}', L), ('\u{112b0}',
- '\u{112de}', L), ('\u{112df}', '\u{112df}', NSM), ('\u{112e0}', '\u{112e2}', L), ('\u{112e3}',
- '\u{112ea}', NSM), ('\u{112f0}', '\u{112f9}', L), ('\u{11300}', '\u{11301}', NSM), ('\u{11302}',
- '\u{11303}', L), ('\u{11305}', '\u{1130c}', L), ('\u{1130f}', '\u{11310}', L), ('\u{11313}',
- '\u{11328}', L), ('\u{1132a}', '\u{11330}', L), ('\u{11332}', '\u{11333}', L), ('\u{11335}',
- '\u{11339}', L), ('\u{1133b}', '\u{1133c}', NSM), ('\u{1133d}', '\u{1133f}', L), ('\u{11340}',
- '\u{11340}', NSM), ('\u{11341}', '\u{11344}', L), ('\u{11347}', '\u{11348}', L), ('\u{1134b}',
- '\u{1134d}', L), ('\u{11350}', '\u{11350}', L), ('\u{11357}', '\u{11357}', L), ('\u{1135d}',
- '\u{11363}', L), ('\u{11366}', '\u{1136c}', NSM), ('\u{11370}', '\u{11374}', NSM), ('\u{11400}',
- '\u{11437}', L), ('\u{11438}', '\u{1143f}', NSM), ('\u{11440}', '\u{11441}', L), ('\u{11442}',
- '\u{11444}', NSM), ('\u{11445}', '\u{11445}', L), ('\u{11446}', '\u{11446}', NSM), ('\u{11447}',
- '\u{1145b}', L), ('\u{1145d}', '\u{1145d}', L), ('\u{1145e}', '\u{1145e}', NSM), ('\u{1145f}',
- '\u{11461}', L), ('\u{11480}', '\u{114b2}', L), ('\u{114b3}', '\u{114b8}', NSM), ('\u{114b9}',
- '\u{114b9}', L), ('\u{114ba}', '\u{114ba}', NSM), ('\u{114bb}', '\u{114be}', L), ('\u{114bf}',
- '\u{114c0}', NSM), ('\u{114c1}', '\u{114c1}', L), ('\u{114c2}', '\u{114c3}', NSM), ('\u{114c4}',
- '\u{114c7}', L), ('\u{114d0}', '\u{114d9}', L), ('\u{11580}', '\u{115b1}', L), ('\u{115b2}',
- '\u{115b5}', NSM), ('\u{115b8}', '\u{115bb}', L), ('\u{115bc}', '\u{115bd}', NSM), ('\u{115be}',
- '\u{115be}', L), ('\u{115bf}', '\u{115c0}', NSM), ('\u{115c1}', '\u{115db}', L), ('\u{115dc}',
- '\u{115dd}', NSM), ('\u{11600}', '\u{11632}', L), ('\u{11633}', '\u{1163a}', NSM), ('\u{1163b}',
- '\u{1163c}', L), ('\u{1163d}', '\u{1163d}', NSM), ('\u{1163e}', '\u{1163e}', L), ('\u{1163f}',
- '\u{11640}', NSM), ('\u{11641}', '\u{11644}', L), ('\u{11650}', '\u{11659}', L), ('\u{11660}',
- '\u{1166c}', ON), ('\u{11680}', '\u{116aa}', L), ('\u{116ab}', '\u{116ab}', NSM), ('\u{116ac}',
- '\u{116ac}', L), ('\u{116ad}', '\u{116ad}', NSM), ('\u{116ae}', '\u{116af}', L), ('\u{116b0}',
- '\u{116b5}', NSM), ('\u{116b6}', '\u{116b6}', L), ('\u{116b7}', '\u{116b7}', NSM), ('\u{116b8}',
- '\u{116b9}', L), ('\u{116c0}', '\u{116c9}', L), ('\u{11700}', '\u{1171a}', L), ('\u{1171d}',
- '\u{1171f}', NSM), ('\u{11720}', '\u{11721}', L), ('\u{11722}', '\u{11725}', NSM), ('\u{11726}',
- '\u{11726}', L), ('\u{11727}', '\u{1172b}', NSM), ('\u{11730}', '\u{11746}', L), ('\u{11800}',
- '\u{1182e}', L), ('\u{1182f}', '\u{11837}', NSM), ('\u{11838}', '\u{11838}', L), ('\u{11839}',
- '\u{1183a}', NSM), ('\u{1183b}', '\u{1183b}', L), ('\u{118a0}', '\u{118f2}', L), ('\u{118ff}',
- '\u{11906}', L), ('\u{11909}', '\u{11909}', L), ('\u{1190c}', '\u{11913}', L), ('\u{11915}',
- '\u{11916}', L), ('\u{11918}', '\u{11935}', L), ('\u{11937}', '\u{11938}', L), ('\u{1193b}',
- '\u{1193c}', NSM), ('\u{1193d}', '\u{1193d}', L), ('\u{1193e}', '\u{1193e}', NSM), ('\u{1193f}',
- '\u{11942}', L), ('\u{11943}', '\u{11943}', NSM), ('\u{11944}', '\u{11946}', L), ('\u{11950}',
- '\u{11959}', L), ('\u{119a0}', '\u{119a7}', L), ('\u{119aa}', '\u{119d3}', L), ('\u{119d4}',
- '\u{119d7}', NSM), ('\u{119da}', '\u{119db}', NSM), ('\u{119dc}', '\u{119df}', L), ('\u{119e0}',
- '\u{119e0}', NSM), ('\u{119e1}', '\u{119e4}', L), ('\u{11a00}', '\u{11a00}', L), ('\u{11a01}',
- '\u{11a06}', NSM), ('\u{11a07}', '\u{11a08}', L), ('\u{11a09}', '\u{11a0a}', NSM), ('\u{11a0b}',
- '\u{11a32}', L), ('\u{11a33}', '\u{11a38}', NSM), ('\u{11a39}', '\u{11a3a}', L), ('\u{11a3b}',
- '\u{11a3e}', NSM), ('\u{11a3f}', '\u{11a46}', L), ('\u{11a47}', '\u{11a47}', NSM), ('\u{11a50}',
- '\u{11a50}', L), ('\u{11a51}', '\u{11a56}', NSM), ('\u{11a57}', '\u{11a58}', L), ('\u{11a59}',
- '\u{11a5b}', NSM), ('\u{11a5c}', '\u{11a89}', L), ('\u{11a8a}', '\u{11a96}', NSM), ('\u{11a97}',
- '\u{11a97}', L), ('\u{11a98}', '\u{11a99}', NSM), ('\u{11a9a}', '\u{11aa2}', L), ('\u{11ab0}',
- '\u{11af8}', L), ('\u{11c00}', '\u{11c08}', L), ('\u{11c0a}', '\u{11c2f}', L), ('\u{11c30}',
- '\u{11c36}', NSM), ('\u{11c38}', '\u{11c3d}', NSM), ('\u{11c3e}', '\u{11c45}', L), ('\u{11c50}',
- '\u{11c6c}', L), ('\u{11c70}', '\u{11c8f}', L), ('\u{11c92}', '\u{11ca7}', NSM), ('\u{11ca9}',
- '\u{11ca9}', L), ('\u{11caa}', '\u{11cb0}', NSM), ('\u{11cb1}', '\u{11cb1}', L), ('\u{11cb2}',
- '\u{11cb3}', NSM), ('\u{11cb4}', '\u{11cb4}', L), ('\u{11cb5}', '\u{11cb6}', NSM), ('\u{11d00}',
- '\u{11d06}', L), ('\u{11d08}', '\u{11d09}', L), ('\u{11d0b}', '\u{11d30}', L), ('\u{11d31}',
- '\u{11d36}', NSM), ('\u{11d3a}', '\u{11d3a}', NSM), ('\u{11d3c}', '\u{11d3d}', NSM),
- ('\u{11d3f}', '\u{11d45}', NSM), ('\u{11d46}', '\u{11d46}', L), ('\u{11d47}', '\u{11d47}', NSM),
- ('\u{11d50}', '\u{11d59}', L), ('\u{11d60}', '\u{11d65}', L), ('\u{11d67}', '\u{11d68}', L),
- ('\u{11d6a}', '\u{11d8e}', L), ('\u{11d90}', '\u{11d91}', NSM), ('\u{11d93}', '\u{11d94}', L),
- ('\u{11d95}', '\u{11d95}', NSM), ('\u{11d96}', '\u{11d96}', L), ('\u{11d97}', '\u{11d97}', NSM),
- ('\u{11d98}', '\u{11d98}', L), ('\u{11da0}', '\u{11da9}', L), ('\u{11ee0}', '\u{11ef2}', L),
- ('\u{11ef3}', '\u{11ef4}', NSM), ('\u{11ef5}', '\u{11ef8}', L), ('\u{11fb0}', '\u{11fb0}', L),
- ('\u{11fc0}', '\u{11fd4}', L), ('\u{11fd5}', '\u{11fdc}', ON), ('\u{11fdd}', '\u{11fe0}', ET),
- ('\u{11fe1}', '\u{11ff1}', ON), ('\u{11fff}', '\u{12399}', L), ('\u{12400}', '\u{1246e}', L),
- ('\u{12470}', '\u{12474}', L), ('\u{12480}', '\u{12543}', L), ('\u{12f90}', '\u{12ff2}', L),
- ('\u{13000}', '\u{1342e}', L), ('\u{13430}', '\u{13438}', L), ('\u{14400}', '\u{14646}', L),
- ('\u{16800}', '\u{16a38}', L), ('\u{16a40}', '\u{16a5e}', L), ('\u{16a60}', '\u{16a69}', L),
- ('\u{16a6e}', '\u{16abe}', L), ('\u{16ac0}', '\u{16ac9}', L), ('\u{16ad0}', '\u{16aed}', L),
- ('\u{16af0}', '\u{16af4}', NSM), ('\u{16af5}', '\u{16af5}', L), ('\u{16b00}', '\u{16b2f}', L),
- ('\u{16b30}', '\u{16b36}', NSM), ('\u{16b37}', '\u{16b45}', L), ('\u{16b50}', '\u{16b59}', L),
- ('\u{16b5b}', '\u{16b61}', L), ('\u{16b63}', '\u{16b77}', L), ('\u{16b7d}', '\u{16b8f}', L),
- ('\u{16e40}', '\u{16e9a}', L), ('\u{16f00}', '\u{16f4a}', L), ('\u{16f4f}', '\u{16f4f}', NSM),
- ('\u{16f50}', '\u{16f87}', L), ('\u{16f8f}', '\u{16f92}', NSM), ('\u{16f93}', '\u{16f9f}', L),
- ('\u{16fe0}', '\u{16fe1}', L), ('\u{16fe2}', '\u{16fe2}', ON), ('\u{16fe3}', '\u{16fe3}', L),
- ('\u{16fe4}', '\u{16fe4}', NSM), ('\u{16ff0}', '\u{16ff1}', L), ('\u{17000}', '\u{187f7}', L),
- ('\u{18800}', '\u{18cd5}', L), ('\u{18d00}', '\u{18d08}', L), ('\u{1aff0}', '\u{1aff3}', L),
- ('\u{1aff5}', '\u{1affb}', L), ('\u{1affd}', '\u{1affe}', L), ('\u{1b000}', '\u{1b122}', L),
- ('\u{1b150}', '\u{1b152}', L), ('\u{1b164}', '\u{1b167}', L), ('\u{1b170}', '\u{1b2fb}', L),
+ '\u{10efc}', R), ('\u{10efd}', '\u{10eff}', NSM), ('\u{10f00}', '\u{10f2f}', R), ('\u{10f30}',
+ '\u{10f45}', AL), ('\u{10f46}', '\u{10f50}', NSM), ('\u{10f51}', '\u{10f59}', AL), ('\u{10f5a}',
+ '\u{10f81}', R), ('\u{10f82}', '\u{10f85}', NSM), ('\u{10f86}', '\u{10fff}', R), ('\u{11000}',
+ '\u{11000}', L), ('\u{11001}', '\u{11001}', NSM), ('\u{11002}', '\u{11037}', L), ('\u{11038}',
+ '\u{11046}', NSM), ('\u{11047}', '\u{1104d}', L), ('\u{11052}', '\u{11065}', ON), ('\u{11066}',
+ '\u{1106f}', L), ('\u{11070}', '\u{11070}', NSM), ('\u{11071}', '\u{11072}', L), ('\u{11073}',
+ '\u{11074}', NSM), ('\u{11075}', '\u{11075}', L), ('\u{1107f}', '\u{11081}', NSM), ('\u{11082}',
+ '\u{110b2}', L), ('\u{110b3}', '\u{110b6}', NSM), ('\u{110b7}', '\u{110b8}', L), ('\u{110b9}',
+ '\u{110ba}', NSM), ('\u{110bb}', '\u{110c1}', L), ('\u{110c2}', '\u{110c2}', NSM), ('\u{110cd}',
+ '\u{110cd}', L), ('\u{110d0}', '\u{110e8}', L), ('\u{110f0}', '\u{110f9}', L), ('\u{11100}',
+ '\u{11102}', NSM), ('\u{11103}', '\u{11126}', L), ('\u{11127}', '\u{1112b}', NSM), ('\u{1112c}',
+ '\u{1112c}', L), ('\u{1112d}', '\u{11134}', NSM), ('\u{11136}', '\u{11147}', L), ('\u{11150}',
+ '\u{11172}', L), ('\u{11173}', '\u{11173}', NSM), ('\u{11174}', '\u{11176}', L), ('\u{11180}',
+ '\u{11181}', NSM), ('\u{11182}', '\u{111b5}', L), ('\u{111b6}', '\u{111be}', NSM), ('\u{111bf}',
+ '\u{111c8}', L), ('\u{111c9}', '\u{111cc}', NSM), ('\u{111cd}', '\u{111ce}', L), ('\u{111cf}',
+ '\u{111cf}', NSM), ('\u{111d0}', '\u{111df}', L), ('\u{111e1}', '\u{111f4}', L), ('\u{11200}',
+ '\u{11211}', L), ('\u{11213}', '\u{1122e}', L), ('\u{1122f}', '\u{11231}', NSM), ('\u{11232}',
+ '\u{11233}', L), ('\u{11234}', '\u{11234}', NSM), ('\u{11235}', '\u{11235}', L), ('\u{11236}',
+ '\u{11237}', NSM), ('\u{11238}', '\u{1123d}', L), ('\u{1123e}', '\u{1123e}', NSM), ('\u{1123f}',
+ '\u{11240}', L), ('\u{11241}', '\u{11241}', NSM), ('\u{11280}', '\u{11286}', L), ('\u{11288}',
+ '\u{11288}', L), ('\u{1128a}', '\u{1128d}', L), ('\u{1128f}', '\u{1129d}', L), ('\u{1129f}',
+ '\u{112a9}', L), ('\u{112b0}', '\u{112de}', L), ('\u{112df}', '\u{112df}', NSM), ('\u{112e0}',
+ '\u{112e2}', L), ('\u{112e3}', '\u{112ea}', NSM), ('\u{112f0}', '\u{112f9}', L), ('\u{11300}',
+ '\u{11301}', NSM), ('\u{11302}', '\u{11303}', L), ('\u{11305}', '\u{1130c}', L), ('\u{1130f}',
+ '\u{11310}', L), ('\u{11313}', '\u{11328}', L), ('\u{1132a}', '\u{11330}', L), ('\u{11332}',
+ '\u{11333}', L), ('\u{11335}', '\u{11339}', L), ('\u{1133b}', '\u{1133c}', NSM), ('\u{1133d}',
+ '\u{1133f}', L), ('\u{11340}', '\u{11340}', NSM), ('\u{11341}', '\u{11344}', L), ('\u{11347}',
+ '\u{11348}', L), ('\u{1134b}', '\u{1134d}', L), ('\u{11350}', '\u{11350}', L), ('\u{11357}',
+ '\u{11357}', L), ('\u{1135d}', '\u{11363}', L), ('\u{11366}', '\u{1136c}', NSM), ('\u{11370}',
+ '\u{11374}', NSM), ('\u{11400}', '\u{11437}', L), ('\u{11438}', '\u{1143f}', NSM), ('\u{11440}',
+ '\u{11441}', L), ('\u{11442}', '\u{11444}', NSM), ('\u{11445}', '\u{11445}', L), ('\u{11446}',
+ '\u{11446}', NSM), ('\u{11447}', '\u{1145b}', L), ('\u{1145d}', '\u{1145d}', L), ('\u{1145e}',
+ '\u{1145e}', NSM), ('\u{1145f}', '\u{11461}', L), ('\u{11480}', '\u{114b2}', L), ('\u{114b3}',
+ '\u{114b8}', NSM), ('\u{114b9}', '\u{114b9}', L), ('\u{114ba}', '\u{114ba}', NSM), ('\u{114bb}',
+ '\u{114be}', L), ('\u{114bf}', '\u{114c0}', NSM), ('\u{114c1}', '\u{114c1}', L), ('\u{114c2}',
+ '\u{114c3}', NSM), ('\u{114c4}', '\u{114c7}', L), ('\u{114d0}', '\u{114d9}', L), ('\u{11580}',
+ '\u{115b1}', L), ('\u{115b2}', '\u{115b5}', NSM), ('\u{115b8}', '\u{115bb}', L), ('\u{115bc}',
+ '\u{115bd}', NSM), ('\u{115be}', '\u{115be}', L), ('\u{115bf}', '\u{115c0}', NSM), ('\u{115c1}',
+ '\u{115db}', L), ('\u{115dc}', '\u{115dd}', NSM), ('\u{11600}', '\u{11632}', L), ('\u{11633}',
+ '\u{1163a}', NSM), ('\u{1163b}', '\u{1163c}', L), ('\u{1163d}', '\u{1163d}', NSM), ('\u{1163e}',
+ '\u{1163e}', L), ('\u{1163f}', '\u{11640}', NSM), ('\u{11641}', '\u{11644}', L), ('\u{11650}',
+ '\u{11659}', L), ('\u{11660}', '\u{1166c}', ON), ('\u{11680}', '\u{116aa}', L), ('\u{116ab}',
+ '\u{116ab}', NSM), ('\u{116ac}', '\u{116ac}', L), ('\u{116ad}', '\u{116ad}', NSM), ('\u{116ae}',
+ '\u{116af}', L), ('\u{116b0}', '\u{116b5}', NSM), ('\u{116b6}', '\u{116b6}', L), ('\u{116b7}',
+ '\u{116b7}', NSM), ('\u{116b8}', '\u{116b9}', L), ('\u{116c0}', '\u{116c9}', L), ('\u{11700}',
+ '\u{1171a}', L), ('\u{1171d}', '\u{1171f}', NSM), ('\u{11720}', '\u{11721}', L), ('\u{11722}',
+ '\u{11725}', NSM), ('\u{11726}', '\u{11726}', L), ('\u{11727}', '\u{1172b}', NSM), ('\u{11730}',
+ '\u{11746}', L), ('\u{11800}', '\u{1182e}', L), ('\u{1182f}', '\u{11837}', NSM), ('\u{11838}',
+ '\u{11838}', L), ('\u{11839}', '\u{1183a}', NSM), ('\u{1183b}', '\u{1183b}', L), ('\u{118a0}',
+ '\u{118f2}', L), ('\u{118ff}', '\u{11906}', L), ('\u{11909}', '\u{11909}', L), ('\u{1190c}',
+ '\u{11913}', L), ('\u{11915}', '\u{11916}', L), ('\u{11918}', '\u{11935}', L), ('\u{11937}',
+ '\u{11938}', L), ('\u{1193b}', '\u{1193c}', NSM), ('\u{1193d}', '\u{1193d}', L), ('\u{1193e}',
+ '\u{1193e}', NSM), ('\u{1193f}', '\u{11942}', L), ('\u{11943}', '\u{11943}', NSM), ('\u{11944}',
+ '\u{11946}', L), ('\u{11950}', '\u{11959}', L), ('\u{119a0}', '\u{119a7}', L), ('\u{119aa}',
+ '\u{119d3}', L), ('\u{119d4}', '\u{119d7}', NSM), ('\u{119da}', '\u{119db}', NSM), ('\u{119dc}',
+ '\u{119df}', L), ('\u{119e0}', '\u{119e0}', NSM), ('\u{119e1}', '\u{119e4}', L), ('\u{11a00}',
+ '\u{11a00}', L), ('\u{11a01}', '\u{11a06}', NSM), ('\u{11a07}', '\u{11a08}', L), ('\u{11a09}',
+ '\u{11a0a}', NSM), ('\u{11a0b}', '\u{11a32}', L), ('\u{11a33}', '\u{11a38}', NSM), ('\u{11a39}',
+ '\u{11a3a}', L), ('\u{11a3b}', '\u{11a3e}', NSM), ('\u{11a3f}', '\u{11a46}', L), ('\u{11a47}',
+ '\u{11a47}', NSM), ('\u{11a50}', '\u{11a50}', L), ('\u{11a51}', '\u{11a56}', NSM), ('\u{11a57}',
+ '\u{11a58}', L), ('\u{11a59}', '\u{11a5b}', NSM), ('\u{11a5c}', '\u{11a89}', L), ('\u{11a8a}',
+ '\u{11a96}', NSM), ('\u{11a97}', '\u{11a97}', L), ('\u{11a98}', '\u{11a99}', NSM), ('\u{11a9a}',
+ '\u{11aa2}', L), ('\u{11ab0}', '\u{11af8}', L), ('\u{11b00}', '\u{11b09}', L), ('\u{11c00}',
+ '\u{11c08}', L), ('\u{11c0a}', '\u{11c2f}', L), ('\u{11c30}', '\u{11c36}', NSM), ('\u{11c38}',
+ '\u{11c3d}', NSM), ('\u{11c3e}', '\u{11c45}', L), ('\u{11c50}', '\u{11c6c}', L), ('\u{11c70}',
+ '\u{11c8f}', L), ('\u{11c92}', '\u{11ca7}', NSM), ('\u{11ca9}', '\u{11ca9}', L), ('\u{11caa}',
+ '\u{11cb0}', NSM), ('\u{11cb1}', '\u{11cb1}', L), ('\u{11cb2}', '\u{11cb3}', NSM), ('\u{11cb4}',
+ '\u{11cb4}', L), ('\u{11cb5}', '\u{11cb6}', NSM), ('\u{11d00}', '\u{11d06}', L), ('\u{11d08}',
+ '\u{11d09}', L), ('\u{11d0b}', '\u{11d30}', L), ('\u{11d31}', '\u{11d36}', NSM), ('\u{11d3a}',
+ '\u{11d3a}', NSM), ('\u{11d3c}', '\u{11d3d}', NSM), ('\u{11d3f}', '\u{11d45}', NSM),
+ ('\u{11d46}', '\u{11d46}', L), ('\u{11d47}', '\u{11d47}', NSM), ('\u{11d50}', '\u{11d59}', L),
+ ('\u{11d60}', '\u{11d65}', L), ('\u{11d67}', '\u{11d68}', L), ('\u{11d6a}', '\u{11d8e}', L),
+ ('\u{11d90}', '\u{11d91}', NSM), ('\u{11d93}', '\u{11d94}', L), ('\u{11d95}', '\u{11d95}', NSM),
+ ('\u{11d96}', '\u{11d96}', L), ('\u{11d97}', '\u{11d97}', NSM), ('\u{11d98}', '\u{11d98}', L),
+ ('\u{11da0}', '\u{11da9}', L), ('\u{11ee0}', '\u{11ef2}', L), ('\u{11ef3}', '\u{11ef4}', NSM),
+ ('\u{11ef5}', '\u{11ef8}', L), ('\u{11f00}', '\u{11f01}', NSM), ('\u{11f02}', '\u{11f10}', L),
+ ('\u{11f12}', '\u{11f35}', L), ('\u{11f36}', '\u{11f3a}', NSM), ('\u{11f3e}', '\u{11f3f}', L),
+ ('\u{11f40}', '\u{11f40}', NSM), ('\u{11f41}', '\u{11f41}', L), ('\u{11f42}', '\u{11f42}', NSM),
+ ('\u{11f43}', '\u{11f59}', L), ('\u{11fb0}', '\u{11fb0}', L), ('\u{11fc0}', '\u{11fd4}', L),
+ ('\u{11fd5}', '\u{11fdc}', ON), ('\u{11fdd}', '\u{11fe0}', ET), ('\u{11fe1}', '\u{11ff1}', ON),
+ ('\u{11fff}', '\u{12399}', L), ('\u{12400}', '\u{1246e}', L), ('\u{12470}', '\u{12474}', L),
+ ('\u{12480}', '\u{12543}', L), ('\u{12f90}', '\u{12ff2}', L), ('\u{13000}', '\u{1343f}', L),
+ ('\u{13440}', '\u{13440}', NSM), ('\u{13441}', '\u{13446}', L), ('\u{13447}', '\u{13455}', NSM),
+ ('\u{14400}', '\u{14646}', L), ('\u{16800}', '\u{16a38}', L), ('\u{16a40}', '\u{16a5e}', L),
+ ('\u{16a60}', '\u{16a69}', L), ('\u{16a6e}', '\u{16abe}', L), ('\u{16ac0}', '\u{16ac9}', L),
+ ('\u{16ad0}', '\u{16aed}', L), ('\u{16af0}', '\u{16af4}', NSM), ('\u{16af5}', '\u{16af5}', L),
+ ('\u{16b00}', '\u{16b2f}', L), ('\u{16b30}', '\u{16b36}', NSM), ('\u{16b37}', '\u{16b45}', L),
+ ('\u{16b50}', '\u{16b59}', L), ('\u{16b5b}', '\u{16b61}', L), ('\u{16b63}', '\u{16b77}', L),
+ ('\u{16b7d}', '\u{16b8f}', L), ('\u{16e40}', '\u{16e9a}', L), ('\u{16f00}', '\u{16f4a}', L),
+ ('\u{16f4f}', '\u{16f4f}', NSM), ('\u{16f50}', '\u{16f87}', L), ('\u{16f8f}', '\u{16f92}', NSM),
+ ('\u{16f93}', '\u{16f9f}', L), ('\u{16fe0}', '\u{16fe1}', L), ('\u{16fe2}', '\u{16fe2}', ON),
+ ('\u{16fe3}', '\u{16fe3}', L), ('\u{16fe4}', '\u{16fe4}', NSM), ('\u{16ff0}', '\u{16ff1}', L),
+ ('\u{17000}', '\u{187f7}', L), ('\u{18800}', '\u{18cd5}', L), ('\u{18d00}', '\u{18d08}', L),
+ ('\u{1aff0}', '\u{1aff3}', L), ('\u{1aff5}', '\u{1affb}', L), ('\u{1affd}', '\u{1affe}', L),
+ ('\u{1b000}', '\u{1b122}', L), ('\u{1b132}', '\u{1b132}', L), ('\u{1b150}', '\u{1b152}', L),
+ ('\u{1b155}', '\u{1b155}', L), ('\u{1b164}', '\u{1b167}', L), ('\u{1b170}', '\u{1b2fb}', L),
('\u{1bc00}', '\u{1bc6a}', L), ('\u{1bc70}', '\u{1bc7c}', L), ('\u{1bc80}', '\u{1bc88}', L),
('\u{1bc90}', '\u{1bc99}', L), ('\u{1bc9c}', '\u{1bc9c}', L), ('\u{1bc9d}', '\u{1bc9e}', NSM),
('\u{1bc9f}', '\u{1bc9f}', L), ('\u{1bca0}', '\u{1bca3}', BN), ('\u{1cf00}', '\u{1cf2d}', NSM),
@@ -460,51 +466,78 @@ pub const bidi_class_table: &'static [(char, char, BidiClass)] = &[
('\u{1d183}', '\u{1d184}', L), ('\u{1d185}', '\u{1d18b}', NSM), ('\u{1d18c}', '\u{1d1a9}', L),
('\u{1d1aa}', '\u{1d1ad}', NSM), ('\u{1d1ae}', '\u{1d1e8}', L), ('\u{1d1e9}', '\u{1d1ea}', ON),
('\u{1d200}', '\u{1d241}', ON), ('\u{1d242}', '\u{1d244}', NSM), ('\u{1d245}', '\u{1d245}', ON),
- ('\u{1d2e0}', '\u{1d2f3}', L), ('\u{1d300}', '\u{1d356}', ON), ('\u{1d360}', '\u{1d378}', L),
- ('\u{1d400}', '\u{1d454}', L), ('\u{1d456}', '\u{1d49c}', L), ('\u{1d49e}', '\u{1d49f}', L),
- ('\u{1d4a2}', '\u{1d4a2}', L), ('\u{1d4a5}', '\u{1d4a6}', L), ('\u{1d4a9}', '\u{1d4ac}', L),
- ('\u{1d4ae}', '\u{1d4b9}', L), ('\u{1d4bb}', '\u{1d4bb}', L), ('\u{1d4bd}', '\u{1d4c3}', L),
- ('\u{1d4c5}', '\u{1d505}', L), ('\u{1d507}', '\u{1d50a}', L), ('\u{1d50d}', '\u{1d514}', L),
- ('\u{1d516}', '\u{1d51c}', L), ('\u{1d51e}', '\u{1d539}', L), ('\u{1d53b}', '\u{1d53e}', L),
- ('\u{1d540}', '\u{1d544}', L), ('\u{1d546}', '\u{1d546}', L), ('\u{1d54a}', '\u{1d550}', L),
- ('\u{1d552}', '\u{1d6a5}', L), ('\u{1d6a8}', '\u{1d6da}', L), ('\u{1d6db}', '\u{1d6db}', ON),
- ('\u{1d6dc}', '\u{1d714}', L), ('\u{1d715}', '\u{1d715}', ON), ('\u{1d716}', '\u{1d74e}', L),
- ('\u{1d74f}', '\u{1d74f}', ON), ('\u{1d750}', '\u{1d788}', L), ('\u{1d789}', '\u{1d789}', ON),
- ('\u{1d78a}', '\u{1d7c2}', L), ('\u{1d7c3}', '\u{1d7c3}', ON), ('\u{1d7c4}', '\u{1d7cb}', L),
- ('\u{1d7ce}', '\u{1d7ff}', EN), ('\u{1d800}', '\u{1d9ff}', L), ('\u{1da00}', '\u{1da36}', NSM),
- ('\u{1da37}', '\u{1da3a}', L), ('\u{1da3b}', '\u{1da6c}', NSM), ('\u{1da6d}', '\u{1da74}', L),
- ('\u{1da75}', '\u{1da75}', NSM), ('\u{1da76}', '\u{1da83}', L), ('\u{1da84}', '\u{1da84}', NSM),
- ('\u{1da85}', '\u{1da8b}', L), ('\u{1da9b}', '\u{1da9f}', NSM), ('\u{1daa1}', '\u{1daaf}', NSM),
- ('\u{1df00}', '\u{1df1e}', L), ('\u{1e000}', '\u{1e006}', NSM), ('\u{1e008}', '\u{1e018}', NSM),
- ('\u{1e01b}', '\u{1e021}', NSM), ('\u{1e023}', '\u{1e024}', NSM), ('\u{1e026}', '\u{1e02a}',
- NSM), ('\u{1e100}', '\u{1e12c}', L), ('\u{1e130}', '\u{1e136}', NSM), ('\u{1e137}', '\u{1e13d}',
- L), ('\u{1e140}', '\u{1e149}', L), ('\u{1e14e}', '\u{1e14f}', L), ('\u{1e290}', '\u{1e2ad}', L),
- ('\u{1e2ae}', '\u{1e2ae}', NSM), ('\u{1e2c0}', '\u{1e2eb}', L), ('\u{1e2ec}', '\u{1e2ef}', NSM),
- ('\u{1e2f0}', '\u{1e2f9}', L), ('\u{1e2ff}', '\u{1e2ff}', ET), ('\u{1e7e0}', '\u{1e7e6}', L),
- ('\u{1e7e8}', '\u{1e7eb}', L), ('\u{1e7ed}', '\u{1e7ee}', L), ('\u{1e7f0}', '\u{1e7fe}', L),
- ('\u{1e800}', '\u{1e8cf}', R), ('\u{1e8d0}', '\u{1e8d6}', NSM), ('\u{1e8d7}', '\u{1e943}', R),
- ('\u{1e944}', '\u{1e94a}', NSM), ('\u{1e94b}', '\u{1ec70}', R), ('\u{1ec71}', '\u{1ecb4}', AL),
- ('\u{1ecb5}', '\u{1ed00}', R), ('\u{1ed01}', '\u{1ed3d}', AL), ('\u{1ed3e}', '\u{1edff}', R),
- ('\u{1ee00}', '\u{1eeef}', AL), ('\u{1eef0}', '\u{1eef1}', ON), ('\u{1eef2}', '\u{1eeff}', AL),
- ('\u{1ef00}', '\u{1efff}', R), ('\u{1f000}', '\u{1f02b}', ON), ('\u{1f030}', '\u{1f093}', ON),
- ('\u{1f0a0}', '\u{1f0ae}', ON), ('\u{1f0b1}', '\u{1f0bf}', ON), ('\u{1f0c1}', '\u{1f0cf}', ON),
- ('\u{1f0d1}', '\u{1f0f5}', ON), ('\u{1f100}', '\u{1f10a}', EN), ('\u{1f10b}', '\u{1f10f}', ON),
- ('\u{1f110}', '\u{1f12e}', L), ('\u{1f12f}', '\u{1f12f}', ON), ('\u{1f130}', '\u{1f169}', L),
- ('\u{1f16a}', '\u{1f16f}', ON), ('\u{1f170}', '\u{1f1ac}', L), ('\u{1f1ad}', '\u{1f1ad}', ON),
- ('\u{1f1e6}', '\u{1f202}', L), ('\u{1f210}', '\u{1f23b}', L), ('\u{1f240}', '\u{1f248}', L),
- ('\u{1f250}', '\u{1f251}', L), ('\u{1f260}', '\u{1f265}', ON), ('\u{1f300}', '\u{1f6d7}', ON),
- ('\u{1f6dd}', '\u{1f6ec}', ON), ('\u{1f6f0}', '\u{1f6fc}', ON), ('\u{1f700}', '\u{1f773}', ON),
- ('\u{1f780}', '\u{1f7d8}', ON), ('\u{1f7e0}', '\u{1f7eb}', ON), ('\u{1f7f0}', '\u{1f7f0}', ON),
- ('\u{1f800}', '\u{1f80b}', ON), ('\u{1f810}', '\u{1f847}', ON), ('\u{1f850}', '\u{1f859}', ON),
- ('\u{1f860}', '\u{1f887}', ON), ('\u{1f890}', '\u{1f8ad}', ON), ('\u{1f8b0}', '\u{1f8b1}', ON),
- ('\u{1f900}', '\u{1fa53}', ON), ('\u{1fa60}', '\u{1fa6d}', ON), ('\u{1fa70}', '\u{1fa74}', ON),
- ('\u{1fa78}', '\u{1fa7c}', ON), ('\u{1fa80}', '\u{1fa86}', ON), ('\u{1fa90}', '\u{1faac}', ON),
- ('\u{1fab0}', '\u{1faba}', ON), ('\u{1fac0}', '\u{1fac5}', ON), ('\u{1fad0}', '\u{1fad9}', ON),
- ('\u{1fae0}', '\u{1fae7}', ON), ('\u{1faf0}', '\u{1faf6}', ON), ('\u{1fb00}', '\u{1fb92}', ON),
- ('\u{1fb94}', '\u{1fbca}', ON), ('\u{1fbf0}', '\u{1fbf9}', EN), ('\u{20000}', '\u{2a6df}', L),
- ('\u{2a700}', '\u{2b738}', L), ('\u{2b740}', '\u{2b81d}', L), ('\u{2b820}', '\u{2cea1}', L),
- ('\u{2ceb0}', '\u{2ebe0}', L), ('\u{2f800}', '\u{2fa1d}', L), ('\u{30000}', '\u{3134a}', L),
- ('\u{e0001}', '\u{e0001}', BN), ('\u{e0020}', '\u{e007f}', BN), ('\u{e0100}', '\u{e01ef}', NSM),
- ('\u{f0000}', '\u{ffffd}', L), ('\u{100000}', '\u{10fffd}', L)
+ ('\u{1d2c0}', '\u{1d2d3}', L), ('\u{1d2e0}', '\u{1d2f3}', L), ('\u{1d300}', '\u{1d356}', ON),
+ ('\u{1d360}', '\u{1d378}', L), ('\u{1d400}', '\u{1d454}', L), ('\u{1d456}', '\u{1d49c}', L),
+ ('\u{1d49e}', '\u{1d49f}', L), ('\u{1d4a2}', '\u{1d4a2}', L), ('\u{1d4a5}', '\u{1d4a6}', L),
+ ('\u{1d4a9}', '\u{1d4ac}', L), ('\u{1d4ae}', '\u{1d4b9}', L), ('\u{1d4bb}', '\u{1d4bb}', L),
+ ('\u{1d4bd}', '\u{1d4c3}', L), ('\u{1d4c5}', '\u{1d505}', L), ('\u{1d507}', '\u{1d50a}', L),
+ ('\u{1d50d}', '\u{1d514}', L), ('\u{1d516}', '\u{1d51c}', L), ('\u{1d51e}', '\u{1d539}', L),
+ ('\u{1d53b}', '\u{1d53e}', L), ('\u{1d540}', '\u{1d544}', L), ('\u{1d546}', '\u{1d546}', L),
+ ('\u{1d54a}', '\u{1d550}', L), ('\u{1d552}', '\u{1d6a5}', L), ('\u{1d6a8}', '\u{1d6da}', L),
+ ('\u{1d6db}', '\u{1d6db}', ON), ('\u{1d6dc}', '\u{1d714}', L), ('\u{1d715}', '\u{1d715}', ON),
+ ('\u{1d716}', '\u{1d74e}', L), ('\u{1d74f}', '\u{1d74f}', ON), ('\u{1d750}', '\u{1d788}', L),
+ ('\u{1d789}', '\u{1d789}', ON), ('\u{1d78a}', '\u{1d7c2}', L), ('\u{1d7c3}', '\u{1d7c3}', ON),
+ ('\u{1d7c4}', '\u{1d7cb}', L), ('\u{1d7ce}', '\u{1d7ff}', EN), ('\u{1d800}', '\u{1d9ff}', L),
+ ('\u{1da00}', '\u{1da36}', NSM), ('\u{1da37}', '\u{1da3a}', L), ('\u{1da3b}', '\u{1da6c}', NSM),
+ ('\u{1da6d}', '\u{1da74}', L), ('\u{1da75}', '\u{1da75}', NSM), ('\u{1da76}', '\u{1da83}', L),
+ ('\u{1da84}', '\u{1da84}', NSM), ('\u{1da85}', '\u{1da8b}', L), ('\u{1da9b}', '\u{1da9f}', NSM),
+ ('\u{1daa1}', '\u{1daaf}', NSM), ('\u{1df00}', '\u{1df1e}', L), ('\u{1df25}', '\u{1df2a}', L),
+ ('\u{1e000}', '\u{1e006}', NSM), ('\u{1e008}', '\u{1e018}', NSM), ('\u{1e01b}', '\u{1e021}',
+ NSM), ('\u{1e023}', '\u{1e024}', NSM), ('\u{1e026}', '\u{1e02a}', NSM), ('\u{1e030}',
+ '\u{1e06d}', L), ('\u{1e08f}', '\u{1e08f}', NSM), ('\u{1e100}', '\u{1e12c}', L), ('\u{1e130}',
+ '\u{1e136}', NSM), ('\u{1e137}', '\u{1e13d}', L), ('\u{1e140}', '\u{1e149}', L), ('\u{1e14e}',
+ '\u{1e14f}', L), ('\u{1e290}', '\u{1e2ad}', L), ('\u{1e2ae}', '\u{1e2ae}', NSM), ('\u{1e2c0}',
+ '\u{1e2eb}', L), ('\u{1e2ec}', '\u{1e2ef}', NSM), ('\u{1e2f0}', '\u{1e2f9}', L), ('\u{1e2ff}',
+ '\u{1e2ff}', ET), ('\u{1e4d0}', '\u{1e4eb}', L), ('\u{1e4ec}', '\u{1e4ef}', NSM), ('\u{1e4f0}',
+ '\u{1e4f9}', L), ('\u{1e7e0}', '\u{1e7e6}', L), ('\u{1e7e8}', '\u{1e7eb}', L), ('\u{1e7ed}',
+ '\u{1e7ee}', L), ('\u{1e7f0}', '\u{1e7fe}', L), ('\u{1e800}', '\u{1e8cf}', R), ('\u{1e8d0}',
+ '\u{1e8d6}', NSM), ('\u{1e8d7}', '\u{1e943}', R), ('\u{1e944}', '\u{1e94a}', NSM), ('\u{1e94b}',
+ '\u{1ec70}', R), ('\u{1ec71}', '\u{1ecb4}', AL), ('\u{1ecb5}', '\u{1ed00}', R), ('\u{1ed01}',
+ '\u{1ed3d}', AL), ('\u{1ed3e}', '\u{1edff}', R), ('\u{1ee00}', '\u{1eeef}', AL), ('\u{1eef0}',
+ '\u{1eef1}', ON), ('\u{1eef2}', '\u{1eeff}', AL), ('\u{1ef00}', '\u{1efff}', R), ('\u{1f000}',
+ '\u{1f02b}', ON), ('\u{1f030}', '\u{1f093}', ON), ('\u{1f0a0}', '\u{1f0ae}', ON), ('\u{1f0b1}',
+ '\u{1f0bf}', ON), ('\u{1f0c1}', '\u{1f0cf}', ON), ('\u{1f0d1}', '\u{1f0f5}', ON), ('\u{1f100}',
+ '\u{1f10a}', EN), ('\u{1f10b}', '\u{1f10f}', ON), ('\u{1f110}', '\u{1f12e}', L), ('\u{1f12f}',
+ '\u{1f12f}', ON), ('\u{1f130}', '\u{1f169}', L), ('\u{1f16a}', '\u{1f16f}', ON), ('\u{1f170}',
+ '\u{1f1ac}', L), ('\u{1f1ad}', '\u{1f1ad}', ON), ('\u{1f1e6}', '\u{1f202}', L), ('\u{1f210}',
+ '\u{1f23b}', L), ('\u{1f240}', '\u{1f248}', L), ('\u{1f250}', '\u{1f251}', L), ('\u{1f260}',
+ '\u{1f265}', ON), ('\u{1f300}', '\u{1f6d7}', ON), ('\u{1f6dc}', '\u{1f6ec}', ON), ('\u{1f6f0}',
+ '\u{1f6fc}', ON), ('\u{1f700}', '\u{1f776}', ON), ('\u{1f77b}', '\u{1f7d9}', ON), ('\u{1f7e0}',
+ '\u{1f7eb}', ON), ('\u{1f7f0}', '\u{1f7f0}', ON), ('\u{1f800}', '\u{1f80b}', ON), ('\u{1f810}',
+ '\u{1f847}', ON), ('\u{1f850}', '\u{1f859}', ON), ('\u{1f860}', '\u{1f887}', ON), ('\u{1f890}',
+ '\u{1f8ad}', ON), ('\u{1f8b0}', '\u{1f8b1}', ON), ('\u{1f900}', '\u{1fa53}', ON), ('\u{1fa60}',
+ '\u{1fa6d}', ON), ('\u{1fa70}', '\u{1fa7c}', ON), ('\u{1fa80}', '\u{1fa88}', ON), ('\u{1fa90}',
+ '\u{1fabd}', ON), ('\u{1fabf}', '\u{1fac5}', ON), ('\u{1face}', '\u{1fadb}', ON), ('\u{1fae0}',
+ '\u{1fae8}', ON), ('\u{1faf0}', '\u{1faf8}', ON), ('\u{1fb00}', '\u{1fb92}', ON), ('\u{1fb94}',
+ '\u{1fbca}', ON), ('\u{1fbf0}', '\u{1fbf9}', EN), ('\u{20000}', '\u{2a6df}', L), ('\u{2a700}',
+ '\u{2b739}', L), ('\u{2b740}', '\u{2b81d}', L), ('\u{2b820}', '\u{2cea1}', L), ('\u{2ceb0}',
+ '\u{2ebe0}', L), ('\u{2f800}', '\u{2fa1d}', L), ('\u{30000}', '\u{3134a}', L), ('\u{31350}',
+ '\u{323af}', L), ('\u{e0001}', '\u{e0001}', BN), ('\u{e0020}', '\u{e007f}', BN), ('\u{e0100}',
+ '\u{e01ef}', NSM), ('\u{f0000}', '\u{ffffd}', L), ('\u{100000}', '\u{10fffd}', L)
+];
+
+pub const bidi_pairs_table: &'static [(char, char, Option<char>)] = &[
+ ('\u{28}', '\u{29}', None), ('\u{5b}', '\u{5d}', None), ('\u{7b}', '\u{7d}', None), ('\u{f3a}',
+ '\u{f3b}', None), ('\u{f3c}', '\u{f3d}', None), ('\u{169b}', '\u{169c}', None), ('\u{2045}',
+ '\u{2046}', None), ('\u{207d}', '\u{207e}', None), ('\u{208d}', '\u{208e}', None), ('\u{2308}',
+ '\u{2309}', None), ('\u{230a}', '\u{230b}', None), ('\u{2329}', '\u{232a}', Some('\u{3008}')),
+ ('\u{2768}', '\u{2769}', None), ('\u{276a}', '\u{276b}', None), ('\u{276c}', '\u{276d}', None),
+ ('\u{276e}', '\u{276f}', None), ('\u{2770}', '\u{2771}', None), ('\u{2772}', '\u{2773}', None),
+ ('\u{2774}', '\u{2775}', None), ('\u{27c5}', '\u{27c6}', None), ('\u{27e6}', '\u{27e7}', None),
+ ('\u{27e8}', '\u{27e9}', None), ('\u{27ea}', '\u{27eb}', None), ('\u{27ec}', '\u{27ed}', None),
+ ('\u{27ee}', '\u{27ef}', None), ('\u{2983}', '\u{2984}', None), ('\u{2985}', '\u{2986}', None),
+ ('\u{2987}', '\u{2988}', None), ('\u{2989}', '\u{298a}', None), ('\u{298b}', '\u{298c}', None),
+ ('\u{298d}', '\u{2990}', None), ('\u{298f}', '\u{298e}', None), ('\u{2991}', '\u{2992}', None),
+ ('\u{2993}', '\u{2994}', None), ('\u{2995}', '\u{2996}', None), ('\u{2997}', '\u{2998}', None),
+ ('\u{29d8}', '\u{29d9}', None), ('\u{29da}', '\u{29db}', None), ('\u{29fc}', '\u{29fd}', None),
+ ('\u{2e22}', '\u{2e23}', None), ('\u{2e24}', '\u{2e25}', None), ('\u{2e26}', '\u{2e27}', None),
+ ('\u{2e28}', '\u{2e29}', None), ('\u{2e55}', '\u{2e56}', None), ('\u{2e57}', '\u{2e58}', None),
+ ('\u{2e59}', '\u{2e5a}', None), ('\u{2e5b}', '\u{2e5c}', None), ('\u{3008}', '\u{3009}', None),
+ ('\u{300a}', '\u{300b}', None), ('\u{300c}', '\u{300d}', None), ('\u{300e}', '\u{300f}', None),
+ ('\u{3010}', '\u{3011}', None), ('\u{3014}', '\u{3015}', None), ('\u{3016}', '\u{3017}', None),
+ ('\u{3018}', '\u{3019}', None), ('\u{301a}', '\u{301b}', None), ('\u{fe59}', '\u{fe5a}', None),
+ ('\u{fe5b}', '\u{fe5c}', None), ('\u{fe5d}', '\u{fe5e}', None), ('\u{ff08}', '\u{ff09}', None),
+ ('\u{ff3b}', '\u{ff3d}', None), ('\u{ff5b}', '\u{ff5d}', None), ('\u{ff5f}', '\u{ff60}', None),
+ ('\u{ff62}', '\u{ff63}', None)
];
diff --git a/vendor/unicode-bidi/src/data_source.rs b/vendor/unicode-bidi/src/data_source.rs
index 3958a255e..319ad53b0 100644
--- a/vendor/unicode-bidi/src/data_source.rs
+++ b/vendor/unicode-bidi/src/data_source.rs
@@ -9,8 +9,38 @@
use crate::BidiClass;
+/// This is the return value of [`BidiDataSource::bidi_matched_opening_bracket()`].
+///
+/// It represents the matching *normalized* opening bracket for a given bracket in a bracket pair,
+/// and whether or not that bracket is opening.
+#[derive(Debug, Copy, Clone)]
+pub struct BidiMatchedOpeningBracket {
+ /// The corresponding opening bracket in this bracket pair, normalized
+ ///
+ /// In case of opening brackets, this will be the bracket itself, except for when the bracket
+ /// is not normalized, in which case it will be the normalized form.
+ pub opening: char,
+ /// Whether or not the requested bracket was an opening bracket. True for opening
+ pub is_open: bool,
+}
+
/// This trait abstracts over a data source that is able to produce the Unicode Bidi class for a given
/// character
pub trait BidiDataSource {
fn bidi_class(&self, c: char) -> BidiClass;
+ /// If this character is a bracket according to BidiBrackets.txt,
+ /// return the corresponding *normalized* *opening bracket* of the pair,
+ /// and whether or not it itself is an opening bracket.
+ ///
+ /// This effectively buckets brackets into equivalence classes keyed on the
+ /// normalized opening bracket.
+ ///
+ /// The default implementation will pull in a small amount of hardcoded data,
+ /// regardless of the `hardcoded-data` feature. This is in part for convenience
+ /// (since this data is small and changes less often), and in part so that this method can be
+ /// added without needing a breaking version bump.
+ /// Override this method in your custom data source to prevent the use of hardcoded data.
+ fn bidi_matched_opening_bracket(&self, c: char) -> Option<BidiMatchedOpeningBracket> {
+ crate::char_data::bidi_matched_opening_bracket(c)
+ }
}
diff --git a/vendor/unicode-bidi/src/explicit.rs b/vendor/unicode-bidi/src/explicit.rs
index e9d579fd6..a9b13e89c 100644
--- a/vendor/unicode-bidi/src/explicit.rs
+++ b/vendor/unicode-bidi/src/explicit.rs
@@ -47,13 +47,17 @@ pub fn compute(
RLE | LRE | RLO | LRO | RLI | LRI | FSI => {
let last_level = stack.last().level;
+ // <https://www.unicode.org/reports/tr9/#Retaining_Explicit_Formatting_Characters>
+ levels[i] = last_level;
+
// X5a-X5c: Isolate initiators get the level of the last entry on the stack.
let is_isolate = match original_classes[i] {
RLI | LRI | FSI => true,
_ => false,
};
if is_isolate {
- levels[i] = last_level;
+ // Redundant due to "Retaining explicit formatting characters" step.
+ // levels[i] = last_level;
match stack.last().status {
OverrideStatus::RTL => processing_classes[i] = R,
OverrideStatus::LTR => processing_classes[i] = L,
@@ -90,6 +94,13 @@ pub fn compute(
} else if overflow_isolate_count == 0 {
overflow_embedding_count += 1;
}
+
+ if !is_isolate {
+ // X9 +
+ // <https://www.unicode.org/reports/tr9/#Retaining_Explicit_Formatting_Characters>
+ // (PDF handled below)
+ processing_classes[i] = BN;
+ }
}
// <http://www.unicode.org/reports/tr9/#X6a>
@@ -123,31 +134,34 @@ pub fn compute(
// <http://www.unicode.org/reports/tr9/#X7>
PDF => {
if overflow_isolate_count > 0 {
- continue;
- }
- if overflow_embedding_count > 0 {
+ // do nothing
+ } else if overflow_embedding_count > 0 {
overflow_embedding_count -= 1;
- continue;
- }
- if stack.last().status != OverrideStatus::Isolate && stack.vec.len() >= 2 {
+ } else if stack.last().status != OverrideStatus::Isolate && stack.vec.len() >= 2 {
stack.vec.pop();
}
- // The spec doesn't explicitly mention this step, but it is necessary.
- // See the reference implementations for comparison.
+ // <https://www.unicode.org/reports/tr9/#Retaining_Explicit_Formatting_Characters>
levels[i] = stack.last().level;
+ // X9 part of retaining explicit formatting characters.
+ processing_classes[i] = BN;
}
- // Nothing
- B | BN => {}
+ // Nothing.
+ // BN case moved down to X6, see <https://www.unicode.org/reports/tr9/#Retaining_Explicit_Formatting_Characters>
+ B => {}
// <http://www.unicode.org/reports/tr9/#X6>
_ => {
let last = stack.last();
levels[i] = last.level;
- match last.status {
- OverrideStatus::RTL => processing_classes[i] = R,
- OverrideStatus::LTR => processing_classes[i] = L,
- _ => {}
+ // This condition is not in the spec, but I am pretty sure that is a spec bug.
+ // https://www.unicode.org/L2/L2023/23014-amd-to-uax9.pdf
+ if original_classes[i] != BN {
+ match last.status {
+ OverrideStatus::RTL => processing_classes[i] = R,
+ OverrideStatus::LTR => processing_classes[i] = L,
+ _ => {}
+ }
}
}
}
diff --git a/vendor/unicode-bidi/src/implicit.rs b/vendor/unicode-bidi/src/implicit.rs
index bf37f17e6..294af7cbd 100644
--- a/vendor/unicode-bidi/src/implicit.rs
+++ b/vendor/unicode-bidi/src/implicit.rs
@@ -14,104 +14,213 @@ use core::cmp::max;
use super::char_data::BidiClass::{self, *};
use super::level::Level;
-use super::prepare::{not_removed_by_x9, removed_by_x9, IsolatingRunSequence, LevelRun};
+use super::prepare::{not_removed_by_x9, removed_by_x9, IsolatingRunSequence};
+use super::BidiDataSource;
/// 3.3.4 Resolving Weak Types
///
/// <http://www.unicode.org/reports/tr9/#Resolving_Weak_Types>
#[cfg_attr(feature = "flame_it", flamer::flame)]
-pub fn resolve_weak(sequence: &IsolatingRunSequence, processing_classes: &mut [BidiClass]) {
- // FIXME (#8): This function applies steps W1-W6 in a single pass. This can produce
- // incorrect results in cases where a "later" rule changes the value of `prev_class` seen
- // by an "earlier" rule. We should either split this into separate passes, or preserve
- // extra state so each rule can see the correct previous class.
-
- // FIXME: Also, this could be the cause of increased failure for using longer-UTF-8 chars in
- // conformance tests, like BidiTest:69635 (AL ET EN)
+pub fn resolve_weak(
+ text: &str,
+ sequence: &IsolatingRunSequence,
+ processing_classes: &mut [BidiClass],
+) {
+ // Note: The spec treats these steps as individual passes that are applied one after the other
+ // on the entire IsolatingRunSequence at once. We instead collapse it into a single iteration,
+ // which is straightforward for rules that are based on the state of the current character, but not
+ // for rules that care about surrounding characters. To deal with them, we retain additional state
+ // about previous character classes that may have since been changed by later rules.
- let mut prev_class = sequence.sos;
+ // The previous class for the purposes of rule W4/W6, not tracking changes made after or during W4.
+ let mut prev_class_before_w4 = sequence.sos;
+ // The previous class for the purposes of rule W5.
+ let mut prev_class_before_w5 = sequence.sos;
+ // The previous class for the purposes of rule W1, not tracking changes from any other rules.
+ let mut prev_class_before_w1 = sequence.sos;
let mut last_strong_is_al = false;
let mut et_run_indices = Vec::new(); // for W5
+ let mut bn_run_indices = Vec::new(); // for W5 + <https://www.unicode.org/reports/tr9/#Retaining_Explicit_Formatting_Characters>
+
+ for (run_index, level_run) in sequence.runs.iter().enumerate() {
+ for i in &mut level_run.clone() {
+ if processing_classes[i] == BN {
+ // <https://www.unicode.org/reports/tr9/#Retaining_Explicit_Formatting_Characters>
+ // Keeps track of bn runs for W5 in case we see an ET.
+ bn_run_indices.push(i);
+ // BNs aren't real, skip over them.
+ continue;
+ }
+
+ // Store the processing class of all rules before W2/W1.
+ // Used to keep track of the last strong character for W2. W3 is able to insert new strong
+ // characters, so we don't want to be misled by it.
+ let mut w2_processing_class = processing_classes[i];
- // Like sequence.runs.iter().flat_map(Clone::clone), but make indices itself clonable.
- fn id(x: LevelRun) -> LevelRun {
- x
- }
- let mut indices = sequence
- .runs
- .iter()
- .cloned()
- .flat_map(id as fn(LevelRun) -> LevelRun);
-
- while let Some(i) = indices.next() {
- match processing_classes[i] {
// <http://www.unicode.org/reports/tr9/#W1>
- NSM => {
- processing_classes[i] = match prev_class {
+ //
+
+ if processing_classes[i] == NSM {
+ processing_classes[i] = match prev_class_before_w1 {
RLI | LRI | FSI | PDI => ON,
- _ => prev_class,
+ _ => prev_class_before_w1,
};
+ // W1 occurs before W2, update this.
+ w2_processing_class = processing_classes[i];
}
- EN => {
- if last_strong_is_al {
- // W2. If previous strong char was AL, change EN to AN.
- processing_classes[i] = AN;
- } else {
+
+ prev_class_before_w1 = processing_classes[i];
+
+ // <http://www.unicode.org/reports/tr9/#W2>
+ // <http://www.unicode.org/reports/tr9/#W3>
+ //
+ match processing_classes[i] {
+ EN => {
+ if last_strong_is_al {
+ // W2. If previous strong char was AL, change EN to AN.
+ processing_classes[i] = AN;
+ }
+ }
+ // W3.
+ AL => processing_classes[i] = R,
+ _ => {}
+ }
+
+ // update last_strong_is_al.
+ match w2_processing_class {
+ L | R => {
+ last_strong_is_al = false;
+ }
+ AL => {
+ last_strong_is_al = true;
+ }
+ _ => {}
+ }
+
+ let class_before_w456 = processing_classes[i];
+
+ // <http://www.unicode.org/reports/tr9/#W4>
+ // <http://www.unicode.org/reports/tr9/#W5>
+ // <http://www.unicode.org/reports/tr9/#W6> (separators only)
+ // (see below for W6 terminator code)
+ //
+ match processing_classes[i] {
+ // <http://www.unicode.org/reports/tr9/#W6>
+ EN => {
// W5. If a run of ETs is adjacent to an EN, change the ETs to EN.
for j in &et_run_indices {
processing_classes[*j] = EN;
}
et_run_indices.clear();
}
- }
- // <http://www.unicode.org/reports/tr9/#W3>
- AL => processing_classes[i] = R,
- // <http://www.unicode.org/reports/tr9/#W4>
- ES | CS => {
- let next_class = indices
- .clone()
- .map(|j| processing_classes[j])
- .find(not_removed_by_x9)
- .unwrap_or(sequence.eos);
- processing_classes[i] = match (prev_class, processing_classes[i], next_class) {
- (EN, ES, EN) | (EN, CS, EN) => EN,
- (AN, CS, AN) => AN,
- (_, _, _) => ON,
+ // <http://www.unicode.org/reports/tr9/#W4>
+ // <http://www.unicode.org/reports/tr9/#W6>
+ ES | CS => {
+ // See https://github.com/servo/unicode-bidi/issues/86 for improving this.
+ // We want to make sure we check the correct next character by skipping past the rest
+ // of this one.
+ if let Some(ch) = text.get(i..).and_then(|s| s.chars().next()) {
+ let mut next_class = sequence
+ .iter_forwards_from(i + ch.len_utf8(), run_index)
+ .map(|j| processing_classes[j])
+ // <https://www.unicode.org/reports/tr9/#Retaining_Explicit_Formatting_Characters>
+ .find(not_removed_by_x9)
+ .unwrap_or(sequence.eos);
+ if next_class == EN && last_strong_is_al {
+ // Apply W2 to next_class. We know that last_strong_is_al
+ // has no chance of changing on this character so we can still assume its value
+ // will be the same by the time we get to it.
+ next_class = AN;
+ }
+ processing_classes[i] =
+ match (prev_class_before_w4, processing_classes[i], next_class) {
+ // W4
+ (EN, ES, EN) | (EN, CS, EN) => EN,
+ // W4
+ (AN, CS, AN) => AN,
+ // W6 (separators only)
+ (_, _, _) => ON,
+ };
+
+ // W6 + <https://www.unicode.org/reports/tr9/#Retaining_Explicit_Formatting_Characters>
+ // We have to do this before W5 gets its grubby hands on these characters and thinks
+ // they're part of an ET run.
+ // We check for ON to ensure that we had hit the W6 branch above, since this `ES | CS` match
+ // arm handles both W4 and W6.
+ if processing_classes[i] == ON {
+ for idx in sequence.iter_backwards_from(i, run_index) {
+ let class = &mut processing_classes[idx];
+ if *class != BN {
+ break;
+ }
+ *class = ON;
+ }
+ for idx in sequence.iter_forwards_from(i + ch.len_utf8(), run_index) {
+ let class = &mut processing_classes[idx];
+ if *class != BN {
+ break;
+ }
+ *class = ON;
+ }
+ }
+ } else {
+ // We're in the middle of a character, copy over work done for previous bytes
+ // since it's going to be the same answer.
+ processing_classes[i] = processing_classes[i - 1];
+ }
}
- }
- // <http://www.unicode.org/reports/tr9/#W5>
- ET => {
- match prev_class {
- EN => processing_classes[i] = EN,
- _ => et_run_indices.push(i), // In case this is followed by an EN.
+ // <http://www.unicode.org/reports/tr9/#W5>
+ ET => {
+ match prev_class_before_w5 {
+ EN => processing_classes[i] = EN,
+ _ => {
+ // <https://www.unicode.org/reports/tr9/#Retaining_Explicit_Formatting_Characters>
+ // If there was a BN run before this, that's now a part of this ET run.
+ et_run_indices.extend(&bn_run_indices);
+
+ // In case this is followed by an EN.
+ et_run_indices.push(i);
+ }
+ }
}
+ _ => {}
}
- class => {
- if removed_by_x9(class) {
- continue;
+
+ // Common loop iteration code
+ //
+
+ // <https://www.unicode.org/reports/tr9/#Retaining_Explicit_Formatting_Characters>
+ // BN runs would have already continued the loop, clear them before we get to the next one.
+ bn_run_indices.clear();
+
+ // W6 above only deals with separators, so it doesn't change anything W5 cares about,
+ // so we still can update this after running that part of W6.
+ prev_class_before_w5 = processing_classes[i];
+
+ // <http://www.unicode.org/reports/tr9/#W6> (terminators only)
+ // (see above for W6 separator code)
+ //
+ if prev_class_before_w5 != ET {
+ // W6. If we didn't find an adjacent EN, turn any ETs into ON instead.
+ for j in &et_run_indices {
+ processing_classes[*j] = ON;
}
+ et_run_indices.clear();
}
- }
- prev_class = processing_classes[i];
- match prev_class {
- L | R => {
- last_strong_is_al = false;
- }
- AL => {
- last_strong_is_al = true;
- }
- _ => {}
- }
- if prev_class != ET {
- // W6. If we didn't find an adjacent EN, turn any ETs into ON instead.
- for j in &et_run_indices {
- processing_classes[*j] = ON;
- }
- et_run_indices.clear();
+ // We stashed this before W4/5/6 could get their grubby hands on it, and it's not
+ // used in the W6 terminator code below so we can update it now.
+ prev_class_before_w4 = class_before_w456;
}
}
+ // Rerun this check in case we ended with a sequence of BNs (i.e., we'd never
+ // hit the end of the for loop above).
+ // W6. If we didn't find an adjacent EN, turn any ETs into ON instead.
+ for j in &et_run_indices {
+ processing_classes[*j] = ON;
+ }
+ et_run_indices.clear();
// W7. If the previous strong char was L, change EN to L.
let mut last_strong_is_l = sequence.sos == L;
@@ -127,6 +236,8 @@ pub fn resolve_weak(sequence: &IsolatingRunSequence, processing_classes: &mut [B
R | AL => {
last_strong_is_l = false;
}
+ // <https://www.unicode.org/reports/tr9/#Retaining_Explicit_Formatting_Characters>
+ // Already scanning past BN here.
_ => {}
}
}
@@ -137,22 +248,172 @@ pub fn resolve_weak(sequence: &IsolatingRunSequence, processing_classes: &mut [B
///
/// <http://www.unicode.org/reports/tr9/#Resolving_Neutral_Types>
#[cfg_attr(feature = "flame_it", flamer::flame)]
-pub fn resolve_neutral(
+pub fn resolve_neutral<D: BidiDataSource>(
+ text: &str,
+ data_source: &D,
sequence: &IsolatingRunSequence,
levels: &[Level],
+ original_classes: &[BidiClass],
processing_classes: &mut [BidiClass],
) {
+ // e = embedding direction
let e: BidiClass = levels[sequence.runs[0].start].bidi_class();
+ let not_e = if e == BidiClass::L {
+ BidiClass::R
+ } else {
+ BidiClass::L
+ };
+ // N0. Process bracket pairs.
+
+ // > Identify the bracket pairs in the current isolating run sequence according to BD16.
+ // We use processing_classes, not original_classes, due to BD14/BD15
+ let bracket_pairs = identify_bracket_pairs(text, data_source, sequence, processing_classes);
+
+ // > For each bracket-pair element in the list of pairs of text positions
+ //
+ // Note: Rust ranges are interpreted as [start..end), be careful using `pair` directly
+ // for indexing as it will include the opening bracket pair but not the closing one.
+ for pair in bracket_pairs {
+ #[cfg(feature = "std")]
+ debug_assert!(
+ pair.start < processing_classes.len(),
+ "identify_bracket_pairs returned a range that is out of bounds!"
+ );
+ #[cfg(feature = "std")]
+ debug_assert!(
+ pair.end < processing_classes.len(),
+ "identify_bracket_pairs returned a range that is out of bounds!"
+ );
+ let mut found_e = false;
+ let mut found_not_e = false;
+ let mut class_to_set = None;
+
+ let start_len_utf8 = text[pair.start..].chars().next().unwrap().len_utf8();
+ // > Inspect the bidirectional types of the characters enclosed within the bracket pair.
+ //
+ // `pair` is [start, end) so we will end up processing the opening character but not the closing one.
+ //
+ for enclosed_i in sequence.iter_forwards_from(pair.start + start_len_utf8, pair.start_run) {
+ if enclosed_i >= pair.end {
+ #[cfg(feature = "std")]
+ debug_assert!(
+ enclosed_i == pair.end,
+ "If we skipped past this, the iterator is broken"
+ );
+ break;
+ }
+ let class = processing_classes[enclosed_i];
+ if class == e {
+ found_e = true;
+ } else if class == not_e {
+ found_not_e = true;
+ } else if class == BidiClass::EN || class == BidiClass::AN {
+ // > Within this scope, bidirectional types EN and AN are treated as R.
+ if e == BidiClass::L {
+ found_not_e = true;
+ } else {
+ found_e = true;
+ }
+ }
+
+ // If we have found a character with the class of the embedding direction
+ // we can bail early.
+ if found_e {
+ break;
+ }
+ }
+ // > If any strong type (either L or R) matching the embedding direction is found
+ if found_e {
+ // > .. set the type for both brackets in the pair to match the embedding direction
+ class_to_set = Some(e);
+ // > Otherwise, if there is a strong type it must be opposite the embedding direction
+ } else if found_not_e {
+ // > Therefore, test for an established context with a preceding strong type by
+ // > checking backwards before the opening paired bracket
+ // > until the first strong type (L, R, or sos) is found.
+ // (see note above about processing_classes and character boundaries)
+ let mut previous_strong = sequence
+ .iter_backwards_from(pair.start, pair.start_run)
+ .map(|i| processing_classes[i])
+ .find(|class| {
+ *class == BidiClass::L
+ || *class == BidiClass::R
+ || *class == BidiClass::EN
+ || *class == BidiClass::AN
+ })
+ .unwrap_or(sequence.sos);
+
+ // > Within this scope, bidirectional types EN and AN are treated as R.
+ if previous_strong == BidiClass::EN || previous_strong == BidiClass::AN {
+ previous_strong = BidiClass::R;
+ }
+
+ // > If the preceding strong type is also opposite the embedding direction,
+ // > context is established,
+ // > so set the type for both brackets in the pair to that direction.
+ // AND
+ // > Otherwise set the type for both brackets in the pair to the embedding direction.
+ // > Either way it gets set to previous_strong
+ //
+ // Both branches amount to setting the type to the strong type.
+ class_to_set = Some(previous_strong);
+ }
+
+ if let Some(class_to_set) = class_to_set {
+ // Update all processing classes corresponding to the start and end elements, as requested.
+ // We should include all bytes of the character, not the first one.
+ let end_len_utf8 = text[pair.end..].chars().next().unwrap().len_utf8();
+ for class in &mut processing_classes[pair.start..pair.start + start_len_utf8] {
+ *class = class_to_set;
+ }
+ for class in &mut processing_classes[pair.end..pair.end + end_len_utf8] {
+ *class = class_to_set;
+ }
+ // <https://www.unicode.org/reports/tr9/#Retaining_Explicit_Formatting_Characters>
+ for idx in sequence.iter_backwards_from(pair.start, pair.start_run) {
+ let class = &mut processing_classes[idx];
+ if *class != BN {
+ break;
+ }
+ *class = class_to_set;
+ }
+ // > Any number of characters that had original bidirectional character type NSM prior to the application of
+ // > W1 that immediately follow a paired bracket which changed to L or R under N0 should change to match the type of their preceding bracket.
+
+ // This rule deals with sequences of NSMs, so we can just update them all at once, we don't need to worry
+ // about character boundaries. We do need to be careful to skip the full set of bytes for the parentheses characters.
+ let nsm_start = pair.start + start_len_utf8;
+ for idx in sequence.iter_forwards_from(nsm_start, pair.start_run) {
+ let class = original_classes[idx];
+ if class == BidiClass::NSM || processing_classes[idx] == BN {
+ processing_classes[idx] = class_to_set;
+ } else {
+ break;
+ }
+ }
+ let nsm_end = pair.end + end_len_utf8;
+ for idx in sequence.iter_forwards_from(nsm_end, pair.end_run) {
+ let class = original_classes[idx];
+ if class == BidiClass::NSM || processing_classes[idx] == BN {
+ processing_classes[idx] = class_to_set;
+ } else {
+ break;
+ }
+ }
+ }
+ // > Otherwise, there are no strong types within the bracket pair
+ // > Therefore, do not set the type for that bracket pair
+ }
+
+ // N1 and N2.
+ // Indices of every byte in this isolating run sequence
let mut indices = sequence.runs.iter().flat_map(Clone::clone);
let mut prev_class = sequence.sos;
-
while let Some(mut i) = indices.next() {
- // N0. Process bracket pairs.
- // TODO
-
// Process sequences of NI characters.
let mut ni_run = Vec::new();
- if is_NI(processing_classes[i]) {
+ // The BN is for <https://www.unicode.org/reports/tr9/#Retaining_Explicit_Formatting_Characters>
+ if is_NI(processing_classes[i]) || processing_classes[i] == BN {
// Consume a run of consecutive NI characters.
ni_run.push(i);
let mut next_class;
@@ -160,11 +421,9 @@ pub fn resolve_neutral(
match indices.next() {
Some(j) => {
i = j;
- if removed_by_x9(processing_classes[i]) {
- continue;
- }
next_class = processing_classes[j];
- if is_NI(next_class) {
+ // The BN is for <https://www.unicode.org/reports/tr9/#Retaining_Explicit_Formatting_Characters>
+ if is_NI(next_class) || next_class == BN {
ni_run.push(i);
} else {
break;
@@ -176,7 +435,6 @@ pub fn resolve_neutral(
}
};
}
-
// N1-N2.
//
// <http://www.unicode.org/reports/tr9/#N1>
@@ -203,6 +461,105 @@ pub fn resolve_neutral(
}
}
+struct BracketPair {
+ /// The text-relative index of the opening bracket.
+ start: usize,
+ /// The text-relative index of the closing bracket.
+ end: usize,
+ /// The index of the run (in the run sequence) that the opening bracket is in.
+ start_run: usize,
+ /// The index of the run (in the run sequence) that the closing bracket is in.
+ end_run: usize,
+}
+/// 3.1.3 Identifying Bracket Pairs
+///
+/// Returns all paired brackets in the source, as indices into the
+/// text source.
+///
+/// <https://www.unicode.org/reports/tr9/#BD16>
+fn identify_bracket_pairs<D: BidiDataSource>(
+ text: &str,
+ data_source: &D,
+ run_sequence: &IsolatingRunSequence,
+ original_classes: &[BidiClass],
+) -> Vec<BracketPair> {
+ let mut ret = vec![];
+ let mut stack = vec![];
+
+ for (run_index, level_run) in run_sequence.runs.iter().enumerate() {
+ let slice = if let Some(slice) = text.get(level_run.clone()) {
+ slice
+ } else {
+ #[cfg(feature = "std")]
+ std::debug_assert!(
+ false,
+ "Found broken indices in level run: found indices {}..{} for string of length {}",
+ level_run.start,
+ level_run.end,
+ text.len()
+ );
+ return ret;
+ };
+
+ for (i, ch) in slice.char_indices() {
+ let actual_index = level_run.start + i;
+ // All paren characters are ON.
+ // From BidiBrackets.txt:
+ // > The Unicode property value stability policy guarantees that characters
+ // > which have bpt=o or bpt=c also have bc=ON and Bidi_M=Y
+ if original_classes[level_run.start + i] != BidiClass::ON {
+ continue;
+ }
+
+ if let Some(matched) = data_source.bidi_matched_opening_bracket(ch) {
+ if matched.is_open {
+ // > If an opening paired bracket is found ...
+
+ // > ... and there is no room in the stack,
+ // > stop processing BD16 for the remainder of the isolating run sequence.
+ if stack.len() >= 63 {
+ break;
+ }
+ // > ... push its Bidi_Paired_Bracket property value and its text position onto the stack
+ stack.push((matched.opening, actual_index, run_index))
+ } else {
+ // > If a closing paired bracket is found, do the following
+
+ // > Declare a variable that holds a reference to the current stack element
+ // > and initialize it with the top element of the stack.
+ // AND
+ // > Else, if the current stack element is not at the bottom of the stack
+ for (stack_index, element) in stack.iter().enumerate().rev() {
+ // > Compare the closing paired bracket being inspected or its canonical
+ // > equivalent to the bracket in the current stack element.
+ if element.0 == matched.opening {
+ // > If the values match, meaning the two characters form a bracket pair, then
+
+ // > Append the text position in the current stack element together with the
+ // > text position of the closing paired bracket to the list.
+ let pair = BracketPair {
+ start: element.1,
+ end: actual_index,
+ start_run: element.2,
+ end_run: run_index,
+ };
+ ret.push(pair);
+
+ // > Pop the stack through the current stack element inclusively.
+ stack.truncate(stack_index);
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+ // > Sort the list of pairs of text positions in ascending order based on
+ // > the text position of the opening paired bracket.
+ ret.sort_by_key(|r| r.start);
+ ret
+}
+
/// 3.3.6 Resolving Implicit Levels
///
/// Returns the maximum embedding level in the paragraph.
@@ -211,7 +568,6 @@ pub fn resolve_neutral(
#[cfg_attr(feature = "flame_it", flamer::flame)]
pub fn resolve_levels(original_classes: &[BidiClass], levels: &mut [Level]) -> Level {
let mut max_level = Level::ltr();
-
assert_eq!(original_classes.len(), levels.len());
for i in 0..levels.len() {
match (levels[i].is_rtl(), original_classes[i]) {
@@ -219,6 +575,7 @@ pub fn resolve_levels(original_classes: &[BidiClass], levels: &mut [Level]) -> L
(false, R) | (true, L) | (true, EN) | (true, AN) => {
levels[i].raise(1).expect("Level number error")
}
+ // <https://www.unicode.org/reports/tr9/#Retaining_Explicit_Formatting_Characters> handled here
(_, _) => {}
}
max_level = max(max_level, levels[i]);
diff --git a/vendor/unicode-bidi/src/lib.rs b/vendor/unicode-bidi/src/lib.rs
index bda9dd8ec..81d4fb5f5 100644
--- a/vendor/unicode-bidi/src/lib.rs
+++ b/vendor/unicode-bidi/src/lib.rs
@@ -354,8 +354,15 @@ impl<'text> BidiInfo<'text> {
let sequences = prepare::isolating_run_sequences(para.level, original_classes, levels);
for sequence in &sequences {
- implicit::resolve_weak(sequence, processing_classes);
- implicit::resolve_neutral(sequence, levels, processing_classes);
+ implicit::resolve_weak(text, sequence, processing_classes);
+ implicit::resolve_neutral(
+ text,
+ data_source,
+ sequence,
+ levels,
+ original_classes,
+ processing_classes,
+ );
}
implicit::resolve_levels(processing_classes, levels);
@@ -411,6 +418,71 @@ impl<'text> BidiInfo<'text> {
result.into()
}
+ /// Reorders pre-calculated levels of a sequence of characters.
+ ///
+ /// NOTE: This is a convenience method that does not use a `Paragraph` object. It is
+ /// intended to be used when an application has determined the levels of the objects (character sequences)
+ /// and just needs to have them reordered.
+ ///
+ /// the index map will result in `indexMap[visualIndex]==logicalIndex`.
+ ///
+ /// # # Example
+ /// ```
+ /// use unicode_bidi::BidiInfo;
+ /// use unicode_bidi::Level;
+ ///
+ /// let l0 = Level::from(0);
+ /// let l1 = Level::from(1);
+ /// let l2 = Level::from(2);
+ ///
+ /// let levels = vec![l0, l0, l0, l0];
+ /// let index_map = BidiInfo::reorder_visual(&levels);
+ /// assert_eq!(levels.len(), index_map.len());
+ /// assert_eq!(index_map, [0, 1, 2, 3]);
+ ///
+ /// let levels: Vec<Level> = vec![l0, l0, l0, l1, l1, l1, l2, l2];
+ /// let index_map = BidiInfo::reorder_visual(&levels);
+ /// assert_eq!(levels.len(), index_map.len());
+ /// assert_eq!(index_map, [0, 1, 2, 5, 4, 3, 6, 7]);
+ /// ```
+ pub fn reorder_visual(levels: &[Level]) -> Vec<usize> {
+ // Gets the next range
+ fn next_range(levels: &[level::Level], start_index: usize) -> Range<usize> {
+ if levels.is_empty() || start_index >= levels.len() {
+ return start_index..start_index;
+ }
+
+ let mut end_index = start_index + 1;
+ while end_index < levels.len() {
+ if levels[start_index] != levels[end_index] {
+ return start_index..end_index;
+ }
+ end_index += 1;
+ }
+
+ start_index..end_index
+ }
+
+ if levels.is_empty() {
+ return vec![];
+ }
+ let mut result: Vec<usize> = (0..levels.len()).collect();
+
+ let mut range: Range<usize> = 0..0;
+ loop {
+ range = next_range(levels, range.end);
+ if levels[range.start].is_rtl() {
+ result[range.clone()].reverse();
+ }
+
+ if range.end >= levels.len() {
+ break;
+ }
+ }
+
+ result
+ }
+
/// Find the level runs within a line and return them in visual order.
///
/// `line` is a range of bytes indices within `levels`.
@@ -434,10 +506,9 @@ impl<'text> BidiInfo<'text> {
let line_str: &str = &self.text[line.clone()];
let mut reset_from: Option<usize> = Some(0);
let mut reset_to: Option<usize> = None;
+ let mut prev_level = para.level;
for (i, c) in line_str.char_indices() {
match line_classes[i] {
- // Ignored by X9
- RLE | LRE | RLO | LRO | PDF | BN => {}
// Segment separator, Paragraph separator
B | S => {
assert_eq!(reset_to, None);
@@ -452,6 +523,15 @@ impl<'text> BidiInfo<'text> {
reset_from = Some(i);
}
}
+ // <https://www.unicode.org/reports/tr9/#Retaining_Explicit_Formatting_Characters>
+ // same as above + set the level
+ RLE | LRE | RLO | LRO | PDF | BN => {
+ if reset_from == None {
+ reset_from = Some(i);
+ }
+ // also set the level to previous
+ line_levels[i] = prev_level;
+ }
_ => {
reset_from = None;
}
@@ -463,6 +543,7 @@ impl<'text> BidiInfo<'text> {
reset_from = None;
reset_to = None;
}
+ prev_level = line_levels[i];
}
if let Some(from) = reset_from {
for level in &mut line_levels[from..] {
@@ -874,7 +955,7 @@ mod tests {
assert_eq!(reorder_paras("א(ב)ג."), vec![".ג)ב(א"]);
// With mirrorable characters on level boundry
- assert_eq!(reorder_paras("אב(גד[&ef].)gh"), vec!["ef].)gh&[דג(בא"]);
+ assert_eq!(reorder_paras("אב(גד[&ef].)gh"), vec!["gh).]ef&[דג(בא"]);
}
fn reordered_levels_for_paras(text: &str) -> Vec<Vec<Level>> {
@@ -1023,7 +1104,7 @@ mod tests {
}
}
-#[cfg(all(feature = "serde", test))]
+#[cfg(all(feature = "serde", feature = "hardcoded-data", test))]
mod serde_tests {
use super::*;
use serde_test::{assert_tokens, Token};
diff --git a/vendor/unicode-bidi/src/prepare.rs b/vendor/unicode-bidi/src/prepare.rs
index 7b952361a..21675e6d1 100644
--- a/vendor/unicode-bidi/src/prepare.rs
+++ b/vendor/unicode-bidi/src/prepare.rs
@@ -89,12 +89,35 @@ pub fn isolating_run_sequences(
.map(|sequence: Vec<LevelRun>| {
assert!(!sequence.is_empty());
- let start_of_seq = sequence[0].start;
- let end_of_seq = sequence[sequence.len() - 1].end;
- let seq_level = levels[start_of_seq];
+ let mut result = IsolatingRunSequence {
+ runs: sequence,
+ sos: L,
+ eos: L,
+ };
+
+ let start_of_seq = result.runs[0].start;
+ let runs_len = result.runs.len();
+ let end_of_seq = result.runs[runs_len - 1].end;
+
+ // > (not counting characters removed by X9)
+ let seq_level = result
+ .iter_forwards_from(start_of_seq, 0)
+ .filter(|i| not_removed_by_x9(&original_classes[*i]))
+ .map(|i| levels[i])
+ .next()
+ .unwrap_or(levels[start_of_seq]);
+
+ // XXXManishearth the spec talks of a start and end level,
+ // but for a given IRS the two should be equivalent, yes?
+ let end_level = result
+ .iter_backwards_from(end_of_seq, runs_len - 1)
+ .filter(|i| not_removed_by_x9(&original_classes[*i]))
+ .map(|i| levels[i])
+ .next()
+ .unwrap_or(levels[end_of_seq - 1]);
#[cfg(test)]
- for run in sequence.clone() {
+ for run in result.runs.clone() {
for idx in run {
if not_removed_by_x9(&original_classes[idx]) {
assert_eq!(seq_level, levels[idx]);
@@ -111,8 +134,19 @@ pub fn isolating_run_sequences(
None => para_level,
};
+ // Get the last non-removed character to check if it is an isolate initiator.
+ // The spec calls for an unmatched one, but matched isolate initiators
+ // will never be at the end of a level run (otherwise there would be more to the run).
+ // We unwrap_or(BN) because BN marks removed classes and it won't matter for the check.
+ let last_non_removed = original_classes[..end_of_seq]
+ .iter()
+ .copied()
+ .rev()
+ .find(not_removed_by_x9)
+ .unwrap_or(BN);
+
// Get the level of the next non-removed char after the runs.
- let succ_level = if let RLI | LRI | FSI = original_classes[end_of_seq - 1] {
+ let succ_level = if let RLI | LRI | FSI = last_non_removed {
para_level
} else {
match original_classes[end_of_seq..]
@@ -124,15 +158,63 @@ pub fn isolating_run_sequences(
}
};
- IsolatingRunSequence {
- runs: sequence,
- sos: max(seq_level, pred_level).bidi_class(),
- eos: max(seq_level, succ_level).bidi_class(),
- }
+ result.sos = max(seq_level, pred_level).bidi_class();
+ result.eos = max(end_level, succ_level).bidi_class();
+ result
})
.collect()
}
+impl IsolatingRunSequence {
+ /// Returns the full range of text represented by this isolating run sequence
+ pub(crate) fn text_range(&self) -> Range<usize> {
+ if let (Some(start), Some(end)) = (self.runs.first(), self.runs.last()) {
+ start.start..end.end
+ } else {
+ return 0..0;
+ }
+ }
+
+ /// Given a text-relative position `pos` and an index of the level run it is in,
+ /// produce an iterator of all characters after and pos (`pos..`) that are in this
+ /// run sequence
+ pub(crate) fn iter_forwards_from(
+ &self,
+ pos: usize,
+ level_run_index: usize,
+ ) -> impl Iterator<Item = usize> + '_ {
+ let runs = &self.runs[level_run_index..];
+
+ // Check that it is in range
+ // (we can't use contains() since we want an inclusive range)
+ #[cfg(feature = "std")]
+ debug_assert!(runs[0].start <= pos && pos <= runs[0].end);
+
+ (pos..runs[0].end).chain(runs[1..].iter().flat_map(Clone::clone))
+ }
+
+ /// Given a text-relative position `pos` and an index of the level run it is in,
+ /// produce an iterator of all characters before and excludingpos (`..pos`) that are in this
+ /// run sequence
+ pub(crate) fn iter_backwards_from(
+ &self,
+ pos: usize,
+ level_run_index: usize,
+ ) -> impl Iterator<Item = usize> + '_ {
+ let prev_runs = &self.runs[..level_run_index];
+ let current = &self.runs[level_run_index];
+
+ // Check that it is in range
+ // (we can't use contains() since we want an inclusive range)
+ #[cfg(feature = "std")]
+ debug_assert!(current.start <= pos && pos <= current.end);
+
+ (current.start..pos)
+ .rev()
+ .chain(prev_runs.iter().rev().flat_map(Clone::clone))
+ }
+}
+
/// Finds the level runs in a paragraph.
///
/// <http://www.unicode.org/reports/tr9/#BD7>
diff --git a/vendor/unicode-ident/.cargo-checksum.json b/vendor/unicode-ident/.cargo-checksum.json
index 1fcb95c86..776275d9e 100644
--- a/vendor/unicode-ident/.cargo-checksum.json
+++ b/vendor/unicode-ident/.cargo-checksum.json
@@ -1 +1 @@
-{"files":{"Cargo.toml":"4589e7f695ce2ae3c0dbb7a79647d044b8f2ef71183bf478fe01922966c54556","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"23f18e03dc49df91622fe2a76176497404e46ced8a715d9d2b67a7446571cca3","LICENSE-UNICODE":"68f5b9f5ea36881a0942ba02f558e9e1faf76cc09cb165ad801744c61b738844","README.md":"3dc1793fcaf87c77c5ed467c4a76cb696883f2f4329c011a869fbd34c4404382","benches/xid.rs":"a61f61ecc7d5124c759cdeb55ab74470ab69f2f3ca37613da65f16e0e5e33487","src/lib.rs":"d0030259a628125669ad6c02d3eb791526e6d6ae35d8a858a87f90245162666c","src/tables.rs":"4a84cc7a1a391abebe5672db993c519b9f8fe462690d7e5a8bdd43be8481c10b","tests/compare.rs":"89c4dc4f745064a9f734667b1d960596a10b8cb019a8ed1c5b9512678a866ad5","tests/fst/mod.rs":"69a3aaf59acd8bca962ecc6234be56be8c0934ab79b253162f10eb881523901f","tests/fst/xid_continue.fst":"0624500413ac318fee8424eecdad70397f911e3beae52231bfca295bb1bb9e04","tests/fst/xid_start.fst":"cc36f4f1149a4004ea7e2075cfb54756328b571946fda526be508cf5ed53dbdb","tests/roaring/mod.rs":"784f65a48477fab7549620c7843c7ad6da533f69a18abca1172f6acb95045e53","tests/static_size.rs":"6686edc08a6718cb4be03916b87a2594a2d2f2c779dbac6372fd27d5d7f7d8b6","tests/trie/mod.rs":"d4acbb716bcbaf80660039797f45e138ed8bbd66749fa3b19b1a971574679cc9","tests/trie/trie.rs":"dbd7de5fe601159643a4c6febed06793f812e8d71010b0ec78f2557353a976b2"},"package":"6ceab39d59e4c9499d4e5a8ee0e2735b891bb7308ac83dfb4e80cad195c9f6f3"} \ No newline at end of file
+{"files":{"Cargo.toml":"29d1c02ffc7c1f34067b04bcc6b38ec41918838d553176d805644d8c03ab3f62","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"23f18e03dc49df91622fe2a76176497404e46ced8a715d9d2b67a7446571cca3","LICENSE-UNICODE":"68f5b9f5ea36881a0942ba02f558e9e1faf76cc09cb165ad801744c61b738844","README.md":"4e3b8b33ce66d038b932b0824e9c5f459893c2004ce68065fb8b68c98692d298","benches/xid.rs":"a61f61ecc7d5124c759cdeb55ab74470ab69f2f3ca37613da65f16e0e5e33487","src/lib.rs":"d0030259a628125669ad6c02d3eb791526e6d6ae35d8a858a87f90245162666c","src/tables.rs":"b4609d6c2e2ba44fba8cdbcec271325ff196afba8001dee805be95424219f01b","tests/compare.rs":"89c4dc4f745064a9f734667b1d960596a10b8cb019a8ed1c5b9512678a866ad5","tests/fst/mod.rs":"69a3aaf59acd8bca962ecc6234be56be8c0934ab79b253162f10eb881523901f","tests/fst/xid_continue.fst":"0624500413ac318fee8424eecdad70397f911e3beae52231bfca295bb1bb9e04","tests/fst/xid_start.fst":"cc36f4f1149a4004ea7e2075cfb54756328b571946fda526be508cf5ed53dbdb","tests/roaring/mod.rs":"784f65a48477fab7549620c7843c7ad6da533f69a18abca1172f6acb95045e53","tests/static_size.rs":"f1275c2bc59e85b5a7c2ce500b50c00a479d314b925538083917dc001c41b187","tests/tables/mod.rs":"e6949172d10fc4b2431ce7546269bfd4f9146454c8c3e31faf5e5d80c16a8ab6","tests/tables/tables.rs":"5194ac98137a3b61322213f2f8e8b83ff925ffcdd79e93a2ec414ef944dc63a3","tests/trie/mod.rs":"d4acbb716bcbaf80660039797f45e138ed8bbd66749fa3b19b1a971574679cc9","tests/trie/trie.rs":"dbd7de5fe601159643a4c6febed06793f812e8d71010b0ec78f2557353a976b2"},"package":"84a22b9f218b40614adcb3f4ff08b703773ad44fa9423e4e0d346d5db86e4ebc"} \ No newline at end of file
diff --git a/vendor/unicode-ident/Cargo.toml b/vendor/unicode-ident/Cargo.toml
index 03e1871fc..735a4ff43 100644
--- a/vendor/unicode-ident/Cargo.toml
+++ b/vendor/unicode-ident/Cargo.toml
@@ -13,7 +13,7 @@
edition = "2018"
rust-version = "1.31"
name = "unicode-ident"
-version = "1.0.5"
+version = "1.0.6"
authors = ["David Tolnay <dtolnay@gmail.com>"]
description = "Determine whether characters have the XID_Start or XID_Continue properties according to Unicode Standard Annex #31"
documentation = "https://docs.rs/unicode-ident"
diff --git a/vendor/unicode-ident/README.md b/vendor/unicode-ident/README.md
index 6c590b06c..dfb943bfe 100644
--- a/vendor/unicode-ident/README.md
+++ b/vendor/unicode-ident/README.md
@@ -4,7 +4,7 @@ Unicode ident
[<img alt="github" src="https://img.shields.io/badge/github-dtolnay/unicode--ident-8da0cb?style=for-the-badge&labelColor=555555&logo=github" height="20">](https://github.com/dtolnay/unicode-ident)
[<img alt="crates.io" src="https://img.shields.io/crates/v/unicode-ident.svg?style=for-the-badge&color=fc8d62&logo=rust" height="20">](https://crates.io/crates/unicode-ident)
[<img alt="docs.rs" src="https://img.shields.io/badge/docs.rs-unicode--ident-66c2a5?style=for-the-badge&labelColor=555555&logo=docs.rs" height="20">](https://docs.rs/unicode-ident)
-[<img alt="build status" src="https://img.shields.io/github/workflow/status/dtolnay/unicode-ident/CI/master?style=for-the-badge" height="20">](https://github.com/dtolnay/unicode-ident/actions?query=branch%3Amaster)
+[<img alt="build status" src="https://img.shields.io/github/actions/workflow/status/dtolnay/unicode-ident/ci.yml?branch=master&style=for-the-badge" height="20">](https://github.com/dtolnay/unicode-ident/actions?query=branch%3Amaster)
Implementation of [Unicode Standard Annex #31][tr31] for determining which
`char` values are valid in programming language identifiers.
diff --git a/vendor/unicode-ident/src/tables.rs b/vendor/unicode-ident/src/tables.rs
index 380c798d1..b355f3096 100644
--- a/vendor/unicode-ident/src/tables.rs
+++ b/vendor/unicode-ident/src/tables.rs
@@ -1,6 +1,6 @@
// @generated by ../generate. To regenerate, run the following in the repo root:
//
-// $ curl -LO https://www.unicode.org/Public/zipped/14.0.0/UCD.zip
+// $ curl -LO https://www.unicode.org/Public/zipped/15.0.0/UCD.zip
// $ unzip UCD.zip -d UCD
// $ cargo run --manifest-path generate/Cargo.toml
diff --git a/vendor/unicode-ident/tests/static_size.rs b/vendor/unicode-ident/tests/static_size.rs
index df65f45dd..24effb489 100644
--- a/vendor/unicode-ident/tests/static_size.rs
+++ b/vendor/unicode-ident/tests/static_size.rs
@@ -19,14 +19,13 @@ fn test_size() {
#[test]
fn test_xid_size() {
#[deny(dead_code)]
- #[allow(clippy::redundant_static_lifetimes)]
- #[path = "../generate/src/ucd.rs"]
- mod ucd;
+ #[path = "tables/mod.rs"]
+ mod tables;
- let size = size_of_val(ucd::XID_START) + size_of_val(ucd::XID_CONTINUE);
+ let size = size_of_val(tables::XID_START) + size_of_val(tables::XID_CONTINUE);
assert_eq!(11528, size);
- let _ = ucd::BY_NAME;
+ let _ = tables::BY_NAME;
}
#[cfg(target_pointer_width = "64")]
diff --git a/vendor/unicode-ident/tests/tables/mod.rs b/vendor/unicode-ident/tests/tables/mod.rs
new file mode 100644
index 000000000..72bfd8bd7
--- /dev/null
+++ b/vendor/unicode-ident/tests/tables/mod.rs
@@ -0,0 +1,7 @@
+#![allow(clippy::module_inception)]
+
+#[allow(clippy::redundant_static_lifetimes)]
+#[rustfmt::skip]
+mod tables;
+
+pub(crate) use self::tables::*;
diff --git a/vendor/unicode-ident/tests/tables/tables.rs b/vendor/unicode-ident/tests/tables/tables.rs
new file mode 100644
index 000000000..30aeee973
--- /dev/null
+++ b/vendor/unicode-ident/tests/tables/tables.rs
@@ -0,0 +1,347 @@
+// DO NOT EDIT THIS FILE. IT WAS AUTOMATICALLY GENERATED BY:
+//
+// ucd-generate property-bool UCD --include XID_Start,XID_Continue
+//
+// Unicode version: 15.0.0.
+//
+// ucd-generate 0.2.13 is available on crates.io.
+
+pub const BY_NAME: &'static [(&'static str, &'static [(u32, u32)])] = &[
+ ("XID_Continue", XID_CONTINUE), ("XID_Start", XID_START),
+];
+
+pub const XID_CONTINUE: &'static [(u32, u32)] = &[
+ (48, 57), (65, 90), (95, 95), (97, 122), (170, 170), (181, 181), (183, 183),
+ (186, 186), (192, 214), (216, 246), (248, 705), (710, 721), (736, 740),
+ (748, 748), (750, 750), (768, 884), (886, 887), (891, 893), (895, 895),
+ (902, 906), (908, 908), (910, 929), (931, 1013), (1015, 1153), (1155, 1159),
+ (1162, 1327), (1329, 1366), (1369, 1369), (1376, 1416), (1425, 1469),
+ (1471, 1471), (1473, 1474), (1476, 1477), (1479, 1479), (1488, 1514),
+ (1519, 1522), (1552, 1562), (1568, 1641), (1646, 1747), (1749, 1756),
+ (1759, 1768), (1770, 1788), (1791, 1791), (1808, 1866), (1869, 1969),
+ (1984, 2037), (2042, 2042), (2045, 2045), (2048, 2093), (2112, 2139),
+ (2144, 2154), (2160, 2183), (2185, 2190), (2200, 2273), (2275, 2403),
+ (2406, 2415), (2417, 2435), (2437, 2444), (2447, 2448), (2451, 2472),
+ (2474, 2480), (2482, 2482), (2486, 2489), (2492, 2500), (2503, 2504),
+ (2507, 2510), (2519, 2519), (2524, 2525), (2527, 2531), (2534, 2545),
+ (2556, 2556), (2558, 2558), (2561, 2563), (2565, 2570), (2575, 2576),
+ (2579, 2600), (2602, 2608), (2610, 2611), (2613, 2614), (2616, 2617),
+ (2620, 2620), (2622, 2626), (2631, 2632), (2635, 2637), (2641, 2641),
+ (2649, 2652), (2654, 2654), (2662, 2677), (2689, 2691), (2693, 2701),
+ (2703, 2705), (2707, 2728), (2730, 2736), (2738, 2739), (2741, 2745),
+ (2748, 2757), (2759, 2761), (2763, 2765), (2768, 2768), (2784, 2787),
+ (2790, 2799), (2809, 2815), (2817, 2819), (2821, 2828), (2831, 2832),
+ (2835, 2856), (2858, 2864), (2866, 2867), (2869, 2873), (2876, 2884),
+ (2887, 2888), (2891, 2893), (2901, 2903), (2908, 2909), (2911, 2915),
+ (2918, 2927), (2929, 2929), (2946, 2947), (2949, 2954), (2958, 2960),
+ (2962, 2965), (2969, 2970), (2972, 2972), (2974, 2975), (2979, 2980),
+ (2984, 2986), (2990, 3001), (3006, 3010), (3014, 3016), (3018, 3021),
+ (3024, 3024), (3031, 3031), (3046, 3055), (3072, 3084), (3086, 3088),
+ (3090, 3112), (3114, 3129), (3132, 3140), (3142, 3144), (3146, 3149),
+ (3157, 3158), (3160, 3162), (3165, 3165), (3168, 3171), (3174, 3183),
+ (3200, 3203), (3205, 3212), (3214, 3216), (3218, 3240), (3242, 3251),
+ (3253, 3257), (3260, 3268), (3270, 3272), (3274, 3277), (3285, 3286),
+ (3293, 3294), (3296, 3299), (3302, 3311), (3313, 3315), (3328, 3340),
+ (3342, 3344), (3346, 3396), (3398, 3400), (3402, 3406), (3412, 3415),
+ (3423, 3427), (3430, 3439), (3450, 3455), (3457, 3459), (3461, 3478),
+ (3482, 3505), (3507, 3515), (3517, 3517), (3520, 3526), (3530, 3530),
+ (3535, 3540), (3542, 3542), (3544, 3551), (3558, 3567), (3570, 3571),
+ (3585, 3642), (3648, 3662), (3664, 3673), (3713, 3714), (3716, 3716),
+ (3718, 3722), (3724, 3747), (3749, 3749), (3751, 3773), (3776, 3780),
+ (3782, 3782), (3784, 3790), (3792, 3801), (3804, 3807), (3840, 3840),
+ (3864, 3865), (3872, 3881), (3893, 3893), (3895, 3895), (3897, 3897),
+ (3902, 3911), (3913, 3948), (3953, 3972), (3974, 3991), (3993, 4028),
+ (4038, 4038), (4096, 4169), (4176, 4253), (4256, 4293), (4295, 4295),
+ (4301, 4301), (4304, 4346), (4348, 4680), (4682, 4685), (4688, 4694),
+ (4696, 4696), (4698, 4701), (4704, 4744), (4746, 4749), (4752, 4784),
+ (4786, 4789), (4792, 4798), (4800, 4800), (4802, 4805), (4808, 4822),
+ (4824, 4880), (4882, 4885), (4888, 4954), (4957, 4959), (4969, 4977),
+ (4992, 5007), (5024, 5109), (5112, 5117), (5121, 5740), (5743, 5759),
+ (5761, 5786), (5792, 5866), (5870, 5880), (5888, 5909), (5919, 5940),
+ (5952, 5971), (5984, 5996), (5998, 6000), (6002, 6003), (6016, 6099),
+ (6103, 6103), (6108, 6109), (6112, 6121), (6155, 6157), (6159, 6169),
+ (6176, 6264), (6272, 6314), (6320, 6389), (6400, 6430), (6432, 6443),
+ (6448, 6459), (6470, 6509), (6512, 6516), (6528, 6571), (6576, 6601),
+ (6608, 6618), (6656, 6683), (6688, 6750), (6752, 6780), (6783, 6793),
+ (6800, 6809), (6823, 6823), (6832, 6845), (6847, 6862), (6912, 6988),
+ (6992, 7001), (7019, 7027), (7040, 7155), (7168, 7223), (7232, 7241),
+ (7245, 7293), (7296, 7304), (7312, 7354), (7357, 7359), (7376, 7378),
+ (7380, 7418), (7424, 7957), (7960, 7965), (7968, 8005), (8008, 8013),
+ (8016, 8023), (8025, 8025), (8027, 8027), (8029, 8029), (8031, 8061),
+ (8064, 8116), (8118, 8124), (8126, 8126), (8130, 8132), (8134, 8140),
+ (8144, 8147), (8150, 8155), (8160, 8172), (8178, 8180), (8182, 8188),
+ (8255, 8256), (8276, 8276), (8305, 8305), (8319, 8319), (8336, 8348),
+ (8400, 8412), (8417, 8417), (8421, 8432), (8450, 8450), (8455, 8455),
+ (8458, 8467), (8469, 8469), (8472, 8477), (8484, 8484), (8486, 8486),
+ (8488, 8488), (8490, 8505), (8508, 8511), (8517, 8521), (8526, 8526),
+ (8544, 8584), (11264, 11492), (11499, 11507), (11520, 11557),
+ (11559, 11559), (11565, 11565), (11568, 11623), (11631, 11631),
+ (11647, 11670), (11680, 11686), (11688, 11694), (11696, 11702),
+ (11704, 11710), (11712, 11718), (11720, 11726), (11728, 11734),
+ (11736, 11742), (11744, 11775), (12293, 12295), (12321, 12335),
+ (12337, 12341), (12344, 12348), (12353, 12438), (12441, 12442),
+ (12445, 12447), (12449, 12538), (12540, 12543), (12549, 12591),
+ (12593, 12686), (12704, 12735), (12784, 12799), (13312, 19903),
+ (19968, 42124), (42192, 42237), (42240, 42508), (42512, 42539),
+ (42560, 42607), (42612, 42621), (42623, 42737), (42775, 42783),
+ (42786, 42888), (42891, 42954), (42960, 42961), (42963, 42963),
+ (42965, 42969), (42994, 43047), (43052, 43052), (43072, 43123),
+ (43136, 43205), (43216, 43225), (43232, 43255), (43259, 43259),
+ (43261, 43309), (43312, 43347), (43360, 43388), (43392, 43456),
+ (43471, 43481), (43488, 43518), (43520, 43574), (43584, 43597),
+ (43600, 43609), (43616, 43638), (43642, 43714), (43739, 43741),
+ (43744, 43759), (43762, 43766), (43777, 43782), (43785, 43790),
+ (43793, 43798), (43808, 43814), (43816, 43822), (43824, 43866),
+ (43868, 43881), (43888, 44010), (44012, 44013), (44016, 44025),
+ (44032, 55203), (55216, 55238), (55243, 55291), (63744, 64109),
+ (64112, 64217), (64256, 64262), (64275, 64279), (64285, 64296),
+ (64298, 64310), (64312, 64316), (64318, 64318), (64320, 64321),
+ (64323, 64324), (64326, 64433), (64467, 64605), (64612, 64829),
+ (64848, 64911), (64914, 64967), (65008, 65017), (65024, 65039),
+ (65056, 65071), (65075, 65076), (65101, 65103), (65137, 65137),
+ (65139, 65139), (65143, 65143), (65145, 65145), (65147, 65147),
+ (65149, 65149), (65151, 65276), (65296, 65305), (65313, 65338),
+ (65343, 65343), (65345, 65370), (65382, 65470), (65474, 65479),
+ (65482, 65487), (65490, 65495), (65498, 65500), (65536, 65547),
+ (65549, 65574), (65576, 65594), (65596, 65597), (65599, 65613),
+ (65616, 65629), (65664, 65786), (65856, 65908), (66045, 66045),
+ (66176, 66204), (66208, 66256), (66272, 66272), (66304, 66335),
+ (66349, 66378), (66384, 66426), (66432, 66461), (66464, 66499),
+ (66504, 66511), (66513, 66517), (66560, 66717), (66720, 66729),
+ (66736, 66771), (66776, 66811), (66816, 66855), (66864, 66915),
+ (66928, 66938), (66940, 66954), (66956, 66962), (66964, 66965),
+ (66967, 66977), (66979, 66993), (66995, 67001), (67003, 67004),
+ (67072, 67382), (67392, 67413), (67424, 67431), (67456, 67461),
+ (67463, 67504), (67506, 67514), (67584, 67589), (67592, 67592),
+ (67594, 67637), (67639, 67640), (67644, 67644), (67647, 67669),
+ (67680, 67702), (67712, 67742), (67808, 67826), (67828, 67829),
+ (67840, 67861), (67872, 67897), (67968, 68023), (68030, 68031),
+ (68096, 68099), (68101, 68102), (68108, 68115), (68117, 68119),
+ (68121, 68149), (68152, 68154), (68159, 68159), (68192, 68220),
+ (68224, 68252), (68288, 68295), (68297, 68326), (68352, 68405),
+ (68416, 68437), (68448, 68466), (68480, 68497), (68608, 68680),
+ (68736, 68786), (68800, 68850), (68864, 68903), (68912, 68921),
+ (69248, 69289), (69291, 69292), (69296, 69297), (69373, 69404),
+ (69415, 69415), (69424, 69456), (69488, 69509), (69552, 69572),
+ (69600, 69622), (69632, 69702), (69734, 69749), (69759, 69818),
+ (69826, 69826), (69840, 69864), (69872, 69881), (69888, 69940),
+ (69942, 69951), (69956, 69959), (69968, 70003), (70006, 70006),
+ (70016, 70084), (70089, 70092), (70094, 70106), (70108, 70108),
+ (70144, 70161), (70163, 70199), (70206, 70209), (70272, 70278),
+ (70280, 70280), (70282, 70285), (70287, 70301), (70303, 70312),
+ (70320, 70378), (70384, 70393), (70400, 70403), (70405, 70412),
+ (70415, 70416), (70419, 70440), (70442, 70448), (70450, 70451),
+ (70453, 70457), (70459, 70468), (70471, 70472), (70475, 70477),
+ (70480, 70480), (70487, 70487), (70493, 70499), (70502, 70508),
+ (70512, 70516), (70656, 70730), (70736, 70745), (70750, 70753),
+ (70784, 70853), (70855, 70855), (70864, 70873), (71040, 71093),
+ (71096, 71104), (71128, 71133), (71168, 71232), (71236, 71236),
+ (71248, 71257), (71296, 71352), (71360, 71369), (71424, 71450),
+ (71453, 71467), (71472, 71481), (71488, 71494), (71680, 71738),
+ (71840, 71913), (71935, 71942), (71945, 71945), (71948, 71955),
+ (71957, 71958), (71960, 71989), (71991, 71992), (71995, 72003),
+ (72016, 72025), (72096, 72103), (72106, 72151), (72154, 72161),
+ (72163, 72164), (72192, 72254), (72263, 72263), (72272, 72345),
+ (72349, 72349), (72368, 72440), (72704, 72712), (72714, 72758),
+ (72760, 72768), (72784, 72793), (72818, 72847), (72850, 72871),
+ (72873, 72886), (72960, 72966), (72968, 72969), (72971, 73014),
+ (73018, 73018), (73020, 73021), (73023, 73031), (73040, 73049),
+ (73056, 73061), (73063, 73064), (73066, 73102), (73104, 73105),
+ (73107, 73112), (73120, 73129), (73440, 73462), (73472, 73488),
+ (73490, 73530), (73534, 73538), (73552, 73561), (73648, 73648),
+ (73728, 74649), (74752, 74862), (74880, 75075), (77712, 77808),
+ (77824, 78895), (78912, 78933), (82944, 83526), (92160, 92728),
+ (92736, 92766), (92768, 92777), (92784, 92862), (92864, 92873),
+ (92880, 92909), (92912, 92916), (92928, 92982), (92992, 92995),
+ (93008, 93017), (93027, 93047), (93053, 93071), (93760, 93823),
+ (93952, 94026), (94031, 94087), (94095, 94111), (94176, 94177),
+ (94179, 94180), (94192, 94193), (94208, 100343), (100352, 101589),
+ (101632, 101640), (110576, 110579), (110581, 110587), (110589, 110590),
+ (110592, 110882), (110898, 110898), (110928, 110930), (110933, 110933),
+ (110948, 110951), (110960, 111355), (113664, 113770), (113776, 113788),
+ (113792, 113800), (113808, 113817), (113821, 113822), (118528, 118573),
+ (118576, 118598), (119141, 119145), (119149, 119154), (119163, 119170),
+ (119173, 119179), (119210, 119213), (119362, 119364), (119808, 119892),
+ (119894, 119964), (119966, 119967), (119970, 119970), (119973, 119974),
+ (119977, 119980), (119982, 119993), (119995, 119995), (119997, 120003),
+ (120005, 120069), (120071, 120074), (120077, 120084), (120086, 120092),
+ (120094, 120121), (120123, 120126), (120128, 120132), (120134, 120134),
+ (120138, 120144), (120146, 120485), (120488, 120512), (120514, 120538),
+ (120540, 120570), (120572, 120596), (120598, 120628), (120630, 120654),
+ (120656, 120686), (120688, 120712), (120714, 120744), (120746, 120770),
+ (120772, 120779), (120782, 120831), (121344, 121398), (121403, 121452),
+ (121461, 121461), (121476, 121476), (121499, 121503), (121505, 121519),
+ (122624, 122654), (122661, 122666), (122880, 122886), (122888, 122904),
+ (122907, 122913), (122915, 122916), (122918, 122922), (122928, 122989),
+ (123023, 123023), (123136, 123180), (123184, 123197), (123200, 123209),
+ (123214, 123214), (123536, 123566), (123584, 123641), (124112, 124153),
+ (124896, 124902), (124904, 124907), (124909, 124910), (124912, 124926),
+ (124928, 125124), (125136, 125142), (125184, 125259), (125264, 125273),
+ (126464, 126467), (126469, 126495), (126497, 126498), (126500, 126500),
+ (126503, 126503), (126505, 126514), (126516, 126519), (126521, 126521),
+ (126523, 126523), (126530, 126530), (126535, 126535), (126537, 126537),
+ (126539, 126539), (126541, 126543), (126545, 126546), (126548, 126548),
+ (126551, 126551), (126553, 126553), (126555, 126555), (126557, 126557),
+ (126559, 126559), (126561, 126562), (126564, 126564), (126567, 126570),
+ (126572, 126578), (126580, 126583), (126585, 126588), (126590, 126590),
+ (126592, 126601), (126603, 126619), (126625, 126627), (126629, 126633),
+ (126635, 126651), (130032, 130041), (131072, 173791), (173824, 177977),
+ (177984, 178205), (178208, 183969), (183984, 191456), (194560, 195101),
+ (196608, 201546), (201552, 205743), (917760, 917999),
+];
+
+pub const XID_START: &'static [(u32, u32)] = &[
+ (65, 90), (97, 122), (170, 170), (181, 181), (186, 186), (192, 214),
+ (216, 246), (248, 705), (710, 721), (736, 740), (748, 748), (750, 750),
+ (880, 884), (886, 887), (891, 893), (895, 895), (902, 902), (904, 906),
+ (908, 908), (910, 929), (931, 1013), (1015, 1153), (1162, 1327),
+ (1329, 1366), (1369, 1369), (1376, 1416), (1488, 1514), (1519, 1522),
+ (1568, 1610), (1646, 1647), (1649, 1747), (1749, 1749), (1765, 1766),
+ (1774, 1775), (1786, 1788), (1791, 1791), (1808, 1808), (1810, 1839),
+ (1869, 1957), (1969, 1969), (1994, 2026), (2036, 2037), (2042, 2042),
+ (2048, 2069), (2074, 2074), (2084, 2084), (2088, 2088), (2112, 2136),
+ (2144, 2154), (2160, 2183), (2185, 2190), (2208, 2249), (2308, 2361),
+ (2365, 2365), (2384, 2384), (2392, 2401), (2417, 2432), (2437, 2444),
+ (2447, 2448), (2451, 2472), (2474, 2480), (2482, 2482), (2486, 2489),
+ (2493, 2493), (2510, 2510), (2524, 2525), (2527, 2529), (2544, 2545),
+ (2556, 2556), (2565, 2570), (2575, 2576), (2579, 2600), (2602, 2608),
+ (2610, 2611), (2613, 2614), (2616, 2617), (2649, 2652), (2654, 2654),
+ (2674, 2676), (2693, 2701), (2703, 2705), (2707, 2728), (2730, 2736),
+ (2738, 2739), (2741, 2745), (2749, 2749), (2768, 2768), (2784, 2785),
+ (2809, 2809), (2821, 2828), (2831, 2832), (2835, 2856), (2858, 2864),
+ (2866, 2867), (2869, 2873), (2877, 2877), (2908, 2909), (2911, 2913),
+ (2929, 2929), (2947, 2947), (2949, 2954), (2958, 2960), (2962, 2965),
+ (2969, 2970), (2972, 2972), (2974, 2975), (2979, 2980), (2984, 2986),
+ (2990, 3001), (3024, 3024), (3077, 3084), (3086, 3088), (3090, 3112),
+ (3114, 3129), (3133, 3133), (3160, 3162), (3165, 3165), (3168, 3169),
+ (3200, 3200), (3205, 3212), (3214, 3216), (3218, 3240), (3242, 3251),
+ (3253, 3257), (3261, 3261), (3293, 3294), (3296, 3297), (3313, 3314),
+ (3332, 3340), (3342, 3344), (3346, 3386), (3389, 3389), (3406, 3406),
+ (3412, 3414), (3423, 3425), (3450, 3455), (3461, 3478), (3482, 3505),
+ (3507, 3515), (3517, 3517), (3520, 3526), (3585, 3632), (3634, 3634),
+ (3648, 3654), (3713, 3714), (3716, 3716), (3718, 3722), (3724, 3747),
+ (3749, 3749), (3751, 3760), (3762, 3762), (3773, 3773), (3776, 3780),
+ (3782, 3782), (3804, 3807), (3840, 3840), (3904, 3911), (3913, 3948),
+ (3976, 3980), (4096, 4138), (4159, 4159), (4176, 4181), (4186, 4189),
+ (4193, 4193), (4197, 4198), (4206, 4208), (4213, 4225), (4238, 4238),
+ (4256, 4293), (4295, 4295), (4301, 4301), (4304, 4346), (4348, 4680),
+ (4682, 4685), (4688, 4694), (4696, 4696), (4698, 4701), (4704, 4744),
+ (4746, 4749), (4752, 4784), (4786, 4789), (4792, 4798), (4800, 4800),
+ (4802, 4805), (4808, 4822), (4824, 4880), (4882, 4885), (4888, 4954),
+ (4992, 5007), (5024, 5109), (5112, 5117), (5121, 5740), (5743, 5759),
+ (5761, 5786), (5792, 5866), (5870, 5880), (5888, 5905), (5919, 5937),
+ (5952, 5969), (5984, 5996), (5998, 6000), (6016, 6067), (6103, 6103),
+ (6108, 6108), (6176, 6264), (6272, 6312), (6314, 6314), (6320, 6389),
+ (6400, 6430), (6480, 6509), (6512, 6516), (6528, 6571), (6576, 6601),
+ (6656, 6678), (6688, 6740), (6823, 6823), (6917, 6963), (6981, 6988),
+ (7043, 7072), (7086, 7087), (7098, 7141), (7168, 7203), (7245, 7247),
+ (7258, 7293), (7296, 7304), (7312, 7354), (7357, 7359), (7401, 7404),
+ (7406, 7411), (7413, 7414), (7418, 7418), (7424, 7615), (7680, 7957),
+ (7960, 7965), (7968, 8005), (8008, 8013), (8016, 8023), (8025, 8025),
+ (8027, 8027), (8029, 8029), (8031, 8061), (8064, 8116), (8118, 8124),
+ (8126, 8126), (8130, 8132), (8134, 8140), (8144, 8147), (8150, 8155),
+ (8160, 8172), (8178, 8180), (8182, 8188), (8305, 8305), (8319, 8319),
+ (8336, 8348), (8450, 8450), (8455, 8455), (8458, 8467), (8469, 8469),
+ (8472, 8477), (8484, 8484), (8486, 8486), (8488, 8488), (8490, 8505),
+ (8508, 8511), (8517, 8521), (8526, 8526), (8544, 8584), (11264, 11492),
+ (11499, 11502), (11506, 11507), (11520, 11557), (11559, 11559),
+ (11565, 11565), (11568, 11623), (11631, 11631), (11648, 11670),
+ (11680, 11686), (11688, 11694), (11696, 11702), (11704, 11710),
+ (11712, 11718), (11720, 11726), (11728, 11734), (11736, 11742),
+ (12293, 12295), (12321, 12329), (12337, 12341), (12344, 12348),
+ (12353, 12438), (12445, 12447), (12449, 12538), (12540, 12543),
+ (12549, 12591), (12593, 12686), (12704, 12735), (12784, 12799),
+ (13312, 19903), (19968, 42124), (42192, 42237), (42240, 42508),
+ (42512, 42527), (42538, 42539), (42560, 42606), (42623, 42653),
+ (42656, 42735), (42775, 42783), (42786, 42888), (42891, 42954),
+ (42960, 42961), (42963, 42963), (42965, 42969), (42994, 43009),
+ (43011, 43013), (43015, 43018), (43020, 43042), (43072, 43123),
+ (43138, 43187), (43250, 43255), (43259, 43259), (43261, 43262),
+ (43274, 43301), (43312, 43334), (43360, 43388), (43396, 43442),
+ (43471, 43471), (43488, 43492), (43494, 43503), (43514, 43518),
+ (43520, 43560), (43584, 43586), (43588, 43595), (43616, 43638),
+ (43642, 43642), (43646, 43695), (43697, 43697), (43701, 43702),
+ (43705, 43709), (43712, 43712), (43714, 43714), (43739, 43741),
+ (43744, 43754), (43762, 43764), (43777, 43782), (43785, 43790),
+ (43793, 43798), (43808, 43814), (43816, 43822), (43824, 43866),
+ (43868, 43881), (43888, 44002), (44032, 55203), (55216, 55238),
+ (55243, 55291), (63744, 64109), (64112, 64217), (64256, 64262),
+ (64275, 64279), (64285, 64285), (64287, 64296), (64298, 64310),
+ (64312, 64316), (64318, 64318), (64320, 64321), (64323, 64324),
+ (64326, 64433), (64467, 64605), (64612, 64829), (64848, 64911),
+ (64914, 64967), (65008, 65017), (65137, 65137), (65139, 65139),
+ (65143, 65143), (65145, 65145), (65147, 65147), (65149, 65149),
+ (65151, 65276), (65313, 65338), (65345, 65370), (65382, 65437),
+ (65440, 65470), (65474, 65479), (65482, 65487), (65490, 65495),
+ (65498, 65500), (65536, 65547), (65549, 65574), (65576, 65594),
+ (65596, 65597), (65599, 65613), (65616, 65629), (65664, 65786),
+ (65856, 65908), (66176, 66204), (66208, 66256), (66304, 66335),
+ (66349, 66378), (66384, 66421), (66432, 66461), (66464, 66499),
+ (66504, 66511), (66513, 66517), (66560, 66717), (66736, 66771),
+ (66776, 66811), (66816, 66855), (66864, 66915), (66928, 66938),
+ (66940, 66954), (66956, 66962), (66964, 66965), (66967, 66977),
+ (66979, 66993), (66995, 67001), (67003, 67004), (67072, 67382),
+ (67392, 67413), (67424, 67431), (67456, 67461), (67463, 67504),
+ (67506, 67514), (67584, 67589), (67592, 67592), (67594, 67637),
+ (67639, 67640), (67644, 67644), (67647, 67669), (67680, 67702),
+ (67712, 67742), (67808, 67826), (67828, 67829), (67840, 67861),
+ (67872, 67897), (67968, 68023), (68030, 68031), (68096, 68096),
+ (68112, 68115), (68117, 68119), (68121, 68149), (68192, 68220),
+ (68224, 68252), (68288, 68295), (68297, 68324), (68352, 68405),
+ (68416, 68437), (68448, 68466), (68480, 68497), (68608, 68680),
+ (68736, 68786), (68800, 68850), (68864, 68899), (69248, 69289),
+ (69296, 69297), (69376, 69404), (69415, 69415), (69424, 69445),
+ (69488, 69505), (69552, 69572), (69600, 69622), (69635, 69687),
+ (69745, 69746), (69749, 69749), (69763, 69807), (69840, 69864),
+ (69891, 69926), (69956, 69956), (69959, 69959), (69968, 70002),
+ (70006, 70006), (70019, 70066), (70081, 70084), (70106, 70106),
+ (70108, 70108), (70144, 70161), (70163, 70187), (70207, 70208),
+ (70272, 70278), (70280, 70280), (70282, 70285), (70287, 70301),
+ (70303, 70312), (70320, 70366), (70405, 70412), (70415, 70416),
+ (70419, 70440), (70442, 70448), (70450, 70451), (70453, 70457),
+ (70461, 70461), (70480, 70480), (70493, 70497), (70656, 70708),
+ (70727, 70730), (70751, 70753), (70784, 70831), (70852, 70853),
+ (70855, 70855), (71040, 71086), (71128, 71131), (71168, 71215),
+ (71236, 71236), (71296, 71338), (71352, 71352), (71424, 71450),
+ (71488, 71494), (71680, 71723), (71840, 71903), (71935, 71942),
+ (71945, 71945), (71948, 71955), (71957, 71958), (71960, 71983),
+ (71999, 71999), (72001, 72001), (72096, 72103), (72106, 72144),
+ (72161, 72161), (72163, 72163), (72192, 72192), (72203, 72242),
+ (72250, 72250), (72272, 72272), (72284, 72329), (72349, 72349),
+ (72368, 72440), (72704, 72712), (72714, 72750), (72768, 72768),
+ (72818, 72847), (72960, 72966), (72968, 72969), (72971, 73008),
+ (73030, 73030), (73056, 73061), (73063, 73064), (73066, 73097),
+ (73112, 73112), (73440, 73458), (73474, 73474), (73476, 73488),
+ (73490, 73523), (73648, 73648), (73728, 74649), (74752, 74862),
+ (74880, 75075), (77712, 77808), (77824, 78895), (78913, 78918),
+ (82944, 83526), (92160, 92728), (92736, 92766), (92784, 92862),
+ (92880, 92909), (92928, 92975), (92992, 92995), (93027, 93047),
+ (93053, 93071), (93760, 93823), (93952, 94026), (94032, 94032),
+ (94099, 94111), (94176, 94177), (94179, 94179), (94208, 100343),
+ (100352, 101589), (101632, 101640), (110576, 110579), (110581, 110587),
+ (110589, 110590), (110592, 110882), (110898, 110898), (110928, 110930),
+ (110933, 110933), (110948, 110951), (110960, 111355), (113664, 113770),
+ (113776, 113788), (113792, 113800), (113808, 113817), (119808, 119892),
+ (119894, 119964), (119966, 119967), (119970, 119970), (119973, 119974),
+ (119977, 119980), (119982, 119993), (119995, 119995), (119997, 120003),
+ (120005, 120069), (120071, 120074), (120077, 120084), (120086, 120092),
+ (120094, 120121), (120123, 120126), (120128, 120132), (120134, 120134),
+ (120138, 120144), (120146, 120485), (120488, 120512), (120514, 120538),
+ (120540, 120570), (120572, 120596), (120598, 120628), (120630, 120654),
+ (120656, 120686), (120688, 120712), (120714, 120744), (120746, 120770),
+ (120772, 120779), (122624, 122654), (122661, 122666), (122928, 122989),
+ (123136, 123180), (123191, 123197), (123214, 123214), (123536, 123565),
+ (123584, 123627), (124112, 124139), (124896, 124902), (124904, 124907),
+ (124909, 124910), (124912, 124926), (124928, 125124), (125184, 125251),
+ (125259, 125259), (126464, 126467), (126469, 126495), (126497, 126498),
+ (126500, 126500), (126503, 126503), (126505, 126514), (126516, 126519),
+ (126521, 126521), (126523, 126523), (126530, 126530), (126535, 126535),
+ (126537, 126537), (126539, 126539), (126541, 126543), (126545, 126546),
+ (126548, 126548), (126551, 126551), (126553, 126553), (126555, 126555),
+ (126557, 126557), (126559, 126559), (126561, 126562), (126564, 126564),
+ (126567, 126570), (126572, 126578), (126580, 126583), (126585, 126588),
+ (126590, 126590), (126592, 126601), (126603, 126619), (126625, 126627),
+ (126629, 126633), (126635, 126651), (131072, 173791), (173824, 177977),
+ (177984, 178205), (178208, 183969), (183984, 191456), (194560, 195101),
+ (196608, 201546), (201552, 205743),
+];
diff --git a/vendor/writeable/.cargo-checksum.json b/vendor/writeable/.cargo-checksum.json
index fe32e7569..35e2eb919 100644
--- a/vendor/writeable/.cargo-checksum.json
+++ b/vendor/writeable/.cargo-checksum.json
@@ -1 +1 @@
-{"files":{"Cargo.lock":"efd045d3270108f64d75d49125e15940cf26b54c2944a13354698223d0c4ce17","Cargo.toml":"32b4d9ebb1a5c179aafb27b212e94203a1a2158b7c0387c712f25de31188b7a6","LICENSE":"4ad7541d66a407234e2c84902124cef325c29f3e966353efdb800bedb8b8da21","README.md":"a47b1fa1adda09e2ca28f7f49878c61d8f2057b8f3c42af7d39d646fedbd9934","benches/writeable.rs":"edc81c5524f98e77f0b3a45545606c4b526f63791e6dd8f90c88679c758c4834","examples/writeable_message.rs":"58bf4007f54f9f80428af7b687531837a294aecde533395a0a4c4cf55c9cad7d","src/impls.rs":"c13310eaf5ecb2f4bb87896ea0ee4f060b7828e7ea07b333e69a397a03ef39ae","src/lib.rs":"056631819550bd2845084f97fa1ee6ae130927c7021af86c8cf83337ae638f77","src/ops.rs":"4e49b1e8a8da46c3bcfecbdcb91f6e2d87afab47b76fcc2c4f005bf3cef675f1","tests/writeable.rs":"6dc3db45174180bcbf8980e640525b441c31b0b9db238721888d8cc0bd998ded"},"package":"f8e6ab4f5da1b24daf2c590cfac801bacb27b15b4f050e84eb60149ea726f06b"} \ No newline at end of file
+{"files":{"Cargo.lock":"4d2a250761f97e955d5c1839cb828fe364db73a6f8e25b4cf3a3e3bc00570cec","Cargo.toml":"e52bc721b0357827fb17713b5eb64791cb152eac5d8abdff35bb1b7a825f524d","LICENSE":"4ad7541d66a407234e2c84902124cef325c29f3e966353efdb800bedb8b8da21","README.md":"a47b1fa1adda09e2ca28f7f49878c61d8f2057b8f3c42af7d39d646fedbd9934","benches/writeable.rs":"edc81c5524f98e77f0b3a45545606c4b526f63791e6dd8f90c88679c758c4834","examples/writeable_message.rs":"58bf4007f54f9f80428af7b687531837a294aecde533395a0a4c4cf55c9cad7d","src/impls.rs":"c8fcad8d4374b28441442fa62c8a1e4c31739fbb3f31ed74a176e7ddd0e08cd0","src/lib.rs":"75edc4baf7f69a20c7d6af54f318f904e798b3d6c58eeb624ddd198114aef09a","src/ops.rs":"f201b36dc6a74d4137cca876b99a871555fe7bed7c784917ede49758a1717359","tests/writeable.rs":"6dc3db45174180bcbf8980e640525b441c31b0b9db238721888d8cc0bd998ded"},"package":"92d74a687e3b9a7a129db0a8c82b4d464eb9c36f5a66ca68572a7e5f1cfdb5bc"} \ No newline at end of file
diff --git a/vendor/writeable/Cargo.lock b/vendor/writeable/Cargo.lock
index c4110d507..e6b901786 100644
--- a/vendor/writeable/Cargo.lock
+++ b/vendor/writeable/Cargo.lock
@@ -8,7 +8,7 @@ version = "0.2.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
dependencies = [
- "hermit-abi",
+ "hermit-abi 0.1.19",
"libc",
"winapi",
]
@@ -39,9 +39,9 @@ dependencies = [
[[package]]
name = "bumpalo"
-version = "3.11.0"
+version = "3.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c1ad822118d20d2c234f427000d5acc36eabe1e29a348c89b63dd60b13f28e5d"
+checksum = "0d261e256854913907f67ed06efbc3338dfe6179796deefc1ff763fc1aee5535"
[[package]]
name = "cast"
@@ -125,26 +125,24 @@ dependencies = [
[[package]]
name = "crossbeam-epoch"
-version = "0.9.10"
+version = "0.9.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "045ebe27666471bb549370b4b0b3e51b07f56325befa4284db65fc89c02511b1"
+checksum = "01a9af1f4c2ef74bb8aa1f7e19706bc72d03598c8a570bb5de72243c7a9d9d5a"
dependencies = [
"autocfg",
"cfg-if",
"crossbeam-utils",
"memoffset",
- "once_cell",
"scopeguard",
]
[[package]]
name = "crossbeam-utils"
-version = "0.8.11"
+version = "0.8.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "51887d4adc7b564537b15adcfb307936f8075dfcd5f00dde9a9f1d29383682bc"
+checksum = "4fb766fa798726286dbbb842f174001dab8abc7b627a1dd86e0b7222a95d929f"
dependencies = [
"cfg-if",
- "once_cell",
]
[[package]]
@@ -177,9 +175,9 @@ checksum = "90e5c1c8368803113bf0c9584fc495a58b86dc8a29edbf8fe877d21d9507e797"
[[package]]
name = "getrandom"
-version = "0.2.7"
+version = "0.2.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4eb1a864a501629691edf6c15a593b7a51eebaa1e8468e9ddc623de7c9b58ec6"
+checksum = "c05aeb6a22b8f62540c194aac980f2115af067bfe15a0734d7277a768d396b31"
dependencies = [
"cfg-if",
"libc",
@@ -202,10 +200,13 @@ dependencies = [
]
[[package]]
-name = "icu_benchmark_macros"
-version = "0.7.0"
+name = "hermit-abi"
+version = "0.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6c867656f2d9c90b13709ac88e710a9d6afe33998c1dfa22384bab8804e8b3d4"
+checksum = "ee512640fe35acbfb4bb779db6f0d80704c2cacfa2e39b601ef3e3f47d1ae4c7"
+dependencies = [
+ "libc",
+]
[[package]]
name = "itertools"
@@ -224,9 +225,9 @@ checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4"
[[package]]
name = "itoa"
-version = "1.0.3"
+version = "1.0.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6c8af84674fe1f223a982c933a0ee1086ac4d4052aa0fb8060c12c6ad838e754"
+checksum = "fad582f4b9e86b6caa621cabeb0963332d92eea04729ab12892c2533951e6440"
[[package]]
name = "js-sys"
@@ -245,9 +246,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
[[package]]
name = "libc"
-version = "0.2.133"
+version = "0.2.139"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c0f80d65747a3e43d1596c7c5492d95d5edddaabd45a7fcdb02b95f644164966"
+checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79"
[[package]]
name = "log"
@@ -266,9 +267,9 @@ checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
[[package]]
name = "memoffset"
-version = "0.6.5"
+version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce"
+checksum = "5de893c32cde5f383baa4c04c5d6dbdd735cfd4a794b0debdb2bb1b421da5ff4"
dependencies = [
"autocfg",
]
@@ -284,19 +285,19 @@ dependencies = [
[[package]]
name = "num_cpus"
-version = "1.13.1"
+version = "1.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "19e64526ebdee182341572e50e9ad03965aa510cd94427a4549448f285e957a1"
+checksum = "0fac9e2da13b5eb447a6ce3d392f23a29d8694bff781bf03a16cd9ac8697593b"
dependencies = [
- "hermit-abi",
+ "hermit-abi 0.2.6",
"libc",
]
[[package]]
name = "once_cell"
-version = "1.15.0"
+version = "1.17.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e82dad04139b71a90c080c8463fe0dc7902db5192d939bd0950f074d014339e1"
+checksum = "6f61fba1741ea2b3d6a1e3178721804bb716a68a6aeba1149b5d52e3d464ea66"
[[package]]
name = "oorandom"
@@ -334,24 +335,24 @@ dependencies = [
[[package]]
name = "ppv-lite86"
-version = "0.2.16"
+version = "0.2.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872"
+checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de"
[[package]]
name = "proc-macro2"
-version = "1.0.44"
+version = "1.0.50"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7bd7356a8122b6c4a24a82b278680c73357984ca2fc79a0f9fa6dea7dced7c58"
+checksum = "6ef7d57beacfaf2d8aee5937dab7b7f28de3cb8b1828479bb5de2a7106f2bae2"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
-version = "1.0.21"
+version = "1.0.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179"
+checksum = "8856d8364d252a14d474036ea1358d63c9e6965c8e5c1885c18f73d70bff9c7b"
dependencies = [
"proc-macro2",
]
@@ -388,21 +389,19 @@ dependencies = [
[[package]]
name = "rayon"
-version = "1.5.3"
+version = "1.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bd99e5772ead8baa5215278c9b15bf92087709e9c1b2d1f97cdb5a183c933a7d"
+checksum = "6db3a213adf02b3bcfd2d3846bb41cb22857d131789e01df434fb7e7bc0759b7"
dependencies = [
- "autocfg",
- "crossbeam-deque",
"either",
"rayon-core",
]
[[package]]
name = "rayon-core"
-version = "1.9.3"
+version = "1.10.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "258bcdb5ac6dad48491bb2992db6b7cf74878b0384908af124823d118c99683f"
+checksum = "356a0625f1954f730c0201cdab48611198dc6ce21f4acff55089b5a78e6e835b"
dependencies = [
"crossbeam-channel",
"crossbeam-deque",
@@ -412,9 +411,9 @@ dependencies = [
[[package]]
name = "regex"
-version = "1.6.0"
+version = "1.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4c4eb3267174b8c6c2f654116623910a0fef09c4753f8dd83db29c48a0df988b"
+checksum = "48aaa5748ba571fb95cd2c85c09f629215d3a6ece942baa100950af03a34f733"
dependencies = [
"regex-syntax",
]
@@ -427,15 +426,15 @@ checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132"
[[package]]
name = "regex-syntax"
-version = "0.6.27"
+version = "0.6.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a3f87b73ce11b1619a3c6332f45341e0047173771e8b8b73f87bfeefb7b56244"
+checksum = "456c603be3e8d448b072f410900c09faf164fbce2d480456f50eea6e25f9c848"
[[package]]
name = "ryu"
-version = "1.0.11"
+version = "1.0.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4501abdff3ae82a1c1b477a17252eb69cee9e66eb915c1abaa4f44d873df9f09"
+checksum = "7b4b9743ed687d4b4bcedf9ff5eaa7398495ae14e61cba0a295704edbc7decde"
[[package]]
name = "same-file"
@@ -454,9 +453,9 @@ checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
[[package]]
name = "serde"
-version = "1.0.145"
+version = "1.0.152"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "728eb6351430bccb993660dfffc5a72f91ccc1295abaa8ce19b27ebe4f75568b"
+checksum = "bb7d1f0d3021d347a83e556fc4683dea2ea09d87bccdf88ff5c12545d89d5efb"
[[package]]
name = "serde_cbor"
@@ -470,9 +469,9 @@ dependencies = [
[[package]]
name = "serde_derive"
-version = "1.0.145"
+version = "1.0.152"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "81fa1584d3d1bcacd84c277a0dfe21f5b0f6accf4a23d04d4c6d61f1af522b4c"
+checksum = "af487d118eecd09402d70a5d72551860e788df87b464af30e5ea6a38c75c541e"
dependencies = [
"proc-macro2",
"quote",
@@ -481,20 +480,20 @@ dependencies = [
[[package]]
name = "serde_json"
-version = "1.0.85"
+version = "1.0.91"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e55a28e3aaef9d5ce0506d0a14dbba8054ddc7e499ef522dd8b26859ec9d4a44"
+checksum = "877c235533714907a8c2464236f5c4b2a17262ef1bd71f38f35ea592c8da6883"
dependencies = [
- "itoa 1.0.3",
+ "itoa 1.0.5",
"ryu",
"serde",
]
[[package]]
name = "syn"
-version = "1.0.101"
+version = "1.0.107"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e90cde112c4b9690b8cbe810cba9ddd8bc1d7472e2cae317b69e9438c1cba7d2"
+checksum = "1f4064b5b16e03ae50984a5a8ed5d4f8803e6bc1fd170a3cda91a1be4b18e3f5"
dependencies = [
"proc-macro2",
"quote",
@@ -522,9 +521,9 @@ dependencies = [
[[package]]
name = "unicode-ident"
-version = "1.0.4"
+version = "1.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dcc811dc4066ac62f84f11307873c4850cb653bfa9b1719cee2bd2204a4bc5dd"
+checksum = "84a22b9f218b40614adcb3f4ff08b703773ad44fa9423e4e0d346d5db86e4ebc"
[[package]]
name = "unicode-width"
@@ -646,9 +645,8 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
[[package]]
name = "writeable"
-version = "0.5.0"
+version = "0.5.1"
dependencies = [
"criterion",
- "icu_benchmark_macros",
"rand",
]
diff --git a/vendor/writeable/Cargo.toml b/vendor/writeable/Cargo.toml
index 1c9d41303..0ec582e48 100644
--- a/vendor/writeable/Cargo.toml
+++ b/vendor/writeable/Cargo.toml
@@ -12,7 +12,7 @@
[package]
edition = "2018"
name = "writeable"
-version = "0.5.0"
+version = "0.5.1"
authors = ["The ICU4X Project Developers"]
include = [
"src/**/*",
@@ -29,9 +29,15 @@ license = "Unicode-DFS-2016"
repository = "https://github.com/unicode-org/icu4x"
resolver = "2"
+[package.metadata.workspaces]
+independent = true
+
[package.metadata.docs.rs]
all-features = true
+[package.metadata.cargo-all-features]
+denylist = ["bench"]
+
[lib]
path = "src/lib.rs"
bench = false
@@ -43,13 +49,9 @@ harness = false
[dev-dependencies.criterion]
version = "0.3"
-[dev-dependencies.icu_benchmark_macros]
-version = "0.7"
-
[dev-dependencies.rand]
version = "0.8"
features = ["small_rng"]
[features]
bench = []
-default = []
diff --git a/vendor/writeable/src/impls.rs b/vendor/writeable/src/impls.rs
index 649ede4d5..a2b5201e0 100644
--- a/vendor/writeable/src/impls.rs
+++ b/vendor/writeable/src/impls.rs
@@ -7,12 +7,12 @@ use alloc::borrow::Cow;
use core::fmt;
macro_rules! impl_write_num {
- ($u:ty, $i:ty, $test:ident, $log10:ident) => {
+ ($u:ty, $i:ty, $test:ident, $max_ilog_10:expr) => {
impl $crate::Writeable for $u {
fn write_to<W: core::fmt::Write + ?Sized>(&self, sink: &mut W) -> core::fmt::Result {
- let mut buf = [b'0'; $log10(<$u>::MAX) as usize + 1];
+ let mut buf = [b'0'; $max_ilog_10 + 1];
let mut n = *self;
- let mut i = buf.len();
+ let mut i = $max_ilog_10 + 1;
#[allow(clippy::indexing_slicing)] // n < 10^i
while n != 0 {
i -= 1;
@@ -29,40 +29,38 @@ macro_rules! impl_write_num {
}
fn writeable_length_hint(&self) -> $crate::LengthHint {
- $crate::LengthHint::exact(if *self == 0 {
- 1
- } else {
- $log10(*self) as usize + 1
- })
+ LengthHint::exact(self.checked_ilog10().unwrap_or(0) as usize + 1)
}
}
- // TODO: use the library functions once stabilized.
- // https://github.com/unicode-org/icu4x/issues/1428
- #[inline]
- const fn $log10(s: $u) -> u32 {
- let b = (<$u>::BITS - 1) - s.leading_zeros();
- // s ∈ [2ᵇ, 2ᵇ⁺¹-1] => ⌊log₁₀(s)⌋ ∈ [⌊log₁₀(2ᵇ)⌋, ⌊log₁₀(2ᵇ⁺¹-1)⌋]
- // <=> ⌊log₁₀(s)⌋ ∈ [⌊log₁₀(2ᵇ)⌋, ⌊log₁₀(2ᵇ⁺¹)⌋]
- // <=> ⌊log₁₀(s)⌋ ∈ [⌊b log₁₀(2)⌋, ⌊(b+1) log₁₀(2)⌋]
- // The second line holds because there is no integer in
- // [log₁₀(2ᶜ-1), log₁₀(2ᶜ)], if there were, there'd be some 10ⁿ in
- // [2ᶜ-1, 2ᶜ], but it can't be 2ᶜ-1 due to parity nor 2ᶜ due to prime
- // factors.
-
- const M: u32 = (core::f64::consts::LOG10_2 * (1 << 26) as f64) as u32;
- let low = (b * M) >> 26;
- let high = ((b + 1) * M) >> 26;
-
- // If the bounds aren't tight (e.g. 87 ∈ [64, 127] ⟹ ⌊log₁₀(87)⌋ ∈ [1,2]),
- // compare to 10ʰ (100). This shouldn't happen too often as there are more
- // powers of 2 than 10 (it happens for 14% of u32s).
- if high == low {
- low
- } else if s < (10 as $u).pow(high) {
- low
- } else {
- high
+ impl ILog10Ext for $u {
+ fn checked_ilog10(self) -> Option<u32> {
+ if self == 0 {
+ return None;
+ }
+ let b = (<$u>::BITS - 1) - self.leading_zeros();
+ // self ∈ [2ᵇ, 2ᵇ⁺¹-1] => ⌊log₁₀(self)⌋ ∈ [⌊log₁₀(2ᵇ)⌋, ⌊log₁₀(2ᵇ⁺¹-1)⌋]
+ // <=> ⌊log₁₀(self)⌋ ∈ [⌊log₁₀(2ᵇ)⌋, ⌊log₁₀(2ᵇ⁺¹)⌋]
+ // <=> ⌊log₁₀(self)⌋ ∈ [⌊b log₁₀(2)⌋, ⌊(b+1) log₁₀(2)⌋]
+ // The second line holds because there is no integer in
+ // [log₁₀(2ᶜ-1), log₁₀(2ᶜ)], if there were, there'd be some 10ⁿ in
+ // [2ᶜ-1, 2ᶜ], but it can't be 2ᶜ-1 due to parity nor 2ᶜ due to prime
+ // factors.
+
+ const M: u32 = (core::f64::consts::LOG10_2 * (1 << 26) as f64) as u32;
+ let low = (b * M) >> 26;
+ let high = ((b + 1) * M) >> 26;
+
+ // If the bounds aren't tight (e.g. 87 ∈ [64, 127] ⟹ ⌊log₁₀(87)⌋ ∈ [1,2]),
+ // compare to 10ʰ (100). This shouldn't happen too often as there are more
+ // powers of 2 than 10 (it happens for 14% of u32s).
+ Some(if high == low {
+ low
+ } else if self < (10 as $u).pow(high) {
+ low
+ } else {
+ high
+ })
}
}
@@ -84,11 +82,14 @@ macro_rules! impl_write_num {
fn $test() {
use $crate::assert_writeable_eq;
assert_writeable_eq!(&(0 as $u), "0");
- assert_writeable_eq!(&(0 as $u), "0");
+ assert_writeable_eq!(&(0 as $i), "0");
assert_writeable_eq!(&(-0 as $i), "0");
assert_writeable_eq!(&(1 as $u), "1");
assert_writeable_eq!(&(1 as $i), "1");
assert_writeable_eq!(&(-1 as $i), "-1");
+ assert_writeable_eq!(&(9 as $u), "9");
+ assert_writeable_eq!(&(9 as $i), "9");
+ assert_writeable_eq!(&(-9 as $i), "-9");
assert_writeable_eq!(&(10 as $u), "10");
assert_writeable_eq!(&(10 as $i), "10");
assert_writeable_eq!(&(-10 as $i), "-10");
@@ -112,19 +113,24 @@ macro_rules! impl_write_num {
};
}
-impl_write_num!(u8, i8, test_u8, log10_u8);
-impl_write_num!(u16, i16, test_u16, log10_u16);
-impl_write_num!(u32, i32, test_u32, log10_u32);
-impl_write_num!(u64, i64, test_u64, log10_u64);
-impl_write_num!(u128, i128, test_u128, log10_u128);
-
-#[test]
-fn assert_log10_approximation() {
- for i in 1..u128::BITS {
- assert_eq!(i * 59 / 196, 2f64.powf(i.into()).log10().floor() as u32);
- }
+/// `checked_ilog10` is added as a method on integer types in 1.67.
+/// This extension trait provides it for older compilers.
+trait ILog10Ext: Sized {
+ fn checked_ilog10(self) -> Option<u32>;
}
+impl_write_num!(u8, i8, test_u8, 2);
+impl_write_num!(u16, i16, test_u16, 4);
+impl_write_num!(u32, i32, test_u32, 9);
+impl_write_num!(u64, i64, test_u64, 19);
+impl_write_num!(u128, i128, test_u128, 38);
+impl_write_num!(
+ usize,
+ isize,
+ test_usize,
+ if usize::MAX as u64 == u64::MAX { 19 } else { 9 }
+);
+
impl Writeable for str {
#[inline]
fn write_to<W: fmt::Write + ?Sized>(&self, sink: &mut W) -> fmt::Result {
@@ -194,7 +200,7 @@ impl<'a, T: Writeable + ?Sized> Writeable for &T {
#[test]
fn test_string_impls() {
- fn check_writeable_slice<W: Writeable>(writeables: &[W]) {
+ fn check_writeable_slice<W: Writeable + core::fmt::Display>(writeables: &[W]) {
assert_writeable_eq!(&writeables[0], "");
assert_writeable_eq!(&writeables[1], "abc");
}
@@ -204,10 +210,10 @@ fn test_string_impls() {
check_writeable_slice(arr);
// test String impl
- let arr: &[String] = &["".to_string(), "abc".to_string()];
+ let arr: &[String] = &[String::new(), "abc".to_owned()];
check_writeable_slice(arr);
// test &T impl
- let arr: &[&String] = &[&"".to_string(), &"abc".to_string()];
+ let arr: &[&String] = &[&String::new(), &"abc".to_owned()];
check_writeable_slice(arr);
}
diff --git a/vendor/writeable/src/lib.rs b/vendor/writeable/src/lib.rs
index 66be7f33b..0eb6be8d6 100644
--- a/vendor/writeable/src/lib.rs
+++ b/vendor/writeable/src/lib.rs
@@ -136,6 +136,28 @@ impl LengthHint {
}
}
+/// [`Part`]s are used as annotations for formatted strings. For example, a string like
+/// `Alice, Bob` could assign a `NAME` part to the substrings `Alice` and `Bob`, and a
+/// `PUNCTUATION` part to `, `. This allows for example to apply styling only to names.
+///
+/// `Part` contains two fields, whose usage is left up to the producer of the [`Writeable`].
+/// Conventionally, the `category` field will identify the formatting logic that produces
+/// the string/parts, whereas the `value` field will have semantic meaning. `NAME` and
+/// `PUNCTUATION` could thus be defined as
+/// ```
+/// # use writeable::Part;
+/// const NAME: Part = Part {
+/// category: "userlist",
+/// value: "name",
+/// };
+/// const PUNCTUATION: Part = Part {
+/// category: "userlist",
+/// value: "punctuation",
+/// };
+/// ```
+///
+/// That said, consumers should not usually have to inspect `Part` internals. Instead,
+/// formatters should expose the `Part`s they produces as constants.
#[derive(Clone, Copy, Debug, PartialEq)]
#[allow(clippy::exhaustive_structs)] // stable
pub struct Part {
@@ -240,7 +262,11 @@ pub trait Writeable {
/// }
/// ```
fn write_to_string(&self) -> Cow<str> {
- let mut output = String::with_capacity(self.writeable_length_hint().capacity());
+ let hint = self.writeable_length_hint();
+ if hint.is_zero() {
+ return Cow::Borrowed("");
+ }
+ let mut output = String::with_capacity(hint.capacity());
let _ = self.write_to(&mut output);
Cow::Owned(output)
}
@@ -289,7 +315,10 @@ macro_rules! impl_display_with_writeable {
///
/// struct Demo;
/// impl Writeable for Demo {
-/// fn write_to_parts<S: writeable::PartsWrite + ?Sized>(&self, sink: &mut S) -> fmt::Result {
+/// fn write_to_parts<S: writeable::PartsWrite + ?Sized>(
+/// &self,
+/// sink: &mut S,
+/// ) -> fmt::Result {
/// sink.with_part(WORD, |w| w.write_str("foo"))
/// }
/// fn writeable_length_hint(&self) -> LengthHint {
@@ -303,7 +332,13 @@ macro_rules! impl_display_with_writeable {
/// assert_writeable_eq!(&Demo, "foo", "Message: {}", "Hello World");
///
/// assert_writeable_parts_eq!(&Demo, "foo", [(0, 3, WORD)]);
-/// assert_writeable_parts_eq!(&Demo, "foo", [(0, 3, WORD)], "Message: {}", "Hello World");
+/// assert_writeable_parts_eq!(
+/// &Demo,
+/// "foo",
+/// [(0, 3, WORD)],
+/// "Message: {}",
+/// "Hello World"
+/// );
/// ```
#[macro_export]
macro_rules! assert_writeable_eq {
@@ -316,10 +351,19 @@ macro_rules! assert_writeable_eq {
assert_eq!(actual_str, $expected_str, $($arg)*);
assert_eq!(actual_str, $crate::Writeable::write_to_string(actual_writeable), $($arg)+);
let length_hint = $crate::Writeable::writeable_length_hint(actual_writeable);
- assert!(length_hint.0 <= actual_str.len(), $($arg)*);
+ assert!(
+ length_hint.0 <= actual_str.len(),
+ "hint lower bound {} larger than actual length {}: {}",
+ length_hint.0, actual_str.len(), format!($($arg)*),
+ );
if let Some(upper) = length_hint.1 {
- assert!(actual_str.len() <= upper, $($arg)*);
+ assert!(
+ actual_str.len() <= upper,
+ "hint upper bound {} smaller than actual length {}: {}",
+ length_hint.0, actual_str.len(), format!($($arg)*),
+ );
}
+ assert_eq!(actual_writeable.to_string(), $expected_str);
}};
}
@@ -340,6 +384,7 @@ macro_rules! assert_writeable_parts_eq {
if let Some(upper) = length_hint.1 {
assert!(actual_str.len() <= upper, $($arg)+);
}
+ assert_eq!(actual_writeable.to_string(), $expected_str);
}};
}
@@ -371,7 +416,10 @@ pub fn writeable_to_parts_for_test<W: Writeable>(
) -> fmt::Result {
let start = self.string.len();
f(self)?;
- self.parts.push((start, self.string.len(), part));
+ let end = self.string.len();
+ if start < end {
+ self.parts.push((start, end, part));
+ }
Ok(())
}
}
diff --git a/vendor/writeable/src/ops.rs b/vendor/writeable/src/ops.rs
index 3ed4406d7..2ccad7d6d 100644
--- a/vendor/writeable/src/ops.rs
+++ b/vendor/writeable/src/ops.rs
@@ -82,7 +82,10 @@ impl core::ops::BitOr<LengthHint> for LengthHint {
/// struct NonDeterministicWriteable(String, String);
///
/// impl Writeable for NonDeterministicWriteable {
- /// fn write_to<W: fmt::Write + ?Sized>(&self, sink: &mut W) -> fmt::Result {
+ /// fn write_to<W: fmt::Write + ?Sized>(
+ /// &self,
+ /// sink: &mut W,
+ /// ) -> fmt::Result {
/// sink.write_str(if coin_flip() { &self.0 } else { &self.1 })
/// }
///
diff --git a/vendor/xflags-macros/.cargo-checksum.json b/vendor/xflags-macros/.cargo-checksum.json
index fcc17d504..9f20539ff 100644
--- a/vendor/xflags-macros/.cargo-checksum.json
+++ b/vendor/xflags-macros/.cargo-checksum.json
@@ -1 +1 @@
-{"files":{"Cargo.toml":"dff52eef5d3a126eefb38eb66ecb194dd9ccd22a6e010df2b672d83264ac65a5","src/ast.rs":"1f3be0fa1c340dbd98f56fd1c10a43b081d4b9179b1666a3dd3f32d8082e452c","src/emit.rs":"03e692330adc927c1d7ea36faebec0df997dd2e6bfb4816661988078b59fdb0b","src/lib.rs":"ce57137b3db248a73b201a5add6b1ac5c80e431e2bc2947962d4b0b6f397a449","src/parse.rs":"15e860ce666b17228ae537b322c096a64696c83b620468a14112bab30c0432a8","src/update.rs":"133dbc864182808ea7679b815863117b51ccc59a0e43796321f9d5a2edcb3ed6","tests/data/help.rs":"a952a2f641fa6db5c7bd25d8480c1dff4f1146db21a0629e0506e4bc87c46d0c","tests/data/repeated_pos.rs":"60b7d6378583765ddda1be127d3f40aa34cf802c64008e9d3a456f5e20100290","tests/data/smoke.rs":"c5d626382c22f147deb0be9396bf4f8256d64618451f8c9b85002d3525c7fff6","tests/data/subcommands.rs":"c2020f895380c95ca6c97f124615ed64f838a6ee3d1bcce8842029c6cef55188","tests/it/help.rs":"d12aba6869f7d40984c9294591fb97fea7d8caf062969e5ae640ba21957a26c3","tests/it/main.rs":"08311bc06020d980867bd696040c6ddd4893700c7a181d4b9d256ef100945a46","tests/it/repeated_pos.rs":"f9acef062eda5ad43722cade6ebde4c0077174a0fae4e2c3c9555ad6dd490599","tests/it/smoke.rs":"3324c20e79258fca2dfe30a7312b5e192d09c104a30142b1362dd89e746d1306","tests/it/subcommands.rs":"900726a1309d753aa3b666c9b3051ec0b26cb1bf59c1d072704d8e497cfa18c4"},"package":"2afbd7f2039bb6cad2dd45f0c5dff49c0d4e26118398768b7a605524d4251809"} \ No newline at end of file
+{"files":{"Cargo.toml":"922faf706912dc58a85a5b8b6a22a7e2dbe17a8682776d25aa8f88c06a3d3bc2","src/ast.rs":"1f3be0fa1c340dbd98f56fd1c10a43b081d4b9179b1666a3dd3f32d8082e452c","src/emit.rs":"03e692330adc927c1d7ea36faebec0df997dd2e6bfb4816661988078b59fdb0b","src/lib.rs":"ce57137b3db248a73b201a5add6b1ac5c80e431e2bc2947962d4b0b6f397a449","src/parse.rs":"15e860ce666b17228ae537b322c096a64696c83b620468a14112bab30c0432a8","src/update.rs":"133dbc864182808ea7679b815863117b51ccc59a0e43796321f9d5a2edcb3ed6","tests/data/help.rs":"a952a2f641fa6db5c7bd25d8480c1dff4f1146db21a0629e0506e4bc87c46d0c","tests/data/repeated_pos.rs":"60b7d6378583765ddda1be127d3f40aa34cf802c64008e9d3a456f5e20100290","tests/data/smoke.rs":"c5d626382c22f147deb0be9396bf4f8256d64618451f8c9b85002d3525c7fff6","tests/data/subcommands.rs":"c2020f895380c95ca6c97f124615ed64f838a6ee3d1bcce8842029c6cef55188","tests/it/help.rs":"d12aba6869f7d40984c9294591fb97fea7d8caf062969e5ae640ba21957a26c3","tests/it/main.rs":"bbae0bff66ccd22f5fb1bcff08d7acadc3c93644bdb90b6f9d9b6ff76dbb9d1a","tests/it/repeated_pos.rs":"f9acef062eda5ad43722cade6ebde4c0077174a0fae4e2c3c9555ad6dd490599","tests/it/smoke.rs":"3324c20e79258fca2dfe30a7312b5e192d09c104a30142b1362dd89e746d1306","tests/it/subcommands.rs":"900726a1309d753aa3b666c9b3051ec0b26cb1bf59c1d072704d8e497cfa18c4"},"package":"f58e7b3ca8977093aae6b87b6a7730216fc4c53a6530bab5c43a783cd810c1a8"} \ No newline at end of file
diff --git a/vendor/xflags-macros/Cargo.toml b/vendor/xflags-macros/Cargo.toml
index 70b748f0a..45ce51de8 100644
--- a/vendor/xflags-macros/Cargo.toml
+++ b/vendor/xflags-macros/Cargo.toml
@@ -12,7 +12,7 @@
[package]
edition = "2021"
name = "xflags-macros"
-version = "0.3.0"
+version = "0.3.1"
authors = ["Aleksey Kladov <aleksey.kladov@gmail.com>"]
description = "Private implementation details of xflags."
license = "MIT OR Apache-2.0"
diff --git a/vendor/xflags-macros/tests/it/main.rs b/vendor/xflags-macros/tests/it/main.rs
index 7d77bda36..bee65b015 100644
--- a/vendor/xflags-macros/tests/it/main.rs
+++ b/vendor/xflags-macros/tests/it/main.rs
@@ -230,3 +230,73 @@ fn subcommand_flag_inheritance() {
expect!["unexpected flag: `--dir`"],
);
}
+
+#[test]
+fn edge_cases() {
+ check(
+ subcommands::RustAnalyzer::from_vec,
+ "server --dir --log",
+ expect![[r#"
+ RustAnalyzer {
+ verbose: 0,
+ subcommand: Server(
+ Server {
+ dir: Some(
+ "--log",
+ ),
+ subcommand: Launch(
+ Launch {
+ log: false,
+ },
+ ),
+ },
+ ),
+ }
+ "#]],
+ );
+ check(
+ subcommands::RustAnalyzer::from_vec,
+ "server --dir -- --log",
+ expect![[r#"
+ RustAnalyzer {
+ verbose: 0,
+ subcommand: Server(
+ Server {
+ dir: Some(
+ "--",
+ ),
+ subcommand: Launch(
+ Launch {
+ log: true,
+ },
+ ),
+ },
+ ),
+ }
+ "#]],
+ );
+ check(
+ subcommands::RustAnalyzer::from_vec,
+ "-- -v server",
+ expect![[r#"unexpected argument: "-v""#]],
+ );
+ check(repeated_pos::RepeatedPos::from_vec, "pos 1 prog -j", expect!["unexpected flag: `-j`"]);
+ check(
+ repeated_pos::RepeatedPos::from_vec,
+ "pos 1 -- prog -j",
+ expect![[r#"
+ RepeatedPos {
+ a: "pos",
+ b: Some(
+ 1,
+ ),
+ c: Some(
+ "prog",
+ ),
+ rest: [
+ "-j",
+ ],
+ }
+ "#]],
+ );
+}
diff --git a/vendor/xflags/.cargo-checksum.json b/vendor/xflags/.cargo-checksum.json
index 1fa4dd9e5..ccb82afb6 100644
--- a/vendor/xflags/.cargo-checksum.json
+++ b/vendor/xflags/.cargo-checksum.json
@@ -1 +1 @@
-{"files":{"Cargo.lock":"bff2ffbef3ca253bcde1624bfc2c2afd244ca39b44e7dd3f4b463873904129c7","Cargo.toml":"faa866c2c32635dfa6d600103595777c330520df5e73aa0461d6f34eb21bbd9a","examples/hello-generated.rs":"3bf7922435ae84e2b8ae022aba1d693fc4e523b354d3141cc62a183864531f31","examples/hello.rs":"235426d1a69eeba790d1e4fc2ac4fa8f30ca16952edb2a026cf6f4b8c78d6fec","examples/immediate-mode.rs":"dcae135769b6104801de7b91fd220fb28ddae097ba7b0474fe32c28a90c4dfef","examples/longer.rs":"b55684fdde16a8462e1c1afaa9f30e75e3472abfcabe950403733c767dd7de96","examples/non-utf8.rs":"23b563180d1d616f81e224890192799a06fdbc21f3ccb7e4234ca51b3c467a9a","src/lib.rs":"780d7be977abefaa4c7229733a916d88480c9228ddb0f9bc2a25aaa626f7f7d7","src/rt.rs":"b80e6b1e180b0bd0fd523a6bc74d6bba40da7af461de37c33c3735bfb3c66254"},"package":"cbf19f5031a1a812e96fede16f8161218883079946cea87619d3613db1efd268"} \ No newline at end of file
+{"files":{"Cargo.lock":"29daddfd833005b0bce977a938c88f5d48e1e7f2112950b266719c0d9c30de87","Cargo.toml":"027201abeeab5b32f12827e94aa78a9e96e43e9c59aa99b1f038949103e1fdd9","examples/hello-generated.rs":"3bf7922435ae84e2b8ae022aba1d693fc4e523b354d3141cc62a183864531f31","examples/hello.rs":"235426d1a69eeba790d1e4fc2ac4fa8f30ca16952edb2a026cf6f4b8c78d6fec","examples/immediate-mode.rs":"dcae135769b6104801de7b91fd220fb28ddae097ba7b0474fe32c28a90c4dfef","examples/longer.rs":"b55684fdde16a8462e1c1afaa9f30e75e3472abfcabe950403733c767dd7de96","examples/non-utf8.rs":"23b563180d1d616f81e224890192799a06fdbc21f3ccb7e4234ca51b3c467a9a","src/lib.rs":"780d7be977abefaa4c7229733a916d88480c9228ddb0f9bc2a25aaa626f7f7d7","src/rt.rs":"be5393c690afde9c8c31b01471100eec21742f735983ef9074c3675daf942ac7"},"package":"c4554b580522d0ca238369c16b8f6ce34524d61dafe7244993754bbd05f2c2ea"} \ No newline at end of file
diff --git a/vendor/xflags/Cargo.lock b/vendor/xflags/Cargo.lock
index e2020eb16..d4df44759 100644
--- a/vendor/xflags/Cargo.lock
+++ b/vendor/xflags/Cargo.lock
@@ -4,13 +4,13 @@ version = 3
[[package]]
name = "xflags"
-version = "0.3.0"
+version = "0.3.1"
dependencies = [
"xflags-macros",
]
[[package]]
name = "xflags-macros"
-version = "0.3.0"
+version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2afbd7f2039bb6cad2dd45f0c5dff49c0d4e26118398768b7a605524d4251809"
+checksum = "f58e7b3ca8977093aae6b87b6a7730216fc4c53a6530bab5c43a783cd810c1a8"
diff --git a/vendor/xflags/Cargo.toml b/vendor/xflags/Cargo.toml
index 091002385..3db90b6be 100644
--- a/vendor/xflags/Cargo.toml
+++ b/vendor/xflags/Cargo.toml
@@ -12,7 +12,7 @@
[package]
edition = "2021"
name = "xflags"
-version = "0.3.0"
+version = "0.3.1"
authors = ["Aleksey Kladov <aleksey.kladov@gmail.com>"]
description = "Moderately simple command line arguments parser."
categories = ["command-line-interface"]
@@ -21,4 +21,4 @@ repository = "https://github.com/matklad/xflags"
resolver = "1"
[dependencies.xflags-macros]
-version = "=0.3.0"
+version = "=0.3.1"
diff --git a/vendor/xflags/src/rt.rs b/vendor/xflags/src/rt.rs
index 988e6cc23..0b3d98c2b 100644
--- a/vendor/xflags/src/rt.rs
+++ b/vendor/xflags/src/rt.rs
@@ -15,36 +15,41 @@ macro_rules! bail {
}
pub struct Parser {
+ after_double_dash: bool,
rargs: Vec<OsString>,
}
impl Parser {
pub fn new(mut args: Vec<OsString>) -> Self {
args.reverse();
- Self { rargs: args }
+ Self { after_double_dash: false, rargs: args }
}
pub fn new_from_env() -> Self {
- let mut args = std::env::args_os().collect::<Vec<_>>();
- args.reverse();
- args.pop();
- Self { rargs: args }
- }
-
- pub fn is_empty(&self) -> bool {
- self.rargs.is_empty()
+ let args = std::env::args_os().collect::<Vec<_>>();
+ let mut res = Parser::new(args);
+ let _progn = res.next();
+ res
}
- pub fn peek_flag(&self) -> Option<&str> {
- self.rargs.last().and_then(|it| it.to_str()).filter(|it| it.starts_with('-'))
- }
pub fn pop_flag(&mut self) -> Option<Result<String, OsString>> {
- if self.peek_flag().is_some() {
- self.next().map(|it| it.into_string())
- } else {
+ if self.after_double_dash {
self.next().map(Err)
+ } else {
+ let arg = self.next()?;
+ let arg_str = arg.to_str().unwrap_or_default();
+ if arg_str.starts_with('-') {
+ if arg_str == "--" {
+ self.after_double_dash = true;
+ return self.next().map(Err);
+ }
+ Some(arg.into_string())
+ } else {
+ Some(Err(arg))
+ }
}
}
+
pub fn push_back(&mut self, arg: Result<String, OsString>) {
let arg = match arg {
Ok(it) => it.into(),
@@ -53,15 +58,12 @@ impl Parser {
self.rargs.push(arg)
}
- pub fn next(&mut self) -> Option<OsString> {
+ fn next(&mut self) -> Option<OsString> {
self.rargs.pop()
}
pub fn next_value(&mut self, flag: &str) -> Result<OsString> {
- if self.peek_flag().is_some() {
- bail!("expected a value for `{}`", flag)
- }
- self.next().ok_or_else(|| format_err!("expected a value for `{}`", flag))
+ self.next().ok_or_else(|| format_err!("expected a value for `{flag}`"))
}
pub fn next_value_from_str<T: FromStr>(&mut self, flag: &str) -> Result<T>
@@ -77,21 +79,19 @@ impl Parser {
T::Err: fmt::Display,
{
match value.into_string() {
- Ok(str) => {
- str.parse::<T>().map_err(|err| format_err!("can't parse `{}`, {}", flag, err))
- }
+ Ok(str) => str.parse::<T>().map_err(|err| format_err!("can't parse `{flag}`, {err}")),
Err(it) => {
- bail!("can't parse `{}`, invalid utf8: {:?}", flag, it)
+ bail!("can't parse `{flag}`, invalid utf8: {it:?}")
}
}
}
pub fn unexpected_flag(&self, flag: &str) -> Error {
- format_err!("unexpected flag: `{}`", flag)
+ format_err!("unexpected flag: `{flag}`")
}
pub fn unexpected_arg(&self, arg: OsString) -> Error {
- format_err!("unexpected argument: {:?}", arg)
+ format_err!("unexpected argument: {arg:?}")
}
pub fn subcommand_required(&self) -> Error {
@@ -104,15 +104,15 @@ impl Parser {
pub fn optional<T>(&self, flag: &str, mut vals: Vec<T>) -> Result<Option<T>> {
if vals.len() > 1 {
- bail!("flag specified more than once: `{}`", flag)
+ bail!("flag specified more than once: `{flag}`")
}
Ok(vals.pop())
}
pub fn required<T>(&self, flag: &str, mut vals: Vec<T>) -> Result<T> {
if vals.len() > 1 {
- bail!("flag specified more than once: `{}`", flag)
+ bail!("flag specified more than once: `{flag}`")
}
- vals.pop().ok_or_else(|| format_err!("flag is required: `{}`", flag))
+ vals.pop().ok_or_else(|| format_err!("flag is required: `{flag}`"))
}
}
diff --git a/vendor/xshell-macros/.cargo-checksum.json b/vendor/xshell-macros/.cargo-checksum.json
index 5198d9797..d909058ce 100644
--- a/vendor/xshell-macros/.cargo-checksum.json
+++ b/vendor/xshell-macros/.cargo-checksum.json
@@ -1 +1 @@
-{"files":{"Cargo.toml":"4c4a333e83824134161380aa9efb26335313dbca9f09e6a7160d53ce4c2f6918","src/lib.rs":"d91daf4306a265ab7343600f8bab807e059de30c04b9e0494faec45404a7efaa"},"package":"88301b56c26dd9bf5c43d858538f82d6f3f7764767defbc5d34e59459901c41a"} \ No newline at end of file
+{"files":{"Cargo.toml":"710b08bcced4154e543123ae84063e615d944d16746ec63c9c55a842223f8aaf","src/lib.rs":"d91daf4306a265ab7343600f8bab807e059de30c04b9e0494faec45404a7efaa"},"package":"1dbabb1cbd15a1d6d12d9ed6b35cc6777d4af87ab3ba155ea37215f20beab80c"} \ No newline at end of file
diff --git a/vendor/xshell-macros/Cargo.toml b/vendor/xshell-macros/Cargo.toml
index c95f0be33..190b1bf88 100644
--- a/vendor/xshell-macros/Cargo.toml
+++ b/vendor/xshell-macros/Cargo.toml
@@ -13,7 +13,7 @@
edition = "2021"
rust-version = "1.59"
name = "xshell-macros"
-version = "0.2.2"
+version = "0.2.3"
authors = ["Aleksey Kladov <aleksey.kladov@gmail.com>"]
description = "Private implementation detail of xshell crate"
license = "MIT OR Apache-2.0"
diff --git a/vendor/xshell/.cargo-checksum.json b/vendor/xshell/.cargo-checksum.json
index dd079af53..bb849f85b 100644
--- a/vendor/xshell/.cargo-checksum.json
+++ b/vendor/xshell/.cargo-checksum.json
@@ -1 +1 @@
-{"files":{"CHANGELOG.md":"dd08a5079cd2e437eb1269f7c60be9c05ce97db407dbb95a631d64c0f1c478a1","Cargo.lock":"f8f5019959ed5fcd772c3cf199220be41ce1e7b2b9a35b153c52f9c8f3a35171","Cargo.toml":"04a9cad4d6a6e7c756c35d3ba776334f0c47b895e54f7006a27617430c84b25f","LICENSE-APACHE":"a9040321c3712d8fd0b09cf52b17445de04a23a10165049ae187cd39e5c86be5","LICENSE-MIT":"23f18e03dc49df91622fe2a76176497404e46ced8a715d9d2b67a7446571cca3","README.md":"a480b1b8b943c633c64ce9c215f8ecea24e58c7242fe4605d37e7a3be810ab9f","examples/ci.rs":"d5fbfc199469c08f3d459164c05a85c1a0a8f1bef625b347533ad7a43c1e97fb","examples/clone_and_publish.rs":"94568ef665e65527417bb5d50b0404bc60d6a72942d70260c8f3ce1a99820077","src/error.rs":"9222d0b21a889c9fbac1d285c6d43573be9c94f0ea5c02b4bd692bdc02753b49","src/lib.rs":"61d7c1dcd569e60188baba51521661c177bff5a27bcf5272bd83f06542c2304a","tests/compile_time.rs":"224f3476eff4070fbd62c1974e7e69996efd92263bc12f7ddbd59823d85484da","tests/data/xecho.rs":"7a82252daade541bc3843fffa617fc50bf2faf7eebc55e4442a0bc9bb59182fd","tests/it/compile_failures.rs":"c87a438583c9f4b4e45a7422df3ee7c6bd5e69150eba5468425c63aa70fa47d3","tests/it/env.rs":"e863965669378e603c36186e1c738914e3d2300cbe3b04288a9ed689edcf09fb","tests/it/main.rs":"1bb089455f92d6486bf80502ebbbd1f136248194b9c454949f21ed279ea58028","tests/it/tidy.rs":"f530cf51504d43716e849ac96fb64a3a6ef80bd3e56b6eb1bd7b5325dc2f2de9"},"package":"6d47097dc5c85234b1e41851b3422dd6d19b3befdd35b4ae5ce386724aeca981"} \ No newline at end of file
+{"files":{"CHANGELOG.md":"c6e15e05c13991d47bbbd21c1fad9005c14de8dfca06a10c860fa1c70f1e069b","Cargo.lock":"1ee8c4b1409e8fecca09396a23d5199a29b04e6f710d04f0d4b5264279a6cb3c","Cargo.toml":"a4617f00daab17b57f080dff8b331d3847433a4fa65b30945d109df0aad6680b","LICENSE-APACHE":"a9040321c3712d8fd0b09cf52b17445de04a23a10165049ae187cd39e5c86be5","LICENSE-MIT":"23f18e03dc49df91622fe2a76176497404e46ced8a715d9d2b67a7446571cca3","README.md":"a480b1b8b943c633c64ce9c215f8ecea24e58c7242fe4605d37e7a3be810ab9f","examples/ci.rs":"d5fbfc199469c08f3d459164c05a85c1a0a8f1bef625b347533ad7a43c1e97fb","examples/clone_and_publish.rs":"94568ef665e65527417bb5d50b0404bc60d6a72942d70260c8f3ce1a99820077","src/error.rs":"9222d0b21a889c9fbac1d285c6d43573be9c94f0ea5c02b4bd692bdc02753b49","src/lib.rs":"8bc6f4eab9734a46a717718001a79825a50874da324bb405b29adb17c6e2f220","tests/compile_time.rs":"224f3476eff4070fbd62c1974e7e69996efd92263bc12f7ddbd59823d85484da","tests/data/xecho.rs":"7a82252daade541bc3843fffa617fc50bf2faf7eebc55e4442a0bc9bb59182fd","tests/it/compile_failures.rs":"c87a438583c9f4b4e45a7422df3ee7c6bd5e69150eba5468425c63aa70fa47d3","tests/it/env.rs":"e863965669378e603c36186e1c738914e3d2300cbe3b04288a9ed689edcf09fb","tests/it/main.rs":"1bb089455f92d6486bf80502ebbbd1f136248194b9c454949f21ed279ea58028","tests/it/tidy.rs":"f530cf51504d43716e849ac96fb64a3a6ef80bd3e56b6eb1bd7b5325dc2f2de9"},"package":"962c039b3a7b16cf4e9a4248397c6585c07547412e7d6a6e035389a802dcfe90"} \ No newline at end of file
diff --git a/vendor/xshell/CHANGELOG.md b/vendor/xshell/CHANGELOG.md
index cbef62a3e..997a28d3c 100644
--- a/vendor/xshell/CHANGELOG.md
+++ b/vendor/xshell/CHANGELOG.md
@@ -1,5 +1,9 @@
# Changelog
+## 0.2.3
+
+- Fix bug where `Cmd::run` would ignore specified stdin.
+
## 0.2.2
- Add `Shell::path_exists`.
diff --git a/vendor/xshell/Cargo.lock b/vendor/xshell/Cargo.lock
index 1ea0d8ff2..bcea12812 100644
--- a/vendor/xshell/Cargo.lock
+++ b/vendor/xshell/Cargo.lock
@@ -4,13 +4,13 @@ version = 3
[[package]]
name = "anyhow"
-version = "1.0.57"
+version = "1.0.66"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "08f9b8508dccb7687a1d6c4ce66b2b0ecef467c94667de27d8d7fe1f8d2a9cdc"
+checksum = "216261ddc8289130e551ddcd5ce8a064710c0d064a4d2895c67151c92b5443f6"
[[package]]
name = "xshell"
-version = "0.2.2"
+version = "0.2.3"
dependencies = [
"anyhow",
"xshell-macros",
@@ -18,6 +18,6 @@ dependencies = [
[[package]]
name = "xshell-macros"
-version = "0.2.2"
+version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "88301b56c26dd9bf5c43d858538f82d6f3f7764767defbc5d34e59459901c41a"
+checksum = "1dbabb1cbd15a1d6d12d9ed6b35cc6777d4af87ab3ba155ea37215f20beab80c"
diff --git a/vendor/xshell/Cargo.toml b/vendor/xshell/Cargo.toml
index f4fb7cff2..781152f51 100644
--- a/vendor/xshell/Cargo.toml
+++ b/vendor/xshell/Cargo.toml
@@ -13,7 +13,7 @@
edition = "2021"
rust-version = "1.59"
name = "xshell"
-version = "0.2.2"
+version = "0.2.3"
authors = ["Aleksey Kladov <aleksey.kladov@gmail.com>"]
exclude = [".github/", "bors.toml", "rustfmt.toml", "cbench", "mock_bin/"]
description = "Utilities for quick shell scripting in Rust"
@@ -22,6 +22,6 @@ license = "MIT OR Apache-2.0"
repository = "https://github.com/matklad/xshell"
resolver = "2"
[dependencies.xshell-macros]
-version = "=0.2.2"
+version = "=0.2.3"
[dev-dependencies.anyhow]
version = "1.0.56"
diff --git a/vendor/xshell/src/lib.rs b/vendor/xshell/src/lib.rs
index 6b980ba22..02d6276f1 100644
--- a/vendor/xshell/src/lib.rs
+++ b/vendor/xshell/src/lib.rs
@@ -960,10 +960,7 @@ impl<'a> Cmd<'a> {
if !self.data.quiet {
eprintln!("$ {}", self);
}
- let mut command = self.to_command();
- let status = command.status().map_err(|err| Error::new_cmd_io(self, err))?;
- self.check_status(status)?;
- Ok(())
+ self.output_impl(false, false).map(|_| ())
}
/// Run the command and return its stdout as a string.
diff --git a/vendor/yoke-derive/.cargo-checksum.json b/vendor/yoke-derive/.cargo-checksum.json
index 00b384ec1..5ab332567 100644
--- a/vendor/yoke-derive/.cargo-checksum.json
+++ b/vendor/yoke-derive/.cargo-checksum.json
@@ -1 +1 @@
-{"files":{"Cargo.lock":"749614197321ed7a12f39f677ac7ff5f47b38bd0b610b0448d31eb0acbbfad2d","Cargo.toml":"efb71924dd343a2bc1c174a5068b9178f96d63967d32b0668d27cdc5c3e53332","LICENSE":"4ad7541d66a407234e2c84902124cef325c29f3e966353efdb800bedb8b8da21","README.md":"a386dfc08e98106071c34adf2cdfea6a60c5a1d71ca9c9ed383a4922148d14d7","examples/yoke_derive.rs":"787ad9872040733c243ec81e67e0b9651937d4e01670b6f050c13e82f1c24a4e","src/lib.rs":"f2fd1a01134d82d34c67539929ad7119f29795b719b534309ef39cbb0b2bb4de","src/visitor.rs":"24545c1e81fd35c1d2bd38a1c8d1e684dd08faed4d10d75b103c371df4446c21"},"package":"1346e4cd025ae818b88566eac7eb65ab33a994ea55f355c86889af2e7e56b14e"} \ No newline at end of file
+{"files":{"Cargo.lock":"745a4d99005483f6b9b4eae8db5ea6b260c1913df23ce26d27ad8885c2707003","Cargo.toml":"e4302428531ee62c223811af40a8a73f8c3e8b9d2da51c83b97d1c80a442f69d","LICENSE":"4ad7541d66a407234e2c84902124cef325c29f3e966353efdb800bedb8b8da21","README.md":"a386dfc08e98106071c34adf2cdfea6a60c5a1d71ca9c9ed383a4922148d14d7","examples/yoke_derive.rs":"787ad9872040733c243ec81e67e0b9651937d4e01670b6f050c13e82f1c24a4e","src/lib.rs":"a320049225282da281b8b5fdb2513f8e4bf81b6b784a21dc8c2bd0f53baed85f","src/visitor.rs":"24545c1e81fd35c1d2bd38a1c8d1e684dd08faed4d10d75b103c371df4446c21"},"package":"ca800d73d6b7a7ee54f2608205c98b549fca71c9500c1abcb3abdc7708b4a8cb"} \ No newline at end of file
diff --git a/vendor/yoke-derive/Cargo.lock b/vendor/yoke-derive/Cargo.lock
index 2822aee8f..6ee02cebf 100644
--- a/vendor/yoke-derive/Cargo.lock
+++ b/vendor/yoke-derive/Cargo.lock
@@ -4,39 +4,27 @@ version = 3
[[package]]
name = "proc-macro2"
-version = "1.0.47"
+version = "1.0.50"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5ea3d908b0e36316caf9e9e2c4625cdde190a7e6f440d794667ed17a1855e725"
+checksum = "6ef7d57beacfaf2d8aee5937dab7b7f28de3cb8b1828479bb5de2a7106f2bae2"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
-version = "1.0.21"
+version = "1.0.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179"
+checksum = "8856d8364d252a14d474036ea1358d63c9e6965c8e5c1885c18f73d70bff9c7b"
dependencies = [
"proc-macro2",
]
[[package]]
-name = "serde"
-version = "1.0.145"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "728eb6351430bccb993660dfffc5a72f91ccc1295abaa8ce19b27ebe4f75568b"
-
-[[package]]
-name = "stable_deref_trait"
-version = "1.2.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3"
-
-[[package]]
name = "syn"
-version = "1.0.103"
+version = "1.0.107"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a864042229133ada95abf3b54fdc62ef5ccabe9515b64717bcb9a1919e59445d"
+checksum = "1f4064b5b16e03ae50984a5a8ed5d4f8803e6bc1fd170a3cda91a1be4b18e3f5"
dependencies = [
"proc-macro2",
"quote",
@@ -57,9 +45,9 @@ dependencies = [
[[package]]
name = "unicode-ident"
-version = "1.0.5"
+version = "1.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6ceab39d59e4c9499d4e5a8ee0e2735b891bb7308ac83dfb4e80cad195c9f6f3"
+checksum = "84a22b9f218b40614adcb3f4ff08b703773ad44fa9423e4e0d346d5db86e4ebc"
[[package]]
name = "unicode-xid"
@@ -68,68 +56,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c"
[[package]]
-name = "yoke"
-version = "0.6.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1fe1d55ca72c32d573bfbd5cb2f0ca65a497854c44762957a6d3da96041a5184"
-dependencies = [
- "serde",
- "stable_deref_trait",
- "yoke-derive 0.6.0",
- "zerofrom",
-]
-
-[[package]]
-name = "yoke-derive"
-version = "0.6.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "58c2c5bb7c929b85c1b9ec69091b0d835f0878b4fd9eb67973b25936e06c4374"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn",
- "synstructure",
-]
-
-[[package]]
name = "yoke-derive"
-version = "0.6.1"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn",
- "synstructure",
- "yoke",
- "zerovec",
-]
-
-[[package]]
-name = "zerofrom"
-version = "0.1.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "79e9355fccf72b04b7deaa99ce7a0f6630530acf34045391b74460fcd714de54"
-dependencies = [
- "zerofrom-derive",
-]
-
-[[package]]
-name = "zerofrom-derive"
-version = "0.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8785f47d6062c1932866147f91297286a9f350b3070e9d9f0b6078e37d623c1a"
+version = "0.7.0"
dependencies = [
"proc-macro2",
"quote",
"syn",
"synstructure",
]
-
-[[package]]
-name = "zerovec"
-version = "0.9.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b9d919a74c17749ccb17beaf6405562e413cd94e98ba52ca1e64bbe7eefbd8b8"
-dependencies = [
- "yoke",
- "zerofrom",
-]
diff --git a/vendor/yoke-derive/Cargo.toml b/vendor/yoke-derive/Cargo.toml
index 4d1eedac9..85e25ffa0 100644
--- a/vendor/yoke-derive/Cargo.toml
+++ b/vendor/yoke-derive/Cargo.toml
@@ -12,7 +12,7 @@
[package]
edition = "2018"
name = "yoke-derive"
-version = "0.6.1"
+version = "0.7.0"
authors = ["Manish Goregaokar <manishsmail@gmail.com>"]
description = "Custom derive for the yoke crate"
keywords = [
@@ -32,6 +32,9 @@ license = "Unicode-DFS-2016"
repository = "https://github.com/unicode-org/icu4x"
resolver = "2"
+[package.metadata.workspaces]
+independent = true
+
[lib]
path = "src/lib.rs"
proc_macro = true
@@ -52,10 +55,4 @@ features = [
[dependencies.synstructure]
version = "0.12.4"
-[dev-dependencies.yoke]
-version = "0.6.0"
-features = ["derive"]
-
-[dev-dependencies.zerovec]
-version = "0.9"
-features = ["yoke"]
+[dev-dependencies]
diff --git a/vendor/yoke-derive/src/lib.rs b/vendor/yoke-derive/src/lib.rs
index 615669d84..4c53bef68 100644
--- a/vendor/yoke-derive/src/lib.rs
+++ b/vendor/yoke-derive/src/lib.rs
@@ -81,8 +81,6 @@ fn yokeable_derive_impl(input: &DeriveInput) -> TokenStream2 {
f(self)
}
}
- // This is safe because there are no lifetime parameters.
- unsafe impl<'a, #(#tybounds),*> yoke::IsCovariant<'a> for #name<#(#typarams),*> where #(#static_bounds),* {}
}
} else {
if lts != 1 {
@@ -110,11 +108,11 @@ fn yokeable_derive_impl(input: &DeriveInput) -> TokenStream2 {
.collect();
let mut yoke_bounds: Vec<WherePredicate> = vec![];
structure.bind_with(|_| synstructure::BindStyle::Move);
- let body = structure.each_variant(|vi| {
+ let owned_body = structure.each_variant(|vi| {
vi.construct(|f, i| {
let binding = format!("__binding_{}", i);
let field = Ident::new(&binding, Span::call_site());
- let fty = replace_lifetime(&f.ty, static_lt());
+ let fty_static = replace_lifetime(&f.ty, static_lt());
let (has_ty, has_lt) = visitor::check_type_for_parameters(&f.ty, &generics_env);
if has_ty {
@@ -123,11 +121,14 @@ fn yokeable_derive_impl(input: &DeriveInput) -> TokenStream2 {
// to `FieldTy: Yokeable` that need to be satisfied. We get them to be satisfied by requiring
// `FieldTy<'static>: Yokeable<FieldTy<'a>>`
if has_lt {
- let a_ty = replace_lifetime(&f.ty, custom_lt("'a"));
- yoke_bounds
- .push(parse_quote!(#fty: yoke::Yokeable<'a, Output = #a_ty>));
+ let fty_a = replace_lifetime(&f.ty, custom_lt("'a"));
+ yoke_bounds.push(
+ parse_quote!(#fty_static: yoke::Yokeable<'a, Output = #fty_a>),
+ );
} else {
- yoke_bounds.push(parse_quote!(#fty: yoke::Yokeable<'a, Output = #fty>));
+ yoke_bounds.push(
+ parse_quote!(#fty_static: yoke::Yokeable<'a, Output = #fty_static>),
+ );
}
}
if has_ty || has_lt {
@@ -135,7 +136,7 @@ fn yokeable_derive_impl(input: &DeriveInput) -> TokenStream2 {
// that the lifetimes are covariant, since this requirement
// must already be true for the type that implements transform_owned().
quote! {
- <#fty as yoke::Yokeable<'a>>::transform_owned(#field)
+ <#fty_static as yoke::Yokeable<'a>>::transform_owned(#field)
}
} else {
// No nested lifetimes, so nothing to be done
@@ -143,6 +144,30 @@ fn yokeable_derive_impl(input: &DeriveInput) -> TokenStream2 {
}
})
});
+ let borrowed_body = structure.each(|binding| {
+ let f = binding.ast();
+ let field = &binding.binding;
+
+ let (has_ty, has_lt) = visitor::check_type_for_parameters(&f.ty, &generics_env);
+
+ if has_ty || has_lt {
+ let fty_static = replace_lifetime(&f.ty, static_lt());
+ let fty_a = replace_lifetime(&f.ty, custom_lt("'a"));
+ // We also must assert that each individual field can `transform()` correctly
+ //
+ // Even though transform_owned() does such an assertion already, CoerceUnsized
+ // can cause type transformations that allow it to succeed where this would fail.
+ // We need to check both.
+ //
+ // https://github.com/unicode-org/icu4x/issues/2928
+ quote! {
+ let _: &#fty_a = &<#fty_static as yoke::Yokeable<'a>>::transform(#field);
+ }
+ } else {
+ // No nested lifetimes, so nothing to be done
+ quote! {}
+ }
+ });
return quote! {
unsafe impl<'a, #(#tybounds),*> yoke::Yokeable<'a> for #name<'static, #(#typarams),*>
where #(#static_bounds,)*
@@ -150,6 +175,12 @@ fn yokeable_derive_impl(input: &DeriveInput) -> TokenStream2 {
type Output = #name<'a, #(#typarams),*>;
#[inline]
fn transform(&'a self) -> &'a Self::Output {
+ // These are just type asserts, we don't need them for anything
+ if false {
+ match self {
+ #borrowed_body
+ }
+ }
unsafe {
// safety: we have asserted covariance in
// transform_owned
@@ -158,7 +189,7 @@ fn yokeable_derive_impl(input: &DeriveInput) -> TokenStream2 {
}
#[inline]
fn transform_owned(self) -> Self::Output {
- match self { #body }
+ match self { #owned_body }
}
#[inline]
unsafe fn make(this: Self::Output) -> Self {
@@ -206,6 +237,7 @@ fn yokeable_derive_impl(input: &DeriveInput) -> TokenStream2 {
// are the same
debug_assert!(mem::size_of::<Self::Output>() == mem::size_of::<Self>());
let ptr: *const Self = (&this as *const Self::Output).cast();
+ #[allow(clippy::forget_copy)] // This is a noop if the struct is copy, which Clippy doesn't like
mem::forget(this);
ptr::read(ptr)
}
@@ -216,9 +248,6 @@ fn yokeable_derive_impl(input: &DeriveInput) -> TokenStream2 {
unsafe { f(core::mem::transmute::<&'a mut Self, &'a mut Self::Output>(self)) }
}
}
- // This is safe because it is in the same block as the above impl, which only compiles
- // if 'a is a covariant lifetime.
- unsafe impl<'a, #(#tybounds),*> yoke::IsCovariant<'a> for #name<'a, #(#typarams),*> where #(#static_bounds),* {}
}
}
}
diff --git a/vendor/yoke/.cargo-checksum.json b/vendor/yoke/.cargo-checksum.json
index 1052beac5..4b8d4839c 100644
--- a/vendor/yoke/.cargo-checksum.json
+++ b/vendor/yoke/.cargo-checksum.json
@@ -1 +1 @@
-{"files":{"Cargo.toml":"a26eaa79fc44d47a95490b583429bc252338eafe17172ddecc5fed5b90709748","LICENSE":"4ad7541d66a407234e2c84902124cef325c29f3e966353efdb800bedb8b8da21","README.md":"30321954bbc84770e2b50e8cc6da2a9e98f97698cbf1fe829747d4f3c6f6f791","src/either.rs":"028bb043392d1f3d608589d65d997a241b5ba7bb5114cf023179a38bf1c1cf2b","src/erased.rs":"97e545e421f08ae22c6bd8b4d89c9f91876a0b502cc74984dce77f0506decc4d","src/is_covariant.rs":"2d7f92083473be10847b4471917994eee060bf9e31f5d2672ac78cfe64be91b9","src/lib.rs":"5cf0694e0168c8240de935a2187d3f34d2b1ebe03429662df45b5bd97d3226ff","src/macro_impls.rs":"7d626660f4f7a0148710c5b308511604bff1010b813f124ba43ec4e591057981","src/trait_hack.rs":"d3a8b93e0a984febabd288af558d25e5a93019e2bf9209bc023762c9182aa7fc","src/yoke.rs":"8ec18fbbeaf9a87d87a3b5cbc859c49d5929a0bdbf43586d70000294c6dae26f","src/yokeable.rs":"1b2e04f620ab7c06c557d23c44b7ebb67736ae239c44277f4fbefbacc011e549","src/zero_from.rs":"c863d016c1e73bbac25f189c78c544ae65649d20fc9412f385a023d30c9a16f5"},"package":"1fe1d55ca72c32d573bfbd5cb2f0ca65a497854c44762957a6d3da96041a5184"} \ No newline at end of file
+{"files":{"Cargo.toml":"73b21b61d53b8b31994e0a5f9509aa0d26212a28bcf2ac1606deb83c6e975197","LICENSE":"4ad7541d66a407234e2c84902124cef325c29f3e966353efdb800bedb8b8da21","README.md":"30321954bbc84770e2b50e8cc6da2a9e98f97698cbf1fe829747d4f3c6f6f791","src/either.rs":"028bb043392d1f3d608589d65d997a241b5ba7bb5114cf023179a38bf1c1cf2b","src/erased.rs":"a97a1be3436314e34903a59330a8f61f96f5543c73d96853c09c32392dd09898","src/lib.rs":"9168593ad938bb19c867a3fde27911003b108ae40efed87741bd5d036c914a39","src/macro_impls.rs":"f81ac8af77ac3641bfee116d6295f5f756f92d4b3b6c7d43a228cd313174d355","src/trait_hack.rs":"d3a8b93e0a984febabd288af558d25e5a93019e2bf9209bc023762c9182aa7fc","src/yoke.rs":"91f8f8b5ea15b42d79c0790eaf1e08607a42bd92e9773db05281e3e1eb9dbb82","src/yokeable.rs":"1b2e04f620ab7c06c557d23c44b7ebb67736ae239c44277f4fbefbacc011e549","src/zero_from.rs":"71d97f87e003db0eb0e97064509bdf9355622ccd655549f926b6a0d9119db3ee"},"package":"222180af14a6b54ef2c33493c1eff77ae95a3687a21b243e752624006fb8f26e"} \ No newline at end of file
diff --git a/vendor/yoke/Cargo.toml b/vendor/yoke/Cargo.toml
index d8629127d..a20e850b6 100644
--- a/vendor/yoke/Cargo.toml
+++ b/vendor/yoke/Cargo.toml
@@ -12,7 +12,7 @@
[package]
edition = "2018"
name = "yoke"
-version = "0.6.2"
+version = "0.7.0"
authors = ["Manish Goregaokar <manishsmail@gmail.com>"]
include = [
"src/**/*",
@@ -40,6 +40,9 @@ license = "Unicode-DFS-2016"
repository = "https://github.com/unicode-org/icu4x"
resolver = "2"
+[package.metadata.workspaces]
+independent = true
+
[package.metadata.docs.rs]
all-features = true
@@ -53,11 +56,11 @@ version = "1.2.0"
default-features = false
[dependencies.yoke-derive]
-version = "0.6.0"
+version = "0.7.0"
optional = true
[dependencies.zerofrom]
-version = "0.1.0"
+version = "0.1.1"
optional = true
default-features = false
@@ -70,7 +73,7 @@ version = "1.0.125"
[features]
alloc = [
"stable_deref_trait/alloc",
- "serde/alloc",
+ "serde?/alloc",
"zerofrom/alloc",
]
default = [
@@ -78,6 +81,6 @@ default = [
"zerofrom",
]
derive = [
- "yoke-derive",
+ "dep:yoke-derive",
"zerofrom/derive",
]
diff --git a/vendor/yoke/src/erased.rs b/vendor/yoke/src/erased.rs
index c314d5186..bc4de9791 100644
--- a/vendor/yoke/src/erased.rs
+++ b/vendor/yoke/src/erased.rs
@@ -7,7 +7,7 @@
//! See the docs of [`Yoke::erase_rc_cart()`](crate::Yoke::erase_rc_cart)
//! and [`Yoke::erase_box_cart()`](crate::Yoke::erase_box_cart) for more info.
//!
-//! Available with the `"alloc"` feature enabled.
+//! Available with the `"alloc"` Cargo feature enabled.
use alloc::boxed::Box;
use alloc::rc::Rc;
@@ -25,17 +25,17 @@ impl<T: 'static> ErasedDestructor for T {}
///
/// See the docs of [`Yoke::erase_arc_cart()`](crate::Yoke::erase_rc_cart) for more info.
///
-/// Available with the `"alloc"` feature enabled.
+/// Available with the `"alloc"` Cargo feature enabled.
pub type ErasedArcCart = Arc<dyn ErasedDestructor + Send + Sync>;
/// A type-erased Cart that has `Rc` semantics
///
/// See the docs of [`Yoke::erase_rc_cart()`](crate::Yoke::erase_rc_cart) for more info.
///
-/// Available with the `"alloc"` feature enabled.
+/// Available with the `"alloc"` Cargo feature enabled.
pub type ErasedRcCart = Rc<dyn ErasedDestructor>;
/// A type-erased Cart that has `Box` semantics
///
/// See the docs of [`Yoke::erase_box_cart()`](crate::Yoke::erase_box_cart) for more info.
///
-/// Available with the `"alloc"` feature enabled.
+/// Available with the `"alloc"` Cargo feature enabled.
pub type ErasedBoxCart = Box<dyn ErasedDestructor>;
diff --git a/vendor/yoke/src/is_covariant.rs b/vendor/yoke/src/is_covariant.rs
deleted file mode 100644
index 75d123c84..000000000
--- a/vendor/yoke/src/is_covariant.rs
+++ /dev/null
@@ -1,142 +0,0 @@
-// This file is part of ICU4X. For terms of use, please see the file
-// called LICENSE at the top level of the ICU4X source tree
-// (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ).
-
-#[cfg(feature = "alloc")]
-use alloc::{
- borrow::{Cow, ToOwned},
- boxed::Box,
- rc::Rc,
- string::String,
-};
-
-/// A type implementing `IsCovariant<'a>` is covariant with respect to lifetime `'a`.
-///
-/// Lifetime parameters that are safely cast in [`Yokeable`] are also valid for `IsCovariant`.
-///
-/// `IsCovariant` exists primarily to serve in trait bounds. The primary use case is to safely
-/// perform lifetime casting on trait objects (`dyn Trait`). This enables a type-erased [`Yoke`]
-/// consisting of only trait objects. See the examples.
-///
-/// `IsCovariant` is auto-implemented in [`#[derive(Yokeable)]`](macro@crate::Yokeable).
-///
-/// # Safety
-///
-/// This trait is safe to implement on types with a _covariant_ lifetime parameter. This will
-/// occur when the lifetime parameter is used within references, but not in the arguments of
-/// function pointers or in mutable positions (either in `&mut` or via interior mutability).
-///
-/// If a struct has multiple lifetime parameters, only the one used in `IsCovariant<'a>` needs to
-/// be covariant.
-///
-/// # Examples
-///
-/// Implementing on a simple struct with a single covariant lifetime:
-///
-/// ```
-/// # use yoke::*;
-/// struct MyStruct<'a>(&'a str);
-///
-/// // This is safe because 'a is covariant
-/// unsafe impl<'a> IsCovariant<'a> for MyStruct<'a> {}
-/// ```
-///
-/// By constraining the trait `ExampleTrait<'a>` on `IsCovariant<'a>`, we can safely implement
-/// [`Yokeable`] and [`ZeroFrom`] on its trait object:
-///
-/// ```
-/// # use yoke::*;
-/// # use zerofrom::*;
-/// # use core::mem;
-/// trait ExampleTrait<'a>: IsCovariant<'a> {
-/// fn get_message(&self) -> &'a str;
-/// }
-///
-/// // This wrapper is required because of the blanket Yokeable impl on &'static T
-/// pub struct ExampleTraitDynRef<'a>(pub &'a dyn ExampleTrait<'a>);
-///
-/// // The following impl is safe because the trait object requires IsCovariant.
-/// unsafe impl<'a> Yokeable<'a> for ExampleTraitDynRef<'static> {
-/// type Output = ExampleTraitDynRef<'a>;
-/// fn transform(&'a self) -> &'a Self::Output {
-/// unsafe { mem::transmute(self) }
-/// }
-///
-/// fn transform_owned(self) -> Self::Output {
-/// unsafe { mem::transmute(self) }
-/// }
-///
-/// unsafe fn make(from: Self::Output) -> Self {
-/// unsafe { mem::transmute(from) }
-/// }
-///
-/// fn transform_mut<F>(&'a mut self, f: F)
-/// where
-/// F: 'static + FnOnce(&'a mut Self::Output),
-/// {
-/// unsafe { f(mem::transmute::<&mut Self, &mut Self::Output>(self)) }
-/// }
-/// }
-///
-/// impl<'zf, 'a> ZeroFrom<'zf, dyn ExampleTrait<'a> + 'a> for ExampleTraitDynRef<'zf> {
-/// fn zero_from(this: &'zf (dyn ExampleTrait<'a> + 'a)) -> ExampleTraitDynRef<'zf> {
-/// // This is safe because the trait object requires IsCovariant.
-/// ExampleTraitDynRef(unsafe { core::mem::transmute(this) })
-/// }
-/// }
-///
-/// // Implement ExampleTrait on the struct from the previous example
-/// # struct MyStruct<'a>(&'a str);
-/// # unsafe impl<'a> IsCovariant<'a> for MyStruct<'a> {}
-/// impl<'a> ExampleTrait<'a> for MyStruct<'a> {
-/// fn get_message(&self) -> &'a str {
-/// self.0
-/// }
-/// }
-///
-/// // Example usage: a Yoke of a trait object
-/// let s = "Hello World".to_string();
-/// let yoke: Yoke<ExampleTraitDynRef<'static>, Box<dyn ExampleTrait>> =
-/// Yoke::attach_to_zero_copy_cart(Box::new(MyStruct(&s)));
-///
-/// assert_eq!(yoke.get().0.get_message(), "Hello World");
-/// ```
-///
-/// [`Yoke`]: crate::Yoke
-/// [`Yokeable`]: crate::Yokeable
-/// [`ZeroFrom`]: crate::ZeroFrom
-pub unsafe trait IsCovariant<'a>: 'a {}
-
-// IsCovariant is implemented on the standard library Copy types in macro_impls.rs
-
-// The following impls are safe because there is only one lifetime, 'a, and 'a is covariant
-
-unsafe impl<'a> IsCovariant<'a> for () {}
-
-unsafe impl<'a> IsCovariant<'a> for str {}
-#[cfg(feature = "alloc")]
-unsafe impl<'a> IsCovariant<'a> for String {}
-
-unsafe impl<'a, T: IsCovariant<'a>> IsCovariant<'a> for Option<T> {}
-
-unsafe impl<'a, T1: IsCovariant<'a>, T2: IsCovariant<'a>> IsCovariant<'a> for (T1, T2) {}
-
-unsafe impl<'a, T: IsCovariant<'a>> IsCovariant<'a> for [T] {}
-
-unsafe impl<'a, T: IsCovariant<'a>, const N: usize> IsCovariant<'a> for [T; N] {}
-
-#[cfg(feature = "alloc")]
-unsafe impl<'a, T: IsCovariant<'a> + ?Sized> IsCovariant<'a> for Box<T> {}
-
-#[cfg(feature = "alloc")]
-unsafe impl<'a, T: IsCovariant<'a> + ?Sized> IsCovariant<'a> for Rc<T> {}
-
-// This is safe because T has a covariant lifetime, and Cow's lifetime is also covariant
-#[cfg(feature = "alloc")]
-unsafe impl<'a, T: IsCovariant<'a> + ToOwned + ?Sized> IsCovariant<'a> for Cow<'a, T> where
- <T as ToOwned>::Owned: Sized
-{
-}
-
-// This is safe because T has a covariant lifetime, and the reference lifetime is also covariant
-unsafe impl<'a, T: IsCovariant<'a> + ?Sized> IsCovariant<'a> for &'a T {}
diff --git a/vendor/yoke/src/lib.rs b/vendor/yoke/src/lib.rs
index 666e179e9..1524c067c 100644
--- a/vendor/yoke/src/lib.rs
+++ b/vendor/yoke/src/lib.rs
@@ -48,7 +48,6 @@ extern crate alloc;
pub mod either;
#[cfg(feature = "alloc")]
pub mod erased;
-mod is_covariant;
mod macro_impls;
pub mod trait_hack;
mod yoke;
@@ -59,7 +58,6 @@ mod zero_from;
#[cfg(feature = "derive")]
pub use yoke_derive::Yokeable;
-pub use crate::is_covariant::IsCovariant;
pub use crate::yoke::{CloneableCart, Yoke};
pub use crate::yokeable::Yokeable;
diff --git a/vendor/yoke/src/macro_impls.rs b/vendor/yoke/src/macro_impls.rs
index 664816818..060061b20 100644
--- a/vendor/yoke/src/macro_impls.rs
+++ b/vendor/yoke/src/macro_impls.rs
@@ -6,7 +6,7 @@
// than using pointer casts
#![allow(clippy::transmute_ptr_to_ptr)]
-use crate::{IsCovariant, Yokeable};
+use crate::Yokeable;
use core::{mem, ptr};
macro_rules! copy_yoke_impl {
@@ -38,7 +38,6 @@ macro_rules! impl_copy_type {
type Output = Self;
copy_yoke_impl!();
}
- unsafe impl<'a> IsCovariant<'a> for $ty {}
};
}
diff --git a/vendor/yoke/src/yoke.rs b/vendor/yoke/src/yoke.rs
index c3d8c37d9..7468b4d99 100644
--- a/vendor/yoke/src/yoke.rs
+++ b/vendor/yoke/src/yoke.rs
@@ -6,7 +6,6 @@ use crate::either::EitherCart;
#[cfg(feature = "alloc")]
use crate::erased::{ErasedArcCart, ErasedBoxCart, ErasedRcCart};
use crate::trait_hack::YokeTraitHack;
-use crate::IsCovariant;
use crate::Yokeable;
use core::marker::PhantomData;
use core::ops::Deref;
@@ -48,8 +47,7 @@ use alloc::sync::Arc;
/// into another `Yoke` containing a different type that may contain elements of the original yoked
/// value. See the [`Yoke::map_project()`] docs for more details.
///
-/// In general, `C` is a concrete type, but it is also possible for it to be a trait object;
-/// for more information, see [`IsCovariant`].
+/// In general, `C` is a concrete type, but it is also possible for it to be a trait object.
///
/// # Example
///
@@ -83,7 +81,10 @@ pub struct Yoke<Y: for<'a> Yokeable<'a>, C> {
cart: C,
}
-impl<Y: for<'a> Yokeable<'a>, C: StableDeref> Yoke<Y, C> {
+impl<Y: for<'a> Yokeable<'a>, C: StableDeref> Yoke<Y, C>
+where
+ <C as Deref>::Target: 'static,
+{
/// Construct a [`Yoke`] by yokeing an object to a cart in a closure.
///
/// See also [`Yoke::try_attach_to_cart()`] to return a `Result` from the closure.
@@ -116,7 +117,14 @@ impl<Y: for<'a> Yokeable<'a>, C: StableDeref> Yoke<Y, C> {
/// ```
pub fn attach_to_cart<F>(cart: C, f: F) -> Self
where
+ // safety note: This works by enforcing that the *only* place the return value of F
+ // can borrow from is the cart, since `F` must be valid for all lifetimes `'de`
+ //
+ // The <C as Deref>::Target: 'static on the impl is crucial for safety as well
+ //
+ // See safety docs at the bottom of this file for more information
F: for<'de> FnOnce(&'de <C as Deref>::Target) -> <Y as Yokeable<'de>>::Output,
+ <C as Deref>::Target: 'static,
{
let deserialized = f(cart.deref());
Self {
@@ -220,8 +228,10 @@ impl<Y: for<'a> Yokeable<'a>, C> Yoke<Y, C> {
/// ```
/// use yoke::Yoke;
///
- /// let local_data = "foo".to_string();
- /// let yoke = Yoke::<&'static str, Box<String>>::attach_to_zero_copy_cart(Box::new(local_data));
+ /// let local_data = "foo".to_owned();
+ /// let yoke = Yoke::<&'static str, Box<String>>::attach_to_zero_copy_cart(
+ /// Box::new(local_data),
+ /// );
/// assert_eq!(*yoke.get(), "foo");
///
/// // Get back the cart
@@ -235,9 +245,11 @@ impl<Y: for<'a> Yokeable<'a>, C> Yoke<Y, C> {
/// use std::borrow::Cow;
/// use yoke::Yoke;
///
- /// let local_data = "foo".to_string();
+ /// let local_data = "foo".to_owned();
/// let mut yoke =
- /// Yoke::<Cow<'static, str>, Box<String>>::attach_to_zero_copy_cart(Box::new(local_data));
+ /// Yoke::<Cow<'static, str>, Box<String>>::attach_to_zero_copy_cart(
+ /// Box::new(local_data),
+ /// );
/// assert_eq!(yoke.get(), "foo");
///
/// // Override data in the cart
@@ -265,6 +277,9 @@ impl<Y: for<'a> Yokeable<'a>, C> Yoke<Y, C> {
/// - `f()` must not panic
/// - References from the yokeable `Y` should still be valid for the lifetime of the
/// returned cart type `C`.
+ /// - Lifetimes inside C must not be lengthened, even if they are themselves contravariant.
+ /// I.e., if C contains an `fn(&'a u8)`, it cannot be replaced with `fn(&'static u8),
+ /// even though that is typically safe.
///
/// Typically, this means implementing `f` as something which _wraps_ the inner cart type `C`.
/// `Yoke` only really cares about destructors for its carts so it's fine to erase other
@@ -506,12 +521,9 @@ where
}
}
-// This is safe because Y is 'static and C has a covariant lifetime
-unsafe impl<'b, Y: for<'a> Yokeable<'a>, C: IsCovariant<'b>> IsCovariant<'b> for Yoke<Y, C> {}
-
#[test]
fn test_clone() {
- let local_data = "foo".to_string();
+ let local_data = "foo".to_owned();
let y1 = Yoke::<alloc::borrow::Cow<'static, str>, Rc<String>>::attach_to_zero_copy_cart(
Rc::new(local_data),
);
@@ -575,7 +587,9 @@ impl<Y: for<'a> Yokeable<'a>, C> Yoke<Y, C> {
/// string_2: &'a str,
/// }
///
- /// fn map_project_string_1(bar: Yoke<Bar<'static>, Rc<[u8]>>) -> Yoke<&'static str, Rc<[u8]>> {
+ /// fn map_project_string_1(
+ /// bar: Yoke<Bar<'static>, Rc<[u8]>>,
+ /// ) -> Yoke<&'static str, Rc<[u8]>> {
/// bar.map_project(|bar, _| bar.string_1)
/// }
///
@@ -651,7 +665,9 @@ impl<Y: for<'a> Yokeable<'a>, C> Yoke<Y, C> {
/// # use yoke::Yoke;
/// # use std::str::{self, Utf8Error};
/// #
- /// fn slice(y: Yoke<&'static [u8], Rc<[u8]>>) -> Result<Yoke<&'static str, Rc<[u8]>>, Utf8Error> {
+ /// fn slice(
+ /// y: Yoke<&'static [u8], Rc<[u8]>>,
+ /// ) -> Result<Yoke<&'static str, Rc<[u8]>>, Utf8Error> {
/// y.try_map_project(move |bytes, _| str::from_utf8(bytes))
/// }
/// ```
@@ -671,7 +687,9 @@ impl<Y: for<'a> Yokeable<'a>, C> Yoke<Y, C> {
/// string_2: &'a str,
/// }
///
- /// fn map_project_string_1(bar: Yoke<Bar<'static>, Rc<[u8]>>) -> Result<Yoke<&'static str, Rc<[u8]>>, Utf8Error> {
+ /// fn map_project_string_1(
+ /// bar: Yoke<Bar<'static>, Rc<[u8]>>,
+ /// ) -> Result<Yoke<&'static str, Rc<[u8]>>, Utf8Error> {
/// bar.try_map_project(|bar, _| str::from_utf8(bar.bytes_1))
/// }
///
@@ -861,17 +879,19 @@ impl<Y: for<'a> Yokeable<'a>, C: 'static + Sized> Yoke<Y, Rc<C>> {
/// let buffer1: Rc<String> = Rc::new(" foo bar baz ".into());
/// let buffer2: Box<String> = Box::new(" baz quux ".into());
///
- /// let yoke1 = Yoke::<&'static str, _>::attach_to_cart(buffer1, |rc| rc.trim());
+ /// let yoke1 =
+ /// Yoke::<&'static str, _>::attach_to_cart(buffer1, |rc| rc.trim());
/// let yoke2 = Yoke::<&'static str, _>::attach_to_cart(buffer2, |b| b.trim());
///
/// let erased1: Yoke<_, ErasedRcCart> = yoke1.erase_rc_cart();
/// // Wrap the Box in an Rc to make it compatible
- /// let erased2: Yoke<_, ErasedRcCart> = yoke2.wrap_cart_in_rc().erase_rc_cart();
+ /// let erased2: Yoke<_, ErasedRcCart> =
+ /// yoke2.wrap_cart_in_rc().erase_rc_cart();
///
/// // Now erased1 and erased2 have the same type!
/// ```
///
- /// Available with the `"alloc"` feature enabled.
+ /// Available with the `"alloc"` Cargo feature enabled.
pub fn erase_rc_cart(self) -> Yoke<Y, ErasedRcCart> {
unsafe {
// safe because the cart is preserved, just
@@ -905,17 +925,19 @@ impl<Y: for<'a> Yokeable<'a>, C: 'static + Sized + Send + Sync> Yoke<Y, Arc<C>>
/// let buffer1: Arc<String> = Arc::new(" foo bar baz ".into());
/// let buffer2: Box<String> = Box::new(" baz quux ".into());
///
- /// let yoke1 = Yoke::<&'static str, _>::attach_to_cart(buffer1, |arc| arc.trim());
+ /// let yoke1 =
+ /// Yoke::<&'static str, _>::attach_to_cart(buffer1, |arc| arc.trim());
/// let yoke2 = Yoke::<&'static str, _>::attach_to_cart(buffer2, |b| b.trim());
///
/// let erased1: Yoke<_, ErasedArcCart> = yoke1.erase_arc_cart();
/// // Wrap the Box in an Rc to make it compatible
- /// let erased2: Yoke<_, ErasedArcCart> = yoke2.wrap_cart_in_arc().erase_arc_cart();
+ /// let erased2: Yoke<_, ErasedArcCart> =
+ /// yoke2.wrap_cart_in_arc().erase_arc_cart();
///
/// // Now erased1 and erased2 have the same type!
/// ```
///
- /// Available with the `"alloc"` feature enabled.
+ /// Available with the `"alloc"` Cargo feature enabled.
pub fn erase_arc_cart(self) -> Yoke<Y, ErasedArcCart> {
unsafe {
// safe because the cart is preserved, just
@@ -949,17 +971,19 @@ impl<Y: for<'a> Yokeable<'a>, C: 'static + Sized> Yoke<Y, Box<C>> {
/// let buffer1: Rc<String> = Rc::new(" foo bar baz ".into());
/// let buffer2: Box<String> = Box::new(" baz quux ".into());
///
- /// let yoke1 = Yoke::<&'static str, _>::attach_to_cart(buffer1, |rc| rc.trim());
+ /// let yoke1 =
+ /// Yoke::<&'static str, _>::attach_to_cart(buffer1, |rc| rc.trim());
/// let yoke2 = Yoke::<&'static str, _>::attach_to_cart(buffer2, |b| b.trim());
///
/// // Wrap the Rc in an Box to make it compatible
- /// let erased1: Yoke<_, ErasedBoxCart> = yoke1.wrap_cart_in_box().erase_box_cart();
+ /// let erased1: Yoke<_, ErasedBoxCart> =
+ /// yoke1.wrap_cart_in_box().erase_box_cart();
/// let erased2: Yoke<_, ErasedBoxCart> = yoke2.erase_box_cart();
///
/// // Now erased1 and erased2 have the same type!
/// ```
///
- /// Available with the `"alloc"` feature enabled.
+ /// Available with the `"alloc"` Cargo feature enabled.
pub fn erase_box_cart(self) -> Yoke<Y, ErasedBoxCart> {
unsafe {
// safe because the cart is preserved, just
@@ -974,7 +998,7 @@ impl<Y: for<'a> Yokeable<'a>, C> Yoke<Y, C> {
/// Helper function allowing one to wrap the cart type `C` in a `Box<T>`.
/// Can be paired with [`Yoke::erase_box_cart()`]
///
- /// Available with the `"alloc"` feature enabled.
+ /// Available with the `"alloc"` Cargo feature enabled.
#[inline]
pub fn wrap_cart_in_box(self) -> Yoke<Y, Box<C>> {
unsafe {
@@ -986,7 +1010,7 @@ impl<Y: for<'a> Yokeable<'a>, C> Yoke<Y, C> {
/// Can be paired with [`Yoke::erase_rc_cart()`], or generally used
/// to make the [`Yoke`] cloneable.
///
- /// Available with the `"alloc"` feature enabled.
+ /// Available with the `"alloc"` Cargo feature enabled.
#[inline]
pub fn wrap_cart_in_rc(self) -> Yoke<Y, Rc<C>> {
unsafe {
@@ -998,7 +1022,7 @@ impl<Y: for<'a> Yokeable<'a>, C> Yoke<Y, C> {
/// Can be paired with [`Yoke::erase_arc_cart()`], or generally used
/// to make the [`Yoke`] cloneable.
///
- /// Available with the `"alloc"` feature enabled.
+ /// Available with the `"alloc"` Cargo feature enabled.
#[inline]
pub fn wrap_cart_in_arc(self) -> Yoke<Y, Arc<C>> {
unsafe {
@@ -1037,7 +1061,7 @@ impl<Y: for<'a> Yokeable<'a>, C> Yoke<Y, C> {
}
}
-/// Safety docs for project()
+/// # Safety docs for project()
///
/// (Docs are on a private const to allow the use of compile_fail doctests)
///
@@ -1140,3 +1164,151 @@ impl<Y: for<'a> Yokeable<'a>, C> Yoke<Y, C> {
/// the output yokeable can _only_ have borrowed data flow in to it from the input. All paths of unsoundness require the
/// unification of an existential and universal lifetime, which isn't possible.
const _: () = ();
+
+/// # Safety docs for attach_to_cart()'s signature
+///
+/// The `attach_to_cart()` family of methods get by by using the following bound:
+///
+/// ```rust,ignore
+/// F: for<'de> FnOnce(&'de <C as Deref>::Target) -> <Y as Yokeable<'de>>::Output,
+/// C::Target: 'static
+/// ```
+///
+/// to enforce that the yoking closure produces a yokeable that is *only* allowed to borrow from the cart.
+/// A way to be sure of this is as follows: imagine if `F` *did* borrow data of lifetime `'a` and stuff it in
+/// its output. Then that lifetime `'a` would have to live at least as long as `'de` *for all `'de`*.
+/// The only lifetime that satisfies that is `'static` (since at least one of the potential `'de`s is `'static`),
+/// and we're fine with that.
+///
+/// ## Implied bounds and variance
+///
+/// The `C::Target: 'static` bound is tricky, however. Let's imagine a situation where we *didn't* have that bound.
+///
+/// One thing to remember is that we are okay with the cart itself borrowing from places,
+/// e.g. `&[u8]` is a valid cart, as is `Box<&[u8]>`. `C` is not `'static`.
+///
+/// (I'm going to use `CT` in prose to refer to `C::Target` here, since almost everything here has to do
+/// with C::Target and not C itself.)
+///
+/// Unfortunately, there's a sneaky additional bound inside `F`. The signature of `F` is *actually*
+///
+/// ```rust,ignore
+/// F: for<'de> where<C::Target: 'de> FnOnce(&'de C::Target) -> <Y as Yokeable<'de>>::Output
+/// ```
+///
+/// using made-up "where clause inside HRTB" syntax to represent a type that can be represented inside the compiler
+/// and type system but not in Rust code. The `CT: 'de` bond comes from the `&'de C::Target`: any time you
+/// write `&'a T`, an implied bound of `T: 'a` materializes and is stored alongside it, since references cannot refer
+/// to data that itself refers to data of shorter lifetimes. If a reference is valid, its referent must be valid for
+/// the duration of the reference's lifetime, so every reference *inside* its referent must also be valid, giving us `T: 'a`.
+/// This kind of constraint is often called a "well formedness" constraint: `&'a T` is not "well formed" without that
+/// bound, and rustc is being helpful by giving it to us for free.
+///
+/// Unfortunately, this messes with our universal quantification. The `for<'de>` is no longer "For all lifetimes `'de`",
+/// it is "for all lifetimes `'de` *where `CT: 'de`*". And if `CT` borrows from somewhere (with lifetime `'ct`), then we get a
+/// `'ct: 'de` bound, and `'de` candidates that live longer than `'ct` won't actually be considered.
+/// The neat little logic at the beginning stops working.
+///
+/// `attach_to_cart()` will instead enforce that the produced yokeable *either* borrows from the cart (fine), or from
+/// data that has a lifetime that is at least `'ct`. Which means that `attach_to_cart()` will allow us to borrow locals
+/// provided they live at least as long as `'ct`.
+///
+/// Is this a problem?
+///
+/// This is totally fine if CT's lifetime is covariant: if C is something like `Box<&'ct [u8]>`, even if our
+/// yoked object borrows from locals outliving `'ct`, our Yoke can't outlive that
+/// lifetime `'ct` anyway (since it's a part of the cart type), so we're fine.
+///
+/// However it's completely broken for contravariant carts (e.g. `Box<fn(&'ct u8)>`). In that case
+/// we still get `'ct: 'de`, and we still end up being able to
+/// borrow from locals that outlive `'ct`. However, our Yoke _can_ outlive
+/// that lifetime, because Yoke shares its variance over `'ct`
+/// with the cart type, and the cart type is contravariant over `'ct`.
+/// So the Yoke can be upcast to having a longer lifetime than `'ct`, and *that* Yoke
+/// can outlive `'ct`.
+///
+/// We fix this by forcing `C::Target: 'static` in `attach_to_cart()`, which would make it work
+/// for fewer types, but would also allow Yoke to continue to be covariant over cart lifetimes if necessary.
+///
+/// An alternate fix would be to not allowing yoke to ever be upcast over lifetimes contained in the cart
+/// by forcing them to be invariant. This is a bit more restrictive and affects *all* `Yoke` users, not just
+/// those using `attach_to_cart()`.
+///
+/// See https://github.com/unicode-org/icu4x/issues/2926
+/// See also https://github.com/rust-lang/rust/issues/106431 for potentially fixing this upstream by
+/// changing how the bound works.
+///
+/// # Tests
+///
+/// Here's a broken `attach_to_cart()` that attempts to borrow from a local:
+///
+/// ```rust,compile_fail
+/// use yoke::{Yoke, Yokeable};
+///
+/// let cart = vec![1, 2, 3, 4].into_boxed_slice();
+/// let local = vec![4, 5, 6, 7];
+/// let yoke: Yoke<&[u8], Box<[u8]>> = Yoke::attach_to_cart(cart, |_| &*local);
+/// ```
+///
+/// Fails as expected.
+///
+/// And here's a working one with a local borrowed cart that does not do any sneaky borrows whilst attaching.
+///
+/// ```rust
+/// use yoke::{Yoke, Yokeable};
+///
+/// let cart = vec![1, 2, 3, 4].into_boxed_slice();
+/// let local = vec![4, 5, 6, 7];
+/// let yoke: Yoke<&[u8], &[u8]> = Yoke::attach_to_cart(&cart, |c| &*c);
+/// ```
+///
+/// Here's an `attach_to_cart()` that attempts to borrow from a longer-lived local due to
+/// the cart being covariant. It fails, but would not if the alternate fix of forcing Yoke to be invariant
+/// were implemented. It is technically a safe operation:
+///
+/// ```rust,compile_fail
+/// use yoke::{Yoke, Yokeable};
+/// // longer lived
+/// let local = vec![4, 5, 6, 7];
+///
+/// let backing = vec![1, 2, 3, 4];
+/// let cart = Box::new(&*backing);
+///
+/// let yoke: Yoke<&[u8], Box<&[u8]>> = Yoke::attach_to_cart(cart, |_| &*local);
+/// println!("{:?}", yoke.get());
+/// ```
+///
+/// Finally, here's an `attach_to_cart()` that attempts to borrow from a longer lived local
+/// in the case of a contravariant lifetime. It does not compile, but in and of itself is not dangerous:
+///
+/// ```rust,compile_fail
+/// use yoke::Yoke;
+///
+/// type Contra<'a> = fn(&'a ());
+///
+/// let local = String::from("Hello World!");
+/// let yoke: Yoke<&'static str, Box<Contra<'_>>> = Yoke::attach_to_cart(Box::new((|_| {}) as _), |_| &local[..]);
+/// println!("{:?}", yoke.get());
+/// ```
+///
+/// It is dangerous if allowed to transform (testcase from #2926)
+///
+/// ```rust,compile_fail
+/// use yoke::Yoke;
+///
+/// type Contra<'a> = fn(&'a ());
+///
+///
+/// let local = String::from("Hello World!");
+/// let yoke: Yoke<&'static str, Box<Contra<'_>>> = Yoke::attach_to_cart(Box::new((|_| {}) as _), |_| &local[..]);
+/// println!("{:?}", yoke.get());
+/// let yoke_longer: Yoke<&'static str, Box<Contra<'static>>> = yoke;
+/// let leaked: &'static Yoke<&'static str, Box<Contra<'static>>> = Box::leak(Box::new(yoke_longer));
+/// let reference: &'static str = leaked.get();
+///
+/// println!("pre-drop: {reference}");
+/// drop(local);
+/// println!("post-drop: {reference}");
+///
+/// ```
+const _: () = ();
diff --git a/vendor/yoke/src/zero_from.rs b/vendor/yoke/src/zero_from.rs
index 679a28d59..d876d9c06 100644
--- a/vendor/yoke/src/zero_from.rs
+++ b/vendor/yoke/src/zero_from.rs
@@ -26,6 +26,7 @@ where
Y: for<'a> Yokeable<'a>,
for<'a> YokeTraitHack<<Y as Yokeable<'a>>::Output>: ZeroFrom<'a, <C as Deref>::Target>,
C: StableDeref + Deref,
+ <C as Deref>::Target: 'static,
{
/// Construct a [`Yoke`]`<Y, C>` from a cart implementing `StableDeref` by zero-copy cloning
/// the cart to `Y` and then yokeing that object to the cart.
@@ -42,7 +43,9 @@ where
/// use std::borrow::Cow;
/// use yoke::Yoke;
///
- /// let yoke = Yoke::<Cow<'static, str>, String>::attach_to_zero_copy_cart("demo".to_string());
+ /// let yoke = Yoke::<Cow<'static, str>, String>::attach_to_zero_copy_cart(
+ /// "demo".to_owned(),
+ /// );
///
/// assert_eq!("demo", yoke.get());
/// ```
diff --git a/vendor/zerovec-derive/.cargo-checksum.json b/vendor/zerovec-derive/.cargo-checksum.json
index 2b18eb43b..c8b3d36ae 100644
--- a/vendor/zerovec-derive/.cargo-checksum.json
+++ b/vendor/zerovec-derive/.cargo-checksum.json
@@ -1 +1 @@
-{"files":{"Cargo.lock":"45317edd3e500bc9c1b4a5bdbdd818d9675d354f0a635c2b515206a98ca671c0","Cargo.toml":"45b4d104f456e16a84efc97ab6ebdacdc3dac27438d1aba3468e9f390daeab0b","LICENSE":"4ad7541d66a407234e2c84902124cef325c29f3e966353efdb800bedb8b8da21","README.md":"77ca5a17524e17ae9098ab00f91cb67996f5a298468d68a15d23a09bde940b9a","examples/derives.rs":"2541311f2b532301ab8600927fb2d12a842166ce98d57879997df12dcb928dd2","examples/make.rs":"58373c89f49e5c7b343d3ab0cb746a062ea1f6aa8839707751bcee484126e77b","examples/make_var.rs":"8faac589bdfa89bb3e5b97553d2fad1aeebf914586731d26433b3dce966d1523","src/lib.rs":"4f4f2a1c0f0204ac782d741f9a188b474b9c0e23a5e6e4619b9a3e926c1e08e5","src/make_ule.rs":"892a6332a6ca29c51899d00e3581a240306e54842cd21ef26d2d496065278144","src/make_varule.rs":"adb44d66eab1cee9f785d2088115a49a8ae47c16d171e606bbb2bbc626906cd4","src/ule.rs":"1f0a46ff39e43bb19deb9e9a06289350096d4e6ca3f33cb76fec3c84c4a439d8","src/utils.rs":"54cd3a6b39c74dc6e12a4019c14ae2f5dd197e8a678dfbf3158dab61d496deac","src/varule.rs":"b0642df70023b2f04aca692010f6b2a81fd3f3db8612dbae072a200eb04f0913"},"package":"490e5f878c2856225e884c35927e7ea6db3c24cdb7229b72542c7526ad7ed49e"} \ No newline at end of file
+{"files":{"Cargo.lock":"2d7d59a1d4b4efeb00fbab029b36910c0caa82aba59c7490a027c6c568e0a8f6","Cargo.toml":"b80ff2c76944c3d016cb05b21c9c20af190e3492c1961a7a0d69b3ba5b4ae868","LICENSE":"4ad7541d66a407234e2c84902124cef325c29f3e966353efdb800bedb8b8da21","README.md":"77ca5a17524e17ae9098ab00f91cb67996f5a298468d68a15d23a09bde940b9a","examples/derives.rs":"2541311f2b532301ab8600927fb2d12a842166ce98d57879997df12dcb928dd2","examples/make.rs":"58373c89f49e5c7b343d3ab0cb746a062ea1f6aa8839707751bcee484126e77b","examples/make_var.rs":"8faac589bdfa89bb3e5b97553d2fad1aeebf914586731d26433b3dce966d1523","src/lib.rs":"4f4f2a1c0f0204ac782d741f9a188b474b9c0e23a5e6e4619b9a3e926c1e08e5","src/make_ule.rs":"892a6332a6ca29c51899d00e3581a240306e54842cd21ef26d2d496065278144","src/make_varule.rs":"e5e037b18f9533e18c8078c532198995437dd08774f773ada01d901cfdef9bac","src/ule.rs":"1f0a46ff39e43bb19deb9e9a06289350096d4e6ca3f33cb76fec3c84c4a439d8","src/utils.rs":"54cd3a6b39c74dc6e12a4019c14ae2f5dd197e8a678dfbf3158dab61d496deac","src/varule.rs":"b0642df70023b2f04aca692010f6b2a81fd3f3db8612dbae072a200eb04f0913"},"package":"2154cb6e2a748163354165e22c6a555effb09ca2d16334767bf66bb404f2206e"} \ No newline at end of file
diff --git a/vendor/zerovec-derive/Cargo.lock b/vendor/zerovec-derive/Cargo.lock
index 06c4b36b2..a5a1a0bf0 100644
--- a/vendor/zerovec-derive/Cargo.lock
+++ b/vendor/zerovec-derive/Cargo.lock
@@ -13,48 +13,48 @@ dependencies = [
[[package]]
name = "itoa"
-version = "1.0.3"
+version = "1.0.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6c8af84674fe1f223a982c933a0ee1086ac4d4052aa0fb8060c12c6ad838e754"
+checksum = "fad582f4b9e86b6caa621cabeb0963332d92eea04729ab12892c2533951e6440"
[[package]]
name = "proc-macro2"
-version = "1.0.44"
+version = "1.0.50"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7bd7356a8122b6c4a24a82b278680c73357984ca2fc79a0f9fa6dea7dced7c58"
+checksum = "6ef7d57beacfaf2d8aee5937dab7b7f28de3cb8b1828479bb5de2a7106f2bae2"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
-version = "1.0.21"
+version = "1.0.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179"
+checksum = "8856d8364d252a14d474036ea1358d63c9e6965c8e5c1885c18f73d70bff9c7b"
dependencies = [
"proc-macro2",
]
[[package]]
name = "ryu"
-version = "1.0.11"
+version = "1.0.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4501abdff3ae82a1c1b477a17252eb69cee9e66eb915c1abaa4f44d873df9f09"
+checksum = "7b4b9743ed687d4b4bcedf9ff5eaa7398495ae14e61cba0a295704edbc7decde"
[[package]]
name = "serde"
-version = "1.0.145"
+version = "1.0.152"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "728eb6351430bccb993660dfffc5a72f91ccc1295abaa8ce19b27ebe4f75568b"
+checksum = "bb7d1f0d3021d347a83e556fc4683dea2ea09d87bccdf88ff5c12545d89d5efb"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
-version = "1.0.145"
+version = "1.0.152"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "81fa1584d3d1bcacd84c277a0dfe21f5b0f6accf4a23d04d4c6d61f1af522b4c"
+checksum = "af487d118eecd09402d70a5d72551860e788df87b464af30e5ea6a38c75c541e"
dependencies = [
"proc-macro2",
"quote",
@@ -63,9 +63,9 @@ dependencies = [
[[package]]
name = "serde_json"
-version = "1.0.85"
+version = "1.0.91"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e55a28e3aaef9d5ce0506d0a14dbba8054ddc7e499ef522dd8b26859ec9d4a44"
+checksum = "877c235533714907a8c2464236f5c4b2a17262ef1bd71f38f35ea592c8da6883"
dependencies = [
"itoa",
"ryu",
@@ -74,9 +74,9 @@ dependencies = [
[[package]]
name = "syn"
-version = "1.0.101"
+version = "1.0.107"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e90cde112c4b9690b8cbe810cba9ddd8bc1d7472e2cae317b69e9438c1cba7d2"
+checksum = "1f4064b5b16e03ae50984a5a8ed5d4f8803e6bc1fd170a3cda91a1be4b18e3f5"
dependencies = [
"proc-macro2",
"quote",
@@ -97,9 +97,9 @@ dependencies = [
[[package]]
name = "unicode-ident"
-version = "1.0.4"
+version = "1.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dcc811dc4066ac62f84f11307873c4850cb653bfa9b1719cee2bd2204a4bc5dd"
+checksum = "84a22b9f218b40614adcb3f4ff08b703773ad44fa9423e4e0d346d5db86e4ebc"
[[package]]
name = "unicode-xid"
@@ -108,14 +108,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c"
[[package]]
-name = "zerofrom"
-version = "0.1.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "79e9355fccf72b04b7deaa99ce7a0f6630530acf34045391b74460fcd714de54"
-
-[[package]]
name = "zerovec-derive"
-version = "0.9.0"
+version = "0.9.3"
dependencies = [
"bincode",
"proc-macro2",
@@ -124,5 +118,4 @@ dependencies = [
"serde_json",
"syn",
"synstructure",
- "zerofrom",
]
diff --git a/vendor/zerovec-derive/Cargo.toml b/vendor/zerovec-derive/Cargo.toml
index fea429984..d9c2a0592 100644
--- a/vendor/zerovec-derive/Cargo.toml
+++ b/vendor/zerovec-derive/Cargo.toml
@@ -12,7 +12,7 @@
[package]
edition = "2018"
name = "zerovec-derive"
-version = "0.9.0"
+version = "0.9.3"
authors = ["Manish Goregaokar <manishsmail@gmail.com>"]
description = "Custom derive for the zerovec crate"
keywords = [
@@ -32,6 +32,9 @@ license = "Unicode-DFS-2016"
repository = "https://github.com/unicode-org/icu4x"
resolver = "2"
+[package.metadata.workspaces]
+independent = true
+
[lib]
path = "src/lib.rs"
proc_macro = true
@@ -61,6 +64,3 @@ features = ["derive"]
[dev-dependencies.serde_json]
version = "1.0"
-
-[dev-dependencies.zerofrom]
-version = "0.1"
diff --git a/vendor/zerovec-derive/src/make_varule.rs b/vendor/zerovec-derive/src/make_varule.rs
index 7dda4932e..3220b0f8a 100644
--- a/vendor/zerovec-derive/src/make_varule.rs
+++ b/vendor/zerovec-derive/src/make_varule.rs
@@ -115,7 +115,6 @@ pub fn make_varule_impl(attr: AttributeArgs, mut input: DeriveInput) -> TokenStr
let doc = format!("[`VarULE`](zerovec::ule::VarULE) type for {name}");
let varule_struct: DeriveInput = parse_quote!(
#[repr(#repr_attr)]
- #[derive(PartialEq, Eq)]
#[doc = #doc]
#vis struct #ule_name #field_inits #semi
);
@@ -142,6 +141,19 @@ pub fn make_varule_impl(attr: AttributeArgs, mut input: DeriveInput) -> TokenStr
input.span(),
);
+ let eq_impl = quote!(
+ impl core::cmp::PartialEq for #ule_name {
+ fn eq(&self, other: &Self) -> bool {
+ // The VarULE invariants allow us to assume that equality is byte equality
+ // in non-safety-critical contexts
+ <Self as zerovec::ule::VarULE>::as_byte_slice(&self)
+ == <Self as zerovec::ule::VarULE>::as_byte_slice(&other)
+ }
+ }
+
+ impl core::cmp::Eq for #ule_name {}
+ );
+
let zerofrom_fq_path =
quote!(<#name as zerovec::__zerovec_internal_reexport::ZeroFrom<#ule_name>>);
@@ -234,6 +246,8 @@ pub fn make_varule_impl(attr: AttributeArgs, mut input: DeriveInput) -> TokenStr
#maybe_ord_impls
+ #eq_impl
+
#zmkv
#maybe_ser
diff --git a/vendor/zerovec/.cargo-checksum.json b/vendor/zerovec/.cargo-checksum.json
index 4e45eb54b..fbf1303f2 100644
--- a/vendor/zerovec/.cargo-checksum.json
+++ b/vendor/zerovec/.cargo-checksum.json
@@ -1 +1 @@
-{"files":{"Cargo.lock":"4a4e071e00c3386a3870ffdc70c8ff156025f1b25b01f136bbc98e63cffe9525","Cargo.toml":"25e11edaad953215cca394ea63f181dbe0ce0105bd0c1b2439830f613c2b4e2a","LICENSE":"4ad7541d66a407234e2c84902124cef325c29f3e966353efdb800bedb8b8da21","README.md":"95660d3a679736a3308aaf2f43728c3052ed9dc93fdec63de163ca90de531a33","benches/testdata/large_hashmap.postcard":"f327c7c25ee0ac05e0c2052ee38b76c77968240e084477b0f703b5a0bc6f4ccf","benches/testdata/large_zeromap.postcard":"d0f15324e7e3bf8318e87fefad9249c0bda8e8d555c220f81467e0a90270059a","benches/vzv.rs":"eb816f36a3fa29dc94e44d2f78bdb62d07fdf58e72054e24645d3da5091145fa","benches/zeromap.rs":"4833d3bddfc80c20748ca8513059f2ed8029fb9dc2267bf332a0659e895d77fa","benches/zerovec.rs":"e32e380e653c62b1f344cb7be917016b739b2c4e722d62193aa3fa45908e77c0","benches/zerovec_iai.rs":"13028e4f1d85bad3ee5e5b783360b7ea247dd5de233d104b91ce46d19bf5765a","benches/zerovec_serde.rs":"7ed92aaaf5981755b4f02f366e1a0434b49a4a6ffa0945c96663626d787db070","examples/zv_serde.rs":"d7fd49aba0400636c1af16ac1cbf28f8d74c61a94ee7b318dcaf23213acec1e8","src/error.rs":"19ca9ab31b2b16cb0f604ed5f4a43c18796672bfd498af334b47aad76059b143","src/flexzerovec/databake.rs":"a32503b5aa4c3e4d5627e91ab0ec0ffbc40983dab93ba9062e4672ee1e7d0335","src/flexzerovec/mod.rs":"647678116fcf0321463b3451462920f7c517f4cf6c8a57f4f7b13f5248c8b9b0","src/flexzerovec/owned.rs":"dc6ea4cdc1b147f9e64f89281a0315fa729d134617a694646463013314e3ab46","src/flexzerovec/serde.rs":"641821a6753477498d28126bdee10a0a625deb92b39ec8c2d3c2d432d9cb9512","src/flexzerovec/slice.rs":"91dd96c895e5da9d88cff9905deece3baef775282602e9a6f0d368ac6139e2cb","src/flexzerovec/vec.rs":"103b72950ae6be8d1fd4c8db07460c2b6203c87927b722807d329177e8d41d48","src/lib.rs":"c4841809466cff4fc33345638aa1c41500b5f76ad6c93990600176b83f75693d","src/map/borrowed.rs":"56a5d2a305227b2e748b2c7172561ffc7ca68302039b21947cc68cf7c6e7c02e","src/map/databake.rs":"29afbc7882f30ce63596e2cb98f589f24bd76919d7062a18f02a5df630f31dce","src/map/kv.rs":"03f3745df8d61ff399b66d32ba1ac9a7ee298ca00dfb463c3ea8d81c746e9d41","src/map/map.rs":"24094239ef0281241c080f6d80375eea8aacbb3ac303a1bd76d7845a8bd70419","src/map/mod.rs":"4961ad14522fcef16b1aad804d9559c0a5eb2582fdd163bf76f9629cb765b6c4","src/map/serde.rs":"e5ee812805788672c40bc912ed70b241328a4098ecc1acea332b92456d082f9b","src/map/serde_helpers.rs":"72787005972b93e49b9dc17aa47d30699364e6da9dc95aadb820ce58e4bf5c54","src/map/vecs.rs":"86c9b04a92b7a918af3653e05fbf622fbb1b52b0a4307a5dadef070882778233","src/map2d/borrowed.rs":"cfbed2709cf0dc508c2da1f6a9c49b6e22deacd19679e296af4e44da3052fe07","src/map2d/cursor.rs":"c19b3d0b13b3cc5d0b3f2fbc246ed511f8ec9ec77a83a2be1aabea0d09c8d3a7","src/map2d/databake.rs":"c9451511566f9589236789c8dc5fbb32112a8324bd9b4bae75cd3be05b42962c","src/map2d/map.rs":"663dbb62f3fe003d5d5587955f693b9e3ee55ac1d366487df45bd302aa5855e7","src/map2d/mod.rs":"80beae7a263f1fe39c9a06d287c9150480fe3ed43397c2a7475a50ee2b2fd37f","src/map2d/serde.rs":"ff25b5b5f40b8bc438f18a96d646c22b0d670a89a3fe822a38b573ce7dc7fc32","src/samples.rs":"a3a2571da3a911f20bad9179441ba2676f4e5cf1ca2408a4dc6111cadbcef6cd","src/ule/chars.rs":"f8b32dd407dcc05b7d416c361d7a7c2166708d1edaa0559c829bd449dcb0a7aa","src/ule/custom.rs":"49604e3c1d67836a7e783b91ef2bfeaddfbe4758d6c5614ce3cd1ae60cfdb5ea","src/ule/encode.rs":"91a11ff2f2ddf3dffc1411343e286249e63b0cfa076d6c41f83ea952c527b014","src/ule/mod.rs":"5550fd0e3c59562bc1e6b417a5c61882d776b906f83befd78608f448323b930c","src/ule/multi.rs":"ed470e4b62c6233ee81b33f473eccf1e8db75db52275ec371cdc2b477478d959","src/ule/niche.rs":"1c64b5862cd7f1cd384160012a39414a335ea1f36119bb5fc56ac7cb5e050d8b","src/ule/option.rs":"0b1ba426e665f7a7fd67e736bf8552a86859b30dc83c35751156f18133e1cf99","src/ule/plain.rs":"acd4507776963459228b5425866e92e7363124f48f96abd28ba99a7c6245709f","src/ule/slices.rs":"a7638535898b39be9f489f3ff9a2140b5334113c2ddc48c4fae2bc8b86efbd14","src/ule/tuple.rs":"498f6863b1af1e6b2c655e77df53cf9818613c60189b2ce1369850e388d09e3c","src/ule/unvalidated.rs":"26b937c6b44afbd94f0e2397e29db820c0eaa7c116c427304741957e825d5893","src/varzerovec/components.rs":"6810dc5cf007572a4e22831f55822f79f720e29309c33b1c546057fd5dedfb61","src/varzerovec/databake.rs":"819c6e511e4256cb0c1e3fbf2bad521472f133355ce0cc12e46c97ec2f71dbb2","src/varzerovec/mod.rs":"c7aaaf571f7406e666d877920966a2e39373b5cf6a038cb31dbe4192b2e75d4d","src/varzerovec/owned.rs":"0aac2dd14fde57c22f4b5a943756ee90001d824d04682336782700c1f7efd272","src/varzerovec/serde.rs":"e008df1773393340abdf1c1cc80ab9035881b5f5de1e48bf4edde0963198bde7","src/varzerovec/slice.rs":"6e03824809aa1d5dcae20844f7d40c2521a824774185fc82b23ed9327b0a6468","src/varzerovec/vec.rs":"49e66dc827ff8fad20dbe86a92239f2131d16c41d7ca6e56f636325a3ff576c6","src/yoke_impls.rs":"84ef42aa194dd56502dba63283652b3783a34b3069211920e5587256c62c4abe","src/zerofrom_impls.rs":"a3e02b3473cf6deba8c0e9dd815ad7db7ced75e7ad3b353597faea189b63c1d5","src/zerovec/databake.rs":"8d1f857fa89b8b64c7a5e2b2ba84d06b266b3cf6c716bc383c9004a6602c5d43","src/zerovec/mod.rs":"3c52bd0f02a92a2c1e8226b26db82c72bc5fa66ded67e1cd6fc05ac3caa1913a","src/zerovec/serde.rs":"873e6e07e4efda0643d77c920067c4b5a30e188da5a176d623b785bbd2980bab","src/zerovec/slice.rs":"e969657302ec0ab822bf6abbb46cce5a4e53ac49e4f7f1db5ed10962926c7adf"},"package":"b9d919a74c17749ccb17beaf6405562e413cd94e98ba52ca1e64bbe7eefbd8b8"} \ No newline at end of file
+{"files":{"Cargo.lock":"ab1a55fa6a0e30a1509d639a0a0c77f500470ddaf6b34a1a9e83ecd7931b9648","Cargo.toml":"977eb85b9a33c508f31264b230c72c66cbf1fd11de723ac79153c1b4f3080b58","LICENSE":"4ad7541d66a407234e2c84902124cef325c29f3e966353efdb800bedb8b8da21","README.md":"6f1174cdbf3467cb6f02e6f715bf105b833cea392995c18ed28cda871c4e15fa","benches/testdata/large_hashmap.postcard":"f327c7c25ee0ac05e0c2052ee38b76c77968240e084477b0f703b5a0bc6f4ccf","benches/testdata/large_zeromap.postcard":"d0f15324e7e3bf8318e87fefad9249c0bda8e8d555c220f81467e0a90270059a","benches/vzv.rs":"2b0de82b4a40d45151e7faa2d18cfcb65351059f3f391dd64f031c565212c561","benches/zeromap.rs":"eb001722b4158a405610d2cb8aa4ccbb53d5e29ea0898639912cf7d55598de6c","benches/zerovec.rs":"e32e380e653c62b1f344cb7be917016b739b2c4e722d62193aa3fa45908e77c0","benches/zerovec_iai.rs":"13028e4f1d85bad3ee5e5b783360b7ea247dd5de233d104b91ce46d19bf5765a","benches/zerovec_serde.rs":"7ed92aaaf5981755b4f02f366e1a0434b49a4a6ffa0945c96663626d787db070","examples/zv_serde.rs":"d7fd49aba0400636c1af16ac1cbf28f8d74c61a94ee7b318dcaf23213acec1e8","src/error.rs":"19ca9ab31b2b16cb0f604ed5f4a43c18796672bfd498af334b47aad76059b143","src/flexzerovec/databake.rs":"a32503b5aa4c3e4d5627e91ab0ec0ffbc40983dab93ba9062e4672ee1e7d0335","src/flexzerovec/mod.rs":"647678116fcf0321463b3451462920f7c517f4cf6c8a57f4f7b13f5248c8b9b0","src/flexzerovec/owned.rs":"dc6ea4cdc1b147f9e64f89281a0315fa729d134617a694646463013314e3ab46","src/flexzerovec/serde.rs":"a0c7a8fcf5ef06f5ea44cbfb89cac47f173c7150082d0cd745a457de3d375b4f","src/flexzerovec/slice.rs":"6c115b32011d127bb59f1818e7d1061a0786a8b2d4d7d174f43acf02189d73eb","src/flexzerovec/vec.rs":"103b72950ae6be8d1fd4c8db07460c2b6203c87927b722807d329177e8d41d48","src/lib.rs":"0e91c4fb200f27665b509796fd4d0672578d140502721a645fe068f23d6aa2bd","src/map/borrowed.rs":"abd5886b384075780498ddc39300eeeda0bc520bdee1cea43096f50a9ac42f07","src/map/databake.rs":"29afbc7882f30ce63596e2cb98f589f24bd76919d7062a18f02a5df630f31dce","src/map/kv.rs":"03f3745df8d61ff399b66d32ba1ac9a7ee298ca00dfb463c3ea8d81c746e9d41","src/map/map.rs":"d0298742d6f46ca39f3ebc9f0761ab2997523da40df5c9ea9515a8584b266c50","src/map/mod.rs":"4961ad14522fcef16b1aad804d9559c0a5eb2582fdd163bf76f9629cb765b6c4","src/map/serde.rs":"3bed09076a45774c65a8116dd21e72413f1657ed569fe32c4abb48e979fd3144","src/map/serde_helpers.rs":"72787005972b93e49b9dc17aa47d30699364e6da9dc95aadb820ce58e4bf5c54","src/map/vecs.rs":"86c9b04a92b7a918af3653e05fbf622fbb1b52b0a4307a5dadef070882778233","src/map2d/borrowed.rs":"f2a1f927c6d0942fd8ad183de24a32a2b1450f2f747cb328862163f6d9505ebb","src/map2d/cursor.rs":"e4447e7b5869e895b852124443151918bff5fe8cfb5207acfe5ff7b57b56bfdf","src/map2d/databake.rs":"c9451511566f9589236789c8dc5fbb32112a8324bd9b4bae75cd3be05b42962c","src/map2d/map.rs":"358408292de4c06e82f6eebf2f014d3737241f383d8fc3c946bfb44da1071b3b","src/map2d/mod.rs":"80beae7a263f1fe39c9a06d287c9150480fe3ed43397c2a7475a50ee2b2fd37f","src/map2d/serde.rs":"c4f32f25bc6e850eccd677e5b0cf9cd796df71855b80459893c0323ad7901bd5","src/samples.rs":"a3a2571da3a911f20bad9179441ba2676f4e5cf1ca2408a4dc6111cadbcef6cd","src/ule/chars.rs":"f8b32dd407dcc05b7d416c361d7a7c2166708d1edaa0559c829bd449dcb0a7aa","src/ule/custom.rs":"49604e3c1d67836a7e783b91ef2bfeaddfbe4758d6c5614ce3cd1ae60cfdb5ea","src/ule/encode.rs":"91a11ff2f2ddf3dffc1411343e286249e63b0cfa076d6c41f83ea952c527b014","src/ule/mod.rs":"4a71652bb0d771aee247518a1c50e72bdea12fd884feaf7f55385808047069ef","src/ule/multi.rs":"ed470e4b62c6233ee81b33f473eccf1e8db75db52275ec371cdc2b477478d959","src/ule/niche.rs":"1c64b5862cd7f1cd384160012a39414a335ea1f36119bb5fc56ac7cb5e050d8b","src/ule/option.rs":"32979913da36452a27951e3f073494006c26f570af5733a1b0ce5a75427300b4","src/ule/plain.rs":"27f47ce32cbcb62ef088dbd60dbb9d79c2d54e1a3ff024cdc863362542b74336","src/ule/slices.rs":"a7638535898b39be9f489f3ff9a2140b5334113c2ddc48c4fae2bc8b86efbd14","src/ule/tuple.rs":"498f6863b1af1e6b2c655e77df53cf9818613c60189b2ce1369850e388d09e3c","src/ule/unvalidated.rs":"a92f2e94ba8bb50b6f63914549501653aa0622b6d6810824c271afe37edc367a","src/varzerovec/components.rs":"6810dc5cf007572a4e22831f55822f79f720e29309c33b1c546057fd5dedfb61","src/varzerovec/databake.rs":"819c6e511e4256cb0c1e3fbf2bad521472f133355ce0cc12e46c97ec2f71dbb2","src/varzerovec/mod.rs":"c7aaaf571f7406e666d877920966a2e39373b5cf6a038cb31dbe4192b2e75d4d","src/varzerovec/owned.rs":"0aac2dd14fde57c22f4b5a943756ee90001d824d04682336782700c1f7efd272","src/varzerovec/serde.rs":"efb06a8b139dffc6d0534f7e0de4dc39b82ed224481f25bc5dea14d0159b5208","src/varzerovec/slice.rs":"4524631711cfa9ac530f116fc2801526d1d14e7a21ead10aa2bfb3f4de298cac","src/varzerovec/vec.rs":"6557bc9a146cc6563a17a62c3e8d38b68ba1451ff99d5741d0bbdb5b67703573","src/yoke_impls.rs":"3d2486b99eda20cc2c9dd6360d5589f95e6b2bfce847c3637b91134836f73566","src/zerofrom_impls.rs":"a3e02b3473cf6deba8c0e9dd815ad7db7ced75e7ad3b353597faea189b63c1d5","src/zerovec/databake.rs":"8d1f857fa89b8b64c7a5e2b2ba84d06b266b3cf6c716bc383c9004a6602c5d43","src/zerovec/mod.rs":"777a70ac94f0c80869f4576d8aaad5c96083a94eb3c3db86ebc98b4805b4a0ff","src/zerovec/serde.rs":"3a088c88732ffc0814a09777f89a83857e948c1eff6dfc2d1eb6bad5ece3976a","src/zerovec/slice.rs":"49c29036ddc9efee1fc327152a78e9d20f8f8174a71468dfe6d68a6437882419"},"package":"154df60c74c4a844bc04a53cef4fc18a909d3ea07e19f5225eaba86209da3aa6"} \ No newline at end of file
diff --git a/vendor/zerovec/Cargo.lock b/vendor/zerovec/Cargo.lock
index 59e492118..f722be128 100644
--- a/vendor/zerovec/Cargo.lock
+++ b/vendor/zerovec/Cargo.lock
@@ -3,19 +3,10 @@
version = 3
[[package]]
-name = "aho-corasick"
-version = "0.7.19"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b4f55bd91a0978cbfd91c457a164bab8b4001c833b7f323132c0a4e1922dd44e"
-dependencies = [
- "memchr",
-]
-
-[[package]]
name = "atomic-polyfill"
-version = "0.1.10"
+version = "0.1.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9c041a8d9751a520ee19656232a18971f18946a7900f1520ee4400002244dd89"
+checksum = "e3ff7eb3f316534d83a8a2c3d1674ace8a5a71198eba31e2e2b597833f699b28"
dependencies = [
"critical-section",
]
@@ -26,7 +17,7 @@ version = "0.2.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
dependencies = [
- "hermit-abi",
+ "hermit-abi 0.1.19",
"libc",
"winapi",
]
@@ -38,21 +29,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
[[package]]
-name = "bare-metal"
-version = "0.2.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5deb64efa5bd81e31fcd1938615a6d98c82eafcbcd787162b6f63b91d6bac5b3"
-dependencies = [
- "rustc_version 0.2.3",
-]
-
-[[package]]
-name = "bare-metal"
-version = "1.0.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f8fe8f5a8a398345e52358e18ff07cc17a568fbca5c6f73873d3a62056309603"
-
-[[package]]
name = "bincode"
version = "1.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -62,18 +38,6 @@ dependencies = [
]
[[package]]
-name = "bit_field"
-version = "0.10.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dcb6dd1c2376d2e096796e234a70e17e94cc2d5d54ff8ce42b28cef1d0d359a4"
-
-[[package]]
-name = "bitfield"
-version = "0.13.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "46afbd2983a5d5a7bd740ccb198caf5b82f45c40c09c0eed36052d91cb92e719"
-
-[[package]]
name = "bitflags"
version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -93,9 +57,9 @@ dependencies = [
[[package]]
name = "bumpalo"
-version = "3.11.0"
+version = "3.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c1ad822118d20d2c234f427000d5acc36eabe1e29a348c89b63dd60b13f28e5d"
+checksum = "0d261e256854913907f67ed06efbc3338dfe6179796deefc1ff763fc1aee5535"
[[package]]
name = "byteorder"
@@ -133,18 +97,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "67ba02a97a2bd10f4b59b25c7973101c79642302776489e030cd13cdab09ed15"
[[package]]
-name = "cortex-m"
-version = "0.7.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "70858629a458fdfd39f9675c4dc309411f2a3f83bede76988d81bf1a0ecee9e0"
-dependencies = [
- "bare-metal 0.2.5",
- "bitfield",
- "embedded-hal",
- "volatile-register",
-]
-
-[[package]]
name = "criterion"
version = "0.3.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -182,15 +134,9 @@ dependencies = [
[[package]]
name = "critical-section"
-version = "0.2.7"
+version = "1.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "95da181745b56d4bd339530ec393508910c909c784e8962d15d722bacf0bcbcd"
-dependencies = [
- "bare-metal 1.0.0",
- "cfg-if",
- "cortex-m",
- "riscv",
-]
+checksum = "6548a0ad5d2549e111e1f6a11a6c2e2d00ce6a3dafe22948d67c2b443f775e52"
[[package]]
name = "crossbeam-channel"
@@ -215,26 +161,24 @@ dependencies = [
[[package]]
name = "crossbeam-epoch"
-version = "0.9.10"
+version = "0.9.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "045ebe27666471bb549370b4b0b3e51b07f56325befa4284db65fc89c02511b1"
+checksum = "01a9af1f4c2ef74bb8aa1f7e19706bc72d03598c8a570bb5de72243c7a9d9d5a"
dependencies = [
"autocfg",
"cfg-if",
"crossbeam-utils",
"memoffset",
- "once_cell",
"scopeguard",
]
[[package]]
name = "crossbeam-utils"
-version = "0.8.11"
+version = "0.8.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "51887d4adc7b564537b15adcfb307936f8075dfcd5f00dde9a9f1d29383682bc"
+checksum = "4fb766fa798726286dbbb842f174001dab8abc7b627a1dd86e0b7222a95d929f"
dependencies = [
"cfg-if",
- "once_cell",
]
[[package]]
@@ -261,9 +205,9 @@ dependencies = [
[[package]]
name = "databake"
-version = "0.1.2"
+version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c87777d6d7bde863ba217aa87521dc857239de1f36d66aac46fd173fb0495858"
+checksum = "df626c4717e455cd7a70a82c4358630554a07e4341f86dd095c625f1474a2857"
dependencies = [
"databake-derive",
"proc-macro2",
@@ -273,9 +217,9 @@ dependencies = [
[[package]]
name = "databake-derive"
-version = "0.1.1"
+version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "905c7a060fc0c84c0452d97473b1177dd7a5cbc7670cfbae4a7fe22e42f6432e"
+checksum = "be51a53c468489ae1ef0efa9f6b10706f426c0dde06d66122ffef1f0c51e87dc"
dependencies = [
"proc-macro2",
"quote",
@@ -290,20 +234,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "90e5c1c8368803113bf0c9584fc495a58b86dc8a29edbf8fe877d21d9507e797"
[[package]]
-name = "embedded-hal"
-version = "0.2.7"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "35949884794ad573cf46071e41c9b60efb0cb311e3ca01f7af807af1debc66ff"
-dependencies = [
- "nb 0.1.3",
- "void",
-]
-
-[[package]]
name = "getrandom"
-version = "0.2.7"
+version = "0.2.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4eb1a864a501629691edf6c15a593b7a51eebaa1e8468e9ddc623de7c9b58ec6"
+checksum = "c05aeb6a22b8f62540c194aac980f2115af067bfe15a0734d7277a768d396b31"
dependencies = [
"cfg-if",
"js-sys",
@@ -335,7 +269,7 @@ checksum = "db04bc24a18b9ea980628ecf00e6c0264f3c1426dac36c00cb49b6fbad8b0743"
dependencies = [
"atomic-polyfill",
"hash32",
- "rustc_version 0.4.0",
+ "rustc_version",
"serde",
"spin",
"stable_deref_trait",
@@ -351,16 +285,19 @@ dependencies = [
]
[[package]]
-name = "iai"
-version = "0.1.1"
+name = "hermit-abi"
+version = "0.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "71a816c97c42258aa5834d07590b718b4c9a598944cd39a52dc25b351185d678"
+checksum = "ee512640fe35acbfb4bb779db6f0d80704c2cacfa2e39b601ef3e3f47d1ae4c7"
+dependencies = [
+ "libc",
+]
[[package]]
-name = "icu_benchmark_macros"
-version = "0.7.0"
+name = "iai"
+version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6c867656f2d9c90b13709ac88e710a9d6afe33998c1dfa22384bab8804e8b3d4"
+checksum = "71a816c97c42258aa5834d07590b718b4c9a598944cd39a52dc25b351185d678"
[[package]]
name = "itertools"
@@ -379,9 +316,9 @@ checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4"
[[package]]
name = "itoa"
-version = "1.0.3"
+version = "1.0.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6c8af84674fe1f223a982c933a0ee1086ac4d4052aa0fb8060c12c6ad838e754"
+checksum = "fad582f4b9e86b6caa621cabeb0963332d92eea04729ab12892c2533951e6440"
[[package]]
name = "js-sys"
@@ -400,15 +337,15 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
[[package]]
name = "libc"
-version = "0.2.133"
+version = "0.2.139"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c0f80d65747a3e43d1596c7c5492d95d5edddaabd45a7fcdb02b95f644164966"
+checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79"
[[package]]
name = "libm"
-version = "0.2.5"
+version = "0.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "292a948cd991e376cf75541fe5b97a1081d713c618b4f1b9500f8844e49eb565"
+checksum = "348108ab3fba42ec82ff6e9564fc4ca0247bdccdc68dd8af9764bbc79c3c8ffb"
[[package]]
name = "lock_api"
@@ -437,29 +374,14 @@ checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
[[package]]
name = "memoffset"
-version = "0.6.5"
+version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce"
+checksum = "5de893c32cde5f383baa4c04c5d6dbdd735cfd4a794b0debdb2bb1b421da5ff4"
dependencies = [
"autocfg",
]
[[package]]
-name = "nb"
-version = "0.1.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "801d31da0513b6ec5214e9bf433a77966320625a37860f910be265be6e18d06f"
-dependencies = [
- "nb 1.0.0",
-]
-
-[[package]]
-name = "nb"
-version = "1.0.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "546c37ac5d9e56f55e73b677106873d9d9f5190605e41a856503623648488cae"
-
-[[package]]
name = "num-traits"
version = "0.2.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -471,19 +393,19 @@ dependencies = [
[[package]]
name = "num_cpus"
-version = "1.13.1"
+version = "1.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "19e64526ebdee182341572e50e9ad03965aa510cd94427a4549448f285e957a1"
+checksum = "0fac9e2da13b5eb447a6ce3d392f23a29d8694bff781bf03a16cd9ac8697593b"
dependencies = [
- "hermit-abi",
+ "hermit-abi 0.2.6",
"libc",
]
[[package]]
name = "once_cell"
-version = "1.15.0"
+version = "1.17.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e82dad04139b71a90c080c8463fe0dc7902db5192d939bd0950f074d014339e1"
+checksum = "6f61fba1741ea2b3d6a1e3178721804bb716a68a6aeba1149b5d52e3d464ea66"
[[package]]
name = "oorandom"
@@ -532,24 +454,24 @@ dependencies = [
[[package]]
name = "ppv-lite86"
-version = "0.2.16"
+version = "0.2.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872"
+checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de"
[[package]]
name = "proc-macro2"
-version = "1.0.44"
+version = "1.0.50"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7bd7356a8122b6c4a24a82b278680c73357984ca2fc79a0f9fa6dea7dced7c58"
+checksum = "6ef7d57beacfaf2d8aee5937dab7b7f28de3cb8b1828479bb5de2a7106f2bae2"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
-version = "1.0.21"
+version = "1.0.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179"
+checksum = "8856d8364d252a14d474036ea1358d63c9e6965c8e5c1885c18f73d70bff9c7b"
dependencies = [
"proc-macro2",
]
@@ -605,21 +527,19 @@ dependencies = [
[[package]]
name = "rayon"
-version = "1.5.3"
+version = "1.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bd99e5772ead8baa5215278c9b15bf92087709e9c1b2d1f97cdb5a183c933a7d"
+checksum = "6db3a213adf02b3bcfd2d3846bb41cb22857d131789e01df434fb7e7bc0759b7"
dependencies = [
- "autocfg",
- "crossbeam-deque",
"either",
"rayon-core",
]
[[package]]
name = "rayon-core"
-version = "1.9.3"
+version = "1.10.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "258bcdb5ac6dad48491bb2992db6b7cf74878b0384908af124823d118c99683f"
+checksum = "356a0625f1954f730c0201cdab48611198dc6ce21f4acff55089b5a78e6e835b"
dependencies = [
"crossbeam-channel",
"crossbeam-deque",
@@ -629,12 +549,10 @@ dependencies = [
[[package]]
name = "regex"
-version = "1.6.0"
+version = "1.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4c4eb3267174b8c6c2f654116623910a0fef09c4753f8dd83db29c48a0df988b"
+checksum = "48aaa5748ba571fb95cd2c85c09f629215d3a6ece942baa100950af03a34f733"
dependencies = [
- "aho-corasick",
- "memchr",
"regex-syntax",
]
@@ -646,39 +564,9 @@ checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132"
[[package]]
name = "regex-syntax"
-version = "0.6.27"
+version = "0.6.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a3f87b73ce11b1619a3c6332f45341e0047173771e8b8b73f87bfeefb7b56244"
-
-[[package]]
-name = "riscv"
-version = "0.7.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6907ccdd7a31012b70faf2af85cd9e5ba97657cc3987c4f13f8e4d2c2a088aba"
-dependencies = [
- "bare-metal 1.0.0",
- "bit_field",
- "riscv-target",
-]
-
-[[package]]
-name = "riscv-target"
-version = "0.1.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "88aa938cda42a0cf62a20cfe8d139ff1af20c2e681212b5b34adb5a58333f222"
-dependencies = [
- "lazy_static",
- "regex",
-]
-
-[[package]]
-name = "rustc_version"
-version = "0.2.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a"
-dependencies = [
- "semver 0.9.0",
-]
+checksum = "456c603be3e8d448b072f410900c09faf164fbce2d480456f50eea6e25f9c848"
[[package]]
name = "rustc_version"
@@ -686,14 +574,14 @@ version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366"
dependencies = [
- "semver 1.0.14",
+ "semver",
]
[[package]]
name = "ryu"
-version = "1.0.11"
+version = "1.0.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4501abdff3ae82a1c1b477a17252eb69cee9e66eb915c1abaa4f44d873df9f09"
+checksum = "7b4b9743ed687d4b4bcedf9ff5eaa7398495ae14e61cba0a295704edbc7decde"
[[package]]
name = "same-file"
@@ -712,30 +600,15 @@ checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
[[package]]
name = "semver"
-version = "0.9.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403"
-dependencies = [
- "semver-parser",
-]
-
-[[package]]
-name = "semver"
-version = "1.0.14"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e25dfac463d778e353db5be2449d1cce89bd6fd23c9f1ea21310ce6e5a1b29c4"
-
-[[package]]
-name = "semver-parser"
-version = "0.7.0"
+version = "1.0.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
+checksum = "58bc9567378fc7690d6b2addae4e60ac2eeea07becb2c64b9f218b53865cba2a"
[[package]]
name = "serde"
-version = "1.0.145"
+version = "1.0.152"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "728eb6351430bccb993660dfffc5a72f91ccc1295abaa8ce19b27ebe4f75568b"
+checksum = "bb7d1f0d3021d347a83e556fc4683dea2ea09d87bccdf88ff5c12545d89d5efb"
dependencies = [
"serde_derive",
]
@@ -752,9 +625,9 @@ dependencies = [
[[package]]
name = "serde_derive"
-version = "1.0.145"
+version = "1.0.152"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "81fa1584d3d1bcacd84c277a0dfe21f5b0f6accf4a23d04d4c6d61f1af522b4c"
+checksum = "af487d118eecd09402d70a5d72551860e788df87b464af30e5ea6a38c75c541e"
dependencies = [
"proc-macro2",
"quote",
@@ -763,11 +636,11 @@ dependencies = [
[[package]]
name = "serde_json"
-version = "1.0.85"
+version = "1.0.91"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e55a28e3aaef9d5ce0506d0a14dbba8054ddc7e499ef522dd8b26859ec9d4a44"
+checksum = "877c235533714907a8c2464236f5c4b2a17262ef1bd71f38f35ea592c8da6883"
dependencies = [
- "itoa 1.0.3",
+ "itoa 1.0.5",
"ryu",
"serde",
]
@@ -789,9 +662,9 @@ checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3"
[[package]]
name = "syn"
-version = "1.0.101"
+version = "1.0.107"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e90cde112c4b9690b8cbe810cba9ddd8bc1d7472e2cae317b69e9438c1cba7d2"
+checksum = "1f4064b5b16e03ae50984a5a8ed5d4f8803e6bc1fd170a3cda91a1be4b18e3f5"
dependencies = [
"proc-macro2",
"quote",
@@ -831,9 +704,9 @@ dependencies = [
[[package]]
name = "unicode-ident"
-version = "1.0.4"
+version = "1.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dcc811dc4066ac62f84f11307873c4850cb653bfa9b1719cee2bd2204a4bc5dd"
+checksum = "84a22b9f218b40614adcb3f4ff08b703773ad44fa9423e4e0d346d5db86e4ebc"
[[package]]
name = "unicode-width"
@@ -848,27 +721,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c"
[[package]]
-name = "vcell"
-version = "0.1.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "77439c1b53d2303b20d9459b1ade71a83c716e3f9c34f3228c00e6f185d6c002"
-
-[[package]]
-name = "void"
-version = "1.0.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d"
-
-[[package]]
-name = "volatile-register"
-version = "0.2.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9ee8f19f9d74293faf70901bc20ad067dc1ad390d2cbf1e3f75f721ffee908b6"
-dependencies = [
- "vcell",
-]
-
-[[package]]
name = "walkdir"
version = "2.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -982,59 +834,30 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
[[package]]
name = "yoke"
-version = "0.6.1"
+version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "620cda8a59740b1e9313dad314848c6ffe15792c38cc4ac2def245ee77a6cae2"
+checksum = "222180af14a6b54ef2c33493c1eff77ae95a3687a21b243e752624006fb8f26e"
dependencies = [
"serde",
"stable_deref_trait",
- "yoke-derive",
"zerofrom",
]
[[package]]
-name = "yoke-derive"
-version = "0.6.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "58c2c5bb7c929b85c1b9ec69091b0d835f0878b4fd9eb67973b25936e06c4374"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn",
- "synstructure",
-]
-
-[[package]]
name = "zerofrom"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "79e9355fccf72b04b7deaa99ce7a0f6630530acf34045391b74460fcd714de54"
-dependencies = [
- "zerofrom-derive",
-]
-
-[[package]]
-name = "zerofrom-derive"
-version = "0.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8785f47d6062c1932866147f91297286a9f350b3070e9d9f0b6078e37d623c1a"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn",
- "synstructure",
-]
[[package]]
name = "zerovec"
-version = "0.9.0"
+version = "0.9.2"
dependencies = [
"bincode",
"criterion",
"databake",
"getrandom",
"iai",
- "icu_benchmark_macros",
"postcard",
"rand",
"rand_distr",
@@ -1048,9 +871,9 @@ dependencies = [
[[package]]
name = "zerovec-derive"
-version = "0.9.0"
+version = "0.9.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "490e5f878c2856225e884c35927e7ea6db3c24cdb7229b72542c7526ad7ed49e"
+checksum = "c630983d26a5f0c061dad3bf22df69a7329b4939a9752bc5f19f1cbd8e2263db"
dependencies = [
"proc-macro2",
"quote",
diff --git a/vendor/zerovec/Cargo.toml b/vendor/zerovec/Cargo.toml
index 2e305d302..2490aa0dc 100644
--- a/vendor/zerovec/Cargo.toml
+++ b/vendor/zerovec/Cargo.toml
@@ -12,7 +12,7 @@
[package]
edition = "2021"
name = "zerovec"
-version = "0.9.0"
+version = "0.9.2"
authors = ["The ICU4X Project Developers"]
include = [
"src/**/*",
@@ -41,9 +41,15 @@ license = "Unicode-DFS-2016"
repository = "https://github.com/unicode-org/icu4x"
resolver = "2"
+[package.metadata.workspaces]
+independent = true
+
[package.metadata.docs.rs]
all-features = true
+[package.metadata.cargo-all-features]
+denylist = ["bench"]
+
[[example]]
name = "zv_serde"
required-features = ["serde"]
@@ -71,7 +77,7 @@ harness = false
required-features = ["serde"]
[dependencies.databake]
-version = "0.1.0"
+version = "0.1.3"
features = ["derive"]
optional = true
@@ -82,14 +88,14 @@ optional = true
default-features = false
[dependencies.yoke]
-version = "0.6.0"
+version = "0.7.0"
optional = true
[dependencies.zerofrom]
-version = "0.1.0"
+version = "0.1.1"
[dependencies.zerovec-derive]
-version = "0.9.0"
+version = "0.9.2"
optional = true
[dev-dependencies.bincode]
@@ -105,9 +111,6 @@ features = ["js"]
[dev-dependencies.iai]
version = "0.1"
-[dev-dependencies.icu_benchmark_macros]
-version = "0.7"
-
[dev-dependencies.postcard]
version = "1.0.0"
features = ["use-std"]
@@ -128,15 +131,7 @@ features = ["derive"]
[dev-dependencies.serde_json]
version = "1.0"
-[dev-dependencies.yoke]
-version = "0.6.0"
-features = ["derive"]
-
-[dev-dependencies.zerofrom]
-version = "0.1.0"
-features = ["derive"]
-
[features]
bench = []
-derive = ["zerovec-derive"]
+derive = ["dep:zerovec-derive"]
std = []
diff --git a/vendor/zerovec/README.md b/vendor/zerovec/README.md
index dbde4022c..b650d7dbd 100644
--- a/vendor/zerovec/README.md
+++ b/vendor/zerovec/README.md
@@ -32,7 +32,7 @@ works under the hood.
## Cargo features
-This crate has five optional features:
+This crate has several optional Cargo features:
- `serde`: Allows serializing and deserializing `zerovec`'s abstractions via [`serde`](https://docs.rs/serde)
- `yoke`: Enables implementations of `Yokeable` from the [`yoke`](https://docs.rs/yoke/) crate, which is also useful
in situations involving a lot of zero-copy deserialization.
diff --git a/vendor/zerovec/benches/vzv.rs b/vendor/zerovec/benches/vzv.rs
index 3bee5add6..94b6621a9 100644
--- a/vendor/zerovec/benches/vzv.rs
+++ b/vendor/zerovec/benches/vzv.rs
@@ -102,7 +102,7 @@ fn binary_search_benches(c: &mut Criterion) {
let (needles, _) = random_alphanums(2..=20, 10, seed);
let bytes: Vec<u8> = VarZeroVec::<str>::from(&string_vec).into_bytes();
let vzv = VarZeroVec::<str>::parse_byte_slice(black_box(bytes.as_slice())).unwrap();
- let single_needle = "lmnop".to_string();
+ let single_needle = "lmnop".to_owned();
// *** Binary search vec of 500 strings 10 times ***
c.bench_function("vzv/binary_search/slice", |b| {
@@ -169,7 +169,7 @@ fn vzv_precompute_bench(c: &mut Criterion) {
let vzv = VarZeroVec::<str>::parse_byte_slice(black_box(bytes.as_slice())).unwrap();
let borrowed = vzv.as_components();
let slice = vzv.as_slice();
- let single_needle = "lmnop".to_string();
+ let single_needle = "lmnop";
c.bench_function("vzv_precompute/get/precomputed", |b| {
b.iter(|| black_box(&borrowed).get(100));
@@ -180,11 +180,11 @@ fn vzv_precompute_bench(c: &mut Criterion) {
});
c.bench_function("vzv_precompute/search/precomputed", |b| {
- b.iter(|| black_box(&borrowed).binary_search(&single_needle));
+ b.iter(|| black_box(&borrowed).binary_search(single_needle));
});
c.bench_function("vzv_precompute/search/slice", |b| {
- b.iter(|| black_box(&slice).binary_search(&single_needle));
+ b.iter(|| black_box(&slice).binary_search(single_needle));
});
c.bench_function("vzv_precompute/search_multi/precomputed", |b| {
diff --git a/vendor/zerovec/benches/zeromap.rs b/vendor/zerovec/benches/zeromap.rs
index 40225ba7a..069331979 100644
--- a/vendor/zerovec/benches/zeromap.rs
+++ b/vendor/zerovec/benches/zeromap.rs
@@ -56,7 +56,8 @@ const POSTCARD_HASHMAP: [u8; 176] = [
114, 97, 98, 105, 99,
];
-/// Run this function to print new data to the console. Requires the optional `serde` feature.
+/// Run this function to print new data to the console.
+/// Requires the optional `serde` Cargo feature.
#[allow(dead_code)]
fn generate() {
let map = build_zeromap(false);
@@ -64,7 +65,8 @@ fn generate() {
println!("{:?}", buf);
}
-/// Run this function to print new data to the console. Requires the optional `serde` feature.
+/// Run this function to print new data to the console.
+/// Requires the optional `serde` Cargo feature.
#[allow(dead_code)]
fn generate_hashmap() {
let map = build_hashmap(false);
@@ -180,13 +182,13 @@ fn bench_hashmap(c: &mut Criterion) {
fn build_hashmap(large: bool) -> HashMap<String, String> {
let mut map: HashMap<String, String> = HashMap::new();
- for (key, value) in DATA.iter() {
+ for &(key, value) in DATA.iter() {
if large {
for n in 0..8192 {
- map.insert(format!("{}{}", key, n), value.to_string());
+ map.insert(format!("{}{}", key, n), value.to_owned());
}
} else {
- map.insert(key.to_string(), value.to_string());
+ map.insert(key.to_owned(), value.to_owned());
}
}
map
@@ -197,7 +199,7 @@ fn bench_deserialize_hashmap(c: &mut Criterion) {
b.iter(|| {
let map: HashMap<String, String> =
postcard::from_bytes(black_box(&POSTCARD_HASHMAP)).unwrap();
- assert_eq!(map.get("iu"), Some(&"Inuktitut".to_string()));
+ assert_eq!(map.get("iu"), Some(&"Inuktitut".to_owned()));
})
});
}
@@ -207,7 +209,7 @@ fn bench_deserialize_large_hashmap(c: &mut Criterion) {
c.bench_function("zeromap/deserialize/large/hashmap", |b| {
b.iter(|| {
let map: HashMap<String, String> = postcard::from_bytes(black_box(&buf)).unwrap();
- assert_eq!(map.get("iu3333"), Some(&"Inuktitut".to_string()));
+ assert_eq!(map.get("iu3333"), Some(&"Inuktitut".to_owned()));
})
});
}
@@ -216,7 +218,7 @@ fn bench_lookup_hashmap(c: &mut Criterion) {
let map: HashMap<String, String> = postcard::from_bytes(black_box(&POSTCARD_HASHMAP)).unwrap();
c.bench_function("zeromap/lookup/small/hashmap", |b| {
b.iter(|| {
- assert_eq!(map.get(black_box("iu")), Some(&"Inuktitut".to_string()));
+ assert_eq!(map.get(black_box("iu")), Some(&"Inuktitut".to_owned()));
assert_eq!(map.get(black_box("zz")), None);
});
});
@@ -227,7 +229,7 @@ fn bench_lookup_large_hashmap(c: &mut Criterion) {
let map: HashMap<String, String> = postcard::from_bytes(&buf).unwrap();
c.bench_function("zeromap/lookup/large/hashmap", |b| {
b.iter(|| {
- assert_eq!(map.get(black_box("iu3333")), Some(&"Inuktitut".to_string()));
+ assert_eq!(map.get(black_box("iu3333")), Some(&"Inuktitut".to_owned()));
assert_eq!(map.get(black_box("zz")), None);
});
});
diff --git a/vendor/zerovec/src/flexzerovec/serde.rs b/vendor/zerovec/src/flexzerovec/serde.rs
index 44179be32..fb7caa7a8 100644
--- a/vendor/zerovec/src/flexzerovec/serde.rs
+++ b/vendor/zerovec/src/flexzerovec/serde.rs
@@ -42,7 +42,7 @@ impl<'de> Visitor<'de> for FlexZeroVecVisitor {
}
}
-/// This impl can be made available by enabling the optional `serde` feature of the `zerovec` crate
+/// This impl requires enabling the optional `serde` Cargo feature of the `zerovec` crate
impl<'de, 'a> Deserialize<'de> for FlexZeroVec<'a>
where
'de: 'a,
@@ -60,7 +60,7 @@ where
}
}
-/// This impl can be made available by enabling the optional `serde` feature of the `zerovec` crate
+/// This impl requires enabling the optional `serde` Cargo feature of the `zerovec` crate
impl<'de, 'a> Deserialize<'de> for &'a FlexZeroSlice
where
'de: 'a,
@@ -87,7 +87,7 @@ where
}
}
-/// This impl can be made available by enabling the optional `serde` feature of the `zerovec` crate
+/// This impl requires enabling the optional `serde` Cargo feature of the `zerovec` crate
impl Serialize for FlexZeroVec<'_> {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
@@ -105,7 +105,7 @@ impl Serialize for FlexZeroVec<'_> {
}
}
-/// This impl can be made available by enabling the optional `serde` feature of the `zerovec` crate
+/// This impl requires enabling the optional `serde` Cargo feature of the `zerovec` crate
impl Serialize for FlexZeroSlice {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
diff --git a/vendor/zerovec/src/flexzerovec/slice.rs b/vendor/zerovec/src/flexzerovec/slice.rs
index 7cc6f12fa..ee164d05b 100644
--- a/vendor/zerovec/src/flexzerovec/slice.rs
+++ b/vendor/zerovec/src/flexzerovec/slice.rs
@@ -14,7 +14,6 @@ const USIZE_WIDTH: usize = mem::size_of::<usize>();
/// A zero-copy "slice" that efficiently represents `[usize]`.
#[repr(packed)]
-#[derive(Eq, PartialEq)]
pub struct FlexZeroSlice {
// Hard Invariant: 1 <= width <= USIZE_WIDTH (which is target_pointer_width)
// Soft Invariant: width == the width of the largest element
@@ -23,6 +22,13 @@ pub struct FlexZeroSlice {
data: [u8],
}
+impl PartialEq for FlexZeroSlice {
+ fn eq(&self, other: &Self) -> bool {
+ self.width == other.width && self.data == other.data
+ }
+}
+impl Eq for FlexZeroSlice {}
+
/// Helper function to decode a little-endian "chunk" (byte slice of a specific length)
/// into a `usize`. We cannot call `usize::from_le_bytes` directly because that function
/// requires the high bits to be set to 0.
diff --git a/vendor/zerovec/src/lib.rs b/vendor/zerovec/src/lib.rs
index 9a37c762e..b8b292488 100644
--- a/vendor/zerovec/src/lib.rs
+++ b/vendor/zerovec/src/lib.rs
@@ -34,7 +34,7 @@
//!
//! # Cargo features
//!
-//! This crate has five optional features:
+//! This crate has several optional Cargo features:
//! - `serde`: Allows serializing and deserializing `zerovec`'s abstractions via [`serde`](https://docs.rs/serde)
//! - `yoke`: Enables implementations of `Yokeable` from the [`yoke`](https://docs.rs/yoke/) crate, which is also useful
//! in situations involving a lot of zero-copy deserialization.
@@ -270,6 +270,8 @@ pub mod maps {
pub use crate::map2d::ZeroMap2dBorrowed;
pub use crate::map::{MutableZeroVecLike, ZeroMapKV, ZeroVecLike};
+
+ pub use crate::map2d::ZeroMap2dCursor;
}
pub mod vecs {
@@ -395,8 +397,9 @@ pub use zerovec_derive::make_ule;
/// Generate a corresponding [`VarULE`] type and the relevant [`EncodeAsVarULE`]/[`zerofrom::ZeroFrom`]
/// implementations for this type
///
-/// This can be attached to structs containing only [`AsULE`] types with the last field being [`Cow<'a, str>`](alloc::borrow::Cow),
-/// [`Cow<'a, str>`](alloc::borrow::Cow), [`ZeroSlice`], or [`VarZeroSlice`].
+/// This can be attached to structs containing only [`AsULE`] types with the last fields being
+/// [`Cow<'a, str>`](alloc::borrow::Cow), [`ZeroSlice`], or [`VarZeroSlice`]. If there is more than one such field, it will be represented
+/// using [`MultiFieldsULE`](crate::ule::MultiFieldsULE) and getters will be generated.
///
/// The type must be [`PartialEq`] and [`Eq`].
///
diff --git a/vendor/zerovec/src/map/borrowed.rs b/vendor/zerovec/src/map/borrowed.rs
index 4c1d1aef6..9d0854601 100644
--- a/vendor/zerovec/src/map/borrowed.rs
+++ b/vendor/zerovec/src/map/borrowed.rs
@@ -163,11 +163,6 @@ where
/// let borrowed = map.as_borrowed();
/// assert_eq!(borrowed.get(&1), Some("one"));
/// assert_eq!(borrowed.get(&3), None);
- ///
- /// let borrow = borrowed.get(&1);
- /// drop(borrowed);
- /// // still exists after the ZeroMapBorrowed has been dropped
- /// assert_eq!(borrow, Some("one"));
/// ```
pub fn get(&self, key: &K) -> Option<&'a V::GetType> {
let index = self.keys.zvl_binary_search(key).ok()?;
@@ -190,11 +185,6 @@ where
/// let borrowed = map.as_borrowed();
/// assert_eq!(borrowed.get_by(|probe| probe.cmp(&1)), Some("one"));
/// assert_eq!(borrowed.get_by(|probe| probe.cmp(&3)), None);
- ///
- /// let borrow = borrowed.get_by(|probe| probe.cmp(&1));
- /// drop(borrowed);
- /// // still exists after the ZeroMapBorrowed has been dropped
- /// assert_eq!(borrow, Some("one"));
/// ```
pub fn get_by(&self, predicate: impl FnMut(&K) -> Ordering) -> Option<&'a V::GetType> {
let index = self.keys.zvl_binary_search_by(predicate).ok()?;
@@ -211,8 +201,8 @@ where
/// map.insert(&1, "one");
/// map.insert(&2, "two");
/// let borrowed = map.as_borrowed();
- /// assert_eq!(borrowed.contains_key(&1), true);
- /// assert_eq!(borrowed.contains_key(&3), false);
+ /// assert!(borrowed.contains_key(&1));
+ /// assert!(!borrowed.contains_key(&3));
/// ```
pub fn contains_key(&self, key: &K) -> bool {
self.keys.zvl_binary_search(key).is_ok()
diff --git a/vendor/zerovec/src/map/map.rs b/vendor/zerovec/src/map/map.rs
index 379b22667..692e265d6 100644
--- a/vendor/zerovec/src/map/map.rs
+++ b/vendor/zerovec/src/map/map.rs
@@ -194,8 +194,8 @@ where
/// let mut map = ZeroMap::new();
/// map.insert(&1, "one");
/// map.insert(&2, "two");
- /// assert_eq!(map.contains_key(&1), true);
- /// assert_eq!(map.contains_key(&3), false);
+ /// assert!(map.contains_key(&1));
+ /// assert!(!map.contains_key(&3));
/// ```
pub fn contains_key(&self, key: &K) -> bool {
self.keys.zvl_binary_search(key).is_ok()
diff --git a/vendor/zerovec/src/map/serde.rs b/vendor/zerovec/src/map/serde.rs
index dbe4b433d..e82886d2a 100644
--- a/vendor/zerovec/src/map/serde.rs
+++ b/vendor/zerovec/src/map/serde.rs
@@ -9,7 +9,7 @@ use serde::de::{self, Deserialize, Deserializer, MapAccess, SeqAccess, Visitor};
#[cfg(feature = "serde")]
use serde::ser::{Serialize, SerializeMap, SerializeSeq, Serializer};
-/// This impl can be made available by enabling the optional `serde` feature of the `zerovec` crate
+/// This impl requires enabling the optional `serde` Cargo feature of the `zerovec` crate
#[cfg(feature = "serde")]
impl<'a, K, V> Serialize for ZeroMap<'a, K, V>
where
@@ -49,7 +49,7 @@ where
}
}
-/// This impl can be made available by enabling the optional `serde` feature of the `zerovec` crate
+/// This impl requires enabling the optional `serde` Cargo feature of the `zerovec` crate
#[cfg(feature = "serde")]
impl<'a, K, V> Serialize for ZeroMapBorrowed<'a, K, V>
where
@@ -158,7 +158,7 @@ where
}
}
-/// This impl can be made available by enabling the optional `serde` feature of the `zerovec` crate
+/// This impl requires enabling the optional `serde` Cargo feature of the `zerovec` crate
impl<'de, 'a, K, V> Deserialize<'de> for ZeroMap<'a, K, V>
where
K: ZeroMapKV<'a> + Ord + ?Sized,
@@ -190,7 +190,7 @@ where
}
}
-// /// This impl can be made available by enabling the optional `serde` feature of the `zerovec` crate
+// /// This impl requires enabling the optional `serde` Cargo feature of the `zerovec` crate
impl<'de, 'a, K, V> Deserialize<'de> for ZeroMapBorrowed<'a, K, V>
where
K: ZeroMapKV<'a> + Ord + ?Sized,
diff --git a/vendor/zerovec/src/map2d/borrowed.rs b/vendor/zerovec/src/map2d/borrowed.rs
index d9972fae9..209da299b 100644
--- a/vendor/zerovec/src/map2d/borrowed.rs
+++ b/vendor/zerovec/src/map2d/borrowed.rs
@@ -199,11 +199,6 @@ where
/// assert_eq!(borrowed.get_2d(&2, "one"), Some("bar"));
/// assert_eq!(borrowed.get_2d(&2, "two"), Some("baz"));
/// assert_eq!(borrowed.get_2d(&3, "three"), None);
- ///
- /// let borrow = borrowed.get_2d(&1, "one");
- /// drop(borrowed);
- /// // still exists after the ZeroMap2dBorrowed has been dropped
- /// assert_eq!(borrow, Some("foo"));
/// ```
pub fn get_2d(&self, key0: &K0, key1: &K1) -> Option<&'a V::GetType> {
self.get0(key0)?.get1(key1)
@@ -270,8 +265,8 @@ where
/// map.insert(&1, "one", "foo");
/// map.insert(&2, "two", "bar");
/// let borrowed = map.as_borrowed();
- /// assert_eq!(borrowed.contains_key0(&1), true);
- /// assert_eq!(borrowed.contains_key0(&3), false);
+ /// assert!(borrowed.contains_key0(&1));
+ /// assert!(!borrowed.contains_key0(&3));
/// ```
pub fn contains_key0(&self, key0: &K0) -> bool {
self.keys0.zvl_binary_search(key0).is_ok()
diff --git a/vendor/zerovec/src/map2d/cursor.rs b/vendor/zerovec/src/map2d/cursor.rs
index 0654ee794..4802187be 100644
--- a/vendor/zerovec/src/map2d/cursor.rs
+++ b/vendor/zerovec/src/map2d/cursor.rs
@@ -92,7 +92,9 @@ where
self.keys0.zvl_get(self.key0_index).unwrap()
}
- /// Borrow an ordered iterator over keys1 for a particular key0.
+ /// Borrow an ordered iterator over keys1 and values for a particular key0.
+ ///
+ /// To get the values as copy types, see [`Self::iter1_copied`].
///
/// For an example, see [`ZeroMap2d::iter0()`].
pub fn iter1(
@@ -153,6 +155,64 @@ where
impl<'l, 'a, K0, K1, V> ZeroMap2dCursor<'l, 'a, K0, K1, V>
where
K0: ZeroMapKV<'a>,
+ K1: ZeroMapKV<'a>,
+ V: ZeroMapKV<'a>,
+ K0: ?Sized,
+ K1: ?Sized,
+ V: Copy,
+{
+ /// Borrow an ordered iterator over keys1 and values for a particular key0.
+ ///
+ /// The values are returned as copy types.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use zerovec::ZeroMap2d;
+ ///
+ /// let zm2d: ZeroMap2d<str, u8, usize> = [
+ /// ("a", 0u8, 1usize),
+ /// ("b", 1u8, 1000usize),
+ /// ("b", 2u8, 2000usize),
+ /// ]
+ /// .into_iter()
+ /// .collect();
+ ///
+ /// let mut total_value = 0;
+ ///
+ /// for cursor in zm2d.iter0() {
+ /// for (_, value) in cursor.iter1_copied() {
+ /// total_value += value;
+ /// }
+ /// }
+ ///
+ /// assert_eq!(total_value, 3001);
+ /// ```
+ pub fn iter1_copied(
+ &self,
+ ) -> impl Iterator<Item = (&'l <K1 as ZeroMapKV<'a>>::GetType, V)> + '_ {
+ let range = self.get_range();
+ #[allow(clippy::unwrap_used)] // `self.get_range()` returns a valid range
+ range.map(move |idx| {
+ (
+ self.keys1.zvl_get(idx).unwrap(),
+ self.get1_copied_at(idx).unwrap(),
+ )
+ })
+ }
+
+ fn get1_copied_at(&self, index: usize) -> Option<V> {
+ let ule = self.values.zvl_get(index)?;
+ let mut result = Option::<V>::None;
+ V::Container::zvl_get_as_t(ule, |v| result.replace(*v));
+ #[allow(clippy::unwrap_used)] // `zvl_get_as_t` guarantees that the callback is invoked
+ Some(result.unwrap())
+ }
+}
+
+impl<'l, 'a, K0, K1, V> ZeroMap2dCursor<'l, 'a, K0, K1, V>
+where
+ K0: ZeroMapKV<'a>,
K1: ZeroMapKV<'a> + Ord,
V: ZeroMapKV<'a>,
K0: ?Sized,
@@ -253,14 +313,6 @@ where
let key1_index = self.get_key1_index_by(predicate)?;
self.get1_copied_at(key1_index)
}
-
- fn get1_copied_at(&self, index: usize) -> Option<V> {
- let ule = self.values.zvl_get(index)?;
- let mut result = Option::<V>::None;
- V::Container::zvl_get_as_t(ule, |v| result.replace(*v));
- #[allow(clippy::unwrap_used)] // `zvl_get_as_t` guarantees that the callback is invoked
- Some(result.unwrap())
- }
}
// We can't use the default PartialEq because ZeroMap2d is invariant
diff --git a/vendor/zerovec/src/map2d/map.rs b/vendor/zerovec/src/map2d/map.rs
index ab6eded4e..e6545dfa5 100644
--- a/vendor/zerovec/src/map2d/map.rs
+++ b/vendor/zerovec/src/map2d/map.rs
@@ -534,8 +534,8 @@ where
/// let mut map = ZeroMap2d::new();
/// map.insert(&1, "one", "foo");
/// map.insert(&2, "two", "bar");
- /// assert_eq!(map.contains_key0(&1), true);
- /// assert_eq!(map.contains_key0(&3), false);
+ /// assert!(map.contains_key0(&1));
+ /// assert!(!map.contains_key0(&3));
/// ```
pub fn contains_key0(&self, key0: &K0) -> bool {
self.keys0.zvl_binary_search(key0).is_ok()
@@ -814,13 +814,13 @@ mod test {
// Remove some elements
let result = zm2d.remove(&3, "ccc"); // first element
- assert_eq!(result, Some(String::from("CCC").into_boxed_str()));
+ assert_eq!(result.as_deref(), Some("CCC"));
let result = zm2d.remove(&3, "mmm"); // middle element
- assert_eq!(result, Some(String::from("MM0").into_boxed_str()));
+ assert_eq!(result.as_deref(), Some("MM0"));
let result = zm2d.remove(&5, "ddd"); // singleton K0
- assert_eq!(result, Some(String::from("DD1").into_boxed_str()));
+ assert_eq!(result.as_deref(), Some("DD1"));
let result = zm2d.remove(&9, "yyy"); // last element
- assert_eq!(result, Some(String::from("YYY").into_boxed_str()));
+ assert_eq!(result.as_deref(), Some("YYY"));
assert_eq!(format!("{:?}", zm2d), "ZeroMap2d { keys0: ZeroVec([3, 6, 7]), joiner: ZeroVec([1, 4, 7]), keys1: [\"eee\", \"ddd\", \"mmm\", \"nnn\", \"ddd\", \"eee\", \"www\"], values: [\"EEE\", \"DD3\", \"MM1\", \"NNN\", \"DD2\", \"EEE\", \"WWW\"] }");
}
diff --git a/vendor/zerovec/src/map2d/serde.rs b/vendor/zerovec/src/map2d/serde.rs
index f8b5f147b..b5e913654 100644
--- a/vendor/zerovec/src/map2d/serde.rs
+++ b/vendor/zerovec/src/map2d/serde.rs
@@ -12,7 +12,7 @@ use serde::de::{self, Deserialize, Deserializer, MapAccess, Visitor};
#[cfg(feature = "serde")]
use serde::ser::{Serialize, SerializeMap, Serializer};
-/// This impl can be made available by enabling the optional `serde` feature of the `zerovec` crate
+/// This impl requires enabling the optional `serde` Cargo feature of the `zerovec` crate
#[cfg(feature = "serde")]
impl<'a, K0, K1, V> Serialize for ZeroMap2d<'a, K0, K1, V>
where
@@ -75,7 +75,7 @@ where
}
}
-/// This impl can be made available by enabling the optional `serde` feature of the `zerovec` crate
+/// This impl requires enabling the optional `serde` Cargo feature of the `zerovec` crate
#[cfg(feature = "serde")]
impl<'a, K0, K1, V> Serialize for ZeroMap2dBorrowed<'a, K0, K1, V>
where
@@ -220,7 +220,7 @@ where
}
}
-/// This impl can be made available by enabling the optional `serde` feature of the `zerovec` crate
+/// This impl requires enabling the optional `serde` Cargo feature of the `zerovec` crate
impl<'de, 'a, K0, K1, V> Deserialize<'de> for ZeroMap2d<'a, K0, K1, V>
where
K0: ZeroMapKV<'a> + Ord + ?Sized,
@@ -287,7 +287,7 @@ where
}
}
-/// This impl can be made available by enabling the optional `serde` feature of the `zerovec` crate
+/// This impl requires enabling the optional `serde` Cargo feature of the `zerovec` crate
impl<'de, 'a, K0, K1, V> Deserialize<'de> for ZeroMap2dBorrowed<'a, K0, K1, V>
where
K0: ZeroMapKV<'a> + Ord + ?Sized,
diff --git a/vendor/zerovec/src/ule/mod.rs b/vendor/zerovec/src/ule/mod.rs
index 29c7d0ecd..e8ecd26e5 100644
--- a/vendor/zerovec/src/ule/mod.rs
+++ b/vendor/zerovec/src/ule/mod.rs
@@ -283,6 +283,12 @@ where
/// "12.3e3" are logically equal, but not byte-for-byte equal, so we could define a canonical form
/// where only a single digit is allowed before `.`.
///
+/// There may also be cases where a `VarULE` has muiltiple canonical forms, such as a faster
+/// version and a smaller version. The cleanest way to handle this case would be separate types.
+/// However, if this is not feasible, then the application should ensure that the data it is
+/// deserializing is in the expected form. For example, if the data is being loaded from an
+/// external source, then requests could carry information about the expected form of the data.
+///
/// Failure to follow this invariant will cause surprising behavior in `PartialEq`, which may
/// result in unpredictable operations on `ZeroVec`, `VarZeroVec`, and `ZeroMap`.
pub unsafe trait VarULE: 'static {
diff --git a/vendor/zerovec/src/ule/option.rs b/vendor/zerovec/src/ule/option.rs
index e1d2d25fa..a6b1966a5 100644
--- a/vendor/zerovec/src/ule/option.rs
+++ b/vendor/zerovec/src/ule/option.rs
@@ -22,7 +22,7 @@ use core::mem::{self, MaybeUninit};
/// Some('ł'),
/// ]);
///
-/// assert_eq!(z.get(2), Some(Some(('ø'))));
+/// assert_eq!(z.get(2), Some(Some('ø')));
/// assert_eq!(z.get(3), Some(None));
/// ```
// Invariants:
diff --git a/vendor/zerovec/src/ule/plain.rs b/vendor/zerovec/src/ule/plain.rs
index 0b1bbb441..49455d45f 100644
--- a/vendor/zerovec/src/ule/plain.rs
+++ b/vendor/zerovec/src/ule/plain.rs
@@ -7,10 +7,7 @@
use super::*;
use crate::ZeroSlice;
-use core::{
- mem,
- num::{NonZeroI8, NonZeroU8},
-};
+use core::num::{NonZeroI8, NonZeroU8};
/// A u8 array of little-endian data with infallible conversions to and from &[u8].
#[repr(transparent)]
@@ -100,19 +97,7 @@ macro_rules! impl_const_constructors {
let len = bytes.len();
#[allow(clippy::modulo_one)]
if len % $size == 0 {
- unsafe {
- // Most of the slice manipulation functions are not yet const-stable,
- // so we construct a slice with the right metadata and cast its type
- // https://rust-lang.github.io/unsafe-code-guidelines/layout/pointers.html#notes
- //
- // Safety:
- // * [u8] and [RawBytesULE<N>] have different lengths but the same alignment
- // * ZeroSlice<$base> is repr(transparent) with [RawBytesULE<N>]
- let [ptr, _]: [usize; 2] = mem::transmute(bytes);
- let new_len = len / $size;
- let raw = [ptr, new_len];
- Ok(mem::transmute(raw))
- }
+ Ok(unsafe { Self::from_bytes_unchecked(bytes) })
} else {
Err(ZeroVecError::InvalidLength {
ty: concat!("<const construct: ", $size, ">"),
diff --git a/vendor/zerovec/src/ule/unvalidated.rs b/vendor/zerovec/src/ule/unvalidated.rs
index a6ae55dcf..4564c8673 100644
--- a/vendor/zerovec/src/ule/unvalidated.rs
+++ b/vendor/zerovec/src/ule/unvalidated.rs
@@ -95,9 +95,9 @@ impl UnvalidatedStr {
/// ```
/// use zerovec::ule::UnvalidatedStr;
///
- /// static a: &UnvalidatedStr = UnvalidatedStr::from_bytes(b"abc");
+ /// static A: &UnvalidatedStr = UnvalidatedStr::from_bytes(b"abc");
///
- /// let b = a.try_as_str().unwrap();
+ /// let b = A.try_as_str().unwrap();
/// assert_eq!(b, "abc");
/// ```
// Note: this is const starting in 1.63
@@ -154,7 +154,7 @@ unsafe impl VarULE for UnvalidatedStr {
}
}
-/// This impl can be made available by enabling the optional `serde` feature of the `zerovec` crate
+/// This impl requires enabling the optional `serde` Cargo feature of the `zerovec` crate
#[cfg(feature = "serde")]
impl serde::Serialize for UnvalidatedStr {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
@@ -173,7 +173,7 @@ impl serde::Serialize for UnvalidatedStr {
}
}
-/// This impl can be made available by enabling the optional `serde` feature of the `zerovec` crate
+/// This impl requires enabling the optional `serde` Cargo feature of the `zerovec` crate
#[cfg(feature = "serde")]
impl<'de> serde::Deserialize<'de> for Box<UnvalidatedStr> {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
@@ -190,7 +190,7 @@ impl<'de> serde::Deserialize<'de> for Box<UnvalidatedStr> {
}
}
-/// This impl can be made available by enabling the optional `serde` feature of the `zerovec` crate
+/// This impl requires enabling the optional `serde` Cargo feature of the `zerovec` crate
#[cfg(feature = "serde")]
impl<'de, 'a> serde::Deserialize<'de> for &'a UnvalidatedStr
where
diff --git a/vendor/zerovec/src/varzerovec/serde.rs b/vendor/zerovec/src/varzerovec/serde.rs
index dd6e863ff..649b29cfb 100644
--- a/vendor/zerovec/src/varzerovec/serde.rs
+++ b/vendor/zerovec/src/varzerovec/serde.rs
@@ -60,7 +60,7 @@ where
}
}
-/// This impl can be made available by enabling the optional `serde` feature of the `zerovec` crate
+/// This impl requires enabling the optional `serde` Cargo feature of the `zerovec` crate
impl<'de, 'a, T, F> Deserialize<'de> for VarZeroVec<'a, T, F>
where
T: VarULE + ?Sized,
@@ -81,7 +81,7 @@ where
}
}
-/// This impl can be made available by enabling the optional `serde` feature of the `zerovec` crate
+/// This impl requires enabling the optional `serde` Cargo feature of the `zerovec` crate
impl<'de, 'a, T, F> Deserialize<'de> for &'a VarZeroSlice<T, F>
where
T: VarULE + ?Sized,
@@ -111,7 +111,7 @@ where
}
}
-/// This impl can be made available by enabling the optional `serde` feature of the `zerovec` crate
+/// This impl requires enabling the optional `serde` Cargo feature of the `zerovec` crate
#[cfg(feature = "serde")]
impl<T, F> Serialize for VarZeroVec<'_, T, F>
where
@@ -134,7 +134,7 @@ where
}
}
-/// This impl can be made available by enabling the optional `serde` feature of the `zerovec` crate
+/// This impl requires enabling the optional `serde` Cargo feature of the `zerovec` crate
#[cfg(feature = "serde")]
impl<T, F> Serialize for VarZeroSlice<T, F>
where
diff --git a/vendor/zerovec/src/varzerovec/slice.rs b/vendor/zerovec/src/varzerovec/slice.rs
index 59e8da03f..afdbe80d9 100644
--- a/vendor/zerovec/src/varzerovec/slice.rs
+++ b/vendor/zerovec/src/varzerovec/slice.rs
@@ -29,8 +29,13 @@ use core::ops::Range;
/// The `F` type parameter is a [`VarZeroVecFormat`] (see its docs for more details), which can be used to select the
/// precise format of the backing buffer with various size and performance tradeoffs. It defaults to [`Index16`].
///
-/// This type can be nested within itself to allow for multi-level nested `Vec`s, for
-/// example the following code constructs the conceptual zero-copy equivalent of `Vec<Vec<Vec<str>>>`
+/// This type can be nested within itself to allow for multi-level nested `Vec`s.
+///
+/// # Examples
+///
+/// ## Nested Slices
+///
+/// The following code constructs the conceptual zero-copy equivalent of `Vec<Vec<Vec<str>>>`
///
/// ```rust
/// use zerovec::ule::*;
@@ -71,6 +76,25 @@ use core::ops::Range;
/// VarZeroVec::parse_byte_slice(bytes).unwrap();
/// assert_eq!(vzv_from_bytes, vzv_all);
/// ```
+///
+/// ## Iterate over Windows
+///
+/// Although [`VarZeroSlice`] does not itself have a `.windows` iterator like
+/// [core::slice::Windows], this behavior can be easily modeled using an iterator:
+///
+/// ```
+/// use zerovec::VarZeroVec;
+///
+/// let vzv = VarZeroVec::<str>::from(&["a", "b", "c", "d"]);
+/// # let mut pairs: Vec<(&str, &str)> = Vec::new();
+///
+/// let mut it = vzv.iter().peekable();
+/// while let (Some(x), Some(y)) = (it.next(), it.peek()) {
+/// // Evaluate (x, y) here.
+/// # pairs.push((x, y));
+/// }
+/// # assert_eq!(pairs, &[("a", "b"), ("b", "c"), ("c", "d")]);
+/// ```
//
// safety invariant: The slice MUST be one which parses to
// a valid VarZeroVecComponents<T>
diff --git a/vendor/zerovec/src/varzerovec/vec.rs b/vendor/zerovec/src/varzerovec/vec.rs
index 031da6453..7edb48a96 100644
--- a/vendor/zerovec/src/varzerovec/vec.rs
+++ b/vendor/zerovec/src/varzerovec/vec.rs
@@ -11,7 +11,7 @@ use core::ops::Deref;
use super::*;
-/// A zero-copy vector for variable-width types.
+/// A zero-copy, byte-aligned vector for variable-width types.
///
/// `VarZeroVec<T>` is designed as a drop-in replacement for `Vec<T>` in situations where it is
/// desirable to borrow data from an unaligned byte slice, such as zero-copy deserialization, and
@@ -39,6 +39,20 @@ use super::*;
/// The `F` type parameter is a [`VarZeroVecFormat`] (see its docs for more details), which can be used to select the
/// precise format of the backing buffer with various size and performance tradeoffs. It defaults to [`Index16`].
///
+/// # Bytes and Equality
+///
+/// Two [`VarZeroVec`]s are equal if and only if their bytes are equal, as described in the trait
+/// [`VarULE`]. However, we do not guarantee stability of byte equality or serialization format
+/// across major SemVer releases.
+///
+/// To compare a [`Vec<T>`] to a [`VarZeroVec<T>`], it is generally recommended to use
+/// [`Iterator::eq`], since it is somewhat expensive at runtime to convert from a [`Vec<T>`] to a
+/// [`VarZeroVec<T>`] or vice-versa.
+///
+/// Prior to zerovec reaching 1.0, the precise byte representation of [`VarZeroVec`] is still
+/// under consideration, with different options along the space-time spectrum. See
+/// [#1410](https://github.com/unicode-org/icu4x/issues/1410).
+///
/// # Example
///
/// ```rust
diff --git a/vendor/zerovec/src/yoke_impls.rs b/vendor/zerovec/src/yoke_impls.rs
index 81fc22c74..0efb47a2d 100644
--- a/vendor/zerovec/src/yoke_impls.rs
+++ b/vendor/zerovec/src/yoke_impls.rs
@@ -15,7 +15,7 @@ use core::{mem, ptr};
use yoke::*;
// This impl is similar to the impl on Cow and is safe for the same reasons
-/// This impl can be made available by enabling the optional `yoke` feature of the `zerovec` crate
+/// This impl requires enabling the optional `yoke` Cargo feature of the `zerovec` crate
unsafe impl<'a, T: 'static + AsULE + ?Sized> Yokeable<'a> for ZeroVec<'static, T> {
type Output = ZeroVec<'a, T>;
#[inline]
@@ -43,7 +43,7 @@ unsafe impl<'a, T: 'static + AsULE + ?Sized> Yokeable<'a> for ZeroVec<'static, T
}
// This impl is similar to the impl on Cow and is safe for the same reasons
-/// This impl can be made available by enabling the optional `yoke` feature of the `zerovec` crate
+/// This impl requires enabling the optional `yoke` Cargo feature of the `zerovec` crate
unsafe impl<'a, T: 'static + VarULE + ?Sized> Yokeable<'a> for VarZeroVec<'static, T> {
type Output = VarZeroVec<'a, T>;
#[inline]
@@ -71,7 +71,7 @@ unsafe impl<'a, T: 'static + VarULE + ?Sized> Yokeable<'a> for VarZeroVec<'stati
}
// This impl is similar to the impl on Cow and is safe for the same reasons
-/// This impl can be made available by enabling the optional `yoke` feature of the `zerovec` crate
+/// This impl requires enabling the optional `yoke` Cargo feature of the `zerovec` crate
unsafe impl<'a> Yokeable<'a> for FlexZeroVec<'static> {
type Output = FlexZeroVec<'a>;
#[inline]
@@ -98,7 +98,7 @@ unsafe impl<'a> Yokeable<'a> for FlexZeroVec<'static> {
}
}
-/// This impl can be made available by enabling the optional `yoke` feature of the `zerovec` crate
+/// This impl requires enabling the optional `yoke` Cargo feature of the `zerovec` crate
#[allow(clippy::transmute_ptr_to_ptr)]
unsafe impl<'a, K, V> Yokeable<'a> for ZeroMap<'static, K, V>
where
@@ -144,7 +144,7 @@ where
}
}
-/// This impl can be made available by enabling the optional `yoke` feature of the `zerovec` crate
+/// This impl requires enabling the optional `yoke` Cargo feature of the `zerovec` crate
#[allow(clippy::transmute_ptr_to_ptr)]
unsafe impl<'a, K, V> Yokeable<'a> for ZeroMapBorrowed<'static, K, V>
where
@@ -190,7 +190,7 @@ where
}
}
-/// This impl can be made available by enabling the optional `yoke` feature of the `zerovec` crate
+/// This impl requires enabling the optional `yoke` Cargo feature of the `zerovec` crate
#[allow(clippy::transmute_ptr_to_ptr)]
unsafe impl<'a, K0, K1, V> Yokeable<'a> for ZeroMap2d<'static, K0, K1, V>
where
@@ -238,7 +238,7 @@ where
}
}
-/// This impl can be made available by enabling the optional `yoke` feature of the `zerovec` crate
+/// This impl requires enabling the optional `yoke` Cargo feature of the `zerovec` crate
#[allow(clippy::transmute_ptr_to_ptr)]
unsafe impl<'a, K0, K1, V> Yokeable<'a> for ZeroMap2dBorrowed<'static, K0, K1, V>
where
diff --git a/vendor/zerovec/src/zerovec/mod.rs b/vendor/zerovec/src/zerovec/mod.rs
index e0876338f..371450e21 100644
--- a/vendor/zerovec/src/zerovec/mod.rs
+++ b/vendor/zerovec/src/zerovec/mod.rs
@@ -22,7 +22,7 @@ use core::marker::PhantomData;
use core::mem;
use core::ops::Deref;
-/// A zero-copy vector for fixed-width types.
+/// A zero-copy, byte-aligned vector for fixed-width types.
///
/// `ZeroVec<T>` is designed as a drop-in replacement for `Vec<T>` in situations where it is
/// desirable to borrow data from an unaligned byte slice, such as zero-copy deserialization.
@@ -352,11 +352,6 @@ where
/// `bytes` need to be an output from [`ZeroSlice::as_bytes()`].
pub const unsafe fn from_bytes_unchecked(bytes: &'a [u8]) -> Self {
// &[u8] and &[T::ULE] are the same slice with different length metadata.
- /// core::slice::from_raw_parts(a, b) = core::mem::transmute((a, b)) hack
- /// ```compile_fail
- /// const unsafe fn canary() { core::slice::from_raw_parts(0 as *const u8, 0); }
- /// ```
- const _: () = ();
Self::new_borrowed(core::mem::transmute((
bytes.as_ptr(),
bytes.len() / core::mem::size_of::<T::ULE>(),
diff --git a/vendor/zerovec/src/zerovec/serde.rs b/vendor/zerovec/src/zerovec/serde.rs
index 8250fc20a..e3141071c 100644
--- a/vendor/zerovec/src/zerovec/serde.rs
+++ b/vendor/zerovec/src/zerovec/serde.rs
@@ -58,7 +58,7 @@ where
}
}
-/// This impl can be made available by enabling the optional `serde` feature of the `zerovec` crate
+/// This impl requires enabling the optional `serde` Cargo feature of the `zerovec` crate
impl<'de, 'a, T> Deserialize<'de> for ZeroVec<'a, T>
where
T: 'de + Deserialize<'de> + AsULE,
@@ -77,7 +77,7 @@ where
}
}
-/// This impl can be made available by enabling the optional `serde` feature of the `zerovec` crate
+/// This impl requires enabling the optional `serde` Cargo feature of the `zerovec` crate
impl<T> Serialize for ZeroVec<'_, T>
where
T: Serialize + AsULE,
@@ -98,7 +98,7 @@ where
}
}
-/// This impl can be made available by enabling the optional `serde` feature of the `zerovec` crate
+/// This impl requires enabling the optional `serde` Cargo feature of the `zerovec` crate
impl<'de, T> Deserialize<'de> for Box<ZeroSlice<T>>
where
T: Deserialize<'de> + AsULE + 'static,
@@ -113,7 +113,7 @@ where
}
}
-/// This impl can be made available by enabling the optional `serde` feature of the `zerovec` crate
+/// This impl requires enabling the optional `serde` Cargo feature of the `zerovec` crate
impl<'de, 'a, T> Deserialize<'de> for &'a ZeroSlice<T>
where
T: Deserialize<'de> + AsULE + 'static,
@@ -141,7 +141,7 @@ where
}
}
-/// This impl can be made available by enabling the optional `serde` feature of the `zerovec` crate
+/// This impl requires enabling the optional `serde` Cargo feature of the `zerovec` crate
impl<T> Serialize for ZeroSlice<T>
where
T: Serialize + AsULE,
diff --git a/vendor/zerovec/src/zerovec/slice.rs b/vendor/zerovec/src/zerovec/slice.rs
index ce27a15b2..847705304 100644
--- a/vendor/zerovec/src/zerovec/slice.rs
+++ b/vendor/zerovec/src/zerovec/slice.rs
@@ -65,12 +65,10 @@ where
/// `bytes` need to be an output from [`ZeroSlice::as_bytes()`].
pub const unsafe fn from_bytes_unchecked(bytes: &[u8]) -> &Self {
// &[u8] and &[T::ULE] are the same slice with different length metadata.
- /// core::slice::from_raw_parts(a, b) = core::mem::transmute((a, b)) hack
- /// ```compile_fail
- /// const unsafe fn canary() { core::slice::from_raw_parts(0 as *const u8, 0); }
- /// ```
- const _: () = ();
- core::mem::transmute((bytes.as_ptr(), bytes.len() / core::mem::size_of::<T::ULE>()))
+ Self::from_ule_slice(core::mem::transmute((
+ bytes.as_ptr(),
+ bytes.len() / core::mem::size_of::<T::ULE>(),
+ )))
}
/// Construct a `&ZeroSlice<T>` from a slice of ULEs.
@@ -235,17 +233,17 @@ where
/// ```
/// use zerovec::ZeroSlice;
///
- /// const bytes: &[u8] = &[0xD3, 0x00, 0x19, 0x01, 0xA5, 0x01, 0xCD, 0x80];
- /// const zs_u16: &ZeroSlice<u16> = {
- /// match ZeroSlice::<u16>::try_from_bytes(bytes) {
+ /// const BYTES: &[u8] = &[0xD3, 0x00, 0x19, 0x01, 0xA5, 0x01, 0xCD, 0x80];
+ /// const ZS_U16: &ZeroSlice<u16> = {
+ /// match ZeroSlice::<u16>::try_from_bytes(BYTES) {
/// Ok(s) => s,
/// Err(_) => unreachable!(),
/// }
/// };
///
- /// let zs_i16: &ZeroSlice<i16> = zs_u16.cast();
+ /// let zs_i16: &ZeroSlice<i16> = ZS_U16.cast();
///
- /// assert_eq!(zs_u16.get(3), Some(32973));
+ /// assert_eq!(ZS_U16.get(3), Some(32973));
/// assert_eq!(zs_i16.get(3), Some(-32563));
/// ```
#[inline]
@@ -268,18 +266,18 @@ where
/// ```
/// use zerovec::ZeroSlice;
///
- /// const bytes: &[u8] = &[0x7F, 0xF3, 0x01, 0x00, 0x49, 0xF6, 0x01, 0x00];
- /// const zs_u32: &ZeroSlice<u32> = {
- /// match ZeroSlice::<u32>::try_from_bytes(bytes) {
+ /// const BYTES: &[u8] = &[0x7F, 0xF3, 0x01, 0x00, 0x49, 0xF6, 0x01, 0x00];
+ /// const ZS_U32: &ZeroSlice<u32> = {
+ /// match ZeroSlice::<u32>::try_from_bytes(BYTES) {
/// Ok(s) => s,
/// Err(_) => unreachable!(),
/// }
/// };
///
/// let zs_u8_4: &ZeroSlice<[u8; 4]> =
- /// zs_u32.try_as_converted().expect("valid code points");
+ /// ZS_U32.try_as_converted().expect("valid code points");
///
- /// assert_eq!(zs_u32.get(0), Some(127871));
+ /// assert_eq!(ZS_U32.get(0), Some(127871));
/// assert_eq!(zs_u8_4.get(0), Some([0x7F, 0xF3, 0x01, 0x00]));
/// ```
#[inline]
diff --git a/vendor/zip/.cargo-checksum.json b/vendor/zip/.cargo-checksum.json
index e3121cd34..9766507eb 100644
--- a/vendor/zip/.cargo-checksum.json
+++ b/vendor/zip/.cargo-checksum.json
@@ -1 +1 @@
-{"files":{"CODE_OF_CONDUCT.md":"77930b2129928632cae79e10d0863885b34729e4f144f3ae5443cff65997196a","Cargo.lock":"bf885d0e396f14628e19f1e5e6757d8539ba6ffa3103849159aa2106d280d6c2","Cargo.toml":"89efc81641360c8d5542d56dd8b23d65b7c4f7921dea5fd4c8c43ef8db358063","LICENSE":"6ac8711fb340c62ce0a4ecd463342d3fa0e8e70de697c863a2e1c0c53006003c","README.md":"0c9a153af715012ac84e84f11de2cf9af94eefd98f4fcaee272fcffae482732e","benches/read_entry.rs":"700235ee560887f33da56895d2a4da901c070b2a6a59aef90331046af4ddadad","benches/read_metadata.rs":"4134c674361534b32ef7fa3776c9da93928d2ba4ad13bc74438397a5a6281555","examples/extract.rs":"c6e16e42391ce294093866822dc2ee8cf45231d50101d619a0caffa1be633ae6","examples/extract_lorem.rs":"a5b33a31e7a2865e8ed7af52bab538268a8ba07cc4c3d8aa85811f80c86cb1fb","examples/file_info.rs":"e091923fc8c492255609efdd3c5fb656ad177601a73f4011005deab8096ca425","examples/stdin_info.rs":"f0bfed4016abbdb3922426f118bc990e6a1335bab878e1e146cb057f4e33d3cf","examples/write_dir.rs":"6f0b62022946765b6ef5f8ecac054a742d823ab0473152748d637da1568a9475","examples/write_sample.rs":"f57f463a9dea4eca7054d10d35bd8c65e1b6e0530bfbebf758006acea1e4ca0d","src/aes.rs":"c1b19bdf15c75cc27b5657d1dc574b5c5ebcdc7ca2573e9909cc6ba1ffe7f6d8","src/aes_ctr.rs":"6a7a07c9538daf53624818f82084c6655db3862ca00751f3679c8b0bc346b70d","src/compression.rs":"20c2f0c1857a3dce154505b5a73b6a22da867e16d676f0617a0e453f13cad175","src/cp437.rs":"e3a044ddefc947f6d9c26ba50ebd438955d90b8971ad8b15e5dd1194495f3b93","src/crc32.rs":"6c5a48834dfa1ab33590fcc63f4121ee6d3f8fbcc5018e905c4d8570096874cf","src/lib.rs":"7c2f6bc3dde9575eeeaef9569139f28351333c29362f74569e627ad7be5a10b2","src/read.rs":"245b8a4d5b367f917668d4db77f20331612a48a59641484e56692a22ffb61a7e","src/result.rs":"cfa7a545a56c6ce807c04675d70f9aed42d1aa19ffb717f4f94b8901a9f3728d","src/spec.rs":"e3b3429c814bb78efe14a8a48d53c30793f017b5d090889d72a2dc20b94c549a","src/types.rs":"b2979cdba63c9f5e9360578036541a80780300ca4febaece5730f670ab1b0a74","src/write.rs":"8062be33459c58751c3ca8f058df0524cfc05d12648cc77b0d505e32afb98c48","src/zipcrypto.rs":"4fe362af2a8e419d9cff6acc165acdc0dccaacc53baec7269b5f55dfcd396f5c","tests/aes_encryption.rs":"3733df1f5dcab4e9f9b9ec25cc7660f23c917759670e9b2e6fe77cfcd771faa9","tests/data/aes_archive.zip":"4abb3f304d1ab669453b7c4eae80db6ce8aff4ab91c8ab9a6edf90bbfede12f4","tests/data/comment_garbage.zip":"4a908af18691e50fc7773b34669a8ab6cb60875bee4d60fb7cd66d90eed55d2b","tests/data/files_and_dirs.zip":"e54cd8d084739f8d0b119d769c1263507b4da915cc38e4e2d3e4ef17c718f317","tests/data/invalid_cde_number_of_files_allocation_greater_offset.zip":"c680ed5ad622aae23eea3b5d90145cb79550e413cc6e9a7b67bb1043851512ee","tests/data/invalid_cde_number_of_files_allocation_smaller_offset.zip":"7c272255e825aff7167dc8d1f2e1d16583e58347bb56ecf9879bdb07c6ad18e9","tests/data/invalid_offset.zip":"c5534a1803145f6344b04c437d436bd583852c78dd3937f4a73a2a39aa2d76b2","tests/data/invalid_offset2.zip":"0f0f3d654f303eaf90f599c0b0266be476ce34857cff932070a86e9853dcb4f9","tests/data/mimetype.zip":"aad4289745bd89016181a35653c9a483c6b9b632e06d002736c7040d61c562a2","tests/data/zip64_demo.zip":"223072a480f60d6a700e427b294e575ae2d6265f3e9881b647927f31d96c7e01","tests/end_to_end.rs":"a39d88edcea901bba2bbdb277f073724a4aadd5c8e692256e9c57a09fb2fd357","tests/invalid_date.rs":"72d5425ffe2887e05646ba56f5116ac760cbeeb7889da5c9be612fe57477bc94","tests/issue_234.rs":"1a3d68d79108140100709c188841c6bf54af8500c819072a440ec72df5d8ab26","tests/zip64_large.rs":"083f070ae566e0a3b317bd94d51186b37f2ff88f225deae721b0b56be838da1c","tests/zip_comment_garbage.rs":"ab0e2e3ace1ca5459977a092ee96836f58c7f7a7cfc8de258ab448d8d24f1cbb","tests/zip_crypto.rs":"7f4f9670e5d971ac4234c7ab2cafecf43801baf0be0cfca6e34c651f6fc6a80d"},"package":"537ce7411d25e54e8ae21a7ce0b15840e7bfcff15b51d697ec3266cc76bdf080"} \ No newline at end of file
+{"files":{"CHANGELOG.md":"da022ffbfcbf04616fc8e31b7a38fd7c8f2ad47a7fb42750fc04de110cf95857","CODE_OF_CONDUCT.md":"77930b2129928632cae79e10d0863885b34729e4f144f3ae5443cff65997196a","Cargo.lock":"5c81aacae00a3838358fed3e453cbb128f9870162a280d91b77f20c7b4c94390","Cargo.toml":"69d71445861d823f30fbd330f74cb395ed1f4e981f3c61e4754eda2f1f1cb0b4","LICENSE":"6ac8711fb340c62ce0a4ecd463342d3fa0e8e70de697c863a2e1c0c53006003c","README.md":"4da0a964d8fb78a5caae4674b4f69fc24f080167af56927d1a5c15412f9f672d","benches/read_entry.rs":"700235ee560887f33da56895d2a4da901c070b2a6a59aef90331046af4ddadad","benches/read_metadata.rs":"591e5adb9d36bf66da21d7e0d36a129c9bcf1331fa11714df8c53c860aee65ff","examples/extract.rs":"81f58da293553fe019319348e1d226a2d192480667877e72d77ab58812f5de1b","examples/extract_lorem.rs":"2d438706ca6e02468f362a54f4f2125598d2be1051e7ce40b71be58cfd703669","examples/file_info.rs":"20639234293511022938c8204488d182ccbcdfb59d962000acd8ac8f2f6db667","examples/stdin_info.rs":"5735801c9692a9b6ec35da6e6a65807db48b577068ab9df0018343df5161034b","examples/write_dir.rs":"224239e040c583f2e1ca4b1328ebe1a63b3c2213df6da8232cd62e004db05587","examples/write_sample.rs":"f723bf69676492599c2684aa995177f80e2aa922f1c9ae1681ed39e0a15959ad","src/aes.rs":"c1b19bdf15c75cc27b5657d1dc574b5c5ebcdc7ca2573e9909cc6ba1ffe7f6d8","src/aes_ctr.rs":"6a7a07c9538daf53624818f82084c6655db3862ca00751f3679c8b0bc346b70d","src/compression.rs":"84f8ded41182155cfbdb1ce79b9dc84cae0a6e55557021cf9f2d7168d8913b48","src/cp437.rs":"e3a044ddefc947f6d9c26ba50ebd438955d90b8971ad8b15e5dd1194495f3b93","src/crc32.rs":"6c5a48834dfa1ab33590fcc63f4121ee6d3f8fbcc5018e905c4d8570096874cf","src/lib.rs":"7c2f6bc3dde9575eeeaef9569139f28351333c29362f74569e627ad7be5a10b2","src/read.rs":"1c8e60c37a7016399d5bdf3796bcd4ad8a5cdf7450498233c7d056fd7533692a","src/result.rs":"7dc62da507ef2228313ed617d01f4d207eacb0b66352a497d24f04298e90e5df","src/spec.rs":"2a249aeb3c58ca475b5c7da6919cb61ac3cbe07b94a0cb3c730646d46fb265a8","src/types.rs":"21a37a8632bd9b2572a7ccd19e6048dcc453a3c4fd7583f3eddefbec7dd641a5","src/write.rs":"16ccc971f2858042d2f92e0448a72849745ea0a25449fd7c8961b78a466b6e6e","src/zipcrypto.rs":"4fe362af2a8e419d9cff6acc165acdc0dccaacc53baec7269b5f55dfcd396f5c","tests/aes_encryption.rs":"3733df1f5dcab4e9f9b9ec25cc7660f23c917759670e9b2e6fe77cfcd771faa9","tests/data/aes_archive.zip":"4abb3f304d1ab669453b7c4eae80db6ce8aff4ab91c8ab9a6edf90bbfede12f4","tests/data/comment_garbage.zip":"4a908af18691e50fc7773b34669a8ab6cb60875bee4d60fb7cd66d90eed55d2b","tests/data/files_and_dirs.zip":"e54cd8d084739f8d0b119d769c1263507b4da915cc38e4e2d3e4ef17c718f317","tests/data/invalid_cde_number_of_files_allocation_greater_offset.zip":"c680ed5ad622aae23eea3b5d90145cb79550e413cc6e9a7b67bb1043851512ee","tests/data/invalid_cde_number_of_files_allocation_smaller_offset.zip":"7c272255e825aff7167dc8d1f2e1d16583e58347bb56ecf9879bdb07c6ad18e9","tests/data/invalid_offset.zip":"c5534a1803145f6344b04c437d436bd583852c78dd3937f4a73a2a39aa2d76b2","tests/data/invalid_offset2.zip":"0f0f3d654f303eaf90f599c0b0266be476ce34857cff932070a86e9853dcb4f9","tests/data/mimetype.zip":"aad4289745bd89016181a35653c9a483c6b9b632e06d002736c7040d61c562a2","tests/data/zip64_demo.zip":"223072a480f60d6a700e427b294e575ae2d6265f3e9881b647927f31d96c7e01","tests/end_to_end.rs":"ba69c247e2f555a954ae97615a46a9b21092671f7ff1abebaba058b30a53bb66","tests/invalid_date.rs":"72d5425ffe2887e05646ba56f5116ac760cbeeb7889da5c9be612fe57477bc94","tests/issue_234.rs":"1a3d68d79108140100709c188841c6bf54af8500c819072a440ec72df5d8ab26","tests/zip64_large.rs":"d4859f551be83c2ae3bd4a8e37c7e617fb54bb27310e725de6c7076c5e566d6b","tests/zip_comment_garbage.rs":"ab0e2e3ace1ca5459977a092ee96836f58c7f7a7cfc8de258ab448d8d24f1cbb","tests/zip_crypto.rs":"7f4f9670e5d971ac4234c7ab2cafecf43801baf0be0cfca6e34c651f6fc6a80d"},"package":"0445d0fbc924bb93539b4316c11afb121ea39296f99a3c4c9edad09e3658cdef"} \ No newline at end of file
diff --git a/vendor/zip/CHANGELOG.md b/vendor/zip/CHANGELOG.md
new file mode 100644
index 000000000..cd79e3913
--- /dev/null
+++ b/vendor/zip/CHANGELOG.md
@@ -0,0 +1,9 @@
+# Changelog
+
+## [0.6.4]
+
+### Changed
+
+ - [#333](https://github.com/zip-rs/zip/pull/333): disabled the default features of the `time` dependency, and also `formatting` and `macros`, as they were enabled by mistake.
+ - Deprecated [`DateTime::from_time`](https://docs.rs/zip/0.6/zip/struct.DateTime.html#method.from_time) in favor of [`DateTime::try_from`](https://docs.rs/zip/0.6/zip/struct.DateTime.html#impl-TryFrom-for-DateTime)
+ \ No newline at end of file
diff --git a/vendor/zip/Cargo.lock b/vendor/zip/Cargo.lock
index 1da5fdf76..f0f4b2bd0 100644
--- a/vendor/zip/Cargo.lock
+++ b/vendor/zip/Cargo.lock
@@ -22,9 +22,9 @@ dependencies = [
[[package]]
name = "base64ct"
-version = "1.0.1"
+version = "1.5.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8a32fd6af2b5827bce66c29053ba0e7c42b9dcab01835835058558c10851a46b"
+checksum = "b645a089122eccb6111b4f81cbc1a49f5900ac4666bb93ac027feaecf15607bf"
[[package]]
name = "bencher"
@@ -34,9 +34,9 @@ checksum = "7dfdb4953a096c551ce9ace855a604d702e6e62d77fac690575ae347571717f5"
[[package]]
name = "block-buffer"
-version = "0.10.2"
+version = "0.10.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0bf7fe51849ea569fd452f37822f606a5cabb684dc918707a0193fd4664ff324"
+checksum = "69cce20737498f97b993470a6e536b8523f0af7892a4f928cceb1ac5e52ebe7e"
dependencies = [
"generic-array",
]
@@ -49,9 +49,9 @@ checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"
[[package]]
name = "bzip2"
-version = "0.4.3"
+version = "0.4.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6afcd980b5f3a45017c57e57a2fcccbb351cc43a356ce117ef760ef8052b89b0"
+checksum = "bdb116a6ef3f6c3698828873ad02c3014b3c85cadb88496095628e3ef1e347f8"
dependencies = [
"bzip2-sys",
"libc",
@@ -70,9 +70,9 @@ dependencies = [
[[package]]
name = "cc"
-version = "1.0.73"
+version = "1.0.78"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11"
+checksum = "a20104e2335ce8a659d6dd92a51a767a0c062599c73b343fd152cb401e828c3d"
dependencies = [
"jobserver",
]
@@ -100,9 +100,9 @@ checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc"
[[package]]
name = "cpufeatures"
-version = "0.2.2"
+version = "0.2.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "59a6001667ab124aebae2a495118e11d30984c3a653e99d86d58971708cf5e4b"
+checksum = "28d997bd5e24a5928dd43e46dc529867e207907fe0b239c3477d924f7f2ca320"
dependencies = [
"libc",
]
@@ -118,19 +118,18 @@ dependencies = [
[[package]]
name = "crossbeam-utils"
-version = "0.8.8"
+version = "0.8.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0bf124c720b7686e3c2663cf54062ab0f68a88af2fb6a030e87e30bf721fcb38"
+checksum = "4fb766fa798726286dbbb842f174001dab8abc7b627a1dd86e0b7222a95d929f"
dependencies = [
"cfg-if",
- "lazy_static",
]
[[package]]
name = "crypto-common"
-version = "0.1.3"
+version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "57952ca27b5e3606ff4dd79b0020231aaf9d6aa76dc05fd30137538c50bd3ce8"
+checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3"
dependencies = [
"generic-array",
"typenum",
@@ -138,9 +137,9 @@ dependencies = [
[[package]]
name = "digest"
-version = "0.10.3"
+version = "0.10.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f2fb860ca6fafa5552fb6d0e816a69c8e49f0908bf524e30a90d97c85892d506"
+checksum = "8168378f4e5023e7218c89c891c0fd8ecdb5e5e4f18cb78f38cf245dd021e76f"
dependencies = [
"block-buffer",
"crypto-common",
@@ -149,9 +148,9 @@ dependencies = [
[[package]]
name = "flate2"
-version = "1.0.24"
+version = "1.0.25"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f82b0f4c27ad9f8bfd1f3208d882da2b09c301bc1c828fd3a00d0216d2fbbff6"
+checksum = "a8a2db397cb1c8772f31494cb8917e48cd1e64f0fa7efac59fbd741a0a8ce841"
dependencies = [
"crc32fast",
"libz-sys",
@@ -160,9 +159,9 @@ dependencies = [
[[package]]
name = "generic-array"
-version = "0.14.5"
+version = "0.14.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fd48d33ec7f05fbfa152300fdad764757cbded343c1aa1cff2fbaf4134851803"
+checksum = "bff49e947297f3312447abdca79f45f4738097cc82b06e72054d2223f601f1b9"
dependencies = [
"typenum",
"version_check",
@@ -170,9 +169,9 @@ dependencies = [
[[package]]
name = "getrandom"
-version = "0.2.6"
+version = "0.2.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9be70c98951c83b8d2f8f60d7065fa6d5146873094452a1008da8c2f1e4205ad"
+checksum = "c05aeb6a22b8f62540c194aac980f2115af067bfe15a0734d7277a768d396b31"
dependencies = [
"cfg-if",
"libc",
@@ -190,30 +189,24 @@ dependencies = [
[[package]]
name = "itoa"
-version = "1.0.1"
+version = "1.0.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1aab8fc367588b89dcee83ab0fd66b72b50b72fa1904d7095045ace2b0c81c35"
+checksum = "fad582f4b9e86b6caa621cabeb0963332d92eea04729ab12892c2533951e6440"
[[package]]
name = "jobserver"
-version = "0.1.24"
+version = "0.1.25"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "af25a77299a7f711a01975c35a6a424eb6862092cc2d6c72c4ed6cbc56dfc1fa"
+checksum = "068b1ee6743e4d11fb9c6a1e6064b3693a1b600e7f5f5988047d98b3dc9fb90b"
dependencies = [
"libc",
]
[[package]]
-name = "lazy_static"
-version = "1.4.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
-
-[[package]]
name = "libc"
-version = "0.2.121"
+version = "0.2.139"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "efaa7b300f3b5fe8eb6bf21ce3895e1751d9665086af2d64b42f19701015ff4f"
+checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79"
[[package]]
name = "libz-sys"
@@ -228,23 +221,14 @@ dependencies = [
[[package]]
name = "miniz_oxide"
-version = "0.5.4"
+version = "0.6.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "96590ba8f175222643a85693f33d26e9c8a015f599c216509b1a6894af675d34"
+checksum = "b275950c28b37e794e8c55d88aeb5e139d0ce23fdbbeda68f8d7174abdf9e8fa"
dependencies = [
"adler",
]
[[package]]
-name = "num_threads"
-version = "0.1.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "aba1801fb138d8e85e11d0fc70baf4fe1cdfffda7c6cd34a854905df588e5ed0"
-dependencies = [
- "libc",
-]
-
-[[package]]
name = "opaque-debug"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -275,15 +259,15 @@ dependencies = [
[[package]]
name = "pkg-config"
-version = "0.3.25"
+version = "0.3.26"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1df8c4ec4b0627e53bdf214615ad287367e482558cf84b109250b37464dc03ae"
+checksum = "6ac9a59f73473f1b8d852421e59e64809f025994837ef743615c6d0c5b305160"
[[package]]
name = "rand_core"
-version = "0.6.3"
+version = "0.6.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7"
+checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
[[package]]
name = "same-file"
@@ -295,10 +279,16 @@ dependencies = [
]
[[package]]
+name = "serde"
+version = "1.0.152"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bb7d1f0d3021d347a83e556fc4683dea2ea09d87bccdf88ff5c12545d89d5efb"
+
+[[package]]
name = "sha1"
-version = "0.10.1"
+version = "0.10.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c77f4e7f65455545c2153c1253d25056825e77ee2533f0e41deb65a93a34852f"
+checksum = "f04293dc80c3993519f2d7f6f511707ee7094fe0c6d3406feb330cdb3540eba3"
dependencies = [
"cfg-if",
"cpufeatures",
@@ -307,9 +297,9 @@ dependencies = [
[[package]]
name = "sha2"
-version = "0.10.2"
+version = "0.10.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "55deaec60f81eefe3cce0dc50bda92d6d8e88f2a27df7c5033b42afeb1ed2676"
+checksum = "82e6b795fe2e3b1e845bafcb27aa35405c4d47cdfc92af5fc8d3002f76cebdc0"
dependencies = [
"cfg-if",
"cpufeatures",
@@ -324,27 +314,36 @@ checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601"
[[package]]
name = "time"
-version = "0.3.9"
+version = "0.3.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c2702e08a7a860f005826c6815dcac101b19b5eb330c27fe4a5928fec1d20ddd"
+checksum = "a561bf4617eebd33bca6434b988f39ed798e527f51a1e797d0ee4f61c0a38376"
dependencies = [
"itoa",
- "libc",
- "num_threads",
+ "serde",
+ "time-core",
"time-macros",
]
[[package]]
+name = "time-core"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2e153e1f1acaef8acc537e68b44906d2db6436e2b35ac2c6b42640fff91f00fd"
+
+[[package]]
name = "time-macros"
-version = "0.2.4"
+version = "0.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "42657b1a6f4d817cda8e7a0ace261fe0cc946cf3a80314390b22cc61ae080792"
+checksum = "d967f99f534ca7e495c575c62638eebc2898a8c84c119b89e250477bc4ba16b2"
+dependencies = [
+ "time-core",
+]
[[package]]
name = "typenum"
-version = "1.15.0"
+version = "1.16.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dcf81ac59edc17cc8697ff311e8f5ef2d99fcbd9817b34cec66f90b6c3dfd987"
+checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba"
[[package]]
name = "vcpkg"
@@ -371,9 +370,9 @@ dependencies = [
[[package]]
name = "wasi"
-version = "0.10.2+wasi-snapshot-preview1"
+version = "0.11.0+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6"
+checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
[[package]]
name = "winapi"
@@ -408,7 +407,7 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
[[package]]
name = "zip"
-version = "0.6.3"
+version = "0.6.4"
dependencies = [
"aes",
"bencher",
@@ -448,10 +447,11 @@ dependencies = [
[[package]]
name = "zstd-sys"
-version = "2.0.1+zstd.1.5.2"
+version = "2.0.5+zstd.1.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9fd07cbbc53846d9145dbffdf6dd09a7a0aa52be46741825f5c97bdd4f73f12b"
+checksum = "edc50ffce891ad571e9f9afe5039c4837bede781ac4bb13052ed7ae695518596"
dependencies = [
"cc",
"libc",
+ "pkg-config",
]
diff --git a/vendor/zip/Cargo.toml b/vendor/zip/Cargo.toml
index 7480ca9ea..7a1b656b2 100644
--- a/vendor/zip/Cargo.toml
+++ b/vendor/zip/Cargo.toml
@@ -12,7 +12,7 @@
[package]
edition = "2018"
name = "zip"
-version = "0.6.3"
+version = "0.6.4"
authors = [
"Mathijs van de Nes <git@mathijs.vd-nes.nl>",
"Marli Frost <marli@frost.red>",
@@ -21,6 +21,7 @@ authors = [
description = """
Library to support the reading and writing of zip files.
"""
+readme = "README.md"
keywords = [
"zip",
"archive",
@@ -74,14 +75,12 @@ optional = true
[dependencies.time]
version = "0.3.7"
-features = [
- "formatting",
- "macros",
-]
+features = ["std"]
optional = true
+default-features = false
[dependencies.zstd]
-version = "0.11.0"
+version = "0.11.2"
optional = true
[dev-dependencies.bencher]
@@ -90,6 +89,13 @@ version = "0.1.5"
[dev-dependencies.getrandom]
version = "0.2.5"
+[dev-dependencies.time]
+version = "0.3.7"
+features = [
+ "formatting",
+ "macros",
+]
+
[dev-dependencies.walkdir]
version = "2.3.2"
diff --git a/vendor/zip/README.md b/vendor/zip/README.md
index 9b3c0599c..3754a7c0f 100644
--- a/vendor/zip/README.md
+++ b/vendor/zip/README.md
@@ -35,14 +35,14 @@ With all default features:
```toml
[dependencies]
-zip = "0.6.3"
+zip = "0.6.4"
```
Without the default features:
```toml
[dependencies]
-zip = { version = "0.6.3", default-features = false }
+zip = { version = "0.6.4", default-features = false }
```
The features available are:
diff --git a/vendor/zip/benches/read_metadata.rs b/vendor/zip/benches/read_metadata.rs
index 51f1f69e8..95334b1c5 100644
--- a/vendor/zip/benches/read_metadata.rs
+++ b/vendor/zip/benches/read_metadata.rs
@@ -17,10 +17,7 @@ fn generate_random_archive(count_files: usize, file_size: usize) -> Vec<u8> {
let bytes = vec![0u8; file_size];
for i in 0..count_files {
- let name = format!(
- "file_deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef_{}.dat",
- i
- );
+ let name = format!("file_deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef_{i}.dat");
writer.start_file(name, options).unwrap();
writer.write_all(&bytes).unwrap();
}
diff --git a/vendor/zip/examples/extract.rs b/vendor/zip/examples/extract.rs
index 7b8860ca0..308071626 100644
--- a/vendor/zip/examples/extract.rs
+++ b/vendor/zip/examples/extract.rs
@@ -12,7 +12,7 @@ fn real_main() -> i32 {
return 1;
}
let fname = std::path::Path::new(&*args[1]);
- let file = fs::File::open(&fname).unwrap();
+ let file = fs::File::open(fname).unwrap();
let mut archive = zip::ZipArchive::new(file).unwrap();
@@ -26,7 +26,7 @@ fn real_main() -> i32 {
{
let comment = file.comment();
if !comment.is_empty() {
- println!("File {} comment: {}", i, comment);
+ println!("File {i} comment: {comment}");
}
}
@@ -42,7 +42,7 @@ fn real_main() -> i32 {
);
if let Some(p) = outpath.parent() {
if !p.exists() {
- fs::create_dir_all(&p).unwrap();
+ fs::create_dir_all(p).unwrap();
}
}
let mut outfile = fs::File::create(&outpath).unwrap();
diff --git a/vendor/zip/examples/extract_lorem.rs b/vendor/zip/examples/extract_lorem.rs
index a34a04f43..bc50abe16 100644
--- a/vendor/zip/examples/extract_lorem.rs
+++ b/vendor/zip/examples/extract_lorem.rs
@@ -11,7 +11,7 @@ fn real_main() -> i32 {
return 1;
}
let fname = std::path::Path::new(&*args[1]);
- let zipfile = std::fs::File::open(&fname).unwrap();
+ let zipfile = std::fs::File::open(fname).unwrap();
let mut archive = zip::ZipArchive::new(zipfile).unwrap();
@@ -25,7 +25,7 @@ fn real_main() -> i32 {
let mut contents = String::new();
file.read_to_string(&mut contents).unwrap();
- println!("{}", contents);
+ println!("{contents}");
0
}
diff --git a/vendor/zip/examples/file_info.rs b/vendor/zip/examples/file_info.rs
index 64969b66c..6a2adc58e 100644
--- a/vendor/zip/examples/file_info.rs
+++ b/vendor/zip/examples/file_info.rs
@@ -12,7 +12,7 @@ fn real_main() -> i32 {
return 1;
}
let fname = std::path::Path::new(&*args[1]);
- let file = fs::File::open(&fname).unwrap();
+ let file = fs::File::open(fname).unwrap();
let reader = BufReader::new(file);
let mut archive = zip::ZipArchive::new(reader).unwrap();
@@ -30,7 +30,7 @@ fn real_main() -> i32 {
{
let comment = file.comment();
if !comment.is_empty() {
- println!("Entry {} comment: {}", i, comment);
+ println!("Entry {i} comment: {comment}");
}
}
diff --git a/vendor/zip/examples/stdin_info.rs b/vendor/zip/examples/stdin_info.rs
index 10d7aa8b8..a609916a0 100644
--- a/vendor/zip/examples/stdin_info.rs
+++ b/vendor/zip/examples/stdin_info.rs
@@ -20,12 +20,12 @@ fn real_main() -> i32 {
);
match file.read(&mut buf) {
Ok(n) => println!("The first {} bytes are: {:?}", n, &buf[0..n]),
- Err(e) => println!("Could not read the file: {:?}", e),
+ Err(e) => println!("Could not read the file: {e:?}"),
};
}
Ok(None) => break,
Err(e) => {
- println!("Error encountered while reading zip: {:?}", e);
+ println!("Error encountered while reading zip: {e:?}");
return 1;
}
}
diff --git a/vendor/zip/examples/write_dir.rs b/vendor/zip/examples/write_dir.rs
index 8cc561ffb..3b043528f 100644
--- a/vendor/zip/examples/write_dir.rs
+++ b/vendor/zip/examples/write_dir.rs
@@ -54,8 +54,8 @@ fn real_main() -> i32 {
continue;
}
match doit(src_dir, dst_file, method.unwrap()) {
- Ok(_) => println!("done: {} written to {}", src_dir, dst_file),
- Err(e) => println!("Error: {:?}", e),
+ Ok(_) => println!("done: {src_dir} written to {dst_file}"),
+ Err(e) => println!("Error: {e:?}"),
}
}
@@ -84,18 +84,18 @@ where
// Write file or directory explicitly
// Some unzip tools unzip files with directory paths correctly, some do not!
if path.is_file() {
- println!("adding file {:?} as {:?} ...", path, name);
+ println!("adding file {path:?} as {name:?} ...");
#[allow(deprecated)]
zip.start_file_from_path(name, options)?;
let mut f = File::open(path)?;
f.read_to_end(&mut buffer)?;
- zip.write_all(&*buffer)?;
+ zip.write_all(&buffer)?;
buffer.clear();
} else if !name.as_os_str().is_empty() {
// Only if not root! Avoids path spec / warning
// and mapname conversion failed error on unzip
- println!("adding dir {:?} as {:?} ...", path, name);
+ println!("adding dir {path:?} as {name:?} ...");
#[allow(deprecated)]
zip.add_directory_from_path(name, options)?;
}
@@ -114,7 +114,7 @@ fn doit(
}
let path = Path::new(dst_file);
- let file = File::create(&path).unwrap();
+ let file = File::create(path).unwrap();
let walkdir = WalkDir::new(src_dir);
let it = walkdir.into_iter();
diff --git a/vendor/zip/examples/write_sample.rs b/vendor/zip/examples/write_sample.rs
index b5749509e..2e45cb1ea 100644
--- a/vendor/zip/examples/write_sample.rs
+++ b/vendor/zip/examples/write_sample.rs
@@ -14,8 +14,8 @@ fn real_main() -> i32 {
let filename = &*args[1];
match doit(filename) {
- Ok(_) => println!("File written to {}", filename),
- Err(e) => println!("Error: {:?}", e),
+ Ok(_) => println!("File written to {filename}"),
+ Err(e) => println!("Error: {e:?}"),
}
0
@@ -23,7 +23,7 @@ fn real_main() -> i32 {
fn doit(filename: &str) -> zip::result::ZipResult<()> {
let path = std::path::Path::new(filename);
- let file = std::fs::File::create(&path).unwrap();
+ let file = std::fs::File::create(path).unwrap();
let mut zip = zip::ZipWriter::new(file);
diff --git a/vendor/zip/src/compression.rs b/vendor/zip/src/compression.rs
index abd8b5300..baec93994 100644
--- a/vendor/zip/src/compression.rs
+++ b/vendor/zip/src/compression.rs
@@ -141,7 +141,7 @@ impl CompressionMethod {
impl fmt::Display for CompressionMethod {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
// Just duplicate what the Debug format looks like, i.e, the enum key:
- write!(f, "{:?}", self)
+ write!(f, "{self:?}")
}
}
@@ -195,8 +195,8 @@ mod test {
#[test]
fn to_display_fmt() {
fn check_match(method: CompressionMethod) {
- let debug_str = format!("{:?}", method);
- let display_str = format!("{}", method);
+ let debug_str = format!("{method:?}");
+ let display_str = format!("{method}");
assert_eq!(debug_str, display_str);
}
diff --git a/vendor/zip/src/read.rs b/vendor/zip/src/read.rs
index 728ddf579..dad20c260 100644
--- a/vendor/zip/src/read.rs
+++ b/vendor/zip/src/read.rs
@@ -348,7 +348,9 @@ impl<R: Read + io::Seek> ZipArchive<R> {
Some(locator64) => {
// If we got here, this is indeed a ZIP64 file.
- if footer.disk_number as u32 != locator64.disk_with_central_directory {
+ if !footer.record_too_small()
+ && footer.disk_number as u32 != locator64.disk_with_central_directory
+ {
return unsupported_zip_error(
"Support for multi-disk files is not implemented",
);
@@ -401,7 +403,7 @@ impl<R: Read + io::Seek> ZipArchive<R> {
pub fn new(mut reader: R) -> ZipResult<ZipArchive<R>> {
let (footer, cde_start_pos) = spec::CentralDirectoryEnd::find_and_parse(&mut reader)?;
- if footer.disk_number != footer.disk_with_central_directory {
+ if !footer.record_too_small() && footer.disk_number != footer.disk_with_central_directory {
return unsupported_zip_error("Support for multi-disk files is not implemented");
}
@@ -461,7 +463,7 @@ impl<R: Read + io::Seek> ZipArchive<R> {
} else {
if let Some(p) = outpath.parent() {
if !p.exists() {
- fs::create_dir_all(&p)?;
+ fs::create_dir_all(p)?;
}
}
let mut outfile = fs::File::create(&outpath)?;
@@ -681,11 +683,11 @@ pub(crate) fn central_header_to_zip_file<R: Read + io::Seek>(
reader.read_exact(&mut file_comment_raw)?;
let file_name = match is_utf8 {
- true => String::from_utf8_lossy(&*file_name_raw).into_owned(),
+ true => String::from_utf8_lossy(&file_name_raw).into_owned(),
false => file_name_raw.clone().from_cp437(),
};
let file_comment = match is_utf8 {
- true => String::from_utf8_lossy(&*file_comment_raw).into_owned(),
+ true => String::from_utf8_lossy(&file_comment_raw).into_owned(),
false => file_comment_raw.from_cp437(),
};
@@ -920,12 +922,12 @@ impl<'a> ZipFile<'a> {
self.data.compression_method
}
- /// Get the size of the file in the archive
+ /// Get the size of the file, in bytes, in the archive
pub fn compressed_size(&self) -> u64 {
self.data.compressed_size
}
- /// Get the size of the file when uncompressed
+ /// Get the size of the file, in bytes, when uncompressed
pub fn size(&self) -> u64 {
self.data.uncompressed_size
}
@@ -1085,7 +1087,7 @@ pub fn read_zipfile_from_stream<'a, R: io::Read>(
reader.read_exact(&mut extra_field)?;
let file_name = match is_utf8 {
- true => String::from_utf8_lossy(&*file_name_raw).into_owned(),
+ true => String::from_utf8_lossy(&file_name_raw).into_owned(),
false => file_name_raw.clone().from_cp437(),
};
@@ -1129,7 +1131,7 @@ pub fn read_zipfile_from_stream<'a, R: io::Read>(
return unsupported_zip_error("The file length is not available in the local header");
}
- let limit_reader = (reader as &'a mut dyn io::Read).take(result.compressed_size as u64);
+ let limit_reader = (reader as &'a mut dyn io::Read).take(result.compressed_size);
let result_crc32 = result.crc32;
let result_compression_method = result.compression_method;
diff --git a/vendor/zip/src/result.rs b/vendor/zip/src/result.rs
index 72a30e488..00d558cb4 100644
--- a/vendor/zip/src/result.rs
+++ b/vendor/zip/src/result.rs
@@ -44,9 +44,9 @@ impl From<io::Error> for ZipError {
impl fmt::Display for ZipError {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
match self {
- ZipError::Io(err) => write!(fmt, "{}", err),
- ZipError::InvalidArchive(err) => write!(fmt, "invalid Zip archive: {}", err),
- ZipError::UnsupportedArchive(err) => write!(fmt, "unsupported Zip archive: {}", err),
+ ZipError::Io(err) => write!(fmt, "{err}"),
+ ZipError::InvalidArchive(err) => write!(fmt, "invalid Zip archive: {err}"),
+ ZipError::UnsupportedArchive(err) => write!(fmt, "unsupported Zip archive: {err}"),
ZipError::FileNotFound => write!(fmt, "specified file not found in archive"),
}
}
@@ -81,3 +81,18 @@ impl From<ZipError> for io::Error {
io::Error::new(io::ErrorKind::Other, err)
}
}
+
+/// Error type for time parsing
+#[derive(Debug)]
+pub struct DateTimeRangeError;
+
+impl fmt::Display for DateTimeRangeError {
+ fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+ write!(
+ fmt,
+ "a date could not be represented within the bounds the MS-DOS date range (1980-2107)"
+ )
+ }
+}
+
+impl Error for DateTimeRangeError {}
diff --git a/vendor/zip/src/spec.rs b/vendor/zip/src/spec.rs
index 3ffcf7323..1d8cb0a64 100644
--- a/vendor/zip/src/spec.rs
+++ b/vendor/zip/src/spec.rs
@@ -23,6 +23,18 @@ pub struct CentralDirectoryEnd {
}
impl CentralDirectoryEnd {
+ // Per spec 4.4.1.4 - a CentralDirectoryEnd field might be insufficient to hold the
+ // required data. In this case the file SHOULD contain a ZIP64 format record
+ // and the field of this record will be set to -1
+ pub(crate) fn record_too_small(&self) -> bool {
+ self.disk_number == 0xFFFF
+ || self.disk_with_central_directory == 0xFFFF
+ || self.number_of_files_on_this_disk == 0xFFFF
+ || self.number_of_files == 0xFFFF
+ || self.central_directory_size == 0xFFFFFFFF
+ || self.central_directory_offset == 0xFFFFFFFF
+ }
+
pub fn parse<T: Read>(reader: &mut T) -> ZipResult<CentralDirectoryEnd> {
let magic = reader.read_u32::<LittleEndian>()?;
if magic != CENTRAL_DIRECTORY_END_SIGNATURE {
@@ -64,12 +76,12 @@ impl CentralDirectoryEnd {
let mut pos = file_length - HEADER_SIZE;
while pos >= search_upper_bound {
- reader.seek(io::SeekFrom::Start(pos as u64))?;
+ reader.seek(io::SeekFrom::Start(pos))?;
if reader.read_u32::<LittleEndian>()? == CENTRAL_DIRECTORY_END_SIGNATURE {
reader.seek(io::SeekFrom::Current(
BYTES_BETWEEN_MAGIC_AND_COMMENT_SIZE as i64,
))?;
- let cde_start_pos = reader.seek(io::SeekFrom::Start(pos as u64))?;
+ let cde_start_pos = reader.seek(io::SeekFrom::Start(pos))?;
return CentralDirectoryEnd::parse(reader).map(|cde| (cde, cde_start_pos));
}
pos = match pos.checked_sub(1) {
diff --git a/vendor/zip/src/types.rs b/vendor/zip/src/types.rs
index b65fad401..ad3a5700b 100644
--- a/vendor/zip/src/types.rs
+++ b/vendor/zip/src/types.rs
@@ -1,13 +1,16 @@
//! Types that specify what is contained in a ZIP.
-#[cfg(doc)]
-use {crate::read::ZipFile, crate::write::FileOptions};
-
+#[cfg(feature = "time")]
+use std::convert::{TryFrom, TryInto};
#[cfg(not(any(
all(target_arch = "arm", target_pointer_width = "32"),
target_arch = "mips",
target_arch = "powerpc"
)))]
use std::sync::atomic;
+#[cfg(not(feature = "time"))]
+use std::time::SystemTime;
+#[cfg(doc)]
+use {crate::read::ZipFile, crate::write::FileOptions};
#[cfg(any(
all(target_arch = "arm", target_pointer_width = "32"),
@@ -42,9 +45,11 @@ mod atomic {
}
#[cfg(feature = "time")]
+use crate::result::DateTimeRangeError;
+#[cfg(feature = "time")]
use time::{error::ComponentRange, Date, Month, OffsetDateTime, PrimitiveDateTime, Time};
-#[derive(Clone, Copy, Debug, PartialEq)]
+#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum System {
Dos = 0,
Unix = 3,
@@ -115,7 +120,7 @@ impl DateTime {
let years = (datepart & 0b1111111000000000) >> 9;
DateTime {
- year: (years + 1980) as u16,
+ year: years + 1980,
month: months as u8,
day: days as u8,
hour: hours as u8,
@@ -143,10 +148,8 @@ impl DateTime {
second: u8,
) -> Result<DateTime, ()> {
if (1980..=2107).contains(&year)
- && month >= 1
- && month <= 12
- && day >= 1
- && day <= 31
+ && (1..=12).contains(&month)
+ && (1..=31).contains(&day)
&& hour <= 23
&& minute <= 59
&& second <= 60
@@ -169,19 +172,9 @@ impl DateTime {
///
/// Returns `Err` when this object is out of bounds
#[allow(clippy::result_unit_err)]
+ #[deprecated(note = "use `DateTime::try_from()`")]
pub fn from_time(dt: OffsetDateTime) -> Result<DateTime, ()> {
- if dt.year() >= 1980 && dt.year() <= 2107 {
- Ok(DateTime {
- year: (dt.year()) as u16,
- month: (dt.month()) as u8,
- day: dt.day() as u8,
- hour: dt.hour() as u8,
- minute: dt.minute() as u8,
- second: dt.second() as u8,
- })
- } else {
- Err(())
- }
+ dt.try_into().map_err(|_err| ())
}
/// Gets the time portion of this datetime in the msdos representation
@@ -197,8 +190,6 @@ impl DateTime {
#[cfg(feature = "time")]
/// Converts the DateTime to a OffsetDateTime structure
pub fn to_time(&self) -> Result<OffsetDateTime, ComponentRange> {
- use std::convert::TryFrom;
-
let date =
Date::from_calendar_date(self.year as i32, Month::try_from(self.month)?, self.day)?;
let time = Time::from_hms(self.hour, self.minute, self.second)?;
@@ -256,6 +247,26 @@ impl DateTime {
}
}
+#[cfg(feature = "time")]
+impl TryFrom<OffsetDateTime> for DateTime {
+ type Error = DateTimeRangeError;
+
+ fn try_from(dt: OffsetDateTime) -> Result<Self, Self::Error> {
+ if dt.year() >= 1980 && dt.year() <= 2107 {
+ Ok(DateTime {
+ year: (dt.year()) as u16,
+ month: (dt.month()) as u8,
+ day: dt.day(),
+ hour: dt.hour(),
+ minute: dt.minute(),
+ second: dt.second(),
+ })
+ } else {
+ Err(DateTimeRangeError)
+ }
+ }
+}
+
pub const DEFAULT_VERSION: u8 = 46;
/// A type like `AtomicU64` except it implements `Clone` and has predefined
@@ -500,20 +511,43 @@ mod test {
#[cfg(feature = "time")]
#[test]
fn datetime_from_time_bounds() {
+ use std::convert::TryFrom;
+
+ use super::DateTime;
+ use time::macros::datetime;
+
+ // 1979-12-31 23:59:59
+ assert!(DateTime::try_from(datetime!(1979-12-31 23:59:59 UTC)).is_err());
+
+ // 1980-01-01 00:00:00
+ assert!(DateTime::try_from(datetime!(1980-01-01 00:00:00 UTC)).is_ok());
+
+ // 2107-12-31 23:59:59
+ assert!(DateTime::try_from(datetime!(2107-12-31 23:59:59 UTC)).is_ok());
+
+ // 2108-01-01 00:00:00
+ assert!(DateTime::try_from(datetime!(2108-01-01 00:00:00 UTC)).is_err());
+ }
+
+ #[cfg(feature = "time")]
+ #[test]
+ fn datetime_try_from_bounds() {
+ use std::convert::TryFrom;
+
use super::DateTime;
use time::macros::datetime;
// 1979-12-31 23:59:59
- assert!(DateTime::from_time(datetime!(1979-12-31 23:59:59 UTC)).is_err());
+ assert!(DateTime::try_from(datetime!(1979-12-31 23:59:59 UTC)).is_err());
// 1980-01-01 00:00:00
- assert!(DateTime::from_time(datetime!(1980-01-01 00:00:00 UTC)).is_ok());
+ assert!(DateTime::try_from(datetime!(1980-01-01 00:00:00 UTC)).is_ok());
// 2107-12-31 23:59:59
- assert!(DateTime::from_time(datetime!(2107-12-31 23:59:59 UTC)).is_ok());
+ assert!(DateTime::try_from(datetime!(2107-12-31 23:59:59 UTC)).is_ok());
// 2108-01-01 00:00:00
- assert!(DateTime::from_time(datetime!(2108-01-01 00:00:00 UTC)).is_err());
+ assert!(DateTime::try_from(datetime!(2108-01-01 00:00:00 UTC)).is_err());
}
#[test]
@@ -564,10 +598,11 @@ mod test {
#[test]
fn time_at_january() {
use super::DateTime;
+ use std::convert::TryFrom;
// 2020-01-01 00:00:00
let clock = OffsetDateTime::from_unix_timestamp(1_577_836_800).unwrap();
- assert!(DateTime::from_time(clock).is_ok());
+ assert!(DateTime::try_from(clock).is_ok());
}
}
diff --git a/vendor/zip/src/write.rs b/vendor/zip/src/write.rs
index 61ce378c0..14252b4d5 100644
--- a/vendor/zip/src/write.rs
+++ b/vendor/zip/src/write.rs
@@ -7,6 +7,7 @@ use crate::spec;
use crate::types::{AtomicU64, DateTime, System, ZipFileData, DEFAULT_VERSION};
use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
use crc32fast::Hasher;
+use std::convert::TryInto;
use std::default::Default;
use std::io;
use std::io::prelude::*;
@@ -110,31 +111,6 @@ pub struct FileOptions {
}
impl FileOptions {
- /// Construct a new FileOptions object
- pub fn default() -> FileOptions {
- FileOptions {
- #[cfg(any(
- feature = "deflate",
- feature = "deflate-miniz",
- feature = "deflate-zlib"
- ))]
- compression_method: CompressionMethod::Deflated,
- #[cfg(not(any(
- feature = "deflate",
- feature = "deflate-miniz",
- feature = "deflate-zlib"
- )))]
- compression_method: CompressionMethod::Stored,
- compression_level: None,
- #[cfg(feature = "time")]
- last_modified_time: DateTime::from_time(OffsetDateTime::now_utc()).unwrap_or_default(),
- #[cfg(not(feature = "time"))]
- last_modified_time: DateTime::default(),
- permissions: None,
- large_file: false,
- }
- }
-
/// Set the compression method for the new file
///
/// The default is `CompressionMethod::Deflated`. If the deflate compression feature is
@@ -198,8 +174,29 @@ impl FileOptions {
}
impl Default for FileOptions {
+ /// Construct a new FileOptions object
fn default() -> Self {
- Self::default()
+ Self {
+ #[cfg(any(
+ feature = "deflate",
+ feature = "deflate-miniz",
+ feature = "deflate-zlib"
+ ))]
+ compression_method: CompressionMethod::Deflated,
+ #[cfg(not(any(
+ feature = "deflate",
+ feature = "deflate-miniz",
+ feature = "deflate-zlib"
+ )))]
+ compression_method: CompressionMethod::Stored,
+ compression_level: None,
+ #[cfg(feature = "time")]
+ last_modified_time: OffsetDateTime::now_utc().try_into().unwrap_or_default(),
+ #[cfg(not(feature = "time"))]
+ last_modified_time: DateTime::default(),
+ permissions: None,
+ large_file: false,
+ }
}
}
@@ -848,7 +845,7 @@ impl<W: Write + io::Seek> Drop for ZipWriter<W> {
fn drop(&mut self) {
if !self.inner.is_closed() {
if let Err(e) = self.finalize() {
- let _ = write!(io::stderr(), "ZipWriter drop failed: {:?}", e);
+ let _ = write!(io::stderr(), "ZipWriter drop failed: {e:?}");
}
}
}
@@ -1211,8 +1208,7 @@ fn validate_extra_data(file: &ZipFileData) -> ZipResult<()> {
return Err(ZipError::Io(io::Error::new(
io::ErrorKind::Other,
format!(
- "Extra data header ID {:#06} requires crate feature \"unreserved\"",
- kind,
+ "Extra data header ID {kind:#06} requires crate feature \"unreserved\"",
),
)));
}
@@ -1301,7 +1297,7 @@ fn path_to_string(path: &std::path::Path) -> String {
if !path_str.is_empty() {
path_str.push('/');
}
- path_str.push_str(&*os_str.to_string_lossy());
+ path_str.push_str(&os_str.to_string_lossy());
}
}
path_str
diff --git a/vendor/zip/tests/end_to_end.rs b/vendor/zip/tests/end_to_end.rs
index 25d0c54d0..09e7ce47e 100644
--- a/vendor/zip/tests/end_to_end.rs
+++ b/vendor/zip/tests/end_to_end.rs
@@ -13,7 +13,7 @@ fn end_to_end() {
for &method in SUPPORTED_COMPRESSION_METHODS {
let file = &mut Cursor::new(Vec::new());
- println!("Writing file with {} compression", method);
+ println!("Writing file with {method} compression");
write_test_archive(file, method).expect("Couldn't write test zip archive");
println!("Checking file contents");
diff --git a/vendor/zip/tests/zip64_large.rs b/vendor/zip/tests/zip64_large.rs
index 3d10a3181..468ef198f 100644
--- a/vendor/zip/tests/zip64_large.rs
+++ b/vendor/zip/tests/zip64_large.rs
@@ -205,7 +205,7 @@ fn zip64_large() {
match file.read_exact(&mut buf) {
Ok(()) => println!("The first {} bytes are: {:?}", buf.len(), buf),
- Err(e) => println!("Could not read the file: {:?}", e),
+ Err(e) => println!("Could not read the file: {e:?}"),
};
}
}
diff --git a/version b/version
index dd7e70484..1dffe21af 100644
--- a/version
+++ b/version
@@ -1 +1 @@
-1.68.2 (9eb3afe9e 2023-03-27) \ No newline at end of file
+1.69.0 (84c898d65 2023-04-16) \ No newline at end of file
diff --git a/x.py b/x.py
index 6df4033d5..5dee953a3 100755
--- a/x.py
+++ b/x.py
@@ -22,7 +22,8 @@ if sys.version_info.major < 3:
pass
rust_dir = os.path.dirname(os.path.abspath(__file__))
-sys.path.append(os.path.join(rust_dir, "src", "bootstrap"))
+# For the import below, have Python search in src/bootstrap first.
+sys.path.insert(0, os.path.join(rust_dir, "src", "bootstrap"))
import bootstrap
bootstrap.main()